diff --git a/.forgejo/ISSUE_TEMPLATE/bug.yml b/.forgejo/ISSUE_TEMPLATE/bug.yml index 516498132d07..5560b2412d70 100644 --- a/.forgejo/ISSUE_TEMPLATE/bug.yml +++ b/.forgejo/ISSUE_TEMPLATE/bug.yml @@ -1,6 +1,6 @@ name: Bug Report description: File a bug report -labels: ["kind/bug"] +labels: ["bug"] body: - type: markdown attributes: diff --git a/.forgejo/ISSUE_TEMPLATE/config.yml b/.forgejo/ISSUE_TEMPLATE/config.yml index 186e4522a0fb..9b11403037cd 100644 --- a/.forgejo/ISSUE_TEMPLATE/config.yml +++ b/.forgejo/ISSUE_TEMPLATE/config.yml @@ -1,7 +1,7 @@ contact_links: - name: Language Proposal about: "Please do not submit a proposal to change the language" - url: https://ziglang.org/code-of-conduct + url: https://ziglang.org/code-of-conduct/#no-language-proposals - name: Question about: "Please use one of the community spaces instead for questions or general discussions." url: https://ziglang.org/community @@ -10,4 +10,4 @@ contact_links: url: https://codeberg.org/ziglang/translate-c - name: Copilot and Other LLMs about: "Please do not use GitHub Copilot or any other LLM to write an issue." - url: https://ziglang.org/code-of-conduct + url: https://ziglang.org/code-of-conduct/#strict-no-llm-no-ai-policy diff --git a/.forgejo/ISSUE_TEMPLATE/error_message.yml b/.forgejo/ISSUE_TEMPLATE/error_message.yml index 1bbbbb2e0752..3f0f3bc307a7 100644 --- a/.forgejo/ISSUE_TEMPLATE/error_message.yml +++ b/.forgejo/ISSUE_TEMPLATE/error_message.yml @@ -1,6 +1,6 @@ name: Error message improvement description: Compiler produces an unhelpful or misleading error message. -labels: ["kind/error message"] +labels: ["error message"] body: - type: input id: version diff --git a/.forgejo/workflows/ci.yaml b/.forgejo/workflows/ci.yaml index 3f646c48aaba..59893e1e95f0 100644 --- a/.forgejo/workflows/ci.yaml +++ b/.forgejo/workflows/ci.yaml @@ -19,7 +19,7 @@ jobs: runs-on: [self-hosted, aarch64-linux] steps: - name: Checkout - uses: actions/checkout@v4 + uses: https://codeberg.org/ziglang/checkout@19af6bac491e2534a4687a50ee84fa7f13258d28 with: fetch-depth: 0 - name: Build and Test @@ -29,7 +29,7 @@ jobs: runs-on: [self-hosted, aarch64-linux] steps: - name: Checkout - uses: actions/checkout@v4 + uses: https://codeberg.org/ziglang/checkout@19af6bac491e2534a4687a50ee84fa7f13258d28 with: fetch-depth: 0 - name: Build and Test @@ -40,7 +40,7 @@ jobs: runs-on: [self-hosted, aarch64-macos] steps: - name: Checkout - uses: actions/checkout@v4 + uses: https://codeberg.org/ziglang/checkout@19af6bac491e2534a4687a50ee84fa7f13258d28 with: fetch-depth: 0 - name: Build and Test @@ -50,7 +50,7 @@ jobs: runs-on: [self-hosted, aarch64-macos] steps: - name: Checkout - uses: actions/checkout@v4 + uses: https://codeberg.org/ziglang/checkout@19af6bac491e2534a4687a50ee84fa7f13258d28 with: fetch-depth: 0 - name: Build and Test @@ -61,51 +61,72 @@ jobs: runs-on: [self-hosted, loongarch64-linux] steps: - name: Checkout - uses: actions/checkout@v4 + uses: https://codeberg.org/ziglang/checkout@19af6bac491e2534a4687a50ee84fa7f13258d28 with: fetch-depth: 0 - name: Build and Test run: sh ci/loongarch64-linux-debug.sh - timeout-minutes: 240 + timeout-minutes: 300 loongarch64-linux-release: runs-on: [self-hosted, loongarch64-linux] steps: - name: Checkout - uses: actions/checkout@v4 + uses: https://codeberg.org/ziglang/checkout@19af6bac491e2534a4687a50ee84fa7f13258d28 with: fetch-depth: 0 - name: Build and Test run: sh ci/loongarch64-linux-release.sh - timeout-minutes: 180 + timeout-minutes: 240 + + powerpc64le-linux-debug: + runs-on: [self-hosted, powerpc64le-linux] + steps: + - name: Checkout + uses: https://codeberg.org/ziglang/checkout@19af6bac491e2534a4687a50ee84fa7f13258d28 + with: + fetch-depth: 0 + - name: Build and Test + run: sh ci/powerpc64le-linux-debug.sh + timeout-minutes: 360 + powerpc64le-linux-release: + runs-on: [self-hosted, powerpc64le-linux] + steps: + - name: Checkout + uses: https://codeberg.org/ziglang/checkout@19af6bac491e2534a4687a50ee84fa7f13258d28 + with: + fetch-depth: 0 + - name: Build and Test + run: sh ci/powerpc64le-linux-release.sh + timeout-minutes: 240 riscv64-linux-debug: if: github.event_name != 'pull_request' runs-on: [self-hosted, riscv64-linux] steps: - name: Checkout - uses: actions/checkout@v4 + uses: https://codeberg.org/ziglang/checkout@19af6bac491e2534a4687a50ee84fa7f13258d28 with: fetch-depth: 0 - name: Build and Test run: sh ci/riscv64-linux-debug.sh - timeout-minutes: 600 + timeout-minutes: 840 riscv64-linux-release: if: github.event_name != 'pull_request' runs-on: [self-hosted, riscv64-linux] steps: - name: Checkout - uses: actions/checkout@v4 + uses: https://codeberg.org/ziglang/checkout@19af6bac491e2534a4687a50ee84fa7f13258d28 with: fetch-depth: 0 - name: Build and Test run: sh ci/riscv64-linux-release.sh - timeout-minutes: 480 + timeout-minutes: 720 s390x-linux-debug: runs-on: [self-hosted, s390x-linux] steps: - name: Checkout - uses: actions/checkout@v4 + uses: https://codeberg.org/ziglang/checkout@19af6bac491e2534a4687a50ee84fa7f13258d28 with: fetch-depth: 0 - name: Build and Test @@ -115,7 +136,7 @@ jobs: runs-on: [self-hosted, s390x-linux] steps: - name: Checkout - uses: actions/checkout@v4 + uses: https://codeberg.org/ziglang/checkout@19af6bac491e2534a4687a50ee84fa7f13258d28 with: fetch-depth: 0 - name: Build and Test @@ -126,7 +147,7 @@ jobs: runs-on: [self-hosted, x86_64-freebsd] steps: - name: Checkout - uses: actions/checkout@v4 + uses: https://codeberg.org/ziglang/checkout@19af6bac491e2534a4687a50ee84fa7f13258d28 with: fetch-depth: 0 - name: Build and Test @@ -136,7 +157,7 @@ jobs: runs-on: [self-hosted, x86_64-freebsd] steps: - name: Checkout - uses: actions/checkout@v4 + uses: https://codeberg.org/ziglang/checkout@19af6bac491e2534a4687a50ee84fa7f13258d28 with: fetch-depth: 0 - name: Build and Test @@ -147,38 +168,59 @@ jobs: runs-on: [self-hosted, x86_64-linux] steps: - name: Checkout - uses: actions/checkout@v4 + uses: https://codeberg.org/ziglang/checkout@19af6bac491e2534a4687a50ee84fa7f13258d28 with: fetch-depth: 0 - name: Build and Test run: sh ci/x86_64-linux-debug.sh - timeout-minutes: 240 + timeout-minutes: 180 x86_64-linux-debug-llvm: runs-on: [self-hosted, x86_64-linux] steps: - name: Checkout - uses: actions/checkout@v4 + uses: https://codeberg.org/ziglang/checkout@19af6bac491e2534a4687a50ee84fa7f13258d28 with: fetch-depth: 0 - name: Build and Test run: sh ci/x86_64-linux-debug-llvm.sh - timeout-minutes: 480 + timeout-minutes: 360 x86_64-linux-release: runs-on: [self-hosted, x86_64-linux] steps: - name: Checkout - uses: actions/checkout@v4 + uses: https://codeberg.org/ziglang/checkout@19af6bac491e2534a4687a50ee84fa7f13258d28 with: fetch-depth: 0 - name: Build and Test run: sh ci/x86_64-linux-release.sh - timeout-minutes: 480 + timeout-minutes: 360 + + x86_64-openbsd-debug: + runs-on: [self-hosted, x86_64-openbsd] + steps: + - name: Checkout + uses: https://codeberg.org/ziglang/checkout@19af6bac491e2534a4687a50ee84fa7f13258d28 + with: + fetch-depth: 0 + - name: Build and Test + run: sh ci/x86_64-openbsd-debug.sh + timeout-minutes: 120 + x86_64-openbsd-release: + runs-on: [self-hosted, x86_64-openbsd] + steps: + - name: Checkout + uses: https://codeberg.org/ziglang/checkout@19af6bac491e2534a4687a50ee84fa7f13258d28 + with: + fetch-depth: 0 + - name: Build and Test + run: sh ci/x86_64-openbsd-release.sh + timeout-minutes: 120 x86_64-windows-debug: runs-on: [self-hosted, x86_64-windows] steps: - name: Checkout - uses: actions/checkout@v4 + uses: https://codeberg.org/ziglang/checkout@19af6bac491e2534a4687a50ee84fa7f13258d28 with: fetch-depth: 0 - name: Build and Test @@ -188,7 +230,7 @@ jobs: runs-on: [self-hosted, x86_64-windows] steps: - name: Checkout - uses: actions/checkout@v4 + uses: https://codeberg.org/ziglang/checkout@19af6bac491e2534a4687a50ee84fa7f13258d28 with: fetch-depth: 0 - name: Build and Test diff --git a/.mailmap b/.mailmap index 2f2a14bc62ba..3d4281b9ffc1 100644 --- a/.mailmap +++ b/.mailmap @@ -2,6 +2,7 @@ Adam Goertz Ali Chraghi Andrea Orru Andrew Kelley +Andrew Kelley Bogdan Romanyuk <65823030+wrongnull@users.noreply.github.com> Casey Banner Dacheng Gao @@ -22,6 +23,7 @@ Felix "xq" Queißner Felix "xq" Queißner Felix "xq" Queißner Frank Denis <124872+jedisct1@users.noreply.github.com> +Frank Denis <124872+jedisct1@users.noreply.github.com> Garrett Beck <138411610+garrettlennoxbeck@users.noreply.github.com> Gaëtan S GalaxyShard @@ -55,6 +57,7 @@ Marc Tiehuis Mason Remaley Mason Remaley Matthew Lugg +Matthew Lugg Meghan Denny Meghan Denny Michael Bartnett diff --git a/CMakeLists.txt b/CMakeLists.txt index 7090f8852768..fe8660559c39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -221,7 +221,6 @@ set(ZIG_STAGE2_SOURCES lib/compiler_rt/aulldiv.zig lib/compiler_rt/aullrem.zig lib/compiler_rt/bswap.zig - lib/compiler_rt/ceil.zig lib/compiler_rt/clear_cache.zig lib/compiler_rt/cmp.zig lib/compiler_rt/cmpdf2.zig @@ -312,7 +311,7 @@ set(ZIG_STAGE2_SOURCES lib/compiler_rt/floatuntisf.zig lib/compiler_rt/floatuntitf.zig lib/compiler_rt/floatuntixf.zig - lib/compiler_rt/floor.zig + lib/compiler_rt/floor_ceil.zig lib/compiler_rt/fma.zig lib/compiler_rt/fmax.zig lib/compiler_rt/fmin.zig @@ -411,7 +410,6 @@ set(ZIG_STAGE2_SOURCES lib/std/Thread.zig lib/std/Thread/Futex.zig lib/std/Thread/Mutex.zig - lib/std/Thread/Pool.zig lib/std/Thread/WaitGroup.zig lib/std/array_hash_map.zig lib/std/array_list.zig @@ -437,10 +435,6 @@ set(ZIG_STAGE2_SOURCES lib/std/fmt.zig lib/std/fmt/parse_float.zig lib/std/fs.zig - lib/std/fs/AtomicFile.zig - lib/std/fs/Dir.zig - lib/std/fs/File.zig - lib/std/fs/get_app_data_dir.zig lib/std/fs/path.zig lib/std/hash.zig lib/std/hash/auto_hash.zig @@ -518,7 +512,6 @@ set(ZIG_STAGE2_SOURCES src/Builtin.zig src/Compilation.zig src/Compilation/Config.zig - src/DarwinPosixSpawn.zig src/InternPool.zig src/Package.zig src/Package/Fetch.zig @@ -553,6 +546,7 @@ set(ZIG_STAGE2_SOURCES src/libs/freebsd.zig src/libs/glibc.zig src/libs/netbsd.zig + src/libs/openbsd.zig src/introspect.zig src/libs/libcxx.zig src/libs/libtsan.zig @@ -792,6 +786,11 @@ else() set(ZIG_WASM2C_COMPILE_FLAGS "-std=c99 -O2") set(ZIG1_COMPILE_FLAGS "-std=c99 -Os") set(ZIG2_COMPILE_FLAGS "-std=c99 -O0 -fno-sanitize=undefined -fno-stack-protector") + # Must match the condition in build.zig. + if(ZIG_HOST_TARGET_ARCH MATCHES "^powerpc(64)?(le)?$") + set(ZIG1_COMPILE_FLAGS "${ZIG1_COMPILE_FLAGS} -ffunction-sections -fdata-sections") + set(ZIG2_COMPILE_FLAGS "${ZIG2_COMPILE_FLAGS} -ffunction-sections -fdata-sections") + endif() if(APPLE) set(ZIG2_LINK_FLAGS "-Wl,-stack_size,0x10000000") elseif(MINGW) diff --git a/README.md b/README.md index b22475b1be10..b9acf00abd44 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ while your Zig build has the option to be a Debug build. It also works completely independently from MSVC so you don't need it to be installed. Determine the URL by -[looking at the CI script](https://github.com/ziglang/zig/blob/master/ci/x86_64-windows-debug.ps1#L1-L4). +[looking at the CI script](https://codeberg.org/ziglang/zig/src/branch/master/ci/x86_64-windows-debug.ps1#L1-L4). It will look something like this (replace `$VERSION` with the one you see by following the above link): @@ -485,16 +485,14 @@ interpret your words. ### Find a Contributor Friendly Issue The issue label -[Contributor Friendly](https://github.com/ziglang/zig/issues?q=is%3Aissue+is%3Aopen+label%3A%22contributor+friendly%22) +[Contributor Friendly](https://codeberg.org/ziglang/zig/issues?labels=741726&state=open) exists to help you find issues that are **limited in scope and/or knowledge of Zig internals.** Please note that issues labeled -[Proposal](https://github.com/ziglang/zig/issues?q=is%3Aissue+is%3Aopen+label%3Aproposal) -but do not also have the -[Accepted](https://github.com/ziglang/zig/issues?q=is%3Aissue+is%3Aopen+label%3Aaccepted) -label are still under consideration, and efforts to implement such a proposal -have a high risk of being wasted. If you are interested in a proposal which is +[Proposal: Proposed](https://codeberg.org/ziglang/zig/issues?labels=746937&state=open) +are still under consideration, and efforts to implement such a proposal have +a high risk of being wasted. If you are interested in a proposal which is still under consideration, please express your interest in the issue tracker, providing extra insights and considerations that others have not yet expressed. The most highly regarded argument in such a discussion is a real world use case. @@ -665,11 +663,11 @@ based on Clang, but is now based on Aro: Test coverage as well as bug reports have been moved to this repository: -[ziglang/translate-c](https://github.com/ziglang/translate-c/) +[ziglang/translate-c](https://codeberg.org/ziglang/translate-c/) In the future, [@cImport will move to the build system](https://github.com/ziglang/zig/issues/20630), but for now, the translate-c logic is copy-pasted from that project into -[ziglang/zig](https://github.com/ziglang/zig/), powering both `zig translate-c` +[ziglang/zig](https://codeberg.org/ziglang/zig/), powering both `zig translate-c` and `@cImport`. Please see the readme of the translate-c project for how to contribute. Once an @@ -777,7 +775,7 @@ If you will be debugging the Zig compiler itself, or if you will be debugging any project compiled with Zig's LLVM backend (not recommended with the LLDB fork, prefer vanilla LLDB with a version that matches the version of LLVM that Zig is using), you can get a better debugging experience by using -[`lldb_pretty_printers.py`](https://github.com/ziglang/zig/blob/master/tools/lldb_pretty_printers.py). +[`lldb_pretty_printers.py`](https://codeberg.org/ziglang/zig/src/branch/master/tools/lldb_pretty_printers.py). Put this line in `~/.lldbinit`: diff --git a/build.zig b/build.zig index 51c4af91dbe2..aaa67f458d53 100644 --- a/build.zig +++ b/build.zig @@ -1,18 +1,20 @@ const std = @import("std"); const builtin = std.builtin; -const tests = @import("test/tests.zig"); const BufMap = std.BufMap; const mem = std.mem; -const io = std.io; const fs = std.fs; const InstallDirectoryOptions = std.Build.InstallDirectoryOptions; const assert = std.debug.assert; +const Io = std.Io; + +const tests = @import("test/tests.zig"); const DevEnv = @import("src/dev.zig").Env; -const ValueInterpretMode = enum { direct, by_name }; const zig_version: std.SemanticVersion = .{ .major = 0, .minor = 16, .patch = 0 }; const stack_size = 46 * 1024 * 1024; +const ValueInterpretMode = enum { direct, by_name }; + pub fn build(b: *std.Build) !void { const only_c = b.option(bool, "only-c", "Translate the Zig compiler to C code, with only the C backend enabled") orelse false; const target = b.standardTargetOptions(.{ @@ -91,8 +93,11 @@ pub fn build(b: *std.Build) !void { const skip_libc = b.option(bool, "skip-libc", "Main test suite skips tests that link libc") orelse false; const skip_single_threaded = b.option(bool, "skip-single-threaded", "Main test suite skips tests that are single-threaded") orelse false; const skip_compile_errors = b.option(bool, "skip-compile-errors", "Main test suite skips compile error tests") orelse false; + const skip_spirv = b.option(bool, "skip-spirv", "Main test suite skips targets with spirv32/spirv64 architecture") orelse false; + const skip_wasm = b.option(bool, "skip-wasm", "Main test suite skips targets with wasm32/wasm64 architecture") orelse false; const skip_freebsd = b.option(bool, "skip-freebsd", "Main test suite skips targets with freebsd OS") orelse false; const skip_netbsd = b.option(bool, "skip-netbsd", "Main test suite skips targets with netbsd OS") orelse false; + const skip_openbsd = b.option(bool, "skip-openbsd", "Main test suite skips targets with openbsd OS") orelse false; const skip_windows = b.option(bool, "skip-windows", "Main test suite skips targets with windows OS") orelse false; const skip_darwin = b.option(bool, "skip-darwin", "Main test suite skips targets with darwin OSs") orelse false; const skip_linux = b.option(bool, "skip-linux", "Main test suite skips targets with linux OS") orelse false; @@ -257,7 +262,7 @@ pub fn build(b: *std.Build) !void { "--git-dir", ".git", // affected by the -C argument "describe", "--match", "*.*.*", // "--tags", "--abbrev=9", - }, &code, .Ignore) catch { + }, &code, .ignore) catch { break :v version_string; }; const git_describe = mem.trim(u8, git_describe_untrimmed, " \n\r"); @@ -304,8 +309,10 @@ pub fn build(b: *std.Build) !void { if (enable_llvm) { const cmake_cfg = if (static_llvm) null else blk: { + const io = b.graph.io; + const cwd: Io.Dir = .cwd(); if (findConfigH(b, config_h_path_option)) |config_h_path| { - const file_contents = fs.cwd().readFileAlloc(config_h_path, b.allocator, .limited(max_config_h_bytes)) catch unreachable; + const file_contents = cwd.readFileAlloc(io, config_h_path, b.allocator, .limited(max_config_h_bytes)) catch unreachable; break :blk parseConfigH(b, file_contents); } else { std.log.warn("config.h could not be located automatically. Consider providing it explicitly via \"-Dconfig_h\"", .{}); @@ -421,8 +428,11 @@ pub fn build(b: *std.Build) !void { .test_target_filters = test_target_filters, .skip_compile_errors = skip_compile_errors, .skip_non_native = skip_non_native, + .skip_spirv = skip_spirv, + .skip_wasm = skip_wasm, .skip_freebsd = skip_freebsd, .skip_netbsd = skip_netbsd, + .skip_openbsd = skip_openbsd, .skip_windows = skip_windows, .skip_darwin = skip_darwin, .skip_linux = skip_linux, @@ -452,15 +462,37 @@ pub fn build(b: *std.Build) !void { .skip_single_threaded = skip_single_threaded, .skip_non_native = skip_non_native, .test_default_only = no_matrix, + .skip_spirv = skip_spirv, + .skip_wasm = skip_wasm, .skip_freebsd = skip_freebsd, .skip_netbsd = skip_netbsd, + .skip_openbsd = skip_openbsd, .skip_windows = skip_windows, .skip_darwin = skip_darwin, .skip_linux = skip_linux, .skip_llvm = skip_llvm, .skip_libc = skip_libc, - // 3888779264 was observed on an x86_64-linux-gnu host. - .max_rss = 4000000000, + .max_rss = switch (b.graph.host.result.os.tag) { + .freebsd => 2_000_000_000, + .linux => switch (b.graph.host.result.cpu.arch) { + .aarch64 => 659_809_075, + .loongarch64 => 598_902_374, + .powerpc64le => 627_431_833, + .riscv64 => 827_043_430, + .s390x => 580_596_121, + .x86_64 => 3_290_894_745, + else => 3_300_000_000, + }, + .macos => switch (b.graph.host.result.cpu.arch) { + .aarch64 => 767_736_217, + else => 800_000_000, + }, + .windows => switch (b.graph.host.result.cpu.arch) { + .x86_64 => 603_070_054, + else => 700_000_000, + }, + else => 3_300_000_000, + }, })); test_modules_step.dependOn(tests.addModuleTests(b, .{ @@ -475,14 +507,37 @@ pub fn build(b: *std.Build) !void { .skip_single_threaded = true, .skip_non_native = skip_non_native, .test_default_only = no_matrix, + .skip_spirv = skip_spirv, + .skip_wasm = skip_wasm, .skip_freebsd = skip_freebsd, .skip_netbsd = skip_netbsd, + .skip_openbsd = skip_openbsd, .skip_windows = skip_windows, .skip_darwin = skip_darwin, .skip_linux = skip_linux, .skip_llvm = skip_llvm, .skip_libc = true, .no_builtin = true, + .max_rss = switch (b.graph.host.result.os.tag) { + .freebsd => switch (b.graph.host.result.cpu.arch) { + .x86_64 => 743_802_470, + else => 800_000_000, + }, + .linux => switch (b.graph.host.result.cpu.arch) { + .aarch64 => 639_565_414, + .loongarch64 => 598_884_352, + .powerpc64le => 597_897_625, + .riscv64 => 636_429_516, + .s390x => 574_166_630, + .x86_64 => 978_463_129, + else => 900_000_000, + }, + .macos => switch (b.graph.host.result.cpu.arch) { + .aarch64 => 701_413_785, + else => 800_000_000, + }, + else => 900_000_000, + }, })); test_modules_step.dependOn(tests.addModuleTests(b, .{ @@ -497,14 +552,18 @@ pub fn build(b: *std.Build) !void { .skip_single_threaded = true, .skip_non_native = skip_non_native, .test_default_only = no_matrix, + .skip_spirv = skip_spirv, + .skip_wasm = skip_wasm, .skip_freebsd = skip_freebsd, .skip_netbsd = skip_netbsd, + .skip_openbsd = skip_openbsd, .skip_windows = skip_windows, .skip_darwin = skip_darwin, .skip_linux = skip_linux, .skip_llvm = skip_llvm, .skip_libc = true, .no_builtin = true, + .max_rss = 900_000_000, })); test_modules_step.dependOn(tests.addModuleTests(b, .{ @@ -519,15 +578,32 @@ pub fn build(b: *std.Build) !void { .skip_single_threaded = skip_single_threaded, .skip_non_native = skip_non_native, .test_default_only = no_matrix, + .skip_spirv = skip_spirv, + .skip_wasm = skip_wasm, .skip_freebsd = skip_freebsd, .skip_netbsd = skip_netbsd, + .skip_openbsd = skip_openbsd, .skip_windows = skip_windows, .skip_darwin = skip_darwin, .skip_linux = skip_linux, .skip_llvm = skip_llvm, .skip_libc = skip_libc, - // I observed a value of 5605064704 on the M2 CI. - .max_rss = 6165571174, + .max_rss = switch (b.graph.host.result.os.tag) { + .freebsd => switch (b.graph.host.result.cpu.arch) { + .x86_64 => 3_756_422_348, + else => 3_800_000_000, + }, + .linux => 6_800_000_000, + .macos => switch (b.graph.host.result.cpu.arch) { + .aarch64 => 8_273_795_481, + else => 8_300_000_000, + }, + .windows => switch (b.graph.host.result.cpu.arch) { + .x86_64 => 3_750_236_160, + else => 3_800_000_000, + }, + else => 8_300_000_000, + }, })); const unit_tests_step = b.step("test-unit", "Run the compiler source unit tests"); @@ -543,6 +619,7 @@ pub fn build(b: *std.Build) !void { .use_llvm = use_llvm, .use_lld = use_llvm, .zig_lib_dir = b.path("lib"), + .max_rss = 2_500_000_000, }); if (link_libc) { unit_tests.root_module.link_libc = true; @@ -560,13 +637,39 @@ pub fn build(b: *std.Build) !void { test_step.dependOn(tests.addCAbiTests(b, .{ .test_target_filters = test_target_filters, .skip_non_native = skip_non_native, + .skip_wasm = skip_wasm, .skip_freebsd = skip_freebsd, .skip_netbsd = skip_netbsd, + .skip_openbsd = skip_openbsd, .skip_windows = skip_windows, .skip_darwin = skip_darwin, .skip_linux = skip_linux, .skip_llvm = skip_llvm, .skip_release = skip_release, + .max_rss = switch (b.graph.host.result.os.tag) { + .freebsd => switch (b.graph.host.result.cpu.arch) { + .x86_64 => 727_221_862, + else => 800_000_000, + }, + .linux => switch (b.graph.host.result.cpu.arch) { + .aarch64 => 1_318_185_369, + .loongarch64 => 1_422_904_524, + .powerpc64le => 560_870_604, + .riscv64 => 449_924_710, + .s390x => 1_946_743_603, + .x86_64 => 2_389_779_251, + else => 2_200_000_000, + }, + .macos => switch (b.graph.host.result.cpu.arch) { + .aarch64 => 1_813_612_134, + else => 1_900_000_000, + }, + .windows => switch (b.graph.host.result.cpu.arch) { + .x86_64 => 386_287_616, + else => 400_000_000, + }, + else => 2_200_000_000, + }, })); test_step.dependOn(tests.addLinkTests(b, enable_macos_sdk, enable_ios_sdk, enable_symlinks_windows)); test_step.dependOn(tests.addStackTraceTests(b, test_filters, skip_non_native)); @@ -609,13 +712,14 @@ pub fn build(b: *std.Build) !void { } const test_incremental_step = b.step("test-incremental", "Run the incremental compilation test cases"); - try tests.addIncrementalTests(b, test_incremental_step); + try tests.addIncrementalTests(b, test_incremental_step, test_filters); if (!skip_test_incremental) test_step.dependOn(test_incremental_step); if (tests.addLibcTests(b, .{ .optimize_modes = optimization_modes, .test_filters = test_filters, .test_target_filters = test_target_filters, + .skip_wasm = skip_wasm, // Highest RSS observed in any test case was exactly 1802878976 on x86_64-linux. .max_rss = 2253598720, })) |test_libc_step| test_step.dependOn(test_libc_step); @@ -721,11 +825,17 @@ fn addCompilerMod(b: *std.Build, options: AddCompilerModOptions) *std.Build.Modu fn addCompilerStep(b: *std.Build, options: AddCompilerModOptions) *std.Build.Step.Compile { const exe = b.addExecutable(.{ .name = "zig", - .max_rss = 7_800_000_000, + .max_rss = 7_900_000_000, .root_module = addCompilerMod(b, options), }); exe.stack_size = stack_size; + // Must match the condition in CMakeLists.txt. + const function_data_sections = options.target.result.cpu.arch.isPowerPC(); + + exe.link_function_sections = function_data_sections; + exe.link_data_sections = function_data_sections; + return exe; } @@ -798,7 +908,7 @@ fn addCmakeCfgOptionsToExe( }; mod.linkSystemLibrary("unwind", .{}); }, - .ios, .macos, .watchos, .tvos, .visionos => { + .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => { mod.link_libcpp = true; }, .windows => { @@ -976,10 +1086,13 @@ const CMakeConfig = struct { const max_config_h_bytes = 1 * 1024 * 1024; fn findConfigH(b: *std.Build, config_h_path_option: ?[]const u8) ?[]const u8 { + const io = b.graph.io; + const cwd: Io.Dir = .cwd(); + if (config_h_path_option) |path| { - var config_h_or_err = fs.cwd().openFile(path, .{}); + var config_h_or_err = cwd.openFile(io, path, .{}); if (config_h_or_err) |*file| { - file.close(); + file.close(io); return path; } else |_| { std.log.err("Could not open provided config.h: \"{s}\"", .{path}); @@ -989,13 +1102,13 @@ fn findConfigH(b: *std.Build, config_h_path_option: ?[]const u8) ?[]const u8 { var check_dir = fs.path.dirname(b.graph.zig_exe).?; while (true) { - var dir = fs.cwd().openDir(check_dir, .{}) catch unreachable; - defer dir.close(); + var dir = cwd.openDir(io, check_dir, .{}) catch unreachable; + defer dir.close(io); // Check if config.h is present in dir - var config_h_or_err = dir.openFile("config.h", .{}); + var config_h_or_err = dir.openFile(io, "config.h", .{}); if (config_h_or_err) |*file| { - file.close(); + file.close(io); return fs.path.join( b.allocator, &[_][]const u8{ check_dir, "config.h" }, @@ -1006,9 +1119,9 @@ fn findConfigH(b: *std.Build, config_h_path_option: ?[]const u8) ?[]const u8 { } // Check if we reached the source root by looking for .git, and bail if so - var git_dir_or_err = dir.openDir(".git", .{}); + var git_dir_or_err = dir.openDir(io, ".git", .{}); if (git_dir_or_err) |*git_dir| { - git_dir.close(); + git_dir.close(io); return null; } else |_| {} @@ -1404,6 +1517,8 @@ const llvm_libs_xtensa = [_][]const u8{ }; fn generateLangRef(b: *std.Build) std.Build.LazyPath { + const io = b.graph.io; + const doctest_exe = b.addExecutable(.{ .name = "doctest", .root_module = b.createModule(.{ @@ -1413,17 +1528,17 @@ fn generateLangRef(b: *std.Build) std.Build.LazyPath { }), }); - var dir = b.build_root.handle.openDir("doc/langref", .{ .iterate = true }) catch |err| { + var dir = b.build_root.handle.openDir(io, "doc/langref", .{ .iterate = true }) catch |err| { std.debug.panic("unable to open '{f}doc/langref' directory: {s}", .{ b.build_root, @errorName(err), }); }; - defer dir.close(); + defer dir.close(io); var wf = b.addWriteFiles(); var it = dir.iterateAssumeFirstIteration(); - while (it.next() catch @panic("failed to read dir")) |entry| { + while (it.next(io) catch @panic("failed to read dir")) |entry| { if (std.mem.startsWith(u8, entry.name, ".") or entry.kind != .file) continue; diff --git a/ci/aarch64-linux-debug.sh b/ci/aarch64-linux-debug.sh index 0892840f942e..7a4a6daa2aef 100755 --- a/ci/aarch64-linux-debug.sh +++ b/ci/aarch64-linux-debug.sh @@ -44,7 +44,7 @@ ninja install # No -fqemu and -fwasmtime here as they're covered by the x86_64-linux scripts. stage3-debug/bin/zig build test docs \ - --maxrss 44918199637 \ + --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ -Dskip-non-native \ -Dtarget=native-native-musl \ diff --git a/ci/aarch64-linux-release.sh b/ci/aarch64-linux-release.sh index 7b0947d385ca..39ad9767ab62 100755 --- a/ci/aarch64-linux-release.sh +++ b/ci/aarch64-linux-release.sh @@ -44,7 +44,7 @@ ninja install # No -fqemu and -fwasmtime here as they're covered by the x86_64-linux scripts. stage3-release/bin/zig build test docs \ - --maxrss 44918199637 \ + --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ -Dskip-non-native \ -Dtarget=native-native-musl \ diff --git a/ci/aarch64-macos-debug.sh b/ci/aarch64-macos-debug.sh index 2ae63e755593..7dc60c1f4ed1 100755 --- a/ci/aarch64-macos-debug.sh +++ b/ci/aarch64-macos-debug.sh @@ -42,9 +42,20 @@ cmake .. \ ninja install stage3-debug/bin/zig build test docs \ + --maxrss ${ZSF_MAX_RSS:-0} \ --zig-lib-dir "$PWD/../lib" \ -Denable-macos-sdk \ -Dstatic-llvm \ -Dskip-non-native \ --search-prefix "$PREFIX" \ --test-timeout 2m + +stage3-debug/bin/zig build \ + --prefix stage4-debug \ + -Denable-llvm \ + -Dno-lib \ + -Dtarget=$TARGET \ + -Duse-zig-libcxx \ + -Dversion-string="$(stage3-debug/bin/zig version)" + +stage4-debug/bin/zig test ../test/behavior.zig diff --git a/ci/aarch64-macos-release.sh b/ci/aarch64-macos-release.sh index 2e3a06a53bfa..00b6571f170a 100755 --- a/ci/aarch64-macos-release.sh +++ b/ci/aarch64-macos-release.sh @@ -51,6 +51,7 @@ stage3-release/bin/zig build test docs \ # Ensure that stage3 and stage4 are byte-for-byte identical. stage3-release/bin/zig build \ + --maxrss ${ZSF_MAX_RSS:-0} \ --prefix stage4-release \ -Denable-llvm \ -Dno-lib \ @@ -61,6 +62,7 @@ stage3-release/bin/zig build \ -Dversion-string="$(stage3-release/bin/zig version)" # diff returns an error code if the files differ. -echo "If the following command fails, it means nondeterminism has been" -echo "introduced, making stage3 and stage4 no longer byte-for-byte identical." -diff stage3-release/bin/zig stage4-release/bin/zig +# https://codeberg.org/ziglang/zig/issues/30687 +#echo "If the following command fails, it means nondeterminism has been" +#echo "introduced, making stage3 and stage4 no longer byte-for-byte identical." +#diff stage3-release/bin/zig stage4-release/bin/zig diff --git a/ci/aarch64-windows.ps1 b/ci/aarch64-windows.ps1 index 610f94a64f8a..96e076425650 100644 --- a/ci/aarch64-windows.ps1 +++ b/ci/aarch64-windows.ps1 @@ -5,6 +5,7 @@ $ZIG_LLVM_CLANG_LLD_URL = "https://ziglang.org/deps/$ZIG_LLVM_CLANG_LLD_NAME.zip $PREFIX_PATH = "$(Get-Location)\..\$ZIG_LLVM_CLANG_LLD_NAME" $ZIG = "$PREFIX_PATH\bin\zig.exe" $ZIG_LIB_DIR = "$(Get-Location)\lib" +$ZSF_MAX_RSS = if ($Env:ZSF_MAX_RSS) { $Env:ZSF_MAX_RSS } else { 0 } if (!(Test-Path "..\$ZIG_LLVM_CLANG_LLD_NAME.zip")) { Write-Output "Downloading $ZIG_LLVM_CLANG_LLD_URL" @@ -54,6 +55,7 @@ CheckLastExitCode Write-Output "Main test suite..." & "stage3-release\bin\zig.exe" build test docs ` + --maxrss $ZSF_MAX_RSS ` --zig-lib-dir "$ZIG_LIB_DIR" ` --search-prefix "$PREFIX_PATH" ` -Dstatic-llvm ` diff --git a/ci/loongarch64-linux-debug.sh b/ci/loongarch64-linux-debug.sh index 9757542cbb4b..4cba17b03190 100755 --- a/ci/loongarch64-linux-debug.sh +++ b/ci/loongarch64-linux-debug.sh @@ -45,7 +45,7 @@ ninja install # No -fqemu and -fwasmtime here as they're covered by the x86_64-linux scripts. stage3-debug/bin/zig build test docs \ - --maxrss 60129542144 \ + --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ -Dskip-non-native \ -Dtarget=native-native-musl \ diff --git a/ci/loongarch64-linux-release.sh b/ci/loongarch64-linux-release.sh index edb46d8565be..5b05284d2666 100755 --- a/ci/loongarch64-linux-release.sh +++ b/ci/loongarch64-linux-release.sh @@ -45,7 +45,7 @@ ninja install # No -fqemu and -fwasmtime here as they're covered by the x86_64-linux scripts. stage3-release/bin/zig build test docs \ - --maxrss 60129542144 \ + --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ -Dskip-non-native \ -Dtarget=native-native-musl \ diff --git a/ci/powerpc64le-linux-debug.sh b/ci/powerpc64le-linux-debug.sh new file mode 100755 index 000000000000..1b9a51e44deb --- /dev/null +++ b/ci/powerpc64le-linux-debug.sh @@ -0,0 +1,66 @@ +#!/bin/sh + +# Requires cmake ninja-build + +set -x +set -e + +TARGET="powerpc64le-linux-musl" +MCPU="baseline" +CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.16.0-dev.1594+9fa433d71" +PREFIX="$HOME/deps/$CACHE_BASENAME" +ZIG="$PREFIX/bin/zig" + +# Override the cache directories because they won't actually help other CI runs +# which will be testing alternate versions of zig, and ultimately would just +# fill up space on the hard drive for no reason. +export ZIG_GLOBAL_CACHE_DIR="$PWD/zig-global-cache" +export ZIG_LOCAL_CACHE_DIR="$PWD/zig-local-cache" + +mkdir build-debug +cd build-debug + +export CC="$ZIG cc -target $TARGET -mcpu=$MCPU" +export CXX="$ZIG c++ -target $TARGET -mcpu=$MCPU" + +cmake .. \ + -DCMAKE_INSTALL_PREFIX="stage3-debug" \ + -DCMAKE_PREFIX_PATH="$PREFIX" \ + -DCMAKE_BUILD_TYPE=Debug \ + -DZIG_TARGET_TRIPLE="$TARGET" \ + -DZIG_TARGET_MCPU="$MCPU" \ + -DZIG_STATIC=ON \ + -DZIG_NO_LIB=ON \ + -GNinja \ + -DCMAKE_C_LINKER_DEPFILE_SUPPORTED=FALSE \ + -DCMAKE_CXX_LINKER_DEPFILE_SUPPORTED=FALSE +# https://github.com/ziglang/zig/issues/22213 + +# Now cmake will use zig as the C/C++ compiler. We reset the environment variables +# so that installation and testing do not get affected by them. +unset CC +unset CXX + +ninja install + +# No -fqemu and -fwasmtime here as they're covered by the x86_64-linux scripts. +stage3-debug/bin/zig build test docs \ + --maxrss ${ZSF_MAX_RSS:-0} \ + -Dstatic-llvm \ + -Dskip-non-native \ + -Dtarget=native-native-musl \ + -Dcpu=native+longcall \ + --search-prefix "$PREFIX" \ + --zig-lib-dir "$PWD/../lib" \ + --test-timeout 4m + +stage3-debug/bin/zig build \ + --prefix stage4-debug \ + -Denable-llvm \ + -Dno-lib \ + -Dtarget=$TARGET \ + -Dcpu=$MCPU \ + -Duse-zig-libcxx \ + -Dversion-string="$(stage3-debug/bin/zig version)" + +stage4-debug/bin/zig test ../test/behavior.zig diff --git a/ci/powerpc64le-linux-release.sh b/ci/powerpc64le-linux-release.sh new file mode 100755 index 000000000000..77e1ca803ae2 --- /dev/null +++ b/ci/powerpc64le-linux-release.sh @@ -0,0 +1,72 @@ +#!/bin/sh + +# Requires cmake ninja-build + +set -x +set -e + +TARGET="powerpc64le-linux-musl" +MCPU="baseline" +CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.16.0-dev.1594+9fa433d71" +PREFIX="$HOME/deps/$CACHE_BASENAME" +ZIG="$PREFIX/bin/zig" + +# Override the cache directories because they won't actually help other CI runs +# which will be testing alternate versions of zig, and ultimately would just +# fill up space on the hard drive for no reason. +export ZIG_GLOBAL_CACHE_DIR="$PWD/zig-global-cache" +export ZIG_LOCAL_CACHE_DIR="$PWD/zig-local-cache" + +mkdir build-release +cd build-release + +export CC="$ZIG cc -target $TARGET -mcpu=$MCPU" +export CXX="$ZIG c++ -target $TARGET -mcpu=$MCPU" + +cmake .. \ + -DCMAKE_INSTALL_PREFIX="stage3-release" \ + -DCMAKE_PREFIX_PATH="$PREFIX" \ + -DCMAKE_BUILD_TYPE=Release \ + -DZIG_TARGET_TRIPLE="$TARGET" \ + -DZIG_TARGET_MCPU="$MCPU" \ + -DZIG_STATIC=ON \ + -DZIG_NO_LIB=ON \ + -GNinja \ + -DCMAKE_C_LINKER_DEPFILE_SUPPORTED=FALSE \ + -DCMAKE_CXX_LINKER_DEPFILE_SUPPORTED=FALSE +# https://github.com/ziglang/zig/issues/22213 + +# Now cmake will use zig as the C/C++ compiler. We reset the environment variables +# so that installation and testing do not get affected by them. +unset CC +unset CXX + +ninja install + +# No -fqemu and -fwasmtime here as they're covered by the x86_64-linux scripts. +stage3-release/bin/zig build test docs \ + --maxrss ${ZSF_MAX_RSS:-0} \ + -Dstatic-llvm \ + -Dskip-non-native \ + -Dtarget=native-native-musl \ + -Dcpu=native+longcall \ + --search-prefix "$PREFIX" \ + --zig-lib-dir "$PWD/../lib" \ + --test-timeout 4m + +# Ensure that stage3 and stage4 are byte-for-byte identical. +stage3-release/bin/zig build \ + --prefix stage4-release \ + -Denable-llvm \ + -Dno-lib \ + -Doptimize=ReleaseFast \ + -Dstrip \ + -Dtarget=$TARGET \ + -Dcpu=$MCPU \ + -Duse-zig-libcxx \ + -Dversion-string="$(stage3-release/bin/zig version)" + +# diff returns an error code if the files differ. +echo "If the following command fails, it means nondeterminism has been" +echo "introduced, making stage3 and stage4 no longer byte-for-byte identical." +diff stage3-release/bin/zig stage4-release/bin/zig diff --git a/ci/riscv64-linux-debug.sh b/ci/riscv64-linux-debug.sh index 51e038b369d3..5e7ae7785bb5 100755 --- a/ci/riscv64-linux-debug.sh +++ b/ci/riscv64-linux-debug.sh @@ -44,7 +44,7 @@ ninja install # No -fqemu and -fwasmtime here as they're covered by the x86_64-linux scripts. stage3-debug/bin/zig build test-cases test-modules test-unit test-c-abi test-stack-traces test-error-traces test-llvm-ir \ - --maxrss 68719476736 \ + --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ -Dskip-non-native \ -Dskip-single-threaded \ diff --git a/ci/riscv64-linux-release.sh b/ci/riscv64-linux-release.sh index 1de0335f42ec..92b3d43465d8 100755 --- a/ci/riscv64-linux-release.sh +++ b/ci/riscv64-linux-release.sh @@ -44,7 +44,7 @@ ninja install # No -fqemu and -fwasmtime here as they're covered by the x86_64-linux scripts. stage3-release/bin/zig build test-cases test-modules test-unit test-c-abi test-stack-traces test-error-traces test-llvm-ir \ - --maxrss 68719476736 \ + --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ -Dskip-non-native \ -Dskip-single-threaded \ diff --git a/ci/s390x-linux-debug.sh b/ci/s390x-linux-debug.sh index ce5057634f6b..ffe4d0f02b3c 100755 --- a/ci/s390x-linux-debug.sh +++ b/ci/s390x-linux-debug.sh @@ -45,7 +45,7 @@ ninja install # No -fqemu and -fwasmtime here as they're covered by the x86_64-linux scripts. stage3-debug/bin/zig build test docs \ - --maxrss 30064771072 \ + --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ -Dskip-non-native \ -Dtarget=native-native-musl \ diff --git a/ci/s390x-linux-release.sh b/ci/s390x-linux-release.sh index e474b89ffe12..7fb6cd3641fa 100755 --- a/ci/s390x-linux-release.sh +++ b/ci/s390x-linux-release.sh @@ -45,7 +45,7 @@ ninja install # No -fqemu and -fwasmtime here as they're covered by the x86_64-linux scripts. stage3-release/bin/zig build test docs \ - --maxrss 30064771072 \ + --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ -Dskip-non-native \ -Dtarget=native-native-musl \ diff --git a/ci/x86_64-freebsd-debug.sh b/ci/x86_64-freebsd-debug.sh index ae2fdbce61d6..a4d7034325b3 100755 --- a/ci/x86_64-freebsd-debug.sh +++ b/ci/x86_64-freebsd-debug.sh @@ -44,10 +44,13 @@ unset CXX ninja install stage3-debug/bin/zig build test docs \ - --maxrss 42949672960 \ + --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ + -Dskip-spirv \ + -Dskip-wasm \ -Dskip-linux \ -Dskip-netbsd \ + -Dskip-openbsd \ -Dskip-windows \ -Dskip-darwin \ --search-prefix "$PREFIX" \ diff --git a/ci/x86_64-freebsd-release.sh b/ci/x86_64-freebsd-release.sh index 39d653cc97b4..0ce708c63d77 100755 --- a/ci/x86_64-freebsd-release.sh +++ b/ci/x86_64-freebsd-release.sh @@ -44,10 +44,13 @@ unset CXX ninja install stage3-release/bin/zig build test docs \ - --maxrss 42949672960 \ + --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ + -Dskip-spirv \ + -Dskip-wasm \ -Dskip-linux \ -Dskip-netbsd \ + -Dskip-openbsd \ -Dskip-windows \ -Dskip-darwin \ --search-prefix "$PREFIX" \ diff --git a/ci/x86_64-linux-debug-llvm.sh b/ci/x86_64-linux-debug-llvm.sh index 3c11820352b5..2696ac60e79f 100755 --- a/ci/x86_64-linux-debug-llvm.sh +++ b/ci/x86_64-linux-debug-llvm.sh @@ -11,7 +11,7 @@ CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.16.0-dev.104+689461e31" PREFIX="$HOME/deps/$CACHE_BASENAME" ZIG="$PREFIX/bin/zig" -export PATH="$HOME/deps/wasmtime-v38.0.3-x86_64-linux:$HOME/deps/qemu-linux-x86_64-10.1.1.1/bin:$HOME/local/bin:$PATH" +export PATH="$HOME/deps/wasmtime-v38.0.3-x86_64-linux:$HOME/deps/qemu-linux-x86_64-10.2.0/bin:$HOME/local/bin:$PATH" # Override the cache directories because they won't actually help other CI runs # which will be testing alternate versions of zig, and ultimately would just @@ -34,7 +34,10 @@ cmake .. \ -DZIG_STATIC=ON \ -DZIG_NO_LIB=ON \ -DZIG_EXTRA_BUILD_ARGS="-Duse-llvm=true" \ - -GNinja + -GNinja \ + -DCMAKE_C_LINKER_DEPFILE_SUPPORTED=FALSE \ + -DCMAKE_CXX_LINKER_DEPFILE_SUPPORTED=FALSE +# https://github.com/ziglang/zig/issues/22213 # Now cmake will use zig as the C/C++ compiler. We reset the environment variables # so that installation and testing do not get affected by them. @@ -49,13 +52,14 @@ stage3-debug/bin/zig build \ -Dno-lib stage3-debug/bin/zig build test docs \ - --maxrss 21000000000 \ + --maxrss ${ZSF_MAX_RSS:-0} \ -Dlldb=$HOME/deps/lldb-zig/Debug-e0a42bb34/bin/lldb \ -fqemu \ -fwasmtime \ -Dstatic-llvm \ -Dskip-freebsd \ -Dskip-netbsd \ + -Dskip-openbsd \ -Dskip-windows \ -Dskip-darwin \ -Dtarget=native-native-musl \ @@ -63,3 +67,14 @@ stage3-debug/bin/zig build test docs \ --zig-lib-dir "$PWD/../lib" \ -Denable-superhtml \ --test-timeout 12m + +stage3-debug/bin/zig build \ + --prefix stage4-debug \ + -Duse-llvm \ + -Denable-llvm \ + -Dno-lib \ + -Dtarget=$TARGET \ + -Duse-zig-libcxx \ + -Dversion-string="$(stage3-debug/bin/zig version)" + +stage4-debug/bin/zig test ../test/behavior.zig diff --git a/ci/x86_64-linux-debug.sh b/ci/x86_64-linux-debug.sh index fb2804487776..baba34033340 100755 --- a/ci/x86_64-linux-debug.sh +++ b/ci/x86_64-linux-debug.sh @@ -11,7 +11,7 @@ CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.16.0-dev.104+689461e31" PREFIX="$HOME/deps/$CACHE_BASENAME" ZIG="$PREFIX/bin/zig" -export PATH="$HOME/deps/wasmtime-v38.0.3-x86_64-linux:$HOME/deps/qemu-linux-x86_64-10.1.1.1/bin:$HOME/local/bin:$PATH" +export PATH="$HOME/deps/wasmtime-v38.0.3-x86_64-linux:$HOME/deps/qemu-linux-x86_64-10.2.0/bin:$HOME/local/bin:$PATH" # Override the cache directories because they won't actually help other CI runs # which will be testing alternate versions of zig, and ultimately would just @@ -33,7 +33,10 @@ cmake .. \ -DZIG_TARGET_MCPU="$MCPU" \ -DZIG_STATIC=ON \ -DZIG_NO_LIB=ON \ - -GNinja + -GNinja \ + -DCMAKE_C_LINKER_DEPFILE_SUPPORTED=FALSE \ + -DCMAKE_CXX_LINKER_DEPFILE_SUPPORTED=FALSE +# https://github.com/ziglang/zig/issues/22213 # Now cmake will use zig as the C/C++ compiler. We reset the environment variables # so that installation and testing do not get affected by them. @@ -48,13 +51,14 @@ stage3-debug/bin/zig build \ -Dno-lib stage3-debug/bin/zig build test docs \ - --maxrss 21000000000 \ + --maxrss ${ZSF_MAX_RSS:-0} \ -Dlldb=$HOME/deps/lldb-zig/Debug-e0a42bb34/bin/lldb \ -fqemu \ -fwasmtime \ -Dstatic-llvm \ -Dskip-freebsd \ -Dskip-netbsd \ + -Dskip-openbsd \ -Dskip-windows \ -Dskip-darwin \ -Dskip-llvm \ @@ -63,3 +67,13 @@ stage3-debug/bin/zig build test docs \ --zig-lib-dir "$PWD/../lib" \ -Denable-superhtml \ --test-timeout 10m + +stage3-debug/bin/zig build \ + --prefix stage4-debug \ + -Denable-llvm \ + -Dno-lib \ + -Dtarget=$TARGET \ + -Duse-zig-libcxx \ + -Dversion-string="$(stage3-debug/bin/zig version)" + +stage4-debug/bin/zig test ../test/behavior.zig diff --git a/ci/x86_64-linux-release.sh b/ci/x86_64-linux-release.sh index c7b3dc7e364c..56ce115e80b1 100755 --- a/ci/x86_64-linux-release.sh +++ b/ci/x86_64-linux-release.sh @@ -11,7 +11,7 @@ CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.16.0-dev.104+689461e31" PREFIX="$HOME/deps/$CACHE_BASENAME" ZIG="$PREFIX/bin/zig" -export PATH="$HOME/deps/wasmtime-v38.0.3-x86_64-linux:$HOME/deps/qemu-linux-x86_64-10.1.1.1/bin:$HOME/local/bin:$PATH" +export PATH="$HOME/deps/wasmtime-v38.0.3-x86_64-linux:$HOME/deps/qemu-linux-x86_64-10.2.0/bin:$HOME/local/bin:$PATH" # Override the cache directories because they won't actually help other CI runs # which will be testing alternate versions of zig, and ultimately would just @@ -39,7 +39,10 @@ cmake .. \ -DZIG_TARGET_MCPU="$MCPU" \ -DZIG_STATIC=ON \ -DZIG_NO_LIB=ON \ - -GNinja + -GNinja \ + -DCMAKE_C_LINKER_DEPFILE_SUPPORTED=FALSE \ + -DCMAKE_CXX_LINKER_DEPFILE_SUPPORTED=FALSE +# https://github.com/ziglang/zig/issues/22213 # Now cmake will use zig as the C/C++ compiler. We reset the environment variables # so that installation and testing do not get affected by them. @@ -54,7 +57,7 @@ stage3-release/bin/zig build \ -Dno-lib stage3-release/bin/zig build test docs \ - --maxrss 21000000000 \ + --maxrss ${ZSF_MAX_RSS:-0} \ -Dlldb=$HOME/deps/lldb-zig/Release-e0a42bb34/bin/lldb \ -fqemu \ -fwasmtime \ @@ -97,7 +100,10 @@ cmake .. \ -DZIG_TARGET_MCPU="$MCPU" \ -DZIG_STATIC=ON \ -DZIG_NO_LIB=ON \ - -GNinja + -GNinja \ + -DCMAKE_C_LINKER_DEPFILE_SUPPORTED=FALSE \ + -DCMAKE_CXX_LINKER_DEPFILE_SUPPORTED=FALSE +# https://github.com/ziglang/zig/issues/22213 unset CC unset CXX diff --git a/ci/x86_64-openbsd-debug.sh b/ci/x86_64-openbsd-debug.sh new file mode 100755 index 000000000000..133c8dd4d642 --- /dev/null +++ b/ci/x86_64-openbsd-debug.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +# Requires cmake ninja-build + +set -x +set -e + +TARGET="x86_64-openbsd-none" +MCPU="baseline" +CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.16.0-dev.2051+28b83e3b0" +PREFIX="$HOME/deps/$CACHE_BASENAME" +ZIG="$PREFIX/bin/zig" + +# Override the cache directories because they won't actually help other CI runs +# which will be testing alternate versions of zig, and ultimately would just +# fill up space on the hard drive for no reason. +export ZIG_GLOBAL_CACHE_DIR="$PWD/zig-global-cache" +export ZIG_LOCAL_CACHE_DIR="$PWD/zig-local-cache" + +mkdir build-debug +cd build-debug + +export CC="$ZIG cc -target $TARGET -mcpu=$MCPU" +export CXX="$ZIG c++ -target $TARGET -mcpu=$MCPU" + +cmake .. \ + -DCMAKE_INSTALL_PREFIX="stage3-debug" \ + -DCMAKE_PREFIX_PATH="$PREFIX" \ + -DCMAKE_BUILD_TYPE=Debug \ + -DZIG_TARGET_TRIPLE="$TARGET" \ + -DZIG_TARGET_MCPU="$MCPU" \ + -DZIG_STATIC=ON \ + -DZIG_NO_LIB=ON \ + -GNinja \ + -DCMAKE_C_LINKER_DEPFILE_SUPPORTED=FALSE \ + -DCMAKE_CXX_LINKER_DEPFILE_SUPPORTED=FALSE +# https://github.com/ziglang/zig/issues/22213 + +# Now cmake will use zig as the C/C++ compiler. We reset the environment variables +# so that installation and testing do not get affected by them. +unset CC +unset CXX + +ninja install + +stage3-debug/bin/zig build test docs \ + --maxrss ${ZSF_MAX_RSS:-0} \ + -Dstatic-llvm \ + -Dskip-non-native \ + --search-prefix "$PREFIX" \ + --zig-lib-dir "$PWD/../lib" \ + --test-timeout 2m + +stage3-debug/bin/zig build \ + --prefix stage4-debug \ + -Denable-llvm \ + -Dno-lib \ + -Dtarget=$TARGET \ + -Duse-zig-libcxx \ + -Dversion-string="$(stage3-debug/bin/zig version)" + +stage4-debug/bin/zig test ../test/behavior.zig diff --git a/ci/x86_64-openbsd-release.sh b/ci/x86_64-openbsd-release.sh new file mode 100755 index 000000000000..535b1a147166 --- /dev/null +++ b/ci/x86_64-openbsd-release.sh @@ -0,0 +1,68 @@ +#!/bin/sh + +# Requires cmake ninja-build + +set -x +set -e + +TARGET="x86_64-openbsd-none" +MCPU="baseline" +CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.16.0-dev.2051+28b83e3b0" +PREFIX="$HOME/deps/$CACHE_BASENAME" +ZIG="$PREFIX/bin/zig" + +# Override the cache directories because they won't actually help other CI runs +# which will be testing alternate versions of zig, and ultimately would just +# fill up space on the hard drive for no reason. +export ZIG_GLOBAL_CACHE_DIR="$PWD/zig-global-cache" +export ZIG_LOCAL_CACHE_DIR="$PWD/zig-local-cache" + +mkdir build-release +cd build-release + +export CC="$ZIG cc -target $TARGET -mcpu=$MCPU" +export CXX="$ZIG c++ -target $TARGET -mcpu=$MCPU" + +cmake .. \ + -DCMAKE_INSTALL_PREFIX="stage3-release" \ + -DCMAKE_PREFIX_PATH="$PREFIX" \ + -DCMAKE_BUILD_TYPE=Release \ + -DZIG_TARGET_TRIPLE="$TARGET" \ + -DZIG_TARGET_MCPU="$MCPU" \ + -DZIG_STATIC=ON \ + -DZIG_NO_LIB=ON \ + -GNinja \ + -DCMAKE_C_LINKER_DEPFILE_SUPPORTED=FALSE \ + -DCMAKE_CXX_LINKER_DEPFILE_SUPPORTED=FALSE +# https://github.com/ziglang/zig/issues/22213 + +# Now cmake will use zig as the C/C++ compiler. We reset the environment variables +# so that installation and testing do not get affected by them. +unset CC +unset CXX + +ninja install + +stage3-release/bin/zig build test docs \ + --maxrss ${ZSF_MAX_RSS:-0} \ + -Dstatic-llvm \ + -Dskip-non-native \ + --search-prefix "$PREFIX" \ + --zig-lib-dir "$PWD/../lib" \ + --test-timeout 2m + +# Ensure that stage3 and stage4 are byte-for-byte identical. +stage3-release/bin/zig build \ + --prefix stage4-release \ + -Denable-llvm \ + -Dno-lib \ + -Doptimize=ReleaseFast \ + -Dstrip \ + -Dtarget=$TARGET \ + -Duse-zig-libcxx \ + -Dversion-string="$(stage3-release/bin/zig version)" + +# diff returns an error code if the files differ. +echo "If the following command fails, it means nondeterminism has been" +echo "introduced, making stage3 and stage4 no longer byte-for-byte identical." +diff stage3-release/bin/zig stage4-release/bin/zig diff --git a/ci/x86_64-windows-debug.ps1 b/ci/x86_64-windows-debug.ps1 index 5cd25e680df2..e6ba8b0861b1 100644 --- a/ci/x86_64-windows-debug.ps1 +++ b/ci/x86_64-windows-debug.ps1 @@ -5,6 +5,7 @@ $ZIG_LLVM_CLANG_LLD_URL = "https://ziglang.org/deps/$ZIG_LLVM_CLANG_LLD_NAME.zip $PREFIX_PATH = "$($Env:USERPROFILE)\$ZIG_LLVM_CLANG_LLD_NAME" $ZIG = "$PREFIX_PATH\bin\zig.exe" $ZIG_LIB_DIR = "$(Get-Location)\lib" +$ZSF_MAX_RSS = if ($Env:ZSF_MAX_RSS) { $Env:ZSF_MAX_RSS } else { 0 } if (!(Test-Path "$PREFIX_PATH.zip")) { Write-Output "Downloading $ZIG_LLVM_CLANG_LLD_URL" @@ -54,11 +55,11 @@ CheckLastExitCode Write-Output "Main test suite..." & "stage3-debug\bin\zig.exe" build test docs ` + --maxrss $ZSF_MAX_RSS ` --zig-lib-dir "$ZIG_LIB_DIR" ` --search-prefix "$PREFIX_PATH" ` -Dstatic-llvm ` -Dskip-non-native ` - -Dskip-release ` -Dskip-test-incremental ` -Denable-symlinks-windows ` --test-timeout 30m diff --git a/ci/x86_64-windows-release.ps1 b/ci/x86_64-windows-release.ps1 index 900224cf9e7d..e22e3af1c79d 100644 --- a/ci/x86_64-windows-release.ps1 +++ b/ci/x86_64-windows-release.ps1 @@ -5,6 +5,7 @@ $ZIG_LLVM_CLANG_LLD_URL = "https://ziglang.org/deps/$ZIG_LLVM_CLANG_LLD_NAME.zip $PREFIX_PATH = "$($Env:USERPROFILE)\$ZIG_LLVM_CLANG_LLD_NAME" $ZIG = "$PREFIX_PATH\bin\zig.exe" $ZIG_LIB_DIR = "$(Get-Location)\lib" +$ZSF_MAX_RSS = if ($Env:ZSF_MAX_RSS) { $Env:ZSF_MAX_RSS } else { 0 } if (!(Test-Path "$PREFIX_PATH.zip")) { Write-Output "Downloading $ZIG_LLVM_CLANG_LLD_URL" @@ -54,6 +55,7 @@ CheckLastExitCode Write-Output "Main test suite..." & "stage3-release\bin\zig.exe" build test docs ` + --maxrss $ZSF_MAX_RSS ` --zig-lib-dir "$ZIG_LIB_DIR" ` --search-prefix "$PREFIX_PATH" ` -Dstatic-llvm ` diff --git a/doc/langref.html.in b/doc/langref.html.in index c0272124caeb..c3aa3c9b1b44 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -7027,8 +7027,7 @@ WebAssembly.instantiate(typedArray, { The result is 3{#end_shell_samp#} {#header_close#} {#header_open|WASI#} -

Zig's support for WebAssembly System Interface (WASI) is under active development. - Example of using the standard library and reading command line arguments:

+

Zig standard library has first-class support for WebAssembly System Interface.

{#code|wasi_args.zig#} {#shell_samp#}$ wasmtime wasi_args.wasm 123 hello diff --git a/doc/langref/bad_default_value.zig b/doc/langref/bad_default_value.zig index df38209c49f0..c80374a3334f 100644 --- a/doc/langref/bad_default_value.zig +++ b/doc/langref/bad_default_value.zig @@ -17,7 +17,7 @@ pub fn main() !void { .maximum = 0.20, }; const category = threshold.categorize(0.90); - try std.fs.File.stdout().writeAll(@tagName(category)); + std.log.info("category: {t}", .{category}); } const std = @import("std"); diff --git a/doc/langref/hello.zig b/doc/langref/hello.zig index 27ea1f689a5e..0986aaae7d4a 100644 --- a/doc/langref/hello.zig +++ b/doc/langref/hello.zig @@ -1,7 +1,7 @@ const std = @import("std"); -pub fn main() !void { - try std.fs.File.stdout().writeAll("Hello, World!\n"); +pub fn main(init: std.process.Init) !void { + try std.Io.File.stdout().writeStreamingAll(init.io, "Hello, World!\n"); } // exe=succeed diff --git a/doc/langref/runtime_shrExact_overflow.zig b/doc/langref/runtime_shrExact_overflow.zig index 32cfc33ca2de..afb9c4b9c1ae 100644 --- a/doc/langref/runtime_shrExact_overflow.zig +++ b/doc/langref/runtime_shrExact_overflow.zig @@ -7,7 +7,7 @@ pub fn main() void { const y = @shrExact(x, 2); std.debug.print("value: {}\n", .{y}); - if ((builtin.cpu.arch.isRISCV() or builtin.cpu.arch.isLoongArch() or builtin.cpu.arch == .s390x) and builtin.zig_backend == .stage2_llvm) @panic("https://github.com/ziglang/zig/issues/24304"); + if ((builtin.cpu.arch.isPowerPC() or builtin.cpu.arch.isRISCV() or builtin.cpu.arch.isLoongArch() or builtin.cpu.arch == .s390x) and builtin.zig_backend == .stage2_llvm) @panic("https://github.com/ziglang/zig/issues/24304"); } // exe=fail diff --git a/doc/langref/wasi_args.zig b/doc/langref/wasi_args.zig index 6801e67f0c7a..e1c8e532d3e8 100644 --- a/doc/langref/wasi_args.zig +++ b/doc/langref/wasi_args.zig @@ -1,13 +1,9 @@ const std = @import("std"); -pub fn main() !void { - var general_purpose_allocator: std.heap.GeneralPurposeAllocator(.{}) = .init; - const gpa = general_purpose_allocator.allocator(); - const args = try std.process.argsAlloc(gpa); - defer std.process.argsFree(gpa, args); - - for (args, 0..) |arg, i| { - std.debug.print("{}: {s}\n", .{ i, arg }); +pub fn main(init: std.process.Init) !void { + const args = try init.minimal.args.toSlice(init.arena.allocator()); + for (0.., args) |i, arg| { + std.debug.print("{d}: {s}\n", .{ i, arg }); } } diff --git a/doc/langref/wasi_preopens.zig b/doc/langref/wasi_preopens.zig index 5a167bc8dbd9..423e79f3c928 100644 --- a/doc/langref/wasi_preopens.zig +++ b/doc/langref/wasi_preopens.zig @@ -1,18 +1,8 @@ const std = @import("std"); -const fs = std.fs; -pub fn main() !void { - var general_purpose_allocator: std.heap.GeneralPurposeAllocator(.{}) = .init; - const gpa = general_purpose_allocator.allocator(); - - var arena_instance = std.heap.ArenaAllocator.init(gpa); - defer arena_instance.deinit(); - const arena = arena_instance.allocator(); - - const preopens = try fs.wasi.preopensAlloc(arena); - - for (preopens.names, 0..) |preopen, i| { - std.debug.print("{}: {s}\n", .{ i, preopen }); +pub fn main(init: std.process.Init) void { + for (init.preopens.map.keys(), 0..) |preopen, i| { + std.log.info("{d}: {s}", .{ i, preopen }); } } diff --git a/lib/c/inttypes.zig b/lib/c/inttypes.zig index 34de671d0cfe..39b2c9ba8850 100644 --- a/lib/c/inttypes.zig +++ b/lib/c/inttypes.zig @@ -2,11 +2,13 @@ const std = @import("std"); const common = @import("common.zig"); const builtin = @import("builtin"); const intmax_t = std.c.intmax_t; +const imaxdiv_t = std.c.imaxdiv_t; comptime { if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) { // Functions specific to musl and wasi-libc. @export(&imaxabs, .{ .name = "imaxabs", .linkage = common.linkage, .visibility = common.visibility }); + @export(&imaxdiv, .{ .name = "imaxdiv", .linkage = common.linkage, .visibility = common.visibility }); } } @@ -14,7 +16,19 @@ fn imaxabs(a: intmax_t) callconv(.c) intmax_t { return @intCast(@abs(a)); } +fn imaxdiv(a: intmax_t, b: intmax_t) callconv(.c) imaxdiv_t { + return .{ + .quot = @divTrunc(a, b), + .rem = @rem(a, b), + }; +} + test imaxabs { const val: intmax_t = -10; try std.testing.expectEqual(10, imaxabs(val)); } + +test imaxdiv { + const expected: imaxdiv_t = .{ .quot = 9, .rem = 0 }; + try std.testing.expectEqual(expected, imaxdiv(9, 1)); +} diff --git a/lib/c/math.zig b/lib/c/math.zig index 161e400e6d70..8282b1ff0ab7 100644 --- a/lib/c/math.zig +++ b/lib/c/math.zig @@ -10,6 +10,27 @@ comptime { @export(&isnanf, .{ .name = "__isnanf", .linkage = common.linkage, .visibility = common.visibility }); @export(&isnanl, .{ .name = "isnanl", .linkage = common.linkage, .visibility = common.visibility }); @export(&isnanl, .{ .name = "__isnanl", .linkage = common.linkage, .visibility = common.visibility }); + + @export(&std.math.nan(f64), .{ .name = "__QNAN", .linkage = common.linkage, .visibility = common.visibility }); + @export(&std.math.snan(f64), .{ .name = "__SNAN", .linkage = common.linkage, .visibility = common.visibility }); + @export(&std.math.inf(f64), .{ .name = "__INF", .linkage = common.linkage, .visibility = common.visibility }); + @export(&std.math.floatTrueMin(f64), .{ .name = "__DENORM", .linkage = common.linkage, .visibility = common.visibility }); + + @export(&std.math.nan(f32), .{ .name = "__QNANF", .linkage = common.linkage, .visibility = common.visibility }); + @export(&std.math.snan(f32), .{ .name = "__SNANF", .linkage = common.linkage, .visibility = common.visibility }); + @export(&std.math.inf(f32), .{ .name = "__INFF", .linkage = common.linkage, .visibility = common.visibility }); + @export(&std.math.floatTrueMin(f32), .{ .name = "__DENORMF", .linkage = common.linkage, .visibility = common.visibility }); + + @export(&std.math.nan(c_longdouble), .{ .name = "__QNANL", .linkage = common.linkage, .visibility = common.visibility }); + @export(&std.math.snan(c_longdouble), .{ .name = "__SNANL", .linkage = common.linkage, .visibility = common.visibility }); + @export(&std.math.inf(c_longdouble), .{ .name = "__INFL", .linkage = common.linkage, .visibility = common.visibility }); + @export(&std.math.floatTrueMin(c_longdouble), .{ .name = "__DENORML", .linkage = common.linkage, .visibility = common.visibility }); + } + + if (builtin.target.isMinGW() or builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) { + @export(&nan, .{ .name = "nan", .linkage = common.linkage, .visibility = common.visibility }); + @export(&nanf, .{ .name = "nanf", .linkage = common.linkage, .visibility = common.visibility }); + @export(&nanl, .{ .name = "nanl", .linkage = common.linkage, .visibility = common.visibility }); } } @@ -24,3 +45,15 @@ fn isnanf(x: f32) callconv(.c) c_int { fn isnanl(x: c_longdouble) callconv(.c) c_int { return if (std.math.isNan(x)) 1 else 0; } + +fn nan(_: [*:0]const c_char) callconv(.c) f64 { + return std.math.nan(f64); +} + +fn nanf(_: [*:0]const c_char) callconv(.c) f32 { + return std.math.nan(f32); +} + +fn nanl(_: [*:0]const c_char) callconv(.c) c_longdouble { + return std.math.nan(c_longdouble); +} diff --git a/lib/c/stdlib.zig b/lib/c/stdlib.zig index e427771640d0..c8db9b85798a 100644 --- a/lib/c/stdlib.zig +++ b/lib/c/stdlib.zig @@ -1,6 +1,9 @@ const std = @import("std"); const common = @import("common.zig"); const builtin = @import("builtin"); +const div_t = std.c.div_t; +const ldiv_t = std.c.ldiv_t; +const lldiv_t = std.c.lldiv_t; comptime { if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) { @@ -8,6 +11,15 @@ comptime { @export(&abs, .{ .name = "abs", .linkage = common.linkage, .visibility = common.visibility }); @export(&labs, .{ .name = "labs", .linkage = common.linkage, .visibility = common.visibility }); @export(&llabs, .{ .name = "llabs", .linkage = common.linkage, .visibility = common.visibility }); + + @export(&div, .{ .name = "div", .linkage = common.linkage, .visibility = common.visibility }); + @export(&ldiv, .{ .name = "ldiv", .linkage = common.linkage, .visibility = common.visibility }); + @export(&lldiv, .{ .name = "lldiv", .linkage = common.linkage, .visibility = common.visibility }); + + @export(&qsort_r, .{ .name = "qsort_r", .linkage = common.linkage, .visibility = common.visibility }); + @export(&qsort, .{ .name = "qsort", .linkage = common.linkage, .visibility = common.visibility }); + + @export(&bsearch, .{ .name = "bsearch", .linkage = common.linkage, .visibility = common.visibility }); } } @@ -23,6 +35,88 @@ fn llabs(a: c_longlong) callconv(.c) c_longlong { return @intCast(@abs(a)); } +fn div(a: c_int, b: c_int) callconv(.c) div_t { + return .{ + .quot = @divTrunc(a, b), + .rem = @rem(a, b), + }; +} + +fn ldiv(a: c_long, b: c_long) callconv(.c) ldiv_t { + return .{ + .quot = @divTrunc(a, b), + .rem = @rem(a, b), + }; +} + +fn lldiv(a: c_longlong, b: c_longlong) callconv(.c) lldiv_t { + return .{ + .quot = @divTrunc(a, b), + .rem = @rem(a, b), + }; +} + +// NOTE: Despite its name, `qsort` doesn't have to use quicksort or make any complexity or stability guarantee. +fn qsort_r(base: *anyopaque, n: usize, size: usize, compare: *const fn (a: *const anyopaque, b: *const anyopaque, arg: ?*anyopaque) callconv(.c) c_int, arg: ?*anyopaque) callconv(.c) void { + const Context = struct { + base: [*]u8, + size: usize, + compare: *const fn (a: *const anyopaque, b: *const anyopaque, arg: ?*anyopaque) callconv(.c) c_int, + arg: ?*anyopaque, + + pub fn lessThan(ctx: @This(), a: usize, b: usize) bool { + return ctx.compare(&ctx.base[a * ctx.size], &ctx.base[b * ctx.size], ctx.arg) < 0; + } + + pub fn swap(ctx: @This(), a: usize, b: usize) void { + const a_bytes: []u8 = ctx.base[a * ctx.size ..][0..ctx.size]; + const b_bytes: []u8 = ctx.base[b * ctx.size ..][0..ctx.size]; + + for (a_bytes, b_bytes) |*ab, *bb| { + const tmp = ab.*; + ab.* = bb.*; + bb.* = tmp; + } + } + }; + + std.mem.sortUnstableContext(0, n, Context{ + .base = @ptrCast(base), + .size = size, + .compare = compare, + .arg = arg, + }); +} + +fn qsort(base: *anyopaque, n: usize, size: usize, compare: *const fn (a: *const anyopaque, b: *const anyopaque) callconv(.c) c_int) callconv(.c) void { + return qsort_r(base, n, size, (struct { + fn wrap(a: *const anyopaque, b: *const anyopaque, arg: ?*anyopaque) callconv(.c) c_int { + const cmp: *const fn (a: *const anyopaque, b: *const anyopaque) callconv(.c) c_int = @ptrCast(@alignCast(arg.?)); + return cmp(a, b); + } + }).wrap, @constCast(compare)); +} + +// NOTE: Despite its name, `bsearch` doesn't need to be implemented using binary search or make any complexity guarantee. +fn bsearch(key: *const anyopaque, base: *const anyopaque, n: usize, size: usize, compare: *const fn (a: *const anyopaque, b: *const anyopaque) callconv(.c) c_int) callconv(.c) ?*anyopaque { + const base_bytes: [*]const u8 = @ptrCast(base); + var low: usize = 0; + var high: usize = n; + + while (low < high) { + // Avoid overflowing in the midpoint calculation + const mid = low + (high - low) / 2; + const elem = &base_bytes[mid * size]; + + switch (std.math.order(compare(key, elem), 0)) { + .eq => return @constCast(elem), + .gt => low = mid + 1, + .lt => high = mid, + } + } + return null; +} + test abs { const val: c_int = -10; try std.testing.expectEqual(10, abs(val)); @@ -37,3 +131,41 @@ test llabs { const val: c_longlong = -10; try std.testing.expectEqual(10, llabs(val)); } + +test div { + const expected: div_t = .{ .quot = 5, .rem = 5 }; + try std.testing.expectEqual(expected, div(55, 10)); +} + +test ldiv { + const expected: ldiv_t = .{ .quot = -6, .rem = 2 }; + try std.testing.expectEqual(expected, ldiv(38, -6)); +} + +test lldiv { + const expected: lldiv_t = .{ .quot = 1, .rem = 2 }; + try std.testing.expectEqual(expected, lldiv(5, 3)); +} + +test bsearch { + const Comparison = struct { + pub fn compare(a: *const anyopaque, b: *const anyopaque) callconv(.c) c_int { + const a_u16: *const u16 = @ptrCast(@alignCast(a)); + const b_u16: *const u16 = @ptrCast(@alignCast(b)); + + return switch (std.math.order(a_u16.*, b_u16.*)) { + .gt => 1, + .eq => 0, + .lt => -1, + }; + } + }; + + const items: []const u16 = &.{ 0, 5, 7, 9, 10, 200, 512, 768 }; + + try std.testing.expectEqual(@as(?*anyopaque, null), bsearch(&@as(u16, 2000), items.ptr, items.len, @sizeOf(u16), Comparison.compare)); + + for (items) |*value| { + try std.testing.expectEqual(@as(*const anyopaque, value), bsearch(value, items.ptr, items.len, @sizeOf(u16), Comparison.compare)); + } +} diff --git a/lib/compiler/aro/aro/Compilation.zig b/lib/compiler/aro/aro/Compilation.zig index c98badcc2296..6f3a1a44da11 100644 --- a/lib/compiler/aro/aro/Compilation.zig +++ b/lib/compiler/aro/aro/Compilation.zig @@ -74,9 +74,7 @@ pub const Environment = struct { pub const default: @This() = .{ .provided = 0 }; }; - /// Load all of the environment variables using the std.process API. Do not use if using Aro as a shared library on Linux without libc - /// See https://github.com/ziglang/zig/issues/4524 - pub fn loadAll(allocator: std.mem.Allocator) !Environment { + pub fn loadAll(allocator: std.mem.Allocator, environ_map: *const std.process.Environ.Map) !Environment { var env: Environment = .{}; errdefer env.deinit(allocator); @@ -85,11 +83,7 @@ pub const Environment = struct { var env_var_buf: [field.name.len]u8 = undefined; const env_var_name = std.ascii.upperString(&env_var_buf, field.name); - const val: ?[]const u8 = std.process.getEnvVarOwned(allocator, env_var_name) catch |err| switch (err) { - error.OutOfMemory => |e| return e, - error.EnvironmentVariableNotFound => null, - error.InvalidWtf8 => null, - }; + const val: ?[]const u8 = if (environ_map.get(env_var_name)) |v| try allocator.dupe(u8, v) else null; @field(env, field.name) = val; } return env; @@ -154,7 +148,7 @@ gpa: Allocator, /// Allocations in this arena live all the way until `Compilation.deinit`. arena: Allocator, io: Io, -cwd: std.fs.Dir, +cwd: Io.Dir, diagnostics: *Diagnostics, sources: std.StringArrayHashMapUnmanaged(Source) = .empty, @@ -181,7 +175,7 @@ pragma_handlers: std.StringArrayHashMapUnmanaged(*Pragma) = .empty, /// Used by MS extensions which allow searching for includes relative to the directory of the main source file. ms_cwd_source_id: ?Source.Id = null, -pub fn init(gpa: Allocator, arena: Allocator, io: Io, diagnostics: *Diagnostics, cwd: std.fs.Dir) Compilation { +pub fn init(gpa: Allocator, arena: Allocator, io: Io, diagnostics: *Diagnostics, cwd: Io.Dir) Compilation { return .{ .gpa = gpa, .arena = arena, @@ -193,13 +187,20 @@ pub fn init(gpa: Allocator, arena: Allocator, io: Io, diagnostics: *Diagnostics, /// Initialize Compilation with default environment, /// pragma handlers and emulation mode set to target. -pub fn initDefault(gpa: Allocator, arena: Allocator, io: Io, diagnostics: *Diagnostics, cwd: std.fs.Dir) !Compilation { +pub fn initDefault( + gpa: Allocator, + arena: Allocator, + io: Io, + diagnostics: *Diagnostics, + cwd: Io.Dir, + environ_map: *const std.process.Environ.Map, +) !Compilation { var comp: Compilation = .{ .gpa = gpa, .arena = arena, .io = io, .diagnostics = diagnostics, - .environment = try Environment.loadAll(gpa), + .environment = try Environment.loadAll(gpa, environ_map), .cwd = cwd, }; errdefer comp.deinit(); @@ -660,6 +661,7 @@ fn generateSystemDefines(comp: *Compilation, w: *Io.Writer) !void { try define(w, "__PPC64__"); try define(w, "_ARCH_PPC"); try define(w, "_ARCH_PPC64"); + try w.writeAll("#define _CALL_ELF 2\n"); }, .sparc64 => { try defineStd(w, "sparc", is_gnu); @@ -1638,12 +1640,14 @@ fn addSourceFromPathExtra(comp: *Compilation, path: []const u8, kind: Source.Kin return error.FileNotFound; } - const file = try comp.cwd.openFile(path, .{}); - defer file.close(); + const io = comp.io; + + const file = try comp.cwd.openFile(io, path, .{}); + defer file.close(io); return comp.addSourceFromFile(file, path, kind); } -pub fn addSourceFromFile(comp: *Compilation, file: std.fs.File, path: []const u8, kind: Source.Kind) !Source { +pub fn addSourceFromFile(comp: *Compilation, file: Io.File, path: []const u8, kind: Source.Kind) !Source { const contents = try comp.getFileContents(file, .unlimited); errdefer comp.gpa.free(contents); return comp.addSourceFromOwnedBuffer(path, contents, kind); @@ -1710,7 +1714,8 @@ pub fn initSearchPath(comp: *Compilation, includes: []const Include, verbose: bo } } fn addToSearchPath(comp: *Compilation, include: Include, verbose: bool) !void { - comp.cwd.access(include.path, .{}) catch { + const io = comp.io; + comp.cwd.access(io, include.path, .{}) catch { if (verbose) { std.debug.print("ignoring nonexistent directory \"{s}\"\n", .{include.path}); return; @@ -1970,12 +1975,14 @@ fn getPathContents(comp: *Compilation, path: []const u8, limit: Io.Limit) ![]u8 return error.FileNotFound; } - const file = try comp.cwd.openFile(path, .{}); - defer file.close(); + const io = comp.io; + + const file = try comp.cwd.openFile(io, path, .{}); + defer file.close(io); return comp.getFileContents(file, limit); } -fn getFileContents(comp: *Compilation, file: std.fs.File, limit: Io.Limit) ![]u8 { +fn getFileContents(comp: *Compilation, file: Io.File, limit: Io.Limit) ![]u8 { var file_buf: [4096]u8 = undefined; var file_reader = file.reader(comp.io, &file_buf); @@ -2157,8 +2164,9 @@ pub fn locSlice(comp: *const Compilation, loc: Source.Location) []const u8 { } pub fn getSourceMTimeUncached(comp: *const Compilation, source_id: Source.Id) ?u64 { + const io = comp.io; const source = comp.getSource(source_id); - if (comp.cwd.statFile(source.path)) |stat| { + if (comp.cwd.statFile(io, source.path, .{})) |stat| { return std.math.cast(u64, stat.mtime.toSeconds()); } else |_| { return null; @@ -2248,7 +2256,7 @@ test "addSourceFromBuffer" { var arena: std.heap.ArenaAllocator = .init(std.testing.allocator); defer arena.deinit(); var diagnostics: Diagnostics = .{ .output = .ignore }; - var comp = Compilation.init(std.testing.allocator, arena.allocator(), std.testing.io, &diagnostics, std.fs.cwd()); + var comp = Compilation.init(std.testing.allocator, arena.allocator(), std.testing.io, &diagnostics, Io.Dir.cwd()); defer comp.deinit(); const source = try comp.addSourceFromBuffer("path", str); @@ -2262,7 +2270,7 @@ test "addSourceFromBuffer" { var arena: std.heap.ArenaAllocator = .init(allocator); defer arena.deinit(); var diagnostics: Diagnostics = .{ .output = .ignore }; - var comp = Compilation.init(allocator, arena.allocator(), std.testing.io, &diagnostics, std.fs.cwd()); + var comp = Compilation.init(allocator, arena.allocator(), std.testing.io, &diagnostics, Io.Dir.cwd()); defer comp.deinit(); _ = try comp.addSourceFromBuffer("path", "spliced\\\nbuffer\n"); @@ -2308,7 +2316,7 @@ test "addSourceFromBuffer - exhaustive check for carriage return elimination" { var buf: [alphabet.len]u8 = @splat(alphabet[0]); var diagnostics: Diagnostics = .{ .output = .ignore }; - var comp = Compilation.init(std.testing.allocator, arena.allocator(), std.testing.io, &diagnostics, std.fs.cwd()); + var comp = Compilation.init(std.testing.allocator, arena.allocator(), std.testing.io, &diagnostics, Io.Dir.cwd()); defer comp.deinit(); var source_count: u32 = 0; @@ -2336,7 +2344,7 @@ test "ignore BOM at beginning of file" { const Test = struct { fn run(arena: Allocator, buf: []const u8) !void { var diagnostics: Diagnostics = .{ .output = .ignore }; - var comp = Compilation.init(std.testing.allocator, arena, std.testing.io, &diagnostics, std.fs.cwd()); + var comp = Compilation.init(std.testing.allocator, arena, std.testing.io, &diagnostics, Io.Dir.cwd()); defer comp.deinit(); const source = try comp.addSourceFromBuffer("file.c", buf); diff --git a/lib/compiler/aro/aro/Diagnostics.zig b/lib/compiler/aro/aro/Diagnostics.zig index 2d58a217ea8a..993b5d93af65 100644 --- a/lib/compiler/aro/aro/Diagnostics.zig +++ b/lib/compiler/aro/aro/Diagnostics.zig @@ -24,20 +24,21 @@ pub const Message = struct { @"fatal error", }; - pub fn write(msg: Message, w: *std.Io.Writer, config: std.Io.tty.Config, details: bool) std.Io.tty.Config.SetColorError!void { - try config.setColor(w, .bold); + pub fn write(msg: Message, t: std.Io.Terminal, details: bool) std.Io.Terminal.SetColorError!void { + const w = t.writer; + try t.setColor(.bold); if (msg.location) |loc| { try w.print("{s}:{d}:{d}: ", .{ loc.path, loc.line_no, loc.col }); } switch (msg.effective_kind) { - .@"fatal error", .@"error" => try config.setColor(w, .bright_red), - .note => try config.setColor(w, .bright_cyan), - .warning => try config.setColor(w, .bright_magenta), + .@"fatal error", .@"error" => try t.setColor(.bright_red), + .note => try t.setColor(.bright_cyan), + .warning => try t.setColor(.bright_magenta), .off => unreachable, } try w.print("{s}: ", .{@tagName(msg.effective_kind)}); - try config.setColor(w, .white); + try t.setColor(.white); try w.writeAll(msg.text); if (msg.opt) |some| { if (msg.effective_kind == .@"error" and msg.kind != .@"error") { @@ -55,17 +56,17 @@ pub const Message = struct { if (!details or msg.location == null) { try w.writeAll("\n"); - try config.setColor(w, .reset); + try t.setColor(.reset); } else { const loc = msg.location.?; const trailer = if (loc.end_with_splice) "\\ " else ""; - try config.setColor(w, .reset); + try t.setColor(.reset); try w.print("\n{s}{s}\n", .{ loc.line, trailer }); try w.splatByteAll(' ', loc.width); - try config.setColor(w, .bold); - try config.setColor(w, .bright_green); + try t.setColor(.bold); + try t.setColor(.bright_green); try w.writeAll("^\n"); - try config.setColor(w, .reset); + try t.setColor(.reset); } try w.flush(); } @@ -290,10 +291,7 @@ pub const State = struct { const Diagnostics = @This(); output: union(enum) { - to_writer: struct { - writer: *std.Io.Writer, - color: std.Io.tty.Config, - }, + to_writer: std.Io.Terminal, to_list: struct { messages: std.ArrayList(Message) = .empty, arena: std.heap.ArenaAllocator, @@ -543,11 +541,11 @@ fn addMessage(d: *Diagnostics, msg: Message) Compilation.Error!void { switch (d.output) { .ignore => {}, - .to_writer => |writer| { - var config = writer.color; - if (d.color == false) config = .no_color; - if (d.color == true and config == .no_color) config = .escape_codes; - msg.write(writer.writer, config, d.details) catch { + .to_writer => |t| { + var new_mode = t.mode; + if (d.color == false) new_mode = .no_color; + if (d.color == true and new_mode == .no_color) new_mode = .escape_codes; + msg.write(.{ .writer = t.writer, .mode = new_mode }, d.details) catch { return error.FatalError; }; }, diff --git a/lib/compiler/aro/aro/Driver.zig b/lib/compiler/aro/aro/Driver.zig index 6a399ece399d..5c356dc5b130 100644 --- a/lib/compiler/aro/aro/Driver.zig +++ b/lib/compiler/aro/aro/Driver.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const mem = std.mem; const Allocator = mem.Allocator; const process = std.process; @@ -133,8 +134,9 @@ strip: bool = false, unwindlib: ?[]const u8 = null, pub fn deinit(d: *Driver) void { + const io = d.comp.io; for (d.link_objects.items[d.link_objects.items.len - d.temp_file_count ..]) |obj| { - std.fs.deleteFileAbsolute(obj) catch {}; + Io.Dir.deleteFileAbsolute(io, obj) catch {}; d.comp.gpa.free(obj); } d.inputs.deinit(d.comp.gpa); @@ -1061,7 +1063,7 @@ pub fn printDiagnosticsStats(d: *Driver) void { } } -pub fn detectConfig(d: *Driver, file: std.fs.File) std.Io.tty.Config { +pub fn detectConfig(d: *Driver, file: Io.File) std.Io.tty.Config { if (d.diagnostics.color == false) return .no_color; const force_color = d.diagnostics.color == true; @@ -1109,7 +1111,7 @@ pub fn main(d: *Driver, tc: *Toolchain, args: []const []const u8, comptime fast_ defer macro_buf.deinit(d.comp.gpa); var stdout_buf: [256]u8 = undefined; - var stdout = std.fs.File.stdout().writer(&stdout_buf); + var stdout = Io.File.stdout().writer(&stdout_buf); if (parseArgs(d, &stdout.interface, ¯o_buf, args) catch |er| switch (er) { error.WriteFailed => return d.fatal("failed to write to stdout: {s}", .{errorDescription(er)}), error.OutOfMemory => return error.OutOfMemory, @@ -1215,13 +1217,14 @@ pub fn getDepFileName(d: *Driver, source: Source, buf: *[std.fs.max_name_bytes]u } fn getRandomFilename(d: *Driver, buf: *[std.fs.max_name_bytes]u8, extension: []const u8) ![]const u8 { + const io = d.comp.io; const random_bytes_count = 12; - const sub_path_len = comptime std.fs.base64_encoder.calcSize(random_bytes_count); + const sub_path_len = comptime std.base64.url_safe.Encoder.calcSize(random_bytes_count); var random_bytes: [random_bytes_count]u8 = undefined; - std.crypto.random.bytes(&random_bytes); + io.random(&random_bytes); var random_name: [sub_path_len]u8 = undefined; - _ = std.fs.base64_encoder.encode(&random_name, &random_bytes); + _ = std.base64.url_safe.Encoder.encode(&random_name, &random_bytes); const fmt_template = "/tmp/{s}{s}"; const fmt_args = .{ @@ -1248,21 +1251,25 @@ fn getOutFileName(d: *Driver, source: Source, buf: *[std.fs.max_name_bytes]u8) ! } fn invokeAssembler(d: *Driver, tc: *Toolchain, input_path: []const u8, output_path: []const u8) !void { + const io = d.comp.io; var assembler_path_buf: [std.fs.max_path_bytes]u8 = undefined; const assembler_path = try tc.getAssemblerPath(&assembler_path_buf); const argv = [_][]const u8{ assembler_path, input_path, "-o", output_path }; - var child = std.process.Child.init(&argv, d.comp.gpa); - // TODO handle better - child.stdin_behavior = .Inherit; - child.stdout_behavior = .Inherit; - child.stderr_behavior = .Inherit; - - const term = child.spawnAndWait() catch |er| { + var child = std.process.spawn(io, .{ + .argv = &argv, + // TODO handle better + .stdin = .inherit, + .stdout = .inherit, + .stderr = .inherit, + }) catch |er| { return d.fatal("unable to spawn linker: {s}", .{errorDescription(er)}); }; + const term = child.wait(io) catch |er| { + return d.fatal("unable to wait linker: {s}", .{errorDescription(er)}); + }; switch (term) { - .Exited => |code| if (code != 0) { + .exited => |code| if (code != 0) { const e = d.fatal("assembler exited with an error code", .{}); return e; }, @@ -1286,6 +1293,8 @@ fn processSource( d.comp.generated_buf.items.len = 0; const prev_total = d.diagnostics.errors; + const io = d.comp.io; + var pp = try Preprocessor.initDefault(d.comp); defer pp.deinit(); @@ -1324,13 +1333,13 @@ fn processSource( const dep_file_name = try d.getDepFileName(source, writer_buf[0..std.fs.max_name_bytes]); const file = if (dep_file_name) |path| - d.comp.cwd.createFile(path, .{}) catch |er| + d.comp.cwd.createFile(io, path, .{}) catch |er| return d.fatal("unable to create dependency file '{s}': {s}", .{ path, errorDescription(er) }) else - std.fs.File.stdout(); - defer if (dep_file_name != null) file.close(); + Io.File.stdout(); + defer if (dep_file_name != null) file.close(io); - var file_writer = file.writer(&writer_buf); + var file_writer = file.writer(io, &writer_buf); dep_file.write(&file_writer.interface) catch return d.fatal("unable to write dependency file: {s}", .{errorDescription(file_writer.err.?)}); } @@ -1349,13 +1358,13 @@ fn processSource( } const file = if (d.output_name) |some| - d.comp.cwd.createFile(some, .{}) catch |er| + d.comp.cwd.createFile(io, some, .{}) catch |er| return d.fatal("unable to create output file '{s}': {s}", .{ some, errorDescription(er) }) else - std.fs.File.stdout(); - defer if (d.output_name != null) file.close(); + Io.File.stdout(); + defer if (d.output_name != null) file.close(io); - var file_writer = file.writer(&writer_buf); + var file_writer = file.writer(io, &writer_buf); pp.prettyPrintTokens(&file_writer.interface, dump_mode) catch return d.fatal("unable to write result: {s}", .{errorDescription(file_writer.err.?)}); @@ -1367,7 +1376,7 @@ fn processSource( defer tree.deinit(); if (d.verbose_ast) { - var stdout = std.fs.File.stdout().writer(&writer_buf); + var stdout = Io.File.stdout().writer(&writer_buf); tree.dump(d.detectConfig(stdout.file), &stdout.interface) catch {}; } @@ -1402,9 +1411,9 @@ fn processSource( defer assembly.deinit(gpa); if (d.only_preprocess_and_compile) { - const out_file = d.comp.cwd.createFile(out_file_name, .{}) catch |er| + const out_file = d.comp.cwd.createFile(io, out_file_name, .{}) catch |er| return d.fatal("unable to create output file '{s}': {s}", .{ out_file_name, errorDescription(er) }); - defer out_file.close(); + defer out_file.close(io); assembly.writeToFile(out_file) catch |er| return d.fatal("unable to write to output file '{s}': {s}", .{ out_file_name, errorDescription(er) }); @@ -1416,9 +1425,9 @@ fn processSource( // then assemble to out_file_name var assembly_name_buf: [std.fs.max_name_bytes]u8 = undefined; const assembly_out_file_name = try d.getRandomFilename(&assembly_name_buf, ".s"); - const out_file = d.comp.cwd.createFile(assembly_out_file_name, .{}) catch |er| + const out_file = d.comp.cwd.createFile(io, assembly_out_file_name, .{}) catch |er| return d.fatal("unable to create output file '{s}': {s}", .{ assembly_out_file_name, errorDescription(er) }); - defer out_file.close(); + defer out_file.close(io); assembly.writeToFile(out_file) catch |er| return d.fatal("unable to write to output file '{s}': {s}", .{ assembly_out_file_name, errorDescription(er) }); try d.invokeAssembler(tc, assembly_out_file_name, out_file_name); @@ -1431,7 +1440,7 @@ fn processSource( defer ir.deinit(gpa); if (d.verbose_ir) { - var stdout = std.fs.File.stdout().writer(&writer_buf); + var stdout = Io.File.stdout().writer(&writer_buf); ir.dump(gpa, d.detectConfig(stdout.file), &stdout.interface) catch {}; } @@ -1452,11 +1461,11 @@ fn processSource( }; defer obj.deinit(); - const out_file = d.comp.cwd.createFile(out_file_name, .{}) catch |er| + const out_file = d.comp.cwd.createFile(io, out_file_name, .{}) catch |er| return d.fatal("unable to create output file '{s}': {s}", .{ out_file_name, errorDescription(er) }); - defer out_file.close(); + defer out_file.close(io); - var file_writer = out_file.writer(&writer_buf); + var file_writer = out_file.writer(io, &writer_buf); obj.finish(&file_writer.interface) catch return d.fatal("could not output to object file '{s}': {s}", .{ out_file_name, errorDescription(file_writer.err.?) }); } @@ -1486,6 +1495,7 @@ fn dumpLinkerArgs(w: *std.Io.Writer, items: []const []const u8) !void { /// **MAY call `exit` if `fast_exit` is set.** pub fn invokeLinker(d: *Driver, tc: *Toolchain, comptime fast_exit: bool) Compilation.Error!void { const gpa = d.comp.gpa; + const io = d.comp.io; var argv: std.ArrayList([]const u8) = .empty; defer argv.deinit(gpa); @@ -1497,22 +1507,25 @@ pub fn invokeLinker(d: *Driver, tc: *Toolchain, comptime fast_exit: bool) Compil if (d.verbose_linker_args) { var stdout_buf: [4096]u8 = undefined; - var stdout = std.fs.File.stdout().writer(&stdout_buf); + var stdout = Io.File.stdout().writer(&stdout_buf); dumpLinkerArgs(&stdout.interface, argv.items) catch { return d.fatal("unable to dump linker args: {s}", .{errorDescription(stdout.err.?)}); }; } - var child = std.process.Child.init(argv.items, d.comp.gpa); - // TODO handle better - child.stdin_behavior = .Inherit; - child.stdout_behavior = .Inherit; - child.stderr_behavior = .Inherit; - - const term = child.spawnAndWait() catch |er| { + var child = std.process.spawn(io, .{ + .argv = argv.items, + // TODO handle better + .stdin = .inherit, + .stdout = .inherit, + .stderr = .inherit, + }) catch |er| { return d.fatal("unable to spawn linker: {s}", .{errorDescription(er)}); }; + const term = child.wait(io) catch |er| { + return d.fatal("unable to wait linker: {s}", .{errorDescription(er)}); + }; switch (term) { - .Exited => |code| if (code != 0) { + .exited => |code| if (code != 0) { const e = d.fatal("linker exited with an error code", .{}); if (fast_exit) d.exitWithCleanup(code); return e; diff --git a/lib/compiler/aro/aro/Driver/Filesystem.zig b/lib/compiler/aro/aro/Driver/Filesystem.zig index 87092cb23513..c229dfd831e0 100644 --- a/lib/compiler/aro/aro/Driver/Filesystem.zig +++ b/lib/compiler/aro/aro/Driver/Filesystem.zig @@ -1,8 +1,10 @@ -const std = @import("std"); -const mem = std.mem; const builtin = @import("builtin"); const is_windows = builtin.os.tag == .windows; +const std = @import("std"); +const Io = std.Io; +const mem = std.std.mem; + fn readFileFake(entries: []const Filesystem.Entry, path: []const u8, buf: []u8) ?[]const u8 { @branchHint(.cold); for (entries) |entry| { @@ -55,8 +57,8 @@ fn existsFake(entries: []const Filesystem.Entry, path: []const u8) bool { return false; } -fn canExecutePosix(path: []const u8) bool { - std.posix.access(path, std.posix.X_OK) catch return false; +fn canExecutePosix(io: Io, path: []const u8) bool { + Io.Dir.accessAbsolute(io, path, .{ .execute = true }) catch return false; // Todo: ensure path is not a directory return true; } @@ -96,7 +98,7 @@ fn findProgramByNamePosix(name: []const u8, path: ?[]const u8, buf: []u8) ?[]con } pub const Filesystem = union(enum) { - real: std.fs.Dir, + real: std.Io.Dir, fake: []const Entry, const Entry = struct { @@ -121,7 +123,7 @@ pub const Filesystem = union(enum) { base: []const u8, i: usize = 0, - fn next(self: *@This()) !?std.fs.Dir.Entry { + fn next(self: *@This()) !?std.Io.Dir.Entry { while (self.i < self.entries.len) { const entry = self.entries[self.i]; self.i += 1; @@ -130,7 +132,7 @@ pub const Filesystem = union(enum) { const remaining = entry.path[self.base.len + 1 ..]; if (std.mem.indexOfScalar(u8, remaining, std.fs.path.sep) != null) continue; const extension = std.fs.path.extension(remaining); - const kind: std.fs.Dir.Entry.Kind = if (extension.len == 0) .directory else .file; + const kind: std.Io.Dir.Entry.Kind = if (extension.len == 0) .directory else .file; return .{ .name = remaining, .kind = kind }; } } @@ -140,7 +142,7 @@ pub const Filesystem = union(enum) { }; const Dir = union(enum) { - dir: std.fs.Dir, + dir: std.Io.Dir, fake: FakeDir, pub fn iterate(self: Dir) Iterator { @@ -150,19 +152,19 @@ pub const Filesystem = union(enum) { }; } - pub fn close(self: *Dir) void { + pub fn close(self: *Dir, io: Io) void { switch (self.*) { - .dir => |*d| d.close(), + .dir => |*d| d.close(io), .fake => {}, } } }; const Iterator = union(enum) { - iterator: std.fs.Dir.Iterator, + iterator: std.Io.Dir.Iterator, fake: FakeDir.Iterator, - pub fn next(self: *Iterator) std.fs.Dir.Iterator.Error!?std.fs.Dir.Entry { + pub fn next(self: *Iterator) std.Io.Dir.Iterator.Error!?std.Io.Dir.Entry { return switch (self.*) { .iterator => |*it| it.next(), .fake => |*it| it.next(), @@ -170,10 +172,10 @@ pub const Filesystem = union(enum) { } }; - pub fn exists(fs: Filesystem, path: []const u8) bool { + pub fn exists(fs: Filesystem, io: Io, path: []const u8) bool { switch (fs) { .real => |cwd| { - cwd.access(path, .{}) catch return false; + cwd.access(io, path, .{}) catch return false; return true; }, .fake => |paths| return existsFake(paths, path), @@ -208,11 +210,11 @@ pub const Filesystem = union(enum) { /// Read the file at `path` into `buf`. /// Returns null if any errors are encountered /// Otherwise returns a slice of `buf`. If the file is larger than `buf` partial contents are returned - pub fn readFile(fs: Filesystem, path: []const u8, buf: []u8) ?[]const u8 { + pub fn readFile(fs: Filesystem, io: Io, path: []const u8, buf: []u8) ?[]const u8 { return switch (fs) { .real => |cwd| { - const file = cwd.openFile(path, .{}) catch return null; - defer file.close(); + const file = cwd.openFile(io, path, .{}) catch return null; + defer file.close(io); const bytes_read = file.readAll(buf) catch return null; return buf[0..bytes_read]; @@ -221,9 +223,9 @@ pub const Filesystem = union(enum) { }; } - pub fn openDir(fs: Filesystem, dir_name: []const u8) std.fs.Dir.OpenError!Dir { + pub fn openDir(fs: Filesystem, io: Io, dir_name: []const u8) std.Io.Dir.OpenError!Dir { return switch (fs) { - .real => |cwd| .{ .dir = try cwd.openDir(dir_name, .{ .access_sub_paths = false, .iterate = true }) }, + .real => |cwd| .{ .dir = try cwd.openDir(io, dir_name, .{ .access_sub_paths = false, .iterate = true }) }, .fake => |entries| .{ .fake = .{ .entries = entries, .path = dir_name } }, }; } diff --git a/lib/compiler/aro/aro/Parser.zig b/lib/compiler/aro/aro/Parser.zig index 4a89e0d46077..fc21ee4d0b5f 100644 --- a/lib/compiler/aro/aro/Parser.zig +++ b/lib/compiler/aro/aro/Parser.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const mem = std.mem; const Allocator = mem.Allocator; const assert = std.debug.assert; @@ -211,7 +212,7 @@ fn checkIdentifierCodepointWarnings(p: *Parser, codepoint: u21, loc: Source.Loca const prev_total = p.diagnostics.total; var sf = std.heap.stackFallback(1024, p.comp.gpa); - var allocating: std.Io.Writer.Allocating = .init(sf.get()); + var allocating: Io.Writer.Allocating = .init(sf.get()); defer allocating.deinit(); if (!char_info.isC99IdChar(codepoint)) { @@ -425,7 +426,7 @@ pub fn err(p: *Parser, tok_i: TokenIndex, diagnostic: Diagnostic, args: anytype) if (p.diagnostics.effectiveKind(diagnostic) == .off) return; var sf = std.heap.stackFallback(1024, p.comp.gpa); - var allocating: std.Io.Writer.Allocating = .init(sf.get()); + var allocating: Io.Writer.Allocating = .init(sf.get()); defer allocating.deinit(); p.formatArgs(&allocating.writer, diagnostic.fmt, args) catch return error.OutOfMemory; @@ -447,7 +448,7 @@ pub fn err(p: *Parser, tok_i: TokenIndex, diagnostic: Diagnostic, args: anytype) }, p.pp.expansionSlice(tok_i), true); } -fn formatArgs(p: *Parser, w: *std.Io.Writer, fmt: []const u8, args: anytype) !void { +fn formatArgs(p: *Parser, w: *Io.Writer, fmt: []const u8, args: anytype) !void { var i: usize = 0; inline for (std.meta.fields(@TypeOf(args))) |arg_info| { const arg = @field(args, arg_info.name); @@ -476,13 +477,13 @@ fn formatArgs(p: *Parser, w: *std.Io.Writer, fmt: []const u8, args: anytype) !vo try w.writeAll(fmt[i..]); } -fn formatTokenId(w: *std.Io.Writer, fmt: []const u8, tok_id: Tree.Token.Id) !usize { +fn formatTokenId(w: *Io.Writer, fmt: []const u8, tok_id: Tree.Token.Id) !usize { const i = Diagnostics.templateIndex(w, fmt, "{tok_id}"); try w.writeAll(tok_id.symbol()); return i; } -fn formatQualType(p: *Parser, w: *std.Io.Writer, fmt: []const u8, qt: QualType) !usize { +fn formatQualType(p: *Parser, w: *Io.Writer, fmt: []const u8, qt: QualType) !usize { const i = Diagnostics.templateIndex(w, fmt, "{qt}"); try w.writeByte('\''); try qt.print(p.comp, w); @@ -501,7 +502,7 @@ fn formatQualType(p: *Parser, w: *std.Io.Writer, fmt: []const u8, qt: QualType) return i; } -fn formatResult(p: *Parser, w: *std.Io.Writer, fmt: []const u8, res: Result) !usize { +fn formatResult(p: *Parser, w: *Io.Writer, fmt: []const u8, res: Result) !usize { const i = Diagnostics.templateIndex(w, fmt, "{value}"); switch (res.val.opt_ref) { .none => try w.writeAll("(none)"), @@ -524,7 +525,7 @@ const Normalized = struct { return .{ .str = str }; } - pub fn format(ctx: Normalized, w: *std.Io.Writer, fmt: []const u8) !usize { + pub fn format(ctx: Normalized, w: *Io.Writer, fmt: []const u8) !usize { const i = Diagnostics.templateIndex(w, fmt, "{normalized}"); var it: std.unicode.Utf8Iterator = .{ .bytes = ctx.str, @@ -558,7 +559,7 @@ const Codepoint = struct { return .{ .codepoint = codepoint }; } - pub fn format(ctx: Codepoint, w: *std.Io.Writer, fmt: []const u8) !usize { + pub fn format(ctx: Codepoint, w: *Io.Writer, fmt: []const u8) !usize { const i = Diagnostics.templateIndex(w, fmt, "{codepoint}"); try w.print("{X:0>4}", .{ctx.codepoint}); return i; @@ -572,7 +573,7 @@ const Escaped = struct { return .{ .str = str }; } - pub fn format(ctx: Escaped, w: *std.Io.Writer, fmt: []const u8) !usize { + pub fn format(ctx: Escaped, w: *Io.Writer, fmt: []const u8) !usize { const i = Diagnostics.templateIndex(w, fmt, "{s}"); try std.zig.stringEscape(ctx.str, w); return i; @@ -1453,7 +1454,7 @@ fn decl(p: *Parser) Error!bool { return true; } -fn staticAssertMessage(p: *Parser, cond_node: Node.Index, maybe_message: ?Result, allocating: *std.Io.Writer.Allocating) !?[]const u8 { +fn staticAssertMessage(p: *Parser, cond_node: Node.Index, maybe_message: ?Result, allocating: *Io.Writer.Allocating) !?[]const u8 { const w = &allocating.writer; const cond = cond_node.get(&p.tree); @@ -1526,7 +1527,7 @@ fn staticAssert(p: *Parser) Error!bool { } else { if (!res.val.toBool(p.comp)) { var sf = std.heap.stackFallback(1024, gpa); - var allocating: std.Io.Writer.Allocating = .init(sf.get()); + var allocating: Io.Writer.Allocating = .init(sf.get()); defer allocating.deinit(); if (p.staticAssertMessage(res_node, str, &allocating) catch return error.OutOfMemory) |message| { @@ -9719,7 +9720,7 @@ fn primaryExpr(p: *Parser) Error!?Result { qt = some.qt; } else if (p.func.qt) |func_qt| { var sf = std.heap.stackFallback(1024, gpa); - var allocating: std.Io.Writer.Allocating = .init(sf.get()); + var allocating: Io.Writer.Allocating = .init(sf.get()); defer allocating.deinit(); func_qt.printNamed(p.tokSlice(p.func.name), p.comp, &allocating.writer) catch return error.OutOfMemory; @@ -10608,7 +10609,7 @@ test "Node locations" { const arena = arena_state.allocator(); var diagnostics: Diagnostics = .{ .output = .ignore }; - var comp = Compilation.init(std.testing.allocator, arena, std.testing.io, &diagnostics, std.fs.cwd()); + var comp = Compilation.init(std.testing.allocator, arena, std.testing.io, &diagnostics, Io.Dir.cwd()); defer comp.deinit(); const file = try comp.addSourceFromBuffer("file.c", diff --git a/lib/compiler/aro/aro/Preprocessor.zig b/lib/compiler/aro/aro/Preprocessor.zig index 6bd1206aff5e..6e36703df14a 100644 --- a/lib/compiler/aro/aro/Preprocessor.zig +++ b/lib/compiler/aro/aro/Preprocessor.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const mem = std.mem; const Allocator = mem.Allocator; const assert = std.debug.assert; @@ -1064,11 +1065,13 @@ fn fatalNotFound(pp: *Preprocessor, tok: TokenWithExpansionLocs, filename: []con fn verboseLog(pp: *Preprocessor, raw: RawToken, comptime fmt: []const u8, args: anytype) void { @branchHint(.cold); - const source = pp.comp.getSource(raw.source); + const comp = pp.comp; + const io = comp.io; + const source = comp.getSource(raw.source); const line_col = source.lineCol(.{ .id = raw.source, .line = raw.line, .byte_offset = raw.start }); var stderr_buf: [4096]u8 = undefined; - var stderr = std.fs.File.stderr().writer(&stderr_buf); + var stderr = Io.File.stderr().writer(io, &stderr_buf); const w = &stderr.interface; w.print("{s}:{d}:{d}: ", .{ source.path, line_col.line_no, line_col.col }) catch return; @@ -3899,7 +3902,7 @@ test "Preserve pragma tokens sometimes" { defer arena.deinit(); var diagnostics: Diagnostics = .{ .output = .ignore }; - var comp = Compilation.init(gpa, arena.allocator(), std.testing.io, &diagnostics, std.fs.cwd()); + var comp = Compilation.init(gpa, arena.allocator(), std.testing.io, &diagnostics, Io.Dir.cwd()); defer comp.deinit(); try comp.addDefaultPragmaHandlers(); @@ -3966,7 +3969,7 @@ test "destringify" { var arena: std.heap.ArenaAllocator = .init(gpa); defer arena.deinit(); var diagnostics: Diagnostics = .{ .output = .ignore }; - var comp = Compilation.init(gpa, arena.allocator(), std.testing.io, &diagnostics, std.fs.cwd()); + var comp = Compilation.init(gpa, arena.allocator(), std.testing.io, &diagnostics, Io.Dir.cwd()); defer comp.deinit(); var pp = Preprocessor.init(&comp, .default); defer pp.deinit(); @@ -4029,7 +4032,7 @@ test "Include guards" { const arena = arena_state.allocator(); var diagnostics: Diagnostics = .{ .output = .ignore }; - var comp = Compilation.init(gpa, arena, std.testing.io, &diagnostics, std.fs.cwd()); + var comp = Compilation.init(gpa, arena, std.testing.io, &diagnostics, Io.Dir.cwd()); defer comp.deinit(); var pp = Preprocessor.init(&comp, .default); defer pp.deinit(); diff --git a/lib/compiler/aro/aro/Tokenizer.zig b/lib/compiler/aro/aro/Tokenizer.zig index c497c5ce828e..198d49364afe 100644 --- a/lib/compiler/aro/aro/Tokenizer.zig +++ b/lib/compiler/aro/aro/Tokenizer.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; const Compilation = @import("Compilation.zig"); @@ -2326,7 +2327,7 @@ test "Tokenizer fuzz test" { fn testOne(_: @This(), input_bytes: []const u8) anyerror!void { var arena: std.heap.ArenaAllocator = .init(std.testing.allocator); defer arena.deinit(); - var comp = Compilation.init(std.testing.allocator, arena.allocator(), std.testing.io, undefined, std.fs.cwd()); + var comp = Compilation.init(std.testing.allocator, arena.allocator(), std.testing.io, undefined, Io.Dir.cwd()); defer comp.deinit(); const source = try comp.addSourceFromBuffer("fuzz.c", input_bytes); @@ -2351,7 +2352,7 @@ test "Tokenizer fuzz test" { fn expectTokensExtra(contents: []const u8, expected_tokens: []const Token.Id, langopts: ?LangOpts) !void { var arena: std.heap.ArenaAllocator = .init(std.testing.allocator); defer arena.deinit(); - var comp = Compilation.init(std.testing.allocator, arena.allocator(), std.testing.io, undefined, std.fs.cwd()); + var comp = Compilation.init(std.testing.allocator, arena.allocator(), std.testing.io, undefined, Io.Dir.cwd()); defer comp.deinit(); if (langopts) |provided| { comp.langopts = provided; diff --git a/lib/compiler/aro/aro/Toolchain.zig b/lib/compiler/aro/aro/Toolchain.zig index 326278cc3832..0aa9d76fc88a 100644 --- a/lib/compiler/aro/aro/Toolchain.zig +++ b/lib/compiler/aro/aro/Toolchain.zig @@ -497,10 +497,11 @@ pub fn addBuiltinIncludeDir(tc: *const Toolchain) !void { const comp = d.comp; const gpa = comp.gpa; const arena = comp.arena; + const io = comp.io; try d.includes.ensureUnusedCapacity(gpa, 1); if (d.resource_dir) |resource_dir| { const path = try std.fs.path.join(arena, &.{ resource_dir, "include" }); - comp.cwd.access(path, .{}) catch { + comp.cwd.access(io, path, .{}) catch { return d.fatal("Aro builtin headers not found in provided -resource-dir", .{}); }; d.includes.appendAssumeCapacity(.{ .kind = .system, .path = path }); @@ -508,10 +509,10 @@ pub fn addBuiltinIncludeDir(tc: *const Toolchain) !void { } var search_path = d.aro_name; while (std.fs.path.dirname(search_path)) |dirname| : (search_path = dirname) { - var base_dir = d.comp.cwd.openDir(dirname, .{}) catch continue; - defer base_dir.close(); + var base_dir = d.comp.cwd.openDir(io, dirname, .{}) catch continue; + defer base_dir.close(io); - base_dir.access("include/stddef.h", .{}) catch continue; + base_dir.access(io, "include/stddef.h", .{}) catch continue; const path = try std.fs.path.join(arena, &.{ dirname, "include" }); d.includes.appendAssumeCapacity(.{ .kind = .system, .path = path }); break; @@ -523,12 +524,14 @@ pub fn addBuiltinIncludeDir(tc: *const Toolchain) !void { /// Otherwise returns a slice of `buf`. If the file is larger than `buf` partial contents are returned pub fn readFile(tc: *const Toolchain, path: []const u8, buf: []u8) ?[]const u8 { const comp = tc.driver.comp; - return comp.cwd.adaptToNewApi().readFile(comp.io, path, buf) catch null; + const io = comp.io; + return comp.cwd.readFile(io, path, buf) catch null; } pub fn exists(tc: *const Toolchain, path: []const u8) bool { const comp = tc.driver.comp; - comp.cwd.adaptToNewApi().access(comp.io, path, .{}) catch return false; + const io = comp.io; + comp.cwd.access(io, path, .{}) catch return false; return true; } @@ -546,7 +549,8 @@ pub fn canExecute(tc: *const Toolchain, path: []const u8) bool { } const comp = tc.driver.comp; - comp.cwd.adaptToNewApi().access(comp.io, path, .{ .execute = true }) catch return false; + const io = comp.io; + comp.cwd.access(io, path, .{ .execute = true }) catch return false; // Todo: ensure path is not a directory return true; } diff --git a/lib/compiler/aro/aro/Value.zig b/lib/compiler/aro/aro/Value.zig index 25a2d1824f7e..14949ce03bbb 100644 --- a/lib/compiler/aro/aro/Value.zig +++ b/lib/compiler/aro/aro/Value.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; const BigIntConst = std.math.big.int.Const; const BigIntMutable = std.math.big.int.Mutable; @@ -80,7 +81,7 @@ test "minUnsignedBits" { defer arena_state.deinit(); const arena = arena_state.allocator(); - var comp = Compilation.init(std.testing.allocator, arena, std.testing.io, undefined, std.fs.cwd()); + var comp = Compilation.init(std.testing.allocator, arena, std.testing.io, undefined, Io.Dir.cwd()); defer comp.deinit(); const target_query = try std.Target.Query.parse(.{ .arch_os_abi = "x86_64-linux-gnu" }); comp.target = .fromZigTarget(try std.zig.system.resolveTargetQuery(std.testing.io, target_query)); @@ -119,7 +120,7 @@ test "minSignedBits" { defer arena_state.deinit(); const arena = arena_state.allocator(); - var comp = Compilation.init(std.testing.allocator, arena, std.testing.io, undefined, std.fs.cwd()); + var comp = Compilation.init(std.testing.allocator, arena, std.testing.io, undefined, Io.Dir.cwd()); defer comp.deinit(); const target_query = try std.Target.Query.parse(.{ .arch_os_abi = "x86_64-linux-gnu" }); comp.target = .fromZigTarget(try std.zig.system.resolveTargetQuery(std.testing.io, target_query)); @@ -1080,7 +1081,7 @@ const NestedPrint = union(enum) { }, }; -pub fn printPointer(offset: Value, base: []const u8, comp: *const Compilation, w: *std.Io.Writer) std.Io.Writer.Error!void { +pub fn printPointer(offset: Value, base: []const u8, comp: *const Compilation, w: *Io.Writer) Io.Writer.Error!void { try w.writeByte('&'); try w.writeAll(base); if (!offset.isZero(comp)) { @@ -1089,7 +1090,7 @@ pub fn printPointer(offset: Value, base: []const u8, comp: *const Compilation, w } } -pub fn print(v: Value, qt: QualType, comp: *const Compilation, w: *std.Io.Writer) std.Io.Writer.Error!?NestedPrint { +pub fn print(v: Value, qt: QualType, comp: *const Compilation, w: *Io.Writer) Io.Writer.Error!?NestedPrint { if (qt.is(comp, .bool)) { try w.writeAll(if (v.isZero(comp)) "false" else "true"); return null; @@ -1116,7 +1117,7 @@ pub fn print(v: Value, qt: QualType, comp: *const Compilation, w: *std.Io.Writer return null; } -pub fn printString(bytes: []const u8, qt: QualType, comp: *const Compilation, w: *std.Io.Writer) std.Io.Writer.Error!void { +pub fn printString(bytes: []const u8, qt: QualType, comp: *const Compilation, w: *Io.Writer) Io.Writer.Error!void { const size: Compilation.CharUnitSize = @enumFromInt(qt.childType(comp).sizeof(comp)); const without_null = bytes[0 .. bytes.len - @intFromEnum(size)]; try w.writeByte('"'); diff --git a/lib/compiler/aro/assembly_backend/x86_64.zig b/lib/compiler/aro/assembly_backend/x86_64.zig index ff106e9d8bde..247c5bf186aa 100644 --- a/lib/compiler/aro/assembly_backend/x86_64.zig +++ b/lib/compiler/aro/assembly_backend/x86_64.zig @@ -58,7 +58,7 @@ fn serializeFloat(comptime T: type, value: T, w: *std.Io.Writer) !void { }, else => { const size = @bitSizeOf(T); - const storage_unit = std.meta.intToEnum(StorageUnit, size) catch unreachable; + const storage_unit = std.enums.fromInt(StorageUnit, size).?; const IntTy = @Int(.unsigned, size); const int_val: IntTy = @bitCast(value); return serializeInt(int_val, storage_unit, w); @@ -95,7 +95,7 @@ fn emitSingleValue(c: *AsmCodeGen, qt: QualType, node: Node.Index) !void { if (!scalar_kind.isReal()) { return c.todo("Codegen _Complex values", node.tok(c.tree)); } else if (scalar_kind.isInt()) { - const storage_unit = std.meta.intToEnum(StorageUnit, bit_size) catch return c.todo("Codegen _BitInt values", node.tok(c.tree)); + const storage_unit = std.enums.fromInt(StorageUnit, bit_size) orelse return c.todo("Codegen _BitInt values", node.tok(c.tree)); try c.data.print(" .{s} ", .{@tagName(storage_unit)}); _ = try value.print(qt, c.comp, c.data); try c.data.writeByte('\n'); diff --git a/lib/compiler/aro/backend/Assembly.zig b/lib/compiler/aro/backend/Assembly.zig index d0d14bdd77d1..4ec4860b514f 100644 --- a/lib/compiler/aro/backend/Assembly.zig +++ b/lib/compiler/aro/backend/Assembly.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const Allocator = std.mem.Allocator; data: []const u8, @@ -11,8 +12,8 @@ pub fn deinit(self: *const Assembly, gpa: Allocator) void { gpa.free(self.text); } -pub fn writeToFile(self: Assembly, file: std.fs.File) !void { - var file_writer = file.writer(&.{}); +pub fn writeToFile(self: Assembly, io: Io, file: Io.File) !void { + var file_writer = file.writer(io, &.{}); var buffers = [_][]const u8{ self.data, self.text }; try file_writer.interface.writeSplatAll(&buffers, 1); diff --git a/lib/compiler/aro/main.zig b/lib/compiler/aro/main.zig index f4fd7e383917..dcc07eaca64c 100644 --- a/lib/compiler/aro/main.zig +++ b/lib/compiler/aro/main.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const Allocator = mem.Allocator; const mem = std.mem; const process = std.process; @@ -17,9 +18,9 @@ var debug_allocator: std.heap.DebugAllocator(.{ .canary = @truncate(0xc647026dc6875134), }) = .{}; -pub fn main() u8 { +pub fn main(init: std.process.Init.Minimal) u8 { const gpa = if (@import("builtin").link_libc) - std.heap.raw_c_allocator + std.heap.c_allocator else debug_allocator.allocator(); defer if (!@import("builtin").link_libc) { @@ -30,19 +31,19 @@ pub fn main() u8 { defer arena_instance.deinit(); const arena = arena_instance.allocator(); - var threaded: std.Io.Threaded = .init(gpa); + var threaded: std.Io.Threaded = .init(gpa, .{}); defer threaded.deinit(); const io = threaded.io(); const fast_exit = @import("builtin").mode != .Debug; - const args = process.argsAlloc(arena) catch { + const args = init.args.toSlice(arena) catch { std.debug.print("out of memory\n", .{}); if (fast_exit) process.exit(1); return 1; }; - const aro_name = std.fs.selfExePathAlloc(gpa) catch { + const aro_name = process.executablePathAlloc(io, gpa) catch { std.debug.print("unable to find Aro executable path\n", .{}); if (fast_exit) process.exit(1); return 1; @@ -50,7 +51,7 @@ pub fn main() u8 { defer gpa.free(aro_name); var stderr_buf: [1024]u8 = undefined; - var stderr = std.fs.File.stderr().writer(&stderr_buf); + var stderr = Io.File.stderr().writer(&stderr_buf); var diagnostics: Diagnostics = .{ .output = .{ .to_writer = .{ .color = .detect(stderr.file), @@ -58,7 +59,7 @@ pub fn main() u8 { } }, }; - var comp = Compilation.initDefault(gpa, arena, io, &diagnostics, std.fs.cwd()) catch |er| switch (er) { + var comp = Compilation.initDefault(gpa, arena, io, &diagnostics, Io.Dir.cwd()) catch |er| switch (er) { error.OutOfMemory => { std.debug.print("out of memory\n", .{}); if (fast_exit) process.exit(1); diff --git a/lib/compiler/build_runner.zig b/lib/compiler/build_runner.zig index 272b1b8077f3..7efee4bac4c7 100644 --- a/lib/compiler/build_runner.zig +++ b/lib/compiler/build_runner.zig @@ -7,14 +7,13 @@ const assert = std.debug.assert; const fmt = std.fmt; const mem = std.mem; const process = std.process; -const File = std.fs.File; +const File = std.Io.File; const Step = std.Build.Step; const Watch = std.Build.Watch; const WebServer = std.Build.WebServer; const Allocator = std.mem.Allocator; const fatal = std.process.fatal; const Writer = std.Io.Writer; -const tty = std.Io.tty; pub const root = @import("@build"); pub const dependencies = @import("@dependencies"); @@ -22,10 +21,9 @@ pub const dependencies = @import("@dependencies"); pub const std_options: std.Options = .{ .side_channels_mitigations = .none, .http_disable_tls = true, - .crypto_fork_safety = false, }; -pub fn main() !void { +pub fn main(init: process.Init.Minimal) !void { // The build runner is often short-lived, but thanks to `--watch` and `--webui`, that's not // always the case. So, we do need a true gpa for some things. var debug_gpa_state: std.heap.DebugAllocator(.{}) = .init; @@ -38,9 +36,12 @@ pub fn main() !void { var thread_safe_arena: std.heap.ThreadSafeAllocator = .{ .child_allocator = single_threaded_arena.allocator() }; const arena = thread_safe_arena.allocator(); - const args = try process.argsAlloc(arena); + const args = try init.args.toSlice(arena); - var threaded: std.Io.Threaded = .init(gpa); + var threaded: std.Io.Threaded = .init(gpa, .{ + .environ = init.environ, + .argv0 = .init(init.args), + }); defer threaded.deinit(); const io = threaded.io(); @@ -53,24 +54,26 @@ pub fn main() !void { const cache_root = nextArg(args, &arg_idx) orelse fatal("missing cache root directory path", .{}); const global_cache_root = nextArg(args, &arg_idx) orelse fatal("missing global cache root directory path", .{}); + const cwd: Io.Dir = .cwd(); + const zig_lib_directory: std.Build.Cache.Directory = .{ .path = zig_lib_dir, - .handle = try std.fs.cwd().openDir(zig_lib_dir, .{}), + .handle = try cwd.openDir(io, zig_lib_dir, .{}), }; const build_root_directory: std.Build.Cache.Directory = .{ .path = build_root, - .handle = try std.fs.cwd().openDir(build_root, .{}), + .handle = try cwd.openDir(io, build_root, .{}), }; const local_cache_directory: std.Build.Cache.Directory = .{ .path = cache_root, - .handle = try std.fs.cwd().makeOpenPath(cache_root, .{}), + .handle = try cwd.createDirPathOpen(io, cache_root, .{}), }; const global_cache_directory: std.Build.Cache.Directory = .{ .path = global_cache_root, - .handle = try std.fs.cwd().makeOpenPath(global_cache_root, .{}), + .handle = try cwd.createDirPathOpen(io, global_cache_root, .{}), }; var graph: std.Build.Graph = .{ @@ -78,11 +81,12 @@ pub fn main() !void { .arena = arena, .cache = .{ .io = io, - .gpa = arena, - .manifest_dir = try local_cache_directory.handle.makeOpenPath("h", .{}), + .gpa = gpa, + .manifest_dir = try local_cache_directory.handle.createDirPathOpen(io, "h", .{}), + .cwd = try process.getCwdAlloc(single_threaded_arena.allocator()), }, .zig_exe = zig_exe, - .env_map = try process.getEnvMap(arena), + .environ_map = try init.environ.createMap(arena), .global_cache_root = global_cache_directory, .zig_lib_directory = zig_lib_directory, .host = .{ @@ -92,7 +96,7 @@ pub fn main() !void { .time_report = false, }; - graph.cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() }); + graph.cache.addPrefix(.{ .path = null, .handle = cwd }); graph.cache.addPrefix(build_root_directory); graph.cache.addPrefix(local_cache_directory); graph.cache.addPrefix(global_cache_directory); @@ -125,13 +129,13 @@ pub fn main() !void { var debounce_interval_ms: u16 = 50; var webui_listen: ?Io.net.IpAddress = null; - if (try std.zig.EnvVar.ZIG_BUILD_ERROR_STYLE.get(arena)) |str| { + if (std.zig.EnvVar.ZIG_BUILD_ERROR_STYLE.get(&graph.environ_map)) |str| { if (std.meta.stringToEnum(ErrorStyle, str)) |style| { error_style = style; } } - if (try std.zig.EnvVar.ZIG_BUILD_MULTILINE_ERRORS.get(arena)) |str| { + if (std.zig.EnvVar.ZIG_BUILD_MULTILINE_ERRORS.get(&graph.environ_map)) |str| { if (std.meta.stringToEnum(MultilineErrors, str)) |style| { multiline_errors = style; } @@ -285,8 +289,8 @@ pub fn main() !void { const next_arg = nextArg(args, &arg_idx) orelse fatalWithHint("expected u16 after '{s}'", .{arg}); debounce_interval_ms = std.fmt.parseUnsigned(u16, next_arg, 0) catch |err| { - fatal("unable to parse debounce interval '{s}' as unsigned 16-bit integer: {s}\n", .{ - next_arg, @errorName(err), + fatal("unable to parse debounce interval '{s}' as unsigned 16-bit integer: {t}\n", .{ + next_arg, err, }); }; } else if (mem.eql(u8, arg, "--webui")) { @@ -428,14 +432,21 @@ pub fn main() !void { } } + const NO_COLOR = std.zig.EnvVar.NO_COLOR.isSet(&graph.environ_map); + const CLICOLOR_FORCE = std.zig.EnvVar.CLICOLOR_FORCE.isSet(&graph.environ_map); + + graph.stderr_mode = switch (color) { + .auto => try .detect(io, .stderr(), NO_COLOR, CLICOLOR_FORCE), + .on => .escape_codes, + .off => .no_color, + }; + if (webui_listen != null) { if (watch) fatal("using '--webui' and '--watch' together is not yet supported; consider omitting '--watch' in favour of the web UI \"Rebuild\" button", .{}); if (builtin.single_threaded) fatal("'--webui' is not yet supported on single-threaded hosts", .{}); } - const ttyconf = color.detectTtyConf(); - - const main_progress_node = std.Progress.start(.{ + const main_progress_node = std.Progress.start(io, .{ .disable_printing = (color == .off), }); defer main_progress_node.end(); @@ -457,7 +468,7 @@ pub fn main() !void { } const s = std.fs.path.sep_str; const tmp_sub_path = "tmp" ++ s ++ (output_tmp_nonce orelse fatal("missing -Z arg", .{})); - local_cache_directory.handle.writeFile(.{ + local_cache_directory.handle.writeFile(io, .{ .sub_path = tmp_sub_path, .data = buffer.items, .flags = .{ .exclusive = true }, @@ -476,14 +487,14 @@ pub fn main() !void { validateSystemLibraryOptions(builder); if (help_menu) { - var w = initStdoutWriter(); + var w = initStdoutWriter(io); printUsage(builder, w) catch return stdout_writer_allocation.err.?; w.flush() catch return stdout_writer_allocation.err.?; return; } if (steps_menu) { - var w = initStdoutWriter(); + var w = initStdoutWriter(io); printSteps(builder, w) catch return stdout_writer_allocation.err.?; w.flush() catch return stdout_writer_allocation.err.?; return; @@ -492,7 +503,7 @@ pub fn main() !void { var run: Run = .{ .gpa = gpa, - .max_rss = max_rss, + .available_rss = max_rss, .max_rss_is_default = false, .max_rss_mutex = .init, .skip_oom_steps = skip_oom_steps, @@ -503,29 +514,26 @@ pub fn main() !void { .memory_blocked_steps = .empty, .step_stack = .empty, - .claimed_rss = 0, .error_style = error_style, .multiline_errors = multiline_errors, .summary = summary orelse if (watch or webui_listen != null) .line else .failures, - - .ttyconf = ttyconf, }; defer { run.memory_blocked_steps.deinit(gpa); run.step_stack.deinit(gpa); } - if (run.max_rss == 0) { - run.max_rss = process.totalSystemMemory() catch std.math.maxInt(u64); + if (run.available_rss == 0) { + run.available_rss = process.totalSystemMemory() catch std.math.maxInt(u64); run.max_rss_is_default = true; } prepare(arena, builder, targets.items, &run, graph.random_seed) catch |err| switch (err) { error.DependencyLoopDetected => { - // Perhaps in the future there could be an Advanced Options flag such as - // --debug-build-runner-leaks which would make this code return instead of - // calling exit. - std.debug.lockStdErr(); + // Perhaps in the future there could be an Advanced Options flag + // such as --debug-build-runner-leaks which would make this code + // return instead of calling exit. + _ = io.lockStderr(&.{}, graph.stderr_mode) catch {}; process.exit(1); }, else => |e| return e, @@ -534,7 +542,7 @@ pub fn main() !void { var w: Watch = w: { if (!watch) break :w undefined; if (!Watch.have_impl) fatal("--watch not yet implemented for {t}", .{builtin.os.tag}); - break :w try .init(); + break :w try .init(graph.cache.cwd); }; const now = Io.Clock.Timestamp.now(io, .awake) catch |err| fatal("failed to collect timestamp: {t}", .{err}); @@ -543,7 +551,6 @@ pub fn main() !void { if (builtin.single_threaded) unreachable; // `fatal` above break :ws .init(.{ .gpa = gpa, - .ttyconf = ttyconf, .graph = &graph, .all_steps = run.step_stack.keys(), .root_prog_node = main_progress_node, @@ -558,9 +565,9 @@ pub fn main() !void { } rebuild: while (true) : (if (run.error_style.clearOnUpdate()) { - const bw, _ = std.debug.lockStderrWriter(&stdio_buffer_allocation); - defer std.debug.unlockStderrWriter(); - try bw.writeAll("\x1B[2J\x1B[3J\x1B[H"); + const stderr = try io.lockStderr(&stdio_buffer_allocation, graph.stderr_mode); + defer io.unlockStderr(); + try stderr.file_writer.interface.writeAll("\x1B[2J\x1B[3J\x1B[H"); }) { if (run.web_server) |*ws| ws.startBuild(); @@ -587,6 +594,7 @@ pub fn main() !void { .rebuild => { for (run.step_stack.keys()) |step| { step.state = .precheck_done; + step.pending_deps = @intCast(step.dependencies.items.len); step.reset(gpa); } continue :rebuild; @@ -629,7 +637,7 @@ pub fn main() !void { fn markFailedStepsDirty(gpa: Allocator, all_steps: []const *Step) void { for (all_steps) |step| switch (step.state) { - .dependency_failure, .failure, .skipped => step.recursiveReset(gpa), + .dependency_failure, .failure, .skipped => _ = step.invalidateResult(gpa), else => continue, }; // Now that all dirty steps have been found, the remaining steps that @@ -650,7 +658,8 @@ fn countSubProcesses(all_steps: []const *Step) usize { const Run = struct { gpa: Allocator, - max_rss: u64, + + available_rss: usize, max_rss_is_default: bool, max_rss_mutex: Io.Mutex, skip_oom_steps: bool, @@ -661,11 +670,7 @@ const Run = struct { memory_blocked_steps: std.ArrayList(*Step), /// Allocated into `gpa`. step_stack: std.AutoArrayHashMapUnmanaged(*Step, void), - /// Similar to the `tty.Config` returned by `std.debug.lockStderrWriter`, - /// but also respects the '--color' flag. - ttyconf: tty.Config, - claimed_rss: usize, error_style: ErrorStyle, multiline_errors: MultilineErrors, summary: Summary, @@ -710,12 +715,15 @@ fn prepare( var any_problems = false; for (step_stack.keys()) |s| { if (s.max_rss == 0) continue; - if (s.max_rss > run.max_rss) { + if (s.max_rss > run.available_rss) { if (run.skip_oom_steps) { s.state = .skipped_oom; + for (s.dependants.items) |dependant| { + dependant.pending_deps -= 1; + } } else { std.debug.print("{s}{s}: this step declares an upper bound of {d} bytes of memory, exceeding the available {d} bytes of memory\n", .{ - s.owner.dep_prefix, s.name, s.max_rss, run.max_rss, + s.owner.dep_prefix, s.name, s.max_rss, run.available_rss, }); any_problems = true; } @@ -737,26 +745,32 @@ fn runStepNames( fuzz: ?std.Build.Fuzz.Mode, ) !void { const gpa = run.gpa; - const io = b.graph.io; + const graph = b.graph; + const io = graph.io; const step_stack = &run.step_stack; { + // Collect the initial set of tasks (those with no outstanding dependencies) into a buffer, + // then spawn them. The buffer is so that we don't race with `makeStep` and end up thinking + // a step is initial when it actually became ready due to an earlier initial step. + var initial_set: std.ArrayList(*Step) = .empty; + defer initial_set.deinit(gpa); + try initial_set.ensureUnusedCapacity(gpa, step_stack.count()); + for (step_stack.keys()) |s| { + if (s.state == .precheck_done and s.pending_deps == 0) { + initial_set.appendAssumeCapacity(s); + } + } + const step_prog = parent_prog_node.start("steps", step_stack.count()); defer step_prog.end(); var group: Io.Group = .init; - defer group.wait(io); - - // Here we spawn the initial set of tasks with a nice heuristic - - // dependency order. Each worker when it finishes a step will then - // check whether it should run any dependants. - const steps_slice = step_stack.keys(); - for (0..steps_slice.len) |i| { - const step = steps_slice[steps_slice.len - i - 1]; - if (step.state == .skipped_oom) continue; - - group.async(io, workerMakeOneStep, .{ &group, b, step, step_prog, run }); - } + defer group.cancel(io); + // Start working on all of the initial steps... + for (initial_set.items) |s| try stepReady(&group, b, s, step_prog, run); + // ...and `makeStep` will trigger every other step when their last dependency finishes. + try group.await(io); } assert(run.memory_blocked_steps.items.len == 0); @@ -775,6 +789,9 @@ fn runStepNames( var pending_count: usize = 0; var total_compile_errors: usize = 0; + var cleanup_task = io.async(cleanTmpFiles, .{ io, step_stack.keys() }); + defer cleanup_task.await(io); + for (step_stack.keys()) |s| { test_pass_count += s.test_results.passCount(); test_skip_count += s.test_results.skip_count; @@ -787,17 +804,7 @@ fn runStepNames( switch (s.state) { .precheck_unstarted => unreachable, .precheck_started => unreachable, - .running => unreachable, - .precheck_done => { - // precheck_done is equivalent to dependency_failure in the case of - // transitive dependencies. For example: - // A -> B -> C (failure) - // B will be marked as dependency_failure, while A may never be queued, and thus - // remain in the initial state of precheck_done. - s.state = .dependency_failure; - if (run.web_server) |*ws| ws.updateStepStatus(s, .failure); - pending_count += 1; - }, + .precheck_done => unreachable, .dependency_failure => pending_count += 1, .success => success_count += 1, .skipped, .skipped_oom => skipped_count += 1, @@ -817,12 +824,12 @@ fn runStepNames( // * Memory-mapping to share data between the fuzzer and build runner. // * COFF/PE support added to `std.debug.Info` (it needs a batching API for resolving // many addresses to source locations). - .windows => fatal("--fuzz not yet implemented for {s}", .{@tagName(builtin.os.tag)}), + .windows => fatal("--fuzz not yet implemented for {t}", .{builtin.os.tag}), else => {}, } if (@bitSizeOf(usize) != 64) { // Current implementation depends on posix.mmap()'s second parameter, `length: usize`, - // being compatible with `std.fs.getEndPos() u64`'s return value. This is not the case + // being compatible with file system's u64 return value. This is not the case // on 32-bit platforms. // Affects or affected by issues #5185, #22523, and #22464. fatal("--fuzz not yet implemented on {d}-bit platforms", .{@bitSizeOf(usize)}); @@ -837,15 +844,14 @@ fn runStepNames( var f = std.Build.Fuzz.init( gpa, io, - run.ttyconf, step_stack.keys(), parent_prog_node, mode, - ) catch |err| fatal("failed to start fuzzer: {s}", .{@errorName(err)}); + ) catch |err| fatal("failed to start fuzzer: {t}", .{err}); defer f.deinit(); f.start(); - f.waitAndPrintReport(); + try f.waitAndPrintReport(); } // Every test has a state @@ -864,18 +870,19 @@ fn runStepNames( .none => break :summary, } - const w, _ = std.debug.lockStderrWriter(&stdio_buffer_allocation); - defer std.debug.unlockStderrWriter(); - const ttyconf = run.ttyconf; + const stderr = try io.lockStderr(&stdio_buffer_allocation, graph.stderr_mode); + defer io.unlockStderr(); + const t = stderr.terminal(); + const w = &stderr.file_writer.interface; const total_count = success_count + failure_count + pending_count + skipped_count; - ttyconf.setColor(w, .cyan) catch {}; - ttyconf.setColor(w, .bold) catch {}; + t.setColor(.cyan) catch {}; + t.setColor(.bold) catch {}; w.writeAll("Build Summary: ") catch {}; - ttyconf.setColor(w, .reset) catch {}; + t.setColor(.reset) catch {}; w.print("{d}/{d} steps succeeded", .{ success_count, total_count }) catch {}; { - ttyconf.setColor(w, .dim) catch {}; + t.setColor(.dim) catch {}; var first = true; if (skipped_count > 0) { w.print("{s}{d} skipped", .{ if (first) " (" else ", ", skipped_count }) catch {}; @@ -886,12 +893,12 @@ fn runStepNames( first = false; } if (!first) w.writeByte(')') catch {}; - ttyconf.setColor(w, .reset) catch {}; + t.setColor(.reset) catch {}; } if (test_count > 0) { w.print("; {d}/{d} tests passed", .{ test_pass_count, test_count }) catch {}; - ttyconf.setColor(w, .dim) catch {}; + t.setColor(.dim) catch {}; var first = true; if (test_skip_count > 0) { w.print("{s}{d} skipped", .{ if (first) " (" else ", ", test_skip_count }) catch {}; @@ -910,7 +917,7 @@ fn runStepNames( first = false; } if (!first) w.writeByte(')') catch {}; - ttyconf.setColor(w, .reset) catch {}; + t.setColor(.reset) catch {}; } w.writeAll("\n") catch {}; @@ -924,7 +931,7 @@ fn runStepNames( var print_node: PrintNode = .{ .parent = null }; if (step_names.len == 0) { print_node.last = true; - printTreeStep(b, b.default_step, run, w, ttyconf, &print_node, &step_stack_copy) catch {}; + printTreeStep(b, b.default_step, run, t, &print_node, &step_stack_copy) catch {}; } else { const last_index = if (run.summary == .all) b.top_level_steps.count() else blk: { var i: usize = step_names.len; @@ -943,7 +950,7 @@ fn runStepNames( for (step_names, 0..) |step_name, i| { const tls = b.top_level_steps.get(step_name).?; print_node.last = i + 1 == last_index; - printTreeStep(b, &tls.step, run, w, ttyconf, &print_node, &step_stack_copy) catch {}; + printTreeStep(b, &tls.step, run, t, &print_node, &step_stack_copy) catch {}; } } w.writeByte('\n') catch {}; @@ -960,7 +967,7 @@ fn runStepNames( if (run.error_style.verboseContext()) break :code 1; // failure; print build command break :code 2; // failure; do not print build command }; - std.debug.lockStdErr(); + _ = io.lockStderr(&.{}, graph.stderr_mode) catch {}; process.exit(code); } @@ -969,173 +976,165 @@ const PrintNode = struct { last: bool = false, }; -fn printPrefix(node: *PrintNode, stderr: *Writer, ttyconf: tty.Config) !void { +fn printPrefix(node: *PrintNode, stderr: Io.Terminal) !void { const parent = node.parent orelse return; + const writer = stderr.writer; if (parent.parent == null) return; - try printPrefix(parent, stderr, ttyconf); + try printPrefix(parent, stderr); if (parent.last) { - try stderr.writeAll(" "); + try writer.writeAll(" "); } else { - try stderr.writeAll(switch (ttyconf) { - .no_color, .windows_api => "| ", + try writer.writeAll(switch (stderr.mode) { .escape_codes => "\x1B\x28\x30\x78\x1B\x28\x42 ", // │ + else => "| ", }); } } -fn printChildNodePrefix(stderr: *Writer, ttyconf: tty.Config) !void { - try stderr.writeAll(switch (ttyconf) { - .no_color, .windows_api => "+- ", +fn printChildNodePrefix(stderr: Io.Terminal) !void { + try stderr.writer.writeAll(switch (stderr.mode) { .escape_codes => "\x1B\x28\x30\x6d\x71\x1B\x28\x42 ", // └─ + else => "+- ", }); } -fn printStepStatus( - s: *Step, - stderr: *Writer, - ttyconf: tty.Config, - run: *const Run, -) !void { +fn printStepStatus(s: *Step, stderr: Io.Terminal, run: *const Run) !void { + const writer = stderr.writer; switch (s.state) { .precheck_unstarted => unreachable, .precheck_started => unreachable, .precheck_done => unreachable, - .running => unreachable, .dependency_failure => { - try ttyconf.setColor(stderr, .dim); - try stderr.writeAll(" transitive failure\n"); - try ttyconf.setColor(stderr, .reset); + try stderr.setColor(.dim); + try writer.writeAll(" transitive failure\n"); + try stderr.setColor(.reset); }, .success => { - try ttyconf.setColor(stderr, .green); + try stderr.setColor(.green); if (s.result_cached) { - try stderr.writeAll(" cached"); + try writer.writeAll(" cached"); } else if (s.test_results.test_count > 0) { const pass_count = s.test_results.passCount(); assert(s.test_results.test_count == pass_count + s.test_results.skip_count); - try stderr.print(" {d} pass", .{pass_count}); + try writer.print(" {d} pass", .{pass_count}); if (s.test_results.skip_count > 0) { - try ttyconf.setColor(stderr, .reset); - try stderr.writeAll(", "); - try ttyconf.setColor(stderr, .yellow); - try stderr.print("{d} skip", .{s.test_results.skip_count}); + try stderr.setColor(.reset); + try writer.writeAll(", "); + try stderr.setColor(.yellow); + try writer.print("{d} skip", .{s.test_results.skip_count}); } - try ttyconf.setColor(stderr, .reset); - try stderr.print(" ({d} total)", .{s.test_results.test_count}); + try stderr.setColor(.reset); + try writer.print(" ({d} total)", .{s.test_results.test_count}); } else { - try stderr.writeAll(" success"); + try writer.writeAll(" success"); } - try ttyconf.setColor(stderr, .reset); + try stderr.setColor(.reset); if (s.result_duration_ns) |ns| { - try ttyconf.setColor(stderr, .dim); + try stderr.setColor(.dim); if (ns >= std.time.ns_per_min) { - try stderr.print(" {d}m", .{ns / std.time.ns_per_min}); + try writer.print(" {d}m", .{ns / std.time.ns_per_min}); } else if (ns >= std.time.ns_per_s) { - try stderr.print(" {d}s", .{ns / std.time.ns_per_s}); + try writer.print(" {d}s", .{ns / std.time.ns_per_s}); } else if (ns >= std.time.ns_per_ms) { - try stderr.print(" {d}ms", .{ns / std.time.ns_per_ms}); + try writer.print(" {d}ms", .{ns / std.time.ns_per_ms}); } else if (ns >= std.time.ns_per_us) { - try stderr.print(" {d}us", .{ns / std.time.ns_per_us}); + try writer.print(" {d}us", .{ns / std.time.ns_per_us}); } else { - try stderr.print(" {d}ns", .{ns}); + try writer.print(" {d}ns", .{ns}); } - try ttyconf.setColor(stderr, .reset); + try stderr.setColor(.reset); } if (s.result_peak_rss != 0) { const rss = s.result_peak_rss; - try ttyconf.setColor(stderr, .dim); + try stderr.setColor(.dim); if (rss >= 1000_000_000) { - try stderr.print(" MaxRSS:{d}G", .{rss / 1000_000_000}); + try writer.print(" MaxRSS:{d}G", .{rss / 1000_000_000}); } else if (rss >= 1000_000) { - try stderr.print(" MaxRSS:{d}M", .{rss / 1000_000}); + try writer.print(" MaxRSS:{d}M", .{rss / 1000_000}); } else if (rss >= 1000) { - try stderr.print(" MaxRSS:{d}K", .{rss / 1000}); + try writer.print(" MaxRSS:{d}K", .{rss / 1000}); } else { - try stderr.print(" MaxRSS:{d}B", .{rss}); + try writer.print(" MaxRSS:{d}B", .{rss}); } - try ttyconf.setColor(stderr, .reset); + try stderr.setColor(.reset); } - try stderr.writeAll("\n"); + try writer.writeAll("\n"); }, - .skipped, .skipped_oom => |skip| { - try ttyconf.setColor(stderr, .yellow); - try stderr.writeAll(" skipped"); - if (skip == .skipped_oom) { - try stderr.writeAll(" (not enough memory)"); - try ttyconf.setColor(stderr, .dim); - try stderr.print(" upper bound of {d} exceeded runner limit ({d})", .{ s.max_rss, run.max_rss }); - try ttyconf.setColor(stderr, .yellow); - } - try stderr.writeAll("\n"); - try ttyconf.setColor(stderr, .reset); + .skipped => { + try stderr.setColor(.yellow); + try writer.writeAll(" skipped\n"); + try stderr.setColor(.reset); + }, + .skipped_oom => { + try stderr.setColor(.yellow); + try writer.writeAll(" skipped (not enough memory)"); + try stderr.setColor(.dim); + try writer.print(" upper bound of {d} exceeded runner limit ({d})\n", .{ s.max_rss, run.available_rss }); + try stderr.setColor(.reset); }, .failure => { - try printStepFailure(s, stderr, ttyconf, false); - try ttyconf.setColor(stderr, .reset); + try printStepFailure(s, stderr, false); + try stderr.setColor(.reset); }, } } -fn printStepFailure( - s: *Step, - stderr: *Writer, - ttyconf: tty.Config, - dim: bool, -) !void { +fn printStepFailure(s: *Step, stderr: Io.Terminal, dim: bool) !void { + const w = stderr.writer; if (s.result_error_bundle.errorMessageCount() > 0) { - try ttyconf.setColor(stderr, .red); - try stderr.print(" {d} errors\n", .{ + try stderr.setColor(.red); + try w.print(" {d} errors\n", .{ s.result_error_bundle.errorMessageCount(), }); } else if (!s.test_results.isSuccess()) { // These first values include all of the test "statuses". Every test is either passsed, // skipped, failed, crashed, or timed out. - try ttyconf.setColor(stderr, .green); - try stderr.print(" {d} pass", .{s.test_results.passCount()}); - try ttyconf.setColor(stderr, .reset); - if (dim) try ttyconf.setColor(stderr, .dim); + try stderr.setColor(.green); + try w.print(" {d} pass", .{s.test_results.passCount()}); + try stderr.setColor(.reset); + if (dim) try stderr.setColor(.dim); if (s.test_results.skip_count > 0) { - try stderr.writeAll(", "); - try ttyconf.setColor(stderr, .yellow); - try stderr.print("{d} skip", .{s.test_results.skip_count}); - try ttyconf.setColor(stderr, .reset); - if (dim) try ttyconf.setColor(stderr, .dim); + try w.writeAll(", "); + try stderr.setColor(.yellow); + try w.print("{d} skip", .{s.test_results.skip_count}); + try stderr.setColor(.reset); + if (dim) try stderr.setColor(.dim); } if (s.test_results.fail_count > 0) { - try stderr.writeAll(", "); - try ttyconf.setColor(stderr, .red); - try stderr.print("{d} fail", .{s.test_results.fail_count}); - try ttyconf.setColor(stderr, .reset); - if (dim) try ttyconf.setColor(stderr, .dim); + try w.writeAll(", "); + try stderr.setColor(.red); + try w.print("{d} fail", .{s.test_results.fail_count}); + try stderr.setColor(.reset); + if (dim) try stderr.setColor(.dim); } if (s.test_results.crash_count > 0) { - try stderr.writeAll(", "); - try ttyconf.setColor(stderr, .red); - try stderr.print("{d} crash", .{s.test_results.crash_count}); - try ttyconf.setColor(stderr, .reset); - if (dim) try ttyconf.setColor(stderr, .dim); + try w.writeAll(", "); + try stderr.setColor(.red); + try w.print("{d} crash", .{s.test_results.crash_count}); + try stderr.setColor(.reset); + if (dim) try stderr.setColor(.dim); } if (s.test_results.timeout_count > 0) { - try stderr.writeAll(", "); - try ttyconf.setColor(stderr, .red); - try stderr.print("{d} timeout", .{s.test_results.timeout_count}); - try ttyconf.setColor(stderr, .reset); - if (dim) try ttyconf.setColor(stderr, .dim); + try w.writeAll(", "); + try stderr.setColor(.red); + try w.print("{d} timeout", .{s.test_results.timeout_count}); + try stderr.setColor(.reset); + if (dim) try stderr.setColor(.dim); } - try stderr.print(" ({d} total)", .{s.test_results.test_count}); + try w.print(" ({d} total)", .{s.test_results.test_count}); // Memory leaks are intentionally written after the total, because is isn't a test *status*, // but just a flag that any tests -- even passed ones -- can have. We also use a different // separator, so it looks like: // 2 pass, 1 skip, 2 fail (5 total); 2 leaks if (s.test_results.leak_count > 0) { - try stderr.writeAll("; "); - try ttyconf.setColor(stderr, .red); - try stderr.print("{d} leaks", .{s.test_results.leak_count}); - try ttyconf.setColor(stderr, .reset); - if (dim) try ttyconf.setColor(stderr, .dim); + try w.writeAll("; "); + try stderr.setColor(.red); + try w.print("{d} leaks", .{s.test_results.leak_count}); + try stderr.setColor(.reset); + if (dim) try stderr.setColor(.dim); } // It's usually not helpful to know how many error logs there were because they tend to @@ -1148,21 +1147,21 @@ fn printStepFailure( break :show alt_results.isSuccess(); }; if (show_err_logs) { - try stderr.writeAll("; "); - try ttyconf.setColor(stderr, .red); - try stderr.print("{d} error logs", .{s.test_results.log_err_count}); - try ttyconf.setColor(stderr, .reset); - if (dim) try ttyconf.setColor(stderr, .dim); + try w.writeAll("; "); + try stderr.setColor(.red); + try w.print("{d} error logs", .{s.test_results.log_err_count}); + try stderr.setColor(.reset); + if (dim) try stderr.setColor(.dim); } - try stderr.writeAll("\n"); + try w.writeAll("\n"); } else if (s.result_error_msgs.items.len > 0) { - try ttyconf.setColor(stderr, .red); - try stderr.writeAll(" failure\n"); + try stderr.setColor(.red); + try w.writeAll(" failure\n"); } else { assert(s.result_stderr.len > 0); - try ttyconf.setColor(stderr, .red); - try stderr.writeAll(" stderr\n"); + try stderr.setColor(.red); + try w.writeAll(" w\n"); } } @@ -1170,11 +1169,11 @@ fn printTreeStep( b: *std.Build, s: *Step, run: *const Run, - stderr: *Writer, - ttyconf: tty.Config, + stderr: Io.Terminal, parent_node: *PrintNode, step_stack: *std.AutoArrayHashMapUnmanaged(*Step, void), ) !void { + const writer = stderr.writer; const first = step_stack.swapRemove(s); const summary = run.summary; const skip = switch (summary) { @@ -1184,25 +1183,26 @@ fn printTreeStep( .failures => s.state == .success, }; if (skip) return; - try printPrefix(parent_node, stderr, ttyconf); + try printPrefix(parent_node, stderr); - if (!first) try ttyconf.setColor(stderr, .dim); if (parent_node.parent != null) { if (parent_node.last) { - try printChildNodePrefix(stderr, ttyconf); + try printChildNodePrefix(stderr); } else { - try stderr.writeAll(switch (ttyconf) { - .no_color, .windows_api => "+- ", + try writer.writeAll(switch (stderr.mode) { .escape_codes => "\x1B\x28\x30\x74\x71\x1B\x28\x42 ", // ├─ + else => "+- ", }); } } + if (!first) try stderr.setColor(.dim); + // dep_prefix omitted here because it is redundant with the tree. - try stderr.writeAll(s.name); + try writer.writeAll(s.name); if (first) { - try printStepStatus(s, stderr, ttyconf, run); + try printStepStatus(s, stderr, run); const last_index = if (summary == .all) s.dependencies.items.len -| 1 else blk: { var i: usize = s.dependencies.items.len; @@ -1224,17 +1224,17 @@ fn printTreeStep( .parent = parent_node, .last = i == last_index, }; - try printTreeStep(b, dep, run, stderr, ttyconf, &print_node, step_stack); + try printTreeStep(b, dep, run, stderr, &print_node, step_stack); } } else { if (s.dependencies.items.len == 0) { - try stderr.writeAll(" (reused)\n"); + try writer.writeAll(" (reused)\n"); } else { - try stderr.print(" (+{d} more reused dependencies)\n", .{ + try writer.print(" (+{d} more reused dependencies)\n", .{ s.dependencies.items.len, }); } - try ttyconf.setColor(stderr, .reset); + try stderr.setColor(.reset); } } @@ -1245,10 +1245,10 @@ fn printTreeStep( /// Each step has its dependencies traversed in random order, this accomplishes /// two things: /// - `step_stack` will be in randomized-depth-first order, so the build runner -/// spawns steps in a random (but optimized) order +/// spawns initial steps in a random order /// - each step's `dependants` list is also filled in a random order, so that -/// when it finishes executing in `workerMakeOneStep`, it spawns next steps -/// to run in random order +/// when it finishes executing in `makeStep`, it spawns next steps to run in +/// random order fn constructGraphAndCheckForDependencyLoop( gpa: Allocator, b: *std.Build, @@ -1285,12 +1285,12 @@ fn constructGraphAndCheckForDependencyLoop( } s.state = .precheck_done; + s.pending_deps = @intCast(s.dependencies.items.len); }, .precheck_done => {}, // These don't happen until we actually run the step graph. .dependency_failure => unreachable, - .running => unreachable, .success => unreachable, .failure => unreachable, .skipped => unreachable, @@ -1298,157 +1298,147 @@ fn constructGraphAndCheckForDependencyLoop( } } -fn workerMakeOneStep( +/// Runs the "make" function of the single step `s`, updates its state, and then spawns newly-ready +/// dependant steps in `group`. If `s` makes an RSS claim (i.e. `s.max_rss != 0`), the caller must +/// have already subtracted this value from `run.available_rss`. This function will release the RSS +/// claim (i.e. add `s.max_rss` back into `run.available_rss`) and queue any viable memory-blocked +/// steps after "make" completes for `s`. +fn makeStep( group: *Io.Group, b: *std.Build, s: *Step, - prog_node: std.Progress.Node, + root_prog_node: std.Progress.Node, run: *Run, -) void { - const io = b.graph.io; +) Io.Cancelable!void { + const graph = b.graph; + const io = graph.io; const gpa = run.gpa; - // First, check the conditions for running this step. If they are not met, - // then we return without doing the step, relying on another worker to - // queue this step up again when dependencies are met. - for (s.dependencies.items) |dep| { - switch (@atomicLoad(Step.State, &dep.state, .seq_cst)) { - .success, .skipped => continue, - .failure, .dependency_failure, .skipped_oom => { - @atomicStore(Step.State, &s.state, .dependency_failure, .seq_cst); - if (run.web_server) |*ws| ws.updateStepStatus(s, .failure); - return; - }, - .precheck_done, .running => { - // dependency is not finished yet. - return; - }, - .precheck_unstarted => unreachable, - .precheck_started => unreachable, - } - } - - if (s.max_rss != 0) { - run.max_rss_mutex.lockUncancelable(io); - defer run.max_rss_mutex.unlock(io); - - // Avoid running steps twice. - if (s.state != .precheck_done) { - // Another worker got the job. - return; - } + { + const step_prog_node = root_prog_node.start(s.name, 0); + defer step_prog_node.end(); - const new_claimed_rss = run.claimed_rss + s.max_rss; - if (new_claimed_rss > run.max_rss) { - // Running this step right now could possibly exceed the allotted RSS. - // Add this step to the queue of memory-blocked steps. - run.memory_blocked_steps.append(gpa, s) catch @panic("OOM"); - return; - } + if (run.web_server) |*ws| ws.updateStepStatus(s, .wip); - run.claimed_rss = new_claimed_rss; - s.state = .running; - } else { - // Avoid running steps twice. - if (@cmpxchgStrong(Step.State, &s.state, .precheck_done, .running, .seq_cst, .seq_cst) != null) { - // Another worker got the job. - return; - } - } + const new_state: Step.State = for (s.dependencies.items) |dep| { + switch (@atomicLoad(Step.State, &dep.state, .monotonic)) { + .precheck_unstarted => unreachable, + .precheck_started => unreachable, + .precheck_done => unreachable, - const sub_prog_node = prog_node.start(s.name, 0); - defer sub_prog_node.end(); + .failure, + .dependency_failure, + .skipped_oom, + => break .dependency_failure, - if (run.web_server) |*ws| ws.updateStepStatus(s, .wip); + .success, .skipped => {}, + } + } else if (s.make(.{ + .progress_node = step_prog_node, + .watch = run.watch, + .web_server = if (run.web_server) |*ws| ws else null, + .unit_test_timeout_ns = run.unit_test_timeout_ns, + .gpa = gpa, + })) state: { + break :state .success; + } else |err| switch (err) { + error.MakeFailed => .failure, + error.MakeSkipped => .skipped, + }; - const make_result = s.make(.{ - .progress_node = sub_prog_node, - .watch = run.watch, - .web_server = if (run.web_server) |*ws| ws else null, - .ttyconf = run.ttyconf, - .unit_test_timeout_ns = run.unit_test_timeout_ns, - .gpa = gpa, - }); + @atomicStore(Step.State, &s.state, new_state, .monotonic); - // No matter the result, we want to display error/warning messages. - const show_compile_errors = s.result_error_bundle.errorMessageCount() > 0; - const show_error_msgs = s.result_error_msgs.items.len > 0; - const show_stderr = s.result_stderr.len > 0; - if (show_error_msgs or show_compile_errors or show_stderr) { - const bw, _ = std.debug.lockStderrWriter(&stdio_buffer_allocation); - defer std.debug.unlockStderrWriter(); - const ttyconf = run.ttyconf; - printErrorMessages(gpa, s, .{}, bw, ttyconf, run.error_style, run.multiline_errors) catch {}; - } + switch (new_state) { + .precheck_unstarted => unreachable, + .precheck_started => unreachable, + .precheck_done => unreachable, - handle_result: { - if (make_result) |_| { - @atomicStore(Step.State, &s.state, .success, .seq_cst); - if (run.web_server) |*ws| ws.updateStepStatus(s, .success); - } else |err| switch (err) { - error.MakeFailed => { - @atomicStore(Step.State, &s.state, .failure, .seq_cst); + .failure, + .dependency_failure, + .skipped_oom, + => { if (run.web_server) |*ws| ws.updateStepStatus(s, .failure); std.Progress.setStatus(.failure_working); - break :handle_result; }, - error.MakeSkipped => { - @atomicStore(Step.State, &s.state, .skipped, .seq_cst); + + .success, + .skipped, + => { if (run.web_server) |*ws| ws.updateStepStatus(s, .success); }, } + } - // Successful completion of a step, so we queue up its dependants as well. - for (s.dependants.items) |dep| { - group.async(io, workerMakeOneStep, .{ group, b, dep, prog_node, run }); - } + // No matter the result, we want to display error/warning messages. + if (s.result_error_bundle.errorMessageCount() > 0 or + s.result_error_msgs.items.len > 0 or + s.result_stderr.len > 0) + { + const stderr = try io.lockStderr(&stdio_buffer_allocation, graph.stderr_mode); + defer io.unlockStderr(); + printErrorMessages(gpa, s, .{}, stderr.terminal(), run.error_style, run.multiline_errors) catch {}; } - // If this is a step that claims resources, we must now queue up other - // steps that are waiting for resources. if (s.max_rss != 0) { - var dispatch_deps: std.ArrayList(*Step) = .empty; - defer dispatch_deps.deinit(gpa); - dispatch_deps.ensureUnusedCapacity(gpa, run.memory_blocked_steps.items.len) catch @panic("OOM"); + var dispatch_set: std.ArrayList(*Step) = .empty; + defer dispatch_set.deinit(gpa); + // Release our RSS claim and kick off some blocked steps if possible. We use `dispatch_set` + // as a staging buffer to avoid recursing into `makeStep` while `run.max_rss_mutex` is held. { - run.max_rss_mutex.lockUncancelable(io); + try run.max_rss_mutex.lock(io); defer run.max_rss_mutex.unlock(io); - - // Give the memory back to the scheduler. - run.claimed_rss -= s.max_rss; - // Avoid kicking off too many tasks that we already know will not have - // enough resources. - var remaining = run.max_rss - run.claimed_rss; - var i: usize = 0; - for (run.memory_blocked_steps.items) |dep| { - assert(dep.max_rss != 0); - if (dep.max_rss <= remaining) { - remaining -= dep.max_rss; - dispatch_deps.appendAssumeCapacity(dep); - } else { - run.memory_blocked_steps.items[i] = dep; - i += 1; - } + run.available_rss += s.max_rss; + dispatch_set.ensureUnusedCapacity(gpa, run.memory_blocked_steps.items.len) catch @panic("OOM"); + while (run.memory_blocked_steps.getLastOrNull()) |candidate| { + if (run.available_rss < candidate.max_rss) break; + assert(run.memory_blocked_steps.pop() == candidate); + dispatch_set.appendAssumeCapacity(candidate); } - run.memory_blocked_steps.shrinkRetainingCapacity(i); } - for (dispatch_deps.items) |dep| { - // Must be called without max_rss_mutex held in case it executes recursively. - group.async(io, workerMakeOneStep, .{ group, b, dep, prog_node, run }); + for (dispatch_set.items) |candidate| { + group.async(io, makeStep, .{ group, b, candidate, root_prog_node, run }); + } + } + + for (s.dependants.items) |dependant| { + // `.acq_rel` synchronizes with itself to ensure all dependencies' final states are visible when this hits 0. + if (@atomicRmw(u32, &dependant.pending_deps, .Sub, 1, .acq_rel) == 1) { + try stepReady(group, b, dependant, root_prog_node, run); + } + } +} + +fn stepReady( + group: *Io.Group, + b: *std.Build, + s: *Step, + root_prog_node: std.Progress.Node, + run: *Run, +) !void { + const io = b.graph.io; + if (s.max_rss != 0) { + try run.max_rss_mutex.lock(io); + defer run.max_rss_mutex.unlock(io); + if (run.available_rss < s.max_rss) { + // Running this step right now could possibly exceed the allotted RSS. + run.memory_blocked_steps.append(run.gpa, s) catch @panic("OOM"); + return; } + run.available_rss -= s.max_rss; } + group.async(io, makeStep, .{ group, b, s, root_prog_node, run }); } pub fn printErrorMessages( gpa: Allocator, failing_step: *Step, options: std.zig.ErrorBundle.RenderOptions, - stderr: *Writer, - ttyconf: tty.Config, + stderr: Io.Terminal, error_style: ErrorStyle, multiline_errors: MultilineErrors, ) !void { + const writer = stderr.writer; if (error_style.verboseContext()) { // Provide context for where these error messages are coming from by // printing the corresponding Step subtree. @@ -1460,70 +1450,70 @@ pub fn printErrorMessages( } // Now, `step_stack` has the subtree that we want to print, in reverse order. - try ttyconf.setColor(stderr, .dim); + try stderr.setColor(.dim); var indent: usize = 0; while (step_stack.pop()) |s| : (indent += 1) { if (indent > 0) { - try stderr.splatByteAll(' ', (indent - 1) * 3); - try printChildNodePrefix(stderr, ttyconf); + try writer.splatByteAll(' ', (indent - 1) * 3); + try printChildNodePrefix(stderr); } - try stderr.writeAll(s.name); + try writer.writeAll(s.name); if (s == failing_step) { - try printStepFailure(s, stderr, ttyconf, true); + try printStepFailure(s, stderr, true); } else { - try stderr.writeAll("\n"); + try writer.writeAll("\n"); } } - try ttyconf.setColor(stderr, .reset); + try stderr.setColor(.reset); } else { // Just print the failing step itself. - try ttyconf.setColor(stderr, .dim); - try stderr.writeAll(failing_step.name); - try printStepFailure(failing_step, stderr, ttyconf, true); - try ttyconf.setColor(stderr, .reset); + try stderr.setColor(.dim); + try writer.writeAll(failing_step.name); + try printStepFailure(failing_step, stderr, true); + try stderr.setColor(.reset); } if (failing_step.result_stderr.len > 0) { - try stderr.writeAll(failing_step.result_stderr); + try writer.writeAll(failing_step.result_stderr); if (!mem.endsWith(u8, failing_step.result_stderr, "\n")) { - try stderr.writeAll("\n"); + try writer.writeAll("\n"); } } - try failing_step.result_error_bundle.renderToWriter(options, stderr, ttyconf); + try failing_step.result_error_bundle.renderToTerminal(options, stderr); for (failing_step.result_error_msgs.items) |msg| { - try ttyconf.setColor(stderr, .red); - try stderr.writeAll("error:"); - try ttyconf.setColor(stderr, .reset); + try stderr.setColor(.red); + try writer.writeAll("error:"); + try stderr.setColor(.reset); if (std.mem.indexOfScalar(u8, msg, '\n') == null) { - try stderr.print(" {s}\n", .{msg}); + try writer.print(" {s}\n", .{msg}); } else switch (multiline_errors) { .indent => { var it = std.mem.splitScalar(u8, msg, '\n'); - try stderr.print(" {s}\n", .{it.first()}); + try writer.print(" {s}\n", .{it.first()}); while (it.next()) |line| { - try stderr.print(" {s}\n", .{line}); + try writer.print(" {s}\n", .{line}); } }, - .newline => try stderr.print("\n{s}\n", .{msg}), - .none => try stderr.print(" {s}\n", .{msg}), + .newline => try writer.print("\n{s}\n", .{msg}), + .none => try writer.print(" {s}\n", .{msg}), } } if (error_style.verboseContext()) { if (failing_step.result_failed_command) |cmd_str| { - try ttyconf.setColor(stderr, .red); - try stderr.writeAll("failed command: "); - try ttyconf.setColor(stderr, .reset); - try stderr.writeAll(cmd_str); - try stderr.writeByte('\n'); + try stderr.setColor(.red); + try writer.writeAll("failed command: "); + try stderr.setColor(.reset); + try writer.writeAll(cmd_str); + try writer.writeByte('\n'); } } - try stderr.writeByte('\n'); + try writer.writeByte('\n'); } fn printSteps(builder: *std.Build, w: *Writer) !void { @@ -1538,6 +1528,8 @@ fn printSteps(builder: *std.Build, w: *Writer) !void { } fn printUsage(b: *std.Build, w: *Writer) !void { + const arena = b.graph.arena; + try w.print( \\Usage: {s} build [steps] [options] \\ @@ -1545,6 +1537,54 @@ fn printUsage(b: *std.Build, w: *Writer) !void { \\ , .{b.graph.zig_exe}); try printSteps(b, w); + try w.writeAll( + \\ + \\Project-Specific Options: + \\ + ); + + if (b.available_options_list.items.len == 0) { + try w.print(" (none)\n", .{}); + } else { + for (b.available_options_list.items) |option| { + const name = try fmt.allocPrint(arena, " -D{s}=[{t}]", .{ option.name, option.type_id }); + try w.print("{s:<30} {s}\n", .{ name, option.description }); + if (option.enum_options) |enum_options| { + const padding = " " ** 33; + try w.writeAll(padding ++ "Supported Values:\n"); + for (enum_options) |enum_option| { + try w.print(padding ++ " {s}\n", .{enum_option}); + } + } + } + } + + try w.writeAll( + \\ + \\System Integration Options: + \\ --search-prefix [path] Add a path to look for binaries, libraries, headers + \\ --sysroot [path] Set the system root directory (usually /) + \\ --libc [file] Provide a file which specifies libc paths + \\ + \\ --system [pkgdir] Disable package fetching; enable all integrations + \\ -fsys=[name] Enable a system integration + \\ -fno-sys=[name] Disable a system integration + \\ + \\ Available System Integrations: Enabled: + \\ + ); + if (b.graph.system_library_options.entries.len == 0) { + try w.writeAll(" (none) -\n"); + } else { + for (b.graph.system_library_options.keys(), b.graph.system_library_options.values()) |k, v| { + const status = switch (v) { + .declared_enabled => "yes", + .declared_disabled => "no", + .user_enabled, .user_disabled => unreachable, // already emitted error + }; + try w.print(" {s:<43} {s}\n", .{ k, status }); + } + } try w.writeAll( \\ @@ -1612,59 +1652,6 @@ fn printUsage(b: *std.Build, w: *Writer) !void { \\ compilation time of Zig source code (implies '--webui') \\ -fincremental Enable incremental compilation \\ -fno-incremental Disable incremental compilation - \\ - \\Project-Specific Options: - \\ - ); - - const arena = b.graph.arena; - if (b.available_options_list.items.len == 0) { - try w.print(" (none)\n", .{}); - } else { - for (b.available_options_list.items) |option| { - const name = try fmt.allocPrint(arena, " -D{s}=[{s}]", .{ - option.name, - @tagName(option.type_id), - }); - try w.print("{s:<30} {s}\n", .{ name, option.description }); - if (option.enum_options) |enum_options| { - const padding = " " ** 33; - try w.writeAll(padding ++ "Supported Values:\n"); - for (enum_options) |enum_option| { - try w.print(padding ++ " {s}\n", .{enum_option}); - } - } - } - } - - try w.writeAll( - \\ - \\System Integration Options: - \\ --search-prefix [path] Add a path to look for binaries, libraries, headers - \\ --sysroot [path] Set the system root directory (usually /) - \\ --libc [file] Provide a file which specifies libc paths - \\ - \\ --system [pkgdir] Disable package fetching; enable all integrations - \\ -fsys=[name] Enable a system integration - \\ -fno-sys=[name] Disable a system integration - \\ - \\ Available System Integrations: Enabled: - \\ - ); - if (b.graph.system_library_options.entries.len == 0) { - try w.writeAll(" (none) -\n"); - } else { - for (b.graph.system_library_options.keys(), b.graph.system_library_options.values()) |k, v| { - const status = switch (v) { - .declared_enabled => "yes", - .declared_disabled => "no", - .user_enabled, .user_disabled => unreachable, // already emitted error - }; - try w.print(" {s:<43} {s}\n", .{ k, status }); - } - } - - try w.writeAll( \\ \\Advanced Options: \\ -freference-trace[=num] How many lines of reference trace should be shown per compile error @@ -1841,9 +1828,20 @@ fn createModuleDependenciesForStep(step: *Step) Allocator.Error!void { } var stdio_buffer_allocation: [256]u8 = undefined; -var stdout_writer_allocation: std.fs.File.Writer = undefined; +var stdout_writer_allocation: Io.File.Writer = undefined; -fn initStdoutWriter() *Writer { - stdout_writer_allocation = std.fs.File.stdout().writerStreaming(&stdio_buffer_allocation); +fn initStdoutWriter(io: Io) *Writer { + stdout_writer_allocation = Io.File.stdout().writerStreaming(io, &stdio_buffer_allocation); return &stdout_writer_allocation.interface; } + +fn cleanTmpFiles(io: Io, steps: []const *Step) void { + for (steps) |step| { + const wf = step.cast(std.Build.Step.WriteFile) orelse continue; + if (wf.mode != .tmp) continue; + const path = wf.generated_directory.path orelse continue; + Io.Dir.cwd().deleteTree(io, path) catch |err| { + std.log.warn("failed to delete {s}: {t}", .{ path, err }); + }; + } +} diff --git a/lib/compiler/libc.zig b/lib/compiler/libc.zig index a18a7a0e06ff..8ca53fefc905 100644 --- a/lib/compiler/libc.zig +++ b/lib/compiler/libc.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const mem = std.mem; const LibCInstallation = std.zig.LibCInstallation; @@ -23,23 +24,19 @@ const usage_libc = var stdout_buffer: [4096]u8 = undefined; -pub fn main() !void { - var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena_instance.deinit(); - const arena = arena_instance.allocator(); - const gpa = arena; +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const gpa = init.gpa; + const io = init.io; + const args = try init.minimal.args.toSlice(arena); + const environ_map = init.environ_map; - var threaded: std.Io.Threaded = .init(gpa); - defer threaded.deinit(); - const io = threaded.io(); - - const args = try std.process.argsAlloc(arena); const zig_lib_directory = args[1]; var input_file: ?[]const u8 = null; var target_arch_os_abi: []const u8 = "native"; var print_includes: bool = false; - var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); + var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer); const stdout = &stdout_writer.interface; { var i: usize = 2; @@ -49,7 +46,7 @@ pub fn main() !void { if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { try stdout.writeAll(usage_libc); try stdout.flush(); - return std.process.cleanExit(); + return std.process.cleanExit(io); } else if (mem.eql(u8, arg, "-target")) { if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); i += 1; @@ -76,8 +73,8 @@ pub fn main() !void { const libc_installation: ?*LibCInstallation = libc: { if (input_file) |libc_file| { const libc = try arena.create(LibCInstallation); - libc.* = LibCInstallation.parse(arena, libc_file, &target) catch |err| { - fatal("unable to parse libc file at path {s}: {s}", .{ libc_file, @errorName(err) }); + libc.* = LibCInstallation.parse(arena, io, libc_file, &target) catch |err| { + fatal("unable to parse libc file at path {s}: {t}", .{ libc_file, err }); }; break :libc libc; } else { @@ -89,14 +86,16 @@ pub fn main() !void { const libc_dirs = std.zig.LibCDirs.detect( arena, + io, zig_lib_directory, &target, is_native_abi, true, libc_installation, + environ_map, ) catch |err| { const zig_target = try target.zigTriple(arena); - fatal("unable to detect libc for target {s}: {s}", .{ zig_target, @errorName(err) }); + fatal("unable to detect libc for target {s}: {t}", .{ zig_target, err }); }; if (libc_dirs.libc_include_dir_list.len == 0) { @@ -109,24 +108,24 @@ pub fn main() !void { try stdout.writeByte('\n'); } try stdout.flush(); - return std.process.cleanExit(); + return std.process.cleanExit(io); } if (input_file) |libc_file| { - var libc = LibCInstallation.parse(gpa, libc_file, &target) catch |err| { - fatal("unable to parse libc file at path {s}: {s}", .{ libc_file, @errorName(err) }); + var libc = LibCInstallation.parse(gpa, io, libc_file, &target) catch |err| { + fatal("unable to parse libc file at path {s}: {t}", .{ libc_file, err }); }; defer libc.deinit(gpa); } else { if (!target_query.canDetectLibC()) { fatal("unable to detect libc for non-native target", .{}); } - var libc = LibCInstallation.findNative(.{ - .allocator = gpa, + var libc = LibCInstallation.findNative(gpa, io, .{ .verbose = true, .target = &target, + .environ_map = environ_map, }) catch |err| { - fatal("unable to detect native libc: {s}", .{@errorName(err)}); + fatal("unable to detect native libc: {t}", .{err}); }; defer libc.deinit(gpa); diff --git a/lib/compiler/objcopy.zig b/lib/compiler/objcopy.zig index 7cf0f14e42be..57d019bc95b8 100644 --- a/lib/compiler/objcopy.zig +++ b/lib/compiler/objcopy.zig @@ -1,12 +1,13 @@ const builtin = @import("builtin"); + const std = @import("std"); +const Io = std.Io; const mem = std.mem; const fs = std.fs; const elf = std.elf; const Allocator = std.mem.Allocator; -const File = std.fs.File; +const File = std.Io.File; const assert = std.debug.assert; - const fatal = std.process.fatal; const Server = std.zig.Server; @@ -16,19 +17,13 @@ var stdout_buffer: [1024]u8 = undefined; var input_buffer: [1024]u8 = undefined; var output_buffer: [1024]u8 = undefined; -pub fn main() !void { - var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena_instance.deinit(); - const arena = arena_instance.allocator(); - - var general_purpose_allocator: std.heap.GeneralPurposeAllocator(.{}) = .init; - const gpa = general_purpose_allocator.allocator(); - - const args = try std.process.argsAlloc(arena); - return cmdObjCopy(gpa, arena, args[1..]); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const args = try init.minimal.args.toSlice(arena); + return cmdObjCopy(arena, init.io, args[1..]); } -fn cmdObjCopy(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { +fn cmdObjCopy(arena: Allocator, io: Io, args: []const []const u8) !void { var i: usize = 0; var opt_out_fmt: ?std.Target.ObjectFormat = null; var opt_input: ?[]const u8 = null; @@ -56,7 +51,7 @@ fn cmdObjCopy(gpa: Allocator, arena: Allocator, args: []const []const u8) !void fatal("unexpected positional argument: '{s}'", .{arg}); } } else if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { - return std.fs.File.stdout().writeAll(usage); + return Io.File.stdout().writeStreamingAll(io, usage); } else if (mem.eql(u8, arg, "-O") or mem.eql(u8, arg, "--output-target")) { i += 1; if (i >= args.len) fatal("expected another argument after '{s}'", .{arg}); @@ -147,16 +142,12 @@ fn cmdObjCopy(gpa: Allocator, arena: Allocator, args: []const []const u8) !void const input = opt_input orelse fatal("expected input parameter", .{}); const output = opt_output orelse fatal("expected output parameter", .{}); - var threaded: std.Io.Threaded = .init(gpa); - defer threaded.deinit(); - const io = threaded.io(); - - const input_file = fs.cwd().openFile(input, .{}) catch |err| fatal("failed to open {s}: {t}", .{ input, err }); - defer input_file.close(); + const input_file = Io.Dir.cwd().openFile(io, input, .{}) catch |err| fatal("failed to open {s}: {t}", .{ input, err }); + defer input_file.close(io); - const stat = input_file.stat() catch |err| fatal("failed to stat {s}: {t}", .{ input, err }); + const stat = input_file.stat(io) catch |err| fatal("failed to stat {s}: {t}", .{ input, err }); - var in: File.Reader = .initSize(input_file.adaptToNewApi(), io, &input_buffer, stat.size); + var in: File.Reader = .initSize(input_file, io, &input_buffer, stat.size); const elf_hdr = std.elf.Header.read(&in.interface) catch |err| switch (err) { error.ReadFailed => fatal("unable to read {s}: {t}", .{ input, in.err.? }), @@ -177,12 +168,12 @@ fn cmdObjCopy(gpa: Allocator, arena: Allocator, args: []const []const u8) !void } }; - const mode = if (out_fmt != .elf or only_keep_debug) fs.File.default_mode else stat.mode; + const permissions: Io.File.Permissions = if (out_fmt != .elf or only_keep_debug) .default_file else stat.permissions; - var output_file = try fs.cwd().createFile(output, .{ .mode = mode }); - defer output_file.close(); + var output_file = try Io.Dir.cwd().createFile(io, output, .{ .permissions = permissions }); + defer output_file.close(io); - var out = output_file.writer(&output_buffer); + var out = output_file.writer(io, &output_buffer); switch (out_fmt) { .hex, .raw => { @@ -221,8 +212,8 @@ fn cmdObjCopy(gpa: Allocator, arena: Allocator, args: []const []const u8) !void try out.end(); if (listen) { - var stdin_reader = fs.File.stdin().reader(io, &stdin_buffer); - var stdout_writer = fs.File.stdout().writer(&stdout_buffer); + var stdin_reader = Io.File.stdin().reader(io, &stdin_buffer); + var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer); var server = try Server.init(.{ .in = &stdin_reader.interface, .out = &stdout_writer.interface, @@ -234,7 +225,7 @@ fn cmdObjCopy(gpa: Allocator, arena: Allocator, args: []const []const u8) !void const hdr = try server.receiveMessage(); switch (hdr.tag) { .exit => { - return std.process.cleanExit(); + return std.process.cleanExit(io); }, .update => { if (seen_update) fatal("zig objcopy only supports 1 update for now", .{}); @@ -249,7 +240,7 @@ fn cmdObjCopy(gpa: Allocator, arena: Allocator, args: []const []const u8) !void } } } - return std.process.cleanExit(); + return std.process.cleanExit(io); } const usage = @@ -675,8 +666,9 @@ fn containsValidAddressRange(segments: []*BinaryElfSegment) bool { } fn padFile(out: *File.Writer, opt_size: ?u64) !void { + const io = out.io; const size = opt_size orelse return; - try out.file.setEndPos(size); + try out.file.setLength(io, size); } test "HexWriter.Record.Address has correct payload and checksum" { diff --git a/lib/compiler/reduce.zig b/lib/compiler/reduce.zig index 28305e801b7b..abdd9f843622 100644 --- a/lib/compiler/reduce.zig +++ b/lib/compiler/reduce.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const mem = std.mem; const Allocator = std.mem.Allocator; const assert = std.debug.assert; @@ -46,15 +47,11 @@ const Interestingness = enum { interesting, unknown, boring }; // - reduce flags sent to the compiler // - integrate with the build system? -pub fn main() !void { - var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena_instance.deinit(); - const arena = arena_instance.allocator(); - - var general_purpose_allocator: std.heap.GeneralPurposeAllocator(.{}) = .init; - const gpa = general_purpose_allocator.allocator(); - - const args = try std.process.argsAlloc(arena); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const gpa = init.gpa; + const io = init.io; + const args = try init.minimal.args.toSlice(arena); var opt_checker_path: ?[]const u8 = null; var opt_root_source_file_path: ?[]const u8 = null; @@ -68,9 +65,8 @@ pub fn main() !void { const arg = args[i]; if (mem.startsWith(u8, arg, "-")) { if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { - const stdout = std.fs.File.stdout(); - try stdout.writeAll(usage); - return std.process.cleanExit(); + try Io.File.stdout().writeStreamingAll(io, usage); + return std.process.cleanExit(io); } else if (mem.eql(u8, arg, "--")) { argv = args[i + 1 ..]; break; @@ -87,9 +83,7 @@ pub fn main() !void { if (i >= args.len) fatal("expected 32-bit integer after {s}", .{arg}); const next_arg = args[i]; seed = std.fmt.parseUnsigned(u32, next_arg, 0) catch |err| { - fatal("unable to parse seed '{s}' as 32-bit integer: {s}", .{ - next_arg, @errorName(err), - }); + fatal("unable to parse seed '{s}' as 32-bit integer: {t}", .{ next_arg, err }); }; } else { fatal("unrecognized parameter: '{s}'", .{arg}); @@ -120,7 +114,7 @@ pub fn main() !void { var astgen_input: std.Io.Writer.Allocating = .init(gpa); defer astgen_input.deinit(); - var tree = try parse(gpa, root_source_file_path); + var tree = try parse(gpa, io, root_source_file_path); defer { gpa.free(tree.source); tree.deinit(gpa); @@ -128,12 +122,10 @@ pub fn main() !void { if (!skip_smoke_test) { std.debug.print("smoke testing the interestingness check...\n", .{}); - switch (try runCheck(arena, interestingness_argv.items)) { + switch (try runCheck(arena, io, interestingness_argv.items)) { .interesting => {}, .boring, .unknown => |t| { - fatal("interestingness check returned {s} for unmodified input\n", .{ - @tagName(t), - }); + fatal("interestingness check returned {t} for unmodified input\n", .{t}); }, } } @@ -185,7 +177,7 @@ pub fn main() !void { std.debug.print("{s} ", .{@tagName(t)}); } std.debug.print("\n", .{}); - try transformationsToFixups(gpa, arena, root_source_file_path, this_set, &fixups); + try transformationsToFixups(gpa, arena, io, root_source_file_path, this_set, &fixups); rendered.clearRetainingCapacity(); try tree.render(gpa, &rendered.writer, fixups); @@ -232,16 +224,16 @@ pub fn main() !void { } } - try std.fs.cwd().writeFile(.{ .sub_path = root_source_file_path, .data = rendered.written() }); + try Io.Dir.cwd().writeFile(io, .{ .sub_path = root_source_file_path, .data = rendered.written() }); // std.debug.print("trying this code:\n{s}\n", .{rendered.items}); - const interestingness = try runCheck(arena, interestingness_argv.items); - std.debug.print("{d} random transformations: {s}. {d}/{d}\n", .{ - subset_size, @tagName(interestingness), start_index, transformations.items.len, + const interestingness = try runCheck(arena, io, interestingness_argv.items); + std.debug.print("{d} random transformations: {t}. {d}/{d}\n", .{ + subset_size, interestingness, start_index, transformations.items.len, }); switch (interestingness) { .interesting => { - const new_tree = try parse(gpa, root_source_file_path); + const new_tree = try parse(gpa, io, root_source_file_path); gpa.free(tree.source); tree.deinit(gpa); tree = new_tree; @@ -273,12 +265,12 @@ pub fn main() !void { fixups.clearRetainingCapacity(); rendered.clearRetainingCapacity(); try tree.render(gpa, &rendered.writer, fixups); - try std.fs.cwd().writeFile(.{ .sub_path = root_source_file_path, .data = rendered.written() }); + try Io.Dir.cwd().writeFile(io, .{ .sub_path = root_source_file_path, .data = rendered.written() }); - return std.process.cleanExit(); + return std.process.cleanExit(io); } std.debug.print("no more transformations found\n", .{}); - return std.process.cleanExit(); + return std.process.cleanExit(io); } fn sortTransformations(transformations: []Walk.Transformation, rng: std.Random) void { @@ -290,23 +282,24 @@ fn sortTransformations(transformations: []Walk.Transformation, rng: std.Random) fn termToInteresting(term: std.process.Child.Term) Interestingness { return switch (term) { - .Exited => |code| switch (code) { + .exited => |code| switch (code) { 0 => .interesting, 1 => .unknown, else => .boring, }, - else => b: { + .signal => |sig| { + std.debug.print("interestingness check terminated with signal {t}\n", .{sig}); + return .boring; + }, + else => { std.debug.print("interestingness check aborted unexpectedly\n", .{}); - break :b .boring; + return .boring; }, }; } -fn runCheck(arena: std.mem.Allocator, argv: []const []const u8) !Interestingness { - const result = try std.process.Child.run(.{ - .allocator = arena, - .argv = argv, - }); +fn runCheck(arena: Allocator, io: Io, argv: []const []const u8) !Interestingness { + const result = try std.process.run(arena, io, .{ .argv = argv }); if (result.stderr.len != 0) std.debug.print("{s}", .{result.stderr}); return termToInteresting(result.term); @@ -315,6 +308,7 @@ fn runCheck(arena: std.mem.Allocator, argv: []const []const u8) !Interestingness fn transformationsToFixups( gpa: Allocator, arena: Allocator, + io: Io, root_source_file_path: []const u8, transforms: []const Walk.Transformation, fixups: *Ast.Render.Fixups, @@ -352,7 +346,7 @@ fn transformationsToFixups( inline_imported_file.imported_string, }); defer gpa.free(full_imported_path); - var other_file_ast = try parse(gpa, full_imported_path); + var other_file_ast = try parse(gpa, io, full_imported_path); defer { gpa.free(other_file_ast.source); other_file_ast.deinit(gpa); @@ -396,8 +390,9 @@ fn transformationsToFixups( }; } -fn parse(gpa: Allocator, file_path: []const u8) !Ast { - const source_code = std.fs.cwd().readFileAllocOptions( +fn parse(gpa: Allocator, io: Io, file_path: []const u8) !Ast { + const source_code = Io.Dir.cwd().readFileAllocOptions( + io, file_path, gpa, .limited(std.math.maxInt(u32)), diff --git a/lib/compiler/reduce/Walk.zig b/lib/compiler/reduce/Walk.zig index 1caf942fac92..230354fee5ea 100644 --- a/lib/compiler/reduce/Walk.zig +++ b/lib/compiler/reduce/Walk.zig @@ -501,10 +501,6 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void { .@"asm", => return walkAsm(w, ast.fullAsm(node).?), - .asm_legacy => { - return walkAsmLegacy(w, ast.legacyAsm(node).?); - }, - .enum_literal => { return walkIdentifier(w, ast.nodeMainToken(node)); // name }, @@ -881,11 +877,6 @@ fn walkAsm(w: *Walk, asm_node: Ast.full.Asm) Error!void { try walkExpressions(w, asm_node.ast.items); } -fn walkAsmLegacy(w: *Walk, asm_node: Ast.full.AsmLegacy) Error!void { - try walkExpression(w, asm_node.ast.template); - try walkExpressions(w, asm_node.ast.items); -} - /// Check if it is already gutted (i.e. its body replaced with `@trap()`). fn isFnBodyGutted(ast: *const Ast, body_node: Ast.Node.Index) bool { // skip over discards diff --git a/lib/compiler/resinator/cli.zig b/lib/compiler/resinator/cli.zig index 59568e9cef47..59843585a25b 100644 --- a/lib/compiler/resinator/cli.zig +++ b/lib/compiler/resinator/cli.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const code_pages = @import("code_pages.zig"); const SupportedCodePage = code_pages.SupportedCodePage; const lang = @import("lang.zig"); @@ -124,15 +125,15 @@ pub const Diagnostics = struct { try self.errors.append(self.allocator, error_details); } - pub fn renderToStdErr(self: *Diagnostics, args: []const []const u8) void { - const stderr, const ttyconf = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); - self.renderToWriter(args, stderr, ttyconf) catch return; + pub fn renderToStderr(self: *Diagnostics, io: Io, args: []const []const u8) Io.Cancelable!void { + const stderr = try io.lockStderr(&.{}, null); + defer io.unlockStderr(); + self.renderToWriter(args, stderr.terminal()) catch return; } - pub fn renderToWriter(self: *Diagnostics, args: []const []const u8, writer: *std.Io.Writer, config: std.Io.tty.Config) !void { + pub fn renderToWriter(self: *Diagnostics, args: []const []const u8, t: Io.Terminal) !void { for (self.errors.items) |err_details| { - try renderErrorMessage(writer, config, err_details, args); + try renderErrorMessage(t, err_details, args); } } @@ -169,7 +170,7 @@ pub const Options = struct { coff_options: cvtres.CoffOptions = .{}, pub const IoSource = union(enum) { - stdio: std.fs.File, + stdio: Io.File, filename: []const u8, }; pub const AutoIncludes = enum { any, msvc, gnu, none }; @@ -249,13 +250,13 @@ pub const Options = struct { /// worlds' situation where we'll be compatible with most use-cases /// of the .rc extension being omitted from the CLI args, but still /// work fine if the file itself does not have an extension. - pub fn maybeAppendRC(options: *Options, cwd: std.fs.Dir) !void { + pub fn maybeAppendRC(options: *Options, io: Io, cwd: Io.Dir) !void { switch (options.input_source) { .stdio => return, .filename => {}, } if (options.input_format == .rc and std.fs.path.extension(options.input_source.filename).len == 0) { - cwd.access(options.input_source.filename, .{}) catch |err| switch (err) { + cwd.access(io, options.input_source.filename, .{}) catch |err| switch (err) { error.FileNotFound => { var filename_bytes = try options.allocator.alloc(u8, options.input_source.filename.len + 3); @memcpy(filename_bytes[0..options.input_source.filename.len], options.input_source.filename); @@ -418,7 +419,7 @@ pub const Arg = struct { }; } - pub fn looksLikeFilepath(self: Arg) bool { + pub fn looksLikeFilepath(self: Arg, io: Io) bool { const meets_min_requirements = self.prefix == .slash and isSupportedInputExtension(std.fs.path.extension(self.full)); if (!meets_min_requirements) return false; @@ -437,7 +438,7 @@ pub const Arg = struct { // It's still possible for a file path to look like a /fo option but not actually // be one, e.g. `/foo/bar.rc`. As a last ditch effort to reduce false negatives, // check if the file path exists and, if so, then we ignore the 'could be /fo option'-ness - std.fs.accessAbsolute(self.full, .{}) catch return false; + Io.Dir.accessAbsolute(io, self.full, .{}) catch return false; return true; } @@ -489,7 +490,7 @@ pub const ParseError = error{ParseError} || Allocator.Error; /// Note: Does not run `Options.maybeAppendRC` automatically. If that behavior is desired, /// it must be called separately. -pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagnostics) ParseError!Options { +pub fn parse(allocator: Allocator, io: Io, args: []const []const u8, diagnostics: *Diagnostics) ParseError!Options { var options = Options{ .allocator = allocator }; errdefer options.deinit(); @@ -529,7 +530,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn } const args_remaining = args.len - arg_i; - if (args_remaining <= 2 and arg.looksLikeFilepath()) { + if (args_remaining <= 2 and arg.looksLikeFilepath(io)) { var err_details = Diagnostics.ErrorDetails{ .type = .note, .print_args = true, .arg_index = arg_i }; try err_details.msg.appendSlice(allocator, "this argument was inferred to be a filepath, so argument parsing was terminated"); try diagnostics.append(err_details); @@ -1343,41 +1344,42 @@ test parsePercent { try std.testing.expectError(error.InvalidFormat, parsePercent("~1")); } -pub fn renderErrorMessage(writer: *std.Io.Writer, config: std.Io.tty.Config, err_details: Diagnostics.ErrorDetails, args: []const []const u8) !void { - try config.setColor(writer, .dim); +pub fn renderErrorMessage(t: Io.Terminal, err_details: Diagnostics.ErrorDetails, args: []const []const u8) !void { + const writer = t.writer; + try t.setColor(.dim); try writer.writeAll(""); - try config.setColor(writer, .reset); - try config.setColor(writer, .bold); + try t.setColor(.reset); + try t.setColor(.bold); try writer.writeAll(": "); switch (err_details.type) { .err => { - try config.setColor(writer, .red); + try t.setColor(.red); try writer.writeAll("error: "); }, .warning => { - try config.setColor(writer, .yellow); + try t.setColor(.yellow); try writer.writeAll("warning: "); }, .note => { - try config.setColor(writer, .cyan); + try t.setColor(.cyan); try writer.writeAll("note: "); }, } - try config.setColor(writer, .reset); - try config.setColor(writer, .bold); + try t.setColor(.reset); + try t.setColor(.bold); try writer.writeAll(err_details.msg.items); try writer.writeByte('\n'); - try config.setColor(writer, .reset); + try t.setColor(.reset); if (!err_details.print_args) { try writer.writeByte('\n'); return; } - try config.setColor(writer, .dim); + try t.setColor(.dim); const prefix = " ... "; try writer.writeAll(prefix); - try config.setColor(writer, .reset); + try t.setColor(.reset); const arg_with_name = args[err_details.arg_index]; const prefix_slice = arg_with_name[0..err_details.arg_span.prefix_len]; @@ -1388,15 +1390,15 @@ pub fn renderErrorMessage(writer: *std.Io.Writer, config: std.Io.tty.Config, err try writer.writeAll(prefix_slice); if (before_name_slice.len > 0) { - try config.setColor(writer, .dim); + try t.setColor(.dim); try writer.writeAll(before_name_slice); - try config.setColor(writer, .reset); + try t.setColor(.reset); } try writer.writeAll(name_slice); if (after_name_slice.len > 0) { - try config.setColor(writer, .dim); + try t.setColor(.dim); try writer.writeAll(after_name_slice); - try config.setColor(writer, .reset); + try t.setColor(.reset); } var next_arg_len: usize = 0; @@ -1414,13 +1416,13 @@ pub fn renderErrorMessage(writer: *std.Io.Writer, config: std.Io.tty.Config, err if (err_details.arg_span.value_offset >= arg_with_name.len) { try writer.writeByte(' '); } - try config.setColor(writer, .dim); + try t.setColor(.dim); try writer.writeAll(" ..."); - try config.setColor(writer, .reset); + try t.setColor(.reset); } try writer.writeByte('\n'); - try config.setColor(writer, .green); + try t.setColor(.green); try writer.splatByteAll(' ', prefix.len); // Special case for when the option is *only* a prefix (e.g. invalid option: -) if (err_details.arg_span.prefix_len == arg_with_name.len) { @@ -1446,7 +1448,7 @@ pub fn renderErrorMessage(writer: *std.Io.Writer, config: std.Io.tty.Config, err } } try writer.writeByte('\n'); - try config.setColor(writer, .reset); + try t.setColor(.reset); } fn testParse(args: []const []const u8) !Options { @@ -1991,6 +1993,8 @@ test "parse: input and output formats" { } test "maybeAppendRC" { + const io = std.testing.io; + var tmp = std.testing.tmpDir(.{}); defer tmp.cleanup(); @@ -2000,21 +2004,21 @@ test "maybeAppendRC" { // Create the file so that it's found. In this scenario, .rc should not get // appended. - var file = try tmp.dir.createFile("foo", .{}); - file.close(); - try options.maybeAppendRC(tmp.dir); + var file = try tmp.dir.createFile(io, "foo", .{}); + file.close(io); + try options.maybeAppendRC(io, tmp.dir); try std.testing.expectEqualStrings("foo", options.input_source.filename); // Now delete the file and try again. But this time change the input format // to non-rc. - try tmp.dir.deleteFile("foo"); + try tmp.dir.deleteFile(io, "foo"); options.input_format = .res; - try options.maybeAppendRC(tmp.dir); + try options.maybeAppendRC(io, tmp.dir); try std.testing.expectEqualStrings("foo", options.input_source.filename); // Finally, reset the input format to rc. Since the verbatim name is no longer found // and the input filename does not have an extension, .rc should get appended. options.input_format = .rc; - try options.maybeAppendRC(tmp.dir); + try options.maybeAppendRC(io, tmp.dir); try std.testing.expectEqualStrings("foo.rc", options.input_source.filename); } diff --git a/lib/compiler/resinator/compile.zig b/lib/compiler/resinator/compile.zig index 08e161e505a0..a315ea488e6b 100644 --- a/lib/compiler/resinator/compile.zig +++ b/lib/compiler/resinator/compile.zig @@ -34,7 +34,7 @@ const code_pages = @import("code_pages.zig"); const errors = @import("errors.zig"); pub const CompileOptions = struct { - cwd: std.fs.Dir, + cwd: std.Io.Dir, diagnostics: *Diagnostics, source_mappings: ?*SourceMappings = null, /// List of paths (absolute or relative to `cwd`) for every file that the resources within the .rc file depend on. @@ -80,7 +80,7 @@ pub const Dependencies = struct { } }; -pub fn compile(allocator: Allocator, io: Io, source: []const u8, writer: *std.Io.Writer, options: CompileOptions) !void { +pub fn compile(allocator: Allocator, io: Io, source: []const u8, writer: *std.Io.Writer, options: CompileOptions, environ_map: *const std.process.Environ.Map) !void { var lexer = lex.Lexer.init(source, .{ .default_code_page = options.default_code_page, .source_mappings = options.source_mappings, @@ -96,7 +96,7 @@ pub fn compile(allocator: Allocator, io: Io, source: []const u8, writer: *std.Io var search_dirs: std.ArrayList(SearchDir) = .empty; defer { for (search_dirs.items) |*search_dir| { - search_dir.deinit(allocator); + search_dir.deinit(allocator, io); } search_dirs.deinit(allocator); } @@ -106,13 +106,13 @@ pub fn compile(allocator: Allocator, io: Io, source: []const u8, writer: *std.Io // If dirname returns null, then the root path will be the same as // the cwd so we don't need to add it as a distinct search path. if (std.fs.path.dirname(root_path)) |root_dir_path| { - var root_dir = try options.cwd.openDir(root_dir_path, .{}); - errdefer root_dir.close(); + var root_dir = try options.cwd.openDir(io, root_dir_path, .{}); + errdefer root_dir.close(io); try search_dirs.append(allocator, .{ .dir = root_dir, .path = try allocator.dupe(u8, root_dir_path) }); } } - // Re-open the passed in cwd since we want to be able to close it (std.fs.cwd() shouldn't be closed) - const cwd_dir = options.cwd.openDir(".", .{}) catch |err| { + // Re-open the passed in cwd since we want to be able to close it (Io.Dir.cwd() shouldn't be closed) + const cwd_dir = options.cwd.openDir(io, ".", .{}) catch |err| { try options.diagnostics.append(.{ .err = .failed_to_open_cwd, .token = .{ @@ -132,24 +132,23 @@ pub fn compile(allocator: Allocator, io: Io, source: []const u8, writer: *std.Io }; try search_dirs.append(allocator, .{ .dir = cwd_dir, .path = null }); for (options.extra_include_paths) |extra_include_path| { - var dir = openSearchPathDir(options.cwd, extra_include_path) catch { + var dir = openSearchPathDir(options.cwd, io, extra_include_path) catch { // TODO: maybe a warning that the search path is skipped? continue; }; - errdefer dir.close(); + errdefer dir.close(io); try search_dirs.append(allocator, .{ .dir = dir, .path = try allocator.dupe(u8, extra_include_path) }); } for (options.system_include_paths) |system_include_path| { - var dir = openSearchPathDir(options.cwd, system_include_path) catch { + var dir = openSearchPathDir(options.cwd, io, system_include_path) catch { // TODO: maybe a warning that the search path is skipped? continue; }; - errdefer dir.close(); + errdefer dir.close(io); try search_dirs.append(allocator, .{ .dir = dir, .path = try allocator.dupe(u8, system_include_path) }); } if (!options.ignore_include_env_var) { - const INCLUDE = std.process.getEnvVarOwned(allocator, "INCLUDE") catch ""; - defer allocator.free(INCLUDE); + const INCLUDE = environ_map.get("INCLUDE") orelse ""; // The only precedence here is llvm-rc which also uses the platform-specific // delimiter. There's no precedence set by `rc.exe` since it's Windows-only. @@ -159,8 +158,8 @@ pub fn compile(allocator: Allocator, io: Io, source: []const u8, writer: *std.Io }; var it = std.mem.tokenizeScalar(u8, INCLUDE, delimiter); while (it.next()) |search_path| { - var dir = openSearchPathDir(options.cwd, search_path) catch continue; - errdefer dir.close(); + var dir = openSearchPathDir(options.cwd, io, search_path) catch continue; + errdefer dir.close(io); try search_dirs.append(allocator, .{ .dir = dir, .path = try allocator.dupe(u8, search_path) }); } } @@ -196,7 +195,7 @@ pub const Compiler = struct { arena: Allocator, allocator: Allocator, io: Io, - cwd: std.fs.Dir, + cwd: std.Io.Dir, state: State = .{}, diagnostics: *Diagnostics, dependencies: ?*Dependencies, @@ -388,7 +387,9 @@ pub const Compiler = struct { /// matching file is invalid. That is, it does not do the `cmd` PATH searching /// thing of continuing to look for matching files until it finds a valid /// one if a matching file is invalid. - fn searchForFile(self: *Compiler, path: []const u8) !std.fs.File { + fn searchForFile(self: *Compiler, path: []const u8) !std.Io.File { + const io = self.io; + // If the path is absolute, then it is not resolved relative to any search // paths, so there's no point in checking them. // @@ -404,8 +405,8 @@ pub const Compiler = struct { // `/test.bin` relative to include paths and instead only treats it as // an absolute path. if (std.fs.path.isAbsolute(path)) { - const file = try utils.openFileNotDir(std.fs.cwd(), path, .{}); - errdefer file.close(); + const file = try utils.openFileNotDir(Io.Dir.cwd(), io, path, .{}); + errdefer file.close(io); if (self.dependencies) |dependencies| { const duped_path = try dependencies.allocator.dupe(u8, path); @@ -414,10 +415,10 @@ pub const Compiler = struct { } } - var first_error: ?(std.fs.File.OpenError || std.fs.File.StatError) = null; + var first_error: ?(std.Io.File.OpenError || std.Io.File.StatError) = null; for (self.search_dirs) |search_dir| { - if (utils.openFileNotDir(search_dir.dir, path, .{})) |file| { - errdefer file.close(); + if (utils.openFileNotDir(search_dir.dir, io, path, .{})) |file| { + errdefer file.close(io); if (self.dependencies) |dependencies| { const searched_file_path = try std.fs.path.join(dependencies.allocator, &.{ @@ -587,7 +588,7 @@ pub const Compiler = struct { }); }, }; - defer file_handle.close(); + defer file_handle.close(io); var file_buffer: [2048]u8 = undefined; var file_reader = file_handle.reader(io, &file_buffer); @@ -2892,13 +2893,13 @@ pub const Compiler = struct { } }; -pub const OpenSearchPathError = std.fs.Dir.OpenError; +pub const OpenSearchPathError = std.Io.Dir.OpenError; -fn openSearchPathDir(dir: std.fs.Dir, path: []const u8) OpenSearchPathError!std.fs.Dir { +fn openSearchPathDir(dir: std.Io.Dir, io: Io, path: []const u8) OpenSearchPathError!std.Io.Dir { // Validate the search path to avoid possible unreachable on invalid paths, // see https://github.com/ziglang/zig/issues/15607 for why this is currently necessary. try validateSearchPath(path); - return dir.openDir(path, .{}); + return dir.openDir(io, path, .{}); } /// Very crude attempt at validating a path. This is imperfect @@ -2927,11 +2928,11 @@ fn validateSearchPath(path: []const u8) error{BadPathName}!void { } pub const SearchDir = struct { - dir: std.fs.Dir, + dir: std.Io.Dir, path: ?[]const u8, - pub fn deinit(self: *SearchDir, allocator: Allocator) void { - self.dir.close(); + pub fn deinit(self: *SearchDir, allocator: Allocator, io: Io) void { + self.dir.close(io); if (self.path) |path| { allocator.free(path); } diff --git a/lib/compiler/resinator/errors.zig b/lib/compiler/resinator/errors.zig index 0060990ab627..4f41a5b56da5 100644 --- a/lib/compiler/resinator/errors.zig +++ b/lib/compiler/resinator/errors.zig @@ -67,12 +67,12 @@ pub const Diagnostics = struct { return @intCast(index); } - pub fn renderToStdErr(self: *Diagnostics, cwd: std.fs.Dir, source: []const u8, source_mappings: ?SourceMappings) void { + pub fn renderToStderr(self: *Diagnostics, cwd: Io.Dir, source: []const u8, source_mappings: ?SourceMappings) Io.Cancelable!void { const io = self.io; - const stderr, const ttyconf = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); + const stderr = try io.lockStderr(&.{}, null); + defer io.unlockStderr(); for (self.errors.items) |err_details| { - renderErrorMessage(io, stderr, ttyconf, cwd, err_details, source, self.strings.items, source_mappings) catch return; + renderErrorMessage(io, stderr.terminal(), cwd, err_details, source, self.strings.items, source_mappings) catch return; } } @@ -169,9 +169,9 @@ pub const ErrorDetails = struct { filename_string_index: FilenameStringIndex, pub const FilenameStringIndex = std.meta.Int(.unsigned, 32 - @bitSizeOf(FileOpenErrorEnum)); - pub const FileOpenErrorEnum = std.meta.FieldEnum(std.fs.File.OpenError || std.fs.File.StatError); + pub const FileOpenErrorEnum = std.meta.FieldEnum(Io.File.OpenError || Io.File.StatError); - pub fn enumFromError(err: (std.fs.File.OpenError || std.fs.File.StatError)) FileOpenErrorEnum { + pub fn enumFromError(err: (Io.File.OpenError || Io.File.StatError)) FileOpenErrorEnum { return switch (err) { inline else => |e| @field(ErrorDetails.FileOpenError.FileOpenErrorEnum, @errorName(e)), }; @@ -901,9 +901,8 @@ const truncated_str = "<...truncated...>"; pub fn renderErrorMessage( io: Io, - writer: *std.Io.Writer, - tty_config: std.Io.tty.Config, - cwd: std.fs.Dir, + t: Io.Terminal, + cwd: Io.Dir, err_details: ErrorDetails, source: []const u8, strings: []const []const u8, @@ -927,36 +926,37 @@ pub fn renderErrorMessage( const err_line = if (corresponding_span) |span| span.start_line else err_details.token.line_number; - try tty_config.setColor(writer, .bold); + const writer = t.writer; + try t.setColor(.bold); if (corresponding_file) |file| { try writer.writeAll(file); } else { - try tty_config.setColor(writer, .dim); + try t.setColor(.dim); try writer.writeAll(""); - try tty_config.setColor(writer, .reset); - try tty_config.setColor(writer, .bold); + try t.setColor(.reset); + try t.setColor(.bold); } try writer.print(":{d}:{d}: ", .{ err_line, column }); switch (err_details.type) { .err => { - try tty_config.setColor(writer, .red); + try t.setColor(.red); try writer.writeAll("error: "); }, .warning => { - try tty_config.setColor(writer, .yellow); + try t.setColor(.yellow); try writer.writeAll("warning: "); }, .note => { - try tty_config.setColor(writer, .cyan); + try t.setColor(.cyan); try writer.writeAll("note: "); }, .hint => unreachable, } - try tty_config.setColor(writer, .reset); - try tty_config.setColor(writer, .bold); + try t.setColor(.reset); + try t.setColor(.bold); try err_details.render(writer, source, strings); try writer.writeByte('\n'); - try tty_config.setColor(writer, .reset); + try t.setColor(.reset); if (!err_details.print_source_line) { try writer.writeByte('\n'); @@ -983,20 +983,20 @@ pub fn renderErrorMessage( try writer.writeAll(source_line_for_display.line); if (source_line_for_display.truncated) { - try tty_config.setColor(writer, .dim); + try t.setColor(.dim); try writer.writeAll(truncated_str); - try tty_config.setColor(writer, .reset); + try t.setColor(.reset); } try writer.writeByte('\n'); - try tty_config.setColor(writer, .green); + try t.setColor(.green); const num_spaces = truncated_visual_info.point_offset - truncated_visual_info.before_len; try writer.splatByteAll(' ', num_spaces); try writer.splatByteAll('~', truncated_visual_info.before_len); try writer.writeByte('^'); try writer.splatByteAll('~', truncated_visual_info.after_len); try writer.writeByte('\n'); - try tty_config.setColor(writer, .reset); + try t.setColor(.reset); if (corresponding_span != null and corresponding_file != null) { var worth_printing_lines: bool = true; @@ -1021,22 +1021,22 @@ pub fn renderErrorMessage( break :blk null; }, }; - defer if (corresponding_lines) |*cl| cl.deinit(); + defer if (corresponding_lines) |*cl| cl.deinit(io); - try tty_config.setColor(writer, .bold); + try t.setColor(.bold); if (corresponding_file) |file| { try writer.writeAll(file); } else { - try tty_config.setColor(writer, .dim); + try t.setColor(.dim); try writer.writeAll(""); - try tty_config.setColor(writer, .reset); - try tty_config.setColor(writer, .bold); + try t.setColor(.reset); + try t.setColor(.bold); } try writer.print(":{d}:{d}: ", .{ err_line, column }); - try tty_config.setColor(writer, .cyan); + try t.setColor(.cyan); try writer.writeAll("note: "); - try tty_config.setColor(writer, .reset); - try tty_config.setColor(writer, .bold); + try t.setColor(.reset); + try t.setColor(.bold); try writer.writeAll("this line originated from line"); if (corresponding_span.?.start_line != corresponding_span.?.end_line) { try writer.print("s {}-{}", .{ corresponding_span.?.start_line, corresponding_span.?.end_line }); @@ -1044,7 +1044,7 @@ pub fn renderErrorMessage( try writer.print(" {}", .{corresponding_span.?.start_line}); } try writer.print(" of file '{s}'\n", .{corresponding_file.?}); - try tty_config.setColor(writer, .reset); + try t.setColor(.reset); if (!worth_printing_lines) return; @@ -1055,21 +1055,21 @@ pub fn renderErrorMessage( }) |display_line| { try writer.writeAll(display_line.line); if (display_line.truncated) { - try tty_config.setColor(writer, .dim); + try t.setColor(.dim); try writer.writeAll(truncated_str); - try tty_config.setColor(writer, .reset); + try t.setColor(.reset); } try writer.writeByte('\n'); } break :write_lines null; }; if (write_lines_err) |err| { - try tty_config.setColor(writer, .red); + try t.setColor(.red); try writer.writeAll(" | "); - try tty_config.setColor(writer, .reset); - try tty_config.setColor(writer, .dim); + try t.setColor(.reset); + try t.setColor(.dim); try writer.print("unable to print line(s) from file: {s}\n", .{@errorName(err)}); - try tty_config.setColor(writer, .reset); + try t.setColor(.reset); } try writer.writeByte('\n'); } @@ -1094,13 +1094,13 @@ const CorrespondingLines = struct { last_byte: u8 = 0, at_eof: bool = false, span: SourceMappings.CorrespondingSpan, - file: std.fs.File, - file_reader: std.fs.File.Reader, + file: Io.File, + file_reader: Io.File.Reader, code_page: SupportedCodePage, pub fn init( io: Io, - cwd: std.fs.Dir, + cwd: Io.Dir, err_details: ErrorDetails, line_for_comparison: []const u8, corresponding_span: SourceMappings.CorrespondingSpan, @@ -1120,12 +1120,12 @@ const CorrespondingLines = struct { var corresponding_lines = CorrespondingLines{ .span = corresponding_span, - .file = try utils.openFileNotDir(cwd, corresponding_file, .{}), + .file = try utils.openFileNotDir(cwd, io, corresponding_file, .{}), .code_page = err_details.code_page, .file_reader = undefined, }; corresponding_lines.file_reader = corresponding_lines.file.reader(io, file_reader_buf); - errdefer corresponding_lines.deinit(); + errdefer corresponding_lines.deinit(io); try corresponding_lines.writeLineFromStreamVerbatim( &corresponding_lines.file_reader.interface, @@ -1221,8 +1221,8 @@ const CorrespondingLines = struct { }; } - pub fn deinit(self: *CorrespondingLines) void { - self.file.close(); + pub fn deinit(self: *CorrespondingLines, io: Io) void { + self.file.close(io); } }; diff --git a/lib/compiler/resinator/main.zig b/lib/compiler/resinator/main.zig index 6d6819f45ae3..d1aaa24264d2 100644 --- a/lib/compiler/resinator/main.zig +++ b/lib/compiler/resinator/main.zig @@ -19,20 +19,30 @@ const fmtResourceType = @import("res.zig").NameOrOrdinal.fmtResourceType; const aro = @import("aro"); const compiler_util = @import("../util.zig"); -pub fn main() !void { +pub fn main(init: std.process.Init.Minimal) !void { var debug_allocator: std.heap.DebugAllocator(.{}) = .init; defer std.debug.assert(debug_allocator.deinit() == .ok); const gpa = debug_allocator.allocator(); + var environ_map = try init.environ.createMap(gpa); + defer environ_map.deinit(); + + var threaded: std.Io.Threaded = .init(gpa, .{ + .environ = init.environ, + .argv0 = .init(init.args), + }); + defer threaded.deinit(); + const io = threaded.io(); + var arena_state = std.heap.ArenaAllocator.init(gpa); defer arena_state.deinit(); const arena = arena_state.allocator(); - const args = try std.process.argsAlloc(arena); + const args = try init.args.toSlice(arena); if (args.len < 2) { - const w, const ttyconf = std.debug.lockStderrWriter(&.{}); - try renderErrorMessage(w, ttyconf, .err, "expected zig lib dir as first argument", .{}); + const stderr = try io.lockStderr(&.{}, null); + try renderErrorMessage(stderr.terminal(), .err, "expected zig lib dir as first argument", .{}); std.process.exit(1); } const zig_lib_dir = args[1]; @@ -45,7 +55,7 @@ pub fn main() !void { } var stdout_buffer: [1024]u8 = undefined; - var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); + var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer); const stdout = &stdout_writer.interface; var error_handler: ErrorHandler = switch (zig_integration) { true => .{ @@ -60,35 +70,31 @@ pub fn main() !void { var options = options: { var cli_diagnostics = cli.Diagnostics.init(gpa); defer cli_diagnostics.deinit(); - var options = cli.parse(gpa, cli_args, &cli_diagnostics) catch |err| switch (err) { + var options = cli.parse(gpa, io, cli_args, &cli_diagnostics) catch |err| switch (err) { error.ParseError => { - try error_handler.emitCliDiagnostics(gpa, cli_args, &cli_diagnostics); + try error_handler.emitCliDiagnostics(gpa, io, cli_args, &cli_diagnostics); std.process.exit(1); }, else => |e| return e, }; - try options.maybeAppendRC(std.fs.cwd()); + try options.maybeAppendRC(io, Io.Dir.cwd()); if (!zig_integration) { // print any warnings/notes - cli_diagnostics.renderToStdErr(cli_args); + try cli_diagnostics.renderToStderr(io, cli_args); // If there was something printed, then add an extra newline separator // so that there is a clear separation between the cli diagnostics and whatever // gets printed after if (cli_diagnostics.errors.items.len > 0) { - const stderr, _ = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); - try stderr.writeByte('\n'); + const stderr = try io.lockStderr(&.{}, null); + defer io.unlockStderr(); + try stderr.file_writer.interface.writeByte('\n'); } } break :options options; }; defer options.deinit(); - var threaded: std.Io.Threaded = .init(gpa); - defer threaded.deinit(); - const io = threaded.io(); - if (options.print_help_and_exit) { try cli.writeUsage(stdout, "zig rc"); try stdout.flush(); @@ -130,26 +136,23 @@ pub fn main() !void { var stderr_buf: [512]u8 = undefined; var diagnostics: aro.Diagnostics = .{ .output = output: { if (zig_integration) break :output .{ .to_list = .{ .arena = .init(gpa) } }; - const w, const ttyconf = std.debug.lockStderrWriter(&stderr_buf); - break :output .{ .to_writer = .{ - .writer = w, - .color = ttyconf, - } }; + const stderr = try io.lockStderr(&stderr_buf, null); + break :output .{ .to_writer = stderr.terminal() }; } }; defer { diagnostics.deinit(); - if (!zig_integration) std.debug.unlockStderrWriter(); + if (!zig_integration) std.debug.unlockStderr(); } - var comp = aro.Compilation.init(aro_arena, aro_arena, io, &diagnostics, std.fs.cwd()); + var comp = aro.Compilation.init(aro_arena, aro_arena, io, &diagnostics, Io.Dir.cwd()); defer comp.deinit(); var argv: std.ArrayList([]const u8) = .empty; defer argv.deinit(aro_arena); try argv.append(aro_arena, "arocc"); // dummy command name - const resolved_include_paths = try include_paths.get(&error_handler); - try preprocess.appendAroArgs(aro_arena, &argv, options, resolved_include_paths); + const resolved_include_paths = try include_paths.get(&error_handler, &environ_map); + try preprocess.appendAroArgs(aro_arena, &argv, options, resolved_include_paths, &environ_map); try argv.append(aro_arena, switch (options.input_source) { .stdio => "-", .filename => |filename| filename, @@ -175,11 +178,11 @@ pub fn main() !void { std.process.exit(1); }, error.FileTooBig => { - try error_handler.emitMessage(gpa, .err, "failed during preprocessing: maximum file size exceeded", .{}); + try error_handler.emitMessage(gpa, io, .err, "failed during preprocessing: maximum file size exceeded", .{}); std.process.exit(1); }, error.WriteFailed => { - try error_handler.emitMessage(gpa, .err, "failed during preprocessing: error writing the preprocessed output", .{}); + try error_handler.emitMessage(gpa, io, .err, "failed during preprocessing: error writing the preprocessed output", .{}); std.process.exit(1); }, error.OutOfMemory => |e| return e, @@ -191,13 +194,13 @@ pub fn main() !void { .stdio => |file| { var file_reader = file.reader(io, &.{}); break :full_input file_reader.interface.allocRemaining(gpa, .unlimited) catch |err| { - try error_handler.emitMessage(gpa, .err, "unable to read input from stdin: {s}", .{@errorName(err)}); + try error_handler.emitMessage(gpa, io, .err, "unable to read input from stdin: {s}", .{@errorName(err)}); std.process.exit(1); }; }, .filename => |input_filename| { - break :full_input std.fs.cwd().readFileAlloc(input_filename, gpa, .unlimited) catch |err| { - try error_handler.emitMessage(gpa, .err, "unable to read input file path '{s}': {s}", .{ input_filename, @errorName(err) }); + break :full_input Io.Dir.cwd().readFileAlloc(io, input_filename, gpa, .unlimited) catch |err| { + try error_handler.emitMessage(gpa, io, .err, "unable to read input file path '{s}': {s}", .{ input_filename, @errorName(err) }); std.process.exit(1); }; }, @@ -209,10 +212,10 @@ pub fn main() !void { if (options.preprocess == .only) { switch (options.output_source) { .stdio => |output_file| { - try output_file.writeAll(full_input); + try output_file.writeStreamingAll(io, full_input); }, .filename => |output_filename| { - try std.fs.cwd().writeFile(.{ .sub_path = output_filename, .data = full_input }); + try Io.Dir.cwd().writeFile(io, .{ .sub_path = output_filename, .data = full_input }); }, } return; @@ -227,16 +230,16 @@ pub fn main() !void { .source = .{ .memory = .empty }, } else if (options.input_format == .res) - IoStream.fromIoSource(options.input_source, .input) catch |err| { - try error_handler.emitMessage(gpa, .err, "unable to read res file path '{s}': {s}", .{ options.input_source.filename, @errorName(err) }); + IoStream.fromIoSource(io, options.input_source, .input) catch |err| { + try error_handler.emitMessage(gpa, io, .err, "unable to read res file path '{s}': {s}", .{ options.input_source.filename, @errorName(err) }); std.process.exit(1); } else - IoStream.fromIoSource(options.output_source, .output) catch |err| { - try error_handler.emitMessage(gpa, .err, "unable to create output file '{s}': {s}", .{ options.output_source.filename, @errorName(err) }); + IoStream.fromIoSource(io, options.output_source, .output) catch |err| { + try error_handler.emitMessage(gpa, io, .err, "unable to create output file '{s}': {s}", .{ options.output_source.filename, @errorName(err) }); std.process.exit(1); }; - defer res_stream.deinit(gpa); + defer res_stream.deinit(gpa, io); const res_data = res_data: { if (options.input_format != .res) { @@ -246,17 +249,17 @@ pub fn main() !void { var mapping_results = parseAndRemoveLineCommands(gpa, full_input, full_input, .{ .initial_filename = options.input_source.filename }) catch |err| switch (err) { error.InvalidLineCommand => { // TODO: Maybe output the invalid line command - try error_handler.emitMessage(gpa, .err, "invalid line command in the preprocessed source", .{}); + try error_handler.emitMessage(gpa, io, .err, "invalid line command in the preprocessed source", .{}); if (options.preprocess == .no) { - try error_handler.emitMessage(gpa, .note, "line commands must be of the format: #line \"\"", .{}); + try error_handler.emitMessage(gpa, io, .note, "line commands must be of the format: #line \"\"", .{}); } else { - try error_handler.emitMessage(gpa, .note, "this is likely to be a bug, please report it", .{}); + try error_handler.emitMessage(gpa, io, .note, "this is likely to be a bug, please report it", .{}); } std.process.exit(1); }, error.LineNumberOverflow => { // TODO: Better error message - try error_handler.emitMessage(gpa, .err, "line number count exceeded maximum of {}", .{std.math.maxInt(usize)}); + try error_handler.emitMessage(gpa, io, .err, "line number count exceeded maximum of {}", .{std.math.maxInt(usize)}); std.process.exit(1); }, error.OutOfMemory => |e| return e, @@ -272,18 +275,18 @@ pub fn main() !void { defer diagnostics.deinit(); var output_buffer: [4096]u8 = undefined; - var res_stream_writer = res_stream.source.writer(gpa, &output_buffer); + var res_stream_writer = res_stream.source.writer(gpa, io, &output_buffer); defer res_stream_writer.deinit(&res_stream.source); const output_buffered_stream = res_stream_writer.interface(); compile(gpa, io, final_input, output_buffered_stream, .{ - .cwd = std.fs.cwd(), + .cwd = Io.Dir.cwd(), .diagnostics = &diagnostics, .source_mappings = &mapping_results.mappings, .dependencies = maybe_dependencies, .ignore_include_env_var = options.ignore_include_env_var, .extra_include_paths = options.extra_include_paths.items, - .system_include_paths = try include_paths.get(&error_handler), + .system_include_paths = try include_paths.get(&error_handler, &environ_map), .default_language_id = options.default_language_id, .default_code_page = default_code_page, .disjoint_code_page = has_disjoint_code_page, @@ -292,11 +295,11 @@ pub fn main() !void { .max_string_literal_codepoints = options.max_string_literal_codepoints, .silent_duplicate_control_ids = options.silent_duplicate_control_ids, .warn_instead_of_error_on_invalid_code_page = options.warn_instead_of_error_on_invalid_code_page, - }) catch |err| switch (err) { + }, &environ_map) catch |err| switch (err) { error.ParseError, error.CompileError => { - try error_handler.emitDiagnostics(gpa, std.fs.cwd(), final_input, &diagnostics, mapping_results.mappings); + try error_handler.emitDiagnostics(gpa, Io.Dir.cwd(), final_input, &diagnostics, mapping_results.mappings); // Delete the output file on error - res_stream.cleanupAfterError(); + res_stream.cleanupAfterError(io); std.process.exit(1); }, else => |e| return e, @@ -306,19 +309,19 @@ pub fn main() !void { // print any warnings/notes if (!zig_integration) { - diagnostics.renderToStdErr(std.fs.cwd(), final_input, mapping_results.mappings); + try diagnostics.renderToStderr(Io.Dir.cwd(), final_input, mapping_results.mappings); } // write the depfile if (options.depfile_path) |depfile_path| { - var depfile = std.fs.cwd().createFile(depfile_path, .{}) catch |err| { - try error_handler.emitMessage(gpa, .err, "unable to create depfile '{s}': {s}", .{ depfile_path, @errorName(err) }); + var depfile = Io.Dir.cwd().createFile(io, depfile_path, .{}) catch |err| { + try error_handler.emitMessage(gpa, io, .err, "unable to create depfile '{s}': {s}", .{ depfile_path, @errorName(err) }); std.process.exit(1); }; - defer depfile.close(); + defer depfile.close(io); var depfile_buffer: [1024]u8 = undefined; - var depfile_writer = depfile.writer(&depfile_buffer); + var depfile_writer = depfile.writer(io, &depfile_buffer); switch (options.depfile_fmt) { .json => { var write_stream: std.json.Stringify = .{ @@ -340,7 +343,7 @@ pub fn main() !void { if (options.output_format != .coff) return; break :res_data res_stream.source.readAll(gpa, io) catch |err| { - try error_handler.emitMessage(gpa, .err, "unable to read res from '{s}': {s}", .{ res_stream.name, @errorName(err) }); + try error_handler.emitMessage(gpa, io, .err, "unable to read res from '{s}': {s}", .{ res_stream.name, @errorName(err) }); std.process.exit(1); }; }; @@ -353,27 +356,27 @@ pub fn main() !void { var res_reader: std.Io.Reader = .fixed(res_data.bytes); break :resources cvtres.parseRes(gpa, &res_reader, .{ .max_size = res_data.bytes.len }) catch |err| { // TODO: Better errors - try error_handler.emitMessage(gpa, .err, "unable to parse res from '{s}': {s}", .{ res_stream.name, @errorName(err) }); + try error_handler.emitMessage(gpa, io, .err, "unable to parse res from '{s}': {s}", .{ res_stream.name, @errorName(err) }); std.process.exit(1); }; }; defer resources.deinit(); - var coff_stream = IoStream.fromIoSource(options.output_source, .output) catch |err| { - try error_handler.emitMessage(gpa, .err, "unable to create output file '{s}': {s}", .{ options.output_source.filename, @errorName(err) }); + var coff_stream = IoStream.fromIoSource(io, options.output_source, .output) catch |err| { + try error_handler.emitMessage(gpa, io, .err, "unable to create output file '{s}': {s}", .{ options.output_source.filename, @errorName(err) }); std.process.exit(1); }; - defer coff_stream.deinit(gpa); + defer coff_stream.deinit(gpa, io); var coff_output_buffer: [4096]u8 = undefined; - var coff_output_buffered_stream = coff_stream.source.writer(gpa, &coff_output_buffer); + var coff_output_buffered_stream = coff_stream.source.writer(gpa, io, &coff_output_buffer); var cvtres_diagnostics: cvtres.Diagnostics = .{ .none = {} }; cvtres.writeCoff(gpa, coff_output_buffered_stream.interface(), resources.list.items, options.coff_options, &cvtres_diagnostics) catch |err| { switch (err) { error.DuplicateResource => { const duplicate_resource = resources.list.items[cvtres_diagnostics.duplicate_resource]; - try error_handler.emitMessage(gpa, .err, "duplicate resource [id: {f}, type: {f}, language: {f}]", .{ + try error_handler.emitMessage(gpa, io, .err, "duplicate resource [id: {f}, type: {f}, language: {f}]", .{ duplicate_resource.name_value, fmtResourceType(duplicate_resource.type_value), duplicate_resource.language, @@ -381,8 +384,8 @@ pub fn main() !void { }, error.ResourceDataTooLong => { const overflow_resource = resources.list.items[cvtres_diagnostics.duplicate_resource]; - try error_handler.emitMessage(gpa, .err, "resource has a data length that is too large to be written into a coff section", .{}); - try error_handler.emitMessage(gpa, .note, "the resource with the invalid size is [id: {f}, type: {f}, language: {f}]", .{ + try error_handler.emitMessage(gpa, io, .err, "resource has a data length that is too large to be written into a coff section", .{}); + try error_handler.emitMessage(gpa, io, .note, "the resource with the invalid size is [id: {f}, type: {f}, language: {f}]", .{ overflow_resource.name_value, fmtResourceType(overflow_resource.type_value), overflow_resource.language, @@ -390,19 +393,19 @@ pub fn main() !void { }, error.TotalResourceDataTooLong => { const overflow_resource = resources.list.items[cvtres_diagnostics.duplicate_resource]; - try error_handler.emitMessage(gpa, .err, "total resource data exceeds the maximum of the coff 'size of raw data' field", .{}); - try error_handler.emitMessage(gpa, .note, "size overflow occurred when attempting to write this resource: [id: {f}, type: {f}, language: {f}]", .{ + try error_handler.emitMessage(gpa, io, .err, "total resource data exceeds the maximum of the coff 'size of raw data' field", .{}); + try error_handler.emitMessage(gpa, io, .note, "size overflow occurred when attempting to write this resource: [id: {f}, type: {f}, language: {f}]", .{ overflow_resource.name_value, fmtResourceType(overflow_resource.type_value), overflow_resource.language, }); }, else => { - try error_handler.emitMessage(gpa, .err, "unable to write coff output file '{s}': {s}", .{ coff_stream.name, @errorName(err) }); + try error_handler.emitMessage(gpa, io, .err, "unable to write coff output file '{s}': {s}", .{ coff_stream.name, @errorName(err) }); }, } // Delete the output file on error - coff_stream.cleanupAfterError(); + coff_stream.cleanupAfterError(io); std.process.exit(1); }; @@ -416,58 +419,58 @@ const IoStream = struct { pub const IoDirection = enum { input, output }; - pub fn fromIoSource(source: cli.Options.IoSource, io: IoDirection) !IoStream { + pub fn fromIoSource(io: Io, source: cli.Options.IoSource, io_direction: IoDirection) !IoStream { return .{ .name = switch (source) { .filename => |filename| filename, - .stdio => switch (io) { + .stdio => switch (io_direction) { .input => "", .output => "", }, }, .intermediate = false, - .source = try Source.fromIoSource(source, io), + .source = try Source.fromIoSource(io, source, io_direction), }; } - pub fn deinit(self: *IoStream, allocator: Allocator) void { - self.source.deinit(allocator); + pub fn deinit(self: *IoStream, allocator: Allocator, io: Io) void { + self.source.deinit(allocator, io); } - pub fn cleanupAfterError(self: *IoStream) void { + pub fn cleanupAfterError(self: *IoStream, io: Io) void { switch (self.source) { .file => |file| { // Delete the output file on error - file.close(); + file.close(io); // Failing to delete is not really a big deal, so swallow any errors - std.fs.cwd().deleteFile(self.name) catch {}; + Io.Dir.cwd().deleteFile(io, self.name) catch {}; }, .stdio, .memory, .closed => return, } } pub const Source = union(enum) { - file: std.fs.File, - stdio: std.fs.File, + file: Io.File, + stdio: Io.File, memory: std.ArrayList(u8), /// The source has been closed and any usage of the Source in this state is illegal (except deinit). closed: void, - pub fn fromIoSource(source: cli.Options.IoSource, io: IoDirection) !Source { + pub fn fromIoSource(io: Io, source: cli.Options.IoSource, io_direction: IoDirection) !Source { switch (source) { .filename => |filename| return .{ - .file = switch (io) { - .input => try openFileNotDir(std.fs.cwd(), filename, .{}), - .output => try std.fs.cwd().createFile(filename, .{}), + .file = switch (io_direction) { + .input => try openFileNotDir(Io.Dir.cwd(), io, filename, .{}), + .output => try Io.Dir.cwd().createFile(io, filename, .{}), }, }, .stdio => |file| return .{ .stdio = file }, } } - pub fn deinit(self: *Source, allocator: Allocator) void { + pub fn deinit(self: *Source, allocator: Allocator, io: Io) void { switch (self.*) { - .file => |file| file.close(), + .file => |file| file.close(io), .stdio => {}, .memory => |*list| list.deinit(allocator), .closed => {}, @@ -500,10 +503,10 @@ const IoStream = struct { } pub const Writer = union(enum) { - file: std.fs.File.Writer, + file: Io.File.Writer, allocating: std.Io.Writer.Allocating, - pub const Error = Allocator.Error || std.fs.File.WriteError; + pub const Error = Allocator.Error || Io.File.WriteError; pub fn interface(this: *@This()) *std.Io.Writer { return switch (this.*) { @@ -521,9 +524,9 @@ const IoStream = struct { } }; - pub fn writer(source: *Source, allocator: Allocator, buffer: []u8) Writer { + pub fn writer(source: *Source, allocator: Allocator, io: Io, buffer: []u8) Writer { return switch (source.*) { - .file, .stdio => |file| .{ .file = file.writer(buffer) }, + .file, .stdio => |file| .{ .file = file.writer(io, buffer) }, .memory => |*list| .{ .allocating = .fromArrayList(allocator, list) }, .closed => unreachable, }; @@ -539,27 +542,38 @@ const LazyIncludePaths = struct { target_machine_type: std.coff.IMAGE.FILE.MACHINE, resolved_include_paths: ?[]const []const u8 = null, - pub fn get(self: *LazyIncludePaths, error_handler: *ErrorHandler) ![]const []const u8 { + pub fn get( + self: *LazyIncludePaths, + error_handler: *ErrorHandler, + environ_map: *const std.process.Environ.Map, + ) ![]const []const u8 { const io = self.io; if (self.resolved_include_paths) |include_paths| return include_paths; - return getIncludePaths(self.arena, io, self.auto_includes_option, self.zig_lib_dir, self.target_machine_type) catch |err| switch (err) { + return getIncludePaths( + self.arena, + io, + self.auto_includes_option, + self.zig_lib_dir, + self.target_machine_type, + environ_map, + ) catch |err| switch (err) { error.OutOfMemory => |e| return e, else => |e| { switch (e) { error.UnsupportedAutoIncludesMachineType => { - try error_handler.emitMessage(self.arena, .err, "automatic include path detection is not supported for target '{s}'", .{@tagName(self.target_machine_type)}); + try error_handler.emitMessage(self.arena, io, .err, "automatic include path detection is not supported for target '{s}'", .{@tagName(self.target_machine_type)}); }, error.MsvcIncludesNotFound => { - try error_handler.emitMessage(self.arena, .err, "MSVC include paths could not be automatically detected", .{}); + try error_handler.emitMessage(self.arena, io, .err, "MSVC include paths could not be automatically detected", .{}); }, error.MingwIncludesNotFound => { - try error_handler.emitMessage(self.arena, .err, "MinGW include paths could not be automatically detected", .{}); + try error_handler.emitMessage(self.arena, io, .err, "MinGW include paths could not be automatically detected", .{}); }, } - try error_handler.emitMessage(self.arena, .note, "to disable auto includes, use the option /:auto-includes none", .{}); + try error_handler.emitMessage(self.arena, io, .note, "to disable auto includes, use the option /:auto-includes none", .{}); std.process.exit(1); }, }; @@ -572,6 +586,7 @@ fn getIncludePaths( auto_includes_option: cli.Options.AutoIncludes, zig_lib_dir: []const u8, target_machine_type: std.coff.IMAGE.FILE.MACHINE, + environ_map: *const std.process.Environ.Map, ) ![]const []const u8 { if (auto_includes_option == .none) return &[_][]const u8{}; @@ -618,7 +633,7 @@ fn getIncludePaths( }; const target = std.zig.resolveTargetQueryOrFatal(io, target_query); const is_native_abi = target_query.isNativeAbi(); - const detected_libc = std.zig.LibCDirs.detect(arena, zig_lib_dir, &target, is_native_abi, true, null) catch { + const detected_libc = std.zig.LibCDirs.detect(arena, io, zig_lib_dir, &target, is_native_abi, true, null, environ_map) catch { if (includes == .any) { // fall back to mingw includes = .gnu; @@ -644,7 +659,16 @@ fn getIncludePaths( }; const target = std.zig.resolveTargetQueryOrFatal(io, target_query); const is_native_abi = target_query.isNativeAbi(); - const detected_libc = std.zig.LibCDirs.detect(arena, zig_lib_dir, &target, is_native_abi, true, null) catch |err| switch (err) { + const detected_libc = std.zig.LibCDirs.detect( + arena, + io, + zig_lib_dir, + &target, + is_native_abi, + true, + null, + environ_map, + ) catch |err| switch (err) { error.OutOfMemory => |e| return e, else => return error.MingwIncludesNotFound, }; @@ -664,6 +688,7 @@ const ErrorHandler = union(enum) { pub fn emitCliDiagnostics( self: *ErrorHandler, allocator: Allocator, + io: Io, args: []const []const u8, diagnostics: *cli.Diagnostics, ) !void { @@ -674,7 +699,7 @@ const ErrorHandler = union(enum) { try server.serveErrorBundle(error_bundle); }, - .stderr => diagnostics.renderToStdErr(args), + .stderr => return diagnostics.renderToStderr(io, args), } } @@ -684,6 +709,7 @@ const ErrorHandler = union(enum) { fail_msg: []const u8, comp: *aro.Compilation, ) !void { + const io = comp.io; switch (self.*) { .server => |*server| { var error_bundle = try compiler_util.aroDiagnosticsToErrorBundle( @@ -697,9 +723,9 @@ const ErrorHandler = union(enum) { }, .stderr => { // aro errors have already been emitted - const stderr, const ttyconf = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); - try renderErrorMessage(stderr, ttyconf, .err, "{s}", .{fail_msg}); + const stderr = try io.lockStderr(&.{}, null); + defer io.unlockStderr(); + try renderErrorMessage(stderr.terminal(), .err, "{s}", .{fail_msg}); }, } } @@ -707,7 +733,7 @@ const ErrorHandler = union(enum) { pub fn emitDiagnostics( self: *ErrorHandler, allocator: Allocator, - cwd: std.fs.Dir, + cwd: Io.Dir, source: []const u8, diagnostics: *Diagnostics, mappings: SourceMappings, @@ -719,13 +745,14 @@ const ErrorHandler = union(enum) { try server.serveErrorBundle(error_bundle); }, - .stderr => diagnostics.renderToStdErr(cwd, source, mappings), + .stderr => return diagnostics.renderToStderr(cwd, source, mappings), } } pub fn emitMessage( self: *ErrorHandler, allocator: Allocator, + io: Io, msg_type: @import("utils.zig").ErrorMessageType, comptime format: []const u8, args: anytype, @@ -741,9 +768,9 @@ const ErrorHandler = union(enum) { try server.serveErrorBundle(error_bundle); }, .stderr => { - const stderr, const ttyconf = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); - try renderErrorMessage(stderr, ttyconf, msg_type, format, args); + const stderr = try io.lockStderr(&.{}, null); + defer io.unlockStderr(); + try renderErrorMessage(stderr.terminal(), msg_type, format, args); }, } } diff --git a/lib/compiler/resinator/preprocess.zig b/lib/compiler/resinator/preprocess.zig index a67721a7e1c6..1d8c038b60ea 100644 --- a/lib/compiler/resinator/preprocess.zig +++ b/lib/compiler/resinator/preprocess.zig @@ -86,7 +86,7 @@ fn hasAnyErrors(comp: *aro.Compilation) bool { /// `arena` is used for temporary -D argument strings and the INCLUDE environment variable. /// The arena should be kept alive at least as long as `argv`. -pub fn appendAroArgs(arena: Allocator, argv: *std.ArrayList([]const u8), options: cli.Options, system_include_paths: []const []const u8) !void { +pub fn appendAroArgs(arena: Allocator, argv: *std.ArrayList([]const u8), options: cli.Options, system_include_paths: []const []const u8, environ_map: *const std.process.Environ.Map) !void { try argv.appendSlice(arena, &.{ "-E", "--comments", @@ -109,7 +109,7 @@ pub fn appendAroArgs(arena: Allocator, argv: *std.ArrayList([]const u8), options } if (!options.ignore_include_env_var) { - const INCLUDE = std.process.getEnvVarOwned(arena, "INCLUDE") catch ""; + const INCLUDE = environ_map.get("INCLUDE") orelse ""; // The only precedence here is llvm-rc which also uses the platform-specific // delimiter. There's no precedence set by `rc.exe` since it's Windows-only. diff --git a/lib/compiler/resinator/utils.zig b/lib/compiler/resinator/utils.zig index 021b8cf4de1f..42d3cc5e31b6 100644 --- a/lib/compiler/resinator/utils.zig +++ b/lib/compiler/resinator/utils.zig @@ -1,6 +1,8 @@ -const std = @import("std"); const builtin = @import("builtin"); +const std = @import("std"); +const Io = std.Io; + pub const UncheckedSliceWriter = struct { const Self = @This(); @@ -23,19 +25,20 @@ pub const UncheckedSliceWriter = struct { } }; -/// Cross-platform 'std.fs.Dir.openFile' wrapper that will always return IsDir if +/// Cross-platform 'Io.Dir.openFile' wrapper that will always return IsDir if /// a directory is attempted to be opened. /// TODO: Remove once https://github.com/ziglang/zig/issues/5732 is addressed. pub fn openFileNotDir( - cwd: std.fs.Dir, + cwd: Io.Dir, + io: Io, path: []const u8, - flags: std.fs.File.OpenFlags, -) (std.fs.File.OpenError || std.fs.File.StatError)!std.fs.File { - const file = try cwd.openFile(path, flags); - errdefer file.close(); + flags: Io.File.OpenFlags, +) (Io.File.OpenError || Io.File.StatError)!Io.File { + const file = try cwd.openFile(io, path, flags); + errdefer file.close(io); // https://github.com/ziglang/zig/issues/5732 if (builtin.os.tag != .windows) { - const stat = try file.stat(); + const stat = try file.stat(io); if (stat.kind == .directory) return error.IsDir; @@ -89,31 +92,32 @@ pub const ErrorMessageType = enum { err, warning, note }; /// Used for generic colored errors/warnings/notes, more context-specific error messages /// are handled elsewhere. -pub fn renderErrorMessage(writer: *std.Io.Writer, config: std.Io.tty.Config, msg_type: ErrorMessageType, comptime format: []const u8, args: anytype) !void { +pub fn renderErrorMessage(t: Io.Terminal, msg_type: ErrorMessageType, comptime format: []const u8, args: anytype) !void { + const writer = t.writer; switch (msg_type) { .err => { - try config.setColor(writer, .bold); - try config.setColor(writer, .red); + try t.setColor(.bold); + try t.setColor(.red); try writer.writeAll("error: "); }, .warning => { - try config.setColor(writer, .bold); - try config.setColor(writer, .yellow); + try t.setColor(.bold); + try t.setColor(.yellow); try writer.writeAll("warning: "); }, .note => { - try config.setColor(writer, .reset); - try config.setColor(writer, .cyan); + try t.setColor(.reset); + try t.setColor(.cyan); try writer.writeAll("note: "); }, } - try config.setColor(writer, .reset); + try t.setColor(.reset); if (msg_type == .err) { - try config.setColor(writer, .bold); + try t.setColor(.bold); } try writer.print(format, args); try writer.writeByte('\n'); - try config.setColor(writer, .reset); + try t.setColor(.reset); } pub fn isLineEndingPair(first: u8, second: u8) bool { diff --git a/lib/compiler/std-docs.zig b/lib/compiler/std-docs.zig index 12825146a2b6..55f49c44e27d 100644 --- a/lib/compiler/std-docs.zig +++ b/lib/compiler/std-docs.zig @@ -1,12 +1,14 @@ const builtin = @import("builtin"); + const std = @import("std"); +const Io = std.Io; const mem = std.mem; const Allocator = std.mem.Allocator; const assert = std.debug.assert; const Cache = std.Build.Cache; -fn usage() noreturn { - std.fs.File.stdout().writeAll( +fn usage(io: Io) noreturn { + Io.File.stdout().writeStreamingAll(io, \\Usage: zig std [options] \\ \\Options: @@ -19,33 +21,30 @@ fn usage() noreturn { std.process.exit(1); } -pub fn main() !void { - var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena_instance.deinit(); - const arena = arena_instance.allocator(); - - var general_purpose_allocator: std.heap.GeneralPurposeAllocator(.{}) = .init; - const gpa = general_purpose_allocator.allocator(); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const gpa = init.gpa; + const io = init.io; - var argv = try std.process.argsWithAllocator(arena); + var argv = try init.minimal.args.iterateAllocator(arena); defer argv.deinit(); assert(argv.skip()); const zig_lib_directory = argv.next().?; const zig_exe_path = argv.next().?; const global_cache_path = argv.next().?; - var lib_dir = try std.fs.cwd().openDir(zig_lib_directory, .{}); - defer lib_dir.close(); + var lib_dir = try Io.Dir.cwd().openDir(io, zig_lib_directory, .{}); + defer lib_dir.close(io); var listen_port: u16 = 0; var force_open_browser: ?bool = null; while (argv.next()) |arg| { if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { - usage(); + usage(io); } else if (mem.eql(u8, arg, "-p") or mem.eql(u8, arg, "--port")) { - listen_port = std.fmt.parseInt(u16, argv.next() orelse usage(), 10) catch |err| { + listen_port = std.fmt.parseInt(u16, argv.next() orelse usage(io), 10) catch |err| { std.log.err("expected port number: {}", .{err}); - usage(); + usage(io); }; } else if (mem.eql(u8, arg, "--open-browser")) { force_open_browser = true; @@ -53,69 +52,70 @@ pub fn main() !void { force_open_browser = false; } else { std.log.err("unrecognized argument: {s}", .{arg}); - usage(); + usage(io); } } const should_open_browser = force_open_browser orelse (listen_port == 0); - const address = std.net.Address.parseIp("127.0.0.1", listen_port) catch unreachable; - var http_server = try address.listen(.{ + const address = Io.net.IpAddress.parse("127.0.0.1", listen_port) catch unreachable; + var http_server = try address.listen(io, .{ .reuse_address = true, }); - const port = http_server.listen_address.in.getPort(); + const port = http_server.socket.address.getPort(); const url_with_newline = try std.fmt.allocPrint(arena, "http://127.0.0.1:{d}/\n", .{port}); - std.fs.File.stdout().writeAll(url_with_newline) catch {}; + Io.File.stdout().writeStreamingAll(io, url_with_newline) catch {}; if (should_open_browser) { - openBrowserTab(gpa, url_with_newline[0 .. url_with_newline.len - 1 :'\n']) catch |err| { - std.log.err("unable to open browser: {s}", .{@errorName(err)}); + openBrowserTab(io, url_with_newline[0 .. url_with_newline.len - 1 :'\n']) catch |err| { + std.log.err("unable to open browser: {t}", .{err}); }; } var context: Context = .{ .gpa = gpa, + .io = io, .zig_exe_path = zig_exe_path, .global_cache_path = global_cache_path, .lib_dir = lib_dir, .zig_lib_directory = zig_lib_directory, }; + var group: Io.Group = .init; + defer group.cancel(io); + while (true) { - const connection = try http_server.accept(); - _ = std.Thread.spawn(.{}, accept, .{ &context, connection }) catch |err| { - std.log.err("unable to accept connection: {s}", .{@errorName(err)}); - connection.stream.close(); - continue; - }; + const stream = try http_server.accept(io); + group.async(io, accept, .{ &context, stream }); } } -fn accept(context: *Context, connection: std.net.Server.Connection) void { - defer connection.stream.close(); +fn accept(context: *Context, stream: Io.net.Stream) void { + const io = context.io; + defer stream.close(io); var recv_buffer: [4000]u8 = undefined; var send_buffer: [4000]u8 = undefined; - var conn_reader = connection.stream.reader(&recv_buffer); - var conn_writer = connection.stream.writer(&send_buffer); - var server = std.http.Server.init(conn_reader.interface(), &conn_writer.interface); + var conn_reader = stream.reader(io, &recv_buffer); + var conn_writer = stream.writer(io, &send_buffer); + var server = std.http.Server.init(&conn_reader.interface, &conn_writer.interface); while (server.reader.state == .ready) { var request = server.receiveHead() catch |err| switch (err) { error.HttpConnectionClosing => return, else => { - std.log.err("closing http connection: {s}", .{@errorName(err)}); + std.log.err("closing http connection: {t}", .{err}); return; }, }; serveRequest(&request, context) catch |err| switch (err) { error.WriteFailed => { if (conn_writer.err) |e| { - std.log.err("unable to serve {s}: {s}", .{ request.head.target, @errorName(e) }); + std.log.err("unable to serve {s}: {t}", .{ request.head.target, e }); } else { - std.log.err("unable to serve {s}: {s}", .{ request.head.target, @errorName(err) }); + std.log.err("unable to serve {s}: {t}", .{ request.head.target, err }); } return; }, else => { - std.log.err("unable to serve {s}: {s}", .{ request.head.target, @errorName(err) }); + std.log.err("unable to serve {s}: {t}", .{ request.head.target, err }); return; }, }; @@ -124,7 +124,8 @@ fn accept(context: *Context, connection: std.net.Server.Connection) void { const Context = struct { gpa: Allocator, - lib_dir: std.fs.Dir, + io: Io, + lib_dir: Io.Dir, zig_lib_directory: []const u8, zig_exe_path: []const u8, global_cache_path: []const u8, @@ -170,10 +171,11 @@ fn serveDocsFile( content_type: []const u8, ) !void { const gpa = context.gpa; + const io = context.io; // The desired API is actually sendfile, which will require enhancing std.http.Server. // We load the file with every request so that the user can make changes to the file // and refresh the HTML page without restarting this server. - const file_contents = try context.lib_dir.readFileAlloc(name, gpa, .limited(10 * 1024 * 1024)); + const file_contents = try context.lib_dir.readFileAlloc(io, name, gpa, .limited(10 * 1024 * 1024)); defer gpa.free(file_contents); try request.respond(file_contents, .{ .extra_headers = &.{ @@ -185,6 +187,7 @@ fn serveDocsFile( fn serveSourcesTar(request: *std.http.Server.Request, context: *Context) !void { const gpa = context.gpa; + const io = context.io; var send_buffer: [0x4000]u8 = undefined; var response = try request.respondStreaming(&send_buffer, .{ @@ -196,8 +199,8 @@ fn serveSourcesTar(request: *std.http.Server.Request, context: *Context) !void { }, }); - var std_dir = try context.lib_dir.openDir("std", .{ .iterate = true }); - defer std_dir.close(); + var std_dir = try context.lib_dir.openDir(io, "std", .{ .iterate = true }); + defer std_dir.close(io); var walker = try std_dir.walk(gpa); defer walker.deinit(); @@ -205,7 +208,7 @@ fn serveSourcesTar(request: *std.http.Server.Request, context: *Context) !void { var archiver: std.tar.Writer = .{ .underlying_writer = &response.writer }; archiver.prefix = "std"; - while (try walker.next()) |entry| { + while (try walker.next(io)) |entry| { switch (entry.kind) { .file => { if (!std.mem.endsWith(u8, entry.basename, ".zig")) @@ -215,15 +218,16 @@ fn serveSourcesTar(request: *std.http.Server.Request, context: *Context) !void { }, else => continue, } - var file = try entry.dir.openFile(entry.basename, .{}); - defer file.close(); - const stat = try file.stat(); - var file_reader: std.fs.File.Reader = .{ + var file = try entry.dir.openFile(io, entry.basename, .{}); + defer file.close(io); + const stat = try file.stat(io); + var file_reader: Io.File.Reader = .{ + .io = io, .file = file, - .interface = std.fs.File.Reader.initInterface(&.{}), + .interface = Io.File.Reader.initInterface(&.{}), .size = stat.size, }; - try archiver.writeFile(entry.path, &file_reader, stat.mtime); + try archiver.writeFileTimestamp(entry.path, &file_reader, stat.mtime); } { @@ -245,6 +249,7 @@ fn serveWasm( optimize_mode: std.builtin.OptimizeMode, ) !void { const gpa = context.gpa; + const io = context.io; var arena_instance = std.heap.ArenaAllocator.init(gpa); defer arena_instance.deinit(); @@ -255,7 +260,7 @@ fn serveWasm( const wasm_base_path = try buildWasmBinary(arena, context, optimize_mode); const bin_name = try std.zig.binNameAlloc(arena, .{ .root_name = autodoc_root_name, - .target = &(std.zig.system.resolveTargetQuery(std.Build.parseTargetQuery(.{ + .target = &(std.zig.system.resolveTargetQuery(io, std.Build.parseTargetQuery(.{ .arch_os_abi = autodoc_arch_os_abi, .cpu_features = autodoc_cpu_features, }) catch unreachable) catch unreachable), @@ -263,7 +268,7 @@ fn serveWasm( }); // std.http.Server does not have a sendfile API yet. const bin_path = try wasm_base_path.join(arena, bin_name); - const file_contents = try bin_path.root_dir.handle.readFileAlloc(bin_path.sub_path, gpa, .limited(10 * 1024 * 1024)); + const file_contents = try bin_path.root_dir.handle.readFileAlloc(io, bin_path.sub_path, gpa, .limited(10 * 1024 * 1024)); defer gpa.free(file_contents); try request.respond(file_contents, .{ .extra_headers = &.{ @@ -283,6 +288,7 @@ fn buildWasmBinary( optimize_mode: std.builtin.OptimizeMode, ) !Cache.Path { const gpa = context.gpa; + const io = context.io; var argv: std.ArrayList([]const u8) = .empty; @@ -311,20 +317,21 @@ fn buildWasmBinary( "--listen=-", // }); - var child = std.process.Child.init(argv.items, gpa); - child.stdin_behavior = .Pipe; - child.stdout_behavior = .Pipe; - child.stderr_behavior = .Pipe; - try child.spawn(); + var child = try std.process.spawn(io, .{ + .argv = argv.items, + .stdin = .pipe, + .stdout = .pipe, + .stderr = .pipe, + }); - var poller = std.Io.poll(gpa, enum { stdout, stderr }, .{ + var poller = Io.poll(gpa, enum { stdout, stderr }, .{ .stdout = child.stdout.?, .stderr = child.stderr.?, }); defer poller.deinit(); - try sendMessage(child.stdin.?, .update); - try sendMessage(child.stdin.?, .exit); + try sendMessage(io, child.stdin.?, .update); + try sendMessage(io, child.stdin.?, .exit); var result: ?Cache.Path = null; var result_error_bundle = std.zig.ErrorBundle.empty; @@ -348,7 +355,7 @@ fn buildWasmBinary( result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body); }, .emit_digest => { - var r: std.Io.Reader = .fixed(body); + var r: Io.Reader = .fixed(body); const emit_digest = r.takeStruct(std.zig.Server.Message.EmitDigest, .little) catch unreachable; if (!emit_digest.flags.cache_hit) { std.log.info("source changes detected; rebuilt wasm component", .{}); @@ -371,72 +378,81 @@ fn buildWasmBinary( } // Send EOF to stdin. - child.stdin.?.close(); + child.stdin.?.close(io); child.stdin = null; - switch (try child.wait()) { - .Exited => |code| { + switch (try child.wait(io)) { + .exited => |code| { if (code != 0) { std.log.err( "the following command exited with error code {d}:\n{s}", - .{ code, try std.Build.Step.allocPrintCmd(arena, null, argv.items) }, + .{ code, try std.Build.Step.allocPrintCmd(arena, null, null, argv.items) }, ); return error.WasmCompilationFailed; } }, - .Signal, .Stopped, .Unknown => { + .signal => |sig| { + std.log.err( + "the following command terminated with signal {t}:\n{s}", + .{ sig, try std.Build.Step.allocPrintCmd(arena, null, null, argv.items) }, + ); + return error.WasmCompilationFailed; + }, + .stopped, .unknown => { std.log.err( "the following command terminated unexpectedly:\n{s}", - .{try std.Build.Step.allocPrintCmd(arena, null, argv.items)}, + .{try std.Build.Step.allocPrintCmd(arena, null, null, argv.items)}, ); return error.WasmCompilationFailed; }, } if (result_error_bundle.errorMessageCount() > 0) { - result_error_bundle.renderToStdErr(.{}, true); + try result_error_bundle.renderToStderr(io, .{}, .auto); std.log.err("the following command failed with {d} compilation errors:\n{s}", .{ result_error_bundle.errorMessageCount(), - try std.Build.Step.allocPrintCmd(arena, null, argv.items), + try std.Build.Step.allocPrintCmd(arena, null, null, argv.items), }); return error.WasmCompilationFailed; } return result orelse { std.log.err("child process failed to report result\n{s}", .{ - try std.Build.Step.allocPrintCmd(arena, null, argv.items), + try std.Build.Step.allocPrintCmd(arena, null, null, argv.items), }); return error.WasmCompilationFailed; }; } -fn sendMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag) !void { +fn sendMessage(io: Io, file: Io.File, tag: std.zig.Client.Message.Tag) !void { const header: std.zig.Client.Message.Header = .{ .tag = tag, .bytes_len = 0, }; - var w = file.writer(&.{}); + var w = file.writer(io, &.{}); w.interface.writeStruct(header, .little) catch |err| switch (err) { error.WriteFailed => return w.err.?, }; } -fn openBrowserTab(gpa: Allocator, url: []const u8) !void { +fn openBrowserTab(io: Io, url: []const u8) !void { // Until https://github.com/ziglang/zig/issues/19205 is implemented, we - // spawn a thread for this child process. - _ = try std.Thread.spawn(.{}, openBrowserTabThread, .{ gpa, url }); + // spawn and then leak a concurrent task for this child process. + const future = try io.concurrent(openBrowserTabTask, .{ io, url }); + _ = future; // leak it } -fn openBrowserTabThread(gpa: Allocator, url: []const u8) !void { +fn openBrowserTabTask(io: Io, url: []const u8) !void { const main_exe = switch (builtin.os.tag) { .windows => "explorer", .macos => "open", else => "xdg-open", }; - var child = std.process.Child.init(&.{ main_exe, url }, gpa); - child.stdin_behavior = .Ignore; - child.stdout_behavior = .Ignore; - child.stderr_behavior = .Ignore; - try child.spawn(); - _ = try child.wait(); + var child = try std.process.spawn(io, .{ + .argv = &.{ main_exe, url }, + .stdin = .ignore, + .stdout = .ignore, + .stderr = .ignore, + }); + _ = try child.wait(io); } diff --git a/lib/compiler/test_runner.zig b/lib/compiler/test_runner.zig index 72ed3e76776d..5885f5cf1265 100644 --- a/lib/compiler/test_runner.zig +++ b/lib/compiler/test_runner.zig @@ -17,7 +17,7 @@ var fba: std.heap.FixedBufferAllocator = .init(&fba_buffer); var fba_buffer: [8192]u8 = undefined; var stdin_buffer: [4096]u8 = undefined; var stdout_buffer: [4096]u8 = undefined; -var runner_threaded_io: Io.Threaded = .init_single_threaded; +const runner_threaded_io: Io = Io.Threaded.global_single_threaded.ioBasic(); /// Keep in sync with logic in `std.Build.addRunArtifact` which decides whether /// the test runner will communicate with the build runner via `std.zig.Server`. @@ -29,7 +29,7 @@ const need_simple = switch (builtin.zig_backend) { else => false, }; -pub fn main() void { +pub fn main(init: std.process.Init.Minimal) void { @disableInstrumentation(); if (builtin.cpu.arch.isSpirV()) { @@ -38,11 +38,10 @@ pub fn main() void { } if (need_simple) { - return mainSimple() catch @panic("test failure\n"); + return mainSimple() catch @panic("test failure"); } - const args = std.process.argsAlloc(fba.allocator()) catch - @panic("unable to parse command line args"); + const args = init.args.toSlice(fba.allocator()) catch @panic("unable to parse command line args"); var listen = false; var opt_cache_dir: ?[]const u8 = null; @@ -66,16 +65,16 @@ pub fn main() void { } if (listen) { - return mainServer() catch @panic("internal test runner failure"); + return mainServer(init) catch @panic("internal test runner failure"); } else { - return mainTerminal(); + return mainTerminal(init); } } -fn mainServer() !void { +fn mainServer(init: std.process.Init.Minimal) !void { @disableInstrumentation(); - var stdin_reader = std.fs.File.stdin().readerStreaming(runner_threaded_io.io(), &stdin_buffer); - var stdout_writer = std.fs.File.stdout().writerStreaming(&stdout_buffer); + var stdin_reader = Io.File.stdin().readerStreaming(runner_threaded_io, &stdin_buffer); + var stdout_writer = Io.File.stdout().writerStreaming(runner_threaded_io, &stdout_buffer); var server = try std.zig.Server.init(.{ .in = &stdin_reader.interface, .out = &stdout_writer.interface, @@ -131,7 +130,10 @@ fn mainServer() !void { .run_test => { testing.allocator_instance = .{}; - testing.io_instance = .init(testing.allocator); + testing.io_instance = .init(testing.allocator, .{ + .argv0 = .init(init.args), + .environ = init.environ, + }); log_err_count = 0; const index = try server.receiveBody_u32(); const test_fn = builtin.test_functions[index]; @@ -215,7 +217,7 @@ fn mainServer() !void { } } -fn mainTerminal() void { +fn mainTerminal(init: std.process.Init.Minimal) void { @disableInstrumentation(); if (builtin.fuzz) @panic("fuzz test requires server"); @@ -224,16 +226,19 @@ fn mainTerminal() void { var skip_count: usize = 0; var fail_count: usize = 0; var fuzz_count: usize = 0; - const root_node = if (builtin.fuzz) std.Progress.Node.none else std.Progress.start(.{ + const root_node = if (builtin.fuzz) std.Progress.Node.none else std.Progress.start(runner_threaded_io, .{ .root_name = "Test", .estimated_total_items = test_fn_list.len, }); - const have_tty = std.fs.File.stderr().isTty(); + const have_tty = Io.File.stderr().isTty(runner_threaded_io) catch unreachable; var leaks: usize = 0; for (test_fn_list, 0..) |test_fn, i| { testing.allocator_instance = .{}; - testing.io_instance = .init(testing.allocator); + testing.io_instance = .init(testing.allocator, .{ + .argv0 = .init(init.args), + .environ = init.environ, + }); defer { testing.io_instance.deinit(); if (testing.allocator_instance.deinit() == .leak) leaks += 1; @@ -318,7 +323,7 @@ pub fn log( /// work-in-progress backends can handle it. pub fn mainSimple() anyerror!void { @disableInstrumentation(); - // is the backend capable of calling `std.fs.File.writeAll`? + // is the backend capable of calling `Io.File.writeAll`? const enable_write = switch (builtin.zig_backend) { .stage2_aarch64, .stage2_riscv64 => true, else => false, @@ -329,35 +334,37 @@ pub fn mainSimple() anyerror!void { else => false, }; + testing.io_instance = .init(testing.allocator, .{}); + var passed: u64 = 0; var skipped: u64 = 0; var failed: u64 = 0; // we don't want to bring in File and Writer if the backend doesn't support it - const stdout = if (enable_write) std.fs.File.stdout() else {}; + const stdout = if (enable_write) Io.File.stdout() else {}; for (builtin.test_functions) |test_fn| { if (enable_write) { - stdout.writeAll(test_fn.name) catch {}; - stdout.writeAll("... ") catch {}; + stdout.writeStreamingAll(runner_threaded_io, test_fn.name) catch {}; + stdout.writeStreamingAll(runner_threaded_io, "... ") catch {}; } if (test_fn.func()) |_| { - if (enable_write) stdout.writeAll("PASS\n") catch {}; + if (enable_write) stdout.writeStreamingAll(runner_threaded_io, "PASS\n") catch {}; } else |err| { if (err != error.SkipZigTest) { - if (enable_write) stdout.writeAll("FAIL\n") catch {}; + if (enable_write) stdout.writeStreamingAll(runner_threaded_io, "FAIL\n") catch {}; failed += 1; if (!enable_write) return err; continue; } - if (enable_write) stdout.writeAll("SKIP\n") catch {}; + if (enable_write) stdout.writeStreamingAll(runner_threaded_io, "SKIP\n") catch {}; skipped += 1; continue; } passed += 1; } if (enable_print) { - var stdout_writer = stdout.writer(&.{}); + var stdout_writer = stdout.writer(runner_threaded_io, &.{}); stdout_writer.interface.print("{} passed, {} skipped, {} failed\n", .{ passed, skipped, failed }) catch {}; } if (failed != 0) std.process.exit(1); @@ -405,15 +412,19 @@ pub fn fuzz( testOne(ctx, input.toSlice()) catch |err| switch (err) { error.SkipZigTest => return, else => { - std.debug.lockStdErr(); - if (@errorReturnTrace()) |trace| std.debug.dumpStackTrace(trace); - std.debug.print("failed with error.{t}\n", .{err}); + const stderr = std.debug.lockStderr(&.{}).terminal(); + p: { + if (@errorReturnTrace()) |trace| { + std.debug.writeStackTrace(trace, stderr) catch break :p; + } + stderr.writer.print("failed with error.{t}\n", .{err}) catch break :p; + } std.process.exit(1); }, }; if (log_err_count != 0) { - std.debug.lockStdErr(); - std.debug.print("error logs detected\n", .{}); + const stderr = std.debug.lockStderr(&.{}).terminal(); + stderr.writer.print("error logs detected\n", .{}) catch {}; std.process.exit(1); } } diff --git a/lib/compiler/translate-c/main.zig b/lib/compiler/translate-c/main.zig index b0d7a5d9bd51..ce8f4f55c3b6 100644 --- a/lib/compiler/translate-c/main.zig +++ b/lib/compiler/translate-c/main.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; const mem = std.mem; const process = std.process; @@ -8,21 +9,13 @@ const Translator = @import("Translator.zig"); const fast_exit = @import("builtin").mode != .Debug; -var general_purpose_allocator: std.heap.GeneralPurposeAllocator(.{}) = .init; +pub fn main(init: std.process.Init) u8 { + const gpa = init.gpa; + const arena = init.arena.allocator(); + const io = init.io; + const environ_map = init.environ_map; -pub fn main() u8 { - const gpa = general_purpose_allocator.allocator(); - defer _ = general_purpose_allocator.deinit(); - - var arena_instance = std.heap.ArenaAllocator.init(gpa); - defer arena_instance.deinit(); - const arena = arena_instance.allocator(); - - var threaded: std.Io.Threaded = .init(gpa); - defer threaded.deinit(); - const io = threaded.io(); - - const args = process.argsAlloc(arena) catch { + const args = init.minimal.args.toSlice(arena) catch { std.debug.print("ran out of memory allocating arguments\n", .{}); if (fast_exit) process.exit(1); return 1; @@ -33,11 +26,14 @@ pub fn main() u8 { zig_integration = true; } + const NO_COLOR = std.zig.EnvVar.NO_COLOR.isSet(environ_map); + const CLICOLOR_FORCE = std.zig.EnvVar.CLICOLOR_FORCE.isSet(environ_map); + var stderr_buf: [1024]u8 = undefined; - var stderr = std.fs.File.stderr().writer(&stderr_buf); + var stderr = Io.File.stderr().writer(io, &stderr_buf); var diagnostics: aro.Diagnostics = switch (zig_integration) { false => .{ .output = .{ .to_writer = .{ - .color = .detect(stderr.file), + .mode = Io.Terminal.Mode.detect(io, stderr.file, NO_COLOR, CLICOLOR_FORCE) catch unreachable, .writer = &stderr.interface, } } }, true => .{ .output = .{ .to_list = .{ @@ -46,7 +42,7 @@ pub fn main() u8 { }; defer diagnostics.deinit(); - var comp = aro.Compilation.initDefault(gpa, arena, io, &diagnostics, std.fs.cwd()) catch |err| switch (err) { + var comp = aro.Compilation.initDefault(gpa, arena, io, &diagnostics, .cwd(), environ_map) catch |err| switch (err) { error.OutOfMemory => { std.debug.print("ran out of memory initializing C compilation\n", .{}); if (fast_exit) process.exit(1); @@ -68,7 +64,7 @@ pub fn main() u8 { return 1; }, error.FatalError => if (zig_integration) { - serveErrorBundle(arena, &diagnostics) catch |bundle_err| { + serveErrorBundle(arena, io, &diagnostics) catch |bundle_err| { std.debug.print("unable to serve error bundle: {}\n", .{bundle_err}); if (fast_exit) process.exit(1); return 1; @@ -92,14 +88,14 @@ pub fn main() u8 { return @intFromBool(comp.diagnostics.errors != 0); } -fn serveErrorBundle(arena: std.mem.Allocator, diagnostics: *const aro.Diagnostics) !void { +fn serveErrorBundle(arena: std.mem.Allocator, io: Io, diagnostics: *const aro.Diagnostics) !void { const error_bundle = try compiler_util.aroDiagnosticsToErrorBundle( diagnostics, arena, "translation failure", ); var stdout_buffer: [1024]u8 = undefined; - var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); + var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer); var server: std.zig.Server = .{ .out = &stdout_writer.interface, .in = undefined, @@ -119,42 +115,41 @@ pub const usage = \\ ; -fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8, zig_integration: bool) !void { +fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: []const [:0]const u8, zig_integration: bool) !void { const gpa = d.comp.gpa; - - const aro_args = args: { - var i: usize = 0; - for (args) |arg| { - args[i] = arg; - if (mem.eql(u8, arg, "--help")) { - var stdout_buf: [512]u8 = undefined; - var stdout = std.fs.File.stdout().writer(&stdout_buf); - try stdout.interface.print(usage, .{args[0]}); - try stdout.interface.flush(); - return; - } else if (mem.eql(u8, arg, "--version")) { - var stdout_buf: [512]u8 = undefined; - var stdout = std.fs.File.stdout().writer(&stdout_buf); - // TODO add version - try stdout.interface.writeAll("0.0.0-dev\n"); - try stdout.interface.flush(); - return; - } else if (mem.eql(u8, arg, "--zig-integration")) { - if (i != 1 or !zig_integration) - return d.fatal("--zig-integration must be the first argument", .{}); - } else { - i += 1; - } + const io = d.comp.io; + + var aro_args: std.ArrayList([:0]const u8) = .empty; + defer aro_args.deinit(gpa); + + for (args, 0..) |arg, i| { + if (mem.eql(u8, arg, "--help")) { + var stdout_buf: [512]u8 = undefined; + var stdout = Io.File.stdout().writer(io, &stdout_buf); + try stdout.interface.print(usage, .{args[0]}); + try stdout.interface.flush(); + return; + } else if (mem.eql(u8, arg, "--version")) { + var stdout_buf: [512]u8 = undefined; + var stdout = Io.File.stdout().writer(io, &stdout_buf); + // TODO add version + try stdout.interface.writeAll("0.0.0-dev\n"); + try stdout.interface.flush(); + return; + } else if (mem.eql(u8, arg, "--zig-integration")) { + if (i != 1 or !zig_integration) + return d.fatal("--zig-integration must be the first argument", .{}); + } else { + try aro_args.append(gpa, arg); } - break :args args[0..i]; - }; + } const user_macros = macros: { var macro_buf: std.ArrayList(u8) = .empty; defer macro_buf.deinit(gpa); var discard_buf: [256]u8 = undefined; var discarding: std.Io.Writer.Discarding = .init(&discard_buf); - assert(!try d.parseArgs(&discarding.writer, ¯o_buf, aro_args)); + assert(!try d.parseArgs(&discarding.writer, ¯o_buf, aro_args.items)); if (macro_buf.items.len > std.math.maxInt(u32)) { return d.fatal("user provided macro source exceeded max size", .{}); } @@ -224,13 +219,13 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8, zig_integration const dep_file_name = try d.getDepFileName(source, out_buf[0..std.fs.max_name_bytes]); const file = if (dep_file_name) |path| - d.comp.cwd.createFile(path, .{}) catch |er| + d.comp.cwd.createFile(io, path, .{}) catch |er| return d.fatal("unable to create dependency file '{s}': {s}", .{ path, aro.Driver.errorDescription(er) }) else - std.fs.File.stdout(); - defer if (dep_file_name != null) file.close(); + Io.File.stdout(); + defer if (dep_file_name != null) file.close(io); - var file_writer = file.writer(&out_buf); + var file_writer = file.writer(io, &out_buf); dep_file.write(&file_writer.interface) catch return d.fatal("unable to write dependency file: {s}", .{aro.Driver.errorDescription(file_writer.err.?)}); } @@ -245,23 +240,23 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8, zig_integration var close_out_file = false; var out_file_path: []const u8 = ""; - var out_file: std.fs.File = .stdout(); - defer if (close_out_file) out_file.close(); + var out_file: Io.File = .stdout(); + defer if (close_out_file) out_file.close(io); if (d.output_name) |path| blk: { if (std.mem.eql(u8, path, "-")) break :blk; if (std.fs.path.dirname(path)) |dirname| { - std.fs.cwd().makePath(dirname) catch |err| + Io.Dir.cwd().createDirPath(io, dirname) catch |err| return d.fatal("failed to create path to '{s}': {s}", .{ path, aro.Driver.errorDescription(err) }); } - out_file = std.fs.cwd().createFile(path, .{}) catch |err| { + out_file = Io.Dir.cwd().createFile(io, path, .{}) catch |err| { return d.fatal("failed to create output file '{s}': {s}", .{ path, aro.Driver.errorDescription(err) }); }; close_out_file = true; out_file_path = path; } - var out_writer = out_file.writer(&out_buf); + var out_writer = out_file.writer(io, &out_buf); out_writer.interface.writeAll(rendered_zig) catch {}; out_writer.interface.flush() catch {}; if (out_writer.err) |write_err| diff --git a/lib/compiler_rt.zig b/lib/compiler_rt.zig index 040d2c6c411f..87ff89c2d937 100644 --- a/lib/compiler_rt.zig +++ b/lib/compiler_rt.zig @@ -1,7 +1,23 @@ +const std = @import("std"); const builtin = @import("builtin"); const common = @import("compiler_rt/common.zig"); -pub const panic = common.panic; +/// Avoid dragging in the runtime safety mechanisms into this .o file, unless +/// we're trying to test compiler-rt. +pub const panic = if (common.test_safety) + std.debug.FullPanic(std.debug.defaultPanic) +else + std.debug.no_panic; + +pub const std_options_debug_threaded_io: ?*std.Io.Threaded = if (builtin.is_test) + std.Io.Threaded.global_single_threaded +else + null; + +pub const std_options_debug_io: std.Io = if (builtin.is_test) + std.Io.Threaded.global_single_threaded.ioBasic() +else + unreachable; comptime { // Integer routines @@ -215,12 +231,11 @@ comptime { _ = @import("compiler_rt/divtc3.zig"); // Math routines. Alphabetically sorted. - _ = @import("compiler_rt/ceil.zig"); _ = @import("compiler_rt/cos.zig"); _ = @import("compiler_rt/exp.zig"); _ = @import("compiler_rt/exp2.zig"); _ = @import("compiler_rt/fabs.zig"); - _ = @import("compiler_rt/floor.zig"); + _ = @import("compiler_rt/floor_ceil.zig"); _ = @import("compiler_rt/fma.zig"); _ = @import("compiler_rt/fmax.zig"); _ = @import("compiler_rt/fmin.zig"); diff --git a/lib/compiler_rt/absvdi2.zig b/lib/compiler_rt/absvdi2.zig index 8b5e5d8a5de6..add32608e8a3 100644 --- a/lib/compiler_rt/absvdi2.zig +++ b/lib/compiler_rt/absvdi2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const absv = @import("./absv.zig").absv; -pub const panic = common.panic; - comptime { @export(&__absvdi2, .{ .name = "__absvdi2", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/absvsi2.zig b/lib/compiler_rt/absvsi2.zig index 0030813db83c..fb527cd997f6 100644 --- a/lib/compiler_rt/absvsi2.zig +++ b/lib/compiler_rt/absvsi2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const absv = @import("./absv.zig").absv; -pub const panic = common.panic; - comptime { @export(&__absvsi2, .{ .name = "__absvsi2", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/absvti2.zig b/lib/compiler_rt/absvti2.zig index be232ece2ce0..1b2ddaaefac6 100644 --- a/lib/compiler_rt/absvti2.zig +++ b/lib/compiler_rt/absvti2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const absv = @import("./absv.zig").absv; -pub const panic = common.panic; - comptime { @export(&__absvti2, .{ .name = "__absvti2", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/adddf3.zig b/lib/compiler_rt/adddf3.zig index 3a10f555203a..98fba79bbd51 100644 --- a/lib/compiler_rt/adddf3.zig +++ b/lib/compiler_rt/adddf3.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const addf3 = @import("./addf3.zig").addf3; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_dadd, .{ .name = "__aeabi_dadd", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/addhf3.zig b/lib/compiler_rt/addhf3.zig index 48a6328836a2..842c88f5d426 100644 --- a/lib/compiler_rt/addhf3.zig +++ b/lib/compiler_rt/addhf3.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const addf3 = @import("./addf3.zig").addf3; -pub const panic = common.panic; - comptime { @export(&__addhf3, .{ .name = "__addhf3", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/addsf3.zig b/lib/compiler_rt/addsf3.zig index c4b7773eb0f0..ef1627ae7ae0 100644 --- a/lib/compiler_rt/addsf3.zig +++ b/lib/compiler_rt/addsf3.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const addf3 = @import("./addf3.zig").addf3; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_fadd, .{ .name = "__aeabi_fadd", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/addtf3.zig b/lib/compiler_rt/addtf3.zig index 34e5bdf7afd5..d4011f923805 100644 --- a/lib/compiler_rt/addtf3.zig +++ b/lib/compiler_rt/addtf3.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const addf3 = @import("./addf3.zig").addf3; -pub const panic = common.panic; - comptime { if (common.want_ppc_abi) { @export(&__addtf3, .{ .name = "__addkf3", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/addvdi3.zig b/lib/compiler_rt/addvdi3.zig index 03aa9b91c717..e7346b717ff8 100644 --- a/lib/compiler_rt/addvdi3.zig +++ b/lib/compiler_rt/addvdi3.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const testing = @import("std").testing; -pub const panic = common.panic; - comptime { @export(&__addvdi3, .{ .name = "__addvdi3", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/addvsi3.zig b/lib/compiler_rt/addvsi3.zig index e688fdba5844..468047eda1c5 100644 --- a/lib/compiler_rt/addvsi3.zig +++ b/lib/compiler_rt/addvsi3.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const testing = @import("std").testing; -pub const panic = common.panic; - comptime { @export(&__addvsi3, .{ .name = "__addvsi3", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/addxf3.zig b/lib/compiler_rt/addxf3.zig index 1aac73675021..e1509f04f5f6 100644 --- a/lib/compiler_rt/addxf3.zig +++ b/lib/compiler_rt/addxf3.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const addf3 = @import("./addf3.zig").addf3; -pub const panic = common.panic; - comptime { @export(&__addxf3, .{ .name = "__addxf3", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/arm.zig b/lib/compiler_rt/arm.zig index 01775ab06fc9..aa31e855dc13 100644 --- a/lib/compiler_rt/arm.zig +++ b/lib/compiler_rt/arm.zig @@ -6,8 +6,6 @@ const target = builtin.target; const arch = builtin.cpu.arch; const common = @import("common.zig"); -pub const panic = common.panic; - comptime { if (!builtin.is_test) { if (arch.isArm()) { diff --git a/lib/compiler_rt/atomics.zig b/lib/compiler_rt/atomics.zig index 09fd1c2c906c..b87b7a631525 100644 --- a/lib/compiler_rt/atomics.zig +++ b/lib/compiler_rt/atomics.zig @@ -5,7 +5,6 @@ const cpu = builtin.cpu; const arch = cpu.arch; const linkage = common.linkage; const visibility = common.visibility; -pub const panic = common.panic; // This parameter is true iff the target architecture supports the bare minimum // to implement the atomic load/store intrinsics. diff --git a/lib/compiler_rt/aulldiv.zig b/lib/compiler_rt/aulldiv.zig index 5a202fec00dc..fbfa18dfd195 100644 --- a/lib/compiler_rt/aulldiv.zig +++ b/lib/compiler_rt/aulldiv.zig @@ -5,8 +5,6 @@ const os = builtin.os.tag; const abi = builtin.abi; const common = @import("common.zig"); -pub const panic = common.panic; - comptime { if (common.want_windows_x86_msvc_abi) { // Don't let LLVM apply the stdcall name mangling on those MSVC builtins diff --git a/lib/compiler_rt/aullrem.zig b/lib/compiler_rt/aullrem.zig index d4365265be25..ea12c16a0620 100644 --- a/lib/compiler_rt/aullrem.zig +++ b/lib/compiler_rt/aullrem.zig @@ -5,8 +5,6 @@ const os = builtin.os.tag; const abi = builtin.abi; const common = @import("common.zig"); -pub const panic = common.panic; - comptime { if (common.want_windows_x86_msvc_abi) { // Don't let LLVM apply the stdcall name mangling on those MSVC builtins diff --git a/lib/compiler_rt/bitreverse.zig b/lib/compiler_rt/bitreverse.zig index fe6cf8988da6..6dbeac77d9e1 100644 --- a/lib/compiler_rt/bitreverse.zig +++ b/lib/compiler_rt/bitreverse.zig @@ -2,8 +2,6 @@ const std = @import("std"); const builtin = @import("builtin"); const common = @import("common.zig"); -pub const panic = common.panic; - comptime { @export(&__bitreversesi2, .{ .name = "__bitreversesi2", .linkage = common.linkage, .visibility = common.visibility }); @export(&__bitreversedi2, .{ .name = "__bitreversedi2", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/bswap.zig b/lib/compiler_rt/bswap.zig index 2d6df339dfc2..e6f634c66fb7 100644 --- a/lib/compiler_rt/bswap.zig +++ b/lib/compiler_rt/bswap.zig @@ -2,8 +2,6 @@ const std = @import("std"); const builtin = @import("builtin"); const common = @import("common.zig"); -pub const panic = common.panic; - comptime { @export(&__bswapsi2, .{ .name = "__bswapsi2", .linkage = common.linkage, .visibility = common.visibility }); @export(&__bswapdi2, .{ .name = "__bswapdi2", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/ceil.zig b/lib/compiler_rt/ceil.zig deleted file mode 100644 index 1900496be97f..000000000000 --- a/lib/compiler_rt/ceil.zig +++ /dev/null @@ -1,238 +0,0 @@ -//! Ported from musl, which is MIT licensed. -//! https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT -//! -//! https://git.musl-libc.org/cgit/musl/tree/src/math/ceilf.c -//! https://git.musl-libc.org/cgit/musl/tree/src/math/ceil.c -//! https://git.musl-libc.org/cgit/musl/tree/src/math/ceill.c - -const std = @import("std"); -const builtin = @import("builtin"); -const arch = builtin.cpu.arch; -const math = std.math; -const mem = std.mem; -const expect = std.testing.expect; -const common = @import("common.zig"); - -pub const panic = common.panic; - -comptime { - @export(&__ceilh, .{ .name = "__ceilh", .linkage = common.linkage, .visibility = common.visibility }); - @export(&ceilf, .{ .name = "ceilf", .linkage = common.linkage, .visibility = common.visibility }); - @export(&ceil, .{ .name = "ceil", .linkage = common.linkage, .visibility = common.visibility }); - @export(&__ceilx, .{ .name = "__ceilx", .linkage = common.linkage, .visibility = common.visibility }); - if (common.want_ppc_abi) { - @export(&ceilq, .{ .name = "ceilf128", .linkage = common.linkage, .visibility = common.visibility }); - } - @export(&ceilq, .{ .name = "ceilq", .linkage = common.linkage, .visibility = common.visibility }); - @export(&ceill, .{ .name = "ceill", .linkage = common.linkage, .visibility = common.visibility }); -} - -pub fn __ceilh(x: f16) callconv(.c) f16 { - var u: u16 = @bitCast(x); - const e = @as(i16, @intCast((u >> 10) & 31)) - 15; - var m: u16 = undefined; - - if (e >= 10) return x; - - if (e >= 0) { - m = @as(u16, 0x03FF) >> @intCast(e); - if (u & m == 0) return x; - if (common.want_float_exceptions) mem.doNotOptimizeAway(x + 0x1.0p120); - if (u >> 15 == 0) u += m; - u &= ~m; - return @bitCast(u); - } else { - if (common.want_float_exceptions) mem.doNotOptimizeAway(x + 0x1.0p120); - return if (u >> 15 != 0) -0.0 else if (u << 1 != 0) 1.0 else x; - } -} - -pub fn ceilf(x: f32) callconv(.c) f32 { - var u: u32 = @bitCast(x); - const e = @as(i32, @intCast((u >> 23) & 0xFF)) - 0x7F; - var m: u32 = undefined; - - if (e >= 23) return x; - - if (e >= 0) { - m = @as(u32, 0x007FFFFF) >> @intCast(e); - if (u & m == 0) return x; - if (common.want_float_exceptions) mem.doNotOptimizeAway(x + 0x1.0p120); - if (u >> 31 == 0) u += m; - u &= ~m; - return @bitCast(u); - } else { - if (common.want_float_exceptions) mem.doNotOptimizeAway(x + 0x1.0p120); - return if (u >> 31 != 0) -0.0 else if (u << 1 != 0) 1.0 else x; - } -} - -pub fn ceil(x: f64) callconv(.c) f64 { - const f64_toint = 1.0 / math.floatEps(f64); - - const u: u64 = @bitCast(x); - const e = (u >> 52) & 0x7FF; - var y: f64 = undefined; - - if (e >= 0x3FF + 52 or x == 0) { - return x; - } - - if (u >> 63 != 0) { - y = x - f64_toint + f64_toint - x; - } else { - y = x + f64_toint - f64_toint - x; - } - - if (e <= 0x3FF - 1) { - if (common.want_float_exceptions) mem.doNotOptimizeAway(y); - if (u >> 63 != 0) { - return -0.0; - } else { - return 1.0; - } - } else if (y < 0) { - return x + y + 1; - } else { - return x + y; - } -} - -pub fn __ceilx(x: f80) callconv(.c) f80 { - const f80_toint = 1.0 / math.floatEps(f80); - - const u: u80 = @bitCast(x); - const e = (u >> 64) & 0x7FFF; - var y: f80 = undefined; - - if (e >= 0x3FFF + 64 or x == 0) return x; - - if (u >> 79 != 0) { - y = x - f80_toint + f80_toint - x; - } else { - y = x + f80_toint - f80_toint - x; - } - - if (e <= 0x3FFF - 1) { - if (common.want_float_exceptions) mem.doNotOptimizeAway(y); - if (u >> 79 != 0) { - return -0.0; - } else { - return 1.0; - } - } else if (y < 0) { - return x + y + 1; - } else { - return x + y; - } -} - -pub fn ceilq(x: f128) callconv(.c) f128 { - const f128_toint = 1.0 / math.floatEps(f128); - - const u: u128 = @bitCast(x); - const e = (u >> 112) & 0x7FFF; - var y: f128 = undefined; - - if (e >= 0x3FFF + 112 or x == 0) return x; - - if (u >> 127 != 0) { - y = x - f128_toint + f128_toint - x; - } else { - y = x + f128_toint - f128_toint - x; - } - - if (e <= 0x3FFF - 1) { - if (common.want_float_exceptions) mem.doNotOptimizeAway(y); - if (u >> 127 != 0) { - return -0.0; - } else { - return 1.0; - } - } else if (y < 0) { - return x + y + 1; - } else { - return x + y; - } -} - -pub fn ceill(x: c_longdouble) callconv(.c) c_longdouble { - switch (@typeInfo(c_longdouble).float.bits) { - 16 => return __ceilh(x), - 32 => return ceilf(x), - 64 => return ceil(x), - 80 => return __ceilx(x), - 128 => return ceilq(x), - else => @compileError("unreachable"), - } -} - -test "ceil16" { - try expect(__ceilh(1.3) == 2.0); - try expect(__ceilh(-1.3) == -1.0); - try expect(__ceilh(0.2) == 1.0); -} - -test "ceil32" { - try expect(ceilf(1.3) == 2.0); - try expect(ceilf(-1.3) == -1.0); - try expect(ceilf(0.2) == 1.0); -} - -test "ceil64" { - try expect(ceil(1.3) == 2.0); - try expect(ceil(-1.3) == -1.0); - try expect(ceil(0.2) == 1.0); -} - -test "ceil80" { - try expect(__ceilx(1.3) == 2.0); - try expect(__ceilx(-1.3) == -1.0); - try expect(__ceilx(0.2) == 1.0); -} - -test "ceil128" { - try expect(ceilq(1.3) == 2.0); - try expect(ceilq(-1.3) == -1.0); - try expect(ceilq(0.2) == 1.0); -} - -test "ceil16.special" { - try expect(__ceilh(0.0) == 0.0); - try expect(__ceilh(-0.0) == -0.0); - try expect(math.isPositiveInf(__ceilh(math.inf(f16)))); - try expect(math.isNegativeInf(__ceilh(-math.inf(f16)))); - try expect(math.isNan(__ceilh(math.nan(f16)))); -} - -test "ceil32.special" { - try expect(ceilf(0.0) == 0.0); - try expect(ceilf(-0.0) == -0.0); - try expect(math.isPositiveInf(ceilf(math.inf(f32)))); - try expect(math.isNegativeInf(ceilf(-math.inf(f32)))); - try expect(math.isNan(ceilf(math.nan(f32)))); -} - -test "ceil64.special" { - try expect(ceil(0.0) == 0.0); - try expect(ceil(-0.0) == -0.0); - try expect(math.isPositiveInf(ceil(math.inf(f64)))); - try expect(math.isNegativeInf(ceil(-math.inf(f64)))); - try expect(math.isNan(ceil(math.nan(f64)))); -} - -test "ceil80.special" { - try expect(__ceilx(0.0) == 0.0); - try expect(__ceilx(-0.0) == -0.0); - try expect(math.isPositiveInf(__ceilx(math.inf(f80)))); - try expect(math.isNegativeInf(__ceilx(-math.inf(f80)))); - try expect(math.isNan(__ceilx(math.nan(f80)))); -} - -test "ceil128.special" { - try expect(ceilq(0.0) == 0.0); - try expect(ceilq(-0.0) == -0.0); - try expect(math.isPositiveInf(ceilq(math.inf(f128)))); - try expect(math.isNegativeInf(ceilq(-math.inf(f128)))); - try expect(math.isNan(ceilq(math.nan(f128)))); -} diff --git a/lib/compiler_rt/clear_cache.zig b/lib/compiler_rt/clear_cache.zig index 6b0fc18082ce..0e3b5d371f93 100644 --- a/lib/compiler_rt/clear_cache.zig +++ b/lib/compiler_rt/clear_cache.zig @@ -3,7 +3,6 @@ const builtin = @import("builtin"); const arch = builtin.cpu.arch; const os = builtin.os.tag; const common = @import("common.zig"); -pub const panic = common.panic; // Ported from llvm-project d32170dbd5b0d54436537b6b75beaf44324e0c28 @@ -62,12 +61,13 @@ fn clear_cache(start: usize, end: usize) callconv(.c) void { // exportIt(); } else if (arm32 and !apple) { switch (os) { - .freebsd, .netbsd => { - var arg = arm_sync_icache_args{ + // FreeBSD and NetBSD should be changed to do direct syscalls here... + .freebsd, .netbsd, .openbsd => { + var arg: arm_sync_icache_args = .{ .addr = start, - .len = end - start, + .size = end - start, }; - const result = sysarch(ARM_SYNC_ICACHE, @intFromPtr(&arg)); + const result = sysarch(ARM_SYNC_ICACHE, &arg); std.debug.assert(result == 0); exportIt(); }, @@ -79,32 +79,32 @@ fn clear_cache(start: usize, end: usize) callconv(.c) void { else => {}, } } else if (os == .linux and mips) { - const flags = 3; // ICACHE | DCACHE - const result = std.os.linux.syscall3(.cacheflush, start, end - start, flags); + const result = std.os.linux.syscall3(.cacheflush, start, end - start, ICACHE | DCACHE); std.debug.assert(result == 0); exportIt(); } else if (os == .netbsd and mips) { // Replace with https://github.com/ziglang/zig/issues/23904 in the future. - const cfa: extern struct { - va: usize, - nbytes: usize, - whichcache: u32, - } = .{ - .va = start, - .nbytes = end - start, - .whichcache = 3, // ICACHE | DCACHE + const cfa: mips_cacheflush_args = .{ + .addr = start, + .size = end - start, + .which = ICACHE | DCACHE, }; asm volatile ("syscall" : : [_] "{$2}" (165), // nr = SYS_sysarch - [_] "{$4}" (0), // op = MIPS_CACHEFLUSH + [_] "{$4}" (MIPS_CACHEFLUSH), // op [_] "{$5}" (&cfa), // args = &cfa : .{ .r1 = true, .r2 = true, .r3 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .r13 = true, .r14 = true, .r15 = true, .r24 = true, .r25 = true, .hi = true, .lo = true, .memory = true }); exportIt(); } else if (mips and os == .openbsd) { - // TODO - //cacheflush(start, (uintptr_t)end - (uintptr_t)start, BCACHE); - // exportIt(); + const cfa: mips_cacheflush_args = .{ + .addr = start, + .size = end - start, + .which = ICACHE | DCACHE, + }; + const result = sysarch(MIPS_CACHEFLUSH, &cfa); + std.debug.assert(result == 0); + exportIt(); } else if (os == .linux and riscv) { const result = std.os.linux.syscall3(.riscv_flush_icache, start, end - start, 0); std.debug.assert(result == 0); @@ -191,12 +191,25 @@ fn exportIt() void { @export(&clear_cache, .{ .name = "__clear_cache", .linkage = common.linkage, .visibility = common.visibility }); } +// MIPS-only +const ICACHE = 0x1; +const DCACHE = 0x2; + // Darwin-only extern fn sys_icache_invalidate(start: usize, len: usize) void; + // BSD-only +const ARM_SYNC_ICACHE = 0; const arm_sync_icache_args = extern struct { - addr: usize, // Virtual start address - len: usize, // Region size + addr: usize, + size: usize, }; -const ARM_SYNC_ICACHE = 0; -extern "c" fn sysarch(number: i32, args: usize) i32; + +const MIPS_CACHEFLUSH = 0; +const mips_cacheflush_args = extern struct { + addr: usize, + size: usize, + which: c_uint, +}; + +extern fn sysarch(op: c_uint, args: *const anyopaque) c_int; diff --git a/lib/compiler_rt/cmp.zig b/lib/compiler_rt/cmp.zig index 67cb5b0938fa..cac23a7508f1 100644 --- a/lib/compiler_rt/cmp.zig +++ b/lib/compiler_rt/cmp.zig @@ -2,8 +2,6 @@ const std = @import("std"); const builtin = @import("builtin"); const common = @import("common.zig"); -pub const panic = common.panic; - comptime { @export(&__cmpsi2, .{ .name = "__cmpsi2", .linkage = common.linkage, .visibility = common.visibility }); @export(&__cmpdi2, .{ .name = "__cmpdi2", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/cmpdf2.zig b/lib/compiler_rt/cmpdf2.zig index a0338c7a1792..ebec596f270d 100644 --- a/lib/compiler_rt/cmpdf2.zig +++ b/lib/compiler_rt/cmpdf2.zig @@ -3,8 +3,6 @@ const common = @import("./common.zig"); const comparef = @import("./comparef.zig"); -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_dcmpeq, .{ .name = "__aeabi_dcmpeq", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/cmphf2.zig b/lib/compiler_rt/cmphf2.zig index 9fcc1e24d53e..ea70e71e161f 100644 --- a/lib/compiler_rt/cmphf2.zig +++ b/lib/compiler_rt/cmphf2.zig @@ -3,8 +3,6 @@ const common = @import("./common.zig"); const comparef = @import("./comparef.zig"); -pub const panic = common.panic; - comptime { @export(&__eqhf2, .{ .name = "__eqhf2", .linkage = common.linkage, .visibility = common.visibility }); @export(&__nehf2, .{ .name = "__nehf2", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/cmpsf2.zig b/lib/compiler_rt/cmpsf2.zig index 371319b072ab..4b200198e662 100644 --- a/lib/compiler_rt/cmpsf2.zig +++ b/lib/compiler_rt/cmpsf2.zig @@ -3,8 +3,6 @@ const common = @import("./common.zig"); const comparef = @import("./comparef.zig"); -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_fcmpeq, .{ .name = "__aeabi_fcmpeq", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/cmptf2.zig b/lib/compiler_rt/cmptf2.zig index d5ee7970d475..3188ecf90ec5 100644 --- a/lib/compiler_rt/cmptf2.zig +++ b/lib/compiler_rt/cmptf2.zig @@ -3,8 +3,6 @@ const common = @import("./common.zig"); const comparef = @import("./comparef.zig"); -pub const panic = common.panic; - comptime { if (common.want_ppc_abi) { @export(&__eqtf2, .{ .name = "__eqkf2", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/cmpxf2.zig b/lib/compiler_rt/cmpxf2.zig index dc90f87c340e..f70de9c0b617 100644 --- a/lib/compiler_rt/cmpxf2.zig +++ b/lib/compiler_rt/cmpxf2.zig @@ -3,8 +3,6 @@ const common = @import("./common.zig"); const comparef = @import("./comparef.zig"); -pub const panic = common.panic; - comptime { @export(&__eqxf2, .{ .name = "__eqxf2", .linkage = common.linkage, .visibility = common.visibility }); @export(&__nexf2, .{ .name = "__nexf2", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/common.zig b/lib/compiler_rt/common.zig index d74eab18d8fb..a9b4c2296c59 100644 --- a/lib/compiler_rt/common.zig +++ b/lib/compiler_rt/common.zig @@ -126,10 +126,6 @@ pub const test_safety = switch (builtin.zig_backend) { else => builtin.is_test, }; -// Avoid dragging in the runtime safety mechanisms into this .o file, unless -// we're trying to test compiler-rt. -pub const panic = if (test_safety) std.debug.FullPanic(std.debug.defaultPanic) else std.debug.no_panic; - /// This seems to mostly correspond to `clang::TargetInfo::HasFloat16`. pub fn F16T(comptime OtherType: type) type { return switch (builtin.cpu.arch) { diff --git a/lib/compiler_rt/cos.zig b/lib/compiler_rt/cos.zig index 01a5196232ab..3384887385f0 100644 --- a/lib/compiler_rt/cos.zig +++ b/lib/compiler_rt/cos.zig @@ -4,8 +4,6 @@ const mem = std.mem; const expect = std.testing.expect; const common = @import("common.zig"); -pub const panic = common.panic; - const trig = @import("trig.zig"); const rem_pio2 = @import("rem_pio2.zig").rem_pio2; const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; diff --git a/lib/compiler_rt/count0bits.zig b/lib/compiler_rt/count0bits.zig index 874604eb2c60..3696c899447e 100644 --- a/lib/compiler_rt/count0bits.zig +++ b/lib/compiler_rt/count0bits.zig @@ -2,8 +2,6 @@ const std = @import("std"); const builtin = @import("builtin"); const common = @import("common.zig"); -pub const panic = common.panic; - comptime { @export(&__clzsi2, .{ .name = "__clzsi2", .linkage = common.linkage, .visibility = common.visibility }); @export(&__clzdi2, .{ .name = "__clzdi2", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/divdf3.zig b/lib/compiler_rt/divdf3.zig index 7b47cd3a703c..a94544165bdf 100644 --- a/lib/compiler_rt/divdf3.zig +++ b/lib/compiler_rt/divdf3.zig @@ -10,8 +10,6 @@ const common = @import("common.zig"); const normalize = common.normalize; const wideMultiply = common.wideMultiply; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_ddiv, .{ .name = "__aeabi_ddiv", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/divsf3.zig b/lib/compiler_rt/divsf3.zig index a74d3f7abdba..dca1d49ebe0c 100644 --- a/lib/compiler_rt/divsf3.zig +++ b/lib/compiler_rt/divsf3.zig @@ -9,8 +9,6 @@ const arch = builtin.cpu.arch; const common = @import("common.zig"); const normalize = common.normalize; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_fdiv, .{ .name = "__aeabi_fdiv", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/divtf3.zig b/lib/compiler_rt/divtf3.zig index 0bab96de3996..6606d0de3808 100644 --- a/lib/compiler_rt/divtf3.zig +++ b/lib/compiler_rt/divtf3.zig @@ -5,8 +5,6 @@ const common = @import("common.zig"); const normalize = common.normalize; const wideMultiply = common.wideMultiply; -pub const panic = common.panic; - comptime { if (common.want_ppc_abi) { @export(&__divtf3, .{ .name = "__divkf3", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/divti3.zig b/lib/compiler_rt/divti3.zig index 5f24d196d721..9eb8dda18741 100644 --- a/lib/compiler_rt/divti3.zig +++ b/lib/compiler_rt/divti3.zig @@ -4,8 +4,6 @@ const udivmod = @import("udivmod.zig").udivmod; const arch = builtin.cpu.arch; const common = @import("common.zig"); -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__divti3_windows_x86_64, .{ .name = "__divti3", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/divxf3.zig b/lib/compiler_rt/divxf3.zig index 1579db226cc6..069510a2b687 100644 --- a/lib/compiler_rt/divxf3.zig +++ b/lib/compiler_rt/divxf3.zig @@ -6,8 +6,6 @@ const common = @import("common.zig"); const normalize = common.normalize; const wideMultiply = common.wideMultiply; -pub const panic = common.panic; - comptime { @export(&__divxf3, .{ .name = "__divxf3", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/emutls.zig b/lib/compiler_rt/emutls.zig index 0bb427b651af..c52ce020eddd 100644 --- a/lib/compiler_rt/emutls.zig +++ b/lib/compiler_rt/emutls.zig @@ -7,7 +7,7 @@ const std = @import("std"); const builtin = @import("builtin"); const common = @import("common.zig"); -const abort = std.posix.abort; +const abort = std.process.abort; const assert = std.debug.assert; const expect = std.testing.expect; @@ -15,8 +15,6 @@ const expect = std.testing.expect; /// typedef unsigned int gcc_word __attribute__((mode(word))); const gcc_word = usize; -pub const panic = common.panic; - comptime { if (builtin.link_libc and (builtin.abi.isAndroid() or builtin.abi.isOpenHarmony() or builtin.os.tag == .openbsd)) { @export(&__emutls_get_address, .{ .name = "__emutls_get_address", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/exp.zig b/lib/compiler_rt/exp.zig index fa4356a3366f..f25bf57092cb 100644 --- a/lib/compiler_rt/exp.zig +++ b/lib/compiler_rt/exp.zig @@ -13,8 +13,6 @@ const expect = std.testing.expect; const expectEqual = std.testing.expectEqual; const common = @import("common.zig"); -pub const panic = common.panic; - comptime { @export(&__exph, .{ .name = "__exph", .linkage = common.linkage, .visibility = common.visibility }); @export(&expf, .{ .name = "expf", .linkage = common.linkage, .visibility = common.visibility }); @@ -136,14 +134,11 @@ pub fn exp(x_: f64) callconv(.c) f64 { } if (x > 709.782712893383973096) { // overflow if x != inf - if (!math.isInf(x)) { - math.raiseOverflow(); - } - return math.inf(f64); + return if (common.want_float_exceptions) x * 0x1p1023 else std.math.inf(f64); } if (x < -708.39641853226410622) { // underflow if x != -inf - // if (common.want_float_exceptions) mem.doNotOptimizeAway(@as(f32, -0x1.0p-149 / x)); + if (common.want_float_exceptions) mem.doNotOptimizeAway(-0x0.0000000000001p-1022 / x); if (x < -745.13321910194110842) { return 0; } @@ -176,7 +171,7 @@ pub fn exp(x_: f64) callconv(.c) f64 { lo = 0; } else { // inexact if x != 0 - // if (common.want_float_exceptions) mem.doNotOptimizeAway(0x1.0p1023 + x); + if (common.want_float_exceptions) mem.doNotOptimizeAway(0x1.0p1023 + x); return 1 + x; } diff --git a/lib/compiler_rt/exp2.zig b/lib/compiler_rt/exp2.zig index ce79dff49748..f59e98620ebd 100644 --- a/lib/compiler_rt/exp2.zig +++ b/lib/compiler_rt/exp2.zig @@ -13,8 +13,6 @@ const expect = std.testing.expect; const expectEqual = std.testing.expectEqual; const common = @import("common.zig"); -pub const panic = common.panic; - comptime { @export(&__exp2h, .{ .name = "__exp2h", .linkage = common.linkage, .visibility = common.visibility }); @export(&exp2f, .{ .name = "exp2f", .linkage = common.linkage, .visibility = common.visibility }); @@ -110,8 +108,7 @@ pub fn exp2(x: f64) callconv(.c) f64 { if (ix >= 0x408FF000) { // x >= 1024 or nan if (ix >= 0x40900000 and ux >> 63 == 0) { - math.raiseOverflow(); - return math.inf(f64); + return if (common.want_float_exceptions) x * 0x1p1023 else std.math.inf(f64); } // -inf or -nan if (ix >= 0x7FF00000) { diff --git a/lib/compiler_rt/extenddftf2.zig b/lib/compiler_rt/extenddftf2.zig index 457a64522a9a..9ef552c2c550 100644 --- a/lib/compiler_rt/extenddftf2.zig +++ b/lib/compiler_rt/extenddftf2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const extendf = @import("./extendf.zig").extendf; -pub const panic = common.panic; - comptime { if (common.want_ppc_abi) { @export(&__extenddftf2, .{ .name = "__extenddfkf2", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/extenddfxf2.zig b/lib/compiler_rt/extenddfxf2.zig index 55a1df566238..1d7bc998d76d 100644 --- a/lib/compiler_rt/extenddfxf2.zig +++ b/lib/compiler_rt/extenddfxf2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const extend_f80 = @import("./extendf.zig").extend_f80; -pub const panic = common.panic; - comptime { @export(&__extenddfxf2, .{ .name = "__extenddfxf2", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/extendf_test.zig b/lib/compiler_rt/extendf_test.zig index bc154e750429..20273507d16d 100644 --- a/lib/compiler_rt/extendf_test.zig +++ b/lib/compiler_rt/extendf_test.zig @@ -110,6 +110,8 @@ test "extenddfxf2" { } test "extenddftf2" { + if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + // qNaN try test__extenddftf2(makeQNaN64(), 0x7fff800000000000, 0x0); diff --git a/lib/compiler_rt/extendhfdf2.zig b/lib/compiler_rt/extendhfdf2.zig index 7b1a7929f7ed..3b3b65ec114c 100644 --- a/lib/compiler_rt/extendhfdf2.zig +++ b/lib/compiler_rt/extendhfdf2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const extendf = @import("./extendf.zig").extendf; -pub const panic = common.panic; - comptime { @export(&__extendhfdf2, .{ .name = "__extendhfdf2", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/extendhfsf2.zig b/lib/compiler_rt/extendhfsf2.zig index 37f3d79c7af5..f4f8be4305c8 100644 --- a/lib/compiler_rt/extendhfsf2.zig +++ b/lib/compiler_rt/extendhfsf2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const extendf = @import("./extendf.zig").extendf; -pub const panic = common.panic; - comptime { if (common.gnu_f16_abi) { @export(&__gnu_h2f_ieee, .{ .name = "__gnu_h2f_ieee", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/extendhftf2.zig b/lib/compiler_rt/extendhftf2.zig index 3b1f257fa9aa..a94b849a5a2c 100644 --- a/lib/compiler_rt/extendhftf2.zig +++ b/lib/compiler_rt/extendhftf2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const extendf = @import("./extendf.zig").extendf; -pub const panic = common.panic; - comptime { @export(&__extendhftf2, .{ .name = "__extendhftf2", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/extendhfxf2.zig b/lib/compiler_rt/extendhfxf2.zig index 74e4fb64cc3c..5e205b1f8888 100644 --- a/lib/compiler_rt/extendhfxf2.zig +++ b/lib/compiler_rt/extendhfxf2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const extend_f80 = @import("./extendf.zig").extend_f80; -pub const panic = common.panic; - comptime { @export(&__extendhfxf2, .{ .name = "__extendhfxf2", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/extendsfdf2.zig b/lib/compiler_rt/extendsfdf2.zig index c87b721cdd40..9cc0a436633d 100644 --- a/lib/compiler_rt/extendsfdf2.zig +++ b/lib/compiler_rt/extendsfdf2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const extendf = @import("./extendf.zig").extendf; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_f2d, .{ .name = "__aeabi_f2d", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/extendsftf2.zig b/lib/compiler_rt/extendsftf2.zig index 4e45f8502970..3690a0733c87 100644 --- a/lib/compiler_rt/extendsftf2.zig +++ b/lib/compiler_rt/extendsftf2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const extendf = @import("./extendf.zig").extendf; -pub const panic = common.panic; - comptime { if (common.want_ppc_abi) { @export(&__extendsftf2, .{ .name = "__extendsfkf2", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/extendsfxf2.zig b/lib/compiler_rt/extendsfxf2.zig index b883034d4eb2..8665c445f770 100644 --- a/lib/compiler_rt/extendsfxf2.zig +++ b/lib/compiler_rt/extendsfxf2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const extend_f80 = @import("./extendf.zig").extend_f80; -pub const panic = common.panic; - comptime { @export(&__extendsfxf2, .{ .name = "__extendsfxf2", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/extendxftf2.zig b/lib/compiler_rt/extendxftf2.zig index 39d66d399ca7..cec1fa1f7ce9 100644 --- a/lib/compiler_rt/extendxftf2.zig +++ b/lib/compiler_rt/extendxftf2.zig @@ -1,8 +1,6 @@ const std = @import("std"); const common = @import("./common.zig"); -pub const panic = common.panic; - comptime { @export(&__extendxftf2, .{ .name = "__extendxftf2", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/fabs.zig b/lib/compiler_rt/fabs.zig index 31c6cb979362..9a10f4ce617a 100644 --- a/lib/compiler_rt/fabs.zig +++ b/lib/compiler_rt/fabs.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const arch = builtin.cpu.arch; const common = @import("common.zig"); -pub const panic = common.panic; - comptime { @export(&__fabsh, .{ .name = "__fabsh", .linkage = common.linkage, .visibility = common.visibility }); @export(&fabsf, .{ .name = "fabsf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fixdfdi.zig b/lib/compiler_rt/fixdfdi.zig index a92c94504389..97f3be044e2b 100644 --- a/lib/compiler_rt/fixdfdi.zig +++ b/lib/compiler_rt/fixdfdi.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_d2lz, .{ .name = "__aeabi_d2lz", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fixdfei.zig b/lib/compiler_rt/fixdfei.zig index 31c7994c58c5..3565cb45ba2b 100644 --- a/lib/compiler_rt/fixdfei.zig +++ b/lib/compiler_rt/fixdfei.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const common = @import("common.zig"); const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; -pub const panic = common.panic; - comptime { @export(&__fixdfei, .{ .name = "__fixdfei", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/fixdfsi.zig b/lib/compiler_rt/fixdfsi.zig index 5076cdc4c07d..b1b26867b9c1 100644 --- a/lib/compiler_rt/fixdfsi.zig +++ b/lib/compiler_rt/fixdfsi.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_d2iz, .{ .name = "__aeabi_d2iz", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fixdfti.zig b/lib/compiler_rt/fixdfti.zig index 46b17505fc5f..499811c5511a 100644 --- a/lib/compiler_rt/fixdfti.zig +++ b/lib/compiler_rt/fixdfti.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__fixdfti_windows_x86_64, .{ .name = "__fixdfti", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fixhfdi.zig b/lib/compiler_rt/fixhfdi.zig index 154bb501ac8a..3bcb848972d9 100644 --- a/lib/compiler_rt/fixhfdi.zig +++ b/lib/compiler_rt/fixhfdi.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { @export(&__fixhfdi, .{ .name = "__fixhfdi", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/fixhfei.zig b/lib/compiler_rt/fixhfei.zig index c7f30055c561..1eef56073fc6 100644 --- a/lib/compiler_rt/fixhfei.zig +++ b/lib/compiler_rt/fixhfei.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const common = @import("common.zig"); const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; -pub const panic = common.panic; - comptime { @export(&__fixhfei, .{ .name = "__fixhfei", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/fixhfsi.zig b/lib/compiler_rt/fixhfsi.zig index 253e7b64501b..658f13bb7190 100644 --- a/lib/compiler_rt/fixhfsi.zig +++ b/lib/compiler_rt/fixhfsi.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { @export(&__fixhfsi, .{ .name = "__fixhfsi", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/fixhfti.zig b/lib/compiler_rt/fixhfti.zig index 01586578fef9..1c51ebc05648 100644 --- a/lib/compiler_rt/fixhfti.zig +++ b/lib/compiler_rt/fixhfti.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__fixhfti_windows_x86_64, .{ .name = "__fixhfti", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fixsfdi.zig b/lib/compiler_rt/fixsfdi.zig index f0f7bb01e3fe..894d5a0c1353 100644 --- a/lib/compiler_rt/fixsfdi.zig +++ b/lib/compiler_rt/fixsfdi.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_f2lz, .{ .name = "__aeabi_f2lz", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fixsfei.zig b/lib/compiler_rt/fixsfei.zig index c72e002fb1ff..efbccfa29956 100644 --- a/lib/compiler_rt/fixsfei.zig +++ b/lib/compiler_rt/fixsfei.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const common = @import("common.zig"); const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; -pub const panic = common.panic; - comptime { @export(&__fixsfei, .{ .name = "__fixsfei", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/fixsfsi.zig b/lib/compiler_rt/fixsfsi.zig index fb83d6922793..abb856436985 100644 --- a/lib/compiler_rt/fixsfsi.zig +++ b/lib/compiler_rt/fixsfsi.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_f2iz, .{ .name = "__aeabi_f2iz", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fixsfti.zig b/lib/compiler_rt/fixsfti.zig index e1d4e7188caf..82b1db70dc94 100644 --- a/lib/compiler_rt/fixsfti.zig +++ b/lib/compiler_rt/fixsfti.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__fixsfti_windows_x86_64, .{ .name = "__fixsfti", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fixtfdi.zig b/lib/compiler_rt/fixtfdi.zig index ebb7484c6257..5c41f56595e5 100644 --- a/lib/compiler_rt/fixtfdi.zig +++ b/lib/compiler_rt/fixtfdi.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { if (common.want_ppc_abi) { @export(&__fixtfdi, .{ .name = "__fixkfdi", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fixtfei.zig b/lib/compiler_rt/fixtfei.zig index 8daf3754f77e..980db4c614f8 100644 --- a/lib/compiler_rt/fixtfei.zig +++ b/lib/compiler_rt/fixtfei.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const common = @import("common.zig"); const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; -pub const panic = common.panic; - comptime { @export(&__fixtfei, .{ .name = "__fixtfei", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/fixtfsi.zig b/lib/compiler_rt/fixtfsi.zig index a6d2daf00c18..0d525cf8c4c4 100644 --- a/lib/compiler_rt/fixtfsi.zig +++ b/lib/compiler_rt/fixtfsi.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { if (common.want_ppc_abi) { @export(&__fixtfsi, .{ .name = "__fixkfsi", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fixtfti.zig b/lib/compiler_rt/fixtfti.zig index 44f88e8dd060..fe71a0f08906 100644 --- a/lib/compiler_rt/fixtfti.zig +++ b/lib/compiler_rt/fixtfti.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__fixtfti_windows_x86_64, .{ .name = "__fixtfti", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fixunsdfdi.zig b/lib/compiler_rt/fixunsdfdi.zig index 52577361a688..211963bf3e6f 100644 --- a/lib/compiler_rt/fixunsdfdi.zig +++ b/lib/compiler_rt/fixunsdfdi.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_d2ulz, .{ .name = "__aeabi_d2ulz", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fixunsdfei.zig b/lib/compiler_rt/fixunsdfei.zig index 886feab66aa5..be5bbf0a8a7a 100644 --- a/lib/compiler_rt/fixunsdfei.zig +++ b/lib/compiler_rt/fixunsdfei.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const common = @import("common.zig"); const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; -pub const panic = common.panic; - comptime { @export(&__fixunsdfei, .{ .name = "__fixunsdfei", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/fixunsdfsi.zig b/lib/compiler_rt/fixunsdfsi.zig index 246cbf97eb24..a8e9197361a7 100644 --- a/lib/compiler_rt/fixunsdfsi.zig +++ b/lib/compiler_rt/fixunsdfsi.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_d2uiz, .{ .name = "__aeabi_d2uiz", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fixunsdfti.zig b/lib/compiler_rt/fixunsdfti.zig index b4429a9d7622..28b79a0733b0 100644 --- a/lib/compiler_rt/fixunsdfti.zig +++ b/lib/compiler_rt/fixunsdfti.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__fixunsdfti_windows_x86_64, .{ .name = "__fixunsdfti", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fixunshfdi.zig b/lib/compiler_rt/fixunshfdi.zig index dca13e17c4e4..a949ee99045d 100644 --- a/lib/compiler_rt/fixunshfdi.zig +++ b/lib/compiler_rt/fixunshfdi.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { @export(&__fixunshfdi, .{ .name = "__fixunshfdi", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/fixunshfei.zig b/lib/compiler_rt/fixunshfei.zig index 788605a6868e..4cb7ef2ba8da 100644 --- a/lib/compiler_rt/fixunshfei.zig +++ b/lib/compiler_rt/fixunshfei.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const common = @import("common.zig"); const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; -pub const panic = common.panic; - comptime { @export(&__fixunshfei, .{ .name = "__fixunshfei", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/fixunshfsi.zig b/lib/compiler_rt/fixunshfsi.zig index 27db84357fae..fca40d1b0a33 100644 --- a/lib/compiler_rt/fixunshfsi.zig +++ b/lib/compiler_rt/fixunshfsi.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { @export(&__fixunshfsi, .{ .name = "__fixunshfsi", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/fixunshfti.zig b/lib/compiler_rt/fixunshfti.zig index c92039212d33..c61be597e772 100644 --- a/lib/compiler_rt/fixunshfti.zig +++ b/lib/compiler_rt/fixunshfti.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__fixunshfti_windows_x86_64, .{ .name = "__fixunshfti", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fixunssfdi.zig b/lib/compiler_rt/fixunssfdi.zig index e05d0377e06f..f12ec1cd5a9d 100644 --- a/lib/compiler_rt/fixunssfdi.zig +++ b/lib/compiler_rt/fixunssfdi.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_f2ulz, .{ .name = "__aeabi_f2ulz", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fixunssfei.zig b/lib/compiler_rt/fixunssfei.zig index bb89fc283dea..0fb957ed1f79 100644 --- a/lib/compiler_rt/fixunssfei.zig +++ b/lib/compiler_rt/fixunssfei.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const common = @import("common.zig"); const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; -pub const panic = common.panic; - comptime { @export(&__fixunssfei, .{ .name = "__fixunssfei", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/fixunssfsi.zig b/lib/compiler_rt/fixunssfsi.zig index d0038add1bb4..4def4b867fea 100644 --- a/lib/compiler_rt/fixunssfsi.zig +++ b/lib/compiler_rt/fixunssfsi.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_f2uiz, .{ .name = "__aeabi_f2uiz", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fixunssfti.zig b/lib/compiler_rt/fixunssfti.zig index 3137fb3bc616..693442417c77 100644 --- a/lib/compiler_rt/fixunssfti.zig +++ b/lib/compiler_rt/fixunssfti.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__fixunssfti_windows_x86_64, .{ .name = "__fixunssfti", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fixunstfdi.zig b/lib/compiler_rt/fixunstfdi.zig index 87a06bc37b2b..f1e1822a3118 100644 --- a/lib/compiler_rt/fixunstfdi.zig +++ b/lib/compiler_rt/fixunstfdi.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { if (common.want_ppc_abi) { @export(&__fixunstfdi, .{ .name = "__fixunskfdi", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fixunstfei.zig b/lib/compiler_rt/fixunstfei.zig index 997a100afacc..84ac5010c96e 100644 --- a/lib/compiler_rt/fixunstfei.zig +++ b/lib/compiler_rt/fixunstfei.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const common = @import("common.zig"); const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; -pub const panic = common.panic; - comptime { @export(&__fixunstfei, .{ .name = "__fixunstfei", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/fixunstfsi.zig b/lib/compiler_rt/fixunstfsi.zig index 8a57e2dbc107..d3a9bfbed85f 100644 --- a/lib/compiler_rt/fixunstfsi.zig +++ b/lib/compiler_rt/fixunstfsi.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { if (common.want_ppc_abi) { @export(&__fixunstfsi, .{ .name = "__fixunskfsi", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fixunstfti.zig b/lib/compiler_rt/fixunstfti.zig index 2c182e3a449f..92fcd569dc6d 100644 --- a/lib/compiler_rt/fixunstfti.zig +++ b/lib/compiler_rt/fixunstfti.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__fixunstfti_windows_x86_64, .{ .name = "__fixunstfti", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fixunsxfdi.zig b/lib/compiler_rt/fixunsxfdi.zig index 1e10786fc879..4dffd0253ee5 100644 --- a/lib/compiler_rt/fixunsxfdi.zig +++ b/lib/compiler_rt/fixunsxfdi.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { @export(&__fixunsxfdi, .{ .name = "__fixunsxfdi", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/fixunsxfei.zig b/lib/compiler_rt/fixunsxfei.zig index 88c7f1824388..dc795e74c691 100644 --- a/lib/compiler_rt/fixunsxfei.zig +++ b/lib/compiler_rt/fixunsxfei.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const common = @import("common.zig"); const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; -pub const panic = common.panic; - comptime { @export(&__fixunsxfei, .{ .name = "__fixunsxfei", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/fixunsxfsi.zig b/lib/compiler_rt/fixunsxfsi.zig index c876ea0d3e07..8f900076c728 100644 --- a/lib/compiler_rt/fixunsxfsi.zig +++ b/lib/compiler_rt/fixunsxfsi.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { @export(&__fixunsxfsi, .{ .name = "__fixunsxfsi", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/fixunsxfti.zig b/lib/compiler_rt/fixunsxfti.zig index bfe8a2c6e2a6..39dde2ca1222 100644 --- a/lib/compiler_rt/fixunsxfti.zig +++ b/lib/compiler_rt/fixunsxfti.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__fixunsxfti_windows_x86_64, .{ .name = "__fixunsxfti", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fixxfdi.zig b/lib/compiler_rt/fixxfdi.zig index 2477a4bb834d..155fead1bbe1 100644 --- a/lib/compiler_rt/fixxfdi.zig +++ b/lib/compiler_rt/fixxfdi.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { @export(&__fixxfdi, .{ .name = "__fixxfdi", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/fixxfei.zig b/lib/compiler_rt/fixxfei.zig index 6f28153a6634..75edfad035cb 100644 --- a/lib/compiler_rt/fixxfei.zig +++ b/lib/compiler_rt/fixxfei.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const common = @import("common.zig"); const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; -pub const panic = common.panic; - comptime { @export(&__fixxfei, .{ .name = "__fixxfei", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/fixxfsi.zig b/lib/compiler_rt/fixxfsi.zig index 846df4d00667..8a645bdae1fb 100644 --- a/lib/compiler_rt/fixxfsi.zig +++ b/lib/compiler_rt/fixxfsi.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { @export(&__fixxfsi, .{ .name = "__fixxfsi", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/fixxfti.zig b/lib/compiler_rt/fixxfti.zig index e1db47dc338c..292b9688e7fa 100644 --- a/lib/compiler_rt/fixxfti.zig +++ b/lib/compiler_rt/fixxfti.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__fixxfti_windows_x86_64, .{ .name = "__fixxfti", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/floatdidf.zig b/lib/compiler_rt/floatdidf.zig index 38890e35a4e4..f614521478da 100644 --- a/lib/compiler_rt/floatdidf.zig +++ b/lib/compiler_rt/floatdidf.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_l2d, .{ .name = "__aeabi_l2d", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/floatdihf.zig b/lib/compiler_rt/floatdihf.zig index 37a03e4ed355..fd534e594620 100644 --- a/lib/compiler_rt/floatdihf.zig +++ b/lib/compiler_rt/floatdihf.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { @export(&__floatdihf, .{ .name = "__floatdihf", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/floatdisf.zig b/lib/compiler_rt/floatdisf.zig index a942d7b0b1f6..1efd9c937ff2 100644 --- a/lib/compiler_rt/floatdisf.zig +++ b/lib/compiler_rt/floatdisf.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_l2f, .{ .name = "__aeabi_l2f", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/floatditf.zig b/lib/compiler_rt/floatditf.zig index b5cc262fa354..864361b7b3d5 100644 --- a/lib/compiler_rt/floatditf.zig +++ b/lib/compiler_rt/floatditf.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { if (common.want_ppc_abi) { @export(&__floatditf, .{ .name = "__floatdikf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/floatdixf.zig b/lib/compiler_rt/floatdixf.zig index eba666c05394..8ac6f06fb592 100644 --- a/lib/compiler_rt/floatdixf.zig +++ b/lib/compiler_rt/floatdixf.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { @export(&__floatdixf, .{ .name = "__floatdixf", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/floateidf.zig b/lib/compiler_rt/floateidf.zig index 96411ae878cc..6434743939ec 100644 --- a/lib/compiler_rt/floateidf.zig +++ b/lib/compiler_rt/floateidf.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const common = @import("common.zig"); const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; -pub const panic = common.panic; - comptime { @export(&__floateidf, .{ .name = "__floateidf", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/floateihf.zig b/lib/compiler_rt/floateihf.zig index ac9fd355c7f6..013e6d2d79cb 100644 --- a/lib/compiler_rt/floateihf.zig +++ b/lib/compiler_rt/floateihf.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const common = @import("common.zig"); const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; -pub const panic = common.panic; - comptime { @export(&__floateihf, .{ .name = "__floateihf", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/floateisf.zig b/lib/compiler_rt/floateisf.zig index f53b75643f73..eb24b6aa4312 100644 --- a/lib/compiler_rt/floateisf.zig +++ b/lib/compiler_rt/floateisf.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const common = @import("common.zig"); const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; -pub const panic = common.panic; - comptime { @export(&__floateisf, .{ .name = "__floateisf", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/floateitf.zig b/lib/compiler_rt/floateitf.zig index 3e07c6becbf8..e5b50ab7a6b3 100644 --- a/lib/compiler_rt/floateitf.zig +++ b/lib/compiler_rt/floateitf.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const common = @import("common.zig"); const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; -pub const panic = common.panic; - comptime { @export(&__floateitf, .{ .name = "__floateitf", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/floateixf.zig b/lib/compiler_rt/floateixf.zig index 65585e2ed30c..ffb8445fd337 100644 --- a/lib/compiler_rt/floateixf.zig +++ b/lib/compiler_rt/floateixf.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const common = @import("common.zig"); const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; -pub const panic = common.panic; - comptime { @export(&__floateixf, .{ .name = "__floateixf", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/floatsidf.zig b/lib/compiler_rt/floatsidf.zig index c3f249a4558a..435c8db9a465 100644 --- a/lib/compiler_rt/floatsidf.zig +++ b/lib/compiler_rt/floatsidf.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_i2d, .{ .name = "__aeabi_i2d", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/floatsihf.zig b/lib/compiler_rt/floatsihf.zig index a5d5d2ba92e8..5f2db12585d9 100644 --- a/lib/compiler_rt/floatsihf.zig +++ b/lib/compiler_rt/floatsihf.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { @export(&__floatsihf, .{ .name = "__floatsihf", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/floatsisf.zig b/lib/compiler_rt/floatsisf.zig index 133bfaabbd3a..9c36387c668c 100644 --- a/lib/compiler_rt/floatsisf.zig +++ b/lib/compiler_rt/floatsisf.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_i2f, .{ .name = "__aeabi_i2f", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/floatsitf.zig b/lib/compiler_rt/floatsitf.zig index 6a5f81ae218e..750633052dce 100644 --- a/lib/compiler_rt/floatsitf.zig +++ b/lib/compiler_rt/floatsitf.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { if (common.want_ppc_abi) { @export(&__floatsitf, .{ .name = "__floatsikf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/floatsixf.zig b/lib/compiler_rt/floatsixf.zig index 31791eb9cc89..59bf7ddb99ff 100644 --- a/lib/compiler_rt/floatsixf.zig +++ b/lib/compiler_rt/floatsixf.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { @export(&__floatsixf, .{ .name = "__floatsixf", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/floattidf.zig b/lib/compiler_rt/floattidf.zig index 420ef9b20148..2ac5726b5166 100644 --- a/lib/compiler_rt/floattidf.zig +++ b/lib/compiler_rt/floattidf.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__floattidf_windows_x86_64, .{ .name = "__floattidf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/floattihf.zig b/lib/compiler_rt/floattihf.zig index 63f079b3a886..9ad705870e9e 100644 --- a/lib/compiler_rt/floattihf.zig +++ b/lib/compiler_rt/floattihf.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__floattihf_windows_x86_64, .{ .name = "__floattihf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/floattisf.zig b/lib/compiler_rt/floattisf.zig index 284580c4b2cc..953192f33115 100644 --- a/lib/compiler_rt/floattisf.zig +++ b/lib/compiler_rt/floattisf.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__floattisf_windows_x86_64, .{ .name = "__floattisf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/floattitf.zig b/lib/compiler_rt/floattitf.zig index c8d2090457fd..3973aa4ab294 100644 --- a/lib/compiler_rt/floattitf.zig +++ b/lib/compiler_rt/floattitf.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__floattitf_windows_x86_64, .{ .name = "__floattitf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/floattixf.zig b/lib/compiler_rt/floattixf.zig index ebf83446d322..ac1df5ba32b3 100644 --- a/lib/compiler_rt/floattixf.zig +++ b/lib/compiler_rt/floattixf.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__floattixf_windows_x86_64, .{ .name = "__floattixf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/floatundidf.zig b/lib/compiler_rt/floatundidf.zig index 887ef8321594..7a9e4afe7af4 100644 --- a/lib/compiler_rt/floatundidf.zig +++ b/lib/compiler_rt/floatundidf.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_ul2d, .{ .name = "__aeabi_ul2d", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/floatundihf.zig b/lib/compiler_rt/floatundihf.zig index 5fefedec1d83..e7a3f865f829 100644 --- a/lib/compiler_rt/floatundihf.zig +++ b/lib/compiler_rt/floatundihf.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { @export(&__floatundihf, .{ .name = "__floatundihf", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/floatundisf.zig b/lib/compiler_rt/floatundisf.zig index 8537779996eb..89e7fa1f4bf6 100644 --- a/lib/compiler_rt/floatundisf.zig +++ b/lib/compiler_rt/floatundisf.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_ul2f, .{ .name = "__aeabi_ul2f", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/floatunditf.zig b/lib/compiler_rt/floatunditf.zig index aadb25132810..d313ff3d12a5 100644 --- a/lib/compiler_rt/floatunditf.zig +++ b/lib/compiler_rt/floatunditf.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { if (common.want_ppc_abi) { @export(&__floatunditf, .{ .name = "__floatundikf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/floatundixf.zig b/lib/compiler_rt/floatundixf.zig index 7f801fd6ba0c..b9691e914488 100644 --- a/lib/compiler_rt/floatundixf.zig +++ b/lib/compiler_rt/floatundixf.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { @export(&__floatundixf, .{ .name = "__floatundixf", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/floatuneidf.zig b/lib/compiler_rt/floatuneidf.zig index c7b1e032ea71..bb8a6579cec5 100644 --- a/lib/compiler_rt/floatuneidf.zig +++ b/lib/compiler_rt/floatuneidf.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const common = @import("common.zig"); const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; -pub const panic = common.panic; - comptime { @export(&__floatuneidf, .{ .name = "__floatuneidf", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/floatuneihf.zig b/lib/compiler_rt/floatuneihf.zig index 00c53a19197c..17b1e1d29059 100644 --- a/lib/compiler_rt/floatuneihf.zig +++ b/lib/compiler_rt/floatuneihf.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const common = @import("common.zig"); const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; -pub const panic = common.panic; - comptime { @export(&__floatuneihf, .{ .name = "__floatuneihf", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/floatuneisf.zig b/lib/compiler_rt/floatuneisf.zig index 4acb0fa7b234..bb43b6ee652c 100644 --- a/lib/compiler_rt/floatuneisf.zig +++ b/lib/compiler_rt/floatuneisf.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const common = @import("common.zig"); const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; -pub const panic = common.panic; - comptime { @export(&__floatuneisf, .{ .name = "__floatuneisf", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/floatuneitf.zig b/lib/compiler_rt/floatuneitf.zig index 323f44611d23..d84678ce115f 100644 --- a/lib/compiler_rt/floatuneitf.zig +++ b/lib/compiler_rt/floatuneitf.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const common = @import("common.zig"); const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; -pub const panic = common.panic; - comptime { @export(&__floatuneitf, .{ .name = "__floatuneitf", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/floatuneixf.zig b/lib/compiler_rt/floatuneixf.zig index 12157d20a343..ad0b8f24de1d 100644 --- a/lib/compiler_rt/floatuneixf.zig +++ b/lib/compiler_rt/floatuneixf.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const common = @import("common.zig"); const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; -pub const panic = common.panic; - comptime { @export(&__floatuneixf, .{ .name = "__floatuneixf", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/floatunsidf.zig b/lib/compiler_rt/floatunsidf.zig index c712428ce24f..fc50a5ad37db 100644 --- a/lib/compiler_rt/floatunsidf.zig +++ b/lib/compiler_rt/floatunsidf.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_ui2d, .{ .name = "__aeabi_ui2d", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/floatunsihf.zig b/lib/compiler_rt/floatunsihf.zig index 5c5778a460b1..123b76fcde1b 100644 --- a/lib/compiler_rt/floatunsihf.zig +++ b/lib/compiler_rt/floatunsihf.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { @export(&__floatunsihf, .{ .name = "__floatunsihf", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/floatunsisf.zig b/lib/compiler_rt/floatunsisf.zig index 9fa213ed2277..4bcceba5c8c9 100644 --- a/lib/compiler_rt/floatunsisf.zig +++ b/lib/compiler_rt/floatunsisf.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_ui2f, .{ .name = "__aeabi_ui2f", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/floatunsitf.zig b/lib/compiler_rt/floatunsitf.zig index d09d31d05dc9..e491987003f0 100644 --- a/lib/compiler_rt/floatunsitf.zig +++ b/lib/compiler_rt/floatunsitf.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { if (common.want_ppc_abi) { @export(&__floatunsitf, .{ .name = "__floatunsikf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/floatunsixf.zig b/lib/compiler_rt/floatunsixf.zig index 678085ad6fcf..875d3476fa99 100644 --- a/lib/compiler_rt/floatunsixf.zig +++ b/lib/compiler_rt/floatunsixf.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { @export(&__floatunsixf, .{ .name = "__floatunsixf", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/floatuntidf.zig b/lib/compiler_rt/floatuntidf.zig index cee154ed0bee..284e50dd367b 100644 --- a/lib/compiler_rt/floatuntidf.zig +++ b/lib/compiler_rt/floatuntidf.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__floatuntidf_windows_x86_64, .{ .name = "__floatuntidf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/floatuntihf.zig b/lib/compiler_rt/floatuntihf.zig index 63cfdb604fac..41da6f1bfb50 100644 --- a/lib/compiler_rt/floatuntihf.zig +++ b/lib/compiler_rt/floatuntihf.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__floatuntihf_windows_x86_64, .{ .name = "__floatuntihf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/floatuntisf.zig b/lib/compiler_rt/floatuntisf.zig index 1e65576f063e..f79d2e5feda5 100644 --- a/lib/compiler_rt/floatuntisf.zig +++ b/lib/compiler_rt/floatuntisf.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__floatuntisf_windows_x86_64, .{ .name = "__floatuntisf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/floatuntitf.zig b/lib/compiler_rt/floatuntitf.zig index 41c48bee990f..77dd22ed5978 100644 --- a/lib/compiler_rt/floatuntitf.zig +++ b/lib/compiler_rt/floatuntitf.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__floatuntitf_windows_x86_64, .{ .name = "__floatuntitf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/floatuntixf.zig b/lib/compiler_rt/floatuntixf.zig index 353a3c3c0d15..12a561b5732a 100644 --- a/lib/compiler_rt/floatuntixf.zig +++ b/lib/compiler_rt/floatuntixf.zig @@ -2,8 +2,6 @@ const builtin = @import("builtin"); const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__floatuntixf_windows_x86_64, .{ .name = "__floatuntixf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/floor.zig b/lib/compiler_rt/floor.zig deleted file mode 100644 index ba1869089aa9..000000000000 --- a/lib/compiler_rt/floor.zig +++ /dev/null @@ -1,238 +0,0 @@ -//! Ported from musl, which is licensed under the MIT license: -//! https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT -//! -//! https://git.musl-libc.org/cgit/musl/tree/src/math/floorf.c -//! https://git.musl-libc.org/cgit/musl/tree/src/math/floor.c -//! https://git.musl-libc.org/cgit/musl/tree/src/math/floorl.c - -const std = @import("std"); -const builtin = @import("builtin"); -const math = std.math; -const mem = std.mem; -const expect = std.testing.expect; -const arch = builtin.cpu.arch; -const common = @import("common.zig"); - -pub const panic = common.panic; - -comptime { - @export(&__floorh, .{ .name = "__floorh", .linkage = common.linkage, .visibility = common.visibility }); - @export(&floorf, .{ .name = "floorf", .linkage = common.linkage, .visibility = common.visibility }); - @export(&floor, .{ .name = "floor", .linkage = common.linkage, .visibility = common.visibility }); - @export(&__floorx, .{ .name = "__floorx", .linkage = common.linkage, .visibility = common.visibility }); - if (common.want_ppc_abi) { - @export(&floorq, .{ .name = "floorf128", .linkage = common.linkage, .visibility = common.visibility }); - } - @export(&floorq, .{ .name = "floorq", .linkage = common.linkage, .visibility = common.visibility }); - @export(&floorl, .{ .name = "floorl", .linkage = common.linkage, .visibility = common.visibility }); -} - -pub fn __floorh(x: f16) callconv(.c) f16 { - var u: u16 = @bitCast(x); - const e = @as(i16, @intCast((u >> 10) & 31)) - 15; - var m: u16 = undefined; - - if (e >= 10) return x; - - if (e >= 0) { - m = @as(u16, 0x03FF) >> @intCast(e); - if (u & m == 0) return x; - if (common.want_float_exceptions) mem.doNotOptimizeAway(x + 0x1.0p120); - if (u >> 15 != 0) u += m; - return @bitCast(u & ~m); - } else { - if (common.want_float_exceptions) mem.doNotOptimizeAway(x + 0x1.0p120); - return if (u >> 15 == 0) 0.0 else if (u << 1 != 0) -1.0 else x; - } -} - -pub fn floorf(x: f32) callconv(.c) f32 { - var u: u32 = @bitCast(x); - const e = @as(i32, @intCast((u >> 23) & 0xFF)) - 0x7F; - var m: u32 = undefined; - - if (e >= 23) return x; - - if (e >= 0) { - m = @as(u32, 0x007FFFFF) >> @intCast(e); - if (u & m == 0) return x; - if (common.want_float_exceptions) mem.doNotOptimizeAway(x + 0x1.0p120); - if (u >> 31 != 0) u += m; - return @bitCast(u & ~m); - } else { - if (common.want_float_exceptions) mem.doNotOptimizeAway(x + 0x1.0p120); - return if (u >> 31 == 0) 0.0 else if (u << 1 != 0) -1.0 else x; - } -} - -pub fn floor(x: f64) callconv(.c) f64 { - const f64_toint = 1.0 / math.floatEps(f64); - - const u: u64 = @bitCast(x); - const e = (u >> 52) & 0x7FF; - var y: f64 = undefined; - - if (e >= 0x3FF + 52 or x == 0) { - return x; - } - - if (u >> 63 != 0) { - y = x - f64_toint + f64_toint - x; - } else { - y = x + f64_toint - f64_toint - x; - } - - if (e <= 0x3FF - 1) { - if (common.want_float_exceptions) mem.doNotOptimizeAway(y); - if (u >> 63 != 0) { - return -1.0; - } else { - return 0.0; - } - } else if (y > 0) { - return x + y - 1; - } else { - return x + y; - } -} - -pub fn __floorx(x: f80) callconv(.c) f80 { - const f80_toint = 1.0 / math.floatEps(f80); - - const u: u80 = @bitCast(x); - const e = (u >> 64) & 0x7FFF; - var y: f80 = undefined; - - if (e >= 0x3FFF + 64 or x == 0) { - return x; - } - - if (u >> 79 != 0) { - y = x - f80_toint + f80_toint - x; - } else { - y = x + f80_toint - f80_toint - x; - } - - if (e <= 0x3FFF - 1) { - if (common.want_float_exceptions) mem.doNotOptimizeAway(y); - if (u >> 79 != 0) { - return -1.0; - } else { - return 0.0; - } - } else if (y > 0) { - return x + y - 1; - } else { - return x + y; - } -} - -pub fn floorq(x: f128) callconv(.c) f128 { - const f128_toint = 1.0 / math.floatEps(f128); - - const u: u128 = @bitCast(x); - const e = (u >> 112) & 0x7FFF; - var y: f128 = undefined; - - if (e >= 0x3FFF + 112 or x == 0) return x; - - if (u >> 127 != 0) { - y = x - f128_toint + f128_toint - x; - } else { - y = x + f128_toint - f128_toint - x; - } - - if (e <= 0x3FFF - 1) { - if (common.want_float_exceptions) mem.doNotOptimizeAway(y); - if (u >> 127 != 0) { - return -1.0; - } else { - return 0.0; - } - } else if (y > 0) { - return x + y - 1; - } else { - return x + y; - } -} - -pub fn floorl(x: c_longdouble) callconv(.c) c_longdouble { - switch (@typeInfo(c_longdouble).float.bits) { - 16 => return __floorh(x), - 32 => return floorf(x), - 64 => return floor(x), - 80 => return __floorx(x), - 128 => return floorq(x), - else => @compileError("unreachable"), - } -} - -test "floor16" { - try expect(__floorh(1.3) == 1.0); - try expect(__floorh(-1.3) == -2.0); - try expect(__floorh(0.2) == 0.0); -} - -test "floor32" { - try expect(floorf(1.3) == 1.0); - try expect(floorf(-1.3) == -2.0); - try expect(floorf(0.2) == 0.0); -} - -test "floor64" { - try expect(floor(1.3) == 1.0); - try expect(floor(-1.3) == -2.0); - try expect(floor(0.2) == 0.0); -} - -test "floor80" { - try expect(__floorx(1.3) == 1.0); - try expect(__floorx(-1.3) == -2.0); - try expect(__floorx(0.2) == 0.0); -} - -test "floor128" { - try expect(floorq(1.3) == 1.0); - try expect(floorq(-1.3) == -2.0); - try expect(floorq(0.2) == 0.0); -} - -test "floor16.special" { - try expect(__floorh(0.0) == 0.0); - try expect(__floorh(-0.0) == -0.0); - try expect(math.isPositiveInf(__floorh(math.inf(f16)))); - try expect(math.isNegativeInf(__floorh(-math.inf(f16)))); - try expect(math.isNan(__floorh(math.nan(f16)))); -} - -test "floor32.special" { - try expect(floorf(0.0) == 0.0); - try expect(floorf(-0.0) == -0.0); - try expect(math.isPositiveInf(floorf(math.inf(f32)))); - try expect(math.isNegativeInf(floorf(-math.inf(f32)))); - try expect(math.isNan(floorf(math.nan(f32)))); -} - -test "floor64.special" { - try expect(floor(0.0) == 0.0); - try expect(floor(-0.0) == -0.0); - try expect(math.isPositiveInf(floor(math.inf(f64)))); - try expect(math.isNegativeInf(floor(-math.inf(f64)))); - try expect(math.isNan(floor(math.nan(f64)))); -} - -test "floor80.special" { - try expect(__floorx(0.0) == 0.0); - try expect(__floorx(-0.0) == -0.0); - try expect(math.isPositiveInf(__floorx(math.inf(f80)))); - try expect(math.isNegativeInf(__floorx(-math.inf(f80)))); - try expect(math.isNan(__floorx(math.nan(f80)))); -} - -test "floor128.special" { - try expect(floorq(0.0) == 0.0); - try expect(floorq(-0.0) == -0.0); - try expect(math.isPositiveInf(floorq(math.inf(f128)))); - try expect(math.isNegativeInf(floorq(-math.inf(f128)))); - try expect(math.isNan(floorq(math.nan(f128)))); -} diff --git a/lib/compiler_rt/floor_ceil.zig b/lib/compiler_rt/floor_ceil.zig new file mode 100644 index 000000000000..e669cb812d72 --- /dev/null +++ b/lib/compiler_rt/floor_ceil.zig @@ -0,0 +1,284 @@ +//! Ported from musl, which is MIT licensed. +//! https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT +//! +//! https://git.musl-libc.org/cgit/musl/tree/src/math/ceilf.c +//! https://git.musl-libc.org/cgit/musl/tree/src/math/ceil.c +//! https://git.musl-libc.org/cgit/musl/tree/src/math/ceill.c +//! +//! https://git.musl-libc.org/cgit/musl/tree/src/math/floorf.c +//! https://git.musl-libc.org/cgit/musl/tree/src/math/floor.c +//! https://git.musl-libc.org/cgit/musl/tree/src/math/floorl.c + +const std = @import("std"); +const math = std.math; +const mem = std.mem; +const expect = std.testing.expect; + +const common = @import("common.zig"); + +comptime { + // floor + @export(&__floorh, .{ .name = "__floorh", .linkage = common.linkage, .visibility = common.visibility }); + @export(&floorf, .{ .name = "floorf", .linkage = common.linkage, .visibility = common.visibility }); + @export(&floor, .{ .name = "floor", .linkage = common.linkage, .visibility = common.visibility }); + @export(&__floorx, .{ .name = "__floorx", .linkage = common.linkage, .visibility = common.visibility }); + if (common.want_ppc_abi) { + @export(&floorq, .{ .name = "floorf128", .linkage = common.linkage, .visibility = common.visibility }); + } + @export(&floorq, .{ .name = "floorq", .linkage = common.linkage, .visibility = common.visibility }); + @export(&floorl, .{ .name = "floorl", .linkage = common.linkage, .visibility = common.visibility }); + + // ceil + @export(&__ceilh, .{ .name = "__ceilh", .linkage = common.linkage, .visibility = common.visibility }); + @export(&ceilf, .{ .name = "ceilf", .linkage = common.linkage, .visibility = common.visibility }); + @export(&ceil, .{ .name = "ceil", .linkage = common.linkage, .visibility = common.visibility }); + @export(&__ceilx, .{ .name = "__ceilx", .linkage = common.linkage, .visibility = common.visibility }); + if (common.want_ppc_abi) { + @export(&ceilq, .{ .name = "ceilf128", .linkage = common.linkage, .visibility = common.visibility }); + } + @export(&ceilq, .{ .name = "ceilq", .linkage = common.linkage, .visibility = common.visibility }); + @export(&ceill, .{ .name = "ceill", .linkage = common.linkage, .visibility = common.visibility }); +} + +pub fn __floorh(x: f16) callconv(.c) f16 { + return impl(f16, .floor, x); +} + +pub fn floorf(x: f32) callconv(.c) f32 { + return impl(f32, .floor, x); +} + +pub fn floor(x: f64) callconv(.c) f64 { + return impl(f64, .floor, x); +} + +pub fn __floorx(x: f80) callconv(.c) f80 { + return impl(f80, .floor, x); +} + +pub fn floorq(x: f128) callconv(.c) f128 { + return impl(f128, .floor, x); +} + +pub fn floorl(x: c_longdouble) callconv(.c) c_longdouble { + return impl(std.meta.Float(@bitSizeOf(c_longdouble)), .floor, x); +} + +pub fn __ceilh(x: f16) callconv(.c) f16 { + return impl(f16, .ceil, x); +} + +pub fn ceilf(x: f32) callconv(.c) f32 { + return impl(f32, .ceil, x); +} + +pub fn ceil(x: f64) callconv(.c) f64 { + return impl(f64, .ceil, x); +} + +pub fn __ceilx(x: f80) callconv(.c) f80 { + return impl(f80, .ceil, x); +} + +pub fn ceilq(x: f128) callconv(.c) f128 { + return impl(f128, .ceil, x); +} + +pub fn ceill(x: c_longdouble) callconv(.c) c_longdouble { + return impl(std.meta.Float(@bitSizeOf(c_longdouble)), .ceil, x); +} + +inline fn impl(comptime T: type, comptime op: enum { floor, ceil }, x: T) T { + const C = 1.0 / math.floatEps(T); + const mantissa = math.floatMantissaBits(T); + const mask = (1 << math.floatExponentBits(T)) - 1; + const bias = (1 << (math.floatExponentBits(T) - 1)) - 1; + + const bits = @bitSizeOf(T); + const U = @Int(.unsigned, bits); + var u: U = @bitCast(x); + switch (T) { + f16, f32 => { + const e = @as(@Int(.signed, bits), @intCast((u >> mantissa) & mask)) - bias; + if (e >= mantissa) return x; + + if (e >= 0) { + const m = (@as(U, 1) << @intCast(mantissa - e)) - 1; + if (u & m == 0) return x; + if (common.want_float_exceptions) mem.doNotOptimizeAway(x + 0x1.0p120); + if (u >> bits - 1 == @intFromBool(op == .floor)) u += m; + return @bitCast(u & ~m); + } else { + if (common.want_float_exceptions) mem.doNotOptimizeAway(x + 0x1.0p120); + return switch (op) { + .floor => if (u >> bits - 1 == 0) 0.0 else if (u << 1 != 0) -1.0 else x, + .ceil => if (u >> bits - 1 != 0) -0.0 else if (u << 1 != 0) 1.0 else x, + }; + } + }, + f64, f80, f128 => { + const e = (u >> mantissa) & mask; + if (e >= bias + math.floatFractionalBits(T) or x == 0) return x; + + const positive = u >> @bitSizeOf(T) - 1 == 0; + const y: T = if (positive) + x + C - C - x + else + x - C + C - x; + + if (e <= bias - 1) { + if (common.want_float_exceptions) mem.doNotOptimizeAway(y); + return switch (op) { + .floor => if (positive) 0.0 else -1.0, + .ceil => if (positive) 1.0 else -0.0, + }; + } + switch (op) { + .floor => if (y > 0) return x + y - 1, + .ceil => if (y < 0) return x + y + 1, + } + return x + y; + }, + else => unreachable, + } +} + +test "floor16" { + try expect(__floorh(1.3) == 1.0); + try expect(__floorh(-1.3) == -2.0); + try expect(__floorh(0.2) == 0.0); +} + +test "floor32" { + try expect(floorf(1.3) == 1.0); + try expect(floorf(-1.3) == -2.0); + try expect(floorf(0.2) == 0.0); +} + +test "floor64" { + try expect(floor(1.3) == 1.0); + try expect(floor(-1.3) == -2.0); + try expect(floor(0.2) == 0.0); +} + +test "floor80" { + try expect(__floorx(1.3) == 1.0); + try expect(__floorx(-1.3) == -2.0); + try expect(__floorx(0.2) == 0.0); +} + +test "floor128" { + try expect(floorq(1.3) == 1.0); + try expect(floorq(-1.3) == -2.0); + try expect(floorq(0.2) == 0.0); +} + +test "floor16.special" { + try expect(__floorh(0.0) == 0.0); + try expect(__floorh(-0.0) == -0.0); + try expect(math.isPositiveInf(__floorh(math.inf(f16)))); + try expect(math.isNegativeInf(__floorh(-math.inf(f16)))); + try expect(math.isNan(__floorh(math.nan(f16)))); +} + +test "floor32.special" { + try expect(floorf(0.0) == 0.0); + try expect(floorf(-0.0) == -0.0); + try expect(math.isPositiveInf(floorf(math.inf(f32)))); + try expect(math.isNegativeInf(floorf(-math.inf(f32)))); + try expect(math.isNan(floorf(math.nan(f32)))); +} + +test "floor64.special" { + try expect(floor(0.0) == 0.0); + try expect(floor(-0.0) == -0.0); + try expect(math.isPositiveInf(floor(math.inf(f64)))); + try expect(math.isNegativeInf(floor(-math.inf(f64)))); + try expect(math.isNan(floor(math.nan(f64)))); +} + +test "floor80.special" { + try expect(__floorx(0.0) == 0.0); + try expect(__floorx(-0.0) == -0.0); + try expect(math.isPositiveInf(__floorx(math.inf(f80)))); + try expect(math.isNegativeInf(__floorx(-math.inf(f80)))); + try expect(math.isNan(__floorx(math.nan(f80)))); +} + +test "floor128.special" { + try expect(floorq(0.0) == 0.0); + try expect(floorq(-0.0) == -0.0); + try expect(math.isPositiveInf(floorq(math.inf(f128)))); + try expect(math.isNegativeInf(floorq(-math.inf(f128)))); + try expect(math.isNan(floorq(math.nan(f128)))); +} + +test "ceil16" { + try expect(__ceilh(1.3) == 2.0); + try expect(__ceilh(-1.3) == -1.0); + try expect(__ceilh(0.2) == 1.0); +} + +test "ceil32" { + try expect(ceilf(1.3) == 2.0); + try expect(ceilf(-1.3) == -1.0); + try expect(ceilf(0.2) == 1.0); +} + +test "ceil64" { + try expect(ceil(1.3) == 2.0); + try expect(ceil(-1.3) == -1.0); + try expect(ceil(0.2) == 1.0); +} + +test "ceil80" { + try expect(__ceilx(1.3) == 2.0); + try expect(__ceilx(-1.3) == -1.0); + try expect(__ceilx(0.2) == 1.0); +} + +test "ceil128" { + try expect(ceilq(1.3) == 2.0); + try expect(ceilq(-1.3) == -1.0); + try expect(ceilq(0.2) == 1.0); +} + +test "ceil16.special" { + try expect(__ceilh(0.0) == 0.0); + try expect(__ceilh(-0.0) == -0.0); + try expect(math.isPositiveInf(__ceilh(math.inf(f16)))); + try expect(math.isNegativeInf(__ceilh(-math.inf(f16)))); + try expect(math.isNan(__ceilh(math.nan(f16)))); +} + +test "ceil32.special" { + try expect(ceilf(0.0) == 0.0); + try expect(ceilf(-0.0) == -0.0); + try expect(math.isPositiveInf(ceilf(math.inf(f32)))); + try expect(math.isNegativeInf(ceilf(-math.inf(f32)))); + try expect(math.isNan(ceilf(math.nan(f32)))); +} + +test "ceil64.special" { + try expect(ceil(0.0) == 0.0); + try expect(ceil(-0.0) == -0.0); + try expect(math.isPositiveInf(ceil(math.inf(f64)))); + try expect(math.isNegativeInf(ceil(-math.inf(f64)))); + try expect(math.isNan(ceil(math.nan(f64)))); +} + +test "ceil80.special" { + try expect(__ceilx(0.0) == 0.0); + try expect(__ceilx(-0.0) == -0.0); + try expect(math.isPositiveInf(__ceilx(math.inf(f80)))); + try expect(math.isNegativeInf(__ceilx(-math.inf(f80)))); + try expect(math.isNan(__ceilx(math.nan(f80)))); +} + +test "ceil128.special" { + try expect(ceilq(0.0) == 0.0); + try expect(ceilq(-0.0) == -0.0); + try expect(math.isPositiveInf(ceilq(math.inf(f128)))); + try expect(math.isNegativeInf(ceilq(-math.inf(f128)))); + try expect(math.isNan(ceilq(math.nan(f128)))); +} diff --git a/lib/compiler_rt/fma.zig b/lib/compiler_rt/fma.zig index 79a120d5a2cc..cce9215f881d 100644 --- a/lib/compiler_rt/fma.zig +++ b/lib/compiler_rt/fma.zig @@ -10,8 +10,6 @@ const math = std.math; const expect = std.testing.expect; const common = @import("common.zig"); -pub const panic = common.panic; - comptime { @export(&__fmah, .{ .name = "__fmah", .linkage = common.linkage, .visibility = common.visibility }); @export(&fmaf, .{ .name = "fmaf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fmax.zig b/lib/compiler_rt/fmax.zig index 02e7d1d75bbe..19a7c3f6f789 100644 --- a/lib/compiler_rt/fmax.zig +++ b/lib/compiler_rt/fmax.zig @@ -4,8 +4,6 @@ const math = std.math; const arch = builtin.cpu.arch; const common = @import("common.zig"); -pub const panic = common.panic; - comptime { @export(&__fmaxh, .{ .name = "__fmaxh", .linkage = common.linkage, .visibility = common.visibility }); @export(&fmaxf, .{ .name = "fmaxf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fmin.zig b/lib/compiler_rt/fmin.zig index 71f9ef589a76..aa54ba6e0b08 100644 --- a/lib/compiler_rt/fmin.zig +++ b/lib/compiler_rt/fmin.zig @@ -4,8 +4,6 @@ const math = std.math; const arch = builtin.cpu.arch; const common = @import("common.zig"); -pub const panic = common.panic; - comptime { @export(&__fminh, .{ .name = "__fminh", .linkage = common.linkage, .visibility = common.visibility }); @export(&fminf, .{ .name = "fminf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/fmod.zig b/lib/compiler_rt/fmod.zig index 5c055049e3ff..ae5abaae65f6 100644 --- a/lib/compiler_rt/fmod.zig +++ b/lib/compiler_rt/fmod.zig @@ -6,8 +6,6 @@ const arch = builtin.cpu.arch; const common = @import("common.zig"); const normalize = common.normalize; -pub const panic = common.panic; - comptime { @export(&__fmodh, .{ .name = "__fmodh", .linkage = common.linkage, .visibility = common.visibility }); @export(&fmodf, .{ .name = "fmodf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/gedf2.zig b/lib/compiler_rt/gedf2.zig index 33b4fa992609..aeb08b4a8b9e 100644 --- a/lib/compiler_rt/gedf2.zig +++ b/lib/compiler_rt/gedf2.zig @@ -3,8 +3,6 @@ const common = @import("./common.zig"); const comparef = @import("./comparef.zig"); -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_dcmpge, .{ .name = "__aeabi_dcmpge", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/gehf2.zig b/lib/compiler_rt/gehf2.zig index 12eccf98d824..b46d4a1a24d0 100644 --- a/lib/compiler_rt/gehf2.zig +++ b/lib/compiler_rt/gehf2.zig @@ -3,8 +3,6 @@ const common = @import("./common.zig"); const comparef = @import("./comparef.zig"); -pub const panic = common.panic; - comptime { @export(&__gehf2, .{ .name = "__gehf2", .linkage = common.linkage, .visibility = common.visibility }); @export(&__gthf2, .{ .name = "__gthf2", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/gesf2.zig b/lib/compiler_rt/gesf2.zig index 5f9aefef4795..d4b6a23c662d 100644 --- a/lib/compiler_rt/gesf2.zig +++ b/lib/compiler_rt/gesf2.zig @@ -3,8 +3,6 @@ const common = @import("./common.zig"); const comparef = @import("./comparef.zig"); -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_fcmpge, .{ .name = "__aeabi_fcmpge", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/getf2.zig b/lib/compiler_rt/getf2.zig index 3a17843718c8..a6014b365e56 100644 --- a/lib/compiler_rt/getf2.zig +++ b/lib/compiler_rt/getf2.zig @@ -3,8 +3,6 @@ const common = @import("./common.zig"); const comparef = @import("./comparef.zig"); -pub const panic = common.panic; - comptime { if (common.want_ppc_abi) { @export(&__getf2, .{ .name = "__gekf2", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/gexf2.zig b/lib/compiler_rt/gexf2.zig index 7ea0d6eebe5b..365c298cc616 100644 --- a/lib/compiler_rt/gexf2.zig +++ b/lib/compiler_rt/gexf2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const comparef = @import("./comparef.zig"); -pub const panic = common.panic; - comptime { @export(&__gexf2, .{ .name = "__gexf2", .linkage = common.linkage, .visibility = common.visibility }); @export(&__gtxf2, .{ .name = "__gtxf2", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/int.zig b/lib/compiler_rt/int.zig index 16c504ee66d1..3f38bad973d5 100644 --- a/lib/compiler_rt/int.zig +++ b/lib/compiler_rt/int.zig @@ -10,8 +10,6 @@ const common = @import("common.zig"); const udivmod = @import("udivmod.zig").udivmod; const __divti3 = @import("divti3.zig").__divti3; -pub const panic = common.panic; - comptime { @export(&__divmodti4, .{ .name = "__divmodti4", .linkage = common.linkage, .visibility = common.visibility }); @export(&__udivmoddi4, .{ .name = "__udivmoddi4", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/log.zig b/lib/compiler_rt/log.zig index f8bbf430ace4..3270b2791616 100644 --- a/lib/compiler_rt/log.zig +++ b/lib/compiler_rt/log.zig @@ -1,8 +1,8 @@ //! Ported from musl, which is licensed under the MIT license: //! https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT //! -//! https://git.musl-libc.org/cgit/musl/tree/src/math/lnf.c -//! https://git.musl-libc.org/cgit/musl/tree/src/math/ln.c +//! https://git.musl-libc.org/cgit/musl/tree/src/math/logf.c?h=2d7d05f031e014068a61d3076c6178513395d2ae +//! https://git.musl-libc.org/cgit/musl/tree/src/math/log.c?h=1b76ff0767d01df72f692806ee5adee13c67ef88 const std = @import("std"); const builtin = @import("builtin"); @@ -12,8 +12,6 @@ const expectEqual = std.testing.expectEqual; const arch = builtin.cpu.arch; const common = @import("common.zig"); -pub const panic = common.panic; - comptime { @export(&__logh, .{ .name = "__logh", .linkage = common.linkage, .visibility = common.visibility }); @export(&logf, .{ .name = "logf", .linkage = common.linkage, .visibility = common.visibility }); @@ -47,11 +45,11 @@ pub fn logf(x_: f32) callconv(.c) f32 { if (ix < 0x00800000 or ix >> 31 != 0) { // log(+-0) = -inf if (ix << 1 == 0) { - return -math.inf(f32); + return if (common.want_float_exceptions) -1 / (x * x) else -std.math.inf(f64); } // log(-#) = nan if (ix >> 31 != 0) { - return math.nan(f32); + return if (common.want_float_exceptions) (x - x) / 0.0 else math.nan(f64); } // subnormal, scale x @@ -83,60 +81,355 @@ pub fn logf(x_: f32) callconv(.c) f32 { return s * (hfsq + R) + dk * ln2_lo - hfsq + f + dk * ln2_hi; } -pub fn log(x_: f64) callconv(.c) f64 { - const ln2_hi: f64 = 6.93147180369123816490e-01; - const ln2_lo: f64 = 1.90821492927058770002e-10; - const Lg1: f64 = 6.666666666666735130e-01; - const Lg2: f64 = 3.999999999940941908e-01; - const Lg3: f64 = 2.857142874366239149e-01; - const Lg4: f64 = 2.222219843214978396e-01; - const Lg5: f64 = 1.818357216161805012e-01; - const Lg6: f64 = 1.531383769920937332e-01; - const Lg7: f64 = 1.479819860511658591e-01; +pub fn log(x: f64) callconv(.c) f64 { + const poly1 = [_]f64{ + -0x1p-1, + 0x1.5555555555577p-2, + -0x1.ffffffffffdcbp-3, + 0x1.999999995dd0cp-3, + -0x1.55555556745a7p-3, + 0x1.24924a344de3p-3, + -0x1.fffffa4423d65p-4, + 0x1.c7184282ad6cap-4, + -0x1.999eb43b068ffp-4, + 0x1.78182f7afd085p-4, + -0x1.5521375d145cdp-4, + }; - var x = x_; - var ix: u64 = @bitCast(x); - var hx: u32 = @intCast(ix >> 32); - var k: i32 = 0; + const poly = [_]f64{ + -0x1.0000000000001p-1, + 0x1.555555551305bp-2, + -0x1.fffffffeb459p-3, + 0x1.999b324f10111p-3, + -0x1.55575e506c89fp-3, + }; - if (hx < 0x00100000 or hx >> 31 != 0) { - // log(+-0) = -inf - if (ix << 1 == 0) { - return -math.inf(f64); - } - // log(-#) = nan - if (hx >> 31 != 0) { - return math.nan(f64); + const tab = [128]struct { invc: f64, logc: f64 }{ + .{ .invc = 0x1.734f0c3e0de9fp+0, .logc = -0x1.7cc7f79e69000p-2 }, + .{ .invc = 0x1.713786a2ce91fp+0, .logc = -0x1.76feec20d0000p-2 }, + .{ .invc = 0x1.6f26008fab5a0p+0, .logc = -0x1.713e31351e000p-2 }, + .{ .invc = 0x1.6d1a61f138c7dp+0, .logc = -0x1.6b85b38287800p-2 }, + .{ .invc = 0x1.6b1490bc5b4d1p+0, .logc = -0x1.65d5590807800p-2 }, + .{ .invc = 0x1.69147332f0cbap+0, .logc = -0x1.602d076180000p-2 }, + .{ .invc = 0x1.6719f18224223p+0, .logc = -0x1.5a8ca86909000p-2 }, + .{ .invc = 0x1.6524f99a51ed9p+0, .logc = -0x1.54f4356035000p-2 }, + .{ .invc = 0x1.63356aa8f24c4p+0, .logc = -0x1.4f637c36b4000p-2 }, + .{ .invc = 0x1.614b36b9ddc14p+0, .logc = -0x1.49da7fda85000p-2 }, + .{ .invc = 0x1.5f66452c65c4cp+0, .logc = -0x1.445923989a800p-2 }, + .{ .invc = 0x1.5d867b5912c4fp+0, .logc = -0x1.3edf439b0b800p-2 }, + .{ .invc = 0x1.5babccb5b90dep+0, .logc = -0x1.396ce448f7000p-2 }, + .{ .invc = 0x1.59d61f2d91a78p+0, .logc = -0x1.3401e17bda000p-2 }, + .{ .invc = 0x1.5805612465687p+0, .logc = -0x1.2e9e2ef468000p-2 }, + .{ .invc = 0x1.56397cee76bd3p+0, .logc = -0x1.2941b3830e000p-2 }, + .{ .invc = 0x1.54725e2a77f93p+0, .logc = -0x1.23ec58cda8800p-2 }, + .{ .invc = 0x1.52aff42064583p+0, .logc = -0x1.1e9e129279000p-2 }, + .{ .invc = 0x1.50f22dbb2bddfp+0, .logc = -0x1.1956d2b48f800p-2 }, + .{ .invc = 0x1.4f38f4734ded7p+0, .logc = -0x1.141679ab9f800p-2 }, + .{ .invc = 0x1.4d843cfde2840p+0, .logc = -0x1.0edd094ef9800p-2 }, + .{ .invc = 0x1.4bd3ec078a3c8p+0, .logc = -0x1.09aa518db1000p-2 }, + .{ .invc = 0x1.4a27fc3e0258ap+0, .logc = -0x1.047e65263b800p-2 }, + .{ .invc = 0x1.4880524d48434p+0, .logc = -0x1.feb224586f000p-3 }, + .{ .invc = 0x1.46dce1b192d0bp+0, .logc = -0x1.f474a7517b000p-3 }, + .{ .invc = 0x1.453d9d3391854p+0, .logc = -0x1.ea4443d103000p-3 }, + .{ .invc = 0x1.43a2744b4845ap+0, .logc = -0x1.e020d44e9b000p-3 }, + .{ .invc = 0x1.420b54115f8fbp+0, .logc = -0x1.d60a22977f000p-3 }, + .{ .invc = 0x1.40782da3ef4b1p+0, .logc = -0x1.cc00104959000p-3 }, + .{ .invc = 0x1.3ee8f5d57fe8fp+0, .logc = -0x1.c202956891000p-3 }, + .{ .invc = 0x1.3d5d9a00b4ce9p+0, .logc = -0x1.b81178d811000p-3 }, + .{ .invc = 0x1.3bd60c010c12bp+0, .logc = -0x1.ae2c9ccd3d000p-3 }, + .{ .invc = 0x1.3a5242b75dab8p+0, .logc = -0x1.a45402e129000p-3 }, + .{ .invc = 0x1.38d22cd9fd002p+0, .logc = -0x1.9a877681df000p-3 }, + .{ .invc = 0x1.3755bc5847a1cp+0, .logc = -0x1.90c6d69483000p-3 }, + .{ .invc = 0x1.35dce49ad36e2p+0, .logc = -0x1.87120a645c000p-3 }, + .{ .invc = 0x1.34679984dd440p+0, .logc = -0x1.7d68fb4143000p-3 }, + .{ .invc = 0x1.32f5cceffcb24p+0, .logc = -0x1.73cb83c627000p-3 }, + .{ .invc = 0x1.3187775a10d49p+0, .logc = -0x1.6a39a9b376000p-3 }, + .{ .invc = 0x1.301c8373e3990p+0, .logc = -0x1.60b3154b7a000p-3 }, + .{ .invc = 0x1.2eb4ebb95f841p+0, .logc = -0x1.5737d76243000p-3 }, + .{ .invc = 0x1.2d50a0219a9d1p+0, .logc = -0x1.4dc7b8fc23000p-3 }, + .{ .invc = 0x1.2bef9a8b7fd2ap+0, .logc = -0x1.4462c51d20000p-3 }, + .{ .invc = 0x1.2a91c7a0c1babp+0, .logc = -0x1.3b08abc830000p-3 }, + .{ .invc = 0x1.293726014b530p+0, .logc = -0x1.31b996b490000p-3 }, + .{ .invc = 0x1.27dfa5757a1f5p+0, .logc = -0x1.2875490a44000p-3 }, + .{ .invc = 0x1.268b39b1d3bbfp+0, .logc = -0x1.1f3b9f879a000p-3 }, + .{ .invc = 0x1.2539d838ff5bdp+0, .logc = -0x1.160c8252ca000p-3 }, + .{ .invc = 0x1.23eb7aac9083bp+0, .logc = -0x1.0ce7f57f72000p-3 }, + .{ .invc = 0x1.22a012ba940b6p+0, .logc = -0x1.03cdc49fea000p-3 }, + .{ .invc = 0x1.2157996cc4132p+0, .logc = -0x1.f57bdbc4b8000p-4 }, + .{ .invc = 0x1.201201dd2fc9bp+0, .logc = -0x1.e370896404000p-4 }, + .{ .invc = 0x1.1ecf4494d480bp+0, .logc = -0x1.d17983ef94000p-4 }, + .{ .invc = 0x1.1d8f5528f6569p+0, .logc = -0x1.bf9674ed8a000p-4 }, + .{ .invc = 0x1.1c52311577e7cp+0, .logc = -0x1.adc79202f6000p-4 }, + .{ .invc = 0x1.1b17c74cb26e9p+0, .logc = -0x1.9c0c3e7288000p-4 }, + .{ .invc = 0x1.19e010c2c1ab6p+0, .logc = -0x1.8a646b372c000p-4 }, + .{ .invc = 0x1.18ab07bb670bdp+0, .logc = -0x1.78d01b3ac0000p-4 }, + .{ .invc = 0x1.1778a25efbcb6p+0, .logc = -0x1.674f145380000p-4 }, + .{ .invc = 0x1.1648d354c31dap+0, .logc = -0x1.55e0e6d878000p-4 }, + .{ .invc = 0x1.151b990275fddp+0, .logc = -0x1.4485cdea1e000p-4 }, + .{ .invc = 0x1.13f0ea432d24cp+0, .logc = -0x1.333d94d6aa000p-4 }, + .{ .invc = 0x1.12c8b7210f9dap+0, .logc = -0x1.22079f8c56000p-4 }, + .{ .invc = 0x1.11a3028ecb531p+0, .logc = -0x1.10e4698622000p-4 }, + .{ .invc = 0x1.107fbda8434afp+0, .logc = -0x1.ffa6c6ad20000p-5 }, + .{ .invc = 0x1.0f5ee0f4e6bb3p+0, .logc = -0x1.dda8d4a774000p-5 }, + .{ .invc = 0x1.0e4065d2a9fcep+0, .logc = -0x1.bbcece4850000p-5 }, + .{ .invc = 0x1.0d244632ca521p+0, .logc = -0x1.9a1894012c000p-5 }, + .{ .invc = 0x1.0c0a77ce2981ap+0, .logc = -0x1.788583302c000p-5 }, + .{ .invc = 0x1.0af2f83c636d1p+0, .logc = -0x1.5715e67d68000p-5 }, + .{ .invc = 0x1.09ddb98a01339p+0, .logc = -0x1.35c8a49658000p-5 }, + .{ .invc = 0x1.08cabaf52e7dfp+0, .logc = -0x1.149e364154000p-5 }, + .{ .invc = 0x1.07b9f2f4e28fbp+0, .logc = -0x1.e72c082eb8000p-6 }, + .{ .invc = 0x1.06ab58c358f19p+0, .logc = -0x1.a55f152528000p-6 }, + .{ .invc = 0x1.059eea5ecf92cp+0, .logc = -0x1.63d62cf818000p-6 }, + .{ .invc = 0x1.04949cdd12c90p+0, .logc = -0x1.228fb8caa0000p-6 }, + .{ .invc = 0x1.038c6c6f0ada9p+0, .logc = -0x1.c317b20f90000p-7 }, + .{ .invc = 0x1.02865137932a9p+0, .logc = -0x1.419355daa0000p-7 }, + .{ .invc = 0x1.0182427ea7348p+0, .logc = -0x1.81203c2ec0000p-8 }, + .{ .invc = 0x1.008040614b195p+0, .logc = -0x1.0040979240000p-9 }, + .{ .invc = 0x1.fe01ff726fa1ap-1, .logc = 0x1.feff384900000p-9 }, + .{ .invc = 0x1.fa11cc261ea74p-1, .logc = 0x1.7dc41353d0000p-7 }, + .{ .invc = 0x1.f6310b081992ep-1, .logc = 0x1.3cea3c4c28000p-6 }, + .{ .invc = 0x1.f25f63ceeadcdp-1, .logc = 0x1.b9fc114890000p-6 }, + .{ .invc = 0x1.ee9c8039113e7p-1, .logc = 0x1.1b0d8ce110000p-5 }, + .{ .invc = 0x1.eae8078cbb1abp-1, .logc = 0x1.58a5bd001c000p-5 }, + .{ .invc = 0x1.e741aa29d0c9bp-1, .logc = 0x1.95c8340d88000p-5 }, + .{ .invc = 0x1.e3a91830a99b5p-1, .logc = 0x1.d276aef578000p-5 }, + .{ .invc = 0x1.e01e009609a56p-1, .logc = 0x1.07598e598c000p-4 }, + .{ .invc = 0x1.dca01e577bb98p-1, .logc = 0x1.253f5e30d2000p-4 }, + .{ .invc = 0x1.d92f20b7c9103p-1, .logc = 0x1.42edd8b380000p-4 }, + .{ .invc = 0x1.d5cac66fb5ccep-1, .logc = 0x1.606598757c000p-4 }, + .{ .invc = 0x1.d272caa5ede9dp-1, .logc = 0x1.7da76356a0000p-4 }, + .{ .invc = 0x1.cf26e3e6b2ccdp-1, .logc = 0x1.9ab434e1c6000p-4 }, + .{ .invc = 0x1.cbe6da2a77902p-1, .logc = 0x1.b78c7bb0d6000p-4 }, + .{ .invc = 0x1.c8b266d37086dp-1, .logc = 0x1.d431332e72000p-4 }, + .{ .invc = 0x1.c5894bd5d5804p-1, .logc = 0x1.f0a3171de6000p-4 }, + .{ .invc = 0x1.c26b533bb9f8cp-1, .logc = 0x1.067152b914000p-3 }, + .{ .invc = 0x1.bf583eeece73fp-1, .logc = 0x1.147858292b000p-3 }, + .{ .invc = 0x1.bc4fd75db96c1p-1, .logc = 0x1.2266ecdca3000p-3 }, + .{ .invc = 0x1.b951e0c864a28p-1, .logc = 0x1.303d7a6c55000p-3 }, + .{ .invc = 0x1.b65e2c5ef3e2cp-1, .logc = 0x1.3dfc33c331000p-3 }, + .{ .invc = 0x1.b374867c9888bp-1, .logc = 0x1.4ba366b7a8000p-3 }, + .{ .invc = 0x1.b094b211d304ap-1, .logc = 0x1.5933928d1f000p-3 }, + .{ .invc = 0x1.adbe885f2ef7ep-1, .logc = 0x1.66acd2418f000p-3 }, + .{ .invc = 0x1.aaf1d31603da2p-1, .logc = 0x1.740f8ec669000p-3 }, + .{ .invc = 0x1.a82e63fd358a7p-1, .logc = 0x1.815c0f51af000p-3 }, + .{ .invc = 0x1.a5740ef09738bp-1, .logc = 0x1.8e92954f68000p-3 }, + .{ .invc = 0x1.a2c2a90ab4b27p-1, .logc = 0x1.9bb3602f84000p-3 }, + .{ .invc = 0x1.a01a01393f2d1p-1, .logc = 0x1.a8bed1c2c0000p-3 }, + .{ .invc = 0x1.9d79f24db3c1bp-1, .logc = 0x1.b5b515c01d000p-3 }, + .{ .invc = 0x1.9ae2505c7b190p-1, .logc = 0x1.c2967ccbcc000p-3 }, + .{ .invc = 0x1.9852ef297ce2fp-1, .logc = 0x1.cf635d5486000p-3 }, + .{ .invc = 0x1.95cbaeea44b75p-1, .logc = 0x1.dc1bd3446c000p-3 }, + .{ .invc = 0x1.934c69de74838p-1, .logc = 0x1.e8c01b8cfe000p-3 }, + .{ .invc = 0x1.90d4f2f6752e6p-1, .logc = 0x1.f5509c0179000p-3 }, + .{ .invc = 0x1.8e6528effd79dp-1, .logc = 0x1.00e6c121fb800p-2 }, + .{ .invc = 0x1.8bfce9fcc007cp-1, .logc = 0x1.071b80e93d000p-2 }, + .{ .invc = 0x1.899c0dabec30ep-1, .logc = 0x1.0d46b9e867000p-2 }, + .{ .invc = 0x1.87427aa2317fbp-1, .logc = 0x1.13687334bd000p-2 }, + .{ .invc = 0x1.84f00acb39a08p-1, .logc = 0x1.1980d67234800p-2 }, + .{ .invc = 0x1.82a49e8653e55p-1, .logc = 0x1.1f8ffe0cc8000p-2 }, + .{ .invc = 0x1.8060195f40260p-1, .logc = 0x1.2595fd7636800p-2 }, + .{ .invc = 0x1.7e22563e0a329p-1, .logc = 0x1.2b9300914a800p-2 }, + .{ .invc = 0x1.7beb377dcb5adp-1, .logc = 0x1.3187210436000p-2 }, + .{ .invc = 0x1.79baa679725c2p-1, .logc = 0x1.377266dec1800p-2 }, + .{ .invc = 0x1.77907f2170657p-1, .logc = 0x1.3d54ffbaf3000p-2 }, + .{ .invc = 0x1.756cadbd6130cp-1, .logc = 0x1.432eee32fe000p-2 }, + }; + + const tab2 = [128]struct { chi: f64, clo: f64 }{ + .{ .chi = 0x1.61000014fb66bp-1, .clo = 0x1.e026c91425b3cp-56 }, + .{ .chi = 0x1.63000034db495p-1, .clo = 0x1.dbfea48005d41p-55 }, + .{ .chi = 0x1.650000d94d478p-1, .clo = 0x1.e7fa786d6a5b7p-55 }, + .{ .chi = 0x1.67000074e6fadp-1, .clo = 0x1.1fcea6b54254cp-57 }, + .{ .chi = 0x1.68ffffedf0faep-1, .clo = -0x1.c7e274c590efdp-56 }, + .{ .chi = 0x1.6b0000763c5bcp-1, .clo = -0x1.ac16848dcda01p-55 }, + .{ .chi = 0x1.6d0001e5cc1f6p-1, .clo = 0x1.33f1c9d499311p-55 }, + .{ .chi = 0x1.6efffeb05f63ep-1, .clo = -0x1.e80041ae22d53p-56 }, + .{ .chi = 0x1.710000e86978p-1, .clo = 0x1.bff6671097952p-56 }, + .{ .chi = 0x1.72ffffc67e912p-1, .clo = 0x1.c00e226bd8724p-55 }, + .{ .chi = 0x1.74fffdf81116ap-1, .clo = -0x1.e02916ef101d2p-57 }, + .{ .chi = 0x1.770000f679c9p-1, .clo = -0x1.7fc71cd549c74p-57 }, + .{ .chi = 0x1.78ffffa7ec835p-1, .clo = 0x1.1bec19ef50483p-55 }, + .{ .chi = 0x1.7affffe20c2e6p-1, .clo = -0x1.07e1729cc6465p-56 }, + .{ .chi = 0x1.7cfffed3fc9p-1, .clo = -0x1.08072087b8b1cp-55 }, + .{ .chi = 0x1.7efffe9261a76p-1, .clo = 0x1.dc0286d9df9aep-55 }, + .{ .chi = 0x1.81000049ca3e8p-1, .clo = 0x1.97fd251e54c33p-55 }, + .{ .chi = 0x1.8300017932c8fp-1, .clo = -0x1.afee9b630f381p-55 }, + .{ .chi = 0x1.850000633739cp-1, .clo = 0x1.9bfbf6b6535bcp-55 }, + .{ .chi = 0x1.87000204289c6p-1, .clo = -0x1.bbf65f3117b75p-55 }, + .{ .chi = 0x1.88fffebf57904p-1, .clo = -0x1.9006ea23dcb57p-55 }, + .{ .chi = 0x1.8b00022bc04dfp-1, .clo = -0x1.d00df38e04b0ap-56 }, + .{ .chi = 0x1.8cfffe50c1b8ap-1, .clo = -0x1.8007146ff9f05p-55 }, + .{ .chi = 0x1.8effffc918e43p-1, .clo = 0x1.3817bd07a7038p-55 }, + .{ .chi = 0x1.910001efa5fc7p-1, .clo = 0x1.93e9176dfb403p-55 }, + .{ .chi = 0x1.9300013467bb9p-1, .clo = 0x1.f804e4b980276p-56 }, + .{ .chi = 0x1.94fffe6ee076fp-1, .clo = -0x1.f7ef0d9ff622ep-55 }, + .{ .chi = 0x1.96fffde3c12d1p-1, .clo = -0x1.082aa962638bap-56 }, + .{ .chi = 0x1.98ffff4458a0dp-1, .clo = -0x1.7801b9164a8efp-55 }, + .{ .chi = 0x1.9afffdd982e3ep-1, .clo = -0x1.740e08a5a9337p-55 }, + .{ .chi = 0x1.9cfffed49fb66p-1, .clo = 0x1.fce08c19bep-60 }, + .{ .chi = 0x1.9f00020f19c51p-1, .clo = -0x1.a3faa27885b0ap-55 }, + .{ .chi = 0x1.a10001145b006p-1, .clo = 0x1.4ff489958da56p-56 }, + .{ .chi = 0x1.a300007bbf6fap-1, .clo = 0x1.cbeab8a2b6d18p-55 }, + .{ .chi = 0x1.a500010971d79p-1, .clo = 0x1.8fecadd78793p-55 }, + .{ .chi = 0x1.a70001df52e48p-1, .clo = -0x1.f41763dd8abdbp-55 }, + .{ .chi = 0x1.a90001c593352p-1, .clo = -0x1.ebf0284c27612p-55 }, + .{ .chi = 0x1.ab0002a4f3e4bp-1, .clo = -0x1.9fd043cff3f5fp-57 }, + .{ .chi = 0x1.acfffd7ae1ed1p-1, .clo = -0x1.23ee7129070b4p-55 }, + .{ .chi = 0x1.aefffee510478p-1, .clo = 0x1.a063ee00edea3p-57 }, + .{ .chi = 0x1.b0fffdb650d5bp-1, .clo = 0x1.a06c8381f0ab9p-58 }, + .{ .chi = 0x1.b2ffffeaaca57p-1, .clo = -0x1.9011e74233c1dp-56 }, + .{ .chi = 0x1.b4fffd995badcp-1, .clo = -0x1.9ff1068862a9fp-56 }, + .{ .chi = 0x1.b7000249e659cp-1, .clo = 0x1.aff45d0864f3ep-55 }, + .{ .chi = 0x1.b8ffff987164p-1, .clo = 0x1.cfe7796c2c3f9p-56 }, + .{ .chi = 0x1.bafffd204cb4fp-1, .clo = -0x1.3ff27eef22bc4p-57 }, + .{ .chi = 0x1.bcfffd2415c45p-1, .clo = -0x1.cffb7ee3bea21p-57 }, + .{ .chi = 0x1.beffff86309dfp-1, .clo = -0x1.14103972e0b5cp-55 }, + .{ .chi = 0x1.c0fffe1b57653p-1, .clo = 0x1.bc16494b76a19p-55 }, + .{ .chi = 0x1.c2ffff1fa57e3p-1, .clo = -0x1.4feef8d30c6edp-57 }, + .{ .chi = 0x1.c4fffdcbfe424p-1, .clo = -0x1.43f68bcec4775p-55 }, + .{ .chi = 0x1.c6fffed54b9f7p-1, .clo = 0x1.47ea3f053e0ecp-55 }, + .{ .chi = 0x1.c8fffeb998fd5p-1, .clo = 0x1.383068df992f1p-56 }, + .{ .chi = 0x1.cb0002125219ap-1, .clo = -0x1.8fd8e64180e04p-57 }, + .{ .chi = 0x1.ccfffdd94469cp-1, .clo = 0x1.e7ebe1cc7ea72p-55 }, + .{ .chi = 0x1.cefffeafdc476p-1, .clo = 0x1.ebe39ad9f88fep-55 }, + .{ .chi = 0x1.d1000169af82bp-1, .clo = 0x1.57d91a8b95a71p-56 }, + .{ .chi = 0x1.d30000d0ff71dp-1, .clo = 0x1.9c1906970c7dap-55 }, + .{ .chi = 0x1.d4fffea790fc4p-1, .clo = -0x1.80e37c558fe0cp-58 }, + .{ .chi = 0x1.d70002edc87e5p-1, .clo = -0x1.f80d64dc10f44p-56 }, + .{ .chi = 0x1.d900021dc82aap-1, .clo = -0x1.47c8f94fd5c5cp-56 }, + .{ .chi = 0x1.dafffd86b0283p-1, .clo = 0x1.c7f1dc521617ep-55 }, + .{ .chi = 0x1.dd000296c4739p-1, .clo = 0x1.8019eb2ffb153p-55 }, + .{ .chi = 0x1.defffe54490f5p-1, .clo = 0x1.e00d2c652cc89p-57 }, + .{ .chi = 0x1.e0fffcdabf694p-1, .clo = -0x1.f8340202d69d2p-56 }, + .{ .chi = 0x1.e2fffdb52c8ddp-1, .clo = 0x1.b00c1ca1b0864p-56 }, + .{ .chi = 0x1.e4ffff24216efp-1, .clo = 0x1.2ffa8b094ab51p-56 }, + .{ .chi = 0x1.e6fffe88a5e11p-1, .clo = -0x1.7f673b1efbe59p-58 }, + .{ .chi = 0x1.e9000119eff0dp-1, .clo = -0x1.4808d5e0bc801p-55 }, + .{ .chi = 0x1.eafffdfa51744p-1, .clo = 0x1.80006d54320b5p-56 }, + .{ .chi = 0x1.ed0001a127fa1p-1, .clo = -0x1.002f860565c92p-58 }, + .{ .chi = 0x1.ef00007babcc4p-1, .clo = -0x1.540445d35e611p-55 }, + .{ .chi = 0x1.f0ffff57a8d02p-1, .clo = -0x1.ffb3139ef9105p-59 }, + .{ .chi = 0x1.f30001ee58ac7p-1, .clo = 0x1.a81acf2731155p-55 }, + .{ .chi = 0x1.f4ffff5823494p-1, .clo = 0x1.a3f41d4d7c743p-55 }, + .{ .chi = 0x1.f6ffffca94c6bp-1, .clo = -0x1.202f41c987875p-57 }, + .{ .chi = 0x1.f8fffe1f9c441p-1, .clo = 0x1.77dd1f477e74bp-56 }, + .{ .chi = 0x1.fafffd2e0e37ep-1, .clo = -0x1.f01199a7ca331p-57 }, + .{ .chi = 0x1.fd0001c77e49ep-1, .clo = 0x1.181ee4bceacb1p-56 }, + .{ .chi = 0x1.feffff7e0c331p-1, .clo = -0x1.e05370170875ap-57 }, + .{ .chi = 0x1.00ffff465606ep+0, .clo = -0x1.a7ead491c0adap-55 }, + .{ .chi = 0x1.02ffff3867a58p+0, .clo = -0x1.77f69c3fcb2ep-54 }, + .{ .chi = 0x1.04ffffdfc0d17p+0, .clo = 0x1.7bffe34cb945bp-54 }, + .{ .chi = 0x1.0700003cd4d82p+0, .clo = 0x1.20083c0e456cbp-55 }, + .{ .chi = 0x1.08ffff9f2cbe8p+0, .clo = -0x1.dffdfbe37751ap-57 }, + .{ .chi = 0x1.0b000010cda65p+0, .clo = -0x1.13f7faee626ebp-54 }, + .{ .chi = 0x1.0d00001a4d338p+0, .clo = 0x1.07dfa79489ff7p-55 }, + .{ .chi = 0x1.0effffadafdfdp+0, .clo = -0x1.7040570d66bcp-56 }, + .{ .chi = 0x1.110000bbafd96p+0, .clo = 0x1.e80d4846d0b62p-55 }, + .{ .chi = 0x1.12ffffae5f45dp+0, .clo = 0x1.dbffa64fd36efp-54 }, + .{ .chi = 0x1.150000dd59ad9p+0, .clo = 0x1.a0077701250aep-54 }, + .{ .chi = 0x1.170000f21559ap+0, .clo = 0x1.dfdf9e2e3deeep-55 }, + .{ .chi = 0x1.18ffffc275426p+0, .clo = 0x1.10030dc3b7273p-54 }, + .{ .chi = 0x1.1b000123d3c59p+0, .clo = 0x1.97f7980030188p-54 }, + .{ .chi = 0x1.1cffff8299eb7p+0, .clo = -0x1.5f932ab9f8c67p-57 }, + .{ .chi = 0x1.1effff48ad4p+0, .clo = 0x1.37fbf9da75bebp-54 }, + .{ .chi = 0x1.210000c8b86a4p+0, .clo = 0x1.f806b91fd5b22p-54 }, + .{ .chi = 0x1.2300003854303p+0, .clo = 0x1.3ffc2eb9fbf33p-54 }, + .{ .chi = 0x1.24fffffbcf684p+0, .clo = 0x1.601e77e2e2e72p-56 }, + .{ .chi = 0x1.26ffff52921d9p+0, .clo = 0x1.ffcbb767f0c61p-56 }, + .{ .chi = 0x1.2900014933a3cp+0, .clo = -0x1.202ca3c02412bp-56 }, + .{ .chi = 0x1.2b00014556313p+0, .clo = -0x1.2808233f21f02p-54 }, + .{ .chi = 0x1.2cfffebfe523bp+0, .clo = -0x1.8ff7e384fdcf2p-55 }, + .{ .chi = 0x1.2f0000bb8ad96p+0, .clo = -0x1.5ff51503041c5p-55 }, + .{ .chi = 0x1.30ffffb7ae2afp+0, .clo = -0x1.10071885e289dp-55 }, + .{ .chi = 0x1.32ffffeac5f7fp+0, .clo = -0x1.1ff5d3fb7b715p-54 }, + .{ .chi = 0x1.350000ca66756p+0, .clo = 0x1.57f82228b82bdp-54 }, + .{ .chi = 0x1.3700011fbf721p+0, .clo = 0x1.000bac40dd5ccp-55 }, + .{ .chi = 0x1.38ffff9592fb9p+0, .clo = -0x1.43f9d2db2a751p-54 }, + .{ .chi = 0x1.3b00004ddd242p+0, .clo = 0x1.57f6b707638e1p-55 }, + .{ .chi = 0x1.3cffff5b2c957p+0, .clo = 0x1.a023a10bf1231p-56 }, + .{ .chi = 0x1.3efffeab0b418p+0, .clo = 0x1.87f6d66b152bp-54 }, + .{ .chi = 0x1.410001532aff4p+0, .clo = 0x1.7f8375f198524p-57 }, + .{ .chi = 0x1.4300017478b29p+0, .clo = 0x1.301e672dc5143p-55 }, + .{ .chi = 0x1.44fffe795b463p+0, .clo = 0x1.9ff69b8b2895ap-55 }, + .{ .chi = 0x1.46fffe80475ep+0, .clo = -0x1.5c0b19bc2f254p-54 }, + .{ .chi = 0x1.48fffef6fc1e7p+0, .clo = 0x1.b4009f23a2a72p-54 }, + .{ .chi = 0x1.4afffe5bea704p+0, .clo = -0x1.4ffb7bf0d7d45p-54 }, + .{ .chi = 0x1.4d000171027dep+0, .clo = -0x1.9c06471dc6a3dp-54 }, + .{ .chi = 0x1.4f0000ff03ee2p+0, .clo = 0x1.77f890b85531cp-54 }, + .{ .chi = 0x1.5100012dc4bd1p+0, .clo = 0x1.004657166a436p-57 }, + .{ .chi = 0x1.530001605277ap+0, .clo = -0x1.6bfcece233209p-54 }, + .{ .chi = 0x1.54fffecdb704cp+0, .clo = -0x1.902720505a1d7p-55 }, + .{ .chi = 0x1.56fffef5f54a9p+0, .clo = 0x1.bbfe60ec96412p-54 }, + .{ .chi = 0x1.5900017e61012p+0, .clo = 0x1.87ec581afef9p-55 }, + .{ .chi = 0x1.5b00003c93e92p+0, .clo = -0x1.f41080abf0ccp-54 }, + .{ .chi = 0x1.5d0001d4919bcp+0, .clo = -0x1.8812afb254729p-54 }, + .{ .chi = 0x1.5efffe7b87a89p+0, .clo = -0x1.47eb780ed6904p-54 }, + }; + + var ix: i64 = @bitCast(x); + + const LO: i64 = @bitCast(@as(f64, 1.0 - 0x1p-4)); + const HI: i64 = @bitCast(@as(f64, 1.0 + 0x1.09p-4)); + if (LO <= ix and ix < HI) { + @branchHint(.unlikely); + if (ix == @as(i64, @bitCast(@as(f64, 1)))) { + @branchHint(.unlikely); + return 0; } - // subnormal, scale x - k -= 54; - x *= 0x1p54; - hx = @intCast(@as(u64, @bitCast(x)) >> 32); - } else if (hx >= 0x7FF00000) { - return x; - } else if (hx == 0x3FF00000 and ix << 32 == 0) { - return 0; + const r = x - 1; + const r2 = r * r; + const r3 = r * r2; + + const y = r3 * (poly1[1] + r * poly1[2] + r2 * poly1[3] + + r3 * (poly1[4] + r * poly1[5] + r2 * poly1[6] + + r3 * (poly1[7] + r * poly1[8] + r2 * poly1[9] + r3 * poly1[10]))); + + var w = r * 0x1p27; + const rhi = r + w - w; + const rlo = r - rhi; + w = rhi * rhi * poly1[0]; + const hi = r + w; + const lo = r - hi + w + poly1[0] * rlo * (rhi + r); + return y + lo + hi; } + const top = @as(u64, @bitCast(ix)) >> 48; + if (top < 0x0010 or 0x7ff0 <= top) { + @branchHint(.unlikely); - // x into [sqrt(2) / 2, sqrt(2)] - hx += 0x3FF00000 - 0x3FE6A09E; - k += @as(i32, @intCast(hx >> 20)) - 0x3FF; - hx = (hx & 0x000FFFFF) + 0x3FE6A09E; - ix = (@as(u64, hx) << 32) | (ix & 0xFFFFFFFF); - x = @bitCast(ix); + if (ix << 1 == 0) + return if (common.want_float_exceptions) -1 / (x * x) else -std.math.inf(f64); - const f = x - 1.0; - const hfsq = 0.5 * f * f; - const s = f / (2.0 + f); - const z = s * s; - const w = z * z; - const t1 = w * (Lg2 + w * (Lg4 + w * Lg6)); - const t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7))); - const R = t2 + t1; - const dk: f64 = @floatFromInt(k); + if (ix == @as(i64, @bitCast(std.math.inf(f64)))) + return x; - return s * (hfsq + R) + dk * ln2_lo - hfsq + f + dk * ln2_hi; + if (top & 0x8000 != 0 or top & 0x7ff0 == 0x7ff0) + return if (common.want_float_exceptions) (x - x) / 0.0 else math.nan(f64); + + ix = @as(i64, @bitCast(x * 0x1p52)) - (52 << 52); + } + + const tmp: packed struct(i64) { unused: u45, i: u7, k: i12 } = @bitCast(ix - 0x3fe6000000000000); + const i = tmp.i; + const k = tmp.k; + const iz = ix - (@as(i64, tmp.k) << 52); + const invc = tab[i].invc; + const logc = tab[i].logc; + const z: f64 = @bitCast(iz); + + // maybe use fma as musl does + const r = (z - tab2[i].chi - tab2[i].clo) * invc; + + // https://github.com/ziglang/zig/issues/18614 + const kd: f64 = @floatFromInt(k); + const w = kd * 0x1.62e42fefa3800p-1 + logc; + const hi = w + r; + const lo = w - hi + r + kd * 0x1.ef35793c76730p-45; + + const r2 = r * r; + + const y = lo + r2 * poly[0] + r * r2 * (poly[1] + r * poly[2] + r2 * (poly[3] + r * poly[4])) + hi; + return @bitCast(y); } pub fn __logx(a: f80) callconv(.c) f80 { diff --git a/lib/compiler_rt/log10.zig b/lib/compiler_rt/log10.zig index 1c2ce4bbcabf..d501cef461a0 100644 --- a/lib/compiler_rt/log10.zig +++ b/lib/compiler_rt/log10.zig @@ -13,8 +13,6 @@ const maxInt = std.math.maxInt; const arch = builtin.cpu.arch; const common = @import("common.zig"); -pub const panic = common.panic; - comptime { @export(&__log10h, .{ .name = "__log10h", .linkage = common.linkage, .visibility = common.visibility }); @export(&log10f, .{ .name = "log10f", .linkage = common.linkage, .visibility = common.visibility }); @@ -51,11 +49,11 @@ pub fn log10f(x_: f32) callconv(.c) f32 { if (ix < 0x00800000 or ix >> 31 != 0) { // log(+-0) = -inf if (ix << 1 == 0) { - return -math.inf(f32); + return if (common.want_float_exceptions) -1 / (x * x) else -std.math.inf(f64); } // log(-#) = nan if (ix >> 31 != 0) { - return math.nan(f32); + return if (common.want_float_exceptions) (x - x) / 0.0 else math.nan(f64); } k -= 25; @@ -113,11 +111,11 @@ pub fn log10(x_: f64) callconv(.c) f64 { if (hx < 0x00100000 or hx >> 31 != 0) { // log(+-0) = -inf if (ix << 1 == 0) { - return -math.inf(f64); + return if (common.want_float_exceptions) -1 / (x * x) else -std.math.inf(f64); } // log(-#) = nan if (hx >> 31 != 0) { - return math.nan(f64); + return if (common.want_float_exceptions) (x - x) / 0.0 else math.nan(f64); } // subnormal, scale x diff --git a/lib/compiler_rt/log2.zig b/lib/compiler_rt/log2.zig index 4cedcfe0c1d2..48ff6135d8f4 100644 --- a/lib/compiler_rt/log2.zig +++ b/lib/compiler_rt/log2.zig @@ -13,8 +13,6 @@ const maxInt = std.math.maxInt; const arch = builtin.cpu.arch; const common = @import("common.zig"); -pub const panic = common.panic; - comptime { @export(&__log2h, .{ .name = "__log2h", .linkage = common.linkage, .visibility = common.visibility }); @export(&log2f, .{ .name = "log2f", .linkage = common.linkage, .visibility = common.visibility }); @@ -49,11 +47,11 @@ pub fn log2f(x_: f32) callconv(.c) f32 { if (ix < 0x00800000 or ix >> 31 != 0) { // log(+-0) = -inf if (ix << 1 == 0) { - return -math.inf(f32); + return if (common.want_float_exceptions) -1 / (x * x) else -std.math.inf(f64); } // log(-#) = nan if (ix >> 31 != 0) { - return math.nan(f32); + return if (common.want_float_exceptions) (x - x) / 0.0 else math.nan(f64); } k -= 25; @@ -107,11 +105,11 @@ pub fn log2(x_: f64) callconv(.c) f64 { if (hx < 0x00100000 or hx >> 31 != 0) { // log(+-0) = -inf if (ix << 1 == 0) { - return -math.inf(f64); + return if (common.want_float_exceptions) -1 / (x * x) else -std.math.inf(f64); } // log(-#) = nan if (hx >> 31 != 0) { - return math.nan(f64); + return if (common.want_float_exceptions) (x - x) / 0.0 else math.nan(f64); } // subnormal, scale x diff --git a/lib/compiler_rt/modti3.zig b/lib/compiler_rt/modti3.zig index b73f3d05fa05..74e431a06166 100644 --- a/lib/compiler_rt/modti3.zig +++ b/lib/compiler_rt/modti3.zig @@ -7,8 +7,6 @@ const builtin = @import("builtin"); const udivmod = @import("udivmod.zig").udivmod; const common = @import("common.zig"); -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__modti3_windows_x86_64, .{ .name = "__modti3", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/mulXi3.zig b/lib/compiler_rt/mulXi3.zig index a96ef135c4d3..198d51c88838 100644 --- a/lib/compiler_rt/mulXi3.zig +++ b/lib/compiler_rt/mulXi3.zig @@ -4,8 +4,6 @@ const testing = std.testing; const common = @import("common.zig"); const native_endian = builtin.cpu.arch.endian(); -pub const panic = common.panic; - comptime { @export(&__mulsi3, .{ .name = "__mulsi3", .linkage = common.linkage, .visibility = common.visibility }); if (common.want_aeabi) { diff --git a/lib/compiler_rt/muldc3.zig b/lib/compiler_rt/muldc3.zig index 1c53b4d07397..9670c1312887 100644 --- a/lib/compiler_rt/muldc3.zig +++ b/lib/compiler_rt/muldc3.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const mulc3 = @import("./mulc3.zig"); -pub const panic = common.panic; - comptime { if (@import("builtin").zig_backend != .stage2_c) { @export(&__muldc3, .{ .name = "__muldc3", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/muldf3.zig b/lib/compiler_rt/muldf3.zig index 1fa4c9debbd2..cf67df0913ab 100644 --- a/lib/compiler_rt/muldf3.zig +++ b/lib/compiler_rt/muldf3.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const mulf3 = @import("./mulf3.zig").mulf3; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_dmul, .{ .name = "__aeabi_dmul", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/mulhc3.zig b/lib/compiler_rt/mulhc3.zig index 4d97a0978dc5..09bca03a050c 100644 --- a/lib/compiler_rt/mulhc3.zig +++ b/lib/compiler_rt/mulhc3.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const mulc3 = @import("./mulc3.zig"); -pub const panic = common.panic; - comptime { if (@import("builtin").zig_backend != .stage2_c) { @export(&__mulhc3, .{ .name = "__mulhc3", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/mulhf3.zig b/lib/compiler_rt/mulhf3.zig index 2731625a160e..22f7a95627f9 100644 --- a/lib/compiler_rt/mulhf3.zig +++ b/lib/compiler_rt/mulhf3.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const mulf3 = @import("./mulf3.zig").mulf3; -pub const panic = common.panic; - comptime { @export(&__mulhf3, .{ .name = "__mulhf3", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/mulo.zig b/lib/compiler_rt/mulo.zig index 20fbff3b96e4..b85623eb7e51 100644 --- a/lib/compiler_rt/mulo.zig +++ b/lib/compiler_rt/mulo.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const math = std.math; const common = @import("common.zig"); -pub const panic = common.panic; - comptime { @export(&__mulosi4, .{ .name = "__mulosi4", .linkage = common.linkage, .visibility = common.visibility }); @export(&__mulodi4, .{ .name = "__mulodi4", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/mulsc3.zig b/lib/compiler_rt/mulsc3.zig index f011d2fe2319..49c1e31aecd4 100644 --- a/lib/compiler_rt/mulsc3.zig +++ b/lib/compiler_rt/mulsc3.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const mulc3 = @import("./mulc3.zig"); -pub const panic = common.panic; - comptime { if (@import("builtin").zig_backend != .stage2_c) { @export(&__mulsc3, .{ .name = "__mulsc3", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/mulsf3.zig b/lib/compiler_rt/mulsf3.zig index 8929b5deba12..a603652262bc 100644 --- a/lib/compiler_rt/mulsf3.zig +++ b/lib/compiler_rt/mulsf3.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const mulf3 = @import("./mulf3.zig").mulf3; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_fmul, .{ .name = "__aeabi_fmul", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/multc3.zig b/lib/compiler_rt/multc3.zig index cf3621919dae..1ed373660f81 100644 --- a/lib/compiler_rt/multc3.zig +++ b/lib/compiler_rt/multc3.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const mulc3 = @import("./mulc3.zig"); -pub const panic = common.panic; - comptime { if (@import("builtin").zig_backend != .stage2_c) { if (common.want_ppc_abi) diff --git a/lib/compiler_rt/multf3.zig b/lib/compiler_rt/multf3.zig index 0da8c506e855..6ef9cc2c2580 100644 --- a/lib/compiler_rt/multf3.zig +++ b/lib/compiler_rt/multf3.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const mulf3 = @import("./mulf3.zig").mulf3; -pub const panic = common.panic; - comptime { if (common.want_ppc_abi) { @export(&__multf3, .{ .name = "__mulkf3", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/mulvsi3.zig b/lib/compiler_rt/mulvsi3.zig index d225552a582a..e773ea0d9ad7 100644 --- a/lib/compiler_rt/mulvsi3.zig +++ b/lib/compiler_rt/mulvsi3.zig @@ -2,8 +2,6 @@ const mulv = @import("mulo.zig"); const common = @import("./common.zig"); const testing = @import("std").testing; -pub const panic = common.panic; - comptime { @export(&__mulvsi3, .{ .name = "__mulvsi3", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/mulxc3.zig b/lib/compiler_rt/mulxc3.zig index ef6927ce089a..cbf9c6408305 100644 --- a/lib/compiler_rt/mulxc3.zig +++ b/lib/compiler_rt/mulxc3.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const mulc3 = @import("./mulc3.zig"); -pub const panic = common.panic; - comptime { if (@import("builtin").zig_backend != .stage2_c) { @export(&__mulxc3, .{ .name = "__mulxc3", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/mulxf3.zig b/lib/compiler_rt/mulxf3.zig index 2db80b81b010..1d9f465ebd05 100644 --- a/lib/compiler_rt/mulxf3.zig +++ b/lib/compiler_rt/mulxf3.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const mulf3 = @import("./mulf3.zig").mulf3; -pub const panic = common.panic; - comptime { @export(&__mulxf3, .{ .name = "__mulxf3", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/negXi2.zig b/lib/compiler_rt/negXi2.zig index eee5202e71b8..7a57e988c6e5 100644 --- a/lib/compiler_rt/negXi2.zig +++ b/lib/compiler_rt/negXi2.zig @@ -10,8 +10,6 @@ const std = @import("std"); const builtin = @import("builtin"); const common = @import("common.zig"); -pub const panic = common.panic; - comptime { @export(&__negsi2, .{ .name = "__negsi2", .linkage = common.linkage, .visibility = common.visibility }); @export(&__negdi2, .{ .name = "__negdi2", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/negdf2.zig b/lib/compiler_rt/negdf2.zig index 85e7f2bd82af..b0ac26e6c0c5 100644 --- a/lib/compiler_rt/negdf2.zig +++ b/lib/compiler_rt/negdf2.zig @@ -1,7 +1,5 @@ const common = @import("./common.zig"); -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_dneg, .{ .name = "__aeabi_dneg", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/neghf2.zig b/lib/compiler_rt/neghf2.zig index 86b28d48021d..59c7e155b72f 100644 --- a/lib/compiler_rt/neghf2.zig +++ b/lib/compiler_rt/neghf2.zig @@ -1,7 +1,5 @@ const common = @import("./common.zig"); -pub const panic = common.panic; - comptime { @export(&__neghf2, .{ .name = "__neghf2", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/negsf2.zig b/lib/compiler_rt/negsf2.zig index 08276e7f26ba..065dc3acd106 100644 --- a/lib/compiler_rt/negsf2.zig +++ b/lib/compiler_rt/negsf2.zig @@ -1,7 +1,5 @@ const common = @import("./common.zig"); -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_fneg, .{ .name = "__aeabi_fneg", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/negtf2.zig b/lib/compiler_rt/negtf2.zig index 9fb938444659..ecb5cc2c9007 100644 --- a/lib/compiler_rt/negtf2.zig +++ b/lib/compiler_rt/negtf2.zig @@ -1,7 +1,5 @@ const common = @import("./common.zig"); -pub const panic = common.panic; - comptime { if (common.want_ppc_abi) @export(&__negtf2, .{ .name = "__negkf2", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/negv.zig b/lib/compiler_rt/negv.zig index 6a2e717db150..98934b78f424 100644 --- a/lib/compiler_rt/negv.zig +++ b/lib/compiler_rt/negv.zig @@ -5,8 +5,6 @@ const std = @import("std"); const builtin = @import("builtin"); const common = @import("common.zig"); -pub const panic = common.panic; - comptime { @export(&__negvsi2, .{ .name = "__negvsi2", .linkage = common.linkage, .visibility = common.visibility }); @export(&__negvdi2, .{ .name = "__negvdi2", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/negxf2.zig b/lib/compiler_rt/negxf2.zig index 9a9c17865498..ea16c8fef215 100644 --- a/lib/compiler_rt/negxf2.zig +++ b/lib/compiler_rt/negxf2.zig @@ -1,7 +1,5 @@ const common = @import("./common.zig"); -pub const panic = common.panic; - comptime { @export(&__negxf2, .{ .name = "__negxf2", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/parity.zig b/lib/compiler_rt/parity.zig index 5a3e5a886d0e..71d50f327b17 100644 --- a/lib/compiler_rt/parity.zig +++ b/lib/compiler_rt/parity.zig @@ -5,8 +5,6 @@ const std = @import("std"); const builtin = @import("builtin"); const common = @import("common.zig"); -pub const panic = common.panic; - comptime { @export(&__paritysi2, .{ .name = "__paritysi2", .linkage = common.linkage, .visibility = common.visibility }); @export(&__paritydi2, .{ .name = "__paritydi2", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/popcount.zig b/lib/compiler_rt/popcount.zig index f937bd0ce05c..12ecda16cc1c 100644 --- a/lib/compiler_rt/popcount.zig +++ b/lib/compiler_rt/popcount.zig @@ -10,8 +10,6 @@ const builtin = @import("builtin"); const std = @import("std"); const common = @import("common.zig"); -pub const panic = common.panic; - comptime { @export(&__popcountsi2, .{ .name = "__popcountsi2", .linkage = common.linkage, .visibility = common.visibility }); @export(&__popcountdi2, .{ .name = "__popcountdi2", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/powiXf2.zig b/lib/compiler_rt/powiXf2.zig index 21e7042a06b2..b603998d5569 100644 --- a/lib/compiler_rt/powiXf2.zig +++ b/lib/compiler_rt/powiXf2.zig @@ -7,8 +7,6 @@ const builtin = @import("builtin"); const common = @import("common.zig"); const std = @import("std"); -pub const panic = common.panic; - comptime { @export(&__powihf2, .{ .name = "__powihf2", .linkage = common.linkage, .visibility = common.visibility }); @export(&__powisf2, .{ .name = "__powisf2", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/round.zig b/lib/compiler_rt/round.zig index 9e8ea42d67c3..b643bfd89fab 100644 --- a/lib/compiler_rt/round.zig +++ b/lib/compiler_rt/round.zig @@ -12,8 +12,6 @@ const expect = std.testing.expect; const arch = builtin.cpu.arch; const common = @import("common.zig"); -pub const panic = common.panic; - comptime { @export(&__roundh, .{ .name = "__roundh", .linkage = common.linkage, .visibility = common.visibility }); @export(&roundf, .{ .name = "roundf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/shift.zig b/lib/compiler_rt/shift.zig index 17860da943a6..9c75bd3475fb 100644 --- a/lib/compiler_rt/shift.zig +++ b/lib/compiler_rt/shift.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const Log2Int = std.math.Log2Int; const common = @import("common.zig"); -pub const panic = common.panic; - comptime { // symbol compatibility with libgcc @export(&__ashlsi3, .{ .name = "__ashlsi3", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/sin.zig b/lib/compiler_rt/sin.zig index e14779d27a2b..d25c1cd23ae1 100644 --- a/lib/compiler_rt/sin.zig +++ b/lib/compiler_rt/sin.zig @@ -16,8 +16,6 @@ const trig = @import("trig.zig"); const rem_pio2 = @import("rem_pio2.zig").rem_pio2; const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; -pub const panic = common.panic; - comptime { @export(&__sinh, .{ .name = "__sinh", .linkage = common.linkage, .visibility = common.visibility }); @export(&sinf, .{ .name = "sinf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/sincos.zig b/lib/compiler_rt/sincos.zig index 72b90a51e703..46fec8ff64c3 100644 --- a/lib/compiler_rt/sincos.zig +++ b/lib/compiler_rt/sincos.zig @@ -8,8 +8,6 @@ const rem_pio2 = @import("rem_pio2.zig").rem_pio2; const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; const common = @import("common.zig"); -pub const panic = common.panic; - comptime { @export(&__sincosh, .{ .name = "__sincosh", .linkage = common.linkage, .visibility = common.visibility }); @export(&sincosf, .{ .name = "sincosf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/sqrt.zig b/lib/compiler_rt/sqrt.zig index ed4602120b1e..2c321863682a 100644 --- a/lib/compiler_rt/sqrt.zig +++ b/lib/compiler_rt/sqrt.zig @@ -11,8 +11,6 @@ const arch = builtin.cpu.arch; const math = std.math; const common = @import("common.zig"); -pub const panic = common.panic; - comptime { @export(&__sqrth, .{ .name = "__sqrth", .linkage = common.linkage, .visibility = common.visibility }); @export(&sqrtf, .{ .name = "sqrtf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/ssp.zig b/lib/compiler_rt/ssp.zig index f0882cfff29a..0a138735baea 100644 --- a/lib/compiler_rt/ssp.zig +++ b/lib/compiler_rt/ssp.zig @@ -21,7 +21,7 @@ extern fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, n: usize) call extern fn memmove(dest: ?[*]u8, src: ?[*]const u8, n: usize) callconv(.c) ?[*]u8; comptime { - @export(&__stack_chk_fail, .{ .name = "__stack_chk_fail", .linkage = common.linkage, .visibility = common.visibility }); + @export(&__stack_chk_fail, .{ .name = if (builtin.os.tag == .openbsd) "__stack_smash_handler" else "__stack_chk_fail", .linkage = common.linkage, .visibility = common.visibility }); @export(&__chk_fail, .{ .name = "__chk_fail", .linkage = common.linkage, .visibility = common.visibility }); @export(&__stack_chk_guard, .{ .name = "__stack_chk_guard", .linkage = common.linkage, .visibility = common.visibility }); @export(&__strcpy_chk, .{ .name = "__strcpy_chk", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/stack_probe.zig b/lib/compiler_rt/stack_probe.zig index 21259ec4354a..83e08be01537 100644 --- a/lib/compiler_rt/stack_probe.zig +++ b/lib/compiler_rt/stack_probe.zig @@ -5,8 +5,6 @@ const os_tag = builtin.os.tag; const arch = builtin.cpu.arch; const abi = builtin.abi; -pub const panic = common.panic; - comptime { if (builtin.os.tag == .windows) { // Default stack-probe functions emitted by LLVM diff --git a/lib/compiler_rt/subdf3.zig b/lib/compiler_rt/subdf3.zig index 24ded58e0c54..b1d78509028c 100644 --- a/lib/compiler_rt/subdf3.zig +++ b/lib/compiler_rt/subdf3.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const addf3 = @import("./addf3.zig").addf3; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_dsub, .{ .name = "__aeabi_dsub", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/subhf3.zig b/lib/compiler_rt/subhf3.zig index cc42eb927022..e019005ae478 100644 --- a/lib/compiler_rt/subhf3.zig +++ b/lib/compiler_rt/subhf3.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const addf3 = @import("./addf3.zig").addf3; -pub const panic = common.panic; - comptime { @export(&__subhf3, .{ .name = "__subhf3", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/subsf3.zig b/lib/compiler_rt/subsf3.zig index f3bb334bd81e..9a1cb559b23a 100644 --- a/lib/compiler_rt/subsf3.zig +++ b/lib/compiler_rt/subsf3.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const addf3 = @import("./addf3.zig").addf3; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_fsub, .{ .name = "__aeabi_fsub", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/subtf3.zig b/lib/compiler_rt/subtf3.zig index aff4904adf6e..b187eaf579b3 100644 --- a/lib/compiler_rt/subtf3.zig +++ b/lib/compiler_rt/subtf3.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const addf3 = @import("./addf3.zig").addf3; -pub const panic = common.panic; - comptime { if (common.want_ppc_abi) { @export(&__subtf3, .{ .name = "__subkf3", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/subvdi3.zig b/lib/compiler_rt/subvdi3.zig index a34deb2da1bf..17c893c91141 100644 --- a/lib/compiler_rt/subvdi3.zig +++ b/lib/compiler_rt/subvdi3.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const testing = @import("std").testing; -pub const panic = common.panic; - comptime { @export(&__subvdi3, .{ .name = "__subvdi3", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/subvsi3.zig b/lib/compiler_rt/subvsi3.zig index c524a3a63499..68f551071c8f 100644 --- a/lib/compiler_rt/subvsi3.zig +++ b/lib/compiler_rt/subvsi3.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const testing = @import("std").testing; -pub const panic = common.panic; - comptime { @export(&__subvsi3, .{ .name = "__subvsi3", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/subxf3.zig b/lib/compiler_rt/subxf3.zig index e79dd230b5d8..d119f0bd984f 100644 --- a/lib/compiler_rt/subxf3.zig +++ b/lib/compiler_rt/subxf3.zig @@ -1,8 +1,6 @@ const std = @import("std"); const common = @import("./common.zig"); -pub const panic = common.panic; - comptime { @export(&__subxf3, .{ .name = "__subxf3", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/tan.zig b/lib/compiler_rt/tan.zig index af8d68eb4444..a78d7afb67b4 100644 --- a/lib/compiler_rt/tan.zig +++ b/lib/compiler_rt/tan.zig @@ -18,8 +18,6 @@ const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; const arch = builtin.cpu.arch; const common = @import("common.zig"); -pub const panic = common.panic; - comptime { @export(&__tanh, .{ .name = "__tanh", .linkage = common.linkage, .visibility = common.visibility }); @export(&tanf, .{ .name = "tanf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/trunc.zig b/lib/compiler_rt/trunc.zig index ff829ea71089..55468c752fa4 100644 --- a/lib/compiler_rt/trunc.zig +++ b/lib/compiler_rt/trunc.zig @@ -12,8 +12,6 @@ const mem = std.mem; const expect = std.testing.expect; const common = @import("common.zig"); -pub const panic = common.panic; - comptime { @export(&__trunch, .{ .name = "__trunch", .linkage = common.linkage, .visibility = common.visibility }); @export(&truncf, .{ .name = "truncf", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/truncdfhf2.zig b/lib/compiler_rt/truncdfhf2.zig index a24650ddb78f..4db14f021184 100644 --- a/lib/compiler_rt/truncdfhf2.zig +++ b/lib/compiler_rt/truncdfhf2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const truncf = @import("./truncf.zig").truncf; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_d2h, .{ .name = "__aeabi_d2h", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/truncdfsf2.zig b/lib/compiler_rt/truncdfsf2.zig index fd42d5d34428..8d6ed5c3206f 100644 --- a/lib/compiler_rt/truncdfsf2.zig +++ b/lib/compiler_rt/truncdfsf2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const truncf = @import("./truncf.zig").truncf; -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_d2f, .{ .name = "__aeabi_d2f", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/truncsfhf2.zig b/lib/compiler_rt/truncsfhf2.zig index 18d5854c91b3..acd5631da8f7 100644 --- a/lib/compiler_rt/truncsfhf2.zig +++ b/lib/compiler_rt/truncsfhf2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const truncf = @import("./truncf.zig").truncf; -pub const panic = common.panic; - comptime { if (common.gnu_f16_abi) { @export(&__gnu_f2h_ieee, .{ .name = "__gnu_f2h_ieee", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/trunctfdf2.zig b/lib/compiler_rt/trunctfdf2.zig index 37b9227e0b97..4f569dae675c 100644 --- a/lib/compiler_rt/trunctfdf2.zig +++ b/lib/compiler_rt/trunctfdf2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const truncf = @import("./truncf.zig").truncf; -pub const panic = common.panic; - comptime { if (common.want_ppc_abi) { @export(&__trunctfdf2, .{ .name = "__trunckfdf2", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/trunctfhf2.zig b/lib/compiler_rt/trunctfhf2.zig index daf4776106db..f5adc918c2d5 100644 --- a/lib/compiler_rt/trunctfhf2.zig +++ b/lib/compiler_rt/trunctfhf2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const truncf = @import("./truncf.zig").truncf; -pub const panic = common.panic; - comptime { @export(&__trunctfhf2, .{ .name = "__trunctfhf2", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/trunctfsf2.zig b/lib/compiler_rt/trunctfsf2.zig index e238e35fb346..17e7570c9f0e 100644 --- a/lib/compiler_rt/trunctfsf2.zig +++ b/lib/compiler_rt/trunctfsf2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const truncf = @import("./truncf.zig").truncf; -pub const panic = common.panic; - comptime { if (common.want_ppc_abi) { @export(&__trunctfsf2, .{ .name = "__trunckfsf2", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/trunctfxf2.zig b/lib/compiler_rt/trunctfxf2.zig index ddc977943a09..df0db2393a62 100644 --- a/lib/compiler_rt/trunctfxf2.zig +++ b/lib/compiler_rt/trunctfxf2.zig @@ -2,8 +2,6 @@ const math = @import("std").math; const common = @import("./common.zig"); const trunc_f80 = @import("./truncf.zig").trunc_f80; -pub const panic = common.panic; - comptime { @export(&__trunctfxf2, .{ .name = "__trunctfxf2", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/truncxfdf2.zig b/lib/compiler_rt/truncxfdf2.zig index f45a07962e5c..1d7e66c278f3 100644 --- a/lib/compiler_rt/truncxfdf2.zig +++ b/lib/compiler_rt/truncxfdf2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const trunc_f80 = @import("./truncf.zig").trunc_f80; -pub const panic = common.panic; - comptime { @export(&__truncxfdf2, .{ .name = "__truncxfdf2", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/truncxfhf2.zig b/lib/compiler_rt/truncxfhf2.zig index 34ee97c04b94..b2dd9c746826 100644 --- a/lib/compiler_rt/truncxfhf2.zig +++ b/lib/compiler_rt/truncxfhf2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const trunc_f80 = @import("./truncf.zig").trunc_f80; -pub const panic = common.panic; - comptime { @export(&__truncxfhf2, .{ .name = "__truncxfhf2", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/truncxfsf2.zig b/lib/compiler_rt/truncxfsf2.zig index 136e941af425..9d36f7aa29a4 100644 --- a/lib/compiler_rt/truncxfsf2.zig +++ b/lib/compiler_rt/truncxfsf2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const trunc_f80 = @import("./truncf.zig").trunc_f80; -pub const panic = common.panic; - comptime { @export(&__truncxfsf2, .{ .name = "__truncxfsf2", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/udivmodti4.zig b/lib/compiler_rt/udivmodti4.zig index 9e9585c635db..a1b89bb9625b 100644 --- a/lib/compiler_rt/udivmodti4.zig +++ b/lib/compiler_rt/udivmodti4.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const udivmod = @import("udivmod.zig").udivmod; const common = @import("common.zig"); -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__udivmodti4_windows_x86_64, .{ .name = "__udivmodti4", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/udivti3.zig b/lib/compiler_rt/udivti3.zig index 8423c1df1876..a579d81e47df 100644 --- a/lib/compiler_rt/udivti3.zig +++ b/lib/compiler_rt/udivti3.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const udivmod = @import("udivmod.zig").udivmod; const common = @import("common.zig"); -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__udivti3_windows_x86_64, .{ .name = "__udivti3", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/umodti3.zig b/lib/compiler_rt/umodti3.zig index 592bc44390a1..63cfcc2c2536 100644 --- a/lib/compiler_rt/umodti3.zig +++ b/lib/compiler_rt/umodti3.zig @@ -3,8 +3,6 @@ const builtin = @import("builtin"); const udivmod = @import("udivmod.zig").udivmod; const common = @import("common.zig"); -pub const panic = common.panic; - comptime { if (common.want_windows_v2u64_abi) { @export(&__umodti3_windows_x86_64, .{ .name = "__umodti3", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/unorddf2.zig b/lib/compiler_rt/unorddf2.zig index dcc8762c66d7..5b17343a5168 100644 --- a/lib/compiler_rt/unorddf2.zig +++ b/lib/compiler_rt/unorddf2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const comparef = @import("./comparef.zig"); -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_dcmpun, .{ .name = "__aeabi_dcmpun", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/unordhf2.zig b/lib/compiler_rt/unordhf2.zig index 2c2edad81686..4fcffd1a1d1c 100644 --- a/lib/compiler_rt/unordhf2.zig +++ b/lib/compiler_rt/unordhf2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const comparef = @import("./comparef.zig"); -pub const panic = common.panic; - comptime { @export(&__unordhf2, .{ .name = "__unordhf2", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/compiler_rt/unordsf2.zig b/lib/compiler_rt/unordsf2.zig index a403fa4fd3d5..56bfb94028d8 100644 --- a/lib/compiler_rt/unordsf2.zig +++ b/lib/compiler_rt/unordsf2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const comparef = @import("./comparef.zig"); -pub const panic = common.panic; - comptime { if (common.want_aeabi) { @export(&__aeabi_fcmpun, .{ .name = "__aeabi_fcmpun", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/unordtf2.zig b/lib/compiler_rt/unordtf2.zig index 618f148296fd..22e90acaaed0 100644 --- a/lib/compiler_rt/unordtf2.zig +++ b/lib/compiler_rt/unordtf2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const comparef = @import("./comparef.zig"); -pub const panic = common.panic; - comptime { if (common.want_ppc_abi) { @export(&__unordtf2, .{ .name = "__unordkf2", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/unordxf2.zig b/lib/compiler_rt/unordxf2.zig index 97a4f8d06f7b..2ebf5f413cc6 100644 --- a/lib/compiler_rt/unordxf2.zig +++ b/lib/compiler_rt/unordxf2.zig @@ -1,8 +1,6 @@ const common = @import("./common.zig"); const comparef = @import("./comparef.zig"); -pub const panic = common.panic; - comptime { @export(&__unordxf2, .{ .name = "__unordxf2", .linkage = common.linkage, .visibility = common.visibility }); } diff --git a/lib/docs/wasm/Walk.zig b/lib/docs/wasm/Walk.zig index bd3051c98fec..074d4c2f1462 100644 --- a/lib/docs/wasm/Walk.zig +++ b/lib/docs/wasm/Walk.zig @@ -791,8 +791,6 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) try expr(w, scope, parent_decl, full.ast.template); }, - .asm_legacy => {}, - .builtin_call_two, .builtin_call_two_comma, .builtin_call, diff --git a/lib/docs/wasm/markdown.zig b/lib/docs/wasm/markdown.zig index 6e9b7a06036f..a15af8869c68 100644 --- a/lib/docs/wasm/markdown.zig +++ b/lib/docs/wasm/markdown.zig @@ -149,7 +149,7 @@ fn mainImpl() !void { var stdin_reader = std.fs.File.stdin().reader(&stdin_buffer); while (stdin_reader.takeDelimiterExclusive('\n')) |line| { - const trimmed = std.mem.trimRight(u8, line, '\r'); + const trimmed = std.mem.trimEnd(u8, line, '\r'); try parser.feedLine(trimmed); } else |err| switch (err) { error.EndOfStream => {}, diff --git a/lib/fuzzer.zig b/lib/fuzzer.zig index 3a48360bf834..a2414744ca82 100644 --- a/lib/fuzzer.zig +++ b/lib/fuzzer.zig @@ -1,18 +1,22 @@ const builtin = @import("builtin"); +const native_endian = builtin.cpu.arch.endian(); + const std = @import("std"); +const Io = std.Io; const fatal = std.process.fatal; const mem = std.mem; const math = std.math; -const Allocator = mem.Allocator; +const Allocator = std.mem.Allocator; const assert = std.debug.assert; const panic = std.debug.panic; const abi = std.Build.abi.fuzz; -const native_endian = builtin.cpu.arch.endian(); pub const std_options = std.Options{ .logFn = logOverride, }; +const io = std.Io.Threaded.global_single_threaded.ioBasic(); + fn logOverride( comptime level: std.log.Level, comptime scope: @EnumLiteral(), @@ -21,12 +25,12 @@ fn logOverride( ) void { const f = log_f orelse panic("attempt to use log before initialization, message:\n" ++ format, args); - f.lock(.exclusive) catch |e| panic("failed to lock logging file: {t}", .{e}); - defer f.unlock(); + f.lock(io, .exclusive) catch |e| panic("failed to lock logging file: {t}", .{e}); + defer f.unlock(io); var buf: [256]u8 = undefined; - var fw = f.writer(&buf); - const end = f.getEndPos() catch |e| panic("failed to get fuzzer log file end: {t}", .{e}); + var fw = f.writer(io, &buf); + const end = f.length(io) catch |e| panic("failed to get fuzzer log file end: {t}", .{e}); fw.seekTo(end) catch |e| panic("failed to seek to fuzzer log file end: {t}", .{e}); const prefix1 = comptime level.asText(); @@ -45,7 +49,7 @@ const gpa = switch (builtin.mode) { }; /// Part of `exec`, however seperate to allow it to be set before `exec` is. -var log_f: ?std.fs.File = null; +var log_f: ?Io.File = null; var exec: Executable = .preinit; var inst: Instrumentation = .preinit; var fuzzer: Fuzzer = undefined; @@ -59,7 +63,7 @@ const Executable = struct { /// Tracks the hit count for each pc as updated by the process's instrumentation. pc_counters: []u8, - cache_f: std.fs.Dir, + cache_f: Io.Dir, /// Shared copy of all pcs that have been hit stored in a memory-mapped file that can viewed /// while the fuzzer is running. shared_seen_pcs: MemoryMappedList, @@ -76,16 +80,16 @@ const Executable = struct { .pc_digest = undefined, }; - fn getCoverageFile(cache_dir: std.fs.Dir, pcs: []const usize, pc_digest: u64) MemoryMappedList { + fn getCoverageFile(cache_dir: Io.Dir, pcs: []const usize, pc_digest: u64) MemoryMappedList { const pc_bitset_usizes = bitsetUsizes(pcs.len); const coverage_file_name = std.fmt.hex(pc_digest); comptime assert(abi.SeenPcsHeader.trailing[0] == .pc_bits_usize); comptime assert(abi.SeenPcsHeader.trailing[1] == .pc_addr); - var v = cache_dir.makeOpenPath("v", .{}) catch |e| + var v = cache_dir.createDirPathOpen(io, "v", .{}) catch |e| panic("failed to create directory 'v': {t}", .{e}); - defer v.close(); - const coverage_file, const populate = if (v.createFile(&coverage_file_name, .{ + defer v.close(io); + const coverage_file, const populate = if (v.createFile(io, &coverage_file_name, .{ .read = true, // If we create the file, we want to block other processes while we populate it .lock = .exclusive, @@ -93,7 +97,7 @@ const Executable = struct { })) |f| .{ f, true } else |e| switch (e) { - error.PathAlreadyExists => .{ v.openFile(&coverage_file_name, .{ + error.PathAlreadyExists => .{ v.openFile(io, &coverage_file_name, .{ .mode = .read_write, .lock = .shared, }) catch |e2| panic( @@ -108,7 +112,7 @@ const Executable = struct { pcs.len * @sizeOf(usize); if (populate) { - defer coverage_file.lock(.shared) catch |e| panic( + defer coverage_file.lock(io, .shared) catch |e| panic( "failed to demote lock for coverage file '{s}': {t}", .{ &coverage_file_name, e }, ); @@ -130,10 +134,8 @@ const Executable = struct { } return map; } else { - const size = coverage_file.getEndPos() catch |e| panic( - "failed to stat coverage file '{s}': {t}", - .{ &coverage_file_name, e }, - ); + const size = coverage_file.length(io) catch |e| + panic("failed to stat coverage file '{s}': {t}", .{ &coverage_file_name, e }); if (size != coverage_file_len) panic( "incompatible existing coverage file '{s}' (differing lengths: {} != {})", .{ &coverage_file_name, size, coverage_file_len }, @@ -165,13 +167,11 @@ const Executable = struct { pub fn init(cache_dir_path: []const u8) Executable { var self: Executable = undefined; - const cache_dir = std.fs.cwd().makeOpenPath(cache_dir_path, .{}) catch |e| panic( - "failed to open directory '{s}': {t}", - .{ cache_dir_path, e }, - ); - log_f = cache_dir.createFile("tmp/libfuzzer.log", .{ .truncate = false }) catch |e| + const cache_dir = Io.Dir.cwd().createDirPathOpen(io, cache_dir_path, .{}) catch |e| + panic("failed to open directory '{s}': {t}", .{ cache_dir_path, e }); + log_f = cache_dir.createFile(io, "tmp/libfuzzer.log", .{ .truncate = false }) catch |e| panic("failed to create file 'tmp/libfuzzer.log': {t}", .{e}); - self.cache_f = cache_dir.makeOpenPath("f", .{}) catch |e| + self.cache_f = cache_dir.createDirPathOpen(io, "f", .{}) catch |e| panic("failed to open directory 'f': {t}", .{e}); // Linkers are expected to automatically add symbols prefixed with these for the start and @@ -391,7 +391,7 @@ const Fuzzer = struct { mutations: std.ArrayList(Mutation) = .empty, /// Filesystem directory containing found inputs for future runs - corpus_dir: std.fs.Dir, + corpus_dir: Io.Dir, corpus_dir_idx: usize = 0, pub fn init(test_one: abi.TestOne, unit_test_name: []const u8) Fuzzer { @@ -405,10 +405,10 @@ const Fuzzer = struct { }; const arena = self.arena_ctx.allocator(); - self.corpus_dir = exec.cache_f.makeOpenPath(unit_test_name, .{}) catch |e| + self.corpus_dir = exec.cache_f.createDirPathOpen(io, unit_test_name, .{}) catch |e| panic("failed to open directory '{s}': {t}", .{ unit_test_name, e }); self.input = in: { - const f = self.corpus_dir.createFile("in", .{ + const f = self.corpus_dir.createFile(io, "in", .{ .read = true, .truncate = false, // In case any other fuzz tests are running under the same test name, @@ -419,7 +419,7 @@ const Fuzzer = struct { error.WouldBlock => @panic("input file 'in' is in use by another fuzzing process"), else => panic("failed to create input file 'in': {t}", .{e}), }; - const size = f.getEndPos() catch |e| panic("failed to stat input file 'in': {t}", .{e}); + const size = f.length(io) catch |e| panic("failed to stat input file 'in': {t}", .{e}); const map = (if (size < std.heap.page_size_max) MemoryMappedList.create(f, 8, std.heap.page_size_max) else @@ -445,6 +445,7 @@ const Fuzzer = struct { while (true) { var name_buf: [@sizeOf(usize) * 2]u8 = undefined; const bytes = self.corpus_dir.readFileAlloc( + io, std.fmt.bufPrint(&name_buf, "{x}", .{self.corpus_dir_idx}) catch unreachable, arena, .unlimited, @@ -466,7 +467,7 @@ const Fuzzer = struct { self.input.deinit(); self.corpus.deinit(gpa); self.mutations.deinit(gpa); - self.corpus_dir.close(); + self.corpus_dir.close(io); self.arena_ctx.deinit(); self.* = undefined; } @@ -573,17 +574,10 @@ const Fuzzer = struct { // Write new corpus to cache var name_buf: [@sizeOf(usize) * 2]u8 = undefined; - self.corpus_dir.writeFile(.{ - .sub_path = std.fmt.bufPrint( - &name_buf, - "{x}", - .{self.corpus_dir_idx}, - ) catch unreachable, + self.corpus_dir.writeFile(io, .{ + .sub_path = std.fmt.bufPrint(&name_buf, "{x}", .{self.corpus_dir_idx}) catch unreachable, .data = bytes, - }) catch |e| panic( - "failed to write corpus file '{x}': {t}", - .{ self.corpus_dir_idx, e }, - ); + }) catch |e| panic("failed to write corpus file '{x}': {t}", .{ self.corpus_dir_idx, e }); self.corpus_dir_idx += 1; } } @@ -1320,9 +1314,9 @@ pub const MemoryMappedList = struct { /// How many bytes this list can hold without allocating additional memory. capacity: usize, /// The file is kept open so that it can be resized. - file: std.fs.File, + file: Io.File, - pub fn init(file: std.fs.File, length: usize, capacity: usize) !MemoryMappedList { + pub fn init(file: Io.File, length: usize, capacity: usize) !MemoryMappedList { const ptr = try std.posix.mmap( null, capacity, @@ -1338,13 +1332,13 @@ pub const MemoryMappedList = struct { }; } - pub fn create(file: std.fs.File, length: usize, capacity: usize) !MemoryMappedList { - try file.setEndPos(capacity); + pub fn create(file: Io.File, length: usize, capacity: usize) !MemoryMappedList { + try file.setLength(io, capacity); return init(file, length, capacity); } pub fn deinit(l: *MemoryMappedList) void { - l.file.close(); + l.file.close(io); std.posix.munmap(@volatileCast(l.items.ptr[0..l.capacity])); l.* = undefined; } @@ -1369,7 +1363,7 @@ pub const MemoryMappedList = struct { if (l.capacity >= new_capacity) return; std.posix.munmap(@volatileCast(l.items.ptr[0..l.capacity])); - try l.file.setEndPos(new_capacity); + try l.file.setLength(io, new_capacity); l.* = try init(l.file, l.items.len, new_capacity); } diff --git a/lib/init/src/main.zig b/lib/init/src/main.zig index 88dd8348e1ff..2c6df25be543 100644 --- a/lib/init/src/main.zig +++ b/lib/init/src/main.zig @@ -1,10 +1,34 @@ const std = @import("std"); +const Io = std.Io; + const _NAME = @import(".NAME"); -pub fn main() !void { - // Prints to stderr, ignoring potential errors. +pub fn main(init: std.process.Init) !void { + // Prints to stderr, unbuffered, ignoring potential errors. std.debug.print("All your {s} are belong to us.\n", .{"codebase"}); - try _NAME.bufferedPrint(); + + // This is appropriate for anything that lives as long as the process. + const arena: std.mem.Allocator = init.arena.allocator(); + + // Accessing command line arguments: + const args = try init.minimal.args.toSlice(arena); + for (args) |arg| { + std.log.info("arg: {s}", .{arg}); + } + + // In order to do I/O operations need an `Io` instance. + const io = init.io; + + // Stdout is for the actual output of your application, for example if you + // are implementing gzip, then only the compressed bytes should be sent to + // stdout, not any debugging messages. + var stdout_buffer: [1024]u8 = undefined; + var stdout_file_writer: Io.File.Writer = .init(.stdout(), io, &stdout_buffer); + const stdout_writer = &stdout_file_writer.interface; + + try _NAME.printAnotherMessage(stdout_writer); + + try stdout_writer.flush(); // Don't forget to flush! } test "simple test" { diff --git a/lib/init/src/root.zig b/lib/init/src/root.zig index 94c7cd01194b..5a7125032bf2 100644 --- a/lib/init/src/root.zig +++ b/lib/init/src/root.zig @@ -1,17 +1,12 @@ -//! By convention, root.zig is the root source file when making a library. +//! By convention, root.zig is the root source file when making a package. const std = @import("std"); +const Io = std.Io; -pub fn bufferedPrint() !void { - // Stdout is for the actual output of your application, for example if you - // are implementing gzip, then only the compressed bytes should be sent to - // stdout, not any debugging messages. - var stdout_buffer: [1024]u8 = undefined; - var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); - const stdout = &stdout_writer.interface; - - try stdout.print("Run `zig build test` to run the tests.\n", .{}); - - try stdout.flush(); // Don't forget to flush! +/// This is a documentation comment to explain the `printAnotherMessage` function below. +/// +/// Accepting an `Io.Writer` instance is a handy way to write reusable code. +pub fn printAnotherMessage(writer: *Io.Writer) Io.Writer.Error!void { + try writer.print("Run `zig build test` to run the tests.\n", .{}); } pub fn add(a: i32, b: i32) i32 { diff --git a/lib/libc/darwin/SDKSettings.json b/lib/libc/darwin/SDKSettings.json index 0c26e178fefd..558b8e78c14d 100644 --- a/lib/libc/darwin/SDKSettings.json +++ b/lib/libc/darwin/SDKSettings.json @@ -1 +1 @@ -{"MinimalDisplayName":"26.1"} +{"MinimalDisplayName":"26.2"} diff --git a/lib/libc/darwin/libSystem.tbd b/lib/libc/darwin/libSystem.tbd index 2ff2446d1651..57efb29c6cfc 100644 --- a/lib/libc/darwin/libSystem.tbd +++ b/lib/libc/darwin/libSystem.tbd @@ -400,7 +400,7 @@ tbd-version: 4 targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos, arm64-maccatalyst, arm64e-macos, arm64e-maccatalyst ] install-name: '/usr/lib/system/libcorecrypto.dylib' -current-version: 1922.40.14 +current-version: 1922.60.11 parent-umbrella: - targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos, arm64-maccatalyst, arm64e-macos, arm64e-maccatalyst ] @@ -1182,7 +1182,7 @@ tbd-version: 4 targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos, arm64-maccatalyst, arm64e-macos, arm64e-maccatalyst ] install-name: '/usr/lib/system/libsystem_asl.dylib' -current-version: 404 +current-version: 406 parent-umbrella: - targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos, arm64-maccatalyst, arm64e-macos, arm64e-maccatalyst ] @@ -1609,7 +1609,7 @@ tbd-version: 4 targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos, arm64-maccatalyst, arm64e-macos, arm64e-maccatalyst ] install-name: '/usr/lib/system/libsystem_configuration.dylib' -current-version: 1385.40.9 +current-version: 1385.60.3 parent-umbrella: - targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos, arm64-maccatalyst, arm64e-macos, arm64e-maccatalyst ] @@ -1927,7 +1927,7 @@ tbd-version: 4 targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos, arm64-maccatalyst, arm64e-macos, arm64e-maccatalyst ] install-name: '/usr/lib/system/libsystem_dnssd.dylib' -current-version: 2881.40.18 +current-version: 2881.60.4 parent-umbrella: - targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos, arm64-maccatalyst, arm64e-macos, arm64e-maccatalyst ] @@ -1964,16 +1964,17 @@ exports: tbd-version: 4 targets: [ x86_64-macos, arm64-macos, arm64e-macos ] install-name: '/usr/lib/system/libsystem_eligibility.dylib' -current-version: 286.40.9 +current-version: 286.60.23 parent-umbrella: - targets: [ x86_64-macos, arm64-macos, arm64e-macos ] umbrella: System exports: - targets: [ x86_64-macos, arm64-macos, arm64e-macos ] symbols: [ _os_eligibility_domain_for_name, _os_eligibility_dump_sysdiagnose_data_to_dir, - _os_eligibility_force_domain_answer, _os_eligibility_force_domain_set_answers, - _os_eligibility_get_all_domain_answers, _os_eligibility_get_domain_answer, - _os_eligibility_get_domain_notification_name, _os_eligibility_get_internal_state, + _os_eligibility_fetch_newest_policies, _os_eligibility_force_domain_answer, + _os_eligibility_force_domain_set_answers, _os_eligibility_get_all_domain_answers, + _os_eligibility_get_domain_answer, _os_eligibility_get_domain_notification_name, + _os_eligibility_get_error_description, _os_eligibility_get_internal_state, _os_eligibility_get_state_dump, _os_eligibility_precise_locations, _os_eligibility_reset_all_domains, _os_eligibility_reset_domain, _os_eligibility_set_input, _os_eligibility_set_test_mode ] @@ -2120,7 +2121,7 @@ tbd-version: 4 targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos, arm64-maccatalyst, arm64e-macos, arm64e-maccatalyst ] install-name: '/usr/lib/system/libsystem_kernel.dylib' -current-version: 12377.41.6 +current-version: 12377.61.12 parent-umbrella: - targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos, arm64-maccatalyst, arm64e-macos, arm64e-maccatalyst ] @@ -2860,7 +2861,7 @@ tbd-version: 4 targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos, arm64-maccatalyst, arm64e-macos, arm64e-maccatalyst ] install-name: '/usr/lib/system/libsystem_malloc.dylib' -current-version: 792.41.1 +current-version: 792.60.6 parent-umbrella: - targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos, arm64-maccatalyst, arm64e-macos, arm64e-maccatalyst ] @@ -3027,7 +3028,7 @@ tbd-version: 4 targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos, arm64-maccatalyst, arm64e-macos, arm64e-maccatalyst ] install-name: '/usr/lib/system/libsystem_platform.dylib' -current-version: 359.40.3 +current-version: 359.60.3 parent-umbrella: - targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos, arm64-maccatalyst, arm64e-macos, arm64e-maccatalyst ] @@ -3203,7 +3204,7 @@ tbd-version: 4 targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos, arm64-maccatalyst, arm64e-macos, arm64e-maccatalyst ] install-name: '/usr/lib/system/libsystem_sandbox.dylib' -current-version: 2680.41.1 +current-version: 2680.60.11 parent-umbrella: - targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos, arm64-maccatalyst, arm64e-macos, arm64e-maccatalyst ] @@ -3357,7 +3358,7 @@ tbd-version: 4 targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos, arm64-maccatalyst, arm64e-macos, arm64e-maccatalyst ] install-name: '/usr/lib/system/libsystem_trace.dylib' -current-version: 1815.40.20 +current-version: 1815.61.1 parent-umbrella: - targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos, arm64-maccatalyst, arm64e-macos, arm64e-maccatalyst ] @@ -3444,7 +3445,7 @@ exports: tbd-version: 4 targets: [ x86_64-macos, arm64-macos, arm64e-macos ] install-name: '/usr/lib/system/libsystem_trial.dylib' -current-version: 474.3 +current-version: 474.2 parent-umbrella: - targets: [ x86_64-macos, arm64-macos, arm64e-macos ] umbrella: System @@ -3487,7 +3488,7 @@ tbd-version: 4 targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos, arm64-maccatalyst, arm64e-macos, arm64e-maccatalyst ] install-name: '/usr/lib/system/libxpc.dylib' -current-version: 3089.41.2 +current-version: 3089.60.7 parent-umbrella: - targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos, arm64-maccatalyst, arm64e-macos, arm64e-maccatalyst ] diff --git a/lib/libc/freebsd/COPYRIGHT b/lib/libc/freebsd/COPYRIGHT index 9ed4f98d95a5..9f8b3d4c01d6 100644 --- a/lib/libc/freebsd/COPYRIGHT +++ b/lib/libc/freebsd/COPYRIGHT @@ -1,9 +1,8 @@ -# @(#)COPYRIGHT 8.2 (Berkeley) 3/21/94 The compilation of software known as FreeBSD is distributed under the following terms: -Copyright (c) 1992-2023 The FreeBSD Project. +Copyright (c) 1992-2025 The FreeBSD Project. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions diff --git a/lib/libc/freebsd/abilists b/lib/libc/freebsd/abilists index 5915910eb7e1..a9de2b275c53 100644 Binary files a/lib/libc/freebsd/abilists and b/lib/libc/freebsd/abilists differ diff --git a/lib/libc/freebsd/lib/csu/amd64/crt1_s.S b/lib/libc/freebsd/lib/csu/amd64/crt1_s.S index f7ea076d94f1..3ceea9289330 100644 --- a/lib/libc/freebsd/lib/csu/amd64/crt1_s.S +++ b/lib/libc/freebsd/lib/csu/amd64/crt1_s.S @@ -49,15 +49,12 @@ _start: #ifdef GCRT subq $16, %rsp #endif - movq %rsi, %rcx - movq %rdi, %rsi /* argv = ap */ - addq $8, %rsi /* argv += 1 */ - movq %rdi, %rdx /* env = ap */ - addq $16, %rdx /* env += 2 */ - movslq (%rdi), %rax - movl %eax, %edi /* argc = *(long *)(void *)ap */ - shlq $3, %rax - addq %rax, %rdx /* env += argc */ + movq %rsi, %rcx /* cleanup */ + movslq (%rdi), %rax /* long *ap; tmpargc = *ap */ + leaq 0x8(%rdi), %rsi /* argv = ap + 1 */ + leaq 0x10(%rdi, %rax, 8), %rdx /* env = ap + 2 + tmpargc */ + movl %eax, %edi /* argc = tmpargc */ + #ifdef PIC /* * XXX. %rip relative addressing is not intended for use in the diff --git a/lib/libc/freebsd/lib/csu/arm/crt1_c.c b/lib/libc/freebsd/lib/csu/arm/crt1_c.c index 7de2d333a598..bb40f262f5c2 100644 --- a/lib/libc/freebsd/lib/csu/arm/crt1_c.c +++ b/lib/libc/freebsd/lib/csu/arm/crt1_c.c @@ -41,7 +41,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include diff --git a/lib/libc/freebsd/lib/csu/common/crtbegin.c b/lib/libc/freebsd/lib/csu/common/crtbegin.c index 20e6ea085de5..c6443d580c2a 100644 --- a/lib/libc/freebsd/lib/csu/common/crtbegin.c +++ b/lib/libc/freebsd/lib/csu/common/crtbegin.c @@ -21,7 +21,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include "crt.h" @@ -41,9 +40,8 @@ void __cxa_finalize(void *) __weak_symbol; * When we have ctors/dtors call from the dtor handler before calling * any dtors, otherwise use a destructor. */ -#ifndef HAVE_CTORS +/* zig patch: no HAVE_CTORS */ __attribute__((destructor)) -#endif static void run_cxa_finalize(void) { @@ -53,43 +51,4 @@ run_cxa_finalize(void) } #endif -/* - * On some architectures and toolchains we may need to call the .dtors. - * These are called in the order they are in the ELF file. - */ -#ifdef HAVE_CTORS -static void __do_global_dtors_aux(void) __used; - -static crt_func __CTOR_LIST__[] __section(".ctors") __used = { - (crt_func)-1 -}; -static crt_func __DTOR_LIST__[] __section(".dtors") __used = { - (crt_func)-1 -}; - -static void -__do_global_dtors_aux(void) -{ - crt_func fn; - int n; - -#ifdef SHARED - run_cxa_finalize(); -#endif - - for (n = 1;; n++) { - fn = __DTOR_LIST__[n]; - if (fn == (crt_func)0 || fn == (crt_func)-1) - break; - fn(); - } -} - -asm ( - ".pushsection .fini \n" - "\t" INIT_CALL_SEQ(__do_global_dtors_aux) "\n" - ".popsection \n" -); -#endif - -/* zig patch: remove gcj nonsense */ +/* zig patch: no HAVE_CTORS */ diff --git a/lib/libc/freebsd/lib/csu/common/crtbrand.S b/lib/libc/freebsd/lib/csu/common/crtbrand.S index bff07ac18d23..a53e5b70ba30 100644 --- a/lib/libc/freebsd/lib/csu/common/crtbrand.S +++ b/lib/libc/freebsd/lib/csu/common/crtbrand.S @@ -36,7 +36,7 @@ * for more information. */ - .section .note.tag,"aG",%note,.freebsd.noteG,comdat + .section .note.tag,"aGR",%note,.freebsd.noteG,comdat .p2align 2 .4byte 2f-1f .4byte 4f-3f diff --git a/lib/libc/freebsd/lib/csu/common/crtend.c b/lib/libc/freebsd/lib/csu/common/crtend.c deleted file mode 100644 index 68a935b51651..000000000000 --- a/lib/libc/freebsd/lib/csu/common/crtend.c +++ /dev/null @@ -1,65 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-1-Clause - * - * Copyright 2018 Andrew Turner - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include "crt.h" - -typedef void (*crt_func)(void); - -/* zig patch: remove gcj nonsense */ - -#ifdef HAVE_CTORS - -/* - * On some architectures and toolchains we may need to call the .ctors. - * These are called in the reverse order they are in the ELF file. - */ -static void __do_global_ctors_aux(void) __used; - -static crt_func __CTOR_END__[] __section(".ctors") __used = { - (crt_func)0 -}; -static crt_func __DTOR_END__[] __section(".dtors") __used = { - (crt_func)0 -}; - -static void -__do_global_ctors_aux(void) -{ - crt_func fn; - int n; - - for (n = 1;; n++) { - fn = __CTOR_END__[-n]; - if (fn == (crt_func)0 || fn == (crt_func)-1) - break; - fn(); - } -} - -asm ( - ".pushsection .init \n" - "\t" INIT_CALL_SEQ(__do_global_ctors_aux) "\n" - ".popsection \n" -); -#endif diff --git a/lib/libc/freebsd/lib/csu/common/feature_note.S b/lib/libc/freebsd/lib/csu/common/feature_note.S index 5c1d56d4cde1..fb9f6141699e 100644 --- a/lib/libc/freebsd/lib/csu/common/feature_note.S +++ b/lib/libc/freebsd/lib/csu/common/feature_note.S @@ -29,7 +29,7 @@ #include #include "notes.h" - .section .note.tag,"a",%note + .section .note.tag,"aR",%note .p2align 2 .4byte 2f-1f .4byte 4f-3f diff --git a/lib/libc/freebsd/lib/csu/common/ignore_init_note.S b/lib/libc/freebsd/lib/csu/common/ignore_init_note.S index 57fb4e8f4d51..d78be61f17a9 100644 --- a/lib/libc/freebsd/lib/csu/common/ignore_init_note.S +++ b/lib/libc/freebsd/lib/csu/common/ignore_init_note.S @@ -30,7 +30,7 @@ #include "notes.h" - .section .note.tag,"a",%note + .section .note.tag,"aR",%note .p2align 2 .4byte 2f-1f .4byte 4f-3f diff --git a/lib/libc/freebsd/lib/csu/powerpc/crt.h b/lib/libc/freebsd/lib/csu/powerpc/crt.h index f8b37f65841f..90da2bb9cace 100644 --- a/lib/libc/freebsd/lib/csu/powerpc/crt.h +++ b/lib/libc/freebsd/lib/csu/powerpc/crt.h @@ -24,8 +24,7 @@ #ifndef _CRT_H_ #define _CRT_H_ -/* zig patch: no HAVE_CTORS */ -#define CTORS_CONSTRUCTORS +/* zig patch: no HAVE_CTORS/CTORS_CONSTRUCTORS */ #define INIT_CALL_SEQ(func) "bl " __STRING(func) "; nop" #endif diff --git a/lib/libc/freebsd/lib/csu/powerpc64/crt.h b/lib/libc/freebsd/lib/csu/powerpc64/crt.h index f8b37f65841f..90da2bb9cace 100644 --- a/lib/libc/freebsd/lib/csu/powerpc64/crt.h +++ b/lib/libc/freebsd/lib/csu/powerpc64/crt.h @@ -24,8 +24,7 @@ #ifndef _CRT_H_ #define _CRT_H_ -/* zig patch: no HAVE_CTORS */ -#define CTORS_CONSTRUCTORS +/* zig patch: no HAVE_CTORS/CTORS_CONSTRUCTORS */ #define INIT_CALL_SEQ(func) "bl " __STRING(func) "; nop" #endif diff --git a/lib/libc/freebsd/lib/libc/include/libc_private.h b/lib/libc/freebsd/lib/libc/include/libc_private.h index e051961712ec..db4cbc32be35 100644 --- a/lib/libc/freebsd/lib/libc/include/libc_private.h +++ b/lib/libc/freebsd/lib/libc/include/libc_private.h @@ -37,6 +37,8 @@ #include #include +#include + extern char **environ; /* @@ -185,10 +187,12 @@ typedef enum { PJT_GETTHREADID_NP, PJT_ATTR_GET_NP, PJT_GETNAME_NP, + PJT_SUSPEND_ALL_NP, + PJT_RESUME_ALL_NP, PJT_MAX } pjt_index_t; -typedef int (*pthread_func_t)(void); +typedef void (*pthread_func_t)(void); typedef pthread_func_t pthread_func_entry_t[2]; extern pthread_func_entry_t __thr_jtable[]; @@ -197,9 +201,10 @@ void __set_error_selector(int *(*arg)(void)); int _pthread_mutex_init_calloc_cb_stub(pthread_mutex_t *mutex, void *(calloc_cb)(__size_t, __size_t)); -typedef int (*interpos_func_t)(void); +typedef void (*interpos_func_t)(void); interpos_func_t *__libc_interposing_slot(int interposno); extern interpos_func_t __libc_interposing[] __hidden; +interpos_func_t *__libsys_interposing_slot(int interposno); enum { INTERPOS_accept, @@ -244,11 +249,18 @@ enum { INTERPOS_map_stacks_exec, INTERPOS_fdatasync, INTERPOS_clock_nanosleep, - INTERPOS_distribute_static_tls, + INTERPOS__reserved0, /* was distribute_static_tls */ INTERPOS_pdfork, + INTERPOS_uexterr_gettext, INTERPOS_MAX }; +#define _INTERPOS_SYS(type, idx, ...) \ + ((type *)*(__libc_interposing_slot(idx)))(__VA_ARGS__) +#define INTERPOS_SYS(syscall, ...) \ + _INTERPOS_SYS(__sys_## syscall ##_t, INTERPOS_## syscall \ + __VA_OPT__(,) __VA_ARGS__) + /* * yplib internal interfaces */ @@ -333,102 +345,22 @@ struct __siginfo; struct __ucontext; struct __wrusage; enum idtype; -int __sys_aio_suspend(const struct aiocb * const[], int, - const struct timespec *); -int __sys_accept(int, struct sockaddr *, __socklen_t *); -int __sys_accept4(int, struct sockaddr *, __socklen_t *, int); -int __sys_clock_gettime(__clockid_t, struct timespec *ts); -int __sys_clock_nanosleep(__clockid_t, int, - const struct timespec *, struct timespec *); -int __sys_close(int); -int __sys_close_range(unsigned, unsigned, int); -int __sys_connect(int, const struct sockaddr *, __socklen_t); -int __sys_fcntl(int, int, ...); -int __sys_fdatasync(int); -int __sys_fstat(int fd, struct stat *); -int __sys_fstatfs(int fd, struct statfs *); -int __sys_fstatat(int, const char *, struct stat *, int); -int __sys_fsync(int); -__pid_t __sys_fork(void); -int __sys_ftruncate(int, __off_t); -__ssize_t __sys_getdirentries(int, char *, __size_t, __off_t *); -int __sys_getfsstat(struct statfs *, long, int); -int __sys_gettimeofday(struct timeval *, struct timezone *); -int __sys_kevent(int, const struct kevent *, int, struct kevent *, - int, const struct timespec *); -__off_t __sys_lseek(int, __off_t, int); -void *__sys_mmap(void *, __size_t, int, int, int, __off_t); -int __sys_msync(void *, __size_t, int); -int __sys_nanosleep(const struct timespec *, struct timespec *); -int __sys_open(const char *, int, ...); -int __sys_openat(int, const char *, int, ...); -int __sys_pdfork(int *, int); -int __sys_pselect(int, struct fd_set *, struct fd_set *, - struct fd_set *, const struct timespec *, - const __sigset_t *); -int __sys_ptrace(int, __pid_t, char *, int); -int __sys_poll(struct pollfd *, unsigned, int); -int __sys_ppoll(struct pollfd *, unsigned, const struct timespec *, - const __sigset_t *); -__ssize_t __sys_pread(int, void *, __size_t, __off_t); -__ssize_t __sys_pwrite(int, const void *, __size_t, __off_t); -__ssize_t __sys_read(int, void *, __size_t); -__ssize_t __sys_readv(int, const struct iovec *, int); -__ssize_t __sys_recv(int, void *, __size_t, int); -__ssize_t __sys_recvfrom(int, void *, __size_t, int, struct sockaddr *, - __socklen_t *); -__ssize_t __sys_recvmsg(int, struct msghdr *, int); -int __sys_sched_getcpu(void); -int __sys_select(int, struct fd_set *, struct fd_set *, - struct fd_set *, struct timeval *); -__ssize_t __sys_sendmsg(int, const struct msghdr *, int); -__ssize_t __sys_sendto(int, const void *, __size_t, int, - const struct sockaddr *, __socklen_t); -int __sys_setcontext(const struct __ucontext *); -int __sys_sigaction(int, const struct sigaction *, - struct sigaction *); -int __sys_sigprocmask(int, const __sigset_t *, __sigset_t *); -int __sys_sigsuspend(const __sigset_t *); -int __sys_sigtimedwait(const __sigset_t *, struct __siginfo *, - const struct timespec *); -int __sys_sigwait(const __sigset_t *, int *); -int __sys_sigwaitinfo(const __sigset_t *, struct __siginfo *); -int __sys___specialfd(int, const void *, __size_t); -int __sys_statfs(const char *, struct statfs *); -int __sys_swapcontext(struct __ucontext *, - const struct __ucontext *); -int __sys_thr_kill(long, int); -int __sys_thr_self(long *); -int __sys_truncate(const char *, __off_t); -__pid_t __sys_wait4(__pid_t, int *, int, struct rusage *); -__pid_t __sys_wait6(enum idtype, __id_t, int *, int, - struct __wrusage *, struct __siginfo *); -__ssize_t __sys_write(int, const void *, __size_t); -__ssize_t __sys_writev(int, const struct iovec *, int); -int __sys_shm_open2(const char *, int, __mode_t, int, const char *); +int __libc_execvpe(const char *, char * const *, char * const *); int __libc_sigaction(int, const struct sigaction *, struct sigaction *) __hidden; int __libc_sigprocmask(int, const __sigset_t *, __sigset_t *) __hidden; int __libc_sigsuspend(const __sigset_t *) __hidden; -int __libc_sigwait(const __sigset_t * __restrict, - int * restrict sig); +int __libsys_sigwait(const __sigset_t *, int *) __hidden; int __libc_system(const char *); int __libc_tcdrain(int); -int __fcntl_compat(int fd, int cmd, ...); - -int __sys_futimens(int fd, const struct timespec *times) __hidden; -int __sys_utimensat(int fd, const char *path, - const struct timespec *times, int flag) __hidden; int _elf_aux_info(int aux, void *buf, int buflen); struct dl_phdr_info; int __elf_phdr_match_addr(struct dl_phdr_info *, void *); void __init_elf_aux_vector(void); void __libc_map_stacks_exec(void); -void __libc_distribute_static_tls(__size_t, void *, __size_t, __size_t); -__uintptr_t __libc_static_tls_base(__size_t); void _pthread_cancel_enter(int); void _pthread_cancel_leave(int); @@ -444,7 +376,11 @@ struct __nl_cat_d; struct _xlocale; struct __nl_cat_d *__catopen_l(const char *name, int type, struct _xlocale *locale); -int __strerror_rl(int errnum, char *strerrbuf, __size_t buflen, +int __strerror_rl(int errnum, char *strerrbuf, size_t buflen, struct _xlocale *locale); +struct uexterror; +int __uexterr_format(const struct uexterror *ue, char *buf, size_t bufsz); +int __libc_uexterr_gettext(char *buf, size_t bufsz); + #endif /* _LIBC_PRIVATE_H_ */ diff --git a/lib/libc/glibc/README.md b/lib/libc/glibc/README.md index 7fba7cc994ac..499e49b4d0fd 100644 --- a/lib/libc/glibc/README.md +++ b/lib/libc/glibc/README.md @@ -39,7 +39,7 @@ v2.2.5. The file `lib/libc/glibc/abilist` is a Zig-specific binary blob that defines the supported glibc versions and the set of symbols each version -must define. See https://github.com/ziglang/glibc-abi-tool for the +must define. See https://codeberg.org/ziglang/libc-abi-tools for the tooling to generate this blob. The code in `glibc.zig` parses the abilist to build version-specific stub libraries on demand. diff --git a/lib/libc/include/aarch64-freebsd-none/arm/_align.h b/lib/libc/include/aarch64-freebsd-none/arm/_align.h index 61c22df04881..5a6acf9624fb 100644 --- a/lib/libc/include/aarch64-freebsd-none/arm/_align.h +++ b/lib/libc/include/aarch64-freebsd-none/arm/_align.h @@ -35,8 +35,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)param.h 5.8 (Berkeley) 6/28/91 */ #ifndef _ARM_INCLUDE__ALIGN_H_ diff --git a/lib/libc/include/aarch64-freebsd-none/arm/_limits.h b/lib/libc/include/aarch64-freebsd-none/arm/_limits.h index bdcfd4d9797d..8dfdf8299b90 100644 --- a/lib/libc/include/aarch64-freebsd-none/arm/_limits.h +++ b/lib/libc/include/aarch64-freebsd-none/arm/_limits.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)limits.h 8.3 (Berkeley) 1/4/94 */ #ifndef _MACHINE__LIMITS_H_ diff --git a/lib/libc/include/aarch64-freebsd-none/arm/_types.h b/lib/libc/include/aarch64-freebsd-none/arm/_types.h index ad50fd62c74e..847aff8d2b89 100644 --- a/lib/libc/include/aarch64-freebsd-none/arm/_types.h +++ b/lib/libc/include/aarch64-freebsd-none/arm/_types.h @@ -32,9 +32,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * From: @(#)ansi.h 8.2 (Berkeley) 1/4/94 - * From: @(#)types.h 8.3 (Berkeley) 1/5/94 */ #ifndef _MACHINE__TYPES_H_ diff --git a/lib/libc/include/aarch64-freebsd-none/arm/acle-compat.h b/lib/libc/include/aarch64-freebsd-none/arm/acle-compat.h index d63a1132e55d..8791e469f8a8 100644 --- a/lib/libc/include/aarch64-freebsd-none/arm/acle-compat.h +++ b/lib/libc/include/aarch64-freebsd-none/arm/acle-compat.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 ARM Ltd + * Copyright (c) 2024 Arm Ltd * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,157 +27,5 @@ */ #ifndef __ARM_ARCH - -/* ACLE standardises a set of pre-defines that describe the ARM architecture. - These were mostly implemented in GCC around GCC-4.8; older versions - have no, or only partial support. To provide a level of backwards - compatibility we try to work out what the definitions should be, given - the older pre-defines that GCC did produce. This isn't complete, but - it should be enough for use by routines that depend on this header. */ - -/* No need to handle ARMv8, GCC had ACLE support before that. */ - -#define __ARM_ACLE 101 - -# ifdef __ARM_ARCH_7__ -/* The common subset of ARMv7 in all profiles. */ -# define __ARM_ARCH 7 -# define __ARM_ARCH_ISA_THUMB 2 -# define __ARM_FEATURE_CLZ -# define __ARM_FEATURE_LDREX 7 -# define __ARM_FEATURE_UNALIGNED -# endif - -# if defined (__ARM_ARCH_7A__) || defined (__ARM_ARCH_7R__) -# define __ARM_ARCH 7 -# define __ARM_ARCH_ISA_THUMB 2 -# define __ARM_ARCH_ISA_ARM -# define __ARM_FEATURE_CLZ -# define __ARM_FEATURE_SIMD32 -# define __ARM_FEATURE_DSP -# define __ARM_FEATURE_QBIT -# define __ARM_FEATURE_SAT -# define __ARM_FEATURE_LDREX 15 -# define __ARM_FEATURE_UNALIGNED -# ifdef __ARM_ARCH_7A__ -# define __ARM_ARCH_PROFILE 'A' -# else -# define __ARM_ARCH_PROFILE 'R' -# endif -# endif - -# ifdef __ARM_ARCH_7EM__ -# define __ARM_ARCH 7 -# define __ARM_ARCH_ISA_THUMB 2 -# define __ARM_FEATURE_CLZ -# define __ARM_FEATURE_SIMD32 -# define __ARM_FEATURE_DSP -# define __ARM_FEATURE_QBIT -# define __ARM_FEATURE_SAT -# define __ARM_FEATURE_LDREX 7 -# define __ARM_FEATURE_UNALIGNED -# define __ARM_ARCH_PROFILE 'M' -# endif - -# ifdef __ARM_ARCH_7M__ -# define __ARM_ARCH 7 -# define __ARM_ARCH_ISA_THUMB 2 -# define __ARM_FEATURE_CLZ -# define __ARM_FEATURE_QBIT -# define __ARM_FEATURE_SAT -# define __ARM_FEATURE_LDREX 7 -# define __ARM_FEATURE_UNALIGNED -# define __ARM_ARCH_PROFILE 'M' -# endif - -# ifdef __ARM_ARCH_6T2__ -# define __ARM_ARCH 6 -# define __ARM_ARCH_ISA_THUMB 2 -# define __ARM_ARCH_ISA_ARM -# define __ARM_FEATURE_CLZ -# define __ARM_FEATURE_SIMD32 -# define __ARM_FEATURE_DSP -# define __ARM_FEATURE_QBIT -# define __ARM_FEATURE_SAT -# define __ARM_FEATURE_LDREX 4 -# define __ARM_FEATURE_UNALIGNED -# endif - -# ifdef __ARM_ARCH_6M__ -# define __ARM_ARCH 6 -# define __ARM_ARCH_ISA_THUMB 1 -# define __ARM_ARCH_PROFILE 'M' -# endif - -# if defined (__ARM_ARCH_6__) || defined (__ARM_ARCH_6J__) \ - || defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6Z__) \ - || defined (__ARM_ARCH_6ZK__) -# define __ARM_ARCH 6 -# define __ARM_ARCH_ISA_THUMB 1 -# define __ARM_ARCH_ISA_ARM -# define __ARM_FEATURE_CLZ -# define __ARM_FEATURE_SIMD32 -# define __ARM_FEATURE_DSP -# define __ARM_FEATURE_QBIT -# define __ARM_FEATURE_SAT -# define __ARM_FEATURE_UNALIGNED -# ifndef __thumb__ -# if defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6ZK__) -# define __ARM_FEATURE_LDREX 15 -# else -# define __ARM_FEATURE_LDREX 4 -# endif -# endif -# endif - -# if defined (__ARM_ARCH_5TE__) || defined (__ARM_ARCH_5E__) -# define __ARM_ARCH 5 -# define __ARM_ARCH_ISA_ARM -# ifdef __ARM_ARCH_5TE__ -# define __ARM_ARCH_ISA_THUMB 1 -# endif -# define __ARM_FEATURE_CLZ -# define __ARM_FEATURE_DSP -# endif - -# if defined (__ARM_ARCH_5T__) || defined (__ARM_ARCH_5__) -# define __ARM_ARCH 5 -# define __ARM_ARCH_ISA_ARM -# ifdef __ARM_ARCH_5TE__ -# define __ARM_ARCH_ISA_THUMB 1 -# endif -# define __ARM_FEATURE_CLZ -# endif - -# ifdef __ARM_ARCH_4T__ -# define __ARM_ARCH 4 -# define __ARM_ARCH_ISA_ARM -# define __ARM_ARCH_ISA_THUMB 1 -# endif - -# ifdef __ARM_ARCH_4__ -# define __ARM_ARCH 4 -# define __ARM_ARCH_ISA_ARM -# endif - -# if defined (__ARM_ARCH_3__) || defined (__ARM_ARCH_3M__) -# define __ARM_ARCH 3 -# define __ARM_ARCH_ISA_ARM -# endif - -# ifdef __ARM_ARCH_2__ -# define __ARM_ARCH 2 -# define __ARM_ARCH_ISA_ARM -# endif - -# ifdef __ARMEB__ -# define __ARM_BIG_ENDIAN -# endif - -/* If we still don't know what the target architecture is, then we're - probably not using GCC. */ -# ifndef __ARM_ARCH -# error Unable to determine architecture version. -# endif - -#endif /* __ARM_ARCH */ \ No newline at end of file +#error Your compiler is too old +#endif \ No newline at end of file diff --git a/lib/libc/include/aarch64-freebsd-none/arm/asm.h b/lib/libc/include/aarch64-freebsd-none/arm/asm.h index fa7cbd669432..52acdd60dbe9 100644 --- a/lib/libc/include/aarch64-freebsd-none/arm/asm.h +++ b/lib/libc/include/aarch64-freebsd-none/arm/asm.h @@ -32,8 +32,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)asm.h 5.5 (Berkeley) 5/7/91 */ #ifndef _MACHINE_ASM_H_ @@ -176,7 +174,6 @@ # define RETne bxne lr # define RETc(c) bx##c lr -#if __ARM_ARCH >= 7 #define ISB isb #define DSB dsb #define DMB dmb @@ -190,12 +187,5 @@ #define ERET .word 0xe160006e #endif -#elif __ARM_ARCH == 6 -#include -#define ISB mcr CP15_CP15ISB -#define DSB mcr CP15_CP15DSB -#define DMB mcr CP15_CP15DMB -#define WFI mcr CP15_CP15WFI -#endif #endif /* !_MACHINE_ASM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-freebsd-none/arm/atomic.h b/lib/libc/include/aarch64-freebsd-none/arm/atomic.h index f4e9fb5c1b29..9a8ae6bc124e 100644 --- a/lib/libc/include/aarch64-freebsd-none/arm/atomic.h +++ b/lib/libc/include/aarch64-freebsd-none/arm/atomic.h @@ -41,15 +41,9 @@ #include -#if __ARM_ARCH >= 7 #define isb() __asm __volatile("isb" : : : "memory") #define dsb() __asm __volatile("dsb" : : : "memory") #define dmb() __asm __volatile("dmb" : : : "memory") -#else -#define isb() __asm __volatile("mcr p15, 0, %0, c7, c5, 4" : : "r" (0) : "memory") -#define dsb() __asm __volatile("mcr p15, 0, %0, c7, c10, 4" : : "r" (0) : "memory") -#define dmb() __asm __volatile("mcr p15, 0, %0, c7, c10, 5" : : "r" (0) : "memory") -#endif #define mb() dmb() #define wmb() dmb() @@ -614,7 +608,7 @@ atomic_fetchadd_long(volatile u_long *p, u_long val) } static __inline uint32_t -atomic_load_acq_32(volatile uint32_t *p) +atomic_load_acq_32(const volatile uint32_t *p) { uint32_t v; @@ -624,7 +618,7 @@ atomic_load_acq_32(volatile uint32_t *p) } static __inline uint64_t -atomic_load_64(volatile uint64_t *p) +atomic_load_64(const volatile uint64_t *p) { uint64_t ret; @@ -643,7 +637,7 @@ atomic_load_64(volatile uint64_t *p) } static __inline uint64_t -atomic_load_acq_64(volatile uint64_t *p) +atomic_load_acq_64(const volatile uint64_t *p) { uint64_t ret; @@ -653,7 +647,7 @@ atomic_load_acq_64(volatile uint64_t *p) } static __inline u_long -atomic_load_acq_long(volatile u_long *p) +atomic_load_acq_long(const volatile u_long *p) { u_long v; @@ -898,8 +892,6 @@ atomic_testandclear_long(volatile u_long *p, u_int v) return (atomic_testandclear_32((volatile uint32_t *)p, v)); } -#define atomic_testandclear_long atomic_testandclear_long - static __inline int atomic_testandclear_64(volatile uint64_t *p, u_int v) @@ -958,7 +950,16 @@ atomic_testandset_long(volatile u_long *p, u_int v) return (atomic_testandset_32((volatile uint32_t *)p, v)); } -#define atomic_testandset_long atomic_testandset_long + +static __inline int +atomic_testandset_acq_long(volatile u_long *p, u_int v) +{ + int ret; + + ret = atomic_testandset_32((volatile uint32_t *)p, v); + dmb(); + return (ret); +} static __inline int atomic_testandset_64(volatile uint64_t *p, u_int v) @@ -1052,6 +1053,12 @@ atomic_thread_fence_seq_cst(void) dmb(); } +#define atomic_add_ptr atomic_add_32 +#define atomic_add_acq_ptr atomic_add_acq_32 +#define atomic_add_rel_ptr atomic_add_rel_32 +#define atomic_subtract_ptr atomic_subtract_32 +#define atomic_subtract_acq_ptr atomic_subtract_acq_32 +#define atomic_subtract_rel_ptr atomic_subtract_rel_32 #define atomic_clear_ptr atomic_clear_32 #define atomic_clear_acq_ptr atomic_clear_acq_32 #define atomic_clear_rel_ptr atomic_clear_rel_32 @@ -1059,15 +1066,18 @@ atomic_thread_fence_seq_cst(void) #define atomic_set_acq_ptr atomic_set_acq_32 #define atomic_set_rel_ptr atomic_set_rel_32 #define atomic_fcmpset_ptr atomic_fcmpset_32 -#define atomic_fcmpset_rel_ptr atomic_fcmpset_rel_32 #define atomic_fcmpset_acq_ptr atomic_fcmpset_acq_32 +#define atomic_fcmpset_rel_ptr atomic_fcmpset_rel_32 #define atomic_cmpset_ptr atomic_cmpset_32 #define atomic_cmpset_acq_ptr atomic_cmpset_acq_32 #define atomic_cmpset_rel_ptr atomic_cmpset_rel_32 +#define atomic_fetchadd_ptr atomic_fetchadd_32 +#define atomic_readandclear_ptr atomic_readandclear_32 #define atomic_load_acq_ptr atomic_load_acq_32 #define atomic_store_rel_ptr atomic_store_rel_32 #define atomic_swap_ptr atomic_swap_32 -#define atomic_readandclear_ptr atomic_readandclear_32 +#define atomic_testandset_ptr atomic_testandset_32 +#define atomic_testandclear_ptr atomic_testandclear_32 #define atomic_add_int atomic_add_32 #define atomic_add_acq_int atomic_add_acq_32 @@ -1093,12 +1103,9 @@ atomic_thread_fence_seq_cst(void) #define atomic_store_rel_int atomic_store_rel_32 #define atomic_swap_int atomic_swap_32 -/* - * For: - * - atomic_load_acq_8 - * - atomic_load_acq_16 - * - atomic_testandset_acq_long - */ #include +#define atomic_set_short atomic_set_16 +#define atomic_clear_short atomic_clear_16 + #endif /* _MACHINE_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-freebsd-none/arm/cpu.h b/lib/libc/include/aarch64-freebsd-none/arm/cpu.h index cc6c423703cf..edba80742197 100644 --- a/lib/libc/include/aarch64-freebsd-none/arm/cpu.h +++ b/lib/libc/include/aarch64-freebsd-none/arm/cpu.h @@ -45,13 +45,7 @@ void cpu_halt(void); * unconditionally with -DSMP. Although it looks like a bug, * handle this case here and in #elif condition in ARM_SMP_UP macro. */ -#if __ARM_ARCH <= 6 && defined(SMP) && !defined(KLD_MODULE) -#error SMP option is not supported on ARMv6 -#endif -#if __ARM_ARCH <= 6 && defined(SMP_ON_UP) -#error SMP_ON_UP option is only supported on ARMv7+ CPUs -#endif #if !defined(SMP) && defined(SMP_ON_UP) #error SMP option must be defined for SMP_ON_UP option @@ -68,7 +62,7 @@ do { \ up_code; \ } \ } while (0) -#elif defined(SMP) && __ARM_ARCH > 6 +#elif defined(SMP) #define ARM_SMP_UP(smp_code, up_code) \ do { \ smp_code; \ @@ -146,15 +140,15 @@ fname(uint64_t reg) \ /* TLB */ _WF0(_CP15_TLBIALL, CP15_TLBIALL) /* Invalidate entire unified TLB */ -#if __ARM_ARCH >= 7 && defined(SMP) +#if defined(SMP) _WF0(_CP15_TLBIALLIS, CP15_TLBIALLIS) /* Invalidate entire unified TLB IS */ #endif _WF1(_CP15_TLBIASID, CP15_TLBIASID(%0)) /* Invalidate unified TLB by ASID */ -#if __ARM_ARCH >= 7 && defined(SMP) +#if defined(SMP) _WF1(_CP15_TLBIASIDIS, CP15_TLBIASIDIS(%0)) /* Invalidate unified TLB by ASID IS */ #endif _WF1(_CP15_TLBIMVAA, CP15_TLBIMVAA(%0)) /* Invalidate unified TLB by MVA, all ASID */ -#if __ARM_ARCH >= 7 && defined(SMP) +#if defined(SMP) _WF1(_CP15_TLBIMVAAIS, CP15_TLBIMVAAIS(%0)) /* Invalidate unified TLB by MVA, all ASID IS */ #endif _WF1(_CP15_TLBIMVA, CP15_TLBIMVA(%0)) /* Invalidate unified TLB by MVA */ @@ -164,21 +158,19 @@ _WF1(_CP15_TTB_SET, CP15_TTBR0(%0)) /* Cache and Branch predictor */ _WF0(_CP15_BPIALL, CP15_BPIALL) /* Branch predictor invalidate all */ -#if __ARM_ARCH >= 7 && defined(SMP) +#if defined(SMP) _WF0(_CP15_BPIALLIS, CP15_BPIALLIS) /* Branch predictor invalidate all IS */ #endif _WF1(_CP15_BPIMVA, CP15_BPIMVA(%0)) /* Branch predictor invalidate by MVA */ _WF1(_CP15_DCCIMVAC, CP15_DCCIMVAC(%0)) /* Data cache clean and invalidate by MVA PoC */ _WF1(_CP15_DCCISW, CP15_DCCISW(%0)) /* Data cache clean and invalidate by set/way */ _WF1(_CP15_DCCMVAC, CP15_DCCMVAC(%0)) /* Data cache clean by MVA PoC */ -#if __ARM_ARCH >= 7 _WF1(_CP15_DCCMVAU, CP15_DCCMVAU(%0)) /* Data cache clean by MVA PoU */ -#endif _WF1(_CP15_DCCSW, CP15_DCCSW(%0)) /* Data cache clean by set/way */ _WF1(_CP15_DCIMVAC, CP15_DCIMVAC(%0)) /* Data cache invalidate by MVA PoC */ _WF1(_CP15_DCISW, CP15_DCISW(%0)) /* Data cache invalidate by set/way */ _WF0(_CP15_ICIALLU, CP15_ICIALLU) /* Instruction cache invalidate all PoU */ -#if __ARM_ARCH >= 7 && defined(SMP) +#if defined(SMP) _WF0(_CP15_ICIALLUIS, CP15_ICIALLUIS) /* Instruction cache invalidate all PoU IS */ #endif _WF1(_CP15_ICIMVAU, CP15_ICIMVAU(%0)) /* Instruction cache invalidate */ @@ -209,10 +201,8 @@ _WF1(cp15_prrr_set, CP15_PRRR(%0)) _WF1(cp15_nmrr_set, CP15_NMRR(%0)) _RF0(cp15_ttbr_get, CP15_TTBR0(%0)) _RF0(cp15_dfar_get, CP15_DFAR(%0)) -#if __ARM_ARCH >= 7 _RF0(cp15_ifar_get, CP15_IFAR(%0)) _RF0(cp15_l2ctlr_get, CP15_L2CTLR(%0)) -#endif _RF0(cp15_actlr_get, CP15_ACTLR(%0)) _WF1(cp15_actlr_set, CP15_ACTLR(%0)) _WF1(cp15_ats1cpr_set, CP15_ATS1CPR(%0)) @@ -251,14 +241,6 @@ _RF0(cp15_cbar_get, CP15_CBAR(%0)) /* Performance Monitor registers */ -#if __ARM_ARCH == 6 && defined(CPU_ARM1176) -_RF0(cp15_pmuserenr_get, CP15_PMUSERENR(%0)) -_WF1(cp15_pmuserenr_set, CP15_PMUSERENR(%0)) -_RF0(cp15_pmcr_get, CP15_PMCR(%0)) -_WF1(cp15_pmcr_set, CP15_PMCR(%0)) -_RF0(cp15_pmccntr_get, CP15_PMCCNTR(%0)) -_WF1(cp15_pmccntr_set, CP15_PMCCNTR(%0)) -#elif __ARM_ARCH > 6 _RF0(cp15_pmcr_get, CP15_PMCR(%0)) _WF1(cp15_pmcr_set, CP15_PMCR(%0)) _RF0(cp15_pmcnten_get, CP15_PMCNTENSET(%0)) @@ -280,7 +262,6 @@ _WF1(cp15_pmuserenr_set, CP15_PMUSERENR(%0)) _RF0(cp15_pminten_get, CP15_PMINTENSET(%0)) _WF1(cp15_pminten_set, CP15_PMINTENSET(%0)) _WF1(cp15_pminten_clr, CP15_PMINTENCLR(%0)) -#endif _RF0(cp15_tpidrurw_get, CP15_TPIDRURW(%0)) _WF1(cp15_tpidrurw_set, CP15_TPIDRURW(%0)) @@ -380,7 +361,7 @@ tlb_flush_range_local(vm_offset_t va, vm_size_t size) } /* Broadcasting operations. */ -#if __ARM_ARCH >= 7 && defined(SMP) +#if defined(SMP) static __inline void tlb_flush_all(void) @@ -442,14 +423,14 @@ tlb_flush_range(vm_offset_t va, vm_size_t size) ); dsb(); } -#else /* __ARM_ARCH < 7 */ +#else /* !SMP */ #define tlb_flush_all() tlb_flush_all_local() #define tlb_flush_all_ng() tlb_flush_all_ng_local() #define tlb_flush(va) tlb_flush_local(va) #define tlb_flush_range(va, size) tlb_flush_range_local(va, size) -#endif /* __ARM_ARCH < 7 */ +#endif /* !SMP */ /* * Cache maintenance operations. @@ -465,11 +446,7 @@ icache_sync(vm_offset_t va, vm_size_t size) va &= ~cpuinfo.dcache_line_mask; for ( ; va < eva; va += cpuinfo.dcache_line_size) { -#if __ARM_ARCH >= 7 _CP15_DCCMVAU(va); -#else - _CP15_DCCMVAC(va); -#endif } dsb(); ARM_SMP_UP( @@ -515,11 +492,7 @@ dcache_wb_pou(vm_offset_t va, vm_size_t size) dsb(); va &= ~cpuinfo.dcache_line_mask; for ( ; va < eva; va += cpuinfo.dcache_line_size) { -#if __ARM_ARCH >= 7 _CP15_DCCMVAU(va); -#else - _CP15_DCCMVAC(va); -#endif } dsb(); } @@ -686,8 +659,7 @@ cp15_ats1cuw_check(vm_offset_t addr) static __inline uint64_t get_cyclecount(void) { -#if __ARM_ARCH > 6 || (__ARM_ARCH == 6 && defined(CPU_ARM1176)) -#if (__ARM_ARCH > 6) && defined(DEV_PMU) +#if defined(DEV_PMU) if (pmu_attched) { u_int cpu; uint64_t h, h2; @@ -711,12 +683,6 @@ get_cyclecount(void) } else #endif return cp15_pmccntr_get(); -#else /* No performance counters, so use nanotime(9). */ - struct timespec tv; - - nanotime(&tv); - return (tv.tv_sec * (uint64_t)1000000000ull + tv.tv_nsec); -#endif } #endif @@ -729,7 +695,7 @@ get_cyclecount(void) #define cpu_spinwait() /* nothing */ #define cpu_lock_delay() DELAY(1) -#define ARM_NVEC 8 +#define ARM_NVEC 7 #define ARM_VEC_ALL 0xffffffff extern vm_offset_t vector_page; diff --git a/lib/libc/include/aarch64-freebsd-none/arm/cpufunc.h b/lib/libc/include/aarch64-freebsd-none/arm/cpufunc.h index 0f3b1a139be9..95bcd2b27b0d 100644 --- a/lib/libc/include/aarch64-freebsd-none/arm/cpufunc.h +++ b/lib/libc/include/aarch64-freebsd-none/arm/cpufunc.h @@ -97,9 +97,6 @@ void armv7_cpu_sleep (int); void pj4b_config (void); #endif -#if defined(CPU_ARM1176) -void arm11x6_sleep (int); /* no ref. for errata */ -#endif /* diff --git a/lib/libc/include/aarch64-freebsd-none/arm/fenv.h b/lib/libc/include/aarch64-freebsd-none/arm/fenv.h index 4aa93a759c26..ca9d01ef40f0 100644 --- a/lib/libc/include/aarch64-freebsd-none/arm/fenv.h +++ b/lib/libc/include/aarch64-freebsd-none/arm/fenv.h @@ -29,6 +29,7 @@ #ifndef _FENV_H_ #define _FENV_H_ +#include #include #ifndef __fenv_static diff --git a/lib/libc/include/aarch64-freebsd-none/arm/float.h b/lib/libc/include/aarch64-freebsd-none/arm/float.h index 8f8a41e8562d..b0ab1592b2ad 100644 --- a/lib/libc/include/aarch64-freebsd-none/arm/float.h +++ b/lib/libc/include/aarch64-freebsd-none/arm/float.h @@ -27,8 +27,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)float.h 7.1 (Berkeley) 5/8/90 */ #ifndef _MACHINE_FLOAT_H_ diff --git a/lib/libc/include/aarch64-freebsd-none/arm/ieeefp.h b/lib/libc/include/aarch64-freebsd-none/arm/ieeefp.h index f3ef2992bc3b..417517432cf5 100644 --- a/lib/libc/include/aarch64-freebsd-none/arm/ieeefp.h +++ b/lib/libc/include/aarch64-freebsd-none/arm/ieeefp.h @@ -49,4 +49,14 @@ typedef enum { #define fp_except_t int +/* Augment the userland declarations. */ +__BEGIN_DECLS +extern fp_rnd_t fpgetround(void); +extern fp_rnd_t fpsetround(fp_rnd_t); +extern fp_except_t fpgetmask(void); +extern fp_except_t fpsetmask(fp_except_t); +extern fp_except_t fpgetsticky(void); +extern fp_except_t fpsetsticky(fp_except_t); +__END_DECLS + #endif /* _MACHINE_IEEEFP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-freebsd-none/arm/param.h b/lib/libc/include/aarch64-freebsd-none/arm/param.h index edab4a72b46f..6fab13f3955c 100644 --- a/lib/libc/include/aarch64-freebsd-none/arm/param.h +++ b/lib/libc/include/aarch64-freebsd-none/arm/param.h @@ -35,8 +35,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)param.h 5.8 (Berkeley) 6/28/91 */ #ifndef _ARM_INCLUDE_PARAM_H_ @@ -51,17 +49,11 @@ #define STACKALIGNBYTES (8 - 1) #define STACKALIGN(p) ((u_int)(p) & ~STACKALIGNBYTES) -#define __PCI_REROUTE_INTERRUPT - #ifndef MACHINE #define MACHINE "arm" #endif #ifndef MACHINE_ARCH -#if __ARM_ARCH >= 7 #define MACHINE_ARCH "armv7" -#else -#define MACHINE_ARCH "armv6" -#endif #endif #ifdef SMP @@ -76,6 +68,8 @@ #define MAXMEMDOM 1 #endif +#define __HAVE_STATIC_DEVMAP + #define ALIGNBYTES _ALIGNBYTES #define ALIGN(p) _ALIGN(p) /* @@ -129,17 +123,10 @@ /* * Mach derived conversion macros */ -#define trunc_page(x) ((x) & ~PAGE_MASK) -#define round_page(x) (((x) + PAGE_MASK) & ~PAGE_MASK) #define trunc_1mpage(x) ((unsigned)(x) & ~PDRMASK) #define round_1mpage(x) ((((unsigned)(x)) + PDRMASK) & ~PDRMASK) -#define atop(x) ((unsigned)(x) >> PAGE_SHIFT) -#define ptoa(x) ((unsigned)(x) << PAGE_SHIFT) - #define arm32_btop(x) ((unsigned)(x) >> PAGE_SHIFT) #define arm32_ptob(x) ((unsigned)(x) << PAGE_SHIFT) -#define pgtok(x) ((x) * (PAGE_SIZE / 1024)) - #endif /* !_ARM_INCLUDE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-freebsd-none/arm/pmap.h b/lib/libc/include/aarch64-freebsd-none/arm/pmap.h index 78b6e5b2c148..3b18349d8813 100644 --- a/lib/libc/include/aarch64-freebsd-none/arm/pmap.h +++ b/lib/libc/include/aarch64-freebsd-none/arm/pmap.h @@ -39,9 +39,6 @@ * map the page tables using the pagetables themselves. This is done to * reduce the impact on kernel virtual memory for lots of sparse address * space, and to reduce the cost of memory to each process. - * - * from: hp300: @(#)pmap.h 7.2 (Berkeley) 12/16/90 - * from: @(#)pmap.h 7.4 (Berkeley) 5/12/91 * from: FreeBSD: src/sys/i386/include/pmap.h,v 1.70 2000/11/30 */ @@ -138,9 +135,9 @@ extern ttb_entry_t pmap_kern_ttb; /* TTB for kernel pmap */ * vtopte2(). */ void pmap_bootstrap(vm_offset_t); -void pmap_kenter(vm_offset_t, vm_paddr_t); +void pmap_kenter(vm_offset_t, vm_size_t, vm_paddr_t, int); void pmap_kremove(vm_offset_t); -boolean_t pmap_page_is_mapped(vm_page_t); +bool pmap_page_is_mapped(vm_page_t); bool pmap_ps_enabled(pmap_t pmap); void pmap_tlb_flush(pmap_t, vm_offset_t); @@ -175,15 +172,9 @@ void pmap_page_set_memattr(vm_page_t, vm_memattr_t); #define pmap_map_delete(pmap, sva, eva) pmap_remove(pmap, sva, eva) void *pmap_mapdev(vm_paddr_t, vm_size_t); +void *pmap_mapdev_attr(vm_paddr_t, vm_size_t, vm_memattr_t); void pmap_unmapdev(void *, vm_size_t); -static inline void * -pmap_mapdev_attr(vm_paddr_t addr __unused, vm_size_t size __unused, - int attr __unused) -{ - panic("%s is not implemented yet!\n", __func__); -} - struct pcb; void pmap_set_pcb_pagedir(pmap_t, struct pcb *); diff --git a/lib/libc/include/aarch64-freebsd-none/arm/proc.h b/lib/libc/include/aarch64-freebsd-none/arm/proc.h index b37f5a690ecd..a142642becf5 100644 --- a/lib/libc/include/aarch64-freebsd-none/arm/proc.h +++ b/lib/libc/include/aarch64-freebsd-none/arm/proc.h @@ -31,8 +31,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)proc.h 7.1 (Berkeley) 5/15/91 * from: FreeBSD: src/sys/i386/include/proc.h,v 1.11 2001/06/29 */ diff --git a/lib/libc/include/aarch64-freebsd-none/arm/profile.h b/lib/libc/include/aarch64-freebsd-none/arm/profile.h index 6154b6b66286..83f743ca16cf 100644 --- a/lib/libc/include/aarch64-freebsd-none/arm/profile.h +++ b/lib/libc/include/aarch64-freebsd-none/arm/profile.h @@ -31,8 +31,6 @@ * 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. - * - * @(#)profile.h 8.1 (Berkeley) 6/11/93 */ #ifndef _MACHINE_PROFILE_H_ diff --git a/lib/libc/include/aarch64-freebsd-none/arm/reloc.h b/lib/libc/include/aarch64-freebsd-none/arm/reloc.h index 9a7855cbeeda..f318d27664e3 100644 --- a/lib/libc/include/aarch64-freebsd-none/arm/reloc.h +++ b/lib/libc/include/aarch64-freebsd-none/arm/reloc.h @@ -31,8 +31,6 @@ * 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. - * - * @(#)reloc.h 8.1 (Berkeley) 6/10/93 */ #ifndef _MACHINE_RELOC_H_ diff --git a/lib/libc/include/aarch64-freebsd-none/arm/resource.h b/lib/libc/include/aarch64-freebsd-none/arm/resource.h index 8edfc1ab1ea3..c22c873f6b01 100644 --- a/lib/libc/include/aarch64-freebsd-none/arm/resource.h +++ b/lib/libc/include/aarch64-freebsd-none/arm/resource.h @@ -40,8 +40,6 @@ #define SYS_RES_MEMORY 3 /* i/o memory */ #define SYS_RES_IOPORT 4 /* i/o ports */ #define SYS_RES_GPIO 5 /* general purpose i/o */ -#ifdef NEW_PCIB #define PCI_RES_BUS 6 /* PCI bus numbers */ -#endif #endif /* !_MACHINE_RESOURCE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-freebsd-none/arm/runq.h b/lib/libc/include/aarch64-freebsd-none/arm/runq.h deleted file mode 100644 index 63b30d582a97..000000000000 --- a/lib/libc/include/aarch64-freebsd-none/arm/runq.h +++ /dev/null @@ -1,46 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2001 Jake Burkholder - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _MACHINE_RUNQ_H_ -#define _MACHINE_RUNQ_H_ - -#define RQB_LEN (2) /* Number of priority status words. */ -#define RQB_L2BPW (5) /* Log2(sizeof(rqb_word_t) * NBBY)). */ -#define RQB_BPW (1<> RQB_L2BPW) - -#define RQB_FFS(word) (ffs(word) - 1) - -/* - * Type of run queue status word. - */ -typedef u_int32_t rqb_word_t; - -#endif \ No newline at end of file diff --git a/lib/libc/include/aarch64-freebsd-none/arm/signal.h b/lib/libc/include/aarch64-freebsd-none/arm/signal.h index d81c04382e06..df41f25faac9 100644 --- a/lib/libc/include/aarch64-freebsd-none/arm/signal.h +++ b/lib/libc/include/aarch64-freebsd-none/arm/signal.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)signal.h 8.1 (Berkeley) 6/11/93 * from: FreeBSD: src/sys/i386/include/signal.h,v 1.13 2000/11/09 * from: FreeBSD: src/sys/sparc64/include/signal.h,v 1.6 2001/09/30 18:52:17 */ diff --git a/lib/libc/include/aarch64-freebsd-none/arm/sysarch.h b/lib/libc/include/aarch64-freebsd-none/arm/sysarch.h index 4a37651d15dd..4536de8ecb20 100644 --- a/lib/libc/include/aarch64-freebsd-none/arm/sysarch.h +++ b/lib/libc/include/aarch64-freebsd-none/arm/sysarch.h @@ -38,6 +38,8 @@ #ifndef _ARM_SYSARCH_H_ #define _ARM_SYSARCH_H_ +#include + #include #ifndef LOCORE diff --git a/lib/libc/include/aarch64-freebsd-none/arm/sysreg.h b/lib/libc/include/aarch64-freebsd-none/arm/sysreg.h index d83305a478d4..ce88a0a4b92e 100644 --- a/lib/libc/include/aarch64-freebsd-none/arm/sysreg.h +++ b/lib/libc/include/aarch64-freebsd-none/arm/sysreg.h @@ -127,11 +127,9 @@ /* From ARMv6: */ #define CP15_IFSR(rr) p15, 0, rr, c5, c0, 1 /* Instruction Fault Status Register */ -#if __ARM_ARCH >= 7 /* From ARMv7: */ #define CP15_ADFSR(rr) p15, 0, rr, c5, c1, 0 /* Auxiliary Data Fault Status Register */ #define CP15_AIFSR(rr) p15, 0, rr, c5, c1, 1 /* Auxiliary Instruction Fault Status Register */ -#endif /* * CP15 C6 registers @@ -147,7 +145,7 @@ /* * CP15 C7 registers */ -#if __ARM_ARCH >= 7 && defined(SMP) +#if defined(SMP) /* From ARMv7: */ #define CP15_ICIALLUIS p15, 0, r0, c7, c1, 0 /* Instruction cache invalidate all PoU, IS */ #define CP15_BPIALLIS p15, 0, r0, c7, c1, 6 /* Branch predictor invalidate all IS */ @@ -157,17 +155,9 @@ #define CP15_ICIALLU p15, 0, r0, c7, c5, 0 /* Instruction cache invalidate all PoU */ #define CP15_ICIMVAU(rr) p15, 0, rr, c7, c5, 1 /* Instruction cache invalidate */ -#if __ARM_ARCH == 6 -/* Deprecated in ARMv7 */ -#define CP15_CP15ISB p15, 0, r0, c7, c5, 4 /* ISB */ -#endif #define CP15_BPIALL p15, 0, r0, c7, c5, 6 /* Branch predictor invalidate all */ #define CP15_BPIMVA p15, 0, rr, c7, c5, 7 /* Branch predictor invalidate by MVA */ -#if __ARM_ARCH == 6 -/* Only ARMv6: */ -#define CP15_DCIALL p15, 0, r0, c7, c6, 0 /* Data cache invalidate all */ -#endif #define CP15_DCIMVAC(rr) p15, 0, rr, c7, c6, 1 /* Data cache invalidate by MVA PoC */ #define CP15_DCISW(rr) p15, 0, rr, c7, c6, 2 /* Data cache invalidate by set/way */ @@ -176,43 +166,25 @@ #define CP15_ATS1CUR(rr) p15, 0, rr, c7, c8, 2 /* Stage 1 Current state unprivileged read */ #define CP15_ATS1CUW(rr) p15, 0, rr, c7, c8, 3 /* Stage 1 Current state unprivileged write */ -#if __ARM_ARCH >= 7 /* From ARMv7: */ #define CP15_ATS12NSOPR(rr) p15, 0, rr, c7, c8, 4 /* Stages 1 and 2 Non-secure only PL1 read */ #define CP15_ATS12NSOPW(rr) p15, 0, rr, c7, c8, 5 /* Stages 1 and 2 Non-secure only PL1 write */ #define CP15_ATS12NSOUR(rr) p15, 0, rr, c7, c8, 6 /* Stages 1 and 2 Non-secure only unprivileged read */ #define CP15_ATS12NSOUW(rr) p15, 0, rr, c7, c8, 7 /* Stages 1 and 2 Non-secure only unprivileged write */ -#endif -#if __ARM_ARCH == 6 -/* Only ARMv6: */ -#define CP15_DCCALL p15, 0, r0, c7, c10, 0 /* Data cache clean all */ -#endif #define CP15_DCCMVAC(rr) p15, 0, rr, c7, c10, 1 /* Data cache clean by MVA PoC */ #define CP15_DCCSW(rr) p15, 0, rr, c7, c10, 2 /* Data cache clean by set/way */ -#if __ARM_ARCH == 6 -/* Only ARMv6: */ -#define CP15_CP15DSB p15, 0, r0, c7, c10, 4 /* DSB */ -#define CP15_CP15DMB p15, 0, r0, c7, c10, 5 /* DMB */ -#define CP15_CP15WFI p15, 0, r0, c7, c0, 4 /* WFI */ -#endif -#if __ARM_ARCH >= 7 /* From ARMv7: */ #define CP15_DCCMVAU(rr) p15, 0, rr, c7, c11, 1 /* Data cache clean by MVA PoU */ -#endif -#if __ARM_ARCH == 6 -/* Only ARMv6: */ -#define CP15_DCCIALL p15, 0, r0, c7, c14, 0 /* Data cache clean and invalidate all */ -#endif #define CP15_DCCIMVAC(rr) p15, 0, rr, c7, c14, 1 /* Data cache clean and invalidate by MVA PoC */ #define CP15_DCCISW(rr) p15, 0, rr, c7, c14, 2 /* Data cache clean and invalidate by set/way */ /* * CP15 C8 registers */ -#if __ARM_ARCH >= 7 && defined(SMP) +#if defined(SMP) /* From ARMv7: */ #define CP15_TLBIALLIS p15, 0, r0, c8, c3, 0 /* Invalidate entire unified TLB IS */ #define CP15_TLBIMVAIS(rr) p15, 0, rr, c8, c3, 1 /* Invalidate unified TLB by MVA IS */ @@ -232,11 +204,6 @@ /* * CP15 C9 registers */ -#if __ARM_ARCH == 6 && defined(CPU_ARM1176) -#define CP15_PMUSERENR(rr) p15, 0, rr, c15, c9, 0 /* Access Validation Control Register */ -#define CP15_PMCR(rr) p15, 0, rr, c15, c12, 0 /* Performance Monitor Control Register */ -#define CP15_PMCCNTR(rr) p15, 0, rr, c15, c12, 1 /* PM Cycle Count Register */ -#else #define CP15_L2CTLR(rr) p15, 1, rr, c9, c0, 2 /* L2 Control Register */ #define CP15_PMCR(rr) p15, 0, rr, c9, c12, 0 /* Performance Monitor Control Register */ #define CP15_PMCNTENSET(rr) p15, 0, rr, c9, c12, 1 /* PM Count Enable Set Register */ @@ -250,7 +217,6 @@ #define CP15_PMUSERENR(rr) p15, 0, rr, c9, c14, 0 /* PM User Enable Register */ #define CP15_PMINTENSET(rr) p15, 0, rr, c9, c14, 1 /* PM Interrupt Enable Set Register */ #define CP15_PMINTENCLR(rr) p15, 0, rr, c9, c14, 2 /* PM Interrupt Enable Clear Register */ -#endif /* * CP15 C10 registers diff --git a/lib/libc/include/aarch64-freebsd-none/arm/vmparam.h b/lib/libc/include/aarch64-freebsd-none/arm/vmparam.h index e5b6b491f701..92285fcfdc25 100644 --- a/lib/libc/include/aarch64-freebsd-none/arm/vmparam.h +++ b/lib/libc/include/aarch64-freebsd-none/arm/vmparam.h @@ -200,5 +200,6 @@ extern vm_offset_t vm_max_kernel_address; * Need a page dump array for minidump. */ #define MINIDUMP_PAGE_TRACKING 1 +#define MINIDUMP_STARTUP_PAGE_TRACKING 0 #endif /* _MACHINE_VMPARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-freebsd-none/fenv.h b/lib/libc/include/aarch64-freebsd-none/fenv.h index 089f228e668e..280ffa22a2b0 100644 --- a/lib/libc/include/aarch64-freebsd-none/fenv.h +++ b/lib/libc/include/aarch64-freebsd-none/fenv.h @@ -31,6 +31,7 @@ #ifndef _FENV_H_ #define _FENV_H_ +#include #include #ifndef __fenv_static diff --git a/lib/libc/include/aarch64-freebsd-none/float.h b/lib/libc/include/aarch64-freebsd-none/float.h index 2ac179777457..c6f1432f6226 100644 --- a/lib/libc/include/aarch64-freebsd-none/float.h +++ b/lib/libc/include/aarch64-freebsd-none/float.h @@ -25,8 +25,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)float.h 7.1 (Berkeley) 5/8/90 */ #ifdef __arm__ diff --git a/lib/libc/include/aarch64-freebsd-none/machine/_align.h b/lib/libc/include/aarch64-freebsd-none/machine/_align.h index 1fa6ddf1e4c1..b416b0198ab7 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/_align.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/_align.h @@ -25,8 +25,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)param.h 5.8 (Berkeley) 6/28/91 */ #ifdef __arm__ diff --git a/lib/libc/include/aarch64-freebsd-none/machine/_bus.h b/lib/libc/include/aarch64-freebsd-none/machine/_bus.h deleted file mode 100644 index 8e9a287dc2ee..000000000000 --- a/lib/libc/include/aarch64-freebsd-none/machine/_bus.h +++ /dev/null @@ -1,43 +0,0 @@ -/*- - * Copyright (c) 2005 M. Warner Losh - * - * 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, - * without modification, immediately at the beginning of the file. - * 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 _MACHINE__BUS_H_ -#define _MACHINE__BUS_H_ - -/* - * Addresses (in bus space). - */ -typedef u_long bus_addr_t; -typedef u_long bus_size_t; - -/* - * Access methods for bus space. - */ -typedef u_long bus_space_handle_t; -typedef struct bus_space *bus_space_tag_t; - -#endif /* !_MACHINE__BUS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-freebsd-none/machine/_limits.h b/lib/libc/include/aarch64-freebsd-none/machine/_limits.h index d8080f73d7b4..44fbd2c293fb 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/_limits.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/_limits.h @@ -22,8 +22,6 @@ * 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. - * - * @(#)limits.h 8.3 (Berkeley) 1/4/94 */ #ifdef __arm__ diff --git a/lib/libc/include/aarch64-freebsd-none/machine/_types.h b/lib/libc/include/aarch64-freebsd-none/machine/_types.h index 0b42e2cc2999..78f216342bf2 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/_types.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/_types.h @@ -26,9 +26,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * From: @(#)ansi.h 8.2 (Berkeley) 1/4/94 - * From: @(#)types.h 8.3 (Berkeley) 1/5/94 */ #ifdef __arm__ diff --git a/lib/libc/include/aarch64-freebsd-none/machine/armreg.h b/lib/libc/include/aarch64-freebsd-none/machine/armreg.h index 166b8912f906..7f51a632a40c 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/armreg.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/armreg.h @@ -36,29 +36,6 @@ #define INSN_SIZE 4 -#define MRS_MASK 0xfff00000 -#define MRS_VALUE 0xd5300000 -#define MRS_SPECIAL(insn) ((insn) & 0x000fffe0) -#define MRS_REGISTER(insn) ((insn) & 0x0000001f) -#define MRS_Op0_SHIFT 19 -#define MRS_Op0_MASK 0x00080000 -#define MRS_Op1_SHIFT 16 -#define MRS_Op1_MASK 0x00070000 -#define MRS_CRn_SHIFT 12 -#define MRS_CRn_MASK 0x0000f000 -#define MRS_CRm_SHIFT 8 -#define MRS_CRm_MASK 0x00000f00 -#define MRS_Op2_SHIFT 5 -#define MRS_Op2_MASK 0x000000e0 -#define MRS_Rt_SHIFT 0 -#define MRS_Rt_MASK 0x0000001f -#define __MRS_REG(op0, op1, crn, crm, op2) \ - (((op0) << MRS_Op0_SHIFT) | ((op1) << MRS_Op1_SHIFT) | \ - ((crn) << MRS_CRn_SHIFT) | ((crm) << MRS_CRm_SHIFT) | \ - ((op2) << MRS_Op2_SHIFT)) -#define MRS_REG(reg) \ - __MRS_REG(reg##_op0, reg##_op1, reg##_CRn, reg##_CRm, reg##_op2) - #define __MRS_REG_ALT_NAME(op0, op1, crn, crm, op2) \ S##op0##_##op1##_C##crn##_C##crm##_##op2 #define _MRS_REG_ALT_NAME(op0, op1, crn, crm, op2) \ @@ -231,8 +208,21 @@ #define CLIDR_CTYPE_ID 0x3 /* Split instruction and data */ #define CLIDR_CTYPE_UNIFIED 0x4 /* Unified */ +/* CNTKCTL_EL1 - Counter-timer Kernel Control Register */ +#define CNTKCTL_EL1_op0 3 +#define CNTKCTL_EL1_op1 0 +#define CNTKCTL_EL1_CRn 14 +#define CNTKCTL_EL1_CRm 1 +#define CNTKCTL_EL1_op2 0 + +/* CNTKCTL_EL12 - Counter-timer Kernel Control Register */ +#define CNTKCTL_EL12_op0 3 +#define CNTKCTL_EL12_op1 5 +#define CNTKCTL_EL12_CRn 14 +#define CNTKCTL_EL12_CRm 1 +#define CNTKCTL_EL12_op2 0 + /* CNTP_CTL_EL0 - Counter-timer Physical Timer Control register */ -#define CNTP_CTL_EL0 MRS_REG(CNTP_CTL_EL0) #define CNTP_CTL_EL0_op0 3 #define CNTP_CTL_EL0_op1 3 #define CNTP_CTL_EL0_CRn 14 @@ -243,7 +233,6 @@ #define CNTP_CTL_ISTATUS (1 << 2) /* CNTP_CVAL_EL0 - Counter-timer Physical Timer CompareValue register */ -#define CNTP_CVAL_EL0 MRS_REG(CNTP_CVAL_EL0) #define CNTP_CVAL_EL0_op0 3 #define CNTP_CVAL_EL0_op1 3 #define CNTP_CVAL_EL0_CRn 14 @@ -251,7 +240,6 @@ #define CNTP_CVAL_EL0_op2 2 /* CNTP_TVAL_EL0 - Counter-timer Physical Timer TimerValue register */ -#define CNTP_TVAL_EL0 MRS_REG(CNTP_TVAL_EL0) #define CNTP_TVAL_EL0_op0 3 #define CNTP_TVAL_EL0_op1 3 #define CNTP_TVAL_EL0_CRn 14 @@ -259,15 +247,42 @@ #define CNTP_TVAL_EL0_op2 0 /* CNTPCT_EL0 - Counter-timer Physical Count register */ -#define CNTPCT_EL0 MRS_REG(CNTPCT_EL0) +#define CNTPCT_EL0_ISS ISS_MSR_REG(CNTPCT_EL0) #define CNTPCT_EL0_op0 3 #define CNTPCT_EL0_op1 3 #define CNTPCT_EL0_CRn 14 #define CNTPCT_EL0_CRm 0 #define CNTPCT_EL0_op2 1 +/* CNTV_CTL_EL0 - Counter-timer Virtual Timer Control register */ +#define CNTV_CTL_EL0_op0 3 +#define CNTV_CTL_EL0_op1 3 +#define CNTV_CTL_EL0_CRn 14 +#define CNTV_CTL_EL0_CRm 3 +#define CNTV_CTL_EL0_op2 1 + +/* CNTV_CTL_EL02 - Counter-timer Virtual Timer Control register */ +#define CNTV_CTL_EL02_op0 3 +#define CNTV_CTL_EL02_op1 5 +#define CNTV_CTL_EL02_CRn 14 +#define CNTV_CTL_EL02_CRm 3 +#define CNTV_CTL_EL02_op2 1 + +/* CNTV_CVAL_EL0 - Counter-timer Virtual Timer CompareValue register */ +#define CNTV_CVAL_EL0_op0 3 +#define CNTV_CVAL_EL0_op1 3 +#define CNTV_CVAL_EL0_CRn 14 +#define CNTV_CVAL_EL0_CRm 3 +#define CNTV_CVAL_EL0_op2 2 + +/* CNTV_CVAL_EL02 - Counter-timer Virtual Timer CompareValue register */ +#define CNTV_CVAL_EL02_op0 3 +#define CNTV_CVAL_EL02_op1 5 +#define CNTV_CVAL_EL02_CRn 14 +#define CNTV_CVAL_EL02_CRm 3 +#define CNTV_CVAL_EL02_op2 2 + /* CONTEXTIDR_EL1 - Context ID register */ -#define CONTEXTIDR_EL1 MRS_REG(CONTEXTIDR_EL1) #define CONTEXTIDR_EL1_REG MRS_REG_ALT_NAME(CONTEXTIDR_EL1) #define CONTEXTIDR_EL1_op0 3 #define CONTEXTIDR_EL1_op1 0 @@ -315,36 +330,52 @@ #define CSSELR_InD 0x00000001 /* CTR_EL0 - Cache Type Register */ +#define CTR_EL0_REG MRS_REG_ALT_NAME(CTR_EL0) +#define CTR_EL0_ISS ISS_MSR_REG(CTR_EL0) +#define CTR_EL0_op0 3 +#define CTR_EL0_op1 3 +#define CTR_EL0_CRn 0 +#define CTR_EL0_CRm 0 +#define CTR_EL0_op2 1 #define CTR_RES1 (1 << 31) #define CTR_TminLine_SHIFT 32 #define CTR_TminLine_MASK (UL(0x3f) << CTR_TminLine_SHIFT) #define CTR_TminLine_VAL(reg) ((reg) & CTR_TminLine_MASK) #define CTR_DIC_SHIFT 29 +#define CTR_DIC_WIDTH 1 #define CTR_DIC_MASK (0x1 << CTR_DIC_SHIFT) #define CTR_DIC_VAL(reg) ((reg) & CTR_DIC_MASK) +#define CTR_DIC_NONE (0x0 << CTR_DIC_SHIFT) +#define CTR_DIC_IMPL (0x1 << CTR_DIC_SHIFT) #define CTR_IDC_SHIFT 28 +#define CTR_IDC_WIDTH 1 #define CTR_IDC_MASK (0x1 << CTR_IDC_SHIFT) #define CTR_IDC_VAL(reg) ((reg) & CTR_IDC_MASK) +#define CTR_IDC_NONE (0x0 << CTR_IDC_SHIFT) +#define CTR_IDC_IMPL (0x1 << CTR_IDC_SHIFT) #define CTR_CWG_SHIFT 24 +#define CTR_CWG_WIDTH 4 #define CTR_CWG_MASK (0xf << CTR_CWG_SHIFT) #define CTR_CWG_VAL(reg) ((reg) & CTR_CWG_MASK) #define CTR_CWG_SIZE(reg) (4 << (CTR_CWG_VAL(reg) >> CTR_CWG_SHIFT)) #define CTR_ERG_SHIFT 20 +#define CTR_ERG_WIDTH 4 #define CTR_ERG_MASK (0xf << CTR_ERG_SHIFT) #define CTR_ERG_VAL(reg) ((reg) & CTR_ERG_MASK) #define CTR_ERG_SIZE(reg) (4 << (CTR_ERG_VAL(reg) >> CTR_ERG_SHIFT)) #define CTR_DLINE_SHIFT 16 +#define CTR_DLINE_WIDTH 4 #define CTR_DLINE_MASK (0xf << CTR_DLINE_SHIFT) #define CTR_DLINE_VAL(reg) ((reg) & CTR_DLINE_MASK) #define CTR_DLINE_SIZE(reg) (4 << (CTR_DLINE_VAL(reg) >> CTR_DLINE_SHIFT)) #define CTR_L1IP_SHIFT 14 +#define CTR_L1IP_WIDTH 2 #define CTR_L1IP_MASK (0x3 << CTR_L1IP_SHIFT) #define CTR_L1IP_VAL(reg) ((reg) & CTR_L1IP_MASK) -#define CTR_L1IP_VPIPT (0 << CTR_L1IP_SHIFT) -#define CTR_L1IP_AIVIVT (1 << CTR_L1IP_SHIFT) #define CTR_L1IP_VIPT (2 << CTR_L1IP_SHIFT) #define CTR_L1IP_PIPT (3 << CTR_L1IP_SHIFT) #define CTR_ILINE_SHIFT 0 +#define CTR_ILINE_WIDTH 4 #define CTR_ILINE_MASK (0xf << CTR_ILINE_SHIFT) #define CTR_ILINE_VAL(reg) ((reg) & CTR_ILINE_MASK) #define CTR_ILINE_SIZE(reg) (4 << (CTR_ILINE_VAL(reg) >> CTR_ILINE_SHIFT)) @@ -363,7 +394,7 @@ #define DAIF_I (1 << 1) #define DAIF_F (1 << 0) #define DAIF_ALL (DAIF_D | DAIF_A | DAIF_I | DAIF_F) -#define DAIF_INTR (DAIF_I) /* All exceptions that pass */ +#define DAIF_INTR (DAIF_I | DAIF_F) /* All exceptions that pass */ /* through the intr framework */ /* DBGBCR_EL1 - Debug Breakpoint Control Registers */ @@ -435,7 +466,6 @@ #define DCZID_BS_SIZE(reg) (((reg) & DCZID_BS_MASK) >> DCZID_BS_SHIFT) /* DBGAUTHSTATUS_EL1 */ -#define DBGAUTHSTATUS_EL1 MRS_REG(DBGAUTHSTATUS_EL1) #define DBGAUTHSTATUS_EL1_op0 2 #define DBGAUTHSTATUS_EL1_op1 0 #define DBGAUTHSTATUS_EL1_CRn 7 @@ -443,7 +473,6 @@ #define DBGAUTHSTATUS_EL1_op2 6 /* DBGCLAIMCLR_EL1 */ -#define DBGCLAIMCLR_EL1 MRS_REG(DBGCLAIMCLR_EL1) #define DBGCLAIMCLR_EL1_op0 2 #define DBGCLAIMCLR_EL1_op1 0 #define DBGCLAIMCLR_EL1_CRn 7 @@ -451,7 +480,6 @@ #define DBGCLAIMCLR_EL1_op2 6 /* DBGCLAIMSET_EL1 */ -#define DBGCLAIMSET_EL1 MRS_REG(DBGCLAIMSET_EL1) #define DBGCLAIMSET_EL1_op0 2 #define DBGCLAIMSET_EL1_op1 0 #define DBGCLAIMSET_EL1_CRn 7 @@ -459,7 +487,6 @@ #define DBGCLAIMSET_EL1_op2 6 /* DBGPRCR_EL1 */ -#define DBGPRCR_EL1 MRS_REG(DBGPRCR_EL1) #define DBGPRCR_EL1_op0 2 #define DBGPRCR_EL1_op1 0 #define DBGPRCR_EL1_CRn 1 @@ -540,12 +567,14 @@ #define ISS_MSR_REG_MASK \ (ISS_MSR_OP0_MASK | ISS_MSR_OP2_MASK | ISS_MSR_OP1_MASK | \ ISS_MSR_CRn_MASK | ISS_MSR_CRm_MASK) +#define __ISS_MSR_REG(op0, op1, crn, crm, op2) \ + (((op0) << ISS_MSR_OP0_SHIFT) | \ + ((op1) << ISS_MSR_OP1_SHIFT) | \ + ((crn) << ISS_MSR_CRn_SHIFT) | \ + ((crm) << ISS_MSR_CRm_SHIFT) | \ + ((op2) << ISS_MSR_OP2_SHIFT)) #define ISS_MSR_REG(reg) \ - (((reg ## _op0) << ISS_MSR_OP0_SHIFT) | \ - ((reg ## _op1) << ISS_MSR_OP1_SHIFT) | \ - ((reg ## _CRn) << ISS_MSR_CRn_SHIFT) | \ - ((reg ## _CRm) << ISS_MSR_CRm_SHIFT) | \ - ((reg ## _op2) << ISS_MSR_OP2_SHIFT)) + __ISS_MSR_REG(reg##_op0, reg##_op1, reg##_CRn, reg##_CRm, reg##_op2) #define ISS_DATA_ISV_SHIFT 24 #define ISS_DATA_ISV (0x01 << ISS_DATA_ISV_SHIFT) @@ -667,7 +696,6 @@ #define ICC_PMR_EL1_PRIO_MASK (0xFFUL) /* ICC_SGI1R_EL1 */ -#define ICC_SGI1R_EL1 MRS_REG(ICC_SGI1R_EL1) #define ICC_SGI1R_EL1_op0 3 #define ICC_SGI1R_EL1_op1 0 #define ICC_SGI1R_EL1_CRn 12 @@ -697,8 +725,8 @@ #define ICC_SRE_EL1_SRE (1U << 0) /* ID_AA64AFR0_EL1 */ -#define ID_AA64AFR0_EL1 MRS_REG(ID_AA64AFR0_EL1) #define ID_AA64AFR0_EL1_REG MRS_REG_ALT_NAME(ID_AA64AFR0_EL1) +#define ID_AA64AFR0_EL1_ISS ISS_MSR_REG(ID_AA64AFR0_EL1) #define ID_AA64AFR0_EL1_op0 3 #define ID_AA64AFR0_EL1_op1 0 #define ID_AA64AFR0_EL1_CRn 0 @@ -706,8 +734,8 @@ #define ID_AA64AFR0_EL1_op2 4 /* ID_AA64AFR1_EL1 */ -#define ID_AA64AFR1_EL1 MRS_REG(ID_AA64AFR1_EL1) #define ID_AA64AFR1_EL1_REG MRS_REG_ALT_NAME(ID_AA64AFR1_EL1) +#define ID_AA64AFR1_EL1_ISS ISS_MSR_REG(ID_AA64AFR1_EL1) #define ID_AA64AFR1_EL1_op0 3 #define ID_AA64AFR1_EL1_op1 0 #define ID_AA64AFR1_EL1_CRn 0 @@ -715,14 +743,15 @@ #define ID_AA64AFR1_EL1_op2 5 /* ID_AA64DFR0_EL1 */ -#define ID_AA64DFR0_EL1 MRS_REG(ID_AA64DFR0_EL1) #define ID_AA64DFR0_EL1_REG MRS_REG_ALT_NAME(ID_AA64DFR0_EL1) +#define ID_AA64DFR0_EL1_ISS ISS_MSR_REG(ID_AA64DFR0_EL1) #define ID_AA64DFR0_EL1_op0 3 #define ID_AA64DFR0_EL1_op1 0 #define ID_AA64DFR0_EL1_CRn 0 #define ID_AA64DFR0_EL1_CRm 5 #define ID_AA64DFR0_EL1_op2 0 #define ID_AA64DFR0_DebugVer_SHIFT 0 +#define ID_AA64DFR0_DebugVer_WIDTH 4 #define ID_AA64DFR0_DebugVer_MASK (UL(0xf) << ID_AA64DFR0_DebugVer_SHIFT) #define ID_AA64DFR0_DebugVer_VAL(x) ((x) & ID_AA64DFR0_DebugVer_MASK) #define ID_AA64DFR0_DebugVer_8 (UL(0x6) << ID_AA64DFR0_DebugVer_SHIFT) @@ -730,12 +759,15 @@ #define ID_AA64DFR0_DebugVer_8_2 (UL(0x8) << ID_AA64DFR0_DebugVer_SHIFT) #define ID_AA64DFR0_DebugVer_8_4 (UL(0x9) << ID_AA64DFR0_DebugVer_SHIFT) #define ID_AA64DFR0_DebugVer_8_8 (UL(0xa) << ID_AA64DFR0_DebugVer_SHIFT) +#define ID_AA64DFR0_DebugVer_8_9 (UL(0xb) << ID_AA64DFR0_DebugVer_SHIFT) #define ID_AA64DFR0_TraceVer_SHIFT 4 +#define ID_AA64DFR0_TraceVer_WIDTH 4 #define ID_AA64DFR0_TraceVer_MASK (UL(0xf) << ID_AA64DFR0_TraceVer_SHIFT) #define ID_AA64DFR0_TraceVer_VAL(x) ((x) & ID_AA64DFR0_TraceVer_MASK) #define ID_AA64DFR0_TraceVer_NONE (UL(0x0) << ID_AA64DFR0_TraceVer_SHIFT) #define ID_AA64DFR0_TraceVer_IMPL (UL(0x1) << ID_AA64DFR0_TraceVer_SHIFT) #define ID_AA64DFR0_PMUVer_SHIFT 8 +#define ID_AA64DFR0_PMUVer_WIDTH 4 #define ID_AA64DFR0_PMUVer_MASK (UL(0xf) << ID_AA64DFR0_PMUVer_SHIFT) #define ID_AA64DFR0_PMUVer_VAL(x) ((x) & ID_AA64DFR0_PMUVer_MASK) #define ID_AA64DFR0_PMUVer_NONE (UL(0x0) << ID_AA64DFR0_PMUVer_SHIFT) @@ -745,25 +777,31 @@ #define ID_AA64DFR0_PMUVer_3_5 (UL(0x6) << ID_AA64DFR0_PMUVer_SHIFT) #define ID_AA64DFR0_PMUVer_3_7 (UL(0x7) << ID_AA64DFR0_PMUVer_SHIFT) #define ID_AA64DFR0_PMUVer_3_8 (UL(0x8) << ID_AA64DFR0_PMUVer_SHIFT) +#define ID_AA64DFR0_PMUVer_3_9 (UL(0x9) << ID_AA64DFR0_PMUVer_SHIFT) #define ID_AA64DFR0_PMUVer_IMPL (UL(0xf) << ID_AA64DFR0_PMUVer_SHIFT) #define ID_AA64DFR0_BRPs_SHIFT 12 +#define ID_AA64DFR0_BRPs_WIDTH 4 #define ID_AA64DFR0_BRPs_MASK (UL(0xf) << ID_AA64DFR0_BRPs_SHIFT) #define ID_AA64DFR0_BRPs_VAL(x) \ ((((x) >> ID_AA64DFR0_BRPs_SHIFT) & 0xf) + 1) #define ID_AA64DFR0_PMSS_SHIFT 16 +#define ID_AA64DFR0_PMSS_WIDTH 4 #define ID_AA64DFR0_PMSS_MASK (UL(0xf) << ID_AA64DFR0_PMSS_SHIFT) #define ID_AA64DFR0_PMSS_VAL(x) ((x) & ID_AA64DFR0_PMSS_MASK) #define ID_AA64DFR0_PMSS_NONE (UL(0x0) << ID_AA64DFR0_PMSS_SHIFT) #define ID_AA64DFR0_PMSS_IMPL (UL(0x1) << ID_AA64DFR0_PMSS_SHIFT) #define ID_AA64DFR0_WRPs_SHIFT 20 +#define ID_AA64DFR0_WRPs_WIDTH 4 #define ID_AA64DFR0_WRPs_MASK (UL(0xf) << ID_AA64DFR0_WRPs_SHIFT) #define ID_AA64DFR0_WRPs_VAL(x) \ ((((x) >> ID_AA64DFR0_WRPs_SHIFT) & 0xf) + 1) #define ID_AA64DFR0_CTX_CMPs_SHIFT 28 +#define ID_AA64DFR0_CTX_CMPs_WIDTH 4 #define ID_AA64DFR0_CTX_CMPs_MASK (UL(0xf) << ID_AA64DFR0_CTX_CMPs_SHIFT) #define ID_AA64DFR0_CTX_CMPs_VAL(x) \ ((((x) >> ID_AA64DFR0_CTX_CMPs_SHIFT) & 0xf) + 1) #define ID_AA64DFR0_PMSVer_SHIFT 32 +#define ID_AA64DFR0_PMSVer_WIDTH 4 #define ID_AA64DFR0_PMSVer_MASK (UL(0xf) << ID_AA64DFR0_PMSVer_SHIFT) #define ID_AA64DFR0_PMSVer_VAL(x) ((x) & ID_AA64DFR0_PMSVer_MASK) #define ID_AA64DFR0_PMSVer_NONE (UL(0x0) << ID_AA64DFR0_PMSVer_SHIFT) @@ -771,150 +809,192 @@ #define ID_AA64DFR0_PMSVer_SPE_1_1 (UL(0x2) << ID_AA64DFR0_PMSVer_SHIFT) #define ID_AA64DFR0_PMSVer_SPE_1_2 (UL(0x3) << ID_AA64DFR0_PMSVer_SHIFT) #define ID_AA64DFR0_PMSVer_SPE_1_3 (UL(0x4) << ID_AA64DFR0_PMSVer_SHIFT) +#define ID_AA64DFR0_PMSVer_SPE_1_4 (UL(0x5) << ID_AA64DFR0_PMSVer_SHIFT) #define ID_AA64DFR0_DoubleLock_SHIFT 36 +#define ID_AA64DFR0_DoubleLock_WIDTH 4 #define ID_AA64DFR0_DoubleLock_MASK (UL(0xf) << ID_AA64DFR0_DoubleLock_SHIFT) #define ID_AA64DFR0_DoubleLock_VAL(x) ((x) & ID_AA64DFR0_DoubleLock_MASK) #define ID_AA64DFR0_DoubleLock_IMPL (UL(0x0) << ID_AA64DFR0_DoubleLock_SHIFT) #define ID_AA64DFR0_DoubleLock_NONE (UL(0xf) << ID_AA64DFR0_DoubleLock_SHIFT) #define ID_AA64DFR0_TraceFilt_SHIFT 40 +#define ID_AA64DFR0_TraceFilt_WIDTH 4 #define ID_AA64DFR0_TraceFilt_MASK (UL(0xf) << ID_AA64DFR0_TraceFilt_SHIFT) #define ID_AA64DFR0_TraceFilt_VAL(x) ((x) & ID_AA64DFR0_TraceFilt_MASK) #define ID_AA64DFR0_TraceFilt_NONE (UL(0x0) << ID_AA64DFR0_TraceFilt_SHIFT) #define ID_AA64DFR0_TraceFilt_8_4 (UL(0x1) << ID_AA64DFR0_TraceFilt_SHIFT) #define ID_AA64DFR0_TraceBuffer_SHIFT 44 +#define ID_AA64DFR0_TraceBuffer_WIDTH 4 #define ID_AA64DFR0_TraceBuffer_MASK (UL(0xf) << ID_AA64DFR0_TraceBuffer_SHIFT) #define ID_AA64DFR0_TraceBuffer_VAL(x) ((x) & ID_AA64DFR0_TraceBuffer_MASK) #define ID_AA64DFR0_TraceBuffer_NONE (UL(0x0) << ID_AA64DFR0_TraceBuffer_SHIFT) #define ID_AA64DFR0_TraceBuffer_IMPL (UL(0x1) << ID_AA64DFR0_TraceBuffer_SHIFT) #define ID_AA64DFR0_MTPMU_SHIFT 48 +#define ID_AA64DFR0_MTPMU_WIDTH 4 #define ID_AA64DFR0_MTPMU_MASK (UL(0xf) << ID_AA64DFR0_MTPMU_SHIFT) #define ID_AA64DFR0_MTPMU_VAL(x) ((x) & ID_AA64DFR0_MTPMU_MASK) #define ID_AA64DFR0_MTPMU_NONE (UL(0x0) << ID_AA64DFR0_MTPMU_SHIFT) #define ID_AA64DFR0_MTPMU_IMPL (UL(0x1) << ID_AA64DFR0_MTPMU_SHIFT) #define ID_AA64DFR0_MTPMU_NONE_MT_RES0 (UL(0xf) << ID_AA64DFR0_MTPMU_SHIFT) #define ID_AA64DFR0_BRBE_SHIFT 52 +#define ID_AA64DFR0_BRBE_WIDTH 4 #define ID_AA64DFR0_BRBE_MASK (UL(0xf) << ID_AA64DFR0_BRBE_SHIFT) #define ID_AA64DFR0_BRBE_VAL(x) ((x) & ID_AA64DFR0_BRBE_MASK) #define ID_AA64DFR0_BRBE_NONE (UL(0x0) << ID_AA64DFR0_BRBE_SHIFT) #define ID_AA64DFR0_BRBE_IMPL (UL(0x1) << ID_AA64DFR0_BRBE_SHIFT) #define ID_AA64DFR0_BRBE_EL3 (UL(0x2) << ID_AA64DFR0_BRBE_SHIFT) #define ID_AA64DFR0_HPMN0_SHIFT 60 +#define ID_AA64DFR0_HPMN0_WIDTH 4 #define ID_AA64DFR0_HPMN0_MASK (UL(0xf) << ID_AA64DFR0_HPMN0_SHIFT) #define ID_AA64DFR0_HPMN0_VAL(x) ((x) & ID_AA64DFR0_HPMN0_MASK) #define ID_AA64DFR0_HPMN0_CONSTR (UL(0x0) << ID_AA64DFR0_HPMN0_SHIFT) #define ID_AA64DFR0_HPMN0_DEFINED (UL(0x1) << ID_AA64DFR0_HPMN0_SHIFT) /* ID_AA64DFR1_EL1 */ -#define ID_AA64DFR1_EL1 MRS_REG(ID_AA64DFR1_EL1) #define ID_AA64DFR1_EL1_REG MRS_REG_ALT_NAME(ID_AA64DFR1_EL1) +#define ID_AA64DFR1_EL1_ISS ISS_MSR_REG(ID_AA64DFR1_EL1) #define ID_AA64DFR1_EL1_op0 3 #define ID_AA64DFR1_EL1_op1 0 #define ID_AA64DFR1_EL1_CRn 0 #define ID_AA64DFR1_EL1_CRm 5 #define ID_AA64DFR1_EL1_op2 1 +#define ID_AA64DFR1_SPMU_SHIFT 32 +#define ID_AA64DFR1_SPMU_WIDTH 4 +#define ID_AA64DFR1_SPMU_MASK (UL(0xf) << ID_AA64DFR1_SPMU_SHIFT) +#define ID_AA64DFR1_SPMU_VAL(x) ((x) & ID_AA64DFR1_SPMU_MASK) +#define ID_AA64DFR1_SPMU_NONE (UL(0x0) << ID_AA64DFR1_SPMU_SHIFT) +#define ID_AA64DFR1_SPMU_IMPL (UL(0x1) << ID_AA64DFR1_SPMU_SHIFT) +#define ID_AA64DFR1_PMICNTR_SHIFT 36 +#define ID_AA64DFR1_PMICNTR_WIDTH 4 +#define ID_AA64DFR1_PMICNTR_MASK (UL(0xf) << ID_AA64DFR1_PMICNTR_SHIFT) +#define ID_AA64DFR1_PMICNTR_VAL(x) ((x) & ID_AA64DFR1_PMICNTR_MASK) +#define ID_AA64DFR1_PMICNTR_NONE (UL(0x0) << ID_AA64DFR1_PMICNTR_SHIFT) +#define ID_AA64DFR1_PMICNTR_IMPL (UL(0x1) << ID_AA64DFR1_PMICNTR_SHIFT) +#define ID_AA64DFR1_DPFZS_SHIFT 52 +#define ID_AA64DFR1_DPFZS_WIDTH 4 +#define ID_AA64DFR1_DPFZS_MASK (UL(0xf) << ID_AA64DFR1_DPFZS_SHIFT) +#define ID_AA64DFR1_DPFZS_VAL(x) ((x) & ID_AA64DFR1_DPFZS_MASK) +#define ID_AA64DFR1_DPFZS_NONE (UL(0x0) << ID_AA64DFR1_DPFZS_SHIFT) +#define ID_AA64DFR1_DPFZS_IMPL (UL(0x1) << ID_AA64DFR1_DPFZS_SHIFT) /* ID_AA64ISAR0_EL1 */ -#define ID_AA64ISAR0_EL1 MRS_REG(ID_AA64ISAR0_EL1) #define ID_AA64ISAR0_EL1_REG MRS_REG_ALT_NAME(ID_AA64ISAR0_EL1) +#define ID_AA64ISAR0_EL1_ISS ISS_MSR_REG(ID_AA64ISAR0_EL1) #define ID_AA64ISAR0_EL1_op0 3 #define ID_AA64ISAR0_EL1_op1 0 #define ID_AA64ISAR0_EL1_CRn 0 #define ID_AA64ISAR0_EL1_CRm 6 #define ID_AA64ISAR0_EL1_op2 0 #define ID_AA64ISAR0_AES_SHIFT 4 +#define ID_AA64ISAR0_AES_WIDTH 4 #define ID_AA64ISAR0_AES_MASK (UL(0xf) << ID_AA64ISAR0_AES_SHIFT) #define ID_AA64ISAR0_AES_VAL(x) ((x) & ID_AA64ISAR0_AES_MASK) #define ID_AA64ISAR0_AES_NONE (UL(0x0) << ID_AA64ISAR0_AES_SHIFT) #define ID_AA64ISAR0_AES_BASE (UL(0x1) << ID_AA64ISAR0_AES_SHIFT) #define ID_AA64ISAR0_AES_PMULL (UL(0x2) << ID_AA64ISAR0_AES_SHIFT) #define ID_AA64ISAR0_SHA1_SHIFT 8 +#define ID_AA64ISAR0_SHA1_WIDTH 4 #define ID_AA64ISAR0_SHA1_MASK (UL(0xf) << ID_AA64ISAR0_SHA1_SHIFT) #define ID_AA64ISAR0_SHA1_VAL(x) ((x) & ID_AA64ISAR0_SHA1_MASK) #define ID_AA64ISAR0_SHA1_NONE (UL(0x0) << ID_AA64ISAR0_SHA1_SHIFT) #define ID_AA64ISAR0_SHA1_BASE (UL(0x1) << ID_AA64ISAR0_SHA1_SHIFT) #define ID_AA64ISAR0_SHA2_SHIFT 12 +#define ID_AA64ISAR0_SHA2_WIDTH 4 #define ID_AA64ISAR0_SHA2_MASK (UL(0xf) << ID_AA64ISAR0_SHA2_SHIFT) #define ID_AA64ISAR0_SHA2_VAL(x) ((x) & ID_AA64ISAR0_SHA2_MASK) #define ID_AA64ISAR0_SHA2_NONE (UL(0x0) << ID_AA64ISAR0_SHA2_SHIFT) #define ID_AA64ISAR0_SHA2_BASE (UL(0x1) << ID_AA64ISAR0_SHA2_SHIFT) #define ID_AA64ISAR0_SHA2_512 (UL(0x2) << ID_AA64ISAR0_SHA2_SHIFT) #define ID_AA64ISAR0_CRC32_SHIFT 16 +#define ID_AA64ISAR0_CRC32_WIDTH 4 #define ID_AA64ISAR0_CRC32_MASK (UL(0xf) << ID_AA64ISAR0_CRC32_SHIFT) #define ID_AA64ISAR0_CRC32_VAL(x) ((x) & ID_AA64ISAR0_CRC32_MASK) #define ID_AA64ISAR0_CRC32_NONE (UL(0x0) << ID_AA64ISAR0_CRC32_SHIFT) #define ID_AA64ISAR0_CRC32_BASE (UL(0x1) << ID_AA64ISAR0_CRC32_SHIFT) #define ID_AA64ISAR0_Atomic_SHIFT 20 +#define ID_AA64ISAR0_Atomic_WIDTH 4 #define ID_AA64ISAR0_Atomic_MASK (UL(0xf) << ID_AA64ISAR0_Atomic_SHIFT) #define ID_AA64ISAR0_Atomic_VAL(x) ((x) & ID_AA64ISAR0_Atomic_MASK) #define ID_AA64ISAR0_Atomic_NONE (UL(0x0) << ID_AA64ISAR0_Atomic_SHIFT) #define ID_AA64ISAR0_Atomic_IMPL (UL(0x2) << ID_AA64ISAR0_Atomic_SHIFT) #define ID_AA64ISAR0_TME_SHIFT 24 +#define ID_AA64ISAR0_TME_WIDTH 4 #define ID_AA64ISAR0_TME_MASK (UL(0xf) << ID_AA64ISAR0_TME_SHIFT) #define ID_AA64ISAR0_TME_NONE (UL(0x0) << ID_AA64ISAR0_TME_SHIFT) #define ID_AA64ISAR0_TME_IMPL (UL(0x1) << ID_AA64ISAR0_TME_SHIFT) #define ID_AA64ISAR0_RDM_SHIFT 28 +#define ID_AA64ISAR0_RDM_WIDTH 4 #define ID_AA64ISAR0_RDM_MASK (UL(0xf) << ID_AA64ISAR0_RDM_SHIFT) #define ID_AA64ISAR0_RDM_VAL(x) ((x) & ID_AA64ISAR0_RDM_MASK) #define ID_AA64ISAR0_RDM_NONE (UL(0x0) << ID_AA64ISAR0_RDM_SHIFT) #define ID_AA64ISAR0_RDM_IMPL (UL(0x1) << ID_AA64ISAR0_RDM_SHIFT) #define ID_AA64ISAR0_SHA3_SHIFT 32 +#define ID_AA64ISAR0_SHA3_WIDTH 4 #define ID_AA64ISAR0_SHA3_MASK (UL(0xf) << ID_AA64ISAR0_SHA3_SHIFT) #define ID_AA64ISAR0_SHA3_VAL(x) ((x) & ID_AA64ISAR0_SHA3_MASK) #define ID_AA64ISAR0_SHA3_NONE (UL(0x0) << ID_AA64ISAR0_SHA3_SHIFT) #define ID_AA64ISAR0_SHA3_IMPL (UL(0x1) << ID_AA64ISAR0_SHA3_SHIFT) #define ID_AA64ISAR0_SM3_SHIFT 36 +#define ID_AA64ISAR0_SM3_WIDTH 4 #define ID_AA64ISAR0_SM3_MASK (UL(0xf) << ID_AA64ISAR0_SM3_SHIFT) #define ID_AA64ISAR0_SM3_VAL(x) ((x) & ID_AA64ISAR0_SM3_MASK) #define ID_AA64ISAR0_SM3_NONE (UL(0x0) << ID_AA64ISAR0_SM3_SHIFT) #define ID_AA64ISAR0_SM3_IMPL (UL(0x1) << ID_AA64ISAR0_SM3_SHIFT) #define ID_AA64ISAR0_SM4_SHIFT 40 +#define ID_AA64ISAR0_SM4_WIDTH 4 #define ID_AA64ISAR0_SM4_MASK (UL(0xf) << ID_AA64ISAR0_SM4_SHIFT) #define ID_AA64ISAR0_SM4_VAL(x) ((x) & ID_AA64ISAR0_SM4_MASK) #define ID_AA64ISAR0_SM4_NONE (UL(0x0) << ID_AA64ISAR0_SM4_SHIFT) #define ID_AA64ISAR0_SM4_IMPL (UL(0x1) << ID_AA64ISAR0_SM4_SHIFT) #define ID_AA64ISAR0_DP_SHIFT 44 +#define ID_AA64ISAR0_DP_WIDTH 4 #define ID_AA64ISAR0_DP_MASK (UL(0xf) << ID_AA64ISAR0_DP_SHIFT) #define ID_AA64ISAR0_DP_VAL(x) ((x) & ID_AA64ISAR0_DP_MASK) #define ID_AA64ISAR0_DP_NONE (UL(0x0) << ID_AA64ISAR0_DP_SHIFT) #define ID_AA64ISAR0_DP_IMPL (UL(0x1) << ID_AA64ISAR0_DP_SHIFT) #define ID_AA64ISAR0_FHM_SHIFT 48 +#define ID_AA64ISAR0_FHM_WIDTH 4 #define ID_AA64ISAR0_FHM_MASK (UL(0xf) << ID_AA64ISAR0_FHM_SHIFT) #define ID_AA64ISAR0_FHM_VAL(x) ((x) & ID_AA64ISAR0_FHM_MASK) #define ID_AA64ISAR0_FHM_NONE (UL(0x0) << ID_AA64ISAR0_FHM_SHIFT) #define ID_AA64ISAR0_FHM_IMPL (UL(0x1) << ID_AA64ISAR0_FHM_SHIFT) #define ID_AA64ISAR0_TS_SHIFT 52 +#define ID_AA64ISAR0_TS_WIDTH 4 #define ID_AA64ISAR0_TS_MASK (UL(0xf) << ID_AA64ISAR0_TS_SHIFT) #define ID_AA64ISAR0_TS_VAL(x) ((x) & ID_AA64ISAR0_TS_MASK) #define ID_AA64ISAR0_TS_NONE (UL(0x0) << ID_AA64ISAR0_TS_SHIFT) #define ID_AA64ISAR0_TS_CondM_8_4 (UL(0x1) << ID_AA64ISAR0_TS_SHIFT) #define ID_AA64ISAR0_TS_CondM_8_5 (UL(0x2) << ID_AA64ISAR0_TS_SHIFT) #define ID_AA64ISAR0_TLB_SHIFT 56 +#define ID_AA64ISAR0_TLB_WIDTH 4 #define ID_AA64ISAR0_TLB_MASK (UL(0xf) << ID_AA64ISAR0_TLB_SHIFT) #define ID_AA64ISAR0_TLB_VAL(x) ((x) & ID_AA64ISAR0_TLB_MASK) #define ID_AA64ISAR0_TLB_NONE (UL(0x0) << ID_AA64ISAR0_TLB_SHIFT) #define ID_AA64ISAR0_TLB_TLBIOS (UL(0x1) << ID_AA64ISAR0_TLB_SHIFT) #define ID_AA64ISAR0_TLB_TLBIOSR (UL(0x2) << ID_AA64ISAR0_TLB_SHIFT) #define ID_AA64ISAR0_RNDR_SHIFT 60 +#define ID_AA64ISAR0_RNDR_WIDTH 4 #define ID_AA64ISAR0_RNDR_MASK (UL(0xf) << ID_AA64ISAR0_RNDR_SHIFT) #define ID_AA64ISAR0_RNDR_VAL(x) ((x) & ID_AA64ISAR0_RNDR_MASK) #define ID_AA64ISAR0_RNDR_NONE (UL(0x0) << ID_AA64ISAR0_RNDR_SHIFT) #define ID_AA64ISAR0_RNDR_IMPL (UL(0x1) << ID_AA64ISAR0_RNDR_SHIFT) /* ID_AA64ISAR1_EL1 */ -#define ID_AA64ISAR1_EL1 MRS_REG(ID_AA64ISAR1_EL1) #define ID_AA64ISAR1_EL1_REG MRS_REG_ALT_NAME(ID_AA64ISAR1_EL1) +#define ID_AA64ISAR1_EL1_ISS ISS_MSR_REG(ID_AA64ISAR1_EL1) #define ID_AA64ISAR1_EL1_op0 3 #define ID_AA64ISAR1_EL1_op1 0 #define ID_AA64ISAR1_EL1_CRn 0 #define ID_AA64ISAR1_EL1_CRm 6 #define ID_AA64ISAR1_EL1_op2 1 #define ID_AA64ISAR1_DPB_SHIFT 0 +#define ID_AA64ISAR1_DPB_WIDTH 4 #define ID_AA64ISAR1_DPB_MASK (UL(0xf) << ID_AA64ISAR1_DPB_SHIFT) #define ID_AA64ISAR1_DPB_VAL(x) ((x) & ID_AA64ISAR1_DPB_MASK) #define ID_AA64ISAR1_DPB_NONE (UL(0x0) << ID_AA64ISAR1_DPB_SHIFT) #define ID_AA64ISAR1_DPB_DCCVAP (UL(0x1) << ID_AA64ISAR1_DPB_SHIFT) #define ID_AA64ISAR1_DPB_DCCVADP (UL(0x2) << ID_AA64ISAR1_DPB_SHIFT) #define ID_AA64ISAR1_APA_SHIFT 4 +#define ID_AA64ISAR1_APA_WIDTH 4 #define ID_AA64ISAR1_APA_MASK (UL(0xf) << ID_AA64ISAR1_APA_SHIFT) #define ID_AA64ISAR1_APA_VAL(x) ((x) & ID_AA64ISAR1_APA_MASK) #define ID_AA64ISAR1_APA_NONE (UL(0x0) << ID_AA64ISAR1_APA_SHIFT) @@ -924,6 +1004,7 @@ #define ID_AA64ISAR1_APA_FPAC (UL(0x4) << ID_AA64ISAR1_APA_SHIFT) #define ID_AA64ISAR1_APA_FPAC_COMBINED (UL(0x5) << ID_AA64ISAR1_APA_SHIFT) #define ID_AA64ISAR1_API_SHIFT 8 +#define ID_AA64ISAR1_API_WIDTH 4 #define ID_AA64ISAR1_API_MASK (UL(0xf) << ID_AA64ISAR1_API_SHIFT) #define ID_AA64ISAR1_API_VAL(x) ((x) & ID_AA64ISAR1_API_MASK) #define ID_AA64ISAR1_API_NONE (UL(0x0) << ID_AA64ISAR1_API_SHIFT) @@ -933,68 +1014,82 @@ #define ID_AA64ISAR1_API_FPAC (UL(0x4) << ID_AA64ISAR1_API_SHIFT) #define ID_AA64ISAR1_API_FPAC_COMBINED (UL(0x5) << ID_AA64ISAR1_API_SHIFT) #define ID_AA64ISAR1_JSCVT_SHIFT 12 +#define ID_AA64ISAR1_JSCVT_WIDTH 4 #define ID_AA64ISAR1_JSCVT_MASK (UL(0xf) << ID_AA64ISAR1_JSCVT_SHIFT) #define ID_AA64ISAR1_JSCVT_VAL(x) ((x) & ID_AA64ISAR1_JSCVT_MASK) #define ID_AA64ISAR1_JSCVT_NONE (UL(0x0) << ID_AA64ISAR1_JSCVT_SHIFT) #define ID_AA64ISAR1_JSCVT_IMPL (UL(0x1) << ID_AA64ISAR1_JSCVT_SHIFT) #define ID_AA64ISAR1_FCMA_SHIFT 16 +#define ID_AA64ISAR1_FCMA_WIDTH 4 #define ID_AA64ISAR1_FCMA_MASK (UL(0xf) << ID_AA64ISAR1_FCMA_SHIFT) #define ID_AA64ISAR1_FCMA_VAL(x) ((x) & ID_AA64ISAR1_FCMA_MASK) #define ID_AA64ISAR1_FCMA_NONE (UL(0x0) << ID_AA64ISAR1_FCMA_SHIFT) #define ID_AA64ISAR1_FCMA_IMPL (UL(0x1) << ID_AA64ISAR1_FCMA_SHIFT) #define ID_AA64ISAR1_LRCPC_SHIFT 20 +#define ID_AA64ISAR1_LRCPC_WIDTH 4 #define ID_AA64ISAR1_LRCPC_MASK (UL(0xf) << ID_AA64ISAR1_LRCPC_SHIFT) #define ID_AA64ISAR1_LRCPC_VAL(x) ((x) & ID_AA64ISAR1_LRCPC_MASK) #define ID_AA64ISAR1_LRCPC_NONE (UL(0x0) << ID_AA64ISAR1_LRCPC_SHIFT) #define ID_AA64ISAR1_LRCPC_RCPC_8_3 (UL(0x1) << ID_AA64ISAR1_LRCPC_SHIFT) #define ID_AA64ISAR1_LRCPC_RCPC_8_4 (UL(0x2) << ID_AA64ISAR1_LRCPC_SHIFT) #define ID_AA64ISAR1_GPA_SHIFT 24 +#define ID_AA64ISAR1_GPA_WIDTH 4 #define ID_AA64ISAR1_GPA_MASK (UL(0xf) << ID_AA64ISAR1_GPA_SHIFT) #define ID_AA64ISAR1_GPA_VAL(x) ((x) & ID_AA64ISAR1_GPA_MASK) #define ID_AA64ISAR1_GPA_NONE (UL(0x0) << ID_AA64ISAR1_GPA_SHIFT) #define ID_AA64ISAR1_GPA_IMPL (UL(0x1) << ID_AA64ISAR1_GPA_SHIFT) #define ID_AA64ISAR1_GPI_SHIFT 28 +#define ID_AA64ISAR1_GPI_WIDTH 4 #define ID_AA64ISAR1_GPI_MASK (UL(0xf) << ID_AA64ISAR1_GPI_SHIFT) #define ID_AA64ISAR1_GPI_VAL(x) ((x) & ID_AA64ISAR1_GPI_MASK) #define ID_AA64ISAR1_GPI_NONE (UL(0x0) << ID_AA64ISAR1_GPI_SHIFT) #define ID_AA64ISAR1_GPI_IMPL (UL(0x1) << ID_AA64ISAR1_GPI_SHIFT) #define ID_AA64ISAR1_FRINTTS_SHIFT 32 +#define ID_AA64ISAR1_FRINTTS_WIDTH 4 #define ID_AA64ISAR1_FRINTTS_MASK (UL(0xf) << ID_AA64ISAR1_FRINTTS_SHIFT) #define ID_AA64ISAR1_FRINTTS_VAL(x) ((x) & ID_AA64ISAR1_FRINTTS_MASK) #define ID_AA64ISAR1_FRINTTS_NONE (UL(0x0) << ID_AA64ISAR1_FRINTTS_SHIFT) #define ID_AA64ISAR1_FRINTTS_IMPL (UL(0x1) << ID_AA64ISAR1_FRINTTS_SHIFT) #define ID_AA64ISAR1_SB_SHIFT 36 +#define ID_AA64ISAR1_SB_WIDTH 4 #define ID_AA64ISAR1_SB_MASK (UL(0xf) << ID_AA64ISAR1_SB_SHIFT) #define ID_AA64ISAR1_SB_VAL(x) ((x) & ID_AA64ISAR1_SB_MASK) #define ID_AA64ISAR1_SB_NONE (UL(0x0) << ID_AA64ISAR1_SB_SHIFT) #define ID_AA64ISAR1_SB_IMPL (UL(0x1) << ID_AA64ISAR1_SB_SHIFT) #define ID_AA64ISAR1_SPECRES_SHIFT 40 +#define ID_AA64ISAR1_SPECRES_WIDTH 4 #define ID_AA64ISAR1_SPECRES_MASK (UL(0xf) << ID_AA64ISAR1_SPECRES_SHIFT) #define ID_AA64ISAR1_SPECRES_VAL(x) ((x) & ID_AA64ISAR1_SPECRES_MASK) #define ID_AA64ISAR1_SPECRES_NONE (UL(0x0) << ID_AA64ISAR1_SPECRES_SHIFT) -#define ID_AA64ISAR1_SPECRES_IMPL (UL(0x1) << ID_AA64ISAR1_SPECRES_SHIFT) +#define ID_AA64ISAR1_SPECRES_8_5 (UL(0x1) << ID_AA64ISAR1_SPECRES_SHIFT) +#define ID_AA64ISAR1_SPECRES_8_9 (UL(0x2) << ID_AA64ISAR1_SPECRES_SHIFT) #define ID_AA64ISAR1_BF16_SHIFT 44 +#define ID_AA64ISAR1_BF16_WIDTH 4 #define ID_AA64ISAR1_BF16_MASK (UL(0xf) << ID_AA64ISAR1_BF16_SHIFT) #define ID_AA64ISAR1_BF16_VAL(x) ((x) & ID_AA64ISAR1_BF16_MASK) #define ID_AA64ISAR1_BF16_NONE (UL(0x0) << ID_AA64ISAR1_BF16_SHIFT) #define ID_AA64ISAR1_BF16_IMPL (UL(0x1) << ID_AA64ISAR1_BF16_SHIFT) #define ID_AA64ISAR1_BF16_EBF (UL(0x2) << ID_AA64ISAR1_BF16_SHIFT) #define ID_AA64ISAR1_DGH_SHIFT 48 +#define ID_AA64ISAR1_DGH_WIDTH 4 #define ID_AA64ISAR1_DGH_MASK (UL(0xf) << ID_AA64ISAR1_DGH_SHIFT) #define ID_AA64ISAR1_DGH_VAL(x) ((x) & ID_AA64ISAR1_DGH_MASK) #define ID_AA64ISAR1_DGH_NONE (UL(0x0) << ID_AA64ISAR1_DGH_SHIFT) #define ID_AA64ISAR1_DGH_IMPL (UL(0x1) << ID_AA64ISAR1_DGH_SHIFT) #define ID_AA64ISAR1_I8MM_SHIFT 52 +#define ID_AA64ISAR1_I8MM_WIDTH 4 #define ID_AA64ISAR1_I8MM_MASK (UL(0xf) << ID_AA64ISAR1_I8MM_SHIFT) #define ID_AA64ISAR1_I8MM_VAL(x) ((x) & ID_AA64ISAR1_I8MM_MASK) #define ID_AA64ISAR1_I8MM_NONE (UL(0x0) << ID_AA64ISAR1_I8MM_SHIFT) #define ID_AA64ISAR1_I8MM_IMPL (UL(0x1) << ID_AA64ISAR1_I8MM_SHIFT) #define ID_AA64ISAR1_XS_SHIFT 56 +#define ID_AA64ISAR1_XS_WIDTH 4 #define ID_AA64ISAR1_XS_MASK (UL(0xf) << ID_AA64ISAR1_XS_SHIFT) #define ID_AA64ISAR1_XS_VAL(x) ((x) & ID_AA64ISAR1_XS_MASK) #define ID_AA64ISAR1_XS_NONE (UL(0x0) << ID_AA64ISAR1_XS_SHIFT) #define ID_AA64ISAR1_XS_IMPL (UL(0x1) << ID_AA64ISAR1_XS_SHIFT) #define ID_AA64ISAR1_LS64_SHIFT 60 +#define ID_AA64ISAR1_LS64_WIDTH 4 #define ID_AA64ISAR1_LS64_MASK (UL(0xf) << ID_AA64ISAR1_LS64_SHIFT) #define ID_AA64ISAR1_LS64_VAL(x) ((x) & ID_AA64ISAR1_LS64_MASK) #define ID_AA64ISAR1_LS64_NONE (UL(0x0) << ID_AA64ISAR1_LS64_SHIFT) @@ -1003,29 +1098,33 @@ #define ID_AA64ISAR1_LS64_ACCDATA (UL(0x3) << ID_AA64ISAR1_LS64_SHIFT) /* ID_AA64ISAR2_EL1 */ -#define ID_AA64ISAR2_EL1 MRS_REG(ID_AA64ISAR2_EL1) #define ID_AA64ISAR2_EL1_REG MRS_REG_ALT_NAME(ID_AA64ISAR2_EL1) +#define ID_AA64ISAR2_EL1_ISS ISS_MSR_REG(ID_AA64ISAR2_EL1) #define ID_AA64ISAR2_EL1_op0 3 #define ID_AA64ISAR2_EL1_op1 0 #define ID_AA64ISAR2_EL1_CRn 0 #define ID_AA64ISAR2_EL1_CRm 6 #define ID_AA64ISAR2_EL1_op2 2 #define ID_AA64ISAR2_WFxT_SHIFT 0 +#define ID_AA64ISAR2_WFxT_WIDTH 4 #define ID_AA64ISAR2_WFxT_MASK (UL(0xf) << ID_AA64ISAR2_WFxT_SHIFT) #define ID_AA64ISAR2_WFxT_VAL(x) ((x) & ID_AA64ISAR2_WFxT_MASK) #define ID_AA64ISAR2_WFxT_NONE (UL(0x0) << ID_AA64ISAR2_WFxT_SHIFT) -#define ID_AA64ISAR2_WFxT_IMPL (UL(0x1) << ID_AA64ISAR2_WFxT_SHIFT) +#define ID_AA64ISAR2_WFxT_IMPL (UL(0x2) << ID_AA64ISAR2_WFxT_SHIFT) #define ID_AA64ISAR2_RPRES_SHIFT 4 +#define ID_AA64ISAR2_RPRES_WIDTH 4 #define ID_AA64ISAR2_RPRES_MASK (UL(0xf) << ID_AA64ISAR2_RPRES_SHIFT) #define ID_AA64ISAR2_RPRES_VAL(x) ((x) & ID_AA64ISAR2_RPRES_MASK) #define ID_AA64ISAR2_RPRES_NONE (UL(0x0) << ID_AA64ISAR2_RPRES_SHIFT) #define ID_AA64ISAR2_RPRES_IMPL (UL(0x1) << ID_AA64ISAR2_RPRES_SHIFT) #define ID_AA64ISAR2_GPA3_SHIFT 8 +#define ID_AA64ISAR2_GPA3_WIDTH 4 #define ID_AA64ISAR2_GPA3_MASK (UL(0xf) << ID_AA64ISAR2_GPA3_SHIFT) #define ID_AA64ISAR2_GPA3_VAL(x) ((x) & ID_AA64ISAR2_GPA3_MASK) #define ID_AA64ISAR2_GPA3_NONE (UL(0x0) << ID_AA64ISAR2_GPA3_SHIFT) #define ID_AA64ISAR2_GPA3_IMPL (UL(0x1) << ID_AA64ISAR2_GPA3_SHIFT) #define ID_AA64ISAR2_APA3_SHIFT 12 +#define ID_AA64ISAR2_APA3_WIDTH 4 #define ID_AA64ISAR2_APA3_MASK (UL(0xf) << ID_AA64ISAR2_APA3_SHIFT) #define ID_AA64ISAR2_APA3_VAL(x) ((x) & ID_AA64ISAR2_APA3_MASK) #define ID_AA64ISAR2_APA3_NONE (UL(0x0) << ID_AA64ISAR2_APA3_SHIFT) @@ -1035,30 +1134,64 @@ #define ID_AA64ISAR2_APA3_FPAC (UL(0x4) << ID_AA64ISAR2_APA3_SHIFT) #define ID_AA64ISAR2_APA3_FPAC_COMBINED (UL(0x5) << ID_AA64ISAR2_APA3_SHIFT) #define ID_AA64ISAR2_MOPS_SHIFT 16 +#define ID_AA64ISAR2_MOPS_WIDTH 4 #define ID_AA64ISAR2_MOPS_MASK (UL(0xf) << ID_AA64ISAR2_MOPS_SHIFT) #define ID_AA64ISAR2_MOPS_VAL(x) ((x) & ID_AA64ISAR2_MOPS_MASK) #define ID_AA64ISAR2_MOPS_NONE (UL(0x0) << ID_AA64ISAR2_MOPS_SHIFT) #define ID_AA64ISAR2_MOPS_IMPL (UL(0x1) << ID_AA64ISAR2_MOPS_SHIFT) #define ID_AA64ISAR2_BC_SHIFT 20 +#define ID_AA64ISAR2_BC_WIDTH 4 #define ID_AA64ISAR2_BC_MASK (UL(0xf) << ID_AA64ISAR2_BC_SHIFT) #define ID_AA64ISAR2_BC_VAL(x) ((x) & ID_AA64ISAR2_BC_MASK) #define ID_AA64ISAR2_BC_NONE (UL(0x0) << ID_AA64ISAR2_BC_SHIFT) #define ID_AA64ISAR2_BC_IMPL (UL(0x1) << ID_AA64ISAR2_BC_SHIFT) -#define ID_AA64ISAR2_PAC_frac_SHIFT 28 +#define ID_AA64ISAR2_PAC_frac_SHIFT 24 +#define ID_AA64ISAR2_PAC_frac_WIDTH 4 #define ID_AA64ISAR2_PAC_frac_MASK (UL(0xf) << ID_AA64ISAR2_PAC_frac_SHIFT) #define ID_AA64ISAR2_PAC_frac_VAL(x) ((x) & ID_AA64ISAR2_PAC_frac_MASK) #define ID_AA64ISAR2_PAC_frac_NONE (UL(0x0) << ID_AA64ISAR2_PAC_frac_SHIFT) #define ID_AA64ISAR2_PAC_frac_IMPL (UL(0x1) << ID_AA64ISAR2_PAC_frac_SHIFT) +#define ID_AA64ISAR2_CLRBHB_SHIFT 28 +#define ID_AA64ISAR2_CLRBHB_WIDTH 4 +#define ID_AA64ISAR2_CLRBHB_MASK (UL(0xf) << ID_AA64ISAR2_CLRBHB_SHIFT) +#define ID_AA64ISAR2_CLRBHB_VAL(x) ((x) & ID_AA64ISAR2_CLRBHB_MASK) +#define ID_AA64ISAR2_CLRBHB_NONE (UL(0x0) << ID_AA64ISAR2_CLRBHB_SHIFT) +#define ID_AA64ISAR2_CLRBHB_IMPL (UL(0x1) << ID_AA64ISAR2_CLRBHB_SHIFT) +#define ID_AA64ISAR2_PRFMSLC_SHIFT 40 +#define ID_AA64ISAR2_PRFMSLC_WIDTH 4 +#define ID_AA64ISAR2_PRFMSLC_MASK (UL(0xf) << ID_AA64ISAR2_PRFMSLC_SHIFT) +#define ID_AA64ISAR2_PRFMSLC_VAL(x) ((x) & ID_AA64ISAR2_PRFMSLC_MASK) +#define ID_AA64ISAR2_PRFMSLC_NONE (UL(0x0) << ID_AA64ISAR2_PRFMSLC_SHIFT) +#define ID_AA64ISAR2_PRFMSLC_IMPL (UL(0x1) << ID_AA64ISAR2_PRFMSLC_SHIFT) +#define ID_AA64ISAR2_RPRFM_SHIFT 48 +#define ID_AA64ISAR2_RPRFM_WIDTH 4 +#define ID_AA64ISAR2_RPRFM_MASK (UL(0xf) << ID_AA64ISAR2_RPRFM_SHIFT) +#define ID_AA64ISAR2_RPRFM_VAL(x) ((x) & ID_AA64ISAR2_RPRFM_MASK) +#define ID_AA64ISAR2_RPRFM_NONE (UL(0x0) << ID_AA64ISAR2_RPRFM_SHIFT) +#define ID_AA64ISAR2_RPRFM_IMPL (UL(0x1) << ID_AA64ISAR2_RPRFM_SHIFT) +#define ID_AA64ISAR2_CSSC_SHIFT 52 +#define ID_AA64ISAR2_CSSC_WIDTH 4 +#define ID_AA64ISAR2_CSSC_MASK (UL(0xf) << ID_AA64ISAR2_CSSC_SHIFT) +#define ID_AA64ISAR2_CSSC_VAL(x) ((x) & ID_AA64ISAR2_CSSC_MASK) +#define ID_AA64ISAR2_CSSC_NONE (UL(0x0) << ID_AA64ISAR2_CSSC_SHIFT) +#define ID_AA64ISAR2_CSSC_IMPL (UL(0x1) << ID_AA64ISAR2_CSSC_SHIFT) +#define ID_AA64ISAR2_ATS1A_SHIFT 60 +#define ID_AA64ISAR2_ATS1A_WIDTH 4 +#define ID_AA64ISAR2_ATS1A_MASK (UL(0xf) << ID_AA64ISAR2_ATS1A_SHIFT) +#define ID_AA64ISAR2_ATS1A_VAL(x) ((x) & ID_AA64ISAR2_ATS1A_MASK) +#define ID_AA64ISAR2_ATS1A_NONE (UL(0x0) << ID_AA64ISAR2_ATS1A_SHIFT) +#define ID_AA64ISAR2_ATS1A_IMPL (UL(0x1) << ID_AA64ISAR2_ATS1A_SHIFT) /* ID_AA64MMFR0_EL1 */ -#define ID_AA64MMFR0_EL1 MRS_REG(ID_AA64MMFR0_EL1) #define ID_AA64MMFR0_EL1_REG MRS_REG_ALT_NAME(ID_AA64MMFR0_EL1) +#define ID_AA64MMFR0_EL1_ISS ISS_MSR_REG(ID_AA64MMFR0_EL1) #define ID_AA64MMFR0_EL1_op0 3 #define ID_AA64MMFR0_EL1_op1 0 #define ID_AA64MMFR0_EL1_CRn 0 #define ID_AA64MMFR0_EL1_CRm 7 #define ID_AA64MMFR0_EL1_op2 0 #define ID_AA64MMFR0_PARange_SHIFT 0 +#define ID_AA64MMFR0_PARange_WIDTH 4 #define ID_AA64MMFR0_PARange_MASK (UL(0xf) << ID_AA64MMFR0_PARange_SHIFT) #define ID_AA64MMFR0_PARange_VAL(x) ((x) & ID_AA64MMFR0_PARange_MASK) #define ID_AA64MMFR0_PARange_4G (UL(0x0) << ID_AA64MMFR0_PARange_SHIFT) @@ -1069,43 +1202,51 @@ #define ID_AA64MMFR0_PARange_256T (UL(0x5) << ID_AA64MMFR0_PARange_SHIFT) #define ID_AA64MMFR0_PARange_4P (UL(0x6) << ID_AA64MMFR0_PARange_SHIFT) #define ID_AA64MMFR0_ASIDBits_SHIFT 4 +#define ID_AA64MMFR0_ASIDBits_WIDTH 4 #define ID_AA64MMFR0_ASIDBits_MASK (UL(0xf) << ID_AA64MMFR0_ASIDBits_SHIFT) #define ID_AA64MMFR0_ASIDBits_VAL(x) ((x) & ID_AA64MMFR0_ASIDBits_MASK) #define ID_AA64MMFR0_ASIDBits_8 (UL(0x0) << ID_AA64MMFR0_ASIDBits_SHIFT) #define ID_AA64MMFR0_ASIDBits_16 (UL(0x2) << ID_AA64MMFR0_ASIDBits_SHIFT) #define ID_AA64MMFR0_BigEnd_SHIFT 8 +#define ID_AA64MMFR0_BigEnd_WIDTH 4 #define ID_AA64MMFR0_BigEnd_MASK (UL(0xf) << ID_AA64MMFR0_BigEnd_SHIFT) #define ID_AA64MMFR0_BigEnd_VAL(x) ((x) & ID_AA64MMFR0_BigEnd_MASK) #define ID_AA64MMFR0_BigEnd_FIXED (UL(0x0) << ID_AA64MMFR0_BigEnd_SHIFT) #define ID_AA64MMFR0_BigEnd_MIXED (UL(0x1) << ID_AA64MMFR0_BigEnd_SHIFT) #define ID_AA64MMFR0_SNSMem_SHIFT 12 +#define ID_AA64MMFR0_SNSMem_WIDTH 4 #define ID_AA64MMFR0_SNSMem_MASK (UL(0xf) << ID_AA64MMFR0_SNSMem_SHIFT) #define ID_AA64MMFR0_SNSMem_VAL(x) ((x) & ID_AA64MMFR0_SNSMem_MASK) #define ID_AA64MMFR0_SNSMem_NONE (UL(0x0) << ID_AA64MMFR0_SNSMem_SHIFT) #define ID_AA64MMFR0_SNSMem_DISTINCT (UL(0x1) << ID_AA64MMFR0_SNSMem_SHIFT) #define ID_AA64MMFR0_BigEndEL0_SHIFT 16 +#define ID_AA64MMFR0_BigEndEL0_WIDTH 4 #define ID_AA64MMFR0_BigEndEL0_MASK (UL(0xf) << ID_AA64MMFR0_BigEndEL0_SHIFT) #define ID_AA64MMFR0_BigEndEL0_VAL(x) ((x) & ID_AA64MMFR0_BigEndEL0_MASK) #define ID_AA64MMFR0_BigEndEL0_FIXED (UL(0x0) << ID_AA64MMFR0_BigEndEL0_SHIFT) #define ID_AA64MMFR0_BigEndEL0_MIXED (UL(0x1) << ID_AA64MMFR0_BigEndEL0_SHIFT) #define ID_AA64MMFR0_TGran16_SHIFT 20 +#define ID_AA64MMFR0_TGran16_WIDTH 4 #define ID_AA64MMFR0_TGran16_MASK (UL(0xf) << ID_AA64MMFR0_TGran16_SHIFT) #define ID_AA64MMFR0_TGran16_VAL(x) ((x) & ID_AA64MMFR0_TGran16_MASK) #define ID_AA64MMFR0_TGran16_NONE (UL(0x0) << ID_AA64MMFR0_TGran16_SHIFT) #define ID_AA64MMFR0_TGran16_IMPL (UL(0x1) << ID_AA64MMFR0_TGran16_SHIFT) #define ID_AA64MMFR0_TGran16_LPA2 (UL(0x2) << ID_AA64MMFR0_TGran16_SHIFT) #define ID_AA64MMFR0_TGran64_SHIFT 24 +#define ID_AA64MMFR0_TGran64_WIDTH 4 #define ID_AA64MMFR0_TGran64_MASK (UL(0xf) << ID_AA64MMFR0_TGran64_SHIFT) #define ID_AA64MMFR0_TGran64_VAL(x) ((x) & ID_AA64MMFR0_TGran64_MASK) #define ID_AA64MMFR0_TGran64_IMPL (UL(0x0) << ID_AA64MMFR0_TGran64_SHIFT) #define ID_AA64MMFR0_TGran64_NONE (UL(0xf) << ID_AA64MMFR0_TGran64_SHIFT) #define ID_AA64MMFR0_TGran4_SHIFT 28 +#define ID_AA64MMFR0_TGran4_WIDTH 4 #define ID_AA64MMFR0_TGran4_MASK (UL(0xf) << ID_AA64MMFR0_TGran4_SHIFT) #define ID_AA64MMFR0_TGran4_VAL(x) ((x) & ID_AA64MMFR0_TGran4_MASK) #define ID_AA64MMFR0_TGran4_IMPL (UL(0x0) << ID_AA64MMFR0_TGran4_SHIFT) #define ID_AA64MMFR0_TGran4_LPA2 (UL(0x1) << ID_AA64MMFR0_TGran4_SHIFT) #define ID_AA64MMFR0_TGran4_NONE (UL(0xf) << ID_AA64MMFR0_TGran4_SHIFT) #define ID_AA64MMFR0_TGran16_2_SHIFT 32 +#define ID_AA64MMFR0_TGran16_2_WIDTH 4 #define ID_AA64MMFR0_TGran16_2_MASK (UL(0xf) << ID_AA64MMFR0_TGran16_2_SHIFT) #define ID_AA64MMFR0_TGran16_2_VAL(x) ((x) & ID_AA64MMFR0_TGran16_2_MASK) #define ID_AA64MMFR0_TGran16_2_TGran16 (UL(0x0) << ID_AA64MMFR0_TGran16_2_SHIFT) @@ -1113,12 +1254,14 @@ #define ID_AA64MMFR0_TGran16_2_IMPL (UL(0x2) << ID_AA64MMFR0_TGran16_2_SHIFT) #define ID_AA64MMFR0_TGran16_2_LPA2 (UL(0x3) << ID_AA64MMFR0_TGran16_2_SHIFT) #define ID_AA64MMFR0_TGran64_2_SHIFT 36 +#define ID_AA64MMFR0_TGran64_2_WIDTH 4 #define ID_AA64MMFR0_TGran64_2_MASK (UL(0xf) << ID_AA64MMFR0_TGran64_2_SHIFT) #define ID_AA64MMFR0_TGran64_2_VAL(x) ((x) & ID_AA64MMFR0_TGran64_2_MASK) #define ID_AA64MMFR0_TGran64_2_TGran64 (UL(0x0) << ID_AA64MMFR0_TGran64_2_SHIFT) #define ID_AA64MMFR0_TGran64_2_NONE (UL(0x1) << ID_AA64MMFR0_TGran64_2_SHIFT) #define ID_AA64MMFR0_TGran64_2_IMPL (UL(0x2) << ID_AA64MMFR0_TGran64_2_SHIFT) #define ID_AA64MMFR0_TGran4_2_SHIFT 40 +#define ID_AA64MMFR0_TGran4_2_WIDTH 4 #define ID_AA64MMFR0_TGran4_2_MASK (UL(0xf) << ID_AA64MMFR0_TGran4_2_SHIFT) #define ID_AA64MMFR0_TGran4_2_VAL(x) ((x) & ID_AA64MMFR0_TGran4_2_MASK) #define ID_AA64MMFR0_TGran4_2_TGran4 (UL(0x0) << ID_AA64MMFR0_TGran4_2_SHIFT) @@ -1126,229 +1269,328 @@ #define ID_AA64MMFR0_TGran4_2_IMPL (UL(0x2) << ID_AA64MMFR0_TGran4_2_SHIFT) #define ID_AA64MMFR0_TGran4_2_LPA2 (UL(0x3) << ID_AA64MMFR0_TGran4_2_SHIFT) #define ID_AA64MMFR0_ExS_SHIFT 44 +#define ID_AA64MMFR0_ExS_WIDTH 4 #define ID_AA64MMFR0_ExS_MASK (UL(0xf) << ID_AA64MMFR0_ExS_SHIFT) #define ID_AA64MMFR0_ExS_VAL(x) ((x) & ID_AA64MMFR0_ExS_MASK) #define ID_AA64MMFR0_ExS_ALL (UL(0x0) << ID_AA64MMFR0_ExS_SHIFT) #define ID_AA64MMFR0_ExS_IMPL (UL(0x1) << ID_AA64MMFR0_ExS_SHIFT) #define ID_AA64MMFR0_FGT_SHIFT 56 +#define ID_AA64MMFR0_FGT_WIDTH 4 #define ID_AA64MMFR0_FGT_MASK (UL(0xf) << ID_AA64MMFR0_FGT_SHIFT) #define ID_AA64MMFR0_FGT_VAL(x) ((x) & ID_AA64MMFR0_FGT_MASK) #define ID_AA64MMFR0_FGT_NONE (UL(0x0) << ID_AA64MMFR0_FGT_SHIFT) -#define ID_AA64MMFR0_FGT_IMPL (UL(0x1) << ID_AA64MMFR0_FGT_SHIFT) +#define ID_AA64MMFR0_FGT_8_6 (UL(0x1) << ID_AA64MMFR0_FGT_SHIFT) +#define ID_AA64MMFR0_FGT_8_9 (UL(0x2) << ID_AA64MMFR0_FGT_SHIFT) #define ID_AA64MMFR0_ECV_SHIFT 60 +#define ID_AA64MMFR0_ECV_WIDTH 4 #define ID_AA64MMFR0_ECV_MASK (UL(0xf) << ID_AA64MMFR0_ECV_SHIFT) #define ID_AA64MMFR0_ECV_VAL(x) ((x) & ID_AA64MMFR0_ECV_MASK) #define ID_AA64MMFR0_ECV_NONE (UL(0x0) << ID_AA64MMFR0_ECV_SHIFT) #define ID_AA64MMFR0_ECV_IMPL (UL(0x1) << ID_AA64MMFR0_ECV_SHIFT) -#define ID_AA64MMFR0_ECV_CNTHCTL (UL(0x2) << ID_AA64MMFR0_ECV_SHIFT) +#define ID_AA64MMFR0_ECV_POFF (UL(0x2) << ID_AA64MMFR0_ECV_SHIFT) /* ID_AA64MMFR1_EL1 */ -#define ID_AA64MMFR1_EL1 MRS_REG(ID_AA64MMFR1_EL1) #define ID_AA64MMFR1_EL1_REG MRS_REG_ALT_NAME(ID_AA64MMFR1_EL1) +#define ID_AA64MMFR1_EL1_ISS ISS_MSR_REG(ID_AA64MMFR1_EL1) #define ID_AA64MMFR1_EL1_op0 3 #define ID_AA64MMFR1_EL1_op1 0 #define ID_AA64MMFR1_EL1_CRn 0 #define ID_AA64MMFR1_EL1_CRm 7 #define ID_AA64MMFR1_EL1_op2 1 #define ID_AA64MMFR1_HAFDBS_SHIFT 0 +#define ID_AA64MMFR1_HAFDBS_WIDTH 4 #define ID_AA64MMFR1_HAFDBS_MASK (UL(0xf) << ID_AA64MMFR1_HAFDBS_SHIFT) #define ID_AA64MMFR1_HAFDBS_VAL(x) ((x) & ID_AA64MMFR1_HAFDBS_MASK) #define ID_AA64MMFR1_HAFDBS_NONE (UL(0x0) << ID_AA64MMFR1_HAFDBS_SHIFT) #define ID_AA64MMFR1_HAFDBS_AF (UL(0x1) << ID_AA64MMFR1_HAFDBS_SHIFT) #define ID_AA64MMFR1_HAFDBS_AF_DBS (UL(0x2) << ID_AA64MMFR1_HAFDBS_SHIFT) #define ID_AA64MMFR1_VMIDBits_SHIFT 4 +#define ID_AA64MMFR1_VMIDBits_WIDTH 4 #define ID_AA64MMFR1_VMIDBits_MASK (UL(0xf) << ID_AA64MMFR1_VMIDBits_SHIFT) #define ID_AA64MMFR1_VMIDBits_VAL(x) ((x) & ID_AA64MMFR1_VMIDBits_MASK) #define ID_AA64MMFR1_VMIDBits_8 (UL(0x0) << ID_AA64MMFR1_VMIDBits_SHIFT) #define ID_AA64MMFR1_VMIDBits_16 (UL(0x2) << ID_AA64MMFR1_VMIDBits_SHIFT) #define ID_AA64MMFR1_VH_SHIFT 8 +#define ID_AA64MMFR1_VH_WIDTH 4 #define ID_AA64MMFR1_VH_MASK (UL(0xf) << ID_AA64MMFR1_VH_SHIFT) #define ID_AA64MMFR1_VH_VAL(x) ((x) & ID_AA64MMFR1_VH_MASK) #define ID_AA64MMFR1_VH_NONE (UL(0x0) << ID_AA64MMFR1_VH_SHIFT) #define ID_AA64MMFR1_VH_IMPL (UL(0x1) << ID_AA64MMFR1_VH_SHIFT) #define ID_AA64MMFR1_HPDS_SHIFT 12 +#define ID_AA64MMFR1_HPDS_WIDTH 4 #define ID_AA64MMFR1_HPDS_MASK (UL(0xf) << ID_AA64MMFR1_HPDS_SHIFT) #define ID_AA64MMFR1_HPDS_VAL(x) ((x) & ID_AA64MMFR1_HPDS_MASK) #define ID_AA64MMFR1_HPDS_NONE (UL(0x0) << ID_AA64MMFR1_HPDS_SHIFT) #define ID_AA64MMFR1_HPDS_HPD (UL(0x1) << ID_AA64MMFR1_HPDS_SHIFT) #define ID_AA64MMFR1_HPDS_TTPBHA (UL(0x2) << ID_AA64MMFR1_HPDS_SHIFT) #define ID_AA64MMFR1_LO_SHIFT 16 +#define ID_AA64MMFR1_LO_WIDTH 4 #define ID_AA64MMFR1_LO_MASK (UL(0xf) << ID_AA64MMFR1_LO_SHIFT) #define ID_AA64MMFR1_LO_VAL(x) ((x) & ID_AA64MMFR1_LO_MASK) #define ID_AA64MMFR1_LO_NONE (UL(0x0) << ID_AA64MMFR1_LO_SHIFT) #define ID_AA64MMFR1_LO_IMPL (UL(0x1) << ID_AA64MMFR1_LO_SHIFT) #define ID_AA64MMFR1_PAN_SHIFT 20 +#define ID_AA64MMFR1_PAN_WIDTH 4 #define ID_AA64MMFR1_PAN_MASK (UL(0xf) << ID_AA64MMFR1_PAN_SHIFT) #define ID_AA64MMFR1_PAN_VAL(x) ((x) & ID_AA64MMFR1_PAN_MASK) #define ID_AA64MMFR1_PAN_NONE (UL(0x0) << ID_AA64MMFR1_PAN_SHIFT) #define ID_AA64MMFR1_PAN_IMPL (UL(0x1) << ID_AA64MMFR1_PAN_SHIFT) #define ID_AA64MMFR1_PAN_ATS1E1 (UL(0x2) << ID_AA64MMFR1_PAN_SHIFT) -#define ID_AA64MMFR1_PAN_EPAN (UL(0x2) << ID_AA64MMFR1_PAN_SHIFT) +#define ID_AA64MMFR1_PAN_EPAN (UL(0x3) << ID_AA64MMFR1_PAN_SHIFT) #define ID_AA64MMFR1_SpecSEI_SHIFT 24 +#define ID_AA64MMFR1_SpecSEI_WIDTH 4 #define ID_AA64MMFR1_SpecSEI_MASK (UL(0xf) << ID_AA64MMFR1_SpecSEI_SHIFT) #define ID_AA64MMFR1_SpecSEI_VAL(x) ((x) & ID_AA64MMFR1_SpecSEI_MASK) #define ID_AA64MMFR1_SpecSEI_NONE (UL(0x0) << ID_AA64MMFR1_SpecSEI_SHIFT) #define ID_AA64MMFR1_SpecSEI_IMPL (UL(0x1) << ID_AA64MMFR1_SpecSEI_SHIFT) #define ID_AA64MMFR1_XNX_SHIFT 28 +#define ID_AA64MMFR1_XNX_WIDTH 4 #define ID_AA64MMFR1_XNX_MASK (UL(0xf) << ID_AA64MMFR1_XNX_SHIFT) #define ID_AA64MMFR1_XNX_VAL(x) ((x) & ID_AA64MMFR1_XNX_MASK) #define ID_AA64MMFR1_XNX_NONE (UL(0x0) << ID_AA64MMFR1_XNX_SHIFT) #define ID_AA64MMFR1_XNX_IMPL (UL(0x1) << ID_AA64MMFR1_XNX_SHIFT) #define ID_AA64MMFR1_TWED_SHIFT 32 +#define ID_AA64MMFR1_TWED_WIDTH 4 #define ID_AA64MMFR1_TWED_MASK (UL(0xf) << ID_AA64MMFR1_TWED_SHIFT) #define ID_AA64MMFR1_TWED_VAL(x) ((x) & ID_AA64MMFR1_TWED_MASK) #define ID_AA64MMFR1_TWED_NONE (UL(0x0) << ID_AA64MMFR1_TWED_SHIFT) #define ID_AA64MMFR1_TWED_IMPL (UL(0x1) << ID_AA64MMFR1_TWED_SHIFT) #define ID_AA64MMFR1_ETS_SHIFT 36 +#define ID_AA64MMFR1_ETS_WIDTH 4 #define ID_AA64MMFR1_ETS_MASK (UL(0xf) << ID_AA64MMFR1_ETS_SHIFT) #define ID_AA64MMFR1_ETS_VAL(x) ((x) & ID_AA64MMFR1_ETS_MASK) #define ID_AA64MMFR1_ETS_NONE (UL(0x0) << ID_AA64MMFR1_ETS_SHIFT) -#define ID_AA64MMFR1_ETS_IMPL (UL(0x1) << ID_AA64MMFR1_ETS_SHIFT) +#define ID_AA64MMFR1_ETS_NONE2 (UL(0x1) << ID_AA64MMFR1_ETS_SHIFT) +#define ID_AA64MMFR1_ETS_IMPL (UL(0x2) << ID_AA64MMFR1_ETS_SHIFT) #define ID_AA64MMFR1_HCX_SHIFT 40 +#define ID_AA64MMFR1_HCX_WIDTH 4 #define ID_AA64MMFR1_HCX_MASK (UL(0xf) << ID_AA64MMFR1_HCX_SHIFT) #define ID_AA64MMFR1_HCX_VAL(x) ((x) & ID_AA64MMFR1_HCX_MASK) #define ID_AA64MMFR1_HCX_NONE (UL(0x0) << ID_AA64MMFR1_HCX_SHIFT) #define ID_AA64MMFR1_HCX_IMPL (UL(0x1) << ID_AA64MMFR1_HCX_SHIFT) #define ID_AA64MMFR1_AFP_SHIFT 44 +#define ID_AA64MMFR1_AFP_WIDTH 4 #define ID_AA64MMFR1_AFP_MASK (UL(0xf) << ID_AA64MMFR1_AFP_SHIFT) #define ID_AA64MMFR1_AFP_VAL(x) ((x) & ID_AA64MMFR1_AFP_MASK) #define ID_AA64MMFR1_AFP_NONE (UL(0x0) << ID_AA64MMFR1_AFP_SHIFT) #define ID_AA64MMFR1_AFP_IMPL (UL(0x1) << ID_AA64MMFR1_AFP_SHIFT) #define ID_AA64MMFR1_nTLBPA_SHIFT 48 +#define ID_AA64MMFR1_nTLBPA_WIDTH 4 #define ID_AA64MMFR1_nTLBPA_MASK (UL(0xf) << ID_AA64MMFR1_nTLBPA_SHIFT) #define ID_AA64MMFR1_nTLBPA_VAL(x) ((x) & ID_AA64MMFR1_nTLBPA_MASK) #define ID_AA64MMFR1_nTLBPA_NONE (UL(0x0) << ID_AA64MMFR1_nTLBPA_SHIFT) #define ID_AA64MMFR1_nTLBPA_IMPL (UL(0x1) << ID_AA64MMFR1_nTLBPA_SHIFT) #define ID_AA64MMFR1_TIDCP1_SHIFT 52 +#define ID_AA64MMFR1_TIDCP1_WIDTH 4 #define ID_AA64MMFR1_TIDCP1_MASK (UL(0xf) << ID_AA64MMFR1_TIDCP1_SHIFT) #define ID_AA64MMFR1_TIDCP1_VAL(x) ((x) & ID_AA64MMFR1_TIDCP1_MASK) #define ID_AA64MMFR1_TIDCP1_NONE (UL(0x0) << ID_AA64MMFR1_TIDCP1_SHIFT) #define ID_AA64MMFR1_TIDCP1_IMPL (UL(0x1) << ID_AA64MMFR1_TIDCP1_SHIFT) #define ID_AA64MMFR1_CMOVW_SHIFT 56 +#define ID_AA64MMFR1_CMOVW_WIDTH 4 #define ID_AA64MMFR1_CMOVW_MASK (UL(0xf) << ID_AA64MMFR1_CMOVW_SHIFT) #define ID_AA64MMFR1_CMOVW_VAL(x) ((x) & ID_AA64MMFR1_CMOVW_MASK) #define ID_AA64MMFR1_CMOVW_NONE (UL(0x0) << ID_AA64MMFR1_CMOVW_SHIFT) #define ID_AA64MMFR1_CMOVW_IMPL (UL(0x1) << ID_AA64MMFR1_CMOVW_SHIFT) +#define ID_AA64MMFR1_ECBHB_SHIFT 60 +#define ID_AA64MMFR1_ECBHB_WIDTH 4 +#define ID_AA64MMFR1_ECBHB_MASK (UL(0xf) << ID_AA64MMFR1_ECBHB_SHIFT) +#define ID_AA64MMFR1_ECBHB_VAL(x) ((x) & ID_AA64MMFR1_ECBHB_MASK) +#define ID_AA64MMFR1_ECBHB_NONE (UL(0x0) << ID_AA64MMFR1_ECBHB_SHIFT) +#define ID_AA64MMFR1_ECBHB_IMPL (UL(0x1) << ID_AA64MMFR1_ECBHB_SHIFT) /* ID_AA64MMFR2_EL1 */ -#define ID_AA64MMFR2_EL1 MRS_REG(ID_AA64MMFR2_EL1) #define ID_AA64MMFR2_EL1_REG MRS_REG_ALT_NAME(ID_AA64MMFR2_EL1) +#define ID_AA64MMFR2_EL1_ISS ISS_MSR_REG(ID_AA64MMFR2_EL1) #define ID_AA64MMFR2_EL1_op0 3 #define ID_AA64MMFR2_EL1_op1 0 #define ID_AA64MMFR2_EL1_CRn 0 #define ID_AA64MMFR2_EL1_CRm 7 #define ID_AA64MMFR2_EL1_op2 2 #define ID_AA64MMFR2_CnP_SHIFT 0 +#define ID_AA64MMFR2_CnP_WIDTH 4 #define ID_AA64MMFR2_CnP_MASK (UL(0xf) << ID_AA64MMFR2_CnP_SHIFT) #define ID_AA64MMFR2_CnP_VAL(x) ((x) & ID_AA64MMFR2_CnP_MASK) #define ID_AA64MMFR2_CnP_NONE (UL(0x0) << ID_AA64MMFR2_CnP_SHIFT) #define ID_AA64MMFR2_CnP_IMPL (UL(0x1) << ID_AA64MMFR2_CnP_SHIFT) #define ID_AA64MMFR2_UAO_SHIFT 4 +#define ID_AA64MMFR2_UAO_WIDTH 4 #define ID_AA64MMFR2_UAO_MASK (UL(0xf) << ID_AA64MMFR2_UAO_SHIFT) #define ID_AA64MMFR2_UAO_VAL(x) ((x) & ID_AA64MMFR2_UAO_MASK) #define ID_AA64MMFR2_UAO_NONE (UL(0x0) << ID_AA64MMFR2_UAO_SHIFT) #define ID_AA64MMFR2_UAO_IMPL (UL(0x1) << ID_AA64MMFR2_UAO_SHIFT) #define ID_AA64MMFR2_LSM_SHIFT 8 +#define ID_AA64MMFR2_LSM_WIDTH 4 #define ID_AA64MMFR2_LSM_MASK (UL(0xf) << ID_AA64MMFR2_LSM_SHIFT) #define ID_AA64MMFR2_LSM_VAL(x) ((x) & ID_AA64MMFR2_LSM_MASK) #define ID_AA64MMFR2_LSM_NONE (UL(0x0) << ID_AA64MMFR2_LSM_SHIFT) #define ID_AA64MMFR2_LSM_IMPL (UL(0x1) << ID_AA64MMFR2_LSM_SHIFT) #define ID_AA64MMFR2_IESB_SHIFT 12 +#define ID_AA64MMFR2_IESB_WIDTH 4 #define ID_AA64MMFR2_IESB_MASK (UL(0xf) << ID_AA64MMFR2_IESB_SHIFT) #define ID_AA64MMFR2_IESB_VAL(x) ((x) & ID_AA64MMFR2_IESB_MASK) #define ID_AA64MMFR2_IESB_NONE (UL(0x0) << ID_AA64MMFR2_IESB_SHIFT) #define ID_AA64MMFR2_IESB_IMPL (UL(0x1) << ID_AA64MMFR2_IESB_SHIFT) #define ID_AA64MMFR2_VARange_SHIFT 16 +#define ID_AA64MMFR2_VARange_WIDTH 4 #define ID_AA64MMFR2_VARange_MASK (UL(0xf) << ID_AA64MMFR2_VARange_SHIFT) #define ID_AA64MMFR2_VARange_VAL(x) ((x) & ID_AA64MMFR2_VARange_MASK) #define ID_AA64MMFR2_VARange_48 (UL(0x0) << ID_AA64MMFR2_VARange_SHIFT) #define ID_AA64MMFR2_VARange_52 (UL(0x1) << ID_AA64MMFR2_VARange_SHIFT) #define ID_AA64MMFR2_CCIDX_SHIFT 20 +#define ID_AA64MMFR2_CCIDX_WIDTH 4 #define ID_AA64MMFR2_CCIDX_MASK (UL(0xf) << ID_AA64MMFR2_CCIDX_SHIFT) #define ID_AA64MMFR2_CCIDX_VAL(x) ((x) & ID_AA64MMFR2_CCIDX_MASK) #define ID_AA64MMFR2_CCIDX_32 (UL(0x0) << ID_AA64MMFR2_CCIDX_SHIFT) #define ID_AA64MMFR2_CCIDX_64 (UL(0x1) << ID_AA64MMFR2_CCIDX_SHIFT) #define ID_AA64MMFR2_NV_SHIFT 24 +#define ID_AA64MMFR2_NV_WIDTH 4 #define ID_AA64MMFR2_NV_MASK (UL(0xf) << ID_AA64MMFR2_NV_SHIFT) #define ID_AA64MMFR2_NV_VAL(x) ((x) & ID_AA64MMFR2_NV_MASK) #define ID_AA64MMFR2_NV_NONE (UL(0x0) << ID_AA64MMFR2_NV_SHIFT) #define ID_AA64MMFR2_NV_8_3 (UL(0x1) << ID_AA64MMFR2_NV_SHIFT) #define ID_AA64MMFR2_NV_8_4 (UL(0x2) << ID_AA64MMFR2_NV_SHIFT) #define ID_AA64MMFR2_ST_SHIFT 28 +#define ID_AA64MMFR2_ST_WIDTH 4 #define ID_AA64MMFR2_ST_MASK (UL(0xf) << ID_AA64MMFR2_ST_SHIFT) #define ID_AA64MMFR2_ST_VAL(x) ((x) & ID_AA64MMFR2_ST_MASK) #define ID_AA64MMFR2_ST_NONE (UL(0x0) << ID_AA64MMFR2_ST_SHIFT) #define ID_AA64MMFR2_ST_IMPL (UL(0x1) << ID_AA64MMFR2_ST_SHIFT) #define ID_AA64MMFR2_AT_SHIFT 32 +#define ID_AA64MMFR2_AT_WIDTH 4 #define ID_AA64MMFR2_AT_MASK (UL(0xf) << ID_AA64MMFR2_AT_SHIFT) #define ID_AA64MMFR2_AT_VAL(x) ((x) & ID_AA64MMFR2_AT_MASK) #define ID_AA64MMFR2_AT_NONE (UL(0x0) << ID_AA64MMFR2_AT_SHIFT) #define ID_AA64MMFR2_AT_IMPL (UL(0x1) << ID_AA64MMFR2_AT_SHIFT) #define ID_AA64MMFR2_IDS_SHIFT 36 +#define ID_AA64MMFR2_IDS_WIDTH 4 #define ID_AA64MMFR2_IDS_MASK (UL(0xf) << ID_AA64MMFR2_IDS_SHIFT) #define ID_AA64MMFR2_IDS_VAL(x) ((x) & ID_AA64MMFR2_IDS_MASK) #define ID_AA64MMFR2_IDS_NONE (UL(0x0) << ID_AA64MMFR2_IDS_SHIFT) #define ID_AA64MMFR2_IDS_IMPL (UL(0x1) << ID_AA64MMFR2_IDS_SHIFT) #define ID_AA64MMFR2_FWB_SHIFT 40 +#define ID_AA64MMFR2_FWB_WIDTH 4 #define ID_AA64MMFR2_FWB_MASK (UL(0xf) << ID_AA64MMFR2_FWB_SHIFT) #define ID_AA64MMFR2_FWB_VAL(x) ((x) & ID_AA64MMFR2_FWB_MASK) #define ID_AA64MMFR2_FWB_NONE (UL(0x0) << ID_AA64MMFR2_FWB_SHIFT) #define ID_AA64MMFR2_FWB_IMPL (UL(0x1) << ID_AA64MMFR2_FWB_SHIFT) #define ID_AA64MMFR2_TTL_SHIFT 48 +#define ID_AA64MMFR2_TTL_WIDTH 4 #define ID_AA64MMFR2_TTL_MASK (UL(0xf) << ID_AA64MMFR2_TTL_SHIFT) #define ID_AA64MMFR2_TTL_VAL(x) ((x) & ID_AA64MMFR2_TTL_MASK) #define ID_AA64MMFR2_TTL_NONE (UL(0x0) << ID_AA64MMFR2_TTL_SHIFT) #define ID_AA64MMFR2_TTL_IMPL (UL(0x1) << ID_AA64MMFR2_TTL_SHIFT) #define ID_AA64MMFR2_BBM_SHIFT 52 +#define ID_AA64MMFR2_BBM_WIDTH 4 #define ID_AA64MMFR2_BBM_MASK (UL(0xf) << ID_AA64MMFR2_BBM_SHIFT) #define ID_AA64MMFR2_BBM_VAL(x) ((x) & ID_AA64MMFR2_BBM_MASK) #define ID_AA64MMFR2_BBM_LEVEL0 (UL(0x0) << ID_AA64MMFR2_BBM_SHIFT) #define ID_AA64MMFR2_BBM_LEVEL1 (UL(0x1) << ID_AA64MMFR2_BBM_SHIFT) #define ID_AA64MMFR2_BBM_LEVEL2 (UL(0x2) << ID_AA64MMFR2_BBM_SHIFT) #define ID_AA64MMFR2_EVT_SHIFT 56 +#define ID_AA64MMFR2_EVT_WIDTH 4 #define ID_AA64MMFR2_EVT_MASK (UL(0xf) << ID_AA64MMFR2_EVT_SHIFT) #define ID_AA64MMFR2_EVT_VAL(x) ((x) & ID_AA64MMFR2_EVT_MASK) #define ID_AA64MMFR2_EVT_NONE (UL(0x0) << ID_AA64MMFR2_EVT_SHIFT) #define ID_AA64MMFR2_EVT_8_2 (UL(0x1) << ID_AA64MMFR2_EVT_SHIFT) #define ID_AA64MMFR2_EVT_8_5 (UL(0x2) << ID_AA64MMFR2_EVT_SHIFT) #define ID_AA64MMFR2_E0PD_SHIFT 60 +#define ID_AA64MMFR2_E0PD_WIDTH 4 #define ID_AA64MMFR2_E0PD_MASK (UL(0xf) << ID_AA64MMFR2_E0PD_SHIFT) #define ID_AA64MMFR2_E0PD_VAL(x) ((x) & ID_AA64MMFR2_E0PD_MASK) #define ID_AA64MMFR2_E0PD_NONE (UL(0x0) << ID_AA64MMFR2_E0PD_SHIFT) #define ID_AA64MMFR2_E0PD_IMPL (UL(0x1) << ID_AA64MMFR2_E0PD_SHIFT) /* ID_AA64MMFR3_EL1 */ -#define ID_AA64MMFR3_EL1 MRS_REG(ID_AA64MMFR3_EL1) #define ID_AA64MMFR3_EL1_REG MRS_REG_ALT_NAME(ID_AA64MMFR3_EL1) +#define ID_AA64MMFR3_EL1_ISS ISS_MSR_REG(ID_AA64MMFR3_EL1) #define ID_AA64MMFR3_EL1_op0 3 #define ID_AA64MMFR3_EL1_op1 0 #define ID_AA64MMFR3_EL1_CRn 0 #define ID_AA64MMFR3_EL1_CRm 7 #define ID_AA64MMFR3_EL1_op2 3 #define ID_AA64MMFR3_TCRX_SHIFT 0 +#define ID_AA64MMFR3_TCRX_WIDTH 4 #define ID_AA64MMFR3_TCRX_MASK (UL(0xf) << ID_AA64MMFR3_TCRX_SHIFT) #define ID_AA64MMFR3_TCRX_VAL(x) ((x) & ID_AA64MMFR3_TCRX_MASK) #define ID_AA64MMFR3_TCRX_NONE (UL(0x0) << ID_AA64MMFR3_TCRX_SHIFT) #define ID_AA64MMFR3_TCRX_IMPL (UL(0x1) << ID_AA64MMFR3_TCRX_SHIFT) #define ID_AA64MMFR3_SCTLRX_SHIFT 4 +#define ID_AA64MMFR3_SCTLRX_WIDTH 4 #define ID_AA64MMFR3_SCTLRX_MASK (UL(0xf) << ID_AA64MMFR3_SCTLRX_SHIFT) #define ID_AA64MMFR3_SCTLRX_VAL(x) ((x) & ID_AA64MMFR3_SCTLRX_MASK) #define ID_AA64MMFR3_SCTLRX_NONE (UL(0x0) << ID_AA64MMFR3_SCTLRX_SHIFT) #define ID_AA64MMFR3_SCTLRX_IMPL (UL(0x1) << ID_AA64MMFR3_SCTLRX_SHIFT) +#define ID_AA64MMFR3_S1PIE_SHIFT 8 +#define ID_AA64MMFR3_S1PIE_WIDTH 4 +#define ID_AA64MMFR3_S1PIE_MASK (UL(0xf) << ID_AA64MMFR3_S1PIE_SHIFT) +#define ID_AA64MMFR3_S1PIE_VAL(x) ((x) & ID_AA64MMFR3_S1PIE_MASK) +#define ID_AA64MMFR3_S1PIE_NONE (UL(0x0) << ID_AA64MMFR3_S1PIE_SHIFT) +#define ID_AA64MMFR3_S1PIE_IMPL (UL(0x1) << ID_AA64MMFR3_S1PIE_SHIFT) +#define ID_AA64MMFR3_S2PIE_SHIFT 12 +#define ID_AA64MMFR3_S2PIE_WIDTH 4 +#define ID_AA64MMFR3_S2PIE_MASK (UL(0xf) << ID_AA64MMFR3_S2PIE_SHIFT) +#define ID_AA64MMFR3_S2PIE_VAL(x) ((x) & ID_AA64MMFR3_S2PIE_MASK) +#define ID_AA64MMFR3_S2PIE_NONE (UL(0x0) << ID_AA64MMFR3_S2PIE_SHIFT) +#define ID_AA64MMFR3_S2PIE_IMPL (UL(0x1) << ID_AA64MMFR3_S2PIE_SHIFT) +#define ID_AA64MMFR3_S1POE_SHIFT 16 +#define ID_AA64MMFR3_S1POE_WIDTH 4 +#define ID_AA64MMFR3_S1POE_MASK (UL(0xf) << ID_AA64MMFR3_S1POE_SHIFT) +#define ID_AA64MMFR3_S1POE_VAL(x) ((x) & ID_AA64MMFR3_S1POE_MASK) +#define ID_AA64MMFR3_S1POE_NONE (UL(0x0) << ID_AA64MMFR3_S1POE_SHIFT) +#define ID_AA64MMFR3_S1POE_IMPL (UL(0x1) << ID_AA64MMFR3_S1POE_SHIFT) +#define ID_AA64MMFR3_S2POE_SHIFT 20 +#define ID_AA64MMFR3_S2POE_WIDTH 4 +#define ID_AA64MMFR3_S2POE_MASK (UL(0xf) << ID_AA64MMFR3_S2POE_SHIFT) +#define ID_AA64MMFR3_S2POE_VAL(x) ((x) & ID_AA64MMFR3_S2POE_MASK) +#define ID_AA64MMFR3_S2POE_NONE (UL(0x0) << ID_AA64MMFR3_S2POE_SHIFT) +#define ID_AA64MMFR3_S2POE_IMPL (UL(0x1) << ID_AA64MMFR3_S2POE_SHIFT) +#define ID_AA64MMFR3_AIE_SHIFT 24 +#define ID_AA64MMFR3_AIE_WIDTH 4 +#define ID_AA64MMFR3_AIE_MASK (UL(0xf) << ID_AA64MMFR3_AIE_SHIFT) +#define ID_AA64MMFR3_AIE_VAL(x) ((x) & ID_AA64MMFR3_AIE_MASK) +#define ID_AA64MMFR3_AIE_NONE (UL(0x0) << ID_AA64MMFR3_AIE_SHIFT) +#define ID_AA64MMFR3_AIE_IMPL (UL(0x1) << ID_AA64MMFR3_AIE_SHIFT) #define ID_AA64MMFR3_MEC_SHIFT 28 +#define ID_AA64MMFR3_MEC_WIDTH 4 #define ID_AA64MMFR3_MEC_MASK (UL(0xf) << ID_AA64MMFR3_MEC_SHIFT) #define ID_AA64MMFR3_MEC_VAL(x) ((x) & ID_AA64MMFR3_MEC_MASK) #define ID_AA64MMFR3_MEC_NONE (UL(0x0) << ID_AA64MMFR3_MEC_SHIFT) #define ID_AA64MMFR3_MEC_IMPL (UL(0x1) << ID_AA64MMFR3_MEC_SHIFT) +#define ID_AA64MMFR3_SNERR_SHIFT 40 +#define ID_AA64MMFR3_SNERR_WIDTH 4 +#define ID_AA64MMFR3_SNERR_MASK (UL(0xf) << ID_AA64MMFR3_SNERR_SHIFT) +#define ID_AA64MMFR3_SNERR_VAL(x) ((x) & ID_AA64MMFR3_SNERR_MASK) +#define ID_AA64MMFR3_SNERR_NONE (UL(0x0) << ID_AA64MMFR3_SNERR_SHIFT) +#define ID_AA64MMFR3_SNERR_ALL (UL(0x1) << ID_AA64MMFR3_SNERR_SHIFT) +#define ID_AA64MMFR3_ANERR_SHIFT 44 +#define ID_AA64MMFR3_ANERR_WIDTH 4 +#define ID_AA64MMFR3_ANERR_MASK (UL(0xf) << ID_AA64MMFR3_ANERR_SHIFT) +#define ID_AA64MMFR3_ANERR_VAL(x) ((x) & ID_AA64MMFR3_ANERR_MASK) +#define ID_AA64MMFR3_ANERR_NONE (UL(0x0) << ID_AA64MMFR3_ANERR_SHIFT) +#define ID_AA64MMFR3_ANERR_SOME (UL(0x1) << ID_AA64MMFR3_ANERR_SHIFT) +#define ID_AA64MMFR3_SDERR_SHIFT 52 +#define ID_AA64MMFR3_SDERR_WIDTH 4 +#define ID_AA64MMFR3_SDERR_MASK (UL(0xf) << ID_AA64MMFR3_SDERR_SHIFT) +#define ID_AA64MMFR3_SDERR_VAL(x) ((x) & ID_AA64MMFR3_SDERR_MASK) +#define ID_AA64MMFR3_SDERR_NONE (UL(0x0) << ID_AA64MMFR3_SDERR_SHIFT) +#define ID_AA64MMFR3_SDERR_ALL (UL(0x1) << ID_AA64MMFR3_SDERR_SHIFT) +#define ID_AA64MMFR3_ADERR_SHIFT 56 +#define ID_AA64MMFR3_ADERR_WIDTH 4 +#define ID_AA64MMFR3_ADERR_MASK (UL(0xf) << ID_AA64MMFR3_ADERR_SHIFT) +#define ID_AA64MMFR3_ADERR_VAL(x) ((x) & ID_AA64MMFR3_ADERR_MASK) +#define ID_AA64MMFR3_ADERR_NONE (UL(0x0) << ID_AA64MMFR3_ADERR_SHIFT) +#define ID_AA64MMFR3_ADERR_SOME (UL(0x1) << ID_AA64MMFR3_ADERR_SHIFT) #define ID_AA64MMFR3_Spec_FPACC_SHIFT 60 +#define ID_AA64MMFR3_Spec_FPACC_WIDTH 4 #define ID_AA64MMFR3_Spec_FPACC_MASK (UL(0xf) << ID_AA64MMFR3_Spec_FPACC_SHIFT) #define ID_AA64MMFR3_Spec_FPACC_VAL(x) ((x) & ID_AA64MMFR3_Spec_FPACC_MASK) #define ID_AA64MMFR3_Spec_FPACC_NONE (UL(0x0) << ID_AA64MMFR3_Spec_FPACC_SHIFT) #define ID_AA64MMFR3_Spec_FPACC_IMPL (UL(0x1) << ID_AA64MMFR3_Spec_FPACC_SHIFT) /* ID_AA64MMFR4_EL1 */ -#define ID_AA64MMFR4_EL1 MRS_REG(ID_AA64MMFR4_EL1) #define ID_AA64MMFR4_EL1_REG MRS_REG_ALT_NAME(ID_AA64MMFR4_EL1) +#define ID_AA64MMFR4_EL1_ISS ISS_MSR_REG(ID_AA64MMFR4_EL1) #define ID_AA64MMFR4_EL1_op0 3 #define ID_AA64MMFR4_EL1_op1 0 #define ID_AA64MMFR4_EL1_CRn 0 @@ -1356,42 +1598,48 @@ #define ID_AA64MMFR4_EL1_op2 4 /* ID_AA64PFR0_EL1 */ -#define ID_AA64PFR0_EL1 MRS_REG(ID_AA64PFR0_EL1) #define ID_AA64PFR0_EL1_REG MRS_REG_ALT_NAME(ID_AA64PFR0_EL1) +#define ID_AA64PFR0_EL1_ISS ISS_MSR_REG(ID_AA64PFR0_EL1) #define ID_AA64PFR0_EL1_op0 3 #define ID_AA64PFR0_EL1_op1 0 #define ID_AA64PFR0_EL1_CRn 0 #define ID_AA64PFR0_EL1_CRm 4 #define ID_AA64PFR0_EL1_op2 0 #define ID_AA64PFR0_EL0_SHIFT 0 +#define ID_AA64PFR0_EL0_WIDTH 4 #define ID_AA64PFR0_EL0_MASK (UL(0xf) << ID_AA64PFR0_EL0_SHIFT) #define ID_AA64PFR0_EL0_VAL(x) ((x) & ID_AA64PFR0_EL0_MASK) #define ID_AA64PFR0_EL0_64 (UL(0x1) << ID_AA64PFR0_EL0_SHIFT) #define ID_AA64PFR0_EL0_64_32 (UL(0x2) << ID_AA64PFR0_EL0_SHIFT) #define ID_AA64PFR0_EL1_SHIFT 4 +#define ID_AA64PFR0_EL1_WIDTH 4 #define ID_AA64PFR0_EL1_MASK (UL(0xf) << ID_AA64PFR0_EL1_SHIFT) #define ID_AA64PFR0_EL1_VAL(x) ((x) & ID_AA64PFR0_EL1_MASK) #define ID_AA64PFR0_EL1_64 (UL(0x1) << ID_AA64PFR0_EL1_SHIFT) #define ID_AA64PFR0_EL1_64_32 (UL(0x2) << ID_AA64PFR0_EL1_SHIFT) #define ID_AA64PFR0_EL2_SHIFT 8 +#define ID_AA64PFR0_EL2_WIDTH 4 #define ID_AA64PFR0_EL2_MASK (UL(0xf) << ID_AA64PFR0_EL2_SHIFT) #define ID_AA64PFR0_EL2_VAL(x) ((x) & ID_AA64PFR0_EL2_MASK) #define ID_AA64PFR0_EL2_NONE (UL(0x0) << ID_AA64PFR0_EL2_SHIFT) #define ID_AA64PFR0_EL2_64 (UL(0x1) << ID_AA64PFR0_EL2_SHIFT) #define ID_AA64PFR0_EL2_64_32 (UL(0x2) << ID_AA64PFR0_EL2_SHIFT) #define ID_AA64PFR0_EL3_SHIFT 12 +#define ID_AA64PFR0_EL3_WIDTH 4 #define ID_AA64PFR0_EL3_MASK (UL(0xf) << ID_AA64PFR0_EL3_SHIFT) #define ID_AA64PFR0_EL3_VAL(x) ((x) & ID_AA64PFR0_EL3_MASK) #define ID_AA64PFR0_EL3_NONE (UL(0x0) << ID_AA64PFR0_EL3_SHIFT) #define ID_AA64PFR0_EL3_64 (UL(0x1) << ID_AA64PFR0_EL3_SHIFT) #define ID_AA64PFR0_EL3_64_32 (UL(0x2) << ID_AA64PFR0_EL3_SHIFT) #define ID_AA64PFR0_FP_SHIFT 16 +#define ID_AA64PFR0_FP_WIDTH 4 #define ID_AA64PFR0_FP_MASK (UL(0xf) << ID_AA64PFR0_FP_SHIFT) #define ID_AA64PFR0_FP_VAL(x) ((x) & ID_AA64PFR0_FP_MASK) #define ID_AA64PFR0_FP_IMPL (UL(0x0) << ID_AA64PFR0_FP_SHIFT) #define ID_AA64PFR0_FP_HP (UL(0x1) << ID_AA64PFR0_FP_SHIFT) #define ID_AA64PFR0_FP_NONE (UL(0xf) << ID_AA64PFR0_FP_SHIFT) #define ID_AA64PFR0_AdvSIMD_SHIFT 20 +#define ID_AA64PFR0_AdvSIMD_WIDTH 4 #define ID_AA64PFR0_AdvSIMD_MASK (UL(0xf) << ID_AA64PFR0_AdvSIMD_SHIFT) #define ID_AA64PFR0_AdvSIMD_VAL(x) ((x) & ID_AA64PFR0_AdvSIMD_MASK) #define ID_AA64PFR0_AdvSIMD_IMPL (UL(0x0) << ID_AA64PFR0_AdvSIMD_SHIFT) @@ -1399,49 +1647,59 @@ #define ID_AA64PFR0_AdvSIMD_NONE (UL(0xf) << ID_AA64PFR0_AdvSIMD_SHIFT) #define ID_AA64PFR0_GIC_BITS 0x4 /* Number of bits in GIC field */ #define ID_AA64PFR0_GIC_SHIFT 24 +#define ID_AA64PFR0_GIC_WIDTH 4 #define ID_AA64PFR0_GIC_MASK (UL(0xf) << ID_AA64PFR0_GIC_SHIFT) #define ID_AA64PFR0_GIC_VAL(x) ((x) & ID_AA64PFR0_GIC_MASK) #define ID_AA64PFR0_GIC_CPUIF_NONE (UL(0x0) << ID_AA64PFR0_GIC_SHIFT) #define ID_AA64PFR0_GIC_CPUIF_EN (UL(0x1) << ID_AA64PFR0_GIC_SHIFT) #define ID_AA64PFR0_GIC_CPUIF_4_1 (UL(0x3) << ID_AA64PFR0_GIC_SHIFT) #define ID_AA64PFR0_RAS_SHIFT 28 +#define ID_AA64PFR0_RAS_WIDTH 4 #define ID_AA64PFR0_RAS_MASK (UL(0xf) << ID_AA64PFR0_RAS_SHIFT) #define ID_AA64PFR0_RAS_VAL(x) ((x) & ID_AA64PFR0_RAS_MASK) #define ID_AA64PFR0_RAS_NONE (UL(0x0) << ID_AA64PFR0_RAS_SHIFT) #define ID_AA64PFR0_RAS_IMPL (UL(0x1) << ID_AA64PFR0_RAS_SHIFT) #define ID_AA64PFR0_RAS_8_4 (UL(0x2) << ID_AA64PFR0_RAS_SHIFT) +#define ID_AA64PFR0_RAS_8_9 (UL(0x3) << ID_AA64PFR0_RAS_SHIFT) #define ID_AA64PFR0_SVE_SHIFT 32 +#define ID_AA64PFR0_SVE_WIDTH 4 #define ID_AA64PFR0_SVE_MASK (UL(0xf) << ID_AA64PFR0_SVE_SHIFT) #define ID_AA64PFR0_SVE_VAL(x) ((x) & ID_AA64PFR0_SVE_MASK) #define ID_AA64PFR0_SVE_NONE (UL(0x0) << ID_AA64PFR0_SVE_SHIFT) #define ID_AA64PFR0_SVE_IMPL (UL(0x1) << ID_AA64PFR0_SVE_SHIFT) #define ID_AA64PFR0_SEL2_SHIFT 36 +#define ID_AA64PFR0_SEL2_WIDTH 4 #define ID_AA64PFR0_SEL2_MASK (UL(0xf) << ID_AA64PFR0_SEL2_SHIFT) #define ID_AA64PFR0_SEL2_VAL(x) ((x) & ID_AA64PFR0_SEL2_MASK) #define ID_AA64PFR0_SEL2_NONE (UL(0x0) << ID_AA64PFR0_SEL2_SHIFT) #define ID_AA64PFR0_SEL2_IMPL (UL(0x1) << ID_AA64PFR0_SEL2_SHIFT) #define ID_AA64PFR0_MPAM_SHIFT 40 +#define ID_AA64PFR0_MPAM_WIDTH 4 #define ID_AA64PFR0_MPAM_MASK (UL(0xf) << ID_AA64PFR0_MPAM_SHIFT) #define ID_AA64PFR0_MPAM_VAL(x) ((x) & ID_AA64PFR0_MPAM_MASK) #define ID_AA64PFR0_MPAM_NONE (UL(0x0) << ID_AA64PFR0_MPAM_SHIFT) #define ID_AA64PFR0_MPAM_IMPL (UL(0x1) << ID_AA64PFR0_MPAM_SHIFT) #define ID_AA64PFR0_AMU_SHIFT 44 +#define ID_AA64PFR0_AMU_WIDTH 4 #define ID_AA64PFR0_AMU_MASK (UL(0xf) << ID_AA64PFR0_AMU_SHIFT) #define ID_AA64PFR0_AMU_VAL(x) ((x) & ID_AA64PFR0_AMU_MASK) #define ID_AA64PFR0_AMU_NONE (UL(0x0) << ID_AA64PFR0_AMU_SHIFT) #define ID_AA64PFR0_AMU_V1 (UL(0x1) << ID_AA64PFR0_AMU_SHIFT) #define ID_AA64PFR0_AMU_V1_1 (UL(0x2) << ID_AA64PFR0_AMU_SHIFT) #define ID_AA64PFR0_DIT_SHIFT 48 +#define ID_AA64PFR0_DIT_WIDTH 4 #define ID_AA64PFR0_DIT_MASK (UL(0xf) << ID_AA64PFR0_DIT_SHIFT) #define ID_AA64PFR0_DIT_VAL(x) ((x) & ID_AA64PFR0_DIT_MASK) #define ID_AA64PFR0_DIT_NONE (UL(0x0) << ID_AA64PFR0_DIT_SHIFT) #define ID_AA64PFR0_DIT_PSTATE (UL(0x1) << ID_AA64PFR0_DIT_SHIFT) #define ID_AA64PFR0_RME_SHIFT 52 +#define ID_AA64PFR0_RME_WIDTH 4 #define ID_AA64PFR0_RME_MASK (UL(0xf) << ID_AA64PFR0_RME_SHIFT) #define ID_AA64PFR0_RME_VAL(x) ((x) & ID_AA64PFR0_RME_MASK) #define ID_AA64PFR0_RME_NONE (UL(0x0) << ID_AA64PFR0_RME_SHIFT) #define ID_AA64PFR0_RME_IMPL (UL(0x1) << ID_AA64PFR0_RME_SHIFT) #define ID_AA64PFR0_CSV2_SHIFT 56 +#define ID_AA64PFR0_CSV2_WIDTH 4 #define ID_AA64PFR0_CSV2_MASK (UL(0xf) << ID_AA64PFR0_CSV2_SHIFT) #define ID_AA64PFR0_CSV2_VAL(x) ((x) & ID_AA64PFR0_CSV2_MASK) #define ID_AA64PFR0_CSV2_NONE (UL(0x0) << ID_AA64PFR0_CSV2_SHIFT) @@ -1449,31 +1707,35 @@ #define ID_AA64PFR0_CSV2_SCXTNUM (UL(0x2) << ID_AA64PFR0_CSV2_SHIFT) #define ID_AA64PFR0_CSV2_3 (UL(0x3) << ID_AA64PFR0_CSV2_SHIFT) #define ID_AA64PFR0_CSV3_SHIFT 60 +#define ID_AA64PFR0_CSV3_WIDTH 4 #define ID_AA64PFR0_CSV3_MASK (UL(0xf) << ID_AA64PFR0_CSV3_SHIFT) #define ID_AA64PFR0_CSV3_VAL(x) ((x) & ID_AA64PFR0_CSV3_MASK) #define ID_AA64PFR0_CSV3_NONE (UL(0x0) << ID_AA64PFR0_CSV3_SHIFT) #define ID_AA64PFR0_CSV3_ISOLATED (UL(0x1) << ID_AA64PFR0_CSV3_SHIFT) /* ID_AA64PFR1_EL1 */ -#define ID_AA64PFR1_EL1 MRS_REG(ID_AA64PFR1_EL1) #define ID_AA64PFR1_EL1_REG MRS_REG_ALT_NAME(ID_AA64PFR1_EL1) +#define ID_AA64PFR1_EL1_ISS ISS_MSR_REG(ID_AA64PFR1_EL1) #define ID_AA64PFR1_EL1_op0 3 #define ID_AA64PFR1_EL1_op1 0 #define ID_AA64PFR1_EL1_CRn 0 #define ID_AA64PFR1_EL1_CRm 4 #define ID_AA64PFR1_EL1_op2 1 #define ID_AA64PFR1_BT_SHIFT 0 +#define ID_AA64PFR1_BT_WIDTH 4 #define ID_AA64PFR1_BT_MASK (UL(0xf) << ID_AA64PFR1_BT_SHIFT) #define ID_AA64PFR1_BT_VAL(x) ((x) & ID_AA64PFR1_BT_MASK) #define ID_AA64PFR1_BT_NONE (UL(0x0) << ID_AA64PFR1_BT_SHIFT) #define ID_AA64PFR1_BT_IMPL (UL(0x1) << ID_AA64PFR1_BT_SHIFT) #define ID_AA64PFR1_SSBS_SHIFT 4 +#define ID_AA64PFR1_SSBS_WIDTH 4 #define ID_AA64PFR1_SSBS_MASK (UL(0xf) << ID_AA64PFR1_SSBS_SHIFT) #define ID_AA64PFR1_SSBS_VAL(x) ((x) & ID_AA64PFR1_SSBS_MASK) #define ID_AA64PFR1_SSBS_NONE (UL(0x0) << ID_AA64PFR1_SSBS_SHIFT) #define ID_AA64PFR1_SSBS_PSTATE (UL(0x1) << ID_AA64PFR1_SSBS_SHIFT) #define ID_AA64PFR1_SSBS_PSTATE_MSR (UL(0x2) << ID_AA64PFR1_SSBS_SHIFT) #define ID_AA64PFR1_MTE_SHIFT 8 +#define ID_AA64PFR1_MTE_WIDTH 4 #define ID_AA64PFR1_MTE_MASK (UL(0xf) << ID_AA64PFR1_MTE_SHIFT) #define ID_AA64PFR1_MTE_VAL(x) ((x) & ID_AA64PFR1_MTE_MASK) #define ID_AA64PFR1_MTE_NONE (UL(0x0) << ID_AA64PFR1_MTE_SHIFT) @@ -1481,41 +1743,77 @@ #define ID_AA64PFR1_MTE_MTE2 (UL(0x2) << ID_AA64PFR1_MTE_SHIFT) #define ID_AA64PFR1_MTE_MTE3 (UL(0x3) << ID_AA64PFR1_MTE_SHIFT) #define ID_AA64PFR1_RAS_frac_SHIFT 12 +#define ID_AA64PFR1_RAS_frac_WIDTH 4 #define ID_AA64PFR1_RAS_frac_MASK (UL(0xf) << ID_AA64PFR1_RAS_frac_SHIFT) #define ID_AA64PFR1_RAS_frac_VAL(x) ((x) & ID_AA64PFR1_RAS_frac_MASK) #define ID_AA64PFR1_RAS_frac_p0 (UL(0x0) << ID_AA64PFR1_RAS_frac_SHIFT) #define ID_AA64PFR1_RAS_frac_p1 (UL(0x1) << ID_AA64PFR1_RAS_frac_SHIFT) #define ID_AA64PFR1_MPAM_frac_SHIFT 16 +#define ID_AA64PFR1_MPAM_frac_WIDTH 4 #define ID_AA64PFR1_MPAM_frac_MASK (UL(0xf) << ID_AA64PFR1_MPAM_frac_SHIFT) #define ID_AA64PFR1_MPAM_frac_VAL(x) ((x) & ID_AA64PFR1_MPAM_frac_MASK) #define ID_AA64PFR1_MPAM_frac_p0 (UL(0x0) << ID_AA64PFR1_MPAM_frac_SHIFT) #define ID_AA64PFR1_MPAM_frac_p1 (UL(0x1) << ID_AA64PFR1_MPAM_frac_SHIFT) #define ID_AA64PFR1_SME_SHIFT 24 +#define ID_AA64PFR1_SME_WIDTH 4 #define ID_AA64PFR1_SME_MASK (UL(0xf) << ID_AA64PFR1_SME_SHIFT) #define ID_AA64PFR1_SME_VAL(x) ((x) & ID_AA64PFR1_SME_MASK) #define ID_AA64PFR1_SME_NONE (UL(0x0) << ID_AA64PFR1_SME_SHIFT) #define ID_AA64PFR1_SME_SME (UL(0x1) << ID_AA64PFR1_SME_SHIFT) #define ID_AA64PFR1_SME_SME2 (UL(0x2) << ID_AA64PFR1_SME_SHIFT) #define ID_AA64PFR1_RNDR_trap_SHIFT 28 +#define ID_AA64PFR1_RNDR_trap_WIDTH 4 #define ID_AA64PFR1_RNDR_trap_MASK (UL(0xf) << ID_AA64PFR1_RNDR_trap_SHIFT) #define ID_AA64PFR1_RNDR_trap_VAL(x) ((x) & ID_AA64PFR1_RNDR_trap_MASK) #define ID_AA64PFR1_RNDR_trap_NONE (UL(0x0) << ID_AA64PFR1_RNDR_trap_SHIFT) #define ID_AA64PFR1_RNDR_trap_IMPL (UL(0x1) << ID_AA64PFR1_RNDR_trap_SHIFT) #define ID_AA64PFR1_CSV2_frac_SHIFT 32 +#define ID_AA64PFR1_CSV2_frac_WIDTH 4 #define ID_AA64PFR1_CSV2_frac_MASK (UL(0xf) << ID_AA64PFR1_CSV2_frac_SHIFT) #define ID_AA64PFR1_CSV2_frac_VAL(x) ((x) & ID_AA64PFR1_CSV2_frac_MASK) #define ID_AA64PFR1_CSV2_frac_p0 (UL(0x0) << ID_AA64PFR1_CSV2_frac_SHIFT) #define ID_AA64PFR1_CSV2_frac_p1 (UL(0x1) << ID_AA64PFR1_CSV2_frac_SHIFT) #define ID_AA64PFR1_CSV2_frac_p2 (UL(0x2) << ID_AA64PFR1_CSV2_frac_SHIFT) #define ID_AA64PFR1_NMI_SHIFT 36 +#define ID_AA64PFR1_NMI_WIDTH 4 #define ID_AA64PFR1_NMI_MASK (UL(0xf) << ID_AA64PFR1_NMI_SHIFT) #define ID_AA64PFR1_NMI_VAL(x) ((x) & ID_AA64PFR1_NMI_MASK) #define ID_AA64PFR1_NMI_NONE (UL(0x0) << ID_AA64PFR1_NMI_SHIFT) #define ID_AA64PFR1_NMI_IMPL (UL(0x1) << ID_AA64PFR1_NMI_SHIFT) +#define ID_AA64PFR1_MTE_frac_SHIFT 40 +#define ID_AA64PFR1_MTE_frac_WIDTH 4 +#define ID_AA64PFR1_MTE_frac_MASK (UL(0xf) << ID_AA64PFR1_MTE_frac_SHIFT) +#define ID_AA64PFR1_MTE_frac_VAL(x) ((x) & ID_AA64PFR1_MTE_frac_MASK) +#define ID_AA64PFR1_MTE_frac_IMPL (UL(0x0) << ID_AA64PFR1_MTE_frac_SHIFT) +#define ID_AA64PFR1_MTE_frac_NONE (UL(0xf) << ID_AA64PFR1_MTE_frac_SHIFT) +#define ID_AA64PFR1_THE_SHIFT 48 +#define ID_AA64PFR1_THE_WIDTH 4 +#define ID_AA64PFR1_THE_MASK (UL(0xf) << ID_AA64PFR1_THE_SHIFT) +#define ID_AA64PFR1_THE_VAL(x) ((x) & ID_AA64PFR1_THE_MASK) +#define ID_AA64PFR1_THE_NONE (UL(0x0) << ID_AA64PFR1_THE_SHIFT) +#define ID_AA64PFR1_THE_IMPL (UL(0x1) << ID_AA64PFR1_THE_SHIFT) +#define ID_AA64PFR1_MTEX_SHIFT 52 +#define ID_AA64PFR1_MTEX_WIDTH 4 +#define ID_AA64PFR1_MTEX_MASK (UL(0xf) << ID_AA64PFR1_MTEX_SHIFT) +#define ID_AA64PFR1_MTEX_VAL(x) ((x) & ID_AA64PFR1_MTEX_MASK) +#define ID_AA64PFR1_MTEX_NONE (UL(0x0) << ID_AA64PFR1_MTEX_SHIFT) +#define ID_AA64PFR1_MTEX_IMPL (UL(0x1) << ID_AA64PFR1_MTEX_SHIFT) +#define ID_AA64PFR1_DF2_SHIFT 56 +#define ID_AA64PFR1_DF2_WIDTH 4 +#define ID_AA64PFR1_DF2_MASK (UL(0xf) << ID_AA64PFR1_DF2_SHIFT) +#define ID_AA64PFR1_DF2_VAL(x) ((x) & ID_AA64PFR1_DF2_MASK) +#define ID_AA64PFR1_DF2_NONE (UL(0x0) << ID_AA64PFR1_DF2_SHIFT) +#define ID_AA64PFR1_DF2_IMPL (UL(0x1) << ID_AA64PFR1_DF2_SHIFT) +#define ID_AA64PFR1_PFAR_SHIFT 60 +#define ID_AA64PFR1_PFAR_WIDTH 4 +#define ID_AA64PFR1_PFAR_MASK (UL(0xf) << ID_AA64PFR1_PFAR_SHIFT) +#define ID_AA64PFR1_PFAR_VAL(x) ((x) & ID_AA64PFR1_PFAR_MASK) +#define ID_AA64PFR1_PFAR_NONE (UL(0x0) << ID_AA64PFR1_PFAR_SHIFT) +#define ID_AA64PFR1_PFAR_IMPL (UL(0x1) << ID_AA64PFR1_PFAR_SHIFT) /* ID_AA64PFR2_EL1 */ -#define ID_AA64PFR2_EL1 MRS_REG(ID_AA64PFR2_EL1) #define ID_AA64PFR2_EL1_REG MRS_REG_ALT_NAME(ID_AA64PFR2_EL1) +#define ID_AA64PFR2_EL1_ISS ISS_MSR_REG(ID_AA64PFR2_EL1) #define ID_AA64PFR2_EL1_op0 3 #define ID_AA64PFR2_EL1_op1 0 #define ID_AA64PFR2_EL1_CRn 0 @@ -1523,101 +1821,117 @@ #define ID_AA64PFR2_EL1_op2 2 /* ID_AA64ZFR0_EL1 */ -#define ID_AA64ZFR0_EL1 MRS_REG(ID_AA64ZFR0_EL1) #define ID_AA64ZFR0_EL1_REG MRS_REG_ALT_NAME(ID_AA64ZFR0_EL1) +#define ID_AA64ZFR0_EL1_ISS ISS_MSR_REG(ID_AA64ZFR0_EL1) #define ID_AA64ZFR0_EL1_op0 3 #define ID_AA64ZFR0_EL1_op1 0 #define ID_AA64ZFR0_EL1_CRn 0 #define ID_AA64ZFR0_EL1_CRm 4 #define ID_AA64ZFR0_EL1_op2 4 #define ID_AA64ZFR0_SVEver_SHIFT 0 +#define ID_AA64ZFR0_SVEver_WIDTH 4 #define ID_AA64ZFR0_SVEver_MASK (UL(0xf) << ID_AA64ZFR0_SVEver_SHIFT) -#define ID_AA64ZFR0_SVEver_VAL(x) ((x) & ID_AA64ZFR0_SVEver_MASK -#define ID_AA64ZFR0_SVEver_SVE1 (UL(0x0) << ID_AA64ZFR0_SVEver_SHIFT) -#define ID_AA64ZFR0_SVEver_SVE2 (UL(0x1) << ID_AA64ZFR0_SVEver_SHIFT) -#define ID_AA64ZFR0_SVEver_SVE2P1 (UL(0x2) << ID_AA64ZFR0_SVEver_SHIFT) +#define ID_AA64ZFR0_SVEver_VAL(x) ((x) & ID_AA64ZFR0_SVEver_MASK) +#define ID_AA64ZFR0_SVEver_SVE1 (UL(0x0) << ID_AA64ZFR0_SVEver_SHIFT) +#define ID_AA64ZFR0_SVEver_SVE2 (UL(0x1) << ID_AA64ZFR0_SVEver_SHIFT) +#define ID_AA64ZFR0_SVEver_SVE2P1 (UL(0x2) << ID_AA64ZFR0_SVEver_SHIFT) #define ID_AA64ZFR0_AES_SHIFT 4 +#define ID_AA64ZFR0_AES_WIDTH 4 #define ID_AA64ZFR0_AES_MASK (UL(0xf) << ID_AA64ZFR0_AES_SHIFT) -#define ID_AA64ZFR0_AES_VAL(x) ((x) & ID_AA64ZFR0_AES_MASK -#define ID_AA64ZFR0_AES_NONE (UL(0x0) << ID_AA64ZFR0_AES_SHIFT) -#define ID_AA64ZFR0_AES_BASE (UL(0x1) << ID_AA64ZFR0_AES_SHIFT) -#define ID_AA64ZFR0_AES_PMULL (UL(0x2) << ID_AA64ZFR0_AES_SHIFT) +#define ID_AA64ZFR0_AES_VAL(x) ((x) & ID_AA64ZFR0_AES_MASK) +#define ID_AA64ZFR0_AES_NONE (UL(0x0) << ID_AA64ZFR0_AES_SHIFT) +#define ID_AA64ZFR0_AES_BASE (UL(0x1) << ID_AA64ZFR0_AES_SHIFT) +#define ID_AA64ZFR0_AES_PMULL (UL(0x2) << ID_AA64ZFR0_AES_SHIFT) #define ID_AA64ZFR0_BitPerm_SHIFT 16 +#define ID_AA64ZFR0_BitPerm_WIDTH 4 #define ID_AA64ZFR0_BitPerm_MASK (UL(0xf) << ID_AA64ZFR0_BitPerm_SHIFT) -#define ID_AA64ZFR0_BitPerm_VAL(x) ((x) & ID_AA64ZFR0_BitPerm_MASK -#define ID_AA64ZFR0_BitPerm_NONE (UL(0x0) << ID_AA64ZFR0_BitPerm_SHIFT) -#define ID_AA64ZFR0_BitPerm_IMPL (UL(0x1) << ID_AA64ZFR0_BitPerm_SHIFT) +#define ID_AA64ZFR0_BitPerm_VAL(x) ((x) & ID_AA64ZFR0_BitPerm_MASK) +#define ID_AA64ZFR0_BitPerm_NONE (UL(0x0) << ID_AA64ZFR0_BitPerm_SHIFT) +#define ID_AA64ZFR0_BitPerm_IMPL (UL(0x1) << ID_AA64ZFR0_BitPerm_SHIFT) #define ID_AA64ZFR0_BF16_SHIFT 20 +#define ID_AA64ZFR0_BF16_WIDTH 4 #define ID_AA64ZFR0_BF16_MASK (UL(0xf) << ID_AA64ZFR0_BF16_SHIFT) -#define ID_AA64ZFR0_BF16_VAL(x) ((x) & ID_AA64ZFR0_BF16_MASK -#define ID_AA64ZFR0_BF16_NONE (UL(0x0) << ID_AA64ZFR0_BF16_SHIFT) -#define ID_AA64ZFR0_BF16_BASE (UL(0x1) << ID_AA64ZFR0_BF16_SHIFT) -#define ID_AA64ZFR0_BF16_EBF (UL(0x1) << ID_AA64ZFR0_BF16_SHIFT) +#define ID_AA64ZFR0_BF16_VAL(x) ((x) & ID_AA64ZFR0_BF16_MASK) +#define ID_AA64ZFR0_BF16_NONE (UL(0x0) << ID_AA64ZFR0_BF16_SHIFT) +#define ID_AA64ZFR0_BF16_BASE (UL(0x1) << ID_AA64ZFR0_BF16_SHIFT) +#define ID_AA64ZFR0_BF16_EBF (UL(0x1) << ID_AA64ZFR0_BF16_SHIFT) #define ID_AA64ZFR0_SHA3_SHIFT 32 +#define ID_AA64ZFR0_SHA3_WIDTH 4 #define ID_AA64ZFR0_SHA3_MASK (UL(0xf) << ID_AA64ZFR0_SHA3_SHIFT) -#define ID_AA64ZFR0_SHA3_VAL(x) ((x) & ID_AA64ZFR0_SHA3_MASK -#define ID_AA64ZFR0_SHA3_NONE (UL(0x0) << ID_AA64ZFR0_SHA3_SHIFT) -#define ID_AA64ZFR0_SHA3_IMPL (UL(0x1) << ID_AA64ZFR0_SHA3_SHIFT) +#define ID_AA64ZFR0_SHA3_VAL(x) ((x) & ID_AA64ZFR0_SHA3_MASK) +#define ID_AA64ZFR0_SHA3_NONE (UL(0x0) << ID_AA64ZFR0_SHA3_SHIFT) +#define ID_AA64ZFR0_SHA3_IMPL (UL(0x1) << ID_AA64ZFR0_SHA3_SHIFT) #define ID_AA64ZFR0_SM4_SHIFT 40 +#define ID_AA64ZFR0_SM4_WIDTH 4 #define ID_AA64ZFR0_SM4_MASK (UL(0xf) << ID_AA64ZFR0_SM4_SHIFT) -#define ID_AA64ZFR0_SM4_VAL(x) ((x) & ID_AA64ZFR0_SM4_MASK -#define ID_AA64ZFR0_SM4_NONE (UL(0x0) << ID_AA64ZFR0_SM4_SHIFT) -#define ID_AA64ZFR0_SM4_IMPL (UL(0x1) << ID_AA64ZFR0_SM4_SHIFT) +#define ID_AA64ZFR0_SM4_VAL(x) ((x) & ID_AA64ZFR0_SM4_MASK) +#define ID_AA64ZFR0_SM4_NONE (UL(0x0) << ID_AA64ZFR0_SM4_SHIFT) +#define ID_AA64ZFR0_SM4_IMPL (UL(0x1) << ID_AA64ZFR0_SM4_SHIFT) #define ID_AA64ZFR0_I8MM_SHIFT 44 +#define ID_AA64ZFR0_I8MM_WIDTH 4 #define ID_AA64ZFR0_I8MM_MASK (UL(0xf) << ID_AA64ZFR0_I8MM_SHIFT) -#define ID_AA64ZFR0_I8MM_VAL(x) ((x) & ID_AA64ZFR0_I8MM_MASK -#define ID_AA64ZFR0_I8MM_NONE (UL(0x0) << ID_AA64ZFR0_I8MM_SHIFT) -#define ID_AA64ZFR0_I8MM_IMPL (UL(0x1) << ID_AA64ZFR0_I8MM_SHIFT) +#define ID_AA64ZFR0_I8MM_VAL(x) ((x) & ID_AA64ZFR0_I8MM_MASK) +#define ID_AA64ZFR0_I8MM_NONE (UL(0x0) << ID_AA64ZFR0_I8MM_SHIFT) +#define ID_AA64ZFR0_I8MM_IMPL (UL(0x1) << ID_AA64ZFR0_I8MM_SHIFT) #define ID_AA64ZFR0_F32MM_SHIFT 52 +#define ID_AA64ZFR0_F32MM_WIDTH 4 #define ID_AA64ZFR0_F32MM_MASK (UL(0xf) << ID_AA64ZFR0_F32MM_SHIFT) -#define ID_AA64ZFR0_F32MM_VAL(x) ((x) & ID_AA64ZFR0_F32MM_MASK -#define ID_AA64ZFR0_F32MM_NONE (UL(0x0) << ID_AA64ZFR0_F32MM_SHIFT) -#define ID_AA64ZFR0_F32MM_IMPL (UL(0x1) << ID_AA64ZFR0_F32MM_SHIFT) +#define ID_AA64ZFR0_F32MM_VAL(x) ((x) & ID_AA64ZFR0_F32MM_MASK) +#define ID_AA64ZFR0_F32MM_NONE (UL(0x0) << ID_AA64ZFR0_F32MM_SHIFT) +#define ID_AA64ZFR0_F32MM_IMPL (UL(0x1) << ID_AA64ZFR0_F32MM_SHIFT) #define ID_AA64ZFR0_F64MM_SHIFT 56 +#define ID_AA64ZFR0_F64MM_WIDTH 4 #define ID_AA64ZFR0_F64MM_MASK (UL(0xf) << ID_AA64ZFR0_F64MM_SHIFT) -#define ID_AA64ZFR0_F64MM_VAL(x) ((x) & ID_AA64ZFR0_F64MM_MASK -#define ID_AA64ZFR0_F64MM_NONE (UL(0x0) << ID_AA64ZFR0_F64MM_SHIFT) -#define ID_AA64ZFR0_F64MM_IMPL (UL(0x1) << ID_AA64ZFR0_F64MM_SHIFT) +#define ID_AA64ZFR0_F64MM_VAL(x) ((x) & ID_AA64ZFR0_F64MM_MASK) +#define ID_AA64ZFR0_F64MM_NONE (UL(0x0) << ID_AA64ZFR0_F64MM_SHIFT) +#define ID_AA64ZFR0_F64MM_IMPL (UL(0x1) << ID_AA64ZFR0_F64MM_SHIFT) /* ID_ISAR5_EL1 */ -#define ID_ISAR5_EL1 MRS_REG(ID_ISAR5_EL1) +#define ID_ISAR5_EL1_ISS ISS_MSR_REG(ID_ISAR5_EL1) #define ID_ISAR5_EL1_op0 0x3 #define ID_ISAR5_EL1_op1 0x0 #define ID_ISAR5_EL1_CRn 0x0 #define ID_ISAR5_EL1_CRm 0x2 #define ID_ISAR5_EL1_op2 0x5 #define ID_ISAR5_SEVL_SHIFT 0 +#define ID_ISAR5_SEVL_WIDTH 4 #define ID_ISAR5_SEVL_MASK (UL(0xf) << ID_ISAR5_SEVL_SHIFT) #define ID_ISAR5_SEVL_VAL(x) ((x) & ID_ISAR5_SEVL_MASK) #define ID_ISAR5_SEVL_NOP (UL(0x0) << ID_ISAR5_SEVL_SHIFT) #define ID_ISAR5_SEVL_IMPL (UL(0x1) << ID_ISAR5_SEVL_SHIFT) #define ID_ISAR5_AES_SHIFT 4 +#define ID_ISAR5_AES_WIDTH 4 #define ID_ISAR5_AES_MASK (UL(0xf) << ID_ISAR5_AES_SHIFT) #define ID_ISAR5_AES_VAL(x) ((x) & ID_ISAR5_AES_MASK) #define ID_ISAR5_AES_NONE (UL(0x0) << ID_ISAR5_AES_SHIFT) #define ID_ISAR5_AES_BASE (UL(0x1) << ID_ISAR5_AES_SHIFT) #define ID_ISAR5_AES_VMULL (UL(0x2) << ID_ISAR5_AES_SHIFT) #define ID_ISAR5_SHA1_SHIFT 8 +#define ID_ISAR5_SHA1_WIDTH 4 #define ID_ISAR5_SHA1_MASK (UL(0xf) << ID_ISAR5_SHA1_SHIFT) #define ID_ISAR5_SHA1_VAL(x) ((x) & ID_ISAR5_SHA1_MASK) #define ID_ISAR5_SHA1_NONE (UL(0x0) << ID_ISAR5_SHA1_SHIFT) #define ID_ISAR5_SHA1_IMPL (UL(0x1) << ID_ISAR5_SHA1_SHIFT) #define ID_ISAR5_SHA2_SHIFT 12 +#define ID_ISAR5_SHA2_WIDTH 4 #define ID_ISAR5_SHA2_MASK (UL(0xf) << ID_ISAR5_SHA2_SHIFT) #define ID_ISAR5_SHA2_VAL(x) ((x) & ID_ISAR5_SHA2_MASK) #define ID_ISAR5_SHA2_NONE (UL(0x0) << ID_ISAR5_SHA2_SHIFT) #define ID_ISAR5_SHA2_IMPL (UL(0x1) << ID_ISAR5_SHA2_SHIFT) #define ID_ISAR5_CRC32_SHIFT 16 +#define ID_ISAR5_CRC32_WIDTH 4 #define ID_ISAR5_CRC32_MASK (UL(0xf) << ID_ISAR5_CRC32_SHIFT) #define ID_ISAR5_CRC32_VAL(x) ((x) & ID_ISAR5_CRC32_MASK) #define ID_ISAR5_CRC32_NONE (UL(0x0) << ID_ISAR5_CRC32_SHIFT) #define ID_ISAR5_CRC32_IMPL (UL(0x1) << ID_ISAR5_CRC32_SHIFT) #define ID_ISAR5_RDM_SHIFT 24 +#define ID_ISAR5_RDM_WIDTH 4 #define ID_ISAR5_RDM_MASK (UL(0xf) << ID_ISAR5_RDM_SHIFT) #define ID_ISAR5_RDM_VAL(x) ((x) & ID_ISAR5_RDM_MASK) #define ID_ISAR5_RDM_NONE (UL(0x0) << ID_ISAR5_RDM_SHIFT) #define ID_ISAR5_RDM_IMPL (UL(0x1) << ID_ISAR5_RDM_SHIFT) #define ID_ISAR5_VCMA_SHIFT 28 +#define ID_ISAR5_VCMA_WIDTH 4 #define ID_ISAR5_VCMA_MASK (UL(0xf) << ID_ISAR5_VCMA_SHIFT) #define ID_ISAR5_VCMA_VAL(x) ((x) & ID_ISAR5_VCMA_MASK) #define ID_ISAR5_VCMA_NONE (UL(0x0) << ID_ISAR5_VCMA_SHIFT) @@ -1647,7 +1961,6 @@ #define MAIR_EL12_op2 0 /* MDCCINT_EL1 */ -#define MDCCINT_EL1 MRS_REG(MDCCINT_EL1) #define MDCCINT_EL1_op0 2 #define MDCCINT_EL1_op1 0 #define MDCCINT_EL1_CRn 0 @@ -1655,7 +1968,6 @@ #define MDCCINT_EL1_op2 0 /* MDCCSR_EL0 */ -#define MDCCSR_EL0 MRS_REG(MDCCSR_EL0) #define MDCCSR_EL0_op0 2 #define MDCCSR_EL0_op1 3 #define MDCCSR_EL0_CRn 0 @@ -1663,7 +1975,6 @@ #define MDCCSR_EL0_op2 0 /* MDSCR_EL1 - Monitor Debug System Control Register */ -#define MDSCR_EL1 MRS_REG(MDSCR_EL1) #define MDSCR_EL1_op0 2 #define MDSCR_EL1_op1 0 #define MDSCR_EL1_CRn 0 @@ -1677,7 +1988,6 @@ #define MDSCR_MDE (UL(0x1) << MDSCR_MDE_SHIFT) /* MIDR_EL1 - Main ID Register */ -#define MIDR_EL1 MRS_REG(MIDR_EL1) #define MIDR_EL1_op0 3 #define MIDR_EL1_op1 0 #define MIDR_EL1_CRn 0 @@ -1685,7 +1995,6 @@ #define MIDR_EL1_op2 0 /* MPIDR_EL1 - Multiprocessor Affinity Register */ -#define MPIDR_EL1 MRS_REG(MPIDR_EL1) #define MPIDR_EL1_op0 3 #define MPIDR_EL1_op1 0 #define MPIDR_EL1_CRn 0 @@ -1709,95 +2018,110 @@ #define MPIDR_AFF3_VAL(x) ((x) & MPIDR_AFF3_MASK) /* MVFR0_EL1 */ -#define MVFR0_EL1 MRS_REG(MVFR0_EL1) +#define MVFR0_EL1_ISS ISS_MSR_REG(MVFR0_EL1) #define MVFR0_EL1_op0 0x3 #define MVFR0_EL1_op1 0x0 #define MVFR0_EL1_CRn 0x0 #define MVFR0_EL1_CRm 0x3 #define MVFR0_EL1_op2 0x0 #define MVFR0_SIMDReg_SHIFT 0 +#define MVFR0_SIMDReg_WIDTH 4 #define MVFR0_SIMDReg_MASK (UL(0xf) << MVFR0_SIMDReg_SHIFT) #define MVFR0_SIMDReg_VAL(x) ((x) & MVFR0_SIMDReg_MASK) #define MVFR0_SIMDReg_NONE (UL(0x0) << MVFR0_SIMDReg_SHIFT) #define MVFR0_SIMDReg_FP (UL(0x1) << MVFR0_SIMDReg_SHIFT) #define MVFR0_SIMDReg_AdvSIMD (UL(0x2) << MVFR0_SIMDReg_SHIFT) #define MVFR0_FPSP_SHIFT 4 +#define MVFR0_FPSP_WIDTH 4 #define MVFR0_FPSP_MASK (UL(0xf) << MVFR0_FPSP_SHIFT) #define MVFR0_FPSP_VAL(x) ((x) & MVFR0_FPSP_MASK) #define MVFR0_FPSP_NONE (UL(0x0) << MVFR0_FPSP_SHIFT) #define MVFR0_FPSP_VFP_v2 (UL(0x1) << MVFR0_FPSP_SHIFT) #define MVFR0_FPSP_VFP_v3_v4 (UL(0x2) << MVFR0_FPSP_SHIFT) #define MVFR0_FPDP_SHIFT 8 +#define MVFR0_FPDP_WIDTH 4 #define MVFR0_FPDP_MASK (UL(0xf) << MVFR0_FPDP_SHIFT) #define MVFR0_FPDP_VAL(x) ((x) & MVFR0_FPDP_MASK) #define MVFR0_FPDP_NONE (UL(0x0) << MVFR0_FPDP_SHIFT) #define MVFR0_FPDP_VFP_v2 (UL(0x1) << MVFR0_FPDP_SHIFT) #define MVFR0_FPDP_VFP_v3_v4 (UL(0x2) << MVFR0_FPDP_SHIFT) #define MVFR0_FPTrap_SHIFT 12 +#define MVFR0_FPTrap_WIDTH 4 #define MVFR0_FPTrap_MASK (UL(0xf) << MVFR0_FPTrap_SHIFT) #define MVFR0_FPTrap_VAL(x) ((x) & MVFR0_FPTrap_MASK) #define MVFR0_FPTrap_NONE (UL(0x0) << MVFR0_FPTrap_SHIFT) #define MVFR0_FPTrap_IMPL (UL(0x1) << MVFR0_FPTrap_SHIFT) #define MVFR0_FPDivide_SHIFT 16 +#define MVFR0_FPDivide_WIDTH 4 #define MVFR0_FPDivide_MASK (UL(0xf) << MVFR0_FPDivide_SHIFT) #define MVFR0_FPDivide_VAL(x) ((x) & MVFR0_FPDivide_MASK) #define MVFR0_FPDivide_NONE (UL(0x0) << MVFR0_FPDivide_SHIFT) #define MVFR0_FPDivide_IMPL (UL(0x1) << MVFR0_FPDivide_SHIFT) #define MVFR0_FPSqrt_SHIFT 20 +#define MVFR0_FPSqrt_WIDTH 4 #define MVFR0_FPSqrt_MASK (UL(0xf) << MVFR0_FPSqrt_SHIFT) #define MVFR0_FPSqrt_VAL(x) ((x) & MVFR0_FPSqrt_MASK) #define MVFR0_FPSqrt_NONE (UL(0x0) << MVFR0_FPSqrt_SHIFT) #define MVFR0_FPSqrt_IMPL (UL(0x1) << MVFR0_FPSqrt_SHIFT) #define MVFR0_FPShVec_SHIFT 24 +#define MVFR0_FPShVec_WIDTH 4 #define MVFR0_FPShVec_MASK (UL(0xf) << MVFR0_FPShVec_SHIFT) #define MVFR0_FPShVec_VAL(x) ((x) & MVFR0_FPShVec_MASK) #define MVFR0_FPShVec_NONE (UL(0x0) << MVFR0_FPShVec_SHIFT) #define MVFR0_FPShVec_IMPL (UL(0x1) << MVFR0_FPShVec_SHIFT) #define MVFR0_FPRound_SHIFT 28 +#define MVFR0_FPRound_WIDTH 4 #define MVFR0_FPRound_MASK (UL(0xf) << MVFR0_FPRound_SHIFT) #define MVFR0_FPRound_VAL(x) ((x) & MVFR0_FPRound_MASK) #define MVFR0_FPRound_NONE (UL(0x0) << MVFR0_FPRound_SHIFT) #define MVFR0_FPRound_IMPL (UL(0x1) << MVFR0_FPRound_SHIFT) /* MVFR1_EL1 */ -#define MVFR1_EL1 MRS_REG(MVFR1_EL1) +#define MVFR1_EL1_ISS ISS_MSR_REG(MVFR1_EL1) #define MVFR1_EL1_op0 0x3 #define MVFR1_EL1_op1 0x0 #define MVFR1_EL1_CRn 0x0 #define MVFR1_EL1_CRm 0x3 #define MVFR1_EL1_op2 0x1 #define MVFR1_FPFtZ_SHIFT 0 +#define MVFR1_FPFtZ_WIDTH 4 #define MVFR1_FPFtZ_MASK (UL(0xf) << MVFR1_FPFtZ_SHIFT) #define MVFR1_FPFtZ_VAL(x) ((x) & MVFR1_FPFtZ_MASK) #define MVFR1_FPFtZ_NONE (UL(0x0) << MVFR1_FPFtZ_SHIFT) #define MVFR1_FPFtZ_IMPL (UL(0x1) << MVFR1_FPFtZ_SHIFT) #define MVFR1_FPDNaN_SHIFT 4 +#define MVFR1_FPDNaN_WIDTH 4 #define MVFR1_FPDNaN_MASK (UL(0xf) << MVFR1_FPDNaN_SHIFT) #define MVFR1_FPDNaN_VAL(x) ((x) & MVFR1_FPDNaN_MASK) #define MVFR1_FPDNaN_NONE (UL(0x0) << MVFR1_FPDNaN_SHIFT) #define MVFR1_FPDNaN_IMPL (UL(0x1) << MVFR1_FPDNaN_SHIFT) #define MVFR1_SIMDLS_SHIFT 8 +#define MVFR1_SIMDLS_WIDTH 4 #define MVFR1_SIMDLS_MASK (UL(0xf) << MVFR1_SIMDLS_SHIFT) #define MVFR1_SIMDLS_VAL(x) ((x) & MVFR1_SIMDLS_MASK) #define MVFR1_SIMDLS_NONE (UL(0x0) << MVFR1_SIMDLS_SHIFT) #define MVFR1_SIMDLS_IMPL (UL(0x1) << MVFR1_SIMDLS_SHIFT) #define MVFR1_SIMDInt_SHIFT 12 +#define MVFR1_SIMDInt_WIDTH 4 #define MVFR1_SIMDInt_MASK (UL(0xf) << MVFR1_SIMDInt_SHIFT) #define MVFR1_SIMDInt_VAL(x) ((x) & MVFR1_SIMDInt_MASK) #define MVFR1_SIMDInt_NONE (UL(0x0) << MVFR1_SIMDInt_SHIFT) #define MVFR1_SIMDInt_IMPL (UL(0x1) << MVFR1_SIMDInt_SHIFT) #define MVFR1_SIMDSP_SHIFT 16 +#define MVFR1_SIMDSP_WIDTH 4 #define MVFR1_SIMDSP_MASK (UL(0xf) << MVFR1_SIMDSP_SHIFT) #define MVFR1_SIMDSP_VAL(x) ((x) & MVFR1_SIMDSP_MASK) #define MVFR1_SIMDSP_NONE (UL(0x0) << MVFR1_SIMDSP_SHIFT) #define MVFR1_SIMDSP_IMPL (UL(0x1) << MVFR1_SIMDSP_SHIFT) #define MVFR1_SIMDHP_SHIFT 20 +#define MVFR1_SIMDHP_WIDTH 4 #define MVFR1_SIMDHP_MASK (UL(0xf) << MVFR1_SIMDHP_SHIFT) #define MVFR1_SIMDHP_VAL(x) ((x) & MVFR1_SIMDHP_MASK) #define MVFR1_SIMDHP_NONE (UL(0x0) << MVFR1_SIMDHP_SHIFT) #define MVFR1_SIMDHP_CONV_SP (UL(0x1) << MVFR1_SIMDHP_SHIFT) #define MVFR1_SIMDHP_ARITH (UL(0x2) << MVFR1_SIMDHP_SHIFT) #define MVFR1_FPHP_SHIFT 24 +#define MVFR1_FPHP_WIDTH 4 #define MVFR1_FPHP_MASK (UL(0xf) << MVFR1_FPHP_SHIFT) #define MVFR1_FPHP_VAL(x) ((x) & MVFR1_FPHP_MASK) #define MVFR1_FPHP_NONE (UL(0x0) << MVFR1_FPHP_SHIFT) @@ -1805,13 +2129,13 @@ #define MVFR1_FPHP_CONV_DP (UL(0x2) << MVFR1_FPHP_SHIFT) #define MVFR1_FPHP_ARITH (UL(0x3) << MVFR1_FPHP_SHIFT) #define MVFR1_SIMDFMAC_SHIFT 28 +#define MVFR1_SIMDFMAC_WIDTH 4 #define MVFR1_SIMDFMAC_MASK (UL(0xf) << MVFR1_SIMDFMAC_SHIFT) #define MVFR1_SIMDFMAC_VAL(x) ((x) & MVFR1_SIMDFMAC_MASK) #define MVFR1_SIMDFMAC_NONE (UL(0x0) << MVFR1_SIMDFMAC_SHIFT) #define MVFR1_SIMDFMAC_IMPL (UL(0x1) << MVFR1_SIMDFMAC_SHIFT) /* OSDLR_EL1 */ -#define OSDLR_EL1 MRS_REG(OSDLR_EL1) #define OSDLR_EL1_op0 2 #define OSDLR_EL1_op1 0 #define OSDLR_EL1_CRn 1 @@ -1819,20 +2143,23 @@ #define OSDLR_EL1_op2 4 /* OSLAR_EL1 */ -#define OSLAR_EL1 MRS_REG(OSLAR_EL1) #define OSLAR_EL1_op0 2 #define OSLAR_EL1_op1 0 #define OSLAR_EL1_CRn 1 #define OSLAR_EL1_CRm 0 #define OSLAR_EL1_op2 4 +#define OSLAR_OSLK (0x1ul << 0) /* OSLSR_EL1 */ -#define OSLSR_EL1 MRS_REG(OSLSR_EL1) #define OSLSR_EL1_op0 2 #define OSLSR_EL1_op1 0 #define OSLSR_EL1_CRn 1 #define OSLSR_EL1_CRm 1 #define OSLSR_EL1_op2 4 +#define OSLSR_OSLM_1 (0x1ul << 3) +#define OSLSR_nTT (0x1ul << 2) +#define OSLSR_OSLK (0x1ul << 1) +#define OSLSR_OSLM_0 (0x1ul << 0) /* PAR_EL1 - Physical Address Register */ #define PAR_F_SHIFT 0 @@ -1845,7 +2172,7 @@ #define PAR_NS_SHIFT 9 #define PAR_NS_MASK (0x3 << PAR_NS_SHIFT) #define PAR_PA_SHIFT 12 -#define PAR_PA_MASK 0x0000fffffffff000 +#define PAR_PA_MASK 0x000ffffffffff000 #define PAR_ATTR_SHIFT 56 #define PAR_ATTR_MASK (0xff << PAR_ATTR_SHIFT) /* When PAR_F == 1 (aborted) */ @@ -1857,7 +2184,6 @@ #define PAR_S_MASK (0x1 << PAR_S_SHIFT) /* PMBIDR_EL1 */ -#define PMBIDR_EL1 MRS_REG(PMBIDR_EL1) #define PMBIDR_EL1_REG MRS_REG_ALT_NAME(PMBIDR_EL1) #define PMBIDR_EL1_op0 3 #define PMBIDR_EL1_op1 0 @@ -1872,7 +2198,6 @@ #define PMBIDR_F (UL(0x1) << PMBIDR_F_SHIFT) /* PMBLIMITR_EL1 */ -#define PMBLIMITR_EL1 MRS_REG(PMBLIMITR_EL1) #define PMBLIMITR_EL1_REG MRS_REG_ALT_NAME(PMBLIMITR_EL1) #define PMBLIMITR_EL1_op0 3 #define PMBLIMITR_EL1_op1 0 @@ -1890,7 +2215,6 @@ (UL(0xfffffffffffff) << PMBLIMITR_LIMIT_SHIFT) /* PMBPTR_EL1 */ -#define PMBPTR_EL1 MRS_REG(PMBPTR_EL1) #define PMBPTR_EL1_REG MRS_REG_ALT_NAME(PMBPTR_EL1) #define PMBPTR_EL1_op0 3 #define PMBPTR_EL1_op1 0 @@ -1902,7 +2226,6 @@ (UL(0xffffffffffffffff) << PMBPTR_PTR_SHIFT) /* PMBSR_EL1 */ -#define PMBSR_EL1 MRS_REG(PMBSR_EL1) #define PMBSR_EL1_REG MRS_REG_ALT_NAME(PMBSR_EL1) #define PMBSR_EL1_op0 3 #define PMBSR_EL1_op1 0 @@ -1925,7 +2248,6 @@ #define PMBSR_EC_MASK (UL(0x3f) << PMBSR_EC_SHIFT) /* PMCCFILTR_EL0 */ -#define PMCCFILTR_EL0 MRS_REG(PMCCFILTR_EL0) #define PMCCFILTR_EL0_op0 3 #define PMCCFILTR_EL0_op1 3 #define PMCCFILTR_EL0_CRn 14 @@ -1933,7 +2255,6 @@ #define PMCCFILTR_EL0_op2 7 /* PMCCNTR_EL0 */ -#define PMCCNTR_EL0 MRS_REG(PMCCNTR_EL0) #define PMCCNTR_EL0_op0 3 #define PMCCNTR_EL0_op1 3 #define PMCCNTR_EL0_CRn 9 @@ -1941,7 +2262,6 @@ #define PMCCNTR_EL0_op2 0 /* PMCEID0_EL0 */ -#define PMCEID0_EL0 MRS_REG(PMCEID0_EL0) #define PMCEID0_EL0_op0 3 #define PMCEID0_EL0_op1 3 #define PMCEID0_EL0_CRn 9 @@ -1949,7 +2269,6 @@ #define PMCEID0_EL0_op2 6 /* PMCEID1_EL0 */ -#define PMCEID1_EL0 MRS_REG(PMCEID1_EL0) #define PMCEID1_EL0_op0 3 #define PMCEID1_EL0_op1 3 #define PMCEID1_EL0_CRn 9 @@ -1957,7 +2276,6 @@ #define PMCEID1_EL0_op2 7 /* PMCNTENCLR_EL0 */ -#define PMCNTENCLR_EL0 MRS_REG(PMCNTENCLR_EL0) #define PMCNTENCLR_EL0_op0 3 #define PMCNTENCLR_EL0_op1 3 #define PMCNTENCLR_EL0_CRn 9 @@ -1965,7 +2283,6 @@ #define PMCNTENCLR_EL0_op2 2 /* PMCNTENSET_EL0 */ -#define PMCNTENSET_EL0 MRS_REG(PMCNTENSET_EL0) #define PMCNTENSET_EL0_op0 3 #define PMCNTENSET_EL0_op1 3 #define PMCNTENSET_EL0_CRn 9 @@ -1973,24 +2290,24 @@ #define PMCNTENSET_EL0_op2 1 /* PMCR_EL0 - Perfomance Monitoring Counters */ -#define PMCR_EL0 MRS_REG(PMCR_EL0) #define PMCR_EL0_op0 3 #define PMCR_EL0_op1 3 #define PMCR_EL0_CRn 9 #define PMCR_EL0_CRm 12 #define PMCR_EL0_op2 0 -#define PMCR_E (1 << 0) /* Enable all counters */ -#define PMCR_P (1 << 1) /* Reset all counters */ -#define PMCR_C (1 << 2) /* Clock counter reset */ -#define PMCR_D (1 << 3) /* CNTR counts every 64 clk cycles */ -#define PMCR_X (1 << 4) /* Export to ext. monitoring (ETM) */ -#define PMCR_DP (1 << 5) /* Disable CCNT if non-invasive debug*/ -#define PMCR_LC (1 << 6) /* Long cycle count enable */ -#define PMCR_IMP_SHIFT 24 /* Implementer code */ -#define PMCR_IMP_MASK (0xff << PMCR_IMP_SHIFT) -#define PMCR_IMP_ARM 0x41 +#define PMCR_E (1ul << 0) /* Enable all counters */ +#define PMCR_P (1ul << 1) /* Reset all counters */ +#define PMCR_C (1ul << 2) /* Clock counter reset */ +#define PMCR_D (1ul << 3) /* CNTR counts every 64 clk cycles */ +#define PMCR_X (1ul << 4) /* Export to ext. monitoring (ETM) */ +#define PMCR_DP (1ul << 5) /* Disable CCNT if non-invasive debug*/ +#define PMCR_LC (1ul << 6) /* Long cycle count enable */ +#define PMCR_LP (1ul << 7) /* Long event count enable */ +#define PMCR_FZO (1ul << 9) /* Freeze-on-overflow */ +#define PMCR_N_SHIFT 11 /* Number of counters implemented */ +#define PMCR_N_MASK (0x1ful << PMCR_N_SHIFT) #define PMCR_IDCODE_SHIFT 16 /* Identification code */ -#define PMCR_IDCODE_MASK (0xff << PMCR_IDCODE_SHIFT) +#define PMCR_IDCODE_MASK (0xfful << PMCR_IDCODE_SHIFT) #define PMCR_IDCODE_CORTEX_A57 0x01 #define PMCR_IDCODE_CORTEX_A72 0x02 #define PMCR_IDCODE_CORTEX_A53 0x03 @@ -2002,8 +2319,10 @@ #define PMCR_IDCODE_CORTEX_A55 0x45 #define PMCR_IDCODE_NEOVERSE_E1 0x46 #define PMCR_IDCODE_CORTEX_A75 0x4a -#define PMCR_N_SHIFT 11 /* Number of counters implemented */ -#define PMCR_N_MASK (0x1f << PMCR_N_SHIFT) +#define PMCR_IMP_SHIFT 24 /* Implementer code */ +#define PMCR_IMP_MASK (0xfful << PMCR_IMP_SHIFT) +#define PMCR_IMP_ARM 0x41 +#define PMCR_FZS (1ul << 32) /* Freeze-on-SPE event */ /* PMEVCNTR_EL0 */ #define PMEVCNTR_EL0_op0 3 @@ -2035,7 +2354,6 @@ #define PMEVTYPER_P (1 << 31) /* Privileged filtering */ /* PMINTENCLR_EL1 */ -#define PMINTENCLR_EL1 MRS_REG(PMINTENCLR_EL1) #define PMINTENCLR_EL1_op0 3 #define PMINTENCLR_EL1_op1 0 #define PMINTENCLR_EL1_CRn 9 @@ -2043,7 +2361,6 @@ #define PMINTENCLR_EL1_op2 2 /* PMINTENSET_EL1 */ -#define PMINTENSET_EL1 MRS_REG(PMINTENSET_EL1) #define PMINTENSET_EL1_op0 3 #define PMINTENSET_EL1_op1 0 #define PMINTENSET_EL1_CRn 9 @@ -2051,7 +2368,6 @@ #define PMINTENSET_EL1_op2 1 /* PMMIR_EL1 */ -#define PMMIR_EL1 MRS_REG(PMMIR_EL1) #define PMMIR_EL1_op0 3 #define PMMIR_EL1_op1 0 #define PMMIR_EL1_CRn 9 @@ -2059,7 +2375,6 @@ #define PMMIR_EL1_op2 6 /* PMOVSCLR_EL0 */ -#define PMOVSCLR_EL0 MRS_REG(PMOVSCLR_EL0) #define PMOVSCLR_EL0_op0 3 #define PMOVSCLR_EL0_op1 3 #define PMOVSCLR_EL0_CRn 9 @@ -2067,7 +2382,6 @@ #define PMOVSCLR_EL0_op2 3 /* PMOVSSET_EL0 */ -#define PMOVSSET_EL0 MRS_REG(PMOVSSET_EL0) #define PMOVSSET_EL0_op0 3 #define PMOVSSET_EL0_op1 3 #define PMOVSSET_EL0_CRn 9 @@ -2075,7 +2389,6 @@ #define PMOVSSET_EL0_op2 3 /* PMSCR_EL1 */ -#define PMSCR_EL1 MRS_REG(PMSCR_EL1) #define PMSCR_EL1_REG MRS_REG_ALT_NAME(PMSCR_EL1) #define PMSCR_EL1_op0 3 #define PMSCR_EL1_op1 0 @@ -2096,7 +2409,6 @@ #define PMSCR_PCT_MASK (UL(0x3) << PMSCR_PCT_SHIFT) /* PMSELR_EL0 */ -#define PMSELR_EL0 MRS_REG(PMSELR_EL0) #define PMSELR_EL0_op0 3 #define PMSELR_EL0_op1 3 #define PMSELR_EL0_CRn 9 @@ -2105,7 +2417,6 @@ #define PMSELR_SEL_MASK 0x1f /* PMSEVFR_EL1 */ -#define PMSEVFR_EL1 MRS_REG(PMSEVFR_EL1) #define PMSEVFR_EL1_REG MRS_REG_ALT_NAME(PMSEVFR_EL1) #define PMSEVFR_EL1_op0 3 #define PMSEVFR_EL1_op1 0 @@ -2114,7 +2425,6 @@ #define PMSEVFR_EL1_op2 5 /* PMSFCR_EL1 */ -#define PMSFCR_EL1 MRS_REG(PMSFCR_EL1) #define PMSFCR_EL1_REG MRS_REG_ALT_NAME(PMSFCR_EL1) #define PMSFCR_EL1_op0 3 #define PMSFCR_EL1_op1 0 @@ -2137,7 +2447,6 @@ #define PMSFCR_ST (UL(0x1) << PMSFCR_ST_SHIFT) /* PMSICR_EL1 */ -#define PMSICR_EL1 MRS_REG(PMSICR_EL1) #define PMSICR_EL1_REG MRS_REG_ALT_NAME(PMSICR_EL1) #define PMSICR_EL1_op0 3 #define PMSICR_EL1_op1 0 @@ -2150,7 +2459,6 @@ #define PMSICR_ECOUNT_MASK (UL(0xff) << PMSICR_ECOUNT_SHIFT) /* PMSIDR_EL1 */ -#define PMSIDR_EL1 MRS_REG(PMSIDR_EL1) #define PMSIDR_EL1_REG MRS_REG_ALT_NAME(PMSIDR_EL1) #define PMSIDR_EL1_op0 3 #define PMSIDR_EL1_op1 0 @@ -2183,7 +2491,6 @@ #define PMSIDR_PBT (UL(0x1) << PMSIDR_PBT_SHIFT) /* PMSIRR_EL1 */ -#define PMSIRR_EL1 MRS_REG(PMSIRR_EL1) #define PMSIRR_EL1_REG MRS_REG_ALT_NAME(PMSIRR_EL1) #define PMSIRR_EL1_op0 3 #define PMSIRR_EL1_op1 0 @@ -2196,7 +2503,6 @@ #define PMSIRR_INTERVAL_MASK (UL(0xffffff) << PMSIRR_INTERVAL_SHIFT) /* PMSLATFR_EL1 */ -#define PMSLATFR_EL1 MRS_REG(PMSLATFR_EL1) #define PMSLATFR_EL1_REG MRS_REG_ALT_NAME(PMSLATFR_EL1) #define PMSLATFR_EL1_op0 3 #define PMSLATFR_EL1_op1 0 @@ -2207,7 +2513,6 @@ #define PMSLATFR_MINLAT_MASK (UL(0xfff) << PMSLATFR_MINLAT_SHIFT) /* PMSNEVFR_EL1 */ -#define PMSNEVFR_EL1 MRS_REG(PMSNEVFR_EL1) #define PMSNEVFR_EL1_REG MRS_REG_ALT_NAME(PMSNEVFR_EL1) #define PMSNEVFR_EL1_op0 3 #define PMSNEVFR_EL1_op1 0 @@ -2216,7 +2521,6 @@ #define PMSNEVFR_EL1_op2 1 /* PMSWINC_EL0 */ -#define PMSWINC_EL0 MRS_REG(PMSWINC_EL0) #define PMSWINC_EL0_op0 3 #define PMSWINC_EL0_op1 3 #define PMSWINC_EL0_CRn 9 @@ -2224,7 +2528,6 @@ #define PMSWINC_EL0_op2 4 /* PMUSERENR_EL0 */ -#define PMUSERENR_EL0 MRS_REG(PMUSERENR_EL0) #define PMUSERENR_EL0_op0 3 #define PMUSERENR_EL0_op1 3 #define PMUSERENR_EL0_CRn 9 @@ -2232,7 +2535,6 @@ #define PMUSERENR_EL0_op2 0 /* PMXEVCNTR_EL0 */ -#define PMXEVCNTR_EL0 MRS_REG(PMXEVCNTR_EL0) #define PMXEVCNTR_EL0_op0 3 #define PMXEVCNTR_EL0_op1 3 #define PMXEVCNTR_EL0_CRn 9 @@ -2240,7 +2542,6 @@ #define PMXEVCNTR_EL0_op2 2 /* PMXEVTYPER_EL0 */ -#define PMXEVTYPER_EL0 MRS_REG(PMXEVTYPER_EL0) #define PMXEVTYPER_EL0_op0 3 #define PMXEVTYPER_EL0_op1 3 #define PMXEVTYPER_EL0_CRn 9 @@ -2248,7 +2549,6 @@ #define PMXEVTYPER_EL0_op2 1 /* RNDRRS */ -#define RNDRRS MRS_REG(RNDRRS) #define RNDRRS_REG MRS_REG_ALT_NAME(RNDRRS) #define RNDRRS_op0 3 #define RNDRRS_op1 3 @@ -2313,6 +2613,26 @@ #define SCTLR_EnALS (UL(0x1) << 56) #define SCTLR_EPAN (UL(0x1) << 57) +#define SCTLR_MMU_OFF \ + (SCTLR_LSMAOE | SCTLR_nTLSMD | SCTLR_EIS | SCTLR_TSCXT | SCTLR_EOS) +#define SCTLR_MMU_ON \ + (SCTLR_MMU_OFF | \ + SCTLR_BT1 | \ + SCTLR_BT0 | \ + SCTLR_UCI | \ + SCTLR_SPAN | \ + SCTLR_nTWE | \ + SCTLR_nTWI | \ + SCTLR_UCT | \ + SCTLR_DZE | \ + SCTLR_I | \ + SCTLR_SED | \ + SCTLR_CP15BEN | \ + SCTLR_SA0 | \ + SCTLR_SA | \ + SCTLR_C | \ + SCTLR_M) + /* SCTLR_EL12 */ #define SCTLR_EL12_REG MRS_REG_ALT_NAME(SCTLR_EL12) #define SCTLR_EL12_op0 3 @@ -2354,7 +2674,8 @@ #define PSR_D 0x00000200UL #define PSR_DAIF (PSR_D | PSR_A | PSR_I | PSR_F) /* The default DAIF mask. These bits are valid in spsr_el1 and daif */ -#define PSR_DAIF_DEFAULT (PSR_F) +#define PSR_DAIF_DEFAULT (0) +#define PSR_DAIF_INTR (PSR_I | PSR_F) #define PSR_BTYPE 0x00000c00UL #define PSR_SSBS 0x00001000UL #define PSR_ALLINT 0x00002000UL @@ -2382,7 +2703,6 @@ #define SPSR_EL12_op2 0 /* REVIDR_EL1 - Revision ID Register */ -#define REVIDR_EL1 MRS_REG(REVIDR_EL1) #define REVIDR_EL1_op0 3 #define REVIDR_EL1_op1 0 #define REVIDR_EL1_CRn 0 @@ -2496,14 +2816,6 @@ #define TCR_T0SZ(x) ((x) << TCR_T0SZ_SHIFT) #define TCR_TxSZ(x) (TCR_T1SZ(x) | TCR_T0SZ(x)) -#define TCR_CACHE_ATTRS ((TCR_IRGN0_WBWA | TCR_IRGN1_WBWA) |\ - (TCR_ORGN0_WBWA | TCR_ORGN1_WBWA)) -#ifdef SMP -#define TCR_SMP_ATTRS (TCR_SH0_IS | TCR_SH1_IS) -#else -#define TCR_SMP_ATTRS 0 -#endif - /* TCR_EL12 */ #define TCR_EL12_REG MRS_REG_ALT_NAME(TCR_EL12) #define TCR_EL12_op0 3 @@ -2568,13 +2880,12 @@ #define VBAR_EL12_op2 0 /* ZCR_EL1 - SVE Control Register */ -#define ZCR_EL1 MRS_REG(ZCR_EL1) -#define ZCR_EL1_REG MRS_REG_ALT_NAME(ZCR_EL1_REG) -#define ZCR_EL1_REG_op0 3 -#define ZCR_EL1_REG_op1 0 -#define ZCR_EL1_REG_CRn 1 -#define ZCR_EL1_REG_CRm 2 -#define ZCR_EL1_REG_op2 0 +#define ZCR_EL1_REG MRS_REG_ALT_NAME(ZCR_EL1) +#define ZCR_EL1_op0 3 +#define ZCR_EL1_op1 0 +#define ZCR_EL1_CRn 1 +#define ZCR_EL1_CRm 2 +#define ZCR_EL1_op2 0 #define ZCR_LEN_SHIFT 0 #define ZCR_LEN_MASK (0xf << ZCR_LEN_SHIFT) #define ZCR_LEN_BYTES(x) ((((x) & ZCR_LEN_MASK) + 1) * 16) diff --git a/lib/libc/include/aarch64-freebsd-none/machine/asm.h b/lib/libc/include/aarch64-freebsd-none/machine/asm.h index 79114a1a86cb..2b8d5a97ec72 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/asm.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/asm.h @@ -72,6 +72,17 @@ /* Alias for link register x30 */ #define lr x30 +/* + * Check whether a given cpu feature is present, in the case it is not we jump + * to the given label. The tmp register should be a register able to hold the + * temporary data. + */ +#define CHECK_CPU_FEAT(tmp, feat_reg, feat, min_val, label) \ + mrs tmp, ##feat_reg##_el1; \ + ubfx tmp, tmp, ##feat_reg##_##feat##_SHIFT, ##feat_reg##_##feat##_WIDTH; \ + cmp tmp, #(##feat_reg##_##feat##_##min_val## >> ##feat_reg##_##feat##_SHIFT); \ + b.lt label + /* * Sets the trap fault handler. The exception handler will return to the * address in the handler register on a data abort or the xzr register to @@ -87,19 +98,25 @@ ldr tmp, =has_pan; /* Get the addr of has_pan */ \ ldr reg, [tmp]; /* Read it */ \ cbz reg, 997f; /* If no PAN skip */ \ - .inst 0xd500409f | (0 << 8); /* Clear PAN */ \ + .arch_extension pan; \ + msr pan, #0; /* Disable PAN checks */ \ + .arch_extension nopan; \ 997: #define EXIT_USER_ACCESS(reg) \ cbz reg, 998f; /* If no PAN skip */ \ - .inst 0xd500409f | (1 << 8); /* Set PAN */ \ + .arch_extension pan; \ + msr pan, #1; /* Enable PAN checks */ \ + .arch_extension nopan; \ 998: #define EXIT_USER_ACCESS_CHECK(reg, tmp) \ ldr tmp, =has_pan; /* Get the addr of has_pan */ \ ldr reg, [tmp]; /* Read it */ \ cbz reg, 999f; /* If no PAN skip */ \ - .inst 0xd500409f | (1 << 8); /* Set PAN */ \ + .arch_extension pan; \ + msr pan, #1; /* Enable PAN checks */ \ + .arch_extension nopan; \ 999: /* diff --git a/lib/libc/include/aarch64-freebsd-none/machine/atomic.h b/lib/libc/include/aarch64-freebsd-none/machine/atomic.h index 48ee9fa92232..5bb323add634 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/atomic.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/atomic.h @@ -465,7 +465,7 @@ _ATOMIC_TEST_OP(set, orr, set) #define _ATOMIC_LOAD_ACQ_IMPL(t, w, s) \ static __inline uint##t##_t \ -atomic_load_acq_##t(volatile uint##t##_t *p) \ +atomic_load_acq_##t(const volatile uint##t##_t *p) \ { \ uint##t##_t ret; \ \ @@ -609,6 +609,8 @@ _ATOMIC_STORE_REL_IMPL(64, , ) #define atomic_set_ptr atomic_set_64 #define atomic_swap_ptr atomic_swap_64 #define atomic_subtract_ptr atomic_subtract_64 +#define atomic_testandclear_ptr atomic_testandclear_64 +#define atomic_testandset_ptr atomic_testandset_64 #define atomic_add_acq_long atomic_add_acq_64 #define atomic_fcmpset_acq_long atomic_fcmpset_acq_64 diff --git a/lib/libc/include/aarch64-freebsd-none/machine/bus.h b/lib/libc/include/aarch64-freebsd-none/machine/bus.h index 76e656e758c4..6bf95d3d4f7b 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/bus.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/bus.h @@ -76,6 +76,7 @@ #define BUS_SPACE_MAXADDR_24BIT 0xFFFFFFUL #define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFFUL +#define BUS_SPACE_MAXADDR_36BIT 0xFFFFFFFFFUL #define BUS_SPACE_MAXADDR_40BIT 0xFFFFFFFFFFUL #define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFFUL #define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFFUL diff --git a/lib/libc/include/aarch64-freebsd-none/machine/bus_dma.h b/lib/libc/include/aarch64-freebsd-none/machine/bus_dma.h index 75c2fc74449a..754781d04923 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/bus_dma.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/bus_dma.h @@ -61,7 +61,7 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, /* * Free a piece of memory and it's allociated dmamap, that was allocated - * via bus_dmamem_alloc. Make the same choice for free/contigfree. + * via bus_dmamem_alloc. */ static inline void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) @@ -148,4 +148,16 @@ _bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map, return (tc->impl->map_complete(dmat, map, segs, nsegs, error)); } +#ifdef KMSAN +static inline void +_bus_dmamap_load_kmsan(bus_dma_tag_t dmat, bus_dmamap_t map, + struct memdesc *mem) +{ + struct bus_dma_tag_common *tc; + + tc = (struct bus_dma_tag_common *)dmat; + return (tc->impl->load_kmsan(map, mem)); +} +#endif + #endif /* !_MACHINE_BUS_DMA_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-freebsd-none/machine/bus_dma_impl.h b/lib/libc/include/aarch64-freebsd-none/machine/bus_dma_impl.h index 1973cf688c5e..24ed3e3ac683 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/bus_dma_impl.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/bus_dma_impl.h @@ -31,28 +31,23 @@ struct bus_dma_tag_common { struct bus_dma_impl *impl; - struct bus_dma_tag_common *parent; bus_size_t alignment; bus_addr_t boundary; bus_addr_t lowaddr; bus_addr_t highaddr; - bus_dma_filter_t *filter; - void *filterarg; bus_size_t maxsize; u_int nsegments; bus_size_t maxsegsz; int flags; bus_dma_lock_t *lockfunc; void *lockfuncarg; - int ref_count; int domain; }; struct bus_dma_impl { int (*tag_create)(bus_dma_tag_t parent, bus_size_t alignment, bus_addr_t boundary, bus_addr_t lowaddr, - bus_addr_t highaddr, bus_dma_filter_t *filter, - void *filterarg, bus_size_t maxsize, int nsegments, + bus_addr_t highaddr, bus_size_t maxsize, int nsegments, bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc, void *lockfuncarg, bus_dma_tag_t *dmat); int (*tag_destroy)(bus_dma_tag_t dmat); @@ -80,14 +75,15 @@ struct bus_dma_impl { void (*map_unload)(bus_dma_tag_t dmat, bus_dmamap_t map); void (*map_sync)(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op); +#ifdef KMSAN + void (*load_kmsan)(bus_dmamap_t map, struct memdesc *mem); +#endif }; -int bus_dma_run_filter(struct bus_dma_tag_common *dmat, bus_addr_t paddr); int common_bus_dma_tag_create(struct bus_dma_tag_common *parent, - bus_size_t alignment, - bus_addr_t boundary, bus_addr_t lowaddr, bus_addr_t highaddr, - bus_dma_filter_t *filter, void *filterarg, bus_size_t maxsize, - int nsegments, bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc, + bus_size_t alignment, bus_addr_t boundary, bus_addr_t lowaddr, + bus_addr_t highaddr, bus_size_t maxsize, int nsegments, + bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc, void *lockfuncarg, size_t sz, void **dmat); extern struct bus_dma_impl bus_dma_bounce_impl; diff --git a/lib/libc/include/aarch64-freebsd-none/machine/cpu.h b/lib/libc/include/aarch64-freebsd-none/machine/cpu.h index c516b89a9f70..755f3404e1af 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/cpu.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/cpu.h @@ -32,8 +32,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)cpu.h 5.4 (Berkeley) 5/9/91 * from: FreeBSD: src/sys/i386/include/cpu.h,v 1.62 2001/06/29 */ @@ -77,6 +75,7 @@ #define CPU_IMPL_CAVIUM 0x43 #define CPU_IMPL_DEC 0x44 #define CPU_IMPL_FUJITSU 0x46 +#define CPU_IMPL_HISILICON 0x48 #define CPU_IMPL_INFINEON 0x49 #define CPU_IMPL_FREESCALE 0x4D #define CPU_IMPL_NVIDIA 0x4E @@ -86,6 +85,7 @@ #define CPU_IMPL_APPLE 0x61 #define CPU_IMPL_INTEL 0x69 #define CPU_IMPL_AMPERE 0xC0 +#define CPU_IMPL_MICROSOFT 0x6D /* ARM Part numbers */ #define CPU_PART_FOUNDATION 0xD00 @@ -105,6 +105,7 @@ #define CPU_PART_AEM_V8 0xD0F #define CPU_PART_NEOVERSE_V1 0xD40 #define CPU_PART_CORTEX_A78 0xD41 +#define CPU_PART_CORTEX_A78AE 0xD42 #define CPU_PART_CORTEX_A65AE 0xD43 #define CPU_PART_CORTEX_X1 0xD44 #define CPU_PART_CORTEX_A510 0xD46 @@ -117,6 +118,18 @@ #define CPU_PART_CORTEX_A715 0xD4D #define CPU_PART_CORTEX_X3 0xD4E #define CPU_PART_NEOVERSE_V2 0xD4F +#define CPU_PART_CORTEX_A520 0xD80 +#define CPU_PART_CORTEX_A720 0xD81 +#define CPU_PART_CORTEX_X4 0xD82 +#define CPU_PART_NEOVERSE_V3AE 0xD83 +#define CPU_PART_NEOVERSE_V3 0xD84 +#define CPU_PART_CORTEX_X925 0xD85 +#define CPU_PART_CORTEX_A725 0xD87 +#define CPU_PART_C1_NANO 0xD8A +#define CPU_PART_C1_PRO 0xD8B +#define CPU_PART_C1_ULTRA 0xD8C +#define CPU_PART_NEOVERSE_N3 0xD8E +#define CPU_PART_C1_PREMIUM 0xD90 /* Cavium Part numbers */ #define CPU_PART_THUNDERX 0x0A1 @@ -129,9 +142,16 @@ #define CPU_REV_THUNDERX2_0 0x00 -/* APM / Ampere Part Number */ +/* APM (now Ampere) Part number */ #define CPU_PART_EMAG8180 0x000 +/* Ampere Part numbers */ +#define CPU_PART_AMPERE1 0xAC3 +#define CPU_PART_AMPERE1A 0xAC4 + +/* Microsoft Part numbers */ +#define CPU_PART_AZURE_COBALT_100 0xD49 + /* Qualcomm */ #define CPU_PART_KRYO400_GOLD 0x804 #define CPU_PART_KRYO400_SILVER 0x805 @@ -177,8 +197,30 @@ (((mask) & PCPU_GET(midr)) == \ ((mask) & CPU_ID_RAW((impl), (part), (var), (rev)))) -#define CPU_MATCH_RAW(mask, devid) \ - (((mask) & PCPU_GET(midr)) == ((mask) & (devid))) +#if !defined(__ASSEMBLER__) +static inline bool +midr_check_var_part_range(u_int midr, u_int impl, u_int part, u_int var_low, + u_int part_low, u_int var_high, u_int part_high) +{ + /* Check for the correct part */ + if (CPU_IMPL(midr) != impl || CPU_PART(midr) != part) + return (false); + + /* Check if the variant is between var_low and var_high inclusive */ + if (CPU_VAR(midr) < var_low || CPU_VAR(midr) > var_high) + return (false); + + /* If the variant is the low value, check if the part is high enough */ + if (CPU_VAR(midr) == var_low && CPU_PART(midr) < part_low) + return (false); + + /* If the variant is the high value, check if the part is low enough */ + if (CPU_VAR(midr) == var_high && CPU_PART(midr) > part_high) + return (false); + + return (true); +} +#endif /* * Chip-specific errata. This defines are intended to be @@ -210,6 +252,12 @@ extern uint64_t __cpu_affinity[]; struct arm64_addr_mask; extern struct arm64_addr_mask elf64_addr_mask; +#ifdef COMPAT_FREEBSD14 +extern struct arm64_addr_mask elf64_addr_mask_14; +#endif + +typedef void (*cpu_reset_hook_t)(void); +extern cpu_reset_hook_t cpu_reset_hook; void cpu_halt(void) __dead2; void cpu_reset(void) __dead2; @@ -231,9 +279,18 @@ void ptrauth_mp_start(uint64_t); /* Functions to read the sanitised view of the special registers */ void update_special_regs(u_int); -bool extract_user_id_field(u_int, u_int, uint8_t *); -bool get_kernel_reg(u_int, uint64_t *); -bool get_kernel_reg_masked(u_int, uint64_t *, uint64_t); +void update_special_reg_iss(u_int, uint64_t, uint64_t); +#define update_special_reg(reg, clear, set) \ + update_special_reg_iss(reg ## _ISS, clear, set) +bool get_kernel_reg_iss(u_int, uint64_t *); +#define get_kernel_reg(reg, valp) \ + get_kernel_reg_iss(reg ## _ISS, valp) +bool get_kernel_reg_iss_masked(u_int, uint64_t *, uint64_t); +#define get_kernel_reg_masked(reg, valp, mask) \ + get_kernel_reg_iss_masked(reg ## _ISS, valp, mask) +bool get_user_reg_iss(u_int, uint64_t *, bool); +#define get_user_reg(reg, valp, fbsd) \ + get_user_reg_iss(reg ## _ISS, valp, fbsd) void cpu_desc_init(void); diff --git a/lib/libc/include/aarch64-freebsd-none/machine/cpu_feat.h b/lib/libc/include/aarch64-freebsd-none/machine/cpu_feat.h new file mode 100644 index 000000000000..79f7cd753230 --- /dev/null +++ b/lib/libc/include/aarch64-freebsd-none/machine/cpu_feat.h @@ -0,0 +1,136 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 Arm Ltd + * + * 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 _MACHINE_CPU_FEAT_H_ +#define _MACHINE_CPU_FEAT_H_ + +#include +#include + +typedef enum { + ERRATA_UNKNOWN, /* Unknown erratum */ + ERRATA_NONE, /* No errata for this feature on this system. */ + ERRATA_AFFECTED, /* There is errata on this system. */ + ERRATA_FW_MITIGAION, /* There is errata, and a firmware */ + /* mitigation. The mitigation may need a */ + /* kernel component. */ +} cpu_feat_errata; + +typedef enum { + /* + * Don't implement the feature or erratum wrokarount, + * e.g. the feature is not implemented or erratum is + * for another CPU. + */ + FEAT_ALWAYS_DISABLE, + + /* + * Disable by default, but allow the user to enable, + * e.g. For a rare erratum with a workaround, Arm + * Category B (rare) or similar. + */ + FEAT_DEFAULT_DISABLE, + + /* + * Enabled by default, bit allow the user to disable, + * e.g. For a common erratum with a workaround, Arm + * Category A or B or similar. + */ + FEAT_DEFAULT_ENABLE, + + /* We could add FEAT_ALWAYS_ENABLE if a need was found. */ +} cpu_feat_en; + +#define CPU_FEAT_STAGE_MASK 0x00000001 +#define CPU_FEAT_EARLY_BOOT 0x00000000 +#define CPU_FEAT_AFTER_DEV 0x00000001 + +#define CPU_FEAT_SCOPE_MASK 0x00000010 +#define CPU_FEAT_PER_CPU 0x00000000 +#define CPU_FEAT_SYSTEM 0x00000010 + +#define CPU_FEAT_USER_ENABLED 0x40000000 +#define CPU_FEAT_USER_DISABLED 0x80000000 + +struct cpu_feat; + +typedef cpu_feat_en (cpu_feat_check)(const struct cpu_feat *, u_int); +typedef bool (cpu_feat_has_errata)(const struct cpu_feat *, u_int, + u_int **, u_int *); +typedef bool (cpu_feat_enable)(const struct cpu_feat *, cpu_feat_errata, + u_int *, u_int); +typedef void (cpu_feat_disabled)(const struct cpu_feat *); + +struct cpu_feat { + const char *feat_name; + cpu_feat_check *feat_check; + cpu_feat_has_errata *feat_has_errata; + cpu_feat_enable *feat_enable; + cpu_feat_disabled *feat_disabled; + uint32_t feat_flags; + bool feat_enabled; +}; +SET_DECLARE(cpu_feat_set, struct cpu_feat); + +SYSCTL_DECL(_hw_feat); + +#define CPU_FEAT(name, descr, check, has_errata, enable, disabled, flags) \ +static struct cpu_feat name = { \ + .feat_name = #name, \ + .feat_check = check, \ + .feat_has_errata = has_errata, \ + .feat_enable = enable, \ + .feat_disabled = disabled, \ + .feat_flags = flags, \ + .feat_enabled = false, \ +}; \ +DATA_SET(cpu_feat_set, name); \ +SYSCTL_BOOL(_hw_feat, OID_AUTO, name, CTLFLAG_RD, &name.feat_enabled, \ + 0, descr) + +/* + * Allow drivers to mark an erratum as worked around, e.g. the Errata + * Management ABI may know the workaround isn't needed on a given system. + */ +typedef cpu_feat_errata (*cpu_feat_errata_check_fn)(const struct cpu_feat *, + u_int); +void cpu_feat_register_errata_check(cpu_feat_errata_check_fn); + +void enable_cpu_feat(uint32_t); + +/* Check if an erratum is in the list of errata */ +static inline bool +cpu_feat_has_erratum(u_int *errata_list, u_int errata_count, u_int erratum) +{ + for (u_int i = 0; i < errata_count; i++) + if (errata_list[0] == erratum) + return (true); + + return (false); +} + +#endif /* _MACHINE_CPU_FEAT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-freebsd-none/machine/cpufunc.h b/lib/libc/include/aarch64-freebsd-none/machine/cpufunc.h index 1d8fb2a88ee5..645f5a47e2ae 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/cpufunc.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/cpufunc.h @@ -41,8 +41,6 @@ breakpoint(void) #ifdef _KERNEL #include -void pan_enable(void); - static __inline register_t dbg_disable(void) { @@ -160,6 +158,26 @@ invalidate_local_icache(void) "isb \n"); } +static __inline void +wfet(uint64_t val) +{ + __asm __volatile( + "msr s0_3_c1_c0_0, %0\n" + : + : "r" ((val)) + : "memory"); +} + +static __inline void +wfit(uint64_t val) +{ + __asm __volatile( + "msr s0_3_c1_c0_1, %0\n" + : + : "r" ((val)) + : "memory"); +} + extern bool icache_aliasing; extern bool icache_vmid; @@ -177,21 +195,21 @@ extern int64_t dczva_line_size; #define cpu_dcache_inv_range(a, s) arm64_dcache_inv_range((a), (s)) #define cpu_dcache_wb_range(a, s) arm64_dcache_wb_range((a), (s)) -extern void (*arm64_icache_sync_range)(vm_offset_t, vm_size_t); +extern void (*arm64_icache_sync_range)(void *, vm_size_t); #define cpu_icache_sync_range(a, s) arm64_icache_sync_range((a), (s)) #define cpu_icache_sync_range_checked(a, s) arm64_icache_sync_range_checked((a), (s)) void arm64_nullop(void); void arm64_tlb_flushID(void); -void arm64_dic_idc_icache_sync_range(vm_offset_t, vm_size_t); -void arm64_idc_aliasing_icache_sync_range(vm_offset_t, vm_size_t); -void arm64_aliasing_icache_sync_range(vm_offset_t, vm_size_t); -int arm64_icache_sync_range_checked(vm_offset_t, vm_size_t); -void arm64_dcache_wbinv_range(vm_offset_t, vm_size_t); -void arm64_dcache_inv_range(vm_offset_t, vm_size_t); -void arm64_dcache_wb_range(vm_offset_t, vm_size_t); -bool arm64_get_writable_addr(vm_offset_t, vm_offset_t *); +void arm64_dic_idc_icache_sync_range(void *, vm_size_t); +void arm64_idc_aliasing_icache_sync_range(void *, vm_size_t); +void arm64_aliasing_icache_sync_range(void *, vm_size_t); +int arm64_icache_sync_range_checked(void *, vm_size_t); +void arm64_dcache_wbinv_range(void *, vm_size_t); +void arm64_dcache_inv_range(void *, vm_size_t); +void arm64_dcache_wb_range(void *, vm_size_t); +bool arm64_get_writable_addr(void *, void **); #endif /* _KERNEL */ #endif /* _MACHINE_CPUFUNC_H_ */ diff --git a/lib/libc/include/aarch64-freebsd-none/machine/db_machdep.h b/lib/libc/include/aarch64-freebsd-none/machine/db_machdep.h index ac7dfeaf9ad1..f66ac49cef13 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/db_machdep.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/db_machdep.h @@ -40,6 +40,9 @@ #define T_SINGLESTEP (EXCP_SOFTSTP_EL1) #define T_WATCHPOINT (EXCP_WATCHPT_EL1) +#define HAS_HW_BREAKPOINT +#define NHBREAKPOINTS 16 + typedef vm_offset_t db_addr_t; typedef long db_expr_t; diff --git a/lib/libc/include/aarch64-freebsd-none/machine/debug_monitor.h b/lib/libc/include/aarch64-freebsd-none/machine/debug_monitor.h index f72b8288d437..6545f6ee2b5a 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/debug_monitor.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/debug_monitor.h @@ -56,6 +56,7 @@ void dbg_monitor_init(void); void dbg_register_sync(struct debug_monitor_state *); #ifdef DDB +void dbg_show_breakpoint(void); void dbg_show_watchpoint(void); #endif diff --git a/lib/libc/include/aarch64-freebsd-none/machine/efi.h b/lib/libc/include/aarch64-freebsd-none/machine/efi.h index d7bd4536f53d..491dcd733559 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/efi.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/efi.h @@ -35,6 +35,8 @@ #ifndef __ARM64_INCLUDE_EFI_H_ #define __ARM64_INCLUDE_EFI_H_ +#include + #define EFIABI_ATTR #ifdef _KERNEL @@ -44,7 +46,7 @@ #define EFI_TIME_UNLOCK() #define EFI_TIME_OWNED() -#define EFI_RT_HANDLE_FAULTS_DEFAULT 0 +#define EFI_RT_HANDLE_FAULTS_DEFAULT 1 #endif struct efirt_callinfo { diff --git a/lib/libc/include/aarch64-freebsd-none/machine/elf.h b/lib/libc/include/aarch64-freebsd-none/machine/elf.h index 1f9c59e80558..04423cb37b49 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/elf.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/elf.h @@ -93,91 +93,114 @@ __ElfType(Auxinfo); #define ET_DYN_LOAD_ADDR 0x100000 #endif +/* First __FreeBSD_version that supports Top Byte Ignore (TBI) */ +#define TBI_VERSION 1500058 + /* HWCAP */ -#define HWCAP_FP 0x00000001 -#define HWCAP_ASIMD 0x00000002 -#define HWCAP_EVTSTRM 0x00000004 -#define HWCAP_AES 0x00000008 -#define HWCAP_PMULL 0x00000010 -#define HWCAP_SHA1 0x00000020 -#define HWCAP_SHA2 0x00000040 -#define HWCAP_CRC32 0x00000080 -#define HWCAP_ATOMICS 0x00000100 -#define HWCAP_FPHP 0x00000200 -#define HWCAP_ASIMDHP 0x00000400 +#define HWCAP_FP (1 << 0) +#define HWCAP_ASIMD (1 << 1) +#define HWCAP_EVTSTRM (1 << 2) +#define HWCAP_AES (1 << 3) +#define HWCAP_PMULL (1 << 4) +#define HWCAP_SHA1 (1 << 5) +#define HWCAP_SHA2 (1 << 6) +#define HWCAP_CRC32 (1 << 7) +#define HWCAP_ATOMICS (1 << 8) +#define HWCAP_FPHP (1 << 9) +#define HWCAP_ASIMDHP (1 << 10) /* * XXX: The following bits (from CPUID to FLAGM) were originally incorrect, * but later changed to match the Linux definitions. No compatibility code is * provided, as the fix was expected to result in near-zero fallout. */ -#define HWCAP_CPUID 0x00000800 -#define HWCAP_ASIMDRDM 0x00001000 -#define HWCAP_JSCVT 0x00002000 -#define HWCAP_FCMA 0x00004000 -#define HWCAP_LRCPC 0x00008000 -#define HWCAP_DCPOP 0x00010000 -#define HWCAP_SHA3 0x00020000 -#define HWCAP_SM3 0x00040000 -#define HWCAP_SM4 0x00080000 -#define HWCAP_ASIMDDP 0x00100000 -#define HWCAP_SHA512 0x00200000 -#define HWCAP_SVE 0x00400000 -#define HWCAP_ASIMDFHM 0x00800000 -#define HWCAP_DIT 0x01000000 -#define HWCAP_USCAT 0x02000000 -#define HWCAP_ILRCPC 0x04000000 -#define HWCAP_FLAGM 0x08000000 -#define HWCAP_SSBS 0x10000000 -#define HWCAP_SB 0x20000000 -#define HWCAP_PACA 0x40000000 -#define HWCAP_PACG 0x80000000 +#define HWCAP_CPUID (1 << 11) +#define HWCAP_ASIMDRDM (1 << 12) +#define HWCAP_JSCVT (1 << 13) +#define HWCAP_FCMA (1 << 14) +#define HWCAP_LRCPC (1 << 15) +#define HWCAP_DCPOP (1 << 16) +#define HWCAP_SHA3 (1 << 17) +#define HWCAP_SM3 (1 << 18) +#define HWCAP_SM4 (1 << 19) +#define HWCAP_ASIMDDP (1 << 20) +#define HWCAP_SHA512 (1 << 21) +#define HWCAP_SVE (1 << 22) +#define HWCAP_ASIMDFHM (1 << 23) +#define HWCAP_DIT (1 << 24) +#define HWCAP_USCAT (1 << 25) +#define HWCAP_ILRCPC (1 << 26) +#define HWCAP_FLAGM (1 << 27) +#define HWCAP_SSBS (1 << 28) +#define HWCAP_SB (1 << 29) +#define HWCAP_PACA (1 << 30) +#define HWCAP_PACG (1UL << 31) +#define HWCAP_GCS (1UL << 32) /* HWCAP2 */ -#define HWCAP2_DCPODP 0x0000000000000001ul -#define HWCAP2_SVE2 0x0000000000000002ul -#define HWCAP2_SVEAES 0x0000000000000004ul -#define HWCAP2_SVEPMULL 0x0000000000000008ul -#define HWCAP2_SVEBITPERM 0x0000000000000010ul -#define HWCAP2_SVESHA3 0x0000000000000020ul -#define HWCAP2_SVESM4 0x0000000000000040ul -#define HWCAP2_FLAGM2 0x0000000000000080ul -#define HWCAP2_FRINT 0x0000000000000100ul -#define HWCAP2_SVEI8MM 0x0000000000000200ul -#define HWCAP2_SVEF32MM 0x0000000000000400ul -#define HWCAP2_SVEF64MM 0x0000000000000800ul -#define HWCAP2_SVEBF16 0x0000000000001000ul -#define HWCAP2_I8MM 0x0000000000002000ul -#define HWCAP2_BF16 0x0000000000004000ul -#define HWCAP2_DGH 0x0000000000008000ul -#define HWCAP2_RNG 0x0000000000010000ul -#define HWCAP2_BTI 0x0000000000020000ul -#define HWCAP2_MTE 0x0000000000040000ul -#define HWCAP2_ECV 0x0000000000080000ul -#define HWCAP2_AFP 0x0000000000100000ul -#define HWCAP2_RPRES 0x0000000000200000ul -#define HWCAP2_MTE3 0x0000000000400000ul -#define HWCAP2_SME 0x0000000000800000ul -#define HWCAP2_SME_I16I64 0x0000000001000000ul -#define HWCAP2_SME_F64F64 0x0000000002000000ul -#define HWCAP2_SME_I8I32 0x0000000004000000ul -#define HWCAP2_SME_F16F32 0x0000000008000000ul -#define HWCAP2_SME_B16F32 0x0000000010000000ul -#define HWCAP2_SME_F32F32 0x0000000020000000ul -#define HWCAP2_SME_FA64 0x0000000040000000ul -#define HWCAP2_WFXT 0x0000000080000000ul -#define HWCAP2_EBF16 0x0000000100000000ul -#define HWCAP2_SVE_EBF16 0x0000000200000000ul -#define HWCAP2_CSSC 0x0000000400000000ul -#define HWCAP2_RPRFM 0x0000000800000000ul -#define HWCAP2_SVE2P1 0x0000001000000000ul -#define HWCAP2_SME2 0x0000002000000000ul -#define HWCAP2_SME2P1 0x0000004000000000ul -#define HWCAP2_SME_I16I32 0x0000008000000000ul -#define HWCAP2_SME_BI32I32 0x0000010000000000ul -#define HWCAP2_SME_B16B16 0x0000020000000000ul -#define HWCAP2_SME_F16F16 0x0000040000000000ul -#define HWCAP2_MOPS 0x0000080000000000ul -#define HWCAP2_HBC 0x0000100000000000ul +#define HWCAP2_DCPODP (1 << 0) +#define HWCAP2_SVE2 (1 << 1) +#define HWCAP2_SVEAES (1 << 2) +#define HWCAP2_SVEPMULL (1 << 3) +#define HWCAP2_SVEBITPERM (1 << 4) +#define HWCAP2_SVESHA3 (1 << 5) +#define HWCAP2_SVESM4 (1 << 6) +#define HWCAP2_FLAGM2 (1 << 7) +#define HWCAP2_FRINT (1 << 8) +#define HWCAP2_SVEI8MM (1 << 9) +#define HWCAP2_SVEF32MM (1 << 10) +#define HWCAP2_SVEF64MM (1 << 11) +#define HWCAP2_SVEBF16 (1 << 12) +#define HWCAP2_I8MM (1 << 13) +#define HWCAP2_BF16 (1 << 14) +#define HWCAP2_DGH (1 << 15) +#define HWCAP2_RNG (1 << 16) +#define HWCAP2_BTI (1 << 17) +#define HWCAP2_MTE (1 << 18) +#define HWCAP2_ECV (1 << 19) +#define HWCAP2_AFP (1 << 20) +#define HWCAP2_RPRES (1 << 21) +#define HWCAP2_MTE3 (1 << 22) +#define HWCAP2_SME (1 << 23) +#define HWCAP2_SME_I16I64 (1 << 24) +#define HWCAP2_SME_F64F64 (1 << 25) +#define HWCAP2_SME_I8I32 (1 << 26) +#define HWCAP2_SME_F16F32 (1 << 27) +#define HWCAP2_SME_B16F32 (1 << 28) +#define HWCAP2_SME_F32F32 (1 << 29) +#define HWCAP2_SME_FA64 (1 << 30) +#define HWCAP2_WFXT (1UL << 31) +#define HWCAP2_EBF16 (1UL << 32) +#define HWCAP2_SVE_EBF16 (1UL << 33) +#define HWCAP2_CSSC (1UL << 34) +#define HWCAP2_RPRFM (1UL << 35) +#define HWCAP2_SVE2P1 (1UL << 36) +#define HWCAP2_SME2 (1UL << 37) +#define HWCAP2_SME2P1 (1UL << 38) +#define HWCAP2_SME_I16I32 (1UL << 39) +#define HWCAP2_SME_BI32I32 (1UL << 40) +#define HWCAP2_SME_B16B16 (1UL << 41) +#define HWCAP2_SME_F16F16 (1UL << 42) +#define HWCAP2_MOPS (1UL << 43) +#define HWCAP2_HBC (1UL << 44) +#define HWCAP2_SVE_B16B16 (1UL << 45) +#define HWCAP2_LRCPC3 (1UL << 46) +#define HWCAP2_LSE128 (1UL << 47) +#define HWCAP2_FPMR (1UL << 48) +#define HWCAP2_LUT (1UL << 49) +#define HWCAP2_FAMINMAX (1UL << 50) +#define HWCAP2_F8CVT (1UL << 51) +#define HWCAP2_F8FMA (1UL << 52) +#define HWCAP2_F8DP4 (1UL << 53) +#define HWCAP2_F8DP2 (1UL << 54) +#define HWCAP2_F8E4M3 (1UL << 55) +#define HWCAP2_F8E5M2 (1UL << 56) +#define HWCAP2_SME_LUTV2 (1UL << 57) +#define HWCAP2_SME_F8F16 (1UL << 58) +#define HWCAP2_SME_F8F32 (1UL << 59) +#define HWCAP2_SME_SF8FMA (1UL << 60) +#define HWCAP2_SME_SF8DP4 (1UL << 61) +#define HWCAP2_SME_SF8DP2 (1UL << 62) +#define HWCAP2_POE (1UL << 63) #ifdef COMPAT_FREEBSD32 /* ARM HWCAP */ diff --git a/lib/libc/include/aarch64-freebsd-none/machine/endian.h b/lib/libc/include/aarch64-freebsd-none/machine/endian.h index 69d16e3fc53c..6b21c3cb51ce 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/endian.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/endian.h @@ -24,8 +24,6 @@ * 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. - * - * @(#)endian.h 8.1 (Berkeley) 6/10/93 * $NetBSD: endian.h,v 1.7 1999/08/21 05:53:51 simonb Exp $ */ diff --git a/lib/libc/include/aarch64-freebsd-none/machine/float.h b/lib/libc/include/aarch64-freebsd-none/machine/float.h index 2ac179777457..c6f1432f6226 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/float.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/float.h @@ -25,8 +25,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)float.h 7.1 (Berkeley) 5/8/90 */ #ifdef __arm__ diff --git a/lib/libc/include/aarch64-freebsd-none/machine/frame.h b/lib/libc/include/aarch64-freebsd-none/machine/frame.h index 0f513846333c..74cdd46e67ce 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/frame.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/frame.h @@ -70,7 +70,7 @@ struct frame { #ifdef COMPAT_FREEBSD32 struct sigframe32 { - struct siginfo32 sf_si; + struct __siginfo32 sf_si; ucontext32_t sf_uc; mcontext32_vfp_t sf_vfp; }; diff --git a/lib/libc/include/aarch64-freebsd-none/machine/hypervisor.h b/lib/libc/include/aarch64-freebsd-none/machine/hypervisor.h index 210fafb16955..fbb9267675dc 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/hypervisor.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/hypervisor.h @@ -41,21 +41,38 @@ #define CNTHCTL_EL1PCTEN (1 << 0) /* Allow physical counter access */ #define CNTHCTL_EL1PCEN (1 << 1) /* Allow physical timer access */ /* Valid if HCR_EL2.E2H == 1 */ +#define CNTHCTL_E2H_EL0PCTEN (1 << 0) /* Allow EL0 physical counter access */ +#define CNTHCTL_E2H_EL0VCTEN (1 << 1) /* Allow EL0 virtual counter access */ +#define CNTHCTL_E2H_EL0VTEN (1 << 8) +#define CNTHCTL_E2H_EL0PTEN (1 << 9) #define CNTHCTL_E2H_EL1PCTEN (1 << 10) /* Allow physical counter access */ #define CNTHCTL_E2H_EL1PTEN (1 << 11) /* Allow physical timer access */ /* Unconditionally valid */ #define CNTHCTL_EVNTDIR (1 << 3) /* Control transition trigger bit */ #define CNTHCTL_EVNTEN (1 << 2) /* Enable event stream */ +/* CNTPOFF_EL2 - Counter-timer Physical Offset Register */ +#define CNTPOFF_EL2_REG MRS_REG_ALT_NAME(CNTPOFF_EL2) +#define CNTPOFF_EL2_op0 3 +#define CNTPOFF_EL2_op1 4 +#define CNTPOFF_EL2_CRn 14 +#define CNTPOFF_EL2_CRm 0 +#define CNTPOFF_EL2_op2 6 + /* CPTR_EL2 - Architecture feature trap register */ /* Valid if HCR_EL2.E2H == 0 */ +#define CPTR_TRAP_ALL 0xc01037ff /* Enable all traps */ #define CPTR_RES0 0x7fefc800 #define CPTR_RES1 0x000032ff +#define CPTR_TZ 0x00000100 #define CPTR_TFP 0x00000400 +#define CPTR_TTA 0x00100000 /* Valid if HCR_EL2.E2H == 1 */ -#define CPTR_FPEN 0x00300000 +#define CPTR_E2H_TRAP_ALL 0xd0000000 +#define CPTR_E2H_ZPEN 0x00030000 +#define CPTR_E2H_FPEN 0x00300000 +#define CPTR_E2H_TTA 0x10000000 /* Unconditionally valid */ -#define CPTR_TTA 0x00100000 #define CPTR_TCPAC 0x80000000 /* HCR_EL2 - Hypervisor Config Register */ @@ -123,6 +140,41 @@ #define HCR_TWEDEn (UL(0x1) << 59) #define HCR_TWEDEL_MASK (UL(0xf) << 60) +/* HCRX_EL2 - Extended Hypervisor Configuration Register */ +#define HCRX_EL2_REG MRS_REG_ALT_NAME(HCRX_EL2) +#define HCRX_EL2_op0 3 +#define HCRX_EL2_op1 4 +#define HCRX_EL2_CRn 1 +#define HCRX_EL2_CRm 2 +#define HCRX_EL2_op2 2 + +#define HCRX_EnAS0 (UL(0x1) << 0) +#define HCRX_EnALS (UL(0x1) << 1) +#define HCRX_EnASR (UL(0x1) << 2) +#define HCRX_FnXS (UL(0x1) << 3) +#define HCRX_FGTnXS (UL(0x1) << 4) +#define HCRX_SMPME (UL(0x1) << 5) +#define HCRX_TALLINT (UL(0x1) << 6) +#define HCRX_VINMI (UL(0x1) << 7) +#define HCRX_VFNMI (UL(0x1) << 8) +#define HCRX_CMOW (UL(0x1) << 9) +#define HCRX_MCE2 (UL(0x1) << 10) +#define HCRX_MSCEn (UL(0x1) << 11) +/* Bits 12 & 13 are reserved */ +#define HCRX_TCR2En (UL(0x1) << 14) +#define HCRX_SCTLR2En (UL(0x1) << 15) +#define HCRX_PTTWI (UL(0x1) << 16) +#define HCRX_D128En (UL(0x1) << 17) +#define HCRX_EnSNERR (UL(0x1) << 18) +#define HCRX_TMEA (UL(0x1) << 19) +#define HCRX_EnSDERR (UL(0x1) << 20) +#define HCRX_EnIDCP128 (UL(0x1) << 21) +#define HCRX_GCSEn (UL(0x1) << 22) +#define HCRX_EnFPM (UL(0x1) << 23) +#define HCRX_PACMEn (UL(0x1) << 24) +/* Bit 25 is reserved */ +#define HCRX_SRMASKEn (UL(0x1) << 26) + /* HPFAR_EL2 - Hypervisor IPA Fault Address Register */ #define HPFAR_EL2_FIPA_SHIFT 4 #define HPFAR_EL2_FIPA_MASK 0xfffffffff0 @@ -138,6 +190,54 @@ #define ICC_SRE_EL2_SRE (1UL << 0) #define ICC_SRE_EL2_EN (1UL << 3) +/* MDCR_EL2 - Hyp Debug Control Register */ +#define MDCR_EL2_HPMN_MASK 0x1f +#define MDCR_EL2_HPMN_SHIFT 0 +#define MDCR_EL2_TPMCR_SHIFT 5 +#define MDCR_EL2_TPMCR (0x1UL << MDCR_EL2_TPMCR_SHIFT) +#define MDCR_EL2_TPM_SHIFT 6 +#define MDCR_EL2_TPM (0x1UL << MDCR_EL2_TPM_SHIFT) +#define MDCR_EL2_HPME_SHIFT 7 +#define MDCR_EL2_HPME (0x1UL << MDCR_EL2_HPME_SHIFT) +#define MDCR_EL2_TDE_SHIFT 8 +#define MDCR_EL2_TDE (0x1UL << MDCR_EL2_TDE_SHIFT) +#define MDCR_EL2_TDA_SHIFT 9 +#define MDCR_EL2_TDA (0x1UL << MDCR_EL2_TDA_SHIFT) +#define MDCR_EL2_TDOSA_SHIFT 10 +#define MDCR_EL2_TDOSA (0x1UL << MDCR_EL2_TDOSA_SHIFT) +#define MDCR_EL2_TDRA_SHIFT 11 +#define MDCR_EL2_TDRA (0x1UL << MDCR_EL2_TDRA_SHIFT) +#define MDCR_EL2_E2PB_SHIFT 12 +#define MDCR_EL2_E2PB_MASK (0x3UL << MDCR_EL2_E2PB_SHIFT) +#define MDCR_EL2_TPMS_SHIFT 14 +#define MDCR_EL2_TPMS (0x1UL << MDCR_EL2_TPMS_SHIFT) +#define MDCR_EL2_EnSPM_SHIFT 15 +#define MDCR_EL2_EnSPM (0x1UL << MDCR_EL2_EnSPM_SHIFT) +#define MDCR_EL2_HPMD_SHIFT 17 +#define MDCR_EL2_HPMD (0x1UL << MDCR_EL2_HPMD_SHIFT) +#define MDCR_EL2_TTRF_SHIFT 19 +#define MDCR_EL2_TTRF (0x1UL << MDCR_EL2_TTRF_SHIFT) +#define MDCR_EL2_HCCD_SHIFT 23 +#define MDCR_EL2_HCCD (0x1UL << MDCR_EL2_HCCD_SHIFT) +#define MDCR_EL2_E2TB_SHIFT 24 +#define MDCR_EL2_E2TB_MASK (0x3UL << MDCR_EL2_E2TB_SHIFT) +#define MDCR_EL2_HLP_SHIFT 26 +#define MDCR_EL2_HLP (0x1UL << MDCR_EL2_HLP_SHIFT) +#define MDCR_EL2_TDCC_SHIFT 27 +#define MDCR_EL2_TDCC (0x1UL << MDCR_EL2_TDCC_SHIFT) +#define MDCR_EL2_MTPME_SHIFT 28 +#define MDCR_EL2_MTPME (0x1UL << MDCR_EL2_MTPME_SHIFT) +#define MDCR_EL2_HPMFZO_SHIFT 29 +#define MDCR_EL2_HPMFZO (0x1UL << MDCR_EL2_HPMFZO_SHIFT) +#define MDCR_EL2_PMSSE_SHIFT 30 +#define MDCR_EL2_PMSSE_MASK (0x3UL << MDCR_EL2_PMSSE_SHIFT) +#define MDCR_EL2_HPMFZS_SHIFT 36 +#define MDCR_EL2_HPMFZS (0x1UL << MDCR_EL2_HPMFZS_SHIFT) +#define MDCR_EL2_PMEE_SHIFT 40 +#define MDCR_EL2_PMEE_MASK (0x3UL << MDCR_EL2_PMEE_SHIFT) +#define MDCR_EL2_EBWE_SHIFT 43 +#define MDCR_EL2_EBWE (0x1UL << MDCR_EL2_EBWE_SHIFT) + /* SCTLR_EL2 - System Control Register */ #define SCTLR_EL2_RES1 0x30c50830 #define SCTLR_EL2_M_SHIFT 0 @@ -237,6 +337,9 @@ #define VTCR_EL2_PS_42BIT (0x3UL << VTCR_EL2_PS_SHIFT) #define VTCR_EL2_PS_44BIT (0x4UL << VTCR_EL2_PS_SHIFT) #define VTCR_EL2_PS_48BIT (0x5UL << VTCR_EL2_PS_SHIFT) +#define VTCR_EL2_PS_52BIT (0x6UL << VTCR_EL2_PS_SHIFT) +#define VTCR_EL2_DS_SHIFT 32 +#define VTCR_EL2_DS (0x1UL << VTCR_EL2_DS_SHIFT) /* VTTBR_EL2 - Virtualization Translation Table Base Register */ #define VTTBR_VMID_MASK 0xffff000000000000 @@ -244,52 +347,4 @@ /* Assumed to be 0 by locore.S */ #define VTTBR_HOST 0x0000000000000000 -/* MDCR_EL2 - Hyp Debug Control Register */ -#define MDCR_EL2_HPMN_MASK 0x1f -#define MDCR_EL2_HPMN_SHIFT 0 -#define MDCR_EL2_TPMCR_SHIFT 5 -#define MDCR_EL2_TPMCR (0x1UL << MDCR_EL2_TPMCR_SHIFT) -#define MDCR_EL2_TPM_SHIFT 6 -#define MDCR_EL2_TPM (0x1UL << MDCR_EL2_TPM_SHIFT) -#define MDCR_EL2_HPME_SHIFT 7 -#define MDCR_EL2_HPME (0x1UL << MDCR_EL2_HPME_SHIFT) -#define MDCR_EL2_TDE_SHIFT 8 -#define MDCR_EL2_TDE (0x1UL << MDCR_EL2_TDE_SHIFT) -#define MDCR_EL2_TDA_SHIFT 9 -#define MDCR_EL2_TDA (0x1UL << MDCR_EL2_TDA_SHIFT) -#define MDCR_EL2_TDOSA_SHIFT 10 -#define MDCR_EL2_TDOSA (0x1UL << MDCR_EL2_TDOSA_SHIFT) -#define MDCR_EL2_TDRA_SHIFT 11 -#define MDCR_EL2_TDRA (0x1UL << MDCR_EL2_TDRA_SHIFT) -#define MDCR_E2PB_SHIFT 12 -#define MDCR_E2PB_MASK (0x3UL << MDCR_E2PB_SHIFT) -#define MDCR_TPMS_SHIFT 14 -#define MDCR_TPMS (0x1UL << MDCR_TPMS_SHIFT) -#define MDCR_EnSPM_SHIFT 15 -#define MDCR_EnSPM (0x1UL << MDCR_EnSPM_SHIFT) -#define MDCR_HPMD_SHIFT 17 -#define MDCR_HPMD (0x1UL << MDCR_HPMD_SHIFT) -#define MDCR_TTRF_SHIFT 19 -#define MDCR_TTRF (0x1UL << MDCR_TTRF_SHIFT) -#define MDCR_HCCD_SHIFT 23 -#define MDCR_HCCD (0x1UL << MDCR_HCCD_SHIFT) -#define MDCR_E2TB_SHIFT 24 -#define MDCR_E2TB_MASK (0x3UL << MDCR_E2TB_SHIFT) -#define MDCR_HLP_SHIFT 26 -#define MDCR_HLP (0x1UL << MDCR_HLP_SHIFT) -#define MDCR_TDCC_SHIFT 27 -#define MDCR_TDCC (0x1UL << MDCR_TDCC_SHIFT) -#define MDCR_MTPME_SHIFT 28 -#define MDCR_MTPME (0x1UL << MDCR_MTPME_SHIFT) -#define MDCR_HPMFZO_SHIFT 29 -#define MDCR_HPMFZO (0x1UL << MDCR_HPMFZO_SHIFT) -#define MDCR_PMSSE_SHIFT 30 -#define MDCR_PMSSE_MASK (0x3UL << MDCR_PMSSE_SHIFT) -#define MDCR_HPMFZS_SHIFT 36 -#define MDCR_HPMFZS (0x1UL << MDCR_HPMFZS_SHIFT) -#define MDCR_PMEE_SHIFT 40 -#define MDCR_PMEE_MASK (0x3UL << MDCR_PMEE_SHIFT) -#define MDCR_EBWE_SHIFT 43 -#define MDCR_EBWE (0x1UL << MDCR_EBWE_SHIFT) - #endif /* !_MACHINE_HYPERVISOR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-freebsd-none/machine/in_cksum.h b/lib/libc/include/aarch64-freebsd-none/machine/in_cksum.h index b6519929ca3c..ad5bd81eae39 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/in_cksum.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/in_cksum.h @@ -27,7 +27,6 @@ * SUCH DAMAGE. * * from tahoe: in_cksum.c 1.2 86/01/05 - * from: @(#)in_cksum.c 1.3 (Berkeley) 1/19/91 * from: Id: in_cksum.c,v 1.8 1995/12/03 18:35:19 bde Exp */ diff --git a/lib/libc/include/aarch64-freebsd-none/machine/intr.h b/lib/libc/include/aarch64-freebsd-none/machine/intr.h index de9bf6b658d4..533b60b3a1ab 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/intr.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/intr.h @@ -27,20 +27,20 @@ #ifndef _MACHINE_INTR_H_ #define _MACHINE_INTR_H_ +#ifndef LOCORE #ifdef FDT #include #endif -#include - -#ifndef NIRQ -#define NIRQ 16384 /* XXX - It should be an option. */ -#endif - static inline void arm_irq_memory_barrier(uintptr_t irq) { } +#endif /* !LOCORE */ + +#ifndef NIRQ +#define NIRQ 16384 /* XXX - It should be an option. */ +#endif #ifdef DEV_ACPI #define ACPI_INTR_XREF 1 @@ -48,4 +48,8 @@ arm_irq_memory_barrier(uintptr_t irq) #define ACPI_GPIO_XREF 3 #endif +#define INTR_ROOT_IRQ 0 +#define INTR_ROOT_FIQ 1 +#define INTR_ROOT_COUNT 2 + #endif /* _MACHINE_INTR_H */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-freebsd-none/machine/kdb.h b/lib/libc/include/aarch64-freebsd-none/machine/kdb.h index b7799037867c..3ab07f98145c 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/kdb.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/kdb.h @@ -37,6 +37,8 @@ void kdb_cpu_clear_singlestep(void); void kdb_cpu_set_singlestep(void); +int kdb_cpu_set_breakpoint(vm_offset_t addr); +int kdb_cpu_clr_breakpoint(vm_offset_t addr); int kdb_cpu_set_watchpoint(vm_offset_t addr, size_t size, int access); int kdb_cpu_clr_watchpoint(vm_offset_t addr, size_t size); @@ -44,7 +46,7 @@ static __inline void kdb_cpu_sync_icache(unsigned char *addr, size_t size) { - cpu_icache_sync_range((vm_offset_t)addr, size); + cpu_icache_sync_range(addr, size); } static __inline void diff --git a/lib/libc/include/aarch64-freebsd-none/machine/machdep.h b/lib/libc/include/aarch64-freebsd-none/machine/machdep.h index c965e4c2a0fb..0718e65b2faa 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/machdep.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/machdep.h @@ -33,7 +33,6 @@ struct arm64_bootparams { vm_offset_t modulep; vm_offset_t kern_stack; vm_paddr_t kern_ttbr0; - uint64_t hcr_el2; int boot_el; /* EL the kernel booted from */ int pad; }; @@ -48,6 +47,7 @@ extern enum arm64_bus arm64_bus_method; void dbg_init(void); bool has_hyp(void); +bool in_vhe(void); void initarm(struct arm64_bootparams *); vm_offset_t parse_boot_param(struct arm64_bootparams *abp); #ifdef FDT diff --git a/lib/libc/include/aarch64-freebsd-none/machine/md_var.h b/lib/libc/include/aarch64-freebsd-none/machine/md_var.h index 8cb7e019467e..169160928adb 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/md_var.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/md_var.h @@ -37,8 +37,12 @@ extern char sigcode[]; extern int szsigcode; extern u_long elf_hwcap; extern u_long elf_hwcap2; +extern u_long elf_hwcap3; +extern u_long elf_hwcap4; extern u_long linux_elf_hwcap; extern u_long linux_elf_hwcap2; +extern u_long linux_elf_hwcap3; +extern u_long linux_elf_hwcap4; #ifdef COMPAT_FREEBSD32 extern u_long elf32_hwcap; extern u_long elf32_hwcap2; diff --git a/lib/libc/include/aarch64-freebsd-none/machine/metadata.h b/lib/libc/include/aarch64-freebsd-none/machine/metadata.h index 51c438678781..b0f7670be581 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/metadata.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/metadata.h @@ -31,10 +31,15 @@ #define MODINFOMD_DTBP 0x1002 #define MODINFOMD_EFI_FB 0x1003 +/* + * This is not the same as the UEFI standard EFI_MEMORY_ATTRIBUTES_TABLE, though + * memory_size / descritpr_size entries of EFI_MEMORY_DESCRIPTORS follow this table + * starting at a 16-byte alignment. + */ struct efi_map_header { - size_t memory_size; - size_t descriptor_size; - uint32_t descriptor_version; + size_t memory_size; /* Numnber of bytes that follow */ + size_t descriptor_size; /* Size of each EFI_MEMORY_DESCRIPTOR */ + uint32_t descriptor_version; /* Currently '1' */ }; struct efi_fb { diff --git a/lib/libc/include/aarch64-freebsd-none/machine/msan.h b/lib/libc/include/aarch64-freebsd-none/machine/msan.h new file mode 100644 index 000000000000..a114188b9084 --- /dev/null +++ b/lib/libc/include/aarch64-freebsd-none/machine/msan.h @@ -0,0 +1,91 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2021 The FreeBSD Foundation + * Copyright (c) 2023 Juniper Networks, Inc. + * + * This software was developed by Mark Johnston 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 _MACHINE_MSAN_H_ +#define _MACHINE_MSAN_H_ + +#ifdef KMSAN + +#include +#include +#include +#include + +typedef uint32_t msan_orig_t; + +/* + * Our 32-bit origin cells encode a 2-bit type and 30-bit pointer to a kernel + * instruction. The pointer is compressed by making it a positive offset + * relative to KERNBASE. + */ +#define KMSAN_ORIG_TYPE_SHIFT 30u +#define KMSAN_ORIG_PTR_MASK ((1ul << KMSAN_ORIG_TYPE_SHIFT) - 1) + +static inline msan_orig_t +kmsan_md_orig_encode(int type, uintptr_t ptr) +{ + return ((type << KMSAN_ORIG_TYPE_SHIFT) | + ((ptr & KMSAN_ORIG_PTR_MASK))); +} + +static inline void +kmsan_md_orig_decode(msan_orig_t orig, int *type, uintptr_t *ptr) +{ + *type = orig >> KMSAN_ORIG_TYPE_SHIFT; + *ptr = (orig & KMSAN_ORIG_PTR_MASK) | KERNBASE; +} + +static inline vm_offset_t +kmsan_md_addr_to_shad(vm_offset_t addr) +{ + return (addr - VM_MIN_KERNEL_ADDRESS + KMSAN_SHAD_MIN_ADDRESS); +} + +static inline vm_offset_t +kmsan_md_addr_to_orig(vm_offset_t addr) +{ + return (addr - VM_MIN_KERNEL_ADDRESS + KMSAN_ORIG_MIN_ADDRESS); +} + +static inline bool +kmsan_md_unsupported(vm_offset_t addr) +{ + /* + * It would be cheaper to use VM_MAX_KERNEL_ADDRESS as the upper bound, + * but we need to exclude device mappings above kernel_vm_end but within + * the kernel map. + */ + return (addr < VM_MIN_KERNEL_ADDRESS || addr >= kernel_vm_end); +} + +#endif /* KMSAN */ + +#endif /* !_MACHINE_MSAN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-freebsd-none/machine/param.h b/lib/libc/include/aarch64-freebsd-none/machine/param.h index 17231651acca..007c5d5c2e83 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/param.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/param.h @@ -25,8 +25,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)param.h 5.8 (Berkeley) 6/28/91 */ #ifdef __arm__ @@ -45,8 +43,6 @@ #define STACKALIGNBYTES (16 - 1) #define STACKALIGN(p) ((uint64_t)(p) & ~STACKALIGNBYTES) -#define __PCI_REROUTE_INTERRUPT - #ifndef MACHINE #define MACHINE "arm64" #endif @@ -99,7 +95,7 @@ #define PAGE_SIZE (1 << PAGE_SHIFT) #define PAGE_MASK (PAGE_SIZE - 1) -#define MAXPAGESIZES 3 /* maximum number of supported page sizes */ +#define MAXPAGESIZES 4 /* maximum number of supported page sizes */ #ifndef KSTACK_PAGES #if defined(KASAN) || defined(KMSAN) @@ -121,17 +117,9 @@ /* * Mach derived conversion macros */ -#define round_page(x) (((unsigned long)(x) + PAGE_MASK) & ~PAGE_MASK) -#define trunc_page(x) ((unsigned long)(x) & ~PAGE_MASK) - -#define atop(x) ((unsigned long)(x) >> PAGE_SHIFT) -#define ptoa(x) ((unsigned long)(x) << PAGE_SHIFT) - #define arm64_btop(x) ((unsigned long)(x) >> PAGE_SHIFT) #define arm64_ptob(x) ((unsigned long)(x) << PAGE_SHIFT) -#define pgtok(x) ((unsigned long)(x) * (PAGE_SIZE / 1024)) - #endif /* !_MACHINE_PARAM_H_ */ #endif /* !__arm__ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-freebsd-none/machine/pci_cfgreg.h b/lib/libc/include/aarch64-freebsd-none/machine/pci_cfgreg.h index aa986363e56b..4411dcb6655f 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/pci_cfgreg.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/pci_cfgreg.h @@ -27,10 +27,7 @@ #define _MACHINE_PCI_CFGREG_H int pci_cfgregopen(void); -uint32_t pci_cfgregread_domain(int, int, int, int, int, int); -void pci_cfgregwrite_domain(int, int, int, int, int, uint32_t, int); - -#define pci_cfgregread pci_cfgregread_domain -#define pci_cfgregwrite pci_cfgregwrite_domain +uint32_t pci_cfgregread(int, int, int, int, int, int); +void pci_cfgregwrite(int, int, int, int, int, uint32_t, int); #endif /* !_MACHINE_PCI_CFGREG_H */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-freebsd-none/machine/pcpu.h b/lib/libc/include/aarch64-freebsd-none/machine/pcpu.h index db47829a86a0..3ef9e6e6ae07 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/pcpu.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/pcpu.h @@ -48,7 +48,6 @@ struct debug_monitor_state; pcpu_ssbd pc_ssbd; \ struct pmap *pc_curpmap; \ struct pmap *pc_curvmpmap; \ - /* Store as two u_int values to preserve KBI */ \ uint64_t pc_mpidr; \ u_int pc_bcast_tlbi_workaround; \ char __pad[197] diff --git a/lib/libc/include/aarch64-freebsd-none/machine/pmap.h b/lib/libc/include/aarch64-freebsd-none/machine/pmap.h index df4161fa9d8d..80b03e3bf57d 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/pmap.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/pmap.h @@ -63,10 +63,13 @@ void pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma); * Pmap stuff */ +struct rangeset; + struct md_page { TAILQ_HEAD(,pv_entry) pv_list; int pv_gen; vm_memattr_t pv_memattr; + uint8_t pv_reserve[3]; }; enum pmap_stage { @@ -87,7 +90,8 @@ struct pmap { struct asid_set *pm_asid_set; /* The ASID/VMID set to use */ enum pmap_stage pm_stage; int pm_levels; - uint64_t pm_reserved[4]; + struct rangeset *pm_bti; + uint64_t pm_reserved[3]; }; typedef struct pmap *pmap_t; @@ -98,6 +102,8 @@ extern struct pmap kernel_pmap_store; #define kernel_pmap (&kernel_pmap_store) #define pmap_kernel() kernel_pmap +extern bool pmap_lpa_enabled; + #define PMAP_ASSERT_LOCKED(pmap) \ mtx_assert(&(pmap)->pm_mtx, MA_OWNED) #define PMAP_LOCK(pmap) mtx_lock(&(pmap)->pm_mtx) @@ -124,6 +130,8 @@ extern struct pmap kernel_pmap_store; extern vm_offset_t virtual_avail; extern vm_offset_t virtual_end; +extern pt_entry_t pmap_sh_attr; + /* * Macros to test if a mapping is mappable with an L1 Section mapping * or an L2 Large Page mapping. @@ -134,7 +142,8 @@ extern vm_offset_t virtual_end; #define pmap_vm_page_alloc_check(m) void pmap_activate_vm(pmap_t); -void pmap_bootstrap(vm_size_t); +void pmap_bootstrap_dmap(vm_size_t); +void pmap_bootstrap(void); int pmap_change_attr(vm_offset_t va, vm_size_t size, int mode); int pmap_change_prot(vm_offset_t va, vm_size_t size, vm_prot_t prot); void pmap_kenter(vm_offset_t sva, vm_size_t size, vm_paddr_t pa, int mode); @@ -166,18 +175,17 @@ int pmap_fault(pmap_t, uint64_t, uint64_t); struct pcb *pmap_switch(struct thread *); +void pmap_s1_invalidate_all_kernel(void); + extern void (*pmap_clean_stage2_tlbi)(void); -extern void (*pmap_invalidate_vpipt_icache)(void); extern void (*pmap_stage2_invalidate_range)(uint64_t, vm_offset_t, vm_offset_t, bool); extern void (*pmap_stage2_invalidate_all)(uint64_t); -static inline int -pmap_vmspace_copy(pmap_t dst_pmap __unused, pmap_t src_pmap __unused) -{ +int pmap_vmspace_copy(pmap_t, pmap_t); - return (0); -} +int pmap_bti_set(pmap_t, vm_offset_t, vm_offset_t); +int pmap_bti_clear(pmap_t, vm_offset_t, vm_offset_t); #if defined(KASAN) || defined(KMSAN) struct arm64_bootparams; diff --git a/lib/libc/include/aarch64-freebsd-none/machine/proc.h b/lib/libc/include/aarch64-freebsd-none/machine/proc.h index 9755856a8f08..fb5f34e59172 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/proc.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/proc.h @@ -25,8 +25,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)proc.h 7.1 (Berkeley) 5/15/91 * from: FreeBSD: src/sys/i386/include/proc.h,v 1.11 2001/06/29 */ @@ -37,6 +35,7 @@ #ifndef _MACHINE_PROC_H_ #define _MACHINE_PROC_H_ +#ifndef LOCORE struct ptrauth_key { uint64_t pa_key_lo; uint64_t pa_key_hi; @@ -67,12 +66,21 @@ struct mdthread { struct ptrauth_key apia; } md_ptrauth_kern; - uint64_t md_reserved[4]; + uint64_t md_efirt_tmp; + int md_efirt_dis_pf; + + int md_reserved0; + uint64_t md_reserved[2]; }; struct mdproc { - long md_dummy; + uint64_t md_tcr; /* TCR_EL1 fields to update */ + uint64_t md_reserved[2]; }; +#endif /* !LOCORE */ + +/* Fields that can be set in md_tcr */ +#define MD_TCR_FIELDS TCR_TBI0 #define KINFO_PROC_SIZE 1088 #define KINFO_PROC32_SIZE 816 diff --git a/lib/libc/include/aarch64-freebsd-none/machine/pte.h b/lib/libc/include/aarch64-freebsd-none/machine/pte.h index 8c1eb5732745..4c7e288e4031 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/pte.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/pte.h @@ -54,13 +54,6 @@ typedef uint64_t pt_entry_t; /* page table entry */ #define ATTR_MASK_L UINT64_C(0x0000000000000fff) #define ATTR_MASK (ATTR_MASK_H | ATTR_MASK_L) -#define BASE_MASK ~ATTR_MASK -#define BASE_ADDR(x) ((x) & BASE_MASK) - -#define PTE_TO_PHYS(pte) BASE_ADDR(pte) -/* Convert a phys addr to the output address field of a PTE */ -#define PHYS_TO_PTE(pa) (pa) - /* Bits 58:55 are reserved for software */ #define ATTR_SW_UNUSED1 (1UL << 58) #define ATTR_SW_NO_PROMOTE (1UL << 57) @@ -80,13 +73,37 @@ typedef uint64_t pt_entry_t; /* page table entry */ #define ATTR_CONTIGUOUS (1UL << 52) #define ATTR_DBM (1UL << 51) +#define ATTR_S1_GP_SHIFT 50 +#define ATTR_S1_GP (1UL << ATTR_S1_GP_SHIFT) + +/* + * Largest possible output address field for a level 3 page. Block + * entries will use fewer low address bits, but these are res0 so + * should be safe to include. + * + * This is also safe to use for the next-level table address for + * table entries as they encode a physical address in the same way. + */ +#if PAGE_SIZE == PAGE_SIZE_4K +#define ATTR_ADDR UINT64_C(0x0003fffffffff000) +#elif PAGE_SIZE == PAGE_SIZE_16K +#define ATTR_ADDR UINT64_C(0x0003ffffffffc000) +#else +#error Unsupported page size +#endif + #define ATTR_S1_nG (1 << 11) #define ATTR_AF (1 << 10) +/* When TCR_EL1.DS == 0 */ #define ATTR_SH(x) ((x) << 8) #define ATTR_SH_MASK ATTR_SH(3) #define ATTR_SH_NS 0 /* Non-shareable */ #define ATTR_SH_OS 2 /* Outer-shareable */ #define ATTR_SH_IS 3 /* Inner-shareable */ +/* When TCR_EL1.DS == 1 */ +#define ATTR_OA_51_50_SHIFT 8 +#define ATTR_OA_51_50_MASK (3 << ATTR_OA_51_50_SHIFT) +#define ATTR_OA_51_50_DELTA (50 - 8) /* Delta from address to pte */ #define ATTR_S1_AP_RW_BIT (1 << 7) #define ATTR_S1_AP(x) ((x) << 6) @@ -110,8 +127,6 @@ typedef uint64_t pt_entry_t; /* page table entry */ #define ATTR_S2_MEMATTR_WT 0xa #define ATTR_S2_MEMATTR_WB 0xf -#define ATTR_DEFAULT (ATTR_AF | ATTR_SH(ATTR_SH_IS)) - #define ATTR_DESCR_MASK 3 #define ATTR_DESCR_VALID 1 #define ATTR_DESCR_TYPE_MASK 2 @@ -119,6 +134,35 @@ typedef uint64_t pt_entry_t; /* page table entry */ #define ATTR_DESCR_TYPE_PAGE 2 #define ATTR_DESCR_TYPE_BLOCK 0 +/* + * Superpage promotion requires that the bits specified by the following + * mask all be identical in the constituent PTEs. + */ +#define ATTR_PROMOTE (ATTR_MASK & ~(ATTR_CONTIGUOUS | ATTR_AF)) + +/* Read the output address or next-level table address from a PTE */ +#define PTE_TO_PHYS(x) ({ \ + pt_entry_t _pte = (x); \ + vm_paddr_t _pa; \ + _pa = _pte & ATTR_ADDR; \ + if (pmap_lpa_enabled) \ + _pa |= (_pte & ATTR_OA_51_50_MASK) << ATTR_OA_51_50_DELTA; \ + _pa; \ +}) + +/* + * Convert a physical address to an output address or next-level + * table address in a PTE + */ +#define PHYS_TO_PTE(x) ({ \ + vm_paddr_t _pa = (x); \ + pt_entry_t _pte; \ + _pte = _pa & ATTR_ADDR; \ + if (pmap_lpa_enabled) \ + _pte |= (_pa >> ATTR_OA_51_50_DELTA) & ATTR_OA_51_50_MASK; \ + _pte; \ +}) + #if PAGE_SIZE == PAGE_SIZE_4K #define L0_SHIFT 39 #define L1_SHIFT 30 @@ -186,6 +230,26 @@ typedef uint64_t pt_entry_t; /* page table entry */ #define Ln_ADDR_MASK (Ln_ENTRIES - 1) #define Ln_TABLE_MASK ((1 << 12) - 1) +/* + * The number of contiguous Level 3 entries (with ATTR_CONTIGUOUS set) that + * can be coalesced into a single TLB entry + */ +#if PAGE_SIZE == PAGE_SIZE_4K +#define L2C_ENTRIES 16 +#define L3C_ENTRIES 16 +#elif PAGE_SIZE == PAGE_SIZE_16K +#define L2C_ENTRIES 32 +#define L3C_ENTRIES 128 +#else +#error Unsupported page size +#endif + +#define L2C_SIZE (L2C_ENTRIES * L2_SIZE) +#define L2C_OFFSET (L2C_SIZE - 1) + +#define L3C_SIZE (L3C_ENTRIES * L3_SIZE) +#define L3C_OFFSET (L3C_SIZE - 1) + #define pmap_l0_index(va) (((va) >> L0_SHIFT) & L0_ADDR_MASK) #define pmap_l1_index(va) (((va) >> L1_SHIFT) & Ln_ADDR_MASK) #define pmap_l2_index(va) (((va) >> L2_SHIFT) & Ln_ADDR_MASK) diff --git a/lib/libc/include/aarch64-freebsd-none/machine/resource.h b/lib/libc/include/aarch64-freebsd-none/machine/resource.h index 2529c90f28d2..22815ed321cb 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/resource.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/resource.h @@ -44,9 +44,7 @@ #define SYS_RES_MEMORY 3 /* i/o memory */ #define SYS_RES_IOPORT 4 /* i/o ports */ #define SYS_RES_GPIO 5 /* general purpose i/o */ -#ifdef NEW_PCIB #define PCI_RES_BUS 6 /* PCI bus numbers */ -#endif #endif /* !_MACHINE_RESOURCE_H_ */ diff --git a/lib/libc/include/aarch64-freebsd-none/machine/runq.h b/lib/libc/include/aarch64-freebsd-none/machine/runq.h deleted file mode 100644 index 77ea2d30dede..000000000000 --- a/lib/libc/include/aarch64-freebsd-none/machine/runq.h +++ /dev/null @@ -1,50 +0,0 @@ -/*- - * Copyright (c) 2001 Jake Burkholder - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifdef __arm__ -#include -#else /* !__arm__ */ - -#ifndef _MACHINE_RUNQ_H_ -#define _MACHINE_RUNQ_H_ - -#define RQB_LEN (1) /* Number of priority status words. */ -#define RQB_L2BPW (6) /* Log2(sizeof(rqb_word_t) * NBBY)). */ -#define RQB_BPW (1<> RQB_L2BPW) - -#define RQB_FFS(word) (ffsl(word) - 1) - -/* - * Type of run queue status word. - */ -typedef unsigned long rqb_word_t; - -#endif - -#endif /* !__arm__ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-freebsd-none/machine/signal.h b/lib/libc/include/aarch64-freebsd-none/machine/signal.h index 3463dae38316..59db752c5bc1 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/signal.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/signal.h @@ -25,8 +25,6 @@ * 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. - * - * @(#)signal.h 8.1 (Berkeley) 6/11/93 * from: FreeBSD: src/sys/i386/include/signal.h,v 1.13 2000/11/09 * from: FreeBSD: src/sys/sparc64/include/signal.h,v 1.6 2001/09/30 18:52:17 */ diff --git a/lib/libc/include/aarch64-freebsd-none/machine/sysarch.h b/lib/libc/include/aarch64-freebsd-none/machine/sysarch.h index 35fa7faa2e77..b82e8d908418 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/sysarch.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/sysarch.h @@ -39,6 +39,15 @@ #ifndef _MACHINE_SYSARCH_H_ #define _MACHINE_SYSARCH_H_ +#include + +#define ARM64_GUARD_PAGE 0x100 + +struct arm64_guard_page_args { + __uintptr_t addr; + __size_t len; +}; + #define ARM64_GET_SVE_VL 0x200 /* Reserved ARM64_SET_SVE_VL 0x201 */ diff --git a/lib/libc/include/aarch64-freebsd-none/machine/undefined.h b/lib/libc/include/aarch64-freebsd-none/machine/undefined.h index f1e6c5a1a9ae..1611769fd8d0 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/undefined.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/undefined.h @@ -35,31 +35,17 @@ typedef int (*undef_handler_t)(vm_offset_t, uint32_t, struct trapframe *, uint32_t); - -static inline int -mrs_Op0(uint32_t insn) -{ - - /* op0 is encoded without the top bit in a mrs instruction */ - return (2 | ((insn & MRS_Op0_MASK) >> MRS_Op0_SHIFT)); -} - -#define MRS_GET(op) \ -static inline int \ -mrs_##op(uint32_t insn) \ -{ \ - \ - return ((insn & MRS_##op##_MASK) >> MRS_##op##_SHIFT); \ -} -MRS_GET(Op1) -MRS_GET(CRn) -MRS_GET(CRm) -MRS_GET(Op2) +typedef bool (*undef_sys_handler_t)(uint64_t, struct trapframe *); void undef_init(void); -void *install_undef_handler(bool, undef_handler_t); +void install_sys_handler(undef_sys_handler_t); +void *install_undef_handler(undef_handler_t); +#ifdef COMPAT_FREEBSD32 +void *install_undef32_handler(undef_handler_t); +#endif void remove_undef_handler(void *); -int undef_insn(u_int, struct trapframe *); +bool undef_sys(uint64_t, struct trapframe *); +int undef_insn(struct trapframe *); #endif /* _KERNEL */ diff --git a/lib/libc/include/aarch64-freebsd-none/machine/vmm.h b/lib/libc/include/aarch64-freebsd-none/machine/vmm.h new file mode 100644 index 000000000000..ffb4a9d2c2df --- /dev/null +++ b/lib/libc/include/aarch64-freebsd-none/machine/vmm.h @@ -0,0 +1,348 @@ +/* + * Copyright (C) 2015 Mihai Carabas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY 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 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 _VMM_H_ +#define _VMM_H_ + +#include +#include +#include +#include + +#include "pte.h" +#include "pmap.h" + +struct vcpu; + +enum vm_suspend_how { + VM_SUSPEND_NONE, + VM_SUSPEND_RESET, + VM_SUSPEND_POWEROFF, + VM_SUSPEND_HALT, + VM_SUSPEND_DESTROY, + VM_SUSPEND_LAST +}; + +/* + * Identifiers for architecturally defined registers. + */ +enum vm_reg_name { + VM_REG_GUEST_X0 = 0, + VM_REG_GUEST_X1, + VM_REG_GUEST_X2, + VM_REG_GUEST_X3, + VM_REG_GUEST_X4, + VM_REG_GUEST_X5, + VM_REG_GUEST_X6, + VM_REG_GUEST_X7, + VM_REG_GUEST_X8, + VM_REG_GUEST_X9, + VM_REG_GUEST_X10, + VM_REG_GUEST_X11, + VM_REG_GUEST_X12, + VM_REG_GUEST_X13, + VM_REG_GUEST_X14, + VM_REG_GUEST_X15, + VM_REG_GUEST_X16, + VM_REG_GUEST_X17, + VM_REG_GUEST_X18, + VM_REG_GUEST_X19, + VM_REG_GUEST_X20, + VM_REG_GUEST_X21, + VM_REG_GUEST_X22, + VM_REG_GUEST_X23, + VM_REG_GUEST_X24, + VM_REG_GUEST_X25, + VM_REG_GUEST_X26, + VM_REG_GUEST_X27, + VM_REG_GUEST_X28, + VM_REG_GUEST_X29, + VM_REG_GUEST_LR, + VM_REG_GUEST_SP, + VM_REG_GUEST_PC, + VM_REG_GUEST_CPSR, + + VM_REG_GUEST_SCTLR_EL1, + VM_REG_GUEST_TTBR0_EL1, + VM_REG_GUEST_TTBR1_EL1, + VM_REG_GUEST_TCR_EL1, + VM_REG_GUEST_TCR2_EL1, + VM_REG_GUEST_MPIDR_EL1, + VM_REG_LAST +}; + +#define VM_INTINFO_VECTOR(info) ((info) & 0xff) +#define VM_INTINFO_DEL_ERRCODE 0x800 +#define VM_INTINFO_RSVD 0x7ffff000 +#define VM_INTINFO_VALID 0x80000000 +#define VM_INTINFO_TYPE 0x700 +#define VM_INTINFO_HWINTR (0 << 8) +#define VM_INTINFO_NMI (2 << 8) +#define VM_INTINFO_HWEXCEPTION (3 << 8) +#define VM_INTINFO_SWINTR (4 << 8) + +#define VM_GUEST_BASE_IPA 0x80000000UL /* Guest kernel start ipa */ + +/* + * The VM name has to fit into the pathname length constraints of devfs, + * governed primarily by SPECNAMELEN. The length is the total number of + * characters in the full path, relative to the mount point and not + * including any leading '/' characters. + * A prefix and a suffix are added to the name specified by the user. + * The prefix is usually "vmm/" or "vmm.io/", but can be a few characters + * longer for future use. + * The suffix is a string that identifies a bootrom image or some similar + * image that is attached to the VM. A separator character gets added to + * the suffix automatically when generating the full path, so it must be + * accounted for, reducing the effective length by 1. + * The effective length of a VM name is 229 bytes for FreeBSD 13 and 37 + * bytes for FreeBSD 12. A minimum length is set for safety and supports + * a SPECNAMELEN as small as 32 on old systems. + */ +#define VM_MAX_PREFIXLEN 10 +#define VM_MAX_SUFFIXLEN 15 +#define VM_MAX_NAMELEN \ + (SPECNAMELEN - VM_MAX_PREFIXLEN - VM_MAX_SUFFIXLEN - 1) + +#ifdef _KERNEL +struct vm; +struct vm_exception; +struct vm_exit; +struct vm_run; +struct vm_object; +struct vm_guest_paging; +struct vm_vgic_descr; +struct pmap; + +struct vm_eventinfo { + void *rptr; /* rendezvous cookie */ + int *sptr; /* suspend cookie */ + int *iptr; /* reqidle cookie */ +}; + +int vm_create(const char *name, struct vm **retvm); +struct vcpu *vm_alloc_vcpu(struct vm *vm, int vcpuid); +void vm_disable_vcpu_creation(struct vm *vm); +void vm_slock_vcpus(struct vm *vm); +void vm_unlock_vcpus(struct vm *vm); +void vm_destroy(struct vm *vm); +int vm_reinit(struct vm *vm); +const char *vm_name(struct vm *vm); + +uint16_t vm_get_maxcpus(struct vm *vm); +void vm_get_topology(struct vm *vm, uint16_t *sockets, uint16_t *cores, + uint16_t *threads, uint16_t *maxcpus); +int vm_set_topology(struct vm *vm, uint16_t sockets, uint16_t cores, + uint16_t threads, uint16_t maxcpus); +int vm_get_register(struct vcpu *vcpu, int reg, uint64_t *retval); +int vm_set_register(struct vcpu *vcpu, int reg, uint64_t val); +int vm_run(struct vcpu *vcpu); +int vm_suspend(struct vm *vm, enum vm_suspend_how how); +void* vm_get_cookie(struct vm *vm); +int vcpu_vcpuid(struct vcpu *vcpu); +void *vcpu_get_cookie(struct vcpu *vcpu); +struct vm *vcpu_vm(struct vcpu *vcpu); +struct vcpu *vm_vcpu(struct vm *vm, int cpu); +int vm_get_capability(struct vcpu *vcpu, int type, int *val); +int vm_set_capability(struct vcpu *vcpu, int type, int val); +int vm_activate_cpu(struct vcpu *vcpu); +int vm_suspend_cpu(struct vm *vm, struct vcpu *vcpu); +int vm_resume_cpu(struct vm *vm, struct vcpu *vcpu); +int vm_inject_exception(struct vcpu *vcpu, uint64_t esr, uint64_t far); +int vm_attach_vgic(struct vm *vm, struct vm_vgic_descr *descr); +int vm_assert_irq(struct vm *vm, uint32_t irq); +int vm_deassert_irq(struct vm *vm, uint32_t irq); +int vm_raise_msi(struct vm *vm, uint64_t msg, uint64_t addr, int bus, int slot, + int func); +struct vm_exit *vm_exitinfo(struct vcpu *vcpu); +void vm_exit_suspended(struct vcpu *vcpu, uint64_t pc); +void vm_exit_debug(struct vcpu *vcpu, uint64_t pc); +void vm_exit_rendezvous(struct vcpu *vcpu, uint64_t pc); +void vm_exit_astpending(struct vcpu *vcpu, uint64_t pc); + +cpuset_t vm_active_cpus(struct vm *vm); +cpuset_t vm_debug_cpus(struct vm *vm); +cpuset_t vm_suspended_cpus(struct vm *vm); + +static __inline int +vcpu_rendezvous_pending(struct vm_eventinfo *info) +{ + + return (*((uintptr_t *)(info->rptr)) != 0); +} + +static __inline int +vcpu_suspended(struct vm_eventinfo *info) +{ + + return (*info->sptr); +} + +int vcpu_debugged(struct vcpu *vcpu); + +enum vcpu_state { + VCPU_IDLE, + VCPU_FROZEN, + VCPU_RUNNING, + VCPU_SLEEPING, +}; + +int vcpu_set_state(struct vcpu *vcpu, enum vcpu_state state, bool from_idle); +enum vcpu_state vcpu_get_state(struct vcpu *vcpu, int *hostcpu); + +static int __inline +vcpu_is_running(struct vcpu *vcpu, int *hostcpu) +{ + return (vcpu_get_state(vcpu, hostcpu) == VCPU_RUNNING); +} + +#ifdef _SYS_PROC_H_ +static int __inline +vcpu_should_yield(struct vcpu *vcpu) +{ + struct thread *td; + + td = curthread; + return (td->td_ast != 0 || td->td_owepreempt != 0); +} +#endif + +void *vcpu_stats(struct vcpu *vcpu); +void vcpu_notify_event(struct vcpu *vcpu); +struct vmspace *vm_vmspace(struct vm *vm); +struct vm_mem *vm_mem(struct vm *vm); + +enum vm_reg_name vm_segment_name(int seg_encoding); + +struct vm_copyinfo { + uint64_t gpa; + size_t len; + void *hva; + void *cookie; +}; + +#endif /* _KERNEL */ + +#define VM_DIR_READ 0 +#define VM_DIR_WRITE 1 + +#define VM_GP_M_MASK 0x1f +#define VM_GP_MMU_ENABLED (1 << 5) + +struct vm_guest_paging { + uint64_t ttbr0_addr; + uint64_t ttbr1_addr; + uint64_t tcr_el1; + uint64_t tcr2_el1; + int flags; + int padding; +}; + +struct vie { + uint8_t access_size:4, sign_extend:1, dir:1, unused:2; + enum vm_reg_name reg; +}; + +struct vre { + uint32_t inst_syndrome; + uint8_t dir:1, unused:7; + enum vm_reg_name reg; +}; + +/* + * Identifiers for optional vmm capabilities + */ +enum vm_cap_type { + VM_CAP_HALT_EXIT, + VM_CAP_PAUSE_EXIT, + VM_CAP_UNRESTRICTED_GUEST, + VM_CAP_BRK_EXIT, + VM_CAP_SS_EXIT, + VM_CAP_MASK_HWINTR, + VM_CAP_MAX +}; + +enum vm_exitcode { + VM_EXITCODE_BOGUS, + VM_EXITCODE_INST_EMUL, + VM_EXITCODE_REG_EMUL, + VM_EXITCODE_HVC, + VM_EXITCODE_SUSPENDED, + VM_EXITCODE_HYP, + VM_EXITCODE_WFI, + VM_EXITCODE_PAGING, + VM_EXITCODE_SMCCC, + VM_EXITCODE_DEBUG, + VM_EXITCODE_BRK, + VM_EXITCODE_SS, + VM_EXITCODE_MAX +}; + +struct vm_exit { + enum vm_exitcode exitcode; + int inst_length; + uint64_t pc; + union { + /* + * ARM specific payload. + */ + struct { + uint32_t exception_nr; + uint32_t pad; + uint64_t esr_el2; /* Exception Syndrome Register */ + uint64_t far_el2; /* Fault Address Register */ + uint64_t hpfar_el2; /* Hypervisor IPA Fault Address Register */ + } hyp; + struct { + struct vre vre; + } reg_emul; + struct { + uint64_t gpa; + uint64_t esr; + } paging; + struct { + uint64_t gpa; + struct vm_guest_paging paging; + struct vie vie; + } inst_emul; + + /* + * A SMCCC call, e.g. starting a core via PSCI. + * Further arguments can be read by asking the kernel for + * all register values. + */ + struct { + uint64_t func_id; + uint64_t args[7]; + } smccc_call; + + struct { + enum vm_suspend_how how; + } suspended; + } u; +}; + +#endif /* _VMM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-freebsd-none/machine/vmm_dev.h b/lib/libc/include/aarch64-freebsd-none/machine/vmm_dev.h new file mode 100644 index 000000000000..b363b3d61a89 --- /dev/null +++ b/lib/libc/include/aarch64-freebsd-none/machine/vmm_dev.h @@ -0,0 +1,274 @@ +/* + * Copyright (C) 2015 Mihai Carabas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY 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 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 _VMM_DEV_H_ +#define _VMM_DEV_H_ + +#include + +#include + +struct vm_memmap { + vm_paddr_t gpa; + int segid; /* memory segment */ + vm_ooffset_t segoff; /* offset into memory segment */ + size_t len; /* mmap length */ + int prot; /* RWX */ + int flags; +}; +#define VM_MEMMAP_F_WIRED 0x01 + +struct vm_munmap { + vm_paddr_t gpa; + size_t len; +}; + +#define VM_MEMSEG_NAME(m) ((m)->name[0] != '\0' ? (m)->name : NULL) +struct vm_memseg { + int segid; + size_t len; + char name[VM_MAX_SUFFIXLEN + 1]; + domainset_t *ds_mask; + size_t ds_mask_size; + int ds_policy; +}; + +struct vm_register { + int cpuid; + int regnum; /* enum vm_reg_name */ + uint64_t regval; +}; + +struct vm_register_set { + int cpuid; + unsigned int count; + const int *regnums; /* enum vm_reg_name */ + uint64_t *regvals; +}; + +struct vm_run { + int cpuid; + cpuset_t *cpuset; /* CPU set storage */ + size_t cpusetsize; + struct vm_exit *vm_exit; +}; + +struct vm_exception { + int cpuid; + uint64_t esr; + uint64_t far; +}; + +struct vm_msi { + uint64_t msg; + uint64_t addr; + int bus; + int slot; + int func; +}; + +struct vm_capability { + int cpuid; + enum vm_cap_type captype; + int capval; + int allcpus; +}; + +#define MAX_VM_STATS 64 +struct vm_stats { + int cpuid; /* in */ + int index; /* in */ + int num_entries; /* out */ + struct timeval tv; + uint64_t statbuf[MAX_VM_STATS]; +}; +struct vm_stat_desc { + int index; /* in */ + char desc[128]; /* out */ +}; + +struct vm_suspend { + enum vm_suspend_how how; +}; + +struct vm_gla2gpa { + int vcpuid; /* inputs */ + int prot; /* PROT_READ or PROT_WRITE */ + uint64_t gla; + struct vm_guest_paging paging; + int fault; /* outputs */ + uint64_t gpa; +}; + +struct vm_activate_cpu { + int vcpuid; +}; + +struct vm_cpuset { + int which; + int cpusetsize; + cpuset_t *cpus; +}; +#define VM_ACTIVE_CPUS 0 +#define VM_SUSPENDED_CPUS 1 +#define VM_DEBUG_CPUS 2 + +struct vm_vgic_version { + u_int version; + u_int flags; +}; + +struct vm_vgic_descr { + struct vm_vgic_version ver; + union { + struct { + uint64_t dist_start; + uint64_t dist_size; + uint64_t redist_start; + uint64_t redist_size; + } v3_regs; + }; +}; + +struct vm_irq { + uint32_t irq; +}; + +struct vm_cpu_topology { + uint16_t sockets; + uint16_t cores; + uint16_t threads; + uint16_t maxcpus; +}; + +enum { + /* general routines */ + IOCNUM_ABIVERS = 0, + IOCNUM_RUN = 1, + IOCNUM_SET_CAPABILITY = 2, + IOCNUM_GET_CAPABILITY = 3, + IOCNUM_SUSPEND = 4, + IOCNUM_REINIT = 5, + + /* memory apis */ + IOCNUM_GET_GPA_PMAP = 12, + IOCNUM_GLA2GPA_NOFAULT = 13, + IOCNUM_ALLOC_MEMSEG = 14, + IOCNUM_GET_MEMSEG = 15, + IOCNUM_MMAP_MEMSEG = 16, + IOCNUM_MMAP_GETNEXT = 17, + IOCNUM_MUNMAP_MEMSEG = 18, + + /* register/state accessors */ + IOCNUM_SET_REGISTER = 20, + IOCNUM_GET_REGISTER = 21, + IOCNUM_SET_REGISTER_SET = 24, + IOCNUM_GET_REGISTER_SET = 25, + + /* statistics */ + IOCNUM_VM_STATS = 50, + IOCNUM_VM_STAT_DESC = 51, + + /* CPU Topology */ + IOCNUM_SET_TOPOLOGY = 63, + IOCNUM_GET_TOPOLOGY = 64, + + /* interrupt injection */ + IOCNUM_ASSERT_IRQ = 80, + IOCNUM_DEASSERT_IRQ = 81, + IOCNUM_RAISE_MSI = 82, + IOCNUM_INJECT_EXCEPTION = 83, + + /* vm_cpuset */ + IOCNUM_ACTIVATE_CPU = 90, + IOCNUM_GET_CPUSET = 91, + IOCNUM_SUSPEND_CPU = 92, + IOCNUM_RESUME_CPU = 93, + + /* vm_attach_vgic */ + IOCNUM_GET_VGIC_VERSION = 110, + IOCNUM_ATTACH_VGIC = 111, +}; + +#define VM_RUN \ + _IOWR('v', IOCNUM_RUN, struct vm_run) +#define VM_SUSPEND \ + _IOW('v', IOCNUM_SUSPEND, struct vm_suspend) +#define VM_REINIT \ + _IO('v', IOCNUM_REINIT) +#define VM_ALLOC_MEMSEG \ + _IOW('v', IOCNUM_ALLOC_MEMSEG, struct vm_memseg) +#define VM_GET_MEMSEG \ + _IOWR('v', IOCNUM_GET_MEMSEG, struct vm_memseg) +#define VM_MMAP_MEMSEG \ + _IOW('v', IOCNUM_MMAP_MEMSEG, struct vm_memmap) +#define VM_MMAP_GETNEXT \ + _IOWR('v', IOCNUM_MMAP_GETNEXT, struct vm_memmap) +#define VM_MUNMAP_MEMSEG \ + _IOW('v', IOCNUM_MUNMAP_MEMSEG, struct vm_munmap) +#define VM_SET_REGISTER \ + _IOW('v', IOCNUM_SET_REGISTER, struct vm_register) +#define VM_GET_REGISTER \ + _IOWR('v', IOCNUM_GET_REGISTER, struct vm_register) +#define VM_SET_REGISTER_SET \ + _IOW('v', IOCNUM_SET_REGISTER_SET, struct vm_register_set) +#define VM_GET_REGISTER_SET \ + _IOWR('v', IOCNUM_GET_REGISTER_SET, struct vm_register_set) +#define VM_SET_CAPABILITY \ + _IOW('v', IOCNUM_SET_CAPABILITY, struct vm_capability) +#define VM_GET_CAPABILITY \ + _IOWR('v', IOCNUM_GET_CAPABILITY, struct vm_capability) +#define VM_STATS \ + _IOWR('v', IOCNUM_VM_STATS, struct vm_stats) +#define VM_STAT_DESC \ + _IOWR('v', IOCNUM_VM_STAT_DESC, struct vm_stat_desc) +#define VM_ASSERT_IRQ \ + _IOW('v', IOCNUM_ASSERT_IRQ, struct vm_irq) +#define VM_DEASSERT_IRQ \ + _IOW('v', IOCNUM_DEASSERT_IRQ, struct vm_irq) +#define VM_RAISE_MSI \ + _IOW('v', IOCNUM_RAISE_MSI, struct vm_msi) +#define VM_INJECT_EXCEPTION \ + _IOW('v', IOCNUM_INJECT_EXCEPTION, struct vm_exception) +#define VM_SET_TOPOLOGY \ + _IOW('v', IOCNUM_SET_TOPOLOGY, struct vm_cpu_topology) +#define VM_GET_TOPOLOGY \ + _IOR('v', IOCNUM_GET_TOPOLOGY, struct vm_cpu_topology) +#define VM_GLA2GPA_NOFAULT \ + _IOWR('v', IOCNUM_GLA2GPA_NOFAULT, struct vm_gla2gpa) +#define VM_ACTIVATE_CPU \ + _IOW('v', IOCNUM_ACTIVATE_CPU, struct vm_activate_cpu) +#define VM_GET_CPUS \ + _IOW('v', IOCNUM_GET_CPUSET, struct vm_cpuset) +#define VM_SUSPEND_CPU \ + _IOW('v', IOCNUM_SUSPEND_CPU, struct vm_activate_cpu) +#define VM_RESUME_CPU \ + _IOW('v', IOCNUM_RESUME_CPU, struct vm_activate_cpu) +#define VM_GET_VGIC_VERSION \ + _IOR('v', IOCNUM_GET_VGIC_VERSION, struct vm_vgic_version) +#define VM_ATTACH_VGIC \ + _IOW('v', IOCNUM_ATTACH_VGIC, struct vm_vgic_descr) +#endif \ No newline at end of file diff --git a/lib/libc/include/aarch64-freebsd-none/machine/vmm_instruction_emul.h b/lib/libc/include/aarch64-freebsd-none/machine/vmm_instruction_emul.h new file mode 100644 index 000000000000..96732c94f01d --- /dev/null +++ b/lib/libc/include/aarch64-freebsd-none/machine/vmm_instruction_emul.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2015 Mihai Carabas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY 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 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 _VMM_INSTRUCTION_EMUL_H_ +#define _VMM_INSTRUCTION_EMUL_H_ + +/* + * Callback functions to read and write memory regions. + */ +typedef int (*mem_region_read_t)(struct vcpu *vcpu, uint64_t gpa, + uint64_t *rval, int rsize, void *arg); +typedef int (*mem_region_write_t)(struct vcpu *vcpu, uint64_t gpa, + uint64_t wval, int wsize, void *arg); + +/* + * Callback functions to read and write registers. + */ +typedef int (*reg_read_t)(struct vcpu *vcpu, uint64_t *rval, void *arg); +typedef int (*reg_write_t)(struct vcpu *vcpu, uint64_t wval, void *arg); + +/* + * Emulate the decoded 'vie' instruction when it contains a memory operation. + * + * The callbacks 'mrr' and 'mrw' emulate reads and writes to the memory region + * containing 'gpa'. 'mrarg' is an opaque argument that is passed into the + * callback functions. + * + * 'void *vm' should be 'struct vm *' when called from kernel context and + * 'struct vmctx *' when called from user context. + * + */ +int vmm_emulate_instruction(struct vcpu *vcpu, uint64_t gpa, struct vie *vie, + struct vm_guest_paging *paging, mem_region_read_t mrr, + mem_region_write_t mrw, void *mrarg); + +/* + * Emulate the decoded 'vre' instruction when it contains a register access. + * + * The callbacks 'regread' and 'regwrite' emulate reads and writes to the + * register from 'vie'. 'regarg' is an opaque argument that is passed into the + * callback functions. + * + * 'void *vm' should be 'struct vm *' when called from kernel context and + * 'struct vmctx *' when called from user context. + * + */ +int vmm_emulate_register(struct vcpu *vcpu, struct vre *vre, reg_read_t regread, + reg_write_t regwrite, void *regarg); + +#ifdef _KERNEL +void vm_register_reg_handler(struct vm *vm, uint64_t iss, uint64_t mask, + reg_read_t reg_read, reg_write_t reg_write, void *arg); +void vm_deregister_reg_handler(struct vm *vm, uint64_t iss, uint64_t mask); + +void vm_register_inst_handler(struct vm *vm, uint64_t start, uint64_t size, + mem_region_read_t mmio_read, mem_region_write_t mmio_write); +void vm_deregister_inst_handler(struct vm *vm, uint64_t start, uint64_t size); +#endif + +#endif /* _VMM_INSTRUCTION_EMUL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-freebsd-none/machine/vmparam.h b/lib/libc/include/aarch64-freebsd-none/machine/vmparam.h index 43836cb53781..cf8d0e7bee85 100644 --- a/lib/libc/include/aarch64-freebsd-none/machine/vmparam.h +++ b/lib/libc/include/aarch64-freebsd-none/machine/vmparam.h @@ -30,8 +30,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)vmparam.h 5.9 (Berkeley) 5/12/91 * from: FreeBSD: src/sys/i386/include/vmparam.h,v 1.33 2000/03/30 */ @@ -75,14 +73,16 @@ #define VM_PHYSSEG_MAX 64 /* - * Create two free page pools: VM_FREEPOOL_DEFAULT is the default pool - * from which physical pages are allocated and VM_FREEPOOL_DIRECT is - * the pool from which physical pages for small UMA objects are - * allocated. + * Create three free page pools: VM_FREEPOOL_DEFAULT is the default pool from + * which physical pages are allocated and VM_FREEPOOL_DIRECT is the pool from + * which physical pages for page tables and small UMA objects are allocated. + * VM_FREEPOOL_LAZYINIT is a special-purpose pool that is populated only during + * boot and is used to implement deferred initialization of page structures. */ -#define VM_NFREEPOOL 2 -#define VM_FREEPOOL_DEFAULT 0 -#define VM_FREEPOOL_DIRECT 1 +#define VM_NFREEPOOL 3 +#define VM_FREEPOOL_LAZYINIT 0 +#define VM_FREEPOOL_DEFAULT 1 +#define VM_FREEPOOL_DIRECT 2 /* * Create two free page lists: VM_FREELIST_DMA32 is for physical pages that have @@ -101,21 +101,46 @@ * are used by UMA, the physical memory allocator reduces the likelihood of * both 2MB page TLB misses and cache misses during the page table walk when * a 2MB page TLB miss does occur. + * + * When PAGE_SIZE is 16KB, an allocation size of 32MB is supported. This + * size is used by level 0 reservations and L2 BLOCK mappings. */ +#if PAGE_SIZE == PAGE_SIZE_4K #define VM_NFREEORDER 13 +#elif PAGE_SIZE == PAGE_SIZE_16K +#define VM_NFREEORDER 12 +#else +#error Unsupported page size +#endif /* - * Enable superpage reservations: 1 level. + * Enable superpage reservations: 2 levels. */ #ifndef VM_NRESERVLEVEL -#define VM_NRESERVLEVEL 1 +#define VM_NRESERVLEVEL 2 #endif /* - * Level 0 reservations consist of 512 pages. + * Level 0 reservations consist of 16 pages when PAGE_SIZE is 4KB, and 128 + * pages when PAGE_SIZE is 16KB. Level 1 reservations consist of 32 64KB + * pages when PAGE_SIZE is 4KB, and 16 2M pages when PAGE_SIZE is 16KB. */ +#if PAGE_SIZE == PAGE_SIZE_4K #ifndef VM_LEVEL_0_ORDER -#define VM_LEVEL_0_ORDER 9 +#define VM_LEVEL_0_ORDER 4 +#endif +#ifndef VM_LEVEL_1_ORDER +#define VM_LEVEL_1_ORDER 5 +#endif +#elif PAGE_SIZE == PAGE_SIZE_16K +#ifndef VM_LEVEL_0_ORDER +#define VM_LEVEL_0_ORDER 7 +#endif +#ifndef VM_LEVEL_1_ORDER +#define VM_LEVEL_1_ORDER 4 +#endif +#else +#error Unsupported page size #endif /** @@ -133,6 +158,12 @@ * 0xfffffeffffffffff End of DMAP * 0xffffa00000000000 Start of DMAP * + * 0xffff027fffffffff End of KMSAN origin map + * 0xffff020000000000 Start of KMSAN origin map + * + * 0xffff017fffffffff End of KMSAN shadow map + * 0xffff010000000000 Start of KMSAN shadow map + * * 0xffff009fffffffff End of KASAN shadow map * 0xffff008000000000 Start of KASAN shadow map * @@ -169,11 +200,25 @@ #define KASAN_MIN_ADDRESS (0xffff008000000000UL) #define KASAN_MAX_ADDRESS (0xffff00a000000000UL) +/* 512GiB KMSAN shadow map */ +#define KMSAN_SHAD_MIN_ADDRESS (0xffff010000000000UL) +#define KMSAN_SHAD_MAX_ADDRESS (0xffff018000000000UL) + +/* 512GiB KMSAN origin map */ +#define KMSAN_ORIG_MIN_ADDRESS (0xffff020000000000UL) +#define KMSAN_ORIG_MAX_ADDRESS (0xffff028000000000UL) + /* The address bits that hold a pointer authentication code */ -#define PAC_ADDR_MASK (0xff7f000000000000UL) +#define PAC_ADDR_MASK (0x007f000000000000UL) +#define PAC_ADDR_MASK_14 (0xff7f000000000000UL) + +/* The top-byte ignore address bits */ +#define TBI_ADDR_MASK 0xff00000000000000UL /* If true addr is in the kernel address space */ #define ADDR_IS_KERNEL(addr) (((addr) & (1ul << 55)) == (1ul << 55)) +/* If true addr is in the user address space */ +#define ADDR_IS_USER(addr) (((addr) & (1ul << 55)) == 0) /* If true addr is in its canonical form (i.e. no TBI, PAC, etc.) */ #define ADDR_IS_CANONICAL(addr) \ (((addr) & 0xffff000000000000UL) == 0 || \ @@ -265,7 +310,7 @@ #endif #if !defined(KASAN) && !defined(KMSAN) -#define UMA_MD_SMALL_ALLOC +#define UMA_USE_DMAP #endif #ifndef LOCORE @@ -289,6 +334,7 @@ extern vm_offset_t dmap_max_addr; * Need a page dump array for minidump. */ #define MINIDUMP_PAGE_TRACKING 1 +#define MINIDUMP_STARTUP_PAGE_TRACKING 1 #endif /* !_MACHINE_VMPARAM_H_ */ diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/_float.h b/lib/libc/include/aarch64-openbsd-none/arm64/_float.h new file mode 100644 index 000000000000..ea467e6f21a1 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/_float.h @@ -0,0 +1,96 @@ +/* $OpenBSD: _float.h,v 1.1 2016/12/17 23:38:33 patrick Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE__FLOAT_H_ +#define _MACHINE__FLOAT_H_ + +#define __FLT_RADIX 2 /* b */ +#define __FLT_ROUNDS __flt_rounds() +#define __FLT_EVAL_METHOD 0 /* no promotions */ + +#define __FLT_MANT_DIG 24 /* p */ +#define __FLT_EPSILON 1.19209290E-7F /* b**(1-p) */ +#define __FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ +#define __FLT_MIN_EXP (-125) /* emin */ +#define __FLT_MIN 1.17549435E-38F /* b**(emin-1) */ +#define __FLT_MIN_10_EXP (-37) /* ceil(log10(b**(emin-1))) */ +#define __FLT_MAX_EXP 128 /* emax */ +#define __FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ +#define __FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ + +#define __DBL_MANT_DIG 53 +#define __DBL_EPSILON 2.2204460492503131E-16 +#define __DBL_DIG 15 +#define __DBL_MIN_EXP (-1021) +#define __DBL_MIN 2.2250738585072014E-308 +#define __DBL_MIN_10_EXP (-307) +#define __DBL_MAX_EXP 1024 +#define __DBL_MAX 1.7976931348623157E+308 +#define __DBL_MAX_10_EXP 308 + +#ifdef __LDBL_MANT_DIG__ +#define __LDBL_MANT_DIG __LDBL_MANT_DIG__ +#define __LDBL_EPSILON __LDBL_EPSILON__ +#define __LDBL_DIG __LDBL_DIG__ +#define __LDBL_MIN_EXP __LDBL_MIN_EXP__ +#define __LDBL_MIN __LDBL_MIN__ +#define __LDBL_MIN_10_EXP __LDBL_MIN_10_EXP__ +#define __LDBL_MAX_EXP __LDBL_MAX_EXP__ +#define __LDBL_MAX __LDBL_MAX__ +#define __LDBL_MAX_10_EXP __LDBL_MAX_10_EXP__ +#else +#define __LDBL_MANT_DIG DBL_MANT_DIG +#define __LDBL_EPSILON DBL_EPSILON +#define __LDBL_DIG DBL_DIG +#define __LDBL_MIN_EXP DBL_MIN_EXP +#define __LDBL_MIN DBL_MIN +#define __LDBL_MIN_10_EXP DBL_MIN_10_EXP +#define __LDBL_MAX_EXP DBL_MAX_EXP +#define __LDBL_MAX DBL_MAX +#define __LDBL_MAX_10_EXP DBL_MAX_10_EXP +#endif + +#define __DECIMAL_DIG 17 + +#endif /* _MACHINE__FLOAT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/_types.h b/lib/libc/include/aarch64-openbsd-none/arm64/_types.h new file mode 100644 index 000000000000..2de0c9d512a5 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/_types.h @@ -0,0 +1,145 @@ +/* $OpenBSD: _types.h,v 1.6 2023/07/02 19:02:27 cheloha Exp $ */ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.3 (Berkeley) 1/5/94 + * @(#)ansi.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _MACHINE__TYPES_H_ +#define _MACHINE__TYPES_H_ + +#if defined(_KERNEL) +typedef struct label_t { + long val[13]; +} label_t; +#endif + +/* + * _ALIGN(p) rounds p (pointer or byte index) up to a correctly-aligned + * value for all data types (int, long, ...). The result is an + * unsigned long and must be cast to any desired pointer type. + * + * _ALIGNED_POINTER is a boolean macro that checks whether an address + * is valid to fetch data elements of type t from on this architecture. + * This does not reflect the optimal alignment, just the possibility + * (within reasonable limits). + */ +#define _ALIGNBYTES (sizeof(long) - 1) +#define _STACKALIGNBYTES 15 +#define _ALIGN(p) (((unsigned long)(p) + _ALIGNBYTES) & ~_ALIGNBYTES) +#define _ALIGNED_POINTER(p,t) ((((unsigned long)(p)) & (sizeof(t) - 1)) == 0) +#define _MAX_PAGE_SHIFT 12 /* same as PAGE_SHIFT */ + +/* 7.18.1.1 Exact-width integer types */ +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short __int16_t; +typedef unsigned short __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; +/* LONGLONG */ +typedef long long __int64_t; +/* LONGLONG */ +typedef unsigned long long __uint64_t; + +/* 7.18.1.2 Minimum-width integer types */ +typedef __int8_t __int_least8_t; +typedef __uint8_t __uint_least8_t; +typedef __int16_t __int_least16_t; +typedef __uint16_t __uint_least16_t; +typedef __int32_t __int_least32_t; +typedef __uint32_t __uint_least32_t; +typedef __int64_t __int_least64_t; +typedef __uint64_t __uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types */ +typedef __int32_t __int_fast8_t; +typedef __uint32_t __uint_fast8_t; +typedef __int32_t __int_fast16_t; +typedef __uint32_t __uint_fast16_t; +typedef __int32_t __int_fast32_t; +typedef __uint32_t __uint_fast32_t; +typedef __int64_t __int_fast64_t; +typedef __uint64_t __uint_fast64_t; +#define __INT_FAST8_MIN INT32_MIN +#define __INT_FAST16_MIN INT32_MIN +#define __INT_FAST32_MIN INT32_MIN +#define __INT_FAST64_MIN INT64_MIN +#define __INT_FAST8_MAX INT32_MAX +#define __INT_FAST16_MAX INT32_MAX +#define __INT_FAST32_MAX INT32_MAX +#define __INT_FAST64_MAX INT64_MAX +#define __UINT_FAST8_MAX UINT32_MAX +#define __UINT_FAST16_MAX UINT32_MAX +#define __UINT_FAST32_MAX UINT32_MAX +#define __UINT_FAST64_MAX UINT64_MAX + +/* 7.18.1.4 Integer types capable of holding object pointers */ +typedef long __intptr_t; +typedef unsigned long __uintptr_t; + +/* 7.18.1.5 Greatest-width integer types */ +typedef __int64_t __intmax_t; +typedef __uint64_t __uintmax_t; + +/* Register size */ +typedef long __register_t; + +/* VM system types */ +typedef unsigned long __vaddr_t; +typedef unsigned long __paddr_t; +typedef unsigned long __vsize_t; +typedef unsigned long __psize_t; + +/* Standard system types */ +typedef double __double_t; +typedef float __float_t; +typedef long __ptrdiff_t; +typedef unsigned long __size_t; +typedef long __ssize_t; +#if defined(__GNUC__) && __GNUC__ >= 3 +typedef __builtin_va_list __va_list; +#else +typedef char * __va_list; +#endif + +/* Wide character support types */ +#ifndef __cplusplus +#ifdef __WCHAR_UNSIGNED__ +typedef unsigned int __wchar_t; +#else +typedef int __wchar_t; +#endif +#endif +typedef int __wint_t; +typedef int __rune_t; +typedef void * __wctrans_t; +typedef void * __wctype_t; + +#endif /* _MACHINE__TYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/acpiapm.h b/lib/libc/include/aarch64-openbsd-none/arm64/acpiapm.h new file mode 100644 index 000000000000..9664811d2bce --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/acpiapm.h @@ -0,0 +1,22 @@ +/* $OpenBSD: acpiapm.h,v 1.1 2019/01/23 09:57:36 phessler Exp $ */ +/* + * Copyright (c) 2007 Ted Unangst + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +extern int (*acpiapm_open)(dev_t, int, int, struct proc *); +extern int (*acpiapm_close)(dev_t, int, int, struct proc *); +extern int (*acpiapm_ioctl)(dev_t, u_long, caddr_t, int, struct proc *); +extern int (*acpiapm_kqfilter)(dev_t, struct knote *); \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/apmvar.h b/lib/libc/include/aarch64-openbsd-none/arm64/apmvar.h new file mode 100644 index 000000000000..f824cfe20417 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/apmvar.h @@ -0,0 +1,127 @@ +/* $OpenBSD: apmvar.h,v 1.3 2023/01/22 13:14:21 kettenis Exp $ */ + +/* + * Copyright (c) 2001 Alexander Guy + * Copyright (c) 1995 John T. Kohl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _MACHINE_APMVAR_H_ +#define _MACHINE_APMVAR_H_ + +#include + +/* Advanced Power Management (v1.0 and v1.1 specification) + * functions/defines/etc. + */ + +/* These definitions make up the heart of the user-land interface + * to the APM devices. + */ + +#define APM_AC_OFF 0x00 +#define APM_AC_ON 0x01 +#define APM_AC_BACKUP 0x02 +#define APM_AC_UNKNOWN 0xff +#define APM_BATT_HIGH 0x00 +#define APM_BATT_LOW 0x01 +#define APM_BATT_CRITICAL 0x02 +#define APM_BATT_CHARGING 0x03 +#define APM_BATT_UNKNOWN 0xff +#define APM_BATT_LIFE_UNKNOWN 0xff + +#define APM_NOEVENT 0x0000 +#define APM_STANDBY_REQ 0x0001 +#define APM_SUSPEND_REQ 0x0002 +#define APM_NORMAL_RESUME 0x0003 +#define APM_CRIT_RESUME 0x0004 /* suspend/resume happened + without us */ +#define APM_BATTERY_LOW 0x0005 +#define APM_POWER_CHANGE 0x0006 +#define APM_UPDATE_TIME 0x0007 +#define APM_CRIT_SUSPEND_REQ 0x0008 +#define APM_USER_STANDBY_REQ 0x0009 +#define APM_USER_SUSPEND_REQ 0x000A +#define APM_SYS_STANDBY_RESUME 0x000B +#define APM_CAPABILITY_CHANGE 0x000C /* apm v1.2 */ +#define APM_USER_HIBERNATE_REQ 0x000D +#define APM_EVENT_MASK 0xffff + +#define APM_EVENT_COMPOSE(t,i) ((((i) & 0x7fff) << 16)|((t) & APM_EVENT_MASK)) +#define APM_EVENT_TYPE(e) ((e) & APM_EVENT_MASK) +#define APM_EVENT_INDEX(e) ((e) >> 16) + +/* + * LP (Laptop Package) + * + * Copyright (C) 1994 by HOSOKAWA Tatsumi + * + * This software may be used, modified, copied, and distributed, in + * both source and binary form provided that the above copyright and + * these terms are retained. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with its + * use. + * + * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) + */ + +#define APM_BATTERY_ABSENT 4 + +struct apm_power_info { + u_char battery_state; + u_char ac_state; + u_char battery_life; + u_char spare1; + u_int minutes_left; /* estimate */ + u_int spare2[6]; +}; + +struct apm_ctl { + u_int dev; + u_int mode; +}; + +#define APM_IOC_REJECT _IOW('A', 0, struct apm_event_info) /* reject request # */ +#define APM_IOC_STANDBY _IO('A', 1) /* put system into standby */ +#define APM_IOC_SUSPEND _IO('A', 2) /* put system into suspend */ +#define APM_IOC_GETPOWER _IOR('A', 3, struct apm_power_info) /* fetch battery state */ +#define APM_IOC_DEV_CTL _IOW('A', 5, struct apm_ctl) /* put device into mode */ +#define APM_IOC_PRN_CTL _IOW('A', 6, int ) /* driver power status msg */ +#define APM_PRINT_ON 0 /* driver power status displayed */ +#define APM_PRINT_OFF 1 /* driver power status not displayed */ +#define APM_PRINT_PCT 2 /* driver power status only displayed + if the percentage changes */ +#define APM_IOC_STANDBY_REQ _IO('A', 7) /* request standby */ +#define APM_IOC_SUSPEND_REQ _IO('A', 8) /* request suspend */ +#define APM_IOC_HIBERNATE _IO('A', 9) /* put system into hibernate */ + +#ifdef _KERNEL +void apm_setinfohook(int (*)(struct apm_power_info *)); +int apm_record_event(u_int); +#endif + +#endif /* _MACHINE_APMVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/armreg.h b/lib/libc/include/aarch64-openbsd-none/arm64/armreg.h new file mode 100644 index 000000000000..7483ae8dd70d --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/armreg.h @@ -0,0 +1,973 @@ +/* $OpenBSD: armreg.h,v 1.44 2025/07/22 09:20:41 kettenis Exp $ */ +/*- + * Copyright (c) 2013, 2014 Andrew Turner + * Copyright (c) 2015 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Andrew Turner 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. + * + * $FreeBSD: head/sys/arm64/include/armreg.h 309248 2016-11-28 14:24:07Z andrew $ + */ + +#ifndef _MACHINE_ARMREG_H_ +#define _MACHINE_ARMREG_H_ + +#define INSN_SIZE 4 + +#define READ_SPECIALREG(reg) \ +({ uint64_t val; \ + __asm volatile("mrs %0, " __STRING(reg) : "=&r" (val)); \ + val; \ +}) +#define WRITE_SPECIALREG(reg, val) \ + __asm volatile("msr " __STRING(reg) ", %0" : : "r"((uint64_t)val)) + +/* CCSIDR_EL1 - Current Cache Size ID Register */ +#define CCSIDR_SETS_MASK 0x0fffe000 +#define CCSIDR_SETS_SHIFT 13 +#define CCSIDR_SETS(reg) \ + ((((reg) & CCSIDR_SETS_MASK) >> CCSIDR_SETS_SHIFT) + 1) +#define CCSIDR_WAYS_MASK 0x00001ff8 +#define CCSIDR_WAYS_SHIFT 3 +#define CCSIDR_WAYS(reg) \ + ((((reg) & CCSIDR_WAYS_MASK) >> CCSIDR_WAYS_SHIFT) + 1) +#define CCSIDR_LINE_MASK 0x00000007 +#define CCSIDR_LINE_SIZE(reg) (1 << (((reg) & CCSIDR_LINE_MASK) + 4)) + +#define CCSIDR_CCIDX_SETS_MASK 0x00ffffff00000000ULL +#define CCSIDR_CCIDX_SETS_SHIFT 32 +#define CCSIDR_CCIDX_SETS(reg) \ + ((((reg) & CCSIDR_CCIDX_SETS_MASK) >> CCSIDR_CCIDX_SETS_SHIFT) + 1) +#define CCSIDR_CCIDX_WAYS_MASK 0x0000000000fffff8ULL +#define CCSIDR_CCIDX_WAYS_SHIFT 3 +#define CCSIDR_CCIDX_WAYS(reg) \ + ((((reg) & CCSIDR_CCIDX_WAYS_MASK) >> CCSIDR_CCIDX_WAYS_SHIFT) + 1) +#define CCSIDR_CCIDX_LINE_MASK 0x0000000000000007ULL +#define CCSIDR_CCIDX_LINE_SIZE(reg) \ + (1 << (((reg) & CCSIDR_CCIDX_LINE_MASK) + 4)) + +/* CLIDR_EL1 - Cache Level ID Register */ +#define CLIDR_CTYPE_MASK 0x7 +#define CLIDR_CTYPE_INSN 0x1 +#define CLIDR_CTYPE_DATA 0x2 +#define CLIDR_CTYPE_UNIFIED 0x4 + +/* CNTHCTL_EL2 - Counter-timer Hypervisor Control Register */ +#define CNTHCTL_EVNTI_MASK (0xf << 4) /* Bit to trigger event stream */ +#define CNTHCTL_EVNTDIR (1 << 3) /* Control transition trigger bit */ +#define CNTHCTL_EVNTEN (1 << 2) /* Enable event stream */ +#define CNTHCTL_EL1PCEN (1 << 1) /* Allow EL0/1 physical timer access */ +#define CNTHCTL_EL1PCTEN (1 << 0) /*Allow EL0/1 physical counter access*/ + +/* CNTKCTL_EL1 - Counter-timer Kernel Control Register */ +#define CNTKCTL_EL0VCTEN (1 << 1) /* Allow EL0 virtual counter access */ + +/* CNTV_CTL_EL0 */ +#define CNTV_CTL_ENABLE (1 << 0) +#define CNTV_CTL_IMASK (1 << 1) +#define CNTV_CTL_ISTATUS (1 << 2) + +/* CPACR_EL1 */ +#define CPACR_ZEN_MASK (0x3 << 16) +#define CPACR_ZEN_TRAP_ALL1 (0x0 << 16) /* Traps from EL0 and EL1 */ +#define CPACR_ZEN_TRAP_EL0 (0x1 << 16) /* Traps from EL0 */ +#define CPACR_ZEN_TRAP_ALL2 (0x2 << 16) /* Traps from EL0 and EL1 */ +#define CPACR_ZEN_TRAP_NONE (0x3 << 16) /* No traps */ +#define CPACR_FPEN_MASK (0x3 << 20) +#define CPACR_FPEN_TRAP_ALL1 (0x0 << 20) /* Traps from EL0 and EL1 */ +#define CPACR_FPEN_TRAP_EL0 (0x1 << 20) /* Traps from EL0 */ +#define CPACR_FPEN_TRAP_ALL2 (0x2 << 20) /* Traps from EL0 and EL1 */ +#define CPACR_FPEN_TRAP_NONE (0x3 << 20) /* No traps */ +#define CPACR_TTA (0x1 << 28) + +/* CSSELR_EL1 - Cache Size Selection Register */ +#define CSSELR_IND (1 << 0) +#define CSSELR_LEVEL_SHIFT 1 + +/* CTR_EL0 - Cache Type Register */ +#define CTR_DLINE_SHIFT 16 +#define CTR_DLINE_MASK (0xf << CTR_DLINE_SHIFT) +#define CTR_DLINE_SIZE(reg) (((reg) & CTR_DLINE_MASK) >> CTR_DLINE_SHIFT) +#define CTR_IL1P_SHIFT 14 +#define CTR_IL1P_MASK (0x3 << CTR_IL1P_SHIFT) +#define CTR_IL1P_AIVIVT (0x1 << CTR_IL1P_SHIFT) +#define CTR_IL1P_VIPT (0x2 << CTR_IL1P_SHIFT) +#define CTR_IL1P_PIPT (0x3 << CTR_IL1P_SHIFT) +#define CTR_ILINE_SHIFT 0 +#define CTR_ILINE_MASK (0xf << CTR_ILINE_SHIFT) +#define CTR_ILINE_SIZE(reg) (((reg) & CTR_ILINE_MASK) >> CTR_ILINE_SHIFT) + +/* MPIDR_EL1 - Multiprocessor Affinity Register */ +#define MPIDR_AFF3 (0xFFULL << 32) +#define MPIDR_AFF2 (0xFFULL << 16) +#define MPIDR_AFF1 (0xFFULL << 8) +#define MPIDR_AFF0 (0xFFULL << 0) +#define MPIDR_AFF (MPIDR_AFF3|MPIDR_AFF2|MPIDR_AFF1|MPIDR_AFF0) + +/* DCZID_EL0 - Data Cache Zero ID register */ +#define DCZID_DZP (1 << 4) /* DC ZVA prohibited if non-0 */ +#define DCZID_BS_SHIFT 0 +#define DCZID_BS_MASK (0xf << DCZID_BS_SHIFT) +#define DCZID_BS_SIZE(reg) (((reg) & DCZID_BS_MASK) >> DCZID_BS_SHIFT) + +/* ESR_ELx */ +#define ESR_ELx_ISS_MASK 0x00ffffff +#define ISS_INSN_FnV (0x01 << 10) +#define ISS_INSN_EA (0x01 << 9) +#define ISS_INSN_S1PTW (0x01 << 7) +#define ISS_INSN_IFSC_MASK (0x1f << 0) +#define ISS_DATA_ISV (0x01 << 24) +#define ISS_DATA_SAS_MASK (0x03 << 22) +#define ISS_DATA_SSE (0x01 << 21) +#define ISS_DATA_SRT_MASK (0x1f << 16) +#define ISS_DATA_SF (0x01 << 15) +#define ISS_DATA_AR (0x01 << 14) +#define ISS_DATA_FnV (0x01 << 10) +#define ISS_DATA_EA (0x01 << 9) +#define ISS_DATA_CM (0x01 << 8) +#define ISS_DATA_S1PTW (0x01 << 7) +#define ISS_DATA_WnR (0x01 << 6) +#define ISS_DATA_DFSC_MASK (0x3f << 0) +#define ISS_DATA_DFSC_ASF_L0 (0x00 << 0) +#define ISS_DATA_DFSC_ASF_L1 (0x01 << 0) +#define ISS_DATA_DFSC_ASF_L2 (0x02 << 0) +#define ISS_DATA_DFSC_ASF_L3 (0x03 << 0) +#define ISS_DATA_DFSC_TF_L0 (0x04 << 0) +#define ISS_DATA_DFSC_TF_L1 (0x05 << 0) +#define ISS_DATA_DFSC_TF_L2 (0x06 << 0) +#define ISS_DATA_DFSC_TF_L3 (0x07 << 0) +#define ISS_DATA_DFSC_AFF_L1 (0x09 << 0) +#define ISS_DATA_DFSC_AFF_L2 (0x0a << 0) +#define ISS_DATA_DFSC_AFF_L3 (0x0b << 0) +#define ISS_DATA_DFSC_PF_L1 (0x0d << 0) +#define ISS_DATA_DFSC_PF_L2 (0x0e << 0) +#define ISS_DATA_DFSC_PF_L3 (0x0f << 0) +#define ISS_DATA_DFSC_EXT (0x10 << 0) +#define ISS_DATA_DFSC_EXT_L0 (0x14 << 0) +#define ISS_DATA_DFSC_EXT_L1 (0x15 << 0) +#define ISS_DATA_DFSC_EXT_L2 (0x16 << 0) +#define ISS_DATA_DFSC_EXT_L3 (0x17 << 0) +#define ISS_DATA_DFSC_ECC (0x18 << 0) +#define ISS_DATA_DFSC_ECC_L0 (0x1c << 0) +#define ISS_DATA_DFSC_ECC_L1 (0x1d << 0) +#define ISS_DATA_DFSC_ECC_L2 (0x1e << 0) +#define ISS_DATA_DFSC_ECC_L3 (0x1f << 0) +#define ISS_DATA_DFSC_ALIGN (0x21 << 0) +#define ISS_DATA_DFSC_TLB_CONFLICT (0x30 << 0) +#define ISS_MSR_DIR_SHIFT 0 +#define ISS_MSR_DIR (0x01 << ISS_MSR_DIR_SHIFT) +#define ISS_MSR_Rt_SHIFT 5 +#define ISS_MSR_Rt_MASK (0x1f << ISS_MSR_Rt_SHIFT) +#define ISS_MSR_Rt(x) (((x) & ISS_MSR_Rt_MASK) >> ISS_MSR_Rt_SHIFT) +#define ISS_MSR_CRm_SHIFT 1 +#define ISS_MSR_CRm_MASK (0xf << ISS_MSR_CRm_SHIFT) +#define ISS_MSR_CRm(x) (((x) & ISS_MSR_CRm_MASK) >> ISS_MSR_CRm_SHIFT) +#define ISS_MSR_CRn_SHIFT 10 +#define ISS_MSR_CRn_MASK (0xf << ISS_MSR_CRn_SHIFT) +#define ISS_MSR_CRn(x) (((x) & ISS_MSR_CRn_MASK) >> ISS_MSR_CRn_SHIFT) +#define ISS_MSR_OP1_SHIFT 14 +#define ISS_MSR_OP1_MASK (0x7 << ISS_MSR_OP1_SHIFT) +#define ISS_MSR_OP1(x) (((x) & ISS_MSR_OP1_MASK) >> ISS_MSR_OP1_SHIFT) +#define ISS_MSR_OP2_SHIFT 17 +#define ISS_MSR_OP2_MASK (0x7 << ISS_MSR_OP2_SHIFT) +#define ISS_MSR_OP2(x) (((x) & ISS_MSR_OP2_MASK) >> ISS_MSR_OP2_SHIFT) +#define ISS_MSR_OP0_SHIFT 20 +#define ISS_MSR_OP0_MASK (0x3 << ISS_MSR_OP0_SHIFT) +#define ISS_MSR_OP0(x) (((x) & ISS_MSR_OP0_MASK) >> ISS_MSR_OP0_SHIFT) +#define ISS_BRK_COMMENT_MASK 0xffff +#define ESR_ELx_IL (0x01 << 25) +#define ESR_ELx_EC_SHIFT 26 +#define ESR_ELx_EC_MASK (0x3f << 26) +#define ESR_ELx_EXCEPTION(esr) (((esr) & ESR_ELx_EC_MASK) >> ESR_ELx_EC_SHIFT) +#define EXCP_UNKNOWN 0x00 /* Unkwn exception */ +#define EXCP_FP_SIMD 0x07 /* FP/SIMD trap */ +#define EXCP_BRANCH_TGT 0x0d /* Branch target exception */ +#define EXCP_ILL_STATE 0x0e /* Illegal execution state */ +#define EXCP_SVC 0x15 /* SVC trap */ +#define EXCP_MSR 0x18 /* MSR/MRS trap */ +#define EXCP_SVE 0x19 /* SVE trap */ +#define EXCP_FPAC 0x1c /* Faulting PAC trap */ +#define EXCP_INSN_ABORT_L 0x20 /* Instruction abort, from lower EL */ +#define EXCP_INSN_ABORT 0x21 /* Instruction abort, from same EL */ +#define EXCP_PC_ALIGN 0x22 /* PC alignment fault */ +#define EXCP_DATA_ABORT_L 0x24 /* Data abort, from lower EL */ +#define EXCP_DATA_ABORT 0x25 /* Data abort, from same EL */ +#define EXCP_SP_ALIGN 0x26 /* SP alignment fault */ +#define EXCP_TRAP_FP 0x2c /* Trapped FP exception */ +#define EXCP_SERROR 0x2f /* SError interrupt */ +#define EXCP_SOFTSTP_EL0 0x32 /* Software Step, from lower EL */ +#define EXCP_SOFTSTP_EL1 0x33 /* Software Step, from same EL */ +#define EXCP_WATCHPT_EL1 0x35 /* Watchpoint, from same EL */ +#define EXCP_BRK 0x3c /* Breakpoint */ + +/* ICC_CTLR_EL1 */ +#define ICC_CTLR_EL1_EOIMODE (1U << 1) +#define ICC_CTLR_EL1_PRIBITS_SHIFT 8 +#define ICC_CTLR_EL1_PRIBITS_MASK (0x7UL << 8) +#define ICC_CTLR_EL1_PRIBITS(reg) \ + (((reg) & ICC_CTLR_EL1_PRIBITS_MASK) >> ICC_CTLR_EL1_PRIBITS_SHIFT) + +/* ICC_IAR1_EL1 */ +#define ICC_IAR1_EL1_SPUR (0x03ff) + +/* ICC_IGRPEN0_EL1 */ +#define ICC_IGRPEN0_EL1_EN (1U << 0) + +/* ICC_PMR_EL1 */ +#define ICC_PMR_EL1_PRIO_MASK (0xFFUL) + +/* ICC_SGI1R_EL1 */ +#define ICC_SGI1R_EL1_TL_MASK 0xffffUL +#define ICC_SGI1R_EL1_AFF1_SHIFT 16 +#define ICC_SGI1R_EL1_SGIID_SHIFT 24 +#define ICC_SGI1R_EL1_AFF2_SHIFT 32 +#define ICC_SGI1R_EL1_AFF3_SHIFT 48 +#define ICC_SGI1R_EL1_SGIID_MASK 0xfUL +#define ICC_SGI1R_EL1_IRM (0x1UL << 40) + +/* ICC_SRE_EL1 */ +#define ICC_SRE_EL1_SRE (1U << 0) + +/* ICC_SRE_EL2 */ +#define ICC_SRE_EL2_SRE (1U << 0) +#define ICC_SRE_EL2_EN (1U << 3) + +/* ID_AA64DFR0_EL1 */ +#define ID_AA64DFR0_MASK 0x00000000f0f0ffffUL +#define ID_AA64DFR0_DEBUG_VER_SHIFT 0 +#define ID_AA64DFR0_DEBUG_VER_MASK (0xfULL << ID_AA64DFR0_DEBUG_VER_SHIFT) +#define ID_AA64DFR0_DEBUG_VER(x) ((x) & ID_AA64DFR0_DEBUG_VER_MASK) +#define ID_AA64DFR0_DEBUG_VER_8 (0x6ULL << ID_AA64DFR0_DEBUG_VER_SHIFT) +#define ID_AA64DFR0_DEBUG_VER_8_VHE (0x7ULL << ID_AA64DFR0_DEBUG_VER_SHIFT) +#define ID_AA64DFR0_TRACE_VER_SHIFT 4 +#define ID_AA64DFR0_TRACE_VER_MASK (0xfULL << ID_AA64DFR0_TRACE_VER_SHIFT) +#define ID_AA64DFR0_TRACE_VER(x) ((x) & ID_AA64DFR0_TRACE_VER_MASK) +#define ID_AA64DFR0_TRACE_VER_NONE (0x0ULL << ID_AA64DFR0_TRACE_VER_SHIFT) +#define ID_AA64DFR0_TRACE_VER_IMPL (0x1ULL << ID_AA64DFR0_TRACE_VER_SHIFT) +#define ID_AA64DFR0_PMU_VER_SHIFT 8 +#define ID_AA64DFR0_PMU_VER_MASK (0xfULL << ID_AA64DFR0_PMU_VER_SHIFT) +#define ID_AA64DFR0_PMU_VER(x) ((x) & ID_AA64DFR0_PMU_VER_MASK) +#define ID_AA64DFR0_PMU_VER_NONE (0x0ULL << ID_AA64DFR0_PMU_VER_SHIFT) +#define ID_AA64DFR0_PMU_VER_3 (0x1ULL << ID_AA64DFR0_PMU_VER_SHIFT) +#define ID_AA64DFR0_PMU_VER_3_1 (0x4ULL << ID_AA64DFR0_PMU_VER_SHIFT) +#define ID_AA64DFR0_PMU_VER_IMPL (0xfULL << ID_AA64DFR0_PMU_VER_SHIFT) +#define ID_AA64DFR0_BRPS_SHIFT 12 +#define ID_AA64DFR0_BRPS_MASK (0xfULL << ID_AA64DFR0_BRPS_SHIFT) +#define ID_AA64DFR0_BRPS(x) \ + ((((x) >> ID_AA64DFR0_BRPS_SHIFT) & 0xf) + 1) +#define ID_AA64DFR0_WRPS_SHIFT 20 +#define ID_AA64DFR0_WRPS_MASK (0xfULL << ID_AA64DFR0_WRPS_SHIFT) +#define ID_AA64DFR0_WRPS(x) \ + ((((x) >> ID_AA64DFR0_WRPS_SHIFT) & 0xf) + 1) +#define ID_AA64DFR0_CTX_CMPS_SHIFT 28 +#define ID_AA64DFR0_CTX_CMPS_MASK (0xfULL << ID_AA64DFR0_CTX_CMPS_SHIFT) +#define ID_AA64DFR0_CTX_CMPS(x) \ + ((((x) >> ID_AA64DFR0_CTX_CMPS_SHIFT) & 0xf) + 1) + +/* ID_AA64ISAR0_EL1 */ +#define ID_AA64ISAR0_MASK 0xfffffffff0fffff0ULL +#define ID_AA64ISAR0_AES_SHIFT 4 +#define ID_AA64ISAR0_AES_MASK (0xfULL << ID_AA64ISAR0_AES_SHIFT) +#define ID_AA64ISAR0_AES(x) ((x) & ID_AA64ISAR0_AES_MASK) +#define ID_AA64ISAR0_AES_NONE (0x0ULL << ID_AA64ISAR0_AES_SHIFT) +#define ID_AA64ISAR0_AES_BASE (0x1ULL << ID_AA64ISAR0_AES_SHIFT) +#define ID_AA64ISAR0_AES_PMULL (0x2ULL << ID_AA64ISAR0_AES_SHIFT) +#define ID_AA64ISAR0_SHA1_SHIFT 8 +#define ID_AA64ISAR0_SHA1_MASK (0xfULL << ID_AA64ISAR0_SHA1_SHIFT) +#define ID_AA64ISAR0_SHA1(x) ((x) & ID_AA64ISAR0_SHA1_MASK) +#define ID_AA64ISAR0_SHA1_NONE (0x0ULL << ID_AA64ISAR0_SHA1_SHIFT) +#define ID_AA64ISAR0_SHA1_BASE (0x1ULL << ID_AA64ISAR0_SHA1_SHIFT) +#define ID_AA64ISAR0_SHA2_SHIFT 12 +#define ID_AA64ISAR0_SHA2_MASK (0xfULL << ID_AA64ISAR0_SHA2_SHIFT) +#define ID_AA64ISAR0_SHA2(x) ((x) & ID_AA64ISAR0_SHA2_MASK) +#define ID_AA64ISAR0_SHA2_NONE (0x0ULL << ID_AA64ISAR0_SHA2_SHIFT) +#define ID_AA64ISAR0_SHA2_BASE (0x1ULL << ID_AA64ISAR0_SHA2_SHIFT) +#define ID_AA64ISAR0_SHA2_512 (0x2ULL << ID_AA64ISAR0_SHA2_SHIFT) +#define ID_AA64ISAR0_CRC32_SHIFT 16 +#define ID_AA64ISAR0_CRC32_MASK (0xfULL << ID_AA64ISAR0_CRC32_SHIFT) +#define ID_AA64ISAR0_CRC32(x) ((x) & ID_AA64ISAR0_CRC32_MASK) +#define ID_AA64ISAR0_CRC32_NONE (0x0ULL << ID_AA64ISAR0_CRC32_SHIFT) +#define ID_AA64ISAR0_CRC32_BASE (0x1ULL << ID_AA64ISAR0_CRC32_SHIFT) +#define ID_AA64ISAR0_ATOMIC_SHIFT 20 +#define ID_AA64ISAR0_ATOMIC_MASK (0xfULL << ID_AA64ISAR0_ATOMIC_SHIFT) +#define ID_AA64ISAR0_ATOMIC(x) ((x) & ID_AA64ISAR0_ATOMIC_MASK) +#define ID_AA64ISAR0_ATOMIC_NONE (0x0ULL << ID_AA64ISAR0_ATOMIC_SHIFT) +#define ID_AA64ISAR0_ATOMIC_IMPL (0x2ULL << ID_AA64ISAR0_ATOMIC_SHIFT) +#define ID_AA64ISAR0_RDM_SHIFT 28 +#define ID_AA64ISAR0_RDM_MASK (0xfULL << ID_AA64ISAR0_RDM_SHIFT) +#define ID_AA64ISAR0_RDM(x) ((x) & ID_AA64ISAR0_RDM_MASK) +#define ID_AA64ISAR0_RDM_NONE (0x0ULL << ID_AA64ISAR0_RDM_SHIFT) +#define ID_AA64ISAR0_RDM_IMPL (0x1ULL << ID_AA64ISAR0_RDM_SHIFT) +#define ID_AA64ISAR0_SHA3_SHIFT 32 +#define ID_AA64ISAR0_SHA3_MASK (0xfULL << ID_AA64ISAR0_SHA3_SHIFT) +#define ID_AA64ISAR0_SHA3(x) ((x) & ID_AA64ISAR0_SHA3_MASK) +#define ID_AA64ISAR0_SHA3_NONE (0x0ULL << ID_AA64ISAR0_SHA3_SHIFT) +#define ID_AA64ISAR0_SHA3_IMPL (0x1ULL << ID_AA64ISAR0_SHA3_SHIFT) +#define ID_AA64ISAR0_SM3_SHIFT 36 +#define ID_AA64ISAR0_SM3_MASK (0xfULL << ID_AA64ISAR0_SM3_SHIFT) +#define ID_AA64ISAR0_SM3(x) ((x) & ID_AA64ISAR0_SM3_MASK) +#define ID_AA64ISAR0_SM3_NONE (0x0ULL << ID_AA64ISAR0_SM3_SHIFT) +#define ID_AA64ISAR0_SM3_IMPL (0x1ULL << ID_AA64ISAR0_SM3_SHIFT) +#define ID_AA64ISAR0_SM4_SHIFT 40 +#define ID_AA64ISAR0_SM4_MASK (0xfULL << ID_AA64ISAR0_SM4_SHIFT) +#define ID_AA64ISAR0_SM4(x) ((x) & ID_AA64ISAR0_SM4_MASK) +#define ID_AA64ISAR0_SM4_NONE (0x0ULL << ID_AA64ISAR0_SM4_SHIFT) +#define ID_AA64ISAR0_SM4_IMPL (0x1ULL << ID_AA64ISAR0_SM4_SHIFT) +#define ID_AA64ISAR0_DP_SHIFT 44 +#define ID_AA64ISAR0_DP_MASK (0xfULL << ID_AA64ISAR0_DP_SHIFT) +#define ID_AA64ISAR0_DP(x) ((x) & ID_AA64ISAR0_DP_MASK) +#define ID_AA64ISAR0_DP_NONE (0x0ULL << ID_AA64ISAR0_DP_SHIFT) +#define ID_AA64ISAR0_DP_IMPL (0x1ULL << ID_AA64ISAR0_DP_SHIFT) +#define ID_AA64ISAR0_FHM_SHIFT 48 +#define ID_AA64ISAR0_FHM_MASK (0xfULL << ID_AA64ISAR0_FHM_SHIFT) +#define ID_AA64ISAR0_FHM(x) ((x) & ID_AA64ISAR0_FHM_MASK) +#define ID_AA64ISAR0_FHM_NONE (0x0ULL << ID_AA64ISAR0_FHM_SHIFT) +#define ID_AA64ISAR0_FHM_IMPL (0x1ULL << ID_AA64ISAR0_FHM_SHIFT) +#define ID_AA64ISAR0_TS_SHIFT 52 +#define ID_AA64ISAR0_TS_MASK (0xfULL << ID_AA64ISAR0_TS_SHIFT) +#define ID_AA64ISAR0_TS(x) ((x) & ID_AA64ISAR0_TS_MASK) +#define ID_AA64ISAR0_TS_NONE (0x0ULL << ID_AA64ISAR0_TS_SHIFT) +#define ID_AA64ISAR0_TS_BASE (0x1ULL << ID_AA64ISAR0_TS_SHIFT) +#define ID_AA64ISAR0_TS_AXFLAG (0x2ULL << ID_AA64ISAR0_TS_SHIFT) +#define ID_AA64ISAR0_TLB_SHIFT 56 +#define ID_AA64ISAR0_TLB_MASK (0xfULL << ID_AA64ISAR0_TLB_SHIFT) +#define ID_AA64ISAR0_TLB(x) ((x) & ID_AA64ISAR0_TLB_MASK) +#define ID_AA64ISAR0_TLB_NONE (0x0ULL << ID_AA64ISAR0_TLB_SHIFT) +#define ID_AA64ISAR0_TLB_IOS (0x1ULL << ID_AA64ISAR0_TLB_SHIFT) +#define ID_AA64ISAR0_TLB_IRANGE (0x2ULL << ID_AA64ISAR0_TLB_SHIFT) +#define ID_AA64ISAR0_RNDR_SHIFT 60 +#define ID_AA64ISAR0_RNDR_MASK (0xfULL << ID_AA64ISAR0_RNDR_SHIFT) +#define ID_AA64ISAR0_RNDR(x) ((x) & ID_AA64ISAR0_RNDR_MASK) +#define ID_AA64ISAR0_RNDR_NONE (0x0ULL << ID_AA64ISAR0_RNDR_SHIFT) +#define ID_AA64ISAR0_RNDR_IMPL (0x1ULL << ID_AA64ISAR0_RNDR_SHIFT) + +/* ID_AA64ISAR1_EL1 */ +#define ID_AA64ISAR1_MASK 0xffffffffffffffffULL +#define ID_AA64ISAR1_DPB_SHIFT 0 +#define ID_AA64ISAR1_DPB_MASK (0xfULL << ID_AA64ISAR1_DPB_SHIFT) +#define ID_AA64ISAR1_DPB(x) ((x) & ID_AA64ISAR1_DPB_MASK) +#define ID_AA64ISAR1_DPB_NONE (0x0ULL << ID_AA64ISAR1_DPB_SHIFT) +#define ID_AA64ISAR1_DPB_IMPL (0x1ULL << ID_AA64ISAR1_DPB_SHIFT) +#define ID_AA64ISAR1_DPB_DCCVADP (0x2ULL << ID_AA64ISAR1_DPB_SHIFT) +#define ID_AA64ISAR1_APA_SHIFT 4 +#define ID_AA64ISAR1_APA_MASK (0xfULL << ID_AA64ISAR1_APA_SHIFT) +#define ID_AA64ISAR1_APA(x) ((x) & ID_AA64ISAR1_APA_MASK) +#define ID_AA64ISAR1_APA_NONE (0x0ULL << ID_AA64ISAR1_APA_SHIFT) +#define ID_AA64ISAR1_APA_PAC (0x1ULL << ID_AA64ISAR1_APA_SHIFT) +#define ID_AA64ISAR1_APA_EPAC (0x2ULL << ID_AA64ISAR1_APA_SHIFT) +#define ID_AA64ISAR1_APA_EPAC2 (0x3ULL << ID_AA64ISAR1_APA_SHIFT) +#define ID_AA64ISAR1_APA_FPAC (0x4ULL << ID_AA64ISAR1_APA_SHIFT) +#define ID_AA64ISAR1_APA_FPAC_COMBINED (0x5ULL << ID_AA64ISAR1_APA_SHIFT) +#define ID_AA64ISAR1_API_SHIFT 8 +#define ID_AA64ISAR1_API_MASK (0xfULL << ID_AA64ISAR1_API_SHIFT) +#define ID_AA64ISAR1_API(x) ((x) & ID_AA64ISAR1_API_MASK) +#define ID_AA64ISAR1_API_NONE (0x0ULL << ID_AA64ISAR1_API_SHIFT) +#define ID_AA64ISAR1_API_PAC (0x1ULL << ID_AA64ISAR1_API_SHIFT) +#define ID_AA64ISAR1_API_EPAC (0x2ULL << ID_AA64ISAR1_API_SHIFT) +#define ID_AA64ISAR1_API_EPAC2 (0x3ULL << ID_AA64ISAR1_API_SHIFT) +#define ID_AA64ISAR1_API_FPAC (0x4ULL << ID_AA64ISAR1_API_SHIFT) +#define ID_AA64ISAR1_API_FPAC_COMBINED (0x5ULL << ID_AA64ISAR1_API_SHIFT) +#define ID_AA64ISAR1_JSCVT_SHIFT 12 +#define ID_AA64ISAR1_JSCVT_MASK (0xfULL << ID_AA64ISAR1_JSCVT_SHIFT) +#define ID_AA64ISAR1_JSCVT(x) ((x) & ID_AA64ISAR1_JSCVT_MASK) +#define ID_AA64ISAR1_JSCVT_NONE (0x0ULL << ID_AA64ISAR1_JSCVT_SHIFT) +#define ID_AA64ISAR1_JSCVT_IMPL (0x1ULL << ID_AA64ISAR1_JSCVT_SHIFT) +#define ID_AA64ISAR1_FCMA_SHIFT 16 +#define ID_AA64ISAR1_FCMA_MASK (0xfULL << ID_AA64ISAR1_FCMA_SHIFT) +#define ID_AA64ISAR1_FCMA(x) ((x) & ID_AA64ISAR1_FCMA_MASK) +#define ID_AA64ISAR1_FCMA_NONE (0x0ULL << ID_AA64ISAR1_FCMA_SHIFT) +#define ID_AA64ISAR1_FCMA_IMPL (0x1ULL << ID_AA64ISAR1_FCMA_SHIFT) +#define ID_AA64ISAR1_LRCPC_SHIFT 20 +#define ID_AA64ISAR1_LRCPC_MASK (0xfULL << ID_AA64ISAR1_LRCPC_SHIFT) +#define ID_AA64ISAR1_LRCPC(x) ((x) & ID_AA64ISAR1_LRCPC_MASK) +#define ID_AA64ISAR1_LRCPC_NONE (0x0ULL << ID_AA64ISAR1_LRCPC_SHIFT) +#define ID_AA64ISAR1_LRCPC_BASE (0x1ULL << ID_AA64ISAR1_LRCPC_SHIFT) +#define ID_AA64ISAR1_LRCPC_LDAPUR (0x2ULL << ID_AA64ISAR1_LRCPC_SHIFT) +#define ID_AA64ISAR1_GPA_SHIFT 24 +#define ID_AA64ISAR1_GPA_MASK (0xfULL << ID_AA64ISAR1_GPA_SHIFT) +#define ID_AA64ISAR1_GPA(x) ((x) & ID_AA64ISAR1_GPA_MASK) +#define ID_AA64ISAR1_GPA_NONE (0x0ULL << ID_AA64ISAR1_GPA_SHIFT) +#define ID_AA64ISAR1_GPA_IMPL (0x1ULL << ID_AA64ISAR1_GPA_SHIFT) +#define ID_AA64ISAR1_GPI_SHIFT 28 +#define ID_AA64ISAR1_GPI_MASK (0xfULL << ID_AA64ISAR1_GPI_SHIFT) +#define ID_AA64ISAR1_GPI(x) ((x) & ID_AA64ISAR1_GPI_MASK) +#define ID_AA64ISAR1_GPI_NONE (0x0ULL << ID_AA64ISAR1_GPI_SHIFT) +#define ID_AA64ISAR1_GPI_IMPL (0x1ULL << ID_AA64ISAR1_GPI_SHIFT) +#define ID_AA64ISAR1_FRINTTS_SHIFT 32 +#define ID_AA64ISAR1_FRINTTS_MASK (0xfULL << ID_AA64ISAR1_FRINTTS_SHIFT) +#define ID_AA64ISAR1_FRINTTS(x) ((x) & ID_AA64ISAR1_FRINTTS_MASK) +#define ID_AA64ISAR1_FRINTTS_NONE (0x0ULL << ID_AA64ISAR1_FRINTTS_SHIFT) +#define ID_AA64ISAR1_FRINTTS_IMPL (0x1ULL << ID_AA64ISAR1_FRINTTS_SHIFT) +#define ID_AA64ISAR1_SB_SHIFT 36 +#define ID_AA64ISAR1_SB_MASK (0xfULL << ID_AA64ISAR1_SB_SHIFT) +#define ID_AA64ISAR1_SB(x) ((x) & ID_AA64ISAR1_SB_MASK) +#define ID_AA64ISAR1_SB_NONE (0x0ULL << ID_AA64ISAR1_SB_SHIFT) +#define ID_AA64ISAR1_SB_IMPL (0x1ULL << ID_AA64ISAR1_SB_SHIFT) +#define ID_AA64ISAR1_SPECRES_SHIFT 40 +#define ID_AA64ISAR1_SPECRES_MASK (0xfULL << ID_AA64ISAR1_SPECRES_SHIFT) +#define ID_AA64ISAR1_SPECRES(x) ((x) & ID_AA64ISAR1_SPECRES_MASK) +#define ID_AA64ISAR1_SPECRES_NONE (0x0ULL << ID_AA64ISAR1_SPECRES_SHIFT) +#define ID_AA64ISAR1_SPECRES_IMPL (0x1ULL << ID_AA64ISAR1_SPECRES_SHIFT) +#define ID_AA64ISAR1_BF16_SHIFT 44 +#define ID_AA64ISAR1_BF16_MASK (0xfULL << ID_AA64ISAR1_BF16_SHIFT) +#define ID_AA64ISAR1_BF16(x) ((x) & ID_AA64ISAR1_BF16_MASK) +#define ID_AA64ISAR1_BF16_NONE (0x0ULL << ID_AA64ISAR1_BF16_SHIFT) +#define ID_AA64ISAR1_BF16_BASE (0x1ULL << ID_AA64ISAR1_BF16_SHIFT) +#define ID_AA64ISAR1_BF16_EBF (0x2ULL << ID_AA64ISAR1_BF16_SHIFT) +#define ID_AA64ISAR1_DGH_SHIFT 48 +#define ID_AA64ISAR1_DGH_MASK (0xfULL << ID_AA64ISAR1_DGH_SHIFT) +#define ID_AA64ISAR1_DGH(x) ((x) & ID_AA64ISAR1_DGH_MASK) +#define ID_AA64ISAR1_DGH_NONE (0x0ULL << ID_AA64ISAR1_DGH_SHIFT) +#define ID_AA64ISAR1_DGH_IMPL (0x1ULL << ID_AA64ISAR1_DGH_SHIFT) +#define ID_AA64ISAR1_I8MM_SHIFT 52 +#define ID_AA64ISAR1_I8MM_MASK (0xfULL << ID_AA64ISAR1_I8MM_SHIFT) +#define ID_AA64ISAR1_I8MM(x) ((x) & ID_AA64ISAR1_I8MM_MASK) +#define ID_AA64ISAR1_I8MM_NONE (0x0ULL << ID_AA64ISAR1_I8MM_SHIFT) +#define ID_AA64ISAR1_I8MM_IMPL (0x1ULL << ID_AA64ISAR1_I8MM_SHIFT) +#define ID_AA64ISAR1_XS_SHIFT 56 +#define ID_AA64ISAR1_XS_MASK (0xfULL << ID_AA64ISAR1_XS_SHIFT) +#define ID_AA64ISAR1_XS(x) ((x) & ID_AA64ISAR1_XS_MASK) +#define ID_AA64ISAR1_XS_NONE (0x0ULL << ID_AA64ISAR1_XS_SHIFT) +#define ID_AA64ISAR1_XS_IMPL (0x1ULL << ID_AA64ISAR1_XS_SHIFT) +#define ID_AA64ISAR1_LS64_SHIFT 60 +#define ID_AA64ISAR1_LS64_MASK (0xfULL << ID_AA64ISAR1_LS64_SHIFT) +#define ID_AA64ISAR1_LS64(x) ((x) & ID_AA64ISAR1_LS64_MASK) +#define ID_AA64ISAR1_LS64_NONE (0x0ULL << ID_AA64ISAR1_LS64_SHIFT) +#define ID_AA64ISAR1_LS64_BASE (0x1ULL << ID_AA64ISAR1_LS64_SHIFT) +#define ID_AA64ISAR1_LS64_V (0x2ULL << ID_AA64ISAR1_LS64_SHIFT) +#define ID_AA64ISAR1_LS64_ACCDATA (0x3ULL << ID_AA64ISAR1_LS64_SHIFT) + +/* ID_AA64ISAR2_EL1 */ +#define ID_AA64ISAR2_MASK 0x00ff0000f0ffffffULL +#define ID_AA64ISAR2_WFXT_SHIFT 0 +#define ID_AA64ISAR2_WFXT_MASK (0xfULL << ID_AA64ISAR2_WFXT_SHIFT) +#define ID_AA64ISAR2_WFXT(x) ((x) & ID_AA64ISAR2_WFXT_MASK) +#define ID_AA64ISAR2_WFXT_NONE (0x0ULL << ID_AA64ISAR2_WFXT_SHIFT) +#define ID_AA64ISAR2_WFXT_IMPL (0x2ULL << ID_AA64ISAR2_WFXT_SHIFT) +#define ID_AA64ISAR2_RPRES_SHIFT 4 +#define ID_AA64ISAR2_RPRES_MASK (0xfULL << ID_AA64ISAR2_RPRES_SHIFT) +#define ID_AA64ISAR2_RPRES(x) ((x) & ID_AA64ISAR2_RPRES_MASK) +#define ID_AA64ISAR2_RPRES_NONE (0x0ULL << ID_AA64ISAR2_RPRES_SHIFT) +#define ID_AA64ISAR2_RPRES_IMPL (0x1ULL << ID_AA64ISAR2_RPRES_SHIFT) +#define ID_AA64ISAR2_GPA3_SHIFT 8 +#define ID_AA64ISAR2_GPA3_WIDTH 4 +#define ID_AA64ISAR2_GPA3_MASK (0xfULL << ID_AA64ISAR2_GPA3_SHIFT) +#define ID_AA64ISAR2_GPA3(x) ((x) & ID_AA64ISAR2_GPA3_MASK) +#define ID_AA64ISAR2_GPA3_NONE (0x0ULL << ID_AA64ISAR2_GPA3_SHIFT) +#define ID_AA64ISAR2_GPA3_IMPL (0x1ULL << ID_AA64ISAR2_GPA3_SHIFT) +#define ID_AA64ISAR2_APA3_SHIFT 12 +#define ID_AA64ISAR2_APA3_WIDTH 4 +#define ID_AA64ISAR2_APA3_MASK (0xfULL << ID_AA64ISAR2_APA3_SHIFT) +#define ID_AA64ISAR2_APA3(x) ((x) & ID_AA64ISAR2_APA3_MASK) +#define ID_AA64ISAR2_APA3_NONE (0x0ULL << ID_AA64ISAR2_APA3_SHIFT) +#define ID_AA64ISAR2_APA3_PAC (0x1ULL << ID_AA64ISAR2_APA3_SHIFT) +#define ID_AA64ISAR2_APA3_EPAC (0x2ULL << ID_AA64ISAR2_APA3_SHIFT) +#define ID_AA64ISAR2_APA3_EPAC2 (0x3ULL << ID_AA64ISAR2_APA3_SHIFT) +#define ID_AA64ISAR2_APA3_FPAC (0x4ULL << ID_AA64ISAR2_APA3_SHIFT) +#define ID_AA64ISAR2_APA3_FPAC_COMBINED (0x5ULL << ID_AA64ISAR2_APA3_SHIFT) +#define ID_AA64ISAR2_MOPS_SHIFT 16 +#define ID_AA64ISAR2_MOPS_MASK (0xfULL << ID_AA64ISAR2_MOPS_SHIFT) +#define ID_AA64ISAR2_MOPS(x) ((x) & ID_AA64ISAR2_MOPS_MASK) +#define ID_AA64ISAR2_MOPS_NONE (0x0ULL << ID_AA64ISAR2_MOPS_SHIFT) +#define ID_AA64ISAR2_MOPS_IMPL (0x1ULL << ID_AA64ISAR2_MOPS_SHIFT) +#define ID_AA64ISAR2_BC_SHIFT 20 +#define ID_AA64ISAR2_BC_MASK (0xfULL << ID_AA64ISAR2_BC_SHIFT) +#define ID_AA64ISAR2_BC(x) ((x) & ID_AA64ISAR2_BC_MASK) +#define ID_AA64ISAR2_BC_NONE (0x0ULL << ID_AA64ISAR2_BC_SHIFT) +#define ID_AA64ISAR2_BC_IMPL (0x1ULL << ID_AA64ISAR2_BC_SHIFT) +#define ID_AA64ISAR2_CLRBHB_SHIFT 28 +#define ID_AA64ISAR2_CLRBHB_MASK (0xfULL << ID_AA64ISAR2_CLRBHB_SHIFT) +#define ID_AA64ISAR2_CLRBHB(x) ((x) & ID_AA64ISAR2_CLRBHB_MASK) +#define ID_AA64ISAR2_CLRBHB_NONE (0x0ULL << ID_AA64ISAR2_CLRBHB_SHIFT) +#define ID_AA64ISAR2_CLRBHB_IMPL (0x1ULL << ID_AA64ISAR2_CLRBHB_SHIFT) +#define ID_AA64ISAR2_RPRFM_SHIFT 48 +#define ID_AA64ISAR2_RPRFM_MASK (0xfULL << ID_AA64ISAR2_RPRFM_SHIFT) +#define ID_AA64ISAR2_RPRFM(x) ((x) & ID_AA64ISAR2_RPRFM_MASK) +#define ID_AA64ISAR2_RPRFM_NONE (0x0ULL << ID_AA64ISAR2_RPRFM_SHIFT) +#define ID_AA64ISAR2_RPRFM_IMPL (0x1ULL << ID_AA64ISAR2_RPRFM_SHIFT) +#define ID_AA64ISAR2_CSSC_SHIFT 52 +#define ID_AA64ISAR2_CSSC_MASK (0xfULL << ID_AA64ISAR2_CSSC_SHIFT) +#define ID_AA64ISAR2_CSSC(x) ((x) & ID_AA64ISAR2_CSSC_MASK) +#define ID_AA64ISAR2_CSSC_NONE (0x0ULL << ID_AA64ISAR2_CSSC_SHIFT) +#define ID_AA64ISAR2_CSSC_IMPL (0x1ULL << ID_AA64ISAR2_CSSC_SHIFT) + +/* ID_AA64MMFR0_EL1 */ +#define ID_AA64MMFR0_MASK 0xf0000000ffffffffULL +#define ID_AA64MMFR0_PA_RANGE_SHIFT 0 +#define ID_AA64MMFR0_PA_RANGE_MASK (0xfULL << ID_AA64MMFR0_PA_RANGE_SHIFT) +#define ID_AA64MMFR0_PA_RANGE(x) ((x) & ID_AA64MMFR0_PA_RANGE_MASK) +#define ID_AA64MMFR0_PA_RANGE_4G (0x0ULL << ID_AA64MMFR0_PA_RANGE_SHIFT) +#define ID_AA64MMFR0_PA_RANGE_64G (0x1ULL << ID_AA64MMFR0_PA_RANGE_SHIFT) +#define ID_AA64MMFR0_PA_RANGE_1T (0x2ULL << ID_AA64MMFR0_PA_RANGE_SHIFT) +#define ID_AA64MMFR0_PA_RANGE_4T (0x3ULL << ID_AA64MMFR0_PA_RANGE_SHIFT) +#define ID_AA64MMFR0_PA_RANGE_16T (0x4ULL << ID_AA64MMFR0_PA_RANGE_SHIFT) +#define ID_AA64MMFR0_PA_RANGE_256T (0x5ULL << ID_AA64MMFR0_PA_RANGE_SHIFT) +#define ID_AA64MMFR0_ASID_BITS_SHIFT 4 +#define ID_AA64MMFR0_ASID_BITS_MASK (0xfULL << ID_AA64MMFR0_ASID_BITS_SHIFT) +#define ID_AA64MMFR0_ASID_BITS(x) ((x) & ID_AA64MMFR0_ASID_BITS_MASK) +#define ID_AA64MMFR0_ASID_BITS_8 (0x0ULL << ID_AA64MMFR0_ASID_BITS_SHIFT) +#define ID_AA64MMFR0_ASID_BITS_16 (0x2ULL << ID_AA64MMFR0_ASID_BITS_SHIFT) +#define ID_AA64MMFR0_BIGEND_SHIFT 8 +#define ID_AA64MMFR0_BIGEND_MASK (0xfULL << ID_AA64MMFR0_BIGEND_SHIFT) +#define ID_AA64MMFR0_BIGEND(x) ((x) & ID_AA64MMFR0_BIGEND_MASK) +#define ID_AA64MMFR0_BIGEND_FIXED (0x0ULL << ID_AA64MMFR0_BIGEND_SHIFT) +#define ID_AA64MMFR0_BIGEND_MIXED (0x1ULL << ID_AA64MMFR0_BIGEND_SHIFT) +#define ID_AA64MMFR0_S_NS_MEM_SHIFT 12 +#define ID_AA64MMFR0_S_NS_MEM_MASK (0xfULL << ID_AA64MMFR0_S_NS_MEM_SHIFT) +#define ID_AA64MMFR0_S_NS_MEM(x) ((x) & ID_AA64MMFR0_S_NS_MEM_MASK) +#define ID_AA64MMFR0_S_NS_MEM_NONE (0x0ULL << ID_AA64MMFR0_S_NS_MEM_SHIFT) +#define ID_AA64MMFR0_S_NS_MEM_DISTINCT (0x1ULL << ID_AA64MMFR0_S_NS_MEM_SHIFT) +#define ID_AA64MMFR0_BIGEND_EL0_SHIFT 16 +#define ID_AA64MMFR0_BIGEND_EL0_MASK (0xfULL << ID_AA64MMFR0_BIGEND_EL0_SHIFT) +#define ID_AA64MMFR0_BIGEND_EL0(x) ((x) & ID_AA64MMFR0_BIGEND_EL0_MASK) +#define ID_AA64MMFR0_BIGEND_EL0_FIXED (0x0ULL << ID_AA64MMFR0_BIGEND_EL0_SHIFT) +#define ID_AA64MMFR0_BIGEND_EL0_MIXED (0x1ULL << ID_AA64MMFR0_BIGEND_EL0_SHIFT) +#define ID_AA64MMFR0_TGRAN16_SHIFT 20 +#define ID_AA64MMFR0_TGRAN16_MASK (0xfULL << ID_AA64MMFR0_TGRAN16_SHIFT) +#define ID_AA64MMFR0_TGRAN16(x) ((x) & ID_AA64MMFR0_TGRAN16_MASK) +#define ID_AA64MMFR0_TGRAN16_NONE (0x0ULL << ID_AA64MMFR0_TGRAN16_SHIFT) +#define ID_AA64MMFR0_TGRAN16_IMPL (0x1ULL << ID_AA64MMFR0_TGRAN16_SHIFT) +#define ID_AA64MMFR0_TGRAN64_SHIFT 24 +#define ID_AA64MMFR0_TGRAN64_MASK (0xfULL << ID_AA64MMFR0_TGRAN64_SHIFT) +#define ID_AA64MMFR0_TGRAN64(x) ((x) & ID_AA64MMFR0_TGRAN64_MASK) +#define ID_AA64MMFR0_TGRAN64_IMPL (0x0ULL << ID_AA64MMFR0_TGRAN64_SHIFT) +#define ID_AA64MMFR0_TGRAN64_NONE (0xfULL << ID_AA64MMFR0_TGRAN64_SHIFT) +#define ID_AA64MMFR0_TGRAN4_SHIFT 28 +#define ID_AA64MMFR0_TGRAN4_MASK (0xfULL << ID_AA64MMFR0_TGRAN4_SHIFT) +#define ID_AA64MMFR0_TGRAN4(x) ((x) & ID_AA64MMFR0_TGRAN4_MASK) +#define ID_AA64MMFR0_TGRAN4_IMPL (0x0ULL << ID_AA64MMFR0_TGRAN4_SHIFT) +#define ID_AA64MMFR0_TGRAN4_NONE (0xfULL << ID_AA64MMFR0_TGRAN4_SHIFT) +#define ID_AA64MMFR0_ECV_SHIFT 60 +#define ID_AA64MMFR0_ECV_MASK (0xfULL << ID_AA64MMFR0_ECV_SHIFT) +#define ID_AA64MMFR0_ECV(x) ((x) & ID_AA64MMFR0_ECV_MASK) +#define ID_AA64MMFR0_ECV_NONE (0x0ULL << ID_AA64MMFR0_ECV_SHIFT) +#define ID_AA64MMFR0_ECV_IMPL (0x1ULL << ID_AA64MMFR0_ECV_SHIFT) +#define ID_AA64MMFR0_ECV_CNTHCTL (0x2ULL << ID_AA64MMFR0_ECV_SHIFT) + +/* ID_AA64MMFR1_EL1 */ +#define ID_AA64MMFR1_MASK 0xf000f000ffffffffULL +#define ID_AA64MMFR1_HAFDBS_SHIFT 0 +#define ID_AA64MMFR1_HAFDBS_MASK (0xfULL << ID_AA64MMFR1_HAFDBS_SHIFT) +#define ID_AA64MMFR1_HAFDBS(x) ((x) & ID_AA64MMFR1_HAFDBS_MASK) +#define ID_AA64MMFR1_HAFDBS_NONE (0x0ULL << ID_AA64MMFR1_HAFDBS_SHIFT) +#define ID_AA64MMFR1_HAFDBS_AF (0x1ULL << ID_AA64MMFR1_HAFDBS_SHIFT) +#define ID_AA64MMFR1_HAFDBS_AF_DBS (0x2ULL << ID_AA64MMFR1_HAFDBS_SHIFT) +#define ID_AA64MMFR1_VMIDBITS_SHIFT 4 +#define ID_AA64MMFR1_VMIDBITS_MASK (0xfULL << ID_AA64MMFR1_VMIDBITS_SHIFT) +#define ID_AA64MMFR1_VMIDBITS(x) ((x) & ID_AA64MMFR1_VMIDBITS_MASK) +#define ID_AA64MMFR1_VMIDBITS_8 (0x0ULL << ID_AA64MMFR1_VMIDBITS_SHIFT) +#define ID_AA64MMFR1_VMIDBITS_16 (0x2ULL << ID_AA64MMFR1_VMIDBITS_SHIFT) +#define ID_AA64MMFR1_VH_SHIFT 8 +#define ID_AA64MMFR1_VH_MASK (0xfULL << ID_AA64MMFR1_VH_SHIFT) +#define ID_AA64MMFR1_VH(x) ((x) & ID_AA64MMFR1_VH_MASK) +#define ID_AA64MMFR1_VH_NONE (0x0ULL << ID_AA64MMFR1_VH_SHIFT) +#define ID_AA64MMFR1_VH_IMPL (0x1ULL << ID_AA64MMFR1_VH_SHIFT) +#define ID_AA64MMFR1_HPDS_SHIFT 12 +#define ID_AA64MMFR1_HPDS_MASK (0xfULL << ID_AA64MMFR1_HPDS_SHIFT) +#define ID_AA64MMFR1_HPDS(x) ((x) & ID_AA64MMFR1_HPDS_MASK) +#define ID_AA64MMFR1_HPDS_NONE (0x0ULL << ID_AA64MMFR1_HPDS_SHIFT) +#define ID_AA64MMFR1_HPDS_IMPL (0x1ULL << ID_AA64MMFR1_HPDS_SHIFT) +#define ID_AA64MMFR1_LO_SHIFT 16 +#define ID_AA64MMFR1_LO_MASK (0xfULL << ID_AA64MMFR1_LO_SHIFT) +#define ID_AA64MMFR1_LO(x) ((x) & ID_AA64MMFR1_LO_MASK) +#define ID_AA64MMFR1_LO_NONE (0x0ULL << ID_AA64MMFR1_LO_SHIFT) +#define ID_AA64MMFR1_LO_IMPL (0x1ULL << ID_AA64MMFR1_LO_SHIFT) +#define ID_AA64MMFR1_PAN_SHIFT 20 +#define ID_AA64MMFR1_PAN_MASK (0xfULL << ID_AA64MMFR1_PAN_SHIFT) +#define ID_AA64MMFR1_PAN(x) ((x) & ID_AA64MMFR1_PAN_MASK) +#define ID_AA64MMFR1_PAN_NONE (0x0ULL << ID_AA64MMFR1_PAN_SHIFT) +#define ID_AA64MMFR1_PAN_IMPL (0x1ULL << ID_AA64MMFR1_PAN_SHIFT) +#define ID_AA64MMFR1_PAN_ATS1E1 (0x2ULL << ID_AA64MMFR1_PAN_SHIFT) +#define ID_AA64MMFR1_PAN_EPAN (0x3ULL << ID_AA64MMFR1_PAN_SHIFT) +#define ID_AA64MMFR1_SPECSEI_SHIFT 24 +#define ID_AA64MMFR1_SPECSEI_MASK (0xfULL << ID_AA64MMFR1_SPECSEI_SHIFT) +#define ID_AA64MMFR1_SPECSEI(x) ((x) & ID_AA64MMFR1_SPECSEI_MASK) +#define ID_AA64MMFR1_SPECSEI_NONE (0x0ULL << ID_AA64MMFR1_SPECSEI_SHIFT) +#define ID_AA64MMFR1_SPECSEI_IMPL (0x1ULL << ID_AA64MMFR1_SPECSEI_SHIFT) +#define ID_AA64MMFR1_XNX_SHIFT 28 +#define ID_AA64MMFR1_XNX_MASK (0xfULL << ID_AA64MMFR1_XNX_SHIFT) +#define ID_AA64MMFR1_XNX(x) ((x) & ID_AA64MMFR1_XNX_MASK) +#define ID_AA64MMFR1_XNX_NONE (0x0ULL << ID_AA64MMFR1_XNX_SHIFT) +#define ID_AA64MMFR1_XNX_IMPL (0x1ULL << ID_AA64MMFR1_XNX_SHIFT) +#define ID_AA64MMFR1_AFP_SHIFT 44 +#define ID_AA64MMFR1_AFP_MASK (0xfULL << ID_AA64MMFR1_AFP_SHIFT) +#define ID_AA64MMFR1_AFP(x) ((x) & ID_AA64MMFR1_AFP_MASK) +#define ID_AA64MMFR1_AFP_NONE (0x0ULL << ID_AA64MMFR1_AFP_SHIFT) +#define ID_AA64MMFR1_AFP_IMPL (0x1ULL << ID_AA64MMFR1_AFP_SHIFT) +#define ID_AA64MMFR1_ECBHB_SHIFT 60 +#define ID_AA64MMFR1_ECBHB_MASK (0xfULL << ID_AA64MMFR1_ECBHB_SHIFT) +#define ID_AA64MMFR1_ECBHB(x) ((x) & ID_AA64MMFR1_ECBHB_MASK) +#define ID_AA64MMFR1_ECBHB_NONE (0x0ULL << ID_AA64MMFR1_ECBHB_SHIFT) +#define ID_AA64MMFR1_ECBHB_IMPL (0x1ULL << ID_AA64MMFR1_ECBHB_SHIFT) + +/* ID_AA64MMFR2_EL1 */ +#define ID_AA64MMFR2_MASK 0xffff0fffffffffffULL +#define ID_AA64MMFR2_CCIDX_SHIFT 20 +#define ID_AA64MMFR2_CCIDX_MASK (0xfULL << ID_AA64MMFR2_CCIDX_SHIFT) +#define ID_AA64MMFR2_CCIDX(x) ((x) & ID_AA64MMFR2_CCIDX_MASK) +#define ID_AA64MMFR2_CCIDX_IMPL (0x1ULL << ID_AA64MMFR2_CCIDX_SHIFT) +#define ID_AA64MMFR2_AT_SHIFT 32 +#define ID_AA64MMFR2_AT_MASK (0xfULL << ID_AA64MMFR2_AT_SHIFT) +#define ID_AA64MMFR2_AT(x) ((x) & ID_AA64MMFR2_AT_MASK) +#define ID_AA64MMFR2_AT_NONE (0x0ULL << ID_AA64MMFR2_AT_SHIFT) +#define ID_AA64MMFR2_AT_IMPL (0x1ULL << ID_AA64MMFR2_AT_SHIFT) +#define ID_AA64MMFR2_IDS_SHIFT 36 +#define ID_AA64MMFR2_IDS_MASK (0xfULL << ID_AA64MMFR2_IDS_SHIFT) +#define ID_AA64MMFR2_IDS(x) ((x) & ID_AA64MMFR2_IDS_MASK) +#define ID_AA64MMFR2_IDS_NONE (0x0ULL << ID_AA64MMFR2_IDS_SHIFT) +#define ID_AA64MMFR2_IDS_IMPL (0x1ULL << ID_AA64MMFR2_IDS_SHIFT) + +/* ID_AA64PFR0_EL1 */ +#define ID_AA64PFR0_MASK 0xff0fffffffffffffULL +#define ID_AA64PFR0_EL0_SHIFT 0 +#define ID_AA64PFR0_EL0_MASK (0xfULL << ID_AA64PFR0_EL0_SHIFT) +#define ID_AA64PFR0_EL0(x) ((x) & ID_AA64PFR0_EL0_MASK) +#define ID_AA64PFR0_EL0_64 (0x1ULL << ID_AA64PFR0_EL0_SHIFT) +#define ID_AA64PFR0_EL0_64_32 (0x2ULL << ID_AA64PFR0_EL0_SHIFT) +#define ID_AA64PFR0_EL1_SHIFT 4 +#define ID_AA64PFR0_EL1_MASK (0xfULL << ID_AA64PFR0_EL1_SHIFT) +#define ID_AA64PFR0_EL1(x) ((x) & ID_AA64PFR0_EL1_MASK) +#define ID_AA64PFR0_EL1_64 (0x1ULL << ID_AA64PFR0_EL1_SHIFT) +#define ID_AA64PFR0_EL1_64_32 (0x2ULL << ID_AA64PFR0_EL1_SHIFT) +#define ID_AA64PFR0_EL2_SHIFT 8 +#define ID_AA64PFR0_EL2_MASK (0xfULL << ID_AA64PFR0_EL2_SHIFT) +#define ID_AA64PFR0_EL2(x) ((x) & ID_AA64PFR0_EL2_MASK) +#define ID_AA64PFR0_EL2_NONE (0x0ULL << ID_AA64PFR0_EL2_SHIFT) +#define ID_AA64PFR0_EL2_64 (0x1ULL << ID_AA64PFR0_EL2_SHIFT) +#define ID_AA64PFR0_EL2_64_32 (0x2ULL << ID_AA64PFR0_EL2_SHIFT) +#define ID_AA64PFR0_EL3_SHIFT 12 +#define ID_AA64PFR0_EL3_MASK (0xfULL << ID_AA64PFR0_EL3_SHIFT) +#define ID_AA64PFR0_EL3(x) ((x) & ID_AA64PFR0_EL3_MASK) +#define ID_AA64PFR0_EL3_NONE (0x0ULL << ID_AA64PFR0_EL3_SHIFT) +#define ID_AA64PFR0_EL3_64 (0x1ULL << ID_AA64PFR0_EL3_SHIFT) +#define ID_AA64PFR0_EL3_64_32 (0x2ULL << ID_AA64PFR0_EL3_SHIFT) +#define ID_AA64PFR0_FP_SHIFT 16 +#define ID_AA64PFR0_FP_MASK (0xfULL << ID_AA64PFR0_FP_SHIFT) +#define ID_AA64PFR0_FP(x) ((x) & ID_AA64PFR0_FP_MASK) +#define ID_AA64PFR0_FP_IMPL (0x0ULL << ID_AA64PFR0_FP_SHIFT) +#define ID_AA64PFR0_FP_HP (0x1ULL << ID_AA64PFR0_FP_SHIFT) +#define ID_AA64PFR0_FP_NONE (0xfULL << ID_AA64PFR0_FP_SHIFT) +#define ID_AA64PFR0_ADV_SIMD_SHIFT 20 +#define ID_AA64PFR0_ADV_SIMD_MASK (0xfULL << ID_AA64PFR0_ADV_SIMD_SHIFT) +#define ID_AA64PFR0_ADV_SIMD(x) ((x) & ID_AA64PFR0_ADV_SIMD_MASK) +#define ID_AA64PFR0_ADV_SIMD_IMPL (0x0ULL << ID_AA64PFR0_ADV_SIMD_SHIFT) +#define ID_AA64PFR0_ADV_SIMD_HP (0x1ULL << ID_AA64PFR0_ADV_SIMD_SHIFT) +#define ID_AA64PFR0_ADV_SIMD_NONE (0xfULL << ID_AA64PFR0_ADV_SIMD_SHIFT) +#define ID_AA64PFR0_GIC_BITS 0x4 /* Number of bits in GIC field */ +#define ID_AA64PFR0_GIC_SHIFT 24 +#define ID_AA64PFR0_GIC_MASK (0xfULL << ID_AA64PFR0_GIC_SHIFT) +#define ID_AA64PFR0_GIC(x) ((x) & ID_AA64PFR0_GIC_MASK) +#define ID_AA64PFR0_GIC_CPUIF_NONE (0x0ULL << ID_AA64PFR0_GIC_SHIFT) +#define ID_AA64PFR0_GIC_CPUIF_EN (0x1ULL << ID_AA64PFR0_GIC_SHIFT) +#define ID_AA64PFR0_RAS_SHIFT 28 +#define ID_AA64PFR0_RAS_MASK (0xfULL << ID_AA64PFR0_RAS_SHIFT) +#define ID_AA64PFR0_RAS(x) ((x) & ID_AA64PFR0_RAS_MASK) +#define ID_AA64PFR0_RAS_NONE (0x0ULL << ID_AA64PFR0_RAS_SHIFT) +#define ID_AA64PFR0_RAS_IMPL (0x1ULL << ID_AA64PFR0_RAS_SHIFT) +#define ID_AA64PFR0_RAS_IMPL_V1P1 (0x2ULL << ID_AA64PFR0_RAS_SHIFT) +#define ID_AA64PFR0_SVE_SHIFT 32 +#define ID_AA64PFR0_SVE_MASK (0xfULL << ID_AA64PFR0_SVE_SHIFT) +#define ID_AA64PFR0_SVE(x) ((x) & ID_AA64PFR0_SVE_MASK) +#define ID_AA64PFR0_SVE_NONE (0x0ULL << ID_AA64PFR0_SVE_SHIFT) +#define ID_AA64PFR0_SVE_IMPL (0x1ULL << ID_AA64PFR0_SVE_SHIFT) +#define ID_AA64PFR0_SEL2_SHIFT 36 +#define ID_AA64PFR0_SEL2_MASK (0xfULL << ID_AA64PFR0_SEL2_SHIFT) +#define ID_AA64PFR0_SEL2(x) ((x) & ID_AA64PFR0_SEL2_MASK) +#define ID_AA64PFR0_SEL2_NONE (0x0ULL << ID_AA64PFR0_SEL2_SHIFT) +#define ID_AA64PFR0_SEL2_IMPL (0x1ULL << ID_AA64PFR0_SEL2_SHIFT) +#define ID_AA64PFR0_MPAM_SHIFT 40 +#define ID_AA64PFR0_MPAM_MASK (0xfULL << ID_AA64PFR0_MPAM_SHIFT) +#define ID_AA64PFR0_MPAM(x) ((x) & ID_AA64PFR0_MPAM_MASK) +#define ID_AA64PFR0_MPAM_NONE (0x0ULL << ID_AA64PFR0_MPAM_SHIFT) +#define ID_AA64PFR0_MPAM_IMPL (0x1ULL << ID_AA64PFR0_MPAM_SHIFT) +#define ID_AA64PFR0_AMU_SHIFT 44 +#define ID_AA64PFR0_AMU_MASK (0xfULL << ID_AA64PFR0_AMU_SHIFT) +#define ID_AA64PFR0_AMU(x) ((x) & ID_AA64PFR0_AMU_MASK) +#define ID_AA64PFR0_AMU_NONE (0x0ULL << ID_AA64PFR0_AMU_SHIFT) +#define ID_AA64PFR0_AMU_IMPL (0x1ULL << ID_AA64PFR0_AMU_SHIFT) +#define ID_AA64PFR0_AMU_IMPL_V1P1 (0x2ULL << ID_AA64PFR0_AMU_SHIFT) +#define ID_AA64PFR0_DIT_SHIFT 48 +#define ID_AA64PFR0_DIT_MASK (0xfULL << ID_AA64PFR0_DIT_SHIFT) +#define ID_AA64PFR0_DIT(x) ((x) & ID_AA64PFR0_DIT_MASK) +#define ID_AA64PFR0_DIT_UNKNOWN (0x0ULL << ID_AA64PFR0_DIT_SHIFT) +#define ID_AA64PFR0_DIT_IMPL (0x1ULL << ID_AA64PFR0_DIT_SHIFT) +#define ID_AA64PFR0_CSV2_SHIFT 56 +#define ID_AA64PFR0_CSV2_MASK (0xfULL << ID_AA64PFR0_CSV2_SHIFT) +#define ID_AA64PFR0_CSV2(x) ((x) & ID_AA64PFR0_CSV2_MASK) +#define ID_AA64PFR0_CSV2_UNKNOWN (0x0ULL << ID_AA64PFR0_CSV2_SHIFT) +#define ID_AA64PFR0_CSV2_IMPL (0x1ULL << ID_AA64PFR0_CSV2_SHIFT) +#define ID_AA64PFR0_CSV2_SCXT (0x2ULL << ID_AA64PFR0_CSV2_SHIFT) +#define ID_AA64PFR0_CSV2_HCXT (0x3ULL << ID_AA64PFR0_CSV2_SHIFT) +#define ID_AA64PFR0_CSV3_SHIFT 60 +#define ID_AA64PFR0_CSV3_MASK (0xfULL << ID_AA64PFR0_CSV3_SHIFT) +#define ID_AA64PFR0_CSV3(x) ((x) & ID_AA64PFR0_CSV3_MASK) +#define ID_AA64PFR0_CSV3_UNKNOWN (0x0ULL << ID_AA64PFR0_CSV3_SHIFT) +#define ID_AA64PFR0_CSV3_IMPL (0x1ULL << ID_AA64PFR0_CSV3_SHIFT) + +/* ID_AA64PFR1_EL1 */ +#define ID_AA64PFR1_MASK 0x000000000000ffffULL +#define ID_AA64PFR1_BT_SHIFT 0 +#define ID_AA64PFR1_BT_MASK (0xfULL << ID_AA64PFR1_BT_SHIFT) +#define ID_AA64PFR1_BT(x) ((x) & ID_AA64PFR1_BT_MASK) +#define ID_AA64PFR1_BT_NONE (0x0ULL << ID_AA64PFR1_BT_SHIFT) +#define ID_AA64PFR1_BT_IMPL (0x1ULL << ID_AA64PFR1_BT_SHIFT) +#define ID_AA64PFR1_SSBS_SHIFT 4 +#define ID_AA64PFR1_SSBS_MASK (0xfULL << ID_AA64PFR1_SSBS_SHIFT) +#define ID_AA64PFR1_SSBS(x) ((x) & ID_AA64PFR1_SSBS_MASK) +#define ID_AA64PFR1_SSBS_NONE (0x0ULL << ID_AA64PFR1_SSBS_SHIFT) +#define ID_AA64PFR1_SSBS_PSTATE (0x1ULL << ID_AA64PFR1_SSBS_SHIFT) +#define ID_AA64PFR1_SSBS_PSTATE_MSR (0x2ULL << ID_AA64PFR1_SSBS_SHIFT) +#define ID_AA64PFR1_MTE_SHIFT 8 +#define ID_AA64PFR1_MTE_MASK (0xfULL << ID_AA64PFR1_MTE_SHIFT) +#define ID_AA64PFR1_MTE(x) ((x) & ID_AA64PFR1_MTE_MASK) +#define ID_AA64PFR1_MTE_NONE (0x0ULL << ID_AA64PFR1_MTE_SHIFT) +#define ID_AA64PFR1_MTE_IMPL (0x1ULL << ID_AA64PFR1_MTE_SHIFT) +#define ID_AA64PFR1_RAS_FRAC_SHIFT 12 +#define ID_AA64PFR1_RAS_FRAC_MASK (0xfULL << ID_AA64PFR1_RAS_FRAC_SHIFT) +#define ID_AA64PFR1_RAS_FRAC(x) ((x) & ID_AA64PFR1_RAS_FRAC_MASK) +#define ID_AA64PFR1_RAS_FRAC_NONE (0x0ULL << ID_AA64PFR1_RAS_FRAC_SHIFT) +#define ID_AA64PFR1_RAS_FRAC_IMPL (0x1ULL << ID_AA64PFR1_RAS_FRAC_SHIFT) + +/* ID_AA64ZFR0_EL1 */ +#define ID_AA64ZFR0_MASK 0x0ff0ff0f00ff00ffULL +#define ID_AA64ZFR0_SVEVER_SHIFT 0 +#define ID_AA64ZFR0_SVEVER_MASK (0xfULL << ID_AA64ZFR0_SVEVER_SHIFT) +#define ID_AA64ZFR0_SVEVER(x) ((x) & ID_AA64ZFR0_SVEVER_MASK) +#define ID_AA64ZFR0_SVEVER_SVE1 (0x0ULL << ID_AA64ZFR0_SVEVER_SHIFT) +#define ID_AA64ZFR0_SVEVER_SVE2 (0x1ULL << ID_AA64ZFR0_SVEVER_SHIFT) +#define ID_AA64ZFR0_SVEVER_SVE2P1 (0x2ULL << ID_AA64ZFR0_SVEVER_SHIFT) +#define ID_AA64ZFR0_AES_SHIFT 4 +#define ID_AA64ZFR0_AES_MASK (0xfULL << ID_AA64ZFR0_AES_SHIFT) +#define ID_AA64ZFR0_AES(x) ((x) & ID_AA64ZFR0_AES_MASK) +#define ID_AA64ZFR0_AES_NONE (0x0ULL << ID_AA64ZFR0_AES_SHIFT) +#define ID_AA64ZFR0_AES_BASE (0x1ULL << ID_AA64ZFR0_AES_SHIFT) +#define ID_AA64ZFR0_AES_PMULL (0x2ULL << ID_AA64ZFR0_AES_SHIFT) +#define ID_AA64ZFR0_BITPERM_SHIFT 16 +#define ID_AA64ZFR0_BITPERM_MASK (0xfULL << ID_AA64ZFR0_BITPERM_SHIFT) +#define ID_AA64ZFR0_BITPERM(x) ((x) & ID_AA64ZFR0_BITPERM_MASK) +#define ID_AA64ZFR0_BITPERM_NONE (0x0ULL << ID_AA64ZFR0_BITPERM_SHIFT) +#define ID_AA64ZFR0_BITPERM_IMPL (0x1ULL << ID_AA64ZFR0_BITPERM_SHIFT) +#define ID_AA64ZFR0_BF16_SHIFT 20 +#define ID_AA64ZFR0_BF16_MASK (0xfULL << ID_AA64ZFR0_BF16_SHIFT) +#define ID_AA64ZFR0_BF16(x) ((x) & ID_AA64ZFR0_BF16_MASK) +#define ID_AA64ZFR0_BF16_NONE (0x0ULL << ID_AA64ZFR0_BF16_SHIFT) +#define ID_AA64ZFR0_BF16_BASE (0x1ULL << ID_AA64ZFR0_BF16_SHIFT) +#define ID_AA64ZFR0_BF16_EBF (0x2ULL << ID_AA64ZFR0_BF16_SHIFT) +#define ID_AA64ZFR0_SHA3_SHIFT 32 +#define ID_AA64ZFR0_SHA3_MASK (0xfULL << ID_AA64ZFR0_SHA3_SHIFT) +#define ID_AA64ZFR0_SHA3(x) ((x) & ID_AA64ZFR0_SHA3_MASK) +#define ID_AA64ZFR0_SHA3_NONE (0x0ULL << ID_AA64ZFR0_SHA3_SHIFT) +#define ID_AA64ZFR0_SHA3_IMPL (0x1ULL << ID_AA64ZFR0_SHA3_SHIFT) +#define ID_AA64ZFR0_SM4_SHIFT 40 +#define ID_AA64ZFR0_SM4_MASK (0xfULL << ID_AA64ZFR0_SM4_SHIFT) +#define ID_AA64ZFR0_SM4(x) ((x) & ID_AA64ZFR0_SM4_MASK) +#define ID_AA64ZFR0_SM4_NONE (0x0ULL << ID_AA64ZFR0_SM4_SHIFT) +#define ID_AA64ZFR0_SM4_IMPL (0x1ULL << ID_AA64ZFR0_SM4_SHIFT) +#define ID_AA64ZFR0_I8MM_SHIFT 44 +#define ID_AA64ZFR0_I8MM_MASK (0xfULL << ID_AA64ZFR0_I8MM_SHIFT) +#define ID_AA64ZFR0_I8MM(x) ((x) & ID_AA64ZFR0_I8MM_MASK) +#define ID_AA64ZFR0_I8MM_NONE (0x0ULL << ID_AA64ZFR0_I8MM_SHIFT) +#define ID_AA64ZFR0_I8MM_IMPL (0x1ULL << ID_AA64ZFR0_I8MM_SHIFT) +#define ID_AA64ZFR0_F32MM_SHIFT 52 +#define ID_AA64ZFR0_F32MM_MASK (0xfULL << ID_AA64ZFR0_F32MM_SHIFT) +#define ID_AA64ZFR0_F32MM(x) ((x) & ID_AA64ZFR0_F32MM_MASK) +#define ID_AA64ZFR0_F32MM_NONE (0x0ULL << ID_AA64ZFR0_F32MM_SHIFT) +#define ID_AA64ZFR0_F32MM_IMPL (0x1ULL << ID_AA64ZFR0_F32MM_SHIFT) +#define ID_AA64ZFR0_F64MM_SHIFT 56 +#define ID_AA64ZFR0_F64MM_MASK (0xfULL << ID_AA64ZFR0_F64MM_SHIFT) +#define ID_AA64ZFR0_F64MM(x) ((x) & ID_AA64ZFR0_F64MM_MASK) +#define ID_AA64ZFR0_F64MM_NONE (0x0ULL << ID_AA64ZFR0_F64MM_SHIFT) +#define ID_AA64ZFR0_F64MM_IMPL (0x1ULL << ID_AA64ZFR0_F64MM_SHIFT) + +/* MAIR_EL1 - Memory Attribute Indirection Register */ +#define MAIR_ATTR_MASK(idx) (0xff << ((n)* 8)) +#define MAIR_ATTR(attr, idx) ((attr) << ((idx) * 8)) +#define MAIR_DEVICE_nGnRnE 0x00 +#define MAIR_NORMAL_NC 0x44 +#define MAIR_NORMAL_WT 0x88 +#define MAIR_NORMAL_WB 0xff + +/* PAR_EL1 - Physical Address Register */ +#define PAR_F_SHIFT 0 +#define PAR_F (0x1 << PAR_F_SHIFT) +#define PAR_SUCCESS(x) (((x) & PAR_F) == 0) +/* When PAR_F == 0 (success) */ +#define PAR_SH_SHIFT 7 +#define PAR_SH_MASK (0x3 << PAR_SH_SHIFT) +#define PAR_NS_SHIFT 9 +#define PAR_NS_MASK (0x3 << PAR_NS_SHIFT) +#define PAR_PA_SHIFT 12 +#define PAR_PA_MASK 0x0000fffffffff000 +#define PAR_ATTR_SHIFT 56 +#define PAR_ATTR_MASK (0xff << PAR_ATTR_SHIFT) +/* When PAR_F == 1 (aborted) */ +#define PAR_FST_SHIFT 1 +#define PAR_FST_MASK (0x3f << PAR_FST_SHIFT) +#define PAR_PTW_SHIFT 8 +#define PAR_PTW_MASK (0x1 << PAR_PTW_SHIFT) +#define PAR_S_SHIFT 9 +#define PAR_S_MASK (0x1 << PAR_S_SHIFT) + +/* SCTLR_EL1 - System Control Register */ +#define SCTLR_RES0 0xffffffffc8222400 /* Reserved, write 0 */ +#define SCTLR_RES1 0x0000000030d00800 /* Reserved, write 1 */ + +#define SCTLR_M 0x0000000000000001 +#define SCTLR_A 0x0000000000000002 +#define SCTLR_C 0x0000000000000004 +#define SCTLR_SA 0x0000000000000008 +#define SCTLR_SA0 0x0000000000000010 +#define SCTLR_CP15BEN 0x0000000000000020 +#define SCTLR_THEE 0x0000000000000040 +#define SCTLR_ITD 0x0000000000000080 +#define SCTLR_SED 0x0000000000000100 +#define SCTLR_UMA 0x0000000000000200 +#define SCTLR_I 0x0000000000001000 +#define SCTLR_EnDB 0x0000000000002000 +#define SCTLR_DZE 0x0000000000004000 +#define SCTLR_UCT 0x0000000000008000 +#define SCTLR_nTWI 0x0000000000010000 +#define SCTLR_nTWE 0x0000000000040000 +#define SCTLR_WXN 0x0000000000080000 +#define SCTLR_SPAN 0x0000000000800000 +#define SCTLR_EOE 0x0000000001000000 +#define SCTLR_EE 0x0000000002000000 +#define SCTLR_UCI 0x0000000004000000 +#define SCTLR_EnDA 0x0000000008000000 +#define SCTLR_EnIB 0x0000000040000000 +#define SCTLR_EnIA 0x0000000080000000 +#define SCTLR_BT0 0x0000000800000000 +#define SCTLR_BT1 0x0000001000000000 +#define SCTLR_EPAN 0x0200000000000000 + +/* SPSR_EL1 */ +/* + * When the exception is taken in AArch64: + * M[4] is 0 for AArch64 mode + * M[3:2] is the exception level + * M[1] is unused + * M[0] is the SP select: + * 0: always SP0 + * 1: current ELs SP + */ +#define PSR_M_EL0t 0x00000000 +#define PSR_M_EL1t 0x00000004 +#define PSR_M_EL1h 0x00000005 +#define PSR_M_EL2t 0x00000008 +#define PSR_M_EL2h 0x00000009 +#define PSR_M_MASK 0x0000001f + +#define PSR_F 0x00000040 +#define PSR_I 0x00000080 +#define PSR_A 0x00000100 +#define PSR_D 0x00000200 +#define PSR_BTYPE 0x00000c00 +#define PSR_SSBS 0x00001000 +#define PSR_IL 0x00100000 +#define PSR_SS 0x00200000 +#define PSR_PAN 0x00400000 +#define PSR_UAO 0x00800000 +#define PSR_DIT 0x01000000 +#define PSR_TCO 0x02000000 +#define PSR_V 0x10000000 +#define PSR_C 0x20000000 +#define PSR_Z 0x40000000 +#define PSR_N 0x80000000 + +/* TCR_EL1 - Translation Control Register */ +#define TCR_AS (1UL << 36) + +#define TCR_IPS_SHIFT 32 +#define TCR_IPS_32BIT (0UL << TCR_IPS_SHIFT) +#define TCR_IPS_36BIT (1UL << TCR_IPS_SHIFT) +#define TCR_IPS_40BIT (2UL << TCR_IPS_SHIFT) +#define TCR_IPS_42BIT (3UL << TCR_IPS_SHIFT) +#define TCR_IPS_44BIT (4UL << TCR_IPS_SHIFT) +#define TCR_IPS_48BIT (5UL << TCR_IPS_SHIFT) + +#define TCR_TG1_SHIFT 30 +#define TCR_TG1_16K (1UL << TCR_TG1_SHIFT) +#define TCR_TG1_4K (2UL << TCR_TG1_SHIFT) +#define TCR_TG1_64K (3UL << TCR_TG1_SHIFT) + +#define TCR_SH1_SHIFT 28 +#define TCR_SH1_IS (0x3UL << TCR_SH1_SHIFT) +#define TCR_ORGN1_SHIFT 26 +#define TCR_ORGN1_WBWA (0x1UL << TCR_ORGN1_SHIFT) +#define TCR_IRGN1_SHIFT 24 +#define TCR_IRGN1_WBWA (0x1UL << TCR_IRGN1_SHIFT) + +#define TCR_A1 (1UL << 22) + +#define TCR_TG0_SHIFT 14 +#define TCR_TG0_4K (0UL << TCR_TG0_SHIFT) +#define TCR_TG0_64K (1UL << TCR_TG0_SHIFT) +#define TCR_TG0_16K (2UL << TCR_TG0_SHIFT) + +#define TCR_SH0_SHIFT 12 +#define TCR_SH0_IS (0x3UL << TCR_SH0_SHIFT) +#define TCR_ORGN0_SHIFT 10 +#define TCR_ORGN0_WBWA (0x1UL << TCR_ORGN0_SHIFT) +#define TCR_IRGN0_SHIFT 8 +#define TCR_IRGN0_WBWA (0x1UL << TCR_IRGN0_SHIFT) + +#define TCR_CACHE_ATTRS ((TCR_IRGN0_WBWA | TCR_IRGN1_WBWA) |\ + (TCR_ORGN0_WBWA | TCR_ORGN1_WBWA)) +#define TCR_SMP_ATTRS (TCR_SH0_IS | TCR_SH1_IS) + +#define TCR_T1SZ_SHIFT 16 +#define TCR_T0SZ_SHIFT 0 +#define TCR_T1SZ(x) ((x) << TCR_T1SZ_SHIFT) +#define TCR_T0SZ(x) ((x) << TCR_T0SZ_SHIFT) +#define TCR_TxSZ(x) (TCR_T1SZ(x) | TCR_T0SZ(x)) + +/* Monitor Debug System Control Register */ +#define DBG_MDSCR_SS (0x1 << 0) +#define DBG_MDSCR_TDCC (0x1 << 12) +#define DBG_MDSCR_KDE (0x1 << 13) +#define DBG_MDSCR_MDE (0x1 << 15) + +/* Performance Monitoring Counters */ +#define PMCR_E (1 << 0) /* Enable all counters */ +#define PMCR_P (1 << 1) /* Reset all counters */ +#define PMCR_C (1 << 2) /* Clock counter reset */ +#define PMCR_D (1 << 3) /* CNTR counts every 64 clk cycles */ +#define PMCR_X (1 << 4) /* Export to ext. monitoring (ETM) */ +#define PMCR_DP (1 << 5) /* Disable CCNT if non-invasive debug*/ +#define PMCR_LC (1 << 6) /* Long cycle count enable */ +#define PMCR_IMP_SHIFT 24 /* Implementer code */ +#define PMCR_IMP_MASK (0xff << PMCR_IMP_SHIFT) +#define PMCR_IDCODE_SHIFT 16 /* Identification code */ +#define PMCR_IDCODE_MASK (0xff << PMCR_IDCODE_SHIFT) +#define PMCR_IDCODE_CORTEX_A57 0x01 +#define PMCR_IDCODE_CORTEX_A72 0x02 +#define PMCR_IDCODE_CORTEX_A53 0x03 +#define PMCR_N_SHIFT 11 /* Number of counters implemented */ +#define PMCR_N_MASK (0x1f << PMCR_N_SHIFT) + +#define I_bit (1 << 7) /* IRQ disable */ +#define F_bit 0 /* FIQ disable - not actually used */ + +#endif /* !_MACHINE_ARMREG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/asm.h b/lib/libc/include/aarch64-openbsd-none/arm64/asm.h new file mode 100644 index 000000000000..e0ad18f38dc7 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/asm.h @@ -0,0 +1,150 @@ +/* $OpenBSD: asm.h,v 1.12 2023/03/27 19:02:48 kettenis Exp $ */ +/* $NetBSD: asm.h,v 1.4 2001/07/16 05:43:32 matt Exp $ */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)asm.h 5.5 (Berkeley) 5/7/91 + */ + +#ifndef _MACHINE_ASM_H_ +#define _MACHINE_ASM_H_ + +#define _C_LABEL(x) x +#define _ASM_LABEL(x) x + +#ifdef __STDC__ +# define __CONCAT(x,y) x ## y +# define __STRING(x) #x +#else +# define __CONCAT(x,y) x/**/y +# define __STRING(x) "x" +#endif + +#ifndef _ALIGN_TEXT +# define _ALIGN_TEXT .align 0 +#endif + +/* + * gas/arm uses @ as a single comment character and thus cannot be used here + * Instead it recognised the # instead of an @ symbols in .type directives + * We define a couple of macros so that assembly code will not be dependant + * on one or the other. + */ +#define _ASM_TYPE_FUNCTION #function +#define _ASM_TYPE_OBJECT #object +/* NB == No Binding: use .globl or .weak as necessary */ +#define _ENTRY_NB(x) \ + .text; _ALIGN_TEXT; .type x,_ASM_TYPE_FUNCTION; x: +#define _ENTRY(x) .globl x; _ENTRY_NB(x) + +#if defined(PROF) || defined(GPROF) +# define _PROF_PROLOGUE \ + stp x29, x30, [sp, #-16]!; \ + mov fp, sp; \ + bl __mcount; \ + ldp x29, x30, [sp], #16; +#else +# define _PROF_PROLOGUE +#endif + +#if defined(_RET_PROTECTOR) +# define RETGUARD_CALC_COOKIE(reg) \ + eor reg, reg, x30 + +# define RETGUARD_LOAD_RANDOM(x, reg) \ + adrp reg, __CONCAT(__retguard_, x); \ + ldr reg, [reg, :lo12:__CONCAT(__retguard_, x)] + +# define RETGUARD_SETUP(x, reg) \ + RETGUARD_SYMBOL(x); \ + RETGUARD_LOAD_RANDOM(x, reg); \ + RETGUARD_CALC_COOKIE(reg) + +# define RETGUARD_CHECK(x, reg) \ + RETGUARD_CALC_COOKIE(reg); \ + RETGUARD_LOAD_RANDOM(x, x9); \ + subs reg, reg, x9; \ + cbz reg, 66f; \ + brk #0x1; \ +66: + +# define RETGUARD_PUSH(reg) \ + str reg, [sp, #-16]! + +# define RETGUARD_POP(reg) \ + ldr reg, [sp, #16]! + +# define RETGUARD_SYMBOL(x) \ + .ifndef __CONCAT(__retguard_, x); \ + .hidden __CONCAT(__retguard_, x); \ + .type __CONCAT(__retguard_, x),@object; \ + .pushsection .openbsd.randomdata.retguard,"aw",@progbits; \ + .weak __CONCAT(__retguard_, x); \ + .p2align 3; \ + __CONCAT(__retguard_, x): ; \ + .xword 0; \ + .size __CONCAT(__retguard_, x), 8; \ + .popsection; \ + .endif +#else +# define RETGUARD_CALC_COOKIE(reg) +# define RETGUARD_LOAD_RANDOM(x, reg) +# define RETGUARD_SETUP(x, reg) +# define RETGUARD_CHECK(x, reg) +# define RETGUARD_PUSH(reg) +# define RETGUARD_POP(reg) +# define RETGUARD_SYMBOL(x) +#endif + +#define ENTRY(y) _ENTRY(y); bti c; _PROF_PROLOGUE +#define ENTRY_NP(y) _ENTRY(y); bti c +#define ENTRY_NB(y) _ENTRY_NB(y); bti c; _PROF_PROLOGUE +#define ASENTRY(y) _ENTRY(y); bti c; _PROF_PROLOGUE +#define ASENTRY_NP(y) _ENTRY(y); bti c +#define END(y) .size y, . - y +#define EENTRY(sym) .globl sym; sym: +#define EEND(sym) + +#ifdef __PIC__ +#define PIC_SYM(x,y) x(y) +#else +#define PIC_SYM(x,y) x +#endif + +#define STRONG_ALIAS(alias,sym) \ + .global alias; \ + alias = sym +#define WEAK_ALIAS(alias,sym) \ + .weak alias; \ + alias = sym + +#endif /* !_MACHINE_ASM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/atomic.h b/lib/libc/include/aarch64-openbsd-none/arm64/atomic.h new file mode 100644 index 000000000000..7a66719a4755 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/atomic.h @@ -0,0 +1,64 @@ +/* $OpenBSD: atomic.h,v 1.4 2022/08/29 02:01:18 jsg Exp $ */ + +/* Public Domain */ + +#ifndef _MACHINE_ATOMIC_H_ +#define _MACHINE_ATOMIC_H_ + +#define __membar(_f) do { __asm volatile(_f ::: "memory"); } while (0) + +#define membar_enter() __membar("dmb sy") +#define membar_exit() __membar("dmb sy") +#define membar_producer() __membar("dmb st") +#define membar_consumer() __membar("dmb ld") +#define membar_sync() __membar("dmb sy") + +#if defined(_KERNEL) + +/* virtio needs MP membars even on SP kernels */ +#define virtio_membar_producer() __membar("dmb st") +#define virtio_membar_consumer() __membar("dmb ld") +#define virtio_membar_sync() __membar("dmb sy") + +/* + * Set bits + * *p = *p | v + */ +static inline void +atomic_setbits_int(volatile unsigned int *p, unsigned int v) +{ + unsigned int modified, tmp; + + __asm volatile ( + "1: ldxr %w0, [%x3] \n\t" + " orr %w0, %w0, %w2 \n\t" + " stxr %w1, %w0, [%x3] \n\t" + " cbnz %w1, 1b \n\t" + : "=&r" (tmp), "=&r" (modified) + : "r" (v), "r" (p) + : "memory", "cc" + ); +} + +/* + * Clear bits + * *p = *p & (~v) + */ +static inline void +atomic_clearbits_int(volatile unsigned int *p, unsigned int v) +{ + unsigned int modified, tmp; + + __asm volatile ( + "1: ldxr %w0, [%x3] \n\t" + " bic %w0, %w0, %w2 \n\t" + " stxr %w1, %w0, [%x3] \n\t" + " cbnz %w1, 1b \n\t" + : "=&r" (tmp), "=&r" (modified) + : "r" (v), "r" (p) + : "memory", "cc" + ); +} + +#endif /* defined(_KERNEL) */ +#endif /* _MACHINE_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/bootconfig.h b/lib/libc/include/aarch64-openbsd-none/arm64/bootconfig.h new file mode 100644 index 000000000000..8767d1ab7f7f --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/bootconfig.h @@ -0,0 +1,47 @@ +/* $OpenBSD: bootconfig.h,v 1.4 2023/12/05 05:27:26 jsg Exp $ */ +/* $NetBSD: bootconfig.h,v 1.2 2001/06/21 22:08:28 chris Exp $ */ + +/*- + * Copyright (c) 2013 Andrew Turner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: head/sys/arm64/include/machdep.h 281494 2015-04-13 14:43:10Z andrew $ + */ + +#ifndef _MACHINE_BOOTCONFIG_H_ +#define _MACHINE_BOOTCONFIG_H_ + +struct arm64_bootparams { + vaddr_t modulep; + vaddr_t kern_l1pt; /* L1 page table for the kernel */ + uint64_t kern_delta; + vaddr_t kern_stack; + void *arg0; // passed to kernel in R0 + void *arg1; // passed to kernel in R1 + void *arg2; // passed to kernel in R2 +}; + +void initarm(struct arm64_bootparams *); + +#endif /* _MACHINE_BOOTCONFIG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/bus.h b/lib/libc/include/aarch64-openbsd-none/arm64/bus.h new file mode 100644 index 000000000000..70ad145593e8 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/bus.h @@ -0,0 +1,536 @@ +/* $OpenBSD: bus.h,v 1.11 2024/11/18 05:32:39 jsg Exp $ */ +/* + * Copyright (c) 2003-2004 Opsycon AB Sweden. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BUS_H_ +#define _MACHINE_BUS_H_ + +#ifdef __STDC__ +#define CAT(a,b) a##b +#define CAT3(a,b,c) a##b##c +#else +#define CAT(a,b) a/**/b +#define CAT3(a,b,c) a/**/b/**/c +#endif + +/* + * Bus access types. + */ +struct bus_space; +typedef u_long bus_addr_t; +typedef u_long bus_size_t; +typedef u_long bus_space_handle_t; +typedef struct bus_space *bus_space_tag_t; +typedef struct bus_space bus_space_t; + +struct bus_space { + bus_addr_t bus_base; + void *bus_private; + u_int8_t (*_space_read_1)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_1)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int8_t); + u_int16_t (*_space_read_2)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_2)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int16_t); + u_int32_t (*_space_read_4)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_4)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int32_t); + u_int64_t (*_space_read_8)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_8)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int64_t); + void (*_space_read_raw_2)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_2)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + void (*_space_read_raw_4)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_4)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + void (*_space_read_raw_8)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_8)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + int (*_space_map)(bus_space_tag_t , bus_addr_t, + bus_size_t, int, bus_space_handle_t *); + void (*_space_unmap)(bus_space_tag_t, bus_space_handle_t, + bus_size_t); + int (*_space_subregion)(bus_space_tag_t, bus_space_handle_t, + bus_size_t, bus_size_t, bus_space_handle_t *); + void * (*_space_vaddr)(bus_space_tag_t, bus_space_handle_t); + paddr_t (*_space_mmap)(bus_space_tag_t, bus_addr_t, off_t, + int, int); +}; + +#define bus_space_read_1(t, h, o) (*(t)->_space_read_1)((t), (h), (o)) +#define bus_space_read_2(t, h, o) (*(t)->_space_read_2)((t), (h), (o)) +#define bus_space_read_4(t, h, o) (*(t)->_space_read_4)((t), (h), (o)) +#define bus_space_read_8(t, h, o) (*(t)->_space_read_8)((t), (h), (o)) + +#define bus_space_write_1(t, h, o, v) (*(t)->_space_write_1)((t), (h), (o), (v)) +#define bus_space_write_2(t, h, o, v) (*(t)->_space_write_2)((t), (h), (o), (v)) +#define bus_space_write_4(t, h, o, v) (*(t)->_space_write_4)((t), (h), (o), (v)) +#define bus_space_write_8(t, h, o, v) (*(t)->_space_write_8)((t), (h), (o), (v)) + +#define bus_space_read_raw_2(t, h, o) \ + (*(t)->_space_read_2)((t), (h), (o)) +#define bus_space_read_raw_4(t, h, o) \ + (*(t)->_space_read_4)((t), (h), (o)) +#define bus_space_read_raw_8(t, h, o) \ + (*(t)->_space_read_8)((t), (h), (o)) + +#define bus_space_write_raw_2(t, h, o, v) \ + (*(t)->_space_write_2)((t), (h), (o), (v)) +#define bus_space_write_raw_4(t, h, o, v) \ + (*(t)->_space_write_4)((t), (h), (o), (v)) +#define bus_space_write_raw_8(t, h, o, v) \ + (*(t)->_space_write_8)((t), (h), (o), (v)) + +#define bus_space_read_raw_multi_2(t, h, a, b, l) \ + (*(t)->_space_read_raw_2)((t), (h), (a), (b), (l)) +#define bus_space_read_raw_multi_4(t, h, a, b, l) \ + (*(t)->_space_read_raw_4)((t), (h), (a), (b), (l)) +#define bus_space_read_raw_multi_8(t, h, a, b, l) \ + (*(t)->_space_read_raw_8)((t), (h), (a), (b), (l)) + +#define bus_space_write_raw_multi_2(t, h, a, b, l) \ + (*(t)->_space_write_raw_2)((t), (h), (a), (b), (l)) +#define bus_space_write_raw_multi_4(t, h, a, b, l) \ + (*(t)->_space_write_raw_4)((t), (h), (a), (b), (l)) +#define bus_space_write_raw_multi_8(t, h, a, b, l) \ + (*(t)->_space_write_raw_8)((t), (h), (a), (b), (l)) + +#define bus_space_map(t, o, s, c, p) (*(t)->_space_map)((t), (o), (s), (c), (p)) +#define bus_space_unmap(t, h, s) (*(t)->_space_unmap)((t), (h), (s)) +#define bus_space_subregion(t, h, o, s, p) \ + (*(t)->_space_subregion)((t), (h), (o), (s), (p)) + +#define BUS_SPACE_MAP_CACHEABLE 0x01 +#define BUS_SPACE_MAP_POSTED 0x02 +#define BUS_SPACE_MAP_LINEAR 0x04 +#define BUS_SPACE_MAP_PREFETCHABLE 0x08 + +extern bus_space_t arm64_bs_tag; + +#define bus_space_vaddr(t, h) (*(t)->_space_vaddr)((t), (h)) +#define bus_space_mmap(t, a, o, p, f) \ + (*(t)->_space_mmap)((t), (a), (o), (p), (f)) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_multi(n,m) \ +static __inline void \ +CAT(bus_space_read_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t o, CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) \ + *x++ = CAT(bus_space_read_,n)(bst, bsh, o); \ +} + +bus_space_read_multi(1,8) +bus_space_read_multi(2,16) +bus_space_read_multi(4,32) +bus_space_read_multi(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_region(n,m) \ +static __inline void \ +CAT(bus_space_read_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) { \ + *x++ = CAT(bus_space_read_,n)(bst, bsh, ba); \ + ba += (n); \ + } \ +} + +bus_space_read_region(1,8) +bus_space_read_region(2,16) +bus_space_read_region(4,32) +bus_space_read_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_raw_region(n,m) \ +static __inline void \ +CAT(bus_space_read_raw_region_,n)(bus_space_tag_t bst, \ + bus_space_handle_t bsh, \ + bus_addr_t ba, u_int8_t *x, size_t cnt) \ +{ \ + cnt >>= ((n) >> 1); \ + while (cnt--) { \ + CAT(bus_space_read_raw_multi_,n)(bst, bsh, ba, x, (n)); \ + ba += (n); \ + x += (n); \ + } \ +} + +bus_space_read_raw_region(2,16) +bus_space_read_raw_region(4,32) +bus_space_read_raw_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_multi(n,m) \ +static __inline void \ +CAT(bus_space_write_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t o, const CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) \ + CAT(bus_space_write_,n)(bst, bsh, o, *x++); \ +} + +bus_space_write_multi(1,8) +bus_space_write_multi(2,16) +bus_space_write_multi(4,32) +bus_space_write_multi(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_region(n,m) \ +static __inline void \ +CAT(bus_space_write_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, const CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) { \ + CAT(bus_space_write_,n)(bst, bsh, ba, *x++); \ + ba += (n); \ + } \ +} + +bus_space_write_region(1,8) +bus_space_write_region(2,16) +bus_space_write_region(4,32) +bus_space_write_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_raw_region(n,m) \ +static __inline void \ +CAT(bus_space_write_raw_region_,n)(bus_space_tag_t bst, \ + bus_space_handle_t bsh, \ + bus_addr_t ba, const u_int8_t *x, size_t cnt) \ +{ \ + cnt >>= ((n) >> 1); \ + while (cnt--) { \ + CAT(bus_space_write_raw_multi_,n)(bst, bsh, ba, x, (n)); \ + ba += (n); \ + x += (n); \ + } \ +} + +bus_space_write_raw_region(2,16) +bus_space_write_raw_region(4,32) +bus_space_write_raw_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_set_region(n,m) \ +static __inline void \ +CAT(bus_space_set_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(u_int,m,_t) x, size_t cnt) \ +{ \ + while (cnt--) { \ + CAT(bus_space_write_,n)(bst, bsh, ba, x); \ + ba += (n); \ + } \ +} + +bus_space_set_region(1,8) +bus_space_set_region(2,16) +bus_space_set_region(4,32) +bus_space_set_region(8,64) + +/*----------------------------------------------------------------------------*/ +static __inline void +bus_space_copy_1(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + char *s = (char *)(h1 + o1); + char *d = (char *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + + +static __inline void +bus_space_copy_2(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + short *s = (short *)(h1 + o1); + short *d = (short *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + +static __inline void +bus_space_copy_4(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + int *s = (int *)(h1 + o1); + int *d = (int *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + +static __inline void +bus_space_copy_8(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + int64_t *s = (int64_t *)(h1 + o1); + int64_t *d = (int64_t *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + +/*----------------------------------------------------------------------------*/ +/* + * Bus read/write barrier methods. + * + * void bus_space_barrier(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * bus_size_t len, int flags); + * + */ +static inline void +bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, + bus_size_t length, int flags) +{ + __asm__ volatile ("dsb sy" ::: "memory"); +} +#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ +#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ + +#define BUS_DMA_WAITOK 0x0000 +#define BUS_DMA_NOWAIT 0x0001 +#define BUS_DMA_ALLOCNOW 0x0002 +#define BUS_DMA_COHERENT 0x0008 +#define BUS_DMA_BUS1 0x0010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x0020 +#define BUS_DMA_BUS3 0x0040 +#define BUS_DMA_BUS4 0x0080 +#define BUS_DMA_READ 0x0100 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x0200 /* mapping is memory -> device only */ +#define BUS_DMA_STREAMING 0x0400 /* hint: sequential, unidirectional */ +#define BUS_DMA_ZERO 0x0800 /* zero memory in dmamem_alloc */ +#define BUS_DMA_NOCACHE 0x1000 +#define BUS_DMA_64BIT 0x2000 /* device handles 64bit dva */ +#define BUS_DMA_FIXED 0x4000 /* place mapping at specified dva */ + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct proc; +struct uio; + +#define BUS_DMASYNC_POSTREAD 0x0001 +#define BUS_DMASYNC_POSTWRITE 0x0002 +#define BUS_DMASYNC_PREREAD 0x0004 +#define BUS_DMASYNC_PREWRITE 0x0008 + +typedef struct machine_bus_dma_tag *bus_dma_tag_t; +typedef struct machine_bus_dmamap *bus_dmamap_t; + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +struct machine_bus_dma_segment { + bus_addr_t ds_addr; /* DMA address */ + bus_size_t ds_len; /* length of transfer */ + + paddr_t _ds_paddr; /* CPU address */ + vaddr_t _ds_vaddr; /* CPU address */ +}; +typedef struct machine_bus_dma_segment bus_dma_segment_t; + +/* + * bus_dma_tag_t + * + * A machine-dependent opaque type describing the implementation of + * DMA for a given bus. + */ + +struct machine_bus_dma_tag { + void *_cookie; /* cookie used in the guts */ + int _flags; /* misc. flags */ + + /* + * DMA mapping methods. + */ + int (*_dmamap_create)(bus_dma_tag_t , bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); + void (*_dmamap_destroy)(bus_dma_tag_t , bus_dmamap_t); + int (*_dmamap_load)(bus_dma_tag_t , bus_dmamap_t, void *, + bus_size_t, struct proc *, int); + int (*_dmamap_load_mbuf)(bus_dma_tag_t , bus_dmamap_t, + struct mbuf *, int); + int (*_dmamap_load_uio)(bus_dma_tag_t , bus_dmamap_t, + struct uio *, int); + int (*_dmamap_load_raw)(bus_dma_tag_t , bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); + int (*_dmamap_load_buffer)(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int, paddr_t *, int *, int); + void (*_dmamap_unload)(bus_dma_tag_t , bus_dmamap_t); + void (*_dmamap_sync)(bus_dma_tag_t , bus_dmamap_t, + bus_addr_t, bus_size_t, int); + + /* + * DMA memory utility functions. + */ + int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); + int (*_dmamem_alloc_range)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int, + bus_addr_t, bus_addr_t); + void (*_dmamem_free)(bus_dma_tag_t, bus_dma_segment_t *, int); + int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); + void (*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t); + paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, + int, off_t, int, int); + + /* + * internal memory address translation information. + */ + bus_addr_t _dma_mask; +}; + +#define bus_dmamap_create(t, s, n, m, b, f, p) \ + (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) +#define bus_dmamap_destroy(t, p) \ + (*(t)->_dmamap_destroy)((t), (p)) +#define bus_dmamap_load(t, m, b, s, p, f) \ + (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) +#define bus_dmamap_load_mbuf(t, m, b, f) \ + (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) +#define bus_dmamap_load_uio(t, m, u, f) \ + (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) +#define bus_dmamap_load_raw(t, m, sg, n, s, f) \ + (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) +#define bus_dmamap_unload(t, p) \ + (*(t)->_dmamap_unload)((t), (p)) +#define bus_dmamap_sync(t, p, a, l, o) \ + (void)((t)->_dmamap_sync ? \ + (*(t)->_dmamap_sync)((t), (p), (a), (l), (o)) : (void)0) + +#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ + (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f)) +#define bus_dmamem_alloc_range(t, s, a, b, sg, n, r, f, l, h) \ + (*(t)->_dmamem_alloc_range)((t), (s), (a), (b), (sg), \ + (n), (r), (f), (l), (h)) +#define bus_dmamem_free(t, sg, n) \ + (*(t)->_dmamem_free)((t), (sg), (n)) +#define bus_dmamem_map(t, sg, n, s, k, f) \ + (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f)) +#define bus_dmamem_unmap(t, k, s) \ + (*(t)->_dmamem_unmap)((t), (k), (s)) +#define bus_dmamem_mmap(t, sg, n, o, p, f) \ + (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f)) + +int _dmamap_create(bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); +void _dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); +int _dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); +int _dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *, int); +int _dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, struct uio *, int); +int _dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); +int _dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int, paddr_t *, int *, int); +void _dmamap_unload(bus_dma_tag_t, bus_dmamap_t); +void _dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, + bus_size_t, int); + +int _dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); +void _dmamem_free(bus_dma_tag_t, bus_dma_segment_t *, int); +int _dmamem_map(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); +void _dmamem_unmap(bus_dma_tag_t, caddr_t, size_t); +paddr_t _dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, int, int); +int _dmamem_alloc_range(bus_dma_tag_t, bus_size_t, bus_size_t, bus_size_t, + bus_dma_segment_t *, int, int *, int, paddr_t, paddr_t); + +/* + * bus_dmamap_t + * + * Describes a DMA mapping. + */ +struct machine_bus_dmamap { + /* + * PRIVATE MEMBERS: not for use by machine-independent code. + */ + bus_size_t _dm_size; /* largest DMA transfer mappable */ + int _dm_segcnt; /* number of segs this map can map */ + bus_size_t _dm_maxsegsz; /* largest possible segment */ + bus_size_t _dm_boundary; /* don't cross this */ + int _dm_flags; /* misc. flags */ + + void *_dm_cookie; /* cookie for bus-specific functions */ + + /* + * PUBLIC MEMBERS: these are used by machine-independent code. + */ + bus_size_t dm_mapsize; /* size of the mapping */ + int dm_nsegs; /* # valid segments in mapping */ + bus_dma_segment_t dm_segs[1]; /* segments; variable length */ +}; + +int generic_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, + bus_space_handle_t *); +void generic_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t); +int generic_space_region(bus_space_tag_t, bus_space_handle_t, bus_size_t, + bus_size_t, bus_space_handle_t *); +void *generic_space_vaddr(bus_space_tag_t, bus_space_handle_t); +paddr_t generic_space_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int); +uint8_t generic_space_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint16_t generic_space_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint32_t generic_space_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint64_t generic_space_read_8(bus_space_tag_t, bus_space_handle_t, bus_size_t); +void generic_space_read_raw_2(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint8_t); +void generic_space_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint16_t); +void generic_space_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint32_t); +void generic_space_write_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint64_t); +void generic_space_write_raw_2(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); +void generic_space_read_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); +void generic_space_read_raw_8(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_raw_8(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); + +#endif /* _MACHINE_BUS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/cdefs.h b/lib/libc/include/aarch64-openbsd-none/arm64/cdefs.h new file mode 100644 index 000000000000..307f720db414 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/cdefs.h @@ -0,0 +1,16 @@ +/* $OpenBSD: cdefs.h,v 1.1 2016/12/17 23:38:33 patrick Exp $ */ + +#ifndef _MACHINE_CDEFS_H_ +#define _MACHINE_CDEFS_H_ + +#define __strong_alias(alias,sym) \ + __asm__(".global " __STRING(alias) " ; " __STRING(alias) \ + " = " __STRING(sym)) +#define __weak_alias(alias,sym) \ + __asm__(".weak " __STRING(alias) " ; " __STRING(alias) \ + " = " __STRING(sym)) +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning." __STRING(sym) \ + " ; .ascii \"" msg "\" ; .text") + +#endif /* !_MACHINE_CDEFS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/conf.h b/lib/libc/include/aarch64-openbsd-none/arm64/conf.h new file mode 100644 index 000000000000..9a9e0a146509 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/conf.h @@ -0,0 +1,61 @@ +/* $OpenBSD: conf.h,v 1.5 2024/06/12 02:50:25 jsg Exp $ */ +/* $NetBSD: conf.h,v 1.2 1996/05/05 19:28:34 christos Exp $ */ + +/* + * Copyright (c) 1996 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_CONF_H_ +#define _MACHINE_CONF_H_ + +#include + +#define mmread mmrw +#define mmwrite mmrw +cdev_decl(mm); + +/* open, close, ioctl */ +#define cdev_openprom_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) nullop, 0, \ + (dev_type_mmap((*))) enodev } + +cdev_decl(openprom); + +/* open, close, write, ioctl, kqueue */ +#define cdev_acpiapm_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev, 0, 0, dev_init(c,n,kqfilter) } + +cdev_decl(apm); +cdev_decl(acpiapm); + +#endif /* _MACHINE_CONF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/cpu.h b/lib/libc/include/aarch64-openbsd-none/arm64/cpu.h new file mode 100644 index 000000000000..39cdc4ecd5ea --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/cpu.h @@ -0,0 +1,360 @@ +/* $OpenBSD: cpu.h,v 1.51 2025/02/11 22:27:09 kettenis Exp $ */ +/* + * Copyright (c) 2016 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_CPU_H_ +#define _MACHINE_CPU_H_ + +/* + * User-visible definitions + */ + +/* + * CTL_MACHDEP definitions. + */ +#define CPU_COMPATIBLE 1 /* compatible property */ +#define CPU_ID_AA64ISAR0 2 +#define CPU_ID_AA64ISAR1 3 +#define CPU_ID_AA64ISAR2 4 +#define CPU_ID_AA64MMFR0 5 +#define CPU_ID_AA64MMFR1 6 +#define CPU_ID_AA64MMFR2 7 +#define CPU_ID_AA64PFR0 8 +#define CPU_ID_AA64PFR1 9 +#define CPU_ID_AA64SMFR0 10 +#define CPU_ID_AA64ZFR0 11 +#define CPU_LIDACTION 12 +#define CPU_MAXID 13 /* number of valid machdep ids */ + +#define CTL_MACHDEP_NAMES { \ + { 0, 0 }, \ + { "compatible", CTLTYPE_STRING }, \ + { "id_aa64isar0", CTLTYPE_QUAD }, \ + { "id_aa64isar1", CTLTYPE_QUAD }, \ + { "id_aa64isar2", CTLTYPE_QUAD }, \ + { "id_aa64mmfr0", CTLTYPE_QUAD }, \ + { "id_aa64mmfr1", CTLTYPE_QUAD }, \ + { "id_aa64mmfr2", CTLTYPE_QUAD }, \ + { "id_aa64pfr0", CTLTYPE_QUAD }, \ + { "id_aa64pfr1", CTLTYPE_QUAD }, \ + { "id_aa64smfr0", CTLTYPE_QUAD }, \ + { "id_aa64zfr0", CTLTYPE_QUAD }, \ + { "lidaction", CTLTYPE_INT }, \ +} + +#ifdef _KERNEL + +/* + * Kernel-only definitions + */ + +extern uint64_t cpu_id_aa64isar0; +extern uint64_t cpu_id_aa64isar1; +extern uint64_t cpu_id_aa64isar2; +extern uint64_t cpu_id_aa64mmfr0; +extern uint64_t cpu_id_aa64mmfr1; +extern uint64_t cpu_id_aa64mmfr2; +extern uint64_t cpu_id_aa64pfr0; +extern uint64_t cpu_id_aa64pfr1; +extern uint64_t cpu_id_aa64zfr0; + +void cpu_identify_cleanup(void); + +#include +#include +#include + +/* All the CLKF_* macros take a struct clockframe * as an argument. */ + +#define clockframe trapframe +/* + * CLKF_USERMODE: Return TRUE/FALSE (1/0) depending on whether the + * frame came from USR mode or not. + */ +#define CLKF_USERMODE(frame) ((frame->tf_elr & (1ul << 63)) == 0) + +/* + * CLKF_INTR: True if we took the interrupt from inside another + * interrupt handler. + */ +#define CLKF_INTR(frame) (curcpu()->ci_idepth > 1) + +/* + * CLKF_PC: Extract the program counter from a clockframe + */ +#define CLKF_PC(frame) (frame->tf_elr) + +/* + * PROC_PC: Find out the program counter for the given process. + */ +#define PROC_PC(p) ((p)->p_addr->u_pcb.pcb_tf->tf_elr) +#define PROC_STACK(p) ((p)->p_addr->u_pcb.pcb_tf->tf_sp) + +/* + * Per-CPU information. For now we assume one CPU. + */ + +#include +#include +#include +#include +#include + +struct cpu_info { + struct device *ci_dev; /* Device corresponding to this CPU */ + struct cpu_info *ci_next; + struct schedstate_percpu ci_schedstate; /* scheduler state */ + + u_int32_t ci_cpuid; + uint64_t ci_mpidr; + uint64_t ci_midr; + u_int ci_acpi_proc_id; + int ci_node; + struct cpu_info *ci_self; + +#define __HAVE_CPU_TOPOLOGY + u_int32_t ci_smt_id; + u_int32_t ci_core_id; + u_int32_t ci_pkg_id; + + struct proc *ci_curproc; + struct pcb *ci_curpcb; + struct pmap *ci_curpm; + u_int32_t ci_randseed; + + u_int32_t ci_ctrl; /* The CPU control register */ + + u_int64_t ci_trampoline_vectors; + + uint32_t ci_cpl; + uint32_t ci_ipending; + uint32_t ci_idepth; +#ifdef DIAGNOSTIC + int ci_mutex_level; +#endif + int ci_want_resched; + + void (*ci_flush_bp)(void); + void (*ci_serror)(void); + + uint64_t ci_ttbr1; + vaddr_t ci_el1_stkend; + + uint32_t ci_psci_idle_latency; + uint32_t ci_psci_idle_param; + uint32_t ci_psci_suspend_param; + + struct opp_table *ci_opp_table; + volatile int ci_opp_idx; + volatile int ci_opp_max; + uint32_t ci_cpu_supply; + + u_long ci_prev_sleep; + u_long ci_last_itime; + +#ifdef MULTIPROCESSOR + struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM]; +#define __HAVE_UVM_PERCPU + struct uvm_pmr_cache ci_uvm; + volatile int ci_flags; + + volatile int ci_ddb_paused; +#define CI_DDB_RUNNING 0 +#define CI_DDB_SHOULDSTOP 1 +#define CI_DDB_STOPPED 2 +#define CI_DDB_ENTERDDB 3 +#define CI_DDB_INDDB 4 + +#endif + +#ifdef GPROF + struct gmonparam *ci_gmon; + struct clockintr ci_gmonclock; +#endif + struct clockqueue ci_queue; + char ci_panicbuf[512]; +}; + +#define CPUF_PRIMARY (1<<0) +#define CPUF_AP (1<<1) +#define CPUF_IDENTIFY (1<<2) +#define CPUF_IDENTIFIED (1<<3) +#define CPUF_PRESENT (1<<4) +#define CPUF_GO (1<<5) +#define CPUF_RUNNING (1<<6) + +static inline struct cpu_info * +curcpu(void) +{ + struct cpu_info *__ci = NULL; + __asm volatile("mrs %0, tpidr_el1" : "=r" (__ci)); + return (__ci); +} + +extern struct cpu_info cpu_info_primary; +extern struct cpu_info *cpu_info_list; + +#ifndef MULTIPROCESSOR +#define cpu_number() 0 +#define CPU_IS_PRIMARY(ci) 1 +#define CPU_IS_RUNNING(ci) 1 +#define CPU_INFO_ITERATOR int +#define CPU_INFO_FOREACH(cii, ci) \ + for (cii = 0, ci = curcpu(); ci != NULL; ci = NULL) +#define CPU_INFO_UNIT(ci) 0 +#define MAXCPUS 1 +#define cpu_unidle(ci) +#else +#define cpu_number() (curcpu()->ci_cpuid) +#define CPU_IS_PRIMARY(ci) ((ci) == &cpu_info_primary) +#define CPU_IS_RUNNING(ci) ((ci)->ci_flags & CPUF_RUNNING) +#define CPU_INFO_ITERATOR int +#define CPU_INFO_FOREACH(cii, ci) for (cii = 0, ci = cpu_info_list; \ + ci != NULL; ci = ci->ci_next) +#define CPU_INFO_UNIT(ci) ((ci)->ci_dev ? (ci)->ci_dev->dv_unit : 0) +#define MAXCPUS 256 + +extern struct cpu_info *cpu_info[MAXCPUS]; + +void cpu_boot_secondary_processors(void); +#endif /* !MULTIPROCESSOR */ + +#define CPU_BUSY_CYCLE() __asm volatile("yield" : : : "memory") + +#define curpcb curcpu()->ci_curpcb + +static inline unsigned int +cpu_rnd_messybits(void) +{ + uint64_t val, rval; + + __asm volatile("mrs %0, CNTVCT_EL0; rbit %1, %0;" + : "=r" (val), "=r" (rval)); + + return (val ^ rval); +} + +/* + * Scheduling glue + */ +#define aston(p) ((p)->p_md.md_astpending = 1) +#define setsoftast() aston(curcpu()->ci_curproc) + +/* + * Notify the current process (p) that it has a signal pending, + * process as soon as possible. + */ + +#ifdef MULTIPROCESSOR +void cpu_unidle(struct cpu_info *ci); +#define signotify(p) (aston(p), cpu_unidle((p)->p_cpu)) +void cpu_kick(struct cpu_info *); +#else +#define cpu_kick(ci) +#define cpu_unidle(ci) +#define signotify(p) setsoftast() +#endif + +/* + * Preempt the current process if in interrupt from user mode, + * or after the current trap/syscall if in system mode. + */ +void need_resched(struct cpu_info *); +#define clear_resched(ci) ((ci)->ci_want_resched = 0) + +/* + * Give a profiling tick to the current process when the user profiling + * buffer pages are invalid. On the i386, request an ast to send us + * through trap(), marking the proc as needing a profiling tick. + */ +#define need_proftick(p) aston(p) + +// asm code to start new kernel contexts. +void proc_trampoline(void); + +/* + * Random cruft + */ +void dumpconf(void); + +// syscall.c +void svc_handler (trapframe_t *); + +// functions to manipulate interrupt state +static __inline void +restore_daif(uint32_t daif) +{ + __asm volatile ("msr daif, %x0":: "r"(daif)); +} + +static __inline void +enable_irq_daif(void) +{ + __asm volatile ("msr daifclr, #3"); +} + +static __inline void +disable_irq_daif(void) +{ + __asm volatile ("msr daifset, #3"); +} + +static __inline uint32_t +disable_irq_daif_ret(void) +{ + uint32_t daif; + __asm volatile ("mrs %x0, daif": "=r"(daif)); + __asm volatile ("msr daifset, #3"); + return daif; +} + +static inline void +intr_enable(void) +{ + enable_irq_daif(); +} + +static inline u_long +intr_disable(void) +{ + return disable_irq_daif_ret(); +} + +static inline void +intr_restore(u_long daif) +{ + restore_daif(daif); +} + +void cpu_halt(void); +int cpu_suspend_primary(void); +void cpu_resume_secondary(struct cpu_info *); + +extern void (*cpu_idle_cycle_fcn)(void); +extern void (*cpu_suspend_cycle_fcn)(void); + +void cpu_wfi(void); + +void delay (unsigned); +#define DELAY(x) delay(x) + +#endif /* _KERNEL */ + +#ifdef MULTIPROCESSOR +#include +#endif /* MULTIPROCESSOR */ + +#endif /* !_MACHINE_CPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/cpufunc.h b/lib/libc/include/aarch64-openbsd-none/arm64/cpufunc.h new file mode 100644 index 000000000000..df2a91afc3bc --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/cpufunc.h @@ -0,0 +1,56 @@ +/* $OpenBSD: cpufunc.h,v 1.4 2018/05/02 15:17:30 patrick Exp $ */ +/*- + * Copyright (c) 2014 Andrew Turner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: head/sys/cpu/include/cpufunc.h 299683 2016-05-13 16:03:50Z andrew $ + */ + +#ifndef _MACHINE_CPUFUNC_H_ +#define _MACHINE_CPUFUNC_H_ + +#ifdef _KERNEL + +#include + +extern int64_t dcache_line_size; +extern int64_t icache_line_size; +extern int64_t idcache_line_size; +extern int64_t dczva_line_size; + +void cpu_setttb(int, paddr_t); +void cpu_tlb_flush(void); +void cpu_tlb_flush_asid(vaddr_t); +void cpu_tlb_flush_all_asid(vaddr_t); +void cpu_tlb_flush_asid_all(vaddr_t); +void cpu_icache_sync_range(vaddr_t, vsize_t); +void cpu_idcache_wbinv_range(vaddr_t, vsize_t); +void cpu_dcache_wbinv_range(vaddr_t, vsize_t); +void cpu_dcache_inv_range(vaddr_t, vsize_t); +void cpu_dcache_wb_range(vaddr_t, vsize_t); + +register_t smc_call(register_t, register_t, register_t, register_t); + +#endif /* _KERNEL */ +#endif /* _MACHINE_CPUFUNC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/db_machdep.h b/lib/libc/include/aarch64-openbsd-none/arm64/db_machdep.h new file mode 100644 index 000000000000..d930085c2d44 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/db_machdep.h @@ -0,0 +1,80 @@ +/* $OpenBSD: db_machdep.h,v 1.8 2025/07/22 09:20:41 kettenis Exp $ */ +/* $NetBSD: db_machdep.h,v 1.5 2001/11/22 18:00:00 thorpej Exp $ */ + +/* + * Copyright (c) 1996 Scott K Stevens + * + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#ifndef _MACHINE_DB_MACHDEP_H_ +#define _MACHINE_DB_MACHDEP_H_ + +/* + * Machine-dependent defines for new kernel debugger. + */ + +#include +#include +#include +#include + +/* end of mangling */ + +typedef long db_expr_t; /* expression - signed */ + +typedef trapframe_t db_regs_t; + +extern db_regs_t ddb_regs; /* register state */ +#define DDB_REGS (&ddb_regs) + +#define PC_REGS(regs) ((vaddr_t)(regs)->tf_elr) +#define SET_PC_REGS(regs, value) (regs)->tf_elr = (register_t)(value) + +#define BKPT_INST 0xd4200000 /* breakpoint instruction */ +#define BKPT_SIZE (INSN_SIZE) /* size of breakpoint inst */ +#define BKPT_SET(inst) (BKPT_INST) + +#define db_clear_single_step(regs) ((regs)->tf_spsr &= ~PSR_SS) +#define db_set_single_step(regs) ((regs)->tf_spsr |= PSR_SS) + +#define IS_BREAKPOINT_TRAP(type, code) ((type) == EXCP_BRK) +#define IS_WATCHPOINT_TRAP(type, code) ((type) == EXCP_WATCHPT_EL1) + +// ALL BROKEN!!! +#define inst_trap_return(ins) ((ins) == 0 && (ins) == 1) +#define inst_return(ins) ((ins) == 0 && (ins) == 1) +#define inst_call(ins) ((ins) == 0 && (ins) == 1) + +#define DB_MACHINE_COMMANDS + +int db_ktrap(int, db_regs_t *); +void db_machine_init (void); + +#define DDB_STATE_NOT_RUNNING 0 +#define DDB_STATE_RUNNING 1 +#define DDB_STATE_EXITING 2 + +#endif /* _MACHINE_DB_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/disklabel.h b/lib/libc/include/aarch64-openbsd-none/arm64/disklabel.h new file mode 100644 index 000000000000..6427b26604f1 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/disklabel.h @@ -0,0 +1,25 @@ +/* $OpenBSD: disklabel.h,v 1.1 2016/12/17 23:38:33 patrick Exp $ */ +/* + * Copyright (c) 2014 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_DISKLABEL_H_ +#define _MACHINE_DISKLABEL_H_ + +#define LABELSECTOR 1 /* sector containing label */ +#define LABELOFFSET 0 /* offset of label in sector */ +#define MAXPARTITIONS 16 /* number of partitions */ + +#endif /* _MACHINE_DISKLABEL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/efivar.h b/lib/libc/include/aarch64-openbsd-none/arm64/efivar.h new file mode 100644 index 000000000000..659349b12b10 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/efivar.h @@ -0,0 +1,46 @@ +/* $OpenBSD: efivar.h,v 1.2 2024/07/10 10:53:55 kettenis Exp $ */ +/* + * Copyright (c) 2022 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_EFIVAR_H_ +#define _MACHINE_EFIVAR_H_ + +#include + +struct efi_softc { + struct device sc_dev; + struct pmap *sc_pm; + EFI_RUNTIME_SERVICES *sc_rs; + EFI_SYSTEM_RESOURCE_TABLE *sc_esrt; + u_long sc_psw; + + struct todr_chip_handle sc_todr; +}; + + +extern EFI_GET_VARIABLE efi_get_variable; +extern EFI_SET_VARIABLE efi_set_variable; +extern EFI_GET_NEXT_VARIABLE_NAME efi_get_next_variable_name; + +void efi_enter(struct efi_softc *); +void efi_leave(struct efi_softc *); + +extern label_t efi_jmpbuf; + +#define efi_enter_check(sc) (setjmp(&efi_jmpbuf) ? \ + (efi_leave(sc), EFAULT) : (efi_enter(sc), 0)) + +#endif /* _MACHINE_EFIVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/elf.h b/lib/libc/include/aarch64-openbsd-none/arm64/elf.h new file mode 100644 index 000000000000..7af1436a51da --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/elf.h @@ -0,0 +1,121 @@ +/*- + * Copyright (c) 1996-1997 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_ELF_H_ +#define _MACHINE_ELF_H_ + +/* + * ELF definitions for the AArch64 architecture. + */ + +#ifdef _KERNEL +# define __HAVE_CPU_HWCAP +# define __HAVE_CPU_HWCAP2 +extern unsigned long hwcap, hwcap2; +#endif /* _KERNEL */ + +/* HWCAP */ +#define HWCAP_FP 0x00000001 +#define HWCAP_ASIMD 0x00000002 +#define HWCAP_EVTSTRM 0x00000004 +#define HWCAP_AES 0x00000008 +#define HWCAP_PMULL 0x00000010 +#define HWCAP_SHA1 0x00000020 +#define HWCAP_SHA2 0x00000040 +#define HWCAP_CRC32 0x00000080 +#define HWCAP_ATOMICS 0x00000100 +#define HWCAP_FPHP 0x00000200 +#define HWCAP_ASIMDHP 0x00000400 +#define HWCAP_CPUID 0x00000800 +#define HWCAP_ASIMDRDM 0x00001000 +#define HWCAP_JSCVT 0x00002000 +#define HWCAP_FCMA 0x00004000 +#define HWCAP_LRCPC 0x00008000 +#define HWCAP_DCPOP 0x00010000 +#define HWCAP_SHA3 0x00020000 +#define HWCAP_SM3 0x00040000 +#define HWCAP_SM4 0x00080000 +#define HWCAP_ASIMDDP 0x00100000 +#define HWCAP_SHA512 0x00200000 +#define HWCAP_SVE 0x00400000 +#define HWCAP_ASIMDFHM 0x00800000 +#define HWCAP_DIT 0x01000000 +#define HWCAP_USCAT 0x02000000 +#define HWCAP_ILRCPC 0x04000000 +#define HWCAP_FLAGM 0x08000000 +#define HWCAP_SSBS 0x10000000 +#define HWCAP_SB 0x20000000 +#define HWCAP_PACA 0x40000000 +#define HWCAP_PACG 0x80000000 + +/* HWCAP2 */ +#define HWCAP2_DCPODP 0x0000000000000001ul +#define HWCAP2_SVE2 0x0000000000000002ul +#define HWCAP2_SVEAES 0x0000000000000004ul +#define HWCAP2_SVEPMULL 0x0000000000000008ul +#define HWCAP2_SVEBITPERM 0x0000000000000010ul +#define HWCAP2_SVESHA3 0x0000000000000020ul +#define HWCAP2_SVESM4 0x0000000000000040ul +#define HWCAP2_FLAGM2 0x0000000000000080ul +#define HWCAP2_FRINT 0x0000000000000100ul +#define HWCAP2_SVEI8MM 0x0000000000000200ul +#define HWCAP2_SVEF32MM 0x0000000000000400ul +#define HWCAP2_SVEF64MM 0x0000000000000800ul +#define HWCAP2_SVEBF16 0x0000000000001000ul +#define HWCAP2_I8MM 0x0000000000002000ul +#define HWCAP2_BF16 0x0000000000004000ul +#define HWCAP2_DGH 0x0000000000008000ul +#define HWCAP2_RNG 0x0000000000010000ul +#define HWCAP2_BTI 0x0000000000020000ul +#define HWCAP2_MTE 0x0000000000040000ul +#define HWCAP2_ECV 0x0000000000080000ul +#define HWCAP2_AFP 0x0000000000100000ul +#define HWCAP2_RPRES 0x0000000000200000ul +#define HWCAP2_MTE3 0x0000000000400000ul +#define HWCAP2_SME 0x0000000000800000ul +#define HWCAP2_SME_I16I64 0x0000000001000000ul +#define HWCAP2_SME_F64F64 0x0000000002000000ul +#define HWCAP2_SME_I8I32 0x0000000004000000ul +#define HWCAP2_SME_F16F32 0x0000000008000000ul +#define HWCAP2_SME_B16F32 0x0000000010000000ul +#define HWCAP2_SME_F32F32 0x0000000020000000ul +#define HWCAP2_SME_FA64 0x0000000040000000ul +#define HWCAP2_WFXT 0x0000000080000000ul +#define HWCAP2_EBF16 0x0000000100000000ul +#define HWCAP2_SVE_EBF16 0x0000000200000000ul +#define HWCAP2_CSSC 0x0000000400000000ul +#define HWCAP2_RPRFM 0x0000000800000000ul +#define HWCAP2_SVE2P1 0x0000001000000000ul +#define HWCAP2_SME2 0x0000002000000000ul +#define HWCAP2_SME2P1 0x0000004000000000ul +#define HWCAP2_SME_I16I32 0x0000008000000000ul +#define HWCAP2_SME_BI32I32 0x0000010000000000ul +#define HWCAP2_SME_B16B16 0x0000020000000000ul +#define HWCAP2_SME_F16F16 0x0000040000000000ul +#define HWCAP2_MOPS 0x0000080000000000ul +#define HWCAP2_HBC 0x0000100000000000ul + +#endif /* !_MACHINE_ELF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/endian.h b/lib/libc/include/aarch64-openbsd-none/arm64/endian.h new file mode 100644 index 000000000000..1de95e0c62b9 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/endian.h @@ -0,0 +1,29 @@ +/* $OpenBSD: endian.h,v 1.4 2024/05/07 14:26:48 naddy Exp $ */ + +/* + * Copyright (c) 2015 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_ENDIAN_H_ +#define _MACHINE_ENDIAN_H_ + +#define _BYTE_ORDER _LITTLE_ENDIAN +#define __STRICT_ALIGNMENT + +#ifndef __FROM_SYS__ENDIAN +#include +#endif + +#endif /* _MACHINE_ENDIAN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/exec.h b/lib/libc/include/aarch64-openbsd-none/arm64/exec.h new file mode 100644 index 000000000000..61fcd9797a2f --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/exec.h @@ -0,0 +1,33 @@ +/* $OpenBSD: exec.h,v 1.3 2025/07/31 16:09:59 kettenis Exp $ */ +/* + * Copyright (c) 2014 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_EXEC_H_ +#define _MACHINE_EXEC_H_ + +#define __LDPGSZ 4096 + +#define ARCH_ELFSIZE 64 + +#define ELF_TARG_CLASS ELFCLASS64 +#define ELF_TARG_DATA ELFDATA2LSB +#define ELF_TARG_MACH EM_AARCH64 + +#ifdef _KERNEL +#define __HAVE_COREDUMP_NOTE_ELF_MD +#endif + +#endif \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/fdt.h b/lib/libc/include/aarch64-openbsd-none/arm64/fdt.h new file mode 100644 index 000000000000..3ea355d9add5 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/fdt.h @@ -0,0 +1,59 @@ +/* $OpenBSD: fdt.h,v 1.7 2020/07/14 15:34:14 patrick Exp $ */ +/* + * Copyright (c) 2016 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __ARM_FDT_H__ +#define __ARM_FDT_H__ + +#define _ARM32_BUS_DMA_PRIVATE +#include + +struct fdt_attach_args { + const char *fa_name; + int fa_node; + bus_space_tag_t fa_iot; + bus_dma_tag_t fa_dmat; + struct fdt_reg *fa_reg; + int fa_nreg; + uint32_t *fa_intr; + int fa_nintr; + int fa_acells; + int fa_scells; +}; + +extern int stdout_node; +extern int stdout_speed; +extern bus_space_tag_t fdt_cons_bs_tag; + +void *fdt_find_cons(const char *); + +#define fdt_intr_enable arm_intr_enable +#define fdt_intr_establish arm_intr_establish_fdt +#define fdt_intr_establish_cpu arm_intr_establish_fdt_cpu +#define fdt_intr_establish_idx arm_intr_establish_fdt_idx +#define fdt_intr_establish_idx_cpu arm_intr_establish_fdt_idx_cpu +#define fdt_intr_establish_imap arm_intr_establish_fdt_imap +#define fdt_intr_establish_imap_cpu arm_intr_establish_fdt_imap_cpu +#define fdt_intr_establish_msi arm_intr_establish_fdt_msi +#define fdt_intr_establish_msi_cpu arm_intr_establish_fdt_msi_cpu +#define fdt_intr_disable arm_intr_disable +#define fdt_intr_disestablish arm_intr_disestablish_fdt +#define fdt_intr_get_parent arm_intr_get_parent +#define fdt_intr_parent_establish arm_intr_parent_establish_fdt +#define fdt_intr_parent_disestablish arm_intr_parent_disestablish_fdt +#define fdt_intr_register arm_intr_register_fdt + +#endif /* __ARM_FDT_H__ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/fenv.h b/lib/libc/include/aarch64-openbsd-none/arm64/fenv.h new file mode 100644 index 000000000000..db0eb47817f5 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/fenv.h @@ -0,0 +1,95 @@ +/* $OpenBSD: fenv.h,v 1.3 2019/03/12 22:14:50 patrick Exp $ */ + +/* + * Copyright (c) 2011 Martynas Venckus + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_FENV_H_ +#define _MACHINE_FENV_H_ + +/* + * Each symbol representing a floating point exception expands to an integer + * constant expression with values, such that bitwise-inclusive ORs of _all + * combinations_ of the constants result in distinct values. + * + * We use such values that allow direct bitwise operations on FPU registers. + */ +#define FE_INVALID 0x01 +#define FE_DIVBYZERO 0x02 +#define FE_OVERFLOW 0x04 +#define FE_UNDERFLOW 0x08 +#define FE_INEXACT 0x10 +#define FE_DENORMAL 0x80 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * exception constants defined above. + */ +#define FE_ALL_EXCEPT (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | \ + FE_UNDERFLOW | FE_INEXACT | FE_DENORMAL) + +/* + * Each symbol representing the rounding direction, expands to an integer + * constant expression whose value is distinct non-negative value. + * + * We use such values that allow direct bitwise operations on FPU registers. + */ +#define FE_TONEAREST 0x0 +#define FE_UPWARD 0x1 +#define FE_DOWNWARD 0x2 +#define FE_TOWARDZERO 0x3 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * rounding direction constants defined above. + */ +#define _ROUND_MASK (FE_TONEAREST | FE_UPWARD | FE_DOWNWARD | \ + FE_TOWARDZERO) +#define _ROUND_SHIFT 22 + +/* + * fenv_t represents the entire floating-point environment. + */ +typedef unsigned long long fenv_t; + +/* + * The following constant represents the default floating-point environment + * (that is, the one installed at program startup) and has type pointer to + * const-qualified fenv_t. + * + * It can be used as an argument to the functions within the header + * that manage the floating-point environment, namely fesetenv() and + * feupdateenv(). + */ +__BEGIN_DECLS +extern fenv_t __fe_dfl_env; +__END_DECLS +#define FE_DFL_ENV ((const fenv_t *)&__fe_dfl_env) + +/* + * fexcept_t represents the floating-point status flags collectively, including + * any status the implementation associates with the flags. + * + * A floating-point status flag is a system variable whose value is set (but + * never cleared) when a floating-point exception is raised, which occurs as a + * side effect of exceptional floating-point arithmetic to provide auxiliary + * information. + * + * A floating-point control mode is a system variable whose value may be set by + * the user to affect the subsequent behavior of floating-point arithmetic. + */ +typedef unsigned long long fexcept_t; + +#endif /* !_MACHINE_FENV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/fpu.h b/lib/libc/include/aarch64-openbsd-none/arm64/fpu.h new file mode 100644 index 000000000000..1c1afec45acf --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/fpu.h @@ -0,0 +1,29 @@ +/* $OpenBSD: fpu.h,v 1.2 2025/02/11 22:27:09 kettenis Exp $ */ +/* + * Copyright (c) 2022 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_FPU_H +#define _MACHINE_FPU_H + +void fpu_save(struct proc *); +void fpu_load(struct proc *); +void sve_load(struct proc *); +void fpu_drop(void); + +void fpu_kernel_enter(void); +void fpu_kernel_exit(void); + +#endif /* !_MACHINE_FPU_H */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/frame.h b/lib/libc/include/aarch64-openbsd-none/arm64/frame.h new file mode 100644 index 000000000000..a169a9a1b9bd --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/frame.h @@ -0,0 +1,77 @@ +/* $OpenBSD: frame.h,v 1.3 2018/06/30 15:23:37 deraadt Exp $ */ +/* + * Copyright (c) 2016 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_FRAME_H_ +#define _MACHINE_FRAME_H_ + +#ifndef _LOCORE + +#include + + +/* + * Exception/Trap Stack Frame + */ +#define clockframe trapframe +typedef struct trapframe { + register_t tf_sp; + register_t tf_lr; + register_t tf_elr; + register_t tf_spsr; + register_t tf_x[30]; +} trapframe_t; + +/* + * pushed on stack for signal delivery + */ +struct sigframe { + int sf_signum; + struct sigcontext sf_sc; + siginfo_t sf_si; +}; + +/* + * System stack frames. + */ + +/* + * Stack frame inside cpu_switch() + */ + +struct switchframe { + register_t sf_x19; + register_t sf_x20; + register_t sf_x21; + register_t sf_x22; + register_t sf_x23; + register_t sf_x24; + register_t sf_x25; + register_t sf_x26; + register_t sf_x27; + register_t sf_x28; + register_t sf_x29; + register_t sf_lr; +}; + +struct callframe { + struct callframe *f_frame; + register_t f_lr; +}; + +#endif /* !_LOCORE */ + +#endif /* _MACHINE_FRAME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/hypervisor.h b/lib/libc/include/aarch64-openbsd-none/arm64/hypervisor.h new file mode 100644 index 000000000000..71dce49532b1 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/hypervisor.h @@ -0,0 +1,88 @@ +/* $OpenBSD: hypervisor.h,v 1.5 2025/02/11 22:27:09 kettenis Exp $ */ +/*- + * Copyright (c) 2013, 2014 Andrew Turner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: head/sys/arm64/include/hypervisor.h 281494 2015-04-13 14:43:10Z andrew $ + */ + +#ifndef _MACHINE_HYPERVISOR_H_ +#define _MACHINE_HYPERVISOR_H_ + +/* + * These registers are only useful when in hypervisor context, + * e.g. specific to EL2, or controlling the hypervisor. + */ + +/* + * Architecture feature trap register + */ +#define CPTR_RES0 0x7fefc800 +#define CPTR_RES1 0x000032ff +#define CPTR_TFP 0x00000400 +#define CPTR_TTA 0x00100000 +#define CPTR_TCPAC 0x80000000 + +/* + * Hypervisor Config Register + */ + +#define HCR_VM 0x0000000000000001 +#define HCR_SWIO 0x0000000000000002 +#define HCR_PTW 0x0000000000000004 +#define HCR_FMO 0x0000000000000008 +#define HCR_IMO 0x0000000000000010 +#define HCR_AMO 0x0000000000000020 +#define HCR_VF 0x0000000000000040 +#define HCR_VI 0x0000000000000080 +#define HCR_VSE 0x0000000000000100 +#define HCR_FB 0x0000000000000200 +#define HCR_BSU_MASK 0x0000000000000c00 +#define HCR_DC 0x0000000000001000 +#define HCR_TWI 0x0000000000002000 +#define HCR_TWE 0x0000000000004000 +#define HCR_TID0 0x0000000000008000 +#define HCR_TID1 0x0000000000010000 +#define HCR_TID2 0x0000000000020000 +#define HCR_TID3 0x0000000000040000 +#define HCR_TSC 0x0000000000080000 +#define HCR_TIDCP 0x0000000000100000 +#define HCR_TACR 0x0000000000200000 +#define HCR_TSW 0x0000000000400000 +#define HCR_TPC 0x0000000000800000 +#define HCR_TPU 0x0000000001000000 +#define HCR_TTLB 0x0000000002000000 +#define HCR_TVM 0x0000000004000000 +#define HCR_TGE 0x0000000008000000 +#define HCR_TDZ 0x0000000010000000 +#define HCR_HCD 0x0000000020000000 +#define HCR_TRVM 0x0000000040000000 +#define HCR_RW 0x0000000080000000 +#define HCR_CD 0x0000000100000000 +#define HCR_ID 0x0000000200000000 +#define HCR_E2H 0x0000000400000000 +#define HCR_APK 0x0000010000000000 +#define HCR_API 0x0000020000000000 + +#endif \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/ieee.h b/lib/libc/include/aarch64-openbsd-none/arm64/ieee.h new file mode 100644 index 000000000000..d5f061fd5411 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/ieee.h @@ -0,0 +1,148 @@ +/* $OpenBSD: ieee.h,v 1.3 2017/04/16 16:14:37 kettenis Exp $ */ +/* $NetBSD: ieee.h,v 1.1 1996/09/30 16:34:25 ws Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ieee.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * ieee.h defines the machine-dependent layout of the machine's IEEE + * floating point. It does *not* define (yet?) any of the rounding + * mode bits, exceptions, and so forth. + */ + +/* + * Define the number of bits in each fraction and exponent. + * + * k k+1 + * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented + * + * (-exp_bias+1) + * as fractions that look like 0.fffff x 2 . This means that + * + * -126 + * the number 0.10000 x 2 , for instance, is the same as the normalized + * + * -127 -128 + * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero + * + * -129 + * in the fraction; to represent 2 , we need two, and so on. This + * + * (-exp_bias-fracbits+1) + * implies that the smallest denormalized number is 2 + * + * for whichever format we are talking about: for single precision, for + * + * -126 -149 + * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and + * + * -149 == -127 - 23 + 1. + */ +#define SNG_EXPBITS 8 +#define SNG_FRACBITS 23 + +#define DBL_EXPBITS 11 +#define DBL_FRACHBITS 20 +#define DBL_FRACLBITS 32 +#define DBL_FRACBITS 52 + +#define EXT_EXPBITS 15 +#define EXT_FRACHBITS 16 +#define EXT_FRACHMBITS 32 +#define EXT_FRACLMBITS 32 +#define EXT_FRACLBITS 32 +#define EXT_FRACBITS 112 + +#define EXT_IMPLICIT_NBIT + +#define EXT_TO_ARRAY32(p, a) do { \ + (a)[0] = (uint32_t)(p)->ext_fracl; \ + (a)[1] = (uint32_t)(p)->ext_fraclm; \ + (a)[2] = (uint32_t)(p)->ext_frachm; \ + (a)[3] = (uint32_t)(p)->ext_frach; \ +} while(0) + +struct ieee_single { + u_int sng_frac:23; + u_int sng_exp:8; + u_int sng_sign:1; +}; + +struct ieee_double { + u_int dbl_fracl; + u_int dbl_frach:20; + u_int dbl_exp:11; + u_int dbl_sign:1; +}; + +struct ieee_ext { + u_int ext_fracl; + u_int ext_fraclm; + u_int ext_frachm; + u_int ext_frach:16; + u_int ext_exp:15; + u_int ext_sign:1; +}; + +/* + * Floats whose exponent is in [1..INFNAN) (of whatever type) are + * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. + * Floats whose exponent is zero are either zero (iff all fraction + * bits are zero) or subnormal values. + * + * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its + * high fraction; if the bit is set, it is a `quiet NaN'. + */ +#define SNG_EXP_INFNAN 255 +#define DBL_EXP_INFNAN 2047 +#define EXT_EXP_INFNAN 32767 + +#if 0 +#define SNG_QUIETNAN (1 << 22) +#define DBL_QUIETNAN (1 << 19) +#define EXT_QUIETNAN (1 << 15) +#endif + +/* + * Exponent biases. + */ +#define SNG_EXP_BIAS 127 +#define DBL_EXP_BIAS 1023 +#define EXT_EXP_BIAS 16383 \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/ieeefp.h b/lib/libc/include/aarch64-openbsd-none/arm64/ieeefp.h new file mode 100644 index 000000000000..b2c302da9a4f --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/ieeefp.h @@ -0,0 +1,25 @@ +/* $OpenBSD: ieeefp.h,v 1.2 2021/05/01 20:07:01 kettenis Exp $ */ + +/* + * Based on ieeefp.h written by J.T. Conklin, Apr 28, 1995 + * Public domain. + */ + +#ifndef _MACHINE_IEEEFP_H_ +#define _MACHINE_IEEEFP_H_ + +typedef int fp_except; +#define FP_X_INV 0x01 /* invalid operation exception */ +#define FP_X_DZ 0x02 /* divide-by-zero exception */ +#define FP_X_OFL 0x04 /* overflow exception */ +#define FP_X_UFL 0x08 /* underflow exception */ +#define FP_X_IMP 0x10 /* imprecise (loss of precision) */ + +typedef enum { + FP_RN=0, /* round to nearest representable number */ + FP_RP=1, /* round toward positive infinity */ + FP_RM=2, /* round toward negative infinity */ + FP_RZ=3 /* round to zero (truncate) */ +} fp_rnd; + +#endif /* _MACHINE_IEEEFP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/intr.h b/lib/libc/include/aarch64-openbsd-none/arm64/intr.h new file mode 100644 index 000000000000..8dbf0d06f8f8 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/intr.h @@ -0,0 +1,226 @@ +/* $OpenBSD: intr.h,v 1.25 2025/06/30 14:19:20 kettenis Exp $ */ + +/* + * Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _MACHINE_INTR_H_ +#define _MACHINE_INTR_H_ + +/* + * The interrupt level ipl is a logical level; per-platform interrupt + * code will turn it into the appropriate hardware interrupt masks + * values. + * + * Interrupt sources on the CPU are kept enabled regardless of the + * current ipl value; individual hardware sources interrupting while + * logically masked are masked on the fly, remembered as pending, and + * unmasked at the first splx() opportunity. + */ +#ifdef _KERNEL + +/* Interrupt priority `levels'; not mutually exclusive. */ +#define IPL_NONE 0 /* nothing */ +#define IPL_SOFTCLOCK 2 /* soft clock interrupts */ +#define IPL_SOFTNET 3 /* soft network interrupts */ +#define IPL_SOFTTTY 4 /* soft terminal interrupts */ +#define IPL_BIO 5 /* block I/O */ +#define IPL_NET 6 /* network */ +#define IPL_TTY 7 /* terminal */ +#define IPL_VM 8 /* memory allocation */ +#define IPL_AUDIO 9 /* audio */ +#define IPL_CLOCK 10 /* clock */ +#define IPL_SCHED IPL_CLOCK +#define IPL_STATCLOCK IPL_CLOCK +#define IPL_HIGH 11 /* everything */ +#define IPL_IPI 12 /* interprocessor interrupt */ +#define NIPL 13 /* number of levels */ + +#define IPL_MPFLOOR IPL_TTY +/* Interrupt priority 'flags'. */ +#define IPL_IRQMASK 0xf /* priority only */ +#define IPL_FLAGMASK 0xf00 /* flags only*/ +#define IPL_MPSAFE 0x100 /* 'mpsafe' interrupt, no kernel lock */ +#define IPL_WAKEUP 0x200 /* 'wakeup' interrupt */ + +/* Interrupt sharing types. */ +#define IST_NONE 0 /* none */ +#define IST_PULSE 1 /* pulsed */ +#define IST_EDGE 2 /* edge-triggered */ +#define IST_LEVEL 3 /* level-triggered */ + +#define IST_LEVEL_LOW IST_LEVEL +#define IST_LEVEL_HIGH 4 +#define IST_EDGE_FALLING IST_EDGE +#define IST_EDGE_RISING 5 +#define IST_EDGE_BOTH 6 + +#define __USE_MI_SOFTINTR + +#include + +#ifndef _LOCORE +#include + +void softintr(int); + +int splraise(int); +int spllower(int); +void splx(int); + +void arm_do_pending_intr(int); +void arm_set_intr_handler(int (*)(int), int (*)(int), void (*)(int), + void (*)(int), void (*)(void *), void (*)(void *), + void (*)(void), void (*)(void)); + +struct machine_intr_handle { + struct interrupt_controller *ih_ic; + void *ih_ih; +}; + +struct arm_intr_func { + int (*raise)(int); + int (*lower)(int); + void (*x)(int); + void (*setipl)(int); + void (*enable_wakeup)(void); + void (*disable_wakeup)(void); +}; + +extern struct arm_intr_func arm_intr_func; + +#define splraise(cpl) (arm_intr_func.raise(cpl)) +#define _splraise(cpl) (arm_intr_func.raise(cpl)) +#define spllower(cpl) (arm_intr_func.lower(cpl)) +#define splx(cpl) (arm_intr_func.x(cpl)) + +#define splsoftclock() splraise(IPL_SOFTCLOCK) +#define splsoftnet() splraise(IPL_SOFTNET) +#define splsofttty() splraise(IPL_SOFTTTY) +#define splbio() splraise(IPL_BIO) +#define splnet() splraise(IPL_NET) +#define spltty() splraise(IPL_TTY) +#define splvm() splraise(IPL_VM) +#define splaudio() splraise(IPL_AUDIO) +#define splclock() splraise(IPL_CLOCK) +#define splsched() splraise(IPL_SCHED) +#define splstatclock() splraise(IPL_STATCLOCK) +#define splhigh() splraise(IPL_HIGH) + +#define spl0() spllower(IPL_NONE) + +void intr_barrier(void *); +void intr_set_wakeup(void *); +void intr_enable_wakeup(void); +void intr_disable_wakeup(void); + +void arm_init_smask(void); /* XXX */ +extern uint32_t arm_smask[NIPL]; + +/* XXX - this is probably the wrong location for this */ +void arm_clock_register(void (*)(void), void (*)(u_int), void (*)(int), + void (*)(void)); + +struct cpu_info; + +struct interrupt_controller { + int ic_node; + void *ic_cookie; + void *(*ic_establish)(void *, int *, int, struct cpu_info *, + int (*)(void *), void *, char *); + void *(*ic_establish_msi)(void *, uint64_t *, uint64_t *, int, + struct cpu_info *, int (*)(void *), void *, char *); + void (*ic_disestablish)(void *); + void (*ic_enable)(void *); + void (*ic_disable)(void *); + void (*ic_route)(void *, int, struct cpu_info *); + void (*ic_cpu_enable)(void); + void (*ic_barrier)(void *); + void (*ic_set_wakeup)(void *); + + LIST_ENTRY(interrupt_controller) ic_list; + uint32_t ic_phandle; + uint32_t ic_cells; + uint32_t ic_gic_its_id; +}; + +void arm_intr_init_fdt(void); +void arm_intr_register_fdt(struct interrupt_controller *); +void *arm_intr_establish_fdt(int, int, int (*)(void *), + void *, char *); +void *arm_intr_establish_fdt_cpu(int, int, struct cpu_info *, + int (*)(void *), void *, char *); +void *arm_intr_establish_fdt_idx(int, int, int, int (*)(void *), + void *, char *); +void *arm_intr_establish_fdt_idx_cpu(int, int, int, struct cpu_info *, + int (*)(void *), void *, char *); +void *arm_intr_establish_fdt_imap(int, int *, int, int, int (*)(void *), + void *, char *); +void *arm_intr_establish_fdt_imap_cpu(int, int *, int, int, + struct cpu_info *, int (*)(void *), void *, char *); +void *arm_intr_establish_fdt_msi(int, uint64_t *, uint64_t *, int, + int (*)(void *), void *, char *); +void *arm_intr_establish_fdt_msi_cpu(int, uint64_t *, uint64_t *, int, + struct cpu_info *, int (*)(void *), void *, char *); +void arm_intr_disestablish_fdt(void *); +void arm_intr_enable(void *); +void arm_intr_disable(void *); +void arm_intr_route(void *, int, struct cpu_info *); +void arm_intr_cpu_enable(void); +void *arm_intr_parent_establish_fdt(void *, int *, int, + struct cpu_info *ci, int (*)(void *), void *, char *); +void arm_intr_parent_disestablish_fdt(void *); + +void arm_send_ipi(struct cpu_info *, int); +extern void (*intr_send_ipi_func)(struct cpu_info *, int); + +#define ARM_IPI_NOP 0 +#define ARM_IPI_DDB 1 +#define ARM_IPI_HALT 2 + +#ifdef DIAGNOSTIC +/* + * Although this function is implemented in MI code, it must be in this MD + * header because we don't want this header to include MI includes. + */ +void splassert_fail(int, int, const char *); +extern int splassert_ctl; +void arm_splassert_check(int, const char *); +#define splassert(__wantipl) do { \ + if (splassert_ctl > 0) { \ + arm_splassert_check(__wantipl, __func__); \ + } \ +} while (0) +#define splsoftassert(wantipl) splassert(wantipl) +#else +#define splassert(wantipl) do { /* nothing */ } while (0) +#define splsoftassert(wantipl) do { /* nothing */ } while (0) +#endif + +#endif /* ! _LOCORE */ + +#endif /* _KERNEL */ + +#endif /* _MACHINE_INTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/kcore.h b/lib/libc/include/aarch64-openbsd-none/arm64/kcore.h new file mode 100644 index 000000000000..a65c7257a0f4 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/kcore.h @@ -0,0 +1,15 @@ +/* $OpenBSD: kcore.h,v 1.1 2016/12/17 23:38:33 patrick Exp $ */ +/* public domain */ + +/* Make sure this is larger than DRAM_BLOCKS on all arm-based platforms */ +#define NPHYS_RAM_SEGS 8 + +typedef struct cpu_kcore_hdr { + u_int64_t kernelbase; /* value of KERNEL_BASE */ + u_int64_t kerneloffs; /* offset of kernel in RAM */ + u_int64_t staticsize; /* size of contiguous mapping */ + u_int64_t pmap_kernel_l1; /* pmap_kernel()->pm_l1 */ + u_int64_t pmap_kernel_l2; /* pmap_kernel()->pm_l2 */ + u_int64_t reserved[11]; + phys_ram_seg_t ram_segs[NPHYS_RAM_SEGS]; +} cpu_kcore_hdr_t; \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/limits.h b/lib/libc/include/aarch64-openbsd-none/arm64/limits.h new file mode 100644 index 000000000000..491b57a52aa8 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/limits.h @@ -0,0 +1,56 @@ +/* $OpenBSD: limits.h,v 1.1 2016/12/17 23:38:33 patrick Exp $ */ +/* $NetBSD: limits.h,v 1.4 2003/04/28 23:16:18 bjh21 Exp $ */ + +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)limits.h 7.2 (Berkeley) 6/28/90 + */ + +#ifndef _MACHINE_LIMITS_H_ +#define _MACHINE_LIMITS_H_ + +#include + +#if __POSIX_VISIBLE || __XPG_VISIBLE +#ifndef SIZE_MAX +#define SIZE_MAX ULONG_MAX /* max value for a size_t */ +#endif +#define SSIZE_MAX LONG_MAX /* max value for a ssize_t */ +#endif + +#if __BSD_VISIBLE +#define SIZE_T_MAX ULONG_MAX /* max value for a size_t (historic) */ + +#define UQUAD_MAX 0xffffffffffffffffULL /* max unsigned quad */ +#define QUAD_MAX 0x7fffffffffffffffLL /* max signed quad */ +#define QUAD_MIN (-0x7fffffffffffffffLL-1) /* min signed quad */ + +#endif /* __BSD_VISIBLE */ + +#endif /* _MACHINE_LIMITS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/loadfile_machdep.h b/lib/libc/include/aarch64-openbsd-none/arm64/loadfile_machdep.h new file mode 100644 index 000000000000..59761f8b7e74 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/loadfile_machdep.h @@ -0,0 +1,53 @@ +/* $OpenBSD: loadfile_machdep.h,v 1.2 2019/04/10 04:17:34 deraadt Exp $ */ +/* $NetBSD: loadfile_machdep.h,v 1.1 1999/04/29 03:17:12 tsubai Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define BOOT_ELF +#define ELFSIZE 64 + +#define LOAD_KERNEL (LOAD_ALL & ~LOAD_TEXTA) +#define COUNT_KERNEL (COUNT_ALL & ~COUNT_TEXTA) + +extern u_long efi_loadaddr; +#define LOADADDR(a) (((((u_long)(a)) + offset)&0x7fffffffff) + \ + efi_loadaddr) +#define ALIGNENTRY(a) ((u_long)(a)) +#define READ(f, b, c) read((f), (void *)LOADADDR(b), (c)) +#define BCOPY(s, d, c) memcpy((void *)LOADADDR(d), (void *)(s), (c)) +#define BZERO(d, c) memset((void *)LOADADDR(d), 0, (c)) +#define WARN(a) (void)(printf a, \ + printf((errno ? ": %s\n" : "\n"), \ + strerror(errno))) +#define PROGRESS(a) (void) printf a +#define ALLOC(a) alloc(a) +#define FREE(a, b) free(a, b) + +void run_loadfile(uint64_t *, int); \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/mplock.h b/lib/libc/include/aarch64-openbsd-none/arm64/mplock.h new file mode 100644 index 000000000000..36a2b125ab75 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/mplock.h @@ -0,0 +1,10 @@ +/* $OpenBSD: mplock.h,v 1.3 2018/01/05 17:42:35 kettenis Exp $ */ + +/* public domain */ + +#ifndef _MACHINE_MPLOCK_H_ +#define _MACHINE_MPLOCK_H_ + +#define __USE_MI_MPLOCK + +#endif /* !_MACHINE_MPLOCK_H */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/mutex.h b/lib/libc/include/aarch64-openbsd-none/arm64/mutex.h new file mode 100644 index 000000000000..f5115c3084e8 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/mutex.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mutex.h,v 1.5 2018/01/25 15:06:29 mpi Exp $ */ + +#define __USE_MI_MUTEX \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/openpromio.h b/lib/libc/include/aarch64-openbsd-none/arm64/openpromio.h new file mode 100644 index 000000000000..3ad914911617 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/openpromio.h @@ -0,0 +1,57 @@ +/* $OpenBSD: openpromio.h,v 1.1 2017/01/23 12:34:06 kettenis Exp $ */ +/* $NetBSD: openpromio.h,v 1.1.1.1 1998/06/20 04:58:52 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)openpromio.h 8.1 (Berkeley) 6/11/93 + */ + +struct opiocdesc { + int op_nodeid; /* passed or returned node id */ + int op_namelen; /* length of op_name */ + char *op_name; /* pointer to field name */ + int op_buflen; /* length of op_buf (value-result) */ + char *op_buf; /* pointer to field value */ +}; + +#define OPIOCGET _IOWR('O', 1, struct opiocdesc) /* get openprom field */ +#define OPIOCSET _IOW('O', 2, struct opiocdesc) /* set openprom field */ +#define OPIOCNEXTPROP _IOWR('O', 3, struct opiocdesc) /* get next property */ +#define OPIOCGETOPTNODE _IOR('O', 4, int) /* get openprom field */ +#define OPIOCGETNEXT _IOWR('O', 5, int) /* get next node of node */ +#define OPIOCGETCHILD _IOWR('O', 6, int) /* get first child of node */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/param.h b/lib/libc/include/aarch64-openbsd-none/arm64/param.h new file mode 100644 index 000000000000..0d7eb0c7964f --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/param.h @@ -0,0 +1,81 @@ +/* $OpenBSD: param.h,v 1.8 2025/07/07 18:33:36 kettenis Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ + +#ifdef _KERNEL +#ifndef _LOCORE +#include +#endif +#endif + +#define _MACHINE arm64 +#define MACHINE "arm64" +#define _MACHINE_ARCH aarch64 +#define MACHINE_ARCH "aarch64" +#define MID_MACHINE MID_ARM64 + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define PAGE_MASK (PAGE_SIZE - 1) + +#define KERNBASE 0xffffff8000000000ULL /* start of kernel virtual space */ + +#ifdef _KERNEL + +#define NBPG PAGE_SIZE /* bytes/page */ +#define PGSHIFT PAGE_SHIFT /* LOG2(PAGE_SIZE) */ +#define PGOFSET PAGE_MASK /* byte offset into page */ + +#define UPAGES 6 /* pages of u-area */ +#define USPACE (UPAGES * PAGE_SIZE) /* total size of u-area */ +#define USPACE_ALIGN 0 /* u-area alignment 0-none */ +#define __HAVE_USPACE_GUARD + +#define NMBCLUSTERS (64 * 1024) /* max cluster allocation */ + +#ifndef MSGBUFSIZE +#define MSGBUFSIZE (16 * PAGE_SIZE) /* default message buffer size */ +#endif + +#define STACKALIGNBYTES (16 - 1) +#define STACKALIGN(p) ((u_long)(p) &~ STACKALIGNBYTES) + +#define __HAVE_ACPI +#define __HAVE_FDT + +#endif /* _KERNEL */ + +#endif /* _MACHINE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/pcb.h b/lib/libc/include/aarch64-openbsd-none/arm64/pcb.h new file mode 100644 index 000000000000..9e4880b7a8ae --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/pcb.h @@ -0,0 +1,45 @@ +/* $OpenBSD: pcb.h,v 1.8 2025/02/24 13:18:01 jsg Exp $ */ +/* + * Copyright (c) 2016 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef _MACHINE_PCB_H_ +#define _MACHINE_PCB_H_ + +#include +#include + +struct trapframe; + +/* + * Warning certain fields must be within 256 bytes of the beginning + * of this structure. + */ +struct pcb { + u_int pcb_flags; +#define PCB_FPU 0x00000001 /* Process had FPU initialized */ +#define PCB_SINGLESTEP 0x00000002 /* Single step process */ +#define PCB_SVE 0x00000004 /* Process had SVE initialized */ + struct trapframe *pcb_tf; + + register_t pcb_sp; /* stack pointer of switchframe */ + + caddr_t pcb_onfault; /* On fault handler */ + struct fpreg pcb_fpstate; /* Floating Point state */ + __uint16_t pcb_sve_p[16]; /* SVE predicate registers */ + __uint16_t pcb_sve_ffr; /* SVE first fault register */ + + void *pcb_tcb; +}; +#endif /* _MACHINE_PCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/pci_machdep.h b/lib/libc/include/aarch64-openbsd-none/arm64/pci_machdep.h new file mode 100644 index 000000000000..fec001a5f434 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/pci_machdep.h @@ -0,0 +1,145 @@ +/* $OpenBSD: pci_machdep.h,v 1.13 2025/01/23 11:24:34 kettenis Exp $ */ + +/* + * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +typedef struct machine_pci_chipset *pci_chipset_tag_t; +typedef uint64_t pcitag_t; + +#define PCITAG_NODE(x) ((x) >> 32) +#define PCITAG_OFFSET(x) ((x) & 0xffffffff) + +/* Supported interrupt types. */ +#define PCI_NONE 0 +#define PCI_INTX 1 +#define PCI_MSI 2 +#define PCI_MSIX 3 + +typedef struct { + pci_chipset_tag_t ih_pc; + pcitag_t ih_tag; + int ih_intrpin; + int ih_type; + bus_dma_tag_t ih_dmat; +} pci_intr_handle_t; + +struct pci_attach_args; + +/* + * Machine-specific PCI structure and type definitions. + * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE. + */ +struct machine_pci_chipset { + void *pc_conf_v; + void (*pc_attach_hook)(struct device *, + struct device *, struct pcibus_attach_args *); + int (*pc_bus_maxdevs)(void *, int); + pcitag_t (*pc_make_tag)(void *, int, int, int); + void (*pc_decompose_tag)(void *, pcitag_t, int *, + int *, int *); + int (*pc_conf_size)(void *, pcitag_t); + pcireg_t (*pc_conf_read)(void *, pcitag_t, int); + void (*pc_conf_write)(void *, pcitag_t, int, pcireg_t); + int (*pc_probe_device_hook)(void *, struct pci_attach_args *); + + void *pc_intr_v; + int (*pc_intr_map)(struct pci_attach_args *, + pci_intr_handle_t *); + int (*pc_intr_map_msi)(struct pci_attach_args *, + pci_intr_handle_t *); + int (*pc_intr_map_msivec)(struct pci_attach_args *, + int, pci_intr_handle_t *); + int (*pc_intr_map_msix)(struct pci_attach_args *, + int, pci_intr_handle_t *); + const char *(*pc_intr_string)(void *, pci_intr_handle_t); + void *(*pc_intr_establish)(void *, pci_intr_handle_t, + int, struct cpu_info *, int (*)(void *), void *, + char *); + void (*pc_intr_disestablish)(void *, void *); +}; + +/* + * Functions provided to machine-independent PCI code. + */ +#define pci_attach_hook(p, s, pba) \ + (*(pba)->pba_pc->pc_attach_hook)((p), (s), (pba)) +#define pci_bus_maxdevs(c, b) \ + (*(c)->pc_bus_maxdevs)((c)->pc_conf_v, (b)) +#define pci_make_tag(c, b, d, f) \ + (*(c)->pc_make_tag)((c)->pc_conf_v, (b), (d), (f)) +#define pci_decompose_tag(c, t, bp, dp, fp) \ + (*(c)->pc_decompose_tag)((c)->pc_conf_v, (t), (bp), (dp), (fp)) +#define pci_conf_size(c, t) \ + (*(c)->pc_conf_size)((c)->pc_conf_v, (t)) +#define pci_conf_read(c, t, r) \ + (*(c)->pc_conf_read)((c)->pc_conf_v, (t), (r)) +#define pci_conf_write(c, t, r, v) \ + (*(c)->pc_conf_write)((c)->pc_conf_v, (t), (r), (v)) +#define pci_probe_device_hook(c, a) \ + (*(c)->pc_probe_device_hook)((c)->pc_conf_v, (a)) +#define pci_intr_map(c, ihp) \ + (*(c)->pa_pc->pc_intr_map)((c), (ihp)) +#define pci_intr_map_msi(c, ihp) \ + (*(c)->pa_pc->pc_intr_map_msi)((c), (ihp)) +#define pci_intr_map_msivec(c, vec, ihp) \ + (*(c)->pa_pc->pc_intr_map_msivec)((c), (vec), (ihp)) +#define pci_intr_map_msix(c, vec, ihp) \ + (*(c)->pa_pc->pc_intr_map_msix)((c), (vec), (ihp)) +#define pci_intr_string(c, ih) \ + (*(c)->pc_intr_string)((c)->pc_intr_v, (ih)) +#define pci_intr_establish(c, ih, l, h, a, nm) \ + (*(c)->pc_intr_establish)((c)->pc_intr_v, (ih), (l), NULL, (h), (a),\ + (nm)) +#define pci_intr_establish_cpu(c, ih, l, ci, h, a, nm) \ + (*(c)->pc_intr_establish)((c)->pc_intr_v, (ih), (l), (ci), (h), (a),\ + (nm)) +#define pci_intr_disestablish(c, iv) \ + (*(c)->pc_intr_disestablish)((c)->pc_intr_v, (iv)) + +#define pci_min_powerstate(c, t) (PCI_PMCSR_STATE_D3) +#define pci_set_powerstate_md(c, t, s, p) + +#define pci_dev_postattach(a, b) + +void pci_mcfg_init(bus_space_tag_t, bus_addr_t, int, int, int); +pci_chipset_tag_t pci_lookup_segment(int, int); + +int pci_intr_enable_msivec(struct pci_attach_args *, int); + +void pci_msi_enable(pci_chipset_tag_t, pcitag_t, bus_addr_t, uint32_t); +void pci_msix_enable(pci_chipset_tag_t, pcitag_t, bus_space_tag_t, + int, bus_addr_t, uint32_t); +int _pci_intr_map_msi(struct pci_attach_args *, pci_intr_handle_t *); +int _pci_intr_map_msivec(struct pci_attach_args *, int, + pci_intr_handle_t *); +int _pci_intr_map_msix(struct pci_attach_args *, int, pci_intr_handle_t *); + +#define __HAVE_PCI_MSIX + +int pci_msix_table_map(pci_chipset_tag_t, pcitag_t, + bus_space_tag_t, bus_space_handle_t *); +void pci_msix_table_unmap(pci_chipset_tag_t, pcitag_t, + bus_space_tag_t, bus_space_handle_t); \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/pmap.h b/lib/libc/include/aarch64-openbsd-none/arm64/pmap.h new file mode 100644 index 000000000000..5f4d7bf5e156 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/pmap.h @@ -0,0 +1,143 @@ +/* $OpenBSD: pmap.h,v 1.29 2025/05/21 09:42:59 kettenis Exp $ */ +/* + * Copyright (c) 2008,2009,2014 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef _ARM64_PMAP_H_ +#define _ARM64_PMAP_H_ + +#ifndef _LOCORE +#include +#include +#include +#endif + + +/* V->P mapping data */ +#define VP_IDX0_CNT 512 +#define VP_IDX0_MASK (VP_IDX0_CNT-1) +#define VP_IDX0_POS 39 +#define VP_IDX1_CNT 512 +#define VP_IDX1_MASK (VP_IDX1_CNT-1) +#define VP_IDX1_POS 30 +#define VP_IDX2_CNT 512 +#define VP_IDX2_MASK (VP_IDX2_CNT-1) +#define VP_IDX2_POS 21 +#define VP_IDX3_CNT 512 +#define VP_IDX3_MASK (VP_IDX3_CNT-1) +#define VP_IDX3_POS 12 + +/* cache flags */ +#define PMAP_CACHE_CI (PMAP_MD0) /* cache inhibit */ +#define PMAP_CACHE_WT (PMAP_MD1) /* writethru */ +#define PMAP_CACHE_WB (PMAP_MD1|PMAP_MD0) /* writeback */ +#define PMAP_CACHE_DEV_NGNRNE (PMAP_MD2) /* device nGnRnE */ +#define PMAP_CACHE_DEV_NGNRE (PMAP_MD2|PMAP_MD0) /* device nGnRE */ +#define PMAP_CACHE_BITS (PMAP_MD0|PMAP_MD1|PMAP_MD2) + +#define PTED_VA_MANAGED_M (PMAP_MD3) +#define PTED_VA_WIRED_M (PMAP_MD3 << 1) + + +#if defined(_KERNEL) && !defined(_LOCORE) +/* + * Pmap stuff + */ + +typedef struct pmap *pmap_t; + +struct pmap { + struct mutex pm_mtx; + union { + struct pmapvp0 *l0; /* virtual to physical table 4 lvl */ + struct pmapvp1 *l1; /* virtual to physical table 3 lvl */ + } pm_vp; + uint64_t pm_pt0pa; + uint64_t pm_asid; + uint64_t pm_guarded; + int have_4_level_pt; + int pm_privileged; + volatile int pm_active; + int pm_refs; /* ref count */ + struct pmap_statistics pm_stats; /* pmap statistics */ + uint64_t pm_apiakey[2]; + uint64_t pm_apdakey[2]; + uint64_t pm_apibkey[2]; + uint64_t pm_apdbkey[2]; + uint64_t pm_apgakey[2]; +}; + +#define PMAP_PA_MASK ~((paddr_t)PAGE_MASK) /* to remove the flags */ +#define PMAP_NOCACHE 0x1 /* non-cacheable memory */ +#define PMAP_DEVICE 0x2 /* device memory */ +#define PMAP_WC PMAP_DEVICE + +#define PG_PMAP_MOD PG_PMAP0 +#define PG_PMAP_REF PG_PMAP1 +#define PG_PMAP_EXE PG_PMAP2 + +// [NCPUS] +extern paddr_t zero_page; +extern paddr_t copy_src_page; +extern paddr_t copy_dst_page; + +void pagezero_cache(vaddr_t); + +extern struct pmap kernel_pmap_; +#define pmap_kernel() (&kernel_pmap_) +#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) +#define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count) + +vaddr_t pmap_bootstrap(long kvo, paddr_t lpt1, long kernelstart, + long kernelend, long ram_start, long ram_end); +void pmap_postinit(void); +void pmap_init_percpu(void); + +void pmap_kenter_cache(vaddr_t va, paddr_t pa, vm_prot_t prot, int cacheable); +void pmap_page_ro(pmap_t pm, vaddr_t va, vm_prot_t prot); +void pmap_page_rw(pmap_t pm, vaddr_t va); + +void pmap_setpauthkeys(struct pmap *); + +paddr_t pmap_steal_avail(size_t size, int align, void **kva); +void pmap_avail_fixup(void); +void pmap_physload_avail(void); + +#define PMAP_GROWKERNEL + +struct pv_entry; + +/* investigate */ +#define pmap_unuse_final(p) do { /* nothing */ } while (0) +int pmap_fault_fixup(pmap_t, vaddr_t, vm_prot_t); + +#define __HAVE_PMAP_MPSAFE_ENTER_COW +#define __HAVE_PMAP_POPULATE +#define __HAVE_PMAP_PURGE + +#endif /* _KERNEL && !_LOCORE */ + +#ifndef _LOCORE +struct vm_page_md { + struct mutex pv_mtx; + LIST_HEAD(,pte_desc) pv_list; +}; + +#define VM_MDPAGE_INIT(pg) do { \ + mtx_init(&(pg)->mdpage.pv_mtx, IPL_VM); \ + LIST_INIT(&((pg)->mdpage.pv_list)); \ +} while (0) +#endif /* _LOCORE */ + +#endif /* _ARM64_PMAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/proc.h b/lib/libc/include/aarch64-openbsd-none/arm64/proc.h new file mode 100644 index 000000000000..0b694ab2f4cb --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/proc.h @@ -0,0 +1,45 @@ +/* $OpenBSD: proc.h,v 1.2 2017/04/13 03:52:25 guenther Exp $ */ +/* $NetBSD: proc.h,v 1.1 2003/04/26 18:39:46 fvdl Exp $ */ + +/* + * Copyright (c) 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)proc.h 7.1 (Berkeley) 5/15/91 + */ + +#ifndef _MACHINE_PROC_H_ +#define _MACHINE_PROC_H_ + +/* + * Machine-dependent part of the proc structure for arm64. + */ +struct mdproc { + volatile int md_astpending; +}; + +#endif /* _MACHINE_PROC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/profile.h b/lib/libc/include/aarch64-openbsd-none/arm64/profile.h new file mode 100644 index 000000000000..65fa3c7bc578 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/profile.h @@ -0,0 +1,68 @@ +/* $OpenBSD: profile.h,v 1.2 2021/02/17 12:11:45 kettenis Exp $ */ +/* + * Copyright (c) 2015 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define _MCOUNT_DECL void _mcount + +#define MCOUNT_ASM_NAME "__mcount" + +#ifdef __PIC__ +#define PLTSYM "" /* XXX -aarch64 defaults to PLT? */ +#else +#define PLTSYM "" +#endif + +#define MCOUNT \ +__asm__ (".text;" \ + ".align 3;" \ + ".globl " MCOUNT_ASM_NAME ";" \ + ".type " MCOUNT_ASM_NAME ",@function;" \ + MCOUNT_ASM_NAME ":;" \ + " stp x0, x1, [sp, #-160]!;" \ + " stp x2, x3, [sp, #16];" \ + " stp x4, x5, [sp, #32];" \ + " stp x6, x7, [sp, #48];" \ + " stp x8, x9, [sp, #64];" \ + " stp x10,x11,[sp, #80];" \ + " stp x12,x13,[sp, #96];" \ + " stp x14,x15,[sp, #112];" \ + " stp x16,x17,[sp, #128];" \ + " stp x29,lr, [sp, #144];" \ + /* load from pc at 8 off frame pointer */ \ + " ldr x0, [x29, #8];" \ + " mov x1, lr;" \ + " bl " __STRING(_mcount) PLTSYM ";" \ + /* restore argument registers */ \ + " ldp x2, x3, [sp, #16];" \ + " ldp x4, x5, [sp, #32];" \ + " ldp x6, x7, [sp, #48];" \ + " ldp x8, x9, [sp, #64];" \ + " ldp x10,x11,[sp, #80];" \ + " ldp x12,x13,[sp, #96];" \ + " ldp x14,x15,[sp, #112];" \ + " ldp x16,x17,[sp, #128];" \ + " ldp x29,lr, [sp, #144];" \ + " ldp x0, x1, [sp], #160;" \ + " ret;"); + +#ifdef _KERNEL +// Change this to dair read/set, then restore. +#define MCOUNT_ENTER \ +__asm__ ("mrs %x0, daif; msr daifset, #0x3": "=r"(s)); +#define MCOUNT_EXIT \ +__asm__ ("msr daif, %x0":: "r"(s)); + +#endif // _KERNEL \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/pte.h b/lib/libc/include/aarch64-openbsd-none/arm64/pte.h new file mode 100644 index 000000000000..980230fc56d0 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/pte.h @@ -0,0 +1,104 @@ +/* $OpenBSD: pte.h,v 1.10 2024/10/14 12:02:16 jsg Exp $ */ +/* + * Copyright (c) 2014 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef _ARM_PTE_H_ +#define _ARM_PTE_H_ + +/* level X descriptor */ +#define Lx_TYPE_MASK (0x00000003) /* mask of type bits */ +#define Lx_TYPE_S (0x00000001) +#define Lx_TYPE_PT (0x00000003) +// XXX need to investigate use of these +#define Lx_PT_NS (1ULL<<63) +#define Lx_PT_AP00 (0ULL<<61) +#define Lx_PT_AP01 (1ULL<<61) +#define Lx_PT_AP10 (2ULL<<61) +#define Lx_PT_AP11 (3ULL<<61) +#define Lx_PT_XN (1ULL<<60) +#define Lx_PT_PXN (1ULL<<59) +#define Lx_TABLE_ALIGN (4096) + +/* Block and Page attributes */ +/* TODO: Add the upper attributes */ +#define ATTR_MASK_H (0xfff0000000000000ULL) +#define ATTR_MASK_L (0x0000000000000fffULL) +#define ATTR_MASK (ATTR_MASK_H | ATTR_MASK_L) +/* Bits 58:55 are reserved for software */ +#define ATTR_SW_MANAGED (1UL << 56) +#define ATTR_SW_WIRED (1UL << 55) +#define ATTR_UXN (1UL << 54) +#define ATTR_PXN (1UL << 53) +#define ATTR_GP (1UL << 50) +#define ATTR_nG (1 << 11) +#define ATTR_AF (1 << 10) +#define ATTR_SH(x) ((x) << 8) +#define ATTR_AP_RW_BIT (1 << 7) +#define ATTR_AP(x) ((x) << 6) +#define ATTR_AP_MASK ATTR_AP(3) +#define ATTR_NS (1 << 5) +#define ATTR_IDX(x) ((x) << 2) +#define ATTR_IDX_MASK (7 << 2) + +#define PTE_ATTR_DEV_NGNRNE 0 +#define PTE_ATTR_DEV_NGNRE 1 +#define PTE_ATTR_CI 2 +#define PTE_ATTR_WB 3 +#define PTE_ATTR_WT 4 + +#define PTE_MEMATTR_DEV_NGNRNE 0x0 +#define PTE_MEMATTR_DEV_NGNRE 0x1 +#define PTE_MEMATTR_CI 0x5 +#define PTE_MEMATTR_WB 0xf +#define PTE_MEMATTR_WT 0xa + +#define SH_INNER 3 +#define SH_OUTER 2 +#define SH_NONE 0 + +/* Level 0 table, 512GiB per entry */ +#define L0_SHIFT 39 +#define L0_INVAL 0x0 /* An invalid address */ +#define L0_BLOCK 0x1 /* A block */ + /* 0x2 also marks an invalid address */ +#define L0_TABLE 0x3 /* A next-level table */ + +/* Level 1 table, 1GiB per entry */ +#define L1_SHIFT 30 +#define L1_SIZE (1 << L1_SHIFT) +#define L1_OFFSET (L1_SIZE - 1) +#define L1_INVAL L0_INVAL +#define L1_BLOCK L0_BLOCK +#define L1_TABLE L0_TABLE + +/* Level 2 table, 2MiB per entry */ +#define L2_SHIFT 21 +#define L2_SIZE (1 << L2_SHIFT) +#define L2_OFFSET (L2_SIZE - 1) +#define L2_INVAL L0_INVAL +#define L2_BLOCK L0_BLOCK +#define L2_TABLE L0_TABLE + +/* page mapping */ +#define L3_P 0x3 + +#define Ln_ENTRIES (1 << 9) +#define Ln_ADDR_MASK (Ln_ENTRIES - 1) +#define Ln_TABLE_MASK ((1 << 12) - 1) + +/* physical page mask */ +#define PTE_RPGN (((1ULL << 48) - 1) & ~PAGE_MASK) + +#endif /* _ARM_PTE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/ptrace.h b/lib/libc/include/aarch64-openbsd-none/arm64/ptrace.h new file mode 100644 index 000000000000..c63c70f29d97 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/ptrace.h @@ -0,0 +1,27 @@ +/* $OpenBSD: ptrace.h,v 1.2 2023/06/10 19:30:48 kettenis Exp $ */ +/* + * Copyright (c) 2014 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define PT_STEP (PT_FIRSTMACH + 0) +#define PT_GETREGS (PT_FIRSTMACH + 1) +#define PT_SETREGS (PT_FIRSTMACH + 2) +#define PT_GETFPREGS (PT_FIRSTMACH + 3) +#define PT_SETFPREGS (PT_FIRSTMACH + 4) +#define PT_PACMASK (PT_FIRSTMACH + 5) + +#ifdef _KERNEL +register_t process_get_pacmask(struct proc *p); +#endif \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/reg.h b/lib/libc/include/aarch64-openbsd-none/arm64/reg.h new file mode 100644 index 000000000000..e8cda2d2dc0f --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/reg.h @@ -0,0 +1,36 @@ +/* $OpenBSD: reg.h,v 1.3 2017/04/11 06:52:13 kettenis Exp $ */ +/* + * Copyright (c) 2014 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_REG_H_ +#define _MACHINE_REG_H_ + +struct reg { + uint64_t r_reg[30]; + uint64_t r_lr; + uint64_t r_sp; + uint64_t r_pc; + uint64_t r_spsr; + uint64_t r_tpidr; +}; + +struct fpreg { + __uint128_t fp_reg[32]; + uint32_t fp_sr; + uint32_t fp_cr; +}; + +#endif /* !_MACHINE_REG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/reloc.h b/lib/libc/include/aarch64-openbsd-none/arm64/reloc.h new file mode 100644 index 000000000000..73ea25bba70f --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/reloc.h @@ -0,0 +1,123 @@ +/* $OpenBSD: reloc.h,v 1.2 2017/10/24 20:35:54 guenther Exp $ */ +/* + * AArch64 static relocation types. + */ + +/* Miscellaneous. */ +#define R_ARM_NONE 0 +#define R_AARCH64_TPOFF64 1 /// COMPLETELY WRONG - stub +#define R_AARCH64_NONE 0 + +/* Data. */ +#define R_AARCH64_ABS64 257 +#define R_AARCH64_ABS32 258 +#define R_AARCH64_ABS16 259 +#define R_AARCH64_PREL64 260 +#define R_AARCH64_PREL32 261 +#define R_AARCH64_PREL16 262 + +/* Instructions. */ +#define R_AARCH64_MOVW_UABS_G0 263 +#define R_AARCH64_MOVW_UABS_G0_NC 264 +#define R_AARCH64_MOVW_UABS_G1 265 +#define R_AARCH64_MOVW_UABS_G1_NC 266 +#define R_AARCH64_MOVW_UABS_G2 267 +#define R_AARCH64_MOVW_UABS_G2_NC 268 +#define R_AARCH64_MOVW_UABS_G3 269 + +#define R_AARCH64_MOVW_SABS_G0 270 +#define R_AARCH64_MOVW_SABS_G1 271 +#define R_AARCH64_MOVW_SABS_G2 272 + +#define R_AARCH64_LD_PREL_LO19 273 +#define R_AARCH64_ADR_PREL_LO21 274 +#define R_AARCH64_ADR_PREL_PG_HI21 275 +#define R_AARCH64_ADR_PREL_PG_HI21_NC 276 +#define R_AARCH64_ADD_ABS_LO12_NC 277 +#define R_AARCH64_LDST8_ABS_LO12_NC 278 + +#define R_AARCH64_TSTBR14 279 +#define R_AARCH64_CONDBR19 280 +#define R_AARCH64_JUMP26 282 +#define R_AARCH64_CALL26 283 +#define R_AARCH64_LDST16_ABS_LO12_NC 284 +#define R_AARCH64_LDST32_ABS_LO12_NC 285 +#define R_AARCH64_LDST64_ABS_LO12_NC 286 +#define R_AARCH64_LDST128_ABS_LO12_NC 299 + +#define R_AARCH64_MOVW_PREL_G0 287 +#define R_AARCH64_MOVW_PREL_G0_NC 288 +#define R_AARCH64_MOVW_PREL_G1 289 +#define R_AARCH64_MOVW_PREL_G1_NC 290 +#define R_AARCH64_MOVW_PREL_G2 291 +#define R_AARCH64_MOVW_PREL_G2_NC 292 +#define R_AARCH64_MOVW_PREL_G3 293 + + +#define R_AARCH64_COPY 1024 +#define R_AARCH64_GLOB_DAT 1025 // S + A +#define R_AARCH64_JUMP_SLOT 1026 // S + A +#define R_AARCH64_RELATIVE 1027 // Delta(S) + A +#define R_AARCH64_TLS_DTPREL64 1028 // DTPREL(S+A) +#define R_AARCH64_TLS_DTPMOD64 1029 // LDM(S) +#define R_AARCH64_TLS_TPREL64 1030 // TPREL(S+A) +#define R_AARCH64_TLSDESC 1031 // TLSDESC(S+A) TLS descriptor to be filled +#define R_AARCH64_IRELATIVE 1032 // Indirect(Delta(S) + A) + +// old arm32 defines. +/* Processor specific relocation types */ + +#define R_ARM_NONE 0 +#define R_ARM_PC24 1 +#define R_ARM_ABS32 2 +#define R_ARM_REL32 3 +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 +#define R_ARM_ABS12 6 +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 + +/* 17-31 are reserved for ARM Linux. */ +#define R_ARM_TLS_DTPMOD32 17 +#define R_ARM_TLS_DTPOFF32 18 +#define R_ARM_TLS_TPOFF32 19 + +#define R_ARM_COPY 20 +#define R_ARM_GLOB_DAT 21 +#define R_ARM_JUMP_SLOT 22 +#define R_ARM_RELATIVE 23 +#define R_ARM_GOTOFF 24 +#define R_ARM_GOTPC 25 +#define R_ARM_GOT32 26 +#define R_ARM_PLT32 27 + +#define R_ARM_ALU_PCREL_7_0 32 +#define R_ARM_ALU_PCREL_15_8 33 +#define R_ARM_ALU_PCREL_23_15 34 +#define R_ARM_ALU_SBREL_11_0 35 +#define R_ARM_ALU_SBREL_19_12 36 +#define R_ARM_ALU_SBREL_27_20 37 + +/* 96-111 are reserved to G++. */ +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_THM_PC11 102 +#define R_ARM_THM_PC9 103 + +/* 112-127 are reserved for private experiments. */ + +#define R_ARM_RXPC25 249 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS32 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/setjmp.h b/lib/libc/include/aarch64-openbsd-none/arm64/setjmp.h new file mode 100644 index 000000000000..098e20281fac --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/setjmp.h @@ -0,0 +1,83 @@ +/* $OpenBSD: setjmp.h,v 1.2 2023/04/11 00:45:07 jsg Exp $ */ +/* $NetBSD: setjmp.h,v 1.2 2001/08/25 14:45:59 bjh21 Exp $ */ + +/* + * machine/setjmp.h: machine dependent setjmp-related information. + */ + +#define _JBLEN 64 /* size, in longs, of a jmp_buf */ + +/* + * NOTE: The internal structure of a jmp_buf is *PRIVATE* + * This information is provided as there is software + * that fiddles with this with obtain the stack pointer + * (yes really ! and it's commercial !). + * + * Description of the setjmp buffer + * + * word 0 magic number (dependant on creator) + * 1 - 3 f4 fp register 4 + * 4 - 6 f5 fp register 5 + * 7 - 9 f6 fp register 6 + * 10 - 12 f7 fp register 7 + * 13 fpsr fp status register + * 14 r4 register 4 + * 15 r5 register 5 + * 16 r6 register 6 + * 17 r7 register 7 + * 18 r8 register 8 + * 19 r9 register 9 + * 20 r10 register 10 (sl) + * 21 r11 register 11 (fp) + * 22 r12 register 12 (ip) + * 23 r13 register 13 (sp) + * 24 r14 register 14 (lr) + * 25 signal mask (dependant on magic) + * 26 (con't) + * 27 (con't) + * 28 (con't) + * + * The magic number identifies the jmp_buf and + * how the buffer was created as well as providing + * a sanity check. + * + * A side note I should mention - please do not tamper + * with the floating point fields. While they are + * always saved and restored at the moment this cannot + * be guaranteed especially if the compiler happens + * to be generating soft-float code so no fp + * registers will be used. + * + * Whilst this can be seen an encouraging people to + * use the setjmp buffer in this way I think that it + * is for the best then if changes occur compiles will + * break rather than just having new builds falling over + * mysteriously. + */ + +#define _JB_MAGIC__SETJMP 0x4278f500 +#define _JB_MAGIC_SETJMP 0x4278f501 + +/* Valid for all jmp_buf's */ + +#define _JB_MAGIC 0 +#define _JB_REG_F4 1 +#define _JB_REG_F5 4 +#define _JB_REG_F6 7 +#define _JB_REG_F7 10 +#define _JB_REG_FPSR 13 +#define _JB_REG_R4 14 +#define _JB_REG_R5 15 +#define _JB_REG_R6 16 +#define _JB_REG_R7 17 +#define _JB_REG_R8 18 +#define _JB_REG_R9 19 +#define _JB_REG_R10 20 +#define _JB_REG_R11 21 +#define _JB_REG_R12 22 +#define _JB_REG_R13 23 +#define _JB_REG_R14 24 + +/* Only valid with the _JB_MAGIC_SETJMP magic */ + +#define _JB_SIGMASK 25 \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/signal.h b/lib/libc/include/aarch64-openbsd-none/arm64/signal.h new file mode 100644 index 000000000000..fede515defa8 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/signal.h @@ -0,0 +1,64 @@ +/* $OpenBSD: signal.h,v 1.2 2017/03/12 17:57:12 kettenis Exp $ */ +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)signal.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _MACHINE_SIGNAL_H_ +#define _MACHINE_SIGNAL_H_ + +#include + +typedef int sig_atomic_t; + +#if __BSD_VISIBLE || __XPG_VISIBLE >= 420 +/* + * Information pushed on stack when a signal is delivered. + * This is used by the kernel to restore state following + * execution of the signal handler. It is also made available + * to the handler to allow it to restore state properly if + * a non-standard exit is performed. + */ +struct sigcontext { + int __sc_unused; + int sc_mask; /* signal mask to restore */ + + unsigned long sc_sp; + unsigned long sc_lr; + unsigned long sc_elr; + unsigned long sc_spsr; + unsigned long sc_x[30]; + + long sc_cookie; +}; +#endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ +#endif /* !_MACHINE_SIGNAL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/simplebusvar.h b/lib/libc/include/aarch64-openbsd-none/arm64/simplebusvar.h new file mode 100644 index 000000000000..be1336cf1fd4 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/simplebusvar.h @@ -0,0 +1,37 @@ +/* $OpenBSD: simplebusvar.h,v 1.1 2023/09/22 01:10:43 jsg Exp $ */ +/* + * Copyright (c) 2016 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +struct simplebus_softc { + struct device sc_dev; + int sc_node; + bus_space_tag_t sc_iot; + bus_dma_tag_t sc_dmat; + int sc_acells; + int sc_scells; + int sc_pacells; + int sc_pscells; + struct bus_space sc_bus; + struct machine_bus_dma_tag sc_dma; + int *sc_ranges; + int sc_rangeslen; + int *sc_dmaranges; + int sc_dmarangeslen; + int sc_early; + int sc_early_nodes[64]; +}; + +extern void simplebus_attach(struct device *, struct device *, void *); \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/smbiosvar.h b/lib/libc/include/aarch64-openbsd-none/arm64/smbiosvar.h new file mode 100644 index 000000000000..5905ff3af6be --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/smbiosvar.h @@ -0,0 +1,278 @@ +/* $OpenBSD: smbiosvar.h,v 1.6 2025/07/15 01:09:32 jsg Exp $ */ +/* + * Copyright (c) 2006 Gordon Willem Klok + * Copyright (c) 2005 Jordan Hargrave + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_SMBIOSVAR_ +#define _MACHINE_SMBIOSVAR_ + +#define SMBIOS_UUID_NPRESENT 0x1 +#define SMBIOS_UUID_NSET 0x2 + +/* + * Section 3.5 of "UUIDs and GUIDs" found at + * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt + * specifies the string representation of a UUID. + */ +#define SMBIOS_UUID_REP "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" +#define SMBIOS_UUID_REPLEN 37 /* 16 zero padded values, 4 hyphens, 1 null */ + +struct smbios_entry { + uint8_t mjr; + uint8_t min; + uint8_t *addr; + uint16_t len; + uint16_t count; +}; + +struct smbhdr { + uint32_t sig; /* "_SM_" */ + uint8_t checksum; /* Entry point checksum */ + uint8_t len; /* Entry point structure length */ + uint8_t majrev; /* Specification major revision */ + uint8_t minrev; /* Specification minor revision */ + uint16_t mss; /* Maximum Structure Size */ + uint8_t epr; /* Entry Point Revision */ + uint8_t fa[5]; /* value determined by EPR */ + uint8_t sasig[5]; /* Secondary Anchor "_DMI_" */ + uint8_t sachecksum; /* Secondary Checksum */ + uint16_t size; /* Length of structure table in bytes */ + uint32_t addr; /* Structure table address */ + uint16_t count; /* Number of SMBIOS structures */ + uint8_t rev; /* BCD revision */ +} __packed; + +struct smb3hdr { + uint8_t sig[5]; /* "_SM3_" */ + uint8_t checksum; /* Entry point structure checksum */ + uint8_t len; /* Entry point length */ + uint8_t majrev; /* SMBIOS major version */ + uint8_t minrev; /* SMBIOS minor version */ + uint8_t docrev; /* SMBIOS docrev */ + uint8_t epr; /* Entry point revision */ + uint8_t reserved; /* Reserved */ + uint32_t size; /* Structure table maximum size */ + uint64_t addr; /* Structure table address */ +} __packed; + +struct smbtblhdr { + uint8_t type; + uint8_t size; + uint16_t handle; +} __packed; + +struct smbtable { + struct smbtblhdr *hdr; + void *tblhdr; + uint32_t cookie; +}; + +#define SMBIOS_TYPE_BIOS 0 +#define SMBIOS_TYPE_SYSTEM 1 +#define SMBIOS_TYPE_BASEBOARD 2 +#define SMBIOS_TYPE_ENCLOSURE 3 +#define SMBIOS_TYPE_PROCESSOR 4 +#define SMBIOS_TYPE_MEMCTRL 5 +#define SMBIOS_TYPE_MEMMOD 6 +#define SMBIOS_TYPE_CACHE 7 +#define SMBIOS_TYPE_PORT 8 +#define SMBIOS_TYPE_SLOTS 9 +#define SMBIOS_TYPE_OBD 10 +#define SMBIOS_TYPE_OEM 11 +#define SMBIOS_TYPE_SYSCONFOPT 12 +#define SMBIOS_TYPE_BIOSLANG 13 +#define SMBIOS_TYPE_GROUPASSOC 14 +#define SMBIOS_TYPE_SYSEVENTLOG 15 +#define SMBIOS_TYPE_PHYMEM 16 +#define SMBIOS_TYPE_MEMDEV 17 +#define SMBIOS_TYPE_ECCINFO32 18 +#define SMBIOS_TYPE_MEMMAPARRAYADDR 19 +#define SMBIOS_TYPE_MEMMAPDEVADDR 20 +#define SMBIOS_TYPE_INBUILTPOINT 21 +#define SMBIOS_TYPE_PORTBATT 22 +#define SMBIOS_TYPE_SYSRESET 23 +#define SMBIOS_TYPE_HWSECUIRTY 24 +#define SMBIOS_TYPE_PWRCTRL 25 +#define SMBIOS_TYPE_VOLTPROBE 26 +#define SMBIOS_TYPE_COOLING 27 +#define SMBIOS_TYPE_TEMPPROBE 28 +#define SMBIOS_TYPE_CURRENTPROBE 29 +#define SMBIOS_TYPE_OOB_REMOTEACCESS 30 +#define SMBIOS_TYPE_BIS 31 +#define SMBIOS_TYPE_SBI 32 +#define SMBIOS_TYPE_ECCINFO64 33 +#define SMBIOS_TYPE_MGMTDEV 34 +#define SMBIOS_TYPE_MGTDEVCOMP 35 +#define SMBIOS_TYPE_MGTDEVTHRESH 36 +#define SMBIOS_TYPE_MEMCHANNEL 37 +#define SMBIOS_TYPE_IPMIDEV 38 +#define SMBIOS_TYPE_SPS 39 +#define SMBIOS_TYPE_INACTIVE 126 +#define SMBIOS_TYPE_EOT 127 + +/* + * SMBIOS Structure Type 0 "BIOS Information" + * DMTF Specification DSP0134 Section: 3.3.1 p.g. 34 + */ +struct smbios_struct_bios { + uint8_t vendor; /* string */ + uint8_t version; /* string */ + uint16_t startaddr; + uint8_t release; /* string */ + uint8_t romsize; + uint64_t characteristics; + uint32_t charext; + uint8_t major_rel; + uint8_t minor_rel; + uint8_t ecf_mjr_rel; /* embedded controller firmware */ + uint8_t ecf_min_rel; /* embedded controller firmware */ +} __packed; + +/* + * SMBIOS Structure Type 1 "System Information" + * DMTF Specification DSP0134 Section 3.3.2 p.g. 35 + */ + +struct smbios_sys { +/* SMBIOS spec 2.0+ */ + uint8_t vendor; /* string */ + uint8_t product; /* string */ + uint8_t version; /* string */ + uint8_t serial; /* string */ +/* SMBIOS spec 2.1+ */ + uint8_t uuid[16]; + uint8_t wakeup; +/* SMBIOS spec 2.4+ */ + uint8_t sku; /* string */ + uint8_t family; /* string */ +} __packed; + +/* + * SMBIOS Structure Type 2 "Base Board (Module) Information" + * DMTF Specification DSP0134 Section 3.3.3 p.g. 37 + */ +struct smbios_board { + uint8_t vendor; /* string */ + uint8_t product; /* string */ + uint8_t version; /* string */ + uint8_t serial; /* string */ + uint8_t asset; /* string */ + uint8_t feature; /* feature flags */ + uint8_t location; /* location in chassis */ + uint16_t handle; /* chassis handle */ + uint8_t type; /* board type */ + uint8_t noc; /* number of contained objects */ +} __packed; + +/* + * SMBIOS Structure Type 3 "System Enclosure or Chassis" + * DMTF Specification DSP0134 + */ +struct smbios_enclosure { + /* SMBIOS spec 2.0+ */ + uint8_t vendor; /* string */ + uint8_t type; + uint8_t version; /* string */ + uint8_t serial; /* string */ + uint8_t asset_tag; /* string */ + /* SMBIOS spec 2.1+ */ + uint8_t boot_state; + uint8_t psu_state; + uint8_t thermal_state; + uint8_t security_status; + /* SMBIOS spec 2.3+ */ + uint16_t oem_defined; + uint8_t height; + uint8_t no_power_cords; + uint8_t no_contained_element; + uint8_t reclen_contained_element; + uint8_t contained_elements; + /* SMBIOS spec 2.7+ */ + uint8_t sku; /* string */ +} __packed; + +/* + * SMBIOS Structure Type 4 "processor Information" + * DMTF Specification DSP0134 v2.5 Section 3.3.5 p.g. 24 + */ +struct smbios_cpu { + uint8_t cpu_socket_designation; /* string */ + uint8_t cpu_type; + uint8_t cpu_family; + uint8_t cpu_mfg; /* string */ + uint32_t cpu_id_eax; + uint32_t cpu_id_edx; + uint8_t cpu_version; /* string */ + uint8_t cpu_voltage; + uint16_t cpu_clock; + uint16_t cpu_max_speed; + uint16_t cpu_current_speed; + uint8_t cpu_status; +#define SMBIOS_CPUST_POPULATED (1<<6) +#define SMBIOS_CPUST_STATUSMASK (0x07) + uint8_t cpu_upgrade; + uint16_t cpu_l1_handle; + uint16_t cpu_l2_handle; + uint16_t cpu_l3_handle; + uint8_t cpu_serial; /* string */ + uint8_t cpu_asset_tag; /* string */ + uint8_t cpu_part_nr; /* string */ + /* following fields were added in smbios 2.5 */ + uint8_t cpu_core_count; + uint8_t cpu_core_enabled; + uint8_t cpu_thread_count; + uint16_t cpu_characteristics; +} __packed; + +/* + * SMBIOS Structure Type 38 "IPMI Information" + * DMTF Specification DSP0134 Section 3.3.39 p.g. 91 + */ +struct smbios_ipmi { + uint8_t smipmi_if_type; /* IPMI Interface Type */ + uint8_t smipmi_if_rev; /* BCD IPMI Revision */ + uint8_t smipmi_i2c_address; /* I2C address of BMC */ + uint8_t smipmi_nvram_address; /* I2C address of NVRAM + * storage */ + uint64_t smipmi_base_address; /* Base address of BMC (BAR + * format */ + uint8_t smipmi_base_flags; /* Flags field: + * bit 7:6 : register spacing + * 00 = byte + * 01 = dword + * 02 = word + * bit 4 : Lower bit BAR + * bit 3 : IRQ valid + * bit 2 : N/A + * bit 1 : Interrupt polarity + * bit 0 : Interrupt trigger */ + uint8_t smipmi_irq; /* IRQ if applicable */ +} __packed; + +int smbios_find_table(uint8_t, struct smbtable *); +char *smbios_get_string(struct smbtable *, uint8_t, char *, size_t); + +#endif \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/spinlock.h b/lib/libc/include/aarch64-openbsd-none/arm64/spinlock.h new file mode 100644 index 000000000000..01f502df0f5a --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/spinlock.h @@ -0,0 +1,25 @@ +/* $OpenBSD: spinlock.h,v 1.2 2017/09/05 02:40:54 guenther Exp $ */ +/* + * Copyright (c) 2014 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_SPINLOCK_H_ +#define _MACHINE_SPINLOCK_H_ + +#define _ATOMIC_LOCK_UNLOCKED (0) +#define _ATOMIC_LOCK_LOCKED (1) +typedef int _atomic_lock_t; + +#endif \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/sysarch.h b/lib/libc/include/aarch64-openbsd-none/arm64/sysarch.h new file mode 100644 index 000000000000..b2b0360289d0 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/sysarch.h @@ -0,0 +1,21 @@ +/* $OpenBSD: sysarch.h,v 1.1 2016/12/17 23:38:33 patrick Exp $ */ +/* + * Copyright (c) 2016 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef _MACHINE_SYSARCH_H_ + +// aarch64 architecture has no libarch or arch specific syscalls. + +#endif /* !_MACHINE_SYSARCH_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/tcb.h b/lib/libc/include/aarch64-openbsd-none/arm64/tcb.h new file mode 100644 index 000000000000..6d129af20ae7 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/tcb.h @@ -0,0 +1,58 @@ +/* $OpenBSD: tcb.h,v 1.2 2017/01/10 13:13:12 patrick Exp $ */ + +/* + * Copyright (c) 2011 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TCB_H_ +#define _MACHINE_TCB_H_ + +#ifdef _KERNEL + +#include + +static inline void +__aarch64_set_tcb(void *tcb) +{ + __asm volatile("msr tpidr_el0, %x0" : : "r" (tcb)); +} + +#define TCB_GET(p) \ + ((struct pcb *)(p)->p_addr)->pcb_tcb + +#define TCB_SET(p, addr) \ + do { \ + ((struct pcb *)(p)->p_addr)->pcb_tcb = (addr); \ + __aarch64_set_tcb(addr); \ + } while (0) + +#else /* _KERNEL */ + +/* ELF TLS ABI calls for small TCB, with static TLS data after it */ +#define TLS_VARIANT 1 + +static inline void * +__aarch64_read_tcb(void) +{ + void *tcb; + __asm volatile("mrs %x0, tpidr_el0": "=r" (tcb)); + return tcb; +} + +#define TCB_GET() __aarch64_read_tcb() + +#endif /* _KERNEL */ + +#endif /* _MACHINE_TCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/timetc.h b/lib/libc/include/aarch64-openbsd-none/arm64/timetc.h new file mode 100644 index 000000000000..ef326e8aca0d --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/timetc.h @@ -0,0 +1,24 @@ +/* $OpenBSD: timetc.h,v 1.3 2023/01/09 15:22:53 kettenis Exp $ */ +/* + * Copyright (c) 2020 Paul Irofti + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TIMETC_H_ +#define _MACHINE_TIMETC_H_ + +#define TC_AGTIMER 1 +#define TC_AGTIMER_SUN50I 2 + +#endif /* _MACHINE_TIMETC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/vmmvar.h b/lib/libc/include/aarch64-openbsd-none/arm64/vmmvar.h new file mode 100644 index 000000000000..7d156212804e --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/vmmvar.h @@ -0,0 +1,93 @@ +/* $OpenBSD: vmmvar.h,v 1.3 2025/08/03 10:17:33 tb Exp $ */ +/* + * Copyright (c) 2014 Mike Larkin + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * CPU capabilities for VMM operation + */ +#ifndef _MACHINE_VMMVAR_H_ +#define _MACHINE_VMMVAR_H_ + +#define VMM_HV_SIGNATURE "OpenBSDVMM58" + +/* Exit Reasons */ +#define VM_EXIT_TERMINATED 0xFFFE +#define VM_EXIT_NONE 0xFFFF + +struct vmm_softc_md { + /* Capabilities */ + uint32_t nr_cpus; /* [I] */ +}; + +/* + * struct vcpu_inject_event : describes an exception or interrupt to inject. + */ +struct vcpu_inject_event { + uint8_t vie_vector; /* Exception or interrupt vector. */ + uint32_t vie_errorcode; /* Optional error code. */ + uint8_t vie_type; +#define VCPU_INJECT_NONE 0 +#define VCPU_INJECT_INTR 1 /* External hardware interrupt. */ +#define VCPU_INJECT_EX 2 /* HW or SW Exception */ +#define VCPU_INJECT_NMI 3 /* Non-maskable Interrupt */ +}; + +#define VCPU_REGS_NGPRS 31 + +struct vcpu_reg_state { + uint64_t vrs_gprs[VCPU_REGS_NGPRS]; +}; + +/* + * struct vm_exit + * + * Contains VM exit information communicated to vmd(8). This information is + * gathered by vmm(4) from the CPU on each exit that requires help from vmd. + */ +struct vm_exit { + struct vcpu_reg_state vrs; +}; + +struct vm_intr_params { + /* Input parameters to VMM_IOC_INTR */ + uint32_t vip_vm_id; + uint32_t vip_vcpu_id; + uint16_t vip_intr; +}; + +#define VM_RWREGS_GPRS 0x1 /* read/write GPRs */ +#define VM_RWREGS_ALL (VM_RWREGS_GPRS) + +struct vm_rwregs_params { + /* + * Input/output parameters to VMM_IOC_READREGS / + * VMM_IOC_WRITEREGS + */ + uint32_t vrwp_vm_id; + uint32_t vrwp_vcpu_id; + uint64_t vrwp_mask; + struct vcpu_reg_state vrwp_regs; +}; + +enum { + VEI_DIR_OUT, + VEI_DIR_IN +}; + +/* IOCTL definitions */ +#define VMM_IOC_INTR _IOW('V', 6, struct vm_intr_params) /* Intr pending */ + +#endif /* ! _MACHINE_VMMVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/arm64/vmparam.h b/lib/libc/include/aarch64-openbsd-none/arm64/vmparam.h new file mode 100644 index 000000000000..94745e8e1c39 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/arm64/vmparam.h @@ -0,0 +1,108 @@ +/* $OpenBSD: vmparam.h,v 1.9 2023/04/28 18:33:22 robert Exp $ */ +/* $NetBSD: vmparam.h,v 1.1 2003/04/26 18:39:49 fvdl Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vmparam.h 5.9 (Berkeley) 5/12/91 + */ + +#ifndef _MACHINE_VMPARAM_H_ +#define _MACHINE_VMPARAM_H_ + +/* + * Machine dependent constants for arm64. + */ + +#define USRSTACK VM_MAXUSER_ADDRESS + +/* + * Virtual memory related constants, all in bytes + */ +#define MAXTSIZ ((paddr_t)256*1024*1024) /* max text size */ +#ifndef DFLDSIZ +#define DFLDSIZ ((paddr_t)512*1024*1024) /* initial data size limit */ +#endif +#ifndef MAXDSIZ +#define MAXDSIZ ((paddr_t)64*1024*1024*1024) /* max data size */ +#endif +#ifndef BRKSIZ +#define BRKSIZ ((paddr_t)16*1024*1024*1024) /* heap gap size */ +#endif +#ifndef DFLSSIZ +#define DFLSSIZ ((paddr_t)2*1024*1024) /* initial stack size limit */ +#endif +#ifndef MAXSSIZ +#define MAXSSIZ ((paddr_t)32*1024*1024) /* max stack size */ +#endif + +#define STACKGAP_RANDOM 256*1024 + +/* + * Size of shared memory map + */ +#ifndef SHMMAXPGS +#define SHMMAXPGS 1024 +#endif + +/* + * Size of User Raw I/O map + */ +#define USRIOSIZE 300 + +/* + * Kernel base + */ +#define KERNEL_BASE 0xffffff8000000000ULL + +/* + * Mach derived constants + */ + +/* user/kernel map constants */ +#define VM_MIN_ADDRESS ((vaddr_t)PAGE_SIZE) +#define USER_SPACE_BITS 39 +#define VM_MAXUSER_ADDRESS ((1ULL << USER_SPACE_BITS) - 0x8000) +#define VM_MAX_ADDRESS VM_MAXUSER_ADDRESS +#ifdef _KERNEL +#define VM_MIN_STACK_ADDRESS (3ULL << (USER_SPACE_BITS - 2)) +#endif +#define VM_MIN_KERNEL_ADDRESS ((vaddr_t)0xffffff8000000000ULL) +#define VM_MAX_KERNEL_ADDRESS ((vaddr_t)0xffffff83ffffffffULL) + +/* virtual sizes (bytes) for various kernel submaps */ +#define VM_PHYS_SIZE (USRIOSIZE*PAGE_SIZE) + +#define VM_PHYSSEG_MAX 32 +#define VM_PHYSSEG_STRAT VM_PSTRAT_BSEARCH +#define VM_PHYSSEG_NOADD /* can't add RAM after vm_mem_init */ + +#endif /* _MACHINE_VMPARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/frame.h b/lib/libc/include/aarch64-openbsd-none/frame.h new file mode 100644 index 000000000000..a169a9a1b9bd --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/frame.h @@ -0,0 +1,77 @@ +/* $OpenBSD: frame.h,v 1.3 2018/06/30 15:23:37 deraadt Exp $ */ +/* + * Copyright (c) 2016 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_FRAME_H_ +#define _MACHINE_FRAME_H_ + +#ifndef _LOCORE + +#include + + +/* + * Exception/Trap Stack Frame + */ +#define clockframe trapframe +typedef struct trapframe { + register_t tf_sp; + register_t tf_lr; + register_t tf_elr; + register_t tf_spsr; + register_t tf_x[30]; +} trapframe_t; + +/* + * pushed on stack for signal delivery + */ +struct sigframe { + int sf_signum; + struct sigcontext sf_sc; + siginfo_t sf_si; +}; + +/* + * System stack frames. + */ + +/* + * Stack frame inside cpu_switch() + */ + +struct switchframe { + register_t sf_x19; + register_t sf_x20; + register_t sf_x21; + register_t sf_x22; + register_t sf_x23; + register_t sf_x24; + register_t sf_x25; + register_t sf_x26; + register_t sf_x27; + register_t sf_x28; + register_t sf_x29; + register_t sf_lr; +}; + +struct callframe { + struct callframe *f_frame; + register_t f_lr; +}; + +#endif /* !_LOCORE */ + +#endif /* _MACHINE_FRAME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/_float.h b/lib/libc/include/aarch64-openbsd-none/machine/_float.h new file mode 100644 index 000000000000..ea467e6f21a1 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/_float.h @@ -0,0 +1,96 @@ +/* $OpenBSD: _float.h,v 1.1 2016/12/17 23:38:33 patrick Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE__FLOAT_H_ +#define _MACHINE__FLOAT_H_ + +#define __FLT_RADIX 2 /* b */ +#define __FLT_ROUNDS __flt_rounds() +#define __FLT_EVAL_METHOD 0 /* no promotions */ + +#define __FLT_MANT_DIG 24 /* p */ +#define __FLT_EPSILON 1.19209290E-7F /* b**(1-p) */ +#define __FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ +#define __FLT_MIN_EXP (-125) /* emin */ +#define __FLT_MIN 1.17549435E-38F /* b**(emin-1) */ +#define __FLT_MIN_10_EXP (-37) /* ceil(log10(b**(emin-1))) */ +#define __FLT_MAX_EXP 128 /* emax */ +#define __FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ +#define __FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ + +#define __DBL_MANT_DIG 53 +#define __DBL_EPSILON 2.2204460492503131E-16 +#define __DBL_DIG 15 +#define __DBL_MIN_EXP (-1021) +#define __DBL_MIN 2.2250738585072014E-308 +#define __DBL_MIN_10_EXP (-307) +#define __DBL_MAX_EXP 1024 +#define __DBL_MAX 1.7976931348623157E+308 +#define __DBL_MAX_10_EXP 308 + +#ifdef __LDBL_MANT_DIG__ +#define __LDBL_MANT_DIG __LDBL_MANT_DIG__ +#define __LDBL_EPSILON __LDBL_EPSILON__ +#define __LDBL_DIG __LDBL_DIG__ +#define __LDBL_MIN_EXP __LDBL_MIN_EXP__ +#define __LDBL_MIN __LDBL_MIN__ +#define __LDBL_MIN_10_EXP __LDBL_MIN_10_EXP__ +#define __LDBL_MAX_EXP __LDBL_MAX_EXP__ +#define __LDBL_MAX __LDBL_MAX__ +#define __LDBL_MAX_10_EXP __LDBL_MAX_10_EXP__ +#else +#define __LDBL_MANT_DIG DBL_MANT_DIG +#define __LDBL_EPSILON DBL_EPSILON +#define __LDBL_DIG DBL_DIG +#define __LDBL_MIN_EXP DBL_MIN_EXP +#define __LDBL_MIN DBL_MIN +#define __LDBL_MIN_10_EXP DBL_MIN_10_EXP +#define __LDBL_MAX_EXP DBL_MAX_EXP +#define __LDBL_MAX DBL_MAX +#define __LDBL_MAX_10_EXP DBL_MAX_10_EXP +#endif + +#define __DECIMAL_DIG 17 + +#endif /* _MACHINE__FLOAT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/_types.h b/lib/libc/include/aarch64-openbsd-none/machine/_types.h new file mode 100644 index 000000000000..2de0c9d512a5 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/_types.h @@ -0,0 +1,145 @@ +/* $OpenBSD: _types.h,v 1.6 2023/07/02 19:02:27 cheloha Exp $ */ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.3 (Berkeley) 1/5/94 + * @(#)ansi.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _MACHINE__TYPES_H_ +#define _MACHINE__TYPES_H_ + +#if defined(_KERNEL) +typedef struct label_t { + long val[13]; +} label_t; +#endif + +/* + * _ALIGN(p) rounds p (pointer or byte index) up to a correctly-aligned + * value for all data types (int, long, ...). The result is an + * unsigned long and must be cast to any desired pointer type. + * + * _ALIGNED_POINTER is a boolean macro that checks whether an address + * is valid to fetch data elements of type t from on this architecture. + * This does not reflect the optimal alignment, just the possibility + * (within reasonable limits). + */ +#define _ALIGNBYTES (sizeof(long) - 1) +#define _STACKALIGNBYTES 15 +#define _ALIGN(p) (((unsigned long)(p) + _ALIGNBYTES) & ~_ALIGNBYTES) +#define _ALIGNED_POINTER(p,t) ((((unsigned long)(p)) & (sizeof(t) - 1)) == 0) +#define _MAX_PAGE_SHIFT 12 /* same as PAGE_SHIFT */ + +/* 7.18.1.1 Exact-width integer types */ +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short __int16_t; +typedef unsigned short __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; +/* LONGLONG */ +typedef long long __int64_t; +/* LONGLONG */ +typedef unsigned long long __uint64_t; + +/* 7.18.1.2 Minimum-width integer types */ +typedef __int8_t __int_least8_t; +typedef __uint8_t __uint_least8_t; +typedef __int16_t __int_least16_t; +typedef __uint16_t __uint_least16_t; +typedef __int32_t __int_least32_t; +typedef __uint32_t __uint_least32_t; +typedef __int64_t __int_least64_t; +typedef __uint64_t __uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types */ +typedef __int32_t __int_fast8_t; +typedef __uint32_t __uint_fast8_t; +typedef __int32_t __int_fast16_t; +typedef __uint32_t __uint_fast16_t; +typedef __int32_t __int_fast32_t; +typedef __uint32_t __uint_fast32_t; +typedef __int64_t __int_fast64_t; +typedef __uint64_t __uint_fast64_t; +#define __INT_FAST8_MIN INT32_MIN +#define __INT_FAST16_MIN INT32_MIN +#define __INT_FAST32_MIN INT32_MIN +#define __INT_FAST64_MIN INT64_MIN +#define __INT_FAST8_MAX INT32_MAX +#define __INT_FAST16_MAX INT32_MAX +#define __INT_FAST32_MAX INT32_MAX +#define __INT_FAST64_MAX INT64_MAX +#define __UINT_FAST8_MAX UINT32_MAX +#define __UINT_FAST16_MAX UINT32_MAX +#define __UINT_FAST32_MAX UINT32_MAX +#define __UINT_FAST64_MAX UINT64_MAX + +/* 7.18.1.4 Integer types capable of holding object pointers */ +typedef long __intptr_t; +typedef unsigned long __uintptr_t; + +/* 7.18.1.5 Greatest-width integer types */ +typedef __int64_t __intmax_t; +typedef __uint64_t __uintmax_t; + +/* Register size */ +typedef long __register_t; + +/* VM system types */ +typedef unsigned long __vaddr_t; +typedef unsigned long __paddr_t; +typedef unsigned long __vsize_t; +typedef unsigned long __psize_t; + +/* Standard system types */ +typedef double __double_t; +typedef float __float_t; +typedef long __ptrdiff_t; +typedef unsigned long __size_t; +typedef long __ssize_t; +#if defined(__GNUC__) && __GNUC__ >= 3 +typedef __builtin_va_list __va_list; +#else +typedef char * __va_list; +#endif + +/* Wide character support types */ +#ifndef __cplusplus +#ifdef __WCHAR_UNSIGNED__ +typedef unsigned int __wchar_t; +#else +typedef int __wchar_t; +#endif +#endif +typedef int __wint_t; +typedef int __rune_t; +typedef void * __wctrans_t; +typedef void * __wctype_t; + +#endif /* _MACHINE__TYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/acpiapm.h b/lib/libc/include/aarch64-openbsd-none/machine/acpiapm.h new file mode 100644 index 000000000000..9664811d2bce --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/acpiapm.h @@ -0,0 +1,22 @@ +/* $OpenBSD: acpiapm.h,v 1.1 2019/01/23 09:57:36 phessler Exp $ */ +/* + * Copyright (c) 2007 Ted Unangst + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +extern int (*acpiapm_open)(dev_t, int, int, struct proc *); +extern int (*acpiapm_close)(dev_t, int, int, struct proc *); +extern int (*acpiapm_ioctl)(dev_t, u_long, caddr_t, int, struct proc *); +extern int (*acpiapm_kqfilter)(dev_t, struct knote *); \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/apmvar.h b/lib/libc/include/aarch64-openbsd-none/machine/apmvar.h new file mode 100644 index 000000000000..f824cfe20417 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/apmvar.h @@ -0,0 +1,127 @@ +/* $OpenBSD: apmvar.h,v 1.3 2023/01/22 13:14:21 kettenis Exp $ */ + +/* + * Copyright (c) 2001 Alexander Guy + * Copyright (c) 1995 John T. Kohl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _MACHINE_APMVAR_H_ +#define _MACHINE_APMVAR_H_ + +#include + +/* Advanced Power Management (v1.0 and v1.1 specification) + * functions/defines/etc. + */ + +/* These definitions make up the heart of the user-land interface + * to the APM devices. + */ + +#define APM_AC_OFF 0x00 +#define APM_AC_ON 0x01 +#define APM_AC_BACKUP 0x02 +#define APM_AC_UNKNOWN 0xff +#define APM_BATT_HIGH 0x00 +#define APM_BATT_LOW 0x01 +#define APM_BATT_CRITICAL 0x02 +#define APM_BATT_CHARGING 0x03 +#define APM_BATT_UNKNOWN 0xff +#define APM_BATT_LIFE_UNKNOWN 0xff + +#define APM_NOEVENT 0x0000 +#define APM_STANDBY_REQ 0x0001 +#define APM_SUSPEND_REQ 0x0002 +#define APM_NORMAL_RESUME 0x0003 +#define APM_CRIT_RESUME 0x0004 /* suspend/resume happened + without us */ +#define APM_BATTERY_LOW 0x0005 +#define APM_POWER_CHANGE 0x0006 +#define APM_UPDATE_TIME 0x0007 +#define APM_CRIT_SUSPEND_REQ 0x0008 +#define APM_USER_STANDBY_REQ 0x0009 +#define APM_USER_SUSPEND_REQ 0x000A +#define APM_SYS_STANDBY_RESUME 0x000B +#define APM_CAPABILITY_CHANGE 0x000C /* apm v1.2 */ +#define APM_USER_HIBERNATE_REQ 0x000D +#define APM_EVENT_MASK 0xffff + +#define APM_EVENT_COMPOSE(t,i) ((((i) & 0x7fff) << 16)|((t) & APM_EVENT_MASK)) +#define APM_EVENT_TYPE(e) ((e) & APM_EVENT_MASK) +#define APM_EVENT_INDEX(e) ((e) >> 16) + +/* + * LP (Laptop Package) + * + * Copyright (C) 1994 by HOSOKAWA Tatsumi + * + * This software may be used, modified, copied, and distributed, in + * both source and binary form provided that the above copyright and + * these terms are retained. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with its + * use. + * + * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) + */ + +#define APM_BATTERY_ABSENT 4 + +struct apm_power_info { + u_char battery_state; + u_char ac_state; + u_char battery_life; + u_char spare1; + u_int minutes_left; /* estimate */ + u_int spare2[6]; +}; + +struct apm_ctl { + u_int dev; + u_int mode; +}; + +#define APM_IOC_REJECT _IOW('A', 0, struct apm_event_info) /* reject request # */ +#define APM_IOC_STANDBY _IO('A', 1) /* put system into standby */ +#define APM_IOC_SUSPEND _IO('A', 2) /* put system into suspend */ +#define APM_IOC_GETPOWER _IOR('A', 3, struct apm_power_info) /* fetch battery state */ +#define APM_IOC_DEV_CTL _IOW('A', 5, struct apm_ctl) /* put device into mode */ +#define APM_IOC_PRN_CTL _IOW('A', 6, int ) /* driver power status msg */ +#define APM_PRINT_ON 0 /* driver power status displayed */ +#define APM_PRINT_OFF 1 /* driver power status not displayed */ +#define APM_PRINT_PCT 2 /* driver power status only displayed + if the percentage changes */ +#define APM_IOC_STANDBY_REQ _IO('A', 7) /* request standby */ +#define APM_IOC_SUSPEND_REQ _IO('A', 8) /* request suspend */ +#define APM_IOC_HIBERNATE _IO('A', 9) /* put system into hibernate */ + +#ifdef _KERNEL +void apm_setinfohook(int (*)(struct apm_power_info *)); +int apm_record_event(u_int); +#endif + +#endif /* _MACHINE_APMVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/armreg.h b/lib/libc/include/aarch64-openbsd-none/machine/armreg.h new file mode 100644 index 000000000000..7483ae8dd70d --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/armreg.h @@ -0,0 +1,973 @@ +/* $OpenBSD: armreg.h,v 1.44 2025/07/22 09:20:41 kettenis Exp $ */ +/*- + * Copyright (c) 2013, 2014 Andrew Turner + * Copyright (c) 2015 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Andrew Turner 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. + * + * $FreeBSD: head/sys/arm64/include/armreg.h 309248 2016-11-28 14:24:07Z andrew $ + */ + +#ifndef _MACHINE_ARMREG_H_ +#define _MACHINE_ARMREG_H_ + +#define INSN_SIZE 4 + +#define READ_SPECIALREG(reg) \ +({ uint64_t val; \ + __asm volatile("mrs %0, " __STRING(reg) : "=&r" (val)); \ + val; \ +}) +#define WRITE_SPECIALREG(reg, val) \ + __asm volatile("msr " __STRING(reg) ", %0" : : "r"((uint64_t)val)) + +/* CCSIDR_EL1 - Current Cache Size ID Register */ +#define CCSIDR_SETS_MASK 0x0fffe000 +#define CCSIDR_SETS_SHIFT 13 +#define CCSIDR_SETS(reg) \ + ((((reg) & CCSIDR_SETS_MASK) >> CCSIDR_SETS_SHIFT) + 1) +#define CCSIDR_WAYS_MASK 0x00001ff8 +#define CCSIDR_WAYS_SHIFT 3 +#define CCSIDR_WAYS(reg) \ + ((((reg) & CCSIDR_WAYS_MASK) >> CCSIDR_WAYS_SHIFT) + 1) +#define CCSIDR_LINE_MASK 0x00000007 +#define CCSIDR_LINE_SIZE(reg) (1 << (((reg) & CCSIDR_LINE_MASK) + 4)) + +#define CCSIDR_CCIDX_SETS_MASK 0x00ffffff00000000ULL +#define CCSIDR_CCIDX_SETS_SHIFT 32 +#define CCSIDR_CCIDX_SETS(reg) \ + ((((reg) & CCSIDR_CCIDX_SETS_MASK) >> CCSIDR_CCIDX_SETS_SHIFT) + 1) +#define CCSIDR_CCIDX_WAYS_MASK 0x0000000000fffff8ULL +#define CCSIDR_CCIDX_WAYS_SHIFT 3 +#define CCSIDR_CCIDX_WAYS(reg) \ + ((((reg) & CCSIDR_CCIDX_WAYS_MASK) >> CCSIDR_CCIDX_WAYS_SHIFT) + 1) +#define CCSIDR_CCIDX_LINE_MASK 0x0000000000000007ULL +#define CCSIDR_CCIDX_LINE_SIZE(reg) \ + (1 << (((reg) & CCSIDR_CCIDX_LINE_MASK) + 4)) + +/* CLIDR_EL1 - Cache Level ID Register */ +#define CLIDR_CTYPE_MASK 0x7 +#define CLIDR_CTYPE_INSN 0x1 +#define CLIDR_CTYPE_DATA 0x2 +#define CLIDR_CTYPE_UNIFIED 0x4 + +/* CNTHCTL_EL2 - Counter-timer Hypervisor Control Register */ +#define CNTHCTL_EVNTI_MASK (0xf << 4) /* Bit to trigger event stream */ +#define CNTHCTL_EVNTDIR (1 << 3) /* Control transition trigger bit */ +#define CNTHCTL_EVNTEN (1 << 2) /* Enable event stream */ +#define CNTHCTL_EL1PCEN (1 << 1) /* Allow EL0/1 physical timer access */ +#define CNTHCTL_EL1PCTEN (1 << 0) /*Allow EL0/1 physical counter access*/ + +/* CNTKCTL_EL1 - Counter-timer Kernel Control Register */ +#define CNTKCTL_EL0VCTEN (1 << 1) /* Allow EL0 virtual counter access */ + +/* CNTV_CTL_EL0 */ +#define CNTV_CTL_ENABLE (1 << 0) +#define CNTV_CTL_IMASK (1 << 1) +#define CNTV_CTL_ISTATUS (1 << 2) + +/* CPACR_EL1 */ +#define CPACR_ZEN_MASK (0x3 << 16) +#define CPACR_ZEN_TRAP_ALL1 (0x0 << 16) /* Traps from EL0 and EL1 */ +#define CPACR_ZEN_TRAP_EL0 (0x1 << 16) /* Traps from EL0 */ +#define CPACR_ZEN_TRAP_ALL2 (0x2 << 16) /* Traps from EL0 and EL1 */ +#define CPACR_ZEN_TRAP_NONE (0x3 << 16) /* No traps */ +#define CPACR_FPEN_MASK (0x3 << 20) +#define CPACR_FPEN_TRAP_ALL1 (0x0 << 20) /* Traps from EL0 and EL1 */ +#define CPACR_FPEN_TRAP_EL0 (0x1 << 20) /* Traps from EL0 */ +#define CPACR_FPEN_TRAP_ALL2 (0x2 << 20) /* Traps from EL0 and EL1 */ +#define CPACR_FPEN_TRAP_NONE (0x3 << 20) /* No traps */ +#define CPACR_TTA (0x1 << 28) + +/* CSSELR_EL1 - Cache Size Selection Register */ +#define CSSELR_IND (1 << 0) +#define CSSELR_LEVEL_SHIFT 1 + +/* CTR_EL0 - Cache Type Register */ +#define CTR_DLINE_SHIFT 16 +#define CTR_DLINE_MASK (0xf << CTR_DLINE_SHIFT) +#define CTR_DLINE_SIZE(reg) (((reg) & CTR_DLINE_MASK) >> CTR_DLINE_SHIFT) +#define CTR_IL1P_SHIFT 14 +#define CTR_IL1P_MASK (0x3 << CTR_IL1P_SHIFT) +#define CTR_IL1P_AIVIVT (0x1 << CTR_IL1P_SHIFT) +#define CTR_IL1P_VIPT (0x2 << CTR_IL1P_SHIFT) +#define CTR_IL1P_PIPT (0x3 << CTR_IL1P_SHIFT) +#define CTR_ILINE_SHIFT 0 +#define CTR_ILINE_MASK (0xf << CTR_ILINE_SHIFT) +#define CTR_ILINE_SIZE(reg) (((reg) & CTR_ILINE_MASK) >> CTR_ILINE_SHIFT) + +/* MPIDR_EL1 - Multiprocessor Affinity Register */ +#define MPIDR_AFF3 (0xFFULL << 32) +#define MPIDR_AFF2 (0xFFULL << 16) +#define MPIDR_AFF1 (0xFFULL << 8) +#define MPIDR_AFF0 (0xFFULL << 0) +#define MPIDR_AFF (MPIDR_AFF3|MPIDR_AFF2|MPIDR_AFF1|MPIDR_AFF0) + +/* DCZID_EL0 - Data Cache Zero ID register */ +#define DCZID_DZP (1 << 4) /* DC ZVA prohibited if non-0 */ +#define DCZID_BS_SHIFT 0 +#define DCZID_BS_MASK (0xf << DCZID_BS_SHIFT) +#define DCZID_BS_SIZE(reg) (((reg) & DCZID_BS_MASK) >> DCZID_BS_SHIFT) + +/* ESR_ELx */ +#define ESR_ELx_ISS_MASK 0x00ffffff +#define ISS_INSN_FnV (0x01 << 10) +#define ISS_INSN_EA (0x01 << 9) +#define ISS_INSN_S1PTW (0x01 << 7) +#define ISS_INSN_IFSC_MASK (0x1f << 0) +#define ISS_DATA_ISV (0x01 << 24) +#define ISS_DATA_SAS_MASK (0x03 << 22) +#define ISS_DATA_SSE (0x01 << 21) +#define ISS_DATA_SRT_MASK (0x1f << 16) +#define ISS_DATA_SF (0x01 << 15) +#define ISS_DATA_AR (0x01 << 14) +#define ISS_DATA_FnV (0x01 << 10) +#define ISS_DATA_EA (0x01 << 9) +#define ISS_DATA_CM (0x01 << 8) +#define ISS_DATA_S1PTW (0x01 << 7) +#define ISS_DATA_WnR (0x01 << 6) +#define ISS_DATA_DFSC_MASK (0x3f << 0) +#define ISS_DATA_DFSC_ASF_L0 (0x00 << 0) +#define ISS_DATA_DFSC_ASF_L1 (0x01 << 0) +#define ISS_DATA_DFSC_ASF_L2 (0x02 << 0) +#define ISS_DATA_DFSC_ASF_L3 (0x03 << 0) +#define ISS_DATA_DFSC_TF_L0 (0x04 << 0) +#define ISS_DATA_DFSC_TF_L1 (0x05 << 0) +#define ISS_DATA_DFSC_TF_L2 (0x06 << 0) +#define ISS_DATA_DFSC_TF_L3 (0x07 << 0) +#define ISS_DATA_DFSC_AFF_L1 (0x09 << 0) +#define ISS_DATA_DFSC_AFF_L2 (0x0a << 0) +#define ISS_DATA_DFSC_AFF_L3 (0x0b << 0) +#define ISS_DATA_DFSC_PF_L1 (0x0d << 0) +#define ISS_DATA_DFSC_PF_L2 (0x0e << 0) +#define ISS_DATA_DFSC_PF_L3 (0x0f << 0) +#define ISS_DATA_DFSC_EXT (0x10 << 0) +#define ISS_DATA_DFSC_EXT_L0 (0x14 << 0) +#define ISS_DATA_DFSC_EXT_L1 (0x15 << 0) +#define ISS_DATA_DFSC_EXT_L2 (0x16 << 0) +#define ISS_DATA_DFSC_EXT_L3 (0x17 << 0) +#define ISS_DATA_DFSC_ECC (0x18 << 0) +#define ISS_DATA_DFSC_ECC_L0 (0x1c << 0) +#define ISS_DATA_DFSC_ECC_L1 (0x1d << 0) +#define ISS_DATA_DFSC_ECC_L2 (0x1e << 0) +#define ISS_DATA_DFSC_ECC_L3 (0x1f << 0) +#define ISS_DATA_DFSC_ALIGN (0x21 << 0) +#define ISS_DATA_DFSC_TLB_CONFLICT (0x30 << 0) +#define ISS_MSR_DIR_SHIFT 0 +#define ISS_MSR_DIR (0x01 << ISS_MSR_DIR_SHIFT) +#define ISS_MSR_Rt_SHIFT 5 +#define ISS_MSR_Rt_MASK (0x1f << ISS_MSR_Rt_SHIFT) +#define ISS_MSR_Rt(x) (((x) & ISS_MSR_Rt_MASK) >> ISS_MSR_Rt_SHIFT) +#define ISS_MSR_CRm_SHIFT 1 +#define ISS_MSR_CRm_MASK (0xf << ISS_MSR_CRm_SHIFT) +#define ISS_MSR_CRm(x) (((x) & ISS_MSR_CRm_MASK) >> ISS_MSR_CRm_SHIFT) +#define ISS_MSR_CRn_SHIFT 10 +#define ISS_MSR_CRn_MASK (0xf << ISS_MSR_CRn_SHIFT) +#define ISS_MSR_CRn(x) (((x) & ISS_MSR_CRn_MASK) >> ISS_MSR_CRn_SHIFT) +#define ISS_MSR_OP1_SHIFT 14 +#define ISS_MSR_OP1_MASK (0x7 << ISS_MSR_OP1_SHIFT) +#define ISS_MSR_OP1(x) (((x) & ISS_MSR_OP1_MASK) >> ISS_MSR_OP1_SHIFT) +#define ISS_MSR_OP2_SHIFT 17 +#define ISS_MSR_OP2_MASK (0x7 << ISS_MSR_OP2_SHIFT) +#define ISS_MSR_OP2(x) (((x) & ISS_MSR_OP2_MASK) >> ISS_MSR_OP2_SHIFT) +#define ISS_MSR_OP0_SHIFT 20 +#define ISS_MSR_OP0_MASK (0x3 << ISS_MSR_OP0_SHIFT) +#define ISS_MSR_OP0(x) (((x) & ISS_MSR_OP0_MASK) >> ISS_MSR_OP0_SHIFT) +#define ISS_BRK_COMMENT_MASK 0xffff +#define ESR_ELx_IL (0x01 << 25) +#define ESR_ELx_EC_SHIFT 26 +#define ESR_ELx_EC_MASK (0x3f << 26) +#define ESR_ELx_EXCEPTION(esr) (((esr) & ESR_ELx_EC_MASK) >> ESR_ELx_EC_SHIFT) +#define EXCP_UNKNOWN 0x00 /* Unkwn exception */ +#define EXCP_FP_SIMD 0x07 /* FP/SIMD trap */ +#define EXCP_BRANCH_TGT 0x0d /* Branch target exception */ +#define EXCP_ILL_STATE 0x0e /* Illegal execution state */ +#define EXCP_SVC 0x15 /* SVC trap */ +#define EXCP_MSR 0x18 /* MSR/MRS trap */ +#define EXCP_SVE 0x19 /* SVE trap */ +#define EXCP_FPAC 0x1c /* Faulting PAC trap */ +#define EXCP_INSN_ABORT_L 0x20 /* Instruction abort, from lower EL */ +#define EXCP_INSN_ABORT 0x21 /* Instruction abort, from same EL */ +#define EXCP_PC_ALIGN 0x22 /* PC alignment fault */ +#define EXCP_DATA_ABORT_L 0x24 /* Data abort, from lower EL */ +#define EXCP_DATA_ABORT 0x25 /* Data abort, from same EL */ +#define EXCP_SP_ALIGN 0x26 /* SP alignment fault */ +#define EXCP_TRAP_FP 0x2c /* Trapped FP exception */ +#define EXCP_SERROR 0x2f /* SError interrupt */ +#define EXCP_SOFTSTP_EL0 0x32 /* Software Step, from lower EL */ +#define EXCP_SOFTSTP_EL1 0x33 /* Software Step, from same EL */ +#define EXCP_WATCHPT_EL1 0x35 /* Watchpoint, from same EL */ +#define EXCP_BRK 0x3c /* Breakpoint */ + +/* ICC_CTLR_EL1 */ +#define ICC_CTLR_EL1_EOIMODE (1U << 1) +#define ICC_CTLR_EL1_PRIBITS_SHIFT 8 +#define ICC_CTLR_EL1_PRIBITS_MASK (0x7UL << 8) +#define ICC_CTLR_EL1_PRIBITS(reg) \ + (((reg) & ICC_CTLR_EL1_PRIBITS_MASK) >> ICC_CTLR_EL1_PRIBITS_SHIFT) + +/* ICC_IAR1_EL1 */ +#define ICC_IAR1_EL1_SPUR (0x03ff) + +/* ICC_IGRPEN0_EL1 */ +#define ICC_IGRPEN0_EL1_EN (1U << 0) + +/* ICC_PMR_EL1 */ +#define ICC_PMR_EL1_PRIO_MASK (0xFFUL) + +/* ICC_SGI1R_EL1 */ +#define ICC_SGI1R_EL1_TL_MASK 0xffffUL +#define ICC_SGI1R_EL1_AFF1_SHIFT 16 +#define ICC_SGI1R_EL1_SGIID_SHIFT 24 +#define ICC_SGI1R_EL1_AFF2_SHIFT 32 +#define ICC_SGI1R_EL1_AFF3_SHIFT 48 +#define ICC_SGI1R_EL1_SGIID_MASK 0xfUL +#define ICC_SGI1R_EL1_IRM (0x1UL << 40) + +/* ICC_SRE_EL1 */ +#define ICC_SRE_EL1_SRE (1U << 0) + +/* ICC_SRE_EL2 */ +#define ICC_SRE_EL2_SRE (1U << 0) +#define ICC_SRE_EL2_EN (1U << 3) + +/* ID_AA64DFR0_EL1 */ +#define ID_AA64DFR0_MASK 0x00000000f0f0ffffUL +#define ID_AA64DFR0_DEBUG_VER_SHIFT 0 +#define ID_AA64DFR0_DEBUG_VER_MASK (0xfULL << ID_AA64DFR0_DEBUG_VER_SHIFT) +#define ID_AA64DFR0_DEBUG_VER(x) ((x) & ID_AA64DFR0_DEBUG_VER_MASK) +#define ID_AA64DFR0_DEBUG_VER_8 (0x6ULL << ID_AA64DFR0_DEBUG_VER_SHIFT) +#define ID_AA64DFR0_DEBUG_VER_8_VHE (0x7ULL << ID_AA64DFR0_DEBUG_VER_SHIFT) +#define ID_AA64DFR0_TRACE_VER_SHIFT 4 +#define ID_AA64DFR0_TRACE_VER_MASK (0xfULL << ID_AA64DFR0_TRACE_VER_SHIFT) +#define ID_AA64DFR0_TRACE_VER(x) ((x) & ID_AA64DFR0_TRACE_VER_MASK) +#define ID_AA64DFR0_TRACE_VER_NONE (0x0ULL << ID_AA64DFR0_TRACE_VER_SHIFT) +#define ID_AA64DFR0_TRACE_VER_IMPL (0x1ULL << ID_AA64DFR0_TRACE_VER_SHIFT) +#define ID_AA64DFR0_PMU_VER_SHIFT 8 +#define ID_AA64DFR0_PMU_VER_MASK (0xfULL << ID_AA64DFR0_PMU_VER_SHIFT) +#define ID_AA64DFR0_PMU_VER(x) ((x) & ID_AA64DFR0_PMU_VER_MASK) +#define ID_AA64DFR0_PMU_VER_NONE (0x0ULL << ID_AA64DFR0_PMU_VER_SHIFT) +#define ID_AA64DFR0_PMU_VER_3 (0x1ULL << ID_AA64DFR0_PMU_VER_SHIFT) +#define ID_AA64DFR0_PMU_VER_3_1 (0x4ULL << ID_AA64DFR0_PMU_VER_SHIFT) +#define ID_AA64DFR0_PMU_VER_IMPL (0xfULL << ID_AA64DFR0_PMU_VER_SHIFT) +#define ID_AA64DFR0_BRPS_SHIFT 12 +#define ID_AA64DFR0_BRPS_MASK (0xfULL << ID_AA64DFR0_BRPS_SHIFT) +#define ID_AA64DFR0_BRPS(x) \ + ((((x) >> ID_AA64DFR0_BRPS_SHIFT) & 0xf) + 1) +#define ID_AA64DFR0_WRPS_SHIFT 20 +#define ID_AA64DFR0_WRPS_MASK (0xfULL << ID_AA64DFR0_WRPS_SHIFT) +#define ID_AA64DFR0_WRPS(x) \ + ((((x) >> ID_AA64DFR0_WRPS_SHIFT) & 0xf) + 1) +#define ID_AA64DFR0_CTX_CMPS_SHIFT 28 +#define ID_AA64DFR0_CTX_CMPS_MASK (0xfULL << ID_AA64DFR0_CTX_CMPS_SHIFT) +#define ID_AA64DFR0_CTX_CMPS(x) \ + ((((x) >> ID_AA64DFR0_CTX_CMPS_SHIFT) & 0xf) + 1) + +/* ID_AA64ISAR0_EL1 */ +#define ID_AA64ISAR0_MASK 0xfffffffff0fffff0ULL +#define ID_AA64ISAR0_AES_SHIFT 4 +#define ID_AA64ISAR0_AES_MASK (0xfULL << ID_AA64ISAR0_AES_SHIFT) +#define ID_AA64ISAR0_AES(x) ((x) & ID_AA64ISAR0_AES_MASK) +#define ID_AA64ISAR0_AES_NONE (0x0ULL << ID_AA64ISAR0_AES_SHIFT) +#define ID_AA64ISAR0_AES_BASE (0x1ULL << ID_AA64ISAR0_AES_SHIFT) +#define ID_AA64ISAR0_AES_PMULL (0x2ULL << ID_AA64ISAR0_AES_SHIFT) +#define ID_AA64ISAR0_SHA1_SHIFT 8 +#define ID_AA64ISAR0_SHA1_MASK (0xfULL << ID_AA64ISAR0_SHA1_SHIFT) +#define ID_AA64ISAR0_SHA1(x) ((x) & ID_AA64ISAR0_SHA1_MASK) +#define ID_AA64ISAR0_SHA1_NONE (0x0ULL << ID_AA64ISAR0_SHA1_SHIFT) +#define ID_AA64ISAR0_SHA1_BASE (0x1ULL << ID_AA64ISAR0_SHA1_SHIFT) +#define ID_AA64ISAR0_SHA2_SHIFT 12 +#define ID_AA64ISAR0_SHA2_MASK (0xfULL << ID_AA64ISAR0_SHA2_SHIFT) +#define ID_AA64ISAR0_SHA2(x) ((x) & ID_AA64ISAR0_SHA2_MASK) +#define ID_AA64ISAR0_SHA2_NONE (0x0ULL << ID_AA64ISAR0_SHA2_SHIFT) +#define ID_AA64ISAR0_SHA2_BASE (0x1ULL << ID_AA64ISAR0_SHA2_SHIFT) +#define ID_AA64ISAR0_SHA2_512 (0x2ULL << ID_AA64ISAR0_SHA2_SHIFT) +#define ID_AA64ISAR0_CRC32_SHIFT 16 +#define ID_AA64ISAR0_CRC32_MASK (0xfULL << ID_AA64ISAR0_CRC32_SHIFT) +#define ID_AA64ISAR0_CRC32(x) ((x) & ID_AA64ISAR0_CRC32_MASK) +#define ID_AA64ISAR0_CRC32_NONE (0x0ULL << ID_AA64ISAR0_CRC32_SHIFT) +#define ID_AA64ISAR0_CRC32_BASE (0x1ULL << ID_AA64ISAR0_CRC32_SHIFT) +#define ID_AA64ISAR0_ATOMIC_SHIFT 20 +#define ID_AA64ISAR0_ATOMIC_MASK (0xfULL << ID_AA64ISAR0_ATOMIC_SHIFT) +#define ID_AA64ISAR0_ATOMIC(x) ((x) & ID_AA64ISAR0_ATOMIC_MASK) +#define ID_AA64ISAR0_ATOMIC_NONE (0x0ULL << ID_AA64ISAR0_ATOMIC_SHIFT) +#define ID_AA64ISAR0_ATOMIC_IMPL (0x2ULL << ID_AA64ISAR0_ATOMIC_SHIFT) +#define ID_AA64ISAR0_RDM_SHIFT 28 +#define ID_AA64ISAR0_RDM_MASK (0xfULL << ID_AA64ISAR0_RDM_SHIFT) +#define ID_AA64ISAR0_RDM(x) ((x) & ID_AA64ISAR0_RDM_MASK) +#define ID_AA64ISAR0_RDM_NONE (0x0ULL << ID_AA64ISAR0_RDM_SHIFT) +#define ID_AA64ISAR0_RDM_IMPL (0x1ULL << ID_AA64ISAR0_RDM_SHIFT) +#define ID_AA64ISAR0_SHA3_SHIFT 32 +#define ID_AA64ISAR0_SHA3_MASK (0xfULL << ID_AA64ISAR0_SHA3_SHIFT) +#define ID_AA64ISAR0_SHA3(x) ((x) & ID_AA64ISAR0_SHA3_MASK) +#define ID_AA64ISAR0_SHA3_NONE (0x0ULL << ID_AA64ISAR0_SHA3_SHIFT) +#define ID_AA64ISAR0_SHA3_IMPL (0x1ULL << ID_AA64ISAR0_SHA3_SHIFT) +#define ID_AA64ISAR0_SM3_SHIFT 36 +#define ID_AA64ISAR0_SM3_MASK (0xfULL << ID_AA64ISAR0_SM3_SHIFT) +#define ID_AA64ISAR0_SM3(x) ((x) & ID_AA64ISAR0_SM3_MASK) +#define ID_AA64ISAR0_SM3_NONE (0x0ULL << ID_AA64ISAR0_SM3_SHIFT) +#define ID_AA64ISAR0_SM3_IMPL (0x1ULL << ID_AA64ISAR0_SM3_SHIFT) +#define ID_AA64ISAR0_SM4_SHIFT 40 +#define ID_AA64ISAR0_SM4_MASK (0xfULL << ID_AA64ISAR0_SM4_SHIFT) +#define ID_AA64ISAR0_SM4(x) ((x) & ID_AA64ISAR0_SM4_MASK) +#define ID_AA64ISAR0_SM4_NONE (0x0ULL << ID_AA64ISAR0_SM4_SHIFT) +#define ID_AA64ISAR0_SM4_IMPL (0x1ULL << ID_AA64ISAR0_SM4_SHIFT) +#define ID_AA64ISAR0_DP_SHIFT 44 +#define ID_AA64ISAR0_DP_MASK (0xfULL << ID_AA64ISAR0_DP_SHIFT) +#define ID_AA64ISAR0_DP(x) ((x) & ID_AA64ISAR0_DP_MASK) +#define ID_AA64ISAR0_DP_NONE (0x0ULL << ID_AA64ISAR0_DP_SHIFT) +#define ID_AA64ISAR0_DP_IMPL (0x1ULL << ID_AA64ISAR0_DP_SHIFT) +#define ID_AA64ISAR0_FHM_SHIFT 48 +#define ID_AA64ISAR0_FHM_MASK (0xfULL << ID_AA64ISAR0_FHM_SHIFT) +#define ID_AA64ISAR0_FHM(x) ((x) & ID_AA64ISAR0_FHM_MASK) +#define ID_AA64ISAR0_FHM_NONE (0x0ULL << ID_AA64ISAR0_FHM_SHIFT) +#define ID_AA64ISAR0_FHM_IMPL (0x1ULL << ID_AA64ISAR0_FHM_SHIFT) +#define ID_AA64ISAR0_TS_SHIFT 52 +#define ID_AA64ISAR0_TS_MASK (0xfULL << ID_AA64ISAR0_TS_SHIFT) +#define ID_AA64ISAR0_TS(x) ((x) & ID_AA64ISAR0_TS_MASK) +#define ID_AA64ISAR0_TS_NONE (0x0ULL << ID_AA64ISAR0_TS_SHIFT) +#define ID_AA64ISAR0_TS_BASE (0x1ULL << ID_AA64ISAR0_TS_SHIFT) +#define ID_AA64ISAR0_TS_AXFLAG (0x2ULL << ID_AA64ISAR0_TS_SHIFT) +#define ID_AA64ISAR0_TLB_SHIFT 56 +#define ID_AA64ISAR0_TLB_MASK (0xfULL << ID_AA64ISAR0_TLB_SHIFT) +#define ID_AA64ISAR0_TLB(x) ((x) & ID_AA64ISAR0_TLB_MASK) +#define ID_AA64ISAR0_TLB_NONE (0x0ULL << ID_AA64ISAR0_TLB_SHIFT) +#define ID_AA64ISAR0_TLB_IOS (0x1ULL << ID_AA64ISAR0_TLB_SHIFT) +#define ID_AA64ISAR0_TLB_IRANGE (0x2ULL << ID_AA64ISAR0_TLB_SHIFT) +#define ID_AA64ISAR0_RNDR_SHIFT 60 +#define ID_AA64ISAR0_RNDR_MASK (0xfULL << ID_AA64ISAR0_RNDR_SHIFT) +#define ID_AA64ISAR0_RNDR(x) ((x) & ID_AA64ISAR0_RNDR_MASK) +#define ID_AA64ISAR0_RNDR_NONE (0x0ULL << ID_AA64ISAR0_RNDR_SHIFT) +#define ID_AA64ISAR0_RNDR_IMPL (0x1ULL << ID_AA64ISAR0_RNDR_SHIFT) + +/* ID_AA64ISAR1_EL1 */ +#define ID_AA64ISAR1_MASK 0xffffffffffffffffULL +#define ID_AA64ISAR1_DPB_SHIFT 0 +#define ID_AA64ISAR1_DPB_MASK (0xfULL << ID_AA64ISAR1_DPB_SHIFT) +#define ID_AA64ISAR1_DPB(x) ((x) & ID_AA64ISAR1_DPB_MASK) +#define ID_AA64ISAR1_DPB_NONE (0x0ULL << ID_AA64ISAR1_DPB_SHIFT) +#define ID_AA64ISAR1_DPB_IMPL (0x1ULL << ID_AA64ISAR1_DPB_SHIFT) +#define ID_AA64ISAR1_DPB_DCCVADP (0x2ULL << ID_AA64ISAR1_DPB_SHIFT) +#define ID_AA64ISAR1_APA_SHIFT 4 +#define ID_AA64ISAR1_APA_MASK (0xfULL << ID_AA64ISAR1_APA_SHIFT) +#define ID_AA64ISAR1_APA(x) ((x) & ID_AA64ISAR1_APA_MASK) +#define ID_AA64ISAR1_APA_NONE (0x0ULL << ID_AA64ISAR1_APA_SHIFT) +#define ID_AA64ISAR1_APA_PAC (0x1ULL << ID_AA64ISAR1_APA_SHIFT) +#define ID_AA64ISAR1_APA_EPAC (0x2ULL << ID_AA64ISAR1_APA_SHIFT) +#define ID_AA64ISAR1_APA_EPAC2 (0x3ULL << ID_AA64ISAR1_APA_SHIFT) +#define ID_AA64ISAR1_APA_FPAC (0x4ULL << ID_AA64ISAR1_APA_SHIFT) +#define ID_AA64ISAR1_APA_FPAC_COMBINED (0x5ULL << ID_AA64ISAR1_APA_SHIFT) +#define ID_AA64ISAR1_API_SHIFT 8 +#define ID_AA64ISAR1_API_MASK (0xfULL << ID_AA64ISAR1_API_SHIFT) +#define ID_AA64ISAR1_API(x) ((x) & ID_AA64ISAR1_API_MASK) +#define ID_AA64ISAR1_API_NONE (0x0ULL << ID_AA64ISAR1_API_SHIFT) +#define ID_AA64ISAR1_API_PAC (0x1ULL << ID_AA64ISAR1_API_SHIFT) +#define ID_AA64ISAR1_API_EPAC (0x2ULL << ID_AA64ISAR1_API_SHIFT) +#define ID_AA64ISAR1_API_EPAC2 (0x3ULL << ID_AA64ISAR1_API_SHIFT) +#define ID_AA64ISAR1_API_FPAC (0x4ULL << ID_AA64ISAR1_API_SHIFT) +#define ID_AA64ISAR1_API_FPAC_COMBINED (0x5ULL << ID_AA64ISAR1_API_SHIFT) +#define ID_AA64ISAR1_JSCVT_SHIFT 12 +#define ID_AA64ISAR1_JSCVT_MASK (0xfULL << ID_AA64ISAR1_JSCVT_SHIFT) +#define ID_AA64ISAR1_JSCVT(x) ((x) & ID_AA64ISAR1_JSCVT_MASK) +#define ID_AA64ISAR1_JSCVT_NONE (0x0ULL << ID_AA64ISAR1_JSCVT_SHIFT) +#define ID_AA64ISAR1_JSCVT_IMPL (0x1ULL << ID_AA64ISAR1_JSCVT_SHIFT) +#define ID_AA64ISAR1_FCMA_SHIFT 16 +#define ID_AA64ISAR1_FCMA_MASK (0xfULL << ID_AA64ISAR1_FCMA_SHIFT) +#define ID_AA64ISAR1_FCMA(x) ((x) & ID_AA64ISAR1_FCMA_MASK) +#define ID_AA64ISAR1_FCMA_NONE (0x0ULL << ID_AA64ISAR1_FCMA_SHIFT) +#define ID_AA64ISAR1_FCMA_IMPL (0x1ULL << ID_AA64ISAR1_FCMA_SHIFT) +#define ID_AA64ISAR1_LRCPC_SHIFT 20 +#define ID_AA64ISAR1_LRCPC_MASK (0xfULL << ID_AA64ISAR1_LRCPC_SHIFT) +#define ID_AA64ISAR1_LRCPC(x) ((x) & ID_AA64ISAR1_LRCPC_MASK) +#define ID_AA64ISAR1_LRCPC_NONE (0x0ULL << ID_AA64ISAR1_LRCPC_SHIFT) +#define ID_AA64ISAR1_LRCPC_BASE (0x1ULL << ID_AA64ISAR1_LRCPC_SHIFT) +#define ID_AA64ISAR1_LRCPC_LDAPUR (0x2ULL << ID_AA64ISAR1_LRCPC_SHIFT) +#define ID_AA64ISAR1_GPA_SHIFT 24 +#define ID_AA64ISAR1_GPA_MASK (0xfULL << ID_AA64ISAR1_GPA_SHIFT) +#define ID_AA64ISAR1_GPA(x) ((x) & ID_AA64ISAR1_GPA_MASK) +#define ID_AA64ISAR1_GPA_NONE (0x0ULL << ID_AA64ISAR1_GPA_SHIFT) +#define ID_AA64ISAR1_GPA_IMPL (0x1ULL << ID_AA64ISAR1_GPA_SHIFT) +#define ID_AA64ISAR1_GPI_SHIFT 28 +#define ID_AA64ISAR1_GPI_MASK (0xfULL << ID_AA64ISAR1_GPI_SHIFT) +#define ID_AA64ISAR1_GPI(x) ((x) & ID_AA64ISAR1_GPI_MASK) +#define ID_AA64ISAR1_GPI_NONE (0x0ULL << ID_AA64ISAR1_GPI_SHIFT) +#define ID_AA64ISAR1_GPI_IMPL (0x1ULL << ID_AA64ISAR1_GPI_SHIFT) +#define ID_AA64ISAR1_FRINTTS_SHIFT 32 +#define ID_AA64ISAR1_FRINTTS_MASK (0xfULL << ID_AA64ISAR1_FRINTTS_SHIFT) +#define ID_AA64ISAR1_FRINTTS(x) ((x) & ID_AA64ISAR1_FRINTTS_MASK) +#define ID_AA64ISAR1_FRINTTS_NONE (0x0ULL << ID_AA64ISAR1_FRINTTS_SHIFT) +#define ID_AA64ISAR1_FRINTTS_IMPL (0x1ULL << ID_AA64ISAR1_FRINTTS_SHIFT) +#define ID_AA64ISAR1_SB_SHIFT 36 +#define ID_AA64ISAR1_SB_MASK (0xfULL << ID_AA64ISAR1_SB_SHIFT) +#define ID_AA64ISAR1_SB(x) ((x) & ID_AA64ISAR1_SB_MASK) +#define ID_AA64ISAR1_SB_NONE (0x0ULL << ID_AA64ISAR1_SB_SHIFT) +#define ID_AA64ISAR1_SB_IMPL (0x1ULL << ID_AA64ISAR1_SB_SHIFT) +#define ID_AA64ISAR1_SPECRES_SHIFT 40 +#define ID_AA64ISAR1_SPECRES_MASK (0xfULL << ID_AA64ISAR1_SPECRES_SHIFT) +#define ID_AA64ISAR1_SPECRES(x) ((x) & ID_AA64ISAR1_SPECRES_MASK) +#define ID_AA64ISAR1_SPECRES_NONE (0x0ULL << ID_AA64ISAR1_SPECRES_SHIFT) +#define ID_AA64ISAR1_SPECRES_IMPL (0x1ULL << ID_AA64ISAR1_SPECRES_SHIFT) +#define ID_AA64ISAR1_BF16_SHIFT 44 +#define ID_AA64ISAR1_BF16_MASK (0xfULL << ID_AA64ISAR1_BF16_SHIFT) +#define ID_AA64ISAR1_BF16(x) ((x) & ID_AA64ISAR1_BF16_MASK) +#define ID_AA64ISAR1_BF16_NONE (0x0ULL << ID_AA64ISAR1_BF16_SHIFT) +#define ID_AA64ISAR1_BF16_BASE (0x1ULL << ID_AA64ISAR1_BF16_SHIFT) +#define ID_AA64ISAR1_BF16_EBF (0x2ULL << ID_AA64ISAR1_BF16_SHIFT) +#define ID_AA64ISAR1_DGH_SHIFT 48 +#define ID_AA64ISAR1_DGH_MASK (0xfULL << ID_AA64ISAR1_DGH_SHIFT) +#define ID_AA64ISAR1_DGH(x) ((x) & ID_AA64ISAR1_DGH_MASK) +#define ID_AA64ISAR1_DGH_NONE (0x0ULL << ID_AA64ISAR1_DGH_SHIFT) +#define ID_AA64ISAR1_DGH_IMPL (0x1ULL << ID_AA64ISAR1_DGH_SHIFT) +#define ID_AA64ISAR1_I8MM_SHIFT 52 +#define ID_AA64ISAR1_I8MM_MASK (0xfULL << ID_AA64ISAR1_I8MM_SHIFT) +#define ID_AA64ISAR1_I8MM(x) ((x) & ID_AA64ISAR1_I8MM_MASK) +#define ID_AA64ISAR1_I8MM_NONE (0x0ULL << ID_AA64ISAR1_I8MM_SHIFT) +#define ID_AA64ISAR1_I8MM_IMPL (0x1ULL << ID_AA64ISAR1_I8MM_SHIFT) +#define ID_AA64ISAR1_XS_SHIFT 56 +#define ID_AA64ISAR1_XS_MASK (0xfULL << ID_AA64ISAR1_XS_SHIFT) +#define ID_AA64ISAR1_XS(x) ((x) & ID_AA64ISAR1_XS_MASK) +#define ID_AA64ISAR1_XS_NONE (0x0ULL << ID_AA64ISAR1_XS_SHIFT) +#define ID_AA64ISAR1_XS_IMPL (0x1ULL << ID_AA64ISAR1_XS_SHIFT) +#define ID_AA64ISAR1_LS64_SHIFT 60 +#define ID_AA64ISAR1_LS64_MASK (0xfULL << ID_AA64ISAR1_LS64_SHIFT) +#define ID_AA64ISAR1_LS64(x) ((x) & ID_AA64ISAR1_LS64_MASK) +#define ID_AA64ISAR1_LS64_NONE (0x0ULL << ID_AA64ISAR1_LS64_SHIFT) +#define ID_AA64ISAR1_LS64_BASE (0x1ULL << ID_AA64ISAR1_LS64_SHIFT) +#define ID_AA64ISAR1_LS64_V (0x2ULL << ID_AA64ISAR1_LS64_SHIFT) +#define ID_AA64ISAR1_LS64_ACCDATA (0x3ULL << ID_AA64ISAR1_LS64_SHIFT) + +/* ID_AA64ISAR2_EL1 */ +#define ID_AA64ISAR2_MASK 0x00ff0000f0ffffffULL +#define ID_AA64ISAR2_WFXT_SHIFT 0 +#define ID_AA64ISAR2_WFXT_MASK (0xfULL << ID_AA64ISAR2_WFXT_SHIFT) +#define ID_AA64ISAR2_WFXT(x) ((x) & ID_AA64ISAR2_WFXT_MASK) +#define ID_AA64ISAR2_WFXT_NONE (0x0ULL << ID_AA64ISAR2_WFXT_SHIFT) +#define ID_AA64ISAR2_WFXT_IMPL (0x2ULL << ID_AA64ISAR2_WFXT_SHIFT) +#define ID_AA64ISAR2_RPRES_SHIFT 4 +#define ID_AA64ISAR2_RPRES_MASK (0xfULL << ID_AA64ISAR2_RPRES_SHIFT) +#define ID_AA64ISAR2_RPRES(x) ((x) & ID_AA64ISAR2_RPRES_MASK) +#define ID_AA64ISAR2_RPRES_NONE (0x0ULL << ID_AA64ISAR2_RPRES_SHIFT) +#define ID_AA64ISAR2_RPRES_IMPL (0x1ULL << ID_AA64ISAR2_RPRES_SHIFT) +#define ID_AA64ISAR2_GPA3_SHIFT 8 +#define ID_AA64ISAR2_GPA3_WIDTH 4 +#define ID_AA64ISAR2_GPA3_MASK (0xfULL << ID_AA64ISAR2_GPA3_SHIFT) +#define ID_AA64ISAR2_GPA3(x) ((x) & ID_AA64ISAR2_GPA3_MASK) +#define ID_AA64ISAR2_GPA3_NONE (0x0ULL << ID_AA64ISAR2_GPA3_SHIFT) +#define ID_AA64ISAR2_GPA3_IMPL (0x1ULL << ID_AA64ISAR2_GPA3_SHIFT) +#define ID_AA64ISAR2_APA3_SHIFT 12 +#define ID_AA64ISAR2_APA3_WIDTH 4 +#define ID_AA64ISAR2_APA3_MASK (0xfULL << ID_AA64ISAR2_APA3_SHIFT) +#define ID_AA64ISAR2_APA3(x) ((x) & ID_AA64ISAR2_APA3_MASK) +#define ID_AA64ISAR2_APA3_NONE (0x0ULL << ID_AA64ISAR2_APA3_SHIFT) +#define ID_AA64ISAR2_APA3_PAC (0x1ULL << ID_AA64ISAR2_APA3_SHIFT) +#define ID_AA64ISAR2_APA3_EPAC (0x2ULL << ID_AA64ISAR2_APA3_SHIFT) +#define ID_AA64ISAR2_APA3_EPAC2 (0x3ULL << ID_AA64ISAR2_APA3_SHIFT) +#define ID_AA64ISAR2_APA3_FPAC (0x4ULL << ID_AA64ISAR2_APA3_SHIFT) +#define ID_AA64ISAR2_APA3_FPAC_COMBINED (0x5ULL << ID_AA64ISAR2_APA3_SHIFT) +#define ID_AA64ISAR2_MOPS_SHIFT 16 +#define ID_AA64ISAR2_MOPS_MASK (0xfULL << ID_AA64ISAR2_MOPS_SHIFT) +#define ID_AA64ISAR2_MOPS(x) ((x) & ID_AA64ISAR2_MOPS_MASK) +#define ID_AA64ISAR2_MOPS_NONE (0x0ULL << ID_AA64ISAR2_MOPS_SHIFT) +#define ID_AA64ISAR2_MOPS_IMPL (0x1ULL << ID_AA64ISAR2_MOPS_SHIFT) +#define ID_AA64ISAR2_BC_SHIFT 20 +#define ID_AA64ISAR2_BC_MASK (0xfULL << ID_AA64ISAR2_BC_SHIFT) +#define ID_AA64ISAR2_BC(x) ((x) & ID_AA64ISAR2_BC_MASK) +#define ID_AA64ISAR2_BC_NONE (0x0ULL << ID_AA64ISAR2_BC_SHIFT) +#define ID_AA64ISAR2_BC_IMPL (0x1ULL << ID_AA64ISAR2_BC_SHIFT) +#define ID_AA64ISAR2_CLRBHB_SHIFT 28 +#define ID_AA64ISAR2_CLRBHB_MASK (0xfULL << ID_AA64ISAR2_CLRBHB_SHIFT) +#define ID_AA64ISAR2_CLRBHB(x) ((x) & ID_AA64ISAR2_CLRBHB_MASK) +#define ID_AA64ISAR2_CLRBHB_NONE (0x0ULL << ID_AA64ISAR2_CLRBHB_SHIFT) +#define ID_AA64ISAR2_CLRBHB_IMPL (0x1ULL << ID_AA64ISAR2_CLRBHB_SHIFT) +#define ID_AA64ISAR2_RPRFM_SHIFT 48 +#define ID_AA64ISAR2_RPRFM_MASK (0xfULL << ID_AA64ISAR2_RPRFM_SHIFT) +#define ID_AA64ISAR2_RPRFM(x) ((x) & ID_AA64ISAR2_RPRFM_MASK) +#define ID_AA64ISAR2_RPRFM_NONE (0x0ULL << ID_AA64ISAR2_RPRFM_SHIFT) +#define ID_AA64ISAR2_RPRFM_IMPL (0x1ULL << ID_AA64ISAR2_RPRFM_SHIFT) +#define ID_AA64ISAR2_CSSC_SHIFT 52 +#define ID_AA64ISAR2_CSSC_MASK (0xfULL << ID_AA64ISAR2_CSSC_SHIFT) +#define ID_AA64ISAR2_CSSC(x) ((x) & ID_AA64ISAR2_CSSC_MASK) +#define ID_AA64ISAR2_CSSC_NONE (0x0ULL << ID_AA64ISAR2_CSSC_SHIFT) +#define ID_AA64ISAR2_CSSC_IMPL (0x1ULL << ID_AA64ISAR2_CSSC_SHIFT) + +/* ID_AA64MMFR0_EL1 */ +#define ID_AA64MMFR0_MASK 0xf0000000ffffffffULL +#define ID_AA64MMFR0_PA_RANGE_SHIFT 0 +#define ID_AA64MMFR0_PA_RANGE_MASK (0xfULL << ID_AA64MMFR0_PA_RANGE_SHIFT) +#define ID_AA64MMFR0_PA_RANGE(x) ((x) & ID_AA64MMFR0_PA_RANGE_MASK) +#define ID_AA64MMFR0_PA_RANGE_4G (0x0ULL << ID_AA64MMFR0_PA_RANGE_SHIFT) +#define ID_AA64MMFR0_PA_RANGE_64G (0x1ULL << ID_AA64MMFR0_PA_RANGE_SHIFT) +#define ID_AA64MMFR0_PA_RANGE_1T (0x2ULL << ID_AA64MMFR0_PA_RANGE_SHIFT) +#define ID_AA64MMFR0_PA_RANGE_4T (0x3ULL << ID_AA64MMFR0_PA_RANGE_SHIFT) +#define ID_AA64MMFR0_PA_RANGE_16T (0x4ULL << ID_AA64MMFR0_PA_RANGE_SHIFT) +#define ID_AA64MMFR0_PA_RANGE_256T (0x5ULL << ID_AA64MMFR0_PA_RANGE_SHIFT) +#define ID_AA64MMFR0_ASID_BITS_SHIFT 4 +#define ID_AA64MMFR0_ASID_BITS_MASK (0xfULL << ID_AA64MMFR0_ASID_BITS_SHIFT) +#define ID_AA64MMFR0_ASID_BITS(x) ((x) & ID_AA64MMFR0_ASID_BITS_MASK) +#define ID_AA64MMFR0_ASID_BITS_8 (0x0ULL << ID_AA64MMFR0_ASID_BITS_SHIFT) +#define ID_AA64MMFR0_ASID_BITS_16 (0x2ULL << ID_AA64MMFR0_ASID_BITS_SHIFT) +#define ID_AA64MMFR0_BIGEND_SHIFT 8 +#define ID_AA64MMFR0_BIGEND_MASK (0xfULL << ID_AA64MMFR0_BIGEND_SHIFT) +#define ID_AA64MMFR0_BIGEND(x) ((x) & ID_AA64MMFR0_BIGEND_MASK) +#define ID_AA64MMFR0_BIGEND_FIXED (0x0ULL << ID_AA64MMFR0_BIGEND_SHIFT) +#define ID_AA64MMFR0_BIGEND_MIXED (0x1ULL << ID_AA64MMFR0_BIGEND_SHIFT) +#define ID_AA64MMFR0_S_NS_MEM_SHIFT 12 +#define ID_AA64MMFR0_S_NS_MEM_MASK (0xfULL << ID_AA64MMFR0_S_NS_MEM_SHIFT) +#define ID_AA64MMFR0_S_NS_MEM(x) ((x) & ID_AA64MMFR0_S_NS_MEM_MASK) +#define ID_AA64MMFR0_S_NS_MEM_NONE (0x0ULL << ID_AA64MMFR0_S_NS_MEM_SHIFT) +#define ID_AA64MMFR0_S_NS_MEM_DISTINCT (0x1ULL << ID_AA64MMFR0_S_NS_MEM_SHIFT) +#define ID_AA64MMFR0_BIGEND_EL0_SHIFT 16 +#define ID_AA64MMFR0_BIGEND_EL0_MASK (0xfULL << ID_AA64MMFR0_BIGEND_EL0_SHIFT) +#define ID_AA64MMFR0_BIGEND_EL0(x) ((x) & ID_AA64MMFR0_BIGEND_EL0_MASK) +#define ID_AA64MMFR0_BIGEND_EL0_FIXED (0x0ULL << ID_AA64MMFR0_BIGEND_EL0_SHIFT) +#define ID_AA64MMFR0_BIGEND_EL0_MIXED (0x1ULL << ID_AA64MMFR0_BIGEND_EL0_SHIFT) +#define ID_AA64MMFR0_TGRAN16_SHIFT 20 +#define ID_AA64MMFR0_TGRAN16_MASK (0xfULL << ID_AA64MMFR0_TGRAN16_SHIFT) +#define ID_AA64MMFR0_TGRAN16(x) ((x) & ID_AA64MMFR0_TGRAN16_MASK) +#define ID_AA64MMFR0_TGRAN16_NONE (0x0ULL << ID_AA64MMFR0_TGRAN16_SHIFT) +#define ID_AA64MMFR0_TGRAN16_IMPL (0x1ULL << ID_AA64MMFR0_TGRAN16_SHIFT) +#define ID_AA64MMFR0_TGRAN64_SHIFT 24 +#define ID_AA64MMFR0_TGRAN64_MASK (0xfULL << ID_AA64MMFR0_TGRAN64_SHIFT) +#define ID_AA64MMFR0_TGRAN64(x) ((x) & ID_AA64MMFR0_TGRAN64_MASK) +#define ID_AA64MMFR0_TGRAN64_IMPL (0x0ULL << ID_AA64MMFR0_TGRAN64_SHIFT) +#define ID_AA64MMFR0_TGRAN64_NONE (0xfULL << ID_AA64MMFR0_TGRAN64_SHIFT) +#define ID_AA64MMFR0_TGRAN4_SHIFT 28 +#define ID_AA64MMFR0_TGRAN4_MASK (0xfULL << ID_AA64MMFR0_TGRAN4_SHIFT) +#define ID_AA64MMFR0_TGRAN4(x) ((x) & ID_AA64MMFR0_TGRAN4_MASK) +#define ID_AA64MMFR0_TGRAN4_IMPL (0x0ULL << ID_AA64MMFR0_TGRAN4_SHIFT) +#define ID_AA64MMFR0_TGRAN4_NONE (0xfULL << ID_AA64MMFR0_TGRAN4_SHIFT) +#define ID_AA64MMFR0_ECV_SHIFT 60 +#define ID_AA64MMFR0_ECV_MASK (0xfULL << ID_AA64MMFR0_ECV_SHIFT) +#define ID_AA64MMFR0_ECV(x) ((x) & ID_AA64MMFR0_ECV_MASK) +#define ID_AA64MMFR0_ECV_NONE (0x0ULL << ID_AA64MMFR0_ECV_SHIFT) +#define ID_AA64MMFR0_ECV_IMPL (0x1ULL << ID_AA64MMFR0_ECV_SHIFT) +#define ID_AA64MMFR0_ECV_CNTHCTL (0x2ULL << ID_AA64MMFR0_ECV_SHIFT) + +/* ID_AA64MMFR1_EL1 */ +#define ID_AA64MMFR1_MASK 0xf000f000ffffffffULL +#define ID_AA64MMFR1_HAFDBS_SHIFT 0 +#define ID_AA64MMFR1_HAFDBS_MASK (0xfULL << ID_AA64MMFR1_HAFDBS_SHIFT) +#define ID_AA64MMFR1_HAFDBS(x) ((x) & ID_AA64MMFR1_HAFDBS_MASK) +#define ID_AA64MMFR1_HAFDBS_NONE (0x0ULL << ID_AA64MMFR1_HAFDBS_SHIFT) +#define ID_AA64MMFR1_HAFDBS_AF (0x1ULL << ID_AA64MMFR1_HAFDBS_SHIFT) +#define ID_AA64MMFR1_HAFDBS_AF_DBS (0x2ULL << ID_AA64MMFR1_HAFDBS_SHIFT) +#define ID_AA64MMFR1_VMIDBITS_SHIFT 4 +#define ID_AA64MMFR1_VMIDBITS_MASK (0xfULL << ID_AA64MMFR1_VMIDBITS_SHIFT) +#define ID_AA64MMFR1_VMIDBITS(x) ((x) & ID_AA64MMFR1_VMIDBITS_MASK) +#define ID_AA64MMFR1_VMIDBITS_8 (0x0ULL << ID_AA64MMFR1_VMIDBITS_SHIFT) +#define ID_AA64MMFR1_VMIDBITS_16 (0x2ULL << ID_AA64MMFR1_VMIDBITS_SHIFT) +#define ID_AA64MMFR1_VH_SHIFT 8 +#define ID_AA64MMFR1_VH_MASK (0xfULL << ID_AA64MMFR1_VH_SHIFT) +#define ID_AA64MMFR1_VH(x) ((x) & ID_AA64MMFR1_VH_MASK) +#define ID_AA64MMFR1_VH_NONE (0x0ULL << ID_AA64MMFR1_VH_SHIFT) +#define ID_AA64MMFR1_VH_IMPL (0x1ULL << ID_AA64MMFR1_VH_SHIFT) +#define ID_AA64MMFR1_HPDS_SHIFT 12 +#define ID_AA64MMFR1_HPDS_MASK (0xfULL << ID_AA64MMFR1_HPDS_SHIFT) +#define ID_AA64MMFR1_HPDS(x) ((x) & ID_AA64MMFR1_HPDS_MASK) +#define ID_AA64MMFR1_HPDS_NONE (0x0ULL << ID_AA64MMFR1_HPDS_SHIFT) +#define ID_AA64MMFR1_HPDS_IMPL (0x1ULL << ID_AA64MMFR1_HPDS_SHIFT) +#define ID_AA64MMFR1_LO_SHIFT 16 +#define ID_AA64MMFR1_LO_MASK (0xfULL << ID_AA64MMFR1_LO_SHIFT) +#define ID_AA64MMFR1_LO(x) ((x) & ID_AA64MMFR1_LO_MASK) +#define ID_AA64MMFR1_LO_NONE (0x0ULL << ID_AA64MMFR1_LO_SHIFT) +#define ID_AA64MMFR1_LO_IMPL (0x1ULL << ID_AA64MMFR1_LO_SHIFT) +#define ID_AA64MMFR1_PAN_SHIFT 20 +#define ID_AA64MMFR1_PAN_MASK (0xfULL << ID_AA64MMFR1_PAN_SHIFT) +#define ID_AA64MMFR1_PAN(x) ((x) & ID_AA64MMFR1_PAN_MASK) +#define ID_AA64MMFR1_PAN_NONE (0x0ULL << ID_AA64MMFR1_PAN_SHIFT) +#define ID_AA64MMFR1_PAN_IMPL (0x1ULL << ID_AA64MMFR1_PAN_SHIFT) +#define ID_AA64MMFR1_PAN_ATS1E1 (0x2ULL << ID_AA64MMFR1_PAN_SHIFT) +#define ID_AA64MMFR1_PAN_EPAN (0x3ULL << ID_AA64MMFR1_PAN_SHIFT) +#define ID_AA64MMFR1_SPECSEI_SHIFT 24 +#define ID_AA64MMFR1_SPECSEI_MASK (0xfULL << ID_AA64MMFR1_SPECSEI_SHIFT) +#define ID_AA64MMFR1_SPECSEI(x) ((x) & ID_AA64MMFR1_SPECSEI_MASK) +#define ID_AA64MMFR1_SPECSEI_NONE (0x0ULL << ID_AA64MMFR1_SPECSEI_SHIFT) +#define ID_AA64MMFR1_SPECSEI_IMPL (0x1ULL << ID_AA64MMFR1_SPECSEI_SHIFT) +#define ID_AA64MMFR1_XNX_SHIFT 28 +#define ID_AA64MMFR1_XNX_MASK (0xfULL << ID_AA64MMFR1_XNX_SHIFT) +#define ID_AA64MMFR1_XNX(x) ((x) & ID_AA64MMFR1_XNX_MASK) +#define ID_AA64MMFR1_XNX_NONE (0x0ULL << ID_AA64MMFR1_XNX_SHIFT) +#define ID_AA64MMFR1_XNX_IMPL (0x1ULL << ID_AA64MMFR1_XNX_SHIFT) +#define ID_AA64MMFR1_AFP_SHIFT 44 +#define ID_AA64MMFR1_AFP_MASK (0xfULL << ID_AA64MMFR1_AFP_SHIFT) +#define ID_AA64MMFR1_AFP(x) ((x) & ID_AA64MMFR1_AFP_MASK) +#define ID_AA64MMFR1_AFP_NONE (0x0ULL << ID_AA64MMFR1_AFP_SHIFT) +#define ID_AA64MMFR1_AFP_IMPL (0x1ULL << ID_AA64MMFR1_AFP_SHIFT) +#define ID_AA64MMFR1_ECBHB_SHIFT 60 +#define ID_AA64MMFR1_ECBHB_MASK (0xfULL << ID_AA64MMFR1_ECBHB_SHIFT) +#define ID_AA64MMFR1_ECBHB(x) ((x) & ID_AA64MMFR1_ECBHB_MASK) +#define ID_AA64MMFR1_ECBHB_NONE (0x0ULL << ID_AA64MMFR1_ECBHB_SHIFT) +#define ID_AA64MMFR1_ECBHB_IMPL (0x1ULL << ID_AA64MMFR1_ECBHB_SHIFT) + +/* ID_AA64MMFR2_EL1 */ +#define ID_AA64MMFR2_MASK 0xffff0fffffffffffULL +#define ID_AA64MMFR2_CCIDX_SHIFT 20 +#define ID_AA64MMFR2_CCIDX_MASK (0xfULL << ID_AA64MMFR2_CCIDX_SHIFT) +#define ID_AA64MMFR2_CCIDX(x) ((x) & ID_AA64MMFR2_CCIDX_MASK) +#define ID_AA64MMFR2_CCIDX_IMPL (0x1ULL << ID_AA64MMFR2_CCIDX_SHIFT) +#define ID_AA64MMFR2_AT_SHIFT 32 +#define ID_AA64MMFR2_AT_MASK (0xfULL << ID_AA64MMFR2_AT_SHIFT) +#define ID_AA64MMFR2_AT(x) ((x) & ID_AA64MMFR2_AT_MASK) +#define ID_AA64MMFR2_AT_NONE (0x0ULL << ID_AA64MMFR2_AT_SHIFT) +#define ID_AA64MMFR2_AT_IMPL (0x1ULL << ID_AA64MMFR2_AT_SHIFT) +#define ID_AA64MMFR2_IDS_SHIFT 36 +#define ID_AA64MMFR2_IDS_MASK (0xfULL << ID_AA64MMFR2_IDS_SHIFT) +#define ID_AA64MMFR2_IDS(x) ((x) & ID_AA64MMFR2_IDS_MASK) +#define ID_AA64MMFR2_IDS_NONE (0x0ULL << ID_AA64MMFR2_IDS_SHIFT) +#define ID_AA64MMFR2_IDS_IMPL (0x1ULL << ID_AA64MMFR2_IDS_SHIFT) + +/* ID_AA64PFR0_EL1 */ +#define ID_AA64PFR0_MASK 0xff0fffffffffffffULL +#define ID_AA64PFR0_EL0_SHIFT 0 +#define ID_AA64PFR0_EL0_MASK (0xfULL << ID_AA64PFR0_EL0_SHIFT) +#define ID_AA64PFR0_EL0(x) ((x) & ID_AA64PFR0_EL0_MASK) +#define ID_AA64PFR0_EL0_64 (0x1ULL << ID_AA64PFR0_EL0_SHIFT) +#define ID_AA64PFR0_EL0_64_32 (0x2ULL << ID_AA64PFR0_EL0_SHIFT) +#define ID_AA64PFR0_EL1_SHIFT 4 +#define ID_AA64PFR0_EL1_MASK (0xfULL << ID_AA64PFR0_EL1_SHIFT) +#define ID_AA64PFR0_EL1(x) ((x) & ID_AA64PFR0_EL1_MASK) +#define ID_AA64PFR0_EL1_64 (0x1ULL << ID_AA64PFR0_EL1_SHIFT) +#define ID_AA64PFR0_EL1_64_32 (0x2ULL << ID_AA64PFR0_EL1_SHIFT) +#define ID_AA64PFR0_EL2_SHIFT 8 +#define ID_AA64PFR0_EL2_MASK (0xfULL << ID_AA64PFR0_EL2_SHIFT) +#define ID_AA64PFR0_EL2(x) ((x) & ID_AA64PFR0_EL2_MASK) +#define ID_AA64PFR0_EL2_NONE (0x0ULL << ID_AA64PFR0_EL2_SHIFT) +#define ID_AA64PFR0_EL2_64 (0x1ULL << ID_AA64PFR0_EL2_SHIFT) +#define ID_AA64PFR0_EL2_64_32 (0x2ULL << ID_AA64PFR0_EL2_SHIFT) +#define ID_AA64PFR0_EL3_SHIFT 12 +#define ID_AA64PFR0_EL3_MASK (0xfULL << ID_AA64PFR0_EL3_SHIFT) +#define ID_AA64PFR0_EL3(x) ((x) & ID_AA64PFR0_EL3_MASK) +#define ID_AA64PFR0_EL3_NONE (0x0ULL << ID_AA64PFR0_EL3_SHIFT) +#define ID_AA64PFR0_EL3_64 (0x1ULL << ID_AA64PFR0_EL3_SHIFT) +#define ID_AA64PFR0_EL3_64_32 (0x2ULL << ID_AA64PFR0_EL3_SHIFT) +#define ID_AA64PFR0_FP_SHIFT 16 +#define ID_AA64PFR0_FP_MASK (0xfULL << ID_AA64PFR0_FP_SHIFT) +#define ID_AA64PFR0_FP(x) ((x) & ID_AA64PFR0_FP_MASK) +#define ID_AA64PFR0_FP_IMPL (0x0ULL << ID_AA64PFR0_FP_SHIFT) +#define ID_AA64PFR0_FP_HP (0x1ULL << ID_AA64PFR0_FP_SHIFT) +#define ID_AA64PFR0_FP_NONE (0xfULL << ID_AA64PFR0_FP_SHIFT) +#define ID_AA64PFR0_ADV_SIMD_SHIFT 20 +#define ID_AA64PFR0_ADV_SIMD_MASK (0xfULL << ID_AA64PFR0_ADV_SIMD_SHIFT) +#define ID_AA64PFR0_ADV_SIMD(x) ((x) & ID_AA64PFR0_ADV_SIMD_MASK) +#define ID_AA64PFR0_ADV_SIMD_IMPL (0x0ULL << ID_AA64PFR0_ADV_SIMD_SHIFT) +#define ID_AA64PFR0_ADV_SIMD_HP (0x1ULL << ID_AA64PFR0_ADV_SIMD_SHIFT) +#define ID_AA64PFR0_ADV_SIMD_NONE (0xfULL << ID_AA64PFR0_ADV_SIMD_SHIFT) +#define ID_AA64PFR0_GIC_BITS 0x4 /* Number of bits in GIC field */ +#define ID_AA64PFR0_GIC_SHIFT 24 +#define ID_AA64PFR0_GIC_MASK (0xfULL << ID_AA64PFR0_GIC_SHIFT) +#define ID_AA64PFR0_GIC(x) ((x) & ID_AA64PFR0_GIC_MASK) +#define ID_AA64PFR0_GIC_CPUIF_NONE (0x0ULL << ID_AA64PFR0_GIC_SHIFT) +#define ID_AA64PFR0_GIC_CPUIF_EN (0x1ULL << ID_AA64PFR0_GIC_SHIFT) +#define ID_AA64PFR0_RAS_SHIFT 28 +#define ID_AA64PFR0_RAS_MASK (0xfULL << ID_AA64PFR0_RAS_SHIFT) +#define ID_AA64PFR0_RAS(x) ((x) & ID_AA64PFR0_RAS_MASK) +#define ID_AA64PFR0_RAS_NONE (0x0ULL << ID_AA64PFR0_RAS_SHIFT) +#define ID_AA64PFR0_RAS_IMPL (0x1ULL << ID_AA64PFR0_RAS_SHIFT) +#define ID_AA64PFR0_RAS_IMPL_V1P1 (0x2ULL << ID_AA64PFR0_RAS_SHIFT) +#define ID_AA64PFR0_SVE_SHIFT 32 +#define ID_AA64PFR0_SVE_MASK (0xfULL << ID_AA64PFR0_SVE_SHIFT) +#define ID_AA64PFR0_SVE(x) ((x) & ID_AA64PFR0_SVE_MASK) +#define ID_AA64PFR0_SVE_NONE (0x0ULL << ID_AA64PFR0_SVE_SHIFT) +#define ID_AA64PFR0_SVE_IMPL (0x1ULL << ID_AA64PFR0_SVE_SHIFT) +#define ID_AA64PFR0_SEL2_SHIFT 36 +#define ID_AA64PFR0_SEL2_MASK (0xfULL << ID_AA64PFR0_SEL2_SHIFT) +#define ID_AA64PFR0_SEL2(x) ((x) & ID_AA64PFR0_SEL2_MASK) +#define ID_AA64PFR0_SEL2_NONE (0x0ULL << ID_AA64PFR0_SEL2_SHIFT) +#define ID_AA64PFR0_SEL2_IMPL (0x1ULL << ID_AA64PFR0_SEL2_SHIFT) +#define ID_AA64PFR0_MPAM_SHIFT 40 +#define ID_AA64PFR0_MPAM_MASK (0xfULL << ID_AA64PFR0_MPAM_SHIFT) +#define ID_AA64PFR0_MPAM(x) ((x) & ID_AA64PFR0_MPAM_MASK) +#define ID_AA64PFR0_MPAM_NONE (0x0ULL << ID_AA64PFR0_MPAM_SHIFT) +#define ID_AA64PFR0_MPAM_IMPL (0x1ULL << ID_AA64PFR0_MPAM_SHIFT) +#define ID_AA64PFR0_AMU_SHIFT 44 +#define ID_AA64PFR0_AMU_MASK (0xfULL << ID_AA64PFR0_AMU_SHIFT) +#define ID_AA64PFR0_AMU(x) ((x) & ID_AA64PFR0_AMU_MASK) +#define ID_AA64PFR0_AMU_NONE (0x0ULL << ID_AA64PFR0_AMU_SHIFT) +#define ID_AA64PFR0_AMU_IMPL (0x1ULL << ID_AA64PFR0_AMU_SHIFT) +#define ID_AA64PFR0_AMU_IMPL_V1P1 (0x2ULL << ID_AA64PFR0_AMU_SHIFT) +#define ID_AA64PFR0_DIT_SHIFT 48 +#define ID_AA64PFR0_DIT_MASK (0xfULL << ID_AA64PFR0_DIT_SHIFT) +#define ID_AA64PFR0_DIT(x) ((x) & ID_AA64PFR0_DIT_MASK) +#define ID_AA64PFR0_DIT_UNKNOWN (0x0ULL << ID_AA64PFR0_DIT_SHIFT) +#define ID_AA64PFR0_DIT_IMPL (0x1ULL << ID_AA64PFR0_DIT_SHIFT) +#define ID_AA64PFR0_CSV2_SHIFT 56 +#define ID_AA64PFR0_CSV2_MASK (0xfULL << ID_AA64PFR0_CSV2_SHIFT) +#define ID_AA64PFR0_CSV2(x) ((x) & ID_AA64PFR0_CSV2_MASK) +#define ID_AA64PFR0_CSV2_UNKNOWN (0x0ULL << ID_AA64PFR0_CSV2_SHIFT) +#define ID_AA64PFR0_CSV2_IMPL (0x1ULL << ID_AA64PFR0_CSV2_SHIFT) +#define ID_AA64PFR0_CSV2_SCXT (0x2ULL << ID_AA64PFR0_CSV2_SHIFT) +#define ID_AA64PFR0_CSV2_HCXT (0x3ULL << ID_AA64PFR0_CSV2_SHIFT) +#define ID_AA64PFR0_CSV3_SHIFT 60 +#define ID_AA64PFR0_CSV3_MASK (0xfULL << ID_AA64PFR0_CSV3_SHIFT) +#define ID_AA64PFR0_CSV3(x) ((x) & ID_AA64PFR0_CSV3_MASK) +#define ID_AA64PFR0_CSV3_UNKNOWN (0x0ULL << ID_AA64PFR0_CSV3_SHIFT) +#define ID_AA64PFR0_CSV3_IMPL (0x1ULL << ID_AA64PFR0_CSV3_SHIFT) + +/* ID_AA64PFR1_EL1 */ +#define ID_AA64PFR1_MASK 0x000000000000ffffULL +#define ID_AA64PFR1_BT_SHIFT 0 +#define ID_AA64PFR1_BT_MASK (0xfULL << ID_AA64PFR1_BT_SHIFT) +#define ID_AA64PFR1_BT(x) ((x) & ID_AA64PFR1_BT_MASK) +#define ID_AA64PFR1_BT_NONE (0x0ULL << ID_AA64PFR1_BT_SHIFT) +#define ID_AA64PFR1_BT_IMPL (0x1ULL << ID_AA64PFR1_BT_SHIFT) +#define ID_AA64PFR1_SSBS_SHIFT 4 +#define ID_AA64PFR1_SSBS_MASK (0xfULL << ID_AA64PFR1_SSBS_SHIFT) +#define ID_AA64PFR1_SSBS(x) ((x) & ID_AA64PFR1_SSBS_MASK) +#define ID_AA64PFR1_SSBS_NONE (0x0ULL << ID_AA64PFR1_SSBS_SHIFT) +#define ID_AA64PFR1_SSBS_PSTATE (0x1ULL << ID_AA64PFR1_SSBS_SHIFT) +#define ID_AA64PFR1_SSBS_PSTATE_MSR (0x2ULL << ID_AA64PFR1_SSBS_SHIFT) +#define ID_AA64PFR1_MTE_SHIFT 8 +#define ID_AA64PFR1_MTE_MASK (0xfULL << ID_AA64PFR1_MTE_SHIFT) +#define ID_AA64PFR1_MTE(x) ((x) & ID_AA64PFR1_MTE_MASK) +#define ID_AA64PFR1_MTE_NONE (0x0ULL << ID_AA64PFR1_MTE_SHIFT) +#define ID_AA64PFR1_MTE_IMPL (0x1ULL << ID_AA64PFR1_MTE_SHIFT) +#define ID_AA64PFR1_RAS_FRAC_SHIFT 12 +#define ID_AA64PFR1_RAS_FRAC_MASK (0xfULL << ID_AA64PFR1_RAS_FRAC_SHIFT) +#define ID_AA64PFR1_RAS_FRAC(x) ((x) & ID_AA64PFR1_RAS_FRAC_MASK) +#define ID_AA64PFR1_RAS_FRAC_NONE (0x0ULL << ID_AA64PFR1_RAS_FRAC_SHIFT) +#define ID_AA64PFR1_RAS_FRAC_IMPL (0x1ULL << ID_AA64PFR1_RAS_FRAC_SHIFT) + +/* ID_AA64ZFR0_EL1 */ +#define ID_AA64ZFR0_MASK 0x0ff0ff0f00ff00ffULL +#define ID_AA64ZFR0_SVEVER_SHIFT 0 +#define ID_AA64ZFR0_SVEVER_MASK (0xfULL << ID_AA64ZFR0_SVEVER_SHIFT) +#define ID_AA64ZFR0_SVEVER(x) ((x) & ID_AA64ZFR0_SVEVER_MASK) +#define ID_AA64ZFR0_SVEVER_SVE1 (0x0ULL << ID_AA64ZFR0_SVEVER_SHIFT) +#define ID_AA64ZFR0_SVEVER_SVE2 (0x1ULL << ID_AA64ZFR0_SVEVER_SHIFT) +#define ID_AA64ZFR0_SVEVER_SVE2P1 (0x2ULL << ID_AA64ZFR0_SVEVER_SHIFT) +#define ID_AA64ZFR0_AES_SHIFT 4 +#define ID_AA64ZFR0_AES_MASK (0xfULL << ID_AA64ZFR0_AES_SHIFT) +#define ID_AA64ZFR0_AES(x) ((x) & ID_AA64ZFR0_AES_MASK) +#define ID_AA64ZFR0_AES_NONE (0x0ULL << ID_AA64ZFR0_AES_SHIFT) +#define ID_AA64ZFR0_AES_BASE (0x1ULL << ID_AA64ZFR0_AES_SHIFT) +#define ID_AA64ZFR0_AES_PMULL (0x2ULL << ID_AA64ZFR0_AES_SHIFT) +#define ID_AA64ZFR0_BITPERM_SHIFT 16 +#define ID_AA64ZFR0_BITPERM_MASK (0xfULL << ID_AA64ZFR0_BITPERM_SHIFT) +#define ID_AA64ZFR0_BITPERM(x) ((x) & ID_AA64ZFR0_BITPERM_MASK) +#define ID_AA64ZFR0_BITPERM_NONE (0x0ULL << ID_AA64ZFR0_BITPERM_SHIFT) +#define ID_AA64ZFR0_BITPERM_IMPL (0x1ULL << ID_AA64ZFR0_BITPERM_SHIFT) +#define ID_AA64ZFR0_BF16_SHIFT 20 +#define ID_AA64ZFR0_BF16_MASK (0xfULL << ID_AA64ZFR0_BF16_SHIFT) +#define ID_AA64ZFR0_BF16(x) ((x) & ID_AA64ZFR0_BF16_MASK) +#define ID_AA64ZFR0_BF16_NONE (0x0ULL << ID_AA64ZFR0_BF16_SHIFT) +#define ID_AA64ZFR0_BF16_BASE (0x1ULL << ID_AA64ZFR0_BF16_SHIFT) +#define ID_AA64ZFR0_BF16_EBF (0x2ULL << ID_AA64ZFR0_BF16_SHIFT) +#define ID_AA64ZFR0_SHA3_SHIFT 32 +#define ID_AA64ZFR0_SHA3_MASK (0xfULL << ID_AA64ZFR0_SHA3_SHIFT) +#define ID_AA64ZFR0_SHA3(x) ((x) & ID_AA64ZFR0_SHA3_MASK) +#define ID_AA64ZFR0_SHA3_NONE (0x0ULL << ID_AA64ZFR0_SHA3_SHIFT) +#define ID_AA64ZFR0_SHA3_IMPL (0x1ULL << ID_AA64ZFR0_SHA3_SHIFT) +#define ID_AA64ZFR0_SM4_SHIFT 40 +#define ID_AA64ZFR0_SM4_MASK (0xfULL << ID_AA64ZFR0_SM4_SHIFT) +#define ID_AA64ZFR0_SM4(x) ((x) & ID_AA64ZFR0_SM4_MASK) +#define ID_AA64ZFR0_SM4_NONE (0x0ULL << ID_AA64ZFR0_SM4_SHIFT) +#define ID_AA64ZFR0_SM4_IMPL (0x1ULL << ID_AA64ZFR0_SM4_SHIFT) +#define ID_AA64ZFR0_I8MM_SHIFT 44 +#define ID_AA64ZFR0_I8MM_MASK (0xfULL << ID_AA64ZFR0_I8MM_SHIFT) +#define ID_AA64ZFR0_I8MM(x) ((x) & ID_AA64ZFR0_I8MM_MASK) +#define ID_AA64ZFR0_I8MM_NONE (0x0ULL << ID_AA64ZFR0_I8MM_SHIFT) +#define ID_AA64ZFR0_I8MM_IMPL (0x1ULL << ID_AA64ZFR0_I8MM_SHIFT) +#define ID_AA64ZFR0_F32MM_SHIFT 52 +#define ID_AA64ZFR0_F32MM_MASK (0xfULL << ID_AA64ZFR0_F32MM_SHIFT) +#define ID_AA64ZFR0_F32MM(x) ((x) & ID_AA64ZFR0_F32MM_MASK) +#define ID_AA64ZFR0_F32MM_NONE (0x0ULL << ID_AA64ZFR0_F32MM_SHIFT) +#define ID_AA64ZFR0_F32MM_IMPL (0x1ULL << ID_AA64ZFR0_F32MM_SHIFT) +#define ID_AA64ZFR0_F64MM_SHIFT 56 +#define ID_AA64ZFR0_F64MM_MASK (0xfULL << ID_AA64ZFR0_F64MM_SHIFT) +#define ID_AA64ZFR0_F64MM(x) ((x) & ID_AA64ZFR0_F64MM_MASK) +#define ID_AA64ZFR0_F64MM_NONE (0x0ULL << ID_AA64ZFR0_F64MM_SHIFT) +#define ID_AA64ZFR0_F64MM_IMPL (0x1ULL << ID_AA64ZFR0_F64MM_SHIFT) + +/* MAIR_EL1 - Memory Attribute Indirection Register */ +#define MAIR_ATTR_MASK(idx) (0xff << ((n)* 8)) +#define MAIR_ATTR(attr, idx) ((attr) << ((idx) * 8)) +#define MAIR_DEVICE_nGnRnE 0x00 +#define MAIR_NORMAL_NC 0x44 +#define MAIR_NORMAL_WT 0x88 +#define MAIR_NORMAL_WB 0xff + +/* PAR_EL1 - Physical Address Register */ +#define PAR_F_SHIFT 0 +#define PAR_F (0x1 << PAR_F_SHIFT) +#define PAR_SUCCESS(x) (((x) & PAR_F) == 0) +/* When PAR_F == 0 (success) */ +#define PAR_SH_SHIFT 7 +#define PAR_SH_MASK (0x3 << PAR_SH_SHIFT) +#define PAR_NS_SHIFT 9 +#define PAR_NS_MASK (0x3 << PAR_NS_SHIFT) +#define PAR_PA_SHIFT 12 +#define PAR_PA_MASK 0x0000fffffffff000 +#define PAR_ATTR_SHIFT 56 +#define PAR_ATTR_MASK (0xff << PAR_ATTR_SHIFT) +/* When PAR_F == 1 (aborted) */ +#define PAR_FST_SHIFT 1 +#define PAR_FST_MASK (0x3f << PAR_FST_SHIFT) +#define PAR_PTW_SHIFT 8 +#define PAR_PTW_MASK (0x1 << PAR_PTW_SHIFT) +#define PAR_S_SHIFT 9 +#define PAR_S_MASK (0x1 << PAR_S_SHIFT) + +/* SCTLR_EL1 - System Control Register */ +#define SCTLR_RES0 0xffffffffc8222400 /* Reserved, write 0 */ +#define SCTLR_RES1 0x0000000030d00800 /* Reserved, write 1 */ + +#define SCTLR_M 0x0000000000000001 +#define SCTLR_A 0x0000000000000002 +#define SCTLR_C 0x0000000000000004 +#define SCTLR_SA 0x0000000000000008 +#define SCTLR_SA0 0x0000000000000010 +#define SCTLR_CP15BEN 0x0000000000000020 +#define SCTLR_THEE 0x0000000000000040 +#define SCTLR_ITD 0x0000000000000080 +#define SCTLR_SED 0x0000000000000100 +#define SCTLR_UMA 0x0000000000000200 +#define SCTLR_I 0x0000000000001000 +#define SCTLR_EnDB 0x0000000000002000 +#define SCTLR_DZE 0x0000000000004000 +#define SCTLR_UCT 0x0000000000008000 +#define SCTLR_nTWI 0x0000000000010000 +#define SCTLR_nTWE 0x0000000000040000 +#define SCTLR_WXN 0x0000000000080000 +#define SCTLR_SPAN 0x0000000000800000 +#define SCTLR_EOE 0x0000000001000000 +#define SCTLR_EE 0x0000000002000000 +#define SCTLR_UCI 0x0000000004000000 +#define SCTLR_EnDA 0x0000000008000000 +#define SCTLR_EnIB 0x0000000040000000 +#define SCTLR_EnIA 0x0000000080000000 +#define SCTLR_BT0 0x0000000800000000 +#define SCTLR_BT1 0x0000001000000000 +#define SCTLR_EPAN 0x0200000000000000 + +/* SPSR_EL1 */ +/* + * When the exception is taken in AArch64: + * M[4] is 0 for AArch64 mode + * M[3:2] is the exception level + * M[1] is unused + * M[0] is the SP select: + * 0: always SP0 + * 1: current ELs SP + */ +#define PSR_M_EL0t 0x00000000 +#define PSR_M_EL1t 0x00000004 +#define PSR_M_EL1h 0x00000005 +#define PSR_M_EL2t 0x00000008 +#define PSR_M_EL2h 0x00000009 +#define PSR_M_MASK 0x0000001f + +#define PSR_F 0x00000040 +#define PSR_I 0x00000080 +#define PSR_A 0x00000100 +#define PSR_D 0x00000200 +#define PSR_BTYPE 0x00000c00 +#define PSR_SSBS 0x00001000 +#define PSR_IL 0x00100000 +#define PSR_SS 0x00200000 +#define PSR_PAN 0x00400000 +#define PSR_UAO 0x00800000 +#define PSR_DIT 0x01000000 +#define PSR_TCO 0x02000000 +#define PSR_V 0x10000000 +#define PSR_C 0x20000000 +#define PSR_Z 0x40000000 +#define PSR_N 0x80000000 + +/* TCR_EL1 - Translation Control Register */ +#define TCR_AS (1UL << 36) + +#define TCR_IPS_SHIFT 32 +#define TCR_IPS_32BIT (0UL << TCR_IPS_SHIFT) +#define TCR_IPS_36BIT (1UL << TCR_IPS_SHIFT) +#define TCR_IPS_40BIT (2UL << TCR_IPS_SHIFT) +#define TCR_IPS_42BIT (3UL << TCR_IPS_SHIFT) +#define TCR_IPS_44BIT (4UL << TCR_IPS_SHIFT) +#define TCR_IPS_48BIT (5UL << TCR_IPS_SHIFT) + +#define TCR_TG1_SHIFT 30 +#define TCR_TG1_16K (1UL << TCR_TG1_SHIFT) +#define TCR_TG1_4K (2UL << TCR_TG1_SHIFT) +#define TCR_TG1_64K (3UL << TCR_TG1_SHIFT) + +#define TCR_SH1_SHIFT 28 +#define TCR_SH1_IS (0x3UL << TCR_SH1_SHIFT) +#define TCR_ORGN1_SHIFT 26 +#define TCR_ORGN1_WBWA (0x1UL << TCR_ORGN1_SHIFT) +#define TCR_IRGN1_SHIFT 24 +#define TCR_IRGN1_WBWA (0x1UL << TCR_IRGN1_SHIFT) + +#define TCR_A1 (1UL << 22) + +#define TCR_TG0_SHIFT 14 +#define TCR_TG0_4K (0UL << TCR_TG0_SHIFT) +#define TCR_TG0_64K (1UL << TCR_TG0_SHIFT) +#define TCR_TG0_16K (2UL << TCR_TG0_SHIFT) + +#define TCR_SH0_SHIFT 12 +#define TCR_SH0_IS (0x3UL << TCR_SH0_SHIFT) +#define TCR_ORGN0_SHIFT 10 +#define TCR_ORGN0_WBWA (0x1UL << TCR_ORGN0_SHIFT) +#define TCR_IRGN0_SHIFT 8 +#define TCR_IRGN0_WBWA (0x1UL << TCR_IRGN0_SHIFT) + +#define TCR_CACHE_ATTRS ((TCR_IRGN0_WBWA | TCR_IRGN1_WBWA) |\ + (TCR_ORGN0_WBWA | TCR_ORGN1_WBWA)) +#define TCR_SMP_ATTRS (TCR_SH0_IS | TCR_SH1_IS) + +#define TCR_T1SZ_SHIFT 16 +#define TCR_T0SZ_SHIFT 0 +#define TCR_T1SZ(x) ((x) << TCR_T1SZ_SHIFT) +#define TCR_T0SZ(x) ((x) << TCR_T0SZ_SHIFT) +#define TCR_TxSZ(x) (TCR_T1SZ(x) | TCR_T0SZ(x)) + +/* Monitor Debug System Control Register */ +#define DBG_MDSCR_SS (0x1 << 0) +#define DBG_MDSCR_TDCC (0x1 << 12) +#define DBG_MDSCR_KDE (0x1 << 13) +#define DBG_MDSCR_MDE (0x1 << 15) + +/* Performance Monitoring Counters */ +#define PMCR_E (1 << 0) /* Enable all counters */ +#define PMCR_P (1 << 1) /* Reset all counters */ +#define PMCR_C (1 << 2) /* Clock counter reset */ +#define PMCR_D (1 << 3) /* CNTR counts every 64 clk cycles */ +#define PMCR_X (1 << 4) /* Export to ext. monitoring (ETM) */ +#define PMCR_DP (1 << 5) /* Disable CCNT if non-invasive debug*/ +#define PMCR_LC (1 << 6) /* Long cycle count enable */ +#define PMCR_IMP_SHIFT 24 /* Implementer code */ +#define PMCR_IMP_MASK (0xff << PMCR_IMP_SHIFT) +#define PMCR_IDCODE_SHIFT 16 /* Identification code */ +#define PMCR_IDCODE_MASK (0xff << PMCR_IDCODE_SHIFT) +#define PMCR_IDCODE_CORTEX_A57 0x01 +#define PMCR_IDCODE_CORTEX_A72 0x02 +#define PMCR_IDCODE_CORTEX_A53 0x03 +#define PMCR_N_SHIFT 11 /* Number of counters implemented */ +#define PMCR_N_MASK (0x1f << PMCR_N_SHIFT) + +#define I_bit (1 << 7) /* IRQ disable */ +#define F_bit 0 /* FIQ disable - not actually used */ + +#endif /* !_MACHINE_ARMREG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/asm.h b/lib/libc/include/aarch64-openbsd-none/machine/asm.h new file mode 100644 index 000000000000..e0ad18f38dc7 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/asm.h @@ -0,0 +1,150 @@ +/* $OpenBSD: asm.h,v 1.12 2023/03/27 19:02:48 kettenis Exp $ */ +/* $NetBSD: asm.h,v 1.4 2001/07/16 05:43:32 matt Exp $ */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)asm.h 5.5 (Berkeley) 5/7/91 + */ + +#ifndef _MACHINE_ASM_H_ +#define _MACHINE_ASM_H_ + +#define _C_LABEL(x) x +#define _ASM_LABEL(x) x + +#ifdef __STDC__ +# define __CONCAT(x,y) x ## y +# define __STRING(x) #x +#else +# define __CONCAT(x,y) x/**/y +# define __STRING(x) "x" +#endif + +#ifndef _ALIGN_TEXT +# define _ALIGN_TEXT .align 0 +#endif + +/* + * gas/arm uses @ as a single comment character and thus cannot be used here + * Instead it recognised the # instead of an @ symbols in .type directives + * We define a couple of macros so that assembly code will not be dependant + * on one or the other. + */ +#define _ASM_TYPE_FUNCTION #function +#define _ASM_TYPE_OBJECT #object +/* NB == No Binding: use .globl or .weak as necessary */ +#define _ENTRY_NB(x) \ + .text; _ALIGN_TEXT; .type x,_ASM_TYPE_FUNCTION; x: +#define _ENTRY(x) .globl x; _ENTRY_NB(x) + +#if defined(PROF) || defined(GPROF) +# define _PROF_PROLOGUE \ + stp x29, x30, [sp, #-16]!; \ + mov fp, sp; \ + bl __mcount; \ + ldp x29, x30, [sp], #16; +#else +# define _PROF_PROLOGUE +#endif + +#if defined(_RET_PROTECTOR) +# define RETGUARD_CALC_COOKIE(reg) \ + eor reg, reg, x30 + +# define RETGUARD_LOAD_RANDOM(x, reg) \ + adrp reg, __CONCAT(__retguard_, x); \ + ldr reg, [reg, :lo12:__CONCAT(__retguard_, x)] + +# define RETGUARD_SETUP(x, reg) \ + RETGUARD_SYMBOL(x); \ + RETGUARD_LOAD_RANDOM(x, reg); \ + RETGUARD_CALC_COOKIE(reg) + +# define RETGUARD_CHECK(x, reg) \ + RETGUARD_CALC_COOKIE(reg); \ + RETGUARD_LOAD_RANDOM(x, x9); \ + subs reg, reg, x9; \ + cbz reg, 66f; \ + brk #0x1; \ +66: + +# define RETGUARD_PUSH(reg) \ + str reg, [sp, #-16]! + +# define RETGUARD_POP(reg) \ + ldr reg, [sp, #16]! + +# define RETGUARD_SYMBOL(x) \ + .ifndef __CONCAT(__retguard_, x); \ + .hidden __CONCAT(__retguard_, x); \ + .type __CONCAT(__retguard_, x),@object; \ + .pushsection .openbsd.randomdata.retguard,"aw",@progbits; \ + .weak __CONCAT(__retguard_, x); \ + .p2align 3; \ + __CONCAT(__retguard_, x): ; \ + .xword 0; \ + .size __CONCAT(__retguard_, x), 8; \ + .popsection; \ + .endif +#else +# define RETGUARD_CALC_COOKIE(reg) +# define RETGUARD_LOAD_RANDOM(x, reg) +# define RETGUARD_SETUP(x, reg) +# define RETGUARD_CHECK(x, reg) +# define RETGUARD_PUSH(reg) +# define RETGUARD_POP(reg) +# define RETGUARD_SYMBOL(x) +#endif + +#define ENTRY(y) _ENTRY(y); bti c; _PROF_PROLOGUE +#define ENTRY_NP(y) _ENTRY(y); bti c +#define ENTRY_NB(y) _ENTRY_NB(y); bti c; _PROF_PROLOGUE +#define ASENTRY(y) _ENTRY(y); bti c; _PROF_PROLOGUE +#define ASENTRY_NP(y) _ENTRY(y); bti c +#define END(y) .size y, . - y +#define EENTRY(sym) .globl sym; sym: +#define EEND(sym) + +#ifdef __PIC__ +#define PIC_SYM(x,y) x(y) +#else +#define PIC_SYM(x,y) x +#endif + +#define STRONG_ALIAS(alias,sym) \ + .global alias; \ + alias = sym +#define WEAK_ALIAS(alias,sym) \ + .weak alias; \ + alias = sym + +#endif /* !_MACHINE_ASM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/atomic.h b/lib/libc/include/aarch64-openbsd-none/machine/atomic.h new file mode 100644 index 000000000000..7a66719a4755 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/atomic.h @@ -0,0 +1,64 @@ +/* $OpenBSD: atomic.h,v 1.4 2022/08/29 02:01:18 jsg Exp $ */ + +/* Public Domain */ + +#ifndef _MACHINE_ATOMIC_H_ +#define _MACHINE_ATOMIC_H_ + +#define __membar(_f) do { __asm volatile(_f ::: "memory"); } while (0) + +#define membar_enter() __membar("dmb sy") +#define membar_exit() __membar("dmb sy") +#define membar_producer() __membar("dmb st") +#define membar_consumer() __membar("dmb ld") +#define membar_sync() __membar("dmb sy") + +#if defined(_KERNEL) + +/* virtio needs MP membars even on SP kernels */ +#define virtio_membar_producer() __membar("dmb st") +#define virtio_membar_consumer() __membar("dmb ld") +#define virtio_membar_sync() __membar("dmb sy") + +/* + * Set bits + * *p = *p | v + */ +static inline void +atomic_setbits_int(volatile unsigned int *p, unsigned int v) +{ + unsigned int modified, tmp; + + __asm volatile ( + "1: ldxr %w0, [%x3] \n\t" + " orr %w0, %w0, %w2 \n\t" + " stxr %w1, %w0, [%x3] \n\t" + " cbnz %w1, 1b \n\t" + : "=&r" (tmp), "=&r" (modified) + : "r" (v), "r" (p) + : "memory", "cc" + ); +} + +/* + * Clear bits + * *p = *p & (~v) + */ +static inline void +atomic_clearbits_int(volatile unsigned int *p, unsigned int v) +{ + unsigned int modified, tmp; + + __asm volatile ( + "1: ldxr %w0, [%x3] \n\t" + " bic %w0, %w0, %w2 \n\t" + " stxr %w1, %w0, [%x3] \n\t" + " cbnz %w1, 1b \n\t" + : "=&r" (tmp), "=&r" (modified) + : "r" (v), "r" (p) + : "memory", "cc" + ); +} + +#endif /* defined(_KERNEL) */ +#endif /* _MACHINE_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/bootconfig.h b/lib/libc/include/aarch64-openbsd-none/machine/bootconfig.h new file mode 100644 index 000000000000..8767d1ab7f7f --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/bootconfig.h @@ -0,0 +1,47 @@ +/* $OpenBSD: bootconfig.h,v 1.4 2023/12/05 05:27:26 jsg Exp $ */ +/* $NetBSD: bootconfig.h,v 1.2 2001/06/21 22:08:28 chris Exp $ */ + +/*- + * Copyright (c) 2013 Andrew Turner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: head/sys/arm64/include/machdep.h 281494 2015-04-13 14:43:10Z andrew $ + */ + +#ifndef _MACHINE_BOOTCONFIG_H_ +#define _MACHINE_BOOTCONFIG_H_ + +struct arm64_bootparams { + vaddr_t modulep; + vaddr_t kern_l1pt; /* L1 page table for the kernel */ + uint64_t kern_delta; + vaddr_t kern_stack; + void *arg0; // passed to kernel in R0 + void *arg1; // passed to kernel in R1 + void *arg2; // passed to kernel in R2 +}; + +void initarm(struct arm64_bootparams *); + +#endif /* _MACHINE_BOOTCONFIG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/bus.h b/lib/libc/include/aarch64-openbsd-none/machine/bus.h new file mode 100644 index 000000000000..70ad145593e8 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/bus.h @@ -0,0 +1,536 @@ +/* $OpenBSD: bus.h,v 1.11 2024/11/18 05:32:39 jsg Exp $ */ +/* + * Copyright (c) 2003-2004 Opsycon AB Sweden. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BUS_H_ +#define _MACHINE_BUS_H_ + +#ifdef __STDC__ +#define CAT(a,b) a##b +#define CAT3(a,b,c) a##b##c +#else +#define CAT(a,b) a/**/b +#define CAT3(a,b,c) a/**/b/**/c +#endif + +/* + * Bus access types. + */ +struct bus_space; +typedef u_long bus_addr_t; +typedef u_long bus_size_t; +typedef u_long bus_space_handle_t; +typedef struct bus_space *bus_space_tag_t; +typedef struct bus_space bus_space_t; + +struct bus_space { + bus_addr_t bus_base; + void *bus_private; + u_int8_t (*_space_read_1)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_1)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int8_t); + u_int16_t (*_space_read_2)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_2)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int16_t); + u_int32_t (*_space_read_4)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_4)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int32_t); + u_int64_t (*_space_read_8)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_8)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int64_t); + void (*_space_read_raw_2)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_2)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + void (*_space_read_raw_4)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_4)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + void (*_space_read_raw_8)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_8)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + int (*_space_map)(bus_space_tag_t , bus_addr_t, + bus_size_t, int, bus_space_handle_t *); + void (*_space_unmap)(bus_space_tag_t, bus_space_handle_t, + bus_size_t); + int (*_space_subregion)(bus_space_tag_t, bus_space_handle_t, + bus_size_t, bus_size_t, bus_space_handle_t *); + void * (*_space_vaddr)(bus_space_tag_t, bus_space_handle_t); + paddr_t (*_space_mmap)(bus_space_tag_t, bus_addr_t, off_t, + int, int); +}; + +#define bus_space_read_1(t, h, o) (*(t)->_space_read_1)((t), (h), (o)) +#define bus_space_read_2(t, h, o) (*(t)->_space_read_2)((t), (h), (o)) +#define bus_space_read_4(t, h, o) (*(t)->_space_read_4)((t), (h), (o)) +#define bus_space_read_8(t, h, o) (*(t)->_space_read_8)((t), (h), (o)) + +#define bus_space_write_1(t, h, o, v) (*(t)->_space_write_1)((t), (h), (o), (v)) +#define bus_space_write_2(t, h, o, v) (*(t)->_space_write_2)((t), (h), (o), (v)) +#define bus_space_write_4(t, h, o, v) (*(t)->_space_write_4)((t), (h), (o), (v)) +#define bus_space_write_8(t, h, o, v) (*(t)->_space_write_8)((t), (h), (o), (v)) + +#define bus_space_read_raw_2(t, h, o) \ + (*(t)->_space_read_2)((t), (h), (o)) +#define bus_space_read_raw_4(t, h, o) \ + (*(t)->_space_read_4)((t), (h), (o)) +#define bus_space_read_raw_8(t, h, o) \ + (*(t)->_space_read_8)((t), (h), (o)) + +#define bus_space_write_raw_2(t, h, o, v) \ + (*(t)->_space_write_2)((t), (h), (o), (v)) +#define bus_space_write_raw_4(t, h, o, v) \ + (*(t)->_space_write_4)((t), (h), (o), (v)) +#define bus_space_write_raw_8(t, h, o, v) \ + (*(t)->_space_write_8)((t), (h), (o), (v)) + +#define bus_space_read_raw_multi_2(t, h, a, b, l) \ + (*(t)->_space_read_raw_2)((t), (h), (a), (b), (l)) +#define bus_space_read_raw_multi_4(t, h, a, b, l) \ + (*(t)->_space_read_raw_4)((t), (h), (a), (b), (l)) +#define bus_space_read_raw_multi_8(t, h, a, b, l) \ + (*(t)->_space_read_raw_8)((t), (h), (a), (b), (l)) + +#define bus_space_write_raw_multi_2(t, h, a, b, l) \ + (*(t)->_space_write_raw_2)((t), (h), (a), (b), (l)) +#define bus_space_write_raw_multi_4(t, h, a, b, l) \ + (*(t)->_space_write_raw_4)((t), (h), (a), (b), (l)) +#define bus_space_write_raw_multi_8(t, h, a, b, l) \ + (*(t)->_space_write_raw_8)((t), (h), (a), (b), (l)) + +#define bus_space_map(t, o, s, c, p) (*(t)->_space_map)((t), (o), (s), (c), (p)) +#define bus_space_unmap(t, h, s) (*(t)->_space_unmap)((t), (h), (s)) +#define bus_space_subregion(t, h, o, s, p) \ + (*(t)->_space_subregion)((t), (h), (o), (s), (p)) + +#define BUS_SPACE_MAP_CACHEABLE 0x01 +#define BUS_SPACE_MAP_POSTED 0x02 +#define BUS_SPACE_MAP_LINEAR 0x04 +#define BUS_SPACE_MAP_PREFETCHABLE 0x08 + +extern bus_space_t arm64_bs_tag; + +#define bus_space_vaddr(t, h) (*(t)->_space_vaddr)((t), (h)) +#define bus_space_mmap(t, a, o, p, f) \ + (*(t)->_space_mmap)((t), (a), (o), (p), (f)) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_multi(n,m) \ +static __inline void \ +CAT(bus_space_read_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t o, CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) \ + *x++ = CAT(bus_space_read_,n)(bst, bsh, o); \ +} + +bus_space_read_multi(1,8) +bus_space_read_multi(2,16) +bus_space_read_multi(4,32) +bus_space_read_multi(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_region(n,m) \ +static __inline void \ +CAT(bus_space_read_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) { \ + *x++ = CAT(bus_space_read_,n)(bst, bsh, ba); \ + ba += (n); \ + } \ +} + +bus_space_read_region(1,8) +bus_space_read_region(2,16) +bus_space_read_region(4,32) +bus_space_read_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_raw_region(n,m) \ +static __inline void \ +CAT(bus_space_read_raw_region_,n)(bus_space_tag_t bst, \ + bus_space_handle_t bsh, \ + bus_addr_t ba, u_int8_t *x, size_t cnt) \ +{ \ + cnt >>= ((n) >> 1); \ + while (cnt--) { \ + CAT(bus_space_read_raw_multi_,n)(bst, bsh, ba, x, (n)); \ + ba += (n); \ + x += (n); \ + } \ +} + +bus_space_read_raw_region(2,16) +bus_space_read_raw_region(4,32) +bus_space_read_raw_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_multi(n,m) \ +static __inline void \ +CAT(bus_space_write_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t o, const CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) \ + CAT(bus_space_write_,n)(bst, bsh, o, *x++); \ +} + +bus_space_write_multi(1,8) +bus_space_write_multi(2,16) +bus_space_write_multi(4,32) +bus_space_write_multi(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_region(n,m) \ +static __inline void \ +CAT(bus_space_write_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, const CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) { \ + CAT(bus_space_write_,n)(bst, bsh, ba, *x++); \ + ba += (n); \ + } \ +} + +bus_space_write_region(1,8) +bus_space_write_region(2,16) +bus_space_write_region(4,32) +bus_space_write_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_raw_region(n,m) \ +static __inline void \ +CAT(bus_space_write_raw_region_,n)(bus_space_tag_t bst, \ + bus_space_handle_t bsh, \ + bus_addr_t ba, const u_int8_t *x, size_t cnt) \ +{ \ + cnt >>= ((n) >> 1); \ + while (cnt--) { \ + CAT(bus_space_write_raw_multi_,n)(bst, bsh, ba, x, (n)); \ + ba += (n); \ + x += (n); \ + } \ +} + +bus_space_write_raw_region(2,16) +bus_space_write_raw_region(4,32) +bus_space_write_raw_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_set_region(n,m) \ +static __inline void \ +CAT(bus_space_set_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(u_int,m,_t) x, size_t cnt) \ +{ \ + while (cnt--) { \ + CAT(bus_space_write_,n)(bst, bsh, ba, x); \ + ba += (n); \ + } \ +} + +bus_space_set_region(1,8) +bus_space_set_region(2,16) +bus_space_set_region(4,32) +bus_space_set_region(8,64) + +/*----------------------------------------------------------------------------*/ +static __inline void +bus_space_copy_1(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + char *s = (char *)(h1 + o1); + char *d = (char *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + + +static __inline void +bus_space_copy_2(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + short *s = (short *)(h1 + o1); + short *d = (short *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + +static __inline void +bus_space_copy_4(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + int *s = (int *)(h1 + o1); + int *d = (int *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + +static __inline void +bus_space_copy_8(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + int64_t *s = (int64_t *)(h1 + o1); + int64_t *d = (int64_t *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + +/*----------------------------------------------------------------------------*/ +/* + * Bus read/write barrier methods. + * + * void bus_space_barrier(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * bus_size_t len, int flags); + * + */ +static inline void +bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, + bus_size_t length, int flags) +{ + __asm__ volatile ("dsb sy" ::: "memory"); +} +#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ +#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ + +#define BUS_DMA_WAITOK 0x0000 +#define BUS_DMA_NOWAIT 0x0001 +#define BUS_DMA_ALLOCNOW 0x0002 +#define BUS_DMA_COHERENT 0x0008 +#define BUS_DMA_BUS1 0x0010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x0020 +#define BUS_DMA_BUS3 0x0040 +#define BUS_DMA_BUS4 0x0080 +#define BUS_DMA_READ 0x0100 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x0200 /* mapping is memory -> device only */ +#define BUS_DMA_STREAMING 0x0400 /* hint: sequential, unidirectional */ +#define BUS_DMA_ZERO 0x0800 /* zero memory in dmamem_alloc */ +#define BUS_DMA_NOCACHE 0x1000 +#define BUS_DMA_64BIT 0x2000 /* device handles 64bit dva */ +#define BUS_DMA_FIXED 0x4000 /* place mapping at specified dva */ + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct proc; +struct uio; + +#define BUS_DMASYNC_POSTREAD 0x0001 +#define BUS_DMASYNC_POSTWRITE 0x0002 +#define BUS_DMASYNC_PREREAD 0x0004 +#define BUS_DMASYNC_PREWRITE 0x0008 + +typedef struct machine_bus_dma_tag *bus_dma_tag_t; +typedef struct machine_bus_dmamap *bus_dmamap_t; + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +struct machine_bus_dma_segment { + bus_addr_t ds_addr; /* DMA address */ + bus_size_t ds_len; /* length of transfer */ + + paddr_t _ds_paddr; /* CPU address */ + vaddr_t _ds_vaddr; /* CPU address */ +}; +typedef struct machine_bus_dma_segment bus_dma_segment_t; + +/* + * bus_dma_tag_t + * + * A machine-dependent opaque type describing the implementation of + * DMA for a given bus. + */ + +struct machine_bus_dma_tag { + void *_cookie; /* cookie used in the guts */ + int _flags; /* misc. flags */ + + /* + * DMA mapping methods. + */ + int (*_dmamap_create)(bus_dma_tag_t , bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); + void (*_dmamap_destroy)(bus_dma_tag_t , bus_dmamap_t); + int (*_dmamap_load)(bus_dma_tag_t , bus_dmamap_t, void *, + bus_size_t, struct proc *, int); + int (*_dmamap_load_mbuf)(bus_dma_tag_t , bus_dmamap_t, + struct mbuf *, int); + int (*_dmamap_load_uio)(bus_dma_tag_t , bus_dmamap_t, + struct uio *, int); + int (*_dmamap_load_raw)(bus_dma_tag_t , bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); + int (*_dmamap_load_buffer)(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int, paddr_t *, int *, int); + void (*_dmamap_unload)(bus_dma_tag_t , bus_dmamap_t); + void (*_dmamap_sync)(bus_dma_tag_t , bus_dmamap_t, + bus_addr_t, bus_size_t, int); + + /* + * DMA memory utility functions. + */ + int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); + int (*_dmamem_alloc_range)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int, + bus_addr_t, bus_addr_t); + void (*_dmamem_free)(bus_dma_tag_t, bus_dma_segment_t *, int); + int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); + void (*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t); + paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, + int, off_t, int, int); + + /* + * internal memory address translation information. + */ + bus_addr_t _dma_mask; +}; + +#define bus_dmamap_create(t, s, n, m, b, f, p) \ + (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) +#define bus_dmamap_destroy(t, p) \ + (*(t)->_dmamap_destroy)((t), (p)) +#define bus_dmamap_load(t, m, b, s, p, f) \ + (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) +#define bus_dmamap_load_mbuf(t, m, b, f) \ + (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) +#define bus_dmamap_load_uio(t, m, u, f) \ + (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) +#define bus_dmamap_load_raw(t, m, sg, n, s, f) \ + (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) +#define bus_dmamap_unload(t, p) \ + (*(t)->_dmamap_unload)((t), (p)) +#define bus_dmamap_sync(t, p, a, l, o) \ + (void)((t)->_dmamap_sync ? \ + (*(t)->_dmamap_sync)((t), (p), (a), (l), (o)) : (void)0) + +#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ + (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f)) +#define bus_dmamem_alloc_range(t, s, a, b, sg, n, r, f, l, h) \ + (*(t)->_dmamem_alloc_range)((t), (s), (a), (b), (sg), \ + (n), (r), (f), (l), (h)) +#define bus_dmamem_free(t, sg, n) \ + (*(t)->_dmamem_free)((t), (sg), (n)) +#define bus_dmamem_map(t, sg, n, s, k, f) \ + (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f)) +#define bus_dmamem_unmap(t, k, s) \ + (*(t)->_dmamem_unmap)((t), (k), (s)) +#define bus_dmamem_mmap(t, sg, n, o, p, f) \ + (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f)) + +int _dmamap_create(bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); +void _dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); +int _dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); +int _dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *, int); +int _dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, struct uio *, int); +int _dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); +int _dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int, paddr_t *, int *, int); +void _dmamap_unload(bus_dma_tag_t, bus_dmamap_t); +void _dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, + bus_size_t, int); + +int _dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); +void _dmamem_free(bus_dma_tag_t, bus_dma_segment_t *, int); +int _dmamem_map(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); +void _dmamem_unmap(bus_dma_tag_t, caddr_t, size_t); +paddr_t _dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, int, int); +int _dmamem_alloc_range(bus_dma_tag_t, bus_size_t, bus_size_t, bus_size_t, + bus_dma_segment_t *, int, int *, int, paddr_t, paddr_t); + +/* + * bus_dmamap_t + * + * Describes a DMA mapping. + */ +struct machine_bus_dmamap { + /* + * PRIVATE MEMBERS: not for use by machine-independent code. + */ + bus_size_t _dm_size; /* largest DMA transfer mappable */ + int _dm_segcnt; /* number of segs this map can map */ + bus_size_t _dm_maxsegsz; /* largest possible segment */ + bus_size_t _dm_boundary; /* don't cross this */ + int _dm_flags; /* misc. flags */ + + void *_dm_cookie; /* cookie for bus-specific functions */ + + /* + * PUBLIC MEMBERS: these are used by machine-independent code. + */ + bus_size_t dm_mapsize; /* size of the mapping */ + int dm_nsegs; /* # valid segments in mapping */ + bus_dma_segment_t dm_segs[1]; /* segments; variable length */ +}; + +int generic_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, + bus_space_handle_t *); +void generic_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t); +int generic_space_region(bus_space_tag_t, bus_space_handle_t, bus_size_t, + bus_size_t, bus_space_handle_t *); +void *generic_space_vaddr(bus_space_tag_t, bus_space_handle_t); +paddr_t generic_space_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int); +uint8_t generic_space_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint16_t generic_space_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint32_t generic_space_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint64_t generic_space_read_8(bus_space_tag_t, bus_space_handle_t, bus_size_t); +void generic_space_read_raw_2(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint8_t); +void generic_space_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint16_t); +void generic_space_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint32_t); +void generic_space_write_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint64_t); +void generic_space_write_raw_2(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); +void generic_space_read_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); +void generic_space_read_raw_8(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_raw_8(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); + +#endif /* _MACHINE_BUS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/cdefs.h b/lib/libc/include/aarch64-openbsd-none/machine/cdefs.h new file mode 100644 index 000000000000..307f720db414 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/cdefs.h @@ -0,0 +1,16 @@ +/* $OpenBSD: cdefs.h,v 1.1 2016/12/17 23:38:33 patrick Exp $ */ + +#ifndef _MACHINE_CDEFS_H_ +#define _MACHINE_CDEFS_H_ + +#define __strong_alias(alias,sym) \ + __asm__(".global " __STRING(alias) " ; " __STRING(alias) \ + " = " __STRING(sym)) +#define __weak_alias(alias,sym) \ + __asm__(".weak " __STRING(alias) " ; " __STRING(alias) \ + " = " __STRING(sym)) +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning." __STRING(sym) \ + " ; .ascii \"" msg "\" ; .text") + +#endif /* !_MACHINE_CDEFS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/conf.h b/lib/libc/include/aarch64-openbsd-none/machine/conf.h new file mode 100644 index 000000000000..9a9e0a146509 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/conf.h @@ -0,0 +1,61 @@ +/* $OpenBSD: conf.h,v 1.5 2024/06/12 02:50:25 jsg Exp $ */ +/* $NetBSD: conf.h,v 1.2 1996/05/05 19:28:34 christos Exp $ */ + +/* + * Copyright (c) 1996 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_CONF_H_ +#define _MACHINE_CONF_H_ + +#include + +#define mmread mmrw +#define mmwrite mmrw +cdev_decl(mm); + +/* open, close, ioctl */ +#define cdev_openprom_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) nullop, 0, \ + (dev_type_mmap((*))) enodev } + +cdev_decl(openprom); + +/* open, close, write, ioctl, kqueue */ +#define cdev_acpiapm_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev, 0, 0, dev_init(c,n,kqfilter) } + +cdev_decl(apm); +cdev_decl(acpiapm); + +#endif /* _MACHINE_CONF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/cpu.h b/lib/libc/include/aarch64-openbsd-none/machine/cpu.h new file mode 100644 index 000000000000..39cdc4ecd5ea --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/cpu.h @@ -0,0 +1,360 @@ +/* $OpenBSD: cpu.h,v 1.51 2025/02/11 22:27:09 kettenis Exp $ */ +/* + * Copyright (c) 2016 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_CPU_H_ +#define _MACHINE_CPU_H_ + +/* + * User-visible definitions + */ + +/* + * CTL_MACHDEP definitions. + */ +#define CPU_COMPATIBLE 1 /* compatible property */ +#define CPU_ID_AA64ISAR0 2 +#define CPU_ID_AA64ISAR1 3 +#define CPU_ID_AA64ISAR2 4 +#define CPU_ID_AA64MMFR0 5 +#define CPU_ID_AA64MMFR1 6 +#define CPU_ID_AA64MMFR2 7 +#define CPU_ID_AA64PFR0 8 +#define CPU_ID_AA64PFR1 9 +#define CPU_ID_AA64SMFR0 10 +#define CPU_ID_AA64ZFR0 11 +#define CPU_LIDACTION 12 +#define CPU_MAXID 13 /* number of valid machdep ids */ + +#define CTL_MACHDEP_NAMES { \ + { 0, 0 }, \ + { "compatible", CTLTYPE_STRING }, \ + { "id_aa64isar0", CTLTYPE_QUAD }, \ + { "id_aa64isar1", CTLTYPE_QUAD }, \ + { "id_aa64isar2", CTLTYPE_QUAD }, \ + { "id_aa64mmfr0", CTLTYPE_QUAD }, \ + { "id_aa64mmfr1", CTLTYPE_QUAD }, \ + { "id_aa64mmfr2", CTLTYPE_QUAD }, \ + { "id_aa64pfr0", CTLTYPE_QUAD }, \ + { "id_aa64pfr1", CTLTYPE_QUAD }, \ + { "id_aa64smfr0", CTLTYPE_QUAD }, \ + { "id_aa64zfr0", CTLTYPE_QUAD }, \ + { "lidaction", CTLTYPE_INT }, \ +} + +#ifdef _KERNEL + +/* + * Kernel-only definitions + */ + +extern uint64_t cpu_id_aa64isar0; +extern uint64_t cpu_id_aa64isar1; +extern uint64_t cpu_id_aa64isar2; +extern uint64_t cpu_id_aa64mmfr0; +extern uint64_t cpu_id_aa64mmfr1; +extern uint64_t cpu_id_aa64mmfr2; +extern uint64_t cpu_id_aa64pfr0; +extern uint64_t cpu_id_aa64pfr1; +extern uint64_t cpu_id_aa64zfr0; + +void cpu_identify_cleanup(void); + +#include +#include +#include + +/* All the CLKF_* macros take a struct clockframe * as an argument. */ + +#define clockframe trapframe +/* + * CLKF_USERMODE: Return TRUE/FALSE (1/0) depending on whether the + * frame came from USR mode or not. + */ +#define CLKF_USERMODE(frame) ((frame->tf_elr & (1ul << 63)) == 0) + +/* + * CLKF_INTR: True if we took the interrupt from inside another + * interrupt handler. + */ +#define CLKF_INTR(frame) (curcpu()->ci_idepth > 1) + +/* + * CLKF_PC: Extract the program counter from a clockframe + */ +#define CLKF_PC(frame) (frame->tf_elr) + +/* + * PROC_PC: Find out the program counter for the given process. + */ +#define PROC_PC(p) ((p)->p_addr->u_pcb.pcb_tf->tf_elr) +#define PROC_STACK(p) ((p)->p_addr->u_pcb.pcb_tf->tf_sp) + +/* + * Per-CPU information. For now we assume one CPU. + */ + +#include +#include +#include +#include +#include + +struct cpu_info { + struct device *ci_dev; /* Device corresponding to this CPU */ + struct cpu_info *ci_next; + struct schedstate_percpu ci_schedstate; /* scheduler state */ + + u_int32_t ci_cpuid; + uint64_t ci_mpidr; + uint64_t ci_midr; + u_int ci_acpi_proc_id; + int ci_node; + struct cpu_info *ci_self; + +#define __HAVE_CPU_TOPOLOGY + u_int32_t ci_smt_id; + u_int32_t ci_core_id; + u_int32_t ci_pkg_id; + + struct proc *ci_curproc; + struct pcb *ci_curpcb; + struct pmap *ci_curpm; + u_int32_t ci_randseed; + + u_int32_t ci_ctrl; /* The CPU control register */ + + u_int64_t ci_trampoline_vectors; + + uint32_t ci_cpl; + uint32_t ci_ipending; + uint32_t ci_idepth; +#ifdef DIAGNOSTIC + int ci_mutex_level; +#endif + int ci_want_resched; + + void (*ci_flush_bp)(void); + void (*ci_serror)(void); + + uint64_t ci_ttbr1; + vaddr_t ci_el1_stkend; + + uint32_t ci_psci_idle_latency; + uint32_t ci_psci_idle_param; + uint32_t ci_psci_suspend_param; + + struct opp_table *ci_opp_table; + volatile int ci_opp_idx; + volatile int ci_opp_max; + uint32_t ci_cpu_supply; + + u_long ci_prev_sleep; + u_long ci_last_itime; + +#ifdef MULTIPROCESSOR + struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM]; +#define __HAVE_UVM_PERCPU + struct uvm_pmr_cache ci_uvm; + volatile int ci_flags; + + volatile int ci_ddb_paused; +#define CI_DDB_RUNNING 0 +#define CI_DDB_SHOULDSTOP 1 +#define CI_DDB_STOPPED 2 +#define CI_DDB_ENTERDDB 3 +#define CI_DDB_INDDB 4 + +#endif + +#ifdef GPROF + struct gmonparam *ci_gmon; + struct clockintr ci_gmonclock; +#endif + struct clockqueue ci_queue; + char ci_panicbuf[512]; +}; + +#define CPUF_PRIMARY (1<<0) +#define CPUF_AP (1<<1) +#define CPUF_IDENTIFY (1<<2) +#define CPUF_IDENTIFIED (1<<3) +#define CPUF_PRESENT (1<<4) +#define CPUF_GO (1<<5) +#define CPUF_RUNNING (1<<6) + +static inline struct cpu_info * +curcpu(void) +{ + struct cpu_info *__ci = NULL; + __asm volatile("mrs %0, tpidr_el1" : "=r" (__ci)); + return (__ci); +} + +extern struct cpu_info cpu_info_primary; +extern struct cpu_info *cpu_info_list; + +#ifndef MULTIPROCESSOR +#define cpu_number() 0 +#define CPU_IS_PRIMARY(ci) 1 +#define CPU_IS_RUNNING(ci) 1 +#define CPU_INFO_ITERATOR int +#define CPU_INFO_FOREACH(cii, ci) \ + for (cii = 0, ci = curcpu(); ci != NULL; ci = NULL) +#define CPU_INFO_UNIT(ci) 0 +#define MAXCPUS 1 +#define cpu_unidle(ci) +#else +#define cpu_number() (curcpu()->ci_cpuid) +#define CPU_IS_PRIMARY(ci) ((ci) == &cpu_info_primary) +#define CPU_IS_RUNNING(ci) ((ci)->ci_flags & CPUF_RUNNING) +#define CPU_INFO_ITERATOR int +#define CPU_INFO_FOREACH(cii, ci) for (cii = 0, ci = cpu_info_list; \ + ci != NULL; ci = ci->ci_next) +#define CPU_INFO_UNIT(ci) ((ci)->ci_dev ? (ci)->ci_dev->dv_unit : 0) +#define MAXCPUS 256 + +extern struct cpu_info *cpu_info[MAXCPUS]; + +void cpu_boot_secondary_processors(void); +#endif /* !MULTIPROCESSOR */ + +#define CPU_BUSY_CYCLE() __asm volatile("yield" : : : "memory") + +#define curpcb curcpu()->ci_curpcb + +static inline unsigned int +cpu_rnd_messybits(void) +{ + uint64_t val, rval; + + __asm volatile("mrs %0, CNTVCT_EL0; rbit %1, %0;" + : "=r" (val), "=r" (rval)); + + return (val ^ rval); +} + +/* + * Scheduling glue + */ +#define aston(p) ((p)->p_md.md_astpending = 1) +#define setsoftast() aston(curcpu()->ci_curproc) + +/* + * Notify the current process (p) that it has a signal pending, + * process as soon as possible. + */ + +#ifdef MULTIPROCESSOR +void cpu_unidle(struct cpu_info *ci); +#define signotify(p) (aston(p), cpu_unidle((p)->p_cpu)) +void cpu_kick(struct cpu_info *); +#else +#define cpu_kick(ci) +#define cpu_unidle(ci) +#define signotify(p) setsoftast() +#endif + +/* + * Preempt the current process if in interrupt from user mode, + * or after the current trap/syscall if in system mode. + */ +void need_resched(struct cpu_info *); +#define clear_resched(ci) ((ci)->ci_want_resched = 0) + +/* + * Give a profiling tick to the current process when the user profiling + * buffer pages are invalid. On the i386, request an ast to send us + * through trap(), marking the proc as needing a profiling tick. + */ +#define need_proftick(p) aston(p) + +// asm code to start new kernel contexts. +void proc_trampoline(void); + +/* + * Random cruft + */ +void dumpconf(void); + +// syscall.c +void svc_handler (trapframe_t *); + +// functions to manipulate interrupt state +static __inline void +restore_daif(uint32_t daif) +{ + __asm volatile ("msr daif, %x0":: "r"(daif)); +} + +static __inline void +enable_irq_daif(void) +{ + __asm volatile ("msr daifclr, #3"); +} + +static __inline void +disable_irq_daif(void) +{ + __asm volatile ("msr daifset, #3"); +} + +static __inline uint32_t +disable_irq_daif_ret(void) +{ + uint32_t daif; + __asm volatile ("mrs %x0, daif": "=r"(daif)); + __asm volatile ("msr daifset, #3"); + return daif; +} + +static inline void +intr_enable(void) +{ + enable_irq_daif(); +} + +static inline u_long +intr_disable(void) +{ + return disable_irq_daif_ret(); +} + +static inline void +intr_restore(u_long daif) +{ + restore_daif(daif); +} + +void cpu_halt(void); +int cpu_suspend_primary(void); +void cpu_resume_secondary(struct cpu_info *); + +extern void (*cpu_idle_cycle_fcn)(void); +extern void (*cpu_suspend_cycle_fcn)(void); + +void cpu_wfi(void); + +void delay (unsigned); +#define DELAY(x) delay(x) + +#endif /* _KERNEL */ + +#ifdef MULTIPROCESSOR +#include +#endif /* MULTIPROCESSOR */ + +#endif /* !_MACHINE_CPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/cpufunc.h b/lib/libc/include/aarch64-openbsd-none/machine/cpufunc.h new file mode 100644 index 000000000000..df2a91afc3bc --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/cpufunc.h @@ -0,0 +1,56 @@ +/* $OpenBSD: cpufunc.h,v 1.4 2018/05/02 15:17:30 patrick Exp $ */ +/*- + * Copyright (c) 2014 Andrew Turner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: head/sys/cpu/include/cpufunc.h 299683 2016-05-13 16:03:50Z andrew $ + */ + +#ifndef _MACHINE_CPUFUNC_H_ +#define _MACHINE_CPUFUNC_H_ + +#ifdef _KERNEL + +#include + +extern int64_t dcache_line_size; +extern int64_t icache_line_size; +extern int64_t idcache_line_size; +extern int64_t dczva_line_size; + +void cpu_setttb(int, paddr_t); +void cpu_tlb_flush(void); +void cpu_tlb_flush_asid(vaddr_t); +void cpu_tlb_flush_all_asid(vaddr_t); +void cpu_tlb_flush_asid_all(vaddr_t); +void cpu_icache_sync_range(vaddr_t, vsize_t); +void cpu_idcache_wbinv_range(vaddr_t, vsize_t); +void cpu_dcache_wbinv_range(vaddr_t, vsize_t); +void cpu_dcache_inv_range(vaddr_t, vsize_t); +void cpu_dcache_wb_range(vaddr_t, vsize_t); + +register_t smc_call(register_t, register_t, register_t, register_t); + +#endif /* _KERNEL */ +#endif /* _MACHINE_CPUFUNC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/db_machdep.h b/lib/libc/include/aarch64-openbsd-none/machine/db_machdep.h new file mode 100644 index 000000000000..d930085c2d44 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/db_machdep.h @@ -0,0 +1,80 @@ +/* $OpenBSD: db_machdep.h,v 1.8 2025/07/22 09:20:41 kettenis Exp $ */ +/* $NetBSD: db_machdep.h,v 1.5 2001/11/22 18:00:00 thorpej Exp $ */ + +/* + * Copyright (c) 1996 Scott K Stevens + * + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#ifndef _MACHINE_DB_MACHDEP_H_ +#define _MACHINE_DB_MACHDEP_H_ + +/* + * Machine-dependent defines for new kernel debugger. + */ + +#include +#include +#include +#include + +/* end of mangling */ + +typedef long db_expr_t; /* expression - signed */ + +typedef trapframe_t db_regs_t; + +extern db_regs_t ddb_regs; /* register state */ +#define DDB_REGS (&ddb_regs) + +#define PC_REGS(regs) ((vaddr_t)(regs)->tf_elr) +#define SET_PC_REGS(regs, value) (regs)->tf_elr = (register_t)(value) + +#define BKPT_INST 0xd4200000 /* breakpoint instruction */ +#define BKPT_SIZE (INSN_SIZE) /* size of breakpoint inst */ +#define BKPT_SET(inst) (BKPT_INST) + +#define db_clear_single_step(regs) ((regs)->tf_spsr &= ~PSR_SS) +#define db_set_single_step(regs) ((regs)->tf_spsr |= PSR_SS) + +#define IS_BREAKPOINT_TRAP(type, code) ((type) == EXCP_BRK) +#define IS_WATCHPOINT_TRAP(type, code) ((type) == EXCP_WATCHPT_EL1) + +// ALL BROKEN!!! +#define inst_trap_return(ins) ((ins) == 0 && (ins) == 1) +#define inst_return(ins) ((ins) == 0 && (ins) == 1) +#define inst_call(ins) ((ins) == 0 && (ins) == 1) + +#define DB_MACHINE_COMMANDS + +int db_ktrap(int, db_regs_t *); +void db_machine_init (void); + +#define DDB_STATE_NOT_RUNNING 0 +#define DDB_STATE_RUNNING 1 +#define DDB_STATE_EXITING 2 + +#endif /* _MACHINE_DB_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/disklabel.h b/lib/libc/include/aarch64-openbsd-none/machine/disklabel.h new file mode 100644 index 000000000000..6427b26604f1 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/disklabel.h @@ -0,0 +1,25 @@ +/* $OpenBSD: disklabel.h,v 1.1 2016/12/17 23:38:33 patrick Exp $ */ +/* + * Copyright (c) 2014 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_DISKLABEL_H_ +#define _MACHINE_DISKLABEL_H_ + +#define LABELSECTOR 1 /* sector containing label */ +#define LABELOFFSET 0 /* offset of label in sector */ +#define MAXPARTITIONS 16 /* number of partitions */ + +#endif /* _MACHINE_DISKLABEL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/efivar.h b/lib/libc/include/aarch64-openbsd-none/machine/efivar.h new file mode 100644 index 000000000000..659349b12b10 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/efivar.h @@ -0,0 +1,46 @@ +/* $OpenBSD: efivar.h,v 1.2 2024/07/10 10:53:55 kettenis Exp $ */ +/* + * Copyright (c) 2022 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_EFIVAR_H_ +#define _MACHINE_EFIVAR_H_ + +#include + +struct efi_softc { + struct device sc_dev; + struct pmap *sc_pm; + EFI_RUNTIME_SERVICES *sc_rs; + EFI_SYSTEM_RESOURCE_TABLE *sc_esrt; + u_long sc_psw; + + struct todr_chip_handle sc_todr; +}; + + +extern EFI_GET_VARIABLE efi_get_variable; +extern EFI_SET_VARIABLE efi_set_variable; +extern EFI_GET_NEXT_VARIABLE_NAME efi_get_next_variable_name; + +void efi_enter(struct efi_softc *); +void efi_leave(struct efi_softc *); + +extern label_t efi_jmpbuf; + +#define efi_enter_check(sc) (setjmp(&efi_jmpbuf) ? \ + (efi_leave(sc), EFAULT) : (efi_enter(sc), 0)) + +#endif /* _MACHINE_EFIVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/elf.h b/lib/libc/include/aarch64-openbsd-none/machine/elf.h new file mode 100644 index 000000000000..7af1436a51da --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/elf.h @@ -0,0 +1,121 @@ +/*- + * Copyright (c) 1996-1997 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_ELF_H_ +#define _MACHINE_ELF_H_ + +/* + * ELF definitions for the AArch64 architecture. + */ + +#ifdef _KERNEL +# define __HAVE_CPU_HWCAP +# define __HAVE_CPU_HWCAP2 +extern unsigned long hwcap, hwcap2; +#endif /* _KERNEL */ + +/* HWCAP */ +#define HWCAP_FP 0x00000001 +#define HWCAP_ASIMD 0x00000002 +#define HWCAP_EVTSTRM 0x00000004 +#define HWCAP_AES 0x00000008 +#define HWCAP_PMULL 0x00000010 +#define HWCAP_SHA1 0x00000020 +#define HWCAP_SHA2 0x00000040 +#define HWCAP_CRC32 0x00000080 +#define HWCAP_ATOMICS 0x00000100 +#define HWCAP_FPHP 0x00000200 +#define HWCAP_ASIMDHP 0x00000400 +#define HWCAP_CPUID 0x00000800 +#define HWCAP_ASIMDRDM 0x00001000 +#define HWCAP_JSCVT 0x00002000 +#define HWCAP_FCMA 0x00004000 +#define HWCAP_LRCPC 0x00008000 +#define HWCAP_DCPOP 0x00010000 +#define HWCAP_SHA3 0x00020000 +#define HWCAP_SM3 0x00040000 +#define HWCAP_SM4 0x00080000 +#define HWCAP_ASIMDDP 0x00100000 +#define HWCAP_SHA512 0x00200000 +#define HWCAP_SVE 0x00400000 +#define HWCAP_ASIMDFHM 0x00800000 +#define HWCAP_DIT 0x01000000 +#define HWCAP_USCAT 0x02000000 +#define HWCAP_ILRCPC 0x04000000 +#define HWCAP_FLAGM 0x08000000 +#define HWCAP_SSBS 0x10000000 +#define HWCAP_SB 0x20000000 +#define HWCAP_PACA 0x40000000 +#define HWCAP_PACG 0x80000000 + +/* HWCAP2 */ +#define HWCAP2_DCPODP 0x0000000000000001ul +#define HWCAP2_SVE2 0x0000000000000002ul +#define HWCAP2_SVEAES 0x0000000000000004ul +#define HWCAP2_SVEPMULL 0x0000000000000008ul +#define HWCAP2_SVEBITPERM 0x0000000000000010ul +#define HWCAP2_SVESHA3 0x0000000000000020ul +#define HWCAP2_SVESM4 0x0000000000000040ul +#define HWCAP2_FLAGM2 0x0000000000000080ul +#define HWCAP2_FRINT 0x0000000000000100ul +#define HWCAP2_SVEI8MM 0x0000000000000200ul +#define HWCAP2_SVEF32MM 0x0000000000000400ul +#define HWCAP2_SVEF64MM 0x0000000000000800ul +#define HWCAP2_SVEBF16 0x0000000000001000ul +#define HWCAP2_I8MM 0x0000000000002000ul +#define HWCAP2_BF16 0x0000000000004000ul +#define HWCAP2_DGH 0x0000000000008000ul +#define HWCAP2_RNG 0x0000000000010000ul +#define HWCAP2_BTI 0x0000000000020000ul +#define HWCAP2_MTE 0x0000000000040000ul +#define HWCAP2_ECV 0x0000000000080000ul +#define HWCAP2_AFP 0x0000000000100000ul +#define HWCAP2_RPRES 0x0000000000200000ul +#define HWCAP2_MTE3 0x0000000000400000ul +#define HWCAP2_SME 0x0000000000800000ul +#define HWCAP2_SME_I16I64 0x0000000001000000ul +#define HWCAP2_SME_F64F64 0x0000000002000000ul +#define HWCAP2_SME_I8I32 0x0000000004000000ul +#define HWCAP2_SME_F16F32 0x0000000008000000ul +#define HWCAP2_SME_B16F32 0x0000000010000000ul +#define HWCAP2_SME_F32F32 0x0000000020000000ul +#define HWCAP2_SME_FA64 0x0000000040000000ul +#define HWCAP2_WFXT 0x0000000080000000ul +#define HWCAP2_EBF16 0x0000000100000000ul +#define HWCAP2_SVE_EBF16 0x0000000200000000ul +#define HWCAP2_CSSC 0x0000000400000000ul +#define HWCAP2_RPRFM 0x0000000800000000ul +#define HWCAP2_SVE2P1 0x0000001000000000ul +#define HWCAP2_SME2 0x0000002000000000ul +#define HWCAP2_SME2P1 0x0000004000000000ul +#define HWCAP2_SME_I16I32 0x0000008000000000ul +#define HWCAP2_SME_BI32I32 0x0000010000000000ul +#define HWCAP2_SME_B16B16 0x0000020000000000ul +#define HWCAP2_SME_F16F16 0x0000040000000000ul +#define HWCAP2_MOPS 0x0000080000000000ul +#define HWCAP2_HBC 0x0000100000000000ul + +#endif /* !_MACHINE_ELF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/endian.h b/lib/libc/include/aarch64-openbsd-none/machine/endian.h new file mode 100644 index 000000000000..1de95e0c62b9 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/endian.h @@ -0,0 +1,29 @@ +/* $OpenBSD: endian.h,v 1.4 2024/05/07 14:26:48 naddy Exp $ */ + +/* + * Copyright (c) 2015 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_ENDIAN_H_ +#define _MACHINE_ENDIAN_H_ + +#define _BYTE_ORDER _LITTLE_ENDIAN +#define __STRICT_ALIGNMENT + +#ifndef __FROM_SYS__ENDIAN +#include +#endif + +#endif /* _MACHINE_ENDIAN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/exec.h b/lib/libc/include/aarch64-openbsd-none/machine/exec.h new file mode 100644 index 000000000000..61fcd9797a2f --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/exec.h @@ -0,0 +1,33 @@ +/* $OpenBSD: exec.h,v 1.3 2025/07/31 16:09:59 kettenis Exp $ */ +/* + * Copyright (c) 2014 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_EXEC_H_ +#define _MACHINE_EXEC_H_ + +#define __LDPGSZ 4096 + +#define ARCH_ELFSIZE 64 + +#define ELF_TARG_CLASS ELFCLASS64 +#define ELF_TARG_DATA ELFDATA2LSB +#define ELF_TARG_MACH EM_AARCH64 + +#ifdef _KERNEL +#define __HAVE_COREDUMP_NOTE_ELF_MD +#endif + +#endif \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/fdt.h b/lib/libc/include/aarch64-openbsd-none/machine/fdt.h new file mode 100644 index 000000000000..3ea355d9add5 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/fdt.h @@ -0,0 +1,59 @@ +/* $OpenBSD: fdt.h,v 1.7 2020/07/14 15:34:14 patrick Exp $ */ +/* + * Copyright (c) 2016 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __ARM_FDT_H__ +#define __ARM_FDT_H__ + +#define _ARM32_BUS_DMA_PRIVATE +#include + +struct fdt_attach_args { + const char *fa_name; + int fa_node; + bus_space_tag_t fa_iot; + bus_dma_tag_t fa_dmat; + struct fdt_reg *fa_reg; + int fa_nreg; + uint32_t *fa_intr; + int fa_nintr; + int fa_acells; + int fa_scells; +}; + +extern int stdout_node; +extern int stdout_speed; +extern bus_space_tag_t fdt_cons_bs_tag; + +void *fdt_find_cons(const char *); + +#define fdt_intr_enable arm_intr_enable +#define fdt_intr_establish arm_intr_establish_fdt +#define fdt_intr_establish_cpu arm_intr_establish_fdt_cpu +#define fdt_intr_establish_idx arm_intr_establish_fdt_idx +#define fdt_intr_establish_idx_cpu arm_intr_establish_fdt_idx_cpu +#define fdt_intr_establish_imap arm_intr_establish_fdt_imap +#define fdt_intr_establish_imap_cpu arm_intr_establish_fdt_imap_cpu +#define fdt_intr_establish_msi arm_intr_establish_fdt_msi +#define fdt_intr_establish_msi_cpu arm_intr_establish_fdt_msi_cpu +#define fdt_intr_disable arm_intr_disable +#define fdt_intr_disestablish arm_intr_disestablish_fdt +#define fdt_intr_get_parent arm_intr_get_parent +#define fdt_intr_parent_establish arm_intr_parent_establish_fdt +#define fdt_intr_parent_disestablish arm_intr_parent_disestablish_fdt +#define fdt_intr_register arm_intr_register_fdt + +#endif /* __ARM_FDT_H__ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/fenv.h b/lib/libc/include/aarch64-openbsd-none/machine/fenv.h new file mode 100644 index 000000000000..db0eb47817f5 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/fenv.h @@ -0,0 +1,95 @@ +/* $OpenBSD: fenv.h,v 1.3 2019/03/12 22:14:50 patrick Exp $ */ + +/* + * Copyright (c) 2011 Martynas Venckus + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_FENV_H_ +#define _MACHINE_FENV_H_ + +/* + * Each symbol representing a floating point exception expands to an integer + * constant expression with values, such that bitwise-inclusive ORs of _all + * combinations_ of the constants result in distinct values. + * + * We use such values that allow direct bitwise operations on FPU registers. + */ +#define FE_INVALID 0x01 +#define FE_DIVBYZERO 0x02 +#define FE_OVERFLOW 0x04 +#define FE_UNDERFLOW 0x08 +#define FE_INEXACT 0x10 +#define FE_DENORMAL 0x80 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * exception constants defined above. + */ +#define FE_ALL_EXCEPT (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | \ + FE_UNDERFLOW | FE_INEXACT | FE_DENORMAL) + +/* + * Each symbol representing the rounding direction, expands to an integer + * constant expression whose value is distinct non-negative value. + * + * We use such values that allow direct bitwise operations on FPU registers. + */ +#define FE_TONEAREST 0x0 +#define FE_UPWARD 0x1 +#define FE_DOWNWARD 0x2 +#define FE_TOWARDZERO 0x3 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * rounding direction constants defined above. + */ +#define _ROUND_MASK (FE_TONEAREST | FE_UPWARD | FE_DOWNWARD | \ + FE_TOWARDZERO) +#define _ROUND_SHIFT 22 + +/* + * fenv_t represents the entire floating-point environment. + */ +typedef unsigned long long fenv_t; + +/* + * The following constant represents the default floating-point environment + * (that is, the one installed at program startup) and has type pointer to + * const-qualified fenv_t. + * + * It can be used as an argument to the functions within the header + * that manage the floating-point environment, namely fesetenv() and + * feupdateenv(). + */ +__BEGIN_DECLS +extern fenv_t __fe_dfl_env; +__END_DECLS +#define FE_DFL_ENV ((const fenv_t *)&__fe_dfl_env) + +/* + * fexcept_t represents the floating-point status flags collectively, including + * any status the implementation associates with the flags. + * + * A floating-point status flag is a system variable whose value is set (but + * never cleared) when a floating-point exception is raised, which occurs as a + * side effect of exceptional floating-point arithmetic to provide auxiliary + * information. + * + * A floating-point control mode is a system variable whose value may be set by + * the user to affect the subsequent behavior of floating-point arithmetic. + */ +typedef unsigned long long fexcept_t; + +#endif /* !_MACHINE_FENV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/fpu.h b/lib/libc/include/aarch64-openbsd-none/machine/fpu.h new file mode 100644 index 000000000000..1c1afec45acf --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/fpu.h @@ -0,0 +1,29 @@ +/* $OpenBSD: fpu.h,v 1.2 2025/02/11 22:27:09 kettenis Exp $ */ +/* + * Copyright (c) 2022 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_FPU_H +#define _MACHINE_FPU_H + +void fpu_save(struct proc *); +void fpu_load(struct proc *); +void sve_load(struct proc *); +void fpu_drop(void); + +void fpu_kernel_enter(void); +void fpu_kernel_exit(void); + +#endif /* !_MACHINE_FPU_H */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/frame.h b/lib/libc/include/aarch64-openbsd-none/machine/frame.h new file mode 100644 index 000000000000..a169a9a1b9bd --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/frame.h @@ -0,0 +1,77 @@ +/* $OpenBSD: frame.h,v 1.3 2018/06/30 15:23:37 deraadt Exp $ */ +/* + * Copyright (c) 2016 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_FRAME_H_ +#define _MACHINE_FRAME_H_ + +#ifndef _LOCORE + +#include + + +/* + * Exception/Trap Stack Frame + */ +#define clockframe trapframe +typedef struct trapframe { + register_t tf_sp; + register_t tf_lr; + register_t tf_elr; + register_t tf_spsr; + register_t tf_x[30]; +} trapframe_t; + +/* + * pushed on stack for signal delivery + */ +struct sigframe { + int sf_signum; + struct sigcontext sf_sc; + siginfo_t sf_si; +}; + +/* + * System stack frames. + */ + +/* + * Stack frame inside cpu_switch() + */ + +struct switchframe { + register_t sf_x19; + register_t sf_x20; + register_t sf_x21; + register_t sf_x22; + register_t sf_x23; + register_t sf_x24; + register_t sf_x25; + register_t sf_x26; + register_t sf_x27; + register_t sf_x28; + register_t sf_x29; + register_t sf_lr; +}; + +struct callframe { + struct callframe *f_frame; + register_t f_lr; +}; + +#endif /* !_LOCORE */ + +#endif /* _MACHINE_FRAME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/hypervisor.h b/lib/libc/include/aarch64-openbsd-none/machine/hypervisor.h new file mode 100644 index 000000000000..71dce49532b1 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/hypervisor.h @@ -0,0 +1,88 @@ +/* $OpenBSD: hypervisor.h,v 1.5 2025/02/11 22:27:09 kettenis Exp $ */ +/*- + * Copyright (c) 2013, 2014 Andrew Turner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: head/sys/arm64/include/hypervisor.h 281494 2015-04-13 14:43:10Z andrew $ + */ + +#ifndef _MACHINE_HYPERVISOR_H_ +#define _MACHINE_HYPERVISOR_H_ + +/* + * These registers are only useful when in hypervisor context, + * e.g. specific to EL2, or controlling the hypervisor. + */ + +/* + * Architecture feature trap register + */ +#define CPTR_RES0 0x7fefc800 +#define CPTR_RES1 0x000032ff +#define CPTR_TFP 0x00000400 +#define CPTR_TTA 0x00100000 +#define CPTR_TCPAC 0x80000000 + +/* + * Hypervisor Config Register + */ + +#define HCR_VM 0x0000000000000001 +#define HCR_SWIO 0x0000000000000002 +#define HCR_PTW 0x0000000000000004 +#define HCR_FMO 0x0000000000000008 +#define HCR_IMO 0x0000000000000010 +#define HCR_AMO 0x0000000000000020 +#define HCR_VF 0x0000000000000040 +#define HCR_VI 0x0000000000000080 +#define HCR_VSE 0x0000000000000100 +#define HCR_FB 0x0000000000000200 +#define HCR_BSU_MASK 0x0000000000000c00 +#define HCR_DC 0x0000000000001000 +#define HCR_TWI 0x0000000000002000 +#define HCR_TWE 0x0000000000004000 +#define HCR_TID0 0x0000000000008000 +#define HCR_TID1 0x0000000000010000 +#define HCR_TID2 0x0000000000020000 +#define HCR_TID3 0x0000000000040000 +#define HCR_TSC 0x0000000000080000 +#define HCR_TIDCP 0x0000000000100000 +#define HCR_TACR 0x0000000000200000 +#define HCR_TSW 0x0000000000400000 +#define HCR_TPC 0x0000000000800000 +#define HCR_TPU 0x0000000001000000 +#define HCR_TTLB 0x0000000002000000 +#define HCR_TVM 0x0000000004000000 +#define HCR_TGE 0x0000000008000000 +#define HCR_TDZ 0x0000000010000000 +#define HCR_HCD 0x0000000020000000 +#define HCR_TRVM 0x0000000040000000 +#define HCR_RW 0x0000000080000000 +#define HCR_CD 0x0000000100000000 +#define HCR_ID 0x0000000200000000 +#define HCR_E2H 0x0000000400000000 +#define HCR_APK 0x0000010000000000 +#define HCR_API 0x0000020000000000 + +#endif \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/ieee.h b/lib/libc/include/aarch64-openbsd-none/machine/ieee.h new file mode 100644 index 000000000000..d5f061fd5411 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/ieee.h @@ -0,0 +1,148 @@ +/* $OpenBSD: ieee.h,v 1.3 2017/04/16 16:14:37 kettenis Exp $ */ +/* $NetBSD: ieee.h,v 1.1 1996/09/30 16:34:25 ws Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ieee.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * ieee.h defines the machine-dependent layout of the machine's IEEE + * floating point. It does *not* define (yet?) any of the rounding + * mode bits, exceptions, and so forth. + */ + +/* + * Define the number of bits in each fraction and exponent. + * + * k k+1 + * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented + * + * (-exp_bias+1) + * as fractions that look like 0.fffff x 2 . This means that + * + * -126 + * the number 0.10000 x 2 , for instance, is the same as the normalized + * + * -127 -128 + * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero + * + * -129 + * in the fraction; to represent 2 , we need two, and so on. This + * + * (-exp_bias-fracbits+1) + * implies that the smallest denormalized number is 2 + * + * for whichever format we are talking about: for single precision, for + * + * -126 -149 + * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and + * + * -149 == -127 - 23 + 1. + */ +#define SNG_EXPBITS 8 +#define SNG_FRACBITS 23 + +#define DBL_EXPBITS 11 +#define DBL_FRACHBITS 20 +#define DBL_FRACLBITS 32 +#define DBL_FRACBITS 52 + +#define EXT_EXPBITS 15 +#define EXT_FRACHBITS 16 +#define EXT_FRACHMBITS 32 +#define EXT_FRACLMBITS 32 +#define EXT_FRACLBITS 32 +#define EXT_FRACBITS 112 + +#define EXT_IMPLICIT_NBIT + +#define EXT_TO_ARRAY32(p, a) do { \ + (a)[0] = (uint32_t)(p)->ext_fracl; \ + (a)[1] = (uint32_t)(p)->ext_fraclm; \ + (a)[2] = (uint32_t)(p)->ext_frachm; \ + (a)[3] = (uint32_t)(p)->ext_frach; \ +} while(0) + +struct ieee_single { + u_int sng_frac:23; + u_int sng_exp:8; + u_int sng_sign:1; +}; + +struct ieee_double { + u_int dbl_fracl; + u_int dbl_frach:20; + u_int dbl_exp:11; + u_int dbl_sign:1; +}; + +struct ieee_ext { + u_int ext_fracl; + u_int ext_fraclm; + u_int ext_frachm; + u_int ext_frach:16; + u_int ext_exp:15; + u_int ext_sign:1; +}; + +/* + * Floats whose exponent is in [1..INFNAN) (of whatever type) are + * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. + * Floats whose exponent is zero are either zero (iff all fraction + * bits are zero) or subnormal values. + * + * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its + * high fraction; if the bit is set, it is a `quiet NaN'. + */ +#define SNG_EXP_INFNAN 255 +#define DBL_EXP_INFNAN 2047 +#define EXT_EXP_INFNAN 32767 + +#if 0 +#define SNG_QUIETNAN (1 << 22) +#define DBL_QUIETNAN (1 << 19) +#define EXT_QUIETNAN (1 << 15) +#endif + +/* + * Exponent biases. + */ +#define SNG_EXP_BIAS 127 +#define DBL_EXP_BIAS 1023 +#define EXT_EXP_BIAS 16383 \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/ieeefp.h b/lib/libc/include/aarch64-openbsd-none/machine/ieeefp.h new file mode 100644 index 000000000000..b2c302da9a4f --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/ieeefp.h @@ -0,0 +1,25 @@ +/* $OpenBSD: ieeefp.h,v 1.2 2021/05/01 20:07:01 kettenis Exp $ */ + +/* + * Based on ieeefp.h written by J.T. Conklin, Apr 28, 1995 + * Public domain. + */ + +#ifndef _MACHINE_IEEEFP_H_ +#define _MACHINE_IEEEFP_H_ + +typedef int fp_except; +#define FP_X_INV 0x01 /* invalid operation exception */ +#define FP_X_DZ 0x02 /* divide-by-zero exception */ +#define FP_X_OFL 0x04 /* overflow exception */ +#define FP_X_UFL 0x08 /* underflow exception */ +#define FP_X_IMP 0x10 /* imprecise (loss of precision) */ + +typedef enum { + FP_RN=0, /* round to nearest representable number */ + FP_RP=1, /* round toward positive infinity */ + FP_RM=2, /* round toward negative infinity */ + FP_RZ=3 /* round to zero (truncate) */ +} fp_rnd; + +#endif /* _MACHINE_IEEEFP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/intr.h b/lib/libc/include/aarch64-openbsd-none/machine/intr.h new file mode 100644 index 000000000000..8dbf0d06f8f8 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/intr.h @@ -0,0 +1,226 @@ +/* $OpenBSD: intr.h,v 1.25 2025/06/30 14:19:20 kettenis Exp $ */ + +/* + * Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _MACHINE_INTR_H_ +#define _MACHINE_INTR_H_ + +/* + * The interrupt level ipl is a logical level; per-platform interrupt + * code will turn it into the appropriate hardware interrupt masks + * values. + * + * Interrupt sources on the CPU are kept enabled regardless of the + * current ipl value; individual hardware sources interrupting while + * logically masked are masked on the fly, remembered as pending, and + * unmasked at the first splx() opportunity. + */ +#ifdef _KERNEL + +/* Interrupt priority `levels'; not mutually exclusive. */ +#define IPL_NONE 0 /* nothing */ +#define IPL_SOFTCLOCK 2 /* soft clock interrupts */ +#define IPL_SOFTNET 3 /* soft network interrupts */ +#define IPL_SOFTTTY 4 /* soft terminal interrupts */ +#define IPL_BIO 5 /* block I/O */ +#define IPL_NET 6 /* network */ +#define IPL_TTY 7 /* terminal */ +#define IPL_VM 8 /* memory allocation */ +#define IPL_AUDIO 9 /* audio */ +#define IPL_CLOCK 10 /* clock */ +#define IPL_SCHED IPL_CLOCK +#define IPL_STATCLOCK IPL_CLOCK +#define IPL_HIGH 11 /* everything */ +#define IPL_IPI 12 /* interprocessor interrupt */ +#define NIPL 13 /* number of levels */ + +#define IPL_MPFLOOR IPL_TTY +/* Interrupt priority 'flags'. */ +#define IPL_IRQMASK 0xf /* priority only */ +#define IPL_FLAGMASK 0xf00 /* flags only*/ +#define IPL_MPSAFE 0x100 /* 'mpsafe' interrupt, no kernel lock */ +#define IPL_WAKEUP 0x200 /* 'wakeup' interrupt */ + +/* Interrupt sharing types. */ +#define IST_NONE 0 /* none */ +#define IST_PULSE 1 /* pulsed */ +#define IST_EDGE 2 /* edge-triggered */ +#define IST_LEVEL 3 /* level-triggered */ + +#define IST_LEVEL_LOW IST_LEVEL +#define IST_LEVEL_HIGH 4 +#define IST_EDGE_FALLING IST_EDGE +#define IST_EDGE_RISING 5 +#define IST_EDGE_BOTH 6 + +#define __USE_MI_SOFTINTR + +#include + +#ifndef _LOCORE +#include + +void softintr(int); + +int splraise(int); +int spllower(int); +void splx(int); + +void arm_do_pending_intr(int); +void arm_set_intr_handler(int (*)(int), int (*)(int), void (*)(int), + void (*)(int), void (*)(void *), void (*)(void *), + void (*)(void), void (*)(void)); + +struct machine_intr_handle { + struct interrupt_controller *ih_ic; + void *ih_ih; +}; + +struct arm_intr_func { + int (*raise)(int); + int (*lower)(int); + void (*x)(int); + void (*setipl)(int); + void (*enable_wakeup)(void); + void (*disable_wakeup)(void); +}; + +extern struct arm_intr_func arm_intr_func; + +#define splraise(cpl) (arm_intr_func.raise(cpl)) +#define _splraise(cpl) (arm_intr_func.raise(cpl)) +#define spllower(cpl) (arm_intr_func.lower(cpl)) +#define splx(cpl) (arm_intr_func.x(cpl)) + +#define splsoftclock() splraise(IPL_SOFTCLOCK) +#define splsoftnet() splraise(IPL_SOFTNET) +#define splsofttty() splraise(IPL_SOFTTTY) +#define splbio() splraise(IPL_BIO) +#define splnet() splraise(IPL_NET) +#define spltty() splraise(IPL_TTY) +#define splvm() splraise(IPL_VM) +#define splaudio() splraise(IPL_AUDIO) +#define splclock() splraise(IPL_CLOCK) +#define splsched() splraise(IPL_SCHED) +#define splstatclock() splraise(IPL_STATCLOCK) +#define splhigh() splraise(IPL_HIGH) + +#define spl0() spllower(IPL_NONE) + +void intr_barrier(void *); +void intr_set_wakeup(void *); +void intr_enable_wakeup(void); +void intr_disable_wakeup(void); + +void arm_init_smask(void); /* XXX */ +extern uint32_t arm_smask[NIPL]; + +/* XXX - this is probably the wrong location for this */ +void arm_clock_register(void (*)(void), void (*)(u_int), void (*)(int), + void (*)(void)); + +struct cpu_info; + +struct interrupt_controller { + int ic_node; + void *ic_cookie; + void *(*ic_establish)(void *, int *, int, struct cpu_info *, + int (*)(void *), void *, char *); + void *(*ic_establish_msi)(void *, uint64_t *, uint64_t *, int, + struct cpu_info *, int (*)(void *), void *, char *); + void (*ic_disestablish)(void *); + void (*ic_enable)(void *); + void (*ic_disable)(void *); + void (*ic_route)(void *, int, struct cpu_info *); + void (*ic_cpu_enable)(void); + void (*ic_barrier)(void *); + void (*ic_set_wakeup)(void *); + + LIST_ENTRY(interrupt_controller) ic_list; + uint32_t ic_phandle; + uint32_t ic_cells; + uint32_t ic_gic_its_id; +}; + +void arm_intr_init_fdt(void); +void arm_intr_register_fdt(struct interrupt_controller *); +void *arm_intr_establish_fdt(int, int, int (*)(void *), + void *, char *); +void *arm_intr_establish_fdt_cpu(int, int, struct cpu_info *, + int (*)(void *), void *, char *); +void *arm_intr_establish_fdt_idx(int, int, int, int (*)(void *), + void *, char *); +void *arm_intr_establish_fdt_idx_cpu(int, int, int, struct cpu_info *, + int (*)(void *), void *, char *); +void *arm_intr_establish_fdt_imap(int, int *, int, int, int (*)(void *), + void *, char *); +void *arm_intr_establish_fdt_imap_cpu(int, int *, int, int, + struct cpu_info *, int (*)(void *), void *, char *); +void *arm_intr_establish_fdt_msi(int, uint64_t *, uint64_t *, int, + int (*)(void *), void *, char *); +void *arm_intr_establish_fdt_msi_cpu(int, uint64_t *, uint64_t *, int, + struct cpu_info *, int (*)(void *), void *, char *); +void arm_intr_disestablish_fdt(void *); +void arm_intr_enable(void *); +void arm_intr_disable(void *); +void arm_intr_route(void *, int, struct cpu_info *); +void arm_intr_cpu_enable(void); +void *arm_intr_parent_establish_fdt(void *, int *, int, + struct cpu_info *ci, int (*)(void *), void *, char *); +void arm_intr_parent_disestablish_fdt(void *); + +void arm_send_ipi(struct cpu_info *, int); +extern void (*intr_send_ipi_func)(struct cpu_info *, int); + +#define ARM_IPI_NOP 0 +#define ARM_IPI_DDB 1 +#define ARM_IPI_HALT 2 + +#ifdef DIAGNOSTIC +/* + * Although this function is implemented in MI code, it must be in this MD + * header because we don't want this header to include MI includes. + */ +void splassert_fail(int, int, const char *); +extern int splassert_ctl; +void arm_splassert_check(int, const char *); +#define splassert(__wantipl) do { \ + if (splassert_ctl > 0) { \ + arm_splassert_check(__wantipl, __func__); \ + } \ +} while (0) +#define splsoftassert(wantipl) splassert(wantipl) +#else +#define splassert(wantipl) do { /* nothing */ } while (0) +#define splsoftassert(wantipl) do { /* nothing */ } while (0) +#endif + +#endif /* ! _LOCORE */ + +#endif /* _KERNEL */ + +#endif /* _MACHINE_INTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/kcore.h b/lib/libc/include/aarch64-openbsd-none/machine/kcore.h new file mode 100644 index 000000000000..a65c7257a0f4 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/kcore.h @@ -0,0 +1,15 @@ +/* $OpenBSD: kcore.h,v 1.1 2016/12/17 23:38:33 patrick Exp $ */ +/* public domain */ + +/* Make sure this is larger than DRAM_BLOCKS on all arm-based platforms */ +#define NPHYS_RAM_SEGS 8 + +typedef struct cpu_kcore_hdr { + u_int64_t kernelbase; /* value of KERNEL_BASE */ + u_int64_t kerneloffs; /* offset of kernel in RAM */ + u_int64_t staticsize; /* size of contiguous mapping */ + u_int64_t pmap_kernel_l1; /* pmap_kernel()->pm_l1 */ + u_int64_t pmap_kernel_l2; /* pmap_kernel()->pm_l2 */ + u_int64_t reserved[11]; + phys_ram_seg_t ram_segs[NPHYS_RAM_SEGS]; +} cpu_kcore_hdr_t; \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/limits.h b/lib/libc/include/aarch64-openbsd-none/machine/limits.h new file mode 100644 index 000000000000..491b57a52aa8 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/limits.h @@ -0,0 +1,56 @@ +/* $OpenBSD: limits.h,v 1.1 2016/12/17 23:38:33 patrick Exp $ */ +/* $NetBSD: limits.h,v 1.4 2003/04/28 23:16:18 bjh21 Exp $ */ + +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)limits.h 7.2 (Berkeley) 6/28/90 + */ + +#ifndef _MACHINE_LIMITS_H_ +#define _MACHINE_LIMITS_H_ + +#include + +#if __POSIX_VISIBLE || __XPG_VISIBLE +#ifndef SIZE_MAX +#define SIZE_MAX ULONG_MAX /* max value for a size_t */ +#endif +#define SSIZE_MAX LONG_MAX /* max value for a ssize_t */ +#endif + +#if __BSD_VISIBLE +#define SIZE_T_MAX ULONG_MAX /* max value for a size_t (historic) */ + +#define UQUAD_MAX 0xffffffffffffffffULL /* max unsigned quad */ +#define QUAD_MAX 0x7fffffffffffffffLL /* max signed quad */ +#define QUAD_MIN (-0x7fffffffffffffffLL-1) /* min signed quad */ + +#endif /* __BSD_VISIBLE */ + +#endif /* _MACHINE_LIMITS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/loadfile_machdep.h b/lib/libc/include/aarch64-openbsd-none/machine/loadfile_machdep.h new file mode 100644 index 000000000000..59761f8b7e74 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/loadfile_machdep.h @@ -0,0 +1,53 @@ +/* $OpenBSD: loadfile_machdep.h,v 1.2 2019/04/10 04:17:34 deraadt Exp $ */ +/* $NetBSD: loadfile_machdep.h,v 1.1 1999/04/29 03:17:12 tsubai Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define BOOT_ELF +#define ELFSIZE 64 + +#define LOAD_KERNEL (LOAD_ALL & ~LOAD_TEXTA) +#define COUNT_KERNEL (COUNT_ALL & ~COUNT_TEXTA) + +extern u_long efi_loadaddr; +#define LOADADDR(a) (((((u_long)(a)) + offset)&0x7fffffffff) + \ + efi_loadaddr) +#define ALIGNENTRY(a) ((u_long)(a)) +#define READ(f, b, c) read((f), (void *)LOADADDR(b), (c)) +#define BCOPY(s, d, c) memcpy((void *)LOADADDR(d), (void *)(s), (c)) +#define BZERO(d, c) memset((void *)LOADADDR(d), 0, (c)) +#define WARN(a) (void)(printf a, \ + printf((errno ? ": %s\n" : "\n"), \ + strerror(errno))) +#define PROGRESS(a) (void) printf a +#define ALLOC(a) alloc(a) +#define FREE(a, b) free(a, b) + +void run_loadfile(uint64_t *, int); \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/mplock.h b/lib/libc/include/aarch64-openbsd-none/machine/mplock.h new file mode 100644 index 000000000000..36a2b125ab75 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/mplock.h @@ -0,0 +1,10 @@ +/* $OpenBSD: mplock.h,v 1.3 2018/01/05 17:42:35 kettenis Exp $ */ + +/* public domain */ + +#ifndef _MACHINE_MPLOCK_H_ +#define _MACHINE_MPLOCK_H_ + +#define __USE_MI_MPLOCK + +#endif /* !_MACHINE_MPLOCK_H */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/mutex.h b/lib/libc/include/aarch64-openbsd-none/machine/mutex.h new file mode 100644 index 000000000000..f5115c3084e8 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/mutex.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mutex.h,v 1.5 2018/01/25 15:06:29 mpi Exp $ */ + +#define __USE_MI_MUTEX \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/openpromio.h b/lib/libc/include/aarch64-openbsd-none/machine/openpromio.h new file mode 100644 index 000000000000..3ad914911617 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/openpromio.h @@ -0,0 +1,57 @@ +/* $OpenBSD: openpromio.h,v 1.1 2017/01/23 12:34:06 kettenis Exp $ */ +/* $NetBSD: openpromio.h,v 1.1.1.1 1998/06/20 04:58:52 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)openpromio.h 8.1 (Berkeley) 6/11/93 + */ + +struct opiocdesc { + int op_nodeid; /* passed or returned node id */ + int op_namelen; /* length of op_name */ + char *op_name; /* pointer to field name */ + int op_buflen; /* length of op_buf (value-result) */ + char *op_buf; /* pointer to field value */ +}; + +#define OPIOCGET _IOWR('O', 1, struct opiocdesc) /* get openprom field */ +#define OPIOCSET _IOW('O', 2, struct opiocdesc) /* set openprom field */ +#define OPIOCNEXTPROP _IOWR('O', 3, struct opiocdesc) /* get next property */ +#define OPIOCGETOPTNODE _IOR('O', 4, int) /* get openprom field */ +#define OPIOCGETNEXT _IOWR('O', 5, int) /* get next node of node */ +#define OPIOCGETCHILD _IOWR('O', 6, int) /* get first child of node */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/param.h b/lib/libc/include/aarch64-openbsd-none/machine/param.h new file mode 100644 index 000000000000..0d7eb0c7964f --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/param.h @@ -0,0 +1,81 @@ +/* $OpenBSD: param.h,v 1.8 2025/07/07 18:33:36 kettenis Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ + +#ifdef _KERNEL +#ifndef _LOCORE +#include +#endif +#endif + +#define _MACHINE arm64 +#define MACHINE "arm64" +#define _MACHINE_ARCH aarch64 +#define MACHINE_ARCH "aarch64" +#define MID_MACHINE MID_ARM64 + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define PAGE_MASK (PAGE_SIZE - 1) + +#define KERNBASE 0xffffff8000000000ULL /* start of kernel virtual space */ + +#ifdef _KERNEL + +#define NBPG PAGE_SIZE /* bytes/page */ +#define PGSHIFT PAGE_SHIFT /* LOG2(PAGE_SIZE) */ +#define PGOFSET PAGE_MASK /* byte offset into page */ + +#define UPAGES 6 /* pages of u-area */ +#define USPACE (UPAGES * PAGE_SIZE) /* total size of u-area */ +#define USPACE_ALIGN 0 /* u-area alignment 0-none */ +#define __HAVE_USPACE_GUARD + +#define NMBCLUSTERS (64 * 1024) /* max cluster allocation */ + +#ifndef MSGBUFSIZE +#define MSGBUFSIZE (16 * PAGE_SIZE) /* default message buffer size */ +#endif + +#define STACKALIGNBYTES (16 - 1) +#define STACKALIGN(p) ((u_long)(p) &~ STACKALIGNBYTES) + +#define __HAVE_ACPI +#define __HAVE_FDT + +#endif /* _KERNEL */ + +#endif /* _MACHINE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/pcb.h b/lib/libc/include/aarch64-openbsd-none/machine/pcb.h new file mode 100644 index 000000000000..9e4880b7a8ae --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/pcb.h @@ -0,0 +1,45 @@ +/* $OpenBSD: pcb.h,v 1.8 2025/02/24 13:18:01 jsg Exp $ */ +/* + * Copyright (c) 2016 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef _MACHINE_PCB_H_ +#define _MACHINE_PCB_H_ + +#include +#include + +struct trapframe; + +/* + * Warning certain fields must be within 256 bytes of the beginning + * of this structure. + */ +struct pcb { + u_int pcb_flags; +#define PCB_FPU 0x00000001 /* Process had FPU initialized */ +#define PCB_SINGLESTEP 0x00000002 /* Single step process */ +#define PCB_SVE 0x00000004 /* Process had SVE initialized */ + struct trapframe *pcb_tf; + + register_t pcb_sp; /* stack pointer of switchframe */ + + caddr_t pcb_onfault; /* On fault handler */ + struct fpreg pcb_fpstate; /* Floating Point state */ + __uint16_t pcb_sve_p[16]; /* SVE predicate registers */ + __uint16_t pcb_sve_ffr; /* SVE first fault register */ + + void *pcb_tcb; +}; +#endif /* _MACHINE_PCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/pci_machdep.h b/lib/libc/include/aarch64-openbsd-none/machine/pci_machdep.h new file mode 100644 index 000000000000..fec001a5f434 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/pci_machdep.h @@ -0,0 +1,145 @@ +/* $OpenBSD: pci_machdep.h,v 1.13 2025/01/23 11:24:34 kettenis Exp $ */ + +/* + * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +typedef struct machine_pci_chipset *pci_chipset_tag_t; +typedef uint64_t pcitag_t; + +#define PCITAG_NODE(x) ((x) >> 32) +#define PCITAG_OFFSET(x) ((x) & 0xffffffff) + +/* Supported interrupt types. */ +#define PCI_NONE 0 +#define PCI_INTX 1 +#define PCI_MSI 2 +#define PCI_MSIX 3 + +typedef struct { + pci_chipset_tag_t ih_pc; + pcitag_t ih_tag; + int ih_intrpin; + int ih_type; + bus_dma_tag_t ih_dmat; +} pci_intr_handle_t; + +struct pci_attach_args; + +/* + * Machine-specific PCI structure and type definitions. + * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE. + */ +struct machine_pci_chipset { + void *pc_conf_v; + void (*pc_attach_hook)(struct device *, + struct device *, struct pcibus_attach_args *); + int (*pc_bus_maxdevs)(void *, int); + pcitag_t (*pc_make_tag)(void *, int, int, int); + void (*pc_decompose_tag)(void *, pcitag_t, int *, + int *, int *); + int (*pc_conf_size)(void *, pcitag_t); + pcireg_t (*pc_conf_read)(void *, pcitag_t, int); + void (*pc_conf_write)(void *, pcitag_t, int, pcireg_t); + int (*pc_probe_device_hook)(void *, struct pci_attach_args *); + + void *pc_intr_v; + int (*pc_intr_map)(struct pci_attach_args *, + pci_intr_handle_t *); + int (*pc_intr_map_msi)(struct pci_attach_args *, + pci_intr_handle_t *); + int (*pc_intr_map_msivec)(struct pci_attach_args *, + int, pci_intr_handle_t *); + int (*pc_intr_map_msix)(struct pci_attach_args *, + int, pci_intr_handle_t *); + const char *(*pc_intr_string)(void *, pci_intr_handle_t); + void *(*pc_intr_establish)(void *, pci_intr_handle_t, + int, struct cpu_info *, int (*)(void *), void *, + char *); + void (*pc_intr_disestablish)(void *, void *); +}; + +/* + * Functions provided to machine-independent PCI code. + */ +#define pci_attach_hook(p, s, pba) \ + (*(pba)->pba_pc->pc_attach_hook)((p), (s), (pba)) +#define pci_bus_maxdevs(c, b) \ + (*(c)->pc_bus_maxdevs)((c)->pc_conf_v, (b)) +#define pci_make_tag(c, b, d, f) \ + (*(c)->pc_make_tag)((c)->pc_conf_v, (b), (d), (f)) +#define pci_decompose_tag(c, t, bp, dp, fp) \ + (*(c)->pc_decompose_tag)((c)->pc_conf_v, (t), (bp), (dp), (fp)) +#define pci_conf_size(c, t) \ + (*(c)->pc_conf_size)((c)->pc_conf_v, (t)) +#define pci_conf_read(c, t, r) \ + (*(c)->pc_conf_read)((c)->pc_conf_v, (t), (r)) +#define pci_conf_write(c, t, r, v) \ + (*(c)->pc_conf_write)((c)->pc_conf_v, (t), (r), (v)) +#define pci_probe_device_hook(c, a) \ + (*(c)->pc_probe_device_hook)((c)->pc_conf_v, (a)) +#define pci_intr_map(c, ihp) \ + (*(c)->pa_pc->pc_intr_map)((c), (ihp)) +#define pci_intr_map_msi(c, ihp) \ + (*(c)->pa_pc->pc_intr_map_msi)((c), (ihp)) +#define pci_intr_map_msivec(c, vec, ihp) \ + (*(c)->pa_pc->pc_intr_map_msivec)((c), (vec), (ihp)) +#define pci_intr_map_msix(c, vec, ihp) \ + (*(c)->pa_pc->pc_intr_map_msix)((c), (vec), (ihp)) +#define pci_intr_string(c, ih) \ + (*(c)->pc_intr_string)((c)->pc_intr_v, (ih)) +#define pci_intr_establish(c, ih, l, h, a, nm) \ + (*(c)->pc_intr_establish)((c)->pc_intr_v, (ih), (l), NULL, (h), (a),\ + (nm)) +#define pci_intr_establish_cpu(c, ih, l, ci, h, a, nm) \ + (*(c)->pc_intr_establish)((c)->pc_intr_v, (ih), (l), (ci), (h), (a),\ + (nm)) +#define pci_intr_disestablish(c, iv) \ + (*(c)->pc_intr_disestablish)((c)->pc_intr_v, (iv)) + +#define pci_min_powerstate(c, t) (PCI_PMCSR_STATE_D3) +#define pci_set_powerstate_md(c, t, s, p) + +#define pci_dev_postattach(a, b) + +void pci_mcfg_init(bus_space_tag_t, bus_addr_t, int, int, int); +pci_chipset_tag_t pci_lookup_segment(int, int); + +int pci_intr_enable_msivec(struct pci_attach_args *, int); + +void pci_msi_enable(pci_chipset_tag_t, pcitag_t, bus_addr_t, uint32_t); +void pci_msix_enable(pci_chipset_tag_t, pcitag_t, bus_space_tag_t, + int, bus_addr_t, uint32_t); +int _pci_intr_map_msi(struct pci_attach_args *, pci_intr_handle_t *); +int _pci_intr_map_msivec(struct pci_attach_args *, int, + pci_intr_handle_t *); +int _pci_intr_map_msix(struct pci_attach_args *, int, pci_intr_handle_t *); + +#define __HAVE_PCI_MSIX + +int pci_msix_table_map(pci_chipset_tag_t, pcitag_t, + bus_space_tag_t, bus_space_handle_t *); +void pci_msix_table_unmap(pci_chipset_tag_t, pcitag_t, + bus_space_tag_t, bus_space_handle_t); \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/pmap.h b/lib/libc/include/aarch64-openbsd-none/machine/pmap.h new file mode 100644 index 000000000000..5f4d7bf5e156 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/pmap.h @@ -0,0 +1,143 @@ +/* $OpenBSD: pmap.h,v 1.29 2025/05/21 09:42:59 kettenis Exp $ */ +/* + * Copyright (c) 2008,2009,2014 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef _ARM64_PMAP_H_ +#define _ARM64_PMAP_H_ + +#ifndef _LOCORE +#include +#include +#include +#endif + + +/* V->P mapping data */ +#define VP_IDX0_CNT 512 +#define VP_IDX0_MASK (VP_IDX0_CNT-1) +#define VP_IDX0_POS 39 +#define VP_IDX1_CNT 512 +#define VP_IDX1_MASK (VP_IDX1_CNT-1) +#define VP_IDX1_POS 30 +#define VP_IDX2_CNT 512 +#define VP_IDX2_MASK (VP_IDX2_CNT-1) +#define VP_IDX2_POS 21 +#define VP_IDX3_CNT 512 +#define VP_IDX3_MASK (VP_IDX3_CNT-1) +#define VP_IDX3_POS 12 + +/* cache flags */ +#define PMAP_CACHE_CI (PMAP_MD0) /* cache inhibit */ +#define PMAP_CACHE_WT (PMAP_MD1) /* writethru */ +#define PMAP_CACHE_WB (PMAP_MD1|PMAP_MD0) /* writeback */ +#define PMAP_CACHE_DEV_NGNRNE (PMAP_MD2) /* device nGnRnE */ +#define PMAP_CACHE_DEV_NGNRE (PMAP_MD2|PMAP_MD0) /* device nGnRE */ +#define PMAP_CACHE_BITS (PMAP_MD0|PMAP_MD1|PMAP_MD2) + +#define PTED_VA_MANAGED_M (PMAP_MD3) +#define PTED_VA_WIRED_M (PMAP_MD3 << 1) + + +#if defined(_KERNEL) && !defined(_LOCORE) +/* + * Pmap stuff + */ + +typedef struct pmap *pmap_t; + +struct pmap { + struct mutex pm_mtx; + union { + struct pmapvp0 *l0; /* virtual to physical table 4 lvl */ + struct pmapvp1 *l1; /* virtual to physical table 3 lvl */ + } pm_vp; + uint64_t pm_pt0pa; + uint64_t pm_asid; + uint64_t pm_guarded; + int have_4_level_pt; + int pm_privileged; + volatile int pm_active; + int pm_refs; /* ref count */ + struct pmap_statistics pm_stats; /* pmap statistics */ + uint64_t pm_apiakey[2]; + uint64_t pm_apdakey[2]; + uint64_t pm_apibkey[2]; + uint64_t pm_apdbkey[2]; + uint64_t pm_apgakey[2]; +}; + +#define PMAP_PA_MASK ~((paddr_t)PAGE_MASK) /* to remove the flags */ +#define PMAP_NOCACHE 0x1 /* non-cacheable memory */ +#define PMAP_DEVICE 0x2 /* device memory */ +#define PMAP_WC PMAP_DEVICE + +#define PG_PMAP_MOD PG_PMAP0 +#define PG_PMAP_REF PG_PMAP1 +#define PG_PMAP_EXE PG_PMAP2 + +// [NCPUS] +extern paddr_t zero_page; +extern paddr_t copy_src_page; +extern paddr_t copy_dst_page; + +void pagezero_cache(vaddr_t); + +extern struct pmap kernel_pmap_; +#define pmap_kernel() (&kernel_pmap_) +#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) +#define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count) + +vaddr_t pmap_bootstrap(long kvo, paddr_t lpt1, long kernelstart, + long kernelend, long ram_start, long ram_end); +void pmap_postinit(void); +void pmap_init_percpu(void); + +void pmap_kenter_cache(vaddr_t va, paddr_t pa, vm_prot_t prot, int cacheable); +void pmap_page_ro(pmap_t pm, vaddr_t va, vm_prot_t prot); +void pmap_page_rw(pmap_t pm, vaddr_t va); + +void pmap_setpauthkeys(struct pmap *); + +paddr_t pmap_steal_avail(size_t size, int align, void **kva); +void pmap_avail_fixup(void); +void pmap_physload_avail(void); + +#define PMAP_GROWKERNEL + +struct pv_entry; + +/* investigate */ +#define pmap_unuse_final(p) do { /* nothing */ } while (0) +int pmap_fault_fixup(pmap_t, vaddr_t, vm_prot_t); + +#define __HAVE_PMAP_MPSAFE_ENTER_COW +#define __HAVE_PMAP_POPULATE +#define __HAVE_PMAP_PURGE + +#endif /* _KERNEL && !_LOCORE */ + +#ifndef _LOCORE +struct vm_page_md { + struct mutex pv_mtx; + LIST_HEAD(,pte_desc) pv_list; +}; + +#define VM_MDPAGE_INIT(pg) do { \ + mtx_init(&(pg)->mdpage.pv_mtx, IPL_VM); \ + LIST_INIT(&((pg)->mdpage.pv_list)); \ +} while (0) +#endif /* _LOCORE */ + +#endif /* _ARM64_PMAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/proc.h b/lib/libc/include/aarch64-openbsd-none/machine/proc.h new file mode 100644 index 000000000000..0b694ab2f4cb --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/proc.h @@ -0,0 +1,45 @@ +/* $OpenBSD: proc.h,v 1.2 2017/04/13 03:52:25 guenther Exp $ */ +/* $NetBSD: proc.h,v 1.1 2003/04/26 18:39:46 fvdl Exp $ */ + +/* + * Copyright (c) 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)proc.h 7.1 (Berkeley) 5/15/91 + */ + +#ifndef _MACHINE_PROC_H_ +#define _MACHINE_PROC_H_ + +/* + * Machine-dependent part of the proc structure for arm64. + */ +struct mdproc { + volatile int md_astpending; +}; + +#endif /* _MACHINE_PROC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/profile.h b/lib/libc/include/aarch64-openbsd-none/machine/profile.h new file mode 100644 index 000000000000..65fa3c7bc578 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/profile.h @@ -0,0 +1,68 @@ +/* $OpenBSD: profile.h,v 1.2 2021/02/17 12:11:45 kettenis Exp $ */ +/* + * Copyright (c) 2015 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define _MCOUNT_DECL void _mcount + +#define MCOUNT_ASM_NAME "__mcount" + +#ifdef __PIC__ +#define PLTSYM "" /* XXX -aarch64 defaults to PLT? */ +#else +#define PLTSYM "" +#endif + +#define MCOUNT \ +__asm__ (".text;" \ + ".align 3;" \ + ".globl " MCOUNT_ASM_NAME ";" \ + ".type " MCOUNT_ASM_NAME ",@function;" \ + MCOUNT_ASM_NAME ":;" \ + " stp x0, x1, [sp, #-160]!;" \ + " stp x2, x3, [sp, #16];" \ + " stp x4, x5, [sp, #32];" \ + " stp x6, x7, [sp, #48];" \ + " stp x8, x9, [sp, #64];" \ + " stp x10,x11,[sp, #80];" \ + " stp x12,x13,[sp, #96];" \ + " stp x14,x15,[sp, #112];" \ + " stp x16,x17,[sp, #128];" \ + " stp x29,lr, [sp, #144];" \ + /* load from pc at 8 off frame pointer */ \ + " ldr x0, [x29, #8];" \ + " mov x1, lr;" \ + " bl " __STRING(_mcount) PLTSYM ";" \ + /* restore argument registers */ \ + " ldp x2, x3, [sp, #16];" \ + " ldp x4, x5, [sp, #32];" \ + " ldp x6, x7, [sp, #48];" \ + " ldp x8, x9, [sp, #64];" \ + " ldp x10,x11,[sp, #80];" \ + " ldp x12,x13,[sp, #96];" \ + " ldp x14,x15,[sp, #112];" \ + " ldp x16,x17,[sp, #128];" \ + " ldp x29,lr, [sp, #144];" \ + " ldp x0, x1, [sp], #160;" \ + " ret;"); + +#ifdef _KERNEL +// Change this to dair read/set, then restore. +#define MCOUNT_ENTER \ +__asm__ ("mrs %x0, daif; msr daifset, #0x3": "=r"(s)); +#define MCOUNT_EXIT \ +__asm__ ("msr daif, %x0":: "r"(s)); + +#endif // _KERNEL \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/pte.h b/lib/libc/include/aarch64-openbsd-none/machine/pte.h new file mode 100644 index 000000000000..980230fc56d0 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/pte.h @@ -0,0 +1,104 @@ +/* $OpenBSD: pte.h,v 1.10 2024/10/14 12:02:16 jsg Exp $ */ +/* + * Copyright (c) 2014 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef _ARM_PTE_H_ +#define _ARM_PTE_H_ + +/* level X descriptor */ +#define Lx_TYPE_MASK (0x00000003) /* mask of type bits */ +#define Lx_TYPE_S (0x00000001) +#define Lx_TYPE_PT (0x00000003) +// XXX need to investigate use of these +#define Lx_PT_NS (1ULL<<63) +#define Lx_PT_AP00 (0ULL<<61) +#define Lx_PT_AP01 (1ULL<<61) +#define Lx_PT_AP10 (2ULL<<61) +#define Lx_PT_AP11 (3ULL<<61) +#define Lx_PT_XN (1ULL<<60) +#define Lx_PT_PXN (1ULL<<59) +#define Lx_TABLE_ALIGN (4096) + +/* Block and Page attributes */ +/* TODO: Add the upper attributes */ +#define ATTR_MASK_H (0xfff0000000000000ULL) +#define ATTR_MASK_L (0x0000000000000fffULL) +#define ATTR_MASK (ATTR_MASK_H | ATTR_MASK_L) +/* Bits 58:55 are reserved for software */ +#define ATTR_SW_MANAGED (1UL << 56) +#define ATTR_SW_WIRED (1UL << 55) +#define ATTR_UXN (1UL << 54) +#define ATTR_PXN (1UL << 53) +#define ATTR_GP (1UL << 50) +#define ATTR_nG (1 << 11) +#define ATTR_AF (1 << 10) +#define ATTR_SH(x) ((x) << 8) +#define ATTR_AP_RW_BIT (1 << 7) +#define ATTR_AP(x) ((x) << 6) +#define ATTR_AP_MASK ATTR_AP(3) +#define ATTR_NS (1 << 5) +#define ATTR_IDX(x) ((x) << 2) +#define ATTR_IDX_MASK (7 << 2) + +#define PTE_ATTR_DEV_NGNRNE 0 +#define PTE_ATTR_DEV_NGNRE 1 +#define PTE_ATTR_CI 2 +#define PTE_ATTR_WB 3 +#define PTE_ATTR_WT 4 + +#define PTE_MEMATTR_DEV_NGNRNE 0x0 +#define PTE_MEMATTR_DEV_NGNRE 0x1 +#define PTE_MEMATTR_CI 0x5 +#define PTE_MEMATTR_WB 0xf +#define PTE_MEMATTR_WT 0xa + +#define SH_INNER 3 +#define SH_OUTER 2 +#define SH_NONE 0 + +/* Level 0 table, 512GiB per entry */ +#define L0_SHIFT 39 +#define L0_INVAL 0x0 /* An invalid address */ +#define L0_BLOCK 0x1 /* A block */ + /* 0x2 also marks an invalid address */ +#define L0_TABLE 0x3 /* A next-level table */ + +/* Level 1 table, 1GiB per entry */ +#define L1_SHIFT 30 +#define L1_SIZE (1 << L1_SHIFT) +#define L1_OFFSET (L1_SIZE - 1) +#define L1_INVAL L0_INVAL +#define L1_BLOCK L0_BLOCK +#define L1_TABLE L0_TABLE + +/* Level 2 table, 2MiB per entry */ +#define L2_SHIFT 21 +#define L2_SIZE (1 << L2_SHIFT) +#define L2_OFFSET (L2_SIZE - 1) +#define L2_INVAL L0_INVAL +#define L2_BLOCK L0_BLOCK +#define L2_TABLE L0_TABLE + +/* page mapping */ +#define L3_P 0x3 + +#define Ln_ENTRIES (1 << 9) +#define Ln_ADDR_MASK (Ln_ENTRIES - 1) +#define Ln_TABLE_MASK ((1 << 12) - 1) + +/* physical page mask */ +#define PTE_RPGN (((1ULL << 48) - 1) & ~PAGE_MASK) + +#endif /* _ARM_PTE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/ptrace.h b/lib/libc/include/aarch64-openbsd-none/machine/ptrace.h new file mode 100644 index 000000000000..c63c70f29d97 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/ptrace.h @@ -0,0 +1,27 @@ +/* $OpenBSD: ptrace.h,v 1.2 2023/06/10 19:30:48 kettenis Exp $ */ +/* + * Copyright (c) 2014 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define PT_STEP (PT_FIRSTMACH + 0) +#define PT_GETREGS (PT_FIRSTMACH + 1) +#define PT_SETREGS (PT_FIRSTMACH + 2) +#define PT_GETFPREGS (PT_FIRSTMACH + 3) +#define PT_SETFPREGS (PT_FIRSTMACH + 4) +#define PT_PACMASK (PT_FIRSTMACH + 5) + +#ifdef _KERNEL +register_t process_get_pacmask(struct proc *p); +#endif \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/reg.h b/lib/libc/include/aarch64-openbsd-none/machine/reg.h new file mode 100644 index 000000000000..e8cda2d2dc0f --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/reg.h @@ -0,0 +1,36 @@ +/* $OpenBSD: reg.h,v 1.3 2017/04/11 06:52:13 kettenis Exp $ */ +/* + * Copyright (c) 2014 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_REG_H_ +#define _MACHINE_REG_H_ + +struct reg { + uint64_t r_reg[30]; + uint64_t r_lr; + uint64_t r_sp; + uint64_t r_pc; + uint64_t r_spsr; + uint64_t r_tpidr; +}; + +struct fpreg { + __uint128_t fp_reg[32]; + uint32_t fp_sr; + uint32_t fp_cr; +}; + +#endif /* !_MACHINE_REG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/reloc.h b/lib/libc/include/aarch64-openbsd-none/machine/reloc.h new file mode 100644 index 000000000000..73ea25bba70f --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/reloc.h @@ -0,0 +1,123 @@ +/* $OpenBSD: reloc.h,v 1.2 2017/10/24 20:35:54 guenther Exp $ */ +/* + * AArch64 static relocation types. + */ + +/* Miscellaneous. */ +#define R_ARM_NONE 0 +#define R_AARCH64_TPOFF64 1 /// COMPLETELY WRONG - stub +#define R_AARCH64_NONE 0 + +/* Data. */ +#define R_AARCH64_ABS64 257 +#define R_AARCH64_ABS32 258 +#define R_AARCH64_ABS16 259 +#define R_AARCH64_PREL64 260 +#define R_AARCH64_PREL32 261 +#define R_AARCH64_PREL16 262 + +/* Instructions. */ +#define R_AARCH64_MOVW_UABS_G0 263 +#define R_AARCH64_MOVW_UABS_G0_NC 264 +#define R_AARCH64_MOVW_UABS_G1 265 +#define R_AARCH64_MOVW_UABS_G1_NC 266 +#define R_AARCH64_MOVW_UABS_G2 267 +#define R_AARCH64_MOVW_UABS_G2_NC 268 +#define R_AARCH64_MOVW_UABS_G3 269 + +#define R_AARCH64_MOVW_SABS_G0 270 +#define R_AARCH64_MOVW_SABS_G1 271 +#define R_AARCH64_MOVW_SABS_G2 272 + +#define R_AARCH64_LD_PREL_LO19 273 +#define R_AARCH64_ADR_PREL_LO21 274 +#define R_AARCH64_ADR_PREL_PG_HI21 275 +#define R_AARCH64_ADR_PREL_PG_HI21_NC 276 +#define R_AARCH64_ADD_ABS_LO12_NC 277 +#define R_AARCH64_LDST8_ABS_LO12_NC 278 + +#define R_AARCH64_TSTBR14 279 +#define R_AARCH64_CONDBR19 280 +#define R_AARCH64_JUMP26 282 +#define R_AARCH64_CALL26 283 +#define R_AARCH64_LDST16_ABS_LO12_NC 284 +#define R_AARCH64_LDST32_ABS_LO12_NC 285 +#define R_AARCH64_LDST64_ABS_LO12_NC 286 +#define R_AARCH64_LDST128_ABS_LO12_NC 299 + +#define R_AARCH64_MOVW_PREL_G0 287 +#define R_AARCH64_MOVW_PREL_G0_NC 288 +#define R_AARCH64_MOVW_PREL_G1 289 +#define R_AARCH64_MOVW_PREL_G1_NC 290 +#define R_AARCH64_MOVW_PREL_G2 291 +#define R_AARCH64_MOVW_PREL_G2_NC 292 +#define R_AARCH64_MOVW_PREL_G3 293 + + +#define R_AARCH64_COPY 1024 +#define R_AARCH64_GLOB_DAT 1025 // S + A +#define R_AARCH64_JUMP_SLOT 1026 // S + A +#define R_AARCH64_RELATIVE 1027 // Delta(S) + A +#define R_AARCH64_TLS_DTPREL64 1028 // DTPREL(S+A) +#define R_AARCH64_TLS_DTPMOD64 1029 // LDM(S) +#define R_AARCH64_TLS_TPREL64 1030 // TPREL(S+A) +#define R_AARCH64_TLSDESC 1031 // TLSDESC(S+A) TLS descriptor to be filled +#define R_AARCH64_IRELATIVE 1032 // Indirect(Delta(S) + A) + +// old arm32 defines. +/* Processor specific relocation types */ + +#define R_ARM_NONE 0 +#define R_ARM_PC24 1 +#define R_ARM_ABS32 2 +#define R_ARM_REL32 3 +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 +#define R_ARM_ABS12 6 +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 + +/* 17-31 are reserved for ARM Linux. */ +#define R_ARM_TLS_DTPMOD32 17 +#define R_ARM_TLS_DTPOFF32 18 +#define R_ARM_TLS_TPOFF32 19 + +#define R_ARM_COPY 20 +#define R_ARM_GLOB_DAT 21 +#define R_ARM_JUMP_SLOT 22 +#define R_ARM_RELATIVE 23 +#define R_ARM_GOTOFF 24 +#define R_ARM_GOTPC 25 +#define R_ARM_GOT32 26 +#define R_ARM_PLT32 27 + +#define R_ARM_ALU_PCREL_7_0 32 +#define R_ARM_ALU_PCREL_15_8 33 +#define R_ARM_ALU_PCREL_23_15 34 +#define R_ARM_ALU_SBREL_11_0 35 +#define R_ARM_ALU_SBREL_19_12 36 +#define R_ARM_ALU_SBREL_27_20 37 + +/* 96-111 are reserved to G++. */ +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_THM_PC11 102 +#define R_ARM_THM_PC9 103 + +/* 112-127 are reserved for private experiments. */ + +#define R_ARM_RXPC25 249 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS32 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/setjmp.h b/lib/libc/include/aarch64-openbsd-none/machine/setjmp.h new file mode 100644 index 000000000000..098e20281fac --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/setjmp.h @@ -0,0 +1,83 @@ +/* $OpenBSD: setjmp.h,v 1.2 2023/04/11 00:45:07 jsg Exp $ */ +/* $NetBSD: setjmp.h,v 1.2 2001/08/25 14:45:59 bjh21 Exp $ */ + +/* + * machine/setjmp.h: machine dependent setjmp-related information. + */ + +#define _JBLEN 64 /* size, in longs, of a jmp_buf */ + +/* + * NOTE: The internal structure of a jmp_buf is *PRIVATE* + * This information is provided as there is software + * that fiddles with this with obtain the stack pointer + * (yes really ! and it's commercial !). + * + * Description of the setjmp buffer + * + * word 0 magic number (dependant on creator) + * 1 - 3 f4 fp register 4 + * 4 - 6 f5 fp register 5 + * 7 - 9 f6 fp register 6 + * 10 - 12 f7 fp register 7 + * 13 fpsr fp status register + * 14 r4 register 4 + * 15 r5 register 5 + * 16 r6 register 6 + * 17 r7 register 7 + * 18 r8 register 8 + * 19 r9 register 9 + * 20 r10 register 10 (sl) + * 21 r11 register 11 (fp) + * 22 r12 register 12 (ip) + * 23 r13 register 13 (sp) + * 24 r14 register 14 (lr) + * 25 signal mask (dependant on magic) + * 26 (con't) + * 27 (con't) + * 28 (con't) + * + * The magic number identifies the jmp_buf and + * how the buffer was created as well as providing + * a sanity check. + * + * A side note I should mention - please do not tamper + * with the floating point fields. While they are + * always saved and restored at the moment this cannot + * be guaranteed especially if the compiler happens + * to be generating soft-float code so no fp + * registers will be used. + * + * Whilst this can be seen an encouraging people to + * use the setjmp buffer in this way I think that it + * is for the best then if changes occur compiles will + * break rather than just having new builds falling over + * mysteriously. + */ + +#define _JB_MAGIC__SETJMP 0x4278f500 +#define _JB_MAGIC_SETJMP 0x4278f501 + +/* Valid for all jmp_buf's */ + +#define _JB_MAGIC 0 +#define _JB_REG_F4 1 +#define _JB_REG_F5 4 +#define _JB_REG_F6 7 +#define _JB_REG_F7 10 +#define _JB_REG_FPSR 13 +#define _JB_REG_R4 14 +#define _JB_REG_R5 15 +#define _JB_REG_R6 16 +#define _JB_REG_R7 17 +#define _JB_REG_R8 18 +#define _JB_REG_R9 19 +#define _JB_REG_R10 20 +#define _JB_REG_R11 21 +#define _JB_REG_R12 22 +#define _JB_REG_R13 23 +#define _JB_REG_R14 24 + +/* Only valid with the _JB_MAGIC_SETJMP magic */ + +#define _JB_SIGMASK 25 \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/signal.h b/lib/libc/include/aarch64-openbsd-none/machine/signal.h new file mode 100644 index 000000000000..fede515defa8 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/signal.h @@ -0,0 +1,64 @@ +/* $OpenBSD: signal.h,v 1.2 2017/03/12 17:57:12 kettenis Exp $ */ +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)signal.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _MACHINE_SIGNAL_H_ +#define _MACHINE_SIGNAL_H_ + +#include + +typedef int sig_atomic_t; + +#if __BSD_VISIBLE || __XPG_VISIBLE >= 420 +/* + * Information pushed on stack when a signal is delivered. + * This is used by the kernel to restore state following + * execution of the signal handler. It is also made available + * to the handler to allow it to restore state properly if + * a non-standard exit is performed. + */ +struct sigcontext { + int __sc_unused; + int sc_mask; /* signal mask to restore */ + + unsigned long sc_sp; + unsigned long sc_lr; + unsigned long sc_elr; + unsigned long sc_spsr; + unsigned long sc_x[30]; + + long sc_cookie; +}; +#endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ +#endif /* !_MACHINE_SIGNAL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/simplebusvar.h b/lib/libc/include/aarch64-openbsd-none/machine/simplebusvar.h new file mode 100644 index 000000000000..be1336cf1fd4 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/simplebusvar.h @@ -0,0 +1,37 @@ +/* $OpenBSD: simplebusvar.h,v 1.1 2023/09/22 01:10:43 jsg Exp $ */ +/* + * Copyright (c) 2016 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +struct simplebus_softc { + struct device sc_dev; + int sc_node; + bus_space_tag_t sc_iot; + bus_dma_tag_t sc_dmat; + int sc_acells; + int sc_scells; + int sc_pacells; + int sc_pscells; + struct bus_space sc_bus; + struct machine_bus_dma_tag sc_dma; + int *sc_ranges; + int sc_rangeslen; + int *sc_dmaranges; + int sc_dmarangeslen; + int sc_early; + int sc_early_nodes[64]; +}; + +extern void simplebus_attach(struct device *, struct device *, void *); \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/smbiosvar.h b/lib/libc/include/aarch64-openbsd-none/machine/smbiosvar.h new file mode 100644 index 000000000000..5905ff3af6be --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/smbiosvar.h @@ -0,0 +1,278 @@ +/* $OpenBSD: smbiosvar.h,v 1.6 2025/07/15 01:09:32 jsg Exp $ */ +/* + * Copyright (c) 2006 Gordon Willem Klok + * Copyright (c) 2005 Jordan Hargrave + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_SMBIOSVAR_ +#define _MACHINE_SMBIOSVAR_ + +#define SMBIOS_UUID_NPRESENT 0x1 +#define SMBIOS_UUID_NSET 0x2 + +/* + * Section 3.5 of "UUIDs and GUIDs" found at + * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt + * specifies the string representation of a UUID. + */ +#define SMBIOS_UUID_REP "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" +#define SMBIOS_UUID_REPLEN 37 /* 16 zero padded values, 4 hyphens, 1 null */ + +struct smbios_entry { + uint8_t mjr; + uint8_t min; + uint8_t *addr; + uint16_t len; + uint16_t count; +}; + +struct smbhdr { + uint32_t sig; /* "_SM_" */ + uint8_t checksum; /* Entry point checksum */ + uint8_t len; /* Entry point structure length */ + uint8_t majrev; /* Specification major revision */ + uint8_t minrev; /* Specification minor revision */ + uint16_t mss; /* Maximum Structure Size */ + uint8_t epr; /* Entry Point Revision */ + uint8_t fa[5]; /* value determined by EPR */ + uint8_t sasig[5]; /* Secondary Anchor "_DMI_" */ + uint8_t sachecksum; /* Secondary Checksum */ + uint16_t size; /* Length of structure table in bytes */ + uint32_t addr; /* Structure table address */ + uint16_t count; /* Number of SMBIOS structures */ + uint8_t rev; /* BCD revision */ +} __packed; + +struct smb3hdr { + uint8_t sig[5]; /* "_SM3_" */ + uint8_t checksum; /* Entry point structure checksum */ + uint8_t len; /* Entry point length */ + uint8_t majrev; /* SMBIOS major version */ + uint8_t minrev; /* SMBIOS minor version */ + uint8_t docrev; /* SMBIOS docrev */ + uint8_t epr; /* Entry point revision */ + uint8_t reserved; /* Reserved */ + uint32_t size; /* Structure table maximum size */ + uint64_t addr; /* Structure table address */ +} __packed; + +struct smbtblhdr { + uint8_t type; + uint8_t size; + uint16_t handle; +} __packed; + +struct smbtable { + struct smbtblhdr *hdr; + void *tblhdr; + uint32_t cookie; +}; + +#define SMBIOS_TYPE_BIOS 0 +#define SMBIOS_TYPE_SYSTEM 1 +#define SMBIOS_TYPE_BASEBOARD 2 +#define SMBIOS_TYPE_ENCLOSURE 3 +#define SMBIOS_TYPE_PROCESSOR 4 +#define SMBIOS_TYPE_MEMCTRL 5 +#define SMBIOS_TYPE_MEMMOD 6 +#define SMBIOS_TYPE_CACHE 7 +#define SMBIOS_TYPE_PORT 8 +#define SMBIOS_TYPE_SLOTS 9 +#define SMBIOS_TYPE_OBD 10 +#define SMBIOS_TYPE_OEM 11 +#define SMBIOS_TYPE_SYSCONFOPT 12 +#define SMBIOS_TYPE_BIOSLANG 13 +#define SMBIOS_TYPE_GROUPASSOC 14 +#define SMBIOS_TYPE_SYSEVENTLOG 15 +#define SMBIOS_TYPE_PHYMEM 16 +#define SMBIOS_TYPE_MEMDEV 17 +#define SMBIOS_TYPE_ECCINFO32 18 +#define SMBIOS_TYPE_MEMMAPARRAYADDR 19 +#define SMBIOS_TYPE_MEMMAPDEVADDR 20 +#define SMBIOS_TYPE_INBUILTPOINT 21 +#define SMBIOS_TYPE_PORTBATT 22 +#define SMBIOS_TYPE_SYSRESET 23 +#define SMBIOS_TYPE_HWSECUIRTY 24 +#define SMBIOS_TYPE_PWRCTRL 25 +#define SMBIOS_TYPE_VOLTPROBE 26 +#define SMBIOS_TYPE_COOLING 27 +#define SMBIOS_TYPE_TEMPPROBE 28 +#define SMBIOS_TYPE_CURRENTPROBE 29 +#define SMBIOS_TYPE_OOB_REMOTEACCESS 30 +#define SMBIOS_TYPE_BIS 31 +#define SMBIOS_TYPE_SBI 32 +#define SMBIOS_TYPE_ECCINFO64 33 +#define SMBIOS_TYPE_MGMTDEV 34 +#define SMBIOS_TYPE_MGTDEVCOMP 35 +#define SMBIOS_TYPE_MGTDEVTHRESH 36 +#define SMBIOS_TYPE_MEMCHANNEL 37 +#define SMBIOS_TYPE_IPMIDEV 38 +#define SMBIOS_TYPE_SPS 39 +#define SMBIOS_TYPE_INACTIVE 126 +#define SMBIOS_TYPE_EOT 127 + +/* + * SMBIOS Structure Type 0 "BIOS Information" + * DMTF Specification DSP0134 Section: 3.3.1 p.g. 34 + */ +struct smbios_struct_bios { + uint8_t vendor; /* string */ + uint8_t version; /* string */ + uint16_t startaddr; + uint8_t release; /* string */ + uint8_t romsize; + uint64_t characteristics; + uint32_t charext; + uint8_t major_rel; + uint8_t minor_rel; + uint8_t ecf_mjr_rel; /* embedded controller firmware */ + uint8_t ecf_min_rel; /* embedded controller firmware */ +} __packed; + +/* + * SMBIOS Structure Type 1 "System Information" + * DMTF Specification DSP0134 Section 3.3.2 p.g. 35 + */ + +struct smbios_sys { +/* SMBIOS spec 2.0+ */ + uint8_t vendor; /* string */ + uint8_t product; /* string */ + uint8_t version; /* string */ + uint8_t serial; /* string */ +/* SMBIOS spec 2.1+ */ + uint8_t uuid[16]; + uint8_t wakeup; +/* SMBIOS spec 2.4+ */ + uint8_t sku; /* string */ + uint8_t family; /* string */ +} __packed; + +/* + * SMBIOS Structure Type 2 "Base Board (Module) Information" + * DMTF Specification DSP0134 Section 3.3.3 p.g. 37 + */ +struct smbios_board { + uint8_t vendor; /* string */ + uint8_t product; /* string */ + uint8_t version; /* string */ + uint8_t serial; /* string */ + uint8_t asset; /* string */ + uint8_t feature; /* feature flags */ + uint8_t location; /* location in chassis */ + uint16_t handle; /* chassis handle */ + uint8_t type; /* board type */ + uint8_t noc; /* number of contained objects */ +} __packed; + +/* + * SMBIOS Structure Type 3 "System Enclosure or Chassis" + * DMTF Specification DSP0134 + */ +struct smbios_enclosure { + /* SMBIOS spec 2.0+ */ + uint8_t vendor; /* string */ + uint8_t type; + uint8_t version; /* string */ + uint8_t serial; /* string */ + uint8_t asset_tag; /* string */ + /* SMBIOS spec 2.1+ */ + uint8_t boot_state; + uint8_t psu_state; + uint8_t thermal_state; + uint8_t security_status; + /* SMBIOS spec 2.3+ */ + uint16_t oem_defined; + uint8_t height; + uint8_t no_power_cords; + uint8_t no_contained_element; + uint8_t reclen_contained_element; + uint8_t contained_elements; + /* SMBIOS spec 2.7+ */ + uint8_t sku; /* string */ +} __packed; + +/* + * SMBIOS Structure Type 4 "processor Information" + * DMTF Specification DSP0134 v2.5 Section 3.3.5 p.g. 24 + */ +struct smbios_cpu { + uint8_t cpu_socket_designation; /* string */ + uint8_t cpu_type; + uint8_t cpu_family; + uint8_t cpu_mfg; /* string */ + uint32_t cpu_id_eax; + uint32_t cpu_id_edx; + uint8_t cpu_version; /* string */ + uint8_t cpu_voltage; + uint16_t cpu_clock; + uint16_t cpu_max_speed; + uint16_t cpu_current_speed; + uint8_t cpu_status; +#define SMBIOS_CPUST_POPULATED (1<<6) +#define SMBIOS_CPUST_STATUSMASK (0x07) + uint8_t cpu_upgrade; + uint16_t cpu_l1_handle; + uint16_t cpu_l2_handle; + uint16_t cpu_l3_handle; + uint8_t cpu_serial; /* string */ + uint8_t cpu_asset_tag; /* string */ + uint8_t cpu_part_nr; /* string */ + /* following fields were added in smbios 2.5 */ + uint8_t cpu_core_count; + uint8_t cpu_core_enabled; + uint8_t cpu_thread_count; + uint16_t cpu_characteristics; +} __packed; + +/* + * SMBIOS Structure Type 38 "IPMI Information" + * DMTF Specification DSP0134 Section 3.3.39 p.g. 91 + */ +struct smbios_ipmi { + uint8_t smipmi_if_type; /* IPMI Interface Type */ + uint8_t smipmi_if_rev; /* BCD IPMI Revision */ + uint8_t smipmi_i2c_address; /* I2C address of BMC */ + uint8_t smipmi_nvram_address; /* I2C address of NVRAM + * storage */ + uint64_t smipmi_base_address; /* Base address of BMC (BAR + * format */ + uint8_t smipmi_base_flags; /* Flags field: + * bit 7:6 : register spacing + * 00 = byte + * 01 = dword + * 02 = word + * bit 4 : Lower bit BAR + * bit 3 : IRQ valid + * bit 2 : N/A + * bit 1 : Interrupt polarity + * bit 0 : Interrupt trigger */ + uint8_t smipmi_irq; /* IRQ if applicable */ +} __packed; + +int smbios_find_table(uint8_t, struct smbtable *); +char *smbios_get_string(struct smbtable *, uint8_t, char *, size_t); + +#endif \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/spinlock.h b/lib/libc/include/aarch64-openbsd-none/machine/spinlock.h new file mode 100644 index 000000000000..01f502df0f5a --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/spinlock.h @@ -0,0 +1,25 @@ +/* $OpenBSD: spinlock.h,v 1.2 2017/09/05 02:40:54 guenther Exp $ */ +/* + * Copyright (c) 2014 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_SPINLOCK_H_ +#define _MACHINE_SPINLOCK_H_ + +#define _ATOMIC_LOCK_UNLOCKED (0) +#define _ATOMIC_LOCK_LOCKED (1) +typedef int _atomic_lock_t; + +#endif \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/sysarch.h b/lib/libc/include/aarch64-openbsd-none/machine/sysarch.h new file mode 100644 index 000000000000..b2b0360289d0 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/sysarch.h @@ -0,0 +1,21 @@ +/* $OpenBSD: sysarch.h,v 1.1 2016/12/17 23:38:33 patrick Exp $ */ +/* + * Copyright (c) 2016 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef _MACHINE_SYSARCH_H_ + +// aarch64 architecture has no libarch or arch specific syscalls. + +#endif /* !_MACHINE_SYSARCH_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/tcb.h b/lib/libc/include/aarch64-openbsd-none/machine/tcb.h new file mode 100644 index 000000000000..6d129af20ae7 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/tcb.h @@ -0,0 +1,58 @@ +/* $OpenBSD: tcb.h,v 1.2 2017/01/10 13:13:12 patrick Exp $ */ + +/* + * Copyright (c) 2011 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TCB_H_ +#define _MACHINE_TCB_H_ + +#ifdef _KERNEL + +#include + +static inline void +__aarch64_set_tcb(void *tcb) +{ + __asm volatile("msr tpidr_el0, %x0" : : "r" (tcb)); +} + +#define TCB_GET(p) \ + ((struct pcb *)(p)->p_addr)->pcb_tcb + +#define TCB_SET(p, addr) \ + do { \ + ((struct pcb *)(p)->p_addr)->pcb_tcb = (addr); \ + __aarch64_set_tcb(addr); \ + } while (0) + +#else /* _KERNEL */ + +/* ELF TLS ABI calls for small TCB, with static TLS data after it */ +#define TLS_VARIANT 1 + +static inline void * +__aarch64_read_tcb(void) +{ + void *tcb; + __asm volatile("mrs %x0, tpidr_el0": "=r" (tcb)); + return tcb; +} + +#define TCB_GET() __aarch64_read_tcb() + +#endif /* _KERNEL */ + +#endif /* _MACHINE_TCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/timetc.h b/lib/libc/include/aarch64-openbsd-none/machine/timetc.h new file mode 100644 index 000000000000..ef326e8aca0d --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/timetc.h @@ -0,0 +1,24 @@ +/* $OpenBSD: timetc.h,v 1.3 2023/01/09 15:22:53 kettenis Exp $ */ +/* + * Copyright (c) 2020 Paul Irofti + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TIMETC_H_ +#define _MACHINE_TIMETC_H_ + +#define TC_AGTIMER 1 +#define TC_AGTIMER_SUN50I 2 + +#endif /* _MACHINE_TIMETC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/vmmvar.h b/lib/libc/include/aarch64-openbsd-none/machine/vmmvar.h new file mode 100644 index 000000000000..7d156212804e --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/vmmvar.h @@ -0,0 +1,93 @@ +/* $OpenBSD: vmmvar.h,v 1.3 2025/08/03 10:17:33 tb Exp $ */ +/* + * Copyright (c) 2014 Mike Larkin + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * CPU capabilities for VMM operation + */ +#ifndef _MACHINE_VMMVAR_H_ +#define _MACHINE_VMMVAR_H_ + +#define VMM_HV_SIGNATURE "OpenBSDVMM58" + +/* Exit Reasons */ +#define VM_EXIT_TERMINATED 0xFFFE +#define VM_EXIT_NONE 0xFFFF + +struct vmm_softc_md { + /* Capabilities */ + uint32_t nr_cpus; /* [I] */ +}; + +/* + * struct vcpu_inject_event : describes an exception or interrupt to inject. + */ +struct vcpu_inject_event { + uint8_t vie_vector; /* Exception or interrupt vector. */ + uint32_t vie_errorcode; /* Optional error code. */ + uint8_t vie_type; +#define VCPU_INJECT_NONE 0 +#define VCPU_INJECT_INTR 1 /* External hardware interrupt. */ +#define VCPU_INJECT_EX 2 /* HW or SW Exception */ +#define VCPU_INJECT_NMI 3 /* Non-maskable Interrupt */ +}; + +#define VCPU_REGS_NGPRS 31 + +struct vcpu_reg_state { + uint64_t vrs_gprs[VCPU_REGS_NGPRS]; +}; + +/* + * struct vm_exit + * + * Contains VM exit information communicated to vmd(8). This information is + * gathered by vmm(4) from the CPU on each exit that requires help from vmd. + */ +struct vm_exit { + struct vcpu_reg_state vrs; +}; + +struct vm_intr_params { + /* Input parameters to VMM_IOC_INTR */ + uint32_t vip_vm_id; + uint32_t vip_vcpu_id; + uint16_t vip_intr; +}; + +#define VM_RWREGS_GPRS 0x1 /* read/write GPRs */ +#define VM_RWREGS_ALL (VM_RWREGS_GPRS) + +struct vm_rwregs_params { + /* + * Input/output parameters to VMM_IOC_READREGS / + * VMM_IOC_WRITEREGS + */ + uint32_t vrwp_vm_id; + uint32_t vrwp_vcpu_id; + uint64_t vrwp_mask; + struct vcpu_reg_state vrwp_regs; +}; + +enum { + VEI_DIR_OUT, + VEI_DIR_IN +}; + +/* IOCTL definitions */ +#define VMM_IOC_INTR _IOW('V', 6, struct vm_intr_params) /* Intr pending */ + +#endif /* ! _MACHINE_VMMVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-openbsd-none/machine/vmparam.h b/lib/libc/include/aarch64-openbsd-none/machine/vmparam.h new file mode 100644 index 000000000000..94745e8e1c39 --- /dev/null +++ b/lib/libc/include/aarch64-openbsd-none/machine/vmparam.h @@ -0,0 +1,108 @@ +/* $OpenBSD: vmparam.h,v 1.9 2023/04/28 18:33:22 robert Exp $ */ +/* $NetBSD: vmparam.h,v 1.1 2003/04/26 18:39:49 fvdl Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vmparam.h 5.9 (Berkeley) 5/12/91 + */ + +#ifndef _MACHINE_VMPARAM_H_ +#define _MACHINE_VMPARAM_H_ + +/* + * Machine dependent constants for arm64. + */ + +#define USRSTACK VM_MAXUSER_ADDRESS + +/* + * Virtual memory related constants, all in bytes + */ +#define MAXTSIZ ((paddr_t)256*1024*1024) /* max text size */ +#ifndef DFLDSIZ +#define DFLDSIZ ((paddr_t)512*1024*1024) /* initial data size limit */ +#endif +#ifndef MAXDSIZ +#define MAXDSIZ ((paddr_t)64*1024*1024*1024) /* max data size */ +#endif +#ifndef BRKSIZ +#define BRKSIZ ((paddr_t)16*1024*1024*1024) /* heap gap size */ +#endif +#ifndef DFLSSIZ +#define DFLSSIZ ((paddr_t)2*1024*1024) /* initial stack size limit */ +#endif +#ifndef MAXSSIZ +#define MAXSSIZ ((paddr_t)32*1024*1024) /* max stack size */ +#endif + +#define STACKGAP_RANDOM 256*1024 + +/* + * Size of shared memory map + */ +#ifndef SHMMAXPGS +#define SHMMAXPGS 1024 +#endif + +/* + * Size of User Raw I/O map + */ +#define USRIOSIZE 300 + +/* + * Kernel base + */ +#define KERNEL_BASE 0xffffff8000000000ULL + +/* + * Mach derived constants + */ + +/* user/kernel map constants */ +#define VM_MIN_ADDRESS ((vaddr_t)PAGE_SIZE) +#define USER_SPACE_BITS 39 +#define VM_MAXUSER_ADDRESS ((1ULL << USER_SPACE_BITS) - 0x8000) +#define VM_MAX_ADDRESS VM_MAXUSER_ADDRESS +#ifdef _KERNEL +#define VM_MIN_STACK_ADDRESS (3ULL << (USER_SPACE_BITS - 2)) +#endif +#define VM_MIN_KERNEL_ADDRESS ((vaddr_t)0xffffff8000000000ULL) +#define VM_MAX_KERNEL_ADDRESS ((vaddr_t)0xffffff83ffffffffULL) + +/* virtual sizes (bytes) for various kernel submaps */ +#define VM_PHYS_SIZE (USRIOSIZE*PAGE_SIZE) + +#define VM_PHYSSEG_MAX 32 +#define VM_PHYSSEG_STRAT VM_PSTRAT_BSEARCH +#define VM_PHYSSEG_NOADD /* can't add RAM after vm_mem_init */ + +#endif /* _MACHINE_VMPARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/any-darwin-any/AvailabilityInternal.h b/lib/libc/include/any-darwin-any/AvailabilityInternal.h index 6549f4df89d0..cc4bc48b4fae 100644 --- a/lib/libc/include/any-darwin-any/AvailabilityInternal.h +++ b/lib/libc/include/any-darwin-any/AvailabilityInternal.h @@ -37,11 +37,11 @@ #if __has_builtin(__is_target_os) #if __is_target_os(macos) #define __MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_OS_VERSION_MIN_REQUIRED__ - #define __MAC_OS_X_VERSION_MAX_ALLOWED __MAC_26_1 + #define __MAC_OS_X_VERSION_MAX_ALLOWED __MAC_26_2 #endif #elif __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ #define __MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ - #define __MAC_OS_X_VERSION_MAX_ALLOWED __MAC_26_1 + #define __MAC_OS_X_VERSION_MAX_ALLOWED __MAC_26_2 #endif /* __has_builtin(__is_target_os) */ #endif /* defined(__has_builtin) */ #endif /* __MAC_OS_X_VERSION_MIN_REQUIRED */ @@ -51,11 +51,11 @@ #if __has_builtin(__is_target_os) #if __is_target_os(ios) #define __IPHONE_OS_VERSION_MIN_REQUIRED __ENVIRONMENT_OS_VERSION_MIN_REQUIRED__ - #define __IPHONE_OS_VERSION_MAX_ALLOWED __IPHONE_26_1 + #define __IPHONE_OS_VERSION_MAX_ALLOWED __IPHONE_26_2 #endif #elif __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ #define __IPHONE_OS_VERSION_MIN_REQUIRED __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ - #define __IPHONE_OS_VERSION_MAX_ALLOWED __IPHONE_26_1 + #define __IPHONE_OS_VERSION_MAX_ALLOWED __IPHONE_26_2 #endif /* __has_builtin(__is_target_os) */ #endif /* defined(__has_builtin) */ #endif /* __IPHONE_OS_VERSION_MIN_REQUIRED */ @@ -65,13 +65,13 @@ #if __has_builtin(__is_target_os) #if __is_target_os(watchos) #define __WATCH_OS_VERSION_MIN_REQUIRED __ENVIRONMENT_OS_VERSION_MIN_REQUIRED__ - #define __WATCH_OS_VERSION_MAX_ALLOWED __WATCHOS_26_1 + #define __WATCH_OS_VERSION_MAX_ALLOWED __WATCHOS_26_2 /* for compatibility with existing code. New code should use platform specific checks */ #define __IPHONE_OS_VERSION_MIN_REQUIRED __IPHONE_9_0 #endif #elif __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ #define __WATCH_OS_VERSION_MIN_REQUIRED __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ - #define __WATCH_OS_VERSION_MAX_ALLOWED __WATCHOS_26_1 + #define __WATCH_OS_VERSION_MAX_ALLOWED __WATCHOS_26_2 /* for compatibility with existing code. New code should use platform specific checks */ #define __IPHONE_OS_VERSION_MIN_REQUIRED __IPHONE_9_0 #endif /* __has_builtin(__is_target_os) */ @@ -83,13 +83,13 @@ #if __has_builtin(__is_target_os) #if __is_target_os(tvos) #define __TV_OS_VERSION_MIN_REQUIRED __ENVIRONMENT_OS_VERSION_MIN_REQUIRED__ - #define __TV_OS_VERSION_MAX_ALLOWED __TVOS_26_1 + #define __TV_OS_VERSION_MAX_ALLOWED __TVOS_26_2 /* for compatibility with existing code. New code should use platform specific checks */ #define __IPHONE_OS_VERSION_MIN_REQUIRED __IPHONE_9_0 #endif #elif __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ #define __TV_OS_VERSION_MIN_REQUIRED __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ - #define __TV_OS_VERSION_MAX_ALLOWED __TVOS_26_1 + #define __TV_OS_VERSION_MAX_ALLOWED __TVOS_26_2 /* for compatibility with existing code. New code should use platform specific checks */ #define __IPHONE_OS_VERSION_MIN_REQUIRED __IPHONE_9_0 #endif /* __has_builtin(__is_target_os) */ @@ -103,7 +103,7 @@ #if __has_builtin(__is_target_os) #if __is_target_os(driverkit) #define __DRIVERKIT_VERSION_MIN_REQUIRED __ENVIRONMENT_OS_VERSION_MIN_REQUIRED__ - #define __DRIVERKIT_VERSION_MAX_ALLOWED __DRIVERKIT_25_1 + #define __DRIVERKIT_VERSION_MAX_ALLOWED __DRIVERKIT_25_2 #endif #endif /* __has_builtin(__is_target_os) */ #endif /* defined(__has_builtin) */ @@ -114,7 +114,7 @@ #if __has_builtin(__is_target_os) #if __is_target_os(visionos) #define __VISION_OS_VERSION_MIN_REQUIRED __ENVIRONMENT_OS_VERSION_MIN_REQUIRED__ - #define __VISION_OS_VERSION_MAX_ALLOWED __VISIONOS_26_1 + #define __VISION_OS_VERSION_MAX_ALLOWED __VISIONOS_26_2 /* for compatibility with existing code. New code should use platform specific checks */ #define __IPHONE_OS_VERSION_MIN_REQUIRED __IPHONE_17_1 #endif diff --git a/lib/libc/include/any-darwin-any/AvailabilityVersions.h b/lib/libc/include/any-darwin-any/AvailabilityVersions.h index e974be52e68c..11b59c4f338d 100644 --- a/lib/libc/include/any-darwin-any/AvailabilityVersions.h +++ b/lib/libc/include/any-darwin-any/AvailabilityVersions.h @@ -98,6 +98,7 @@ #define __MAC_16_0 160000 #define __MAC_26_0 260000 #define __MAC_26_1 260100 +#define __MAC_26_2 260200 /* __MAC__NA is not defined to a value but is used as a token by macros to indicate that the API is unavailable */ #define __IPHONE_2_0 20000 @@ -190,6 +191,7 @@ #define __IPHONE_19_0 190000 #define __IPHONE_26_0 260000 #define __IPHONE_26_1 260100 +#define __IPHONE_26_2 260200 /* __IPHONE__NA is not defined to a value but is used as a token by macros to indicate that the API is unavailable */ #define __WATCHOS_1_0 10000 @@ -251,6 +253,7 @@ #define __WATCHOS_12_0 120000 #define __WATCHOS_26_0 260000 #define __WATCHOS_26_1 260100 +#define __WATCHOS_26_2 260200 /* __WATCHOS__NA is not defined to a value but is used as a token by macros to indicate that the API is unavailable */ #define __TVOS_9_0 90000 @@ -312,6 +315,7 @@ #define __TVOS_19_0 190000 #define __TVOS_26_0 260000 #define __TVOS_26_1 260100 +#define __TVOS_26_2 260200 /* __TVOS__NA is not defined to a value but is used as a token by macros to indicate that the API is unavailable */ #define __BRIDGEOS_2_0 20000 @@ -350,6 +354,7 @@ #define __BRIDGEOS_9_6 90600 #define __BRIDGEOS_10_0 100000 #define __BRIDGEOS_10_1 100100 +#define __BRIDGEOS_10_2 100200 #define __DRIVERKIT_19_0 190000 @@ -375,6 +380,7 @@ #define __DRIVERKIT_24_6 240600 #define __DRIVERKIT_25_0 250000 #define __DRIVERKIT_25_1 250100 +#define __DRIVERKIT_25_2 250200 /* __DRIVERKIT__NA is not defined to a value but is used as a token by macros to indicate that the API is unavailable */ #define __VISIONOS_1_0 10000 @@ -391,6 +397,7 @@ #define __VISIONOS_3_0 30000 #define __VISIONOS_26_0 260000 #define __VISIONOS_26_1 260100 +#define __VISIONOS_26_2 260200 /* __VISIONOS__NA is not defined to a value but is used as a token by macros to indicate that the API is unavailable */ @@ -482,6 +489,7 @@ #define MAC_OS_VERSION_16_0 __MAC_16_0 #define MAC_OS_VERSION_26_0 __MAC_26_0 #define MAC_OS_VERSION_26_1 __MAC_26_1 +#define MAC_OS_VERSION_26_2 __MAC_26_2 #endif /* #if (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || defined(_DARWIN_C_SOURCE) */ diff --git a/lib/libc/include/any-darwin-any/mach/port.h b/lib/libc/include/any-darwin-any/mach/port.h index 8b04a51a8182..4d0fdcb1ca74 100644 --- a/lib/libc/include/any-darwin-any/mach/port.h +++ b/lib/libc/include/any-darwin-any/mach/port.h @@ -482,7 +482,7 @@ enum mach_port_guard_exception_codes { /* start of always non-fatal guards */ kGUARD_EXC_RCV_GUARDED_DESC = 0x00100000, /* for development only */ kGUARD_EXC_SERVICE_PORT_VIOLATION_NON_FATAL = 0x00100001, /* unused, for future sp defense enablement */ - kGUARD_EXC_PROVISIONAL_REPLY_PORT = 0x00100002, + kGUARD_EXC_PROVISIONAL_REPLY_PORT = 0x00100002, /* unused */ kGUARD_EXC_OOL_PORT_ARRAY_CREATION = 0x00100003, /* unused */ kGUARD_EXC_MOVE_PROVISIONAL_REPLY_PORT = 0x00100004, kGUARD_EXC_REPLY_PORT_SINGLE_SO_RIGHT = 0x00100005, diff --git a/lib/libc/include/any-darwin-any/sys/_symbol_aliasing.h b/lib/libc/include/any-darwin-any/sys/_symbol_aliasing.h index c1db55b9542b..6e1fb045ea8c 100644 --- a/lib/libc/include/any-darwin-any/sys/_symbol_aliasing.h +++ b/lib/libc/include/any-darwin-any/sys/_symbol_aliasing.h @@ -569,6 +569,12 @@ #define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_26_1(x) #endif +#if defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 260200 +#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_26_2(x) x +#else +#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_26_2(x) +#endif + #if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1000 #define __DARWIN_ALIAS_STARTING_MAC___MAC_10_0(x) x #else @@ -1013,3 +1019,9 @@ #define __DARWIN_ALIAS_STARTING_MAC___MAC_26_1(x) #endif +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 260200 +#define __DARWIN_ALIAS_STARTING_MAC___MAC_26_2(x) x +#else +#define __DARWIN_ALIAS_STARTING_MAC___MAC_26_2(x) +#endif + diff --git a/lib/libc/include/arm-freebsd-eabihf/fenv.h b/lib/libc/include/arm-freebsd-eabihf/fenv.h index 4aa93a759c26..ca9d01ef40f0 100644 --- a/lib/libc/include/arm-freebsd-eabihf/fenv.h +++ b/lib/libc/include/arm-freebsd-eabihf/fenv.h @@ -29,6 +29,7 @@ #ifndef _FENV_H_ #define _FENV_H_ +#include #include #ifndef __fenv_static diff --git a/lib/libc/include/arm-freebsd-eabihf/float.h b/lib/libc/include/arm-freebsd-eabihf/float.h index 8f8a41e8562d..b0ab1592b2ad 100644 --- a/lib/libc/include/arm-freebsd-eabihf/float.h +++ b/lib/libc/include/arm-freebsd-eabihf/float.h @@ -27,8 +27,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)float.h 7.1 (Berkeley) 5/8/90 */ #ifndef _MACHINE_FLOAT_H_ diff --git a/lib/libc/include/arm-freebsd-eabihf/floatingpoint.h b/lib/libc/include/arm-freebsd-eabihf/floatingpoint.h index 428967247163..bd3020282afc 100644 --- a/lib/libc/include/arm-freebsd-eabihf/floatingpoint.h +++ b/lib/libc/include/arm-freebsd-eabihf/floatingpoint.h @@ -31,8 +31,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#) floatingpoint.h 1.0 (Berkeley) 9/23/93 */ #ifndef _FLOATINGPOINT_H_ diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/_align.h b/lib/libc/include/arm-freebsd-eabihf/machine/_align.h index 61c22df04881..5a6acf9624fb 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/_align.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/_align.h @@ -35,8 +35,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)param.h 5.8 (Berkeley) 6/28/91 */ #ifndef _ARM_INCLUDE__ALIGN_H_ diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/_bus.h b/lib/libc/include/arm-freebsd-eabihf/machine/_bus.h index ffa8addd0d95..7b5f67bec68b 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/_bus.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/_bus.h @@ -1,30 +1,13 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2005 M. Warner Losh + * Copyright (c) 2005 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, - * without modification, immediately at the beginning of the file. - * 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. + * SPDX-License-Identifier: BSD-2-Clause * - * 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. + * Derived in part from NetBSD's bus.h files by (alphabetically): + * Christopher G. Demetriou + * Charles M. Hannum + * Jason Thorpe + * The NetBSD Foundation. */ #ifndef ARM_INCLUDE__BUS_H diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/_limits.h b/lib/libc/include/arm-freebsd-eabihf/machine/_limits.h index bdcfd4d9797d..8dfdf8299b90 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/_limits.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/_limits.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)limits.h 8.3 (Berkeley) 1/4/94 */ #ifndef _MACHINE__LIMITS_H_ diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/_types.h b/lib/libc/include/arm-freebsd-eabihf/machine/_types.h index ad50fd62c74e..847aff8d2b89 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/_types.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/_types.h @@ -32,9 +32,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * From: @(#)ansi.h 8.2 (Berkeley) 1/4/94 - * From: @(#)types.h 8.3 (Berkeley) 1/5/94 */ #ifndef _MACHINE__TYPES_H_ diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/acle-compat.h b/lib/libc/include/arm-freebsd-eabihf/machine/acle-compat.h index d63a1132e55d..8791e469f8a8 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/acle-compat.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/acle-compat.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 ARM Ltd + * Copyright (c) 2024 Arm Ltd * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,157 +27,5 @@ */ #ifndef __ARM_ARCH - -/* ACLE standardises a set of pre-defines that describe the ARM architecture. - These were mostly implemented in GCC around GCC-4.8; older versions - have no, or only partial support. To provide a level of backwards - compatibility we try to work out what the definitions should be, given - the older pre-defines that GCC did produce. This isn't complete, but - it should be enough for use by routines that depend on this header. */ - -/* No need to handle ARMv8, GCC had ACLE support before that. */ - -#define __ARM_ACLE 101 - -# ifdef __ARM_ARCH_7__ -/* The common subset of ARMv7 in all profiles. */ -# define __ARM_ARCH 7 -# define __ARM_ARCH_ISA_THUMB 2 -# define __ARM_FEATURE_CLZ -# define __ARM_FEATURE_LDREX 7 -# define __ARM_FEATURE_UNALIGNED -# endif - -# if defined (__ARM_ARCH_7A__) || defined (__ARM_ARCH_7R__) -# define __ARM_ARCH 7 -# define __ARM_ARCH_ISA_THUMB 2 -# define __ARM_ARCH_ISA_ARM -# define __ARM_FEATURE_CLZ -# define __ARM_FEATURE_SIMD32 -# define __ARM_FEATURE_DSP -# define __ARM_FEATURE_QBIT -# define __ARM_FEATURE_SAT -# define __ARM_FEATURE_LDREX 15 -# define __ARM_FEATURE_UNALIGNED -# ifdef __ARM_ARCH_7A__ -# define __ARM_ARCH_PROFILE 'A' -# else -# define __ARM_ARCH_PROFILE 'R' -# endif -# endif - -# ifdef __ARM_ARCH_7EM__ -# define __ARM_ARCH 7 -# define __ARM_ARCH_ISA_THUMB 2 -# define __ARM_FEATURE_CLZ -# define __ARM_FEATURE_SIMD32 -# define __ARM_FEATURE_DSP -# define __ARM_FEATURE_QBIT -# define __ARM_FEATURE_SAT -# define __ARM_FEATURE_LDREX 7 -# define __ARM_FEATURE_UNALIGNED -# define __ARM_ARCH_PROFILE 'M' -# endif - -# ifdef __ARM_ARCH_7M__ -# define __ARM_ARCH 7 -# define __ARM_ARCH_ISA_THUMB 2 -# define __ARM_FEATURE_CLZ -# define __ARM_FEATURE_QBIT -# define __ARM_FEATURE_SAT -# define __ARM_FEATURE_LDREX 7 -# define __ARM_FEATURE_UNALIGNED -# define __ARM_ARCH_PROFILE 'M' -# endif - -# ifdef __ARM_ARCH_6T2__ -# define __ARM_ARCH 6 -# define __ARM_ARCH_ISA_THUMB 2 -# define __ARM_ARCH_ISA_ARM -# define __ARM_FEATURE_CLZ -# define __ARM_FEATURE_SIMD32 -# define __ARM_FEATURE_DSP -# define __ARM_FEATURE_QBIT -# define __ARM_FEATURE_SAT -# define __ARM_FEATURE_LDREX 4 -# define __ARM_FEATURE_UNALIGNED -# endif - -# ifdef __ARM_ARCH_6M__ -# define __ARM_ARCH 6 -# define __ARM_ARCH_ISA_THUMB 1 -# define __ARM_ARCH_PROFILE 'M' -# endif - -# if defined (__ARM_ARCH_6__) || defined (__ARM_ARCH_6J__) \ - || defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6Z__) \ - || defined (__ARM_ARCH_6ZK__) -# define __ARM_ARCH 6 -# define __ARM_ARCH_ISA_THUMB 1 -# define __ARM_ARCH_ISA_ARM -# define __ARM_FEATURE_CLZ -# define __ARM_FEATURE_SIMD32 -# define __ARM_FEATURE_DSP -# define __ARM_FEATURE_QBIT -# define __ARM_FEATURE_SAT -# define __ARM_FEATURE_UNALIGNED -# ifndef __thumb__ -# if defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6ZK__) -# define __ARM_FEATURE_LDREX 15 -# else -# define __ARM_FEATURE_LDREX 4 -# endif -# endif -# endif - -# if defined (__ARM_ARCH_5TE__) || defined (__ARM_ARCH_5E__) -# define __ARM_ARCH 5 -# define __ARM_ARCH_ISA_ARM -# ifdef __ARM_ARCH_5TE__ -# define __ARM_ARCH_ISA_THUMB 1 -# endif -# define __ARM_FEATURE_CLZ -# define __ARM_FEATURE_DSP -# endif - -# if defined (__ARM_ARCH_5T__) || defined (__ARM_ARCH_5__) -# define __ARM_ARCH 5 -# define __ARM_ARCH_ISA_ARM -# ifdef __ARM_ARCH_5TE__ -# define __ARM_ARCH_ISA_THUMB 1 -# endif -# define __ARM_FEATURE_CLZ -# endif - -# ifdef __ARM_ARCH_4T__ -# define __ARM_ARCH 4 -# define __ARM_ARCH_ISA_ARM -# define __ARM_ARCH_ISA_THUMB 1 -# endif - -# ifdef __ARM_ARCH_4__ -# define __ARM_ARCH 4 -# define __ARM_ARCH_ISA_ARM -# endif - -# if defined (__ARM_ARCH_3__) || defined (__ARM_ARCH_3M__) -# define __ARM_ARCH 3 -# define __ARM_ARCH_ISA_ARM -# endif - -# ifdef __ARM_ARCH_2__ -# define __ARM_ARCH 2 -# define __ARM_ARCH_ISA_ARM -# endif - -# ifdef __ARMEB__ -# define __ARM_BIG_ENDIAN -# endif - -/* If we still don't know what the target architecture is, then we're - probably not using GCC. */ -# ifndef __ARM_ARCH -# error Unable to determine architecture version. -# endif - -#endif /* __ARM_ARCH */ \ No newline at end of file +#error Your compiler is too old +#endif \ No newline at end of file diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/asm.h b/lib/libc/include/arm-freebsd-eabihf/machine/asm.h index fa7cbd669432..52acdd60dbe9 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/asm.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/asm.h @@ -32,8 +32,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)asm.h 5.5 (Berkeley) 5/7/91 */ #ifndef _MACHINE_ASM_H_ @@ -176,7 +174,6 @@ # define RETne bxne lr # define RETc(c) bx##c lr -#if __ARM_ARCH >= 7 #define ISB isb #define DSB dsb #define DMB dmb @@ -190,12 +187,5 @@ #define ERET .word 0xe160006e #endif -#elif __ARM_ARCH == 6 -#include -#define ISB mcr CP15_CP15ISB -#define DSB mcr CP15_CP15DSB -#define DMB mcr CP15_CP15DMB -#define WFI mcr CP15_CP15WFI -#endif #endif /* !_MACHINE_ASM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/atomic.h b/lib/libc/include/arm-freebsd-eabihf/machine/atomic.h index f4e9fb5c1b29..9a8ae6bc124e 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/atomic.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/atomic.h @@ -41,15 +41,9 @@ #include -#if __ARM_ARCH >= 7 #define isb() __asm __volatile("isb" : : : "memory") #define dsb() __asm __volatile("dsb" : : : "memory") #define dmb() __asm __volatile("dmb" : : : "memory") -#else -#define isb() __asm __volatile("mcr p15, 0, %0, c7, c5, 4" : : "r" (0) : "memory") -#define dsb() __asm __volatile("mcr p15, 0, %0, c7, c10, 4" : : "r" (0) : "memory") -#define dmb() __asm __volatile("mcr p15, 0, %0, c7, c10, 5" : : "r" (0) : "memory") -#endif #define mb() dmb() #define wmb() dmb() @@ -614,7 +608,7 @@ atomic_fetchadd_long(volatile u_long *p, u_long val) } static __inline uint32_t -atomic_load_acq_32(volatile uint32_t *p) +atomic_load_acq_32(const volatile uint32_t *p) { uint32_t v; @@ -624,7 +618,7 @@ atomic_load_acq_32(volatile uint32_t *p) } static __inline uint64_t -atomic_load_64(volatile uint64_t *p) +atomic_load_64(const volatile uint64_t *p) { uint64_t ret; @@ -643,7 +637,7 @@ atomic_load_64(volatile uint64_t *p) } static __inline uint64_t -atomic_load_acq_64(volatile uint64_t *p) +atomic_load_acq_64(const volatile uint64_t *p) { uint64_t ret; @@ -653,7 +647,7 @@ atomic_load_acq_64(volatile uint64_t *p) } static __inline u_long -atomic_load_acq_long(volatile u_long *p) +atomic_load_acq_long(const volatile u_long *p) { u_long v; @@ -898,8 +892,6 @@ atomic_testandclear_long(volatile u_long *p, u_int v) return (atomic_testandclear_32((volatile uint32_t *)p, v)); } -#define atomic_testandclear_long atomic_testandclear_long - static __inline int atomic_testandclear_64(volatile uint64_t *p, u_int v) @@ -958,7 +950,16 @@ atomic_testandset_long(volatile u_long *p, u_int v) return (atomic_testandset_32((volatile uint32_t *)p, v)); } -#define atomic_testandset_long atomic_testandset_long + +static __inline int +atomic_testandset_acq_long(volatile u_long *p, u_int v) +{ + int ret; + + ret = atomic_testandset_32((volatile uint32_t *)p, v); + dmb(); + return (ret); +} static __inline int atomic_testandset_64(volatile uint64_t *p, u_int v) @@ -1052,6 +1053,12 @@ atomic_thread_fence_seq_cst(void) dmb(); } +#define atomic_add_ptr atomic_add_32 +#define atomic_add_acq_ptr atomic_add_acq_32 +#define atomic_add_rel_ptr atomic_add_rel_32 +#define atomic_subtract_ptr atomic_subtract_32 +#define atomic_subtract_acq_ptr atomic_subtract_acq_32 +#define atomic_subtract_rel_ptr atomic_subtract_rel_32 #define atomic_clear_ptr atomic_clear_32 #define atomic_clear_acq_ptr atomic_clear_acq_32 #define atomic_clear_rel_ptr atomic_clear_rel_32 @@ -1059,15 +1066,18 @@ atomic_thread_fence_seq_cst(void) #define atomic_set_acq_ptr atomic_set_acq_32 #define atomic_set_rel_ptr atomic_set_rel_32 #define atomic_fcmpset_ptr atomic_fcmpset_32 -#define atomic_fcmpset_rel_ptr atomic_fcmpset_rel_32 #define atomic_fcmpset_acq_ptr atomic_fcmpset_acq_32 +#define atomic_fcmpset_rel_ptr atomic_fcmpset_rel_32 #define atomic_cmpset_ptr atomic_cmpset_32 #define atomic_cmpset_acq_ptr atomic_cmpset_acq_32 #define atomic_cmpset_rel_ptr atomic_cmpset_rel_32 +#define atomic_fetchadd_ptr atomic_fetchadd_32 +#define atomic_readandclear_ptr atomic_readandclear_32 #define atomic_load_acq_ptr atomic_load_acq_32 #define atomic_store_rel_ptr atomic_store_rel_32 #define atomic_swap_ptr atomic_swap_32 -#define atomic_readandclear_ptr atomic_readandclear_32 +#define atomic_testandset_ptr atomic_testandset_32 +#define atomic_testandclear_ptr atomic_testandclear_32 #define atomic_add_int atomic_add_32 #define atomic_add_acq_int atomic_add_acq_32 @@ -1093,12 +1103,9 @@ atomic_thread_fence_seq_cst(void) #define atomic_store_rel_int atomic_store_rel_32 #define atomic_swap_int atomic_swap_32 -/* - * For: - * - atomic_load_acq_8 - * - atomic_load_acq_16 - * - atomic_testandset_acq_long - */ #include +#define atomic_set_short atomic_set_16 +#define atomic_clear_short atomic_clear_16 + #endif /* _MACHINE_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/cpu.h b/lib/libc/include/arm-freebsd-eabihf/machine/cpu.h index cc6c423703cf..edba80742197 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/cpu.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/cpu.h @@ -45,13 +45,7 @@ void cpu_halt(void); * unconditionally with -DSMP. Although it looks like a bug, * handle this case here and in #elif condition in ARM_SMP_UP macro. */ -#if __ARM_ARCH <= 6 && defined(SMP) && !defined(KLD_MODULE) -#error SMP option is not supported on ARMv6 -#endif -#if __ARM_ARCH <= 6 && defined(SMP_ON_UP) -#error SMP_ON_UP option is only supported on ARMv7+ CPUs -#endif #if !defined(SMP) && defined(SMP_ON_UP) #error SMP option must be defined for SMP_ON_UP option @@ -68,7 +62,7 @@ do { \ up_code; \ } \ } while (0) -#elif defined(SMP) && __ARM_ARCH > 6 +#elif defined(SMP) #define ARM_SMP_UP(smp_code, up_code) \ do { \ smp_code; \ @@ -146,15 +140,15 @@ fname(uint64_t reg) \ /* TLB */ _WF0(_CP15_TLBIALL, CP15_TLBIALL) /* Invalidate entire unified TLB */ -#if __ARM_ARCH >= 7 && defined(SMP) +#if defined(SMP) _WF0(_CP15_TLBIALLIS, CP15_TLBIALLIS) /* Invalidate entire unified TLB IS */ #endif _WF1(_CP15_TLBIASID, CP15_TLBIASID(%0)) /* Invalidate unified TLB by ASID */ -#if __ARM_ARCH >= 7 && defined(SMP) +#if defined(SMP) _WF1(_CP15_TLBIASIDIS, CP15_TLBIASIDIS(%0)) /* Invalidate unified TLB by ASID IS */ #endif _WF1(_CP15_TLBIMVAA, CP15_TLBIMVAA(%0)) /* Invalidate unified TLB by MVA, all ASID */ -#if __ARM_ARCH >= 7 && defined(SMP) +#if defined(SMP) _WF1(_CP15_TLBIMVAAIS, CP15_TLBIMVAAIS(%0)) /* Invalidate unified TLB by MVA, all ASID IS */ #endif _WF1(_CP15_TLBIMVA, CP15_TLBIMVA(%0)) /* Invalidate unified TLB by MVA */ @@ -164,21 +158,19 @@ _WF1(_CP15_TTB_SET, CP15_TTBR0(%0)) /* Cache and Branch predictor */ _WF0(_CP15_BPIALL, CP15_BPIALL) /* Branch predictor invalidate all */ -#if __ARM_ARCH >= 7 && defined(SMP) +#if defined(SMP) _WF0(_CP15_BPIALLIS, CP15_BPIALLIS) /* Branch predictor invalidate all IS */ #endif _WF1(_CP15_BPIMVA, CP15_BPIMVA(%0)) /* Branch predictor invalidate by MVA */ _WF1(_CP15_DCCIMVAC, CP15_DCCIMVAC(%0)) /* Data cache clean and invalidate by MVA PoC */ _WF1(_CP15_DCCISW, CP15_DCCISW(%0)) /* Data cache clean and invalidate by set/way */ _WF1(_CP15_DCCMVAC, CP15_DCCMVAC(%0)) /* Data cache clean by MVA PoC */ -#if __ARM_ARCH >= 7 _WF1(_CP15_DCCMVAU, CP15_DCCMVAU(%0)) /* Data cache clean by MVA PoU */ -#endif _WF1(_CP15_DCCSW, CP15_DCCSW(%0)) /* Data cache clean by set/way */ _WF1(_CP15_DCIMVAC, CP15_DCIMVAC(%0)) /* Data cache invalidate by MVA PoC */ _WF1(_CP15_DCISW, CP15_DCISW(%0)) /* Data cache invalidate by set/way */ _WF0(_CP15_ICIALLU, CP15_ICIALLU) /* Instruction cache invalidate all PoU */ -#if __ARM_ARCH >= 7 && defined(SMP) +#if defined(SMP) _WF0(_CP15_ICIALLUIS, CP15_ICIALLUIS) /* Instruction cache invalidate all PoU IS */ #endif _WF1(_CP15_ICIMVAU, CP15_ICIMVAU(%0)) /* Instruction cache invalidate */ @@ -209,10 +201,8 @@ _WF1(cp15_prrr_set, CP15_PRRR(%0)) _WF1(cp15_nmrr_set, CP15_NMRR(%0)) _RF0(cp15_ttbr_get, CP15_TTBR0(%0)) _RF0(cp15_dfar_get, CP15_DFAR(%0)) -#if __ARM_ARCH >= 7 _RF0(cp15_ifar_get, CP15_IFAR(%0)) _RF0(cp15_l2ctlr_get, CP15_L2CTLR(%0)) -#endif _RF0(cp15_actlr_get, CP15_ACTLR(%0)) _WF1(cp15_actlr_set, CP15_ACTLR(%0)) _WF1(cp15_ats1cpr_set, CP15_ATS1CPR(%0)) @@ -251,14 +241,6 @@ _RF0(cp15_cbar_get, CP15_CBAR(%0)) /* Performance Monitor registers */ -#if __ARM_ARCH == 6 && defined(CPU_ARM1176) -_RF0(cp15_pmuserenr_get, CP15_PMUSERENR(%0)) -_WF1(cp15_pmuserenr_set, CP15_PMUSERENR(%0)) -_RF0(cp15_pmcr_get, CP15_PMCR(%0)) -_WF1(cp15_pmcr_set, CP15_PMCR(%0)) -_RF0(cp15_pmccntr_get, CP15_PMCCNTR(%0)) -_WF1(cp15_pmccntr_set, CP15_PMCCNTR(%0)) -#elif __ARM_ARCH > 6 _RF0(cp15_pmcr_get, CP15_PMCR(%0)) _WF1(cp15_pmcr_set, CP15_PMCR(%0)) _RF0(cp15_pmcnten_get, CP15_PMCNTENSET(%0)) @@ -280,7 +262,6 @@ _WF1(cp15_pmuserenr_set, CP15_PMUSERENR(%0)) _RF0(cp15_pminten_get, CP15_PMINTENSET(%0)) _WF1(cp15_pminten_set, CP15_PMINTENSET(%0)) _WF1(cp15_pminten_clr, CP15_PMINTENCLR(%0)) -#endif _RF0(cp15_tpidrurw_get, CP15_TPIDRURW(%0)) _WF1(cp15_tpidrurw_set, CP15_TPIDRURW(%0)) @@ -380,7 +361,7 @@ tlb_flush_range_local(vm_offset_t va, vm_size_t size) } /* Broadcasting operations. */ -#if __ARM_ARCH >= 7 && defined(SMP) +#if defined(SMP) static __inline void tlb_flush_all(void) @@ -442,14 +423,14 @@ tlb_flush_range(vm_offset_t va, vm_size_t size) ); dsb(); } -#else /* __ARM_ARCH < 7 */ +#else /* !SMP */ #define tlb_flush_all() tlb_flush_all_local() #define tlb_flush_all_ng() tlb_flush_all_ng_local() #define tlb_flush(va) tlb_flush_local(va) #define tlb_flush_range(va, size) tlb_flush_range_local(va, size) -#endif /* __ARM_ARCH < 7 */ +#endif /* !SMP */ /* * Cache maintenance operations. @@ -465,11 +446,7 @@ icache_sync(vm_offset_t va, vm_size_t size) va &= ~cpuinfo.dcache_line_mask; for ( ; va < eva; va += cpuinfo.dcache_line_size) { -#if __ARM_ARCH >= 7 _CP15_DCCMVAU(va); -#else - _CP15_DCCMVAC(va); -#endif } dsb(); ARM_SMP_UP( @@ -515,11 +492,7 @@ dcache_wb_pou(vm_offset_t va, vm_size_t size) dsb(); va &= ~cpuinfo.dcache_line_mask; for ( ; va < eva; va += cpuinfo.dcache_line_size) { -#if __ARM_ARCH >= 7 _CP15_DCCMVAU(va); -#else - _CP15_DCCMVAC(va); -#endif } dsb(); } @@ -686,8 +659,7 @@ cp15_ats1cuw_check(vm_offset_t addr) static __inline uint64_t get_cyclecount(void) { -#if __ARM_ARCH > 6 || (__ARM_ARCH == 6 && defined(CPU_ARM1176)) -#if (__ARM_ARCH > 6) && defined(DEV_PMU) +#if defined(DEV_PMU) if (pmu_attched) { u_int cpu; uint64_t h, h2; @@ -711,12 +683,6 @@ get_cyclecount(void) } else #endif return cp15_pmccntr_get(); -#else /* No performance counters, so use nanotime(9). */ - struct timespec tv; - - nanotime(&tv); - return (tv.tv_sec * (uint64_t)1000000000ull + tv.tv_nsec); -#endif } #endif @@ -729,7 +695,7 @@ get_cyclecount(void) #define cpu_spinwait() /* nothing */ #define cpu_lock_delay() DELAY(1) -#define ARM_NVEC 8 +#define ARM_NVEC 7 #define ARM_VEC_ALL 0xffffffff extern vm_offset_t vector_page; diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/cpufunc.h b/lib/libc/include/arm-freebsd-eabihf/machine/cpufunc.h index 0f3b1a139be9..95bcd2b27b0d 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/cpufunc.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/cpufunc.h @@ -97,9 +97,6 @@ void armv7_cpu_sleep (int); void pj4b_config (void); #endif -#if defined(CPU_ARM1176) -void arm11x6_sleep (int); /* no ref. for errata */ -#endif /* diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/endian.h b/lib/libc/include/arm-freebsd-eabihf/machine/endian.h index cbcfa2d88579..dac6e2b4c2c7 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/endian.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/endian.h @@ -26,8 +26,6 @@ * 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. - * - * @(#)endian.h 8.1 (Berkeley) 6/10/93 * $NetBSD: endian.h,v 1.7 1999/08/21 05:53:51 simonb Exp $ */ diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/exec.h b/lib/libc/include/arm-freebsd-eabihf/machine/exec.h new file mode 100644 index 000000000000..8a2c6bd93612 --- /dev/null +++ b/lib/libc/include/arm-freebsd-eabihf/machine/exec.h @@ -0,0 +1,37 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2001 David E. O'Brien + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_EXEC_H_ +#define _MACHINE_EXEC_H_ + +#define __LDPGSZ 4096 + +#endif /* !_MACHINE_EXEC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/float.h b/lib/libc/include/arm-freebsd-eabihf/machine/float.h index 8f8a41e8562d..b0ab1592b2ad 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/float.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/float.h @@ -27,8 +27,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)float.h 7.1 (Berkeley) 5/8/90 */ #ifndef _MACHINE_FLOAT_H_ diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/floatingpoint.h b/lib/libc/include/arm-freebsd-eabihf/machine/floatingpoint.h index 428967247163..bd3020282afc 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/floatingpoint.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/floatingpoint.h @@ -31,8 +31,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#) floatingpoint.h 1.0 (Berkeley) 9/23/93 */ #ifndef _FLOATINGPOINT_H_ diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/ieee.h b/lib/libc/include/arm-freebsd-eabihf/machine/ieee.h index 446908cdbe4d..20658d176396 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/ieee.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/ieee.h @@ -39,8 +39,6 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)ieee.h 8.1 (Berkeley) 6/11/93 - * */ /* diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/ieeefp.h b/lib/libc/include/arm-freebsd-eabihf/machine/ieeefp.h index f3ef2992bc3b..417517432cf5 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/ieeefp.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/ieeefp.h @@ -49,4 +49,14 @@ typedef enum { #define fp_except_t int +/* Augment the userland declarations. */ +__BEGIN_DECLS +extern fp_rnd_t fpgetround(void); +extern fp_rnd_t fpsetround(fp_rnd_t); +extern fp_except_t fpgetmask(void); +extern fp_except_t fpsetmask(fp_except_t); +extern fp_except_t fpgetsticky(void); +extern fp_except_t fpsetsticky(fp_except_t); +__END_DECLS + #endif /* _MACHINE_IEEEFP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/in_cksum.h b/lib/libc/include/arm-freebsd-eabihf/machine/in_cksum.h index 7adfb5d1d6b9..86ee82e582c5 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/in_cksum.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/in_cksum.h @@ -29,7 +29,6 @@ * SUCH DAMAGE. * * from tahoe: in_cksum.c 1.2 86/01/05 - * from: @(#)in_cksum.c 1.3 (Berkeley) 1/19/91 * from: Id: in_cksum.c,v 1.8 1995/12/03 18:35:19 bde Exp */ diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/intr.h b/lib/libc/include/arm-freebsd-eabihf/machine/intr.h index bca24ce483f4..65fca3b5e6e1 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/intr.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/intr.h @@ -39,16 +39,19 @@ #ifndef _MACHINE_INTR_H_ #define _MACHINE_INTR_H_ +#ifndef LOCORE #ifdef FDT #include #endif +void arm_irq_memory_barrier(uintptr_t); +#endif /* !LOCORE */ + #ifndef NIRQ #define NIRQ 1024 /* XXX - It should be an option. */ #endif -#include - -void arm_irq_memory_barrier(uintptr_t); +#define INTR_ROOT_IRQ 0 +#define INTR_ROOT_COUNT 1 #endif /* _MACHINE_INTR_H */ \ No newline at end of file diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/machdep.h b/lib/libc/include/arm-freebsd-eabihf/machine/machdep.h index d6260277bb3f..3cab2935895e 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/machdep.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/machdep.h @@ -51,6 +51,13 @@ void arm_add_efi_map_entries(struct efi_map_header *efihdr, struct mem_region *mr, int *mrcnt); #endif +#ifdef SOCDEV_PA +/* + * The virtual address SOCDEV_PA is mapped at. + */ +extern uintptr_t socdev_va; +#endif + /* * Symbols created by ldscript.arm which are accessible in the kernel as global * symbols. They have uint8 type because they mark the byte location where the diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/metadata.h b/lib/libc/include/arm-freebsd-eabihf/machine/metadata.h index 3708e09f6f66..722ef7c3fd41 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/metadata.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/metadata.h @@ -33,10 +33,15 @@ #define MODINFOMD_DTBP 0x1002 #define MODINFOMD_EFI_MAP 0x1003 +/* + * This is not the same as the UEFI standard EFI_MEMORY_ATTRIBUTES_TABLE, though + * memory_size / descritpr_size entries of EFI_MEMORY_DESCRIPTORS follow this table + * starting at a 16-byte alignment. + */ struct efi_map_header { - uint64_t memory_size; - uint64_t descriptor_size; - uint32_t descriptor_version; + uint64_t memory_size; /* Numnber of bytes that follow */ + uint64_t descriptor_size; /* Size of each EFI_MEMORY_DESCRIPTOR */ + uint32_t descriptor_version; /* Currently '1' */ }; /* diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/param.h b/lib/libc/include/arm-freebsd-eabihf/machine/param.h index edab4a72b46f..6fab13f3955c 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/param.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/param.h @@ -35,8 +35,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)param.h 5.8 (Berkeley) 6/28/91 */ #ifndef _ARM_INCLUDE_PARAM_H_ @@ -51,17 +49,11 @@ #define STACKALIGNBYTES (8 - 1) #define STACKALIGN(p) ((u_int)(p) & ~STACKALIGNBYTES) -#define __PCI_REROUTE_INTERRUPT - #ifndef MACHINE #define MACHINE "arm" #endif #ifndef MACHINE_ARCH -#if __ARM_ARCH >= 7 #define MACHINE_ARCH "armv7" -#else -#define MACHINE_ARCH "armv6" -#endif #endif #ifdef SMP @@ -76,6 +68,8 @@ #define MAXMEMDOM 1 #endif +#define __HAVE_STATIC_DEVMAP + #define ALIGNBYTES _ALIGNBYTES #define ALIGN(p) _ALIGN(p) /* @@ -129,17 +123,10 @@ /* * Mach derived conversion macros */ -#define trunc_page(x) ((x) & ~PAGE_MASK) -#define round_page(x) (((x) + PAGE_MASK) & ~PAGE_MASK) #define trunc_1mpage(x) ((unsigned)(x) & ~PDRMASK) #define round_1mpage(x) ((((unsigned)(x)) + PDRMASK) & ~PDRMASK) -#define atop(x) ((unsigned)(x) >> PAGE_SHIFT) -#define ptoa(x) ((unsigned)(x) << PAGE_SHIFT) - #define arm32_btop(x) ((unsigned)(x) >> PAGE_SHIFT) #define arm32_ptob(x) ((unsigned)(x) << PAGE_SHIFT) -#define pgtok(x) ((x) * (PAGE_SIZE / 1024)) - #endif /* !_ARM_INCLUDE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/pmap.h b/lib/libc/include/arm-freebsd-eabihf/machine/pmap.h index 78b6e5b2c148..3b18349d8813 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/pmap.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/pmap.h @@ -39,9 +39,6 @@ * map the page tables using the pagetables themselves. This is done to * reduce the impact on kernel virtual memory for lots of sparse address * space, and to reduce the cost of memory to each process. - * - * from: hp300: @(#)pmap.h 7.2 (Berkeley) 12/16/90 - * from: @(#)pmap.h 7.4 (Berkeley) 5/12/91 * from: FreeBSD: src/sys/i386/include/pmap.h,v 1.70 2000/11/30 */ @@ -138,9 +135,9 @@ extern ttb_entry_t pmap_kern_ttb; /* TTB for kernel pmap */ * vtopte2(). */ void pmap_bootstrap(vm_offset_t); -void pmap_kenter(vm_offset_t, vm_paddr_t); +void pmap_kenter(vm_offset_t, vm_size_t, vm_paddr_t, int); void pmap_kremove(vm_offset_t); -boolean_t pmap_page_is_mapped(vm_page_t); +bool pmap_page_is_mapped(vm_page_t); bool pmap_ps_enabled(pmap_t pmap); void pmap_tlb_flush(pmap_t, vm_offset_t); @@ -175,15 +172,9 @@ void pmap_page_set_memattr(vm_page_t, vm_memattr_t); #define pmap_map_delete(pmap, sva, eva) pmap_remove(pmap, sva, eva) void *pmap_mapdev(vm_paddr_t, vm_size_t); +void *pmap_mapdev_attr(vm_paddr_t, vm_size_t, vm_memattr_t); void pmap_unmapdev(void *, vm_size_t); -static inline void * -pmap_mapdev_attr(vm_paddr_t addr __unused, vm_size_t size __unused, - int attr __unused) -{ - panic("%s is not implemented yet!\n", __func__); -} - struct pcb; void pmap_set_pcb_pagedir(pmap_t, struct pcb *); diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/pmap_var.h b/lib/libc/include/arm-freebsd-eabihf/machine/pmap_var.h index ad0a787981a9..1a213f868c27 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/pmap_var.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/pmap_var.h @@ -161,7 +161,7 @@ pte1_clear_bit(pt1_entry_t *pte1p, uint32_t bit) pte1_sync(pte1p); } -static __inline boolean_t +static __inline bool pte1_is_link(pt1_entry_t pte1) { @@ -175,21 +175,21 @@ pte1_is_section(pt1_entry_t pte1) return ((pte1 & L1_TYPE_MASK) == L1_TYPE_S); } -static __inline boolean_t +static __inline bool pte1_is_dirty(pt1_entry_t pte1) { return ((pte1 & (PTE1_NM | PTE1_RO)) == 0); } -static __inline boolean_t +static __inline bool pte1_is_global(pt1_entry_t pte1) { return ((pte1 & PTE1_NG) == 0); } -static __inline boolean_t +static __inline bool pte1_is_valid(pt1_entry_t pte1) { int l1_type; @@ -198,7 +198,7 @@ pte1_is_valid(pt1_entry_t pte1) return ((l1_type == L1_TYPE_C) || (l1_type == L1_TYPE_S)); } -static __inline boolean_t +static __inline bool pte1_is_wired(pt1_entry_t pte1) { @@ -301,28 +301,28 @@ pte2_clear_bit(pt2_entry_t *pte2p, uint32_t bit) pte2_sync(pte2p); } -static __inline boolean_t +static __inline bool pte2_is_dirty(pt2_entry_t pte2) { return ((pte2 & (PTE2_NM | PTE2_RO)) == 0); } -static __inline boolean_t +static __inline bool pte2_is_global(pt2_entry_t pte2) { return ((pte2 & PTE2_NG) == 0); } -static __inline boolean_t +static __inline bool pte2_is_valid(pt2_entry_t pte2) { return (pte2 & PTE2_V); } -static __inline boolean_t +static __inline bool pte2_is_wired(pt2_entry_t pte2) { @@ -358,7 +358,7 @@ pte2_set_bit(pt2_entry_t *pte2p, uint32_t bit) } static __inline void -pte2_set_wired(pt2_entry_t *pte2p, boolean_t wired) +pte2_set_wired(pt2_entry_t *pte2p, bool wired) { /* diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/proc.h b/lib/libc/include/arm-freebsd-eabihf/machine/proc.h index b37f5a690ecd..a142642becf5 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/proc.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/proc.h @@ -31,8 +31,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)proc.h 7.1 (Berkeley) 5/15/91 * from: FreeBSD: src/sys/i386/include/proc.h,v 1.11 2001/06/29 */ diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/profile.h b/lib/libc/include/arm-freebsd-eabihf/machine/profile.h index 6154b6b66286..83f743ca16cf 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/profile.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/profile.h @@ -31,8 +31,6 @@ * 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. - * - * @(#)profile.h 8.1 (Berkeley) 6/11/93 */ #ifndef _MACHINE_PROFILE_H_ diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/reloc.h b/lib/libc/include/arm-freebsd-eabihf/machine/reloc.h index 9a7855cbeeda..f318d27664e3 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/reloc.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/reloc.h @@ -31,8 +31,6 @@ * 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. - * - * @(#)reloc.h 8.1 (Berkeley) 6/10/93 */ #ifndef _MACHINE_RELOC_H_ diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/resource.h b/lib/libc/include/arm-freebsd-eabihf/machine/resource.h index 8edfc1ab1ea3..c22c873f6b01 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/resource.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/resource.h @@ -40,8 +40,6 @@ #define SYS_RES_MEMORY 3 /* i/o memory */ #define SYS_RES_IOPORT 4 /* i/o ports */ #define SYS_RES_GPIO 5 /* general purpose i/o */ -#ifdef NEW_PCIB #define PCI_RES_BUS 6 /* PCI bus numbers */ -#endif #endif /* !_MACHINE_RESOURCE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/runq.h b/lib/libc/include/arm-freebsd-eabihf/machine/runq.h deleted file mode 100644 index 63b30d582a97..000000000000 --- a/lib/libc/include/arm-freebsd-eabihf/machine/runq.h +++ /dev/null @@ -1,46 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2001 Jake Burkholder - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _MACHINE_RUNQ_H_ -#define _MACHINE_RUNQ_H_ - -#define RQB_LEN (2) /* Number of priority status words. */ -#define RQB_L2BPW (5) /* Log2(sizeof(rqb_word_t) * NBBY)). */ -#define RQB_BPW (1<> RQB_L2BPW) - -#define RQB_FFS(word) (ffs(word) - 1) - -/* - * Type of run queue status word. - */ -typedef u_int32_t rqb_word_t; - -#endif \ No newline at end of file diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/signal.h b/lib/libc/include/arm-freebsd-eabihf/machine/signal.h index d81c04382e06..df41f25faac9 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/signal.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/signal.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)signal.h 8.1 (Berkeley) 6/11/93 * from: FreeBSD: src/sys/i386/include/signal.h,v 1.13 2000/11/09 * from: FreeBSD: src/sys/sparc64/include/signal.h,v 1.6 2001/09/30 18:52:17 */ diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/sysarch.h b/lib/libc/include/arm-freebsd-eabihf/machine/sysarch.h index 4a37651d15dd..4536de8ecb20 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/sysarch.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/sysarch.h @@ -38,6 +38,8 @@ #ifndef _ARM_SYSARCH_H_ #define _ARM_SYSARCH_H_ +#include + #include #ifndef LOCORE diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/sysreg.h b/lib/libc/include/arm-freebsd-eabihf/machine/sysreg.h index d83305a478d4..ce88a0a4b92e 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/sysreg.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/sysreg.h @@ -127,11 +127,9 @@ /* From ARMv6: */ #define CP15_IFSR(rr) p15, 0, rr, c5, c0, 1 /* Instruction Fault Status Register */ -#if __ARM_ARCH >= 7 /* From ARMv7: */ #define CP15_ADFSR(rr) p15, 0, rr, c5, c1, 0 /* Auxiliary Data Fault Status Register */ #define CP15_AIFSR(rr) p15, 0, rr, c5, c1, 1 /* Auxiliary Instruction Fault Status Register */ -#endif /* * CP15 C6 registers @@ -147,7 +145,7 @@ /* * CP15 C7 registers */ -#if __ARM_ARCH >= 7 && defined(SMP) +#if defined(SMP) /* From ARMv7: */ #define CP15_ICIALLUIS p15, 0, r0, c7, c1, 0 /* Instruction cache invalidate all PoU, IS */ #define CP15_BPIALLIS p15, 0, r0, c7, c1, 6 /* Branch predictor invalidate all IS */ @@ -157,17 +155,9 @@ #define CP15_ICIALLU p15, 0, r0, c7, c5, 0 /* Instruction cache invalidate all PoU */ #define CP15_ICIMVAU(rr) p15, 0, rr, c7, c5, 1 /* Instruction cache invalidate */ -#if __ARM_ARCH == 6 -/* Deprecated in ARMv7 */ -#define CP15_CP15ISB p15, 0, r0, c7, c5, 4 /* ISB */ -#endif #define CP15_BPIALL p15, 0, r0, c7, c5, 6 /* Branch predictor invalidate all */ #define CP15_BPIMVA p15, 0, rr, c7, c5, 7 /* Branch predictor invalidate by MVA */ -#if __ARM_ARCH == 6 -/* Only ARMv6: */ -#define CP15_DCIALL p15, 0, r0, c7, c6, 0 /* Data cache invalidate all */ -#endif #define CP15_DCIMVAC(rr) p15, 0, rr, c7, c6, 1 /* Data cache invalidate by MVA PoC */ #define CP15_DCISW(rr) p15, 0, rr, c7, c6, 2 /* Data cache invalidate by set/way */ @@ -176,43 +166,25 @@ #define CP15_ATS1CUR(rr) p15, 0, rr, c7, c8, 2 /* Stage 1 Current state unprivileged read */ #define CP15_ATS1CUW(rr) p15, 0, rr, c7, c8, 3 /* Stage 1 Current state unprivileged write */ -#if __ARM_ARCH >= 7 /* From ARMv7: */ #define CP15_ATS12NSOPR(rr) p15, 0, rr, c7, c8, 4 /* Stages 1 and 2 Non-secure only PL1 read */ #define CP15_ATS12NSOPW(rr) p15, 0, rr, c7, c8, 5 /* Stages 1 and 2 Non-secure only PL1 write */ #define CP15_ATS12NSOUR(rr) p15, 0, rr, c7, c8, 6 /* Stages 1 and 2 Non-secure only unprivileged read */ #define CP15_ATS12NSOUW(rr) p15, 0, rr, c7, c8, 7 /* Stages 1 and 2 Non-secure only unprivileged write */ -#endif -#if __ARM_ARCH == 6 -/* Only ARMv6: */ -#define CP15_DCCALL p15, 0, r0, c7, c10, 0 /* Data cache clean all */ -#endif #define CP15_DCCMVAC(rr) p15, 0, rr, c7, c10, 1 /* Data cache clean by MVA PoC */ #define CP15_DCCSW(rr) p15, 0, rr, c7, c10, 2 /* Data cache clean by set/way */ -#if __ARM_ARCH == 6 -/* Only ARMv6: */ -#define CP15_CP15DSB p15, 0, r0, c7, c10, 4 /* DSB */ -#define CP15_CP15DMB p15, 0, r0, c7, c10, 5 /* DMB */ -#define CP15_CP15WFI p15, 0, r0, c7, c0, 4 /* WFI */ -#endif -#if __ARM_ARCH >= 7 /* From ARMv7: */ #define CP15_DCCMVAU(rr) p15, 0, rr, c7, c11, 1 /* Data cache clean by MVA PoU */ -#endif -#if __ARM_ARCH == 6 -/* Only ARMv6: */ -#define CP15_DCCIALL p15, 0, r0, c7, c14, 0 /* Data cache clean and invalidate all */ -#endif #define CP15_DCCIMVAC(rr) p15, 0, rr, c7, c14, 1 /* Data cache clean and invalidate by MVA PoC */ #define CP15_DCCISW(rr) p15, 0, rr, c7, c14, 2 /* Data cache clean and invalidate by set/way */ /* * CP15 C8 registers */ -#if __ARM_ARCH >= 7 && defined(SMP) +#if defined(SMP) /* From ARMv7: */ #define CP15_TLBIALLIS p15, 0, r0, c8, c3, 0 /* Invalidate entire unified TLB IS */ #define CP15_TLBIMVAIS(rr) p15, 0, rr, c8, c3, 1 /* Invalidate unified TLB by MVA IS */ @@ -232,11 +204,6 @@ /* * CP15 C9 registers */ -#if __ARM_ARCH == 6 && defined(CPU_ARM1176) -#define CP15_PMUSERENR(rr) p15, 0, rr, c15, c9, 0 /* Access Validation Control Register */ -#define CP15_PMCR(rr) p15, 0, rr, c15, c12, 0 /* Performance Monitor Control Register */ -#define CP15_PMCCNTR(rr) p15, 0, rr, c15, c12, 1 /* PM Cycle Count Register */ -#else #define CP15_L2CTLR(rr) p15, 1, rr, c9, c0, 2 /* L2 Control Register */ #define CP15_PMCR(rr) p15, 0, rr, c9, c12, 0 /* Performance Monitor Control Register */ #define CP15_PMCNTENSET(rr) p15, 0, rr, c9, c12, 1 /* PM Count Enable Set Register */ @@ -250,7 +217,6 @@ #define CP15_PMUSERENR(rr) p15, 0, rr, c9, c14, 0 /* PM User Enable Register */ #define CP15_PMINTENSET(rr) p15, 0, rr, c9, c14, 1 /* PM Interrupt Enable Set Register */ #define CP15_PMINTENCLR(rr) p15, 0, rr, c9, c14, 2 /* PM Interrupt Enable Clear Register */ -#endif /* * CP15 C10 registers diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/vm.h b/lib/libc/include/arm-freebsd-eabihf/machine/vm.h index df7052a08faa..14c120012521 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/vm.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/vm.h @@ -36,7 +36,7 @@ #define VM_MEMATTR_WRITE_THROUGH ((vm_memattr_t)4) #define VM_MEMATTR_DEFAULT VM_MEMATTR_WB_WA -#define VM_MEMATTR_UNCACHEABLE VM_MEMATTR_SO /* misused by DMA */ +#define VM_MEMATTR_UNCACHEABLE VM_MEMATTR_NOCACHE /* used by BUSDMA */ #ifdef _KERNEL /* Don't export aliased VM_MEMATTR to userland */ #define VM_MEMATTR_WRITE_COMBINING VM_MEMATTR_WRITE_THROUGH /* for DRM */ diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/vmparam.h b/lib/libc/include/arm-freebsd-eabihf/machine/vmparam.h index e5b6b491f701..92285fcfdc25 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/vmparam.h +++ b/lib/libc/include/arm-freebsd-eabihf/machine/vmparam.h @@ -200,5 +200,6 @@ extern vm_offset_t vm_max_kernel_address; * Need a page dump array for minidump. */ #define MINIDUMP_PAGE_TRACKING 1 +#define MINIDUMP_STARTUP_PAGE_TRACKING 0 #endif /* _MACHINE_VMPARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/_float.h b/lib/libc/include/arm-openbsd-eabi/arm/_float.h new file mode 100644 index 000000000000..3fa7289390c2 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/_float.h @@ -0,0 +1,84 @@ +/* $OpenBSD: _float.h,v 1.1 2012/06/26 16:12:43 deraadt Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE__FLOAT_H_ +#define _MACHINE__FLOAT_H_ + +#define __FLT_RADIX 2 /* b */ +#define __FLT_ROUNDS __flt_rounds() +#define __FLT_EVAL_METHOD 0 /* no promotions */ + +#define __FLT_MANT_DIG 24 /* p */ +#define __FLT_EPSILON 1.19209290E-7F /* b**(1-p) */ +#define __FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ +#define __FLT_MIN_EXP (-125) /* emin */ +#define __FLT_MIN 1.17549435E-38F /* b**(emin-1) */ +#define __FLT_MIN_10_EXP (-37) /* ceil(log10(b**(emin-1))) */ +#define __FLT_MAX_EXP 128 /* emax */ +#define __FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ +#define __FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ + +#define __DBL_MANT_DIG 53 +#define __DBL_EPSILON 2.2204460492503131E-16 +#define __DBL_DIG 15 +#define __DBL_MIN_EXP (-1021) +#define __DBL_MIN 2.2250738585072014E-308 +#define __DBL_MIN_10_EXP (-307) +#define __DBL_MAX_EXP 1024 +#define __DBL_MAX 1.7976931348623157E+308 +#define __DBL_MAX_10_EXP 308 + +#define __LDBL_MANT_DIG DBL_MANT_DIG +#define __LDBL_EPSILON DBL_EPSILON +#define __LDBL_DIG DBL_DIG +#define __LDBL_MIN_EXP DBL_MIN_EXP +#define __LDBL_MIN DBL_MIN +#define __LDBL_MIN_10_EXP DBL_MIN_10_EXP +#define __LDBL_MAX_EXP DBL_MAX_EXP +#define __LDBL_MAX DBL_MAX +#define __LDBL_MAX_10_EXP DBL_MAX_10_EXP + +#define __DECIMAL_DIG 17 + +#endif /* _MACHINE__FLOAT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/_types.h b/lib/libc/include/arm-openbsd-eabi/arm/_types.h new file mode 100644 index 000000000000..5693a7cce191 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/_types.h @@ -0,0 +1,140 @@ +/* $OpenBSD: _types.h,v 1.21 2023/07/02 19:02:27 cheloha Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.3 (Berkeley) 1/5/94 + * @(#)ansi.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _ARM__TYPES_H_ +#define _ARM__TYPES_H_ + +#if defined(_KERNEL) +typedef struct label_t { + long val[11]; +} label_t; +#endif + +/* + * _ALIGN(p) rounds p (pointer or byte index) up to a correctly-aligned + * value for all data types (int, long, ...). The result is an + * unsigned long and must be cast to any desired pointer type. + * + * _ALIGNED_POINTER is a boolean macro that checks whether an address + * is valid to fetch data elements of type t from on this architecture. + * This does not reflect the optimal alignment, just the possibility + * (within reasonable limits). + */ +#define _ALIGNBYTES (sizeof(double) - 1) +#define _STACKALIGNBYTES 7 +#define _ALIGN(p) (((unsigned long)(p) + _ALIGNBYTES) & ~_ALIGNBYTES) +#define _ALIGNED_POINTER(p,t) ((((unsigned long)(p)) & (sizeof(t) - 1)) == 0) +#define _MAX_PAGE_SHIFT 12 /* same as PAGE_SHIFT */ + +/* 7.18.1.1 Exact-width integer types */ +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short __int16_t; +typedef unsigned short __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; +typedef long long __int64_t; +typedef unsigned long long __uint64_t; + +/* 7.18.1.2 Minimum-width integer types */ +typedef __int8_t __int_least8_t; +typedef __uint8_t __uint_least8_t; +typedef __int16_t __int_least16_t; +typedef __uint16_t __uint_least16_t; +typedef __int32_t __int_least32_t; +typedef __uint32_t __uint_least32_t; +typedef __int64_t __int_least64_t; +typedef __uint64_t __uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types */ +typedef __int32_t __int_fast8_t; +typedef __uint32_t __uint_fast8_t; +typedef __int32_t __int_fast16_t; +typedef __uint32_t __uint_fast16_t; +typedef __int32_t __int_fast32_t; +typedef __uint32_t __uint_fast32_t; +typedef __int64_t __int_fast64_t; +typedef __uint64_t __uint_fast64_t; +#define __INT_FAST8_MIN INT32_MIN +#define __INT_FAST16_MIN INT32_MIN +#define __INT_FAST32_MIN INT32_MIN +#define __INT_FAST64_MIN INT64_MIN +#define __INT_FAST8_MAX INT32_MAX +#define __INT_FAST16_MAX INT32_MAX +#define __INT_FAST32_MAX INT32_MAX +#define __INT_FAST64_MAX INT64_MAX +#define __UINT_FAST8_MAX UINT32_MAX +#define __UINT_FAST16_MAX UINT32_MAX +#define __UINT_FAST32_MAX UINT32_MAX +#define __UINT_FAST64_MAX UINT64_MAX + +/* 7.18.1.4 Integer types capable of holding object pointers */ +typedef long __intptr_t; +typedef unsigned long __uintptr_t; + +/* 7.18.1.5 Greatest-width integer types */ +typedef __int64_t __intmax_t; +typedef __uint64_t __uintmax_t; + +/* Register size */ +typedef long __register_t; + +/* VM system types */ +typedef unsigned long __vaddr_t; +typedef unsigned long __paddr_t; +typedef unsigned long __vsize_t; +typedef unsigned long __psize_t; + +/* Standard system types */ +typedef double __double_t; +typedef float __float_t; +typedef long __ptrdiff_t; +typedef unsigned long __size_t; +typedef long __ssize_t; +#if defined(__GNUC__) && __GNUC__ >= 3 +typedef __builtin_va_list __va_list; +#else +typedef char * __va_list; +#endif + +/* Wide character support types */ +#ifndef __cplusplus +typedef int __wchar_t; +#endif +typedef int __wint_t; +typedef int __rune_t; +typedef void * __wctrans_t; +typedef void * __wctype_t; + +#endif /* _ARM__TYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/apmvar.h b/lib/libc/include/arm-openbsd-eabi/arm/apmvar.h new file mode 100644 index 000000000000..d4b6d1142413 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/apmvar.h @@ -0,0 +1,122 @@ +/* $OpenBSD: apmvar.h,v 1.6 2019/01/22 02:36:30 phessler Exp $ */ + +/* + * Copyright (c) 2001 Alexander Guy + * Copyright (c) 1995 John T. Kohl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _ARM_APMVAR_H_ +#define _ARM_APMVAR_H_ + +#include + +/* Advanced Power Management (v1.0 and v1.1 specification) + * functions/defines/etc. + */ + +/* These definitions make up the heart of the user-land interface + * to the APM devices. + */ + +#define APM_AC_OFF 0x00 +#define APM_AC_ON 0x01 +#define APM_AC_BACKUP 0x02 +#define APM_AC_UNKNOWN 0xff +#define APM_BATT_HIGH 0x00 +#define APM_BATT_LOW 0x01 +#define APM_BATT_CRITICAL 0x02 +#define APM_BATT_CHARGING 0x03 +#define APM_BATT_UNKNOWN 0xff +#define APM_BATT_LIFE_UNKNOWN 0xff + +#define APM_NOEVENT 0x0000 +#define APM_STANDBY_REQ 0x0001 +#define APM_SUSPEND_REQ 0x0002 +#define APM_NORMAL_RESUME 0x0003 +#define APM_CRIT_RESUME 0x0004 /* suspend/resume happened + without us */ +#define APM_BATTERY_LOW 0x0005 +#define APM_POWER_CHANGE 0x0006 +#define APM_UPDATE_TIME 0x0007 +#define APM_CRIT_SUSPEND_REQ 0x0008 +#define APM_USER_STANDBY_REQ 0x0009 +#define APM_USER_SUSPEND_REQ 0x000A +#define APM_SYS_STANDBY_RESUME 0x000B +#define APM_CAPABILITY_CHANGE 0x000C /* apm v1.2 */ +#define APM_USER_HIBERNATE_REQ 0x000D +#define APM_EVENT_MASK 0xffff + +#define APM_EVENT_COMPOSE(t,i) ((((i) & 0x7fff) << 16)|((t) & APM_EVENT_MASK)) +#define APM_EVENT_TYPE(e) ((e) & APM_EVENT_MASK) +#define APM_EVENT_INDEX(e) ((e) >> 16) + +/* + * LP (Laptop Package) + * + * Copyright (C) 1994 by HOSOKAWA Tatsumi + * + * This software may be used, modified, copied, and distributed, in + * both source and binary form provided that the above copyright and + * these terms are retained. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with its + * use. + * + * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) + */ + +#define APM_BATTERY_ABSENT 4 + +struct apm_power_info { + u_char battery_state; + u_char ac_state; + u_char battery_life; + u_char spare1; + u_int minutes_left; /* estimate */ + u_int spare2[6]; +}; + +struct apm_ctl { + u_int dev; + u_int mode; +}; + +#define APM_IOC_REJECT _IOW('A', 0, struct apm_event_info) /* reject request # */ +#define APM_IOC_STANDBY _IO('A', 1) /* put system into standby */ +#define APM_IOC_SUSPEND _IO('A', 2) /* put system into suspend */ +#define APM_IOC_GETPOWER _IOR('A', 3, struct apm_power_info) /* fetch battery state */ +#define APM_IOC_DEV_CTL _IOW('A', 5, struct apm_ctl) /* put device into mode */ +#define APM_IOC_PRN_CTL _IOW('A', 6, int ) /* driver power status msg */ +#define APM_PRINT_ON 0 /* driver power status displayed */ +#define APM_PRINT_OFF 1 /* driver power status not displayed */ +#define APM_PRINT_PCT 2 /* driver power status only displayed + if the percentage changes */ +#define APM_IOC_STANDBY_REQ _IO('A', 7) /* request standby */ +#define APM_IOC_SUSPEND_REQ _IO('A', 8) /* request suspend */ +#define APM_IOC_HIBERNATE _IO('A', 9) /* put system into hibernate */ + +#endif /* _ARM_APMVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/armreg.h b/lib/libc/include/arm-openbsd-eabi/arm/armreg.h new file mode 100644 index 000000000000..ee51ae5616d2 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/armreg.h @@ -0,0 +1,392 @@ +/* $OpenBSD: armreg.h,v 1.43 2019/09/30 21:48:32 kettenis Exp $ */ +/* $NetBSD: armreg.h,v 1.27 2003/09/06 08:43:02 rearnsha Exp $ */ + +/* + * Copyright (c) 1998, 2001 Ben Harris + * Copyright (c) 1994-1996 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Brini. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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 _ARM_ARMREG_H +#define _ARM_ARMREG_H + +/* CCSIDR - Current Cache Size ID Register */ +#define CCSIDR_SETS_MASK 0x0fffe000 +#define CCSIDR_SETS_SHIFT 13 +#define CCSIDR_SETS(reg) \ + ((((reg) & CCSIDR_SETS_MASK) >> CCSIDR_SETS_SHIFT) + 1) +#define CCSIDR_WAYS_MASK 0x00001ff8 +#define CCSIDR_WAYS_SHIFT 3 +#define CCSIDR_WAYS(reg) \ + ((((reg) & CCSIDR_WAYS_MASK) >> CCSIDR_WAYS_SHIFT) + 1) +#define CCSIDR_LINE_MASK 0x00000007 +#define CCSIDR_LINE_SIZE(reg) (1 << (((reg) & CCSIDR_LINE_MASK) + 4)) + +/* CLIDR - Cache Level ID Register */ +#define CLIDR_CTYPE_MASK 0x7 +#define CLIDR_CTYPE_INSN 0x1 +#define CLIDR_CTYPE_DATA 0x2 +#define CLIDR_CTYPE_UNIFIED 0x4 + +/* CSSELR - Cache Size Selection Register */ +#define CSSELR_IND (1 << 0) +#define CSSELR_LEVEL_SHIFT 1 + +/* CTR - Cache Type Register */ +#define CTR_DLINE_SHIFT 16 +#define CTR_DLINE_MASK (0xf << CTR_DLINE_SHIFT) +#define CTR_DLINE_SIZE(reg) (((reg) & CTR_DLINE_MASK) >> CTR_DLINE_SHIFT) +#define CTR_IL1P_SHIFT 14 +#define CTR_IL1P_MASK (0x3 << CTR_IL1P_SHIFT) +#define CTR_IL1P_AIVIVT (0x1 << CTR_IL1P_SHIFT) +#define CTR_IL1P_VIPT (0x2 << CTR_IL1P_SHIFT) +#define CTR_IL1P_PIPT (0x3 << CTR_IL1P_SHIFT) +#define CTR_ILINE_SHIFT 0 +#define CTR_ILINE_MASK (0xf << CTR_ILINE_SHIFT) +#define CTR_ILINE_SIZE(reg) (((reg) & CTR_ILINE_MASK) >> CTR_ILINE_SHIFT) + +/* + * ARM Process Status Register + * + * The picture in early ARM manuals looks like this: + * 3 3 2 2 2 2 + * 1 0 9 8 7 6 8 7 6 5 4 0 + * +-+-+-+-+-+-------------------------------------+-+-+-+---------+ + * |N|Z|C|V|Q| reserved |I|F|T|M M M M M| + * | | | | | | | | | |4 3 2 1 0| + * +-+-+-+-+-+-------------------------------------+-+-+-+---------+ + * + * The picture in the ARMv7-A manuals looks like this: + * 3 3 2 2 2 2 2 2 2 2 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 0 9 6 5 0 9 8 7 6 5 4 0 + * +-+-+-+-+-+---+-+-------+-------+-----------+-+-+-+-+-+---------+ + * |N|Z|C|V|Q|I I|J|reserv-|G G G G|I I I I I I|E|A|I|F|T|M M M M M| + * | | | | | |T T| |ed |E E E E|T T T T T T| | | | | | | + * | | | | | |1 0| | |3 2 1 0|7 6 5 4 3 2| | | | | |4 3 2 1 0| + * +-+-+-+-+-+---+-+-------+-------+-----------+-+-+-+-+-+---------+ + * | flags 'f' | status 's' | extension 'x' | control 'c' | + */ + +#define PSR_FLAGS 0xf0000000 /* flags */ +#define PSR_N (1U << 31) /* negative */ +#define PSR_Z (1 << 30) /* zero */ +#define PSR_C (1 << 29) /* carry */ +#define PSR_V (1 << 28) /* overflow */ + +#define PSR_Q (1 << 27) /* saturation */ + +#define PSR_A (1 << 8) /* Asynchronous abort disable */ +#define PSR_I (1 << 7) /* IRQ disable */ +#define PSR_F (1 << 6) /* FIQ disable */ + +#define PSR_T (1 << 5) /* Thumb state */ +#define PSR_J (1 << 24) /* Java mode */ + +#define PSR_MODE 0x0000001f /* mode mask */ +#define PSR_USR26_MODE 0x00000000 +#define PSR_FIQ26_MODE 0x00000001 +#define PSR_IRQ26_MODE 0x00000002 +#define PSR_SVC26_MODE 0x00000003 +#define PSR_USR32_MODE 0x00000010 +#define PSR_FIQ32_MODE 0x00000011 +#define PSR_IRQ32_MODE 0x00000012 +#define PSR_SVC32_MODE 0x00000013 +#define PSR_MON32_MODE 0x00000016 +#define PSR_ABT32_MODE 0x00000017 +#define PSR_HYP32_MODE 0x0000001a +#define PSR_UND32_MODE 0x0000001b +#define PSR_SYS32_MODE 0x0000001f +#define PSR_32_MODE 0x00000010 + +#define PSR_IN_USR_MODE(psr) (!((psr) & 3)) /* XXX */ + +/* + * Co-processor 15: The system control co-processor. + */ + +#define ARM_CP15_CPU_ID 0 + +/* + * The CPU ID register is theoretically structured, but the definitions of + * the fields keep changing. + */ + +/* The high-order byte is always the implementor */ +#define CPU_ID_IMPLEMENTOR_MASK 0xff000000 +#define CPU_ID_ARM_LTD 0x41000000 /* 'A' */ + +#define CPU_ID_ARCH_MASK 0x000f0000 +#define CPU_ID_ARCH_V6 0x00070000 +#define CPU_ID_ARCH_CPUID 0x000f0000 +#define CPU_ID_VARIANT_MASK 0x00f00000 + +/* Next three nybbles are part number */ +#define CPU_ID_PARTNO_MASK 0x0000fff0 + +/* And finally, the revision number. */ +#define CPU_ID_REVISION_MASK 0x0000000f + +/* Individual CPUs are probably best IDed by everything but the revision. */ +#define CPU_ID_CPU_MASK 0xfffffff0 +#define CPU_ID_CORTEX_MASK 0xff0ffff0 +#define CPU_ID_CORTEX_A5 0x410fc050 +#define CPU_ID_CORTEX_A5_MASK 0xff0ffff0 +#define CPU_ID_CORTEX_A7 0x410fc070 +#define CPU_ID_CORTEX_A7_MASK 0xff0ffff0 +#define CPU_ID_CORTEX_A8_R1 0x411fc080 +#define CPU_ID_CORTEX_A8_R2 0x412fc080 +#define CPU_ID_CORTEX_A8_R3 0x413fc080 +#define CPU_ID_CORTEX_A8 0x410fc080 +#define CPU_ID_CORTEX_A8_MASK 0xff0ffff0 +#define CPU_ID_CORTEX_A9 0x410fc090 +#define CPU_ID_CORTEX_A9_R1 0x411fc090 +#define CPU_ID_CORTEX_A9_R2 0x412fc090 +#define CPU_ID_CORTEX_A9_R3 0x413fc090 +#define CPU_ID_CORTEX_A9_R4 0x414fc090 +#define CPU_ID_CORTEX_A9_MASK 0xff0ffff0 +#define CPU_ID_CORTEX_A12 0x410fc0d0 +#define CPU_ID_CORTEX_A12_MASK 0xff0ffff0 +#define CPU_ID_CORTEX_A15 0x410fc0f0 +#define CPU_ID_CORTEX_A15_R1 0x411fc0f0 +#define CPU_ID_CORTEX_A15_R2 0x412fc0f0 +#define CPU_ID_CORTEX_A15_R3 0x413fc0f0 +#define CPU_ID_CORTEX_A15_R4 0x414fc0f0 +#define CPU_ID_CORTEX_A15_MASK 0xff0ffff0 +#define CPU_ID_CORTEX_A17 0x410fc0e0 +#define CPU_ID_CORTEX_A17_R1 0x411fc0e0 +#define CPU_ID_CORTEX_A17_MASK 0xff0ffff0 +#define CPU_ID_CORTEX_A32 0x410fd010 +#define CPU_ID_CORTEX_A32_MASK 0xff0ffff0 +#define CPU_ID_CORTEX_A35 0x410fd040 +#define CPU_ID_CORTEX_A35_MASK 0xff0ffff0 +#define CPU_ID_CORTEX_A53 0x410fd030 +#define CPU_ID_CORTEX_A53_R1 0x411fd030 +#define CPU_ID_CORTEX_A53_MASK 0xff0ffff0 +#define CPU_ID_CORTEX_A55 0x410fd050 +#define CPU_ID_CORTEX_A55_MASK 0xff0ffff0 +#define CPU_ID_CORTEX_A57 0x410fd070 +#define CPU_ID_CORTEX_A57_R1 0x411fd070 +#define CPU_ID_CORTEX_A57_MASK 0xff0ffff0 +#define CPU_ID_CORTEX_A72 0x410fd080 +#define CPU_ID_CORTEX_A72_R1 0x411fd080 +#define CPU_ID_CORTEX_A72_MASK 0xff0ffff0 +#define CPU_ID_CORTEX_A73 0x410fd090 +#define CPU_ID_CORTEX_A73_MASK 0xff0ffff0 +#define CPU_ID_CORTEX_A75 0x410fd0a0 +#define CPU_ID_CORTEX_A75_MASK 0xff0ffff0 + +/* CPUID on >= v7 */ +#define ID_MMFR0_VMSA_MASK 0x0000000f + +#define VMSA_V7 3 +#define VMSA_V7_PXN 4 +#define VMSA_V7_LDT 5 + +/* + * Post-ARM3 CP15 registers: + * + * 1 Control register + * + * 2 Translation Table Base + * + * 3 Domain Access Control + * + * 4 Reserved + * + * 5 Fault Status + * + * 6 Fault Address + * + * 7 Cache/write-buffer Control + * + * 8 TLB Control + * + * 9 Cache Lockdown + * + * 10 TLB Lockdown + * + * 11 Reserved + * + * 12 Reserved + * + * 13 Process ID (for FCSE) + * + * 14 Reserved + * + * 15 Implementation Dependent + */ + +/* Some of the definitions below need cleaning up for V3/V4 architectures */ + +/* CPU control register (CP15 register 1) */ +#define CPU_CONTROL_MMU_ENABLE 0x00000001 /* M: MMU/Protection unit enable */ +#define CPU_CONTROL_AFLT_ENABLE 0x00000002 /* A: Alignment fault enable */ +#define CPU_CONTROL_DC_ENABLE 0x00000004 /* C: IDC/DC enable */ +#define CPU_CONTROL_WBUF_ENABLE 0x00000008 /* W: Write buffer enable */ +#define CPU_CONTROL_32BP_ENABLE 0x00000010 /* P: 32-bit exception handlers */ +#define CPU_CONTROL_32BD_ENABLE 0x00000020 /* D: 32-bit addressing */ +#define CPU_CONTROL_LABT_ENABLE 0x00000040 /* L: Late abort enable */ +#define CPU_CONTROL_BEND_ENABLE 0x00000080 /* B: Big-endian mode */ +#define CPU_CONTROL_SYST_ENABLE 0x00000100 /* S: System protection bit */ +#define CPU_CONTROL_ROM_ENABLE 0x00000200 /* R: ROM protection bit */ +#define CPU_CONTROL_CPCLK 0x00000400 /* F: Implementation defined */ +#define CPU_CONTROL_BPRD_ENABLE 0x00000800 /* Z: Branch prediction enable */ +#define CPU_CONTROL_IC_ENABLE 0x00001000 /* I: IC enable */ +#define CPU_CONTROL_VECRELOC 0x00002000 /* V: Vector relocation */ +#define CPU_CONTROL_ROUNDROBIN 0x00004000 /* RR: Predictable replacement */ +#define CPU_CONTROL_V4COMPAT 0x00008000 /* L4: ARMv4 compat LDR R15 etc */ + +/* below were added by V6 */ +#define CPU_CONTROL_FI (1<<21) /* FI: fast interrupts */ +#define CPU_CONTROL_U (1<<22) /* U: Unaligned */ +#define CPU_CONTROL_VE (1<<24) /* VE: Vector enable */ +#define CPU_CONTROL_EE (1<<25) /* EE: Exception Endianness */ +#define CPU_CONTROL_L2 (1<<25) /* L2: L2 cache enable */ + +/* added with v7 */ +#define CPU_CONTROL_WXN (1<<19) /* WXN: Write implies XN */ +#define CPU_CONTROL_UWXN (1<<20) /* UWXN: Unpriv write implies XN */ +#define CPU_CONTROL_NMFI (1<<27) /* NMFI: Non Maskable fast interrupt */ +#define CPU_CONTROL_TRE (1<<28) /* TRE: TEX Remap Enable */ +#define CPU_CONTROL_AFE (1<<29) /* AFE: Access Flag Enable */ +#define CPU_CONTROL_TE (1<<30) /* TE: Thumb Exception Enable */ + +#define CPU_CONTROL_IDC_ENABLE CPU_CONTROL_DC_ENABLE + +/* Cortex-A9 Auxiliary Control Register (CP15 register 1, opcode 1) */ +#define CORTEXA9_AUXCTL_FW (1 << 0) /* Cache and TLB updates broadcast */ +#define CORTEXA9_AUXCTL_L2PE (1 << 1) /* Prefetch hint enable */ +#define CORTEXA9_AUXCTL_L1PE (1 << 2) /* Data prefetch hint enable */ +#define CORTEXA9_AUXCTL_WR_ZERO (1 << 3) /* Ena. write full line of 0s mode */ +#define CORTEXA9_AUXCTL_SMP (1 << 6) /* Coherency is active */ +#define CORTEXA9_AUXCTL_EXCL (1 << 7) /* Exclusive cache bit */ +#define CORTEXA9_AUXCTL_ONEWAY (1 << 8) /* Allocate in on cache way only */ +#define CORTEXA9_AUXCTL_PARITY (1 << 9) /* Support parity checking */ + +/* Cache type register definitions */ +#define CPU_CT_ISIZE(x) ((x) & 0xfff) /* I$ info */ +#define CPU_CT_DSIZE(x) (((x) >> 12) & 0xfff) /* D$ info */ +#define CPU_CT_S (1U << 24) /* split cache */ +#define CPU_CT_CTYPE(x) (((x) >> 25) & 0xf) /* cache type */ +/* Cache type register definitions for ARM v7 */ +#define CPU_CT_IMINLINE(x) ((x) & 0xf) /* I$ min line size */ +#define CPU_CT_DMINLINE(x) (((x) >> 16) & 0xf) /* D$ min line size */ + +#define CPU_CT_CTYPE_WT 0 /* write-through */ +#define CPU_CT_CTYPE_WB1 1 /* write-back, clean w/ read */ +#define CPU_CT_CTYPE_WB2 2 /* w/b, clean w/ cp15,7 */ +#define CPU_CT_CTYPE_WB6 6 /* w/b, cp15,7, lockdown fmt A */ +#define CPU_CT_CTYPE_WB7 7 /* w/b, cp15,7, lockdown fmt B */ + +#define CPU_CT_xSIZE_LEN(x) ((x) & 0x3) /* line size */ +#define CPU_CT_xSIZE_M (1U << 2) /* multiplier */ +#define CPU_CT_xSIZE_ASSOC(x) (((x) >> 3) & 0x7) /* associativity */ +#define CPU_CT_xSIZE_SIZE(x) (((x) >> 6) & 0x7) /* size */ + +/* MPIDR, Multiprocessor Affinity Register */ +#define MPIDR_AFF2 (0xffU << 16) +#define MPIDR_AFF1 (0xffU << 8) +#define MPIDR_AFF0 (0xffU << 0) +#define MPIDR_AFF (MPIDR_AFF2|MPIDR_AFF1|MPIDR_AFF0) + +/* Fault status register definitions */ + +#define FAULT_USER 0x20 + +#define FAULT_WRTBUF_0 0x00 /* Vector Exception */ +#define FAULT_WRTBUF_1 0x02 /* Terminal Exception */ +#define FAULT_BUSERR_0 0x04 /* External Abort on Linefetch -- Section */ +#define FAULT_BUSERR_1 0x06 /* External Abort on Linefetch -- Page */ +#define FAULT_BUSERR_2 0x08 /* External Abort on Non-linefetch -- Section */ +#define FAULT_BUSERR_3 0x0a /* External Abort on Non-linefetch -- Page */ +#define FAULT_BUSTRNL1 0x0c /* External abort on Translation -- Level 1 */ +#define FAULT_BUSTRNL2 0x0e /* External abort on Translation -- Level 2 */ +#define FAULT_ALIGN_0 0x01 /* Alignment */ +#define FAULT_ALIGN_1 0x03 /* Alignment */ +#define FAULT_TRANS_S 0x05 /* Translation -- Section */ +#define FAULT_TRANS_P 0x07 /* Translation -- Page */ +#define FAULT_DOMAIN_S 0x09 /* Domain -- Section */ +#define FAULT_DOMAIN_P 0x0b /* Domain -- Page */ +#define FAULT_PERM_S 0x0d /* Permission -- Section */ +#define FAULT_PERM_P 0x0f /* Permission -- Page */ + +/* Fault type definitions for ARM v7 */ +#define FAULT_ACCESS_1 0x03 /* Access flag fault -- Level 1 */ +#define FAULT_ACCESS_2 0x06 /* Access flag fault -- Level 2 */ + +#define FAULT_IMPRECISE 0x400 /* Imprecise exception (XSCALE) */ + +#define FAULT_EXT 0x00001000 /* external abort */ +#define FAULT_WNR 0x00000800 /* write fault */ + +#define FAULT_TYPE(fsr) ((fsr) & 0x0f) +#define FAULT_TYPE_V7(fsr) (((fsr) & 0x0f) | (((fsr) & 0x00000400) >> 6)) + +/* + * Address of the vector page, low and high versions. + */ +#define ARM_VECTORS_LOW 0x00000000U +#define ARM_VECTORS_HIGH 0xffff0000U + +/* + * ARM Instructions + * + * 3 3 2 2 2 + * 1 0 9 8 7 0 + * +-------+-------------------------------------------------------+ + * | cond | instruction dependant | + * |c c c c| | + * +-------+-------------------------------------------------------+ + */ + +#define INSN_SIZE 4 /* Always 4 bytes */ +#define INSN_COND_MASK 0xf0000000 /* Condition mask */ +#define INSN_COND_AL 0xe0000000 /* Always condition */ + +/* Translation Table Base Register */ +#define TTBR_C (1 << 0) /* without MPE */ +#define TTBR_S (1 << 1) +#define TTBR_IMP (1 << 2) +#define TTBR_RGN_MASK (3 << 3) +#define TTBR_RGN_NC (0 << 3) +#define TTBR_RGN_WBWA (1 << 3) +#define TTBR_RGN_WT (2 << 3) +#define TTBR_RGN_WBNWA (3 << 3) +#define TTBR_NOS (1 << 5) +#define TTBR_IRGN_MASK ((1 << 0) | (1 << 6)) +#define TTBR_IRGN_NC ((0 << 0) | (0 << 6)) +#define TTBR_IRGN_WBWA ((0 << 0) | (1 << 6)) +#define TTBR_IRGN_WT ((1 << 0) | (0 << 6)) +#define TTBR_IRGN_WBNWA ((1 << 0) | (1 << 6)) + +#endif \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/asm.h b/lib/libc/include/arm-openbsd-eabi/arm/asm.h new file mode 100644 index 000000000000..b39691115ce5 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/asm.h @@ -0,0 +1,97 @@ +/* $OpenBSD: asm.h,v 1.13 2022/12/08 01:25:44 guenther Exp $ */ +/* $NetBSD: asm.h,v 1.4 2001/07/16 05:43:32 matt Exp $ */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)asm.h 5.5 (Berkeley) 5/7/91 + */ + +#ifndef _ARM_ASM_H_ +#define _ARM_ASM_H_ + +#define _C_LABEL(x) x +#define _ASM_LABEL(x) x + +#ifdef __STDC__ +# define __CONCAT(x,y) x ## y +# define __STRING(x) #x +#else +# define __CONCAT(x,y) x/**/y +# define __STRING(x) "x" +#endif + +#ifndef _ALIGN_TEXT +# define _ALIGN_TEXT .align 2 +#endif + +/* + * gas/arm uses @ as a single comment character and thus cannot be used here + * Instead it recognised the # instead of an @ symbols in .type directives + * We define a couple of macros so that assembly code will not be dependant + * on one or the other. + */ +#define _ASM_TYPE_FUNCTION #function +#define _ASM_TYPE_OBJECT #object + +/* NB == No Binding: use .globl or .weak as necessary */ +#define _ENTRY_NB(x) \ + .text; _ALIGN_TEXT; .type x,_ASM_TYPE_FUNCTION; x: +#define _ENTRY(x) .globl x; _ENTRY_NB(x) + +#if defined(PROF) || defined(GPROF) +# define _PROF_PROLOGUE \ + mov ip, lr; bl __mcount +#else +# define _PROF_PROLOGUE +#endif + +#define ENTRY(y) _ENTRY(y); _PROF_PROLOGUE +#define ENTRY_NP(y) _ENTRY(y) +#define ENTRY_NB(y) _ENTRY_NB(y); _PROF_PROLOGUE +#define ASENTRY(y) _ENTRY(y); _PROF_PROLOGUE +#define ASENTRY_NP(y) _ENTRY(y) +#define END(y) .size y, . - y + +#if defined(__PIC__) +#define PIC_SYM(x,y) x(y) +#else +#define PIC_SYM(x,y) x +#endif + +#define STRONG_ALIAS(alias,sym) \ + .global alias; \ + alias = sym +#define WEAK_ALIAS(alias,sym) \ + .weak alias; \ + alias = sym + +#endif /* !_ARM_ASM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/atomic.h b/lib/libc/include/arm-openbsd-eabi/arm/atomic.h new file mode 100644 index 000000000000..beef1c851952 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/atomic.h @@ -0,0 +1,295 @@ +/* $OpenBSD: atomic.h,v 1.19 2022/08/29 02:01:18 jsg Exp $ */ + +/* Public Domain */ + +#ifndef _ARM_ATOMIC_H_ +#define _ARM_ATOMIC_H_ + +/* + * Compare and set: + * ret = *ptr + * if (ret == expect) + * *ptr = new + * return (ret) + */ +#define _def_atomic_cas(_f, _t) \ +static inline _t \ +_f(volatile _t *p, _t e, _t n) \ +{ \ + _t ret, modified; \ + \ + __asm volatile ( \ + "1: ldrex %0, [%4] \n\t" \ + " cmp %0, %3 \n\t" \ + " bne 2f \n\t" \ + " strex %1, %2, [%4] \n\t" \ + " cmp %1, #0 \n\t" \ + " bne 1b \n\t" \ + " b 3f \n\t" \ + "2: clrex \n\t" \ + "3: \n\t" \ + : "=&r" (ret), "=&r" (modified) \ + : "r" (n), "r" (e), "r" (p) \ + : "memory", "cc" \ + ); \ + return (ret); \ +} +_def_atomic_cas(_atomic_cas_uint, unsigned int) +_def_atomic_cas(_atomic_cas_ulong, unsigned long) +#undef _def_atomic_cas + +#define atomic_cas_uint(_p, _e, _n) _atomic_cas_uint((_p), (_e), (_n)) +#define atomic_cas_ulong(_p, _e, _n) _atomic_cas_ulong((_p), (_e), (_n)) + +static inline void * +_atomic_cas_ptr(volatile void *p, void *e, void *n) +{ + void *ret; + unsigned long modified; + + __asm volatile ( + "1: ldrex %0, [%4] \n\t" + " cmp %0, %3 \n\t" + " bne 2f \n\t" + " strex %1, %2, [%4] \n\t" + " cmp %1, #0 \n\t" + " bne 1b \n\t" + " b 3f \n\t" + "2: clrex \n\t" + "3: \n\t" + : "=&r" (ret), "=&r" (modified) + : "r" (n), "r" (e), "r" (p) + : "memory", "cc" + ); + return (ret); +} +#define atomic_cas_ptr(_p, _e, _n) _atomic_cas_ptr((_p), (_e), (_n)) + +/* + * Swap: + * ret = *p + * *p = val + * return (ret) + */ +#define _def_atomic_swap(_f, _t) \ +static inline _t \ +_f(volatile _t *p, _t v) \ +{ \ + _t ret, modified; \ + \ + __asm volatile ( \ + "1: ldrex %0, [%3] \n\t" \ + " strex %1, %2, [%3] \n\t" \ + " cmp %1, #0 \n\t" \ + " bne 1b \n\t" \ + : "=&r" (ret), "=&r" (modified) \ + : "r" (v), "r" (p) \ + : "memory", "cc" \ + ); \ + return (ret); \ +} +_def_atomic_swap(_atomic_swap_uint, unsigned int) +_def_atomic_swap(_atomic_swap_ulong, unsigned long) +#undef _def_atomic_swap + +#define atomic_swap_uint(_p, _v) _atomic_swap_uint((_p), (_v)) +#define atomic_swap_ulong(_p, _v) _atomic_swap_ulong((_p), (_v)) + +static inline void * +_atomic_swap_ptr(volatile void *p, void *v) +{ + void *ret; + unsigned long modified; + + __asm volatile ( + "1: ldrex %0, [%3] \n\t" + " strex %1, %2, [%3] \n\t" + " cmp %1, #0 \n\t" + " bne 1b \n\t" + : "=&r" (ret), "=&r" (modified) + : "r" (v), "r" (p) + : "memory", "cc" + ); + return (ret); +} +#define atomic_swap_ptr(_p, _v) _atomic_swap_ptr((_p), (_v)) + +/* + * Increment returning the new value + * *p += 1 + * return (*p) + */ +#define _def_atomic_inc_nv(_f, _t) \ +static inline _t \ +_f(volatile _t *p) \ +{ \ + _t ret, modified; \ + \ + __asm volatile ( \ + "1: ldrex %0, [%2] \n\t" \ + " add %0, %0, #1 \n\t" \ + " strex %1, %0, [%2] \n\t" \ + " cmp %1, #0 \n\t" \ + " bne 1b \n\t" \ + : "=&r" (ret), "=&r" (modified) \ + : "r" (p) \ + : "memory", "cc" \ + ); \ + return (ret); \ +} +_def_atomic_inc_nv(_atomic_inc_int_nv, unsigned int) +_def_atomic_inc_nv(_atomic_inc_long_nv, unsigned long) +#undef _def_atomic_inc_nv + +#define atomic_inc_int_nv(_p) _atomic_inc_int_nv((_p)) +#define atomic_inc_long_nv(_p) _atomic_inc_long_nv((_p)) + +/* + * Decrement returning the new value + * *p -= 1 + * return (*p) + */ +#define _def_atomic_dec_nv(_f, _t) \ +static inline _t \ +_f(volatile _t *p) \ +{ \ + _t ret, modified; \ + \ + __asm volatile ( \ + "1: ldrex %0, [%2] \n\t" \ + " sub %0, %0, #1 \n\t" \ + " strex %1, %0, [%2] \n\t" \ + " cmp %1, #0 \n\t" \ + " bne 1b \n\t" \ + : "=&r" (ret), "=&r" (modified) \ + : "r" (p) \ + : "memory", "cc" \ + ); \ + return (ret); \ +} +_def_atomic_dec_nv(_atomic_dec_int_nv, unsigned int) +_def_atomic_dec_nv(_atomic_dec_long_nv, unsigned long) +#undef _def_atomic_dec_nv + +#define atomic_dec_int_nv(_p) _atomic_dec_int_nv((_p)) +#define atomic_dec_long_nv(_p) _atomic_dec_long_nv((_p)) + +/* + * Addition returning the new value + * *p += v + * return (*p) + */ +#define _def_atomic_add_nv(_f, _t) \ +static inline _t \ +_f(volatile _t *p, _t v) \ +{ \ + _t ret, modified; \ + \ + __asm volatile ( \ + "1: ldrex %0, [%2] \n\t" \ + " add %0, %0, %3 \n\t" \ + " strex %1, %0, [%2] \n\t" \ + " cmp %1, #0 \n\t" \ + " bne 1b \n\t" \ + : "=&r" (ret), "=&r" (modified) \ + : "r" (p), "r" (v) \ + : "memory", "cc" \ + ); \ + return (ret); \ +} +_def_atomic_add_nv(_atomic_add_int_nv, unsigned int) +_def_atomic_add_nv(_atomic_add_long_nv, unsigned long) +#undef _def_atomic_add_nv + +#define atomic_add_int_nv(_p, _v) _atomic_add_int_nv((_p), (_v)) +#define atomic_add_long_nv(_p, _v) _atomic_add_long_nv((_p), (_v)) + +/* + * Subtraction returning the new value + * *p -= v + * return (*p) + */ +#define _def_atomic_sub_nv(_f, _t) \ +static inline _t \ +_f(volatile _t *p, _t v) \ +{ \ + _t ret, modified; \ + \ + __asm volatile ( \ + "1: ldrex %0, [%2] \n\t" \ + " sub %0, %0, %3 \n\t" \ + " strex %1, %0, [%2] \n\t" \ + " cmp %1, #0 \n\t" \ + " bne 1b \n\t" \ + : "=&r" (ret), "=&r" (modified) \ + : "r" (p), "r" (v) \ + : "memory", "cc" \ + ); \ + return (ret); \ +} +_def_atomic_sub_nv(_atomic_sub_int_nv, unsigned int) +_def_atomic_sub_nv(_atomic_sub_long_nv, unsigned long) +#undef _def_atomic_sub_nv + +#define atomic_sub_int_nv(_p, _v) _atomic_sub_int_nv((_p), (_v)) +#define atomic_sub_long_nv(_p, _v) _atomic_sub_long_nv((_p), (_v)) + +#define __membar(_f) do { __asm volatile(_f ::: "memory"); } while (0) + +#define membar_enter() __membar("dmb sy") +#define membar_exit() __membar("dmb sy") +#define membar_producer() __membar("dmb st") +#define membar_consumer() __membar("dmb sy") +#define membar_sync() __membar("dmb sy") + +#if defined(_KERNEL) + +/* virtio needs MP membars even on SP kernels */ +#define virtio_membar_producer() __membar("dmb st") +#define virtio_membar_consumer() __membar("dmb sy") +#define virtio_membar_sync() __membar("dmb sy") + +/* + * Set bits + * *p = *p | v + */ +static inline void +atomic_setbits_int(volatile unsigned int *p, unsigned int v) +{ + unsigned int modified, tmp; + + __asm volatile ( + "1: ldrex %0, [%3] \n\t" + " orr %0, %0, %2 \n\t" + " strex %1, %0, [%3] \n\t" + " cmp %1, #0 \n\t" + " bne 1b \n\t" + : "=&r" (tmp), "=&r" (modified) + : "r" (v), "r" (p) + : "memory", "cc" + ); +} + +/* + * Clear bits + * *p = *p & (~v) + */ +static inline void +atomic_clearbits_int(volatile unsigned int *p, unsigned int v) +{ + unsigned int modified, tmp; + + __asm volatile ( + "1: ldrex %0, [%3] \n\t" + " bic %0, %0, %2 \n\t" + " strex %1, %0, [%3] \n\t" + " cmp %1, #0 \n\t" + " bne 1b \n\t" + : "=&r" (tmp), "=&r" (modified) + : "r" (v), "r" (p) + : "memory", "cc" + ); +} + +#endif /* defined(_KERNEL) */ +#endif /* _ARM_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/bus.h b/lib/libc/include/arm-openbsd-eabi/arm/bus.h new file mode 100644 index 000000000000..f31a6d2dd864 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/bus.h @@ -0,0 +1,882 @@ +/* $OpenBSD: bus.h,v 1.19 2025/08/11 07:18:40 miod Exp $ */ +/* $NetBSD: bus.h,v 1.12 2003/10/23 15:03:24 scw Exp $ */ + +/*- + * Copyright (c) 1996, 1997, 1998, 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1996 Charles M. Hannum. All rights reserved. + * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _ARM_BUS_H_ +#define _ARM_BUS_H_ + +/* + * Addresses (in bus space). + */ +typedef u_long bus_addr_t; +typedef u_long bus_size_t; + +/* + * Access methods for bus space. + */ +typedef struct bus_space *bus_space_tag_t; +typedef u_long bus_space_handle_t; + +/* + * int bus_space_map (bus_space_tag_t t, bus_addr_t addr, + * bus_size_t size, int flags, bus_space_handle_t *bshp); + * + * Map a region of bus space. + */ + +#define BUS_SPACE_MAP_CACHEABLE 0x01 +#define BUS_SPACE_MAP_LINEAR 0x02 +#define BUS_SPACE_MAP_PREFETCHABLE 0x04 + +struct bus_space { + /* cookie */ + void *bs_cookie; + + /* mapping/unmapping */ + int (*bs_map) (void *, uint64_t, bus_size_t, + int, bus_space_handle_t *); + void (*bs_unmap) (void *, bus_space_handle_t, + bus_size_t); + int (*bs_subregion) (void *, bus_space_handle_t, + bus_size_t, bus_size_t, bus_space_handle_t *); + + /* allocation/deallocation */ + int (*bs_alloc) (void *, bus_addr_t, bus_addr_t, + bus_size_t, bus_size_t, bus_size_t, int, + bus_addr_t *, bus_space_handle_t *); + void (*bs_free) (void *, bus_space_handle_t, + bus_size_t); + + /* get kernel virtual address */ + void * (*bs_vaddr) (void *, bus_space_handle_t); + + /* mmap bus space for user */ + paddr_t (*bs_mmap) (void *, bus_addr_t, off_t, int, int); + + /* barrier */ + void (*bs_barrier) (void *, bus_space_handle_t, + bus_size_t, bus_size_t, int); + + /* read (single) */ + u_int8_t (*bs_r_1) (void *, bus_space_handle_t, + bus_size_t); + u_int16_t (*bs_r_2) (void *, bus_space_handle_t, + bus_size_t); + u_int32_t (*bs_r_4) (void *, bus_space_handle_t, + bus_size_t); + u_int64_t (*bs_r_8) (void *, bus_space_handle_t, + bus_size_t); + + /* read multiple */ + void (*bs_rm_1) (void *, bus_space_handle_t, + bus_size_t, u_int8_t *, bus_size_t); + void (*bs_rm_2) (void *, bus_space_handle_t, + bus_size_t, u_int16_t *, bus_size_t); + void (*bs_rm_4) (void *, bus_space_handle_t, + bus_size_t, u_int32_t *, bus_size_t); + void (*bs_rm_8) (void *, bus_space_handle_t, + bus_size_t, u_int64_t *, bus_size_t); + + /* read region */ + void (*bs_rr_1) (void *, bus_space_handle_t, + bus_size_t, u_int8_t *, bus_size_t); + void (*bs_rr_2) (void *, bus_space_handle_t, + bus_size_t, u_int16_t *, bus_size_t); + void (*bs_rr_4) (void *, bus_space_handle_t, + bus_size_t, u_int32_t *, bus_size_t); + void (*bs_rr_8) (void *, bus_space_handle_t, + bus_size_t, u_int64_t *, bus_size_t); + + /* write (single) */ + void (*bs_w_1) (void *, bus_space_handle_t, + bus_size_t, u_int8_t); + void (*bs_w_2) (void *, bus_space_handle_t, + bus_size_t, u_int16_t); + void (*bs_w_4) (void *, bus_space_handle_t, + bus_size_t, u_int32_t); + void (*bs_w_8) (void *, bus_space_handle_t, + bus_size_t, u_int64_t); + + /* write multiple */ + void (*bs_wm_1) (void *, bus_space_handle_t, + bus_size_t, const u_int8_t *, bus_size_t); + void (*bs_wm_2) (void *, bus_space_handle_t, + bus_size_t, const u_int16_t *, bus_size_t); + void (*bs_wm_4) (void *, bus_space_handle_t, + bus_size_t, const u_int32_t *, bus_size_t); + void (*bs_wm_8) (void *, bus_space_handle_t, + bus_size_t, const u_int64_t *, bus_size_t); + + /* write region */ + void (*bs_wr_1) (void *, bus_space_handle_t, + bus_size_t, const u_int8_t *, bus_size_t); + void (*bs_wr_2) (void *, bus_space_handle_t, + bus_size_t, const u_int16_t *, bus_size_t); + void (*bs_wr_4) (void *, bus_space_handle_t, + bus_size_t, const u_int32_t *, bus_size_t); + void (*bs_wr_8) (void *, bus_space_handle_t, + bus_size_t, const u_int64_t *, bus_size_t); + + /* set multiple */ + void (*bs_sm_1) (void *, bus_space_handle_t, + bus_size_t, u_int8_t, bus_size_t); + void (*bs_sm_2) (void *, bus_space_handle_t, + bus_size_t, u_int16_t, bus_size_t); + void (*bs_sm_4) (void *, bus_space_handle_t, + bus_size_t, u_int32_t, bus_size_t); + void (*bs_sm_8) (void *, bus_space_handle_t, + bus_size_t, u_int64_t, bus_size_t); + + /* set region */ + void (*bs_sr_1) (void *, bus_space_handle_t, + bus_size_t, u_int8_t, bus_size_t); + void (*bs_sr_2) (void *, bus_space_handle_t, + bus_size_t, u_int16_t, bus_size_t); + void (*bs_sr_4) (void *, bus_space_handle_t, + bus_size_t, u_int32_t, bus_size_t); + void (*bs_sr_8) (void *, bus_space_handle_t, + bus_size_t, u_int64_t, bus_size_t); + + /* copy */ + void (*bs_c_1) (void *, bus_space_handle_t, bus_size_t, + bus_space_handle_t, bus_size_t, bus_size_t); + void (*bs_c_2) (void *, bus_space_handle_t, bus_size_t, + bus_space_handle_t, bus_size_t, bus_size_t); + void (*bs_c_4) (void *, bus_space_handle_t, bus_size_t, + bus_space_handle_t, bus_size_t, bus_size_t); + void (*bs_c_8) (void *, bus_space_handle_t, bus_size_t, + bus_space_handle_t, bus_size_t, bus_size_t); +}; + + +/* + * Utility macros; INTERNAL USE ONLY. + */ +#define __bs_c(a,b) __CONCAT(a,b) +#define __bs_opname(op,size) __bs_c(__bs_c(__bs_c(bs_,op),_),size) + +#define __bs_rs(sz, t, h, o) \ + (*(t)->__bs_opname(r,sz))((t)->bs_cookie, h, o) +#define __bs_ws(sz, t, h, o, v) \ + (*(t)->__bs_opname(w,sz))((t)->bs_cookie, h, o, v) +#define __bs_nonsingle(type, sz, t, h, o, a, c) \ + (*(t)->__bs_opname(type,sz))((t)->bs_cookie, h, o, a, c) +#define __bs_set(type, sz, t, h, o, v, c) \ + (*(t)->__bs_opname(type,sz))((t)->bs_cookie, h, o, v, c) +#define __bs_copy(sz, t, h1, o1, h2, o2, cnt) \ + (*(t)->__bs_opname(c,sz))((t)->bs_cookie, h1, o1, h2, o2, cnt) + +/* + * Mapping and unmapping operations. + */ +#define bus_space_map(t, a, s, c, hp) \ + (*(t)->bs_map)((t)->bs_cookie, (a), (s), (c), (hp)) +#define bus_space_unmap(t, h, s) \ + (*(t)->bs_unmap)((t)->bs_cookie, (h), (s)) +#define bus_space_subregion(t, h, o, s, hp) \ + (*(t)->bs_subregion)((t)->bs_cookie, (h), (o), (s), (hp)) + + +/* + * Allocation and deallocation operations. + */ +#define bus_space_alloc(t, rs, re, s, a, b, c, ap, hp) \ + (*(t)->bs_alloc)((t)->bs_cookie, (rs), (re), (s), (a), (b), \ + (c), (ap), (hp)) +#define bus_space_free(t, h, s) \ + (*(t)->bs_free)((t)->bs_cookie, (h), (s)) + +/* + * Get kernel virtual address for ranges mapped BUS_SPACE_MAP_LINEAR. + */ +#define bus_space_vaddr(t, h) \ + (*(t)->bs_vaddr)((t)->bs_cookie, (h)) + +/* + * MMap bus space for a user application. + */ +#define bus_space_mmap(t, a, o, p, f) \ + (*(t)->bs_mmap)((t)->bs_cookie, (a), (o), (p), (f)) + +/* + * Bus barrier operations. + */ +#define bus_space_barrier(t, h, o, l, f) \ + (*(t)->bs_barrier)((t)->bs_cookie, (h), (o), (l), (f)) + +#define BUS_SPACE_BARRIER_READ 0x01 +#define BUS_SPACE_BARRIER_WRITE 0x02 + +/* + * Bus read (single) operations. + */ +#define bus_space_read_1(t, h, o) __bs_rs(1,(t),(h),(o)) +#define bus_space_read_2(t, h, o) __bs_rs(2,(t),(h),(o)) +#define bus_space_read_4(t, h, o) __bs_rs(4,(t),(h),(o)) +#define bus_space_read_8(t, h, o) __bs_rs(8,(t),(h),(o)) + +/* + * Bus read multiple operations. + */ +#define bus_space_read_multi_1(t, h, o, a, c) \ + __bs_nonsingle(rm,1,(t),(h),(o),(a),(c)) +#define bus_space_read_multi_2(t, h, o, a, c) \ + __bs_nonsingle(rm,2,(t),(h),(o),(a),(c)) +#define bus_space_read_multi_4(t, h, o, a, c) \ + __bs_nonsingle(rm,4,(t),(h),(o),(a),(c)) +#define bus_space_read_multi_8(t, h, o, a, c) \ + __bs_nonsingle(rm,8,(t),(h),(o),(a),(c)) + +/* + * Bus read region operations. + */ +#define bus_space_read_region_1(t, h, o, a, c) \ + __bs_nonsingle(rr,1,(t),(h),(o),(a),(c)) +#define bus_space_read_region_2(t, h, o, a, c) \ + __bs_nonsingle(rr,2,(t),(h),(o),(a),(c)) +#define bus_space_read_region_4(t, h, o, a, c) \ + __bs_nonsingle(rr,4,(t),(h),(o),(a),(c)) +#define bus_space_read_region_8(t, h, o, a, c) \ + __bs_nonsingle(rr,8,(t),(h),(o),(a),(c)) + +/* + * Bus write (single) operations. + */ +#define bus_space_write_1(t, h, o, v) __bs_ws(1,(t),(h),(o),(v)) +#define bus_space_write_2(t, h, o, v) __bs_ws(2,(t),(h),(o),(v)) +#define bus_space_write_4(t, h, o, v) __bs_ws(4,(t),(h),(o),(v)) +#define bus_space_write_8(t, h, o, v) __bs_ws(8,(t),(h),(o),(v)) + +/* + * Bus write multiple operations. + */ +#define bus_space_write_multi_1(t, h, o, a, c) \ + __bs_nonsingle(wm,1,(t),(h),(o),(a),(c)) +#define bus_space_write_multi_2(t, h, o, a, c) \ + __bs_nonsingle(wm,2,(t),(h),(o),(a),(c)) +#define bus_space_write_multi_4(t, h, o, a, c) \ + __bs_nonsingle(wm,4,(t),(h),(o),(a),(c)) +#define bus_space_write_multi_8(t, h, o, a, c) \ + __bs_nonsingle(wm,8,(t),(h),(o),(a),(c)) + +/* + * Bus write region operations. + */ +#define bus_space_write_region_1(t, h, o, a, c) \ + __bs_nonsingle(wr,1,(t),(h),(o),(a),(c)) +#define bus_space_write_region_2(t, h, o, a, c) \ + __bs_nonsingle(wr,2,(t),(h),(o),(a),(c)) +#define bus_space_write_region_4(t, h, o, a, c) \ + __bs_nonsingle(wr,4,(t),(h),(o),(a),(c)) +#define bus_space_write_region_8(t, h, o, a, c) \ + __bs_nonsingle(wr,8,(t),(h),(o),(a),(c)) + +/* + * Set multiple operations. + */ +#define bus_space_set_multi_1(t, h, o, v, c) \ + __bs_set(sm,1,(t),(h),(o),(v),(c)) +#define bus_space_set_multi_2(t, h, o, v, c) \ + __bs_set(sm,2,(t),(h),(o),(v),(c)) +#define bus_space_set_multi_4(t, h, o, v, c) \ + __bs_set(sm,4,(t),(h),(o),(v),(c)) +#define bus_space_set_multi_8(t, h, o, v, c) \ + __bs_set(sm,8,(t),(h),(o),(v),(c)) + +/* + * Set region operations. + */ +#define bus_space_set_region_1(t, h, o, v, c) \ + __bs_set(sr,1,(t),(h),(o),(v),(c)) +#define bus_space_set_region_2(t, h, o, v, c) \ + __bs_set(sr,2,(t),(h),(o),(v),(c)) +#define bus_space_set_region_4(t, h, o, v, c) \ + __bs_set(sr,4,(t),(h),(o),(v),(c)) +#define bus_space_set_region_8(t, h, o, v, c) \ + __bs_set(sr,8,(t),(h),(o),(v),(c)) + +/* + * Copy operations. + */ +#define bus_space_copy_1(t, h1, o1, h2, o2, c) \ + __bs_copy(1, t, h1, o1, h2, o2, c) +#define bus_space_copy_2(t, h1, o1, h2, o2, c) \ + __bs_copy(2, t, h1, o1, h2, o2, c) +#define bus_space_copy_4(t, h1, o1, h2, o2, c) \ + __bs_copy(4, t, h1, o1, h2, o2, c) +#define bus_space_copy_8(t, h1, o1, h2, o2, c) \ + __bs_copy(8, t, h1, o1, h2, o2, c) + +/* + * Macros to provide prototypes for all the functions used in the + * bus_space structure + */ + +#define bs_map_proto(f) \ +int __bs_c(f,_bs_map) (void *t, uint64_t addr, \ + bus_size_t size, int flags, bus_space_handle_t *bshp); + +#define bs_unmap_proto(f) \ +void __bs_c(f,_bs_unmap) (void *t, bus_space_handle_t bsh, \ + bus_size_t size); + +#define bs_subregion_proto(f) \ +int __bs_c(f,_bs_subregion) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, bus_size_t size, \ + bus_space_handle_t *nbshp); + +#define bs_alloc_proto(f) \ +int __bs_c(f,_bs_alloc) (void *t, bus_addr_t rstart, \ + bus_addr_t rend, bus_size_t size, bus_size_t align, \ + bus_size_t boundary, int flags, bus_addr_t *addrp, \ + bus_space_handle_t *bshp); + +#define bs_free_proto(f) \ +void __bs_c(f,_bs_free) (void *t, bus_space_handle_t bsh, \ + bus_size_t size); + +#define bs_vaddr_proto(f) \ +void * __bs_c(f,_bs_vaddr) (void *t, bus_space_handle_t bsh); + +#define bs_mmap_proto(f) \ +paddr_t __bs_c(f,_bs_mmap) (void *, bus_addr_t, off_t, int, int); + +#define bs_barrier_proto(f) \ +void __bs_c(f,_bs_barrier) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, bus_size_t len, int flags); + +#define bs_r_1_proto(f) \ +u_int8_t __bs_c(f,_bs_r_1) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset); + +#define bs_r_2_proto(f) \ +u_int16_t __bs_c(f,_bs_r_2) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset); + +#define bs_r_4_proto(f) \ +u_int32_t __bs_c(f,_bs_r_4) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset); + +#define bs_r_8_proto(f) \ +u_int64_t __bs_c(f,_bs_r_8) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset); + +#define bs_w_1_proto(f) \ +void __bs_c(f,_bs_w_1) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, u_int8_t value); + +#define bs_w_2_proto(f) \ +void __bs_c(f,_bs_w_2) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, u_int16_t value); + +#define bs_w_4_proto(f) \ +void __bs_c(f,_bs_w_4) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, u_int32_t value); + +#define bs_w_8_proto(f) \ +void __bs_c(f,_bs_w_8) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, u_int64_t value); + +#define bs_rm_1_proto(f) \ +void __bs_c(f,_bs_rm_1) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, u_int8_t *addr, bus_size_t count); + +#define bs_rm_2_proto(f) \ +void __bs_c(f,_bs_rm_2) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, u_int16_t *addr, bus_size_t count); + +#define bs_rm_4_proto(f) \ +void __bs_c(f,_bs_rm_4) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, u_int32_t *addr, bus_size_t count); + +#define bs_rm_8_proto(f) \ +void __bs_c(f,_bs_rm_8) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, u_int64_t *addr, bus_size_t count); + +#define bs_wm_1_proto(f) \ +void __bs_c(f,_bs_wm_1) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, const u_int8_t *addr, bus_size_t count); + +#define bs_wm_2_proto(f) \ +void __bs_c(f,_bs_wm_2) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, const u_int16_t *addr, bus_size_t count); + +#define bs_wm_4_proto(f) \ +void __bs_c(f,_bs_wm_4) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, const u_int32_t *addr, bus_size_t count); + +#define bs_wm_8_proto(f) \ +void __bs_c(f,_bs_wm_8) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, const u_int64_t *addr, bus_size_t count); + +#define bs_rr_1_proto(f) \ +void __bs_c(f, _bs_rr_1) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, u_int8_t *addr, bus_size_t count); + +#define bs_rr_2_proto(f) \ +void __bs_c(f, _bs_rr_2) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, u_int16_t *addr, bus_size_t count); + +#define bs_rr_4_proto(f) \ +void __bs_c(f, _bs_rr_4) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, u_int32_t *addr, bus_size_t count); + +#define bs_rr_8_proto(f) \ +void __bs_c(f, _bs_rr_8) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, u_int64_t *addr, bus_size_t count); + +#define bs_wr_1_proto(f) \ +void __bs_c(f, _bs_wr_1) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, const u_int8_t *addr, bus_size_t count); + +#define bs_wr_2_proto(f) \ +void __bs_c(f, _bs_wr_2) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, const u_int16_t *addr, bus_size_t count); + +#define bs_wr_4_proto(f) \ +void __bs_c(f, _bs_wr_4) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, const u_int32_t *addr, bus_size_t count); + +#define bs_wr_8_proto(f) \ +void __bs_c(f, _bs_wr_8) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, const u_int64_t *addr, bus_size_t count); + +#define bs_sm_1_proto(f) \ +void __bs_c(f,_bs_sm_1) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, u_int8_t value, bus_size_t count); + +#define bs_sm_2_proto(f) \ +void __bs_c(f,_bs_sm_2) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, u_int16_t value, bus_size_t count); + +#define bs_sm_4_proto(f) \ +void __bs_c(f,_bs_sm_4) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, u_int32_t value, bus_size_t count); + +#define bs_sm_8_proto(f) \ +void __bs_c(f,_bs_sm_8) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, u_int64_t value, bus_size_t count); + +#define bs_sr_1_proto(f) \ +void __bs_c(f,_bs_sr_1) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, u_int8_t value, bus_size_t count); + +#define bs_sr_2_proto(f) \ +void __bs_c(f,_bs_sr_2) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, u_int16_t value, bus_size_t count); + +#define bs_sr_4_proto(f) \ +void __bs_c(f,_bs_sr_4) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, u_int32_t value, bus_size_t count); + +#define bs_sr_8_proto(f) \ +void __bs_c(f,_bs_sr_8) (void *t, bus_space_handle_t bsh, \ + bus_size_t offset, u_int64_t value, bus_size_t count); + +#define bs_c_1_proto(f) \ +void __bs_c(f,_bs_c_1) (void *t, bus_space_handle_t bsh1, \ + bus_size_t offset1, bus_space_handle_t bsh2, \ + bus_size_t offset2, bus_size_t count); + +#define bs_c_2_proto(f) \ +void __bs_c(f,_bs_c_2) (void *t, bus_space_handle_t bsh1, \ + bus_size_t offset1, bus_space_handle_t bsh2, \ + bus_size_t offset2, bus_size_t count); + +#define bs_c_4_proto(f) \ +void __bs_c(f,_bs_c_4) (void *t, bus_space_handle_t bsh1, \ + bus_size_t offset1, bus_space_handle_t bsh2, \ + bus_size_t offset2, bus_size_t count); + +#define bs_c_8_proto(f) \ +void __bs_c(f,_bs_c_8) (void *t, bus_space_handle_t bsh1, \ + bus_size_t offset1, bus_space_handle_t bsh2, \ + bus_size_t offset2, bus_size_t count); + +#define bs_protos(f) \ +bs_map_proto(f); \ +bs_unmap_proto(f); \ +bs_subregion_proto(f); \ +bs_alloc_proto(f); \ +bs_free_proto(f); \ +bs_vaddr_proto(f); \ +bs_mmap_proto(f); \ +bs_barrier_proto(f); \ +bs_r_1_proto(f); \ +bs_r_2_proto(f); \ +bs_r_4_proto(f); \ +bs_r_8_proto(f); \ +bs_w_1_proto(f); \ +bs_w_2_proto(f); \ +bs_w_4_proto(f); \ +bs_w_8_proto(f); \ +bs_rm_1_proto(f); \ +bs_rm_2_proto(f); \ +bs_rm_4_proto(f); \ +bs_rm_8_proto(f); \ +bs_wm_1_proto(f); \ +bs_wm_2_proto(f); \ +bs_wm_4_proto(f); \ +bs_wm_8_proto(f); \ +bs_rr_1_proto(f); \ +bs_rr_2_proto(f); \ +bs_rr_4_proto(f); \ +bs_rr_8_proto(f); \ +bs_wr_1_proto(f); \ +bs_wr_2_proto(f); \ +bs_wr_4_proto(f); \ +bs_wr_8_proto(f); \ +bs_sm_1_proto(f); \ +bs_sm_2_proto(f); \ +bs_sm_4_proto(f); \ +bs_sm_8_proto(f); \ +bs_sr_1_proto(f); \ +bs_sr_2_proto(f); \ +bs_sr_4_proto(f); \ +bs_sr_8_proto(f); \ +bs_c_1_proto(f); \ +bs_c_2_proto(f); \ +bs_c_4_proto(f); \ +bs_c_8_proto(f); + +/* Bus Space DMA macros */ + +/* + * Flags used in various bus DMA methods. + */ +#define BUS_DMA_WAITOK 0x0000 /* safe to sleep (pseudo-flag) */ +#define BUS_DMA_NOWAIT 0x0001 /* not safe to sleep */ +#define BUS_DMA_ALLOCNOW 0x0002 /* perform resource allocation now */ +#define BUS_DMA_COHERENT 0x0004 /* hint: map memory DMA coherent */ +#define BUS_DMA_STREAMING 0x0008 /* hint: sequential, unidirectional */ +#define BUS_DMA_BUS1 0x0010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x0020 +#define BUS_DMA_BUS3 0x0040 +#define BUS_DMA_BUS4 0x0080 +#define BUS_DMA_READ 0x0100 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x0200 /* mapping is memory -> device only */ +#define BUS_DMA_NOCACHE 0x0400 /* hint: map non-cached memory */ +#define BUS_DMA_ZERO 0x0800 /* dmamem_alloc returns zeroed mem */ +#define BUS_DMA_64BIT 0x1000 /* device handles 64bit dva */ + +/* + * Private flags stored in the DMA map. + */ +#define ARM32_DMAMAP_COHERENT 0x10000 /* no cache flush necessary on sync */ + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct uio; + +/* + * Operations performed by bus_dmamap_sync(). + */ +#define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */ +#define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */ +#define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */ +#define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */ + +typedef struct arm32_bus_dma_tag *bus_dma_tag_t; +typedef struct arm32_bus_dmamap *bus_dmamap_t; + +#define BUS_DMA_TAG_VALID(t) ((t) != (bus_dma_tag_t)0) + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +struct arm32_bus_dma_segment { + /* + * PUBLIC MEMBERS: these are used by machine-independent code. + */ + bus_addr_t ds_addr; /* DMA address */ + bus_size_t ds_len; /* length of transfer */ + /* + * PRIVATE MEMBERS: not for use by machine-independent code. + */ + bus_addr_t _ds_vaddr; /* Virtual mapped address + * Used by bus_dmamem_sync() */ + int _ds_coherent; /* Coherently mapped */ +}; +typedef struct arm32_bus_dma_segment bus_dma_segment_t; + +/* + * bus_dma_tag_t + * + * A machine-dependent opaque type describing the implementation of + * DMA for a given bus. + */ + +struct arm32_bus_dma_tag { + /* + * Opaque cookie for use by back-end. + */ + void *_cookie; + + /* + * DMA mapping methods. + */ + int (*_dmamap_create) (bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); + void (*_dmamap_destroy) (bus_dma_tag_t, bus_dmamap_t); + int (*_dmamap_load) (bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); + int (*_dmamap_load_mbuf) (bus_dma_tag_t, bus_dmamap_t, + struct mbuf *, int); + int (*_dmamap_load_uio) (bus_dma_tag_t, bus_dmamap_t, + struct uio *, int); + int (*_dmamap_load_raw) (bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); + int (*_dmamap_load_buffer)(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int, paddr_t *, int *, int); + void (*_dmamap_unload) (bus_dma_tag_t, bus_dmamap_t); + void (*_dmamap_sync) (bus_dma_tag_t, bus_dmamap_t, + bus_addr_t, bus_size_t, int); + + /* + * DMA memory utility functions. + */ + int (*_dmamem_alloc) (bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); + int (*_dmamem_alloc_range) (bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int, + paddr_t, paddr_t); + void (*_dmamem_free) (bus_dma_tag_t, + bus_dma_segment_t *, int); + int (*_dmamem_map) (bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); + void (*_dmamem_unmap) (bus_dma_tag_t, caddr_t, size_t); + paddr_t (*_dmamem_mmap) (bus_dma_tag_t, bus_dma_segment_t *, + int, off_t, int, int); +}; + +#define bus_dmamap_create(t, s, n, m, b, f, p) \ + (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) +#define bus_dmamap_destroy(t, p) \ + (*(t)->_dmamap_destroy)((t), (p)) +#define bus_dmamap_load(t, m, b, s, p, f) \ + (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) +#define bus_dmamap_load_mbuf(t, m, b, f) \ + (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) +#define bus_dmamap_load_uio(t, m, u, f) \ + (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) +#define bus_dmamap_load_raw(t, m, sg, n, s, f) \ + (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) +#define bus_dmamap_unload(t, p) \ + (*(t)->_dmamap_unload)((t), (p)) +#define bus_dmamap_sync(t, p, o, l, ops) \ + (void)((t)->_dmamap_sync ? \ + (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops)) : (void)0) + +#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ + (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f)) +#define bus_dmamem_alloc_range(t, s, a, b, sg, n, r, f, l, h) \ + (*(t)->_dmamem_alloc_range)((t), (s), (a), (b), (sg), \ + (n), (r), (f), (l), (h)) +#define bus_dmamem_free(t, sg, n) \ + (*(t)->_dmamem_free)((t), (sg), (n)) +#define bus_dmamem_map(t, sg, n, s, k, f) \ + (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f)) +#define bus_dmamem_unmap(t, k, s) \ + (*(t)->_dmamem_unmap)((t), (k), (s)) +#define bus_dmamem_mmap(t, sg, n, o, p, f) \ + (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f)) + +/* + * bus_dmamap_t + * + * Describes a DMA mapping. + */ +struct arm32_bus_dmamap { + /* + * PRIVATE MEMBERS: not for use by machine-independent code. + */ + bus_size_t _dm_size; /* largest DMA transfer mappable */ + int _dm_segcnt; /* number of segs this map can map */ + bus_size_t _dm_maxsegsz; /* largest possible segment */ + bus_size_t _dm_boundary; /* don't cross this */ + int _dm_flags; /* misc. flags */ + + void *_dm_origbuf; /* pointer to original buffer */ + int _dm_buftype; /* type of buffer */ + struct proc *_dm_proc; /* proc that owns the mapping */ + + void *_dm_cookie; /* cookie for bus-specific functions */ + + /* + * PUBLIC MEMBERS: these are used by machine-independent code. + */ + bus_size_t dm_mapsize; /* size of the mapping */ + int dm_nsegs; /* # valid segments in mapping */ + bus_dma_segment_t dm_segs[1]; /* segments; variable length */ +}; + +#ifdef _ARM32_BUS_DMA_PRIVATE + +/* _dm_buftype */ +#define ARM32_BUFTYPE_INVALID 0 +#define ARM32_BUFTYPE_LINEAR 1 +#define ARM32_BUFTYPE_MBUF 2 +#define ARM32_BUFTYPE_UIO 3 +#define ARM32_BUFTYPE_RAW 4 + +int _bus_dmamap_create (bus_dma_tag_t, bus_size_t, int, bus_size_t, + bus_size_t, int, bus_dmamap_t *); +void _bus_dmamap_destroy (bus_dma_tag_t, bus_dmamap_t); +int _bus_dmamap_load (bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); +int _bus_dmamap_load_mbuf (bus_dma_tag_t, bus_dmamap_t, + struct mbuf *, int); +int _bus_dmamap_load_uio (bus_dma_tag_t, bus_dmamap_t, + struct uio *, int); +int _bus_dmamap_load_raw (bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); +int _bus_dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int, paddr_t *, int *, int); +void _bus_dmamap_unload (bus_dma_tag_t, bus_dmamap_t); +void _bus_dmamap_sync (bus_dma_tag_t, bus_dmamap_t, bus_addr_t, + bus_size_t, int); + +int _bus_dmamem_alloc (bus_dma_tag_t tag, bus_size_t size, + bus_size_t alignment, bus_size_t boundary, + bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags); +void _bus_dmamem_free (bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs); +int _bus_dmamem_map (bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs, size_t size, caddr_t *kvap, int flags); +void _bus_dmamem_unmap (bus_dma_tag_t tag, caddr_t kva, + size_t size); +paddr_t _bus_dmamem_mmap (bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs, off_t off, int prot, int flags); + +int _bus_dmamem_alloc_range (bus_dma_tag_t tag, bus_size_t size, + bus_size_t alignment, bus_size_t boundary, + bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags, + vaddr_t low, vaddr_t high); +#endif /* _ARM32_BUS_DMA_PRIVATE */ +/* These are OpenBSD extensions to the general NetBSD bus interface. */ +void +bus_space_read_raw_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_addr_t ba, u_int8_t *dst, bus_size_t size); +void +bus_space_read_raw_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_addr_t ba, u_int8_t *dst, bus_size_t size); +#define bus_space_read_raw_multi_8 \ + !!! bus_space_read_raw_multi_8 not implemented !!! + +void +bus_space_write_raw_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_addr_t ba, const u_int8_t *src, bus_size_t size); +void +bus_space_write_raw_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_addr_t ba, const u_int8_t *src, bus_size_t size); +#define bus_space_write_raw_multi_8 \ + !!! bus_space_write_raw_multi_8 not implemented !!! + +/* + * void bus_space_read_raw_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_int8_t *addr, size_t count); + * + * Read `count' bytes in 2, 4 or 8 byte wide quantities from bus space + * described by tag/handle and starting at `offset' and copy into + * buffer provided. The buffer must have proper alignment for the N byte + * wide entities. Furthermore possible byte-swapping should be done by + * these functions. + */ + +#define bus_space_read_raw_region_2(t, h, o, a, c) \ + bus_space_read_region_2((t), (h), (o), (u_int16_t *)(a), (c) >> 1) +#define bus_space_read_raw_region_4(t, h, o, a, c) \ + bus_space_read_region_4((t), (h), (o), (u_int32_t *)(a), (c) >> 2) + +#if 0 /* Cause a link error for bus_space_read_raw_region_8 */ +#define bus_space_read_raw_region_8 \ + !!! bus_space_read_raw_region_8 unimplemented !!! +#endif + +/* + * void bus_space_write_raw_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_int8_t *addr, size_t count); + * + * Write `count' bytes in 2, 4 or 8 byte wide quantities to bus space + * described by tag/handle and starting at `offset' from the + * buffer provided. The buffer must have proper alignment for the N byte + * wide entities. Furthermore possible byte-swapping should be done by + * these functions. + */ + +#define bus_space_write_raw_region_2(t, h, o, a, c) \ + bus_space_write_region_2((t), (h), (o), (const u_int16_t *)(a), (c) >> 1) +#define bus_space_write_raw_region_4(t, h, o, a, c) \ + bus_space_write_region_4((t), (h), (o), (const u_int32_t *)(a), (c) >> 2) + +#if 0 /* Cause a link error for bus_space_write_raw_region_8 */ +#define bus_space_write_raw_region_8 \ + !!! bus_space_write_raw_region_8 unimplemented !!! +#endif + +#endif /* _ARM_BUS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/cdefs.h b/lib/libc/include/arm-openbsd-eabi/arm/cdefs.h new file mode 100644 index 000000000000..b2d807a184d9 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/cdefs.h @@ -0,0 +1,16 @@ +/* $OpenBSD: cdefs.h,v 1.4 2013/03/28 17:30:45 martynas Exp $ */ + +#ifndef _ARM_CDEFS_H_ +#define _ARM_CDEFS_H_ + +#define __strong_alias(alias,sym) \ + __asm__(".global " __STRING(alias) " ; " __STRING(alias) \ + " = " __STRING(sym)) +#define __weak_alias(alias,sym) \ + __asm__(".weak " __STRING(alias) " ; " __STRING(alias) \ + " = " __STRING(sym)) +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning." __STRING(sym) \ + " ; .ascii \"" msg "\" ; .text") + +#endif /* !_ARM_CDEFS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/conf.h b/lib/libc/include/arm-openbsd-eabi/arm/conf.h new file mode 100644 index 000000000000..ad76452696e6 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/conf.h @@ -0,0 +1,82 @@ +/* $OpenBSD: conf.h,v 1.12 2022/06/28 14:43:50 visa Exp $ */ +/* $NetBSD: conf.h,v 1.7 2002/04/19 01:04:39 wiz Exp $ */ + +/* + * Copyright (c) 1997 Mark Brinicombe. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mark Brinicombe + * for the NetBSD Project. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR 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. + * + * RiscBSD kernel project + * + * conf.h + * + * Prototypes for device driver functions + */ + +#ifndef _ARM_CONF_H_ +#define _ARM_CONF_H_ + + +#include + +#define mmread mmrw +#define mmwrite mmrw +cdev_decl(mm); + +bdev_decl(wd); +cdev_decl(wd); +bdev_decl(fd); +cdev_decl(fd); + +/* Character device declarations */ + +/* open, close, ioctl, kqueue */ +#define cdev_apm_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev, 0, 0, dev_init(c,n,kqfilter) } + +cdev_decl(com); +cdev_decl(lpt); +cdev_decl(pci); +cdev_decl(apm); +cdev_decl(spkr); + +/* open, close, ioctl */ +#define cdev_openprom_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) nullop, 0, \ + (dev_type_mmap((*))) enodev } + +cdev_decl(openprom); + +#endif /* _ARM_CONF_H__ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/cpu.h b/lib/libc/include/arm-openbsd-eabi/arm/cpu.h new file mode 100644 index 000000000000..eb81d8ee82a3 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/cpu.h @@ -0,0 +1,338 @@ +/* $OpenBSD: cpu.h,v 1.67 2024/06/09 21:15:29 jca Exp $ */ +/* $NetBSD: cpu.h,v 1.34 2003/06/23 11:01:08 martin Exp $ */ + +/* + * Copyright (c) 1994-1996 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Brini. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. + * + * RiscBSD kernel project + * + * cpu.h + * + * CPU specific symbols + * + * Created : 18/09/94 + * + * Based on kate/katelib/arm6.h + */ + +#ifndef _ARM_CPU_H_ +#define _ARM_CPU_H_ + +/* + * User-visible definitions + */ + +/* CTL_MACHDEP definitions. */ + /* 1 formerly int: CPU_DEBUG */ + /* 2 formerly string: CPU_BOOTED_DEVICE */ + /* 3 formerly string: CPU_BOOTED_KERNEL */ +#define CPU_CONSDEV 4 /* struct: dev_t of our console */ +#define CPU_POWERSAVE 5 /* int: use CPU powersave mode */ +#define CPU_ALLOWAPERTURE 6 /* int: allow mmap of /dev/xf86 */ + /* 7 formerly int: apmwarn */ + /* 8 formerly int: keyboard reset */ + /* 9 formerly int: CPU_ZTSRAWMODE */ + /* 10 formerly struct: CPU_ZTSSCALE */ +#define CPU_MAXSPEED 11 /* int: number of valid machdep ids */ + /* 12 formerly int: CPU_LIDSUSPEND */ +#define CPU_LIDACTION 13 /* action caused by lid close */ +#define CPU_COMPATIBLE 14 /* compatible property */ +#define CPU_MAXID 15 /* number of valid machdep ids */ + +#define CTL_MACHDEP_NAMES { \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "console_device", CTLTYPE_STRUCT }, \ + { "powersave", CTLTYPE_INT }, \ + { "allowaperture", CTLTYPE_INT }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "maxspeed", CTLTYPE_INT }, \ + { 0, 0 }, \ + { "lidaction", CTLTYPE_INT }, \ + { "compatible", CTLTYPE_STRING }, \ +} + +#ifdef _KERNEL + +/* + * Kernel-only definitions + */ + +#include + +#include +#include +#include +#include + +/* 1 == use cpu_sleep(), 0 == don't */ +extern int cpu_do_powersave; + +/* All the CLKF_* macros take a struct clockframe * as an argument. */ + +/* + * CLKF_USERMODE: Return TRUE/FALSE (1/0) depending on whether the + * frame came from USR mode or not. + */ +#define CLKF_USERMODE(frame) ((frame->if_spsr & PSR_MODE) == PSR_USR32_MODE) + +/* + * CLKF_INTR: True if we took the interrupt from inside another + * interrupt handler. + */ +#define CLKF_INTR(frame) (curcpu()->ci_idepth > 1) + +/* + * CLKF_PC: Extract the program counter from a clockframe + */ +#define CLKF_PC(frame) (frame->if_pc) + +/* + * PROC_PC: Find out the program counter for the given process. + */ +#define PROC_PC(p) ((p)->p_addr->u_pcb.pcb_tf->tf_pc) +#define PROC_STACK(p) ((p)->p_addr->u_pcb.pcb_tf->tf_usr_sp) + +/* The address of the vector page. */ +extern vaddr_t vector_page; +void arm32_vector_init(vaddr_t, int); + +#define ARM_VEC_RESET (1 << 0) +#define ARM_VEC_UNDEFINED (1 << 1) +#define ARM_VEC_SWI (1 << 2) +#define ARM_VEC_PREFETCH_ABORT (1 << 3) +#define ARM_VEC_DATA_ABORT (1 << 4) +#define ARM_VEC_ADDRESS_EXCEPTION (1 << 5) +#define ARM_VEC_IRQ (1 << 6) +#define ARM_VEC_FIQ (1 << 7) + +#define ARM_NVEC 8 +#define ARM_VEC_ALL 0xffffffff + +/* + * Per-CPU information. For now we assume one CPU. + */ + +#include +#include +#include +#include + +struct cpu_info { + struct device *ci_dev; /* Device corresponding to this CPU */ + struct cpu_info *ci_next; + struct schedstate_percpu ci_schedstate; /* scheduler state */ + + u_int32_t ci_cpuid; + uint64_t ci_mpidr; + int ci_node; + struct cpu_info *ci_self; + + struct proc *ci_curproc; + struct proc *ci_fpuproc; + u_int32_t ci_randseed; + + struct pcb *ci_curpcb; + struct pcb *ci_idle_pcb; + + uint32_t ci_cpl; + uint32_t ci_ipending; + uint32_t ci_idepth; +#ifdef DIAGNOSTIC + int ci_mutex_level; +#endif + int ci_want_resched; + + void (*ci_flush_bp)(void); + + struct opp_table *ci_opp_table; + volatile int ci_opp_idx; + volatile int ci_opp_max; + uint32_t ci_cpu_supply; + +#ifdef MULTIPROCESSOR + struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM]; + volatile int ci_flags; + uint32_t ci_ttbr0; + vaddr_t ci_pl1_stkend; + vaddr_t ci_irq_stkend; + vaddr_t ci_abt_stkend; + vaddr_t ci_und_stkend; +#endif + +#ifdef GPROF + struct gmonparam *ci_gmon; + struct clockintr ci_gmonclock; +#endif + struct clockqueue ci_queue; + char ci_panicbuf[512]; +}; + +#define CPUF_PRIMARY (1<<0) +#define CPUF_AP (1<<1) +#define CPUF_IDENTIFY (1<<2) +#define CPUF_IDENTIFIED (1<<3) +#define CPUF_PRESENT (1<<4) +#define CPUF_GO (1<<5) +#define CPUF_RUNNING (1<<6) + +static inline struct cpu_info * +curcpu(void) +{ + struct cpu_info *__ci; + __asm volatile("mrc p15, 0, %0, c13, c0, 4" : "=r" (__ci)); + return (__ci); +} + +extern struct cpu_info cpu_info_primary; +extern struct cpu_info *cpu_info_list; + +#ifndef MULTIPROCESSOR +#define cpu_number() 0 +#define CPU_IS_PRIMARY(ci) 1 +#define CPU_IS_RUNNING(ci) 1 +#define CPU_INFO_ITERATOR int +#define CPU_INFO_FOREACH(cii, ci) \ + for (cii = 0, ci = curcpu(); ci != NULL; ci = NULL) +#define CPU_INFO_UNIT(ci) 0 +#define MAXCPUS 1 +#define cpu_kick(ci) +#define cpu_unidle(ci) +#else +#define cpu_number() (curcpu()->ci_cpuid) +#define CPU_IS_PRIMARY(ci) ((ci) == &cpu_info_primary) +#define CPU_IS_RUNNING(ci) ((ci)->ci_flags & CPUF_RUNNING) +#define CPU_INFO_ITERATOR int +#define CPU_INFO_FOREACH(cii, ci) for (cii = 0, ci = cpu_info_list; \ + ci != NULL; ci = ci->ci_next) +#define CPU_INFO_UNIT(ci) ((ci)->ci_dev ? (ci)->ci_dev->dv_unit : 0) +#define MAXCPUS 4 +void cpu_kick(struct cpu_info *); +void cpu_unidle(struct cpu_info *ci); + +extern struct cpu_info *cpu_info[MAXCPUS]; + +void cpu_boot_secondary_processors(void); +#endif /* !MULTIPROCESSOR */ + +#define CPU_BUSY_CYCLE() __asm volatile ("" ::: "memory") + +#define curpcb curcpu()->ci_curpcb + +unsigned int cpu_rnd_messybits(void); + +/* + * Scheduling glue + */ + +extern int astpending; +#define setsoftast() (astpending = 1) + +/* + * Notify the current process (p) that it has a signal pending, + * process as soon as possible. + */ + +#define signotify(p) setsoftast() + +/* + * Preempt the current process if in interrupt from user mode, + * or after the current trap/syscall if in system mode. + */ +extern int want_resched; /* resched() was called */ +#define need_resched(ci) (want_resched = 1, setsoftast()) +#define clear_resched(ci) want_resched = 0 + +/* + * Give a profiling tick to the current process when the user profiling + * buffer pages are invalid. On the i386, request an ast to send us + * through trap(), marking the proc as needing a profiling tick. + */ +#define need_proftick(p) setsoftast() + +/* + * cpu device glue (belongs in cpuvar.h) + */ + +int cpu_alloc_idle_pcb(struct cpu_info *); + +/* + * Random cruft + */ + +/* cpuswitch.S */ +struct pcb; +void savectx (struct pcb *pcb); + +/* machdep.h */ +void bootsync (int); + +/* fault.c */ +int badaddr_read (void *, size_t, void *); + +/* syscall.c */ +void swi_handler (trapframe_t *); + +/* machine_machdep.c */ +void board_startup(void); + +static inline u_long +intr_disable(void) +{ + uint32_t cpsr; + + __asm volatile ("mrs %0, cpsr" : "=r"(cpsr)); + __asm volatile ("msr cpsr_c, %0" :: "r"(cpsr | PSR_I)); + + return cpsr; +} + +static inline void +intr_restore(u_long cpsr) +{ + __asm volatile ("msr cpsr_c, %0" :: "r"(cpsr)); +} + +#endif /* _KERNEL */ + +#ifdef MULTIPROCESSOR +#include +#endif /* MULTIPROCESSOR */ + +#endif /* !_ARM_CPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/cpuconf.h b/lib/libc/include/arm-openbsd-eabi/arm/cpuconf.h new file mode 100644 index 000000000000..a1576f651121 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/cpuconf.h @@ -0,0 +1,53 @@ +/* $OpenBSD: cpuconf.h,v 1.20 2024/11/07 08:12:12 miod Exp $ */ +/* $NetBSD: cpuconf.h,v 1.7 2003/05/23 00:57:24 ichiro Exp $ */ + +/* + * Copyright (c) 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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 _ARM_CPUCONF_H_ +#define _ARM_CPUCONF_H_ + +/* + * Define which MMU classes are configured: + * + * ARM_MMU_V7 v6/v7 MMU with XP bit enabled subpage + * protection is not used, TEX/AP is used instead. + */ + +#define ARM_MMU_V7 1 + +#define ARM_NMMUS (ARM_MMU_V7) + +#endif /* _ARM_CPUCONF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/cpufunc.h b/lib/libc/include/arm-openbsd-eabi/arm/cpufunc.h new file mode 100644 index 000000000000..07d18177ae0d --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/cpufunc.h @@ -0,0 +1,339 @@ +/* $OpenBSD: cpufunc.h,v 1.34 2023/05/30 08:30:00 jsg Exp $ */ +/* $NetBSD: cpufunc.h,v 1.29 2003/09/06 09:08:35 rearnsha Exp $ */ + +/* + * Copyright (c) 1997 Mark Brinicombe. + * Copyright (c) 1997 Causality Limited + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Causality Limited. + * 4. The name of Causality Limited may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``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 CAUSALITY LIMITED 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. + * + * RiscBSD kernel project + * + * cpufunc.h + * + * Prototypes for cpu, mmu and tlb related functions. + */ + +#ifndef _ARM_CPUFUNC_H_ +#define _ARM_CPUFUNC_H_ + +#ifdef _KERNEL + +#include +#include + +struct cpu_functions { + + /* CPU functions */ + + u_int (*cf_id) (void); + void (*cf_cpwait) (void); + + /* MMU functions */ + + u_int (*cf_control) (u_int clear, u_int set); + u_int (*cf_auxcontrol) (u_int clear, u_int set); + void (*cf_domains) (u_int domains); + void (*cf_setttb) (u_int ttb); + u_int (*cf_dfsr) (void); + u_int (*cf_dfar) (void); + u_int (*cf_ifsr) (void); + u_int (*cf_ifar) (void); + + /* TLB functions */ + + void (*cf_tlb_flushID) (void); + void (*cf_tlb_flushID_SE) (u_int va); + void (*cf_tlb_flushI) (void); + void (*cf_tlb_flushI_SE) (u_int va); + void (*cf_tlb_flushD) (void); + void (*cf_tlb_flushD_SE) (u_int va); + + /* + * Cache operations: + * + * We define the following primitives: + * + * icache_sync_all Synchronize I-cache + * icache_sync_range Synchronize I-cache range + * + * dcache_wbinv_all Write-back and Invalidate D-cache + * dcache_wbinv_range Write-back and Invalidate D-cache range + * dcache_inv_range Invalidate D-cache range + * dcache_wb_range Write-back D-cache range + * + * idcache_wbinv_all Write-back and Invalidate D-cache, + * Invalidate I-cache + * idcache_wbinv_range Write-back and Invalidate D-cache, + * Invalidate I-cache range + * + * Note that the ARM term for "write-back" is "clean". We use + * the term "write-back" since it's a more common way to describe + * the operation. + * + * There are some rules that must be followed: + * + * I-cache Synch (all or range): + * The goal is to synchronize the instruction stream, + * so you may need to write-back dirty D-cache blocks + * first. If a range is requested, and you can't + * synchronize just a range, you have to hit the whole + * thing. + * + * D-cache Write-Back and Invalidate range: + * If you can't WB-Inv a range, you must WB-Inv the + * entire D-cache. + * + * D-cache Invalidate: + * If you can't Inv the D-cache, you must Write-Back + * and Invalidate. Code that uses this operation + * MUST NOT assume that the D-cache will not be written + * back to memory. + * + * D-cache Write-Back: + * If you can't Write-back without doing an Inv, + * that's fine. Then treat this as a WB-Inv. + * Skipping the invalidate is merely an optimization. + * + * All operations: + * Valid virtual addresses must be passed to each + * cache operation. + */ + void (*cf_icache_sync_all) (void); + void (*cf_icache_sync_range) (vaddr_t, vsize_t); + + void (*cf_dcache_wbinv_all) (void); + void (*cf_dcache_wbinv_range) (vaddr_t, vsize_t); + void (*cf_dcache_inv_range) (vaddr_t, vsize_t); + void (*cf_dcache_wb_range) (vaddr_t, vsize_t); + + void (*cf_idcache_wbinv_all) (void); + void (*cf_idcache_wbinv_range) (vaddr_t, vsize_t); + + void (*cf_sdcache_wbinv_all) (void); + void (*cf_sdcache_wbinv_range) (vaddr_t, paddr_t, vsize_t); + void (*cf_sdcache_inv_range) (vaddr_t, paddr_t, vsize_t); + void (*cf_sdcache_wb_range) (vaddr_t, paddr_t, vsize_t); + void (*cf_sdcache_drain_writebuf) (void); + + /* Other functions */ + + void (*cf_flush_prefetchbuf) (void); + void (*cf_drain_writebuf) (void); + + void (*cf_sleep) (int mode); + + /* Soft functions */ + void (*cf_context_switch) (u_int); + void (*cf_setup) (void); +}; + +extern struct cpu_functions cpufuncs; +extern u_int cputype; + +#define cpu_id() cpufuncs.cf_id() +#define cpu_cpwait() cpufuncs.cf_cpwait() + +#define cpu_control(c, s) cpufuncs.cf_control(c, s) +#define cpu_auxcontrol(c, s) cpufuncs.cf_auxcontrol(c, s) +#define cpu_domains(d) cpufuncs.cf_domains(d) +#define cpu_setttb(t) cpufuncs.cf_setttb(t) +#define cpu_dfsr() cpufuncs.cf_dfsr() +#define cpu_dfar() cpufuncs.cf_dfar() +#define cpu_ifsr() cpufuncs.cf_ifsr() +#define cpu_ifar() cpufuncs.cf_ifar() + +#define cpu_tlb_flushID() cpufuncs.cf_tlb_flushID() +#define cpu_tlb_flushID_SE(e) cpufuncs.cf_tlb_flushID_SE(e) +#define cpu_tlb_flushI() cpufuncs.cf_tlb_flushI() +#define cpu_tlb_flushI_SE(e) cpufuncs.cf_tlb_flushI_SE(e) +#define cpu_tlb_flushD() cpufuncs.cf_tlb_flushD() +#define cpu_tlb_flushD_SE(e) cpufuncs.cf_tlb_flushD_SE(e) + +#define cpu_icache_sync_all() cpufuncs.cf_icache_sync_all() +#define cpu_icache_sync_range(a, s) cpufuncs.cf_icache_sync_range((a), (s)) + +#define cpu_dcache_wbinv_all() cpufuncs.cf_dcache_wbinv_all() +#define cpu_dcache_wbinv_range(a, s) cpufuncs.cf_dcache_wbinv_range((a), (s)) +#define cpu_dcache_inv_range(a, s) cpufuncs.cf_dcache_inv_range((a), (s)) +#define cpu_dcache_wb_range(a, s) cpufuncs.cf_dcache_wb_range((a), (s)) + +#define cpu_idcache_wbinv_all() cpufuncs.cf_idcache_wbinv_all() +#define cpu_idcache_wbinv_range(a, s) cpufuncs.cf_idcache_wbinv_range((a), (s)) + +#define cpu_sdcache_enabled() (cpufuncs.cf_sdcache_wbinv_all != cpufunc_nullop) +#define cpu_sdcache_wbinv_all() cpufuncs.cf_sdcache_wbinv_all() +#define cpu_sdcache_wbinv_range(va, pa, s) cpufuncs.cf_sdcache_wbinv_range((va), (pa), (s)) +#define cpu_sdcache_inv_range(va, pa, s) cpufuncs.cf_sdcache_inv_range((va), (pa), (s)) +#define cpu_sdcache_wb_range(va, pa, s) cpufuncs.cf_sdcache_wb_range((va), (pa), (s)) +#define cpu_sdcache_drain_writebuf() cpufuncs.cf_sdcache_drain_writebuf() + +#define cpu_flush_prefetchbuf() cpufuncs.cf_flush_prefetchbuf() +#define cpu_drain_writebuf() cpufuncs.cf_drain_writebuf() + +#define cpu_sleep(m) cpufuncs.cf_sleep(m) + +#define cpu_context_switch(a) cpufuncs.cf_context_switch(a) +#define cpu_setup(a) cpufuncs.cf_setup(a) + +int set_cpufuncs (void); +#define ARCHITECTURE_NOT_PRESENT 1 /* known but not configured */ +#define ARCHITECTURE_NOT_SUPPORTED 2 /* not known */ + +void cpufunc_nullop (void); +int early_abort_fixup (void *); +int late_abort_fixup (void *); +u_int cpufunc_id (void); +u_int cpufunc_control (u_int clear, u_int set); +u_int cpufunc_auxcontrol (u_int clear, u_int set); +void cpufunc_domains (u_int domains); +u_int cpufunc_dfsr (void); +u_int cpufunc_dfar (void); +u_int cpufunc_ifsr (void); +u_int cpufunc_ifar (void); + +void armv7_setttb (u_int); + +void armv7_tlb_flushID_SE (u_int); +void armv7_tlb_flushI_SE (u_int); + +void armv7_context_switch (u_int); + +void armv7_setup (void); +void armv7_tlb_flushID (void); +void armv7_tlb_flushI (void); +void armv7_tlb_flushD (void); +void armv7_tlb_flushD_SE (u_int va); + +void armv7_flush_bp(void); +void cortex_a15_flush_bp(void); + +void armv7_drain_writebuf (void); +void armv7_cpu_sleep (int mode); + +u_int armv7_periphbase (void); + +void armv7_icache_sync_all (void); +void armv7_icache_sync_range (vaddr_t, vsize_t); + +void armv7_dcache_wbinv_all (void); +void armv7_dcache_wbinv_range (vaddr_t, vsize_t); +void armv7_dcache_inv_range (vaddr_t, vsize_t); +void armv7_dcache_wb_range (vaddr_t, vsize_t); + +void armv7_idcache_wbinv_all (void); +void armv7_idcache_wbinv_range (vaddr_t, vsize_t); + +extern unsigned armv7_dcache_sets_max; +extern unsigned armv7_dcache_sets_inc; +extern unsigned armv7_dcache_index_max; +extern unsigned armv7_dcache_index_inc; + +#define tlb_flush cpu_tlb_flushID +#define setttb cpu_setttb +#define drain_writebuf cpu_drain_writebuf + +/* + * Macros for manipulating CPU interrupts + */ +/* Functions to manipulate the CPSR. */ +static __inline u_int32_t __set_cpsr_c(u_int bic, u_int eor); +static __inline u_int32_t __get_cpsr(void); + +static __inline u_int32_t +__set_cpsr_c(u_int bic, u_int eor) +{ + u_int32_t tmp, ret; + + __asm volatile( + "mrs %0, cpsr\n\t" /* Get the CPSR */ + "bic %1, %0, %2\n\t" /* Clear bits */ + "eor %1, %1, %3\n\t" /* XOR bits */ + "msr cpsr_c, %1" /* Set CPSR control field */ + : "=&r" (ret), "=&r" (tmp) + : "r" (bic), "r" (eor)); + + return ret; +} + +static __inline u_int32_t +__get_cpsr(void) +{ + u_int32_t ret; + + __asm volatile("mrs %0, cpsr" : "=&r" (ret)); + + return ret; +} + +#define disable_interrupts(mask) \ + (__set_cpsr_c((mask) & (PSR_I | PSR_F), \ + (mask) & (PSR_I | PSR_F))) + +#define enable_interrupts(mask) \ + (__set_cpsr_c((mask) & (PSR_I | PSR_F), 0)) + +#define restore_interrupts(old_cpsr) \ + (__set_cpsr_c((PSR_I | PSR_F), (old_cpsr) & (PSR_I | PSR_F))) + +/* + * Functions to manipulate cpu r13 + * (in arm/arm/setstack.S) + */ + +void set_stackptr (u_int mode, u_int address); +u_int get_stackptr (u_int mode); + +/* + * CPU functions from locore.S + */ + +void cpu_reset (void) __attribute__((__noreturn__)); + +/* + * Cache info variables. + */ + +/* PRIMARY CACHE VARIABLES */ +extern int arm_picache_size; +extern int arm_picache_line_size; +extern int arm_picache_ways; + +extern int arm_pdcache_size; /* and unified */ +extern int arm_pdcache_line_size; +extern int arm_pdcache_ways; + +extern int arm_pcache_type; +extern int arm_pcache_unified; + +extern int arm_dcache_align; +extern int arm_dcache_align_mask; + +#endif /* _KERNEL */ +#endif /* _ARM_CPUFUNC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/db_machdep.h b/lib/libc/include/arm-openbsd-eabi/arm/db_machdep.h new file mode 100644 index 000000000000..e5cb80c22d72 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/db_machdep.h @@ -0,0 +1,104 @@ +/* $OpenBSD: db_machdep.h,v 1.13 2021/08/30 08:11:12 jasper Exp $ */ +/* $NetBSD: db_machdep.h,v 1.5 2001/11/22 18:00:00 thorpej Exp $ */ + +/* + * Copyright (c) 1996 Scott K Stevens + * + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#ifndef _ARM_DB_MACHDEP_H_ +#define _ARM_DB_MACHDEP_H_ + +/* + * Machine-dependent defines for new kernel debugger. + */ + +#include +#include +#include +#include + +/* end of mangling */ + +typedef long db_expr_t; /* expression - signed */ + +typedef trapframe_t db_regs_t; + +extern db_regs_t ddb_regs; /* register state */ + +#define PC_REGS(regs) ((vaddr_t)(regs)->tf_pc) +#define SET_PC_REGS(regs, value) (regs)->tf_pc = (register_t)(value) + +#define BKPT_INST (KERNEL_BREAKPOINT) /* breakpoint instruction */ +#define BKPT_SIZE (INSN_SIZE) /* size of breakpoint inst */ +#define BKPT_SET(inst) (BKPT_INST) + +/*#define FIXUP_PC_AFTER_BREAK(regs) ((regs)->tf_pc -= BKPT_SIZE)*/ + +#define T_BREAKPOINT (1) + +#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BREAKPOINT) +#define IS_WATCHPOINT_TRAP(type, code) (0) + +#define inst_trap_return(ins) (0) +/* ldmxx reg, {..., pc} + 01800000 stack mode + 000f0000 register + 0000ffff register list */ +/* mov pc, reg + 0000000f register */ +#define inst_return(ins) (((ins) & 0x0e108000) == 0x08108000 || \ + ((ins) & 0x0ff0fff0) == 0x01a0f000) +/* bl ... + 00ffffff offset>>2 */ +#define inst_call(ins) (((ins) & 0x0f000000) == 0x0b000000) +/* b ... + 00ffffff offset>>2 */ +/* ldr pc, [pc, reg, lsl #2] + 0000000f register */ +#define inst_branch(ins) (((ins) & 0x0f000000) == 0x0a000000 || \ + ((ins) & 0x0fdffff0) == 0x079ff100) +#define inst_unconditional_flow_transfer(ins) \ + ((((ins) & INSN_COND_MASK) == INSN_COND_AL) && \ + (inst_branch(ins) || inst_call(ins) || inst_return(ins))) + +#define getreg_val (0) +#define next_instr_address(pc, bd) ((bd) ? (pc) : ((pc) + INSN_SIZE)) + +#define DB_MACHINE_COMMANDS + +#define SOFTWARE_SSTEP + +vaddr_t db_branch_taken(u_int inst, vaddr_t pc, db_regs_t *regs); +int db_ktrap (int, db_regs_t *); +void db_machine_init (void); + +#define branch_taken(ins, pc, fun, regs) \ + db_branch_taken((ins), (pc), (regs)) + +void db_show_frame_cmd(db_expr_t, int, db_expr_t, char *); + +#endif /* _ARM_DB_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/disklabel.h b/lib/libc/include/arm-openbsd-eabi/arm/disklabel.h new file mode 100644 index 000000000000..302bb5510342 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/disklabel.h @@ -0,0 +1,45 @@ +/* $OpenBSD: disklabel.h,v 1.15 2015/09/30 15:35:30 krw Exp $ */ + +/* + * Copyright (c) 1994 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Brini. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_DISKLABEL_H_ +#define _MACHINE_DISKLABEL_H_ + +#define LABELSECTOR 1 /* sector containing label */ +#define LABELOFFSET 0 /* offset of label in sector */ +#define MAXPARTITIONS 16 /* number of partitions */ + +#endif /* _MACHINE_DISKLABEL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/elf.h b/lib/libc/include/arm-openbsd-eabi/arm/elf.h new file mode 100644 index 000000000000..2c9d2c87b630 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/elf.h @@ -0,0 +1,77 @@ +/* $OpenBSD: elf.h,v 1.1 2024/07/14 09:48:48 jca Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2001 David E. O'Brien + * Copyright (c) 1996-1997 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_ELF_H_ +#define _MACHINE_ELF_H_ + +/* + * ELF definitions for the ARM architecture. + */ + +#ifdef _KERNEL +# define __HAVE_CPU_HWCAP +# define __HAVE_CPU_HWCAP2 +extern unsigned long hwcap, hwcap2; +#endif /* _KERNEL */ + +/* Flags passed in AT_HWCAP. */ +#define HWCAP_SWP 0x00000001 /* Unsupported, never set. */ +#define HWCAP_HALF 0x00000002 /* Always set. */ +#define HWCAP_THUMB 0x00000004 +#define HWCAP_26BIT 0x00000008 /* Unsupported, never set. */ +#define HWCAP_FAST_MULT 0x00000010 /* Always set. */ +#define HWCAP_FPA 0x00000020 /* Unsupported, never set. */ +#define HWCAP_VFP 0x00000040 +#define HWCAP_EDSP 0x00000080 /* Always set for ARMv6+. */ +#define HWCAP_JAVA 0x00000100 /* Unsupported, never set. */ +#define HWCAP_IWMMXT 0x00000200 /* Unsupported, never set. */ +#define HWCAP_CRUNCH 0x00000400 /* Unsupported, never set. */ +#define HWCAP_THUMBEE 0x00000800 +#define HWCAP_NEON 0x00001000 +#define HWCAP_VFPv3 0x00002000 +#define HWCAP_VFPv3D16 0x00004000 +#define HWCAP_TLS 0x00008000 /* Always set for ARMv6+. */ +#define HWCAP_VFPv4 0x00010000 +#define HWCAP_IDIVA 0x00020000 +#define HWCAP_IDIVT 0x00040000 +#define HWCAP_VFPD32 0x00080000 +#define HWCAP_IDIV (HWCAP_IDIVA | HWCAP_IDIVT) +#define HWCAP_LPAE 0x00100000 +#define HWCAP_EVTSTRM 0x00200000 /* Not implemented yet. */ + +/* Flags passed in AT_HWCAP2. */ +#define HWCAP2_AES 0x00000001 +#define HWCAP2_PMULL 0x00000002 +#define HWCAP2_SHA1 0x00000004 +#define HWCAP2_SHA2 0x00000008 +#define HWCAP2_CRC32 0x00000010 + +#endif /* !_MACHINE_ELF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/endian.h b/lib/libc/include/arm-openbsd-eabi/arm/endian.h new file mode 100644 index 000000000000..5075fc147587 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/endian.h @@ -0,0 +1,29 @@ +/* $OpenBSD: endian.h,v 1.12 2024/05/07 14:26:48 naddy Exp $ */ + +/* + * Copyright (c) 2015 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _ARM_ENDIAN_H_ +#define _ARM_ENDIAN_H_ + +#define _BYTE_ORDER _LITTLE_ENDIAN +#define __STRICT_ALIGNMENT + +#ifndef __FROM_SYS__ENDIAN +#include +#endif + +#endif /* _ARM_ENDIAN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/exec.h b/lib/libc/include/arm-openbsd-eabi/arm/exec.h new file mode 100644 index 000000000000..52730e7d75a2 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/exec.h @@ -0,0 +1,44 @@ +/* $OpenBSD: exec.h,v 1.6 2017/02/08 05:09:25 guenther Exp $ */ +/* $NetBSD: exec.h,v 1.6 1994/10/27 04:16:05 cgd Exp $ */ + +/* + * Copyright (c) 1993 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _ARM_EXEC_H_ +#define _ARM_EXEC_H_ + +#define __LDPGSZ 4096 + +#define ARCH_ELFSIZE 32 + +#define ELF_TARG_CLASS ELFCLASS32 +#define ELF_TARG_DATA ELFDATA2LSB +#define ELF_TARG_MACH EM_ARM + +#define PT_ARM_EXIDX 0x70000001 + +#endif /* _ARM_EXEC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/fdt.h b/lib/libc/include/arm-openbsd-eabi/arm/fdt.h new file mode 100644 index 000000000000..213caef44cae --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/fdt.h @@ -0,0 +1,59 @@ +/* $OpenBSD: fdt.h,v 1.10 2020/07/14 15:34:14 patrick Exp $ */ +/* + * Copyright (c) 2016 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __ARM_FDT_H__ +#define __ARM_FDT_H__ + +#define _ARM32_BUS_DMA_PRIVATE +#include + +struct fdt_attach_args { + const char *fa_name; + int fa_node; + bus_space_tag_t fa_iot; + bus_dma_tag_t fa_dmat; + struct fdt_reg *fa_reg; + int fa_nreg; + uint32_t *fa_intr; + int fa_nintr; + int fa_acells; + int fa_scells; +}; + +extern int stdout_node; +extern int stdout_speed; +extern bus_space_tag_t fdt_cons_bs_tag; + +void *fdt_find_cons(const char *); + +#define fdt_intr_enable arm_intr_enable +#define fdt_intr_establish arm_intr_establish_fdt +#define fdt_intr_establish_cpu arm_intr_establish_fdt_cpu +#define fdt_intr_establish_idx arm_intr_establish_fdt_idx +#define fdt_intr_establish_idx_cpu arm_intr_establish_fdt_idx_cpu +#define fdt_intr_establish_imap arm_intr_establish_fdt_imap +#define fdt_intr_establish_imap_cpu arm_intr_establish_fdt_imap_cpu +#define fdt_intr_establish_msi arm_intr_establish_fdt_msi +#define fdt_intr_establish_msi_cpu arm_intr_establish_fdt_msi_cpu +#define fdt_intr_disable arm_intr_disable +#define fdt_intr_disestablish arm_intr_disestablish_fdt +#define fdt_intr_get_parent arm_intr_get_parent +#define fdt_intr_parent_establish arm_intr_parent_establish_fdt +#define fdt_intr_parent_disestablish arm_intr_parent_disestablish_fdt +#define fdt_intr_register arm_intr_register_fdt + +#endif /* __ARM_FDT_H__ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/fenv.h b/lib/libc/include/arm-openbsd-eabi/arm/fenv.h new file mode 100644 index 000000000000..c9c49d0ab180 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/fenv.h @@ -0,0 +1,97 @@ +/* $OpenBSD: fenv.h,v 1.3 2011/05/25 21:46:49 martynas Exp $ */ + +/* + * Copyright (c) 2011 Martynas Venckus + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _ARM_FENV_H_ +#define _ARM_FENV_H_ + +/* + * Each symbol representing a floating point exception expands to an integer + * constant expression with values, such that bitwise-inclusive ORs of _all + * combinations_ of the constants result in distinct values. + * + * We use such values that allow direct bitwise operations on FPU registers. + */ +#define FE_INVALID 0x01 +#define FE_DIVBYZERO 0x02 +#define FE_OVERFLOW 0x04 +#define FE_UNDERFLOW 0x08 +#define FE_INEXACT 0x10 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * exception constants defined above. + */ +#define FE_ALL_EXCEPT (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | \ + FE_UNDERFLOW | FE_INEXACT) + +/* + * Each symbol representing the rounding direction, expands to an integer + * constant expression whose value is distinct non-negative value. + * + * We use such values that allow direct bitwise operations on FPU registers. + */ +#define FE_TONEAREST 0x0 +#define FE_UPWARD 0x1 +#define FE_DOWNWARD 0x2 +#define FE_TOWARDZERO 0x3 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * rounding direction constants defined above. + */ +#define _ROUND_MASK (FE_TONEAREST | FE_UPWARD | FE_DOWNWARD | \ + FE_TOWARDZERO) + +/* + * fenv_t represents the entire floating-point environment. + */ +typedef struct { + unsigned int __sticky; + unsigned int __mask; + unsigned int __round; +} fenv_t; + +/* + * The following constant represents the default floating-point environment + * (that is, the one installed at program startup) and has type pointer to + * const-qualified fenv_t. + * + * It can be used as an argument to the functions within the header + * that manage the floating-point environment, namely fesetenv() and + * feupdateenv(). + */ +__BEGIN_DECLS +extern fenv_t __fe_dfl_env; +__END_DECLS +#define FE_DFL_ENV ((const fenv_t *)&__fe_dfl_env) + +/* + * fexcept_t represents the floating-point status flags collectively, including + * any status the implementation associates with the flags. + * + * A floating-point status flag is a system variable whose value is set (but + * never cleared) when a floating-point exception is raised, which occurs as a + * side effect of exceptional floating-point arithmetic to provide auxiliary + * information. + * + * A floating-point control mode is a system variable whose value may be set by + * the user to affect the subsequent behavior of floating-point arithmetic. + */ +typedef unsigned int fexcept_t; + +#endif /* !_ARM_FENV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-freebsd-eabihf/machine/fiq.h b/lib/libc/include/arm-openbsd-eabi/arm/fiq.h similarity index 95% rename from lib/libc/include/arm-freebsd-eabihf/machine/fiq.h rename to lib/libc/include/arm-openbsd-eabi/arm/fiq.h index 13d84d5ba350..4abafaa056c8 100644 --- a/lib/libc/include/arm-freebsd-eabihf/machine/fiq.h +++ b/lib/libc/include/arm-openbsd-eabi/arm/fiq.h @@ -1,8 +1,7 @@ +/* $OpenBSD: fiq.h,v 1.1 2004/02/01 05:09:49 drahn Exp $ */ /* $NetBSD: fiq.h,v 1.1 2001/12/20 01:20:23 thorpej Exp $ */ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * +/* * Copyright (c) 2001 Wasabi Systems, Inc. * All rights reserved. * @@ -35,11 +34,10 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * */ -#ifndef _MACHINE_FIQ_H_ -#define _MACHINE_FIQ_H_ +#ifndef _ARM_FIQ_H_ +#define _ARM_FIQ_H_ #include @@ -68,4 +66,4 @@ void fiq_release(struct fiqhandler *); void fiq_getregs(struct fiqregs *); void fiq_setregs(struct fiqregs *); -#endif /* _MACHINE_FIQ_H_ */ \ No newline at end of file +#endif /* _ARM_FIQ_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/frame.h b/lib/libc/include/arm-openbsd-eabi/arm/frame.h new file mode 100644 index 000000000000..cbd99bcc8c7f --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/frame.h @@ -0,0 +1,297 @@ +/* $OpenBSD: frame.h,v 1.14 2022/12/08 01:25:44 guenther Exp $ */ +/* $NetBSD: frame.h,v 1.9 2003/12/01 08:48:33 scw Exp $ */ + +/* + * Copyright (c) 1994-1997 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Brini. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. + * + * RiscBSD kernel project + * + * frame.h + * + * Stack frames structures + * + * Created : 30/09/94 + */ + +#ifndef _ARM_FRAME_H_ +#define _ARM_FRAME_H_ + +#ifndef _LOCORE + +#include + +/* + * Trap frame. Pushed onto the kernel stack on a trap (synchronous exception). + */ + +typedef struct trapframe { + register_t tf_spsr; + register_t tf_r0; + register_t tf_r1; + register_t tf_r2; + register_t tf_r3; + register_t tf_r4; + register_t tf_r5; + register_t tf_r6; + register_t tf_r7; + register_t tf_r8; + register_t tf_r9; + register_t tf_r10; + register_t tf_r11; + register_t tf_r12; + register_t tf_usr_sp; + register_t tf_usr_lr; + register_t tf_svc_sp; + register_t tf_svc_lr; + register_t tf_pc; + register_t tf_pad; +} trapframe_t; + +/* Register numbers */ +#define tf_r13 tf_usr_sp +#define tf_r14 tf_usr_lr +#define tf_r15 tf_pc + +/* Determine if a fault came from user mode */ +#define TRAP_USERMODE(tf) ((tf->tf_spsr & PSR_MODE) == PSR_USR32_MODE) + +/* + * Signal frame. Pushed onto user stack before calling sigcode. + */ + +struct sigframe { + int sf_signum; + siginfo_t *sf_sip; + struct sigcontext *sf_scp; + sig_t sf_handler; + struct sigcontext sf_sc; + siginfo_t sf_si; +}; + +/* the pointers are used in the trampoline code to locate the ucontext */ +#if 0 +struct sigframe_siginfo { + siginfo_t sf_si; /* actual saved siginfo */ + ucontext_t sf_uc; /* actual saved ucontext */ +}; +#endif + +#if 0 +#ifdef _KERNEL +void sendsig_sigcontext(const ksiginfo_t *, const sigset_t *); +#endif +#endif + +#endif /* _LOCORE */ + +#ifndef _LOCORE + +/* + * System stack frames. + */ + +typedef struct irqframe { + unsigned int if_spsr; + unsigned int if_r0; + unsigned int if_r1; + unsigned int if_r2; + unsigned int if_r3; + unsigned int if_r4; + unsigned int if_r5; + unsigned int if_r6; + unsigned int if_r7; + unsigned int if_r8; + unsigned int if_r9; + unsigned int if_r10; + unsigned int if_r11; + unsigned int if_r12; + unsigned int if_usr_sp; + unsigned int if_usr_lr; + unsigned int if_svc_sp; + unsigned int if_svc_lr; + unsigned int if_pc; + unsigned int if_pad; +} irqframe_t; + +#define clockframe irqframe + +/* + * Switch frame + */ + +struct switchframe { + u_int sf_pad; + u_int sf_r4; + u_int sf_r5; + u_int sf_r6; + u_int sf_r7; + u_int sf_pc; +}; + +/* + * Stack frame. Used during stack traces (db_trace.c) + */ +struct frame { + u_int fr_fp; + u_int fr_sp; + u_int fr_lr; + u_int fr_pc; +}; + +#else /* _LOCORE */ + +#define AST_LOCALS \ +.Laflt_astpending: ;\ + .word astpending + +#define DO_AST \ + ldr r0, [sp] /* Get the SPSR from stack */ ;\ + mrs r4, cpsr /* save CPSR */ ;\ + and r0, r0, #(PSR_MODE) /* Returning to USR mode? */ ;\ + teq r0, #(PSR_USR32_MODE) ;\ + ldreq r5, .Laflt_astpending ;\ + bne 2f /* Nope, get out now */ ;\ + bic r4, r4, #(PSR_I) ;\ +1: orr r0, r4, #(PSR_I) /* Disable IRQs */ ;\ + msr cpsr_c, r0 ;\ + ldr r1, [r5] /* Pending AST? */ ;\ + teq r1, #0x00000000 ;\ + beq 2f /* Nope. Just bail */ ;\ + mov r1, #0x00000000 ;\ + str r1, [r5] /* Clear astpending */ ;\ + msr cpsr_c, r4 /* Restore interrupts */ ;\ + mov r0, sp ;\ + adr lr, 1b ;\ + b ast /* ast(frame) */ ;\ +2: + +/* + * ASM macros for pushing and pulling trapframes from the stack + * + * These macros are used to handle the irqframe and trapframe structures + * defined above. + */ + +/* + * CLREX - On ARMv7 machines that support atomic instructions, we need + * to clear the exclusive monitors on kernel exit, so that a userland + * atomic store can't succeed due to an unrelated outstanding atomic + * operation. ARM also highly recommends clearing the monitor on data + * aborts, as the monitor state after taking a data abort is unknown. + * Issuing a clrex on kernel entry and on kernel exit is the easiest + * way to take care of both issues and to make sure that the kernel + * and userland do not leave any outstanding reserves active. + */ + +/* + * PUSHFRAME - macro to push a trap frame on the stack in the current mode + * Since the current mode is used, the SVC lr field is not defined. + */ + +#define PUSHFRAME \ + clrex; \ + sub sp, sp, #4; /* Align the stack */ \ + str lr, [sp, #-4]!; /* Push the return address */ \ + sub sp, sp, #(4*17); /* Adjust the stack pointer */ \ + stmia sp, {r0-r14}^; /* Push the user mode registers */ \ + mov r0, r0; /* NOP for previous instruction */ \ + mrs r0, spsr; /* Put the SPSR on the stack */ \ + str r0, [sp, #-4]! + +/* + * PULLFRAME - macro to pull a trap frame from the stack in the current mode + * Since the current mode is used, the SVC lr field is ignored. + */ + +#define PULLFRAME \ + clrex; \ + ldr r0, [sp], #0x0004; /* Get the SPSR from stack */ \ + msr spsr_fsxc, r0; \ + ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \ + mov r0, r0; /* NOP for previous instruction */ \ + add sp, sp, #(4*17); /* Adjust the stack pointer */ \ + ldr lr, [sp], #0x0004; /* Pull the return address */ \ + add sp, sp, #4 /* Align the stack */ + +/* + * PUSHFRAMEINSVC - macro to push a trap frame on the stack in SVC32 mode + * This should only be used if the processor is not currently in SVC32 + * mode. The processor mode is switched to SVC mode and the trap frame is + * stored. The SVC lr field is used to store the previous value of + * lr in SVC mode. + */ + +#define PUSHFRAMEINSVC \ + clrex; \ + stmdb sp, {r0-r3}; /* Save 4 registers */ \ + mov r0, lr; /* Save xxx32 r14 */ \ + mov r1, sp; /* Save xxx32 sp */ \ + mrs r3, spsr; /* Save xxx32 spsr */ \ + mrs r2, cpsr; /* Get the CPSR */ \ + bic r2, r2, #(PSR_MODE); /* Fix for SVC mode */ \ + orr r2, r2, #(PSR_SVC32_MODE); \ + msr cpsr_c, r2; /* Punch into SVC mode */ \ + mov r2, sp; /* Save SVC sp */ \ + bic sp, sp, #7; /* Align sp to an 8-byte address */ \ + sub sp, sp, #4; /* Pad trapframe to keep alignment */ \ + str r0, [sp, #-4]!; /* Push return address */ \ + str lr, [sp, #-4]!; /* Push SVC lr */ \ + str r2, [sp, #-4]!; /* Push SVC sp */ \ + msr spsr_fsxc, r3; /* Restore correct spsr */ \ + ldmdb r1, {r0-r3}; /* Restore 4 regs from xxx mode */ \ + sub sp, sp, #(4*15); /* Adjust the stack pointer */ \ + stmia sp, {r0-r14}^; /* Push the user mode registers */ \ + mov r0, r0; /* NOP for previous instruction */ \ + mrs r0, spsr; /* Put the SPSR on the stack */ \ + str r0, [sp, #-4]! + +/* + * PULLFRAMEFROMSVCANDEXIT - macro to pull a trap frame from the stack + * in SVC32 mode and restore the saved processor mode and PC. + * This should be used when the SVC lr register needs to be restored on + * exit. + */ + +#define PULLFRAMEFROMSVCANDEXIT \ + clrex; \ + ldr r0, [sp], #0x0004; /* Get the SPSR from stack */ \ + msr spsr_fsxc, r0; /* restore SPSR */ \ + ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \ + mov r0, r0; /* NOP for previous instruction */ \ + add sp, sp, #(4*15); /* Adjust the stack pointer */ \ + ldmia sp, {sp, lr, pc}^ /* Restore lr and exit */ + +#endif /* _LOCORE */ + +#endif /* _ARM_FRAME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/ieee.h b/lib/libc/include/arm-openbsd-eabi/arm/ieee.h new file mode 100644 index 000000000000..dc7998e8d1b4 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/ieee.h @@ -0,0 +1,192 @@ +/* $OpenBSD: ieee.h,v 1.4 2011/11/08 17:06:51 deraadt Exp $ */ +/* $NetBSD: ieee.h,v 1.2 2001/02/21 17:43:50 bjh21 Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ieee.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * ieee.h defines the machine-dependent layout of the machine's IEEE + * floating point. + */ + +/* + * Define the number of bits in each fraction and exponent. + * + * k k+1 + * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented + * + * (-exp_bias+1) + * as fractions that look like 0.fffff x 2 . This means that + * + * -126 + * the number 0.10000 x 2 , for instance, is the same as the normalized + * + * -127 -128 + * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero + * + * -129 + * in the fraction; to represent 2 , we need two, and so on. This + * + * (-exp_bias-fracbits+1) + * implies that the smallest denormalized number is 2 + * + * for whichever format we are talking about: for single precision, for + * + * -126 -149 + * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and + * + * -149 == -127 - 23 + 1. + */ + +/* + * The ARM has two sets of FP data formats. The FPA supports 32-bit, 64-bit + * and 96-bit IEEE formats, with the words in big-endian order. VFP supports + * 32-bin and 64-bit IEEE formats with the words in the CPU's native byte + * order. + * + * The FPA also has two packed decimal formats, but we ignore them here. + */ + +#define SNG_EXPBITS 8 +#define SNG_FRACBITS 23 + +#define DBL_EXPBITS 11 +#define DBL_FRACHBITS 20 +#define DBL_FRACLBITS 32 +#define DBL_FRACBITS 52 + +#ifndef __VFP_FP__ +#define E80_EXPBITS 15 +#define E80_FRACHBITS 31 +#define E80_FRACLBITS 32 +#define E80_FRACBITS 64 + +#define EXT_EXPBITS 15 +#define EXT_FRACHBITS 16 +#define EXT_FRACHMBITS 32 +#define EXT_FRACLMBITS 32 +#define EXT_FRACLBITS 32 +#define EXT_FRACBITS 112 +#endif + +struct ieee_single { + u_int sng_frac:23; + u_int sng_exp:8; + u_int sng_sign:1; +}; + +#ifdef __VFP_FP__ +struct ieee_double { + u_int dbl_fracl; + u_int dbl_frach:20; + u_int dbl_exp:11; + u_int dbl_sign:1; +}; +#else /* !__VFP_FP__ */ +struct ieee_double { + u_int dbl_frach:20; + u_int dbl_exp:11; + u_int dbl_sign:1; + u_int dbl_fracl; +}; + +union ieee_double_u { + double dblu_d; + struct ieee_double dblu_dbl; +}; + + +struct ieee_e80 { + u_int e80_exp:15; + u_int e80_zero:16; + u_int e80_sign:1; + u_int e80_frach:31; + u_int e80_j:1; + u_int e80_fracl; +}; + +struct ieee_ext { + u_int ext_frach:16; + u_int ext_exp:15; + u_int ext_sign:1; + u_int ext_frachm; + u_int ext_fraclm; + u_int ext_fracl; +}; +#endif /* !__VFP_FP__ */ + +/* + * Floats whose exponent is in [1..INFNAN) (of whatever type) are + * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. + * Floats whose exponent is zero are either zero (iff all fraction + * bits are zero) or subnormal values. + * + * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its + * high fraction; if the bit is set, it is a `quiet NaN'. + */ +#define SNG_EXP_INFNAN 255 +#define DBL_EXP_INFNAN 2047 +#ifndef __VFP_FP__ +#define E80_EXP_INFNAN 32767 +#define EXT_EXP_INFNAN 32767 +#endif /* !__VFP_FP__ */ + +#if 0 +#define SNG_QUIETNAN (1 << 22) +#define DBL_QUIETNAN (1 << 19) +#ifndef __VFP_FP__ +#define E80_QUIETNAN (1 << 15) +#define EXT_QUIETNAN (1 << 15) +#endif /* !__VFP_FP__ */ +#endif + +/* + * Exponent biases. + */ +#define SNG_EXP_BIAS 127 +#define DBL_EXP_BIAS 1023 +#ifndef __VFP_FP__ +#define E80_EXP_BIAS 16383 +#define EXT_EXP_BIAS 16383 +#endif /* !__VFP_FP__ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/ieeefp.h b/lib/libc/include/arm-openbsd-eabi/arm/ieeefp.h new file mode 100644 index 000000000000..cf2906b99b8d --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/ieeefp.h @@ -0,0 +1,41 @@ +/* $OpenBSD: ieeefp.h,v 1.2 2011/03/23 16:54:34 pirofti Exp $ */ +/* $NetBSD: ieeefp.h,v 1.1 2001/01/10 19:02:06 bjh21 Exp $ */ + +/* + * Based on ieeefp.h written by J.T. Conklin, Apr 28, 1995 + * Public domain. + */ + +#ifndef _ARM_IEEEFP_H_ +#define _ARM_IEEEFP_H_ + +/* FP exception codes */ + +#define FP_EXCEPT_INV 0 +#define FP_EXCEPT_DZ 1 +#define FP_EXCEPT_OFL 2 +#define FP_EXCEPT_UFL 3 +#define FP_EXCEPT_IMP 4 + +/* Exception type (used by fpsetmask() et al.) */ + +typedef int fp_except; + +/* Bit defines for fp_except */ + +#define FP_X_INV (1 << FP_EXCEPT_INV) /* invalid operation exception */ +#define FP_X_DZ (1 << FP_EXCEPT_DZ) /* divide-by-zero exception */ +#define FP_X_OFL (1 << FP_EXCEPT_OFL) /* overflow exception */ +#define FP_X_UFL (1 << FP_EXCEPT_UFL) /* underflow exception */ +#define FP_X_IMP (1 << FP_EXCEPT_IMP) /* imprecise (loss of precision; "inexact") */ + +/* Rounding modes */ + +typedef enum { + FP_RN=0, /* round to nearest representable number */ + FP_RP=1, /* round toward positive infinity */ + FP_RM=2, /* round toward negative infinity */ + FP_RZ=3 /* round to zero (truncate) */ +} fp_rnd; + +#endif /* _ARM_IEEEFP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/kcore.h b/lib/libc/include/arm-openbsd-eabi/arm/kcore.h new file mode 100644 index 000000000000..5371f1021887 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/kcore.h @@ -0,0 +1,15 @@ +/* $OpenBSD: kcore.h,v 1.1 2007/05/19 15:49:05 miod Exp $ */ +/* public domain */ + +/* Make sure this is larger than DRAM_BLOCKS on all arm-based platforms */ +#define NPHYS_RAM_SEGS 8 + +typedef struct cpu_kcore_hdr { + u_int32_t kernelbase; /* value of KERNEL_BASE */ + u_int32_t kerneloffs; /* offset of kernel in RAM */ + u_int32_t staticsize; /* size of contiguous mapping */ + u_int32_t pmap_kernel_l1; /* pmap_kernel()->pm_l1 */ + u_int32_t pmap_kernel_l2; /* pmap_kernel()->pm_l2 */ + u_int32_t reserved[11]; + phys_ram_seg_t ram_segs[NPHYS_RAM_SEGS]; +} cpu_kcore_hdr_t; \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/limits.h b/lib/libc/include/arm-openbsd-eabi/arm/limits.h new file mode 100644 index 000000000000..822acbd3be3a --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/limits.h @@ -0,0 +1,53 @@ +/* $OpenBSD: limits.h,v 1.7 2015/04/30 13:42:08 millert Exp $ */ +/* $NetBSD: limits.h,v 1.4 2003/04/28 23:16:18 bjh21 Exp $ */ + +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)limits.h 7.2 (Berkeley) 6/28/90 + */ + +#ifndef _ARM_LIMITS_H_ +#define _ARM_LIMITS_H_ + +#include + +#if __POSIX_VISIBLE || __XPG_VISIBLE +#define SSIZE_MAX LONG_MAX /* max value for a ssize_t */ +#endif + +#if __BSD_VISIBLE +#define SIZE_T_MAX ULONG_MAX /* max value for a size_t (historic) */ + +#define UQUAD_MAX 0xffffffffffffffffULL /* max unsigned quad */ +#define QUAD_MAX 0x7fffffffffffffffLL /* max signed quad */ +#define QUAD_MIN (-0x7fffffffffffffffLL-1) /* min signed quad */ + +#endif /* __BSD_VISIBLE */ + +#endif /* _ARM_LIMITS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/machdep.h b/lib/libc/include/arm-openbsd-eabi/arm/machdep.h new file mode 100644 index 000000000000..8dba386dc195 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/machdep.h @@ -0,0 +1,20 @@ +/* $OpenBSD: machdep.h,v 1.6 2024/04/29 12:24:46 jsg Exp $ */ +/* $NetBSD: machdep.h,v 1.7 2002/02/21 02:52:21 thorpej Exp $ */ + +#ifndef _ARM_MACHDEP_H_ +#define _ARM_MACHDEP_H_ + +/* misc prototypes used by the many arm machdeps */ +void halt (void); +void data_abort_handler (trapframe_t *); +void prefetch_abort_handler (trapframe_t *); +void undefinedinstruction_bounce (trapframe_t *); +void dumpsys (void); + +/* + * note that we use void * as all the platforms have different ideas on what + * the structure is + */ +u_int initarm (void *, void *, void *, paddr_t); + +#endif \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/mplock.h b/lib/libc/include/arm-openbsd-eabi/arm/mplock.h new file mode 100644 index 000000000000..f3981f16b1b6 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/mplock.h @@ -0,0 +1,10 @@ +/* $OpenBSD: mplock.h,v 1.1 2018/08/06 18:39:13 kettenis Exp $ */ + +/* public domain */ + +#ifndef _MACHINE_MPLOCK_H_ +#define _MACHINE_MPLOCK_H_ + +#define __USE_MI_MPLOCK + +#endif /* !_MACHINE_MPLOCK_H */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/mutex.h b/lib/libc/include/arm-openbsd-eabi/arm/mutex.h new file mode 100644 index 000000000000..c10ae2bcb445 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/mutex.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mutex.h,v 1.5 2018/02/10 12:44:20 mpi Exp $ */ + +#define __USE_MI_MUTEX \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/openpromio.h b/lib/libc/include/arm-openbsd-eabi/arm/openpromio.h new file mode 100644 index 000000000000..45e430e353a2 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/openpromio.h @@ -0,0 +1,57 @@ +/* $OpenBSD: openpromio.h,v 1.1 2016/05/21 21:24:36 kettenis Exp $ */ +/* $NetBSD: openpromio.h,v 1.1.1.1 1998/06/20 04:58:52 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)openpromio.h 8.1 (Berkeley) 6/11/93 + */ + +struct opiocdesc { + int op_nodeid; /* passed or returned node id */ + int op_namelen; /* length of op_name */ + char *op_name; /* pointer to field name */ + int op_buflen; /* length of op_buf (value-result) */ + char *op_buf; /* pointer to field value */ +}; + +#define OPIOCGET _IOWR('O', 1, struct opiocdesc) /* get openprom field */ +#define OPIOCSET _IOW('O', 2, struct opiocdesc) /* set openprom field */ +#define OPIOCNEXTPROP _IOWR('O', 3, struct opiocdesc) /* get next property */ +#define OPIOCGETOPTNODE _IOR('O', 4, int) /* get openprom field */ +#define OPIOCGETNEXT _IOWR('O', 5, int) /* get next node of node */ +#define OPIOCGETCHILD _IOWR('O', 6, int) /* get first child of node */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/param.h b/lib/libc/include/arm-openbsd-eabi/arm/param.h new file mode 100644 index 000000000000..8b542e1d4da8 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/param.h @@ -0,0 +1,106 @@ +/* $OpenBSD: param.h,v 1.25 2023/12/14 13:26:49 claudio Exp $ */ + +/* + * Copyright (c) 1994,1995 Mark Brinicombe. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the RiscBSD team. + * 4. The name "RiscBSD" nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RISCBSD ``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 RISCBSD 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 _ARM_PARAM_H_ +#define _ARM_PARAM_H_ + +#define MACHINE_ARCH "arm" +#define _MACHINE_ARCH arm +#define MID_MACHINE MID_ARM6 + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define PAGE_MASK (PAGE_SIZE - 1) + +#ifdef _KERNEL + +#define NPTEPG (PAGE_SIZE/(sizeof (pt_entry_t))) + +#define NBPG PAGE_SIZE +#define PGSHIFT PAGE_SHIFT +#define PGOFSET PAGE_MASK + +#define UPAGES 2 /* pages of u-area */ +#define USPACE (UPAGES * PAGE_SIZE) /* total size of u-area */ +#define USPACE_ALIGN 0 /* u-area alignment 0-none */ + +#define NMBCLUSTERS (32 * 1024) /* max cluster allocation */ + +/* Constants used to divide the USPACE area */ +/* + * The USPACE area contains : + * 1. the user structure for the process + * 2. the fp context for FP emulation + * 3. the kernel (svc) stack + * 4. the undefined instruction stack + * + * The layout of the area looks like this + * + * | user area | FP context | undefined stack | kernel stack | + * + * The size of the user area is known. + * The size of the FP context is variable depending of the FP emulator + * in use and whether there is hardware FP support. However we can put + * an upper limit on it. + * The undefined stack needs to be at least 512 bytes. This is a requirement + * of the FP emulators + * The kernel stack should be at least 4K in size. + * + * The stack top addresses are used to set the stack pointers. The stack bottom + * addresses are the addresses monitored by the diagnostic code for stack + * overflows. + */ + +#define FPCONTEXTSIZE (0x100) +#define USPACE_SVC_STACK_TOP (USPACE) +#define USPACE_SVC_STACK_BOTTOM (USPACE_SVC_STACK_TOP - 0x1000) +#define USPACE_UNDEF_STACK_TOP (USPACE_SVC_STACK_BOTTOM - 0x10) +#define USPACE_UNDEF_STACK_BOTTOM (sizeof(struct user) + FPCONTEXTSIZE + 10) + +#ifndef _LOCORE +void delay (unsigned); +#define DELAY(x) delay(x) +#endif + +#if !defined(_LOCORE) +#include +#endif + +/* ARM-specific macro to align a stack pointer (downwards). */ +#define STACKALIGNBYTES (8 - 1) +#define STACKALIGN(p) ((u_long)(p) &~ STACKALIGNBYTES) + +#endif /* _KERNEL */ + +#endif /* _ARM_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/pcb.h b/lib/libc/include/arm-openbsd-eabi/arm/pcb.h new file mode 100644 index 000000000000..066db42bb343 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/pcb.h @@ -0,0 +1,91 @@ +/* $OpenBSD: pcb.h,v 1.8 2018/01/26 16:22:20 kettenis Exp $ */ +/* $NetBSD: pcb.h,v 1.10 2003/10/13 21:46:39 scw Exp $ */ + +/* + * Copyright (c) 2001 Matt Thomas . + * Copyright (c) 1994 Mark Brinicombe. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the RiscBSD team. + * 4. The name "RiscBSD" nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RISCBSD ``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 RISCBSD 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 _ARM_PCB_H_ +#define _ARM_PCB_H_ + +#include + +#include +#include + +struct trapframe; + +struct pcb_arm32 { + paddr_t pcb32_pagedir; /* PT hooks */ + pd_entry_t *pcb32_pl1vec; /* PTR to vector_base L1 entry*/ + pd_entry_t pcb32_l1vec; /* Value to stuff on ctx sw */ + u_int pcb32_dacr; /* Domain Access Control Reg */ + void *pcb32_cstate; /* &pmap->pm_cstate */ + /* + * WARNING! + * cpuswitch.S relies on pcb32_r8 being quad-aligned in struct pcb + * (due to the use of "strd" when compiled for XSCALE) + */ + u_int pcb32_r8; /* used */ + u_int pcb32_r9; /* used */ + u_int pcb32_r10; /* used */ + u_int pcb32_r11; /* used */ + u_int pcb32_r12; /* used */ + u_int pcb32_sp; /* used */ + u_int pcb32_lr; + u_int pcb32_pc; + u_int pcb32_und_sp; +}; +#define pcb_pagedir pcb_un.un_32.pcb32_pagedir +#define pcb_pl1vec pcb_un.un_32.pcb32_pl1vec +#define pcb_l1vec pcb_un.un_32.pcb32_l1vec +#define pcb_dacr pcb_un.un_32.pcb32_dacr +#define pcb_cstate pcb_un.un_32.pcb32_cstate + +/* + * WARNING! + * See warning for struct pcb_arm32, above, before changing struct pcb! + */ +struct pcb { + u_int pcb_flags; +#define PCB_FPU 0x00000001 /* Process had FPU initialized */ + struct trapframe *pcb_tf; + caddr_t pcb_onfault; /* On fault handler */ + union { + struct pcb_arm32 un_32; + } pcb_un; + struct fpreg pcb_fpstate; /* Floating Point state */ + struct cpu_info *pcb_fpcpu; + void *pcb_tcb; +}; + +#endif /* _ARM_PCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/pci_machdep.h b/lib/libc/include/arm-openbsd-eabi/arm/pci_machdep.h new file mode 100644 index 000000000000..4d03f5b112ed --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/pci_machdep.h @@ -0,0 +1,109 @@ +/* $OpenBSD: pci_machdep.h,v 1.18 2022/01/06 08:46:50 kettenis Exp $ */ + +/* + * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +typedef struct arm32_pci_chipset *pci_chipset_tag_t; +typedef uint64_t pcitag_t; + +#define PCITAG_NODE(x) ((x) >> 32) +#define PCITAG_OFFSET(x) ((x) & 0xffffffff) + +typedef u_long pci_intr_handle_t; + +struct pci_attach_args; + +/* + * arm32-specific PCI structure and type definitions. + * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE. + */ +struct arm32_pci_chipset { + void *pc_conf_v; + void (*pc_attach_hook)(struct device *, + struct device *, struct pcibus_attach_args *); + int (*pc_bus_maxdevs)(void *, int); + pcitag_t (*pc_make_tag)(void *, int, int, int); + void (*pc_decompose_tag)(void *, pcitag_t, int *, + int *, int *); + int (*pc_conf_size)(void *, pcitag_t); + pcireg_t (*pc_conf_read)(void *, pcitag_t, int); + void (*pc_conf_write)(void *, pcitag_t, int, pcireg_t); + int (*pc_probe_device_hook)(void *, struct pci_attach_args *); + + void *pc_intr_v; + int (*pc_intr_map)(struct pci_attach_args *, + pci_intr_handle_t *); + int (*pc_intr_map_msi)(struct pci_attach_args *, + pci_intr_handle_t *); + int (*pc_intr_map_msix)(struct pci_attach_args *, + int, pci_intr_handle_t *); + const char *(*pc_intr_string)(void *, pci_intr_handle_t); + void *(*pc_intr_establish)(void *, pci_intr_handle_t, + int, struct cpu_info *, int (*)(void *), void *, + char *); + void (*pc_intr_disestablish)(void *, void *); +}; + +/* + * Functions provided to machine-independent PCI code. + */ +#define pci_attach_hook(p, s, pba) \ + (*(pba)->pba_pc->pc_attach_hook)((p), (s), (pba)) +#define pci_bus_maxdevs(c, b) \ + (*(c)->pc_bus_maxdevs)((c)->pc_conf_v, (b)) +#define pci_make_tag(c, b, d, f) \ + (*(c)->pc_make_tag)((c)->pc_conf_v, (b), (d), (f)) +#define pci_decompose_tag(c, t, bp, dp, fp) \ + (*(c)->pc_decompose_tag)((c)->pc_conf_v, (t), (bp), (dp), (fp)) +#define pci_conf_size(c, t) \ + (*(c)->pc_conf_size)((c)->pc_conf_v, (t)) +#define pci_conf_read(c, t, r) \ + (*(c)->pc_conf_read)((c)->pc_conf_v, (t), (r)) +#define pci_conf_write(c, t, r, v) \ + (*(c)->pc_conf_write)((c)->pc_conf_v, (t), (r), (v)) +#define pci_probe_device_hook(c, a) \ + (*(c)->pc_probe_device_hook)((c)->pc_conf_v, (a)) +#define pci_intr_map(c, ihp) \ + (*(c)->pa_pc->pc_intr_map)((c), (ihp)) +#define pci_intr_map_msi(c, ihp) \ + (*(c)->pa_pc->pc_intr_map_msi)((c), (ihp)) +#define pci_intr_map_msix(c, vec, ihp) \ + (*(c)->pa_pc->pc_intr_map_msix)((c), (vec), (ihp)) +#define pci_intr_string(c, ih) \ + (*(c)->pc_intr_string)((c)->pc_intr_v, (ih)) +#define pci_intr_establish(c, ih, l, h, a, nm) \ + (*(c)->pc_intr_establish)((c)->pc_intr_v, (ih), (l), NULL, (h), (a),\ + (nm)) +#define pci_intr_establish_cpu(c, ih, l, ci, h, a, nm) \ + (*(c)->pc_intr_establish)((c)->pc_intr_v, (ih), (l), (ci), (h), (a),\ + (nm)) +#define pci_intr_disestablish(c, iv) \ + (*(c)->pc_intr_disestablish)((c)->pc_intr_v, (iv)) + +#define pci_min_powerstate(c, t) (PCI_PMCSR_STATE_D3) +#define pci_set_powerstate_md(c, t, s, p) + +#define pci_dev_postattach(a, b) \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/pmap.h b/lib/libc/include/arm-openbsd-eabi/arm/pmap.h new file mode 100644 index 000000000000..4e717b13d1c8 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/pmap.h @@ -0,0 +1,513 @@ +/* $OpenBSD: pmap.h,v 1.57 2024/11/07 08:12:12 miod Exp $ */ +/* $NetBSD: pmap.h,v 1.76 2003/09/06 09:10:46 rearnsha Exp $ */ + +/* + * Copyright (c) 2002, 2003 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe & Steve C. Woodford for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1994,1995 Mark Brinicombe. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mark Brinicombe + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _ARM_PMAP_H_ +#define _ARM_PMAP_H_ + +#ifdef _KERNEL + +#include +#include +#ifndef _LOCORE +#include +#endif + +/* + * a pmap describes a processes' 4GB virtual address space. this + * virtual address space can be broken up into 4096 1MB regions which + * are described by L1 PTEs in the L1 table. + * + * There is a line drawn at KERNEL_BASE. Everything below that line + * changes when the VM context is switched. Everything above that line + * is the same no matter which VM context is running. This is achieved + * by making the L1 PTEs for those slots above KERNEL_BASE reference + * kernel L2 tables. + * + * The basic layout of the virtual address space thus looks like this: + * + * 0xffffffff + * . + * . + * . + * KERNEL_BASE + * -------------------- + * . + * . + * . + * 0x00000000 + */ + +/* + * The number of L2 descriptor tables which can be tracked by an l2_dtable. + * A bucket size of 16 provides for 16MB of contiguous virtual address + * space per l2_dtable. Most processes will, therefore, require only two or + * three of these to map their whole working set. + */ +#define L2_BUCKET_LOG2 4 +#define L2_BUCKET_SIZE (1 << L2_BUCKET_LOG2) + +/* + * Given the above "L2-descriptors-per-l2_dtable" constant, the number + * of l2_dtable structures required to track all possible page descriptors + * mappable by an L1 translation table is given by the following constants: + */ +#define L2_LOG2 ((32 - L1_S_SHIFT) - L2_BUCKET_LOG2) +#define L2_SIZE (1 << L2_LOG2) + +#ifndef _LOCORE + +struct l1_ttable; +struct l2_dtable; + +/* + * Track cache/tlb occupancy using the following structure + */ +union pmap_cache_state { + struct { + union { + u_int8_t csu_cache_b[2]; + u_int16_t csu_cache; + } cs_cache_u; + + union { + u_int8_t csu_tlb_b[2]; + u_int16_t csu_tlb; + } cs_tlb_u; + } cs_s; + u_int32_t cs_all; +}; +#define cs_cache_id cs_s.cs_cache_u.csu_cache_b[0] +#define cs_cache_d cs_s.cs_cache_u.csu_cache_b[1] +#define cs_cache cs_s.cs_cache_u.csu_cache +#define cs_tlb_id cs_s.cs_tlb_u.csu_tlb_b[0] +#define cs_tlb_d cs_s.cs_tlb_u.csu_tlb_b[1] +#define cs_tlb cs_s.cs_tlb_u.csu_tlb + +/* + * Assigned to cs_all to force cacheops to work for a particular pmap + */ +#define PMAP_CACHE_STATE_ALL 0xffffffffu + +/* + * The pmap structure itself + */ +struct pmap { + u_int8_t pm_domain; + int pm_remove_all; + struct l1_ttable *pm_l1; + union pmap_cache_state pm_cstate; + u_int pm_refs; + struct l2_dtable *pm_l2[L2_SIZE]; + struct pmap_statistics pm_stats; +}; + +typedef struct pmap *pmap_t; + +/* + * MD flags that we use for pmap_enter (in the pa): + */ +#define PMAP_PA_MASK ~((paddr_t)PAGE_MASK) /* to remove the flags */ +#define PMAP_NOCACHE 0x1 /* non-cacheable memory. */ +#define PMAP_DEVICE 0x2 /* device memory. */ + +/* + * Physical / virtual address structure. In a number of places (particularly + * during bootstrapping) we need to keep track of the physical and virtual + * addresses of various pages + */ +typedef struct pv_addr { + SLIST_ENTRY(pv_addr) pv_list; + paddr_t pv_pa; + vaddr_t pv_va; +} pv_addr_t; + +/* + * Determine various modes for PTEs (user vs. kernel, cacheable + * vs. non-cacheable). + */ +#define PTE_KERNEL 0 +#define PTE_USER 1 +#define PTE_NOCACHE 0 +#define PTE_CACHE 1 +#define PTE_PAGETABLE 2 + +/* + * Flags that indicate attributes of pages or mappings of pages. + * + * The PVF_MOD and PVF_REF flags are stored in the mdpage for each + * page. PVF_WIRED and PVF_WRITE are kept in individual pv_entry's + * for each page. They live in the same "namespace" so that we can + * clear multiple attributes at a time. + */ +#define PVF_MOD 0x01 /* page is modified */ +#define PVF_REF 0x02 /* page is referenced */ +#define PVF_WIRED 0x04 /* mapping is wired */ +#define PVF_WRITE 0x08 /* mapping is writable */ +#define PVF_EXEC 0x10 /* mapping is executable */ + +/* + * Commonly referenced structures + */ +extern struct pmap kernel_pmap_store; + +/* + * Macros that we need to export + */ +#define pmap_kernel() (&kernel_pmap_store) +#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) +#define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count) + +#define pmap_is_modified(pg) \ + (((pg)->mdpage.pvh_attrs & PVF_MOD) != 0) +#define pmap_is_referenced(pg) \ + (((pg)->mdpage.pvh_attrs & PVF_REF) != 0) + +#define pmap_deactivate(p) do { /* nothing */ } while (0) + +#define pmap_init_percpu() do { /* nothing */ } while (0) +#define pmap_unuse_final(p) do { /* nothing */ } while (0) +#define pmap_remove_holes(vm) do { /* nothing */ } while (0) + +#define PMAP_CHECK_COPYIN 1 + +#define PMAP_GROWKERNEL /* turn on pmap_growkernel interface */ + +/* Functions we use internally. */ +void pmap_bootstrap(pd_entry_t *, vaddr_t, vaddr_t); + +int pmap_get_pde_pte(pmap_t, vaddr_t, pd_entry_t **, pt_entry_t **); +int pmap_get_pde(pmap_t, vaddr_t, pd_entry_t **); +void pmap_set_pcb_pagedir(pmap_t, struct pcb *); + +void pmap_postinit(void); + +void vector_page_setprot(int); + +/* XXX */ +void pmap_kenter_cache(vaddr_t va, paddr_t pa, vm_prot_t prot, int cacheable); + +/* Bootstrapping routines. */ +void pmap_map_section(vaddr_t, vaddr_t, paddr_t, int, int); +void pmap_map_entry(vaddr_t, vaddr_t, paddr_t, int, int); +vsize_t pmap_map_chunk(vaddr_t, vaddr_t, paddr_t, vsize_t, int, int); +void pmap_link_l2pt(vaddr_t, vaddr_t, pv_addr_t *); + +/* + * The current top of kernel VM + */ +extern vaddr_t pmap_curmaxkvaddr; + +/* + * Useful macros and constants + */ + +/* Virtual address to page table entry */ +static __inline pt_entry_t * +vtopte(vaddr_t va) +{ + pd_entry_t *pdep; + pt_entry_t *ptep; + + if (pmap_get_pde_pte(pmap_kernel(), va, &pdep, &ptep) == FALSE) + return (NULL); + return (ptep); +} + +/* + * Page tables are always mapped write-through. + * Thus, on some platforms we can run fast and loose and avoid syncing PTEs + * on every change. + * + * Unfortunately, not all CPUs have a write-through cache mode. So we + * define PMAP_NEEDS_PTE_SYNC for C code to conditionally do PTE syncs. + */ +extern int pmap_needs_pte_sync; + +#define PMAP_NEEDS_PTE_SYNC pmap_needs_pte_sync + +#define PTE_SYNC(pte) \ +do { \ + cpu_drain_writebuf(); \ + if (PMAP_NEEDS_PTE_SYNC) { \ + paddr_t pa; \ + cpu_dcache_wb_range((vaddr_t)(pte), sizeof(pt_entry_t));\ + if (cpu_sdcache_enabled()) { \ + (void)pmap_extract(pmap_kernel(), (vaddr_t)(pte), &pa); \ + cpu_sdcache_wb_range((vaddr_t)(pte), (paddr_t)(pa), \ + sizeof(pt_entry_t)); \ + }; \ + cpu_drain_writebuf(); \ + } \ +} while (/*CONSTCOND*/0) + +#define PTE_SYNC_RANGE(pte, cnt) \ +do { \ + cpu_drain_writebuf(); \ + if (PMAP_NEEDS_PTE_SYNC) { \ + paddr_t pa; \ + cpu_dcache_wb_range((vaddr_t)(pte), \ + (cnt) << 2); /* * sizeof(pt_entry_t) */ \ + if (cpu_sdcache_enabled()) { \ + (void)pmap_extract(pmap_kernel(), (vaddr_t)(pte), &pa);\ + cpu_sdcache_wb_range((vaddr_t)(pte), (paddr_t)(pa), \ + (cnt) << 2); /* * sizeof(pt_entry_t) */ \ + }; \ + cpu_drain_writebuf(); \ + } \ +} while (/*CONSTCOND*/0) + +#define l1pte_valid(pde) (((pde) & L1_TYPE_MASK) != L1_TYPE_INV) +#define l1pte_section_p(pde) (((pde) & L1_TYPE_MASK) == L1_TYPE_S) +#define l1pte_page_p(pde) (((pde) & L1_TYPE_MASK) == L1_TYPE_C) +#define l1pte_fpage_p(pde) (((pde) & L1_TYPE_MASK) == L1_TYPE_F) + +#define l2pte_index(v) (((v) & L2_ADDR_BITS) >> L2_S_SHIFT) +#define l2pte_valid(pte) (((pte) & L2_TYPE_MASK) != L2_TYPE_INV) +#define l2pte_pa(pte) ((pte) & L2_S_FRAME) + +/* L1 and L2 page table macros */ +#define pmap_pde_v(pde) l1pte_valid(*(pde)) +#define pmap_pde_section(pde) l1pte_section_p(*(pde)) +#define pmap_pde_page(pde) l1pte_page_p(*(pde)) +#define pmap_pde_fpage(pde) l1pte_fpage_p(*(pde)) + +/************************* ARM MMU configuration *****************************/ + +void pmap_pte_init_armv7(void); + +#endif /* !_LOCORE */ + +/*****************************************************************************/ + +/* + * Definitions for MMU domains + */ +#define PMAP_DOMAINS 15 /* 15 'user' domains (0-14) */ +#define PMAP_DOMAIN_KERNEL 15 /* The kernel uses domain #15 */ + +/* + * These macros define the various bit masks in the PTE. + * + * We use these macros since we use different bits on different processor + * models. + */ +#define L1_S_PROT_UR_v7 (L1_S_V7_AP(AP_V7_KRUR)) +#define L1_S_PROT_UW_v7 (L1_S_V7_AP(AP_KRWURW)) +#define L1_S_PROT_KR_v7 (L1_S_V7_AP(AP_V7_KR)) +#define L1_S_PROT_KW_v7 (L1_S_V7_AP(AP_KRW)) +#define L1_S_PROT_MASK_v7 (L1_S_V7_AP(0x07)) + +#define L1_S_CACHE_MASK_v7 (L1_S_B|L1_S_C|L1_S_V7_TEX_MASK) + +#define L1_S_COHERENT_v7 (L1_S_C) + +#define L2_L_PROT_UR_v7 (L2_V7_AP(AP_V7_KRUR)) +#define L2_L_PROT_UW_v7 (L2_V7_AP(AP_KRWURW)) +#define L2_L_PROT_KR_v7 (L2_V7_AP(AP_V7_KR)) +#define L2_L_PROT_KW_v7 (L2_V7_AP(AP_KRW)) +#define L2_L_PROT_MASK_v7 (L2_V7_AP(0x07) | L2_V7_L_XN) + +#define L2_L_CACHE_MASK_v7 (L2_B|L2_C|L2_V7_L_TEX_MASK) + +#define L2_L_COHERENT_v7 (L2_C) + +#define L2_S_PROT_UR_v7 (L2_V7_AP(AP_V7_KRUR)) +#define L2_S_PROT_UW_v7 (L2_V7_AP(AP_KRWURW)) +#define L2_S_PROT_KR_v7 (L2_V7_AP(AP_V7_KR)) +#define L2_S_PROT_KW_v7 (L2_V7_AP(AP_KRW)) +#define L2_S_PROT_MASK_v7 (L2_V7_AP(0x07) | L2_V7_S_XN) + +#define L2_S_CACHE_MASK_v7 (L2_B|L2_C|L2_V7_S_TEX_MASK) + +#define L2_S_COHERENT_v7 (L2_C) + +#define L1_S_PROTO_v7 (L1_TYPE_S) + +#define L1_C_PROTO_v7 (L1_TYPE_C) + +#define L2_L_PROTO (L2_TYPE_L) + +#define L2_S_PROTO_v7 (L2_TYPE_S) + +#define L1_S_PROT_UR L1_S_PROT_UR_v7 +#define L1_S_PROT_UW L1_S_PROT_UW_v7 +#define L1_S_PROT_KR L1_S_PROT_KR_v7 +#define L1_S_PROT_KW L1_S_PROT_KW_v7 +#define L1_S_PROT_MASK L1_S_PROT_MASK_v7 + +#define L2_L_PROT_UR L2_L_PROT_UR_v7 +#define L2_L_PROT_UW L2_L_PROT_UW_v7 +#define L2_L_PROT_KR L2_L_PROT_KR_v7 +#define L2_L_PROT_KW L2_L_PROT_KW_v7 +#define L2_L_PROT_MASK L2_L_PROT_MASK_v7 + +#define L2_S_PROT_UR L2_S_PROT_UR_v7 +#define L2_S_PROT_UW L2_S_PROT_UW_v7 +#define L2_S_PROT_KR L2_S_PROT_KR_v7 +#define L2_S_PROT_KW L2_S_PROT_KW_v7 +#define L2_S_PROT_MASK L2_S_PROT_MASK_v7 + +#define L1_S_CACHE_MASK L1_S_CACHE_MASK_v7 +#define L2_L_CACHE_MASK L2_L_CACHE_MASK_v7 +#define L2_S_CACHE_MASK L2_S_CACHE_MASK_v7 + +#define L1_S_COHERENT L1_S_COHERENT_v7 +#define L2_L_COHERENT L2_L_COHERENT_v7 +#define L2_S_COHERENT L2_S_COHERENT_v7 + +#define L1_S_PROTO L1_S_PROTO_v7 +#define L1_C_PROTO L1_C_PROTO_v7 +#define L2_S_PROTO L2_S_PROTO_v7 + +/* + * These macros return various bits based on kernel/user and protection. + * Note that the compiler will usually fold these at compile time. + */ +#ifndef _LOCORE +static __inline pt_entry_t +L1_S_PROT(int ku, vm_prot_t pr) +{ + pt_entry_t pte; + + if (ku == PTE_USER) + pte = (pr & PROT_WRITE) ? L1_S_PROT_UW : L1_S_PROT_UR; + else + pte = (pr & PROT_WRITE) ? L1_S_PROT_KW : L1_S_PROT_KR; + + if ((pr & PROT_EXEC) == 0) + pte |= L1_S_V7_XN; + + return pte; +} +static __inline pt_entry_t +L2_L_PROT(int ku, vm_prot_t pr) +{ + pt_entry_t pte; + + if (ku == PTE_USER) + pte = (pr & PROT_WRITE) ? L2_L_PROT_UW : L2_L_PROT_UR; + else + pte = (pr & PROT_WRITE) ? L2_L_PROT_KW : L2_L_PROT_KR; + + if ((pr & PROT_EXEC) == 0) + pte |= L2_V7_L_XN; + + return pte; +} +static __inline pt_entry_t +L2_S_PROT(int ku, vm_prot_t pr) +{ + pt_entry_t pte; + + if (ku == PTE_USER) + pte = (pr & PROT_WRITE) ? L2_S_PROT_UW : L2_S_PROT_UR; + else + pte = (pr & PROT_WRITE) ? L2_S_PROT_KW : L2_S_PROT_KR; + + if ((pr & PROT_EXEC) == 0) + pte |= L2_V7_S_XN; + + return pte; +} + +static __inline int +l2pte_is_writeable(pt_entry_t pte, struct pmap *pm) +{ + return (pte & L2_V7_AP(0x4)) == 0; +} +#endif + +/* + * Macros to test if a mapping is mappable with an L1 Section mapping + * or an L2 Large Page mapping. + */ +#define L1_S_MAPPABLE_P(va, pa, size) \ + ((((va) | (pa)) & L1_S_OFFSET) == 0 && (size) >= L1_S_SIZE) + +#define L2_L_MAPPABLE_P(va, pa, size) \ + ((((va) | (pa)) & L2_L_OFFSET) == 0 && (size) >= L2_L_SIZE) + +#endif /* _KERNEL */ + +#ifndef _LOCORE +/* + * pmap-specific data store in the vm_page structure. + */ +struct vm_page_md { + struct pv_entry *pvh_list; /* pv_entry list */ + int pvh_attrs; /* page attributes */ +}; + +#define VM_MDPAGE_INIT(pg) \ +do { \ + (pg)->mdpage.pvh_list = NULL; \ + (pg)->mdpage.pvh_attrs = 0; \ +} while (/*CONSTCOND*/0) +#endif /* _LOCORE */ + +#endif /* _ARM_PMAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/proc.h b/lib/libc/include/arm-openbsd-eabi/arm/proc.h new file mode 100644 index 000000000000..ee878612c5e9 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/proc.h @@ -0,0 +1,50 @@ +/* $OpenBSD: proc.h,v 1.5 2017/04/13 03:52:25 guenther Exp $ */ +/* $NetBSD: proc.h,v 1.5 2003/03/01 04:36:39 thorpej Exp $ */ + +/* + * Copyright (c) 1994 Mark Brinicombe. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the RiscBSD team. + * 4. The name "RiscBSD" nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RISCBSD ``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 RISCBSD 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 _ARM_PROC_H_ +#define _ARM_PROC_H_ + +/* + * Machine-dependent part of the proc structure for arm. + */ + +struct trapframe; + +struct mdproc { + int pmc_enabled; /* bitfield of enabled counters */ + void *pmc_state; /* port-specific pmc state */ +}; + +#endif /* _ARM_PROC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/profile.h b/lib/libc/include/arm-openbsd-eabi/arm/profile.h new file mode 100644 index 000000000000..95f53009403e --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/profile.h @@ -0,0 +1,91 @@ +/* $OpenBSD: profile.h,v 1.5 2016/09/21 11:33:05 kettenis Exp $ */ +/* $NetBSD: profile.h,v 1.5 2002/03/24 15:49:40 bjh21 Exp $ */ + +/* + * Copyright (c) 2001 Ben Harris + * Copyright (c) 1995-1996 Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mark Brinicombe. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define _MCOUNT_DECL void _mcount + +/* + * Cannot implement mcount in C as GCC will trash the ip register when it + * pushes a trapframe. Pity we cannot insert assembly before the function + * prologue. + */ + +#define MCOUNT_ASM_NAME "__mcount" +#ifdef __PIC__ +#define PLTSYM "(PLT)" +#endif + +#ifndef PLTSYM +#define PLTSYM +#endif + +#define MCOUNT \ + __asm__(".text"); \ + __asm__(".align 2"); \ + __asm__(".type " MCOUNT_ASM_NAME ",%function"); \ + __asm__(".global " MCOUNT_ASM_NAME); \ + __asm__(MCOUNT_ASM_NAME ":"); \ + /* \ + * Preserve registers that are trashed during mcount \ + */ \ + __asm__("stmfd sp!, {r0-r3, ip, lr}"); \ + /* \ + * find the return address for mcount, \ + * and the return address for mcount's caller. \ + * \ + * frompcindex = pc pushed by call into self. \ + */ \ + __asm__("mov r0, ip"); \ + /* \ + * selfpc = pc pushed by mcount call \ + */ \ + __asm__("mov r1, lr"); \ + /* \ + * Call the real mcount code \ + */ \ + __asm__("bl " __STRING(_mcount) PLTSYM); \ + /* \ + * Restore registers that were trashed during mcount \ + */ \ + __asm__("ldmfd sp!, {r0-r3, lr, pc}"); + +#ifdef _KERNEL +#include +/* + * splhigh() and splx() are heavyweight, and call mcount(). Therefore + * we disabled interrupts (IRQ, but not FIQ) directly on the CPU. + * + * We're lucky that the CPSR and 's' both happen to be 'int's. + */ +#define MCOUNT_ENTER s = __set_cpsr_c(0x0080, 0x0080); /* kill IRQ */ +#define MCOUNT_EXIT __set_cpsr_c(0xffffffff, s); /* restore old value */ +#endif /* _KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/pte.h b/lib/libc/include/arm-openbsd-eabi/arm/pte.h new file mode 100644 index 000000000000..cd9fd67ad64b --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/pte.h @@ -0,0 +1,232 @@ +/* $OpenBSD: pte.h,v 1.10 2021/03/11 11:16:55 jsg Exp $ */ +/* $NetBSD: pte.h,v 1.6 2003/04/18 11:08:28 scw Exp $ */ + +/* + * Copyright (c) 2001, 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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 _ARM_PTE_H_ +#define _ARM_PTE_H_ + +/* + * The ARM MMU architecture was introduced with ARM v3 (previous ARM + * architecture versions used an optional off-CPU memory controller + * to perform address translation). + * + * The ARM MMU consists of a TLB and translation table walking logic. + * There is typically one TLB per memory interface (or, put another + * way, one TLB per software-visible cache). + * + * The ARM MMU is capable of mapping memory in the following chunks: + * + * 1M Sections (L1 table) + * + * 64K Large Pages (L2 table) + * + * 4K Small Pages (L2 table) + * + * 1K Tiny Pages (L2 table) + * + * There are two types of L2 tables: Coarse Tables and Fine Tables. + * Coarse Tables can map Large and Small Pages. Fine Tables can + * map Tiny Pages. + * + * Coarse Tables can define 4 Subpages within Large and Small pages. + * Subpages define different permissions for each Subpage within + * a Page. + * + * Coarse Tables are 1K in length. Fine tables are 4K in length. + * + * The Translation Table Base register holds the pointer to the + * L1 Table. The L1 Table is a 16K contiguous chunk of memory + * aligned to a 16K boundary. Each entry in the L1 Table maps + * 1M of virtual address space, either via a Section mapping or + * via an L2 Table. + * + * In addition, the Fast Context Switching Extension (FCSE) is available + * on some ARM v4 and ARM v5 processors. FCSE is a way of eliminating + * TLB/cache flushes on context switch by use of a smaller address space + * and a "process ID" that modifies the virtual address before being + * presented to the translation logic. + */ + +#ifndef _LOCORE +typedef uint32_t pd_entry_t; /* L1 table entry */ +typedef uint32_t pt_entry_t; /* L2 table entry */ +#endif /* _LOCORE */ + +#define L1_S_SIZE 0x00100000 /* 1M */ +#define L1_S_OFFSET (L1_S_SIZE - 1) +#define L1_S_FRAME (~L1_S_OFFSET) +#define L1_S_SHIFT 20 + +#define L2_L_SIZE 0x00010000 /* 64K */ +#define L2_L_OFFSET (L2_L_SIZE - 1) +#define L2_L_FRAME (~L2_L_OFFSET) +#define L2_L_SHIFT 16 + +#define L2_S_SIZE 0x00001000 /* 4K */ +#define L2_S_OFFSET (L2_S_SIZE - 1) +#define L2_S_FRAME (~L2_S_OFFSET) +#define L2_S_SHIFT 12 + +#define L2_T_SIZE 0x00000400 /* 1K */ +#define L2_T_OFFSET (L2_T_SIZE - 1) +#define L2_T_FRAME (~L2_T_OFFSET) +#define L2_T_SHIFT 10 + +/* + * The NetBSD VM implementation only works on whole pages (4K), + * whereas the ARM MMU's Coarse tables are sized in terms of 1K + * (16K L1 table, 1K L2 table). + * + * So, we allocate L2 tables 4 at a time, thus yielding a 4K L2 + * table. + */ +#define L1_ADDR_BITS 0xfff00000 /* L1 PTE address bits */ +#define L2_ADDR_BITS 0x000ff000 /* L2 PTE address bits */ + +#define L1_TABLE_SIZE 0x4000 /* 16K */ +#define L2_TABLE_SIZE 0x1000 /* 4K */ +/* + * The new pmap deals with the 1KB coarse L2 tables by + * allocating them from a pool. Until every port has been converted, + * keep the old L2_TABLE_SIZE define lying around. Converted ports + * should use L2_TABLE_SIZE_REAL until then. + */ +#define L2_TABLE_SIZE_REAL 0x400 /* 1K */ + +/* + * ARM L1 Descriptors + */ + +#define L1_TYPE_INV 0x00 /* Invalid (fault) */ +#define L1_TYPE_C 0x01 /* Coarse L2 */ +#define L1_TYPE_S 0x02 /* Section or Supersection */ +#define L1_TYPE_F 0x03 /* Fine L2 (pre-V7) */ +#define L1_TYPE_MASK 0x03 /* mask of type bits */ + +/* L1 Section Descriptor */ +#define L1_S_B 0x00000004 /* bufferable Section */ +#define L1_S_C 0x00000008 /* cacheable Section */ +#define L1_S_IMP 0x00000010 /* implementation defined */ +#define L1_S_DOM(x) ((x) << 5) /* domain */ +#define L1_S_DOM_MASK L1_S_DOM(0xf) +#define L1_S_AP(x) ((x) << 10) /* access permissions */ +#define L1_S_ADDR_MASK 0xfff00000 /* phys address of section */ + +#define L1_S_V7_TEX(x) (((x) & 0x7) << 12) /* Type Extension */ +#define L1_S_V7_TEX_MASK (0x7 << 12) /* Type Extension */ +#define L1_S_V7_NS 0x00080000 /* Non-secure */ +#define L1_S_V7_SS 0x00040000 /* Supersection */ +#define L1_S_V7_nG 0x00020000 /* not Global */ +#define L1_S_V7_S 0x00010000 /* Shareable */ +#define L1_S_V7_AP(x) ((((x) & 0x4) << 13) | (((x) & 0x2) << 10)) /* AP */ +#define L1_S_V7_AF 0x00000400 /* Access Flag */ +#define L1_S_V7_IMP 0x00000200 /* implementation defined */ +#define L1_S_V7_XN 0x00000010 /* eXecute Never */ +#define L1_S_V7_PXN 0x00000001 /* Privileged eXecute Never */ + +/* L1 Coarse Descriptor */ +#define L1_C_IMP0 0x00000004 /* implementation defined */ +#define L1_C_IMP1 0x00000008 /* implementation defined */ +#define L1_C_IMP2 0x00000010 /* implementation defined */ +#define L1_C_DOM(x) ((x) << 5) /* domain */ +#define L1_C_DOM_MASK L1_C_DOM(0xf) +#define L1_C_ADDR_MASK 0xfffffc00 /* phys address of L2 Table */ + +#define L1_C_V7_IMP 0x00000200 /* implementation defined */ +#define L1_C_V7_NS 0x00000008 /* Non-secure */ +#define L1_C_V7_PXN 0x00000004 /* Privileged eXecute Never */ + +/* L1 Fine Descriptor */ +#define L1_F_IMP0 0x00000004 /* implementation defined */ +#define L1_F_IMP1 0x00000008 /* implementation defined */ +#define L1_F_IMP2 0x00000010 /* implementation defined */ +#define L1_F_DOM(x) ((x) << 5) /* domain */ +#define L1_F_DOM_MASK L1_F_DOM(0xf) +#define L1_F_ADDR_MASK 0xfffff000 /* phys address of L2 Table */ + +/* + * ARM L2 Descriptors + */ + +#define L2_TYPE_INV 0x00 /* Invalid (fault) */ +#define L2_TYPE_L 0x01 /* Large Page */ +#define L2_TYPE_S 0x02 /* Small Page */ +#define L2_TYPE_T 0x03 /* Tiny Page (pre-V7) */ +#define L2_TYPE_MASK 0x03 /* mask of type bits */ + +#define L2_B 0x00000004 /* Bufferable page */ +#define L2_C 0x00000008 /* Cacheable page */ +#define L2_AP0(x) ((x) << 4) /* access permissions (sp 0) */ +#define L2_AP1(x) ((x) << 6) /* access permissions (sp 1) */ +#define L2_AP2(x) ((x) << 8) /* access permissions (sp 2) */ +#define L2_AP3(x) ((x) << 10) /* access permissions (sp 3) */ +#define L2_AP(x) (L2_AP0(x) | L2_AP1(x) | L2_AP2(x) | L2_AP3(x)) + +#define L2_V7_L_TEX(x) (((x) & 0x7) << 12) /* Type Extension */ +#define L2_V7_L_TEX_MASK (0x7 << 12) /* Type Extension */ +#define L2_V7_L_XN 0x00008000 /* eXecute Never */ +#define L2_V7_S_TEX(x) (((x) & 0x7) << 6) /* Type Extension */ +#define L2_V7_S_TEX_MASK (0x7 << 6) /* Type Extension */ +#define L2_V7_S_XN 0x00000001 /* eXecute Never */ + +#define L2_V7_AP(x) ((((x) & 0x4) << 7) | (((x) & 0x2) << 4)) /* AP */ +#define L2_V7_AF 0x00000010 /* Access Flag */ +#define L2_V7_S 0x00000400 /* Shareable */ +#define L2_V7_nG 0x00000800 /* not Global */ + +/* + * Short-hand for common AP_* constants. + * + * Note: These values assume the S (System) bit is set and + * the R (ROM) bit is clear in CP15 register 1. + */ +#define AP_KR 0x00 /* kernel read */ +#define AP_V7_KR 0x05 +#define AP_KRW 0x01 /* kernel read/write */ +#define AP_KRWUR 0x02 /* kernel read/write usr read */ +#define AP_V7_KRUR 0x07 /* kernel read usr read */ +#define AP_KRWURW 0x03 /* kernel read/write usr read/write */ + +/* + * Domain Types for the Domain Access Control Register. + */ +#define DOMAIN_FAULT 0x00 /* no access */ +#define DOMAIN_CLIENT 0x01 /* client */ +#define DOMAIN_RESERVED 0x02 /* reserved */ +#define DOMAIN_MANAGER 0x03 /* manager */ + +#endif /* _ARM_PTE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/ptrace.h b/lib/libc/include/arm-openbsd-eabi/arm/ptrace.h new file mode 100644 index 000000000000..97bdac92c437 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/ptrace.h @@ -0,0 +1,44 @@ +/* $OpenBSD: ptrace.h,v 1.1 2004/02/01 05:09:49 drahn Exp $ */ +/* $NetBSD: ptrace.h,v 1.2 2001/10/19 00:18:20 bjh21 Exp $ */ + +/* + * Copyright (c) 1995 Frank Lancaster + * Copyright (c) 1995 Tools GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + */ + +/* + * arm-dependent ptrace definitions + */ +#ifndef _KERNEL +#define PT_STEP (PT_FIRSTMACH + 0) /* Not implemented */ +#endif +#define PT_GETREGS (PT_FIRSTMACH + 1) +#define PT_SETREGS (PT_FIRSTMACH + 2) +#define PT_GETFPREGS (PT_FIRSTMACH + 3) +#define PT_SETFPREGS (PT_FIRSTMACH + 4) \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/reg.h b/lib/libc/include/arm-openbsd-eabi/arm/reg.h new file mode 100644 index 000000000000..b456a865179f --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/reg.h @@ -0,0 +1,53 @@ +/* $OpenBSD: reg.h,v 1.3 2018/01/23 12:38:14 kettenis Exp $ */ +/* $NetBSD: reg.h,v 1.1 2001/02/11 14:51:55 bjh21 Exp $ */ + +/* + * Copyright (C) 1994, 1995 Frank Lancaster + * Copyright (C) 1994, 1995 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + * + * @(#)reg.h 5.5 (Berkeley) 1/18/91 + */ + +#ifndef _ARM_REG_H_ +#define _ARM_REG_H_ + +struct reg { + unsigned int r[13]; + unsigned int r_sp; + unsigned int r_lr; + unsigned int r_pc; + unsigned int r_cpsr; +}; + +struct fpreg { + uint64_t fp_reg[32]; + uint32_t fp_scr; +}; + +#endif /* !_ARM_REG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/reloc.h b/lib/libc/include/arm-openbsd-eabi/arm/reloc.h new file mode 100644 index 000000000000..e7415bd50d5b --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/reloc.h @@ -0,0 +1,53 @@ +/* $OpenBSD: reloc.h,v 1.2 2006/05/26 20:22:04 miod Exp $ */ +/* Processor specific relocation types */ + +#define R_ARM_NONE 0 +#define R_ARM_PC24 1 +#define R_ARM_ABS32 2 +#define R_ARM_REL32 3 +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 +#define R_ARM_ABS12 6 +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 + +/* 17-31 are reserved for ARM Linux. */ +#define R_ARM_COPY 20 +#define R_ARM_GLOB_DAT 21 +#define R_ARM_JUMP_SLOT 22 +#define R_ARM_RELATIVE 23 +#define R_ARM_GOTOFF 24 +#define R_ARM_GOTPC 25 +#define R_ARM_GOT32 26 +#define R_ARM_PLT32 27 + +#define R_ARM_ALU_PCREL_7_0 32 +#define R_ARM_ALU_PCREL_15_8 33 +#define R_ARM_ALU_PCREL_23_15 34 +#define R_ARM_ALU_SBREL_11_0 35 +#define R_ARM_ALU_SBREL_19_12 36 +#define R_ARM_ALU_SBREL_27_20 37 + +/* 96-111 are reserved to G++. */ +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_THM_PC11 102 +#define R_ARM_THM_PC9 103 + +/* 112-127 are reserved for private experiments. */ + +#define R_ARM_RXPC25 249 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS32 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/setjmp.h b/lib/libc/include/arm-openbsd-eabi/arm/setjmp.h new file mode 100644 index 000000000000..16c91184989e --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/setjmp.h @@ -0,0 +1,67 @@ +/* $OpenBSD: setjmp.h,v 1.6 2023/04/11 00:45:07 jsg Exp $ */ +/* $NetBSD: setjmp.h,v 1.2 2001/08/25 14:45:59 bjh21 Exp $ */ + +/* + * machine/setjmp.h: machine dependent setjmp-related information. + */ + +#define _JBLEN 64 /* size, in longs, of a jmp_buf */ + +/* + * Description of the setjmp buffer + * + * word 0 magic number (dependant on creator) + * 1 fpscr fpscr + * 2 - 17 d8 - d15 vfp registers + * 18 r13 register 13 (sp) XOR cookie0 + * 19 r14 register 14 (lr) XOR cookie1 + * 20 r4 register 4 + * 21 r5 register 5 + * 22 r6 register 6 + * 23 r7 register 7 + * 24 r8 register 8 + * 25 r9 register 9 + * 26 r10 register 10 (sl) + * 27 r11 register 11 (fp) + * 28 unused unused + * 29 signal mask (dependant on magic) + * 30 (con't) + * 31 (con't) + * 32 (con't) + * + * The magic number identifies the jmp_buf and + * how the buffer was created as well as providing + * a sanity check. + * + * A side note I should mention - please do not tamper + * with the floating point fields. While they are + * always saved and restored at the moment this cannot + * be guaranteed especially if the compiler happens + * to be generating soft-float code so no fp + * registers will be used. + * + * Whilst this can be seen an encouraging people to + * use the setjmp buffer in this way I think that it + * is for the best then if changes occur compiles will + * break rather than just having new builds falling over + * mysteriously. + */ + +#define _JB_MAGIC__SETJMP 0x4278f500 +#define _JB_MAGIC_SETJMP 0x4278f501 + +/* Valid for all jmp_buf's */ + +#define _JB_MAGIC 0 +#define _JB_REG_R4 20 +#define _JB_REG_R5 21 +#define _JB_REG_R6 22 +#define _JB_REG_R7 23 +#define _JB_REG_R8 24 +#define _JB_REG_R9 25 +#define _JB_REG_R10 26 +#define _JB_REG_R11 27 + +/* Only valid with the _JB_MAGIC_SETJMP magic */ + +#define _JB_SIGMASK 29 \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/signal.h b/lib/libc/include/arm-openbsd-eabi/arm/signal.h new file mode 100644 index 000000000000..2b226ebd7035 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/signal.h @@ -0,0 +1,93 @@ +/* $OpenBSD: signal.h,v 1.10 2018/06/23 22:15:14 kettenis Exp $ */ +/* $NetBSD: signal.h,v 1.5 2003/10/18 17:57:21 briggs Exp $ */ + +/* + * Copyright (c) 1994-1996 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Brini. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. + * + * RiscBSD kernel project + * + * signal.h + * + * Architecture dependant signal types and structures + * + * Created : 30/09/94 + */ + +#ifndef _ARM_SIGNAL_H_ +#define _ARM_SIGNAL_H_ + +#ifndef _LOCORE +#include + +typedef int sig_atomic_t; + +#if __BSD_VISIBLE || __XPG_VISIBLE >= 420 +/* + * Information pushed on stack when a signal is delivered. + * This is used by the kernel to restore state following + * execution of the signal handler. It is also made available + * to the handler to allow it to restore state properly if + * a non-standard exit is performed. + */ +struct sigcontext { + long sc_cookie; + int sc_mask; /* signal mask to restore */ + + unsigned int sc_spsr; + unsigned int sc_r0; + unsigned int sc_r1; + unsigned int sc_r2; + unsigned int sc_r3; + unsigned int sc_r4; + unsigned int sc_r5; + unsigned int sc_r6; + unsigned int sc_r7; + unsigned int sc_r8; + unsigned int sc_r9; + unsigned int sc_r10; + unsigned int sc_r11; + unsigned int sc_r12; + unsigned int sc_usr_sp; + unsigned int sc_usr_lr; + unsigned int sc_svc_lr; + unsigned int sc_pc; + + unsigned int sc_fpused; + unsigned int sc_fpscr; + unsigned long long sc_fpreg[32]; +}; +#endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ +#endif /* !_LOCORE */ + +#endif /* !_ARM_SIGNAL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/simplebusvar.h b/lib/libc/include/arm-openbsd-eabi/arm/simplebusvar.h new file mode 100644 index 000000000000..4ed0e3f60a48 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/simplebusvar.h @@ -0,0 +1,37 @@ +/* $OpenBSD: simplebusvar.h,v 1.1 2023/09/22 01:10:43 jsg Exp $ */ +/* + * Copyright (c) 2016 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +struct simplebus_softc { + struct device sc_dev; + int sc_node; + bus_space_tag_t sc_iot; + bus_dma_tag_t sc_dmat; + int sc_acells; + int sc_scells; + int sc_pacells; + int sc_pscells; + struct bus_space sc_bus; + struct arm32_bus_dma_tag sc_dma; + int *sc_ranges; + int sc_rangeslen; + int *sc_dmaranges; + int sc_dmarangeslen; + int sc_early; + int sc_early_nodes[64]; +}; + +extern void simplebus_attach(struct device *, struct device *, void *); \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/spinlock.h b/lib/libc/include/arm-openbsd-eabi/arm/spinlock.h new file mode 100644 index 000000000000..d8dbd0dc1c27 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/spinlock.h @@ -0,0 +1,10 @@ +/* $OpenBSD: spinlock.h,v 1.3 2017/09/05 02:40:54 guenther Exp $ */ + +#ifndef _ARM_SPINLOCK_H_ +#define _ARM_SPINLOCK_H_ + +#define _ATOMIC_LOCK_UNLOCKED (0) +#define _ATOMIC_LOCK_LOCKED (1) +typedef int _atomic_lock_t; + +#endif \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/sysarch.h b/lib/libc/include/arm-openbsd-eabi/arm/sysarch.h new file mode 100644 index 000000000000..1f1f41c04dbd --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/sysarch.h @@ -0,0 +1,62 @@ +/* $OpenBSD: sysarch.h,v 1.3 2012/12/05 23:20:11 deraadt Exp $ */ +/* $NetBSD: sysarch.h,v 1.4 2002/03/30 06:23:39 thorpej Exp $ */ + +/* + * Copyright (c) 1996-1997 Mark Brinicombe. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mark Brinicombe. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL 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 _ARM_SYSARCH_H_ +#define _ARM_SYSARCH_H_ + +/* + * Architecture specific syscalls (arm) + */ + +#define ARM_SYNC_ICACHE 0 +#define ARM_DRAIN_WRITEBUF 1 + +struct arm_sync_icache_args { + u_int32_t addr; /* Virtual start address */ + size_t len; /* Region size */ +}; + +#ifndef _KERNEL + +#include + +__BEGIN_DECLS +int arm_sync_icache (u_int addr, int len); +int arm_drain_writebuf (void); +int sysarch (int, void *); +__END_DECLS +#endif + +#endif /* !_ARM_SYSARCH_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/sysreg.h b/lib/libc/include/arm-openbsd-eabi/arm/sysreg.h new file mode 100644 index 000000000000..5133ae186b30 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/sysreg.h @@ -0,0 +1,272 @@ +/* $OpenBSD: sysreg.h,v 1.1 2016/04/25 04:25:36 jsg Exp $ */ +/*- + * Copyright 2014 Svatopluk Kraus + * Copyright 2014 Michal Meloun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: head/sys/arm/include/sysreg.h 294740 2016-01-25 18:02:28Z zbb $ + */ + +/* + * Macros to make working with the System Control Registers simpler. + * + * Note that when register r0 is hard-coded in these definitions it means the + * cp15 operation neither reads nor writes the register, and r0 is used only + * because some syntatically-valid register name has to appear at that point to + * keep the asm parser happy. + */ + +#ifndef MACHINE_SYSREG_H +#define MACHINE_SYSREG_H + +/* + * CP14 registers + */ + +#define CP14_DBGDIDR(rr) p14, 0, rr, c0, c0, 0 /* Debug ID Register */ +#define CP14_DBGDSCRext_V6(rr) p14, 0, rr, c0, c1, 0 /* Debug Status and Ctrl Register v6 */ +#define CP14_DBGDSCRext_V7(rr) p14, 0, rr, c0, c2, 2 /* Debug Status and Ctrl Register v7 */ +#define CP14_DBGVCR(rr) p14, 0, rr, c0, c7, 0 /* Vector Catch Register */ +#define CP14_DBGOSLAR(rr) p14, 0, rr, c1, c0, 4 /* OS Lock Access Register */ +#define CP14_DBGOSLSR(rr) p14, 0, rr, c1, c1, 4 /* OS Lock Status Register */ +#define CP14_DBGOSDLR(rr) p14, 0, rr, c1, c3, 4 /* OS Double Lock Register */ +#define CP14_DBGPRSR(rr) p14, 0, rr, c1, c5, 4 /* Device Powerdown and Reset Status */ + +#define CP14_DBGDSCRint(rr) CP14_DBGDSCRext_V6(rr) /* Debug Status and Ctrl internal view */ + + +/* + * CP15 C0 registers + */ +#define CP15_MIDR(rr) p15, 0, rr, c0, c0, 0 /* Main ID Register */ +#define CP15_CTR(rr) p15, 0, rr, c0, c0, 1 /* Cache Type Register */ +#define CP15_TCMTR(rr) p15, 0, rr, c0, c0, 2 /* TCM Type Register */ +#define CP15_TLBTR(rr) p15, 0, rr, c0, c0, 3 /* TLB Type Register */ +#define CP15_MPIDR(rr) p15, 0, rr, c0, c0, 5 /* Multiprocessor Affinity Register */ +#define CP15_REVIDR(rr) p15, 0, rr, c0, c0, 6 /* Revision ID Register */ + +#define CP15_ID_PFR0(rr) p15, 0, rr, c0, c1, 0 /* Processor Feature Register 0 */ +#define CP15_ID_PFR1(rr) p15, 0, rr, c0, c1, 1 /* Processor Feature Register 1 */ +#define CP15_ID_DFR0(rr) p15, 0, rr, c0, c1, 2 /* Debug Feature Register 0 */ +#define CP15_ID_AFR0(rr) p15, 0, rr, c0, c1, 3 /* Auxiliary Feature Register 0 */ +#define CP15_ID_MMFR0(rr) p15, 0, rr, c0, c1, 4 /* Memory Model Feature Register 0 */ +#define CP15_ID_MMFR1(rr) p15, 0, rr, c0, c1, 5 /* Memory Model Feature Register 1 */ +#define CP15_ID_MMFR2(rr) p15, 0, rr, c0, c1, 6 /* Memory Model Feature Register 2 */ +#define CP15_ID_MMFR3(rr) p15, 0, rr, c0, c1, 7 /* Memory Model Feature Register 3 */ + +#define CP15_ID_ISAR0(rr) p15, 0, rr, c0, c2, 0 /* Instruction Set Attribute Register 0 */ +#define CP15_ID_ISAR1(rr) p15, 0, rr, c0, c2, 1 /* Instruction Set Attribute Register 1 */ +#define CP15_ID_ISAR2(rr) p15, 0, rr, c0, c2, 2 /* Instruction Set Attribute Register 2 */ +#define CP15_ID_ISAR3(rr) p15, 0, rr, c0, c2, 3 /* Instruction Set Attribute Register 3 */ +#define CP15_ID_ISAR4(rr) p15, 0, rr, c0, c2, 4 /* Instruction Set Attribute Register 4 */ +#define CP15_ID_ISAR5(rr) p15, 0, rr, c0, c2, 5 /* Instruction Set Attribute Register 5 */ + +#define CP15_CCSIDR(rr) p15, 1, rr, c0, c0, 0 /* Cache Size ID Registers */ +#define CP15_CLIDR(rr) p15, 1, rr, c0, c0, 1 /* Cache Level ID Register */ +#define CP15_AIDR(rr) p15, 1, rr, c0, c0, 7 /* Auxiliary ID Register */ + +#define CP15_CSSELR(rr) p15, 2, rr, c0, c0, 0 /* Cache Size Selection Register */ + +/* + * CP15 C1 registers + */ +#define CP15_SCTLR(rr) p15, 0, rr, c1, c0, 0 /* System Control Register */ +#define CP15_ACTLR(rr) p15, 0, rr, c1, c0, 1 /* IMPLEMENTATION DEFINED Auxiliary Control Register */ +#define CP15_CPACR(rr) p15, 0, rr, c1, c0, 2 /* Coprocessor Access Control Register */ + +#define CP15_SCR(rr) p15, 0, rr, c1, c1, 0 /* Secure Configuration Register */ +#define CP15_SDER(rr) p15, 0, rr, c1, c1, 1 /* Secure Debug Enable Register */ +#define CP15_NSACR(rr) p15, 0, rr, c1, c1, 2 /* Non-Secure Access Control Register */ + +/* + * CP15 C2 registers + */ +#define CP15_TTBR0(rr) p15, 0, rr, c2, c0, 0 /* Translation Table Base Register 0 */ +#define CP15_TTBR1(rr) p15, 0, rr, c2, c0, 1 /* Translation Table Base Register 1 */ +#define CP15_TTBCR(rr) p15, 0, rr, c2, c0, 2 /* Translation Table Base Control Register */ + +/* + * CP15 C3 registers + */ +#define CP15_DACR(rr) p15, 0, rr, c3, c0, 0 /* Domain Access Control Register */ + +/* + * CP15 C5 registers + */ +#define CP15_DFSR(rr) p15, 0, rr, c5, c0, 0 /* Data Fault Status Register */ + +/* From ARMv6: */ +#define CP15_IFSR(rr) p15, 0, rr, c5, c0, 1 /* Instruction Fault Status Register */ +/* From ARMv7: */ +#define CP15_ADFSR(rr) p15, 0, rr, c5, c1, 0 /* Auxiliary Data Fault Status Register */ +#define CP15_AIFSR(rr) p15, 0, rr, c5, c1, 1 /* Auxiliary Instruction Fault Status Register */ + +/* + * CP15 C6 registers + */ +#define CP15_DFAR(rr) p15, 0, rr, c6, c0, 0 /* Data Fault Address Register */ + +/* From ARMv6k: */ +#define CP15_IFAR(rr) p15, 0, rr, c6, c0, 2 /* Instruction Fault Address Register */ + +/* + * CP15 C7 registers + */ +#ifdef MULTIPROCESSOR +/* From ARMv7: */ +#define CP15_ICIALLUIS p15, 0, r0, c7, c1, 0 /* Instruction cache invalidate all PoU, IS */ +#define CP15_BPIALLIS p15, 0, r0, c7, c1, 6 /* Branch predictor invalidate all IS */ +#endif + +#define CP15_PAR(rr) p15, 0, rr, c7, c4, 0 /* Physical Address Register */ + +#define CP15_ICIALLU p15, 0, r0, c7, c5, 0 /* Instruction cache invalidate all PoU */ +#define CP15_ICIMVAU(rr) p15, 0, rr, c7, c5, 1 /* Instruction cache invalidate */ +#define CP15_BPIALL p15, 0, r0, c7, c5, 6 /* Branch predictor invalidate all */ +#define CP15_BPIMVA p15, 0, r0, c7, c5, 7 /* Branch predictor invalidate by MVA */ + +#define CP15_DCIMVAC(rr) p15, 0, rr, c7, c6, 1 /* Data cache invalidate by MVA PoC */ +#define CP15_DCISW(rr) p15, 0, rr, c7, c6, 2 /* Data cache invalidate by set/way */ + +#define CP15_ATS1CPR(rr) p15, 0, rr, c7, c8, 0 /* Stage 1 Current state PL1 read */ +#define CP15_ATS1CPW(rr) p15, 0, rr, c7, c8, 1 /* Stage 1 Current state PL1 write */ +#define CP15_ATS1CUR(rr) p15, 0, rr, c7, c8, 2 /* Stage 1 Current state unprivileged read */ +#define CP15_ATS1CUW(rr) p15, 0, rr, c7, c8, 3 /* Stage 1 Current state unprivileged write */ + +/* From ARMv7: */ +#define CP15_ATS12NSOPR(rr) p15, 0, rr, c7, c8, 4 /* Stages 1 and 2 Non-secure only PL1 read */ +#define CP15_ATS12NSOPW(rr) p15, 0, rr, c7, c8, 5 /* Stages 1 and 2 Non-secure only PL1 write */ +#define CP15_ATS12NSOUR(rr) p15, 0, rr, c7, c8, 6 /* Stages 1 and 2 Non-secure only unprivileged read */ +#define CP15_ATS12NSOUW(rr) p15, 0, rr, c7, c8, 7 /* Stages 1 and 2 Non-secure only unprivileged write */ + +#define CP15_DCCMVAC(rr) p15, 0, rr, c7, c10, 1 /* Data cache clean by MVA PoC */ +#define CP15_DCCSW(rr) p15, 0, rr, c7, c10, 2 /* Data cache clean by set/way */ + +#define CP15_CP15DSB(rr) p15, 0, rr, c7, c10, 4 +#define CP15_CP15DMB(rr) p15, 0, rr, c7, c10, 5 + +/* From ARMv7: */ +#define CP15_DCCMVAU(rr) p15, 0, rr, c7, c11, 1 /* Data cache clean by MVA PoU */ + +#define CP15_DCCIMVAC(rr) p15, 0, rr, c7, c14, 1 /* Data cache clean and invalidate by MVA PoC */ +#define CP15_DCCISW(rr) p15, 0, rr, c7, c14, 2 /* Data cache clean and invalidate by set/way */ + +/* + * CP15 C8 registers + */ +#ifdef MULTIPROCESSOR +/* From ARMv7: */ +#define CP15_TLBIALLIS p15, 0, r0, c8, c3, 0 /* Invalidate entire unified TLB IS */ +#define CP15_TLBIMVAIS(rr) p15, 0, rr, c8, c3, 1 /* Invalidate unified TLB by MVA IS */ +#define CP15_TLBIASIDIS(rr) p15, 0, rr, c8, c3, 2 /* Invalidate unified TLB by ASID IS */ +#define CP15_TLBIMVAAIS(rr) p15, 0, rr, c8, c3, 3 /* Invalidate unified TLB by MVA, all ASID IS */ +#endif + +#define CP15_DTLBIALL p15, 0, r0, c8, c6, 0 /* flush D tlb */ +#define CP15_DTLBIMVA p15, 0, r0, c8, c6, 1 /* Invalidate D TLB by MVA */ +#define CP15_ITLBIALL p15, 0, r0, c8, c5, 0 /* flush I tlb */ +#define CP15_ITLBIMVA p15, 0, r0, c8, c5, 1 /* Invalidate I TLB by MVA */ + +#define CP15_TLBIALL(rr) p15, 0, rr, c8, c7, 0 /* Invalidate entire unified TLB */ +#define CP15_TLBIMVA(rr) p15, 0, rr, c8, c7, 1 /* Invalidate unified TLB by MVA */ +#define CP15_TLBIASID(rr) p15, 0, rr, c8, c7, 2 /* Invalidate unified TLB by ASID */ + +/* From ARMv6: */ +#define CP15_TLBIMVAA(rr) p15, 0, rr, c8, c7, 3 /* Invalidate unified TLB by MVA, all ASID */ + +/* + * CP15 C9 registers + */ +#define CP15_L2CTLR(rr) p15, 1, rr, c9, c0, 2 /* L2 Control Register */ +#define CP15_PMCR(rr) p15, 0, rr, c9, c12, 0 /* Performance Monitor Control Register */ +#define CP15_PMCNTENSET(rr) p15, 0, rr, c9, c12, 1 /* PM Count Enable Set Register */ +#define CP15_PMCNTENCLR(rr) p15, 0, rr, c9, c12, 2 /* PM Count Enable Clear Register */ +#define CP15_PMOVSR(rr) p15, 0, rr, c9, c12, 3 /* PM Overflow Flag Status Register */ +#define CP15_PMSWINC(rr) p15, 0, rr, c9, c12, 4 /* PM Software Increment Register */ +#define CP15_PMSELR(rr) p15, 0, rr, c9, c12, 5 /* PM Event Counter Selection Register */ +#define CP15_PMCCNTR(rr) p15, 0, rr, c9, c13, 0 /* PM Cycle Count Register */ +#define CP15_PMXEVTYPER(rr) p15, 0, rr, c9, c13, 1 /* PM Event Type Select Register */ +#define CP15_PMXEVCNTRR(rr) p15, 0, rr, c9, c13, 2 /* PM Event Count Register */ +#define CP15_PMUSERENR(rr) p15, 0, rr, c9, c14, 0 /* PM User Enable Register */ +#define CP15_PMINTENSET(rr) p15, 0, rr, c9, c14, 1 /* PM Interrupt Enable Set Register */ +#define CP15_PMINTENCLR(rr) p15, 0, rr, c9, c14, 2 /* PM Interrupt Enable Clear Register */ + +/* + * CP15 C10 registers + */ +/* Without LPAE this is PRRR, with LPAE it's MAIR0 */ +#define CP15_PRRR(rr) p15, 0, rr, c10, c2, 0 /* Primary Region Remap Register */ +#define CP15_MAIR0(rr) p15, 0, rr, c10, c2, 0 /* Memory Attribute Indirection Register 0 */ +/* Without LPAE this is NMRR, with LPAE it's MAIR1 */ +#define CP15_NMRR(rr) p15, 0, rr, c10, c2, 1 /* Normal Memory Remap Register */ +#define CP15_MAIR1(rr) p15, 0, rr, c10, c2, 1 /* Memory Attribute Indirection Register 1 */ + +#define CP15_AMAIR0(rr) p15, 0, rr, c10, c3, 0 /* Auxiliary Memory Attribute Indirection Register 0 */ +#define CP15_AMAIR1(rr) p15, 0, rr, c10, c3, 1 /* Auxiliary Memory Attribute Indirection Register 1 */ + +/* + * CP15 C12 registers + */ +#define CP15_VBAR(rr) p15, 0, rr, c12, c0, 0 /* Vector Base Address Register */ +#define CP15_MVBAR(rr) p15, 0, rr, c12, c0, 1 /* Monitor Vector Base Address Register */ + +#define CP15_ISR(rr) p15, 0, rr, c12, c1, 0 /* Interrupt Status Register */ + +/* + * CP15 C13 registers + */ +#define CP15_FCSEIDR(rr) p15, 0, rr, c13, c0, 0 /* FCSE Process ID Register */ +#define CP15_CONTEXTIDR(rr) p15, 0, rr, c13, c0, 1 /* Context ID Register */ +#define CP15_TPIDRURW(rr) p15, 0, rr, c13, c0, 2 /* User Read/Write Thread ID Register */ +#define CP15_TPIDRURO(rr) p15, 0, rr, c13, c0, 3 /* User Read-Only Thread ID Register */ +#define CP15_TPIDRPRW(rr) p15, 0, rr, c13, c0, 4 /* PL1 only Thread ID Register */ + +/* + * CP15 C14 registers + * These are the Generic Timer registers and may be unallocated on some SoCs. + * Only use these when you know the Generic Timer is available. + */ +#define CP15_CNTFRQ(rr) p15, 0, rr, c14, c0, 0 /* Counter Frequency Register */ +#define CP15_CNTKCTL(rr) p15, 0, rr, c14, c1, 0 /* Timer PL1 Control Register */ +#define CP15_CNTP_TVAL(rr) p15, 0, rr, c14, c2, 0 /* PL1 Physical Timer Value Register */ +#define CP15_CNTP_CTL(rr) p15, 0, rr, c14, c2, 1 /* PL1 Physical Timer Control Register */ +#define CP15_CNTV_TVAL(rr) p15, 0, rr, c14, c3, 0 /* Virtual Timer Value Register */ +#define CP15_CNTV_CTL(rr) p15, 0, rr, c14, c3, 1 /* Virtual Timer Control Register */ +#define CP15_CNTHCTL(rr) p15, 4, rr, c14, c1, 0 /* Timer PL2 Control Register */ +#define CP15_CNTHP_TVAL(rr) p15, 4, rr, c14, c2, 0 /* PL2 Physical Timer Value Register */ +#define CP15_CNTHP_CTL(rr) p15, 4, rr, c14, c2, 1 /* PL2 Physical Timer Control Register */ +/* 64-bit registers for use with mcrr/mrrc */ +#define CP15_CNTPCT(rq, rr) p15, 0, rq, rr, c14 /* Physical Count Register */ +#define CP15_CNTVCT(rq, rr) p15, 1, rq, rr, c14 /* Virtual Count Register */ +#define CP15_CNTP_CVAL(rq, rr) p15, 2, rq, rr, c14 /* PL1 Physical Timer Compare Value Register */ +#define CP15_CNTV_CVAL(rq, rr) p15, 3, rq, rr, c14 /* Virtual Timer Compare Value Register */ +#define CP15_CNTVOFF(rq, rr) p15, 4, rq, rr, c14 /* Virtual Offset Register */ +#define CP15_CNTHP_CVAL(rq, rr) p15, 6, rq, rr, c14 /* PL2 Physical Timer Compare Value Register */ + +/* + * CP15 C15 registers + */ +#define CP15_CBAR(rr) p15, 4, rr, c15, c0, 0 /* Configuration Base Address Register */ + +#endif /* !MACHINE_SYSREG_H */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/tcb.h b/lib/libc/include/arm-openbsd-eabi/arm/tcb.h new file mode 100644 index 000000000000..3cc74e0f2733 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/tcb.h @@ -0,0 +1,58 @@ +/* $OpenBSD: tcb.h,v 1.3 2016/10/02 20:11:32 guenther Exp $ */ + +/* + * Copyright (c) 2011 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TCB_H_ +#define _MACHINE_TCB_H_ + +#ifdef _KERNEL + +#include + +static inline void +__arm_set_tcb(void *tcb) +{ + __asm volatile("mcr p15, 0, %0, c13, c0, 3\n" : : "r" (tcb)); +} + +#define TCB_GET(p) \ + ((struct pcb *)(p)->p_addr)->pcb_tcb + +#define TCB_SET(p, addr) \ + do { \ + ((struct pcb *)(p)->p_addr)->pcb_tcb = (addr); \ + __arm_set_tcb(addr); \ + } while (0) + +#else /* _KERNEL */ + +/* ELF TLS ABI calls for small TCB, with static TLS data after it */ +#define TLS_VARIANT 1 + +static inline void * +__arm_read_tcb(void) +{ + void *tcb; + __asm volatile("mrc p15, 0, %0, c13, c0, 3\n" : "=r" (tcb)); + return tcb; +} + +#define TCB_GET() __arm_read_tcb() + +#endif /* _KERNEL */ + +#endif /* _MACHINE_TCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/trap.h b/lib/libc/include/arm-openbsd-eabi/arm/trap.h new file mode 100644 index 000000000000..8b34cd224074 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/trap.h @@ -0,0 +1,69 @@ +/* $OpenBSD: trap.h,v 1.2 2018/06/30 15:23:37 deraadt Exp $ */ +/* $NetBSD: trap.h,v 1.4 2003/04/28 01:54:50 briggs Exp $ */ + +/* + * Copyright (c) 1995 Mark Brinicombe. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mark Brinicombe. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR 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. + * + * RiscBSD kernel project + * + * trap.h + * + * Various trap definitions + */ + +/* + * Instructions used for breakpoints. + * + * These are undefined instructions. + * Technically the userspace breakpoint could be a SWI but we want to + * keep this the same as IPKDB which needs an undefined instruction as + * a break point. + * + * Ideally ARM would define several standard instruction sequences for + * use as breakpoints. + * + * The BKPT instruction isn't much use to us, since its behaviour is + * unpredictable on ARMv3 and lower. + * + * The ARM ARM says that for maximum compatibility, we should use undefined + * instructions that look like 0x.7f...f. . + */ + +#define GDB_BREAKPOINT 0xe6000011 /* Used by GDB 4.x */ +#define IPKDB_BREAKPOINT 0xe6000010 /* Used by IPKDB */ +#define GDB5_BREAKPOINT 0xe7ffdefe /* Used by GDB 5.0 */ +#define KERNEL_BREAKPOINT 0xe7ffffff /* Used by DDB */ + +#define KBPT_ASM ".word 0xe7ffdefe" + +#define USER_BREAKPOINT GDB_BREAKPOINT + +#define T_FAULT 1 \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/undefined.h b/lib/libc/include/arm-openbsd-eabi/arm/undefined.h new file mode 100644 index 000000000000..87fd59dd75c2 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/undefined.h @@ -0,0 +1,87 @@ +/* $OpenBSD: undefined.h,v 1.4 2019/03/13 09:28:21 patrick Exp $ */ +/* $NetBSD: undefined.h,v 1.4 2001/12/20 01:20:23 thorpej Exp $ */ + +/* + * Copyright (c) 1995-1996 Mark Brinicombe. + * Copyright (c) 1995 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Brini. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. + * + * RiscBSD kernel project + * + * undefined.h + * + * Undefined instruction types, symbols and prototypes + * + * Created : 08/02/95 + */ + + +#ifndef _ARM_UNDEFINED_H_ +#define _ARM_UNDEFINED_H_ +#ifdef _KERNEL + +#include + +typedef int (*undef_handler_t) (unsigned int, unsigned int, trapframe_t *, int, uint32_t); + +#define FP_COPROC 1 +#define FP_COPROC2 2 +#define MAX_COPROCS 16 + +/* Prototypes for undefined.c */ + +void *install_coproc_handler (int, undef_handler_t); +void remove_coproc_handler (void *); +void undefined_init (void); + +/* + * XXX Stuff below here is for use before malloc() is available. Most code + * shouldn't use it. + */ + +struct undefined_handler { + LIST_ENTRY(undefined_handler) uh_link; + undef_handler_t uh_handler; +}; + +/* + * Handlers installed using install_coproc_handler_static shouldn't be + * removed. + */ +void install_coproc_handler_static (int, struct undefined_handler *); + +/* Calls up to undefined.c from trap handlers */ +void undefinedinstruction(struct trapframe *); + +#endif + +#endif /* _ARM_UNDEFINED_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/vfp.h b/lib/libc/include/arm-openbsd-eabi/arm/vfp.h new file mode 100644 index 000000000000..eadfa46c5873 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/vfp.h @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2012 Mark Tinguely + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * $FreeBSD$ + */ + + +#ifndef _MACHINE__VFP_H_ +#define _MACHINE__VFP_H_ + +#ifdef _KERNEL +/* Only kernel defines exist here */ + +/* fpsid, fpscr, fpexc are defined in the newer gas */ +#define VFPSID cr0 +#define VFPSCR cr1 +#define VMVFR1 cr6 +#define VMVFR0 cr7 +#define VFPEXC cr8 +#define VFPINST cr9 /* vfp 1 and 2 except instruction */ +#define VFPINST2 cr10 /* vfp 2? */ + +/* VFPSID */ +#define VFPSID_IMPLEMENTOR_OFF 24 +#define VFPSID_IMPLEMENTOR_MASK (0xff000000) +#define VFPSID_HARDSOFT_IMP (0x00800000) +#define VFPSID_SINGLE_PREC 20 /* version 1 and 2 */ +#define VFPSID_SUBVERSION_OFF 16 +#define VFPSID_SUBVERSION2_MASK (0x000f0000) /* version 1 and 2 */ +#define VFPSID_SUBVERSION3_MASK (0x007f0000) /* version 3 */ +#define VFP_ARCH3 (0x00030000) +#define VFPSID_PARTNUMBER_OFF 8 +#define VFPSID_PARTNUMBER_MASK (0x0000ff00) +#define VFPSID_VARIANT_OFF 4 +#define VFPSID_VARIANT_MASK (0x000000f0) +#define VFPSID_REVISION_MASK 0x0f + +/* VFPSCR */ +#define VFPSCR_CC_N (0x80000000) /* comparison less than */ +#define VFPSCR_CC_Z (0x40000000) /* comparison equal */ +#define VFPSCR_CC_C (0x20000000) /* comparison = > unordered */ +#define VFPSCR_CC_V (0x10000000) /* comparison unordered */ +#define VFPSCR_QC (0x08000000) /* cumulative saturation */ +#define VFPSCR_DN (0x02000000) /* default NaN enable */ +#define VFPSCR_FZ (0x01000000) /* flush to zero enabled */ + +#define VFPSCR_RMODE_OFF 22 /* rounding mode offset */ +#define VFPSCR_RMODE_MASK (0x00c00000) /* rounding mode mask */ +#define VFPSCR_RMODE_RN (0x00000000) /* round nearest */ +#define VFPSCR_RMODE_RPI (0x00400000) /* round to plus infinity */ +#define VFPSCR_RMODE_RNI (0x00800000) /* round to neg infinity */ +#define VFPSCR_RMODE_RM (0x00c00000) /* round to zero */ + +#define VFPSCR_STRIDE_OFF 20 /* vector stride -1 */ +#define VFPSCR_STRIDE_MASK (0x00300000) +#define VFPSCR_LEN_OFF 16 /* vector length -1 */ +#define VFPSCR_LEN_MASK (0x00070000) +#define VFPSCR_IDE (0x00008000) /* input subnormal exc enable */ +#define VFPSCR_IXE (0x00001000) /* inexact exception enable */ +#define VFPSCR_UFE (0x00000800) /* underflow exception enable */ +#define VFPSCR_OFE (0x00000400) /* overflow exception enable */ +#define VFPSCR_DNZ (0x00000200) /* div by zero exception en */ +#define VFPSCR_IOE (0x00000100) /* invalid op exec enable */ +#define VFPSCR_IDC (0x00000080) /* input subnormal cumul */ +#define VFPSCR_IXC (0x00000010) /* Inexact cumulative flag */ +#define VFPSCR_UFC (0x00000008) /* underflow cumulative flag */ +#define VFPSCR_OFC (0x00000004) /* overflow cumulative flag */ +#define VFPSCR_DZC (0x00000002) /* division by zero flag */ +#define VFPSCR_IOC (0x00000001) /* invalid operation cumul */ + +/* VFPEXC */ +#define VFPEXC_EX (0x80000000) /* exception v1 v2 */ +#define VFPEXC_EN (0x40000000) /* vfp enable */ + +/* version 3 registers */ +/* VMVFR0 */ +#define VMVFR0_RM_OFF 28 +#define VMVFR0_RM_MASK (0xf0000000) /* VFP rounding modes */ + +#define VMVFR0_SV_OFF 24 +#define VMVFR0_SV_MASK (0x0f000000) /* VFP short vector supp */ +#define VMVFR0_SR_OFF 20 +#define VMVFR0_SR (0x00f00000) /* VFP hw sqrt supp */ +#define VMVFR0_D_OFF 16 +#define VMVFR0_D_MASK (0x000f0000) /* VFP divide supp */ +#define VMVFR0_TE_OFF 12 +#define VMVFR0_TE_MASK (0x0000f000) /* VFP trap exception supp */ +#define VMVFR0_DP_OFF 8 +#define VMVFR0_DP_MASK (0x00000f00) /* VFP double prec support */ +#define VMVFR0_SP_OFF 4 +#define VMVFR0_SP_MASK (0x000000f0) /* VFP single prec support */ +#define VMVFR0_RB_MASK (0x0000000f) /* VFP 64 bit media support */ + +/* VMVFR1 */ +#define VMVFR1_SP_OFF 16 +#define VMVFR1_SP_MASK (0x000f0000) /* Neon single prec support */ +#define VMVFR1_I_OFF 12 +#define VMVFR1_I_MASK (0x0000f000) /* Neon integer support */ +#define VMVFR1_LS_OFF 8 +#define VMVFR1_LS_MASK (0x00000f00) /* Neon ld/st instr support */ +#define VMVFR1_DN_OFF 4 +#define VMVFR1_DN_MASK (0x000000f0) /* Neon prop NaN support */ +#define VMVFR1_FZ_MASK (0x0000000f) /* Neon denormal arith supp */ + +#define COPROC10 (0x3 << 20) +#define COPROC11 (0x3 << 22) + +void vfp_init(void); +void vfp_discard(struct proc *); +uint32_t vfp_save(void); +void vfp_enable(void); + +#endif /* _KERNEL */ +#endif /* _MACHINE__VFP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/arm/vmparam.h b/lib/libc/include/arm-openbsd-eabi/arm/vmparam.h new file mode 100644 index 000000000000..6a93dd73786a --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/arm/vmparam.h @@ -0,0 +1,85 @@ +/* $OpenBSD: vmparam.h,v 1.20 2024/02/01 00:39:57 deraadt Exp $ */ +/* $NetBSD: vmparam.h,v 1.18 2003/05/21 18:04:44 thorpej Exp $ */ + +/* + * Copyright (c) 2001, 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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 _ARM_VMPARAM_H_ +#define _ARM_VMPARAM_H_ + +/* + * Virtual Memory parameters common to all arm32 platforms. + */ + +#define USRSTACK VM_MAXUSER_ADDRESS +#define KERNBASE VM_MAXUSER_ADDRESS + +#define MAXTSIZ (128*1024*1024) /* max text size */ + +#ifndef DFLDSIZ +#define DFLDSIZ (128*1024*1024) /* initial data size limit */ +#endif +#ifndef MAXDSIZ +#define MAXDSIZ (512*1024*1024) /* max data size */ +#endif +#ifndef BRKSIZ +#define BRKSIZ MAXDSIZ /* heap gap size */ +#endif +#ifndef DFLSSIZ +#define DFLSSIZ (2*1024*1024) /* initial stack size limit */ +#endif +#ifndef MAXSSIZ +#define MAXSSIZ (32*1024*1024) /* max stack size */ +#endif + +#define STACKGAP_RANDOM 256*1024 + +/* + * Size of SysV shared memory map + */ +#ifndef SHMMAXPGS +#define SHMMAXPGS 1024 +#endif + +/* + * Mach derived constants + */ +#define VM_MIN_ADDRESS ((vaddr_t) PAGE_SIZE) +#define VM_MAXUSER_ADDRESS ((vaddr_t) ARM_KERNEL_BASE) +#define VM_MAX_ADDRESS VM_MAXUSER_ADDRESS + +#define VM_MIN_KERNEL_ADDRESS ((vaddr_t) ARM_KERNEL_BASE) + +#endif /* _ARM_VMPARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/_float.h b/lib/libc/include/arm-openbsd-eabi/armv7/_float.h new file mode 100644 index 000000000000..0f250fbbe4d1 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/_float.h @@ -0,0 +1,3 @@ +/* $OpenBSD: _float.h,v 1.1 2013/09/04 14:38:26 patrick Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/_types.h b/lib/libc/include/arm-openbsd-eabi/armv7/_types.h new file mode 100644 index 000000000000..74ac2daf85df --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/_types.h @@ -0,0 +1,9 @@ +/* $OpenBSD: _types.h,v 1.1 2013/09/04 14:38:26 patrick Exp $ */ +/* $NetBSD: types.h,v 1.4 2002/02/28 03:17:26 simonb Exp $ */ + +#ifndef _MACHINE__TYPES_H_ +#define _MACHINE__TYPES_H_ + +#include + +#endif /* _MACHINE__TYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/apmvar.h b/lib/libc/include/arm-openbsd-eabi/armv7/apmvar.h new file mode 100644 index 000000000000..191926310246 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/apmvar.h @@ -0,0 +1,2 @@ +/* $OpenBSD: apmvar.h,v 1.1 2013/09/04 14:38:26 patrick Exp $ */ +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/asm.h b/lib/libc/include/arm-openbsd-eabi/armv7/asm.h new file mode 100644 index 000000000000..358368b17d2d --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/asm.h @@ -0,0 +1,4 @@ +/* $OpenBSD: asm.h,v 1.1 2013/09/04 14:38:26 patrick Exp $ */ +/* $NetBSD: asm.h,v 1.3 2001/11/25 15:55:54 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/atomic.h b/lib/libc/include/arm-openbsd-eabi/armv7/atomic.h new file mode 100644 index 000000000000..ec3b2814a4eb --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/atomic.h @@ -0,0 +1,10 @@ +/* $OpenBSD: atomic.h,v 1.1 2013/09/04 14:38:26 patrick Exp $ */ + +/* Public Domain */ + +#ifndef _MACHINE_ATOMIC_H_ +#define _MACHINE_ATOMIC_H_ + +#include + +#endif /* _MACHINE_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/bootconfig.h b/lib/libc/include/arm-openbsd-eabi/armv7/bootconfig.h new file mode 100644 index 000000000000..c806b7a421c2 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/bootconfig.h @@ -0,0 +1,70 @@ +/* $OpenBSD: bootconfig.h,v 1.2 2019/05/06 03:34:43 mlarkin Exp $ */ +/* $NetBSD: bootconfig.h,v 1.2 2001/06/21 22:08:28 chris Exp $ */ + +/* + * Copyright (c) 1994 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mark Brinicombe + * for the NetBSD Project. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR 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. + * + * boot configuration structures + * + * Created : 12/09/94 + * + * Based on kate/boot/bootconfig.h + */ + +#if defined(_KERNEL) || defined(_STANDALONE) + +typedef struct _PhysMem { + u_int address; + u_int pages; +} PhysMem; + +#define DRAM_BLOCKS 2 +#define MAX_BOOT_STRING 255 + +typedef struct _BootConfig { + PhysMem dram[DRAM_BLOCKS]; + u_int dramblocks; + char bootstring[MAX_BOOT_STRING]; +} BootConfig; + +extern BootConfig bootconfig; + +#endif /* _KERNEL || _STANDALONE */ +#if defined(_KERNEL) +extern char *boot_args; +extern char *boot_file; +#endif /* _KERNEL */ + +/* End of bootconfig.h */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/bus.h b/lib/libc/include/arm-openbsd-eabi/armv7/bus.h new file mode 100644 index 000000000000..0a27ab9dd430 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/bus.h @@ -0,0 +1,4 @@ +/* $OpenBSD: bus.h,v 1.1 2013/09/04 14:38:26 patrick Exp $ */ +/* $NetBSD: bus.h,v 1.3 2001/11/25 15:55:55 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/cdefs.h b/lib/libc/include/arm-openbsd-eabi/armv7/cdefs.h new file mode 100644 index 000000000000..8ca96399b0ea --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/cdefs.h @@ -0,0 +1,3 @@ +/* $OpenBSD: cdefs.h,v 1.1 2013/09/04 14:38:26 patrick Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/conf.h b/lib/libc/include/arm-openbsd-eabi/armv7/conf.h new file mode 100644 index 000000000000..514e8d026224 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/conf.h @@ -0,0 +1,10 @@ +/* $OpenBSD: conf.h,v 1.2 2025/07/16 03:01:53 jsg Exp $ */ +/* $NetBSD: conf.h,v 1.8 2002/02/10 12:26:03 chris Exp $ */ + +#ifndef _MACHINE_CONF_H_ +#define _MACHINE_CONF_H_ + +#include +#include + +#endif /* _MACHINE_CONF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/cpu.h b/lib/libc/include/arm-openbsd-eabi/armv7/cpu.h new file mode 100644 index 000000000000..e9e7ffb3c6e2 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/cpu.h @@ -0,0 +1,4 @@ +/* $OpenBSD: cpu.h,v 1.1 2013/09/04 14:38:26 patrick Exp $ */ +/* $NetBSD: cpu.h,v 1.3 2001/11/25 15:55:55 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/cpufunc.h b/lib/libc/include/arm-openbsd-eabi/armv7/cpufunc.h new file mode 100644 index 000000000000..83545e6386ea --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/cpufunc.h @@ -0,0 +1,16 @@ +/* $OpenBSD: cpufunc.h,v 1.1 2020/11/29 12:54:36 kettenis Exp $ */ + +/* Public Domain */ + +#ifndef _MACHINE_CPUFUNC_H_ +#define _MACHINE_CPUFUNC_H_ + +#include + +#ifdef _KERNEL + +register_t smc_call(register_t, register_t, register_t, register_t); + +#endif /* _KERNEL */ + +#endif /* _MACHINE_CPUFUNC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/db_machdep.h b/lib/libc/include/arm-openbsd-eabi/armv7/db_machdep.h new file mode 100644 index 000000000000..0142ddba5ed3 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/db_machdep.h @@ -0,0 +1,4 @@ +/* $OpenBSD: db_machdep.h,v 1.1 2013/09/04 14:38:26 patrick Exp $ */ +/* $NetBSD: db_machdep.h,v 1.3 2001/11/25 15:55:55 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/disklabel.h b/lib/libc/include/arm-openbsd-eabi/armv7/disklabel.h new file mode 100644 index 000000000000..bb72317025cb --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/disklabel.h @@ -0,0 +1,3 @@ +/* $OpenBSD: disklabel.h,v 1.1 2013/09/04 14:38:27 patrick Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/elf.h b/lib/libc/include/arm-openbsd-eabi/armv7/elf.h new file mode 100644 index 000000000000..adbf226bf24e --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/elf.h @@ -0,0 +1,3 @@ +/* $OpenBSD: elf.h,v 1.1 2024/07/14 19:33:59 miod Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/endian.h b/lib/libc/include/arm-openbsd-eabi/armv7/endian.h new file mode 100644 index 000000000000..a38e0819d637 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/endian.h @@ -0,0 +1,4 @@ +/* $OpenBSD: endian.h,v 1.1 2013/09/04 14:38:27 patrick Exp $ */ +/* $NetBSD: endian.h,v 1.3 2001/11/25 15:55:56 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/exec.h b/lib/libc/include/arm-openbsd-eabi/armv7/exec.h new file mode 100644 index 000000000000..6bb7f50e7ef1 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/exec.h @@ -0,0 +1,3 @@ +/* $OpenBSD: exec.h,v 1.1 2013/09/04 14:38:27 patrick Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/fdt.h b/lib/libc/include/arm-openbsd-eabi/armv7/fdt.h new file mode 100644 index 000000000000..386a6d31cf01 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/fdt.h @@ -0,0 +1,3 @@ +/* $OpenBSD: fdt.h,v 1.1 2016/05/02 08:15:55 patrick Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/fenv.h b/lib/libc/include/arm-openbsd-eabi/armv7/fenv.h new file mode 100644 index 000000000000..1f648e10050b --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/fenv.h @@ -0,0 +1,3 @@ +/* $OpenBSD: fenv.h,v 1.1 2013/09/04 14:38:27 patrick Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/frame.h b/lib/libc/include/arm-openbsd-eabi/armv7/frame.h new file mode 100644 index 000000000000..9ca41597feb2 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/frame.h @@ -0,0 +1,4 @@ +/* $OpenBSD: frame.h,v 1.1 2013/09/04 14:38:27 patrick Exp $ */ +/* $NetBSD: frame.h,v 1.1 2001/06/08 22:23:00 chris Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/ieee.h b/lib/libc/include/arm-openbsd-eabi/armv7/ieee.h new file mode 100644 index 000000000000..cbd95dc298c8 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/ieee.h @@ -0,0 +1,4 @@ +/* $OpenBSD: ieee.h,v 1.1 2013/09/04 14:38:27 patrick Exp $ */ +/* $NetBSD: ieee.h,v 1.3 2001/11/25 15:55:56 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/ieeefp.h b/lib/libc/include/arm-openbsd-eabi/armv7/ieeefp.h new file mode 100644 index 000000000000..f4c270c6903a --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/ieeefp.h @@ -0,0 +1,4 @@ +/* $OpenBSD: ieeefp.h,v 1.1 2013/09/04 14:38:27 patrick Exp $ */ +/* $NetBSD: ieeefp.h,v 1.3 2001/11/25 15:55:56 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/intr.h b/lib/libc/include/arm-openbsd-eabi/armv7/intr.h new file mode 100644 index 000000000000..0f597a3f152d --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/intr.h @@ -0,0 +1,229 @@ +/* $OpenBSD: intr.h,v 1.16 2025/05/10 10:11:02 visa Exp $ */ +/* $NetBSD: intr.h,v 1.12 2003/06/16 20:00:59 thorpej Exp $ */ + +/* + * Copyright (c) 2001, 2003 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_INTR_H_ +#define _MACHINE_INTR_H_ + +#ifdef _KERNEL + +/* Interrupt priority `levels'; not mutually exclusive. */ +#define IPL_NONE 0 /* nothing */ +#define IPL_SOFTCLOCK 2 /* soft clock interrupts */ +#define IPL_SOFTNET 3 /* soft network interrupts */ +#define IPL_SOFTTTY 4 /* soft terminal interrupts */ +#define IPL_BIO 5 /* block I/O */ +#define IPL_NET 6 /* network */ +#define IPL_TTY 7 /* terminal */ +#define IPL_VM 8 /* memory allocation */ +#define IPL_AUDIO 9 /* audio */ +#define IPL_CLOCK 10 /* clock */ +#define IPL_SCHED IPL_CLOCK +#define IPL_STATCLOCK IPL_CLOCK +#define IPL_HIGH 11 /* everything */ +#define IPL_IPI 12 /* interprocessor interrupt */ +#define NIPL 13 /* number of levels */ + +#define IPL_MPFLOOR IPL_TTY +/* Interrupt priority 'flags'. */ +#define IPL_IRQMASK 0xf /* priority only */ +#define IPL_FLAGMASK 0xf00 /* flags only*/ +#define IPL_MPSAFE 0x100 /* 'mpsafe' interrupt, no kernel lock */ + +/* Interrupt sharing types. */ +#define IST_NONE 0 /* none */ +#define IST_PULSE 1 /* pulsed */ +#define IST_EDGE 2 /* edge-triggered */ +#define IST_LEVEL 3 /* level-triggered */ + +#define IST_LEVEL_LOW IST_LEVEL +#define IST_LEVEL_HIGH 4 +#define IST_EDGE_FALLING IST_EDGE +#define IST_EDGE_RISING 5 +#define IST_EDGE_BOTH 6 + +#define __USE_MI_SOFTINTR + +#include + +#ifndef _LOCORE +#include + +struct cpu_info; + +int splraise(int); +int spllower(int); +void splx(int); + +void arm_do_pending_intr(int); +void arm_set_intr_handler(int (*raise)(int), int (*lower)(int), + void (*x)(int), void (*setipl)(int), + void *(*intr_establish)(int irqno, int level, struct cpu_info *ci, + int (*func)(void *), void *cookie, char *name), + void (*intr_disestablish)(void *cookie), + const char *(*intr_string)(void *cookie), + void (*intr_handle)(void *)); + +struct arm_intr_func { + int (*raise)(int); + int (*lower)(int); + void (*x)(int); + void (*setipl)(int); + void *(*intr_establish)(int irqno, int level, struct cpu_info *, + int (*func)(void *), void *cookie, char *name); + void (*intr_disestablish)(void *cookie); + const char *(*intr_string)(void *cookie); +}; + +extern struct arm_intr_func arm_intr_func; + +#define splraise(cpl) (arm_intr_func.raise(cpl)) +#define _splraise(cpl) (arm_intr_func.raise(cpl)) +#define spllower(cpl) (arm_intr_func.lower(cpl)) +#define splx(cpl) (arm_intr_func.x(cpl)) + +#define splhigh() splraise(IPL_HIGH) +#define splsoftclock() splraise(IPL_SOFTCLOCK) +#define splsoftnet() splraise(IPL_SOFTNET) +#define splbio() splraise(IPL_BIO) +#define splnet() splraise(IPL_NET) +#define spltty() splraise(IPL_TTY) +#define splvm() splraise(IPL_VM) +#define splaudio() splraise(IPL_AUDIO) +#define splclock() splraise(IPL_CLOCK) +#define splstatclock() splraise(IPL_STATCLOCK) + +#define spl0() spllower(IPL_NONE) + +#define splsched() splhigh() + +void intr_barrier(void *); + +void arm_init_smask(void); /* XXX */ +extern uint32_t arm_smask[NIPL]; +void arm_setsoftintr(int si); + +#define softintr arm_setsoftintr + +void *arm_intr_establish(int irqno, int level, int (*func)(void *), + void *cookie, char *name); +void arm_intr_disestablish(void *cookie); +const char *arm_intr_string(void *cookie); + +/* XXX - this is probably the wrong location for this */ +void arm_clock_register(void (*)(void), void (*)(u_int), void (*)(int), + void (*)(void)); + +struct interrupt_controller { + int ic_node; + void *ic_cookie; + void *(*ic_establish)(void *, int *, int, struct cpu_info *, + int (*)(void *), void *, char *); + void *(*ic_establish_msi)(void *, uint64_t *, uint64_t *, int, + struct cpu_info *, int (*)(void *), void *, char *); + void (*ic_disestablish)(void *); + void (*ic_enable)(void *); + void (*ic_disable)(void *); + void (*ic_route)(void *, int, struct cpu_info *); + void (*ic_cpu_enable)(void); + void (*ic_barrier)(void *); + + LIST_ENTRY(interrupt_controller) ic_list; + uint32_t ic_phandle; + uint32_t ic_cells; +}; + +void arm_intr_init_fdt(void); +void arm_intr_register_fdt(struct interrupt_controller *); +void *arm_intr_establish_fdt(int, int, int (*)(void *), + void *, char *); +void *arm_intr_establish_fdt_cpu(int, int, struct cpu_info *, + int (*)(void *), void *, char *); +void *arm_intr_establish_fdt_idx(int, int, int, int (*)(void *), + void *, char *); +void *arm_intr_establish_fdt_idx_cpu(int, int, int, struct cpu_info *, + int (*)(void *), void *, char *); +void *arm_intr_establish_fdt_imap(int, int *, int, int, int (*)(void *), + void *, char *); +void *arm_intr_establish_fdt_imap_cpu(int, int *, int, int, + struct cpu_info *, int (*)(void *), void *, char *); +void *arm_intr_establish_fdt_msi(int, uint64_t *, uint64_t *, int, + int (*)(void *), void *, char *); +void *arm_intr_establish_fdt_msi_cpu(int, uint64_t *, uint64_t *, int, + struct cpu_info *, int (*)(void *), void *, char *); +void arm_intr_disestablish_fdt(void *); +void arm_intr_enable(void *); +void arm_intr_disable(void *); +void arm_intr_route(void *, int, struct cpu_info *); +void arm_intr_cpu_enable(void); + +void *arm_intr_parent_establish_fdt(void *, int *, int, + struct cpu_info *ci, int (*)(void *), void *, char *); +void arm_intr_parent_disestablish_fdt(void *); + +void arm_send_ipi(struct cpu_info *, int); +extern void (*intr_send_ipi_func)(struct cpu_info *, int); + +#define ARM_IPI_NOP 0 +#define ARM_IPI_DDB 1 + +#ifdef DIAGNOSTIC +/* + * Although this function is implemented in MI code, it must be in this MD + * header because we don't want this header to include MI includes. + */ +void splassert_fail(int, int, const char *); +extern int splassert_ctl; +void arm_splassert_check(int, const char *); +#define splassert(__wantipl) do { \ + if (splassert_ctl > 0) { \ + arm_splassert_check(__wantipl, __func__); \ + } \ +} while (0) +#define splsoftassert(wantipl) splassert(wantipl) +#else +#define splassert(wantipl) do { /* nothing */ } while (0) +#define splsoftassert(wantipl) do { /* nothing */ } while (0) +#endif + +#endif /* ! _LOCORE */ + +#define ARM_IRQ_HANDLER arm_intr + +#endif /* _KERNEL */ + +#endif /* _MACHINE_INTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/limits.h b/lib/libc/include/arm-openbsd-eabi/armv7/limits.h new file mode 100644 index 000000000000..59a9c2820add --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/limits.h @@ -0,0 +1,4 @@ +/* $OpenBSD: limits.h,v 1.1 2013/09/04 14:38:27 patrick Exp $ */ +/* $NetBSD: limits.h,v 1.3 2001/11/25 15:55:57 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/loadfile_machdep.h b/lib/libc/include/arm-openbsd-eabi/armv7/loadfile_machdep.h new file mode 100644 index 000000000000..d4af12ff27ff --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/loadfile_machdep.h @@ -0,0 +1,53 @@ +/* $OpenBSD: loadfile_machdep.h,v 1.5 2019/04/10 04:17:34 deraadt Exp $ */ +/* $NetBSD: loadfile_machdep.h,v 1.1 1999/04/29 03:17:12 tsubai Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define BOOT_ELF +#define ELFSIZE 32 + +#define LOAD_KERNEL LOAD_ALL +#define COUNT_KERNEL COUNT_ALL + +extern u_long efi_loadaddr; +#define LOADADDR(a) (((((u_long)(a)) + offset)&0xfffffff) + \ + efi_loadaddr) +#define ALIGNENTRY(a) ((u_long)(a)) +#define READ(f, b, c) read((f), (void *)LOADADDR(b), (c)) +#define BCOPY(s, d, c) memcpy((void *)LOADADDR(d), (void *)(s), (c)) +#define BZERO(d, c) memset((void *)LOADADDR(d), 0, (c)) +#define WARN(a) (void)(printf a, \ + printf((errno ? ": %s\n" : "\n"), \ + strerror(errno))) +#define PROGRESS(a) (void) printf a +#define ALLOC(a) alloc(a) +#define FREE(a, b) free(a, b) + +void run_loadfile(uint64_t *, int); \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/machine_reg.h b/lib/libc/include/arm-openbsd-eabi/armv7/machine_reg.h new file mode 100644 index 000000000000..ef8753801289 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/machine_reg.h @@ -0,0 +1,57 @@ +/* $OpenBSD: machine_reg.h,v 1.3 2019/05/06 03:34:43 mlarkin Exp $ */ + +/* + * Copyright (c) 2002, 2003 Genetec Corporation. All rights reserved. + * Written by Hiroyuki Bessho for Genetec Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of Genetec Corporation may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``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 GENETEC CORPORATION + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef _MACHINE_REG_H +#define _MACHINE_REG_H + +/* + * Logical mapping for onboard/integrated peripherals + */ +#define MACHINE_IO_AREA_VBASE 0xfd000000 +#define MACHINE_GPIO_VBASE 0xfd000000 +#define MACHINE_CLKMAN_VBASE 0xfd100000 +#define MACHINE_INTCTL_VBASE 0xfd200000 +#define MACHINE_AGPIO_VBASE 0xfd300000 +#define MACHINE_VBASE_FREE 0xfd400000 +/* FFUART and/or BTUART are mapped to this area when + used for console */ + +#define ioreg_read(a) (*(volatile unsigned *)(a)) +#define ioreg_write(a,v) (*(volatile unsigned *)(a)=(v)) + +#define ioreg16_read(a) (*(volatile uint16_t *)(a)) +#define ioreg16_write(a,v) (*(volatile uint16_t *)(a)=(v)) + +#define ioreg8_read(a) (*(volatile uint8_t *)(a)) +#define ioreg8_write(a,v) (*(volatile uint8_t *)(a)=(v)) + +#endif /* _MACHINE_REG_H */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/mplock.h b/lib/libc/include/arm-openbsd-eabi/armv7/mplock.h new file mode 100644 index 000000000000..d4ecdcd49fab --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/mplock.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mplock.h,v 1.1 2018/08/06 18:39:13 kettenis Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/mutex.h b/lib/libc/include/arm-openbsd-eabi/armv7/mutex.h new file mode 100644 index 000000000000..1af94436f5a7 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/mutex.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mutex.h,v 1.1 2013/09/04 14:38:28 patrick Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/openpromio.h b/lib/libc/include/arm-openbsd-eabi/armv7/openpromio.h new file mode 100644 index 000000000000..39f68f71a594 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/openpromio.h @@ -0,0 +1,3 @@ +/* $OpenBSD: openpromio.h,v 1.1 2016/05/21 21:24:36 kettenis Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/param.h b/lib/libc/include/arm-openbsd-eabi/armv7/param.h new file mode 100644 index 000000000000..72d453ef46ba --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/param.h @@ -0,0 +1,51 @@ +/* $OpenBSD: param.h,v 1.3 2018/08/09 12:19:32 patrick Exp $ */ + +/* + * Copyright (c) 1994,1995 Mark Brinicombe. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the RiscBSD team. + * 4. The name "RiscBSD" nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RISCBSD ``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 RISCBSD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ + +#include + +#define _MACHINE armv7 +#define MACHINE "armv7" + +#ifndef MSGBUFSIZE +#define MSGBUFSIZE (8 * PAGE_SIZE) +#endif + +#ifdef _KERNEL +#define __HAVE_FDT +#endif + +#endif /* _MACHINE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/pcb.h b/lib/libc/include/arm-openbsd-eabi/armv7/pcb.h new file mode 100644 index 000000000000..d2b73c6db576 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/pcb.h @@ -0,0 +1,4 @@ +/* $OpenBSD: pcb.h,v 1.1 2013/09/04 14:38:28 patrick Exp $ */ +/* $NetBSD: pcb.h,v 1.3 2001/11/25 15:55:57 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/pci_machdep.h b/lib/libc/include/arm-openbsd-eabi/armv7/pci_machdep.h new file mode 100644 index 000000000000..54442a800530 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/pci_machdep.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pci_machdep.h,v 1.1 2018/07/09 09:53:06 patrick Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/pmap.h b/lib/libc/include/arm-openbsd-eabi/armv7/pmap.h new file mode 100644 index 000000000000..bc631302ef85 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/pmap.h @@ -0,0 +1,4 @@ +/* $OpenBSD: pmap.h,v 1.1 2013/09/04 14:38:28 patrick Exp $ */ +/* $NetBSD: pmap.h,v 1.2 2001/11/23 17:29:01 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/proc.h b/lib/libc/include/arm-openbsd-eabi/armv7/proc.h new file mode 100644 index 000000000000..d92b1e2712db --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/proc.h @@ -0,0 +1,4 @@ +/* $OpenBSD: proc.h,v 1.1 2013/09/04 14:38:28 patrick Exp $ */ +/* $NetBSD: proc.h,v 1.3 2001/11/25 15:55:57 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/profile.h b/lib/libc/include/arm-openbsd-eabi/armv7/profile.h new file mode 100644 index 000000000000..72aa69fcf300 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/profile.h @@ -0,0 +1,4 @@ +/* $OpenBSD: profile.h,v 1.1 2013/09/04 14:38:28 patrick Exp $ */ +/* $NetBSD: profile.h,v 1.3 2001/11/25 15:55:57 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/ptrace.h b/lib/libc/include/arm-openbsd-eabi/armv7/ptrace.h new file mode 100644 index 000000000000..fda3e95619c4 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/ptrace.h @@ -0,0 +1,4 @@ +/* $OpenBSD: ptrace.h,v 1.1 2013/09/04 14:38:28 patrick Exp $ */ +/* $NetBSD: ptrace.h,v 1.3 2001/11/25 15:55:58 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/reg.h b/lib/libc/include/arm-openbsd-eabi/armv7/reg.h new file mode 100644 index 000000000000..8bee9a0ffcfa --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/reg.h @@ -0,0 +1,4 @@ +/* $OpenBSD: reg.h,v 1.1 2013/09/04 14:38:28 patrick Exp $ */ +/* $NetBSD: reg.h,v 1.3 2001/11/25 15:55:58 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/reloc.h b/lib/libc/include/arm-openbsd-eabi/armv7/reloc.h new file mode 100644 index 000000000000..d4311b2f1410 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/reloc.h @@ -0,0 +1,2 @@ +/* $OpenBSD: reloc.h,v 1.1 2013/09/04 14:38:29 patrick Exp $ */ +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/setjmp.h b/lib/libc/include/arm-openbsd-eabi/armv7/setjmp.h new file mode 100644 index 000000000000..5125b28bd363 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/setjmp.h @@ -0,0 +1,4 @@ +/* $OpenBSD: setjmp.h,v 1.1 2013/09/04 14:38:29 patrick Exp $ */ +/* $NetBSD: setjmp.h,v 1.3 2001/11/25 15:55:58 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/signal.h b/lib/libc/include/arm-openbsd-eabi/armv7/signal.h new file mode 100644 index 000000000000..0fc0632217b8 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/signal.h @@ -0,0 +1,4 @@ +/* $OpenBSD: signal.h,v 1.1 2013/09/04 14:38:29 patrick Exp $ */ +/* $NetBSD: signal.h,v 1.3 2001/11/25 15:55:58 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/simplebusvar.h b/lib/libc/include/arm-openbsd-eabi/armv7/simplebusvar.h new file mode 100644 index 000000000000..0620d804493f --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/simplebusvar.h @@ -0,0 +1,3 @@ +/* $OpenBSD: simplebusvar.h,v 1.1 2023/09/22 01:10:43 jsg Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/spinlock.h b/lib/libc/include/arm-openbsd-eabi/armv7/spinlock.h new file mode 100644 index 000000000000..675d503f4362 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/spinlock.h @@ -0,0 +1,3 @@ +/* $OpenBSD: spinlock.h,v 1.2 2017/01/05 16:52:42 patrick Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/sysarch.h b/lib/libc/include/arm-openbsd-eabi/armv7/sysarch.h new file mode 100644 index 000000000000..4a65320d7030 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/sysarch.h @@ -0,0 +1,4 @@ +/* $OpenBSD: sysarch.h,v 1.1 2013/09/04 14:38:29 patrick Exp $ */ +/* $NetBSD: sysarch.h,v 1.3 2001/11/25 15:55:58 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/tcb.h b/lib/libc/include/arm-openbsd-eabi/armv7/tcb.h new file mode 100644 index 000000000000..a5a3f7799f2c --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/tcb.h @@ -0,0 +1,3 @@ +/* $OpenBSD: tcb.h,v 1.1 2013/09/04 14:38:29 patrick Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/timetc.h b/lib/libc/include/arm-openbsd-eabi/armv7/timetc.h new file mode 100644 index 000000000000..9af8a41ca23f --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/timetc.h @@ -0,0 +1,23 @@ +/* $OpenBSD: timetc.h,v 1.1 2020/07/06 13:33:07 pirofti Exp $ */ +/* + * Copyright (c) 2020 Paul Irofti + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TIMETC_H_ +#define _MACHINE_TIMETC_H_ + +#define TC_LAST 0 + +#endif /* _MACHINE_TIMETC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/trap.h b/lib/libc/include/arm-openbsd-eabi/armv7/trap.h new file mode 100644 index 000000000000..2904fcc7b59d --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/trap.h @@ -0,0 +1,4 @@ +/* $OpenBSD: trap.h,v 1.1 2013/09/04 14:38:29 patrick Exp $ */ +/* $NetBSD: trap.h,v 1.3 2001/11/25 15:55:58 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/armv7/vmparam.h b/lib/libc/include/arm-openbsd-eabi/armv7/vmparam.h new file mode 100644 index 000000000000..fb4d068a386a --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/armv7/vmparam.h @@ -0,0 +1,98 @@ +/* $OpenBSD: vmparam.h,v 1.8 2023/11/12 16:37:28 kettenis Exp $ */ +/* $NetBSD: vmparam.h,v 1.23 2003/05/22 05:47:07 thorpej Exp $ */ + +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_VMPARAM_H_ +#define _MACHINE_VMPARAM_H_ + +#define ARM_KERNEL_BASE 0xc0000000U + +/* Allow armv7 to have bigger limits than generic arm, allow user to override */ +#ifndef MAXDSIZ +#define MAXDSIZ (2UL*1024*1024*1024) /* max data size */ +#endif +#ifndef BRKSIZ +#define BRKSIZ MAXDSIZ /* heap gap size */ +#endif +#ifndef DFLSSIZ +#define DFLSSIZ (4*1024*1024) /* initial stack size limit */ +#endif +#ifndef MAXSSIZ +#define MAXSSIZ (32*1024*1024) /* max stack size */ +#endif + +#include + +#ifdef _KERNEL +/* + * Address space constants + */ + +/* + * The line between user space and kernel space + * Mappings >= KERNEL_BASE are constant across all processes + */ +#define KERNEL_BASE ARM_KERNEL_BASE + +#define VM_KERNEL_SPACE_SIZE 0x20000000 + +/* + * Override the default pager_map size, there's not enough KVA. + */ +#define PAGER_MAP_SIZE (4 * 1024 * 1024) + +/* + * Size of User Raw I/O map + */ + +#define USRIOSIZE 300 + +/* virtual sizes (bytes) for various kernel submaps */ + +#define VM_PHYS_SIZE (USRIOSIZE*PAGE_SIZE) + +/* + * max number of non-contig chunks of physical RAM you can have + */ + +#define VM_PHYSSEG_MAX 32 +#define VM_PHYSSEG_STRAT VM_PSTRAT_BSEARCH + +/* + * this indicates that we can't add RAM to the VM system after the + * vm system is init'd. + */ + +#define VM_PHYSSEG_NOADD + +#endif /* _KERNEL */ + +#endif /* _MACHINE_VMPARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/frame.h b/lib/libc/include/arm-openbsd-eabi/frame.h new file mode 100644 index 000000000000..9ca41597feb2 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/frame.h @@ -0,0 +1,4 @@ +/* $OpenBSD: frame.h,v 1.1 2013/09/04 14:38:27 patrick Exp $ */ +/* $NetBSD: frame.h,v 1.1 2001/06/08 22:23:00 chris Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/_float.h b/lib/libc/include/arm-openbsd-eabi/machine/_float.h new file mode 100644 index 000000000000..0f250fbbe4d1 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/_float.h @@ -0,0 +1,3 @@ +/* $OpenBSD: _float.h,v 1.1 2013/09/04 14:38:26 patrick Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/_types.h b/lib/libc/include/arm-openbsd-eabi/machine/_types.h new file mode 100644 index 000000000000..74ac2daf85df --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/_types.h @@ -0,0 +1,9 @@ +/* $OpenBSD: _types.h,v 1.1 2013/09/04 14:38:26 patrick Exp $ */ +/* $NetBSD: types.h,v 1.4 2002/02/28 03:17:26 simonb Exp $ */ + +#ifndef _MACHINE__TYPES_H_ +#define _MACHINE__TYPES_H_ + +#include + +#endif /* _MACHINE__TYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/apmvar.h b/lib/libc/include/arm-openbsd-eabi/machine/apmvar.h new file mode 100644 index 000000000000..191926310246 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/apmvar.h @@ -0,0 +1,2 @@ +/* $OpenBSD: apmvar.h,v 1.1 2013/09/04 14:38:26 patrick Exp $ */ +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/asm.h b/lib/libc/include/arm-openbsd-eabi/machine/asm.h new file mode 100644 index 000000000000..358368b17d2d --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/asm.h @@ -0,0 +1,4 @@ +/* $OpenBSD: asm.h,v 1.1 2013/09/04 14:38:26 patrick Exp $ */ +/* $NetBSD: asm.h,v 1.3 2001/11/25 15:55:54 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/atomic.h b/lib/libc/include/arm-openbsd-eabi/machine/atomic.h new file mode 100644 index 000000000000..ec3b2814a4eb --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/atomic.h @@ -0,0 +1,10 @@ +/* $OpenBSD: atomic.h,v 1.1 2013/09/04 14:38:26 patrick Exp $ */ + +/* Public Domain */ + +#ifndef _MACHINE_ATOMIC_H_ +#define _MACHINE_ATOMIC_H_ + +#include + +#endif /* _MACHINE_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/bootconfig.h b/lib/libc/include/arm-openbsd-eabi/machine/bootconfig.h new file mode 100644 index 000000000000..c806b7a421c2 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/bootconfig.h @@ -0,0 +1,70 @@ +/* $OpenBSD: bootconfig.h,v 1.2 2019/05/06 03:34:43 mlarkin Exp $ */ +/* $NetBSD: bootconfig.h,v 1.2 2001/06/21 22:08:28 chris Exp $ */ + +/* + * Copyright (c) 1994 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mark Brinicombe + * for the NetBSD Project. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR 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. + * + * boot configuration structures + * + * Created : 12/09/94 + * + * Based on kate/boot/bootconfig.h + */ + +#if defined(_KERNEL) || defined(_STANDALONE) + +typedef struct _PhysMem { + u_int address; + u_int pages; +} PhysMem; + +#define DRAM_BLOCKS 2 +#define MAX_BOOT_STRING 255 + +typedef struct _BootConfig { + PhysMem dram[DRAM_BLOCKS]; + u_int dramblocks; + char bootstring[MAX_BOOT_STRING]; +} BootConfig; + +extern BootConfig bootconfig; + +#endif /* _KERNEL || _STANDALONE */ +#if defined(_KERNEL) +extern char *boot_args; +extern char *boot_file; +#endif /* _KERNEL */ + +/* End of bootconfig.h */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/bus.h b/lib/libc/include/arm-openbsd-eabi/machine/bus.h new file mode 100644 index 000000000000..0a27ab9dd430 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/bus.h @@ -0,0 +1,4 @@ +/* $OpenBSD: bus.h,v 1.1 2013/09/04 14:38:26 patrick Exp $ */ +/* $NetBSD: bus.h,v 1.3 2001/11/25 15:55:55 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/cdefs.h b/lib/libc/include/arm-openbsd-eabi/machine/cdefs.h new file mode 100644 index 000000000000..8ca96399b0ea --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/cdefs.h @@ -0,0 +1,3 @@ +/* $OpenBSD: cdefs.h,v 1.1 2013/09/04 14:38:26 patrick Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/conf.h b/lib/libc/include/arm-openbsd-eabi/machine/conf.h new file mode 100644 index 000000000000..514e8d026224 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/conf.h @@ -0,0 +1,10 @@ +/* $OpenBSD: conf.h,v 1.2 2025/07/16 03:01:53 jsg Exp $ */ +/* $NetBSD: conf.h,v 1.8 2002/02/10 12:26:03 chris Exp $ */ + +#ifndef _MACHINE_CONF_H_ +#define _MACHINE_CONF_H_ + +#include +#include + +#endif /* _MACHINE_CONF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/cpu.h b/lib/libc/include/arm-openbsd-eabi/machine/cpu.h new file mode 100644 index 000000000000..e9e7ffb3c6e2 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/cpu.h @@ -0,0 +1,4 @@ +/* $OpenBSD: cpu.h,v 1.1 2013/09/04 14:38:26 patrick Exp $ */ +/* $NetBSD: cpu.h,v 1.3 2001/11/25 15:55:55 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/cpufunc.h b/lib/libc/include/arm-openbsd-eabi/machine/cpufunc.h new file mode 100644 index 000000000000..83545e6386ea --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/cpufunc.h @@ -0,0 +1,16 @@ +/* $OpenBSD: cpufunc.h,v 1.1 2020/11/29 12:54:36 kettenis Exp $ */ + +/* Public Domain */ + +#ifndef _MACHINE_CPUFUNC_H_ +#define _MACHINE_CPUFUNC_H_ + +#include + +#ifdef _KERNEL + +register_t smc_call(register_t, register_t, register_t, register_t); + +#endif /* _KERNEL */ + +#endif /* _MACHINE_CPUFUNC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/db_machdep.h b/lib/libc/include/arm-openbsd-eabi/machine/db_machdep.h new file mode 100644 index 000000000000..0142ddba5ed3 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/db_machdep.h @@ -0,0 +1,4 @@ +/* $OpenBSD: db_machdep.h,v 1.1 2013/09/04 14:38:26 patrick Exp $ */ +/* $NetBSD: db_machdep.h,v 1.3 2001/11/25 15:55:55 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/disklabel.h b/lib/libc/include/arm-openbsd-eabi/machine/disklabel.h new file mode 100644 index 000000000000..bb72317025cb --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/disklabel.h @@ -0,0 +1,3 @@ +/* $OpenBSD: disklabel.h,v 1.1 2013/09/04 14:38:27 patrick Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/elf.h b/lib/libc/include/arm-openbsd-eabi/machine/elf.h new file mode 100644 index 000000000000..adbf226bf24e --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/elf.h @@ -0,0 +1,3 @@ +/* $OpenBSD: elf.h,v 1.1 2024/07/14 19:33:59 miod Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/endian.h b/lib/libc/include/arm-openbsd-eabi/machine/endian.h new file mode 100644 index 000000000000..a38e0819d637 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/endian.h @@ -0,0 +1,4 @@ +/* $OpenBSD: endian.h,v 1.1 2013/09/04 14:38:27 patrick Exp $ */ +/* $NetBSD: endian.h,v 1.3 2001/11/25 15:55:56 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/exec.h b/lib/libc/include/arm-openbsd-eabi/machine/exec.h new file mode 100644 index 000000000000..6bb7f50e7ef1 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/exec.h @@ -0,0 +1,3 @@ +/* $OpenBSD: exec.h,v 1.1 2013/09/04 14:38:27 patrick Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/fdt.h b/lib/libc/include/arm-openbsd-eabi/machine/fdt.h new file mode 100644 index 000000000000..386a6d31cf01 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/fdt.h @@ -0,0 +1,3 @@ +/* $OpenBSD: fdt.h,v 1.1 2016/05/02 08:15:55 patrick Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/fenv.h b/lib/libc/include/arm-openbsd-eabi/machine/fenv.h new file mode 100644 index 000000000000..1f648e10050b --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/fenv.h @@ -0,0 +1,3 @@ +/* $OpenBSD: fenv.h,v 1.1 2013/09/04 14:38:27 patrick Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/frame.h b/lib/libc/include/arm-openbsd-eabi/machine/frame.h new file mode 100644 index 000000000000..9ca41597feb2 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/frame.h @@ -0,0 +1,4 @@ +/* $OpenBSD: frame.h,v 1.1 2013/09/04 14:38:27 patrick Exp $ */ +/* $NetBSD: frame.h,v 1.1 2001/06/08 22:23:00 chris Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/ieee.h b/lib/libc/include/arm-openbsd-eabi/machine/ieee.h new file mode 100644 index 000000000000..cbd95dc298c8 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/ieee.h @@ -0,0 +1,4 @@ +/* $OpenBSD: ieee.h,v 1.1 2013/09/04 14:38:27 patrick Exp $ */ +/* $NetBSD: ieee.h,v 1.3 2001/11/25 15:55:56 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/ieeefp.h b/lib/libc/include/arm-openbsd-eabi/machine/ieeefp.h new file mode 100644 index 000000000000..f4c270c6903a --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/ieeefp.h @@ -0,0 +1,4 @@ +/* $OpenBSD: ieeefp.h,v 1.1 2013/09/04 14:38:27 patrick Exp $ */ +/* $NetBSD: ieeefp.h,v 1.3 2001/11/25 15:55:56 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/intr.h b/lib/libc/include/arm-openbsd-eabi/machine/intr.h new file mode 100644 index 000000000000..0f597a3f152d --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/intr.h @@ -0,0 +1,229 @@ +/* $OpenBSD: intr.h,v 1.16 2025/05/10 10:11:02 visa Exp $ */ +/* $NetBSD: intr.h,v 1.12 2003/06/16 20:00:59 thorpej Exp $ */ + +/* + * Copyright (c) 2001, 2003 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_INTR_H_ +#define _MACHINE_INTR_H_ + +#ifdef _KERNEL + +/* Interrupt priority `levels'; not mutually exclusive. */ +#define IPL_NONE 0 /* nothing */ +#define IPL_SOFTCLOCK 2 /* soft clock interrupts */ +#define IPL_SOFTNET 3 /* soft network interrupts */ +#define IPL_SOFTTTY 4 /* soft terminal interrupts */ +#define IPL_BIO 5 /* block I/O */ +#define IPL_NET 6 /* network */ +#define IPL_TTY 7 /* terminal */ +#define IPL_VM 8 /* memory allocation */ +#define IPL_AUDIO 9 /* audio */ +#define IPL_CLOCK 10 /* clock */ +#define IPL_SCHED IPL_CLOCK +#define IPL_STATCLOCK IPL_CLOCK +#define IPL_HIGH 11 /* everything */ +#define IPL_IPI 12 /* interprocessor interrupt */ +#define NIPL 13 /* number of levels */ + +#define IPL_MPFLOOR IPL_TTY +/* Interrupt priority 'flags'. */ +#define IPL_IRQMASK 0xf /* priority only */ +#define IPL_FLAGMASK 0xf00 /* flags only*/ +#define IPL_MPSAFE 0x100 /* 'mpsafe' interrupt, no kernel lock */ + +/* Interrupt sharing types. */ +#define IST_NONE 0 /* none */ +#define IST_PULSE 1 /* pulsed */ +#define IST_EDGE 2 /* edge-triggered */ +#define IST_LEVEL 3 /* level-triggered */ + +#define IST_LEVEL_LOW IST_LEVEL +#define IST_LEVEL_HIGH 4 +#define IST_EDGE_FALLING IST_EDGE +#define IST_EDGE_RISING 5 +#define IST_EDGE_BOTH 6 + +#define __USE_MI_SOFTINTR + +#include + +#ifndef _LOCORE +#include + +struct cpu_info; + +int splraise(int); +int spllower(int); +void splx(int); + +void arm_do_pending_intr(int); +void arm_set_intr_handler(int (*raise)(int), int (*lower)(int), + void (*x)(int), void (*setipl)(int), + void *(*intr_establish)(int irqno, int level, struct cpu_info *ci, + int (*func)(void *), void *cookie, char *name), + void (*intr_disestablish)(void *cookie), + const char *(*intr_string)(void *cookie), + void (*intr_handle)(void *)); + +struct arm_intr_func { + int (*raise)(int); + int (*lower)(int); + void (*x)(int); + void (*setipl)(int); + void *(*intr_establish)(int irqno, int level, struct cpu_info *, + int (*func)(void *), void *cookie, char *name); + void (*intr_disestablish)(void *cookie); + const char *(*intr_string)(void *cookie); +}; + +extern struct arm_intr_func arm_intr_func; + +#define splraise(cpl) (arm_intr_func.raise(cpl)) +#define _splraise(cpl) (arm_intr_func.raise(cpl)) +#define spllower(cpl) (arm_intr_func.lower(cpl)) +#define splx(cpl) (arm_intr_func.x(cpl)) + +#define splhigh() splraise(IPL_HIGH) +#define splsoftclock() splraise(IPL_SOFTCLOCK) +#define splsoftnet() splraise(IPL_SOFTNET) +#define splbio() splraise(IPL_BIO) +#define splnet() splraise(IPL_NET) +#define spltty() splraise(IPL_TTY) +#define splvm() splraise(IPL_VM) +#define splaudio() splraise(IPL_AUDIO) +#define splclock() splraise(IPL_CLOCK) +#define splstatclock() splraise(IPL_STATCLOCK) + +#define spl0() spllower(IPL_NONE) + +#define splsched() splhigh() + +void intr_barrier(void *); + +void arm_init_smask(void); /* XXX */ +extern uint32_t arm_smask[NIPL]; +void arm_setsoftintr(int si); + +#define softintr arm_setsoftintr + +void *arm_intr_establish(int irqno, int level, int (*func)(void *), + void *cookie, char *name); +void arm_intr_disestablish(void *cookie); +const char *arm_intr_string(void *cookie); + +/* XXX - this is probably the wrong location for this */ +void arm_clock_register(void (*)(void), void (*)(u_int), void (*)(int), + void (*)(void)); + +struct interrupt_controller { + int ic_node; + void *ic_cookie; + void *(*ic_establish)(void *, int *, int, struct cpu_info *, + int (*)(void *), void *, char *); + void *(*ic_establish_msi)(void *, uint64_t *, uint64_t *, int, + struct cpu_info *, int (*)(void *), void *, char *); + void (*ic_disestablish)(void *); + void (*ic_enable)(void *); + void (*ic_disable)(void *); + void (*ic_route)(void *, int, struct cpu_info *); + void (*ic_cpu_enable)(void); + void (*ic_barrier)(void *); + + LIST_ENTRY(interrupt_controller) ic_list; + uint32_t ic_phandle; + uint32_t ic_cells; +}; + +void arm_intr_init_fdt(void); +void arm_intr_register_fdt(struct interrupt_controller *); +void *arm_intr_establish_fdt(int, int, int (*)(void *), + void *, char *); +void *arm_intr_establish_fdt_cpu(int, int, struct cpu_info *, + int (*)(void *), void *, char *); +void *arm_intr_establish_fdt_idx(int, int, int, int (*)(void *), + void *, char *); +void *arm_intr_establish_fdt_idx_cpu(int, int, int, struct cpu_info *, + int (*)(void *), void *, char *); +void *arm_intr_establish_fdt_imap(int, int *, int, int, int (*)(void *), + void *, char *); +void *arm_intr_establish_fdt_imap_cpu(int, int *, int, int, + struct cpu_info *, int (*)(void *), void *, char *); +void *arm_intr_establish_fdt_msi(int, uint64_t *, uint64_t *, int, + int (*)(void *), void *, char *); +void *arm_intr_establish_fdt_msi_cpu(int, uint64_t *, uint64_t *, int, + struct cpu_info *, int (*)(void *), void *, char *); +void arm_intr_disestablish_fdt(void *); +void arm_intr_enable(void *); +void arm_intr_disable(void *); +void arm_intr_route(void *, int, struct cpu_info *); +void arm_intr_cpu_enable(void); + +void *arm_intr_parent_establish_fdt(void *, int *, int, + struct cpu_info *ci, int (*)(void *), void *, char *); +void arm_intr_parent_disestablish_fdt(void *); + +void arm_send_ipi(struct cpu_info *, int); +extern void (*intr_send_ipi_func)(struct cpu_info *, int); + +#define ARM_IPI_NOP 0 +#define ARM_IPI_DDB 1 + +#ifdef DIAGNOSTIC +/* + * Although this function is implemented in MI code, it must be in this MD + * header because we don't want this header to include MI includes. + */ +void splassert_fail(int, int, const char *); +extern int splassert_ctl; +void arm_splassert_check(int, const char *); +#define splassert(__wantipl) do { \ + if (splassert_ctl > 0) { \ + arm_splassert_check(__wantipl, __func__); \ + } \ +} while (0) +#define splsoftassert(wantipl) splassert(wantipl) +#else +#define splassert(wantipl) do { /* nothing */ } while (0) +#define splsoftassert(wantipl) do { /* nothing */ } while (0) +#endif + +#endif /* ! _LOCORE */ + +#define ARM_IRQ_HANDLER arm_intr + +#endif /* _KERNEL */ + +#endif /* _MACHINE_INTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/limits.h b/lib/libc/include/arm-openbsd-eabi/machine/limits.h new file mode 100644 index 000000000000..59a9c2820add --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/limits.h @@ -0,0 +1,4 @@ +/* $OpenBSD: limits.h,v 1.1 2013/09/04 14:38:27 patrick Exp $ */ +/* $NetBSD: limits.h,v 1.3 2001/11/25 15:55:57 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/loadfile_machdep.h b/lib/libc/include/arm-openbsd-eabi/machine/loadfile_machdep.h new file mode 100644 index 000000000000..d4af12ff27ff --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/loadfile_machdep.h @@ -0,0 +1,53 @@ +/* $OpenBSD: loadfile_machdep.h,v 1.5 2019/04/10 04:17:34 deraadt Exp $ */ +/* $NetBSD: loadfile_machdep.h,v 1.1 1999/04/29 03:17:12 tsubai Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define BOOT_ELF +#define ELFSIZE 32 + +#define LOAD_KERNEL LOAD_ALL +#define COUNT_KERNEL COUNT_ALL + +extern u_long efi_loadaddr; +#define LOADADDR(a) (((((u_long)(a)) + offset)&0xfffffff) + \ + efi_loadaddr) +#define ALIGNENTRY(a) ((u_long)(a)) +#define READ(f, b, c) read((f), (void *)LOADADDR(b), (c)) +#define BCOPY(s, d, c) memcpy((void *)LOADADDR(d), (void *)(s), (c)) +#define BZERO(d, c) memset((void *)LOADADDR(d), 0, (c)) +#define WARN(a) (void)(printf a, \ + printf((errno ? ": %s\n" : "\n"), \ + strerror(errno))) +#define PROGRESS(a) (void) printf a +#define ALLOC(a) alloc(a) +#define FREE(a, b) free(a, b) + +void run_loadfile(uint64_t *, int); \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/machine_reg.h b/lib/libc/include/arm-openbsd-eabi/machine/machine_reg.h new file mode 100644 index 000000000000..ef8753801289 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/machine_reg.h @@ -0,0 +1,57 @@ +/* $OpenBSD: machine_reg.h,v 1.3 2019/05/06 03:34:43 mlarkin Exp $ */ + +/* + * Copyright (c) 2002, 2003 Genetec Corporation. All rights reserved. + * Written by Hiroyuki Bessho for Genetec Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of Genetec Corporation may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``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 GENETEC CORPORATION + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef _MACHINE_REG_H +#define _MACHINE_REG_H + +/* + * Logical mapping for onboard/integrated peripherals + */ +#define MACHINE_IO_AREA_VBASE 0xfd000000 +#define MACHINE_GPIO_VBASE 0xfd000000 +#define MACHINE_CLKMAN_VBASE 0xfd100000 +#define MACHINE_INTCTL_VBASE 0xfd200000 +#define MACHINE_AGPIO_VBASE 0xfd300000 +#define MACHINE_VBASE_FREE 0xfd400000 +/* FFUART and/or BTUART are mapped to this area when + used for console */ + +#define ioreg_read(a) (*(volatile unsigned *)(a)) +#define ioreg_write(a,v) (*(volatile unsigned *)(a)=(v)) + +#define ioreg16_read(a) (*(volatile uint16_t *)(a)) +#define ioreg16_write(a,v) (*(volatile uint16_t *)(a)=(v)) + +#define ioreg8_read(a) (*(volatile uint8_t *)(a)) +#define ioreg8_write(a,v) (*(volatile uint8_t *)(a)=(v)) + +#endif /* _MACHINE_REG_H */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/mplock.h b/lib/libc/include/arm-openbsd-eabi/machine/mplock.h new file mode 100644 index 000000000000..d4ecdcd49fab --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/mplock.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mplock.h,v 1.1 2018/08/06 18:39:13 kettenis Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/mutex.h b/lib/libc/include/arm-openbsd-eabi/machine/mutex.h new file mode 100644 index 000000000000..1af94436f5a7 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/mutex.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mutex.h,v 1.1 2013/09/04 14:38:28 patrick Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/openpromio.h b/lib/libc/include/arm-openbsd-eabi/machine/openpromio.h new file mode 100644 index 000000000000..39f68f71a594 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/openpromio.h @@ -0,0 +1,3 @@ +/* $OpenBSD: openpromio.h,v 1.1 2016/05/21 21:24:36 kettenis Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/param.h b/lib/libc/include/arm-openbsd-eabi/machine/param.h new file mode 100644 index 000000000000..72d453ef46ba --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/param.h @@ -0,0 +1,51 @@ +/* $OpenBSD: param.h,v 1.3 2018/08/09 12:19:32 patrick Exp $ */ + +/* + * Copyright (c) 1994,1995 Mark Brinicombe. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the RiscBSD team. + * 4. The name "RiscBSD" nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RISCBSD ``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 RISCBSD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ + +#include + +#define _MACHINE armv7 +#define MACHINE "armv7" + +#ifndef MSGBUFSIZE +#define MSGBUFSIZE (8 * PAGE_SIZE) +#endif + +#ifdef _KERNEL +#define __HAVE_FDT +#endif + +#endif /* _MACHINE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/pcb.h b/lib/libc/include/arm-openbsd-eabi/machine/pcb.h new file mode 100644 index 000000000000..d2b73c6db576 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/pcb.h @@ -0,0 +1,4 @@ +/* $OpenBSD: pcb.h,v 1.1 2013/09/04 14:38:28 patrick Exp $ */ +/* $NetBSD: pcb.h,v 1.3 2001/11/25 15:55:57 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/pci_machdep.h b/lib/libc/include/arm-openbsd-eabi/machine/pci_machdep.h new file mode 100644 index 000000000000..54442a800530 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/pci_machdep.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pci_machdep.h,v 1.1 2018/07/09 09:53:06 patrick Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/pmap.h b/lib/libc/include/arm-openbsd-eabi/machine/pmap.h new file mode 100644 index 000000000000..bc631302ef85 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/pmap.h @@ -0,0 +1,4 @@ +/* $OpenBSD: pmap.h,v 1.1 2013/09/04 14:38:28 patrick Exp $ */ +/* $NetBSD: pmap.h,v 1.2 2001/11/23 17:29:01 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/proc.h b/lib/libc/include/arm-openbsd-eabi/machine/proc.h new file mode 100644 index 000000000000..d92b1e2712db --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/proc.h @@ -0,0 +1,4 @@ +/* $OpenBSD: proc.h,v 1.1 2013/09/04 14:38:28 patrick Exp $ */ +/* $NetBSD: proc.h,v 1.3 2001/11/25 15:55:57 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/profile.h b/lib/libc/include/arm-openbsd-eabi/machine/profile.h new file mode 100644 index 000000000000..72aa69fcf300 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/profile.h @@ -0,0 +1,4 @@ +/* $OpenBSD: profile.h,v 1.1 2013/09/04 14:38:28 patrick Exp $ */ +/* $NetBSD: profile.h,v 1.3 2001/11/25 15:55:57 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/ptrace.h b/lib/libc/include/arm-openbsd-eabi/machine/ptrace.h new file mode 100644 index 000000000000..fda3e95619c4 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/ptrace.h @@ -0,0 +1,4 @@ +/* $OpenBSD: ptrace.h,v 1.1 2013/09/04 14:38:28 patrick Exp $ */ +/* $NetBSD: ptrace.h,v 1.3 2001/11/25 15:55:58 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/reg.h b/lib/libc/include/arm-openbsd-eabi/machine/reg.h new file mode 100644 index 000000000000..8bee9a0ffcfa --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/reg.h @@ -0,0 +1,4 @@ +/* $OpenBSD: reg.h,v 1.1 2013/09/04 14:38:28 patrick Exp $ */ +/* $NetBSD: reg.h,v 1.3 2001/11/25 15:55:58 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/reloc.h b/lib/libc/include/arm-openbsd-eabi/machine/reloc.h new file mode 100644 index 000000000000..d4311b2f1410 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/reloc.h @@ -0,0 +1,2 @@ +/* $OpenBSD: reloc.h,v 1.1 2013/09/04 14:38:29 patrick Exp $ */ +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/setjmp.h b/lib/libc/include/arm-openbsd-eabi/machine/setjmp.h new file mode 100644 index 000000000000..5125b28bd363 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/setjmp.h @@ -0,0 +1,4 @@ +/* $OpenBSD: setjmp.h,v 1.1 2013/09/04 14:38:29 patrick Exp $ */ +/* $NetBSD: setjmp.h,v 1.3 2001/11/25 15:55:58 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/signal.h b/lib/libc/include/arm-openbsd-eabi/machine/signal.h new file mode 100644 index 000000000000..0fc0632217b8 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/signal.h @@ -0,0 +1,4 @@ +/* $OpenBSD: signal.h,v 1.1 2013/09/04 14:38:29 patrick Exp $ */ +/* $NetBSD: signal.h,v 1.3 2001/11/25 15:55:58 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/simplebusvar.h b/lib/libc/include/arm-openbsd-eabi/machine/simplebusvar.h new file mode 100644 index 000000000000..0620d804493f --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/simplebusvar.h @@ -0,0 +1,3 @@ +/* $OpenBSD: simplebusvar.h,v 1.1 2023/09/22 01:10:43 jsg Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/spinlock.h b/lib/libc/include/arm-openbsd-eabi/machine/spinlock.h new file mode 100644 index 000000000000..675d503f4362 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/spinlock.h @@ -0,0 +1,3 @@ +/* $OpenBSD: spinlock.h,v 1.2 2017/01/05 16:52:42 patrick Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/sysarch.h b/lib/libc/include/arm-openbsd-eabi/machine/sysarch.h new file mode 100644 index 000000000000..4a65320d7030 --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/sysarch.h @@ -0,0 +1,4 @@ +/* $OpenBSD: sysarch.h,v 1.1 2013/09/04 14:38:29 patrick Exp $ */ +/* $NetBSD: sysarch.h,v 1.3 2001/11/25 15:55:58 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/tcb.h b/lib/libc/include/arm-openbsd-eabi/machine/tcb.h new file mode 100644 index 000000000000..a5a3f7799f2c --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/tcb.h @@ -0,0 +1,3 @@ +/* $OpenBSD: tcb.h,v 1.1 2013/09/04 14:38:29 patrick Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/trap.h b/lib/libc/include/arm-openbsd-eabi/machine/trap.h new file mode 100644 index 000000000000..2904fcc7b59d --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/trap.h @@ -0,0 +1,4 @@ +/* $OpenBSD: trap.h,v 1.1 2013/09/04 14:38:29 patrick Exp $ */ +/* $NetBSD: trap.h,v 1.3 2001/11/25 15:55:58 thorpej Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/arm-openbsd-eabi/machine/vmparam.h b/lib/libc/include/arm-openbsd-eabi/machine/vmparam.h new file mode 100644 index 000000000000..fb4d068a386a --- /dev/null +++ b/lib/libc/include/arm-openbsd-eabi/machine/vmparam.h @@ -0,0 +1,98 @@ +/* $OpenBSD: vmparam.h,v 1.8 2023/11/12 16:37:28 kettenis Exp $ */ +/* $NetBSD: vmparam.h,v 1.23 2003/05/22 05:47:07 thorpej Exp $ */ + +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_VMPARAM_H_ +#define _MACHINE_VMPARAM_H_ + +#define ARM_KERNEL_BASE 0xc0000000U + +/* Allow armv7 to have bigger limits than generic arm, allow user to override */ +#ifndef MAXDSIZ +#define MAXDSIZ (2UL*1024*1024*1024) /* max data size */ +#endif +#ifndef BRKSIZ +#define BRKSIZ MAXDSIZ /* heap gap size */ +#endif +#ifndef DFLSSIZ +#define DFLSSIZ (4*1024*1024) /* initial stack size limit */ +#endif +#ifndef MAXSSIZ +#define MAXSSIZ (32*1024*1024) /* max stack size */ +#endif + +#include + +#ifdef _KERNEL +/* + * Address space constants + */ + +/* + * The line between user space and kernel space + * Mappings >= KERNEL_BASE are constant across all processes + */ +#define KERNEL_BASE ARM_KERNEL_BASE + +#define VM_KERNEL_SPACE_SIZE 0x20000000 + +/* + * Override the default pager_map size, there's not enough KVA. + */ +#define PAGER_MAP_SIZE (4 * 1024 * 1024) + +/* + * Size of User Raw I/O map + */ + +#define USRIOSIZE 300 + +/* virtual sizes (bytes) for various kernel submaps */ + +#define VM_PHYS_SIZE (USRIOSIZE*PAGE_SIZE) + +/* + * max number of non-contig chunks of physical RAM you can have + */ + +#define VM_PHYSSEG_MAX 32 +#define VM_PHYSSEG_STRAT VM_PSTRAT_BSEARCH + +/* + * this indicates that we can't add RAM to the VM system after the + * vm system is init'd. + */ + +#define VM_PHYSSEG_NOADD + +#endif /* _KERNEL */ + +#endif /* _MACHINE_VMPARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/_ctype.h b/lib/libc/include/generic-freebsd/_ctype.h index c7142800d85e..478eebd89ae0 100644 --- a/lib/libc/include/generic-freebsd/_ctype.h +++ b/lib/libc/include/generic-freebsd/_ctype.h @@ -35,8 +35,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * From @(#)ctype.h 8.4 (Berkeley) 1/21/94 * From FreeBSD: src/include/ctype.h,v 1.27 2004/06/23 07:11:39 tjr Exp */ diff --git a/lib/libc/include/generic-freebsd/_libsys.h b/lib/libc/include/generic-freebsd/_libsys.h new file mode 100644 index 000000000000..1183efab7f20 --- /dev/null +++ b/lib/libc/include/generic-freebsd/_libsys.h @@ -0,0 +1,881 @@ +/* + * Public system call stubs provided by libsys. + * + * Do not use directly, include instead. + * + * DO NOT EDIT-- this file is automatically @generated. + */ + +#ifndef __LIBSYS_H_ +#define __LIBSYS_H_ + +#include +#include +#include +#include +#include +#include /* for mcontext_t */ +#include +#include + +struct __siginfo; +struct __ucontext; +struct __wrusage; +struct acl; +struct aiocb; +struct auditinfo; +struct auditinfo_addr; +struct ffclock_estimate; +struct fhandle; +struct iovec; +struct itimerspec; +struct itimerval; +struct jail; +struct kevent; +struct kld_file_stat; +struct mac; +struct module_stat; +struct mq_attr; +struct msghdr; +struct msqid_ds; +struct ntptimeval; +struct pollfd; +struct rlimit; +struct rtprio; +struct rusage; +struct sched_param; +struct sctp_sndrcvinfo; +struct sembuf; +struct setcred; +struct sf_hdtr; +struct shmid_ds; +struct sigaction; +struct sigaltstack; +struct sigevent; +struct sockaddr; +struct spacectl_range; +struct stat; +struct statfs; +struct thr_param; +struct timespec; +struct timeval; +struct timex; +struct timezone; +struct uuid; +union semun; + +__BEGIN_DECLS +typedef void (__sys__exit_t)(int); +typedef int (__sys_fork_t)(void); +typedef ssize_t (__sys_read_t)(int, void *, size_t); +typedef ssize_t (__sys_write_t)(int, const void *, size_t); +typedef int (__sys_open_t)(const char *, int, mode_t); +typedef int (__sys_close_t)(int); +typedef int (__sys_wait4_t)(int, int *, int, struct rusage *); +typedef int (__sys_link_t)(const char *, const char *); +typedef int (__sys_unlink_t)(const char *); +typedef int (__sys_chdir_t)(const char *); +typedef int (__sys_fchdir_t)(int); +typedef int (__sys_chmod_t)(const char *, mode_t); +typedef int (__sys_chown_t)(const char *, int, int); +typedef void * (__sys_break_t)(char *); +typedef pid_t (__sys_getpid_t)(void); +typedef int (__sys_mount_t)(const char *, const char *, int, void *); +typedef int (__sys_unmount_t)(const char *, int); +typedef int (__sys_setuid_t)(uid_t); +typedef uid_t (__sys_getuid_t)(void); +typedef uid_t (__sys_geteuid_t)(void); +typedef int (__sys_ptrace_t)(int, pid_t, caddr_t, int); +typedef ssize_t (__sys_recvmsg_t)(int, struct msghdr *, int); +typedef ssize_t (__sys_sendmsg_t)(int, const struct msghdr *, int); +typedef ssize_t (__sys_recvfrom_t)(int, void *, size_t, int, struct sockaddr *, __socklen_t *); +typedef int (__sys_accept_t)(int, struct sockaddr *, __socklen_t *); +typedef int (__sys_getpeername_t)(int, struct sockaddr *, __socklen_t *); +typedef int (__sys_getsockname_t)(int, struct sockaddr *, __socklen_t *); +typedef int (__sys_access_t)(const char *, int); +typedef int (__sys_chflags_t)(const char *, u_long); +typedef int (__sys_fchflags_t)(int, u_long); +typedef int (__sys_sync_t)(void); +typedef int (__sys_kill_t)(int, int); +typedef pid_t (__sys_getppid_t)(void); +typedef int (__sys_dup_t)(u_int); +typedef gid_t (__sys_getegid_t)(void); +typedef int (__sys_profil_t)(char *, size_t, size_t, u_int); +typedef int (__sys_ktrace_t)(const char *, int, int, int); +typedef gid_t (__sys_getgid_t)(void); +typedef int (__sys_getlogin_t)(char *, u_int); +typedef int (__sys_setlogin_t)(const char *); +typedef int (__sys_acct_t)(const char *); +typedef int (__sys_sigaltstack_t)(const struct sigaltstack *, struct sigaltstack *); +typedef int (__sys_ioctl_t)(int, u_long, char *); +typedef int (__sys_reboot_t)(int); +typedef int (__sys_revoke_t)(const char *); +typedef int (__sys_symlink_t)(const char *, const char *); +typedef ssize_t (__sys_readlink_t)(const char *, char *, size_t); +typedef int (__sys_execve_t)(const char *, char **, char **); +typedef mode_t (__sys_umask_t)(mode_t); +typedef int (__sys_chroot_t)(const char *); +typedef int (__sys_msync_t)(void *, size_t, int); +typedef int (__sys_vfork_t)(void); +typedef int (__sys_munmap_t)(void *, size_t); +typedef int (__sys_mprotect_t)(void *, size_t, int); +typedef int (__sys_madvise_t)(void *, size_t, int); +typedef int (__sys_mincore_t)(const void *, size_t, char *); +typedef int (__sys_getpgrp_t)(void); +typedef int (__sys_setpgid_t)(int, int); +typedef int (__sys_setitimer_t)(int, const struct itimerval *, struct itimerval *); +typedef int (__sys_swapon_t)(const char *); +typedef int (__sys_getitimer_t)(int, struct itimerval *); +typedef int (__sys_getdtablesize_t)(void); +typedef int (__sys_dup2_t)(u_int, u_int); +typedef int (__sys_fcntl_t)(int, int, intptr_t); +typedef int (__sys_select_t)(int, fd_set *, fd_set *, fd_set *, struct timeval *); +typedef int (__sys_fsync_t)(int); +typedef int (__sys_setpriority_t)(int, int, int); +typedef int (__sys_socket_t)(int, int, int); +typedef int (__sys_connect_t)(int, const struct sockaddr *, __socklen_t); +typedef int (__sys_getpriority_t)(int, int); +typedef int (__sys_bind_t)(int, const struct sockaddr *, __socklen_t); +typedef int (__sys_setsockopt_t)(int, int, int, const void *, __socklen_t); +typedef int (__sys_listen_t)(int, int); +typedef int (__sys_gettimeofday_t)(struct timeval *, struct timezone *); +typedef int (__sys_getrusage_t)(int, struct rusage *); +typedef int (__sys_getsockopt_t)(int, int, int, void *, __socklen_t *); +typedef ssize_t (__sys_readv_t)(int, const struct iovec *, u_int); +typedef ssize_t (__sys_writev_t)(int, const struct iovec *, u_int); +typedef int (__sys_settimeofday_t)(const struct timeval *, const struct timezone *); +typedef int (__sys_fchown_t)(int, int, int); +typedef int (__sys_fchmod_t)(int, mode_t); +typedef int (__sys_setreuid_t)(int, int); +typedef int (__sys_setregid_t)(int, int); +typedef int (__sys_rename_t)(const char *, const char *); +typedef int (__sys_flock_t)(int, int); +typedef int (__sys_mkfifo_t)(const char *, mode_t); +typedef ssize_t (__sys_sendto_t)(int, const void *, size_t, int, const struct sockaddr *, __socklen_t); +typedef int (__sys_shutdown_t)(int, int); +typedef int (__sys_socketpair_t)(int, int, int, int *); +typedef int (__sys_mkdir_t)(const char *, mode_t); +typedef int (__sys_rmdir_t)(const char *); +typedef int (__sys_utimes_t)(const char *, const struct timeval *); +typedef int (__sys_adjtime_t)(const struct timeval *, struct timeval *); +typedef int (__sys_setsid_t)(void); +typedef int (__sys_quotactl_t)(const char *, int, int, void *); +typedef int (__sys_nlm_syscall_t)(int, int, int, char **); +typedef int (__sys_nfssvc_t)(int, void *); +typedef int (__sys_lgetfh_t)(const char *, struct fhandle *); +typedef int (__sys_getfh_t)(const char *, struct fhandle *); +typedef int (__sys_sysarch_t)(int, char *); +typedef int (__sys_rtprio_t)(int, pid_t, struct rtprio *); +typedef int (__sys_semsys_t)(int, int, int, int, int); +typedef int (__sys_msgsys_t)(int, int, int, int, int, int); +typedef int (__sys_shmsys_t)(int, int, int, int); +typedef int (__sys_setfib_t)(int); +typedef int (__sys_ntp_adjtime_t)(struct timex *); +typedef int (__sys_setgid_t)(gid_t); +typedef int (__sys_setegid_t)(gid_t); +typedef int (__sys_seteuid_t)(uid_t); +typedef int (__sys_pathconf_t)(const char *, int); +typedef int (__sys_fpathconf_t)(int, int); +typedef int (__sys_getrlimit_t)(u_int, struct rlimit *); +typedef int (__sys_setrlimit_t)(u_int, struct rlimit *); +typedef int (__sys___sysctl_t)(const int *, u_int, void *, size_t *, const void *, size_t); +typedef int (__sys_mlock_t)(const void *, size_t); +typedef int (__sys_munlock_t)(const void *, size_t); +typedef int (__sys_undelete_t)(const char *); +typedef int (__sys_futimes_t)(int, const struct timeval *); +typedef int (__sys_getpgid_t)(pid_t); +typedef int (__sys_poll_t)(struct pollfd *, u_int, int); +typedef int (__sys_semget_t)(key_t, int, int); +typedef int (__sys_semop_t)(int, struct sembuf *, size_t); +typedef int (__sys_msgget_t)(key_t, int); +typedef int (__sys_msgsnd_t)(int, const void *, size_t, int); +typedef ssize_t (__sys_msgrcv_t)(int, void *, size_t, long, int); +typedef void * (__sys_shmat_t)(int, const void *, int); +typedef int (__sys_shmdt_t)(const void *); +typedef int (__sys_shmget_t)(key_t, size_t, int); +typedef int (__sys_clock_gettime_t)(clockid_t, struct timespec *); +typedef int (__sys_clock_settime_t)(clockid_t, const struct timespec *); +typedef int (__sys_clock_getres_t)(clockid_t, struct timespec *); +typedef int (__sys_ktimer_create_t)(clockid_t, struct sigevent *, int *); +typedef int (__sys_ktimer_delete_t)(int); +typedef int (__sys_ktimer_settime_t)(int, int, const struct itimerspec *, struct itimerspec *); +typedef int (__sys_ktimer_gettime_t)(int, struct itimerspec *); +typedef int (__sys_ktimer_getoverrun_t)(int); +typedef int (__sys_nanosleep_t)(const struct timespec *, struct timespec *); +typedef int (__sys_ffclock_getcounter_t)(ffcounter *); +typedef int (__sys_ffclock_setestimate_t)(struct ffclock_estimate *); +typedef int (__sys_ffclock_getestimate_t)(struct ffclock_estimate *); +typedef int (__sys_clock_nanosleep_t)(clockid_t, int, const struct timespec *, struct timespec *); +typedef int (__sys_clock_getcpuclockid2_t)(id_t, int, clockid_t *); +typedef int (__sys_ntp_gettime_t)(struct ntptimeval *); +typedef int (__sys_minherit_t)(void *, size_t, int); +typedef int (__sys_rfork_t)(int); +typedef int (__sys_issetugid_t)(void); +typedef int (__sys_lchown_t)(const char *, int, int); +typedef int (__sys_aio_read_t)(struct aiocb *); +typedef int (__sys_aio_write_t)(struct aiocb *); +typedef int (__sys_lio_listio_t)(int, struct aiocb * const *, int, struct sigevent *); +typedef int (__sys_lchmod_t)(const char *, mode_t); +typedef int (__sys_lutimes_t)(const char *, const struct timeval *); +typedef ssize_t (__sys_preadv_t)(int, struct iovec *, u_int, off_t); +typedef ssize_t (__sys_pwritev_t)(int, struct iovec *, u_int, off_t); +typedef int (__sys_fhopen_t)(const struct fhandle *, int); +typedef int (__sys_modnext_t)(int); +typedef int (__sys_modstat_t)(int, struct module_stat *); +typedef int (__sys_modfnext_t)(int); +typedef int (__sys_modfind_t)(const char *); +typedef int (__sys_kldload_t)(const char *); +typedef int (__sys_kldunload_t)(int); +typedef int (__sys_kldfind_t)(const char *); +typedef int (__sys_kldnext_t)(int); +typedef int (__sys_kldstat_t)(int, struct kld_file_stat *); +typedef int (__sys_kldfirstmod_t)(int); +typedef int (__sys_getsid_t)(pid_t); +typedef int (__sys_setresuid_t)(uid_t, uid_t, uid_t); +typedef int (__sys_setresgid_t)(gid_t, gid_t, gid_t); +typedef ssize_t (__sys_aio_return_t)(struct aiocb *); +typedef int (__sys_aio_suspend_t)(const struct aiocb * const *, int, const struct timespec *); +typedef int (__sys_aio_cancel_t)(int, struct aiocb *); +typedef int (__sys_aio_error_t)(struct aiocb *); +typedef int (__sys_mlockall_t)(int); +typedef int (__sys_munlockall_t)(void); +typedef int (__sys___getcwd_t)(char *, size_t); +typedef int (__sys_sched_setparam_t)(pid_t, const struct sched_param *); +typedef int (__sys_sched_getparam_t)(pid_t, struct sched_param *); +typedef int (__sys_sched_setscheduler_t)(pid_t, int, const struct sched_param *); +typedef int (__sys_sched_getscheduler_t)(pid_t); +typedef int (__sys_sched_yield_t)(void); +typedef int (__sys_sched_get_priority_max_t)(int); +typedef int (__sys_sched_get_priority_min_t)(int); +typedef int (__sys_sched_rr_get_interval_t)(pid_t, struct timespec *); +typedef int (__sys_utrace_t)(const void *, size_t); +typedef int (__sys_kldsym_t)(int, int, void *); +typedef int (__sys_jail_t)(struct jail *); +typedef int (__sys_nnpfs_syscall_t)(int, char *, int, void *, int); +typedef int (__sys_sigprocmask_t)(int, const sigset_t *, sigset_t *); +typedef int (__sys_sigsuspend_t)(const sigset_t *); +typedef int (__sys_sigpending_t)(sigset_t *); +typedef int (__sys_sigtimedwait_t)(const sigset_t *, struct __siginfo *, const struct timespec *); +typedef int (__sys_sigwaitinfo_t)(const sigset_t *, struct __siginfo *); +typedef int (__sys___acl_get_file_t)(const char *, __acl_type_t, struct acl *); +typedef int (__sys___acl_set_file_t)(const char *, __acl_type_t, struct acl *); +typedef int (__sys___acl_get_fd_t)(int, __acl_type_t, struct acl *); +typedef int (__sys___acl_set_fd_t)(int, __acl_type_t, struct acl *); +typedef int (__sys___acl_delete_file_t)(const char *, __acl_type_t); +typedef int (__sys___acl_delete_fd_t)(int, __acl_type_t); +typedef int (__sys___acl_aclcheck_file_t)(const char *, __acl_type_t, struct acl *); +typedef int (__sys___acl_aclcheck_fd_t)(int, __acl_type_t, struct acl *); +typedef int (__sys_extattrctl_t)(const char *, int, const char *, int, const char *); +typedef ssize_t (__sys_extattr_set_file_t)(const char *, int, const char *, void *, size_t); +typedef ssize_t (__sys_extattr_get_file_t)(const char *, int, const char *, void *, size_t); +typedef int (__sys_extattr_delete_file_t)(const char *, int, const char *); +typedef ssize_t (__sys_aio_waitcomplete_t)(struct aiocb **, struct timespec *); +typedef int (__sys_getresuid_t)(uid_t *, uid_t *, uid_t *); +typedef int (__sys_getresgid_t)(gid_t *, gid_t *, gid_t *); +typedef int (__sys_kqueue_t)(void); +typedef ssize_t (__sys_extattr_set_fd_t)(int, int, const char *, void *, size_t); +typedef ssize_t (__sys_extattr_get_fd_t)(int, int, const char *, void *, size_t); +typedef int (__sys_extattr_delete_fd_t)(int, int, const char *); +typedef int (__sys___setugid_t)(int); +typedef int (__sys_eaccess_t)(const char *, int); +typedef int (__sys_afs3_syscall_t)(long, long, long, long, long, long, long); +typedef int (__sys_nmount_t)(struct iovec *, unsigned int, int); +typedef int (__sys___mac_get_proc_t)(struct mac *); +typedef int (__sys___mac_set_proc_t)(struct mac *); +typedef int (__sys___mac_get_fd_t)(int, struct mac *); +typedef int (__sys___mac_get_file_t)(const char *, struct mac *); +typedef int (__sys___mac_set_fd_t)(int, struct mac *); +typedef int (__sys___mac_set_file_t)(const char *, struct mac *); +typedef int (__sys_kenv_t)(int, const char *, char *, int); +typedef int (__sys_lchflags_t)(const char *, u_long); +typedef int (__sys_uuidgen_t)(struct uuid *, int); +typedef int (__sys_sendfile_t)(int, int, off_t, size_t, struct sf_hdtr *, off_t *, int); +typedef int (__sys_mac_syscall_t)(const char *, int, void *); +typedef int (__sys_ksem_close_t)(semid_t); +typedef int (__sys_ksem_post_t)(semid_t); +typedef int (__sys_ksem_wait_t)(semid_t); +typedef int (__sys_ksem_trywait_t)(semid_t); +typedef int (__sys_ksem_init_t)(semid_t *, unsigned int); +typedef int (__sys_ksem_open_t)(semid_t *, const char *, int, mode_t, unsigned int); +typedef int (__sys_ksem_unlink_t)(const char *); +typedef int (__sys_ksem_getvalue_t)(semid_t, int *); +typedef int (__sys_ksem_destroy_t)(semid_t); +typedef int (__sys___mac_get_pid_t)(pid_t, struct mac *); +typedef int (__sys___mac_get_link_t)(const char *, struct mac *); +typedef int (__sys___mac_set_link_t)(const char *, struct mac *); +typedef ssize_t (__sys_extattr_set_link_t)(const char *, int, const char *, void *, size_t); +typedef ssize_t (__sys_extattr_get_link_t)(const char *, int, const char *, void *, size_t); +typedef int (__sys_extattr_delete_link_t)(const char *, int, const char *); +typedef int (__sys___mac_execve_t)(const char *, char **, char **, struct mac *); +typedef int (__sys_sigaction_t)(int, const struct sigaction *, struct sigaction *); +typedef int (__sys_sigreturn_t)(const struct __ucontext *); +typedef int (__sys_getcontext_t)(struct __ucontext *); +typedef int (__sys_setcontext_t)(const struct __ucontext *); +typedef int (__sys_swapcontext_t)(struct __ucontext *, const struct __ucontext *); +typedef int (__sys___acl_get_link_t)(const char *, __acl_type_t, struct acl *); +typedef int (__sys___acl_set_link_t)(const char *, __acl_type_t, struct acl *); +typedef int (__sys___acl_delete_link_t)(const char *, __acl_type_t); +typedef int (__sys___acl_aclcheck_link_t)(const char *, __acl_type_t, struct acl *); +typedef int (__sys_sigwait_t)(const sigset_t *, int *); +typedef int (__sys_thr_create_t)(ucontext_t *, long *, int); +typedef void (__sys_thr_exit_t)(long *); +typedef int (__sys_thr_self_t)(long *); +typedef int (__sys_thr_kill_t)(long, int); +typedef int (__sys_jail_attach_t)(int); +typedef ssize_t (__sys_extattr_list_fd_t)(int, int, void *, size_t); +typedef ssize_t (__sys_extattr_list_file_t)(const char *, int, void *, size_t); +typedef ssize_t (__sys_extattr_list_link_t)(const char *, int, void *, size_t); +typedef int (__sys_ksem_timedwait_t)(semid_t, const struct timespec *); +typedef int (__sys_thr_suspend_t)(const struct timespec *); +typedef int (__sys_thr_wake_t)(long); +typedef int (__sys_kldunloadf_t)(int, int); +typedef int (__sys_audit_t)(const void *, u_int); +typedef int (__sys_auditon_t)(int, void *, u_int); +typedef int (__sys_getauid_t)(uid_t *); +typedef int (__sys_setauid_t)(uid_t *); +typedef int (__sys_getaudit_t)(struct auditinfo *); +typedef int (__sys_setaudit_t)(struct auditinfo *); +typedef int (__sys_getaudit_addr_t)(struct auditinfo_addr *, u_int); +typedef int (__sys_setaudit_addr_t)(struct auditinfo_addr *, u_int); +typedef int (__sys_auditctl_t)(const char *); +typedef int (__sys__umtx_op_t)(void *, int, u_long, void *, void *); +typedef int (__sys_thr_new_t)(struct thr_param *, int); +typedef int (__sys_sigqueue_t)(pid_t, int, void *); +typedef int (__sys_kmq_open_t)(const char *, int, mode_t, const struct mq_attr *); +typedef int (__sys_kmq_setattr_t)(int, const struct mq_attr *, struct mq_attr *); +typedef int (__sys_kmq_timedreceive_t)(int, char *, size_t, unsigned *, const struct timespec *); +typedef int (__sys_kmq_timedsend_t)(int, const char *, size_t, unsigned, const struct timespec *); +typedef int (__sys_kmq_notify_t)(int, const struct sigevent *); +typedef int (__sys_kmq_unlink_t)(const char *); +typedef void (__sys_abort2_t)(const char *, int, void **); +typedef int (__sys_thr_set_name_t)(long, const char *); +typedef int (__sys_aio_fsync_t)(int, struct aiocb *); +typedef int (__sys_rtprio_thread_t)(int, lwpid_t, struct rtprio *); +typedef int (__sys_sctp_peeloff_t)(int, uint32_t); +typedef int (__sys_sctp_generic_sendmsg_t)(int, void *, int, const struct sockaddr *, __socklen_t, struct sctp_sndrcvinfo *, int); +typedef int (__sys_sctp_generic_sendmsg_iov_t)(int, struct iovec *, int, const struct sockaddr *, __socklen_t, struct sctp_sndrcvinfo *, int); +typedef int (__sys_sctp_generic_recvmsg_t)(int, struct iovec *, int, struct sockaddr *, __socklen_t *, struct sctp_sndrcvinfo *, int *); +typedef ssize_t (__sys_pread_t)(int, void *, size_t, off_t); +typedef ssize_t (__sys_pwrite_t)(int, const void *, size_t, off_t); +typedef void * (__sys_mmap_t)(void *, size_t, int, int, int, off_t); +typedef off_t (__sys_lseek_t)(int, off_t, int); +typedef int (__sys_truncate_t)(const char *, off_t); +typedef int (__sys_ftruncate_t)(int, off_t); +typedef int (__sys_thr_kill2_t)(pid_t, long, int); +typedef int (__sys_shm_unlink_t)(const char *); +typedef int (__sys_cpuset_t)(cpusetid_t *); +typedef int (__sys_cpuset_setid_t)(cpuwhich_t, id_t, cpusetid_t); +typedef int (__sys_cpuset_getid_t)(cpulevel_t, cpuwhich_t, id_t, cpusetid_t *); +typedef int (__sys_cpuset_getaffinity_t)(cpulevel_t, cpuwhich_t, id_t, size_t, cpuset_t *); +typedef int (__sys_cpuset_setaffinity_t)(cpulevel_t, cpuwhich_t, id_t, size_t, const cpuset_t *); +typedef int (__sys_faccessat_t)(int, const char *, int, int); +typedef int (__sys_fchmodat_t)(int, const char *, mode_t, int); +typedef int (__sys_fchownat_t)(int, const char *, uid_t, gid_t, int); +typedef int (__sys_fexecve_t)(int, char **, char **); +typedef int (__sys_futimesat_t)(int, const char *, const struct timeval *); +typedef int (__sys_linkat_t)(int, const char *, int, const char *, int); +typedef int (__sys_mkdirat_t)(int, const char *, mode_t); +typedef int (__sys_mkfifoat_t)(int, const char *, mode_t); +typedef int (__sys_openat_t)(int, const char *, int, mode_t); +typedef ssize_t (__sys_readlinkat_t)(int, const char *, char *, size_t); +typedef int (__sys_renameat_t)(int, const char *, int, const char *); +typedef int (__sys_symlinkat_t)(const char *, int, const char *); +typedef int (__sys_unlinkat_t)(int, const char *, int); +typedef int (__sys_posix_openpt_t)(int); +typedef int (__sys_jail_get_t)(struct iovec *, unsigned int, int); +typedef int (__sys_jail_set_t)(struct iovec *, unsigned int, int); +typedef int (__sys_jail_remove_t)(int); +typedef int (__sys___semctl_t)(int, int, int, union semun *); +typedef int (__sys_msgctl_t)(int, int, struct msqid_ds *); +typedef int (__sys_shmctl_t)(int, int, struct shmid_ds *); +typedef int (__sys_lpathconf_t)(const char *, int); +typedef int (__sys___cap_rights_get_t)(int, int, cap_rights_t *); +typedef int (__sys_cap_enter_t)(void); +typedef int (__sys_cap_getmode_t)(u_int *); +typedef int (__sys_pdfork_t)(int *, int); +typedef int (__sys_pdkill_t)(int, int); +typedef int (__sys_pdgetpid_t)(int, pid_t *); +typedef int (__sys_pselect_t)(int, fd_set *, fd_set *, fd_set *, const struct timespec *, const sigset_t *); +typedef int (__sys_getloginclass_t)(char *, size_t); +typedef int (__sys_setloginclass_t)(const char *); +typedef int (__sys_rctl_get_racct_t)(const void *, size_t, void *, size_t); +typedef int (__sys_rctl_get_rules_t)(const void *, size_t, void *, size_t); +typedef int (__sys_rctl_get_limits_t)(const void *, size_t, void *, size_t); +typedef int (__sys_rctl_add_rule_t)(const void *, size_t, void *, size_t); +typedef int (__sys_rctl_remove_rule_t)(const void *, size_t, void *, size_t); +typedef int (__sys_posix_fallocate_t)(int, off_t, off_t); +typedef int (__sys_posix_fadvise_t)(int, off_t, off_t, int); +typedef int (__sys_wait6_t)(idtype_t, id_t, int *, int, struct __wrusage *, struct __siginfo *); +typedef int (__sys_cap_rights_limit_t)(int, cap_rights_t *); +typedef int (__sys_cap_ioctls_limit_t)(int, const u_long *, size_t); +typedef ssize_t (__sys_cap_ioctls_get_t)(int, u_long *, size_t); +typedef int (__sys_cap_fcntls_limit_t)(int, uint32_t); +typedef int (__sys_cap_fcntls_get_t)(int, uint32_t *); +typedef int (__sys_bindat_t)(int, int, const struct sockaddr *, __socklen_t); +typedef int (__sys_connectat_t)(int, int, const struct sockaddr *, __socklen_t); +typedef int (__sys_chflagsat_t)(int, const char *, u_long, int); +typedef int (__sys_accept4_t)(int, struct sockaddr *, __socklen_t *, int); +typedef int (__sys_pipe2_t)(int *, int); +typedef int (__sys_aio_mlock_t)(struct aiocb *); +typedef int (__sys_procctl_t)(idtype_t, id_t, int, void *); +typedef int (__sys_ppoll_t)(struct pollfd *, u_int, const struct timespec *, const sigset_t *); +typedef int (__sys_futimens_t)(int, const struct timespec *); +typedef int (__sys_utimensat_t)(int, const char *, const struct timespec *, int); +typedef int (__sys_fdatasync_t)(int); +typedef int (__sys_fstat_t)(int, struct stat *); +typedef int (__sys_fstatat_t)(int, const char *, struct stat *, int); +typedef int (__sys_fhstat_t)(const struct fhandle *, struct stat *); +typedef ssize_t (__sys_getdirentries_t)(int, char *, size_t, off_t *); +typedef int (__sys_statfs_t)(const char *, struct statfs *); +typedef int (__sys_fstatfs_t)(int, struct statfs *); +typedef int (__sys_getfsstat_t)(struct statfs *, long, int); +typedef int (__sys_fhstatfs_t)(const struct fhandle *, struct statfs *); +typedef int (__sys_mknodat_t)(int, const char *, mode_t, dev_t); +typedef int (__sys_kevent_t)(int, const struct kevent *, int, struct kevent *, int, const struct timespec *); +typedef int (__sys_cpuset_getdomain_t)(cpulevel_t, cpuwhich_t, id_t, size_t, domainset_t *, int *); +typedef int (__sys_cpuset_setdomain_t)(cpulevel_t, cpuwhich_t, id_t, size_t, domainset_t *, int); +typedef int (__sys_getrandom_t)(void *, size_t, unsigned int); +typedef int (__sys_getfhat_t)(int, char *, struct fhandle *, int); +typedef int (__sys_fhlink_t)(struct fhandle *, const char *); +typedef int (__sys_fhlinkat_t)(struct fhandle *, int, const char *); +typedef int (__sys_fhreadlink_t)(struct fhandle *, char *, size_t); +typedef int (__sys_funlinkat_t)(int, const char *, int, int); +typedef ssize_t (__sys_copy_file_range_t)(int, off_t *, int, off_t *, size_t, unsigned int); +typedef int (__sys___sysctlbyname_t)(const char *, size_t, void *, size_t *, void *, size_t); +typedef int (__sys_shm_open2_t)(const char *, int, mode_t, int, const char *); +typedef int (__sys_shm_rename_t)(const char *, const char *, int); +typedef int (__sys_sigfastblock_t)(int, void *); +typedef int (__sys___realpathat_t)(int, const char *, char *, size_t, int); +typedef int (__sys_close_range_t)(u_int, u_int, int); +typedef int (__sys_rpctls_syscall_t)(uint64_t); +typedef int (__sys___specialfd_t)(int, const void *, size_t); +typedef int (__sys_aio_writev_t)(struct aiocb *); +typedef int (__sys_aio_readv_t)(struct aiocb *); +typedef int (__sys_fspacectl_t)(int, int, const struct spacectl_range *, int, struct spacectl_range *); +typedef int (__sys_sched_getcpu_t)(void); +typedef int (__sys_swapoff_t)(const char *, u_int); +typedef int (__sys_kqueuex_t)(u_int); +typedef int (__sys_membarrier_t)(int, unsigned, int); +typedef int (__sys_timerfd_create_t)(int, int); +typedef int (__sys_timerfd_gettime_t)(int, struct itimerspec *); +typedef int (__sys_timerfd_settime_t)(int, int, const struct itimerspec *, struct itimerspec *); +typedef int (__sys_kcmp_t)(pid_t, pid_t, int, uintptr_t, uintptr_t); +typedef int (__sys_getrlimitusage_t)(u_int, int, rlim_t *); +typedef int (__sys_fchroot_t)(int); +typedef int (__sys_setcred_t)(u_int, const struct setcred *, size_t); +typedef int (__sys_exterrctl_t)(u_int, u_int, void *); +typedef int (__sys_inotify_add_watch_at_t)(int, int, const char *, uint32_t); +typedef int (__sys_inotify_rm_watch_t)(int, int); +typedef int (__sys_getgroups_t)(int, gid_t *); +typedef int (__sys_setgroups_t)(int, const gid_t *); +typedef int (__sys_jail_attach_jd_t)(int); +typedef int (__sys_jail_remove_jd_t)(int); + +_Noreturn void __sys__exit(int rval); +int __sys_fork(void); +ssize_t __sys_read(int fd, void * buf, size_t nbyte); +ssize_t __sys_write(int fd, const void * buf, size_t nbyte); +int __sys_open(const char * path, int flags, mode_t mode); +int __sys_close(int fd); +int __sys_wait4(int pid, int * status, int options, struct rusage * rusage); +int __sys_link(const char * path, const char * link); +int __sys_unlink(const char * path); +int __sys_chdir(const char * path); +int __sys_fchdir(int fd); +int __sys_chmod(const char * path, mode_t mode); +int __sys_chown(const char * path, int uid, int gid); +void * __sys_break(char * nsize); +pid_t __sys_getpid(void); +int __sys_mount(const char * type, const char * path, int flags, void * data); +int __sys_unmount(const char * path, int flags); +int __sys_setuid(uid_t uid); +uid_t __sys_getuid(void); +uid_t __sys_geteuid(void); +int __sys_ptrace(int req, pid_t pid, caddr_t addr, int data); +ssize_t __sys_recvmsg(int s, struct msghdr * msg, int flags); +ssize_t __sys_sendmsg(int s, const struct msghdr * msg, int flags); +ssize_t __sys_recvfrom(int s, void * buf, size_t len, int flags, struct sockaddr * from, __socklen_t * fromlenaddr); +int __sys_accept(int s, struct sockaddr * name, __socklen_t * anamelen); +int __sys_getpeername(int fdes, struct sockaddr * asa, __socklen_t * alen); +int __sys_getsockname(int fdes, struct sockaddr * asa, __socklen_t * alen); +int __sys_access(const char * path, int amode); +int __sys_chflags(const char * path, u_long flags); +int __sys_fchflags(int fd, u_long flags); +int __sys_sync(void); +int __sys_kill(int pid, int signum); +pid_t __sys_getppid(void); +int __sys_dup(u_int fd); +gid_t __sys_getegid(void); +int __sys_profil(char * samples, size_t size, size_t offset, u_int scale); +int __sys_ktrace(const char * fname, int ops, int facs, int pid); +gid_t __sys_getgid(void); +int __sys_getlogin(char * namebuf, u_int namelen); +int __sys_setlogin(const char * namebuf); +int __sys_acct(const char * path); +int __sys_sigaltstack(const struct sigaltstack * ss, struct sigaltstack * oss); +int __sys_ioctl(int fd, u_long com, char * data); +int __sys_reboot(int opt); +int __sys_revoke(const char * path); +int __sys_symlink(const char * path, const char * link); +ssize_t __sys_readlink(const char * path, char * buf, size_t count); +int __sys_execve(const char * fname, char ** argv, char ** envv); +mode_t __sys_umask(mode_t newmask); +int __sys_chroot(const char * path); +int __sys_msync(void * addr, size_t len, int flags); +int __sys_vfork(void); +int __sys_munmap(void * addr, size_t len); +int __sys_mprotect(void * addr, size_t len, int prot); +int __sys_madvise(void * addr, size_t len, int behav); +int __sys_mincore(const void * addr, size_t len, char * vec); +int __sys_getpgrp(void); +int __sys_setpgid(int pid, int pgid); +int __sys_setitimer(int which, const struct itimerval * itv, struct itimerval * oitv); +int __sys_swapon(const char * name); +int __sys_getitimer(int which, struct itimerval * itv); +int __sys_getdtablesize(void); +int __sys_dup2(u_int from, u_int to); +int __sys_fcntl(int fd, int cmd, intptr_t arg); +int __sys_select(int nd, fd_set * in, fd_set * ou, fd_set * ex, struct timeval * tv); +int __sys_fsync(int fd); +int __sys_setpriority(int which, int who, int prio); +int __sys_socket(int domain, int type, int protocol); +int __sys_connect(int s, const struct sockaddr * name, __socklen_t namelen); +int __sys_getpriority(int which, int who); +int __sys_bind(int s, const struct sockaddr * name, __socklen_t namelen); +int __sys_setsockopt(int s, int level, int name, const void * val, __socklen_t valsize); +int __sys_listen(int s, int backlog); +int __sys_gettimeofday(struct timeval * tp, struct timezone * tzp); +int __sys_getrusage(int who, struct rusage * rusage); +int __sys_getsockopt(int s, int level, int name, void * val, __socklen_t * avalsize); +ssize_t __sys_readv(int fd, const struct iovec * iovp, u_int iovcnt); +ssize_t __sys_writev(int fd, const struct iovec * iovp, u_int iovcnt); +int __sys_settimeofday(const struct timeval * tv, const struct timezone * tzp); +int __sys_fchown(int fd, int uid, int gid); +int __sys_fchmod(int fd, mode_t mode); +int __sys_setreuid(int ruid, int euid); +int __sys_setregid(int rgid, int egid); +int __sys_rename(const char * from, const char * to); +int __sys_flock(int fd, int how); +int __sys_mkfifo(const char * path, mode_t mode); +ssize_t __sys_sendto(int s, const void * buf, size_t len, int flags, const struct sockaddr * to, __socklen_t tolen); +int __sys_shutdown(int s, int how); +int __sys_socketpair(int domain, int type, int protocol, int * rsv); +int __sys_mkdir(const char * path, mode_t mode); +int __sys_rmdir(const char * path); +int __sys_utimes(const char * path, const struct timeval * tptr); +int __sys_adjtime(const struct timeval * delta, struct timeval * olddelta); +int __sys_setsid(void); +int __sys_quotactl(const char * path, int cmd, int uid, void * arg); +int __sys_nlm_syscall(int debug_level, int grace_period, int addr_count, char ** addrs); +int __sys_nfssvc(int flag, void * argp); +int __sys_lgetfh(const char * fname, struct fhandle * fhp); +int __sys_getfh(const char * fname, struct fhandle * fhp); +int __sys_sysarch(int op, char * parms); +int __sys_rtprio(int function, pid_t pid, struct rtprio * rtp); +int __sys_semsys(int which, int a2, int a3, int a4, int a5); +int __sys_msgsys(int which, int a2, int a3, int a4, int a5, int a6); +int __sys_shmsys(int which, int a2, int a3, int a4); +int __sys_setfib(int fibnum); +int __sys_ntp_adjtime(struct timex * tp); +int __sys_setgid(gid_t gid); +int __sys_setegid(gid_t egid); +int __sys_seteuid(uid_t euid); +int __sys_pathconf(const char * path, int name); +int __sys_fpathconf(int fd, int name); +int __sys_getrlimit(u_int which, struct rlimit * rlp); +int __sys_setrlimit(u_int which, struct rlimit * rlp); +int __sys___sysctl(const int * name, u_int namelen, void * old, size_t * oldlenp, const void * new, size_t newlen); +int __sys_mlock(const void * addr, size_t len); +int __sys_munlock(const void * addr, size_t len); +int __sys_undelete(const char * path); +int __sys_futimes(int fd, const struct timeval * tptr); +int __sys_getpgid(pid_t pid); +int __sys_poll(struct pollfd * fds, u_int nfds, int timeout); +int __sys_semget(key_t key, int nsems, int semflg); +int __sys_semop(int semid, struct sembuf * sops, size_t nsops); +int __sys_msgget(key_t key, int msgflg); +int __sys_msgsnd(int msqid, const void * msgp, size_t msgsz, int msgflg); +ssize_t __sys_msgrcv(int msqid, void * msgp, size_t msgsz, long msgtyp, int msgflg); +void * __sys_shmat(int shmid, const void * shmaddr, int shmflg); +int __sys_shmdt(const void * shmaddr); +int __sys_shmget(key_t key, size_t size, int shmflg); +int __sys_clock_gettime(clockid_t clock_id, struct timespec * tp); +int __sys_clock_settime(clockid_t clock_id, const struct timespec * tp); +int __sys_clock_getres(clockid_t clock_id, struct timespec * tp); +int __sys_ktimer_create(clockid_t clock_id, struct sigevent * evp, int * timerid); +int __sys_ktimer_delete(int timerid); +int __sys_ktimer_settime(int timerid, int flags, const struct itimerspec * value, struct itimerspec * ovalue); +int __sys_ktimer_gettime(int timerid, struct itimerspec * value); +int __sys_ktimer_getoverrun(int timerid); +int __sys_nanosleep(const struct timespec * rqtp, struct timespec * rmtp); +int __sys_ffclock_getcounter(ffcounter * ffcount); +int __sys_ffclock_setestimate(struct ffclock_estimate * cest); +int __sys_ffclock_getestimate(struct ffclock_estimate * cest); +int __sys_clock_nanosleep(clockid_t clock_id, int flags, const struct timespec * rqtp, struct timespec * rmtp); +int __sys_clock_getcpuclockid2(id_t id, int which, clockid_t * clock_id); +int __sys_ntp_gettime(struct ntptimeval * ntvp); +int __sys_minherit(void * addr, size_t len, int inherit); +int __sys_rfork(int flags); +int __sys_issetugid(void); +int __sys_lchown(const char * path, int uid, int gid); +int __sys_aio_read(struct aiocb * aiocbp); +int __sys_aio_write(struct aiocb * aiocbp); +int __sys_lio_listio(int mode, struct aiocb * const * acb_list, int nent, struct sigevent * sig); +int __sys_lchmod(const char * path, mode_t mode); +int __sys_lutimes(const char * path, const struct timeval * tptr); +ssize_t __sys_preadv(int fd, struct iovec * iovp, u_int iovcnt, off_t offset); +ssize_t __sys_pwritev(int fd, struct iovec * iovp, u_int iovcnt, off_t offset); +int __sys_fhopen(const struct fhandle * u_fhp, int flags); +int __sys_modnext(int modid); +int __sys_modstat(int modid, struct module_stat * stat); +int __sys_modfnext(int modid); +int __sys_modfind(const char * name); +int __sys_kldload(const char * file); +int __sys_kldunload(int fileid); +int __sys_kldfind(const char * file); +int __sys_kldnext(int fileid); +int __sys_kldstat(int fileid, struct kld_file_stat * stat); +int __sys_kldfirstmod(int fileid); +int __sys_getsid(pid_t pid); +int __sys_setresuid(uid_t ruid, uid_t euid, uid_t suid); +int __sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid); +ssize_t __sys_aio_return(struct aiocb * aiocbp); +int __sys_aio_suspend(const struct aiocb * const * aiocbp, int nent, const struct timespec * timeout); +int __sys_aio_cancel(int fd, struct aiocb * aiocbp); +int __sys_aio_error(struct aiocb * aiocbp); +int __sys_mlockall(int how); +int __sys_munlockall(void); +int __sys___getcwd(char * buf, size_t buflen); +int __sys_sched_setparam(pid_t pid, const struct sched_param * param); +int __sys_sched_getparam(pid_t pid, struct sched_param * param); +int __sys_sched_setscheduler(pid_t pid, int policy, const struct sched_param * param); +int __sys_sched_getscheduler(pid_t pid); +int __sys_sched_yield(void); +int __sys_sched_get_priority_max(int policy); +int __sys_sched_get_priority_min(int policy); +int __sys_sched_rr_get_interval(pid_t pid, struct timespec * interval); +int __sys_utrace(const void * addr, size_t len); +int __sys_kldsym(int fileid, int cmd, void * data); +int __sys_jail(struct jail * jail); +int __sys_nnpfs_syscall(int operation, char * a_pathP, int a_opcode, void * a_paramsP, int a_followSymlinks); +int __sys_sigprocmask(int how, const sigset_t * set, sigset_t * oset); +int __sys_sigsuspend(const sigset_t * sigmask); +int __sys_sigpending(sigset_t * set); +int __sys_sigtimedwait(const sigset_t * set, struct __siginfo * info, const struct timespec * timeout); +int __sys_sigwaitinfo(const sigset_t * set, struct __siginfo * info); +int __sys___acl_get_file(const char * path, __acl_type_t type, struct acl * aclp); +int __sys___acl_set_file(const char * path, __acl_type_t type, struct acl * aclp); +int __sys___acl_get_fd(int filedes, __acl_type_t type, struct acl * aclp); +int __sys___acl_set_fd(int filedes, __acl_type_t type, struct acl * aclp); +int __sys___acl_delete_file(const char * path, __acl_type_t type); +int __sys___acl_delete_fd(int filedes, __acl_type_t type); +int __sys___acl_aclcheck_file(const char * path, __acl_type_t type, struct acl * aclp); +int __sys___acl_aclcheck_fd(int filedes, __acl_type_t type, struct acl * aclp); +int __sys_extattrctl(const char * path, int cmd, const char * filename, int attrnamespace, const char * attrname); +ssize_t __sys_extattr_set_file(const char * path, int attrnamespace, const char * attrname, void * data, size_t nbytes); +ssize_t __sys_extattr_get_file(const char * path, int attrnamespace, const char * attrname, void * data, size_t nbytes); +int __sys_extattr_delete_file(const char * path, int attrnamespace, const char * attrname); +ssize_t __sys_aio_waitcomplete(struct aiocb ** aiocbp, struct timespec * timeout); +int __sys_getresuid(uid_t * ruid, uid_t * euid, uid_t * suid); +int __sys_getresgid(gid_t * rgid, gid_t * egid, gid_t * sgid); +int __sys_kqueue(void); +ssize_t __sys_extattr_set_fd(int fd, int attrnamespace, const char * attrname, void * data, size_t nbytes); +ssize_t __sys_extattr_get_fd(int fd, int attrnamespace, const char * attrname, void * data, size_t nbytes); +int __sys_extattr_delete_fd(int fd, int attrnamespace, const char * attrname); +int __sys___setugid(int flag); +int __sys_eaccess(const char * path, int amode); +int __sys_afs3_syscall(long syscall, long parm1, long parm2, long parm3, long parm4, long parm5, long parm6); +int __sys_nmount(struct iovec * iovp, unsigned int iovcnt, int flags); +int __sys___mac_get_proc(struct mac * mac_p); +int __sys___mac_set_proc(struct mac * mac_p); +int __sys___mac_get_fd(int fd, struct mac * mac_p); +int __sys___mac_get_file(const char * path_p, struct mac * mac_p); +int __sys___mac_set_fd(int fd, struct mac * mac_p); +int __sys___mac_set_file(const char * path_p, struct mac * mac_p); +int __sys_kenv(int what, const char * name, char * value, int len); +int __sys_lchflags(const char * path, u_long flags); +int __sys_uuidgen(struct uuid * store, int count); +int __sys_sendfile(int fd, int s, off_t offset, size_t nbytes, struct sf_hdtr * hdtr, off_t * sbytes, int flags); +int __sys_mac_syscall(const char * policy, int call, void * arg); +int __sys_ksem_close(semid_t id); +int __sys_ksem_post(semid_t id); +int __sys_ksem_wait(semid_t id); +int __sys_ksem_trywait(semid_t id); +int __sys_ksem_init(semid_t * idp, unsigned int value); +int __sys_ksem_open(semid_t * idp, const char * name, int oflag, mode_t mode, unsigned int value); +int __sys_ksem_unlink(const char * name); +int __sys_ksem_getvalue(semid_t id, int * val); +int __sys_ksem_destroy(semid_t id); +int __sys___mac_get_pid(pid_t pid, struct mac * mac_p); +int __sys___mac_get_link(const char * path_p, struct mac * mac_p); +int __sys___mac_set_link(const char * path_p, struct mac * mac_p); +ssize_t __sys_extattr_set_link(const char * path, int attrnamespace, const char * attrname, void * data, size_t nbytes); +ssize_t __sys_extattr_get_link(const char * path, int attrnamespace, const char * attrname, void * data, size_t nbytes); +int __sys_extattr_delete_link(const char * path, int attrnamespace, const char * attrname); +int __sys___mac_execve(const char * fname, char ** argv, char ** envv, struct mac * mac_p); +int __sys_sigaction(int sig, const struct sigaction * act, struct sigaction * oact); +int __sys_sigreturn(const struct __ucontext * sigcntxp); +int __sys_getcontext(struct __ucontext * ucp); +int __sys_setcontext(const struct __ucontext * ucp); +int __sys_swapcontext(struct __ucontext * oucp, const struct __ucontext * ucp); +int __sys___acl_get_link(const char * path, __acl_type_t type, struct acl * aclp); +int __sys___acl_set_link(const char * path, __acl_type_t type, struct acl * aclp); +int __sys___acl_delete_link(const char * path, __acl_type_t type); +int __sys___acl_aclcheck_link(const char * path, __acl_type_t type, struct acl * aclp); +int __sys_sigwait(const sigset_t * set, int * sig); +int __sys_thr_create(ucontext_t * ctx, long * id, int flags); +void __sys_thr_exit(long * state); +int __sys_thr_self(long * id); +int __sys_thr_kill(long id, int sig); +int __sys_jail_attach(int jid); +ssize_t __sys_extattr_list_fd(int fd, int attrnamespace, void * data, size_t nbytes); +ssize_t __sys_extattr_list_file(const char * path, int attrnamespace, void * data, size_t nbytes); +ssize_t __sys_extattr_list_link(const char * path, int attrnamespace, void * data, size_t nbytes); +int __sys_ksem_timedwait(semid_t id, const struct timespec * abstime); +int __sys_thr_suspend(const struct timespec * timeout); +int __sys_thr_wake(long id); +int __sys_kldunloadf(int fileid, int flags); +int __sys_audit(const void * record, u_int length); +int __sys_auditon(int cmd, void * data, u_int length); +int __sys_getauid(uid_t * auid); +int __sys_setauid(uid_t * auid); +int __sys_getaudit(struct auditinfo * auditinfo); +int __sys_setaudit(struct auditinfo * auditinfo); +int __sys_getaudit_addr(struct auditinfo_addr * auditinfo_addr, u_int length); +int __sys_setaudit_addr(struct auditinfo_addr * auditinfo_addr, u_int length); +int __sys_auditctl(const char * path); +int __sys__umtx_op(void * obj, int op, u_long val, void * uaddr1, void * uaddr2); +int __sys_thr_new(struct thr_param * param, int param_size); +int __sys_sigqueue(pid_t pid, int signum, void * value); +int __sys_kmq_open(const char * path, int flags, mode_t mode, const struct mq_attr * attr); +int __sys_kmq_setattr(int mqd, const struct mq_attr * attr, struct mq_attr * oattr); +int __sys_kmq_timedreceive(int mqd, char * msg_ptr, size_t msg_len, unsigned * msg_prio, const struct timespec * abs_timeout); +int __sys_kmq_timedsend(int mqd, const char * msg_ptr, size_t msg_len, unsigned msg_prio, const struct timespec * abs_timeout); +int __sys_kmq_notify(int mqd, const struct sigevent * sigev); +int __sys_kmq_unlink(const char * path); +void __sys_abort2(const char * why, int nargs, void ** args); +int __sys_thr_set_name(long id, const char * name); +int __sys_aio_fsync(int op, struct aiocb * aiocbp); +int __sys_rtprio_thread(int function, lwpid_t lwpid, struct rtprio * rtp); +int __sys_sctp_peeloff(int sd, uint32_t name); +int __sys_sctp_generic_sendmsg(int sd, void * msg, int mlen, const struct sockaddr * to, __socklen_t tolen, struct sctp_sndrcvinfo * sinfo, int flags); +int __sys_sctp_generic_sendmsg_iov(int sd, struct iovec * iov, int iovlen, const struct sockaddr * to, __socklen_t tolen, struct sctp_sndrcvinfo * sinfo, int flags); +int __sys_sctp_generic_recvmsg(int sd, struct iovec * iov, int iovlen, struct sockaddr * from, __socklen_t * fromlenaddr, struct sctp_sndrcvinfo * sinfo, int * msg_flags); +ssize_t __sys_pread(int fd, void * buf, size_t nbyte, off_t offset); +ssize_t __sys_pwrite(int fd, const void * buf, size_t nbyte, off_t offset); +void * __sys_mmap(void * addr, size_t len, int prot, int flags, int fd, off_t pos); +off_t __sys_lseek(int fd, off_t offset, int whence); +int __sys_truncate(const char * path, off_t length); +int __sys_ftruncate(int fd, off_t length); +int __sys_thr_kill2(pid_t pid, long id, int sig); +int __sys_shm_unlink(const char * path); +int __sys_cpuset(cpusetid_t * setid); +int __sys_cpuset_setid(cpuwhich_t which, id_t id, cpusetid_t setid); +int __sys_cpuset_getid(cpulevel_t level, cpuwhich_t which, id_t id, cpusetid_t * setid); +int __sys_cpuset_getaffinity(cpulevel_t level, cpuwhich_t which, id_t id, size_t cpusetsize, cpuset_t * mask); +int __sys_cpuset_setaffinity(cpulevel_t level, cpuwhich_t which, id_t id, size_t cpusetsize, const cpuset_t * mask); +int __sys_faccessat(int fd, const char * path, int amode, int flag); +int __sys_fchmodat(int fd, const char * path, mode_t mode, int flag); +int __sys_fchownat(int fd, const char * path, uid_t uid, gid_t gid, int flag); +int __sys_fexecve(int fd, char ** argv, char ** envv); +int __sys_futimesat(int fd, const char * path, const struct timeval * times); +int __sys_linkat(int fd1, const char * path1, int fd2, const char * path2, int flag); +int __sys_mkdirat(int fd, const char * path, mode_t mode); +int __sys_mkfifoat(int fd, const char * path, mode_t mode); +int __sys_openat(int fd, const char * path, int flag, mode_t mode); +ssize_t __sys_readlinkat(int fd, const char * path, char * buf, size_t bufsize); +int __sys_renameat(int oldfd, const char * old, int newfd, const char * new); +int __sys_symlinkat(const char * path1, int fd, const char * path2); +int __sys_unlinkat(int fd, const char * path, int flag); +int __sys_posix_openpt(int flags); +int __sys_jail_get(struct iovec * iovp, unsigned int iovcnt, int flags); +int __sys_jail_set(struct iovec * iovp, unsigned int iovcnt, int flags); +int __sys_jail_remove(int jid); +int __sys___semctl(int semid, int semnum, int cmd, union semun * arg); +int __sys_msgctl(int msqid, int cmd, struct msqid_ds * buf); +int __sys_shmctl(int shmid, int cmd, struct shmid_ds * buf); +int __sys_lpathconf(const char * path, int name); +int __sys___cap_rights_get(int version, int fd, cap_rights_t * rightsp); +int __sys_cap_enter(void); +int __sys_cap_getmode(u_int * modep); +int __sys_pdfork(int * fdp, int flags); +int __sys_pdkill(int fd, int signum); +int __sys_pdgetpid(int fd, pid_t * pidp); +int __sys_pselect(int nd, fd_set * in, fd_set * ou, fd_set * ex, const struct timespec * ts, const sigset_t * sm); +int __sys_getloginclass(char * namebuf, size_t namelen); +int __sys_setloginclass(const char * namebuf); +int __sys_rctl_get_racct(const void * inbufp, size_t inbuflen, void * outbufp, size_t outbuflen); +int __sys_rctl_get_rules(const void * inbufp, size_t inbuflen, void * outbufp, size_t outbuflen); +int __sys_rctl_get_limits(const void * inbufp, size_t inbuflen, void * outbufp, size_t outbuflen); +int __sys_rctl_add_rule(const void * inbufp, size_t inbuflen, void * outbufp, size_t outbuflen); +int __sys_rctl_remove_rule(const void * inbufp, size_t inbuflen, void * outbufp, size_t outbuflen); +int __sys_posix_fallocate(int fd, off_t offset, off_t len); +int __sys_posix_fadvise(int fd, off_t offset, off_t len, int advice); +int __sys_wait6(idtype_t idtype, id_t id, int * status, int options, struct __wrusage * wrusage, struct __siginfo * info); +int __sys_cap_rights_limit(int fd, cap_rights_t * rightsp); +int __sys_cap_ioctls_limit(int fd, const u_long * cmds, size_t ncmds); +ssize_t __sys_cap_ioctls_get(int fd, u_long * cmds, size_t maxcmds); +int __sys_cap_fcntls_limit(int fd, uint32_t fcntlrights); +int __sys_cap_fcntls_get(int fd, uint32_t * fcntlrightsp); +int __sys_bindat(int fd, int s, const struct sockaddr * name, __socklen_t namelen); +int __sys_connectat(int fd, int s, const struct sockaddr * name, __socklen_t namelen); +int __sys_chflagsat(int fd, const char * path, u_long flags, int atflag); +int __sys_accept4(int s, struct sockaddr * name, __socklen_t * anamelen, int flags); +int __sys_pipe2(int * fildes, int flags); +int __sys_aio_mlock(struct aiocb * aiocbp); +int __sys_procctl(idtype_t idtype, id_t id, int com, void * data); +int __sys_ppoll(struct pollfd * fds, u_int nfds, const struct timespec * ts, const sigset_t * set); +int __sys_futimens(int fd, const struct timespec * times); +int __sys_utimensat(int fd, const char * path, const struct timespec * times, int flag); +int __sys_fdatasync(int fd); +int __sys_fstat(int fd, struct stat * sb); +int __sys_fstatat(int fd, const char * path, struct stat * buf, int flag); +int __sys_fhstat(const struct fhandle * u_fhp, struct stat * sb); +ssize_t __sys_getdirentries(int fd, char * buf, size_t count, off_t * basep); +int __sys_statfs(const char * path, struct statfs * buf); +int __sys_fstatfs(int fd, struct statfs * buf); +int __sys_getfsstat(struct statfs * buf, long bufsize, int mode); +int __sys_fhstatfs(const struct fhandle * u_fhp, struct statfs * buf); +int __sys_mknodat(int fd, const char * path, mode_t mode, dev_t dev); +int __sys_kevent(int fd, const struct kevent * changelist, int nchanges, struct kevent * eventlist, int nevents, const struct timespec * timeout); +int __sys_cpuset_getdomain(cpulevel_t level, cpuwhich_t which, id_t id, size_t domainsetsize, domainset_t * mask, int * policy); +int __sys_cpuset_setdomain(cpulevel_t level, cpuwhich_t which, id_t id, size_t domainsetsize, domainset_t * mask, int policy); +int __sys_getrandom(void * buf, size_t buflen, unsigned int flags); +int __sys_getfhat(int fd, char * path, struct fhandle * fhp, int flags); +int __sys_fhlink(struct fhandle * fhp, const char * to); +int __sys_fhlinkat(struct fhandle * fhp, int tofd, const char * to); +int __sys_fhreadlink(struct fhandle * fhp, char * buf, size_t bufsize); +int __sys_funlinkat(int dfd, const char * path, int fd, int flag); +ssize_t __sys_copy_file_range(int infd, off_t * inoffp, int outfd, off_t * outoffp, size_t len, unsigned int flags); +int __sys___sysctlbyname(const char * name, size_t namelen, void * old, size_t * oldlenp, void * new, size_t newlen); +int __sys_shm_open2(const char * path, int flags, mode_t mode, int shmflags, const char * name); +int __sys_shm_rename(const char * path_from, const char * path_to, int flags); +int __sys_sigfastblock(int cmd, void * ptr); +int __sys___realpathat(int fd, const char * path, char * buf, size_t size, int flags); +int __sys_close_range(u_int lowfd, u_int highfd, int flags); +int __sys_rpctls_syscall(uint64_t socookie); +int __sys___specialfd(int type, const void * req, size_t len); +int __sys_aio_writev(struct aiocb * aiocbp); +int __sys_aio_readv(struct aiocb * aiocbp); +int __sys_fspacectl(int fd, int cmd, const struct spacectl_range * rqsr, int flags, struct spacectl_range * rmsr); +int __sys_sched_getcpu(void); +int __sys_swapoff(const char * name, u_int flags); +int __sys_kqueuex(u_int flags); +int __sys_membarrier(int cmd, unsigned flags, int cpu_id); +int __sys_timerfd_create(int clockid, int flags); +int __sys_timerfd_gettime(int fd, struct itimerspec * curr_value); +int __sys_timerfd_settime(int fd, int flags, const struct itimerspec * new_value, struct itimerspec * old_value); +int __sys_kcmp(pid_t pid1, pid_t pid2, int type, uintptr_t idx1, uintptr_t idx2); +int __sys_getrlimitusage(u_int which, int flags, rlim_t * res); +int __sys_fchroot(int fd); +int __sys_setcred(u_int flags, const struct setcred * wcred, size_t size); +int __sys_exterrctl(u_int op, u_int flags, void * ptr); +int __sys_inotify_add_watch_at(int fd, int dfd, const char * path, uint32_t mask); +int __sys_inotify_rm_watch(int fd, int wd); +int __sys_getgroups(int gidsetsize, gid_t * gidset); +int __sys_setgroups(int gidsetsize, const gid_t * gidset); +int __sys_jail_attach_jd(int fd); +int __sys_jail_remove_jd(int fd); +__END_DECLS + +#endif /* __LIBSYS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/a.out.h b/lib/libc/include/generic-freebsd/a.out.h index bd347bbe1ffd..1830d83aac92 100644 --- a/lib/libc/include/generic-freebsd/a.out.h +++ b/lib/libc/include/generic-freebsd/a.out.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)a.out.h 8.1 (Berkeley) 6/2/93 */ #ifndef _AOUT_H_ diff --git a/lib/libc/include/generic-freebsd/aio.h b/lib/libc/include/generic-freebsd/aio.h index c27e766737bf..6aa067394811 100644 --- a/lib/libc/include/generic-freebsd/aio.h +++ b/lib/libc/include/generic-freebsd/aio.h @@ -97,7 +97,7 @@ struct __aiocb_private { long status; long error; - void *kernelinfo; + void *spare; }; /* diff --git a/lib/libc/include/generic-freebsd/ar.h b/lib/libc/include/generic-freebsd/ar.h index 2e6599536cda..da952d735f6c 100644 --- a/lib/libc/include/generic-freebsd/ar.h +++ b/lib/libc/include/generic-freebsd/ar.h @@ -35,8 +35,6 @@ * 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. - * - * @(#)ar.h 8.2 (Berkeley) 1/21/94 */ #ifndef _AR_H_ diff --git a/lib/libc/include/generic-freebsd/arpa/ftp.h b/lib/libc/include/generic-freebsd/arpa/ftp.h index 9384fd498333..3309c27381e1 100644 --- a/lib/libc/include/generic-freebsd/arpa/ftp.h +++ b/lib/libc/include/generic-freebsd/arpa/ftp.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)ftp.h 8.1 (Berkeley) 6/2/93 */ #ifndef _ARPA_FTP_H_ diff --git a/lib/libc/include/generic-freebsd/arpa/inet.h b/lib/libc/include/generic-freebsd/arpa/inet.h index fc96ba8b5076..31377feb8388 100644 --- a/lib/libc/include/generic-freebsd/arpa/inet.h +++ b/lib/libc/include/generic-freebsd/arpa/inet.h @@ -52,7 +52,6 @@ */ /*% - * @(#)inet.h 8.1 (Berkeley) 6/2/93 * $Id: inet.h,v 1.3 2005/04/27 04:56:16 sra Exp $ */ diff --git a/lib/libc/include/generic-freebsd/arpa/telnet.h b/lib/libc/include/generic-freebsd/arpa/telnet.h index 62817ade3d6e..44cec222efbf 100644 --- a/lib/libc/include/generic-freebsd/arpa/telnet.h +++ b/lib/libc/include/generic-freebsd/arpa/telnet.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)telnet.h 8.2 (Berkeley) 12/15/93 */ #ifndef _ARPA_TELNET_H_ diff --git a/lib/libc/include/generic-freebsd/arpa/tftp.h b/lib/libc/include/generic-freebsd/arpa/tftp.h index c186e16b8ab6..69c0cb3ffa73 100644 --- a/lib/libc/include/generic-freebsd/arpa/tftp.h +++ b/lib/libc/include/generic-freebsd/arpa/tftp.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)tftp.h 8.1 (Berkeley) 6/2/93 */ #ifndef _ARPA_TFTP_H_ diff --git a/lib/libc/include/generic-freebsd/assert.h b/lib/libc/include/generic-freebsd/assert.h index 36080f57e29c..b7c7deb1206a 100644 --- a/lib/libc/include/generic-freebsd/assert.h +++ b/lib/libc/include/generic-freebsd/assert.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)assert.h 8.2 (Berkeley) 1/21/94 */ #include @@ -45,15 +43,22 @@ #undef assert #undef _assert +#undef __assert_unreachable #ifdef NDEBUG #define assert(e) ((void)0) #define _assert(e) ((void)0) +#if __BSD_VISIBLE +#define __assert_unreachable() __unreachable() +#endif /* __BSD_VISIBLE */ #else #define _assert(e) assert(e) #define assert(e) ((e) ? (void)0 : __assert(__func__, __FILE__, \ __LINE__, #e)) +#if __BSD_VISIBLE +#define __assert_unreachable() assert(0 && "unreachable segment reached") +#endif /* __BSD_VISIBLE */ #endif /* NDEBUG */ #ifndef _ASSERT_H_ diff --git a/lib/libc/include/generic-freebsd/bsm/audit.h b/lib/libc/include/generic-freebsd/bsm/audit.h index abdacf6b1754..8ac621e6931b 100644 --- a/lib/libc/include/generic-freebsd/bsm/audit.h +++ b/lib/libc/include/generic-freebsd/bsm/audit.h @@ -342,4 +342,4 @@ au_asid_t audit_session_join(mach_port_name_t port); __END_DECLS -#endif /* !_BSM_AUDIT_H */ \ No newline at end of file +#endif /* !_BSM_AUDIT_H */ diff --git a/lib/libc/include/generic-freebsd/bsm/audit_domain.h b/lib/libc/include/generic-freebsd/bsm/audit_domain.h index d2cbe5e48bff..a05dc653fe2f 100644 --- a/lib/libc/include/generic-freebsd/bsm/audit_domain.h +++ b/lib/libc/include/generic-freebsd/bsm/audit_domain.h @@ -111,4 +111,4 @@ */ #define BSM_PF_UNKNOWN 700 /* OpenBSM-specific. */ -#endif /* !_BSM_AUDIT_DOMAIN_H_ */ \ No newline at end of file +#endif /* !_BSM_AUDIT_DOMAIN_H_ */ diff --git a/lib/libc/include/generic-freebsd/bsm/audit_errno.h b/lib/libc/include/generic-freebsd/bsm/audit_errno.h index 99d6be05f196..2c27bd905cb4 100644 --- a/lib/libc/include/generic-freebsd/bsm/audit_errno.h +++ b/lib/libc/include/generic-freebsd/bsm/audit_errno.h @@ -214,4 +214,4 @@ */ #define BSM_ERRNO_UNKNOWN 250 /* OpenBSM-specific. */ -#endif /* !_BSM_AUDIT_ERRNO_H_ */ \ No newline at end of file +#endif /* !_BSM_AUDIT_ERRNO_H_ */ diff --git a/lib/libc/include/generic-freebsd/bsm/audit_fcntl.h b/lib/libc/include/generic-freebsd/bsm/audit_fcntl.h index 49763107eca2..47af4902936a 100644 --- a/lib/libc/include/generic-freebsd/bsm/audit_fcntl.h +++ b/lib/libc/include/generic-freebsd/bsm/audit_fcntl.h @@ -137,4 +137,4 @@ #define BSM_F_UNKNOWN 0xFFFF -#endif /* !_BSM_AUDIT_FCNTL_H_ */ \ No newline at end of file +#endif /* !_BSM_AUDIT_FCNTL_H_ */ diff --git a/lib/libc/include/generic-freebsd/bsm/audit_internal.h b/lib/libc/include/generic-freebsd/bsm/audit_internal.h index 1de62cf9d4e1..700e4b268857 100644 --- a/lib/libc/include/generic-freebsd/bsm/audit_internal.h +++ b/lib/libc/include/generic-freebsd/bsm/audit_internal.h @@ -114,4 +114,4 @@ typedef struct au_record au_record_t; #define ADD_STRING(loc, data, size) ADD_MEM(loc, data, size) -#endif /* !_AUDIT_INTERNAL_H_ */ \ No newline at end of file +#endif /* !_AUDIT_INTERNAL_H_ */ diff --git a/lib/libc/include/generic-freebsd/bsm/audit_kevents.h b/lib/libc/include/generic-freebsd/bsm/audit_kevents.h index e9c03cac0ef2..9381396f247c 100644 --- a/lib/libc/include/generic-freebsd/bsm/audit_kevents.h +++ b/lib/libc/include/generic-freebsd/bsm/audit_kevents.h @@ -662,6 +662,8 @@ #define AUE_AIO_READV 43268 /* FreeBSD-specific. */ #define AUE_FSPACECTL 43269 /* FreeBSD-specific. */ #define AUE_TIMERFD 43270 /* FreeBSD/Linux. */ +#define AUE_SETCRED 43271 /* FreeBSD-specific. */ +#define AUE_INOTIFY 43272 /* FreeBSD/Linux. */ /* * Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the @@ -848,4 +850,4 @@ #define AUE_WORKQOPEN AUE_NULL #define AUE_WORKQOPS AUE_NULL -#endif /* !_BSM_AUDIT_KEVENTS_H_ */ \ No newline at end of file +#endif /* !_BSM_AUDIT_KEVENTS_H_ */ diff --git a/lib/libc/include/generic-freebsd/bsm/audit_record.h b/lib/libc/include/generic-freebsd/bsm/audit_record.h index b852b002edcb..2ad0e954997f 100644 --- a/lib/libc/include/generic-freebsd/bsm/audit_record.h +++ b/lib/libc/include/generic-freebsd/bsm/audit_record.h @@ -308,4 +308,4 @@ u_short au_socket_type_to_bsm(int local_socket_type); __END_DECLS -#endif /* ! _BSM_AUDIT_RECORD_H_ */ \ No newline at end of file +#endif /* ! _BSM_AUDIT_RECORD_H_ */ diff --git a/lib/libc/include/generic-freebsd/bsm/audit_socket_type.h b/lib/libc/include/generic-freebsd/bsm/audit_socket_type.h index b64992a062af..5a7a742f26c1 100644 --- a/lib/libc/include/generic-freebsd/bsm/audit_socket_type.h +++ b/lib/libc/include/generic-freebsd/bsm/audit_socket_type.h @@ -43,4 +43,4 @@ #define BSM_SOCK_UNKNOWN 500 -#endif /* !_BSM_AUDIT_SOCKET_TYPE_H_ */ \ No newline at end of file +#endif /* !_BSM_AUDIT_SOCKET_TYPE_H_ */ diff --git a/lib/libc/include/generic-freebsd/cam/cam.h b/lib/libc/include/generic-freebsd/cam/cam.h index c51675755935..dac54a16ac63 100644 --- a/lib/libc/include/generic-freebsd/cam/cam.h +++ b/lib/libc/include/generic-freebsd/cam/cam.h @@ -35,9 +35,9 @@ #include "opt_cam.h" #endif -#include #ifndef _KERNEL #include +#include #endif typedef u_int path_id_t; @@ -350,6 +350,11 @@ typedef enum { CAM_EAF_PRINT_RESULT = 0x20 } cam_error_ata_flags; +typedef enum { + CAM_ENF_PRINT_NONE = 0x00, + CAM_ENF_PRINT_STATUS = 0x10, +} cam_error_nvme_flags; + typedef enum { CAM_STRVIS_FLAG_NONE = 0x00, CAM_STRVIS_FLAG_NONASCII_MASK = 0x03, diff --git a/lib/libc/include/generic-freebsd/cam/cam_ccb.h b/lib/libc/include/generic-freebsd/cam/cam_ccb.h index 9cfb694452bb..93d5d843d834 100644 --- a/lib/libc/include/generic-freebsd/cam/cam_ccb.h +++ b/lib/libc/include/generic-freebsd/cam/cam_ccb.h @@ -32,7 +32,6 @@ #define _CAM_CAM_CCB_H 1 #include -#include #include #include #ifndef _KERNEL @@ -298,15 +297,18 @@ typedef enum { XPORT_SRP, /* SCSI RDMA Protocol */ XPORT_NVME, /* NVMe over PCIe */ XPORT_MMCSD, /* MMC, SD, SDIO card */ + XPORT_NVMF, /* NVMe over Fabrics */ + XPORT_UFSHCI, /* Universal Flash Storage Host Interface */ } cam_xport; -#define XPORT_IS_NVME(t) ((t) == XPORT_NVME) +#define XPORT_IS_NVME(t) ((t) == XPORT_NVME || (t) == XPORT_NVMF) #define XPORT_IS_ATA(t) ((t) == XPORT_ATA || (t) == XPORT_SATA) #define XPORT_IS_SCSI(t) ((t) != XPORT_UNKNOWN && \ (t) != XPORT_UNSPECIFIED && \ !XPORT_IS_ATA(t) && !XPORT_IS_NVME(t)) #define XPORT_DEVSTAT_TYPE(t) (XPORT_IS_ATA(t) ? DEVSTAT_TYPE_IF_IDE : \ XPORT_IS_SCSI(t) ? DEVSTAT_TYPE_IF_SCSI : \ + XPORT_IS_NVME(t) ? DEVSTAT_TYPE_IF_NVME : \ DEVSTAT_TYPE_IF_OTHER) #define PROTO_VERSION_UNKNOWN (UINT_MAX - 1) @@ -653,6 +655,12 @@ struct ccb_pathinq_settings_nvme { _Static_assert(sizeof(struct ccb_pathinq_settings_nvme) == 64, "ccb_pathinq_settings_nvme too big"); +struct ccb_pathinq_settings_nvmf { + uint32_t nsid; /* Namespace ID for this path */ + uint8_t trtype; + char dev_name[NVME_DEV_NAME_LEN]; /* nvme controller dev name for this device */ +}; + #define PATHINQ_SETTINGS_SIZE 128 struct ccb_pathinq { @@ -684,6 +692,7 @@ struct ccb_pathinq { struct ccb_pathinq_settings_fc fc; struct ccb_pathinq_settings_sas sas; struct ccb_pathinq_settings_nvme nvme; + struct ccb_pathinq_settings_nvmf nvmf; char ccb_pathinq_settings_opaque[PATHINQ_SETTINGS_SIZE]; } xport_specific; u_int maxio; /* Max supported I/O size, in bytes. */ @@ -1050,6 +1059,31 @@ struct ccb_trans_settings_nvme uint8_t max_speed; /* PCIe generation for each lane */ }; +struct ccb_trans_settings_nvmf +{ + u_int valid; /* Which fields to honor */ +#define CTS_NVMF_VALID_TRTYPE 0x01 + uint8_t trtype; +}; + +struct ccb_trans_settings_ufshci +{ + u_int valid; /* Which fields to honor */ + /* + * Ensure the validity of the information for the Unipro link + * (GEAR, SPEED, LANE) + */ +#define CTS_UFSHCI_VALID_LINK 0x01 + uint32_t speed; + uint8_t hs_gear; /* High Speed Gear (G1, G2, G3...) */ + uint8_t tx_lanes; + uint8_t rx_lanes; + uint8_t max_hs_gear; /* Maximum HS Gear */ + uint8_t max_tx_lanes; + uint8_t max_rx_lanes; +}; + + #include struct ccb_trans_settings_mmc { struct mmc_ios ios; @@ -1122,6 +1156,8 @@ struct ccb_trans_settings { struct ccb_trans_settings_pata ata; struct ccb_trans_settings_sata sata; struct ccb_trans_settings_nvme nvme; + struct ccb_trans_settings_nvmf nvmf; + struct ccb_trans_settings_ufshci ufshci; } xport_specific; }; @@ -1488,6 +1524,7 @@ cam_fill_mmcio(struct ccb_mmcio *mmcio, uint32_t retries, mmcio->cmd.opcode = mmc_opcode; mmcio->cmd.arg = mmc_arg; mmcio->cmd.flags = mmc_flags; + mmcio->cmd.error = 0; mmcio->stop.opcode = 0; mmcio->stop.arg = 0; mmcio->stop.flags = 0; diff --git a/lib/libc/include/generic-freebsd/cam/cam_debug.h b/lib/libc/include/generic-freebsd/cam/cam_debug.h index 42694db2607a..33c248cbd3d0 100644 --- a/lib/libc/include/generic-freebsd/cam/cam_debug.h +++ b/lib/libc/include/generic-freebsd/cam/cam_debug.h @@ -81,57 +81,46 @@ extern uint32_t cam_dflags; /* Printf delay value (to prevent scrolling) */ extern uint32_t cam_debug_delay; -/* Debugging macros. */ -#define CAM_DEBUGGED(path, flag) \ - (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags) \ - && (cam_dpath != NULL) \ - && (xpt_path_comp(cam_dpath, path) >= 0) \ - && (xpt_path_comp(cam_dpath, path) < 2)) - -#define CAM_DEBUG(path, flag, printfargs) \ - if (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags) \ - && (cam_dpath != NULL) \ - && (xpt_path_comp(cam_dpath, path) >= 0) \ - && (xpt_path_comp(cam_dpath, path) < 2)) { \ - xpt_print_path(path); \ - printf printfargs; \ - if (cam_debug_delay != 0) \ - DELAY(cam_debug_delay); \ - } +/* Helper routines -- helps conserve stack */ +struct cam_ed; +void xpt_cam_path_debug(struct cam_path *path, const char *fmt, ...); +void xpt_cam_dev_debug(struct cam_ed *dev, const char *fmt, ...); +void xpt_cam_debug(const char *fmt, ...); -#define CAM_DEBUG_DEV(dev, flag, printfargs) \ - if (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags) \ - && (cam_dpath != NULL) \ - && (xpt_path_comp_dev(cam_dpath, dev) >= 0) \ - && (xpt_path_comp_dev(cam_dpath, dev) < 2)) { \ - xpt_print_device(dev); \ - printf printfargs; \ - if (cam_debug_delay != 0) \ - DELAY(cam_debug_delay); \ +/* Stupid macro to remove a layer of parens */ +#define _CAM_X(...) __VA_ARGS__ + +/* Debugging macros. */ +#define CAM_DEBUGGED(path, flag) \ + (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags) \ + && (cam_dpath != NULL) \ + && (xpt_path_comp(cam_dpath, (path)) >= 0) \ + && (xpt_path_comp(cam_dpath, (path)) < 2)) + +#define CAM_DEBUG(path, flag, printfargs) \ + if (CAM_DEBUGGED(path, flag)) { \ + xpt_cam_path_debug(path, _CAM_X printfargs); \ } -#define CAM_DEBUG_PRINT(flag, printfargs) \ - if (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags)) { \ - printf("cam_debug: "); \ - printf printfargs; \ - if (cam_debug_delay != 0) \ - DELAY(cam_debug_delay); \ +#define CAM_DEBUG_DEV(dev, flag, printfargs) \ + if (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags) \ + && (cam_dpath != NULL) \ + && (xpt_path_comp_dev(cam_dpath, (dev)) >= 0) \ + && (xpt_path_comp_dev(cam_dpath, (dev)) < 2)) { \ + xpt_cam_dev_debug(dev, _CAM_X printfargs); \ } -#define CAM_DEBUG_PATH_PRINT(flag, path, printfargs) \ - if (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags)) { \ - xpt_print(path, "cam_debug: "); \ - printf printfargs; \ - if (cam_debug_delay != 0) \ - DELAY(cam_debug_delay); \ +#define CAM_DEBUG_PRINT(flag, printfargs) \ + if (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags)) { \ + xpt_cam_debug(_CAM_X printfargs); \ } #else /* !_KERNEL */ #define CAM_DEBUGGED(A, B) 0 #define CAM_DEBUG(A, B, C) +#define CAM_DEBUG_DEV(A, B, C) #define CAM_DEBUG_PRINT(A, B) -#define CAM_DEBUG_PATH_PRINT(A, B, C) #endif /* _KERNEL */ diff --git a/lib/libc/include/generic-freebsd/cam/cam_iosched.h b/lib/libc/include/generic-freebsd/cam/cam_iosched.h index 332152858e51..3c9e3cadc121 100644 --- a/lib/libc/include/generic-freebsd/cam/cam_iosched.h +++ b/lib/libc/include/generic-freebsd/cam/cam_iosched.h @@ -79,8 +79,10 @@ cam_iosched_sbintime_t(uintptr_t delta) } typedef void (*cam_iosched_latfcn_t)(void *, sbintime_t, struct bio *); +typedef void (*cam_iosched_schedule_t)(struct cam_periph *periph); -int cam_iosched_init(struct cam_iosched_softc **, struct cam_periph *periph); +int cam_iosched_init(struct cam_iosched_softc **, struct cam_periph *periph, + const struct disk *dp, cam_iosched_schedule_t schedfnp); void cam_iosched_fini(struct cam_iosched_softc *); void cam_iosched_sysctl_init(struct cam_iosched_softc *, struct sysctl_ctx_list *, struct sysctl_oid *); struct bio *cam_iosched_next_trim(struct cam_iosched_softc *isc); diff --git a/lib/libc/include/generic-freebsd/cam/cam_sim.h b/lib/libc/include/generic-freebsd/cam/cam_sim.h index 07db069f9f69..3a19639a5c3d 100644 --- a/lib/libc/include/generic-freebsd/cam/cam_sim.h +++ b/lib/libc/include/generic-freebsd/cam/cam_sim.h @@ -60,15 +60,6 @@ struct cam_sim * cam_sim_alloc(sim_action_func sim_action, int max_dev_transactions, int max_tagged_dev_transactions, struct cam_devq *queue); -struct cam_sim * cam_sim_alloc_dev(sim_action_func sim_action, - sim_poll_func sim_poll, - const char *sim_name, - void *softc, - device_t dev, - struct mtx *mtx, - int max_dev_transactions, - int max_tagged_dev_transactions, - struct cam_devq *queue); void cam_sim_free(struct cam_sim *sim, int free_devq); void cam_sim_hold(struct cam_sim *sim); void cam_sim_release(struct cam_sim *sim); diff --git a/lib/libc/include/generic-freebsd/cam/cam_xpt.h b/lib/libc/include/generic-freebsd/cam/cam_xpt.h index 3cfb6148c3b0..6d25ebd507c0 100644 --- a/lib/libc/include/generic-freebsd/cam/cam_xpt.h +++ b/lib/libc/include/generic-freebsd/cam/cam_xpt.h @@ -33,16 +33,15 @@ #define _CAM_CAM_XPT_H 1 #ifdef _KERNEL -#include #include #endif +#include /* Forward Declarations */ union ccb; struct cam_periph; struct cam_ed; struct cam_sim; -struct sbuf; /* * Definition of a CAM path. Paths are created from bus, target, and lun ids @@ -113,7 +112,6 @@ struct cam_sim *xpt_path_sim(struct cam_path *path); struct cam_periph *xpt_path_periph(struct cam_path *path); device_t xpt_path_sim_device(const struct cam_path *path); void xpt_print_path(struct cam_path *path); -void xpt_print_device(struct cam_ed *device); void xpt_print(struct cam_path *path, const char *fmt, ...); void xpt_async(uint32_t async_code, struct cam_path *path, void *async_arg); @@ -147,19 +145,31 @@ uint32_t xpt_poll_setup(union ccb *start_ccb); void xpt_sim_poll(struct cam_sim *sim); /* - * Perform a path inquiry at the request priority. The bzero may be - * unnecessary. + * Perform a path inquiry. bzero may be redundant for allocated CCBs, but for + * the on-stack CCBs it's required. */ static inline void xpt_path_inq(struct ccb_pathinq *cpi, struct cam_path *path) { - bzero(cpi, sizeof(*cpi)); - xpt_setup_ccb(&cpi->ccb_h, path, CAM_PRIORITY_NORMAL); + xpt_setup_ccb(&cpi->ccb_h, path, CAM_PRIORITY_NONE); cpi->ccb_h.func_code = XPT_PATH_INQ; xpt_action((union ccb *)cpi); } +/* + * Perform get device type. bzero may be redundant for allocated CCBs, but for + * the on-stack CCBs it's required. + */ +static inline void +xpt_gdev_type(struct ccb_getdev *cgd, struct cam_path *path) +{ + bzero(cgd, sizeof(*cgd)); + xpt_setup_ccb(&cgd->ccb_h, path, CAM_PRIORITY_NONE); + cgd->ccb_h.func_code = XPT_GDEV_TYPE; + xpt_action((union ccb *)cgd); +} + #endif /* _KERNEL */ #endif /* _CAM_CAM_XPT_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/cam/nvme/nvme_all.h b/lib/libc/include/generic-freebsd/cam/nvme/nvme_all.h index 6ba15263c01a..694439e4f50e 100644 --- a/lib/libc/include/generic-freebsd/cam/nvme/nvme_all.h +++ b/lib/libc/include/generic-freebsd/cam/nvme/nvme_all.h @@ -42,10 +42,10 @@ struct sbuf; void nvme_print_ident(const struct nvme_controller_data *, const struct nvme_namespace_data *, struct sbuf *); void nvme_print_ident_short(const struct nvme_controller_data *, const struct nvme_namespace_data *, struct sbuf *); -const char *nvme_op_string(const struct nvme_command *, int admin); -const char *nvme_cmd_string(const struct nvme_command *, char *, size_t); void nvme_cmd_sbuf(const struct nvme_command *, struct sbuf *sb); int nvme_command_sbuf(struct ccb_nvmeio *nvmeio, struct sbuf *sb); +const char *nvme_command_string(struct ccb_nvmeio *nvmeio, char *, size_t); +int nvme_status_sbuf(struct ccb_nvmeio *nvmeio, struct sbuf *sb); const void *nvme_get_identify_cntrl(struct cam_periph *); const void *nvme_get_identify_ns(struct cam_periph *); diff --git a/lib/libc/include/generic-freebsd/cam/scsi/scsi_all.h b/lib/libc/include/generic-freebsd/cam/scsi/scsi_all.h index f09d991bce46..7a96a072e831 100644 --- a/lib/libc/include/generic-freebsd/cam/scsi/scsi_all.h +++ b/lib/libc/include/generic-freebsd/cam/scsi/scsi_all.h @@ -1,18 +1,12 @@ -/*- - * Largely written by Julian Elischer (julian@tfs.com) - * for TRW Financial Systems. - * - * TRW Financial Systems, in accordance with their agreement with Carnegie - * Mellon University, makes this software available to CMU to distribute - * or use in any manner that they see fit as long as this message is kept with - * the software. For this reason TFS also grants any other persons or - * organisations permission to use or modify this software. +/* + * Copyright (c) 1997-2017 Kenneth D. Merry + * Copyright (c) 2012-2020 Alexander Motin + * Copyright (c) 1997-2011 Justin T. Gibbs * - * TFS supplies this software to be publicly redistributed - * on the understanding that TFS is not responsible for the correct - * functioning of this software in any circumstances. + * SPDX-License-Identifier: BSD-2-Clause * - * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 + * Original scsi_all.h from 386BSD was by Julian Elischer at TRW Financial + * Services has been transformed into a new work by subsequent contributors. */ /* @@ -22,10 +16,9 @@ #ifndef _SCSI_SCSI_ALL_H #define _SCSI_SCSI_ALL_H 1 -#include #ifdef _KERNEL #include -#include +#include #else #include #endif diff --git a/lib/libc/include/generic-freebsd/cam/scsi/scsi_ch.h b/lib/libc/include/generic-freebsd/cam/scsi/scsi_ch.h index e268a926dd33..6531075c8314 100644 --- a/lib/libc/include/generic-freebsd/cam/scsi/scsi_ch.h +++ b/lib/libc/include/generic-freebsd/cam/scsi/scsi_ch.h @@ -64,7 +64,6 @@ #ifndef _SCSI_SCSI_CH_H #define _SCSI_SCSI_CH_H 1 -#include /* * SCSI command format diff --git a/lib/libc/include/generic-freebsd/cam/scsi/scsi_da.h b/lib/libc/include/generic-freebsd/cam/scsi/scsi_da.h index f53f4c6b44e0..05cccfcf3ff1 100644 --- a/lib/libc/include/generic-freebsd/cam/scsi/scsi_da.h +++ b/lib/libc/include/generic-freebsd/cam/scsi/scsi_da.h @@ -50,7 +50,6 @@ #ifndef _SCSI_SCSI_DA_H #define _SCSI_SCSI_DA_H 1 -#include struct scsi_rezero_unit { diff --git a/lib/libc/include/generic-freebsd/cam/scsi/scsi_sa.h b/lib/libc/include/generic-freebsd/cam/scsi/scsi_sa.h index 4b1e905001fe..be4bc6fe3593 100644 --- a/lib/libc/include/generic-freebsd/cam/scsi/scsi_sa.h +++ b/lib/libc/include/generic-freebsd/cam/scsi/scsi_sa.h @@ -33,7 +33,6 @@ #ifndef _SCSI_SCSI_SA_H #define _SCSI_SCSI_SA_H 1 -#include struct scsi_read_block_limits { diff --git a/lib/libc/include/generic-freebsd/crypto/cryptodev.h b/lib/libc/include/generic-freebsd/crypto/cryptodev.h index d43dc925e80a..46716b60f873 100644 --- a/lib/libc/include/generic-freebsd/crypto/cryptodev.h +++ b/lib/libc/include/generic-freebsd/crypto/cryptodev.h @@ -433,7 +433,7 @@ struct cryptop { int crp_flags; #define CRYPTO_F_CBIMM 0x0010 /* Do callback immediately */ -#define CRYPTO_F_DONE 0x0020 /* Operation completed */ +#define CRYPTO_F_DONE 0x0020 /* Deprecated, do not use */ #define CRYPTO_F_CBIFSYNC 0x0040 /* Do CBIMM if op is synchronous */ #define CRYPTO_F_ASYNC_ORDERED 0x0100 /* Completions must happen in order */ #define CRYPTO_F_IV_SEPARATE 0x0200 /* Use crp_iv[] as IV. */ diff --git a/lib/libc/include/generic-freebsd/ctype.h b/lib/libc/include/generic-freebsd/ctype.h index db8e17fbe4ed..9ba19981b78c 100644 --- a/lib/libc/include/generic-freebsd/ctype.h +++ b/lib/libc/include/generic-freebsd/ctype.h @@ -35,8 +35,6 @@ * 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. - * - * @(#)ctype.h 8.4 (Berkeley) 1/21/94 */ #ifndef _CTYPE_H_ diff --git a/lib/libc/include/generic-freebsd/db.h b/lib/libc/include/generic-freebsd/db.h index 1447927ec334..dba042d910f1 100644 --- a/lib/libc/include/generic-freebsd/db.h +++ b/lib/libc/include/generic-freebsd/db.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)db.h 8.7 (Berkeley) 6/16/94 */ #ifndef _DB_H_ diff --git a/lib/libc/include/generic-freebsd/dev/ciss/cissreg.h b/lib/libc/include/generic-freebsd/dev/ciss/cissreg.h index 8939fd796fa3..e4d6adbe392e 100644 --- a/lib/libc/include/generic-freebsd/dev/ciss/cissreg.h +++ b/lib/libc/include/generic-freebsd/dev/ciss/cissreg.h @@ -684,7 +684,7 @@ struct ciss_bmic_id_table { u_int8_t percent_write_cache; /* Percent of memory allocated to write cache */ u_int16_t daughterboard_size_mb; /* Total size (MB) of cache board */ u_int8_t cache_batter_count; /* Number of cache batteries */ - u_int16_t total_controller_mem_mb; /* Total size (MB) of atttached memory */ + u_int16_t total_controller_mem_mb; /* Total size (MB) of attached memory */ u_int8_t more_controller_flags; /* Additional controller flags byte */ u_int8_t x_board_host_i2c_rev; /* 2nd byte of 3 byte autorev field */ u_int8_t battery_pic_rev; /* BBWC PIC revision */ diff --git a/lib/libc/include/generic-freebsd/dev/ciss/cissvar.h b/lib/libc/include/generic-freebsd/dev/ciss/cissvar.h index 10cb78629883..eb96e442bf56 100644 --- a/lib/libc/include/generic-freebsd/dev/ciss/cissvar.h +++ b/lib/libc/include/generic-freebsd/dev/ciss/cissvar.h @@ -184,7 +184,7 @@ struct ciss_softc { /* bus connections */ device_t ciss_dev; /* bus attachment */ - struct cdev *ciss_dev_t; /* control device */ + struct cdev *ciss_dev_t; /* control device */ struct resource *ciss_regs_resource; /* register interface window */ int ciss_regs_rid; /* resource ID */ @@ -236,6 +236,7 @@ struct ciss_softc int ciss_max_bus_number; /* maximum bus number */ int ciss_max_logical_bus; int ciss_max_physical_bus; + int ciss_max_physical_target; /* highest physical target number */ struct cam_devq *ciss_cam_devq; struct cam_sim **ciss_cam_sim; diff --git a/lib/libc/include/generic-freebsd/dev/firewire/firewirereg.h b/lib/libc/include/generic-freebsd/dev/firewire/firewirereg.h index dfb973308a0d..01381dce637a 100644 --- a/lib/libc/include/generic-freebsd/dev/firewire/firewirereg.h +++ b/lib/libc/include/generic-freebsd/dev/firewire/firewirereg.h @@ -293,7 +293,7 @@ extern int firewire_debug; extern devclass_t firewire_devclass; extern int firewire_phydma_enable; -#define FWPRI ((PZERO + 8) | PCATCH) +#define FWPRI (PWAIT | PCATCH) #define CALLOUT_INIT(x) callout_init(x, 1 /* mpsafe */) diff --git a/lib/libc/include/generic-freebsd/dev/hid/hid.h b/lib/libc/include/generic-freebsd/dev/hid/hid.h index b3017cdab1c8..8e55116085e3 100644 --- a/lib/libc/include/generic-freebsd/dev/hid/hid.h +++ b/lib/libc/include/generic-freebsd/dev/hid/hid.h @@ -57,6 +57,7 @@ #define HUP_SCALE 0x008c #define HUP_CAMERA_CONTROL 0x0090 #define HUP_ARCADE 0x0091 +#define HUP_FIDO 0xf1d0 #define HUP_MICROSOFT 0xff00 /* Usages, generic desktop */ @@ -161,6 +162,9 @@ #define HUC_HEADPHONE 0x0005 #define HUC_AC_PAN 0x0238 +/* Usages, FIDO */ +#define HUF_U2FHID 0x0001 + #define HID_USAGE2(p,u) (((p) << 16) | (u)) #define HID_GET_USAGE(u) ((u) & 0xffff) #define HID_GET_USAGE_PAGE(u) (((u) >> 16) & 0xffff) @@ -233,31 +237,31 @@ struct hid_location { struct hid_item { /* Global */ - int32_t _usage_page; + uint32_t _usage_page; int32_t logical_minimum; int32_t logical_maximum; int32_t physical_minimum; int32_t physical_maximum; - int32_t unit_exponent; - int32_t unit; - int32_t report_ID; + uint32_t unit_exponent; + uint32_t unit; + uint32_t report_ID; /* Local */ int nusages; union { - int32_t usage; - int32_t usages[HID_ITEM_MAXUSAGE]; + uint32_t usage; + uint32_t usages[HID_ITEM_MAXUSAGE]; }; - int32_t usage_minimum; - int32_t usage_maximum; - int32_t designator_index; - int32_t designator_minimum; - int32_t designator_maximum; - int32_t string_index; - int32_t string_minimum; - int32_t string_maximum; - int32_t set_delimiter; + uint32_t usage_minimum; + uint32_t usage_maximum; + uint32_t designator_index; + uint32_t designator_minimum; + uint32_t designator_maximum; + uint32_t string_index; + uint32_t string_minimum; + uint32_t string_maximum; + uint32_t set_delimiter; /* Misc */ - int32_t collection; + uint32_t collection; int collevel; enum hid_kind kind; uint32_t flags; diff --git a/lib/libc/include/generic-freebsd/dev/hid/hidraw.h b/lib/libc/include/generic-freebsd/dev/hid/hidraw.h index c7df23a8e622..f36e3d46a0ad 100644 --- a/lib/libc/include/generic-freebsd/dev/hid/hidraw.h +++ b/lib/libc/include/generic-freebsd/dev/hid/hidraw.h @@ -92,5 +92,9 @@ struct hidraw_devinfo { #define HIDIOCSFEATURE(len) _IOC(IOC_IN, 'U', 35, len) #define HIDIOCGFEATURE(len) _IOC(IOC_INOUT, 'U', 36, len) #define HIDIOCGRAWUNIQ(len) _IOC(IOC_OUT, 'U', 37, len) +#define HIDIOCSINPUT(len) _IOC(IOC_IN, 'U', 38, len) +#define HIDIOCGINPUT(len) _IOC(IOC_INOUT, 'U', 39, len) +#define HIDIOCSOUTPUT(len) _IOC(IOC_IN, 'U', 40, len) +#define HIDIOCGOUTPUT(len) _IOC(IOC_INOUT, 'U', 41, len) #endif /* _HID_HIDRAW_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/dev/hwpmc/hwpmc_amd.h b/lib/libc/include/generic-freebsd/dev/hwpmc/hwpmc_amd.h index dcdd27061277..e2bf15f734cf 100644 --- a/lib/libc/include/generic-freebsd/dev/hwpmc/hwpmc_amd.h +++ b/lib/libc/include/generic-freebsd/dev/hwpmc/hwpmc_amd.h @@ -31,7 +31,7 @@ #ifndef _DEV_HWPMC_AMD_H_ #define _DEV_HWPMC_AMD_H_ 1 -/* AMD K7 and K8 PMCs */ +/* AMD K8 PMCs */ #define AMD_PMC_EVSEL_0 0xC0010000 #define AMD_PMC_EVSEL_1 0xC0010001 diff --git a/lib/libc/include/generic-freebsd/dev/hwpmc/hwpmc_arm64.h b/lib/libc/include/generic-freebsd/dev/hwpmc/hwpmc_arm64.h index 21127f2149c5..45ef8793c042 100644 --- a/lib/libc/include/generic-freebsd/dev/hwpmc/hwpmc_arm64.h +++ b/lib/libc/include/generic-freebsd/dev/hwpmc/hwpmc_arm64.h @@ -42,7 +42,7 @@ #ifdef _KERNEL /* MD extension for 'struct pmc' */ struct pmc_md_arm64_pmc { - uint32_t pm_arm64_evsel; + uint64_t pm_arm64_evsel; }; #endif /* _KERNEL */ #endif /* _DEV_HWPMC_ARMV8_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/dev/hwpmc/hwpmc_core.h b/lib/libc/include/generic-freebsd/dev/hwpmc/hwpmc_core.h index 004fd428cec2..502ea6505205 100644 --- a/lib/libc/include/generic-freebsd/dev/hwpmc/hwpmc_core.h +++ b/lib/libc/include/generic-freebsd/dev/hwpmc/hwpmc_core.h @@ -198,11 +198,9 @@ int pmc_core_initialize(struct pmc_mdep *_md, int _maxcpu, void pmc_core_finalize(struct pmc_mdep *_md); int pmc_iaf_initialize(struct pmc_mdep *_md, int _maxcpu, int _npmc, int _width); -void pmc_iaf_finalize(struct pmc_mdep *_md); int pmc_iap_initialize(struct pmc_mdep *_md, int _maxcpu, int _npmc, int _width, int _flags); -void pmc_iap_finalize(struct pmc_mdep *_md); #endif /* _KERNEL */ #endif /* _DEV_HWPMC_CORE_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/dev/hwpmc/pmc_events.h b/lib/libc/include/generic-freebsd/dev/hwpmc/pmc_events.h index c8d57c685fb8..84b16e150ccd 100644 --- a/lib/libc/include/generic-freebsd/dev/hwpmc/pmc_events.h +++ b/lib/libc/include/generic-freebsd/dev/hwpmc/pmc_events.h @@ -62,39 +62,6 @@ __PMC_EV_ALIAS("cycles", TSC_TSC) #define PMC_EV_SOFT_FIRST 0x20000 #define PMC_EV_SOFT_LAST (PMC_EV_SOFT_FIRST + PMC_EV_DYN_COUNT - 1) -/* - * AMD K7 Events, from "The AMD Athlon(tm) Processor x86 Code - * Optimization Guide" [Doc#22007K, Feb 2002] - */ - -#define __PMC_EV_K7() \ -__PMC_EV(K7, DC_ACCESSES) \ -__PMC_EV(K7, DC_MISSES) \ -__PMC_EV(K7, DC_REFILLS_FROM_L2) \ -__PMC_EV(K7, DC_REFILLS_FROM_SYSTEM) \ -__PMC_EV(K7, DC_WRITEBACKS) \ -__PMC_EV(K7, L1_DTLB_MISS_AND_L2_DTLB_HITS) \ -__PMC_EV(K7, L1_AND_L2_DTLB_MISSES) \ -__PMC_EV(K7, MISALIGNED_REFERENCES) \ -__PMC_EV(K7, IC_FETCHES) \ -__PMC_EV(K7, IC_MISSES) \ -__PMC_EV(K7, L1_ITLB_MISSES) \ -__PMC_EV(K7, L1_L2_ITLB_MISSES) \ -__PMC_EV(K7, RETIRED_INSTRUCTIONS) \ -__PMC_EV(K7, RETIRED_OPS) \ -__PMC_EV(K7, RETIRED_BRANCHES) \ -__PMC_EV(K7, RETIRED_BRANCHES_MISPREDICTED) \ -__PMC_EV(K7, RETIRED_TAKEN_BRANCHES) \ -__PMC_EV(K7, RETIRED_TAKEN_BRANCHES_MISPREDICTED) \ -__PMC_EV(K7, RETIRED_FAR_CONTROL_TRANSFERS) \ -__PMC_EV(K7, RETIRED_RESYNC_BRANCHES) \ -__PMC_EV(K7, INTERRUPTS_MASKED_CYCLES) \ -__PMC_EV(K7, INTERRUPTS_MASKED_WHILE_PENDING_CYCLES) \ -__PMC_EV(K7, HARDWARE_INTERRUPTS) - -#define PMC_EV_K7_FIRST PMC_EV_K7_DC_ACCESSES -#define PMC_EV_K7_LAST PMC_EV_K7_HARDWARE_INTERRUPTS - /* AMD K8 PMCs */ #define __PMC_EV_K8() \ @@ -2431,7 +2398,7 @@ __PMC_EV_ALIAS("unhalted-reference-cycles", IAF_CPU_CLK_UNHALTED_REF) * START #EVENTS DESCRIPTION * 0 0x1000 Reserved * 0x1000 0x0001 TSC - * 0x2000 0x0080 AMD K7 events + * 0x2000 0x0080 free (was AMD K7 events) * 0x2080 0x0100 AMD K8 events * 0x10000 0x0080 INTEL architectural fixed-function events * 0x10080 0x0F80 free (was INTEL architectural programmable events) @@ -2457,8 +2424,6 @@ __PMC_EV_ALIAS("unhalted-reference-cycles", IAF_CPU_CLK_UNHALTED_REF) #define __PMC_EVENTS() \ __PMC_EV_BLOCK(TSC, 0x01000) \ __PMC_EV_TSC() \ - __PMC_EV_BLOCK(K7, 0x02000) \ - __PMC_EV_K7() \ __PMC_EV_BLOCK(K8, 0x02080) \ __PMC_EV_K8() \ __PMC_EV_BLOCK(IAF, 0x10000) \ diff --git a/lib/libc/include/generic-freebsd/dev/ic/nec765.h b/lib/libc/include/generic-freebsd/dev/ic/nec765.h index 383c40e881ff..40077ceed4a9 100644 --- a/lib/libc/include/generic-freebsd/dev/ic/nec765.h +++ b/lib/libc/include/generic-freebsd/dev/ic/nec765.h @@ -27,8 +27,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)nec765.h 7.1 (Berkeley) 5/9/91 */ /* diff --git a/lib/libc/include/generic-freebsd/dev/ic/ns16550.h b/lib/libc/include/generic-freebsd/dev/ic/ns16550.h index 24201f7319b7..6214db16d485 100644 --- a/lib/libc/include/generic-freebsd/dev/ic/ns16550.h +++ b/lib/libc/include/generic-freebsd/dev/ic/ns16550.h @@ -27,8 +27,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)ns16550.h 7.1 (Berkeley) 5/9/91 */ /* @@ -162,9 +160,6 @@ #define FIFO_XMT_RST FCR_XMT_RST #define FCR_DMA 0x08 #define FIFO_DMA_MODE FCR_DMA -#ifdef CPU_XBURST -#define FCR_UART_ON 0x10 -#endif #define FCR_RX_LOW 0x00 #define FIFO_RX_LOW FCR_RX_LOW #define FCR_RX_MEDL 0x40 diff --git a/lib/libc/include/generic-freebsd/dev/iicbus/iiconf.h b/lib/libc/include/generic-freebsd/dev/iicbus/iiconf.h index a14aa381f9c0..447375857314 100644 --- a/lib/libc/include/generic-freebsd/dev/iicbus/iiconf.h +++ b/lib/libc/include/generic-freebsd/dev/iicbus/iiconf.h @@ -32,7 +32,7 @@ #include -#define IICPRI (PZERO+8) /* XXX sleep/wakeup queue priority */ +#define IICPRI (PWAIT) /* XXX sleep/wakeup queue priority */ #define LSB 0x1 diff --git a/lib/libc/include/generic-freebsd/dev/mfi/mfireg.h b/lib/libc/include/generic-freebsd/dev/mfi/mfireg.h index a43f2e346b94..f5d9922b5bb3 100644 --- a/lib/libc/include/generic-freebsd/dev/mfi/mfireg.h +++ b/lib/libc/include/generic-freebsd/dev/mfi/mfireg.h @@ -1028,7 +1028,7 @@ struct mfi_evt_detail { } pd_prog; struct { - struct mfi_evt_pd ld; + struct mfi_evt_pd pd; uint32_t prev_state; uint32_t new_state; } pd_state; diff --git a/lib/libc/include/generic-freebsd/dev/mmc/bridge.h b/lib/libc/include/generic-freebsd/dev/mmc/bridge.h index e0f21c2ae9d0..22468466a6d3 100644 --- a/lib/libc/include/generic-freebsd/dev/mmc/bridge.h +++ b/lib/libc/include/generic-freebsd/dev/mmc/bridge.h @@ -103,6 +103,10 @@ enum mmc_chip_select { cs_dontcare = 0, cs_high, cs_low }; +enum mmc_bus_type { + bus_type_default = 0, bus_type_spi +}; + enum mmc_bus_width { bus_width_1 = 0, bus_width_4 = 2, bus_width_8 = 3 }; @@ -123,6 +127,7 @@ struct mmc_ios { uint32_t clock; /* Speed of the clock in Hz to move data */ enum mmc_vdd vdd; /* Voltage to apply to the power pins */ enum mmc_vccq vccq; /* Voltage to use for signaling */ + enum mmc_bus_type bus_type; enum mmc_bus_mode bus_mode; enum mmc_chip_select chip_select; enum mmc_bus_width bus_width; diff --git a/lib/libc/include/generic-freebsd/dev/mmc/mmc_fdt_helpers.h b/lib/libc/include/generic-freebsd/dev/mmc/mmc_fdt_helpers.h index 1630aee3d3a2..9e3cf06fdfae 100644 --- a/lib/libc/include/generic-freebsd/dev/mmc/mmc_fdt_helpers.h +++ b/lib/libc/include/generic-freebsd/dev/mmc/mmc_fdt_helpers.h @@ -31,7 +31,7 @@ #include #include -#include +#include #include diff --git a/lib/libc/include/generic-freebsd/dev/mmc/mmc_helpers.h b/lib/libc/include/generic-freebsd/dev/mmc/mmc_helpers.h index c94727dee706..03fded905d4d 100644 --- a/lib/libc/include/generic-freebsd/dev/mmc/mmc_helpers.h +++ b/lib/libc/include/generic-freebsd/dev/mmc/mmc_helpers.h @@ -30,7 +30,7 @@ #include -#include +#include struct mmc_helper { device_t dev; diff --git a/lib/libc/include/generic-freebsd/dev/mmc/mmcbrvar.h b/lib/libc/include/generic-freebsd/dev/mmc/mmcbrvar.h index 1c6b08223a3e..34988b6c93af 100644 --- a/lib/libc/include/generic-freebsd/dev/mmc/mmcbrvar.h +++ b/lib/libc/include/generic-freebsd/dev/mmc/mmcbrvar.h @@ -60,6 +60,7 @@ #include "mmcbr_if.h" enum mmcbr_device_ivars { + MMCBR_IVAR_BUS_TYPE, MMCBR_IVAR_BUS_MODE, MMCBR_IVAR_BUS_WIDTH, MMCBR_IVAR_CHIP_SELECT, @@ -113,6 +114,17 @@ mmcbr_get_retune_req(device_t dev) return ((int)v); } +static int __inline +mmcbr_get_bus_type(device_t dev) +{ + uintptr_t v; + + if (__predict_false(BUS_READ_IVAR(device_get_parent(dev), dev, + MMCBR_IVAR_BUS_TYPE, &v) != 0)) + return (bus_type_default); + return ((int)v); +} + /* * Convenience wrappers for the mmcbr interface */ diff --git a/lib/libc/include/generic-freebsd/dev/mmc/mmcreg.h b/lib/libc/include/generic-freebsd/dev/mmc/mmcreg.h index 497a126999b0..6be01d45350b 100644 --- a/lib/libc/include/generic-freebsd/dev/mmc/mmcreg.h +++ b/lib/libc/include/generic-freebsd/dev/mmc/mmcreg.h @@ -80,6 +80,7 @@ struct mmc_command { #define MMC_CMD_BC (2ul << 5) /* Broadcast command, no response */ #define MMC_CMD_BCR (3ul << 5) /* Broadcast command with response */ #define MMC_CMD_MASK (3ul << 5) +#define MMC_CMD_IS_APP (1ul << 7) /* Next cmd after MMC_APP_CMD */ /* Possible response types defined in the standard: */ #define MMC_RSP_NONE (0) diff --git a/lib/libc/include/generic-freebsd/dev/nvme/nvme.h b/lib/libc/include/generic-freebsd/dev/nvme/nvme.h index 09c46d4c5de7..803797e61178 100644 --- a/lib/libc/include/generic-freebsd/dev/nvme/nvme.h +++ b/lib/libc/include/generic-freebsd/dev/nvme/nvme.h @@ -35,15 +35,23 @@ #include #include +#ifndef _KERNEL +#include +#endif + +struct sbuf; #define NVME_PASSTHROUGH_CMD _IOWR('n', 0, struct nvme_pt_command) #define NVME_RESET_CONTROLLER _IO('n', 1) #define NVME_GET_NSID _IOR('n', 2, struct nvme_get_nsid) #define NVME_GET_MAX_XFER_SIZE _IOR('n', 3, uint64_t) +#define NVME_GET_CONTROLLER_DATA _IOR('n', 4, struct nvme_controller_data) #define NVME_IO_TEST _IOWR('n', 100, struct nvme_io_test) #define NVME_BIO_TEST _IOWR('n', 101, struct nvme_io_test) +/* NB: Fabrics-specific ioctls defined in nvmf.h start at 200. */ + /* * Macros to deal with NVME revisions, as defined VS register */ @@ -211,6 +219,11 @@ /* Command field definitions */ +enum nvme_fuse { + NVME_FUSE_NORMAL = 0x0, + NVME_FUSE_FIRST = 0x1, + NVME_FUSE_SECOND = 0x2 +}; #define NVME_CMD_FUSE_SHIFT (0) #define NVME_CMD_FUSE_MASK (0x3) @@ -390,9 +403,24 @@ enum nvme_psdt { /* per namespace smart/health log page */ #define NVME_CTRLR_DATA_LPA_NS_SMART_SHIFT (0) #define NVME_CTRLR_DATA_LPA_NS_SMART_MASK (0x1) +/* Commands Supported and Effects log page */ +#define NVME_CTRLR_DATA_LPA_CMD_EFFECTS_SHIFT (1) +#define NVME_CTRLR_DATA_LPA_CMD_EFFECTS_MASK (0x1) /* extended data for Get Log Page command */ #define NVME_CTRLR_DATA_LPA_EXT_DATA_SHIFT (2) #define NVME_CTRLR_DATA_LPA_EXT_DATA_MASK (0x1) +/* telemetry */ +#define NVME_CTRLR_DATA_LPA_TELEMETRY_SHIFT (3) +#define NVME_CTRLR_DATA_LPA_TELEMETRY_MASK (0x1) +/* persistent event */ +#define NVME_CTRLR_DATA_LPA_PERSISTENT_EVENT_SHIFT (4) +#define NVME_CTRLR_DATA_LPA_PERSISTENT_EVENT_MASK (0x1) +/* Supported log pages, etc */ +#define NVME_CTRLR_DATA_LPA_LOG_PAGES_PAGE_SHIFT (5) +#define NVME_CTRLR_DATA_LPA_LOG_PAGES_PAGE_MASK (0x1) +/* Data Area 4 for Telemetry */ +#define NVME_CTRLR_DATA_LPA_DA4_TELEMETRY_SHIFT (6) +#define NVME_CTRLR_DATA_LPA_DA4_TELEMETRY_MASK (0x1) /** AVSCC - admin vendor specific command configuration */ /* admin vendor specific commands use spec format */ @@ -623,10 +651,19 @@ enum nvme_critical_warning_state { NVME_CRIT_WARN_ST_DEVICE_RELIABILITY = 0x4, NVME_CRIT_WARN_ST_READ_ONLY = 0x8, NVME_CRIT_WARN_ST_VOLATILE_MEMORY_BACKUP = 0x10, + NVME_CRIT_WARN_ST_PERSISTENT_MEMORY_REGION = 0x20, }; -#define NVME_CRIT_WARN_ST_RESERVED_MASK (0xE0) -#define NVME_ASYNC_EVENT_NS_ATTRIBUTE (0x100) -#define NVME_ASYNC_EVENT_FW_ACTIVATE (0x200) +#define NVME_CRIT_WARN_ST_RESERVED_MASK (0xC0) +#define NVME_ASYNC_EVENT_NS_ATTRIBUTE (1U << 8) +#define NVME_ASYNC_EVENT_FW_ACTIVATE (1U << 9) +#define NVME_ASYNC_EVENT_TELEMETRY_LOG (1U << 10) +#define NVME_ASYNC_EVENT_ASYM_NS_ACC (1U << 11) +#define NVME_ASYNC_EVENT_PRED_LAT_DELTA (1U << 12) +#define NVME_ASYNC_EVENT_LBA_STATUS (1U << 13) +#define NVME_ASYNC_EVENT_ENDURANCE_DELTA (1U << 14) +#define NVME_ASYNC_EVENT_NVM_SHUTDOWN (1U << 15) +#define NVME_ASYNC_EVENT_ZONE_DELTA (1U << 27) +#define NVME_ASYNC_EVENT_DISCOVERY_DELTA (1U << 31) /* slot for current FW */ #define NVME_FIRMWARE_PAGE_AFI_SLOT_SHIFT (0) @@ -809,7 +846,7 @@ struct nvme_command { uint32_t cdw13; /* command-specific */ uint32_t cdw14; /* command-specific */ uint32_t cdw15; /* command-specific */ -}; +} __aligned(8); _Static_assert(sizeof(struct nvme_command) == 16 * 4, "bad size for nvme_command"); @@ -1578,7 +1615,7 @@ struct nvme_health_information_page { uint32_t ttftmt2; uint8_t reserved2[280]; -} __packed __aligned(4); +} __packed __aligned(8); _Static_assert(sizeof(struct nvme_health_information_page) == 512, "bad size for nvme_health_information_page"); @@ -1629,6 +1666,30 @@ struct nvme_device_self_test_page { _Static_assert(sizeof(struct nvme_device_self_test_page) == 564, "bad size for nvme_device_self_test_page"); +/* + * Header structure for both host initiated telemetry (page 7) and controller + * initiated telemetry (page 8). + */ +struct nvme_telemetry_log_page { + uint8_t identifier; + uint8_t rsvd[4]; + uint8_t oui[3]; + uint16_t da1_last; + uint16_t da2_last; + uint16_t da3_last; + uint8_t rsvd2[2]; + uint32_t da4_last; + uint8_t rsvd3[361]; + uint8_t hi_gen; + uint8_t ci_avail; + uint8_t ci_gen; + uint8_t reason[128]; + /* Blocks of telemetry data follow */ +} __packed __aligned(4); + +_Static_assert(sizeof(struct nvme_telemetry_log_page) == 512, + "bad size for nvme_telemetry_log"); + struct nvme_discovery_log_entry { uint8_t trtype; uint8_t adrfam; @@ -1845,6 +1906,9 @@ struct nvme_hmb_desc { #define nvme_completion_is_error(cpl) \ (NVME_STATUS_GET_SC((cpl)->status) != 0 || NVME_STATUS_GET_SCT((cpl)->status) != 0) +void nvme_cpl_sbuf(const struct nvme_completion *cpl, struct sbuf *sbuf); +void nvme_opcode_sbuf(bool admin, uint8_t opc, struct sbuf *sb); +void nvme_sc_sbuf(const struct nvme_completion *cpl, struct sbuf *sbuf); void nvme_strvis(uint8_t *dst, const uint8_t *src, int dstlen, int srclen); #ifdef _KERNEL @@ -1855,6 +1919,7 @@ struct thread; struct nvme_namespace; struct nvme_controller; struct nvme_consumer; +struct nvme_passthru_cmd; typedef void (*nvme_cb_fn_t)(void *, const struct nvme_completion *); @@ -1865,8 +1930,11 @@ typedef void (*nvme_cons_async_fn_t)(void *, const struct nvme_completion *, typedef void (*nvme_cons_fail_fn_t)(void *); enum nvme_namespace_flags { - NVME_NS_DEALLOCATE_SUPPORTED = 0x1, - NVME_NS_FLUSH_SUPPORTED = 0x2, + NVME_NS_DEALLOCATE_SUPPORTED = 0x01, + NVME_NS_FLUSH_SUPPORTED = 0x02, + NVME_NS_ADDED = 0x04, + NVME_NS_CHANGED = 0x08, + NVME_NS_GONE = 0x10, }; int nvme_ctrlr_passthrough_cmd(struct nvme_controller *ctrlr, @@ -1874,6 +1942,11 @@ int nvme_ctrlr_passthrough_cmd(struct nvme_controller *ctrlr, uint32_t nsid, int is_user_buffer, int is_admin_cmd); +int nvme_ctrlr_linux_passthru_cmd(struct nvme_controller *ctrlr, + struct nvme_passthru_cmd *npc, + uint32_t nsid, bool is_user, + bool is_admin); + /* Admin functions */ void nvme_ctrlr_cmd_set_feature(struct nvme_controller *ctrlr, uint8_t feature, uint32_t cdw11, diff --git a/lib/libc/include/generic-freebsd/dev/nvmf/nvmf.h b/lib/libc/include/generic-freebsd/dev/nvmf/nvmf.h new file mode 100644 index 000000000000..229f8659280c --- /dev/null +++ b/lib/libc/include/generic-freebsd/dev/nvmf/nvmf.h @@ -0,0 +1,132 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022-2024 Chelsio Communications, Inc. + * Written by: John Baldwin + */ + +#ifndef __NVMF_H__ +#define __NVMF_H__ + +#include +#ifndef _KERNEL +#include +#endif + +/* + * Default settings in Fabrics controllers. These match values used by the + * Linux target. + */ +#define NVMF_MAX_IO_ENTRIES (1024) +#define NVMF_CC_EN_TIMEOUT (15) /* In 500ms units */ + +/* Allows for a 16k data buffer + SQE */ +#define NVMF_IOCCSZ (sizeof(struct nvme_command) + 16 * 1024) +#define NVMF_IORCSZ (sizeof(struct nvme_completion)) + +#define NVMF_NN (1024) + +/* + * Default timeouts for Fabrics hosts. These match values used by + * Linux. + */ +#define NVMF_DEFAULT_RECONNECT_DELAY 10 +#define NVMF_DEFAULT_CONTROLLER_LOSS 600 + +/* + * (data, size) is the userspace buffer for a packed nvlist. + * + * For requests that copyout an nvlist, len is the amount of data + * copied out to *data. If size is zero, no data is copied and len is + * set to the required buffer size. + */ +struct nvmf_ioc_nv { + void *data; + size_t len; + size_t size; +}; + +/* + * The fields in a qpair handoff nvlist are: + * + * Transport independent: + * + * bool admin + * bool sq_flow_control + * number qsize + * number sqhd + * number sqtail host only + * + * TCP transport: + * + * number fd + * number rxpda + * number txpda + * bool header_digests + * bool data_digests + * number maxr2t + * number maxh2cdata + * number max_icd + */ + +/* + * The fields in the nvlist for NVMF_HANDOFF_HOST and + * NVMF_RECONNECT_HOST are: + * + * number trtype + * number kato (optional) + * number reconnect_delay (optional) + * number controller_loss_timeout (optional) + * qpair handoff nvlist admin + * qpair handoff nvlist array io + * binary cdata struct nvme_controller_data + * NVMF_RECONNECT_PARAMS nvlist rparams + */ + +/* + * The fields in the nvlist for NVMF_RECONNECT_PARAMS are: + * + * binary dle struct nvme_discovery_log_entry + * string hostnqn + * number num_io_queues + * number kato (optional) + * number reconnect_delay (optional) + * number controller_loss_timeout (optional) + * number io_qsize + * bool sq_flow_control + * + * TCP transport: + * + * bool header_digests + * bool data_digests + */ + +/* + * The fields in the nvlist for NVMF_CONNECTION_STATUS are: + * + * bool connected + * timespec nvlist last_disconnect + * number tv_sec + * number tv_nsec + */ + +/* + * The fields in the nvlist for handing off a controller qpair are: + * + * number trtype + * qpair handoff nvlist params + * binary cmd struct nvmf_fabric_connect_cmd + * binary data struct nvmf_fabric_connect_data + */ + +/* Operations on /dev/nvmf */ +#define NVMF_HANDOFF_HOST _IOW('n', 200, struct nvmf_ioc_nv) +#define NVMF_DISCONNECT_HOST _IOW('n', 201, const char *) +#define NVMF_DISCONNECT_ALL _IO('n', 202) + +/* Operations on /dev/nvmeX */ +#define NVMF_RECONNECT_PARAMS _IOWR('n', 203, struct nvmf_ioc_nv) +#define NVMF_RECONNECT_HOST _IOW('n', 204, struct nvmf_ioc_nv) +#define NVMF_CONNECTION_STATUS _IOWR('n', 205, struct nvmf_ioc_nv) + +#endif /* !__NVMF_H__ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/dev/nvmf/nvmf_proto.h b/lib/libc/include/generic-freebsd/dev/nvmf/nvmf_proto.h new file mode 100644 index 000000000000..cd42db2cfd47 --- /dev/null +++ b/lib/libc/include/generic-freebsd/dev/nvmf/nvmf_proto.h @@ -0,0 +1,765 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (C) 2016 Intel Corporation. + * All rights reserved. + */ + +/* Derived from include/spdk/nvmf_spec.h from Intel's SPDK. */ + +#ifndef __NVMF_PROTO_H__ +#define __NVMF_PROTO_H__ + +#include +#include +#ifdef _KERNEL +#include +#else +#include +#endif +#include + +/** + * \file + * NVMe over Fabrics specification definitions + */ + +#define NVME_NQN_FIELD_SIZE 256 + +struct nvmf_capsule_cmd { + uint8_t opcode; + uint8_t reserved1; + uint16_t cid; + uint8_t fctype; + uint8_t reserved2[35]; + uint8_t fabric_specific[24]; +}; +_Static_assert(sizeof(struct nvmf_capsule_cmd) == 64, "Incorrect size"); + +/* Fabric Command Set */ +enum nvmf_fabric_cmd_types { + NVMF_FABRIC_COMMAND_PROPERTY_SET = 0x00, + NVMF_FABRIC_COMMAND_CONNECT = 0x01, + NVMF_FABRIC_COMMAND_PROPERTY_GET = 0x04, + NVMF_FABRIC_COMMAND_AUTHENTICATION_SEND = 0x05, + NVMF_FABRIC_COMMAND_AUTHENTICATION_RECV = 0x06, + NVMF_FABRIC_COMMAND_DISCONNECT = 0x08, + NVMF_FABRIC_COMMAND_START_VENDOR_SPECIFIC = 0xC0, +}; + +enum nvmf_fabric_cmd_status_code { + NVMF_FABRIC_SC_INCOMPATIBLE_FORMAT = 0x80, + NVMF_FABRIC_SC_CONTROLLER_BUSY = 0x81, + NVMF_FABRIC_SC_INVALID_PARAM = 0x82, + NVMF_FABRIC_SC_RESTART_DISCOVERY = 0x83, + NVMF_FABRIC_SC_INVALID_HOST = 0x84, + NVMF_FABRIC_SC_INVALID_QUEUE_TYPE = 0x85, + NVMF_FABRIC_SC_LOG_RESTART_DISCOVERY = 0x90, + NVMF_FABRIC_SC_AUTH_REQUIRED = 0x91, +}; + +/** + * RDMA Queue Pair service types + */ +enum nvmf_rdma_qptype { + /** Reliable connected */ + NVMF_RDMA_QPTYPE_RELIABLE_CONNECTED = 0x1, + + /** Reliable datagram */ + NVMF_RDMA_QPTYPE_RELIABLE_DATAGRAM = 0x2, +}; + +/** + * RDMA provider types + */ +enum nvmf_rdma_prtype { + /** No provider specified */ + NVMF_RDMA_PRTYPE_NONE = 0x1, + + /** InfiniBand */ + NVMF_RDMA_PRTYPE_IB = 0x2, + + /** RoCE v1 */ + NVMF_RDMA_PRTYPE_ROCE = 0x3, + + /** RoCE v2 */ + NVMF_RDMA_PRTYPE_ROCE2 = 0x4, + + /** iWARP */ + NVMF_RDMA_PRTYPE_IWARP = 0x5, +}; + +/** + * RDMA connection management service types + */ +enum nvmf_rdma_cms { + /** Sockets based endpoint addressing */ + NVMF_RDMA_CMS_RDMA_CM = 0x1, +}; + +/** + * NVMe over Fabrics transport types + */ +enum nvmf_trtype { + /** RDMA */ + NVMF_TRTYPE_RDMA = 0x1, + + /** Fibre Channel */ + NVMF_TRTYPE_FC = 0x2, + + /** TCP */ + NVMF_TRTYPE_TCP = 0x3, + + /** Intra-host transport (loopback) */ + NVMF_TRTYPE_INTRA_HOST = 0xfe, +}; + +/** + * Address family types + */ +enum nvmf_adrfam { + /** IPv4 (AF_INET) */ + NVMF_ADRFAM_IPV4 = 0x1, + + /** IPv6 (AF_INET6) */ + NVMF_ADRFAM_IPV6 = 0x2, + + /** InfiniBand (AF_IB) */ + NVMF_ADRFAM_IB = 0x3, + + /** Fibre Channel address family */ + NVMF_ADRFAM_FC = 0x4, + + /** Intra-host transport (loopback) */ + NVMF_ADRFAM_INTRA_HOST = 0xfe, +}; + +/** + * NVM subsystem types + */ +enum nvmf_subtype { + /** Referral to a discovery service */ + NVMF_SUBTYPE_DISCOVERY = 0x1, + + /** NVM Subsystem */ + NVMF_SUBTYPE_NVME = 0x2, + + /** Current Discovery Subsystem */ + NVMF_SUBTYPE_DISCOVERY_CURRENT = 0x3 +}; + +/* Discovery Log Entry Flags - Duplicate Returned Information */ +#define NVMF_DISCOVERY_LOG_EFLAGS_DUPRETINFO (1u << 0u) + +/* Discovery Log Entry Flags - Explicit Persistent Connection Support for Discovery */ +#define NVMF_DISCOVERY_LOG_EFLAGS_EPCSD (1u << 1u) + +/** + * Connections shall be made over a fabric secure channel + */ +enum nvmf_treq_secure_channel { + /** Not specified */ + NVMF_TREQ_SECURE_CHANNEL_NOT_SPECIFIED = 0x0, + + /** Required */ + NVMF_TREQ_SECURE_CHANNEL_REQUIRED = 0x1, + + /** Not required */ + NVMF_TREQ_SECURE_CHANNEL_NOT_REQUIRED = 0x2, +}; + +struct nvmf_fabric_cmd { + uint8_t opcode; + uint8_t reserved1; + uint16_t cid; + uint8_t fctype; + uint8_t reserved2[59]; +} __aligned(8); + +struct nvmf_fabric_auth_recv_cmd { + uint8_t opcode; + uint8_t reserved1; + uint16_t cid; + uint8_t fctype; /* NVMF_FABRIC_COMMAND_AUTHENTICATION_RECV (0x06) */ + uint8_t reserved2[19]; + struct nvme_sgl_descriptor sgl1; + uint8_t reserved3; + uint8_t spsp0; + uint8_t spsp1; + uint8_t secp; + uint32_t al; + uint8_t reserved4[16]; +}; +_Static_assert(sizeof(struct nvmf_fabric_auth_recv_cmd) == 64, "Incorrect size"); + +struct nvmf_fabric_auth_send_cmd { + uint8_t opcode; + uint8_t reserved1; + uint16_t cid; + uint8_t fctype; /* NVMF_FABRIC_COMMAND_AUTHENTICATION_SEND (0x05) */ + uint8_t reserved2[19]; + struct nvme_sgl_descriptor sgl1; + uint8_t reserved3; + uint8_t spsp0; + uint8_t spsp1; + uint8_t secp; + uint32_t tl; + uint8_t reserved4[16]; +}; +_Static_assert(sizeof(struct nvmf_fabric_auth_send_cmd) == 64, "Incorrect size"); + +struct nvmf_fabric_connect_data { + uint8_t hostid[16]; + uint16_t cntlid; + uint8_t reserved5[238]; + uint8_t subnqn[NVME_NQN_FIELD_SIZE]; + uint8_t hostnqn[NVME_NQN_FIELD_SIZE]; + uint8_t reserved6[256]; +}; +_Static_assert(sizeof(struct nvmf_fabric_connect_data) == 1024, "Incorrect size"); + +struct nvmf_fabric_connect_cmd { + uint8_t opcode; + uint8_t reserved1; + uint16_t cid; + uint8_t fctype; + uint8_t reserved2[19]; + struct nvme_sgl_descriptor sgl1; + uint16_t recfmt; /* Connect Record Format */ + uint16_t qid; /* Queue Identifier */ + uint16_t sqsize; /* Submission Queue Size */ + uint8_t cattr; /* queue attributes */ + uint8_t reserved3; + uint32_t kato; /* keep alive timeout */ + uint8_t reserved4[12]; +}; +_Static_assert(sizeof(struct nvmf_fabric_connect_cmd) == 64, "Incorrect size"); + +#define NVMF_CNTLID_DYNAMIC 0xFFFF +#define NVMF_CNTLID_STATIC_ANY 0xFFFE + +/* + * XXX: 5.3 in NVMe-over-Fabrics 1.1 gives this as an upper bound in + * the Discovery Log Entry. + */ +#define NVMF_CNTLID_STATIC_MAX 0xFFEF + +/* 5.21.1.15 in NVMe 1.4b */ +#define NVMF_KATO_DEFAULT (120000) + +#define NVMF_CONNECT_ATTR_PRIORITY_CLASS (0x3) +#define NVMF_CONNECT_ATTR_DISABLE_SQ_FC (1u << 2) +#define NVMF_CONNECT_ATTR_IO_QUEUE_DELETION (1u << 3) + +struct nvmf_fabric_connect_rsp { + union { + struct { + uint16_t cntlid; + uint16_t authreq; + } success; + + struct { + uint16_t ipo; + uint8_t iattr; + uint8_t reserved; + } invalid; + + uint32_t raw; + } status_code_specific; + + uint32_t reserved0; + uint16_t sqhd; + uint16_t reserved1; + uint16_t cid; + uint16_t status; +}; +_Static_assert(sizeof(struct nvmf_fabric_connect_rsp) == 16, "Incorrect size"); + +struct nvmf_fabric_disconnect_cmd { + uint8_t opcode; + uint8_t reserved1; + uint16_t cid; + uint8_t fctype; + uint8_t reserved2[19]; + struct nvme_sgl_descriptor sgl1; + uint16_t recfmt; /* Disconnect Record Format */ + uint8_t reserved3[22]; +}; +_Static_assert(sizeof(struct nvmf_fabric_disconnect_cmd) == 64, "Incorrect size"); + +#define NVMF_PROP_SIZE_4 0 +#define NVMF_PROP_SIZE_8 1 + +#define NVMF_PROP_CAP 0x00 /* Controller Capabilities */ +#define NVMF_PROP_VS 0x08 /* Version */ +#define NVMF_PROP_CC 0x14 /* Controller Configuration */ +#define NVMF_PROP_CSTS 0x1C /* Controller Status */ +#define NVMF_PROP_NSSR 0x20 /* NVM Subsystem Reset */ + +struct nvmf_fabric_prop_get_cmd { + uint8_t opcode; + uint8_t reserved1; + uint16_t cid; + uint8_t fctype; + uint8_t reserved2[35]; + struct { + uint8_t size : 3; + uint8_t reserved : 5; + } attrib; + uint8_t reserved3[3]; + uint32_t ofst; + uint8_t reserved4[16]; +}; +_Static_assert(sizeof(struct nvmf_fabric_prop_get_cmd) == 64, "Incorrect size"); + +struct nvmf_fabric_prop_get_rsp { + union { + uint64_t u64; + struct { + uint32_t low; + uint32_t high; + } u32; + } value; + + uint16_t sqhd; + uint16_t reserved0; + uint16_t cid; + uint16_t status; +}; +_Static_assert(sizeof(struct nvmf_fabric_prop_get_rsp) == 16, "Incorrect size"); + +struct nvmf_fabric_prop_set_cmd { + uint8_t opcode; + uint8_t reserved0; + uint16_t cid; + uint8_t fctype; + uint8_t reserved1[35]; + struct { + uint8_t size : 3; + uint8_t reserved : 5; + } attrib; + uint8_t reserved2[3]; + uint32_t ofst; + + union { + uint64_t u64; + struct { + uint32_t low; + uint32_t high; + } u32; + } value; + + uint8_t reserved4[8]; +}; +_Static_assert(sizeof(struct nvmf_fabric_prop_set_cmd) == 64, "Incorrect size"); + +#define NVMF_NQN_MIN_LEN 11 /* The prefix in the spec is 11 characters */ +#define NVMF_NQN_MAX_LEN 223 +#define NVMF_NQN_UUID_PRE_LEN 32 +#define NVMF_UUID_STRING_LEN 36 +#define NVMF_NQN_UUID_PRE "nqn.2014-08.org.nvmexpress:uuid:" +#define NVMF_DISCOVERY_NQN "nqn.2014-08.org.nvmexpress.discovery" + +#define NVMF_TRSTRING_MAX_LEN 32 +#define NVMF_TRADDR_MAX_LEN 256 +#define NVMF_TRSVCID_MAX_LEN 32 + +/** RDMA transport-specific address subtype */ +struct nvmf_rdma_transport_specific_address_subtype { + /** RDMA QP service type (\ref nvmf_rdma_qptype) */ + uint8_t rdma_qptype; + + /** RDMA provider type (\ref nvmf_rdma_prtype) */ + uint8_t rdma_prtype; + + /** RDMA connection management service (\ref nvmf_rdma_cms) */ + uint8_t rdma_cms; + + uint8_t reserved0[5]; + + /** RDMA partition key for AF_IB */ + uint16_t rdma_pkey; + + uint8_t reserved2[246]; +}; +_Static_assert(sizeof(struct nvmf_rdma_transport_specific_address_subtype) == 256, + "Incorrect size"); + +/** TCP Secure Socket Type */ +enum nvme_tcp_secure_socket_type { + /** No security */ + NVME_TCP_SECURITY_NONE = 0, + + /** TLS (Secure Sockets) version 1.2 */ + NVME_TCP_SECURITY_TLS_1_2 = 1, + + /** TLS (Secure Sockets) version 1.3 */ + NVME_TCP_SECURITY_TLS_1_3 = 2, +}; + +/** TCP transport-specific address subtype */ +struct nvme_tcp_transport_specific_address_subtype { + /** Security type (\ref nvme_tcp_secure_socket_type) */ + uint8_t sectype; + + uint8_t reserved0[255]; +}; +_Static_assert(sizeof(struct nvme_tcp_transport_specific_address_subtype) == 256, + "Incorrect size"); + +/** Transport-specific address subtype */ +union nvmf_transport_specific_address_subtype { + uint8_t raw[256]; + + /** RDMA */ + struct nvmf_rdma_transport_specific_address_subtype rdma; + + /** TCP */ + struct nvme_tcp_transport_specific_address_subtype tcp; +}; +_Static_assert(sizeof(union nvmf_transport_specific_address_subtype) == 256, + "Incorrect size"); + +#define NVMF_MIN_ADMIN_MAX_SQ_SIZE 32 + +/** + * Discovery Log Page entry + */ +struct nvmf_discovery_log_page_entry { + /** Transport type (\ref nvmf_trtype) */ + uint8_t trtype; + + /** Address family (\ref nvmf_adrfam) */ + uint8_t adrfam; + + /** Subsystem type (\ref nvmf_subtype) */ + uint8_t subtype; + + /** Transport requirements */ + struct { + /** Secure channel requirements (\ref nvmf_treq_secure_channel) */ + uint8_t secure_channel : 2; + + uint8_t reserved : 6; + } treq; + + /** NVM subsystem port ID */ + uint16_t portid; + + /** Controller ID */ + uint16_t cntlid; + + /** Admin max SQ size */ + uint16_t asqsz; + + /** Entry Flags */ + uint16_t eflags; + + uint8_t reserved0[20]; + + /** Transport service identifier */ + uint8_t trsvcid[NVMF_TRSVCID_MAX_LEN]; + + uint8_t reserved1[192]; + + /** NVM subsystem qualified name */ + uint8_t subnqn[256]; + + /** Transport address */ + uint8_t traddr[NVMF_TRADDR_MAX_LEN]; + + /** Transport-specific address subtype */ + union nvmf_transport_specific_address_subtype tsas; +}; +_Static_assert(sizeof(struct nvmf_discovery_log_page_entry) == 1024, "Incorrect size"); + +struct nvmf_discovery_log_page { + uint64_t genctr; + uint64_t numrec; + uint16_t recfmt; + uint8_t reserved0[1006]; + struct nvmf_discovery_log_page_entry entries[0]; +}; +_Static_assert(sizeof(struct nvmf_discovery_log_page) == 1024, "Incorrect size"); + +/* RDMA Fabric specific definitions below */ + +#define NVME_SGL_SUBTYPE_INVALIDATE_KEY 0xF + +struct nvmf_rdma_request_private_data { + uint16_t recfmt; /* record format */ + uint16_t qid; /* queue id */ + uint16_t hrqsize; /* host receive queue size */ + uint16_t hsqsize; /* host send queue size */ + uint16_t cntlid; /* controller id */ + uint8_t reserved[22]; +}; +_Static_assert(sizeof(struct nvmf_rdma_request_private_data) == 32, "Incorrect size"); + +struct nvmf_rdma_accept_private_data { + uint16_t recfmt; /* record format */ + uint16_t crqsize; /* controller receive queue size */ + uint8_t reserved[28]; +}; +_Static_assert(sizeof(struct nvmf_rdma_accept_private_data) == 32, "Incorrect size"); + +struct nvmf_rdma_reject_private_data { + uint16_t recfmt; /* record format */ + uint16_t sts; /* status */ +}; +_Static_assert(sizeof(struct nvmf_rdma_reject_private_data) == 4, "Incorrect size"); + +union nvmf_rdma_private_data { + struct nvmf_rdma_request_private_data pd_request; + struct nvmf_rdma_accept_private_data pd_accept; + struct nvmf_rdma_reject_private_data pd_reject; +}; +_Static_assert(sizeof(union nvmf_rdma_private_data) == 32, "Incorrect size"); + +enum nvmf_rdma_transport_error { + NVMF_RDMA_ERROR_INVALID_PRIVATE_DATA_LENGTH = 0x1, + NVMF_RDMA_ERROR_INVALID_RECFMT = 0x2, + NVMF_RDMA_ERROR_INVALID_QID = 0x3, + NVMF_RDMA_ERROR_INVALID_HSQSIZE = 0x4, + NVMF_RDMA_ERROR_INVALID_HRQSIZE = 0x5, + NVMF_RDMA_ERROR_NO_RESOURCES = 0x6, + NVMF_RDMA_ERROR_INVALID_IRD = 0x7, + NVMF_RDMA_ERROR_INVALID_ORD = 0x8, +}; + +/* TCP transport specific definitions below */ + +/** NVMe/TCP PDU type */ +enum nvme_tcp_pdu_type { + /** Initialize Connection Request (ICReq) */ + NVME_TCP_PDU_TYPE_IC_REQ = 0x00, + + /** Initialize Connection Response (ICResp) */ + NVME_TCP_PDU_TYPE_IC_RESP = 0x01, + + /** Terminate Connection Request (TermReq) */ + NVME_TCP_PDU_TYPE_H2C_TERM_REQ = 0x02, + + /** Terminate Connection Response (TermResp) */ + NVME_TCP_PDU_TYPE_C2H_TERM_REQ = 0x03, + + /** Command Capsule (CapsuleCmd) */ + NVME_TCP_PDU_TYPE_CAPSULE_CMD = 0x04, + + /** Response Capsule (CapsuleRsp) */ + NVME_TCP_PDU_TYPE_CAPSULE_RESP = 0x05, + + /** Host To Controller Data (H2CData) */ + NVME_TCP_PDU_TYPE_H2C_DATA = 0x06, + + /** Controller To Host Data (C2HData) */ + NVME_TCP_PDU_TYPE_C2H_DATA = 0x07, + + /** Ready to Transfer (R2T) */ + NVME_TCP_PDU_TYPE_R2T = 0x09, +}; + +/** Common NVMe/TCP PDU header */ +struct nvme_tcp_common_pdu_hdr { + /** PDU type (\ref nvme_tcp_pdu_type) */ + uint8_t pdu_type; + + /** pdu_type-specific flags */ + uint8_t flags; + + /** Length of PDU header (not including the Header Digest) */ + uint8_t hlen; + + /** PDU Data Offset from the start of the PDU */ + uint8_t pdo; + + /** Total number of bytes in PDU, including pdu_hdr */ + uint32_t plen; +}; +_Static_assert(sizeof(struct nvme_tcp_common_pdu_hdr) == 8, "Incorrect size"); +_Static_assert(offsetof(struct nvme_tcp_common_pdu_hdr, pdu_type) == 0, + "Incorrect offset"); +_Static_assert(offsetof(struct nvme_tcp_common_pdu_hdr, flags) == 1, "Incorrect offset"); +_Static_assert(offsetof(struct nvme_tcp_common_pdu_hdr, hlen) == 2, "Incorrect offset"); +_Static_assert(offsetof(struct nvme_tcp_common_pdu_hdr, pdo) == 3, "Incorrect offset"); +_Static_assert(offsetof(struct nvme_tcp_common_pdu_hdr, plen) == 4, "Incorrect offset"); + +#define NVME_TCP_CH_FLAGS_HDGSTF (1u << 0) +#define NVME_TCP_CH_FLAGS_DDGSTF (1u << 1) + +/** + * ICReq + * + * common.pdu_type == NVME_TCP_PDU_TYPE_IC_REQ + */ +struct nvme_tcp_ic_req { + struct nvme_tcp_common_pdu_hdr common; + uint16_t pfv; + /** Specifies the data alignment for all PDUs transferred from the controller to the host that contain data */ + uint8_t hpda; + union { + uint8_t raw; + struct { + uint8_t hdgst_enable : 1; + uint8_t ddgst_enable : 1; + uint8_t reserved : 6; + } bits; + } dgst; + uint32_t maxr2t; + uint8_t reserved16[112]; +}; +_Static_assert(sizeof(struct nvme_tcp_ic_req) == 128, "Incorrect size"); +_Static_assert(offsetof(struct nvme_tcp_ic_req, pfv) == 8, "Incorrect offset"); +_Static_assert(offsetof(struct nvme_tcp_ic_req, hpda) == 10, "Incorrect offset"); +_Static_assert(offsetof(struct nvme_tcp_ic_req, maxr2t) == 12, "Incorrect offset"); + +#define NVME_TCP_HPDA_MAX 31 +#define NVME_TCP_CPDA_MAX 31 +#define NVME_TCP_PDU_PDO_MAX_OFFSET ((NVME_TCP_CPDA_MAX + 1) << 2) + +/** + * ICResp + * + * common.pdu_type == NVME_TCP_PDU_TYPE_IC_RESP + */ +struct nvme_tcp_ic_resp { + struct nvme_tcp_common_pdu_hdr common; + uint16_t pfv; + /** Specifies the data alignment for all PDUs transferred from the host to the controller that contain data */ + uint8_t cpda; + union { + uint8_t raw; + struct { + uint8_t hdgst_enable : 1; + uint8_t ddgst_enable : 1; + uint8_t reserved : 6; + } bits; + } dgst; + /** Specifies the maximum number of PDU-Data bytes per H2C Data Transfer PDU */ + uint32_t maxh2cdata; + uint8_t reserved16[112]; +}; +_Static_assert(sizeof(struct nvme_tcp_ic_resp) == 128, "Incorrect size"); +_Static_assert(offsetof(struct nvme_tcp_ic_resp, pfv) == 8, "Incorrect offset"); +_Static_assert(offsetof(struct nvme_tcp_ic_resp, cpda) == 10, "Incorrect offset"); +_Static_assert(offsetof(struct nvme_tcp_ic_resp, maxh2cdata) == 12, "Incorrect offset"); + +/** + * TermReq + * + * common.pdu_type == NVME_TCP_PDU_TYPE_TERM_REQ + */ +struct nvme_tcp_term_req_hdr { + struct nvme_tcp_common_pdu_hdr common; + uint16_t fes; + uint8_t fei[4]; + uint8_t reserved14[10]; +}; + +_Static_assert(sizeof(struct nvme_tcp_term_req_hdr) == 24, "Incorrect size"); +_Static_assert(offsetof(struct nvme_tcp_term_req_hdr, fes) == 8, "Incorrect offset"); +_Static_assert(offsetof(struct nvme_tcp_term_req_hdr, fei) == 10, "Incorrect offset"); + +enum nvme_tcp_term_req_fes { + NVME_TCP_TERM_REQ_FES_INVALID_HEADER_FIELD = 0x01, + NVME_TCP_TERM_REQ_FES_PDU_SEQUENCE_ERROR = 0x02, + NVME_TCP_TERM_REQ_FES_HDGST_ERROR = 0x03, + NVME_TCP_TERM_REQ_FES_DATA_TRANSFER_OUT_OF_RANGE = 0x04, + NVME_TCP_TERM_REQ_FES_DATA_TRANSFER_LIMIT_EXCEEDED = 0x05, + NVME_TCP_TERM_REQ_FES_R2T_LIMIT_EXCEEDED = 0x05, + NVME_TCP_TERM_REQ_FES_INVALID_DATA_UNSUPPORTED_PARAMETER = 0x06, +}; + +/* Total length of term req PDU (including PDU header and DATA) in bytes shall not exceed a limit of 152 bytes. */ +#define NVME_TCP_TERM_REQ_ERROR_DATA_MAX_SIZE 128 +#define NVME_TCP_TERM_REQ_PDU_MAX_SIZE (NVME_TCP_TERM_REQ_ERROR_DATA_MAX_SIZE + sizeof(struct nvme_tcp_term_req_hdr)) + +/** + * CapsuleCmd + * + * common.pdu_type == NVME_TCP_PDU_TYPE_CAPSULE_CMD + */ +struct nvme_tcp_cmd { + struct nvme_tcp_common_pdu_hdr common; + struct nvme_command ccsqe; + /**< icdoff hdgst padding + in-capsule data + ddgst (if enabled) */ +}; +_Static_assert(sizeof(struct nvme_tcp_cmd) == 72, "Incorrect size"); +_Static_assert(offsetof(struct nvme_tcp_cmd, ccsqe) == 8, "Incorrect offset"); + +/** + * CapsuleResp + * + * common.pdu_type == NVME_TCP_PDU_TYPE_CAPSULE_RESP + */ +struct nvme_tcp_rsp { + struct nvme_tcp_common_pdu_hdr common; + struct nvme_completion rccqe; +}; +_Static_assert(sizeof(struct nvme_tcp_rsp) == 24, "incorrect size"); +_Static_assert(offsetof(struct nvme_tcp_rsp, rccqe) == 8, "Incorrect offset"); + + +/** + * H2CData + * + * hdr.pdu_type == NVME_TCP_PDU_TYPE_H2C_DATA + */ +struct nvme_tcp_h2c_data_hdr { + struct nvme_tcp_common_pdu_hdr common; + uint16_t cccid; + uint16_t ttag; + uint32_t datao; + uint32_t datal; + uint8_t reserved20[4]; +}; +_Static_assert(sizeof(struct nvme_tcp_h2c_data_hdr) == 24, "Incorrect size"); +_Static_assert(offsetof(struct nvme_tcp_h2c_data_hdr, cccid) == 8, "Incorrect offset"); +_Static_assert(offsetof(struct nvme_tcp_h2c_data_hdr, ttag) == 10, "Incorrect offset"); +_Static_assert(offsetof(struct nvme_tcp_h2c_data_hdr, datao) == 12, "Incorrect offset"); +_Static_assert(offsetof(struct nvme_tcp_h2c_data_hdr, datal) == 16, "Incorrect offset"); + +#define NVME_TCP_H2C_DATA_FLAGS_LAST_PDU (1u << 2) +#define NVME_TCP_H2C_DATA_FLAGS_SUCCESS (1u << 3) +#define NVME_TCP_H2C_DATA_PDO_MULT 8u + +/** + * C2HData + * + * hdr.pdu_type == NVME_TCP_PDU_TYPE_C2H_DATA + */ +struct nvme_tcp_c2h_data_hdr { + struct nvme_tcp_common_pdu_hdr common; + uint16_t cccid; + uint8_t reserved10[2]; + uint32_t datao; + uint32_t datal; + uint8_t reserved20[4]; +}; +_Static_assert(sizeof(struct nvme_tcp_c2h_data_hdr) == 24, "Incorrect size"); +_Static_assert(offsetof(struct nvme_tcp_c2h_data_hdr, cccid) == 8, "Incorrect offset"); +_Static_assert(offsetof(struct nvme_tcp_c2h_data_hdr, datao) == 12, "Incorrect offset"); +_Static_assert(offsetof(struct nvme_tcp_c2h_data_hdr, datal) == 16, "Incorrect offset"); + +#define NVME_TCP_C2H_DATA_FLAGS_SUCCESS (1u << 3) +#define NVME_TCP_C2H_DATA_FLAGS_LAST_PDU (1u << 2) +#define NVME_TCP_C2H_DATA_PDO_MULT 8u + +/** + * R2T + * + * common.pdu_type == NVME_TCP_PDU_TYPE_R2T + */ +struct nvme_tcp_r2t_hdr { + struct nvme_tcp_common_pdu_hdr common; + uint16_t cccid; + uint16_t ttag; + uint32_t r2to; + uint32_t r2tl; + uint8_t reserved20[4]; +}; +_Static_assert(sizeof(struct nvme_tcp_r2t_hdr) == 24, "Incorrect size"); +_Static_assert(offsetof(struct nvme_tcp_r2t_hdr, cccid) == 8, "Incorrect offset"); +_Static_assert(offsetof(struct nvme_tcp_r2t_hdr, ttag) == 10, "Incorrect offset"); +_Static_assert(offsetof(struct nvme_tcp_r2t_hdr, r2to) == 12, "Incorrect offset"); +_Static_assert(offsetof(struct nvme_tcp_r2t_hdr, r2tl) == 16, "Incorrect offset"); + +#endif /* __NVMF_PROTO_H__ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/dev/ofw/ofw_cpu.h b/lib/libc/include/generic-freebsd/dev/ofw/ofw_cpu.h index 4dd7f5556791..bde462cc62ad 100644 --- a/lib/libc/include/generic-freebsd/dev/ofw/ofw_cpu.h +++ b/lib/libc/include/generic-freebsd/dev/ofw/ofw_cpu.h @@ -30,6 +30,6 @@ #define _DEV_OFW_OFW_CPU_H_ typedef bool (*ofw_cpu_foreach_cb)(u_int, phandle_t, u_int, pcell_t *); -int ofw_cpu_early_foreach(ofw_cpu_foreach_cb, boolean_t); +int ofw_cpu_early_foreach(ofw_cpu_foreach_cb, bool); #endif /* _DEV_OFW_OFW_CPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/dev/ofw/openfirm.h b/lib/libc/include/generic-freebsd/dev/ofw/openfirm.h index 87bfbcd3c2d7..1bb249a2957d 100644 --- a/lib/libc/include/generic-freebsd/dev/ofw/openfirm.h +++ b/lib/libc/include/generic-freebsd/dev/ofw/openfirm.h @@ -83,8 +83,8 @@ MALLOC_DECLARE(M_OFWPROP); * interface as the Open Firmware access mechanism, OF_init initializes it. */ -boolean_t OF_install(char *name, int prio); -int OF_init(void *cookie); +bool OF_install(char *name, int prio); +int OF_init(void *cookie); /* * Known Open Firmware interface names @@ -149,6 +149,7 @@ phandle_t OF_xref_from_node(phandle_t node); device_t OF_device_from_xref(phandle_t xref); phandle_t OF_xref_from_device(device_t dev); int OF_device_register_xref(phandle_t xref, device_t dev); +void OF_device_unregister_xref(phandle_t xref, device_t dev); /* Device I/O functions */ ihandle_t OF_open(const char *path); diff --git a/lib/libc/include/generic-freebsd/dev/ofw/openfirmio.h b/lib/libc/include/generic-freebsd/dev/ofw/openfirmio.h index 003300d21b26..d49696f274e8 100644 --- a/lib/libc/include/generic-freebsd/dev/ofw/openfirmio.h +++ b/lib/libc/include/generic-freebsd/dev/ofw/openfirmio.h @@ -33,8 +33,6 @@ * 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. - * - * @(#)openpromio.h 8.1 (Berkeley) 6/11/93 */ #ifndef _DEV_OFW_OPENFIRMIO_H_ diff --git a/lib/libc/include/generic-freebsd/dev/pci/pcireg.h b/lib/libc/include/generic-freebsd/dev/pci/pcireg.h index cc2e06f966ec..c934264a84cf 100644 --- a/lib/libc/include/generic-freebsd/dev/pci/pcireg.h +++ b/lib/libc/include/generic-freebsd/dev/pci/pcireg.h @@ -616,6 +616,8 @@ #define PCIM_MSICTRL_MMC_16 0x0008 #define PCIM_MSICTRL_MMC_32 0x000A #define PCIM_MSICTRL_MSI_ENABLE 0x0001 +#define PCI_MSI_MSGNUM(ctrl) \ + (1 << (((ctrl) & PCIM_MSICTRL_MMC_MASK) >> 1)) #define PCIR_MSI_ADDR 0x4 #define PCIR_MSI_ADDR_HIGH 0x8 #define PCIR_MSI_DATA 0x8 @@ -965,6 +967,7 @@ #define PCIM_MSIXCTRL_MSIX_ENABLE 0x8000 #define PCIM_MSIXCTRL_FUNCTION_MASK 0x4000 #define PCIM_MSIXCTRL_TABLE_SIZE 0x07FF +#define PCI_MSIX_MSGNUM(ctrl) (((ctrl) & PCIM_MSIXCTRL_TABLE_SIZE) + 1) #define PCIR_MSIX_TABLE 0x4 #define PCIR_MSIX_PBA 0x8 #define PCIM_MSIX_BIR_MASK 0x7 diff --git a/lib/libc/include/generic-freebsd/dev/ppbus/lpt.h b/lib/libc/include/generic-freebsd/dev/ppbus/lpt.h index 16bdfa2329ae..7c181a2f5bf7 100644 --- a/lib/libc/include/generic-freebsd/dev/ppbus/lpt.h +++ b/lib/libc/include/generic-freebsd/dev/ppbus/lpt.h @@ -32,7 +32,6 @@ * SUCH DAMAGE. * * Distantly from : - * @(#)lptreg.h 1.1 (Berkeley) 12/19/90 * Id: lptreg.h,v 1.6 1997/02/22 09:36:52 peter Exp * From Id: nlpt.h,v 1.3 1999/01/10 12:04:54 nsouch Exp */ diff --git a/lib/libc/include/generic-freebsd/dev/ppbus/ppbconf.h b/lib/libc/include/generic-freebsd/dev/ppbus/ppbconf.h index 7df8714eee64..704b074faa85 100644 --- a/lib/libc/include/generic-freebsd/dev/ppbus/ppbconf.h +++ b/lib/libc/include/generic-freebsd/dev/ppbus/ppbconf.h @@ -63,7 +63,7 @@ /* * Parallel Port Bus sleep/wakeup queue. */ -#define PPBPRI (PZERO+8) +#define PPBPRI (PWAIT) /* * Parallel Port Chipset mode masks. diff --git a/lib/libc/include/generic-freebsd/dev/smbus/smbconf.h b/lib/libc/include/generic-freebsd/dev/smbus/smbconf.h index 3c86cde0fa7c..c5e107b9e63a 100644 --- a/lib/libc/include/generic-freebsd/dev/smbus/smbconf.h +++ b/lib/libc/include/generic-freebsd/dev/smbus/smbconf.h @@ -30,7 +30,7 @@ #include -#define SMBPRI (PZERO+8) /* XXX sleep/wakeup queue priority */ +#define SMBPRI (PWAIT) /* XXX sleep/wakeup queue priority */ #define n(flags) (~(flags) & (flags)) diff --git a/lib/libc/include/generic-freebsd/dev/usb/usb.h b/lib/libc/include/generic-freebsd/dev/usb/usb.h index cd33ae06c9a8..f2e0dc0a3731 100644 --- a/lib/libc/include/generic-freebsd/dev/usb/usb.h +++ b/lib/libc/include/generic-freebsd/dev/usb/usb.h @@ -114,7 +114,7 @@ MALLOC_DECLARE(M_USBDEV); /* Allow for marginal and non-conforming devices. */ #define USB_PORT_RESET_DELAY 50 /* ms */ #define USB_PORT_ROOT_RESET_DELAY 200 /* ms */ -#define USB_PORT_RESET_RECOVERY 10 /* ms */ +#define USB_PORT_RESET_RECOVERY 20 /* ms */ #define USB_PORT_POWERUP_DELAY 300 /* ms */ #define USB_PORT_RESUME_DELAY (20*2) /* ms */ #define USB_SET_ADDRESS_SETTLE 10 /* ms */ diff --git a/lib/libc/include/generic-freebsd/dev/usb/usb_bus.h b/lib/libc/include/generic-freebsd/dev/usb/usb_bus.h index 216aa1763a91..9bdc9995b2b6 100644 --- a/lib/libc/include/generic-freebsd/dev/usb/usb_bus.h +++ b/lib/libc/include/generic-freebsd/dev/usb/usb_bus.h @@ -86,7 +86,7 @@ struct usb_bus { struct usb_bus_msg shutdown_msg[2]; #if USB_HAVE_UGEN struct usb_bus_msg cleanup_msg[2]; - LIST_HEAD(,usb_fs_privdata) pd_cleanup_list; + SLIST_HEAD(,usb_fs_privdata) pd_cleanup_list; #endif /* * This mutex protects the USB hardware: diff --git a/lib/libc/include/generic-freebsd/dev/usb/usb_dev.h b/lib/libc/include/generic-freebsd/dev/usb/usb_dev.h index a59b404be702..119f99d56fed 100644 --- a/lib/libc/include/generic-freebsd/dev/usb/usb_dev.h +++ b/lib/libc/include/generic-freebsd/dev/usb/usb_dev.h @@ -96,7 +96,7 @@ struct usb_fs_privdata { int fifo_index; struct cdev *cdev; - LIST_ENTRY(usb_fs_privdata) pd_next; + SLIST_ENTRY(usb_fs_privdata) pd_next; }; /* diff --git a/lib/libc/include/generic-freebsd/dev/usb/usb_device.h b/lib/libc/include/generic-freebsd/dev/usb/usb_device.h index 3443d4df5129..83e455a73fe9 100644 --- a/lib/libc/include/generic-freebsd/dev/usb/usb_device.h +++ b/lib/libc/include/generic-freebsd/dev/usb/usb_device.h @@ -225,7 +225,7 @@ struct usb_device { struct usb_fifo *fifo[USB_FIFO_MAX]; struct usb_symlink *ugen_symlink; /* our generic symlink */ struct usb_fs_privdata *ctrl_dev; /* Control Endpoint 0 device node */ - LIST_HEAD(,usb_fs_privdata) pd_list; + SLIST_HEAD(,usb_fs_privdata) pd_list; char ugen_name[20]; /* name of ugenX.X device */ #endif usb_ticks_t plugtime; /* copy of "ticks" */ diff --git a/lib/libc/include/generic-freebsd/dev/usb/usb_freebsd.h b/lib/libc/include/generic-freebsd/dev/usb/usb_freebsd.h index 937835a08c9c..551df441b3fc 100644 --- a/lib/libc/include/generic-freebsd/dev/usb/usb_freebsd.h +++ b/lib/libc/include/generic-freebsd/dev/usb/usb_freebsd.h @@ -42,6 +42,7 @@ #define USB_HAVE_TT_SUPPORT 1 #define USB_HAVE_POWERD 1 #define USB_HAVE_MSCTEST 1 +#define USB_HAVE_MSCTEST_AUTOQUIRK 0 #define USB_HAVE_MSCTEST_DETACH 1 #define USB_HAVE_PF 1 #define USB_HAVE_ROOT_MOUNT_HOLD 1 diff --git a/lib/libc/include/generic-freebsd/dev/usb/usb_freebsd_loader.h b/lib/libc/include/generic-freebsd/dev/usb/usb_freebsd_loader.h index 2548d9deb4f7..526ea167cc48 100644 --- a/lib/libc/include/generic-freebsd/dev/usb/usb_freebsd_loader.h +++ b/lib/libc/include/generic-freebsd/dev/usb/usb_freebsd_loader.h @@ -42,6 +42,7 @@ #define USB_HAVE_TT_SUPPORT 1 #define USB_HAVE_POWERD 1 #define USB_HAVE_MSCTEST 1 +#define USB_HAVE_MSCTEST_AUTOQUIRK 0 #define USB_HAVE_MSCTEST_DETACH 0 #define USB_HAVE_PF 0 #define USB_HAVE_ROOT_MOUNT_HOLD 0 diff --git a/lib/libc/include/generic-freebsd/dev/usb/usb_ioctl.h b/lib/libc/include/generic-freebsd/dev/usb/usb_ioctl.h index 51f09c1c19ec..4d1771aaf15a 100644 --- a/lib/libc/include/generic-freebsd/dev/usb/usb_ioctl.h +++ b/lib/libc/include/generic-freebsd/dev/usb/usb_ioctl.h @@ -239,7 +239,7 @@ struct usb_gen_quirk { #define USB_DEVICESTATS _IOR ('U', 5, struct usb_device_stats) #define USB_DEVICEENUMERATE _IOW ('U', 6, int) -/* Generic HID device. Numbers 26 and 30-39 are occupied by hidraw. */ +/* Generic HID device. Numbers 26 and 30-49 are occupied by hidraw. */ #define USB_GET_REPORT_DESC _IOWR('U', 21, struct usb_gen_descriptor) #define USB_SET_IMMED _IOW ('U', 22, int) #define USB_GET_REPORT _IOWR('U', 23, struct usb_gen_descriptor) diff --git a/lib/libc/include/generic-freebsd/dev/usb/usb_process.h b/lib/libc/include/generic-freebsd/dev/usb/usb_process.h index f79aaf1cf2ef..bb377a9852c2 100644 --- a/lib/libc/include/generic-freebsd/dev/usb/usb_process.h +++ b/lib/libc/include/generic-freebsd/dev/usb/usb_process.h @@ -31,7 +31,6 @@ #ifndef USB_GLOBAL_INCLUDE_FILE #include #include -#include #endif /* defines */ @@ -76,6 +75,7 @@ int usb_proc_create(struct usb_process *up, struct mtx *p_mtx, const char *pmesg, uint8_t prio); void usb_proc_drain(struct usb_process *up); void usb_proc_mwait(struct usb_process *up, void *pm0, void *pm1); +int usb_proc_mwait_sig(struct usb_process *up, void *pm0, void *pm1); void usb_proc_free(struct usb_process *up); void *usb_proc_msignal(struct usb_process *up, void *pm0, void *pm1); void usb_proc_rewakeup(struct usb_process *up); diff --git a/lib/libc/include/generic-freebsd/dev/usb/usbdi.h b/lib/libc/include/generic-freebsd/dev/usb/usbdi.h index db954753a55f..afaf4872a54f 100644 --- a/lib/libc/include/generic-freebsd/dev/usb/usbdi.h +++ b/lib/libc/include/generic-freebsd/dev/usb/usbdi.h @@ -38,6 +38,7 @@ struct usb_process; struct usb_proc_msg; struct usb_mbuf; struct usb_fs_privdata; +struct usb_device_info; struct mbuf; typedef enum { /* keep in sync with usb_errstr_table */ @@ -525,6 +526,8 @@ struct usb_proc_msg { usb_size_t pm_num; }; +#define USB_PROC_MSG_ENQUEUED(msg) ((msg)->pm_qentry.tqe_prev != NULL) + #define USB_FIFO_TX 0 #define USB_FIFO_RX 1 @@ -585,6 +588,8 @@ usb_error_t usbd_set_endpoint_mode(struct usb_device *udev, struct usb_endpoint *ep, uint8_t ep_mode); uint8_t usbd_get_endpoint_mode(struct usb_device *udev, struct usb_endpoint *ep); +int usbd_fill_deviceinfo(struct usb_device *udev, + struct usb_device_info *di); const struct usb_device_id *usbd_lookup_id_by_info( const struct usb_device_id *id, usb_size_t sizeof_id, diff --git a/lib/libc/include/generic-freebsd/dev/veriexec/veriexec_ioctl.h b/lib/libc/include/generic-freebsd/dev/veriexec/veriexec_ioctl.h index 1eeaa77ed1d1..e20cd80a25c7 100644 --- a/lib/libc/include/generic-freebsd/dev/veriexec/veriexec_ioctl.h +++ b/lib/libc/include/generic-freebsd/dev/veriexec/veriexec_ioctl.h @@ -63,7 +63,7 @@ struct verified_exec_label_params { #define VERIEXEC_DEBUG_OFF _IO('S', 0x6) /* reset debug */ #define VERIEXEC_GETSTATE _IOR('S', 0x7, int) /* get state */ #define VERIEXEC_SIGNED_LOAD32 _IOW('S', 0x8, struct verified_exec_params32) -#define VERIEXEC_VERIFIED_FILD _IOW('S', 0x9, int) /* fd */ +#define VERIEXEC_VERIFIED_FILE _IOW('S', 0x9, int) /* fd */ #define VERIEXEC_GETVERSION _IOR('S', 0xa, int) /* get version */ #define VERIEXEC_LABEL_LOAD _IOW('S', 0xb, struct verified_exec_label_params) #define VERIEXEC_SIGNED_LOAD _IOW('S', 0xc, struct verified_exec_params) diff --git a/lib/libc/include/generic-freebsd/dev/wg/if_wg.h b/lib/libc/include/generic-freebsd/dev/wg/if_wg.h index b6750892c8cb..d73516e769a3 100644 --- a/lib/libc/include/generic-freebsd/dev/wg/if_wg.h +++ b/lib/libc/include/generic-freebsd/dev/wg/if_wg.h @@ -32,4 +32,10 @@ struct wg_data_io { #define SIOCSWG _IOWR('i', 210, struct wg_data_io) #define SIOCGWG _IOWR('i', 211, struct wg_data_io) + +/* Keep these in sync with wireguard-tools:containers.h */ +#define WGALLOWEDIP_REMOVE_ME 0x0001 + +#define WGALLOWEDIP_VALID_FLAGS WGALLOWEDIP_REMOVE_ME + #endif /* __IF_WG_H__ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/dirent.h b/lib/libc/include/generic-freebsd/dirent.h index 597a4d517154..e29b29805e7e 100644 --- a/lib/libc/include/generic-freebsd/dirent.h +++ b/lib/libc/include/generic-freebsd/dirent.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)dirent.h 8.2 (Berkeley) 7/28/94 */ #ifndef _DIRENT_H_ @@ -118,7 +116,8 @@ DIR *fdopendir(int); struct dirent * readdir(DIR *); #if __POSIX_VISIBLE >= 199506 || __XSI_VISIBLE >= 500 -int readdir_r(DIR *, struct dirent *, struct dirent **); +int readdir_r(DIR *, struct dirent *, struct dirent **) + __deprecated1("Does not take variable {NAME_MAX} into account"); #endif void rewinddir(DIR *); #if __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE >= 700 @@ -132,9 +131,22 @@ int scandir_b(const char *, struct dirent ***, #endif #endif #if __BSD_VISIBLE +int fdscandir(int, struct dirent ***, + int (*)(const struct dirent *), int (*)(const struct dirent **, + const struct dirent **)); +#ifdef __BLOCKS__ +int fdscandir_b(int, struct dirent ***, + int (^)(const struct dirent *), + int (^)(const struct dirent **, const struct dirent **)); +#endif int scandirat(int, const char *, struct dirent ***, int (*)(const struct dirent *), int (*)(const struct dirent **, const struct dirent **)); +#ifdef __BLOCKS__ +int scandirat_b(int, const char *, struct dirent ***, + int (^)(const struct dirent *), + int (^)(const struct dirent **, const struct dirent **)); +#endif #endif #if __XSI_VISIBLE void seekdir(DIR *, long); diff --git a/lib/libc/include/generic-freebsd/dlfcn.h b/lib/libc/include/generic-freebsd/dlfcn.h index 0d4f1902d4ce..c608aefe67ad 100644 --- a/lib/libc/include/generic-freebsd/dlfcn.h +++ b/lib/libc/include/generic-freebsd/dlfcn.h @@ -32,6 +32,7 @@ #ifndef _DLFCN_H_ #define _DLFCN_H_ +#include #include /* diff --git a/lib/libc/include/generic-freebsd/endian.h b/lib/libc/include/generic-freebsd/endian.h index c73f87b1e90b..b30db5816fc0 100644 --- a/lib/libc/include/generic-freebsd/endian.h +++ b/lib/libc/include/generic-freebsd/endian.h @@ -11,9 +11,34 @@ #ifndef _ENDIAN_H_ #define _ENDIAN_H_ +/* + * POSIX.1-2024 requires that endian.h define uint{16,32,64}_t. Although POSIX + * allows stdint.h symbols here, be conservative and only define there required + * ones. FreeBSD's sys/_endian.h doesn't need to expose those types since it + * implements all the [bl]eXtoh hto[bl]eX interfaces as macros calling builtin + * functions. POSIX.1-2024 allows functions, macros or both. We opt for macros + * only. + */ +#include + +#ifndef _UINT16_T_DECLARED +typedef __uint16_t uint16_t; +#define _UINT16_T_DECLARED +#endif + +#ifndef _UINT32_T_DECLARED +typedef __uint32_t uint32_t; +#define _UINT32_T_DECLARED +#endif + +#ifndef _UINT64_T_DECLARED +typedef __uint64_t uint64_t; +#define _UINT64_T_DECLARED +#endif + /* * FreeBSD's sys/_endian.h is very close to the interface provided on Linux by - * glibc's endian.h. + * glibc's endian.h as well as POSIX.1-2024's endian.h. */ #include diff --git a/lib/libc/include/generic-freebsd/err.h b/lib/libc/include/generic-freebsd/err.h index b68463a94b4e..111b6d2015c4 100644 --- a/lib/libc/include/generic-freebsd/err.h +++ b/lib/libc/include/generic-freebsd/err.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)err.h 8.1 (Berkeley) 6/2/93 */ #ifndef _ERR_H_ diff --git a/lib/libc/include/generic-freebsd/errno.h b/lib/libc/include/generic-freebsd/errno.h index cdeb8fbcadc4..6238ec73d92d 100644 --- a/lib/libc/include/generic-freebsd/errno.h +++ b/lib/libc/include/generic-freebsd/errno.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)errno.h 8.5 (Berkeley) 1/21/94 */ #ifndef _SYS_ERRNO_H_ diff --git a/lib/libc/include/generic-freebsd/execinfo.h b/lib/libc/include/generic-freebsd/execinfo.h index 99eafc35ffd5..903f4530d948 100644 --- a/lib/libc/include/generic-freebsd/execinfo.h +++ b/lib/libc/include/generic-freebsd/execinfo.h @@ -32,6 +32,8 @@ #ifndef _EXECINFO_H_ #define _EXECINFO_H_ +#include + #include __BEGIN_DECLS diff --git a/lib/libc/include/generic-freebsd/exterr.h b/lib/libc/include/generic-freebsd/exterr.h new file mode 100644 index 000000000000..052913a7edbc --- /dev/null +++ b/lib/libc/include/generic-freebsd/exterr.h @@ -0,0 +1,21 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 The FreeBSD Foundation + * All rights reserved. + * + * This software were developed by Konstantin Belousov + * under sponsorship from the FreeBSD Foundation. + */ + +#ifndef _EXTERR_H_ +#define _EXTERR_H_ + +#include +#include + +__BEGIN_DECLS +int uexterr_gettext(char *buf, size_t bufsz); +__END_DECLS + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/fcntl.h b/lib/libc/include/generic-freebsd/fcntl.h index d0d93108b5e9..0120afe643a1 100644 --- a/lib/libc/include/generic-freebsd/fcntl.h +++ b/lib/libc/include/generic-freebsd/fcntl.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)fcntl.h 8.3 (Berkeley) 1/21/94 */ #ifndef _SYS_FCNTL_H_ @@ -142,8 +140,24 @@ typedef __pid_t pid_t; #define O_DSYNC 0x01000000 /* POSIX data sync */ #if __BSD_VISIBLE #define O_EMPTY_PATH 0x02000000 +#define O_NAMEDATTR 0x04000000 /* NFSv4 named attributes */ +#define O_XATTR O_NAMEDATTR /* Solaris compatibility */ +#endif + +#if __POSIX_VISIBLE >= 202405 +#define O_CLOFORK 0x08000000 #endif +/* + * !!! DANGER !!! + * + * There are very few bits left for O_* flags. Every bit we consume for + * local features is one bit we can't use for future source compatibility + * with other operating systems. + * + * All additions should be coordinated with srcmgr@. + */ + /* * XXX missing O_RSYNC. */ @@ -270,6 +284,16 @@ typedef __pid_t pid_t; #define F_GET_SEALS 20 #define F_ISUNIONSTACK 21 /* Kludge for libc, don't use it. */ #define F_KINFO 22 /* Return kinfo_file for this fd */ +#endif /* __BSD_VISIBLE */ + +#if __POSIX_VISIBLE >= 202405 +#define F_DUPFD_CLOFORK 23 /* Like F_DUPFD, but FD_CLOFORK is set */ +#endif + +#if __BSD_VISIBLE +#define F_DUP3FD 24 /* Used with dup3() */ + +#define F_DUP3FD_SHIFT 16 /* Shift used for F_DUP3FD */ /* Seals (F_ADD_SEALS, F_GET_SEALS). */ #define F_SEAL_SEAL 0x0001 /* Prevent adding sealings */ @@ -280,6 +304,11 @@ typedef __pid_t pid_t; /* file descriptor flags (F_GETFD, F_SETFD) */ #define FD_CLOEXEC 1 /* close-on-exec flag */ +#define FD_RESOLVE_BENEATH 2 /* all lookups relative to fd have + O_RESOLVE_BENEATH semantics */ +#if __POSIX_VISIBLE >= 202405 +#define FD_CLOFORK 4 /* close-on-fork flag */ +#endif /* record locking flags (F_GETLK, F_SETLK, F_SETLKW) */ #define F_RDLCK 1 /* shared or read lock */ diff --git a/lib/libc/include/generic-freebsd/fenv.h b/lib/libc/include/generic-freebsd/fenv.h index 1838590a9950..3f511b649c27 100644 --- a/lib/libc/include/generic-freebsd/fenv.h +++ b/lib/libc/include/generic-freebsd/fenv.h @@ -29,276 +29,319 @@ #ifndef _FENV_H_ #define _FENV_H_ +#include #include -#include +#include #ifndef __fenv_static #define __fenv_static static #endif -typedef __uint32_t fenv_t; -typedef __uint32_t fexcept_t; +typedef __uint16_t fexcept_t; /* Exception flags */ -#ifdef __SPE__ -#define FE_OVERFLOW 0x00000100 -#define FE_UNDERFLOW 0x00000200 -#define FE_DIVBYZERO 0x00000400 -#define FE_INVALID 0x00000800 -#define FE_INEXACT 0x00001000 - -#define FE_ALL_INVALID FE_INVALID - -#define _FPUSW_SHIFT 6 -#else -#define FE_INEXACT 0x02000000 -#define FE_DIVBYZERO 0x04000000 -#define FE_UNDERFLOW 0x08000000 -#define FE_OVERFLOW 0x10000000 -#define FE_INVALID 0x20000000 /* all types of invalid FP ops */ - -/* - * The PowerPC architecture has extra invalid flags that indicate the - * specific type of invalid operation occurred. These flags may be - * tested, set, and cleared---but not masked---separately. All of - * these bits are cleared when FE_INVALID is cleared, but only - * FE_VXSOFT is set when FE_INVALID is explicitly set in software. - */ -#define FE_VXCVI 0x00000100 /* invalid integer convert */ -#define FE_VXSQRT 0x00000200 /* square root of a negative */ -#define FE_VXSOFT 0x00000400 /* software-requested exception */ -#define FE_VXVC 0x00080000 /* ordered comparison involving NaN */ -#define FE_VXIMZ 0x00100000 /* inf * 0 */ -#define FE_VXZDZ 0x00200000 /* 0 / 0 */ -#define FE_VXIDI 0x00400000 /* inf / inf */ -#define FE_VXISI 0x00800000 /* inf - inf */ -#define FE_VXSNAN 0x01000000 /* operation on a signalling NaN */ -#define FE_ALL_INVALID (FE_VXCVI | FE_VXSQRT | FE_VXSOFT | FE_VXVC | \ - FE_VXIMZ | FE_VXZDZ | FE_VXIDI | FE_VXISI | \ - FE_VXSNAN | FE_INVALID) - -#define _FPUSW_SHIFT 22 -#endif -#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ - FE_ALL_INVALID | FE_OVERFLOW | FE_UNDERFLOW) +#define FE_INVALID 0x01 +#define FE_DENORMAL 0x02 +#define FE_DIVBYZERO 0x04 +#define FE_OVERFLOW 0x08 +#define FE_UNDERFLOW 0x10 +#define FE_INEXACT 0x20 +#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_DENORMAL | FE_INEXACT | \ + FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) /* Rounding modes */ #define FE_TONEAREST 0x0000 -#define FE_TOWARDZERO 0x0001 -#define FE_UPWARD 0x0002 -#define FE_DOWNWARD 0x0003 +#define FE_DOWNWARD 0x0400 +#define FE_UPWARD 0x0800 +#define FE_TOWARDZERO 0x0c00 #define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ FE_UPWARD | FE_TOWARDZERO) +/* + * As compared to the x87 control word, the SSE unit's control word + * has the rounding control bits offset by 3 and the exception mask + * bits offset by 7. + */ +#define _SSE_ROUND_SHIFT 3 +#define _SSE_EMASK_SHIFT 7 + +#ifdef __i386__ +/* + * To preserve binary compatibility with FreeBSD 5.3, we pack the + * mxcsr into some reserved fields, rather than changing sizeof(fenv_t). + */ +typedef struct { + __uint16_t __control; + __uint16_t __mxcsr_hi; + __uint16_t __status; + __uint16_t __mxcsr_lo; + __uint32_t __tag; + char __other[16]; +} fenv_t; +#else /* __amd64__ */ +typedef struct { + struct { + __uint32_t __control; + __uint32_t __status; + __uint32_t __tag; + char __other[16]; + } __x87; + __uint32_t __mxcsr; +} fenv_t; +#endif /* __i386__ */ + __BEGIN_DECLS /* Default floating-point environment */ extern const fenv_t __fe_dfl_env; #define FE_DFL_ENV (&__fe_dfl_env) -/* We need to be able to map status flag positions to mask flag positions */ -#define _ENABLE_MASK ((FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ - FE_OVERFLOW | FE_UNDERFLOW) >> _FPUSW_SHIFT) - -#ifndef _SOFT_FLOAT -#ifdef __SPE__ -#define __mffs(__env) \ - __asm __volatile("mfspr %0, 512" : "=r" ((__env)->__bits.__reg)) -#define __mtfsf(__env) \ - __asm __volatile("mtspr 512,%0;isync" :: "r" ((__env).__bits.__reg)) -#else -#define __mffs(__env) \ - __asm __volatile("mffs %0" : "=f" ((__env)->__d)) -#define __mtfsf(__env) \ - __asm __volatile("mtfsf 255,%0" :: "f" ((__env).__d)) -#endif -#else -#define __mffs(__env) -#define __mtfsf(__env) -#endif +#define __fldenvx(__env) __asm __volatile("fldenv %0" : : "m" (__env) \ + : "st", "st(1)", "st(2)", "st(3)", "st(4)", \ + "st(5)", "st(6)", "st(7)") +#define __fwait() __asm __volatile("fwait") -union __fpscr { - double __d; - struct { -#if _BYTE_ORDER == _LITTLE_ENDIAN - fenv_t __reg; - __uint32_t __junk; -#else - __uint32_t __junk; - fenv_t __reg; -#endif - } __bits; -}; +int fegetenv(fenv_t *__envp); +int feholdexcept(fenv_t *__envp); +int fesetexceptflag(const fexcept_t *__flagp, int __excepts); +int feraiseexcept(int __excepts); +int feupdateenv(const fenv_t *__envp); __fenv_static inline int -feclearexcept(int __excepts) +fegetround(void) { - union __fpscr __r; - - if (__excepts & FE_INVALID) - __excepts |= FE_ALL_INVALID; - __mffs(&__r); - __r.__bits.__reg &= ~__excepts; - __mtfsf(__r); - return (0); + __uint16_t __control; + + /* + * We assume that the x87 and the SSE unit agree on the + * rounding mode. Reading the control word on the x87 turns + * out to be about 5 times faster than reading it on the SSE + * unit on an Opteron 244. + */ + __fnstcw(&__control); + return (__control & _ROUND_MASK); } -__fenv_static inline int -fegetexceptflag(fexcept_t *__flagp, int __excepts) -{ - union __fpscr __r; +#if __BSD_VISIBLE - __mffs(&__r); - *__flagp = __r.__bits.__reg & __excepts; - return (0); -} +int feenableexcept(int __mask); +int fedisableexcept(int __mask); -__fenv_static inline int -fesetexceptflag(const fexcept_t *__flagp, int __excepts) +/* We currently provide no external definition of fegetexcept(). */ +static inline int +fegetexcept(void) { - union __fpscr __r; - - if (__excepts & FE_INVALID) - __excepts |= FE_ALL_INVALID; - __mffs(&__r); - __r.__bits.__reg &= ~__excepts; - __r.__bits.__reg |= *__flagp & __excepts; - __mtfsf(__r); - return (0); + __uint16_t __control; + + /* + * We assume that the masks for the x87 and the SSE unit are + * the same. + */ + __fnstcw(&__control); + return (~__control & FE_ALL_EXCEPT); } -#ifdef __SPE__ -extern int feraiseexcept(int __excepts); +#endif /* __BSD_VISIBLE */ + +#ifdef __i386__ + +/* After testing for SSE support once, we cache the result in __has_sse. */ +enum __sse_support { __SSE_YES, __SSE_NO, __SSE_UNK }; +extern enum __sse_support __has_sse; +int __test_sse(void); +#ifdef __SSE__ +#define __HAS_SSE() 1 #else +#define __HAS_SSE() (__has_sse == __SSE_YES || \ + (__has_sse == __SSE_UNK && __test_sse())) +#endif + +#define __get_mxcsr(env) (((env).__mxcsr_hi << 16) | \ + ((env).__mxcsr_lo)) +#define __set_mxcsr(env, x) do { \ + (env).__mxcsr_hi = (__uint32_t)(x) >> 16; \ + (env).__mxcsr_lo = (__uint16_t)(x); \ +} while (0) + __fenv_static inline int -feraiseexcept(int __excepts) +feclearexcept(int __excepts) { - union __fpscr __r; - - if (__excepts & FE_INVALID) - __excepts |= FE_VXSOFT; - __mffs(&__r); - __r.__bits.__reg |= __excepts; - __mtfsf(__r); + fenv_t __env; + __uint32_t __mxcsr; + + if (__excepts == FE_ALL_EXCEPT) { + __fnclex(); + } else { + __fnstenv(&__env); + __env.__status &= ~__excepts; + __fldenv(&__env); + } + if (__HAS_SSE()) { + __stmxcsr(&__mxcsr); + __mxcsr &= ~__excepts; + __ldmxcsr(&__mxcsr); + } return (0); } -#endif __fenv_static inline int -fetestexcept(int __excepts) +fegetexceptflag(fexcept_t *__flagp, int __excepts) { - union __fpscr __r; - - __mffs(&__r); - return (__r.__bits.__reg & __excepts); + __uint32_t __mxcsr; + __uint16_t __status; + + __fnstsw(&__status); + if (__HAS_SSE()) + __stmxcsr(&__mxcsr); + else + __mxcsr = 0; + *__flagp = (__mxcsr | __status) & __excepts; + return (0); } __fenv_static inline int -fegetround(void) +fetestexcept(int __excepts) { - union __fpscr __r; - - __mffs(&__r); - return (__r.__bits.__reg & _ROUND_MASK); + __uint32_t __mxcsr; + __uint16_t __status; + + __fnstsw(&__status); + if (__HAS_SSE()) + __stmxcsr(&__mxcsr); + else + __mxcsr = 0; + return ((__status | __mxcsr) & __excepts); } __fenv_static inline int fesetround(int __round) { - union __fpscr __r; + __uint32_t __mxcsr; + __uint16_t __control; if (__round & ~_ROUND_MASK) return (-1); - __mffs(&__r); - __r.__bits.__reg &= ~_ROUND_MASK; - __r.__bits.__reg |= __round; - __mtfsf(__r); - return (0); -} -__fenv_static inline int -fegetenv(fenv_t *__envp) -{ - union __fpscr __r; + __fnstcw(&__control); + __control &= ~_ROUND_MASK; + __control |= __round; + __fldcw(&__control); + + if (__HAS_SSE()) { + __stmxcsr(&__mxcsr); + __mxcsr &= ~(_ROUND_MASK << _SSE_ROUND_SHIFT); + __mxcsr |= __round << _SSE_ROUND_SHIFT; + __ldmxcsr(&__mxcsr); + } - __mffs(&__r); - *__envp = __r.__bits.__reg; return (0); } __fenv_static inline int -feholdexcept(fenv_t *__envp) +fesetenv(const fenv_t *__envp) { - union __fpscr __r; - - __mffs(&__r); - *__envp = __r.__bits.__reg; - __r.__bits.__reg &= ~(FE_ALL_EXCEPT | _ENABLE_MASK); - __mtfsf(__r); + fenv_t __env = *__envp; + __uint32_t __mxcsr; + + __mxcsr = __get_mxcsr(__env); + __set_mxcsr(__env, 0xffffffff); + /* + * XXX Using fldenvx() instead of fldenv() tells the compiler that this + * instruction clobbers the i387 register stack. This happens because + * we restore the tag word from the saved environment. Normally, this + * would happen anyway and we wouldn't care, because the ABI allows + * function calls to clobber the i387 regs. However, fesetenv() is + * inlined, so we need to be more careful. + */ + __fldenvx(__env); + if (__HAS_SSE()) + __ldmxcsr(&__mxcsr); return (0); } +#else /* __amd64__ */ + __fenv_static inline int -fesetenv(const fenv_t *__envp) +feclearexcept(int __excepts) { - union __fpscr __r; - - __r.__bits.__reg = *__envp; - __mtfsf(__r); + fenv_t __env; + + if (__excepts == FE_ALL_EXCEPT) { + __fnclex(); + } else { + __fnstenv(&__env.__x87); + __env.__x87.__status &= ~__excepts; + __fldenv(&__env.__x87); + } + __stmxcsr(&__env.__mxcsr); + __env.__mxcsr &= ~__excepts; + __ldmxcsr(&__env.__mxcsr); return (0); } __fenv_static inline int -feupdateenv(const fenv_t *__envp) +fegetexceptflag(fexcept_t *__flagp, int __excepts) { - union __fpscr __r; + __uint32_t __mxcsr; + __uint16_t __status; - __mffs(&__r); - __r.__bits.__reg &= FE_ALL_EXCEPT; - __r.__bits.__reg |= *__envp; - __mtfsf(__r); + __stmxcsr(&__mxcsr); + __fnstsw(&__status); + *__flagp = (__mxcsr | __status) & __excepts; return (0); } -#if __BSD_VISIBLE - __fenv_static inline int -feenableexcept(int __mask) +fetestexcept(int __excepts) { - union __fpscr __r; - fenv_t __oldmask; - - __mffs(&__r); - __oldmask = __r.__bits.__reg; - __r.__bits.__reg |= (__mask & FE_ALL_EXCEPT) >> _FPUSW_SHIFT; - __mtfsf(__r); - return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT); + __uint32_t __mxcsr; + __uint16_t __status; + + __stmxcsr(&__mxcsr); + __fnstsw(&__status); + return ((__status | __mxcsr) & __excepts); } __fenv_static inline int -fedisableexcept(int __mask) +fesetround(int __round) { - union __fpscr __r; - fenv_t __oldmask; - - __mffs(&__r); - __oldmask = __r.__bits.__reg; - __r.__bits.__reg &= ~((__mask & FE_ALL_EXCEPT) >> _FPUSW_SHIFT); - __mtfsf(__r); - return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT); + __uint32_t __mxcsr; + __uint16_t __control; + + if (__round & ~_ROUND_MASK) + return (-1); + + __fnstcw(&__control); + __control &= ~_ROUND_MASK; + __control |= __round; + __fldcw(&__control); + + __stmxcsr(&__mxcsr); + __mxcsr &= ~(_ROUND_MASK << _SSE_ROUND_SHIFT); + __mxcsr |= __round << _SSE_ROUND_SHIFT; + __ldmxcsr(&__mxcsr); + + return (0); } -/* We currently provide no external definition of fegetexcept(). */ -static inline int -fegetexcept(void) +__fenv_static inline int +fesetenv(const fenv_t *__envp) { - union __fpscr __r; - __mffs(&__r); - return ((__r.__bits.__reg & _ENABLE_MASK) << _FPUSW_SHIFT); + /* + * XXX Using fldenvx() instead of fldenv() tells the compiler that this + * instruction clobbers the i387 register stack. This happens because + * we restore the tag word from the saved environment. Normally, this + * would happen anyway and we wouldn't care, because the ABI allows + * function calls to clobber the i387 regs. However, fesetenv() is + * inlined, so we need to be more careful. + */ + __fldenvx(__envp->__x87); + __ldmxcsr(&__envp->__mxcsr); + return (0); } -#endif /* __BSD_VISIBLE */ +#endif /* __i386__ */ __END_DECLS diff --git a/lib/libc/include/generic-freebsd/float.h b/lib/libc/include/generic-freebsd/float.h index a39a98229f77..0e6d11c8c393 100644 --- a/lib/libc/include/generic-freebsd/float.h +++ b/lib/libc/include/generic-freebsd/float.h @@ -1,100 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1989 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)float.h 7.1 (Berkeley) 5/8/90 - * from: FreeBSD: src/sys/i386/include/float.h,v 1.8 1999/08/28 00:44:11 + * This file is in the public domain. */ -#ifndef _MACHINE_FLOAT_H_ -#define _MACHINE_FLOAT_H_ 1 - -#include - -#ifndef _SOFT_FLOAT -__BEGIN_DECLS -extern int __flt_rounds(void); -__END_DECLS -#define FLT_ROUNDS __flt_rounds() -#else -#define FLT_ROUNDS (-1) -#endif - -#define FLT_RADIX 2 /* b */ -#if __ISO_C_VISIBLE >= 1999 -#define FLT_EVAL_METHOD 0 -#define DECIMAL_DIG 17 /* max precision in decimal digits */ -#endif - -#define FLT_MANT_DIG 24 /* p */ -#define FLT_EPSILON 1.19209290E-07F /* b**(1-p) */ -#define FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ -#define FLT_MIN_EXP (-125) /* emin */ -#define FLT_MIN 1.17549435E-38F /* b**(emin-1) */ -#define FLT_MIN_10_EXP (-37) /* ceil(log10(b**(emin-1))) */ -#define FLT_MAX_EXP 128 /* emax */ -#define FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ -#define FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ -#if __ISO_C_VISIBLE >= 2011 -#define FLT_TRUE_MIN 1.40129846E-45F /* b**(emin-p) */ -#define FLT_DECIMAL_DIG 9 /* ceil(1+p*log10(b)) */ -#define FLT_HAS_SUBNORM 1 -#endif /* __ISO_C_VISIBLE >= 2011 */ - -#define DBL_MANT_DIG 53 -#define DBL_EPSILON 2.2204460492503131E-16 -#define DBL_DIG 15 -#define DBL_MIN_EXP (-1021) -#define DBL_MIN 2.2250738585072014E-308 -#define DBL_MIN_10_EXP (-307) -#define DBL_MAX_EXP 1024 -#define DBL_MAX 1.7976931348623157E+308 -#define DBL_MAX_10_EXP 308 -#if __ISO_C_VISIBLE >= 2011 -#define DBL_TRUE_MIN 4.9406564584124654E-324 -#define DBL_DECIMAL_DIG 17 -#define DBL_HAS_SUBNORM 1 -#endif /* __ISO_C_VISIBLE >= 2011 */ - -#define LDBL_MANT_DIG DBL_MANT_DIG -#define LDBL_EPSILON ((long double)DBL_EPSILON) -#define LDBL_DIG DBL_DIG -#define LDBL_MIN_EXP DBL_MIN_EXP -#define LDBL_MIN ((long double)DBL_MIN) -#define LDBL_MIN_10_EXP DBL_MIN_10_EXP -#define LDBL_MAX_EXP DBL_MAX_EXP -#define LDBL_MAX ((long double)DBL_MAX) -#define LDBL_MAX_10_EXP DBL_MAX_10_EXP -#if __ISO_C_VISIBLE >= 2011 -#define LDBL_TRUE_MIN ((long double)DBL_TRUE_MIN) -#define LDBL_DECIMAL_DIG DBL_DECIMAL_DIG -#define LDBL_HAS_SUBNORM DBL_HAS_SUBNORM -#endif /* __ISO_C_VISIBLE >= 2011 */ - -#endif /* _MACHINE_FLOAT_H_ */ \ No newline at end of file +#include \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/floatingpoint.h b/lib/libc/include/generic-freebsd/floatingpoint.h index d2c7e15ad2e8..e05bc6f49c01 100644 --- a/lib/libc/include/generic-freebsd/floatingpoint.h +++ b/lib/libc/include/generic-freebsd/floatingpoint.h @@ -1,7 +1,7 @@ /*- - * SPDX-License-Identifier: BSD-3-Clause + * SPDX-License-Identifier: BSD-4-Clause * - * Copyright (c) 2004 Suleiman Souhlal + * Copyright (c) 1993 Andrew Moore, Talke Studio * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -12,11 +12,15 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the author nor the names of any co-contributors + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY DAVID O'BRIEN AND CONTRIBUTORS ``AS IS'' AND + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE @@ -32,6 +36,7 @@ #ifndef _FLOATINGPOINT_H_ #define _FLOATINGPOINT_H_ +#include #include #endif /* !_FLOATINGPOINT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/fnmatch.h b/lib/libc/include/generic-freebsd/fnmatch.h index 79253d2c574e..d19d301091ff 100644 --- a/lib/libc/include/generic-freebsd/fnmatch.h +++ b/lib/libc/include/generic-freebsd/fnmatch.h @@ -27,7 +27,6 @@ * 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. - * @(#)fnmatch.h 8.1 (Berkeley) 6/2/93 */ #ifndef _FNMATCH_H_ diff --git a/lib/libc/include/generic-freebsd/fs/devfs/devfs.h b/lib/libc/include/generic-freebsd/fs/devfs/devfs.h index 29227b289844..78473fbef7ee 100644 --- a/lib/libc/include/generic-freebsd/fs/devfs/devfs.h +++ b/lib/libc/include/generic-freebsd/fs/devfs/devfs.h @@ -31,8 +31,6 @@ * 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. - * - * @(#)kernfs.h 8.6 (Berkeley) 3/29/95 * From: FreeBSD: src/sys/miscfs/kernfs/kernfs.h 1.14 */ diff --git a/lib/libc/include/generic-freebsd/fs/fdescfs/fdesc.h b/lib/libc/include/generic-freebsd/fs/fdescfs/fdesc.h index f7dca514557b..4a95b37fa02a 100644 --- a/lib/libc/include/generic-freebsd/fs/fdescfs/fdesc.h +++ b/lib/libc/include/generic-freebsd/fs/fdescfs/fdesc.h @@ -30,8 +30,6 @@ * 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. - * - * @(#)fdesc.h 8.5 (Berkeley) 1/21/94 */ #ifndef _FS_FDESC_H_ diff --git a/lib/libc/include/generic-freebsd/fs/msdosfs/bootsect.h b/lib/libc/include/generic-freebsd/fs/msdosfs/bootsect.h index e12afc7a3a47..d5d922697cf3 100644 --- a/lib/libc/include/generic-freebsd/fs/msdosfs/bootsect.h +++ b/lib/libc/include/generic-freebsd/fs/msdosfs/bootsect.h @@ -20,7 +20,7 @@ /* * Format of a boot sector. This is the first sector on a DOS floppy disk - * or the fist sector of a partition on a hard disk. But, it is not the + * or the first sector of a partition on a hard disk. But, it is not the * first sector of a partitioned hard disk. */ struct bootsector33 { diff --git a/lib/libc/include/generic-freebsd/fs/msdosfs/denode.h b/lib/libc/include/generic-freebsd/fs/msdosfs/denode.h index 6eedf0eeca00..c437075c4ec2 100644 --- a/lib/libc/include/generic-freebsd/fs/msdosfs/denode.h +++ b/lib/libc/include/generic-freebsd/fs/msdosfs/denode.h @@ -212,7 +212,7 @@ struct denode { ((dep)->de_Attributes & ATTR_DIRECTORY) ? 0 : (dep)->de_FileSize), \ putushort((dp)->deHighClust, (dep)->de_StartCluster >> 16)) -#if defined(_KERNEL) || defined(MAKEFS) +#if defined(_KERNEL) || defined(_WANT_MSDOSFS_INTERNALS) #define VTODE(vp) ((struct denode *)(vp)->v_data) #define DETOV(de) ((de)->de_vnode) @@ -294,5 +294,5 @@ int removede(struct denode *pdep, struct denode *dep); int detrunc(struct denode *dep, u_long length, int flags, struct ucred *cred); int doscheckpath( struct denode *source, struct denode *target, daddr_t *wait_scn); -#endif /* _KERNEL || MAKEFS */ +#endif /* _KERNEL || _WANT_MSDOSFS_INTERNALS */ #endif /* !_FS_MSDOSFS_DENODE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/fs/msdosfs/fat.h b/lib/libc/include/generic-freebsd/fs/msdosfs/fat.h index 014ff14a4ec3..df3865028840 100644 --- a/lib/libc/include/generic-freebsd/fs/msdosfs/fat.h +++ b/lib/libc/include/generic-freebsd/fs/msdosfs/fat.h @@ -81,7 +81,7 @@ #define MSDOSFSEOF(pmp, cn) ((((cn) | ~(pmp)->pm_fatmask) & CLUST_EOFS) == CLUST_EOFS) -#if defined (_KERNEL) || defined(MAKEFS) +#if defined (_KERNEL) || defined(_WANT_MSDOSFS_INTERNALS) /* * These are the values for the function argument to the function * fatentry(). @@ -110,5 +110,5 @@ markvoldirty(struct msdosfsmount *pmp, bool dirty) return (markvoldirty_upgrade(pmp, dirty, false)); } -#endif /* _KERNEL || MAKEFS */ +#endif /* _KERNEL || _WANT_MSDOSFS_INTERNALS */ #endif /* !_FS_MSDOSFS_FAT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/fs/msdosfs/msdosfsmount.h b/lib/libc/include/generic-freebsd/fs/msdosfs/msdosfsmount.h index 9a4fc568dde9..45a72cdd48a9 100644 --- a/lib/libc/include/generic-freebsd/fs/msdosfs/msdosfsmount.h +++ b/lib/libc/include/generic-freebsd/fs/msdosfs/msdosfsmount.h @@ -52,14 +52,17 @@ #ifndef _MSDOSFS_MSDOSFSMOUNT_H_ #define _MSDOSFS_MSDOSFSMOUNT_H_ -#if defined (_KERNEL) || defined(MAKEFS) +#if defined(_KERNEL) || defined(_WANT_MSDOSFS_INTERNALS) #include -#ifndef MAKEFS +#ifdef _KERNEL #include #include -#include +#else +#include +#include #endif +#include #include #ifdef MALLOC_DECLARE @@ -114,11 +117,8 @@ struct msdosfsmount { void *pm_w2u; /* Unicode->Local iconv handle */ void *pm_u2d; /* Unicode->DOS iconv handle */ void *pm_d2u; /* DOS->Local iconv handle */ -#ifndef MAKEFS struct lock pm_fatlock; /* lockmgr protecting allocations */ - struct lock pm_checkpath_lock; /* protects doscheckpath result */ struct task pm_rw2ro_task; /* context for emergency remount ro */ -#endif }; /* @@ -245,9 +245,9 @@ struct msdosfs_fileno { #define MSDOSFS_ASSERT_MP_LOCKED(pmp) \ lockmgr_assert(&(pmp)->pm_fatlock, KA_XLOCKED) -#endif /* _KERNEL || MAKEFS */ +#endif /* _KERNEL || _WANT_MSDOSFS_INTERNALS */ -#ifndef MAKEFS +#ifdef _KERNEL /* * Arguments to mount MSDOS filesystems. */ @@ -265,7 +265,7 @@ struct msdosfs_args { char *cs_local; /* Local Charset */ mode_t dirmask; /* dir mask to be applied for msdosfs perms */ }; -#endif /* MAKEFS */ +#endif /* _KERNEL */ /* * Msdosfs mount options: diff --git a/lib/libc/include/generic-freebsd/fs/nfs/nfs.h b/lib/libc/include/generic-freebsd/fs/nfs/nfs.h index f3ec45352b7d..72c52134d457 100644 --- a/lib/libc/include/generic-freebsd/fs/nfs/nfs.h +++ b/lib/libc/include/generic-freebsd/fs/nfs/nfs.h @@ -865,6 +865,8 @@ struct nfsslot { /* Enumerated type for nfsuserd state. */ typedef enum { NOTRUNNING=0, STARTSTOP=1, RUNNING=2 } nfsuserd_state; +typedef enum { UNKNOWN=0, DELETED=1, NLINK_ZERO=2, VALID=3 } nfsremove_status; + #endif /* _KERNEL */ #endif /* _NFS_NFS_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/fs/nfs/nfs_var.h b/lib/libc/include/generic-freebsd/fs/nfs/nfs_var.h index 0a4d70898b24..42e71e33ec9c 100644 --- a/lib/libc/include/generic-freebsd/fs/nfs/nfs_var.h +++ b/lib/libc/include/generic-freebsd/fs/nfs/nfs_var.h @@ -169,6 +169,7 @@ int nfsrv_mdscopymr(char *, char *, char *, char *, int *, char *, NFSPROC_T *, struct vnode **, struct vnode **, struct pnfsdsfile **, struct nfsdevice **, struct nfsdevice **); void nfsrv_marknospc(char *, bool); +void nfsrv_removedeleg(fhandle_t *, struct nfsrv_descript *, NFSPROC_T *); /* nfs_nfsdserv.c */ int nfsrvd_access(struct nfsrv_descript *, int, @@ -285,6 +286,8 @@ int nfsrvd_deallocate(struct nfsrv_descript *, int, vnode_t, struct nfsexstuff *); int nfsrvd_copy_file_range(struct nfsrv_descript *, int, vnode_t, vnode_t, struct nfsexstuff *, struct nfsexstuff *); +int nfsrvd_clone(struct nfsrv_descript *, int, + vnode_t, vnode_t, struct nfsexstuff *, struct nfsexstuff *); int nfsrvd_seek(struct nfsrv_descript *, int, vnode_t, struct nfsexstuff *); int nfsrvd_getxattr(struct nfsrv_descript *, int, @@ -340,7 +343,8 @@ int nfsv4_loadattr(struct nfsrv_descript *, vnode_t, struct nfsvattr *, struct nfsfh **, fhandle_t *, int, struct nfsv3_pathconf *, struct statfs *, struct nfsstatfs *, struct nfsfsinfo *, NFSACL_T *, - int, int *, u_int32_t *, u_int32_t *, NFSPROC_T *, struct ucred *); + int, int *, u_int32_t *, u_int32_t *, bool *, uint32_t *, NFSPROC_T *, + struct ucred *); int nfsv4_lock(struct nfsv4lock *, int, int *, struct mtx *, struct mount *); void nfsv4_unlock(struct nfsv4lock *, int); void nfsv4_relref(struct nfsv4lock *); @@ -394,8 +398,9 @@ int nfsrv_putopbit(struct nfsrv_descript *, nfsopbit_t *); void nfsrv_wcc(struct nfsrv_descript *, int, struct nfsvattr *, int, struct nfsvattr *); int nfsv4_fillattr(struct nfsrv_descript *, struct mount *, vnode_t, NFSACL_T *, - struct vattr *, fhandle_t *, int, nfsattrbit_t *, - struct ucred *, NFSPROC_T *, int, int, int, int, uint64_t, struct statfs *); + struct vattr *, fhandle_t *, int, nfsattrbit_t *, struct ucred *, + NFSPROC_T *, int, int, int, int, uint64_t, struct statfs *, bool, bool, + bool, uint32_t); void nfsrv_fillattr(struct nfsrv_descript *, struct nfsvattr *); struct mbuf *nfsrv_adj(struct mbuf *, int, int); void nfsrv_postopattr(struct nfsrv_descript *, int, struct nfsvattr *); @@ -438,6 +443,7 @@ int nfs_supportsnfsv4acls(vnode_t); /* nfs_commonacl.c */ int nfsrv_dissectace(struct nfsrv_descript *, struct acl_entry *, bool, int *, int *, NFSPROC_T *); +uint32_t nfs_aceperm(acl_perm_t); int nfsrv_buildacl(struct nfsrv_descript *, NFSACL_T *, __enum_uint8(vtype), NFSPROC_T *); int nfsrv_compareacl(NFSACL_T *, NFSACL_T *); @@ -481,11 +487,13 @@ int nfsrpc_mknod(vnode_t, char *, int, struct vattr *, u_int32_t, int nfsrpc_create(vnode_t, char *, int, struct vattr *, nfsquad_t, int, struct ucred *, NFSPROC_T *, struct nfsvattr *, struct nfsvattr *, struct nfsfh **, int *, int *); -int nfsrpc_remove(vnode_t, char *, int, vnode_t, struct ucred *, NFSPROC_T *, - struct nfsvattr *, int *); -int nfsrpc_rename(vnode_t, vnode_t, char *, int, vnode_t, vnode_t, char *, int, - struct ucred *, NFSPROC_T *, struct nfsvattr *, struct nfsvattr *, - int *, int *); +int nfsrpc_remove(struct vnode *, char *, int, struct vnode *, + struct nfsvattr *, int *, nfsremove_status *, struct nfsvattr *, int *, + struct ucred *, NFSPROC_T *); +int nfsrpc_rename(struct vnode *, struct vnode *, char *, int, struct vnode *, + struct vnode *, char *, int, nfsremove_status *, struct nfsvattr *, + struct nfsvattr *, int *, int *, struct nfsvattr *, int *, struct ucred *, + NFSPROC_T *); int nfsrpc_link(vnode_t, vnode_t, char *, int, struct ucred *, NFSPROC_T *, struct nfsvattr *, struct nfsvattr *, int *, int *); @@ -512,10 +520,10 @@ int nfsrpc_lock(struct nfsrv_descript *, struct nfsmount *, vnode_t, u_int8_t *, int, struct nfscllockowner *, int, int, u_int64_t, u_int64_t, short, struct ucred *, NFSPROC_T *, int); int nfsrpc_statfs(vnode_t, struct nfsstatfs *, struct nfsfsinfo *, uint32_t *, - struct ucred *, NFSPROC_T *, struct nfsvattr *, int *); + uint32_t *, struct ucred *, NFSPROC_T *, struct nfsvattr *, int *); int nfsrpc_fsinfo(vnode_t, struct nfsfsinfo *, struct ucred *, NFSPROC_T *, struct nfsvattr *, int *); -int nfsrpc_pathconf(vnode_t, struct nfsv3_pathconf *, +int nfsrpc_pathconf(vnode_t, struct nfsv3_pathconf *, bool *, uint32_t *, struct ucred *, NFSPROC_T *, struct nfsvattr *, int *); int nfsrpc_renew(struct nfsclclient *, struct nfsclds *, struct ucred *, NFSPROC_T *); @@ -557,6 +565,8 @@ int nfsrpc_deallocate(vnode_t, off_t, off_t, struct nfsvattr *, int *, int nfsrpc_copy_file_range(vnode_t, off_t *, vnode_t, off_t *, size_t *, unsigned int, int *, struct nfsvattr *, int *, struct nfsvattr *, struct ucred *, bool, bool *); +int nfsrpc_clone(vnode_t, off_t *, vnode_t, off_t *, size_t *, bool, + int *, struct nfsvattr *, int *, struct nfsvattr *, struct ucred *); int nfsrpc_seek(vnode_t, off_t *, bool *, int, struct ucred *, struct nfsvattr *, int *); int nfsrpc_getextattr(vnode_t, const char *, struct uio *, ssize_t *, @@ -568,6 +578,9 @@ int nfsrpc_listextattr(vnode_t, uint64_t *, struct uio *, size_t *, bool *, int nfsrpc_rmextattr(vnode_t, const char *, struct nfsvattr *, int *, struct ucred *, NFSPROC_T *); void nfsrpc_bindconnsess(CLIENT *, void *, struct ucred *); +int nfsrpc_openattr(struct nfsmount *, struct vnode *, uint8_t *, int, + bool, struct ucred *, NFSPROC_T *, struct nfsvattr *, struct nfsfh **, + int *); /* nfs_clstate.c */ int nfscl_open(vnode_t, u_int8_t *, int, u_int32_t, int, @@ -606,12 +619,12 @@ int nfscl_doclose(vnode_t, struct nfsclclient **, NFSPROC_T *); int nfsrpc_doclose(struct nfsmount *, struct nfsclopen *, NFSPROC_T *, bool, bool); int nfscl_deleg(mount_t, struct nfsclclient *, u_int8_t *, int, - struct ucred *, NFSPROC_T *, struct nfscldeleg **); + struct ucred *, NFSPROC_T *, struct nfscldeleg *); void nfscl_lockinit(struct nfsv4lock *); void nfscl_lockexcl(struct nfsv4lock *, void *); void nfscl_lockunlock(struct nfsv4lock *); void nfscl_lockderef(struct nfsv4lock *); -void nfscl_delegreturnvp(vnode_t, NFSPROC_T *); +void nfscl_delegreturnvp(struct vnode *, bool, NFSPROC_T *); void nfscl_docb(struct nfsrv_descript *, NFSPROC_T *); void nfscl_releasealllocks(struct nfsclclient *, vnode_t, NFSPROC_T *, void *, int); @@ -626,7 +639,7 @@ int nfscl_renamedeleg(vnode_t, nfsv4stateid_t *, int *, vnode_t, nfsv4stateid_t *, int *, NFSPROC_T *); void nfscl_reclaimnode(vnode_t); void nfscl_newnode(vnode_t); -void nfscl_delegmodtime(vnode_t); +void nfscl_delegmodtime(struct vnode *, struct timespec *); void nfscl_deleggetmodtime(vnode_t, struct timespec *); int nfscl_trydelegreturn(struct nfscldeleg *, struct ucred *, struct nfsmount *, NFSPROC_T *); @@ -651,6 +664,8 @@ void nfscl_freelayout(struct nfscllayout *); void nfscl_freeflayout(struct nfsclflayout *); void nfscl_freedevinfo(struct nfscldevinfo *); int nfscl_layoutcommit(vnode_t, NFSPROC_T *); +int nfscl_delegacecheck(struct vnode *, accmode_t, struct ucred *); +void nfscl_startdelegrecall(struct nfsclclient *, struct nfsfh *); /* nfs_clport.c */ int nfscl_nget(mount_t, vnode_t, struct nfsfh *, @@ -658,7 +673,7 @@ int nfscl_nget(mount_t, vnode_t, struct nfsfh *, NFSPROC_T *nfscl_getparent(NFSPROC_T *); void nfscl_start_renewthread(struct nfsclclient *); void nfscl_loadsbinfo(struct nfsmount *, struct nfsstatfs *, void *); -void nfscl_loadfsinfo (struct nfsmount *, struct nfsfsinfo *); +void nfscl_loadfsinfo(struct nfsmount *, struct nfsfsinfo *, uint32_t); void nfscl_delegreturn(struct nfscldeleg *, int, struct nfsmount *, struct ucred *, NFSPROC_T *); void nfsrvd_cbinit(int); @@ -707,12 +722,12 @@ int nfsvno_symlink(struct nameidata *, struct nfsvattr *, char *, int, int, uid_t, struct ucred *, NFSPROC_T *, struct nfsexstuff *); int nfsvno_getsymlink(struct nfsrv_descript *, struct nfsvattr *, NFSPROC_T *, char **, int *); -int nfsvno_removesub(struct nameidata *, int, struct ucred *, NFSPROC_T *, - struct nfsexstuff *); +int nfsvno_removesub(struct nameidata *, bool, struct nfsrv_descript *, + NFSPROC_T *, struct nfsexstuff *); int nfsvno_rmdirsub(struct nameidata *, int, struct ucred *, NFSPROC_T *, struct nfsexstuff *); -int nfsvno_rename(struct nameidata *, struct nameidata *, u_int32_t, - u_int32_t, struct ucred *, NFSPROC_T *); +int nfsvno_rename(struct nameidata *, struct nameidata *, + struct nfsrv_descript *, NFSPROC_T *); int nfsvno_link(struct nameidata *, vnode_t, nfsquad_t, struct ucred *, NFSPROC_T *, struct nfsexstuff *); int nfsvno_fsync(vnode_t, u_int64_t, int, struct ucred *, NFSPROC_T *); @@ -726,7 +741,8 @@ int nfsvno_updfilerev(vnode_t, struct nfsvattr *, struct nfsrv_descript *, NFSPROC_T *); int nfsvno_fillattr(struct nfsrv_descript *, struct mount *, vnode_t, struct nfsvattr *, fhandle_t *, int, nfsattrbit_t *, - struct ucred *, NFSPROC_T *, int, int, int, int, uint64_t); + struct ucred *, NFSPROC_T *, int, int, int, int, uint64_t, bool, bool, + bool, uint32_t); int nfsrv_sattr(struct nfsrv_descript *, vnode_t, struct nfsvattr *, nfsattrbit_t *, NFSACL_T *, NFSPROC_T *); int nfsv4_sattr(struct nfsrv_descript *, vnode_t, struct nfsvattr *, nfsattrbit_t *, @@ -780,6 +796,7 @@ int newnfs_request(struct nfsrv_descript *, struct nfsmount *, struct nfsclient *, struct nfssockreq *, vnode_t, NFSPROC_T *, struct ucred *, u_int32_t, u_int32_t, u_char *, int, u_int64_t *, struct nfsclsession *); +void nfs_resetslots(struct nfsclsession *); int newnfs_connect(struct nfsmount *, struct nfssockreq *, struct ucred *, NFSPROC_T *, int, bool, struct __rpc_client **); void newnfs_disconnect(struct nfsmount *, struct nfssockreq *); diff --git a/lib/libc/include/generic-freebsd/fs/nfs/nfscl.h b/lib/libc/include/generic-freebsd/fs/nfs/nfscl.h index 702e36387beb..c64b25a7df7c 100644 --- a/lib/libc/include/generic-freebsd/fs/nfs/nfscl.h +++ b/lib/libc/include/generic-freebsd/fs/nfs/nfscl.h @@ -68,10 +68,11 @@ struct nfsv4node { * These flag bits are used for the argument to nfscl_fillsattr() to * indicate special handling of the attributes. */ -#define NFSSATTR_FULL 0x1 -#define NFSSATTR_SIZE0 0x2 -#define NFSSATTR_SIZENEG1 0x4 -#define NFSSATTR_SIZERDEV 0x8 +#define NFSSATTR_FULL 0x01 +#define NFSSATTR_SIZE0 0x02 +#define NFSSATTR_SIZENEG1 0x04 +#define NFSSATTR_SIZERDEV 0x08 +#define NFSSATTR_NEWFILE 0x10 /* Use this macro for debug printfs. */ #define NFSCL_DEBUG(level, ...) do { \ diff --git a/lib/libc/include/generic-freebsd/fs/nfs/nfsclstate.h b/lib/libc/include/generic-freebsd/fs/nfs/nfsclstate.h index a54339e07224..7147929594aa 100644 --- a/lib/libc/include/generic-freebsd/fs/nfs/nfsclstate.h +++ b/lib/libc/include/generic-freebsd/fs/nfs/nfsclstate.h @@ -116,6 +116,10 @@ struct nfsclclient { struct proc *nfsc_renewthread; struct nfsmount *nfsc_nmp; time_t nfsc_expire; + int nfsc_delegcnt; + int nfsc_deleghighwater; + int nfsc_layoutcnt; + int nfsc_layouthighwater; u_int32_t nfsc_clientidrev; u_int32_t nfsc_rev; u_int32_t nfsc_renew; diff --git a/lib/libc/include/generic-freebsd/fs/nfs/nfsport.h b/lib/libc/include/generic-freebsd/fs/nfs/nfsport.h index a40aba5cf5e9..94ad3c1be990 100644 --- a/lib/libc/include/generic-freebsd/fs/nfs/nfsport.h +++ b/lib/libc/include/generic-freebsd/fs/nfs/nfsport.h @@ -439,10 +439,16 @@ /* Do an NFSv4 Verify+Write. */ #define NFSPROC_APPENDWRITE 69 +/* Do a NFSv4 Openattr. */ +#define NFSPROC_OPENATTR 70 + +/* Do a NFSv4.2 Clone. */ +#define NFSPROC_CLONE 71 + /* * Must be defined as one higher than the last NFSv4.2 Proc# above. */ -#define NFSV42_NPROCS 70 +#define NFSV42_NPROCS 72 /* Value of NFSV42_NPROCS for old nfsstats structure. (Always 69) */ #define NFSV42_OLDNPROCS 69 @@ -474,7 +480,7 @@ struct nfsstatsv1 { uint64_t readlink_bios; uint64_t biocache_readdirs; uint64_t readdir_bios; - uint64_t rpccnt[NFSV42_NPROCS + 10]; + uint64_t rpccnt[NFSV42_NPROCS + 8]; uint64_t rpcretries; uint64_t srvrpccnt[NFSV42_NOPS + NFSV4OP_FAKENOPS + 15]; uint64_t srvlayouts; @@ -690,6 +696,7 @@ struct nfsvattr { #define na_bytes na_vattr.va_bytes #define na_filerev na_vattr.va_filerev #define na_vaflags na_vattr.va_vaflags +#define na_bsdflags na_vattr.va_bsdflags #include @@ -901,15 +908,6 @@ int nfsmsleep(void *, void *, int, const char *, struct timespec *); #define NFSBCMP(s, d, l) bcmp((s), (d), (l)) #define NFSBZERO(s, l) bzero((s), (l)) -/* - * Some queue.h files don't have these dfined in them. - */ -#ifndef LIST_END -#define LIST_END(head) NULL -#define SLIST_END(head) NULL -#define TAILQ_END(head) NULL -#endif - /* * This must be defined to be a global variable that increments once * per second, but never stops or goes backwards, even when a "date" @@ -1019,7 +1017,7 @@ MALLOC_DECLARE(M_NEWNFSDSESSION); int nfscl_loadattrcache(struct vnode **, struct nfsvattr *, void *, int, int); int newnfs_realign(struct mbuf **, int); bool ncl_pager_setsize(struct vnode *vp, u_quad_t *nsizep); -void ncl_copy_vattr(struct vattr *dst, struct vattr *src); +void ncl_copy_vattr(struct vnode *vp, struct vattr *dst, struct vattr *src); /* * If the port runs on an SMP box that can enforce Atomic ops with low @@ -1030,9 +1028,6 @@ void ncl_copy_vattr(struct vattr *dst, struct vattr *src); #define NFSINCRGLOBAL(a) ((a)++) #define NFSDECRGLOBAL(a) ((a)--) -/* - * Assorted funky stuff to make things work under Darwin8. - */ /* * These macros checks for a field in vattr being set. */ @@ -1180,9 +1175,11 @@ struct nfsreq { */ #ifdef VV_DISABLEDELEG #define NFSVNO_DELEGOK(v) \ - ((v) == NULL || ((v)->v_vflag & VV_DISABLEDELEG) == 0) + ((v) == NULL || ((v)->v_vflag & VV_DISABLEDELEG) == 0 || \ + (vn_irflag_read(v) & VIRF_NAMEDATTR) == 0) #else -#define NFSVNO_DELEGOK(v) (1) +#define NFSVNO_DELEGOK(v) \ + ((v) == NULL || (vn_irflag_read(v) & VIRF_NAMEDATTR) == 0) #endif /* diff --git a/lib/libc/include/generic-freebsd/fs/nfs/nfsproto.h b/lib/libc/include/generic-freebsd/fs/nfs/nfsproto.h index 4791ceaf0229..cfc0b6f898ce 100644 --- a/lib/libc/include/generic-freebsd/fs/nfs/nfsproto.h +++ b/lib/libc/include/generic-freebsd/fs/nfs/nfsproto.h @@ -275,6 +275,8 @@ #define NFSX_V4SESSIONID 16 #define NFSX_V4DEVICEID 16 #define NFSX_V4PNFSFH (sizeof(fhandle_t) + 1) +#define NFSX_V4NAMEDDIRFH 2 +#define NFSX_V4NAMEDATTRFH 3 #define NFSX_V4FILELAYOUT (4 * NFSX_UNSIGNED + NFSX_V4DEVICEID + \ NFSX_HYPER + NFSM_RNDUP(NFSX_V4PNFSFH)) #define NFSX_V4FLEXLAYOUT(m) (NFSX_HYPER + 3 * NFSX_UNSIGNED + \ @@ -406,10 +408,16 @@ /* Do an NFSv4 Verify+Write. */ #define NFSPROC_APPENDWRITE 69 +/* Do a NFSv4 Openattr. */ +#define NFSPROC_OPENATTR 70 + +/* Do a NFSv4.2 Clone. */ +#define NFSPROC_CLONE 71 + /* * Must be defined as one higher than the last NFSv4.2 Proc# above. */ -#define NFSV42_NPROCS 70 +#define NFSV42_NPROCS 72 /* Value of NFSV42_NPROCS for old nfsstats structure. (Always 69) */ #define NFSV42_OLDNPROCS 69 @@ -744,6 +752,17 @@ #define NFSSECINFONONAME_CURFH 0 #define NFSSECINFONONAME_PARENT 1 +/* Bits for CB_RECALL_ANY. */ +#define NFSRCA4_RDATA_DLG 0x00000001 +#define NFSRCA4_WDATA_DLG 0x00000002 +#define NFSRCA4_DIR_DLG 0x00000004 +#define NFSRCA4_FILE_LAYOUT 0x00000008 +#define NFSRCA4_BLK_LAYOUT 0x00000010 +#define NFSRCA4_OBJ_LAYOUT_MIN 0x00000100 +#define NFSRCA4_OBJ_LAYOUT_MAX 0x00000200 +#define NFSRCA4_FF_LAYOUT_READ 0x00010000 +#define NFSRCA4_FF_LAYOUT_RW 0x00020000 + #if defined(_KERNEL) || defined(KERNEL) /* Conversion macros */ #define vtonfsv2_mode(t,m) \ @@ -1126,6 +1145,7 @@ struct nfsv3_sattr { NFSATTRBM_FILESFREE | \ NFSATTRBM_FILESTOTAL | \ NFSATTRBM_FSLOCATIONS | \ + NFSATTRBM_HIDDEN | \ NFSATTRBM_HOMOGENEOUS | \ NFSATTRBM_MAXFILESIZE | \ NFSATTRBM_MAXLINK | \ @@ -1147,6 +1167,7 @@ struct nfsv3_sattr { NFSATTRBM_SPACEFREE | \ NFSATTRBM_SPACETOTAL | \ NFSATTRBM_SPACEUSED | \ + NFSATTRBM_SYSTEM | \ NFSATTRBM_TIMEACCESS | \ NFSATTRBM_TIMECREATE | \ NFSATTRBM_TIMEDELTA | \ @@ -1176,6 +1197,8 @@ struct nfsv3_sattr { NFSATTRBM_LAYOUTBLKSIZE | \ NFSATTRBM_LAYOUTALIGNMENT | \ NFSATTRBM_SUPPATTREXCLCREAT | \ + NFSATTRBM_CLONEBLKSIZE | \ + NFSATTRBM_CHANGEATTRTYPE | \ NFSATTRBM_XATTRSUPPORT) /* @@ -1183,7 +1206,8 @@ struct nfsv3_sattr { */ #define NFSATTRBIT_SUPPSETONLY1 (NFSATTRBM_TIMEACCESSSET | \ NFSATTRBM_TIMEMODIFYSET) -#define NFSATTRBIT_SUPPSETONLY2 (NFSATTRBM_MODESETMASKED) +#define NFSATTRBIT_SUPPSETONLY2 (NFSATTRBM_MODESETMASKED | \ + NFSATTRBM_MODEUMASK) /* * NFSATTRBIT_SETABLE - SETABLE0 - bits 0<->31 @@ -1192,16 +1216,19 @@ struct nfsv3_sattr { */ #define NFSATTRBIT_SETABLE0 \ (NFSATTRBM_SIZE | \ + NFSATTRBM_HIDDEN | \ NFSATTRBM_ACL) #define NFSATTRBIT_SETABLE1 \ (NFSATTRBM_MODE | \ NFSATTRBM_OWNER | \ NFSATTRBM_OWNERGROUP | \ - NFSATTRBM_TIMECREATE | \ + NFSATTRBM_SYSTEM | \ + NFSATTRBM_TIMECREATE | \ NFSATTRBM_TIMEACCESSSET | \ NFSATTRBM_TIMEMODIFYSET) #define NFSATTRBIT_SETABLE2 \ - (NFSATTRBM_MODESETMASKED) + (NFSATTRBM_MODESETMASKED | \ + NFSATTRBM_MODEUMASK) /* * NFSATTRBIT_NFSV41 - Attributes only supported by NFSv4.1. @@ -1218,7 +1245,11 @@ struct nfsv3_sattr { /* * NFSATTRBIT_NFSV42 - Attributes only supported by NFSv4.2. */ -#define NFSATTRBIT_NFSV42_2 NFSATTRBM_XATTRSUPPORT +#define NFSATTRBIT_NFSV42_2 \ + (NFSATTRBM_CLONEBLKSIZE | \ + NFSATTRBM_CHANGEATTRTYPE | \ + NFSATTRBM_XATTRSUPPORT | \ + NFSATTRBM_MODEUMASK) /* * Set of attributes that the getattr vnode op needs. @@ -1232,6 +1263,7 @@ struct nfsv3_sattr { NFSATTRBM_SIZE | \ NFSATTRBM_FSID | \ NFSATTRBM_FILEID | \ + NFSATTRBM_HIDDEN | \ NFSATTRBM_MAXREAD) /* @@ -1244,6 +1276,7 @@ struct nfsv3_sattr { NFSATTRBM_OWNERGROUP | \ NFSATTRBM_RAWDEV | \ NFSATTRBM_SPACEUSED | \ + NFSATTRBM_SYSTEM | \ NFSATTRBM_TIMEACCESS | \ NFSATTRBM_TIMECREATE | \ NFSATTRBM_TIMEMETADATA | \ @@ -1266,6 +1299,7 @@ struct nfsv3_sattr { NFSATTRBM_SIZE | \ NFSATTRBM_FSID | \ NFSATTRBM_FILEID | \ + NFSATTRBM_HIDDEN | \ NFSATTRBM_MAXREAD) /* @@ -1276,6 +1310,7 @@ struct nfsv3_sattr { NFSATTRBM_NUMLINKS | \ NFSATTRBM_RAWDEV | \ NFSATTRBM_SPACEUSED | \ + NFSATTRBM_SYSTEM | \ NFSATTRBM_TIMEACCESS | \ NFSATTRBM_TIMECREATE | \ NFSATTRBM_TIMEMETADATA | \ @@ -1385,13 +1420,14 @@ struct nfsv3_sattr { /* * NFSGETATTRBIT_STATFS2 - bits 64<->95 */ -#define NFSGETATTRBIT_STATFS2 0 +#define NFSGETATTRBIT_STATFS2 (NFSATTRBM_CLONEBLKSIZE) /* * Set of attributes for the equivalent of an nfsv3 pathconf rpc. * NFSGETATTRBIT_PATHCONF0 - bits 0<->31 */ #define NFSGETATTRBIT_PATHCONF0 (NFSATTRBIT_GETATTR0 | \ + NFSATTRBM_NAMEDATTR | \ NFSATTRBM_CASEINSENSITIVE | \ NFSATTRBM_CASEPRESERVING | \ NFSATTRBM_CHOWNRESTRICTED | \ @@ -1407,7 +1443,7 @@ struct nfsv3_sattr { /* * NFSGETATTRBIT_PATHCONF2 - bits 64<->95 */ -#define NFSGETATTRBIT_PATHCONF2 0 +#define NFSGETATTRBIT_PATHCONF2 (NFSATTRBM_CLONEBLKSIZE) /* * Sets of attributes required by readdir and readdirplus. @@ -1653,4 +1689,11 @@ typedef struct nfsv4stateid nfsv4stateid_t; #define NFSV4SXATTR_CREATE 1 #define NFSV4SXATTR_REPLACE 2 +/* Values for ChangeAttrType (RFC-7862). */ +#define NFSV4CHANGETYPE_MONOTONIC_INCR 0 +#define NFSV4CHANGETYPE_VERS_COUNTER 1 +#define NFSV4CHANGETYPE_VERS_COUNTER_NOPNFS 2 +#define NFSV4CHANGETYPE_TIME_METADATA 3 +#define NFSV4CHANGETYPE_UNDEFINED 4 + #endif /* _NFS_NFSPROTO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/fs/nullfs/null.h b/lib/libc/include/generic-freebsd/fs/nullfs/null.h index 8e2c2c8b573a..ba64f8ce71dd 100644 --- a/lib/libc/include/generic-freebsd/fs/nullfs/null.h +++ b/lib/libc/include/generic-freebsd/fs/nullfs/null.h @@ -30,8 +30,6 @@ * 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. - * - * @(#)null.h 8.3 (Berkeley) 8/20/94 */ #ifndef FS_NULL_H diff --git a/lib/libc/include/generic-freebsd/fs/procfs/procfs.h b/lib/libc/include/generic-freebsd/fs/procfs/procfs.h index 47c9b2a761d3..daee89f6c79a 100644 --- a/lib/libc/include/generic-freebsd/fs/procfs/procfs.h +++ b/lib/libc/include/generic-freebsd/fs/procfs/procfs.h @@ -32,8 +32,6 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)procfs.h 8.9 (Berkeley) 5/14/95 - * * From: */ diff --git a/lib/libc/include/generic-freebsd/fs/smbfs/smbfs_node.h b/lib/libc/include/generic-freebsd/fs/smbfs/smbfs_node.h index 1e53fce8a6a0..3b480074089f 100644 --- a/lib/libc/include/generic-freebsd/fs/smbfs/smbfs_node.h +++ b/lib/libc/include/generic-freebsd/fs/smbfs/smbfs_node.h @@ -93,7 +93,7 @@ u_int32_t smbfs_hash(const u_char *name, int nmlen); int smbfs_getpages(struct vop_getpages_args *); int smbfs_putpages(struct vop_putpages_args *); -int smbfs_readvnode(struct vnode *vp, struct uio *uiop, struct ucred *cred); +int smbfs_readvnode(struct vnode *vp, struct uio *uiop, struct ucred *cred, int *eofp); int smbfs_writevnode(struct vnode *vp, struct uio *uiop, struct ucred *cred, int ioflag); void smbfs_attr_cacheenter(struct vnode *vp, struct smbfattr *fap); int smbfs_attr_cachelookup(struct vnode *vp ,struct vattr *va); diff --git a/lib/libc/include/generic-freebsd/fs/udf/ecma167-udf.h b/lib/libc/include/generic-freebsd/fs/udf/ecma167-udf.h index 335bf5212fda..dec14812c625 100644 --- a/lib/libc/include/generic-freebsd/fs/udf/ecma167-udf.h +++ b/lib/libc/include/generic-freebsd/fs/udf/ecma167-udf.h @@ -243,7 +243,7 @@ struct part_map_spare { uint8_t n_st; /* Number of Sparing Tables */ uint8_t reserved1; uint32_t st_size; - uint32_t st_loc[1]; + uint32_t st_loc[]; } __packed; union udf_pmap { @@ -266,7 +266,7 @@ struct udf_sparing_table { uint16_t rt_l; /* Relocation Table len */ uint8_t reserved[2]; uint32_t seq_num; - struct spare_map_entry entries[1]; + struct spare_map_entry entries[]; } __packed; /* Partition Descriptor [3/10.5] */ diff --git a/lib/libc/include/generic-freebsd/fs/unionfs/union.h b/lib/libc/include/generic-freebsd/fs/unionfs/union.h index 4fe3ccda005d..426918b46772 100644 --- a/lib/libc/include/generic-freebsd/fs/unionfs/union.h +++ b/lib/libc/include/generic-freebsd/fs/unionfs/union.h @@ -33,8 +33,6 @@ * 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. - * - * @(#)union.h 8.9 (Berkeley) 12/10/94 */ #ifdef _KERNEL @@ -99,15 +97,17 @@ struct unionfs_node { char *un_path; /* path */ int un_pathlen; /* strlen of path */ - int un_flag; /* unionfs node flag */ -}; -/* - * unionfs node flags - * It needs the vnode with exclusive lock, when changing the un_flag variable. - */ -#define UNIONFS_OPENEXTL 0x01 /* openextattr (lower) */ -#define UNIONFS_OPENEXTU 0x02 /* openextattr (upper) */ + /* + * unionfs node flags + * Changing these flags requires the vnode to be locked exclusive. + */ + #define UNIONFS_OPENEXTL 0x01 /* openextattr (lower) */ + #define UNIONFS_OPENEXTU 0x02 /* openextattr (upper) */ + #define UNIONFS_COPY_IN_PROGRESS 0x04 /* copy/dir shadow in progres */ + #define UNIONFS_LOOKUP_IN_PROGRESS 0x08 + unsigned int un_flag; /* unionfs node flag */ +}; extern struct vop_vector unionfs_vnodeops; @@ -133,34 +133,32 @@ int unionfs_uninit(struct vfsconf *); int unionfs_nodeget(struct mount *, struct vnode *, struct vnode *, struct vnode *, struct vnode **, struct componentname *); void unionfs_noderem(struct vnode *); +struct unionfs_node_status * unionfs_find_node_status(struct unionfs_node *, + struct thread *td); void unionfs_get_node_status(struct unionfs_node *, struct thread *, struct unionfs_node_status **); void unionfs_tryrem_node_status(struct unionfs_node *, struct unionfs_node_status *); int unionfs_check_rmdir(struct vnode *, struct ucred *, struct thread *td); -int unionfs_copyfile(struct unionfs_node *, int, struct ucred *, +int unionfs_copyfile(struct vnode *, int, struct ucred *, struct thread *); void unionfs_create_uppervattr_core(struct unionfs_mount *, struct vattr *, struct vattr *, struct thread *); int unionfs_create_uppervattr(struct unionfs_mount *, struct vnode *, struct vattr *, struct ucred *, struct thread *); -int unionfs_mkshadowdir(struct unionfs_mount *, struct vnode *, - struct unionfs_node *, struct componentname *, struct thread *); +int unionfs_mkshadowdir(struct vnode *, struct vnode *, + struct componentname *, struct thread *); int unionfs_mkwhiteout(struct vnode *, struct vnode *, struct componentname *, struct thread *, char *, int); int unionfs_relookup(struct vnode *, struct vnode **, struct componentname *, struct componentname *, struct thread *, char *, int, u_long); -int unionfs_relookup_for_create(struct vnode *, struct componentname *, - struct thread *); -int unionfs_relookup_for_delete(struct vnode *, struct componentname *, - struct thread *); -int unionfs_relookup_for_rename(struct vnode *, struct componentname *, - struct thread *); void unionfs_forward_vop_start_pair(struct vnode *, int *, struct vnode *, int *); bool unionfs_forward_vop_finish_pair(struct vnode *, struct vnode *, int, struct vnode *, struct vnode *, int); +int unionfs_set_in_progress_flag(struct vnode *, unsigned int); +void unionfs_clear_in_progress_flag(struct vnode *, unsigned int); static inline void unionfs_forward_vop_start(struct vnode *basevp, int *lkflags) diff --git a/lib/libc/include/generic-freebsd/fstab.h b/lib/libc/include/generic-freebsd/fstab.h index d43df2530ced..ab39157500a4 100644 --- a/lib/libc/include/generic-freebsd/fstab.h +++ b/lib/libc/include/generic-freebsd/fstab.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)fstab.h 8.1 (Berkeley) 6/2/93 */ #ifndef _FSTAB_H_ diff --git a/lib/libc/include/generic-freebsd/fts.h b/lib/libc/include/generic-freebsd/fts.h index ad16892a4cd7..69b271ac2b68 100644 --- a/lib/libc/include/generic-freebsd/fts.h +++ b/lib/libc/include/generic-freebsd/fts.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)fts.h 8.3 (Berkeley) 8/14/94 */ #ifndef _FTS_H_ @@ -36,35 +34,54 @@ #include +typedef struct _ftsent FTSENT; + typedef struct { - struct _ftsent *fts_cur; /* current node */ - struct _ftsent *fts_child; /* linked list of children */ - struct _ftsent **fts_array; /* sort array */ + FTSENT *fts_cur; /* current node */ + FTSENT *fts_child; /* linked list of children */ + FTSENT **fts_array; /* sort array */ __dev_t fts_dev; /* starting device # */ char *fts_path; /* path for this descent */ int fts_rfd; /* fd for root */ __size_t fts_pathlen; /* sizeof(path) */ __size_t fts_nitems; /* elements in the sort array */ - int (*fts_compar) /* compare function */ - (const struct _ftsent * const *, const struct _ftsent * const *); - -#define FTS_COMFOLLOW 0x001 /* follow command line symlinks */ -#define FTS_LOGICAL 0x002 /* logical walk */ -#define FTS_NOCHDIR 0x004 /* don't change directories */ -#define FTS_NOSTAT 0x008 /* don't get stat info */ -#define FTS_PHYSICAL 0x010 /* physical walk */ -#define FTS_SEEDOT 0x020 /* return dot and dot-dot */ -#define FTS_XDEV 0x040 /* don't cross devices */ -#define FTS_WHITEOUT 0x080 /* return whiteout information */ -#define FTS_OPTIONMASK 0x0ff /* valid user option mask */ - -#define FTS_NAMEONLY 0x100 /* (private) child names only */ -#define FTS_STOP 0x200 /* (private) unrecoverable error */ + union { + int (*fts_compar) /* compare function */ + (const FTSENT * const *, const FTSENT * const *); +#ifdef __BLOCKS__ + int (^fts_compar_b) + (const FTSENT * const *, const FTSENT * const *); +#else + void *fts_compar_b; +#endif /* __BLOCKS__ */ + }; + +/* valid for fts_open() */ +#define FTS_COMFOLLOW 0x000001 /* follow command line symlinks */ +#define FTS_LOGICAL 0x000002 /* logical walk */ +#define FTS_NOCHDIR 0x000004 /* don't change directories */ +#define FTS_NOSTAT 0x000008 /* don't get stat info */ +#define FTS_PHYSICAL 0x000010 /* physical walk */ +#define FTS_SEEDOT 0x000020 /* return dot and dot-dot */ +#define FTS_XDEV 0x000040 /* don't cross devices */ +#define FTS_WHITEOUT 0x000080 /* return whiteout information */ + /* 0x0100 is FTS_NAMEONLY below */ + /* 0x0200 was previously FTS_STOP */ +#define FTS_COMFOLLOWDIR 0x00400 /* like COMFOLLOW but directories only */ +#define FTS_NOSTAT_TYPE 0x000800 /* like NOSTAT but use d_type */ +#define FTS_OPTIONMASK 0x000cff /* valid user option mask */ + +/* valid only for fts_children() */ +#define FTS_NAMEONLY 0x000100 /* child names only */ + +/* internal use only */ +#define FTS_STOP 0x010000 /* unrecoverable error */ +#define FTS_COMPAR_B 0x020000 /* compare function is a block */ int fts_options; /* fts_open options, global flags */ void *fts_clientptr; /* thunk for sort function */ } FTS; -typedef struct _ftsent { +struct _ftsent { struct _ftsent *fts_cycle; /* cycle node */ struct _ftsent *fts_parent; /* parent directory */ struct _ftsent *fts_link; /* next file in directory */ @@ -116,7 +133,7 @@ typedef struct _ftsent { struct stat *fts_statp; /* stat(2) information */ char *fts_name; /* file name */ FTS *fts_fts; /* back pointer to main FTS */ -} FTSENT; +}; #include @@ -129,6 +146,10 @@ FTS *fts_get_stream(FTSENT *); #define fts_get_stream(ftsent) ((ftsent)->fts_fts) FTS *fts_open(char * const *, int, int (*)(const FTSENT * const *, const FTSENT * const *)); +#ifdef __BLOCKS__ +FTS *fts_open_b(char * const *, int, + int (^)(const FTSENT * const *, const FTSENT * const *)); +#endif /* __BLOCKS__ */ FTSENT *fts_read(FTS *); int fts_set(FTS *, FTSENT *, int); void fts_set_clientptr(FTS *, void *); diff --git a/lib/libc/include/generic-freebsd/geom/geom.h b/lib/libc/include/generic-freebsd/geom/geom.h index 88a50bfa792b..7c69b60d5386 100644 --- a/lib/libc/include/generic-freebsd/geom/geom.h +++ b/lib/libc/include/generic-freebsd/geom/geom.h @@ -282,7 +282,7 @@ void g_detach(struct g_consumer *cp); void g_error_provider(struct g_provider *pp, int error); struct g_provider *g_provider_by_name(char const *arg); int g_getattr__(const char *attr, struct g_consumer *cp, void *var, int len); -#define g_getattr(a, c, v) g_getattr__((a), (c), (v), sizeof *(v)) +#define g_getattr(a, c, v) g_getattr__((a), (c), (v), sizeof(*(v))) int g_handleattr(struct bio *bp, const char *attribute, const void *val, int len); int g_handleattr_int(struct bio *bp, const char *attribute, int val); @@ -417,7 +417,7 @@ g_free(void *ptr) static moduledata_t name##_mod = { \ #name, g_modevent, &class \ }; \ - DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND); + DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, SI_ORDER_THIRD); int g_is_geom_thread(struct thread *td); diff --git a/lib/libc/include/generic-freebsd/geom/label/g_label.h b/lib/libc/include/generic-freebsd/geom/label/g_label.h index 0ca929a1a81f..fb4755ced428 100644 --- a/lib/libc/include/generic-freebsd/geom/label/g_label.h +++ b/lib/libc/include/generic-freebsd/geom/label/g_label.h @@ -73,12 +73,12 @@ extern struct g_label_desc g_label_ufs_volume; extern struct g_label_desc g_label_iso9660; extern struct g_label_desc g_label_msdosfs; extern struct g_label_desc g_label_ext2fs; -extern struct g_label_desc g_label_reiserfs; extern struct g_label_desc g_label_ntfs; extern struct g_label_desc g_label_gpt; extern struct g_label_desc g_label_gpt_uuid; extern struct g_label_desc g_label_disk_ident; extern struct g_label_desc g_label_flashmap; +extern struct g_label_desc g_label_swaplinux; extern void g_label_rtrim(char *label, size_t size); #endif /* _KERNEL */ diff --git a/lib/libc/include/generic-freebsd/glob.h b/lib/libc/include/generic-freebsd/glob.h index d8c3f9017a6a..bfc40a034108 100644 --- a/lib/libc/include/generic-freebsd/glob.h +++ b/lib/libc/include/generic-freebsd/glob.h @@ -30,8 +30,6 @@ * 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. - * - * @(#)glob.h 8.1 (Berkeley) 6/2/93 */ #ifndef _GLOB_H_ @@ -52,8 +50,15 @@ typedef struct { size_t gl_offs; /* Reserved at beginning of gl_pathv. */ int gl_flags; /* Copy of flags parameter to glob. */ char **gl_pathv; /* List of paths matching pattern. */ - /* Copy of errfunc parameter to glob. */ - int (*gl_errfunc)(const char *, int); + /* Copy of error callback parameter to glob. */ + union { + int (*gl_errfunc)(const char *, int); +#ifdef __BLOCKS__ + int (^gl_errblk)(const char *, int); +#else + void *gl_errblk; +#endif + }; /* * Alternate filesystem access methods for glob; replacement @@ -92,6 +97,7 @@ typedef struct { #define GLOB_QUOTE 0x0400 /* Quote special chars with \. */ #define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */ #define GLOB_LIMIT 0x1000 /* limit number of returned paths */ +#define _GLOB_ERR_BLOCK 0x08000000 /* (internal) error callback is a block */ /* source compatibility, these are the old names */ #define GLOB_MAXPATH GLOB_LIMIT @@ -101,6 +107,10 @@ typedef struct { __BEGIN_DECLS int glob(const char * __restrict, int, int (*)(const char *, int), glob_t * __restrict); +#if defined(__BLOCKS__) && __BSD_VISIBLE +int glob_b(const char * __restrict, int, + int (^)(const char *, int), glob_t * __restrict); +#endif void globfree(glob_t *); __END_DECLS diff --git a/lib/libc/include/generic-freebsd/grp.h b/lib/libc/include/generic-freebsd/grp.h index 95de6bebef2d..1aa52223cf9d 100644 --- a/lib/libc/include/generic-freebsd/grp.h +++ b/lib/libc/include/generic-freebsd/grp.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)grp.h 8.2 (Berkeley) 1/21/94 */ #ifndef _GRP_H_ diff --git a/lib/libc/include/generic-freebsd/iconv.h b/lib/libc/include/generic-freebsd/iconv.h index 4a22166a1d15..39ca3f108a07 100644 --- a/lib/libc/include/generic-freebsd/iconv.h +++ b/lib/libc/include/generic-freebsd/iconv.h @@ -33,12 +33,10 @@ #ifndef _ICONV_H_ #define _ICONV_H_ -#include #include #include -#include #include #ifdef __cplusplus diff --git a/lib/libc/include/generic-freebsd/isofs/cd9660/cd9660_mount.h b/lib/libc/include/generic-freebsd/isofs/cd9660/cd9660_mount.h index 0af01c536ea6..b0e6f51a9f2e 100644 --- a/lib/libc/include/generic-freebsd/isofs/cd9660/cd9660_mount.h +++ b/lib/libc/include/generic-freebsd/isofs/cd9660/cd9660_mount.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)cd9660_mount.h 8.1 (Berkeley) 5/24/95 */ /* diff --git a/lib/libc/include/generic-freebsd/isofs/cd9660/cd9660_node.h b/lib/libc/include/generic-freebsd/isofs/cd9660/cd9660_node.h index 64fc930d89f2..d76640fdae9b 100644 --- a/lib/libc/include/generic-freebsd/isofs/cd9660/cd9660_node.h +++ b/lib/libc/include/generic-freebsd/isofs/cd9660/cd9660_node.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)cd9660_node.h 8.6 (Berkeley) 5/14/95 */ /* @@ -58,7 +56,7 @@ typedef struct { struct iso_node { struct vnode *i_vnode; /* vnode associated with this inode */ - cd_ino_t i_number; /* the identity of the inode */ + ino_t i_number; /* the identity of the inode */ /* we use the actual starting block of the file */ struct iso_mnt *i_mnt; /* filesystem associated with this inode */ struct lockf *i_lockf; /* head of byte-level lock list */ diff --git a/lib/libc/include/generic-freebsd/isofs/cd9660/cd9660_rrip.h b/lib/libc/include/generic-freebsd/isofs/cd9660/cd9660_rrip.h index d120dd014742..d9d3c474362c 100644 --- a/lib/libc/include/generic-freebsd/isofs/cd9660/cd9660_rrip.h +++ b/lib/libc/include/generic-freebsd/isofs/cd9660/cd9660_rrip.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)cd9660_rrip.h 8.2 (Berkeley) 12/5/94 */ #ifndef _ISOFS_CD9660_CD9660_RRIP_H_ diff --git a/lib/libc/include/generic-freebsd/isofs/cd9660/iso.h b/lib/libc/include/generic-freebsd/isofs/cd9660/iso.h index 332c0c5d8311..ba65e04d7f93 100644 --- a/lib/libc/include/generic-freebsd/isofs/cd9660/iso.h +++ b/lib/libc/include/generic-freebsd/isofs/cd9660/iso.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)iso.h 8.6 (Berkeley) 5/10/95 */ #ifndef _ISOFS_CD9660_ISO_H_ @@ -214,21 +212,12 @@ struct iso_extended_attributes { u_char len_au [ISODCL (247, 250)]; /* 723 */ }; -#ifdef _KERNEL +#if defined(_KERNEL) || defined(_WANT_ISO_MNT) /* CD-ROM Format type */ enum ISO_FTYPE { ISO_FTYPE_DEFAULT, ISO_FTYPE_9660, ISO_FTYPE_RRIP, ISO_FTYPE_JOLIET, ISO_FTYPE_ECMA, ISO_FTYPE_HIGH_SIERRA }; -#ifndef ISOFSMNT_ROOT -#define ISOFSMNT_ROOT 0 -#endif - -/* - * When ino_t becomes 64-bit, we can remove this definition in favor of ino_t. - */ -typedef __uint64_t cd_ino_t; - struct iso_mnt { uint64_t im_flags; @@ -264,12 +253,16 @@ struct iso_mnt { void *im_l2d; }; +#endif /* defined(_KERNEL) || defined(_WANT_ISO_MNT) */ + +#ifdef _KERNEL + struct ifid { u_short ifid_len; u_short ifid_pad; - cd_ino_t ifid_ino; + ino_t ifid_ino; long ifid_start; -}; +} __packed; #define VFSTOISOFS(mp) ((struct iso_mnt *)((mp)->mnt_data)) @@ -278,7 +271,7 @@ struct ifid { #define lblkno(imp, loc) ((loc) >> (imp)->im_bshift) #define blksize(imp, ip, lbn) ((imp)->logical_block_size) -int cd9660_vget_internal(struct mount *, cd_ino_t, int, struct vnode **, int, +int cd9660_vget_internal(struct mount *, ino_t , int, struct vnode **, int, struct iso_directory_record *); #define cd9660_sysctl ((int (*)(int *, u_int, void *, size_t *, void *, \ size_t, struct proc *))eopnotsupp) @@ -289,7 +282,7 @@ extern struct vop_vector cd9660_fifoops; int isochar(u_char *, u_char *, int, u_short *, int *, int, void *); int isofncmp(u_char *, int, u_char *, int, int, int, void *, void *); void isofntrans(u_char *, int, u_char *, u_short *, int, int, int, int, void *); -cd_ino_t isodirino(struct iso_directory_record *, struct iso_mnt *); +ino_t isodirino(struct iso_directory_record *, struct iso_mnt *); u_short sgetrune(const char *, size_t, char const **, int, void *); #endif /* _KERNEL */ diff --git a/lib/libc/include/generic-freebsd/isofs/cd9660/iso_rrip.h b/lib/libc/include/generic-freebsd/isofs/cd9660/iso_rrip.h index c899ca42f726..d4b6d59dd47d 100644 --- a/lib/libc/include/generic-freebsd/isofs/cd9660/iso_rrip.h +++ b/lib/libc/include/generic-freebsd/isofs/cd9660/iso_rrip.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)iso_rrip.h 8.2 (Berkeley) 1/23/94 */ #ifndef _ISOFS_CD9660_ISO_RRIP_H_ @@ -65,7 +63,7 @@ typedef struct { off_t iso_ce_off; /* offset of continuation area */ int iso_ce_len; /* length of continuation area */ struct iso_mnt *imp; /* mount structure */ - cd_ino_t *inump; /* inode number pointer */ + ino_t *inump; /* inode number pointer */ char *outbuf; /* name/symbolic link output area */ u_short *outlen; /* length of above */ u_short maxlen; /* maximum length of above */ @@ -78,7 +76,7 @@ int cd9660_rrip_analyze(struct iso_directory_record *isodir, struct iso_node *inop, struct iso_mnt *imp); int cd9660_rrip_getname(struct iso_directory_record *isodir, char *outbuf, u_short *outlen, - cd_ino_t *inump, struct iso_mnt *imp); + ino_t *inump, struct iso_mnt *imp); int cd9660_rrip_getsymname(struct iso_directory_record *isodir, char *outbuf, u_short *outlen, struct iso_mnt *imp); diff --git a/lib/libc/include/generic-freebsd/libsys.h b/lib/libc/include/generic-freebsd/libsys.h new file mode 100644 index 000000000000..6e24496c4688 --- /dev/null +++ b/lib/libc/include/generic-freebsd/libsys.h @@ -0,0 +1,25 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 SRI International + * + * This software was developed by SRI International, the University of + * Cambridge Computer Laboratory (Department of Computer Science and + * Technology), and Capabilities Limited under Defense Advanced Research + * Projects Agency (DARPA) Contract No. FA8750-24-C-B047 ("DEC"). + */ + +#ifndef _LIBSYS_H_ +#define _LIBSYS_H_ + +#include + +#include <_libsys.h> + +typedef int (__sys_syscall_t)(int number, ...); +typedef int (__sys___syscall_t)(int64_t number, ...); + +int __sys_syscall(int number, ...); +off_t __sys___syscall(int64_t number, ...); + +#endif /* _LIBSYS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/libutil.h b/lib/libc/include/generic-freebsd/libutil.h index 10cff683f737..877f02103464 100644 --- a/lib/libc/include/generic-freebsd/libutil.h +++ b/lib/libc/include/generic-freebsd/libutil.h @@ -86,10 +86,17 @@ struct termios; struct winsize; __BEGIN_DECLS -char *auth_getval(const char *_name); void clean_environment(const char * const *_white, const char * const *_more_white); -int expand_number(const char *_buf, uint64_t *_num); +int expand_number(const char *_buf, int64_t *_num); +int expand_unsigned(const char *_buf, uint64_t *_num); +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \ + __has_extension(c_generic_selections) +#define expand_number(_buf, _num) \ + _Generic((_num), \ + uint64_t *: expand_unsigned, \ + default: expand_number)((_buf), (_num)) +#endif int extattr_namespace_to_string(int _attrnamespace, char **_string); int extattr_string_to_namespace(const char *_string, int *_attrnamespace); int flopen(const char *_path, int _flags, ...); @@ -213,7 +220,13 @@ int cpuset_parselist(const char *list, cpuset_t *mask); #define CPUSET_PARSE_OK 0 #define CPUSET_PARSE_GETAFFINITY -1 #define CPUSET_PARSE_ERROR -2 -#define CPUSET_PARSE_INVALID_CPU -3 +#define CPUSET_PARSE_OUT_OF_RANGE -3 +#define CPUSET_PARSE_GETDOMAIN -4 +#define CPUSET_PARSE_INVALID_CPU CPUSET_PARSE_OUT_OF_RANGE /* backwards compat */ +#endif + +#ifdef _SYS_DOMAINSET_H_ +int domainset_parselist(const char *list, domainset_t *mask, int *policyp); #endif __END_DECLS diff --git a/lib/libc/include/generic-freebsd/limits.h b/lib/libc/include/generic-freebsd/limits.h index e711c34db2e9..21fcd0e682fd 100644 --- a/lib/libc/include/generic-freebsd/limits.h +++ b/lib/libc/include/generic-freebsd/limits.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)limits.h 8.2 (Berkeley) 1/4/94 */ #ifndef _LIMITS_H_ @@ -139,6 +137,11 @@ #define MB_LEN_MAX 6 /* 31-bit UTF-8 */ +#if __POSIX_VISIBLE >= 202405 +#define GETENTROPY_MAX 256 +#define NSIG_MAX 128 /* _SIG_MAXSIG from */ +#endif + #include #if __POSIX_VISIBLE diff --git a/lib/libc/include/generic-freebsd/locale.h b/lib/libc/include/generic-freebsd/locale.h index d780f93db618..82b4c6423a35 100644 --- a/lib/libc/include/generic-freebsd/locale.h +++ b/lib/libc/include/generic-freebsd/locale.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)locale.h 8.1 (Berkeley) 6/2/93 */ #ifndef _LOCALE_H_ diff --git a/lib/libc/include/generic-freebsd/machine/_align.h b/lib/libc/include/generic-freebsd/machine/_align.h index d7a186a2eb09..4af6dd67a7aa 100644 --- a/lib/libc/include/generic-freebsd/machine/_align.h +++ b/lib/libc/include/generic-freebsd/machine/_align.h @@ -1,53 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2001 David E. O'Brien - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * William Jolitz. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)param.h 5.8 (Berkeley) 6/28/91 + * This file is in the public domain. */ -#ifndef _POWERPC_INCLUDE__ALIGN_H_ -#define _POWERPC_INCLUDE__ALIGN_H_ - -/* - * Round p (pointer or byte index) up to a correctly-aligned value - * for all data types (int, long, ...). The result is unsigned int - * and must be cast to any desired pointer type. - */ -#define _ALIGNBYTES (sizeof(register_t) - 1) -#define _ALIGN(p) (((uintptr_t)(p) + _ALIGNBYTES) & ~_ALIGNBYTES) - -#endif /* !_POWERPC_INCLUDE__ALIGN_H_ */ \ No newline at end of file +#include \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/_bus.h b/lib/libc/include/generic-freebsd/machine/_bus.h index 409470a3657c..684d5496d9f3 100644 --- a/lib/libc/include/generic-freebsd/machine/_bus.h +++ b/lib/libc/include/generic-freebsd/machine/_bus.h @@ -1,47 +1,28 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2005 M. Warner Losh + * Copyright (c) 2005 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, - * without modification, immediately at the beginning of the file. - * 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. + * SPDX-License-Identifier: BSD-2-Clause * - * 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. + * Derived in part from NetBSD's bus.h files by (alphabetically): + * Christopher G. Demetriou + * Charles M. Hannum + * Jason Thorpe + * The NetBSD Foundation. */ -#ifndef POWERPC_INCLUDE__BUS_H -#define POWERPC_INCLUDE__BUS_H - -#include +#ifndef _MACHINE__BUS_H_ +#define _MACHINE__BUS_H_ /* - * Bus address and size types + * Addresses (in bus space). */ -typedef vm_paddr_t bus_addr_t; -typedef vm_size_t bus_size_t; +typedef u_long bus_addr_t; +typedef u_long bus_size_t; /* - * Access methods for bus resources and address space. + * Access methods for bus space. */ +typedef u_long bus_space_handle_t; typedef struct bus_space *bus_space_tag_t; -typedef vm_offset_t bus_space_handle_t; -#endif /* POWERPC_INCLUDE__BUS_H */ \ No newline at end of file +#endif /* !_MACHINE__BUS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/_inttypes.h b/lib/libc/include/generic-freebsd/machine/_inttypes.h index 770c91e43415..218f00871b16 100644 --- a/lib/libc/include/generic-freebsd/machine/_inttypes.h +++ b/lib/libc/include/generic-freebsd/machine/_inttypes.h @@ -1,222 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Klaus Klein. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * From: $NetBSD: int_fmtio.h,v 1.2 2001/04/26 16:25:21 kleink Exp $ + * This file is in the public domain. */ -#ifndef _MACHINE_INTTYPES_H_ -#define _MACHINE_INTTYPES_H_ - -/* - * Macros for format specifiers. - */ - -#ifdef __LP64__ -#define __PRI64 "l" -#define __PRIptr "l" -#else -#define __PRI64 "ll" -#define __PRIptr -#endif - -/* fprintf(3) macros for signed integers. */ - -#define PRId8 "d" /* int8_t */ -#define PRId16 "d" /* int16_t */ -#define PRId32 "d" /* int32_t */ -#define PRId64 __PRI64"d" /* int64_t */ -#define PRIdLEAST8 "d" /* int_least8_t */ -#define PRIdLEAST16 "d" /* int_least16_t */ -#define PRIdLEAST32 "d" /* int_least32_t */ -#define PRIdLEAST64 __PRI64"d" /* int_least64_t */ -#define PRIdFAST8 "d" /* int_fast8_t */ -#define PRIdFAST16 "d" /* int_fast16_t */ -#define PRIdFAST32 "d" /* int_fast32_t */ -#define PRIdFAST64 __PRI64"d" /* int_fast64_t */ -#define PRIdMAX "jd" /* intmax_t */ -#define PRIdPTR __PRIptr"d" /* intptr_t */ - -#define PRIi8 "i" /* int8_t */ -#define PRIi16 "i" /* int16_t */ -#define PRIi32 "i" /* int32_t */ -#define PRIi64 __PRI64"i" /* int64_t */ -#define PRIiLEAST8 "i" /* int_least8_t */ -#define PRIiLEAST16 "i" /* int_least16_t */ -#define PRIiLEAST32 "i" /* int_least32_t */ -#define PRIiLEAST64 __PRI64"i" /* int_least64_t */ -#define PRIiFAST8 "i" /* int_fast8_t */ -#define PRIiFAST16 "i" /* int_fast16_t */ -#define PRIiFAST32 "i" /* int_fast32_t */ -#define PRIiFAST64 __PRI64"i" /* int_fast64_t */ -#define PRIiMAX "ji" /* intmax_t */ -#define PRIiPTR __PRIptr"i" /* intptr_t */ - -/* fprintf(3) macros for unsigned integers. */ - -#define PRIo8 "o" /* uint8_t */ -#define PRIo16 "o" /* uint16_t */ -#define PRIo32 "o" /* uint32_t */ -#define PRIo64 __PRI64"o" /* uint64_t */ -#define PRIoLEAST8 "o" /* uint_least8_t */ -#define PRIoLEAST16 "o" /* uint_least16_t */ -#define PRIoLEAST32 "o" /* uint_least32_t */ -#define PRIoLEAST64 __PRI64"o" /* uint_least64_t */ -#define PRIoFAST8 "o" /* uint_fast8_t */ -#define PRIoFAST16 "o" /* uint_fast16_t */ -#define PRIoFAST32 "o" /* uint_fast32_t */ -#define PRIoFAST64 __PRI64"o" /* uint_fast64_t */ -#define PRIoMAX "jo" /* uintmax_t */ -#define PRIoPTR __PRIptr"o" /* uintptr_t */ - -#define PRIu8 "u" /* uint8_t */ -#define PRIu16 "u" /* uint16_t */ -#define PRIu32 "u" /* uint32_t */ -#define PRIu64 __PRI64"u" /* uint64_t */ -#define PRIuLEAST8 "u" /* uint_least8_t */ -#define PRIuLEAST16 "u" /* uint_least16_t */ -#define PRIuLEAST32 "u" /* uint_least32_t */ -#define PRIuLEAST64 __PRI64"u" /* uint_least64_t */ -#define PRIuFAST8 "u" /* uint_fast8_t */ -#define PRIuFAST16 "u" /* uint_fast16_t */ -#define PRIuFAST32 "u" /* uint_fast32_t */ -#define PRIuFAST64 __PRI64"u" /* uint_fast64_t */ -#define PRIuMAX "ju" /* uintmax_t */ -#define PRIuPTR __PRIptr"u" /* uintptr_t */ - -#define PRIx8 "x" /* uint8_t */ -#define PRIx16 "x" /* uint16_t */ -#define PRIx32 "x" /* uint32_t */ -#define PRIx64 __PRI64"x" /* uint64_t */ -#define PRIxLEAST8 "x" /* uint_least8_t */ -#define PRIxLEAST16 "x" /* uint_least16_t */ -#define PRIxLEAST32 "x" /* uint_least32_t */ -#define PRIxLEAST64 __PRI64"x" /* uint_least64_t */ -#define PRIxFAST8 "x" /* uint_fast8_t */ -#define PRIxFAST16 "x" /* uint_fast16_t */ -#define PRIxFAST32 "x" /* uint_fast32_t */ -#define PRIxFAST64 __PRI64"x" /* uint_fast64_t */ -#define PRIxMAX "jx" /* uintmax_t */ -#define PRIxPTR __PRIptr"x" /* uintptr_t */ - -#define PRIX8 "X" /* uint8_t */ -#define PRIX16 "X" /* uint16_t */ -#define PRIX32 "X" /* uint32_t */ -#define PRIX64 __PRI64"X" /* uint64_t */ -#define PRIXLEAST8 "X" /* uint_least8_t */ -#define PRIXLEAST16 "X" /* uint_least16_t */ -#define PRIXLEAST32 "X" /* uint_least32_t */ -#define PRIXLEAST64 __PRI64"X" /* uint_least64_t */ -#define PRIXFAST8 "X" /* uint_fast8_t */ -#define PRIXFAST16 "X" /* uint_fast16_t */ -#define PRIXFAST32 "X" /* uint_fast32_t */ -#define PRIXFAST64 __PRI64"X" /* uint_fast64_t */ -#define PRIXMAX "jX" /* uintmax_t */ -#define PRIXPTR __PRIptr"X" /* uintptr_t */ - -/* fscanf(3) macros for signed integers. */ - -#define SCNd8 "hhd" /* int8_t */ -#define SCNd16 "hd" /* int16_t */ -#define SCNd32 "d" /* int32_t */ -#define SCNd64 __PRI64"d" /* int64_t */ -#define SCNdLEAST8 "hhd" /* int_least8_t */ -#define SCNdLEAST16 "hd" /* int_least16_t */ -#define SCNdLEAST32 "d" /* int_least32_t */ -#define SCNdLEAST64 __PRI64"d" /* int_least64_t */ -#define SCNdFAST8 "d" /* int_fast8_t */ -#define SCNdFAST16 "d" /* int_fast16_t */ -#define SCNdFAST32 "d" /* int_fast32_t */ -#define SCNdFAST64 __PRI64"d" /* int_fast64_t */ -#define SCNdMAX "jd" /* intmax_t */ -#define SCNdPTR __PRIptr"d" /* intptr_t */ - -#define SCNi8 "hhi" /* int8_t */ -#define SCNi16 "hi" /* int16_t */ -#define SCNi32 "i" /* int32_t */ -#define SCNi64 __PRI64"i" /* int64_t */ -#define SCNiLEAST8 "hhi" /* int_least8_t */ -#define SCNiLEAST16 "hi" /* int_least16_t */ -#define SCNiLEAST32 "i" /* int_least32_t */ -#define SCNiLEAST64 __PRI64"i" /* int_least64_t */ -#define SCNiFAST8 "i" /* int_fast8_t */ -#define SCNiFAST16 "i" /* int_fast16_t */ -#define SCNiFAST32 "i" /* int_fast32_t */ -#define SCNiFAST64 __PRI64"i" /* int_fast64_t */ -#define SCNiMAX "ji" /* intmax_t */ -#define SCNiPTR __PRIptr"i" /* intptr_t */ - -/* fscanf(3) macros for unsigned integers. */ - -#define SCNo8 "hho" /* uint8_t */ -#define SCNo16 "ho" /* uint16_t */ -#define SCNo32 "o" /* uint32_t */ -#define SCNo64 __PRI64"o" /* uint64_t */ -#define SCNoLEAST8 "hho" /* uint_least8_t */ -#define SCNoLEAST16 "ho" /* uint_least16_t */ -#define SCNoLEAST32 "o" /* uint_least32_t */ -#define SCNoLEAST64 __PRI64"o" /* uint_least64_t */ -#define SCNoFAST8 "o" /* uint_fast8_t */ -#define SCNoFAST16 "o" /* uint_fast16_t */ -#define SCNoFAST32 "o" /* uint_fast32_t */ -#define SCNoFAST64 __PRI64"o" /* uint_fast64_t */ -#define SCNoMAX "jo" /* uintmax_t */ -#define SCNoPTR __PRIptr"o" /* uintptr_t */ - -#define SCNu8 "hhu" /* uint8_t */ -#define SCNu16 "hu" /* uint16_t */ -#define SCNu32 "u" /* uint32_t */ -#define SCNu64 __PRI64"u" /* uint64_t */ -#define SCNuLEAST8 "hhu" /* uint_least8_t */ -#define SCNuLEAST16 "hu" /* uint_least16_t */ -#define SCNuLEAST32 "u" /* uint_least32_t */ -#define SCNuLEAST64 __PRI64"u" /* uint_least64_t */ -#define SCNuFAST8 "u" /* uint_fast8_t */ -#define SCNuFAST16 "u" /* uint_fast16_t */ -#define SCNuFAST32 "u" /* uint_fast32_t */ -#define SCNuFAST64 __PRI64"u" /* uint_fast64_t */ -#define SCNuMAX "ju" /* uintmax_t */ -#define SCNuPTR __PRIptr"u" /* uintptr_t */ - -#define SCNx8 "hhx" /* uint8_t */ -#define SCNx16 "hx" /* uint16_t */ -#define SCNx32 "x" /* uint32_t */ -#define SCNx64 __PRI64"x" /* uint64_t */ -#define SCNxLEAST8 "hhx" /* uint_least8_t */ -#define SCNxLEAST16 "hx" /* uint_least16_t */ -#define SCNxLEAST32 "x" /* uint_least32_t */ -#define SCNxLEAST64 __PRI64"x" /* uint_least64_t */ -#define SCNxFAST8 "x" /* uint_fast8_t */ -#define SCNxFAST16 "x" /* uint_fast16_t */ -#define SCNxFAST32 "x" /* uint_fast32_t */ -#define SCNxFAST64 __PRI64"x" /* uint_fast64_t */ -#define SCNxMAX "jx" /* uintmax_t */ -#define SCNxPTR __PRIptr"x" /* uintptr_t */ - -#endif /* !_MACHINE_INTTYPES_H_ */ \ No newline at end of file +#include \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/_limits.h b/lib/libc/include/generic-freebsd/machine/_limits.h index fd8ab8e08a93..71d8b62434e1 100644 --- a/lib/libc/include/generic-freebsd/machine/_limits.h +++ b/lib/libc/include/generic-freebsd/machine/_limits.h @@ -1,98 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)limits.h 8.3 (Berkeley) 1/4/94 + * This file is in the public domain. */ -#ifndef _MACHINE__LIMITS_H_ -#define _MACHINE__LIMITS_H_ - -/* - * According to ANSI (section 2.2.4.2), the values below must be usable by - * #if preprocessing directives. Additionally, the expression must have the - * same type as would an expression that is an object of the corresponding - * type converted according to the integral promotions. The subtraction for - * INT_MIN, etc., is so the value is not unsigned; e.g., 0x80000000 is an - * unsigned int for 32-bit two's complement ANSI compilers (section 3.1.3.2). - */ - -#define __CHAR_BIT 8 /* number of bits in a char */ - -#define __SCHAR_MAX 0x7f /* max value for a signed char */ -#define __SCHAR_MIN (-0x7f - 1) /* min value for a signed char */ - -#define __UCHAR_MAX 0xff /* max value for an unsigned char */ - -#define __USHRT_MAX 0xffff /* max value for an unsigned short */ -#define __SHRT_MAX 0x7fff /* max value for a short */ -#define __SHRT_MIN (-0x7fff - 1) /* min value for a short */ - -#define __UINT_MAX 0xffffffff /* max value for an unsigned int */ -#define __INT_MAX 0x7fffffff /* max value for an int */ -#define __INT_MIN (-0x7fffffff - 1) /* min value for an int */ - -#ifdef __LP64__ -#define __ULONG_MAX 0xffffffffffffffff -#define __LONG_MAX 0x7fffffffffffffff -#define __LONG_MIN (-0x7fffffffffffffff - 1) -#define __LONG_BIT 64 -#else -#define __ULONG_MAX 0xffffffffUL /* max value for an unsigned long */ -#define __LONG_MAX 0x7fffffffL /* max value for a long */ -#define __LONG_MIN (-0x7fffffffL - 1) /* min value for a long */ -#define __LONG_BIT 32 -#endif - -#define __ULLONG_MAX 0xffffffffffffffffULL -#define __LLONG_MAX 0x7fffffffffffffffLL /* max value for a long long */ -#define __LLONG_MIN (-0x7fffffffffffffffLL - 1) /* min for a long long */ - -#ifdef __LP64__ -#define __SSIZE_MAX __LONG_MAX /* max value for a ssize_t */ -#define __SIZE_T_MAX __ULONG_MAX /* max value for a size_t */ -#else -#define __SSIZE_MAX __INT_MAX /* max value for a ssize_t */ -#define __SIZE_T_MAX __UINT_MAX /* max value for a size_t */ -#endif - -#define __OFF_MAX __LLONG_MAX /* max value for an off_t */ -#define __OFF_MIN __LLONG_MIN /* min value for an off_t */ - -/* Quads and long longs are the same size. Ensure they stay in sync. */ -#define __UQUAD_MAX __ULLONG_MAX /* max value for a uquad_t */ -#define __QUAD_MAX __LLONG_MAX /* max value for a quad_t */ -#define __QUAD_MIN __LLONG_MIN /* min value for a quad_t */ - -#define __WORD_BIT 32 - -/* Minimum signal stack size. */ -#define __MINSIGSTKSZ (512 * 4) - -#endif /* !_MACHINE__LIMITS_H_ */ \ No newline at end of file +#include \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/_stdint.h b/lib/libc/include/generic-freebsd/machine/_stdint.h index 6111b8467c09..4fb2b3fb4ada 100644 --- a/lib/libc/include/generic-freebsd/machine/_stdint.h +++ b/lib/libc/include/generic-freebsd/machine/_stdint.h @@ -1,200 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2001, 2002 Mike Barcroft - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Klaus Klein. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * This file is in the public domain. */ -#ifndef _MACHINE__STDINT_H_ -#define _MACHINE__STDINT_H_ - -#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) - -#define INT8_C(c) (c) -#define INT16_C(c) (c) -#define INT32_C(c) (c) - -#define UINT8_C(c) (c) -#define UINT16_C(c) (c) -#define UINT32_C(c) (c ## U) - -#ifdef __LP64__ -#define INT64_C(c) (c ## L) -#define UINT64_C(c) (c ## UL) -#else -#define INT64_C(c) (c ## LL) -#define UINT64_C(c) (c ## ULL) -#endif - -#define INTMAX_C(c) INT64_C(c) -#define UINTMAX_C(c) UINT64_C(c) - -#endif /* !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) */ - -#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) - -#ifndef __INT64_C -#ifdef __LP64__ -#define __INT64_C(c) (c ## L) -#define __UINT64_C(c) (c ## UL) -#else -#define __INT64_C(c) (c ## LL) -#define __UINT64_C(c) (c ## ULL) -#endif -#endif - -/* - * ISO/IEC 9899:1999 - * 7.18.2.1 Limits of exact-width integer types - */ -/* Minimum values of exact-width signed integer types. */ -#define INT8_MIN (-0x7f-1) -#define INT16_MIN (-0x7fff-1) -#define INT32_MIN (-0x7fffffff-1) -#define INT64_MIN (-__INT64_C(0x7fffffffffffffff)-1) - -/* Maximum values of exact-width signed integer types. */ -#define INT8_MAX 0x7f -#define INT16_MAX 0x7fff -#define INT32_MAX 0x7fffffff -#define INT64_MAX __INT64_C(0x7fffffffffffffff) - -/* Maximum values of exact-width unsigned integer types. */ -#define UINT8_MAX 0xff -#define UINT16_MAX 0xffff -#define UINT32_MAX 0xffffffff -#define UINT64_MAX __UINT64_C(0xffffffffffffffff) - -/* - * ISO/IEC 9899:1999 - * 7.18.2.2 Limits of minimum-width integer types - */ -/* Minimum values of minimum-width signed integer types. */ -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST64_MIN INT64_MIN - -/* Maximum values of minimum-width signed integer types. */ -#define INT_LEAST8_MAX INT8_MAX -#define INT_LEAST16_MAX INT16_MAX -#define INT_LEAST32_MAX INT32_MAX -#define INT_LEAST64_MAX INT64_MAX - -/* Maximum values of minimum-width unsigned integer types. */ -#define UINT_LEAST8_MAX UINT8_MAX -#define UINT_LEAST16_MAX UINT16_MAX -#define UINT_LEAST32_MAX UINT32_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -/* - * ISO/IEC 9899:1999 - * 7.18.2.3 Limits of fastest minimum-width integer types - */ -/* Minimum values of fastest minimum-width signed integer types. */ -#define INT_FAST8_MIN INT32_MIN -#define INT_FAST16_MIN INT32_MIN -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST64_MIN INT64_MIN - -/* Maximum values of fastest minimum-width signed integer types. */ -#define INT_FAST8_MAX INT32_MAX -#define INT_FAST16_MAX INT32_MAX -#define INT_FAST32_MAX INT32_MAX -#define INT_FAST64_MAX INT64_MAX - -/* Maximum values of fastest minimum-width unsigned integer types. */ -#define UINT_FAST8_MAX UINT32_MAX -#define UINT_FAST16_MAX UINT32_MAX -#define UINT_FAST32_MAX UINT32_MAX -#define UINT_FAST64_MAX UINT64_MAX - -/* - * ISO/IEC 9899:1999 - * 7.18.2.4 Limits of integer types capable of holding object pointers - */ -#ifdef __LP64__ -#define INTPTR_MIN INT64_MIN -#define INTPTR_MAX INT64_MAX -#define UINTPTR_MAX UINT64_MAX -#else -#define INTPTR_MIN INT32_MIN -#define INTPTR_MAX INT32_MAX -#define UINTPTR_MAX UINT32_MAX -#endif - -/* - * ISO/IEC 9899:1999 - * 7.18.2.5 Limits of greatest-width integer types - */ -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -/* - * ISO/IEC 9899:1999 - * 7.18.3 Limits of other integer types - */ -#ifdef __LP64__ -/* Limits of ptrdiff_t. */ -#define PTRDIFF_MIN INT64_MIN -#define PTRDIFF_MAX INT64_MAX - -/* Limits of sig_atomic_t. */ -#define SIG_ATOMIC_MIN INT64_MIN -#define SIG_ATOMIC_MAX INT64_MAX - -/* Limit of size_t. */ -#define SIZE_MAX UINT64_MAX -#else -/* Limits of ptrdiff_t. */ -#define PTRDIFF_MIN INT32_MIN -#define PTRDIFF_MAX INT32_MAX - -/* Limits of sig_atomic_t. */ -#define SIG_ATOMIC_MIN INT32_MIN -#define SIG_ATOMIC_MAX INT32_MAX - -/* Limit of size_t. */ -#define SIZE_MAX UINT32_MAX -#endif - -/* Limits of wint_t. */ -#define WINT_MIN INT32_MIN -#define WINT_MAX INT32_MAX - -#endif /* !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) */ - -#endif /* !_MACHINE__STDINT_H_ */ \ No newline at end of file +#include \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/_types.h b/lib/libc/include/generic-freebsd/machine/_types.h index 889fdffe74d1..da8cb16909c4 100644 --- a/lib/libc/include/generic-freebsd/machine/_types.h +++ b/lib/libc/include/generic-freebsd/machine/_types.h @@ -1,92 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2002 Mike Barcroft - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * From: @(#)ansi.h 8.2 (Berkeley) 1/4/94 - * From: @(#)types.h 8.3 (Berkeley) 1/5/94 + * This file is in the public domain. */ -#ifndef _MACHINE__TYPES_H_ -#define _MACHINE__TYPES_H_ - -#ifndef _SYS__TYPES_H_ -#error do not include this header, use sys/_types.h -#endif - -/* - * Standard type definitions. - */ -typedef __uint32_t __clock_t; /* clock()... */ -#ifndef _STANDALONE -typedef double __double_t; -typedef float __float_t; -#endif -#ifdef __LP64__ -typedef __int64_t __critical_t; -#else -typedef __int32_t __critical_t; -#endif -typedef __int32_t __int_fast8_t; -typedef __int32_t __int_fast16_t; -typedef __int32_t __int_fast32_t; -typedef __int64_t __int_fast64_t; -#ifdef __LP64__ -typedef __int64_t __register_t; -typedef __int64_t __segsz_t; /* segment size (in pages) */ -#else -typedef __int32_t __register_t; -typedef __int32_t __segsz_t; /* segment size (in pages) */ -#endif -typedef __int64_t __time_t; /* time()... */ -typedef __uint32_t __uint_fast8_t; -typedef __uint32_t __uint_fast16_t; -typedef __uint32_t __uint_fast32_t; -typedef __uint64_t __uint_fast64_t; -#ifdef __LP64__ -typedef __uint64_t __u_register_t; -typedef __uint64_t __vm_paddr_t; -#else -typedef __uint32_t __u_register_t; -#ifdef BOOKE -typedef __uint64_t __vm_paddr_t; -#else -typedef __uint32_t __vm_paddr_t; -#endif -#endif -typedef int ___wchar_t; - -#define __WCHAR_MIN __INT_MIN /* min value for a wchar_t */ -#define __WCHAR_MAX __INT_MAX /* max value for a wchar_t */ - -#endif /* !_MACHINE__TYPES_H_ */ \ No newline at end of file +#include \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/atomic.h b/lib/libc/include/generic-freebsd/machine/atomic.h deleted file mode 100644 index eb9ab520c9af..000000000000 --- a/lib/libc/include/generic-freebsd/machine/atomic.h +++ /dev/null @@ -1,1148 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2008 Marcel Moolenaar - * Copyright (c) 2001 Benno Rice - * Copyright (c) 2001 David E. O'Brien - * Copyright (c) 1998 Doug Rabson - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _MACHINE_ATOMIC_H_ -#define _MACHINE_ATOMIC_H_ - -#include - -#ifndef __powerpc64__ -#include -#endif - -/* - * The __ATOMIC_REL/ACQ() macros provide memory barriers only in conjunction - * with the atomic lXarx/stXcx. sequences below. They are not exposed outside - * of this file. See also Appendix B.2 of Book II of the architecture manual. - * - * Note that not all Book-E processors accept the light-weight sync variant. - * In particular, early models of E500 cores are known to wedge. Bank on all - * 64-bit capable CPUs to accept lwsync properly and pressimize 32-bit CPUs - * to use the heavier-weight sync. - */ - -#ifdef __powerpc64__ -#define mb() __asm __volatile("sync" : : : "memory") -#define rmb() __asm __volatile("lwsync" : : : "memory") -#define wmb() __asm __volatile("lwsync" : : : "memory") -#define __ATOMIC_REL() __asm __volatile("lwsync" : : : "memory") -#define __ATOMIC_ACQ() __asm __volatile("isync" : : : "memory") -#else -#define mb() __asm __volatile("sync" : : : "memory") -#define rmb() __asm __volatile("sync" : : : "memory") -#define wmb() __asm __volatile("sync" : : : "memory") -#define __ATOMIC_REL() __asm __volatile("sync" : : : "memory") -#define __ATOMIC_ACQ() __asm __volatile("isync" : : : "memory") -#endif - -static __inline void -powerpc_lwsync(void) -{ - -#ifdef __powerpc64__ - __asm __volatile("lwsync" : : : "memory"); -#else - __asm __volatile("sync" : : : "memory"); -#endif -} - -/* - * atomic_add(p, v) - * { *p += v; } - */ - -#define __atomic_add_int(p, v, t) \ - __asm __volatile( \ - "1: lwarx %0, 0, %2\n" \ - " add %0, %3, %0\n" \ - " stwcx. %0, 0, %2\n" \ - " bne- 1b\n" \ - : "=&r" (t), "=m" (*p) \ - : "r" (p), "r" (v), "m" (*p) \ - : "cr0", "memory") \ - /* __atomic_add_int */ - -#ifdef __powerpc64__ -#define __atomic_add_long(p, v, t) \ - __asm __volatile( \ - "1: ldarx %0, 0, %2\n" \ - " add %0, %3, %0\n" \ - " stdcx. %0, 0, %2\n" \ - " bne- 1b\n" \ - : "=&r" (t), "=m" (*p) \ - : "r" (p), "r" (v), "m" (*p) \ - : "cr0", "memory") \ - /* __atomic_add_long */ -#else -#define __atomic_add_long(p, v, t) \ - __asm __volatile( \ - "1: lwarx %0, 0, %2\n" \ - " add %0, %3, %0\n" \ - " stwcx. %0, 0, %2\n" \ - " bne- 1b\n" \ - : "=&r" (t), "=m" (*p) \ - : "r" (p), "r" (v), "m" (*p) \ - : "cr0", "memory") \ - /* __atomic_add_long */ -#endif - -#define _ATOMIC_ADD(type) \ - static __inline void \ - atomic_add_##type(volatile u_##type *p, u_##type v) { \ - u_##type t; \ - __atomic_add_##type(p, v, t); \ - } \ - \ - static __inline void \ - atomic_add_acq_##type(volatile u_##type *p, u_##type v) { \ - u_##type t; \ - __atomic_add_##type(p, v, t); \ - __ATOMIC_ACQ(); \ - } \ - \ - static __inline void \ - atomic_add_rel_##type(volatile u_##type *p, u_##type v) { \ - u_##type t; \ - __ATOMIC_REL(); \ - __atomic_add_##type(p, v, t); \ - } \ - /* _ATOMIC_ADD */ - -_ATOMIC_ADD(int) -_ATOMIC_ADD(long) - -#define atomic_add_32 atomic_add_int -#define atomic_add_acq_32 atomic_add_acq_int -#define atomic_add_rel_32 atomic_add_rel_int - -#ifdef __powerpc64__ -#define atomic_add_64 atomic_add_long -#define atomic_add_acq_64 atomic_add_acq_long -#define atomic_add_rel_64 atomic_add_rel_long - -#define atomic_add_ptr atomic_add_long -#define atomic_add_acq_ptr atomic_add_acq_long -#define atomic_add_rel_ptr atomic_add_rel_long -#else -#define atomic_add_ptr atomic_add_int -#define atomic_add_acq_ptr atomic_add_acq_int -#define atomic_add_rel_ptr atomic_add_rel_int -#endif -#undef _ATOMIC_ADD -#undef __atomic_add_long -#undef __atomic_add_int - -/* - * atomic_clear(p, v) - * { *p &= ~v; } - */ - -#define __atomic_clear_int(p, v, t) \ - __asm __volatile( \ - "1: lwarx %0, 0, %2\n" \ - " andc %0, %0, %3\n" \ - " stwcx. %0, 0, %2\n" \ - " bne- 1b\n" \ - : "=&r" (t), "=m" (*p) \ - : "r" (p), "r" (v), "m" (*p) \ - : "cr0", "memory") \ - /* __atomic_clear_int */ - -#ifdef __powerpc64__ -#define __atomic_clear_long(p, v, t) \ - __asm __volatile( \ - "1: ldarx %0, 0, %2\n" \ - " andc %0, %0, %3\n" \ - " stdcx. %0, 0, %2\n" \ - " bne- 1b\n" \ - : "=&r" (t), "=m" (*p) \ - : "r" (p), "r" (v), "m" (*p) \ - : "cr0", "memory") \ - /* __atomic_clear_long */ -#else -#define __atomic_clear_long(p, v, t) \ - __asm __volatile( \ - "1: lwarx %0, 0, %2\n" \ - " andc %0, %0, %3\n" \ - " stwcx. %0, 0, %2\n" \ - " bne- 1b\n" \ - : "=&r" (t), "=m" (*p) \ - : "r" (p), "r" (v), "m" (*p) \ - : "cr0", "memory") \ - /* __atomic_clear_long */ -#endif - -#define _ATOMIC_CLEAR(type) \ - static __inline void \ - atomic_clear_##type(volatile u_##type *p, u_##type v) { \ - u_##type t; \ - __atomic_clear_##type(p, v, t); \ - } \ - \ - static __inline void \ - atomic_clear_acq_##type(volatile u_##type *p, u_##type v) { \ - u_##type t; \ - __atomic_clear_##type(p, v, t); \ - __ATOMIC_ACQ(); \ - } \ - \ - static __inline void \ - atomic_clear_rel_##type(volatile u_##type *p, u_##type v) { \ - u_##type t; \ - __ATOMIC_REL(); \ - __atomic_clear_##type(p, v, t); \ - } \ - /* _ATOMIC_CLEAR */ - -_ATOMIC_CLEAR(int) -_ATOMIC_CLEAR(long) - -#define atomic_clear_32 atomic_clear_int -#define atomic_clear_acq_32 atomic_clear_acq_int -#define atomic_clear_rel_32 atomic_clear_rel_int - -#ifdef __powerpc64__ -#define atomic_clear_64 atomic_clear_long -#define atomic_clear_acq_64 atomic_clear_acq_long -#define atomic_clear_rel_64 atomic_clear_rel_long - -#define atomic_clear_ptr atomic_clear_long -#define atomic_clear_acq_ptr atomic_clear_acq_long -#define atomic_clear_rel_ptr atomic_clear_rel_long -#else -#define atomic_clear_ptr atomic_clear_int -#define atomic_clear_acq_ptr atomic_clear_acq_int -#define atomic_clear_rel_ptr atomic_clear_rel_int -#endif -#undef _ATOMIC_CLEAR -#undef __atomic_clear_long -#undef __atomic_clear_int - -/* - * atomic_cmpset(p, o, n) - */ -/* TODO -- see below */ - -/* - * atomic_load_acq(p) - */ -/* TODO -- see below */ - -/* - * atomic_readandclear(p) - */ -/* TODO -- see below */ - -/* - * atomic_set(p, v) - * { *p |= v; } - */ - -#define __atomic_set_int(p, v, t) \ - __asm __volatile( \ - "1: lwarx %0, 0, %2\n" \ - " or %0, %3, %0\n" \ - " stwcx. %0, 0, %2\n" \ - " bne- 1b\n" \ - : "=&r" (t), "=m" (*p) \ - : "r" (p), "r" (v), "m" (*p) \ - : "cr0", "memory") \ - /* __atomic_set_int */ - -#ifdef __powerpc64__ -#define __atomic_set_long(p, v, t) \ - __asm __volatile( \ - "1: ldarx %0, 0, %2\n" \ - " or %0, %3, %0\n" \ - " stdcx. %0, 0, %2\n" \ - " bne- 1b\n" \ - : "=&r" (t), "=m" (*p) \ - : "r" (p), "r" (v), "m" (*p) \ - : "cr0", "memory") \ - /* __atomic_set_long */ -#else -#define __atomic_set_long(p, v, t) \ - __asm __volatile( \ - "1: lwarx %0, 0, %2\n" \ - " or %0, %3, %0\n" \ - " stwcx. %0, 0, %2\n" \ - " bne- 1b\n" \ - : "=&r" (t), "=m" (*p) \ - : "r" (p), "r" (v), "m" (*p) \ - : "cr0", "memory") \ - /* __atomic_set_long */ -#endif - -#define _ATOMIC_SET(type) \ - static __inline void \ - atomic_set_##type(volatile u_##type *p, u_##type v) { \ - u_##type t; \ - __atomic_set_##type(p, v, t); \ - } \ - \ - static __inline void \ - atomic_set_acq_##type(volatile u_##type *p, u_##type v) { \ - u_##type t; \ - __atomic_set_##type(p, v, t); \ - __ATOMIC_ACQ(); \ - } \ - \ - static __inline void \ - atomic_set_rel_##type(volatile u_##type *p, u_##type v) { \ - u_##type t; \ - __ATOMIC_REL(); \ - __atomic_set_##type(p, v, t); \ - } \ - /* _ATOMIC_SET */ - -_ATOMIC_SET(int) -_ATOMIC_SET(long) - -#define atomic_set_32 atomic_set_int -#define atomic_set_acq_32 atomic_set_acq_int -#define atomic_set_rel_32 atomic_set_rel_int - -#ifdef __powerpc64__ -#define atomic_set_64 atomic_set_long -#define atomic_set_acq_64 atomic_set_acq_long -#define atomic_set_rel_64 atomic_set_rel_long - -#define atomic_set_ptr atomic_set_long -#define atomic_set_acq_ptr atomic_set_acq_long -#define atomic_set_rel_ptr atomic_set_rel_long -#else -#define atomic_set_ptr atomic_set_int -#define atomic_set_acq_ptr atomic_set_acq_int -#define atomic_set_rel_ptr atomic_set_rel_int -#endif -#undef _ATOMIC_SET -#undef __atomic_set_long -#undef __atomic_set_int - -/* - * atomic_subtract(p, v) - * { *p -= v; } - */ - -#define __atomic_subtract_int(p, v, t) \ - __asm __volatile( \ - "1: lwarx %0, 0, %2\n" \ - " subf %0, %3, %0\n" \ - " stwcx. %0, 0, %2\n" \ - " bne- 1b\n" \ - : "=&r" (t), "=m" (*p) \ - : "r" (p), "r" (v), "m" (*p) \ - : "cr0", "memory") \ - /* __atomic_subtract_int */ - -#ifdef __powerpc64__ -#define __atomic_subtract_long(p, v, t) \ - __asm __volatile( \ - "1: ldarx %0, 0, %2\n" \ - " subf %0, %3, %0\n" \ - " stdcx. %0, 0, %2\n" \ - " bne- 1b\n" \ - : "=&r" (t), "=m" (*p) \ - : "r" (p), "r" (v), "m" (*p) \ - : "cr0", "memory") \ - /* __atomic_subtract_long */ -#else -#define __atomic_subtract_long(p, v, t) \ - __asm __volatile( \ - "1: lwarx %0, 0, %2\n" \ - " subf %0, %3, %0\n" \ - " stwcx. %0, 0, %2\n" \ - " bne- 1b\n" \ - : "=&r" (t), "=m" (*p) \ - : "r" (p), "r" (v), "m" (*p) \ - : "cr0", "memory") \ - /* __atomic_subtract_long */ -#endif - -#define _ATOMIC_SUBTRACT(type) \ - static __inline void \ - atomic_subtract_##type(volatile u_##type *p, u_##type v) { \ - u_##type t; \ - __atomic_subtract_##type(p, v, t); \ - } \ - \ - static __inline void \ - atomic_subtract_acq_##type(volatile u_##type *p, u_##type v) { \ - u_##type t; \ - __atomic_subtract_##type(p, v, t); \ - __ATOMIC_ACQ(); \ - } \ - \ - static __inline void \ - atomic_subtract_rel_##type(volatile u_##type *p, u_##type v) { \ - u_##type t; \ - __ATOMIC_REL(); \ - __atomic_subtract_##type(p, v, t); \ - } \ - /* _ATOMIC_SUBTRACT */ - -_ATOMIC_SUBTRACT(int) -_ATOMIC_SUBTRACT(long) - -#define atomic_subtract_32 atomic_subtract_int -#define atomic_subtract_acq_32 atomic_subtract_acq_int -#define atomic_subtract_rel_32 atomic_subtract_rel_int - -#ifdef __powerpc64__ -#define atomic_subtract_64 atomic_subtract_long -#define atomic_subtract_acq_64 atomic_subract_acq_long -#define atomic_subtract_rel_64 atomic_subtract_rel_long - -#define atomic_subtract_ptr atomic_subtract_long -#define atomic_subtract_acq_ptr atomic_subtract_acq_long -#define atomic_subtract_rel_ptr atomic_subtract_rel_long -#else -#define atomic_subtract_ptr atomic_subtract_int -#define atomic_subtract_acq_ptr atomic_subtract_acq_int -#define atomic_subtract_rel_ptr atomic_subtract_rel_int -#endif -#undef _ATOMIC_SUBTRACT -#undef __atomic_subtract_long -#undef __atomic_subtract_int - -/* - * atomic_store_rel(p, v) - */ -/* TODO -- see below */ - -/* - * Old/original implementations that still need revisiting. - */ - -static __inline u_int -atomic_readandclear_int(volatile u_int *addr) -{ - u_int result,temp; - - __asm __volatile ( - "\tsync\n" /* drain writes */ - "1:\tlwarx %0, 0, %3\n\t" /* load old value */ - "li %1, 0\n\t" /* load new value */ - "stwcx. %1, 0, %3\n\t" /* attempt to store */ - "bne- 1b\n\t" /* spin if failed */ - : "=&r"(result), "=&r"(temp), "=m" (*addr) - : "r" (addr), "m" (*addr) - : "cr0", "memory"); - - return (result); -} - -#ifdef __powerpc64__ -static __inline u_long -atomic_readandclear_long(volatile u_long *addr) -{ - u_long result,temp; - - __asm __volatile ( - "\tsync\n" /* drain writes */ - "1:\tldarx %0, 0, %3\n\t" /* load old value */ - "li %1, 0\n\t" /* load new value */ - "stdcx. %1, 0, %3\n\t" /* attempt to store */ - "bne- 1b\n\t" /* spin if failed */ - : "=&r"(result), "=&r"(temp), "=m" (*addr) - : "r" (addr), "m" (*addr) - : "cr0", "memory"); - - return (result); -} -#endif - -#define atomic_readandclear_32 atomic_readandclear_int - -#ifdef __powerpc64__ -#define atomic_readandclear_64 atomic_readandclear_long - -#define atomic_readandclear_ptr atomic_readandclear_long -#else -static __inline u_long -atomic_readandclear_long(volatile u_long *addr) -{ - - return ((u_long)atomic_readandclear_int((volatile u_int *)addr)); -} - -#define atomic_readandclear_ptr atomic_readandclear_int -#endif - -/* - * We assume that a = b will do atomic loads and stores. - */ -#define ATOMIC_STORE_LOAD(TYPE) \ -static __inline u_##TYPE \ -atomic_load_acq_##TYPE(volatile u_##TYPE *p) \ -{ \ - u_##TYPE v; \ - \ - v = *p; \ - powerpc_lwsync(); \ - return (v); \ -} \ - \ -static __inline void \ -atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v) \ -{ \ - \ - powerpc_lwsync(); \ - *p = v; \ -} - -ATOMIC_STORE_LOAD(int) - -#define atomic_load_acq_32 atomic_load_acq_int -#define atomic_store_rel_32 atomic_store_rel_int - -#ifdef __powerpc64__ -ATOMIC_STORE_LOAD(long) - -#define atomic_load_acq_64 atomic_load_acq_long -#define atomic_store_rel_64 atomic_store_rel_long - -#define atomic_load_acq_ptr atomic_load_acq_long -#define atomic_store_rel_ptr atomic_store_rel_long -#else -static __inline u_long -atomic_load_acq_long(volatile u_long *addr) -{ - - return ((u_long)atomic_load_acq_int((volatile u_int *)addr)); -} - -static __inline void -atomic_store_rel_long(volatile u_long *addr, u_long val) -{ - - atomic_store_rel_int((volatile u_int *)addr, (u_int)val); -} - -#define atomic_load_acq_ptr atomic_load_acq_int -#define atomic_store_rel_ptr atomic_store_rel_int -#endif -#undef ATOMIC_STORE_LOAD - -/* - * Atomically compare the value stored at *p with cmpval and if the - * two values are equal, update the value of *p with newval. Returns - * zero if the compare failed, nonzero otherwise. - */ -#ifdef ISA_206_ATOMICS -static __inline int -atomic_cmpset_char(volatile u_char *p, u_char cmpval, u_char newval) -{ - int ret; - - __asm __volatile ( - "1:\tlbarx %0, 0, %2\n\t" /* load old value */ - "cmplw %3, %0\n\t" /* compare */ - "bne- 2f\n\t" /* exit if not equal */ - "stbcx. %4, 0, %2\n\t" /* attempt to store */ - "bne- 1b\n\t" /* spin if failed */ - "li %0, 1\n\t" /* success - retval = 1 */ - "b 3f\n\t" /* we've succeeded */ - "2:\n\t" - "stbcx. %0, 0, %2\n\t" /* clear reservation (74xx) */ - "li %0, 0\n\t" /* failure - retval = 0 */ - "3:\n\t" - : "=&r" (ret), "=m" (*p) - : "r" (p), "r" (cmpval), "r" (newval), "m" (*p) - : "cr0", "memory"); - - return (ret); -} - -static __inline int -atomic_cmpset_short(volatile u_short *p, u_short cmpval, u_short newval) -{ - int ret; - - __asm __volatile ( - "1:\tlharx %0, 0, %2\n\t" /* load old value */ - "cmplw %3, %0\n\t" /* compare */ - "bne- 2f\n\t" /* exit if not equal */ - "sthcx. %4, 0, %2\n\t" /* attempt to store */ - "bne- 1b\n\t" /* spin if failed */ - "li %0, 1\n\t" /* success - retval = 1 */ - "b 3f\n\t" /* we've succeeded */ - "2:\n\t" - "sthcx. %0, 0, %2\n\t" /* clear reservation (74xx) */ - "li %0, 0\n\t" /* failure - retval = 0 */ - "3:\n\t" - : "=&r" (ret), "=m" (*p) - : "r" (p), "r" (cmpval), "r" (newval), "m" (*p) - : "cr0", "memory"); - - return (ret); -} -#else -static __inline int -atomic_cmpset_masked(uint32_t *p, uint32_t cmpval, uint32_t newval, - uint32_t mask) -{ - int ret; - uint32_t tmp; - - __asm __volatile ( - "1:\tlwarx %2, 0, %3\n\t" /* load old value */ - "and %0, %2, %7\n\t" - "cmplw %4, %0\n\t" /* compare */ - "bne- 2f\n\t" /* exit if not equal */ - "andc %2, %2, %7\n\t" - "or %2, %2, %5\n\t" - "stwcx. %2, 0, %3\n\t" /* attempt to store */ - "bne- 1b\n\t" /* spin if failed */ - "li %0, 1\n\t" /* success - retval = 1 */ - "b 3f\n\t" /* we've succeeded */ - "2:\n\t" - "stwcx. %2, 0, %3\n\t" /* clear reservation (74xx) */ - "li %0, 0\n\t" /* failure - retval = 0 */ - "3:\n\t" - : "=&r" (ret), "=m" (*p), "+&r" (tmp) - : "r" (p), "r" (cmpval), "r" (newval), "m" (*p), - "r" (mask) - : "cr0", "memory"); - - return (ret); -} - -#define _atomic_cmpset_masked_word(a,o,v,m) atomic_cmpset_masked(a, o, v, m) -#endif - -static __inline int -atomic_cmpset_int(volatile u_int* p, u_int cmpval, u_int newval) -{ - int ret; - - __asm __volatile ( - "1:\tlwarx %0, 0, %2\n\t" /* load old value */ - "cmplw %3, %0\n\t" /* compare */ - "bne- 2f\n\t" /* exit if not equal */ - "stwcx. %4, 0, %2\n\t" /* attempt to store */ - "bne- 1b\n\t" /* spin if failed */ - "li %0, 1\n\t" /* success - retval = 1 */ - "b 3f\n\t" /* we've succeeded */ - "2:\n\t" - "stwcx. %0, 0, %2\n\t" /* clear reservation (74xx) */ - "li %0, 0\n\t" /* failure - retval = 0 */ - "3:\n\t" - : "=&r" (ret), "=m" (*p) - : "r" (p), "r" (cmpval), "r" (newval), "m" (*p) - : "cr0", "memory"); - - return (ret); -} -static __inline int -atomic_cmpset_long(volatile u_long* p, u_long cmpval, u_long newval) -{ - int ret; - - __asm __volatile ( - #ifdef __powerpc64__ - "1:\tldarx %0, 0, %2\n\t" /* load old value */ - "cmpld %3, %0\n\t" /* compare */ - "bne- 2f\n\t" /* exit if not equal */ - "stdcx. %4, 0, %2\n\t" /* attempt to store */ - #else - "1:\tlwarx %0, 0, %2\n\t" /* load old value */ - "cmplw %3, %0\n\t" /* compare */ - "bne- 2f\n\t" /* exit if not equal */ - "stwcx. %4, 0, %2\n\t" /* attempt to store */ - #endif - "bne- 1b\n\t" /* spin if failed */ - "li %0, 1\n\t" /* success - retval = 1 */ - "b 3f\n\t" /* we've succeeded */ - "2:\n\t" - #ifdef __powerpc64__ - "stdcx. %0, 0, %2\n\t" /* clear reservation (74xx) */ - #else - "stwcx. %0, 0, %2\n\t" /* clear reservation (74xx) */ - #endif - "li %0, 0\n\t" /* failure - retval = 0 */ - "3:\n\t" - : "=&r" (ret), "=m" (*p) - : "r" (p), "r" (cmpval), "r" (newval), "m" (*p) - : "cr0", "memory"); - - return (ret); -} - -#define ATOMIC_CMPSET_ACQ_REL(type) \ - static __inline int \ - atomic_cmpset_acq_##type(volatile u_##type *p, \ - u_##type cmpval, u_##type newval)\ - {\ - u_##type retval; \ - retval = atomic_cmpset_##type(p, cmpval, newval);\ - __ATOMIC_ACQ();\ - return (retval);\ - }\ - static __inline int \ - atomic_cmpset_rel_##type(volatile u_##type *p, \ - u_##type cmpval, u_##type newval)\ - {\ - __ATOMIC_REL();\ - return (atomic_cmpset_##type(p, cmpval, newval));\ - }\ - struct hack - -ATOMIC_CMPSET_ACQ_REL(int); -ATOMIC_CMPSET_ACQ_REL(long); - -#ifdef ISA_206_ATOMICS -#define atomic_cmpset_8 atomic_cmpset_char -#endif -#define atomic_cmpset_acq_8 atomic_cmpset_acq_char -#define atomic_cmpset_rel_8 atomic_cmpset_rel_char - -#ifdef ISA_206_ATOMICS -#define atomic_cmpset_16 atomic_cmpset_short -#endif -#define atomic_cmpset_acq_16 atomic_cmpset_acq_short -#define atomic_cmpset_rel_16 atomic_cmpset_rel_short - -#define atomic_cmpset_32 atomic_cmpset_int -#define atomic_cmpset_acq_32 atomic_cmpset_acq_int -#define atomic_cmpset_rel_32 atomic_cmpset_rel_int - -#ifdef __powerpc64__ -#define atomic_cmpset_64 atomic_cmpset_long -#define atomic_cmpset_acq_64 atomic_cmpset_acq_long -#define atomic_cmpset_rel_64 atomic_cmpset_rel_long - -#define atomic_cmpset_ptr atomic_cmpset_long -#define atomic_cmpset_acq_ptr atomic_cmpset_acq_long -#define atomic_cmpset_rel_ptr atomic_cmpset_rel_long -#else -#define atomic_cmpset_ptr atomic_cmpset_int -#define atomic_cmpset_acq_ptr atomic_cmpset_acq_int -#define atomic_cmpset_rel_ptr atomic_cmpset_rel_int -#endif - -/* - * Atomically compare the value stored at *p with *cmpval and if the - * two values are equal, update the value of *p with newval. Returns - * zero if the compare failed and sets *cmpval to the read value from *p, - * nonzero otherwise. - */ -#ifdef ISA_206_ATOMICS -static __inline int -atomic_fcmpset_char(volatile u_char *p, u_char *cmpval, u_char newval) -{ - int ret; - - __asm __volatile ( - "lbarx %0, 0, %3\n\t" /* load old value */ - "cmplw %4, %0\n\t" /* compare */ - "bne- 1f\n\t" /* exit if not equal */ - "stbcx. %5, 0, %3\n\t" /* attempt to store */ - "bne- 1f\n\t" /* exit if failed */ - "li %0, 1\n\t" /* success - retval = 1 */ - "b 2f\n\t" /* we've succeeded */ - "1:\n\t" - "stbcx. %0, 0, %3\n\t" /* clear reservation (74xx) */ - "stbx %0, 0, %7\n\t" - "li %0, 0\n\t" /* failure - retval = 0 */ - "2:\n\t" - : "=&r" (ret), "=m" (*p), "=m" (*cmpval) - : "r" (p), "r" (*cmpval), "r" (newval), "m" (*p), "r"(cmpval) - : "cr0", "memory"); - - return (ret); -} - -static __inline int -atomic_fcmpset_short(volatile u_short *p, u_short *cmpval, u_short newval) -{ - int ret; - - __asm __volatile ( - "lharx %0, 0, %3\n\t" /* load old value */ - "cmplw %4, %0\n\t" /* compare */ - "bne- 1f\n\t" /* exit if not equal */ - "sthcx. %5, 0, %3\n\t" /* attempt to store */ - "bne- 1f\n\t" /* exit if failed */ - "li %0, 1\n\t" /* success - retval = 1 */ - "b 2f\n\t" /* we've succeeded */ - "1:\n\t" - "sthcx. %0, 0, %3\n\t" /* clear reservation (74xx) */ - "sthx %0, 0, %7\n\t" - "li %0, 0\n\t" /* failure - retval = 0 */ - "2:\n\t" - : "=&r" (ret), "=m" (*p), "=m" (*cmpval) - : "r" (p), "r" (*cmpval), "r" (newval), "m" (*p), "r"(cmpval) - : "cr0", "memory"); - - return (ret); -} -#endif /* ISA_206_ATOMICS */ - -static __inline int -atomic_fcmpset_int(volatile u_int *p, u_int *cmpval, u_int newval) -{ - int ret; - - __asm __volatile ( - "lwarx %0, 0, %3\n\t" /* load old value */ - "cmplw %4, %0\n\t" /* compare */ - "bne- 1f\n\t" /* exit if not equal */ - "stwcx. %5, 0, %3\n\t" /* attempt to store */ - "bne- 1f\n\t" /* exit if failed */ - "li %0, 1\n\t" /* success - retval = 1 */ - "b 2f\n\t" /* we've succeeded */ - "1:\n\t" - "stwcx. %0, 0, %3\n\t" /* clear reservation (74xx) */ - "stwx %0, 0, %7\n\t" - "li %0, 0\n\t" /* failure - retval = 0 */ - "2:\n\t" - : "=&r" (ret), "=m" (*p), "=m" (*cmpval) - : "r" (p), "r" (*cmpval), "r" (newval), "m" (*p), "r"(cmpval) - : "cr0", "memory"); - - return (ret); -} -static __inline int -atomic_fcmpset_long(volatile u_long *p, u_long *cmpval, u_long newval) -{ - int ret; - - __asm __volatile ( - #ifdef __powerpc64__ - "ldarx %0, 0, %3\n\t" /* load old value */ - "cmpld %4, %0\n\t" /* compare */ - "bne- 1f\n\t" /* exit if not equal */ - "stdcx. %5, 0, %3\n\t" /* attempt to store */ - #else - "lwarx %0, 0, %3\n\t" /* load old value */ - "cmplw %4, %0\n\t" /* compare */ - "bne- 1f\n\t" /* exit if not equal */ - "stwcx. %5, 0, %3\n\t" /* attempt to store */ - #endif - "bne- 1f\n\t" /* exit if failed */ - "li %0, 1\n\t" /* success - retval = 1 */ - "b 2f\n\t" /* we've succeeded */ - "1:\n\t" - #ifdef __powerpc64__ - "stdcx. %0, 0, %3\n\t" /* clear reservation (74xx) */ - "stdx %0, 0, %7\n\t" - #else - "stwcx. %0, 0, %3\n\t" /* clear reservation (74xx) */ - "stwx %0, 0, %7\n\t" - #endif - "li %0, 0\n\t" /* failure - retval = 0 */ - "2:\n\t" - : "=&r" (ret), "=m" (*p), "=m" (*cmpval) - : "r" (p), "r" (*cmpval), "r" (newval), "m" (*p), "r"(cmpval) - : "cr0", "memory"); - - return (ret); -} - -#define ATOMIC_FCMPSET_ACQ_REL(type) \ - static __inline int \ - atomic_fcmpset_acq_##type(volatile u_##type *p, \ - u_##type *cmpval, u_##type newval)\ - {\ - u_##type retval; \ - retval = atomic_fcmpset_##type(p, cmpval, newval);\ - __ATOMIC_ACQ();\ - return (retval);\ - }\ - static __inline int \ - atomic_fcmpset_rel_##type(volatile u_##type *p, \ - u_##type *cmpval, u_##type newval)\ - {\ - __ATOMIC_REL();\ - return (atomic_fcmpset_##type(p, cmpval, newval));\ - }\ - struct hack - -ATOMIC_FCMPSET_ACQ_REL(int); -ATOMIC_FCMPSET_ACQ_REL(long); - -#ifdef ISA_206_ATOMICS -#define atomic_fcmpset_8 atomic_fcmpset_char -#endif -#define atomic_fcmpset_acq_8 atomic_fcmpset_acq_char -#define atomic_fcmpset_rel_8 atomic_fcmpset_rel_char - -#ifdef ISA_206_ATOMICS -#define atomic_fcmpset_16 atomic_fcmpset_short -#endif -#define atomic_fcmpset_acq_16 atomic_fcmpset_acq_short -#define atomic_fcmpset_rel_16 atomic_fcmpset_rel_short - -#define atomic_fcmpset_32 atomic_fcmpset_int -#define atomic_fcmpset_acq_32 atomic_fcmpset_acq_int -#define atomic_fcmpset_rel_32 atomic_fcmpset_rel_int - -#ifdef __powerpc64__ -#define atomic_fcmpset_64 atomic_fcmpset_long -#define atomic_fcmpset_acq_64 atomic_fcmpset_acq_long -#define atomic_fcmpset_rel_64 atomic_fcmpset_rel_long - -#define atomic_fcmpset_ptr atomic_fcmpset_long -#define atomic_fcmpset_acq_ptr atomic_fcmpset_acq_long -#define atomic_fcmpset_rel_ptr atomic_fcmpset_rel_long -#else -#define atomic_fcmpset_ptr atomic_fcmpset_int -#define atomic_fcmpset_acq_ptr atomic_fcmpset_acq_int -#define atomic_fcmpset_rel_ptr atomic_fcmpset_rel_int -#endif - -static __inline u_int -atomic_fetchadd_int(volatile u_int *p, u_int v) -{ - u_int value; - - do { - value = *p; - } while (!atomic_cmpset_int(p, value, value + v)); - return (value); -} - -static __inline u_long -atomic_fetchadd_long(volatile u_long *p, u_long v) -{ - u_long value; - - do { - value = *p; - } while (!atomic_cmpset_long(p, value, value + v)); - return (value); -} - -static __inline u_int -atomic_swap_32(volatile u_int *p, u_int v) -{ - u_int prev; - - __asm __volatile( - "1: lwarx %0,0,%2\n" - " stwcx. %3,0,%2\n" - " bne- 1b\n" - : "=&r" (prev), "+m" (*(volatile u_int *)p) - : "r" (p), "r" (v) - : "cr0", "memory"); - - return (prev); -} - -#ifdef __powerpc64__ -static __inline u_long -atomic_swap_64(volatile u_long *p, u_long v) -{ - u_long prev; - - __asm __volatile( - "1: ldarx %0,0,%2\n" - " stdcx. %3,0,%2\n" - " bne- 1b\n" - : "=&r" (prev), "+m" (*(volatile u_long *)p) - : "r" (p), "r" (v) - : "cr0", "memory"); - - return (prev); -} -#endif - -#define atomic_fetchadd_32 atomic_fetchadd_int -#define atomic_swap_int atomic_swap_32 - -#ifdef __powerpc64__ -#define atomic_fetchadd_64 atomic_fetchadd_long -#define atomic_swap_long atomic_swap_64 -#define atomic_swap_ptr atomic_swap_64 -#else -#define atomic_swap_long(p,v) atomic_swap_32((volatile u_int *)(p), v) -#define atomic_swap_ptr(p,v) atomic_swap_32((volatile u_int *)(p), v) -#endif - -static __inline int -atomic_testandset_int(volatile u_int *p, u_int v) -{ - u_int m = (1u << (v & 0x1f)); - u_int res; - u_int tmp; - - __asm __volatile( - "1: lwarx %0,0,%3\n" - " and %1,%0,%4\n" - " or %0,%0,%4\n" - " stwcx. %0,0,%3\n" - " bne- 1b\n" - : "=&r"(tmp), "=&r"(res), "+m"(*p) - : "r"(p), "r"(m) - : "cr0", "memory"); - - return (res != 0); -} - -static __inline int -atomic_testandclear_int(volatile u_int *p, u_int v) -{ - u_int m = (1u << (v & 0x1f)); - u_int res; - u_int tmp; - - __asm __volatile( - "1: lwarx %0,0,%3\n" - " and %1,%0,%4\n" - " andc %0,%0,%4\n" - " stwcx. %0,0,%3\n" - " bne- 1b\n" - : "=&r"(tmp), "=&r"(res), "+m"(*p) - : "r"(p), "r"(m) - : "cr0", "memory"); - - return (res != 0); -} - -#ifdef __powerpc64__ -static __inline int -atomic_testandset_long(volatile u_long *p, u_int v) -{ - u_long m = (1ul << (v & 0x3f)); - u_long res; - u_long tmp; - - __asm __volatile( - "1: ldarx %0,0,%3\n" - " and %1,%0,%4\n" - " or %0,%0,%4\n" - " stdcx. %0,0,%3\n" - " bne- 1b\n" - : "=&r"(tmp), "=&r"(res), "+m"(*(volatile u_long *)p) - : "r"(p), "r"(m) - : "cr0", "memory"); - - return (res != 0); -} - -static __inline int -atomic_testandclear_long(volatile u_long *p, u_int v) -{ - u_long m = (1ul << (v & 0x3f)); - u_long res; - u_long tmp; - - __asm __volatile( - "1: ldarx %0,0,%3\n" - " and %1,%0,%4\n" - " andc %0,%0,%4\n" - " stdcx. %0,0,%3\n" - " bne- 1b\n" - : "=&r"(tmp), "=&r"(res), "+m"(*p) - : "r"(p), "r"(m) - : "cr0", "memory"); - - return (res != 0); -} -#else -static __inline int -atomic_testandset_long(volatile u_long *p, u_int v) -{ - return (atomic_testandset_int((volatile u_int *)p, v)); -} - -static __inline int -atomic_testandclear_long(volatile u_long *p, u_int v) -{ - return (atomic_testandclear_int((volatile u_int *)p, v)); -} -#endif - -#define atomic_testandclear_32 atomic_testandclear_int -#define atomic_testandset_32 atomic_testandset_int - -static __inline int -atomic_testandset_acq_long(volatile u_long *p, u_int v) -{ - u_int a = atomic_testandset_long(p, v); - __ATOMIC_ACQ(); - return (a); -} - -#define atomic_testandclear_int atomic_testandclear_int -#define atomic_testandset_int atomic_testandset_int -#define atomic_testandclear_long atomic_testandclear_long -#define atomic_testandset_long atomic_testandset_long -#define atomic_testandset_acq_long atomic_testandset_acq_long - -static __inline void -atomic_thread_fence_acq(void) -{ - - powerpc_lwsync(); -} - -static __inline void -atomic_thread_fence_rel(void) -{ - - powerpc_lwsync(); -} - -static __inline void -atomic_thread_fence_acq_rel(void) -{ - - powerpc_lwsync(); -} - -static __inline void -atomic_thread_fence_seq_cst(void) -{ - - __asm __volatile("sync" : : : "memory"); -} - -#ifndef ISA_206_ATOMICS -#include -#define atomic_cmpset_char atomic_cmpset_8 -#define atomic_cmpset_short atomic_cmpset_16 -#define atomic_fcmpset_char atomic_fcmpset_8 -#define atomic_fcmpset_short atomic_fcmpset_16 -#endif - -/* These need sys/_atomic_subword.h on non-ISA-2.06-atomic platforms. */ -ATOMIC_CMPSET_ACQ_REL(char); -ATOMIC_CMPSET_ACQ_REL(short); - -ATOMIC_FCMPSET_ACQ_REL(char); -ATOMIC_FCMPSET_ACQ_REL(short); - -#undef __ATOMIC_REL -#undef __ATOMIC_ACQ - -#endif /* ! _MACHINE_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/bus.h b/lib/libc/include/generic-freebsd/machine/bus.h index 9955a93d75ee..025c59ba2f2f 100644 --- a/lib/libc/include/generic-freebsd/machine/bus.h +++ b/lib/libc/include/generic-freebsd/machine/bus.h @@ -1,493 +1,5 @@ -/* $NetBSD: bus.h,v 1.11 2003/07/28 17:35:54 thorpej Exp $ */ - /*- - * SPDX-License-Identifier: BSD-2-Clause AND BSD-4-Clause - * - * Copyright (c) 1996, 1997, 1998, 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, - * NASA Ames Research Center. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * This file is in the public domain. */ -/*- - * Copyright (c) 1996 Charles M. Hannum. All rights reserved. - * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Christopher G. Demetriou - * for the NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _MACHINE_BUS_H_ -#define _MACHINE_BUS_H_ - -#include - -#define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t) - -#define BUS_SPACE_MAXADDR_24BIT 0xFFFFFFUL -#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFFUL -#define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFFUL -#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFFUL - -#ifdef __powerpc64__ -#define BUS_SPACE_MAXADDR 0xFFFFFFFFFFFFFFFFUL -#define BUS_SPACE_MAXSIZE 0xFFFFFFFFFFFFFFFFUL -#else -#ifdef BOOKE -#define BUS_SPACE_MAXADDR 0xFFFFFFFFFULL -#define BUS_SPACE_MAXSIZE 0xFFFFFFFFUL -#else -#define BUS_SPACE_MAXADDR 0xFFFFFFFFUL -#define BUS_SPACE_MAXSIZE 0xFFFFFFFFUL -#endif -#endif - -#define BUS_SPACE_MAP_CACHEABLE 0x01 -#define BUS_SPACE_MAP_LINEAR 0x02 -#define BUS_SPACE_MAP_PREFETCHABLE 0x04 - -#define BUS_SPACE_UNRESTRICTED (~0) - -#define BUS_SPACE_BARRIER_READ 0x01 -#define BUS_SPACE_BARRIER_WRITE 0x02 - -struct bus_space_access; - -struct bus_space { - /* mapping/unmapping */ - int (*bs_map)(bus_addr_t, bus_size_t, int, - bus_space_handle_t *); - void (*bs_unmap)(bus_size_t); - int (*bs_subregion)(bus_space_handle_t, bus_size_t, - bus_size_t, bus_space_handle_t *); - - /* allocation/deallocation */ - int (*bs_alloc)(bus_addr_t, bus_addr_t, bus_size_t, - bus_size_t, bus_size_t, int, bus_addr_t *, bus_space_handle_t *); - void (*bs_free)(bus_space_handle_t, bus_size_t); - - void (*bs_barrier)(bus_space_handle_t, bus_size_t, - bus_size_t, int); - - /* Read single. */ - uint8_t (*bs_r_1)(bus_space_handle_t, bus_size_t); - uint16_t (*bs_r_2)(bus_space_handle_t, bus_size_t); - uint32_t (*bs_r_4)(bus_space_handle_t, bus_size_t); - uint64_t (*bs_r_8)(bus_space_handle_t, bus_size_t); - - uint16_t (*bs_r_s_2)(bus_space_handle_t, bus_size_t); - uint32_t (*bs_r_s_4)(bus_space_handle_t, bus_size_t); - uint64_t (*bs_r_s_8)(bus_space_handle_t, bus_size_t); - - /* read multiple */ - void (*bs_rm_1)(bus_space_handle_t, bus_size_t, uint8_t *, - bus_size_t); - void (*bs_rm_2)(bus_space_handle_t, bus_size_t, uint16_t *, - bus_size_t); - void (*bs_rm_4)(bus_space_handle_t, bus_size_t, uint32_t *, - bus_size_t); - void (*bs_rm_8)(bus_space_handle_t, bus_size_t, uint64_t *, - bus_size_t); - - void (*bs_rm_s_2)(bus_space_handle_t, bus_size_t, uint16_t *, - bus_size_t); - void (*bs_rm_s_4)(bus_space_handle_t, bus_size_t, uint32_t *, - bus_size_t); - void (*bs_rm_s_8)(bus_space_handle_t, bus_size_t, uint64_t *, - bus_size_t); - - /* read region */ - void (*bs_rr_1)(bus_space_handle_t, bus_size_t, uint8_t *, - bus_size_t); - void (*bs_rr_2)(bus_space_handle_t, bus_size_t, uint16_t *, - bus_size_t); - void (*bs_rr_4)(bus_space_handle_t, bus_size_t, uint32_t *, - bus_size_t); - void (*bs_rr_8)(bus_space_handle_t, bus_size_t, uint64_t *, - bus_size_t); - - void (*bs_rr_s_2)(bus_space_handle_t, bus_size_t, uint16_t *, - bus_size_t); - void (*bs_rr_s_4)(bus_space_handle_t, bus_size_t, uint32_t *, - bus_size_t); - void (*bs_rr_s_8)(bus_space_handle_t, bus_size_t, uint64_t *, - bus_size_t); - - /* write */ - void (*bs_w_1)(bus_space_handle_t, bus_size_t, uint8_t); - void (*bs_w_2)(bus_space_handle_t, bus_size_t, uint16_t); - void (*bs_w_4)(bus_space_handle_t, bus_size_t, uint32_t); - void (*bs_w_8)(bus_space_handle_t, bus_size_t, uint64_t); - - void (*bs_w_s_2)(bus_space_handle_t, bus_size_t, uint16_t); - void (*bs_w_s_4)(bus_space_handle_t, bus_size_t, uint32_t); - void (*bs_w_s_8)(bus_space_handle_t, bus_size_t, uint64_t); - - /* write multiple */ - void (*bs_wm_1)(bus_space_handle_t, bus_size_t, - const uint8_t *, bus_size_t); - void (*bs_wm_2)(bus_space_handle_t, bus_size_t, - const uint16_t *, bus_size_t); - void (*bs_wm_4)(bus_space_handle_t, bus_size_t, - const uint32_t *, bus_size_t); - void (*bs_wm_8)(bus_space_handle_t, bus_size_t, - const uint64_t *, bus_size_t); - - void (*bs_wm_s_2)(bus_space_handle_t, bus_size_t, - const uint16_t *, bus_size_t); - void (*bs_wm_s_4)(bus_space_handle_t, bus_size_t, - const uint32_t *, bus_size_t); - void (*bs_wm_s_8)(bus_space_handle_t, bus_size_t, - const uint64_t *, bus_size_t); - - /* write region */ - void (*bs_wr_1)(bus_space_handle_t, bus_size_t, - const uint8_t *, bus_size_t); - void (*bs_wr_2)(bus_space_handle_t, bus_size_t, - const uint16_t *, bus_size_t); - void (*bs_wr_4)(bus_space_handle_t, bus_size_t, - const uint32_t *, bus_size_t); - void (*bs_wr_8)(bus_space_handle_t, bus_size_t, - const uint64_t *, bus_size_t); - - void (*bs_wr_s_2)(bus_space_handle_t, bus_size_t, - const uint16_t *, bus_size_t); - void (*bs_wr_s_4)(bus_space_handle_t, bus_size_t, - const uint32_t *, bus_size_t); - void (*bs_wr_s_8)(bus_space_handle_t, bus_size_t, - const uint64_t *, bus_size_t); - - /* set multiple */ - void (*bs_sm_1)(bus_space_handle_t, bus_size_t, uint8_t, - bus_size_t); - void (*bs_sm_2)(bus_space_handle_t, bus_size_t, uint16_t, - bus_size_t); - void (*bs_sm_4)(bus_space_handle_t, bus_size_t, uint32_t, - bus_size_t); - void (*bs_sm_8)(bus_space_handle_t, bus_size_t, uint64_t, - bus_size_t); - - void (*bs_sm_s_2)(bus_space_handle_t, bus_size_t, uint16_t, - bus_size_t); - void (*bs_sm_s_4)(bus_space_handle_t, bus_size_t, uint32_t, - bus_size_t); - void (*bs_sm_s_8)(bus_space_handle_t, bus_size_t, uint64_t, - bus_size_t); - - /* set region */ - void (*bs_sr_1)(bus_space_handle_t, bus_size_t, uint8_t, - bus_size_t); - void (*bs_sr_2)(bus_space_handle_t, bus_size_t, uint16_t, - bus_size_t); - void (*bs_sr_4)(bus_space_handle_t, bus_size_t, uint32_t, - bus_size_t); - void (*bs_sr_8)(bus_space_handle_t, bus_size_t, uint64_t, - bus_size_t); - - void (*bs_sr_s_2)(bus_space_handle_t, bus_size_t, uint16_t, - bus_size_t); - void (*bs_sr_s_4)(bus_space_handle_t, bus_size_t, uint32_t, - bus_size_t); - void (*bs_sr_s_8)(bus_space_handle_t, bus_size_t, uint64_t, - bus_size_t); - - /* copy region */ - void (*bs_cr_1)(bus_space_handle_t, bus_size_t, - bus_space_handle_t, bus_size_t, bus_size_t); - void (*bs_cr_2)(bus_space_handle_t, bus_size_t, - bus_space_handle_t, bus_size_t, bus_size_t); - void (*bs_cr_4)(bus_space_handle_t, bus_size_t, - bus_space_handle_t, bus_size_t, bus_size_t); - void (*bs_cr_8)(bus_space_handle_t, bus_size_t, - bus_space_handle_t, bus_size_t, bus_size_t); - - void (*bs_cr_s_2)(bus_space_handle_t, bus_size_t, - bus_space_handle_t, bus_size_t, bus_size_t); - void (*bs_cr_s_4)(bus_space_handle_t, bus_size_t, - bus_space_handle_t, bus_size_t, bus_size_t); - void (*bs_cr_s_8)(bus_space_handle_t, bus_size_t, - bus_space_handle_t, bus_size_t, bus_size_t); -}; - -extern struct bus_space bs_be_tag; -extern struct bus_space bs_le_tag; - -#define __bs_c(a,b) __CONCAT(a,b) -#define __bs_opname(op,size) __bs_c(__bs_c(__bs_c(bs_,op),_),size) - -#define __bs_rs(sz, t, h, o) \ - (*(t)->__bs_opname(r,sz))(h, o) -#define __bs_ws(sz, t, h, o, v) \ - (*(t)->__bs_opname(w,sz))(h, o, v) -#define __bs_nonsingle(type, sz, t, h, o, a, c) \ - (*(t)->__bs_opname(type,sz))(h, o, a, c) -#define __bs_set(type, sz, t, h, o, v, c) \ - (*(t)->__bs_opname(type,sz))(h, o, v, c) -#define __bs_copy(sz, t, h1, o1, h2, o2, cnt) \ - (*(t)->__bs_opname(c,sz))(h1, o1, h2, o2, cnt) - -/* - * Mapping and unmapping operations. - */ -#define bus_space_map(t, a, s, c, hp) (*(t)->bs_map)(a, s, c, hp) -#define bus_space_unmap(t, h, s) (*(t)->bs_unmap)(h, s) -#define bus_space_subregion(t, h, o, s, hp) (*(t)->bs_subregion)(h, o, s, hp) - -/* - * Allocation and deallocation operations. - */ -#define bus_space_alloc(t, rs, re, s, a, b, c, ap, hp) \ - (*(t)->bs_alloc)(rs, re, s, a, b, c, ap, hp) -#define bus_space_free(t, h, s) \ - (*(t)->bs_free)(h, s) - -/* - * Bus barrier operations. - */ -#define bus_space_barrier(t, h, o, l, f) (*(t)->bs_barrier)(h, o, l, f) - -/* - * Bus read (single) operations. - */ -#define bus_space_read_1(t, h, o) __bs_rs(1,t,h,o) -#define bus_space_read_2(t, h, o) __bs_rs(2,t,h,o) -#define bus_space_read_4(t, h, o) __bs_rs(4,t,h,o) -#define bus_space_read_8(t, h, o) __bs_rs(8,t,h,o) - -#define bus_space_read_stream_1 bus_space_read_1 -#define bus_space_read_stream_2(t, h, o) __bs_rs(s_2,t,h,o) -#define bus_space_read_stream_4(t, h, o) __bs_rs(s_4,t,h,o) -#define bus_space_read_stream_8(t, h, o) __bs_rs(s_8,t,h,o) - -/* - * Bus read multiple operations. - */ -#define bus_space_read_multi_1(t, h, o, a, c) \ - __bs_nonsingle(rm,1,(t),(h),(o),(a),(c)) -#define bus_space_read_multi_2(t, h, o, a, c) \ - __bs_nonsingle(rm,2,(t),(h),(o),(a),(c)) -#define bus_space_read_multi_4(t, h, o, a, c) \ - __bs_nonsingle(rm,4,(t),(h),(o),(a),(c)) -#define bus_space_read_multi_8(t, h, o, a, c) \ - __bs_nonsingle(rm,8,(t),(h),(o),(a),(c)) - -#define bus_space_read_multi_stream_1 bus_space_read_multi_1 -#define bus_space_read_multi_stream_2(t, h, o, a, c) \ - __bs_nonsingle(rm,s_2,(t),(h),(o),(a),(c)) -#define bus_space_read_multi_stream_4(t, h, o, a, c) \ - __bs_nonsingle(rm,s_4,(t),(h),(o),(a),(c)) -#define bus_space_read_multi_stream_8(t, h, o, a, c) \ - __bs_nonsingle(rm,s_8,(t),(h),(o),(a),(c)) - -/* - * Bus read region operations. - */ -#define bus_space_read_region_1(t, h, o, a, c) \ - __bs_nonsingle(rr,1,(t),(h),(o),(a),(c)) -#define bus_space_read_region_2(t, h, o, a, c) \ - __bs_nonsingle(rr,2,(t),(h),(o),(a),(c)) -#define bus_space_read_region_4(t, h, o, a, c) \ - __bs_nonsingle(rr,4,(t),(h),(o),(a),(c)) -#define bus_space_read_region_8(t, h, o, a, c) \ - __bs_nonsingle(rr,8,(t),(h),(o),(a),(c)) - -#define bus_space_read_region_stream_1 bus_space_read_region_1 -#define bus_space_read_region_stream_2(t, h, o, a, c) \ - __bs_nonsingle(rr,s_2,(t),(h),(o),(a),(c)) -#define bus_space_read_region_stream_4(t, h, o, a, c) \ - __bs_nonsingle(rr,s_4,(t),(h),(o),(a),(c)) -#define bus_space_read_region_stream_8(t, h, o, a, c) \ - __bs_nonsingle(rr,s_8,(t),(h),(o),(a),(c)) - -/* - * Bus write (single) operations. - */ -#define bus_space_write_1(t, h, o, v) __bs_ws(1,(t),(h),(o),(v)) -#define bus_space_write_2(t, h, o, v) __bs_ws(2,(t),(h),(o),(v)) -#define bus_space_write_4(t, h, o, v) __bs_ws(4,(t),(h),(o),(v)) -#define bus_space_write_8(t, h, o, v) __bs_ws(8,(t),(h),(o),(v)) - -#define bus_space_write_stream_1 bus_space_write_1 -#define bus_space_write_stream_2(t, h, o, v) __bs_ws(s_2,(t),(h),(o),(v)) -#define bus_space_write_stream_4(t, h, o, v) __bs_ws(s_4,(t),(h),(o),(v)) -#define bus_space_write_stream_8(t, h, o, v) __bs_ws(s_8,(t),(h),(o),(v)) - -/* - * Bus write multiple operations. - */ -#define bus_space_write_multi_1(t, h, o, a, c) \ - __bs_nonsingle(wm,1,(t),(h),(o),(a),(c)) -#define bus_space_write_multi_2(t, h, o, a, c) \ - __bs_nonsingle(wm,2,(t),(h),(o),(a),(c)) -#define bus_space_write_multi_4(t, h, o, a, c) \ - __bs_nonsingle(wm,4,(t),(h),(o),(a),(c)) -#define bus_space_write_multi_8(t, h, o, a, c) \ - __bs_nonsingle(wm,8,(t),(h),(o),(a),(c)) - -#define bus_space_write_multi_stream_1 bus_space_write_multi_1 -#define bus_space_write_multi_stream_2(t, h, o, a, c) \ - __bs_nonsingle(wm,s_2,(t),(h),(o),(a),(c)) -#define bus_space_write_multi_stream_4(t, h, o, a, c) \ - __bs_nonsingle(wm,s_4,(t),(h),(o),(a),(c)) -#define bus_space_write_multi_stream_8(t, h, o, a, c) \ - __bs_nonsingle(wm,s_8,(t),(h),(o),(a),(c)) - -/* - * Bus write region operations. - */ -#define bus_space_write_region_1(t, h, o, a, c) \ - __bs_nonsingle(wr,1,(t),(h),(o),(a),(c)) -#define bus_space_write_region_2(t, h, o, a, c) \ - __bs_nonsingle(wr,2,(t),(h),(o),(a),(c)) -#define bus_space_write_region_4(t, h, o, a, c) \ - __bs_nonsingle(wr,4,(t),(h),(o),(a),(c)) -#define bus_space_write_region_8(t, h, o, a, c) \ - __bs_nonsingle(wr,8,(t),(h),(o),(a),(c)) - -#define bus_space_write_region_stream_1 bus_space_write_region_1 -#define bus_space_write_region_stream_2(t, h, o, a, c) \ - __bs_nonsingle(wr,s_2,(t),(h),(o),(a),(c)) -#define bus_space_write_region_stream_4(t, h, o, a, c) \ - __bs_nonsingle(wr,s_4,(t),(h),(o),(a),(c)) -#define bus_space_write_region_stream_8(t, h, o, a, c) \ - __bs_nonsingle(wr,s_8,(t),(h),(o),(a),(c)) - -/* - * Set multiple operations. - */ -#define bus_space_set_multi_1(t, h, o, v, c) \ - __bs_set(sm,1,(t),(h),(o),(v),(c)) -#define bus_space_set_multi_2(t, h, o, v, c) \ - __bs_set(sm,2,(t),(h),(o),(v),(c)) -#define bus_space_set_multi_4(t, h, o, v, c) \ - __bs_set(sm,4,(t),(h),(o),(v),(c)) -#define bus_space_set_multi_8(t, h, o, v, c) \ - __bs_set(sm,8,(t),(h),(o),(v),(c)) - -#define bus_space_set_multi_stream_1 bus_space_set_multi_1 -#define bus_space_set_multi_stream_2(t, h, o, v, c) \ - __bs_set(sm,s_2,(t),(h),(o),(v),(c)) -#define bus_space_set_multi_stream_4(t, h, o, v, c) \ - __bs_set(sm,s_4,(t),(h),(o),(v),(c)) -#define bus_space_set_multi_stream_8(t, h, o, v, c) \ - __bs_set(sm,s_8,(t),(h),(o),(v),(c)) - -/* - * Set region operations. - */ -#define bus_space_set_region_1(t, h, o, v, c) \ - __bs_set(sr,1,(t),(h),(o),(v),(c)) -#define bus_space_set_region_2(t, h, o, v, c) \ - __bs_set(sr,2,(t),(h),(o),(v),(c)) -#define bus_space_set_region_4(t, h, o, v, c) \ - __bs_set(sr,4,(t),(h),(o),(v),(c)) -#define bus_space_set_region_8(t, h, o, v, c) \ - __bs_set(sr,8,(t),(h),(o),(v),(c)) - -#define bus_space_set_region_stream_1 bus_space_set_region_1 -#define bus_space_set_region_stream_2(t, h, o, v, c) \ - __bs_set(sr,s_2,(t),(h),(o),(v),(c)) -#define bus_space_set_region_stream_4(t, h, o, v, c) \ - __bs_set(sr,s_4,(t),(h),(o),(v),(c)) -#define bus_space_set_region_stream_8(t, h, o, v, c) \ - __bs_set(sr,s_8,(t),(h),(o),(v),(c)) - -#if 0 -/* - * Copy operations. - */ -#define bus_space_copy_region_1(t, h1, o1, h2, o2, c) \ - __bs_copy(1, t, h1, o1, h2, o2, c) -#define bus_space_copy_region_2(t, h1, o1, h2, o2, c) \ - __bs_copy(2, t, h1, o1, h2, o2, c) -#define bus_space_copy_region_4(t, h1, o1, h2, o2, c) \ - __bs_copy(4, t, h1, o1, h2, o2, c) -#define bus_space_copy_region_8(t, h1, o1, h2, o2, c) \ - __bs_copy(8, t, h1, o1, h2, o2, c) - -#define bus_space_copy_region_stream_1 bus_space_copy_region_1 -#define bus_space_copy_region_stream_2(t, h1, o1, h2, o2, c) \ - __bs_copy(s_2, t, h1, o1, h2, o2, c) -#define bus_space_copy_region_stream_4(t, h1, o1, h2, o2, c) \ - __bs_copy(s_4, t, h1, o1, h2, o2, c) -#define bus_space_copy_region_stream_8(t, h1, o1, h2, o2, c) \ - __bs_copy(s_8, t, h1, o1, h2, o2, c) -#endif - -#define BUS_PEEK_FUNC(width, type) \ - static inline int \ - bus_space_peek_##width(bus_space_tag_t tag, \ - bus_space_handle_t hnd, bus_size_t offset, type *value) \ - { \ - type tmp; \ - tmp = bus_space_read_##width(tag, hnd, offset); \ - *value = (type)tmp; \ - return (0); \ - } -BUS_PEEK_FUNC(1, uint8_t) -BUS_PEEK_FUNC(2, uint16_t) -BUS_PEEK_FUNC(4, uint32_t) -BUS_PEEK_FUNC(8, uint64_t) - -#define BUS_POKE_FUNC(width, type) \ - static inline int \ - bus_space_poke_##width(bus_space_tag_t tag, \ - bus_space_handle_t hnd, bus_size_t offset, type value) \ - { \ - bus_space_write_##width(tag, hnd, offset, value); \ - return (0); \ - } -BUS_POKE_FUNC(1, uint8_t) -BUS_POKE_FUNC(2, uint16_t) -BUS_POKE_FUNC(4, uint32_t) -BUS_POKE_FUNC(8, uint64_t) - -#include - -#endif /* _MACHINE_BUS_H_ */ \ No newline at end of file +#include \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/clock.h b/lib/libc/include/generic-freebsd/machine/clock.h index 9998037028b5..838e4abd5916 100644 --- a/lib/libc/include/generic-freebsd/machine/clock.h +++ b/lib/libc/include/generic-freebsd/machine/clock.h @@ -1,18 +1,5 @@ -/*- - * Kernel interface to machine-dependent clock driver. - * Garrett Wollman, September 1994. +/* * This file is in the public domain. */ -#ifndef _MACHINE_CLOCK_H_ -#define _MACHINE_CLOCK_H_ - -#ifdef _KERNEL - -struct trapframe; - -void decr_intr(struct trapframe *); - -#endif - -#endif /* !_MACHINE_CLOCK_H_ */ \ No newline at end of file +#include \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/dump.h b/lib/libc/include/generic-freebsd/machine/dump.h index 68051ae782c0..cf91d4b47952 100644 --- a/lib/libc/include/generic-freebsd/machine/dump.h +++ b/lib/libc/include/generic-freebsd/machine/dump.h @@ -1,73 +1,5 @@ /*- - * Copyright (c) 2014 EMC Corp. - * Author: Conrad Meyer - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * This file is in the public domain. */ -#ifndef _MACHINE_DUMP_H_ -#define _MACHINE_DUMP_H_ - -#define KERNELDUMP_ARCH_VERSION KERNELDUMP_POWERPC_VERSION -#define EM_VALUE ELF_ARCH /* Defined in powerpc/include/elf.h */ -#define DUMPSYS_MD_PA_NPAIRS (PHYS_AVAIL_SZ + 1) -#define DUMPSYS_NUM_AUX_HDRS 0 - -/* How often to check the dump progress bar? */ -#define DUMPSYS_PB_CHECK_BITS 20 /* Every 1MB */ - -void dumpsys_pa_init(void); -void dumpsys_unmap_chunk(vm_paddr_t, size_t, void *); -size_t dumpsys_scan_pmap(struct bitset *); -void *dumpsys_dump_pmap_init(unsigned blkpgs); -void *dumpsys_dump_pmap(void *ctx, void *buf, u_long *nbytes); - -static inline struct dump_pa * -dumpsys_pa_next(struct dump_pa *p) -{ - - return (dumpsys_gen_pa_next(p)); -} - -static inline void -dumpsys_wbinv_all(void) -{ - - dumpsys_gen_wbinv_all(); -} - -static inline int -dumpsys_write_aux_headers(struct dumperinfo *di) -{ - - return (dumpsys_gen_write_aux_headers(di)); -} - -static inline int -dumpsys(struct dumperinfo *di) -{ - - return (dumpsys_generic(di)); -} - -#endif /* !_MACHINE_DUMP_H_ */ \ No newline at end of file +#include \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/elf.h b/lib/libc/include/generic-freebsd/machine/elf.h index b643c6592160..36a7ae1abaad 100644 --- a/lib/libc/include/generic-freebsd/machine/elf.h +++ b/lib/libc/include/generic-freebsd/machine/elf.h @@ -1,146 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2001 David E. O'Brien - * Copyright (c) 1996-1997 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * This file is in the public domain. */ -#ifndef _MACHINE_ELF_H_ -#define _MACHINE_ELF_H_ 1 - -/* - * EABI ELF definitions for the PowerPC architecture. - * See "PowerPC Embedded Application Binary Interface, 32-Bit Impliementation" - * [ppc-eabi-1995-01.pdf] for details. - */ - -#ifndef __ELF_WORD_SIZE -#ifdef __powerpc64__ -#define __ELF_WORD_SIZE 64 /* Used by */ -#else -#define __ELF_WORD_SIZE 32 /* Used by */ -#endif -#endif - -#include /* Definitions common to all 32 bit architectures. */ -#include /* Definitions common to all 64 bit architectures. */ -#include - -#if __ELF_WORD_SIZE == 64 -#define ELF_ARCH EM_PPC64 -#define ELF_MACHINE_OK(x) ((x) == EM_PPC64) -#else -#define ELF_ARCH EM_PPC -#define ELF_ARCH32 EM_PPC -#define ELF_MACHINE_OK(x) ((x) == EM_PPC) -#endif - -/* - * Auxiliary vector entries for passing information to the interpreter. - * - * The PowerPC supplement to the SVR4 ABI specification names this "auxv_t", - * but POSIX lays claim to all symbols ending with "_t". - */ - -typedef struct { /* Auxiliary vector entry on initial stack */ - int a_type; /* Entry type. */ - union { -#ifdef __powerpc64__ - int a_val; /* Integer value */ -#else - long a_val; /* Integer value. */ - void *a_ptr; /* Address. */ - void (*a_fcn)(void); /* Function pointer (not used). */ -#endif - } a_un; -} Elf32_Auxinfo; - -typedef struct { /* Auxiliary vector entry on initial stack */ - long a_type; /* Entry type. */ - union { - long a_val; /* Integer value. */ - void *a_ptr; /* Address. */ - void (*a_fcn)(void); /* Function pointer (not used). */ - } a_un; -} Elf64_Auxinfo; - -__ElfType(Auxinfo); - -/* - * Relocation types. - */ - -#define R_PPC_COUNT 37 /* Count of defined relocation types. */ - - /* Count of defined relocation types. */ -#define R_PPC_EMB_COUNT (R_PPC_EMB_RELSDA - R_PPC_EMB_NADDR32 + 1) - -/* Define "machine" characteristics */ -#if BYTE_ORDER == LITTLE_ENDIAN -#define ELF_TARG_DATA ELFDATA2LSB -#else -#define ELF_TARG_DATA ELFDATA2MSB -#endif -#if __ELF_WORD_SIZE == 64 -#define ELF_TARG_CLASS ELFCLASS64 -#define ELF_TARG_MACH EM_PPC64 -#define ELF_TARG_VER 1 -#else -#define ELF_TARG_CLASS ELFCLASS32 -#define ELF_TARG_MACH EM_PPC -#define ELF_TARG_VER 1 -#endif - -#define ET_DYN_LOAD_ADDR 0x01010000 - -#define AT_OLD_NULL AT_NULL -#define AT_OLD_IGNORE AT_IGNORE -#define AT_OLD_EXECFD AT_EXECFD -#define AT_OLD_PHDR AT_PHDR -#define AT_OLD_PHENT AT_PHENT -#define AT_OLD_PHNUM AT_PHNUM -#define AT_OLD_PAGESZ AT_PAGESZ -#define AT_OLD_BASE AT_BASE -#define AT_OLD_FLAGS AT_FLAGS -#define AT_OLD_ENTRY AT_ENTRY -#define AT_OLD_NOTELF AT_NOTELF -#define AT_OLD_UID AT_UID -#define AT_OLD_EUID AT_EUID -#define AT_OLD_EXECPATH 13 -#define AT_OLD_CANARY 14 -#define AT_OLD_CANARYLEN 15 -#define AT_OLD_OSRELDATE 16 -#define AT_OLD_NCPUS 17 -#define AT_OLD_PAGESIZES 18 -#define AT_OLD_PAGESIZESLEN 19 -#define AT_OLD_STACKPROT 21 -#define AT_OLD_TIMEKEEP AT_TIMEKEEP -#define AT_OLD_EHDRFLAGS AT_EHDRFLAGS -#define AT_OLD_HWCAP AT_HWCAP -#define AT_OLD_HWCAP2 AT_HWCAP2 - -#define AT_OLD_COUNT 27 /* Count of defined aux entry types. */ - -#endif /* !_MACHINE_ELF_H_ */ \ No newline at end of file +#include \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/endian.h b/lib/libc/include/generic-freebsd/machine/endian.h index cee6814d10bf..02be261a3b80 100644 --- a/lib/libc/include/generic-freebsd/machine/endian.h +++ b/lib/libc/include/generic-freebsd/machine/endian.h @@ -1,40 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1987, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)endian.h 8.1 (Berkeley) 6/10/93 + * This file is in the public domain. */ -#ifndef _MACHINE_ENDIAN_H_ -#define _MACHINE_ENDIAN_H_ - -#include -#include - -#endif /* !_MACHINE_ENDIAN_H_ */ \ No newline at end of file +#include \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/exec.h b/lib/libc/include/generic-freebsd/machine/exec.h index 8a2c6bd93612..22a48bd0f8ed 100644 --- a/lib/libc/include/generic-freebsd/machine/exec.h +++ b/lib/libc/include/generic-freebsd/machine/exec.h @@ -1,8 +1,8 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * - * Copyright (c) 2001 David E. O'Brien - * All rights reserved. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -12,11 +12,11 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the author nor the names of any co-contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE diff --git a/lib/libc/include/generic-freebsd/machine/float.h b/lib/libc/include/generic-freebsd/machine/float.h index a39a98229f77..0e6d11c8c393 100644 --- a/lib/libc/include/generic-freebsd/machine/float.h +++ b/lib/libc/include/generic-freebsd/machine/float.h @@ -1,100 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1989 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)float.h 7.1 (Berkeley) 5/8/90 - * from: FreeBSD: src/sys/i386/include/float.h,v 1.8 1999/08/28 00:44:11 + * This file is in the public domain. */ -#ifndef _MACHINE_FLOAT_H_ -#define _MACHINE_FLOAT_H_ 1 - -#include - -#ifndef _SOFT_FLOAT -__BEGIN_DECLS -extern int __flt_rounds(void); -__END_DECLS -#define FLT_ROUNDS __flt_rounds() -#else -#define FLT_ROUNDS (-1) -#endif - -#define FLT_RADIX 2 /* b */ -#if __ISO_C_VISIBLE >= 1999 -#define FLT_EVAL_METHOD 0 -#define DECIMAL_DIG 17 /* max precision in decimal digits */ -#endif - -#define FLT_MANT_DIG 24 /* p */ -#define FLT_EPSILON 1.19209290E-07F /* b**(1-p) */ -#define FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ -#define FLT_MIN_EXP (-125) /* emin */ -#define FLT_MIN 1.17549435E-38F /* b**(emin-1) */ -#define FLT_MIN_10_EXP (-37) /* ceil(log10(b**(emin-1))) */ -#define FLT_MAX_EXP 128 /* emax */ -#define FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ -#define FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ -#if __ISO_C_VISIBLE >= 2011 -#define FLT_TRUE_MIN 1.40129846E-45F /* b**(emin-p) */ -#define FLT_DECIMAL_DIG 9 /* ceil(1+p*log10(b)) */ -#define FLT_HAS_SUBNORM 1 -#endif /* __ISO_C_VISIBLE >= 2011 */ - -#define DBL_MANT_DIG 53 -#define DBL_EPSILON 2.2204460492503131E-16 -#define DBL_DIG 15 -#define DBL_MIN_EXP (-1021) -#define DBL_MIN 2.2250738585072014E-308 -#define DBL_MIN_10_EXP (-307) -#define DBL_MAX_EXP 1024 -#define DBL_MAX 1.7976931348623157E+308 -#define DBL_MAX_10_EXP 308 -#if __ISO_C_VISIBLE >= 2011 -#define DBL_TRUE_MIN 4.9406564584124654E-324 -#define DBL_DECIMAL_DIG 17 -#define DBL_HAS_SUBNORM 1 -#endif /* __ISO_C_VISIBLE >= 2011 */ - -#define LDBL_MANT_DIG DBL_MANT_DIG -#define LDBL_EPSILON ((long double)DBL_EPSILON) -#define LDBL_DIG DBL_DIG -#define LDBL_MIN_EXP DBL_MIN_EXP -#define LDBL_MIN ((long double)DBL_MIN) -#define LDBL_MIN_10_EXP DBL_MIN_10_EXP -#define LDBL_MAX_EXP DBL_MAX_EXP -#define LDBL_MAX ((long double)DBL_MAX) -#define LDBL_MAX_10_EXP DBL_MAX_10_EXP -#if __ISO_C_VISIBLE >= 2011 -#define LDBL_TRUE_MIN ((long double)DBL_TRUE_MIN) -#define LDBL_DECIMAL_DIG DBL_DECIMAL_DIG -#define LDBL_HAS_SUBNORM DBL_HAS_SUBNORM -#endif /* __ISO_C_VISIBLE >= 2011 */ - -#endif /* _MACHINE_FLOAT_H_ */ \ No newline at end of file +#include \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/floatingpoint.h b/lib/libc/include/generic-freebsd/machine/floatingpoint.h index d2c7e15ad2e8..e05bc6f49c01 100644 --- a/lib/libc/include/generic-freebsd/machine/floatingpoint.h +++ b/lib/libc/include/generic-freebsd/machine/floatingpoint.h @@ -1,7 +1,7 @@ /*- - * SPDX-License-Identifier: BSD-3-Clause + * SPDX-License-Identifier: BSD-4-Clause * - * Copyright (c) 2004 Suleiman Souhlal + * Copyright (c) 1993 Andrew Moore, Talke Studio * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -12,11 +12,15 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the author nor the names of any co-contributors + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY DAVID O'BRIEN AND CONTRIBUTORS ``AS IS'' AND + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE @@ -32,6 +36,7 @@ #ifndef _FLOATINGPOINT_H_ #define _FLOATINGPOINT_H_ +#include #include #endif /* !_FLOATINGPOINT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/ieee.h b/lib/libc/include/generic-freebsd/machine/ieee.h deleted file mode 100644 index 73f04cb16043..000000000000 --- a/lib/libc/include/generic-freebsd/machine/ieee.h +++ /dev/null @@ -1,143 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This software was developed by the Computer Systems Engineering group - * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and - * contributed to Berkeley. - * - * All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Lawrence Berkeley Laboratory. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)ieee.h 8.1 (Berkeley) 6/11/93 - * from: NetBSD: ieee.h,v 1.1.1.1 1998/06/20 04:58:51 eeh Exp - */ - -#ifndef _MACHINE_IEEE_H_ -#define _MACHINE_IEEE_H_ - -/* - * ieee.h defines the machine-dependent layout of the machine's IEEE - * floating point. It does *not* define (yet?) any of the rounding - * mode bits, exceptions, and so forth. - */ - -/* - * Define the number of bits in each fraction and exponent. - * - * k k+1 - * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented - * - * (-exp_bias+1) - * as fractions that look like 0.fffff x 2 . This means that - * - * -126 - * the number 0.10000 x 2 , for instance, is the same as the normalized - * - * -127 -128 - * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero - * - * -129 - * in the fraction; to represent 2 , we need two, and so on. This - * - * (-exp_bias-fracbits+1) - * implies that the smallest denormalized number is 2 - * - * for whichever format we are talking about: for single precision, for - * - * -126 -149 - * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and - * - * -149 == -127 - 23 + 1. - */ -#define SNG_EXPBITS 8 -#define SNG_FRACBITS 23 - -#define DBL_EXPBITS 11 -#define DBL_FRACBITS 52 - -#ifdef notyet -#define E80_EXPBITS 15 -#define E80_FRACBITS 64 -#endif - -#define EXT_EXPBITS 15 -#define EXT_FRACBITS 112 - -struct ieee_single { - u_int sng_sign:1; - u_int sng_exp:8; - u_int sng_frac:23; -}; - -struct ieee_double { - u_int dbl_sign:1; - u_int dbl_exp:11; - u_int dbl_frach:20; - u_int dbl_fracl; -}; - -struct ieee_ext { - u_int ext_sign:1; - u_int ext_exp:15; - u_int ext_frach:16; - u_int ext_frachm; - u_int ext_fraclm; - u_int ext_fracl; -}; - -/* - * Floats whose exponent is in [1..INFNAN) (of whatever type) are - * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. - * Floats whose exponent is zero are either zero (iff all fraction - * bits are zero) or subnormal values. - * - * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its - * high fraction; if the bit is set, it is a `quiet NaN'. - */ -#define SNG_EXP_INFNAN 255 -#define DBL_EXP_INFNAN 2047 -#define EXT_EXP_INFNAN 32767 - -#if 0 -#define SNG_QUIETNAN (1 << 22) -#define DBL_QUIETNAN (1 << 19) -#define EXT_QUIETNAN (1 << 15) -#endif - -/* - * Exponent biases. - */ -#define SNG_EXP_BIAS 127 -#define DBL_EXP_BIAS 1023 -#define EXT_EXP_BIAS 16383 - -#endif \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/in_cksum.h b/lib/libc/include/generic-freebsd/machine/in_cksum.h index 6d9dad8fbb77..0a931caffe96 100644 --- a/lib/libc/include/generic-freebsd/machine/in_cksum.h +++ b/lib/libc/include/generic-freebsd/machine/in_cksum.h @@ -29,7 +29,6 @@ * SUCH DAMAGE. * * from tahoe: in_cksum.c 1.2 86/01/05 - * from: @(#)in_cksum.c 1.3 (Berkeley) 1/19/91 * from: Id: in_cksum.c,v 1.8 1995/12/03 18:35:19 bde Exp */ diff --git a/lib/libc/include/generic-freebsd/machine/limits.h b/lib/libc/include/generic-freebsd/machine/limits.h index 8dd7900a374c..4c4e5c0bb04b 100644 --- a/lib/libc/include/generic-freebsd/machine/limits.h +++ b/lib/libc/include/generic-freebsd/machine/limits.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)limits.h 8.3 (Berkeley) 1/4/94 */ #ifndef _MACHINE_LIMITS_H_ diff --git a/lib/libc/include/generic-freebsd/machine/metadata.h b/lib/libc/include/generic-freebsd/machine/metadata.h index e82eb2790b10..2b194e06d14b 100644 --- a/lib/libc/include/generic-freebsd/machine/metadata.h +++ b/lib/libc/include/generic-freebsd/machine/metadata.h @@ -1,38 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2001 Jake Burkholder. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * This file is in the public domain. */ -#ifndef _MACHINE_METADATA_H_ -#define _MACHINE_METADATA_H_ - -#define MODINFOMD_ENVP 0x1001 -#define MODINFOMD_HOWTO 0x1002 -#define MODINFOMD_KERNEND 0x1003 -#define MODINFOMD_BOOTINFO 0x1004 -#define MODINFOMD_DTBP 0x1005 - -#endif /* !_MACHINE_METADATA_H_ */ \ No newline at end of file +#include \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/ofw_machdep.h b/lib/libc/include/generic-freebsd/machine/ofw_machdep.h index 78fe8dd7e44b..21d28906f0dd 100644 --- a/lib/libc/include/generic-freebsd/machine/ofw_machdep.h +++ b/lib/libc/include/generic-freebsd/machine/ofw_machdep.h @@ -1,58 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2001 by Thomas Moestl . - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * This file is in the public domain. */ -#ifndef _MACHINE_OFW_MACHDEP_H_ -#define _MACHINE_OFW_MACHDEP_H_ - -#include -#include -#include -#include -#include -#include - -struct mem_region; -struct numa_mem_region; - -typedef uint32_t cell_t; - -void OF_getetheraddr(device_t dev, u_char *addr); - -void OF_initial_setup(void *fdt_ptr, void *junk, int (*openfirm)(void *)); -boolean_t OF_bootstrap(void); - -void OF_reboot(void); - -void ofw_mem_regions(struct mem_region *, int *, struct mem_region *, int *); -void ofw_numa_mem_regions(struct numa_mem_region *, int *); -void ofw_quiesce(void); /* Must be called before VM is up! */ -void ofw_save_trap_vec(char *); -int ofw_pcibus_get_domain(device_t dev, device_t child, int *domain); -int ofw_pcibus_get_cpus(device_t dev, device_t child, enum cpu_sets op, - size_t setsize, cpuset_t *cpuset); - -#endif /* _MACHINE_OFW_MACHDEP_H_ */ \ No newline at end of file +#include \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/param.h b/lib/libc/include/generic-freebsd/machine/param.h deleted file mode 100644 index bc157c464e41..000000000000 --- a/lib/libc/include/generic-freebsd/machine/param.h +++ /dev/null @@ -1,162 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 2001 David E. O'Brien - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * William Jolitz. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)param.h 5.8 (Berkeley) 6/28/91 - */ - -#ifndef _POWERPC_INCLUDE_PARAM_H_ -#define _POWERPC_INCLUDE_PARAM_H_ - -/* - * Machine dependent constants for PowerPC - */ - -#include - -/* Needed to display interrupts on OFW PCI */ -#define __PCI_REROUTE_INTERRUPT - -#ifndef MACHINE -#define MACHINE "powerpc" -#endif -#ifndef MACHINE_ARCH -#ifdef __powerpc64__ -#if defined(__LITTLE_ENDIAN__) -#define MACHINE_ARCH "powerpc64le" -#else -#define MACHINE_ARCH "powerpc64" -#endif -#else -#ifdef __SPE__ -#define MACHINE_ARCH "powerpcspe" -#else -#define MACHINE_ARCH "powerpc" -#endif -#endif -#endif -#define MID_MACHINE MID_POWERPC -#ifdef __powerpc64__ -#ifndef MACHINE_ARCH32 -#define MACHINE_ARCH32 "powerpc" -#endif -#endif - -#ifdef SMP -#ifndef MAXCPU -#define MAXCPU 256 -#endif -#else -#define MAXCPU 1 -#endif - -#ifndef MAXMEMDOM -#define MAXMEMDOM 8 -#endif - -#define ALIGNBYTES _ALIGNBYTES -#define ALIGN(p) _ALIGN(p) -/* - * ALIGNED_POINTER is a boolean macro that checks whether an address - * is valid to fetch data elements of type t from on this architecture. - * This does not reflect the optimal alignment, just the possibility - * (within reasonable limits). - */ -#define ALIGNED_POINTER(p, t) ((((uintptr_t)(p)) & (sizeof (t) - 1)) == 0) - -/* - * CACHE_LINE_SIZE is the compile-time maximum cache line size for an - * architecture. It should be used with appropriate caution. - */ -#define CACHE_LINE_SHIFT 7 -#define CACHE_LINE_SIZE (1 << CACHE_LINE_SHIFT) - -#define PAGE_SHIFT 12 -#define PAGE_SIZE (1 << PAGE_SHIFT) /* Page size */ -#define PAGE_MASK (PAGE_SIZE - 1) -#define NPTEPG (PAGE_SIZE/(sizeof (pt_entry_t))) -#define NPDEPG (PAGE_SIZE/(sizeof (pt_entry_t))) - -#define L1_PAGE_SIZE_SHIFT 39 -#define L1_PAGE_SIZE (1UL<> PAGE_SHIFT) -#define ptoa(x) ((x) << PAGE_SHIFT) - -#define powerpc_btop(x) ((x) >> PAGE_SHIFT) -#define powerpc_ptob(x) ((x) << PAGE_SHIFT) - -#define pgtok(x) ((x) * (PAGE_SIZE / 1024UL)) - -#define btoc(x) ((vm_offset_t)(((x)+PAGE_MASK)>>PAGE_SHIFT)) - -#endif /* !_POWERPC_INCLUDE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/pcb.h b/lib/libc/include/generic-freebsd/machine/pcb.h deleted file mode 100644 index 0ad791d624aa..000000000000 --- a/lib/libc/include/generic-freebsd/machine/pcb.h +++ /dev/null @@ -1,137 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (C) 1995, 1996 Wolfgang Solfrank. - * Copyright (C) 1995, 1996 TooLs GmbH. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by TooLs GmbH. - * 4. The name of TooLs GmbH may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. - * - * $NetBSD: pcb.h,v 1.4 2000/06/04 11:57:17 tsubai Exp $ - */ - -#ifndef _MACHINE_PCB_H_ -#define _MACHINE_PCB_H_ - -#include - -#include - -#ifndef _STANDALONE -struct pcb { - register_t pcb_context[20]; /* non-volatile r12-r31 */ - register_t pcb_cr; /* Condition register */ - register_t pcb_sp; /* stack pointer */ - register_t pcb_toc; /* toc pointer */ - register_t pcb_lr; /* link register */ - register_t pcb_dscr; /* dscr value */ - register_t pcb_fscr; - register_t pcb_tar; - struct pmap *pcb_pm; /* pmap of our vmspace */ - jmp_buf *pcb_onfault; /* For use during - copyin/copyout */ - int pcb_flags; -#define PCB_FPU 0x1 /* Process uses FPU */ -#define PCB_FPREGS 0x2 /* Process had FPU registers initialized */ -#define PCB_VEC 0x4 /* Process uses Altivec */ -#define PCB_VSX 0x8 /* Process had VSX initialized */ -#define PCB_CDSCR 0x10 /* Process had Custom DSCR initialized */ -#define PCB_HTM 0x20 /* Process had HTM initialized */ -#define PCB_CFSCR 0x40 /* Process had FSCR updated */ -#define PCB_KERN_FPU 0x80 /* Kernel is using FPU/Vector unit */ -#define PCB_KERN_FPU_NOSAVE 0x100 /* FPU/Vec state not saved for kernel use */ -#define PCB_VECREGS 0x200 /* Process had Altivec registers initialized */ - struct fpu { - union { -#if _BYTE_ORDER == _BIG_ENDIAN - double fpr; - uint32_t vsr[4]; -#else - uint32_t vsr[4]; - struct { - double padding; - double fpr; - }; -#endif - } fpr[32]; - double fpscr; /* FPSCR stored as double for easier access */ - } pcb_fpu; /* Floating point processor */ - unsigned int pcb_fpcpu; /* which CPU had our FPU - stuff. */ - struct vec { - uint32_t vr[32][4]; - uint32_t spare[2]; - uint32_t vrsave; - uint32_t vscr; /* aligned at vector element 3 */ - } pcb_vec __aligned(16); /* Vector processor */ - unsigned int pcb_veccpu; /* which CPU had our vector - stuff. */ - struct htm { - uint64_t tfhar; - uint64_t texasr; - uint64_t tfiar; - } pcb_htm; - - struct ebb { - uint64_t ebbhr; - uint64_t ebbrr; - uint64_t bescr; - } pcb_ebb; - - struct lmon { - uint64_t lmrr; - uint64_t lmser; - } pcb_lm; - - union { - struct { - vm_offset_t usr_segm; /* Base address */ - register_t usr_vsid; /* USER_SR segment */ - } aim; - struct { - register_t dbcr0; - } booke; - } pcb_cpu; - vm_offset_t pcb_lastill; /* Last illegal instruction */ -}; -#endif - -#ifdef _KERNEL - -struct trapframe; - -#ifndef curpcb -extern struct pcb *curpcb; -#endif - -extern struct pmap *curpm; -extern struct proc *fpuproc; - -void makectx(struct trapframe *, struct pcb *); -void savectx(struct pcb *) __returns_twice; - -#endif -#endif /* _MACHINE_PCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/pmap.h b/lib/libc/include/generic-freebsd/machine/pmap.h deleted file mode 100644 index 4342dd9e4c21..000000000000 --- a/lib/libc/include/generic-freebsd/machine/pmap.h +++ /dev/null @@ -1,361 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause AND BSD-4-Clause - * - * Copyright (C) 2006 Semihalf, Marian Balakowicz - * All rights reserved. - * - * Adapted for Freescale's e500 core CPUs. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/*- - * Copyright (C) 1995, 1996 Wolfgang Solfrank. - * Copyright (C) 1995, 1996 TooLs GmbH. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by TooLs GmbH. - * 4. The name of TooLs GmbH may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * from: $NetBSD: pmap.h,v 1.17 2000/03/30 16:18:24 jdolecek Exp $ - */ - -#ifndef _MACHINE_PMAP_H_ -#define _MACHINE_PMAP_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef __powerpc64__ -#include -#endif - -/* - * The radix page table structure is described by levels 1-4. - * See Fig 33. on p. 1002 of Power ISA v3.0B - * - * Page directories and tables must be size aligned. - */ - -/* Root page directory - 64k -- each entry covers 512GB */ -typedef uint64_t pml1_entry_t; -/* l2 page directory - 4k -- each entry covers 1GB */ -typedef uint64_t pml2_entry_t; -/* l3 page directory - 4k -- each entry covers 2MB */ -typedef uint64_t pml3_entry_t; -/* l4 page directory - 256B/4k -- each entry covers 64k/4k */ -typedef uint64_t pml4_entry_t; - -typedef uint64_t pt_entry_t; - -struct pmap; -typedef struct pmap *pmap_t; - -#define PMAP_ENTER_QUICK_LOCKED 0x10000000 - -#if !defined(NPMAPS) -#define NPMAPS 32768 -#endif /* !defined(NPMAPS) */ - -struct slbtnode; - -struct pvo_entry { - LIST_ENTRY(pvo_entry) pvo_vlink; /* Link to common virt page */ -#ifndef __powerpc64__ - LIST_ENTRY(pvo_entry) pvo_olink; /* Link to overflow entry */ -#endif - union { - RB_ENTRY(pvo_entry) pvo_plink; /* Link to pmap entries */ - SLIST_ENTRY(pvo_entry) pvo_dlink; /* Link to delete enty */ - }; - struct { -#ifndef __powerpc64__ - /* 32-bit fields */ - pte_t pte; -#endif - /* 64-bit fields */ - uintptr_t slot; - vm_paddr_t pa; - vm_prot_t prot; - } pvo_pte; - pmap_t pvo_pmap; /* Owning pmap */ - vm_offset_t pvo_vaddr; /* VA of entry */ - uint64_t pvo_vpn; /* Virtual page number */ -}; -LIST_HEAD(pvo_head, pvo_entry); -SLIST_HEAD(pvo_dlist, pvo_entry); -RB_HEAD(pvo_tree, pvo_entry); -int pvo_vaddr_compare(struct pvo_entry *, struct pvo_entry *); -RB_PROTOTYPE(pvo_tree, pvo_entry, pvo_plink, pvo_vaddr_compare); - -/* Used by 32-bit PMAP */ -#define PVO_PTEGIDX_MASK 0x007UL /* which PTEG slot */ -#define PVO_PTEGIDX_VALID 0x008UL /* slot is valid */ -/* Used by 64-bit PMAP */ -#define PVO_HID 0x008UL /* PVO entry in alternate hash*/ -/* Used by both */ -#define PVO_WIRED 0x010UL /* PVO entry is wired */ -#define PVO_MANAGED 0x020UL /* PVO entry is managed */ -#define PVO_BOOTSTRAP 0x080UL /* PVO entry allocated during - bootstrap */ -#define PVO_DEAD 0x100UL /* waiting to be deleted */ -#define PVO_LARGE 0x200UL /* large page */ -#define PVO_VADDR(pvo) ((pvo)->pvo_vaddr & ~ADDR_POFF) -#define PVO_PTEGIDX_GET(pvo) ((pvo)->pvo_vaddr & PVO_PTEGIDX_MASK) -#define PVO_PTEGIDX_ISSET(pvo) ((pvo)->pvo_vaddr & PVO_PTEGIDX_VALID) -#define PVO_PTEGIDX_CLR(pvo) \ - ((void)((pvo)->pvo_vaddr &= ~(PVO_PTEGIDX_VALID|PVO_PTEGIDX_MASK))) -#define PVO_PTEGIDX_SET(pvo, i) \ - ((void)((pvo)->pvo_vaddr |= (i)|PVO_PTEGIDX_VALID)) -#define PVO_VSID(pvo) ((pvo)->pvo_vpn >> 16) - -struct pmap { - struct pmap_statistics pm_stats; - struct mtx pm_mtx; - cpuset_t pm_active; - union { - struct { - #ifdef __powerpc64__ - struct slbtnode *pm_slb_tree_root; - struct slb **pm_slb; - int pm_slb_len; - #else - register_t pm_sr[16]; - #endif - - struct pmap *pmap_phys; - struct pvo_tree pmap_pvo; - }; -#ifdef __powerpc64__ - /* Radix support */ - struct { - pml1_entry_t *pm_pml1; /* KVA of root page directory */ - struct vm_radix pm_radix; /* spare page table pages */ - TAILQ_HEAD(,pv_chunk) pm_pvchunk; /* list of mappings in pmap */ - uint64_t pm_pid; /* PIDR value */ - int pm_flags; - }; -#endif - struct { - /* TID to identify this pmap entries in TLB */ - tlbtid_t pm_tid[MAXCPU]; - -#ifdef __powerpc64__ - /* - * Page table directory, - * array of pointers to page directories. - */ - pte_t ****pm_root; -#else - /* - * Page table directory, - * array of pointers to page tables. - */ - pte_t **pm_pdir; - - /* List of allocated ptbl bufs (ptbl kva regions). */ - TAILQ_HEAD(, ptbl_buf) pm_ptbl_list; -#endif - }; - } __aligned(CACHE_LINE_SIZE); -}; - -/* - * pv_entries are allocated in chunks per-process. This avoids the - * need to track per-pmap assignments. - */ -#define _NPCPV 126 -#define _NPCM howmany(_NPCPV, 64) - -#define PV_CHUNK_HEADER \ - pmap_t pc_pmap; \ - TAILQ_ENTRY(pv_chunk) pc_list; \ - uint64_t pc_map[_NPCM]; /* bitmap; 1 = free */ \ - TAILQ_ENTRY(pv_chunk) pc_lru; - -struct pv_entry { - pmap_t pv_pmap; - vm_offset_t pv_va; - TAILQ_ENTRY(pv_entry) pv_link; -}; -typedef struct pv_entry *pv_entry_t; - -struct pv_chunk_header { - PV_CHUNK_HEADER -}; -struct pv_chunk { - PV_CHUNK_HEADER - uint64_t reserved; - struct pv_entry pc_pventry[_NPCPV]; -}; - -struct md_page { - union { - struct { - volatile int32_t mdpg_attrs; - vm_memattr_t mdpg_cache_attrs; - struct pvo_head mdpg_pvoh; - int pv_gen; /* (p) */ - }; - struct { - int pv_tracked; - }; - }; - TAILQ_HEAD(, pv_entry) pv_list; /* (p) */ -}; - -#ifdef AIM -#define pmap_page_get_memattr(m) ((m)->md.mdpg_cache_attrs) -#else -#define pmap_page_get_memattr(m) VM_MEMATTR_DEFAULT -#endif /* AIM */ - -/* - * Return the VSID corresponding to a given virtual address. - * If no VSID is currently defined, it will allocate one, and add - * it to a free slot if available. - * - * NB: The PMAP MUST be locked already. - */ -uint64_t va_to_vsid(pmap_t pm, vm_offset_t va); - -/* Lock-free, non-allocating lookup routines */ -uint64_t kernel_va_to_slbv(vm_offset_t va); -struct slb *user_va_to_slb_entry(pmap_t pm, vm_offset_t va); - -uint64_t allocate_user_vsid(pmap_t pm, uint64_t esid, int large); -void free_vsid(pmap_t pm, uint64_t esid, int large); -void slb_insert_user(pmap_t pm, struct slb *slb); -void slb_insert_kernel(uint64_t slbe, uint64_t slbv); - -struct slbtnode *slb_alloc_tree(void); -void slb_free_tree(pmap_t pm); -struct slb **slb_alloc_user_cache(void); -void slb_free_user_cache(struct slb **); - -extern struct pmap kernel_pmap_store; -#define kernel_pmap (&kernel_pmap_store) - -#ifdef _KERNEL - -#define PMAP_LOCK(pmap) mtx_lock(&(pmap)->pm_mtx) -#define PMAP_LOCK_ASSERT(pmap, type) \ - mtx_assert(&(pmap)->pm_mtx, (type)) -#define PMAP_LOCK_DESTROY(pmap) mtx_destroy(&(pmap)->pm_mtx) -#define PMAP_LOCK_INIT(pmap) mtx_init(&(pmap)->pm_mtx, \ - (pmap == kernel_pmap) ? "kernelpmap" : \ - "pmap", NULL, MTX_DEF | MTX_DUPOK) -#define PMAP_LOCKED(pmap) mtx_owned(&(pmap)->pm_mtx) -#define PMAP_MTX(pmap) (&(pmap)->pm_mtx) -#define PMAP_TRYLOCK(pmap) mtx_trylock(&(pmap)->pm_mtx) -#define PMAP_UNLOCK(pmap) mtx_unlock(&(pmap)->pm_mtx) - -#define pmap_page_is_write_mapped(m) (((m)->a.flags & PGA_WRITEABLE) != 0) - -#define pmap_vm_page_alloc_check(m) - -void pmap_bootstrap(vm_offset_t, vm_offset_t); -void pmap_kenter(vm_offset_t va, vm_paddr_t pa); -void pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, vm_memattr_t); -void pmap_kremove(vm_offset_t); -void *pmap_mapdev(vm_paddr_t, vm_size_t); -void *pmap_mapdev_attr(vm_paddr_t, vm_size_t, vm_memattr_t); -void pmap_unmapdev(void *, vm_size_t); -void pmap_page_set_memattr(vm_page_t, vm_memattr_t); -int pmap_change_attr(vm_offset_t, vm_size_t, vm_memattr_t); -int pmap_map_user_ptr(pmap_t pm, volatile const void *uaddr, - void **kaddr, size_t ulen, size_t *klen); -int pmap_decode_kernel_ptr(vm_offset_t addr, int *is_user, - vm_offset_t *decoded_addr); -void pmap_deactivate(struct thread *); -vm_paddr_t pmap_kextract(vm_offset_t); -int pmap_dev_direct_mapped(vm_paddr_t, vm_size_t); -boolean_t pmap_mmu_install(char *name, int prio); -void pmap_mmu_init(void); -const char *pmap_mmu_name(void); -bool pmap_ps_enabled(pmap_t pmap); -int pmap_nofault(pmap_t pmap, vm_offset_t va, vm_prot_t flags); -boolean_t pmap_page_is_mapped(vm_page_t m); -#define pmap_map_delete(pmap, sva, eva) pmap_remove(pmap, sva, eva) - -void pmap_page_array_startup(long count); - -#define vtophys(va) pmap_kextract((vm_offset_t)(va)) - -extern vm_offset_t virtual_avail; -extern vm_offset_t virtual_end; -extern caddr_t crashdumpmap; - -extern vm_offset_t msgbuf_phys; - -extern int pmap_bootstrapped; -extern int radix_mmu; -extern int superpages_enabled; - -#ifdef AIM -void pmap_early_io_map_init(void); -#endif -vm_offset_t pmap_early_io_map(vm_paddr_t pa, vm_size_t size); -void pmap_early_io_unmap(vm_offset_t va, vm_size_t size); -void pmap_track_page(pmap_t pmap, vm_offset_t va); -void pmap_page_print_mappings(vm_page_t m); -void pmap_tlbie_all(void); - -static inline int -pmap_vmspace_copy(pmap_t dst_pmap __unused, pmap_t src_pmap __unused) -{ - - return (0); -} - -#endif - -#endif /* !_MACHINE_PMAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/psl.h b/lib/libc/include/generic-freebsd/machine/psl.h index b8aed73f27df..59536384fca5 100644 --- a/lib/libc/include/generic-freebsd/machine/psl.h +++ b/lib/libc/include/generic-freebsd/machine/psl.h @@ -1,101 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (C) 1995, 1996 Wolfgang Solfrank. - * Copyright (C) 1995, 1996 TooLs GmbH. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by TooLs GmbH. - * 4. The name of TooLs GmbH may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. - * - * $NetBSD: psl.h,v 1.5 2000/11/19 19:52:37 matt Exp $ + * This file is in the public domain. */ -#ifndef _MACHINE_PSL_H_ -#define _MACHINE_PSL_H_ - -/* - * Machine State Register (MSR) - All cores - */ -#define PSL_VEC 0x02000000UL /* AltiVec/SPE vector unit available */ -#define PSL_VSX 0x00800000UL /* Vector-Scalar unit available */ -#define PSL_EE 0x00008000UL /* external interrupt enable */ -#define PSL_PR 0x00004000UL /* privilege mode (1 == user) */ -#define PSL_FP 0x00002000UL /* floating point enable */ -#define PSL_ME 0x00001000UL /* machine check enable */ -#define PSL_FE0 0x00000800UL /* floating point interrupt mode 0 */ -#define PSL_FE1 0x00000100UL /* floating point interrupt mode 1 */ -#define PSL_PMM 0x00000004UL /* performance monitor mark */ -#define PSL_RI 0x00000002UL /* recoverable interrupt */ - -/* Machine State Register - Book-E cores */ -#ifdef __powerpc64__ -#define PSL_CM 0x80000000UL /* Computation Mode (64-bit) */ -#endif - -#define PSL_GS 0x10000000UL /* Guest state */ -#define PSL_UCLE 0x04000000UL /* User mode cache lock enable */ -#define PSL_WE 0x00040000UL /* Wait state enable */ -#define PSL_CE 0x00020000UL /* Critical interrupt enable */ -#define PSL_UBLE 0x00000400UL /* BTB lock enable - e500 only */ -#define PSL_DWE 0x00000400UL /* Debug Wait Enable - 440 only*/ -#define PSL_DE 0x00000200UL /* Debug interrupt enable */ -#define PSL_IS 0x00000020UL /* Instruction address space */ -#define PSL_DS 0x00000010UL /* Data address space */ - -/* Machine State Register (MSR) - AIM cores */ -#ifdef __powerpc64__ -#define PSL_SF 0x8000000000000000UL /* 64-bit addressing */ -#define PSL_HV 0x1000000000000000UL /* hyper-privileged mode */ -#endif - -#define PSL_POW 0x00040000UL /* power management */ -#define PSL_ILE 0x00010000UL /* interrupt endian mode (1 == le) */ -#define PSL_SE 0x00000400UL /* single-step trace enable */ -#define PSL_BE 0x00000200UL /* branch trace enable */ -#define PSL_IP 0x00000040UL /* interrupt prefix - 601 only */ -#define PSL_IR 0x00000020UL /* instruction address relocation */ -#define PSL_DR 0x00000010UL /* data address relocation */ -#define PSL_LE 0x00000001UL /* endian mode (1 == le) */ - -/* - * Floating-point exception modes: - */ -#define PSL_FE_DIS 0 /* none */ -#define PSL_FE_NONREC PSL_FE1 /* imprecise non-recoverable */ -#define PSL_FE_REC PSL_FE0 /* imprecise recoverable */ -#define PSL_FE_PREC (PSL_FE0 | PSL_FE1) /* precise */ -#define PSL_FE_DFLT PSL_FE_PREC /* default == precise */ - -#ifndef LOCORE -extern register_t psl_kernset; /* Default MSR values for kernel */ -extern register_t psl_userset; /* Default MSR values for userland */ -#ifdef __powerpc64__ -extern register_t psl_userset32; /* Default user MSR values for 32-bit */ -#endif -extern register_t psl_userstatic; /* Bits of SRR1 userland may not set */ -#endif - -#endif /* _MACHINE_PSL_H_ */ \ No newline at end of file +#include \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/ptrace.h b/lib/libc/include/generic-freebsd/machine/ptrace.h index 2e1f48e840a2..0a426e24fabd 100644 --- a/lib/libc/include/generic-freebsd/machine/ptrace.h +++ b/lib/libc/include/generic-freebsd/machine/ptrace.h @@ -1,44 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 2014 Justin Hibbits - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)ptrace.h 8.1 (Berkeley) 6/11/93 + * This file is in the public domain. */ -#ifndef _MACHINE_PTRACE_H_ -#define _MACHINE_PTRACE_H_ - -#define __HAVE_PTRACE_MACHDEP - -#define PT_GETVRREGS (PT_FIRSTMACH + 0) -#define PT_SETVRREGS (PT_FIRSTMACH + 1) -#define PT_GETVSRREGS (PT_FIRSTMACH + 2) -#define PT_SETVSRREGS (PT_FIRSTMACH + 3) - -#endif \ No newline at end of file +#include \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/reg.h b/lib/libc/include/generic-freebsd/machine/reg.h index 743dad6839bc..419b2756cc0d 100644 --- a/lib/libc/include/generic-freebsd/machine/reg.h +++ b/lib/libc/include/generic-freebsd/machine/reg.h @@ -1,92 +1,5 @@ -/* $NetBSD: reg.h,v 1.4 2000/06/04 09:30:44 tsubai Exp $ */ - -#ifndef _POWERPC_REG_H_ -#define _POWERPC_REG_H_ - -#include - -/* Must match struct trapframe */ -struct reg { - __register_t fixreg[32]; - __register_t lr; - __register_t cr; - __register_t xer; - __register_t ctr; - __register_t pc; -}; - -struct fpreg { - double fpreg[32]; - double fpscr; -}; - -/* Must match pcb.pcb_vec */ -struct vmxreg { - __uint32_t vr[32][4]; - __uint32_t pad[2]; - __uint32_t vrsave; - __uint32_t vscr; -}; - -struct dbreg { - unsigned int junk; -}; - -#ifdef __LP64__ -/* Must match struct trapframe */ -struct reg32 { - __int32_t fixreg[32]; - __int32_t lr; - __int32_t cr; - __int32_t xer; - __int32_t ctr; - __int32_t pc; -}; - -struct fpreg32 { - struct fpreg data; -}; - -struct vmxreg32 { - struct vmxreg data; -}; - -struct dbreg32 { - struct dbreg data; -}; - -#define __HAVE_REG32 -#endif - -#ifdef _KERNEL -/* - * XXX these interfaces are MI, so they should be declared in a MI place. - */ -int fill_regs(struct thread *, struct reg *); -int set_regs(struct thread *, struct reg *); -int fill_fpregs(struct thread *, struct fpreg *); -int set_fpregs(struct thread *, struct fpreg *); -int fill_dbregs(struct thread *, struct dbreg *); -int set_dbregs(struct thread *, struct dbreg *); - -/* - * MD interfaces. +/*- + * This file is in the public domain. */ -void cpu_save_thread_regs(struct thread *); - -#ifdef COMPAT_FREEBSD32 -struct image_params; - -int fill_regs32(struct thread *, struct reg32 *); -int set_regs32(struct thread *, struct reg32 *); -void ppc32_setregs(struct thread *, struct image_params *, uintptr_t); - -#define fill_fpregs32(td, reg) fill_fpregs(td,(struct fpreg *)reg) -#define set_fpregs32(td, reg) set_fpregs(td,(struct fpreg *)reg) -#define fill_dbregs32(td, reg) fill_dbregs(td,(struct dbreg *)reg) -#define set_dbregs32(td, reg) set_dbregs(td,(struct dbreg *)reg) -#endif - -#endif -#endif /* _POWERPC_REG_H_ */ \ No newline at end of file +#include \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/reloc.h b/lib/libc/include/generic-freebsd/machine/reloc.h index 592510637e39..497e91c8e25b 100644 --- a/lib/libc/include/generic-freebsd/machine/reloc.h +++ b/lib/libc/include/generic-freebsd/machine/reloc.h @@ -1,8 +1,8 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * - * Copyright (c) 1998 John Birrell . - * All rights reserved. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -12,11 +12,11 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the author nor the names of any co-contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE @@ -27,4 +27,22 @@ * 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. - */ \ No newline at end of file + */ + +#ifndef _I386_MACHINE_RELOC_H_ +#define _I386_MACHINE_RELOC_H_ + +/* Relocation format. */ +struct relocation_info { + int r_address; /* offset in text or data segment */ + unsigned int r_symbolnum : 24, /* ordinal number of add symbol */ + r_pcrel : 1, /* 1 if value should be pc-relative */ + r_length : 2, /* log base 2 of value's width */ + r_extern : 1, /* 1 if need to add symbol to value */ + r_baserel : 1, /* linkage table relative */ + r_jmptable : 1, /* relocate to jump table */ + r_relative : 1, /* load address relative */ + r_copy : 1; /* run time copy */ +}; + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/resource.h b/lib/libc/include/generic-freebsd/machine/resource.h deleted file mode 100644 index 4c356f38308e..000000000000 --- a/lib/libc/include/generic-freebsd/machine/resource.h +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * Copyright 1998 Massachusetts Institute of Technology - * - * Permission to use, copy, modify, and distribute this software and - * its documentation for any purpose and without fee is hereby - * granted, provided that both the above copyright notice and this - * permission notice appear in all copies, that both the above - * copyright notice and this permission notice appear in all - * supporting documentation, and that the name of M.I.T. not be used - * in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. M.I.T. makes - * no representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS - * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT - * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _MACHINE_RESOURCE_H_ -#define _MACHINE_RESOURCE_H_ 1 - -/* - * Definitions of resource types for Intel Architecture machines - * with support for legacy ISA devices and drivers. - */ - -#define SYS_RES_IRQ 1 /* interrupt lines */ -#define SYS_RES_DRQ 2 /* isa dma lines */ -#define SYS_RES_MEMORY 3 /* i/o memory */ -#define SYS_RES_IOPORT 4 /* i/o ports */ -#define PCI_RES_BUS 5 /* PCI bus numbers */ - -#endif /* !_MACHINE_RESOURCE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/runq.h b/lib/libc/include/generic-freebsd/machine/runq.h deleted file mode 100644 index e321547c218f..000000000000 --- a/lib/libc/include/generic-freebsd/machine/runq.h +++ /dev/null @@ -1,55 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2001 Jake Burkholder - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _MACHINE_RUNQ_H_ -#define _MACHINE_RUNQ_H_ - -#ifdef __powerpc64__ -#define RQB_LEN (1UL) /* Number of priority status words. */ -#define RQB_L2BPW (6UL) /* Log2(sizeof(rqb_word_t) * NBBY)). */ -#else -#define RQB_LEN (2) /* Number of priority status words. */ -#define RQB_L2BPW (5) /* Log2(sizeof(rqb_word_t) * NBBY)). */ -#endif -#define RQB_BPW (1UL<> RQB_L2BPW) - -#define RQB_FFS(word) (ffsl(word) - 1) - -/* - * Type of run queue status word. - */ -#ifdef __powerpc64__ -typedef u_int64_t rqb_word_t; -#else -typedef u_int32_t rqb_word_t; -#endif - -#endif \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/sdt_machdep.h b/lib/libc/include/generic-freebsd/machine/sdt_machdep.h new file mode 100644 index 000000000000..1b4d9152d2ec --- /dev/null +++ b/lib/libc/include/generic-freebsd/machine/sdt_machdep.h @@ -0,0 +1,12 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 Mark Johnston + */ + +#ifndef _SYS_SDT_MACHDEP_H_ +#define _SYS_SDT_MACHDEP_H_ + +#define _SDT_ASM_PATCH_INSTR "nop" + +#endif /* _SYS_SDT_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/setjmp.h b/lib/libc/include/generic-freebsd/machine/setjmp.h index fcc287508602..41ef6217a78d 100644 --- a/lib/libc/include/generic-freebsd/machine/setjmp.h +++ b/lib/libc/include/generic-freebsd/machine/setjmp.h @@ -1,27 +1,5 @@ /*- - * $NetBSD: setjmp.h,v 1.3 1998/09/16 23:51:27 thorpej Exp $ + * This file is in the public domain. */ -#ifndef _MACHINE_SETJMP_H_ -#define _MACHINE_SETJMP_H_ - -#include - -#ifdef _KERNEL -#define _JBLEN 25 /* Kernel doesn't save FP and Altivec regs */ -#else -#define _JBLEN 100 -#endif - -/* - * jmp_buf and sigjmp_buf are encapsulated in different structs to force - * compile-time diagnostics for mismatches. The structs are the same - * internally to avoid some run-time errors for mismatches. - */ -#if __BSD_VISIBLE || __POSIX_VISIBLE || __XSI_VISIBLE -typedef struct _sigjmp_buf { long _sjb[_JBLEN + 1]; } sigjmp_buf[1]; -#endif - -typedef struct _jmp_buf { long _jb[_JBLEN + 1]; } jmp_buf[1]; - -#endif /* !_MACHINE_SETJMP_H_ */ \ No newline at end of file +#include \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/sysarch.h b/lib/libc/include/generic-freebsd/machine/sysarch.h index e1911def3572..7a8789707932 100644 --- a/lib/libc/include/generic-freebsd/machine/sysarch.h +++ b/lib/libc/include/generic-freebsd/machine/sysarch.h @@ -1,43 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1993 The Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * This file is in the public domain. */ -#ifndef _MACHINE_SYSARCH_H_ -#define _MACHINE_SYSARCH_H_ - -#ifndef _KERNEL -#include - -__BEGIN_DECLS -int sysarch(int, void *); -__END_DECLS -#endif - -#endif /* !_MACHINE_SYSARCH_H_ */ \ No newline at end of file +#include \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/tls.h b/lib/libc/include/generic-freebsd/machine/tls.h index 6dea3eb3a99f..9a386029151e 100644 --- a/lib/libc/include/generic-freebsd/machine/tls.h +++ b/lib/libc/include/generic-freebsd/machine/tls.h @@ -1,66 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright 2004 by Peter Grehan. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * This file is in the public domain. */ -#ifndef _MACHINE_TLS_H_ -#define _MACHINE_TLS_H_ - -#include - -#define TLS_DTV_OFFSET 0x8000 -#define TLS_TCB_ALIGN TLS_TCB_SIZE -#define TLS_TP_OFFSET 0x7000 - -static __inline void -_tcb_set(struct tcb *tcb) -{ -#ifdef __powerpc64__ - __asm __volatile("mr 13,%0" :: - "r" ((uint8_t *)tcb + TLS_TP_OFFSET + TLS_TCB_SIZE)); -#else - __asm __volatile("mr 2,%0" :: - "r" ((uint8_t *)tcb + TLS_TP_OFFSET + TLS_TCB_SIZE)); -#endif -} - -static __inline struct tcb * -_tcb_get(void) -{ - struct tcb *tcb; - -#ifdef __powerpc64__ - __asm __volatile("addi %0,13,%1" : "=r" (tcb) : - "i" (-(TLS_TP_OFFSET + TLS_TCB_SIZE))); -#else - __asm __volatile("addi %0,2,%1" : "=r" (tcb) : - "i" (-(TLS_TP_OFFSET + TLS_TCB_SIZE))); -#endif - return (tcb); -} - -#endif /* !_MACHINE_TLS_H_ */ \ No newline at end of file +#include \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/trap.h b/lib/libc/include/generic-freebsd/machine/trap.h index 7326ba17c5cd..d8320b7b3503 100644 --- a/lib/libc/include/generic-freebsd/machine/trap.h +++ b/lib/libc/include/generic-freebsd/machine/trap.h @@ -1,160 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (C) 1995, 1996 Wolfgang Solfrank. - * Copyright (C) 1995, 1996 TooLs GmbH. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by TooLs GmbH. - * 4. The name of TooLs GmbH may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. - * - * $NetBSD: trap.h,v 1.7 2002/02/22 13:51:40 kleink Exp $ + * This file is in the public domain. */ -#ifndef _POWERPC_TRAP_H_ -#define _POWERPC_TRAP_H_ - -#define EXC_RSVD 0x0000 /* Reserved */ -#define EXC_RST 0x0100 /* Reset; all but IBM4xx */ -#define EXC_MCHK 0x0200 /* Machine Check */ -#define EXC_DSI 0x0300 /* Data Storage Interrupt */ -#define EXC_DSE 0x0380 /* Data Segment Interrupt */ -#define EXC_ISI 0x0400 /* Instruction Storage Interrupt */ -#define EXC_ISE 0x0480 /* Instruction Segment Interrupt */ -#define EXC_EXI 0x0500 /* External Interrupt */ -#define EXC_ALI 0x0600 /* Alignment Interrupt */ -#define EXC_PGM 0x0700 /* Program Interrupt */ -#define EXC_FPU 0x0800 /* Floating-point Unavailable */ -#define EXC_DECR 0x0900 /* Decrementer Interrupt */ -#define EXC_SC 0x0c00 /* System Call */ -#define EXC_TRC 0x0d00 /* Trace */ -#define EXC_FPA 0x0e00 /* Floating-point Assist */ - -/* The following is only available on the 601: */ -#define EXC_RUNMODETRC 0x2000 /* Run Mode/Trace Exception */ - -/* The following are only available on 970(G5): */ -#define EXC_VECAST_G5 0x1700 /* AltiVec Assist */ - -/* The following are only available on 7400(G4): */ -#define EXC_VEC 0x0f20 /* AltiVec Unavailable */ -#define EXC_VECAST_G4 0x1600 /* AltiVec Assist */ - -/* The following are only available on 604/750/7400: */ -#define EXC_PERF 0x0f00 /* Performance Monitoring */ -#define EXC_BPT 0x1300 /* Instruction Breakpoint */ -#define EXC_SMI 0x1400 /* System Managment Interrupt */ - -/* The following are only available on 750/7400: */ -#define EXC_THRM 0x1700 /* Thermal Management Interrupt */ - -/* And these are only on the 603: */ -#define EXC_IMISS 0x1000 /* Instruction translation miss */ -#define EXC_DLMISS 0x1100 /* Data load translation miss */ -#define EXC_DSMISS 0x1200 /* Data store translation miss */ - -/* Power ISA 2.06+: */ -#define EXC_HDSI 0x0e00 /* Hypervisor Data Storage */ -#define EXC_HISI 0x0e20 /* Hypervisor Instruction Storage */ -#define EXC_HEA 0x0e40 /* Hypervisor Emulation Assistance */ -#define EXC_HMI 0x0e60 /* Hypervisor Maintenance */ -#define EXC_VSX 0x0f40 /* VSX Unavailable */ - -/* Power ISA 2.07+: */ -#define EXC_FAC 0x0f60 /* Facility Unavailable */ -#define EXC_HFAC 0x0f80 /* Hypervisor Facility Unavailable */ - -/* Power ISA 3.0+: */ -#define EXC_HVI 0x0ea0 /* Hypervisor Virtualization */ - -/* The following are available on 4xx and 85xx */ -#define EXC_CRIT 0x0100 /* Critical Input Interrupt */ -#define EXC_PIT 0x1000 /* Programmable Interval Timer */ -#define EXC_FIT 0x1010 /* Fixed Interval Timer */ -#define EXC_WDOG 0x1020 /* Watchdog Timer */ -#define EXC_DTMISS 0x1100 /* Data TLB Miss */ -#define EXC_ITMISS 0x1200 /* Instruction TLB Miss */ -#define EXC_APU 0x1300 /* Auxiliary Processing Unit */ -#define EXC_DEBUG 0x2f10 /* Debug trap */ -#define EXC_VECAST_E 0x2f20 /* Altivec Assist (Book-E) */ -#define EXC_SPFPD 0x2f30 /* SPE Floating-point Data */ -#define EXC_SPFPR 0x2f40 /* SPE Floating-point Round */ - -/* POWER8 */ -#define EXC_SOFT_PATCH 0x1500 /* POWER8 Soft Patch Exception */ - -#define EXC_LAST 0x2f00 /* Last possible exception vector */ - -#define EXC_AST 0x3000 /* Fake AST vector */ - -/* Trap was in user mode */ -#define EXC_USER 0x10000 - -/* - * EXC_ALI sets bits in the DSISR and DAR to provide enough - * information to recover from the unaligned access without needing to - * parse the offending instruction. This includes certain bits of the - * opcode, and information about what registers are used. The opcode - * indicator values below come from Appendix F of Book III of "The - * PowerPC Architecture". - */ - -#define EXC_ALI_OPCODE_INDICATOR(dsisr) ((dsisr >> 10) & 0x7f) -#define EXC_ALI_LFD 0x09 -#define EXC_ALI_STFD 0x0b - -/* Macros to extract register information */ -#define EXC_ALI_RST(dsisr) ((dsisr >> 5) & 0x1f) /* source or target */ -#define EXC_ALI_RA(dsisr) (dsisr & 0x1f) -#define EXC_ALI_INST_RST(instr) ((instr >> 21) & 0x1f) - -/* - * SRR1 bits for program exception traps. These identify what caused - * the program exception. See section 6.5.9 of the Power ISA Version - * 2.05. - */ - -#define EXC_PGM_FPENABLED (1UL << 20) -#define EXC_PGM_ILLEGAL (1UL << 19) -#define EXC_PGM_PRIV (1UL << 18) -#define EXC_PGM_TRAP (1UL << 17) - -/* DTrace trap opcode. */ -#define EXC_DTRACE 0x7ffff808 - -/* Magic pointer to store TOC base and other info for trap handlers on ppc64 */ -#define TRAP_ENTRY 0x1e8 -#define TRAP_GENTRAP 0x1f0 -#define TRAP_TOCBASE 0x1f8 - -#ifndef LOCORE -struct trapframe; -struct thread; -extern int (*hmi_handler)(struct trapframe *); -void trap(struct trapframe *); -int ppc_instr_emulate(struct trapframe *, struct thread *); -#endif - -#endif /* _POWERPC_TRAP_H_ */ \ No newline at end of file +#include \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/vdso.h b/lib/libc/include/generic-freebsd/machine/vdso.h index 2a3e6f6dfd8f..57db69e06a7c 100644 --- a/lib/libc/include/generic-freebsd/machine/vdso.h +++ b/lib/libc/include/generic-freebsd/machine/vdso.h @@ -1,43 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright 2012 Konstantin Belousov . - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * This file is in the public domain. */ -#ifndef _POWERPC_VDSO_H -#define _POWERPC_VDSO_H - -#define VDSO_TIMEHANDS_MD \ - uint32_t th_res[8]; - -#define VDSO_TH_ALGO_PPC_TB VDSO_TH_ALGO_1 - -#ifdef _KERNEL -#ifdef COMPAT_FREEBSD32 - -#define VDSO_TIMEHANDS_MD32 VDSO_TIMEHANDS_MD - -#endif -#endif -#endif \ No newline at end of file +#include \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/vm.h b/lib/libc/include/generic-freebsd/machine/vm.h index fa397b398c8d..fdd08a2e4de4 100644 --- a/lib/libc/include/generic-freebsd/machine/vm.h +++ b/lib/libc/include/generic-freebsd/machine/vm.h @@ -1,7 +1,8 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2009 Alan L. Cox + * Copyright (c) 2009 Hudson River Trading LLC + * Written by: John H. Baldwin * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,17 +30,17 @@ #ifndef _MACHINE_VM_H_ #define _MACHINE_VM_H_ -#include +#include /* Memory attributes. */ -#define VM_MEMATTR_DEFAULT 0 -#define VM_MEMATTR_UNCACHEABLE 0x01 -#define VM_MEMATTR_CACHEABLE 0x02 -#define VM_MEMATTR_WRITE_COMBINING 0x04 -#define VM_MEMATTR_WRITE_BACK 0x08 -#define VM_MEMATTR_WRITE_THROUGH 0x10 -#define VM_MEMATTR_PREFETCHABLE 0x20 +#define VM_MEMATTR_UNCACHEABLE ((vm_memattr_t)PAT_UNCACHEABLE) +#define VM_MEMATTR_WRITE_COMBINING ((vm_memattr_t)PAT_WRITE_COMBINING) +#define VM_MEMATTR_WRITE_THROUGH ((vm_memattr_t)PAT_WRITE_THROUGH) +#define VM_MEMATTR_WRITE_PROTECTED ((vm_memattr_t)PAT_WRITE_PROTECTED) +#define VM_MEMATTR_WRITE_BACK ((vm_memattr_t)PAT_WRITE_BACK) +#define VM_MEMATTR_WEAK_UNCACHEABLE ((vm_memattr_t)PAT_UNCACHED) -#define VM_MEMATTR_DEVICE VM_MEMATTR_DEFAULT +#define VM_MEMATTR_DEFAULT VM_MEMATTR_WRITE_BACK +#define VM_MEMATTR_DEVICE VM_MEMATTR_UNCACHEABLE #endif /* !_MACHINE_VM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/vmm_snapshot.h b/lib/libc/include/generic-freebsd/machine/vmm_snapshot.h new file mode 100644 index 000000000000..7a41612f9ec1 --- /dev/null +++ b/lib/libc/include/generic-freebsd/machine/vmm_snapshot.h @@ -0,0 +1 @@ +/* $FreeBSD$ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/vmparam.h b/lib/libc/include/generic-freebsd/machine/vmparam.h deleted file mode 100644 index be779d31e0bf..000000000000 --- a/lib/libc/include/generic-freebsd/machine/vmparam.h +++ /dev/null @@ -1,329 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (C) 1995, 1996 Wolfgang Solfrank. - * Copyright (C) 1995, 1996 TooLs GmbH. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by TooLs GmbH. - * 4. The name of TooLs GmbH may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. - * - * $NetBSD: vmparam.h,v 1.11 2000/02/11 19:25:16 thorpej Exp $ - */ - -#ifndef _MACHINE_VMPARAM_H_ -#define _MACHINE_VMPARAM_H_ - -#ifndef LOCORE -#include -#endif - -#define USRSTACK SHAREDPAGE - -#ifndef MAXTSIZ -#define MAXTSIZ (1*1024*1024*1024) /* max text size */ -#endif - -#ifndef DFLDSIZ -#define DFLDSIZ (128*1024*1024) /* default data size */ -#endif - -#ifndef MAXDSIZ -#ifdef __powerpc64__ -#define MAXDSIZ (32UL*1024*1024*1024) /* max data size */ -#else -#define MAXDSIZ (1*1024*1024*1024) /* max data size */ -#endif -#endif - -#ifndef DFLSSIZ -#define DFLSSIZ (8*1024*1024) /* default stack size */ -#endif - -#ifndef MAXSSIZ -#ifdef __powerpc64__ -#define MAXSSIZ (512*1024*1024) /* max stack size */ -#else -#define MAXSSIZ (64*1024*1024) /* max stack size */ -#endif -#endif - -#ifdef AIM -#define VM_MAXUSER_ADDRESS32 0xfffff000 -#else -#define VM_MAXUSER_ADDRESS32 0x7ffff000 -#endif - -/* - * Would like to have MAX addresses = 0, but this doesn't (currently) work - */ -#ifdef __powerpc64__ -/* - * Virtual addresses of things. Derived from the page directory and - * page table indexes from pmap.h for precision. - * - * kernel map should be able to start at 0xc008000000000000 - - * but at least the functional simulator doesn't like it - * - * 0x0000000000000000 - 0x000fffffffffffff user map - * 0xc000000000000000 - 0xc007ffffffffffff direct map - * 0xc008000000000000 - 0xc00fffffffffffff kernel map - * - */ -#define VM_MIN_ADDRESS 0x0000000000000000 -#define VM_MAXUSER_ADDRESS 0x000fffffc0000000 -#define VM_MAX_ADDRESS 0xc00fffffffffffff -#define VM_MIN_KERNEL_ADDRESS 0xc008000000000000 -#define VM_MAX_KERNEL_ADDRESS 0xc0080007ffffffff -#define VM_MAX_SAFE_KERNEL_ADDRESS VM_MAX_KERNEL_ADDRESS -#else -#define VM_MIN_ADDRESS 0 -#define VM_MAXUSER_ADDRESS VM_MAXUSER_ADDRESS32 -#define VM_MAX_ADDRESS 0xffffffff -#endif - -#define SHAREDPAGE (VM_MAXUSER_ADDRESS - PAGE_SIZE) - -#define FREEBSD32_SHAREDPAGE (VM_MAXUSER_ADDRESS32 - PAGE_SIZE) -#define FREEBSD32_USRSTACK FREEBSD32_SHAREDPAGE - -#define KERNBASE 0x00100100 /* start of kernel virtual */ - -#ifdef AIM -#ifndef __powerpc64__ -#define VM_MIN_KERNEL_ADDRESS ((vm_offset_t)KERNEL_SR << ADDR_SR_SHFT) -#define VM_MAX_SAFE_KERNEL_ADDRESS (VM_MIN_KERNEL_ADDRESS + 2*SEGMENT_LENGTH -1) -#define VM_MAX_KERNEL_ADDRESS (VM_MIN_KERNEL_ADDRESS + 3*SEGMENT_LENGTH - 1) -#endif - -/* - * Use the direct-mapped BAT registers for UMA small allocs. This - * takes pressure off the small amount of available KVA. - */ -#define UMA_MD_SMALL_ALLOC - -#else /* Book-E */ - -/* Use the direct map for UMA small allocs on powerpc64. */ -#ifdef __powerpc64__ -#define UMA_MD_SMALL_ALLOC -#else -#define VM_MIN_KERNEL_ADDRESS 0xc0000000 -#define VM_MAX_KERNEL_ADDRESS 0xffffefff -#define VM_MAX_SAFE_KERNEL_ADDRESS VM_MAX_KERNEL_ADDRESS -#endif - -#endif /* AIM/E500 */ - -#if !defined(LOCORE) -struct pmap_physseg { - struct pv_entry *pvent; - char *attrs; -}; -#endif - -#ifdef __powerpc64__ -#define VM_PHYSSEG_MAX 63 /* 1? */ -#else -#define VM_PHYSSEG_MAX 16 /* 1? */ -#endif - -#define PHYS_AVAIL_SZ 256 /* Allows up to 16GB Ram on pSeries with - * logical memory block size of 64MB. - * For more Ram increase the lmb or this value. - */ - -/* XXX This is non-sensical. Phys avail should hold contiguous regions. */ -#define PHYS_AVAIL_ENTRIES PHYS_AVAIL_SZ - -/* - * The physical address space is densely populated on 32-bit systems, - * but may not be on 64-bit ones. - */ -#ifdef __powerpc64__ -#define VM_PHYSSEG_SPARSE -#else -#define VM_PHYSSEG_DENSE -#endif - -/* - * Create two free page pools: VM_FREEPOOL_DEFAULT is the default pool - * from which physical pages are allocated and VM_FREEPOOL_DIRECT is - * the pool from which physical pages for small UMA objects are - * allocated. - */ -#define VM_NFREEPOOL 2 -#define VM_FREEPOOL_DEFAULT 0 -#define VM_FREEPOOL_DIRECT 1 - -/* - * Create one free page list. - */ -#define VM_NFREELIST 1 -#define VM_FREELIST_DEFAULT 0 - -#ifdef __powerpc64__ -/* The largest allocation size is 16MB. */ -#define VM_NFREEORDER 13 -#else -/* The largest allocation size is 4MB. */ -#define VM_NFREEORDER 11 -#endif - -#ifndef VM_NRESERVLEVEL -#ifdef __powerpc64__ -/* Enable superpage reservations: 1 level. */ -#define VM_NRESERVLEVEL 1 -#else -/* Disable superpage reservations. */ -#define VM_NRESERVLEVEL 0 -#endif -#endif - -#ifndef VM_LEVEL_0_ORDER -/* Level 0 reservations consist of 512 (RPT) or 4096 (HPT) pages. */ -#define VM_LEVEL_0_ORDER vm_level_0_order -#ifndef __ASSEMBLER__ -extern int vm_level_0_order; -#endif -#endif - -#ifndef VM_LEVEL_0_ORDER_MAX -#define VM_LEVEL_0_ORDER_MAX 12 -#endif - -#ifdef __powerpc64__ -#ifdef SMP -#define PA_LOCK_COUNT 256 -#endif -#endif - -#ifndef VM_INITIAL_PAGEIN -#define VM_INITIAL_PAGEIN 16 -#endif - -#ifndef SGROWSIZ -#define SGROWSIZ (128UL*1024) /* amount to grow stack */ -#endif - -/* - * How many physical pages per kmem arena virtual page. - */ -#ifndef VM_KMEM_SIZE_SCALE -#define VM_KMEM_SIZE_SCALE (3) -#endif - -/* - * Optional floor (in bytes) on the size of the kmem arena. - */ -#ifndef VM_KMEM_SIZE_MIN -#define VM_KMEM_SIZE_MIN (12 * 1024 * 1024) -#endif - -/* - * Optional ceiling (in bytes) on the size of the kmem arena: 40% of the - * usable KVA space. - */ -#ifndef VM_KMEM_SIZE_MAX -#define VM_KMEM_SIZE_MAX ((VM_MAX_SAFE_KERNEL_ADDRESS - \ - VM_MIN_KERNEL_ADDRESS + 1) * 2 / 5) -#endif - -#ifdef __powerpc64__ -#define ZERO_REGION_SIZE (2 * 1024 * 1024) /* 2MB */ -#else -#define ZERO_REGION_SIZE (64 * 1024) /* 64KB */ -#endif - -/* - * On 32-bit OEA, the only purpose for which sf_buf is used is to implement - * an opaque pointer required by the machine-independent parts of the kernel. - * That pointer references the vm_page that is "mapped" by the sf_buf. The - * actual mapping is provided by the direct virtual-to-physical mapping. - * - * On OEA64 and Book-E, we need to do something a little more complicated. Use - * the runtime-detected hw_direct_map to pick between the two cases. Our - * friends in vm_machdep.c will do the same to ensure nothing gets confused. - */ -#define SFBUF -#define SFBUF_NOMD - -/* - * We (usually) have a direct map of all physical memory, so provide - * a macro to use to get the kernel VA address for a given PA. Check the - * value of PMAP_HAS_PMAP before using. - */ -#ifndef LOCORE -#ifdef __powerpc64__ -#define DMAP_BASE_ADDRESS 0xc000000000000000UL -#define DMAP_MIN_ADDRESS DMAP_BASE_ADDRESS -#define DMAP_MAX_ADDRESS 0xc007ffffffffffffUL -#else -#define DMAP_BASE_ADDRESS 0x00000000UL -#define DMAP_MAX_ADDRESS 0xbfffffffUL -#endif -#endif - -#if defined(__powerpc64__) || defined(BOOKE) -/* - * powerpc64 and Book-E will provide their own page array allocators. - * - * On AIM, this will allocate a single virtual array, with pages from the - * correct memory domains. - * On Book-E this will let us put the array in TLB1, removing the need for TLB - * thrashing. - * - * VM_MIN_KERNEL_ADDRESS is just a dummy. It will get set by the MMU driver. - */ -#define PA_MIN_ADDRESS VM_MIN_KERNEL_ADDRESS -#define PMAP_HAS_PAGE_ARRAY 1 -#endif - -#if defined(__powerpc64__) -/* - * Need a page dump array for minidump. - */ -#define MINIDUMP_PAGE_TRACKING 1 -#else -/* - * No minidump with 32-bit powerpc. - */ -#define MINIDUMP_PAGE_TRACKING 0 -#endif - -#define PMAP_HAS_DMAP (hw_direct_map) -#define PHYS_TO_DMAP(x) ({ \ - KASSERT(hw_direct_map, ("Direct map not provided by PMAP")); \ - (x) | DMAP_BASE_ADDRESS; }) -#define DMAP_TO_PHYS(x) ({ \ - KASSERT(hw_direct_map, ("Direct map not provided by PMAP")); \ - (x) &~ DMAP_BASE_ADDRESS; }) - -/* - * No non-transparent large page support in the pmap. - */ -#define PMAP_HAS_LARGEPAGES 0 - -#endif /* _MACHINE_VMPARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/math.h b/lib/libc/include/generic-freebsd/math.h index 1f049ec5a02f..3a9e3fa119da 100644 --- a/lib/libc/include/generic-freebsd/math.h +++ b/lib/libc/include/generic-freebsd/math.h @@ -10,12 +10,12 @@ */ /* - * from: @(#)fdlibm.h 5.1 93/09/24 */ #ifndef _MATH_H_ #define _MATH_H_ +#include #include #include @@ -32,13 +32,8 @@ extern const union __nan_un { float __uf; } __nan; -#if __GNUC_PREREQ__(3, 3) #define __MATH_BUILTIN_CONSTANTS -#endif - -#if __GNUC_PREREQ__(3, 0) #define __MATH_BUILTIN_RELOPS -#endif #ifdef __MATH_BUILTIN_CONSTANTS #define HUGE_VAL __builtin_huge_val() @@ -77,10 +72,10 @@ extern const union __nan_un { #if __STDC_VERSION__ >= 201112L || __has_extension(c_generic_selections) #define __fp_type_select(x, f, d, ld) __extension__ _Generic((x), \ - float: f(x), \ - double: d(x), \ - long double: ld(x)) -#elif __GNUC_PREREQ__(3, 1) && !defined(__cplusplus) + float: f, \ + double: d, \ + long double: ld)(x) +#elif !defined(__cplusplus) #define __fp_type_select(x, f, d, ld) __builtin_choose_expr( \ __builtin_types_compatible_p(__typeof(x), long double), ld(x), \ __builtin_choose_expr( \ @@ -143,6 +138,22 @@ typedef __float_t float_t; #define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ #define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ +#if __BSD_VISIBLE || __XSI_VISIBLE >= 800 +#define M_El 2.718281828459045235360287471352662498L /* e */ +#define M_LOG2El 1.442695040888963407359924681001892137L /* log_2 e */ +#define M_LOG10El 0.434294481903251827651128918916605082L /* log_10 e */ +#define M_LN2l 0.693147180559945309417232121458176568L /* log_e 2 */ +#define M_LN10l 2.302585092994045684017991454684364208L /* log_e 10 */ +#define M_PIl 3.141592653589793238462643383279502884L /* pi */ +#define M_PI_2l 1.570796326794896619231321691639751442L /* pi/2 */ +#define M_PI_4l 0.785398163397448309615660845819875721L /* pi/4 */ +#define M_1_PIl 0.318309886183790671537767526745028724L /* 1/pi */ +#define M_2_PIl 0.636619772367581343075535053490057448L /* 2/pi */ +#define M_2_SQRTPIl 1.128379167095512573896158903121545172L /* 2/sqrt(pi) */ +#define M_SQRT2l 1.414213562373095048801688724209698079L /* sqrt(2) */ +#define M_SQRT1_2l 0.707106781186547524400844362104849039L /* 1/sqrt(2) */ +#endif /* __BSD_VISIBLE || __XSI_VISIBLE >= 800 */ + #define MAXFLOAT ((float)3.40282346638528860e+38) extern int signgam; #endif /* __BSD_VISIBLE || __XSI_VISIBLE */ @@ -182,21 +193,21 @@ int __signbitf(float) __pure2; int __signbitl(long double) __pure2; static __inline int -__inline_isnan(__const double __x) +__inline_isnan(const double __x) { return (__x != __x); } static __inline int -__inline_isnanf(__const float __x) +__inline_isnanf(const float __x) { return (__x != __x); } static __inline int -__inline_isnanl(__const long double __x) +__inline_isnanl(const long double __x) { return (__x != __x); diff --git a/lib/libc/include/generic-freebsd/memory.h b/lib/libc/include/generic-freebsd/memory.h index 09031b50abb1..56fbbe6aed28 100644 --- a/lib/libc/include/generic-freebsd/memory.h +++ b/lib/libc/include/generic-freebsd/memory.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)memory.h 8.1 (Berkeley) 6/2/93 */ #include \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/mntopts.h b/lib/libc/include/generic-freebsd/mntopts.h new file mode 100644 index 000000000000..36082194193f --- /dev/null +++ b/lib/libc/include/generic-freebsd/mntopts.h @@ -0,0 +1,114 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MNTOPTS_H_ +#define _MNTOPTS_H_ + +struct mntopt { + const char *m_option; /* option name */ + int m_inverse; /* if a negative option, e.g. "atime" */ + long long m_flag; /* bit to set, e.g. MNT_RDONLY */ + int m_altloc; /* 1 => set bit in altflags */ +}; + +/* User-visible MNT_ flags. */ +#define MOPT_ASYNC { "async", 0, MNT_ASYNC, 0 } +#define MOPT_NOATIME { "atime", 1, MNT_NOATIME, 0 } +#define MOPT_NOEXEC { "exec", 1, MNT_NOEXEC, 0 } +#define MOPT_NOSUID { "suid", 1, MNT_NOSUID, 0 } +#define MOPT_NOSYMFOLLOW { "symfollow", 1, MNT_NOSYMFOLLOW, 0 } +#define MOPT_RDONLY { "rdonly", 0, MNT_RDONLY, 0 } +#define MOPT_SYNC { "sync", 0, MNT_SYNCHRONOUS, 0 } +#define MOPT_UNION { "union", 0, MNT_UNION, 0 } +#define MOPT_USERQUOTA { "userquota", 0, 0, 0 } +#define MOPT_GROUPQUOTA { "groupquota", 0, 0, 0 } +#define MOPT_NOCLUSTERR { "clusterr", 1, MNT_NOCLUSTERR, 0 } +#define MOPT_NOCLUSTERW { "clusterw", 1, MNT_NOCLUSTERW, 0 } +#define MOPT_SUIDDIR { "suiddir", 0, MNT_SUIDDIR, 0 } +#define MOPT_SNAPSHOT { "snapshot", 0, MNT_SNAPSHOT, 0 } +#define MOPT_MULTILABEL { "multilabel", 0, MNT_MULTILABEL, 0 } +#define MOPT_ACLS { "acls", 0, MNT_ACLS, 0 } +#define MOPT_NFS4ACLS { "nfsv4acls", 0, MNT_NFS4ACLS, 0 } +#define MOPT_AUTOMOUNTED { "automounted",0, MNT_AUTOMOUNTED, 0 } +#define MOPT_UNTRUSTED { "untrusted", 0, MNT_UNTRUSTED, 0 } + +/* Control flags. */ +#define MOPT_FORCE { "force", 0, MNT_FORCE, 0 } +#define MOPT_UPDATE { "update", 0, MNT_UPDATE, 0 } +#define MOPT_RO { "ro", 0, MNT_RDONLY, 0 } +#define MOPT_RW { "rw", 1, MNT_RDONLY, 0 } +#define MOPT_NOCOVER { "cover", 1, MNT_NOCOVER, 0 } +#define MOPT_EMPTYDIR { "emptydir", 0, MNT_EMPTYDIR, 0 } +/* This is parsed by mount(8), but is ignored by specific mount_*(8)s. */ +#define MOPT_AUTO { "auto", 0, 0, 0 } + +/* A handy macro as terminator of MNT_ array. */ +#define MOPT_END { NULL, 0, 0, 0 } + +#define MOPT_FSTAB_COMPAT \ + MOPT_RO, \ + MOPT_RW, \ + MOPT_AUTO + +/* Standard options which all mounts can understand. */ +#define MOPT_STDOPTS \ + MOPT_USERQUOTA, \ + MOPT_GROUPQUOTA, \ + MOPT_FSTAB_COMPAT, \ + MOPT_NOATIME, \ + MOPT_NOEXEC, \ + MOPT_SUIDDIR, /* must be before MOPT_NOSUID */ \ + MOPT_NOSUID, \ + MOPT_NOSYMFOLLOW, \ + MOPT_RDONLY, \ + MOPT_UNION, \ + MOPT_NOCLUSTERR, \ + MOPT_NOCLUSTERW, \ + MOPT_MULTILABEL, \ + MOPT_ACLS, \ + MOPT_NFS4ACLS, \ + MOPT_AUTOMOUNTED, \ + MOPT_UNTRUSTED, \ + MOPT_NOCOVER, \ + MOPT_EMPTYDIR + +void getmntopts(const char *, const struct mntopt *, int *, int *); +void rmslashes(char *, char *); +int checkpath(const char *, char resolved_path[]); +int checkpath_allow_file(const char *, char resolved_path[]); +struct statfs *getmntpoint(const char *); +int chkdoreload(struct statfs *, void (*)(const char *, ...) __printflike(1,2)); +extern int getmnt_silent; +void build_iovec(struct iovec **iov, int *iovlen, const char *name, void *val, size_t len); +void build_iovec_argf(struct iovec **iov, int *iovlen, const char *name, const char *fmt, ...); +void free_iovec(struct iovec **iovec, int *iovlen); + +#endif /* !_MNTOPTS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/mpool.h b/lib/libc/include/generic-freebsd/mpool.h index 64bfd8a7cd52..fdabbf606f48 100644 --- a/lib/libc/include/generic-freebsd/mpool.h +++ b/lib/libc/include/generic-freebsd/mpool.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #ifndef _MPOOL_H_ diff --git a/lib/libc/include/generic-freebsd/mqueue.h b/lib/libc/include/generic-freebsd/mqueue.h index e76a659daaea..366b4e84f474 100644 --- a/lib/libc/include/generic-freebsd/mqueue.h +++ b/lib/libc/include/generic-freebsd/mqueue.h @@ -29,7 +29,6 @@ #ifndef _MQUEUE_H_ #define _MQUEUE_H_ -#include #include #include #include diff --git a/lib/libc/include/generic-freebsd/ndbm.h b/lib/libc/include/generic-freebsd/ndbm.h index a647d2a89fde..827654f64d8c 100644 --- a/lib/libc/include/generic-freebsd/ndbm.h +++ b/lib/libc/include/generic-freebsd/ndbm.h @@ -30,8 +30,6 @@ * 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. - * - * @(#)ndbm.h 8.1 (Berkeley) 6/2/93 */ #ifndef _NDBM_H_ diff --git a/lib/libc/include/generic-freebsd/net/altq/altq_rmclass.h b/lib/libc/include/generic-freebsd/net/altq/altq_rmclass.h index 82aa9a980d0c..9572784f5951 100644 --- a/lib/libc/include/generic-freebsd/net/altq/altq_rmclass.h +++ b/lib/libc/include/generic-freebsd/net/altq/altq_rmclass.h @@ -38,8 +38,6 @@ #include -/* #pragma ident "@(#)rm_class.h 1.20 97/10/23 SMI" */ - #ifdef __cplusplus extern "C" { #endif diff --git a/lib/libc/include/generic-freebsd/net/altq/altq_rmclass_debug.h b/lib/libc/include/generic-freebsd/net/altq/altq_rmclass_debug.h index 32e7ee3e45fe..07f3aed89152 100644 --- a/lib/libc/include/generic-freebsd/net/altq/altq_rmclass_debug.h +++ b/lib/libc/include/generic-freebsd/net/altq/altq_rmclass_debug.h @@ -33,8 +33,6 @@ #ifndef _ALTQ_ALTQ_RMCLASS_DEBUG_H_ #define _ALTQ_ALTQ_RMCLASS_DEBUG_H_ -/* #pragma ident "@(#)rm_class_debug.h 1.7 98/05/04 SMI" */ - /* * Cbq debugging macros */ diff --git a/lib/libc/include/generic-freebsd/net/bpf.h b/lib/libc/include/generic-freebsd/net/bpf.h index cac440dfbfea..b80675ff2070 100644 --- a/lib/libc/include/generic-freebsd/net/bpf.h +++ b/lib/libc/include/generic-freebsd/net/bpf.h @@ -32,14 +32,12 @@ * 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. - * - * @(#)bpf.h 8.1 (Berkeley) 6/10/93 - * @(#)bpf.h 1.34 (LBL) 6/16/96 */ #ifndef _NET_BPF_H_ #define _NET_BPF_H_ +#include #include #include #include @@ -431,6 +429,7 @@ void bpfdetach(struct ifnet *); bool bpf_peers_present_if(struct ifnet *); #ifdef VIMAGE int bpf_get_bp_params(struct bpf_if *, u_int *, u_int *); +void bpf_ifdetach(struct ifnet *); #endif void bpfilterattach(int); diff --git a/lib/libc/include/generic-freebsd/net/bpfdesc.h b/lib/libc/include/generic-freebsd/net/bpfdesc.h index 6ddb9b063080..d2a512ee02bd 100644 --- a/lib/libc/include/generic-freebsd/net/bpfdesc.h +++ b/lib/libc/include/generic-freebsd/net/bpfdesc.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)bpfdesc.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NET_BPFDESC_H_ diff --git a/lib/libc/include/generic-freebsd/net/dlt.h b/lib/libc/include/generic-freebsd/net/dlt.h index 41ed713449bd..76be93efe736 100644 --- a/lib/libc/include/generic-freebsd/net/dlt.h +++ b/lib/libc/include/generic-freebsd/net/dlt.h @@ -30,8 +30,6 @@ * 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. - * - * @(#)bpf.h 7.1 (Berkeley) 5/7/91 */ #ifndef _NET_DLT_H_ diff --git a/lib/libc/include/generic-freebsd/net/ethernet.h b/lib/libc/include/generic-freebsd/net/ethernet.h index f9ba1ceb7b29..b78c080d72d4 100644 --- a/lib/libc/include/generic-freebsd/net/ethernet.h +++ b/lib/libc/include/generic-freebsd/net/ethernet.h @@ -40,7 +40,6 @@ /* * Ethernet-specific mbuf flags. */ -#define M_HASFCS M_PROTO5 /* FCS included at end of frame */ #define M_BRIDGE_INJECT M_PROTO6 /* if_bridge-injected frame */ /* @@ -63,6 +62,8 @@ struct ether_header { u_char ether_shost[ETHER_ADDR_LEN]; u_short ether_type; } __packed; +_Static_assert(sizeof(struct ether_header) == ETHER_HDR_LEN, + "size of struct ether_header is wrong"); /* * Structure of a 48-bit Ethernet address. @@ -70,6 +71,8 @@ struct ether_header { struct ether_addr { u_char octet[ETHER_ADDR_LEN]; } __packed; +_Static_assert(sizeof(struct ether_addr) == ETHER_ADDR_LEN, + "size of struct ether_addr is wrong"); #define ETHER_IS_MULTICAST(addr) (*(addr) & 0x01) /* is address mcast/bcast? */ #define ETHER_IS_IPV6_MULTICAST(addr) \ @@ -81,6 +84,28 @@ struct ether_addr { (((addr)[0] | (addr)[1] | (addr)[2] | \ (addr)[3] | (addr)[4] | (addr)[5]) == 0x00) +/* + * 802.1q VID constants from IEEE 802.1Q-2014, table 9-2. + */ + +/* Null VID: The tag contains only PCP (priority) and DEI information. */ +#define DOT1Q_VID_NULL 0x0 +/* The default PVID for a bridge port. NB: bridge(4) does not honor this. */ +#define DOT1Q_VID_DEF_PVID 0x1 +/* The default SR_PVID for SRP Stream related traffic. */ +#define DOT1Q_VID_DEF_SR_PVID 0x2 +/* A VID reserved for implementation use, not permitted on the wire. */ +#define DOT1Q_VID_RSVD_IMPL 0xfff +/* The lowest valid VID. */ +#define DOT1Q_VID_MIN 0x1 +/* The highest valid VID. */ +#define DOT1Q_VID_MAX 0xffe + +/* + * This is the type of the VLAN ID inside the tag, not the tag itself. + */ +typedef uint16_t ether_vlanid_t; + /* * 802.1q Virtual LAN header. */ @@ -91,6 +116,8 @@ struct ether_vlan_header { uint16_t evl_tag; uint16_t evl_proto; } __packed; +_Static_assert(sizeof(struct ether_vlan_header) == ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN, + "size of struct ether_vlan_header is wrong"); #define EVL_VLID_MASK 0x0FFF #define EVL_PRI_MASK 0xE000 diff --git a/lib/libc/include/generic-freebsd/net/if.h b/lib/libc/include/generic-freebsd/net/if.h index a35a56388c7e..06d63a2df8ad 100644 --- a/lib/libc/include/generic-freebsd/net/if.h +++ b/lib/libc/include/generic-freebsd/net/if.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)if.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NET_IF_H_ @@ -257,7 +255,8 @@ struct if_data { #define IFCAP_B_TXTLS_RTLMT 31 /* can do TLS with rate limiting */ #define IFCAP_B_RXTLS4 32 /* can to TLS receive for TCP */ #define IFCAP_B_RXTLS6 33 /* can to TLS receive for TCP6 */ -#define __IFCAP_B_SIZE 34 +#define IFCAP_B_IPSEC_OFFLOAD 34 /* inline IPSEC offload */ +#define __IFCAP_B_SIZE 35 #define IFCAP_B_MAX (__IFCAP_B_MAX - 1) #define IFCAP_B_SIZE (__IFCAP_B_SIZE) @@ -300,6 +299,7 @@ struct if_data { /* IFCAP2_* are integers, not bits. */ #define IFCAP2_RXTLS4 (IFCAP_B_RXTLS4 - 32) #define IFCAP2_RXTLS6 (IFCAP_B_RXTLS6 - 32) +#define IFCAP2_IPSEC_OFFLOAD (IFCAP_B_IPSEC_OFFLOAD - 32) #define IFCAP2_BIT(x) (1UL << (x)) diff --git a/lib/libc/include/generic-freebsd/net/if_arp.h b/lib/libc/include/generic-freebsd/net/if_arp.h index 5379ca79e5b5..4a55d5fd686f 100644 --- a/lib/libc/include/generic-freebsd/net/if_arp.h +++ b/lib/libc/include/generic-freebsd/net/if_arp.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)if_arp.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NET_IF_ARP_H_ diff --git a/lib/libc/include/generic-freebsd/net/if_bridgevar.h b/lib/libc/include/generic-freebsd/net/if_bridgevar.h index 6be40a8ec10f..09679bff72f6 100644 --- a/lib/libc/include/generic-freebsd/net/if_bridgevar.h +++ b/lib/libc/include/generic-freebsd/net/if_bridgevar.h @@ -74,7 +74,12 @@ * Data structure and control definitions for bridge interfaces. */ +#ifndef _NET_IF_BRIDGEVAR_H_ +#define _NET_IF_BRIDGEVAR_H_ + #include +#include +#include #include #include #include @@ -119,6 +124,22 @@ #define BRDGSPROTO 28 /* set protocol (ifbrparam) */ #define BRDGSTXHC 29 /* set tx hold count (ifbrparam) */ #define BRDGSIFAMAX 30 /* set max interface addrs (ifbreq) */ +#define BRDGSIFPVID 31 /* set if PVID */ +#define BRDGSIFVLANSET 32 /* set if vlan set */ +#define BRDGGIFVLANSET 33 /* get if vlan set */ +#define BRDGGFLAGS 34 /* get bridge flags (ifbrparam) */ +#define BRDGSFLAGS 35 /* set bridge flags (ifbrparam) */ +#define BRDGGDEFPVID 36 /* get default pvid (ifbrparam) */ +#define BRDGSDEFPVID 37 /* set default pvid (ifbrparam) */ +#define BRDGSIFVLANPROTO 38 /* set if vlan protocol (ifbreq) */ + +/* BRDGSFLAGS, Bridge flags (non-interface-specific) */ +typedef uint32_t ifbr_flags_t; + +#define IFBRF_VLANFILTER (1U<<0) /* VLAN filtering enabled */ +#define IFBRF_DEFQINQ (1U<<1) /* 802.1ad Q-in-Q allowed by default */ + +#define IFBRFBITS "\020\01VLANFILTER\02DEFQINQ" /* * Generic bridge control request. @@ -136,7 +157,9 @@ struct ifbreq { uint32_t ifbr_addrcnt; /* member if addr number */ uint32_t ifbr_addrmax; /* member if addr max */ uint32_t ifbr_addrexceeded; /* member if addr violations */ - uint8_t pad[32]; + ether_vlanid_t ifbr_pvid; /* member if PVID */ + uint16_t ifbr_vlanproto; /* member if VLAN protocol */ + uint8_t pad[28]; }; /* BRDGGIFFLAGS, BRDGSIFFLAGS */ @@ -152,10 +175,11 @@ struct ifbreq { #define IFBIF_BSTP_ADMEDGE 0x0200 /* member stp admin edge enabled */ #define IFBIF_BSTP_ADMCOST 0x0400 /* member stp admin path cost */ #define IFBIF_PRIVATE 0x0800 /* if is a private segment */ +#define IFBIF_QINQ 0x1000 /* if allows 802.1ad Q-in-Q */ #define IFBIFBITS "\020\001LEARNING\002DISCOVER\003STP\004SPAN" \ "\005STICKY\014PRIVATE\006EDGE\007AUTOEDGE\010PTP" \ - "\011AUTOPTP" + "\011AUTOPTP\015QINQ" #define IFBIFMASK ~(IFBIF_BSTP_EDGE|IFBIF_BSTP_AUTOEDGE|IFBIF_BSTP_PTP| \ IFBIF_BSTP_AUTOPTP|IFBIF_BSTP_ADMEDGE| \ IFBIF_BSTP_ADMCOST) /* not saved */ @@ -185,7 +209,7 @@ struct ifbareq { unsigned long ifba_expire; /* address expire time */ uint8_t ifba_flags; /* address flags */ uint8_t ifba_dst[ETHER_ADDR_LEN];/* destination address */ - uint16_t ifba_vlan; /* vlan id */ + ether_vlanid_t ifba_vlan; /* vlan id */ }; #define IFBAF_TYPEMASK 0x03 /* address type mask */ @@ -227,7 +251,11 @@ struct ifbrparam { #define ifbrp_fwddelay ifbrp_ifbrpu.ifbrpu_int8 /* fwd time (sec) */ #define ifbrp_maxage ifbrp_ifbrpu.ifbrpu_int8 /* max age (sec) */ #define ifbrp_cexceeded ifbrp_ifbrpu.ifbrpu_int32 /* # of cache dropped - * adresses */ + * addresses */ +#define ifbrp_flags ifbrp_ifbrpu.ifbrpu_int32 /* bridge flags */ +#define ifbrp_defpvid ifbrp_ifbrpu.ifbrpu_int16 /* default pvid */ +#define ifbrp_vlanproto ifbrp_ifbrpu.ifbrpu_int8 /* vlan protocol */ + /* * Bridge current operational parameters structure. */ @@ -301,6 +329,26 @@ struct ifbpstpconf { eaddr[5] = pv >> 0; \ } while (0) +/* + * Bridge VLAN access request. + */ +#define BRVLAN_SETSIZE 4096 +typedef __BITSET_DEFINE(ifbvlan_set, BRVLAN_SETSIZE) ifbvlan_set_t; + +#define BRVLAN_SET(set, bit) __BIT_SET(BRVLAN_SETSIZE, (bit), set) +#define BRVLAN_CLR(set, bit) __BIT_CLR(BRVLAN_SETSIZE, (bit), set) +#define BRVLAN_TEST(set, bit) __BIT_ISSET(BRVLAN_SETSIZE, (bit), set) + +#define BRDG_VLAN_OP_SET 1 /* replace current vlan set */ +#define BRDG_VLAN_OP_ADD 2 /* add vlans to current set */ +#define BRDG_VLAN_OP_DEL 3 /* remove vlans from current set */ + +struct ifbif_vlan_req { + char bv_ifname[IFNAMSIZ]; + uint8_t bv_op; + ifbvlan_set_t bv_set; +}; + #ifdef _KERNEL #define BRIDGE_INPUT(_ifp, _m) do { \ @@ -320,5 +368,10 @@ struct ifbpstpconf { } while (0) extern void (*bridge_dn_p)(struct mbuf *, struct ifnet *); +extern bool (*bridge_same_p)(const void *, const void *); +extern void *(*bridge_get_softc_p)(struct ifnet *); +extern bool (*bridge_member_ifaddrs_p)(void); + +#endif /* _KERNEL */ -#endif /* _KERNEL */ \ No newline at end of file +#endif /* _NET_IF_BRIDGEVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/net/if_clone.h b/lib/libc/include/generic-freebsd/net/if_clone.h index e9a25bffc1d8..84a7d91176b2 100644 --- a/lib/libc/include/generic-freebsd/net/if_clone.h +++ b/lib/libc/include/generic-freebsd/net/if_clone.h @@ -27,8 +27,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * From: @(#)if.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NET_IF_CLONE_H_ @@ -150,13 +148,12 @@ typedef void (*if_clone_event_handler_t)(void *, struct if_clone *); EVENTHANDLER_DECLARE(if_clone_event, if_clone_event_handler_t); /* The below interfaces used only by net/if.c. */ -void vnet_if_clone_init(void); int if_clone_create(char *, size_t, caddr_t); int if_clone_destroy(const char *); int if_clone_list(struct if_clonereq *); void if_clone_restoregroup(struct ifnet *); -/* The below interfaces are used only by epair(4). */ +/* The below interfaces are used only by epair(4) and tun(4)/tap(4). */ void if_clone_addif(struct if_clone *, struct ifnet *); int if_clone_destroyif(struct if_clone *, struct ifnet *); diff --git a/lib/libc/include/generic-freebsd/net/if_dl.h b/lib/libc/include/generic-freebsd/net/if_dl.h index 282d4b5fab73..a88e404a5356 100644 --- a/lib/libc/include/generic-freebsd/net/if_dl.h +++ b/lib/libc/include/generic-freebsd/net/if_dl.h @@ -27,13 +27,13 @@ * 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. - * - * @(#)if_dl.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NET_IF_DL_H_ #define _NET_IF_DL_H_ +#include + /* * A Link-Level Sockaddr may specify the interface in one of two * ways: either by means of a system-provided index number (computed @@ -67,22 +67,25 @@ struct sockaddr_dl { contains both if name and ll address */ }; -#define LLADDR(s) ((caddr_t)((s)->sdl_data + (s)->sdl_nlen)) -#define CLLADDR(s) ((c_caddr_t)((s)->sdl_data + (s)->sdl_nlen)) +#define LLADDR(s) (&(s)->sdl_data[(s)->sdl_nlen]) #define LLINDEX(s) ((s)->sdl_index) +#ifdef _KERNEL + struct ifnet; -struct sockaddr_dl *link_alloc_sdl(size_t, int); +struct sockaddr_dl *link_alloc_sdl(size_t size, int flags); void link_free_sdl(struct sockaddr *sa); -struct sockaddr_dl *link_init_sdl(struct ifnet *, struct sockaddr *, u_char); +struct sockaddr_dl *link_init_sdl(struct ifnet *ifp, struct sockaddr *paddr, + u_char iftypes); -#ifndef _KERNEL +#else /* !_KERNEL */ #include __BEGIN_DECLS -void link_addr(const char *, struct sockaddr_dl *); +int link_addr(const char *, struct sockaddr_dl *); char *link_ntoa(const struct sockaddr_dl *); +int link_ntoa_r(const struct sockaddr_dl *, char *, size_t *); __END_DECLS #endif /* !_KERNEL */ diff --git a/lib/libc/include/generic-freebsd/net/if_gif.h b/lib/libc/include/generic-freebsd/net/if_gif.h index 76bc55ce9726..7476c04d333c 100644 --- a/lib/libc/include/generic-freebsd/net/if_gif.h +++ b/lib/libc/include/generic-freebsd/net/if_gif.h @@ -120,7 +120,8 @@ int in6_gif_setopts(struct gif_softc *, u_int); #define GIFGOPTS _IOWR('i', 150, struct ifreq) #define GIFSOPTS _IOW('i', 151, struct ifreq) +#define GIF_NOCLAMP 0x0001 #define GIF_IGNORE_SOURCE 0x0002 -#define GIF_OPTMASK (GIF_IGNORE_SOURCE) +#define GIF_OPTMASK (GIF_NOCLAMP|GIF_IGNORE_SOURCE) #endif /* _NET_IF_GIF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/net/if_llc.h b/lib/libc/include/generic-freebsd/net/if_llc.h index 555e2cd0641e..fc5a6bd167e3 100644 --- a/lib/libc/include/generic-freebsd/net/if_llc.h +++ b/lib/libc/include/generic-freebsd/net/if_llc.h @@ -29,8 +29,6 @@ * 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. - * - * @(#)if_llc.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NET_IF_LLC_H_ diff --git a/lib/libc/include/generic-freebsd/net/if_media.h b/lib/libc/include/generic-freebsd/net/if_media.h index 5f35ef1a5dbc..8dae3a001497 100644 --- a/lib/libc/include/generic-freebsd/net/if_media.h +++ b/lib/libc/include/generic-freebsd/net/if_media.h @@ -258,6 +258,8 @@ uint64_t ifmedia_baudrate(int); #define IFM_400G_AUI8 IFM_X(117) /* 400G-AUI8 */ #define IFM_50G_KR4 IFM_X(118) /* 50GBase-KR4 */ #define IFM_40G_LM4 IFM_X(119) /* 40GBase-LM4 */ +#define IFM_100_BX IFM_X(120) /* 100Base-BX */ +#define IFM_1000_BX IFM_X(121) /* 1000Base-BX */ /* * Please update ieee8023ad_lacp.c:lacp_compose_key() @@ -437,11 +439,13 @@ struct ifmedia_description { { IFM_100_T4, "100baseT4" }, \ { IFM_100_VG, "100baseVG" }, \ { IFM_100_T2, "100baseT2" }, \ + { IFM_100_BX, "100baseBX" }, \ { IFM_10_STP, "10baseSTP" }, \ { IFM_10_FL, "10baseFL" }, \ { IFM_1000_SX, "1000baseSX" }, \ { IFM_1000_LX, "1000baseLX" }, \ { IFM_1000_CX, "1000baseCX" }, \ + { IFM_1000_BX, "1000baseBX" }, \ { IFM_1000_T, "1000baseT" }, \ { IFM_HPNA_1, "homePNA" }, \ { IFM_10G_LR, "10Gbase-LR" }, \ @@ -784,11 +788,13 @@ struct ifmedia_baudrate { { IFM_ETHER | IFM_100_T4, IF_Mbps(100) }, \ { IFM_ETHER | IFM_100_VG, IF_Mbps(100) }, \ { IFM_ETHER | IFM_100_T2, IF_Mbps(100) }, \ + { IFM_ETHER | IFM_100_BX, IF_Mbps(100) }, \ { IFM_ETHER | IFM_1000_SX, IF_Mbps(1000) }, \ { IFM_ETHER | IFM_10_STP, IF_Mbps(10) }, \ { IFM_ETHER | IFM_10_FL, IF_Mbps(10) }, \ { IFM_ETHER | IFM_1000_LX, IF_Mbps(1000) }, \ { IFM_ETHER | IFM_1000_CX, IF_Mbps(1000) }, \ + { IFM_ETHER | IFM_1000_BX, IF_Mbps(1000) }, \ { IFM_ETHER | IFM_1000_T, IF_Mbps(1000) }, \ { IFM_ETHER | IFM_HPNA_1, IF_Mbps(1) }, \ { IFM_ETHER | IFM_10G_LR, IF_Gbps(10ULL) }, \ diff --git a/lib/libc/include/generic-freebsd/net/if_ovpn.h b/lib/libc/include/generic-freebsd/net/if_ovpn.h index d982717d87bb..6754b810fc76 100644 --- a/lib/libc/include/generic-freebsd/net/if_ovpn.h +++ b/lib/libc/include/generic-freebsd/net/if_ovpn.h @@ -37,6 +37,7 @@ enum ovpn_notif_type { OVPN_NOTIF_DEL_PEER, OVPN_NOTIF_ROTATE_KEY, + OVPN_NOTIF_FLOAT, }; enum ovpn_del_reason { diff --git a/lib/libc/include/generic-freebsd/net/if_pflog.h b/lib/libc/include/generic-freebsd/net/if_pflog.h index 327abfd631ea..18d333456bef 100644 --- a/lib/libc/include/generic-freebsd/net/if_pflog.h +++ b/lib/libc/include/generic-freebsd/net/if_pflog.h @@ -33,8 +33,6 @@ #include -#define PFLOGIFS_MAX 16 - #define PFLOG_RULESET_NAME_SIZE 16 struct pfloghdr { @@ -51,7 +49,9 @@ struct pfloghdr { uid_t rule_uid; pid_t rule_pid; u_int8_t dir; - u_int8_t pad[3]; + u_int8_t pad1; /* rewritten, on OpenBSD */ + sa_family_t naf; + u_int8_t pad[1]; u_int32_t ridentifier; u_int8_t reserve; /* Appease broken software like Wireshark. */ u_int8_t pad2[3]; @@ -69,9 +69,9 @@ struct pf_ruleset; struct pfi_kif; struct pf_pdesc; -#define PFLOG_PACKET(i,a,b,c,d,e,f,g,di) do { \ +#define PFLOG_PACKET(b,t,c,d,e,f,g,h) do { \ if (pflog_packet_ptr != NULL) \ - pflog_packet_ptr(i,a,b,c,d,e,f,g,di); \ + pflog_packet_ptr(b,t,c,d,e,f,g,h); \ } while (0) #endif /* _KERNEL */ #endif /* _NET_IF_PFLOG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/net/if_pfsync.h b/lib/libc/include/generic-freebsd/net/if_pfsync.h index fcbb52e2ef13..a07c0d880f16 100644 --- a/lib/libc/include/generic-freebsd/net/if_pfsync.h +++ b/lib/libc/include/generic-freebsd/net/if_pfsync.h @@ -62,9 +62,10 @@ enum pfsync_msg_versions { PFSYNC_MSG_VERSION_UNSPECIFIED = 0, PFSYNC_MSG_VERSION_1301 = 1301, PFSYNC_MSG_VERSION_1400 = 1400, + PFSYNC_MSG_VERSION_1500 = 1500, }; -#define PFSYNC_MSG_VERSION_DEFAULT PFSYNC_MSG_VERSION_1400 +#define PFSYNC_MSG_VERSION_DEFAULT PFSYNC_MSG_VERSION_1500 #define PFSYNC_ACT_CLR 0 /* clear all states */ #define PFSYNC_ACT_INS_1301 1 /* insert state */ @@ -81,7 +82,9 @@ enum pfsync_msg_versions { #define PFSYNC_ACT_EOF 12 /* end of frame */ #define PFSYNC_ACT_INS_1400 13 /* insert state */ #define PFSYNC_ACT_UPD_1400 14 /* update state */ -#define PFSYNC_ACT_MAX 15 +#define PFSYNC_ACT_INS_1500 15 /* insert state */ +#define PFSYNC_ACT_UPD_1500 16 /* update state */ +#define PFSYNC_ACT_MAX 17 /* * A pfsync frame is built from a header followed by several sections which @@ -160,8 +163,8 @@ struct pfsync_ins_ack { struct pfsync_upd_c { u_int64_t id; - struct pfsync_state_peer src; - struct pfsync_state_peer dst; + struct pf_state_peer_export src; + struct pf_state_peer_export dst; u_int32_t creatorid; u_int32_t expire; u_int8_t timeout; diff --git a/lib/libc/include/generic-freebsd/net/if_private.h b/lib/libc/include/generic-freebsd/net/if_private.h index f779490c3f09..22444e666053 100644 --- a/lib/libc/include/generic-freebsd/net/if_private.h +++ b/lib/libc/include/generic-freebsd/net/if_private.h @@ -27,8 +27,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * From: @(#)if.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NET_IF_PRIVATE_H_ @@ -140,6 +138,8 @@ struct ifnet { int (*if_requestencap) /* make link header from request */ (struct ifnet *, struct if_encap_req *); + const struct if_ipsec_accel_methods *if_ipsec_accel_m; + /* Statistics. */ counter_u64_t if_counters[IFCOUNTERS]; diff --git a/lib/libc/include/generic-freebsd/net/if_strings.h b/lib/libc/include/generic-freebsd/net/if_strings.h index b58825cdce5b..1427475b2fde 100644 --- a/lib/libc/include/generic-freebsd/net/if_strings.h +++ b/lib/libc/include/generic-freebsd/net/if_strings.h @@ -60,10 +60,13 @@ #define IFCAP_TXTLS_RTLMT_NAME "TXTLS_RTLMT" #define IFCAP_RXTLS4_NAME "RXTLS4" #define IFCAP_RXTLS6_NAME "RXTLS6" +#define IFCAP_IPSEC_OFFLOAD_NAME "IPSEC" #define IFCAP2_RXTLS4_NAME IFCAP_RXTLS4_NAME #define IFCAP2_RXTLS6_NAME IFCAP_RXTLS6_NAME +#define IFCAP2_IPSEC_OFFLOAD_NAME IFCAP_IPSEC_OFFLOAD_NAME +#ifdef _WANT_IFCAP_BIT_NAMES static const char *ifcap_bit_names[] = { IFCAP_RXCSUM_NAME, IFCAP_TXCSUM_NAME, @@ -99,11 +102,13 @@ static const char *ifcap_bit_names[] = { IFCAP_TXTLS_RTLMT_NAME, IFCAP_RXTLS4_NAME, IFCAP_RXTLS6_NAME, + IFCAP_IPSEC_OFFLOAD_NAME, }; #ifdef IFCAP_B_SIZE _Static_assert(sizeof(ifcap_bit_names) >= IFCAP_B_SIZE * sizeof(char *), "ifcap bit names missing from ifcap_bit_names"); #endif +#endif #endif \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/net/if_tap.h b/lib/libc/include/generic-freebsd/net/if_tap.h index 7c06de555fa8..4c9e86ef847e 100644 --- a/lib/libc/include/generic-freebsd/net/if_tap.h +++ b/lib/libc/include/generic-freebsd/net/if_tap.h @@ -57,6 +57,8 @@ #define TAPGIFNAME TUNGIFNAME #define TAPSVNETHDR _IOW('t', 91, int) #define TAPGVNETHDR _IOR('t', 94, int) +#define TAPSTRANSIENT TUNSTRANSIENT +#define TAPGTRANSIENT TUNGTRANSIENT /* VMware ioctl's */ #define VMIO_SIOCSIFFLAGS _IOWINT('V', 0) diff --git a/lib/libc/include/generic-freebsd/net/if_tun.h b/lib/libc/include/generic-freebsd/net/if_tun.h index 7c6e2e7361f3..ca80dd32b2e9 100644 --- a/lib/libc/include/generic-freebsd/net/if_tun.h +++ b/lib/libc/include/generic-freebsd/net/if_tun.h @@ -43,5 +43,7 @@ struct tuninfo { #define TUNSIFPID _IO('t', 95) #define TUNSIFHEAD _IOW('t', 96, int) #define TUNGIFHEAD _IOR('t', 97, int) +#define TUNSTRANSIENT _IOW('t', 98, int) +#define TUNGTRANSIENT _IOR('t', 99, int) #endif /* !_NET_IF_TUN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/net/if_types.h b/lib/libc/include/generic-freebsd/net/if_types.h index e4869b3b6d74..918e3f7e465b 100644 --- a/lib/libc/include/generic-freebsd/net/if_types.h +++ b/lib/libc/include/generic-freebsd/net/if_types.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)if_types.h 8.3 (Berkeley) 4/28/95 * $NetBSD: if_types.h,v 1.16 2000/04/19 06:30:53 itojun Exp $ */ @@ -256,6 +254,7 @@ typedef enum { IFT_PFLOG = 0xf6, /* PF packet filter logging */ IFT_PFSYNC = 0xf7, /* PF packet filter synchronization */ IFT_WIREGUARD = 0xf8, /* WireGuard tunnel */ + IFT_MBIM = 0xf9, /* Mobile Broadband Interface Model */ } ifType; /* diff --git a/lib/libc/include/generic-freebsd/net/if_var.h b/lib/libc/include/generic-freebsd/net/if_var.h index 57d135eacfe2..f4e12ce9ec97 100644 --- a/lib/libc/include/generic-freebsd/net/if_var.h +++ b/lib/libc/include/generic-freebsd/net/if_var.h @@ -27,8 +27,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * From: @(#)if.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NET_IF_VAR_H_ @@ -133,6 +131,25 @@ typedef void (*if_qflush_fn_t)(if_t); typedef int (*if_transmit_fn_t)(if_t, struct mbuf *); typedef uint64_t (*if_get_counter_t)(if_t, ift_counter); typedef void (*if_reassign_fn_t)(if_t, struct vnet *, char *); +typedef int (*if_spdadd_fn_t)(if_t ifp, void *sp, void *inp, void **priv); +typedef int (*if_spddel_fn_t)(if_t ifp, void *sp, void *priv); +typedef int (*if_sa_newkey_fn_t)(if_t ifp, void *sav, u_int drv_spi, + void **privp); +typedef int (*if_sa_deinstall_fn_t)(if_t ifp, u_int drv_spi, void *priv); +struct seclifetime; +#define IF_SA_CNT_UPD 0x80000000 +enum IF_SA_CNT_WHICH { + IF_SA_CNT_IFP_HW_VAL = 1, + IF_SA_CNT_TOTAL_SW_VAL, + IF_SA_CNT_TOTAL_HW_VAL, + IF_SA_CNT_IFP_HW_UPD = IF_SA_CNT_IFP_HW_VAL | IF_SA_CNT_UPD, + IF_SA_CNT_TOTAL_SW_UPD = IF_SA_CNT_TOTAL_SW_VAL | IF_SA_CNT_UPD, + IF_SA_CNT_TOTAL_HW_UPD = IF_SA_CNT_TOTAL_HW_VAL | IF_SA_CNT_UPD, +}; +typedef int (*if_sa_cnt_fn_t)(if_t ifp, void *sa, + uint32_t drv_spi, void *priv, struct seclifetime *lt); +typedef int (*if_ipsec_hwassist_fn_t)(if_t ifp, void *sav, + u_int drv_spi,void *priv); struct ifnet_hw_tsomax { u_int tsomaxbytes; /* TSO total burst length limit in bytes */ @@ -280,12 +297,14 @@ typedef int (if_snd_tag_modify_t)(struct m_snd_tag *, union if_snd_tag_modify_pa typedef int (if_snd_tag_query_t)(struct m_snd_tag *, union if_snd_tag_query_params *); typedef void (if_snd_tag_free_t)(struct m_snd_tag *); typedef struct m_snd_tag *(if_next_send_tag_t)(struct m_snd_tag *); +typedef int (if_snd_tag_status_str_t)(struct m_snd_tag *, char *buf, size_t *sz); struct if_snd_tag_sw { if_snd_tag_modify_t *snd_tag_modify; if_snd_tag_query_t *snd_tag_query; if_snd_tag_free_t *snd_tag_free; if_next_send_tag_t *next_snd_tag; + if_snd_tag_status_str_t *snd_tag_status_str; u_int type; /* One of IF_SND_TAG_TYPE_*. */ }; @@ -603,6 +622,7 @@ int if_setmtu(if_t ifp, int mtu); int if_getmtu(const if_t ifp); int if_getmtu_family(const if_t ifp, int family); void if_notifymtu(if_t ifp); +void if_setppromisc(const if_t ifp, bool ppromisc); int if_setflagbits(if_t ifp, int set, int clear); int if_setflags(if_t ifp, int flags); int if_getflags(const if_t ifp); @@ -626,11 +646,9 @@ void if_setrcvif(struct mbuf *m, if_t ifp); void if_setvtag(struct mbuf *m, u_int16_t tag); u_int16_t if_getvtag(struct mbuf *m); int if_vlantrunkinuse(if_t ifp); -caddr_t if_getlladdr(const if_t ifp); +char *if_getlladdr(const if_t ifp); struct vnet *if_getvnet(const if_t ifp); void *if_gethandle(u_char); -void if_bpfmtap(if_t ifp, struct mbuf *m); -void if_etherbpfmtap(if_t ifp, struct mbuf *m); void if_vlancap(if_t ifp); int if_transmit(if_t ifp, struct mbuf *m); void if_init(if_t ifp, void *ctx); @@ -703,6 +721,20 @@ void if_setdebugnet_methods(if_t, struct debugnet_methods *); void if_setreassignfn(if_t ifp, if_reassign_fn_t); void if_setratelimitqueryfn(if_t ifp, if_ratelimit_query_t); +/* + * NB: The interface is not yet stable, drivers implementing IPSEC + * offload need to be prepared to adapt to changes. + */ +struct if_ipsec_accel_methods { + if_spdadd_fn_t if_spdadd; + if_spddel_fn_t if_spddel; + if_sa_newkey_fn_t if_sa_newkey; + if_sa_deinstall_fn_t if_sa_deinstall; + if_sa_cnt_fn_t if_sa_cnt; + if_ipsec_hwassist_fn_t if_hwassist; +}; +void if_setipsec_accel_methods(if_t ifp, const struct if_ipsec_accel_methods *); + /* TSO */ void if_hw_tsomax_common(if_t ifp, struct ifnet_hw_tsomax *); int if_hw_tsomax_update(if_t ifp, struct ifnet_hw_tsomax *); @@ -724,7 +756,6 @@ int ether_poll_deregister(if_t ifp); #endif /* _KERNEL */ -#include /* XXX: temporary until drivers converted. */ #include /* XXXAO: temporary unconditional include */ #endif /* !_NET_IF_VAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/net/if_vlan_var.h b/lib/libc/include/generic-freebsd/net/if_vlan_var.h index 24397ce8e91b..5cdcc962d344 100644 --- a/lib/libc/include/generic-freebsd/net/if_vlan_var.h +++ b/lib/libc/include/generic-freebsd/net/if_vlan_var.h @@ -126,11 +126,6 @@ struct vlanreq { #define VLAN_PCP_MAX 7 -#define DOT1Q_VID_NULL 0x0 -#define DOT1Q_VID_DEF_PVID 0x1 -#define DOT1Q_VID_DEF_SR_PVID 0x2 -#define DOT1Q_VID_RSVD_IMPL 0xfff - /* * 802.1q full tag. Proto and vid are stored in host byte order. */ @@ -166,6 +161,7 @@ extern int (*vlan_tag_p)(struct ifnet *, uint16_t *); extern int (*vlan_pcp_p)(struct ifnet *, uint16_t *); extern int (*vlan_setcookie_p)(struct ifnet *, void *); extern void *(*vlan_cookie_p)(struct ifnet *); +extern void (*vlan_input_p)(struct ifnet *, struct mbuf *); #include diff --git a/lib/libc/include/generic-freebsd/net/iflib.h b/lib/libc/include/generic-freebsd/net/iflib.h index 45be7047a35d..e32f0eed6314 100644 --- a/lib/libc/include/generic-freebsd/net/iflib.h +++ b/lib/libc/include/generic-freebsd/net/iflib.h @@ -121,13 +121,13 @@ typedef struct if_pkt_info { uint16_t ipi_tso_segsz; /* tso segment size */ uint16_t ipi_vtag; /* VLAN tag */ uint16_t ipi_etype; /* ether header type */ - uint8_t ipi_tcp_hflags; /* tcp header flags */ - uint8_t ipi_mflags; /* packet mbuf flags */ + uint16_t ipi_tcp_hflags; /* tcp header flags */ uint32_t ipi_tcp_seq; /* tcp seqno */ uint8_t ipi_ip_tos; /* IP ToS field data */ + uint8_t ipi_mflags; /* packet mbuf flags */ uint8_t __spare0__; - uint16_t __spare1__; + uint8_t __spare1__; } *if_pkt_info_t; typedef struct if_irq { @@ -470,9 +470,9 @@ void iflib_irq_free(if_ctx_t ctx, if_irq_t irq); void iflib_io_tqg_attach(struct grouptask *gt, void *uniq, int cpu, const char *name); -void iflib_config_gtask_init(void *ctx, struct grouptask *gtask, - gtask_fn_t *fn, const char *name); -void iflib_config_gtask_deinit(struct grouptask *gtask); +void iflib_config_task_init(if_ctx_t ctx, struct task *config_task, + task_fn_t *fn); +void iflib_config_task_enqueue(if_ctx_t ctx, struct task *config_task); void iflib_tx_intr_deferred(if_ctx_t ctx, int txqid); void iflib_rx_intr_deferred(if_ctx_t ctx, int rxqid); diff --git a/lib/libc/include/generic-freebsd/net/ifq.h b/lib/libc/include/generic-freebsd/net/ifq.h index c114e91cc30a..5a55dc1d8954 100644 --- a/lib/libc/include/generic-freebsd/net/ifq.h +++ b/lib/libc/include/generic-freebsd/net/ifq.h @@ -27,8 +27,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * From: @(#)if.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NET_IFQ_H_ diff --git a/lib/libc/include/generic-freebsd/net/pfkeyv2.h b/lib/libc/include/generic-freebsd/net/pfkeyv2.h index 8b0e7d3ddcc3..cd4e4b9e6072 100644 --- a/lib/libc/include/generic-freebsd/net/pfkeyv2.h +++ b/lib/libc/include/generic-freebsd/net/pfkeyv2.h @@ -296,6 +296,13 @@ struct sadb_x_sa_replay { }; _Static_assert(sizeof(struct sadb_x_sa_replay) == 8, "struct size mismatch"); +struct sadb_x_if_hw_offl { + u_int16_t sadb_x_if_hw_offl_len; + u_int16_t sadb_x_if_hw_offl_exttype; + u_int32_t sadb_x_if_hw_offl_flags; + u_int8_t sadb_x_if_hw_offl_if[32]; /* IF_NAMESIZE is 16, keep room */ +}; + #define SADB_EXT_RESERVED 0 #define SADB_EXT_SA 1 #define SADB_EXT_LIFETIME_CURRENT 2 @@ -326,7 +333,10 @@ _Static_assert(sizeof(struct sadb_x_sa_replay) == 8, "struct size mismatch"); #define SADB_X_EXT_SA_REPLAY 26 /* Replay window override. */ #define SADB_X_EXT_NEW_ADDRESS_SRC 27 #define SADB_X_EXT_NEW_ADDRESS_DST 28 -#define SADB_EXT_MAX 28 +#define SADB_X_EXT_LFT_CUR_SW_OFFL 29 +#define SADB_X_EXT_LFT_CUR_HW_OFFL 30 +#define SADB_X_EXT_IF_HW_OFFL 31 +#define SADB_EXT_MAX 31 #define SADB_SATYPE_UNSPEC 0 #define SADB_SATYPE_AH 2 @@ -444,13 +454,13 @@ _Static_assert(sizeof(struct sadb_x_sa_replay) == 8, "struct size mismatch"); /* Utilities */ #define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1))) #define PFKEY_EXTLEN(msg) \ - PFKEY_UNUNIT64(((struct sadb_ext *)(msg))->sadb_ext_len) + PFKEY_UNUNIT64(((const struct sadb_ext *)(msg))->sadb_ext_len) #define PFKEY_ADDR_PREFIX(ext) \ - (((struct sadb_address *)(ext))->sadb_address_prefixlen) + (((const struct sadb_address *)(ext))->sadb_address_prefixlen) #define PFKEY_ADDR_PROTO(ext) \ - (((struct sadb_address *)(ext))->sadb_address_proto) + (((const struct sadb_address *)(ext))->sadb_address_proto) #define PFKEY_ADDR_SADDR(ext) \ - ((struct sockaddr *)((caddr_t)(ext) + sizeof(struct sadb_address))) + ((const struct sockaddr *)((c_caddr_t)(ext) + sizeof(struct sadb_address))) /* in 64bits */ #define PFKEY_UNUNIT64(a) ((a) << 3) diff --git a/lib/libc/include/generic-freebsd/net/pflow.h b/lib/libc/include/generic-freebsd/net/pflow.h new file mode 100644 index 000000000000..8fcbfe666232 --- /dev/null +++ b/lib/libc/include/generic-freebsd/net/pflow.h @@ -0,0 +1,382 @@ +/* $OpenBSD: if_pflow.h,v 1.19 2022/11/23 15:12:27 mvs Exp $ */ + +/* + * Copyright (c) 2008 Henning Brauer + * Copyright (c) 2008 Joerg Goltermann + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _NET_IF_PFLOW_H_ +#define _NET_IF_PFLOW_H_ + +#include +#include +#include + +#include + +#ifdef _KERNEL +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#endif + +#define PFLOW_MAX_ENTRIES 128 + +#define PFLOW_ID_LEN sizeof(u_int64_t) + +#define PFLOW_MAXFLOWS 30 +#define PFLOW_ENGINE_TYPE 42 +#define PFLOW_ENGINE_ID 42 +#define PFLOW_MAXBYTES 0xffffffff +#define PFLOW_TIMEOUT 30 +#define PFLOW_TMPL_TIMEOUT 30 /* rfc 5101 10.3.6 (p.40) recommends 600 */ + +#define PFLOW_IPFIX_TMPL_SET_ID 2 + +/* RFC 5102 Information Element Identifiers */ + +#define PFIX_IE_octetDeltaCount 1 +#define PFIX_IE_packetDeltaCount 2 +#define PFIX_IE_protocolIdentifier 4 +#define PFIX_IE_ipClassOfService 5 +#define PFIX_IE_sourceTransportPort 7 +#define PFIX_IE_sourceIPv4Address 8 +#define PFIX_IE_ingressInterface 10 +#define PFIX_IE_destinationTransportPort 11 +#define PFIX_IE_destinationIPv4Address 12 +#define PFIX_IE_egressInterface 14 +#define PFIX_IE_flowEndSysUpTime 21 +#define PFIX_IE_flowStartSysUpTime 22 +#define PFIX_IE_sourceIPv6Address 27 +#define PFIX_IE_destinationIPv6Address 28 +#define PFIX_IE_flowStartMilliseconds 152 +#define PFIX_IE_flowEndMilliseconds 153 +#define PFIX_IE_postNATSourceIPv4Address 225 +#define PFIX_IE_postNATDestinationIPv4Address 226 +#define PFIX_IE_postNAPTSourceTransportPort 227 +#define PFIX_IE_postNAPTDestinationTransportPort 228 +#define PFIX_IE_natEvent 230 +#define PFIX_NAT_EVENT_SESSION_CREATE 4 +#define PFIX_NAT_EVENT_SESSION_DELETE 5 +#define PFIX_IE_timeStamp 323 + +struct pflow_flow { + u_int32_t src_ip; + u_int32_t dest_ip; + u_int32_t nexthop_ip; + u_int16_t if_index_in; + u_int16_t if_index_out; + u_int32_t flow_packets; + u_int32_t flow_octets; + u_int32_t flow_start; + u_int32_t flow_finish; + u_int16_t src_port; + u_int16_t dest_port; + u_int8_t pad1; + u_int8_t tcp_flags; + u_int8_t protocol; + u_int8_t tos; + u_int16_t src_as; + u_int16_t dest_as; + u_int8_t src_mask; + u_int8_t dest_mask; + u_int16_t pad2; +} __packed; + +struct pflow_set_header { + u_int16_t set_id; + u_int16_t set_length; /* total length of the set, + in octets, including the set header */ +} __packed; + +#define PFLOW_SET_HDRLEN sizeof(struct pflow_set_header) + +struct pflow_tmpl_hdr { + u_int16_t tmpl_id; + u_int16_t field_count; +} __packed; + +struct pflow_tmpl_fspec { + u_int16_t field_id; + u_int16_t len; +} __packed; + +/* update pflow_clone_create() when changing pflow_ipfix_tmpl_ipv4 */ +struct pflow_ipfix_tmpl_ipv4 { + struct pflow_tmpl_hdr h; + struct pflow_tmpl_fspec src_ip; + struct pflow_tmpl_fspec dest_ip; + struct pflow_tmpl_fspec if_index_in; + struct pflow_tmpl_fspec if_index_out; + struct pflow_tmpl_fspec packets; + struct pflow_tmpl_fspec octets; + struct pflow_tmpl_fspec start; + struct pflow_tmpl_fspec finish; + struct pflow_tmpl_fspec src_port; + struct pflow_tmpl_fspec dest_port; + struct pflow_tmpl_fspec tos; + struct pflow_tmpl_fspec protocol; +#define PFLOW_IPFIX_TMPL_IPV4_FIELD_COUNT 12 +#define PFLOW_IPFIX_TMPL_IPV4_ID 256 +} __packed; + +/* update pflow_clone_create() when changing pflow_ipfix_tmpl_v6 */ +struct pflow_ipfix_tmpl_ipv6 { + struct pflow_tmpl_hdr h; + struct pflow_tmpl_fspec src_ip; + struct pflow_tmpl_fspec dest_ip; + struct pflow_tmpl_fspec if_index_in; + struct pflow_tmpl_fspec if_index_out; + struct pflow_tmpl_fspec packets; + struct pflow_tmpl_fspec octets; + struct pflow_tmpl_fspec start; + struct pflow_tmpl_fspec finish; + struct pflow_tmpl_fspec src_port; + struct pflow_tmpl_fspec dest_port; + struct pflow_tmpl_fspec tos; + struct pflow_tmpl_fspec protocol; +#define PFLOW_IPFIX_TMPL_IPV6_FIELD_COUNT 12 +#define PFLOW_IPFIX_TMPL_IPV6_ID 257 +} __packed; + +struct pflow_ipfix_tmpl_nat44 { + struct pflow_tmpl_hdr h; + struct pflow_tmpl_fspec timestamp; + struct pflow_tmpl_fspec nat_event; + struct pflow_tmpl_fspec protocol; + struct pflow_tmpl_fspec src_ip; + struct pflow_tmpl_fspec src_port; + struct pflow_tmpl_fspec postnat_src_ip; + struct pflow_tmpl_fspec postnat_src_port; + struct pflow_tmpl_fspec dst_ip; + struct pflow_tmpl_fspec dst_port; + struct pflow_tmpl_fspec postnat_dst_ip; + struct pflow_tmpl_fspec postnat_dst_port; +#define PFLOW_IPFIX_TMPL_NAT44_FIELD_COUNT 11 +#define PFLOW_IPFIX_TMPL_NAT44_ID 258 +}; + +struct pflow_ipfix_tmpl { + struct pflow_set_header set_header; + struct pflow_ipfix_tmpl_ipv4 ipv4_tmpl; + struct pflow_ipfix_tmpl_ipv6 ipv6_tmpl; + struct pflow_ipfix_tmpl_nat44 nat44_tmpl; +} __packed; + +struct pflow_ipfix_flow4 { + u_int32_t src_ip; /* sourceIPv4Address*/ + u_int32_t dest_ip; /* destinationIPv4Address */ + u_int32_t if_index_in; /* ingressInterface */ + u_int32_t if_index_out; /* egressInterface */ + u_int64_t flow_packets; /* packetDeltaCount */ + u_int64_t flow_octets; /* octetDeltaCount */ + int64_t flow_start; /* flowStartMilliseconds */ + int64_t flow_finish; /* flowEndMilliseconds */ + u_int16_t src_port; /* sourceTransportPort */ + u_int16_t dest_port; /* destinationTransportPort */ + u_int8_t tos; /* ipClassOfService */ + u_int8_t protocol; /* protocolIdentifier */ + /* XXX padding needed? */ +} __packed; + +struct pflow_ipfix_flow6 { + struct in6_addr src_ip; /* sourceIPv6Address */ + struct in6_addr dest_ip; /* destinationIPv6Address */ + u_int32_t if_index_in; /* ingressInterface */ + u_int32_t if_index_out; /* egressInterface */ + u_int64_t flow_packets; /* packetDeltaCount */ + u_int64_t flow_octets; /* octetDeltaCount */ + int64_t flow_start; /* flowStartMilliseconds */ + int64_t flow_finish; /* flowEndMilliseconds */ + u_int16_t src_port; /* sourceTransportPort */ + u_int16_t dest_port; /* destinationTransportPort */ + u_int8_t tos; /* ipClassOfService */ + u_int8_t protocol; /* protocolIdentifier */ + /* XXX padding needed? */ +} __packed; + +struct pflow_ipfix_nat4 { + u_int64_t timestamp; /* timeStamp */ + u_int8_t nat_event; /* natEvent */ + u_int8_t protocol; /* protocolIdentifier */ + u_int32_t src_ip; /* sourceIPv4Address */ + u_int16_t src_port; /* sourceTransportPort */ + u_int32_t postnat_src_ip; /* postNATSourceIPv4Address */ + u_int16_t postnat_src_port;/* postNAPTSourceTransportPort */ + u_int32_t dest_ip; /* destinationIPv4Address */ + u_int16_t dest_port; /* destinationTransportPort */ + u_int32_t postnat_dest_ip;/* postNATDestinationIPv4Address */ + u_int16_t postnat_dest_port;/* postNAPTDestinationTransportPort */ +} __packed; + +#ifdef _KERNEL + +struct pflow_softc { + int sc_id; + + struct mtx sc_lock; + + int sc_dying; /* [N] */ + struct vnet *sc_vnet; + + unsigned int sc_count; + unsigned int sc_count4; + unsigned int sc_count6; + unsigned int sc_count_nat4; + unsigned int sc_maxcount; + unsigned int sc_maxcount4; + unsigned int sc_maxcount6; + unsigned int sc_maxcount_nat4; + u_int32_t sc_gcounter; + u_int32_t sc_sequence; + struct callout sc_tmo; + struct callout sc_tmo6; + struct callout sc_tmo_nat4; + struct callout sc_tmo_tmpl; + struct intr_event *sc_swi_ie; + void *sc_swi_cookie; + struct mbufq sc_outputqueue; + struct task sc_outputtask; + struct socket *so; /* [p] */ + struct sockaddr *sc_flowsrc; + struct sockaddr *sc_flowdst; + struct pflow_ipfix_tmpl sc_tmpl_ipfix; + u_int8_t sc_version; + u_int32_t sc_observation_dom; + struct mbuf *sc_mbuf; /* current cumulative mbuf */ + struct mbuf *sc_mbuf6; /* current cumulative mbuf */ + struct mbuf *sc_mbuf_nat4; + CK_LIST_ENTRY(pflow_softc) sc_next; + struct epoch_context sc_epoch_ctx; +}; + +#endif /* _KERNEL */ + +struct pflow_header { + u_int16_t version; + u_int16_t count; + u_int32_t uptime_ms; + u_int32_t time_sec; + u_int32_t time_nanosec; + u_int32_t flow_sequence; + u_int8_t engine_type; + u_int8_t engine_id; + u_int8_t reserved1; + u_int8_t reserved2; +} __packed; + +#define PFLOW_HDRLEN sizeof(struct pflow_header) + +struct pflow_v10_header { + u_int16_t version; + u_int16_t length; + u_int32_t time_sec; + u_int32_t flow_sequence; + u_int32_t observation_dom; +} __packed; + +#define PFLOW_IPFIX_HDRLEN sizeof(struct pflow_v10_header) + +struct pflowstats { + u_int64_t pflow_flows; + u_int64_t pflow_packets; + u_int64_t pflow_onomem; + u_int64_t pflow_oerrors; +}; + +/* Supported flow protocols */ +#define PFLOW_PROTO_5 5 /* original pflow */ +#define PFLOW_PROTO_10 10 /* ipfix */ +#define PFLOW_PROTO_MAX 11 + +#define PFLOW_PROTO_DEFAULT PFLOW_PROTO_5 + +struct pflow_protos { + const char *ppr_name; + u_int8_t ppr_proto; +}; + +#define PFLOW_PROTOS { \ + { "5", PFLOW_PROTO_5 }, \ + { "10", PFLOW_PROTO_10 }, \ +} + +#define PFLOWNL_FAMILY_NAME "pflow" + +enum { + PFLOWNL_CMD_UNSPEC = 0, + PFLOWNL_CMD_LIST = 1, + PFLOWNL_CMD_CREATE = 2, + PFLOWNL_CMD_DEL = 3, + PFLOWNL_CMD_SET = 4, + PFLOWNL_CMD_GET = 5, + __PFLOWNL_CMD_MAX, +}; +#define PFLOWNL_CMD_MAX (__PFLOWNL_CMD_MAX - 1) + +enum pflow_list_type_t { + PFLOWNL_L_UNSPEC, + PFLOWNL_L_ID = 1, /* u32 */ +}; + +enum pflow_create_type_t { + PFLOWNL_CREATE_UNSPEC, + PFLOWNL_CREATE_ID = 1, /* u32 */ +}; + +enum pflow_del_type_t { + PFLOWNL_DEL_UNSPEC, + PFLOWNL_DEL_ID = 1, /* u32 */ +}; + +enum pflow_addr_type_t { + PFLOWNL_ADDR_UNSPEC, + PFLOWNL_ADDR_FAMILY = 1, /* u8 */ + PFLOWNL_ADDR_PORT = 2, /* u16 */ + PFLOWNL_ADDR_IP = 3, /* struct in_addr */ + PFLOWNL_ADDR_IP6 = 4, /* struct in6_addr */ +}; + +enum pflow_get_type_t { + PFLOWNL_GET_UNSPEC, + PFLOWNL_GET_ID = 1, /* u32 */ + PFLOWNL_GET_VERSION = 2, /* u16 */ + PFLOWNL_GET_SRC = 3, /* struct sockaddr_storage */ + PFLOWNL_GET_DST = 4, /* struct sockaddr_storage */ + PFLOWNL_GET_OBSERVATION_DOMAIN = 5, /* u32 */ + PFLOWNL_GET_SOCKET_STATUS = 6, /* u8 */ +}; + +enum pflow_set_type_t { + PFLOWNL_SET_UNSPEC, + PFLOWNL_SET_ID = 1, /* u32 */ + PFLOWNL_SET_VERSION = 2, /* u16 */ + PFLOWNL_SET_SRC = 3, /* struct sockaddr_storage */ + PFLOWNL_SET_DST = 4, /* struct sockaddr_storage */ + PFLOWNL_SET_OBSERVATION_DOMAIN = 5, /* u32 */ +}; + +#ifdef _KERNEL +int pflow_sysctl(int *, u_int, void *, size_t *, void *, size_t); +#endif /* _KERNEL */ + +#endif /* _NET_IF_PFLOW_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/net/pfvar.h b/lib/libc/include/generic-freebsd/net/pfvar.h index 1e61aba2b574..c1b72d6ca2cf 100644 --- a/lib/libc/include/generic-freebsd/net/pfvar.h +++ b/lib/libc/include/generic-freebsd/net/pfvar.h @@ -70,6 +70,8 @@ #ifdef _KERNEL +#define PF_PFIL_NOREFRAGMENT 0x80000000 + #if defined(__arm__) #define PF_WANT_32_TO_64_COUNTER #endif @@ -127,6 +129,14 @@ pf_counter_u64_critical_exit(void) critical_exit(); } +static inline void +pf_counter_u64_rollup_protected(struct pf_counter_u64 *pfcu64, uint64_t n) +{ + + MPASS(curthread->td_critnest > 0); + pfcu64->pfcu64_value += n; +} + static inline void pf_counter_u64_add_protected(struct pf_counter_u64 *pfcu64, uint32_t n) { @@ -250,6 +260,13 @@ pf_counter_u64_critical_exit(void) } +static inline void +pf_counter_u64_rollup_protected(struct pf_counter_u64 *pfcu64, uint64_t n) +{ + + counter_u64_add(pfcu64->counter, n); +} + static inline void pf_counter_u64_add_protected(struct pf_counter_u64 *pfcu64, uint32_t n) { @@ -309,10 +326,20 @@ pf_counter_u64_zero(struct pf_counter_u64 *pfcu64) _Static_assert(sizeof(time_t) == 4 || sizeof(time_t) == 8, "unexpected time_t size"); SYSCTL_DECL(_net_pf); +MALLOC_DECLARE(M_PF); MALLOC_DECLARE(M_PFHASH); MALLOC_DECLARE(M_PF_RULE_ITEM); SDT_PROVIDER_DECLARE(pf); +SDT_PROBE_DECLARE(pf, , test, reason_set); +SDT_PROBE_DECLARE(pf, , log, log); + +#define DPFPRINTF(n, fmt, x...) \ + do { \ + SDT_PROBE2(pf, , log, log, (n), fmt); \ + if (V_pf_status.debug >= (n)) \ + printf(fmt "\n", ##x); \ + } while (0) struct pfi_dynaddr { TAILQ_ENTRY(pfi_dynaddr) entry; @@ -329,14 +356,6 @@ struct pfi_dynaddr { u_int8_t pfid_iflags; /* PFI_AFLAG_* */ }; -/* - * Address manipulation macros - */ -#define HTONL(x) (x) = htonl((__uint32_t)(x)) -#define HTONS(x) (x) = htons((__uint16_t)(x)) -#define NTOHL(x) (x) = ntohl((__uint32_t)(x)) -#define NTOHS(x) (x) = ntohs((__uint16_t)(x)) - #define PF_NAME "pf" #define PF_HASHROW_ASSERT(h) mtx_assert(&(h)->lock, MA_OWNED) @@ -433,6 +452,16 @@ VNET_DECLARE(struct rmlock, pf_rules_lock); #define PF_RULES_RASSERT() rm_assert(&V_pf_rules_lock, RA_RLOCKED) #define PF_RULES_WASSERT() rm_assert(&V_pf_rules_lock, RA_WLOCKED) +VNET_DECLARE(struct rmlock, pf_tags_lock); +#define V_pf_tags_lock VNET(pf_tags_lock) + +#define PF_TAGS_RLOCK_TRACKER struct rm_priotracker _pf_tags_tracker +#define PF_TAGS_RLOCK() rm_rlock(&V_pf_tags_lock, &_pf_tags_tracker) +#define PF_TAGS_RUNLOCK() rm_runlock(&V_pf_tags_lock, &_pf_tags_tracker) +#define PF_TAGS_WLOCK() rm_wlock(&V_pf_tags_lock) +#define PF_TAGS_WUNLOCK() rm_wunlock(&V_pf_tags_lock) +#define PF_TAGS_WASSERT() rm_assert(&V_pf_tags_lock, RA_WLOCKED) + extern struct mtx_padalign pf_table_stats_lock; #define PF_TABLE_STATS_LOCK() mtx_lock(&pf_table_stats_lock) #define PF_TABLE_STATS_UNLOCK() mtx_unlock(&pf_table_stats_lock) @@ -498,18 +527,6 @@ extern struct sx pf_end_lock; (c == AF_INET6 && !(a)->addr32[0] && !(a)->addr32[1] && \ !(a)->addr32[2] && !(a)->addr32[3] )) \ -#define PF_MATCHA(n, a, m, b, f) \ - pf_match_addr(n, a, m, b, f) - -#define PF_ACPY(a, b, f) \ - pf_addrcpy(a, b, f) - -#define PF_AINC(a, f) \ - pf_addr_inc(a, f) - -#define PF_POOLMASK(a, b, c, d, f) \ - pf_poolmask(a, b, c, d, f) - #else /* Just IPv6 */ @@ -534,18 +551,6 @@ extern struct sx pf_end_lock; !(a)->addr32[2] && \ !(a)->addr32[3] ) \ -#define PF_MATCHA(n, a, m, b, f) \ - pf_match_addr(n, a, m, b, f) - -#define PF_ACPY(a, b, f) \ - pf_addrcpy(a, b, f) - -#define PF_AINC(a, f) \ - pf_addr_inc(a, f) - -#define PF_POOLMASK(a, b, c, d, f) \ - pf_poolmask(a, b, c, d, f) - #else /* Just IPv4 */ @@ -560,27 +565,34 @@ extern struct sx pf_end_lock; #define PF_AZERO(a, c) \ (!(a)->addr32[0]) -#define PF_MATCHA(n, a, m, b, f) \ - pf_match_addr(n, a, m, b, f) - -#define PF_ACPY(a, b, f) \ - (a)->v4.s_addr = (b)->v4.s_addr - -#define PF_AINC(a, f) \ - do { \ - (a)->addr32[0] = htonl(ntohl((a)->addr32[0]) + 1); \ - } while (0) - -#define PF_POOLMASK(a, b, c, d, f) \ - do { \ - (a)->addr32[0] = ((b)->addr32[0] & (c)->addr32[0]) | \ - (((c)->addr32[0] ^ 0xffffffff ) & (d)->addr32[0]); \ - } while (0) - #endif /* PF_INET_ONLY */ #endif /* PF_INET6_ONLY */ #endif /* PF_INET_INET6 */ +#ifdef _KERNEL + +void unhandled_af(int) __dead2; + +static void inline +pf_addrcpy(struct pf_addr *dst, const struct pf_addr *src, sa_family_t af) +{ + switch (af) { +#ifdef INET + case AF_INET: + memcpy(&dst->v4, &src->v4, sizeof(dst->v4)); + break; +#endif /* INET */ +#ifdef INET6 + case AF_INET6: + memcpy(&dst->v6, &src->v6, sizeof(dst->v6)); + break; +#endif /* INET6 */ + default: + unhandled_af(af); + } +} +#endif + /* * XXX callers not FIB-aware in our version of pf yet. * OpenBSD fixed it later it seems, 2010/05/07 13:33:16 claudio. @@ -600,19 +612,35 @@ extern struct sx pf_end_lock; &(aw)->v.a.mask, (x), (af))) || \ ((aw)->type == PF_ADDR_ADDRMASK && \ !PF_AZERO(&(aw)->v.a.mask, (af)) && \ - !PF_MATCHA(0, &(aw)->v.a.addr, \ + !pf_match_addr(0, &(aw)->v.a.addr, \ &(aw)->v.a.mask, (x), (af))))) != \ (neg) \ ) #define PF_ALGNMNT(off) (((off) % 2) == 0) +/* + * At the moment there are no rules which have both NAT and RDR actions, + * apart from af-to rules, but those don't to source tracking for address + * translation. And the r->rdr pool is used for both NAT and RDR. + * So there is no PF_SN_RDR. + */ +enum pf_sn_types { PF_SN_LIMIT, PF_SN_NAT, PF_SN_ROUTE, PF_SN_MAX }; +typedef enum pf_sn_types pf_sn_types_t; +#define PF_SN_TYPE_NAMES { \ + "limit source-track", \ + "NAT/RDR sticky-address", \ + "route sticky-address", \ + NULL \ +} + #ifdef _KERNEL struct pf_kpooladdr { struct pf_addr_wrap addr; TAILQ_ENTRY(pf_kpooladdr) entries; char ifname[IFNAMSIZ]; + sa_family_t af; struct pfi_kkif *kif; }; @@ -628,20 +656,27 @@ struct pf_kpool { int tblidx; u_int16_t proxy_port[2]; u_int8_t opts; + sa_family_t ipv6_nexthop_af; }; struct pf_rule_actions { + struct pf_addr rt_addr; + struct pfi_kkif *rt_kif; int32_t rtableid; + uint32_t flags; uint16_t qid; uint16_t pqid; uint16_t max_mss; + uint16_t dnpipe; + uint16_t dnrpipe; /* Reverse direction pipe */ + sa_family_t rt_af; uint8_t log; uint8_t set_tos; uint8_t min_ttl; - uint16_t dnpipe; - uint16_t dnrpipe; /* Reverse direction pipe */ - uint32_t flags; uint8_t set_prio[2]; + uint8_t rt; + uint8_t allow_opts; + uint16_t max_pkt_size; }; union pf_keth_rule_ptr { @@ -667,7 +702,6 @@ struct pf_keth_ruleset { int open; uint32_t ticket; } active, inactive; - struct epoch_context epoch_ctx; struct vnet *vnet; struct pf_keth_anchor *anchor; }; @@ -746,9 +780,10 @@ struct pf_keth_rule { uint32_t ridentifier; }; -union pf_krule_ptr { - struct pf_krule *ptr; - u_int32_t nr; +struct pf_kthreshold { + uint32_t limit; + uint32_t seconds; + struct counter_rate *cr; }; RB_HEAD(pf_krule_global, pf_krule); @@ -757,10 +792,11 @@ RB_PROTOTYPE(pf_krule_global, pf_krule, entry_global, pf_krule_compare); struct pf_krule { struct pf_rule_addr src; struct pf_rule_addr dst; - union pf_krule_ptr skip[PF_SKIP_COUNT]; + struct pf_krule *skip[PF_SKIP_COUNT]; char label[PF_RULE_MAX_LABEL_COUNT][PF_RULE_LABEL_SIZE]; uint32_t ridentifier; char ifname[IFNAMSIZ]; + char rcv_ifname[IFNAMSIZ]; char qname[PF_QNAME_SIZE]; char pqname[PF_QNAME_SIZE]; char tagname[PF_TAG_NAME_SIZE]; @@ -769,7 +805,10 @@ struct pf_krule { char overload_tblname[PF_TABLE_NAME_SIZE]; TAILQ_ENTRY(pf_krule) entries; - struct pf_kpool rpool; + struct pf_kpool nat; + struct pf_kpool rdr; + struct pf_kpool route; + struct pf_kthreshold pktrate; struct pf_counter_u64 evaluations; struct pf_counter_u64 packets[2]; @@ -777,6 +816,7 @@ struct pf_krule { time_t *timestamp; struct pfi_kkif *kif; + struct pfi_kkif *rcv_kif; struct pf_kanchor *anchor; struct pfr_ktable *overload_tbl; @@ -792,6 +832,7 @@ struct pf_krule { u_int32_t limit; u_int32_t seconds; } max_src_conn_rate; + uint16_t max_pkt_size; u_int16_t qid; u_int16_t pqid; u_int16_t dnpipe; @@ -804,7 +845,7 @@ struct pf_krule { counter_u64_t states_cur; counter_u64_t states_tot; - counter_u64_t src_nodes; + counter_u64_t src_nodes[PF_SN_MAX]; u_int16_t return_icmp; u_int16_t return_icmp6; @@ -830,8 +871,8 @@ struct pf_krule { u_int8_t keep_state; sa_family_t af; u_int8_t proto; - u_int8_t type; - u_int8_t code; + uint16_t type; + uint16_t code; u_int8_t flags; u_int8_t flagset; u_int8_t min_ttl; @@ -846,6 +887,8 @@ struct pf_krule { u_int8_t flush; u_int8_t prio; u_int8_t set_prio[2]; + sa_family_t naf; + u_int8_t rcvifnot; struct { struct pf_addr addr; @@ -869,21 +912,23 @@ SLIST_HEAD(pf_krule_slist, pf_krule_item); struct pf_ksrc_node { LIST_ENTRY(pf_ksrc_node) entry; - struct pf_addr addr; - struct pf_addr raddr; + struct pf_addr addr; + struct pf_addr raddr; struct pf_krule_slist match_rules; - union pf_krule_ptr rule; - struct pfi_kkif *rkif; - counter_u64_t bytes[2]; - counter_u64_t packets[2]; - u_int32_t states; - u_int32_t conn; - struct pf_threshold conn_rate; - u_int32_t creation; - u_int32_t expire; - sa_family_t af; - u_int8_t ruletype; - struct mtx *lock; + struct pf_krule *rule; + struct pfi_kkif *rkif; + counter_u64_t bytes[2]; + counter_u64_t packets[2]; + u_int32_t states; + u_int32_t conn; + struct pf_kthreshold conn_rate; + u_int32_t creation; + u_int32_t expire; + sa_family_t af; + sa_family_t raf; + u_int8_t ruletype; + pf_sn_types_t type; + struct mtx *lock; }; #endif @@ -925,6 +970,29 @@ struct pf_state_peer { u_int8_t pad[1]; }; +/* Keep synced with struct pf_udp_endpoint. */ +struct pf_udp_endpoint_cmp { + struct pf_addr addr; + uint16_t port; + sa_family_t af; + uint8_t pad[1]; +}; + +struct pf_udp_endpoint { + struct pf_addr addr; + uint16_t port; + sa_family_t af; + uint8_t pad[1]; + + struct pf_udp_mapping *mapping; + LIST_ENTRY(pf_udp_endpoint) entry; +}; + +struct pf_udp_mapping { + struct pf_udp_endpoint endpoints[2]; + u_int refs; +}; + /* Keep synced with struct pf_state_key. */ struct pf_state_key_cmp { struct pf_addr addr[2]; @@ -945,6 +1013,11 @@ struct pf_state_key { TAILQ_HEAD(, pf_kstate) states[2]; }; +#define PF_REVERSED_KEY(state, family) \ + (((state)->key[PF_SK_WIRE]->af != (state)->key[PF_SK_STACK]->af) && \ + ((state)->key[PF_SK_WIRE]->af != (family)) && \ + ((state)->direction == PF_IN)) + /* Keep synced with struct pf_kstate. */ struct pf_state_cmp { u_int64_t id; @@ -959,7 +1032,7 @@ struct pf_state_scrub_export { #define PF_SCRUB_FLAG_VALID 0x01 uint8_t scrub_flag; uint32_t pfss_ts_mod; /* timestamp modulation */ -}; +} __packed; struct pf_state_key_export { struct pf_addr addr[2]; @@ -976,7 +1049,7 @@ struct pf_state_peer_export { uint8_t state; /* active state level */ uint8_t wscale; /* window scaling factor */ uint8_t dummy[6]; -}; +} __packed; _Static_assert(sizeof(struct pf_state_peer_export) == 32, "size incorrect"); struct pf_state_export { @@ -1040,7 +1113,7 @@ struct pf_kstate { u_int16_t state_flags; u_int8_t timeout; u_int8_t sync_state; /* PFSYNC_S_x */ - u_int8_t sync_updates; /* XXX */ + u_int8_t sync_updates; u_int refs; struct mtx *lock; TAILQ_ENTRY(pf_kstate) sync_list; @@ -1049,56 +1122,74 @@ struct pf_kstate { struct pf_state_peer src; struct pf_state_peer dst; struct pf_krule_slist match_rules; - union pf_krule_ptr rule; - union pf_krule_ptr anchor; - union pf_krule_ptr nat_rule; - struct pf_addr rt_addr; + struct pf_krule *rule; + struct pf_krule *anchor; + struct pf_krule *nat_rule; struct pf_state_key *key[2]; /* addresses stack and wire */ + struct pf_udp_mapping *udp_mapping; struct pfi_kkif *kif; struct pfi_kkif *orig_kif; /* The real kif, even if we're a floating state (i.e. if == V_pfi_all). */ - struct pfi_kkif *rt_kif; - struct pf_ksrc_node *src_node; - struct pf_ksrc_node *nat_src_node; + struct pf_ksrc_node *sns[PF_SN_MAX];/* source nodes */ u_int64_t packets[2]; u_int64_t bytes[2]; - u_int32_t creation; - u_int32_t expire; + u_int64_t creation; + u_int64_t expire; u_int32_t pfsync_time; struct pf_rule_actions act; u_int16_t tag; - u_int8_t rt; + u_int16_t if_index_in; + u_int16_t if_index_out; }; /* - * Size <= fits 11 objects per page on LP64. Try to not grow the struct beyond that. + * 6 cache lines per struct, 10 structs per page. + * Try to not grow the struct beyond that. */ -_Static_assert(sizeof(struct pf_kstate) <= 368, "pf_kstate size crosses 368 bytes"); +_Static_assert(sizeof(struct pf_kstate) <= 384, "pf_kstate size crosses 384 bytes"); + +enum pf_test_status { + PF_TEST_FAIL = -1, + PF_TEST_OK, + PF_TEST_QUICK +}; + +struct pf_test_ctx { + enum pf_test_status test_status; + struct pf_pdesc *pd; + struct pf_rule_actions act; + uint8_t icmpcode; + uint8_t icmptype; + int icmp_dir; + int state_icmp; + int tag; + int rewrite; + u_short reason; + struct pf_src_node *sns[PF_SN_MAX]; + struct pf_krule *nr; + struct pf_krule *tr; + struct pf_krule **rm; + struct pf_krule *a; + struct pf_krule **am; + struct pf_kruleset **rsm; + struct pf_kruleset *arsm; + struct pf_kruleset *aruleset; + struct pf_state_key *sk; + struct pf_state_key *nk; + struct tcphdr *th; + struct pf_udp_mapping *udp_mapping; + struct pf_kpool *nat_pool; + uint16_t virtual_type; + uint16_t virtual_id; + int depth; +}; + +#define PF_ANCHOR_STACK_MAX 32 #endif /* * Unified state structures for pulling states out of the kernel * used by pfsync(4) and the pf(4) ioctl. */ -struct pfsync_state_scrub { - u_int16_t pfss_flags; - u_int8_t pfss_ttl; /* stashed TTL */ -#define PFSYNC_SCRUB_FLAG_VALID 0x01 - u_int8_t scrub_flag; - u_int32_t pfss_ts_mod; /* timestamp modulation */ -} __packed; - -struct pfsync_state_peer { - struct pfsync_state_scrub scrub; /* state is scrubbed */ - u_int32_t seqlo; /* Max sequence number sent */ - u_int32_t seqhi; /* Max the other end ACKd + win */ - u_int32_t seqdiff; /* Sequence number modulator */ - u_int16_t max_win; /* largest window (pre scaling) */ - u_int16_t mss; /* Maximum segment size option */ - u_int8_t state; /* active state level */ - u_int8_t wscale; /* window scaling factor */ - u_int8_t pad[6]; -} __packed; - struct pfsync_state_key { struct pf_addr addr[2]; u_int16_t port[2]; @@ -1108,8 +1199,8 @@ struct pfsync_state_1301 { u_int64_t id; char ifname[IFNAMSIZ]; struct pfsync_state_key key[2]; - struct pfsync_state_peer src; - struct pfsync_state_peer dst; + struct pf_state_peer_export src; + struct pf_state_peer_export dst; struct pf_addr rt_addr; u_int32_t rule; u_int32_t anchor; @@ -1127,16 +1218,16 @@ struct pfsync_state_1301 { u_int8_t state_flags; u_int8_t timeout; u_int8_t sync_flags; - u_int8_t updates; + u_int8_t updates; /* unused */ } __packed; struct pfsync_state_1400 { - /* The beginning of the struct is compatible with previous versions */ + /* The beginning of the struct is compatible with pfsync_state_1301 */ u_int64_t id; char ifname[IFNAMSIZ]; struct pfsync_state_key key[2]; - struct pfsync_state_peer src; - struct pfsync_state_peer dst; + struct pf_state_peer_export src; + struct pf_state_peer_export dst; struct pf_addr rt_addr; u_int32_t rule; u_int32_t anchor; @@ -1154,7 +1245,7 @@ struct pfsync_state_1400 { u_int8_t __spare; u_int8_t timeout; u_int8_t sync_flags; - u_int8_t updates; + u_int8_t updates; /* unused */ /* The rest is not */ u_int16_t qid; u_int16_t pqid; @@ -1167,12 +1258,54 @@ struct pfsync_state_1400 { u_int8_t set_prio[2]; u_int8_t rt; char rt_ifname[IFNAMSIZ]; +} __packed; +struct pfsync_state_1500 { + /* The beginning of the struct is compatible with pfsync_state_1301 */ + u_int64_t id; + char ifname[IFNAMSIZ]; + struct pfsync_state_key key[2]; + struct pf_state_peer_export src; + struct pf_state_peer_export dst; + struct pf_addr rt_addr; + u_int32_t rule; + u_int32_t anchor; + u_int32_t nat_rule; + u_int32_t creation; + u_int32_t expire; + u_int32_t packets[2][2]; + u_int32_t bytes[2][2]; + u_int32_t creatorid; + /* The rest is not, use the opportunity to fix alignment */ + char tagname[PF_TAG_NAME_SIZE]; + char rt_ifname[IFNAMSIZ]; + char orig_ifname[IFNAMSIZ]; + int32_t rtableid; + u_int16_t state_flags; + u_int16_t qid; + u_int16_t pqid; + u_int16_t dnpipe; + u_int16_t dnrpipe; + u_int16_t max_mss; + sa_family_t wire_af; + sa_family_t stack_af; + sa_family_t rt_af; + u_int8_t wire_proto; + u_int8_t stack_proto; + u_int8_t log; + u_int8_t timeout; + u_int8_t direction; + u_int8_t rt; + u_int8_t min_ttl; + u_int8_t set_tos; + u_int8_t set_prio[2]; + u_int8_t spare[3]; /* Improve struct alignment */ } __packed; union pfsync_state_union { struct pfsync_state_1301 pfs_1301; struct pfsync_state_1400 pfs_1400; + struct pfsync_state_1500 pfs_1500; } __packed; #ifdef _KERNEL @@ -1184,6 +1317,8 @@ typedef void pfsync_delete_state_t(struct pf_kstate *); typedef void pfsync_clear_states_t(u_int32_t, const char *); typedef int pfsync_defer_t(struct pf_kstate *, struct mbuf *); typedef void pfsync_detach_ifnet_t(struct ifnet *); +typedef void pflow_export_state_t(const struct pf_kstate *); +typedef bool pf_addr_filter_func_t(const sa_family_t, const struct pf_addr *); VNET_DECLARE(pfsync_state_import_t *, pfsync_state_import_ptr); #define V_pfsync_state_import_ptr VNET(pfsync_state_import_ptr) @@ -1197,6 +1332,8 @@ VNET_DECLARE(pfsync_clear_states_t *, pfsync_clear_states_ptr); #define V_pfsync_clear_states_ptr VNET(pfsync_clear_states_ptr) VNET_DECLARE(pfsync_defer_t *, pfsync_defer_ptr); #define V_pfsync_defer_ptr VNET(pfsync_defer_ptr) +VNET_DECLARE(pflow_export_state_t *, pflow_export_state_ptr); +#define V_pflow_export_state_ptr VNET(pflow_export_state_ptr) extern pfsync_detach_ifnet_t *pfsync_detach_ifnet_ptr; void pfsync_state_export(union pfsync_state_union *, @@ -1207,9 +1344,9 @@ void pf_state_export(struct pf_state_export *, /* pflog */ struct pf_kruleset; struct pf_pdesc; -typedef int pflog_packet_t(struct pfi_kkif *, struct mbuf *, sa_family_t, - u_int8_t, struct pf_krule *, struct pf_krule *, struct pf_kruleset *, - struct pf_pdesc *, int); +typedef int pflog_packet_t(uint8_t, u_int8_t, + struct pf_krule *, struct pf_krule *, struct pf_kruleset *, + struct pf_pdesc *, int, struct pf_krule *); extern pflog_packet_t *pflog_packet_ptr; #endif /* _KERNEL */ @@ -1219,39 +1356,10 @@ extern pflog_packet_t *pflog_packet_ptr; /* for copies to/from network byte order */ /* ioctl interface also uses network byte order */ -#define pf_state_peer_hton(s,d) do { \ - (d)->seqlo = htonl((s)->seqlo); \ - (d)->seqhi = htonl((s)->seqhi); \ - (d)->seqdiff = htonl((s)->seqdiff); \ - (d)->max_win = htons((s)->max_win); \ - (d)->mss = htons((s)->mss); \ - (d)->state = (s)->state; \ - (d)->wscale = (s)->wscale; \ - if ((s)->scrub) { \ - (d)->scrub.pfss_flags = \ - htons((s)->scrub->pfss_flags & PFSS_TIMESTAMP); \ - (d)->scrub.pfss_ttl = (s)->scrub->pfss_ttl; \ - (d)->scrub.pfss_ts_mod = htonl((s)->scrub->pfss_ts_mod);\ - (d)->scrub.scrub_flag = PFSYNC_SCRUB_FLAG_VALID; \ - } \ -} while (0) - -#define pf_state_peer_ntoh(s,d) do { \ - (d)->seqlo = ntohl((s)->seqlo); \ - (d)->seqhi = ntohl((s)->seqhi); \ - (d)->seqdiff = ntohl((s)->seqdiff); \ - (d)->max_win = ntohs((s)->max_win); \ - (d)->mss = ntohs((s)->mss); \ - (d)->state = (s)->state; \ - (d)->wscale = (s)->wscale; \ - if ((s)->scrub.scrub_flag == PFSYNC_SCRUB_FLAG_VALID && \ - (d)->scrub != NULL) { \ - (d)->scrub->pfss_flags = \ - ntohs((s)->scrub.pfss_flags) & PFSS_TIMESTAMP; \ - (d)->scrub->pfss_ttl = (s)->scrub.pfss_ttl; \ - (d)->scrub->pfss_ts_mod = ntohl((s)->scrub.pfss_ts_mod);\ - } \ -} while (0) +void pf_state_peer_hton(const struct pf_state_peer *, + struct pf_state_peer_export *); +void pf_state_peer_ntoh(const struct pf_state_peer_export *, + struct pf_state_peer *); #define pf_state_counter_hton(s,d) do { \ d[0] = htonl((s>>32)&0xffffffff); \ @@ -1276,7 +1384,6 @@ struct pf_kruleset { struct pf_krulequeue queues[2]; struct { struct pf_krulequeue *ptr; - struct pf_krule **ptr_array; u_int32_t rcount; u_int32_t ticket; int open; @@ -1329,7 +1436,6 @@ RB_PROTOTYPE(pf_kanchor_node, pf_kanchor, entry_node, pf_kanchor_compare); PFR_TFLAG_REFDANCHOR | \ PFR_TFLAG_COUNTERS) -struct pf_kanchor_stackframe; struct pf_keth_anchor_stackframe; struct pfr_table { @@ -1366,7 +1472,7 @@ struct pfr_astats { struct pfr_addr pfras_a; u_int64_t pfras_packets[PFR_DIR_MAX][PFR_OP_ADDR_MAX]; u_int64_t pfras_bytes[PFR_DIR_MAX][PFR_OP_ADDR_MAX]; - long pfras_tzero; + time_t pfras_tzero; }; enum { PFR_REFCNT_RULE, PFR_REFCNT_ANCHOR, PFR_REFCNT_MAX }; @@ -1377,7 +1483,7 @@ struct pfr_tstats { u_int64_t pfrts_bytes[PFR_DIR_MAX][PFR_OP_TABLE_MAX]; u_int64_t pfrts_match; u_int64_t pfrts_nomatch; - long pfrts_tzero; + time_t pfrts_tzero; int pfrts_cnt; int pfrts_refcnt[PFR_REFCNT_MAX]; }; @@ -1439,7 +1545,7 @@ struct pfr_ktstats { struct pfr_kstate_counter pfrkts_bytes[PFR_DIR_MAX][PFR_OP_TABLE_MAX]; struct pfr_kstate_counter pfrkts_match; struct pfr_kstate_counter pfrkts_nomatch; - long pfrkts_tzero; + time_t pfrkts_tzero; int pfrkts_cnt; int pfrkts_refcnt[PFR_REFCNT_MAX]; }; @@ -1460,7 +1566,7 @@ union sockaddr_union { struct pfr_kcounters { counter_u64_t pfrkc_counters; - long pfrkc_tzero; + time_t pfrkc_tzero; }; #define pfr_kentry_counter(kc, dir, op, t) \ ((kc)->pfrkc_counters + \ @@ -1518,7 +1624,7 @@ struct pfi_kkif { #define pfik_list _pfik_glue._pfik_list struct pf_counter_u64 pfik_packets[2][2][2]; struct pf_counter_u64 pfik_bytes[2][2][2]; - u_int32_t pfik_tzero; + time_t pfik_tzero; u_int pfik_flags; struct ifnet *pfik_ifp; struct ifg_group *pfik_group; @@ -1532,6 +1638,7 @@ struct pfi_kkif { #define PFI_IFLAG_REFS 0x0001 /* has state references */ #define PFI_IFLAG_SKIP 0x0100 /* skip filtering on interface */ +#define PFI_IFLAG_ANY 0x0200 /* match any non-loopback interface */ #ifdef _KERNEL struct pf_sctp_multihome_job; @@ -1555,25 +1662,49 @@ struct pf_pdesc { char any[0]; } hdr; - struct pf_krule *nat_rule; /* nat/rdr rule applied to packet */ + struct pf_addr nsaddr; /* src address after NAT */ + struct pf_addr ndaddr; /* dst address after NAT */ + + struct pfi_kkif *kif; /* incomming interface */ + struct mbuf *m; + struct pf_addr *src; /* src address */ struct pf_addr *dst; /* dst address */ - u_int16_t *sport; - u_int16_t *dport; + struct pf_addr osrc; + struct pf_addr odst; + u_int16_t *pcksum; /* proto cksum */ + u_int16_t *sport; + u_int16_t *dport; + u_int16_t osport; + u_int16_t odport; + u_int16_t nsport; /* src port after NAT */ + u_int16_t ndport; /* dst port after NAT */ struct pf_mtag *pf_mtag; struct pf_rule_actions act; - u_int32_t p_len; /* total length of payload */ + u_int32_t off; /* protocol header offset */ + bool df; /* IPv4 Don't fragment flag. */ + u_int32_t hdrlen; /* protocol header length */ + u_int32_t p_len; /* total length of protocol payload */ + u_int32_t extoff; /* extentsion header offset */ + u_int32_t fragoff; /* fragment header offset */ + u_int32_t jumbolen; /* length from v6 jumbo header */ + u_int32_t badopts; /* v4 options or v6 routing headers */ +#define PF_OPT_OTHER 0x0001 +#define PF_OPT_JUMBO 0x0002 +#define PF_OPT_ROUTER_ALERT 0x0004 u_int16_t *ip_sum; - u_int16_t *proto_sum; u_int16_t flags; /* Let SCRUB trigger behavior in * state code. Easier than tags */ #define PFDESC_TCP_NORM 0x0001 /* TCP shall be statefully scrubbed */ -#define PFDESC_IP_REAS 0x0002 /* IP frags would've been reassembled */ + u_int16_t virtual_proto; +#define PF_VPROTO_FRAGMENT 256 sa_family_t af; + sa_family_t naf; u_int8_t proto; u_int8_t tos; + u_int8_t ttl; u_int8_t dir; /* direction */ u_int8_t sidx; /* key index for source */ u_int8_t didx; /* key index for destination */ @@ -1592,6 +1723,8 @@ struct pf_pdesc { #define PFDESC_SCTP_ADD_IP 0x1000 u_int16_t sctp_flags; u_int32_t sctp_initiate_tag; + u_int16_t sctp_dummy_sum; + struct pf_krule *related_rule; struct pf_sctp_multihome_jobs sctp_multihome_jobs; }; @@ -1601,7 +1734,6 @@ struct pf_sctp_multihome_job { struct pf_pdesc pd; struct pf_addr src; struct pf_addr dst; - struct mbuf *m; int op; }; @@ -1647,6 +1779,7 @@ struct pf_sctp_multihome_job { #define REASON_SET(a, x) \ do { \ + SDT_PROBE2(pf, , test, reason_set, x, __LINE__); \ if ((a) != NULL) \ *(a) = (x); \ if (x < PFRES_MAX) \ @@ -1697,6 +1830,13 @@ struct pf_divert { #define PFFRAG_FRENT_HIWAT 5000 /* Number of fragment entries */ #define PFR_KENTRY_HIWAT 200000 /* Number of table entries */ +struct pf_fragment_tag { + uint16_t ft_hdrlen; /* header length of reassembled pkt */ + uint16_t ft_extoff; /* last extension header offset or 0 */ + uint16_t ft_maxlen; /* maximum fragment payload length */ + uint32_t ft_id; /* fragment id */ +}; + /* * Limit the length of the fragment queue traversal. Remember * search entry points based on the fragment offset. @@ -1773,6 +1913,7 @@ struct pf_kstate_kill { char psk_label[PF_RULE_LABEL_SIZE]; u_int psk_killed; bool psk_kill_match; + bool psk_nat; }; #endif @@ -1944,29 +2085,25 @@ struct pfioc_iface { #define DIOCADDRULE _IOWR('D', 4, struct pfioc_rule) #define DIOCADDRULENV _IOWR('D', 4, struct pfioc_nv) #define DIOCGETRULES _IOWR('D', 6, struct pfioc_rule) -#define DIOCGETRULE _IOWR('D', 7, struct pfioc_rule) #define DIOCGETRULENV _IOWR('D', 7, struct pfioc_nv) -/* XXX cut 8 - 17 */ -#define DIOCCLRSTATES _IOWR('D', 18, struct pfioc_state_kill) #define DIOCCLRSTATESNV _IOWR('D', 18, struct pfioc_nv) #define DIOCGETSTATE _IOWR('D', 19, struct pfioc_state) #define DIOCGETSTATENV _IOWR('D', 19, struct pfioc_nv) #define DIOCSETSTATUSIF _IOWR('D', 20, struct pfioc_if) -#define DIOCGETSTATUS _IOWR('D', 21, struct pf_status) #define DIOCGETSTATUSNV _IOWR('D', 21, struct pfioc_nv) #define DIOCCLRSTATUS _IO ('D', 22) #define DIOCNATLOOK _IOWR('D', 23, struct pfioc_natlook) #define DIOCSETDEBUG _IOWR('D', 24, u_int32_t) +#ifdef COMPAT_FREEBSD14 #define DIOCGETSTATES _IOWR('D', 25, struct pfioc_states) +#endif #define DIOCCHANGERULE _IOWR('D', 26, struct pfioc_rule) -/* XXX cut 26 - 28 */ #define DIOCSETTIMEOUT _IOWR('D', 29, struct pfioc_tm) #define DIOCGETTIMEOUT _IOWR('D', 30, struct pfioc_tm) #define DIOCADDSTATE _IOWR('D', 37, struct pfioc_state) #define DIOCCLRRULECTRS _IO ('D', 38) #define DIOCGETLIMIT _IOWR('D', 39, struct pfioc_limit) #define DIOCSETLIMIT _IOWR('D', 40, struct pfioc_limit) -#define DIOCKILLSTATES _IOWR('D', 41, struct pfioc_state_kill) #define DIOCKILLSTATESNV _IOWR('D', 41, struct pfioc_nv) #define DIOCSTARTALTQ _IO ('D', 42) #define DIOCSTOPALTQ _IO ('D', 43) @@ -1985,7 +2122,6 @@ struct pfioc_iface { #define DIOCGETADDRS _IOWR('D', 53, struct pfioc_pooladdr) #define DIOCGETADDR _IOWR('D', 54, struct pfioc_pooladdr) #define DIOCCHANGEADDR _IOWR('D', 55, struct pfioc_pooladdr) -/* XXX cut 55 - 57 */ #define DIOCGETRULESETS _IOWR('D', 58, struct pfioc_ruleset) #define DIOCGETRULESET _IOWR('D', 59, struct pfioc_ruleset) #define DIOCRCLRTABLES _IOWR('D', 60, struct pfioc_table) @@ -2019,7 +2155,9 @@ struct pfioc_iface { #define DIOCKILLSRCNODES _IOWR('D', 91, struct pfioc_src_node_kill) #define DIOCGIFSPEEDV0 _IOWR('D', 92, struct pf_ifspeed_v0) #define DIOCGIFSPEEDV1 _IOWR('D', 92, struct pf_ifspeed_v1) +#ifdef COMPAT_FREEBSD14 #define DIOCGETSTATESV2 _IOWR('D', 93, struct pfioc_states_v2) +#endif #define DIOCGETSYNCOOKIES _IOWR('D', 94, struct pfioc_nv) #define DIOCSETSYNCOOKIES _IOWR('D', 95, struct pfioc_nv) #define DIOCKEEPCOUNTERS _IOWR('D', 96, struct pfioc_nv) @@ -2103,21 +2241,33 @@ struct pf_idhash { struct mtx lock; }; +struct pf_udpendpointhash { + LIST_HEAD(, pf_udp_endpoint) endpoints; + /* refcont is synchronized on the source endpoint's row lock */ + struct mtx lock; +}; + extern u_long pf_ioctl_maxcount; VNET_DECLARE(u_long, pf_hashmask); #define V_pf_hashmask VNET(pf_hashmask) VNET_DECLARE(u_long, pf_srchashmask); #define V_pf_srchashmask VNET(pf_srchashmask) +VNET_DECLARE(u_long, pf_udpendpointhashmask); +#define V_pf_udpendpointhashmask VNET(pf_udpendpointhashmask) #define PF_HASHSIZ (131072) #define PF_SRCHASHSIZ (PF_HASHSIZ/4) +#define PF_UDPENDHASHSIZ (PF_HASHSIZ/4) VNET_DECLARE(struct pf_keyhash *, pf_keyhash); VNET_DECLARE(struct pf_idhash *, pf_idhash); +VNET_DECLARE(struct pf_udpendpointhash *, pf_udpendpointhash); #define V_pf_keyhash VNET(pf_keyhash) #define V_pf_idhash VNET(pf_idhash) +#define V_pf_udpendpointhash VNET(pf_udpendpointhash) VNET_DECLARE(struct pf_srchash *, pf_srchash); #define V_pf_srchash VNET(pf_srchash) -#define PF_IDHASH(s) (be64toh((s)->id) % (V_pf_hashmask + 1)) +#define PF_IDHASHID(id) (be64toh(id) % (V_pf_hashmask + 1)) +#define PF_IDHASH(s) PF_IDHASHID((s)->id) VNET_DECLARE(void *, pf_swi_cookie); #define V_pf_swi_cookie VNET(pf_swi_cookie) @@ -2130,7 +2280,7 @@ VNET_DECLARE(struct unrhdr64, pf_stateid); TAILQ_HEAD(pf_altqqueue, pf_altq); VNET_DECLARE(struct pf_altqqueue, pf_altqs[4]); #define V_pf_altqs VNET(pf_altqs) -VNET_DECLARE(struct pf_kpalist, pf_pabuf); +VNET_DECLARE(struct pf_kpalist, pf_pabuf[3]); #define V_pf_pabuf VNET(pf_pabuf) VNET_DECLARE(u_int32_t, ticket_altqs_active); @@ -2171,6 +2321,8 @@ VNET_DECLARE(struct pf_krule *, pf_rulemarker); #define V_pf_rulemarker VNET(pf_rulemarker) #endif +int pf_start(void); +int pf_stop(void); void pf_initialize(void); void pf_mtag_initialize(void); void pf_mtag_cleanup(void); @@ -2186,15 +2338,21 @@ VNET_DECLARE(uma_zone_t, pf_state_z); #define V_pf_state_z VNET(pf_state_z) VNET_DECLARE(uma_zone_t, pf_state_key_z); #define V_pf_state_key_z VNET(pf_state_key_z) +VNET_DECLARE(uma_zone_t, pf_udp_mapping_z); +#define V_pf_udp_mapping_z VNET(pf_udp_mapping_z) VNET_DECLARE(uma_zone_t, pf_state_scrub_z); #define V_pf_state_scrub_z VNET(pf_state_scrub_z) +VNET_DECLARE(uma_zone_t, pf_anchor_z); +#define V_pf_anchor_z VNET(pf_anchor_z) +VNET_DECLARE(uma_zone_t, pf_eth_anchor_z); +#define V_pf_eth_anchor_z VNET(pf_eth_anchor_z) extern void pf_purge_thread(void *); extern void pf_unload_vnet_purge(void); extern void pf_intr(void *); extern void pf_purge_expired_src_nodes(void); -extern int pf_unlink_state(struct pf_kstate *); +extern int pf_remove_state(struct pf_kstate *); extern int pf_state_insert(struct pfi_kkif *, struct pfi_kkif *, struct pf_state_key *, @@ -2202,6 +2360,9 @@ extern int pf_state_insert(struct pfi_kkif *, struct pf_kstate *); extern struct pf_kstate *pf_alloc_state(int); extern void pf_free_state(struct pf_kstate *); +extern void pf_killstates(struct pf_kstate_kill *, + unsigned int *); +extern unsigned int pf_clear_states(const struct pf_kstate_kill *); static __inline void pf_ref_state(struct pf_kstate *s) @@ -2232,6 +2393,22 @@ pf_release_staten(struct pf_kstate *s, u_int n) return (0); } +static __inline uint64_t +pf_get_uptime(void) +{ + struct timeval t; + microuptime(&t); + return ((t.tv_sec * 1000) + (t.tv_usec / 1000)); +} + +static __inline uint64_t +pf_get_time(void) +{ + struct timeval t; + microtime(&t); + return ((t.tv_sec * 1000) + (t.tv_usec / 1000)); +} + extern struct pf_kstate *pf_find_state_byid(uint64_t, uint32_t); extern struct pf_kstate *pf_find_state_all( const struct pf_state_key_cmp *, @@ -2239,13 +2416,25 @@ extern struct pf_kstate *pf_find_state_all( extern bool pf_find_state_all_exists( const struct pf_state_key_cmp *, u_int); +extern struct pf_udp_mapping *pf_udp_mapping_find(struct pf_udp_endpoint_cmp + *endpoint); +extern struct pf_udp_mapping *pf_udp_mapping_create(sa_family_t af, + struct pf_addr *src_addr, uint16_t src_port, + struct pf_addr *nat_addr, uint16_t nat_port); +extern int pf_udp_mapping_insert(struct pf_udp_mapping + *mapping); +extern void pf_udp_mapping_release(struct pf_udp_mapping + *mapping); +uint32_t pf_hashsrc(struct pf_addr *, sa_family_t); +extern bool pf_src_node_exists(struct pf_ksrc_node **, + struct pf_srchash *); extern struct pf_ksrc_node *pf_find_src_node(struct pf_addr *, struct pf_krule *, sa_family_t, - struct pf_srchash **, bool); + struct pf_srchash **, pf_sn_types_t, bool); extern void pf_unlink_src_node(struct pf_ksrc_node *); extern u_int pf_free_src_nodes(struct pf_ksrc_node_list *); extern void pf_print_state(struct pf_kstate *); -extern void pf_print_flags(u_int8_t); +extern void pf_print_flags(uint16_t); extern int pf_addr_wrap_neq(struct pf_addr_wrap *, struct pf_addr_wrap *); extern u_int16_t pf_cksum_fixup(u_int16_t, u_int16_t, u_int16_t, @@ -2257,80 +2446,85 @@ VNET_DECLARE(struct ifnet *, sync_ifp); #define V_sync_ifp VNET(sync_ifp); VNET_DECLARE(struct pf_krule, pf_default_rule); #define V_pf_default_rule VNET(pf_default_rule) -extern void pf_addrcpy(struct pf_addr *, struct pf_addr *, +extern void pf_addrcpy(struct pf_addr *, const struct pf_addr *, sa_family_t); void pf_free_rule(struct pf_krule *); int pf_test_eth(int, int, struct ifnet *, struct mbuf **, struct inpcb *); -#ifdef INET -int pf_test(int, int, struct ifnet *, struct mbuf **, struct inpcb *, +int pf_scan_sctp(struct pf_pdesc *); +#if defined(INET) || defined(INET6) +int pf_test(sa_family_t, int, int, struct ifnet *, struct mbuf **, struct inpcb *, struct pf_rule_actions *); -int pf_normalize_ip(struct mbuf **, struct pfi_kkif *, u_short *, - struct pf_pdesc *); +#endif +#ifdef INET +int pf_normalize_ip(u_short *, struct pf_pdesc *); #endif /* INET */ -#ifdef INET6 -int pf_test6(int, int, struct ifnet *, struct mbuf **, struct inpcb *, - struct pf_rule_actions *); -int pf_normalize_ip6(struct mbuf **, struct pfi_kkif *, u_short *, - struct pf_pdesc *); 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_refragment6(struct ifnet *, struct mbuf **, struct m_tag *, bool); +#ifdef INET6 +int pf_normalize_ip6(int, u_short *, struct pf_pdesc *); +int pf_max_frag_size(struct mbuf *); +int pf_refragment6(struct ifnet *, struct mbuf **, struct m_tag *, + struct ifnet *, bool); #endif /* INET6 */ -int pf_multihome_scan_init(struct mbuf *, int, int, struct pf_pdesc *, - struct pfi_kkif *); -int pf_multihome_scan_asconf(struct mbuf *, int, int, struct pf_pdesc *, - struct pfi_kkif *); +int pf_multihome_scan_init(int, int, struct pf_pdesc *); +int pf_multihome_scan_asconf(int, int, struct pf_pdesc *); u_int32_t pf_new_isn(struct pf_kstate *); -void *pf_pull_hdr(struct mbuf *, int, void *, int, u_short *, u_short *, +void *pf_pull_hdr(const struct mbuf *, int, void *, int, u_short *, u_short *, sa_family_t); void pf_change_a(void *, u_int16_t *, u_int32_t, u_int8_t); void pf_change_proto_a(struct mbuf *, void *, u_int16_t *, u_int32_t, u_int8_t); void pf_change_tcp_a(struct mbuf *, void *, u_int16_t *, u_int32_t); -void pf_patch_16_unaligned(struct mbuf *, u_int16_t *, void *, u_int16_t, - bool, u_int8_t); -void pf_patch_32_unaligned(struct mbuf *, u_int16_t *, void *, u_int32_t, - bool, u_int8_t); +int pf_patch_16(struct pf_pdesc *, void *, u_int16_t, bool); +int pf_patch_32(struct pf_pdesc *, void *, u_int32_t, bool); void pf_send_deferred_syn(struct pf_kstate *); -int pf_match_addr(u_int8_t, struct pf_addr *, struct pf_addr *, - struct pf_addr *, sa_family_t); -int pf_match_addr_range(struct pf_addr *, struct pf_addr *, - struct pf_addr *, sa_family_t); +int pf_match_addr(u_int8_t, const struct pf_addr *, + const struct pf_addr *, const struct pf_addr *, sa_family_t); +int pf_match_addr_range(const struct pf_addr *, const struct pf_addr *, + const struct pf_addr *, sa_family_t); int pf_match_port(u_int8_t, u_int16_t, u_int16_t, u_int16_t); void pf_normalize_init(void); void pf_normalize_cleanup(void); -int pf_normalize_tcp(struct pfi_kkif *, struct mbuf *, int, int, void *, - struct pf_pdesc *); +int pf_normalize_tcp(struct pf_pdesc *); void pf_normalize_tcp_cleanup(struct pf_kstate *); -int pf_normalize_tcp_init(struct mbuf *, int, struct pf_pdesc *, - struct tcphdr *, struct pf_state_peer *, struct pf_state_peer *); -int pf_normalize_tcp_stateful(struct mbuf *, int, struct pf_pdesc *, +int pf_normalize_tcp_init(struct pf_pdesc *, + struct tcphdr *, struct pf_state_peer *); +int pf_normalize_tcp_stateful(struct pf_pdesc *, u_short *, struct tcphdr *, struct pf_kstate *, struct pf_state_peer *, struct pf_state_peer *, int *); -int pf_normalize_sctp_init(struct mbuf *, int, struct pf_pdesc *, +int pf_normalize_sctp_init(struct pf_pdesc *, struct pf_state_peer *, struct pf_state_peer *); -int pf_normalize_sctp(int, struct pfi_kkif *, struct mbuf *, int, - int, void *, struct pf_pdesc *); +int pf_normalize_sctp(struct pf_pdesc *); u_int32_t pf_state_expires(const struct pf_kstate *); void pf_purge_expired_fragments(void); void pf_purge_fragments(uint32_t); int pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kkif *, int); -int pf_socket_lookup(struct pf_pdesc *, struct mbuf *); +int pf_socket_lookup(struct pf_pdesc *); struct pf_state_key *pf_alloc_state_key(int); +int pf_translate(struct pf_pdesc *, struct pf_addr *, u_int16_t, + struct pf_addr *, u_int16_t, u_int16_t, int); +int pf_translate_af(struct pf_pdesc *); +bool pf_init_threshold(struct pf_kthreshold *, uint32_t, uint32_t); +uint16_t pf_tagname2tag(const char *); +#ifdef ALTQ +uint16_t pf_qname2qid(const char *, bool); +#endif /* ALTQ */ + void pfr_initialize(void); void pfr_cleanup(void); int pfr_match_addr(struct pfr_ktable *, struct pf_addr *, sa_family_t); void pfr_update_stats(struct pfr_ktable *, struct pf_addr *, sa_family_t, u_int64_t, int, int, int); -int pfr_pool_get(struct pfr_ktable *, int *, struct pf_addr *, sa_family_t); +int pfr_pool_get(struct pfr_ktable *, int *, struct pf_addr *, sa_family_t, + pf_addr_filter_func_t, bool); void pfr_dynaddr_update(struct pfr_ktable *, struct pfi_dynaddr *); struct pfr_ktable * pfr_attach_table(struct pf_kruleset *, char *); @@ -2346,7 +2540,7 @@ int pfr_get_tstats(struct pfr_table *, struct pfr_tstats *, int *, int); int pfr_clr_tstats(struct pfr_table *, int, int *, int); int pfr_set_tflags(struct pfr_table *, int, int, int, int *, int *, int); int pfr_clr_addrs(struct pfr_table *, int *, int); -int pfr_insert_kentry(struct pfr_ktable *, struct pfr_addr *, long); +int pfr_insert_kentry(struct pfr_ktable *, struct pfr_addr *, time_t); int pfr_add_addrs(struct pfr_table *, struct pfr_addr *, int, int *, int); int pfr_del_addrs(struct pfr_table *, struct pfr_addr *, int, int *, @@ -2364,6 +2558,8 @@ int pfr_ina_rollback(struct pfr_table *, u_int32_t, int *, int); int pfr_ina_commit(struct pfr_table *, u_int32_t, int *, int *, int); int pfr_ina_define(struct pfr_table *, struct pfr_addr *, int, int *, int *, u_int32_t, int); +struct pfr_ktable + *pfr_ktable_select_active(struct pfr_ktable *); MALLOC_DECLARE(PFI_MTYPE); VNET_DECLARE(struct pfi_kkif *, pfi_all); @@ -2390,21 +2586,23 @@ int pfi_set_flags(const char *, int); int pfi_clear_flags(const char *, int); int pf_match_tag(struct mbuf *, struct pf_krule *, int *, int); -int pf_tag_packet(struct mbuf *, struct pf_pdesc *, int); +int pf_tag_packet(struct pf_pdesc *, int); int pf_addr_cmp(struct pf_addr *, struct pf_addr *, sa_family_t); -u_int16_t pf_get_mss(struct mbuf *, int, u_int16_t, sa_family_t); -u_int8_t pf_get_wscale(struct mbuf *, int, u_int16_t, sa_family_t); +uint8_t* pf_find_tcpopt(u_int8_t *, u_int8_t *, size_t, + u_int8_t, u_int8_t); +u_int16_t pf_get_mss(struct pf_pdesc *); +u_int8_t pf_get_wscale(struct pf_pdesc *); struct mbuf *pf_build_tcp(const struct pf_krule *, sa_family_t, const struct pf_addr *, const struct pf_addr *, u_int16_t, u_int16_t, u_int32_t, u_int32_t, - u_int8_t, u_int16_t, u_int16_t, u_int8_t, bool, - u_int16_t, u_int16_t, int); + u_int8_t, u_int16_t, u_int16_t, u_int8_t, int, + u_int16_t, u_int16_t, u_int, int); void pf_send_tcp(const struct pf_krule *, sa_family_t, const struct pf_addr *, const struct pf_addr *, u_int16_t, u_int16_t, u_int32_t, u_int32_t, - u_int8_t, u_int16_t, u_int16_t, u_int8_t, bool, + u_int8_t, u_int16_t, u_int16_t, u_int8_t, int, u_int16_t, u_int16_t, int); void pf_syncookies_init(void); @@ -2412,12 +2610,10 @@ void pf_syncookies_cleanup(void); int pf_get_syncookies(struct pfioc_nv *); int pf_set_syncookies(struct pfioc_nv *); int pf_synflood_check(struct pf_pdesc *); -void pf_syncookie_send(struct mbuf *m, int off, - struct pf_pdesc *); +void pf_syncookie_send(struct pf_pdesc *); bool pf_syncookie_check(struct pf_pdesc *); u_int8_t pf_syncookie_validate(struct pf_pdesc *); -struct mbuf * pf_syncookie_recreate_syn(uint8_t, int, - struct pf_pdesc *); +struct mbuf * pf_syncookie_recreate_syn(struct pf_pdesc *); VNET_DECLARE(struct pf_kstatus, pf_status); #define V_pf_status VNET(pf_status) @@ -2432,6 +2628,20 @@ VNET_DECLARE(struct pf_limit, pf_limits[PF_LIMIT_MAX]); #endif /* _KERNEL */ #ifdef _KERNEL +struct pf_nl_pooladdr { + u_int32_t action; + u_int32_t ticket; + u_int32_t nr; + u_int32_t r_num; + u_int8_t r_action; + u_int8_t r_last; + u_int8_t af; + char anchor[MAXPATHLEN]; + struct pf_pooladdr addr; + /* Above this is identical to pfioc_pooladdr */ + int which; +}; + VNET_DECLARE(struct pf_kanchor_global, pf_anchors); #define V_pf_anchors VNET(pf_anchors) VNET_DECLARE(struct pf_kanchor, pf_main_anchor); @@ -2449,15 +2659,17 @@ void pf_init_kruleset(struct pf_kruleset *); void pf_init_keth(struct pf_keth_ruleset *); int pf_kanchor_setup(struct pf_krule *, const struct pf_kruleset *, const char *); +int pf_kanchor_copyout(const struct pf_kruleset *, + const struct pf_krule *, char *, size_t); int pf_kanchor_nvcopyout(const struct pf_kruleset *, const struct pf_krule *, nvlist_t *); -int pf_kanchor_copyout(const struct pf_kruleset *, - const struct pf_krule *, struct pfioc_rule *); -void pf_kanchor_remove(struct pf_krule *); +void pf_remove_kanchor(struct pf_krule *); void pf_remove_if_empty_kruleset(struct pf_kruleset *); struct pf_kruleset *pf_find_kruleset(const char *); +struct pf_kruleset *pf_get_leaf_kruleset(char *, char **); struct pf_kruleset *pf_find_or_create_kruleset(const char *); void pf_rs_initialize(void); +void pf_rule_tree_free(struct pf_krule_global *); struct pf_krule *pf_krule_alloc(void); @@ -2474,15 +2686,33 @@ int pf_keth_anchor_nvcopyout( struct pf_keth_ruleset *pf_find_or_create_keth_ruleset(const char *); void pf_keth_anchor_remove(struct pf_keth_rule *); +int pf_ioctl_getrules(struct pfioc_rule *); +int pf_ioctl_addrule(struct pf_krule *, uint32_t, + uint32_t, const char *, const char *, uid_t uid, + pid_t); +void pf_ioctl_clear_status(void); +int pf_ioctl_get_timeout(int, int *); +int pf_ioctl_set_timeout(int, int, int *); +int pf_ioctl_get_limit(int, unsigned int *); +int pf_ioctl_set_limit(int, unsigned int, unsigned int *); +int pf_ioctl_begin_addrs(uint32_t *); +int pf_ioctl_add_addr(struct pf_nl_pooladdr *); +int pf_ioctl_get_addrs(struct pf_nl_pooladdr *); +int pf_ioctl_get_addr(struct pf_nl_pooladdr *); +int pf_ioctl_get_rulesets(struct pfioc_ruleset *); +int pf_ioctl_get_ruleset(struct pfioc_ruleset *); +int pf_ioctl_natlook(struct pfioc_natlook *); + void pf_krule_free(struct pf_krule *); +void pf_krule_clear_counters(struct pf_krule *); +void pf_addr_copyout(struct pf_addr_wrap *); #endif /* The fingerprint functions can be linked into userland programs (tcpdump) */ int pf_osfp_add(struct pf_osfp_ioctl *); #ifdef _KERNEL struct pf_osfp_enlist * - pf_osfp_fingerprint(struct pf_pdesc *, struct mbuf *, int, - const struct tcphdr *); + pf_osfp_fingerprint(struct pf_pdesc *, const struct tcphdr *); #endif /* _KERNEL */ void pf_osfp_flush(void); int pf_osfp_get(struct pf_osfp_ioctl *); @@ -2491,12 +2721,10 @@ int pf_osfp_match(struct pf_osfp_enlist *, pf_osfp_t); #ifdef _KERNEL void pf_print_host(struct pf_addr *, u_int16_t, sa_family_t); -void pf_step_into_anchor(struct pf_kanchor_stackframe *, int *, - struct pf_kruleset **, int, struct pf_krule **, - struct pf_krule **, int *); -int pf_step_out_of_anchor(struct pf_kanchor_stackframe *, int *, - struct pf_kruleset **, int, struct pf_krule **, - struct pf_krule **, int *); +enum pf_test_status pf_step_into_anchor(struct pf_test_ctx *, struct pf_krule *, + struct pf_krule_slist *match_rules); +enum pf_test_status pf_match_rule(struct pf_test_ctx *, struct pf_kruleset *, + struct pf_krule_slist *); void pf_step_into_keth_anchor(struct pf_keth_anchor_stackframe *, int *, struct pf_keth_ruleset **, struct pf_keth_rule **, struct pf_keth_rule **, @@ -2506,33 +2734,48 @@ int pf_step_out_of_keth_anchor(struct pf_keth_anchor_stackframe *, struct pf_keth_rule **, struct pf_keth_rule **, int *); -u_short pf_map_addr(u_int8_t, struct pf_krule *, +u_short pf_map_addr(sa_family_t, struct pf_krule *, struct pf_addr *, struct pf_addr *, - struct pfi_kkif **nkif, struct pf_addr *, - struct pf_ksrc_node **); -struct pf_krule *pf_get_translation(struct pf_pdesc *, struct mbuf *, - int, struct pfi_kkif *, struct pf_ksrc_node **, - struct pf_state_key **, struct pf_state_key **, + struct pfi_kkif **nkif, sa_family_t *, + struct pf_addr *, struct pf_kpool *); +u_short pf_map_addr_sn(u_int8_t, struct pf_krule *, struct pf_addr *, struct pf_addr *, - uint16_t, uint16_t, struct pf_kanchor_stackframe *); - -struct pf_state_key *pf_state_key_setup(struct pf_pdesc *, struct mbuf *, int, - struct pf_addr *, struct pf_addr *, u_int16_t, u_int16_t); + sa_family_t *, struct pfi_kkif **, + struct pf_addr *, struct pf_kpool *, + pf_sn_types_t); +int pf_get_transaddr_af(struct pf_krule *, + struct pf_pdesc *); +u_short pf_get_translation(struct pf_test_ctx *); +u_short pf_get_transaddr(struct pf_test_ctx *, + struct pf_krule *, + u_int8_t, struct pf_kpool *); +int pf_translate_compat(struct pf_test_ctx *); + +int pf_state_key_setup(struct pf_pdesc *, + u_int16_t, u_int16_t, + struct pf_state_key **sk, struct pf_state_key **nk); struct pf_state_key *pf_state_key_clone(const struct pf_state_key *); void pf_rule_to_actions(struct pf_krule *, struct pf_rule_actions *); -int pf_normalize_mss(struct mbuf *m, int off, - struct pf_pdesc *pd); -#ifdef INET -void pf_scrub_ip(struct mbuf **, struct pf_pdesc *); -#endif /* INET */ -#ifdef INET6 -void pf_scrub_ip6(struct mbuf **, struct pf_pdesc *); -#endif /* INET6 */ +int pf_normalize_mss(struct pf_pdesc *pd); +#if defined(INET) || defined(INET6) +void pf_scrub(struct pf_pdesc *); +#endif struct pfi_kkif *pf_kkif_create(int); void pf_kkif_free(struct pfi_kkif *); void pf_kkif_zero(struct pfi_kkif *); + + +/* NAT64 functions. */ +int inet_nat64(int, const void *, void *, const void *, u_int8_t); +int inet_nat64_inet(const void *, void *, const void *, u_int8_t); +int inet_nat64_inet6(const void *, void *, const void *, u_int8_t); + +int inet_nat46(int, const void *, void *, const void *, u_int8_t); +int inet_nat46_inet(const void *, void *, const void *, u_int8_t); +int inet_nat46_inet6(const void *, void *, const void *, u_int8_t); + #endif /* _KERNEL */ #endif /* _NET_PFVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/net/radix.h b/lib/libc/include/generic-freebsd/net/radix.h index 9ba671a9684a..09b7a8be8143 100644 --- a/lib/libc/include/generic-freebsd/net/radix.h +++ b/lib/libc/include/generic-freebsd/net/radix.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)radix.h 8.2 (Berkeley) 10/31/94 */ #ifndef _RADIX_H_ diff --git a/lib/libc/include/generic-freebsd/net/rndis.h b/lib/libc/include/generic-freebsd/net/rndis.h index d2883342f4b4..2e437069f24c 100644 --- a/lib/libc/include/generic-freebsd/net/rndis.h +++ b/lib/libc/include/generic-freebsd/net/rndis.h @@ -339,7 +339,7 @@ struct rndis_diag_info { uint32_t rm_erroffset; }; -/* Keepalive messsage. May be sent by device. */ +/* Keepalive message. May be sent by device. */ #define REMOTE_NDIS_KEEPALIVE_MSG 0x00000008 #define REMOTE_NDIS_KEEPALIVE_CMPLT 0x80000008 diff --git a/lib/libc/include/generic-freebsd/net/route.h b/lib/libc/include/generic-freebsd/net/route.h index 1f82a835a572..284e5dabf887 100644 --- a/lib/libc/include/generic-freebsd/net/route.h +++ b/lib/libc/include/generic-freebsd/net/route.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)route.h 8.4 (Berkeley) 1/9/95 */ #ifndef _NET_ROUTE_H_ @@ -241,6 +239,7 @@ struct rtstat { uint64_t rts_add_retry; /* # of route addition retries */ uint64_t rts_del_failure; /* # of route deletion failure */ uint64_t rts_del_retry; /* # of route deletion retries */ + uint64_t rts_spare[5]; }; /* @@ -296,6 +295,7 @@ struct rt_msghdr { #define RTM_DELMADDR 0x10 /* (4) mcast group membership being deleted */ #define RTM_IFANNOUNCE 0x11 /* (5) iface arrival/departure */ #define RTM_IEEE80211 0x12 /* (5) IEEE80211 wireless event */ +#define RTM_IPFWLOG 0x13 /* (1) IPFW rule match log event */ #endif /* NETLINK_COMPAT*/ diff --git a/lib/libc/include/generic-freebsd/net/route/route_ctl.h b/lib/libc/include/generic-freebsd/net/route/route_ctl.h index befc51d099c5..1225444541f2 100644 --- a/lib/libc/include/generic-freebsd/net/route/route_ctl.h +++ b/lib/libc/include/generic-freebsd/net/route/route_ctl.h @@ -61,11 +61,11 @@ int rib_del_route_px_gw(uint32_t fibnum, struct sockaddr *dst, int plen, const struct sockaddr *gw, int op_flags, struct rib_cmd_info *rc); /* operation flags */ -#define RTM_F_CREATE 0x01 -#define RTM_F_EXCL 0x02 -#define RTM_F_REPLACE 0x04 -#define RTM_F_APPEND 0x08 -#define RTM_F_FORCE 0x10 +#define RTM_F_CREATE 0x01 /* Create object if not exists */ +#define RTM_F_EXCL 0x02 /* (Deprecated) Do not replace or append if exists */ +#define RTM_F_REPLACE 0x04 /* Replace if route (even multipath) if exists */ +#define RTM_F_APPEND 0x08 /* Append path to the route */ +#define RTM_F_FORCE 0x10 /* Bump operation priority to highest */ int rib_add_route(uint32_t fibnum, struct rt_addrinfo *info, struct rib_cmd_info *rc); diff --git a/lib/libc/include/generic-freebsd/net/route/route_debug.h b/lib/libc/include/generic-freebsd/net/route/route_debug.h index b0b8be53f5e1..e28543c2fd42 100644 --- a/lib/libc/include/generic-freebsd/net/route/route_debug.h +++ b/lib/libc/include/generic-freebsd/net/route/route_debug.h @@ -116,10 +116,11 @@ SYSCTL_DECL(_net_route_debug); * Example: [nhop_neigh] nhops_update_neigh: */ #define RT_LOG(_l, _fmt, ...) RT_LOG_##_l(_l, _fmt, ## __VA_ARGS__) -#define _RT_LOG(_l, _fmt, ...) if (_DEBUG_PASS_MSG(_l)) { \ - _output("[" DEBUG_PREFIX_NAME "] %s: " _fmt "\n", __func__, ##__VA_ARGS__); \ -} - +#define _RT_LOG(_l, _fmt, ...) do { \ + if (_DEBUG_PASS_MSG(_l)) \ + _output("[" DEBUG_PREFIX_NAME "] %s: " _fmt "\n", \ + __func__, ##__VA_ARGS__); \ +} while (0) /* * Wrapper logic to avoid compiling high levels of debugging messages for diff --git a/lib/libc/include/generic-freebsd/net/sff8472.h b/lib/libc/include/generic-freebsd/net/sff8472.h index ee61377ac1a7..6ffdba9d6660 100644 --- a/lib/libc/include/generic-freebsd/net/sff8472.h +++ b/lib/libc/include/generic-freebsd/net/sff8472.h @@ -26,6 +26,9 @@ * SUCH DAMAGE. */ +#ifndef _NET_SFF8472_H_ +#define _NET_SFF8472_H_ + /* * The following set of constants are from Document SFF-8472 * "Diagnostic Monitoring Interface for Optical Transceivers" revision @@ -415,6 +418,7 @@ enum { SFF_8024_ID_LAST = SFF_8024_ID_QSFP_CMIS }; +#if defined(_WANT_SFF_8024_ID) || defined(_WANT_SFF_8472_ID) static const char *sff_8024_id[SFF_8024_ID_LAST + 1] = { "Unknown", "GBIC", @@ -448,6 +452,7 @@ static const char *sff_8024_id[SFF_8024_ID_LAST + 1] = { "x8MiniLink", "QSFP+(CIMS)" }; +#endif /* Keep compatibility with old definitions */ #define SFF_8472_ID_UNKNOWN SFF_8024_ID_UNKNOWN @@ -523,4 +528,6 @@ static const char *sff_8024_id[SFF_8024_ID_LAST + 1] = { * yielding a total range of 0 to 6.5535 mW (~ -40 to +8.2 dBm). */ -#define SFF_8472_POWER_FACTOR 10000.0 \ No newline at end of file +#define SFF_8472_POWER_FACTOR 10000.0 + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/net/vnet.h b/lib/libc/include/generic-freebsd/net/vnet.h index 33cf304daf75..54d35cbeb392 100644 --- a/lib/libc/include/generic-freebsd/net/vnet.h +++ b/lib/libc/include/generic-freebsd/net/vnet.h @@ -311,6 +311,12 @@ void *vnet_data_alloc(int size); void vnet_data_copy(void *start, int size); void vnet_data_free(void *start_arg, int size); +/* + * Interfaces to manipulate the initial values of virtualized global variables. + */ +void vnet_save_init(void *, size_t); +void vnet_restore_init(void *, size_t); + /* * Virtual sysinit mechanism, allowing network stack components to declare * startup and shutdown methods to be run when virtual network stack @@ -400,7 +406,7 @@ do { \ #define CURVNET_SET(arg) #define CURVNET_SET_QUIET(arg) #define CURVNET_RESTORE() -#define CURVNET_ASSERT_SET() \ +#define CURVNET_ASSERT_SET() #define VNET_LIST_RLOCK() #define VNET_LIST_RLOCK_NOSLEEP() diff --git a/lib/libc/include/generic-freebsd/net80211/_ieee80211.h b/lib/libc/include/generic-freebsd/net80211/_ieee80211.h index 442bac97aff6..23d3d75d00f9 100644 --- a/lib/libc/include/generic-freebsd/net80211/_ieee80211.h +++ b/lib/libc/include/generic-freebsd/net80211/_ieee80211.h @@ -536,6 +536,27 @@ struct ieee80211_mimo_info { "\21AMPDU\22AMSDU\23HT\24SMPS\25RIFS\32TXLDPC\33RXAMSDUAMPDU" \ "\34TXAMSDUAMPDU" +/* + * AKM (key management) suite capability list. + * + * These represent what's in 802.11-2016 - Table 9-133 - AKM Suite Selectors. + * Note that they do not match what the table values are, in case other key + * management suites want to be added with different OUIs. + */ +#define IEEE80211_KEYMGMT_RSN_UNSPEC_802_1X 0x00000001 /* RSN suite 1 */ +#define IEEE80211_KEYMGMT_RSN_PSK_OVER_802_1X 0x00000002 /* RSN suite 2 */ +#define IEEE80211_KEYMGMT_RSN_FT_OVER_802_1X 0x00000004 /* RSN suite 3 */ +#define IEEE80211_KEYMGMT_RSN_FT_PSK 0x00000008 /* RSN suite 4 */ +#define IEEE80211_KEYMGMT_RSN_802_1X_SHA256 0x00000010 /* RSN suite 5 */ +#define IEEE80211_KEYMGMT_RSN_PSK_SHA256 0x00000020 /* RSN suite 6 */ +#define IEEE80211_KEYMGMT_RSN_TPK_HANDSHAKE 0x00000040 /* RSN suite 7 */ +#define IEEE80211_KEYMGMT_RSN_SAE 0x00000080 /* RSN suite 8 */ +#define IEEE80211_KEYMGMT_RSN_FT_SAE 0x00000100 /* RSN suite 9 */ +#define IEEE80211_KEYMGMT_RSN_APPEERKEY_SHA256 0x00000200 /* RSN suite 10 */ +#define IEEE80211_KEYMGMT_RSN_802_1X_SUITE_B 0x00000400 /* RSN suite 11 */ +#define IEEE80211_KEYMGMT_RSN_802_1X_SUITE_B_192 0x00000800 /* RSN suite 12 */ +#define IEEE80211_KEYMGMT_RSN_FT_802_1X_SHA384 0x00001000 /* RSN suite 13 */ + /* * RX status notification - which fields are valid. */ @@ -564,15 +585,18 @@ struct ieee80211_mimo_info { #define IEEE80211_RX_F_AMPDU 0x00000010 /* This is the start of an decap AMPDU list */ #define IEEE80211_RX_F_AMPDU_MORE 0x00000020 /* This is another decap AMPDU frame in the batch */ #define IEEE80211_RX_F_FAIL_FCSCRC 0x00000040 /* Failed CRC/FCS */ -#define IEEE80211_RX_F_FAIL_MIC 0x00000080 /* Failed MIC check */ +#define IEEE80211_RX_F_FAIL_MMIC 0x00000080 /* Failed Michael MIC (MMIC) check */ #define IEEE80211_RX_F_DECRYPTED 0x00000100 /* Hardware decrypted */ #define IEEE80211_RX_F_IV_STRIP 0x00000200 /* Decrypted; IV stripped */ -#define IEEE80211_RX_F_MMIC_STRIP 0x00000400 /* Decrypted; MMIC stripped */ +#define IEEE80211_RX_F_MMIC_STRIP 0x00000400 /* Decrypted; Michael MIC (MMIC) stripped */ #define IEEE80211_RX_F_SHORTGI 0x00000800 /* This is a short-GI frame */ #define IEEE80211_RX_F_CCK 0x00001000 #define IEEE80211_RX_F_OFDM 0x00002000 #define IEEE80211_RX_F_HT 0x00004000 #define IEEE80211_RX_F_VHT 0x00008000 +#define IEEE80211_RX_F_PN_VALIDATED 0x00010000 /* Decrypted; PN validated */ +#define IEEE80211_RX_F_MIC_STRIP 0x00020000 /* Decrypted; MIC stripped */ +#define IEEE80211_RX_F_ICV_STRIP 0x00040000 /* Decrypted: ICV (ic_trailer) stripped */ /* Channel width */ #define IEEE80211_RX_FW_20MHZ 1 diff --git a/lib/libc/include/generic-freebsd/net80211/ieee80211.h b/lib/libc/include/generic-freebsd/net80211/ieee80211.h index 04b62c98718d..8b68116251e8 100644 --- a/lib/libc/include/generic-freebsd/net80211/ieee80211.h +++ b/lib/libc/include/generic-freebsd/net80211/ieee80211.h @@ -4,6 +4,10 @@ * Copyright (c) 2001 Atsushi Onoe * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting * All rights reserved. + * Copyright (c) 2020-2025 The FreeBSD Foundation + * + * Portions of this software were developed by Björn Zeeb + * 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 @@ -28,6 +32,12 @@ #ifndef _NET80211_IEEE80211_H_ #define _NET80211_IEEE80211_H_ +#include + +#ifndef _KERNEL +#include +#endif + /* * 802.11 protocol definitions. */ @@ -161,6 +171,7 @@ struct ieee80211_qosframe_addr4 { /* 0001-0011 Reserved 0x10-0x30 */ /* Were: CF_ACK, CF_POLL, CF_ACPL */ #define IEEE80211_FC0_SUBTYPE_NODATA 0x40 /* Null */ /* 0101-0111 Reserved 0x50-0x70 */ /* Were: CFACK, CFPOLL, CF_ACK_CF_ACK */ +#define IEEE80211_FC0_SUBTYPE_QOS_MASK_ANY 0x80 /* QoS mask - matching any subtypes 8..15 */ #define IEEE80211_FC0_SUBTYPE_QOS_DATA 0x80 /* QoS Data */ #define IEEE80211_FC0_SUBTYPE_QOS_DATA_CFACK 0x90 /* QoS Data +CF-Ack */ #define IEEE80211_FC0_SUBTYPE_QOS_DATA_CFPOLL 0xa0 /* QoS Data +CF-Poll */ @@ -190,24 +201,98 @@ struct ieee80211_qosframe_addr4 { #define IEEE80211_CTL_EXT_TDD_BF 0x0b /* TDD Beamforming, 80211ay-2021 */ /* 1100-1111 Reserved 0xc-0xf */ -#define IEEE80211_IS_MGMT(wh) \ - (!! (((wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK) \ - == IEEE80211_FC0_TYPE_MGT)) +/* Check the version field */ +#define IEEE80211_IS_FC0_CHECK_VER(wh, v) \ + (((wh)->i_fc[0] & IEEE80211_FC0_VERSION_MASK) == (v)) + +/* Check the version and type field */ +#define IEEE80211_IS_FC0_CHECK_VER_TYPE(wh, v, t) \ + (((((wh)->i_fc[0] & IEEE80211_FC0_VERSION_MASK) == (v))) && \ + (((wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == (t))) + +/* Check the version, type and subtype field */ +#define IEEE80211_IS_FC0_CHECK_VER_TYPE_SUBTYPE(wh, v, t, st) \ + (((((wh)->i_fc[0] & IEEE80211_FC0_VERSION_MASK) == (v))) && \ + (((wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == (t)) && \ + (((wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == (st))) + +#define IEEE80211_IS_MGMT(wh) \ + (IEEE80211_IS_FC0_CHECK_VER_TYPE(wh, IEEE80211_FC0_VERSION_0, \ + IEEE80211_FC0_TYPE_MGT)) #define IEEE80211_IS_CTL(wh) \ - (!! (((wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK) \ - == IEEE80211_FC0_TYPE_CTL)) + (IEEE80211_IS_FC0_CHECK_VER_TYPE(wh, IEEE80211_FC0_VERSION_0, \ + IEEE80211_FC0_TYPE_CTL)) #define IEEE80211_IS_DATA(wh) \ - (!! (((wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK) \ - == IEEE80211_FC0_TYPE_DATA)) + (IEEE80211_IS_FC0_CHECK_VER_TYPE(wh, IEEE80211_FC0_VERSION_0, \ + IEEE80211_FC0_TYPE_DATA)) #define IEEE80211_IS_EXT(wh) \ - (!! (((wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK) \ - == IEEE80211_FC0_TYPE_EXT)) + (IEEE80211_IS_FC0_CHECK_VER_TYPE(wh, IEEE80211_FC0_VERSION_0, \ + IEEE80211_FC0_TYPE_EXT)) + +/* Management frame types */ + +#define IEEE80211_IS_MGMT_BEACON(wh) \ + (IEEE80211_IS_FC0_CHECK_VER_TYPE_SUBTYPE(wh, \ + IEEE80211_FC0_VERSION_0, \ + IEEE80211_FC0_TYPE_MGT, \ + IEEE80211_FC0_SUBTYPE_BEACON)) -#define IEEE80211_FC0_QOSDATA \ - (IEEE80211_FC0_TYPE_DATA|IEEE80211_FC0_SUBTYPE_QOS_DATA|IEEE80211_FC0_VERSION_0) +#define IEEE80211_IS_MGMT_PROBE_RESP(wh) \ + (IEEE80211_IS_FC0_CHECK_VER_TYPE_SUBTYPE(wh, \ + IEEE80211_FC0_VERSION_0, \ + IEEE80211_FC0_TYPE_MGT, \ + IEEE80211_FC0_SUBTYPE_PROBE_RESP)) + +#define IEEE80211_IS_MGMT_ACTION(wh) \ + (IEEE80211_IS_FC0_CHECK_VER_TYPE_SUBTYPE(wh, \ + IEEE80211_FC0_VERSION_0, \ + IEEE80211_FC0_TYPE_MGT, \ + IEEE80211_FC0_SUBTYPE_ACTION)) + +/* Control frame types */ + +#define IEEE80211_IS_CTL_PS_POLL(wh) \ + (IEEE80211_IS_FC0_CHECK_VER_TYPE_SUBTYPE(wh, \ + IEEE80211_FC0_VERSION_0, \ + IEEE80211_FC0_TYPE_CTL, \ + IEEE80211_FC0_SUBTYPE_PS_POLL)) + +#define IEEE80211_IS_CTL_BAR(wh) \ + (IEEE80211_IS_FC0_CHECK_VER_TYPE_SUBTYPE(wh, \ + IEEE80211_FC0_VERSION_0, \ + IEEE80211_FC0_TYPE_CTL, \ + IEEE80211_FC0_SUBTYPE_BAR)) + +/* Data frame types */ + +/* + * Return true if the frame is any of the QOS frame types, not just + * data frames. Matching on the IEEE80211_FC0_SUBTYPE_QOS_ANY bit + * being set also matches on subtypes 8..15. + */ +#define IEEE80211_IS_QOS_ANY(wh) \ + ((IEEE80211_IS_FC0_CHECK_VER_TYPE(wh, IEEE80211_FC0_VERSION_0, \ + IEEE80211_FC0_TYPE_DATA)) && \ + ((wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS_MASK_ANY)) + +/* + * Return true if this frame is QOS data, and only QOS data. + */ +#define IEEE80211_IS_QOSDATA(wh) \ + (IEEE80211_IS_FC0_CHECK_VER_TYPE_SUBTYPE(wh, \ + IEEE80211_FC0_VERSION_0, \ + IEEE80211_FC0_TYPE_DATA, \ + IEEE80211_FC0_SUBTYPE_QOS_DATA)) + +/* + * Return true if this frame is a QoS NULL data frame. + */ +#define IEEE80211_IS_QOS_NULL(wh) \ + (IEEE80211_IS_FC0_CHECK_VER_TYPE_SUBTYPE(wh, \ + IEEE80211_FC0_VERSION_0, \ + IEEE80211_FC0_TYPE_DATA, \ + IEEE80211_FC0_SUBTYPE_QOS_NULL)) -#define IEEE80211_IS_QOSDATA(wh) \ - ((wh)->i_fc[0] == IEEE80211_FC0_QOSDATA) #define IEEE80211_FC1_DIR_MASK 0x03 #define IEEE80211_FC1_DIR_NODS 0x00 /* STA->STA */ @@ -421,7 +506,7 @@ struct ieee80211_action { #define IEEE80211_ACTION_CAT_BA 3 /* 9.6.4 Block Ack */ #define IEEE80211_ACTION_CAT_PUBLIC 4 /* 9.6.7 Public */ #define IEEE80211_ACTION_CAT_RADIO_MEASUREMENT 5 /* 9.6.6 Radio Measurement */ -#define IEEE80211_ACTION_CAT_FAST_BBS_TRANSITION 6 /* 9.6.8 Fast BSS Transition */ +#define IEEE80211_ACTION_CAT_FAST_BSS_TRANSITION 6 /* 9.6.8 Fast BSS Transition */ #define IEEE80211_ACTION_CAT_HT 7 /* 9.6.11 HT */ #define IEEE80211_ACTION_CAT_SA_QUERY 8 /* 9.6.9 SA Query */ #define IEEE80211_ACTION_CAT_PROTECTED_DUAL_OF_PUBLIC_ACTION 9 /* 9.6.10 Protected Dual of Public Action */ @@ -856,6 +941,7 @@ enum ieee80211_vht_mcs_support { IEEE80211_VHT_MCS_NOT_SUPPORTED = 3 /* not supported */ }; +/* 802.11ac-2013, 8.4.2.160.3 Supported VHT-MCS and NSS Set field */ struct ieee80211_vht_mcs_info { uint16_t rx_mcs_map; uint16_t rx_highest; @@ -869,12 +955,15 @@ struct ieee80211_vht_cap { struct ieee80211_vht_mcs_info supp_mcs; } __packed; -/* 802.11ac-2013, Table 8-183x-VHT Operation Information subfields */ +/* + * 802.11ac-2013, Table 8-183x-VHT Operation Information subfields. + * 802.11-2020, Table 9-274-VHT Operation Information subfields (for deprecations) + */ enum ieee80211_vht_chanwidth { IEEE80211_VHT_CHANWIDTH_USE_HT = 0, /* 20 MHz or 40 MHz */ IEEE80211_VHT_CHANWIDTH_80MHZ = 1, /* 80MHz */ - IEEE80211_VHT_CHANWIDTH_160MHZ = 2, /* 160MHz */ - IEEE80211_VHT_CHANWIDTH_80P80MHZ = 3, /* 80+80MHz */ + IEEE80211_VHT_CHANWIDTH_160MHZ = 2, /* 160MHz (deprecated) */ + IEEE80211_VHT_CHANWIDTH_80P80MHZ = 3, /* 80+80MHz (deprecated) */ /* 4..255 reserved. */ }; @@ -898,7 +987,7 @@ struct ieee80211_vht_operation { #define IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK 0x0000000C #define IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK_S 2 -#define IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_NONE 0 +#define IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_NO160 0 #define IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160MHZ 1 #define IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160_80P80MHZ 2 #define IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_RESERVED 3 @@ -969,11 +1058,15 @@ struct ieee80211_vht_operation { #define IEEE80211_VHTCAP_TX_ANTENNA_PATTERN 0x20000000 #define IEEE80211_VHTCAP_TX_ANTENNA_PATTERN_S 29 +/* 802.11-2016, 9.4.2.158.2 VHT Capabilities Information field. */ +#define IEEE80211_VHTCAP_EXT_NSS_BW 0xc0000000 +#define IEEE80211_VHTCAP_EXT_NSS_BW_S 30 + /* * XXX TODO: add the rest of the bits */ #define IEEE80211_VHTCAP_BITS \ - "\20\1MPDU7991\2MPDU11454\3CHAN160\4CHAN8080\5RXLDPC\6SHORTGI80" \ + "\20\1MPDU7991\2MPDU11454\3CHAN160\4CHAN160+80P80\5RXLDPC\6SHORTGI80" \ "\7SHORTGI160\10RXSTBC1\11RXSTBC2\12RXSTBC3\13RXSTBC4\14BFERCAP" \ "\15BFEECAP\27VHT\37RXANTPTN\40TXANTPTN" @@ -1015,22 +1108,296 @@ struct ieee80211_ie_vht_txpwrenv { #define WLAN_ACTION_VHT_GROUPID_MGMT 1 #define WLAN_ACTION_VHT_OPMODE_NOTIF 2 +#if defined(_KERNEL) || defined(WANT_NET80211) +/* + * HE + */ + +/* + * 802.11ax-2021, 9.4.2.248.2 HE MAC Capabilities Information field. + */ +/* B0..B7 */ +#define IEEE80211_HE_MAC_CAP0_HTC_HE (1<<0) +#define IEEE80211_HE_MAC_CAP0_TWT_REQ (1<<1) +#define IEEE80211_HE_MAC_CAP0_TWT_RES (1<<2) + +/* B8..B15 */ +#define IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US (1<<3) +#define IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK (1<<3 | 1<<2) +#define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8 (1<<6 | 1<<5 | 1<<4) +#define IEEE80211_HE_MAC_CAP1_LINK_ADAPTATION (1<<7) +/* Note: B15|B16 are split between octets %!$@??? */ + +/* B16..B23 */ +#define IEEE80211_HE_MAC_CAP2_LINK_ADAPTATION (1<<0) +#define IEEE80211_HE_MAC_CAP2_ALL_ACK (1<<1) +#define IEEE80211_HE_MAC_CAP2_TRS (1<<2) +#define IEEE80211_HE_MAC_CAP2_BSR (1<<3) +#define IEEE80211_HE_MAC_CAP2_BCAST_TWT (1<<4) +#define IEEE80211_HE_MAC_CAP2_32BIT_BA_BITMAP (1<<5) +#define IEEE80211_HE_MAC_CAP2_MU_CASCADING (1<<6) +#define IEEE80211_HE_MAC_CAP2_ACK_EN (1<<7) + +/* B24..B31 */ +#define IEEE80211_HE_MAC_CAP3_OMI_CONTROL (1<<1) +#define IEEE80211_HE_MAC_CAP3_OFDMA_RA (1<<2) +#define IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_1 (1<<3) +#define IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_2 (1<<4) +#define IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3 (1<<4 | 1<<3) +#define IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK (1<<4 | 1<<3) +#define IEEE80211_HE_MAC_CAP3_FLEX_TWT_SCHED (1<<6) +#define IEEE80211_HE_MAC_CAP3_RX_CTRL_FRAME_TO_MULTIBSS (1<<7) + +/* B32..B39 */ +#define IEEE80211_HE_MAC_CAP4_BSRP_BQRP_A_MPDU_AGG (1<<0) +#define IEEE80211_HE_MAC_CAP4_BQR (1<<2) +#define IEEE80211_HE_MAC_CAP4_OPS (1<<5) +#define IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU (1<<6) +#define IEEE80211_HE_MAC_CAP4_MULTI_TID_AGG_TX_QOS_B39 (1<<7) +/* Note: B39|B40|B41 are split between octets %!$@??? */ + +/* B40..B47 */ +#define IEEE80211_HE_MAC_CAP5_MULTI_TID_AGG_TX_QOS_B40 (1<<0) +#define IEEE80211_HE_MAC_CAP5_MULTI_TID_AGG_TX_QOS_B41 (1<<1) +#define IEEE80211_HE_MAC_CAP5_SUBCHAN_SELECTIVE_TRANSMISSION (1<<2) +#define IEEE80211_HE_MAC_CAP5_UL_2x996_TONE_RU (1<<3) +#define IEEE80211_HE_MAC_CAP5_OM_CTRL_UL_MU_DATA_DIS_RX (1<<4) +#define IEEE80211_HE_MAC_CAP5_HE_DYNAMIC_SM_PS (1<<5) +#define IEEE80211_HE_MAC_CAP5_PUNCTURED_SOUNDING (1<<6) +#define IEEE80211_HE_MAC_CAP5_HT_VHT_TRIG_FRAME_RX (1<<7) + +/* + * 802.11ax-2021, 9.4.2.248.3 HE PHY Capabilities Information field. + */ +/* B0..B7 */ +#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G (1<<1) +#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G (1<<2) +#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G (1<<3) +#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G (1<<4) +#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL (1<<4 | 1<<3 | 1<<2 | 1<<1) +#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G (1<<5) +#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G (1<<6) +#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK (1<<6 | 1<<5 | 1<<4 | 1<<3 | 1<<2 | 1<<1) + +/* B8..B15 */ +#define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK (1<<3 | 1<<2 | 1<<1 | 1<<0) +#define IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A (1<<4) +#define IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD (1<<5) +#define IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US (1<<6) +#define IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS (1<<7) +/* Note: B15|B16 are split between octets %!$@??? */ + +/* B16..B23 */ +#define IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_TX_MAX_NSTS (1<<0) +#define IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US (1<<1) +#define IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ (1<<2) +#define IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ (1<<3) +#define IEEE80211_HE_PHY_CAP2_DOPPLER_TX (1<<4) +#define IEEE80211_HE_PHY_CAP2_DOPPLER_RX (1<<5) +#define IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO (1<<6) +#define IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO (1<<7) + +/* B24..B31 */ +#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_NO_DCM 0x00 +#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_BPSK (1<<0) +#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK (1<<1) +#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_16_QAM (1<<1 | 1<<0) +#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK (1<<1 | 1<<0) +#define IEEE80211_HE_PHY_CAP3_DCM_MAX_TX_NSS_1 0x00 +#define IEEE80211_HE_PHY_CAP3_DCM_MAX_TX_NSS_2 (1<<2) +#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_NO_DCM 0x00 +#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_BPSK (1<<3) +#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK (1<<4) +#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM (1<<4 | 1<<3) +#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK (1<<4 | 1<<3) +#define IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 0x00 +#define IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_2 (1<<5) +#define IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU (1<<6) +#define IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER (1<<7) + +/* B32..B39 */ +#define IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE (1<<0) +#define IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER (1<<1) +#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4 (1<<3 | 1<<2) +#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_5 (1<<4) +#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_8 (1<<4 | 1<<3 | 1<<2) +#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_MASK (1<<4 | 1<<3 | 1<<2) +#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4 (1<<6 | 1<<5) +#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_5 (1<<7) +#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_8 (1<<7 | 1<<6 | 1<<5) +#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_MASK (1<<7 | 1<<6 | 1<<5) + +/* B40..B47 */ +#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_2 (1<<0) +#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK (1<<2 | 1<<1 | 1<<0) +#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2 (1<<3) +#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK (1<<5 | 1<<4 | 1<<3) +#define IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK (1<<6) +#define IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK (1<<7) + +/* B48..B55 */ +#define IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU (1<<0) +#define IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU (1<<1) +#define IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB (1<<2) +#define IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB (1<<3) +#define IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB (1<<4) +#define IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE (1<<5) +#define IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO (1<<6) +#define IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT (1<<7) + +/* B56..B63 */ +#define IEEE80211_HE_PHY_CAP7_PSR_BASED_SR (1<<0) +#define IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP (1<<1) +#define IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI (1<<2) +#define IEEE80211_HE_PHY_CAP7_MAX_NC_1 (1<<3) +#define IEEE80211_HE_PHY_CAP7_MAX_NC_2 (1<<4) +#define IEEE80211_HE_PHY_CAP7_MAX_NC_MASK (1<<5 | 1<<4 | 1<<3) +#define IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ (1<<6) +#define IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ (1<<7) + +/* B64..B71 */ +#define IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI (1<<0) +#define IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G (1<<1) +#define IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU (1<<2) +#define IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU (1<<3) +#define IEEE80211_HE_PHY_CAP8_HE_ER_SU_1XLTF_AND_08_US_GI (1<<4) +#define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_242 0x00 +#define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_484 (1<<6) +#define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_996 (1<<7) +#define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_2x996 (1<<7 | 1<<6) +#define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_MASK (1<<7 | 1<<6) + +/* B72..B79 */ +#define IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM (1<<0) +#define IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK (1<<1) +#define IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU (1<<2) +#define IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU (1<<3) +#define IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB (1<<4) +#define IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB (1<<5) +#define IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_0US 0x00 +#define IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_8US 1 +#define IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US 2 +#define IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_RESERVED 3 +#define IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_POS 6 +#define IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK (1<<7 | 1<<6) + +/* B80..B87 */ +#define IEEE80211_HE_PHY_CAP10_HE_MU_M1RU_MAX_LTF (1<<0) + +/* + * 802.11ax-2021, + * 9.4.2.248.2 HE MAC Capabilities Information field. + * 9.4.2.248.3 HE PHY Capabilities Information field. + */ +struct ieee80211_he_cap_elem { + uint8_t mac_cap_info[6]; + uint8_t phy_cap_info[11]; +} __packed; + +/* 802.11ax-2021, 9.4.2.248.4 Supported HE-MCS And NSS Set field. */ +enum ieee80211_he_mcs_support { + IEEE80211_HE_MCS_SUPPORT_0_7 = 0, /* HE-MCS 0-7 for n NSS */ + IEEE80211_HE_MCS_SUPPORT_0_9 = 1, /* HE-MCS 0-9 for n NSS */ + IEEE80211_HE_MCS_SUPPORT_0_11 = 2, /* HE-MCS 0-11 for n NSS */ + IEEE80211_HE_MCS_NOT_SUPPORTED = 3 /* n NSS not supported. */ +}; + +struct ieee80211_he_mcs_nss_supp { + uint16_t rx_mcs_80; + uint16_t tx_mcs_80; + uint16_t rx_mcs_160; + uint16_t tx_mcs_160; + uint16_t rx_mcs_80p80; + uint16_t tx_mcs_80p80; +} __packed; + +#define IEEE80211_HE_CAP_PPE_THRES_MAX 25 + +/* XXX this should only be internal. */ +struct net80211_he_cap { + bool has_he; + struct ieee80211_he_cap_elem he_cap_elem; + struct ieee80211_he_mcs_nss_supp he_mcs_nss_supp; + uint8_t ppe_thres[IEEE80211_HE_CAP_PPE_THRES_MAX]; +}; + +/* 802.11ax-2021, 9.4.2.249 HE Operation element. */ +#define IEEE80211_HE_OPERATION_ER_SU_DISABLE (1<<16) +#define IEEE80211_HE_OPERATION_BSS_COLOR_OFFSET 24 +#define IEEE80211_HE_OPERATION_BSS_COLOR_DISABLED (1<<31) + +struct ieee80211_he_operation { + uint32_t he_oper_params; /* (3) params | (1) bss color info */ + uint16_t he_mcs_nss_set; + uint8_t optional[0]; +} __packed; + +/* 802.11ax-2021, 9.4.2.251 MU EDCA Parameter Set element. */ +struct ieee80211_he_mu_edca_param_ac_rec { + uint8_t aifsn; + uint8_t ecw_min_max; + uint8_t mu_edca_timer; +} __packed; + +struct ieee80211_mu_edca_param_set { + uint8_t mu_qos_info; + union { + struct { + struct ieee80211_he_mu_edca_param_ac_rec ac_be; + struct ieee80211_he_mu_edca_param_ac_rec ac_bk; + struct ieee80211_he_mu_edca_param_ac_rec ac_vi; + struct ieee80211_he_mu_edca_param_ac_rec ac_vo; + }; + struct ieee80211_he_mu_edca_param_ac_rec param_ac_recs[4]; + }; +} __packed; + +/* 802.11ax-2021, 9.4.2.252 Spatial Reuse Parameter Set element */ +/* Figure 9-788r-SR Control field format */ +#define IEEE80211_HE_SPR_NON_SRG_OBSS_PD_SR_DISALLOWED (1<<1) +#define IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT (1<<2) +#define IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT (1<<3) +#define IEEE80211_HE_SPR_HESIGA_SR_VAL15_ALLOWED (1<<4) + +/* 802.11ax-2021, 9.4.2.263 HE 6 GHz Band Capabilities element */ +/* Figure 9-788aj-Capabilities Information field format */ +#define IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START (1<<2 | 1<<1 | 1<<0) +#define IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP (1<<5 | 1<<4 | 1<<3) +#define IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN (1<<7 | 1<<6) +#define IEEE80211_HE_6GHZ_CAP_SM_PS (1<<10 | 1<<9) +#define IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS (1<<12) +#define IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS (1<<13) + +struct ieee80211_he_6ghz_capa { + uint16_t capa; +}; +#endif /* _KERNEL || WANT_NET80211 */ + /* * Management information element payloads. + * + * 802.11-2020 Table 9-92 (Element IDs). + * 802.11ax-2021 */ enum { IEEE80211_ELEMID_SSID = 0, IEEE80211_ELEMID_RATES = 1, - IEEE80211_ELEMID_FHPARMS = 2, + /* 2 Reserved */ + IEEE80211_ELEMID_FHPARMS = 2, /* remove? */ IEEE80211_ELEMID_DSPARMS = 3, - IEEE80211_ELEMID_CFPARMS = 4, + /* 4 Reserved */ + IEEE80211_ELEMID_CFPARMS = 4, /* remove? */ IEEE80211_ELEMID_TIM = 5, IEEE80211_ELEMID_IBSSPARMS = 6, IEEE80211_ELEMID_COUNTRY = 7, + /* 8, 9 reserved */ + IEEE80211_ELEMID_REQUEST = 10, IEEE80211_ELEMID_BSSLOAD = 11, + IEEE80211_ELEMID_EDCA_PARAM_SET = 12, IEEE80211_ELEMID_TSPEC = 13, IEEE80211_ELEMID_TCLAS = 14, + IEEE80211_ELEMID_SCHEDULE = 15, IEEE80211_ELEMID_CHALLENGE = 16, /* 17-31 reserved for challenge text extension */ IEEE80211_ELEMID_PWRCNSTR = 32, @@ -1044,28 +1411,77 @@ enum { IEEE80211_ELEMID_QUIET = 40, IEEE80211_ELEMID_IBSSDFS = 41, IEEE80211_ELEMID_ERP = 42, + IEEE80211_ELEMID_TS_DELAY = 43, + IEEE80211_ELEMID_TCLAS_PROCES = 44, IEEE80211_ELEMID_HTCAP = 45, IEEE80211_ELEMID_QOS = 46, + /* 47 reserved */ IEEE80211_ELEMID_RESERVED_47 = 47, IEEE80211_ELEMID_RSN = 48, + /* 49 reserved */ IEEE80211_ELEMID_XRATES = 50, IEEE80211_ELEMID_APCHANREP = 51, - IEEE80211_ELEMID_MOBILITY_DOMAIN = 54, - IEEE80211_ELEMID_HTINFO = 61, + IEEE80211_ELEMID_NEIGHBOR_REP = 52, + IEEE80211_ELEMID_RCPI = 53, + IEEE80211_ELEMID_MOBILITY_DOMAIN = 54, /* MDE */ + IEEE80211_ELEMID_FAST_BSS_TRANS = 55, /* FTE */ + IEEE80211_ELEMID_TIMEOUT_INTVL = 56, + IEEE80211_ELEMID_RIC_DATA = 57, /* RDE */ + IEEE80211_ELEMID_DSE_REG_LOC = 58, + IEEE80211_ELEMID_SUP_OP_CLASS = 59, + IEEE80211_ELEMID_EXT_CSA = 60, + IEEE80211_ELEMID_HTINFO = 61, /* HTOPER */ IEEE80211_ELEMID_SECCHAN_OFFSET = 62, - IEEE80211_ELEMID_RRM_ENACAPS = 70, + IEEE80211_ELEMID_BSS_AVG_ACC_DELAY = 63, + IEEE80211_ELEMID_ANTENNA = 64, + IEEE80211_ELEMID_RSNI = 65, + IEEE80211_ELEMID_MEAS_PILOT_TRANS = 66, + IEEE80211_ELEMID_BSS_AVAIL_AD_CAP = 67, + IEEE80211_ELEMID_BSS_AC_ACC_DELAY = 68, + IEEE80211_ELEMID_TIME_ADV = 69, + IEEE80211_ELEMID_RRM_ENACAPS = 70, /* RM_ENCAPS */ IEEE80211_ELEMID_MULTIBSSID = 71, IEEE80211_ELEMID_COEX_2040 = 72, - IEEE80211_ELEMID_INTOL_CHN_REPORT = 73, + IEEE80211_ELEMID_2040_INTOL_CHAN_REPORT = 73, IEEE80211_ELEMID_OVERLAP_BSS_SCAN_PARAM = 74, + IEEE80211_ELEMID_RIC_DESC = 75, + IEEE80211_ELEMID_MGMT_MIC = 76, + /* 77 reserved */ + IEEE80211_ELEMID_EVENT_REQ = 78, + IEEE80211_ELEMID_EVENT_REP = 79, + IEEE80211_ELEMID_DIAGNOSTIC_REQ = 80, + IEEE80211_ELEMID_DIAGNOSTIC_REP = 81, + IEEE80211_ELEMID_LOCATION_PARAM = 82, + IEEE80211_ELEMID_NONTRANS_BSSID_CAP = 83, + IEEE80211_ELEMID_SSID_LIST = 84, + IEEE80211_ELEMID_MULTI_BSSID_IDX = 85, + IEEE80211_ELEMID_FMS_DESC = 86, + IEEE80211_ELEMID_FMS_REQ = 87, + IEEE80211_ELEMID_FMS_RESP = 88, + IEEE80211_ELEMID_QOS_TRAFFIC_CAP = 89, + IEEE80211_ELEMID_BSS_MAX_IDLE_P = 90, IEEE80211_ELEMID_TSF_REQ = 91, IEEE80211_ELEMID_TSF_RESP = 92, IEEE80211_ELEMID_WNM_SLEEP_MODE = 93, IEEE80211_ELEMID_TIM_BCAST_REQ = 94, IEEE80211_ELEMID_TIM_BCAST_RESP = 95, - IEEE80211_ELEMID_TPC = 150, - IEEE80211_ELEMID_CCKM = 156, - IEEE80211_ELEMID_VENDOR = 221, /* vendor private */ + IEEE80211_ELEMID_COL_INTERF_REP = 96, + IEEE80211_ELEMID_CHAN_USAGE = 97, + IEEE80211_ELEMID_TIME_ZONE = 98, + IEEE80211_ELEMID_DMS_REQ = 99, + IEEE80211_ELEMID_DMS_RESP = 100, + IEEE80211_ELEMID_LINK_ID = 101, + IEEE80211_ELEMID_WAKEUP_SCHED = 102, + /* 103 reserved */ + IEEE80211_ELEMID_CHAN_SW_TIMING = 104, + IEEE80211_ELEMID_PTI_CONTROL = 105, + IEEE80211_ELEMID_TPU_BUF_STATUS = 106, + IEEE80211_ELEMID_INTERWORKING = 107, + IEEE80211_ELEMID_ADV_PROTO = 108, + IEEE80211_ELEMID_EXP_BW_REQ = 109, + IEEE80211_ELEMID_QOS_MAP = 110, + IEEE80211_ELEMID_ROAM_CONSORT = 111, + IEEE80211_ELEMID_EMERG_ALERT_ID = 112, /* * 802.11s IEs @@ -1095,17 +1511,180 @@ enum { IEEE80211_ELEMID_MESHPXU = 137, IEEE80211_ELEMID_MESHPXUC = 138, IEEE80211_ELEMID_MESHAH = 60, /* XXX: remove */ - - /* 802.11ac-2013, Table 8-54-Element IDs */ + /* XXX 139 */ + + IEEE80211_ELEMID_MIC = 140, + IEEE80211_ELEMID_DEST_URI = 141, + IEEE80211_ELEMID_U_APSD_COEX = 142, + IEEE80211_ELEMID_DMG_WAKEUP_SCHED = 143, + IEEE80211_ELEMID_EXT_SCHED = 144, + IEEE80211_ELEMID_STA_AVAIL = 145, + IEEE80211_ELEMID_DMG_TSPEC = 146, + IEEE80211_ELEMID_NEXT_DMG_ATI = 147, + IEEE80211_ELEMID_DMG_CAP = 148, + /* 149-150 reserved. */ + IEEE80211_ELEMID_TPC = 150, /* XXX: remove */ + IEEE80211_ELEMID_DMG_OPER = 151, + IEEE80211_ELEMID_DMG_BSS_PARAM_CHANGE = 152, + IEEE80211_ELEMID_DMG_BEAM_REF = 153, + IEEE80211_ELEMID_CHAN_MEAS_FEEDB = 154, + /* 155-156 reserved. */ + IEEE80211_ELEMID_CCKM = 156, /* XXX: remove? */ + IEEE80211_ELEMID_AWAKE_WIN = 157, + IEEE80211_ELEMID_MULTI_BAND = 158, + IEEE80211_ELEMID_ADDBA_EXT = 159, + IEEE80211_ELEMID_NEXTPCP_LIST = 160, + IEEE80211_ELEMID_PCP_HANDOVER = 161, + IEEE80211_ELEMID_DMG_LINK_MARGIN = 162, + IEEE80211_ELEMID_SW_STREAM = 163, + IEEE80211_ELEMID_SESS_TRANS = 164, + /* 165 reserved. */ + IEEE80211_ELEMID_CLUSTER_REP = 166, + IEEE80211_ELEMID_RELAY_CAP = 167, + IEEE80211_ELEMID_RELAY_TRANS_PARAM_SET = 168, + IEEE80211_ELEMID_BEAMLINK_MAINT = 169, + IEEE80211_ELEMID_MULTI_MAC_SUBL = 170, + IEEE80211_ELEMID_U_PID = 171, + IEEE80211_ELEMID_DMG_LINK_ADAP_ACK = 172, + /* 173 reserved. */ + IEEE80211_ELEMID_MCCAOP_ADV_OV = 174, + IEEE80211_ELEMID_QUIET_PERIOD_REQ = 175, + /* 176 reserved. */ + IEEE80211_ELEMID_QUIET_PERIOD_RESP = 177, + /* 178-180 reserved. */ + IEEE80211_ELEMID_QMF_POLICY = 181, + IEEE80211_ELEMID_ECAPC_POLICY = 182, + IEEE80211_ELEMID_CLUSTER_TIME_OFFSET = 183, + IEEE80211_ELEMID_INTRA_ACC_CAT_PRIO = 184, + IEEE80211_ELEMID_SCS_DESCR = 185, + IEEE80211_ELEMID_QLOAD_REPORT = 186, + IEEE80211_ELEMID_HCCA_TXOP_UP_CNT = 187, + IEEE80211_ELEMID_HL_STREAM_ID = 188, + IEEE80211_ELEMID_GCR_GROUP_ADDR = 189, + IEEE80211_ELEMID_ANTENNA_SECTOR_ID_PAT = 190, IEEE80211_ELEMID_VHT_CAP = 191, IEEE80211_ELEMID_VHT_OPMODE = 192, IEEE80211_ELEMID_EXTENDED_BSS_LOAD = 193, - IEEE80211_ELEMID_WIDE_BW_CHANNEL_SWITCH = 194, - IEEE80211_ELEMID_VHT_PWR_ENV = 195, + IEEE80211_ELEMID_WIDE_BW_CHAN_SW = 194, + IEEE80211_ELEMID_VHT_PWR_ENV = 195, /* TX_PWR_ENV */ IEEE80211_ELEMID_CHANNEL_SWITCH_WRAPPER = 196, IEEE80211_ELEMID_AID = 197, IEEE80211_ELEMID_QUIET_CHANNEL = 198, IEEE80211_ELEMID_OPMODE_NOTIF = 199, + IEEE80211_ELEMID_UPSIM = 200, + IEEE80211_ELEMID_RED_NEIGH_REP = 201, + IEEE80211_ELEMID_TVHT_OP = 202, + /* 203 reserved. */ + IEEE80211_ELEMID_DEVICE_LOC = 204, + IEEE80211_ELEMID_WHITE_SPACE_MAP = 205, + IEEE80211_ELEMID_FINE_TIME_MEAS_PARAM = 206, + IEEE80211_ELEMID_SIG_OPEN_LOOP_LINK_MARGIN_IDX = 207, + IEEE80211_ELEMID_RPS = 208, + IEEE80211_ELEMID_PAGE_SLICE = 209, + IEEE80211_ELEMID_AID_REQ = 210, + IEEE80211_ELEMID_AID_RESP = 211, + IEEE80211_ELEMID_SIG_SECTOR_OP = 212, + IEEE80211_ELEMID_SIG_BEACON_COMPAT = 213, + IEEE80211_ELEMID_SHORT_BEACON_INTVL = 214, + IEEE80211_ELEMID_CHANGE_SEQ = 215, + IEEE80211_ELEMID_TWT = 216, + IEEE80211_ELEMID_SIG_CAPS = 217, + /* 218-219 reserved. */ + IEEE80211_ELEMID_SUBCHAN_SELECT_TRANS = 220, + IEEE80211_ELEMID_VENDOR = 221, /* vendor private */ + IEEE80211_ELEMID_AUTH_CONTROL = 222, + IEEE80211_ELEMID_TSF_TIMER_ACC = 223, + IEEE80211_ELEMID_S1G_RELAY = 224, + IEEE80211_ELEMID_REACHABLE_ADDR = 225, + IEEE80211_ELEMID_SIG_RELAY_DISC = 226, + /* 227 reserved. */ + IEEE80211_ELEMID_AID_ANNOUNCEMENT = 228, + IEEE80211_ELEMID_PV1_PROBE_RESP_OPT = 229, + IEEE80211_ELEMID_EL_OP = 230, + IEEE80211_ELEMID_SECTORIZED_GRP_ID_LIST = 231, + IEEE80211_ELEMID_SIG_OP = 232, + IEEE80211_ELEMID_HDR_COMPRESSION = 233, + IEEE80211_ELEMID_SST_OP = 234, + IEEE80211_ELEMID_MAD = 235, + IEEE80211_ELEMID_SIG_RELAY_ACT = 236, + IEEE80211_ELEMID_CAG_NUMBER = 237, + /* 238 reserved. */ + IEEE80211_ELEMID_AP_CSN = 239, + IEEE80211_ELEMID_FILS_INDICATION = 240, + IEEE80211_ELEMID_DILS = 241, + IEEE80211_ELEMID_FRAGMENT = 242, + /* 243 reserved. */ + IEEE80211_ELEMID_RSN_EXT = 244, + /* 245-254 reserved. */ + IEEE80211_ELEMID_EXTFIELD = 255 +}; + +enum ieee80211_elemid_ext { + IEEE80211_ELEMID_EXT_ASSOC_DELAY_INFO = 1, + IEEE80211_ELEMID_EXT_FILS_REQ_PARAMS = 2, + IEEE80211_ELEMID_EXT_FILS_KEY_CONFIRM = 3, + IEEE80211_ELEMID_EXT_FILS_SESSION = 4, + IEEE80211_ELEMID_EXT_FILS_HLP_CONTAINER = 5, + IEEE80211_ELEMID_EXT_FILS_IP_ADDR_ASSIGNMENT = 6, + IEEE80211_ELEMID_EXT_KEY_DELIVERY = 7, + IEEE80211_ELEMID_EXT_FILS_WRAPPED_DATA = 8, + IEEE80211_ELEMID_EXT_FTM_SYNC_INFO = 9, + IEEE80211_ELEMID_EXT_EXT_REQ = 10, + IEEE80211_ELEMID_EXT_EST_SERVICE_PARAM_INBOUND = 11, + IEEE80211_ELEMID_EXT_FILS_PUBLIC_KEY = 12, + IEEE80211_ELEMID_EXT_FILS_NONCE = 13, + IEEE80211_ELEMID_EXT_FUTURE_CHAN_GUIDANCE = 14, + IEEE80211_ELEMID_EXT_SERVICE_HINT = 15, + IEEE80211_ELEMID_EXT_SERVICE_HASH = 16, + IEEE80211_ELEMID_EXT_CDMG_CAPA = 17, + IEEE80211_ELEMID_EXT_DYN_BW_CTRL = 18, + IEEE80211_ELEMID_EXT_CDMG_EXT_SCHEDULE = 19, + IEEE80211_ELEMID_EXT_SSW_REPORT = 20, + IEEE80211_ELEMID_EXT_CLUSTER_PROBE = 21, + IEEE80211_ELEMID_EXT_EXT_CLUSTER_REPORT = 22, + IEEE80211_ELEMID_EXT_CLUSTER_SW_ANNOUNCEMENT = 23, + IEEE80211_ELEMID_EXT_ENHANCED_BEAM_TRACKING = 24, + IEEE80211_ELEMID_EXT_SPSH_REPORT = 25, + IEEE80211_ELEMID_EXT_CLUSTER_INTERF_ASSESS = 26, + IEEE80211_ELEMID_EXT_CMMG_CAPA = 27, + IEEE80211_ELEMID_EXT_CMMG_OPER = 28, + IEEE80211_ELEMID_EXT_CMMG_OPMODE_NOTIF = 29, + IEEE80211_ELEMID_EXT_CMMG_LINK_MARGIN = 30, + IEEE80211_ELEMID_EXT_CMMG_LINK_ADAP_ACK = 31, + /* 32 reserved. */ + IEEE80211_ELEMID_EXT_PASSWORD_ID = 33, + IEEE80211_ELEMID_EXT_GLK_GCR_PARAM_SET = 34, + IEEE80211_ELEMID_EXT_HE_CAPA = 35, + IEEE80211_ELEMID_EXT_HE_OPER = 36, + IEEE80211_ELEMID_EXT_UORA_PARAM_SET = 37, + IEEE80211_ELEMID_EXT_MU_EDCA_PARAM_SET = 38, + IEEE80211_ELEMID_EXT_SPATIAL_REUSE_PARAM_SET = 39, + IEEE80211_ELEMID_EXT_GAS_EXTENSION = 40, + IEEE80211_ELEMID_EXT_NDP_FEEDB_REPORT_PARAM = 41, + IEEE80211_ELEMID_EXT_BSS_COLOR_CHG_ANNOUNCE = 42, + IEEE80211_ELEMID_EXT_QUIET_TIMME_PERIOD = 43, + IEEE80211_ELEMID_EXT_VENDOR_SPECIFIC_REQ_ELEM = 44, + IEEE80211_ELEMID_EXT_ESS_REPORT = 45, + IEEE80211_ELEMID_EXT_OPS = 46, + IEEE80211_ELEMID_EXT_HE_BSS_LOAD = 47, + /* 48-51 reserved. */ + IEEE80211_ELEMID_EXT_MAC_CH_SW_TIME = 52, + IEEE80211_ELEMID_EXT_EST_SERVICE_PARAM_OUTBOUND = 53, + IEEE80211_ELEMID_EXT_OCI = 54, + IEEE80211_ELEMID_EXT_MULTI_BSSID_CONFIG = 55, + IEEE80211_ELEMID_EXT_NON_INHERITANCE = 56, + IEEE80211_ELEMID_EXT_KNOWN_BSSID = 57, + IEEE80211_ELEMID_EXT_SHORT_SSID_LIST = 58, + IEEE80211_ELEMID_EXT_HE_6GHZ_BAND_CAPA = 59, + IEEE80211_ELEMID_EXT_ULMU_POWER_CAAP = 60, + /* 61-87 reserved. */ + IEEE80211_ELEMID_EXT_MSCS_DESCRIPTOR = 88, + IEEE80211_ELEMID_EXT_TCLAS_MASK = 89, + IEEE80211_ELEMID_EXT_SUPPL_CLASS_2_CAPA = 90, + IEEE80211_ELEMID_EXT_OCT_SOURCE = 91, + IEEE80211_ELEMID_EXT_REJECTED_GROUPS = 92, + IEEE80211_ELEMID_EXT_ANTI_CLOGGING_TAOKEN_CONTAINER = 93, + /* 94-255 reserved. */ }; struct ieee80211_tim_ie { @@ -1266,7 +1845,7 @@ struct ieee80211_csa_ie { #define WPA_CSE_NULL 0x00 #define WPA_CSE_WEP40 0x01 #define WPA_CSE_TKIP 0x02 -#define WPA_CSE_CCMP 0x04 +#define WPA_CSE_CCMP 0x04 /* CCMP 128-bit */ #define WPA_CSE_WEP104 0x05 #define WPA_ASE_NONE 0x00 @@ -1275,21 +1854,62 @@ struct ieee80211_csa_ie { #define WPS_OUI_TYPE 0x04 +/* 802.11-2016 Table 9-131 - Cipher Suite Selectors */ #define RSN_OUI 0xac0f00 #define RSN_VERSION 1 /* current supported version */ -#define RSN_CSE_NULL 0x00 -#define RSN_CSE_WEP40 0x01 -#define RSN_CSE_TKIP 0x02 -#define RSN_CSE_WRAP 0x03 -#define RSN_CSE_CCMP 0x04 -#define RSN_CSE_WEP104 0x05 - -#define RSN_ASE_NONE 0x00 -#define RSN_ASE_8021X_UNSPEC 0x01 -#define RSN_ASE_8021X_PSK 0x02 - -#define RSN_CAP_PREAUTH 0x01 +/* RSN cipher suite element */ +#define RSN_CSE_NULL 0 +#define RSN_CSE_WEP40 1 +#define RSN_CSE_TKIP 2 +#define RSN_CSE_WRAP 3 /* Reserved in the 802.11-2016 */ +#define RSN_CSE_CCMP 4 /* CCMP 128 bit */ +#define RSN_CSE_WEP104 5 +#define RSN_CSE_BIP_CMAC_128 6 +/* 7 - "Group addressed traffic not allowed" */ +#define RSN_CSE_GCMP_128 8 +#define RSN_CSE_GCMP_256 9 +#define RSN_CSE_CCMP_256 10 +#define RSN_CSE_BIP_GMAC_128 11 +#define RSN_CSE_BIP_GMAC_256 12 +#define RSN_CSE_BIP_CMAC_256 13 + +/* 802.11-2016 Table 9-133 - AKM suite selectors */ +/* RSN AKM suite element */ +#define RSN_ASE_NONE 0 +#define RSN_ASE_8021X_UNSPEC 1 +#define RSN_ASE_8021X_PSK 2 +#define RSN_ASE_FT_8021X 3 /* SHA-256 */ +#define RSN_ASE_FT_PSK 4 /* SHA-256 */ +#define RSN_ASE_8021X_UNSPEC_SHA256 5 +#define RSN_ASE_8021X_PSK_SHA256 6 +#define RSN_ASE_8021X_TDLS 7 /* SHA-256 */ +#define RSN_ASE_SAE_UNSPEC 8 /* SHA-256 */ +#define RSN_ASE_FT_SAE 9 /* SHA-256 */ +#define RSN_ASE_AP_PEERKEY 10 /* SHA-256 */ +#define RSN_ASE_8021X_SUITE_B_SHA256 11 +#define RSN_ASE_8021X_SUITE_B_SHA384 12 +#define RSN_ASE_FT_8021X_SHA384 13 + +/* 802.11-2016 Figure 9-257 - RSN Capabilities (2 byte field) */ +#define RSN_CAP_PREAUTH 0x0001 +#define RSN_CAP_NO_PAIRWISE 0x0002 +#define RSN_CAP_PTKSA_REPLAY_COUNTER 0x000c /* 2 bit field */ +#define RSN_CAP_GTKSA_REPLAY_COUNTER 0x0030 /* 2 bit field */ +#define RSN_CAP_MFP_REQUIRED 0x0040 +#define RSN_CAP_MFP_CAPABLE 0x0080 +#define RSN_CAP_JOINT_MULTIBAND_RSNA 0x0100 +#define RSN_CAP_PEERKEY_ENABLED 0x0200 +#define RSN_CAP_SPP_AMSDU_CAPABLE 0x0400 +#define RSN_CAP_SPP_AMSDU_REQUIRED 0x0800 +#define RSN_CAP_PBAC_CAPABLE 0x1000 +#define RSN_CAP_EXT_KEYID_CAPABLE 0x0200 + +/* 802.11-2016 Table 9-134 PTKSA/GTKSA/STKSA replay counters usage */ +#define RSN_CAP_REPLAY_COUNTER_1_PER 0 +#define RSN_CAP_REPLAY_COUNTER_2_PER 1 +#define RSN_CAP_REPLAY_COUNTER_4_PER 2 +#define RSN_CAP_REPLAY_COUNTER_16_PER 3 #define WME_OUI 0xf25000 #define WME_OUI_TYPE 0x02 diff --git a/lib/libc/include/generic-freebsd/net80211/ieee80211_amrr.h b/lib/libc/include/generic-freebsd/net80211/ieee80211_amrr.h index dc593b0dd9f0..0039f7383c5e 100644 --- a/lib/libc/include/generic-freebsd/net80211/ieee80211_amrr.h +++ b/lib/libc/include/generic-freebsd/net80211/ieee80211_amrr.h @@ -49,6 +49,10 @@ struct ieee80211_amrr_node { struct ieee80211_amrr *amn_amrr;/* backpointer */ int amn_rix; /* current rate index */ int amn_ticks; /* time of last update */ + /* for VHT, since there's no VHT RIX right now */ + int amn_vht_mcs; + int amn_vht_nss; + /* statistics */ u_int amn_txcnt; u_int amn_success; diff --git a/lib/libc/include/generic-freebsd/net80211/ieee80211_crypto.h b/lib/libc/include/generic-freebsd/net80211/ieee80211_crypto.h index a261385ac756..8e64e8d81f0b 100644 --- a/lib/libc/include/generic-freebsd/net80211/ieee80211_crypto.h +++ b/lib/libc/include/generic-freebsd/net80211/ieee80211_crypto.h @@ -118,8 +118,8 @@ struct ieee80211_key { IEEE80211_KEY_NOIVMGT|IEEE80211_KEY_NOMIC|IEEE80211_KEY_NOMICMGT) #define IEEE80211_KEY_BITS \ - "\20\1XMIT\2RECV\3GROUP\4SWENCRYPT\5SWDECRYPT\6SWENMIC\7SWDEMIC" \ - "\10DEVKEY\11CIPHER0\12CIPHER1" + "\20\1XMIT\2RECV\3GROUP\4NOREPLAY\5SWENCRYPT\6SWDECRYPT\7SWENMIC\10SWDEMIC" \ + "\11DEVKEY\12CIPHER0\13CIPHER1\14NOIV\15NOIVMGT\16NOMIC\17NOMICMGT" #define IEEE80211_KEYIX_NONE ((ieee80211_keyix) -1) @@ -137,8 +137,17 @@ struct ieee80211_key { #define IEEE80211_CIPHER_TKIPMIC 4 /* TKIP MIC capability */ #define IEEE80211_CIPHER_CKIP 5 #define IEEE80211_CIPHER_NONE 6 /* pseudo value */ +#define IEEE80211_CIPHER_AES_CCM_256 7 +#define IEEE80211_CIPHER_BIP_CMAC_128 8 +#define IEEE80211_CIPHER_BIP_CMAC_256 9 +#define IEEE80211_CIPHER_BIP_GMAC_128 10 +#define IEEE80211_CIPHER_BIP_GMAC_256 11 +#define IEEE80211_CIPHER_AES_GCM_128 12 +#define IEEE80211_CIPHER_AES_GCM_256 13 -#define IEEE80211_CIPHER_MAX (IEEE80211_CIPHER_NONE+1) +#define IEEE80211_CIPHER_LAST 13 + +#define IEEE80211_CIPHER_MAX (IEEE80211_CIPHER_LAST+1) /* capability bits in ic_cryptocaps/iv_cryptocaps */ #define IEEE80211_CRYPTO_WEP (1< + * All rights reserved. + * + * Galois/Counter Mode (GCM) and GMAC with AES + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __IEEE80211_CRYPTO_GCM_H__ +#define __IEEE80211_CRYPTO_GCM_H__ + +#if defined(__KERNEL__) || defined(_KERNEL) + +#include + +#define AES_BLOCK_LEN 16 + +/* + * buffer is 2x the AES_BLOCK_LEN, but the AAD contents may be variable + * and are padded. + */ +#define GCM_AAD_LEN (AES_BLOCK_LEN * 2) + +/* GCMP is always 128 bit / 16 byte MIC */ +#define GCMP_MIC_LEN 16 + +void ieee80211_crypto_aes_gcm_ae(rijndael_ctx *aes, const uint8_t *iv, + size_t iv_len, const uint8_t *plain, size_t plain_len, + const uint8_t *aad, size_t aad_len, uint8_t *crypt, uint8_t *tag); + +int ieee80211_crypto_aes_gcm_ad(rijndael_ctx *aes, const uint8_t *iv, + size_t iv_len, const uint8_t *crypt, size_t crypt_len, + const uint8_t *aad, size_t aad_len, const uint8_t *tag, + uint8_t *plain); + +#endif /* __KERNEL__ */ + +#endif /* __IEEE80211_CRYPTO_GCM_H__ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/net80211/ieee80211_freebsd.h b/lib/libc/include/generic-freebsd/net80211/ieee80211_freebsd.h index 11453c7f6b43..7b1460b5fa0e 100644 --- a/lib/libc/include/generic-freebsd/net80211/ieee80211_freebsd.h +++ b/lib/libc/include/generic-freebsd/net80211/ieee80211_freebsd.h @@ -73,6 +73,8 @@ typedef struct { mtx_assert(IEEE80211_LOCK_OBJ(_ic), MA_OWNED) #define IEEE80211_UNLOCK_ASSERT(_ic) \ mtx_assert(IEEE80211_LOCK_OBJ(_ic), MA_NOTOWNED) +#define IEEE80211_IS_LOCKED(_ic) \ + mtx_owned(IEEE80211_LOCK_OBJ(_ic)) /* * Transmit lock. @@ -91,12 +93,22 @@ typedef struct { } while (0) #define IEEE80211_TX_LOCK_OBJ(_ic) (&(_ic)->ic_txlock.mtx) #define IEEE80211_TX_LOCK_DESTROY(_ic) mtx_destroy(IEEE80211_TX_LOCK_OBJ(_ic)) -#define IEEE80211_TX_LOCK(_ic) mtx_lock(IEEE80211_TX_LOCK_OBJ(_ic)) -#define IEEE80211_TX_UNLOCK(_ic) mtx_unlock(IEEE80211_TX_LOCK_OBJ(_ic)) -#define IEEE80211_TX_LOCK_ASSERT(_ic) \ - mtx_assert(IEEE80211_TX_LOCK_OBJ(_ic), MA_OWNED) -#define IEEE80211_TX_UNLOCK_ASSERT(_ic) \ - mtx_assert(IEEE80211_TX_LOCK_OBJ(_ic), MA_NOTOWNED) +#define IEEE80211_TX_LOCK(_ic) do { \ + if (!IEEE80211_CONF_SEQNO_OFFLOAD(_ic)) \ + mtx_lock(IEEE80211_TX_LOCK_OBJ(_ic)); \ + } while (0); +#define IEEE80211_TX_UNLOCK(_ic) do { \ + if (!IEEE80211_CONF_SEQNO_OFFLOAD(_ic)) \ + mtx_unlock(IEEE80211_TX_LOCK_OBJ(_ic)); \ + } while (0); +#define IEEE80211_TX_LOCK_ASSERT(_ic) do { \ + if (!IEEE80211_CONF_SEQNO_OFFLOAD(_ic)) \ + mtx_assert(IEEE80211_TX_LOCK_OBJ(_ic), MA_OWNED); \ + } while (0) +#define IEEE80211_TX_UNLOCK_ASSERT(_ic) { \ + if (!IEEE80211_CONF_SEQNO_OFFLOAD(_ic)) \ + mtx_assert(IEEE80211_TX_LOCK_OBJ(_ic), MA_NOTOWNED); \ + } while (0) /* * Stageq / ni_tx_superg lock @@ -260,9 +272,9 @@ void ieee80211_flush_ifq(struct ifqueue *, struct ieee80211vap *); void ieee80211_vap_destroy(struct ieee80211vap *); const char * ieee80211_get_vap_ifname(struct ieee80211vap *); -#define IFNET_IS_UP_RUNNING(_ifp) \ - (((_ifp)->if_flags & IFF_UP) && \ - ((_ifp)->if_drv_flags & IFF_DRV_RUNNING)) +#define IFNET_IS_UP_RUNNING(_ifp) \ + (((if_getflags(_ifp) & IFF_UP) != 0) && \ + ((if_getdrvflags(_ifp) & IFF_DRV_RUNNING) != 0)) #define msecs_to_ticks(ms) MSEC_2_TICKS(ms) #define ticks_to_msecs(t) TICKS_2_MSEC(t) @@ -329,11 +341,16 @@ struct mbuf *ieee80211_getmgtframe(uint8_t **frm, int headroom, int pktlen); #define M_AGE_SUB(m,adj) (m->m_pkthdr.csum_data -= adj) /* - * Store the sequence number. + * Store / retrieve the sequence number in an mbuf. + * + * The sequence number being stored/retreived is the 12 bit + * base sequence number, not the 16 bit sequence number field. + * I.e., it's from 0..4095 inclusive, with no 4 bit padding for + * fragment numbers. */ #define M_SEQNO_SET(m, seqno) \ - ((m)->m_pkthdr.tso_segsz = (seqno)) -#define M_SEQNO_GET(m) ((m)->m_pkthdr.tso_segsz) + ((m)->m_pkthdr.tso_segsz = ((seqno) % IEEE80211_SEQ_RANGE)) +#define M_SEQNO_GET(m) (((m)->m_pkthdr.tso_segsz) % IEEE80211_SEQ_RANGE) #define MTAG_ABI_NET80211 1132948340 /* net80211 ABI */ @@ -417,8 +434,7 @@ MODULE_DEPEND(wlan_##name, wlan, 1, 1, 1) /* * Crypto modules implement cipher support. */ -#define IEEE80211_CRYPTO_MODULE(name, version) \ -_IEEE80211_POLICY_MODULE(crypto, name, version); \ +#define IEEE80211_CRYPTO_MODULE_ADD(name) \ static void \ name##_modevent(int type) \ { \ @@ -429,6 +445,10 @@ name##_modevent(int type) \ } \ TEXT_SET(crypto##_set, name##_modevent) +#define IEEE80211_CRYPTO_MODULE(name, version) \ + _IEEE80211_POLICY_MODULE(crypto, name, version); \ + IEEE80211_CRYPTO_MODULE_ADD(name) + /* * Scanner modules provide scanning policy. */ @@ -535,6 +555,21 @@ struct debugnet80211_methods { #define DEBUGNET80211_SET(ic, driver) #endif /* DEBUGNET */ +void ieee80211_vap_sync_mac_address(struct ieee80211vap *); +void ieee80211_vap_copy_mac_address(struct ieee80211vap *); +void ieee80211_vap_deliver_data(struct ieee80211vap *, struct mbuf *); +bool ieee80211_vap_ifp_check_is_monitor(struct ieee80211vap *); +bool ieee80211_vap_ifp_check_is_simplex(struct ieee80211vap *); +bool ieee80211_vap_ifp_check_is_running(struct ieee80211vap *); +void ieee80211_vap_ifp_set_running_state(struct ieee80211vap *, bool); +const uint8_t * ieee80211_vap_get_broadcast_address(struct ieee80211vap *); + +void net80211_printf(const char *fmt, ...) __printflike(1, 2); +void net80211_vap_printf(const struct ieee80211vap *, const char *fmt, ...) + __printflike(2, 3); +void net80211_ic_printf(const struct ieee80211com *, const char *fmt, ...) + __printflike(2, 3); + #endif /* _KERNEL */ /* XXX this stuff belongs elsewhere */ diff --git a/lib/libc/include/generic-freebsd/net80211/ieee80211_ht.h b/lib/libc/include/generic-freebsd/net80211/ieee80211_ht.h index 878215910104..5f51a78906bf 100644 --- a/lib/libc/include/generic-freebsd/net80211/ieee80211_ht.h +++ b/lib/libc/include/generic-freebsd/net80211/ieee80211_ht.h @@ -87,7 +87,8 @@ struct ieee80211_tx_ampdu { (IEEE80211_AGGR_RUNNING|IEEE80211_AGGR_XCHGPEND|IEEE80211_AGGR_NAK)) != 0) #define IEEE80211_AGGR_BITS \ - "\20\1IMMEDIATE\2XCHGPEND\3RUNNING\4SETUP\5NAK" + "\20\1IMMEDIATE\2XCHGPEND\3RUNNING\4SETUP\5NAK" \ + "\6BARPEND\7WAITRX\10AMSDU" /* * Traffic estimator support. We estimate packets/sec for @@ -240,5 +241,11 @@ int ieee80211_ampdu_tx_request_ext(struct ieee80211_node *ni, int tid); int ieee80211_ampdu_tx_request_active_ext(struct ieee80211_node *ni, int tid, int status); void ieee80211_htinfo_notify(struct ieee80211vap *vap); +int ieee80211_ht_get_node_ampdu_density(const struct ieee80211_node *ni); +int ieee80211_ht_get_node_ampdu_limit(const struct ieee80211_node *ni); +bool ieee80211_ht_check_tx_shortgi_20(const struct ieee80211_node *ni); +bool ieee80211_ht_check_tx_shortgi_40(const struct ieee80211_node *ni); +bool ieee80211_ht_check_tx_ht40(const struct ieee80211_node *ni); +bool ieee80211_ht_check_tx_ht(const struct ieee80211_node *ht); #endif /* _NET80211_IEEE80211_HT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/net80211/ieee80211_ioctl.h b/lib/libc/include/generic-freebsd/net80211/ieee80211_ioctl.h index 44567d5d6bb1..37c490e1c479 100644 --- a/lib/libc/include/generic-freebsd/net80211/ieee80211_ioctl.h +++ b/lib/libc/include/generic-freebsd/net80211/ieee80211_ioctl.h @@ -253,6 +253,14 @@ struct ieee80211_stats { uint32_t is_ff_encapfail; /* failed FF encap */ uint32_t is_amsdu_encapfail; /* failed A-MSDU encap */ + uint32_t is_crypto_gcmp; /* gcmp crypto done in s/w */ + uint32_t is_rx_gcmpreplay; /* rx seq# violation (GCMP) */ + uint32_t is_rx_gcmpformat; /* rx format bad (GCMP) */ + uint32_t is_rx_gcmpmic; /* rx MIC check failed (GCMP) */ + uint32_t is_crypto_gcmp_nomem; /* gcmp crypto failed; no mem */ + uint32_t is_crypto_gcmp_nospc; /* gcmp crypto failed; no mbuf space */ + uint32_t is_crypto_swcipherfail; /* no support for SW cipher */ + uint32_t is_spare[5]; }; @@ -551,13 +559,13 @@ struct ieee80211_regdomain_req { IEEE80211_REGDOMAIN_SIZE((_req)->chaninfo.ic_nchans) /* - * Get driver capabilities. Driver, hardware crypto, and + * Get driver capabilities. Driver, hardware/software crypto, and * HT/802.11n capabilities, and a table that describes what * the radio can do. */ struct ieee80211_devcaps_req { uint32_t dc_drivercaps; /* general driver caps */ - uint32_t dc_cryptocaps; /* hardware crypto support */ + uint32_t dc_cryptocaps; /* software + hardware crypto support */ uint32_t dc_htcaps; /* HT/802.11n support */ uint32_t dc_vhtcaps; /* VHT/802.11ac capabilities */ struct ieee80211req_chaninfo dc_chaninfo; diff --git a/lib/libc/include/generic-freebsd/net80211/ieee80211_node.h b/lib/libc/include/generic-freebsd/net80211/ieee80211_node.h index 1a7f4db634e7..927fb329f22f 100644 --- a/lib/libc/include/generic-freebsd/net80211/ieee80211_node.h +++ b/lib/libc/include/generic-freebsd/net80211/ieee80211_node.h @@ -108,6 +108,69 @@ enum ieee80211_mesh_mlstate { #define IEEE80211_MESH_MLSTATE_BITS \ "\20\1IDLE\2OPENSNT\2OPENRCV\3CONFIRMRCV\4ESTABLISHED\5HOLDING" +/* + * This enum was shared with the LinuxKPI enum ieee80211_sta_rx_bandwidth + * describing up-to which channel width the station can receive. + * Rather than using hardcoded MHz values for the channel width use an enum with + * flags. This allows us to keep the uint8_t slot for ni_chw in + * struct ieee80211_node it means we do not have to sync to the value for + * LinuxKPI (just the names). + * + * NB: BW_20 needs to 0 and values need to be sorted! Cannot make it + * bitfield-alike for use with %b. + */ +enum net80211_sta_rx_bw { + NET80211_STA_RX_BW_20 = 0x00, + NET80211_STA_RX_BW_40, + NET80211_STA_RX_BW_80, + NET80211_STA_RX_BW_160, + NET80211_STA_RX_BW_320, +} __packed; + +static inline const char * +net80211_ni_chw_to_str(enum net80211_sta_rx_bw bw) +{ + switch (bw) { + case NET80211_STA_RX_BW_20: return ("BW_20"); + case NET80211_STA_RX_BW_40: return ("BW_40"); + case NET80211_STA_RX_BW_80: return ("BW_80"); + case NET80211_STA_RX_BW_160: return ("BW_160"); + case NET80211_STA_RX_BW_320: return ("BW_320"); + } +} + +enum ieee80211_node_txrate_type { + IEEE80211_NODE_TXRATE_UNDEFINED = 0, + IEEE80211_NODE_TXRATE_LEGACY = 1, /* CCK/OFDM, HT for now */ + IEEE80211_NODE_TXRATE_HT = 2, /* HT */ + IEEE80211_NODE_TXRATE_VHT = 3, /* VHT */ +}; + +struct ieee80211_node_txrate { + enum ieee80211_node_txrate_type type; + uint8_t nss; /* VHT - number of spatial streams */ + uint8_t mcs; /* HT/VHT - MCS */ + uint8_t dot11rate; /* Legacy/HT - dot11rate / ratecode */ +}; + +#define IEEE80211_NODE_TXRATE_INIT_LEGACY(rate) \ + (struct ieee80211_node_txrate) { .type = IEEE80211_NODE_TXRATE_LEGACY, \ + .nss = 0, \ + .mcs = 0, \ + .dot11rate = (rate) } + +#define IEEE80211_NODE_TXRATE_INIT_HT(i_mcs) \ + (struct ieee80211_node_txrate) { .type = IEEE80211_NODE_TXRATE_HT, \ + .nss = 0, \ + .mcs = (i_mcs), \ + .dot11rate = (i_mcs) | IEEE80211_RATE_MCS } + +#define IEEE80211_NODE_TXRATE_INIT_VHT(i_nss, i_mcs) \ + (struct ieee80211_node_txrate) { .type = IEEE80211_NODE_TXRATE_VHT, \ + .nss = (i_nss), \ + .mcs = (i_mcs), \ + .dot11rate = 0 } + /* * Node specific information. Note that drivers are expected * to derive from this structure to add device-specific per-node @@ -222,15 +285,15 @@ struct ieee80211_node { uint8_t ni_ht2ndchan; /* HT 2nd channel */ uint8_t ni_htopmode; /* HT operating mode */ uint8_t ni_htstbc; /* HT */ - uint8_t ni_chw; /* negotiated channel width */ + enum net80211_sta_rx_bw ni_chw; /* negotiated channel width */ struct ieee80211_htrateset ni_htrates; /* negotiated ht rate set */ struct ieee80211_tx_ampdu ni_tx_ampdu[WME_NUM_TID]; struct ieee80211_rx_ampdu ni_rx_ampdu[WME_NUM_TID]; /* VHT state */ uint32_t ni_vhtcap; - uint16_t ni_vht_basicmcs; - uint16_t ni_vht_pad2; + uint16_t ni_vht_basicmcs; /* Basic VHT MCS bitmap from IE */ + uint16_t ni_vht_tx_map; /* Negotiated MCS TX map with peer */ struct ieee80211_vht_mcs_info ni_vht_mcsinfo; uint8_t ni_vht_chan1; /* 20/40/80/160 - VHT chan1 */ uint8_t ni_vht_chan2; /* 80+80 - VHT chan2 */ @@ -244,7 +307,7 @@ struct ieee80211_node { /* others */ short ni_inact; /* inactivity mark count */ short ni_inact_reload;/* inactivity reload value */ - int ni_txrate; /* legacy rate/MCS */ + struct ieee80211_node_txrate ni_txrate; /* current transmit rate */ struct ieee80211_psq ni_psq; /* power save queue */ struct ieee80211_nodestats ni_stats; /* per-node statistics */ @@ -279,7 +342,7 @@ MALLOC_DECLARE(M_80211_NODE_IE); #define IEEE80211_NODE_BITS \ "\20\1AUTH\2QOS\3ERP\5PWR_MGT\6AREF\7HT\10HTCOMPAT\11WPS\12TSN" \ "\13AMPDU_RX\14AMPDU_TX\15MIMO_PS\16MIMO_RTS\17RIFS\20SGI20\21SGI40" \ - "\22ASSOCID" + "\22ASSOCID\23AMSDU_RX\24AMSDU_TX\25VHT\26LDPC\27UAPSD" #define IEEE80211_NODE_AID(ni) IEEE80211_AID(ni->ni_associd) @@ -467,4 +530,27 @@ void ieee80211_node_join(struct ieee80211_node *,int); void ieee80211_node_leave(struct ieee80211_node *); int8_t ieee80211_getrssi(struct ieee80211vap *); void ieee80211_getsignal(struct ieee80211vap *, int8_t *, int8_t *); + +/* TX sequence space related routines */ +ieee80211_seq ieee80211_tx_seqno_fetch_incr(struct ieee80211_node *, + uint8_t); +ieee80211_seq ieee80211_tx_seqno_fetch(const struct ieee80211_node *, + uint8_t); + +/* + * Node transmit rate specific manipulation. + * + * This should eventually be refactored into its own type. + */ +uint8_t ieee80211_node_get_txrate_dot11rate(struct ieee80211_node *); +void ieee80211_node_get_txrate(struct ieee80211_node *, + struct ieee80211_node_txrate *); +void ieee80211_node_set_txrate(struct ieee80211_node *, + const struct ieee80211_node_txrate *); +void ieee80211_node_set_txrate_dot11rate(struct ieee80211_node *, uint8_t); +void ieee80211_node_set_txrate_ht_mcsrate(struct ieee80211_node *, uint8_t); +uint32_t ieee80211_node_get_txrate_kbit(struct ieee80211_node *); +void ieee80211_node_set_txrate_vht_rate(struct ieee80211_node *ni, + uint8_t nss, uint8_t mcs); + #endif /* _NET80211_IEEE80211_NODE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/net80211/ieee80211_phy.h b/lib/libc/include/generic-freebsd/net80211/ieee80211_phy.h index 44103caed983..27521544ef14 100644 --- a/lib/libc/include/generic-freebsd/net80211/ieee80211_phy.h +++ b/lib/libc/include/generic-freebsd/net80211/ieee80211_phy.h @@ -221,5 +221,14 @@ uint32_t ieee80211_compute_duration_ht(uint32_t frameLen, uint16_t rate, int streams, int isht40, int isShortGI); +enum net80211_sta_rx_bw; + +uint16_t ieee80211_phy_vht_get_mcs_mask(enum net80211_sta_rx_bw, + uint8_t); +bool ieee80211_phy_vht_validate_mcs(enum net80211_sta_rx_bw, + uint8_t, uint8_t); +uint32_t ieee80211_phy_vht_get_mcs_kbit(enum net80211_sta_rx_bw, + uint8_t, uint8_t, bool); + #endif /* _KERNEL */ #endif /* !_NET80211_IEEE80211_PHY_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/net80211/ieee80211_proto.h b/lib/libc/include/generic-freebsd/net80211/ieee80211_proto.h index e88cdbfc6734..c7a79c945be2 100644 --- a/lib/libc/include/generic-freebsd/net80211/ieee80211_proto.h +++ b/lib/libc/include/generic-freebsd/net80211/ieee80211_proto.h @@ -123,6 +123,10 @@ struct mbuf * ieee80211_ff_encap1(struct ieee80211vap *, struct mbuf *, const struct ether_header *); void ieee80211_tx_complete(struct ieee80211_node *, struct mbuf *, int); +void ieee80211_output_seqno_assign(struct ieee80211_node *, + int, struct mbuf *); +void ieee80211_output_beacon_seqno_assign(struct ieee80211_node *, + struct mbuf *); /* * The formation of ProbeResponse frames requires guidance to diff --git a/lib/libc/include/generic-freebsd/net80211/ieee80211_ratectl.h b/lib/libc/include/generic-freebsd/net80211/ieee80211_ratectl.h index bd24f42cc37d..2880e73e44d9 100644 --- a/lib/libc/include/generic-freebsd/net80211/ieee80211_ratectl.h +++ b/lib/libc/include/generic-freebsd/net80211/ieee80211_ratectl.h @@ -127,12 +127,12 @@ ieee80211_ratectl_node_deinit(struct ieee80211_node *ni) vap->iv_rate->ir_node_deinit(ni); } -static int __inline +static void __inline ieee80211_ratectl_rate(struct ieee80211_node *ni, void *arg, uint32_t iarg) { const struct ieee80211vap *vap = ni->ni_vap; - return vap->iv_rate->ir_rate(ni, arg, iarg); + vap->iv_rate->ir_rate(ni, arg, iarg); } static __inline void diff --git a/lib/libc/include/generic-freebsd/net80211/ieee80211_var.h b/lib/libc/include/generic-freebsd/net80211/ieee80211_var.h index 4aa9db39ab48..6041f28c9772 100644 --- a/lib/libc/include/generic-freebsd/net80211/ieee80211_var.h +++ b/lib/libc/include/generic-freebsd/net80211/ieee80211_var.h @@ -100,6 +100,8 @@ ((ic)->ic_flags_ext & IEEE80211_FEXT_SEQNO_OFFLOAD) #define IEEE80211_CONF_FRAG_OFFLOAD(ic) \ ((ic)->ic_flags_ext & IEEE80211_FEXT_FRAG_OFFLOAD) +#define IEEE80211_CONF_AMPDU_OFFLOAD(ic) \ + ((ic)->ic_flags_ext & IEEE80211_FEXT_AMPDU_OFFLOAD) /* * 802.11 control state is split into a common portion that maps @@ -163,8 +165,12 @@ struct ieee80211com { uint32_t ic_caps; /* capabilities */ uint32_t ic_htcaps; /* HT capabilities */ uint32_t ic_htextcaps; /* HT extended capabilities */ - uint32_t ic_cryptocaps; /* crypto capabilities */ + /* driver-supported software crypto caps */ + uint32_t ic_sw_cryptocaps; + uint32_t ic_cryptocaps; /* hardware crypto caps */ /* set of mode capabilities */ + /* driver/net80211 sw KEYMGMT capabilities */ + uint32_t ic_sw_keymgmtcaps; uint8_t ic_modecaps[IEEE80211_MODE_BYTES]; uint8_t ic_promisc; /* vap's needing promisc mode */ uint8_t ic_allmulti; /* vap's needing all multicast*/ @@ -693,13 +699,14 @@ MALLOC_DECLARE(M_80211_VAP); #define IEEE80211_FEXT_VHT 0x00400000 /* CONF: VHT support */ #define IEEE80211_FEXT_QUIET_IE 0x00800000 /* STATUS: quiet IE in a beacon has been added */ #define IEEE80211_FEXT_UAPSD 0x01000000 /* CONF: enable U-APSD */ +#define IEEE80211_FEXT_AMPDU_OFFLOAD 0x02000000 /* CONF: driver/fw handles AMPDU[-TX] itself */ #define IEEE80211_FEXT_BITS \ "\20\2INACT\3SCANWAIT\4BGSCAN\5WPS\6TSN\7SCANREQ\10RESUME" \ "\0114ADDR\12NONEPR_PR\13SWBMISS\14DFS\15DOTD\16STATEWAIT\17REINIT" \ "\20BPF\21WDSLEGACY\22PROBECHAN\23UNIQMAC\24SCAN_OFFLOAD\25SEQNO_OFFLOAD" \ "\26FRAG_OFFLOAD\27VHT" \ - "\30QUIET_IE\31UAPSD" + "\30QUIET_IE\31UAPSD\32AMPDU_OFFLOAD" /* ic_flags_ht/iv_flags_ht */ #define IEEE80211_FHT_NONHT_PR 0x00000001 /* STATUS: non-HT sta present */ @@ -728,17 +735,29 @@ MALLOC_DECLARE(M_80211_VAP); #define IEEE80211_FVEN_BITS "\20" +/* + * These flags are compared in ieee80211_setupcurchan(). + * Thus 160 should be > 80P80. + */ #define IEEE80211_FVHT_VHT 0x000000001 /* CONF: VHT supported */ #define IEEE80211_FVHT_USEVHT40 0x000000002 /* CONF: Use VHT40 */ #define IEEE80211_FVHT_USEVHT80 0x000000004 /* CONF: Use VHT80 */ -#define IEEE80211_FVHT_USEVHT160 0x000000008 /* CONF: Use VHT160 */ -#define IEEE80211_FVHT_USEVHT80P80 0x000000010 /* CONF: Use VHT 80+80 */ -#define IEEE80211_FVHT_MASK \ +#define IEEE80211_FVHT_USEVHT80P80 0x000000008 /* CONF: Use VHT 80+80 */ +#define IEEE80211_FVHT_USEVHT160 0x000000010 /* CONF: Use VHT160 */ +#define IEEE80211_FVHT_STBC_TX 0x00000020 /* CONF: STBC tx enabled */ +#define IEEE80211_FVHT_STBC_RX 0x00000040 /* CONF: STBC rx enabled */ + +#define IEEE80211_FVHT_CHANWIDTH_MASK \ (IEEE80211_FVHT_VHT | IEEE80211_FVHT_USEVHT40 | \ IEEE80211_FVHT_USEVHT80 | IEEE80211_FVHT_USEVHT160 | \ IEEE80211_FVHT_USEVHT80P80) + +#define IEEE80211_FVHT_MASK \ + (IEEE80211_FVHT_CHANWIDTH_MASK | \ + IEEE80211_FVHT_STBC_TX | IEEE80211_FVHT_STBC_RX) + #define IEEE80211_VFHT_BITS \ - "\20\1VHT\2VHT40\3VHT80\4VHT160\5VHT80P80" + "\20\1VHT\2VHT40\3VHT80\4VHT80P80\5VHT160\6STBC_TX\7STBC_RX" #define IEEE80211_COM_DETACHED 0x00000001 /* ieee80211_ifdetach called */ #define IEEE80211_COM_REF_ADD 0x00000002 /* add / remove reference */ @@ -746,9 +765,17 @@ MALLOC_DECLARE(M_80211_VAP); #define IEEE80211_COM_REF_S 1 #define IEEE80211_COM_REF_MAX (IEEE80211_COM_REF >> IEEE80211_COM_REF_S) -int ic_printf(struct ieee80211com *, const char *, ...) __printflike(2, 3); +/* TODO: Transition macro */ +#define ic_printf net80211_ic_printf + void ieee80211_ifattach(struct ieee80211com *); void ieee80211_ifdetach(struct ieee80211com *); +void ieee80211_set_software_ciphers(struct ieee80211com *, + uint32_t cipher_suite); +void ieee80211_set_hardware_ciphers(struct ieee80211com *, + uint32_t cipher_suite); +void ieee80211_set_driver_keymgmt_suites(struct ieee80211com *ic, + uint32_t keymgmt_set); int ieee80211_vap_setup(struct ieee80211com *, struct ieee80211vap *, const char name[IFNAMSIZ], int unit, enum ieee80211_opmode opmode, int flags, @@ -772,7 +799,8 @@ void ieee80211_iterate_coms(ieee80211_com_iter_func *, void *); int ieee80211_media_change(struct ifnet *); void ieee80211_media_status(struct ifnet *, struct ifmediareq *); int ieee80211_ioctl(struct ifnet *, u_long, caddr_t); -int ieee80211_rate2media(struct ieee80211com *, int, +int ieee80211_rate2media(struct ieee80211com *, + const struct ieee80211_node_txrate *, enum ieee80211_phymode); int ieee80211_media2rate(int); int ieee80211_mhz2ieee(u_int, u_int); @@ -814,6 +842,14 @@ char ieee80211_channel_type_char(const struct ieee80211_channel *c); #define ieee80211_get_home_channel(_ic) ((_ic)->ic_bsschan) #define ieee80211_get_vap_desired_channel(_iv) ((_iv)->iv_des_chan) +bool ieee80211_is_key_global(const struct ieee80211vap *vap, + const struct ieee80211_key *key); +bool ieee80211_is_key_unicast(const struct ieee80211vap *vap, + const struct ieee80211_key *key); + +bool ieee80211_is_ctl_frame_for_vap(struct ieee80211_node *, + const struct mbuf *); + void ieee80211_radiotap_attach(struct ieee80211com *, struct ieee80211_radiotap_header *th, int tlen, uint32_t tx_radiotap, @@ -976,7 +1012,7 @@ ieee80211_get_node_txpower(struct ieee80211_node *ni) * Debugging facilities compiled in when IEEE80211_DEBUG is defined. * * The intent is that any problem in the net80211 layer can be - * diagnosed by inspecting the statistics (dumped by the wlanstats + * diagnosed by inspecting the statistics (dumped by the wlanstat * program) and/or the msgs generated by net80211. Messages are * broken into functional classes and can be controlled with the * wlandebug program. Certain of these msg groups are for facilities diff --git a/lib/libc/include/generic-freebsd/net80211/ieee80211_vht.h b/lib/libc/include/generic-freebsd/net80211/ieee80211_vht.h index 20a3b6d8fe54..621c39ebc695 100644 --- a/lib/libc/include/generic-freebsd/net80211/ieee80211_vht.h +++ b/lib/libc/include/generic-freebsd/net80211/ieee80211_vht.h @@ -40,8 +40,7 @@ void ieee80211_parse_vhtcap(struct ieee80211_node *, const uint8_t *); int ieee80211_vht_updateparams(struct ieee80211_node *, const uint8_t *, const uint8_t *); -void ieee80211_setup_vht_rates(struct ieee80211_node *, - const uint8_t *, const uint8_t *); +void ieee80211_setup_vht_rates(struct ieee80211_node *); void ieee80211_vht_timeout(struct ieee80211vap *vap); @@ -53,8 +52,7 @@ uint8_t * ieee80211_add_vhtinfo(uint8_t *frm, struct ieee80211_node *); uint8_t *ieee80211_add_vhtcap_ch(uint8_t *, struct ieee80211vap *, struct ieee80211_channel *); -void ieee80211_vht_update_cap(struct ieee80211_node *, - const uint8_t *, const uint8_t *); +void ieee80211_vht_update_cap(struct ieee80211_node *, const uint8_t *); struct ieee80211_channel * ieee80211_vht_adjust_channel(struct ieee80211com *, @@ -65,4 +63,10 @@ void ieee80211_vht_get_vhtcap_ie(struct ieee80211_node *ni, void ieee80211_vht_get_vhtinfo_ie(struct ieee80211_node *ni, struct ieee80211_vht_operation *, int); +bool ieee80211_vht_check_tx_vht(const struct ieee80211_node *); +bool ieee80211_vht_check_tx_bw(const struct ieee80211_node *, + enum net80211_sta_rx_bw); +bool ieee80211_vht_node_check_tx_valid_mcs(const struct ieee80211_node *, + enum net80211_sta_rx_bw bw, uint8_t, uint8_t); + #endif /* _NET80211_IEEE80211_VHT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/netdb.h b/lib/libc/include/generic-freebsd/netdb.h index 3a3c6033a652..8b2eda8b0ac9 100644 --- a/lib/libc/include/generic-freebsd/netdb.h +++ b/lib/libc/include/generic-freebsd/netdb.h @@ -51,7 +51,6 @@ */ /* - * @(#)netdb.h 8.1 (Berkeley) 6/2/93 * From: Id: netdb.h,v 8.9 1996/11/19 08:39:29 vixie Exp $ */ diff --git a/lib/libc/include/generic-freebsd/netgraph/bluetooth/include/ng_btsocket_hci_raw.h b/lib/libc/include/generic-freebsd/netgraph/bluetooth/include/ng_btsocket_hci_raw.h index cc9b546ee661..81af1bdc97e0 100644 --- a/lib/libc/include/generic-freebsd/netgraph/bluetooth/include/ng_btsocket_hci_raw.h +++ b/lib/libc/include/generic-freebsd/netgraph/bluetooth/include/ng_btsocket_hci_raw.h @@ -78,11 +78,10 @@ int ng_btsocket_hci_raw_control (struct socket *, u_long, void *, int ng_btsocket_hci_raw_ctloutput (struct socket *, struct sockopt *); void ng_btsocket_hci_raw_detach (struct socket *); int ng_btsocket_hci_raw_disconnect (struct socket *); -int ng_btsocket_hci_raw_peeraddr (struct socket *, struct sockaddr **); int ng_btsocket_hci_raw_send (struct socket *, int, struct mbuf *, struct sockaddr *, struct mbuf *, struct thread *); -int ng_btsocket_hci_raw_sockaddr (struct socket *, struct sockaddr **); +int ng_btsocket_hci_raw_sockaddr (struct socket *, struct sockaddr *); #endif /* _KERNEL */ diff --git a/lib/libc/include/generic-freebsd/netgraph/bluetooth/include/ng_btsocket_l2cap.h b/lib/libc/include/generic-freebsd/netgraph/bluetooth/include/ng_btsocket_l2cap.h index e0d8e6345083..6e7975a6675a 100644 --- a/lib/libc/include/generic-freebsd/netgraph/bluetooth/include/ng_btsocket_l2cap.h +++ b/lib/libc/include/generic-freebsd/netgraph/bluetooth/include/ng_btsocket_l2cap.h @@ -105,11 +105,11 @@ int ng_btsocket_l2cap_raw_control (struct socket *, u_long, void *, struct ifnet *, struct thread *); void ng_btsocket_l2cap_raw_detach (struct socket *); int ng_btsocket_l2cap_raw_disconnect (struct socket *); -int ng_btsocket_l2cap_raw_peeraddr (struct socket *, struct sockaddr **); +int ng_btsocket_l2cap_raw_peeraddr (struct socket *, struct sockaddr *); int ng_btsocket_l2cap_raw_send (struct socket *, int, struct mbuf *, struct sockaddr *, struct mbuf *, struct thread *); -int ng_btsocket_l2cap_raw_sockaddr (struct socket *, struct sockaddr **); +int ng_btsocket_l2cap_raw_sockaddr (struct socket *, struct sockaddr *); #endif /* _KERNEL */ @@ -191,7 +191,6 @@ typedef struct ng_btsocket_l2cap_pcb * ng_btsocket_l2cap_pcb_p; void ng_btsocket_l2cap_abort (struct socket *); void ng_btsocket_l2cap_close (struct socket *); -int ng_btsocket_l2cap_accept (struct socket *, struct sockaddr **); int ng_btsocket_l2cap_attach (struct socket *, int, struct thread *); int ng_btsocket_l2cap_bind (struct socket *, struct sockaddr *, struct thread *); @@ -203,11 +202,11 @@ int ng_btsocket_l2cap_ctloutput (struct socket *, struct sockopt *); void ng_btsocket_l2cap_detach (struct socket *); int ng_btsocket_l2cap_disconnect (struct socket *); int ng_btsocket_l2cap_listen (struct socket *, int, struct thread *); -int ng_btsocket_l2cap_peeraddr (struct socket *, struct sockaddr **); +int ng_btsocket_l2cap_peeraddr (struct socket *, struct sockaddr *); int ng_btsocket_l2cap_send (struct socket *, int, struct mbuf *, struct sockaddr *, struct mbuf *, struct thread *); -int ng_btsocket_l2cap_sockaddr (struct socket *, struct sockaddr **); +int ng_btsocket_l2cap_sockaddr (struct socket *, struct sockaddr *); #endif /* _KERNEL */ diff --git a/lib/libc/include/generic-freebsd/netgraph/bluetooth/include/ng_btsocket_rfcomm.h b/lib/libc/include/generic-freebsd/netgraph/bluetooth/include/ng_btsocket_rfcomm.h index 399f13390f01..1535e0849799 100644 --- a/lib/libc/include/generic-freebsd/netgraph/bluetooth/include/ng_btsocket_rfcomm.h +++ b/lib/libc/include/generic-freebsd/netgraph/bluetooth/include/ng_btsocket_rfcomm.h @@ -316,7 +316,7 @@ typedef struct ng_btsocket_rfcomm_pcb * ng_btsocket_rfcomm_pcb_p; void ng_btsocket_rfcomm_abort (struct socket *); void ng_btsocket_rfcomm_close (struct socket *); -int ng_btsocket_rfcomm_accept (struct socket *, struct sockaddr **); +int ng_btsocket_rfcomm_accept (struct socket *, struct sockaddr *); int ng_btsocket_rfcomm_attach (struct socket *, int, struct thread *); int ng_btsocket_rfcomm_bind (struct socket *, struct sockaddr *, struct thread *); @@ -328,11 +328,11 @@ int ng_btsocket_rfcomm_ctloutput (struct socket *, struct sockopt *); void ng_btsocket_rfcomm_detach (struct socket *); int ng_btsocket_rfcomm_disconnect (struct socket *); int ng_btsocket_rfcomm_listen (struct socket *, int, struct thread *); -int ng_btsocket_rfcomm_peeraddr (struct socket *, struct sockaddr **); +int ng_btsocket_rfcomm_peeraddr (struct socket *, struct sockaddr *); int ng_btsocket_rfcomm_send (struct socket *, int, struct mbuf *, struct sockaddr *, struct mbuf *, struct thread *); -int ng_btsocket_rfcomm_sockaddr (struct socket *, struct sockaddr **); +int ng_btsocket_rfcomm_sockaddr (struct socket *, struct sockaddr *); #endif /* _KERNEL */ diff --git a/lib/libc/include/generic-freebsd/netgraph/bluetooth/include/ng_btsocket_sco.h b/lib/libc/include/generic-freebsd/netgraph/bluetooth/include/ng_btsocket_sco.h index 14d364c07502..39d1644e1e4d 100644 --- a/lib/libc/include/generic-freebsd/netgraph/bluetooth/include/ng_btsocket_sco.h +++ b/lib/libc/include/generic-freebsd/netgraph/bluetooth/include/ng_btsocket_sco.h @@ -106,7 +106,7 @@ typedef struct ng_btsocket_sco_pcb * ng_btsocket_sco_pcb_p; void ng_btsocket_sco_abort (struct socket *); void ng_btsocket_sco_close (struct socket *); -int ng_btsocket_sco_accept (struct socket *, struct sockaddr **); +int ng_btsocket_sco_accept (struct socket *, struct sockaddr *); int ng_btsocket_sco_attach (struct socket *, int, struct thread *); int ng_btsocket_sco_bind (struct socket *, struct sockaddr *, struct thread *); @@ -118,11 +118,11 @@ int ng_btsocket_sco_ctloutput (struct socket *, struct sockopt *); void ng_btsocket_sco_detach (struct socket *); int ng_btsocket_sco_disconnect (struct socket *); int ng_btsocket_sco_listen (struct socket *, int, struct thread *); -int ng_btsocket_sco_peeraddr (struct socket *, struct sockaddr **); +int ng_btsocket_sco_peeraddr (struct socket *, struct sockaddr *); int ng_btsocket_sco_send (struct socket *, int, struct mbuf *, struct sockaddr *, struct mbuf *, struct thread *); -int ng_btsocket_sco_sockaddr (struct socket *, struct sockaddr **); +int ng_btsocket_sco_sockaddr (struct socket *, struct sockaddr *); #endif /* _KERNEL */ diff --git a/lib/libc/include/generic-freebsd/netgraph/bluetooth/include/ng_hci.h b/lib/libc/include/generic-freebsd/netgraph/bluetooth/include/ng_hci.h index 79ce0160340f..8947ce1c0d19 100644 --- a/lib/libc/include/generic-freebsd/netgraph/bluetooth/include/ng_hci.h +++ b/lib/libc/include/generic-freebsd/netgraph/bluetooth/include/ng_hci.h @@ -114,6 +114,8 @@ #define NG_HCI_LMP_FLOW_CONTROL_LAG0 0x10 #define NG_HCI_LMP_FLOW_CONTROL_LAG1 0x20 #define NG_HCI_LMP_FLOW_CONTROL_LAG2 0x40 +/* ------------------- byte 6 --------------------*/ +#define NG_HCI_LMP_SECURE_SIMPLE_PAIRING 0x08 /* Link types */ #define NG_HCI_LINK_SCO 0x00 /* Voice */ @@ -446,7 +448,7 @@ typedef struct { typedef bdaddr_t * bdaddr_p; /* Any BD_ADDR. Note: This is actually 7 bytes (count '\0' terminator) */ -#define NG_HCI_BDADDR_ANY ((bdaddr_p) "\000\000\000\000\000\000") +#define NG_HCI_BDADDR_ANY (&(const bdaddr_t){"\000\000\000\000\000\000"}) /* HCI status return parameter */ typedef struct { @@ -860,6 +862,50 @@ typedef struct { } __attribute__ ((packed)) ng_hci_read_clock_offset_cp; /* No return parameter(s) */ +#define NG_HCI_IO_CAPABILITY_REQUEST_REPLY 0x002b +typedef struct { + bdaddr_t bdaddr; + u_int8_t io_capability; + u_int8_t oob_data_present; + u_int8_t authentication_requirements; +} __attribute__ ((packed)) ng_hci_io_capability_request_reply_cp; + +typedef struct { + u_int8_t status; + bdaddr_t bdaddr; +} __attribute__ ((packed)) ng_hci_io_capability_request_reply_rp; + +#define NG_HCI_USER_CONFIRMATION_REQUEST_REPLY 0x002c +typedef struct { + bdaddr_t bdaddr; +} __attribute__ ((packed)) ng_hci_user_confirmation_request_reply_cp; + +typedef struct { + u_int8_t status; + bdaddr_t bdaddr; +} __attribute__ ((packed)) ng_hci_user_confirmation_request_reply_rp; + +#define NG_HCI_USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY 0x002d +typedef struct { + bdaddr_t bdaddr; +} __attribute__((packed)) ng_hci_user_confirmation_request_negative_reply_cp; + +typedef struct { + u_int8_t status; + bdaddr_t bdaddr; +} __attribute__ ((packed)) ng_hci_user_confirmation_request_negative_reply_rp; + +#define NG_HCI_IO_CAPABILITY_REQUEST_NEGATIVE_REPLY 0x0034 +typedef struct { + bdaddr_t bdaddr; + u_int8_t reason; +} __attribute__ ((packed)) ng_hci_io_capability_request_negative_reply_cp; + +typedef struct { + u_int8_t status; + bdaddr_t bdaddr; +} __attribute__ ((packed)) ng_hci_io_capability_request_negative_reply_rp; + /************************************************************************** ************************************************************************** ** Link policy commands and return parameters @@ -1374,6 +1420,13 @@ typedef struct { typedef ng_hci_status_rp ng_hci_write_page_scan_rp; +#define NG_HCI_OCF_WRITE_SIMPLE_PAIRING 0x0056 +typedef struct { + u_int8_t simple_pairing; /* 1 -> enabled, 0 -> disabled */ +} __attribute__ ((packed)) ng_hci_write_simple_pairing_cp; + +typedef ng_hci_status_rp ng_hci_write_simple_pairing_rp; + #define NG_HCI_OCF_READ_LE_HOST_SUPPORTED 0x6c typedef struct { u_int8_t status; /* 0x00 - success */ @@ -1389,6 +1442,13 @@ typedef struct { typedef ng_hci_status_rp ng_hci_write_le_host_supported_rp; +#define NG_HCI_OCF_WRITE_SECURE_CONNECTIONS_HOST_SUPPORT 0x007a +typedef struct { + u_int8_t support; /* 0 - disabled, 1 - enabled */ +} __attribute__ ((packed)) ng_hci_write_secure_connections_host_support_cp; + +typedef ng_hci_status_rp ng_hci_write_secure_connections_host_support_rp; + /************************************************************************** ************************************************************************** ** Informational commands and return parameters @@ -2025,6 +2085,24 @@ typedef struct { bdaddr_t bdaddr; /* destination address */ u_int8_t page_scan_rep_mode; /* page scan repetition mode */ } __attribute__ ((packed)) ng_hci_page_scan_rep_mode_change_ep; + +#define NG_HCI_EVENT_IO_CAPABILITY_REQUEST 0x31 +typedef struct { + bdaddr_t bdaddr; +} __attribute__ ((packed)) ng_hci_io_capability_request_ep; + +#define NG_HCI_EVENT_USER_CONFIRMATION_REQUEST 0x33 +typedef struct { + bdaddr_t bdaddr; + u_int32_t numeric_value; +} __attribute__ ((packed)) ng_hci_user_confirmation_request_ep; + +#define NG_HCI_EVENT_SIMPLE_PAIRING_COMPLETE 0x36 +typedef struct { + u_int8_t status; + bdaddr_t bdaddr; +} __attribute__ ((packed)) ng_hci_simple_pairing_complete_ep; + #define NG_HCI_EVENT_LE 0x3e typedef struct { u_int8_t subevent_code; diff --git a/lib/libc/include/generic-freebsd/netgraph/netflow/ng_netflow.h b/lib/libc/include/generic-freebsd/netgraph/netflow/ng_netflow.h index f7d914a015b9..8ceee7765238 100644 --- a/lib/libc/include/generic-freebsd/netgraph/netflow/ng_netflow.h +++ b/lib/libc/include/generic-freebsd/netgraph/netflow/ng_netflow.h @@ -259,7 +259,7 @@ struct flow_entry_data { u_long bytes; long first; /* uptime on first packet */ long last; /* uptime on last packet */ - u_char tcp_flags; /* cumulative OR */ + uint16_t tcp_flags; /* cumulative OR */ }; struct flow6_entry_data { @@ -277,7 +277,7 @@ struct flow6_entry_data { u_long bytes; long first; /* uptime on first packet */ long last; /* uptime on last packet */ - u_char tcp_flags; /* cumulative OR */ + uint16_t tcp_flags; /* cumulative OR */ }; /* diff --git a/lib/libc/include/generic-freebsd/netgraph/netgraph.h b/lib/libc/include/generic-freebsd/netgraph/netgraph.h index 406419032f4a..2561b72f624d 100644 --- a/lib/libc/include/generic-freebsd/netgraph/netgraph.h +++ b/lib/libc/include/generic-freebsd/netgraph/netgraph.h @@ -69,11 +69,20 @@ * modules. */ #define _NG_ABI_VERSION 12 -#ifdef NETGRAPH_DEBUG /*----------------------------------------------*/ -#define NG_ABI_VERSION (_NG_ABI_VERSION + 0x10000) -#else /* NETGRAPH_DEBUG */ /*----------------------------------------------*/ -#define NG_ABI_VERSION _NG_ABI_VERSION -#endif /* NETGRAPH_DEBUG */ /*----------------------------------------------*/ + +#ifdef NETGRAPH_DEBUG +#define _NG_ABI_PREFIX1 0x10000 +#else +#define _NG_ABI_PREFIX1 0 +#endif + +#ifdef INVARIANTS +#define _NG_ABI_PREFIX2 0x20000 +#else +#define _NG_ABI_PREFIX2 0 +#endif + +#define NG_ABI_VERSION (_NG_ABI_PREFIX1 + _NG_ABI_PREFIX2 + _NG_ABI_VERSION) /* * Forward references for the basic structures so we can diff --git a/lib/libc/include/generic-freebsd/netgraph/ng_message.h b/lib/libc/include/generic-freebsd/netgraph/ng_message.h index 74b19ce59a66..8781253ed0a1 100644 --- a/lib/libc/include/generic-freebsd/netgraph/ng_message.h +++ b/lib/libc/include/generic-freebsd/netgraph/ng_message.h @@ -42,7 +42,10 @@ #ifndef _NETGRAPH_NG_MESSAGE_H_ #define _NETGRAPH_NG_MESSAGE_H_ -/* ASCII string size limits */ +/* + * ASCII string size limits + * Check with struct sockaddr_ng if changing. + */ #define NG_TYPESIZ 32 /* max type name len (including null) */ #define NG_HOOKSIZ 32 /* max hook name len (including null) */ #define NG_NODESIZ 32 /* max node name len (including null) */ diff --git a/lib/libc/include/generic-freebsd/netgraph/ng_nat.h b/lib/libc/include/generic-freebsd/netgraph/ng_nat.h index fbdbcf646df4..47823930b09e 100644 --- a/lib/libc/include/generic-freebsd/netgraph/ng_nat.h +++ b/lib/libc/include/generic-freebsd/netgraph/ng_nat.h @@ -53,6 +53,7 @@ struct ng_nat_mode { #define NG_NAT_PROXY_ONLY 0x40 #define NG_NAT_REVERSE 0x80 #define NG_NAT_UNREGISTERED_CGN 0x100 +#define NG_NAT_UDP_EIM 0x200 #define NG_NAT_DESC_LENGTH 64 #define NG_NAT_REDIRPROTO_ADDR (IPPROTO_MAX + 3) /* LibAlias' LINK_ADDR, also unused in in.h */ diff --git a/lib/libc/include/generic-freebsd/netgraph/ng_socket.h b/lib/libc/include/generic-freebsd/netgraph/ng_socket.h index 5244d03e7f86..2dc386bd8ea3 100644 --- a/lib/libc/include/generic-freebsd/netgraph/ng_socket.h +++ b/lib/libc/include/generic-freebsd/netgraph/ng_socket.h @@ -60,7 +60,7 @@ enum { struct sockaddr_ng { unsigned char sg_len; /* total length */ sa_family_t sg_family; /* address family */ - char sg_data[14]; /* actually longer; address value */ + char sg_data[32]; /* see NG_NODESIZ in ng_message.h */ }; #endif /* _NETGRAPH_NG_SOCKET_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/netinet/cc/cc.h b/lib/libc/include/generic-freebsd/netinet/cc/cc.h index 48472f8fd332..e04dfcfc17de 100644 --- a/lib/libc/include/generic-freebsd/netinet/cc/cc.h +++ b/lib/libc/include/generic-freebsd/netinet/cc/cc.h @@ -87,21 +87,12 @@ int cc_deregister_algo(struct cc_algo *remove_cc); #endif /* _KERNEL */ #if defined(_KERNEL) || defined(_WANT_TCPCB) -/* - * Wrapper around transport structs that contain same-named congestion - * control variables. Allows algos to be shared amongst multiple CC aware - * transprots. - */ struct cc_var { void *cc_data; /* Per-connection private CC algorithm data. */ int bytes_this_ack; /* # bytes acked by the current ACK. */ tcp_seq curack; /* Most recent ACK. */ uint32_t flags; /* Flags for cc_var (see below) */ - int type; /* Indicates which ptr is valid in ccvc. */ - union ccv_container { - struct tcpcb *tcp; - struct sctp_nets *sctp; - } ccvc; + struct tcpcb *tp; /* Pointer to tcpcb */ uint16_t nsegs; /* # segments coalesced into current chain. */ uint8_t labc; /* Dont use system abc use passed in */ }; @@ -113,32 +104,34 @@ struct cc_var { #define CCF_ACKNOW 0x0008 /* Will this ack be sent now? */ #define CCF_IPHDR_CE 0x0010 /* Does this packet set CE bit? */ #define CCF_TCPHDR_CWR 0x0020 /* Does this packet set CWR bit? */ -#define CCF_MAX_CWND 0x0040 /* Have we reached maximum cwnd? */ -#define CCF_CHG_MAX_CWND 0x0080 /* CUBIC max_cwnd changed, for K */ -#define CCF_USR_IWND 0x0100 /* User specified initial window */ -#define CCF_USR_IWND_INIT_NSEG 0x0200 /* Convert segs to bytes on conn init */ +#define CCF_UNUSED1 0x0040 +#define CCF_UNUSED2 0x0080 +#define CCF_UNUSED3 0x0100 +#define CCF_UNUSED4 0x0200 #define CCF_HYSTART_ALLOWED 0x0400 /* If the CC supports it Hystart is allowed */ #define CCF_HYSTART_CAN_SH_CWND 0x0800 /* Can hystart when going CSS -> CA slam the cwnd */ #define CCF_HYSTART_CONS_SSTH 0x1000 /* Should hystart use the more conservative ssthresh */ -/* ACK types passed to the ack_received() hook. */ -#define CC_ACK 0x0001 /* Regular in sequence ACK. */ -#define CC_DUPACK 0x0002 /* Duplicate ACK. */ -#define CC_PARTIALACK 0x0004 /* Not yet. */ -#define CC_SACK 0x0008 /* Not yet. */ #endif /* defined(_KERNEL) || defined(_WANT_TCPCB) */ - -/* - * Congestion signal types passed to the cong_signal() hook. The highest order 8 - * bits (0x01000000 - 0x80000000) are reserved for CC algos to declare their own - * congestion signal types. - */ -#define CC_ECN 0x00000001 /* ECN marked packet received. */ -#define CC_RTO 0x00000002 /* RTO fired. */ -#define CC_RTO_ERR 0x00000004 /* RTO fired in error. */ -#define CC_NDUPACK 0x00000008 /* Threshold of dupack's reached. */ - -#define CC_SIGPRIVMASK 0xFF000000 /* Mask to check if sig is private. */ +typedef enum { +#if defined(_KERNEL) || defined(_WANT_TCPCB) + /* ACK types passed to the ack_received() hook. */ + CC_ACK = 0x0001, /* Regular in sequence ACK. */ + CC_DUPACK = 0x0002, /* Duplicate ACK. */ + CC_PARTIALACK = 0x0004, /* Not yet. */ + CC_SACK = 0x0008, /* Not yet. */ +#endif /* defined(_KERNEL) || defined(_WANT_TCPCB) */ + /* Congestion signal types passed to the cong_signal() hook. */ + CC_ECN = 0x0100, /* ECN marked packet received. */ + CC_RTO = 0x0200, /* RTO fired. */ + CC_RTO_ERR = 0x0400, /* RTO fired in error. */ + CC_NDUPACK = 0x0800, /* Threshold of dupack's reached. */ + /* + * The highest order 8 bits (0x01000000 - 0x80000000) are reserved + * for CC algos to declare their own congestion signal types. + */ + CC_SIGPRIVMASK = 0xFF000000 /* Mask to check if sig is private. */ +} ccsignal_t; #ifdef _KERNEL /* @@ -175,10 +168,10 @@ struct cc_algo { void (*conn_init)(struct cc_var *ccv); /* Called on receipt of an ack. */ - void (*ack_received)(struct cc_var *ccv, uint16_t type); + void (*ack_received)(struct cc_var *ccv, ccsignal_t type); /* Called on detection of a congestion signal. */ - void (*cong_signal)(struct cc_var *ccv, uint32_t type); + void (*cong_signal)(struct cc_var *ccv, ccsignal_t type); /* Called after exiting congestion recovery. */ void (*post_recovery)(struct cc_var *ccv); @@ -236,8 +229,11 @@ extern struct rwlock cc_list_lock; */ void newreno_cc_post_recovery(struct cc_var *); void newreno_cc_after_idle(struct cc_var *); -void newreno_cc_cong_signal(struct cc_var *, uint32_t ); -void newreno_cc_ack_received(struct cc_var *, uint16_t); +void newreno_cc_cong_signal(struct cc_var *, ccsignal_t); +void newreno_cc_ack_received(struct cc_var *, ccsignal_t); +u_int newreno_cc_cwnd_on_multiplicative_decrease(struct cc_var *ccv, uint32_t mss); +u_int newreno_cc_cwnd_in_cong_avoid(struct cc_var *ccv); +u_int newreno_cc_cwnd_in_slow_start(struct cc_var *ccv); /* Called to temporarily keep an algo from going away during change */ void cc_refer(struct cc_algo *algo); diff --git a/lib/libc/include/generic-freebsd/netinet/cc/cc_cubic.h b/lib/libc/include/generic-freebsd/netinet/cc/cc_cubic.h index c9547b29f2ae..ae93df284bfa 100644 --- a/lib/libc/include/generic-freebsd/netinet/cc/cc_cubic.h +++ b/lib/libc/include/generic-freebsd/netinet/cc/cc_cubic.h @@ -83,26 +83,28 @@ #define CUBICFLAG_RTO_EVENT 0x00000008 /* RTO experienced */ #define CUBICFLAG_HYSTART_ENABLED 0x00000010 /* Hystart++ is enabled */ #define CUBICFLAG_HYSTART_IN_CSS 0x00000020 /* We are in Hystart++ CSS */ +#define CUBICFLAG_IN_TF 0x00000040 /* We are in TCP friendly region */ /* Kernel only bits */ #ifdef _KERNEL struct cubic { - /* CUBIC K in fixed point form with CUBIC_SHIFT worth of precision. */ + /* + * CUBIC K in fixed point form with CUBIC_SHIFT worth of precision. + * Also means the time period in seconds it takes to increase the + * congestion window size at the beginning of the current congestion + * avoidance stage to W_max. + */ int64_t K; /* Sum of RTT samples across an epoch in usecs. */ int64_t sum_rtt_usecs; - /* Size of cwnd just before cwnd was reduced in the last congestion event */ - uint64_t W_max; - /* An estimate for the congestion window in the Reno-friendly region */ - uint64_t W_est; - /* The cwnd at the beginning of the current congestion avoidance stage */ - uint64_t cwnd_epoch; - /* - * Size of cwnd at the time of setting ssthresh most recently, - * either upon exiting the first slow start, or just before cwnd - * was reduced in the last congestion event - */ - uint64_t cwnd_prior; + /* Size of cwnd (in bytes) just before cwnd was reduced in the last congestion event. */ + uint32_t W_max; + /* An estimate (in bytes) for the congestion window in the Reno-friendly region */ + uint32_t W_est; + /* An estimate (in bytes) for the congestion window in the CUBIC region */ + uint32_t W_cubic; + /* The cwnd (in bytes) at the beginning of the current congestion avoidance stage. */ + uint32_t cwnd_epoch; /* various flags */ uint32_t flags; /* Minimum observed rtt in usecs. */ @@ -117,12 +119,8 @@ struct cubic { int undo_t_epoch; /* Few variables to restore the state after RTO_ERR */ int64_t undo_K; - uint64_t undo_cwnd_prior; - uint64_t undo_W_max; - uint64_t undo_W_est; - uint64_t undo_cwnd_epoch; - /* Number of congestion events experienced */ - uint64_t num_cong_events; + uint32_t undo_W_max; + uint32_t undo_cwnd_epoch; uint32_t css_baseline_minrtt; uint32_t css_current_round_minrtt; uint32_t css_lastround_minrtt; @@ -141,60 +139,103 @@ struct cubic { extern int hz; /* - * Implementation based on the formulae found in the CUBIC Internet Draft - * "draft-ietf-tcpm-cubic-04". + * Implementation based on the formulas in RFC9438. * */ -static __inline float -theoretical_cubic_k(double wmax_pkts) + +/* + * Returns K, the time period in seconds it takes to increase the congestion + * window size at the beginning of the current congestion avoidance stage to + * W_max. + */ +static inline float +theoretical_cubic_k(uint32_t wmax_segs, uint32_t cwnd_epoch_segs) { double C; C = 0.4; + if (wmax_segs <= cwnd_epoch_segs) + return 0.0; - return (pow((wmax_pkts * 0.3) / C, (1.0 / 3.0)) * pow(2, CUBIC_SHIFT)); + /* + * Figure 2: K = ((W_max - cwnd_epoch) / C)^(1/3) + */ + return (pow((wmax_segs - cwnd_epoch_segs) / C, (1.0 / 3.0)) * pow(2, CUBIC_SHIFT)); } -static __inline unsigned long -theoretical_cubic_cwnd(int ticks_since_epoch, unsigned long wmax, uint32_t smss) +/* + * Returns the congestion window in segments at time t in seconds based on the + * cubic increase function, where t is the elapsed time in seconds from the + * beginning of the current congestion avoidance stage, as described in RFC9438 + * Section 4.2. + */ +static inline unsigned long +theoretical_cubic_cwnd(int ticks_elapsed, uint32_t wmax_segs, uint32_t cwnd_epoch_segs) { - double C, wmax_pkts; + double C, t; + float K; C = 0.4; - wmax_pkts = wmax / (double)smss; + t = ticks_elapsed / (double)hz; + K = theoretical_cubic_k(wmax_segs, cwnd_epoch_segs); - return (smss * (wmax_pkts + - (C * pow(ticks_since_epoch / (double)hz - - theoretical_cubic_k(wmax_pkts) / pow(2, CUBIC_SHIFT), 3.0)))); + /* + * Figure 1: W_cubic(t) = C * (t - K)^3 + W_max + */ + return (C * pow(t - K / pow(2, CUBIC_SHIFT), 3.0) + wmax_segs); } -static __inline unsigned long -theoretical_reno_cwnd(int ticks_since_epoch, int rtt_ticks, unsigned long wmax, - uint32_t smss) +/* + * Returns estimated Reno congestion window in segments. + */ +static inline unsigned long +theoretical_reno_cwnd(int ticks_elapsed, int rtt_ticks, uint32_t wmax_segs) { - return ((wmax * 0.5) + ((ticks_since_epoch / (float)rtt_ticks) * smss)); + return (wmax_segs * 0.5 + ticks_elapsed / (float)rtt_ticks); } -static __inline unsigned long -theoretical_tf_cwnd(int ticks_since_epoch, int rtt_ticks, unsigned long wmax, - uint32_t smss) +/* + * Returns an estimate for the congestion window in segments in the + * Reno-friendly region -- that is, an estimate for the congestion window of + * Reno, as described in RFC9438 Section 4.3, where: + * cwnd: Current congestion window in segments. + * cwnd_prior: Size of cwnd in segments at the time of setting ssthresh most + * recently, either upon exiting the first slow start or just before + * cwnd was reduced in the last congestion event. + * W_est: An estimate for the congestion window in segments in the Reno-friendly + * region -- that is, an estimate for the congestion window of Reno. + */ +static inline unsigned long +theoretical_tf_cwnd(unsigned long W_est, unsigned long segs_acked, unsigned long cwnd, + unsigned long cwnd_prior) { + float cubic_alpha, cubic_beta; - return ((wmax * 0.7) + ((3 * 0.3) / (2 - 0.3) * - (ticks_since_epoch / (float)rtt_ticks) * smss)); + /* RFC9438 Section 4.6: The parameter β_cubic SHOULD be set to 0.7. */ + cubic_beta = 0.7; + + if (W_est >= cwnd_prior) + cubic_alpha = 1.0; + else + cubic_alpha = (3.0 * (1.0 - cubic_beta)) / (1.0 + cubic_beta); + + /* + * Figure 4: W_est = W_est + α_cubic * segments_acked / cwnd + */ + return (W_est + cubic_alpha * segs_acked / cwnd); } #endif /* !_KERNEL */ /* * Compute the CUBIC K value used in the cwnd calculation, using an - * implementation of eqn 2 in the I-D. The method used - * here is adapted from Apple Computer Technical Report #KT-32. + * implementation mentioned in Figure. 2 of RFC9438. + * The method used here is adapted from Apple Computer Technical Report #KT-32. */ -static __inline int64_t -cubic_k(unsigned long wmax_pkts) +static inline int64_t +cubic_k(uint32_t wmax_segs, uint32_t cwnd_epoch_segs) { int64_t s, K; uint16_t p; @@ -202,8 +243,13 @@ cubic_k(unsigned long wmax_pkts) K = s = 0; p = 0; - /* (wmax * beta)/C with CUBIC_SHIFT worth of precision. */ - s = ((wmax_pkts * ONE_SUB_CUBIC_BETA) << CUBIC_SHIFT) / CUBIC_C_FACTOR; + /* Handle the corner case where W_max <= cwnd_epoch */ + if (wmax_segs <= cwnd_epoch_segs) { + return 0; + } + + /* (wmax - cwnd_epoch) / C with CUBIC_SHIFT worth of precision. */ + s = ((wmax_segs - cwnd_epoch_segs) << (2 * CUBIC_SHIFT)) / CUBIC_C_FACTOR; /* Rebase s to be between 1 and 1/8 with a shift of CUBIC_SHIFT. */ while (s >= 256) { @@ -224,13 +270,14 @@ cubic_k(unsigned long wmax_pkts) } /* - * Compute the new cwnd value using an implementation of eqn 1 from the I-D. + * Compute and return the new cwnd value in bytes using an implementation + * mentioned in Figure. 1 of RFC9438. * Thanks to Kip Macy for help debugging this function. * * XXXLAS: Characterise bounds for overflow. */ -static __inline unsigned long -cubic_cwnd(int usecs_since_epoch, unsigned long wmax, uint32_t smss, int64_t K) +static inline uint32_t +cubic_cwnd(int usecs_since_epoch, uint32_t wmax, uint32_t smss, int64_t K) { int64_t cwnd; @@ -249,7 +296,7 @@ cubic_cwnd(int usecs_since_epoch, unsigned long wmax, uint32_t smss, int64_t K) cwnd *= (cwnd * cwnd); /* - * C(t - K)^3 + wmax + * Figure 1: C * (t - K)^3 + wmax * The down shift by CUBIC_SHIFT_4 is because cwnd has 4 lots of * CUBIC_SHIFT included in the value. 3 from the cubing of cwnd above, * and an extra from multiplying through by CUBIC_C_FACTOR. @@ -264,46 +311,13 @@ cubic_cwnd(int usecs_since_epoch, unsigned long wmax, uint32_t smss, int64_t K) } /* - * Compute an approximation of the NewReno cwnd some number of usecs after a - * congestion event. RTT should be the average RTT estimate for the path - * measured over the previous congestion epoch and wmax is the value of cwnd at - * the last congestion event. The "TCP friendly" concept in the CUBIC I-D is - * rather tricky to understand and it turns out this function is not required. - * It is left here for reference. - * - * XXX: Not used + * Compute the "TCP friendly" cwnd by newreno in congestion avoidance state. */ -static __inline unsigned long -reno_cwnd(int usecs_since_epoch, int rtt_usecs, unsigned long wmax, - uint32_t smss) +static inline uint32_t +tf_cwnd(struct cc_var *ccv) { - - /* - * For NewReno, beta = 0.5, therefore: W_tcp(t) = wmax*0.5 + t/RTT - * W_tcp(t) deals with cwnd/wmax in pkts, so because our cwnd is in - * bytes, we have to multiply by smss. - */ - return (((wmax * RENO_BETA) + (((usecs_since_epoch * smss) - << CUBIC_SHIFT) / rtt_usecs)) >> CUBIC_SHIFT); -} - -/* - * Compute an approximation of the "TCP friendly" cwnd some number of usecs - * after a congestion event that is designed to yield the same average cwnd as - * NewReno while using CUBIC's beta of 0.7. RTT should be the average RTT - * estimate for the path measured over the previous congestion epoch and wmax is - * the value of cwnd at the last congestion event. - */ -static __inline unsigned long -tf_cwnd(int usecs_since_epoch, int rtt_usecs, unsigned long wmax, - uint32_t smss) -{ - - /* Equation 4 of I-D. */ - return (((wmax * CUBIC_BETA) + - (((THREE_X_PT3 * (unsigned long)usecs_since_epoch * - (unsigned long)smss) << CUBIC_SHIFT) / (TWO_SUB_PT3 * rtt_usecs))) - >> CUBIC_SHIFT); + /* newreno is "TCP friendly" */ + return newreno_cc_cwnd_in_cong_avoid(ccv); } #endif /* _NETINET_CC_CUBIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/netinet/cc/cc_module.h b/lib/libc/include/generic-freebsd/netinet/cc/cc_module.h index 32e2c0b21a98..285986455492 100644 --- a/lib/libc/include/generic-freebsd/netinet/cc/cc_module.h +++ b/lib/libc/include/generic-freebsd/netinet/cc/cc_module.h @@ -43,18 +43,7 @@ #ifndef _NETINET_CC_MODULE_H_ #define _NETINET_CC_MODULE_H_ -/* - * Allows a CC algorithm to manipulate a commonly named CC variable regardless - * of the transport protocol and associated C struct. - * XXXLAS: Out of action until the work to support SCTP is done. - * -#define CCV(ccv, what) \ -(*( \ - (ccv)->type == IPPROTO_TCP ? &(ccv)->ccvc.tcp->what : \ - &(ccv)->ccvc.sctp->what \ -)) - */ -#define CCV(ccv, what) (ccv)->ccvc.tcp->what +#define CCV(ccv, what) (ccv)->tp->what #define DECLARE_CC_MODULE(ccname, ccalgo) \ static moduledata_t cc_##ccname = { \ diff --git a/lib/libc/include/generic-freebsd/netinet/dccp.h b/lib/libc/include/generic-freebsd/netinet/dccp.h index 6a9f03712693..02f8aa00c76b 100644 --- a/lib/libc/include/generic-freebsd/netinet/dccp.h +++ b/lib/libc/include/generic-freebsd/netinet/dccp.h @@ -64,7 +64,7 @@ struct dccphdr { uint8_t seq[6]; } longseq; } d_seqno; -}; +} __packed; #define d_seqno_short d_seqno.shortseq; #define d_seqno_long d_seqno.longseq.seq; diff --git a/lib/libc/include/generic-freebsd/netinet/icmp6.h b/lib/libc/include/generic-freebsd/netinet/icmp6.h index d8d4bfd165dd..5a840ba85448 100644 --- a/lib/libc/include/generic-freebsd/netinet/icmp6.h +++ b/lib/libc/include/generic-freebsd/netinet/icmp6.h @@ -58,13 +58,13 @@ * 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. - * - * @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NETINET_ICMP6_H_ #define _NETINET_ICMP6_H_ +#include + #define ICMPV6_PLD_MAXLEN 1232 /* IPV6_MMTU - sizeof(struct ip6_hdr) - sizeof(struct icmp6_hdr) */ @@ -309,7 +309,8 @@ struct nd_opt_hdr { /* Neighbor discovery option header */ #define ND_OPT_ROUTE_INFO 24 /* RFC 4191 */ #define ND_OPT_RDNSS 25 /* RFC 6106 */ #define ND_OPT_DNSSL 31 /* RFC 6106 */ -#define ND_OPT_MAX 31 +#define ND_OPT_PREF64 38 /* RFC 8781 */ +#define ND_OPT_MAX 38 struct nd_opt_prefix_info { /* prefix information */ u_int8_t nd_opt_pi_type; @@ -375,6 +376,14 @@ struct nd_opt_dnssl { /* DNSSL option (RFC 6106) */ /* followed by list of DNS search domains */ } __packed; +struct nd_opt_pref64 { /* PREF64 option (RFC 8781) */ + uint8_t nd_opt_pref64_type; + uint8_t nd_opt_pref64_len; + /* bits 0-12 are the SL, bits 13-15 are the PLC */ + uint16_t nd_opt_pref64_sl_plc; + char nd_opt_prefix[12]; +} __packed; + /* * icmp6 namelookup */ @@ -574,22 +583,6 @@ do { \ * Variables related to this implementation * of the internet control message protocol version 6. */ -struct icmp6errstat { - uint64_t icp6errs_dst_unreach_noroute; - uint64_t icp6errs_dst_unreach_admin; - uint64_t icp6errs_dst_unreach_beyondscope; - uint64_t icp6errs_dst_unreach_addr; - uint64_t icp6errs_dst_unreach_noport; - uint64_t icp6errs_packet_too_big; - uint64_t icp6errs_time_exceed_transit; - uint64_t icp6errs_time_exceed_reassembly; - uint64_t icp6errs_paramprob_header; - uint64_t icp6errs_paramprob_nextheader; - uint64_t icp6errs_paramprob_option; - uint64_t icp6errs_redirect; /* we regard redirect as an error here */ - uint64_t icp6errs_unknown; -}; - struct icmp6stat { /* statistics related to icmp6 packets generated */ uint64_t icp6s_error; /* # of calls to icmp6_error */ @@ -609,25 +602,19 @@ struct icmp6stat { uint64_t icp6s_reflect; uint64_t icp6s_inhist[256]; uint64_t icp6s_nd_toomanyopt; /* too many ND options */ - struct icmp6errstat icp6s_outerrhist; -#define icp6s_odst_unreach_noroute \ - icp6s_outerrhist.icp6errs_dst_unreach_noroute -#define icp6s_odst_unreach_admin icp6s_outerrhist.icp6errs_dst_unreach_admin -#define icp6s_odst_unreach_beyondscope \ - icp6s_outerrhist.icp6errs_dst_unreach_beyondscope -#define icp6s_odst_unreach_addr icp6s_outerrhist.icp6errs_dst_unreach_addr -#define icp6s_odst_unreach_noport icp6s_outerrhist.icp6errs_dst_unreach_noport -#define icp6s_opacket_too_big icp6s_outerrhist.icp6errs_packet_too_big -#define icp6s_otime_exceed_transit \ - icp6s_outerrhist.icp6errs_time_exceed_transit -#define icp6s_otime_exceed_reassembly \ - icp6s_outerrhist.icp6errs_time_exceed_reassembly -#define icp6s_oparamprob_header icp6s_outerrhist.icp6errs_paramprob_header -#define icp6s_oparamprob_nextheader \ - icp6s_outerrhist.icp6errs_paramprob_nextheader -#define icp6s_oparamprob_option icp6s_outerrhist.icp6errs_paramprob_option -#define icp6s_oredirect icp6s_outerrhist.icp6errs_redirect -#define icp6s_ounknown icp6s_outerrhist.icp6errs_unknown + uint64_t icp6s_odst_unreach_noroute; + uint64_t icp6s_odst_unreach_admin; + uint64_t icp6s_odst_unreach_beyondscope; + uint64_t icp6s_odst_unreach_addr; + uint64_t icp6s_odst_unreach_noport; + uint64_t icp6s_opacket_too_big; + uint64_t icp6s_otime_exceed_transit; + uint64_t icp6s_otime_exceed_reassembly; + uint64_t icp6s_oparamprob_header; + uint64_t icp6s_oparamprob_nextheader; + uint64_t icp6s_oparamprob_option; + uint64_t icp6s_oredirect; + uint64_t icp6s_ounknown; uint64_t icp6s_pmtuchg; /* path MTU changes */ uint64_t icp6s_nd_badopt; /* bad ND options */ uint64_t icp6s_badns; /* bad neighbor solicitation */ @@ -645,6 +632,7 @@ struct icmp6stat { #ifdef _KERNEL #include +#include #ifdef SYSCTL_DECL SYSCTL_DECL(_net_inet6_icmp6); @@ -655,16 +643,28 @@ VNET_PCPUSTAT_DECLARE(struct icmp6stat, icmp6stat); * In-kernel consumers can use these accessor macros directly to update * stats. */ -#define ICMP6STAT_ADD(name, val) \ - VNET_PCPUSTAT_ADD(struct icmp6stat, icmp6stat, name, (val)) -#define ICMP6STAT_INC(name) ICMP6STAT_ADD(name, 1) +#define ICMP6STAT_ADD(name, val) \ + do { \ + MIB_SDT_PROBE1(icmp6, count, name, (val)); \ + VNET_PCPUSTAT_ADD(struct icmp6stat, icmp6stat, name, (val)); \ + } while (0) +#define ICMP6STAT_INC(name) ICMP6STAT_ADD(name, 1) +#define ICMP6STAT_INC2(name, type) \ + do { \ + MIB_SDT_PROBE2(icmp6, count, name, 1, type); \ + VNET_PCPUSTAT_ADD(struct icmp6stat, icmp6stat, name[type], 1); \ + } while (0) /* * Kernel module consumers must use this accessor macro. */ void kmod_icmp6stat_inc(int statnum); -#define KMOD_ICMP6STAT_INC(name) \ - kmod_icmp6stat_inc(offsetof(struct icmp6stat, name) / sizeof(uint64_t)) +#define KMOD_ICMP6STAT_INC(name) \ + do { \ + MIB_SDT_PROBE1(icmp6, count, name, 1); \ + kmod_icmp6stat_inc( \ + offsetof(struct icmp6stat, name) / sizeof(uint64_t)); \ + } while (0) #endif /* @@ -713,9 +713,6 @@ void icmp6_redirect_input(struct mbuf *, int); void icmp6_redirect_output(struct mbuf *, struct nhop_object *); int icmp6_ratelimit(const struct in6_addr *, const int, const int); -struct ip6ctlparam; -void icmp6_mtudisc_update(struct ip6ctlparam *, int); - /* XXX: is this the right place for these macros? */ #define icmp6_ifstat_inc(ifp, tag) \ do { \ diff --git a/lib/libc/include/generic-freebsd/netinet/icmp_var.h b/lib/libc/include/generic-freebsd/netinet/icmp_var.h index f2283c4a3891..a2a03590328b 100644 --- a/lib/libc/include/generic-freebsd/netinet/icmp_var.h +++ b/lib/libc/include/generic-freebsd/netinet/icmp_var.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)icmp_var.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NETINET_ICMP_VAR_H_ @@ -59,22 +57,36 @@ struct icmpstat { #ifdef _KERNEL #include +#include VNET_PCPUSTAT_DECLARE(struct icmpstat, icmpstat); /* * In-kernel consumers can use these accessor macros directly to update * stats. */ -#define ICMPSTAT_ADD(name, val) \ - VNET_PCPUSTAT_ADD(struct icmpstat, icmpstat, name, (val)) +#define ICMPSTAT_ADD(name, val) \ + do { \ + MIB_SDT_PROBE1(icmp, count, name, (val)); \ + VNET_PCPUSTAT_ADD(struct icmpstat, icmpstat, name, (val)); \ + } while (0) + #define ICMPSTAT_INC(name) ICMPSTAT_ADD(name, 1) +#define ICMPSTAT_INC2(name, type) \ + do { \ + MIB_SDT_PROBE2(icmp, count, name, 1, type); \ + VNET_PCPUSTAT_ADD(struct icmpstat, icmpstat, name[type], 1); \ + } while (0) /* * Kernel module consumers must use this accessor macro. */ void kmod_icmpstat_inc(int statnum); -#define KMOD_ICMPSTAT_INC(name) \ - kmod_icmpstat_inc(offsetof(struct icmpstat, name) / sizeof(uint64_t)) +#define KMOD_ICMPSTAT_INC(name) \ + do { \ + MIB_SDT_PROBE1(icmp, count, name, 1); \ + kmod_icmpstat_inc( \ + offsetof(struct icmpstat, name) / sizeof(uint64_t)); \ + } while (0) #endif /* @@ -88,15 +100,13 @@ void kmod_icmpstat_inc(int statnum); SYSCTL_DECL(_net_inet_icmp); extern int badport_bandlim(int); -#define BANDLIM_UNLIMITED -1 #define BANDLIM_ICMP_UNREACH 0 #define BANDLIM_ICMP_ECHO 1 #define BANDLIM_ICMP_TSTAMP 2 -#define BANDLIM_RST_CLOSEDPORT 3 /* No connection, and no listeners */ -#define BANDLIM_RST_OPENPORT 4 /* No connection, listener */ -#define BANDLIM_ICMP6_UNREACH 5 -#define BANDLIM_SCTP_OOTB 6 -#define BANDLIM_MAX 7 +#define BANDLIM_TCP_RST 3 +#define BANDLIM_ICMP6_UNREACH 4 +#define BANDLIM_SCTP_OOTB 5 +#define BANDLIM_MAX 6 #endif #endif \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/netinet/if_ether.h b/lib/libc/include/generic-freebsd/netinet/if_ether.h index e0ba1a8809c7..0740e972ef61 100644 --- a/lib/libc/include/generic-freebsd/netinet/if_ether.h +++ b/lib/libc/include/generic-freebsd/netinet/if_ether.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)if_ether.h 8.3 (Berkeley) 5/2/95 */ #ifndef _NETINET_IF_ETHER_H_ diff --git a/lib/libc/include/generic-freebsd/netinet/igmp.h b/lib/libc/include/generic-freebsd/netinet/igmp.h index fc686fbb1ad7..71eadad23940 100644 --- a/lib/libc/include/generic-freebsd/netinet/igmp.h +++ b/lib/libc/include/generic-freebsd/netinet/igmp.h @@ -31,8 +31,6 @@ * 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. - * - * @(#)igmp.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NETINET_IGMP_H_ diff --git a/lib/libc/include/generic-freebsd/netinet/igmp_var.h b/lib/libc/include/generic-freebsd/netinet/igmp_var.h index a55c0eba5ab9..3f75dad32f6b 100644 --- a/lib/libc/include/generic-freebsd/netinet/igmp_var.h +++ b/lib/libc/include/generic-freebsd/netinet/igmp_var.h @@ -31,8 +31,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)igmp_var.h 8.1 (Berkeley) 7/19/93 */ #ifndef _NETINET_IGMP_VAR_H_ diff --git a/lib/libc/include/generic-freebsd/netinet/in.h b/lib/libc/include/generic-freebsd/netinet/in.h index eb0b586624ac..ed7ecda83041 100644 --- a/lib/libc/include/generic-freebsd/netinet/in.h +++ b/lib/libc/include/generic-freebsd/netinet/in.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)in.h 8.3 (Berkeley) 1/3/94 */ #ifndef _NETINET_IN_H_ @@ -674,13 +672,13 @@ int getsourcefilter(int, uint32_t, struct sockaddr *, socklen_t, struct ifnet; struct mbuf; /* forward declarations for Standard C */ struct in_ifaddr; -int in_broadcast(struct in_addr, struct ifnet *); -int in_ifaddr_broadcast(struct in_addr, struct in_ifaddr *); -int in_canforward(struct in_addr); -int in_localaddr(struct in_addr); +bool in_ifnet_broadcast(struct in_addr, struct ifnet *); +bool in_ifaddr_broadcast(struct in_addr, struct in_ifaddr *); +bool in_canforward(struct in_addr); +bool in_localaddr(struct in_addr); bool in_localip(struct in_addr); bool in_localip_fib(struct in_addr, uint16_t); -int in_ifhasaddr(struct ifnet *, struct in_addr); +bool in_ifhasaddr(struct ifnet *, struct in_addr); struct in_ifaddr *in_findlocal(uint32_t, bool); int inet_aton(const char *, struct in_addr *); /* in libkern */ char *inet_ntoa_r(struct in_addr ina, char *buf); /* in libkern */ @@ -688,6 +686,13 @@ char *inet_ntop(int, const void *, char *, socklen_t); /* in libkern */ int inet_pton(int af, const char *, void *); /* in libkern */ void in_ifdetach(struct ifnet *); +static inline bool +in_broadcast(struct in_addr in) +{ + return (in.s_addr == __htonl(INADDR_BROADCAST) || + in.s_addr == __htonl(INADDR_ANY)); +} + #define in_hosteq(s, t) ((s).s_addr == (t).s_addr) #define in_nullhost(x) ((x).s_addr == INADDR_ANY) #define in_allhosts(x) ((x).s_addr == htonl(INADDR_ALLHOSTS_GROUP)) diff --git a/lib/libc/include/generic-freebsd/netinet/in_kdtrace.h b/lib/libc/include/generic-freebsd/netinet/in_kdtrace.h index 768feb147c96..b37b3dda4849 100644 --- a/lib/libc/include/generic-freebsd/netinet/in_kdtrace.h +++ b/lib/libc/include/generic-freebsd/netinet/in_kdtrace.h @@ -28,6 +28,8 @@ #ifndef _SYS_IN_KDTRACE_H_ #define _SYS_IN_KDTRACE_H_ +#include + #define IP_PROBE(probe, arg0, arg1, arg2, arg3, arg4, arg5) \ SDT_PROBE6(ip, , , probe, arg0, arg1, arg2, arg3, arg4, arg5) #define UDP_PROBE(probe, arg0, arg1, arg2, arg3, arg4) \ @@ -52,6 +54,371 @@ SDT_PROVIDER_DECLARE(tcp); SDT_PROVIDER_DECLARE(udp); SDT_PROVIDER_DECLARE(udplite); +#ifdef KDTRACE_MIB_SDT +SDT_PROVIDER_DECLARE(mib); + +SDT_PROBE_DECLARE(mib, ip, count, ips_total); +SDT_PROBE_DECLARE(mib, ip, count, ips_badsum); +SDT_PROBE_DECLARE(mib, ip, count, ips_tooshort); +SDT_PROBE_DECLARE(mib, ip, count, ips_toosmall); +SDT_PROBE_DECLARE(mib, ip, count, ips_badhlen); +SDT_PROBE_DECLARE(mib, ip, count, ips_badlen); +SDT_PROBE_DECLARE(mib, ip, count, ips_fragments); +SDT_PROBE_DECLARE(mib, ip, count, ips_fragdropped); +SDT_PROBE_DECLARE(mib, ip, count, ips_fragtimeout); +SDT_PROBE_DECLARE(mib, ip, count, ips_forward); +SDT_PROBE_DECLARE(mib, ip, count, ips_fastforward); +SDT_PROBE_DECLARE(mib, ip, count, ips_cantforward); +SDT_PROBE_DECLARE(mib, ip, count, ips_redirectsent); +SDT_PROBE_DECLARE(mib, ip, count, ips_noproto); +SDT_PROBE_DECLARE(mib, ip, count, ips_delivered); +SDT_PROBE_DECLARE(mib, ip, count, ips_localout); +SDT_PROBE_DECLARE(mib, ip, count, ips_odropped); +SDT_PROBE_DECLARE(mib, ip, count, ips_reassembled); +SDT_PROBE_DECLARE(mib, ip, count, ips_fragmented); +SDT_PROBE_DECLARE(mib, ip, count, ips_ofragments); +SDT_PROBE_DECLARE(mib, ip, count, ips_cantfrag); +SDT_PROBE_DECLARE(mib, ip, count, ips_badoptions); +SDT_PROBE_DECLARE(mib, ip, count, ips_noroute); +SDT_PROBE_DECLARE(mib, ip, count, ips_badvers); +SDT_PROBE_DECLARE(mib, ip, count, ips_rawout); +SDT_PROBE_DECLARE(mib, ip, count, ips_toolong); +SDT_PROBE_DECLARE(mib, ip, count, ips_notmember); +SDT_PROBE_DECLARE(mib, ip, count, ips_nogif); +SDT_PROBE_DECLARE(mib, ip, count, ips_badaddr); + +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_total); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_tooshort); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_toosmall); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_fragments); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_fragdropped); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_fragtimeout); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_fragoverflow); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_forward); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_cantforward); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_redirectsent); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_delivered); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_localout); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_odropped); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_reassembled); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_atomicfrags); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_fragmented); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_ofragments); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_cantfrag); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_badoptions); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_noroute); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_badvers); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_rawout); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_badscope); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_notmember); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_nxthist); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_m1); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_m2m); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_mext1); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_mext2m); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_exthdrtoolong); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_nogif); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_toomanyhdr); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_sources_none); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_sources_sameif); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_sources_otherif); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_sources_samescope); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_sources_otherscope); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_sources_deprecated); +SDT_PROBE_DECLARE(mib, ip6, count, ip6s_sources_rule); + +SDT_PROBE_DECLARE(mib, icmp, count, icps_error); +SDT_PROBE_DECLARE(mib, icmp, count, icps_oldshort); +SDT_PROBE_DECLARE(mib, icmp, count, icps_oldicmp); +SDT_PROBE_DECLARE(mib, icmp, count, icps_outhist); +SDT_PROBE_DECLARE(mib, icmp, count, icps_badcode); +SDT_PROBE_DECLARE(mib, icmp, count, icps_tooshort); +SDT_PROBE_DECLARE(mib, icmp, count, icps_checksum); +SDT_PROBE_DECLARE(mib, icmp, count, icps_badlen); +SDT_PROBE_DECLARE(mib, icmp, count, icps_reflect); +SDT_PROBE_DECLARE(mib, icmp, count, icps_inhist); +SDT_PROBE_DECLARE(mib, icmp, count, icps_bmcastecho); +SDT_PROBE_DECLARE(mib, icmp, count, icps_bmcasttstamp); +SDT_PROBE_DECLARE(mib, icmp, count, icps_badaddr); +SDT_PROBE_DECLARE(mib, icmp, count, icps_noroute); + +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_error); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_canterror); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_toofreq); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_outhist); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_badcode); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_tooshort); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_checksum); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_badlen); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_dropped); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_reflect); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_inhist); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_nd_toomanyopt); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_odst_unreach_noroute); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_odst_unreach_admin); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_odst_unreach_beyondscope); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_odst_unreach_addr); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_odst_unreach_noport); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_opacket_too_big); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_otime_exceed_transit); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_otime_exceed_reassembly); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_oparamprob_header); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_oparamprob_nextheader); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_oparamprob_option); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_oredirect); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_ounknown); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_pmtuchg); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_nd_badopt); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_badns); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_badna); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_badrs); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_badra); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_badredirect); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_overflowdefrtr); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_overflowprfx); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_overflownndp); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_overflowredirect); +SDT_PROBE_DECLARE(mib, icmp6, count, icp6s_invlhlim); + +SDT_PROBE_DECLARE(mib, udp, count, udps_ipackets); +SDT_PROBE_DECLARE(mib, udp, count, udps_hdrops); +SDT_PROBE_DECLARE(mib, udp, count, udps_badsum); +SDT_PROBE_DECLARE(mib, udp, count, udps_nosum); +SDT_PROBE_DECLARE(mib, udp, count, udps_badlen); +SDT_PROBE_DECLARE(mib, udp, count, udps_noport); +SDT_PROBE_DECLARE(mib, udp, count, udps_noportbcast); +SDT_PROBE_DECLARE(mib, udp, count, udps_fullsock); +SDT_PROBE_DECLARE(mib, udp, count, udps_pcbcachemiss); +SDT_PROBE_DECLARE(mib, udp, count, udps_pcbhashmiss); +SDT_PROBE_DECLARE(mib, udp, count, udps_opackets); +SDT_PROBE_DECLARE(mib, udp, count, udps_fastout); +SDT_PROBE_DECLARE(mib, udp, count, udps_noportmcast); +SDT_PROBE_DECLARE(mib, udp, count, udps_filtermcast); + +SDT_PROBE_DECLARE(mib, tcp, count, tcps_connattempt); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_accepts); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_connects); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_drops); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_conndrops); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_minmssdrops); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_closed); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_segstimed); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rttupdated); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_delack); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_timeoutdrop); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rexmttimeo); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_persisttimeo); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_keeptimeo); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_keepprobe); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_keepdrops); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_progdrops); + +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sndtotal); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sndpack); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sndbyte); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sndrexmitpack); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sndrexmitbyte); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sndrexmitbad); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sndacks); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sndprobe); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sndurg); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sndwinup); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sndctrl); + +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvtotal); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvpack); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvbyte); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvbadsum); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvbadoff); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvreassfull); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvshort); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvduppack); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvdupbyte); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvpartduppack); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvpartdupbyte); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvoopack); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvoobyte); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvpackafterwin); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvbyteafterwin); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvafterclose); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvwinprobe); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvdupack); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvacktoomuch); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvackpack); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvackbyte); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvwinupd); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_pawsdrop); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_predack); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_preddat); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_pcbcachemiss); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_cachedrtt); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_cachedrttvar); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_cachedssthresh); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_usedrtt); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_usedrttvar); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_usedssthresh); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_persistdrop); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_badsyn); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_mturesent); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_listendrop); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_badrst); + +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sc_added); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sc_retransmitted); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sc_dupsyn); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sc_dropped); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sc_completed); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sc_bucketoverflow); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sc_cacheoverflow); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sc_reset); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sc_stale); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sc_aborted); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sc_badack); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sc_unreach); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sc_zonefail); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sc_sendcookie); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sc_recvcookie); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sc_spurcookie); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sc_failcookie); + +SDT_PROBE_DECLARE(mib, tcp, count, tcps_hc_added); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_hc_bucketoverflow); + +SDT_PROBE_DECLARE(mib, tcp, count, tcps_finwait2_drops); + +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sack_recovery_episode); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sack_rexmits); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sack_rexmits_tso); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sack_rexmit_bytes); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sack_rcv_blocks); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sack_send_blocks); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sack_lostrexmt); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sack_sboverflow); + +SDT_PROBE_DECLARE(mib, tcp, count, tcps_ecn_rcvce); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_ecn_rcvect0); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_ecn_rcvect1); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_ecn_shs); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_ecn_rcwnd); + +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sig_rcvgoodsig); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sig_rcvbadsig); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sig_err_buildsig); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sig_err_sigopt); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_sig_err_nosigopt); + +SDT_PROBE_DECLARE(mib, tcp, count, tcps_pmtud_blackhole_activated); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_pmtud_blackhole_activated_min_mss); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_pmtud_blackhole_failed); + +SDT_PROBE_DECLARE(mib, tcp, count, tcps_tunneled_pkts); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_tunneled_errs); + +SDT_PROBE_DECLARE(mib, tcp, count, tcps_dsack_count); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_dsack_bytes); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_dsack_tlp_bytes); + +SDT_PROBE_DECLARE(mib, tcp, count, tcps_tw_recycles); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_tw_resets); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_tw_responds); + +SDT_PROBE_DECLARE(mib, tcp, count, tcps_ace_nect); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_ace_ect1); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_ace_ect0); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_ace_ce); + +SDT_PROBE_DECLARE(mib, tcp, count, tcps_ecn_sndect0); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_ecn_sndect1); + +SDT_PROBE_DECLARE(mib, tcp, count, tcps_tlpresends); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_tlpresend_bytes); + +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvghostack); +SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvacktooold); + +SDT_PROBE_DECLARE(mib, ipsec, count, ips_in_polvio); +SDT_PROBE_DECLARE(mib, ipsec, count, ips_in_nomem); +SDT_PROBE_DECLARE(mib, ipsec, count, ips_in_inval); +SDT_PROBE_DECLARE(mib, ipsec, count, ips_out_polvio); +SDT_PROBE_DECLARE(mib, ipsec, count, ips_out_nosa); +SDT_PROBE_DECLARE(mib, ipsec, count, ips_out_nomem); +SDT_PROBE_DECLARE(mib, ipsec, count, ips_out_noroute); +SDT_PROBE_DECLARE(mib, ipsec, count, ips_out_inval); +SDT_PROBE_DECLARE(mib, ipsec, count, ips_out_bundlesa); + +SDT_PROBE_DECLARE(mib, ipsec, count, ips_spdcache_hits); +SDT_PROBE_DECLARE(mib, ipsec, count, ips_spdcache_misses); + +SDT_PROBE_DECLARE(mib, ipsec, count, ips_clcopied); +SDT_PROBE_DECLARE(mib, ipsec, count, ips_mbinserted); +SDT_PROBE_DECLARE(mib, ipsec, count, ips_input_front); +SDT_PROBE_DECLARE(mib, ipsec, count, ips_input_middle); +SDT_PROBE_DECLARE(mib, ipsec, count, ips_input_end); + +SDT_PROBE_DECLARE(mib, esp, count, esps_hdrops); +SDT_PROBE_DECLARE(mib, esp, count, esps_nopf); +SDT_PROBE_DECLARE(mib, esp, count, esps_notdb); +SDT_PROBE_DECLARE(mib, esp, count, esps_badkcr); +SDT_PROBE_DECLARE(mib, esp, count, esps_qfull); +SDT_PROBE_DECLARE(mib, esp, count, esps_noxform); +SDT_PROBE_DECLARE(mib, esp, count, esps_badilen); +SDT_PROBE_DECLARE(mib, esp, count, esps_wrap); +SDT_PROBE_DECLARE(mib, esp, count, esps_badenc); +SDT_PROBE_DECLARE(mib, esp, count, esps_badauth); +SDT_PROBE_DECLARE(mib, esp, count, esps_replay); +SDT_PROBE_DECLARE(mib, esp, count, esps_input); +SDT_PROBE_DECLARE(mib, esp, count, esps_output); +SDT_PROBE_DECLARE(mib, esp, count, esps_invalid); +SDT_PROBE_DECLARE(mib, esp, count, esps_ibytes); +SDT_PROBE_DECLARE(mib, esp, count, esps_obytes); +SDT_PROBE_DECLARE(mib, esp, count, esps_toobig); +SDT_PROBE_DECLARE(mib, esp, count, esps_pdrops); +SDT_PROBE_DECLARE(mib, esp, count, esps_crypto); +SDT_PROBE_DECLARE(mib, esp, count, esps_tunnel); +SDT_PROBE_DECLARE(mib, esp, count, esps_hist); + +SDT_PROBE_DECLARE(mib, ah, count, ahs_hdrops); +SDT_PROBE_DECLARE(mib, ah, count, ahs_nopf); +SDT_PROBE_DECLARE(mib, ah, count, ahs_notdb); +SDT_PROBE_DECLARE(mib, ah, count, ahs_badkcr); +SDT_PROBE_DECLARE(mib, ah, count, ahs_badauth); +SDT_PROBE_DECLARE(mib, ah, count, ahs_noxform); +SDT_PROBE_DECLARE(mib, ah, count, ahs_qfull); +SDT_PROBE_DECLARE(mib, ah, count, ahs_wrap); +SDT_PROBE_DECLARE(mib, ah, count, ahs_replay); +SDT_PROBE_DECLARE(mib, ah, count, ahs_badauthl); +SDT_PROBE_DECLARE(mib, ah, count, ahs_input); +SDT_PROBE_DECLARE(mib, ah, count, ahs_output); +SDT_PROBE_DECLARE(mib, ah, count, ahs_invalid); +SDT_PROBE_DECLARE(mib, ah, count, ahs_ibytes); +SDT_PROBE_DECLARE(mib, ah, count, ahs_obytes); +SDT_PROBE_DECLARE(mib, ah, count, ahs_toobig); +SDT_PROBE_DECLARE(mib, ah, count, ahs_pdrops); +SDT_PROBE_DECLARE(mib, ah, count, ahs_crypto); +SDT_PROBE_DECLARE(mib, ah, count, ahs_tunnel); +SDT_PROBE_DECLARE(mib, ah, count, ahs_hist); + +SDT_PROBE_DECLARE(mib, ipcomp, count, ipcomps_hdrops); +SDT_PROBE_DECLARE(mib, ipcomp, count, ipcomps_nopf); +SDT_PROBE_DECLARE(mib, ipcomp, count, ipcomps_notdb); +SDT_PROBE_DECLARE(mib, ipcomp, count, ipcomps_badkcr); +SDT_PROBE_DECLARE(mib, ipcomp, count, ipcomps_qfull); +SDT_PROBE_DECLARE(mib, ipcomp, count, ipcomps_noxform); +SDT_PROBE_DECLARE(mib, ipcomp, count, ipcomps_wrap); +SDT_PROBE_DECLARE(mib, ipcomp, count, ipcomps_input); +SDT_PROBE_DECLARE(mib, ipcomp, count, ipcomps_output); +SDT_PROBE_DECLARE(mib, ipcomp, count, ipcomps_invalid); +SDT_PROBE_DECLARE(mib, ipcomp, count, ipcomps_ibytes); +SDT_PROBE_DECLARE(mib, ipcomp, count, ipcomps_obytes); +SDT_PROBE_DECLARE(mib, ipcomp, count, ipcomps_toobig); +SDT_PROBE_DECLARE(mib, ipcomp, count, ipcomps_pdrops); +SDT_PROBE_DECLARE(mib, ipcomp, count, ipcomps_crypto); +SDT_PROBE_DECLARE(mib, ipcomp, count, ipcomps_hist); +SDT_PROBE_DECLARE(mib, ipcomp, count, ipcomps_threshold); +SDT_PROBE_DECLARE(mib, ipcomp, count, ipcomps_uncompr); + +#endif + SDT_PROBE_DECLARE(ip, , , receive); SDT_PROBE_DECLARE(ip, , , send); diff --git a/lib/libc/include/generic-freebsd/netinet/in_pcb.h b/lib/libc/include/generic-freebsd/netinet/in_pcb.h index be69e6a40be2..a1caca964fa4 100644 --- a/lib/libc/include/generic-freebsd/netinet/in_pcb.h +++ b/lib/libc/include/generic-freebsd/netinet/in_pcb.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)in_pcb.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NETINET_IN_PCB_H_ @@ -66,7 +64,6 @@ * protocol-specific control block) are stored here. */ CK_LIST_HEAD(inpcbhead, inpcb); -CK_LIST_HEAD(inpcbporthead, inpcbport); CK_LIST_HEAD(inpcblbgrouphead, inpcblbgroup); typedef uint64_t inp_gen_t; @@ -135,8 +132,9 @@ struct in_conninfo { /* * struct inpcb captures the network layer state for TCP, UDP, and raw IPv4 and * IPv6 sockets. In the case of TCP and UDP, further per-connection state is - * hung off of inp_ppcb most of the time. Almost all fields of struct inpcb - * are static after creation or protected by a per-inpcb rwlock, inp_lock. + * located in a larger protocol specific structure that embeds inpcb in it. + * Almost all fields of struct inpcb are static after creation or protected by + * a per-inpcb rwlock, inp_lock. * * A inpcb database is indexed by addresses/ports hash as well as list of * all pcbs that belong to a certain proto. Database lookups or list traversals @@ -168,7 +166,10 @@ struct inpcbpolicy; struct m_snd_tag; struct inpcb { /* Cache line #1 (amd64) */ - CK_LIST_ENTRY(inpcb) inp_hash_exact; /* hash table linkage */ + union { + CK_LIST_ENTRY(inpcb) inp_hash_exact; /* hash table linkage */ + LIST_ENTRY(inpcb) inp_lbgroup_list; /* lb group list */ + }; CK_LIST_ENTRY(inpcb) inp_hash_wild; /* hash table linkage */ struct rwlock inp_lock; /* Cache line #2 (amd64) */ @@ -179,7 +180,6 @@ struct inpcb { int inp_flags; /* (i) generic IP/datagram flags */ int inp_flags2; /* (i) generic IP/datagram flags #2*/ uint8_t inp_numa_domain; /* numa domain */ - void *inp_ppcb; /* (i) pointer to per-protocol pcb */ struct socket *inp_socket; /* (i) back pointer to socket */ struct inpcbinfo *inp_pcbinfo; /* (c) PCB list info */ struct ucred *inp_cred; /* (c) cache of socket cred */ @@ -220,7 +220,6 @@ struct inpcb { short in6p_hops; }; CK_LIST_ENTRY(inpcb) inp_portlist; /* (r:e/w:h) port list */ - struct inpcbport *inp_phd; /* (r:e/w:h) head of this list */ inp_gen_t inp_gencnt; /* (c) generation count */ void *spare_ptr; /* Spare pointer. */ rt_gen_t inp_rt_cookie; /* generation for route entry */ @@ -268,8 +267,7 @@ struct xinpcb { struct xsocket xi_socket; /* (s,p) */ struct in_conninfo inp_inc; /* (s,p) */ uint64_t inp_gencnt; /* (s,p) */ - kvaddr_t inp_ppcb; /* (s) netstat(1) */ - int64_t inp_spare64[4]; + int64_t inp_spare64[5]; uint32_t inp_flow; /* (s) */ uint32_t inp_flowid; /* (s) */ uint32_t inp_flowtype; /* (s) */ @@ -305,6 +303,30 @@ struct sockopt_parameters { char sop_optval[]; }; +#ifdef _SYS_KTLS_H_ +struct xktls_session { + uint32_t tsz; /* total sz of elm, next elm is at this+tsz */ + uint32_t fsz; /* size of the struct up to keys */ + uint64_t inp_gencnt; + kvaddr_t so_pcb; + struct in_conninfo coninf; + u_short rx_vlan_id; + struct xktls_session_onedir rcv; + struct xktls_session_onedir snd; +/* + * Next are + * - keydata for rcv, first cipher of length rcv.cipher_key_len, then + * authentication of length rcv.auth_key_len; + * - driver data (string) of length rcv.drv_st_len, if the rcv session is + * offloaded to ifnet rcv.ifnet; + * - keydata for snd, first cipher of length snd.cipher_key_len, then + * authentication of length snd.auth_key_len; + * - driver data (string) of length snd.drv_st_len, if the snd session is + * offloaded to ifnet snd.ifnet; + */ +}; +#endif /* _SYS_KTLS_H_ */ + #ifdef _KERNEL int sysctl_setsockopt(SYSCTL_HANDLER_ARGS, struct inpcbinfo *pcbinfo, int (*ctloutput_set)(struct inpcb *, struct sockopt *)); @@ -370,7 +392,7 @@ struct inpcbinfo { /* * Global hash of inpcbs, hashed by only local port number. */ - struct inpcbporthead *ipi_porthashbase; /* (h) */ + struct inpcbhead *ipi_porthashbase; /* (h) */ u_long ipi_porthashmask; /* (h) */ /* @@ -392,11 +414,9 @@ struct inpcbinfo { */ struct inpcbstorage { uma_zone_t ips_zone; - uma_zone_t ips_portzone; uma_init ips_pcbinit; size_t ips_size; const char * ips_zone_name; - const char * ips_portzone_name; const char * ips_infolock_name; const char * ips_hashlock_name; }; @@ -414,7 +434,6 @@ static struct inpcbstorage prot = { \ .ips_size = sizeof(struct ppcb), \ .ips_pcbinit = prot##_inpcb_init, \ .ips_zone_name = zname, \ - .ips_portzone_name = zname " ports", \ .ips_infolock_name = iname, \ .ips_hashlock_name = hname, \ }; \ @@ -423,28 +442,6 @@ SYSINIT(prot##_inpcbstorage_init, SI_SUB_PROTO_DOMAIN, \ SYSUNINIT(prot##_inpcbstorage_uninit, SI_SUB_PROTO_DOMAIN, \ SI_ORDER_SECOND, in_pcbstorage_destroy, &prot) -/* - * Load balance groups used for the SO_REUSEPORT_LB socket option. Each group - * (or unique address:port combination) can be re-used at most - * INPCBLBGROUP_SIZMAX (256) times. The inpcbs are stored in il_inp which - * is dynamically resized as processes bind/unbind to that specific group. - */ -struct inpcblbgroup { - CK_LIST_ENTRY(inpcblbgroup) il_list; - struct epoch_context il_epoch_ctx; - struct ucred *il_cred; - uint16_t il_lport; /* (c) */ - u_char il_vflag; /* (c) */ - uint8_t il_numa_domain; - uint32_t il_pad2; - union in_dependaddr il_dependladdr; /* (c) */ -#define il_laddr il_dependladdr.id46_addr.ia46_addr4 -#define il6_laddr il_dependladdr.id6_addr - uint32_t il_inpsiz; /* max count in il_inp[] (h) */ - uint32_t il_inpcnt; /* cur count in il_inp[] (h) */ - struct inpcb *il_inp[]; /* (h) */ -}; - #define INP_LOCK_DESTROY(inp) rw_destroy(&(inp)->inp_lock) #define INP_RLOCK(inp) rw_rlock(&(inp)->inp_lock) #define INP_WLOCK(inp) rw_wlock(&(inp)->inp_lock) @@ -481,12 +478,8 @@ void inp_unlock_assert(struct inpcb *); void inp_apply_all(struct inpcbinfo *, void (*func)(struct inpcb *, void *), void *arg); -int inp_ip_tos_get(const struct inpcb *inp); -void inp_ip_tos_set(struct inpcb *inp, int val); struct socket * inp_inpcbtosocket(struct inpcb *inp); -struct tcpcb * - inp_inpcbtotcpcb(struct inpcb *inp); void inp_4tuple_get(struct inpcb *inp, uint32_t *laddr, uint16_t *lp, uint32_t *faddr, uint16_t *fp); @@ -578,7 +571,7 @@ void inp_4tuple_get(struct inpcb *inp, uint32_t *laddr, uint16_t *lp, #define INP_DROPPED 0x04000000 /* protocol drop flag */ #define INP_SOCKREF 0x08000000 /* strong socket reference */ #define INP_RESERVED_0 0x10000000 /* reserved field */ -#define INP_RESERVED_1 0x20000000 /* reserved field */ +#define INP_BOUNDFIB 0x20000000 /* Bound to a specific FIB. */ #define IN6P_RFC2292 0x40000000 /* used RFC2292 API on the socket */ #define IN6P_MTU 0x80000000 /* receive path MTU */ @@ -624,10 +617,11 @@ typedef enum { INPLOOKUP_WILDCARD = 0x00000001, /* Allow wildcard sockets. */ INPLOOKUP_RLOCKPCB = 0x00000002, /* Return inpcb read-locked. */ INPLOOKUP_WLOCKPCB = 0x00000004, /* Return inpcb write-locked. */ + INPLOOKUP_FIB = 0x00000008, /* inp must be from same FIB. */ } inp_lookup_t; #define INPLOOKUP_MASK (INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB | \ - INPLOOKUP_WLOCKPCB) + INPLOOKUP_WLOCKPCB | INPLOOKUP_FIB) #define INPLOOKUP_LOCKMASK (INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB) #define sotoinpcb(so) ((struct inpcb *)(so)->so_pcb) @@ -665,34 +659,29 @@ void in_pcbstorage_destroy(void *); void in_pcbpurgeif0(struct inpcbinfo *, struct ifnet *); int in_pcballoc(struct socket *, struct inpcbinfo *); -int in_pcbbind(struct inpcb *, struct sockaddr_in *, struct ucred *); +#define INPBIND_FIB 0x0001 /* bind to the PCB's FIB only */ +int in_pcbbind(struct inpcb *, struct sockaddr_in *, int, struct ucred *); int in_pcbbind_setup(struct inpcb *, struct sockaddr_in *, in_addr_t *, - u_short *, struct ucred *); -int in_pcbconnect(struct inpcb *, struct sockaddr_in *, struct ucred *, - bool); -int in_pcbconnect_setup(struct inpcb *, struct sockaddr_in *, in_addr_t *, - u_short *, in_addr_t *, u_short *, struct ucred *); + u_short *, int, struct ucred *); +int in_pcbconnect(struct inpcb *, struct sockaddr_in *, struct ucred *); void in_pcbdisconnect(struct inpcb *); void in_pcbdrop(struct inpcb *); void in_pcbfree(struct inpcb *); -int in_pcbinshash(struct inpcb *); -int in_pcbladdr(struct inpcb *, struct in_addr *, struct in_addr *, +int in_pcbladdr(const struct inpcb *, struct in_addr *, struct in_addr *, struct ucred *); int in_pcblbgroup_numa(struct inpcb *, int arg); +void in_pcblisten(struct inpcb *); struct inpcb * in_pcblookup(struct inpcbinfo *, struct in_addr, u_int, struct in_addr, u_int, int, struct ifnet *); struct inpcb * in_pcblookup_mbuf(struct inpcbinfo *, struct in_addr, u_int, struct in_addr, u_int, int, struct ifnet *, struct mbuf *); -void in_pcbnotifyall(struct inpcbinfo *pcbinfo, struct in_addr, - int, struct inpcb *(*)(struct inpcb *, int)); void in_pcbref(struct inpcb *); -void in_pcbrehash(struct inpcb *); -void in_pcbremhash_locked(struct inpcb *); bool in_pcbrele(struct inpcb *, inp_lookup_t); bool in_pcbrele_rlocked(struct inpcb *); bool in_pcbrele_wlocked(struct inpcb *); +bool in_pcbrele_rlock(struct inpcb *inp); typedef bool inp_match_t(const struct inpcb *, void *); struct inpcb_iterator { @@ -724,10 +713,8 @@ struct inpcb_iterator { struct inpcb *inp_next(struct inpcb_iterator *); void in_losing(struct inpcb *); void in_pcbsetsolabel(struct socket *so); -int in_getpeeraddr(struct socket *so, struct sockaddr **nam); -int in_getsockaddr(struct socket *so, struct sockaddr **nam); -struct sockaddr * - in_sockaddr(in_port_t port, struct in_addr *addr); +int in_getpeeraddr(struct socket *, struct sockaddr *sa); +int in_getsockaddr(struct socket *, struct sockaddr *sa); void in_pcbsosetlabel(struct socket *so); #ifdef RATELIMIT int diff --git a/lib/libc/include/generic-freebsd/netinet/in_pcb_var.h b/lib/libc/include/generic-freebsd/netinet/in_pcb_var.h index f17d6c876faa..6fb09157c7d4 100644 --- a/lib/libc/include/generic-freebsd/netinet/in_pcb_var.h +++ b/lib/libc/include/generic-freebsd/netinet/in_pcb_var.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)in_pcb.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NETINET_IN_PCB_VAR_H_ @@ -52,16 +50,37 @@ int inp_trylock(struct inpcb *inp, const inp_lookup_t lock); bool inp_smr_lock(struct inpcb *, const inp_lookup_t); int in_pcb_lport(struct inpcb *, struct in_addr *, u_short *, struct ucred *, int); -int in_pcb_lport_dest(struct inpcb *inp, struct sockaddr *lsa, +int in_pcb_lport_dest(const struct inpcb *inp, struct sockaddr *lsa, u_short *lportp, struct sockaddr *fsa, u_short fport, struct ucred *cred, int lookupflags); -struct inpcb * in_pcblookup_local(struct inpcbinfo *, struct in_addr, u_short, - int, struct ucred *); +struct inpcb *in_pcblookup_local(struct inpcbinfo *, struct in_addr, u_short, + int, int, struct ucred *); +int in_pcbinshash(struct inpcb *); +void in_pcbrehash(struct inpcb *); +void in_pcbremhash_locked(struct inpcb *); -struct inpcbport { - struct inpcbhead phd_pcblist; - CK_LIST_ENTRY(inpcbport) phd_hash; - u_short phd_port; +/* + * Load balance groups used for the SO_REUSEPORT_LB socket option. Each group + * (or unique address:port combination) can be re-used at most + * INPCBLBGROUP_SIZMAX (256) times. The inpcbs are stored in il_inp which + * is dynamically resized as processes bind/unbind to that specific group. + */ +struct inpcblbgroup { + CK_LIST_ENTRY(inpcblbgroup) il_list; + LIST_HEAD(, inpcb) il_pending; /* PCBs waiting for listen() */ + struct epoch_context il_epoch_ctx; + struct ucred *il_cred; + uint16_t il_lport; /* (c) */ + u_char il_vflag; /* (c) */ + uint8_t il_numa_domain; + int il_fibnum; + union in_dependaddr il_dependladdr; /* (c) */ +#define il_laddr il_dependladdr.id46_addr.ia46_addr4 +#define il6_laddr il_dependladdr.id6_addr + uint32_t il_inpsiz; /* max count in il_inp[] (h) */ + uint32_t il_inpcnt; /* cur count in il_inp[] (h) */ + uint32_t il_pendcnt; /* cur count in il_pending (h) */ + struct inpcb *il_inp[]; /* (h) */ }; #endif /* !_NETINET_IN_PCB_VAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/netinet/in_systm.h b/lib/libc/include/generic-freebsd/netinet/in_systm.h index aa601357a80d..b4e5879c810b 100644 --- a/lib/libc/include/generic-freebsd/netinet/in_systm.h +++ b/lib/libc/include/generic-freebsd/netinet/in_systm.h @@ -27,13 +27,13 @@ * 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. - * - * @(#)in_systm.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NETINET_IN_SYSTM_H_ #define _NETINET_IN_SYSTM_H_ +#include + /* * Miscellaneous internetwork * definitions for kernel. @@ -58,8 +58,10 @@ typedef u_int32_t n_time; /* ms since 00:00 UTC, byte rev */ #ifdef _KERNEL struct inpcb; struct ucred; +struct thread; int cr_canseeinpcb(struct ucred *cred, struct inpcb *inp); +bool cr_canexport_ktlskeys(struct thread *td, struct inpcb *inp); uint32_t iptime(void); #endif diff --git a/lib/libc/include/generic-freebsd/netinet/in_var.h b/lib/libc/include/generic-freebsd/netinet/in_var.h index 96557fc052ac..7282aac363f0 100644 --- a/lib/libc/include/generic-freebsd/netinet/in_var.h +++ b/lib/libc/include/generic-freebsd/netinet/in_var.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)in_var.h 8.2 (Berkeley) 1/9/95 */ #ifndef _NETINET_IN_VAR_H_ @@ -99,6 +97,11 @@ struct in_ifaddr { #define IN_LNAOF(in, ifa) \ ((ntohl((in).s_addr) & ~((struct in_ifaddr *)(ifa)->ia_subnetmask)) +#ifdef _KERNEL +#define IN_ARE_MASKED_ADDR_EQUAL(d, a, m) ( \ + ((((d).s_addr ^ (a).s_addr) & (m).s_addr)) == 0 ) +#endif + #define LLTABLE(ifp) \ ((struct in_ifinfo *)(ifp)->if_afdata[AF_INET])->ii_llt /* @@ -456,6 +459,7 @@ int in_joingroup_locked(struct ifnet *, const struct in_addr *, int in_leavegroup(struct in_multi *, /*const*/ struct in_mfilter *); int in_leavegroup_locked(struct in_multi *, /*const*/ struct in_mfilter *); +int in_mask2len(struct in_addr *); int in_control(struct socket *, u_long, void *, struct ifnet *, struct thread *); int in_control_ioctl(u_long, void *, struct ifnet *, diff --git a/lib/libc/include/generic-freebsd/netinet/ip.h b/lib/libc/include/generic-freebsd/netinet/ip.h index 636b48e62341..1843027a58e7 100644 --- a/lib/libc/include/generic-freebsd/netinet/ip.h +++ b/lib/libc/include/generic-freebsd/netinet/ip.h @@ -28,14 +28,13 @@ * 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. - * - * @(#)ip.h 8.2 (Berkeley) 6/1/94 */ #ifndef _NETINET_IP_H_ #define _NETINET_IP_H_ -#include +#include +#include /* * Definitions for internet protocol version 4. @@ -68,7 +67,7 @@ struct ip { u_char ip_p; /* protocol */ u_short ip_sum; /* checksum */ struct in_addr ip_src,ip_dst; /* source and dest address */ -} __packed __aligned(2); +} __packed; #define IP_MAXPACKET 65535 /* maximum packet size */ @@ -188,7 +187,7 @@ struct ip_timestamp { uint32_t ipt_time; /* network format */ } ipt_ta[1]; } ipt_timestamp; -}; +} __packed; /* Flag bits for ipt_flg. */ #define IPOPT_TS_TSONLY 0 /* timestamps only */ diff --git a/lib/libc/include/generic-freebsd/netinet/ip6.h b/lib/libc/include/generic-freebsd/netinet/ip6.h index 873cf9a91008..b26826250ad4 100644 --- a/lib/libc/include/generic-freebsd/netinet/ip6.h +++ b/lib/libc/include/generic-freebsd/netinet/ip6.h @@ -58,8 +58,6 @@ * 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. - * - * @(#)ip.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NETINET_IP6_H_ diff --git a/lib/libc/include/generic-freebsd/netinet/ip_carp.h b/lib/libc/include/generic-freebsd/netinet/ip_carp.h index c043153d3007..495e298a6b9b 100644 --- a/lib/libc/include/generic-freebsd/netinet/ip_carp.h +++ b/lib/libc/include/generic-freebsd/netinet/ip_carp.h @@ -31,6 +31,7 @@ #ifndef _IP_CARP_H #define _IP_CARP_H +#ifdef _KERNEL /* * The CARP header layout is as follows: * @@ -77,14 +78,53 @@ struct carp_header { unsigned char carp_md[20]; /* SHA1 HMAC */ } __packed; -#ifdef CTASSERT CTASSERT(sizeof(struct carp_header) == 36); + +/* + * The VRRPv3 header layout is as follows: + * See RFC9568, 5.1. VRRP Packet Format + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |Version| Type | Virtual Rtr ID| Priority |Count IPvX Addr| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |(rsvd) | Max Adver Int | Checksum | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | + * + + + * | IPvX Address(es) | + * + + + * + + + * + + + * + + + * | | + * + + + * | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ + +struct vrrpv3_header { +#if BYTE_ORDER == LITTLE_ENDIAN + uint8_t vrrp_type:4, + vrrp_version:4; +#endif +#if BYTE_ORDER == BIG_ENDIAN + uint8_t vrrp_version:4, + vrrp_type:4; #endif + uint8_t vrrp_vrtid; + uint8_t vrrp_priority; + uint8_t vrrp_count_addr; + uint16_t vrrp_max_adver_int; + uint16_t vrrp_checksum; +} __packed; -#define CARP_DFLTTL 255 +CTASSERT(sizeof(struct vrrpv3_header) == 8); +#endif /* _KERNEL */ -/* carp_version */ -#define CARP_VERSION 2 +#define CARP_DFLTTL 255 /* carp_type */ #define CARP_ADVERTISEMENT 0x01 @@ -94,6 +134,8 @@ CTASSERT(sizeof(struct carp_header) == 36); /* carp_advbase */ #define CARP_DFLTINTV 1 +#define VRRP_TYPE_ADVERTISEMENT 0x01 +#define VRRP_MAX_INTERVAL (0x1000 - 1) /* * Statistics. */ @@ -136,6 +178,11 @@ struct carpreq { #define SIOCSVH _IOWR('i', 245, struct ifreq) #define SIOCGVH _IOWR('i', 246, struct ifreq) +typedef enum carp_version { + CARP_VERSION_CARP = 2, + CARP_VERSION_VRRPv3 = 3, +} carp_version_t; + #ifdef _KERNEL int carp_ioctl(struct ifreq *, u_long, struct thread *); int carp_attach(struct ifaddr *, int); diff --git a/lib/libc/include/generic-freebsd/netinet/ip_carp_nl.h b/lib/libc/include/generic-freebsd/netinet/ip_carp_nl.h index 3f56c8170ae9..ab155b6ba6ed 100644 --- a/lib/libc/include/generic-freebsd/netinet/ip_carp_nl.h +++ b/lib/libc/include/generic-freebsd/netinet/ip_carp_nl.h @@ -32,6 +32,9 @@ enum carp_nl_type_t { CARP_NL_ADDR = 7, /* in_addr_t */ CARP_NL_ADDR6 = 8, /* in6_addr_t */ CARP_NL_IFNAME = 9, /* string */ + CARP_NL_VERSION = 10, /* u8 */ + CARP_NL_VRRP_PRIORITY = 11, /* u8 */ + CARP_NL_VRRP_ADV_INTER = 12, /* u16, 12-bit field in centiseconds*/ }; #endif \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/netinet/ip_compat.h b/lib/libc/include/generic-freebsd/netinet/ip_compat.h index ee33c6515aca..5ca48ab9928e 100644 --- a/lib/libc/include/generic-freebsd/netinet/ip_compat.h +++ b/lib/libc/include/generic-freebsd/netinet/ip_compat.h @@ -2,8 +2,6 @@ * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. - * - * @(#)ip_compat.h 1.8 1/14/96 * Id: ip_compat.h,v 2.142.2.57 2007/10/10 09:51:42 darrenr Exp $ */ @@ -689,12 +687,6 @@ typedef struct tcpiphdr tcpiphdr_t; #ifndef IP_HL_A # define IP_HL_A(x,y) (x)->ip_hl = ((y) & 0xf) #endif -#ifndef TCP_X2 -# define TCP_X2(x) (x)->th_x2 -#endif -#ifndef TCP_X2_A -# define TCP_X2_A(x,y) (x)->th_x2 = (y) -#endif #ifndef TCP_OFF # define TCP_OFF(x) (x)->th_off #endif @@ -703,9 +695,6 @@ typedef struct tcpiphdr tcpiphdr_t; #endif #define IPMINLEN(i, h) ((i)->ip_len >= (IP_HL(i) * 4 + sizeof(struct h))) -#define TCPF_ALL (TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG|\ - TH_ECN|TH_CWR) - #if !SOLARIS && !defined(m_act) # define m_act m_nextpkt #endif @@ -1136,7 +1125,10 @@ typedef struct tcpiphdr tcpiphdr_t; #ifndef TH_CWR # define TH_CWR 0x80 #endif -#define TH_ECNALL (TH_ECN|TH_CWR) +#ifndef TH_AE +# define TH_AE 0x100 +#endif +#define TH_ECNALL (TH_ECN|TH_CWR|TH_AE) /* * TCP States diff --git a/lib/libc/include/generic-freebsd/netinet/ip_dummynet.h b/lib/libc/include/generic-freebsd/netinet/ip_dummynet.h index 23e61b4135f8..035dfa92463d 100644 --- a/lib/libc/include/generic-freebsd/netinet/ip_dummynet.h +++ b/lib/libc/include/generic-freebsd/netinet/ip_dummynet.h @@ -145,7 +145,7 @@ struct dn_fs { uint32_t fs_nr; /* the flowset number */ uint32_t flags; /* userland flags */ int qsize; /* queue size in slots or bytes */ - int32_t plr; /* PLR, pkt loss rate (2^31-1 means 100%) */ + int32_t pl_state; /* packet loss state */ uint32_t buckets; /* buckets used for the queue hash table */ struct ipfw_flow_id flow_mask; @@ -168,6 +168,7 @@ struct dn_fs { int min_th ; /* minimum threshold for queue (scaled) */ int max_p ; /* maximum value for p_b (scaled) */ + int32_t plr[4]; /* PLR, pkt loss rate (2^31-1 means 100%) */ }; /* diff --git a/lib/libc/include/generic-freebsd/netinet/ip_fil.h b/lib/libc/include/generic-freebsd/netinet/ip_fil.h index 0a169736393e..db2689cc38f0 100644 --- a/lib/libc/include/generic-freebsd/netinet/ip_fil.h +++ b/lib/libc/include/generic-freebsd/netinet/ip_fil.h @@ -2,8 +2,6 @@ * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. - * - * @(#)ip_fil.h 1.35 6/5/96 * Id: ip_fil.h,v 2.170.2.51 2007/10/10 09:48:03 darrenr Exp $ */ diff --git a/lib/libc/include/generic-freebsd/netinet/ip_frag.h b/lib/libc/include/generic-freebsd/netinet/ip_frag.h index dcd6d4d1652b..25602dbab84f 100644 --- a/lib/libc/include/generic-freebsd/netinet/ip_frag.h +++ b/lib/libc/include/generic-freebsd/netinet/ip_frag.h @@ -2,8 +2,6 @@ * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. - * - * @(#)ip_frag.h 1.5 3/24/96 * Id: ip_frag.h,v 2.23.2.1 2004/03/29 16:21:56 darrenr Exp */ diff --git a/lib/libc/include/generic-freebsd/netinet/ip_fw.h b/lib/libc/include/generic-freebsd/netinet/ip_fw.h index a6002a6c5a92..76b1ee577226 100644 --- a/lib/libc/include/generic-freebsd/netinet/ip_fw.h +++ b/lib/libc/include/generic-freebsd/netinet/ip_fw.h @@ -75,6 +75,10 @@ typedef struct _ip_fw3_opheader { uint16_t reserved[2]; /* Align to 64-bit boundary */ } ip_fw3_opheader; +#define IP_FW3_OPVER_0 0 +#define IP_FW3_OPVER_1 1 /* 32bit rulenum */ +#define IP_FW3_OPVER IP_FW3_OPVER_1 + /* IP_FW3 opcodes */ #define IP_FW_TABLE_XADD 86 /* add entry */ #define IP_FW_TABLE_XDEL 87 /* delete entry */ @@ -109,6 +113,7 @@ typedef struct _ip_fw3_opheader { #define IP_FW_DUMP_SOPTCODES 116 /* Dump available sopts/versions */ #define IP_FW_DUMP_SRVOBJECTS 117 /* Dump existing named objects */ +#define IP_FW_SKIPTO_CACHE 118 /* Manage skipto cache */ #define IP_FW_NAT64STL_CREATE 130 /* Create stateless NAT64 instance */ #define IP_FW_NAT64STL_DESTROY 131 /* Destroy stateless NAT64 instance */ @@ -162,162 +167,153 @@ typedef struct _ip_fw3_opheader { */ enum ipfw_opcodes { /* arguments (4 byte each) */ - O_NOP, - - O_IP_SRC, /* u32 = IP */ - O_IP_SRC_MASK, /* ip = IP/mask */ - O_IP_SRC_ME, /* none */ - O_IP_SRC_SET, /* u32=base, arg1=len, bitmap */ - - O_IP_DST, /* u32 = IP */ - O_IP_DST_MASK, /* ip = IP/mask */ - O_IP_DST_ME, /* none */ - O_IP_DST_SET, /* u32=base, arg1=len, bitmap */ - - O_IP_SRCPORT, /* (n)port list:mask 4 byte ea */ - O_IP_DSTPORT, /* (n)port list:mask 4 byte ea */ - O_PROTO, /* arg1=protocol */ - - O_MACADDR2, /* 2 mac addr:mask */ - O_MAC_TYPE, /* same as srcport */ - - O_LAYER2, /* none */ - O_IN, /* none */ - O_FRAG, /* none */ - - O_RECV, /* none */ - O_XMIT, /* none */ - O_VIA, /* none */ - - O_IPOPT, /* arg1 = 2*u8 bitmap */ - O_IPLEN, /* arg1 = len */ - O_IPID, /* arg1 = id */ - - O_IPTOS, /* arg1 = id */ - O_IPPRECEDENCE, /* arg1 = precedence << 5 */ - O_IPTTL, /* arg1 = TTL */ - - O_IPVER, /* arg1 = version */ - O_UID, /* u32 = id */ - O_GID, /* u32 = id */ - O_ESTAB, /* none (tcp established) */ - O_TCPFLAGS, /* arg1 = 2*u8 bitmap */ - O_TCPWIN, /* arg1 = desired win */ - O_TCPSEQ, /* u32 = desired seq. */ - O_TCPACK, /* u32 = desired seq. */ - O_ICMPTYPE, /* u32 = icmp bitmap */ - O_TCPOPTS, /* arg1 = 2*u8 bitmap */ - - O_VERREVPATH, /* none */ - O_VERSRCREACH, /* none */ - - O_PROBE_STATE, /* none */ - O_KEEP_STATE, /* none */ - O_LIMIT, /* ipfw_insn_limit */ - O_LIMIT_PARENT, /* dyn_type, not an opcode. */ + O_NOP = 0, + + O_IP_SRC = 1, /* u32 = IP */ + O_IP_SRC_MASK = 2, /* ip = IP/mask */ + O_IP_SRC_ME = 3, /* none */ + O_IP_SRC_SET = 4, /* u32=base, arg1=len, bitmap */ + + O_IP_DST = 5, /* u32 = IP */ + O_IP_DST_MASK = 6, /* ip = IP/mask */ + O_IP_DST_ME = 7, /* none */ + O_IP_DST_SET = 8, /* u32=base, arg1=len, bitmap */ + + O_IP_SRCPORT = 9, /* (n)port list:mask 4 byte ea */ + O_IP_DSTPORT = 10, /* (n)port list:mask 4 byte ea */ + O_PROTO = 11, /* arg1=protocol */ + + O_MACADDR2 = 12, /* 2 mac addr:mask */ + O_MAC_TYPE = 13, /* same as srcport */ + + O_LAYER2 = 14, /* none */ + O_IN = 15, /* none */ + O_FRAG = 16, /* none */ + + O_RECV = 17, /* none */ + O_XMIT = 18, /* none */ + O_VIA = 19, /* none */ + + O_IPOPT = 20, /* arg1 = 2*u8 bitmap */ + O_IPLEN = 21, /* arg1 = len */ + O_IPID = 22, /* arg1 = id */ + + O_IPTOS = 23, /* arg1 = id */ + O_IPPRECEDENCE = 24, /* arg1 = precedence << 5 */ + O_IPTTL = 25, /* arg1 = TTL */ + + O_IPVER = 26, /* arg1 = version */ + O_UID = 27, /* u32 = id */ + O_GID = 28, /* u32 = id */ + O_ESTAB = 29, /* none (tcp established) */ + O_TCPFLAGS = 30, /* arg1 = 2*u8 bitmap */ + O_TCPWIN = 31, /* arg1 = desired win */ + O_TCPSEQ = 32, /* u32 = desired seq. */ + O_TCPACK = 33, /* u32 = desired seq. */ + O_ICMPTYPE = 34, /* u32 = icmp bitmap */ + O_TCPOPTS = 35, /* arg1 = 2*u8 bitmap */ + + O_VERREVPATH = 36, /* none */ + O_VERSRCREACH = 37, /* none */ + + O_PROBE_STATE = 38, /* v0:arg1=kidx, v1:kidx=kidx */ + O_KEEP_STATE = 39, /* v0:arg1=kidx, v1:kidx=kidx */ + O_LIMIT = 40, /* ipfw_insn_limit */ + O_LIMIT_PARENT = 41, /* dyn_type, not an opcode. */ /* * These are really 'actions'. */ - O_LOG, /* ipfw_insn_log */ - O_PROB, /* u32 = match probability */ - - O_CHECK_STATE, /* none */ - O_ACCEPT, /* none */ - O_DENY, /* none */ - O_REJECT, /* arg1=icmp arg (same as deny) */ - O_COUNT, /* none */ - O_SKIPTO, /* arg1=next rule number */ - O_PIPE, /* arg1=pipe number */ - O_QUEUE, /* arg1=queue number */ - O_DIVERT, /* arg1=port number */ - O_TEE, /* arg1=port number */ - O_FORWARD_IP, /* fwd sockaddr */ - O_FORWARD_MAC, /* fwd mac */ - O_NAT, /* nope */ - O_REASS, /* none */ + O_LOG = 42, /* ipfw_insn_log */ + O_PROB = 43, /* u32 = match probability */ + + O_CHECK_STATE = 44, /* v0:arg1=kidx, v1:kidx=kidx */ + O_ACCEPT = 45, /* none */ + O_DENY = 46, /* none */ + O_REJECT = 47, /* arg1=icmp arg (same as deny) */ + O_COUNT = 48, /* none */ + O_SKIPTO = 49, /* v0:arg1=next rule number */ + /* v1:kidx= next rule number */ + O_PIPE = 50, /* arg1=pipe number */ + O_QUEUE = 51, /* arg1=queue number */ + O_DIVERT = 52, /* arg1=port number */ + O_TEE = 53, /* arg1=port number */ + O_FORWARD_IP = 54, /* fwd sockaddr */ + O_FORWARD_MAC = 55, /* fwd mac */ + O_NAT = 56, /* nope */ + O_REASS = 57, /* none */ /* * More opcodes. */ - O_IPSEC, /* has ipsec history */ - O_IP_SRC_LOOKUP, /* arg1=table number, u32=value */ - O_IP_DST_LOOKUP, /* arg1=table number, u32=value */ - O_ANTISPOOF, /* none */ - O_JAIL, /* u32 = id */ - O_ALTQ, /* u32 = altq classif. qid */ - O_DIVERTED, /* arg1=bitmap (1:loop, 2:out) */ - O_TCPDATALEN, /* arg1 = tcp data len */ - O_IP6_SRC, /* address without mask */ - O_IP6_SRC_ME, /* my addresses */ - O_IP6_SRC_MASK, /* address with the mask */ - O_IP6_DST, - O_IP6_DST_ME, - O_IP6_DST_MASK, - O_FLOW6ID, /* for flow id tag in the ipv6 pkt */ - O_ICMP6TYPE, /* icmp6 packet type filtering */ - O_EXT_HDR, /* filtering for ipv6 extension header */ - O_IP6, + O_IPSEC = 58, /* has ipsec history */ + O_IP_SRC_LOOKUP = 59, /* v0:arg1=table number, u32=value */ + /* v1:kidx=name, u32=value, arg1=key */ + O_IP_DST_LOOKUP = 60, /* arg1=table number, u32=value */ + /* v1:kidx=name, u32=value, arg1=key */ + O_ANTISPOOF = 61, /* none */ + O_JAIL = 62, /* u32 = id */ + O_ALTQ = 63, /* u32 = altq classif. qid */ + O_DIVERTED = 64, /* arg1=bitmap (1:loop, 2:out) */ + O_TCPDATALEN = 65, /* arg1 = tcp data len */ + O_IP6_SRC = 66, /* address without mask */ + O_IP6_SRC_ME = 67, /* my addresses */ + O_IP6_SRC_MASK = 68, /* address with the mask */ + O_IP6_DST = 69, + O_IP6_DST_ME = 70, + O_IP6_DST_MASK = 71, + O_FLOW6ID = 72, /* for flow id tag in the ipv6 pkt */ + O_ICMP6TYPE = 73, /* icmp6 packet type filtering */ + O_EXT_HDR = 74, /* filtering for ipv6 extension header */ + O_IP6 = 75, /* * actions for ng_ipfw */ - O_NETGRAPH, /* send to ng_ipfw */ - O_NGTEE, /* copy to ng_ipfw */ + O_NETGRAPH = 76, /* send to ng_ipfw */ + O_NGTEE = 77, /* copy to ng_ipfw */ - O_IP4, + O_IP4 = 78, - O_UNREACH6, /* arg1=icmpv6 code arg (deny) */ + O_UNREACH6 = 79, /* arg1=icmpv6 code arg (deny) */ - O_TAG, /* arg1=tag number */ - O_TAGGED, /* arg1=tag number */ + O_TAG = 80, /* arg1=tag number */ + O_TAGGED = 81, /* arg1=tag number */ - O_SETFIB, /* arg1=FIB number */ - O_FIB, /* arg1=FIB desired fib number */ + O_SETFIB = 82, /* arg1=FIB number */ + O_FIB = 83, /* arg1=FIB desired fib number */ - O_SOCKARG, /* socket argument */ + O_SOCKARG = 84, /* socket argument */ - O_CALLRETURN, /* arg1=called rule number */ + O_CALLRETURN = 85, /* v0:arg1=called rule number */ + /* v1:kidx=called rule number */ - O_FORWARD_IP6, /* fwd sockaddr_in6 */ + O_FORWARD_IP6 = 86, /* fwd sockaddr_in6 */ - O_DSCP, /* 2 u32 = DSCP mask */ - O_SETDSCP, /* arg1=DSCP value */ - O_IP_FLOW_LOOKUP, /* arg1=table number, u32=value */ + O_DSCP = 87, /* 2 u32 = DSCP mask */ + O_SETDSCP = 88, /* arg1=DSCP value */ + O_IP_FLOW_LOOKUP = 89, /* v0:arg1=table number, u32=value */ + /* v1:kidx=name, u32=value */ - O_EXTERNAL_ACTION, /* arg1=id of external action handler */ - O_EXTERNAL_INSTANCE, /* arg1=id of eaction handler instance */ - O_EXTERNAL_DATA, /* variable length data */ + O_EXTERNAL_ACTION = 90, /* v0:arg1=id of external action handler */ + /* v1:kidx=id of external action handler */ + O_EXTERNAL_INSTANCE = 91, /* v0:arg1=id of eaction handler instance */ + /* v1:kidx=id of eaction handler instance */ + O_EXTERNAL_DATA = 92, /* variable length data */ - O_SKIP_ACTION, /* none */ - O_TCPMSS, /* arg1=MSS value */ + O_SKIP_ACTION = 93, /* none */ + O_TCPMSS = 94, /* arg1=MSS value */ - O_MAC_SRC_LOOKUP, /* arg1=table number, u32=value */ - O_MAC_DST_LOOKUP, /* arg1=table number, u32=value */ + O_MAC_SRC_LOOKUP = 95, /* kidx=name, u32=value, arg1=key */ + O_MAC_DST_LOOKUP = 96, /* kidx=name, u32=value, arg1=key */ - O_SETMARK, /* u32 = value */ - O_MARK, /* 2 u32 = value, bitmask */ + O_SETMARK = 97, /* u32 = value */ + O_MARK = 98, /* 2 u32 = value, bitmask */ O_LAST_OPCODE /* not an opcode! */ }; -/* - * Defines key types used by lookup instruction - */ -enum ipfw_table_lookup_type { - LOOKUP_DST_IP, - LOOKUP_SRC_IP, - LOOKUP_DST_PORT, - LOOKUP_SRC_PORT, - LOOKUP_UID, - LOOKUP_JAIL, - LOOKUP_DSCP, - LOOKUP_DST_MAC, - LOOKUP_SRC_MAC, - LOOKUP_MARK, -}; - /* * The extension header are filtered only for presence using a bit * vector with a flag for each header. @@ -392,6 +388,11 @@ typedef struct _ipfw_insn_u32 { u_int32_t d[1]; /* one or more */ } ipfw_insn_u32; +typedef struct _ipfw_insn_kidx { + ipfw_insn o; + uint32_t kidx; +} ipfw_insn_kidx; + /* * This is used to store IP addr-mask pairs. */ @@ -401,6 +402,47 @@ typedef struct _ipfw_insn_ip { struct in_addr mask; } ipfw_insn_ip; +typedef struct _ipfw_insn_table { + ipfw_insn o; /* arg1 is optional lookup key */ + uint32_t kidx; /* table name index */ + uint32_t value; /* table value */ +} ipfw_insn_table; + +#define IPFW_LOOKUP_TYPE_MASK 0x00FF +#define IPFW_LOOKUP_TYPE(insn) ((insn)->arg1 & IPFW_LOOKUP_TYPE_MASK) +#define IPFW_SET_LOOKUP_TYPE(insn, type) do { \ + (insn)->arg1 &= ~IPFW_LOOKUP_TYPE_MASK; \ + (insn)->arg1 |= (type) & IPFW_LOOKUP_TYPE_MASK; \ +} while (0) + +/* + * Defines key types used by lookup instruction + */ +enum ipfw_table_lookup_type { + LOOKUP_NONE = 0, + LOOKUP_DST_IP, + LOOKUP_SRC_IP, + LOOKUP_DST_PORT, + LOOKUP_SRC_PORT, + LOOKUP_UID, + LOOKUP_JAIL, + LOOKUP_DSCP, + LOOKUP_DST_MAC, + LOOKUP_SRC_MAC, + LOOKUP_MARK, + LOOKUP_RULENUM, +}; + +enum ipfw_return_type { + RETURN_NEXT_RULENUM = 0, + RETURN_NEXT_RULE, +}; + +enum ipfw_skipto_cache_op { + SKIPTO_CACHE_DISABLE = 0, + SKIPTO_CACHE_ENABLE, +}; + /* * This is used to forward to a given address (ip). */ @@ -434,7 +476,8 @@ typedef struct _ipfw_insn_if { union { struct in_addr ip; int glob; - uint16_t kidx; + uint16_t kidx_v0; + uint32_t kidx; } p; char name[IFNAMSIZ]; } ipfw_insn_if; @@ -452,6 +495,7 @@ typedef struct _ipfw_insn_altq { */ typedef struct _ipfw_insn_limit { ipfw_insn o; + u_int32_t kidx; u_int8_t _pad; u_int8_t limit_mask; /* combination of DYN_* below */ #define DYN_SRC_ADDR 0x1 @@ -462,6 +506,9 @@ typedef struct _ipfw_insn_limit { u_int16_t conn_limit; } ipfw_insn_limit; +/* MAC/InfiniBand/etc address length */ +#define IPFW_MAX_L2_ADDR_LEN 20 + /* * This is used for log instructions. */ @@ -471,6 +518,22 @@ typedef struct _ipfw_insn_log { u_int32_t log_left; /* how many left to log */ } ipfw_insn_log; +/* ipfw_insn_log->o.arg1 bitmasks */ +#define IPFW_LOG_DEFAULT 0x0000 +#define IPFW_LOG_SYSLOG (1 << 15) +#define IPFW_LOG_IPFW0 (1 << 14) +#define IPFW_LOG_RTSOCK (1 << 13) + +typedef struct _ipfwlog_rtsock_hdr_v2 { + uint32_t rulenum; + uint32_t tablearg; + ipfw_insn cmd; + u_char ether_shost[IPFW_MAX_L2_ADDR_LEN]; + u_char ether_dhost[IPFW_MAX_L2_ADDR_LEN]; + uint32_t mark; + char comment[0]; +} ipfwlog_rtsock_hdr_v2; + /* Legacy NAT structures, compat only */ #ifndef _KERNEL /* @@ -604,6 +667,10 @@ typedef struct _ipfw_insn_icmp6 { */ } ipfw_insn_icmp6; +/* Convert pointer to instruction with specified type */ +#define insntod(p, type) ((ipfw_insn_ ## type *)(p)) +#define insntoc(p, type) ((const ipfw_insn_ ## type *)(p)) + /* * Here we have the structure representing an ipfw rule. * @@ -719,30 +786,29 @@ struct ipfw_flow_id { /* * Dynamic ipfw rule. */ -typedef struct _ipfw_dyn_rule ipfw_dyn_rule; - -struct _ipfw_dyn_rule { - ipfw_dyn_rule *next; /* linked list of rules. */ - struct ip_fw *rule; /* pointer to rule */ - /* 'rule' is used to pass up the rule number (from the parent) */ +#define IPFW_DYN_ORPHANED 0x40000 /* state's parent rule was deleted */ - ipfw_dyn_rule *parent; /* pointer to parent rule */ - u_int64_t pcnt; /* packet match counter */ - u_int64_t bcnt; /* byte match counter */ +typedef struct _ipfw_dyn_rule { struct ipfw_flow_id id; /* (masked) flow id */ - u_int32_t expire; /* expire time */ - u_int32_t bucket; /* which bucket in hash table */ - u_int32_t state; /* state of this rule (typically a + uint8_t set; + uint8_t type; /* rule type */ + uint16_t pad; + uint32_t expire; /* expire time */ + uint32_t rulenum; /* parent's rule number */ + uint32_t kidx; /* index of named object */ + uint64_t pcnt; /* packet match counter */ + uint64_t bcnt; /* byte match counter */ + uint32_t hashval; /* hash value */ + union { + uint32_t state; /* state of this rule (typically a * combination of TCP flags) */ -#define IPFW_DYN_ORPHANED 0x40000 /* state's parent rule was deleted */ - u_int32_t ack_fwd; /* most recent ACKs in forward */ - u_int32_t ack_rev; /* and reverse directions (used */ + uint32_t count; /* number of linked states */ + }; + uint32_t ack_fwd; /* most recent ACKs in forward */ + uint32_t ack_rev; /* and reverse directions (used */ /* to generate keepalives) */ - u_int16_t dyn_type; /* rule type */ - u_int16_t count; /* refcount */ - u_int16_t kidx; /* index of named object */ -} __packed __aligned(8); +} __packed __aligned(8) ipfw_dyn_rule; /* * Definitions for IP option names. @@ -794,16 +860,6 @@ struct _ipfw_dyn_rule { #define IPFW_VTYPE_NH6 0x00000400 /* IPv6 nexthop */ #define IPFW_VTYPE_MARK 0x00000800 /* [fw]mark */ -/* MAC/InfiniBand/etc address length */ -#define IPFW_MAX_L2_ADDR_LEN 20 - -typedef struct _ipfw_table_entry { - in_addr_t addr; /* network address */ - u_int32_t value; /* value */ - u_int16_t tbl; /* table number */ - u_int8_t masklen; /* mask length */ -} ipfw_table_entry; - typedef struct _ipfw_table_xentry { uint16_t len; /* Total entry length */ uint8_t type; /* entry type */ @@ -819,13 +875,6 @@ typedef struct _ipfw_table_xentry { } ipfw_table_xentry; #define IPFW_TCF_INET 0x01 /* CIDR flags: IPv4 record */ -typedef struct _ipfw_table { - u_int32_t size; /* size of entries in bytes */ - u_int32_t cnt; /* # of entries */ - u_int16_t tbl; /* table number */ - ipfw_table_entry ent[0]; /* entries */ -} ipfw_table; - typedef struct _ipfw_xtable { ip_fw3_opheader opheader; /* IP_FW3 opcode */ uint32_t size; /* size of entries in bytes */ @@ -865,10 +914,10 @@ typedef struct _ipfw_obj_data { /* Object name TLV */ typedef struct _ipfw_obj_ntlv { ipfw_obj_tlv head; /* TLV header */ - uint16_t idx; /* Name index */ + uint32_t idx; /* Name index */ uint8_t set; /* set, if applicable */ uint8_t type; /* object type, if applicable */ - uint32_t spare; /* unused */ + uint16_t spare; /* unused */ char name[64]; /* Null-terminated name */ } ipfw_obj_ntlv; @@ -891,19 +940,40 @@ struct tflow_entry { } a; }; +#define IPFW_TVALUE_TYPE_MASK 0xFF00 +#define IPFW_TVALUE_TYPE(insn) (((insn)->arg1 & IPFW_TVALUE_TYPE_MASK) >> 8) +#define IPFW_SET_TVALUE_TYPE(insn, type) do { \ + (insn)->arg1 &= ~IPFW_TVALUE_TYPE_MASK; \ + (insn)->arg1 |= ((type) << 8) & IPFW_TVALUE_TYPE_MASK; \ +} while (0) + +enum ipfw_table_value_type { + TVALUE_TAG = 0, + TVALUE_PIPE, + TVALUE_DIVERT, + TVALUE_SKIPTO, + TVALUE_NETGRAPH, + TVALUE_FIB, + TVALUE_NAT, + TVALUE_NH4, + TVALUE_DSCP, + TVALUE_LIMIT, + TVALUE_MARK, +}; + /* 64-byte structure representing multi-field table value */ typedef struct _ipfw_table_value { uint32_t tag; /* O_TAG/O_TAGGED */ - uint32_t pipe; /* O_PIPE/O_QUEUE */ + uint16_t pipe; /* O_PIPE/O_QUEUE */ uint16_t divert; /* O_DIVERT/O_TEE */ - uint16_t skipto; /* skipto, CALLRET */ + uint32_t skipto; /* skipto, CALLRET */ uint32_t netgraph; /* O_NETGRAPH/O_NGTEE */ - uint32_t fib; /* O_SETFIB */ uint32_t nat; /* O_NAT */ uint32_t nh4; + uint16_t fib; /* O_SETFIB */ uint8_t dscp; uint8_t spare0; - uint16_t kidx; /* value kernel index */ + uint32_t kidx; /* value kernel index */ struct in6_addr nh6; uint32_t limit; /* O_LIMIT */ uint32_t zoneid; /* scope zone id for nh6 */ @@ -918,8 +988,7 @@ typedef struct _ipfw_obj_tentry { uint8_t masklen; /* mask length */ uint8_t result; /* request result */ uint8_t spare0; - uint16_t idx; /* Table name index */ - uint16_t spare1; + uint32_t idx; /* Table name index */ union { /* Longest field needs to be aligned by 8-byte boundary */ struct in_addr addr; /* IPv4 address */ @@ -966,8 +1035,8 @@ typedef struct _ipfw_obj_ctlv { typedef struct _ipfw_range_tlv { ipfw_obj_tlv head; /* TLV header */ uint32_t flags; /* Range flags */ - uint16_t start_rule; /* Range start */ - uint16_t end_rule; /* Range end */ + uint32_t start_rule; /* Range start */ + uint32_t end_rule; /* Range end */ uint32_t set; /* Range set to match */ uint32_t new_set; /* New set to move/swap to */ } ipfw_range_tlv; @@ -1051,10 +1120,16 @@ typedef struct _ipfw_ta_info { uint64_t spare1; } ipfw_ta_info; +typedef struct _ipfw_cmd_header { /* control command header */ + ip_fw3_opheader opheader; /* IP_FW3 opcode */ + uint32_t size; /* Total size (incl. header) */ + uint32_t cmd; /* command */ +} ipfw_cmd_header; + typedef struct _ipfw_obj_header { ip_fw3_opheader opheader; /* IP_FW3 opcode */ - uint32_t spare; - uint16_t idx; /* object name index */ + uint32_t idx; /* object name index */ + uint16_t spare; uint8_t objtype; /* object type */ uint8_t objsubtype; /* object subtype */ ipfw_obj_ntlv ntlv; /* object name tlv */ diff --git a/lib/libc/include/generic-freebsd/netinet/ip_icmp.h b/lib/libc/include/generic-freebsd/netinet/ip_icmp.h index 68b017287a8b..a1c025d1afd7 100644 --- a/lib/libc/include/generic-freebsd/netinet/ip_icmp.h +++ b/lib/libc/include/generic-freebsd/netinet/ip_icmp.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NETINET_IP_ICMP_H_ diff --git a/lib/libc/include/generic-freebsd/netinet/ip_mroute.h b/lib/libc/include/generic-freebsd/netinet/ip_mroute.h index 6dbb6ae90943..a57b0de54fde 100644 --- a/lib/libc/include/generic-freebsd/netinet/ip_mroute.h +++ b/lib/libc/include/generic-freebsd/netinet/ip_mroute.h @@ -31,8 +31,6 @@ * 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. - * - * @(#)ip_mroute.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NETINET_IP_MROUTE_H_ diff --git a/lib/libc/include/generic-freebsd/netinet/ip_nat.h b/lib/libc/include/generic-freebsd/netinet/ip_nat.h index 7c2defc30604..81da2c778d84 100644 --- a/lib/libc/include/generic-freebsd/netinet/ip_nat.h +++ b/lib/libc/include/generic-freebsd/netinet/ip_nat.h @@ -2,8 +2,6 @@ * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. - * - * @(#)ip_nat.h 1.5 2/4/96 * Id: ip_nat.h,v 2.90.2.20 2007/09/25 08:27:32 darrenr Exp $ */ diff --git a/lib/libc/include/generic-freebsd/netinet/ip_scan.h b/lib/libc/include/generic-freebsd/netinet/ip_scan.h index 0aa120c3b98a..e7f2e63c6c29 100644 --- a/lib/libc/include/generic-freebsd/netinet/ip_scan.h +++ b/lib/libc/include/generic-freebsd/netinet/ip_scan.h @@ -2,8 +2,6 @@ * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. - * - * @(#)ip_fil.h 1.35 6/5/96 * $Id$ */ diff --git a/lib/libc/include/generic-freebsd/netinet/ip_state.h b/lib/libc/include/generic-freebsd/netinet/ip_state.h index 10dcd43fac02..c53e5761938b 100644 --- a/lib/libc/include/generic-freebsd/netinet/ip_state.h +++ b/lib/libc/include/generic-freebsd/netinet/ip_state.h @@ -2,8 +2,6 @@ * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. - * - * @(#)ip_state.h 1.3 1/12/96 (C) 1995 Darren Reed * Id: ip_state.h,v 2.68.2.10 2007/10/16 09:33:24 darrenr Exp $ */ #ifndef __IP_STATE_H__ diff --git a/lib/libc/include/generic-freebsd/netinet/ip_sync.h b/lib/libc/include/generic-freebsd/netinet/ip_sync.h index 4188fce1fe54..398ef091ffca 100644 --- a/lib/libc/include/generic-freebsd/netinet/ip_sync.h +++ b/lib/libc/include/generic-freebsd/netinet/ip_sync.h @@ -2,8 +2,6 @@ * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. - * - * @(#)ip_fil.h 1.35 6/5/96 * $Id$ */ diff --git a/lib/libc/include/generic-freebsd/netinet/ip_var.h b/lib/libc/include/generic-freebsd/netinet/ip_var.h index 0b359c8175f0..5b9097d244e9 100644 --- a/lib/libc/include/generic-freebsd/netinet/ip_var.h +++ b/lib/libc/include/generic-freebsd/netinet/ip_var.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)ip_var.h 8.2 (Berkeley) 1/9/95 */ #ifndef _NETINET_IP_VAR_H_ @@ -49,7 +47,7 @@ struct ipovly { u_short ih_len; /* protocol length */ struct in_addr ih_src; /* source internet address */ struct in_addr ih_dst; /* destination internet address */ -}; +} __packed; #ifdef _KERNEL /* @@ -138,15 +136,19 @@ struct ipstat { #include #include +#include VNET_PCPUSTAT_DECLARE(struct ipstat, ipstat); /* * In-kernel consumers can use these accessor macros directly to update * stats. */ -#define IPSTAT_ADD(name, val) \ - VNET_PCPUSTAT_ADD(struct ipstat, ipstat, name, (val)) -#define IPSTAT_SUB(name, val) IPSTAT_ADD(name, -(val)) +#define IPSTAT_ADD(name, val) \ + do { \ + MIB_SDT_PROBE1(ip, count, name, (val)); \ + VNET_PCPUSTAT_ADD(struct ipstat, ipstat, name, (val)); \ + } while (0) +#define IPSTAT_SUB(name, val) IPSTAT_ADD(name, -(val)) #define IPSTAT_INC(name) IPSTAT_ADD(name, 1) #define IPSTAT_DEC(name) IPSTAT_SUB(name, 1) @@ -154,11 +156,19 @@ VNET_PCPUSTAT_DECLARE(struct ipstat, ipstat); * Kernel module consumers must use this accessor macro. */ void kmod_ipstat_inc(int statnum); -#define KMOD_IPSTAT_INC(name) \ - kmod_ipstat_inc(offsetof(struct ipstat, name) / sizeof(uint64_t)) -void kmod_ipstat_dec(int statnum); -#define KMOD_IPSTAT_DEC(name) \ - kmod_ipstat_dec(offsetof(struct ipstat, name) / sizeof(uint64_t)) +#define KMOD_IPSTAT_INC(name) \ + do { \ + MIB_SDT_PROBE1(ip, count, name, 1); \ + kmod_ipstat_inc( \ + offsetof(struct ipstat, name) / sizeof(uint64_t)); \ + } while (0) +void kmod_ipstat_dec(int statnum); +#define KMOD_IPSTAT_DEC(name) \ + do { \ + MIB_SDT_PROBE1(ip, count, name, -1); \ + kmod_ipstat_dec( \ + offsetof(struct ipstat, name) / sizeof(uint64_t)); \ + } while (0) /* flags passed to ip_output as last parameter */ #define IP_FORWARDING 0x1 /* most of ip header exists */ @@ -194,6 +204,7 @@ extern int (*legal_vif_num)(int); extern u_long (*ip_mcast_src)(int); VNET_DECLARE(int, rsvp_on); VNET_DECLARE(int, drop_redirect); +VNET_DECLARE(int, ip_random_id); #define V_ip_id VNET(ip_id) #define V_ip_defttl VNET(ip_defttl) @@ -206,6 +217,7 @@ VNET_DECLARE(int, drop_redirect); #define V_ip_mrouter VNET(ip_mrouter) #define V_rsvp_on VNET(rsvp_on) #define V_drop_redirect VNET(drop_redirect) +#define V_ip_random_id VNET(ip_random_id) void inp_freemoptions(struct ip_moptions *); int inp_getmoptions(struct inpcb *, struct sockopt *); @@ -225,7 +237,7 @@ struct mbuf * ip_reass(struct mbuf *); void ip_savecontrol(struct inpcb *, struct mbuf **, struct ip *, struct mbuf *); -void ip_fillid(struct ip *); +void ip_fillid(struct ip *, bool); int rip_ctloutput(struct socket *, struct sockopt *); int ipip_input(struct mbuf **, int *, int); int rsvp_input(struct mbuf **, int *, int); @@ -259,6 +271,7 @@ VNET_DECLARE(struct pfil_head *, inet_local_pfil_head); #define PFIL_INET_LOCAL_NAME "inet-local" void in_delayed_cksum(struct mbuf *m); +void in_delayed_cksum_o(struct mbuf *m, uint16_t o); /* Hooks for ipfw, dummynet, divert etc. Most are declared in raw_ip.c */ /* diff --git a/lib/libc/include/generic-freebsd/netinet/ipf_rb.h b/lib/libc/include/generic-freebsd/netinet/ipf_rb.h index 6bd46513307a..ae0b8b1a4454 100644 --- a/lib/libc/include/generic-freebsd/netinet/ipf_rb.h +++ b/lib/libc/include/generic-freebsd/netinet/ipf_rb.h @@ -305,13 +305,11 @@ _n##_rb_walktree(struct _n##_rb_head *head, _n##_rb_walker_t func, void *arg)\ _t *prev; \ _t *next; \ _t *node = head->top._f.right; \ - _t *base; \ \ while (node != &_n##_rb_zero) \ node = node->_f.left; \ \ for (;;) { \ - base = node; \ prev = node; \ while ((node->_f.parent->_f.right == node) && \ (node != &_n##_rb_zero)) { \ diff --git a/lib/libc/include/generic-freebsd/netinet/ipl.h b/lib/libc/include/generic-freebsd/netinet/ipl.h index 25cfa011388c..f7d9d3f463a9 100644 --- a/lib/libc/include/generic-freebsd/netinet/ipl.h +++ b/lib/libc/include/generic-freebsd/netinet/ipl.h @@ -2,8 +2,6 @@ * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. - * - * @(#)ipl.h 1.21 6/5/96 * Id: ipl.h,v 2.52.2.30 2007/10/16 09:41:00 darrenr Exp $ */ diff --git a/lib/libc/include/generic-freebsd/netinet/pim.h b/lib/libc/include/generic-freebsd/netinet/pim.h index c13c619888f6..1f2996d0a505 100644 --- a/lib/libc/include/generic-freebsd/netinet/pim.h +++ b/lib/libc/include/generic-freebsd/netinet/pim.h @@ -71,7 +71,7 @@ struct pim { #endif /* ! _PIM_VT */ uint8_t pim_reserved; /* Reserved */ uint16_t pim_cksum; /* IP-style checksum */ -}; +} __packed; /* KAME-related name backward compatibility */ #define pim_ver pim_vers #define pim_rsv pim_reserved diff --git a/lib/libc/include/generic-freebsd/netinet/sctp.h b/lib/libc/include/generic-freebsd/netinet/sctp.h index 4336ce888744..ecfad4679117 100644 --- a/lib/libc/include/generic-freebsd/netinet/sctp.h +++ b/lib/libc/include/generic-freebsd/netinet/sctp.h @@ -35,7 +35,6 @@ #ifndef _NETINET_SCTP_H_ #define _NETINET_SCTP_H_ -#include #include #define SCTP_PACKED __attribute__((packed)) diff --git a/lib/libc/include/generic-freebsd/netinet/sctp_os.h b/lib/libc/include/generic-freebsd/netinet/sctp_os.h index 8ec0c37a563e..25805dd14c9f 100644 --- a/lib/libc/include/generic-freebsd/netinet/sctp_os.h +++ b/lib/libc/include/generic-freebsd/netinet/sctp_os.h @@ -39,9 +39,6 @@ * General kernel memory allocation: * SCTP_MALLOC(element, type, size, name) * SCTP_FREE(element) - * Kernel memory allocation for "soname"- memory must be zeroed. - * SCTP_MALLOC_SONAME(name, type, size) - * SCTP_FREE_SONAME(name) */ /* diff --git a/lib/libc/include/generic-freebsd/netinet/sctp_os_bsd.h b/lib/libc/include/generic-freebsd/netinet/sctp_os_bsd.h index abec26447f5b..d6ea7ecb7047 100644 --- a/lib/libc/include/generic-freebsd/netinet/sctp_os_bsd.h +++ b/lib/libc/include/generic-freebsd/netinet/sctp_os_bsd.h @@ -219,13 +219,6 @@ MALLOC_DECLARE(SCTP_M_MCORE); #define SCTP_FREE(var, type) free(var, type) -#define SCTP_MALLOC_SONAME(var, type, size) \ - do { \ - var = (type)malloc(size, M_SONAME, M_WAITOK | M_ZERO); \ - } while (0) - -#define SCTP_FREE_SONAME(var) free(var, M_SONAME) - #define SCTP_PROCESS_STRUCT struct proc * /* @@ -349,7 +342,7 @@ typedef struct callout sctp_os_timer_t; } while(0) /* Other m_pkthdr type things */ -#define SCTP_IS_IT_BROADCAST(dst, m) ((m->m_flags & M_PKTHDR) ? in_broadcast(dst, m->m_pkthdr.rcvif) : 0) +#define SCTP_IS_IT_BROADCAST(dst, m) ((m->m_flags & M_PKTHDR) ? in_ifnet_broadcast(dst, m->m_pkthdr.rcvif) : 0) #define SCTP_IS_IT_LOOPBACK(m) ((m->m_flags & M_PKTHDR) && ((m->m_pkthdr.rcvif == NULL) || (m->m_pkthdr.rcvif->if_type == IFT_LOOP))) /* This converts any input packet header diff --git a/lib/libc/include/generic-freebsd/netinet/sctp_var.h b/lib/libc/include/generic-freebsd/netinet/sctp_var.h index b7bbab2d484a..79a7db27e476 100644 --- a/lib/libc/include/generic-freebsd/netinet/sctp_var.h +++ b/lib/libc/include/generic-freebsd/netinet/sctp_var.h @@ -331,17 +331,17 @@ void sctp_notify(struct sctp_inpcb *, struct sctp_tcb *, struct sctp_nets *, uint8_t, uint8_t, uint16_t, uint32_t); int sctp_flush(struct socket *, int); -int sctp_shutdown(struct socket *); +int sctp_shutdown(struct socket *, enum shutdown_how); int sctp_bindx(struct socket *, int, struct sockaddr_storage *, int, int, struct proc *); /* can't use sctp_assoc_t here */ int sctp_peeloff(struct socket *, struct socket *, int, caddr_t, int *); -int sctp_ingetaddr(struct socket *, struct sockaddr **); -int sctp_peeraddr(struct socket *, struct sockaddr **); +int sctp_ingetaddr(struct socket *, struct sockaddr *); +int sctp_peeraddr(struct socket *, struct sockaddr *); int sctp_listen(struct socket *, int, struct thread *); -int sctp_accept(struct socket *, struct sockaddr **); +int sctp_accept(struct socket *, struct sockaddr *); #endif /* _KERNEL */ diff --git a/lib/libc/include/generic-freebsd/netinet/tcp.h b/lib/libc/include/generic-freebsd/netinet/tcp.h index 67d3e2e20167..7918489df498 100644 --- a/lib/libc/include/generic-freebsd/netinet/tcp.h +++ b/lib/libc/include/generic-freebsd/netinet/tcp.h @@ -27,14 +27,11 @@ * 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. - * - * @(#)tcp.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NETINET_TCP_H_ #define _NETINET_TCP_H_ -#include #include #if __BSD_VISIBLE @@ -74,13 +71,31 @@ struct tcphdr { #define TH_RES3 0x200 #define TH_RES2 0x400 #define TH_RES1 0x800 -#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG|TH_ECE|TH_CWR) +#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG|TH_ECE|TH_CWR|TH_AE) #define PRINT_TH_FLAGS "\20\1FIN\2SYN\3RST\4PUSH\5ACK\6URG\7ECE\10CWR\11AE" u_short th_win; /* window */ u_short th_sum; /* checksum */ u_short th_urp; /* urgent pointer */ -}; +} __packed; + +static __inline uint16_t +__tcp_get_flags(const struct tcphdr *th) +{ + return (((uint16_t)th->th_x2 << 8) | th->th_flags); +} + +static __inline void +__tcp_set_flags(struct tcphdr *th, uint16_t flags) +{ + th->th_x2 = (flags >> 8) & 0x0f; + th->th_flags = flags & 0xff; +} + +#ifdef _KERNEL +#define tcp_get_flags(th) __tcp_get_flags(th) +#define tcp_set_flags(th, flags) __tcp_set_flags(th, flags) +#endif #define PADTCPOLEN(len) ((((len) / 4) + !!((len) % 4)) * 4) @@ -151,8 +166,6 @@ struct tcphdr { #define TCP_MAX_WINSHIFT 14 /* maximum window shift */ -#define TCP_MAXBURST 4 /* maximum segments in a burst */ - #define TCP_MAXHLEN (0xf<<2) /* max length of header in bytes */ #define TCP_MAXOLEN (TCP_MAXHLEN - sizeof(struct tcphdr)) /* max space left for options */ @@ -167,165 +180,170 @@ struct tcphdr { * values and are not masked together. Some values appear to be * bitmasks for historical reasons. */ -#define TCP_NODELAY 1 /* don't delay send to coalesce packets */ +#define TCP_NODELAY 1 /* don't delay send to coalesce packets */ #if __BSD_VISIBLE -#define TCP_MAXSEG 2 /* set maximum segment size */ -#define TCP_NOPUSH 4 /* don't push last block of write */ -#define TCP_NOOPT 8 /* don't use TCP options */ -#define TCP_MD5SIG 16 /* use MD5 digests (RFC2385) */ -#define TCP_INFO 32 /* retrieve tcp_info structure */ -#define TCP_STATS 33 /* retrieve stats blob structure */ -#define TCP_LOG 34 /* configure event logging for connection */ -#define TCP_LOGBUF 35 /* retrieve event log for connection */ -#define TCP_LOGID 36 /* configure log ID to correlate connections */ -#define TCP_LOGDUMP 37 /* dump connection log events to device */ -#define TCP_LOGDUMPID 38 /* dump events from connections with same ID to - device */ -#define TCP_TXTLS_ENABLE 39 /* TLS framing and encryption for transmit */ -#define TCP_TXTLS_MODE 40 /* Transmit TLS mode */ -#define TCP_RXTLS_ENABLE 41 /* TLS framing and encryption for receive */ -#define TCP_RXTLS_MODE 42 /* Receive TLS mode */ -#define TCP_IWND_NB 43 /* Override initial window (units: bytes) */ -#define TCP_IWND_NSEG 44 /* Override initial window (units: MSS segs) */ +#define TCP_MAXSEG 2 /* set maximum segment size */ +#define TCP_NOPUSH 4 /* don't push last block of write */ +#define TCP_NOOPT 8 /* don't use TCP options */ +#define TCP_MD5SIG 16 /* use MD5 digests (RFC2385) */ +#define TCP_INFO 32 /* retrieve tcp_info structure */ +#define TCP_STATS 33 /* retrieve stats blob structure */ +#define TCP_LOG 34 /* configure event logging for connection */ +#define TCP_LOGBUF 35 /* retrieve event log for connection */ +#define TCP_LOGID 36 /* configure log ID to correlate connections */ +#define TCP_LOGDUMP 37 /* dump connection log events to device */ +#define TCP_LOGDUMPID 38 /* dump events from connections with same ID to + device */ +#define TCP_TXTLS_ENABLE 39 /* TLS framing and encryption for transmit */ +#define TCP_TXTLS_MODE 40 /* Transmit TLS mode */ +#define TCP_RXTLS_ENABLE 41 /* TLS framing and encryption for receive */ +#define TCP_RXTLS_MODE 42 /* Receive TLS mode */ +#define TCP_IWND_NB 43 /* Override initial window (units: bytes) */ +#define TCP_IWND_NSEG 44 /* Override initial window (units: MSS segs) */ #ifdef _KERNEL -#define TCP_USE_DDP 45 /* Use direct data placement for so_rcvbuf */ +#define TCP_USE_DDP 45 /* Use direct data placement for so_rcvbuf */ #endif -#define TCP_LOGID_CNT 46 /* get number of connections with the same ID */ -#define TCP_LOG_TAG 47 /* configure tag for grouping logs */ -#define TCP_USER_LOG 48 /* userspace log event */ -#define TCP_CONGESTION 64 /* get/set congestion control algorithm */ -#define TCP_CCALGOOPT 65 /* get/set cc algorithm specific options */ -#define TCP_MAXUNACKTIME 68 /* maximum time without making progress (sec) */ -#define TCP_MAXPEAKRATE 69 /* maximum peak rate allowed (kbps) */ -#define TCP_IDLE_REDUCE 70 /* Reduce cwnd on idle input */ -#define TCP_REMOTE_UDP_ENCAPS_PORT 71 /* Enable TCP over UDP tunneling via the specified port */ -#define TCP_DELACK 72 /* socket option for delayed ack */ -#define TCP_FIN_IS_RST 73 /* A fin from the peer is treated has a RST */ -#define TCP_LOG_LIMIT 74 /* Limit to number of records in tcp-log */ -#define TCP_SHARED_CWND_ALLOWED 75 /* Use of a shared cwnd is allowed */ -#define TCP_PROC_ACCOUNTING 76 /* Do accounting on tcp cpu usage and counts */ -#define TCP_USE_CMP_ACKS 77 /* The transport can handle the Compressed mbuf acks */ -#define TCP_PERF_INFO 78 /* retrieve accounting counters */ -#define TCP_LRD 79 /* toggle Lost Retransmission Detection for A/B testing */ -#define TCP_KEEPINIT 128 /* N, time to establish connection */ -#define TCP_KEEPIDLE 256 /* L,N,X start keeplives after this period */ -#define TCP_KEEPINTVL 512 /* L,N interval between keepalives */ -#define TCP_KEEPCNT 1024 /* L,N number of keepalives before close */ -#define TCP_FASTOPEN 1025 /* enable TFO / was created via TFO */ -#define TCP_PCAP_OUT 2048 /* number of output packets to keep */ -#define TCP_PCAP_IN 4096 /* number of input packets to keep */ -#define TCP_FUNCTION_BLK 8192 /* Set the tcp function pointers to the specified stack */ -#define TCP_FUNCTION_ALIAS 8193 /* Get the current tcp function pointer name alias */ +#define TCP_LOGID_CNT 46 /* get number of connections with the same ID */ +#define TCP_LOG_TAG 47 /* configure tag for grouping logs */ +#define TCP_USER_LOG 48 /* userspace log event */ +#define TCP_CONGESTION 64 /* get/set congestion control algorithm */ +#define TCP_CCALGOOPT 65 /* get/set cc algorithm specific options */ +#define TCP_MAXUNACKTIME 68 /* maximum time without making progress (sec) */ +/* unused 69 */ +#define TCP_IDLE_REDUCE 70 /* Reduce cwnd on idle input */ +#define TCP_REMOTE_UDP_ENCAPS_PORT 71 /* Enable TCP over UDP tunneling via the specified port */ +#define TCP_DELACK 72 /* socket option for delayed ack */ +#define TCP_FIN_IS_RST 73 /* A fin from the peer is treated has a RST */ +#define TCP_LOG_LIMIT 74 /* Limit to number of records in tcp-log */ +#define TCP_SHARED_CWND_ALLOWED 75 /* Use of a shared cwnd is allowed */ +#define TCP_PROC_ACCOUNTING 76 /* Do accounting on tcp cpu usage and counts */ +#define TCP_USE_CMP_ACKS 77 /* The transport can handle the Compressed mbuf acks */ +#define TCP_PERF_INFO 78 /* retrieve accounting counters */ +#define TCP_KEEPINIT 128 /* N, time to establish connection */ +#define TCP_KEEPIDLE 256 /* L,N,X start keeplives after this period */ +#define TCP_KEEPINTVL 512 /* L,N interval between keepalives */ +#define TCP_KEEPCNT 1024 /* L,N number of keepalives before close */ +#define TCP_FASTOPEN 1025 /* enable TFO / was created via TFO */ +/* unused 2048 was TCP_PCAP_OUT */ +/* unused 4096 was TCP_PCAP_IN */ +#define TCP_FUNCTION_BLK 8192 /* Set the tcp function pointers to the specified stack */ +#define TCP_FUNCTION_ALIAS 8193 /* Get the current tcp function pointer name alias */ /* Options for Rack and BBR */ -#define TCP_REUSPORT_LB_NUMA 1026 /* set listen socket numa domain */ -#define TCP_RACK_MBUF_QUEUE 1050 /* Do we allow mbuf queuing if supported */ -#define TCP_RACK_PROP 1051 /* Not used */ -#define TCP_RACK_TLP_REDUCE 1052 /* RACK TLP cwnd reduction (bool) */ -#define TCP_RACK_PACE_REDUCE 1053 /* RACK Pacingv reduction factor (divisor) */ -#define TCP_RACK_PACE_MAX_SEG 1054 /* Max TSO size we will send */ -#define TCP_RACK_PACE_ALWAYS 1055 /* Use the always pace method */ -#define TCP_RACK_PROP_RATE 1056 /* Not used */ -#define TCP_RACK_PRR_SENDALOT 1057 /* Allow PRR to send more than one seg */ -#define TCP_RACK_MIN_TO 1058 /* Minimum time between rack t-o's in ms */ -#define TCP_RACK_EARLY_RECOV 1059 /* Not used */ -#define TCP_RACK_EARLY_SEG 1060 /* If early recovery max segments */ -#define TCP_RACK_REORD_THRESH 1061 /* RACK reorder threshold (shift amount) */ -#define TCP_RACK_REORD_FADE 1062 /* Does reordering fade after ms time */ -#define TCP_RACK_TLP_THRESH 1063 /* RACK TLP theshold i.e. srtt+(srtt/N) */ -#define TCP_RACK_PKT_DELAY 1064 /* RACK added ms i.e. rack-rtt + reord + N */ -#define TCP_RACK_TLP_INC_VAR 1065 /* Does TLP include rtt variance in t-o */ -#define TCP_BBR_IWINTSO 1067 /* Initial TSO window for BBRs first sends */ -#define TCP_BBR_RECFORCE 1068 /* Enter recovery force out a segment disregard pacer no longer valid */ -#define TCP_BBR_STARTUP_PG 1069 /* Startup pacing gain */ -#define TCP_BBR_DRAIN_PG 1070 /* Drain pacing gain */ -#define TCP_BBR_RWND_IS_APP 1071 /* Rwnd limited is considered app limited */ -#define TCP_BBR_PROBE_RTT_INT 1072 /* How long in useconds between probe-rtt */ -#define TCP_BBR_ONE_RETRAN 1073 /* Is only one segment allowed out during retran */ -#define TCP_BBR_STARTUP_LOSS_EXIT 1074 /* Do we exit a loss during startup if not 20% incr */ -#define TCP_BBR_USE_LOWGAIN 1075 /* lower the gain in PROBE_BW enable */ -#define TCP_BBR_LOWGAIN_THRESH 1076 /* Unused after 2.3 morphs to TSLIMITS >= 2.3 */ -#define TCP_BBR_TSLIMITS 1076 /* Do we use experimental Timestamp limiting for our algo */ -#define TCP_BBR_LOWGAIN_HALF 1077 /* Unused after 2.3 */ -#define TCP_BBR_PACE_OH 1077 /* Reused in 4.2 for pacing overhead setting */ -#define TCP_BBR_LOWGAIN_FD 1078 /* Unused after 2.3 */ -#define TCP_BBR_HOLD_TARGET 1078 /* For 4.3 on */ -#define TCP_BBR_USEDEL_RATE 1079 /* Enable use of delivery rate for loss recovery */ -#define TCP_BBR_MIN_RTO 1080 /* Min RTO in milliseconds */ -#define TCP_BBR_MAX_RTO 1081 /* Max RTO in milliseconds */ -#define TCP_BBR_REC_OVER_HPTS 1082 /* Recovery override htps settings 0/1/3 */ -#define TCP_BBR_UNLIMITED 1083 /* Not used before 2.3 and morphs to algorithm >= 2.3 */ -#define TCP_BBR_ALGORITHM 1083 /* What measurement algo does BBR use netflix=0, google=1 */ -#define TCP_BBR_DRAIN_INC_EXTRA 1084 /* Does the 3/4 drain target include the extra gain */ -#define TCP_BBR_STARTUP_EXIT_EPOCH 1085 /* what epoch gets us out of startup */ -#define TCP_BBR_PACE_PER_SEC 1086 -#define TCP_BBR_PACE_DEL_TAR 1087 -#define TCP_BBR_PACE_SEG_MAX 1088 -#define TCP_BBR_PACE_SEG_MIN 1089 -#define TCP_BBR_PACE_CROSS 1090 -#define TCP_RACK_IDLE_REDUCE_HIGH 1092 /* Reduce the highest cwnd seen to IW on idle */ -#define TCP_RACK_MIN_PACE 1093 /* Do we enforce rack min pace time */ -#define TCP_RACK_MIN_PACE_SEG 1094 /* If so what is the seg threshould */ -#define TCP_RACK_GP_INCREASE 1094 /* After 4.1 its the GP increase in older rack */ -#define TCP_RACK_TLP_USE 1095 -#define TCP_BBR_ACK_COMP_ALG 1096 /* Not used */ -#define TCP_BBR_TMR_PACE_OH 1096 /* Recycled in 4.2 */ -#define TCP_BBR_EXTRA_GAIN 1097 -#define TCP_RACK_DO_DETECTION 1097 /* Recycle of extra gain for rack, attack detection */ -#define TCP_BBR_RACK_RTT_USE 1098 /* what RTT should we use 0, 1, or 2? */ -#define TCP_BBR_RETRAN_WTSO 1099 -#define TCP_DATA_AFTER_CLOSE 1100 -#define TCP_BBR_PROBE_RTT_GAIN 1101 -#define TCP_BBR_PROBE_RTT_LEN 1102 -#define TCP_BBR_SEND_IWND_IN_TSO 1103 /* Do we burst out whole iwin size chunks at start? */ -#define TCP_BBR_USE_RACK_RR 1104 /* Do we use the rack rapid recovery for pacing rxt's */ -#define TCP_BBR_USE_RACK_CHEAT TCP_BBR_USE_RACK_RR /* Compat. */ -#define TCP_BBR_HDWR_PACE 1105 /* Enable/disable hardware pacing */ -#define TCP_BBR_UTTER_MAX_TSO 1106 /* Do we enforce an utter max TSO size */ -#define TCP_BBR_EXTRA_STATE 1107 /* Special exit-persist catch up */ -#define TCP_BBR_FLOOR_MIN_TSO 1108 /* The min tso size */ -#define TCP_BBR_MIN_TOPACEOUT 1109 /* Do we suspend pacing until */ -#define TCP_BBR_TSTMP_RAISES 1110 /* Can a timestamp measurement raise the b/w */ -#define TCP_BBR_POLICER_DETECT 1111 /* Turn on/off google mode policer detection */ -#define TCP_BBR_RACK_INIT_RATE 1112 /* Set an initial pacing rate for when we have no b/w in kbits per sec */ -#define TCP_RACK_RR_CONF 1113 /* Rack rapid recovery configuration control*/ -#define TCP_RACK_CHEAT_NOT_CONF_RATE TCP_RACK_RR_CONF -#define TCP_RACK_GP_INCREASE_CA 1114 /* GP increase for Congestion Avoidance */ -#define TCP_RACK_GP_INCREASE_SS 1115 /* GP increase for Slow Start */ -#define TCP_RACK_GP_INCREASE_REC 1116 /* GP increase for Recovery */ -#define TCP_RACK_FORCE_MSEG 1117 /* Override to use the user set max-seg value */ -#define TCP_RACK_PACE_RATE_CA 1118 /* Pacing rate for Congestion Avoidance */ -#define TCP_RACK_PACE_RATE_SS 1119 /* Pacing rate for Slow Start */ -#define TCP_RACK_PACE_RATE_REC 1120 /* Pacing rate for Recovery */ -#define TCP_NO_PRR 1122 /* If pacing, don't use prr */ -#define TCP_RACK_NONRXT_CFG_RATE 1123 /* In recovery does a non-rxt use the cfg rate */ -#define TCP_SHARED_CWND_ENABLE 1124 /* Use a shared cwnd if allowed */ -#define TCP_TIMELY_DYN_ADJ 1125 /* Do we attempt dynamic multipler adjustment with timely. */ -#define TCP_RACK_NO_PUSH_AT_MAX 1126 /* For timely do not push if we are over max rtt */ -#define TCP_RACK_PACE_TO_FILL 1127 /* If we are not in recovery, always pace to fill the cwnd in 1 RTT */ -#define TCP_SHARED_CWND_TIME_LIMIT 1128 /* we should limit to low time values the scwnd life */ -#define TCP_RACK_PROFILE 1129 /* Select a profile that sets multiple options */ -#define TCP_HDWR_RATE_CAP 1130 /* Allow hardware rates to cap pacing rate */ -#define TCP_PACING_RATE_CAP 1131 /* Highest rate allowed in pacing in bytes per second (uint64_t) */ -#define TCP_HDWR_UP_ONLY 1132 /* Allow the pacing rate to climb but not descend (with the exception of fill-cw */ -#define TCP_RACK_ABC_VAL 1133 /* Set a local ABC value different then the system default */ -#define TCP_REC_ABC_VAL 1134 /* Do we use the ABC value for recovery or the override one from sysctl */ -#define TCP_RACK_MEASURE_CNT 1135 /* How many measurements are required in GP pacing */ -#define TCP_DEFER_OPTIONS 1136 /* Defer options until the proper number of measurements occur, does not defer TCP_RACK_MEASURE_CNT */ -#define TCP_FAST_RSM_HACK 1137 /* Not used in modern stacks */ -#define TCP_RACK_PACING_BETA 1138 /* Changing the beta for pacing */ -#define TCP_RACK_PACING_BETA_ECN 1139 /* Changing the beta for ecn with pacing */ -#define TCP_RACK_TIMER_SLOP 1140 /* Set or get the timer slop used */ -#define TCP_RACK_DSACK_OPT 1141 /* How do we setup rack timer DSACK options bit 1/2 */ -#define TCP_RACK_ENABLE_HYSTART 1142 /* Do we allow hystart in the CC modules */ -#define TCP_RACK_SET_RXT_OPTIONS 1143 /* Set the bits in the retransmit options */ -#define TCP_RACK_HI_BETA 1144 /* Turn on/off high beta */ -#define TCP_RACK_SPLIT_LIMIT 1145 /* Set a split limit for split allocations */ -#define TCP_RACK_PACING_DIVISOR 1146 /* Pacing divisor given to rate-limit code for burst sizing */ -#define TCP_RACK_PACE_MIN_SEG 1147 /* Pacing min seg size rack will use */ -#define TCP_RACK_DGP_IN_REC 1148 /* Do we use full DGP in recovery? */ -#define TCP_RXT_CLAMP 1149 /* Do we apply a threshold to rack so if excess rxt clamp cwnd? */ -#define TCP_HYBRID_PACING 1150 /* Hybrid pacing enablement */ -#define TCP_PACING_DND 1151 /* When pacing with rr_config=3 can sacks disturb us */ +#define TCP_REUSPORT_LB_NUMA 1026 /* set listen socket numa domain */ +#define TCP_RACK_MBUF_QUEUE 1050 /* Do we allow mbuf queuing if supported */ +/* unused 1051 */ +#define TCP_RACK_TLP_REDUCE 1052 /* RACK TLP cwnd reduction (bool) */ +/* unused 1053 */ +#define TCP_RACK_PACE_MAX_SEG 1054 /* Max TSO size we will send */ +#define TCP_RACK_PACE_ALWAYS 1055 /* Use the always pace method */ +/* unused 1056 */ +#define TCP_RACK_PRR_SENDALOT 1057 /* Allow PRR to send more than one seg */ +#define TCP_RACK_MIN_TO 1058 /* Minimum time between rack t-o's in ms */ +/* unused 1059 */ +#define TCP_RACK_EARLY_SEG 1060 /* If early recovery max segments */ +#define TCP_RACK_REORD_THRESH 1061 /* RACK reorder threshold (shift amount) */ +#define TCP_RACK_REORD_FADE 1062 /* Does reordering fade after ms time */ +#define TCP_RACK_TLP_THRESH 1063 /* RACK TLP theshold i.e. srtt+(srtt/N) */ +#define TCP_RACK_PKT_DELAY 1064 /* RACK added ms i.e. rack-rtt + reord + N */ +/* unused 1065 */ +/* unused 1066 */ +#define TCP_BBR_IWINTSO 1067 /* Initial TSO window for BBRs first sends */ +/* unused 1068 */ +#define TCP_BBR_STARTUP_PG 1069 /* Startup pacing gain */ +#define TCP_BBR_DRAIN_PG 1070 /* Drain pacing gain */ +/* unused 1071 */ +#define TCP_BBR_PROBE_RTT_INT 1072 /* How long in useconds between probe-rtt */ +/* unused 1073 */ +#define TCP_BBR_STARTUP_LOSS_EXIT 1074 /* Do we exit a loss during startup if not 20% incr */ +/* unused 1075 */ +#define TCP_BBR_TSLIMITS 1076 /* Do we use experimental Timestamp limiting for our algo */ +#define TCP_BBR_PACE_OH 1077 /* pacing overhead setting */ +/* unused 1078 */ +#define TCP_BBR_USEDEL_RATE 1079 /* Enable use of delivery rate for loss recovery */ +#define TCP_BBR_MIN_RTO 1080 /* Min RTO in milliseconds */ +#define TCP_BBR_MAX_RTO 1081 /* Max RTO in milliseconds */ +/* unused 1082 */ +#define TCP_BBR_ALGORITHM 1083 /* What measurement algo does BBR use netflix=0, google=1 */ +/* unused 1084 */ +/* unused 1085 */ +#define TCP_BBR_PACE_PER_SEC 1086 +#define TCP_BBR_PACE_DEL_TAR 1087 +#define TCP_BBR_PACE_SEG_MAX 1088 +#define TCP_BBR_PACE_SEG_MIN 1089 +#define TCP_BBR_PACE_CROSS 1090 +/* unused 1091 */ +/* unused 1092 */ +/* unused 1093 */ +/* unused 1094 */ +#define TCP_RACK_TLP_USE 1095 +#define TCP_BBR_TMR_PACE_OH 1096 /* ??? */ +#define TCP_RACK_DO_DETECTION 1097 /* Recycle of extra gain for rack, attack detection */ +#define TCP_BBR_RACK_RTT_USE 1098 /* what RTT should we use 0, 1, or 2? */ +#define TCP_BBR_RETRAN_WTSO 1099 +#define TCP_DATA_AFTER_CLOSE 1100 +#define TCP_BBR_PROBE_RTT_GAIN 1101 +#define TCP_BBR_PROBE_RTT_LEN 1102 +#define TCP_BBR_SEND_IWND_IN_TSO 1103 /* Do we burst out whole iwin size chunks at start? */ +#define TCP_BBR_USE_RACK_RR 1104 /* Do we use the rack rapid recovery for pacing rxt's */ +#define TCP_BBR_USE_RACK_CHEAT TCP_BBR_USE_RACK_RR /* Compat. */ +#define TCP_BBR_HDWR_PACE 1105 /* Enable/disable hardware pacing */ +#define TCP_BBR_UTTER_MAX_TSO 1106 /* Do we enforce an utter max TSO size */ +#define TCP_BBR_EXTRA_STATE 1107 /* Special exit-persist catch up */ +#define TCP_BBR_FLOOR_MIN_TSO 1108 /* The min tso size */ +#define TCP_BBR_MIN_TOPACEOUT 1109 /* Do we suspend pacing until */ +#define TCP_BBR_TSTMP_RAISES 1110 /* Can a timestamp measurement raise the b/w */ +#define TCP_BBR_POLICER_DETECT 1111 /* Turn on/off google mode policer detection */ +#define TCP_BBR_RACK_INIT_RATE 1112 /* Set an initial pacing rate for when we have no b/w in kbits per sec */ +#define TCP_RACK_RR_CONF 1113 /* Rack rapid recovery configuration control*/ +#define TCP_RACK_GP_INCREASE_CA 1114 /* GP increase for Congestion Avoidance */ +#define TCP_RACK_GP_INCREASE_SS 1115 /* GP increase for Slow Start */ +#define TCP_RACK_GP_INCREASE_REC 1116 /* GP increase for Recovery */ +#define TCP_RACK_FORCE_MSEG 1117 /* Override to use the user set max-seg value */ +#define TCP_RACK_PACE_RATE_CA 1118 /* Pacing rate for Congestion Avoidance */ +#define TCP_RACK_PACE_RATE_SS 1119 /* Pacing rate for Slow Start */ +#define TCP_RACK_PACE_RATE_REC 1120 /* Pacing rate for Recovery */ +#define TCP_NO_PRR 1122 /* If pacing, don't use prr */ +#define TCP_RACK_NONRXT_CFG_RATE 1123 /* In recovery does a non-rxt use the cfg rate */ +#define TCP_SHARED_CWND_ENABLE 1124 /* Use a shared cwnd if allowed */ +#define TCP_TIMELY_DYN_ADJ 1125 /* Do we attempt dynamic multipler adjustment with timely. */ +#define TCP_RACK_NO_PUSH_AT_MAX 1126 /* For timely do not push if we are over max rtt */ +#define TCP_RACK_PACE_TO_FILL 1127 /* If we are not in recovery, always pace to fill the cwnd in 1 RTT */ +#define TCP_SHARED_CWND_TIME_LIMIT 1128 /* we should limit to low time values the scwnd life */ +#define TCP_RACK_PROFILE 1129 /* Select a profile that sets multiple options */ +#define TCP_HDWR_RATE_CAP 1130 /* Allow hardware rates to cap pacing rate */ +#define TCP_PACING_RATE_CAP 1131 /* Highest rate allowed in pacing in bytes per second (uint64_t) */ +#define TCP_HDWR_UP_ONLY 1132 /* Allow the pacing rate to climb but not descend (with the exception of fill-cw */ +#define TCP_RACK_ABC_VAL 1133 /* Set a local ABC value different then the system default */ +#define TCP_REC_ABC_VAL 1134 /* Do we use the ABC value for recovery or the override one from sysctl */ +#define TCP_RACK_MEASURE_CNT 1135 /* How many measurements are required in GP pacing */ +#define TCP_DEFER_OPTIONS 1136 /* Defer options until the proper number of measurements occur, does not defer TCP_RACK_MEASURE_CNT */ +/* unused 1137 */ +#define TCP_RACK_PACING_BETA 1138 /* Changing the beta for pacing */ +#define TCP_RACK_PACING_BETA_ECN 1139 /* Changing the beta for ecn with pacing */ +#define TCP_RACK_TIMER_SLOP 1140 /* Set or get the timer slop used */ +#define TCP_RACK_DSACK_OPT 1141 /* How do we setup rack timer DSACK options bit 1/2 */ +#define TCP_RACK_ENABLE_HYSTART 1142 /* Do we allow hystart in the CC modules */ +#define TCP_RACK_SET_RXT_OPTIONS 1143 /* Set the bits in the retransmit options */ +#define TCP_RACK_HI_BETA 1144 /* Turn on/off high beta */ +#define TCP_RACK_SPLIT_LIMIT 1145 /* Set a split limit for split allocations */ +#define TCP_RACK_PACING_DIVISOR 1146 /* Pacing divisor given to rate-limit code for burst sizing */ +#define TCP_RACK_PACE_MIN_SEG 1147 /* Pacing min seg size rack will use */ +#define TCP_RACK_DGP_IN_REC 1148 /* Do we use full DGP in recovery? */ +/* unused 1149 */ +#define TCP_HYBRID_PACING 1150 /* Hybrid pacing enablement */ +#define TCP_PACING_DND 1151 /* When pacing with rr_config=3 can sacks disturb us */ +#define TCP_SS_EEXIT 1152 /* Do we do early exit from slowtart if no b/w growth */ +#define TCP_DGP_UPPER_BOUNDS 1153 /* SS and CA upper bound in percentage */ +#define TCP_NO_TIMELY 1154 /* Disable/enable Timely */ +#define TCP_HONOR_HPTS_MIN 1155 /* Do we honor hpts min to */ +#define TCP_REC_IS_DYN 1156 /* Do we allow timely to change recovery multiplier? */ +#define TCP_SIDECHAN_DIS 1157 /* Disable/enable the side-channel */ +#define TCP_FILLCW_RATE_CAP 1158 /* Set a cap for DGP's fillcw */ +/* unused 1159 */ +#define TCP_STACK_SPEC_INFO 1160 /* Get stack specific information (if present) */ +#define RACK_CSPR_IS_FCC 1161 +#define TCP_GP_USE_LTBW 1162 /* how we use lt_bw 0=not, 1=min, 2=max */ + /* Start of reserved space for third-party user-settable options. */ #define TCP_VENDOR SO_VENDOR @@ -436,8 +454,9 @@ struct tcp_info { u_int32_t tcpi_rcv_adv; /* Peer advertised window */ u_int32_t tcpi_dupacks; /* Consecutive dup ACKs recvd */ + u_int32_t tcpi_rttmin; /* Min observed RTT */ /* Padding to grow without breaking ABI. */ - u_int32_t __tcpi_pad[10]; /* Padding. */ + u_int32_t __tcpi_pad[14]; /* Padding. */ }; /* @@ -449,9 +468,23 @@ struct tcp_fastopen { int enable; uint8_t psk[TCP_FASTOPEN_PSK_LEN]; }; -#endif + #define TCP_FUNCTION_NAME_LEN_MAX 32 +struct stack_specific_info { + char stack_name[TCP_FUNCTION_NAME_LEN_MAX]; + uint64_t policer_last_bw; /* Only valid if detection enabled and policer detected */ + uint64_t bytes_transmitted; + uint64_t bytes_retransmitted; + uint32_t policer_detection_enabled: 1, + policer_detected : 1, /* transport thinks a policer is on path */ + highly_buffered : 1, /* transport considers the path highly buffered */ + spare : 29; + uint32_t policer_bucket_size; /* Only valid if detection enabled and policer detected */ + uint32_t current_round; + uint32_t _rack_i_pad[18]; +}; + struct tcp_function_set { char function_set_name[TCP_FUNCTION_NAME_LEN_MAX]; uint32_t pcbcnt; @@ -477,6 +510,7 @@ struct tcp_snd_req { uint64_t start; uint64_t end; uint32_t flags; + uint32_t playout_ms; }; union tcp_log_userdata { @@ -507,9 +541,12 @@ struct tcp_log_user { #define TCP_HYBRID_PACING_H_MS 0x0008 /* A client hint for maxseg is present */ #define TCP_HYBRID_PACING_ENABLE 0x0010 /* We are enabling hybrid pacing else disable */ #define TCP_HYBRID_PACING_S_MSS 0x0020 /* Clent wants us to set the mss overriding gp est in CU */ -#define TCP_HYBRID_PACING_SETMSS 0x1000 /* Internal flag that tellsus we set the mss on this entry */ +#define TCP_HAS_PLAYOUT_MS 0x0040 /* The client included the chunk playout milliseconds: deprecate */ +/* the below are internal only flags */ +#define TCP_HYBRID_PACING_USER_MASK 0x0FFF /* Non-internal flags mask */ +#define TCP_HYBRID_PACING_SETMSS 0x1000 /* Internal flag that tells us we set the mss on this entry */ #define TCP_HYBRID_PACING_WASSET 0x2000 /* We init to this to know if a hybrid command was issued */ - +#define TCP_HYBRID_PACING_SENDTIME 0x4000 /* Duplicate tm to last, use sendtime for catch up mode */ struct tcp_hybrid_req { struct tcp_snd_req req; @@ -536,4 +573,5 @@ struct tcp_hybrid_req { #define TCP_REUSPORT_LB_NUMA_NODOM (-2) /* remove numa binding */ #define TCP_REUSPORT_LB_NUMA_CURDOM (-1) /* bind to current domain */ +#endif /* __BSD_VISIBLE */ #endif /* !_NETINET_TCP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/netinet/tcp_ecn.h b/lib/libc/include/generic-freebsd/netinet/tcp_ecn.h index 8d312344bb3f..94636ce646df 100644 --- a/lib/libc/include/generic-freebsd/netinet/tcp_ecn.h +++ b/lib/libc/include/generic-freebsd/netinet/tcp_ecn.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)tcp_ecn.h 8.4 (Berkeley) 5/24/95 */ #ifndef _NETINET_TCP_ECN_H_ @@ -40,6 +38,8 @@ #include #include +#define TH_ACE_SHIFT 6 + void tcp_ecn_input_syn_sent(struct tcpcb *, uint16_t, int); void tcp_ecn_input_parallel_syn(struct tcpcb *, uint16_t, int); int tcp_ecn_input_segment(struct tcpcb *, uint16_t, int, int, int); @@ -48,7 +48,6 @@ int tcp_ecn_output_established(struct tcpcb *, uint16_t *, int, bool); void tcp_ecn_syncache_socket(struct tcpcb *, struct syncache *); int tcp_ecn_syncache_add(uint16_t, int); uint16_t tcp_ecn_syncache_respond(uint16_t, struct syncache *); -int tcp_ecn_get_ace(uint16_t); #endif /* _KERNEL */ diff --git a/lib/libc/include/generic-freebsd/netinet/tcp_fastopen.h b/lib/libc/include/generic-freebsd/netinet/tcp_fastopen.h index 4028b9191f00..2eb22ea47603 100644 --- a/lib/libc/include/generic-freebsd/netinet/tcp_fastopen.h +++ b/lib/libc/include/generic-freebsd/netinet/tcp_fastopen.h @@ -79,6 +79,7 @@ struct tcp_fastopen_ccache { uint32_t secret; }; +struct tcpcb; #ifdef TCP_RFC7413 void tcp_fastopen_init(void); void tcp_fastopen_destroy(void); diff --git a/lib/libc/include/generic-freebsd/netinet/tcp_fsm.h b/lib/libc/include/generic-freebsd/netinet/tcp_fsm.h index 0d93b132e6e1..be9203016810 100644 --- a/lib/libc/include/generic-freebsd/netinet/tcp_fsm.h +++ b/lib/libc/include/generic-freebsd/netinet/tcp_fsm.h @@ -28,8 +28,6 @@ * 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. - * - * @(#)tcp_fsm.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NETINET_TCP_FSM_H_ diff --git a/lib/libc/include/generic-freebsd/netinet/tcp_hpts.h b/lib/libc/include/generic-freebsd/netinet/tcp_hpts.h index abb23403ca46..1433579c86e8 100644 --- a/lib/libc/include/generic-freebsd/netinet/tcp_hpts.h +++ b/lib/libc/include/generic-freebsd/netinet/tcp_hpts.h @@ -26,14 +26,38 @@ #ifndef __tcp_hpts_h__ #define __tcp_hpts_h__ -/* Number of useconds in a hpts tick */ -#define HPTS_TICKS_PER_SLOT 10 +/* Number of useconds represented by an hpts slot */ +#define HPTS_USECS_PER_SLOT 10 #define HPTS_MS_TO_SLOTS(x) ((x * 100) + 1) #define HPTS_USEC_TO_SLOTS(x) ((x+9) /10) #define HPTS_USEC_IN_SEC 1000000 #define HPTS_MSEC_IN_SEC 1000 #define HPTS_USEC_IN_MSEC 1000 +static inline uint32_t +tcp_tv_to_hpts_slot(const struct timeval *sv) +{ + return ((sv->tv_sec * 100000) + (sv->tv_usec / HPTS_USECS_PER_SLOT)); +} + +static inline uint32_t +tcp_tv_to_usec(const struct timeval *sv) +{ + return ((uint32_t) ((sv->tv_sec * HPTS_USEC_IN_SEC) + sv->tv_usec)); +} + +static inline uint32_t +tcp_tv_to_msec(const struct timeval *sv) +{ + return ((uint32_t) ((sv->tv_sec * HPTS_MSEC_IN_SEC) + (sv->tv_usec/HPTS_USEC_IN_MSEC))); +} + +static inline uint64_t +tcp_tv_to_lusec(const struct timeval *sv) +{ + return ((uint64_t)((sv->tv_sec * HPTS_USEC_IN_SEC) + sv->tv_usec)); +} + struct hpts_diag { uint32_t p_hpts_active; /* bbr->flex7 x */ uint32_t p_nxt_slot; /* bbr->flex1 x */ @@ -66,52 +90,16 @@ struct hpts_diag { #define PACE_PKT_OUTPUT 0x40 /* Output Packets being paced */ #define PACE_TMR_MASK (PACE_TMR_KEEP|PACE_TMR_PERSIT|PACE_TMR_RXT|PACE_TMR_TLP|PACE_TMR_RACK|PACE_TMR_DELACK) -#define DEFAULT_CONNECTION_THESHOLD 100 +#ifdef _KERNEL /* - * When using the hpts, a TCP stack must make sure - * that once a INP_DROPPED flag is applied to a INP - * that it does not expect tcp_output() to ever be - * called by the hpts. The hpts will *not* call - * any output (or input) functions on a TCB that - * is in the DROPPED state. - * - * This implies final ACK's and RST's that might - * be sent when a TCB is still around must be - * sent from a routine like tcp_respond(). - */ -#define LOWEST_SLEEP_ALLOWED 50 -#define DEFAULT_MIN_SLEEP 250 /* How many usec's is default for hpts sleep - * this determines min granularity of the - * hpts. If 1, granularity is 10useconds at - * the cost of more CPU (context switching). - * Note do not set this to 0. - */ -#define DYNAMIC_MIN_SLEEP DEFAULT_MIN_SLEEP -#define DYNAMIC_MAX_SLEEP 5000 /* 5ms */ - -/* Thresholds for raising/lowering sleep */ -#define TICKS_INDICATE_MORE_SLEEP 100 /* This would be 1ms */ -#define TICKS_INDICATE_LESS_SLEEP 1000 /* This would indicate 10ms */ -/** - * - * Dynamic adjustment of sleeping times is done in "new" mode - * where we are depending on syscall returns and lro returns - * to push hpts forward mainly and the timer is only a backstop. - * - * When we are in the "new" mode i.e. conn_cnt > conn_cnt_thresh - * then we do a dynamic adjustment on the time we sleep. - * Our threshold is if the lateness of the first client served (in ticks) is - * greater than or equal too ticks_indicate_more_sleep (10ms - * or 10000 ticks). If we were that late, the actual sleep time - * is adjusted down by 50%. If the ticks_ran is less than - * ticks_indicate_more_sleep (100 ticks or 1000usecs). - * - */ + * The following are the definitions for the kernel HPTS interface for managing + * the HPTS ring and the TCBs on it. +*/ -#ifdef _KERNEL void tcp_hpts_init(struct tcpcb *); void tcp_hpts_remove(struct tcpcb *); + static inline bool tcp_in_hpts(struct tcpcb *tp) { @@ -149,57 +137,17 @@ uint32_t tcp_hpts_insert_diag(struct tcpcb *tp, uint32_t slot, int32_t line, #define tcp_hpts_insert(inp, slot) \ tcp_hpts_insert_diag((inp), (slot), __LINE__, NULL) -void __tcp_set_hpts(struct tcpcb *tp, int32_t line); -#define tcp_set_hpts(a) __tcp_set_hpts(a, __LINE__) - -void tcp_set_inp_to_drop(struct inpcb *inp, uint16_t reason); - -void tcp_lro_hpts_init(void); -void tcp_lro_hpts_uninit(void); - -extern int32_t tcp_min_hptsi_time; - -#endif /* _KERNEL */ - -/* - * The following functions should also be available - * to userspace as well. - */ -static __inline uint32_t -tcp_tv_to_hptstick(const struct timeval *sv) -{ - return ((sv->tv_sec * 100000) + (sv->tv_usec / HPTS_TICKS_PER_SLOT)); -} - -static __inline uint32_t -tcp_tv_to_usectick(const struct timeval *sv) -{ - return ((uint32_t) ((sv->tv_sec * HPTS_USEC_IN_SEC) + sv->tv_usec)); -} - -static __inline uint32_t -tcp_tv_to_mssectick(const struct timeval *sv) -{ - return ((uint32_t) ((sv->tv_sec * HPTS_MSEC_IN_SEC) + (sv->tv_usec/HPTS_USEC_IN_MSEC))); -} - -static __inline uint64_t -tcp_tv_to_lusectick(const struct timeval *sv) -{ - return ((uint64_t)((sv->tv_sec * HPTS_USEC_IN_SEC) + sv->tv_usec)); -} - -#ifdef _KERNEL +void tcp_set_hpts(struct tcpcb *tp); extern int32_t tcp_min_hptsi_time; static inline int32_t get_hpts_min_sleep_time(void) { - return (tcp_min_hptsi_time + HPTS_TICKS_PER_SLOT); + return (tcp_min_hptsi_time + HPTS_USECS_PER_SLOT); } -static __inline uint32_t +static inline uint32_t tcp_gethptstick(struct timeval *sv) { struct timeval tv; @@ -207,10 +155,10 @@ tcp_gethptstick(struct timeval *sv) if (sv == NULL) sv = &tv; microuptime(sv); - return (tcp_tv_to_hptstick(sv)); + return (tcp_tv_to_hpts_slot(sv)); } -static __inline uint64_t +static inline uint64_t tcp_get_u64_usecs(struct timeval *tv) { struct timeval tvd; @@ -218,10 +166,10 @@ tcp_get_u64_usecs(struct timeval *tv) if (tv == NULL) tv = &tvd; microuptime(tv); - return (tcp_tv_to_lusectick(tv)); + return (tcp_tv_to_lusec(tv)); } -static __inline uint32_t +static inline uint32_t tcp_get_usecs(struct timeval *tv) { struct timeval tvd; @@ -229,8 +177,15 @@ tcp_get_usecs(struct timeval *tv) if (tv == NULL) tv = &tvd; microuptime(tv); - return (tcp_tv_to_usectick(tv)); + return (tcp_tv_to_usec(tv)); } +/* + * LRO HPTS initialization and uninitialization, only for internal use by the + * HPTS code. + */ +void tcp_lro_hpts_init(void); +void tcp_lro_hpts_uninit(void); + #endif /* _KERNEL */ #endif /* __tcp_hpts_h__ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/netinet/tcp_log_buf.h b/lib/libc/include/generic-freebsd/netinet/tcp_log_buf.h index 286762f8ee94..d3ab8f6e18d4 100644 --- a/lib/libc/include/generic-freebsd/netinet/tcp_log_buf.h +++ b/lib/libc/include/generic-freebsd/netinet/tcp_log_buf.h @@ -60,14 +60,6 @@ struct tcp_log_verbose uint8_t _pad[4]; } ALIGN_TCP_LOG; -/* Internal RACK state variables. */ -struct tcp_log_rack -{ - uint32_t tlr_rack_rtt; /* rc_rack_rtt */ - uint8_t tlr_state; /* Internal RACK state */ - uint8_t _pad[3]; /* Padding */ -}; - struct tcp_log_bbr { uint64_t cur_del_rate; uint64_t delRate; @@ -126,7 +118,6 @@ struct tcp_log_sendfile { */ union tcp_log_stackspecific { - struct tcp_log_rack u_rack; struct tcp_log_bbr u_bbr; struct tcp_log_sendfile u_sf; struct tcp_log_raw u_raw; /* "raw" log access */ @@ -185,7 +176,6 @@ struct tcp_log_buffer uint8_t _pad[3]; /* Padding */ /* Per-stack info */ union tcp_log_stackspecific tlb_stackinfo; -#define tlb_rack tlb_stackinfo.u_rack /* The packet */ uint32_t tlb_len; /* The packet's data length */ @@ -201,14 +191,14 @@ enum tcp_log_events { TCP_LOG_OUT, /* Transmit (without other event) 2 */ TCP_LOG_RTO, /* Retransmit timeout 3 */ TCP_LOG_SB_WAKE, /* Awaken socket buffer 4 */ - TCP_LOG_BAD_RETRAN, /* Detected bad retransmission 5 */ + TCP_UNUSED_5, /* Detected bad retransmission 5 */ TCP_LOG_PRR, /* Doing PRR 6 */ - TCP_LOG_REORDER, /* Detected reorder 7 */ + TCP_UNUSED_7, /* Detected reorder 7 */ TCP_LOG_HPTS, /* Hpts sending a packet 8 */ BBR_LOG_BBRUPD, /* We updated BBR info 9 */ BBR_LOG_BBRSND, /* We did a slot calculation and sending is done 10 */ BBR_LOG_ACKCLEAR, /* A ack clears all outstanding 11 */ - BBR_LOG_INQUEUE, /* The tcb had a packet input to it 12 */ + TCP_UNUSED_12, /* The tcb had a packet input to it 12 */ BBR_LOG_TIMERSTAR, /* Start a timer 13 */ BBR_LOG_TIMERCANC, /* Cancel a timer 14 */ BBR_LOG_ENTREC, /* Entered recovery 15 */ @@ -245,7 +235,7 @@ enum tcp_log_events { BBR_LOG_REDUCE, /* old bbr log reduce for 4.1 and earlier 46*/ TCP_LOG_RTT, /* A rtt (in useconds) is being sampled and applied to the srtt algo 47 */ BBR_LOG_SETTINGS_CHG, /* Settings changed for loss response 48 */ - BBR_LOG_SRTT_GAIN_EVENT, /* SRTT gaining -- now not used 49 */ + TCP_UNUSED_49, /* SRTT gaining -- now not used 49 */ TCP_LOG_REASS, /* Reassembly buffer logging 50 */ TCP_HDWR_PACE_SIZE, /* TCP pacing size set (rl and rack uses this) 51 */ BBR_LOG_HDWR_PACE, /* TCP Hardware pacing log 52 */ @@ -253,9 +243,9 @@ enum tcp_log_events { TCP_LOG_CONNEND, /* End of connection 54 */ TCP_LOG_LRO, /* LRO entry 55 */ TCP_SACK_FILTER_RES, /* Results of SACK Filter 56 */ - TCP_SAD_DETECT, /* Sack Attack Detection 57 */ + TCP_UNUSED_57, /* Sack Attack Detection 57 */ TCP_TIMELY_WORK, /* Logs regarding Timely CC tweaks 58 */ - TCP_LOG_USER_EVENT, /* User space event data 59 */ + TCP_UNUSED_59, /* User space event data 59 */ TCP_LOG_SENDFILE, /* sendfile() logging for TCP connections 60 */ TCP_LOG_REQ_T, /* logging of request tracking 61 */ TCP_LOG_ACCOUNTING, /* Log of TCP Accounting data 62 */ @@ -267,7 +257,9 @@ enum tcp_log_events { TCP_RACK_TP_TRIGGERED, /* A rack tracepoint is triggered 68 */ TCP_HYBRID_PACING_LOG, /* Hybrid pacing log 69 */ TCP_LOG_PRU, /* TCP protocol user request 70 */ - TCP_LOG_END /* End (keep at end) 71 */ + TCP_UNUSED_71, /* old TCP Policer detectionn, not used 71 */ + TCP_PCM_MEASURE, /* TCP Path Capacity Measurement 72 */ + TCP_LOG_END /* End (keep at end) 73 */ }; enum tcp_log_states { @@ -371,10 +363,11 @@ struct tcp_log_dev_log_queue { #define TCP_TP_COLLAPSED_RXT 0x00000004 /* When we actually retransmit a collapsed window rsm */ #define TCP_TP_REQ_LOG_FAIL 0x00000005 /* We tried to allocate a Request log but had no space */ #define TCP_TP_RESET_RCV 0x00000006 /* Triggers when we receive a RST */ -#define TCP_TP_EXCESS_RXT 0x00000007 /* When we get excess RXT's clamping the cwnd */ +#define TCP_TP_POLICER_DET 0x00000007 /* When we detect a policer */ +#define TCP_TP_EXCESS_RXT TCP_TP_POLICER_DET /* alias */ #define TCP_TP_SAD_TRIGGERED 0x00000008 /* Sack Attack Detection triggers */ - #define TCP_TP_SAD_SUSPECT 0x0000000a /* A sack has supicious information in it */ +#define TCP_TP_PACED_BOTTOM 0x0000000b /* We have paced at the bottom */ #ifdef _KERNEL @@ -384,12 +377,12 @@ extern int32_t tcp_trace_point_count; /* * Returns true if any sort of BB logging is enabled, - * commonly used throughout the codebase. + * commonly used throughout the codebase. */ static inline int tcp_bblogging_on(struct tcpcb *tp) { - if (tp->_t_logstate <= TCP_LOG_STATE_OFF) + if (tp->_t_logstate <= TCP_LOG_STATE_OFF) return (0); if (tp->_t_logstate == TCP_LOG_VIA_BBPOINTS) return (0); @@ -434,7 +427,7 @@ tcp_set_bblog_state(struct tcpcb *tp, uint8_t ls, uint8_t bbpoint) } } -static inline uint32_t +static inline uint32_t tcp_get_bblog_state(struct tcpcb *tp) { return (tp->_t_logstate); @@ -546,12 +539,12 @@ struct tcpcb; NULL, NULL, 0, NULL); \ } while (0) #endif /* TCP_LOG_FORCEVERBOSE */ +/* Assumes/requires the caller has already checked tcp_bblogging_on(tp). */ #define TCP_LOG_EVENTP(tp, th, rxbuf, txbuf, eventid, errornum, len, stackinfo, th_hostorder, tv) \ do { \ - if (tcp_bblogging_on(tp)) \ - tcp_log_event(tp, th, rxbuf, txbuf, eventid, \ - errornum, len, stackinfo, th_hostorder, \ - NULL, NULL, 0, tv); \ + KASSERT(tcp_bblogging_on(tp), ("bblogging is off")); \ + tcp_log_event(tp, th, rxbuf, txbuf, eventid, errornum, len, \ + stackinfo, th_hostorder, NULL, NULL, 0, tv); \ } while (0) #ifdef TCP_BLACKBOX @@ -577,6 +570,9 @@ void tcp_log_flowend(struct tcpcb *tp); void tcp_log_sendfile(struct socket *so, off_t offset, size_t nbytes, int flags); int tcp_log_apply_ratio(struct tcpcb *tp, int ratio); +#ifdef DDB +void db_print_bblog_entries(struct tcp_log_stailq *log_entries, int indent); +#endif #else /* !TCP_BLACKBOX */ #define tcp_log_verbose (false) diff --git a/lib/libc/include/generic-freebsd/netinet/tcp_offload.h b/lib/libc/include/generic-freebsd/netinet/tcp_offload.h index fcc33734eafa..f06c2932cdf1 100644 --- a/lib/libc/include/generic-freebsd/netinet/tcp_offload.h +++ b/lib/libc/include/generic-freebsd/netinet/tcp_offload.h @@ -38,6 +38,8 @@ extern int registered_toedevs; +struct tcpcb; + int tcp_offload_connect(struct socket *, struct sockaddr *); void tcp_offload_listen_start(struct tcpcb *); void tcp_offload_listen_stop(struct tcpcb *); diff --git a/lib/libc/include/generic-freebsd/netinet/tcp_pcap.h b/lib/libc/include/generic-freebsd/netinet/tcp_pcap.h deleted file mode 100644 index f6af5dc5723c..000000000000 --- a/lib/libc/include/generic-freebsd/netinet/tcp_pcap.h +++ /dev/null @@ -1,39 +0,0 @@ -/*- - * Copyright (c) 2015 - * Jonathan Looney. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _NETINET_TCP_PCAP_H_ -#define _NETINET_TCP_PCAP_H_ - -void tcp_pcap_init(void); -void tcp_pcap_add(struct tcphdr *th, struct mbuf *m, struct mbufq *queue); -void tcp_pcap_drain(struct mbufq *queue); -void tcp_pcap_tcpcb_init(struct tcpcb *tp); -void tcp_pcap_set_sock_max(struct mbufq *queue, int newval); -int tcp_pcap_get_sock_max(struct mbufq *queue); - -extern int tcp_pcap_aggressive_free; - -#endif /* _NETINET_TCP_PCAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/netinet/tcp_ratelimit.h b/lib/libc/include/generic-freebsd/netinet/tcp_ratelimit.h index cf9278bb68a0..347802d9f041 100644 --- a/lib/libc/include/generic-freebsd/netinet/tcp_ratelimit.h +++ b/lib/libc/include/generic-freebsd/netinet/tcp_ratelimit.h @@ -94,6 +94,8 @@ CK_LIST_HEAD(head_tcp_rate_set, tcp_rate_set); #ifndef ETHERNET_SEGMENT_SIZE #define ETHERNET_SEGMENT_SIZE 1514 #endif +struct tcpcb; + #ifdef RATELIMIT #define DETAILED_RATELIMIT_SYSCTL 1 /* * Undefine this if you don't want @@ -131,6 +133,9 @@ tcp_get_pacing_burst_size_w_divisor(struct tcpcb *tp, uint64_t bw, uint32_t segs void tcp_rl_log_enobuf(const struct tcp_hwrate_limit_table *rte); +void +tcp_rl_release_ifnet(struct ifnet *ifp); + #else static inline const struct tcp_hwrate_limit_table * tcp_set_pacing_rate(struct tcpcb *tp, struct ifnet *ifp, @@ -218,6 +223,10 @@ tcp_rl_log_enobuf(const struct tcp_hwrate_limit_table *rte) { } +static inline void +tcp_rl_release_ifnet(struct ifnet *ifp) +{ +} #endif /* diff --git a/lib/libc/include/generic-freebsd/netinet/tcp_seq.h b/lib/libc/include/generic-freebsd/netinet/tcp_seq.h index c1517dc5037d..83e344e4adf5 100644 --- a/lib/libc/include/generic-freebsd/netinet/tcp_seq.h +++ b/lib/libc/include/generic-freebsd/netinet/tcp_seq.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)tcp_seq.h 8.3 (Berkeley) 6/21/95 */ #ifndef _NETINET_TCP_SEQ_H_ diff --git a/lib/libc/include/generic-freebsd/netinet/tcp_stacks/rack_bbr_common.h b/lib/libc/include/generic-freebsd/netinet/tcp_stacks/rack_bbr_common.h index 860cc1a7ba3b..8202e5bd0ae0 100644 --- a/lib/libc/include/generic-freebsd/netinet/tcp_stacks/rack_bbr_common.h +++ b/lib/libc/include/generic-freebsd/netinet/tcp_stacks/rack_bbr_common.h @@ -89,30 +89,25 @@ int ctf_do_queued_segments(struct tcpcb *tp, int have_pkt); uint32_t ctf_outstanding(struct tcpcb *tp); uint32_t ctf_flight_size(struct tcpcb *tp, uint32_t rc_sacked); int -_ctf_drop_checks(struct tcpopt *to, struct mbuf *m, struct tcphdr *th, +ctf_drop_checks(struct tcpopt *to, struct mbuf *m, struct tcphdr *th, struct tcpcb *tp, int32_t *tlenp, - int32_t *thf, int32_t *drop_hdrlen, int32_t *ret_val, - uint32_t *ts, uint32_t *cnt); -void ctf_ack_war_checks(struct tcpcb *tp, uint32_t *ts, uint32_t *cnt); -#define ctf_drop_checks(a, b, c, d, e, f, g, h) _ctf_drop_checks(a, b, c, d, e, f, g, h, NULL, NULL) + int32_t *thf, int32_t *drop_hdrlen, int32_t *ret_val); +void ctf_ack_war_checks(struct tcpcb *tp); void -__ctf_do_dropafterack(struct mbuf *m, struct tcpcb *tp, +ctf_do_dropafterack(struct mbuf *m, struct tcpcb *tp, struct tcphdr *th, int32_t thflags, int32_t tlen, - int32_t *ret_val, uint32_t *ts, uint32_t *cnt); - -#define ctf_do_dropafterack(a, b, c, d, e, f) __ctf_do_dropafterack(a, b, c, d, e, f, NULL, NULL) + int32_t *ret_val); void ctf_do_dropwithreset(struct mbuf *m, struct tcpcb *tp, - struct tcphdr *th, int32_t rstreason, int32_t tlen); + struct tcphdr *th, int32_t tlen); void ctf_do_drop(struct mbuf *m, struct tcpcb *tp); int -__ctf_process_rst(struct mbuf *m, struct tcphdr *th, - struct socket *so, struct tcpcb *tp, uint32_t *ts, uint32_t *cnt); -#define ctf_process_rst(m, t, s, p) __ctf_process_rst(m, t, s, p, NULL, NULL) +ctf_process_rst(struct mbuf *m, struct tcphdr *th, + struct socket *so, struct tcpcb *tp); void ctf_challenge_ack(struct mbuf *m, struct tcphdr *th, @@ -130,7 +125,7 @@ ctf_calc_rwin(struct socket *so, struct tcpcb *tp); void ctf_do_dropwithreset_conn(struct mbuf *m, struct tcpcb *tp, struct tcphdr *th, - int32_t rstreason, int32_t tlen); + int32_t tlen); uint32_t ctf_fixed_maxseg(struct tcpcb *tp); diff --git a/lib/libc/include/generic-freebsd/netinet/tcp_stacks/sack_filter.h b/lib/libc/include/generic-freebsd/netinet/tcp_stacks/sack_filter.h index 37c172666985..7823fa577a18 100644 --- a/lib/libc/include/generic-freebsd/netinet/tcp_stacks/sack_filter.h +++ b/lib/libc/include/generic-freebsd/netinet/tcp_stacks/sack_filter.h @@ -25,19 +25,84 @@ * SUCH DAMAGE. */ -/* - * Seven entry's is carefully choosen to - * fit in one cache line. We can easily - * change this to 15 (but it gets very - * little extra filtering). To change it - * to be larger than 15 would require either - * sf_bits becoming a uint32_t and then you - * could go to 31.. or change it to a full - * bitstring.. It is really doubtful you - * will get much benefit beyond 7, in testing - * there was a small amount but very very small. +/** + * + * The Sack filter is designed to do two functions, first it trys to reduce + * the processing of sacks. Consider that often times you get something like + * + * ack 1 (sack 100:200) + * ack 1 (sack 100:300) + * ack 1 (sack(100:400) + * + * You really want to process the 100:200 and then on the next sack process + * only 200:300 (the new data) and then finally on the third 300:400. The filter + * removes from your processing routines the already processed sack information so + * that after the filter completes you only have "new" sacks that you have not + * processed. This saves computation time so you do not need to worry about + * previously processed sack information. + * + * The second thing that the sack filter does is help protect against malicious + * attackers that are trying to attack any linked lists (or other data structures) + * that are used in sack processing. Consider an attacker sending in sacks for + * every other byte of data outstanding. This could in theory drastically split + * up any scoreboard you are maintaining and make you search through a very large + * linked list (or other structure) eating up CPU. If you split far enough and + * fracture your data structure enough you could potentially be crippled by a malicious + * peer. How the filter works here is it filters out sacks that are less than an MSS. + * We do this because generally a packet (aka MSS) should be kept whole. The only place + * we allow a smaller SACK is when the SACK touches the end of our socket buffer. This allows + * TLP to still work properly and yet protects us from splitting. The filter also only allows + * a set number of splits (defined in SACK_FILTER_BLOCKS). If more than that many sacks locations + * are being sent we discard additional ones until the earlier holes are filled up. The maximum + * the current filter can be is 15, which we have moved to since we want to be as generous as + * possible with allowing for loss. However, in previous testing of the filter it was found + * that there was very little benefit from moving from 7 to 15 sack points. Though at + * that previous set of tests, we would just discard earlier information in the filter. Now + * that we do not do that i.e. discard information and instead drop sack data we have raised + * the value to the max i.e. 15. If you want to expand beyond 15 one would have to either increase + * the size of the sf_bits to a uint32_t which could then get you a maximum of 31 splits or + * move to a true bitstring. If this is done however it further increases your risk to + * sack attacks, the bigger the number of splits (filter blocks) that are allowed + * the larger your processing arrays will grow as well as the filter. + * + * Note that this protection does not prevent an attacker from asking for a 20 byte + * MSS, that protection must be done elsewhere during the negotiation of the connection + * and is done now by just ignoring sack's from connections with too small of MSS which + * prevents sack from working and thus makes the connection less efficient but protects + * the system from harm. + * + * We may actually want to consider dropping the size of the array back to 7 to further + * protect the system which would be a more cautious approach. + * + * TCP Developer information: + * + * To use the sack filter its actually pretty simple. All you do is the normal sorting + * and sanity checks of your sacks but then after that you call out to sack_filter_blks() + * passing in the tcpcb, the sack-filter you are using (memory you have allocated) the + * pointer to the sackblk array and how many sorted valid blocks there are as well + * as what the new th_ack point is. The filter will return to you the number of + * blocks left after filtering. It will reshape the blocks based on the previous + * sacks you have received and processed. If sack_filter_blks() returns 0 then no + * new sack data is present to be processed. + * + * Whenever you reach the point of snd_una == snd_max, you should call sack_filter_clear with + * the snd_una point. You also need to call this if you invalidate your sack array for any + * reason (such as RTO's or MTU changes or some other thing that makes you think all + * data is now un-acknowledged). You can also pass in sack_filter_blks(tp, sf, NULL, 0, th_ack) to + * advance the cum-ack point. You can use sack_filter_blks_used(sf) to determine if you have filter blocks as + * well. So putting these two together, anytime the cum-ack moves forward you probably want to + * do: + * if (sack_filter_blks_used(sf)) + * sack_filter_blks(tp, sf, NULL, 0, th_ack); + * + * If for some reason you have ran the sack-filter and something goes wrong (you can't allocate space + * for example to split your sack-array. You can "undo" the data within the sack filter by calling + * sack_filter_rject(sf, in) passing in the list of blocks to be "removed" from the sack-filter. + * You can see an example of this use in bbr.c though rack.c has never found it needed. + * */ -#define SACK_FILTER_BLOCKS 7 + +#define SACK_FILTER_BLOCKS 15 struct sack_filter { tcp_seq sf_ack; @@ -48,8 +113,13 @@ struct sack_filter { }; #ifdef _KERNEL void sack_filter_clear(struct sack_filter *sf, tcp_seq seq); -int sack_filter_blks(struct sack_filter *sf, struct sackblk *in, int numblks, +int sack_filter_blks(struct tcpcb *tp, struct sack_filter *sf, struct sackblk *in, int numblks, tcp_seq th_ack); void sack_filter_reject(struct sack_filter *sf, struct sackblk *in); +static inline uint8_t sack_filter_blks_used(struct sack_filter *sf) +{ + return (sf->sf_used); +} + #endif #endif \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/netinet/tcp_stacks/tailq_hash.h b/lib/libc/include/generic-freebsd/netinet/tcp_stacks/tailq_hash.h index cf0314c6c0fd..853928f0a418 100644 --- a/lib/libc/include/generic-freebsd/netinet/tcp_stacks/tailq_hash.h +++ b/lib/libc/include/generic-freebsd/netinet/tcp_stacks/tailq_hash.h @@ -13,10 +13,12 @@ #define MAX_ALLOWED_SEQ_RANGE (SEQ_BUCKET_SIZE * (MAX_HASH_ENTRIES-1)) struct tailq_hash { - struct rack_head ht[MAX_HASH_ENTRIES]; uint32_t min; uint32_t max; uint32_t count; + struct rack_sendmap *rsm_min; + struct rack_sendmap *rsm_max; + struct rack_head ht[MAX_HASH_ENTRIES]; }; struct rack_sendmap * @@ -53,6 +55,10 @@ tqhash_init(struct tailq_hash *hs); int tqhash_trim(struct tailq_hash *hs, uint32_t th_ack); +void +tqhash_update_end(struct tailq_hash *hs, struct rack_sendmap *rsm, + uint32_t th_ack); + #define TQHASH_FOREACH(var, head) \ for ((var) = tqhash_min((head)); \ diff --git a/lib/libc/include/generic-freebsd/netinet/tcp_stacks/tcp_bbr.h b/lib/libc/include/generic-freebsd/netinet/tcp_stacks/tcp_bbr.h index d79315ac49dc..88cdfd44fa35 100644 --- a/lib/libc/include/generic-freebsd/netinet/tcp_stacks/tcp_bbr.h +++ b/lib/libc/include/generic-freebsd/netinet/tcp_stacks/tcp_bbr.h @@ -347,8 +347,6 @@ struct bbr_log_sysctl_out { /* * Locking for the rack control block. * a) Locked by INP_WLOCK - * b) Locked by the hpts-mutex - * */ #define BBR_STATE_STARTUP 0x01 #define BBR_STATE_DRAIN 0x02 diff --git a/lib/libc/include/generic-freebsd/netinet/tcp_stacks/tcp_rack.h b/lib/libc/include/generic-freebsd/netinet/tcp_stacks/tcp_rack.h index ad5a0d889df2..5e312158b4f7 100644 --- a/lib/libc/include/generic-freebsd/netinet/tcp_stacks/tcp_rack.h +++ b/lib/libc/include/generic-freebsd/netinet/tcp_stacks/tcp_rack.h @@ -48,6 +48,8 @@ #define RACK_MERGED 0x080000/* The RSM was merged */ #define RACK_PMTU_CHG 0x100000/* The path mtu changed on this guy */ #define RACK_STRADDLE 0x200000/* The seq straddles the bucket line */ +#define RACK_WAS_LOST 0x400000/* Is the rsm considered lost */ +#define RACK_IS_PCM 0x800000/* A PCM measurement is being taken */ #define RACK_NUM_OF_RETRANS 3 #define RACK_INITIAL_RTO 1000000 /* 1 second in microseconds */ @@ -63,6 +65,7 @@ struct rack_sendmap { uint32_t r_rtr_bytes; /* How many bytes have been retransmitted */ uint32_t r_flags : 24, /* Flags as defined above */ r_rtr_cnt : 8; /* Retran count, index this -1 to get time */ + uint32_t r_act_rxt_cnt; /* The actual total count of transmits */ struct mbuf *m; uint32_t soff; uint32_t orig_m_len; /* The original mbuf len when we sent (can update) */ @@ -174,6 +177,8 @@ struct rack_rtt_sample { #define RACK_TO_FRM_PERSIST 5 #define RACK_TO_FRM_DELACK 6 +#define RCV_PATH_RTT_MS 10 /* How many ms between recv path RTT's */ + struct rack_opts_stats { uint64_t tcp_rack_tlp_reduce; uint64_t tcp_rack_pace_always; @@ -194,7 +199,6 @@ struct rack_opts_stats { uint64_t tcp_rack_min_pace_seg; uint64_t tcp_rack_pace_rate_ca; uint64_t tcp_rack_rr; - uint64_t tcp_rack_do_detection; uint64_t tcp_rack_rrr_no_conf_rate; uint64_t tcp_initial_rate; uint64_t tcp_initial_win; @@ -232,7 +236,7 @@ struct rack_opts_stats { uint64_t tcp_rack_rtt_use; uint64_t tcp_data_after_close; uint64_t tcp_defer_opt; - uint64_t tcp_rxt_clamp; + uint64_t tcp_pol_detect; uint64_t tcp_rack_beta; uint64_t tcp_rack_beta_ecn; uint64_t tcp_rack_timer_slop; @@ -242,6 +246,11 @@ struct rack_opts_stats { uint64_t tcp_rack_pacing_divisor; uint64_t tcp_rack_min_seg; uint64_t tcp_dgp_in_rec; + uint64_t tcp_notimely; + uint64_t tcp_honor_hpts; + uint64_t tcp_dyn_rec; + uint64_t tcp_fillcw_rate_cap; + uint64_t tcp_pol_mss; }; /* RTT shrink reasons */ @@ -263,6 +272,9 @@ struct rack_opts_stats { #define TLP_USE_TWO_TWO 3 /* Use 2.2 behavior */ #define RACK_MIN_BW 8000 /* 64kbps in Bps */ +#define CCSP_DIS_MASK 0x0001 +#define HYBRID_DIS_MASK 0x0002 + /* Rack quality indicators for GPUT measurements */ #define RACK_QUALITY_NONE 0 /* No quality stated */ #define RACK_QUALITY_HIGH 1 /* A normal measurement of a GP RTT */ @@ -315,10 +327,9 @@ extern counter_u64_t rack_opts_arry[RACK_OPTS_SIZE]; /* * Locking for the rack control block. * a) Locked by INP_WLOCK - * b) Locked by the hpts-mutex - * */ #define RACK_GP_HIST 4 /* How much goodput history do we maintain? */ +#define RETRAN_CNT_SIZE 16 #define RACK_NUM_FSB_DEBUG 16 #ifdef _KERNEL @@ -342,6 +353,26 @@ struct rack_fast_send_blk { struct tailq_hash; +struct rack_pcm_info { + /* Base send time and s/e filled in by rack_log_output */ + uint64_t send_time; + uint32_t sseq; + uint32_t eseq; + /* Ack's fill in the rest of the data */ + uint16_t cnt; + /* Maximum acks present */ + uint16_t cnt_alloc; +}; + +#define RACK_DEFAULT_PCM_ARRAY 16 + +struct rack_pcm_stats { + uint32_t sseq; + uint32_t eseq; + uint64_t ack_time; +}; + + struct rack_control { /* Second cache line 0x40 from tcp_rack */ struct tailq_hash *tqh; /* Tree of all segments Lock(a) */ @@ -423,20 +454,14 @@ struct rack_control { uint16_t rack_per_of_gp_rec; /* 100 = 100%, so from 65536 = 655 x bw, 0=off */ uint16_t rack_per_of_gp_probertt; /* 100 = 100%, so from 65536 = 655 x bw, 0=off */ uint32_t rc_high_rwnd; - uint32_t ack_count; - uint32_t sack_count; - uint32_t sack_noextra_move; - uint32_t sack_moved_extra; struct rack_rtt_sample rack_rs; const struct tcp_hwrate_limit_table *crte; uint32_t rc_agg_early; uint32_t rc_agg_delayed; uint32_t rc_tlp_rxt_last_time; - uint32_t rc_saved_cwnd; uint64_t rc_gp_output_ts; /* chg*/ uint64_t rc_gp_cumack_ts; /* chg*/ struct timeval act_rcv_time; - struct timeval rc_last_time_decay; /* SAD time decay happened here */ uint64_t gp_bw; uint64_t init_rate; #ifdef NETFLIX_SHARED_CWND @@ -452,19 +477,29 @@ struct rack_control { struct tcp_sendfile_track *rc_last_sft; uint32_t lt_seq; /* Seq at start of lt_bw gauge */ int32_t rc_rtt_diff; /* Timely style rtt diff of our gp_srtt */ - uint64_t last_sndbytes; - uint64_t last_snd_rxt_bytes; - uint64_t rxt_threshold; uint64_t last_tmit_time_acked; /* Holds the last cumack point's last send time */ - uint32_t last_rnd_rxt_clamped; - uint32_t num_of_clamps_applied; - uint32_t clamp_options; - uint32_t max_clamps; + /* Recovery stats */ + uint64_t last_sendtime; + + uint64_t last_gpest; + uint64_t last_tm_mark; /* Last tm mark used */ + uint64_t fillcw_cap; /* B/W cap on fill cw */ + struct rack_pcm_info pcm_i; + struct rack_pcm_stats *pcm_s; + uint32_t gp_gain_req; /* Percent off gp gain req */ + uint32_t last_rnd_of_gp_rise; + uint32_t gp_rnd_thresh; + uint32_t ss_hi_fs; + uint32_t gate_to_fs; + uint32_t pcm_max_seg; + uint32_t last_pcm_round; + uint32_t pcm_idle_rounds; uint32_t rc_gp_srtt; /* Current GP srtt */ uint32_t rc_prev_gp_srtt; /* Previous RTT */ uint32_t rc_entry_gp_rtt; /* Entry to PRTT gp-rtt */ uint32_t rc_loss_at_start; /* At measurement window where was our lost value */ + uint32_t rc_considered_lost; /* Count in recovery of non-retransmitted bytes considered lost */ uint32_t dsack_round_end; /* In a round of seeing a DSACK */ uint32_t current_round; /* Starting at zero */ @@ -491,22 +526,23 @@ struct rack_control { uint32_t rc_snd_max_at_rto; /* For non-sack when the RTO occurred what was snd-max */ uint32_t rc_out_at_rto; int32_t rc_scw_index; + uint32_t max_reduction; + uint32_t side_chan_dis_mask; /* Bit mask of socket opt's disabled */ uint32_t rc_tlp_threshold; /* Socket option value Lock(a) */ uint32_t rc_last_timeout_snduna; uint32_t last_tlp_acked_start; uint32_t last_tlp_acked_end; - uint32_t challenge_ack_ts; - uint32_t challenge_ack_cnt; uint32_t rc_min_to; /* Socket option value Lock(a) */ uint32_t rc_pkt_delay; /* Socket option value Lock(a) */ uint32_t persist_lost_ends; - uint32_t ack_during_sd; - uint32_t input_pkt; - uint32_t saved_input_pkt; - uint32_t saved_rxt_clamp_val; /* The encoded value we used to setup clamping */ - struct newreno rc_saved_beta; /* - * For newreno cc: - * rc_saved_cc are the values we have had + uint32_t cleared_app_ack_seq; + uint32_t last_rcv_tstmp_for_rtt; + uint32_t last_time_of_arm_rcv; + uint32_t rto_ssthresh; + uint32_t rc_saved_beta; + uint32_t rc_saved_beta_ecn; /* + * For newreno cc: rc_saved_beta and + * rc_saved_beta_ecn are the values we have had * set by the user, if pacing is not happening * (i.e. its early and we have not turned on yet * or it was turned off). The minute pacing @@ -516,10 +552,12 @@ struct rack_control { * we also set the flag (if ecn_beta is set) to make * new_reno do less of a backoff for ecn (think abe). */ + uint16_t rc_cnt_of_retran[RETRAN_CNT_SIZE]; uint16_t rc_early_recovery_segs; /* Socket option value Lock(a) */ uint16_t rc_reorder_shift; /* Socket option value Lock(a) */ uint8_t rack_per_upper_bound_ss; uint8_t rack_per_upper_bound_ca; + uint8_t cleared_app_ack; uint8_t dsack_persist; uint8_t rc_no_push_at_mrtt; /* No push when we exceed max rtt */ uint8_t num_measurements; /* Number of measurements (up to 0xff, we freeze at 0xff) */ @@ -528,37 +566,15 @@ struct rack_control { uint8_t rc_tlp_cwnd_reduce; /* Socket option value Lock(a) */ uint8_t rc_prr_sendalot;/* Socket option value Lock(a) */ uint8_t rc_rate_sample_method; - uint8_t rc_dgp_bl_agg; /* Buffer Level aggression during DGP */ - uint8_t full_dgp_in_rec; /* Flag to say if we do full DGP in recovery */ uint8_t client_suggested_maxseg; /* Not sure what to do with this yet */ - uint8_t pacing_discount_amm; /* - * This is a multipler to the base discount that - * can be used to increase the discount. - */ - uint8_t already_had_a_excess; + uint8_t use_gp_not_last; + uint8_t pacing_method; /* If pace_always, what type of pacing */ }; #endif -/* DGP with no buffer level mitigations */ -#define DGP_LEVEL0 0 - -/* - * DGP with buffer level mitigation where BL:4 caps fillcw and BL:5 - * turns off fillcw. - */ -#define DGP_LEVEL1 1 - -/* - * DGP with buffer level mitigation where BL:3 caps fillcw and BL:4 turns off fillcw - * and BL:5 reduces by 10% - */ -#define DGP_LEVEL2 2 - -/* - * DGP with buffer level mitigation where BL:2 caps fillcw and BL:3 turns off - * fillcw BL:4 reduces by 10% and BL:5 reduces by 20% - */ -#define DGP_LEVEL3 3 +#define RACK_PACING_NONE 0x00 +#define RACK_DGP_PACING 0x01 +#define RACK_REG_PACING 0x02 /* Hybrid pacing log defines */ #define HYBRID_LOG_NO_ROOM 0 /* No room for the clients request */ @@ -579,7 +595,6 @@ struct rack_control { #define HYBRID_LOG_SENT_LOST 15 /* A closing sent/lost report */ #define RACK_TIMELY_CNT_BOOST 5 /* At 5th increase boost */ -#define RACK_MINRTT_FILTER_TIM 10 /* Seconds */ #define RACK_HYSTART_OFF 0 #define RACK_HYSTART_ON 1 /* hystart++ on */ @@ -590,19 +605,20 @@ struct rack_control { */ #define MAX_USER_SET_SEG 0x3f /* The max we can set is 63 which is probably too many */ +#define RACK_FREE_CNT_MAX 0x2f /* Max our counter can do */ #ifdef _KERNEL struct tcp_rack { /* First cache line 0x00 */ - TAILQ_ENTRY(tcp_rack) r_hpts; /* hptsi queue next Lock(b) */ int32_t(*r_substate) (struct mbuf *, struct tcphdr *, struct socket *, struct tcpcb *, struct tcpopt *, int32_t, int32_t, uint32_t, int, int, uint8_t); /* Lock(a) */ struct tcpcb *rc_tp; /* The tcpcb Lock(a) */ struct inpcb *rc_inp; /* The inpcb Lock(a) */ - uint8_t rc_free_cnt; /* Number of free entries on the rc_free list - * Lock(a) */ + uint8_t rc_free_cnt : 6, + rc_skip_timely : 1, + pcm_enabled : 1; /* Is PCM enabled */ uint8_t client_bufferlvl : 3, /* Expected range [0,5]: 0=unset, 1=low/empty */ rack_deferred_inited : 1, /* ******************************************************************** */ @@ -612,11 +628,11 @@ struct tcp_rack { shape_rxt_to_pacing_min : 1, /* ******************************************************************** */ rc_ack_required: 1, - r_pacing_discount : 1; + r_use_hpts_min : 1; uint8_t no_prr_addback : 1, gp_ready : 1, defer_options: 1, - excess_rxt_on: 1, /* Are actions on for excess retransmissions? */ + dis_lt_bw : 1, rc_ack_can_sendout_data: 1, /* * If set it will override pacing restrictions on not sending * data when the pacing timer is running. I.e. you set this @@ -659,7 +675,7 @@ struct tcp_rack { r_rack_hw_rate_caps: 1, r_up_only: 1, r_via_fill_cw : 1, - r_fill_less_agg : 1; + r_rcvpath_rtt_up : 1; uint8_t rc_user_set_max_segs : 7, /* Socket option value Lock(a) */ rc_fillcw_apply_discount; @@ -673,7 +689,7 @@ struct tcp_rack { rc_highly_buffered: 1, /* The path is highly buffered */ rc_dragged_bottom: 1, rc_pace_dnd : 1, /* The pace do not disturb bit */ - rc_avali2 : 1, + rc_initial_ss_comp : 1, rc_gp_filled : 1, rc_hw_nobuf : 1; uint8_t r_state : 4, /* Current rack state Lock(a) */ @@ -696,8 +712,8 @@ struct tcp_rack { uint8_t app_limited_needs_set : 1, use_fixed_rate : 1, rc_has_collapsed : 1, - r_cwnd_was_clamped : 1, - r_clamped_gets_lower : 1, + use_lesser_lt_bw : 1, + cspr_is_fcc : 1, rack_hdrw_pacing : 1, /* We are doing Hardware pacing */ rack_hdw_pace_ena : 1, /* Is hardware pacing enabled? */ rack_attempt_hdwr_pace : 1; /* Did we attempt hdwr pacing (if allowed) */ @@ -712,8 +728,7 @@ struct tcp_rack { set_pacing_done_a_iw : 1, use_rack_rr : 1, alloc_limit_reported : 1, - sack_attack_disable : 1, - do_detection : 1, + rack_avail : 2, rc_force_max_seg : 1; uint8_t r_early : 1, r_late : 1, @@ -722,7 +737,11 @@ struct tcp_rack { r_persist_lt_bw_off : 1, r_collapse_point_valid : 1, dgp_on : 1; - uint16_t rc_init_win : 8, + uint16_t rto_from_rec: 1, + avail_bit: 4, + pcm_in_progress: 1, + pcm_needed: 1, + rc_sendvars_notset : 1, /* Inside rack_init send variables (snd_max/una etc) were not set */ rc_gp_rtt_set : 1, rc_gp_dyn_mul : 1, rc_gp_saw_rec : 1, @@ -735,5 +754,9 @@ struct tcp_rack { struct rack_control r_ctl; } __aligned(CACHE_LINE_SIZE); + +void rack_update_pcm_ack(struct tcp_rack *rack, int was_cumack, + uint32_t ss, uint32_t es); + #endif #endif \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/netinet/tcp_syncache.h b/lib/libc/include/generic-freebsd/netinet/tcp_syncache.h index 43984cebe6b4..d583416bb74d 100644 --- a/lib/libc/include/generic-freebsd/netinet/tcp_syncache.h +++ b/lib/libc/include/generic-freebsd/netinet/tcp_syncache.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)tcp_var.h 8.4 (Berkeley) 5/24/95 */ #ifndef _NETINET_TCP_SYNCACHE_H_ @@ -47,12 +45,11 @@ struct socket * syncache_add(struct in_conninfo *, struct tcpopt *, void *, void *, uint8_t, uint16_t); void syncache_chkrst(struct in_conninfo *, struct tcphdr *, struct mbuf *, uint16_t); -void syncache_badack(struct in_conninfo *, uint16_t); int syncache_pcblist(struct sysctl_req *); struct syncache { TAILQ_ENTRY(syncache) sc_hash; - struct in_conninfo sc_inc; /* addresses */ + struct in_conninfo sc_inc; /* addresses */ int sc_rxttime; /* retransmit time */ u_int16_t sc_rxmits; /* retransmit counter */ u_int16_t sc_port; /* remote UDP encaps port */ @@ -61,7 +58,7 @@ struct syncache { u_int32_t sc_flowlabel; /* IPv6 flowlabel */ tcp_seq sc_irs; /* seq from peer */ tcp_seq sc_iss; /* our ISS */ - struct mbuf *sc_ipopts; /* source route */ + struct mbuf *sc_ipopts; /* source route */ u_int16_t sc_peer_mss; /* peer's MSS */ u_int16_t sc_wnd; /* advertised window */ u_int8_t sc_ip_ttl; /* TTL / Hop Limit */ @@ -69,7 +66,9 @@ struct syncache { u_int8_t sc_requested_s_scale:4, sc_requested_r_scale:4; u_int16_t sc_flags; -#if defined(TCP_OFFLOAD) || !defined(TCP_OFFLOAD_DISABLE) + u_int32_t sc_challenge_ack_cnt; /* chall. ACKs sent in epoch */ + sbintime_t sc_challenge_ack_end; /* End of chall. ack epoch */ +#if defined(TCP_OFFLOAD) struct toedev *sc_tod; /* entry added by this TOE */ void *sc_todctx; /* TOE driver context */ #endif @@ -129,7 +128,9 @@ struct tcp_syncache { u_int cache_limit; u_int rexmt_limit; uint32_t hash_secret; +#ifdef VIMAGE struct vnet *vnet; +#endif struct syncookie_secret secret; struct mtx pause_mtx; struct callout pause_co; diff --git a/lib/libc/include/generic-freebsd/netinet/tcp_timer.h b/lib/libc/include/generic-freebsd/netinet/tcp_timer.h index 1d0d3e16176b..95ea610a37ef 100644 --- a/lib/libc/include/generic-freebsd/netinet/tcp_timer.h +++ b/lib/libc/include/generic-freebsd/netinet/tcp_timer.h @@ -27,13 +27,13 @@ * 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. - * - * @(#)tcp_timer.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NETINET_TCP_TIMER_H_ #define _NETINET_TCP_TIMER_H_ +#ifdef _KERNEL + /* * The TCPT_REXMT timer is used to force retransmissions. * The TCP has the TCPT_REXMT timer set whenever segments @@ -73,21 +73,22 @@ /* * Time constants. */ -#define TCPTV_MSL ( 30*hz) /* max seg lifetime (hah!) */ +#define TCPTV_MSL MSEC_2_TICKS(30000) /* max seg lifetime (hah!) */ +#define TCPTV_MSL_LOCAL MSEC_2_TICKS(10) /* max seg lifetime for local comm */ #define TCPTV_SRTTBASE 0 /* base roundtrip time; if 0, no idea yet */ -#define TCPTV_RTOBASE ( 1*hz) /* assumed RTO if no info */ +#define TCPTV_RTOBASE MSEC_2_TICKS(1000) /* assumed RTO if no info */ -#define TCPTV_PERSMIN ( 5*hz) /* minimum persist interval */ -#define TCPTV_PERSMAX ( 60*hz) /* maximum persist interval */ +#define TCPTV_PERSMIN MSEC_2_TICKS(5000) /* minimum persist interval */ +#define TCPTV_PERSMAX MSEC_2_TICKS(60000) /* maximum persist interval */ -#define TCPTV_KEEP_INIT ( 75*hz) /* initial connect keepalive */ -#define TCPTV_KEEP_IDLE (120*60*hz) /* dflt time before probing */ -#define TCPTV_KEEPINTVL ( 75*hz) /* default probe interval */ +#define TCPTV_KEEP_INIT MSEC_2_TICKS(75000) /* initial connect keepalive */ +#define TCPTV_KEEP_IDLE MSEC_2_TICKS(120*60*1000) /* dflt time before probing */ +#define TCPTV_KEEPINTVL MSEC_2_TICKS(75000) /* default probe interval */ #define TCPTV_KEEPCNT 8 /* max probes before drop */ #define TCPTV_MAXUNACKTIME 0 /* max time without making progress */ -#define TCPTV_FINWAIT2_TIMEOUT (60*hz) /* FIN_WAIT_2 timeout if no receiver */ +#define TCPTV_FINWAIT2_TIMEOUT MSEC_2_TICKS(60000) /* FIN_WAIT_2 timeout if no receiver */ /* * Minimum retransmit timer is 3 ticks, for algorithmic stability. @@ -109,15 +110,13 @@ * The prior minimum of 1*hz (1 second) badly breaks throughput on any * networks faster then a modem that has minor (e.g. 1%) packet loss. */ -#define TCPTV_MIN ( hz/33 ) /* minimum allowable value */ -#define TCPTV_CPU_VAR ( hz/5 ) /* cpu variance allowed (200ms) */ -#define TCPTV_REXMTMAX ( 64*hz) /* max allowable REXMT value */ - -#define TCPTV_TWTRUNC 8 /* RTO factor to truncate TW */ +#define TCPTV_MIN MSEC_2_TICKS(30) /* minimum allowable value */ +#define TCPTV_CPU_VAR MSEC_2_TICKS(200) /* cpu variance allowed (200ms) */ +#define TCPTV_REXMTMAX MSEC_2_TICKS(64000) /* max allowable REXMT value */ #define TCP_MAXRXTSHIFT 12 /* maximum retransmits */ -#define TCPTV_DELACK ( hz/25 ) /* 40ms timeout */ +#define TCPTV_DELACK MSEC_2_TICKS(40) /* 40ms timeout */ /* * If we exceed this number of retransmits for a single segment, we'll consider @@ -137,8 +136,6 @@ (tv) = (tvmax); \ } while(0) -#ifdef _KERNEL - #define TP_KEEPINIT(tp) ((tp)->t_keepinit ? (tp)->t_keepinit : tcp_keepinit) #define TP_KEEPIDLE(tp) ((tp)->t_keepidle ? (tp)->t_keepidle : tcp_keepidle) #define TP_KEEPINTVL(tp) ((tp)->t_keepintvl ? (tp)->t_keepintvl : tcp_keepintvl) @@ -167,6 +164,7 @@ extern int tcp_maxunacktime; /* max time without making progress */ extern int tcp_maxpersistidle; extern int tcp_rexmit_initial; extern int tcp_rexmit_min; +extern int tcp_rexmit_max; extern int tcp_rexmit_slop; extern int tcp_ttl; /* time to live for TCP segs */ extern int tcp_backoff[]; @@ -186,6 +184,8 @@ VNET_DECLARE(int, tcp_v6pmtud_blackhole_mss); #define V_tcp_v6pmtud_blackhole_mss VNET(tcp_v6pmtud_blackhole_mss) VNET_DECLARE(int, tcp_msl); #define V_tcp_msl VNET(tcp_msl) +VNET_DECLARE(int, tcp_msl_local); +#define V_tcp_msl_local VNET(tcp_msl_local) #endif /* _KERNEL */ diff --git a/lib/libc/include/generic-freebsd/netinet/tcp_var.h b/lib/libc/include/generic-freebsd/netinet/tcp_var.h index 458235fcfb39..818e23205ce5 100644 --- a/lib/libc/include/generic-freebsd/netinet/tcp_var.h +++ b/lib/libc/include/generic-freebsd/netinet/tcp_var.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)tcp_var.h 8.4 (Berkeley) 5/24/95 */ #ifndef _NETINET_TCP_VAR_H_ @@ -130,6 +128,8 @@ struct sackhint { uint32_t recover_fs; /* Flight Size at the start of Loss recovery */ uint32_t prr_delivered; /* Total bytes delivered using PRR */ uint32_t prr_out; /* Bytes sent during IN_RECOVERY */ + int32_t hole_bytes; /* current number of bytes in scoreboard holes */ + int32_t lost_bytes; /* number of rfc6675 IsLost() bytes */ }; #define SEGQ_EMPTY(tp) TAILQ_EMPTY(&(tp)->t_segq) @@ -141,7 +141,8 @@ STAILQ_HEAD(tcp_log_stailq, tcp_log_mem); #define TCP_TRK_TRACK_FLG_OPEN 0x02 /* End is not valid (open range request) */ #define TCP_TRK_TRACK_FLG_SEQV 0x04 /* We had a sendfile that touched it */ #define TCP_TRK_TRACK_FLG_COMP 0x08 /* Sendfile as placed the last bits (range req only) */ -#define TCP_TRK_TRACK_FLG_FSND 0x10 /* First send has been done into the seq space */ +#define TCP_TRK_TRACK_FLG_FSND 0x10 /* First send has been done into the seq space */ +#define TCP_TRK_TRACK_FLG_LSND 0x20 /* We were able to set the Last Sent */ #define MAX_TCP_TRK_REQ 5 /* Max we will have at once */ struct tcp_sendfile_track { @@ -154,11 +155,14 @@ struct tcp_sendfile_track { uint64_t cspr; /* Client suggested pace rate */ uint64_t sent_at_fs; /* What was t_sndbytes as we begun sending */ uint64_t rxt_at_fs; /* What was t_snd_rxt_bytes as we begun sending */ + uint64_t sent_at_ls; /* Sent value at the last send */ + uint64_t rxt_at_ls; /* Retransmit value at the last send */ tcp_seq start_seq; /* First TCP Seq assigned */ tcp_seq end_seq; /* If range req last seq */ uint32_t flags; /* Type of request open etc */ uint32_t sbcc_at_s; /* When we allocate what is the sb_cc */ uint32_t hint_maxseg; /* Client hinted maxseg */ + uint32_t playout_ms; /* Client playout ms */ uint32_t hybrid_flags; /* Hybrid flags on this request */ }; @@ -178,7 +182,7 @@ struct tcp_sendfile_track { * snd_una). When the response comes back indicating * that there was data (return value 1), then the caller * can build a sendmap entry based on the range and the - * times. The next query would then be done at the + * times. The next query would then be done at the * newly created sendmap_end. Repeated until sendmap_end == snd_max. * * Flags in sendmap_flags are defined below as well. @@ -193,7 +197,7 @@ struct tcp_sendfile_track { * The rack_times are a misc collection of information that * the old stack might possibly fill in. Of course its possible * that an old stack may not have a piece of information. If so - * then setting that value to zero is advised. Setting any + * then setting that value to zero is advised. Setting any * timestamp passed should only place a zero in it when it * is unfilled. This may mean that a time is off by a micro-second * but this is ok in the grand scheme of things. @@ -201,13 +205,13 @@ struct tcp_sendfile_track { * When switching stacks it is desireable to get as much information * from the old stack to the new stack as possible. Though not always * will the stack be compatible in the types of information. The - * init() function needs to take care when it begins changing + * init() function needs to take care when it begins changing * things such as inp_flags2 and the timer units to position these * changes at a point where it is unlikely they will fail after * making such changes. A stack optionally can have an "undo" - * function + * function * - * To transfer information to the old stack from the new in + * To transfer information to the old stack from the new in * respect to LRO and the inp_flags2, the new stack should set * the inp_flags2 to what it supports. The old stack in its * fini() function should call the tcp_handle_orphaned_packets() @@ -448,7 +452,6 @@ struct tcpcb { tcp_seq gput_seq; /* Outbound measurement seq */ tcp_seq gput_ack; /* Inbound measurement ack */ int32_t t_stats_gput_prev; /* XXXLAS: Prev gput measurement */ - uint32_t t_maxpeakrate; /* max peak rate set by user, bytes/s */ uint32_t t_sndtlppack; /* tail loss probe packets sent */ uint64_t t_sndtlpbyte; /* total tail loss probe bytes sent */ uint64_t t_sndbytes; /* total bytes sent */ @@ -496,10 +499,6 @@ struct tcpcb { uint64_t tcp_cnt_counters[TCP_NUM_CNT_COUNTERS]; uint64_t tcp_proc_time[TCP_NUM_CNT_COUNTERS]; #endif -#ifdef TCPPCAP - struct mbufq t_inpkts; /* List of saved input packets. */ - struct mbufq t_outpkts; /* List of saved output packets. */ -#endif }; #endif /* _KERNEL || _WANT_TCPCB */ @@ -529,31 +528,12 @@ typedef enum { /* Minimum map entries limit value, if set */ #define TCP_MIN_MAP_ENTRIES_LIMIT 128 -/* - * TODO: We yet need to brave plowing in - * to tcp_input() and the pru_usrreq() block. - * Right now these go to the old standards which - * are somewhat ok, but in the long term may - * need to be changed. If we do tackle tcp_input() - * then we need to get rid of the tcp_do_segment() - * function below. - */ /* Flags for tcp functions */ #define TCP_FUNC_BEING_REMOVED 0x01 /* Can no longer be referenced */ #define TCP_FUNC_OUTPUT_CANDROP 0x02 /* tfb_tcp_output may ask tcp_drop */ #define TCP_FUNC_DEFAULT_OK 0x04 /* Can be used as default */ /** - * If defining the optional tcp_timers, in the - * tfb_tcp_timer_stop call you must use the - * callout_async_drain() function with the - * tcp_timer_discard callback. You should check - * the return of callout_async_drain() and if 0 - * increment tt_draincnt. Since the timer sub-system - * does not know your callbacks you must provide a - * stop_all function that loops through and calls - * tcp_timer_stop() with each of your defined timers. - * * tfb_tcp_handoff_ok is a mandatory function allowing * to query a stack, if it can take over a tcpcb. * You return 0 to say you can take over and run your stack, @@ -564,13 +544,13 @@ typedef enum { * do is: * a) Make sure that the inp_flags2 is setup correctly * for LRO. There are two flags that the previous - * stack may have set INP_MBUF_ACKCMP and + * stack may have set INP_MBUF_ACKCMP and * INP_SUPPORTS_MBUFQ. If the new stack does not * support these it *should* clear the flags. * b) Make sure that the timers are in the proper * granularity that the stack wants. The stack * should check the t_tmr_granularity field. Currently - * there are two values that it may hold + * there are two values that it may hold * TCP_TMR_GRANULARITY_TICKS and TCP_TMR_GRANULARITY_USEC. * Use the functions tcp_timer_convert(tp, granularity); * to move the timers to the correct format for your stack. @@ -578,14 +558,14 @@ typedef enum { * The new stack may also optionally query the tfb_chg_query * function if the old stack has one. The new stack may ask * for one of three entries and can also state to the old - * stack its support for the INP_MBUF_ACKCMP and + * stack its support for the INP_MBUF_ACKCMP and * INP_SUPPORTS_MBUFQ. This is important since if there are * queued ack's without that statement the old stack will * be forced to discard the queued acks. The requests that * can be made for information by the new stacks are: * * Note also that the tfb_tcp_fb_init() when called can - * determine if a query is needed by looking at the + * determine if a query is needed by looking at the * value passed in the ptr. The ptr is designed to be * set in with any allocated memory, but the address * of the condtion (ptr == &tp->t_fb_ptr) will be @@ -593,17 +573,17 @@ typedef enum { * setup of a tcb (which means no query would be needed). * If, however, the value is not t_fb_ptr, then the caller * is in the middle of a stack switch and is the new stack. - * A query would be appropriate (if the new stack support + * A query would be appropriate (if the new stack support * the query mechanism). * * TCP_QUERY_SENDMAP - Query of outstanding data. * TCP_QUERY_TIMERS_UP - Query about running timers. - * TCP_SUPPORTED_LRO - Declaration in req_param of - * the inp_flags2 supported by + * TCP_SUPPORTED_LRO - Declaration in req_param of + * the inp_flags2 supported by * the new stack. * TCP_QUERY_RACK_TIMES - Enquire about various timestamps * and states the old stack may be in. - * + * * tfb_tcp_fb_fini is changed to add a flag to tell * the old stack if the tcb is being destroyed or * not. A one in the flag means the TCB is being @@ -639,6 +619,8 @@ struct tcp_function_block { void (*tfb_switch_failed)(struct tcpcb *); bool (*tfb_early_wake_check)(struct tcpcb *); int (*tfb_compute_pipe)(struct tcpcb *tp); + int (*tfb_stack_info)(struct tcpcb *tp, struct stack_specific_info *); + void (*tfb_inherit)(struct tcpcb *tp, struct inpcb *h_inp); volatile uint32_t tfb_refcnt; uint32_t tfb_flags; uint8_t tfb_id; @@ -807,7 +789,7 @@ tcp_packets_this_ack(struct tcpcb *tp, tcp_seq ack) #define TF_TSO 0x01000000 /* TSO enabled on this connection */ #define TF_TOE 0x02000000 /* this connection is offloaded */ #define TF_CLOSED 0x04000000 /* close(2) called on socket */ -#define TF_UNUSED1 0x08000000 /* unused */ +#define TF_SENTSYN 0x08000000 /* At least one syn has been sent */ #define TF_LRD 0x10000000 /* Lost Retransmission Detection */ #define TF_CONGRECOVERY 0x20000000 /* congestion recovery mode */ #define TF_WASCRECOVERY 0x40000000 /* was in congestion recovery */ @@ -825,14 +807,6 @@ tcp_packets_this_ack(struct tcpcb *tp, tcp_seq ack) #define ENTER_RECOVERY(t_flags) t_flags |= (TF_CONGRECOVERY | TF_FASTRECOVERY) #define EXIT_RECOVERY(t_flags) t_flags &= ~(TF_CONGRECOVERY | TF_FASTRECOVERY) -#if defined(_KERNEL) -#if !defined(TCP_RFC7413) -#define IS_FASTOPEN(t_flags) (false) -#else -#define IS_FASTOPEN(t_flags) (t_flags & TF_FASTOPEN) -#endif -#endif - #define BYTES_THIS_ACK(tp, th) (th->th_ack - tp->snd_una) /* @@ -864,6 +838,8 @@ tcp_packets_this_ack(struct tcpcb *tp, tcp_seq ack) #define TF2_MBUF_QUEUE_READY 0x00020000 /* Inputs can be queued */ #define TF2_DONT_SACK_QUEUE 0x00040000 /* Don't wake on sack */ #define TF2_CANNOT_DO_ECN 0x00080000 /* The stack does not do ECN */ +#define TF2_PROC_SACK_PROHIBIT 0x00100000 /* Due to small MSS size do not process sack's */ +#define TF2_IPSEC_TSO 0x00200000 /* IPSEC + TSO supported */ #define TF2_NO_ISS_CHECK 0x00400000 /* Don't check SEG.ACK against ISS */ /* @@ -902,24 +878,13 @@ struct tcpopt { #define TO_SYN 0x01 /* parse SYN-only options */ struct hc_metrics_lite { /* must stay in sync with hc_metrics */ - uint32_t rmx_mtu; /* MTU for this path */ - uint32_t rmx_ssthresh; /* outbound gateway buffer limit */ - uint32_t rmx_rtt; /* estimated round trip time */ - uint32_t rmx_rttvar; /* estimated rtt variance */ - uint32_t rmx_cwnd; /* congestion window */ - uint32_t rmx_sendpipe; /* outbound delay-bandwidth product */ - uint32_t rmx_recvpipe; /* inbound delay-bandwidth product */ -}; - -/* - * Used by tcp_maxmtu() to communicate interface specific features - * and limits at the time of connection setup. - */ -struct tcp_ifcap { - int ifcap; - u_int tsomax; - u_int tsomaxsegcount; - u_int tsomaxsegsize; + uint32_t hc_mtu; /* MTU for this path */ + uint32_t hc_ssthresh; /* outbound gateway buffer limit */ + uint32_t hc_rtt; /* estimated round trip time */ + uint32_t hc_rttvar; /* estimated rtt variance */ + uint32_t hc_cwnd; /* congestion window */ + uint32_t hc_sendpipe; /* outbound delay-bandwidth product */ + uint32_t hc_recvpipe; /* inbound delay-bandwidth product */ }; #ifndef _NETINET_IN_PCB_H_ @@ -962,9 +927,12 @@ struct in_conninfo; + (tp)->t_rttvar) >> TCP_DELTA_SHIFT) /* - * TCP statistics. - * Many of these should be kept per connection, - * but that's inconvenient at the moment. + * Global (per-VNET) TCP statistics. The below structure represents what we + * export to the userland, but in the kernel we have an array of counter_u64_t + * with as many elements as there are members in the structure. The counters + * shall be increased by TCPSTAT_INC() or KMOD_TCPSTAT_INC(). Adding a new + * counter also requires adding corresponding SDT probes into in_kdtrace.h and + * into in_kdtrace.c. */ struct tcpstat { uint64_t tcps_connattempt; /* connections initiated */ @@ -1050,6 +1018,8 @@ struct tcpstat { uint64_t tcps_sc_zonefail; /* zalloc() failed */ uint64_t tcps_sc_sendcookie; /* SYN cookie sent */ uint64_t tcps_sc_recvcookie; /* SYN cookie received */ + uint64_t tcps_sc_spurcookie; /* SYN cookie spurious, rejected */ + uint64_t tcps_sc_failcookie; /* SYN cookie failed, rejected */ uint64_t tcps_hc_added; /* entry added to hostcache */ uint64_t tcps_hc_bucketoverflow;/* hostcache per bucket limit hit */ @@ -1059,6 +1029,7 @@ struct tcpstat { /* SACK related stats */ uint64_t tcps_sack_recovery_episode; /* SACK recovery episodes */ uint64_t tcps_sack_rexmits; /* SACK rexmit segments */ + uint64_t tcps_sack_rexmits_tso; /* SACK rexmit TSO chunks */ uint64_t tcps_sack_rexmit_bytes; /* SACK rexmit bytes */ uint64_t tcps_sack_rcv_blocks; /* SACK blocks (options) received */ uint64_t tcps_sack_send_blocks; /* SACK blocks (options) sent */ @@ -1120,31 +1091,39 @@ struct tcpstat { uint64_t tcps_rcvghostack; /* received ACK for data never sent */ uint64_t tcps_rcvacktooold; /* received ACK for data too long ago */ - uint64_t _pad[2]; /* 2 TBD placeholder for STABLE */ + + uint64_t _pad[1]; /* 1 TBD placeholder for STABLE */ }; #define tcps_rcvmemdrop tcps_rcvreassfull /* compat */ #ifdef _KERNEL -#define TI_UNLOCKED 1 -#define TI_RLOCKED 2 #include +#include VNET_PCPUSTAT_DECLARE(struct tcpstat, tcpstat); /* tcp statistics */ /* * In-kernel consumers can use these accessor macros directly to update * stats. */ -#define TCPSTAT_ADD(name, val) \ - VNET_PCPUSTAT_ADD(struct tcpstat, tcpstat, name, (val)) +#define TCPSTAT_ADD(name, val) \ + do { \ + MIB_SDT_PROBE1(tcp, count, name, (val)); \ + VNET_PCPUSTAT_ADD(struct tcpstat, tcpstat, name, (val)); \ + } while (0) #define TCPSTAT_INC(name) TCPSTAT_ADD(name, 1) /* * Kernel module consumers must use this accessor macro. */ void kmod_tcpstat_add(int statnum, int val); -#define KMOD_TCPSTAT_ADD(name, val) \ - kmod_tcpstat_add(offsetof(struct tcpstat, name) / sizeof(uint64_t), val) +#define KMOD_TCPSTAT_ADD(name, val) \ + do { \ + MIB_SDT_PROBE1(tcp, count, name, (val)); \ + kmod_tcpstat_add(offsetof(struct tcpstat, name) / \ + sizeof(uint64_t), \ + val); \ + } while (0) #define KMOD_TCPSTAT_INC(name) KMOD_TCPSTAT_ADD(name, 1) /* @@ -1260,6 +1239,9 @@ struct tcp_function_info { #define TCPCTL_SACK 14 /* Selective Acknowledgement,rfc 2018 */ #define TCPCTL_DROP 15 /* drop tcp connection */ #define TCPCTL_STATES 16 /* connection counts by TCP state */ +#define TCPCTL_KTLSLIST 17 /* connections with active ktls + session */ +#define TCPCTL_KTLSLIST_WKEYS 18 /* KTLSLIST with key data exported */ #ifdef _KERNEL #ifdef SYSCTL_DECL @@ -1283,6 +1265,7 @@ VNET_DECLARE(uint32_t, tcp_ack_war_time_window); VNET_DECLARE(int, tcp_autorcvbuf_max); VNET_DECLARE(int, tcp_autosndbuf_inc); VNET_DECLARE(int, tcp_autosndbuf_max); +VNET_DECLARE(int, tcp_bind_all_fibs); VNET_DECLARE(int, tcp_delack_enabled); VNET_DECLARE(int, tcp_do_autorcvbuf); VNET_DECLARE(int, tcp_do_autosndbuf); @@ -1317,6 +1300,7 @@ VNET_DECLARE(int, tcp_retries); VNET_DECLARE(int, tcp_sack_globalholes); VNET_DECLARE(int, tcp_sack_globalmaxholes); VNET_DECLARE(int, tcp_sack_maxholes); +VNET_DECLARE(int, tcp_sack_tso); VNET_DECLARE(int, tcp_sc_rst_sock_fail); VNET_DECLARE(int, tcp_sendspace); VNET_DECLARE(int, tcp_udp_tunneling_overhead); @@ -1335,6 +1319,7 @@ VNET_DECLARE(struct inpcbinfo, tcbinfo); #define V_tcp_autorcvbuf_max VNET(tcp_autorcvbuf_max) #define V_tcp_autosndbuf_inc VNET(tcp_autosndbuf_inc) #define V_tcp_autosndbuf_max VNET(tcp_autosndbuf_max) +#define V_tcp_bind_all_fibs VNET(tcp_bind_all_fibs) #define V_tcp_delack_enabled VNET(tcp_delack_enabled) #define V_tcp_do_autorcvbuf VNET(tcp_do_autorcvbuf) #define V_tcp_do_autosndbuf VNET(tcp_do_autosndbuf) @@ -1366,6 +1351,7 @@ VNET_DECLARE(struct inpcbinfo, tcbinfo); #define V_tcp_sack_globalholes VNET(tcp_sack_globalholes) #define V_tcp_sack_globalmaxholes VNET(tcp_sack_globalmaxholes) #define V_tcp_sack_maxholes VNET(tcp_sack_maxholes) +#define V_tcp_sack_tso VNET(tcp_sack_tso) #define V_tcp_sc_rst_sock_fail VNET(tcp_sc_rst_sock_fail) #define V_tcp_sendspace VNET(tcp_sendspace) #define V_tcp_udp_tunneling_overhead VNET(tcp_udp_tunneling_overhead) @@ -1393,8 +1379,7 @@ int tcp_reass(struct tcpcb *, struct tcphdr *, tcp_seq *, int *, void tcp_reass_global_init(void); void tcp_reass_flush(struct tcpcb *); void tcp_dooptions(struct tcpopt *, u_char *, int, int); -void tcp_dropwithreset(struct mbuf *, struct tcphdr *, - struct tcpcb *, int, int); +void tcp_dropwithreset(struct mbuf *, struct tcphdr *, struct tcpcb *, int); void tcp_pulloutofband(struct socket *, struct tcphdr *, struct mbuf *, int); void tcp_xmit_timer(struct tcpcb *, int); @@ -1447,24 +1432,23 @@ extern counter_u64_t tcp_comp_total; extern counter_u64_t tcp_uncomp_total; extern counter_u64_t tcp_bad_csums; -#ifdef TCP_SAD_DETECTION -/* Various SACK attack thresholds */ -extern int32_t tcp_force_detection; -extern int32_t tcp_sad_limit; -extern int32_t tcp_sack_to_ack_thresh; -extern int32_t tcp_sack_to_move_thresh; -extern int32_t tcp_restoral_thresh; -extern int32_t tcp_sad_decay_val; -extern int32_t tcp_sad_pacing_interval; -extern int32_t tcp_sad_low_pps; -extern int32_t tcp_map_minimum; -extern int32_t tcp_attack_on_turns_on_logging; -#endif extern uint32_t tcp_ack_war_time_window; extern uint32_t tcp_ack_war_cnt; +/* + * Used by tcp_maxmtu() to communicate interface specific features + * and limits at the time of connection setup. + */ +struct tcp_ifcap { + int ifcap; + u_int tsomax; + u_int tsomaxsegcount; + u_int tsomaxsegsize; + bool ipsec_tso; +}; uint32_t tcp_maxmtu(struct in_conninfo *, struct tcp_ifcap *); uint32_t tcp_maxmtu6(struct in_conninfo *, struct tcp_ifcap *); + void tcp6_use_min_mtu(struct tcpcb *); u_int tcp_maxseg(const struct tcpcb *); u_int tcp_fixed_maxseg(const struct tcpcb *); @@ -1478,6 +1462,7 @@ int tcp_default_output(struct tcpcb *); void tcp_state_change(struct tcpcb *, int); void tcp_respond(struct tcpcb *, void *, struct tcphdr *, struct mbuf *, tcp_seq, tcp_seq, uint16_t); +bool tcp_challenge_ack_check(sbintime_t *, uint32_t *); void tcp_send_challenge_ack(struct tcpcb *, struct tcphdr *, struct mbuf *); bool tcp_twcheck(struct inpcb *, struct tcpopt *, struct tcphdr *, struct mbuf *, int); @@ -1497,10 +1482,10 @@ void tcp_hc_init(void); #ifdef VIMAGE void tcp_hc_destroy(void); #endif -void tcp_hc_get(struct in_conninfo *, struct hc_metrics_lite *); -uint32_t tcp_hc_getmtu(struct in_conninfo *); -void tcp_hc_updatemtu(struct in_conninfo *, uint32_t); -void tcp_hc_update(struct in_conninfo *, struct hc_metrics_lite *); +void tcp_hc_get(const struct in_conninfo *, struct hc_metrics_lite *); +uint32_t tcp_hc_getmtu(const struct in_conninfo *); +void tcp_hc_updatemtu(const struct in_conninfo *, uint32_t); +void tcp_hc_update(const struct in_conninfo *, struct hc_metrics_lite *); void cc_after_idle(struct tcpcb *tp); extern struct protosw tcp_protosw; /* shared for TOE */ @@ -1513,14 +1498,17 @@ sackstatus_t tcp_sack_doack(struct tcpcb *, struct tcpopt *, tcp_seq); int tcp_dsack_block_exists(struct tcpcb *); void tcp_update_dsack_list(struct tcpcb *, tcp_seq, tcp_seq); -void tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_laststart, tcp_seq rcv_lastend); +void tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_laststart, + tcp_seq rcv_lastend); void tcp_clean_dsack_blocks(struct tcpcb *tp); void tcp_clean_sackreport(struct tcpcb *tp); int tcp_sack_adjust(struct tcpcb *tp); struct sackhole *tcp_sack_output(struct tcpcb *tp, int *sack_bytes_rexmt); -void tcp_do_prr_ack(struct tcpcb *, struct tcphdr *, struct tcpopt *, sackstatus_t); +void tcp_do_prr_ack(struct tcpcb *, struct tcphdr *, struct tcpopt *, + sackstatus_t, u_int *); void tcp_lost_retransmission(struct tcpcb *, struct tcphdr *); -void tcp_sack_partialack(struct tcpcb *, struct tcphdr *); +void tcp_sack_partialack(struct tcpcb *, struct tcphdr *, u_int *); +void tcp_resend_sackholes(struct tcpcb *tp); void tcp_free_sackholes(struct tcpcb *tp); void tcp_sack_lost_retransmission(struct tcpcb *, struct tcphdr *); int tcp_newreno(struct tcpcb *, struct tcphdr *); @@ -1530,6 +1518,8 @@ void tcp_sndbuf_autoscale(struct tcpcb *, struct socket *, uint32_t); int tcp_stats_sample_rollthedice(struct tcpcb *tp, void *seed_bytes, size_t seed_len); int tcp_can_enable_pacing(void); +int tcp_incr_dgp_pacing_cnt(void); +void tcp_dec_dgp_pacing_cnt(void); void tcp_decrement_paced_conn(void); void tcp_change_time_units(struct tcpcb *, int); void tcp_handle_orphaned_packets(struct tcpcb *); @@ -1598,19 +1588,6 @@ tcp_fields_to_net(struct tcphdr *th) th->th_win = htons(th->th_win); th->th_urp = htons(th->th_urp); } - -static inline uint16_t -tcp_get_flags(const struct tcphdr *th) -{ - return (((uint16_t)th->th_x2 << 8) | th->th_flags); -} - -static inline void -tcp_set_flags(struct tcphdr *th, uint16_t flags) -{ - th->th_x2 = (flags >> 8) & 0x0f; - th->th_flags = flags & 0xff; -} #endif /* _KERNEL */ #endif /* _NETINET_TCP_VAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/netinet/tcpip.h b/lib/libc/include/generic-freebsd/netinet/tcpip.h index 118e0cc28119..943d6540dc81 100644 --- a/lib/libc/include/generic-freebsd/netinet/tcpip.h +++ b/lib/libc/include/generic-freebsd/netinet/tcpip.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)tcpip.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NETINET_TCPIP_H_ diff --git a/lib/libc/include/generic-freebsd/netinet/toecore.h b/lib/libc/include/generic-freebsd/netinet/toecore.h index f37983312f1a..7986dc698e04 100644 --- a/lib/libc/include/generic-freebsd/netinet/toecore.h +++ b/lib/libc/include/generic-freebsd/netinet/toecore.h @@ -36,6 +36,7 @@ #include #include +struct tcpcb; struct tcpopt; struct tcphdr; struct in_conninfo; @@ -65,7 +66,7 @@ struct toedev { void (*tod_input)(struct toedev *, struct tcpcb *, struct mbuf *); /* - * This is called by the kernel during pru_rcvd for an offloaded TCP + * This is called by the kernel during pr_rcvd() for an offloaded TCP * connection and provides an opportunity for the TOE driver to manage * its rx window and credits. */ diff --git a/lib/libc/include/generic-freebsd/netinet/udp.h b/lib/libc/include/generic-freebsd/netinet/udp.h index df34acd49736..1b28518c0a91 100644 --- a/lib/libc/include/generic-freebsd/netinet/udp.h +++ b/lib/libc/include/generic-freebsd/netinet/udp.h @@ -28,8 +28,6 @@ * 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. - * - * @(#)udp.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NETINET_UDP_H_ @@ -46,7 +44,7 @@ struct udphdr { u_short uh_dport; /* destination port */ u_short uh_ulen; /* udp length */ u_short uh_sum; /* udp checksum */ -}; +} __packed; /* * User-settable options (used with setsockopt). diff --git a/lib/libc/include/generic-freebsd/netinet/udp_var.h b/lib/libc/include/generic-freebsd/netinet/udp_var.h index d97804a02f1c..87896e78ad8d 100644 --- a/lib/libc/include/generic-freebsd/netinet/udp_var.h +++ b/lib/libc/include/generic-freebsd/netinet/udp_var.h @@ -28,8 +28,6 @@ * 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. - * - * @(#)udp_var.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NETINET_UDP_VAR_H_ @@ -95,6 +93,7 @@ struct udpstat { #ifdef _KERNEL #include #include +#include struct mbuf; typedef bool udp_tun_func_t(struct mbuf *, int, struct inpcb *, @@ -121,7 +120,7 @@ struct udpcb { void *u_tun_ctx; /* Tunneling callback context. */ }; -#define intoudpcb(ip) __containerof((inp), struct udpcb, u_inpcb) +#define intoudpcb(ip) __containerof((ip), struct udpcb, u_inpcb) #define sotoudpcb(so) (intoudpcb(sotoinpcb(so))) VNET_PCPUSTAT_DECLARE(struct udpstat, udpstat); @@ -129,18 +128,26 @@ VNET_PCPUSTAT_DECLARE(struct udpstat, udpstat); * In-kernel consumers can use these accessor macros directly to update * stats. */ -#define UDPSTAT_ADD(name, val) \ - VNET_PCPUSTAT_ADD(struct udpstat, udpstat, name, (val)) -#define UDPSTAT_INC(name) UDPSTAT_ADD(name, 1) +#define UDPSTAT_ADD(name, val) \ + do { \ + MIB_SDT_PROBE1(udp, count, name, (val)); \ + VNET_PCPUSTAT_ADD(struct udpstat, udpstat, name, (val)); \ + } while (0) +#define UDPSTAT_INC(name) UDPSTAT_ADD(name, 1) /* * Kernel module consumers must use this accessor macro. */ void kmod_udpstat_inc(int statnum); -#define KMOD_UDPSTAT_INC(name) \ - kmod_udpstat_inc(offsetof(struct udpstat, name) / sizeof(uint64_t)) +#define KMOD_UDPSTAT_INC(name) \ + do { \ + MIB_SDT_PROBE1(udp, count, name, 1); \ + kmod_udpstat_inc( \ + offsetof(struct udpstat, name) / sizeof(uint64_t)); \ + } while (0) SYSCTL_DECL(_net_inet_udp); +SYSCTL_DECL(_net_inet_udplite); VNET_DECLARE(struct inpcbinfo, udbinfo); VNET_DECLARE(struct inpcbinfo, ulitecbinfo); @@ -149,13 +156,15 @@ VNET_DECLARE(struct inpcbinfo, ulitecbinfo); extern u_long udp_sendspace; extern u_long udp_recvspace; -VNET_DECLARE(int, udp_cksum); +VNET_DECLARE(int, udp_bind_all_fibs); VNET_DECLARE(int, udp_blackhole); VNET_DECLARE(bool, udp_blackhole_local); +VNET_DECLARE(int, udp_cksum); VNET_DECLARE(int, udp_log_in_vain); -#define V_udp_cksum VNET(udp_cksum) +#define V_udp_bind_all_fibs VNET(udp_bind_all_fibs) #define V_udp_blackhole VNET(udp_blackhole) #define V_udp_blackhole_local VNET(udp_blackhole_local) +#define V_udp_cksum VNET(udp_cksum) #define V_udp_log_in_vain VNET(udp_log_in_vain) VNET_DECLARE(int, zero_checksum_port); @@ -170,7 +179,7 @@ udp_get_inpcbinfo(int protocol) int udp_ctloutput(struct socket *, struct sockopt *); void udplite_input(struct mbuf *, int); struct inpcb *udp_notify(struct inpcb *inp, int errno); -int udp_shutdown(struct socket *so); +int udp_shutdown(struct socket *, enum shutdown_how); int udp_set_kernel_tunneling(struct socket *so, udp_tun_func_t f, udp_tun_icmp_t i, void *ctx); diff --git a/lib/libc/include/generic-freebsd/netinet6/in6.h b/lib/libc/include/generic-freebsd/netinet6/in6.h index 3a4c4a9606c6..81e5c27aeefc 100644 --- a/lib/libc/include/generic-freebsd/netinet6/in6.h +++ b/lib/libc/include/generic-freebsd/netinet6/in6.h @@ -58,8 +58,6 @@ * 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. - * - * @(#)in.h 8.3 (Berkeley) 1/3/94 */ #ifndef __KAME_NETINET_IN_H_INCLUDED_ @@ -360,11 +358,11 @@ extern const struct in6_addr in6addr_linklocal_allv2routers; #define IFA6_IS_DEPRECATED(a) \ ((a)->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME && \ - (u_int32_t)((time_uptime - (a)->ia6_updatetime)) > \ + (u_int32_t)((time_uptime - (a)->ia6_updatetime)) >= \ (a)->ia6_lifetime.ia6t_pltime) #define IFA6_IS_INVALID(a) \ ((a)->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME && \ - (u_int32_t)((time_uptime - (a)->ia6_updatetime)) > \ + (u_int32_t)((time_uptime - (a)->ia6_updatetime)) >= \ (a)->ia6_lifetime.ia6t_vltime) #endif /* _KERNEL */ @@ -666,6 +664,8 @@ struct ip6_hdr; int in6_cksum(struct mbuf *, uint8_t, uint32_t, uint32_t); int in6_cksum_partial(struct mbuf *, uint8_t, uint32_t, uint32_t, uint32_t); +int in6_cksum_partial_l2(struct mbuf *m, uint8_t nxt, uint32_t off_l3, + uint32_t off_l4, uint32_t len, uint32_t cov); int in6_cksum_pseudo(struct ip6_hdr *, uint32_t, uint8_t, uint16_t); int in6_localaddr(struct in6_addr *); @@ -679,11 +679,10 @@ extern void in6_if_up(struct ifnet *); struct sockaddr; void in6_sin6_2_sin(struct sockaddr_in *sin, - struct sockaddr_in6 *sin6); -void in6_sin_2_v4mapsin6(struct sockaddr_in *sin, - struct sockaddr_in6 *sin6); + const struct sockaddr_in6 *sin6); +void in6_sin_2_v4mapsin6(const struct sockaddr_in *sin, + struct sockaddr_in6 *sin6); void in6_sin6_2_sin_in_sock(struct sockaddr *nam); -void in6_sin_2_v4mapsin6_in_sock(struct sockaddr **nam); extern void addrsel_policy_init(void); #define satosin6(sa) ((struct sockaddr_in6 *)(sa)) diff --git a/lib/libc/include/generic-freebsd/netinet6/in6_ifattach.h b/lib/libc/include/generic-freebsd/netinet6/in6_ifattach.h index b0f53ce7b1bf..7fd7255ced56 100644 --- a/lib/libc/include/generic-freebsd/netinet6/in6_ifattach.h +++ b/lib/libc/include/generic-freebsd/netinet6/in6_ifattach.h @@ -39,7 +39,6 @@ void in6_ifattach(struct ifnet *, struct ifnet *); void in6_ifattach_destroy(void); void in6_ifdetach(struct ifnet *); void in6_ifdetach_destroy(struct ifnet *); -int in6_get_tmpifid(struct ifnet *, u_int8_t *, const u_int8_t *, int); void in6_tmpaddrtimer(void *); int in6_get_hw_ifid(struct ifnet *, struct in6_addr *); int in6_nigroup(struct ifnet *, const char *, int, struct in6_addr *); diff --git a/lib/libc/include/generic-freebsd/netinet6/in6_pcb.h b/lib/libc/include/generic-freebsd/netinet6/in6_pcb.h index 3d14852ef6a0..a2b767a3a99f 100644 --- a/lib/libc/include/generic-freebsd/netinet6/in6_pcb.h +++ b/lib/libc/include/generic-freebsd/netinet6/in6_pcb.h @@ -58,8 +58,6 @@ * 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. - * - * @(#)in_pcb.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NETINET6_IN6_PCB_H_ @@ -72,40 +70,30 @@ void in6_pcbpurgeif0(struct inpcbinfo *, struct ifnet *); void in6_losing(struct inpcb *); -int in6_pcbbind(struct inpcb *, struct sockaddr_in6 *, struct ucred *); +int in6_pcbbind(struct inpcb *, struct sockaddr_in6 *, int, struct ucred *); int in6_pcbconnect(struct inpcb *, struct sockaddr_in6 *, struct ucred *, bool); void in6_pcbdisconnect(struct inpcb *); -struct inpcb * - in6_pcblookup_local(struct inpcbinfo *, - struct in6_addr *, u_short, int, - struct ucred *); -struct inpcb * - in6_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, +struct inpcb *in6_pcblookup_local(struct inpcbinfo *, const struct in6_addr *, + u_short, int, int, struct ucred *); +struct inpcb *in6_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, const struct in6_addr *faddr, u_int fport_arg, const struct in6_addr *laddr, u_int lport_arg, - int lookupflags, uint8_t); -struct inpcb * - in6_pcblookup(struct inpcbinfo *, struct in6_addr *, - u_int, struct in6_addr *, u_int, int, - struct ifnet *); -struct inpcb * - in6_pcblookup_mbuf(struct inpcbinfo *, struct in6_addr *, - u_int, struct in6_addr *, u_int, int, - struct ifnet *ifp, struct mbuf *); + int lookupflags, uint8_t numa_domain, int fib); +struct inpcb *in6_pcblookup(struct inpcbinfo *, const struct in6_addr *, u_int, + const struct in6_addr *, u_int, int, struct ifnet *); +struct inpcb *in6_pcblookup_mbuf(struct inpcbinfo *, const struct in6_addr *, + u_int, const struct in6_addr *, u_int, int, struct ifnet *ifp, + struct mbuf *); void in6_pcbnotify(struct inpcbinfo *, struct sockaddr_in6 *, u_int, const struct sockaddr_in6 *, u_int, int, void *, struct inpcb *(*)(struct inpcb *, int)); struct inpcb * in6_rtchange(struct inpcb *, int); -struct sockaddr * - in6_sockaddr(in_port_t port, struct in6_addr *addr_p); -struct sockaddr * - in6_v4mapsin6_sockaddr(in_port_t port, struct in_addr *addr_p); -int in6_getpeeraddr(struct socket *so, struct sockaddr **nam); -int in6_getsockaddr(struct socket *so, struct sockaddr **nam); -int in6_mapped_sockaddr(struct socket *so, struct sockaddr **nam); -int in6_mapped_peeraddr(struct socket *so, struct sockaddr **nam); +int in6_getpeeraddr(struct socket *, struct sockaddr *); +int in6_getsockaddr(struct socket *, struct sockaddr *); +int in6_mapped_sockaddr(struct socket *, struct sockaddr *); +int in6_mapped_peeraddr(struct socket *, struct sockaddr *); int in6_selecthlim(struct inpcb *, struct ifnet *); int in6_pcbsetport(struct in6_addr *, struct inpcb *, struct ucred *); void init_sin6(struct sockaddr_in6 *sin6, struct mbuf *m, int); diff --git a/lib/libc/include/generic-freebsd/netinet6/in6_var.h b/lib/libc/include/generic-freebsd/netinet6/in6_var.h index 2740316f1eeb..82e644d1b326 100644 --- a/lib/libc/include/generic-freebsd/netinet6/in6_var.h +++ b/lib/libc/include/generic-freebsd/netinet6/in6_var.h @@ -58,8 +58,6 @@ * 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. - * - * @(#)in_var.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NETINET6_IN6_VAR_H_ @@ -117,7 +115,7 @@ struct in6_ifextra { SLIST_HEAD(in6_multi_head, in6_multi); MALLOC_DECLARE(M_IP6MADDR); -struct in6_ifaddr { +struct in6_ifaddr { struct ifaddr ia_ifa; /* protocol-independent info */ #define ia_ifp ia_ifa.ifa_ifp #define ia_flags ia_ifa.ifa_flags @@ -325,8 +323,7 @@ struct in6_prflags { struct prf_ra { u_char onlink : 1; u_char autonomous : 1; - u_char ra_derived: 1; - u_char reserved : 5; + u_char reserved : 6; } prf_ra; u_char prf_reserved1; u_short prf_reserved2; @@ -357,7 +354,6 @@ struct in6_prefixreq { #define ipr_raf_onlink ipr_flags.prf_ra.onlink #define ipr_raf_auto ipr_flags.prf_ra.autonomous -#define ipr_raf_ra_derived ipr_flags.prf_ra.ra_derived #define ipr_statef_onlink ipr_flags.prf_state.onlink @@ -551,9 +547,6 @@ do { \ ((ifp)->if_afdata[AF_INET6]))->in6_ifstat[ \ offsetof(struct in6_ifstat, tag) / sizeof(uint64_t)], 1);\ } while (/*CONSTCOND*/ 0) - -VNET_DECLARE(unsigned long, in6_maxmtu); -#define V_in6_maxmtu VNET(in6_maxmtu) #endif /* _KERNEL */ /* @@ -877,7 +870,6 @@ void in6_domifdetach(struct ifnet *, void *); int in6_domifmtu(struct ifnet *); struct rib_head *in6_inithead(uint32_t fibnum); void in6_detachhead(struct rib_head *rh); -void in6_setmaxmtu(void); int in6_if2idlen(struct ifnet *); struct in6_ifaddr *in6ifa_ifpforlinklocal(struct ifnet *, int); struct in6_ifaddr *in6ifa_ifpwithaddr(struct ifnet *, const struct in6_addr *); diff --git a/lib/libc/include/generic-freebsd/netinet6/ip6_var.h b/lib/libc/include/generic-freebsd/netinet6/ip6_var.h index 22483ca5c4a3..bca6d8c5cccd 100644 --- a/lib/libc/include/generic-freebsd/netinet6/ip6_var.h +++ b/lib/libc/include/generic-freebsd/netinet6/ip6_var.h @@ -58,8 +58,6 @@ * 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. - * - * @(#)ip_var.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NETINET6_IP6_VAR_H_ @@ -132,27 +130,26 @@ struct ip6po_nhinfo { #define ip6po_nexthop ip6po_nhinfo.ip6po_nhi_nexthop #define ip6po_nextroute ip6po_nhinfo.ip6po_nhi_route +/* + * Note that fields with valid data must be flagged in ip6po_valid. + * This is done to reduce cache misses in ip6_output(). Before + * ip6po_valid, ip6_output needed to check all the individual fields + * of ip6_pktopts needed to be checked themselves, and they are spread + * across 4 cachelines. ip6_output() is currently the only consumer of + * these flags, as it is in the critical path of every packet sent. + */ struct ip6_pktopts { - struct mbuf *ip6po_m; /* Pointer to mbuf storing the data */ - int ip6po_hlim; /* Hoplimit for outgoing packets */ - - /* Outgoing IF/address information */ - struct in6_pktinfo *ip6po_pktinfo; - - /* Next-hop address information */ - struct ip6po_nhinfo ip6po_nhinfo; - - struct ip6_hbh *ip6po_hbh; /* Hop-by-Hop options header */ - - /* Destination options header (before a routing header) */ - struct ip6_dest *ip6po_dest1; - - /* Routing header related info. */ - struct ip6po_rhinfo ip6po_rhinfo; - - /* Destination options header (after a routing header) */ - struct ip6_dest *ip6po_dest2; + uint32_t ip6po_valid; +#define IP6PO_VALID_HLIM 0x0001 +#define IP6PO_VALID_PKTINFO 0x0002 +#define IP6PO_VALID_NHINFO 0x0004 +#define IP6PO_VALID_HBH 0x0008 +#define IP6PO_VALID_DEST1 0x0010 +#define IP6PO_VALID_RHINFO 0x0020 +#define IP6PO_VALID_DEST2 0x0040 +#define IP6PO_VALID_TC 0x0080 + int ip6po_hlim; /* Hoplimit for outgoing packets */ int ip6po_tclass; /* traffic class */ int ip6po_minmtu; /* fragment vs PMTU discovery policy */ @@ -173,6 +170,25 @@ struct ip6_pktopts { #endif #define IP6PO_DONTFRAG 0x04 /* disable fragmentation (IPV6_DONTFRAG) */ #define IP6PO_USECOA 0x08 /* use care of address */ + + struct mbuf *ip6po_m; /* Pointer to mbuf storing the data */ + + /* Outgoing IF/address information */ + struct in6_pktinfo *ip6po_pktinfo; + + /* Next-hop address information */ + struct ip6po_nhinfo ip6po_nhinfo; + + struct ip6_hbh *ip6po_hbh; /* Hop-by-Hop options header */ + + /* Destination options header (before a routing header) */ + struct ip6_dest *ip6po_dest1; + + /* Routing header related info. */ + struct ip6po_rhinfo ip6po_rhinfo; + + /* Destination options header (after a routing header) */ + struct ip6_dest *ip6po_dest2; }; /* @@ -247,13 +263,22 @@ struct ip6stat { #ifdef _KERNEL #include +#include VNET_PCPUSTAT_DECLARE(struct ip6stat, ip6stat); -#define IP6STAT_ADD(name, val) \ - VNET_PCPUSTAT_ADD(struct ip6stat, ip6stat, name, (val)) -#define IP6STAT_SUB(name, val) IP6STAT_ADD(name, -(val)) +#define IP6STAT_ADD(name, val) \ + do { \ + MIB_SDT_PROBE1(ip6, count, name, (val)); \ + VNET_PCPUSTAT_ADD(struct ip6stat, ip6stat, name, (val)); \ + } while (0) +#define IP6STAT_SUB(name, val) IP6STAT_ADD(name, -(val)) #define IP6STAT_INC(name) IP6STAT_ADD(name, 1) -#define IP6STAT_DEC(name) IP6STAT_SUB(name, 1) +#define IP6STAT_INC2(name, type) \ + do { \ + MIB_SDT_PROBE2(ip6, count, name, 1, type); \ + VNET_PCPUSTAT_ADD(struct ip6stat, ip6stat, name, 1); \ + } while (0) +#define IP6STAT_DEC(name) IP6STAT_SUB(name, 1) #endif #ifdef _KERNEL @@ -389,7 +414,7 @@ int route6_input(struct mbuf **, int *, int); void frag6_init(void); void frag6_destroy(void); int frag6_input(struct mbuf **, int *, int); -void frag6_drain(void); +void frag6_drain(void *, int); void rip6_init(void); int rip6_ctloutput(struct socket *, struct sockopt *); diff --git a/lib/libc/include/generic-freebsd/netinet6/ip_fw_nat64.h b/lib/libc/include/generic-freebsd/netinet6/ip_fw_nat64.h index c12eee7082cf..944ac5fc2f8a 100644 --- a/lib/libc/include/generic-freebsd/netinet6/ip_fw_nat64.h +++ b/lib/libc/include/generic-freebsd/netinet6/ip_fw_nat64.h @@ -84,9 +84,9 @@ struct ipfw_nat64lsn_stats { uint64_t spgcreated; /* Number of portgroups created */ uint64_t spgdeleted; /* Number of portgroups deleted */ uint64_t hostcount; /* Number of hosts */ - uint64_t tcpchunks; /* Number of TCP chunks */ - uint64_t udpchunks; /* Number of UDP chunks */ - uint64_t icmpchunks; /* Number of ICMP chunks */ + uint64_t tcpchunks; /* Number of TCP portgroups */ + uint64_t udpchunks; /* Number of UDP portgroups */ + uint64_t icmpchunks; /* Number of ICMP portgroups */ uint64_t _reserved[4]; }; @@ -95,6 +95,10 @@ struct ipfw_nat64lsn_stats { #define NAT64_ALLOW_PRIVATE 0x0002 /* Allow private IPv4 address * translation */ +#define NAT64LSN_ALLOW_SWAPCONF 0x0004 /* Allow configuration exchange + * between NAT64LSN instances + * during the sets swapping. + */ typedef struct _ipfw_nat64stl_cfg { char name[64]; /* NAT name */ ipfw_obj_ntlv ntlv6; /* object name tlv */ diff --git a/lib/libc/include/generic-freebsd/netinet6/nd6.h b/lib/libc/include/generic-freebsd/netinet6/nd6.h index 129ef7bbd47f..316fc6ff4e77 100644 --- a/lib/libc/include/generic-freebsd/netinet6/nd6.h +++ b/lib/libc/include/generic-freebsd/netinet6/nd6.h @@ -184,10 +184,10 @@ struct in6_ndifreq { #define RETRANS_TIMER 1000 /* msec */ #define MIN_RANDOM_FACTOR 512 /* 1024 * 0.5 */ #define MAX_RANDOM_FACTOR 1536 /* 1024 * 1.5 */ -#define DEF_TEMP_VALID_LIFETIME 604800 /* 1 week */ +#define DEF_TEMP_VALID_LIFETIME 172800 /* 2 days */ #define DEF_TEMP_PREFERRED_LIFETIME 86400 /* 1 day */ #define TEMPADDR_REGEN_ADVANCE 5 /* sec */ -#define MAX_TEMP_DESYNC_FACTOR 600 /* 10 min */ +#define TEMP_MAX_DESYNC_FACTOR_BASE 300 /* 5 min */ #define ND_COMPUTE_RTIME(x) \ (((MIN_RANDOM_FACTOR * (x >> 10)) + (arc4random() & \ ((MAX_RANDOM_FACTOR - MIN_RANDOM_FACTOR) * (x >> 10)))) /1000) @@ -242,7 +242,6 @@ struct nd_prefix { #define ndpr_raf ndpr_flags #define ndpr_raf_onlink ndpr_flags.onlink #define ndpr_raf_auto ndpr_flags.autonomous -#define ndpr_raf_ra_derived ndpr_flags.ra_derived #define ndpr_raf_router ndpr_flags.router struct nd_pfxrouter { @@ -293,11 +292,13 @@ VNET_DECLARE(struct mtx, nd6_onlink_mtx); /* nd6_rtr.c */ VNET_DECLARE(int, nd6_defifindex); VNET_DECLARE(int, ip6_desync_factor); /* seconds */ +VNET_DECLARE(uint32_t, ip6_temp_max_desync_factor); /* seconds */ VNET_DECLARE(u_int32_t, ip6_temp_preferred_lifetime); /* seconds */ VNET_DECLARE(u_int32_t, ip6_temp_valid_lifetime); /* seconds */ VNET_DECLARE(int, ip6_temp_regen_advance); /* seconds */ #define V_nd6_defifindex VNET(nd6_defifindex) #define V_ip6_desync_factor VNET(ip6_desync_factor) +#define V_ip6_temp_max_desync_factor VNET(ip6_temp_max_desync_factor) #define V_ip6_temp_preferred_lifetime VNET(ip6_temp_preferred_lifetime) #define V_ip6_temp_valid_lifetime VNET(ip6_temp_valid_lifetime) #define V_ip6_temp_regen_advance VNET(ip6_temp_regen_advance) diff --git a/lib/libc/include/generic-freebsd/netinet6/tcp6_var.h b/lib/libc/include/generic-freebsd/netinet6/tcp6_var.h index 5759b7f60f4d..d4262f934a44 100644 --- a/lib/libc/include/generic-freebsd/netinet6/tcp6_var.h +++ b/lib/libc/include/generic-freebsd/netinet6/tcp6_var.h @@ -56,8 +56,6 @@ * 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. - * - * @(#)tcp_var.h 8.4 (Berkeley) 5/24/95 */ #ifndef _NETINET_TCP6_VAR_H_ diff --git a/lib/libc/include/generic-freebsd/netinet6/udp6_var.h b/lib/libc/include/generic-freebsd/netinet6/udp6_var.h index 150e11189522..e9a76f97ae93 100644 --- a/lib/libc/include/generic-freebsd/netinet6/udp6_var.h +++ b/lib/libc/include/generic-freebsd/netinet6/udp6_var.h @@ -57,8 +57,6 @@ * 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. - * - * @(#)udp_var.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NETINET6_UDP6_VAR_H_ diff --git a/lib/libc/include/generic-freebsd/netipsec/ah_var.h b/lib/libc/include/generic-freebsd/netipsec/ah_var.h index 8bba4f40a212..1aea0fb6ab1f 100644 --- a/lib/libc/include/generic-freebsd/netipsec/ah_var.h +++ b/lib/libc/include/generic-freebsd/netipsec/ah_var.h @@ -71,13 +71,22 @@ struct ahstat { #ifdef _KERNEL #include +#include VNET_DECLARE(int, ah_enable); VNET_DECLARE(int, ah_cleartos); VNET_PCPUSTAT_DECLARE(struct ahstat, ahstat); -#define AHSTAT_ADD(name, val) \ - VNET_PCPUSTAT_ADD(struct ahstat, ahstat, name , (val)) +#define AHSTAT_ADD(name, val) \ + do { \ + MIB_SDT_PROBE1(ah, count, name, (val)); \ + VNET_PCPUSTAT_ADD(struct ahstat, ahstat, name, (val)); \ + } while (0) +#define AHSTAT_INC2(name, type) \ + do { \ + MIB_SDT_PROBE2(ah, count, name, 1, (type)); \ + VNET_PCPUSTAT_ADD(struct ahstat, ahstat, name[type], 1); \ + } while (0) #define AHSTAT_INC(name) AHSTAT_ADD(name, 1) #define V_ah_enable VNET(ah_enable) #define V_ah_cleartos VNET(ah_cleartos) diff --git a/lib/libc/include/generic-freebsd/netipsec/esp_var.h b/lib/libc/include/generic-freebsd/netipsec/esp_var.h index cbd27ab35be9..64115b4ab2c8 100644 --- a/lib/libc/include/generic-freebsd/netipsec/esp_var.h +++ b/lib/libc/include/generic-freebsd/netipsec/esp_var.h @@ -72,13 +72,25 @@ struct espstat { #ifdef _KERNEL #include +#include VNET_DECLARE(int, esp_enable); +VNET_DECLARE(int, esp_ctr_compatibility); +#define V_esp_ctr_compatibility VNET(esp_ctr_compatibility) VNET_PCPUSTAT_DECLARE(struct espstat, espstat); -#define ESPSTAT_ADD(name, val) \ - VNET_PCPUSTAT_ADD(struct espstat, espstat, name, (val)) +#define ESPSTAT_ADD(name, val) \ + do { \ + MIB_SDT_PROBE1(esp, count, name, (val)); \ + VNET_PCPUSTAT_ADD(struct espstat, espstat, name, (val)); \ + } while (0) #define ESPSTAT_INC(name) ESPSTAT_ADD(name, 1) +#define ESPSTAT_INC2(name, type) \ + do { \ + MIB_SDT_PROBE2(esp, count, name, 1, (type)); \ + VNET_PCPUSTAT_ADD(struct espstat, espstat, name[type], 1); \ + } while (0) + #define V_esp_enable VNET(esp_enable) #endif /* _KERNEL */ #endif /*_NETIPSEC_ESP_VAR_H_*/ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/netipsec/ipcomp_var.h b/lib/libc/include/generic-freebsd/netipsec/ipcomp_var.h index 2b50c3accedb..7a4e9c13d217 100644 --- a/lib/libc/include/generic-freebsd/netipsec/ipcomp_var.h +++ b/lib/libc/include/generic-freebsd/netipsec/ipcomp_var.h @@ -66,12 +66,22 @@ struct ipcompstat { #ifdef _KERNEL #include +#include VNET_DECLARE(int, ipcomp_enable); VNET_PCPUSTAT_DECLARE(struct ipcompstat, ipcompstat); -#define IPCOMPSTAT_ADD(name, val) \ - VNET_PCPUSTAT_ADD(struct ipcompstat, ipcompstat, name, (val)) +#define IPCOMPSTAT_ADD(name, val) \ + do { \ + MIB_SDT_PROBE1(ipcomp, count, name, (val)); \ + VNET_PCPUSTAT_ADD(struct ipcompstat, ipcompstat, name, (val)); \ + } while (0) +#define IPCOMPSTAT_INC2(name, type) \ + do { \ + MIB_SDT_PROBE2(ipcomp, count, name, 1, (type)); \ + VNET_PCPUSTAT_ADD(struct ipcompstat, ipcompstat, name[type], \ + 1); \ + } while (0) #define IPCOMPSTAT_INC(name) IPCOMPSTAT_ADD(name, 1) #define V_ipcomp_enable VNET(ipcomp_enable) #endif /* _KERNEL */ diff --git a/lib/libc/include/generic-freebsd/netipsec/ipsec.h b/lib/libc/include/generic-freebsd/netipsec/ipsec.h index f6a06466be97..fbd855756a04 100644 --- a/lib/libc/include/generic-freebsd/netipsec/ipsec.h +++ b/lib/libc/include/generic-freebsd/netipsec/ipsec.h @@ -46,6 +46,9 @@ #include #include #include +#include + +#include #define IPSEC_ASSERT(_c,_m) KASSERT(_c, _m) @@ -71,6 +74,12 @@ struct ipsecrequest { u_int level; /* IPsec level defined below. */ }; +struct ipsec_accel_adddel_sp_tq { + struct vnet *adddel_vnet; + struct task adddel_task; + int adddel_scheduled; +}; + /* Security Policy Data Base */ struct secpolicy { TAILQ_ENTRY(secpolicy) chain; @@ -93,7 +102,7 @@ struct secpolicy { uint32_t id; /* It's unique number on the system. */ /* * lifetime handler. - * the policy can be used without limitiation if both lifetime and + * the policy can be used without limitation if both lifetime and * validtime are zero. * "lifetime" is passed by sadb_lifetime.sadb_lifetime_addtime. * "validtime" is passed by sadb_lifetime.sadb_lifetime_usetime. @@ -102,6 +111,11 @@ struct secpolicy { time_t lastused; /* updated every when kernel sends a packet */ long lifetime; /* duration of the lifetime of this policy */ long validtime; /* duration this policy is valid without use */ + CK_LIST_HEAD(, ifp_handle_sp) accel_ifps; + struct ipsec_accel_adddel_sp_tq accel_add_tq; + struct ipsec_accel_adddel_sp_tq accel_del_tq; + struct inpcb *ipsec_accel_add_sp_inp; + const char *accel_ifname; }; /* @@ -246,6 +260,7 @@ struct ipsecstat { #define IPSECCTL_DEBUG 12 #define IPSECCTL_ESP_RANDPAD 13 #define IPSECCTL_MIN_PMTU 14 +#define IPSECCTL_RANDOM_ID 15 #ifdef _KERNEL #include @@ -279,12 +294,17 @@ VNET_DECLARE(int, ip4_ah_net_deflev); VNET_DECLARE(int, ip4_ipsec_dfbit); VNET_DECLARE(int, ip4_ipsec_min_pmtu); VNET_DECLARE(int, ip4_ipsec_ecn); +VNET_DECLARE(int, ip4_ipsec_random_id); VNET_DECLARE(int, crypto_support); VNET_DECLARE(int, async_crypto); VNET_DECLARE(int, natt_cksum_policy); -#define IPSECSTAT_INC(name) \ - VNET_PCPUSTAT_ADD(struct ipsecstat, ipsec4stat, name, 1) +#define IPSECSTAT_INC(name) \ + do { \ + MIB_SDT_PROBE1(ipsec, count, name, 1); \ + VNET_PCPUSTAT_ADD(struct ipsecstat, ipsec4stat, name, 1); \ + } while (0) + #define V_ip4_esp_trans_deflev VNET(ip4_esp_trans_deflev) #define V_ip4_esp_net_deflev VNET(ip4_esp_net_deflev) #define V_ip4_ah_trans_deflev VNET(ip4_ah_trans_deflev) @@ -292,6 +312,7 @@ VNET_DECLARE(int, natt_cksum_policy); #define V_ip4_ipsec_dfbit VNET(ip4_ipsec_dfbit) #define V_ip4_ipsec_min_pmtu VNET(ip4_ipsec_min_pmtu) #define V_ip4_ipsec_ecn VNET(ip4_ipsec_ecn) +#define V_ip4_ipsec_random_id VNET(ip4_ipsec_random_id) #define V_crypto_support VNET(crypto_support) #define V_async_crypto VNET(async_crypto) #define V_natt_cksum_policy VNET(natt_cksum_policy) @@ -307,6 +328,7 @@ VNET_DECLARE(int, natt_cksum_policy); #endif struct inpcb; +struct ip; struct m_tag; struct secasvar; struct sockopt; @@ -318,7 +340,7 @@ int ipsec_if_input(struct mbuf *, struct secasvar *, uint32_t); struct ipsecrequest *ipsec_newisr(void); void ipsec_delisr(struct ipsecrequest *); struct secpolicy *ipsec4_checkpolicy(const struct mbuf *, struct inpcb *, - int *, int); + struct ip *, int *, int); u_int ipsec_get_reqlevel(struct secpolicy *, u_int); @@ -333,27 +355,32 @@ size_t ipsec_hdrsiz_internal(struct secpolicy *); void ipsec_setspidx_inpcb(struct inpcb *, struct secpolicyindex *, u_int); -void ipsec4_setsockaddrs(const struct mbuf *, union sockaddr_union *, - union sockaddr_union *); +void ipsec4_setsockaddrs(const struct mbuf *, const struct ip *, + union sockaddr_union *, union sockaddr_union *); int ipsec4_common_input_cb(struct mbuf *, struct secasvar *, int, int); -int ipsec4_check_pmtu(struct mbuf *, struct secpolicy *, int); -int ipsec4_process_packet(struct mbuf *, struct secpolicy *, struct inpcb *); +int ipsec4_check_pmtu(struct ifnet *, struct mbuf *, struct ip *ip1, + struct secpolicy *, int); +int ipsec4_process_packet(struct ifnet *, struct mbuf *, struct ip *ip1, + struct secpolicy *, struct inpcb *, u_long); int ipsec_process_done(struct mbuf *, struct secpolicy *, struct secasvar *, u_int); -extern void m_checkalignment(const char* where, struct mbuf *m0, - int off, int len); -extern struct mbuf *m_makespace(struct mbuf *m0, int skip, int hlen, int *off); -extern caddr_t m_pad(struct mbuf *m, int n); -extern int m_striphdr(struct mbuf *m, int skip, int hlen); +void m_checkalignment(const char* where, struct mbuf *m0, + int off, int len); +struct mbuf *m_makespace(struct mbuf *m0, int skip, int hlen, int *off); +caddr_t m_pad(struct mbuf *m, int n); +int m_striphdr(struct mbuf *m, int skip, int hlen); + +SYSCTL_DECL(_net_inet_ipsec); +SYSCTL_DECL(_net_inet6_ipsec6); #endif /* _KERNEL */ #ifndef _KERNEL -extern caddr_t ipsec_set_policy(char *, int); -extern int ipsec_get_policylen(caddr_t); -extern char *ipsec_dump_policy(caddr_t, char *); -extern const char *ipsec_strerror(void); +caddr_t ipsec_set_policy(const char *, int); +int ipsec_get_policylen(c_caddr_t); +char *ipsec_dump_policy(c_caddr_t, const char *); +const char *ipsec_strerror(void); #endif /* ! KERNEL */ diff --git a/lib/libc/include/generic-freebsd/netipsec/ipsec6.h b/lib/libc/include/generic-freebsd/netipsec/ipsec6.h index 7c507806205b..50854251556a 100644 --- a/lib/libc/include/generic-freebsd/netipsec/ipsec6.h +++ b/lib/libc/include/generic-freebsd/netipsec/ipsec6.h @@ -66,8 +66,9 @@ struct secpolicy *ipsec6_checkpolicy(const struct mbuf *, void ipsec6_setsockaddrs(const struct mbuf *, union sockaddr_union *, union sockaddr_union *); int ipsec6_common_input_cb(struct mbuf *, struct secasvar *, int, int); -int ipsec6_check_pmtu(struct mbuf *, struct secpolicy *, int); -int ipsec6_process_packet(struct mbuf *, struct secpolicy *, struct inpcb *); +int ipsec6_check_pmtu(struct ifnet *, struct mbuf *, struct secpolicy *, int); +int ipsec6_process_packet(struct ifnet *, struct mbuf *, struct secpolicy *, + struct inpcb *, u_long); int ip6_ipsec_filtertunnel(struct mbuf *); int ip6_ipsec_pcbctl(struct inpcb *, struct sockopt *); diff --git a/lib/libc/include/generic-freebsd/netipsec/ipsec_offload.h b/lib/libc/include/generic-freebsd/netipsec/ipsec_offload.h new file mode 100644 index 000000000000..cf570a8e63a2 --- /dev/null +++ b/lib/libc/include/generic-freebsd/netipsec/ipsec_offload.h @@ -0,0 +1,217 @@ +/*- + * Copyright (c) 2021,2022 NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY 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 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 _NETIPSEC_IPSEC_OFFLOAD_H_ +#define _NETIPSEC_IPSEC_OFFLOAD_H_ + +#ifdef _KERNEL +#include +#include +#include +#include + +struct secpolicy; +struct secasvar; +struct inpcb; + +struct ipsec_accel_out_tag { + struct m_tag tag; + uint16_t drv_spi; +}; + +struct ipsec_accel_in_tag { + struct m_tag tag; + struct xform_history xh; /* Must be first to mimic IPSEC_IN_DONE */ + uint16_t drv_spi; +}; + +#define IPSEC_ACCEL_DRV_SPI_BYPASS 2 +#define IPSEC_ACCEL_DRV_SPI_MIN 3 +#define IPSEC_ACCEL_DRV_SPI_MAX 0xffff + +extern void (*ipsec_accel_sa_newkey_p)(struct secasvar *sav); +extern void (*ipsec_accel_sa_install_input_p)(struct secasvar *sav, + const union sockaddr_union *dst_address, int sproto, uint32_t spi); +extern void (*ipsec_accel_forget_sav_p)(struct secasvar *sav); +extern void (*ipsec_accel_spdadd_p)(struct secpolicy *sp, struct inpcb *inp); +extern void (*ipsec_accel_spddel_p)(struct secpolicy *sp); +extern int (*ipsec_accel_sa_lifetime_op_p)(struct secasvar *sav, + struct seclifetime *lft_c, if_t ifp, enum IF_SA_CNT_WHICH op, + struct rm_priotracker *sahtree_trackerp); +extern void (*ipsec_accel_sync_p)(void); +extern bool (*ipsec_accel_is_accel_sav_p)(struct secasvar *sav); +extern struct mbuf *(*ipsec_accel_key_setaccelif_p)(struct secasvar *sav); +extern void (*ipsec_accel_on_ifdown_p)(struct ifnet *ifp); +extern void (*ipsec_accel_drv_sa_lifetime_update_p)(struct secasvar *sav, + if_t ifp, u_int drv_spi, uint64_t octets, uint64_t allocs); +extern int (*ipsec_accel_drv_sa_lifetime_fetch_p)(struct secasvar *sav, + if_t ifp, u_int drv_spi, uint64_t *octets, uint64_t *allocs); +extern bool (*ipsec_accel_fill_xh_p)(if_t ifp, uint32_t drv_spi, + struct xform_history *xh); + +#ifdef IPSEC_OFFLOAD +/* + * Have to use ipsec_accel_sa_install_input_p indirection because + * key.c is unconditionally included into the static kernel. + */ +static inline void +ipsec_accel_sa_newkey(struct secasvar *sav) +{ + void (*p)(struct secasvar *sav); + + p = atomic_load_ptr(&ipsec_accel_sa_newkey_p); + if (p != NULL) + p(sav); +} + +static inline void +ipsec_accel_forget_sav(struct secasvar *sav) +{ + void (*p)(struct secasvar *sav); + + p = atomic_load_ptr(&ipsec_accel_forget_sav_p); + if (p != NULL) + p(sav); +} + +static inline void +ipsec_accel_spdadd(struct secpolicy *sp, struct inpcb *inp) +{ + void (*p)(struct secpolicy *sp, struct inpcb *inp); + + p = atomic_load_ptr(&ipsec_accel_spdadd_p); + if (p != NULL) + p(sp, inp); +} + +static inline void +ipsec_accel_spddel(struct secpolicy *sp) +{ + void (*p)(struct secpolicy *sp); + + p = atomic_load_ptr(&ipsec_accel_spddel_p); + if (p != NULL) + p(sp); +} + +static inline int +ipsec_accel_sa_lifetime_op(struct secasvar *sav, + struct seclifetime *lft_c, if_t ifp, enum IF_SA_CNT_WHICH op, + struct rm_priotracker *sahtree_trackerp) +{ + int (*p)(struct secasvar *sav, struct seclifetime *lft_c, if_t ifp, + enum IF_SA_CNT_WHICH op, struct rm_priotracker *sahtree_trackerp); + + p = atomic_load_ptr(&ipsec_accel_sa_lifetime_op_p); + if (p != NULL) + return (p(sav, lft_c, ifp, op, sahtree_trackerp)); + return (ENOTSUP); +} + +static inline void +ipsec_accel_sync(void) +{ + void (*p)(void); + + p = atomic_load_ptr(&ipsec_accel_sync_p); + if (p != NULL) + p(); +} + +static inline bool +ipsec_accel_is_accel_sav(struct secasvar *sav) +{ + bool (*p)(struct secasvar *sav); + + p = atomic_load_ptr(&ipsec_accel_is_accel_sav_p); + if (p != NULL) + return (p(sav)); + return (false); +} + +static inline struct mbuf * +ipsec_accel_key_setaccelif(struct secasvar *sav) +{ + struct mbuf *(*p)(struct secasvar *sav); + + p = atomic_load_ptr(&ipsec_accel_key_setaccelif_p); + if (p != NULL) + return (p(sav)); + return (NULL); +} + +static inline bool +ipsec_accel_fill_xh(if_t ifp, uint32_t drv_spi, struct xform_history *xh) +{ + bool (*p)(if_t ifp, uint32_t drv_spi, struct xform_history *xh); + + p = atomic_load_ptr(&ipsec_accel_fill_xh_p); + if (p != NULL) + return (p(ifp, drv_spi, xh)); + return (false); +} + +#else +#define ipsec_accel_sa_newkey(a) +#define ipsec_accel_forget_sav(a) +#define ipsec_accel_spdadd(a, b) +#define ipsec_accel_spddel(a) +#define ipsec_accel_sa_lifetime_op(a, b, c, d, e) +#define ipsec_accel_sync() +#define ipsec_accel_is_accel_sav(a) +#define ipsec_accel_key_setaccelif(a) +#define ipsec_accel_fill_xh(a, b, c) (false) +#endif + +void ipsec_accel_forget_sav_impl(struct secasvar *sav); +void ipsec_accel_spdadd_impl(struct secpolicy *sp, struct inpcb *inp); +void ipsec_accel_spddel_impl(struct secpolicy *sp); + +#ifdef IPSEC_OFFLOAD +int ipsec_accel_input(struct mbuf *m, int offset, int proto); +bool ipsec_accel_output(struct ifnet *ifp, struct mbuf *m, + struct inpcb *inp, struct secpolicy *sp, struct secasvar *sav, int af, + int mtu, int *hwassist); +void ipsec_accel_forget_sav(struct secasvar *sav); +struct xform_history; +#else +#define ipsec_accel_input(a, b, c) (ENXIO) +#define ipsec_accel_output(a, b, c, d, e, f, g, h) ({ \ + *h = 0; \ + false; \ +}) +#define ipsec_accel_forget_sav(a) +#endif + +struct ipsec_accel_in_tag *ipsec_accel_input_tag_lookup(const struct mbuf *); +void ipsec_accel_on_ifdown(struct ifnet *ifp); +void ipsec_accel_drv_sa_lifetime_update(struct secasvar *sav, if_t ifp, + u_int drv_spi, uint64_t octets, uint64_t allocs); +int ipsec_accel_drv_sa_lifetime_fetch(struct secasvar *sav, + if_t ifp, u_int drv_spi, uint64_t *octets, uint64_t *allocs); + +#endif /* _KERNEL */ + +#endif /* _NETIPSEC_IPSEC_OFFLOAD_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/netipsec/ipsec_support.h b/lib/libc/include/generic-freebsd/netipsec/ipsec_support.h index 10b3671cdcc9..2b3fc69c8b46 100644 --- a/lib/libc/include/generic-freebsd/netipsec/ipsec_support.h +++ b/lib/libc/include/generic-freebsd/netipsec/ipsec_support.h @@ -29,6 +29,8 @@ #ifdef _KERNEL #if defined(IPSEC) || defined(IPSEC_SUPPORT) +struct ifnet; +struct ip; struct mbuf; struct inpcb; struct tcphdr; @@ -49,14 +51,17 @@ int ipsec_init_pcbpolicy(struct inpcb *); int ipsec_delete_pcbpolicy(struct inpcb *); int ipsec_copy_pcbpolicy(struct inpcb *, struct inpcb *); -#ifdef INET +#if defined(INET) || defined(INET6) int udp_ipsec_input(struct mbuf *, int, int); int udp_ipsec_pcbctl(struct inpcb *, struct sockopt *); +#endif +#ifdef INET int ipsec4_in_reject(const struct mbuf *, struct inpcb *); +int ipsec4_in_reject1(const struct mbuf *m, struct ip *ip1, struct inpcb *inp); int ipsec4_input(struct mbuf *, int, int); int ipsec4_forward(struct mbuf *); int ipsec4_pcbctl(struct inpcb *, struct sockopt *); -int ipsec4_output(struct mbuf *, struct inpcb *); +int ipsec4_output(struct ifnet *, struct mbuf *, struct inpcb *, u_long); int ipsec4_capability(struct mbuf *, u_int); int ipsec4_ctlinput(ipsec_ctlinput_param_t); #endif /* INET */ @@ -66,7 +71,7 @@ int ipsec6_input(struct mbuf *, int, int); int ipsec6_in_reject(const struct mbuf *, struct inpcb *); int ipsec6_forward(struct mbuf *); int ipsec6_pcbctl(struct inpcb *, struct sockopt *); -int ipsec6_output(struct mbuf *, struct inpcb *); +int ipsec6_output(struct ifnet *, struct mbuf *, struct inpcb *, u_long); int ipsec6_capability(struct mbuf *, u_int); int ipsec6_ctlinput(ipsec_ctlinput_param_t); #endif /* INET6 */ @@ -75,7 +80,8 @@ struct ipsec_methods { int (*input)(struct mbuf *, int, int); int (*check_policy)(const struct mbuf *, struct inpcb *); int (*forward)(struct mbuf *); - int (*output)(struct mbuf *, struct inpcb *); + int (*output)(struct ifnet *, struct mbuf *, struct inpcb *, + u_long); int (*pcbctl)(struct inpcb *, struct sockopt *); size_t (*hdrsize)(struct inpcb *); int (*capability)(struct mbuf *, u_int); @@ -164,10 +170,10 @@ extern const struct ipsec_support * const ipv6_ipsec_support; #define IPSEC_CTLINPUT(proto, param) \ (*(proto ## _ipsec_support)->methods->ctlinput)(param) -#define UDPENCAP_INPUT(m, ...) \ - (*ipv4_ipsec_support->methods->udp_input)(m, __VA_ARGS__) -#define UDPENCAP_PCBCTL(inp, sopt) \ - (*ipv4_ipsec_support->methods->udp_pcbctl)(inp, sopt) +#define UDPENCAP_INPUT(proto, m, ...) \ + (*(proto ## _ipsec_support)->methods->udp_input)(m, __VA_ARGS__) +#define UDPENCAP_PCBCTL(proto, inp, sopt) \ + (*(proto ## _ipsec_support)->methods->udp_pcbctl)(inp, sopt) #elif defined(IPSEC_SUPPORT) struct ipsec_support { @@ -185,8 +191,8 @@ int ipsec_kmod_input(struct ipsec_support * const, struct mbuf *, int, int); int ipsec_kmod_check_policy(struct ipsec_support * const, struct mbuf *, struct inpcb *); int ipsec_kmod_forward(struct ipsec_support * const, struct mbuf *); -int ipsec_kmod_output(struct ipsec_support * const, struct mbuf *, - struct inpcb *); +int ipsec_kmod_output(struct ipsec_support * const, struct ifnet *, + struct mbuf *, struct inpcb *, u_long); int ipsec_kmod_pcbctl(struct ipsec_support * const, struct inpcb *, struct sockopt *); int ipsec_kmod_capability(struct ipsec_support * const, struct mbuf *, u_int); @@ -196,10 +202,10 @@ int ipsec_kmod_udp_input(struct ipsec_support * const, struct mbuf *, int, int); int ipsec_kmod_udp_pcbctl(struct ipsec_support * const, struct inpcb *, struct sockopt *); -#define UDPENCAP_INPUT(m, ...) \ - ipsec_kmod_udp_input(ipv4_ipsec_support, m, __VA_ARGS__) -#define UDPENCAP_PCBCTL(inp, sopt) \ - ipsec_kmod_udp_pcbctl(ipv4_ipsec_support, inp, sopt) +#define UDPENCAP_INPUT(proto, m, ...) \ + ipsec_kmod_udp_input(proto ## _ipsec_support, m, __VA_ARGS__) +#define UDPENCAP_PCBCTL(proto, inp, sopt) \ + ipsec_kmod_udp_pcbctl(proto ## _ipsec_support, inp, sopt) #define IPSEC_INPUT(proto, ...) \ ipsec_kmod_input(proto ## _ipsec_support, __VA_ARGS__) diff --git a/lib/libc/include/generic-freebsd/netipsec/key.h b/lib/libc/include/generic-freebsd/netipsec/key.h index 2bd48a5e242b..a191f9208a3b 100644 --- a/lib/libc/include/generic-freebsd/netipsec/key.h +++ b/lib/libc/include/generic-freebsd/netipsec/key.h @@ -36,6 +36,7 @@ #ifdef _KERNEL +struct mbuf; struct secpolicy; struct secpolicyindex; struct secasvar; @@ -49,6 +50,7 @@ struct xformsw; struct secpolicy *key_newsp(void); struct secpolicy *key_allocsp(struct secpolicyindex *, u_int); +struct secpolicy *key_do_allocsp(struct secpolicyindex *spidx, u_int dir); struct secpolicy *key_msg2sp(struct sadb_x_policy *, size_t, int *); int key_sp2msg(struct secpolicy *, void *, size_t *); void key_addref(struct secpolicy *); @@ -59,6 +61,7 @@ int key_havesp_any(void); void key_bumpspgen(void); uint32_t key_getspgen(void); uint32_t key_newreqid(void); +struct mbuf *key_setaccelif(const char *ifname); struct secasvar *key_allocsa(union sockaddr_union *, uint8_t, uint32_t); struct secasvar *key_allocsa_tunnel(union sockaddr_union *, @@ -84,6 +87,10 @@ extern void key_sa_recordxfer(struct secasvar *, struct mbuf *); uint16_t key_portfromsaddr(struct sockaddr *); void key_porttosaddr(struct sockaddr *, uint16_t port); +struct rm_priotracker; +void ipsec_sahtree_runlock(struct rm_priotracker *); +void ipsec_sahtree_rlock(struct rm_priotracker *); + #ifdef MALLOC_DECLARE MALLOC_DECLARE(M_IPSEC_SA); MALLOC_DECLARE(M_IPSEC_SAH); diff --git a/lib/libc/include/generic-freebsd/netipsec/keydb.h b/lib/libc/include/generic-freebsd/netipsec/keydb.h index b8449a03f43f..df9e0a0f3aef 100644 --- a/lib/libc/include/generic-freebsd/netipsec/keydb.h +++ b/lib/libc/include/generic-freebsd/netipsec/keydb.h @@ -36,9 +36,11 @@ #ifdef _KERNEL #include +#include #include #include #include +#include #include #include @@ -125,6 +127,7 @@ struct xformsw; struct enc_xform; struct auth_hash; struct comp_algo; +struct ifp_handle_sav; /* * Security Association @@ -185,8 +188,19 @@ struct secasvar { uint64_t cntr; /* counter for GCM and CTR */ volatile u_int refcnt; /* reference count */ + CK_LIST_HEAD(, ifp_handle_sav) accel_ifps; + uintptr_t accel_forget_tq; + const char *accel_ifname; + uint32_t accel_flags; + counter_u64_t accel_lft_sw; + uint64_t accel_hw_allocs; + uint64_t accel_hw_octets; + uint64_t accel_firstused; }; +#define SADB_KEY_ACCEL_INST 0x00000001 +#define SADB_KEY_ACCEL_DEINST 0x00000002 + #define SECASVAR_RLOCK_TRACKER struct rm_priotracker _secas_tracker #define SECASVAR_RLOCK(_sav) rm_rlock((_sav)->lock, &_secas_tracker) #define SECASVAR_RUNLOCK(_sav) rm_runlock((_sav)->lock, &_secas_tracker) diff --git a/lib/libc/include/generic-freebsd/netlink/ktest_netlink_message_writer.h b/lib/libc/include/generic-freebsd/netlink/ktest_netlink_message_writer.h index 0d4e7018f6cf..b83287f7d6b5 100644 --- a/lib/libc/include/generic-freebsd/netlink/ktest_netlink_message_writer.h +++ b/lib/libc/include/generic-freebsd/netlink/ktest_netlink_message_writer.h @@ -30,28 +30,14 @@ #if defined(_KERNEL) && defined(INVARIANTS) -bool nlmsg_get_buf_type_wrapper(struct nl_writer *nw, int size, int type, bool waitok); -void nlmsg_set_callback_wrapper(struct nl_writer *nw); -struct mbuf *nl_get_mbuf_chain_wrapper(int len, int malloc_flags); +bool nlmsg_get_buf_wrapper(struct nl_writer *nw, size_t size, bool waitok); #ifndef KTEST_CALLER bool -nlmsg_get_buf_type_wrapper(struct nl_writer *nw, int size, int type, bool waitok) +nlmsg_get_buf_wrapper(struct nl_writer *nw, size_t size, bool waitok) { - return (nlmsg_get_buf_type(nw, size, type, waitok)); -} - -void -nlmsg_set_callback_wrapper(struct nl_writer *nw) -{ - nlmsg_set_callback(nw); -} - -struct mbuf * -nl_get_mbuf_chain_wrapper(int len, int malloc_flags) -{ - return (nl_get_mbuf_chain(len, malloc_flags)); + return (nlmsg_get_buf(nw, size, waitok)); } #endif diff --git a/lib/libc/include/generic-freebsd/netlink/netlink.h b/lib/libc/include/generic-freebsd/netlink/netlink.h index a3c1e5d5a4a8..853bfbea6251 100644 --- a/lib/libc/include/generic-freebsd/netlink/netlink.h +++ b/lib/libc/include/generic-freebsd/netlink/netlink.h @@ -61,7 +61,7 @@ #ifndef _NETLINK_NETLINK_H_ #define _NETLINK_NETLINK_H_ -#include +#include #include struct sockaddr_nl { @@ -194,11 +194,8 @@ enum nlmsginfo_attrs { }; -#ifndef roundup2 -#define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */ -#endif #define NL_ITEM_ALIGN_SIZE sizeof(uint32_t) -#define NL_ITEM_ALIGN(_len) roundup2(_len, NL_ITEM_ALIGN_SIZE) +#define NL_ITEM_ALIGN(_len) __align_up(_len, NL_ITEM_ALIGN_SIZE) #define NL_ITEM_DATA(_ptr, _off) ((void *)((char *)(_ptr) + _off)) #define NL_ITEM_DATA_CONST(_ptr, _off) ((const void *)((const char *)(_ptr) + _off)) @@ -208,25 +205,24 @@ enum nlmsginfo_attrs { #define NL_ITEM_ITER(_ptr, _len, _LEN_MACRO) \ ((_len) -= _LEN_MACRO(_ptr), NL_ITEM_NEXT(_ptr, _LEN_MACRO)) +/* part of netlink(3) API */ +#define NLMSG_ALIGNTO NL_ITEM_ALIGN_SIZE +#define NLMSG_ALIGN(_len) NL_ITEM_ALIGN(_len) #ifndef _KERNEL /* part of netlink(3) API */ -#define NLMSG_ALIGNTO NL_ITEM_ALIGN_SIZE -#define NLMSG_ALIGN(_len) NL_ITEM_ALIGN(_len) -#define NLMSG_HDRLEN ((int)sizeof(struct nlmsghdr)) -#define NLMSG_LENGTH(_len) ((_len) + NLMSG_HDRLEN) -#define NLMSG_SPACE(_len) NLMSG_ALIGN(NLMSG_LENGTH(_len)) -#define NLMSG_DATA(_hdr) NL_ITEM_DATA(_hdr, NLMSG_HDRLEN) -#define _NLMSG_LEN(_hdr) ((int)(_hdr)->nlmsg_len) +#define NLMSG_HDRLEN (sizeof(struct nlmsghdr)) +#define NLMSG_LENGTH(_len) ((_len) + NLMSG_HDRLEN) +#define NLMSG_SPACE(_len) NLMSG_ALIGN(NLMSG_LENGTH(_len)) +#define NLMSG_DATA(_hdr) NL_ITEM_DATA(_hdr, NLMSG_HDRLEN) +#define _NLMSG_LEN(_hdr) ((_hdr)->nlmsg_len) #define _NLMSG_ALIGNED_LEN(_hdr) NLMSG_ALIGN(_NLMSG_LEN(_hdr)) #define NLMSG_OK(_hdr, _len) NL_ITEM_OK(_hdr, _len, NLMSG_HDRLEN, _NLMSG_LEN) #define NLMSG_PAYLOAD(_hdr,_len) (_NLMSG_LEN(_hdr) - NLMSG_SPACE((_len))) #define NLMSG_NEXT(_hdr, _len) NL_ITEM_ITER(_hdr, _len, _NLMSG_ALIGNED_LEN) #else -#define NLMSG_ALIGNTO 4U -#define NLMSG_ALIGN(len) (((len) + NLMSG_ALIGNTO - 1) & ~(NLMSG_ALIGNTO - 1)) -#define NLMSG_HDRLEN ((int)NLMSG_ALIGN(sizeof(struct nlmsghdr))) +#define NLMSG_HDRLEN (NLMSG_ALIGN(sizeof(struct nlmsghdr))) #endif /* diff --git a/lib/libc/include/generic-freebsd/netlink/netlink_ctl.h b/lib/libc/include/generic-freebsd/netlink/netlink_ctl.h index 2c48e26730cc..c124da742703 100644 --- a/lib/libc/include/generic-freebsd/netlink/netlink_ctl.h +++ b/lib/libc/include/generic-freebsd/netlink/netlink_ctl.h @@ -47,8 +47,8 @@ MALLOC_DECLARE(M_NETLINK); #define NLA_ALIGN_SIZE sizeof(uint32_t) #define NLA_ALIGN(_len) _roundup2(_len, NLA_ALIGN_SIZE) -#define NLA_HDRLEN ((int)sizeof(struct nlattr)) -#define NLA_DATA_LEN(_nla) ((int)((_nla)->nla_len - NLA_HDRLEN)) +#define NLA_HDRLEN ((uint16_t)sizeof(struct nlattr)) +#define NLA_DATA_LEN(_nla) ((_nla)->nla_len - NLA_HDRLEN) #define NLA_DATA(_nla) NL_ITEM_DATA(_nla, NLA_HDRLEN) #define NLA_DATA_CONST(_nla) NL_ITEM_DATA_CONST(_nla, NLA_HDRLEN) #define NLA_TYPE(_nla) ((_nla)->nla_type & 0x3FFF) @@ -65,8 +65,6 @@ MALLOC_DECLARE(M_NETLINK); ((char *)NLA_NEXT(_attr) <= (char *)_end); \ _attr = (_len -= NLA_ALIGN(_attr->nla_len), NLA_NEXT(_attr))) -#define NL_ARRAY_LEN(_a) (sizeof(_a) / sizeof((_a)[0])) - #include #include @@ -79,7 +77,6 @@ bool netlink_register_proto(int proto, const char *proto_name, nl_handler_f hand bool netlink_unregister_proto(int proto); /* Common helpers */ -bool nl_has_listeners(int netlink_family, uint32_t groups_mask); bool nlp_has_priv(struct nlpcb *nlp, int priv); struct ucred *nlp_get_cred(struct nlpcb *nlp); uint32_t nlp_get_pid(const struct nlpcb *nlp); @@ -94,18 +91,16 @@ struct genl_cmd { uint32_t cmd_num; }; -uint32_t genl_register_family(const char *family_name, size_t hdrsize, - int family_version, int max_attr_idx); -bool genl_unregister_family(const char *family_name); -bool genl_register_cmds(const char *family_name, const struct genl_cmd *cmds, - int count); -uint32_t genl_register_group(const char *family_name, const char *group_name); - -struct genl_family; -const char *genl_get_family_name(const struct genl_family *gf); -uint32_t genl_get_family_id(const struct genl_family *gf); +uint16_t genl_register_family(const char *family_name, size_t hdrsize, + uint16_t family_version, uint16_t max_attr_idx); +void genl_unregister_family(uint16_t family); +bool genl_register_cmds(uint16_t family, const struct genl_cmd *cmds, + u_int count); +uint32_t genl_register_group(uint16_t family, const char *group_name); +void genl_unregister_group(uint16_t family, uint32_t group); -typedef void (*genl_family_event_handler_t)(void *arg, const struct genl_family *gf, int action); +typedef void (*genl_family_event_handler_t)(void *arg, const char *family_name, + uint16_t family_id, u_int action); EVENTHANDLER_DECLARE(genl_family_event, genl_family_event_handler_t); struct thread; diff --git a/lib/libc/include/generic-freebsd/netlink/netlink_linux.h b/lib/libc/include/generic-freebsd/netlink/netlink_linux.h index f46ee83dcf0a..6461aa086d0c 100644 --- a/lib/libc/include/generic-freebsd/netlink/netlink_linux.h +++ b/lib/libc/include/generic-freebsd/netlink/netlink_linux.h @@ -27,6 +27,7 @@ #ifndef _NETLINK_LINUX_VAR_H_ #define _NETLINK_LINUX_VAR_H_ +#ifdef _KERNEL /* * The file contains headers for the bridge interface between @@ -34,16 +35,13 @@ */ struct nlpcb; struct nl_pstate; +struct nl_writer; -typedef struct mbuf *mbufs_to_linux_cb_t(int netlink_family, struct mbuf *m, - struct nlpcb *nlp); -typedef struct mbuf *msgs_to_linux_cb_t(int netlink_family, char *buf, int data_length, - struct nlpcb *nlp); -typedef struct nlmsghdr *msg_from_linux_cb_t(int netlink_family, struct nlmsghdr *hdr, +typedef struct nl_buf * msgs_to_linux_cb_t(struct nl_buf *, struct nlpcb *); +typedef int msg_from_linux_cb_t(int netlink_family, struct nlmsghdr **hdr, struct nl_pstate *npt); struct linux_netlink_provider { - mbufs_to_linux_cb_t *mbufs_to_linux; msgs_to_linux_cb_t *msgs_to_linux; msg_from_linux_cb_t *msg_from_linux; @@ -51,4 +49,5 @@ struct linux_netlink_provider { extern struct linux_netlink_provider *linux_netlink_p; +#endif #endif \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/netlink/netlink_message_parser.h b/lib/libc/include/generic-freebsd/netlink/netlink_message_parser.h index 48832ed6e528..9b09087263f1 100644 --- a/lib/libc/include/generic-freebsd/netlink/netlink_message_parser.h +++ b/lib/libc/include/generic-freebsd/netlink/netlink_message_parser.h @@ -64,15 +64,15 @@ lb_clear(struct linear_buffer *lb) #define NL_MAX_ERROR_BUF 128 #define SCRATCH_BUFFER_SIZE (1024 + NL_MAX_ERROR_BUF) struct nl_pstate { - struct linear_buffer lb; /* Per-message scratch buffer */ - struct nlpcb *nlp; /* Originator socket */ - struct nl_writer *nw; /* Message writer to use */ - struct nlmsghdr *hdr; /* Current parsed message header */ - uint32_t err_off; /* error offset from hdr start */ - int error; /* last operation error */ - char *err_msg; /* Description of last error */ - struct nlattr *cookie; /* NLA to return to the userspace */ - bool strict; /* Strict parsing required */ + struct linear_buffer lb; /* Per-message scratch buffer */ + struct nlpcb *nlp; /* Originator socket */ + struct nl_writer *nw; /* Message writer to use */ + struct nlmsghdr *hdr; /* Current parsed message header */ + uint32_t err_off; /* error offset from hdr start */ + int error; /* last operation error */ + char *err_msg; /* Description of last error */ + struct nlattr *cookie; /* NLA to return to the userspace */ + bool strict; /* Strict parsing required */ }; static inline void * @@ -80,10 +80,10 @@ npt_alloc(struct nl_pstate *npt, int len) { return (lb_alloc(&npt->lb, len)); } -#define npt_alloc_sockaddr(_npt, _len) ((struct sockaddr *)(npt_alloc(_npt, _len))) +#define npt_alloc_sockaddr(_npt, _len) \ + ((struct sockaddr *)(npt_alloc((_npt), (_len)))) -typedef int parse_field_f(void *hdr, struct nl_pstate *npt, - void *target); +typedef int parse_field_f(void *hdr, struct nl_pstate *npt, void *target); struct nlfield_parser { uint16_t off_in; uint16_t off_out; @@ -98,29 +98,28 @@ int nlf_get_u16(void *src, struct nl_pstate *npt, void *target); int nlf_get_u32(void *src, struct nl_pstate *npt, void *target); int nlf_get_u8_u32(void *src, struct nl_pstate *npt, void *target); - struct nlattr_parser; typedef int parse_attr_f(struct nlattr *attr, struct nl_pstate *npt, const void *arg, void *target); struct nlattr_parser { - uint16_t type; /* Attribute type */ - uint16_t off; /* field offset in the target structure */ - parse_attr_f *cb; /* parser function to call */ - const void *arg; + uint16_t type; /* Attribute type */ + uint16_t off; /* field offset in the target structure */ + parse_attr_f *cb; /* parser function to call */ + const void *arg; }; typedef bool strict_parser_f(void *hdr, struct nl_pstate *npt); typedef bool post_parser_f(void *parsed_attrs, struct nl_pstate *npt); struct nlhdr_parser { - int nl_hdr_off; /* aligned netlink header size */ - int out_hdr_off; /* target header size */ - int fp_size; - int np_size; + u_int nl_hdr_off; /* aligned netlink header size */ + u_int out_hdr_off; /* target header size */ + u_int fp_size; + u_int np_size; const struct nlfield_parser *fp; /* array of header field parsers */ const struct nlattr_parser *np; /* array of attribute parsers */ - strict_parser_f *sp; /* Pre-parse strict validation function */ - post_parser_f *post_parse; + strict_parser_f *sp; /* Pre-parse strict validation function */ + post_parser_f *post_parse; }; #define NL_DECLARE_PARSER_EXT(_name, _t, _sp, _fp, _np, _pp) \ @@ -128,8 +127,8 @@ static const struct nlhdr_parser _name = { \ .nl_hdr_off = sizeof(_t), \ .fp = &((_fp)[0]), \ .np = &((_np)[0]), \ - .fp_size = NL_ARRAY_LEN(_fp), \ - .np_size = NL_ARRAY_LEN(_np), \ + .fp_size = nitems(_fp), \ + .np_size = nitems(_np), \ .sp = _sp, \ .post_parse = _pp, \ } @@ -146,29 +145,37 @@ static const struct nlhdr_parser _name = { \ .out_hdr_off = sizeof(_o), \ .fp = &((_fp)[0]), \ .np = &((_np)[0]), \ - .fp_size = NL_ARRAY_LEN(_fp), \ - .np_size = NL_ARRAY_LEN(_np), \ + .fp_size = nitems(_fp), \ + .np_size = nitems(_np), \ } -#define NL_DECLARE_ATTR_PARSER(_name, _np) \ +#define NL_DECLARE_ATTR_PARSER_EXT(_name, _np, _pp) \ static const struct nlhdr_parser _name = { \ .np = &((_np)[0]), \ - .np_size = NL_ARRAY_LEN(_np), \ + .np_size = nitems(_np), \ + .post_parse = (_pp) \ } +#define NL_DECLARE_ATTR_PARSER(_name, _np) \ + NL_DECLARE_ATTR_PARSER_EXT(_name, _np, NULL) + #define NL_ATTR_BMASK_SIZE 128 BITSET_DEFINE(nlattr_bmask, NL_ATTR_BMASK_SIZE); -void nl_get_attrs_bmask_raw(struct nlattr *nla_head, int len, struct nlattr_bmask *bm); -bool nl_has_attr(const struct nlattr_bmask *bm, unsigned int nla_type); +void nl_get_attrs_bmask_raw(struct nlattr *nla_head, uint32_t len, + struct nlattr_bmask *bm); +bool nl_has_attr(const struct nlattr_bmask *bm, uint16_t nla_type); -int nl_parse_attrs_raw(struct nlattr *nla_head, int len, const struct nlattr_parser *ps, - int pslen, struct nl_pstate *npt, void *target); +int nl_parse_attrs_raw(struct nlattr *nla_head, uint16_t len, + const struct nlattr_parser *ps, u_int pslen, struct nl_pstate *npt, + void *target); int nlattr_get_flag(struct nlattr *nla, struct nl_pstate *npt, const void *arg, void *target); int nlattr_get_ip(struct nlattr *nla, struct nl_pstate *npt, const void *arg, void *target); +int nlattr_get_bool(struct nlattr *nla, struct nl_pstate *npt, + const void *arg, void *target); int nlattr_get_uint8(struct nlattr *nla, struct nl_pstate *npt, const void *arg, void *target); int nlattr_get_uint16(struct nlattr *nla, struct nl_pstate *npt, @@ -187,16 +194,23 @@ int nlattr_get_ifpz(struct nlattr *nla, struct nl_pstate *npt, const void *arg, void *target); int nlattr_get_ipvia(struct nlattr *nla, struct nl_pstate *npt, const void *arg, void *target); +int nlattr_get_chara(struct nlattr *nla, struct nl_pstate *npt, + const void *arg, void *target); int nlattr_get_string(struct nlattr *nla, struct nl_pstate *npt, const void *arg, void *target); int nlattr_get_stringn(struct nlattr *nla, struct nl_pstate *npt, const void *arg, void *target); +int nlattr_get_bytes(struct nlattr *nla, struct nl_pstate *npt, + const void *arg, void *target); int nlattr_get_nla(struct nlattr *nla, struct nl_pstate *npt, const void *arg, void *target); int nlattr_get_nested(struct nlattr *nla, struct nl_pstate *npt, const void *arg, void *target); +int nlattr_get_nested_ptr(struct nlattr *nla, struct nl_pstate *npt, + const void *arg, void *target); -bool nlmsg_report_err_msg(struct nl_pstate *npt, const char *fmt, ...); +bool nlmsg_report_err_msg(struct nl_pstate *npt, const char *fmt, ...) + __printflike(2, 3); #define NLMSG_REPORT_ERR_MSG(_npt, _fmt, ...) { \ nlmsg_report_err_msg(_npt, _fmt, ## __VA_ARGS__); \ @@ -213,20 +227,26 @@ void nlmsg_report_cookie_u32(struct nl_pstate *npt, uint32_t val); * the list of direct function calls without iteration. */ static inline int -nl_parse_header(void *hdr, int len, const struct nlhdr_parser *parser, +nl_parse_header(void *hdr, uint32_t len, const struct nlhdr_parser *parser, struct nl_pstate *npt, void *target) { int error; if (__predict_false(len < parser->nl_hdr_off)) { + void *tmp_hdr; + if (npt->strict) { - nlmsg_report_err_msg(npt, "header too short: expected %d, got %d", + nlmsg_report_err_msg(npt, + "header too short: expected %d, got %d", parser->nl_hdr_off, len); return (EINVAL); } - /* Compat with older applications: pretend there's a full header */ - void *tmp_hdr = npt_alloc(npt, parser->nl_hdr_off); + /* + * Compatibility with older applications: + * pretend there's a full header. + */ + tmp_hdr = npt_alloc(npt, parser->nl_hdr_off); if (tmp_hdr == NULL) return (EINVAL); memcpy(tmp_hdr, hdr, len); @@ -238,7 +258,7 @@ nl_parse_header(void *hdr, int len, const struct nlhdr_parser *parser, return (EINVAL); /* Extract fields first */ - for (int i = 0; i < parser->fp_size; i++) { + for (u_int i = 0; i < parser->fp_size; i++) { const struct nlfield_parser *fp = &parser->fp[i]; void *src = (char *)hdr + fp->off_in; void *dst = (char *)target + fp->off_out; @@ -248,9 +268,9 @@ nl_parse_header(void *hdr, int len, const struct nlhdr_parser *parser, return (error); } - struct nlattr *nla_head = (struct nlattr *)((char *)hdr + parser->nl_hdr_off); - error = nl_parse_attrs_raw(nla_head, len - parser->nl_hdr_off, parser->np, - parser->np_size, npt, target); + error = nl_parse_attrs_raw( + (struct nlattr *)((char *)hdr + parser->nl_hdr_off), + len - parser->nl_hdr_off, parser->np, parser->np_size, npt, target); if (parser->post_parse != NULL && error == 0) { if (!parser->post_parse(target, npt)) @@ -264,10 +284,8 @@ static inline int nl_parse_nested(struct nlattr *nla, const struct nlhdr_parser *parser, struct nl_pstate *npt, void *target) { - struct nlattr *nla_head = (struct nlattr *)NLA_DATA(nla); - - return (nl_parse_attrs_raw(nla_head, NLA_DATA_LEN(nla), parser->np, - parser->np_size, npt, target)); + return (nl_parse_attrs_raw((struct nlattr *)NLA_DATA(nla), + NLA_DATA_LEN(nla), parser->np, parser->np_size, npt, target)); } /* @@ -283,30 +301,36 @@ nl_verify_parsers(const struct nlhdr_parser **parser, int count) for (int j = 0; j < p->np_size; j++) { MPASS(p->np[j].type > attr_type); attr_type = p->np[j].type; + + /* Recurse into nested objects. */ + if (p->np[j].cb == nlattr_get_nested || + p->np[j].cb == nlattr_get_nested_ptr) { + const struct nlhdr_parser *np = + (const struct nlhdr_parser *)p->np[j].arg; + nl_verify_parsers(&np, 1); + } } } #endif } void nl_verify_parsers(const struct nlhdr_parser **parser, int count); -#define NL_VERIFY_PARSERS(_p) nl_verify_parsers((_p), NL_ARRAY_LEN(_p)) +#define NL_VERIFY_PARSERS(_p) nl_verify_parsers((_p), nitems(_p)) static inline int nl_parse_nlmsg(struct nlmsghdr *hdr, const struct nlhdr_parser *parser, struct nl_pstate *npt, void *target) { - return (nl_parse_header(hdr + 1, hdr->nlmsg_len - sizeof(*hdr), parser, npt, target)); + return (nl_parse_header(hdr + 1, hdr->nlmsg_len - sizeof(*hdr), parser, + npt, target)); } static inline void -nl_get_attrs_bmask_nlmsg(struct nlmsghdr *hdr, const struct nlhdr_parser *parser, - struct nlattr_bmask *bm) +nl_get_attrs_bmask_nlmsg(struct nlmsghdr *hdr, + const struct nlhdr_parser *parser, struct nlattr_bmask *bm) { - struct nlattr *nla_head; - - nla_head = (struct nlattr *)((char *)(hdr + 1) + parser->nl_hdr_off); - int len = hdr->nlmsg_len - sizeof(*hdr) - parser->nl_hdr_off; - - nl_get_attrs_bmask_raw(nla_head, len, bm); + nl_get_attrs_bmask_raw( + (struct nlattr *)((char *)(hdr + 1) + parser->nl_hdr_off), + hdr->nlmsg_len - sizeof(*hdr) - parser->nl_hdr_off, bm); } #endif diff --git a/lib/libc/include/generic-freebsd/netlink/netlink_message_writer.h b/lib/libc/include/generic-freebsd/netlink/netlink_message_writer.h index 1faa47f31601..715185469e63 100644 --- a/lib/libc/include/generic-freebsd/netlink/netlink_message_writer.h +++ b/lib/libc/include/generic-freebsd/netlink/netlink_message_writer.h @@ -37,62 +37,45 @@ * It is not meant to be included directly */ -struct mbuf; +struct nl_buf; struct nl_writer; -typedef bool nl_writer_cb(struct nl_writer *nw, void *buf, int buflen, int cnt); +typedef bool nl_writer_cb(struct nl_writer *nw); struct nl_writer { - int alloc_len; /* allocated buffer length */ - int offset; /* offset from the start of the buffer */ - struct nlmsghdr *hdr; /* Pointer to the currently-filled msg */ - char *data; /* pointer to the contiguous storage */ - void *_storage; /* Underlying storage pointer */ - nl_writer_cb *cb; /* Callback to flush data */ + struct nl_buf *buf; /* Underlying storage pointer */ + struct nlmsghdr *hdr; /* Pointer to the currently-filled msg */ + nl_writer_cb *cb; /* Callback to flush data */ union { - void *ptr; + struct nlpcb *nlp; struct { uint16_t proto; uint16_t id; + int priv; } group; - } arg; - int num_messages; /* Number of messages in the buffer */ - int malloc_flag; /* M_WAITOK or M_NOWAIT */ - uint8_t writer_type; /* NS_WRITER_TYPE_* */ - uint8_t writer_target; /* NS_WRITER_TARGET_* */ - bool ignore_limit; /* If true, ignores RCVBUF limit */ - bool enomem; /* True if ENOMEM occured */ - bool suppress_ack; /* If true, don't send NLMSG_ERR */ + }; + u_int num_messages; /* Number of messages in the buffer */ + int malloc_flag; /* M_WAITOK or M_NOWAIT */ + bool ignore_limit; /* If true, ignores RCVBUF limit */ + bool enomem; /* True if ENOMEM occured */ + bool suppress_ack; /* If true, don't send NLMSG_ERR */ }; -#define NS_WRITER_TARGET_SOCKET 0 -#define NS_WRITER_TARGET_GROUP 1 -#define NS_WRITER_TARGET_CHAIN 2 - -#define NS_WRITER_TYPE_MBUF 0 -#define NS_WRITER_TYPE_BUF 1 -#define NS_WRITER_TYPE_LBUF 2 -#define NS_WRITER_TYPE_MBUFC 3 -#define NS_WRITER_TYPE_STUB 4 - #define NLMSG_SMALL 128 #define NLMSG_LARGE 2048 /* Message and attribute writing */ - -struct nlpcb; - #if defined(NETLINK) || defined(NETLINK_MODULE) /* Provide optimized calls to the functions inside the same linking unit */ -bool _nlmsg_get_unicast_writer(struct nl_writer *nw, int expected_size, struct nlpcb *nlp); -bool _nlmsg_get_group_writer(struct nl_writer *nw, int expected_size, int proto, int group_id); -bool _nlmsg_get_chain_writer(struct nl_writer *nw, int expected_size, struct mbuf **pm); +bool _nl_writer_unicast(struct nl_writer *, size_t, struct nlpcb *nlp, bool); +bool _nl_writer_group(struct nl_writer *, size_t, uint16_t, uint16_t, int, + bool); bool _nlmsg_flush(struct nl_writer *nw); void _nlmsg_ignore_limit(struct nl_writer *nw); -bool _nlmsg_refill_buffer(struct nl_writer *nw, int required_size); -bool _nlmsg_add(struct nl_writer *nw, uint32_t portid, uint32_t seq, uint16_t type, - uint16_t flags, uint32_t len); +bool _nlmsg_refill_buffer(struct nl_writer *nw, size_t required_len); +bool _nlmsg_add(struct nl_writer *nw, uint32_t portid, uint32_t seq, + uint16_t type, uint16_t flags, uint32_t len); bool _nlmsg_end(struct nl_writer *nw); void _nlmsg_abort(struct nl_writer *nw); @@ -100,21 +83,17 @@ bool _nlmsg_end_dump(struct nl_writer *nw, int error, struct nlmsghdr *hdr); static inline bool -nlmsg_get_unicast_writer(struct nl_writer *nw, int expected_size, struct nlpcb *nlp) -{ - return (_nlmsg_get_unicast_writer(nw, expected_size, nlp)); -} - -static inline bool -nlmsg_get_group_writer(struct nl_writer *nw, int expected_size, int proto, int group_id) +nl_writer_unicast(struct nl_writer *nw, size_t size, struct nlpcb *nlp, + bool waitok) { - return (_nlmsg_get_group_writer(nw, expected_size, proto, group_id)); + return (_nl_writer_unicast(nw, size, nlp, waitok)); } static inline bool -nlmsg_get_chain_writer(struct nl_writer *nw, int expected_size, struct mbuf **pm) +nl_writer_group(struct nl_writer *nw, size_t size, uint16_t proto, + uint16_t group_id, int priv, bool waitok) { - return (_nlmsg_get_chain_writer(nw, expected_size, pm)); + return (_nl_writer_group(nw, size, proto, group_id, priv, waitok)); } static inline bool @@ -130,7 +109,7 @@ nlmsg_ignore_limit(struct nl_writer *nw) } static inline bool -nlmsg_refill_buffer(struct nl_writer *nw, int required_size) +nlmsg_refill_buffer(struct nl_writer *nw, size_t required_size) { return (_nlmsg_refill_buffer(nw, required_size)); } @@ -163,15 +142,15 @@ nlmsg_end_dump(struct nl_writer *nw, int error, struct nlmsghdr *hdr) #else /* Provide access to the functions via netlink_glue.c */ -bool nlmsg_get_unicast_writer(struct nl_writer *nw, int expected_size, struct nlpcb *nlp); -bool nlmsg_get_group_writer(struct nl_writer *nw, int expected_size, int proto, int group_id); -bool nlmsg_get_chain_writer(struct nl_writer *nw, int expected_size, struct mbuf **pm); +bool nl_writer_unicast(struct nl_writer *, size_t, struct nlpcb *, bool waitok); +bool nl_writer_group(struct nl_writer *, size_t, uint16_t, uint16_t, int, + bool waitok); bool nlmsg_flush(struct nl_writer *nw); void nlmsg_ignore_limit(struct nl_writer *nw); -bool nlmsg_refill_buffer(struct nl_writer *nw, int required_size); -bool nlmsg_add(struct nl_writer *nw, uint32_t portid, uint32_t seq, uint16_t type, - uint16_t flags, uint32_t len); +bool nlmsg_refill_buffer(struct nl_writer *nw, size_t required_size); +bool nlmsg_add(struct nl_writer *nw, uint32_t portid, uint32_t seq, + uint16_t type, uint16_t flags, uint32_t len); bool nlmsg_end(struct nl_writer *nw); void nlmsg_abort(struct nl_writer *nw); @@ -186,18 +165,12 @@ nlmsg_reply(struct nl_writer *nw, const struct nlmsghdr *hdr, int payload_len) hdr->nlmsg_flags, payload_len)); } -#define nlmsg_data(_hdr) ((void *)((_hdr) + 1)) - /* * KPI similar to mtodo(): * current (uncompleted) header is guaranteed to be contiguous, * but can be reallocated, thus pointers may need to be readjusted. */ -static inline int -nlattr_save_offset(const struct nl_writer *nw) -{ - return (nw->offset - ((char *)nw->hdr - nw->data)); -} +u_int nlattr_save_offset(const struct nl_writer *nw); static inline void * _nlattr_restore_offset(const struct nl_writer *nw, int off) @@ -213,22 +186,7 @@ nlattr_set_len(const struct nl_writer *nw, int off) nla->nla_len = nlattr_save_offset(nw) - off; } -static inline void * -nlmsg_reserve_data_raw(struct nl_writer *nw, size_t sz) -{ - sz = NETLINK_ALIGN(sz); - - if (__predict_false(nw->offset + sz > nw->alloc_len)) { - if (!nlmsg_refill_buffer(nw, sz)) - return (NULL); - } - - void *data_ptr = &nw->data[nw->offset]; - nw->offset += sz; - bzero(data_ptr, sz); - - return (data_ptr); -} +void *nlmsg_reserve_data_raw(struct nl_writer *nw, size_t sz); #define nlmsg_reserve_object(_ns, _t) ((_t *)nlmsg_reserve_data_raw(_ns, sizeof(_t))) #define nlmsg_reserve_data(_ns, _sz, _t) ((_t *)nlmsg_reserve_data_raw(_ns, _sz)) @@ -258,109 +216,95 @@ _nlmsg_reserve_attr(struct nl_writer *nw, uint16_t nla_type, uint16_t sz) } #define nlmsg_reserve_attr(_ns, _at, _t) ((_t *)_nlmsg_reserve_attr(_ns, _at, NLA_ALIGN(sizeof(_t)))) -static inline bool -nlattr_add(struct nl_writer *nw, int attr_type, int attr_len, const void *data) -{ - int required_len = NLA_ALIGN(attr_len + sizeof(struct nlattr)); - - if (__predict_false(nw->offset + required_len > nw->alloc_len)) { - if (!nlmsg_refill_buffer(nw, required_len)) - return (false); - } - - struct nlattr *nla = (struct nlattr *)(&nw->data[nw->offset]); - - nla->nla_len = attr_len + sizeof(struct nlattr); - nla->nla_type = attr_type; - if (attr_len > 0) { - if ((attr_len % 4) != 0) { - /* clear padding bytes */ - bzero((char *)nla + required_len - 4, 4); - } - memcpy((nla + 1), data, attr_len); - } - nw->offset += required_len; - return (true); -} +bool nlattr_add(struct nl_writer *nw, uint16_t attr_type, uint16_t attr_len, + const void *data); static inline bool nlattr_add_raw(struct nl_writer *nw, const struct nlattr *nla_src) { - int attr_len = nla_src->nla_len - sizeof(struct nlattr); + MPASS(nla_src->nla_len >= sizeof(struct nlattr)); - MPASS(attr_len >= 0); + return (nlattr_add(nw, nla_src->nla_type, + nla_src->nla_len - sizeof(struct nlattr), + (const void *)(nla_src + 1))); +} - return (nlattr_add(nw, nla_src->nla_type, attr_len, (const void *)(nla_src + 1))); +static inline bool +nlattr_add_bool(struct nl_writer *nw, uint16_t attrtype, bool value) +{ + return (nlattr_add(nw, attrtype, sizeof(bool), &value)); } static inline bool -nlattr_add_u8(struct nl_writer *nw, int attrtype, uint8_t value) +nlattr_add_u8(struct nl_writer *nw, uint16_t attrtype, uint8_t value) { return (nlattr_add(nw, attrtype, sizeof(uint8_t), &value)); } static inline bool -nlattr_add_u16(struct nl_writer *nw, int attrtype, uint16_t value) +nlattr_add_u16(struct nl_writer *nw, uint16_t attrtype, uint16_t value) { return (nlattr_add(nw, attrtype, sizeof(uint16_t), &value)); } static inline bool -nlattr_add_u32(struct nl_writer *nw, int attrtype, uint32_t value) +nlattr_add_u32(struct nl_writer *nw, uint16_t attrtype, uint32_t value) { return (nlattr_add(nw, attrtype, sizeof(uint32_t), &value)); } static inline bool -nlattr_add_u64(struct nl_writer *nw, int attrtype, uint64_t value) +nlattr_add_u64(struct nl_writer *nw, uint16_t attrtype, uint64_t value) { return (nlattr_add(nw, attrtype, sizeof(uint64_t), &value)); } static inline bool -nlattr_add_s8(struct nl_writer *nw, int attrtype, int8_t value) +nlattr_add_s8(struct nl_writer *nw, uint16_t attrtype, int8_t value) { return (nlattr_add(nw, attrtype, sizeof(int8_t), &value)); } static inline bool -nlattr_add_s16(struct nl_writer *nw, int attrtype, int16_t value) +nlattr_add_s16(struct nl_writer *nw, uint16_t attrtype, int16_t value) { return (nlattr_add(nw, attrtype, sizeof(int16_t), &value)); } static inline bool -nlattr_add_s32(struct nl_writer *nw, int attrtype, int32_t value) +nlattr_add_s32(struct nl_writer *nw, uint16_t attrtype, int32_t value) { return (nlattr_add(nw, attrtype, sizeof(int32_t), &value)); } static inline bool -nlattr_add_s64(struct nl_writer *nw, int attrtype, int64_t value) +nlattr_add_s64(struct nl_writer *nw, uint16_t attrtype, int64_t value) { return (nlattr_add(nw, attrtype, sizeof(int64_t), &value)); } static inline bool -nlattr_add_flag(struct nl_writer *nw, int attrtype) +nlattr_add_flag(struct nl_writer *nw, uint16_t attrtype) { return (nlattr_add(nw, attrtype, 0, NULL)); } static inline bool -nlattr_add_string(struct nl_writer *nw, int attrtype, const char *str) +nlattr_add_string(struct nl_writer *nw, uint16_t attrtype, const char *str) { return (nlattr_add(nw, attrtype, strlen(str) + 1, str)); } static inline bool -nlattr_add_in_addr(struct nl_writer *nw, int attrtype, const struct in_addr *in) +nlattr_add_in_addr(struct nl_writer *nw, uint16_t attrtype, + const struct in_addr *in) { return (nlattr_add(nw, attrtype, sizeof(*in), in)); } static inline bool -nlattr_add_in6_addr(struct nl_writer *nw, int attrtype, const struct in6_addr *in6) +nlattr_add_in6_addr(struct nl_writer *nw, uint16_t attrtype, + const struct in6_addr *in6) { return (nlattr_add(nw, attrtype, sizeof(*in6), in6)); } diff --git a/lib/libc/include/generic-freebsd/netlink/netlink_snl.h b/lib/libc/include/generic-freebsd/netlink/netlink_snl.h index 5cb36f60df0e..2b104c77b421 100644 --- a/lib/libc/include/generic-freebsd/netlink/netlink_snl.h +++ b/lib/libc/include/generic-freebsd/netlink/netlink_snl.h @@ -31,6 +31,12 @@ * Simple Netlink Library */ +#include +#include + +#include +#include + #include #include #include @@ -41,11 +47,6 @@ #include #include -#include -#include -#include -#include - #define _roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) #define NETLINK_ALIGN_SIZE sizeof(uint32_t) @@ -68,8 +69,6 @@ ((char *)NLA_NEXT(_attr) <= _NLA_END(_start, _len)); \ _attr = NLA_NEXT(_attr)) -#define NL_ARRAY_LEN(_a) (sizeof(_a) / sizeof((_a)[0])) - struct linear_buffer { char *base; /* Base allocated memory pointer */ uint32_t offset; /* Currently used offset */ @@ -133,6 +132,7 @@ struct snl_field_parser { uint16_t off_out; snl_parse_field_f *cb; }; +static const struct snl_field_parser snl_f_p_empty[] = {}; typedef bool snl_parse_attr_f(struct snl_state *ss, struct nlattr *attr, const void *arg, void *target); @@ -166,8 +166,8 @@ static const struct snl_hdr_parser _name = { \ .out_size = _sz_out, \ .fp = &((_fp)[0]), \ .np = &((_np)[0]), \ - .fp_size = NL_ARRAY_LEN(_fp), \ - .np_size = NL_ARRAY_LEN(_np), \ + .fp_size = nitems(_fp), \ + .np_size = nitems(_np), \ .cb_post = _cb, \ } @@ -179,7 +179,7 @@ static const struct snl_hdr_parser _name = { \ .in_hdr_size = _sz_h_in, \ .out_size = _sz_out, \ .fp = &((_fp)[0]), \ - .fp_size = NL_ARRAY_LEN(_fp), \ + .fp_size = nitems(_fp), \ .cb_post = _cb, \ } @@ -190,7 +190,7 @@ static const struct snl_hdr_parser _name = { \ static const struct snl_hdr_parser _name = { \ .out_size = _sz_out, \ .np = &((_np)[0]), \ - .np_size = NL_ARRAY_LEN(_np), \ + .np_size = nitems(_np), \ .cb_post = _cb, \ } @@ -240,14 +240,13 @@ snl_clear_lb(struct snl_state *ss) static void snl_free(struct snl_state *ss) { - if (ss->init_done) { + if (ss->init_done) close(ss->fd); - if (ss->buf != NULL) - free(ss->buf); - if (ss->lb != NULL) { - snl_clear_lb(ss); - lb_free(ss->lb); - } + if (ss->buf != NULL) + free(ss->buf); + if (ss->lb != NULL) { + snl_clear_lb(ss); + lb_free(ss->lb); } } @@ -290,6 +289,16 @@ snl_init(struct snl_state *ss, int netlink_family) return (true); } +static inline bool +snl_clone(struct snl_state *ss, const struct snl_state *orig) +{ + *ss = (struct snl_state){ + .fd = orig->fd, + .init_done = false, + }; + return ((ss->lb = lb_init(SCRATCH_BUFFER_SIZE)) != NULL); +} + static inline bool snl_send(struct snl_state *ss, void *data, int sz) { @@ -418,7 +427,7 @@ snl_verify_parsers(const struct snl_hdr_parser **parser, int count) } } } -#define SNL_VERIFY_PARSERS(_p) snl_verify_parsers((_p), NL_ARRAY_LEN(_p)) +#define SNL_VERIFY_PARSERS(_p) snl_verify_parsers((_p), nitems(_p)) static const struct snl_attr_parser * find_parser(const struct snl_attr_parser *ps, int pslen, int key) @@ -526,6 +535,29 @@ snl_attr_get_flag(struct snl_state *ss __unused, struct nlattr *nla, const void return (false); } +static inline bool +snl_attr_get_bytes(struct snl_state *ss __unused, struct nlattr *nla, const void *arg, + void *target) +{ + if ((size_t)NLA_DATA_LEN(nla) != (size_t)arg) + return (false); + + memcpy(target, NLA_DATA_CONST(nla), (size_t)arg); + + return (true); +} + +static inline bool +snl_attr_get_bool(struct snl_state *ss __unused, struct nlattr *nla, + const void *arg __unused, void *target) +{ + if (NLA_DATA_LEN(nla) == sizeof(bool)) { + *((bool *)target) = *((const bool *)NLA_DATA_CONST(nla)); + return (true); + } + return (false); +} + static inline bool snl_attr_get_uint8(struct snl_state *ss __unused, struct nlattr *nla, const void *arg __unused, void *target) @@ -1086,20 +1118,22 @@ snl_reserve_msg_data_raw(struct snl_writer *nw, size_t sz) #define snl_reserve_msg_object(_ns, _t) ((_t *)snl_reserve_msg_data_raw(_ns, sizeof(_t))) #define snl_reserve_msg_data(_ns, _sz, _t) ((_t *)snl_reserve_msg_data_raw(_ns, _sz)) -static inline void * -_snl_reserve_msg_attr(struct snl_writer *nw, uint16_t nla_type, uint16_t sz) +static inline struct nlattr * +snl_reserve_msg_attr_raw(struct snl_writer *nw, uint16_t nla_type, uint16_t sz) { - sz += sizeof(struct nlattr); + struct nlattr *nla; - struct nlattr *nla = snl_reserve_msg_data(nw, sz, struct nlattr); + sz += sizeof(struct nlattr); + nla = snl_reserve_msg_data(nw, sz, struct nlattr); if (__predict_false(nla == NULL)) return (NULL); nla->nla_type = nla_type; nla->nla_len = sz; - return ((void *)(nla + 1)); + return (nla); } -#define snl_reserve_msg_attr(_ns, _at, _t) ((_t *)_snl_reserve_msg_attr(_ns, _at, sizeof(_t))) +#define snl_reserve_msg_attr(_ns, _at, _t) \ + ((_t *)(snl_reserve_msg_attr_raw(_ns, _at, sizeof(_t)) + 1)) static inline bool snl_add_msg_attr(struct snl_writer *nw, int attr_type, int attr_len, const void *data) @@ -1136,6 +1170,12 @@ snl_add_msg_attr_raw(struct snl_writer *nw, const struct nlattr *nla_src) return (snl_add_msg_attr(nw, nla_src->nla_type, attr_len, (const void *)(nla_src + 1))); } +static inline bool +snl_add_msg_attr_bool(struct snl_writer *nw, int attrtype, bool value) +{ + return (snl_add_msg_attr(nw, attrtype, sizeof(bool), &value)); +} + static inline bool snl_add_msg_attr_u8(struct snl_writer *nw, int attrtype, uint8_t value) { @@ -1233,9 +1273,13 @@ snl_end_attr_nested(const struct snl_writer *nw, int off) static inline struct nlmsghdr * snl_create_msg_request(struct snl_writer *nw, int nlmsg_type) { + struct nlmsghdr *hdr; + assert(nw->hdr == NULL); - struct nlmsghdr *hdr = snl_reserve_msg_object(nw, struct nlmsghdr); + if (__predict_false((hdr = + snl_reserve_msg_object(nw, struct nlmsghdr)) == NULL)) + return (NULL); hdr->nlmsg_type = nlmsg_type; hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; nw->hdr = hdr; @@ -1283,9 +1327,4 @@ snl_send_msgs(struct snl_writer *nw) return (snl_send(nw->ss, nw->base, offset)); } -static const struct snl_hdr_parser *snl_all_core_parsers[] = { - &snl_errmsg_parser, &snl_donemsg_parser, - &_nla_bit_parser, &_nla_bitset_parser, -}; - #endif \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/netlink/netlink_snl_generic.h b/lib/libc/include/generic-freebsd/netlink/netlink_snl_generic.h index bb347921d9ff..05c7ce1b5a68 100644 --- a/lib/libc/include/generic-freebsd/netlink/netlink_snl_generic.h +++ b/lib/libc/include/generic-freebsd/netlink/netlink_snl_generic.h @@ -33,16 +33,24 @@ /* Genetlink helpers */ static inline struct nlmsghdr * -snl_create_genl_msg_request(struct snl_writer *nw, int genl_family, uint8_t genl_cmd) +snl_create_genl_msg_request(struct snl_writer *nw, uint16_t genl_family, + uint8_t genl_cmd) { + struct nlmsghdr *hdr; + struct genlmsghdr *ghdr; + assert(nw->hdr == NULL); - struct nlmsghdr *hdr = snl_reserve_msg_object(nw, struct nlmsghdr); + hdr = snl_reserve_msg_object(nw, struct nlmsghdr); + if (__predict_false(hdr == NULL)) + return (NULL); hdr->nlmsg_type = genl_family; hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; - nw->hdr = hdr; - struct genlmsghdr *ghdr = snl_reserve_msg_object(nw, struct genlmsghdr); + ghdr = snl_reserve_msg_object(nw, struct genlmsghdr); + if (__predict_false(ghdr == NULL)) + return (NULL); ghdr->cmd = genl_cmd; + nw->hdr = hdr; return (hdr); } @@ -52,37 +60,52 @@ static struct snl_field_parser snl_fp_genl[] = {}; #define SNL_DECLARE_GENL_PARSER(_name, _np) SNL_DECLARE_PARSER(_name,\ struct genlmsghdr, snl_fp_genl, _np) -struct snl_genl_ctrl_mcast_group { +struct _snl_genl_ctrl_mcast_group { uint32_t mcast_grp_id; - char *mcast_grp_name; + const char *mcast_grp_name; }; -struct snl_genl_ctrl_mcast_groups { +struct _snl_genl_ctrl_mcast_groups { uint32_t num_groups; - struct snl_genl_ctrl_mcast_group **groups; + struct _snl_genl_ctrl_mcast_group **groups; }; -#define _OUT(_field) offsetof(struct snl_genl_ctrl_mcast_group, _field) +#define _OUT(_field) offsetof(struct _snl_genl_ctrl_mcast_group, _field) static struct snl_attr_parser _nla_p_getmc[] = { - { .type = CTRL_ATTR_MCAST_GRP_NAME, .off = _OUT(mcast_grp_name), .cb = snl_attr_get_string }, - { .type = CTRL_ATTR_MCAST_GRP_ID, .off = _OUT(mcast_grp_id), .cb = snl_attr_get_uint32 }, + { + .type = CTRL_ATTR_MCAST_GRP_NAME, + .off = _OUT(mcast_grp_name), + .cb = snl_attr_get_string, + }, + { + .type = CTRL_ATTR_MCAST_GRP_ID, + .off = _OUT(mcast_grp_id), + .cb = snl_attr_get_uint32, + }, }; #undef _OUT SNL_DECLARE_ATTR_PARSER_EXT(_genl_ctrl_mc_parser, - sizeof(struct snl_genl_ctrl_mcast_group), - _nla_p_getmc, NULL); + sizeof(struct _snl_genl_ctrl_mcast_group), _nla_p_getmc, NULL); struct _getfamily_attrs { uint16_t family_id; - char *family_name; - struct snl_genl_ctrl_mcast_groups mcast_groups; + const char *family_name; + struct _snl_genl_ctrl_mcast_groups mcast_groups; }; #define _IN(_field) offsetof(struct genlmsghdr, _field) #define _OUT(_field) offsetof(struct _getfamily_attrs, _field) static struct snl_attr_parser _nla_p_getfam[] = { - { .type = CTRL_ATTR_FAMILY_ID , .off = _OUT(family_id), .cb = snl_attr_get_uint16 }, - { .type = CTRL_ATTR_FAMILY_NAME, .off = _OUT(family_name), .cb = snl_attr_get_string }, + { + .type = CTRL_ATTR_FAMILY_ID, + .off = _OUT(family_id), + .cb = snl_attr_get_uint16, + }, + { + .type = CTRL_ATTR_FAMILY_NAME, + .off = _OUT(family_name), + .cb = snl_attr_get_string, + }, { .type = CTRL_ATTR_MCAST_GROUPS, .off = _OUT(mcast_groups), @@ -95,7 +118,7 @@ static struct snl_attr_parser _nla_p_getfam[] = { SNL_DECLARE_GENL_PARSER(_genl_ctrl_getfam_parser, _nla_p_getfam); static bool -snl_get_genl_family_info(struct snl_state *ss, const char *family_name, +_snl_get_genl_family_info(struct snl_state *ss, const char *family_name, struct _getfamily_attrs *attrs) { struct snl_writer nw; @@ -104,7 +127,7 @@ snl_get_genl_family_info(struct snl_state *ss, const char *family_name, memset(attrs, 0, sizeof(*attrs)); snl_init_writer(ss, &nw); - hdr = snl_create_genl_msg_request(&nw, GENL_ID_CTRL, CTRL_CMD_GETFAMILY); + snl_create_genl_msg_request(&nw, GENL_ID_CTRL, CTRL_CMD_GETFAMILY); snl_add_msg_attr_string(&nw, CTRL_ATTR_FAMILY_NAME, family_name); if ((hdr = snl_finalize_msg(&nw)) == NULL || !snl_send_message(ss, hdr)) return (false); @@ -123,12 +146,30 @@ snl_get_genl_family(struct snl_state *ss, const char *family_name) { struct _getfamily_attrs attrs = {}; - snl_get_genl_family_info(ss, family_name, &attrs); + if (__predict_false(!_snl_get_genl_family_info(ss, family_name, + &attrs))) + return (0); return (attrs.family_id); } -static const struct snl_hdr_parser *snl_all_genl_parsers[] = { - &_genl_ctrl_getfam_parser, &_genl_ctrl_mc_parser, -}; +static inline uint16_t +snl_get_genl_mcast_group(struct snl_state *ss, const char *family_name, + const char *group_name, uint16_t *family_id) +{ + struct _getfamily_attrs attrs = {}; + + if (__predict_false(!_snl_get_genl_family_info(ss, family_name, + &attrs))) + return (0); + if (attrs.family_id == 0) + return (0); + if (family_id != NULL) + *family_id = attrs.family_id; + for (u_int i = 0; i < attrs.mcast_groups.num_groups; i++) + if (strcmp(attrs.mcast_groups.groups[i]->mcast_grp_name, + group_name) == 0) + return (attrs.mcast_groups.groups[i]->mcast_grp_id); + return (0); +} #endif \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/netlink/netlink_snl_route_parsers.h b/lib/libc/include/generic-freebsd/netlink/netlink_snl_route_parsers.h index 5499092ffc0d..dc401d9b63ff 100644 --- a/lib/libc/include/generic-freebsd/netlink/netlink_snl_route_parsers.h +++ b/lib/libc/include/generic-freebsd/netlink/netlink_snl_route_parsers.h @@ -389,11 +389,4 @@ _cb_p_nh(struct snl_state *ss __unused, void *_target) SNL_DECLARE_PARSER_EXT(snl_nhmsg_parser, sizeof(struct nhmsg), sizeof(struct snl_parsed_nhop), _fp_p_nh, _nla_p_nh, _cb_p_nh); -static const struct snl_hdr_parser *snl_all_route_parsers[] = { - &_metrics_mp_nh_parser, &_mpath_nh_parser, &_metrics_parser, &snl_rtm_route_parser, - &_link_fbsd_parser, &snl_rtm_link_parser, &snl_rtm_link_parser_simple, - &_neigh_fbsd_parser, &snl_rtm_neigh_parser, - &_addr_fbsd_parser, &snl_rtm_addr_parser, &_nh_fbsd_parser, &snl_nhmsg_parser, -}; - #endif \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/netlink/netlink_var.h b/lib/libc/include/generic-freebsd/netlink/netlink_var.h index 2f47cc85222a..5fc67229b981 100644 --- a/lib/libc/include/generic-freebsd/netlink/netlink_var.h +++ b/lib/libc/include/generic-freebsd/netlink/netlink_var.h @@ -43,33 +43,32 @@ struct ucred; -struct nl_io_queue { - STAILQ_HEAD(, mbuf) head; - int length; - int hiwat; +struct nl_buf { + TAILQ_ENTRY(nl_buf) tailq; + u_int buflen; + u_int datalen; + u_int offset; + char data[]; }; #define NLP_MAX_GROUPS 128 +BITSET_DEFINE(nl_groups, NLP_MAX_GROUPS); struct nlpcb { struct socket *nl_socket; - uint64_t nl_groups[NLP_MAX_GROUPS / 64]; + struct nl_groups nl_groups; uint32_t nl_port; uint32_t nl_flags; uint32_t nl_process_id; int nl_proto; - bool nl_active; bool nl_bound; bool nl_task_pending; bool nl_tx_blocked; /* No new requests accepted */ bool nl_linux; /* true if running under compat */ bool nl_unconstrained_vnet; /* true if running under VNET jail (or without jail) */ bool nl_need_thread_setup; - struct nl_io_queue rx_queue; - struct nl_io_queue tx_queue; struct taskqueue *nl_taskqueue; struct task nl_task; - struct ucred *nl_cred; /* Copy of nl_socket->so_cred */ uint64_t nl_dropped_bytes; uint64_t nl_dropped_messages; CK_LIST_ENTRY(nlpcb) nl_next; @@ -96,31 +95,19 @@ struct nlpcb { SYSCTL_DECL(_net_netlink); SYSCTL_DECL(_net_netlink_debug); -struct nl_io { - struct callout callout; - struct mbuf *head; - struct mbuf *last; - int64_t length; -}; - struct nl_control { CK_LIST_HEAD(nl_pid_head, nlpcb) ctl_port_head; CK_LIST_HEAD(nlpcb_head, nlpcb) ctl_pcb_head; CK_LIST_ENTRY(nl_control) ctl_next; - struct nl_io ctl_io; struct rmlock ctl_lock; }; -VNET_DECLARE(struct nl_control *, nl_ctl); +VNET_DECLARE(struct nl_control, nl_ctl); #define V_nl_ctl VNET(nl_ctl) - struct sockaddr_nl; struct sockaddr; struct nlmsghdr; -/* netlink_module.c */ -struct nl_control *vnet_nl_ctl_init(void); - int nl_verify_proto(int proto); const char *nl_get_proto_name(int proto); @@ -133,57 +120,34 @@ struct nl_proto_handler { extern struct nl_proto_handler *nl_handlers; /* netlink_domain.c */ -void nl_send_group(struct mbuf *m, int cnt, int proto, int group_id); +bool nl_send_group(struct nl_writer *); +void nl_clear_group(u_int); void nl_osd_register(void); void nl_osd_unregister(void); void nl_set_thread_nlp(struct thread *td, struct nlpcb *nlp); /* netlink_io.c */ -#define NL_IOF_UNTRANSLATED 0x01 -#define NL_IOF_IGNORE_LIMIT 0x02 -bool nl_send_one(struct mbuf *m, struct nlpcb *nlp, int cnt, int io_flags); +bool nl_send(struct nl_writer *, struct nlpcb *); void nlmsg_ack(struct nlpcb *nlp, int error, struct nlmsghdr *nlmsg, struct nl_pstate *npt); void nl_on_transmit(struct nlpcb *nlp); -void nl_init_io(struct nlpcb *nlp); -void nl_free_io(struct nlpcb *nlp); void nl_taskqueue_handler(void *_arg, int pending); -int nl_receive_async(struct mbuf *m, struct socket *so); +void nl_schedule_taskqueue(struct nlpcb *nlp); void nl_process_receive_locked(struct nlpcb *nlp); void nl_set_source_metadata(struct mbuf *m, int num_messages); -void nl_add_msg_info(struct mbuf *m); - -/* netlink_message_writer.c */ -void nl_init_msg_zone(void); -void nl_destroy_msg_zone(void); - -/* netlink_generic.c */ -struct genl_family { - const char *family_name; - uint16_t family_hdrsize; - uint16_t family_id; - uint16_t family_version; - uint16_t family_attr_max; - uint16_t family_cmd_size; - uint16_t family_num_groups; - struct genl_cmd *family_cmds; -}; - -struct genl_group { - struct genl_family *group_family; - const char *group_name; -}; - -struct genl_family *genl_get_family(uint32_t family_id); -struct genl_group *genl_get_group(uint32_t group_id); +struct nl_buf *nl_buf_alloc(size_t len, int mflag); +void nl_buf_free(struct nl_buf *nb); #define MAX_FAMILIES 20 #define MAX_GROUPS 64 #define MIN_GROUP_NUM 48 +#define CTRL_FAMILY_ID 0 #define CTRL_FAMILY_NAME "nlctrl" +#define CTRL_GROUP_ID 0 +#define CTRL_GROUP_NAME "notify" struct ifnet; struct nl_parsed_link; @@ -194,14 +158,15 @@ struct nl_pstate; struct nl_function_wrapper { bool (*nlmsg_add)(struct nl_writer *nw, uint32_t portid, uint32_t seq, uint16_t type, uint16_t flags, uint32_t len); - bool (*nlmsg_refill_buffer)(struct nl_writer *nw, int required_len); + bool (*nlmsg_refill_buffer)(struct nl_writer *nw, size_t required_len); bool (*nlmsg_flush)(struct nl_writer *nw); bool (*nlmsg_end)(struct nl_writer *nw); void (*nlmsg_abort)(struct nl_writer *nw); void (*nlmsg_ignore_limit)(struct nl_writer *nw); - bool (*nlmsg_get_unicast_writer)(struct nl_writer *nw, int size, struct nlpcb *nlp); - bool (*nlmsg_get_group_writer)(struct nl_writer *nw, int size, int protocol, int group_id); - bool (*nlmsg_get_chain_writer)(struct nl_writer *nw, int size, struct mbuf **pm); + bool (*nl_writer_unicast)(struct nl_writer *nw, size_t size, + struct nlpcb *nlp, bool waitok); + bool (*nl_writer_group)(struct nl_writer *nw, size_t size, + uint16_t protocol, uint16_t group_id, int priv, bool waitok); bool (*nlmsg_end_dump)(struct nl_writer *nw, int error, struct nlmsghdr *hdr); int (*nl_modify_ifp_generic)(struct ifnet *ifp, struct nl_parsed_link *lattrs, const struct nlattr_bmask *bm, struct nl_pstate *npt); diff --git a/lib/libc/include/generic-freebsd/netlink/route/route.h b/lib/libc/include/generic-freebsd/netlink/route/route.h index 9f765853ede5..14bc246d8d9a 100644 --- a/lib/libc/include/generic-freebsd/netlink/route/route.h +++ b/lib/libc/include/generic-freebsd/netlink/route/route.h @@ -134,9 +134,10 @@ enum rt_scope_t { /* * Routing table identifiers. - * FreeBSD route table numbering starts from 0, where 0 is a valid default routing table. - * Indicating "all tables" via netlink can be done by not including RTA_TABLE attribute - * and keeping rtm_table=0 (compatibility) or setting RTA_TABLE value to RT_TABLE_UNSPEC. + * FreeBSD route table numbering starts from 0, where 0 is a valid default + * routing table. Indicating "all tables" via netlink can be done by not + * including RTA_TABLE attribute and keeping rtm_table=0 (compatibility) or + * setting RTA_TABLE value to RT_TABLE_UNSPEC. */ #define RT_TABLE_MAIN 0 /* RT_DEFAULT_FIB */ #define RT_TABLE_UNSPEC 0xFFFFFFFF /* RT_ALL_FIBS */ diff --git a/lib/libc/include/generic-freebsd/netlink/route/route_var.h b/lib/libc/include/generic-freebsd/netlink/route/route_var.h index bf039b524df7..fad06bc5da03 100644 --- a/lib/libc/include/generic-freebsd/netlink/route/route_var.h +++ b/lib/libc/include/generic-freebsd/netlink/route/route_var.h @@ -69,6 +69,7 @@ struct nl_parsed_link { char *ifla_cloner; char *ifla_ifalias; struct nlattr *ifla_idata; + struct nlattr *ifla_address; unsigned short ifi_type; int ifi_index; uint32_t ifla_link; diff --git a/lib/libc/include/generic-freebsd/netpfil/pf/pf.h b/lib/libc/include/generic-freebsd/netpfil/pf/pf.h index dcd427e9780b..da529a5b26e0 100644 --- a/lib/libc/include/generic-freebsd/netpfil/pf/pf.h +++ b/lib/libc/include/generic-freebsd/netpfil/pf/pf.h @@ -49,7 +49,7 @@ enum { PF_INOUT, PF_IN, PF_OUT }; enum { PF_PASS, PF_DROP, PF_SCRUB, PF_NOSCRUB, PF_NAT, PF_NONAT, PF_BINAT, PF_NOBINAT, PF_RDR, PF_NORDR, PF_SYNPROXY_DROP, PF_DEFER, - PF_MATCH }; + PF_MATCH, PF_AFRT, PF_RT }; enum { PF_RULESET_SCRUB, PF_RULESET_FILTER, PF_RULESET_NAT, PF_RULESET_BINAT, PF_RULESET_RDR, PF_RULESET_MAX }; enum { PF_OP_NONE, PF_OP_IRG, PF_OP_EQ, PF_OP_NE, PF_OP_LT, @@ -113,29 +113,38 @@ enum { #define PFTM_OTHER_FIRST_PACKET_VAL 60 /* First packet */ #define PFTM_OTHER_SINGLE_VAL 30 /* Unidirectional */ #define PFTM_OTHER_MULTIPLE_VAL 60 /* Bidirectional */ -#define PFTM_FRAG_VAL 30 /* Fragment expire */ +#define PFTM_FRAG_VAL 60 /* Fragment expire */ #define PFTM_INTERVAL_VAL 10 /* Expire interval */ #define PFTM_SRC_NODE_VAL 0 /* Source tracking */ #define PFTM_TS_DIFF_VAL 30 /* Allowed TS diff */ enum { PF_NOPFROUTE, PF_FASTROUTE, PF_ROUTETO, PF_DUPTO, PF_REPLYTO }; enum { PF_LIMIT_STATES, PF_LIMIT_SRC_NODES, PF_LIMIT_FRAGS, - PF_LIMIT_TABLE_ENTRIES, PF_LIMIT_MAX }; + PF_LIMIT_TABLE_ENTRIES, PF_LIMIT_ANCHORS, PF_LIMIT_ETH_ANCHORS, + PF_LIMIT_MAX }; #define PF_POOL_IDMASK 0x0f enum { PF_POOL_NONE, PF_POOL_BITMASK, PF_POOL_RANDOM, PF_POOL_SRCHASH, PF_POOL_ROUNDROBIN }; enum { PF_ADDR_ADDRMASK, PF_ADDR_NOROUTE, PF_ADDR_DYNIFTL, PF_ADDR_TABLE, PF_ADDR_URPFFAILED, - PF_ADDR_RANGE }; + PF_ADDR_RANGE, PF_ADDR_NONE }; #define PF_POOL_TYPEMASK 0x0f #define PF_POOL_STICKYADDR 0x20 +#define PF_POOL_ENDPI 0x40 +#define PF_POOL_IPV6NH 0x80 #define PF_WSCALE_FLAG 0x80 #define PF_WSCALE_MASK 0x0f +#define PF_POOL_DYNTYPE(_o) \ + ((((_o) & PF_POOL_TYPEMASK) == PF_POOL_ROUNDROBIN) || \ + (((_o) & PF_POOL_TYPEMASK) == PF_POOL_RANDOM) || \ + (((_o) & PF_POOL_TYPEMASK) == PF_POOL_SRCHASH)) + #define PF_LOG 0x01 #define PF_LOG_ALL 0x02 -#define PF_LOG_SOCKET_LOOKUP 0x04 +#define PF_LOG_USER 0x04 #define PF_LOG_FORCE 0x08 +#define PF_LOG_MATCHES 0x10 /* Reasons code for passing/dropping a packet */ #define PFRES_MATCH 0 /* Explicit match of a rule */ @@ -154,7 +163,8 @@ enum { PF_ADDR_ADDRMASK, PF_ADDR_NOROUTE, PF_ADDR_DYNIFTL, #define PFRES_SRCLIMIT 13 /* Source node/conn limit */ #define PFRES_SYNPROXY 14 /* SYN proxy */ #define PFRES_MAPFAILED 15 /* pf_map_addr() failed */ -#define PFRES_MAX 16 /* total+1 */ +#define PFRES_TRANSLATE 16 /* No translation address available */ +#define PFRES_MAX 17 /* total+1 */ #define PFRES_NAMES { \ "match", \ @@ -173,6 +183,7 @@ enum { PF_ADDR_ADDRMASK, PF_ADDR_NOROUTE, PF_ADDR_DYNIFTL, "src-limit", \ "synproxy", \ "map-failed", \ + "translate", \ NULL \ } @@ -480,6 +491,9 @@ struct pf_osfp_ioctl { }; #define PF_ANCHOR_NAME_SIZE 64 +#define PF_ANCHOR_MAXPATH (MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 1) +#define PF_ANCHOR_HIWAT 512 +#define PF_OPTIMIZER_TABLE_PFX "__automatic_" struct pf_rule { struct pf_rule_addr src; @@ -489,8 +503,8 @@ struct pf_rule { #define PF_SKIP_AF 2 #define PF_SKIP_PROTO 3 #define PF_SKIP_SRC_ADDR 4 -#define PF_SKIP_SRC_PORT 5 -#define PF_SKIP_DST_ADDR 6 +#define PF_SKIP_DST_ADDR 5 +#define PF_SKIP_SRC_PORT 6 #define PF_SKIP_DST_PORT 7 #define PF_SKIP_COUNT 8 union pf_rule_ptr skip[PF_SKIP_COUNT]; @@ -614,6 +628,9 @@ struct pf_rule { #define PFRULE_SET_TOS 0x00002000 #define PFRULE_IFBOUND 0x00010000 /* if-bound */ #define PFRULE_STATESLOPPY 0x00020000 /* sloppy state tracking */ +#define PFRULE_PFLOW 0x00040000 +#define PFRULE_ALLOW_RELATED 0x00080000 +#define PFRULE_AFTO 0x00200000 /* af-to rule */ #ifdef _KERNEL #define PFRULE_REFS 0x0080 /* rule has references */ @@ -626,7 +643,7 @@ struct pf_rule { /* pf_state->state_flags, pf_rule_actions->flags, pf_krule->scrub_flags */ #define PFSTATE_ALLOWOPTS 0x0001 #define PFSTATE_SLOPPY 0x0002 -/* was PFSTATE_PFLOW 0x0004 */ +#define PFSTATE_PFLOW 0x0004 #define PFSTATE_NOSYNC 0x0008 #define PFSTATE_ACK 0x0010 #define PFSTATE_NODF 0x0020 @@ -642,6 +659,12 @@ struct pf_rule { #define PFSTATE_SCRUBMASK (PFSTATE_NODF|PFSTATE_RANDOMID|PFSTATE_SCRUB_TCP) #define PFSTATE_SETMASK (PFSTATE_SETTOS|PFSTATE_SETPRIO) +/* pfctl_state->src_node_flags */ +#define PFSTATE_SRC_NODE_LIMIT 0x01 +#define PFSTATE_SRC_NODE_NAT 0x02 +#define PFSTATE_SRC_NODE_ROUTE 0x04 +#define PFSTATE_SRC_NODE_LIMIT_GLOBAL 0x10 + #define PFSTATE_HIWAT 100000 /* default state table size */ #define PFSTATE_ADAPT_START 60000 /* default adaptive timeout start */ #define PFSTATE_ADAPT_END 120000 /* default adaptive timeout end */ @@ -670,6 +693,7 @@ struct pf_src_node { u_int32_t creation; u_int32_t expire; sa_family_t af; + sa_family_t naf; u_int8_t ruletype; }; diff --git a/lib/libc/include/generic-freebsd/netpfil/pf/pf_mtag.h b/lib/libc/include/generic-freebsd/netpfil/pf/pf_mtag.h index 6e1781891616..a423f89d44e4 100644 --- a/lib/libc/include/generic-freebsd/netpfil/pf/pf_mtag.h +++ b/lib/libc/include/generic-freebsd/netpfil/pf/pf_mtag.h @@ -41,7 +41,7 @@ #define PF_MTAG_FLAG_TRANSLATE_LOCALHOST 0x04 #define PF_MTAG_FLAG_PACKET_LOOPED 0x08 #define PF_MTAG_FLAG_FASTFWD_OURS_PRESENT 0x10 -/* 0x20 unused */ +#define PF_MTAG_FLAG_DUMMYNETED 0x20 #define PF_MTAG_FLAG_DUPLICATED 0x40 #define PF_MTAG_FLAG_SYNCOOKIE_RECREATED 0x80 diff --git a/lib/libc/include/generic-freebsd/netpfil/pf/pf_nl.h b/lib/libc/include/generic-freebsd/netpfil/pf/pf_nl.h new file mode 100644 index 000000000000..8582612ca556 --- /dev/null +++ b/lib/libc/include/generic-freebsd/netpfil/pf/pf_nl.h @@ -0,0 +1,492 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Alexander V. Chernikov + * Copyright (c) 2023 Rubicon Communications, LLC (Netgate) + * + * 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 _NETPFIL_PF_PF_NL_H_ +#define _NETPFIL_PF_PF_NL_H_ + +/* Genetlink family */ +#define PFNL_FAMILY_NAME "pfctl" + +/* available commands */ +enum { + PFNL_CMD_UNSPEC = 0, + PFNL_CMD_GETSTATES = 1, + PFNL_CMD_GETCREATORS = 2, + PFNL_CMD_START = 3, + PFNL_CMD_STOP = 4, + PFNL_CMD_ADDRULE = 5, + PFNL_CMD_GETRULES = 6, + PFNL_CMD_GETRULE = 7, + PFNL_CMD_CLRSTATES = 8, + PFNL_CMD_KILLSTATES = 9, + PFNL_CMD_SET_STATUSIF = 10, + PFNL_CMD_GET_STATUS = 11, + PFNL_CMD_CLEAR_STATUS = 12, + PFNL_CMD_NATLOOK = 13, + PFNL_CMD_SET_DEBUG = 14, + PFNL_CMD_SET_TIMEOUT = 15, + PFNL_CMD_GET_TIMEOUT = 16, + PFNL_CMD_SET_LIMIT = 17, + PFNL_CMD_GET_LIMIT = 18, + PFNL_CMD_BEGIN_ADDRS = 19, + PFNL_CMD_ADD_ADDR = 20, + PFNL_CMD_GET_ADDRS = 21, + PFNL_CMD_GET_ADDR = 22, + PFNL_CMD_GET_RULESETS = 23, + PFNL_CMD_GET_RULESET = 24, + PFNL_CMD_GET_SRCNODES = 25, + PFNL_CMD_CLEAR_TABLES = 26, + PFNL_CMD_ADD_TABLE = 27, + PFNL_CMD_DEL_TABLE = 28, + PFNL_CMD_GET_TSTATS = 29, + PFNL_CMD_CLR_TSTATS = 30, + PFNL_CMD_CLR_ADDRS = 31, + PFNL_CMD_TABLE_ADD_ADDR = 32, + PFNL_CMD_TABLE_DEL_ADDR = 33, + __PFNL_CMD_MAX, +}; +#define PFNL_CMD_MAX (__PFNL_CMD_MAX -1) + +enum pfstate_key_type_t { + PF_STK_UNSPEC, + PF_STK_ADDR0 = 1, /* ip */ + PF_STK_ADDR1 = 2, /* ip */ + PF_STK_PORT0 = 3, /* u16 */ + PF_STK_PORT1 = 4, /* u16 */ + PF_STK_AF = 5, /* u8 */ + PF_STK_PROTO = 6, /* u16 */ +}; + +enum pfstate_peer_type_t { + PF_STP_UNSPEC, + PF_STP_PFSS_FLAGS = 1, /* u16 */ + PF_STP_PFSS_TTL = 2, /* u8 */ + PF_STP_SCRUB_FLAG = 3, /* u8 */ + PF_STP_PFSS_TS_MOD = 4, /* u32 */ + PF_STP_SEQLO = 5, /* u32 */ + PF_STP_SEQHI = 6, /* u32 */ + PF_STP_SEQDIFF = 7, /* u32 */ + PF_STP_MAX_WIN = 8, /* u16 */ + PF_STP_MSS = 9, /* u16 */ + PF_STP_STATE = 10, /* u8 */ + PF_STP_WSCALE = 11, /* u8 */ +}; + +enum pfstate_type_t { + PF_ST_UNSPEC, + PF_ST_ID = 1, /* u32, state id */ + PF_ST_CREATORID = 2, /* u32, */ + PF_ST_IFNAME = 3, /* string */ + PF_ST_ORIG_IFNAME = 4, /* string */ + PF_ST_KEY_WIRE = 5, /* nested, pfstate_key_type_t */ + PF_ST_KEY_STACK = 6, /* nested, pfstate_key_type_t */ + PF_ST_PEER_SRC = 7, /* nested, pfstate_peer_type_t*/ + PF_ST_PEER_DST = 8, /* nested, pfstate_peer_type_t */ + PF_ST_RT_ADDR = 9, /* ip */ + PF_ST_RULE = 10, /* u32 */ + PF_ST_ANCHOR = 11, /* u32 */ + PF_ST_NAT_RULE = 12, /* u32 */ + PF_ST_CREATION = 13, /* u32 */ + PF_ST_EXPIRE = 14, /* u32 */ + PF_ST_PACKETS0 = 15, /* u64 */ + PF_ST_PACKETS1 = 16, /* u64 */ + PF_ST_BYTES0 = 17, /* u64 */ + PF_ST_BYTES1 = 18, /* u64 */ + PF_ST_AF = 19, /* u8 */ + PF_ST_PROTO = 21, /* u8 */ + PF_ST_DIRECTION = 22, /* u8 */ + PF_ST_LOG = 23, /* u8 */ + PF_ST_TIMEOUT = 24, /* u8 */ + PF_ST_STATE_FLAGS = 25, /* u8 */ + PF_ST_SYNC_FLAGS = 26, /* u8 */ + PF_ST_UPDATES = 27, /* u8 */ + PF_ST_VERSION = 28, /* u64 */ + PF_ST_FILTER_ADDR = 29, /* in6_addr */ + PF_ST_FILTER_MASK = 30, /* in6_addr */ + PF_ST_RTABLEID = 31, /* i32 */ + PF_ST_MIN_TTL = 32, /* u8 */ + PF_ST_MAX_MSS = 33, /* u16 */ + PF_ST_DNPIPE = 34, /* u16 */ + PF_ST_DNRPIPE = 35, /* u16 */ + PF_ST_RT = 36, /* u8 */ + PF_ST_RT_IFNAME = 37, /* string */ + PF_ST_SRC_NODE_FLAGS = 38, /* u8 */ + PF_ST_RT_AF = 39, /* u8 */ +}; + +enum pf_addr_type_t { + PF_AT_UNSPEC, + PF_AT_ADDR = 1, /* in6_addr */ + PF_AT_MASK = 2, /* in6_addr */ + PF_AT_IFNAME = 3, /* string */ + PF_AT_TABLENAME = 4, /* string */ + PF_AT_TYPE = 5, /* u8 */ + PF_AT_IFLAGS = 6, /* u8 */ + PF_AT_TBLCNT = 7, /* u32 */ + PF_AT_DYNCNT = 8, /* u32 */ +}; + +enum pfrule_addr_type_t { + PF_RAT_UNSPEC, + PF_RAT_ADDR = 1, /* nested, pf_addr_type_t */ + PF_RAT_SRC_PORT = 2, /* u16 */ + PF_RAT_DST_PORT = 3, /* u16 */ + PF_RAT_NEG = 4, /* u8 */ + PF_RAT_OP = 5, /* u8 */ +}; + +enum pf_labels_type_t { + PF_LT_UNSPEC, + PF_LT_LABEL = 1, /* string */ +}; + +enum pf_mape_portset_type_t +{ + PF_MET_UNSPEC, + PF_MET_OFFSET = 1, /* u8 */ + PF_MET_PSID_LEN = 2, /* u8 */ + PF_MET_PSID = 3, /* u16 */ +}; + +enum pf_rpool_type_t +{ + PF_PT_UNSPEC, + PF_PT_KEY = 1, /* bytes, sizeof(struct pf_poolhashkey) */ + PF_PT_COUNTER = 2, /* in6_addr */ + PF_PT_TBLIDX = 3, /* u32 */ + PF_PT_PROXY_SRC_PORT = 4, /* u16 */ + PF_PT_PROXY_DST_PORT = 5, /* u16 */ + PF_PT_OPTS = 6, /* u8 */ + PF_PT_MAPE = 7, /* nested, pf_mape_portset_type_t */ +}; + +enum pf_timeout_type_t { + PF_TT_UNSPEC, + PF_TT_TIMEOUT = 1, /* u32 */ +}; + +enum pf_rule_uid_type_t { + PF_RUT_UNSPEC, + PF_RUT_UID_LOW = 1, /* u32 */ + PF_RUT_UID_HIGH = 2, /* u32 */ + PF_RUT_OP = 3, /* u8 */ +}; + +enum pf_rule_type_t { + PF_RT_UNSPEC, + PF_RT_SRC = 1, /* nested, pf_rule_addr_type_t */ + PF_RT_DST = 2, /* nested, pf_rule_addr_type_t */ + PF_RT_RIDENTIFIER = 3, /* u32 */ + PF_RT_LABELS = 4, /* nested, pf_labels_type_t */ + PF_RT_IFNAME = 5, /* string */ + PF_RT_QNAME = 6, /* string */ + PF_RT_PQNAME = 7, /* string */ + PF_RT_TAGNAME = 8, /* string */ + PF_RT_MATCH_TAGNAME = 9, /* string */ + PF_RT_OVERLOAD_TBLNAME = 10, /* string */ + PF_RT_RPOOL_RDR = 11, /* nested, pf_rpool_type_t */ + PF_RT_OS_FINGERPRINT = 12, /* u32 */ + PF_RT_RTABLEID = 13, /* u32 */ + PF_RT_TIMEOUT = 14, /* nested, pf_timeout_type_t */ + PF_RT_MAX_STATES = 15, /* u32 */ + PF_RT_MAX_SRC_NODES = 16, /* u32 */ + PF_RT_MAX_SRC_STATES = 17, /* u32 */ + PF_RT_MAX_SRC_CONN_RATE_LIMIT = 18, /* u32 */ + PF_RT_MAX_SRC_CONN_RATE_SECS = 19, /* u32 */ + PF_RT_DNPIPE = 20, /* u16 */ + PF_RT_DNRPIPE = 21, /* u16 */ + PF_RT_DNFLAGS = 22, /* u32 */ + PF_RT_NR = 23, /* u32 */ + PF_RT_PROB = 24, /* u32 */ + PF_RT_CUID = 25, /* u32 */ + PF_RT_CPID = 26, /* u32 */ + PF_RT_RETURN_ICMP = 27, /* u16 */ + PF_RT_RETURN_ICMP6 = 28, /* u16 */ + PF_RT_MAX_MSS = 29, /* u16 */ + PF_RT_SCRUB_FLAGS = 30, /* u16 */ + PF_RT_UID = 31, /* nested, pf_rule_uid_type_t */ + PF_RT_GID = 32, /* nested, pf_rule_uid_type_t */ + PF_RT_RULE_FLAG = 33, /* u32 */ + PF_RT_ACTION = 34, /* u8 */ + PF_RT_DIRECTION = 35, /* u8 */ + PF_RT_LOG = 36, /* u8 */ + PF_RT_LOGIF = 37, /* u8 */ + PF_RT_QUICK = 38, /* u8 */ + PF_RT_IF_NOT = 39, /* u8 */ + PF_RT_MATCH_TAG_NOT = 40, /* u8 */ + PF_RT_NATPASS = 41, /* u8 */ + PF_RT_KEEP_STATE = 42, /* u8 */ + PF_RT_AF = 43, /* u8 */ + PF_RT_PROTO = 44, /* u8 */ + PF_RT_TYPE = 45, /* u8 */ + PF_RT_CODE = 46, /* u8 */ + PF_RT_FLAGS = 47, /* u8 */ + PF_RT_FLAGSET = 48, /* u8 */ + PF_RT_MIN_TTL = 49, /* u8 */ + PF_RT_ALLOW_OPTS = 50, /* u8 */ + PF_RT_RT = 51, /* u8 */ + PF_RT_RETURN_TTL = 52, /* u8 */ + PF_RT_TOS = 53, /* u8 */ + PF_RT_SET_TOS = 54, /* u8 */ + PF_RT_ANCHOR_RELATIVE = 55, /* u8 */ + PF_RT_ANCHOR_WILDCARD = 56, /* u8 */ + PF_RT_FLUSH = 57, /* u8 */ + PF_RT_PRIO = 58, /* u8 */ + PF_RT_SET_PRIO = 59, /* u8 */ + PF_RT_SET_PRIO_REPLY = 60, /* u8 */ + PF_RT_DIVERT_ADDRESS = 61, /* in6_addr */ + PF_RT_DIVERT_PORT = 62, /* u16 */ + PF_RT_PACKETS_IN = 63, /* u64 */ + PF_RT_PACKETS_OUT = 64, /* u64 */ + PF_RT_BYTES_IN = 65, /* u64 */ + PF_RT_BYTES_OUT = 66, /* u64 */ + PF_RT_EVALUATIONS = 67, /* u64 */ + PF_RT_TIMESTAMP = 68, /* u64 */ + PF_RT_STATES_CUR = 69, /* u64 */ + PF_RT_STATES_TOTAL = 70, /* u64 */ + PF_RT_SRC_NODES = 71, /* u64 */ + PF_RT_ANCHOR_CALL = 72, /* string */ + PF_RT_RCV_IFNAME = 73, /* string */ + PF_RT_MAX_SRC_CONN = 74, /* u32 */ + PF_RT_RPOOL_NAT = 75, /* nested, pf_rpool_type_t */ + PF_RT_NAF = 76, /* u8 */ + PF_RT_RPOOL_RT = 77, /* nested, pf_rpool_type_t */ + PF_RT_RCV_IFNOT = 78, /* bool */ + PF_RT_SRC_NODES_LIMIT = 79, /* u64 */ + PF_RT_SRC_NODES_NAT = 80, /* u64 */ + PF_RT_SRC_NODES_ROUTE = 81, /* u64 */ + PF_RT_PKTRATE = 82, /* nested, pf_threshold_type_t */ + PF_RT_MAX_PKT_SIZE = 83, /* u16 */ + PF_RT_TYPE_2 = 84, /* u16 */ + PF_RT_CODE_2 = 85, /* u16 */ +}; + +enum pf_addrule_type_t { + PF_ART_UNSPEC, + PF_ART_TICKET = 1, /* u32 */ + PF_ART_POOL_TICKET = 2, /* u32 */ + PF_ART_ANCHOR = 3, /* string */ + PF_ART_ANCHOR_CALL = 4, /* string */ + PF_ART_RULE = 5, /* nested, pfrule_type_t */ +}; + +enum pf_getrules_type_t { + PF_GR_UNSPEC, + PF_GR_ANCHOR = 1, /* string */ + PF_GR_ACTION = 2, /* u8 */ + PF_GR_NR = 3, /* u32 */ + PF_GR_TICKET = 4, /* u32 */ + PF_GR_CLEAR = 5, /* u8 */ +}; + +enum pf_clear_states_type_t { + PF_CS_UNSPEC, + PF_CS_CMP_ID = 1, /* u64 */ + PF_CS_CMP_CREATORID = 2, /* u32 */ + PF_CS_CMP_DIR = 3, /* u8 */ + PF_CS_AF = 4, /* u8 */ + PF_CS_PROTO = 5, /* u8 */ + PF_CS_SRC = 6, /* nested, pf_addr_wrap */ + PF_CS_DST = 7, /* nested, pf_addr_wrap */ + PF_CS_RT_ADDR = 8, /* nested, pf_addr_wrap */ + PF_CS_IFNAME = 9, /* string */ + PF_CS_LABEL = 10, /* string */ + PF_CS_KILL_MATCH = 11, /* bool */ + PF_CS_NAT = 12, /* bool */ + PF_CS_KILLED = 13, /* u32 */ +}; + +enum pf_set_statusif_types_t { + PF_SS_UNSPEC, + PF_SS_IFNAME = 1, /* string */ +}; + +enum pf_counter_types_t { + PF_C_UNSPEC, + PF_C_COUNTER = 1, /* u64 */ + PF_C_NAME = 2, /* string */ + PF_C_ID = 3, /* u32 */ +}; + +enum pf_get_status_types_t { + PF_GS_UNSPEC, + PF_GS_IFNAME = 1, /* string */ + PF_GS_RUNNING = 2, /* bool */ + PF_GS_SINCE = 3, /* u32 */ + PF_GS_DEBUG = 4, /* u32 */ + PF_GS_HOSTID = 5, /* u32 */ + PF_GS_STATES = 6, /* u32 */ + PF_GS_SRC_NODES = 7, /* u32 */ + PF_GS_REASSEMBLE = 8, /* u32 */ + PF_GS_SYNCOOKIES_ACTIVE = 9, /* bool */ + PF_GS_COUNTERS = 10, /* nested, */ + PF_GS_LCOUNTERS = 11, /* nested, */ + PF_GS_FCOUNTERS = 12, /* nested, */ + PF_GS_SCOUNTERS = 13, /* nested, */ + PF_GS_CHKSUM = 14, /* byte array */ + PF_GS_PCOUNTERS = 15, /* u64 array */ + PF_GS_BCOUNTERS = 16, /* u64 array */ +}; + +enum pf_natlook_types_t { + PF_NL_UNSPEC, + PF_NL_AF = 1, /* u8 */ + PF_NL_DIRECTION = 2, /* u8 */ + PF_NL_PROTO = 3, /* u8 */ + PF_NL_SRC_ADDR = 4, /* in6_addr */ + PF_NL_DST_ADDR = 5, /* in6_addr */ + PF_NL_SRC_PORT = 6, /* u16 */ + PF_NL_DST_PORT = 7, /* u16 */ +}; + +enum pf_set_debug_types_t { + PF_SD_UNSPEC, + PF_SD_LEVEL = 1, /* u32 */ +}; + +enum pf_timeout_types_t { + PF_TO_UNSPEC, + PF_TO_TIMEOUT = 1, /* u32 */ + PF_TO_SECONDS = 2, /* u32 */ +}; + +enum pf_limit_types_t { + PF_LI_UNSPEC, + PF_LI_INDEX = 1, /* u32 */ + PF_LI_LIMIT = 2, /* u32 */ +}; + +enum pf_begin_addrs_types_t { + PF_BA_UNSPEC, + PF_BA_TICKET = 1, /* u32 */ +}; + +enum pf_pool_addr_types_t { + PF_PA_UNSPEC, + PF_PA_ADDR = 1, /* nested, pf_addr_wrap */ + PF_PA_IFNAME = 2, /* string */ +}; + +enum pf_add_addr_types_t { + PF_AA_UNSPEC, + PF_AA_ACTION = 1, /* u32 */ + PF_AA_TICKET = 2, /* u32 */ + PF_AA_NR = 3, /* u32 */ + PF_AA_R_NUM = 4, /* u32 */ + PF_AA_R_ACTION = 5, /* u8 */ + PF_AA_R_LAST = 6, /* u8 */ + PF_AA_AF = 7, /* u8 */ + PF_AA_ANCHOR = 8, /* string */ + PF_AA_ADDR = 9, /* nested, pf_pooladdr */ + PF_AA_WHICH = 10, /* u32 */ +}; + +enum pf_get_rulesets_types_t { + PF_RS_UNSPEC, + PF_RS_PATH = 1, /* string */ + PF_RS_NR = 2, /* u32 */ + PF_RS_NAME = 3, /* string */ +}; + +enum pf_threshold_types_t { + PF_TH_UNSPEC, + PF_TH_LIMIT = 1, /* u32 */ + PF_TH_SECONDS = 2, /* u32 */ + PF_TH_COUNT = 3, /* u32 */ + PF_TH_LAST = 4, /* u32 */ +}; + +enum pf_srcnodes_types_t { + PF_SN_UNSPEC, + PF_SN_ADDR = 1, /* nested, pf_addr */ + PF_SN_RADDR = 2, /* nested, pf_addr */ + PF_SN_RULE_NR = 3, /* u32 */ + PF_SN_BYTES_IN = 4, /* u64 */ + PF_SN_BYTES_OUT = 5, /* u64 */ + PF_SN_PACKETS_IN = 6, /* u64 */ + PF_SN_PACKETS_OUT = 7, /* u64 */ + PF_SN_STATES = 8, /* u32 */ + PF_SN_CONNECTIONS = 9, /* u32 */ + PF_SN_AF = 10, /* u8 */ + PF_SN_RULE_TYPE = 11, /* u8 */ + PF_SN_CREATION = 12, /* u64 */ + PF_SN_EXPIRE = 13, /* u64 */ + PF_SN_CONNECTION_RATE = 14, /* nested, pf_threshold */ + PF_SN_RAF = 15, /* u8 */ + PF_SN_NODE_TYPE = 16, /* u8 */ +}; + +enum pf_tables_t { + PF_T_UNSPEC, + PF_T_ANCHOR = 1, /* string */ + PF_T_NAME = 2, /* string */ + PF_T_TABLE_FLAGS = 3, /* u32 */ + PF_T_FLAGS = 4, /* u32 */ + PF_T_NBR_DELETED = 5, /* u32 */ + PF_T_NBR_ADDED = 6, /* u32 */ +}; + +enum pf_tstats_t { + PF_TS_UNSPEC, + PF_TS_TABLE = 1, /* nested, pfr_table */ + PF_TS_PACKETS = 2, /* u64 array */ + PF_TS_BYTES = 3, /* u64 array */ + PF_TS_MATCH = 4, /* u64 */ + PF_TS_NOMATCH = 5, /* u64 */ + PF_TS_TZERO = 6, /* u64 */ + PF_TS_CNT = 7, /* u64 */ + PF_TS_REFCNT = 8, /* u64 array */ + PF_TS_NZERO = 9, /* u64 */ +}; + +enum pfr_addr_t { + PFR_A_UNSPEC, + PFR_A_AF = 1, /* uint8_t */ + PFR_A_NET = 2, /* uint8_t */ + PFR_A_NOT = 3, /* bool */ + PFR_A_ADDR = 4, /* in6_addr */ +}; + +enum pf_table_addrs_t { + PF_TA_UNSPEC, + PF_TA_TABLE = 1, /* nested, pf_table_t */ + PF_TA_ADDR = 2, /* nested, pfr_addr_t */ + PF_TA_FLAGS = 3, /* u32 */ + PF_TA_NBR_ADDED = 4, /* u32 */ + PF_TA_NBR_DELETED = 5, /* u32 */ +}; + +#ifdef _KERNEL + +void pf_nl_register(void); +void pf_nl_unregister(void); + +#endif + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/nfs/nfsdiskless.h b/lib/libc/include/generic-freebsd/nfs/nfsdiskless.h index b98351ef96c7..7aecb7b43de8 100644 --- a/lib/libc/include/generic-freebsd/nfs/nfsdiskless.h +++ b/lib/libc/include/generic-freebsd/nfs/nfsdiskless.h @@ -30,8 +30,6 @@ * 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. - * - * @(#)nfsdiskless.h 8.2 (Berkeley) 3/30/95 */ #ifndef _NFSCLIENT_NFSDISKLESS_H_ diff --git a/lib/libc/include/generic-freebsd/nfs/nfsproto.h b/lib/libc/include/generic-freebsd/nfs/nfsproto.h index cfc66b8c6e42..936885ed5752 100644 --- a/lib/libc/include/generic-freebsd/nfs/nfsproto.h +++ b/lib/libc/include/generic-freebsd/nfs/nfsproto.h @@ -30,8 +30,6 @@ * 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. - * - * @(#)nfsproto.h 8.2 (Berkeley) 3/30/95 */ #ifndef _NFS_NFSPROTO_H_ diff --git a/lib/libc/include/generic-freebsd/nfs/xdr_subs.h b/lib/libc/include/generic-freebsd/nfs/xdr_subs.h index d17157c5f9b8..27c5697926a6 100644 --- a/lib/libc/include/generic-freebsd/nfs/xdr_subs.h +++ b/lib/libc/include/generic-freebsd/nfs/xdr_subs.h @@ -30,8 +30,6 @@ * 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. - * - * @(#)xdr_subs.h 8.3 (Berkeley) 3/30/95 */ #ifndef _NFS_XDR_SUBS_H_ diff --git a/lib/libc/include/generic-freebsd/nfsclient/nfs.h b/lib/libc/include/generic-freebsd/nfsclient/nfs.h index 0314c78c4a6d..fa917ec4f7ff 100644 --- a/lib/libc/include/generic-freebsd/nfsclient/nfs.h +++ b/lib/libc/include/generic-freebsd/nfsclient/nfs.h @@ -30,8 +30,6 @@ * 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. - * - * @(#)nfs.h 8.4 (Berkeley) 5/1/95 */ #ifndef _NFSCLIENT_NFS_H_ diff --git a/lib/libc/include/generic-freebsd/nfsclient/nfsargs.h b/lib/libc/include/generic-freebsd/nfsclient/nfsargs.h index 3d49d86c3905..68e2006fe96c 100644 --- a/lib/libc/include/generic-freebsd/nfsclient/nfsargs.h +++ b/lib/libc/include/generic-freebsd/nfsclient/nfsargs.h @@ -30,8 +30,6 @@ * 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. - * - * @(#)nfs.h 8.4 (Berkeley) 5/1/95 */ #ifndef _NFSCLIENT_NFSARGS_H_ diff --git a/lib/libc/include/generic-freebsd/nfsclient/nfsmount.h b/lib/libc/include/generic-freebsd/nfsclient/nfsmount.h index 0d5d87bcabd0..9ef05998dda1 100644 --- a/lib/libc/include/generic-freebsd/nfsclient/nfsmount.h +++ b/lib/libc/include/generic-freebsd/nfsclient/nfsmount.h @@ -30,8 +30,6 @@ * 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. - * - * @(#)nfsmount.h 8.3 (Berkeley) 3/30/95 */ #ifndef _NFSCLIENT_NFSMOUNT_H_ diff --git a/lib/libc/include/generic-freebsd/nfsclient/nfsnode.h b/lib/libc/include/generic-freebsd/nfsclient/nfsnode.h index 0f8fa85d0257..9434d8d4ef32 100644 --- a/lib/libc/include/generic-freebsd/nfsclient/nfsnode.h +++ b/lib/libc/include/generic-freebsd/nfsclient/nfsnode.h @@ -30,8 +30,6 @@ * 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. - * - * @(#)nfsnode.h 8.9 (Berkeley) 5/14/95 */ #ifndef _NFSCLIENT_NFSNODE_H_ diff --git a/lib/libc/include/generic-freebsd/nfsclient/nfsstats.h b/lib/libc/include/generic-freebsd/nfsclient/nfsstats.h index 0865f513b32b..246c588b8e29 100644 --- a/lib/libc/include/generic-freebsd/nfsclient/nfsstats.h +++ b/lib/libc/include/generic-freebsd/nfsclient/nfsstats.h @@ -30,8 +30,6 @@ * 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. - * - * @(#)nfs.h 8.4 (Berkeley) 5/1/95 */ #ifndef _NFSCLIENT_NFSSTATS_H_ diff --git a/lib/libc/include/generic-freebsd/nfsserver/nfs.h b/lib/libc/include/generic-freebsd/nfsserver/nfs.h index 2f313551c8b2..7f186249f7cc 100644 --- a/lib/libc/include/generic-freebsd/nfsserver/nfs.h +++ b/lib/libc/include/generic-freebsd/nfsserver/nfs.h @@ -30,8 +30,6 @@ * 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. - * - * @(#)nfs.h 8.4 (Berkeley) 5/1/95 */ #ifndef _NFSSERVER_NFS_H_ diff --git a/lib/libc/include/generic-freebsd/nfsserver/nfsrvstats.h b/lib/libc/include/generic-freebsd/nfsserver/nfsrvstats.h index adb36b952332..564207996bb7 100644 --- a/lib/libc/include/generic-freebsd/nfsserver/nfsrvstats.h +++ b/lib/libc/include/generic-freebsd/nfsserver/nfsrvstats.h @@ -30,8 +30,6 @@ * 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. - * - * @(#)nfs.h 8.4 (Berkeley) 5/1/95 */ #ifndef _NFSSERVER_NFSRVSTATS_H_ diff --git a/lib/libc/include/generic-freebsd/nl_types.h b/lib/libc/include/generic-freebsd/nl_types.h index 68f7d6982225..efea87bc4ef5 100644 --- a/lib/libc/include/generic-freebsd/nl_types.h +++ b/lib/libc/include/generic-freebsd/nl_types.h @@ -34,7 +34,6 @@ #ifndef _NL_TYPES_H_ #define _NL_TYPES_H_ -#include #include #ifdef _NLS_PRIVATE diff --git a/lib/libc/include/generic-freebsd/nlist.h b/lib/libc/include/generic-freebsd/nlist.h index d075b20871fe..a10a5532c3dc 100644 --- a/lib/libc/include/generic-freebsd/nlist.h +++ b/lib/libc/include/generic-freebsd/nlist.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)nlist.h 8.2 (Berkeley) 1/21/94 */ #ifndef _NLIST_H_ diff --git a/lib/libc/include/generic-freebsd/osreldate.h b/lib/libc/include/generic-freebsd/osreldate.h index 1cbc95cd3674..81afbd301b14 100644 --- a/lib/libc/include/generic-freebsd/osreldate.h +++ b/lib/libc/include/generic-freebsd/osreldate.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1992-2023 The FreeBSD Project. + * Copyright (c) 1992-2025 The FreeBSD Project. * */ #ifdef _KERNEL diff --git a/lib/libc/include/generic-freebsd/paths.h b/lib/libc/include/generic-freebsd/paths.h index 371deb51d0e2..60b3d872bb38 100644 --- a/lib/libc/include/generic-freebsd/paths.h +++ b/lib/libc/include/generic-freebsd/paths.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)paths.h 8.1 (Berkeley) 6/2/93 */ #ifndef _PATHS_H_ @@ -63,7 +61,6 @@ #define _PATH_FIRMWARE "/usr/share/firmware" #define _PATH_FTPUSERS "/etc/ftpusers" #define _PATH_FWMEM "/dev/fwmem" -#define _PATH_GBDE "/sbin/gbde" #define _PATH_GELI "/sbin/geli" #define _PATH_HALT "/sbin/halt" #ifdef COMPAT_libcompat @@ -84,6 +81,7 @@ #define _PATH_MOUNT "/sbin/mount" #define _PATH_NEWFS "/sbin/newfs" #define _PATH_NOLOGIN "/var/run/nologin" +#define _PATH_NOSHUTDOWN "/var/run/noshutdown" #define _PATH_RCP "/bin/rcp" #define _PATH_REBOOT "/sbin/reboot" #define _PATH_RLOGIN "/usr/bin/rlogin" diff --git a/lib/libc/include/generic-freebsd/poll.h b/lib/libc/include/generic-freebsd/poll.h index a731b70329ff..b915f5a37d7e 100644 --- a/lib/libc/include/generic-freebsd/poll.h +++ b/lib/libc/include/generic-freebsd/poll.h @@ -96,7 +96,7 @@ struct pollfd { #ifndef _KERNEL -#if __BSD_VISIBLE +#if __POSIX_VISIBLE >= 202405 #include #include @@ -109,9 +109,13 @@ typedef __sigset_t sigset_t; #endif +#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 +#include +#endif + __BEGIN_DECLS int poll(struct pollfd _pfd[], nfds_t _nfds, int _timeout); -#if __BSD_VISIBLE +#if __POSIX_VISIBLE >= 202405 int ppoll(struct pollfd _pfd[], nfds_t _nfds, const struct timespec *__restrict _timeout, const sigset_t *__restrict _newsigmask); diff --git a/lib/libc/include/generic-freebsd/protocols/dumprestore.h b/lib/libc/include/generic-freebsd/protocols/dumprestore.h index 37b53648151a..ef3e9e4f1156 100644 --- a/lib/libc/include/generic-freebsd/protocols/dumprestore.h +++ b/lib/libc/include/generic-freebsd/protocols/dumprestore.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)dumprestore.h 8.2 (Berkeley) 1/21/94 */ #ifndef _PROTOCOLS_DUMPRESTORE_H_ diff --git a/lib/libc/include/generic-freebsd/protocols/routed.h b/lib/libc/include/generic-freebsd/protocols/routed.h index ba2dc2db56bc..9d282efcc7bf 100644 --- a/lib/libc/include/generic-freebsd/protocols/routed.h +++ b/lib/libc/include/generic-freebsd/protocols/routed.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)routed.h 8.1 (Berkeley) 6/2/93 * $Revision: 2.26 $ */ diff --git a/lib/libc/include/generic-freebsd/protocols/rwhod.h b/lib/libc/include/generic-freebsd/protocols/rwhod.h index 793d5d6aba69..a995671b864c 100644 --- a/lib/libc/include/generic-freebsd/protocols/rwhod.h +++ b/lib/libc/include/generic-freebsd/protocols/rwhod.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)rwhod.h 8.1 (Berkeley) 6/2/93 */ #ifndef _PROTOCOLS_RWHOD_H_ diff --git a/lib/libc/include/generic-freebsd/protocols/talkd.h b/lib/libc/include/generic-freebsd/protocols/talkd.h index 82fe09d45282..116f0ee3e761 100644 --- a/lib/libc/include/generic-freebsd/protocols/talkd.h +++ b/lib/libc/include/generic-freebsd/protocols/talkd.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)talkd.h 8.1 (Berkeley) 6/2/93 */ #ifndef _PROTOCOLS_TALKD_H_ diff --git a/lib/libc/include/generic-freebsd/protocols/timed.h b/lib/libc/include/generic-freebsd/protocols/timed.h index 48618d6f5a1a..18fda3f954d6 100644 --- a/lib/libc/include/generic-freebsd/protocols/timed.h +++ b/lib/libc/include/generic-freebsd/protocols/timed.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)timed.h 8.1 (Berkeley) 6/2/93 */ #ifndef _PROTOCOLS_TIMED_H_ diff --git a/lib/libc/include/generic-freebsd/pthread_np.h b/lib/libc/include/generic-freebsd/pthread_np.h index 445394489275..9c4ec917d27d 100644 --- a/lib/libc/include/generic-freebsd/pthread_np.h +++ b/lib/libc/include/generic-freebsd/pthread_np.h @@ -34,11 +34,6 @@ #include #include -/* - * Non-POSIX type definitions: - */ -typedef void (*pthread_switch_routine_t)(pthread_t, pthread_t); - /* * Non-POSIX thread function prototype definitions: */ @@ -64,11 +59,11 @@ int pthread_resume_np(pthread_t); int pthread_peekjoin_np(pthread_t, void **); void pthread_set_name_np(pthread_t, const char *); int pthread_setaffinity_np(pthread_t, size_t, const cpuset_t *); +void pthread_signals_block_np(void); +void pthread_signals_unblock_np(void); int pthread_single_np(void); void pthread_suspend_all_np(void); int pthread_suspend_np(pthread_t); -int pthread_switch_add_np(pthread_switch_routine_t); -int pthread_switch_delete_np(pthread_switch_routine_t); int pthread_timedjoin_np(pthread_t, void **, const struct timespec *); __END_DECLS diff --git a/lib/libc/include/generic-freebsd/pwd.h b/lib/libc/include/generic-freebsd/pwd.h index b1834446995c..6e5a081c5b28 100644 --- a/lib/libc/include/generic-freebsd/pwd.h +++ b/lib/libc/include/generic-freebsd/pwd.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)pwd.h 8.2 (Berkeley) 1/21/94 */ #ifndef _PWD_H_ diff --git a/lib/libc/include/generic-freebsd/ranlib.h b/lib/libc/include/generic-freebsd/ranlib.h index bc8d09fcf8af..0038e3d302a0 100644 --- a/lib/libc/include/generic-freebsd/ranlib.h +++ b/lib/libc/include/generic-freebsd/ranlib.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)ranlib.h 8.1 (Berkeley) 6/2/93 */ #ifndef _RANLIB_H_ diff --git a/lib/libc/include/generic-freebsd/regex.h b/lib/libc/include/generic-freebsd/regex.h index 4e6f91d9d2d4..ec98c574d7d4 100644 --- a/lib/libc/include/generic-freebsd/regex.h +++ b/lib/libc/include/generic-freebsd/regex.h @@ -31,8 +31,6 @@ * 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. - * - * @(#)regex.h 8.2 (Berkeley) 1/3/94 */ #ifndef _REGEX_H_ diff --git a/lib/libc/include/generic-freebsd/resolv.h b/lib/libc/include/generic-freebsd/resolv.h index 0d871655d98e..03da1cf95c66 100644 --- a/lib/libc/include/generic-freebsd/resolv.h +++ b/lib/libc/include/generic-freebsd/resolv.h @@ -47,7 +47,6 @@ */ /*% - * @(#)resolv.h 8.1 (Berkeley) 6/2/93 * $Id: resolv.h,v 1.30 2009/03/03 01:52:48 each Exp $ */ diff --git a/lib/libc/include/generic-freebsd/rpc/auth.h b/lib/libc/include/generic-freebsd/rpc/auth.h index b6d923124b35..81b7e496436e 100644 --- a/lib/libc/include/generic-freebsd/rpc/auth.h +++ b/lib/libc/include/generic-freebsd/rpc/auth.h @@ -28,10 +28,6 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * from: @(#)auth.h 1.17 88/02/08 SMI - * from: @(#)auth.h 2.3 88/08/07 4.0 RPCSRC - * from: @(#)auth.h 1.43 98/02/02 SMI */ /* diff --git a/lib/libc/include/generic-freebsd/rpc/auth_des.h b/lib/libc/include/generic-freebsd/rpc/auth_des.h index f3ba957d3a2f..f02b90e06479 100644 --- a/lib/libc/include/generic-freebsd/rpc/auth_des.h +++ b/lib/libc/include/generic-freebsd/rpc/auth_des.h @@ -1,4 +1,3 @@ -/* @(#)auth_des.h 2.2 88/07/29 4.0 RPCSRC; from 1.3 88/02/08 SMI */ /*- * SPDX-License-Identifier: BSD-3-Clause * @@ -28,8 +27,6 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - * from: @(#)auth_des.h 2.2 88/07/29 4.0 RPCSRC - * from: @(#)auth_des.h 1.14 94/04/25 SMI */ /* diff --git a/lib/libc/include/generic-freebsd/rpc/auth_unix.h b/lib/libc/include/generic-freebsd/rpc/auth_unix.h index b68956b3b692..7494012dceb0 100644 --- a/lib/libc/include/generic-freebsd/rpc/auth_unix.h +++ b/lib/libc/include/generic-freebsd/rpc/auth_unix.h @@ -26,9 +26,6 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * from: @(#)auth_unix.h 1.8 88/02/08 SMI - * from: @(#)auth_unix.h 2.2 88/07/29 4.0 RPCSRC */ /* diff --git a/lib/libc/include/generic-freebsd/rpc/clnt.h b/lib/libc/include/generic-freebsd/rpc/clnt.h index fa4415573351..a3601d47d52c 100644 --- a/lib/libc/include/generic-freebsd/rpc/clnt.h +++ b/lib/libc/include/generic-freebsd/rpc/clnt.h @@ -28,9 +28,6 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * from: @(#)clnt.h 1.31 94/04/29 SMI - * from: @(#)clnt.h 2.1 88/07/29 4.0 RPCSRC */ /* diff --git a/lib/libc/include/generic-freebsd/rpc/clnt_nl.h b/lib/libc/include/generic-freebsd/rpc/clnt_nl.h new file mode 100644 index 000000000000..224a9c14255b --- /dev/null +++ b/lib/libc/include/generic-freebsd/rpc/clnt_nl.h @@ -0,0 +1,42 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Gleb Smirnoff + * + * 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 _RPC_CLNT_NL_H +#define _RPC_CLNT_NL_H + +enum rpcnl_cmds_t { + RPCNL_REQUEST = 1, /* mcast: kernel -> userland */ + RPCNL_REPLY, /* unicast: userland -> kernel */ +}; + +enum rpcnl_attr_t { + RPCNL_REQUEST_GROUP = 1, + RPCNL_REQUEST_BODY, + RPCNL_REPLY_GROUP, + RPCNL_REPLY_BODY, +}; +#endif /* _RPC_CLNT_NL_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/rpc/clnt_stat.h b/lib/libc/include/generic-freebsd/rpc/clnt_stat.h index d63bb895a706..6905029fff46 100644 --- a/lib/libc/include/generic-freebsd/rpc/clnt_stat.h +++ b/lib/libc/include/generic-freebsd/rpc/clnt_stat.h @@ -11,8 +11,6 @@ #ifndef _RPC_CLNT_STAT_H #define _RPC_CLNT_STAT_H -/* #pragma ident "@(#)clnt_stat.h 1.2 97/04/28 SMI" */ - #ifdef __cplusplus extern "C" { #endif diff --git a/lib/libc/include/generic-freebsd/rpc/des.h b/lib/libc/include/generic-freebsd/rpc/des.h index cc51b3bb604f..de1dcdb9ef71 100644 --- a/lib/libc/include/generic-freebsd/rpc/des.h +++ b/lib/libc/include/generic-freebsd/rpc/des.h @@ -1,4 +1,3 @@ -/* @(#)des.h 2.2 88/08/10 4.0 RPCSRC; from 2.7 88/02/08 SMI */ /*- * SPDX-License-Identifier: BSD-3-Clause * @@ -57,26 +56,6 @@ struct desparams { # define des_buf UDES.UDES_buf /* otherwise, pointer to data */ }; -#ifdef notdef - -/* - * These ioctls are only implemented in SunOS. Maybe someday - * if somebody writes a driver for DES hardware that works - * with FreeBSD, we can being that back. - */ - -/* - * Encrypt an arbitrary sized buffer - */ -#define DESIOCBLOCK _IOWR('d', 6, struct desparams) - -/* - * Encrypt of small amount of data, quickly - */ -#define DESIOCQUICK _IOWR('d', 7, struct desparams) - -#endif - /* * Software DES. */ diff --git a/lib/libc/include/generic-freebsd/rpc/des_crypt.h b/lib/libc/include/generic-freebsd/rpc/des_crypt.h index 7028777a01bf..c9e20fca6f87 100644 --- a/lib/libc/include/generic-freebsd/rpc/des_crypt.h +++ b/lib/libc/include/generic-freebsd/rpc/des_crypt.h @@ -1,5 +1,4 @@ /* - * @(#)des_crypt.h 2.1 88/08/11 4.0 RPCSRC; from 1.4 88/02/08 (C) 1986 SMI * * des_crypt.h, des library routine interface * Copyright (C) 1986, Sun Microsystems, Inc. diff --git a/lib/libc/include/generic-freebsd/rpc/key_prot.h b/lib/libc/include/generic-freebsd/rpc/key_prot.h index f34d0133dae0..4541929b6a0d 100644 --- a/lib/libc/include/generic-freebsd/rpc/key_prot.h +++ b/lib/libc/include/generic-freebsd/rpc/key_prot.h @@ -42,10 +42,6 @@ extern "C" { * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* From: #pragma ident "@(#)key_prot.x 1.7 94/04/29 SMI" */ -/* Copyright (c) 1990, 1991 Sun Microsystems, Inc. */ -#include - /* * Compiled from key_prot.x using rpcgen. * DO NOT EDIT THIS FILE! diff --git a/lib/libc/include/generic-freebsd/rpc/pmap_clnt.h b/lib/libc/include/generic-freebsd/rpc/pmap_clnt.h index 3ff3ae906b0d..510e95354961 100644 --- a/lib/libc/include/generic-freebsd/rpc/pmap_clnt.h +++ b/lib/libc/include/generic-freebsd/rpc/pmap_clnt.h @@ -28,9 +28,6 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * from: @(#)pmap_clnt.h 1.11 88/02/08 SMI - * from: @(#)pmap_clnt.h 2.1 88/07/29 4.0 RPCSRC */ /* diff --git a/lib/libc/include/generic-freebsd/rpc/pmap_prot.h b/lib/libc/include/generic-freebsd/rpc/pmap_prot.h index 704a6c71b70e..8ea0df569fff 100644 --- a/lib/libc/include/generic-freebsd/rpc/pmap_prot.h +++ b/lib/libc/include/generic-freebsd/rpc/pmap_prot.h @@ -28,9 +28,6 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * from: @(#)pmap_prot.h 1.14 88/02/08 SMI - * from: @(#)pmap_prot.h 2.1 88/07/29 4.0 RPCSRC */ /* diff --git a/lib/libc/include/generic-freebsd/rpc/pmap_rmt.h b/lib/libc/include/generic-freebsd/rpc/pmap_rmt.h index 8be6811decde..02c5e0939f5d 100644 --- a/lib/libc/include/generic-freebsd/rpc/pmap_rmt.h +++ b/lib/libc/include/generic-freebsd/rpc/pmap_rmt.h @@ -28,9 +28,6 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * from: @(#)pmap_rmt.h 1.2 88/02/08 SMI - * from: @(#)pmap_rmt.h 2.1 88/07/29 4.0 RPCSRC */ /* diff --git a/lib/libc/include/generic-freebsd/rpc/raw.h b/lib/libc/include/generic-freebsd/rpc/raw.h index d0b54abf8dbf..afa739e1255e 100644 --- a/lib/libc/include/generic-freebsd/rpc/raw.h +++ b/lib/libc/include/generic-freebsd/rpc/raw.h @@ -36,9 +36,6 @@ #ifndef _RPC_RAW_H #define _RPC_RAW_H -/* from: @(#)raw.h 1.11 94/04/25 SMI */ -/* from: @(#)raw.h 1.2 88/10/25 SMI */ - #ifdef __cplusplus extern "C" { #endif diff --git a/lib/libc/include/generic-freebsd/rpc/rpc.h b/lib/libc/include/generic-freebsd/rpc/rpc.h index e4c1302c7bf2..8832c23d5622 100644 --- a/lib/libc/include/generic-freebsd/rpc/rpc.h +++ b/lib/libc/include/generic-freebsd/rpc/rpc.h @@ -28,9 +28,6 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * from: @(#)rpc.h 1.9 88/02/08 SMI - * from: @(#)rpc.h 2.4 89/07/11 4.0 RPCSRC */ /* diff --git a/lib/libc/include/generic-freebsd/rpc/rpc_com.h b/lib/libc/include/generic-freebsd/rpc/rpc_com.h index f435e163c3af..1beb67a70779 100644 --- a/lib/libc/include/generic-freebsd/rpc/rpc_com.h +++ b/lib/libc/include/generic-freebsd/rpc/rpc_com.h @@ -44,8 +44,6 @@ #include -/* #pragma ident "@(#)rpc_com.h 1.11 93/07/05 SMI" */ - /* * The max size of the transport, if the size cannot be determined * by other means. diff --git a/lib/libc/include/generic-freebsd/rpc/rpc_msg.h b/lib/libc/include/generic-freebsd/rpc/rpc_msg.h index 92fa4276a262..f76f82c1b19f 100644 --- a/lib/libc/include/generic-freebsd/rpc/rpc_msg.h +++ b/lib/libc/include/generic-freebsd/rpc/rpc_msg.h @@ -28,9 +28,6 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * from: @(#)rpc_msg.h 1.7 86/07/16 SMI - * from: @(#)rpc_msg.h 2.1 88/07/29 4.0 RPCSRC */ /* diff --git a/lib/libc/include/generic-freebsd/rpc/rpcb_clnt.h b/lib/libc/include/generic-freebsd/rpc/rpcb_clnt.h index 8aead1af0d16..2b47110d763f 100644 --- a/lib/libc/include/generic-freebsd/rpc/rpcb_clnt.h +++ b/lib/libc/include/generic-freebsd/rpc/rpcb_clnt.h @@ -55,7 +55,6 @@ #ifndef _RPC_RPCB_CLNT_H #define _RPC_RPCB_CLNT_H -/* #pragma ident "@(#)rpcb_clnt.h 1.13 94/04/25 SMI" */ /* rpcb_clnt.h 1.3 88/12/05 SMI */ #include diff --git a/lib/libc/include/generic-freebsd/rpc/rpcb_prot.h b/lib/libc/include/generic-freebsd/rpc/rpcb_prot.h index 35b4c4506357..bb33f29e6414 100644 --- a/lib/libc/include/generic-freebsd/rpc/rpcb_prot.h +++ b/lib/libc/include/generic-freebsd/rpc/rpcb_prot.h @@ -44,8 +44,6 @@ extern "C" { */ /* from rpcb_prot.x */ -/* #pragma ident "@(#)rpcb_prot.x 1.5 94/04/29 SMI" */ - #ifndef _KERNEL diff --git a/lib/libc/include/generic-freebsd/rpc/rpcb_prot.x b/lib/libc/include/generic-freebsd/rpc/rpcb_prot.x index 7feee8aeae8e..8a6027d971b8 100644 --- a/lib/libc/include/generic-freebsd/rpc/rpcb_prot.x +++ b/lib/libc/include/generic-freebsd/rpc/rpcb_prot.x @@ -33,8 +33,6 @@ #ifdef RPC_HDR % -%/* #pragma ident "@(#)rpcb_prot.x 1.5 94/04/29 SMI" */ -% %#ifndef _KERNEL % #endif diff --git a/lib/libc/include/generic-freebsd/rpc/rpcent.h b/lib/libc/include/generic-freebsd/rpc/rpcent.h index 1e6415c2b2e2..4bd144450717 100644 --- a/lib/libc/include/generic-freebsd/rpc/rpcent.h +++ b/lib/libc/include/generic-freebsd/rpc/rpcent.h @@ -42,10 +42,6 @@ #ifndef _RPC_RPCENT_H #define _RPC_RPCENT_H -/* #pragma ident "@(#)rpcent.h 1.13 94/04/25 SMI" */ -/* @(#)rpcent.h 1.1 88/12/06 SMI */ - - struct rpcent { char *r_name; /* name of server for this rpc program */ char **r_aliases; /* alias list */ diff --git a/lib/libc/include/generic-freebsd/rpc/rpcsec_tls.h b/lib/libc/include/generic-freebsd/rpc/rpcsec_tls.h index fade49c1ef7d..0ec985e383ca 100644 --- a/lib/libc/include/generic-freebsd/rpc/rpcsec_tls.h +++ b/lib/libc/include/generic-freebsd/rpc/rpcsec_tls.h @@ -28,20 +28,8 @@ #ifndef _RPC_RPCSEC_TLS_H_ #define _RPC_RPCSEC_TLS_H_ -/* Operation values for rpctls syscall. */ -#define RPCTLS_SYSC_CLSETPATH 1 -#define RPCTLS_SYSC_CLSOCKET 2 -#define RPCTLS_SYSC_CLSHUTDOWN 3 -#define RPCTLS_SYSC_SRVSETPATH 4 -#define RPCTLS_SYSC_SRVSOCKET 5 -#define RPCTLS_SYSC_SRVSHUTDOWN 6 -#define RPCTLS_SYSC_SRVSTARTUP 7 - -/* Max nprocs for SRV startup */ -#define RPCTLS_SRV_MAXNPROCS 16 - -/* System call used by the rpctlscd, rpctlssd daemons. */ -int rpctls_syscall(int, const char *); +/* System call used by the rpc.tlsclntd(8), rpc.tlsservd(8) daemons. */ +int rpctls_syscall(uint64_t); /* Flag bits to indicate certificate results. */ #define RPCTLS_FLAGS_HANDSHAKE 0x01 @@ -61,15 +49,11 @@ int rpctls_syscall(int, const char *); #ifdef _KERNEL /* Functions that perform upcalls to the rpctlsd daemon. */ enum clnt_stat rpctls_connect(CLIENT *newclient, char *certname, - struct socket *so, uint64_t *sslp, uint32_t *reterr); -enum clnt_stat rpctls_cl_handlerecord(uint64_t sec, uint64_t usec, - uint64_t ssl, uint32_t *reterr); -enum clnt_stat rpctls_srv_handlerecord(uint64_t sec, uint64_t usec, - uint64_t ssl, int procpos, uint32_t *reterr); -enum clnt_stat rpctls_cl_disconnect(uint64_t sec, uint64_t usec, - uint64_t ssl, uint32_t *reterr); -enum clnt_stat rpctls_srv_disconnect(uint64_t sec, uint64_t usec, - uint64_t ssl, int procpos, uint32_t *reterr); + struct socket *so, uint32_t *reterr); +enum clnt_stat rpctls_cl_handlerecord(void *socookie, uint32_t *reterr); +enum clnt_stat rpctls_srv_handlerecord(void *socookie, uint32_t *reterr); +enum clnt_stat rpctls_cl_disconnect(void *socookie, uint32_t *reterr); +enum clnt_stat rpctls_srv_disconnect(void *socookie, uint32_t *reterr); /* Initialization function for rpcsec_tls. */ int rpctls_init(void); @@ -81,9 +65,6 @@ bool rpctls_getinfo(u_int *maxlen, bool rpctlscd_run, /* String for AUTH_TLS reply verifier. */ #define RPCTLS_START_STRING "STARTTLS" -/* ssl refno value to indicate TLS handshake being done. */ -#define RPCTLS_REFNO_HANDSHAKE 0xFFFFFFFFFFFFFFFFULL - /* Macros for VIMAGE. */ /* Just define the KRPC_VNETxxx() macros as VNETxxx() macros. */ #define KRPC_VNET_NAME(n) VNET_NAME(n) diff --git a/lib/libc/include/generic-freebsd/rpc/svc.h b/lib/libc/include/generic-freebsd/rpc/svc.h index a1bc765bea8c..860c0927b955 100644 --- a/lib/libc/include/generic-freebsd/rpc/svc.h +++ b/lib/libc/include/generic-freebsd/rpc/svc.h @@ -28,9 +28,6 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * from: @(#)svc.h 1.35 88/12/17 SMI - * from: @(#)svc.h 1.27 94/04/25 SMI */ /* @@ -458,6 +455,19 @@ extern SVCXPRT *svc_fd_create(const int, const u_int, const u_int); */ extern SVCXPRT *svcunixfd_create(int, u_int, u_int); +/* + * netlink(4) server creation. To be used to service requests that + * originate from an in-kernel client. + */ +extern SVCXPRT *svc_nl_create(const char *); + +/* + * Arguments to SVC_CONTROL(svc_nl) + */ +enum { + SVCNL_GET_XIDKEY = 1, /* obtain pthread specific key for xid */ +}; + /* * Memory based rpc (for speed check and testing) */ diff --git a/lib/libc/include/generic-freebsd/rpc/svc_auth.h b/lib/libc/include/generic-freebsd/rpc/svc_auth.h index 6f035780510e..4e206823638f 100644 --- a/lib/libc/include/generic-freebsd/rpc/svc_auth.h +++ b/lib/libc/include/generic-freebsd/rpc/svc_auth.h @@ -28,9 +28,6 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * from: @(#)svc_auth.h 1.6 86/07/16 SMI - * @(#)svc_auth.h 2.1 88/07/29 4.0 RPCSRC */ /* diff --git a/lib/libc/include/generic-freebsd/rpc/svc_soc.h b/lib/libc/include/generic-freebsd/rpc/svc_soc.h index 36d1defe9206..8513e48042e0 100644 --- a/lib/libc/include/generic-freebsd/rpc/svc_soc.h +++ b/lib/libc/include/generic-freebsd/rpc/svc_soc.h @@ -41,7 +41,6 @@ #define _RPC_SVC_SOC_H #include -/* #pragma ident "@(#)svc_soc.h 1.11 94/04/25 SMI" */ /* svc_soc.h 1.8 89/05/01 SMI */ /* diff --git a/lib/libc/include/generic-freebsd/rpc/types.h b/lib/libc/include/generic-freebsd/rpc/types.h index 0a99cedb2577..691feec8da55 100644 --- a/lib/libc/include/generic-freebsd/rpc/types.h +++ b/lib/libc/include/generic-freebsd/rpc/types.h @@ -28,9 +28,6 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * from: @(#)types.h 1.18 87/07/24 SMI - * from: @(#)types.h 2.3 88/08/15 4.0 RPCSRC */ /* diff --git a/lib/libc/include/generic-freebsd/rpc/xdr.h b/lib/libc/include/generic-freebsd/rpc/xdr.h index 4fa2b95d8641..d614b6dcbd5d 100644 --- a/lib/libc/include/generic-freebsd/rpc/xdr.h +++ b/lib/libc/include/generic-freebsd/rpc/xdr.h @@ -28,9 +28,6 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * from: @(#)xdr.h 1.19 87/04/22 SMI - * from: @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC */ /* diff --git a/lib/libc/include/generic-freebsd/rpcsvc/bootparam_prot.x b/lib/libc/include/generic-freebsd/rpcsvc/bootparam_prot.x index 418bd5e9714a..30f2fd811226 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/bootparam_prot.x +++ b/lib/libc/include/generic-freebsd/rpcsvc/bootparam_prot.x @@ -45,12 +45,6 @@ %#include %#include %#include -#else -%#ifndef lint -%/*static char sccsid[] = "from: @(#)bootparam_prot.x 1.2 87/06/24 Copyr 1987 Sun Micro";*/ -%/*static char sccsid[] = "from: @(#)bootparam_prot.x 2.1 88/08/01 4.0 RPCSRC";*/ -%#endif /* not lint */ -%#include #endif const MAX_MACHINE_NAME = 255; diff --git a/lib/libc/include/generic-freebsd/rpcsvc/crypt.x b/lib/libc/include/generic-freebsd/rpcsvc/crypt.x index 1eddfa8783b3..e3e14429d79f 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/crypt.x +++ b/lib/libc/include/generic-freebsd/rpcsvc/crypt.x @@ -30,10 +30,6 @@ * SUCH DAMAGE. */ -#ifndef RPC_HDR -%#include -#endif - /* * This protocol definition exists because of the U.S. government and * its stupid export laws. We can't export DES code from the United diff --git a/lib/libc/include/generic-freebsd/rpcsvc/key_prot.h b/lib/libc/include/generic-freebsd/rpcsvc/key_prot.h index f34d0133dae0..4541929b6a0d 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/key_prot.h +++ b/lib/libc/include/generic-freebsd/rpcsvc/key_prot.h @@ -42,10 +42,6 @@ extern "C" { * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* From: #pragma ident "@(#)key_prot.x 1.7 94/04/29 SMI" */ -/* Copyright (c) 1990, 1991 Sun Microsystems, Inc. */ -#include - /* * Compiled from key_prot.x using rpcgen. * DO NOT EDIT THIS FILE! diff --git a/lib/libc/include/generic-freebsd/rpcsvc/key_prot.x b/lib/libc/include/generic-freebsd/rpcsvc/key_prot.x index d7f1d11f3bd1..4d4d1f134122 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/key_prot.x +++ b/lib/libc/include/generic-freebsd/rpcsvc/key_prot.x @@ -45,10 +45,6 @@ * requirements. */ -%/* From: #pragma ident "@(#)key_prot.x 1.7 94/04/29 SMI" */ -%/* Copyright (c) 1990, 1991 Sun Microsystems, Inc. */ -%#include -% %/* % * Compiled from key_prot.x using rpcgen. % * DO NOT EDIT THIS FILE! diff --git a/lib/libc/include/generic-freebsd/rpcsvc/klm_prot.x b/lib/libc/include/generic-freebsd/rpcsvc/klm_prot.x index 4a25d1d45572..5dd5873743bd 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/klm_prot.x +++ b/lib/libc/include/generic-freebsd/rpcsvc/klm_prot.x @@ -38,14 +38,6 @@ * above the kernel. */ -#ifndef RPC_HDR -%#ifndef lint -%/*static char sccsid[] = "from: @(#)klm_prot.x 1.7 87/07/08 Copyr 1987 Sun Micro";*/ -%/*static char sccsid[] = "from: @(#)klm_prot.x 2.1 88/08/01 4.0 RPCSRC";*/ -%#endif /* not lint */ -%#include -#endif - const LM_MAXSTRLEN = 1024; /* diff --git a/lib/libc/include/generic-freebsd/rpcsvc/mount.x b/lib/libc/include/generic-freebsd/rpcsvc/mount.x index 5d65c3ce676e..9f6fa6384294 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/mount.x +++ b/lib/libc/include/generic-freebsd/rpcsvc/mount.x @@ -33,14 +33,6 @@ * Protocol description for the mount program */ -#ifndef RPC_HDR -%#ifndef lint -%/*static char sccsid[] = "from: @(#)mount.x 1.2 87/09/18 Copyr 1987 Sun Micro";*/ -%/*static char sccsid[] = "from: @(#)mount.x 2.1 88/08/01 4.0 RPCSRC";*/ -%#endif /* not lint */ -%#include -#endif - const MNTPATHLEN = 1024; /* maximum bytes in a pathname argument */ const MNTNAMLEN = 255; /* maximum bytes in a name argument */ const FHSIZE = 32; /* size in bytes of a file handle */ diff --git a/lib/libc/include/generic-freebsd/rpcsvc/nfs_prot.x b/lib/libc/include/generic-freebsd/rpcsvc/nfs_prot.x index 3057bd31d5fe..13d65a3dc4c4 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/nfs_prot.x +++ b/lib/libc/include/generic-freebsd/rpcsvc/nfs_prot.x @@ -29,14 +29,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef RPC_HDR -%#ifndef lint -%/*static char sccsid[] = "from: @(#)nfs_prot.x 1.2 87/10/12 Copyr 1987 Sun Micro";*/ -%/*static char sccsid[] = "from: @(#)nfs_prot.x 2.1 88/08/01 4.0 RPCSRC";*/ -%#endif /* not lint */ -%#include -#endif - const NFS_PORT = 2049; const NFS_MAXDATA = 8192; const NFS_MAXPATHLEN = 1024; diff --git a/lib/libc/include/generic-freebsd/rpcsvc/nis.x b/lib/libc/include/generic-freebsd/rpcsvc/nis.x index e6d151cd5e7f..80788f7ea6de 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/nis.x +++ b/lib/libc/include/generic-freebsd/rpcsvc/nis.x @@ -29,12 +29,7 @@ % * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. % */ -#ifndef RPC_HDR -%#include -#endif - /* - * From 4.1 : @(#)nis.x 1.61 Copyright 1989 Sun Microsystems * * RPC Language Protocol description file for NIS Plus * This version : 1.61 diff --git a/lib/libc/include/generic-freebsd/rpcsvc/nis_cache.x b/lib/libc/include/generic-freebsd/rpcsvc/nis_cache.x index e169ca9f26c6..cc41c616b159 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/nis_cache.x +++ b/lib/libc/include/generic-freebsd/rpcsvc/nis_cache.x @@ -35,12 +35,6 @@ * All Rights Reserved. */ -/* From: %#pragma ident "@(#)nis_cache.x 1.11 94/05/03 SMI" */ - -#ifndef RPC_HDR -%#include -#endif - #ifdef RPC_HDR %#include %#include diff --git a/lib/libc/include/generic-freebsd/rpcsvc/nis_callback.x b/lib/libc/include/generic-freebsd/rpcsvc/nis_callback.x index ed53c0d7950b..13228a2782a1 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/nis_callback.x +++ b/lib/libc/include/generic-freebsd/rpcsvc/nis_callback.x @@ -36,14 +36,7 @@ * All Rights Reserved. */ -/* From: %#pragma ident "@(#)nis_callback.x 1.7 94/05/03 SMI" */ - -#ifndef RPC_HDR -%#include -#endif - /* - * "@(#)zns_cback.x 1.2 90/09/10 Copyr 1990 Sun Micro" * * RPCL description of the Callback Service. */ diff --git a/lib/libc/include/generic-freebsd/rpcsvc/nis_db.h b/lib/libc/include/generic-freebsd/rpcsvc/nis_db.h index 0442f9103370..d89b6120b626 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/nis_db.h +++ b/lib/libc/include/generic-freebsd/rpcsvc/nis_db.h @@ -42,8 +42,6 @@ #define _RPCSVC_NIS_DB_H -/* From: #pragma ident "@(#)nis_db.h 1.8 94/05/03 SMI" */ - /* * Note: although the version of shipped with Solaris * 2.5/2.5.x is actually older than this one (according to the ident diff --git a/lib/libc/include/generic-freebsd/rpcsvc/nis_object.x b/lib/libc/include/generic-freebsd/rpcsvc/nis_object.x index cb0f1c9f50d7..e09154b18e7a 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/nis_object.x +++ b/lib/libc/include/generic-freebsd/rpcsvc/nis_object.x @@ -36,8 +36,6 @@ * All Rights Reserved. */ -/* From: %#pragma ident "@(#)nis_object.x 1.10 94/05/03 SMI" */ - #if RPC_HDR % %#ifndef __nis_object_h diff --git a/lib/libc/include/generic-freebsd/rpcsvc/nis_tags.h b/lib/libc/include/generic-freebsd/rpcsvc/nis_tags.h index 34a7301a6a9c..011ecf8ded9c 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/nis_tags.h +++ b/lib/libc/include/generic-freebsd/rpcsvc/nis_tags.h @@ -45,7 +45,6 @@ #ifndef _RPCSVC_NIS_TAGS_H #define _RPCSVC_NIS_TAGS_H -/* From: #pragma ident "@(#)nis_tags.h 1.10 94/05/03 SMI" */ /* from file: zns_tags.h 1.7 Copyright (c) 1990 Sun Microsystems */ #ifdef __cplusplus diff --git a/lib/libc/include/generic-freebsd/rpcsvc/nislib.h b/lib/libc/include/generic-freebsd/rpcsvc/nislib.h index 38557bf9ebe1..8b84056f6132 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/nislib.h +++ b/lib/libc/include/generic-freebsd/rpcsvc/nislib.h @@ -39,8 +39,6 @@ #ifndef _RPCSVC_NISLIB_H #define _RPCSVC_NISLIB_H -/* From: #pragma ident "@(#)nislib.h 1.16 94/05/03 SMI" */ - #ifdef __cplusplus extern "C" { #endif diff --git a/lib/libc/include/generic-freebsd/rpcsvc/nlm_prot.x b/lib/libc/include/generic-freebsd/rpcsvc/nlm_prot.x index 7c11e427df10..f809d31d5059 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/nlm_prot.x +++ b/lib/libc/include/generic-freebsd/rpcsvc/nlm_prot.x @@ -8,14 +8,8 @@ #ifdef RPC_HDR %#define LM_MAXSTRLEN 1024 %#define MAXNAMELEN LM_MAXSTRLEN+1 -#else -%#include -%#ifndef lint -%/*static char sccsid[] = "from: @(#)nlm_prot.x 1.8 87/09/21 Copyr 1987 Sun Micro";*/ -%/*static char sccsid[] = "from: * @(#)nlm_prot.x 2.1 88/08/01 4.0 RPCSRC";*/ -%__RCSID("$NetBSD: nlm_prot.x,v 1.6 2000/06/07 14:30:15 bouyer Exp $"); -%#endif /* not lint */ #endif +/* $NetBSD: nlm_prot.x,v 1.6 2000/06/07 14:30:15 bouyer Exp $ */ /* * status of a call to the lock manager diff --git a/lib/libc/include/generic-freebsd/rpcsvc/rex.x b/lib/libc/include/generic-freebsd/rpcsvc/rex.x index 1554d863870e..d8256467fa4e 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/rex.x +++ b/lib/libc/include/generic-freebsd/rpcsvc/rex.x @@ -33,14 +33,6 @@ * Remote execution (rex) protocol specification */ -#ifndef RPC_HDR -%#ifndef lint -%/*static char sccsid[] = "from: @(#)rex.x 1.3 87/09/18 Copyr 1987 Sun Micro";*/ -%/*static char sccsid[] = "from: @(#)rex.x 2.1 88/08/01 4.0 RPCSRC";*/ -%#endif /* not lint */ -%#include -#endif - const STRINGSIZE = 1024; typedef string rexstring<1024>; diff --git a/lib/libc/include/generic-freebsd/rpcsvc/rnusers.x b/lib/libc/include/generic-freebsd/rpcsvc/rnusers.x index 5f34fcb959f7..8ab76635eb2a 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/rnusers.x +++ b/lib/libc/include/generic-freebsd/rpcsvc/rnusers.x @@ -33,14 +33,6 @@ * Find out about remote users */ -#ifndef RPC_HDR -%#ifndef lint -%/*static char sccsid[] = "from: @(#)rnusers.x 1.2 87/09/20 Copyr 1987 Sun Micro";*/ -%/*static char sccsid[] = "from: @(#)rnusers.x 2.1 88/08/01 4.0 RPCSRC";*/ -%#endif /* not lint */ -%#include -#endif - const MAXUSERS = 100; const MAXUTLEN = 256; diff --git a/lib/libc/include/generic-freebsd/rpcsvc/rquota.x b/lib/libc/include/generic-freebsd/rpcsvc/rquota.x index cc14494332f8..cb4c7d47abb5 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/rquota.x +++ b/lib/libc/include/generic-freebsd/rpcsvc/rquota.x @@ -1,15 +1,8 @@ -/* @(#)rquota.x 2.1 88/08/01 4.0 RPCSRC */ -/* @(#)rquota.x 1.2 87/09/20 Copyr 1987 Sun Micro */ - /* * Remote quota protocol * Requires unix authentication */ -#ifndef RPC_HDR -%#include -#endif - const RQ_PATHLEN = 1024; struct sq_dqblk { diff --git a/lib/libc/include/generic-freebsd/rpcsvc/rstat.x b/lib/libc/include/generic-freebsd/rpcsvc/rstat.x index 3c3049b9de0e..d1e8f2438e4b 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/rstat.x +++ b/lib/libc/include/generic-freebsd/rpcsvc/rstat.x @@ -44,13 +44,6 @@ % %#endif /* ndef FSCALE */ -#else - -%#ifndef lint -%/*static char sccsid[] = "from: @(#)rstat.x 1.2 87/09/18 Copyr 1987 Sun Micro";*/ -%/*static char sccsid[] = "from: @(#)rstat.x 2.2 88/08/01 4.0 RPCSRC";*/ -%#endif /* not lint */ -%#include #endif /* def RPC_HDR */ const RSTAT_CPUSTATES = 4; diff --git a/lib/libc/include/generic-freebsd/rpcsvc/rwall.h b/lib/libc/include/generic-freebsd/rpcsvc/rwall.h index 58d95e31659e..cd1aa710dd29 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/rwall.h +++ b/lib/libc/include/generic-freebsd/rpcsvc/rwall.h @@ -45,8 +45,6 @@ extern "C" { * Copyright (c) 1984, 1990 by Sun Microsystems, Inc. */ -/* from @(#)rwall.x 1.6 91/03/11 TIRPC 1.0 */ - #ifndef _rpcsvc_rwall_h #define _rpcsvc_rwall_h diff --git a/lib/libc/include/generic-freebsd/rpcsvc/rwall.x b/lib/libc/include/generic-freebsd/rpcsvc/rwall.x index 3bfbae868242..67e600a54ecf 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/rwall.x +++ b/lib/libc/include/generic-freebsd/rpcsvc/rwall.x @@ -31,8 +31,6 @@ %/* % * Copyright (c) 1984, 1990 by Sun Microsystems, Inc. % */ -% -%/* from @(#)rwall.x 1.6 91/03/11 TIRPC 1.0 */ #ifdef RPC_HDR % diff --git a/lib/libc/include/generic-freebsd/rpcsvc/sm_inter.x b/lib/libc/include/generic-freebsd/rpcsvc/sm_inter.x index 5565947e5ad6..b7ff3c17c8fd 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/sm_inter.x +++ b/lib/libc/include/generic-freebsd/rpcsvc/sm_inter.x @@ -1,6 +1,3 @@ -/* @(#)sm_inter.x 2.2 88/08/01 4.0 RPCSRC */ -/* @(#)sm_inter.x 1.7 87/06/24 Copyr 1987 Sun Micro */ - /*- * Copyright (c) 2010, Oracle America, Inc. * @@ -38,10 +35,6 @@ * */ -#ifndef RPC_HDR -%#include -#endif - program SM_PROG { version SM_VERS { /* res_stat = stat_succ if status monitor agrees to monitor */ diff --git a/lib/libc/include/generic-freebsd/rpcsvc/spray.x b/lib/libc/include/generic-freebsd/rpcsvc/spray.x index 2fe910fe33f8..c8d9ba33c1ef 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/spray.x +++ b/lib/libc/include/generic-freebsd/rpcsvc/spray.x @@ -34,14 +34,6 @@ * Useful for testing flakiness of network interfaces */ -#ifndef RPC_HDR -%#ifndef lint -%/*static char sccsid[] = "from: @(#)spray.x 1.2 87/09/18 Copyr 1987 Sun Micro";*/ -%/*static char sccsid[] = "from: @(#)spray.x 2.1 88/08/01 4.0 RPCSRC";*/ -%#endif /* not lint */ -%#include -#endif - const SPRAYMAX = 8845; /* max amount can spray */ /* diff --git a/lib/libc/include/generic-freebsd/rpcsvc/yp.x b/lib/libc/include/generic-freebsd/rpcsvc/yp.x index 2234810d35b7..8af521cf38ae 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/yp.x +++ b/lib/libc/include/generic-freebsd/rpcsvc/yp.x @@ -1,5 +1,3 @@ -/* @(#)yp.x 2.1 88/08/01 4.0 RPCSRC */ - /*- * Copyright (c) 2010, Oracle America, Inc. * @@ -35,10 +33,6 @@ * Protocol description file for the Yellow Pages Service */ -#ifndef RPC_HDR -%#include -#endif - const YPMAXRECORD = 16777216; const YPMAXDOMAIN = 64; const YPMAXMAP = 64; diff --git a/lib/libc/include/generic-freebsd/rpcsvc/yp_prot.h b/lib/libc/include/generic-freebsd/rpcsvc/yp_prot.h index dcc0a37f1916..f7c7935e6b2d 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/yp_prot.h +++ b/lib/libc/include/generic-freebsd/rpcsvc/yp_prot.h @@ -271,7 +271,7 @@ struct ypbind_setdom { * * Sun says: * "Protocol between clients (ypxfr, only) and yppush - * yppush speaks a protocol in the transient range, which + * speaks a protocol in the transient range, which * is supplied to ypxfr as a command-line parameter when it * is activated by ypserv." * diff --git a/lib/libc/include/generic-freebsd/rpcsvc/yppasswd.x b/lib/libc/include/generic-freebsd/rpcsvc/yppasswd.x index 7d2efba53fb2..0f2cfba00cc2 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/yppasswd.x +++ b/lib/libc/include/generic-freebsd/rpcsvc/yppasswd.x @@ -34,14 +34,6 @@ * Requires unix authentication */ -#ifndef RPC_HDR -%#ifndef lint -%/*static char sccsid[] = "from: @(#)yppasswd.x 1.1 87/04/13 Copyr 1987 Sun Micro";*/ -%/*static char sccsid[] = "from: @(#)yppasswd.x 2.1 88/08/01 4.0 RPCSRC";*/ -%#endif /* not lint */ -%#include -#endif - program YPPASSWDPROG { version YPPASSWDVERS { /* diff --git a/lib/libc/include/generic-freebsd/rpcsvc/ypupdate_prot.h b/lib/libc/include/generic-freebsd/rpcsvc/ypupdate_prot.h index dca7d59bfd64..44609b8488b1 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/ypupdate_prot.h +++ b/lib/libc/include/generic-freebsd/rpcsvc/ypupdate_prot.h @@ -45,7 +45,6 @@ extern "C" { * Copyright (c) 1986, 1990 by Sun Microsystems, Inc. */ -/* from @(#)ypupdate_prot.x 1.3 91/03/11 TIRPC 1.0 */ /* * Compiled from ypupdate_prot.x using rpcgen diff --git a/lib/libc/include/generic-freebsd/rpcsvc/ypupdate_prot.x b/lib/libc/include/generic-freebsd/rpcsvc/ypupdate_prot.x index edca0da83268..8bee4e0ce981 100644 --- a/lib/libc/include/generic-freebsd/rpcsvc/ypupdate_prot.x +++ b/lib/libc/include/generic-freebsd/rpcsvc/ypupdate_prot.x @@ -32,7 +32,6 @@ % * Copyright (c) 1986, 1990 by Sun Microsystems, Inc. % */ % -%/* from @(#)ypupdate_prot.x 1.3 91/03/11 TIRPC 1.0 */ #ifndef RPC_HDR %#include #endif diff --git a/lib/libc/include/generic-freebsd/runetype.h b/lib/libc/include/generic-freebsd/runetype.h index 88601f7232af..cb344862a53d 100644 --- a/lib/libc/include/generic-freebsd/runetype.h +++ b/lib/libc/include/generic-freebsd/runetype.h @@ -30,8 +30,6 @@ * 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. - * - * @(#)runetype.h 8.1 (Berkeley) 6/2/93 */ #ifndef _RUNETYPE_H_ diff --git a/lib/libc/include/generic-freebsd/sched.h b/lib/libc/include/generic-freebsd/sched.h index ce0dc8983afc..7413acd0bbb6 100644 --- a/lib/libc/include/generic-freebsd/sched.h +++ b/lib/libc/include/generic-freebsd/sched.h @@ -29,7 +29,6 @@ #ifndef __SCHED_H__ #define __SCHED_H__ -#include #include #include #if __BSD_VISIBLE diff --git a/lib/libc/include/generic-freebsd/security/audit/audit.h b/lib/libc/include/generic-freebsd/security/audit/audit.h index abdacf6b1754..642b74b03f0b 100644 --- a/lib/libc/include/generic-freebsd/security/audit/audit.h +++ b/lib/libc/include/generic-freebsd/security/audit/audit.h @@ -1,19 +1,18 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * - * Copyright (c) 2005-2009 Apple Inc. - * Copyright (c) 2016 Robert N. M. Watson + * Copyright (c) 1999-2005 Apple Inc. + * Copyright (c) 2016-2018 Robert N. M. Watson * All rights reserved. * - * Portions of this software were developed by BAE Systems, the University of - * Cambridge Computer Laboratory, and Memorial University under DARPA/AFRL - * contract FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent - * Computing (TC) research program. + * This software was developed by BAE Systems, the University of Cambridge + * Computer Laboratory, and Memorial University under DARPA/AFRL contract + * FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent Computing + * (TC) research program. * * 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 @@ -23,323 +22,460 @@ * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS 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 APPLE OR ITS 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 _BSM_AUDIT_H -#define _BSM_AUDIT_H - -#include -#include - -#define AUDIT_RECORD_MAGIC 0x828a0f1b -#define MAX_AUDIT_RECORDS 20 -#define MAXAUDITDATA (0x8000 - 1) -#define MAX_AUDIT_RECORD_SIZE MAXAUDITDATA -#define MIN_AUDIT_FILE_SIZE (512 * 1024) - -/* - * Minimum noumber of free blocks on the filesystem containing the audit - * log necessary to avoid a hard log rotation. DO NOT SET THIS VALUE TO 0 - * as the kernel does an unsigned compare, plus we want to leave a few blocks - * free so userspace can terminate the log, etc. - */ -#define AUDIT_HARD_LIMIT_FREE_BLOCKS 4 - -/* - * Triggers for the audit daemon. + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS 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 APPLE OR ITS 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. */ -#define AUDIT_TRIGGER_MIN 1 -#define AUDIT_TRIGGER_LOW_SPACE 1 /* Below low watermark. */ -#define AUDIT_TRIGGER_ROTATE_KERNEL 2 /* Kernel requests rotate. */ -#define AUDIT_TRIGGER_READ_FILE 3 /* Re-read config file. */ -#define AUDIT_TRIGGER_CLOSE_AND_DIE 4 /* Terminate audit. */ -#define AUDIT_TRIGGER_NO_SPACE 5 /* Below min free space. */ -#define AUDIT_TRIGGER_ROTATE_USER 6 /* User requests rotate. */ -#define AUDIT_TRIGGER_INITIALIZE 7 /* User initialize of auditd. */ -#define AUDIT_TRIGGER_EXPIRE_TRAILS 8 /* User expiration of trails. */ -#define AUDIT_TRIGGER_MAX 8 /* - * The special device filename (FreeBSD). + * This header includes function prototypes and type definitions that are + * necessary for the kernel as a whole to interact with the audit subsystem. */ -#define AUDITDEV_FILENAME "audit" -#define AUDIT_TRIGGER_FILE ("/dev/" AUDITDEV_FILENAME) -/* - * Pre-defined audit IDs - */ -#define AU_DEFAUDITID (uid_t)(-1) -#define AU_DEFAUDITSID 0 -#define AU_ASSIGN_ASID -1 +#ifndef _SECURITY_AUDIT_KERNEL_H_ +#define _SECURITY_AUDIT_KERNEL_H_ -/* - * IPC types. - */ -#define AT_IPC_MSG ((u_char)1) /* Message IPC id. */ -#define AT_IPC_SEM ((u_char)2) /* Semaphore IPC id. */ -#define AT_IPC_SHM ((u_char)3) /* Shared mem IPC id. */ +#ifndef _KERNEL +#error "no user-serviceable parts inside" +#endif -/* - * Audit conditions. - */ -#define AUC_UNSET 0 -#define AUC_AUDITING 1 -#define AUC_NOAUDIT 2 -#define AUC_DISABLED -1 +#include -/* - * auditon(2) commands. - */ -#define A_OLDGETPOLICY 2 -#define A_OLDSETPOLICY 3 -#define A_GETKMASK 4 -#define A_SETKMASK 5 -#define A_OLDGETQCTRL 6 -#define A_OLDSETQCTRL 7 -#define A_GETCWD 8 -#define A_GETCAR 9 -#define A_GETSTAT 12 -#define A_SETSTAT 13 -#define A_SETUMASK 14 -#define A_SETSMASK 15 -#define A_OLDGETCOND 20 -#define A_OLDSETCOND 21 -#define A_GETCLASS 22 -#define A_SETCLASS 23 -#define A_GETPINFO 24 -#define A_SETPMASK 25 -#define A_SETFSIZE 26 -#define A_GETFSIZE 27 -#define A_GETPINFO_ADDR 28 -#define A_GETKAUDIT 29 -#define A_SETKAUDIT 30 -#define A_SENDTRIGGER 31 -#define A_GETSINFO_ADDR 32 -#define A_GETPOLICY 33 -#define A_SETPOLICY 34 -#define A_GETQCTRL 35 -#define A_SETQCTRL 36 -#define A_GETCOND 37 -#define A_SETCOND 38 -#define A_GETEVENT 39 /* Get audit event-to-name mapping. */ -#define A_SETEVENT 40 /* Set audit event-to-name mapping. */ +#include +#include /* - * Audit policy controls. - */ -#define AUDIT_CNT 0x0001 -#define AUDIT_AHLT 0x0002 -#define AUDIT_ARGV 0x0004 -#define AUDIT_ARGE 0x0008 -#define AUDIT_SEQ 0x0010 -#define AUDIT_WINDATA 0x0020 -#define AUDIT_USER 0x0040 -#define AUDIT_GROUP 0x0080 -#define AUDIT_TRAIL 0x0100 -#define AUDIT_PATH 0x0200 -#define AUDIT_SCNT 0x0400 -#define AUDIT_PUBLIC 0x0800 -#define AUDIT_ZONENAME 0x1000 -#define AUDIT_PERZONE 0x2000 - -/* - * Default audit queue control parameters. - */ -#define AQ_HIWATER 100 -#define AQ_MAXHIGH 10000 -#define AQ_LOWATER 10 -#define AQ_BUFSZ MAXAUDITDATA -#define AQ_MAXBUFSZ 1048576 - -/* - * Default minimum percentage free space on file system. - */ -#define AU_FS_MINFREE 20 - -/* - * Type definitions used indicating the length of variable length addresses - * in tokens containing addresses, such as header fields. - */ -#define AU_IPv4 4 -#define AU_IPv6 16 - -__BEGIN_DECLS - -typedef uid_t au_id_t; -typedef pid_t au_asid_t; -typedef u_int16_t au_event_t; -typedef u_int16_t au_emod_t; -typedef u_int32_t au_class_t; -typedef u_int64_t au_asflgs_t __attribute__ ((aligned (8))); - -struct au_tid { - u_int32_t port; /* XXX dev_t compatibility */ - u_int32_t machine; -}; -typedef struct au_tid au_tid_t; - -struct au_tid_addr { - u_int32_t at_port; /* XXX dev_t compatibility */ - u_int32_t at_type; - u_int32_t at_addr[4]; -}; -typedef struct au_tid_addr au_tid_addr_t; - -struct au_mask { - unsigned int am_success; /* Success bits. */ - unsigned int am_failure; /* Failure bits. */ -}; -typedef struct au_mask au_mask_t; - -struct auditinfo { - au_id_t ai_auid; /* Audit user ID. */ - au_mask_t ai_mask; /* Audit masks. */ - au_tid_t ai_termid; /* Terminal ID. */ - au_asid_t ai_asid; /* Audit session ID. */ -}; -typedef struct auditinfo auditinfo_t; - -struct auditinfo_addr { - au_id_t ai_auid; /* Audit user ID. */ - au_mask_t ai_mask; /* Audit masks. */ - au_tid_addr_t ai_termid; /* Terminal ID. */ - au_asid_t ai_asid; /* Audit session ID. */ - au_asflgs_t ai_flags; /* Audit session flags. */ -}; -typedef struct auditinfo_addr auditinfo_addr_t; - -struct auditpinfo { - pid_t ap_pid; /* ID of target process. */ - au_id_t ap_auid; /* Audit user ID. */ - au_mask_t ap_mask; /* Audit masks. */ - au_tid_t ap_termid; /* Terminal ID. */ - au_asid_t ap_asid; /* Audit session ID. */ -}; -typedef struct auditpinfo auditpinfo_t; - -struct auditpinfo_addr { - pid_t ap_pid; /* ID of target process. */ - au_id_t ap_auid; /* Audit user ID. */ - au_mask_t ap_mask; /* Audit masks. */ - au_tid_addr_t ap_termid; /* Terminal ID. */ - au_asid_t ap_asid; /* Audit session ID. */ - au_asflgs_t ap_flags; /* Audit session flags. */ -}; -typedef struct auditpinfo_addr auditpinfo_addr_t; - -struct au_session { - auditinfo_addr_t *as_aia_p; /* Ptr to full audit info. */ - au_mask_t as_mask; /* Process Audit Masks. */ -}; -typedef struct au_session au_session_t; - -/* - * Contents of token_t are opaque outside of libbsm. - */ -typedef struct au_token token_t; - -/* - * Kernel audit queue control parameters: - * Default: Maximum: - * aq_hiwater: AQ_HIWATER (100) AQ_MAXHIGH (10000) - * aq_lowater: AQ_LOWATER (10) td_pflags & TDP_AUDITREC)) + +#define AUDIT_ARG_ADDR(addr) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_addr((addr)); \ +} while (0) + +#define AUDIT_ARG_ARGV(argv, argc, length) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_argv((argv), (argc), (length)); \ +} while (0) + +#define AUDIT_ARG_ATFD1(atfd) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_atfd1((atfd)); \ +} while (0) + +#define AUDIT_ARG_ATFD2(atfd) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_atfd2((atfd)); \ +} while (0) + +#define AUDIT_ARG_AUDITON(udata) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_auditon((udata)); \ +} while (0) + +#define AUDIT_ARG_CMD(cmd) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_cmd((cmd)); \ +} while (0) + +#define AUDIT_ARG_DEV(dev) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_dev((dev)); \ +} while (0) + +#define AUDIT_ARG_EGID(egid) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_egid((egid)); \ +} while (0) + +#define AUDIT_ARG_ENVV(envv, envc, length) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_envv((envv), (envc), (length)); \ +} while (0) + +#define AUDIT_ARG_EXIT(status, retval) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_exit((status), (retval)); \ +} while (0) + +#define AUDIT_ARG_EUID(euid) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_euid((euid)); \ +} while (0) + +#define AUDIT_ARG_FD(fd) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_fd((fd)); \ +} while (0) + +#define AUDIT_ARG_FILE(p, fp) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_file((p), (fp)); \ +} while (0) + +#define AUDIT_ARG_FFLAGS(fflags) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_fflags((fflags)); \ +} while (0) + +#define AUDIT_ARG_GID(gid) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_gid((gid)); \ +} while (0) + +#define AUDIT_ARG_GROUPSET(gidset, gidset_size) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_groupset((gidset), (gidset_size)); \ +} while (0) + +#define AUDIT_ARG_LOGIN(login) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_login((login)); \ +} while (0) + +#define AUDIT_ARG_MODE(mode) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_mode((mode)); \ +} while (0) + +#define AUDIT_ARG_OWNER(uid, gid) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_owner((uid), (gid)); \ +} while (0) + +#define AUDIT_ARG_PID(pid) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_pid((pid)); \ +} while (0) + +#define AUDIT_ARG_POSIX_IPC_PERM(uid, gid, mode) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_posix_ipc_perm((uid), (gid), (mod)); \ +} while (0) + +#define AUDIT_ARG_PROCESS(p) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_process((p)); \ +} while (0) + +#define AUDIT_ARG_RGID(rgid) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_rgid((rgid)); \ +} while (0) + +#define AUDIT_ARG_RIGHTS(rights) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_rights((rights)); \ +} while (0) + +#define AUDIT_ARG_FCNTL_RIGHTS(fcntlrights) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_fcntl_rights((fcntlrights)); \ +} while (0) + +#define AUDIT_ARG_RUID(ruid) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_ruid((ruid)); \ +} while (0) + +#define AUDIT_ARG_SIGNUM(signum) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_signum((signum)); \ +} while (0) + +#define AUDIT_ARG_SGID(sgid) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_sgid((sgid)); \ +} while (0) + +#define AUDIT_ARG_SOCKET(sodomain, sotype, soprotocol) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_socket((sodomain), (sotype), (soprotocol)); \ +} while (0) + +#define AUDIT_ARG_SOCKADDR(td, dirfd, sa) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_sockaddr((td), (dirfd), (sa)); \ +} while (0) + +#define AUDIT_ARG_SUID(suid) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_suid((suid)); \ +} while (0) + +#define AUDIT_ARG_SVIPC_CMD(cmd) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_svipc_cmd((cmd)); \ +} while (0) + +#define AUDIT_ARG_SVIPC_PERM(perm) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_svipc_perm((perm)); \ +} while (0) + +#define AUDIT_ARG_SVIPC_ID(id) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_svipc_id((id)); \ +} while (0) + +#define AUDIT_ARG_SVIPC_ADDR(addr) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_svipc_addr((addr)); \ +} while (0) + +#define AUDIT_ARG_SVIPC_WHICH(which) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_svipc_which((which)); \ +} while (0) + +#define AUDIT_ARG_TEXT(text) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_text((text)); \ +} while (0) + +#define AUDIT_ARG_UID(uid) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_uid((uid)); \ +} while (0) + +#define AUDIT_ARG_UPATH1(td, dirfd, upath) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_upath1((td), (dirfd), (upath)); \ +} while (0) + +#define AUDIT_ARG_UPATH1_CANON(upath) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_upath1_canon((upath)); \ +} while (0) + +#define AUDIT_ARG_UPATH2(td, dirfd, upath) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_upath2((td), (dirfd), (upath)); \ +} while (0) + +#define AUDIT_ARG_UPATH2_CANON(upath) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_upath2_canon((upath)); \ +} while (0) + +#define AUDIT_ARG_UPATH1_VP(td, rdir, cdir, upath) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_upath1_vp((td), (rdir), (cdir), (upath)); \ +} while (0) + +#define AUDIT_ARG_UPATH2_VP(td, rdir, cdir, upath) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_upath2_vp((td), (rdir), (cdir), (upath)); \ +} while (0) + +#define AUDIT_ARG_VALUE(value) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_value((value)); \ +} while (0) + +#define AUDIT_ARG_VNODE1(vp) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_vnode1((vp)); \ +} while (0) + +#define AUDIT_ARG_VNODE2(vp) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_vnode2((vp)); \ +} while (0) + +#define AUDIT_SYSCALL_ENABLED() audit_syscalls_enabled + +#define AUDIT_SYSCALL_ENTER(code, td) ({ \ + bool _audit_entered = false; \ + if (audit_syscalls_enabled) { \ + audit_syscall_enter(code, td); \ + _audit_entered = true; \ + } \ + _audit_entered; \ +}) /* - * Event-to-name mapping. + * Wrap the audit_syscall_exit() function so that it is called only when + * we have a audit record on the thread. Audit records can persist after + * auditing is disabled, so we don't just check audit_syscalls_enabled here. */ -#define EVNAMEMAP_NAME_SIZE 64 -struct au_evname_map { - au_event_t en_number; - char en_name[EVNAMEMAP_NAME_SIZE]; -}; -typedef struct au_evname_map au_evname_map_t; +#define AUDIT_SYSCALL_EXIT(error, td) do { \ + if (AUDITING_TD(td)) \ + audit_syscall_exit(error, td); \ +} while (0) /* - * Audit system calls. + * A Macro to wrap the audit_sysclose() function. */ -#if !defined(_KERNEL) && !defined(KERNEL) -int audit(const void *, int); -int auditon(int, void *, int); -int auditctl(const char *); -int getauid(au_id_t *); -int setauid(const au_id_t *); -int getaudit(struct auditinfo *); -int setaudit(const struct auditinfo *); -int getaudit_addr(struct auditinfo_addr *, int); -int setaudit_addr(const struct auditinfo_addr *, int); - -#ifdef __APPLE_API_PRIVATE -#include -mach_port_name_t audit_session_self(void); -au_asid_t audit_session_join(mach_port_name_t port); -#endif /* __APPLE_API_PRIVATE */ - -#endif /* defined(_KERNEL) || defined(KERNEL) */ - -__END_DECLS - -#endif /* !_BSM_AUDIT_H */ \ No newline at end of file +#define AUDIT_SYSCLOSE(td, fd) do { \ + if (AUDITING_TD(td)) \ + audit_sysclose(td, fd); \ +} while (0) + +#else /* !AUDIT */ + +#define AUDIT_ARG_ADDR(addr) +#define AUDIT_ARG_ARGV(argv, argc, length) +#define AUDIT_ARG_ATFD1(atfd) +#define AUDIT_ARG_ATFD2(atfd) +#define AUDIT_ARG_AUDITON(udata) +#define AUDIT_ARG_CMD(cmd) +#define AUDIT_ARG_DEV(dev) +#define AUDIT_ARG_EGID(egid) +#define AUDIT_ARG_ENVV(envv, envc, length) +#define AUDIT_ARG_EXIT(status, retval) +#define AUDIT_ARG_EUID(euid) +#define AUDIT_ARG_FD(fd) +#define AUDIT_ARG_FILE(p, fp) +#define AUDIT_ARG_FFLAGS(fflags) +#define AUDIT_ARG_GID(gid) +#define AUDIT_ARG_GROUPSET(gidset, gidset_size) +#define AUDIT_ARG_LOGIN(login) +#define AUDIT_ARG_MODE(mode) +#define AUDIT_ARG_OWNER(uid, gid) +#define AUDIT_ARG_PID(pid) +#define AUDIT_ARG_POSIX_IPC_PERM(uid, gid, mode) +#define AUDIT_ARG_PROCESS(p) +#define AUDIT_ARG_RGID(rgid) +#define AUDIT_ARG_RIGHTS(rights) +#define AUDIT_ARG_FCNTL_RIGHTS(fcntlrights) +#define AUDIT_ARG_RUID(ruid) +#define AUDIT_ARG_SIGNUM(signum) +#define AUDIT_ARG_SGID(sgid) +#define AUDIT_ARG_SOCKET(sodomain, sotype, soprotocol) +#define AUDIT_ARG_SOCKADDR(td, dirfd, sa) +#define AUDIT_ARG_SUID(suid) +#define AUDIT_ARG_SVIPC_CMD(cmd) +#define AUDIT_ARG_SVIPC_PERM(perm) +#define AUDIT_ARG_SVIPC_ID(id) +#define AUDIT_ARG_SVIPC_ADDR(addr) +#define AUDIT_ARG_SVIPC_WHICH(which) +#define AUDIT_ARG_TEXT(text) +#define AUDIT_ARG_UID(uid) +#define AUDIT_ARG_UPATH1(td, dirfd, upath) +#define AUDIT_ARG_UPATH1_CANON(upath) +#define AUDIT_ARG_UPATH2(td, dirfd, upath) +#define AUDIT_ARG_UPATH2_CANON(upath) +#define AUDIT_ARG_UPATH1_VP(td, rdir, cdir, upath) +#define AUDIT_ARG_UPATH2_VP(td, rdir, cdir, upath) +#define AUDIT_ARG_VALUE(value) +#define AUDIT_ARG_VNODE1(vp) +#define AUDIT_ARG_VNODE2(vp) + +#define AUDITING_TD(td) 0 + +#define AUDIT_SYSCALL_ENABLED() 0 +#define AUDIT_SYSCALL_ENTER(code, td) 0 +#define AUDIT_SYSCALL_EXIT(error, td) + +#define AUDIT_SYSCLOSE(p, fd) + +#endif /* AUDIT */ + +#endif /* !_SECURITY_AUDIT_KERNEL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/security/mac_grantbylabel/mac_grantbylabel.h b/lib/libc/include/generic-freebsd/security/mac_grantbylabel/mac_grantbylabel.h new file mode 100644 index 000000000000..2cfaee3baaf8 --- /dev/null +++ b/lib/libc/include/generic-freebsd/security/mac_grantbylabel/mac_grantbylabel.h @@ -0,0 +1,63 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2018-2023, Juniper Networks, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _SECURITY_MAC_GRANTBYLABEL_H +#define _SECURITY_MAC_GRANTBYLABEL_H + +#include + +#define MAC_GRANTBYLABEL_NAME "mac_grantbylabel" + +/* the bits we use to represent tokens */ +#define GBL_EMPTY (1<<0) +#define GBL_BIND (1<<1) +#define GBL_IPC (1<<2) +#define GBL_NET (1<<3) +#define GBL_PROC (1<<4) +#define GBL_RTSOCK (1<<5) +#define GBL_SYSCTL (1<<6) +#define GBL_VACCESS (1<<7) +#define GBL_VERIEXEC (1<<8) +#define GBL_KMEM (1<<9) +#define GBL_MAX 9 + +/* this should suffice for now */ +typedef uint32_t gbl_label_t; + +#define MAC_GRANTBYLABEL_FETCH_GBL 1 +#define MAC_GRANTBYLABEL_FETCH_PID_GBL 2 + +struct mac_grantbylabel_fetch_gbl_args { + union { + int fd; + pid_t pid; + } u; + gbl_label_t gbl; +}; + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/setjmp.h b/lib/libc/include/generic-freebsd/setjmp.h index 9e3b6741976a..7f79230b6774 100644 --- a/lib/libc/include/generic-freebsd/setjmp.h +++ b/lib/libc/include/generic-freebsd/setjmp.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)setjmp.h 8.2 (Berkeley) 1/21/94 */ #ifndef _SETJMP_H_ diff --git a/lib/libc/include/generic-freebsd/signal.h b/lib/libc/include/generic-freebsd/signal.h index e6f599b0291d..5f213b97020b 100644 --- a/lib/libc/include/generic-freebsd/signal.h +++ b/lib/libc/include/generic-freebsd/signal.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)signal.h 8.3 (Berkeley) 3/30/94 */ #ifndef _SIGNAL_H_ @@ -42,6 +40,10 @@ #include #endif +#if __POSIX_VISIBLE >= 202405 || __BSD_VISIBLE +#define SIG2STR_MAX 32 /* size of buffer required for sig2str() */ +#endif + __NULLABILITY_PRAGMA_PUSH #if __BSD_VISIBLE @@ -70,6 +72,10 @@ typedef __pthread_t pthread_t; #endif #endif /* __POSIX_VISIBLE || __XSI_VISIBLE */ +#if !defined(_STANDALONE) && defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 +#include +#endif + __BEGIN_DECLS int raise(int); @@ -117,9 +123,15 @@ int siginterrupt(int, int); #endif #if __POSIX_VISIBLE >= 200809 +void psiginfo(const siginfo_t *, const char *); void psignal(int, const char *); #endif +#if __POSIX_VISIBLE >= 202405 || __BSD_VISIBLE +int sig2str(int, char *); +int str2sig(const char * __restrict, int * __restrict); +#endif + #if __BSD_VISIBLE int sigandset(sigset_t *dest, const sigset_t *left, const sigset_t *right); int sigblock(int); diff --git a/lib/libc/include/generic-freebsd/ssp/poll.h b/lib/libc/include/generic-freebsd/ssp/poll.h new file mode 100644 index 000000000000..6db5bcd102a3 --- /dev/null +++ b/lib/libc/include/generic-freebsd/ssp/poll.h @@ -0,0 +1,60 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024, Klara, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _SSP_POLL_H_ +#define _SSP_POLL_H_ + +#include + +#if __SSP_FORTIFY_LEVEL > 0 + +__BEGIN_DECLS + +__ssp_redirect_raw_impl(int, poll, poll, + (struct pollfd fds[], nfds_t nfds, int timeout)) +{ + if (__ssp_bos(fds) / sizeof(fds[0]) < nfds) + __chk_fail(); + + return (__ssp_real(poll)(fds, nfds, timeout)); +} + +#if __POSIX_VISIBLE >= 202405 +__ssp_redirect_raw_impl(int, ppoll, ppoll, + (struct pollfd fds[], nfds_t nfds, + const struct timespec *__restrict timeout, + const sigset_t *__restrict newsigmask)) +{ + if (__ssp_bos(fds) / sizeof(fds[0]) < nfds) + __chk_fail(); + + return (__ssp_real(ppoll)(fds, nfds, timeout, newsigmask)); +} +#endif /* __POSIX_VISIBLE >= 202405 */ +__END_DECLS + +#endif /* __SSP_FORTIFY_LEVEL > 0 */ +#endif /* _SSP_POLL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/ssp/random.h b/lib/libc/include/generic-freebsd/ssp/random.h new file mode 100644 index 000000000000..83d1b33f1dd7 --- /dev/null +++ b/lib/libc/include/generic-freebsd/ssp/random.h @@ -0,0 +1,42 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024, Klara, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _SSP_RANDOM_H_ +#define _SSP_RANDOM_H_ + +#include + +#if __SSP_FORTIFY_LEVEL > 0 + +__BEGIN_DECLS + +__ssp_redirect(ssize_t, getrandom, (void *__buf, size_t __len, + unsigned int __flags), (__buf, __len, __flags)); + +__END_DECLS + +#endif /* __SSP_FORTIFY_LEVEL > 0 */ +#endif /* _SSP_RANDOM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/ssp/signal.h b/lib/libc/include/generic-freebsd/ssp/signal.h new file mode 100644 index 000000000000..f37940750e05 --- /dev/null +++ b/lib/libc/include/generic-freebsd/ssp/signal.h @@ -0,0 +1,52 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025, Ricardo Branco + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _SSP_SIGNAL_H_ +#define _SSP_SIGNAL_H_ + +#include + +#if __SSP_FORTIFY_LEVEL > 0 + +#include + +__BEGIN_DECLS + +#if __POSIX_VISIBLE >= 202405 || __BSD_VISIBLE +__ssp_redirect_raw_impl(int, sig2str, sig2str, + (int signum, char *__restrict str)) +{ + if (__ssp_bos(str) < SIG2STR_MAX) + __chk_fail(); + + return (__ssp_real(sig2str)(signum, str)); +} +#endif + +__END_DECLS + +#endif /* __SSP_FORTIFY_LEVEL > 0 */ +#endif /* _SSP_SIGNAL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/ssp/socket.h b/lib/libc/include/generic-freebsd/ssp/socket.h new file mode 100644 index 000000000000..e8abe21e769c --- /dev/null +++ b/lib/libc/include/generic-freebsd/ssp/socket.h @@ -0,0 +1,120 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024, Klara, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _SSP_SOCKET_H_ +#define _SSP_SOCKET_H_ + +#include + +#if __SSP_FORTIFY_LEVEL > 0 + +#include + +__BEGIN_DECLS + +__ssp_inline void +__ssp_check_msghdr(struct msghdr *hdr) +{ + if (__ssp_bos(hdr->msg_name) < hdr->msg_namelen) + __chk_fail(); + + __ssp_check_iovec(hdr->msg_iov, hdr->msg_iovlen); + + if (__ssp_bos(hdr->msg_control) < hdr->msg_controllen) + __chk_fail(); +} + +__ssp_redirect_raw_impl(int, getpeername, getpeername, + (int fdes, struct sockaddr *__restrict name, socklen_t *__restrict namelen)) +{ + size_t namesz = __ssp_bos(name); + + if (namesz != (size_t)-1 && namesz < *namelen) + __chk_fail(); + + return (__ssp_real(getpeername)(fdes, name, namelen)); +} + +__ssp_redirect_raw_impl(int, getsockname, getsockname, + (int fdes, struct sockaddr *__restrict name, + socklen_t *__restrict namelen)) +{ + size_t namesz = __ssp_bos(name); + + if (namesz != (size_t)-1 && namesz < *namelen) + __chk_fail(); + + return (__ssp_real(getsockname)(fdes, name, namelen)); +} + +__ssp_redirect(ssize_t, recv, (int __sock, void *__buf, size_t __len, + int __flags), (__sock, __buf, __len, __flags)); + +__ssp_redirect_raw_impl(ssize_t, recvfrom, recvfrom, + (int s, void *buf, size_t len, int flags, + struct sockaddr *__restrict from, + socklen_t *__restrict fromlen)) +{ + if (__ssp_bos(buf) < len) + __chk_fail(); + if (from != NULL && __ssp_bos(from) < *fromlen) + __chk_fail(); + + return (__ssp_real(recvfrom)(s, buf, len, flags, from, fromlen)); +} + +__ssp_redirect_raw_impl(ssize_t, recvmsg, recvmsg, + (int s, struct msghdr *hdr, int flags)) +{ + __ssp_check_msghdr(hdr); + return (__ssp_real(recvmsg)(s, hdr, flags)); +} + +#if __BSD_VISIBLE +struct timespec; + +__ssp_redirect_raw_impl(ssize_t, recvmmsg, recvmmsg, + (int s, struct mmsghdr *__restrict hdrvec, size_t vlen, int flags, + const struct timespec *__restrict timeout)) +{ + const size_t vecsz = __ssp_bos(hdrvec); + size_t i; + + if (vecsz != (size_t)-1 && vecsz / sizeof(*hdrvec) < vlen) + __chk_fail(); + + for (i = 0; i < vlen; i++) { + __ssp_check_msghdr(&hdrvec[i].msg_hdr); + } + + return (__ssp_real(recvmmsg)(s, hdrvec, vlen, flags, timeout)); +} +#endif + +__END_DECLS + +#endif /* __SSP_FORTIFY_LEVEL > 0 */ +#endif /* _SSP_SOCKET_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/ssp/ssp.h b/lib/libc/include/generic-freebsd/ssp/ssp.h new file mode 100644 index 000000000000..9dce2d401393 --- /dev/null +++ b/lib/libc/include/generic-freebsd/ssp/ssp.h @@ -0,0 +1,127 @@ +/* $NetBSD: ssp.h,v 1.13 2015/09/03 20:43:47 plunky Exp $ */ + +/*- + * + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2006, 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _SSP_SSP_H_ +#define _SSP_SSP_H_ + +#include + +#if !defined(__cplusplus) +# if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && \ + (__OPTIMIZE__ > 0 || defined(__clang__)) +# if _FORTIFY_SOURCE > 1 +# define __SSP_FORTIFY_LEVEL 2 +# else +# define __SSP_FORTIFY_LEVEL 1 +# endif +# else +# define __SSP_FORTIFY_LEVEL 0 +# endif +#else +# define __SSP_FORTIFY_LEVEL 0 +#endif + +#define __ssp_var(type) __CONCAT(__ssp_ ## type, __COUNTER__) + +/* __ssp_real is used by the implementation in libc */ +#if __SSP_FORTIFY_LEVEL == 0 +#define __ssp_real_(fun) fun +#else +#define __ssp_real_(fun) __ssp_real_ ## fun +#endif +#define __ssp_real(fun) __ssp_real_(fun) + +#define __ssp_inline static __inline __attribute__((__always_inline__)) + +#define __ssp_bos(ptr) __builtin_object_size(ptr, __SSP_FORTIFY_LEVEL > 1) +#define __ssp_bos0(ptr) __builtin_object_size(ptr, 0) + +#define __ssp_check(buf, len, bos) \ + if (bos(buf) != (size_t)-1 && (size_t)len > bos(buf)) \ + __chk_fail() + +#define __ssp_redirect_raw_impl(rtype, fun, symbol, args) \ +rtype __ssp_real_(fun) args __RENAME(symbol); \ +__ssp_inline rtype fun args __RENAME(__ssp_protected_ ## fun); \ +__ssp_inline rtype fun args + +#define __ssp_redirect_raw(rtype, fun, symbol, args, call, cond, bos, len) \ +__ssp_redirect_raw_impl(rtype, fun, symbol, args) { \ + if (cond) \ + __ssp_check(__buf, len, bos); \ + return __ssp_real_(fun) call; \ +} + +#define __ssp_redirect(rtype, fun, args, call) \ + __ssp_redirect_raw(rtype, fun, fun, args, call, 1, __ssp_bos, __len) +#define __ssp_redirect0(rtype, fun, args, call) \ + __ssp_redirect_raw(rtype, fun, fun, args, call, 1, __ssp_bos0, __len) + +#include +#include + +__ssp_inline int +__ssp_overlap(const void *leftp, const void *rightp, __size_t sz) +{ + __uintptr_t left = (__uintptr_t)leftp; + __uintptr_t right = (__uintptr_t)rightp; + + if (left <= right) + return (__SIZE_T_MAX - sz < left || right < left + sz); + + return (__SIZE_T_MAX - sz < right || left < right + sz); +} + +#include + +__BEGIN_DECLS +void __stack_chk_fail(void) __dead2; +void __chk_fail(void) __dead2; +__END_DECLS + +__ssp_inline void +__ssp_check_iovec(const struct iovec *iov, int iovcnt) +{ + const size_t iovsz = __ssp_bos(iov); + int i; + + if (iovsz != (size_t)-1 && iovsz / sizeof(*iov) < (size_t)iovcnt) + __chk_fail(); + + for (i = 0; i < iovcnt; i++) { + if (__ssp_bos(iov[i].iov_base) < iov[i].iov_len) + __chk_fail(); + } +} + +#endif /* _SSP_SSP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/ssp/stdio.h b/lib/libc/include/generic-freebsd/ssp/stdio.h new file mode 100644 index 000000000000..76bc897573a1 --- /dev/null +++ b/lib/libc/include/generic-freebsd/ssp/stdio.h @@ -0,0 +1,107 @@ +/* $NetBSD: stdio.h,v 1.5 2011/07/17 20:54:34 joerg Exp $ */ + +/*- + * + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2006 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _SSP_STDIO_H_ +#define _SSP_STDIO_H_ + +#include + +__BEGIN_DECLS +#if __SSP_FORTIFY_LEVEL > 0 +#if __POSIX_VISIBLE +__ssp_redirect_raw(char *, ctermid, ctermid, (char *__buf), (__buf), + __buf != NULL, __ssp_bos, L_ctermid); +#if __BSD_VISIBLE +__ssp_redirect_raw(char *, ctermid_r, ctermid_r, (char *__buf), (__buf), + __buf != NULL, __ssp_bos, L_ctermid); +#endif /* __BSD_VISIBLE */ +#endif /* __POSIX_VISIBLE */ +__ssp_redirect(size_t, fread, (void *__restrict __buf, size_t __len, + size_t __nmemb, FILE *__restrict __fp), (__buf, __len, __nmemb, __fp)); +__ssp_redirect(size_t, fread_unlocked, (void *__restrict __buf, size_t __len, + size_t __nmemb, FILE *__restrict __fp), (__buf, __len, __nmemb, __fp)); +#if __EXT1_VISIBLE +__ssp_redirect(char *, gets_s, (char *__buf, rsize_t __len), (__buf, __len)); +#endif /* __EXT1_VISIBLE */ +__ssp_redirect_raw(char *, tmpnam, tmpnam, (char *__buf), (__buf), 1, + __ssp_bos, L_tmpnam); +#endif + +int __sprintf_chk(char *__restrict, int, size_t, const char *__restrict, ...) + __printflike(4, 5); +int __vsprintf_chk(char *__restrict, int, size_t, const char *__restrict, + __va_list) + __printflike(4, 0); +int __snprintf_chk(char *__restrict, size_t, int, size_t, + const char *__restrict, ...) + __printflike(5, 6); +int __vsnprintf_chk(char *__restrict, size_t, int, size_t, + const char *__restrict, __va_list) + __printflike(5, 0); +char *__fgets_chk(char *, int, size_t, FILE *); +__END_DECLS + +#if __SSP_FORTIFY_LEVEL > 0 + +#define sprintf(str, ...) __extension__ ({ \ + char *_ssp_str = (str); \ + __builtin___sprintf_chk(_ssp_str, 0, __ssp_bos(_ssp_str), \ + __VA_ARGS__); \ +}) + +#define vsprintf(str, fmt, ap) __extension__ ({ \ + char *_ssp_str = (str); \ + __builtin___vsprintf_chk(_ssp_str, 0, __ssp_bos(_ssp_str), fmt, \ + ap); \ +}) + +#define snprintf(str, len, ...) __extension__ ({ \ + char *_ssp_str = (str); \ + __builtin___snprintf_chk(_ssp_str, len, 0, __ssp_bos(_ssp_str), \ + __VA_ARGS__); \ +}) + +#define vsnprintf(str, len, fmt, ap) __extension__ ({ \ + char *_ssp_str = (str); \ + __builtin___vsnprintf_chk(_ssp_str, len, 0, __ssp_bos(_ssp_str), \ + fmt, ap); \ +}) + +#define fgets(str, len, fp) __extension__ ({ \ + char *_ssp_str = (str); \ + __fgets_chk(_ssp_str, len, __ssp_bos(_ssp_str), fp); \ +}) + +#endif /* __SSP_FORTIFY_LEVEL > 0 */ + +#endif /* _SSP_STDIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/ssp/stdlib.h b/lib/libc/include/generic-freebsd/ssp/stdlib.h new file mode 100644 index 000000000000..c41fd7c2029f --- /dev/null +++ b/lib/libc/include/generic-freebsd/ssp/stdlib.h @@ -0,0 +1,57 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024, Klara, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _SSP_STDLIB_H_ +#define _SSP_STDLIB_H_ + +#include + +#if __SSP_FORTIFY_LEVEL > 0 + +#include + +__BEGIN_DECLS + +__ssp_redirect(void, arc4random_buf, (void *__buf, size_t __len), + (__buf, __len)); + +__ssp_redirect(int, getenv_r, + (const char *name, char * _Nonnull __buf, size_t __len), + (name, __buf, __len)); + +__ssp_redirect_raw_impl(char *, realpath, realpath, + (const char *__restrict path, char *__restrict buf)) +{ + if (__ssp_bos(buf) < PATH_MAX) + __chk_fail(); + + return (__ssp_real(realpath)(path, buf)); +} + +__END_DECLS + +#endif /* __SSP_FORTIFY_LEVEL > 0 */ +#endif /* _SSP_STDLIB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/ssp/string.h b/lib/libc/include/generic-freebsd/ssp/string.h new file mode 100644 index 000000000000..8e50a74174c0 --- /dev/null +++ b/lib/libc/include/generic-freebsd/ssp/string.h @@ -0,0 +1,141 @@ +/* $NetBSD: string.h,v 1.14 2020/09/05 13:37:59 mrg Exp $ */ + +/*- + * + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2006 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _SSP_STRING_H_ +#define _SSP_STRING_H_ + +#include + +__BEGIN_DECLS +void *__memcpy_chk(void *, const void *, size_t, size_t); +void *__memmove_chk(void *, const void *, size_t, size_t); +void *__memset_chk(void *, int, size_t, size_t); +char *__stpcpy_chk(char *, const char *, size_t); +char *__stpncpy_chk(char *, const char *, size_t, size_t); +char *__strcat_chk(char *, const char *, size_t); +char *__strcpy_chk(char *, const char *, size_t); +char *__strncat_chk(char *, const char *, size_t, size_t); +size_t __strlcat_chk(char *, const char *, size_t, size_t); +char *__strncpy_chk(char *, const char *, size_t, size_t); +size_t __strlcpy_chk(char *, const char *, size_t, size_t); +__END_DECLS + +#if __SSP_FORTIFY_LEVEL > 0 + +#define __ssp_bos_check3_typed_var(fun, dsttype, dsrvar, dst, srctype, srcvar, \ + src, lenvar, len) __extension__ ({ \ + srctype srcvar = (src); \ + dsttype dstvar = (dst); \ + size_t lenvar = (len); \ + ((__ssp_bos0(dstvar) != (size_t)-1) ? \ + __builtin___ ## fun ## _chk(dstvar, srcvar, lenvar, \ + __ssp_bos0(dstvar)) : \ + __ ## fun ## _ichk(dstvar, srcvar, lenvar)); \ +}) + +#define __ssp_bos_check3_typed(fun, dsttype, dst, srctype, src, len) \ + __ssp_bos_check3_typed_var(fun, dsttype, __ssp_var(dstv), dst, \ + srctype, __ssp_var(srcv), src, __ssp_var(lenv), len) + +#define __ssp_bos_check3(fun, dst, src, len) \ + __ssp_bos_check3_typed_var(fun, void *, __ssp_var(dstv), dst, \ + const void *, __ssp_var(srcv), src, __ssp_var(lenv), len) + +#define __ssp_bos_check2_var(fun, dstvar, dst, srcvar, src) __extension__ ({ \ + const void *srcvar = (src); \ + void *dstvar = (dst); \ + ((__ssp_bos0(dstvar) != (size_t)-1) ? \ + __builtin___ ## fun ## _chk(dstvar, srcvar, \ + __ssp_bos0(dstvar)) : \ + __ ## fun ## _ichk(dstvar, srcvar)); \ +}) + +#define __ssp_bos_check2(fun, dst, src) \ + __ssp_bos_check2_var(fun, __ssp_var(dstv), dst, __ssp_var(srcv), src) + +#define __ssp_bos_icheck3_restrict(fun, type1, type2) \ +static __inline type1 __ ## fun ## _ichk(type1 __restrict, type2 __restrict, size_t); \ +static __inline __attribute__((__always_inline__)) type1 \ +__ ## fun ## _ichk(type1 __restrict dst, type2 __restrict src, size_t len) { \ + return __builtin___ ## fun ## _chk(dst, src, len, __ssp_bos0(dst)); \ +} + +#define __ssp_bos_icheck3(fun, type1, type2) \ +static __inline type1 __ ## fun ## _ichk(type1, type2, size_t); \ +static __inline __attribute__((__always_inline__)) type1 \ +__ ## fun ## _ichk(type1 dst, type2 src, size_t len) { \ + return __builtin___ ## fun ## _chk(dst, src, len, __ssp_bos0(dst)); \ +} + +#define __ssp_bos_icheck2_restrict(fun, type1, type2) \ +static __inline type1 __ ## fun ## _ichk(type1, type2); \ +static __inline __attribute__((__always_inline__)) type1 \ +__ ## fun ## _ichk(type1 __restrict dst, type2 __restrict src) { \ + return __builtin___ ## fun ## _chk(dst, src, __ssp_bos0(dst)); \ +} + +__BEGIN_DECLS +__ssp_bos_icheck3_restrict(memcpy, void *, const void *) +__ssp_bos_icheck3_restrict(mempcpy, void *, const void *) +__ssp_bos_icheck3(memmove, void *, const void *) +__ssp_bos_icheck3(memset, void *, int) +__ssp_redirect(void *, memset_explicit, (void *__buf, int __ch, size_t __len), + (__buf, __ch, __len)); +__ssp_bos_icheck2_restrict(stpcpy, char *, const char *) +__ssp_bos_icheck3_restrict(stpncpy, char *, const char *) +__ssp_bos_icheck2_restrict(strcpy, char *, const char *) +__ssp_bos_icheck2_restrict(strcat, char *, const char *) +__ssp_redirect0(int, strerror_r, (int __errnum, char *__buf, size_t __len), + (__errnum, __buf, __len)); +__ssp_bos_icheck3_restrict(strncpy, char *, const char *) +__ssp_bos_icheck3_restrict(strncat, char *, const char *) +__END_DECLS + +#define memcpy(dst, src, len) __ssp_bos_check3(memcpy, dst, src, len) +#define mempcpy(dst, src, len) __ssp_bos_check3(mempcpy, dst, src, len) +#define memmove(dst, src, len) __ssp_bos_check3(memmove, dst, src, len) +#define memset(dst, val, len) \ + __ssp_bos_check3_typed(memset, void *, dst, int, val, len) +#define stpcpy(dst, src) __ssp_bos_check2(stpcpy, dst, src) +#define stpncpy(dst, src, len) __ssp_bos_check3(stpncpy, dst, src, len) +#define strcpy(dst, src) __ssp_bos_check2(strcpy, dst, src) +#define strcat(dst, src) __ssp_bos_check2(strcat, dst, src) +#define strlcpy(dst, src, dstlen) \ + __strlcpy_chk(dst, src, dstlen, __ssp_bos(dst)) +#define strncpy(dst, src, len) __ssp_bos_check3(strncpy, dst, src, len) +#define strlcat(dst, src, dstlen) \ + __strlcat_chk(dst, src, dstlen, __ssp_bos(dst)) +#define strncat(dst, src, len) __ssp_bos_check3(strncat, dst, src, len) + +#endif /* __SSP_FORTIFY_LEVEL > 0 */ +#endif /* _SSP_STRING_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/ssp/strings.h b/lib/libc/include/generic-freebsd/ssp/strings.h new file mode 100644 index 000000000000..fc3b14062efc --- /dev/null +++ b/lib/libc/include/generic-freebsd/ssp/strings.h @@ -0,0 +1,72 @@ +/* $NetBSD: strings.h,v 1.3 2008/04/28 20:22:54 martin Exp $ */ + +/*- + * + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2007 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _SSP_STRINGS_H_ +#define _SSP_STRINGS_H_ + +#include +#include + +#if __SSP_FORTIFY_LEVEL > 0 + +#define _ssp_bcopy(srcvar, src, dstvar, dst, lenvar, len) __extension__ ({ \ + const void *srcvar = (src); \ + void *dstvar = (dst); \ + size_t lenvar = (len); \ + ((__ssp_bos0(dstvar) != (size_t)-1) ? \ + __builtin___memmove_chk(dstvar, srcvar, lenvar, \ + __ssp_bos0(dstvar)) : \ + __memmove_ichk(dstvar, srcvar, lenvar)); \ +}) + +#define bcopy(src, dst, len) \ + _ssp_bcopy(__ssp_var(srcv), src, __ssp_var(dstv), dst, __ssp_var(lenv), len) + +#define _ssp_bzero(dstvar, dst, lenvar, len) __extension__ ({ \ + void *dstvar = (dst); \ + size_t lenvar = (len); \ + ((__ssp_bos0(dstvar) != (size_t)-1) ? \ + __builtin___memset_chk(dstvar, 0, lenvar, \ + __ssp_bos0(dstvar)) : \ + __memset_ichk(dstvar, 0, lenvar)); \ +}) + +#define bzero(dst, len) _ssp_bzero(__ssp_var(dstv), dst, __ssp_var(lenv), len) + +__BEGIN_DECLS +__ssp_redirect(void, explicit_bzero, (void *__buf, size_t __len), + (__buf, __len)); +__END_DECLS + +#endif /* __SSP_FORTIFY_LEVEL > 0 */ +#endif /* _SSP_STRINGS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/ssp/uio.h b/lib/libc/include/generic-freebsd/ssp/uio.h new file mode 100644 index 000000000000..cd513db6aac9 --- /dev/null +++ b/lib/libc/include/generic-freebsd/ssp/uio.h @@ -0,0 +1,53 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024, Klara, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _SSP_UIO_H_ +#define _SSP_UIO_H_ + +#include + +#if __SSP_FORTIFY_LEVEL > 0 + +__BEGIN_DECLS + +__ssp_redirect_raw_impl(ssize_t, readv, readv, + (int fd, const struct iovec *iov, int iovcnt)) +{ + __ssp_check_iovec(iov, iovcnt); + return (__ssp_real(readv)(fd, iov, iovcnt)); +} + +__ssp_redirect_raw_impl(ssize_t, preadv, preadv, + (int fd, const struct iovec *iov, int iovcnt, off_t offset)) +{ + __ssp_check_iovec(iov, iovcnt); + return (__ssp_real(preadv)(fd, iov, iovcnt, offset)); +} + +__END_DECLS + +#endif /* __SSP_FORTIFY_LEVEL > 0 */ +#endif /* _SSP_UIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/ssp/unistd.h b/lib/libc/include/generic-freebsd/ssp/unistd.h new file mode 100644 index 000000000000..fc7a17da3703 --- /dev/null +++ b/lib/libc/include/generic-freebsd/ssp/unistd.h @@ -0,0 +1,90 @@ +/* $NetBSD: unistd.h,v 1.7 2015/06/25 18:41:03 joerg Exp $ */ + +/*- + * + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2006 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _SSP_UNISTD_H_ +#define _SSP_UNISTD_H_ + +#include + +#if __SSP_FORTIFY_LEVEL > 0 +__BEGIN_DECLS + +#ifndef _FORTIFY_SOURCE_read +#define _FORTIFY_SOURCE_read read +#endif + +__ssp_inline size_t +__ssp_gid_bos(const void *ptr) +{ + size_t ptrsize = __ssp_bos(ptr); + + if (ptrsize == (size_t)-1) + return (ptrsize); + + return (ptrsize / sizeof(gid_t)); +} + +__ssp_redirect_raw(int, getgrouplist, getgrouplist, + (const char *__name, gid_t __base, gid_t *__buf, int *__lenp), + (__name, __base, __buf, __lenp), 1, __ssp_gid_bos, *__lenp); + +__ssp_redirect_raw(int, getgroups, getgroups, (int __len, gid_t *__buf), + (__len, __buf), 1, __ssp_gid_bos, __len); + +__ssp_redirect(int, getloginclass, (char *__buf, size_t __len), + (__buf, __len)); + +__ssp_redirect(ssize_t, _FORTIFY_SOURCE_read, (int __fd, void *__buf, + size_t __len), (__fd, __buf, __len)); +__ssp_redirect(ssize_t, pread, (int __fd, void *__buf, size_t __len, + off_t __offset), (__fd, __buf, __len, __offset)); + +__ssp_redirect(ssize_t, readlink, (const char *__restrict __path, \ + char *__restrict __buf, size_t __len), (__path, __buf, __len)); +__ssp_redirect(ssize_t, readlinkat, (int __fd, const char *__restrict __path, + char *__restrict __buf, size_t __len), (__fd, __path, __buf, __len)); + +__ssp_redirect_raw(char *, getcwd, getcwd, (char *__buf, size_t __len), + (__buf, __len), __buf != 0, __ssp_bos, __len); + +__ssp_redirect(int, getdomainname, (char *__buf, int __len), (__buf, __len)); +__ssp_redirect(int, getentropy, (void *__buf, size_t __len), (__buf, __len)); +__ssp_redirect(int, gethostname, (char *__buf, size_t __len), (__buf, __len)); +__ssp_redirect(int, getlogin_r, (char *__buf, size_t __len), (__buf, __len)); +__ssp_redirect(int, ttyname_r, (int __fd, char *__buf, size_t __len), + (__fd, __buf, __len)); + +__END_DECLS + +#endif /* __SSP_FORTIFY_LEVEL > 0 */ +#endif /* _SSP_UNISTD_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/ssp/wchar.h b/lib/libc/include/generic-freebsd/ssp/wchar.h new file mode 100644 index 000000000000..4b22b755b162 --- /dev/null +++ b/lib/libc/include/generic-freebsd/ssp/wchar.h @@ -0,0 +1,229 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024, Klara, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _SSP_WCHAR_H_ +#define _SSP_WCHAR_H_ + +#include + +#if __SSP_FORTIFY_LEVEL > 0 + +__ssp_inline int +__ssp_wchar_overlap(const void *leftp, const void *rightp, size_t len) +{ + + if (len > __SIZE_T_MAX / sizeof(wchar_t)) + return (1); + return (__ssp_overlap(leftp, rightp, len * sizeof(wchar_t))); +} + +/* + * __ssp_wbos for w*() calls where the size parameters are in sizeof(wchar_t) + * units, so the result needs to be scaled appropriately. + */ +__ssp_inline size_t +__ssp_wbos(void *ptr) +{ + const size_t ptrsize = __ssp_bos(ptr); + + if (ptrsize == (size_t)-1) + return (ptrsize); + + return (ptrsize / sizeof(wchar_t)); +} + +__BEGIN_DECLS +__ssp_redirect_raw_impl(wchar_t *, wmemcpy, wmemcpy, + (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len)) +{ + const size_t slen = __ssp_wbos(buf); + + if (len > slen) + __chk_fail(); + if (__ssp_wchar_overlap(src, buf, len)) + __chk_fail(); + + return (__ssp_real(wmemcpy)(buf, src, len)); +} + +__ssp_redirect_raw_impl(wchar_t *, wmempcpy, wmempcpy, + (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len)) +{ + const size_t slen = __ssp_wbos(buf); + + if (len > slen) + __chk_fail(); + if (__ssp_wchar_overlap(src, buf, len)) + __chk_fail(); + + return (__ssp_real(wmempcpy)(buf, src, len)); +} + +__ssp_redirect_raw_impl(wchar_t *, wmemmove, wmemmove, + (wchar_t *buf, const wchar_t *src, size_t len)) +{ + const size_t slen = __ssp_wbos(buf); + + if (len > slen) + __chk_fail(); + + return (__ssp_real(wmemmove)(buf, src, len)); +} + +__ssp_redirect_raw_impl(wchar_t *, wmemset, wmemset, + (wchar_t *buf, wchar_t c, size_t len)) +{ + const size_t slen = __ssp_wbos(buf); + + if (len > slen) + __chk_fail(); + return (__ssp_real(wmemset)(buf, c, len)); +} + +__ssp_redirect_raw_impl(wchar_t *, wcpcpy, wcpcpy, + (wchar_t *__restrict buf, const wchar_t *__restrict src)) +{ + const size_t slen = __ssp_wbos(buf); + const size_t len = wcslen(src); + + if (len >= slen) + __chk_fail(); + if (__ssp_wchar_overlap(buf, src, len)) + __chk_fail(); + + (void)__ssp_real(wmemcpy)(buf, src, len + 1); + return (buf + len); +} + +__ssp_redirect_raw_impl(wchar_t *, wcpncpy, wcpncpy, + (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len)) +{ + const size_t slen = __ssp_wbos(buf); + + if (len > slen) + __chk_fail(); + if (__ssp_wchar_overlap(buf, src, len)) + __chk_fail(); + + return (__ssp_real(wcpncpy)(buf, src, len)); +} + +__ssp_redirect_raw_impl(wchar_t *, wcscat, wcscat, + (wchar_t *__restrict buf, const wchar_t *__restrict src)) +{ + size_t slen = __ssp_wbos(buf); + wchar_t *cp; + + cp = buf; + while (*cp != L'\0') { + cp++; + if (slen-- == 0) + __chk_fail(); + } + + while (*src != L'\0') { + if (slen-- == 0) + __chk_fail(); + *cp++ = *src++; + } + + if (slen-- == 0) + __chk_fail(); + *cp = '\0'; + return (buf); +} + +__ssp_redirect_raw_impl(wchar_t *, wcscpy, wcscpy, + (wchar_t *__restrict buf, const wchar_t *__restrict src)) +{ + const size_t slen = __ssp_wbos(buf); + size_t len = wcslen(src) + 1; + + if (len > slen) + __chk_fail(); + if (__ssp_wchar_overlap(buf, src, len)) + __chk_fail(); + + return (__ssp_real(wmemcpy)(buf, src, len)); +} + +__ssp_redirect_raw_impl(wchar_t *, wcsncat, wcsncat, + (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len)) +{ + const size_t slen = __ssp_wbos(buf); + + if (len == 0) + return (buf); + if (len > slen) + __chk_fail(); + if (__ssp_wchar_overlap(buf, src, len)) + __chk_fail(); + + return (__ssp_real(wcsncat)(buf, src, len)); +} + +__ssp_redirect_raw_impl(size_t, wcslcat, wcslcat, + (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len)) +{ + const size_t slen = __ssp_wbos(buf); + + if (len > slen) + __chk_fail(); + if (__ssp_wchar_overlap(buf, src, len)) + __chk_fail(); + + return (__ssp_real(wcslcat)(buf, src, len)); +} + +__ssp_redirect_raw_impl(wchar_t *, wcsncpy, wcsncpy, + (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len)) +{ + const size_t slen = __ssp_wbos(buf); + + if (len > slen) + __chk_fail(); + if (__ssp_wchar_overlap(buf, src, len)) + __chk_fail(); + + return (__ssp_real(wcsncpy)(buf, src, len)); +} + +__ssp_redirect_raw_impl(size_t, wcslcpy, wcslcpy, + (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len)) +{ + const size_t slen = __ssp_wbos(buf); + + if (len > slen) + __chk_fail(); + if (__ssp_wchar_overlap(buf, src, len)) + __chk_fail(); + + return (__ssp_real(wcslcpy)(buf, src, len)); +} +__END_DECLS + +#endif /* __SSP_FORTIFY_LEVEL > 0 */ +#endif /* _SSP_WCHAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/stab.h b/lib/libc/include/generic-freebsd/stab.h index 4696c7a98444..9d8933e8fbe6 100644 --- a/lib/libc/include/generic-freebsd/stab.h +++ b/lib/libc/include/generic-freebsd/stab.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)stab.h 8.1 (Berkeley) 6/2/93 */ #ifndef _STAB_H_ diff --git a/lib/libc/include/generic-freebsd/stdarg.h b/lib/libc/include/generic-freebsd/stdarg.h index d613817c6b08..aebbb7c4d564 100644 --- a/lib/libc/include/generic-freebsd/stdarg.h +++ b/lib/libc/include/generic-freebsd/stdarg.h @@ -1,37 +1,6 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2017 Poul-Henning Kamp. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _MACHINE_STDARG_H_ -#define _MACHINE_STDARG_H_ +#ifndef __SYS_STDARG_H__ +#define __SYS_STDARG_H__ #include -#ifndef va_start - #error this file needs to be ported to your compiler -#endif - -#endif /* !_MACHINE_STDARG_H_ */ \ No newline at end of file +#endif /* __SYS_STDARG_H__ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/stdatomic.h b/lib/libc/include/generic-freebsd/stdatomic.h index ae0516be1c8f..e2ff73bcfb89 100644 --- a/lib/libc/include/generic-freebsd/stdatomic.h +++ b/lib/libc/include/generic-freebsd/stdatomic.h @@ -33,7 +33,8 @@ #include #include -#if __has_extension(c_atomic) || __has_extension(cxx_atomic) +#if (__has_extension(c_atomic) || __has_extension(cxx_atomic)) && \ + defined(__clang__) #define __CLANG_ATOMICS #elif __GNUC_PREREQ__(4, 7) #define __GNUC_ATOMICS diff --git a/lib/libc/include/generic-freebsd/stdckdint.h b/lib/libc/include/generic-freebsd/stdckdint.h index 5a0adc0c714f..9375673c04ea 100644 --- a/lib/libc/include/generic-freebsd/stdckdint.h +++ b/lib/libc/include/generic-freebsd/stdckdint.h @@ -13,7 +13,7 @@ #if __GNUC_PREREQ__(5, 1) || __has_builtin(__builtin_add_overflow) #define ckd_add(result, a, b) \ - (_Bool)__builtin_add_overflow((a), (b), (result)) + __builtin_add_overflow((a), (b), (result)) #else #define ckd_add(result, a, b) \ _Static_assert(0, "checked addition not supported") @@ -21,7 +21,7 @@ #if __GNUC_PREREQ__(5, 1) || __has_builtin(__builtin_sub_overflow) #define ckd_sub(result, a, b) \ - (_Bool)__builtin_sub_overflow((a), (b), (result)) + __builtin_sub_overflow((a), (b), (result)) #else #define ckd_sub(result, a, b) \ _Static_assert(0, "checked subtraction not supported") @@ -29,7 +29,7 @@ #if __GNUC_PREREQ__(5, 1) || __has_builtin(__builtin_mul_overflow) #define ckd_mul(result, a, b) \ - (_Bool)__builtin_mul_overflow((a), (b), (result)) + __builtin_mul_overflow((a), (b), (result)) #else #define ckd_mul(result, a, b) \ _Static_assert(0, "checked multiplication not supported") diff --git a/lib/libc/include/generic-freebsd/stddef.h b/lib/libc/include/generic-freebsd/stddef.h index 302e8f9d8c53..108c3385a1b2 100644 --- a/lib/libc/include/generic-freebsd/stddef.h +++ b/lib/libc/include/generic-freebsd/stddef.h @@ -27,29 +27,20 @@ * 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. - * - * @(#)stddef.h 8.1 (Berkeley) 6/2/93 */ #ifndef _STDDEF_H_ #define _STDDEF_H_ -#include #include #include +#include #ifndef _PTRDIFF_T_DECLARED typedef __ptrdiff_t ptrdiff_t; #define _PTRDIFF_T_DECLARED #endif -#if __BSD_VISIBLE -#ifndef _RUNE_T_DECLARED -typedef __rune_t rune_t; -#define _RUNE_T_DECLARED -#endif -#endif - #ifndef _SIZE_T_DECLARED typedef __size_t size_t; #define _SIZE_T_DECLARED @@ -70,7 +61,9 @@ typedef __max_align_t max_align_t; #endif #endif -#define offsetof(type, field) __offsetof(type, field) +#ifndef offsetof +#define offsetof(type, field) __builtin_offsetof(type, field) +#endif #if __EXT1_VISIBLE /* ISO/IEC 9899:2011 K.3.3.2 */ diff --git a/lib/libc/include/generic-freebsd/stdio.h b/lib/libc/include/generic-freebsd/stdio.h index 41ce3df9dc07..e9119c81f59d 100644 --- a/lib/libc/include/generic-freebsd/stdio.h +++ b/lib/libc/include/generic-freebsd/stdio.h @@ -30,8 +30,6 @@ * 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. - * - * @(#)stdio.h 8.5 (Berkeley) 4/29/95 */ #ifndef _STDIO_H_ @@ -50,10 +48,13 @@ typedef __size_t size_t; #define _SIZE_T_DECLARED #endif +#if __EXT1_VISIBLE +/* ISO/IEC 9899:2011 K.3.3.2 */ #ifndef _RSIZE_T_DEFINED #define _RSIZE_T_DEFINED typedef size_t rsize_t; #endif +#endif /* __EXT1_VISIBLE */ #if __POSIX_VISIBLE >= 200809 #ifndef _OFF_T_DECLARED @@ -73,7 +74,7 @@ typedef __off64_t off64_t; #if __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE #ifndef _VA_LIST_DECLARED -typedef __va_list va_list; +typedef __builtin_va_list va_list; #define _VA_LIST_DECLARED #endif #endif @@ -240,6 +241,21 @@ __END_DECLS #define stdout __stdoutp #define stderr __stderrp +/* + * Functions defined in all versions of POSIX 1003.1. + */ +#if __BSD_VISIBLE || (__POSIX_VISIBLE && __POSIX_VISIBLE <= 199506) +#define L_cuserid 17 /* size for cuserid(3); MAXLOGNAME, legacy */ +#endif + +#if __POSIX_VISIBLE +#define L_ctermid 1024 /* size for ctermid(3); PATH_MAX */ +#endif /* __POSIX_VISIBLE */ + +#if !defined(_STANDALONE) && defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 +#include +#endif + __BEGIN_DECLS #ifdef _XLOCALE_H_ #include @@ -254,7 +270,7 @@ int ferror(FILE *); int fflush(FILE *); int fgetc(FILE *); int fgetpos(FILE * __restrict, fpos_t * __restrict); -char *fgets(char * __restrict, int, FILE * __restrict); +char *(fgets)(char * __restrict, int, FILE * __restrict); FILE *fopen(const char * __restrict, const char * __restrict); int fprintf(FILE * __restrict, const char * __restrict, ...); int fputc(int, FILE *); @@ -282,7 +298,7 @@ void rewind(FILE *); int scanf(const char * __restrict, ...); void setbuf(FILE * __restrict, char * __restrict); int setvbuf(FILE * __restrict, char * __restrict, int, size_t); -int sprintf(char * __restrict, const char * __restrict, ...); +int (sprintf)(char * __restrict, const char * __restrict, ...); int sscanf(const char * __restrict, const char * __restrict, ...); FILE *tmpfile(void); char *tmpnam(char *); @@ -290,13 +306,13 @@ int ungetc(int, FILE *); int vfprintf(FILE * __restrict, const char * __restrict, __va_list); int vprintf(const char * __restrict, __va_list); -int vsprintf(char * __restrict, const char * __restrict, +int (vsprintf)(char * __restrict, const char * __restrict, __va_list); #if __ISO_C_VISIBLE >= 1999 || __POSIX_VISIBLE >= 199506 -int snprintf(char * __restrict, size_t, const char * __restrict, +int (snprintf)(char * __restrict, size_t, const char * __restrict, ...) __printflike(3, 4); -int vsnprintf(char * __restrict, size_t, const char * __restrict, +int (vsnprintf)(char * __restrict, size_t, const char * __restrict, __va_list) __printflike(3, 0); #endif #if __ISO_C_VISIBLE >= 1999 @@ -307,16 +323,7 @@ int vsscanf(const char * __restrict, const char * __restrict, __va_list) __scanflike(2, 0); #endif -/* - * Functions defined in all versions of POSIX 1003.1. - */ -#if __BSD_VISIBLE || (__POSIX_VISIBLE && __POSIX_VISIBLE <= 199506) -#define L_cuserid 17 /* size for cuserid(3); MAXLOGNAME, legacy */ -#endif - #if __POSIX_VISIBLE -#define L_ctermid 1024 /* size for ctermid(3); PATH_MAX */ - char *ctermid(char *); FILE *fdopen(int, const char *); int fileno(FILE *); @@ -415,6 +422,7 @@ FILE *funopen(const void *, #define fropen(cookie, fn) funopen(cookie, fn, 0, 0, 0) #define fwopen(cookie, fn) funopen(cookie, 0, fn, 0, 0) +#if __BSD_VISIBLE typedef __ssize_t cookie_read_function_t(void *, char *, size_t); typedef __ssize_t cookie_write_function_t(void *, const char *, size_t); typedef int cookie_seek_function_t(void *, off64_t *, int); @@ -426,6 +434,7 @@ typedef struct { cookie_close_function_t *close; } cookie_io_functions_t; FILE *fopencookie(void *, const char *, cookie_io_functions_t); +#endif /* * Portability hacks. See . @@ -497,10 +506,6 @@ extern int __isthreaded; #define ferror(p) (!__isthreaded ? __sferror(p) : (ferror)(p)) #define clearerr(p) (!__isthreaded ? __sclearerr(p) : (clearerr)(p)) -#if __POSIX_VISIBLE -#define fileno(p) (!__isthreaded ? __sfileno(p) : (fileno)(p)) -#endif - #define getc(fp) (!__isthreaded ? __sgetc(fp) : (getc)(fp)) #define putc(x, fp) (!__isthreaded ? __sputc(x, fp) : (putc)(x, fp)) diff --git a/lib/libc/include/generic-freebsd/stdlib.h b/lib/libc/include/generic-freebsd/stdlib.h index ab7cac8768cc..c2522b9d6499 100644 --- a/lib/libc/include/generic-freebsd/stdlib.h +++ b/lib/libc/include/generic-freebsd/stdlib.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)stdlib.h 8.5 (Berkeley) 5/19/95 */ #ifndef _STDLIB_H_ @@ -40,13 +38,6 @@ __NULLABILITY_PRAGMA_PUSH -#if __BSD_VISIBLE -#ifndef _RUNE_T_DECLARED -typedef __rune_t rune_t; -#define _RUNE_T_DECLARED -#endif -#endif - #ifndef _SIZE_T_DECLARED typedef __size_t size_t; #define _SIZE_T_DECLARED @@ -78,6 +69,10 @@ typedef struct { */ #define RAND_MAX 0x7fffffff +#if !defined(_STANDALONE) && defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 +#include +#endif + __BEGIN_DECLS #ifdef _XLOCALE_H_ #include @@ -86,9 +81,9 @@ extern int __mb_cur_max; extern int ___mb_cur_max(void); #define MB_CUR_MAX ((size_t)___mb_cur_max()) -_Noreturn void abort(void); +_Noreturn void abort(void) __noexcept; int abs(int) __pure2; -int atexit(void (* _Nonnull)(void)); +int atexit(void (* _Nonnull)(void)) __noexcept; double atof(const char *); int atoi(const char *); long atol(const char *); @@ -100,6 +95,9 @@ div_t div(int, int) __pure2; _Noreturn void exit(int); void free(void *); char *getenv(const char *); +#if __BSD_VISIBLE +int getenv_r(const char *, char * _Nonnull, size_t); +#endif long labs(long) __pure2; ldiv_t ldiv(long, long) __pure2; void *malloc(size_t) __malloc_like __result_use_check __alloc_size(1); @@ -156,7 +154,7 @@ unsigned long long strtoull(const char * __restrict, char ** __restrict, int); #endif /* __LONG_LONG_SUPPORTED */ -_Noreturn void _Exit(int); +_Noreturn void _Exit(int) __noexcept; #endif /* __ISO_C_VISIBLE >= 1999 */ /* @@ -165,9 +163,9 @@ _Noreturn void _Exit(int); #if __ISO_C_VISIBLE >= 2011 || __cplusplus >= 201103L void * aligned_alloc(size_t, size_t) __malloc_like __alloc_align(1) __alloc_size(2); -int at_quick_exit(void (*)(void)); +int at_quick_exit(void (*)(void)) __noexcept; _Noreturn void - quick_exit(int); + quick_exit(int) /* __noexcept -- not ready ABI issues? */; #endif /* __ISO_C_VISIBLE >= 2011 */ /* * Extensions made by POSIX relative to C. @@ -339,23 +337,26 @@ __uint64_t * parameter, and both are different from the ones expected by the historical * FreeBSD qsort_r() interface. * - * Apply a workaround where we explicitly link against the historical - * interface, qsort_r@FBSD_1.0, in case when qsort_r() is called with - * the last parameter with a function pointer that exactly matches the - * historical FreeBSD qsort_r() comparator signature, so applications - * written for the historical interface can continue to work without - * modification. + * Apply a workaround where we explicitly link against the historical interface, + * qsort_r@FBSD_1.0, in case when qsort_r() is called with the last parameter + * with a function pointer that exactly matches the historical FreeBSD qsort_r() + * comparator signature, so applications written for the historical interface + * can continue to work without modification. Toolchains that don't support + * symbol versioning don't define __sym_compat, so only provide this symbol in + * supported environments. */ +#ifdef __sym_compat #if defined(__generic) || defined(__cplusplus) void __qsort_r_compat(void *, size_t, size_t, void *, int (*)(void *, const void *, const void *)); __sym_compat(qsort_r, __qsort_r_compat, FBSD_1.0); #endif +#endif #if defined(__generic) && !defined(__cplusplus) #define qsort_r(base, nel, width, arg4, arg5) \ __generic(arg5, int (*)(void *, const void *, const void *), \ __qsort_r_compat, qsort_r)(base, nel, width, arg4, arg5) -#elif defined(__cplusplus) +#elif defined(__cplusplus) && defined(__sym_compat) __END_DECLS extern "C++" { static inline void qsort_r(void *base, size_t nmemb, size_t size, diff --git a/lib/libc/include/generic-freebsd/string.h b/lib/libc/include/generic-freebsd/string.h index a51dc0fefbe7..48bdd01cf03b 100644 --- a/lib/libc/include/generic-freebsd/string.h +++ b/lib/libc/include/generic-freebsd/string.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)string.h 8.1 (Berkeley) 6/2/93 */ #ifndef _STRING_H_ @@ -51,8 +49,12 @@ typedef __size_t size_t; #define _SIZE_T_DECLARED #endif +#if !defined(_STANDALONE) && defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 +#include +#endif + __BEGIN_DECLS -#if __XSI_VISIBLE >= 600 +#if __XSI_VISIBLE >= 600 || __ISO_C_VISIBLE >= 2023 void *memccpy(void * __restrict, const void * __restrict, int, size_t); #endif void *memchr(const void *, int, size_t) __pure; @@ -60,23 +62,26 @@ void *memchr(const void *, int, size_t) __pure; void *memrchr(const void *, int, size_t) __pure; #endif int memcmp(const void *, const void *, size_t) __pure; -void *memcpy(void * __restrict, const void * __restrict, size_t); +void *(memcpy)(void * __restrict, const void * __restrict, size_t); #if __BSD_VISIBLE void *memmem(const void *, size_t, const void *, size_t) __pure; #endif -void *memmove(void *, const void *, size_t); +void *(memmove)(void *, const void *, size_t); #if __BSD_VISIBLE -void *mempcpy(void * __restrict, const void * __restrict, size_t); +void *(mempcpy)(void * __restrict, const void * __restrict, size_t); +#endif +void *(memset)(void *, int, size_t); +#if __BSD_VISIBLE || __ISO_C_VISIBLE >= 2023 +void *memset_explicit(void *, int, size_t); #endif -void *memset(void *, int, size_t); #if __POSIX_VISIBLE >= 200809 -char *stpcpy(char * __restrict, const char * __restrict); -char *stpncpy(char * __restrict, const char * __restrict, size_t); +char *(stpcpy)(char * __restrict, const char * __restrict); +char *(stpncpy)(char * __restrict, const char * __restrict, size_t); #endif #if __BSD_VISIBLE char *strcasestr(const char *, const char *) __pure; #endif -char *strcat(char * __restrict, const char * __restrict); +char *(strcat)(char * __restrict, const char * __restrict); char *strchr(const char *, int) __pure; #if __BSD_VISIBLE char *strchrnul(const char*, int) __pure; @@ -84,9 +89,9 @@ int strverscmp(const char *, const char *) __pure; #endif int strcmp(const char *, const char *) __pure; int strcoll(const char *, const char *); -char *strcpy(char * __restrict, const char * __restrict); +char *(strcpy)(char * __restrict, const char * __restrict); size_t strcspn(const char *, const char *) __pure; -#if __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE +#if __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE || __ISO_C_VISIBLE >= 2023 char *strdup(const char *) __malloc_like; #endif char *strerror(int); @@ -94,8 +99,8 @@ char *strerror(int); int strerror_r(int, char *, size_t); #endif #if __BSD_VISIBLE -size_t strlcat(char * __restrict, const char * __restrict, size_t); -size_t strlcpy(char * __restrict, const char * __restrict, size_t); +size_t (strlcat)(char * __restrict, const char * __restrict, size_t); +size_t (strlcpy)(char * __restrict, const char * __restrict, size_t); #endif size_t strlen(const char *) __pure; #if __BSD_VISIBLE @@ -107,11 +112,13 @@ typedef __mode_t mode_t; void strmode(mode_t, char *); #endif -char *strncat(char * __restrict, const char * __restrict, size_t); +char *(strncat)(char * __restrict, const char * __restrict, size_t); int strncmp(const char *, const char *, size_t) __pure; -char *strncpy(char * __restrict, const char * __restrict, size_t); -#if __POSIX_VISIBLE >= 200809 +char *(strncpy)(char * __restrict, const char * __restrict, size_t); +#if __POSIX_VISIBLE >= 200809 || __ISO_C_VISIBLE >= 2023 char *strndup(const char *, size_t) __malloc_like; +#endif +#if __POSIX_VISIBLE >= 200809 size_t strnlen(const char *, size_t) __pure; #endif #if __BSD_VISIBLE diff --git a/lib/libc/include/generic-freebsd/stringlist.h b/lib/libc/include/generic-freebsd/stringlist.h index 326b16e1cc2b..56aa350188e3 100644 --- a/lib/libc/include/generic-freebsd/stringlist.h +++ b/lib/libc/include/generic-freebsd/stringlist.h @@ -30,7 +30,7 @@ #ifndef _STRINGLIST_H #define _STRINGLIST_H -#include + #include /* diff --git a/lib/libc/include/generic-freebsd/strings.h b/lib/libc/include/generic-freebsd/strings.h index 6373e6af041a..38e05ff63704 100644 --- a/lib/libc/include/generic-freebsd/strings.h +++ b/lib/libc/include/generic-freebsd/strings.h @@ -37,11 +37,15 @@ typedef __size_t size_t; #define _SIZE_T_DECLARED #endif +#if !defined(_STANDALONE) && defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 +#include +#endif + __BEGIN_DECLS #if __BSD_VISIBLE || __POSIX_VISIBLE <= 200112 int bcmp(const void *, const void *, size_t) __pure; /* LEGACY */ -void bcopy(const void *, void *, size_t); /* LEGACY */ -void bzero(void *, size_t); /* LEGACY */ +void (bcopy)(const void *, void *, size_t); /* LEGACY */ +void (bzero)(void *, size_t); /* LEGACY */ #endif #if __BSD_VISIBLE void explicit_bzero(void *, size_t); diff --git a/lib/libc/include/generic-freebsd/sys/_atomic64e.h b/lib/libc/include/generic-freebsd/sys/_atomic64e.h index 0b06a7e856b6..772e2f2635cf 100644 --- a/lib/libc/include/generic-freebsd/sys/_atomic64e.h +++ b/lib/libc/include/generic-freebsd/sys/_atomic64e.h @@ -55,7 +55,7 @@ int atomic_fcmpset_64(volatile u_int64_t *, u_int64_t *, u_int64_t); u_int64_t atomic_fetchadd_64(volatile u_int64_t *, u_int64_t); -u_int64_t atomic_load_64(volatile u_int64_t *); +u_int64_t atomic_load_64(const volatile u_int64_t *); #define atomic_load_acq_64 atomic_load_64 void atomic_readandclear_64(volatile u_int64_t *); diff --git a/lib/libc/include/generic-freebsd/sys/_atomic_subword.h b/lib/libc/include/generic-freebsd/sys/_atomic_subword.h index 9982e4242ec8..b96b83b6683e 100644 --- a/lib/libc/include/generic-freebsd/sys/_atomic_subword.h +++ b/lib/libc/include/generic-freebsd/sys/_atomic_subword.h @@ -176,7 +176,7 @@ atomic_fcmpset_16(__volatile uint16_t *addr, uint16_t *old, uint16_t val) #ifndef atomic_load_acq_8 static __inline uint8_t -atomic_load_acq_8(volatile uint8_t *p) +atomic_load_acq_8(const volatile uint8_t *p) { int shift; uint8_t ret; @@ -189,7 +189,7 @@ atomic_load_acq_8(volatile uint8_t *p) #ifndef atomic_load_acq_16 static __inline uint16_t -atomic_load_acq_16(volatile uint16_t *p) +atomic_load_acq_16(const volatile uint16_t *p) { int shift; uint16_t ret; @@ -205,67 +205,31 @@ atomic_load_acq_16(volatile uint16_t *p) #undef _ATOMIC_BYTE_SHIFT #undef _ATOMIC_HWORD_SHIFT -/* - * Provide generic testandset_long implementation based on fcmpset long - * primitive. It may not be ideal for any given arch, so machine/atomic.h - * should define the macro atomic_testandset_long to override with an - * MD-specific version. - * - * (Organizationally, this isn't really subword atomics. But atomic_common is - * included too early in machine/atomic.h, so it isn't a good place for derived - * primitives like this.) - */ -#ifndef atomic_testandset_acq_long -static __inline int -atomic_testandset_acq_long(volatile u_long *p, u_int v) -{ - u_long bit, old; - bool ret; - - bit = (1ul << (v % (sizeof(*p) * NBBY))); - - old = atomic_load_acq_long(p); - ret = false; - while (!ret && (old & bit) == 0) - ret = atomic_fcmpset_acq_long(p, &old, old | bit); - - return (!ret); -} -#endif - -#ifndef atomic_testandset_long -static __inline int -atomic_testandset_long(volatile u_long *p, u_int v) +#ifndef atomic_set_16 +static __inline void +atomic_set_16(volatile uint16_t *p, uint16_t bit) { - u_long bit, old; - bool ret; - - bit = (1ul << (v % (sizeof(*p) * NBBY))); - - old = atomic_load_long(p); - ret = false; - while (!ret && (old & bit) == 0) - ret = atomic_fcmpset_long(p, &old, old | bit); + uint16_t v; - return (!ret); + v = atomic_load_16(p); + for (;;) { + if (atomic_fcmpset_16(p, &v, v | bit)) + break; + } } #endif -#ifndef atomic_testandclear_long -static __inline int -atomic_testandclear_long(volatile u_long *p, u_int v) +#ifndef atomic_clear_16 +static __inline void +atomic_clear_16(volatile uint16_t *p, uint16_t bit) { - u_long bit, old; - bool ret; - - bit = (1ul << (v % (sizeof(*p) * NBBY))); + uint16_t v; - old = atomic_load_long(p); - ret = false; - while (!ret && (old & bit) != 0) - ret = atomic_fcmpset_long(p, &old, old & ~bit); - - return (ret); + v = atomic_load_16(p); + for (;;) { + if (atomic_fcmpset_16(p, &v, v & ~bit)) + break; + } } #endif diff --git a/lib/libc/include/generic-freebsd/sys/_bitset.h b/lib/libc/include/generic-freebsd/sys/_bitset.h index 35df39987667..0d37757a7444 100644 --- a/lib/libc/include/generic-freebsd/sys/_bitset.h +++ b/lib/libc/include/generic-freebsd/sys/_bitset.h @@ -36,7 +36,7 @@ * Macros addressing word and bit within it, tuned to make compiler * optimize cases when SETSIZE fits into single machine word. */ -#define _BITSET_BITS (sizeof(long) * 8) +#define _BITSET_BITS (sizeof(unsigned long) * 8) #define __howmany(x, y) (((x) + ((y) - 1)) / (y)) @@ -44,7 +44,7 @@ #define __BITSET_DEFINE(_t, _s) \ struct _t { \ - long __bits[__bitset_words((_s))]; \ + unsigned long __bits[__bitset_words((_s))]; \ } /* diff --git a/lib/libc/include/generic-freebsd/sys/_callout.h b/lib/libc/include/generic-freebsd/sys/_callout.h index 32c21b70260a..b45662894cb3 100644 --- a/lib/libc/include/generic-freebsd/sys/_callout.h +++ b/lib/libc/include/generic-freebsd/sys/_callout.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)callout.h 8.2 (Berkeley) 1/21/94 */ #ifndef _SYS__CALLOUT_H diff --git a/lib/libc/include/generic-freebsd/sys/_clock_id.h b/lib/libc/include/generic-freebsd/sys/_clock_id.h index 8719871c000c..50769db5d85e 100644 --- a/lib/libc/include/generic-freebsd/sys/_clock_id.h +++ b/lib/libc/include/generic-freebsd/sys/_clock_id.h @@ -74,11 +74,15 @@ #define CLOCK_PROCESS_CPUTIME_ID 15 #endif /* __POSIX_VISIBLE >= 199309 */ +#ifdef __BSD_VISIBLE +#define CLOCK_TAI 16 +#endif + /* * Linux compatible names. */ #if __BSD_VISIBLE -#define CLOCK_BOOTTIME CLOCK_UPTIME +#define CLOCK_BOOTTIME CLOCK_MONOTONIC #define CLOCK_REALTIME_COARSE CLOCK_REALTIME_FAST #define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC_FAST #endif diff --git a/lib/libc/include/generic-freebsd/sys/_cpuset.h b/lib/libc/include/generic-freebsd/sys/_cpuset.h index aaec383b9795..9939e6306bb6 100644 --- a/lib/libc/include/generic-freebsd/sys/_cpuset.h +++ b/lib/libc/include/generic-freebsd/sys/_cpuset.h @@ -35,6 +35,8 @@ #include #ifdef _KERNEL +#include + #define CPU_SETSIZE MAXCPU #endif diff --git a/lib/libc/include/generic-freebsd/sys/_domainset.h b/lib/libc/include/generic-freebsd/sys/_domainset.h index 73efbe97184a..19f2b037f449 100644 --- a/lib/libc/include/generic-freebsd/sys/_domainset.h +++ b/lib/libc/include/generic-freebsd/sys/_domainset.h @@ -32,6 +32,8 @@ #include #ifdef _KERNEL +#include + #define DOMAINSET_SETSIZE MAXMEMDOM #endif diff --git a/lib/libc/include/generic-freebsd/sys/_endian.h b/lib/libc/include/generic-freebsd/sys/_endian.h index fb506e6a5bef..eff27d0c3248 100644 --- a/lib/libc/include/generic-freebsd/sys/_endian.h +++ b/lib/libc/include/generic-freebsd/sys/_endian.h @@ -69,8 +69,10 @@ /* * POSIX Issue 8 will require these for endian.h. Define them there and in the - * traditional BSD compilation environment. Since issue 8 doesn't yet have an - * assigned date, use strictly greater than issue 7's date. + * traditional BSD compilation environment. PDP_ENDIAN isn't strictly in Issue + * 8, but is allowed as implementations can define any *_ENDIAN symbol. Since + * issue 8 doesn't yet have an assigned date, use strictly greater than issue + * 7's date. */ #if __BSD_VISIBLE || _POSIX_C_SOURCE > 200809 #define LITTLE_ENDIAN _LITTLE_ENDIAN diff --git a/lib/libc/include/generic-freebsd/sys/_exterr.h b/lib/libc/include/generic-freebsd/sys/_exterr.h new file mode 100644 index 000000000000..e141c3767251 --- /dev/null +++ b/lib/libc/include/generic-freebsd/sys/_exterr.h @@ -0,0 +1,25 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 The FreeBSD Foundation + * All rights reserved. + * + * This software were developed by Konstantin Belousov + * under sponsorship from the FreeBSD Foundation. + */ + +#ifndef _SYS__EXTERR_H_ +#define _SYS__EXTERR_H_ + +#include + +struct kexterr { + int error; + const char *msg; + __uint64_t p1; + __uint64_t p2; + unsigned cat; + unsigned src_line; +}; + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/_iovec.h b/lib/libc/include/generic-freebsd/sys/_iovec.h index 0f113de6d694..e7c02ecf2953 100644 --- a/lib/libc/include/generic-freebsd/sys/_iovec.h +++ b/lib/libc/include/generic-freebsd/sys/_iovec.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)uio.h 8.5 (Berkeley) 2/22/94 */ #ifndef _SYS__IOVEC_H_ @@ -46,4 +44,28 @@ struct iovec { size_t iov_len; /* Length. */ }; +#ifdef _KERNEL +#define IOVEC_INIT(iovp, base, len) \ + *(iovp) = (struct iovec){ .iov_base = (base), .iov_len = (len) } + +/* String with length including NUL terminator */ +#define IOVEC_INIT_CSTR(iovp, str) do { \ + void *__str = (str); \ + IOVEC_INIT(iovp, __str, strlen(__str) + 1); \ +} while(0) + +/* Object with size from sizeof() */ +#define IOVEC_INIT_OBJ(iovp, obj) \ + IOVEC_INIT(iovp, &(obj), sizeof(obj)) + +#define IOVEC_ADVANCE(iovp, amt) do { \ + struct iovec *__iovp = (iovp); \ + size_t __amt = (amt); \ + KASSERT(__amt <= __iovp->iov_len, ("%s: amount %zu > iov_len \ + %zu", __func__, __amt, __iovp->iov_len)); \ + __iovp->iov_len -= __amt; \ + __iovp->iov_base = (char *)__iovp->iov_base + __amt; \ +} while(0) +#endif /* _KERNEL */ + #endif /* !_SYS__IOVEC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/_lock.h b/lib/libc/include/generic-freebsd/sys/_lock.h index 3945f7ffc10c..017fedbde8f4 100644 --- a/lib/libc/include/generic-freebsd/sys/_lock.h +++ b/lib/libc/include/generic-freebsd/sys/_lock.h @@ -33,8 +33,8 @@ struct lock_object { const char *lo_name; /* Individual lock name. */ - u_int lo_flags; - u_int lo_data; /* General class specific data. */ + unsigned int lo_flags; + unsigned int lo_data; /* General class specific data. */ struct witness *lo_witness; /* Data for witness. */ }; diff --git a/lib/libc/include/generic-freebsd/sys/_maxphys.h b/lib/libc/include/generic-freebsd/sys/_maxphys.h new file mode 100644 index 000000000000..4a52368fdbad --- /dev/null +++ b/lib/libc/include/generic-freebsd/sys/_maxphys.h @@ -0,0 +1,10 @@ +/*- + * This file is in the public domain. + */ +#ifndef MAXPHYS +#ifdef __ILP32__ +#define MAXPHYS (128 * 1024) +#else +#define MAXPHYS (1024 * 1024) +#endif +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/_mutex.h b/lib/libc/include/generic-freebsd/sys/_mutex.h index 3d5137963a64..6a5e1b1b6b06 100644 --- a/lib/libc/include/generic-freebsd/sys/_mutex.h +++ b/lib/libc/include/generic-freebsd/sys/_mutex.h @@ -31,6 +31,8 @@ #ifndef _SYS__MUTEX_H_ #define _SYS__MUTEX_H_ +#include +#include #include /* @@ -44,7 +46,7 @@ */ struct mtx { struct lock_object lock_object; /* Common lock properties. */ - volatile uintptr_t mtx_lock; /* Owner and flags. */ + volatile __uintptr_t mtx_lock; /* Owner and flags. */ }; /* @@ -58,7 +60,7 @@ struct mtx { */ struct mtx_padalign { struct lock_object lock_object; /* Common lock properties. */ - volatile uintptr_t mtx_lock; /* Owner and flags. */ + volatile __uintptr_t mtx_lock; /* Owner and flags. */ } __aligned(CACHE_LINE_SIZE); #endif /* !_SYS__MUTEX_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/_null.h b/lib/libc/include/generic-freebsd/sys/_null.h index 0f16678d74de..372724897dbe 100644 --- a/lib/libc/include/generic-freebsd/sys/_null.h +++ b/lib/libc/include/generic-freebsd/sys/_null.h @@ -31,9 +31,7 @@ #if !defined(__cplusplus) #define NULL ((void *)0) #else -#if __cplusplus >= 201103L -#define NULL nullptr -#elif defined(__GNUG__) && defined(__GNUC__) && __GNUC__ >= 4 +#if defined(__GNUG__) && defined(__GNUC__) && __GNUC__ >= 4 #define NULL __null #else #if defined(__LP64__) diff --git a/lib/libc/include/generic-freebsd/sys/_nv.h b/lib/libc/include/generic-freebsd/sys/_nv.h new file mode 100644 index 000000000000..517928714660 --- /dev/null +++ b/lib/libc/include/generic-freebsd/sys/_nv.h @@ -0,0 +1,45 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2009-2013 The FreeBSD Foundation + * + * This software was developed by Pawel Jakub Dawidek 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 AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __NV_H_ +#define __NV_H_ + +#ifndef _KERNEL +#include +#endif + +#ifndef _NVLIST_T_DECLARED +#define _NVLIST_T_DECLARED +struct nvlist; + +typedef struct nvlist nvlist_t; +#endif + +#endif /* !__NV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/_param.h b/lib/libc/include/generic-freebsd/sys/_param.h new file mode 100644 index 000000000000..bf99ac0b8ebe --- /dev/null +++ b/lib/libc/include/generic-freebsd/sys/_param.h @@ -0,0 +1,28 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + */ + +#ifndef _SYS__PARAM_H_ +#define _SYS__PARAM_H_ + +#define NBBY 8 /* number of bits in a byte */ +#define NBPW sizeof(int) /* number of bytes per word (integer) */ + +/* + * Macros for counting and rounding. + */ +#define nitems(x) (sizeof((x)) / sizeof((x)[0])) +#ifndef howmany +#define howmany(x, y) (((x)+((y)-1))/(y)) +#endif +#define rounddown(x, y) (((x)/(y))*(y)) +#define rounddown2(x, y) __align_down(x, y) /* if y is power of two */ +#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */ +#define roundup2(x, y) __align_up(x, y) /* if y is powers of two */ +#define powerof2(x) ((((x)-1)&(x))==0) + +#endif /* _SYS__PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/_rmlock.h b/lib/libc/include/generic-freebsd/sys/_rmlock.h index e7659e45823a..b17cca8cf1ac 100644 --- a/lib/libc/include/generic-freebsd/sys/_rmlock.h +++ b/lib/libc/include/generic-freebsd/sys/_rmlock.h @@ -32,6 +32,14 @@ #ifndef _SYS__RMLOCK_H_ #define _SYS__RMLOCK_H_ +#include +#include +#include +#include +#include + +struct thread; + /* * Mostly reader/occasional writer lock. */ @@ -66,8 +74,6 @@ struct rm_priotracker { LIST_ENTRY(rm_priotracker) rmp_qentry; }; -#include - struct rmslock_pcpu; struct rmslock { diff --git a/lib/libc/include/generic-freebsd/sys/_rwlock.h b/lib/libc/include/generic-freebsd/sys/_rwlock.h index 0b8f93b16edf..1c73c35023f9 100644 --- a/lib/libc/include/generic-freebsd/sys/_rwlock.h +++ b/lib/libc/include/generic-freebsd/sys/_rwlock.h @@ -28,6 +28,8 @@ #ifndef _SYS__RWLOCK_H_ #define _SYS__RWLOCK_H_ +#include +#include #include /* @@ -41,7 +43,7 @@ */ struct rwlock { struct lock_object lock_object; - volatile uintptr_t rw_lock; + volatile __uintptr_t rw_lock; }; /* @@ -55,7 +57,7 @@ struct rwlock { */ struct rwlock_padalign { struct lock_object lock_object; - volatile uintptr_t rw_lock; + volatile __uintptr_t rw_lock; } __aligned(CACHE_LINE_SIZE); #endif /* !_SYS__RWLOCK_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/_sigaltstack.h b/lib/libc/include/generic-freebsd/sys/_sigaltstack.h new file mode 100644 index 000000000000..be4522e0b852 --- /dev/null +++ b/lib/libc/include/generic-freebsd/sys/_sigaltstack.h @@ -0,0 +1,65 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1982, 1986, 1989, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _SYS__SIGALTSTACK_H_ +#define _SYS__SIGALTSTACK_H_ + +#include + +#if __XSI_VISIBLE +#if __BSD_VISIBLE +#define __stack_t sigaltstack +#endif +typedef struct __stack_t stack_t; + +#define SS_ONSTACK 0x0001 /* take signal on alternate stack */ +#define SS_DISABLE 0x0004 /* disable taking signals on alternate stack */ +#define MINSIGSTKSZ __MINSIGSTKSZ /* minimum stack size */ +#define SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended stack size */ +#endif + +/* + * Structure used in sigaltstack call. Its definition is always + * needed for __ucontext. If __BSD_VISIBLE is defined, the structure + * tag is actually sigaltstack. + */ +struct __stack_t { + void *ss_sp; /* signal stack base */ + __size_t ss_size; /* signal stack length */ + int ss_flags; /* SS_DISABLE and/or SS_ONSTACK */ +}; + +#endif /* !_SYS__SIGALTSTACK_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/_sigset.h b/lib/libc/include/generic-freebsd/sys/_sigset.h index 340288d82c19..951168089683 100644 --- a/lib/libc/include/generic-freebsd/sys/_sigset.h +++ b/lib/libc/include/generic-freebsd/sys/_sigset.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)signal.h 8.4 (Berkeley) 5/4/95 */ #ifndef _SYS__SIGSET_H_ diff --git a/lib/libc/include/generic-freebsd/sys/_sockaddr_storage.h b/lib/libc/include/generic-freebsd/sys/_sockaddr_storage.h index 8719fc22f221..3a9a65481f01 100644 --- a/lib/libc/include/generic-freebsd/sys/_sockaddr_storage.h +++ b/lib/libc/include/generic-freebsd/sys/_sockaddr_storage.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)socket.h 8.4 (Berkeley) 2/21/94 */ #ifndef _SYS__SOCKADDR_STORAGE_H_ diff --git a/lib/libc/include/generic-freebsd/sys/_stdarg.h b/lib/libc/include/generic-freebsd/sys/_stdarg.h index bd662fd512bb..040f8ae9dfc5 100644 --- a/lib/libc/include/generic-freebsd/sys/_stdarg.h +++ b/lib/libc/include/generic-freebsd/sys/_stdarg.h @@ -31,12 +31,11 @@ #ifndef _SYS__STDARG_H_ #define _SYS__STDARG_H_ -#include -#include +#include #ifndef _VA_LIST_DECLARED - #define _VA_LIST_DECLARED - typedef __va_list va_list; +#define _VA_LIST_DECLARED +typedef __builtin_va_list va_list; #endif #define va_start(ap, last) __builtin_va_start((ap), (last)) diff --git a/lib/libc/include/generic-freebsd/sys/_sx.h b/lib/libc/include/generic-freebsd/sys/_sx.h index 41ab002625eb..6e00a1320252 100644 --- a/lib/libc/include/generic-freebsd/sys/_sx.h +++ b/lib/libc/include/generic-freebsd/sys/_sx.h @@ -31,12 +31,15 @@ #ifndef _SYS__SX_H_ #define _SYS__SX_H_ +#include +#include + /* * Shared/exclusive lock main structure definition. */ struct sx { struct lock_object lock_object; - volatile uintptr_t sx_lock; + volatile __uintptr_t sx_lock; }; #endif /* !_SYS__SX_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/_termios.h b/lib/libc/include/generic-freebsd/sys/_termios.h index f54d4163f9c3..056e5549cb38 100644 --- a/lib/libc/include/generic-freebsd/sys/_termios.h +++ b/lib/libc/include/generic-freebsd/sys/_termios.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)termios.h 8.3 (Berkeley) 3/28/94 */ #ifndef _SYS__TERMIOS_H_ diff --git a/lib/libc/include/generic-freebsd/sys/_timespec.h b/lib/libc/include/generic-freebsd/sys/_timespec.h index 63891fb4bcc6..1663dc3a73b6 100644 --- a/lib/libc/include/generic-freebsd/sys/_timespec.h +++ b/lib/libc/include/generic-freebsd/sys/_timespec.h @@ -27,9 +27,6 @@ * 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. - * - * @(#)time.h 8.5 (Berkeley) 5/4/95 - * from: FreeBSD: src/sys/sys/time.h,v 1.43 2000/03/20 14:09:05 phk Exp */ #ifndef _SYS__TIMESPEC_H_ diff --git a/lib/libc/include/generic-freebsd/sys/_tls_variant_i.h b/lib/libc/include/generic-freebsd/sys/_tls_variant_i.h index de16f3e4be2b..ed8910a76786 100644 --- a/lib/libc/include/generic-freebsd/sys/_tls_variant_i.h +++ b/lib/libc/include/generic-freebsd/sys/_tls_variant_i.h @@ -37,8 +37,18 @@ struct pthread; +struct dtv_slot { + char *dtvs_tls; +}; + +struct dtv { + uintptr_t dtv_gen; + uintptr_t dtv_size; + struct dtv_slot dtv_slots[]; +}; + struct tcb { - uintptr_t *tcb_dtv; /* required by rtld */ + struct dtv *tcb_dtv; /* required by rtld */ struct pthread *tcb_thread; }; diff --git a/lib/libc/include/generic-freebsd/sys/_types.h b/lib/libc/include/generic-freebsd/sys/_types.h index de93e2389f75..fb5b14162cc3 100644 --- a/lib/libc/include/generic-freebsd/sys/_types.h +++ b/lib/libc/include/generic-freebsd/sys/_types.h @@ -29,8 +29,6 @@ #ifndef _SYS__TYPES_H_ #define _SYS__TYPES_H_ -#include - /* * Basic types upon which most other types are built. * @@ -181,12 +179,23 @@ typedef __uint_least32_t __char32_t; #endif typedef struct { - long long __max_align1 __aligned(_Alignof(long long)); + long long __max_align1 + __attribute__((__aligned__(__alignof__(long long)))); #ifndef _STANDALONE - long double __max_align2 __aligned(_Alignof(long double)); + long double __max_align2 + __attribute__((__aligned__(__alignof__(long long)))); #endif } __max_align_t; +/* Types for sys/acl.h */ +typedef __uint32_t __acl_tag_t; +typedef __uint32_t __acl_perm_t; +typedef __uint16_t __acl_entry_type_t; +typedef __uint16_t __acl_flag_t; +typedef __uint32_t __acl_type_t; +typedef __uint32_t *__acl_permset_t; +typedef __uint16_t *__acl_flagset_t; + typedef __uint64_t __dev_t; /* device number */ typedef __uint32_t __fixpt_t; /* fixed point number */ diff --git a/lib/libc/include/generic-freebsd/sys/_uexterror.h b/lib/libc/include/generic-freebsd/sys/_uexterror.h new file mode 100644 index 000000000000..e428715a8567 --- /dev/null +++ b/lib/libc/include/generic-freebsd/sys/_uexterror.h @@ -0,0 +1,29 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 The FreeBSD Foundation + * All rights reserved. + * + * This software were developed by Konstantin Belousov + * under sponsorship from the FreeBSD Foundation. + */ + +#ifndef _SYS__UEXTERROR_H_ +#define _SYS__UEXTERROR_H_ + +#include + +struct uexterror { + __uint32_t ver; + __uint32_t error; + __uint32_t cat; + __uint32_t src_line; + __uint32_t flags; + __uint32_t rsrv0; + __uint64_t p1; + __uint64_t p2; + __uint64_t rsrv1[4]; + char msg[128]; +}; + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/_uio.h b/lib/libc/include/generic-freebsd/sys/_uio.h index e530d1df0ccf..959e683f6cbd 100644 --- a/lib/libc/include/generic-freebsd/sys/_uio.h +++ b/lib/libc/include/generic-freebsd/sys/_uio.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)uio.h 8.5 (Berkeley) 2/22/94 */ #ifndef _SYS__UIO_H_ diff --git a/lib/libc/include/generic-freebsd/sys/_visible.h b/lib/libc/include/generic-freebsd/sys/_visible.h new file mode 100644 index 000000000000..91a58159bab3 --- /dev/null +++ b/lib/libc/include/generic-freebsd/sys/_visible.h @@ -0,0 +1,223 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Berkeley Software Design, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _SYS__VISIBLE_H_ +#define _SYS__VISIBLE_H_ + +/*- + * The following definitions are an extension of the behavior originally + * implemented in , but with a different level of granularity. + * POSIX.1 requires that the macros we test be defined before any standard + * header file is included. + * + * Here's a quick run-down of the versions (and some informal names) + * defined(_POSIX_SOURCE) 1003.1-1988 + * encoded as 198808 below + * _POSIX_C_SOURCE == 1 1003.1-1990 + * encoded as 199009 below + * _POSIX_C_SOURCE == 2 1003.2-1992 C Language Binding Option + * encoded as 199209 below + * _POSIX_C_SOURCE == 199309 1003.1b-1993 + * (1003.1 Issue 4, Single Unix Spec v1, Unix 93) + * _POSIX_C_SOURCE == 199506 1003.1c-1995, 1003.1i-1995, + * and the omnibus ISO/IEC 9945-1: 1996 + * (1003.1 Issue 5, Single Unix Spec v2, Unix 95) + * _POSIX_C_SOURCE == 200112 1003.1-2001 (1003.1 Issue 6, Unix 03) + * with _XOPEN_SOURCE=600 + * _POSIX_C_SOURCE == 200809 1003.1-2008 (1003.1 Issue 7) + * IEEE Std 1003.1-2017 (Rev of 1003.1-2008) is + * 1003.1-2008 with two TCs applied and + * _XOPEN_SOURCE=700 + * _POSIX_C_SOURCE == 202405 1003.1-2004 (1003.1 Issue 8), IEEE Std 1003.1-2024 + * with _XOPEN_SOURCE=800 + * + * In addition, the X/Open Portability Guide, which is now the Single UNIX + * Specification, defines a feature-test macro which indicates the version of + * that specification, and which subsumes _POSIX_C_SOURCE. + * + * Our macros begin with two underscores to avoid namespace screwage. + */ + +/* Deal with IEEE Std. 1003.1-1990, in which _POSIX_C_SOURCE == 1. */ +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE == 1 +#undef _POSIX_C_SOURCE /* Probably illegal, but beyond caring now. */ +#define _POSIX_C_SOURCE 199009 +#endif + +/* Deal with IEEE Std. 1003.2-1992, in which _POSIX_C_SOURCE == 2. */ +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE == 2 +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 199209 +#endif + +/* + * Deal with various X/Open Portability Guides and Single UNIX Spec. We use the + * '- 0' construct so software that defines _XOPEN_SOURCE to nothing doesn't + * cause errors. X/Open CAE Specification, August 1994, System Interfaces and + * Headers, Issue 4, Version 2 section 2.2 states an empty definition means the + * same thing as _POSIX_C_SOURCE == 2. This broadly mirrors "System V Interface + * Definition, Fourth Edition", but earlier editions suggest some ambiguity. + * However, FreeBSD has histoically implemented this as a NOP, so we just + * document what it should be for now to not break ports gratuitously. + */ +#ifdef _XOPEN_SOURCE +#if _XOPEN_SOURCE - 0 >= 800 +#define __XSI_VISIBLE 800 +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 202405 +#elif _XOPEN_SOURCE - 0 >= 700 +#define __XSI_VISIBLE 700 +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200809 +#elif _XOPEN_SOURCE - 0 >= 600 +#define __XSI_VISIBLE 600 +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200112 +#elif _XOPEN_SOURCE - 0 >= 500 +#define __XSI_VISIBLE 500 +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 199506 +#else +/* #define _POSIX_C_SOURCE 199209 */ +#endif +#endif + +/* + * Deal with all versions of POSIX. The ordering relative to the tests above is + * important. + */ +#if defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 198808 +#endif +#ifdef _POSIX_C_SOURCE +#if _POSIX_C_SOURCE >= 202405 +#define __POSIX_VISIBLE 202405 +#define __ISO_C_VISIBLE 2017 +#elif _POSIX_C_SOURCE >= 200809 +#define __POSIX_VISIBLE 200809 +#define __ISO_C_VISIBLE 1999 +#elif _POSIX_C_SOURCE >= 200112 +#define __POSIX_VISIBLE 200112 +#define __ISO_C_VISIBLE 1999 +#elif _POSIX_C_SOURCE >= 199506 +#define __POSIX_VISIBLE 199506 +#define __ISO_C_VISIBLE 1990 +#elif _POSIX_C_SOURCE >= 199309 +#define __POSIX_VISIBLE 199309 +#define __ISO_C_VISIBLE 1990 +#elif _POSIX_C_SOURCE >= 199209 +#define __POSIX_VISIBLE 199209 +#define __ISO_C_VISIBLE 1990 +#elif _POSIX_C_SOURCE >= 199009 +#define __POSIX_VISIBLE 199009 +#define __ISO_C_VISIBLE 1990 +#else +#define __POSIX_VISIBLE 198808 +#define __ISO_C_VISIBLE 0 +#endif /* _POSIX_C_SOURCE */ + +/* + * When we've explicitly asked for a newer C version, make the C variable + * visible by default. Also honor the glibc _ISOC{11,23}_SOURCE macros + * extensions. Both glibc and OpenBSD do this, even when a more strict + * _POSIX_C_SOURCE has been requested, and it makes good sense (especially for + * pre POSIX 2024, since C11 is much nicer than the old C99 base). Continue the + * practice with C23, though don't do older standards. Also, GLIBC doesn't have + * a _ISOC17_SOURCE, so it's not implemented here. glibc has earlier ISOCxx defines, + * but we don't implement those as they are not relevant enough. + */ +#if _ISOC23_SOURCE || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) +#undef __ISO_C_VISIBLE +#define __ISO_C_VISIBLE 2023 +#elif _ISOC11_SOURCE || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) +#undef __ISO_C_VISIBLE +#define __ISO_C_VISIBLE 2011 +#endif +#else /* _POSIX_C_SOURCE */ +/*- + * Deal with _ANSI_SOURCE: + * If it is defined, and no other compilation environment is explicitly + * requested, then define our internal feature-test macros to zero. This + * makes no difference to the preprocessor (undefined symbols in preprocessing + * expressions are defined to have value zero), but makes it more convenient for + * a test program to print out the values. + * + * If a program mistakenly defines _ANSI_SOURCE and some other macro such as + * _POSIX_C_SOURCE, we will assume that it wants the broader compilation + * environment (and in fact we will never get here). + */ +#if defined(_ANSI_SOURCE) /* Hide almost everything. */ +#define __POSIX_VISIBLE 0 +#define __XSI_VISIBLE 0 +#define __BSD_VISIBLE 0 +#define __ISO_C_VISIBLE 1990 +#define __EXT1_VISIBLE 0 +#elif defined(_C99_SOURCE) /* Localism to specify strict C99 env. */ +#define __POSIX_VISIBLE 0 +#define __XSI_VISIBLE 0 +#define __BSD_VISIBLE 0 +#define __ISO_C_VISIBLE 1999 +#define __EXT1_VISIBLE 0 +#elif defined(_C11_SOURCE) /* Localism to specify strict C11 env. */ +#define __POSIX_VISIBLE 0 +#define __XSI_VISIBLE 0 +#define __BSD_VISIBLE 0 +#define __ISO_C_VISIBLE 2011 +#define __EXT1_VISIBLE 0 +#elif defined(_C23_SOURCE) /* Localism to specify strict C23 env. */ +#define __POSIX_VISIBLE 0 +#define __XSI_VISIBLE 0 +#define __BSD_VISIBLE 0 +#define __ISO_C_VISIBLE 2023 +#define __EXT1_VISIBLE 0 +#else /* Default environment: show everything. */ +#define __POSIX_VISIBLE 202405 +#define __XSI_VISIBLE 800 +#define __BSD_VISIBLE 1 +#define __ISO_C_VISIBLE 2023 +#define __EXT1_VISIBLE 1 +#endif +#endif /* _POSIX_C_SOURCE */ + +/* User override __EXT1_VISIBLE */ +#if defined(__STDC_WANT_LIB_EXT1__) +#undef __EXT1_VISIBLE +#if __STDC_WANT_LIB_EXT1__ +#define __EXT1_VISIBLE 1 +#else +#define __EXT1_VISIBLE 0 +#endif +#endif /* __STDC_WANT_LIB_EXT1__ */ + +#endif /* !_SYS__VISIBLE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/_winsize.h b/lib/libc/include/generic-freebsd/sys/_winsize.h index 035db068a7d4..c4f9d4562509 100644 --- a/lib/libc/include/generic-freebsd/sys/_winsize.h +++ b/lib/libc/include/generic-freebsd/sys/_winsize.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)ttycom.h 8.1 (Berkeley) 3/28/94 */ #ifndef _SYS__WINSIZE_H_ diff --git a/lib/libc/include/generic-freebsd/sys/acct.h b/lib/libc/include/generic-freebsd/sys/acct.h index fd68325c0fc8..9b994de4176f 100644 --- a/lib/libc/include/generic-freebsd/sys/acct.h +++ b/lib/libc/include/generic-freebsd/sys/acct.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)acct.h 8.4 (Berkeley) 1/9/95 */ #ifndef _SYS_ACCT_H_ diff --git a/lib/libc/include/generic-freebsd/sys/acl.h b/lib/libc/include/generic-freebsd/sys/acl.h index 059b65f0e84d..508e3d5d3328 100644 --- a/lib/libc/include/generic-freebsd/sys/acl.h +++ b/lib/libc/include/generic-freebsd/sys/acl.h @@ -36,21 +36,23 @@ #ifndef _SYS_ACL_H_ #define _SYS_ACL_H_ -#include -#include -#include +#include +#include +#ifdef _KERNEL +#include +#endif /* * POSIX.1e and NFSv4 ACL types and related constants. */ -typedef uint32_t acl_tag_t; -typedef uint32_t acl_perm_t; -typedef uint16_t acl_entry_type_t; -typedef uint16_t acl_flag_t; -typedef int acl_type_t; -typedef int *acl_permset_t; -typedef uint16_t *acl_flagset_t; +typedef __acl_tag_t acl_tag_t; +typedef __acl_perm_t acl_perm_t; +typedef __acl_entry_type_t acl_entry_type_t; +typedef __acl_flag_t acl_flag_t; +typedef __acl_type_t acl_type_t; +typedef __acl_permset_t acl_permset_t; +typedef __acl_flagset_t acl_flagset_t; /* * With 254 entries, "struct acl_t_struct" is exactly one 4kB page big. diff --git a/lib/libc/include/generic-freebsd/sys/aio.h b/lib/libc/include/generic-freebsd/sys/aio.h index c27e766737bf..6aa067394811 100644 --- a/lib/libc/include/generic-freebsd/sys/aio.h +++ b/lib/libc/include/generic-freebsd/sys/aio.h @@ -97,7 +97,7 @@ struct __aiocb_private { long status; long error; - void *kernelinfo; + void *spare; }; /* diff --git a/lib/libc/include/generic-freebsd/sys/asan.h b/lib/libc/include/generic-freebsd/sys/asan.h index fc6b826f40df..1cd2e4d702d7 100644 --- a/lib/libc/include/generic-freebsd/sys/asan.h +++ b/lib/libc/include/generic-freebsd/sys/asan.h @@ -53,14 +53,18 @@ #define KASAN_KSTACK_FREED 0xFE #define KASAN_EXEC_ARGS_FREED 0xFF +struct thread; + void kasan_init(void); void kasan_init_early(vm_offset_t, size_t); void kasan_shadow_map(vm_offset_t, size_t); void kasan_mark(const void *, size_t, size_t, uint8_t); +void kasan_thread_alloc(struct thread *); #else /* KASAN */ #define kasan_init() #define kasan_shadow_map(a, s) #define kasan_mark(p, s, l, c) +#define kasan_thread_alloc(t) #endif /* !KASAN */ #endif /* !_SYS_ASAN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/atomic_common.h b/lib/libc/include/generic-freebsd/sys/atomic_common.h index b33543ebdbfa..bb005ec34b06 100644 --- a/lib/libc/include/generic-freebsd/sys/atomic_common.h +++ b/lib/libc/include/generic-freebsd/sys/atomic_common.h @@ -36,18 +36,18 @@ #include -#define __atomic_load_bool_relaxed(p) (*(volatile _Bool *)(p)) +#define __atomic_load_bool_relaxed(p) (*(const volatile _Bool *)(p)) #define __atomic_store_bool_relaxed(p, v) \ (*(volatile _Bool *)(p) = (_Bool)(v)) -#define __atomic_load_char_relaxed(p) (*(volatile u_char *)(p)) -#define __atomic_load_short_relaxed(p) (*(volatile u_short *)(p)) -#define __atomic_load_int_relaxed(p) (*(volatile u_int *)(p)) -#define __atomic_load_long_relaxed(p) (*(volatile u_long *)(p)) -#define __atomic_load_8_relaxed(p) (*(volatile uint8_t *)(p)) -#define __atomic_load_16_relaxed(p) (*(volatile uint16_t *)(p)) -#define __atomic_load_32_relaxed(p) (*(volatile uint32_t *)(p)) -#define __atomic_load_64_relaxed(p) (*(volatile uint64_t *)(p)) +#define __atomic_load_char_relaxed(p) (*(const volatile u_char *)(p)) +#define __atomic_load_short_relaxed(p) (*(const volatile u_short *)(p)) +#define __atomic_load_int_relaxed(p) (*(const volatile u_int *)(p)) +#define __atomic_load_long_relaxed(p) (*(const volatile u_long *)(p)) +#define __atomic_load_8_relaxed(p) (*(const volatile uint8_t *)(p)) +#define __atomic_load_16_relaxed(p) (*(const volatile uint16_t *)(p)) +#define __atomic_load_32_relaxed(p) (*(const volatile uint32_t *)(p)) +#define __atomic_load_64_relaxed(p) (*(const volatile uint64_t *)(p)) #define __atomic_store_char_relaxed(p, v) \ (*(volatile u_char *)(p) = (u_char)(v)) @@ -124,7 +124,7 @@ __atomic_store_generic(p, v, int64_t, uint64_t, 64) #endif -#define atomic_load_ptr(p) (*(volatile __typeof(*p) *)(p)) +#define atomic_load_ptr(p) (*(const volatile __typeof(*p) *)(p)) #define atomic_store_ptr(p, v) (*(volatile __typeof(*p) *)(p) = (v)) /* @@ -133,7 +133,7 @@ * openly resorting to the stronger acquire fence, to be sorted out. */ #define atomic_load_consume_ptr(p) \ - ((__typeof(*p)) atomic_load_acq_ptr((uintptr_t *)p)) + ((__typeof(*p)) atomic_load_acq_ptr((const volatile uintptr_t *)p)) #define atomic_interrupt_fence() __compiler_membar() diff --git a/lib/libc/include/generic-freebsd/sys/atomic_san.h b/lib/libc/include/generic-freebsd/sys/atomic_san.h index 6c308ba40611..b9c76185766c 100644 --- a/lib/libc/include/generic-freebsd/sys/atomic_san.h +++ b/lib/libc/include/generic-freebsd/sys/atomic_san.h @@ -65,10 +65,10 @@ type sp##_atomic_readandclear_##name(volatile type *) #define ATOMIC_SAN_LOAD(sp, name, type) \ - type sp##_atomic_load_##name(volatile type *) + type sp##_atomic_load_##name(const volatile type *) #define ATOMIC_SAN_LOAD_ACQ(sp, name, type) \ - type sp##_atomic_load_acq_##name(volatile type *) + type sp##_atomic_load_acq_##name(const volatile type *) #define ATOMIC_SAN_STORE(sp, name, type) \ void sp##_atomic_store_##name(volatile type *, type) @@ -266,11 +266,10 @@ ATOMIC_SAN_THREAD_FENCE(SAN_INTERCEPTOR_PREFIX); #define atomic_fcmpset_rel_ptr ATOMIC_SAN(fcmpset_rel_ptr) #define atomic_fetchadd_ptr ATOMIC_SAN(fetchadd_ptr) #define atomic_load_ptr(x) \ - ((__typeof(*x))ATOMIC_SAN(load_ptr)( \ - __DECONST(volatile uintptr_t *, (x)))) + ((__typeof(*x))ATOMIC_SAN(load_ptr)((const volatile uintptr_t *)(x))) #define atomic_load_acq_ptr ATOMIC_SAN(load_acq_ptr) #define atomic_load_consume_ptr(x) \ - ((__typeof(*x))atomic_load_acq_ptr((volatile uintptr_t *)(x))) + ((__typeof(*x))atomic_load_acq_ptr((const volatile uintptr_t *)(x))) #define atomic_readandclear_ptr ATOMIC_SAN(readandclear_ptr) #define atomic_set_ptr ATOMIC_SAN(set_ptr) #define atomic_set_acq_ptr ATOMIC_SAN(set_acq_ptr) diff --git a/lib/libc/include/generic-freebsd/sys/bio.h b/lib/libc/include/generic-freebsd/sys/bio.h index dbde610f8c05..bcd955d17e3c 100644 --- a/lib/libc/include/generic-freebsd/sys/bio.h +++ b/lib/libc/include/generic-freebsd/sys/bio.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)buf.h 8.9 (Berkeley) 3/30/95 */ #ifndef _SYS_BIO_H_ @@ -77,7 +75,6 @@ #ifdef _KERNEL struct disk; struct bio; -struct vm_map; typedef void bio_task_t(void *); @@ -146,7 +143,6 @@ struct bio_queue_head { int batched; }; -extern struct vm_map *bio_transient_map; extern int bio_transient_maxcnt; void biodone(struct bio *bp); diff --git a/lib/libc/include/generic-freebsd/sys/bitcount.h b/lib/libc/include/generic-freebsd/sys/bitcount.h index 4153d8b8e6cc..0f7fdeaf8917 100644 --- a/lib/libc/include/generic-freebsd/sys/bitcount.h +++ b/lib/libc/include/generic-freebsd/sys/bitcount.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)types.h 8.6 (Berkeley) 2/19/95 */ #ifndef _SYS_BITCOUNT_H_ diff --git a/lib/libc/include/generic-freebsd/sys/buf.h b/lib/libc/include/generic-freebsd/sys/buf.h index 4a1338d2cb87..beafe9d9c577 100644 --- a/lib/libc/include/generic-freebsd/sys/buf.h +++ b/lib/libc/include/generic-freebsd/sys/buf.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)buf.h 8.9 (Berkeley) 3/30/95 */ #ifndef _SYS_BUF_H_ @@ -298,7 +296,7 @@ struct buf { * Initialize a lock. */ #define BUF_LOCKINIT(bp, wmesg) \ - lockinit(&(bp)->b_lock, PRIBIO + 4, wmesg, 0, LK_NEW) + lockinit(&(bp)->b_lock, PVFS, wmesg, 0, LK_NEW) /* * * Get a lock sleeping non-interruptably until it becomes available. @@ -313,7 +311,7 @@ struct buf { */ #define BUF_TIMELOCK(bp, locktype, interlock, wmesg, catch, timo) \ _lockmgr_args_rw(&(bp)->b_lock, (locktype) | LK_TIMELOCK, \ - (interlock), (wmesg), (PRIBIO + 4) | (catch), (timo), \ + (interlock), (wmesg), PVFS | (catch), (timo), \ LOCK_FILE, LOCK_LINE) /* @@ -343,6 +341,13 @@ struct buf { */ #define BUF_ISLOCKED(bp) \ lockstatus(&(bp)->b_lock) + +/* + * Check if a buffer lock is currently held by LK_KERNPROC. + */ +#define BUF_DISOWNED(bp) \ + lockmgr_disowned(&(bp)->b_lock) + /* * Free a buffer lock. */ @@ -514,7 +519,6 @@ extern int nbuf; /* The number of buffer headers */ extern u_long maxswzone; /* Max KVA for swap structures */ extern u_long maxbcache; /* Max KVA for buffer cache */ extern int maxbcachebuf; /* Max buffer cache block size */ -extern long runningbufspace; extern long hibufspace; extern int dirtybufthresh; extern int bdwriteskip; @@ -531,6 +535,7 @@ buf_mapped(struct buf *bp) return (bp->b_data != unmapped_buf); } +long runningbufclaim(struct buf *, int); void runningbufwakeup(struct buf *); void waitrunningbufspace(void); caddr_t kern_vfs_bio_buffer_alloc(caddr_t v, long physmem_est); @@ -598,7 +603,7 @@ void vfs_unbusy_pages(struct buf *); int vmapbuf(struct buf *, void *, size_t, int); void vunmapbuf(struct buf *); void brelvp(struct buf *); -void bgetvp(struct vnode *, struct buf *); +int bgetvp(struct vnode *, struct buf *) __result_use_check; void pbgetbo(struct bufobj *bo, struct buf *bp); void pbgetvp(struct vnode *, struct buf *); void pbrelbo(struct buf *); diff --git a/lib/libc/include/generic-freebsd/sys/buf_ring.h b/lib/libc/include/generic-freebsd/sys/buf_ring.h index b97a4bd51b8a..5e48d6612869 100644 --- a/lib/libc/include/generic-freebsd/sys/buf_ring.h +++ b/lib/libc/include/generic-freebsd/sys/buf_ring.h @@ -51,13 +51,13 @@ * */ struct buf_ring { - volatile uint32_t br_prod_head; - volatile uint32_t br_prod_tail; + uint32_t br_prod_head; + uint32_t br_prod_tail; int br_prod_size; int br_prod_mask; uint64_t br_drops; - volatile uint32_t br_cons_head __aligned(CACHE_LINE_SIZE); - volatile uint32_t br_cons_tail; + uint32_t br_cons_head __aligned(CACHE_LINE_SIZE); + uint32_t br_cons_tail; int br_cons_size; int br_cons_mask; #if defined(DEBUG_BUFRING) && defined(_KERNEL) @@ -83,10 +83,12 @@ buf_ring_enqueue(struct buf_ring *br, void *buf) * via drbr_peek(), and then re-added via drbr_putback() and * trigger a spurious panic. */ - for (uint32_t i = br->br_cons_head; i != br->br_prod_head; i++) + for (uint32_t i = atomic_load_32(&br->br_cons_head); + i != atomic_load_32(&br->br_prod_head); i++) if (br->br_ring[i & mask] == buf) panic("buf=%p already enqueue at %d prod=%d cons=%d", - buf, i, br->br_prod_tail, br->br_cons_tail); + buf, i, atomic_load_32(&br->br_prod_tail), + atomic_load_32(&br->br_cons_tail)); #endif critical_enter(); do { @@ -105,16 +107,15 @@ buf_ring_enqueue(struct buf_ring *br, void *buf) cons_tail = atomic_load_acq_32(&br->br_cons_tail); if ((int32_t)(cons_tail + br->br_prod_size - prod_next) < 1) { - rmb(); - if (prod_head == br->br_prod_head && - cons_tail == br->br_cons_tail) { + if (prod_head == atomic_load_32(&br->br_prod_head) && + cons_tail == atomic_load_32(&br->br_cons_tail)) { br->br_drops++; critical_exit(); return (ENOBUFS); } continue; } - } while (!atomic_cmpset_acq_32(&br->br_prod_head, prod_head, prod_next)); + } while (!atomic_cmpset_32(&br->br_prod_head, prod_head, prod_next)); prod_idx = prod_head & mask; #ifdef DEBUG_BUFRING if (br->br_ring[prod_idx] != NULL) @@ -127,7 +128,7 @@ buf_ring_enqueue(struct buf_ring *br, void *buf) * that preceded us, we need to wait for them * to complete */ - while (br->br_prod_tail != prod_head) + while (atomic_load_32(&br->br_prod_tail) != prod_head) cpu_spinwait(); atomic_store_rel_32(&br->br_prod_tail, prod_next); critical_exit(); @@ -161,7 +162,7 @@ buf_ring_dequeue_mc(struct buf_ring *br) critical_exit(); return (NULL); } - } while (!atomic_cmpset_acq_32(&br->br_cons_head, cons_head, cons_next)); + } while (!atomic_cmpset_32(&br->br_cons_head, cons_head, cons_next)); cons_idx = cons_head & mask; buf = br->br_ring[cons_idx]; @@ -173,7 +174,7 @@ buf_ring_dequeue_mc(struct buf_ring *br) * that preceded us, we need to wait for them * to complete */ - while (br->br_cons_tail != cons_head) + while (atomic_load_32(&br->br_cons_tail) != cons_head) cpu_spinwait(); atomic_store_rel_32(&br->br_cons_tail, cons_next); @@ -195,7 +196,7 @@ buf_ring_dequeue_sc(struct buf_ring *br) void *buf; mask = br->br_cons_mask; - cons_head = br->br_cons_head; + cons_head = atomic_load_32(&br->br_cons_head); prod_tail = atomic_load_acq_32(&br->br_prod_tail); cons_next = cons_head + 1; @@ -204,7 +205,7 @@ buf_ring_dequeue_sc(struct buf_ring *br) return (NULL); cons_idx = cons_head & mask; - br->br_cons_head = cons_next; + atomic_store_32(&br->br_cons_head, cons_next); buf = br->br_ring[cons_idx]; #ifdef DEBUG_BUFRING @@ -213,9 +214,9 @@ buf_ring_dequeue_sc(struct buf_ring *br) if (!mtx_owned(br->br_lock)) panic("lock not held on single consumer dequeue"); #endif - if (br->br_cons_tail != cons_head) + if (atomic_load_32(&br->br_cons_tail) != cons_head) panic("inconsistent list cons_tail=%d cons_head=%d", - br->br_cons_tail, cons_head); + atomic_load_32(&br->br_cons_tail), cons_head); #endif atomic_store_rel_32(&br->br_cons_tail, cons_next); return (buf); @@ -235,13 +236,13 @@ buf_ring_advance_sc(struct buf_ring *br) mask = br->br_cons_mask; #endif - cons_head = br->br_cons_head; - prod_tail = br->br_prod_tail; + cons_head = atomic_load_32(&br->br_cons_head); + prod_tail = atomic_load_32(&br->br_prod_tail); cons_next = cons_head + 1; if (cons_head == prod_tail) return; - br->br_cons_head = cons_next; + atomic_store_32(&br->br_cons_head, cons_next); #ifdef DEBUG_BUFRING br->br_ring[cons_head & mask] = NULL; #endif @@ -267,12 +268,13 @@ buf_ring_advance_sc(struct buf_ring *br) static __inline void buf_ring_putback_sc(struct buf_ring *br, void *new) { - uint32_t mask; + uint32_t cons_idx, mask; mask = br->br_cons_mask; - KASSERT((br->br_cons_head & mask) != (br->br_prod_tail & mask), + cons_idx = atomic_load_32(&br->br_cons_head) & mask; + KASSERT(cons_idx != (atomic_load_32(&br->br_prod_tail) & mask), ("Buf-Ring has none in putback")) ; - br->br_ring[br->br_cons_head & mask] = new; + br->br_ring[cons_idx] = new; } /* @@ -291,7 +293,7 @@ buf_ring_peek(struct buf_ring *br) #endif mask = br->br_cons_mask; prod_tail = atomic_load_acq_32(&br->br_prod_tail); - cons_head = br->br_cons_head; + cons_head = atomic_load_32(&br->br_cons_head); if (cons_head == prod_tail) return (NULL); @@ -312,7 +314,7 @@ buf_ring_peek_clear_sc(struct buf_ring *br) mask = br->br_cons_mask; prod_tail = atomic_load_acq_32(&br->br_prod_tail); - cons_head = br->br_cons_head; + cons_head = atomic_load_32(&br->br_cons_head); if (cons_head == prod_tail) return (NULL); @@ -332,22 +334,26 @@ static __inline int buf_ring_full(struct buf_ring *br) { - return (br->br_prod_head == br->br_cons_tail + br->br_cons_size - 1); + return (atomic_load_32(&br->br_prod_head) == + atomic_load_32(&br->br_cons_tail) + br->br_cons_size - 1); } static __inline int buf_ring_empty(struct buf_ring *br) { - return (br->br_cons_head == br->br_prod_tail); + return (atomic_load_32(&br->br_cons_head) == + atomic_load_32(&br->br_prod_tail)); } static __inline int buf_ring_count(struct buf_ring *br) { + uint32_t cons_tail, prod_tail; - return ((br->br_prod_size + br->br_prod_tail - br->br_cons_tail) - & br->br_prod_mask); + cons_tail = atomic_load_32(&br->br_cons_tail); + prod_tail = atomic_load_32(&br->br_prod_tail); + return ((br->br_prod_size + prod_tail - cons_tail) & br->br_prod_mask); } #ifdef _KERNEL diff --git a/lib/libc/include/generic-freebsd/sys/bufobj.h b/lib/libc/include/generic-freebsd/sys/bufobj.h index ca2b25d85ef7..8d9b52231ff0 100644 --- a/lib/libc/include/generic-freebsd/sys/bufobj.h +++ b/lib/libc/include/generic-freebsd/sys/bufobj.h @@ -33,7 +33,7 @@ * cache. * * This used to be vnodes, but we need non-vnode code to be able - * to use the buffer cache as well, specifically geom classes like gbde, + * to use the buffer cache as well, specifically geom classes like * raid3 and raid5. * * All vnodes will contain a bufobj initially, but down the road we may @@ -116,6 +116,7 @@ struct bufobj { #define BO_WWAIT (1 << 1) /* Wait for output to complete */ #define BO_DEAD (1 << 2) /* Dead; only with INVARIANTS */ #define BO_NOBUFS (1 << 3) /* No bufs allowed */ +#define BO_NONSTERILE (1 << 4) /* Ever called reassignbuf() */ #define BO_LOCKPTR(bo) (&(bo)->bo_lock) #define BO_LOCK(bo) rw_wlock(BO_LOCKPTR((bo))) diff --git a/lib/libc/include/generic-freebsd/sys/bus.h b/lib/libc/include/generic-freebsd/sys/bus.h index 272518bd97ad..a884a4fc07c4 100644 --- a/lib/libc/include/generic-freebsd/sys/bus.h +++ b/lib/libc/include/generic-freebsd/sys/bus.h @@ -159,6 +159,7 @@ struct devreq { /* Flags for DEV_RESET */ #define DEVF_RESET_DETACH 0x0000001 /* Detach drivers vs suspend device */ +#define DEVICE_UNIT_ANY (-1) #ifdef _KERNEL @@ -276,6 +277,7 @@ enum intr_type { INTR_EXCL = 256, /* exclusive interrupt */ INTR_MPSAFE = 512, /* this interrupt is SMP safe */ INTR_ENTROPY = 1024, /* this interrupt provides entropy */ + INTR_SLEEPABLE = 2048, /* this interrupt handler can sleep */ INTR_MD1 = 4096, /* flag reserved for MD use */ INTR_MD2 = 8192, /* flag reserved for MD use */ INTR_MD3 = 16384, /* flag reserved for MD use */ @@ -305,18 +307,6 @@ enum cpu_sets { INTR_CPUS }; -typedef int (*devop_t)(void); - -/** - * @brief This structure is deprecated. - * - * Use the kobj(9) macro DEFINE_CLASS to - * declare classes which implement device drivers. - */ -struct driver { - KOBJ_CLASS_FIELDS; -}; - struct resource; /** @@ -396,7 +386,7 @@ struct resource * rman_res_t count, u_int flags); int resource_list_release(struct resource_list *rl, device_t bus, device_t child, - int type, int rid, struct resource *res); + struct resource *res); int resource_list_release_active(struct resource_list *rl, device_t bus, device_t child, int type); @@ -427,12 +417,12 @@ void root_bus_configure(void); struct _cpuset; -int bus_generic_activate_resource(device_t dev, device_t child, int type, - int rid, struct resource *r); +int bus_generic_activate_resource(device_t dev, device_t child, + struct resource *r); device_t bus_generic_add_child(device_t dev, u_int order, const char *name, int unit); -int bus_generic_adjust_resource(device_t bus, device_t child, int type, +int bus_generic_adjust_resource(device_t bus, device_t child, struct resource *r, rman_res_t start, rman_res_t end); struct resource * @@ -441,7 +431,8 @@ struct resource * rman_res_t count, u_int flags); int bus_generic_translate_resource(device_t dev, int type, rman_res_t start, rman_res_t *newstart); -int bus_generic_attach(device_t dev); +int bus_generic_attach(device_t dev) + __deprecated1("Use bus_attach_children instead"); int bus_generic_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu); int bus_generic_child_location(device_t dev, device_t child, struct sbuf *sb); @@ -452,8 +443,8 @@ int bus_generic_config_intr(device_t, int, enum intr_trigger, int bus_generic_describe_intr(device_t dev, device_t child, struct resource *irq, void *cookie, const char *descr); -int bus_generic_deactivate_resource(device_t dev, device_t child, int type, - int rid, struct resource *r); +int bus_generic_deactivate_resource(device_t dev, device_t child, + struct resource *r); int bus_generic_detach(device_t dev); void bus_generic_driver_added(device_t dev, driver_t *driver); int bus_generic_get_cpus(device_t dev, device_t child, enum cpu_sets op, @@ -466,9 +457,7 @@ int bus_generic_get_domain(device_t dev, device_t child, int *domain); ssize_t bus_generic_get_property(device_t dev, device_t child, const char *propname, void *propvalue, size_t size, device_property_type_t type); -struct resource_list * - bus_generic_get_resource_list(device_t, device_t); -int bus_generic_map_resource(device_t dev, device_t child, int type, +int bus_generic_map_resource(device_t dev, device_t child, struct resource *r, struct resource_map_request *args, struct resource_map *map); @@ -477,11 +466,12 @@ int bus_print_child_header(device_t dev, device_t child); int bus_print_child_domain(device_t dev, device_t child); int bus_print_child_footer(device_t dev, device_t child); int bus_generic_print_child(device_t dev, device_t child); -int bus_generic_probe(device_t dev); +int bus_generic_probe(device_t dev) + __deprecated1("Use bus_identify_children instead"); int bus_generic_read_ivar(device_t dev, device_t child, int which, uintptr_t *result); int bus_generic_release_resource(device_t bus, device_t child, - int type, int rid, struct resource *r); + struct resource *r); int bus_generic_resume(device_t dev); int bus_generic_resume_child(device_t dev, device_t child); int bus_generic_setup_intr(device_t dev, device_t child, @@ -497,24 +487,20 @@ int bus_generic_rl_get_resource (device_t, device_t, int, int, rman_res_t *, rman_res_t *); int bus_generic_rl_set_resource (device_t, device_t, int, int, rman_res_t, rman_res_t); -int bus_generic_rl_release_resource (device_t, device_t, int, int, - struct resource *); +int bus_generic_rl_release_resource (device_t, device_t, struct resource *); struct resource * bus_generic_rman_alloc_resource(device_t dev, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags); -int bus_generic_rman_adjust_resource(device_t dev, device_t child, int type, +int bus_generic_rman_adjust_resource(device_t dev, device_t child, struct resource *r, rman_res_t start, rman_res_t end); int bus_generic_rman_release_resource(device_t dev, device_t child, - int type, int rid, struct resource *r); int bus_generic_rman_activate_resource(device_t dev, device_t child, - int type, int rid, struct resource *r); int bus_generic_rman_deactivate_resource(device_t dev, device_t child, - int type, int rid, struct resource *r); int bus_generic_shutdown(device_t dev); @@ -526,7 +512,7 @@ int bus_generic_suspend_intr(device_t dev, device_t child, struct resource *irq); int bus_generic_resume_intr(device_t dev, device_t child, struct resource *irq); -int bus_generic_unmap_resource(device_t dev, device_t child, int type, +int bus_generic_unmap_resource(device_t dev, device_t child, struct resource *r, struct resource_map *map); int bus_generic_write_ivar(device_t dev, device_t child, int which, @@ -554,29 +540,26 @@ int bus_alloc_resources(device_t dev, struct resource_spec *rs, void bus_release_resources(device_t dev, const struct resource_spec *rs, struct resource **res); -int bus_adjust_resource(device_t child, int type, struct resource *r, +int bus_adjust_resource(device_t child, struct resource *r, rman_res_t start, rman_res_t end); int bus_translate_resource(device_t child, int type, rman_res_t start, rman_res_t *newstart); struct resource *bus_alloc_resource(device_t dev, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags); -int bus_activate_resource(device_t dev, int type, int rid, - struct resource *r); -int bus_deactivate_resource(device_t dev, int type, int rid, - struct resource *r); -int bus_map_resource(device_t dev, int type, struct resource *r, +int bus_activate_resource(device_t dev, struct resource *r); +int bus_deactivate_resource(device_t dev, struct resource *r); +int bus_map_resource(device_t dev, struct resource *r, struct resource_map_request *args, struct resource_map *map); -int bus_unmap_resource(device_t dev, int type, struct resource *r, +int bus_unmap_resource(device_t dev, struct resource *r, struct resource_map *map); int bus_get_cpus(device_t dev, enum cpu_sets op, size_t setsize, struct _cpuset *cpuset); bus_dma_tag_t bus_get_dma_tag(device_t dev); bus_space_tag_t bus_get_bus_tag(device_t dev); int bus_get_domain(device_t dev, int *domain); -int bus_release_resource(device_t dev, int type, int rid, - struct resource *r); +int bus_release_resource(device_t dev, struct resource *r); int bus_free_resource(device_t dev, int type, struct resource *r); int bus_setup_intr(device_t dev, struct resource *r, int flags, driver_filter_t filter, driver_intr_t handler, @@ -597,8 +580,12 @@ void bus_delete_resource(device_t dev, int type, int rid); int bus_child_present(device_t child); int bus_child_pnpinfo(device_t child, struct sbuf *sb); int bus_child_location(device_t child, struct sbuf *sb); + +void bus_attach_children(device_t dev); +void bus_delayed_attach_children(device_t bus); +int bus_detach_children(device_t dev); void bus_enumerate_hinted_children(device_t bus); -int bus_delayed_attach_children(device_t bus); +void bus_identify_children(device_t dev); static __inline struct resource * bus_alloc_resource_any(device_t dev, int type, int *rid, u_int flags) @@ -613,6 +600,47 @@ bus_alloc_resource_anywhere(device_t dev, int type, int *rid, return (bus_alloc_resource(dev, type, rid, 0, ~0, count, flags)); } +/* Compat shims for simpler bus resource API. */ +int bus_adjust_resource_old(device_t child, int type, struct resource *r, + rman_res_t start, rman_res_t end); +int bus_activate_resource_old(device_t dev, int type, int rid, + struct resource *r); +int bus_deactivate_resource_old(device_t dev, int type, int rid, + struct resource *r); +int bus_map_resource_old(device_t dev, int type, struct resource *r, + struct resource_map_request *args, + struct resource_map *map); +int bus_unmap_resource_old(device_t dev, int type, struct resource *r, + struct resource_map *map); +int bus_release_resource_old(device_t dev, int type, int rid, + struct resource *r); + +#define _BUS_API_MACRO(_1, _2, _3, _4, _5, NAME, ...) NAME + +#define bus_adjust_resource(...) \ + _BUS_API_MACRO(__VA_ARGS__, bus_adjust_resource_old, \ + bus_adjust_resource)(__VA_ARGS__) + +#define bus_activate_resource(...) \ + _BUS_API_MACRO(__VA_ARGS__, INVALID, bus_activate_resource_old, \ + INVALID, bus_activate_resource)(__VA_ARGS__) + +#define bus_deactivate_resource(...) \ + _BUS_API_MACRO(__VA_ARGS__, INVALID, bus_deactivate_resource_old, \ + INVALID, bus_deactivate_resource)(__VA_ARGS__) + +#define bus_map_resource(...) \ + _BUS_API_MACRO(__VA_ARGS__, bus_map_resource_old, \ + bus_map_resource)(__VA_ARGS__) + +#define bus_unmap_resource(...) \ + _BUS_API_MACRO(__VA_ARGS__, INVALID, bus_unmap_resource_old, \ + bus_unmap_resource)(__VA_ARGS__) + +#define bus_release_resource(...) \ + _BUS_API_MACRO(__VA_ARGS__, INVALID, bus_release_resource_old, \ + INVALID, bus_release_resource)(__VA_ARGS__) + /* * Access functions for device. */ @@ -783,9 +811,7 @@ void bus_data_generation_update(void); #define BUS_LOCATOR_UEFI "UEFI" #define BUS_LOCATOR_OFW "OFW" -extern int bus_current_pass; - -void bus_set_pass(int pass); +int bus_get_pass(void); /** * Routines to lock / unlock the newbus lock. @@ -824,24 +850,25 @@ struct driver_module_data { int dmd_pass; }; -#define EARLY_DRIVER_MODULE_ORDERED(name, busname, driver, evh, arg, \ +#define EARLY_DRIVER_MODULE_ORDERED(_name, busname, driver, evh, arg, \ order, pass) \ \ -static struct driver_module_data name##_##busname##_driver_mod = { \ - evh, arg, \ - #busname, \ - (kobj_class_t) &driver, \ - NULL, \ - pass \ +static struct driver_module_data _name##_##busname##_driver_mod = { \ + .dmd_chainevh = evh, \ + .dmd_chainarg = arg, \ + .dmd_busname = #busname, \ + .dmd_driver = (kobj_class_t)&driver, \ + .dmd_devclass = NULL, \ + .dmd_pass = pass, \ }; \ \ -static moduledata_t name##_##busname##_mod = { \ - #busname "/" #name, \ - driver_module_handler, \ - &name##_##busname##_driver_mod \ +static moduledata_t _name##_##busname##_mod = { \ + .name = #busname "/" #_name , \ + .evhand = driver_module_handler, \ + .priv = &_name##_##busname##_driver_mod, \ }; \ -DECLARE_MODULE(name##_##busname, name##_##busname##_mod, \ - SI_SUB_DRIVERS, order) +DECLARE_MODULE(_name##_##busname, _name##_##busname##_mod, \ + SI_SUB_DRIVERS, order) #define EARLY_DRIVER_MODULE(name, busname, driver, evh, arg, pass) \ EARLY_DRIVER_MODULE_ORDERED(name, busname, driver, evh, arg, \ diff --git a/lib/libc/include/generic-freebsd/sys/bus_dma.h b/lib/libc/include/generic-freebsd/sys/bus_dma.h index edf3d7bd9a98..5c6b2be705c1 100644 --- a/lib/libc/include/generic-freebsd/sys/bus_dma.h +++ b/lib/libc/include/generic-freebsd/sys/bus_dma.h @@ -161,11 +161,8 @@ void _busdma_dflt_lock(void *arg, bus_dma_lock_op_t op); * boundary: Boundary that segments cannot cross. * lowaddr: Low restricted address that cannot appear in a mapping. * highaddr: High restricted address that cannot appear in a mapping. - * filtfunc: An optional function to further test if an address - * within the range of lowaddr and highaddr cannot appear - * in a mapping. - * filtfuncarg: An argument that will be passed to filtfunc in addition - * to the address to test. + * filtfunc: (deprecated, must be NULL) + * filtfuncarg: (deprecated, must be NULL) * maxsize: Maximum mapping size supported by this tag. * nsegments: Number of discontinuities allowed in maps. * maxsegsz: Maximum size of a segment in the map. diff --git a/lib/libc/include/generic-freebsd/sys/callout.h b/lib/libc/include/generic-freebsd/sys/callout.h index c18df73207e4..d95e05695470 100644 --- a/lib/libc/include/generic-freebsd/sys/callout.h +++ b/lib/libc/include/generic-freebsd/sys/callout.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)callout.h 8.2 (Berkeley) 1/21/94 */ #ifndef _SYS_CALLOUT_H_ @@ -41,7 +39,7 @@ #include -#define CALLOUT_LOCAL_ALLOC 0x0001 /* was allocated from callfree */ +#define CALLOUT_TRYLOCK 0x0001 /* try semantic in softclock_call_cc */ #define CALLOUT_ACTIVE 0x0002 /* callout is currently active */ #define CALLOUT_PENDING 0x0004 /* callout is waiting for timeout */ #define CALLOUT_MPSAFE 0x0008 /* deprecated */ @@ -83,18 +81,15 @@ */ #define callout_active(c) ((c)->c_flags & CALLOUT_ACTIVE) #define callout_deactivate(c) ((c)->c_flags &= ~CALLOUT_ACTIVE) -#define callout_drain(c) _callout_stop_safe(c, CS_DRAIN, NULL) +#define callout_drain(c) _callout_stop_safe(c, CS_DRAIN) void callout_init(struct callout *, int); void _callout_init_lock(struct callout *, struct lock_object *, int); #define callout_init_mtx(c, mtx, flags) \ - _callout_init_lock((c), ((mtx) != NULL) ? &(mtx)->lock_object : \ - NULL, (flags)) + _callout_init_lock((c), &(mtx)->lock_object, (flags)) #define callout_init_rm(c, rm, flags) \ - _callout_init_lock((c), ((rm) != NULL) ? &(rm)->lock_object : \ - NULL, (flags)) + _callout_init_lock((c), &(rm)->lock_object, (flags)) #define callout_init_rw(c, rw, flags) \ - _callout_init_lock((c), ((rw) != NULL) ? &(rw)->lock_object : \ - NULL, (flags)) + _callout_init_lock((c), &(rw)->lock_object, (flags)) #define callout_pending(c) ((c)->c_iflags & CALLOUT_PENDING) int callout_reset_sbt_on(struct callout *, sbintime_t, sbintime_t, void (*)(void *), void *, int, int); @@ -121,11 +116,9 @@ int callout_schedule(struct callout *, int); int callout_schedule_on(struct callout *, int, int); #define callout_schedule_curcpu(c, on_tick) \ callout_schedule_on((c), (on_tick), PCPU_GET(cpuid)) -#define callout_stop(c) _callout_stop_safe(c, 0, NULL) -int _callout_stop_safe(struct callout *, int, void (*)(void *)); +#define callout_stop(c) _callout_stop_safe(c, 0) +int _callout_stop_safe(struct callout *, int); void callout_process(sbintime_t now); -#define callout_async_drain(c, d) \ - _callout_stop_safe(c, 0, d) void callout_when(sbintime_t sbt, sbintime_t precision, int flags, sbintime_t *sbt_res, sbintime_t *prec_res); #endif diff --git a/lib/libc/include/generic-freebsd/sys/caprights.h b/lib/libc/include/generic-freebsd/sys/caprights.h index 26eb80db7fd1..3c06e9433b66 100644 --- a/lib/libc/include/generic-freebsd/sys/caprights.h +++ b/lib/libc/include/generic-freebsd/sys/caprights.h @@ -58,51 +58,54 @@ typedef struct cap_rights cap_rights_t; #endif #ifdef _KERNEL -extern cap_rights_t cap_accept_rights; -extern cap_rights_t cap_bind_rights; -extern cap_rights_t cap_connect_rights; -extern cap_rights_t cap_event_rights; -extern cap_rights_t cap_fchdir_rights; -extern cap_rights_t cap_fchflags_rights; -extern cap_rights_t cap_fchmod_rights; -extern cap_rights_t cap_fchown_rights; -extern cap_rights_t cap_fcntl_rights; -extern cap_rights_t cap_fexecve_rights; -extern cap_rights_t cap_flock_rights; -extern cap_rights_t cap_fpathconf_rights; -extern cap_rights_t cap_fstat_rights; -extern cap_rights_t cap_fstatfs_rights; -extern cap_rights_t cap_fsync_rights; -extern cap_rights_t cap_ftruncate_rights; -extern cap_rights_t cap_futimes_rights; -extern cap_rights_t cap_getpeername_rights; -extern cap_rights_t cap_getsockopt_rights; -extern cap_rights_t cap_getsockname_rights; -extern cap_rights_t cap_ioctl_rights; -extern cap_rights_t cap_linkat_source_rights; -extern cap_rights_t cap_linkat_target_rights; -extern cap_rights_t cap_listen_rights; -extern cap_rights_t cap_mkdirat_rights; -extern cap_rights_t cap_mkfifoat_rights; -extern cap_rights_t cap_mknodat_rights; -extern cap_rights_t cap_mmap_rights; -extern cap_rights_t cap_no_rights; -extern cap_rights_t cap_pdgetpid_rights; -extern cap_rights_t cap_pdkill_rights; -extern cap_rights_t cap_pread_rights; -extern cap_rights_t cap_pwrite_rights; -extern cap_rights_t cap_read_rights; -extern cap_rights_t cap_recv_rights; -extern cap_rights_t cap_renameat_source_rights; -extern cap_rights_t cap_renameat_target_rights; -extern cap_rights_t cap_seek_rights; -extern cap_rights_t cap_send_rights; -extern cap_rights_t cap_send_connect_rights; -extern cap_rights_t cap_setsockopt_rights; -extern cap_rights_t cap_shutdown_rights; -extern cap_rights_t cap_symlinkat_rights; -extern cap_rights_t cap_unlinkat_rights; -extern cap_rights_t cap_write_rights; +extern const cap_rights_t cap_accept_rights; +extern const cap_rights_t cap_bind_rights; +extern const cap_rights_t cap_connect_rights; +extern const cap_rights_t cap_event_rights; +extern const cap_rights_t cap_fchdir_rights; +extern const cap_rights_t cap_fchflags_rights; +extern const cap_rights_t cap_fchmod_rights; +extern const cap_rights_t cap_fchown_rights; +extern const cap_rights_t cap_fchroot_rights; +extern const cap_rights_t cap_fcntl_rights; +extern const cap_rights_t cap_fexecve_rights; +extern const cap_rights_t cap_flock_rights; +extern const cap_rights_t cap_fpathconf_rights; +extern const cap_rights_t cap_fstat_rights; +extern const cap_rights_t cap_fstatfs_rights; +extern const cap_rights_t cap_fsync_rights; +extern const cap_rights_t cap_ftruncate_rights; +extern const cap_rights_t cap_futimes_rights; +extern const cap_rights_t cap_getpeername_rights; +extern const cap_rights_t cap_getsockopt_rights; +extern const cap_rights_t cap_getsockname_rights; +extern const cap_rights_t cap_inotify_add_rights; +extern const cap_rights_t cap_inotify_rm_rights; +extern const cap_rights_t cap_ioctl_rights; +extern const cap_rights_t cap_linkat_source_rights; +extern const cap_rights_t cap_linkat_target_rights; +extern const cap_rights_t cap_listen_rights; +extern const cap_rights_t cap_mkdirat_rights; +extern const cap_rights_t cap_mkfifoat_rights; +extern const cap_rights_t cap_mknodat_rights; +extern const cap_rights_t cap_mmap_rights; +extern const cap_rights_t cap_no_rights; +extern const cap_rights_t cap_pdgetpid_rights; +extern const cap_rights_t cap_pdkill_rights; +extern const cap_rights_t cap_pread_rights; +extern const cap_rights_t cap_pwrite_rights; +extern const cap_rights_t cap_read_rights; +extern const cap_rights_t cap_recv_rights; +extern const cap_rights_t cap_renameat_source_rights; +extern const cap_rights_t cap_renameat_target_rights; +extern const cap_rights_t cap_seek_rights; +extern const cap_rights_t cap_send_rights; +extern const cap_rights_t cap_send_connect_rights; +extern const cap_rights_t cap_setsockopt_rights; +extern const cap_rights_t cap_shutdown_rights; +extern const cap_rights_t cap_symlinkat_rights; +extern const cap_rights_t cap_unlinkat_rights; +extern const cap_rights_t cap_write_rights; #endif #endif /* !_SYS_CAPRIGHTS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/capsicum.h b/lib/libc/include/generic-freebsd/sys/capsicum.h index cf1faa52a020..bc5e6ca8e4b9 100644 --- a/lib/libc/include/generic-freebsd/sys/capsicum.h +++ b/lib/libc/include/generic-freebsd/sys/capsicum.h @@ -39,7 +39,6 @@ #ifndef _SYS_CAPSICUM_H_ #define _SYS_CAPSICUM_H_ -#include #include #include @@ -202,6 +201,9 @@ /* Allows for renameat(2) (target directory descriptor). */ #define CAP_RENAMEAT_TARGET (CAP_LOOKUP | 0x0000040000000000ULL) +/* Allows for fchroot(2). */ +#define CAP_FCHROOT CAPRIGHT(0, 0x0000080000000000ULL) + #define CAP_SOCK_CLIENT \ (CAP_CONNECT | CAP_GETPEERNAME | CAP_GETSOCKNAME | CAP_GETSOCKOPT | \ CAP_PEELOFF | CAP_RECV | CAP_SEND | CAP_SETSOCKOPT | CAP_SHUTDOWN) @@ -211,11 +213,9 @@ CAP_SETSOCKOPT | CAP_SHUTDOWN) /* All used bits for index 0. */ -#define CAP_ALL0 CAPRIGHT(0, 0x000007FFFFFFFFFFULL) +#define CAP_ALL0 CAPRIGHT(0, 0x00000FFFFFFFFFFFULL) /* Available bits for index 0. */ -#define CAP_UNUSED0_44 CAPRIGHT(0, 0x0000080000000000ULL) -/* ... */ #define CAP_UNUSED0_57 CAPRIGHT(0, 0x0100000000000000ULL) /* INDEX 1 */ @@ -279,11 +279,15 @@ #define CAP_KQUEUE (CAP_KQUEUE_EVENT | CAP_KQUEUE_CHANGE) +/* Allows operations on inotify descriptors. */ +#define CAP_INOTIFY_ADD CAPRIGHT(1, 0x0000000000200000ULL) +#define CAP_INOTIFY_RM CAPRIGHT(1, 0x0000000000400000ULL) + /* All used bits for index 1. */ -#define CAP_ALL1 CAPRIGHT(1, 0x00000000001FFFFFULL) +#define CAP_ALL1 CAPRIGHT(1, 0x00000000007FFFFFULL) /* Available bits for index 1. */ -#define CAP_UNUSED1_22 CAPRIGHT(1, 0x0000000000200000ULL) +#define CAP_UNUSED1_22 CAPRIGHT(1, 0x0000000000800000ULL) /* ... */ #define CAP_UNUSED1_57 CAPRIGHT(1, 0x0100000000000000ULL) @@ -371,6 +375,24 @@ _Static_assert(CAP_RIGHTS_VERSION == CAP_RIGHTS_VERSION_00, _r; \ }) +#define _CAP_RIGHTS_WORD_INITIALIZER(i, r) \ + (CAPIDXBIT(r) == (i) + 1 ? (r) : 0ULL) + +/* + * Define a set of up to two rights at compile time. + */ +#define CAP_RIGHTS_INITIALIZER2(r1, r2) ((struct cap_rights){ \ + .cr_rights = { \ + [0] = ((uint64_t)CAP_RIGHTS_VERSION << 62) | \ + _CAP_RIGHTS_WORD_INITIALIZER(0, r1) | \ + _CAP_RIGHTS_WORD_INITIALIZER(0, r2), \ + [1] = _CAP_RIGHTS_WORD_INITIALIZER(1, r1) | \ + _CAP_RIGHTS_WORD_INITIALIZER(1, r2), \ + }, \ +}) +#define CAP_RIGHTS_INITIALIZER(r) \ + CAP_RIGHTS_INITIALIZER2(r, 0ULL) + /* * Allow checking caps which are possibly getting modified at the same time. * The caller is expected to determine whether the result is legitimate via diff --git a/lib/libc/include/generic-freebsd/sys/cdefs.h b/lib/libc/include/generic-freebsd/sys/cdefs.h index ebdedf902353..695f9919aaf2 100644 --- a/lib/libc/include/generic-freebsd/sys/cdefs.h +++ b/lib/libc/include/generic-freebsd/sys/cdefs.h @@ -30,8 +30,6 @@ * 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. - * - * @(#)cdefs.h 8.8 (Berkeley) 1/9/95 */ #ifndef _SYS_CDEFS_H_ @@ -42,7 +40,10 @@ #endif /* - * Testing against Clang-specific extensions. + * Provide clang-compatible testing macros. All supported versions of gcc (10+) + * provide all of these except has_feature and has_extension which are new in + * gcc 14. Keep the older ifndefs, though, for non-gcc compilers that may lack + * them like tcc and pcc. */ #ifndef __has_attribute #define __has_attribute(x) 0 @@ -74,61 +75,34 @@ * having a compiler-agnostic source tree. */ +/* + * Macro to test if we're using a specific version of gcc or later. + */ #if defined(__GNUC__) - -#if __GNUC__ >= 3 -#define __GNUCLIKE_ASM 3 -#define __GNUCLIKE_MATH_BUILTIN_CONSTANTS +#define __GNUC_PREREQ__(ma, mi) \ + (__GNUC__ > (ma) || __GNUC__ == (ma) && __GNUC_MINOR__ >= (mi)) #else -#define __GNUCLIKE_ASM 2 -#endif -#define __GNUCLIKE___TYPEOF 1 -#define __GNUCLIKE___SECTION 1 - -#define __GNUCLIKE_CTOR_SECTION_HANDLING 1 - -#define __GNUCLIKE_BUILTIN_CONSTANT_P 1 - -#if (__GNUC_MINOR__ > 95 || __GNUC__ >= 3) -#define __GNUCLIKE_BUILTIN_VARARGS 1 -#define __GNUCLIKE_BUILTIN_STDARG 1 -#define __GNUCLIKE_BUILTIN_VAALIST 1 +#define __GNUC_PREREQ__(ma, mi) 0 #endif -#define __GNUC_VA_LIST_COMPATIBILITY 1 +#if defined(__GNUC__) /* * Compiler memory barriers, specific to gcc and clang. */ #define __compiler_membar() __asm __volatile(" " : : : "memory") -#define __GNUCLIKE_BUILTIN_NEXT_ARG 1 -#define __GNUCLIKE_MATH_BUILTIN_RELOPS - -#define __GNUCLIKE_BUILTIN_MEMCPY 1 - -/* XXX: if __GNUC__ >= 2: not tested everywhere originally, where replaced */ -#define __CC_SUPPORTS_INLINE 1 #define __CC_SUPPORTS___INLINE 1 -#define __CC_SUPPORTS___INLINE__ 1 - -#define __CC_SUPPORTS___FUNC__ 1 -#define __CC_SUPPORTS_WARNING 1 - -#define __CC_SUPPORTS_VARADIC_XXX 1 /* see varargs.h */ - -#define __CC_SUPPORTS_DYNAMIC_ARRAY_INIT 1 +#define __CC_SUPPORTS_SYMVER 1 #endif /* __GNUC__ */ /* - * Macro to test if we're using a specific version of gcc or later. + * TinyC pretends to be gcc 9.3. This is generally good enough to support + * everything FreeBSD... except for the .symver assembler directive. */ -#if defined(__GNUC__) -#define __GNUC_PREREQ__(ma, mi) \ - (__GNUC__ > (ma) || __GNUC__ == (ma) && __GNUC_MINOR__ >= (mi)) -#else -#define __GNUC_PREREQ__(ma, mi) 0 +#ifdef __TINYC__ +#undef __CC_SUPPORTS_SYMVER #endif /* @@ -150,8 +124,6 @@ #define __STRING(x) #x /* stringify without expanding x */ #define __XSTRING(x) __STRING(x) /* expand x, then stringify */ -#define __const const /* define reserved names to standard */ -#define __signed signed #define __volatile volatile #if defined(__cplusplus) #define __inline inline /* convert to C++ keyword */ @@ -165,76 +137,32 @@ #define __P(protos) () /* traditional C preprocessor */ #define __CONCAT(x,y) x/**/y #define __STRING(x) "x" - #if !defined(__CC_SUPPORTS___INLINE) -#define __const /* delete pseudo-ANSI C keywords */ +/* Just delete these in a K&R environment */ #define __inline -#define __signed #define __volatile -/* - * In non-ANSI C environments, new programs will want ANSI-only C keywords - * deleted from the program and old programs will want them left alone. - * When using a compiler other than gcc, programs using the ANSI C keywords - * const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS. - * When using "gcc -traditional", we assume that this is the intent; if - * __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone. - */ -#ifndef NO_ANSI_KEYWORDS -#define const /* delete ANSI C keywords */ -#define inline -#define signed -#define volatile -#endif /* !NO_ANSI_KEYWORDS */ #endif /* !__CC_SUPPORTS___INLINE */ #endif /* !(__STDC__ || __cplusplus) */ /* - * Compiler-dependent macros to help declare dead (non-returning) and - * pure (no side effects) functions, and unused variables. They are - * null except for versions of gcc that are known to support the features - * properly (old versions of gcc-2 supported the dead and pure features - * in a different (wrong) way). If we do not provide an implementation - * for a given compiler, let the compile fail if it is told to use - * a feature that we cannot live without. + * Compiler-dependent macros to help declare dead (non-returning) and pure (no + * side effects) functions, and unused variables. These attributes are supported + * by all current compilers, even pcc. */ #define __weak_symbol __attribute__((__weak__)) -#if !__GNUC_PREREQ__(2, 5) -#define __dead2 -#define __pure2 -#define __unused -#endif -#if __GNUC__ == 2 && __GNUC_MINOR__ >= 5 && __GNUC_MINOR__ < 7 -#define __dead2 __attribute__((__noreturn__)) -#define __pure2 __attribute__((__const__)) -#define __unused -/* XXX Find out what to do for __packed, __aligned and __section */ -#endif -#if __GNUC_PREREQ__(2, 7) #define __dead2 __attribute__((__noreturn__)) #define __pure2 __attribute__((__const__)) #define __unused __attribute__((__unused__)) #define __used __attribute__((__used__)) +#define __deprecated __attribute__((__deprecated__)) +#define __deprecated1(msg) __attribute__((__deprecated__(msg))) #define __packed __attribute__((__packed__)) #define __aligned(x) __attribute__((__aligned__(x))) #define __section(x) __attribute__((__section__(x))) -#endif #define __writeonly __unused -#if __GNUC_PREREQ__(4, 3) || __has_attribute(__alloc_size__) #define __alloc_size(x) __attribute__((__alloc_size__(x))) #define __alloc_size2(n, x) __attribute__((__alloc_size__(n, x))) -#else -#define __alloc_size(x) -#define __alloc_size2(n, x) -#endif -#if __GNUC_PREREQ__(4, 9) || __has_attribute(__alloc_align__) #define __alloc_align(x) __attribute__((__alloc_align__(x))) -#else -#define __alloc_align(x) -#endif - -#if !__GNUC_PREREQ__(2, 95) -#define __alignof(x) __offsetof(struct { char __a; x __b; }, __b) -#endif /* * Keywords added in C11. @@ -258,15 +186,6 @@ #define _Alignof(x) __alignof(x) #endif -#if !defined(__cplusplus) && !__has_extension(c_atomic) && \ - !__has_extension(cxx_atomic) && !__GNUC_PREREQ__(4, 7) -/* - * No native support for _Atomic(). Place object in structure to prevent - * most forms of direct non-atomic access. - */ -#define _Atomic(T) struct { T volatile __val; } -#endif - #if defined(__cplusplus) && __cplusplus >= 201103L #define _Noreturn [[noreturn]] #else @@ -281,12 +200,7 @@ #endif #if !__has_extension(c_thread_local) -/* - * XXX: Some compilers (Clang 3.3, GCC 4.7) falsely announce C++11 mode - * without actually supporting the thread_local keyword. Don't check for - * the presence of C++11 when defining _Thread_local. - */ -#if /* (defined(__cplusplus) && __cplusplus >= 201103L) || */ \ +#if (defined(__cplusplus) && __cplusplus >= 201103L) || \ __has_extension(cxx_thread_local) #define _Thread_local thread_local #else @@ -312,10 +226,10 @@ __has_extension(c_generic_selections) #define __generic(expr, t, yes, no) \ _Generic(expr, t: yes, default: no) -#elif __GNUC_PREREQ__(3, 1) && !defined(__cplusplus) +#elif !defined(__cplusplus) #define __generic(expr, t, yes, no) \ - __builtin_choose_expr( \ - __builtin_types_compatible_p(__typeof((0, (expr))), t), yes, no) + __builtin_choose_expr(__builtin_types_compatible_p( \ + __typeof(((void)0, (expr))), t), yes, no) #endif /* @@ -326,59 +240,24 @@ * void bar(int myArray[__min_size(10)]); */ #if !defined(__cplusplus) && \ - (defined(__clang__) || __GNUC_PREREQ__(4, 6)) && \ (!defined(__STDC_VERSION__) || (__STDC_VERSION__ >= 199901)) #define __min_size(x) static (x) #else #define __min_size(x) (x) #endif -#if __GNUC_PREREQ__(2, 96) #define __malloc_like __attribute__((__malloc__)) #define __pure __attribute__((__pure__)) -#else -#define __malloc_like -#define __pure -#endif - -#if __GNUC_PREREQ__(3, 1) -#define __always_inline __attribute__((__always_inline__)) -#else -#define __always_inline -#endif -#if __GNUC_PREREQ__(3, 1) +#define __always_inline __inline __attribute__((__always_inline__)) #define __noinline __attribute__ ((__noinline__)) -#else -#define __noinline -#endif - -#if __GNUC_PREREQ__(3, 4) #define __fastcall __attribute__((__fastcall__)) #define __result_use_check __attribute__((__warn_unused_result__)) -#else -#define __fastcall -#define __result_use_check -#endif - -#if __GNUC_PREREQ__(4, 1) #define __returns_twice __attribute__((__returns_twice__)) -#else -#define __returns_twice -#endif -#if __GNUC_PREREQ__(4, 6) || __has_builtin(__builtin_unreachable) #define __unreachable() __builtin_unreachable() -#else -#define __unreachable() ((void)0) -#endif -/* XXX: should use `#if __STDC_VERSION__ < 199901'. */ -#if !__GNUC_PREREQ__(2, 7) -#define __func__ NULL -#endif - -#if (defined(__GNUC__) && __GNUC__ >= 2) && !defined(__STRICT_ANSI__) || __STDC_VERSION__ >= 199901 +#if !defined(__STRICT_ANSI__) || __STDC_VERSION__ >= 199901 #define __LONG_LONG_SUPPORTED #endif @@ -393,6 +272,55 @@ #endif #endif +/* + * noexcept keyword added in C++11. + */ +#if defined(__cplusplus) && __cplusplus >= 201103L +#define __noexcept noexcept +#define __noexcept_if(__c) noexcept(__c) +#else +#define __noexcept +#define __noexcept_if(__c) +#endif + +/* + * nodiscard attribute added in C++17 and C23, but supported by both LLVM and + * GCC in earlier language versions, so we use __has_c{,pp}_attribute to test + * for it. + * + * __nodiscard may be used on a function: + * __nodiscard int f(); + * + * or on a struct, union or enum: + * struct __nodiscard S{}; + * struct S f(); + * + * or in C++, on an object constructor. + */ + +#if defined(__cplusplus) && defined(__has_cpp_attribute) +#if __has_cpp_attribute(nodiscard) +#define __nodiscard [[nodiscard]] +#endif +#elif defined(__STDC_VERSION__) && defined(__has_c_attribute) +#if __has_c_attribute(__nodiscard__) +#define __nodiscard [[__nodiscard__]] +#endif +#endif + +#ifndef __nodiscard +/* + * LLVM 16 and earlier don't support [[nodiscard]] in C, but they do support + * __warn_unused_result__ with the same semantics, so fall back to that. + * We can't do this for GCC because the semantics are different. + */ +#ifdef __clang__ +#define __nodiscard __attribute__((__warn_unused_result__)) +#else +#define __nodiscard +#endif +#endif + /* * We use `__restrict' as a way to define the `restrict' type qualifier * without disturbing older software that is unaware of C99 keywords. @@ -401,73 +329,27 @@ */ #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901 #define __restrict restrict -#elif !__GNUC_PREREQ__(2, 95) -#define __restrict #endif /* - * GNU C version 2.96 adds explicit branch prediction so that - * the CPU back-end can hint the processor and also so that - * code blocks can be reordered such that the predicted path - * sees a more linear flow, thus improving cache behavior, etc. - * - * The following two macros provide us with a way to utilize this - * compiler feature. Use __predict_true() if you expect the expression - * to evaluate to true, and __predict_false() if you expect the - * expression to evaluate to false. - * - * A few notes about usage: - * - * * Generally, __predict_false() error condition checks (unless - * you have some _strong_ reason to do otherwise, in which case - * document it), and/or __predict_true() `no-error' condition - * checks, assuming you want to optimize for the no-error case. - * - * * Other than that, if you don't know the likelihood of a test - * succeeding from empirical or other `hard' evidence, don't - * make predictions. - * - * * These are meant to be used in places that are run `a lot'. - * It is wasteful to make predictions in code that is run - * seldomly (e.g. at subsystem initialization time) as the - * basic block reordering that this affects can often generate - * larger code. + * All modern compilers have explicit branch prediction so that the CPU back-end + * can hint to the processor and also so that code blocks can be reordered such + * that the predicted path sees a more linear flow, thus improving cache + * behavior, etc. Use sparingly, except in performance critical code where + * they make things measurably faster. */ -#if __GNUC_PREREQ__(2, 96) #define __predict_true(exp) __builtin_expect((exp), 1) #define __predict_false(exp) __builtin_expect((exp), 0) -#else -#define __predict_true(exp) (exp) -#define __predict_false(exp) (exp) -#endif -#if __GNUC_PREREQ__(4, 0) #define __null_sentinel __attribute__((__sentinel__)) #define __exported __attribute__((__visibility__("default"))) #define __hidden __attribute__((__visibility__("hidden"))) -#else -#define __null_sentinel -#define __exported -#define __hidden -#endif /* * We define this here since , , and * require it. */ -#if __GNUC_PREREQ__(4, 1) #define __offsetof(type, field) __builtin_offsetof(type, field) -#else -#ifndef __cplusplus -#define __offsetof(type, field) \ - ((__size_t)(__uintptr_t)((const volatile void *)&((type *)0)->field)) -#else -#define __offsetof(type, field) \ - (__offsetof__ (reinterpret_cast <__size_t> \ - (&reinterpret_cast \ - (static_cast (0)->field)))) -#endif -#endif #define __rangeof(type, start, end) \ (__offsetof(type, end) - __offsetof(type, start)) @@ -477,29 +359,15 @@ * assign pointer x to a local variable, to check that its type is * compatible with member m. */ -#if __GNUC_PREREQ__(3, 1) #define __containerof(x, s, m) ({ \ const volatile __typeof(((s *)0)->m) *__x = (x); \ __DEQUALIFY(s *, (const volatile char *)__x - __offsetof(s, m));\ }) -#else -#define __containerof(x, s, m) \ - __DEQUALIFY(s *, (const volatile char *)(x) - __offsetof(s, m)) -#endif /* * Compiler-dependent macros to declare that functions take printf-like - * or scanf-like arguments. They are null except for versions of gcc - * that are known to support the features properly (old versions of gcc-2 - * didn't permit keeping the keywords out of the application namespace). + * or scanf-like arguments. */ -#if !__GNUC_PREREQ__(2, 7) -#define __printflike(fmtarg, firstvararg) -#define __scanflike(fmtarg, firstvararg) -#define __format_arg(fmtarg) -#define __strfmonlike(fmtarg, firstvararg) -#define __strftimelike(fmtarg, firstvararg) -#else #define __printflike(fmtarg, firstvararg) \ __attribute__((__format__ (__printf__, fmtarg, firstvararg))) #define __scanflike(fmtarg, firstvararg) \ @@ -509,18 +377,23 @@ __attribute__((__format__ (__strfmon__, fmtarg, firstvararg))) #define __strftimelike(fmtarg, firstvararg) \ __attribute__((__format__ (__strftime__, fmtarg, firstvararg))) -#endif -/* Compiler-dependent macros that rely on FreeBSD-specific extensions. */ -#if defined(__FreeBSD_cc_version) && __FreeBSD_cc_version >= 300001 && \ - defined(__GNUC__) +/* + * Like __printflike, but allows fmtarg to be NULL. FreeBSD invented 'printf0' + * for this because older versions of gcc issued warnings for NULL first args. + * Clang has always had printf and printf0 as aliases. gcc 11.0 now follows + * clang. So now this is an alias for __printflike, or nothing. In the future + * _Nullable or _Nonnull will replace this. + * XXX Except that doesn't work, so for now revert to printf0 for clang and + * the FreeBSD gcc until I can work this out. + */ +#if defined(__clang__) || (defined(__GNUC__) && defined (__FreeBSD_cc_version)) #define __printf0like(fmtarg, firstvararg) \ __attribute__((__format__ (__printf0__, fmtarg, firstvararg))) #else #define __printf0like(fmtarg, firstvararg) #endif -#if defined(__GNUC__) #define __strong_reference(sym,aliassym) \ extern __typeof (sym) aliassym __attribute__ ((__alias__ (#sym))) #ifdef __STDC__ @@ -531,10 +404,12 @@ __asm__(".section .gnu.warning." #sym); \ __asm__(".asciz \"" msg "\""); \ __asm__(".previous") +#ifdef __CC_SUPPORTS_SYMVER #define __sym_compat(sym,impl,verid) \ __asm__(".symver " #impl ", " #sym "@" #verid) #define __sym_default(sym,impl,verid) \ __asm__(".symver " #impl ", " #sym "@@@" #verid) +#endif #else #define __weak_reference(sym,alias) \ __asm__(".weak alias"); \ @@ -543,27 +418,18 @@ __asm__(".section .gnu.warning.sym"); \ __asm__(".asciz \"msg\""); \ __asm__(".previous") +#ifdef __CC_SUPPORTS_SYMVER #define __sym_compat(sym,impl,verid) \ __asm__(".symver impl, sym@verid") #define __sym_default(impl,sym,verid) \ __asm__(".symver impl, sym@@@verid") +#endif #endif /* __STDC__ */ -#endif /* __GNUC__ */ #define __GLOBL(sym) __asm__(".globl " __XSTRING(sym)) #define __WEAK(sym) __asm__(".weak " __XSTRING(sym)) -#if defined(__GNUC__) #define __IDSTRING(name,string) __asm__(".ident\t\"" string "\"") -#else -/* - * The following definition might not work well if used in header files, - * but it should be better than nothing. If you want a "do nothing" - * version, then it should generate some harmless declaration, such as: - * #define __IDSTRING(name,string) struct __hack - */ -#define __IDSTRING(name,string) static const char name[] __unused = string -#endif /* * Embed the rcs id of a source file in the resulting library. Note that in @@ -622,164 +488,13 @@ #define __DEQUALIFY(type, var) ((type)(__uintptr_t)(const volatile void *)(var)) #endif -/*- - * The following definitions are an extension of the behavior originally - * implemented in , but with a different level of granularity. - * POSIX.1 requires that the macros we test be defined before any standard - * header file is included. - * - * Here's a quick run-down of the versions (and some informal names) - * defined(_POSIX_SOURCE) 1003.1-1988 - * encoded as 198808 below - * _POSIX_C_SOURCE == 1 1003.1-1990 - * encoded as 199009 below - * _POSIX_C_SOURCE == 2 1003.2-1992 C Language Binding Option - * encoded as 199209 below - * _POSIX_C_SOURCE == 199309 1003.1b-1993 - * (1003.1 Issue 4, Single Unix Spec v1, Unix 93) - * _POSIX_C_SOURCE == 199506 1003.1c-1995, 1003.1i-1995, - * and the omnibus ISO/IEC 9945-1: 1996 - * (1003.1 Issue 5, Single Unix Spec v2, Unix 95) - * _POSIX_C_SOURCE == 200112 1003.1-2001 (1003.1 Issue 6, Unix 03) - * _POSIX_C_SOURCE == 200809 1003.1-2008 (1003.1 Issue 7) - * IEEE Std 1003.1-2017 (Rev of 1003.1-2008) is - * 1003.1-2008 with two TCs applied with - * _POSIX_C_SOURCE=200809 and _XOPEN_SOURCE=700 - * - * In addition, the X/Open Portability Guide, which is now the Single UNIX - * Specification, defines a feature-test macro which indicates the version of - * that specification, and which subsumes _POSIX_C_SOURCE. - * - * Our macros begin with two underscores to avoid namespace screwage. - */ - -/* Deal with IEEE Std. 1003.1-1990, in which _POSIX_C_SOURCE == 1. */ -#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE == 1 -#undef _POSIX_C_SOURCE /* Probably illegal, but beyond caring now. */ -#define _POSIX_C_SOURCE 199009 -#endif - -/* Deal with IEEE Std. 1003.2-1992, in which _POSIX_C_SOURCE == 2. */ -#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE == 2 -#undef _POSIX_C_SOURCE -#define _POSIX_C_SOURCE 199209 -#endif - -/* Deal with various X/Open Portability Guides and Single UNIX Spec. */ -#ifdef _XOPEN_SOURCE -#if _XOPEN_SOURCE - 0 >= 700 -#define __XSI_VISIBLE 700 -#undef _POSIX_C_SOURCE -#define _POSIX_C_SOURCE 200809 -#elif _XOPEN_SOURCE - 0 >= 600 -#define __XSI_VISIBLE 600 -#undef _POSIX_C_SOURCE -#define _POSIX_C_SOURCE 200112 -#elif _XOPEN_SOURCE - 0 >= 500 -#define __XSI_VISIBLE 500 -#undef _POSIX_C_SOURCE -#define _POSIX_C_SOURCE 199506 -#endif +#if !defined(_STANDALONE) && !defined(_KERNEL) +#define __RENAME(x) __asm(__STRING(x)) +#else /* _STANDALONE || _KERNEL */ +#define __RENAME(x) no renaming in kernel/standalone environment #endif -/* - * Deal with all versions of POSIX. The ordering relative to the tests above is - * important. - */ -#if defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) -#define _POSIX_C_SOURCE 198808 -#endif -#ifdef _POSIX_C_SOURCE -#if _POSIX_C_SOURCE >= 200809 -#define __POSIX_VISIBLE 200809 -#define __ISO_C_VISIBLE 1999 -#elif _POSIX_C_SOURCE >= 200112 -#define __POSIX_VISIBLE 200112 -#define __ISO_C_VISIBLE 1999 -#elif _POSIX_C_SOURCE >= 199506 -#define __POSIX_VISIBLE 199506 -#define __ISO_C_VISIBLE 1990 -#elif _POSIX_C_SOURCE >= 199309 -#define __POSIX_VISIBLE 199309 -#define __ISO_C_VISIBLE 1990 -#elif _POSIX_C_SOURCE >= 199209 -#define __POSIX_VISIBLE 199209 -#define __ISO_C_VISIBLE 1990 -#elif _POSIX_C_SOURCE >= 199009 -#define __POSIX_VISIBLE 199009 -#define __ISO_C_VISIBLE 1990 -#else -#define __POSIX_VISIBLE 198808 -#define __ISO_C_VISIBLE 0 -#endif /* _POSIX_C_SOURCE */ -/* - * Both glibc and OpenBSD enable c11 features when _ISOC11_SOURCE is defined, or - * when compiling with -stdc=c11. A strict reading of the standard would suggest - * doing it only for the former. However, a strict reading also requires C99 - * mode only, so building with C11 is already undefined. Follow glibc's and - * OpenBSD's lead for this non-standard configuration for maximum compatibility. - */ -#if _ISOC11_SOURCE || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) -#undef __ISO_C_VISIBLE -#define __ISO_C_VISIBLE 2011 -#endif -#else -/*- - * Deal with _ANSI_SOURCE: - * If it is defined, and no other compilation environment is explicitly - * requested, then define our internal feature-test macros to zero. This - * makes no difference to the preprocessor (undefined symbols in preprocessing - * expressions are defined to have value zero), but makes it more convenient for - * a test program to print out the values. - * - * If a program mistakenly defines _ANSI_SOURCE and some other macro such as - * _POSIX_C_SOURCE, we will assume that it wants the broader compilation - * environment (and in fact we will never get here). - */ -#if defined(_ANSI_SOURCE) /* Hide almost everything. */ -#define __POSIX_VISIBLE 0 -#define __XSI_VISIBLE 0 -#define __BSD_VISIBLE 0 -#define __ISO_C_VISIBLE 1990 -#define __EXT1_VISIBLE 0 -#elif defined(_C99_SOURCE) /* Localism to specify strict C99 env. */ -#define __POSIX_VISIBLE 0 -#define __XSI_VISIBLE 0 -#define __BSD_VISIBLE 0 -#define __ISO_C_VISIBLE 1999 -#define __EXT1_VISIBLE 0 -#elif defined(_C11_SOURCE) /* Localism to specify strict C11 env. */ -#define __POSIX_VISIBLE 0 -#define __XSI_VISIBLE 0 -#define __BSD_VISIBLE 0 -#define __ISO_C_VISIBLE 2011 -#define __EXT1_VISIBLE 0 -#else /* Default environment: show everything. */ -#define __POSIX_VISIBLE 200809 -#define __XSI_VISIBLE 700 -#define __BSD_VISIBLE 1 -#define __ISO_C_VISIBLE 2011 -#define __EXT1_VISIBLE 1 -#endif -#endif - -/* User override __EXT1_VISIBLE */ -#if defined(__STDC_WANT_LIB_EXT1__) -#undef __EXT1_VISIBLE -#if __STDC_WANT_LIB_EXT1__ -#define __EXT1_VISIBLE 1 -#else -#define __EXT1_VISIBLE 0 -#endif -#endif /* __STDC_WANT_LIB_EXT1__ */ - -/* - * Old versions of GCC use non-standard ARM arch symbols; acle-compat.h - * translates them to __ARM_ARCH and the modern feature symbols defined by ARM. - */ -#if defined(__arm__) && !defined(__ARM_ARCH) -#include -#endif +#include /* * Nullability qualifiers: currently only supported by Clang. diff --git a/lib/libc/include/generic-freebsd/sys/cnv.h b/lib/libc/include/generic-freebsd/sys/cnv.h index 848ba6aee0b8..ec506bc758d0 100644 --- a/lib/libc/include/generic-freebsd/sys/cnv.h +++ b/lib/libc/include/generic-freebsd/sys/cnv.h @@ -30,6 +30,7 @@ #define _CNV_H_ #include +#include #ifndef _KERNEL #include @@ -39,13 +40,6 @@ #include #endif -#ifndef _NVLIST_T_DECLARED -#define _NVLIST_T_DECLARED -struct nvlist; - -typedef struct nvlist nvlist_t; -#endif - __BEGIN_DECLS /* diff --git a/lib/libc/include/generic-freebsd/sys/compressor.h b/lib/libc/include/generic-freebsd/sys/compressor.h index 6055be709521..3672d644fca1 100644 --- a/lib/libc/include/generic-freebsd/sys/compressor.h +++ b/lib/libc/include/generic-freebsd/sys/compressor.h @@ -42,6 +42,7 @@ struct compressor; bool compressor_avail(int format); struct compressor *compressor_init(compressor_cb_t cb, int format, size_t maxiosize, int level, void *arg); +int compressor_format(const struct compressor *stream); void compressor_reset(struct compressor *stream); int compressor_write(struct compressor *stream, void *data, size_t len); diff --git a/lib/libc/include/generic-freebsd/sys/conf.h b/lib/libc/include/generic-freebsd/sys/conf.h index 6b5d407e6d1c..419b8ea2cec5 100644 --- a/lib/libc/include/generic-freebsd/sys/conf.h +++ b/lib/libc/include/generic-freebsd/sys/conf.h @@ -34,8 +34,6 @@ * 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. - * - * @(#)conf.h 8.5 (Berkeley) 1/9/95 */ #ifndef _SYS_CONF_H_ @@ -46,6 +44,7 @@ #else #include #endif +#include struct snapdata; struct devfs_dirent; @@ -160,6 +159,7 @@ typedef int dumper_hdr_t(struct dumperinfo *di, struct kerneldumpheader *kdh); #define GID_RT_PRIO 47 #define GID_ID_PRIO 48 #define GID_DIALER 68 +#define GID_U2F 116 #define GID_NOGROUP 65533 #define GID_NOBODY 65534 @@ -278,6 +278,7 @@ void destroy_dev(struct cdev *_dev); int destroy_dev_sched(struct cdev *dev); int destroy_dev_sched_cb(struct cdev *dev, void (*cb)(void *), void *arg); void destroy_dev_drain(struct cdevsw *csw); +void dev_copyname(struct cdev *dev, char *path, size_t len); struct cdevsw *dev_refthread(struct cdev *_dev, int *_ref); struct cdevsw *devvn_refthread(struct vnode *vp, struct cdev **devp, int *_ref); void dev_relthread(struct cdev *_dev, int _ref); @@ -360,6 +361,7 @@ struct dumperinfo { }; extern int dumping; /* system is dumping */ +extern bool dumped_core; /* system successfully dumped kernel core */ /* * Save registers for later extraction from a kernel dump. diff --git a/lib/libc/include/generic-freebsd/sys/cons.h b/lib/libc/include/generic-freebsd/sys/cons.h index 0f9e15cb6c25..a6f81371c9ee 100644 --- a/lib/libc/include/generic-freebsd/sys/cons.h +++ b/lib/libc/include/generic-freebsd/sys/cons.h @@ -32,8 +32,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)cons.h 7.2 (Berkeley) 5/9/91 */ #ifndef _MACHINE_CONS_H_ @@ -96,6 +94,8 @@ struct consdev { #ifdef _KERNEL +extern int cn_mute; + extern struct msgbuf consmsgbuf; /* Message buffer for constty. */ extern struct tty *constty; /* Temporary virtual console. */ diff --git a/lib/libc/include/generic-freebsd/sys/copyright.h b/lib/libc/include/generic-freebsd/sys/copyright.h index e6fad408baa1..024b0417564f 100644 --- a/lib/libc/include/generic-freebsd/sys/copyright.h +++ b/lib/libc/include/generic-freebsd/sys/copyright.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (C) 1992-2023 The FreeBSD Project. All rights reserved. + * Copyright (C) 1992-2025 The FreeBSD Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,7 +35,7 @@ /* FreeBSD */ #define COPYRIGHT_FreeBSD \ - "Copyright (c) 1992-2023 The FreeBSD Project.\n" + "Copyright (c) 1992-2025 The FreeBSD Project.\n" /* Foundation */ #define TRADEMARK_Foundation \ diff --git a/lib/libc/include/generic-freebsd/sys/counter.h b/lib/libc/include/generic-freebsd/sys/counter.h index 12521036a2f0..9fa5f85bf637 100644 --- a/lib/libc/include/generic-freebsd/sys/counter.h +++ b/lib/libc/include/generic-freebsd/sys/counter.h @@ -60,17 +60,12 @@ uint64_t counter_u64_fetch(counter_u64_t); counter_u64_zero((a)[_i]); \ } while (0) -/* - * counter(9) based rate checking. - */ -struct counter_rate { - counter_u64_t cr_rate; /* Events since last second */ - volatile int cr_lock; /* Lock to clean the struct */ - int cr_ticks; /* Ticks on last clean */ - int cr_over; /* Over limit since cr_ticks? */ -}; +struct counter_rate; +struct counter_rate *counter_rate_alloc(int flags, int period); +void counter_rate_free(struct counter_rate *); int64_t counter_ratecheck(struct counter_rate *, int64_t); +uint64_t counter_rate_get(struct counter_rate *); #define COUNTER_U64_SYSINIT(c) \ SYSINIT(c##_counter_sysinit, SI_SUB_COUNTER, \ diff --git a/lib/libc/include/generic-freebsd/sys/cpuset.h b/lib/libc/include/generic-freebsd/sys/cpuset.h index d78fe502679e..f91e224ac567 100644 --- a/lib/libc/include/generic-freebsd/sys/cpuset.h +++ b/lib/libc/include/generic-freebsd/sys/cpuset.h @@ -61,8 +61,10 @@ #define CPU_ANDNOT(d, s1, s2) __BIT_ANDNOT2(CPU_SETSIZE, d, s1, s2) #define CPU_XOR(d, s1, s2) __BIT_XOR2(CPU_SETSIZE, d, s1, s2) #define CPU_CLR_ATOMIC(n, p) __BIT_CLR_ATOMIC(CPU_SETSIZE, n, p) +#define CPU_TEST_CLR_ATOMIC(n, p) __BIT_TEST_CLR_ATOMIC(CPU_SETSIZE, n, p) #define CPU_SET_ATOMIC(n, p) __BIT_SET_ATOMIC(CPU_SETSIZE, n, p) #define CPU_SET_ATOMIC_ACQ(n, p) __BIT_SET_ATOMIC_ACQ(CPU_SETSIZE, n, p) +#define CPU_TEST_SET_ATOMIC(n, p) __BIT_TEST_SET_ATOMIC(CPU_SETSIZE, n, p) #define CPU_AND_ATOMIC(n, p) __BIT_AND_ATOMIC(CPU_SETSIZE, n, p) #define CPU_OR_ATOMIC(d, s) __BIT_OR_ATOMIC(CPU_SETSIZE, d, s) #define CPU_COPY_STORE_REL(f, t) __BIT_COPY_STORE_REL(CPU_SETSIZE, f, t) diff --git a/lib/libc/include/generic-freebsd/sys/devicestat.h b/lib/libc/include/generic-freebsd/sys/devicestat.h index 6800b78a2786..3432e2e07840 100644 --- a/lib/libc/include/generic-freebsd/sys/devicestat.h +++ b/lib/libc/include/generic-freebsd/sys/devicestat.h @@ -125,6 +125,7 @@ typedef enum { DEVSTAT_TYPE_IF_SCSI = 0x010, DEVSTAT_TYPE_IF_IDE = 0x020, DEVSTAT_TYPE_IF_OTHER = 0x030, + DEVSTAT_TYPE_IF_NVME = 0x040, DEVSTAT_TYPE_IF_MASK = 0x0f0, DEVSTAT_TYPE_PASS = 0x100 } devstat_type_flags; diff --git a/lib/libc/include/generic-freebsd/sys/devmap.h b/lib/libc/include/generic-freebsd/sys/devmap.h index 16352124de49..e8c59b9e2b74 100644 --- a/lib/libc/include/generic-freebsd/sys/devmap.h +++ b/lib/libc/include/generic-freebsd/sys/devmap.h @@ -33,6 +33,7 @@ #error "no user-serviceable parts inside" #endif +#ifdef __HAVE_STATIC_DEVMAP /* * This structure is used by MD code to describe static mappings of devices * which are established as part of bringing up the MMU early in the boot. @@ -71,27 +72,13 @@ void devmap_register_table(const struct devmap_entry * _table); * Establish mappings for all the entries in the table. This is called * automatically from the common platform-specific init function in * /machdep.c, and also from the custom platform-specific init routines - * in older code. If the table pointer is NULL, this will use the table - * installed previously by devmap_register_table(). + * in older code. This function only has an effect when a table was installed + * previously by devmap_register_table(). */ -void devmap_bootstrap(vm_offset_t _l1pt, - const struct devmap_entry *_table); - -/* - * Translate between virtual and physical addresses within a region that is - * static-mapped by the devmap code. If the given address range isn't - * static-mapped, then ptov returns NULL and vtop returns DEVMAP_PADDR_NOTFOUND. - * The latter implies that you can't vtop just the last byte of physical address - * space. This is not as limiting as it might sound, because even if a device - * occupies the end of the physical address space, you're only prevented from - * doing vtop for that single byte. If you vtop a size bigger than 1 it works. - */ -#define DEVMAP_PADDR_NOTFOUND ((vm_paddr_t)(-1)) - -void * devmap_ptov(vm_paddr_t _pa, vm_size_t _sz); -vm_paddr_t devmap_vtop(void * _va, vm_size_t _sz); +void devmap_bootstrap(void); /* Print the static mapping table; used for bootverbose output. */ void devmap_print_table(void); +#endif #endif /* !_SYS_DEVMAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/dirent.h b/lib/libc/include/generic-freebsd/sys/dirent.h index 17bf89cf8554..036b5f802b5b 100644 --- a/lib/libc/include/generic-freebsd/sys/dirent.h +++ b/lib/libc/include/generic-freebsd/sys/dirent.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)dirent.h 8.3 (Berkeley) 8/10/94 */ #ifndef _SYS_DIRENT_H_ diff --git a/lib/libc/include/generic-freebsd/sys/disk.h b/lib/libc/include/generic-freebsd/sys/disk.h index 2a129d2d5b4e..e6f1fd5d1d23 100644 --- a/lib/libc/include/generic-freebsd/sys/disk.h +++ b/lib/libc/include/generic-freebsd/sys/disk.h @@ -78,7 +78,7 @@ void disk_err(struct bio *bp, const char *what, int blkdone, int nl); * only if they point at exactly the same physical storage, this is * the case for multipathing for example, * - GEOM classes that consumes single providers and provide single - * providers, like geli, gbde, should just attach class name to the + * providers, like geli, should just attach class name to the * ident of the underlying provider, * - ident is an ASCII string (is printable), * - ident is optional and applications can't relay on its presence. diff --git a/lib/libc/include/generic-freebsd/sys/disk/bsd.h b/lib/libc/include/generic-freebsd/sys/disk/bsd.h index 13261bee65ae..6bb186b35e88 100644 --- a/lib/libc/include/generic-freebsd/sys/disk/bsd.h +++ b/lib/libc/include/generic-freebsd/sys/disk/bsd.h @@ -25,8 +25,6 @@ * 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. - * - * @(#)disklabel.h 8.2 (Berkeley) 7/10/94 */ #ifndef _SYS_DISK_BSD_H_ diff --git a/lib/libc/include/generic-freebsd/sys/disk/gpt.h b/lib/libc/include/generic-freebsd/sys/disk/gpt.h index a11256e08cf2..ae886b1a789e 100644 --- a/lib/libc/include/generic-freebsd/sys/disk/gpt.h +++ b/lib/libc/include/generic-freebsd/sys/disk/gpt.h @@ -259,6 +259,9 @@ CTASSERT(sizeof(struct gpt_ent) == 128); #define GPT_ENT_TYPE_HIFIVE_BBL \ {0x2e54b353,0x1271,0x4842,0x80,0x6f,{0xe4,0x36,0xd6,0xaf,0x69,0x85}} +#define GPT_ENT_TYPE_U_BOOT_ENV \ + {0x3de21764,0x95bd,0x54bd,0xa5,0xc3,{0x4a,0xbe,0x78,0x6f,0x38,0xa8}} + /* * Boot partition used by GRUB 2. */ diff --git a/lib/libc/include/generic-freebsd/sys/disk/mbr.h b/lib/libc/include/generic-freebsd/sys/disk/mbr.h index a2ba2262c9f4..735744eaba90 100644 --- a/lib/libc/include/generic-freebsd/sys/disk/mbr.h +++ b/lib/libc/include/generic-freebsd/sys/disk/mbr.h @@ -25,8 +25,6 @@ * 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. - * - * @(#)disklabel.h 8.2 (Berkeley) 7/10/94 */ #ifndef _SYS_DISK_MBR_H_ diff --git a/lib/libc/include/generic-freebsd/sys/disklabel.h b/lib/libc/include/generic-freebsd/sys/disklabel.h index 0a0917975ca8..72a9c7334f00 100644 --- a/lib/libc/include/generic-freebsd/sys/disklabel.h +++ b/lib/libc/include/generic-freebsd/sys/disklabel.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)disklabel.h 8.2 (Berkeley) 7/10/94 */ #ifndef _SYS_DISKLABEL_H_ diff --git a/lib/libc/include/generic-freebsd/sys/diskmbr.h b/lib/libc/include/generic-freebsd/sys/diskmbr.h index 770ee2ef3c94..37e25bf83c8e 100644 --- a/lib/libc/include/generic-freebsd/sys/diskmbr.h +++ b/lib/libc/include/generic-freebsd/sys/diskmbr.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)disklabel.h 8.2 (Berkeley) 7/10/94 */ #ifndef _SYS_DISKMBR_H_ diff --git a/lib/libc/include/generic-freebsd/sys/dkstat.h b/lib/libc/include/generic-freebsd/sys/dkstat.h index 502de1a66c12..2a494e5c517d 100644 --- a/lib/libc/include/generic-freebsd/sys/dkstat.h +++ b/lib/libc/include/generic-freebsd/sys/dkstat.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)dkstat.h 8.2 (Berkeley) 1/21/94 */ #ifndef _SYS_DKSTAT_H_ diff --git a/lib/libc/include/generic-freebsd/sys/dnv.h b/lib/libc/include/generic-freebsd/sys/dnv.h index 07541306e103..4b40f9b8d4c8 100644 --- a/lib/libc/include/generic-freebsd/sys/dnv.h +++ b/lib/libc/include/generic-freebsd/sys/dnv.h @@ -32,6 +32,7 @@ #define _DNV_H_ #include +#include #ifndef _KERNEL #include @@ -41,13 +42,6 @@ #include #endif -#ifndef _NVLIST_T_DECLARED -#define _NVLIST_T_DECLARED -struct nvlist; - -typedef struct nvlist nvlist_t; -#endif - __BEGIN_DECLS /* diff --git a/lib/libc/include/generic-freebsd/sys/domain.h b/lib/libc/include/generic-freebsd/sys/domain.h index e9e15b91c65f..e1ef0ba3ccbf 100644 --- a/lib/libc/include/generic-freebsd/sys/domain.h +++ b/lib/libc/include/generic-freebsd/sys/domain.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)domain.h 8.1 (Berkeley) 6/2/93 */ #ifndef _SYS_DOMAIN_H_ @@ -54,10 +52,6 @@ struct domain { char *dom_name; int dom_flags; int (*dom_probe)(void); /* check for support (optional) */ - int (*dom_externalize) /* externalize access rights */ - (struct mbuf *, struct mbuf **, int); - void (*dom_dispose) /* dispose of internalized rights */ - (struct socket *); struct rib_head *(*dom_rtattach) /* initialize routing table */ (uint32_t); void (*dom_rtdetach) /* clean up routing table */ diff --git a/lib/libc/include/generic-freebsd/sys/domainset.h b/lib/libc/include/generic-freebsd/sys/domainset.h index 71ba4310e92d..24675195c190 100644 --- a/lib/libc/include/generic-freebsd/sys/domainset.h +++ b/lib/libc/include/generic-freebsd/sys/domainset.h @@ -113,6 +113,20 @@ void domainset_zero(void); * returned value will not match the key pointer. */ struct domainset *domainset_create(const struct domainset *); + +/* + * Remove empty domains from a given domainset. + * Returns 'false' if the domainset consists entirely of empty domains. + */ +bool domainset_empty_vm(struct domainset *domain); + +/* + * Validate and populate a domainset structure according to the specified + * policy and mask. + */ +int domainset_populate(struct domainset *domain, const domainset_t *mask, int policy, + size_t mask_size); + #ifdef _SYS_SYSCTL_H_ int sysctl_handle_domainset(SYSCTL_HANDLER_ARGS); #endif diff --git a/lib/libc/include/generic-freebsd/sys/efi.h b/lib/libc/include/generic-freebsd/sys/efi.h index 6f2f327f5273..33b6cb28f994 100644 --- a/lib/libc/include/generic-freebsd/sys/efi.h +++ b/lib/libc/include/generic-freebsd/sys/efi.h @@ -35,15 +35,17 @@ #define EFI_PAGE_MASK (EFI_PAGE_SIZE - 1) #define EFI_TABLE_SMBIOS \ - {0xeb9d2d31,0x2d88,0x11d3,0x9a,0x16,{0x00,0x90,0x27,0x3f,0xc1,0x4d}} + {0xeb9d2d31,0x2d88,0x11d3,{0x9a,0x16,0x00,0x90,0x27,0x3f,0xc1,0x4d}} #define EFI_TABLE_SMBIOS3 \ - {0xf2fd1544,0x9794,0x4a2c,0x99,0x2e,{0xe5,0xbb,0xcf,0x20,0xe3,0x94}} + {0xf2fd1544,0x9794,0x4a2c,{0x99,0x2e,0xe5,0xbb,0xcf,0x20,0xe3,0x94}} #define EFI_TABLE_ESRT \ - {0xb122a263,0x3661,0x4f68,0x99,0x29,{0x78,0xf8,0xb0,0xd6,0x21,0x80}} + {0xb122a263,0x3661,0x4f68,{0x99,0x29,0x78,0xf8,0xb0,0xd6,0x21,0x80}} #define EFI_PROPERTIES_TABLE \ - {0x880aaca3,0x4adc,0x4a04,0x90,0x79,{0xb7,0x47,0x34,0x08,0x25,0xe5}} + {0x880aaca3,0x4adc,0x4a04,{0x90,0x79,0xb7,0x47,0x34,0x08,0x25,0xe5}} +#define EFI_MEMORY_ATTRIBUTES_TABLE \ + {0xdcfa911d,0x26eb,0x469f,{0xa2,0x20,0x38,0xb7,0xdc,0x46,0x12,0x20}} #define LINUX_EFI_MEMRESERVE_TABLE \ - {0x888eb0c6,0x8ede,0x4ff5,0xa8,0xf0,{0x9a,0xee,0x5c,0xb9,0x77,0xc2}} + {0x888eb0c6,0x8ede,0x4ff5,{0xa8,0xf0,0x9a,0xee,0x5c,0xb9,0x77,0xc2}} enum efi_reset { EFI_RESET_COLD = 0, @@ -54,8 +56,20 @@ enum efi_reset { typedef uint16_t efi_char; typedef unsigned long efi_status; +/* + * This type-puns to a struct uuid, but all the EDK2 headers use this variation, + * and we use it in the loader to specify GUIDs. We define it here so that we + * can use EDK2 definitions both places. + */ +typedef struct efi_guid { + uint32_t Data1; + uint16_t Data2; + uint16_t Data3; + uint8_t Data4[8]; +} efi_guid_t; /* Type puns with GUID and EFI_GUID */ + struct efi_cfgtbl { - struct uuid ct_uuid; + efi_guid_t ct_guid; void *ct_data; }; @@ -139,7 +153,7 @@ struct efi_esrt_table { }; struct efi_esrt_entry_v1 { - struct uuid fw_class; + efi_guid_t fw_class; uint32_t fw_type; uint32_t fw_version; uint32_t lowest_supported_fw_version; @@ -154,6 +168,22 @@ struct efi_prop_table { uint64_t memory_protection_attribute; }; +struct efi_memory_descriptor { + uint32_t type; + caddr_t phy_addr; + caddr_t virt_addr; + uint64_t pages; + uint64_t attrs; +}; + +struct efi_memory_attribute_table { + uint32_t version; + uint32_t num_ents; + uint32_t descriptor_size; + uint32_t flags; + struct efi_memory_descriptor tables[]; +}; + #ifdef _KERNEL #ifdef EFIABI_ATTR @@ -169,11 +199,11 @@ struct efi_rt { efi_status (*rt_setvirtual)(u_long, u_long, uint32_t, struct efi_md *) EFIABI_ATTR; efi_status (*rt_cvtptr)(u_long, void **) EFIABI_ATTR; - efi_status (*rt_getvar)(efi_char *, struct uuid *, uint32_t *, + efi_status (*rt_getvar)(efi_char *, efi_guid_t *, uint32_t *, u_long *, void *) EFIABI_ATTR; - efi_status (*rt_scanvar)(u_long *, efi_char *, struct uuid *) + efi_status (*rt_scanvar)(u_long *, efi_char *, efi_guid_t *) EFIABI_ATTR; - efi_status (*rt_setvar)(efi_char *, struct uuid *, uint32_t, + efi_status (*rt_setvar)(efi_char *, efi_guid_t *, uint32_t, u_long, void *) EFIABI_ATTR; efi_status (*rt_gethicnt)(uint32_t *) EFIABI_ATTR; efi_status (*rt_reset)(enum efi_reset, efi_status, u_long, @@ -246,8 +276,8 @@ struct efi_ops { * access them. */ int (*rt_ok)(void); - int (*get_table)(struct uuid *, void **); - int (*copy_table)(struct uuid *, void **, size_t, size_t *); + int (*get_table)(efi_guid_t *, void **); + int (*copy_table)(efi_guid_t *, void **, size_t, size_t *); int (*get_time)(struct efi_tm *); int (*get_time_capabilities)(struct efi_tmcap *); int (*reset_system)(enum efi_reset); @@ -255,10 +285,10 @@ struct efi_ops { int (*get_waketime)(uint8_t *enabled, uint8_t *pending, struct efi_tm *tm); int (*set_waketime)(uint8_t enable, struct efi_tm *tm); - int (*var_get)(uint16_t *, struct uuid *, uint32_t *, size_t *, + int (*var_get)(uint16_t *, efi_guid_t *, uint32_t *, size_t *, void *); - int (*var_nextname)(size_t *, uint16_t *, struct uuid *); - int (*var_set)(uint16_t *, struct uuid *, uint32_t, size_t, void *); + int (*var_nextname)(size_t *, uint16_t *, efi_guid_t *); + int (*var_set)(uint16_t *, efi_guid_t *, uint32_t, size_t, void *); }; extern const struct efi_ops *active_efi_ops; @@ -271,21 +301,21 @@ static inline int efi_rt_ok(void) return (active_efi_ops->rt_ok()); } -static inline int efi_get_table(struct uuid *uuid, void **ptr) +static inline int efi_get_table(efi_guid_t *guid, void **ptr) { if (active_efi_ops->get_table == NULL) return (ENXIO); - return (active_efi_ops->get_table(uuid, ptr)); + return (active_efi_ops->get_table(guid, ptr)); } -static inline int efi_copy_table(struct uuid *uuid, void **buf, +static inline int efi_copy_table(efi_guid_t *guid, void **buf, size_t buf_len, size_t *table_len) { if (active_efi_ops->copy_table == NULL) return (ENXIO); - return (active_efi_ops->copy_table(uuid, buf, buf_len, table_len)); + return (active_efi_ops->copy_table(guid, buf, buf_len, table_len)); } static inline int efi_get_time(struct efi_tm *tm) @@ -335,7 +365,7 @@ static inline int efi_set_waketime(uint8_t enable, struct efi_tm *tm) return (active_efi_ops->set_waketime(enable, tm)); } -static inline int efi_var_get(uint16_t *name, struct uuid *vendor, +static inline int efi_var_get(uint16_t *name, efi_guid_t *vendor, uint32_t *attrib, size_t *datasize, void *data) { @@ -345,7 +375,7 @@ static inline int efi_var_get(uint16_t *name, struct uuid *vendor, } static inline int efi_var_nextname(size_t *namesize, uint16_t *name, - struct uuid *vendor) + efi_guid_t *vendor) { if (active_efi_ops->var_nextname == NULL) @@ -353,7 +383,7 @@ static inline int efi_var_nextname(size_t *namesize, uint16_t *name, return (active_efi_ops->var_nextname(namesize, name, vendor)); } -static inline int efi_var_set(uint16_t *name, struct uuid *vendor, +static inline int efi_var_set(uint16_t *name, efi_guid_t *vendor, uint32_t attrib, size_t datasize, void *data) { diff --git a/lib/libc/include/generic-freebsd/sys/efi_map.h b/lib/libc/include/generic-freebsd/sys/efi_map.h new file mode 100644 index 000000000000..aec3b697a1bb --- /dev/null +++ b/lib/libc/include/generic-freebsd/sys/efi_map.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2014 The FreeBSD Foundation + * Copyright (c) 2018 Andrew Turner + * + * SPDX-License-Identifier: BSD-2-Clause + */ +#ifndef _SYS_EFI_MAP_H_ +#define _SYS_EFI_MAP_H_ + +#include +#include + +struct efi_map_header; + +typedef void (*efi_map_entry_cb)(struct efi_md *, void *argp); + +void efi_map_foreach_entry(struct efi_map_header *efihdr, efi_map_entry_cb cb, + void *argp); + +void efi_map_add_entries(struct efi_map_header *efihdr); +void efi_map_exclude_entries(struct efi_map_header *efihdr); +void efi_map_print_entries(struct efi_map_header *efihdr); + +#endif /* !_SYS_EFI_MAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/efiio.h b/lib/libc/include/generic-freebsd/sys/efiio.h index 5790238c84df..474827ee12a3 100644 --- a/lib/libc/include/generic-freebsd/sys/efiio.h +++ b/lib/libc/include/generic-freebsd/sys/efiio.h @@ -30,38 +30,79 @@ #include #include -struct efi_get_table_ioc +/* + * The EFI world chose not to use the typical uuid_t defines for its global + * universal identifiers. But the textual representation is the same, and we can + * use the uuid_* routines to parse and print them. However, all EFI interfaces + * for this need to be efi_guid_t so we can share code with EDK2, so the *_ioc + * structures in this file are converted to _ioctl structure to transition to + * this new requirement. This library is little used outside of FreeBSD and they + * will be dropped in 16. + */ +_Static_assert(sizeof(struct uuid) == sizeof(efi_guid_t), + "uuid_t and efi_guid_t are same bytes, but different elements"); +#if __FreeBSD_version < 1600000 && !defined(_KERNEL) +#define _WANT_EFI_IOC +#endif + +struct efi_get_table_ioctl { void *buf; /* Pointer to userspace buffer */ - struct uuid uuid; /* UUID to look up */ + efi_guid_t guid; /* GUID to look up */ size_t table_len; /* Table size */ size_t buf_len; /* Size of the buffer */ }; -struct efi_var_ioc +struct efi_var_ioctl { efi_char *name; /* User pointer to name, in wide chars */ size_t namesize; /* Number of wide characters in name */ - struct uuid vendor; /* Vendor's UUID for variable */ + efi_guid_t vendor; /* Vendor's GUID for variable */ uint32_t attrib; /* Attributes */ void *data; /* User pointer to the data */ size_t datasize; /* Number of *bytes* in the data */ }; -struct efi_waketime_ioc +struct efi_waketime_ioctl { struct efi_tm waketime; uint8_t enabled; uint8_t pending; }; -#define EFIIOC_GET_TABLE _IOWR('E', 1, struct efi_get_table_ioc) +#define EFIIOC_GET_TABLE _IOWR('E', 1, struct efi_get_table_ioctl) #define EFIIOC_GET_TIME _IOR('E', 2, struct efi_tm) #define EFIIOC_SET_TIME _IOW('E', 3, struct efi_tm) -#define EFIIOC_VAR_GET _IOWR('E', 4, struct efi_var_ioc) -#define EFIIOC_VAR_NEXT _IOWR('E', 5, struct efi_var_ioc) -#define EFIIOC_VAR_SET _IOWR('E', 6, struct efi_var_ioc) -#define EFIIOC_GET_WAKETIME _IOR('E', 7, struct efi_waketime_ioc) -#define EFIIOC_SET_WAKETIME _IOW('E', 8, struct efi_waketime_ioc) +#define EFIIOC_VAR_GET _IOWR('E', 4, struct efi_var_ioctl) +#define EFIIOC_VAR_NEXT _IOWR('E', 5, struct efi_var_ioctl) +#define EFIIOC_VAR_SET _IOWR('E', 6, struct efi_var_ioctl) +#define EFIIOC_GET_WAKETIME _IOR('E', 7, struct efi_waketime_ioctl) +#define EFIIOC_SET_WAKETIME _IOW('E', 8, struct efi_waketime_ioctl) + +#ifdef _WANT_EFI_IOC +struct efi_get_table_ioc +{ + void *buf; /* Pointer to userspace buffer */ + struct uuid uuid; /* GUID to look up */ + size_t table_len; /* Table size */ + size_t buf_len; /* Size of the buffer */ +}; + +struct efi_var_ioc +{ + efi_char *name; /* User pointer to name, in wide chars */ + size_t namesize; /* Number of wide characters in name */ + struct uuid vendor; /* Vendor's GUID for variable */ + uint32_t attrib; /* Attributes */ + void *data; /* User pointer to the data */ + size_t datasize; /* Number of *bytes* in the data */ +}; + +_Static_assert(sizeof(struct efi_get_table_ioc) == sizeof(struct efi_get_table_ioctl), + "Old and new struct table defines must be the same size"); +_Static_assert(sizeof(struct efi_var_ioc) == sizeof(struct efi_var_ioctl), + "Old and new struct var defines must be the same size"); +#define efi_waketime_ioc efi_waketime_ioctl +#endif #endif /* _SYS_EFIIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/elf_common.h b/lib/libc/include/generic-freebsd/sys/elf_common.h index 272ecf80ff32..0583ea2b8025 100644 --- a/lib/libc/include/generic-freebsd/sys/elf_common.h +++ b/lib/libc/include/generic-freebsd/sys/elf_common.h @@ -306,6 +306,7 @@ typedef struct { and MPRC of Peking University */ #define EM_AARCH64 183 /* AArch64 (64-bit ARM) */ #define EM_RISCV 243 /* RISC-V */ +#define EM_LOONGARCH 258 /* Loongson LoongArch */ /* Non-standard or deprecated. */ #define EM_486 6 /* Intel i486. */ @@ -382,6 +383,25 @@ typedef struct { #define EF_RISCV_RVE 0x00000008 #define EF_RISCV_TSO 0x00000010 +/* + * Loongson LoongArch Specific e_flags + * + * Definitions from LoongArch ELF psABI v2.01. + * Reference: https://github.com/loongson/LoongArch-Documentation + * (commit hash 296de4def055c871809068e0816325a4ac04eb12) + */ + +/* LoongArch Base ABI Modifiers */ +#define EF_LOONGARCH_ABI_SOFT_FLOAT 0x00000001 +#define EF_LOONGARCH_ABI_SINGLE_FLOAT 0x00000002 +#define EF_LOONGARCH_ABI_DOUBLE_FLOAT 0x00000003 +#define EF_LOONGARCH_ABI_MODIFIER_MASK 0x00000007 + +/* LoongArch Object file ABI versions */ +#define EF_LOONGARCH_OBJABI_V0 0x00000000 +#define EF_LOONGARCH_OBJABI_V1 0x00000040 +#define EF_LOONGARCH_OBJABI_MASK 0x000000C0 + #define EF_SPARC_EXT_MASK 0x00ffff00 #define EF_SPARC_32PLUS 0x00000100 #define EF_SPARC_SUN_US1 0x00000200 @@ -450,12 +470,12 @@ typedef struct { #define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */ #define SHT_LOPROC 0x70000000 /* reserved range for processor */ #define SHT_X86_64_UNWIND 0x70000001 /* unwind information */ -#define SHT_AMD64_UNWIND SHT_X86_64_UNWIND +#define SHT_AMD64_UNWIND SHT_X86_64_UNWIND #define SHT_ARM_EXIDX 0x70000001 /* Exception index table. */ -#define SHT_ARM_PREEMPTMAP 0x70000002 /* BPABI DLL dynamic linking +#define SHT_ARM_PREEMPTMAP 0x70000002 /* BPABI DLL dynamic linking pre-emption map. */ -#define SHT_ARM_ATTRIBUTES 0x70000003 /* Object file compatibility +#define SHT_ARM_ATTRIBUTES 0x70000003 /* Object file compatibility attributes. */ #define SHT_ARM_DEBUGOVERLAY 0x70000004 /* See DBGOVL for details. */ #define SHT_ARM_OVERLAYSECTION 0x70000005 /* See DBGOVL for details. */ @@ -534,8 +554,8 @@ typedef struct { #define PT_GNU_EH_FRAME 0x6474e550 #define PT_GNU_STACK 0x6474e551 #define PT_GNU_RELRO 0x6474e552 -#define PT_DUMP_DELTA 0x6fb5d000 /* va->pa map for kernel dumps - (currently arm). */ +#define PT_DUMP_DELTA 0x6fb5d000 /* va->pa map for arm and amd64 kernel + dumps */ #define PT_LOSUNW 0x6ffffffa #define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ #define PT_SUNWSTACK 0x6ffffffb /* describes the stack segment */ @@ -770,7 +790,8 @@ typedef struct { #define DF_1_GLOBAL 0x00000002 /* Set the RTLD_GLOBAL for object */ #define DF_1_NODELETE 0x00000008 /* Set the RTLD_NODELETE for object */ #define DF_1_LOADFLTR 0x00000010 /* Immediate loading of filtees */ -#define DF_1_NOOPEN 0x00000040 /* Do not allow loading on dlopen() */ +#define DF_1_INITFIRST 0x00000020 /* Initialize DSO first at runtime */ +#define DF_1_NOOPEN 0x00000040 /* Do not allow loading on dlopen() */ #define DF_1_ORIGIN 0x00000080 /* Process $ORIGIN */ #define DF_1_INTERPOSE 0x00000400 /* Interpose all objects but main */ #define DF_1_NODEFLIB 0x00000800 /* Do not search default paths */ @@ -804,6 +825,7 @@ typedef struct { #define NT_FREEBSD_FCTL_WXNEEDED 0x00000008 #define NT_FREEBSD_FCTL_LA48 0x00000010 /* was ASG_DISABLE, do not reuse 0x00000020 */ +#define NT_FREEBSD_FCTL_LA57 0x00000040 /* Values for n_type. Used in core files. */ #define NT_PRSTATUS 1 /* Process status. */ @@ -820,6 +842,7 @@ typedef struct { #define NT_PROCSTAT_PSSTRINGS 15 /* Procstat ps_strings data. */ #define NT_PROCSTAT_AUXV 16 /* Procstat auxv data. */ #define NT_PTLWPINFO 17 /* Thread ptrace miscellaneous info. */ +#define NT_PROCSTAT_KQUEUES 18 /* Procstat kqueues events. */ #define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */ #define NT_PPC_VSX 0x102 /* PowerPC VSX registers */ #define NT_X86_SEGBASES 0x200 /* x86 FS/GS base addresses. */ @@ -885,7 +908,7 @@ typedef struct { #define STV_ELIMINATE 0x6 /* Architecture specific data - st_other */ -#define STO_AARCH64_VARIANT_PCS 0x80 +#define STO_AARCH64_VARIANT_PCS 0x80 /* Special symbol table indexes. */ #define STN_UNDEF 0 /* Undefined symbol index. */ @@ -991,8 +1014,11 @@ typedef struct { #define AT_KPRELOAD 34 /* Base of vdso, preloaded by rtld */ #define AT_USRSTACKBASE 35 /* Top of user stack */ #define AT_USRSTACKLIM 36 /* Grow limit of user stack */ +#define AT_CHERI_STATS 37 /* Reserved */ +#define AT_HWCAP3 38 /* CPU feature flags 3. */ +#define AT_HWCAP4 39 /* CPU feature flags 4. */ -#define AT_COUNT 37 /* Count of defined aux entry types. */ +#define AT_COUNT 40 /* Count of defined aux entry types. */ /* * Relocation types. @@ -1058,11 +1084,11 @@ typedef struct { #define R_AARCH64_COPY 1024 /* Copy data from shared object */ #define R_AARCH64_GLOB_DAT 1025 /* Set GOT entry to data address */ #define R_AARCH64_JUMP_SLOT 1026 /* Set GOT entry to code address */ -#define R_AARCH64_RELATIVE 1027 /* Add load address of shared object */ +#define R_AARCH64_RELATIVE 1027 /* Add load address of shared object */ #define R_AARCH64_TLS_DTPREL64 1028 #define R_AARCH64_TLS_DTPMOD64 1029 -#define R_AARCH64_TLS_TPREL64 1030 -#define R_AARCH64_TLSDESC 1031 /* Identify the TLS descriptor */ +#define R_AARCH64_TLS_TPREL64 1030 +#define R_AARCH64_TLSDESC 1031 /* Identify the TLS descriptor */ #define R_AARCH64_IRELATIVE 1032 #define R_ARM_NONE 0 /* No relocation. */ @@ -1205,8 +1231,8 @@ typedef struct { #define R_MIPS_GOT_HI16 22 /* GOT HI 16 bit */ #define R_MIPS_GOT_LO16 23 /* GOT LO 16 bit */ #define R_MIPS_SUB 24 -#define R_MIPS_CALLHI16 30 /* upper 16 bit GOT entry for function */ -#define R_MIPS_CALLLO16 31 /* lower 16 bit GOT entry for function */ +#define R_MIPS_CALLHI16 30 /* upper 16 bit GOT entry for function */ +#define R_MIPS_CALLLO16 31 /* lower 16 bit GOT entry for function */ #define R_MIPS_JALR 37 #define R_MIPS_TLS_GD 42 #define R_MIPS_COPY 126 @@ -1326,7 +1352,6 @@ typedef struct { * RISC-V relocation types. */ -/* Relocation types used by the dynamic linker. */ #define R_RISCV_NONE 0 #define R_RISCV_32 1 #define R_RISCV_64 2 @@ -1339,8 +1364,7 @@ typedef struct { #define R_RISCV_TLS_DTPREL64 9 #define R_RISCV_TLS_TPREL32 10 #define R_RISCV_TLS_TPREL64 11 - -/* Relocation types not used by the dynamic linker. */ +#define R_RISCV_TLSDESC 12 #define R_RISCV_BRANCH 16 #define R_RISCV_JAL 17 #define R_RISCV_CALL 18 @@ -1366,10 +1390,10 @@ typedef struct { #define R_RISCV_SUB16 38 #define R_RISCV_SUB32 39 #define R_RISCV_SUB64 40 +#define R_RISCV_GOT32_PCREL 41 #define R_RISCV_ALIGN 43 #define R_RISCV_RVC_BRANCH 44 #define R_RISCV_RVC_JUMP 45 -#define R_RISCV_RVC_LUI 46 #define R_RISCV_RELAX 51 #define R_RISCV_SUB6 52 #define R_RISCV_SET6 53 @@ -1378,6 +1402,170 @@ typedef struct { #define R_RISCV_SET32 56 #define R_RISCV_32_PCREL 57 #define R_RISCV_IRELATIVE 58 +#define R_RISCV_PLT32 59 +#define R_RISCV_SET_ULEB128 60 +#define R_RISCV_SUB_ULEB128 61 +#define R_RISCV_TLSDESC_HI20 62 +#define R_RISCV_TLSDESC_LOAD_LO12 63 +#define R_RISCV_TLSDESC_ADD_LO12 64 +#define R_RISCV_TLSDESC_CALL 65 +#define R_RISCV_VENDOR 191 + +/* + * Loongson LoongArch relocation types. + * + * LoongArch ELF psABI: https://github.com/loongson/LoongArch-Documentation + * (commit hash 9b3bd9f4a497115913c22f1a2a47863798fbc02a) + */ + +/* Relocation types used by the dynamic linker */ +#define R_LARCH_NONE 0 +#define R_LARCH_32 1 +#define R_LARCH_64 2 +#define R_LARCH_RELATIVE 3 +#define R_LARCH_COPY 4 +#define R_LARCH_JUMP_SLOT 5 +#define R_LARCH_TLS_DTPMOD32 6 +#define R_LARCH_TLS_DTPMOD64 7 +#define R_LARCH_TLS_DTPREL32 8 +#define R_LARCH_TLS_DTPREL64 9 +#define R_LARCH_TLS_TPREL32 10 +#define R_LARCH_TLS_TPREL64 11 +#define R_LARCH_IRELATIVE 12 +#define R_LARCH_MARK_LA 20 +#define R_LARCH_MARK_PCREL 21 +#define R_LARCH_SOP_PUSH_PCREL 22 +#define R_LARCH_SOP_PUSH_ABSOLUTE 23 +#define R_LARCH_SOP_PUSH_DUP 24 +#define R_LARCH_SOP_PUSH_GPREL 25 +#define R_LARCH_SOP_PUSH_TLS_TPREL 26 +#define R_LARCH_SOP_PUSH_TLS_GOT 27 +#define R_LARCH_SOP_PUSH_TLS_GD 28 +#define R_LARCH_SOP_PUSH_PLT_PCREL 29 +#define R_LARCH_SOP_ASSERT 30 +#define R_LARCH_SOP_NOT 31 +#define R_LARCH_SOP_SUB 32 +#define R_LARCH_SOP_SL 33 +#define R_LARCH_SOP_SR 34 +#define R_LARCH_SOP_ADD 35 +#define R_LARCH_SOP_AND 36 +#define R_LARCH_SOP_IF_ELSE 37 +#define R_LARCH_SOP_POP_32_S_10_5 38 +#define R_LARCH_SOP_POP_32_U_10_12 39 +#define R_LARCH_SOP_POP_32_S_10_12 40 +#define R_LARCH_SOP_POP_32_S_10_16 41 +#define R_LARCH_SOP_POP_32_S_10_16_S2 42 +#define R_LARCH_SOP_POP_32_S_5_20 43 +#define R_LARCH_SOP_POP_32_S_0_5_10_16_S2 44 +#define R_LARCH_SOP_POP_32_S_0_10_10_16_S2 45 +#define R_LARCH_SOP_POP_32_U 46 +#define R_LARCH_ADD8 47 +#define R_LARCH_ADD16 48 +#define R_LARCH_ADD24 49 +#define R_LARCH_ADD32 50 +#define R_LARCH_ADD64 51 +#define R_LARCH_SUB8 52 +#define R_LARCH_SUB16 53 +#define R_LARCH_SUB24 54 +#define R_LARCH_SUB32 55 +#define R_LARCH_SUB64 56 +#define R_LARCH_GNU_VTINHERIT 57 +#define R_LARCH_GNU_VTENTRY 58 + +/* + * Relocs whose processing do not require a stack machine. + * + * Spec addition: https://github.com/loongson/LoongArch-Documentation/pull/57 + */ +#define R_LARCH_B16 64 +#define R_LARCH_B21 65 +#define R_LARCH_B26 66 +#define R_LARCH_ABS_HI20 67 +#define R_LARCH_ABS_LO12 68 +#define R_LARCH_ABS64_LO20 69 +#define R_LARCH_ABS64_HI12 70 +#define R_LARCH_PCALA_HI20 71 +#define R_LARCH_PCALA_LO12 72 +#define R_LARCH_PCALA64_LO20 73 +#define R_LARCH_PCALA64_HI12 74 +#define R_LARCH_GOT_PC_HI20 75 +#define R_LARCH_GOT_PC_LO12 76 +#define R_LARCH_GOT64_PC_LO20 77 +#define R_LARCH_GOT64_PC_HI12 78 +#define R_LARCH_GOT_HI20 79 +#define R_LARCH_GOT_LO12 80 +#define R_LARCH_GOT64_LO20 81 +#define R_LARCH_GOT64_HI12 82 +#define R_LARCH_TLS_LE_HI20 83 +#define R_LARCH_TLS_LE_LO12 84 +#define R_LARCH_TLS_LE64_LO20 85 +#define R_LARCH_TLS_LE64_HI12 86 +#define R_LARCH_TLS_IE_PC_HI20 87 +#define R_LARCH_TLS_IE_PC_LO12 88 +#define R_LARCH_TLS_IE64_PC_LO20 89 +#define R_LARCH_TLS_IE64_PC_HI12 90 +#define R_LARCH_TLS_IE_HI20 91 +#define R_LARCH_TLS_IE_LO12 92 +#define R_LARCH_TLS_IE64_LO20 93 +#define R_LARCH_TLS_IE64_HI12 94 +#define R_LARCH_TLS_LD_PC_HI20 95 +#define R_LARCH_TLS_LD_HI20 96 +#define R_LARCH_TLS_GD_PC_HI20 97 +#define R_LARCH_TLS_GD_HI20 98 +#define R_LARCH_32_PCREL 99 +#define R_LARCH_RELAX 100 + +/* + * Relocs added in ELF for the LoongArch™ Architecture v20230519, part of the + * v2.10 LoongArch ABI specs. + * + * Spec addition: https://github.com/loongson/la-abi-specs/pull/1 + * + * Note that the 101 and 104 relocation numbers are defined as R_LARCH_DELETE + * and R_LARCH_CFA respectively in psABI 2.10. But they are marked as reserved + * in psABI v2.20 because they were proved not necessary to be exposed outside + * of the linker. + */ +#define R_LARCH_ALIGN 102 +#define R_LARCH_PCREL20_S2 103 +#define R_LARCH_ADD6 105 +#define R_LARCH_SUB6 106 +#define R_LARCH_ADD_ULEB128 107 +#define R_LARCH_SUB_ULEB128 108 +#define R_LARCH_64_PCREL 109 + +/* + * Relocs added in ELF for the LoongArch™ Architecture v20231102, part of the + * v2.20 LoongArch ABI specs. + * + * Spec addition: https://github.com/loongson/la-abi-specs/pull/4 + */ +#define R_LARCH_CALL36 110 + +/* + * Relocs added in ELF for the LoongArch™ Architecture v20231219, part of the + * v2.30 LoongArch ABI specs. + * + * Spec addition: https://github.com/loongson/la-abi-specs/pull/5 + */ +#define R_LARCH_TLS_DESC32 13 +#define R_LARCH_TLS_DESC64 14 +#define R_LARCH_TLS_DESC_PC_HI20 111 +#define R_LARCH_TLS_DESC_PC_LO12 112 +#define R_LARCH_TLS_DESC64_PC_LO20 113 +#define R_LARCH_TLS_DESC64_PC_HI12 114 +#define R_LARCH_TLS_DESC_HI20 115 +#define R_LARCH_TLS_DESC_LO12 116 +#define R_LARCH_TLS_DESC64_LO20 117 +#define R_LARCH_TLS_DESC64_HI12 118 +#define R_LARCH_TLS_DESC_LD 119 +#define R_LARCH_TLS_DESC_CALL 120 +#define R_LARCH_TLS_LE_HI20_R 121 +#define R_LARCH_TLS_LE_ADD_R 122 +#define R_LARCH_TLS_LE_LO12_R 123 +#define R_LARCH_TLS_LD_PCREL20_S2 124 +#define R_LARCH_TLS_GD_PCREL20_S2 125 +#define R_LARCH_TLS_DESC_PCREL20_S2 126 #define R_SPARC_NONE 0 #define R_SPARC_8 1 diff --git a/lib/libc/include/generic-freebsd/sys/endian.h b/lib/libc/include/generic-freebsd/sys/endian.h index ab0dd7038c0e..b5050abe3986 100644 --- a/lib/libc/include/generic-freebsd/sys/endian.h +++ b/lib/libc/include/generic-freebsd/sys/endian.h @@ -56,7 +56,9 @@ typedef __uint64_t uint64_t; /* * Note: While tempting to try to avoid namespace pollution from this file, * several software packages assume these marcos are defined, even when it - * defines _POSIX_C_SOURCE to request an unpolluted namespace. + * defines _POSIX_C_SOURCE to request an unpolluted namespace. + * is not defined by any version of POSIX.1, so we don't have to be + * careful. No POSIX.1 defined header file includes on FreeBSD. */ /* diff --git a/lib/libc/include/generic-freebsd/sys/errno.h b/lib/libc/include/generic-freebsd/sys/errno.h index cdeb8fbcadc4..6238ec73d92d 100644 --- a/lib/libc/include/generic-freebsd/sys/errno.h +++ b/lib/libc/include/generic-freebsd/sys/errno.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)errno.h 8.5 (Berkeley) 1/21/94 */ #ifndef _SYS_ERRNO_H_ diff --git a/lib/libc/include/generic-freebsd/sys/event.h b/lib/libc/include/generic-freebsd/sys/event.h index a206671c083d..139f934c0028 100644 --- a/lib/libc/include/generic-freebsd/sys/event.h +++ b/lib/libc/include/generic-freebsd/sys/event.h @@ -45,7 +45,9 @@ #define EVFILT_USER (-11) /* User events */ #define EVFILT_SENDFILE (-12) /* attached to sendfile requests */ #define EVFILT_EMPTY (-13) /* empty send socket buf */ -#define EVFILT_SYSCOUNT 13 +#define EVFILT_JAIL (-14) /* attached to struct prison */ +#define EVFILT_JAILDESC (-15) /* attached to jail descriptors */ +#define EVFILT_SYSCOUNT 15 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define EV_SET(kevp_, a, b, c, d, e, f) do { \ @@ -101,7 +103,7 @@ struct freebsd11_kevent { }; #endif -#if defined(_WANT_KEVENT32) || (defined(_KERNEL) && defined(__LP64__)) +#if defined(_WANT_KEVENT32) || defined(_KERNEL) struct kevent32 { __uint32_t ident; /* identifier for this event */ short filter; /* filter for event */ @@ -205,10 +207,18 @@ struct freebsd11_kevent32 { #define NOTE_PDATAMASK 0x000fffff /* mask for pid */ /* additional flags for EVFILT_PROC */ -#define NOTE_TRACK 0x00000001 /* follow across forks */ +#define NOTE_TRACK 0x00000001 /* follow across fork/create */ #define NOTE_TRACKERR 0x00000002 /* could not track child */ #define NOTE_CHILD 0x00000004 /* am a child process */ +/* data/hint flags for EVFILT_JAIL and EVFILT_JAILDESC */ +#define NOTE_JAIL_CHILD 0x80000000 /* child jail was created */ +#define NOTE_JAIL_SET 0x40000000 /* jail was modified */ +#define NOTE_JAIL_ATTACH 0x20000000 /* jail was attached to */ +#define NOTE_JAIL_REMOVE 0x10000000 /* jail was removed */ +#define NOTE_JAIL_MULTI 0x08000000 /* multiple child or attach */ +#define NOTE_JAIL_CTRLMASK 0xf0000000 /* mask for hint bits */ + /* additional flags for EVFILT_TIMER */ #define NOTE_SECONDS 0x00000001 /* data is seconds */ #define NOTE_MSECONDS 0x00000002 /* data is milliseconds */ @@ -262,12 +272,17 @@ struct knlist { #define EVENT_REGISTER 1 #define EVENT_PROCESS 2 +struct kinfo_knote; +struct proc; + struct filterops { int f_isfd; /* true if ident == filedescriptor */ int (*f_attach)(struct knote *kn); void (*f_detach)(struct knote *kn); int (*f_event)(struct knote *kn, long hint); void (*f_touch)(struct knote *kn, struct kevent *kev, u_long type); + int (*f_userdump)(struct proc *p, struct knote *kn, + struct kinfo_knote *kin); }; /* @@ -304,6 +319,7 @@ struct knote { struct proc *p_proc; /* proc pointer */ struct kaiocb *p_aio; /* AIO job pointer */ struct aioliojob *p_lio; /* LIO job pointer */ + struct prison *p_prison; /* prison pointer */ void *p_v; /* generic other pointer */ } kn_ptr; const struct filterops *kn_fop; diff --git a/lib/libc/include/generic-freebsd/sys/eventhandler.h b/lib/libc/include/generic-freebsd/sys/eventhandler.h index 476524d8d116..1523bbe78db5 100644 --- a/lib/libc/include/generic-freebsd/sys/eventhandler.h +++ b/lib/libc/include/generic-freebsd/sys/eventhandler.h @@ -326,4 +326,9 @@ struct ifaddr; typedef void (*rt_addrmsg_fn)(void *, struct ifaddr *, int); EVENTHANDLER_DECLARE(rt_addrmsg, rt_addrmsg_fn); +/* Kernel environment variable change event */ +typedef void (*env_change_fn)(void *, const char *); +EVENTHANDLER_DECLARE(setenv, env_change_fn); +EVENTHANDLER_DECLARE(unsetenv, env_change_fn); + #endif /* _SYS_EVENTHANDLER_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/exec.h b/lib/libc/include/generic-freebsd/sys/exec.h index e85907d5bef0..38ec61df1965 100644 --- a/lib/libc/include/generic-freebsd/sys/exec.h +++ b/lib/libc/include/generic-freebsd/sys/exec.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)exec.h 8.3 (Berkeley) 1/21/94 */ #ifndef _SYS_EXEC_H_ @@ -59,16 +57,6 @@ struct ps_strings { unsigned int ps_nenvstr; /* the number of environment strings */ }; -/* Coredump output parameters. */ -struct coredump_params { - off_t offset; - struct ucred *active_cred; - struct ucred *file_cred; - struct thread *td; - struct vnode *vp; - struct compressor *comp; -}; - struct image_params; struct execsw { @@ -107,16 +95,6 @@ int exec_unregister(const struct execsw *); enum uio_seg; -#define CORE_BUF_SIZE (16 * 1024) - -int core_write(struct coredump_params *, const void *, size_t, off_t, - enum uio_seg, size_t *); -int core_output(char *, size_t, off_t, struct coredump_params *, void *); -int sbuf_drain_core_output(void *, const char *, int); - -extern int coredump_pack_fileinfo; -extern int coredump_pack_vmmapinfo; - /* * note: name##_mod cannot be const storage because the * linker_file_sysinit() function modifies _file in the diff --git a/lib/libc/include/generic-freebsd/sys/exterr_cat.h b/lib/libc/include/generic-freebsd/sys/exterr_cat.h new file mode 100644 index 000000000000..ddc427370bb4 --- /dev/null +++ b/lib/libc/include/generic-freebsd/sys/exterr_cat.h @@ -0,0 +1,25 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 The FreeBSD Foundation + * All rights reserved. + * + * This software were developed by Konstantin Belousov + * under sponsorship from the FreeBSD Foundation. + */ + +#ifndef _SYS_EXTERR_CAT_H_ +#define _SYS_EXTERR_CAT_H_ + +#define EXTERR_CAT_MMAP 1 +#define EXTERR_CAT_FILEDESC 2 +#define EXTERR_KTRACE 3 /* To allow inclusion of this + file into kern_ktrace.c */ +#define EXTERR_CAT_FUSE 4 +#define EXTERR_CAT_INOTIFY 5 +#define EXTERR_CAT_GENIO 6 +#define EXTERR_CAT_BRIDGE 7 +#define EXTERR_CAT_SWAP 8 +#define EXTERR_CAT_VFSSYSCALL 9 + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/exterrvar.h b/lib/libc/include/generic-freebsd/sys/exterrvar.h new file mode 100644 index 000000000000..fd76510792fc --- /dev/null +++ b/lib/libc/include/generic-freebsd/sys/exterrvar.h @@ -0,0 +1,67 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 The FreeBSD Foundation + * All rights reserved. + * + * This software were developed by Konstantin Belousov + * under sponsorship from the FreeBSD Foundation. + */ + +#ifndef _SYS_EXTERRVAR_H_ +#define _SYS_EXTERRVAR_H_ + +#include +#include +#include + +#define UEXTERROR_MAXLEN 256 + +#define UEXTERROR_VER 0x10010002 + +#define EXTERRCTL_ENABLE 1 +#define EXTERRCTL_DISABLE 2 +#define EXTERRCTL_UD 3 + +#define EXTERRCTLF_FORCE 0x00000001 + +#ifdef _KERNEL + +#ifndef EXTERR_CATEGORY +#error "Specify error category before including sys/exterrvar.h" +#endif + +#ifdef EXTERR_STRINGS +#define SET_ERROR_MSG(mmsg) (mmsg) +#else +#define SET_ERROR_MSG(mmsg) NULL +#endif + +#define _SET_ERROR2(eerror, mmsg, pp1, pp2) \ + exterr_set(eerror, EXTERR_CATEGORY, SET_ERROR_MSG(mmsg), \ + (uintptr_t)(pp1), (uintptr_t)(pp2), __LINE__) +#define _SET_ERROR0(eerror, mmsg) _SET_ERROR2(eerror, mmsg, 0, 0) +#define _SET_ERROR1(eerror, mmsg, pp1) _SET_ERROR2(eerror, mmsg, pp1, 0) + +#define _EXTERROR_MACRO(eerror, mmsg, _1, _2, NAME, ...) \ + NAME +#define EXTERROR(...) \ + _EXTERROR_MACRO(__VA_ARGS__, _SET_ERROR2, _SET_ERROR1, \ + _SET_ERROR0)(__VA_ARGS__) + +int exterr_set(int eerror, int category, const char *mmsg, uintptr_t pp1, + uintptr_t pp2, int line); +int exterr_to_ue(struct thread *td, struct uexterror *ue); +void ktrexterr(struct thread *td); + +#else /* _KERNEL */ + +#include + +__BEGIN_DECLS +int exterrctl(u_int op, u_int flags, void *ptr); +__END_DECLS + +#endif /* _KERNEL */ + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/fbio.h b/lib/libc/include/generic-freebsd/sys/fbio.h index d3fb0c39f2b3..30672d236072 100644 --- a/lib/libc/include/generic-freebsd/sys/fbio.h +++ b/lib/libc/include/generic-freebsd/sys/fbio.h @@ -31,8 +31,6 @@ * 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. - * - * @(#)fbio.h 8.2 (Berkeley) 10/30/93 */ #ifndef _SYS_FBIO_H_ diff --git a/lib/libc/include/generic-freebsd/sys/fcntl.h b/lib/libc/include/generic-freebsd/sys/fcntl.h index d0d93108b5e9..0120afe643a1 100644 --- a/lib/libc/include/generic-freebsd/sys/fcntl.h +++ b/lib/libc/include/generic-freebsd/sys/fcntl.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)fcntl.h 8.3 (Berkeley) 1/21/94 */ #ifndef _SYS_FCNTL_H_ @@ -142,8 +140,24 @@ typedef __pid_t pid_t; #define O_DSYNC 0x01000000 /* POSIX data sync */ #if __BSD_VISIBLE #define O_EMPTY_PATH 0x02000000 +#define O_NAMEDATTR 0x04000000 /* NFSv4 named attributes */ +#define O_XATTR O_NAMEDATTR /* Solaris compatibility */ +#endif + +#if __POSIX_VISIBLE >= 202405 +#define O_CLOFORK 0x08000000 #endif +/* + * !!! DANGER !!! + * + * There are very few bits left for O_* flags. Every bit we consume for + * local features is one bit we can't use for future source compatibility + * with other operating systems. + * + * All additions should be coordinated with srcmgr@. + */ + /* * XXX missing O_RSYNC. */ @@ -270,6 +284,16 @@ typedef __pid_t pid_t; #define F_GET_SEALS 20 #define F_ISUNIONSTACK 21 /* Kludge for libc, don't use it. */ #define F_KINFO 22 /* Return kinfo_file for this fd */ +#endif /* __BSD_VISIBLE */ + +#if __POSIX_VISIBLE >= 202405 +#define F_DUPFD_CLOFORK 23 /* Like F_DUPFD, but FD_CLOFORK is set */ +#endif + +#if __BSD_VISIBLE +#define F_DUP3FD 24 /* Used with dup3() */ + +#define F_DUP3FD_SHIFT 16 /* Shift used for F_DUP3FD */ /* Seals (F_ADD_SEALS, F_GET_SEALS). */ #define F_SEAL_SEAL 0x0001 /* Prevent adding sealings */ @@ -280,6 +304,11 @@ typedef __pid_t pid_t; /* file descriptor flags (F_GETFD, F_SETFD) */ #define FD_CLOEXEC 1 /* close-on-exec flag */ +#define FD_RESOLVE_BENEATH 2 /* all lookups relative to fd have + O_RESOLVE_BENEATH semantics */ +#if __POSIX_VISIBLE >= 202405 +#define FD_CLOFORK 4 /* close-on-fork flag */ +#endif /* record locking flags (F_GETLK, F_SETLK, F_SETLKW) */ #define F_RDLCK 1 /* shared or read lock */ diff --git a/lib/libc/include/generic-freebsd/sys/file.h b/lib/libc/include/generic-freebsd/sys/file.h index 1a84d5b062ea..138c4cd33dce 100644 --- a/lib/libc/include/generic-freebsd/sys/file.h +++ b/lib/libc/include/generic-freebsd/sys/file.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)file.h 8.3 (Berkeley) 1/9/95 */ #ifndef _SYS_FILE_H_ @@ -39,13 +37,16 @@ #include #include #else -#include -#include +#include #include #include +#include +#include +#include #include struct filedesc; +struct proc; struct stat; struct thread; struct uio; @@ -70,6 +71,8 @@ struct nameidata; #define DTYPE_PROCDESC 12 /* process descriptor */ #define DTYPE_EVENTFD 13 /* eventfd */ #define DTYPE_TIMERFD 14 /* timerfd */ +#define DTYPE_INOTIFY 15 /* inotify descriptor */ +#define DTYPE_JAILDESC 16 /* jail descriptor */ #ifdef _KERNEL @@ -85,6 +88,8 @@ struct ucred; #define FOF_NEXTOFF_W 0x08 /* Also update f_nextoff[UIO_WRITE] */ #define FOF_NOUPDATE 0x10 /* Do not update f_offset */ off_t foffset_lock(struct file *fp, int flags); +void foffset_lock_pair(struct file *fp1, off_t *off1p, struct file *fp2, + off_t *off2p, int flags); void foffset_lock_uio(struct file *fp, struct uio *uio, int flags); void foffset_unlock(struct file *fp, off_t val, int flags); void foffset_unlock_uio(struct file *fp, struct uio *uio, int flags); @@ -156,7 +161,7 @@ struct fileops { fo_fallocate_t *fo_fallocate; fo_fspacectl_t *fo_fspacectl; fo_cmp_t *fo_cmp; - fo_spare_t *fo_spares[7]; /* Spare slots */ + fo_spare_t *fo_spares[8]; /* Spare slots */ fo_flags_t fo_flags; /* DFLAG_* below */ }; @@ -188,11 +193,11 @@ struct file { volatile u_int f_flag; /* see fcntl.h */ volatile u_int f_count; /* reference count */ void *f_data; /* file descriptor specific data */ - struct fileops *f_ops; /* File operations */ + const struct fileops *f_ops; /* File operations */ struct vnode *f_vnode; /* NULL or applicable vnode */ struct ucred *f_cred; /* associated credentials. */ short f_type; /* descriptor type */ - short f_vnread_flags; /* (f) Sleep lock for f_offset */ + short f_vflags; /* (f) Sleep lock flags for members */ /* * DTYPE_VNODE specific fields. */ @@ -215,8 +220,8 @@ struct file { #define f_cdevpriv f_vnun.fvn_cdevpriv #define f_advice f_vnun.fvn_advice -#define FOFFSET_LOCKED 0x1 -#define FOFFSET_LOCK_WAITING 0x2 +#define FILE_V_FOFFSET_LOCKED 0x0001 +#define FILE_V_FOFFSET_LOCK_WAITING 0x0002 #endif /* __BSD_VISIBLE */ #endif /* _KERNEL || _WANT_FILE */ @@ -248,24 +253,27 @@ struct xfile { #ifdef _KERNEL -extern struct fileops vnops; -extern struct fileops badfileops; -extern struct fileops path_fileops; -extern struct fileops socketops; +extern const struct fileops vnops; +extern const struct fileops badfileops; +extern const struct fileops path_fileops; +extern const struct fileops socketops; extern int maxfiles; /* kernel limit on number of open files */ extern int maxfilesperproc; /* per process limit on number of open files */ -int fget(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp); -int fget_mmap(struct thread *td, int fd, cap_rights_t *rightsp, +int fget(struct thread *td, int fd, const cap_rights_t *rightsp, + struct file **fpp); +int fget_mmap(struct thread *td, int fd, const cap_rights_t *rightsp, vm_prot_t *maxprotp, struct file **fpp); -int fget_read(struct thread *td, int fd, cap_rights_t *rightsp, +int fget_read(struct thread *td, int fd, const cap_rights_t *rightsp, struct file **fpp); -int fget_write(struct thread *td, int fd, cap_rights_t *rightsp, +int fget_write(struct thread *td, int fd, const cap_rights_t *rightsp, struct file **fpp); -int fget_fcntl(struct thread *td, int fd, cap_rights_t *rightsp, +int fget_fcntl(struct thread *td, int fd, const cap_rights_t *rightsp, int needfcntl, struct file **fpp); int _fdrop(struct file *fp, struct thread *td); int fget_remote(struct thread *td, struct proc *p, int fd, struct file **fpp); +int fget_remote_foreach(struct thread *td, struct proc *p, + int (*fn)(struct proc *, int, struct file *, void *), void *arg); fo_rdwr_t invfo_rdwr; fo_truncate_t invfo_truncate; @@ -283,19 +291,19 @@ fo_kqfilter_t vn_kqfilter_opath; int vn_fill_kinfo_vnode(struct vnode *vp, struct kinfo_file *kif); int file_kcmp_generic(struct file *fp1, struct file *fp2, struct thread *td); -void finit(struct file *, u_int, short, void *, struct fileops *); -void finit_vnode(struct file *, u_int, void *, struct fileops *); -int fgetvp(struct thread *td, int fd, cap_rights_t *rightsp, +void finit(struct file *, u_int, short, void *, const struct fileops *); +void finit_vnode(struct file *, u_int, void *, const struct fileops *); +int fgetvp(struct thread *td, int fd, const cap_rights_t *rightsp, struct vnode **vpp); -int fgetvp_exec(struct thread *td, int fd, cap_rights_t *rightsp, +int fgetvp_exec(struct thread *td, int fd, const cap_rights_t *rightsp, struct vnode **vpp); -int fgetvp_rights(struct thread *td, int fd, cap_rights_t *needrightsp, +int fgetvp_rights(struct thread *td, int fd, const cap_rights_t *needrightsp, struct filecaps *havecaps, struct vnode **vpp); -int fgetvp_read(struct thread *td, int fd, cap_rights_t *rightsp, +int fgetvp_read(struct thread *td, int fd, const cap_rights_t *rightsp, struct vnode **vpp); -int fgetvp_write(struct thread *td, int fd, cap_rights_t *rightsp, +int fgetvp_write(struct thread *td, int fd, const cap_rights_t *rightsp, struct vnode **vpp); -int fgetvp_lookup_smr(struct nameidata *ndp, struct vnode **vpp, bool *fsearch); +int fgetvp_lookup_smr(struct nameidata *ndp, struct vnode **vpp, int *flagsp); int fgetvp_lookup(struct nameidata *ndp, struct vnode **vpp); static __inline __result_use_check bool diff --git a/lib/libc/include/generic-freebsd/sys/filedesc.h b/lib/libc/include/generic-freebsd/sys/filedesc.h index 865cba6ad418..6e9f4faf98d5 100644 --- a/lib/libc/include/generic-freebsd/sys/filedesc.h +++ b/lib/libc/include/generic-freebsd/sys/filedesc.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)filedesc.h 8.1 (Berkeley) 6/2/93 */ #ifndef _SYS_FILEDESC_H_ @@ -150,6 +148,8 @@ struct filedesc_to_leader { * Per-process open flags. */ #define UF_EXCLOSE 0x01 /* auto-close on exec */ +#define UF_RESOLVE_BENEATH 0x02 /* lookups must be beneath this dir */ +#define UF_FOCLOSE 0x04 /* auto-close on fork */ #ifdef _KERNEL @@ -222,6 +222,7 @@ enum { /* Flags for kern_dup(). */ #define FDDUP_FLAG_CLOEXEC 0x1 /* Atomically set UF_EXCLOSE. */ +#define FDDUP_FLAG_CLOFORK 0x2 /* Atomically set UF_FOCLOSE. */ /* For backward compatibility. */ #define falloc(td, resultfp, resultfd, flags) \ @@ -277,22 +278,26 @@ struct filedesc_to_leader * struct filedesc_to_leader * filedesc_to_leader_share(struct filedesc_to_leader *fdtol, struct filedesc *fdp); -int getvnode(struct thread *td, int fd, cap_rights_t *rightsp, - struct file **fpp); -int getvnode_path(struct thread *td, int fd, cap_rights_t *rightsp, +int getvnode(struct thread *td, int fd, const cap_rights_t *rightsp, struct file **fpp); +int getvnode_path(struct thread *td, int fd, const cap_rights_t *rightsp, + uint8_t *flagsp, struct file **fpp); void mountcheckdirs(struct vnode *olddp, struct vnode *newdp); -int fget_cap_noref(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, - struct file **fpp, struct filecaps *havecapsp); -int fget_cap(struct thread *td, int fd, cap_rights_t *needrightsp, - struct file **fpp, struct filecaps *havecapsp); +int fget_cap_noref(struct filedesc *fdp, int fd, + const cap_rights_t *needrightsp, struct file **fpp, + struct filecaps *havecapsp); +int fget_cap(struct thread *td, int fd, const cap_rights_t *needrightsp, + uint8_t *flagsp, struct file **fpp, struct filecaps *havecapsp); /* Return a referenced file from an unlocked descriptor. */ -int fget_unlocked(struct thread *td, int fd, cap_rights_t *needrightsp, +int fget_unlocked(struct thread *td, int fd, + const cap_rights_t *needrightsp, struct file **fpp); +int fget_unlocked_flags(struct thread *td, int fd, + const cap_rights_t *needrightsp, uint8_t *flagsp, struct file **fpp); /* Return a file pointer without a ref. FILEDESC_IS_ONLY_USER must be true. */ -int fget_only_user(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, - struct file **fpp); +int fget_only_user(struct filedesc *fdp, int fd, + const cap_rights_t *needrightsp, struct file **fpp); #define fput_only_user(fdp, fp) ({ \ MPASS(FILEDESC_IS_ONLY_USER(fdp)); \ MPASS(refcount_load(&fp->f_count) > 0); \ diff --git a/lib/libc/include/generic-freebsd/sys/filio.h b/lib/libc/include/generic-freebsd/sys/filio.h index 1f4024a0cfa1..f65959c1c961 100644 --- a/lib/libc/include/generic-freebsd/sys/filio.h +++ b/lib/libc/include/generic-freebsd/sys/filio.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)filio.h 8.1 (Berkeley) 3/28/94 */ #ifndef _SYS_FILIO_H_ diff --git a/lib/libc/include/generic-freebsd/sys/gmon.h b/lib/libc/include/generic-freebsd/sys/gmon.h index 31d45b4d735f..86f39b683213 100644 --- a/lib/libc/include/generic-freebsd/sys/gmon.h +++ b/lib/libc/include/generic-freebsd/sys/gmon.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)gmon.h 8.2 (Berkeley) 1/4/94 */ #ifndef _SYS_GMON_H_ diff --git a/lib/libc/include/generic-freebsd/sys/hwt.h b/lib/libc/include/generic-freebsd/sys/hwt.h new file mode 100644 index 000000000000..1e711aa308dc --- /dev/null +++ b/lib/libc/include/generic-freebsd/sys/hwt.h @@ -0,0 +1,129 @@ +/*- + * Copyright (c) 2023-2025 Ruslan Bukin + * + * This work was supported by Innovate UK project 105694, "Digital Security + * by Design (DSbD) Technology Platform Prototype". + * + * 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. + */ + +/* User-visible header. */ + +#include +#include +#include +#include + +#ifndef _SYS_HWT_H_ +#define _SYS_HWT_H_ + +#define HWT_MAGIC 0x42 +#define HWT_IOC_ALLOC _IOW(HWT_MAGIC, 0x00, struct hwt_alloc) +#define HWT_IOC_START _IOW(HWT_MAGIC, 0x01, struct hwt_start) +#define HWT_IOC_STOP _IOW(HWT_MAGIC, 0x02, struct hwt_stop) +#define HWT_IOC_RECORD_GET _IOW(HWT_MAGIC, 0x03, struct hwt_record_get) +#define HWT_IOC_BUFPTR_GET _IOW(HWT_MAGIC, 0x04, struct hwt_bufptr_get) +#define HWT_IOC_SET_CONFIG _IOW(HWT_MAGIC, 0x05, struct hwt_set_config) +#define HWT_IOC_WAKEUP _IOW(HWT_MAGIC, 0x06, struct hwt_wakeup) +#define HWT_IOC_SVC_BUF _IOW(HWT_MAGIC, 0x07, struct hwt_svc_buf) + +#define HWT_BACKEND_MAXNAMELEN 256 + +#define HWT_MODE_THREAD 1 +#define HWT_MODE_CPU 2 + +struct hwt_alloc { + size_t bufsize; + int mode; + pid_t pid; /* thread mode */ + cpuset_t *cpu_map; /* cpu mode only */ + size_t cpusetsize; + const char *backend_name; + int *ident; + int kqueue_fd; +} __aligned(16); + +struct hwt_start { + int reserved; +} __aligned(16); + +struct hwt_stop { + int reserved; +} __aligned(16); + +struct hwt_wakeup { + int reserved; +} __aligned(16); + +struct hwt_record_user_entry { + enum hwt_record_type record_type; + union { + /* + * Used for MMAP, EXECUTABLE, INTERP, + * and KERNEL records. + */ + struct { + char fullpath[MAXPATHLEN]; + uintptr_t addr; + uintptr_t baseaddr; + }; + /* Used for BUFFER records. */ + struct { + int buf_id; + int curpage; + vm_offset_t offset; + }; + /* Used for THREAD_* records. */ + int thread_id; + }; +} __aligned(16); + +struct hwt_record_get { + struct hwt_record_user_entry *records; + int *nentries; + int wait; +} __aligned(16); + +struct hwt_bufptr_get { + int *ident; + vm_offset_t *offset; + uint64_t *data; +} __aligned(16); + +struct hwt_set_config { + /* Configuration of ctx. */ + int pause_on_mmap; + + /* The following passed to backend as is. */ + void *config; + size_t config_size; + int config_version; +} __aligned(16); + +struct hwt_svc_buf { + /* The following passed to backend as is. */ + void *data; + size_t data_size; + int data_version; +} __aligned(16); + +#endif /* !_SYS_HWT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/hwt_record.h b/lib/libc/include/generic-freebsd/sys/hwt_record.h new file mode 100644 index 000000000000..a3dc7181dea7 --- /dev/null +++ b/lib/libc/include/generic-freebsd/sys/hwt_record.h @@ -0,0 +1,70 @@ +/*- + * Copyright (c) 2023-2025 Ruslan Bukin + * + * This work was supported by Innovate UK project 105694, "Digital Security + * by Design (DSbD) Technology Platform Prototype". + * + * 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. + */ + +/* User-visible header. */ + +#ifndef _SYS_HWT_RECORD_H_ +#define _SYS_HWT_RECORD_H_ + +enum hwt_record_type { + HWT_RECORD_MMAP, + HWT_RECORD_MUNMAP, + HWT_RECORD_EXECUTABLE, + HWT_RECORD_KERNEL, + HWT_RECORD_THREAD_CREATE, + HWT_RECORD_THREAD_SET_NAME, + HWT_RECORD_BUFFER +}; + +#ifdef _KERNEL +struct hwt_record_entry { + TAILQ_ENTRY(hwt_record_entry) next; + enum hwt_record_type record_type; + union { + /* + * Used for MMAP, EXECUTABLE, INTERP, + * and KERNEL records. + */ + struct { + char *fullpath; + uintptr_t addr; + uintptr_t baseaddr; + }; + /* Used for BUFFER records. */ + struct { + int buf_id; + int curpage; + vm_offset_t offset; + }; + /* Used for THREAD_* records. */ + int thread_id; + }; +}; +#endif + +#endif /* !_SYS_HWT_RECORD_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/imgact.h b/lib/libc/include/generic-freebsd/sys/imgact.h index 853e2e7682b7..54e669d24099 100644 --- a/lib/libc/include/generic-freebsd/sys/imgact.h +++ b/lib/libc/include/generic-freebsd/sys/imgact.h @@ -119,8 +119,7 @@ int exec_map_stack(struct image_params *); int exec_new_vmspace(struct image_params *, struct sysentvec *); void exec_setregs(struct thread *, struct image_params *, uintptr_t); int exec_shell_imgact(struct image_params *); -int exec_copyin_args(struct image_args *, const char *, enum uio_seg, - char **, char **); +int exec_copyin_args(struct image_args *, const char *, char **, char **); int pre_execve(struct thread *td, struct vmspace **oldvmspace); void post_execve(struct thread *td, int error, struct vmspace *oldvmspace); #endif diff --git a/lib/libc/include/generic-freebsd/sys/imgact_aout.h b/lib/libc/include/generic-freebsd/sys/imgact_aout.h index 07f49bf80cff..61b420743f2b 100644 --- a/lib/libc/include/generic-freebsd/sys/imgact_aout.h +++ b/lib/libc/include/generic-freebsd/sys/imgact_aout.h @@ -27,8 +27,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)exec.h 8.1 (Berkeley) 6/11/93 */ #ifndef _IMGACT_AOUT_H_ diff --git a/lib/libc/include/generic-freebsd/sys/imgact_elf.h b/lib/libc/include/generic-freebsd/sys/imgact_elf.h index f60851e2bf24..2d19cb603d95 100644 --- a/lib/libc/include/generic-freebsd/sys/imgact_elf.h +++ b/lib/libc/include/generic-freebsd/sys/imgact_elf.h @@ -45,6 +45,7 @@ {(pos)->a_type = (id); (pos)->a_un.a_ptr = (ptr); (pos)++;} #endif +struct coredump_writer; struct image_params; struct thread; struct vnode; @@ -86,8 +87,8 @@ typedef struct { const char *interp_newpath; int flags; Elf_Brandnote *brand_note; - bool (*header_supported)(struct image_params *, - int32_t *, uint32_t *); + bool (*header_supported)(const struct image_params *, + const int32_t *, const uint32_t *); /* High 8 bits of flags is private to the ABI */ #define BI_CAN_EXEC_DYN 0x0001 #define BI_BRAND_NOTE 0x0002 /* May have note.ABI-tag section. */ @@ -114,7 +115,7 @@ bool __elfN(brand_inuse)(Elf_Brandinfo *entry); int __elfN(insert_brand_entry)(Elf_Brandinfo *entry); int __elfN(remove_brand_entry)(Elf_Brandinfo *entry); int __elfN(freebsd_fixup)(uintptr_t *, struct image_params *); -int __elfN(coredump)(struct thread *, struct vnode *, off_t, int); +int __elfN(coredump)(struct thread *, struct coredump_writer *, off_t, int); size_t __elfN(populate_note)(int, void *, void *, size_t, void **); int __elfN(freebsd_copyout_auxargs)(struct image_params *, uintptr_t); void __elfN(puthdr)(struct thread *, void *, size_t, int, size_t, int); @@ -123,9 +124,9 @@ void __elfN(prepare_notes)(struct thread *, struct note_info_list *, void __elfN(size_segments)(struct thread *, struct sseg_closure *, int); size_t __elfN(register_note)(struct thread *, struct note_info_list *, int, outfunc_t, void *); -bool __elfN(parse_notes)(struct image_params *, Elf_Note *, const char *, - const Elf_Phdr *, bool (*)(const Elf_Note *, void *, bool *), - void *); +bool __elfN(parse_notes)(const struct image_params *, const Elf_Note *, + const char *, const Elf_Phdr *, + bool (*)(const Elf_Note *, void *, bool *), void *); /* Machine specific function to dump per-thread information. */ void __elfN(dump_thread)(struct thread *, void *, size_t *); diff --git a/lib/libc/include/generic-freebsd/sys/inotify.h b/lib/libc/include/generic-freebsd/sys/inotify.h new file mode 100644 index 000000000000..b3bd0da8748b --- /dev/null +++ b/lib/libc/include/generic-freebsd/sys/inotify.h @@ -0,0 +1,158 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Klara, Inc. + */ + +#ifndef _INOTIFY_H_ +#define _INOTIFY_H_ + +#include + +/* Flags for inotify_init1(). */ +#define IN_NONBLOCK 0x00000004 /* O_NONBLOCK */ +#define IN_CLOEXEC 0x00100000 /* O_CLOEXEC */ + +struct inotify_event { + int wd; + __uint32_t mask; + __uint32_t cookie; + __uint32_t len; + char name[0]; +}; + +/* Events, set in the mask field. */ +#define IN_ACCESS 0x00000001 +#define IN_MODIFY 0x00000002 +#define IN_ATTRIB 0x00000004 +#define IN_CLOSE_WRITE 0x00000008 +#define IN_CLOSE_NOWRITE 0x00000010 +#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) +#define IN_OPEN 0x00000020 +#define IN_MOVED_FROM 0x00000040 +#define IN_MOVED_TO 0x00000080 +#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) +#define IN_CREATE 0x00000100 +#define IN_DELETE 0x00000200 +#define IN_DELETE_SELF 0x00000400 +#define IN_MOVE_SELF 0x00000800 +#define IN_ALL_EVENTS 0x00000fff + +/* Events report only for entries in a watched dir, not the dir itself. */ +#define _IN_DIR_EVENTS (IN_CLOSE_WRITE | IN_DELETE | IN_MODIFY | \ + IN_MOVED_FROM | IN_MOVED_TO) + +#ifdef _KERNEL +/* + * An unlink that's done as part of a rename only records IN_DELETE if the + * unlinked vnode itself is watched, and not when the containing directory is + * watched. + */ +#define _IN_MOVE_DELETE 0x40000000 +/* + * Inode link count changes only trigger IN_ATTRIB events if the inode itself is + * watched, and not when the containing directory is watched. + */ +#define _IN_ATTRIB_LINKCOUNT 0x80000000 +#endif + +/* Flags, set in the mask field. */ +#define IN_ONLYDIR 0x01000000 +#define IN_DONT_FOLLOW 0x02000000 +#define IN_EXCL_UNLINK 0x04000000 +#define IN_MASK_CREATE 0x10000000 +#define IN_MASK_ADD 0x20000000 +#define IN_ONESHOT 0x80000000 +#define _IN_ALL_FLAGS (IN_ONLYDIR | IN_DONT_FOLLOW | \ + IN_EXCL_UNLINK | IN_MASK_CREATE | \ + IN_MASK_ADD | IN_ONESHOT) + +/* Flags returned by the kernel. */ +#define IN_UNMOUNT 0x00002000 +#define IN_Q_OVERFLOW 0x00004000 +#define IN_IGNORED 0x00008000 +#define IN_ISDIR 0x40000000 +#define _IN_ALL_RETFLAGS (IN_Q_OVERFLOW | IN_UNMOUNT | IN_IGNORED | \ + IN_ISDIR) + +#define _IN_ALIGN _Alignof(struct inotify_event) +#define _IN_NAMESIZE(namelen) \ + ((namelen) == 0 ? 0 : __align_up((namelen) + 1, _IN_ALIGN)) + +#ifdef _KERNEL +struct componentname; +struct file; +struct inotify_softc; +struct thread; +struct vnode; + +int inotify_create_file(struct thread *, struct file *, int, int *); +void inotify_log(struct vnode *, const char *, size_t, int, __uint32_t); + +int kern_inotify_rm_watch(int, uint32_t, struct thread *); +int kern_inotify_add_watch(int, int, const char *, uint32_t, + struct thread *); + +void vn_inotify(struct vnode *, struct vnode *, struct componentname *, int, + uint32_t); +int vn_inotify_add_watch(struct vnode *, struct inotify_softc *, + __uint32_t, __uint32_t *, struct thread *); +void vn_inotify_revoke(struct vnode *); + +/* Log an inotify event. */ +#define INOTIFY(vp, ev) do { \ + if (__predict_false((vn_irflag_read(vp) & (VIRF_INOTIFY | \ + VIRF_INOTIFY_PARENT)) != 0)) \ + VOP_INOTIFY((vp), NULL, NULL, (ev), 0); \ +} while (0) + +/* Log an inotify event using a specific name for the vnode. */ +#define INOTIFY_NAME_LOCK(vp, dvp, cnp, ev, lock) do { \ + if (__predict_false((vn_irflag_read(vp) & VIRF_INOTIFY) != 0 || \ + (vn_irflag_read(dvp) & VIRF_INOTIFY) != 0)) { \ + if (lock) \ + vn_lock((vp), LK_SHARED | LK_RETRY); \ + VOP_INOTIFY((vp), (dvp), (cnp), (ev), 0); \ + if (lock) \ + VOP_UNLOCK(vp); \ + } \ +} while (0) +#define INOTIFY_NAME(vp, dvp, cnp, ev) \ + INOTIFY_NAME_LOCK((vp), (dvp), (cnp), (ev), false) + +extern __uint32_t inotify_rename_cookie; + +#define INOTIFY_MOVE(vp, fdvp, fcnp, tvp, tdvp, tcnp) do { \ + if (__predict_false((vn_irflag_read(fdvp) & VIRF_INOTIFY) != 0 || \ + (vn_irflag_read(tdvp) & VIRF_INOTIFY) != 0 || \ + (vn_irflag_read(vp) & VIRF_INOTIFY) != 0)) { \ + __uint32_t cookie; \ + \ + cookie = atomic_fetchadd_32(&inotify_rename_cookie, 1); \ + VOP_INOTIFY((vp), (fdvp), (fcnp), IN_MOVED_FROM, cookie); \ + VOP_INOTIFY((vp), (tdvp), (tcnp), IN_MOVED_TO, cookie); \ + } \ + if ((tvp) != NULL) \ + INOTIFY_NAME_LOCK((tvp), (tdvp), (tcnp), \ + _IN_MOVE_DELETE, true); \ +} while (0) + +#define INOTIFY_REVOKE(vp) do { \ + if (__predict_false((vn_irflag_read(vp) & VIRF_INOTIFY) != 0)) \ + vn_inotify_revoke((vp)); \ +} while (0) + +#else +#include + +__BEGIN_DECLS +int inotify_init(void); +int inotify_init1(int flags); +int inotify_add_watch(int fd, const char *pathname, __uint32_t mask); +int inotify_add_watch_at(int fd, int dfd, const char *pathname, + __uint32_t mask); +int inotify_rm_watch(int fd, int wd); +__END_DECLS +#endif /* !_KERNEL */ + +#endif /* !_INOTIFY_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/interrupt.h b/lib/libc/include/generic-freebsd/sys/interrupt.h index 60cd6119201c..8126df6a3980 100644 --- a/lib/libc/include/generic-freebsd/sys/interrupt.h +++ b/lib/libc/include/generic-freebsd/sys/interrupt.h @@ -121,7 +121,7 @@ struct intr_event { int ie_count; /* Loop counter. */ int ie_warncnt; /* Rate-check interrupt storm warns. */ struct timeval ie_warntm; - int ie_irq; /* Physical irq number if !SOFT. */ + u_int ie_irq; /* Physical irq number if !SOFT. */ int ie_cpu; /* CPU this event is bound to. */ volatile int ie_phase; /* Switched to establish a barrier. */ volatile int ie_active[2]; /* Filters in ISR context. */ @@ -129,6 +129,7 @@ struct intr_event { /* Interrupt event flags kept in ie_flags. */ #define IE_SOFT 0x000001 /* Software interrupt. */ +#define IE_SLEEPABLE 0x000002 /* Sleepable ithread */ #define IE_ADDING_THREAD 0x000004 /* Currently building an ithread. */ /* Flags to pass to swi_sched. */ @@ -175,7 +176,7 @@ struct _cpuset; int intr_event_bind_ithread_cpuset(struct intr_event *ie, struct _cpuset *mask); int intr_event_create(struct intr_event **event, void *source, - int flags, int irq, void (*pre_ithread)(void *), + int flags, u_int irq, void (*pre_ithread)(void *), void (*post_ithread)(void *), void (*post_filter)(void *), int (*assign_cpu)(void *, int), const char *fmt, ...) __printflike(9, 10); @@ -188,7 +189,7 @@ int intr_event_suspend_handler(void *cookie); int intr_event_resume_handler(void *cookie); int intr_getaffinity(int irq, int mode, void *mask); void *intr_handler_source(void *cookie); -int intr_setaffinity(int irq, int mode, void *mask); +int intr_setaffinity(int irq, int mode, const void *mask); void _intr_drain(int irq); /* LinuxKPI only. */ int swi_add(struct intr_event **eventp, const char *name, driver_intr_t handler, void *arg, int pri, enum intr_type flags, diff --git a/lib/libc/include/generic-freebsd/sys/intr.h b/lib/libc/include/generic-freebsd/sys/intr.h index 665d96e5445b..9680dbe0bad4 100644 --- a/lib/libc/include/generic-freebsd/sys/intr.h +++ b/lib/libc/include/generic-freebsd/sys/intr.h @@ -33,10 +33,12 @@ #error Need INTRNG for this file #endif -#include +#include #define INTR_IRQ_INVALID 0xFFFFFFFF +#ifndef LOCORE + enum intr_map_data_type { INTR_MAP_DATA_ACPI = 0, INTR_MAP_DATA_FDT, @@ -110,12 +112,13 @@ u_int intr_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask); struct intr_pic *intr_pic_register(device_t, intptr_t); int intr_pic_deregister(device_t, intptr_t); -int intr_pic_claim_root(device_t, intptr_t, intr_irq_filter_t *, void *); +int intr_pic_claim_root(device_t, intptr_t, intr_irq_filter_t *, void *, + uint32_t); int intr_pic_add_handler(device_t, struct intr_pic *, intr_child_irq_filter_t *, void *, uintptr_t, uintptr_t); bool intr_is_per_cpu(struct resource *); -extern device_t intr_irq_root_dev; +device_t intr_irq_root_device(uint32_t); /* Intr interface for BUS. */ @@ -163,4 +166,9 @@ void intr_ipi_send(cpuset_t cpus, u_int ipi); void intr_ipi_dispatch(u_int ipi); #endif +/* Main interrupt handler called from asm on most archs except riscv. */ +void intr_irq_handler(struct trapframe *tf, uint32_t rootnum); + +#endif /* !LOCORE */ + #endif /* _SYS_INTR_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/ioccom.h b/lib/libc/include/generic-freebsd/sys/ioccom.h index 6beecbd3d1cc..c5c7497a473f 100644 --- a/lib/libc/include/generic-freebsd/sys/ioccom.h +++ b/lib/libc/include/generic-freebsd/sys/ioccom.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)ioccom.h 8.3 (Berkeley) 1/9/95 */ #ifndef _SYS_IOCCOM_H_ diff --git a/lib/libc/include/generic-freebsd/sys/ioctl.h b/lib/libc/include/generic-freebsd/sys/ioctl.h index f023f930a02f..8f729647742f 100644 --- a/lib/libc/include/generic-freebsd/sys/ioctl.h +++ b/lib/libc/include/generic-freebsd/sys/ioctl.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)ioctl.h 8.6 (Berkeley) 3/28/94 */ #ifndef _SYS_IOCTL_H_ diff --git a/lib/libc/include/generic-freebsd/sys/ioctl_compat.h b/lib/libc/include/generic-freebsd/sys/ioctl_compat.h index 2f8562ad7719..e552744ff084 100644 --- a/lib/libc/include/generic-freebsd/sys/ioctl_compat.h +++ b/lib/libc/include/generic-freebsd/sys/ioctl_compat.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)ioctl_compat.h 8.4 (Berkeley) 1/21/94 */ #ifndef _SYS_IOCTL_COMPAT_H_ diff --git a/lib/libc/include/generic-freebsd/sys/ipc.h b/lib/libc/include/generic-freebsd/sys/ipc.h index a1052d2a9bcf..b16820710277 100644 --- a/lib/libc/include/generic-freebsd/sys/ipc.h +++ b/lib/libc/include/generic-freebsd/sys/ipc.h @@ -37,8 +37,6 @@ * 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. - * - * @(#)ipc.h 8.4 (Berkeley) 2/19/95 */ /* diff --git a/lib/libc/include/generic-freebsd/sys/jail.h b/lib/libc/include/generic-freebsd/sys/jail.h index 9aff4f33bebf..a96c08ab82fa 100644 --- a/lib/libc/include/generic-freebsd/sys/jail.h +++ b/lib/libc/include/generic-freebsd/sys/jail.h @@ -99,8 +99,12 @@ enum prison_state { #define JAIL_UPDATE 0x02 /* Update parameters of existing jail */ #define JAIL_ATTACH 0x04 /* Attach to jail upon creation */ #define JAIL_DYING 0x08 /* Allow getting a dying jail */ -#define JAIL_SET_MASK 0x0f -#define JAIL_GET_MASK 0x08 +#define JAIL_USE_DESC 0x10 /* Get/set jail in descriptor */ +#define JAIL_AT_DESC 0x20 /* Find/add jail under descriptor */ +#define JAIL_GET_DESC 0x40 /* Return a new jail descriptor */ +#define JAIL_OWN_DESC 0x80 /* Return a new owning jail descriptor */ +#define JAIL_SET_MASK 0xff /* JAIL_DYING is deprecated/ignored here */ +#define JAIL_GET_MASK 0xf8 #define JAIL_SYS_DISABLE 0 #define JAIL_SYS_NEW 1 @@ -115,7 +119,9 @@ int jail(struct jail *); int jail_set(struct iovec *, unsigned int, int); int jail_get(struct iovec *, unsigned int, int); int jail_attach(int); +int jail_attach_jd(int); int jail_remove(int); +int jail_remove_jd(int); __END_DECLS #else /* _KERNEL */ @@ -141,6 +147,11 @@ MALLOC_DECLARE(M_PRISON); #define DEFAULT_HOSTUUID "00000000-0000-0000-0000-000000000000" #define OSRELEASELEN 32 +#define JAIL_META_PRIVATE "meta" +#define JAIL_META_SHARED "env" + +struct jaildesc; +struct knlist; struct racct; struct prison_racct; @@ -186,7 +197,9 @@ struct prison { struct vnode *pr_root; /* (c) vnode to rdir */ struct prison_ip *pr_addrs[PR_FAMILY_MAX]; /* (p,n) IPs of jail */ struct prison_racct *pr_prison_racct; /* (c) racct jail proxy */ - void *pr_sparep[3]; + struct knlist *pr_klist; /* (m) attached knotes */ + LIST_HEAD(, jaildesc) pr_descs; /* (a) attached descriptors */ + void *pr_sparep; int pr_childcount; /* (a) number of child jails */ int pr_childmax; /* (p) maximum child jails */ unsigned pr_allow; /* (p) PR_ALLOW_* flags */ @@ -253,13 +266,29 @@ struct prison_racct { #define PR_ALLOW_RESERVED_PORTS 0x00008000 #define PR_ALLOW_KMEM_ACCESS 0x00010000 /* reserved, not used yet */ #define PR_ALLOW_NFSD 0x00020000 -#define PR_ALLOW_ALL_STATIC 0x000387ff +#define PR_ALLOW_EXTATTR 0x00040000 +#define PR_ALLOW_ADJTIME 0x00080000 +#define PR_ALLOW_SETTIME 0x00100000 +#define PR_ALLOW_ROUTING 0x00200000 +#define PR_ALLOW_UNPRIV_PARENT_TAMPER 0x00400000 +#define PR_ALLOW_SETAUDIT 0x00800000 + +/* + * PR_ALLOW_PRISON0 are the allow flags that we apply by default to prison0, + * while PR_ALLOW_ALL_STATIC are all of the allow bits that we have allocated at + * build time. PR_ALLOW_ALL_STATIC should contain any bit above that we expect + * to be used on the system, while PR_ALLOW_PRISON0 will be some subset of that. + */ +#define PR_ALLOW_ALL_STATIC 0x00ff87ff +#define PR_ALLOW_PRISON0 \ + (PR_ALLOW_ALL_STATIC & ~(PR_ALLOW_UNPRIV_PARENT_TAMPER)) /* * PR_ALLOW_DIFFERENCES determines which flags are able to be * different between the parent and child jail upon creation. */ -#define PR_ALLOW_DIFFERENCES (PR_ALLOW_UNPRIV_DEBUG) +#define PR_ALLOW_DIFFERENCES \ + (PR_ALLOW_UNPRIV_DEBUG | PR_ALLOW_UNPRIV_PARENT_TAMPER) /* * OSD methods @@ -373,37 +402,45 @@ extern struct sx allprison_lock; /* * Sysctls to describe jail parameters. */ +SYSCTL_DECL(_security_jail); SYSCTL_DECL(_security_jail_param); +#define SYSCTL_JAIL_PARAM_DECL(name) \ + SYSCTL_DECL(_security_jail_param_##name) #define SYSCTL_JAIL_PARAM(module, param, type, fmt, descr) \ - SYSCTL_PROC(_security_jail_param ## module, OID_AUTO, param, \ - (type) | CTLFLAG_MPSAFE, NULL, 0, sysctl_jail_param, fmt, descr) + SYSCTL_PROC(_security_jail_param ## module, OID_AUTO, param, \ + (type) | CTLFLAG_MPSAFE, NULL, 0, sysctl_jail_param, fmt, descr) #define SYSCTL_JAIL_PARAM_STRING(module, param, access, len, descr) \ - SYSCTL_PROC(_security_jail_param ## module, OID_AUTO, param, \ - CTLTYPE_STRING | CTLFLAG_MPSAFE | (access), NULL, len, \ - sysctl_jail_param, "A", descr) -#define SYSCTL_JAIL_PARAM_STRUCT(module, param, access, len, fmt, descr)\ - SYSCTL_PROC(_security_jail_param ## module, OID_AUTO, param, \ - CTLTYPE_STRUCT | CTLFLAG_MPSAFE | (access), NULL, len, \ - sysctl_jail_param, fmt, descr) + SYSCTL_PROC(_security_jail_param ## module, OID_AUTO, param, \ + CTLTYPE_STRING | CTLFLAG_MPSAFE | (access), NULL, len, \ + sysctl_jail_param, "A", descr) +#define SYSCTL_JAIL_PARAM_STRUCT(module, param, access, len, fmt, descr) \ + SYSCTL_PROC(_security_jail_param ## module, OID_AUTO, param, \ + CTLTYPE_STRUCT | CTLFLAG_MPSAFE | (access), NULL, len, \ + sysctl_jail_param, fmt, descr) #define SYSCTL_JAIL_PARAM_NODE(module, descr) \ - SYSCTL_NODE(_security_jail_param, OID_AUTO, module, CTLFLAG_MPSAFE, \ - 0, descr) + SYSCTL_NODE(_security_jail_param, OID_AUTO, module, CTLFLAG_MPSAFE, \ + 0, descr) #define SYSCTL_JAIL_PARAM_SUBNODE(parent, module, descr) \ - SYSCTL_NODE(_security_jail_param_##parent, OID_AUTO, module, \ - CTLFLAG_MPSAFE, 0, descr) + SYSCTL_NODE(_security_jail_param_##parent, OID_AUTO, module, \ + CTLFLAG_MPSAFE, 0, descr) #define SYSCTL_JAIL_PARAM_SYS_NODE(module, access, descr) \ - SYSCTL_JAIL_PARAM_NODE(module, descr); \ - SYSCTL_JAIL_PARAM(_##module, , CTLTYPE_INT | (access), "E,jailsys", \ - descr) + SYSCTL_JAIL_PARAM_NODE(module, descr); \ + SYSCTL_JAIL_PARAM(_##module, , CTLTYPE_INT | (access), "E,jailsys", \ + descr) +#define SYSCTL_JAIL_PARAM_SYS_SUBNODE(parent, module, access, descr) \ + SYSCTL_JAIL_PARAM_SUBNODE(parent, module, descr); \ + SYSCTL_JAIL_PARAM(_##parent##_##module, , CTLTYPE_INT | (access), \ + "E,jailsys", descr) /* * Kernel support functions for jail(). */ -struct ucred; +struct knote; struct mount; struct sockaddr; struct statfs; +struct ucred; struct vfsconf; /* @@ -421,7 +458,7 @@ void prison0_init(void); bool prison_allow(struct ucred *, unsigned); int prison_check(struct ucred *cred1, struct ucred *cred2); bool prison_check_nfsd(struct ucred *cred); -bool prison_owns_vnet(struct ucred *); +bool prison_owns_vnet(struct prison *pr); int prison_canseemount(struct ucred *cred, struct mount *mp); void prison_enforce_statfs(struct ucred *cred, struct mount *mp, struct statfs *sp); @@ -438,6 +475,7 @@ void prison_proc_free(struct prison *); void prison_proc_link(struct prison *, struct proc *); void prison_proc_unlink(struct prison *, struct proc *); void prison_proc_iterate(struct prison *, void (*)(struct proc *, void *), void *); +void prison_remove(struct prison *); void prison_set_allow(struct ucred *cred, unsigned flag, int enable); bool prison_ischild(struct prison *, struct prison *); bool prison_isalive(const struct prison *); diff --git a/lib/libc/include/generic-freebsd/sys/jaildesc.h b/lib/libc/include/generic-freebsd/sys/jaildesc.h new file mode 100644 index 000000000000..31559478dcc9 --- /dev/null +++ b/lib/libc/include/generic-freebsd/sys/jaildesc.h @@ -0,0 +1,87 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 James Gritton. + * All rights reserved. + * + * This software was developed at the University of Cambridge Computer + * Laboratory with support from a grant from Google, Inc. + * + * 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 _SYS_JAILDESC_H_ +#define _SYS_JAILDESC_H_ + +#ifdef _KERNEL + +#include +#include +#include +#include +#include + +struct prison; + +/*- + * struct jaildesc describes a jail descriptor, which points to a struct + * prison. struct prison in turn has a linked list of struct jaildesc. + * + * Locking key: + * (c) set on creation, remains unchanged + * (d) jd_lock + * (p) jd_prison->pr_mtx + */ +struct jaildesc { + LIST_ENTRY(jaildesc) jd_list; /* (d,p) this prison's descs */ + struct prison *jd_prison; /* (d) the prison */ + struct mtx jd_lock; + struct selinfo jd_selinfo; /* (d) event notification */ + unsigned jd_flags; /* (d) JDF_* flags */ +}; + +/* + * Locking macros for the jaildesc. + */ +#define JAILDESC_LOCK_DESTROY(jd) mtx_destroy(&(jd)->jd_lock) +#define JAILDESC_LOCK_INIT(jd) mtx_init(&(jd)->jd_lock, "jaildesc", \ + NULL, MTX_DEF) +#define JAILDESC_LOCK(jd) mtx_lock(&(jd)->jd_lock) +#define JAILDESC_UNLOCK(jd) mtx_unlock(&(jd)->jd_lock) + +/* + * Flags for the jd_flags field + */ +#define JDF_SELECTED 0x00000001 /* issue selwakeup() */ +#define JDF_REMOVED 0x00000002 /* jail was removed */ +#define JDF_OWNING 0x00000004 /* closing descriptor removes jail */ + +int jaildesc_find(struct thread *td, int fd, struct prison **prp, + struct ucred **ucredp); +int jaildesc_alloc(struct thread *td, struct file **fpp, int *fdp, int owning); +void jaildesc_set_prison(struct file *jd, struct prison *pr); +void jaildesc_prison_cleanup(struct prison *pr); +void jaildesc_knote(struct prison *pr, long hint); + +#endif /* _KERNEL */ + +#endif /* !_SYS_JAILDESC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/kassert.h b/lib/libc/include/generic-freebsd/sys/kassert.h index 5524b5acb19f..d3f7655f9edf 100644 --- a/lib/libc/include/generic-freebsd/sys/kassert.h +++ b/lib/libc/include/generic-freebsd/sys/kassert.h @@ -31,12 +31,37 @@ #ifndef _SYS_KASSERT_H_ #define _SYS_KASSERT_H_ +#include #include #ifdef _KERNEL extern const char *panicstr; /* panic message */ -extern bool panicked; -#define KERNEL_PANICKED() __predict_false(panicked) +#define KERNEL_PANICKED() __predict_false(panicstr != NULL) + +/* + * Trap accesses going through a pointer. + * + * Sample usage: you have a struct with numerous fields and by API contract + * only some of them get populated, even if the implementation temporary writes + * to them. You can use DEBUG_POISON_POINTER so that the consumer which should + * no be looking at the field gets caught. + * + * DEBUG_POISON_POINTER(obj->ptr); + * .... + * if (obj->ptr->field) // traps + */ +#ifdef INVARIANTS + +extern void *poisoned_buf; +#define DEBUG_POISON_POINTER_VALUE poisoned_buf + +#define DEBUG_POISON_POINTER(x) ({ \ + x = (DEBUG_POISON_POINTER_VALUE); \ +}) + +#else +#define DEBUG_POISON_POINTER(x) +#endif #ifdef INVARIANTS /* The option is always available */ #define VNASSERT(exp, vp, msg) do { \ diff --git a/lib/libc/include/generic-freebsd/sys/kernel.h b/lib/libc/include/generic-freebsd/sys/kernel.h index 11a8383c310b..1415d4af070c 100644 --- a/lib/libc/include/generic-freebsd/sys/kernel.h +++ b/lib/libc/include/generic-freebsd/sys/kernel.h @@ -39,8 +39,6 @@ * 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. - * - * @(#)kernel.h 8.3 (Berkeley) 1/21/94 */ #ifndef _SYS_KERNEL_H_ @@ -67,7 +65,16 @@ extern int psratio; /* ratio: prof / stat */ extern int stathz; /* statistics clock's frequency */ extern int profhz; /* profiling clock's frequency */ extern int profprocs; /* number of process's profiling */ + +/* + * The ticks and ticksl symbols overlap, giving a 64-bit tick counter on 64-bit + * platforms while still maintaining compatibility with the legacy 32-bit + * counter. Either value can be used, but rollover must be handled; at 1000Hz, + * ticks (and ticksl on 32-bit platforms) roll over roughly every 25 days. On + * 64-bit platforms, ticksl will not roll over in the foreseeable future. + */ extern volatile int ticks; +extern volatile long ticksl; #endif /* _KERNEL */ @@ -86,16 +93,15 @@ extern volatile int ticks; * The SI_SUB_LAST value must have the highest lexical value. */ enum sysinit_sub_id { - SI_SUB_DUMMY = 0x0000000, /* not executed; for linker*/ - SI_SUB_DONE = 0x0000001, /* processed*/ + SI_SUB_DUMMY = 0x0000000, /* not executed; for linker */ SI_SUB_TUNABLES = 0x0700000, /* establish tunable values */ - SI_SUB_COPYRIGHT = 0x0800001, /* first use of console*/ + SI_SUB_COPYRIGHT = 0x0800001, /* first use of console */ SI_SUB_VM = 0x1000000, /* virtual memory system init */ SI_SUB_COUNTER = 0x1100000, /* counter(9) is initialized */ - SI_SUB_KMEM = 0x1800000, /* kernel memory*/ + SI_SUB_KMEM = 0x1800000, /* kernel memory */ SI_SUB_HYPERVISOR = 0x1A40000, /* * Hypervisor detection and - * virtualization support + * virtualization support * setup. */ SI_SUB_WITNESS = 0x1A80000, /* witness initialization */ @@ -105,7 +111,7 @@ enum sysinit_sub_id { SI_SUB_VNET_PRELINK = 0x1E00000, /* vnet init before modules */ SI_SUB_KLD = 0x2000000, /* KLD and module setup */ SI_SUB_KHELP = 0x2080000, /* khelp modules */ - SI_SUB_CPU = 0x2100000, /* CPU resource(s)*/ + SI_SUB_CPU = 0x2100000, /* CPU resource(s) */ SI_SUB_RACCT = 0x2110000, /* resource accounting */ SI_SUB_KDTRACE = 0x2140000, /* Kernel dtrace hooks */ SI_SUB_RANDOM = 0x2160000, /* random number generator */ @@ -113,21 +119,21 @@ enum sysinit_sub_id { SI_SUB_MAC_POLICY = 0x21C0000, /* TrustedBSD MAC policies */ SI_SUB_MAC_LATE = 0x21D0000, /* TrustedBSD MAC subsystem */ SI_SUB_VNET = 0x21E0000, /* vnet 0 */ - SI_SUB_INTRINSIC = 0x2200000, /* proc 0*/ - SI_SUB_VM_CONF = 0x2300000, /* config VM, set limits*/ + SI_SUB_INTRINSIC = 0x2200000, /* proc 0 */ + SI_SUB_VM_CONF = 0x2300000, /* config VM, set limits */ SI_SUB_DDB_SERVICES = 0x2380000, /* capture, scripting, etc. */ - SI_SUB_RUN_QUEUE = 0x2400000, /* set up run queue*/ + SI_SUB_RUN_QUEUE = 0x2400000, /* set up run queue */ SI_SUB_KTRACE = 0x2480000, /* ktrace */ SI_SUB_OPENSOLARIS = 0x2490000, /* OpenSolaris compatibility */ SI_SUB_AUDIT = 0x24C0000, /* audit */ - SI_SUB_CREATE_INIT = 0x2500000, /* create init process*/ + SI_SUB_CREATE_INIT = 0x2500000, /* create init process */ SI_SUB_SCHED_IDLE = 0x2600000, /* required idle procs */ SI_SUB_MBUF = 0x2700000, /* mbuf subsystem */ SI_SUB_INTR = 0x2800000, /* interrupt threads */ SI_SUB_TASKQ = 0x2880000, /* task queues */ SI_SUB_EPOCH = 0x2888000, /* epoch subsystem */ #ifdef EARLY_AP_STARTUP - SI_SUB_SMP = 0x2900000, /* start the APs*/ + SI_SUB_SMP = 0x2900000, /* start the APs */ #endif SI_SUB_SOFTINTR = 0x2A00000, /* start soft interrupt thread */ SI_SUB_DEVFS = 0x2F00000, /* devfs ready for devices */ @@ -138,40 +144,40 @@ enum sysinit_sub_id { SI_SUB_DTRACE_ANON = 0x308C000, /* DTrace anon enabling */ SI_SUB_DRIVERS = 0x3100000, /* Let Drivers initialize */ SI_SUB_CONFIGURE = 0x3800000, /* Configure devices */ - SI_SUB_VFS = 0x4000000, /* virtual filesystem*/ - SI_SUB_CLOCKS = 0x4800000, /* real time and stat clocks*/ - SI_SUB_SYSV_SHM = 0x6400000, /* System V shared memory*/ - SI_SUB_SYSV_SEM = 0x6800000, /* System V semaphores*/ - SI_SUB_SYSV_MSG = 0x6C00000, /* System V message queues*/ + SI_SUB_VFS = 0x4000000, /* virtual filesystem */ + SI_SUB_CLOCKS = 0x4800000, /* real time and stat clocks */ + SI_SUB_SYSV_SHM = 0x6400000, /* System V shared memory */ + SI_SUB_SYSV_SEM = 0x6800000, /* System V semaphores */ + SI_SUB_SYSV_MSG = 0x6C00000, /* System V message queues */ SI_SUB_P1003_1B = 0x6E00000, /* P1003.1B realtime */ - SI_SUB_PSEUDO = 0x7000000, /* pseudo devices*/ + SI_SUB_PSEUDO = 0x7000000, /* pseudo devices */ SI_SUB_EXEC = 0x7400000, /* execve() handlers */ SI_SUB_PROTO_BEGIN = 0x8000000, /* VNET initialization */ SI_SUB_PROTO_PFIL = 0x8100000, /* Initialize pfil before FWs */ - SI_SUB_PROTO_IF = 0x8400000, /* interfaces*/ + SI_SUB_PROTO_IF = 0x8400000, /* interfaces */ SI_SUB_PROTO_DOMAININIT = 0x8600000, /* domain registration system */ SI_SUB_PROTO_MC = 0x8700000, /* Multicast */ - SI_SUB_PROTO_DOMAIN = 0x8800000, /* domains (address families?)*/ + SI_SUB_PROTO_DOMAIN = 0x8800000, /* domains (address families?) */ SI_SUB_PROTO_FIREWALL = 0x8806000, /* Firewalls */ SI_SUB_PROTO_IFATTACHDOMAIN = 0x8808000,/* domain dependent data init */ SI_SUB_PROTO_END = 0x8ffffff, /* VNET helper functions */ - SI_SUB_KPROF = 0x9000000, /* kernel profiling*/ - SI_SUB_KICK_SCHEDULER = 0xa000000, /* start the timeout events*/ + SI_SUB_KPROF = 0x9000000, /* kernel profiling */ + SI_SUB_KICK_SCHEDULER = 0xa000000, /* start the timeout events */ SI_SUB_INT_CONFIG_HOOKS = 0xa800000, /* Interrupts enabled config */ SI_SUB_ROOT_CONF = 0xb000000, /* Find root devices */ - SI_SUB_INTRINSIC_POST = 0xd000000, /* proc 0 cleanup*/ + SI_SUB_INTRINSIC_POST = 0xd000000, /* proc 0 cleanup */ SI_SUB_SYSCALLS = 0xd800000, /* register system calls */ SI_SUB_VNET_DONE = 0xdc00000, /* vnet registration complete */ - SI_SUB_KTHREAD_INIT = 0xe000000, /* init process*/ - SI_SUB_KTHREAD_PAGE = 0xe400000, /* pageout daemon*/ - SI_SUB_KTHREAD_VM = 0xe800000, /* vm daemon*/ - SI_SUB_KTHREAD_BUF = 0xea00000, /* buffer daemon*/ - SI_SUB_KTHREAD_UPDATE = 0xec00000, /* update daemon*/ - SI_SUB_KTHREAD_IDLE = 0xee00000, /* idle procs*/ + SI_SUB_KTHREAD_INIT = 0xe000000, /* init process */ + SI_SUB_KTHREAD_PAGE = 0xe400000, /* pageout daemon */ + SI_SUB_KTHREAD_VM = 0xe800000, /* vm daemon */ + SI_SUB_KTHREAD_BUF = 0xea00000, /* buffer daemon */ + SI_SUB_KTHREAD_UPDATE = 0xec00000, /* update daemon */ + SI_SUB_KTHREAD_IDLE = 0xee00000, /* idle procs */ #ifndef EARLY_AP_STARTUP - SI_SUB_SMP = 0xf000000, /* start the APs*/ -#endif - SI_SUB_RACCTD = 0xf100000, /* start racctd*/ + SI_SUB_SMP = 0xf000000, /* start the APs */ +#endif + SI_SUB_RACCTD = 0xf100000, /* start racctd */ SI_SUB_LAST = 0xfffffff /* final initialization */ }; @@ -179,16 +185,16 @@ enum sysinit_sub_id { * Some enumerated orders; "ANY" sorts last. */ enum sysinit_elem_order { - SI_ORDER_FIRST = 0x0000000, /* first*/ - SI_ORDER_SECOND = 0x0000001, /* second*/ - SI_ORDER_THIRD = 0x0000002, /* third*/ - SI_ORDER_FOURTH = 0x0000003, /* fourth*/ - SI_ORDER_FIFTH = 0x0000004, /* fifth*/ - SI_ORDER_SIXTH = 0x0000005, /* sixth*/ - SI_ORDER_SEVENTH = 0x0000006, /* seventh*/ - SI_ORDER_EIGHTH = 0x0000007, /* eighth*/ + SI_ORDER_FIRST = 0x0000000, /* first */ + SI_ORDER_SECOND = 0x0000001, /* second */ + SI_ORDER_THIRD = 0x0000002, /* third */ + SI_ORDER_FOURTH = 0x0000003, /* fourth */ + SI_ORDER_FIFTH = 0x0000004, /* fifth */ + SI_ORDER_SIXTH = 0x0000005, /* sixth */ + SI_ORDER_SEVENTH = 0x0000006, /* seventh */ + SI_ORDER_EIGHTH = 0x0000007, /* eighth */ SI_ORDER_MIDDLE = 0x1000000, /* somewhere in the middle */ - SI_ORDER_ANY = 0xfffffff /* last*/ + SI_ORDER_ANY = 0xfffffff /* last */ }; /* @@ -218,10 +224,10 @@ typedef void (*sysinit_nfunc_t)(void *); typedef void (*sysinit_cfunc_t)(const void *); struct sysinit { - enum sysinit_sub_id subsystem; /* subsystem identifier*/ - enum sysinit_elem_order order; /* init order within subsystem*/ + enum sysinit_sub_id subsystem; /* subsystem identifier */ + enum sysinit_elem_order order; /* init order within subsystem */ STAILQ_ENTRY(sysinit) next; /* singly-linked list */ - sysinit_cfunc_t func; /* function */ + sysinit_cfunc_t func; /* function */ const void *udata; /* multiplexer/argument */ }; @@ -240,18 +246,11 @@ struct sysinit { #ifdef TSLOG struct sysinit_tslog { sysinit_cfunc_t func; - const void * data; - const char * name; + const void *data; + const char *name; }; -static inline void -sysinit_tslog_shim(const void * data) -{ - const struct sysinit_tslog * x = data; - - TSRAW(curthread, TS_ENTER, "SYSINIT", x->name); - (x->func)(x->data); - TSRAW(curthread, TS_EXIT, "SYSINIT", x->name); -} +void sysinit_tslog_shim(const void *); + #define C_SYSINIT(uniquifier, subsystem, order, func, ident) \ static struct sysinit_tslog uniquifier ## _sys_init_tslog = { \ func, \ @@ -265,7 +264,7 @@ sysinit_tslog_shim(const void * data) sysinit_tslog_shim, \ &uniquifier ## _sys_init_tslog \ }; \ - DATA_WSET(sysinit_set,uniquifier ## _sys_init) + DATA_WSET(sysinit_set, uniquifier ## _sys_init) #else #define C_SYSINIT(uniquifier, subsystem, order, func, ident) \ static struct sysinit uniquifier ## _sys_init = { \ @@ -275,7 +274,7 @@ sysinit_tslog_shim(const void * data) func, \ (ident) \ }; \ - DATA_WSET(sysinit_set,uniquifier ## _sys_init) + DATA_WSET(sysinit_set, uniquifier ## _sys_init) #endif #define SYSINIT(uniquifier, subsystem, order, func, ident) \ @@ -293,7 +292,7 @@ sysinit_tslog_shim(const void * data) func, \ (ident) \ }; \ - DATA_WSET(sysuninit_set,uniquifier ## _sys_uninit) + DATA_WSET(sysuninit_set, uniquifier ## _sys_uninit) #define SYSUNINIT(uniquifier, subsystem, order, func, ident) \ C_SYSUNINIT(uniquifier, subsystem, order, \ @@ -316,7 +315,7 @@ void sysinit_add(struct sysinit **set, struct sysinit **set_end); * int * please avoid using for new tunables! */ -extern void tunable_int_init(void *); +extern void tunable_int_init(const void *); struct tunable_int { const char *path; int *var; @@ -335,7 +334,7 @@ struct tunable_int { /* * long */ -extern void tunable_long_init(void *); +extern void tunable_long_init(const void *); struct tunable_long { const char *path; long *var; @@ -354,7 +353,7 @@ struct tunable_long { /* * unsigned long */ -extern void tunable_ulong_init(void *); +extern void tunable_ulong_init(const void *); struct tunable_ulong { const char *path; unsigned long *var; @@ -373,7 +372,7 @@ struct tunable_ulong { /* * int64_t */ -extern void tunable_int64_init(void *); +extern void tunable_int64_init(const void *); struct tunable_int64 { const char *path; int64_t *var; @@ -392,7 +391,7 @@ struct tunable_int64 { /* * uint64_t */ -extern void tunable_uint64_init(void *); +extern void tunable_uint64_init(const void *); struct tunable_uint64 { const char *path; uint64_t *var; @@ -411,7 +410,7 @@ struct tunable_uint64 { /* * quad */ -extern void tunable_quad_init(void *); +extern void tunable_quad_init(const void *); struct tunable_quad { const char *path; quad_t *var; @@ -430,7 +429,7 @@ struct tunable_quad { /* * bool */ -extern void tunable_bool_init(void *); +extern void tunable_bool_init(const void *); struct tunable_bool { const char *path; bool *var; @@ -446,7 +445,7 @@ struct tunable_bool { #define TUNABLE_BOOL_FETCH(path, var) getenv_bool((path), (var)) -extern void tunable_str_init(void *); +extern void tunable_str_init(const void *); struct tunable_str { const char *path; char *var; diff --git a/lib/libc/include/generic-freebsd/sys/kerneldump.h b/lib/libc/include/generic-freebsd/sys/kerneldump.h index 2408d1e824d7..10d8dd17964b 100644 --- a/lib/libc/include/generic-freebsd/sys/kerneldump.h +++ b/lib/libc/include/generic-freebsd/sys/kerneldump.h @@ -161,6 +161,7 @@ void dumpsys_pb_progress(size_t); extern int do_minidump; int livedump_start(int, int, uint8_t); +int livedump_start_vnode(struct vnode *, int, uint8_t); /* Live minidump events */ typedef void (*livedump_start_fn)(void *arg, int *errorp); diff --git a/lib/libc/include/generic-freebsd/sys/ktls.h b/lib/libc/include/generic-freebsd/sys/ktls.h index 2ee0e354732a..62ce2ba82ed3 100644 --- a/lib/libc/include/generic-freebsd/sys/ktls.h +++ b/lib/libc/include/generic-freebsd/sys/ktls.h @@ -28,8 +28,11 @@ #define _SYS_KTLS_H_ #ifdef _KERNEL +#include #include #include + +#include #endif struct tls_record_layer { @@ -142,6 +145,28 @@ struct tls_get_record { uint16_t tls_length; }; +#define XKTLS_SESSION_IV_BUF_LEN 32 +struct xktls_session_onedir { + uint64_t gen; + uint64_t rsrv1[8]; + uint32_t rsrv2[8]; + uint8_t iv[XKTLS_SESSION_IV_BUF_LEN]; + int cipher_algorithm; + int auth_algorithm; + uint16_t cipher_key_len; + uint16_t iv_len; + uint16_t auth_key_len; + uint16_t max_frame_len; + uint8_t tls_vmajor; + uint8_t tls_vminor; + uint8_t tls_hlen; + uint8_t tls_tlen; + uint8_t tls_bs; + uint8_t flags; + uint16_t drv_st_len; + char ifnet[16]; /* IFNAMSIZ */ +}; + #ifdef _KERNEL struct tls_session_params { @@ -174,6 +199,7 @@ struct m_snd_tag; struct mbuf; struct sockbuf; struct socket; +struct sockopt; struct ktls_session { struct ktls_ocf_session *ocf_session; @@ -202,6 +228,8 @@ struct ktls_session { /* Used to destroy any kTLS session */ struct task destroy_task; + + uint64_t gen; } __aligned(CACHE_LINE_SIZE); extern unsigned int ktls_ifnet_max_rexmit_pct; @@ -213,27 +241,29 @@ typedef enum { } ktls_mbuf_crypto_st_t; void ktls_check_rx(struct sockbuf *sb); -ktls_mbuf_crypto_st_t ktls_mbuf_crypto_state(struct mbuf *mb, int offset, int len); +void ktls_cleanup_tls_enable(struct tls_enable *tls); +int ktls_copyin_tls_enable(struct sockopt *sopt, struct tls_enable *tls); void ktls_disable_ifnet(void *arg); int ktls_enable_rx(struct socket *so, struct tls_enable *en); int ktls_enable_tx(struct socket *so, struct tls_enable *en); +void ktls_enqueue(struct mbuf *m, struct socket *so, int page_count); +void ktls_enqueue_to_free(struct mbuf *m); void ktls_destroy(struct ktls_session *tls); void ktls_frame(struct mbuf *m, struct ktls_session *tls, int *enqueue_cnt, uint8_t record_type); -bool ktls_permit_empty_frames(struct ktls_session *tls); -void ktls_seq(struct sockbuf *sb, struct mbuf *m); -void ktls_enqueue(struct mbuf *m, struct socket *so, int page_count); -void ktls_enqueue_to_free(struct mbuf *m); int ktls_get_rx_mode(struct socket *so, int *modep); -int ktls_set_tx_mode(struct socket *so, int mode); int ktls_get_tx_mode(struct socket *so, int *modep); int ktls_get_rx_sequence(struct inpcb *inp, uint32_t *tcpseq, uint64_t *tlsseq); void ktls_input_ifp_mismatch(struct sockbuf *sb, struct ifnet *ifp); -int ktls_output_eagain(struct inpcb *inp, struct ktls_session *tls); +ktls_mbuf_crypto_st_t ktls_mbuf_crypto_state(struct mbuf *mb, int offset, int len); #ifdef RATELIMIT int ktls_modify_txrtlmt(struct ktls_session *tls, uint64_t max_pacing_rate); #endif +int ktls_output_eagain(struct inpcb *inp, struct ktls_session *tls); bool ktls_pending_rx_info(struct sockbuf *sb, uint64_t *seqnop, size_t *residp); +bool ktls_permit_empty_frames(struct ktls_session *tls); +void ktls_seq(struct sockbuf *sb, struct mbuf *m); +int ktls_set_tx_mode(struct socket *so, int mode); static inline struct ktls_session * ktls_hold(struct ktls_session *tls) @@ -252,5 +282,10 @@ ktls_free(struct ktls_session *tls) ktls_destroy(tls); } +void ktls_session_to_xktls_onedir(const struct ktls_session *ks, + bool export_keys, struct xktls_session_onedir *xktls_od); +void ktls_session_copy_keys(const struct ktls_session *ktls, + uint8_t *data, size_t *sz); + #endif /* !_KERNEL */ #endif /* !_SYS_KTLS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/ktrace.h b/lib/libc/include/generic-freebsd/sys/ktrace.h index 8f57b9007cc6..e4596a212ddf 100644 --- a/lib/libc/include/generic-freebsd/sys/ktrace.h +++ b/lib/libc/include/generic-freebsd/sys/ktrace.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)ktrace.h 8.1 (Berkeley) 6/2/93 */ #ifndef _SYS_KTRACE_H_ @@ -38,6 +36,7 @@ #include #include #include +#include #include /* @@ -89,10 +88,9 @@ struct ktr_header { * is the public interface. */ #define KTRCHECK(td, type) ((td)->td_proc->p_traceflag & (1 << type)) -#define KTRPOINT(td, type) (__predict_false(KTRCHECK((td), (type)))) -#define KTRCHECKDRAIN(td) (!(STAILQ_EMPTY(&(td)->td_proc->p_ktr))) +#define KTRPOINT(td, type) (__predict_false(KTRCHECK((td), (type)))) #define KTRUSERRET(td) do { \ - if (__predict_false(KTRCHECKDRAIN(td))) \ + if (__predict_false(!STAILQ_EMPTY_ATOMIC(&(td)->td_proc->p_ktr))) \ ktruserret(td); \ } while (0) @@ -265,6 +263,24 @@ struct ktr_struct_array { */ }; +/* + * KTR_ARGS - arguments of execve() + */ +#define KTR_ARGS 16 + +/* + * KTR_ENVS - environment variables of execve() + */ +#define KTR_ENVS 17 + +/* + * KTR_EXTERR - extended error reported + */ +#define KTR_EXTERR 18 +struct ktr_exterr { + struct uexterror ue; +}; + /* * KTR_DROP - If this bit is set in ktr_type, then at least one event * between the previous record and this record was dropped. @@ -297,6 +313,9 @@ struct ktr_struct_array { #define KTRFAC_FAULT (1< #include #ifdef _KERNEL #include #endif +#include #ifndef LIBKERN_INLINE #define LIBKERN_INLINE static __inline @@ -189,6 +187,49 @@ flsll(long long mask) 8 * sizeof(mask) - __builtin_clzll((unsigned long long)mask)); } +static __inline __pure2 int +ilog2_int(int n) +{ + + KASSERT(n != 0, ("ilog argument must be nonzero")); + return (8 * sizeof(n) - 1 - __builtin_clz((u_int)n)); +} + +static __inline __pure2 int +ilog2_long(long n) +{ + + KASSERT(n != 0, ("ilog argument must be nonzero")); + return (8 * sizeof(n) - 1 - __builtin_clzl((u_long)n)); +} + +static __inline __pure2 int +ilog2_long_long(long long n) +{ + + KASSERT(n != 0, ("ilog argument must be nonzero")); + return (8 * sizeof(n) - 1 - + __builtin_clzll((unsigned long long)n)); +} + +#define ilog2_var(n) \ + _Generic((n), \ + default: ilog2_int, \ + long: ilog2_long, \ + unsigned long: ilog2_long, \ + long long: ilog2_long_long, \ + unsigned long long: ilog2_long_long \ + )(n) + +#define ilog2_const(n) \ + (8 * (int)sizeof(unsigned long long) - 1 - \ + __builtin_clzll(n)) + +#define ilog2(n) (__builtin_constant_p(n) ? ilog2_const(n) : ilog2_var(n)) +#define rounddown_pow_of_two(n) ((__typeof(n))1 << ilog2(n)) +#define order_base_2(n) ilog2(2*(n)-1) +#define roundup_pow_of_two(n) ((__typeof(n))1 << order_base_2(n)) + #define bitcount64(x) __bitcount64((uint64_t)(x)) #define bitcount32(x) __bitcount32((uint32_t)(x)) #define bitcount16(x) __bitcount16((uint16_t)(x)) @@ -293,4 +334,10 @@ signed_extend32(uint32_t bitmap, int lsb, int width) #define FNM_IGNORECASE FNM_CASEFOLD #define FNM_FILE_NAME FNM_PATHNAME +#if !defined(_KERNEL) && __has_include() +#include /* __ssp_real */ +#else +#define __ssp_real(fun) fun +#endif + #endif /* !_SYS_LIBKERN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/link_elf.h b/lib/libc/include/generic-freebsd/sys/link_elf.h index fc66b1dd5fc4..531e56504b77 100644 --- a/lib/libc/include/generic-freebsd/sys/link_elf.h +++ b/lib/libc/include/generic-freebsd/sys/link_elf.h @@ -93,10 +93,12 @@ struct dl_phdr_info __BEGIN_DECLS typedef int (*__dl_iterate_hdr_callback)(struct dl_phdr_info *, size_t, void *); -extern int dl_iterate_phdr(__dl_iterate_hdr_callback, void *); +int dl_iterate_phdr(__dl_iterate_hdr_callback, void *); int _rtld_addr_phdr(const void *, struct dl_phdr_info *); int _rtld_get_stack_prot(void); int _rtld_is_dlopened(void *); +const char *rtld_get_var(const char *name); +int rtld_set_var(const char *name, const char *val); #ifdef __ARM_EABI__ void * dl_unwind_find_exidx(const void *, int *); diff --git a/lib/libc/include/generic-freebsd/sys/linker.h b/lib/libc/include/generic-freebsd/sys/linker.h index 526ac3765c36..ba68128470ef 100644 --- a/lib/libc/include/generic-freebsd/sys/linker.h +++ b/lib/libc/include/generic-freebsd/sys/linker.h @@ -29,6 +29,8 @@ #ifndef _SYS_LINKER_H_ #define _SYS_LINKER_H_ +#include + #ifdef _KERNEL #include @@ -130,6 +132,12 @@ typedef int linker_predicate_t(linker_file_t, void *); */ extern linker_file_t linker_kernel_file; +/* + * Special symbol which will be replaced by a reference to the linker_file_t + * of the module it is used in. + */ +extern linker_file_t __this_linker_file; + /* * Obtain a reference to a module, loading it if required. */ @@ -212,6 +220,14 @@ void linker_kldload_unbusy(int flags); #endif /* _KERNEL */ +/* + * ELF file types + */ +#define KERNTYPE_MB "elf multiboot kernel" +#define KERNTYPE "elf kernel" +#define MODTYPE_OBJ "elf obj module" +#define MODTYPE "elf module" + /* * Module information subtypes */ @@ -264,7 +280,10 @@ void linker_kldload_unbusy(int flags); * Module lookup */ extern vm_offset_t preload_addr_relocate; -extern caddr_t preload_metadata; +extern caddr_t preload_metadata, preload_kmdp; +extern const char preload_modtype[]; +extern const char preload_kerntype[]; +extern const char preload_modtype_obj[]; extern void * preload_fetch_addr(caddr_t _mod); extern size_t preload_fetch_size(caddr_t _mod); @@ -272,6 +291,7 @@ extern caddr_t preload_search_by_name(const char *_name); extern caddr_t preload_search_by_type(const char *_type); extern caddr_t preload_search_next_name(caddr_t _base); extern caddr_t preload_search_info(caddr_t _mod, int _inf); +extern void preload_initkmdp(bool _fatal); extern void preload_delete_name(const char *_name); extern void preload_bootstrap_relocate(vm_offset_t _offset); extern void preload_dump(void); @@ -304,7 +324,7 @@ int elf_reloc_local(linker_file_t _lf, Elf_Addr base, const void *_rel, Elf_Addr elf_relocaddr(linker_file_t _lf, Elf_Addr addr); const Elf_Sym *elf_get_sym(linker_file_t _lf, Elf_Size _symidx); const char *elf_get_symname(linker_file_t _lf, Elf_Size _symidx); -void link_elf_ireloc(caddr_t kmdp); +void link_elf_ireloc(void); #if defined(__aarch64__) || defined(__amd64__) int elf_reloc_late(linker_file_t _lf, Elf_Addr base, const void *_rel, @@ -325,6 +345,9 @@ typedef struct linker_ctf { } linker_ctf_t; int linker_ctf_get(linker_file_t, linker_ctf_t *); +int linker_ctf_lookup_sym_ddb(const char *symname, c_linker_sym_t *sym, + linker_ctf_t *lc); +int linker_ctf_lookup_typename_ddb(linker_ctf_t *lc, const char *typename); int elf_cpu_load_file(linker_file_t); int elf_cpu_unload_file(linker_file_t); diff --git a/lib/libc/include/generic-freebsd/sys/lock.h b/lib/libc/include/generic-freebsd/sys/lock.h index 2c153b0132ca..c6f38c346396 100644 --- a/lib/libc/include/generic-freebsd/sys/lock.h +++ b/lib/libc/include/generic-freebsd/sys/lock.h @@ -66,6 +66,7 @@ struct lock_class { int (*lc_owner)(const struct lock_object *lock, struct thread **owner); uintptr_t (*lc_unlock)(struct lock_object *lock); + int (*lc_trylock)(struct lock_object *lock, uintptr_t how); }; #define LC_SLEEPLOCK 0x00000001 /* Sleep lock. */ diff --git a/lib/libc/include/generic-freebsd/sys/lockf.h b/lib/libc/include/generic-freebsd/sys/lockf.h index 035099886ebb..58e197bffb37 100644 --- a/lib/libc/include/generic-freebsd/sys/lockf.h +++ b/lib/libc/include/generic-freebsd/sys/lockf.h @@ -30,8 +30,6 @@ * 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. - * - * @(#)lockf.h 8.1 (Berkeley) 6/11/93 */ #ifndef _SYS_LOCKF_H_ diff --git a/lib/libc/include/generic-freebsd/sys/lockmgr.h b/lib/libc/include/generic-freebsd/sys/lockmgr.h index 76f18a80bebe..cbed90ce98cc 100644 --- a/lib/libc/include/generic-freebsd/sys/lockmgr.h +++ b/lib/libc/include/generic-freebsd/sys/lockmgr.h @@ -130,6 +130,10 @@ _lockmgr_args_rw(struct lock *lk, u_int flags, struct rwlock *ilk, LOCK_FILE, LOCK_LINE) #define lockmgr_disown(lk) \ _lockmgr_disown((lk), LOCK_FILE, LOCK_LINE) +#define lockmgr_disowned_v(v) \ + (LK_HOLDER((v)) == LK_KERNPROC) +#define lockmgr_disowned(lk) \ + lockmgr_disowned_v(lockmgr_read_value((lk))) #define lockmgr_recursed_v(v) \ (v & LK_WRITER_RECURSED) #define lockmgr_recursed(lk) \ diff --git a/lib/libc/include/generic-freebsd/sys/mac.h b/lib/libc/include/generic-freebsd/sys/mac.h index 8dedb9f17dff..11c38b55668e 100644 --- a/lib/libc/include/generic-freebsd/sys/mac.h +++ b/lib/libc/include/generic-freebsd/sys/mac.h @@ -47,6 +47,13 @@ #ifndef _SYS_MAC_H_ #define _SYS_MAC_H_ +#include + +#ifndef _SIZE_T_DECLARED +typedef __size_t size_t; +#define _SIZE_T_DECLARED +#endif + #ifndef _POSIX_MAC #define _POSIX_MAC #endif @@ -72,6 +79,13 @@ typedef struct mac *mac_t; #ifndef _KERNEL +#include /* For __BEGIN_DECLS and __END_DECLS. */ + +#ifndef _PID_T_DECLARED +typedef __pid_t pid_t; /* process id */ +#define _PID_T_DECLARED +#endif + /* * Location of the userland MAC framework configuration file. mac.conf * set defaults for MAC-aware applications. diff --git a/lib/libc/include/generic-freebsd/sys/malloc.h b/lib/libc/include/generic-freebsd/sys/malloc.h index ec13eb3d2ca0..ee47ef204162 100644 --- a/lib/libc/include/generic-freebsd/sys/malloc.h +++ b/lib/libc/include/generic-freebsd/sys/malloc.h @@ -29,8 +29,6 @@ * 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. - * - * @(#)malloc.h 8.5 (Berkeley) 5/3/95 */ #ifndef _SYS_MALLOC_H_ @@ -62,8 +60,9 @@ #define M_BESTFIT 0x2000 /* only for vmem, low fragmentation */ #define M_EXEC 0x4000 /* allocate executable space */ #define M_NEXTFIT 0x8000 /* only for vmem, follow cursor */ +#define M_NEVERFREED 0x10000 /* chunk will never get freed */ -#define M_VERSION 2020110501 +#define M_VERSION 2024073001 /* * Two malloc type structures are present: malloc_type, which is used by a @@ -159,6 +158,9 @@ struct malloc_type_header { MALLOC_DECLARE(M_CACHE); MALLOC_DECLARE(M_DEVBUF); +MALLOC_DECLARE(M_PARGS); +MALLOC_DECLARE(M_SESSION); +MALLOC_DECLARE(M_SUBPROC); MALLOC_DECLARE(M_TEMP); /* @@ -176,7 +178,8 @@ extern struct mtx malloc_mtx; */ typedef void malloc_type_list_func_t(struct malloc_type *, void *); -void contigfree(void *addr, unsigned long size, struct malloc_type *type); +/* contigfree(9) is deprecated. */ +void contigfree(void *addr, unsigned long, struct malloc_type *type); void *contigmalloc(unsigned long size, struct malloc_type *type, int flags, vm_paddr_t low, vm_paddr_t high, unsigned long alignment, vm_paddr_t boundary) __malloc_like __result_use_check diff --git a/lib/libc/include/generic-freebsd/sys/mbuf.h b/lib/libc/include/generic-freebsd/sys/mbuf.h index 50ad174d57f6..2fff2e53e9e6 100644 --- a/lib/libc/include/generic-freebsd/sys/mbuf.h +++ b/lib/libc/include/generic-freebsd/sys/mbuf.h @@ -28,8 +28,6 @@ * 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. - * - * @(#)mbuf.h 8.5 (Berkeley) 2/19/95 */ #ifndef _SYS_MBUF_H_ @@ -596,6 +594,7 @@ m_epg_pagelen(const struct mbuf *m, int pidx, int pgoff) #define EXT_PACKET 6 /* mbuf+cluster from packet zone */ #define EXT_MBUF 7 /* external mbuf reference */ #define EXT_RXRING 8 /* data in NIC receive ring */ +#define EXT_CTL 9 /* buffer from a ctl(4) backend */ #define EXT_VENDOR1 224 /* for vendor-internal use */ #define EXT_VENDOR2 225 /* for vendor-internal use */ @@ -642,16 +641,15 @@ m_epg_pagelen(const struct mbuf *m, int pidx, int pgoff) /* * Flags indicating checksum, segmentation and other offload work to be - * done, or already done, by hardware or lower layers. It is split into - * separate inbound and outbound flags. + * done, or already done, by hardware or lower layers. * - * Outbound flags that are set by upper protocol layers requesting lower + * Flags that are set by upper protocol layers requesting lower * layers, or ideally the hardware, to perform these offloading tasks. - * For outbound packets this field and its flags can be directly tested - * against ifnet if_hwassist. Note that the outbound and the inbound flags do - * not collide right now but they could be allowed to (as long as the flags are - * scrubbed appropriately when the direction of an mbuf changes). CSUM_BITS - * would also have to split into CSUM_BITS_TX and CSUM_BITS_RX. + * Before passing packets to a network interface this field and its flags can + * be directly tested against ifnet if_hwassist. Note that the flags + * CSUM_IP_SCTP, CSUM_IP_TCP, and CSUM_IP_UDP can appear on input processing + * of SCTP, TCP, and UDP. In such a case the checksum will not be computed or + * validated by SCTP, TCP, or TCP, since the packet has not been on the wire. * * CSUM_INNER_ is the same as CSUM_ but it applies to the inner frame. * The CSUM_ENCAP_ bits identify the outer encapsulation. @@ -680,7 +678,7 @@ m_epg_pagelen(const struct mbuf *m, int pidx, int pgoff) #define CSUM_ENCAP_VXLAN 0x00040000 /* VXLAN outer encapsulation */ #define CSUM_ENCAP_RSVD1 0x00080000 -/* Inbound checksum support where the checksum was verified by hardware. */ +/* Flags used to indicate that the checksum was verified by hardware. */ #define CSUM_INNER_L3_CALC 0x00100000 #define CSUM_INNER_L3_VALID 0x00200000 #define CSUM_INNER_L4_CALC 0x00400000 @@ -809,12 +807,12 @@ void mb_dupcl(struct mbuf *, struct mbuf *); void mb_free_ext(struct mbuf *); void mb_free_extpg(struct mbuf *); void mb_free_mext_pgs(struct mbuf *); -struct mbuf *mb_alloc_ext_pgs(int, m_ext_free_t); +struct mbuf *mb_alloc_ext_pgs(int, m_ext_free_t, int); struct mbuf *mb_alloc_ext_plus_pages(int, int); struct mbuf *mb_mapped_to_unmapped(struct mbuf *, int, int, int, struct mbuf **); int mb_unmapped_compress(struct mbuf *m); -struct mbuf *mb_unmapped_to_ext(struct mbuf *m); +int mb_unmapped_to_ext(struct mbuf *m, struct mbuf **mres); void mb_free_notready(struct mbuf *m, int count); void m_adj(struct mbuf *, int); void m_adj_decap(struct mbuf *, int); @@ -886,9 +884,11 @@ m_gettype(int size) case MCLBYTES: type = EXT_CLUSTER; break; +#if MJUMPAGESIZE != MCLBYTES case MJUMPAGESIZE: type = EXT_JUMBOP; break; +#endif case MJUM9BYTES: type = EXT_JUMBO9; break; @@ -934,9 +934,11 @@ m_getzone(int size) case MCLBYTES: zone = zone_clust; break; +#if MJUMPAGESIZE != MCLBYTES case MJUMPAGESIZE: zone = zone_jumbop; break; +#endif case MJUM9BYTES: zone = zone_jumbo9; break; @@ -1056,9 +1058,11 @@ m_cljset(struct mbuf *m, void *cl, int type) case EXT_CLUSTER: size = MCLBYTES; break; +#if MJUMPAGESIZE != MCLBYTES case EXT_JUMBOP: size = MJUMPAGESIZE; break; +#endif case EXT_JUMBO9: size = MJUM9BYTES; break; @@ -1110,7 +1114,7 @@ static inline u_int m_extrefcnt(struct mbuf *m) { - KASSERT(m->m_flags & M_EXT, ("%s: M_EXT missing", __func__)); + KASSERT(m->m_flags & M_EXT, ("%s: M_EXT missing for %p", __func__, m)); return ((m->m_ext.ext_flags & EXT_FLAG_EMBREF) ? m->m_ext.ext_count : *m->m_ext.ext_cnt); @@ -1142,13 +1146,13 @@ m_extrefcnt(struct mbuf *m) /* Check if the supplied mbuf has a packet header, or else panic. */ #define M_ASSERTPKTHDR(m) \ KASSERT((m) != NULL && (m)->m_flags & M_PKTHDR, \ - ("%s: no mbuf packet header!", __func__)) + ("%s: no mbuf %p packet header!", __func__, (m))) /* Check if the supplied mbuf has no send tag, or else panic. */ #define M_ASSERT_NO_SND_TAG(m) \ KASSERT((m) != NULL && (m)->m_flags & M_PKTHDR && \ ((m)->m_pkthdr.csum_flags & CSUM_SND_TAG) == 0, \ - ("%s: receive mbuf has send tag!", __func__)) + ("%s: receive mbuf %p has send tag!", __func__, (m))) /* Check if mbuf is multipage. */ #define M_ASSERTEXTPG(m) \ @@ -1162,7 +1166,7 @@ m_extrefcnt(struct mbuf *m) */ #define M_ASSERTVALID(m) \ KASSERT((((struct mbuf *)m)->m_flags & 0) == 0, \ - ("%s: attempted use of a free mbuf!", __func__)) + ("%s: attempted use of a free mbuf %p!", __func__, (m))) /* Check whether any mbuf in the chain is unmapped. */ #ifdef INVARIANTS @@ -1207,12 +1211,9 @@ m_extrefcnt(struct mbuf *m) static __inline void m_align(struct mbuf *m, int len) { -#ifdef INVARIANTS - const char *msg = "%s: not a virgin mbuf"; -#endif int adjust; - - KASSERT(m->m_data == M_START(m), (msg, __func__)); + KASSERT(m->m_data == M_START(m), + ("%s: not a virgin mbuf %p", __func__, m)); adjust = M_SIZE(m) - len; m->m_data += adjust &~ (sizeof(long)-1); @@ -1387,6 +1388,9 @@ extern bool mb_use_ext_pgs; /* Use ext_pgs for sendfile */ #define PACKET_TAG_IPSEC_NAT_T_PORTS 29 /* two uint16_t */ #define PACKET_TAG_ND_OUTGOING 30 /* ND outgoing */ #define PACKET_TAG_PF_REASSEMBLED 31 +#define PACKET_TAG_IPSEC_ACCEL_OUT 32 /* IPSEC accel out */ +#define PACKET_TAG_IPSEC_ACCEL_IN 33 /* IPSEC accel in */ +#define PACKET_TAG_OVPN 34 /* if_ovpn */ /* Specific cookies and tags. */ @@ -1530,14 +1534,16 @@ m_free(struct mbuf *m) static __inline int rt_m_getfib(struct mbuf *m) { - KASSERT(m->m_flags & M_PKTHDR , ("Attempt to get FIB from non header mbuf.")); + KASSERT(m->m_flags & M_PKTHDR, + ("%s: Attempt to get FIB from non header mbuf %p", __func__, m)); return (m->m_pkthdr.fibnum); } #define M_GETFIB(_m) rt_m_getfib(_m) #define M_SETFIB(_m, _fib) do { \ - KASSERT((_m)->m_flags & M_PKTHDR, ("Attempt to set FIB on non header mbuf.")); \ + KASSERT((_m)->m_flags & M_PKTHDR, \ + ("%s: Attempt to set FIB on non header mbuf %p", __func__, (_m))); \ ((_m)->m_pkthdr.fibnum) = (_fib); \ } while (0) @@ -1559,6 +1565,10 @@ uint32_t m_infiniband_tcpip_hash(const uint32_t, const struct mbuf *, uint32_t); #define M_PROFILE(m) #endif +/* + * Structure describing a packet queue: mbufs linked by m_stailqpkt. + * Does accounting of number of packets and has a cap. + */ struct mbufq { STAILQ_HEAD(, mbuf) mq_head; int mq_len; @@ -1676,14 +1686,137 @@ mbufq_concat(struct mbufq *mq_dst, struct mbufq *mq_src) mq_src->mq_len = 0; } +/* + * Structure describing a chain of mbufs linked by m_stailq, also tracking + * the pointer to the last. Also does accounting of data length and memory + * usage. + * To be used as an argument to mbuf chain allocation and manipulation KPIs, + * and can be allocated on the stack of a caller. Kernel facilities may use + * it internally as a most simple implementation of a stream data buffer. + */ +struct mchain { + STAILQ_HEAD(, mbuf) mc_q; + u_int mc_len; + u_int mc_mlen; +}; + +#define MCHAIN_INITIALIZER(mc) \ + (struct mchain){ .mc_q = STAILQ_HEAD_INITIALIZER((mc)->mc_q) } + +static inline struct mbuf * +mc_first(struct mchain *mc) +{ + return (STAILQ_FIRST(&mc->mc_q)); +} + +static inline struct mbuf * +mc_last(struct mchain *mc) +{ + return (STAILQ_LAST(&mc->mc_q, mbuf, m_stailq)); +} + +static inline bool +mc_empty(struct mchain *mc) +{ + return (STAILQ_EMPTY(&mc->mc_q)); +} + +/* Account addition of m to mc. */ +static inline void +mc_inc(struct mchain *mc, struct mbuf *m) +{ + mc->mc_len += m->m_len; + mc->mc_mlen += MSIZE; + if (m->m_flags & M_EXT) + mc->mc_mlen += m->m_ext.ext_size; +} + +/* Account removal of m from mc. */ +static inline void +mc_dec(struct mchain *mc, struct mbuf *m) +{ + MPASS(mc->mc_len >= m->m_len); + mc->mc_len -= m->m_len; + MPASS(mc->mc_mlen >= MSIZE); + mc->mc_mlen -= MSIZE; + if (m->m_flags & M_EXT) { + MPASS(mc->mc_mlen >= m->m_ext.ext_size); + mc->mc_mlen -= m->m_ext.ext_size; + } +} + +/* + * Get mchain from a classic mbuf chain linked by m_next. Two hacks here: + * we use the fact that m_next is alias to m_stailq, we use internal queue(3) + * fields. + */ +static inline void +mc_init_m(struct mchain *mc, struct mbuf *m) +{ + struct mbuf *last; + + STAILQ_FIRST(&mc->mc_q) = m; + mc->mc_len = mc->mc_mlen = 0; + STAILQ_FOREACH(m, &mc->mc_q, m_stailq) { + mc_inc(mc, m); + last = m; + } + mc->mc_q.stqh_last = &STAILQ_NEXT(last, m_stailq); +} + +static inline void +mc_freem(struct mchain *mc) +{ + if (!mc_empty(mc)) + m_freem(mc_first(mc)); +} + +static inline void +mc_prepend(struct mchain *mc, struct mbuf *m) +{ + STAILQ_INSERT_HEAD(&mc->mc_q, m, m_stailq); + mc_inc(mc, m); +} + +static inline void +mc_append(struct mchain *mc, struct mbuf *m) +{ + STAILQ_INSERT_TAIL(&mc->mc_q, m, m_stailq); + mc_inc(mc, m); +} + +static inline void +mc_concat(struct mchain *head, struct mchain *tail) +{ + STAILQ_CONCAT(&head->mc_q, &tail->mc_q); + head->mc_len += tail->mc_len; + head->mc_mlen += tail->mc_mlen; + tail->mc_len = tail->mc_mlen = 0; +} + +/* + * Note: STAILQ_REMOVE() is expensive. mc_remove_after() needs to be provided + * as long as there consumers that would benefit from it. + */ +static inline void +mc_remove(struct mchain *mc, struct mbuf *m) +{ + STAILQ_REMOVE(&mc->mc_q, m, mbuf, m_stailq); + mc_dec(mc, m); +} + +int mc_get(struct mchain *, u_int, int, short, int); +int mc_split(struct mchain *, struct mchain *, u_int, int); +int mc_uiotomc(struct mchain *, struct uio *, u_int, u_int, int, int); + #ifdef _SYS_TIMESPEC_H_ static inline void mbuf_tstmp2timespec(struct mbuf *m, struct timespec *ts) { - KASSERT((m->m_flags & M_PKTHDR) != 0, ("mbuf %p no M_PKTHDR", m)); + M_ASSERTPKTHDR(m); KASSERT((m->m_flags & (M_TSTMP|M_TSTMP_LRO)) != 0, - ("mbuf %p no M_TSTMP or M_TSTMP_LRO", m)); + ("%s: mbuf %p no M_TSTMP or M_TSTMP_LRO", __func__, m)); ts->tv_sec = m->m_pkthdr.rcv_tstmp / 1000000000; ts->tv_nsec = m->m_pkthdr.rcv_tstmp % 1000000000; } @@ -1693,9 +1826,9 @@ static inline void mbuf_tstmp2timeval(struct mbuf *m, struct timeval *tv) { - KASSERT((m->m_flags & M_PKTHDR) != 0, ("mbuf %p no M_PKTHDR", m)); + M_ASSERTPKTHDR(m); KASSERT((m->m_flags & (M_TSTMP|M_TSTMP_LRO)) != 0, - ("mbuf %p no M_TSTMP or M_TSTMP_LRO", m)); + ("%s: mbuf %p no M_TSTMP or M_TSTMP_LRO", __func__, m)); tv->tv_sec = m->m_pkthdr.rcv_tstmp / 1000000000; tv->tv_usec = (m->m_pkthdr.rcv_tstmp % 1000000000) / 1000; } diff --git a/lib/libc/include/generic-freebsd/sys/md4.h b/lib/libc/include/generic-freebsd/sys/md4.h index 3173070ad25b..d42a52780ac8 100644 --- a/lib/libc/include/generic-freebsd/sys/md4.h +++ b/lib/libc/include/generic-freebsd/sys/md4.h @@ -25,8 +25,8 @@ documentation and/or software. */ -#ifndef _MD4_H_ -#define _MD4_H_ +#ifndef _SYS_MD4_H_ +#define _SYS_MD4_H_ /* MD4 context. */ typedef struct MD4Context { u_int32_t state[4]; /* state (ABCD) */ @@ -36,6 +36,43 @@ typedef struct MD4Context { #include +#ifndef _KERNEL + +/* Ensure libmd symbols do not clash with libcrypto */ + +#ifndef MD4Init +#define MD4Init _libmd_MD4Init +#endif +#ifndef MD4Update +#define MD4Update _libmd_MD4Update +#endif +#ifndef MD4Pad +#define MD4Pad _libmd_MD4Pad +#endif +#ifndef MD4Final +#define MD4Final _libmd_MD4Final +#endif +#ifndef MD4End +#define MD4End _libmd_MD4End +#endif +#ifndef MD4Fd +#define MD4Fd _libmd_MD4Fd +#endif +#ifndef MD4FdChunk +#define MD4FdChunk _libmd_MD4FdChunk +#endif +#ifndef MD4File +#define MD4File _libmd_MD4File +#endif +#ifndef MD4FileChunk +#define MD4FileChunk _libmd_MD4FileChunk +#endif +#ifndef MD4Data +#define MD4Data _libmd_MD4Data +#endif + +#endif + __BEGIN_DECLS void MD4Init(MD4_CTX *); void MD4Update(MD4_CTX *, const unsigned char *, unsigned int); @@ -43,9 +80,12 @@ void MD4Pad(MD4_CTX *); void MD4Final(unsigned char [__min_size(16)], MD4_CTX *); #ifndef _KERNEL char * MD4End(MD4_CTX *, char *); +char * MD4Fd(int, char *); +char * MD4FdChunk(int, char *, off_t, off_t); char * MD4File(const char *, char *); -char * MD4Data(const unsigned char *, unsigned int, char *); +char * MD4FileChunk(const char *, char *, off_t, off_t); +char * MD4Data(const void *, unsigned int, char *); #endif __END_DECLS -#endif /* _MD4_H_ */ \ No newline at end of file +#endif /* _SYS_MD4_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/md5.h b/lib/libc/include/generic-freebsd/sys/md5.h index 303719c83342..fa83112a01b2 100644 --- a/lib/libc/include/generic-freebsd/sys/md5.h +++ b/lib/libc/include/generic-freebsd/sys/md5.h @@ -29,6 +29,8 @@ documentation and/or software. #ifndef _SYS_MD5_H_ #define _SYS_MD5_H_ +#include + #define MD5_BLOCK_LENGTH 64 #define MD5_DIGEST_LENGTH 16 #define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1) @@ -40,6 +42,46 @@ typedef struct MD5Context { unsigned char buffer[64]; /* input buffer */ } MD5_CTX; +#ifndef _KERNEL + +/* Ensure libmd symbols do not clash with libcrypto */ + +#ifndef MD5Init +#define MD5Init _libmd_MD5Init +#endif +#ifndef MD5Update +#define MD5Update _libmd_MD5Update +#endif +#ifndef MD5Pad +#define MD5Pad _libmd_MD5Pad +#endif +#ifndef MD5Final +#define MD5Final _libmd_MD5Final +#endif +#ifndef MD5Transform +#define MD5Transform _libmd_MD5Transform +#endif +#ifndef MD5End +#define MD5End _libmd_MD5End +#endif +#ifndef MD5Fd +#define MD5Fd _libmd_MD5Fd +#endif +#ifndef MD5FdChunk +#define MD5FdChunk _libmd_MD5FdChunk +#endif +#ifndef MD5File +#define MD5File _libmd_MD5File +#endif +#ifndef MD5FileChunk +#define MD5FileChunk _libmd_MD5FileChunk +#endif +#ifndef MD5Data +#define MD5Data _libmd_MD5Data +#endif + +#endif + #include __BEGIN_DECLS diff --git a/lib/libc/include/generic-freebsd/sys/mdioctl.h b/lib/libc/include/generic-freebsd/sys/mdioctl.h index 68e4b29b9b34..1783748f7360 100644 --- a/lib/libc/include/generic-freebsd/sys/mdioctl.h +++ b/lib/libc/include/generic-freebsd/sys/mdioctl.h @@ -34,10 +34,6 @@ * SUCH DAMAGE. * * from: Utah $Hdr: fdioctl.h 1.1 90/07/09$ - * - * @(#)vnioctl.h 8.1 (Berkeley) 6/10/93 - * - * From: src/sys/sys/vnioctl.h,v 1.4 */ #ifndef _SYS_MDIOCTL_H_ diff --git a/lib/libc/include/generic-freebsd/sys/memdesc.h b/lib/libc/include/generic-freebsd/sys/memdesc.h index 69fdd50c911d..8d591367a4b8 100644 --- a/lib/libc/include/generic-freebsd/sys/memdesc.h +++ b/lib/libc/include/generic-freebsd/sys/memdesc.h @@ -163,4 +163,40 @@ void memdesc_copyback(struct memdesc *mem, int off, int size, const void *src); void memdesc_copydata(struct memdesc *mem, int off, int size, void *dst); +/* + * This routine constructs a chain of M_EXT mbufs backed by a data + * buffer described by a memory descriptor. Some buffers may require + * multiple mbufs. For memory descriptors using unmapped storage + * (e.g. memdesc_vmpages), M_EXTPG mbufs are used. + * + * Since memory descriptors are not an actual buffer, just a + * description of the buffer, the caller is required to supply a + * couple of helper routines to manage allocation of the raw mbufs and + * associate them with a reference to the underlying buffer. + * + * The memdesc_alloc_ext_mbuf_t callback is passed the callback + * argument as its first argument, the how flag as its second + * argument, and the pointer and length of a KVA buffer. This + * callback should allocate an mbuf for the KVA buffer, either by + * making a copy of the data or using m_extaddref(). + * + * The memdesc_alloc_extpg_mbuf_t callback is passed the callback + * argument as its first argument and the how flag as its second + * argument. It should return an empty mbuf allocated by + * mb_alloc_ext_pgs. + * + * If either of the callbacks returns NULL, any partially allocated + * chain is freed and this routine returns NULL. + * + * If can_truncate is true, then this function might return a short + * chain to avoid gratuitously splitting up a page. + */ +typedef struct mbuf *memdesc_alloc_ext_mbuf_t(void *, int, void *, size_t); +typedef struct mbuf *memdesc_alloc_extpg_mbuf_t(void *, int); + +struct mbuf *memdesc_alloc_ext_mbufs(struct memdesc *mem, + memdesc_alloc_ext_mbuf_t *ext_alloc, + memdesc_alloc_extpg_mbuf_t *extpg_alloc, void *cb_arg, int how, + size_t offset, size_t len, size_t *actual_len, bool can_truncate); + #endif /* _SYS_MEMDESC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/mman.h b/lib/libc/include/generic-freebsd/sys/mman.h index 9b2c0a0dc98d..d64691cd6e38 100644 --- a/lib/libc/include/generic-freebsd/sys/mman.h +++ b/lib/libc/include/generic-freebsd/sys/mman.h @@ -27,12 +27,10 @@ * 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. - * - * @(#)mman.h 8.2 (Berkeley) 1/9/95 */ #ifndef _SYS_MMAN_H_ -#define _SYS_MMAN_H_ +#define _SYS_MMAN_H_ #include #include @@ -41,10 +39,10 @@ /* * Inheritance for minherit() */ -#define INHERIT_SHARE 0 -#define INHERIT_COPY 1 -#define INHERIT_NONE 2 -#define INHERIT_ZERO 3 +#define INHERIT_SHARE 0 +#define INHERIT_COPY 1 +#define INHERIT_NONE 2 +#define INHERIT_ZERO 3 #endif /* @@ -55,6 +53,8 @@ #define PROT_WRITE 0x02 /* pages can be written */ #define PROT_EXEC 0x04 /* pages can be executed */ #if __BSD_VISIBLE +#define PROT_CHERI0 0x08 +#define PROT_CHERI1 0x10 #define _PROT_ALL (PROT_READ | PROT_WRITE | PROT_EXEC) #define PROT_EXTRACT(prot) ((prot) & _PROT_ALL) @@ -120,9 +120,9 @@ * Flags provided to shm_rename */ /* Don't overwrite dest, if it exists */ -#define SHM_RENAME_NOREPLACE (1 << 0) +#define SHM_RENAME_NOREPLACE (1 << 0) /* Atomically swap src and dest */ -#define SHM_RENAME_EXCHANGE (1 << 1) +#define SHM_RENAME_EXCHANGE (1 << 1) #endif /* __BSD_VISIBLE */ @@ -130,21 +130,21 @@ /* * Process memory locking */ -#define MCL_CURRENT 0x0001 /* Lock only current memory */ -#define MCL_FUTURE 0x0002 /* Lock all future memory as well */ +#define MCL_CURRENT 0x0001 /* Lock only current memory */ +#define MCL_FUTURE 0x0002 /* Lock all future memory as well */ #endif /* * Error return from mmap() */ -#define MAP_FAILED ((void *)-1) +#define MAP_FAILED ((void *)-1) /* * msync() flags */ #define MS_SYNC 0x0000 /* msync synchronously */ -#define MS_ASYNC 0x0001 /* return immediately */ -#define MS_INVALIDATE 0x0002 /* invalidate all cached data */ +#define MS_ASYNC 0x0001 /* return immediately */ +#define MS_INVALIDATE 0x0002 /* invalidate all cached data */ /* * Advice to madvise @@ -177,7 +177,9 @@ #define MINCORE_REFERENCED_OTHER 0x8 /* Page has been referenced */ #define MINCORE_MODIFIED_OTHER 0x10 /* Page has been modified */ #define MINCORE_SUPER 0x60 /* Page is a "super" page */ -#define MINCORE_PSIND(i) (((i) << 5) & MINCORE_SUPER) /* Page size */ +#define MINCORE_PSIND_SHIFT 5 +#define MINCORE_PSIND(i) (((i) << MINCORE_PSIND_SHIFT) & MINCORE_SUPER) + /* Page size */ /* * Anonymous object constant for shm_open(). @@ -312,7 +314,7 @@ bool shm_largepage(struct shmfd *shmfd); void shm_remove_prison(struct prison *pr); int shm_get_path(struct vm_object *obj, char *path, size_t sz); -extern struct fileops shm_ops; +extern const struct fileops shm_ops; #define MAP_32BIT_MAX_ADDR ((vm_offset_t)1 << 31) diff --git a/lib/libc/include/generic-freebsd/sys/mount.h b/lib/libc/include/generic-freebsd/sys/mount.h index 325f05c895aa..de92bfee3610 100644 --- a/lib/libc/include/generic-freebsd/sys/mount.h +++ b/lib/libc/include/generic-freebsd/sys/mount.h @@ -27,22 +27,24 @@ * 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. - * - * @(#)mount.h 8.21 (Berkeley) 5/20/95 */ #ifndef _SYS_MOUNT_H_ #define _SYS_MOUNT_H_ +#include #include #include #ifdef _KERNEL -#include #include #include #include #include #include +#elif defined(_WANT_MOUNT) +#include +#include +#include #endif /* @@ -265,6 +267,7 @@ struct mount { int mnt_lazyvnodelistsize; /* (l) # of lazy vnodes */ int mnt_upper_pending; /* (i) # of pending ops on mnt_uppers */ struct lock mnt_explock; /* vfs_export walkers lock */ + struct lock mnt_renamelock; /* renames and O_RESOLVE_BENEATH */ TAILQ_HEAD(, mount_upper_node) mnt_uppers; /* (i) upper mounts over us */ TAILQ_HEAD(, mount_upper_node) mnt_notify; /* (i) upper mounts for notification */ STAILQ_ENTRY(mount) mnt_taskqueue_link; /* (d) our place in deferred unmount list */ @@ -367,6 +370,7 @@ struct mntoptnames { { MNT_RELOAD, "reload" }, \ { MNT_FORCE, "force" }, \ { MNT_SNAPSHOT, "snapshot" }, \ + { MNT_NAMEDATTR, "named attributes" }, \ { 0, NULL } #endif @@ -392,6 +396,7 @@ struct mntoptnames { #define MNT_SUJ 0x0000000100000000ULL /* using journaled soft updates */ #define MNT_AUTOMOUNTED 0x0000000200000000ULL /* mounted by automountd(8) */ #define MNT_UNTRUSTED 0x0000000800000000ULL /* filesys metadata untrusted */ +#define MNT_NAMEDATTR 0x0000020000000000ULL /* named attributes enabled */ /* * NFS export related mount flags. @@ -431,7 +436,7 @@ struct mntoptnames { MNT_IGNORE | MNT_EXPUBLIC | MNT_NOSYMFOLLOW | \ MNT_GJOURNAL | MNT_MULTILABEL | MNT_ACLS | \ MNT_NFS4ACLS | MNT_AUTOMOUNTED | MNT_VERIFIED | \ - MNT_UNTRUSTED) + MNT_UNTRUSTED | MNT_NAMEDATTR) /* Mask of flags that can be updated. */ #define MNT_UPDATEMASK (MNT_NOSUID | MNT_NOEXEC | \ @@ -687,6 +692,8 @@ struct ovfsconf { #define VFCF_SBDRY 0x01000000 /* Stop at Boundary: defer stop requests to kernel->user (AST) transition */ #define VFCF_FILEMOUNT 0x02000000 /* allow mounting files */ +#define VFCF_FILEREVINC 0x04000000 /* va_filerev is incr. by one */ +#define VFCF_FILEREVCT 0x08000000 /* va_filerev is set to ctime */ typedef uint32_t fsctlop_t; @@ -1000,6 +1007,7 @@ struct mntarg *mount_argsu(struct mntarg *ma, const char *name, const void *val, void statfs_scale_blocks(struct statfs *sf, long max_size); struct vfsconf *vfs_byname(const char *); struct vfsconf *vfs_byname_kld(const char *, struct thread *td, int *); +void vfs_unref_vfsconf(struct vfsconf *vfsp); void vfs_mount_destroy(struct mount *); void vfs_event_signal(fsid_t *, u_int32_t, intptr_t); void vfs_freeopts(struct vfsoptlist *opts); diff --git a/lib/libc/include/generic-freebsd/sys/msg.h b/lib/libc/include/generic-freebsd/sys/msg.h index 95c5f376b50d..db8928fcae5c 100644 --- a/lib/libc/include/generic-freebsd/sys/msg.h +++ b/lib/libc/include/generic-freebsd/sys/msg.h @@ -162,9 +162,6 @@ int msgctl(int, int, struct msqid_ds *); int msgget(key_t, int); ssize_t msgrcv(int, void *, size_t, long, int); int msgsnd(int, const void *, size_t, int); -#if __BSD_VISIBLE -int msgsys(int, ...); -#endif __END_DECLS #endif /* !_KERNEL */ diff --git a/lib/libc/include/generic-freebsd/sys/msgbuf.h b/lib/libc/include/generic-freebsd/sys/msgbuf.h index 30d1c17a615c..315b66d7cd5f 100644 --- a/lib/libc/include/generic-freebsd/sys/msgbuf.h +++ b/lib/libc/include/generic-freebsd/sys/msgbuf.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)msgbuf.h 8.1 (Berkeley) 6/2/93 */ #ifndef _SYS_MSGBUF_H_ diff --git a/lib/libc/include/generic-freebsd/sys/mtio.h b/lib/libc/include/generic-freebsd/sys/mtio.h index ec1e61a9fd35..9fd6046b6d13 100644 --- a/lib/libc/include/generic-freebsd/sys/mtio.h +++ b/lib/libc/include/generic-freebsd/sys/mtio.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)mtio.h 8.1 (Berkeley) 6/2/93 */ #ifndef _SYS_MTIO_H_ diff --git a/lib/libc/include/generic-freebsd/sys/mutex.h b/lib/libc/include/generic-freebsd/sys/mutex.h index feee6a5d983d..0fa9cfe14ac3 100644 --- a/lib/libc/include/generic-freebsd/sys/mutex.h +++ b/lib/libc/include/generic-freebsd/sys/mutex.h @@ -91,7 +91,7 @@ void _mtx_init(volatile uintptr_t *c, const char *name, const char *type, int opts); void _mtx_destroy(volatile uintptr_t *c); -void mtx_sysinit(void *arg); +void mtx_sysinit(const void *arg); int _mtx_trylock_flags_int(struct mtx *m, int opts LOCK_FILE_LINE_ARG_DEF); int _mtx_trylock_flags_(volatile uintptr_t *c, int opts, const char *file, int line); diff --git a/lib/libc/include/generic-freebsd/sys/namei.h b/lib/libc/include/generic-freebsd/sys/namei.h index 40100bd9256c..d14b51354f38 100644 --- a/lib/libc/include/generic-freebsd/sys/namei.h +++ b/lib/libc/include/generic-freebsd/sys/namei.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)namei.h 8.5 (Berkeley) 1/9/95 */ #ifndef _SYS_NAMEI_H_ @@ -40,6 +38,8 @@ #include #include +#include + enum nameiop { LOOKUP, CREATE, DELETE, RENAME }; struct componentname { @@ -70,7 +70,7 @@ struct nameidata { */ const char *ni_dirp; /* pathname pointer */ enum uio_seg ni_segflg; /* location of pathname */ - cap_rights_t *ni_rightsneeded; /* rights required to look up vnode */ + const cap_rights_t *ni_rightsneeded; /* rights needed to look up vnode */ /* * Arguments to lookup. */ @@ -108,7 +108,12 @@ struct nameidata { * through the VOP interface. */ struct componentname ni_cnd; + + /* Serving RBENEATH. */ struct nameicap_tracker_head ni_cap_tracker; + struct vnode *ni_rbeneath_dpp; + struct mount *ni_nctrack_mnt; + /* * Private helper data for UFS, must be at the end. See * NDINIT_PREFILL(). @@ -152,6 +157,7 @@ int cache_fplookup(struct nameidata *ndp, enum cache_fpl_status *status, #define LOCKSHARED 0x0100 /* Shared lock leaf */ #define NOFOLLOW 0x0000 /* do not follow symbolic links (pseudo) */ #define RBENEATH 0x100000000ULL /* No escape, even tmp, from start dir */ +#define NAMEILOOKUP 0x200000000ULL /* cnp is embedded in nameidata */ #define MODMASK 0xf000001ffULL /* mask of operational modifiers */ /* @@ -159,7 +165,7 @@ int cache_fplookup(struct nameidata *ndp, enum cache_fpl_status *status, */ #define RDONLY 0x00000200 /* lookup with read-only semantics */ #define ISRESTARTED 0x00000400 /* restarted namei */ -/* UNUSED 0x00000800 */ +#define IGNOREWHITEOUT 0x00000800 /* ignore whiteouts, e.g. when checking if a dir is empty */ #define ISWHITEOUT 0x00001000 /* found whiteout */ #define DOWHITEOUT 0x00002000 /* do whiteouts */ #define WILLBEDIR 0x00004000 /* new files will be dirs; allow trailing / */ @@ -172,14 +178,15 @@ int cache_fplookup(struct nameidata *ndp, enum cache_fpl_status *status, #define OPENREAD 0x00200000 /* open for reading */ #define OPENWRITE 0x00400000 /* open for writing */ #define WANTIOCTLCAPS 0x00800000 /* leave ioctl caps for the caller */ -/* UNUSED 0x01000000 */ +#define OPENNAMED 0x01000000 /* opening a named attribute (dir) */ #define NOEXECCHECK 0x02000000 /* do not perform exec check on dir */ #define MAKEENTRY 0x04000000 /* entry is to be added to name cache */ #define ISSYMLINK 0x08000000 /* symlink needs interpretation */ #define ISLASTCN 0x10000000 /* this is last component of pathname */ #define ISDOTDOT 0x20000000 /* current component name is .. */ #define TRAILINGSLASH 0x40000000 /* path ended in a slash */ -#define PARAMASK 0x7ffffe00 /* mask of parameter descriptors */ +#define CREATENAMED 0x80000000 /* create a named attribute dir */ +#define PARAMASK 0xfffffe00 /* mask of parameter descriptors */ /* * Flags which must not be passed in by callers. @@ -194,6 +201,7 @@ int cache_fplookup(struct nameidata *ndp, enum cache_fpl_status *status, #define NIRES_ABS 0x00000001 /* Path was absolute */ #define NIRES_STRICTREL 0x00000002 /* Restricted lookup result */ #define NIRES_EMPTYPATH 0x00000004 /* EMPTYPATH used */ +#define NIRES_BENEATH 0x00000008 /* O_RESOLVE_BENEATH is to be inherited */ /* * Flags in ni_lcf, valid for the duration of the namei call. @@ -232,6 +240,10 @@ int cache_fplookup(struct nameidata *ndp, enum cache_fpl_status *status, panic("namei data not inited"); \ if (((arg)->ni_debugflags & NAMEI_DBG_HADSTARTDIR) != 0) \ panic("NDREINIT on namei data with NAMEI_DBG_HADSTARTDIR"); \ + if ((arg)->ni_nctrack_mnt != NULL) \ + panic("NDREINIT on namei data with leaked ni_nctrack_mnt"); \ + if (!TAILQ_EMPTY(&(arg)->ni_cap_tracker)) \ + panic("NDREINIT on namei data with leaked ni_cap_tracker"); \ (arg)->ni_debugflags = NAMEI_DBG_INITED; \ } #else @@ -243,12 +255,12 @@ int cache_fplookup(struct nameidata *ndp, enum cache_fpl_status *status, #define NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, startdir, rightsp) \ do { \ struct nameidata *_ndp = (ndp); \ - cap_rights_t *_rightsp = (rightsp); \ + const cap_rights_t *_rightsp = (rightsp); \ MPASS(_rightsp != NULL); \ NDINIT_PREFILL(_ndp); \ NDINIT_DBG(_ndp); \ _ndp->ni_cnd.cn_nameiop = op; \ - _ndp->ni_cnd.cn_flags = flags; \ + _ndp->ni_cnd.cn_flags = (flags) | NAMEILOOKUP; \ _ndp->ni_segflg = segflg; \ _ndp->ni_dirp = namep; \ _ndp->ni_dirfd = dirfd; \ @@ -256,6 +268,9 @@ do { \ _ndp->ni_resflags = 0; \ filecaps_init(&_ndp->ni_filecaps); \ _ndp->ni_rightsneeded = _rightsp; \ + _ndp->ni_rbeneath_dpp = NULL; \ + _ndp->ni_nctrack_mnt = NULL; \ + TAILQ_INIT(&_ndp->ni_cap_tracker); \ } while (0) #define NDREINIT(ndp) do { \ @@ -264,6 +279,7 @@ do { \ filecaps_free(&_ndp->ni_filecaps); \ _ndp->ni_resflags = 0; \ _ndp->ni_startdir = NULL; \ + _ndp->ni_cnd.cn_flags &= ~NAMEI_INTERNAL_FLAGS; \ } while (0) #define NDPREINIT(ndp) do { \ @@ -285,6 +301,8 @@ do { \ int namei(struct nameidata *ndp); int vfs_lookup(struct nameidata *ndp); +bool vfs_lookup_isroot(struct nameidata *ndp, struct vnode *dvp); +struct nameidata *vfs_lookup_nameidata(struct componentname *cnp); int vfs_relookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, bool refstart); diff --git a/lib/libc/include/generic-freebsd/sys/nlist_aout.h b/lib/libc/include/generic-freebsd/sys/nlist_aout.h index fe5320429f02..da507cede864 100644 --- a/lib/libc/include/generic-freebsd/sys/nlist_aout.h +++ b/lib/libc/include/generic-freebsd/sys/nlist_aout.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)nlist.h 8.2 (Berkeley) 1/21/94 */ #ifndef _SYS_NLIST_AOUT_H_ diff --git a/lib/libc/include/generic-freebsd/sys/nv.h b/lib/libc/include/generic-freebsd/sys/nv.h index 20f401a9fdd4..0a8b9c5be216 100644 --- a/lib/libc/include/generic-freebsd/sys/nv.h +++ b/lib/libc/include/generic-freebsd/sys/nv.h @@ -34,6 +34,7 @@ #define _NV_H_ #include +#include #ifndef _KERNEL #include @@ -43,13 +44,6 @@ #include #endif -#ifndef _NVLIST_T_DECLARED -#define _NVLIST_T_DECLARED -struct nvlist; - -typedef struct nvlist nvlist_t; -#endif - #define NV_NAME_MAX 2048 #define NV_TYPE_NONE 0 diff --git a/lib/libc/include/generic-freebsd/sys/nvpair.h b/lib/libc/include/generic-freebsd/sys/nvpair.h index 98b1b1d54a42..f19d629f0549 100644 --- a/lib/libc/include/generic-freebsd/sys/nvpair.h +++ b/lib/libc/include/generic-freebsd/sys/nvpair.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: CDDL-1.0 /* * CDDL HEADER START * @@ -266,6 +267,8 @@ _SYS_NVPAIR_H int nvlist_lookup_double(const nvlist_t *, const char *, double *); #endif +_SYS_NVPAIR_H int nvlist_snprintf(char *, size_t, nvlist_t *, int); + _SYS_NVPAIR_H int nvlist_lookup_nvpair(nvlist_t *, const char *, nvpair_t **); _SYS_NVPAIR_H int nvlist_lookup_nvpair_embedded_index(nvlist_t *, const char *, nvpair_t **, int *, const char **); diff --git a/lib/libc/include/generic-freebsd/sys/osd.h b/lib/libc/include/generic-freebsd/sys/osd.h index e3b35702fdfa..d76a20b95984 100644 --- a/lib/libc/include/generic-freebsd/sys/osd.h +++ b/lib/libc/include/generic-freebsd/sys/osd.h @@ -55,7 +55,7 @@ typedef void (*osd_destructor_t)(void *value); typedef int (*osd_method_t)(void *obj, void *data); int osd_register(u_int type, osd_destructor_t destructor, - osd_method_t *methods); + const osd_method_t *methods); void osd_deregister(u_int type, u_int slot); int osd_set(u_int type, struct osd *osd, u_int slot, void *value); @@ -64,6 +64,7 @@ int osd_set_reserved(u_int type, struct osd *osd, u_int slot, void **rsv, void *value); void osd_free_reserved(void **rsv); void *osd_get(u_int type, struct osd *osd, u_int slot); +void *osd_get_unlocked(u_int type, struct osd *osd, u_int slot); void osd_del(u_int type, struct osd *osd, u_int slot); int osd_call(u_int type, u_int method, void *obj, void *data); @@ -79,6 +80,8 @@ void osd_exit(u_int type, struct osd *osd); osd_set_reserved(OSD_THREAD, &(td)->td_osd, (slot), (rsv), (value)) #define osd_thread_get(td, slot) \ osd_get(OSD_THREAD, &(td)->td_osd, (slot)) +#define osd_thread_get_unlocked(td, slot) \ + osd_get_unlocked(OSD_THREAD, &(td)->td_osd, (slot)) #define osd_thread_del(td, slot) do { \ KASSERT((td) == curthread, ("Not curthread.")); \ osd_del(OSD_THREAD, &(td)->td_osd, (slot)); \ @@ -98,6 +101,8 @@ void osd_exit(u_int type, struct osd *osd); osd_set_reserved(OSD_JAIL, &(pr)->pr_osd, (slot), (rsv), (value)) #define osd_jail_get(pr, slot) \ osd_get(OSD_JAIL, &(pr)->pr_osd, (slot)) +#define osd_jail_get_unlocked(pr, slot) \ + osd_get_unlocked(OSD_JAIL, &(pr)->pr_osd, (slot)) #define osd_jail_del(pr, slot) \ osd_del(OSD_JAIL, &(pr)->pr_osd, (slot)) #define osd_jail_call(pr, method, data) \ diff --git a/lib/libc/include/generic-freebsd/sys/param.h b/lib/libc/include/generic-freebsd/sys/param.h index cf7e24e88c0c..b97dca187c15 100644 --- a/lib/libc/include/generic-freebsd/sys/param.h +++ b/lib/libc/include/generic-freebsd/sys/param.h @@ -32,14 +32,13 @@ * 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. - * - * @(#)param.h 8.3 (Berkeley) 4/4/95 */ #ifndef _SYS_PARAM_H_ #define _SYS_PARAM_H_ #include +#include #define BSD 199506 /* System version (year & month). */ #define BSD4_3 1 @@ -107,6 +106,8 @@ #define P_OSREL_POWERPC_NEW_AUX_ARGS 1300070 #define P_OSREL_TIDPID 1400079 #define P_OSREL_ARM64_SPSR 1400084 +#define P_OSREL_TLSBASE 1500044 +#define P_OSREL_EXTERRCTL 1500045 #define P_OSREL_MAJOR(x) ((x) / 100000) #endif @@ -151,17 +152,16 @@ #endif #endif -#ifndef _KERNEL -#ifndef LOCORE +#if !defined(_KERNEL) && !defined(_STANDALONE) && !defined(LOCORE) /* Signals. */ #include #endif -#endif /* Machine type dependent parameters. */ #include #ifndef _KERNEL #include +#include #endif #ifndef DEV_BSHIFT @@ -175,13 +175,6 @@ #ifndef DFLTPHYS #define DFLTPHYS (64 * 1024) /* default max raw I/O transfer size */ #endif -#ifndef MAXPHYS /* max raw I/O transfer size */ -#ifdef __ILP32__ -#define MAXPHYS (128 * 1024) -#else -#define MAXPHYS (1024 * 1024) -#endif -#endif #ifndef MAXDUMPPGS #define MAXDUMPPGS (DFLTPHYS/PAGE_SIZE) #endif @@ -209,6 +202,17 @@ #define MJUM9BYTES (9 * 1024) /* jumbo cluster 9k */ #define MJUM16BYTES (16 * 1024) /* jumbo cluster 16k */ +/* + * Mach derived conversion macros + */ +#define round_page(x) roundup2(x, PAGE_SIZE) +#define trunc_page(x) rounddown2(x, PAGE_SIZE) + +#define atop(x) ((x) >> PAGE_SHIFT) +#define ptoa(x) ((x) << PAGE_SHIFT) + +#define pgtok(x) ((x) * (PAGE_SIZE / 1024)) + /* * Some macros for units conversion */ @@ -249,9 +253,6 @@ #define NZERO 0 /* default "nice" */ -#define NBBY 8 /* number of bits in a byte */ -#define NBPW sizeof(int) /* number of bytes per word (integer) */ - #define CMASK 022 /* default file mask: S_IWGRP|S_IWOTH */ #define NODEV (dev_t)(-1) /* non-existent device */ @@ -315,16 +316,7 @@ #define isclr(a,i) \ ((((const unsigned char *)(a))[(i)/NBBY] & (1<<((i)%NBBY))) == 0) -/* Macros for counting and rounding. */ -#ifndef howmany -#define howmany(x, y) (((x)+((y)-1))/(y)) -#endif -#define nitems(x) (sizeof((x)) / sizeof((x)[0])) -#define rounddown(x, y) (((x)/(y))*(y)) -#define rounddown2(x, y) __align_down(x, y) /* if y is power of two */ -#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */ -#define roundup2(x, y) __align_up(x, y) /* if y is powers of two */ -#define powerof2(x) ((((x)-1)&(x))==0) +/* Macros for counting and rounding provided by . */ /* Macros for min/max. */ #define MIN(a,b) (((a)<(b))?(a):(b)) @@ -387,4 +379,4 @@ __END_DECLS */ #define __PAST_END(array, offset) (((__typeof__(*(array)) *)(array))[offset]) -#endif /* _SYS_PARAM_H_ */ +#endif /* _SYS_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/pciio.h b/lib/libc/include/generic-freebsd/sys/pciio.h index dffd559965f1..9298c944ca08 100644 --- a/lib/libc/include/generic-freebsd/sys/pciio.h +++ b/lib/libc/include/generic-freebsd/sys/pciio.h @@ -66,10 +66,10 @@ struct pci_conf { struct pcisel pc_sel; /* domain+bus+slot+function */ u_int8_t pc_hdr; /* PCI header type */ u_int16_t pc_subvendor; /* card vendor ID */ - u_int16_t pc_subdevice; /* card device ID, assigned by + u_int16_t pc_subdevice; /* card device ID, assigned by card vendor */ u_int16_t pc_vendor; /* chip vendor ID */ - u_int16_t pc_device; /* chip device ID, assigned by + u_int16_t pc_device; /* chip device ID, assigned by chip vendor */ u_int8_t pc_class; /* chip PCI class */ u_int8_t pc_subclass; /* chip PCI subclass */ @@ -77,6 +77,9 @@ struct pci_conf { u_int8_t pc_revid; /* chip revision ID */ char pd_name[PCI_MAXNAMELEN + 1]; /* device name */ u_long pd_unit; /* device unit number */ + int pd_numa_domain; /* device NUMA domain */ + size_t pc_reported_len;/* length of PCI data reported */ + char pc_spare[64]; /* space for future fields */ }; struct pci_match_conf { @@ -165,7 +168,6 @@ struct pci_bar_ioreq { #define PCIIO_BAR_MMAP_RW 0x04 #define PCIIO_BAR_MMAP_ACTIVATE 0x08 -#define PCIOCGETCONF _IOWR('p', 5, struct pci_conf_io) #define PCIOCREAD _IOWR('p', 2, struct pci_io) #define PCIOCWRITE _IOWR('p', 3, struct pci_io) #define PCIOCATTACHED _IOWR('p', 4, struct pci_io) @@ -173,5 +175,6 @@ struct pci_bar_ioreq { #define PCIOCLISTVPD _IOWR('p', 7, struct pci_list_vpd_io) #define PCIOCBARMMAP _IOWR('p', 8, struct pci_bar_mmap) #define PCIOCBARIO _IOWR('p', 9, struct pci_bar_ioreq) +#define PCIOCGETCONF _IOWR('p', 10, struct pci_conf_io) #endif /* !_SYS_PCIIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/pctrie.h b/lib/libc/include/generic-freebsd/sys/pctrie.h index f00e4fbda981..54c770a385df 100644 --- a/lib/libc/include/generic-freebsd/sys/pctrie.h +++ b/lib/libc/include/generic-freebsd/sys/pctrie.h @@ -34,8 +34,45 @@ #include #include +struct pctrie_iter { + struct pctrie *ptree; + struct pctrie_node *node; + uint64_t index; + uint64_t limit; +}; + +static __inline void +pctrie_iter_reset(struct pctrie_iter *it) +{ + it->node = NULL; +} + +static __inline bool +pctrie_iter_is_reset(struct pctrie_iter *it) +{ + return (it->node == NULL); +} + +static __inline void +pctrie_iter_init(struct pctrie_iter *it, struct pctrie *ptree) +{ + it->ptree = ptree; + it->node = NULL; + it->limit = 0; +} + +static __inline void +pctrie_iter_limit_init(struct pctrie_iter *it, struct pctrie *ptree, + uint64_t limit) +{ + pctrie_iter_init(it, ptree); + it->limit = limit; +} + #ifdef _KERNEL +typedef void (*pctrie_cb_t)(void *ptr, void *arg); + #define PCTRIE_DEFINE_SMR(name, type, field, allocfn, freefn, smr) \ PCTRIE_DEFINE(name, type, field, allocfn, freefn) \ \ @@ -46,6 +83,19 @@ name##_PCTRIE_LOOKUP_UNLOCKED(struct pctrie *ptree, uint64_t key) \ return name##_PCTRIE_VAL2PTR(pctrie_lookup_unlocked(ptree, \ key, (smr))); \ } \ + \ +static __inline __unused int \ +name##_PCTRIE_LOOKUP_RANGE_UNLOCKED(struct pctrie *ptree, uint64_t key, \ + struct type *value[], int count) \ +{ \ + uint64_t **data = (uint64_t **)value; \ + \ + count = pctrie_lookup_range_unlocked(ptree, key, data, count, \ + (smr)); \ + for (int i = 0; i < count; i++) \ + value[i] = name##_PCTRIE_NZVAL2PTR(data[i]); \ + return (count); \ +} \ #define PCTRIE_DEFINE(name, type, field, allocfn, freefn) \ \ @@ -57,13 +107,18 @@ CTASSERT(sizeof(((struct type *)0)->field) == sizeof(uint64_t)); \ CTASSERT((__offsetof(struct type, field) & (sizeof(uint32_t) - 1)) == 0); \ \ static __inline struct type * \ -name##_PCTRIE_VAL2PTR(uint64_t *val) \ +name##_PCTRIE_NZVAL2PTR(uint64_t *val) \ { \ + return (struct type *) \ + ((uintptr_t)val - __offsetof(struct type, field)); \ +} \ \ +static __inline struct type * \ +name##_PCTRIE_VAL2PTR(uint64_t *val) \ +{ \ if (val == NULL) \ return (NULL); \ - return (struct type *) \ - ((uintptr_t)val - __offsetof(struct type, field)); \ + return (name##_PCTRIE_NZVAL2PTR(val)); \ } \ \ static __inline uint64_t * \ @@ -73,23 +128,87 @@ name##_PCTRIE_PTR2VAL(struct type *ptr) \ return &ptr->field; \ } \ \ -static __inline int \ +static __inline __unused int \ +name##_PCTRIE_INSERT_BASE(struct pctrie *ptree, uint64_t *val, \ + struct pctrie_node **parent, void *parentp, \ + uint64_t *found, struct type **found_out) \ +{ \ + struct pctrie_node *child; \ + \ + if (__predict_false(found != NULL)) { \ + *found_out = name##_PCTRIE_VAL2PTR(found); \ + return (EEXIST); \ + } \ + if (parentp != NULL) { \ + child = allocfn(ptree); \ + if (__predict_false(child == NULL)) { \ + if (found_out != NULL) \ + *found_out = NULL; \ + return (ENOMEM); \ + } \ + pctrie_insert_node(val, *parent, parentp, child); \ + *parent = child; \ + } \ + return (0); \ +} \ + \ +static __inline __unused int \ name##_PCTRIE_INSERT(struct pctrie *ptree, struct type *ptr) \ { \ + void *parentp; \ struct pctrie_node *parent; \ + uint64_t *val = name##_PCTRIE_PTR2VAL(ptr); \ + \ + parentp = pctrie_insert_lookup_strict(ptree, val, &parent); \ + return (name##_PCTRIE_INSERT_BASE(ptree, val, &parent, parentp, \ + NULL, NULL)); \ +} \ + \ +static __inline __unused int \ +name##_PCTRIE_FIND_OR_INSERT(struct pctrie *ptree, struct type *ptr, \ + struct type **found_out_opt) \ +{ \ void *parentp; \ + struct pctrie_node *parent; \ uint64_t *val = name##_PCTRIE_PTR2VAL(ptr); \ + uint64_t *found; \ \ - parentp = pctrie_insert_lookup(ptree, val); \ - if (parentp == NULL) \ - return (0); \ - parent = allocfn(ptree); \ - if (parent == NULL) \ - return (ENOMEM); \ - pctrie_insert_node(parentp, parent, val); \ + parentp = pctrie_insert_lookup(ptree, val, &parent, &found); \ + return (name##_PCTRIE_INSERT_BASE(ptree, val, &parent, parentp, \ + found, found_out_opt)); \ +} \ + \ +static __inline __unused int \ +name##_PCTRIE_INSERT_LOOKUP_LE(struct pctrie *ptree, struct type *ptr, \ + struct type **found_out) \ +{ \ + struct pctrie_node *parent; \ + void *parentp; \ + uint64_t *val = name##_PCTRIE_PTR2VAL(ptr); \ + uint64_t *found; \ + int retval; \ + \ + parentp = pctrie_insert_lookup(ptree, val, &parent, &found); \ + retval = name##_PCTRIE_INSERT_BASE(ptree, val, &parent, parentp, \ + found, found_out); \ + if (retval != 0) \ + return (retval); \ + found = pctrie_subtree_lookup_lt(ptree, parent, *val); \ + *found_out = name##_PCTRIE_VAL2PTR(found); \ return (0); \ } \ \ +static __inline __unused int \ +name##_PCTRIE_ITER_INSERT(struct pctrie_iter *it, struct type *ptr) \ +{ \ + void *parentp; \ + uint64_t *val = name##_PCTRIE_PTR2VAL(ptr); \ + \ + parentp = pctrie_iter_insert_lookup(it, val); \ + return (name##_PCTRIE_INSERT_BASE(it->ptree, val, &it->node, \ + parentp, NULL, NULL)); \ +} \ + \ static __inline __unused struct type * \ name##_PCTRIE_LOOKUP(struct pctrie *ptree, uint64_t key) \ { \ @@ -97,6 +216,30 @@ name##_PCTRIE_LOOKUP(struct pctrie *ptree, uint64_t key) \ return name##_PCTRIE_VAL2PTR(pctrie_lookup(ptree, key)); \ } \ \ +static __inline __unused int \ +name##_PCTRIE_LOOKUP_RANGE(struct pctrie *ptree, uint64_t key, \ + struct type *value[], int count) \ +{ \ + uint64_t **data = (uint64_t **)value; \ + \ + count = pctrie_lookup_range(ptree, key, data, count); \ + for (int i = 0; i < count; i++) \ + value[i] = name##_PCTRIE_NZVAL2PTR(data[i]); \ + return (count); \ +} \ + \ +static __inline __unused int \ +name##_PCTRIE_ITER_LOOKUP_RANGE(struct pctrie_iter *it, uint64_t key, \ + struct type *value[], int count) \ +{ \ + uint64_t **data = (uint64_t **)value; \ + \ + count = pctrie_iter_lookup_range(it, key, data, count); \ + for (int i = 0; i < count; i++) \ + value[i] = name##_PCTRIE_NZVAL2PTR(data[i]); \ + return (count); \ +} \ + \ static __inline __unused struct type * \ name##_PCTRIE_LOOKUP_LE(struct pctrie *ptree, uint64_t key) \ { \ @@ -122,6 +265,108 @@ name##_PCTRIE_RECLAIM(struct pctrie *ptree) \ freefn(ptree, freenode); \ } \ \ +/* \ + * While reclaiming all internal trie nodes, invoke callback(leaf, arg) \ + * on every leaf in the trie, in order. \ + */ \ +static __inline __unused void \ +name##_PCTRIE_RECLAIM_CALLBACK(struct pctrie *ptree, \ + void (*typed_cb)(struct type *, void *), void *arg) \ +{ \ + struct pctrie_node *freenode, *node; \ + pctrie_cb_t callback = (pctrie_cb_t)typed_cb; \ + \ + for (freenode = pctrie_reclaim_begin_cb(&node, ptree, \ + callback, __offsetof(struct type, field), arg); \ + freenode != NULL; \ + freenode = pctrie_reclaim_resume_cb(&node, \ + callback, __offsetof(struct type, field), arg)) \ + freefn(ptree, freenode); \ +} \ + \ +static __inline __unused struct type * \ +name##_PCTRIE_ITER_LOOKUP(struct pctrie_iter *it, uint64_t index) \ +{ \ + return name##_PCTRIE_VAL2PTR(pctrie_iter_lookup(it, index)); \ +} \ + \ +static __inline __unused struct type * \ +name##_PCTRIE_ITER_STRIDE(struct pctrie_iter *it, int stride) \ +{ \ + return name##_PCTRIE_VAL2PTR(pctrie_iter_stride(it, stride)); \ +} \ + \ +static __inline __unused struct type * \ +name##_PCTRIE_ITER_NEXT(struct pctrie_iter *it) \ +{ \ + return name##_PCTRIE_VAL2PTR(pctrie_iter_next(it)); \ +} \ + \ +static __inline __unused struct type * \ +name##_PCTRIE_ITER_PREV(struct pctrie_iter *it) \ +{ \ + return name##_PCTRIE_VAL2PTR(pctrie_iter_prev(it)); \ +} \ + \ +static __inline __unused struct type * \ +name##_PCTRIE_ITER_VALUE(struct pctrie_iter *it) \ +{ \ + return name##_PCTRIE_VAL2PTR(pctrie_iter_value(it)); \ +} \ + \ +static __inline __unused struct type * \ +name##_PCTRIE_ITER_LOOKUP_GE(struct pctrie_iter *it, uint64_t index) \ +{ \ + return name##_PCTRIE_VAL2PTR(pctrie_iter_lookup_ge(it, index)); \ +} \ + \ +static __inline __unused struct type * \ +name##_PCTRIE_ITER_JUMP_GE(struct pctrie_iter *it, int64_t jump) \ +{ \ + return name##_PCTRIE_VAL2PTR(pctrie_iter_jump_ge(it, jump)); \ +} \ + \ +static __inline __unused struct type * \ +name##_PCTRIE_ITER_STEP_GE(struct pctrie_iter *it) \ +{ \ + return name##_PCTRIE_VAL2PTR(pctrie_iter_jump_ge(it, 1)); \ +} \ + \ +static __inline __unused struct type * \ +name##_PCTRIE_ITER_LOOKUP_LE(struct pctrie_iter *it, uint64_t index) \ +{ \ + return name##_PCTRIE_VAL2PTR(pctrie_iter_lookup_le(it, index)); \ +} \ + \ +static __inline __unused struct type * \ +name##_PCTRIE_ITER_JUMP_LE(struct pctrie_iter *it, int64_t jump) \ +{ \ + return name##_PCTRIE_VAL2PTR(pctrie_iter_jump_le(it, jump)); \ +} \ + \ +static __inline __unused struct type * \ +name##_PCTRIE_ITER_STEP_LE(struct pctrie_iter *it) \ +{ \ + return name##_PCTRIE_VAL2PTR(pctrie_iter_jump_le(it, 1)); \ +} \ + \ +static __inline __unused void \ +name##_PCTRIE_REMOVE_BASE(struct pctrie *ptree, \ + struct pctrie_node *freenode) \ +{ \ + if (freenode != NULL) \ + freefn(ptree, freenode); \ +} \ + \ +static __inline __unused void \ +name##_PCTRIE_ITER_REMOVE(struct pctrie_iter *it) \ +{ \ + struct pctrie_node *freenode; \ + \ + pctrie_iter_remove(it, &freenode); \ + name##_PCTRIE_REMOVE_BASE(it->ptree, freenode); \ +} \ + \ static __inline __unused struct type * \ name##_PCTRIE_REPLACE(struct pctrie *ptree, struct type *ptr) \ { \ @@ -139,8 +384,7 @@ name##_PCTRIE_REMOVE(struct pctrie *ptree, uint64_t key) \ val = pctrie_remove_lookup(ptree, key, &freenode); \ if (val == NULL) \ panic("%s: key not found", __func__); \ - if (freenode != NULL) \ - freefn(ptree, freenode); \ + name##_PCTRIE_REMOVE_BASE(ptree, freenode); \ } \ \ static __inline __unused struct type * \ @@ -150,24 +394,53 @@ name##_PCTRIE_REMOVE_LOOKUP(struct pctrie *ptree, uint64_t key) \ struct pctrie_node *freenode; \ \ val = pctrie_remove_lookup(ptree, key, &freenode); \ - if (freenode != NULL) \ - freefn(ptree, freenode); \ + name##_PCTRIE_REMOVE_BASE(ptree, freenode); \ return name##_PCTRIE_VAL2PTR(val); \ } -void *pctrie_insert_lookup(struct pctrie *ptree, uint64_t *val); -void pctrie_insert_node(void *parentp, - struct pctrie_node *parent, uint64_t *val); +struct pctrie_iter; +void *pctrie_insert_lookup(struct pctrie *ptree, uint64_t *val, + struct pctrie_node **parent_out, uint64_t **found_out); +void *pctrie_insert_lookup_strict(struct pctrie *ptree, uint64_t *val, + struct pctrie_node **parent_out); +void pctrie_insert_node(uint64_t *val, struct pctrie_node *parent, + void *parentp, struct pctrie_node *child); uint64_t *pctrie_lookup(struct pctrie *ptree, uint64_t key); -uint64_t *pctrie_lookup_ge(struct pctrie *ptree, uint64_t key); -uint64_t *pctrie_lookup_le(struct pctrie *ptree, uint64_t key); uint64_t *pctrie_lookup_unlocked(struct pctrie *ptree, uint64_t key, smr_t smr); +int pctrie_lookup_range(struct pctrie *ptree, + uint64_t index, uint64_t *value[], int count); +int pctrie_lookup_range_unlocked(struct pctrie *ptree, + uint64_t index, uint64_t *value[], int count, smr_t smr); +int pctrie_iter_lookup_range(struct pctrie_iter *it, uint64_t index, + uint64_t *value[], int count); +uint64_t *pctrie_iter_lookup(struct pctrie_iter *it, uint64_t index); +uint64_t *pctrie_iter_stride(struct pctrie_iter *it, int stride); +uint64_t *pctrie_iter_next(struct pctrie_iter *it); +uint64_t *pctrie_iter_prev(struct pctrie_iter *it); +void *pctrie_iter_insert_lookup(struct pctrie_iter *it, + uint64_t *val); +uint64_t *pctrie_lookup_ge(struct pctrie *ptree, uint64_t key); +uint64_t *pctrie_iter_lookup_ge(struct pctrie_iter *it, uint64_t index); +uint64_t *pctrie_iter_jump_ge(struct pctrie_iter *it, int64_t jump); +uint64_t *pctrie_lookup_le(struct pctrie *ptree, uint64_t key); +uint64_t *pctrie_subtree_lookup_lt(struct pctrie *ptree, + struct pctrie_node *node, uint64_t key); +uint64_t *pctrie_iter_lookup_le(struct pctrie_iter *it, uint64_t index); +uint64_t *pctrie_iter_jump_le(struct pctrie_iter *it, int64_t jump); struct pctrie_node *pctrie_reclaim_begin(struct pctrie_node **pnode, struct pctrie *ptree); struct pctrie_node *pctrie_reclaim_resume(struct pctrie_node **pnode); +struct pctrie_node *pctrie_reclaim_begin_cb(struct pctrie_node **pnode, + struct pctrie *ptree, + pctrie_cb_t callback, int keyoff, void *arg); +struct pctrie_node *pctrie_reclaim_resume_cb(struct pctrie_node **pnode, + pctrie_cb_t callback, int keyoff, void *arg); uint64_t *pctrie_remove_lookup(struct pctrie *ptree, uint64_t index, struct pctrie_node **killnode); +void pctrie_iter_remove(struct pctrie_iter *it, + struct pctrie_node **freenode); +uint64_t *pctrie_iter_value(struct pctrie_iter *it); uint64_t *pctrie_replace(struct pctrie *ptree, uint64_t *newval); size_t pctrie_node_size(void); int pctrie_zone_init(void *mem, int size, int flags); diff --git a/lib/libc/include/generic-freebsd/sys/pipe.h b/lib/libc/include/generic-freebsd/sys/pipe.h index 352c83d4e540..56a8490fb58c 100644 --- a/lib/libc/include/generic-freebsd/sys/pipe.h +++ b/lib/libc/include/generic-freebsd/sys/pipe.h @@ -52,7 +52,7 @@ * See sys_pipe.c for info on what these limits mean. */ extern long maxpipekva; -extern struct fileops pipeops; +extern const struct fileops pipeops; #endif /* diff --git a/lib/libc/include/generic-freebsd/sys/pmc.h b/lib/libc/include/generic-freebsd/sys/pmc.h index 0d8e7f3e320c..6377d6d07318 100644 --- a/lib/libc/include/generic-freebsd/sys/pmc.h +++ b/lib/libc/include/generic-freebsd/sys/pmc.h @@ -81,7 +81,6 @@ extern char pmc_cpuid[PMC_CPUID_LEN]; * Please keep the pmc(3) manual page in sync with this list. */ #define __PMC_CPUS() \ - __PMC_CPU(AMD_K7, 0x00, "AMD K7") \ __PMC_CPU(AMD_K8, 0x01, "AMD K8") \ __PMC_CPU(INTEL_CORE, 0x87, "Intel Core Solo/Duo") \ __PMC_CPU(INTEL_CORE2, 0x88, "Intel Core2") \ @@ -130,7 +129,7 @@ enum pmc_cputype { __PMC_CPUS() }; -#define PMC_CPU_FIRST PMC_CPU_AMD_K7 +#define PMC_CPU_FIRST PMC_CPU_AMD_K8 #define PMC_CPU_LAST PMC_CPU_ARMV8_CORTEX_A76 /* @@ -138,7 +137,6 @@ enum pmc_cputype { */ #define __PMC_CLASSES() \ __PMC_CLASS(TSC, 0x00, "CPU Timestamp counter") \ - __PMC_CLASS(K7, 0x01, "AMD K7 performance counters") \ __PMC_CLASS(K8, 0x02, "AMD K8 performance counters") \ __PMC_CLASS(IAF, 0x06, "Intel Core2/Atom, fixed function") \ __PMC_CLASS(IAP, 0x07, "Intel Core...Atom, programmable") \ diff --git a/lib/libc/include/generic-freebsd/sys/poll.h b/lib/libc/include/generic-freebsd/sys/poll.h index a731b70329ff..b915f5a37d7e 100644 --- a/lib/libc/include/generic-freebsd/sys/poll.h +++ b/lib/libc/include/generic-freebsd/sys/poll.h @@ -96,7 +96,7 @@ struct pollfd { #ifndef _KERNEL -#if __BSD_VISIBLE +#if __POSIX_VISIBLE >= 202405 #include #include @@ -109,9 +109,13 @@ typedef __sigset_t sigset_t; #endif +#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 +#include +#endif + __BEGIN_DECLS int poll(struct pollfd _pfd[], nfds_t _nfds, int _timeout); -#if __BSD_VISIBLE +#if __POSIX_VISIBLE >= 202405 int ppoll(struct pollfd _pfd[], nfds_t _nfds, const struct timespec *__restrict _timeout, const sigset_t *__restrict _newsigmask); diff --git a/lib/libc/include/generic-freebsd/sys/priority.h b/lib/libc/include/generic-freebsd/sys/priority.h index 6ea8666803aa..1a05ab3648f6 100644 --- a/lib/libc/include/generic-freebsd/sys/priority.h +++ b/lib/libc/include/generic-freebsd/sys/priority.h @@ -64,17 +64,23 @@ */ /* - * Priorities range from 0 to 255, but differences of less then 4 (RQ_PPQ) - * are insignificant. Ranges are as follows: + * Priorities range from 0 to 255. Ranges are as follows: * - * Interrupt threads: 0 - 15 - * Realtime user threads: 16 - 47 - * Top half kernel threads: 48 - 87 - * Time sharing user threads: 88 - 223 + * Interrupt threads: 0 - 7 + * Realtime user threads: 8 - 39 + * Top half kernel threads: 40 - 55 + * Time sharing user threads: 56 - 223 * Idle user threads: 224 - 255 * - * XXX If/When the specific interrupt thread and top half thread ranges - * disappear, a larger range can be used for user processes. + * Priority levels of rtprio(2)'s RTP_PRIO_FIFO and RTP_PRIO_REALTIME and + * POSIX's SCHED_FIFO and SCHED_RR are directly mapped to the internal realtime + * range mentioned above by a simple translation. This range's length + * consequently cannot be changed without impacts on the scheduling priority + * code, and in any case must never be smaller than 32 for POSIX compliance and + * rtprio(2) backwards compatibility. Similarly, priority levels of rtprio(2)'s + * RTP_PRIO_IDLE are directly mapped to the internal idle range above (and, + * soon, those of the to-be-introduced SCHED_IDLE policy as well), so changing + * that range is subject to the same caveats and restrictions. */ #define PRI_MIN (0) /* Highest priority. */ @@ -88,34 +94,34 @@ * decay to lower priorities if they run for full time slices. */ #define PI_REALTIME (PRI_MIN_ITHD + 0) -#define PI_INTR (PRI_MIN_ITHD + 4) +#define PI_INTR (PRI_MIN_ITHD + 1) #define PI_AV PI_INTR #define PI_NET PI_INTR #define PI_DISK PI_INTR #define PI_TTY PI_INTR #define PI_DULL PI_INTR -#define PI_SOFT (PRI_MIN_ITHD + 8) +#define PI_SOFT (PRI_MIN_ITHD + 2) #define PI_SOFTCLOCK PI_SOFT #define PI_SWI(x) PI_SOFT -#define PRI_MIN_REALTIME (16) +#define PRI_MIN_REALTIME (8) #define PRI_MAX_REALTIME (PRI_MIN_KERN - 1) -#define PRI_MIN_KERN (48) +#define PRI_MIN_KERN (40) #define PRI_MAX_KERN (PRI_MIN_TIMESHARE - 1) #define PSWP (PRI_MIN_KERN + 0) -#define PVM (PRI_MIN_KERN + 4) -#define PINOD (PRI_MIN_KERN + 8) -#define PRIBIO (PRI_MIN_KERN + 12) -#define PVFS (PRI_MIN_KERN + 16) -#define PZERO (PRI_MIN_KERN + 20) -#define PSOCK (PRI_MIN_KERN + 24) -#define PWAIT (PRI_MIN_KERN + 28) -#define PLOCK (PRI_MIN_KERN + 32) -#define PPAUSE (PRI_MIN_KERN + 36) - -#define PRI_MIN_TIMESHARE (88) +#define PVM (PRI_MIN_KERN + 1) +#define PINOD (PRI_MIN_KERN + 2) +#define PRIBIO (PRI_MIN_KERN + 3) +#define PVFS (PRI_MIN_KERN + 4) +#define PZERO (PRI_MIN_KERN + 5) +#define PSOCK (PRI_MIN_KERN + 6) +#define PWAIT (PRI_MIN_KERN + 7) +#define PLOCK (PRI_MIN_KERN + 8) +#define PPAUSE (PRI_MIN_KERN + 9) + +#define PRI_MIN_TIMESHARE (56) #define PRI_MAX_TIMESHARE (PRI_MIN_IDLE - 1) #define PUSER (PRI_MIN_TIMESHARE) diff --git a/lib/libc/include/generic-freebsd/sys/priv.h b/lib/libc/include/generic-freebsd/sys/priv.h index b659da09f5bc..7ad062fda99f 100644 --- a/lib/libc/include/generic-freebsd/sys/priv.h +++ b/lib/libc/include/generic-freebsd/sys/priv.h @@ -105,7 +105,8 @@ #define PRIV_CRED_SETRESGID 58 /* setresgid. */ #define PRIV_SEEOTHERGIDS 59 /* Exempt bsd.seeothergids. */ #define PRIV_SEEOTHERUIDS 60 /* Exempt bsd.seeotheruids. */ -#define PRIV_SEEJAILPROC 61 /* Exempt from bsd.see_jail_proc. */ +#define PRIV_SEEJAILPROC 61 /* Exempt from bsd.see_jail_proc. */ +#define PRIV_CRED_SETCRED 62 /* setcred. */ /* * Debugging privileges. @@ -114,6 +115,7 @@ #define PRIV_DEBUG_SUGID 81 /* Exempt debugging setuid proc. */ #define PRIV_DEBUG_UNPRIV 82 /* Exempt unprivileged debug limit. */ #define PRIV_DEBUG_DENIED 83 /* Exempt P2_NOTRACE. */ +#define PRIV_DEBUG_DIFFJAIL 84 /* Exempt debugging other jails. */ /* * Dtrace privileges. @@ -192,6 +194,7 @@ #define PRIV_SCHED_CPUSET 206 /* Can manipulate cpusets. */ #define PRIV_SCHED_CPUSET_INTR 207 /* Can adjust IRQ to CPU binding. */ #define PRIV_SCHED_IDPRIO 208 /* Can set idle time scheduling. */ +#define PRIV_SCHED_DIFFJAIL 209 /* Exempt scheduling other jails. */ /* * POSIX semaphore privileges. @@ -203,6 +206,7 @@ */ #define PRIV_SIGNAL_DIFFCRED 230 /* Exempt signalling other users. */ #define PRIV_SIGNAL_SUGID 231 /* Non-conserv signal setuid proc. */ +#define PRIV_SIGNAL_DIFFJAIL 232 /* Exempt signalling other jails. */ /* * Sysctl privileges. @@ -210,6 +214,7 @@ #define PRIV_SYSCTL_DEBUG 240 /* Can invoke sysctl.debug. */ #define PRIV_SYSCTL_WRITE 241 /* Can write sysctls. */ #define PRIV_SYSCTL_WRITEJAIL 242 /* Can write sysctls, jail permitted. */ +#define PRIV_SYSCTL_MEMLOCK 243 /* Large requests are not serialized. */ /* * TTY privileges. @@ -404,6 +409,7 @@ #define PRIV_NETINET_SETHDROPTS 505 /* Set certain IPv4/6 header options. */ #define PRIV_NETINET_BINDANY 506 /* Allow bind to any address. */ #define PRIV_NETINET_HASHKEY 507 /* Get and set hash keys for IPv4/6. */ +#define PRIV_NETINET_KTLSKEYS 508 /* Read ktls session keys. */ /* * Placeholders for IPX/SPX privileges, not supported any more. @@ -515,6 +521,7 @@ */ #define PRIV_KMEM_READ 680 /* Open mem/kmem for reading. */ #define PRIV_KMEM_WRITE 681 /* Open mem/kmem for writing. */ +#define PRIV_PROC_MEM_WRITE 682 /* Writes via proc_rwmem */ /* * Kernel debugger privileges. diff --git a/lib/libc/include/generic-freebsd/sys/proc.h b/lib/libc/include/generic-freebsd/sys/proc.h index 9a96b377f799..dc092f825409 100644 --- a/lib/libc/include/generic-freebsd/sys/proc.h +++ b/lib/libc/include/generic-freebsd/sys/proc.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)proc.h 8.15 (Berkeley) 5/19/95 */ #ifndef _SYS_PROC_H_ @@ -44,6 +42,7 @@ #ifdef _KERNEL #include #endif +#include #include #ifndef _KERNEL #include @@ -55,7 +54,6 @@ #include #include #include /* XXX. */ -#include #include #include #include @@ -249,7 +247,7 @@ struct thread { struct seltd *td_sel; /* Select queue/channel. */ struct sleepqueue *td_sleepqueue; /* (k) Associated sleep queue. */ struct turnstile *td_turnstile; /* (k) Associated turnstile. */ - struct rl_q_entry *td_rlqe; /* (k) Associated range lock entry. */ + void *td_pad1; /* Available */ struct umtx_q *td_umtxq; /* (c?) Link for when we're blocked. */ lwpid_t td_tid; /* (b) Thread ID. */ sigqueue_t td_sigqueue; /* (c) Sigs arrived, not delivered. */ @@ -272,11 +270,12 @@ struct thread { const char *td_wmesg; /* (t) Reason for sleep. */ volatile u_char td_owepreempt; /* (k*) Preempt on last critical_exit */ u_char td_tsqueue; /* (t) Turnstile queue blocked on. */ - u_char td_stopsched; /* (k) Scheduler stopped. */ + u_char _td_pad0[2]; /* Available. */ int td_locks; /* (k) Debug: count of non-spin locks */ int td_rw_rlocks; /* (k) Count of rwlock read locks. */ int td_sx_slocks; /* (k) Count of sx shared locks. */ int td_lk_slocks; /* (k) Count of lockmgr shared locks. */ + struct lock_object *td_wantedlock; /* (k) Lock we are contending on */ struct turnstile *td_blocked; /* (t) Lock thread is blocked on. */ const char *td_lockname; /* (t) Name of lock blocked on. */ LIST_HEAD(, turnstile) td_contested; /* (q) Contested locks. */ @@ -314,8 +313,8 @@ struct thread { struct osd td_osd; /* (k) Object specific data. */ struct vm_map_entry *td_map_def_user; /* (k) Deferred entries. */ pid_t td_dbg_forked; /* (c) Child pid for debugger. */ - struct vnode *td_vp_reserved;/* (k) Preallocated vnode. */ u_int td_no_sleeping; /* (k) Sleeping disabled count. */ + struct vnode *td_vp_reserved;/* (k) Preallocated vnode. */ void *td_su; /* (k) FFS SU private */ sbintime_t td_sleeptimo; /* (t) Sleep timeout. */ int td_rtcgen; /* (s) rtc_generation of abs. sleep */ @@ -323,6 +322,7 @@ struct thread { size_t td_vslock_sz; /* (k) amount of vslock-ed space */ struct kcov_info *td_kcov_info; /* (*) Kernel code coverage data */ long td_ucredref; /* (k) references on td_realucred */ + struct kexterr td_kexterr; #define td_endzero td_sigmask /* Copied during fork1(), thread_create(), or kthread_add(). */ @@ -342,6 +342,7 @@ struct thread { void *td_sigblock_ptr; /* (k) uptr for fast sigblock. */ uint32_t td_sigblock_val; /* (k) fast sigblock value read at td_sigblock_ptr on kern entry */ + void *td_exterr_ptr; #define td_endcopy td_pcb /* @@ -367,7 +368,8 @@ struct thread { struct callout td_slpcallout; /* (h) Callout for sleep. */ struct trapframe *td_frame; /* (k) */ vm_offset_t td_kstack; /* (a) Kernel VA of kstack. */ - int td_kstack_pages; /* (a) Size of the kstack. */ + u_short td_kstack_pages; /* (a) Size of the kstack. */ + u_short td_kstack_domain; /* (a) Domain backing kstack KVA. */ volatile u_int td_critnest; /* (k*) Critical section nest level. */ struct mdthread td_md; /* (k) Any machine-dependent fields. */ struct kaudit_record *td_ar; /* (k) Active audit record, if any. */ @@ -430,7 +432,7 @@ do { \ #define TD_LOCKS_INC(td) ((td)->td_locks++) #define TD_LOCKS_DEC(td) do { \ - KASSERT(SCHEDULER_STOPPED_TD(td) || (td)->td_locks > 0, \ + KASSERT(SCHEDULER_STOPPED() || (td)->td_locks > 0, \ ("Thread %p owns no locks", (td))); \ (td)->td_locks--; \ } while (0) @@ -452,7 +454,7 @@ do { \ #define TDF_SINTR 0x00000008 /* Sleep is interruptible. */ #define TDF_TIMEOUT 0x00000010 /* Timing out during sleep. */ #define TDF_IDLETD 0x00000020 /* This is a per-CPU idle thread. */ -#define TDF_CANSWAP 0x00000040 /* Thread can be swapped. */ +#define TDF_UNUSED11 0x00000040 /* Available */ #define TDF_SIGWAIT 0x00000080 /* Ignore ignored signals */ #define TDF_KTH_SUSP 0x00000100 /* kthread is suspended */ #define TDF_ALLPROCSUSP 0x00000200 /* suspended by SINGLE_ALLPROC */ @@ -468,7 +470,7 @@ do { \ #define TDF_SERESTART 0x00080000 /* ERESTART on stop attempts. */ #define TDF_THRWAKEUP 0x00100000 /* Libthr thread must not suspend itself. */ #define TDF_SEINTR 0x00200000 /* EINTR on stop attempts. */ -#define TDF_SWAPINREQ 0x00400000 /* Swapin request due to wakeup. */ +#define TDF_UNUSED12 0x00400000 /* Available */ #define TDF_UNUSED6 0x00800000 /* Available */ #define TDF_SCHED0 0x01000000 /* Reserved for scheduler private use */ #define TDF_SCHED1 0x02000000 /* Reserved for scheduler private use */ @@ -493,13 +495,14 @@ enum { TDA_KQUEUE, TDA_RACCT, TDA_MOD1, /* For third party use, before signals are */ - TAD_MOD2, /* processed .. */ + TDA_MOD2, /* processed .. */ + TDA_PSELECT, /* For discarding temporary signal mask */ TDA_SIG, TDA_KTRACE, TDA_SUSPEND, TDA_SIGSUSPEND, TDA_MOD3, /* .. and after */ - TAD_MOD4, + TDA_MOD4, TDA_MAX, }; #define TDAI(tda) (1U << (tda)) @@ -560,13 +563,16 @@ enum { #define TDP_RESETSPUR 0x04000000 /* Reset spurious page fault history. */ #define TDP_NERRNO 0x08000000 /* Last errno is already in td_errno */ #define TDP_UIOHELD 0x10000000 /* Current uio has pages held in td_ma */ -#define TDP_INTCPCALLOUT 0x20000000 /* used by netinet/tcp_timer.c */ +#define TDP_EFIRT 0x20000000 /* In firmware (EFI RT) call */ #define TDP_EXECVMSPC 0x40000000 /* Execve destroyed old vmspace */ #define TDP_SIGFASTPENDING 0x80000000 /* Pending signal due to sigfastblock */ #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 */ +#define TDP2_EXTERR 0x00000010 /* Kernel reported ext error */ +#define TDP2_UEXTERR 0x00000020 /* User set ext error reporting ptr */ /* * Reasons that the current thread can not be run yet. @@ -574,14 +580,12 @@ enum { */ #define TDI_SUSPENDED 0x0001 /* On suspension queue. */ #define TDI_SLEEPING 0x0002 /* Actually asleep! (tricky). */ -#define TDI_SWAPPED 0x0004 /* Stack not in mem. Bad juju if run. */ #define TDI_LOCK 0x0008 /* Stopped on a lock. */ #define TDI_IWAIT 0x0010 /* Awaiting interrupt. */ #define TD_IS_SLEEPING(td) ((td)->td_inhibitors & TDI_SLEEPING) #define TD_ON_SLEEPQ(td) ((td)->td_wchan != NULL) #define TD_IS_SUSPENDED(td) ((td)->td_inhibitors & TDI_SUSPENDED) -#define TD_IS_SWAPPED(td) ((td)->td_inhibitors & TDI_SWAPPED) #define TD_ON_LOCK(td) ((td)->td_inhibitors & TDI_LOCK) #define TD_AWAITING_INTR(td) ((td)->td_inhibitors & TDI_IWAIT) #ifdef _KERNEL @@ -602,7 +606,6 @@ enum { #define KTDSTATE(td) \ (((td)->td_inhibitors & TDI_SLEEPING) != 0 ? "sleep" : \ ((td)->td_inhibitors & TDI_SUSPENDED) != 0 ? "suspended" : \ - ((td)->td_inhibitors & TDI_SWAPPED) != 0 ? "swapped" : \ ((td)->td_inhibitors & TDI_LOCK) != 0 ? "blocked" : \ ((td)->td_inhibitors & TDI_IWAIT) != 0 ? "iwait" : "yielding") @@ -618,14 +621,12 @@ enum { } while (0) #define TD_SET_SLEEPING(td) TD_SET_INHIB((td), TDI_SLEEPING) -#define TD_SET_SWAPPED(td) TD_SET_INHIB((td), TDI_SWAPPED) #define TD_SET_LOCK(td) TD_SET_INHIB((td), TDI_LOCK) #define TD_SET_SUSPENDED(td) TD_SET_INHIB((td), TDI_SUSPENDED) #define TD_SET_IWAIT(td) TD_SET_INHIB((td), TDI_IWAIT) #define TD_SET_EXITING(td) TD_SET_INHIB((td), TDI_EXITING) #define TD_CLR_SLEEPING(td) TD_CLR_INHIB((td), TDI_SLEEPING) -#define TD_CLR_SWAPPED(td) TD_CLR_INHIB((td), TDI_SWAPPED) #define TD_CLR_LOCK(td) TD_CLR_INHIB((td), TDI_LOCK) #define TD_CLR_SUSPENDED(td) TD_CLR_INHIB((td), TDI_SUSPENDED) #define TD_CLR_IWAIT(td) TD_CLR_INHIB((td), TDI_IWAIT) @@ -704,7 +705,7 @@ struct proc { struct vnode *p_textvp; /* (b) Vnode of executable. */ struct vnode *p_textdvp; /* (b) Dir containing textvp. */ char *p_binname; /* (b) Binary hardlink name. */ - u_int p_lock; /* (c) Proclock (prevent swap) count. */ + u_int p_lock; /* (c) Prevent exit. */ struct sigiolst p_sigiolst; /* (c) List of sigio sources. */ int p_sigparent; /* (c) Signal to parent on exit. */ int p_sig; /* (n) For core dump/debugger XXX. */ @@ -714,7 +715,7 @@ struct proc { int p_suspcount; /* (j) Num threads in suspended mode. */ struct thread *p_xthread; /* (c) Trap thread */ int p_boundary_count;/* (j) Num threads at user boundary */ - int p_pendingcnt; /* how many signals are pending */ + int p_pendingcnt; /* (c) how many signals are pending */ struct itimers *p_itimers; /* (c) POSIX interval timers. */ struct procdesc *p_procdesc; /* (e) Process descriptor, if any. */ u_int p_treeflag; /* (e) P_TREE flags */ @@ -762,7 +763,6 @@ struct proc { LIST_HEAD(, mqueue_notifier) p_mqnotifier; /* (c) mqueue notifiers.*/ struct kdtrace_proc *p_dtrace; /* (*) DTrace-specific data. */ struct cv p_pwait; /* (*) wait cv for exit/exec. */ - uint64_t p_prev_runtime; /* (c) Resource usage accounting. */ struct racct *p_racct; /* (b) Resource accounting. */ int p_throttled; /* (c) Flag for racct pcpu throttling */ /* @@ -806,7 +806,7 @@ struct proc { lock. */ #define P_CONTROLT 0x00000002 /* Has a controlling terminal. */ #define P_KPROC 0x00000004 /* Kernel process. */ -#define P_UNUSED3 0x00000008 /* --available-- */ +#define P_IDLEPROC 0x00000008 /* Container for system idle threads. */ #define P_PPWAIT 0x00000010 /* Parent is waiting for child to exec/exit. */ #define P_PROFIL 0x00000020 /* Has started profiling. */ @@ -816,8 +816,7 @@ struct proc { shortcuts) */ #define P_SUGID 0x00000100 /* Had set id privileges since last exec. */ -#define P_SYSTEM 0x00000200 /* System proc: no sigs, stats or - swapping. */ +#define P_SYSTEM 0x00000200 /* System proc: no sigs or stats. */ #define P_SINGLE_EXIT 0x00000400 /* Threads suspending should exit, not wait. */ #define P_TRACED 0x00000800 /* Debugged process being traced. */ @@ -841,9 +840,9 @@ struct proc { #define P_TOTAL_STOP 0x02000000 /* Stopped in stop_all_proc. */ #define P_INEXEC 0x04000000 /* Process is in execve(). */ #define P_STATCHILD 0x08000000 /* Child process stopped or exited. */ -#define P_INMEM 0x10000000 /* Loaded into memory. */ -#define P_SWAPPINGOUT 0x20000000 /* Process is being swapped out. */ -#define P_SWAPPINGIN 0x40000000 /* Process is being swapped in. */ +#define P_INMEM 0x10000000 /* Loaded into memory, always set. */ +#define P_UNUSED1 0x20000000 /* --available-- */ +#define P_UNUSED2 0x40000000 /* --available-- */ #define P_PPTRACE 0x80000000 /* PT_TRACEME by vforked child. */ #define P_STOPPED (P_STOPPED_SIG|P_STOPPED_SINGLE|P_STOPPED_TRACE) @@ -874,7 +873,7 @@ struct proc { MAP_STACK */ #define P2_STKGAP_DISABLE_EXEC 0x00001000 /* Stack gap disabled after exec */ -#define P2_ITSTOPPED 0x00002000 +#define P2_ITSTOPPED 0x00002000 /* itimers stopped */ #define P2_PTRACEREQ 0x00004000 /* Active ptrace req */ #define P2_NO_NEW_PRIVS 0x00008000 /* Ignore setuid */ #define P2_WXORX_DISABLE 0x00010000 /* WX mappings enabled */ @@ -882,7 +881,7 @@ struct proc { #define P2_WEXIT 0x00040000 /* exit just started, no external thread_single() is permitted */ -#define P2_REAPKILLED 0x00080000 +#define P2_REAPKILLED 0x00080000 /* REAP_KILL pass touched me */ #define P2_MEMBAR_PRIVE 0x00100000 /* membar private expedited registered */ #define P2_MEMBAR_PRIVE_SYNCORE 0x00200000 /* membar private expedited @@ -890,6 +889,11 @@ struct proc { #define P2_MEMBAR_GLOBE 0x00400000 /* membar global expedited registered */ +#define P2_LOGSIGEXIT_ENABLE 0x00800000 /* Disable logging on sigexit */ +#define P2_LOGSIGEXIT_CTL 0x01000000 /* Override kern.logsigexit */ + +#define P2_HWT 0x02000000 /* Process is using HWT. */ + /* Flags protected by proctree_lock, kept in p_treeflags. */ #define P_TREE_ORPHANED 0x00000001 /* Reparented, on orphan list */ #define P_TREE_FIRST_ORPHAN 0x00000002 /* First element of orphan @@ -938,12 +942,6 @@ struct proc { #define SINGLE_BOUNDARY 2 #define SINGLE_ALLPROC 3 -#ifdef MALLOC_DECLARE -MALLOC_DECLARE(M_PARGS); -MALLOC_DECLARE(M_SESSION); -MALLOC_DECLARE(M_SUBPROC); -#endif - #define FOREACH_PROC_IN_SYSTEM(p) \ LIST_FOREACH((p), &allproc, p_list) #define FOREACH_THREAD_IN_PROC(p, td) \ @@ -956,7 +954,7 @@ MALLOC_DECLARE(M_SUBPROC); * in a pid_t, as it is used to represent "no process group". */ #define PID_MAX 99999 -#define NO_PID 100000 +#define NO_PID (PID_MAX + 1) #define THREAD0_TID NO_PID extern pid_t pid_max; @@ -992,18 +990,12 @@ extern pid_t pid_max; #define SESS_LOCK_ASSERT(s, type) mtx_assert(&(s)->s_mtx, (type)) /* - * Non-zero p_lock ensures that: - * - exit1() is not performed until p_lock reaches zero; - * - the process' threads stack are not swapped out if they are currently - * not (P_INMEM). + * A non-zero p_lock prevents the process from exiting; it will sleep in exit1() + * until the count reaches zero. * * PHOLD() asserts that the process (except the current process) is - * not exiting, increments p_lock and swaps threads stacks into memory, - * if needed. + * not exiting and increments p_lock. * _PHOLD() is same as PHOLD(), it takes the process locked. - * _PHOLD_LITE() also takes the process locked, but comparing with - * _PHOLD(), it only guarantees that exit1() is not executed, - * faultin() is not called. */ #define PHOLD(p) do { \ PROC_LOCK(p); \ @@ -1015,14 +1007,6 @@ extern pid_t pid_max; KASSERT(!((p)->p_flag & P_WEXIT) || (p) == curproc, \ ("PHOLD of exiting process %p", p)); \ (p)->p_lock++; \ - if (((p)->p_flag & P_INMEM) == 0) \ - faultin((p)); \ -} while (0) -#define _PHOLD_LITE(p) do { \ - PROC_LOCK_ASSERT((p), MA_OWNED); \ - KASSERT(!((p)->p_flag & P_WEXIT) || (p) == curproc, \ - ("PHOLD of exiting process %p", p)); \ - (p)->p_lock++; \ } while (0) #define PROC_ASSERT_HELD(p) do { \ KASSERT((p)->p_lock > 0, ("process %p not held", p)); \ @@ -1058,9 +1042,6 @@ extern pid_t pid_max; _p->p_cowgen - _td->td_cowgen; \ }) -/* Check whether a thread is safe to be swapped out. */ -#define thread_safetoswapout(td) ((td)->td_flags & TDF_CANSWAP) - /* Control whether or not it is safe for curthread to sleep. */ #define THREAD_NO_SLEEPING() do { \ curthread->td_no_sleeping++; \ @@ -1074,6 +1055,16 @@ extern pid_t pid_max; #define THREAD_CAN_SLEEP() ((curthread)->td_no_sleeping == 0) +#define THREAD_CONTENDS_ON_LOCK(lo) do { \ + MPASS(curthread->td_wantedlock == NULL); \ + curthread->td_wantedlock = lo; \ +} while (0) + +#define THREAD_CONTENTION_DONE(lo) do { \ + MPASS(curthread->td_wantedlock == lo); \ + curthread->td_wantedlock = NULL; \ +} while (0) + #define PIDHASH(pid) (&pidhashtbl[(pid) & pidhash]) #define PIDHASHLOCK(pid) (&pidhashtbl_lock[((pid) & pidhashlock)]) extern LIST_HEAD(pidhashhead, proc) *pidhashtbl; @@ -1170,7 +1161,6 @@ int cr_cansignal(struct ucred *cred, struct proc *proc, int signum); int enterpgrp(struct proc *p, pid_t pgid, struct pgrp *pgrp, struct session *sess); int enterthispgrp(struct proc *p, struct pgrp *pgrp); -void faultin(struct proc *p); int fork1(struct thread *, struct fork_req *); void fork_exit(void (*)(void *, struct trapframe *), void *, struct trapframe *); @@ -1181,7 +1171,6 @@ void kqtimer_proc_continue(struct proc *p); void kern_proc_vmmap_resident(struct vm_map *map, struct vm_map_entry *entry, int *resident_count, bool *super); void kern_yield(int); -void kick_proc0(void); void killjobc(void); int leavepgrp(struct proc *p); int maybe_preempt(struct thread *td); @@ -1195,6 +1184,7 @@ int p_canwait(struct thread *td, struct proc *p); struct pargs *pargs_alloc(int len); void pargs_drop(struct pargs *pa); void pargs_hold(struct pargs *pa); +int pgrp_calc_jobc(struct pgrp *pgrp); void proc_add_orphan(struct proc *child, struct proc *parent); int proc_get_binpath(struct proc *p, char *binname, char **fullpath, char **freepath); @@ -1220,7 +1210,7 @@ int securelevel_ge(struct ucred *cr, int level); int securelevel_gt(struct ucred *cr, int level); void sess_hold(struct session *); void sess_release(struct session *); -int setrunnable(struct thread *, int); +void setrunnable(struct thread *, int); void setsugid(struct proc *p); bool should_yield(void); int sigonstack(size_t sp); @@ -1235,6 +1225,7 @@ extern void (*cpu_idle_hook)(sbintime_t); /* Hook to machdep CPU idler. */ void cpu_switch(struct thread *, struct thread *, struct mtx *); void cpu_sync_core(void); void cpu_throw(struct thread *, struct thread *) __dead2; +void cpu_update_pcb(struct thread *); bool curproc_sigkilled(void); void userret(struct thread *, struct trapframe *); @@ -1250,15 +1241,12 @@ int cpu_procctl(struct thread *td, int idtype, id_t id, int com, void cpu_set_syscall_retval(struct thread *, int); int cpu_set_upcall(struct thread *, void (*)(void *), void *, stack_t *); -int cpu_set_user_tls(struct thread *, void *tls_base); +int cpu_set_user_tls(struct thread *, void *tls_base, int flags); void cpu_thread_alloc(struct thread *); void cpu_thread_clean(struct thread *); void cpu_thread_exit(struct thread *); void cpu_thread_free(struct thread *); -void cpu_thread_swapin(struct thread *); -void cpu_thread_swapout(struct thread *); struct thread *thread_alloc(int pages); -int thread_alloc_stack(struct thread *, int pages); int thread_check_susp(struct thread *td, bool sleep); void thread_cow_get_proc(struct thread *newtd, struct proc *p); void thread_cow_get(struct thread *newtd, struct thread *td); @@ -1271,6 +1259,7 @@ void thread_exit(void) __dead2; void thread_free(struct thread *td); void thread_link(struct thread *td, struct proc *p); void thread_reap_barrier(void); +int thread_recycle(struct thread *, int pages); int thread_single(struct proc *p, int how); void thread_single_end(struct proc *p, int how); void thread_stash(struct thread *td); diff --git a/lib/libc/include/generic-freebsd/sys/procctl.h b/lib/libc/include/generic-freebsd/sys/procctl.h index f3df63731998..ac7abfacca75 100644 --- a/lib/libc/include/generic-freebsd/sys/procctl.h +++ b/lib/libc/include/generic-freebsd/sys/procctl.h @@ -65,6 +65,8 @@ #define PROC_NO_NEW_PRIVS_STATUS 20 /* query suid/sgid disabled status */ #define PROC_WXMAP_CTL 21 /* control W^X */ #define PROC_WXMAP_STATUS 22 /* query W^X */ +#define PROC_LOGSIGEXIT_CTL 23 /* en/dis logging on sigexit */ +#define PROC_LOGSIGEXIT_STATUS 24 /* query logging on sigexit */ /* Operations for PROC_SPROTECT (passed in integer arg). */ #define PPROT_OP(x) ((x) & 0xf) @@ -153,6 +155,10 @@ struct procctl_reaper_kill { #define PROC_WX_MAPPINGS_DISALLOW_EXEC 0x0002 #define PROC_WXORX_ENFORCE 0x80000000 +#define PROC_LOGSIGEXIT_CTL_NOFORCE 1 +#define PROC_LOGSIGEXIT_CTL_FORCE_ENABLE 2 +#define PROC_LOGSIGEXIT_CTL_FORCE_DISABLE 3 + #ifndef _KERNEL __BEGIN_DECLS int procctl(idtype_t, id_t, int, void *); diff --git a/lib/libc/include/generic-freebsd/sys/procdesc.h b/lib/libc/include/generic-freebsd/sys/procdesc.h index a257b1e20543..21e0ea9f84a9 100644 --- a/lib/libc/include/generic-freebsd/sys/procdesc.h +++ b/lib/libc/include/generic-freebsd/sys/procdesc.h @@ -94,8 +94,10 @@ struct procdesc { * In-kernel interfaces to process descriptors. */ int procdesc_exit(struct proc *); -int procdesc_find(struct thread *, int fd, cap_rights_t *, struct proc **); -int kern_pdgetpid(struct thread *, int fd, cap_rights_t *, pid_t *pidp); +int procdesc_find(struct thread *, int fd, const cap_rights_t *, + struct proc **); +int kern_pdgetpid(struct thread *, int fd, const cap_rights_t *, + pid_t *pidp); void procdesc_new(struct proc *, int); void procdesc_finit(struct procdesc *, struct file *); pid_t procdesc_pid(struct file *); @@ -106,6 +108,7 @@ int procdesc_falloc(struct thread *, struct file **, int *, int, #else /* !_KERNEL */ +#include #include #ifndef _PID_T_DECLARED diff --git a/lib/libc/include/generic-freebsd/sys/protosw.h b/lib/libc/include/generic-freebsd/sys/protosw.h index 912810237975..3fc387f2b360 100644 --- a/lib/libc/include/generic-freebsd/sys/protosw.h +++ b/lib/libc/include/generic-freebsd/sys/protosw.h @@ -27,24 +27,11 @@ * 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. - * - * @(#)protosw.h 8.1 (Berkeley) 6/2/93 */ #ifndef _SYS_PROTOSW_H_ #define _SYS_PROTOSW_H_ - -#include - -/* Forward declare these structures referenced from prototypes below. */ -struct kaiocb; -struct mbuf; -struct thread; -struct sockaddr; -struct socket; -struct sockopt; - -/*#ifdef _KERNEL*/ +#if defined(_KERNEL) || defined(_WANT_PROTOSW) /* * Protocol switch table. * @@ -54,16 +41,24 @@ struct sockopt; * In retrospect, it would be a lot nicer to use an interface * similar to the vnode VOP interface. */ +struct socket; +struct sockopt; +struct thread; +struct sockaddr; struct ifnet; +struct mbuf; struct stat; struct ucred; struct uio; +struct kaiocb; +struct knote; +enum shutdown_how; /* USE THESE FOR YOUR PROTOTYPES ! */ typedef int pr_ctloutput_t(struct socket *, struct sockopt *); typedef int pr_setsbopt_t(struct socket *, struct sockopt *); typedef void pr_abort_t(struct socket *); -typedef int pr_accept_t(struct socket *, struct sockaddr **); +typedef int pr_accept_t(struct socket *, struct sockaddr *); typedef int pr_attach_t(struct socket *, int, struct thread *); typedef int pr_bind_t(struct socket *, struct sockaddr *, struct thread *); typedef int pr_connect_t(struct socket *, struct sockaddr *, @@ -74,7 +69,7 @@ typedef int pr_control_t(struct socket *, unsigned long, void *, typedef void pr_detach_t(struct socket *); typedef int pr_disconnect_t(struct socket *); typedef int pr_listen_t(struct socket *, int, struct thread *); -typedef int pr_peeraddr_t(struct socket *, struct sockaddr **); +typedef int pr_peeraddr_t(struct socket *, struct sockaddr *); typedef int pr_rcvd_t(struct socket *, int); typedef int pr_rcvoob_t(struct socket *, struct mbuf *, int); typedef enum { @@ -86,17 +81,17 @@ typedef enum { } pr_send_flags_t; typedef int pr_send_t(struct socket *, int, struct mbuf *, struct sockaddr *, struct mbuf *, struct thread *); +typedef int pr_sendfile_wait_t(struct socket *, off_t, int *); typedef int pr_ready_t(struct socket *, struct mbuf *, int); typedef int pr_sense_t(struct socket *, struct stat *); -typedef int pr_shutdown_t(struct socket *); -typedef int pr_flush_t(struct socket *, int); -typedef int pr_sockaddr_t(struct socket *, struct sockaddr **); +typedef int pr_shutdown_t(struct socket *, enum shutdown_how); +typedef int pr_sockaddr_t(struct socket *, struct sockaddr *); typedef int pr_sosend_t(struct socket *, struct sockaddr *, struct uio *, struct mbuf *, struct mbuf *, int, struct thread *); typedef int pr_soreceive_t(struct socket *, struct sockaddr **, struct uio *, struct mbuf **, struct mbuf **, int *); -typedef int pr_sopoll_t(struct socket *, int, struct ucred *, - struct thread *); +typedef int pr_sopoll_t(struct socket *, int, struct thread *); +typedef int pr_kqfilter_t(struct socket *, struct knote *); typedef void pr_sosetlabel_t(struct socket *); typedef void pr_close_t(struct socket *); typedef int pr_bindat_t(int, struct socket *, struct sockaddr *, @@ -104,6 +99,8 @@ typedef int pr_bindat_t(int, struct socket *, struct sockaddr *, typedef int pr_connectat_t(int, struct socket *, struct sockaddr *, struct thread *); typedef int pr_aio_queue_t(struct socket *, struct kaiocb *); +typedef int pr_chmod_t(struct socket *, __mode_t, struct ucred *, + struct thread *); struct protosw { short pr_type; /* socket type used for */ @@ -113,9 +110,9 @@ struct protosw { struct domain *pr_domain; /* domain protocol a member of */ pr_soreceive_t *pr_soreceive; /* recv(2) */ - pr_rcvd_t *pr_rcvd; /* soreceive_generic() if PR_WANTRCVD */ pr_sosend_t *pr_sosend; /* send(2) */ pr_send_t *pr_send; /* send(2) via sosend_generic() */ + pr_sendfile_wait_t *pr_sendfile_wait; /* sendfile helper */ pr_ready_t *pr_ready; /* sendfile/ktls readyness */ pr_sopoll_t *pr_sopoll; /* poll(2) */ /* Cache line #2 */ @@ -125,7 +122,7 @@ struct protosw { pr_disconnect_t *pr_disconnect; /* sodisconnect() */ pr_close_t *pr_close; /* close(2) */ pr_shutdown_t *pr_shutdown; /* shutdown(2) */ - pr_abort_t *pr_abort; /* abrupt tear down: soabort() */ + pr_rcvd_t *pr_rcvd; /* soreceive_generic() if PR_WANTRCVD */ pr_aio_queue_t *pr_aio_queue; /* aio(9) */ /* Cache line #3 */ pr_bind_t *pr_bind; /* bind(2) */ @@ -137,15 +134,18 @@ struct protosw { pr_control_t *pr_control; /* ioctl(2) */ pr_rcvoob_t *pr_rcvoob; /* soreceive_rcvoob() */ /* Cache line #4 */ + pr_abort_t *pr_abort; /* abrupt tear down: soabort() */ pr_ctloutput_t *pr_ctloutput; /* control output (from above) */ pr_peeraddr_t *pr_peeraddr; /* getpeername(2) */ pr_sockaddr_t *pr_sockaddr; /* getsockname(2) */ pr_sense_t *pr_sense; /* stat(2) */ - pr_flush_t *pr_flush; /* XXXGL: merge with pr_shutdown_t! */ pr_sosetlabel_t *pr_sosetlabel; /* MAC, XXXGL: remove */ pr_setsbopt_t *pr_setsbopt; /* Socket buffer ioctls */ + pr_chmod_t *pr_chmod; /* fchmod(2) */ + pr_kqfilter_t *pr_kqfilter; /* kevent(2) */ }; -/*#endif*/ +#endif /* defined(_KERNEL) || defined(_WANT_PROTOSW) */ +#ifdef _KERNEL /* * Values for pr_flags. @@ -162,37 +162,12 @@ struct protosw { #define PR_ADDR 0x02 /* addresses given with messages */ #define PR_CONNREQUIRED 0x04 /* connection required by protocol */ #define PR_WANTRCVD 0x08 /* want PRU_RCVD calls */ -#define PR_RIGHTS 0x10 /* passes capabilities */ +/* was PR_RIGHTS 0x10 passes capabilities */ #define PR_IMPLOPCL 0x20 /* implied open/close */ /* was PR_LASTHDR 0x40 enforce ipsec policy; last header */ #define PR_CAPATTACH 0x80 /* socket can attach in cap mode */ #define PR_SOCKBUF 0x100 /* private implementation of buffers */ -/* - * The arguments to ctloutput are: - * (*protosw[].pr_ctloutput)(req, so, level, optname, optval, p); - * req is one of the actions listed below, so is a (struct socket *), - * level is an indication of which protocol layer the option is intended. - * optname is a protocol dependent socket option request, - * optval is a pointer to a mbuf-chain pointer, for value-return results. - * The protocol is responsible for disposal of the mbuf chain *optval - * if supplied, - * the caller is responsible for any space held by *optval, when returned. - * A non-zero return from ctloutput gives an - * UNIX error number which should be passed to higher level software. - */ -#define PRCO_GETOPT 0 -#define PRCO_SETOPT 1 - -#define PRCO_NCMDS 2 - -#ifdef PRCOREQUESTS -char *prcorequests[] = { - "GETOPT", "SETOPT", -}; -#endif - -#ifdef _KERNEL struct domain *pffinddomain(int family); struct protosw *pffindproto(int family, int type, int proto); int protosw_register(struct domain *, struct protosw *); @@ -202,5 +177,4 @@ int protosw_unregister(struct protosw *); extern struct domain inetdomain; extern struct domain inet6domain; #endif - #endif \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/ptrace.h b/lib/libc/include/generic-freebsd/sys/ptrace.h index 1d1d4db0d32c..e621c0b689af 100644 --- a/lib/libc/include/generic-freebsd/sys/ptrace.h +++ b/lib/libc/include/generic-freebsd/sys/ptrace.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)ptrace.h 8.2 (Berkeley) 1/4/94 */ #ifndef _SYS_PTRACE_H_ @@ -89,8 +87,16 @@ #define PT_SC_REMOTE 44 /* Execute a syscall */ #define PT_FIRSTMACH 64 /* for machine-specific requests */ +#define PT_LASTMACH 127 #include /* machine-specific requests, if any */ +#ifdef _KERNEL +/* Space for ptrace commands not exposed directly to userspace. */ +#define PTINTERNAL_FIRST 128 +#define PTINTERNAL_LAST 191 +#define PTLINUX_GET_SC_ARGS (PTINTERNAL_FIRST + 0) +#endif + /* Events used with PT_GET_EVENT_MASK and PT_SET_EVENT_MASK */ #define PTRACE_EXEC 0x0001 #define PTRACE_SCE 0x0002 @@ -152,7 +158,7 @@ struct ptrace_lwpinfo32 { int pl_flags; /* LWP flags. */ sigset_t pl_sigmask; /* LWP signal mask */ sigset_t pl_siglist; /* LWP pending signal */ - struct siginfo32 pl_siginfo; /* siginfo for signal */ + struct __siginfo32 pl_siginfo; /* siginfo for signal */ char pl_tdname[MAXCOMLEN + 1]; /* LWP name. */ pid_t pl_child_pid; /* New child pid */ u_int pl_syscall_code; diff --git a/lib/libc/include/generic-freebsd/sys/qmath.h b/lib/libc/include/generic-freebsd/sys/qmath.h index cc388623d3c0..6c469e7d9cb9 100644 --- a/lib/libc/include/generic-freebsd/sys/qmath.h +++ b/lib/libc/include/generic-freebsd/sys/qmath.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2018 Netflix, Inc. + * Copyright (c) 2018-2024 Netflix, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -378,15 +378,18 @@ typedef u64q_t umaxq_t; #define Q_QMINQ(a, b) (Q_LT(a, b) ? (a) : (b)) /* - * Test if 'a' can be represented by 'b' with full accuracy (T) or not (F). - * The type casting has to be done to a's type so that any truncation caused by - * the casts will not affect the logic. + * Test if 'a' can be represented by 'b' with full accuracy (0) or not + * (EOVERFLOW). If 'b' has fewer integer and/or fractional bits than 'a', + * the integer and fractional values stored in 'a' must fit in the available + * number of integer and fractional bits in 'b'. */ -#define Q_QCANREPQ(a, b) \ - ((((Q_LTZ(a) && Q_SIGNED(b)) || !Q_LTZ(a)) && \ - Q_GIABSVAL(a) <= Q_TC(a, Q_IMAXVAL(b)) && \ - Q_GFABSVAL(a) <= Q_TC(a, Q_FMAXVAL(b))) ? \ - 0 : EOVERFLOW) +#define Q_QCANREPQ(a, b) (( \ + (!Q_LTZ(a) || Q_SIGNED(b)) \ + && ( Q_NIBITS(a) <= Q_NIBITS(b) \ + || 0 == (Q_GIABSVAL(a) & (~Q_TC(a, 0) << Q_NIBITS(b)))) \ + && ( Q_NFBITS(a) <= Q_NFBITS(b) \ + || 0 == (Q_GFABSVAL(a) & ~(~Q_TC(a, 0) << (Q_NFBITS(a) - Q_NFBITS(b))))) \ + ) ? 0 : EOVERFLOW) /* Test if raw integer value 'i' can be represented by 'q' (T) or not (F). */ #define Q_QCANREPI(q, i) \ diff --git a/lib/libc/include/generic-freebsd/sys/queue.h b/lib/libc/include/generic-freebsd/sys/queue.h index 2a8c6942003b..15d07559fb8b 100644 --- a/lib/libc/include/generic-freebsd/sys/queue.h +++ b/lib/libc/include/generic-freebsd/sys/queue.h @@ -27,12 +27,10 @@ * 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. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 */ #ifndef _SYS_QUEUE_H_ -#define _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ #include @@ -113,15 +111,15 @@ * _REMOVE_HEAD + + + + * _REMOVE s + s + * _REPLACE - + - + + * _SPLIT_AFTER + + + + * _SWAP + + + + * */ #ifdef QUEUE_MACRO_DEBUG -#warn Use QUEUE_MACRO_DEBUG_TRACE and/or QUEUE_MACRO_DEBUG_TRASH -#define QUEUE_MACRO_DEBUG_TRACE -#define QUEUE_MACRO_DEBUG_TRASH +#warn Use QUEUE_MACRO_DEBUG_xxx instead (TRACE, TRASH and/or ASSERTIONS) +#define QUEUE_MACRO_DEBUG_TRACE +#define QUEUE_MACRO_DEBUG_TRASH #endif - #ifdef QUEUE_MACRO_DEBUG_TRACE /* Store the last 2 places the queue element or head was altered */ struct qm_trace { @@ -131,17 +129,17 @@ struct qm_trace { const char *prevfile; }; -#define TRACEBUF struct qm_trace trace; -#define TRACEBUF_INITIALIZER { __LINE__, 0, __FILE__, NULL } , +#define TRACEBUF struct qm_trace trace; +#define TRACEBUF_INITIALIZER { __LINE__, 0, __FILE__, NULL } , -#define QMD_TRACE_HEAD(head) do { \ +#define QMD_TRACE_HEAD(head) do { \ (head)->trace.prevline = (head)->trace.lastline; \ (head)->trace.prevfile = (head)->trace.lastfile; \ (head)->trace.lastline = __LINE__; \ (head)->trace.lastfile = __FILE__; \ } while (0) -#define QMD_TRACE_ELEM(elem) do { \ +#define QMD_TRACE_ELEM(elem) do { \ (elem)->trace.prevline = (elem)->trace.lastline; \ (elem)->trace.prevfile = (elem)->trace.lastfile; \ (elem)->trace.lastline = __LINE__; \ @@ -149,53 +147,110 @@ struct qm_trace { } while (0) #else /* !QUEUE_MACRO_DEBUG_TRACE */ -#define QMD_TRACE_ELEM(elem) -#define QMD_TRACE_HEAD(head) -#define TRACEBUF -#define TRACEBUF_INITIALIZER +#define QMD_TRACE_ELEM(elem) +#define QMD_TRACE_HEAD(head) +#define TRACEBUF +#define TRACEBUF_INITIALIZER #endif /* QUEUE_MACRO_DEBUG_TRACE */ #ifdef QUEUE_MACRO_DEBUG_TRASH -#define QMD_SAVELINK(name, link) void **name = (void *)&(link) -#define TRASHIT(x) do {(x) = (void *)-1;} while (0) -#define QMD_IS_TRASHED(x) ((x) == (void *)(intptr_t)-1) +#define QMD_SAVELINK(name, link) void **name = (void *)&(link) +#define TRASHIT(x) do {(x) = (void *)-1;} while (0) +#define QMD_IS_TRASHED(x) ((x) == (void *)(intptr_t)-1) #else /* !QUEUE_MACRO_DEBUG_TRASH */ -#define QMD_SAVELINK(name, link) -#define TRASHIT(x) -#define QMD_IS_TRASHED(x) 0 +#define QMD_SAVELINK(name, link) +#define TRASHIT(x) +#define QMD_IS_TRASHED(x) 0 #endif /* QUEUE_MACRO_DEBUG_TRASH */ +#if defined(QUEUE_MACRO_DEBUG_ASSERTIONS) && \ + defined(QUEUE_MACRO_NO_DEBUG_ASSERTIONS) +#error Both QUEUE_MACRO_DEBUG_ASSERTIONS and QUEUE_MACRO_NO_DEBUG_ASSERTIONS defined +#endif + +/* + * Automatically define QUEUE_MACRO_DEBUG_ASSERTIONS when compiling the kernel + * with INVARIANTS, if not already defined and not prevented by presence of + * QUEUE_MACRO_NO_DEBUG_ASSERTIONS. + */ +#if !defined(QUEUE_MACRO_DEBUG_ASSERTIONS) && \ + !defined(QUEUE_MACRO_NO_DEBUG_ASSERTIONS) && \ + (defined(_KERNEL) && defined(INVARIANTS)) +#define QUEUE_MACRO_DEBUG_ASSERTIONS +#endif + +/* + * If queue assertions are enabled, provide default definitions for QMD_PANIC() + * and QMD_ASSERT() if undefined. + */ +#ifdef QUEUE_MACRO_DEBUG_ASSERTIONS +#ifndef QMD_PANIC +#if defined(_KERNEL) || defined(_STANDALONE) +/* + * On _STANDALONE, either or the headers using provide + * a declaration or macro for panic(). + */ +#ifdef _KERNEL +#include +#endif +#define QMD_PANIC(fmt, ...) do { \ + panic(fmt, ##__VA_ARGS__); \ +} while (0) +#else /* !(_KERNEL || _STANDALONE) */ +#include +#include +#define QMD_PANIC(fmt, ...) do { \ + fprintf(stderr, fmt "\n", ##__VA_ARGS__); \ + abort(); \ +} while (0) +#endif /* _KERNEL || _STANDALONE */ +#endif /* !QMD_PANIC */ + +#ifndef QMD_ASSERT +#define QMD_ASSERT(expression, fmt, ...) do { \ + if (__predict_false(!(expression))) \ + QMD_PANIC("%s:%u: %s: " fmt, \ + __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ +} while (0) +#endif /* !QMD_ASSERT */ +#else /* !QUEUE_MACRO_DEBUG_ASSERTIONS */ +#undef QMD_ASSERT +#define QMD_ASSERT(test, fmt, ...) do {} while (0) +#endif /* QUEUE_MACRO_DEBUG_ASSERTIONS */ + + #ifdef __cplusplus /* * In C++ there can be structure lists and class lists: */ -#define QUEUE_TYPEOF(type) type +#define QUEUE_TYPEOF(type) type #else -#define QUEUE_TYPEOF(type) struct type +#define QUEUE_TYPEOF(type) struct type #endif /* * Singly-linked List declarations. */ -#define SLIST_HEAD(name, type) \ + +#define SLIST_HEAD(name, type) \ struct name { \ struct type *slh_first; /* first element */ \ } -#define SLIST_CLASS_HEAD(name, type) \ +#define SLIST_CLASS_HEAD(name, type) \ struct name { \ class type *slh_first; /* first element */ \ } -#define SLIST_HEAD_INITIALIZER(head) \ +#define SLIST_HEAD_INITIALIZER(head) \ { NULL } -#define SLIST_ENTRY(type) \ +#define SLIST_ENTRY(type) \ struct { \ struct type *sle_next; /* next element */ \ } -#define SLIST_CLASS_ENTRY(type) \ +#define SLIST_CLASS_ENTRY(type) \ struct { \ class type *sle_next; /* next element */ \ } @@ -203,137 +258,151 @@ struct { \ /* * Singly-linked List functions. */ -#if (defined(_KERNEL) && defined(INVARIANTS)) -#define QMD_SLIST_CHECK_PREVPTR(prevp, elm) do { \ - if (*(prevp) != (elm)) \ - panic("Bad prevptr *(%p) == %p != %p", \ - (prevp), *(prevp), (elm)); \ -} while (0) -#else -#define QMD_SLIST_CHECK_PREVPTR(prevp, elm) -#endif + +#define QMD_SLIST_CHECK_PREVPTR(prevp, elm) \ + QMD_ASSERT(*(prevp) == (elm), \ + "Bad prevptr *(%p) == %p != %p", \ + (prevp), *(prevp), (elm)) + +#define SLIST_ASSERT_EMPTY(head) \ + QMD_ASSERT(SLIST_EMPTY((head)), \ + "slist %p is not empty", (head)) + +#define SLIST_ASSERT_NONEMPTY(head) \ + QMD_ASSERT(!SLIST_EMPTY((head)), \ + "slist %p is empty", (head)) #define SLIST_CONCAT(head1, head2, type, field) do { \ - QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head1); \ - if (curelm == NULL) { \ + QUEUE_TYPEOF(type) *_Curelm = SLIST_FIRST(head1); \ + if (_Curelm == NULL) { \ if ((SLIST_FIRST(head1) = SLIST_FIRST(head2)) != NULL) \ SLIST_INIT(head2); \ } else if (SLIST_FIRST(head2) != NULL) { \ - while (SLIST_NEXT(curelm, field) != NULL) \ - curelm = SLIST_NEXT(curelm, field); \ - SLIST_NEXT(curelm, field) = SLIST_FIRST(head2); \ + while (SLIST_NEXT(_Curelm, field) != NULL) \ + _Curelm = SLIST_NEXT(_Curelm, field); \ + SLIST_NEXT(_Curelm, field) = SLIST_FIRST(head2); \ SLIST_INIT(head2); \ } \ } while (0) -#define SLIST_EMPTY(head) ((head)->slh_first == NULL) +#define SLIST_EMPTY(head) ((head)->slh_first == NULL) -#define SLIST_FIRST(head) ((head)->slh_first) +#define SLIST_EMPTY_ATOMIC(head) \ + (atomic_load_ptr(&(head)->slh_first) == NULL) -#define SLIST_FOREACH(var, head, field) \ +#define SLIST_FIRST(head) ((head)->slh_first) + +#define SLIST_FOREACH(var, head, field) \ for ((var) = SLIST_FIRST((head)); \ (var); \ (var) = SLIST_NEXT((var), field)) -#define SLIST_FOREACH_FROM(var, head, field) \ +#define SLIST_FOREACH_FROM(var, head, field) \ for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ (var); \ (var) = SLIST_NEXT((var), field)) -#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = SLIST_FIRST((head)); \ (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ (var) = (tvar)) -#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ +#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ (var) = (tvar)) -#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ +#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ for ((varp) = &SLIST_FIRST((head)); \ ((var) = *(varp)) != NULL; \ (varp) = &SLIST_NEXT((var), field)) -#define SLIST_INIT(head) do { \ +#define SLIST_INIT(head) do { \ SLIST_FIRST((head)) = NULL; \ } while (0) -#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ SLIST_NEXT((slistelm), field) = (elm); \ } while (0) -#define SLIST_INSERT_HEAD(head, elm, field) do { \ +#define SLIST_INSERT_HEAD(head, elm, field) do { \ SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ SLIST_FIRST((head)) = (elm); \ } while (0) -#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) -#define SLIST_REMOVE(head, elm, type, field) do { \ +#define SLIST_REMOVE(head, elm, type, field) do { \ if (SLIST_FIRST((head)) == (elm)) { \ SLIST_REMOVE_HEAD((head), field); \ } \ else { \ - QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head); \ - while (SLIST_NEXT(curelm, field) != (elm)) \ - curelm = SLIST_NEXT(curelm, field); \ - SLIST_REMOVE_AFTER(curelm, field); \ + QUEUE_TYPEOF(type) *_Curelm = SLIST_FIRST(head); \ + while (SLIST_NEXT(_Curelm, field) != (elm)) \ + _Curelm = SLIST_NEXT(_Curelm, field); \ + SLIST_REMOVE_AFTER(_Curelm, field); \ } \ } while (0) #define SLIST_REMOVE_AFTER(elm, field) do { \ - QMD_SAVELINK(oldnext, SLIST_NEXT(elm, field)->field.sle_next); \ + QMD_SAVELINK(_Oldnext, SLIST_NEXT(elm, field)->field.sle_next); \ SLIST_NEXT(elm, field) = \ SLIST_NEXT(SLIST_NEXT(elm, field), field); \ - TRASHIT(*oldnext); \ + TRASHIT(*_Oldnext); \ } while (0) -#define SLIST_REMOVE_HEAD(head, field) do { \ - QMD_SAVELINK(oldnext, SLIST_FIRST(head)->field.sle_next); \ +#define SLIST_REMOVE_HEAD(head, field) do { \ + QMD_SAVELINK(_Oldnext, SLIST_FIRST(head)->field.sle_next); \ SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ - TRASHIT(*oldnext); \ + TRASHIT(*_Oldnext); \ } while (0) -#define SLIST_REMOVE_PREVPTR(prevp, elm, field) do { \ +#define SLIST_REMOVE_PREVPTR(prevp, elm, field) do { \ QMD_SLIST_CHECK_PREVPTR(prevp, elm); \ *(prevp) = SLIST_NEXT(elm, field); \ TRASHIT((elm)->field.sle_next); \ } while (0) +#define SLIST_SPLIT_AFTER(head, elm, rest, field) do { \ + SLIST_ASSERT_NONEMPTY((head)); \ + SLIST_FIRST((rest)) = SLIST_NEXT((elm), field); \ + SLIST_NEXT((elm), field) = NULL; \ +} while (0) + #define SLIST_SWAP(head1, head2, type) do { \ - QUEUE_TYPEOF(type) *swap_first = SLIST_FIRST(head1); \ + QUEUE_TYPEOF(type) *_Swap_first = SLIST_FIRST(head1); \ SLIST_FIRST(head1) = SLIST_FIRST(head2); \ - SLIST_FIRST(head2) = swap_first; \ + SLIST_FIRST(head2) = _Swap_first; \ } while (0) -#define SLIST_END(head) NULL +#define SLIST_END(head) NULL /* * Singly-linked Tail queue declarations. */ -#define STAILQ_HEAD(name, type) \ + +#define STAILQ_HEAD(name, type) \ struct name { \ struct type *stqh_first;/* first element */ \ struct type **stqh_last;/* addr of last next element */ \ } -#define STAILQ_CLASS_HEAD(name, type) \ +#define STAILQ_CLASS_HEAD(name, type) \ struct name { \ class type *stqh_first; /* first element */ \ class type **stqh_last; /* addr of last next element */ \ } -#define STAILQ_HEAD_INITIALIZER(head) \ +#define STAILQ_HEAD_INITIALIZER(head) \ { NULL, &(head).stqh_first } -#define STAILQ_ENTRY(type) \ +#define STAILQ_ENTRY(type) \ struct { \ struct type *stqe_next; /* next element */ \ } -#define STAILQ_CLASS_ENTRY(type) \ +#define STAILQ_CLASS_ENTRY(type) \ struct { \ class type *stqe_next; /* next element */ \ } @@ -341,7 +410,38 @@ struct { \ /* * Singly-linked Tail queue functions. */ -#define STAILQ_CONCAT(head1, head2) do { \ + +/* + * QMD_STAILQ_CHECK_EMPTY(STAILQ_HEAD *head) + * + * Validates that the stailq head's pointer to the last element's next pointer + * actually points to the head's first element pointer field. + */ +#define QMD_STAILQ_CHECK_EMPTY(head) \ + QMD_ASSERT((head)->stqh_last == &(head)->stqh_first, \ + "Empty stailq %p->stqh_last is %p, " \ + "not head's first field address", \ + (head), (head)->stqh_last) + +/* + * QMD_STAILQ_CHECK_TAIL(STAILQ_HEAD *head) + * + * Validates that the stailq's last element's next pointer is NULL. + */ +#define QMD_STAILQ_CHECK_TAIL(head) \ + QMD_ASSERT(*(head)->stqh_last == NULL, \ + "Stailq %p last element's next pointer is " \ + "%p, not NULL", (head), *(head)->stqh_last) + +#define STAILQ_ASSERT_EMPTY(head) \ + QMD_ASSERT(STAILQ_EMPTY((head)), \ + "stailq %p is not empty", (head)) + +#define STAILQ_ASSERT_NONEMPTY(head) \ + QMD_ASSERT(!STAILQ_EMPTY((head)), \ + "stailq %p is empty", (head)) + +#define STAILQ_CONCAT(head1, head2) do { \ if (!STAILQ_EMPTY((head2))) { \ *(head1)->stqh_last = (head2)->stqh_first; \ (head1)->stqh_last = (head2)->stqh_last; \ @@ -349,72 +449,80 @@ struct { \ } \ } while (0) -#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) +#define STAILQ_EMPTY(head) ({ \ + if (STAILQ_FIRST(head) == NULL) \ + QMD_STAILQ_CHECK_EMPTY(head); \ + STAILQ_FIRST(head) == NULL; \ +}) + +#define STAILQ_EMPTY_ATOMIC(head) \ + (atomic_load_ptr(&(head)->stqh_first) == NULL) -#define STAILQ_FIRST(head) ((head)->stqh_first) +#define STAILQ_FIRST(head) ((head)->stqh_first) -#define STAILQ_FOREACH(var, head, field) \ +#define STAILQ_FOREACH(var, head, field) \ for((var) = STAILQ_FIRST((head)); \ (var); \ (var) = STAILQ_NEXT((var), field)) -#define STAILQ_FOREACH_FROM(var, head, field) \ +#define STAILQ_FOREACH_FROM(var, head, field) \ for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ (var); \ (var) = STAILQ_NEXT((var), field)) -#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = STAILQ_FIRST((head)); \ (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ (var) = (tvar)) -#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ +#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ (var) = (tvar)) -#define STAILQ_INIT(head) do { \ +#define STAILQ_INIT(head) do { \ STAILQ_FIRST((head)) = NULL; \ (head)->stqh_last = &STAILQ_FIRST((head)); \ } while (0) -#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ +#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ (head)->stqh_last = &STAILQ_NEXT((elm), field); \ STAILQ_NEXT((tqelm), field) = (elm); \ } while (0) -#define STAILQ_INSERT_HEAD(head, elm, field) do { \ +#define STAILQ_INSERT_HEAD(head, elm, field) do { \ if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ (head)->stqh_last = &STAILQ_NEXT((elm), field); \ STAILQ_FIRST((head)) = (elm); \ } while (0) -#define STAILQ_INSERT_TAIL(head, elm, field) do { \ +#define STAILQ_INSERT_TAIL(head, elm, field) do { \ + QMD_STAILQ_CHECK_TAIL(head); \ STAILQ_NEXT((elm), field) = NULL; \ *(head)->stqh_last = (elm); \ (head)->stqh_last = &STAILQ_NEXT((elm), field); \ } while (0) -#define STAILQ_LAST(head, type, field) \ +#define STAILQ_LAST(head, type, field) \ (STAILQ_EMPTY((head)) ? NULL : \ __containerof((head)->stqh_last, \ QUEUE_TYPEOF(type), field.stqe_next)) -#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) -#define STAILQ_REMOVE(head, elm, type, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \ +#define STAILQ_REMOVE(head, elm, type, field) do { \ + QMD_SAVELINK(_Oldnext, (elm)->field.stqe_next); \ if (STAILQ_FIRST((head)) == (elm)) { \ STAILQ_REMOVE_HEAD((head), field); \ } \ else { \ - QUEUE_TYPEOF(type) *curelm = STAILQ_FIRST(head); \ - while (STAILQ_NEXT(curelm, field) != (elm)) \ - curelm = STAILQ_NEXT(curelm, field); \ - STAILQ_REMOVE_AFTER(head, curelm, field); \ + QUEUE_TYPEOF(type) *_Curelm = STAILQ_FIRST(head); \ + while (STAILQ_NEXT(_Curelm, field) != (elm)) \ + _Curelm = STAILQ_NEXT(_Curelm, field); \ + STAILQ_REMOVE_AFTER(head, _Curelm, field); \ } \ - TRASHIT(*oldnext); \ + TRASHIT(*_Oldnext); \ } while (0) #define STAILQ_REMOVE_AFTER(head, elm, field) do { \ @@ -423,51 +531,81 @@ struct { \ (head)->stqh_last = &STAILQ_NEXT((elm), field); \ } while (0) -#define STAILQ_REMOVE_HEAD(head, field) do { \ +#define STAILQ_REMOVE_HEAD(head, field) do { \ if ((STAILQ_FIRST((head)) = \ STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ (head)->stqh_last = &STAILQ_FIRST((head)); \ } while (0) +#define STAILQ_SPLIT_AFTER(head, elm, rest, field) do { \ + STAILQ_ASSERT_NONEMPTY((head)); \ + QMD_STAILQ_CHECK_TAIL((head)); \ + if (STAILQ_NEXT((elm), field) == NULL) \ + /* 'elm' is the last element in 'head'. */ \ + STAILQ_INIT((rest)); \ + else { \ + STAILQ_FIRST((rest)) = STAILQ_NEXT((elm), field); \ + (rest)->stqh_last = (head)->stqh_last; \ + STAILQ_NEXT((elm), field) = NULL; \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + } \ +} while (0) + #define STAILQ_SWAP(head1, head2, type) do { \ - QUEUE_TYPEOF(type) *swap_first = STAILQ_FIRST(head1); \ - QUEUE_TYPEOF(type) **swap_last = (head1)->stqh_last; \ + QUEUE_TYPEOF(type) *_Swap_first = STAILQ_FIRST(head1); \ + QUEUE_TYPEOF(type) **_Swap_last = (head1)->stqh_last; \ STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ (head1)->stqh_last = (head2)->stqh_last; \ - STAILQ_FIRST(head2) = swap_first; \ - (head2)->stqh_last = swap_last; \ - if (STAILQ_EMPTY(head1)) \ + STAILQ_FIRST(head2) = _Swap_first; \ + (head2)->stqh_last = _Swap_last; \ + if (STAILQ_FIRST(head1) == NULL) \ (head1)->stqh_last = &STAILQ_FIRST(head1); \ - if (STAILQ_EMPTY(head2)) \ + if (STAILQ_FIRST(head2) == NULL) \ (head2)->stqh_last = &STAILQ_FIRST(head2); \ } while (0) -#define STAILQ_END(head) NULL +#define STAILQ_REVERSE(head, type, field) do { \ + if (STAILQ_EMPTY(head)) \ + break; \ + QUEUE_TYPEOF(type) *_Var, *_Varp, *_Varn; \ + for (_Var = STAILQ_FIRST(head), _Varp = NULL; \ + _Var != NULL;) { \ + _Varn = STAILQ_NEXT(_Var, field); \ + STAILQ_NEXT(_Var, field) = _Varp; \ + _Varp = _Var; \ + _Var = _Varn; \ + } \ + (head)->stqh_last = &STAILQ_NEXT(STAILQ_FIRST(head), field); \ + (head)->stqh_first = _Varp; \ +} while (0) + +#define STAILQ_END(head) NULL /* * List declarations. */ -#define LIST_HEAD(name, type) \ + +#define LIST_HEAD(name, type) \ struct name { \ struct type *lh_first; /* first element */ \ } -#define LIST_CLASS_HEAD(name, type) \ +#define LIST_CLASS_HEAD(name, type) \ struct name { \ class type *lh_first; /* first element */ \ } -#define LIST_HEAD_INITIALIZER(head) \ +#define LIST_HEAD_INITIALIZER(head) \ { NULL } -#define LIST_ENTRY(type) \ +#define LIST_ENTRY(type) \ struct { \ struct type *le_next; /* next element */ \ struct type **le_prev; /* address of previous next element */ \ } -#define LIST_CLASS_ENTRY(type) \ +#define LIST_CLASS_ENTRY(type) \ struct { \ class type *le_next; /* next element */ \ class type **le_prev; /* address of previous next element */ \ @@ -477,19 +615,18 @@ struct { \ * List functions. */ -#if (defined(_KERNEL) && defined(INVARIANTS)) /* * QMD_LIST_CHECK_HEAD(LIST_HEAD *head, LIST_ENTRY NAME) * * If the list is non-empty, validates that the first element of the list * points back at 'head.' */ -#define QMD_LIST_CHECK_HEAD(head, field) do { \ - if (LIST_FIRST((head)) != NULL && \ - LIST_FIRST((head))->field.le_prev != \ - &LIST_FIRST((head))) \ - panic("Bad list head %p first->prev != head", (head)); \ -} while (0) +#define QMD_LIST_CHECK_HEAD(head, field) \ + QMD_ASSERT(LIST_FIRST((head)) == NULL || \ + LIST_FIRST((head))->field.le_prev == \ + &LIST_FIRST((head)), \ + "Bad list head %p first->prev != head", \ + (head)) /* * QMD_LIST_CHECK_NEXT(TYPE *elm, LIST_ENTRY NAME) @@ -497,74 +634,78 @@ struct { \ * If an element follows 'elm' in the list, validates that the next element * points back at 'elm.' */ -#define QMD_LIST_CHECK_NEXT(elm, field) do { \ - if (LIST_NEXT((elm), field) != NULL && \ - LIST_NEXT((elm), field)->field.le_prev != \ - &((elm)->field.le_next)) \ - panic("Bad link elm %p next->prev != elm", (elm)); \ -} while (0) +#define QMD_LIST_CHECK_NEXT(elm, field) \ + QMD_ASSERT(LIST_NEXT((elm), field) == NULL || \ + LIST_NEXT((elm), field)->field.le_prev == \ + &((elm)->field.le_next), \ + "Bad link elm %p next->prev != elm", (elm)) /* * QMD_LIST_CHECK_PREV(TYPE *elm, LIST_ENTRY NAME) * * Validates that the previous element (or head of the list) points to 'elm.' */ -#define QMD_LIST_CHECK_PREV(elm, field) do { \ - if (*(elm)->field.le_prev != (elm)) \ - panic("Bad link elm %p prev->next != elm", (elm)); \ -} while (0) -#else -#define QMD_LIST_CHECK_HEAD(head, field) -#define QMD_LIST_CHECK_NEXT(elm, field) -#define QMD_LIST_CHECK_PREV(elm, field) -#endif /* (_KERNEL && INVARIANTS) */ +#define QMD_LIST_CHECK_PREV(elm, field) \ + QMD_ASSERT(*(elm)->field.le_prev == (elm), \ + "Bad link elm %p prev->next != elm", (elm)) + +#define LIST_ASSERT_EMPTY(head) \ + QMD_ASSERT(LIST_EMPTY((head)), \ + "list %p is not empty", (head)) + +#define LIST_ASSERT_NONEMPTY(head) \ + QMD_ASSERT(!LIST_EMPTY((head)), \ + "list %p is empty", (head)) #define LIST_CONCAT(head1, head2, type, field) do { \ - QUEUE_TYPEOF(type) *curelm = LIST_FIRST(head1); \ - if (curelm == NULL) { \ + QUEUE_TYPEOF(type) *_Curelm = LIST_FIRST(head1); \ + if (_Curelm == NULL) { \ if ((LIST_FIRST(head1) = LIST_FIRST(head2)) != NULL) { \ LIST_FIRST(head2)->field.le_prev = \ &LIST_FIRST((head1)); \ LIST_INIT(head2); \ } \ } else if (LIST_FIRST(head2) != NULL) { \ - while (LIST_NEXT(curelm, field) != NULL) \ - curelm = LIST_NEXT(curelm, field); \ - LIST_NEXT(curelm, field) = LIST_FIRST(head2); \ - LIST_FIRST(head2)->field.le_prev = &LIST_NEXT(curelm, field);\ + while (LIST_NEXT(_Curelm, field) != NULL) \ + _Curelm = LIST_NEXT(_Curelm, field); \ + LIST_NEXT(_Curelm, field) = LIST_FIRST(head2); \ + LIST_FIRST(head2)->field.le_prev = &LIST_NEXT(_Curelm, field);\ LIST_INIT(head2); \ } \ } while (0) -#define LIST_EMPTY(head) ((head)->lh_first == NULL) +#define LIST_EMPTY(head) ((head)->lh_first == NULL) + +#define LIST_EMPTY_ATOMIC(head) \ + (atomic_load_ptr(&(head)->lh_first) == NULL) -#define LIST_FIRST(head) ((head)->lh_first) +#define LIST_FIRST(head) ((head)->lh_first) -#define LIST_FOREACH(var, head, field) \ +#define LIST_FOREACH(var, head, field) \ for ((var) = LIST_FIRST((head)); \ (var); \ (var) = LIST_NEXT((var), field)) -#define LIST_FOREACH_FROM(var, head, field) \ +#define LIST_FOREACH_FROM(var, head, field) \ for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ (var); \ (var) = LIST_NEXT((var), field)) -#define LIST_FOREACH_SAFE(var, head, field, tvar) \ +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = LIST_FIRST((head)); \ (var) && ((tvar) = LIST_NEXT((var), field), 1); \ (var) = (tvar)) -#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ +#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ (var) && ((tvar) = LIST_NEXT((var), field), 1); \ (var) = (tvar)) -#define LIST_INIT(head) do { \ +#define LIST_INIT(head) do { \ LIST_FIRST((head)) = NULL; \ } while (0) -#define LIST_INSERT_AFTER(listelm, elm, field) do { \ +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ QMD_LIST_CHECK_NEXT(listelm, field); \ if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ LIST_NEXT((listelm), field)->field.le_prev = \ @@ -573,7 +714,7 @@ struct { \ (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ } while (0) -#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ QMD_LIST_CHECK_PREV(listelm, field); \ (elm)->field.le_prev = (listelm)->field.le_prev; \ LIST_NEXT((elm), field) = (listelm); \ @@ -581,7 +722,7 @@ struct { \ (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ } while (0) -#define LIST_INSERT_HEAD(head, elm, field) do { \ +#define LIST_INSERT_HEAD(head, elm, field) do { \ QMD_LIST_CHECK_HEAD((head), field); \ if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ @@ -589,9 +730,9 @@ struct { \ (elm)->field.le_prev = &LIST_FIRST((head)); \ } while (0) -#define LIST_NEXT(elm, field) ((elm)->field.le_next) +#define LIST_NEXT(elm, field) ((elm)->field.le_next) -#define LIST_PREV(elm, head, type, field) \ +#define LIST_PREV(elm, head, type, field) \ ((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \ __containerof((elm)->field.le_prev, \ QUEUE_TYPEOF(type), field.le_next)) @@ -599,22 +740,22 @@ struct { \ #define LIST_REMOVE_HEAD(head, field) \ LIST_REMOVE(LIST_FIRST(head), field) -#define LIST_REMOVE(elm, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.le_next); \ - QMD_SAVELINK(oldprev, (elm)->field.le_prev); \ +#define LIST_REMOVE(elm, field) do { \ + QMD_SAVELINK(_Oldnext, (elm)->field.le_next); \ + QMD_SAVELINK(_Oldprev, (elm)->field.le_prev); \ QMD_LIST_CHECK_NEXT(elm, field); \ QMD_LIST_CHECK_PREV(elm, field); \ if (LIST_NEXT((elm), field) != NULL) \ LIST_NEXT((elm), field)->field.le_prev = \ (elm)->field.le_prev; \ *(elm)->field.le_prev = LIST_NEXT((elm), field); \ - TRASHIT(*oldnext); \ - TRASHIT(*oldprev); \ + TRASHIT(*_Oldnext); \ + TRASHIT(*_Oldprev); \ } while (0) #define LIST_REPLACE(elm, elm2, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.le_next); \ - QMD_SAVELINK(oldprev, (elm)->field.le_prev); \ + QMD_SAVELINK(_Oldnext, (elm)->field.le_next); \ + QMD_SAVELINK(_Oldprev, (elm)->field.le_prev); \ QMD_LIST_CHECK_NEXT(elm, field); \ QMD_LIST_CHECK_PREV(elm, field); \ LIST_NEXT((elm2), field) = LIST_NEXT((elm), field); \ @@ -623,8 +764,21 @@ struct { \ &(elm2)->field.le_next; \ (elm2)->field.le_prev = (elm)->field.le_prev; \ *(elm2)->field.le_prev = (elm2); \ - TRASHIT(*oldnext); \ - TRASHIT(*oldprev); \ + TRASHIT(*_Oldnext); \ + TRASHIT(*_Oldprev); \ +} while (0) + +#define LIST_SPLIT_AFTER(head, elm, rest, field) do { \ + LIST_ASSERT_NONEMPTY((head)); \ + if (LIST_NEXT((elm), field) == NULL) \ + /* 'elm' is the last element in 'head'. */ \ + LIST_INIT((rest)); \ + else { \ + LIST_FIRST((rest)) = LIST_NEXT((elm), field); \ + LIST_NEXT((elm), field)->field.le_prev = \ + &LIST_FIRST((rest)); \ + LIST_NEXT((elm), field) = NULL; \ + } \ } while (0) #define LIST_SWAP(head1, head2, type, field) do { \ @@ -637,36 +791,37 @@ struct { \ swap_tmp->field.le_prev = &LIST_FIRST((head2)); \ } while (0) -#define LIST_END(head) NULL +#define LIST_END(head) NULL /* * Tail queue declarations. */ -#define TAILQ_HEAD(name, type) \ + +#define TAILQ_HEAD(name, type) \ struct name { \ struct type *tqh_first; /* first element */ \ struct type **tqh_last; /* addr of last next element */ \ TRACEBUF \ } -#define TAILQ_CLASS_HEAD(name, type) \ +#define TAILQ_CLASS_HEAD(name, type) \ struct name { \ class type *tqh_first; /* first element */ \ class type **tqh_last; /* addr of last next element */ \ TRACEBUF \ } -#define TAILQ_HEAD_INITIALIZER(head) \ +#define TAILQ_HEAD_INITIALIZER(head) \ { NULL, &(head).tqh_first, TRACEBUF_INITIALIZER } -#define TAILQ_ENTRY(type) \ +#define TAILQ_ENTRY(type) \ struct { \ struct type *tqe_next; /* next element */ \ struct type **tqe_prev; /* address of previous next element */ \ TRACEBUF \ } -#define TAILQ_CLASS_ENTRY(type) \ +#define TAILQ_CLASS_ENTRY(type) \ struct { \ class type *tqe_next; /* next element */ \ class type **tqe_prev; /* address of previous next element */ \ @@ -676,29 +831,29 @@ struct { \ /* * Tail queue functions. */ -#if (defined(_KERNEL) && defined(INVARIANTS)) + /* * QMD_TAILQ_CHECK_HEAD(TAILQ_HEAD *head, TAILQ_ENTRY NAME) * * If the tailq is non-empty, validates that the first element of the tailq * points back at 'head.' */ -#define QMD_TAILQ_CHECK_HEAD(head, field) do { \ - if (!TAILQ_EMPTY(head) && \ - TAILQ_FIRST((head))->field.tqe_prev != \ - &TAILQ_FIRST((head))) \ - panic("Bad tailq head %p first->prev != head", (head)); \ -} while (0) +#define QMD_TAILQ_CHECK_HEAD(head, field) \ + QMD_ASSERT(TAILQ_EMPTY(head) || \ + TAILQ_FIRST((head))->field.tqe_prev == \ + &TAILQ_FIRST((head)), \ + "Bad tailq head %p first->prev != head", \ + (head)) /* * QMD_TAILQ_CHECK_TAIL(TAILQ_HEAD *head, TAILQ_ENTRY NAME) * * Validates that the tail of the tailq is a pointer to pointer to NULL. */ -#define QMD_TAILQ_CHECK_TAIL(head, field) do { \ - if (*(head)->tqh_last != NULL) \ - panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ -} while (0) +#define QMD_TAILQ_CHECK_TAIL(head, field) \ + QMD_ASSERT(*(head)->tqh_last == NULL, \ + "Bad tailq NEXT(%p->tqh_last) != NULL", \ + (head)) /* * QMD_TAILQ_CHECK_NEXT(TYPE *elm, TAILQ_ENTRY NAME) @@ -706,30 +861,30 @@ struct { \ * If an element follows 'elm' in the tailq, validates that the next element * points back at 'elm.' */ -#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ - if (TAILQ_NEXT((elm), field) != NULL && \ - TAILQ_NEXT((elm), field)->field.tqe_prev != \ - &((elm)->field.tqe_next)) \ - panic("Bad link elm %p next->prev != elm", (elm)); \ -} while (0) +#define QMD_TAILQ_CHECK_NEXT(elm, field) \ + QMD_ASSERT(TAILQ_NEXT((elm), field) == NULL || \ + TAILQ_NEXT((elm), field)->field.tqe_prev == \ + &((elm)->field.tqe_next), \ + "Bad link elm %p next->prev != elm", (elm)) /* * QMD_TAILQ_CHECK_PREV(TYPE *elm, TAILQ_ENTRY NAME) * * Validates that the previous element (or head of the tailq) points to 'elm.' */ -#define QMD_TAILQ_CHECK_PREV(elm, field) do { \ - if (*(elm)->field.tqe_prev != (elm)) \ - panic("Bad link elm %p prev->next != elm", (elm)); \ -} while (0) -#else -#define QMD_TAILQ_CHECK_HEAD(head, field) -#define QMD_TAILQ_CHECK_TAIL(head, headname) -#define QMD_TAILQ_CHECK_NEXT(elm, field) -#define QMD_TAILQ_CHECK_PREV(elm, field) -#endif /* (_KERNEL && INVARIANTS) */ +#define QMD_TAILQ_CHECK_PREV(elm, field) \ + QMD_ASSERT(*(elm)->field.tqe_prev == (elm), \ + "Bad link elm %p prev->next != elm", (elm)) -#define TAILQ_CONCAT(head1, head2, field) do { \ +#define TAILQ_ASSERT_EMPTY(head) \ + QMD_ASSERT(TAILQ_EMPTY((head)), \ + "tailq %p is not empty", (head)) + +#define TAILQ_ASSERT_NONEMPTY(head) \ + QMD_ASSERT(!TAILQ_EMPTY((head)), \ + "tailq %p is empty", (head)) + +#define TAILQ_CONCAT(head1, head2, field) do { \ if (!TAILQ_EMPTY(head2)) { \ *(head1)->tqh_last = (head2)->tqh_first; \ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ @@ -740,57 +895,60 @@ struct { \ } \ } while (0) -#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) + +#define TAILQ_EMPTY_ATOMIC(head) \ + (atomic_load_ptr(&(head)->tqh_first) == NULL) -#define TAILQ_FIRST(head) ((head)->tqh_first) +#define TAILQ_FIRST(head) ((head)->tqh_first) -#define TAILQ_FOREACH(var, head, field) \ +#define TAILQ_FOREACH(var, head, field) \ for ((var) = TAILQ_FIRST((head)); \ (var); \ (var) = TAILQ_NEXT((var), field)) -#define TAILQ_FOREACH_FROM(var, head, field) \ +#define TAILQ_FOREACH_FROM(var, head, field) \ for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ (var); \ (var) = TAILQ_NEXT((var), field)) -#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = TAILQ_FIRST((head)); \ (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ (var) = (tvar)) -#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ +#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ (var) = (tvar)) -#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ for ((var) = TAILQ_LAST((head), headname); \ (var); \ (var) = TAILQ_PREV((var), headname, field)) -#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \ +#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \ for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ (var); \ (var) = TAILQ_PREV((var), headname, field)) -#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ for ((var) = TAILQ_LAST((head), headname); \ (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ (var) = (tvar)) -#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar)\ +#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar)\ for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ (var) = (tvar)) -#define TAILQ_INIT(head) do { \ +#define TAILQ_INIT(head) do { \ TAILQ_FIRST((head)) = NULL; \ (head)->tqh_last = &TAILQ_FIRST((head)); \ QMD_TRACE_HEAD(head); \ } while (0) -#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ QMD_TAILQ_CHECK_NEXT(listelm, field); \ if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ TAILQ_NEXT((elm), field)->field.tqe_prev = \ @@ -805,7 +963,7 @@ struct { \ QMD_TRACE_ELEM(&(listelm)->field); \ } while (0) -#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ QMD_TAILQ_CHECK_PREV(listelm, field); \ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ TAILQ_NEXT((elm), field) = (listelm); \ @@ -815,7 +973,7 @@ struct { \ QMD_TRACE_ELEM(&(listelm)->field); \ } while (0) -#define TAILQ_INSERT_HEAD(head, elm, field) do { \ +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ QMD_TAILQ_CHECK_HEAD(head, field); \ if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ TAILQ_FIRST((head))->field.tqe_prev = \ @@ -828,7 +986,7 @@ struct { \ QMD_TRACE_ELEM(&(elm)->field); \ } while (0) -#define TAILQ_INSERT_TAIL(head, elm, field) do { \ +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ QMD_TAILQ_CHECK_TAIL(head, field); \ TAILQ_NEXT((elm), field) = NULL; \ (elm)->field.tqe_prev = (head)->tqh_last; \ @@ -838,7 +996,7 @@ struct { \ QMD_TRACE_ELEM(&(elm)->field); \ } while (0) -#define TAILQ_LAST(head, headname) \ +#define TAILQ_LAST(head, headname) \ (*(((struct headname *)((head)->tqh_last))->tqh_last)) /* @@ -848,24 +1006,24 @@ struct { \ * the previous element. FAST is very useful for instances when * you may want to prefetch the last data element. */ -#define TAILQ_LAST_FAST(head, type, field) \ +#define TAILQ_LAST_FAST(head, type, field) \ (TAILQ_EMPTY(head) ? NULL : __containerof((head)->tqh_last, QUEUE_TYPEOF(type), field.tqe_next)) -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) -#define TAILQ_PREV(elm, headname, field) \ +#define TAILQ_PREV(elm, headname, field) \ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) -#define TAILQ_PREV_FAST(elm, head, type, field) \ +#define TAILQ_PREV_FAST(elm, head, type, field) \ ((elm)->field.tqe_prev == &(head)->tqh_first ? NULL : \ __containerof((elm)->field.tqe_prev, QUEUE_TYPEOF(type), field.tqe_next)) #define TAILQ_REMOVE_HEAD(head, field) \ TAILQ_REMOVE(head, TAILQ_FIRST(head), field) -#define TAILQ_REMOVE(head, elm, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \ - QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \ +#define TAILQ_REMOVE(head, elm, field) do { \ + QMD_SAVELINK(_Oldnext, (elm)->field.tqe_next); \ + QMD_SAVELINK(_Oldprev, (elm)->field.tqe_prev); \ QMD_TAILQ_CHECK_NEXT(elm, field); \ QMD_TAILQ_CHECK_PREV(elm, field); \ if ((TAILQ_NEXT((elm), field)) != NULL) \ @@ -876,14 +1034,14 @@ struct { \ QMD_TRACE_HEAD(head); \ } \ *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ - TRASHIT(*oldnext); \ - TRASHIT(*oldprev); \ + TRASHIT(*_Oldnext); \ + TRASHIT(*_Oldprev); \ QMD_TRACE_ELEM(&(elm)->field); \ } while (0) #define TAILQ_REPLACE(head, elm, elm2, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \ - QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \ + QMD_SAVELINK(_Oldnext, (elm)->field.tqe_next); \ + QMD_SAVELINK(_Oldprev, (elm)->field.tqe_prev); \ QMD_TAILQ_CHECK_NEXT(elm, field); \ QMD_TAILQ_CHECK_PREV(elm, field); \ TAILQ_NEXT((elm2), field) = TAILQ_NEXT((elm), field); \ @@ -894,11 +1052,28 @@ struct { \ (head)->tqh_last = &(elm2)->field.tqe_next; \ (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ *(elm2)->field.tqe_prev = (elm2); \ - TRASHIT(*oldnext); \ - TRASHIT(*oldprev); \ + TRASHIT(*_Oldnext); \ + TRASHIT(*_Oldprev); \ QMD_TRACE_ELEM(&(elm)->field); \ } while (0) +#define TAILQ_SPLIT_AFTER(head, elm, rest, field) do { \ + TAILQ_ASSERT_NONEMPTY((head)); \ + QMD_TAILQ_CHECK_TAIL((head), field); \ + if (TAILQ_NEXT((elm), field) == NULL) \ + /* 'elm' is the last element in 'head'. */ \ + TAILQ_INIT((rest)); \ + else { \ + TAILQ_FIRST((rest)) = TAILQ_NEXT((elm), field); \ + (rest)->tqh_last = (head)->tqh_last; \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + &TAILQ_FIRST((rest)); \ + \ + TAILQ_NEXT((elm), field) = NULL; \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + } \ +} while (0) + #define TAILQ_SWAP(head1, head2, type, field) do { \ QUEUE_TYPEOF(type) *swap_first = (head1)->tqh_first; \ QUEUE_TYPEOF(type) **swap_last = (head1)->tqh_last; \ @@ -916,6 +1091,6 @@ struct { \ (head2)->tqh_last = &(head2)->tqh_first; \ } while (0) -#define TAILQ_END(head) NULL +#define TAILQ_END(head) NULL #endif /* !_SYS_QUEUE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/racct.h b/lib/libc/include/generic-freebsd/sys/racct.h index 66f97e475636..31141adb8c35 100644 --- a/lib/libc/include/generic-freebsd/sys/racct.h +++ b/lib/libc/include/generic-freebsd/sys/racct.h @@ -35,7 +35,6 @@ #ifndef _RACCT_H_ #define _RACCT_H_ -#include #include #include #include @@ -142,13 +141,17 @@ extern bool racct_enable; /* * The 'racct' structure defines resource consumption for a particular - * subject, such as process or jail. + * subject, such as process or jail. It also contains the total + * cpu time and real time of the subject, recorded at the most recent + * time that RACCT_PCPU was updated. * * This structure must be filled with zeroes initially. */ struct racct { int64_t r_resources[RACCT_MAX + 1]; LIST_HEAD(, rctl_rule_link) r_rule_links; + uint64_t r_runtime; + struct timeval r_time; }; SYSCTL_DECL(_kern_racct); diff --git a/lib/libc/include/generic-freebsd/sys/random.h b/lib/libc/include/generic-freebsd/sys/random.h index c7e6e4c4275e..7b9af981dfd1 100644 --- a/lib/libc/include/generic-freebsd/sys/random.h +++ b/lib/libc/include/generic-freebsd/sys/random.h @@ -85,24 +85,26 @@ enum random_entropy_source { RANDOM_FS_ATIME, RANDOM_UMA, /* Special!! UMA/SLAB Allocator */ RANDOM_CALLOUT, - RANDOM_ENVIRONMENTAL_END = RANDOM_CALLOUT, + RANDOM_RANDOMDEV, + RANDOM_ENVIRONMENTAL_END = RANDOM_RANDOMDEV, /* Fast hardware random-number sources from here on. */ RANDOM_PURE_START, - RANDOM_PURE_OCTEON = RANDOM_PURE_START, - RANDOM_PURE_SAFE, - RANDOM_PURE_GLXSB, - RANDOM_PURE_HIFN, + RANDOM_PURE_TPM = RANDOM_PURE_START, RANDOM_PURE_RDRAND, + RANDOM_PURE_RDSEED, RANDOM_PURE_NEHEMIAH, RANDOM_PURE_RNDTEST, RANDOM_PURE_VIRTIO, RANDOM_PURE_BROADCOM, RANDOM_PURE_CCP, RANDOM_PURE_DARN, - RANDOM_PURE_TPM, RANDOM_PURE_VMGENID, RANDOM_PURE_QUALCOMM, RANDOM_PURE_ARMV8, + RANDOM_PURE_ARM_TRNG, + RANDOM_PURE_SAFE, + RANDOM_PURE_GLXSB, + RANDOM_PURE_HIFN, ENTROPYSOURCE }; _Static_assert(ENTROPYSOURCE <= 32, @@ -140,9 +142,6 @@ random_harvest_direct(const void *entropy, u_int size, enum random_entropy_sourc random_harvest_direct_(entropy, size, origin); } -void random_harvest_register_source(enum random_entropy_source); -void random_harvest_deregister_source(enum random_entropy_source); - #if defined(RANDOM_ENABLE_UMA) #define random_harvest_fast_uma(a, b, c) random_harvest_fast(a, b, c) #else /* !defined(RANDOM_ENABLE_UMA) */ @@ -155,6 +154,12 @@ void random_harvest_deregister_source(enum random_entropy_source); #define random_harvest_queue_ether(a, b) do {} while (0) #endif /* defined(RANDOM_ENABLE_ETHER) */ +#else /* !_KERNEL */ + +#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 +#include +#endif + #endif /* _KERNEL */ #define GRND_NONBLOCK 0x1 diff --git a/lib/libc/include/generic-freebsd/sys/rangelock.h b/lib/libc/include/generic-freebsd/sys/rangelock.h index b379e4d7334e..b392d6bc5038 100644 --- a/lib/libc/include/generic-freebsd/sys/rangelock.h +++ b/lib/libc/include/generic-freebsd/sys/rangelock.h @@ -29,12 +29,14 @@ #ifndef _SYS_RANGELOCK_H #define _SYS_RANGELOCK_H -#include +#include +#ifndef _KERNEL +#include +#endif #define RL_LOCK_READ 0x0001 #define RL_LOCK_WRITE 0x0002 #define RL_LOCK_TYPE_MASK 0x0003 -#define RL_LOCK_GRANTED 0x0004 struct rl_q_entry; @@ -44,42 +46,26 @@ struct rl_q_entry; * all existing lock owners are compatible with the request. Two lock * owners are compatible if their ranges do not overlap, or both * owners are for read. - * - * Access to the structure itself is synchronized with the externally - * supplied mutex. - * - * rl_waiters is the queue containing in order (a) granted write lock - * requests, (b) granted read lock requests, and (c) in order of arrival, - * lock requests which cannot be granted yet. - * - * rl_currdep is the first lock request that cannot be granted now due - * to the preceding requests conflicting with it (i.e., it points to - * position (c) in the list above). */ struct rangelock { - TAILQ_HEAD(, rl_q_entry) rl_waiters; - struct rl_q_entry *rl_currdep; + uintptr_t head; + bool sleepers; }; #ifdef _KERNEL -struct mtx; - void rangelock_init(struct rangelock *lock); void rangelock_destroy(struct rangelock *lock); -void rangelock_unlock(struct rangelock *lock, void *cookie, - struct mtx *ilk); -void *rangelock_unlock_range(struct rangelock *lock, void *cookie, - off_t start, off_t end, struct mtx *ilk); -void *rangelock_rlock(struct rangelock *lock, off_t start, off_t end, - struct mtx *ilk); -void *rangelock_tryrlock(struct rangelock *lock, off_t start, off_t end, - struct mtx *ilk); -void *rangelock_wlock(struct rangelock *lock, off_t start, off_t end, - struct mtx *ilk); -void *rangelock_trywlock(struct rangelock *lock, off_t start, off_t end, - struct mtx *ilk); -void rlqentry_free(struct rl_q_entry *rlqe); +void rangelock_unlock(struct rangelock *lock, void *cookie); +void *rangelock_rlock(struct rangelock *lock, vm_ooffset_t start, + vm_ooffset_t end); +void *rangelock_tryrlock(struct rangelock *lock, vm_ooffset_t start, + vm_ooffset_t end); +void *rangelock_wlock(struct rangelock *lock, vm_ooffset_t start, + vm_ooffset_t end); +void *rangelock_trywlock(struct rangelock *lock, vm_ooffset_t start, + vm_ooffset_t end); +void rangelock_may_recurse(struct rangelock *lock); #if defined(INVARIANTS) || defined(INVARIANT_SUPPORT) void _rangelock_cookie_assert(void *cookie, int what, const char *file, int line); diff --git a/lib/libc/include/generic-freebsd/sys/rangeset.h b/lib/libc/include/generic-freebsd/sys/rangeset.h index 8e716f7b3073..007c9f811034 100644 --- a/lib/libc/include/generic-freebsd/sys/rangeset.h +++ b/lib/libc/include/generic-freebsd/sys/rangeset.h @@ -69,10 +69,19 @@ int rangeset_remove_pred(struct rangeset *rs, uint64_t start, uint64_t end, rs_pred_t pred); /* - * Really returns the pointer to the data with struct rs_el embedded - * at the beginning. + * Finds the range that contains place, if any. */ -void *rangeset_lookup(struct rangeset *rs, uint64_t place); +void *rangeset_containing(struct rangeset *rs, uint64_t place); + +/* + * Report whether no range begins between start and end. + */ +bool rangeset_empty(struct rangeset *rs, uint64_t start, uint64_t end); + +/* + * Finds the range that begins at place, if any. + */ +void *rangeset_beginning(struct rangeset *rs, uint64_t place); /* * Copies src_rs entries into dst_rs. dst_rs must be empty. diff --git a/lib/libc/include/generic-freebsd/sys/reboot.h b/lib/libc/include/generic-freebsd/sys/reboot.h index 33594130322b..76a7eca075ba 100644 --- a/lib/libc/include/generic-freebsd/sys/reboot.h +++ b/lib/libc/include/generic-freebsd/sys/reboot.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)reboot.h 8.3 (Berkeley) 12/13/94 */ #ifndef _SYS_REBOOT_H_ @@ -62,6 +60,7 @@ #define RB_PAUSE 0x100000 /* pause after each output line during probe */ #define RB_REROOT 0x200000 /* unmount the rootfs and mount it again */ #define RB_POWERCYCLE 0x400000 /* Power cycle if possible */ +#define RB_MUTEMSGS 0x800000 /* start up with console muted after banner */ #define RB_PROBE 0x10000000 /* Probe multiple consoles */ #define RB_MULTIPLE 0x20000000 /* use multiple consoles */ diff --git a/lib/libc/include/generic-freebsd/sys/refcount.h b/lib/libc/include/generic-freebsd/sys/refcount.h index ef49d96d3938..41f919e08edf 100644 --- a/lib/libc/include/generic-freebsd/sys/refcount.h +++ b/lib/libc/include/generic-freebsd/sys/refcount.h @@ -28,15 +28,14 @@ #ifndef __SYS_REFCOUNT_H__ #define __SYS_REFCOUNT_H__ -#include - -#if defined(_KERNEL) || defined(_STANDALONE) -#include -#else +#include +#include +#if !defined(_KERNEL) && !defined(_STANDALONE) #include -#define KASSERT(exp, msg) /* */ #endif +#include + #define REFCOUNT_SATURATED(val) (((val) & (1U << 31)) != 0) #define REFCOUNT_SATURATION_VALUE (3U << 30) @@ -65,7 +64,7 @@ refcount_init(volatile u_int *count, u_int value) } static __inline u_int -refcount_load(volatile u_int *count) +refcount_load(volatile const u_int *count) { return (atomic_load_int(count)); } diff --git a/lib/libc/include/generic-freebsd/sys/resource.h b/lib/libc/include/generic-freebsd/sys/resource.h index 76c4b59e4ffc..05b28b5037f9 100644 --- a/lib/libc/include/generic-freebsd/sys/resource.h +++ b/lib/libc/include/generic-freebsd/sys/resource.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)resource.h 8.4 (Berkeley) 1/9/95 */ #ifndef _SYS_RESOURCE_H_ diff --git a/lib/libc/include/generic-freebsd/sys/resourcevar.h b/lib/libc/include/generic-freebsd/sys/resourcevar.h index 32c7fbb8cc29..90cab55431cf 100644 --- a/lib/libc/include/generic-freebsd/sys/resourcevar.h +++ b/lib/libc/include/generic-freebsd/sys/resourcevar.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)resourcevar.h 8.4 (Berkeley) 1/9/95 */ #ifndef _SYS_RESOURCEVAR_H_ @@ -124,6 +122,8 @@ struct uidinfo { long ui_kqcnt; /* (b) number of kqueues */ long ui_umtxcnt; /* (b) number of shared umtxs */ long ui_pipecnt; /* (b) consumption of pipe buffers */ + long ui_inotifycnt; /* (b) number of inotify descriptors */ + long ui_inotifywatchcnt; /* (b) number of inotify watches */ uid_t ui_uid; /* (a) uid */ u_int ui_ref; /* (b) reference count */ #ifdef RACCT @@ -146,6 +146,8 @@ int chgsbsize(struct uidinfo *uip, u_int *hiwat, u_int to, int chgptscnt(struct uidinfo *uip, int diff, rlim_t maxval); int chgumtxcnt(struct uidinfo *uip, int diff, rlim_t maxval); int chgpipecnt(struct uidinfo *uip, int diff, rlim_t max); +int chginotifycnt(struct uidinfo *uip, int diff, rlim_t maxval); +int chginotifywatchcnt(struct uidinfo *uip, int diff, rlim_t maxval); int kern_proc_setrlimit(struct thread *td, struct proc *p, u_int which, struct rlimit *limp); struct plimit diff --git a/lib/libc/include/generic-freebsd/sys/rman.h b/lib/libc/include/generic-freebsd/sys/rman.h index 8437c898be89..78e63888788a 100644 --- a/lib/libc/include/generic-freebsd/sys/rman.h +++ b/lib/libc/include/generic-freebsd/sys/rman.h @@ -124,17 +124,18 @@ TAILQ_HEAD(rman_head, rman); int rman_activate_resource(struct resource *r); int rman_adjust_resource(struct resource *r, rman_res_t start, rman_res_t end); int rman_first_free_region(struct rman *rm, rman_res_t *start, rman_res_t *end); -bus_space_handle_t rman_get_bushandle(struct resource *); -bus_space_tag_t rman_get_bustag(struct resource *); -rman_res_t rman_get_end(struct resource *); -device_t rman_get_device(struct resource *); -u_int rman_get_flags(struct resource *); -void *rman_get_irq_cookie(struct resource *); -void rman_get_mapping(struct resource *, struct resource_map *); -int rman_get_rid(struct resource *); -rman_res_t rman_get_size(struct resource *); -rman_res_t rman_get_start(struct resource *); -void *rman_get_virtual(struct resource *); +bus_space_handle_t rman_get_bushandle(const struct resource *); +bus_space_tag_t rman_get_bustag(const struct resource *); +rman_res_t rman_get_end(const struct resource *); +device_t rman_get_device(const struct resource *); +u_int rman_get_flags(const struct resource *); +void *rman_get_irq_cookie(const struct resource *); +void rman_get_mapping(const struct resource *, struct resource_map *); +int rman_get_rid(const struct resource *); +rman_res_t rman_get_size(const struct resource *); +rman_res_t rman_get_start(const struct resource *); +int rman_get_type(const struct resource *); +void *rman_get_virtual(const struct resource *); int rman_deactivate_resource(struct resource *r); int rman_fini(struct rman *rm); int rman_init(struct rman *rm); @@ -142,22 +143,18 @@ int rman_init_from_resource(struct rman *rm, struct resource *r); int rman_last_free_region(struct rman *rm, rman_res_t *start, rman_res_t *end); uint32_t rman_make_alignment_flags(uint32_t size); int rman_manage_region(struct rman *rm, rman_res_t start, rman_res_t end); -int rman_is_region_manager(struct resource *r, struct rman *rm); +int rman_is_region_manager(const struct resource *r, const struct rman *rm); int rman_release_resource(struct resource *r); struct resource *rman_reserve_resource(struct rman *rm, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags, device_t dev); -struct resource *rman_reserve_resource_bound(struct rman *rm, rman_res_t start, - rman_res_t end, rman_res_t count, rman_res_t bound, - u_int flags, device_t dev); void rman_set_bushandle(struct resource *_r, bus_space_handle_t _h); void rman_set_bustag(struct resource *_r, bus_space_tag_t _t); void rman_set_device(struct resource *_r, device_t _dev); -void rman_set_end(struct resource *_r, rman_res_t _end); void rman_set_irq_cookie(struct resource *_r, void *_c); void rman_set_mapping(struct resource *, struct resource_map *); void rman_set_rid(struct resource *_r, int _rid); -void rman_set_start(struct resource *_r, rman_res_t _start); +void rman_set_type(struct resource *_r, int _type); void rman_set_virtual(struct resource *_r, void *_v); extern struct rman_head rman_head; diff --git a/lib/libc/include/generic-freebsd/sys/rmlock.h b/lib/libc/include/generic-freebsd/sys/rmlock.h index 075cf60223ae..8d7978866750 100644 --- a/lib/libc/include/generic-freebsd/sys/rmlock.h +++ b/lib/libc/include/generic-freebsd/sys/rmlock.h @@ -52,7 +52,7 @@ void rm_init(struct rmlock *rm, const char *name); void rm_init_flags(struct rmlock *rm, const char *name, int opts); void rm_destroy(struct rmlock *rm); int rm_wowned(const struct rmlock *rm); -void rm_sysinit(void *arg); +void rm_sysinit(const void *arg); void _rm_wlock_debug(struct rmlock *rm, const char *file, int line); void _rm_wunlock_debug(struct rmlock *rm, const char *file, int line); diff --git a/lib/libc/include/generic-freebsd/sys/runq.h b/lib/libc/include/generic-freebsd/sys/runq.h index 7776786913bc..588178c541c6 100644 --- a/lib/libc/include/generic-freebsd/sys/runq.h +++ b/lib/libc/include/generic-freebsd/sys/runq.h @@ -3,6 +3,11 @@ * * Copyright (c) 2001 Jake Burkholder * All rights reserved. + * Copyright (c) 2024 The FreeBSD Foundation + * + * Portions of this software were developed by Olivier Certner + * at Kumacom SARL 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 @@ -29,7 +34,14 @@ #ifndef _RUNQ_H_ #define _RUNQ_H_ -#include +#ifndef _KERNEL +#error "no user-serviceable parts inside" +#endif + +#include /* For bool. */ +#include +#include +#include struct thread; @@ -37,20 +49,46 @@ struct thread; * Run queue parameters. */ -#define RQ_NQS (64) /* Number of run queues. */ -#define RQ_PPQ (4) /* Priorities per queue. */ +#define RQ_MAX_PRIO (255) /* Maximum priority (minimum is 0). */ +#define RQ_PPQ (1) /* Priorities per queue. */ + +/* + * Deduced from the above parameters and machine ones. + */ +#define RQ_NQS (howmany(RQ_MAX_PRIO + 1, RQ_PPQ)) /* Number of run queues. */ +#define RQ_PRI_TO_QUEUE_IDX(pri) ((pri) / RQ_PPQ) /* Priority to queue index. */ + +typedef unsigned long rqsw_t; /* runq's status words type. */ +#define RQSW_BPW (sizeof(rqsw_t) * NBBY) /* Bits per runq word. */ +#define RQSW_PRI "%#lx" /* printf() directive. */ + +/* Number of status words to cover RQ_NQS queues. */ +#define RQSW_NB (howmany(RQ_NQS, RQSW_BPW)) +#define RQSW_IDX(idx) ((idx) / RQSW_BPW) +#define RQSW_BIT_IDX(idx) ((idx) % RQSW_BPW) +#define RQSW_BIT(idx) (1ul << RQSW_BIT_IDX(idx)) +#define RQSW_BSF(word) __extension__ ({ \ + int _res = ffsl((long)(word)); /* Assumes two-complement. */ \ + MPASS(_res > 0); \ + _res - 1; \ +}) +#define RQSW_TO_QUEUE_IDX(word_idx, bit_idx) \ + (((word_idx) * RQSW_BPW) + (bit_idx)) +#define RQSW_FIRST_QUEUE_IDX(word_idx, word) \ + RQSW_TO_QUEUE_IDX(word_idx, RQSW_BSF(word)) + /* - * Head of run queues. + * The queue for a given index as a list of threads. */ -TAILQ_HEAD(rqhead, thread); +TAILQ_HEAD(rq_queue, thread); /* * Bit array which maintains the status of a run queue. When a queue is * non-empty the bit corresponding to the queue number will be set. */ -struct rqbits { - rqb_word_t rqb_bits[RQB_LEN]; +struct rq_status { + rqsw_t rq_sw[RQSW_NB]; }; /* @@ -58,18 +96,29 @@ struct rqbits { * are placed, and a structure to maintain the status of each queue. */ struct runq { - struct rqbits rq_status; - struct rqhead rq_queues[RQ_NQS]; + struct rq_status rq_status; + struct rq_queue rq_queues[RQ_NQS]; }; -void runq_add(struct runq *, struct thread *, int); -void runq_add_pri(struct runq *, struct thread *, u_char, int); -int runq_check(struct runq *); -struct thread *runq_choose(struct runq *); -struct thread *runq_choose_from(struct runq *, u_char); -struct thread *runq_choose_fuzz(struct runq *, int); void runq_init(struct runq *); -void runq_remove(struct runq *, struct thread *); -void runq_remove_idx(struct runq *, struct thread *, u_char *); +bool runq_is_queue_empty(struct runq *, int _idx); +void runq_add(struct runq *, struct thread *, int _flags); +void runq_add_idx(struct runq *, struct thread *, int _idx, int _flags); +bool runq_remove(struct runq *, struct thread *); + +/* + * Implementation helpers for common and scheduler-specific runq_choose*() + * functions. + */ +typedef bool runq_pred_t(int _idx, struct rq_queue *, void *_data); +int runq_findq(struct runq *const rq, const int lvl_min, + const int lvl_max, + runq_pred_t *const pred, void *const pred_data); +struct thread *runq_first_thread_range(struct runq *const rq, + const int lvl_min, const int lvl_max); + +bool runq_not_empty(struct runq *); +struct thread *runq_choose(struct runq *); +struct thread *runq_choose_fuzz(struct runq *, int _fuzz); #endif \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/rwlock.h b/lib/libc/include/generic-freebsd/sys/rwlock.h index b0f21fb8d81b..3042661b460a 100644 --- a/lib/libc/include/generic-freebsd/sys/rwlock.h +++ b/lib/libc/include/generic-freebsd/sys/rwlock.h @@ -128,7 +128,7 @@ */ void _rw_init_flags(volatile uintptr_t *c, const char *name, int opts); void _rw_destroy(volatile uintptr_t *c); -void rw_sysinit(void *arg); +void rw_sysinit(const void *arg); int _rw_wowned(const volatile uintptr_t *c); void _rw_wlock_cookie(volatile uintptr_t *c, const char *file, int line); int __rw_try_wlock_int(struct rwlock *rw LOCK_FILE_LINE_ARG_DEF); diff --git a/lib/libc/include/generic-freebsd/sys/sched.h b/lib/libc/include/generic-freebsd/sys/sched.h index a3165c3651fd..25220eedb0ab 100644 --- a/lib/libc/include/generic-freebsd/sys/sched.h +++ b/lib/libc/include/generic-freebsd/sys/sched.h @@ -63,6 +63,15 @@ #define _SCHED_H_ #ifdef _KERNEL + +#include +#ifdef SCHED_STATS +#include +#endif + +struct proc; +struct thread; + /* * General scheduling info. * @@ -74,7 +83,7 @@ */ int sched_load(void); int sched_rr_interval(void); -int sched_runnable(void); +bool sched_runnable(void); /* * Proc related scheduling hooks. @@ -214,7 +223,7 @@ SYSINIT(name, SI_SUB_LAST, SI_ORDER_MIDDLE, name ## _add_proc, NULL); SCHED_STAT_DEFINE_VAR(name, &DPCPU_NAME(name), descr) /* * Sched stats are always incremented in critical sections so no atomic - * is necesssary to increment them. + * is necessary to increment them. */ #define SCHED_STAT_INC(var) DPCPU_GET(var)++; #else diff --git a/lib/libc/include/generic-freebsd/sys/sdt.h b/lib/libc/include/generic-freebsd/sys/sdt.h index f951b33dd016..d33795f4e586 100644 --- a/lib/libc/include/generic-freebsd/sys/sdt.h +++ b/lib/libc/include/generic-freebsd/sys/sdt.h @@ -77,8 +77,8 @@ #else /* _KERNEL */ -#include #include +#include extern volatile bool sdt_probes_enabled; @@ -102,8 +102,6 @@ extern volatile bool sdt_probes_enabled; #define SDT_PROBE_DEFINE5(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4) #define SDT_PROBE_DEFINE6(prov, mod, func, name, arg0, arg1, arg2, \ arg3, arg4, arg5) -#define SDT_PROBE_DEFINE7(prov, mod, func, name, arg0, arg1, arg2, \ - arg3, arg4, arg5, arg6) #define SDT_PROBE0(prov, mod, func, name) #define SDT_PROBE1(prov, mod, func, name, arg0) @@ -112,8 +110,9 @@ extern volatile bool sdt_probes_enabled; #define SDT_PROBE4(prov, mod, func, name, arg0, arg1, arg2, arg3) #define SDT_PROBE5(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4) #define SDT_PROBE6(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4, arg5) -#define SDT_PROBE7(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4, arg5, \ - arg6) + +#define MIB_SDT_PROBE1(...) +#define MIB_SDT_PROBE2(...) #define SDT_PROBE_DEFINE0_XLATE(prov, mod, func, name) #define SDT_PROBE_DEFINE1_XLATE(prov, mod, func, name, arg0, xarg0) @@ -127,9 +126,6 @@ extern volatile bool sdt_probes_enabled; arg1, xarg1, arg2, xarg2, arg3, xarg3, arg4, xarg4) #define SDT_PROBE_DEFINE6_XLATE(prov, mod, func, name, arg0, xarg0, \ arg1, xarg1, arg2, xarg2, arg3, xarg3, arg4, xarg4, arg5, xarg5) -#define SDT_PROBE_DEFINE7_XLATE(prov, mod, func, name, arg0, xarg0, \ - arg1, xarg1, arg2, xarg2, arg3, xarg3, arg4, xarg4, arg5, xarg5, arg6, \ - xarg6) #define DTRACE_PROBE(name) #define DTRACE_PROBE1(name, type0, arg0) @@ -141,6 +137,18 @@ extern volatile bool sdt_probes_enabled; #else +void sdt_probe(uint32_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, + uintptr_t); +void sdt_probe6(uint32_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, + uintptr_t, uintptr_t); + +#define _SDT_TRACEPOINT_SET sdt_tracepoint_set +#define _SDT_TRACEPOINT_SECTION "set_sdt_tracepoint_set" + +bool sdt_tracepoint_valid(uintptr_t patchpoint, uintptr_t target); +void sdt_tracepoint_patch(uintptr_t patchpoint, uintptr_t target); +void sdt_tracepoint_restore(uintptr_t patchpoint); + #define __sdt_used SET_DECLARE(sdt_providers_set, struct sdt_provider); @@ -153,39 +161,81 @@ SET_DECLARE(sdt_argtypes_set, struct sdt_argtype); sdt_provider_##prov #define SDT_PROVIDER_DEFINE(_prov) \ - struct sdt_provider _SDT_PROVIDER_NAME(_prov)[1] = { \ - [0] = { .name = #_prov }, \ + struct sdt_provider _SDT_PROVIDER_NAME(_prov) = { \ + .name = #_prov, \ }; \ DATA_SET(sdt_providers_set, _SDT_PROVIDER_NAME(_prov)) #define SDT_PROVIDER_DECLARE(prov) \ - extern struct sdt_provider _SDT_PROVIDER_NAME(prov)[1] + extern struct sdt_provider _SDT_PROVIDER_NAME(prov) #define SDT_PROBE_DEFINE(_prov, _mod, _func, _name) \ - struct sdt_probe _SDT_PROBE_NAME(_prov, _mod, _func, _name)[1] = { \ - [0] = { \ - .version = sizeof(struct sdt_probe), \ - .prov = _SDT_PROVIDER_NAME(_prov), \ - .mod = #_mod, \ - .func = #_func, \ - .name = #_name, \ - }, \ + struct sdt_probe _SDT_PROBE_NAME(_prov, _mod, _func, _name) = { \ + .version = sizeof(struct sdt_probe), \ + .prov = &_SDT_PROVIDER_NAME(_prov), \ + .mod = #_mod, \ + .func = #_func, \ + .name = #_name, \ }; \ DATA_SET(sdt_probes_set, _SDT_PROBE_NAME(_prov, _mod, _func, _name)) #define SDT_PROBE_DECLARE(prov, mod, func, name) \ - extern struct sdt_probe _SDT_PROBE_NAME(prov, mod, func, name)[1] + extern struct sdt_probe _SDT_PROBE_NAME(prov, mod, func, name) #define SDT_PROBES_ENABLED() __predict_false(sdt_probes_enabled) -#define SDT_PROBE(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4) do { \ - if (SDT_PROBES_ENABLED()) { \ - if (__predict_false(_SDT_PROBE_NAME(prov, mod, func, name)->id)) \ - (*sdt_probe_func)(_SDT_PROBE_NAME(prov, mod, func, name)->id, \ - (uintptr_t) arg0, (uintptr_t) arg1, (uintptr_t) arg2, \ - (uintptr_t) arg3, (uintptr_t) arg4); \ - } \ +#ifdef _ILP32 +#define _SDT_ASM_WORD ".long" +#else +#define _SDT_ASM_WORD ".quad" +#endif + +#ifndef _SDT_ASM_PROBE_CONSTRAINT +#define _SDT_ASM_PROBE_CONSTRAINT "i" +#endif +#ifndef _SDT_ASM_PROBE_OPERAND +#define _SDT_ASM_PROBE_OPERAND "c" +#endif + +/* + * The asm below generates records corresponding to the structure's layout, so + * the two must be kept in sync. + */ +struct sdt_tracepoint { + struct sdt_probe *probe; + uintptr_t patchpoint; + uintptr_t target; + STAILQ_ENTRY(sdt_tracepoint) tracepoint_entry; +}; + +#define __SDT_PROBE(prov, mod, func, name, uniq, f, ...) do { \ + __WEAK(__CONCAT(__start_set_, _SDT_TRACEPOINT_SET)); \ + __WEAK(__CONCAT(__stop_set_, _SDT_TRACEPOINT_SET)); \ + asm goto( \ + "0:\n" \ + _SDT_ASM_PATCH_INSTR "\n" \ + ".pushsection " _SDT_TRACEPOINT_SECTION ", \"aw\"\n" \ + _SDT_ASM_WORD " %" _SDT_ASM_PROBE_OPERAND "0\n" \ + _SDT_ASM_WORD " 0b\n" \ + _SDT_ASM_WORD " %l1\n" \ + _SDT_ASM_WORD " 0\n" \ + ".popsection\n" \ + : \ + : _SDT_ASM_PROBE_CONSTRAINT (&_SDT_PROBE_NAME(prov, mod, \ + func, name)) \ + : \ + : __sdt_probe##uniq); \ + if (0) { \ +__sdt_probe##uniq:; \ + f(_SDT_PROBE_NAME(prov, mod, func, name).id, __VA_ARGS__); \ + } \ } while (0) +#define _SDT_PROBE(prov, mod, func, name, uniq, f, ...) \ + __SDT_PROBE(prov, mod, func, name, uniq, f, __VA_ARGS__) +#define SDT_PROBE(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4) \ + _SDT_PROBE(prov, mod, func, name, __COUNTER__, sdt_probe, \ + (uintptr_t)arg0, (uintptr_t)arg1, (uintptr_t)arg2, \ + (uintptr_t)arg3, (uintptr_t)arg4) #define SDT_PROBE_ARGTYPE(_prov, _mod, _func, _name, _num, _type, _xtype) \ static struct sdt_argtype \ @@ -194,7 +244,7 @@ SET_DECLARE(sdt_argtypes_set, struct sdt_argtype); .ndx = _num, \ .type = _type, \ .xtype = _xtype, \ - .probe = _SDT_PROBE_NAME(_prov, _mod, _func, _name), \ + .probe = &_SDT_PROBE_NAME(_prov, _mod, _func, _name), \ }, \ }; \ DATA_SET(sdt_argtypes_set, \ @@ -243,17 +293,6 @@ SET_DECLARE(sdt_argtypes_set, struct sdt_argtype); SDT_PROBE_ARGTYPE(prov, mod, func, name, 4, arg4, NULL); \ SDT_PROBE_ARGTYPE(prov, mod, func, name, 5, arg5, NULL) -#define SDT_PROBE_DEFINE7(prov, mod, func, name, arg0, arg1, arg2, arg3,\ - arg4, arg5, arg6) \ - SDT_PROBE_DEFINE(prov, mod, func, name); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, arg0, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 1, arg1, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 2, arg2, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 3, arg3, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 4, arg4, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 5, arg5, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 6, arg6, NULL) - #define SDT_PROBE_DEFINE0_XLATE(prov, mod, func, name) \ SDT_PROBE_DEFINE(prov, mod, func, name) @@ -301,18 +340,6 @@ SET_DECLARE(sdt_argtypes_set, struct sdt_argtype); SDT_PROBE_ARGTYPE(prov, mod, func, name, 4, arg4, xarg4); \ SDT_PROBE_ARGTYPE(prov, mod, func, name, 5, arg5, xarg5) -#define SDT_PROBE_DEFINE7_XLATE(prov, mod, func, name, arg0, xarg0, \ - arg1, xarg1, arg2, xarg2, arg3, xarg3, arg4, xarg4, arg5, xarg5, arg6, \ - xarg6) \ - SDT_PROBE_DEFINE(prov, mod, func, name); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, arg0, xarg0); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 1, arg1, xarg1); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 2, arg2, xarg2); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 3, arg3, xarg3); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 4, arg4, xarg4); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 5, arg5, xarg5); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 6, arg6, xarg6) - #define SDT_PROBE0(prov, mod, func, name) \ SDT_PROBE(prov, mod, func, name, 0, 0, 0, 0, 0) #define SDT_PROBE1(prov, mod, func, name, arg0) \ @@ -325,27 +352,18 @@ SET_DECLARE(sdt_argtypes_set, struct sdt_argtype); SDT_PROBE(prov, mod, func, name, arg0, arg1, arg2, arg3, 0) #define SDT_PROBE5(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4) \ SDT_PROBE(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4) -#define SDT_PROBE6(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4, arg5) \ - do { \ - if (_SDT_PROBE_NAME(prov, mod, func, name)->id) \ - (*(void (*)(uint32_t, uintptr_t, uintptr_t, uintptr_t, \ - uintptr_t, uintptr_t, uintptr_t))sdt_probe_func)( \ - _SDT_PROBE_NAME(prov, mod, func, name)->id, \ - (uintptr_t)arg0, (uintptr_t)arg1, (uintptr_t)arg2, \ - (uintptr_t)arg3, (uintptr_t)arg4, (uintptr_t)arg5);\ - } while (0) -#define SDT_PROBE7(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4, arg5, \ - arg6) \ - do { \ - if (_SDT_PROBE_NAME(prov, mod, func, name)->id) \ - (*(void (*)(uint32_t, uintptr_t, uintptr_t, uintptr_t, \ - uintptr_t, uintptr_t, uintptr_t, uintptr_t)) \ - sdt_probe_func)( \ - _SDT_PROBE_NAME(prov, mod, func, name)->id, \ - (uintptr_t)arg0, (uintptr_t)arg1, (uintptr_t)arg2, \ - (uintptr_t)arg3, (uintptr_t)arg4, (uintptr_t)arg5, \ - (uintptr_t)arg6); \ - } while (0) +#define SDT_PROBE6(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4, arg5) \ + _SDT_PROBE(prov, mod, func, name, __COUNTER__, sdt_probe6, \ + (uintptr_t)arg0, (uintptr_t)arg1, (uintptr_t)arg2, \ + (uintptr_t)arg3, (uintptr_t)arg4, (uintptr_t)arg5) + +#ifdef KDTRACE_MIB_SDT +#define MIB_SDT_PROBE1(...) SDT_PROBE1(mib, __VA_ARGS__) +#define MIB_SDT_PROBE2(...) SDT_PROBE2(mib, __VA_ARGS__) +#else +#define MIB_SDT_PROBE1(...) +#define MIB_SDT_PROBE2(...) +#endif #define DTRACE_PROBE_IMPL_START(name, arg0, arg1, arg2, arg3, arg4) do { \ static SDT_PROBE_DEFINE(sdt, , , name); \ @@ -399,12 +417,12 @@ SET_DECLARE(sdt_argtypes_set, struct sdt_argtype); * way to avoid having to rely on CDDL code. */ typedef void (*sdt_probe_func_t)(uint32_t, uintptr_t arg0, uintptr_t arg1, - uintptr_t arg2, uintptr_t arg3, uintptr_t arg4); + uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5); /* * The 'sdt' provider will set it to dtrace_probe when it loads. */ -extern sdt_probe_func_t sdt_probe_func; +extern sdt_probe_func_t sdt_probe_func; struct sdt_probe; struct sdt_provider; @@ -425,6 +443,7 @@ struct sdt_probe { TAILQ_ENTRY(sdt_probe) probe_entry; /* SDT probe list entry. */ TAILQ_HEAD(, sdt_argtype) argtype_list; + STAILQ_HEAD(, sdt_tracepoint) tracepoint_list; const char *mod; const char *func; const char *name; @@ -442,7 +461,7 @@ struct sdt_provider { }; void sdt_probe_stub(uint32_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, - uintptr_t); + uintptr_t, uintptr_t); SDT_PROVIDER_DECLARE(sdt); diff --git a/lib/libc/include/generic-freebsd/sys/select.h b/lib/libc/include/generic-freebsd/sys/select.h index 790c2d045fed..dd75cacf0af5 100644 --- a/lib/libc/include/generic-freebsd/sys/select.h +++ b/lib/libc/include/generic-freebsd/sys/select.h @@ -49,6 +49,12 @@ typedef __fd_mask fd_mask; typedef __sigset_t sigset_t; #endif +#if !defined(_KERNEL) && defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 +#include +#else +#define __SSP_FORTIFY_LEVEL 0 +#endif + /* * Select uses bit masks of file descriptors in longs. These macros * manipulate such bit fields (the filesystem macros use chars). @@ -75,13 +81,33 @@ typedef struct fd_set { #define fds_bits __fds_bits #endif +#define __fdset_idx_(p, n) ((n) / _NFDBITS) +#if __SSP_FORTIFY_LEVEL == 0 +#define __fdset_idx(p, n) __fdset_idx_(p, n) +#else +__ssp_inline unsigned long +__fdset_idx(const fd_set *p, unsigned long idx) +{ + __size_t psz = __ssp_bos0(p); + unsigned long sidx = __fdset_idx_(p, idx); + + if (idx >= FD_SETSIZE) + __chk_fail(); + if (psz / sizeof(__fd_mask) < (sidx + 1)) + __chk_fail(); + + return (sidx); +} +#endif + #define __fdset_mask(n) ((__fd_mask)1 << ((n) % _NFDBITS)) -#define FD_CLR(n, p) ((p)->__fds_bits[(n)/_NFDBITS] &= ~__fdset_mask(n)) +#define FD_CLR(n, p) ((p)->__fds_bits[__fdset_idx(p, n)] &= ~__fdset_mask(n)) #if __BSD_VISIBLE #define FD_COPY(f, t) (void)(*(t) = *(f)) #endif -#define FD_ISSET(n, p) (((p)->__fds_bits[(n)/_NFDBITS] & __fdset_mask(n)) != 0) -#define FD_SET(n, p) ((p)->__fds_bits[(n)/_NFDBITS] |= __fdset_mask(n)) +#define FD_ISSET(n, p) \ + (((p)->__fds_bits[__fdset_idx(p, n)] & __fdset_mask(n)) != 0) +#define FD_SET(n, p) ((p)->__fds_bits[__fdset_idx(p, n)] |= __fdset_mask(n)) #define FD_ZERO(p) do { \ fd_set *_p; \ __size_t _n; \ diff --git a/lib/libc/include/generic-freebsd/sys/selinfo.h b/lib/libc/include/generic-freebsd/sys/selinfo.h index 565236d3a89d..6c82a54f15ad 100644 --- a/lib/libc/include/generic-freebsd/sys/selinfo.h +++ b/lib/libc/include/generic-freebsd/sys/selinfo.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)select.h 8.2 (Berkeley) 1/4/94 */ #ifndef _SYS_SELINFO_H_ diff --git a/lib/libc/include/generic-freebsd/sys/sem.h b/lib/libc/include/generic-freebsd/sys/sem.h index 79b15ab5e6cf..15fcc9e17099 100644 --- a/lib/libc/include/generic-freebsd/sys/sem.h +++ b/lib/libc/include/generic-freebsd/sys/sem.h @@ -148,9 +148,6 @@ int kern_get_sema(struct thread *td, struct semid_kernel **res, #else /* !_KERNEL */ __BEGIN_DECLS -#if __BSD_VISIBLE -int semsys(int, ...); -#endif int semctl(int, int, int, ...); int semget(key_t, int, int); int semop(int, struct sembuf *, size_t); diff --git a/lib/libc/include/generic-freebsd/sys/seqc.h b/lib/libc/include/generic-freebsd/sys/seqc.h index a2bdc86658a3..727ec1a251b3 100644 --- a/lib/libc/include/generic-freebsd/sys/seqc.h +++ b/lib/libc/include/generic-freebsd/sys/seqc.h @@ -78,14 +78,14 @@ static __inline seqc_t seqc_read_any(const seqc_t *seqcp) { - return (atomic_load_acq_int(__DECONST(seqc_t *, seqcp))); + return (atomic_load_acq_int(seqcp)); } static __inline seqc_t seqc_read_notmodify(const seqc_t *seqcp) { - return (atomic_load_acq_int(__DECONST(seqc_t *, seqcp)) & ~SEQC_MOD); + return (atomic_load_acq_int(seqcp) & ~SEQC_MOD); } static __inline seqc_t diff --git a/lib/libc/include/generic-freebsd/sys/sglist.h b/lib/libc/include/generic-freebsd/sys/sglist.h index 5a1701744c5e..64e4b786d569 100644 --- a/lib/libc/include/generic-freebsd/sys/sglist.h +++ b/lib/libc/include/generic-freebsd/sys/sglist.h @@ -55,6 +55,7 @@ struct sglist { struct bio; struct mbuf; +struct thread; struct uio; static __inline void diff --git a/lib/libc/include/generic-freebsd/sys/shm.h b/lib/libc/include/generic-freebsd/sys/shm.h index a31adc49e9db..1d2344bb0209 100644 --- a/lib/libc/include/generic-freebsd/sys/shm.h +++ b/lib/libc/include/generic-freebsd/sys/shm.h @@ -51,7 +51,7 @@ #define SHM_RDONLY 010000 /* Attach read-only (else read-write) */ #define SHM_RND 020000 /* Round attach address to SHMLBA */ -#define SHM_REMAP 030000 /* Unmap before mapping */ +#define SHM_REMAP 040000 /* Unmap before mapping */ #define SHMLBA PAGE_SIZE /* Segment low boundary address multiple */ /* "official" access mode definitions; somewhat braindead since you have @@ -173,9 +173,6 @@ typedef __size_t size_t; #endif __BEGIN_DECLS -#if __BSD_VISIBLE -int shmsys(int, ...); -#endif void *shmat(int, const void *, int); int shmget(key_t, size_t, int); int shmctl(int, int, struct shmid_ds *); diff --git a/lib/libc/include/generic-freebsd/sys/sigio.h b/lib/libc/include/generic-freebsd/sys/sigio.h index 5cf831b40763..7b560271d77a 100644 --- a/lib/libc/include/generic-freebsd/sys/sigio.h +++ b/lib/libc/include/generic-freebsd/sys/sigio.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)filedesc.h 8.1 (Berkeley) 6/2/93 */ #ifndef _SYS_SIGIO_H_ diff --git a/lib/libc/include/generic-freebsd/sys/signal.h b/lib/libc/include/generic-freebsd/sys/signal.h index 0859eaf578ed..90565ec5f691 100644 --- a/lib/libc/include/generic-freebsd/sys/signal.h +++ b/lib/libc/include/generic-freebsd/sys/signal.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)signal.h 8.4 (Berkeley) 5/4/95 */ #ifndef _SYS_SIGNAL_H_ @@ -42,6 +40,7 @@ #include #include #include +#include #include #include /* __MINSIGSTKSZ */ @@ -255,7 +254,7 @@ typedef struct __siginfo { #define si_syscall _reason._capsicum._syscall #if defined(_WANT_LWPINFO32) || (defined(_KERNEL) && defined(__LP64__)) -struct siginfo32 { +struct __siginfo32 { int si_signo; /* signal number */ int si_errno; /* errno association */ int si_code; /* signal code */ @@ -373,7 +372,7 @@ struct sigaction { #define SA_NOCLDSTOP 0x0008 /* do not generate SIGCHLD on child stop */ #endif /* __POSIX_VISIBLE || __XSI_VISIBLE */ -#if __XSI_VISIBLE +#if __XSI_VISIBLE || __POSIX_VISIBLE >= 200809 #define SA_ONSTACK 0x0001 /* take signal on signal stack */ #define SA_RESTART 0x0002 /* restart system call on signal return */ #define SA_RESETHAND 0x0004 /* reset to SIG_DFL when taking signal */ @@ -408,29 +407,6 @@ typedef __sighandler_t *sig_t; /* type of pointer to a signal function */ typedef void __siginfohandler_t(int, struct __siginfo *, void *); #endif -#if __XSI_VISIBLE -#if __BSD_VISIBLE -#define __stack_t sigaltstack -#endif -typedef struct __stack_t stack_t; - -#define SS_ONSTACK 0x0001 /* take signal on alternate stack */ -#define SS_DISABLE 0x0004 /* disable taking signals on alternate stack */ -#define MINSIGSTKSZ __MINSIGSTKSZ /* minimum stack size */ -#define SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended stack size */ -#endif - -/* - * Structure used in sigaltstack call. Its definition is always - * needed for __ucontext. If __BSD_VISIBLE is defined, the structure - * tag is actually sigaltstack. - */ -struct __stack_t { - void *ss_sp; /* signal stack base */ - __size_t ss_size; /* signal stack length */ - int ss_flags; /* SS_DISABLE and/or SS_ONSTACK */ -}; - #if __BSD_VISIBLE /* * 4.3 compatibility: diff --git a/lib/libc/include/generic-freebsd/sys/signalvar.h b/lib/libc/include/generic-freebsd/sys/signalvar.h index 6f618dffa338..433d148b13a8 100644 --- a/lib/libc/include/generic-freebsd/sys/signalvar.h +++ b/lib/libc/include/generic-freebsd/sys/signalvar.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)signalvar.h 8.6 (Berkeley) 2/19/95 */ #ifndef _SYS_SIGNALVAR_H_ @@ -272,6 +270,7 @@ int __sys_sigfastblock(int cmd, void *ptr); #ifdef _KERNEL extern bool sigfastblock_fetch_always; +extern bool pt_attach_transparent; /* Return nonzero if process p has an unmasked pending signal. */ #define SIGPENDING(td) \ @@ -404,6 +403,7 @@ int sigev_findtd(struct proc *p, struct sigevent *sigev, struct thread **); void sigfastblock_clear(struct thread *td); void sigfastblock_fetch(struct thread *td); int sig_intr(void); +bool sig_do_core(int); void siginit(struct proc *p); void signotify(struct thread *td); void sigqueue_delete(struct sigqueue *queue, int sig); diff --git a/lib/libc/include/generic-freebsd/sys/sleepqueue.h b/lib/libc/include/generic-freebsd/sys/sleepqueue.h index be825205eb51..f164e3ff7801 100644 --- a/lib/libc/include/generic-freebsd/sys/sleepqueue.h +++ b/lib/libc/include/generic-freebsd/sys/sleepqueue.h @@ -86,21 +86,21 @@ struct thread; #define SLEEPQ_DROP 0x400 /* Return without lock held. */ void init_sleepqueues(void); -int sleepq_abort(struct thread *td, int intrval); +void sleepq_abort(struct thread *td, int intrval); void sleepq_add(const void *wchan, struct lock_object *lock, const char *wmesg, int flags, int queue); struct sleepqueue *sleepq_alloc(void); -int sleepq_broadcast(const void *wchan, int flags, int pri, int queue); +void sleepq_broadcast(const void *wchan, int flags, int pri, int queue); void sleepq_chains_remove_matching(bool (*matches)(struct thread *)); void sleepq_free(struct sleepqueue *sq); void sleepq_lock(const void *wchan); struct sleepqueue *sleepq_lookup(const void *wchan); void sleepq_release(const void *wchan); void sleepq_remove(struct thread *td, const void *wchan); -int sleepq_remove_matching(struct sleepqueue *sq, int queue, +void sleepq_remove_matching(struct sleepqueue *sq, int queue, bool (*matches)(struct thread *), int pri); void sleepq_remove_nested(struct thread *td); -int sleepq_signal(const void *wchan, int flags, int pri, int queue); +void sleepq_signal(const void *wchan, int flags, int pri, int queue); void sleepq_set_timeout_sbt(const void *wchan, sbintime_t sbt, sbintime_t pr, int flags); #define sleepq_set_timeout(wchan, timo) \ diff --git a/lib/libc/include/generic-freebsd/sys/smr_types.h b/lib/libc/include/generic-freebsd/sys/smr_types.h index 4016023fcc1b..1b81a65a5de4 100644 --- a/lib/libc/include/generic-freebsd/sys/smr_types.h +++ b/lib/libc/include/generic-freebsd/sys/smr_types.h @@ -60,7 +60,8 @@ struct { \ */ #define smr_entered_load(p, smr) ({ \ SMR_ASSERT(SMR_ENTERED((smr)), "smr_entered_load"); \ - (__typeof((p)->__ptr))atomic_load_acq_ptr((uintptr_t *)&(p)->__ptr); \ + (__typeof((p)->__ptr))atomic_load_acq_ptr( \ + (const uintptr_t *)&(p)->__ptr); \ }) /* @@ -70,7 +71,8 @@ struct { \ */ #define smr_serialized_load(p, ex) ({ \ SMR_ASSERT(ex, "smr_serialized_load"); \ - (__typeof((p)->__ptr))atomic_load_ptr(&(p)->__ptr); \ + (__typeof((p)->__ptr))atomic_load_ptr( \ + (const uintptr_t *)&(p)->__ptr); \ }) /* diff --git a/lib/libc/include/generic-freebsd/sys/sndstat.h b/lib/libc/include/generic-freebsd/sys/sndstat.h index ed4fa2493a62..c80580ba07eb 100644 --- a/lib/libc/include/generic-freebsd/sys/sndstat.h +++ b/lib/libc/include/generic-freebsd/sys/sndstat.h @@ -94,12 +94,14 @@ struct sndstioc_nv_arg { #define SNDST_DSPS_SOUND4_CHAN_LEFTVOL "left_volume" #define SNDST_DSPS_SOUND4_CHAN_RIGHTVOL "right_volume" #define SNDST_DSPS_SOUND4_CHAN_HWBUF_FORMAT "hwbuf_format" +#define SNDST_DSPS_SOUND4_CHAN_HWBUF_RATE "hwbuf_rate" #define SNDST_DSPS_SOUND4_CHAN_HWBUF_SIZE "hwbuf_size" #define SNDST_DSPS_SOUND4_CHAN_HWBUF_BLKSZ "hwbuf_blksz" #define SNDST_DSPS_SOUND4_CHAN_HWBUF_BLKCNT "hwbuf_blkcnt" #define SNDST_DSPS_SOUND4_CHAN_HWBUF_FREE "hwbuf_free" #define SNDST_DSPS_SOUND4_CHAN_HWBUF_READY "hwbuf_ready" #define SNDST_DSPS_SOUND4_CHAN_SWBUF_FORMAT "swbuf_format" +#define SNDST_DSPS_SOUND4_CHAN_SWBUF_RATE "swbuf_rate" #define SNDST_DSPS_SOUND4_CHAN_SWBUF_SIZE "swbuf_size" #define SNDST_DSPS_SOUND4_CHAN_SWBUF_BLKSZ "swbuf_blksz" #define SNDST_DSPS_SOUND4_CHAN_SWBUF_BLKCNT "swbuf_blkcnt" diff --git a/lib/libc/include/generic-freebsd/sys/sockbuf.h b/lib/libc/include/generic-freebsd/sys/sockbuf.h index bb6e9d6d8073..240afbe3827f 100644 --- a/lib/libc/include/generic-freebsd/sys/sockbuf.h +++ b/lib/libc/include/generic-freebsd/sys/sockbuf.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)socketvar.h 8.3 (Berkeley) 2/19/95 */ #ifndef _SYS_SOCKBUF_H_ #define _SYS_SOCKBUF_H_ @@ -42,13 +40,13 @@ #define SB_SEL 0x08 /* someone is selecting */ #define SB_ASYNC 0x10 /* ASYNC I/O, need signals */ #define SB_UPCALL 0x20 /* someone wants an upcall */ -#define SB_NOINTR 0x40 /* operations not interruptible */ +#define SB_AUTOLOWAT 0x40 /* sendfile(2) may autotune sb_lowat */ #define SB_AIO 0x80 /* AIO operations queued */ #define SB_KNOTE 0x100 /* kernel note attached */ #define SB_NOCOALESCE 0x200 /* don't coalesce new data into existing mbufs */ #define SB_IN_TOE 0x400 /* socket buffer is in the middle of an operation */ #define SB_AUTOSIZE 0x800 /* automatically size socket buffer */ -#define SB_STOP 0x1000 /* backpressure indicator */ +/* was SB_STOP 0x1000 */ #define SB_AIO_RUNNING 0x2000 /* AIO operation running */ #define SB_SPLICED 0x4000 /* socket buffer is spliced; previously used for SB_TLS_IFNET */ @@ -64,7 +62,7 @@ #include #include -#define SB_MAX (2*1024*1024) /* default for max chars in sockbuf */ +#define SB_MAX (8*1024*1024) /* default for max chars in sockbuf */ struct ktls_session; struct mbuf; @@ -134,6 +132,18 @@ struct sockbuf { /* TLS state, locked by sockbuf and sock I/O mutexes. */ struct ktls_session *sb_tls_info; }; + /* + * PF_UNIX/SOCK_STREAM and PF_UNIX/SOCK_SEQPACKET + * A simple stream buffer with not ready data pointer. + */ + struct { + STAILQ_HEAD(, mbuf) uxst_mbq; + struct mbuf *uxst_fnrdy; + struct socket *uxst_peer; + u_int uxst_flags; +#define UXST_PEER_AIO 0x1 +#define UXST_PEER_SEL 0x2 + }; /* * PF_UNIX/SOCK_DGRAM * @@ -167,6 +177,12 @@ struct sockbuf { u_int uxdg_ctl; u_int uxdg_mbcnt; }; + /* + * Netlink socket. + */ + struct { + TAILQ_HEAD(, nl_buf) nl_queue; + }; }; }; @@ -194,8 +210,6 @@ typedef enum { SO_RCV, SO_SND } sb_which; * Socket buffer private mbuf(9) flags. */ #define M_NOTREADY M_PROTO1 /* m_data not populated yet */ -#define M_BLOCKED M_PROTO2 /* M_NOTREADY in front of m */ -#define M_NOTAVAIL (M_NOTREADY | M_BLOCKED) void sbappend(struct sockbuf *sb, struct mbuf *m, int flags); void sbappend_locked(struct sockbuf *sb, struct mbuf *m, int flags); @@ -287,9 +301,6 @@ sbspace(struct sockbuf *sb) SOCKBUF_LOCK_ASSERT(sb); #endif - if (sb->sb_flags & SB_STOP) - return(0); - bleft = sb->sb_hiwat - sb->sb_ccc; mleft = sb->sb_mbmax - sb->sb_mbcnt; diff --git a/lib/libc/include/generic-freebsd/sys/socket.h b/lib/libc/include/generic-freebsd/sys/socket.h index 402997116455..aea4284303de 100644 --- a/lib/libc/include/generic-freebsd/sys/socket.h +++ b/lib/libc/include/generic-freebsd/sys/socket.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)socket.h 8.4 (Berkeley) 2/21/94 */ #ifndef _SYS_SOCKET_H_ @@ -113,10 +111,11 @@ typedef __uintptr_t uintptr_t; */ #define SOCK_CLOEXEC 0x10000000 #define SOCK_NONBLOCK 0x20000000 +#define SOCK_CLOFORK 0x40000000 #ifdef _KERNEL /* * Flags for accept1(), kern_accept4() and solisten_dequeue, in addition - * to SOCK_CLOEXEC and SOCK_NONBLOCK. + * to SOCK_CLOEXEC, SOCK_CLOFORK and SOCK_NONBLOCK. */ #define ACCEPT4_INHERIT 0x1 #define ACCEPT4_COMPAT 0x2 @@ -166,17 +165,18 @@ typedef __uintptr_t uintptr_t; #define SO_LISTENQLIMIT 0x1011 /* socket's backlog limit */ #define SO_LISTENQLEN 0x1012 /* socket's complete queue length */ #define SO_LISTENINCQLEN 0x1013 /* socket's incomplete queue length */ -#define SO_SETFIB 0x1014 /* use this FIB to route */ +#define SO_FIB 0x1014 /* get or set socket FIB */ +#define SO_SETFIB SO_FIB /* backward compat alias */ #define SO_USER_COOKIE 0x1015 /* user cookie (dummynet etc.) */ #define SO_PROTOCOL 0x1016 /* get socket protocol (Linux name) */ #define SO_PROTOTYPE SO_PROTOCOL /* alias for SO_PROTOCOL (SunOS name) */ #define SO_TS_CLOCK 0x1017 /* clock type used for SO_TIMESTAMP */ #define SO_MAX_PACING_RATE 0x1018 /* socket's max TX pacing rate (Linux name) */ #define SO_DOMAIN 0x1019 /* get socket domain */ +#define SO_SPLICE 0x1023 /* splice data to other socket */ #endif #if __BSD_VISIBLE -#define SO_SPLICE 0x1023 /* splice data to other socket */ #define SO_TS_REALTIME_MICRO 0 /* microsecond resolution, realtime */ #define SO_TS_BINTIME 1 /* sub-nanosecond resolution, realtime */ #define SO_TS_REALTIME 2 /* nanosecond resolution, realtime */ @@ -270,7 +270,8 @@ struct accept_filter_arg { #define AF_INET6_SDP 42 /* OFED Socket Direct Protocol ipv6 */ #define AF_HYPERV 43 /* HyperV sockets */ #define AF_DIVERT 44 /* divert(4) */ -#define AF_MAX 44 +#define AF_IPFWLOG 46 +#define AF_MAX 46 /* * When allocating a new AF_ constant, please only allocate * even numbered constants for FreeBSD until 134 as odd numbered AF_ @@ -396,6 +397,7 @@ struct sockproto { #define PF_INET_SDP AF_INET_SDP #define PF_INET6_SDP AF_INET6_SDP #define PF_DIVERT AF_DIVERT +#define PF_IPFWLOG AF_IPFWLOG #define PF_MAX AF_MAX @@ -477,6 +479,9 @@ struct msghdr { #define MSG_MORETOCOME 0x00100000 /* additional data pending */ #define MSG_TLSAPPDATA 0x00200000 /* do not soreceive() alert rec. (TLS) */ #endif +#if __BSD_VISIBLE +#define MSG_CMSG_CLOFORK 0x00400000 /* make received fds close-on-fork */ +#endif /* * Header for ancillary data objects in msg_control buffer. @@ -631,17 +636,14 @@ struct omsghdr { /* * howto arguments for shutdown(2), specified by Posix.1g. */ -#define SHUT_RD 0 /* shut down the reading side */ -#define SHUT_WR 1 /* shut down the writing side */ -#define SHUT_RDWR 2 /* shut down both sides */ - -#if __BSD_VISIBLE -/* for SCTP */ -/* we cheat and use the SHUT_XX defines for these */ -#define PRU_FLUSH_RD SHUT_RD -#define PRU_FLUSH_WR SHUT_WR -#define PRU_FLUSH_RDWR SHUT_RDWR -#endif +enum shutdown_how { + SHUT_RD = 0, /* shut down the reading side */ +#define SHUT_RD SHUT_RD + SHUT_WR, /* shut down the writing side */ +#define SHUT_WR SHUT_WR + SHUT_RDWR /* shut down both sides */ +#define SHUT_RDWR SHUT_RDWR +}; #if __BSD_VISIBLE /* @@ -689,6 +691,10 @@ struct splice { #ifndef _KERNEL +#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 +#include +#endif + #include __BEGIN_DECLS @@ -733,33 +739,10 @@ __END_DECLS #ifdef _KERNEL struct socket; -struct inpcb *so_sotoinpcb(struct socket *so); -struct sockbuf *so_sockbuf_snd(struct socket *); -struct sockbuf *so_sockbuf_rcv(struct socket *); - -int so_state_get(const struct socket *); -void so_state_set(struct socket *, int); - int so_options_get(const struct socket *); void so_options_set(struct socket *, int); int so_error_get(const struct socket *); void so_error_set(struct socket *, int); - -int so_linger_get(const struct socket *); -void so_linger_set(struct socket *, int); - -struct protosw *so_protosw_get(const struct socket *); -void so_protosw_set(struct socket *, struct protosw *); - -void so_sorwakeup_locked(struct socket *so); -void so_sowwakeup_locked(struct socket *so); - -void so_sorwakeup(struct socket *so); -void so_sowwakeup(struct socket *so); - -void so_lock(struct socket *so); -void so_unlock(struct socket *so); - #endif /* _KERNEL */ #endif /* !_SYS_SOCKET_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/socketvar.h b/lib/libc/include/generic-freebsd/sys/socketvar.h index 5b686e218913..4d135960a22f 100644 --- a/lib/libc/include/generic-freebsd/sys/socketvar.h +++ b/lib/libc/include/generic-freebsd/sys/socketvar.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)socketvar.h 8.3 (Berkeley) 2/19/95 */ #ifndef _SYS_SOCKETVAR_H_ @@ -82,6 +80,7 @@ struct so_splice { struct mtx mtx; unsigned int wq_index; enum so_splice_state { + SPLICE_INIT, /* embryonic state, don't queue work yet */ SPLICE_IDLE, /* waiting for work to arrive */ SPLICE_QUEUED, /* a wakeup has queued some work */ SPLICE_RUNNING, /* currently transferring data */ @@ -239,7 +238,7 @@ struct socket { #define SS_ISDISCONNECTING 0x0008 /* in process of disconnecting */ #define SS_NBIO 0x0100 /* non-blocking ops */ #define SS_ASYNC 0x0200 /* async i/o notify */ -#define SS_ISCONFIRMING 0x0400 /* deciding to accept connection req */ +/* was SS_ISCONFIRMING 0x0400 */ #define SS_ISDISCONNECTED 0x2000 /* socket disconnected from peer */ #ifdef _KERNEL @@ -343,16 +342,14 @@ soeventmtx(struct socket *so, const sb_which which) soiolock((so), &(so)->so_snd_sx, (flags)) #define SOCK_IO_SEND_UNLOCK(so) \ soiounlock(&(so)->so_snd_sx) -#define SOCK_IO_SEND_OWNED(so) sx_xlocked(&(so)->so_snd_sx) #define SOCK_IO_SEND_ASSERT_LOCKED(so) \ - sx_assert(&(so)->so_snd_sx, SA_XLOCKED) + sx_assert(&(so)->so_snd_sx, SA_LOCKED) #define SOCK_IO_RECV_LOCK(so, flags) \ soiolock((so), &(so)->so_rcv_sx, (flags)) #define SOCK_IO_RECV_UNLOCK(so) \ soiounlock(&(so)->so_rcv_sx) -#define SOCK_IO_RECV_OWNED(so) sx_xlocked(&(so)->so_rcv_sx) #define SOCK_IO_RECV_ASSERT_LOCKED(so) \ - sx_assert(&(so)->so_rcv_sx, SA_XLOCKED) + sx_assert(&(so)->so_rcv_sx, SA_LOCKED) /* do we have to send all at once on a socket? */ #define sosendallatonce(so) \ @@ -459,7 +456,8 @@ MALLOC_DECLARE(M_SONAME); #define HHOOK_FILT_SOREAD 4 #define HHOOK_FILT_SOWRITE 5 #define HHOOK_SOCKET_CLOSE 6 -#define HHOOK_SOCKET_LAST HHOOK_SOCKET_CLOSE +#define HHOOK_SOCKET_NEWCONN 7 +#define HHOOK_SOCKET_LAST HHOOK_SOCKET_NEWCONN struct socket_hhook_data { struct socket *so; @@ -479,6 +477,7 @@ struct mbuf; struct sockaddr; struct ucred; struct uio; +enum shutdown_how; /* Return values for socket upcalls. */ #define SU_OK 0 @@ -489,12 +488,14 @@ struct uio; */ int getsockaddr(struct sockaddr **namp, const struct sockaddr *uaddr, size_t len); -int getsock_cap(struct thread *td, int fd, cap_rights_t *rightsp, +int getsock_cap(struct thread *td, int fd, const cap_rights_t *rightsp, struct file **fpp, struct filecaps *havecaps); -int getsock(struct thread *td, int fd, cap_rights_t *rightsp, +int getsock(struct thread *td, int fd, const cap_rights_t *rightsp, struct file **fpp); void soabort(struct socket *so); -int soaccept(struct socket *so, struct sockaddr **nam); +int soaccept(struct socket *so, struct sockaddr *sa); +int sopeeraddr(struct socket *so, struct sockaddr *sa); +int sosockaddr(struct socket *so, struct sockaddr *sa); void soaio_enqueue(struct task *task); void soaio_rcv(void *context, int pending); void soaio_snd(void *context, int pending); @@ -525,10 +526,9 @@ struct socket * sonewconn(struct socket *head, int connstatus); struct socket * sopeeloff(struct socket *); -int sopoll(struct socket *so, int events, struct ucred *active_cred, - struct thread *td); -int sopoll_generic(struct socket *so, int events, - struct ucred *active_cred, struct thread *td); +int sopoll_generic(struct socket *so, int events, struct thread *td); +int sokqfilter_generic(struct socket *so, struct knote *kn); +int soaio_queue_generic(struct socket *so, struct kaiocb *job); int soreceive(struct socket *so, struct sockaddr **paddr, struct uio *uio, struct mbuf **mp0, struct mbuf **controlp, int *flagsp); int soreceive_stream(struct socket *so, struct sockaddr **paddr, @@ -555,7 +555,9 @@ int sosend_dgram(struct socket *so, struct sockaddr *addr, int sosend_generic(struct socket *so, struct sockaddr *addr, struct uio *uio, struct mbuf *top, struct mbuf *control, int flags, struct thread *td); -int soshutdown(struct socket *so, int how); +int sendfile_wait_generic(struct socket *so, off_t need, int *space); +int sosetfib(struct socket *so, int fibnum); +int soshutdown(struct socket *so, enum shutdown_how); void soupcall_clear(struct socket *, sb_which); void soupcall_set(struct socket *, sb_which, so_upcall_t, void *); void solisten_upcall_set(struct socket *, so_upcall_t, void *); @@ -596,6 +598,8 @@ SYSCTL_DECL(_net_inet_accf); int accept_filt_generic_mod_event(module_t mod, int event, void *data); #endif +int pr_listen_notsupp(struct socket *so, int backlog, struct thread *td); + #endif /* _KERNEL */ /* @@ -615,7 +619,8 @@ struct xsocket { uint32_t so_qlimit; pid_t so_pgid; uid_t so_uid; - int32_t so_spare32[8]; + int32_t so_fibnum; + int32_t so_spare32[7]; int16_t so_type; int16_t so_options; int16_t so_linger; diff --git a/lib/libc/include/generic-freebsd/sys/sockio.h b/lib/libc/include/generic-freebsd/sys/sockio.h index 87d96f12435c..fc3b2087ae96 100644 --- a/lib/libc/include/generic-freebsd/sys/sockio.h +++ b/lib/libc/include/generic-freebsd/sys/sockio.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)sockio.h 8.1 (Berkeley) 3/28/94 */ #ifndef _SYS_SOCKIO_H_ @@ -149,4 +147,8 @@ #define SIOCSIFCAPNV _IOW('i', 155, struct ifreq) /* set IF features */ #define SIOCGIFCAPNV _IOWR('i', 156, struct ifreq) /* get IF features */ +#define SIOCGUMBINFO _IOWR('i', 157, struct ifreq) /* get MBIM info */ +#define SIOCSUMBPARAM _IOW('i', 158, struct ifreq) /* set MBIM param */ +#define SIOCGUMBPARAM _IOWR('i', 159, struct ifreq) /* get MBIM param */ + #endif /* !_SYS_SOCKIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/sockopt.h b/lib/libc/include/generic-freebsd/sys/sockopt.h index 95d4cc40a12f..b1d92465793b 100644 --- a/lib/libc/include/generic-freebsd/sys/sockopt.h +++ b/lib/libc/include/generic-freebsd/sys/sockopt.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)socketvar.h 8.3 (Berkeley) 2/19/95 */ #ifndef _SYS_SOCKOPT_H_ #define _SYS_SOCKOPT_H_ diff --git a/lib/libc/include/generic-freebsd/sys/soundcard.h b/lib/libc/include/generic-freebsd/sys/soundcard.h index e55e8b3c72d2..4c285eff2853 100644 --- a/lib/libc/include/generic-freebsd/sys/soundcard.h +++ b/lib/libc/include/generic-freebsd/sys/soundcard.h @@ -184,6 +184,8 @@ struct snd_size { #define AFMT_S24_BE 0x00020000 /* Big endian signed 24-bit */ #define AFMT_U24_LE 0x00040000 /* Little endian unsigned 24-bit */ #define AFMT_U24_BE 0x00080000 /* Big endian unsigned 24-bit */ +#define AFMT_F32_LE 0x10000000 /* Little endian 32-bit floating point */ +#define AFMT_F32_BE 0x20000000 /* Big endian 32-bit floating point */ /* Machine dependent AFMT_* definitions. */ #if BYTE_ORDER == LITTLE_ENDIAN @@ -199,6 +201,8 @@ struct snd_size { #define AFMT_U16_OE AFMT_U16_BE #define AFMT_U24_OE AFMT_U24_BE #define AFMT_U32_OE AFMT_U32_BE +#define AFMT_F32_NE AFMT_F32_LE +#define AFMT_F32_OE AFMT_F32_BE #else #define AFMT_S16_OE AFMT_S16_LE #define AFMT_S24_OE AFMT_S24_LE @@ -212,8 +216,12 @@ struct snd_size { #define AFMT_U16_NE AFMT_U16_BE #define AFMT_U24_NE AFMT_U24_BE #define AFMT_U32_NE AFMT_U32_BE +#define AFMT_F32_NE AFMT_F32_BE +#define AFMT_F32_OE AFMT_F32_LE #endif +#define AFMT_FLOAT AFMT_F32_NE /* compatibility alias */ + #define AFMT_STEREO 0x10000000 /* can do/want stereo */ /* @@ -1400,8 +1408,9 @@ void seqbuf_dump(void); /* This function must be provided by programs */ int i, l=(len); if (l>6)l=6;\ _SEQ_NEEDBUF(8);\ _seqbuf[_seqbufptr] = EV_SYSEX;\ - for(i=0;i + +#endif /* __SYS_STDARG_H__ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/stdatomic.h b/lib/libc/include/generic-freebsd/sys/stdatomic.h index ae0516be1c8f..e2ff73bcfb89 100644 --- a/lib/libc/include/generic-freebsd/sys/stdatomic.h +++ b/lib/libc/include/generic-freebsd/sys/stdatomic.h @@ -33,7 +33,8 @@ #include #include -#if __has_extension(c_atomic) || __has_extension(cxx_atomic) +#if (__has_extension(c_atomic) || __has_extension(cxx_atomic)) && \ + defined(__clang__) #define __CLANG_ATOMICS #elif __GNUC_PREREQ__(4, 7) #define __GNUC_ATOMICS diff --git a/lib/libc/include/generic-freebsd/sys/sx.h b/lib/libc/include/generic-freebsd/sys/sx.h index d6756fbc1dff..c40bd9c9c7a9 100644 --- a/lib/libc/include/generic-freebsd/sys/sx.h +++ b/lib/libc/include/generic-freebsd/sys/sx.h @@ -99,7 +99,7 @@ * Function prototipes. Routines that start with an underscore are not part * of the public interface and are wrappered with a macro. */ -void sx_sysinit(void *arg); +void sx_sysinit(const void *arg); #define sx_init(sx, desc) sx_init_flags((sx), (desc), 0) void sx_init_flags(struct sx *sx, const char *description, int opts); void sx_destroy(struct sx *sx); @@ -301,12 +301,12 @@ __sx_xunlock(struct sx *sx, struct thread *td, const char *file, int line) #ifdef _STANDALONE /* since we have no threads in the boot loader, trivially implement no-op version */ -#define sx_xlock(s) (1) -#define sx_try_xlock(s) (1) -#define sx_xunlock(s) (1) -#define SX_DUPOK 0 -#define SX_NEW 0 -#define SX_NOWITNESS 0 +#define sx_xlock(s) do {} while (0) +#define sx_try_xlock(s) (1) +#define sx_xunlock(s) do {} while (0) +#define SX_DUPOK 0 +#define SX_NEW 0 +#define SX_NOWITNESS 0 static __inline void sx_init_flags(struct sx *sx, const char *description, int opts) diff --git a/lib/libc/include/generic-freebsd/sys/syscall.h b/lib/libc/include/generic-freebsd/sys/syscall.h index 0cec5b059aa2..1333b48c7ff6 100644 --- a/lib/libc/include/generic-freebsd/sys/syscall.h +++ b/lib/libc/include/generic-freebsd/sys/syscall.h @@ -4,8 +4,10 @@ * DO NOT EDIT-- this file is automatically @generated. */ +#define SYS_exit SYS__exit + #define SYS_syscall 0 -#define SYS_exit 1 +#define SYS__exit 1 #define SYS_fork 2 #define SYS_read 3 #define SYS_write 4 @@ -73,8 +75,8 @@ #define SYS_vfork 66 /* 67 is obsolete vread */ /* 68 is obsolete vwrite */ -#define SYS_sbrk 69 -#define SYS_sstk 70 + /* 69 is obsolete sbrk */ + /* 70 is obsolete sstk */ /* 71 is old mmap */ #define SYS_freebsd11_vadvise 72 #define SYS_munmap 73 @@ -83,8 +85,8 @@ /* 76 is obsolete vhangup */ /* 77 is obsolete vlimit */ #define SYS_mincore 78 -#define SYS_getgroups 79 -#define SYS_setgroups 80 +#define SYS_freebsd14_getgroups 79 +#define SYS_freebsd14_setgroups 80 #define SYS_getpgrp 81 #define SYS_setpgid 82 #define SYS_setitimer 83 @@ -442,7 +444,7 @@ #define SYS_symlinkat 502 #define SYS_unlinkat 503 #define SYS_posix_openpt 504 -#define SYS_gssd_syscall 505 + /* 505 is obsolete kgssapi */ #define SYS_jail_get 506 #define SYS_jail_set 507 #define SYS_jail_remove 508 @@ -526,4 +528,13 @@ #define SYS_timerfd_settime 587 #define SYS_kcmp 588 #define SYS_getrlimitusage 589 -#define SYS_MAXSYSCALL 590 \ No newline at end of file +#define SYS_fchroot 590 +#define SYS_setcred 591 +#define SYS_exterrctl 592 +#define SYS_inotify_add_watch_at 593 +#define SYS_inotify_rm_watch 594 +#define SYS_getgroups 595 +#define SYS_setgroups 596 +#define SYS_jail_attach_jd 597 +#define SYS_jail_remove_jd 598 +#define SYS_MAXSYSCALL 599 \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/syscallsubr.h b/lib/libc/include/generic-freebsd/sys/syscallsubr.h index 219a3a8eb819..ebd4cb5618c5 100644 --- a/lib/libc/include/generic-freebsd/sys/syscallsubr.h +++ b/lib/libc/include/generic-freebsd/sys/syscallsubr.h @@ -28,13 +28,14 @@ #ifndef _SYS_SYSCALLSUBR_H_ #define _SYS_SYSCALLSUBR_H_ -#include -#include -#include -#include +#include #include #include #include +#include +#include +#include +#include struct __wrusage; struct cpuset_copy_cb; @@ -49,6 +50,7 @@ struct kevent_copyops; struct kld_file_stat; struct ksiginfo; struct mbuf; +struct mq_attr; struct msghdr; struct msqid_ds; struct pollfd; @@ -58,6 +60,7 @@ struct rusage; struct sched_param; struct sembuf; union semun; +struct shmfd; struct sockaddr; struct spacectl_range; struct stat; @@ -84,10 +87,10 @@ int kern___getcwd(struct thread *td, char *buf, enum uio_seg bufseg, size_t buflen, size_t path_max); int kern_abort2(struct thread *td, const char *why, int nargs, void **uargs); -int kern_accept(struct thread *td, int s, struct sockaddr **name, - socklen_t *namelen, struct file **fp); -int kern_accept4(struct thread *td, int s, struct sockaddr **name, - socklen_t *namelen, int flags, struct file **fp); +int kern_accept(struct thread *td, int s, struct sockaddr *sa, + struct file **fp); +int kern_accept4(struct thread *td, int s, struct sockaddr *sa, + int flags, struct file **fp); int kern_accessat(struct thread *td, int fd, const char *path, enum uio_seg pathseg, int flags, int mode); int kern_adjtime(struct thread *td, struct timeval *delta, @@ -164,7 +167,7 @@ int kern_fchmodat(struct thread *td, int fd, const char *path, int kern_fchownat(struct thread *td, int fd, const char *path, enum uio_seg pathseg, int uid, int gid, int flag); int kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg); -int kern_fcntl_freebsd(struct thread *td, int fd, int cmd, long arg); +int kern_fcntl_freebsd(struct thread *td, int fd, int cmd, intptr_t arg); int kern_fhopen(struct thread *td, const struct fhandle *u_fhp, int flags); int kern_fhstat(struct thread *td, fhandle_t fh, struct stat *buf); int kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf); @@ -187,13 +190,11 @@ int kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize, size_t *countp, enum uio_seg bufseg, int mode); int kern_getitimer(struct thread *, u_int, struct itimerval *); int kern_getppid(struct thread *); -int kern_getpeername(struct thread *td, int fd, struct sockaddr **sa, - socklen_t *alen); +int kern_getpeername(struct thread *td, int fd, struct sockaddr *sa); int kern_getpriority(struct thread *td, int which, int who); int kern_getrusage(struct thread *td, int who, struct rusage *rup); int kern_getsid(struct thread *td, pid_t pid); -int kern_getsockname(struct thread *td, int fd, struct sockaddr **sa, - socklen_t *alen); +int kern_getsockname(struct thread *td, int fd, struct sockaddr *sa); int kern_getsockopt(struct thread *td, int s, int level, int name, void *optval, enum uio_seg valseg, socklen_t *valsize); int kern_ioctl(struct thread *td, int fd, u_long com, caddr_t data); @@ -214,6 +215,15 @@ int kern_kqueue(struct thread *td, int flags, struct filecaps *fcaps); int kern_kldload(struct thread *td, const char *file, int *fileid); int kern_kldstat(struct thread *td, int fileid, struct kld_file_stat *stat); int kern_kldunload(struct thread *td, int fileid, int flags); +int kern_kmq_notify(struct thread *, int, struct sigevent *); +int kern_kmq_open(struct thread *, const char *, int, mode_t, + const struct mq_attr *); +int kern_kmq_setattr(struct thread *, int, const struct mq_attr *, + struct mq_attr *); +int kern_kmq_timedreceive(struct thread *, int, char *, + size_t, unsigned int *, const struct timespec *); +int kern_kmq_timedsend(struct thread *td, int, const char *, + size_t, unsigned int, const struct timespec *); int kern_linkat(struct thread *td, int fd1, int fd2, const char *path1, const char *path2, enum uio_seg segflg, int flag); int kern_listen(struct thread *td, int s, int backlog); @@ -248,6 +258,7 @@ int kern_munlock(struct thread *td, uintptr_t addr, size_t size); int kern_munmap(struct thread *td, uintptr_t addr, size_t size); int kern_nanosleep(struct thread *td, struct timespec *rqt, struct timespec *rmt); +int kern_nosys(struct thread *td, int dummy); int kern_ntp_adjtime(struct thread *td, struct timex *ntv, int *retvalp); int kern_ogetdirentries(struct thread *td, struct ogetdirentries_args *uap, long *ploff); @@ -312,7 +323,9 @@ int kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou, fd_set *fd_ex, struct timeval *tvp, int abi_nfdbits); int kern_sendit(struct thread *td, int s, struct msghdr *mp, int flags, struct mbuf *control, enum uio_seg segflg); -int kern_setgroups(struct thread *td, u_int ngrp, gid_t *groups); +int kern_setcred(struct thread *const td, const u_int flags, + struct setcred *const wcred, gid_t *preallocated_groups); +int kern_setgroups(struct thread *td, int *ngrpp, gid_t *groups); int kern_setitimer(struct thread *, u_int, struct itimerval *, struct itimerval *); int kern_setpriority(struct thread *td, int which, int who, int prio); @@ -325,7 +338,7 @@ int kern_shm_open(struct thread *td, const char *userpath, int flags, mode_t mode, struct filecaps *fcaps); int kern_shm_open2(struct thread *td, const char *path, int flags, mode_t mode, int shmflags, struct filecaps *fcaps, - const char *name); + const char *name, struct shmfd *shmfd); int kern_shmat(struct thread *td, int shmid, const void *shmaddr, int shmflg); int kern_shmctl(struct thread *td, int shmid, int cmd, void *buf, diff --git a/lib/libc/include/generic-freebsd/sys/sysctl.h b/lib/libc/include/generic-freebsd/sys/sysctl.h index 6550ca063046..059a0998606d 100644 --- a/lib/libc/include/generic-freebsd/sys/sysctl.h +++ b/lib/libc/include/generic-freebsd/sys/sysctl.h @@ -30,14 +30,13 @@ * 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. - * - * @(#)sysctl.h 8.1 (Berkeley) 6/2/93 */ #ifndef _SYS_SYSCTL_H_ #define _SYS_SYSCTL_H_ #ifdef _KERNEL +#include #include #include #endif @@ -866,7 +865,7 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry); /* OID expressing a sbintime_t as microseconds */ #define SYSCTL_SBINTIME_USEC(parent, nbr, name, access, ptr, descr) \ SYSCTL_OID(parent, nbr, name, \ - CTLTYPE_INT | CTLFLAG_MPSAFE | CTLFLAG_RD | (access), \ + CTLTYPE_S64 | CTLFLAG_MPSAFE | CTLFLAG_RD | (access), \ (ptr), 0, sysctl_usec_to_sbintime, "Q", descr); \ CTASSERT(((access) & CTLTYPE) == 0 || \ ((access) & SYSCTL_CT_ASSERT_MASK) == CTLTYPE_S64) @@ -876,7 +875,7 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry); CTASSERT(((access) & CTLTYPE) == 0 || \ ((access) & SYSCTL_CT_ASSERT_MASK) == CTLTYPE_S64); \ sysctl_add_oid(ctx, parent, nbr, name, \ - CTLTYPE_INT | CTLFLAG_MPSAFE | CTLFLAG_RD | (access), \ + CTLTYPE_S64 | CTLFLAG_MPSAFE | CTLFLAG_RD | (access), \ __ptr, 0, sysctl_usec_to_sbintime, "Q", __DESCR(descr), \ NULL); \ }) @@ -884,7 +883,7 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry); /* OID expressing a sbintime_t as milliseconds */ #define SYSCTL_SBINTIME_MSEC(parent, nbr, name, access, ptr, descr) \ SYSCTL_OID(parent, nbr, name, \ - CTLTYPE_INT | CTLFLAG_MPSAFE | CTLFLAG_RD | (access), \ + CTLTYPE_S64 | CTLFLAG_MPSAFE | CTLFLAG_RD | (access), \ (ptr), 0, sysctl_msec_to_sbintime, "Q", descr); \ CTASSERT(((access) & CTLTYPE) == 0 || \ ((access) & SYSCTL_CT_ASSERT_MASK) == CTLTYPE_S64) @@ -894,7 +893,7 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry); CTASSERT(((access) & CTLTYPE) == 0 || \ ((access) & SYSCTL_CT_ASSERT_MASK) == CTLTYPE_S64); \ sysctl_add_oid(ctx, parent, nbr, name, \ - CTLTYPE_INT | CTLFLAG_MPSAFE | CTLFLAG_RD | (access), \ + CTLTYPE_S64 | CTLFLAG_MPSAFE | CTLFLAG_RD | (access), \ __ptr, 0, sysctl_msec_to_sbintime, "Q", __DESCR(descr), \ NULL); \ }) @@ -934,6 +933,26 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry); CTLFLAG_RD | CTLFLAG_CAPRD | CTLTYPE_INT | CTLFLAG_MPSAFE, \ NULL, 1, sysctl_handle_int, "I", desc, "feature"); +/* + * Adding new leaves to the 'debug.sizeof' MIB tree for ad-hoc reasons is + * discouraged, and in particular for reporting to developers the size of some + * kernel structures, which can be obtained by the following alternative means: + * 1. In GDB, load a full kernel image and use 'print(sizeof(struct XXX))'. + * Alternatively, use 'ptype/o struct XXX' to additionally get the offsets + * and size of all structure's fields. + * 2. If the structure is allocated from UMA, then 'vmstat -z' reports its size + * (the mapping between structure types and zones is usually + * straightforward). + */ +/* Generates a read-only sysctl reporting the size of an object/structure. */ +#define SYSCTL_SIZEOF(name, expr) \ + SYSCTL_INT(_debug_sizeof, OID_AUTO, name, CTLFLAG_RD, \ + SYSCTL_NULL_INT_PTR, sizeof(expr), \ + "sizeof(" __STRING(expr) ")"); +/* Same, specialized for structures. */ +#define SYSCTL_SIZEOF_STRUCT(struct_name) \ + SYSCTL_SIZEOF(struct_name, struct struct_name) + #endif /* _KERNEL */ /* @@ -1043,6 +1062,7 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry); #define KERN_PROC_SIGFASTBLK 44 /* address of fastsigblk magic word */ #define KERN_PROC_VM_LAYOUT 45 /* virtual address space layout info */ #define KERN_PROC_RLIMIT_USAGE 46 /* array of rlim_t */ +#define KERN_PROC_KQUEUE 47 /* array of struct kinfo_knote */ /* * KERN_IPC identifiers diff --git a/lib/libc/include/generic-freebsd/sys/sysent.h b/lib/libc/include/generic-freebsd/sys/sysent.h index 537130a46233..24a5b17dbca5 100644 --- a/lib/libc/include/generic-freebsd/sys/sysent.h +++ b/lib/libc/include/generic-freebsd/sys/sysent.h @@ -79,11 +79,10 @@ struct sysent { /* system call table */ */ #define SYF_CAPENABLED 0x00000001 -#define SY_THR_FLAGMASK 0x7 -#define SY_THR_STATIC 0x1 -#define SY_THR_DRAINING 0x2 -#define SY_THR_ABSENT 0x4 -#define SY_THR_INCR 0x8 +#define SY_THR_STATIC 0x01 +#define SY_THR_DRAINING 0x02 +#define SY_THR_ABSENT 0x04 +#define SY_THR_INCR 0x08 #ifdef KLD_MODULE #define SY_THR_STATIC_KLD 0 @@ -91,6 +90,7 @@ struct sysent { /* system call table */ #define SY_THR_STATIC_KLD SY_THR_STATIC #endif +struct coredump_writer; struct image_params; struct proc; struct __sigset; @@ -109,7 +109,8 @@ struct sysentvec { int *sv_szsigcode; /* size of sigtramp code */ int sv_sigcodeoff; char *sv_name; /* name of binary type */ - int (*sv_coredump)(struct thread *, struct vnode *, off_t, int); + int (*sv_coredump)(struct thread *, struct coredump_writer *, + off_t, int); /* function to dump core, or NULL */ int sv_elf_core_osabi; const char *sv_elf_core_abi_vendor; @@ -145,10 +146,13 @@ struct sysentvec { int (*sv_trap)(struct thread *); u_long *sv_hwcap; /* Value passed in AT_HWCAP. */ u_long *sv_hwcap2; /* Value passed in AT_HWCAP2. */ + u_long *sv_hwcap3; /* Value passed in AT_HWCAP3. */ + u_long *sv_hwcap4; /* Value passed in AT_HWCAP4. */ const char *(*sv_machine_arch)(struct proc *); vm_offset_t sv_fxrng_gen_offset; void (*sv_onexec_old)(struct thread *td); int (*sv_onexec)(struct proc *, struct image_params *); + void (*sv_protect)(struct image_params *, int); void (*sv_onexit)(struct proc *); void (*sv_ontdexit)(struct thread *td); int (*sv_setid_allowed)(struct thread *td, @@ -161,7 +165,7 @@ struct sysentvec { #define SV_ILP32 0x000100 /* 32-bit executable. */ #define SV_LP64 0x000200 /* 64-bit executable. */ -#define SV_IA32 0x004000 /* Intel 32-bit executable. */ +#define SV_RESERVED0 0x004000 /* Formerly SV_IA32 */ #define SV_AOUT 0x008000 /* a.out executable. */ #define SV_SHP 0x010000 /* Shared page. */ #define SV_SIGSYS 0x020000 /* SIGSYS for non-existing syscall */ @@ -187,6 +191,10 @@ struct sysentvec { #define SVC_NOCOMPRESS 0x00000002 /* disable compression. */ #define SVC_ALL 0x00000004 /* dump everything */ +/* sv_protect flags */ +#define SVP_IMAGE 0x00000001 +#define SVP_INTERP 0x00000002 + #ifdef _KERNEL extern struct sysentvec aout_sysvec; extern struct sysent sysent[]; diff --git a/lib/libc/include/generic-freebsd/sys/syslimits.h b/lib/libc/include/generic-freebsd/sys/syslimits.h index 3d06dc0b294d..546c143f5040 100644 --- a/lib/libc/include/generic-freebsd/sys/syslimits.h +++ b/lib/libc/include/generic-freebsd/sys/syslimits.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)syslimits.h 8.1 (Berkeley) 6/2/93 */ #ifndef _SYS_SYSLIMITS_H_ diff --git a/lib/libc/include/generic-freebsd/sys/syslog.h b/lib/libc/include/generic-freebsd/sys/syslog.h index b6528a384113..3c822d795d52 100644 --- a/lib/libc/include/generic-freebsd/sys/syslog.h +++ b/lib/libc/include/generic-freebsd/sys/syslog.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)syslog.h 8.1 (Berkeley) 6/2/93 */ #ifndef _SYS_SYSLOG_H_ diff --git a/lib/libc/include/generic-freebsd/sys/sysproto.h b/lib/libc/include/generic-freebsd/sys/sysproto.h index 69f63c8daeb7..0672feb70d10 100644 --- a/lib/libc/include/generic-freebsd/sys/sysproto.h +++ b/lib/libc/include/generic-freebsd/sys/sysproto.h @@ -7,8 +7,8 @@ #ifndef _SYS_SYSPROTO_H_ #define _SYS_SYSPROTO_H_ +#include #include -#include #include #include #include @@ -33,7 +33,7 @@ struct thread; #define PADR_(t) 0 #endif -struct exit_args { +struct _exit_args { char rval_l_[PADL_(int)]; int rval; char rval_r_[PADR_(int)]; }; struct fork_args { @@ -254,12 +254,6 @@ struct msync_args { struct vfork_args { syscallarg_t dummy; }; -struct sbrk_args { - char incr_l_[PADL_(int)]; int incr; char incr_r_[PADR_(int)]; -}; -struct sstk_args { - char incr_l_[PADL_(int)]; int incr; char incr_r_[PADR_(int)]; -}; struct munmap_args { char addr_l_[PADL_(void *)]; void * addr; char addr_r_[PADR_(void *)]; char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)]; @@ -279,14 +273,6 @@ struct mincore_args { char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)]; char vec_l_[PADL_(char *)]; char * vec; char vec_r_[PADR_(char *)]; }; -struct getgroups_args { - char gidsetsize_l_[PADL_(int)]; int gidsetsize; char gidsetsize_r_[PADR_(int)]; - char gidset_l_[PADL_(gid_t *)]; gid_t * gidset; char gidset_r_[PADR_(gid_t *)]; -}; -struct setgroups_args { - char gidsetsize_l_[PADL_(int)]; int gidsetsize; char gidsetsize_r_[PADR_(int)]; - char gidset_l_[PADL_(const gid_t *)]; const gid_t * gidset; char gidset_r_[PADR_(const gid_t *)]; -}; struct getpgrp_args { syscallarg_t dummy; }; @@ -319,7 +305,7 @@ struct dup2_args { struct fcntl_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)]; - char arg_l_[PADL_(long)]; long arg; char arg_r_[PADR_(long)]; + char arg_l_[PADL_(intptr_t)]; intptr_t arg; char arg_r_[PADR_(intptr_t)]; }; struct select_args { char nd_l_[PADL_(int)]; int nd; char nd_r_[PADR_(int)]; @@ -383,12 +369,12 @@ struct getsockopt_args { }; struct readv_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; - char iovp_l_[PADL_(struct iovec *)]; struct iovec * iovp; char iovp_r_[PADR_(struct iovec *)]; + char iovp_l_[PADL_(const struct iovec *)]; const struct iovec * iovp; char iovp_r_[PADR_(const struct iovec *)]; char iovcnt_l_[PADL_(u_int)]; u_int iovcnt; char iovcnt_r_[PADR_(u_int)]; }; struct writev_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; - char iovp_l_[PADL_(struct iovec *)]; struct iovec * iovp; char iovp_r_[PADR_(struct iovec *)]; + char iovp_l_[PADL_(const struct iovec *)]; const struct iovec * iovp; char iovp_r_[PADR_(const struct iovec *)]; char iovcnt_l_[PADL_(u_int)]; u_int iovcnt; char iovcnt_r_[PADR_(u_int)]; }; struct settimeofday_args { @@ -552,7 +538,7 @@ struct setrlimit_args { char rlp_l_[PADL_(struct rlimit *)]; struct rlimit * rlp; char rlp_r_[PADR_(struct rlimit *)]; }; struct __sysctl_args { - char name_l_[PADL_(int *)]; int * name; char name_r_[PADR_(int *)]; + char name_l_[PADL_(const int *)]; const int * name; char name_r_[PADR_(const int *)]; char namelen_l_[PADL_(u_int)]; u_int namelen; char namelen_r_[PADR_(u_int)]; char old_l_[PADL_(void *)]; void * old; char old_r_[PADR_(void *)]; char oldlenp_l_[PADL_(size_t *)]; size_t * oldlenp; char oldlenp_r_[PADR_(size_t *)]; @@ -783,7 +769,7 @@ struct aio_return_args { char aiocbp_l_[PADL_(struct aiocb *)]; struct aiocb * aiocbp; char aiocbp_r_[PADR_(struct aiocb *)]; }; struct aio_suspend_args { - char aiocbp_l_[PADL_(struct aiocb * const *)]; struct aiocb * const * aiocbp; char aiocbp_r_[PADR_(struct aiocb * const *)]; + char aiocbp_l_[PADL_(const struct aiocb * const *)]; const struct aiocb * const * aiocbp; char aiocbp_r_[PADR_(const struct aiocb * const *)]; char nent_l_[PADL_(int)]; int nent; char nent_r_[PADR_(int)]; char timeout_l_[PADL_(const struct timespec *)]; const struct timespec * timeout; char timeout_r_[PADR_(const struct timespec *)]; }; @@ -868,49 +854,49 @@ struct sigpending_args { }; struct sigtimedwait_args { char set_l_[PADL_(const sigset_t *)]; const sigset_t * set; char set_r_[PADR_(const sigset_t *)]; - char info_l_[PADL_(struct siginfo *)]; struct siginfo * info; char info_r_[PADR_(struct siginfo *)]; + char info_l_[PADL_(struct __siginfo *)]; struct __siginfo * info; char info_r_[PADR_(struct __siginfo *)]; char timeout_l_[PADL_(const struct timespec *)]; const struct timespec * timeout; char timeout_r_[PADR_(const struct timespec *)]; }; struct sigwaitinfo_args { char set_l_[PADL_(const sigset_t *)]; const sigset_t * set; char set_r_[PADR_(const sigset_t *)]; - char info_l_[PADL_(struct siginfo *)]; struct siginfo * info; char info_r_[PADR_(struct siginfo *)]; + char info_l_[PADL_(struct __siginfo *)]; struct __siginfo * info; char info_r_[PADR_(struct __siginfo *)]; }; struct __acl_get_file_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; - char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; + char type_l_[PADL_(__acl_type_t)]; __acl_type_t type; char type_r_[PADR_(__acl_type_t)]; char aclp_l_[PADL_(struct acl *)]; struct acl * aclp; char aclp_r_[PADR_(struct acl *)]; }; struct __acl_set_file_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; - char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; + char type_l_[PADL_(__acl_type_t)]; __acl_type_t type; char type_r_[PADR_(__acl_type_t)]; char aclp_l_[PADL_(struct acl *)]; struct acl * aclp; char aclp_r_[PADR_(struct acl *)]; }; struct __acl_get_fd_args { char filedes_l_[PADL_(int)]; int filedes; char filedes_r_[PADR_(int)]; - char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; + char type_l_[PADL_(__acl_type_t)]; __acl_type_t type; char type_r_[PADR_(__acl_type_t)]; char aclp_l_[PADL_(struct acl *)]; struct acl * aclp; char aclp_r_[PADR_(struct acl *)]; }; struct __acl_set_fd_args { char filedes_l_[PADL_(int)]; int filedes; char filedes_r_[PADR_(int)]; - char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; + char type_l_[PADL_(__acl_type_t)]; __acl_type_t type; char type_r_[PADR_(__acl_type_t)]; char aclp_l_[PADL_(struct acl *)]; struct acl * aclp; char aclp_r_[PADR_(struct acl *)]; }; struct __acl_delete_file_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; - char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; + char type_l_[PADL_(__acl_type_t)]; __acl_type_t type; char type_r_[PADR_(__acl_type_t)]; }; struct __acl_delete_fd_args { char filedes_l_[PADL_(int)]; int filedes; char filedes_r_[PADR_(int)]; - char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; + char type_l_[PADL_(__acl_type_t)]; __acl_type_t type; char type_r_[PADR_(__acl_type_t)]; }; struct __acl_aclcheck_file_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; - char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; + char type_l_[PADL_(__acl_type_t)]; __acl_type_t type; char type_r_[PADR_(__acl_type_t)]; char aclp_l_[PADL_(struct acl *)]; struct acl * aclp; char aclp_r_[PADR_(struct acl *)]; }; struct __acl_aclcheck_fd_args { char filedes_l_[PADL_(int)]; int filedes; char filedes_r_[PADR_(int)]; - char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; + char type_l_[PADL_(__acl_type_t)]; __acl_type_t type; char type_r_[PADR_(__acl_type_t)]; char aclp_l_[PADL_(struct acl *)]; struct acl * aclp; char aclp_r_[PADR_(struct acl *)]; }; struct extattrctl_args { @@ -1136,21 +1122,21 @@ struct swapcontext_args { }; struct __acl_get_link_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; - char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; + char type_l_[PADL_(__acl_type_t)]; __acl_type_t type; char type_r_[PADR_(__acl_type_t)]; char aclp_l_[PADL_(struct acl *)]; struct acl * aclp; char aclp_r_[PADR_(struct acl *)]; }; struct __acl_set_link_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; - char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; + char type_l_[PADL_(__acl_type_t)]; __acl_type_t type; char type_r_[PADR_(__acl_type_t)]; char aclp_l_[PADL_(struct acl *)]; struct acl * aclp; char aclp_r_[PADR_(struct acl *)]; }; struct __acl_delete_link_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; - char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; + char type_l_[PADL_(__acl_type_t)]; __acl_type_t type; char type_r_[PADR_(__acl_type_t)]; }; struct __acl_aclcheck_link_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; - char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; + char type_l_[PADL_(__acl_type_t)]; __acl_type_t type; char type_r_[PADR_(__acl_type_t)]; char aclp_l_[PADL_(struct acl *)]; struct acl * aclp; char aclp_r_[PADR_(struct acl *)]; }; struct sigwait_args { @@ -1482,9 +1468,6 @@ struct unlinkat_args { struct posix_openpt_args { char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; -struct gssd_syscall_args { - char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; -}; struct jail_get_args { char iovp_l_[PADL_(struct iovec *)]; struct iovec * iovp; char iovp_r_[PADR_(struct iovec *)]; char iovcnt_l_[PADL_(unsigned int)]; unsigned int iovcnt; char iovcnt_r_[PADR_(unsigned int)]; @@ -1603,7 +1586,7 @@ struct wait6_args { char status_l_[PADL_(int *)]; int * status; char status_r_[PADR_(int *)]; char options_l_[PADL_(int)]; int options; char options_r_[PADR_(int)]; char wrusage_l_[PADL_(struct __wrusage *)]; struct __wrusage * wrusage; char wrusage_r_[PADR_(struct __wrusage *)]; - char info_l_[PADL_(struct siginfo *)]; struct siginfo * info; char info_r_[PADR_(struct siginfo *)]; + char info_l_[PADL_(struct __siginfo *)]; struct __siginfo * info; char info_r_[PADR_(struct __siginfo *)]; }; struct cap_rights_limit_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; @@ -1811,7 +1794,7 @@ struct shm_rename_args { }; struct sigfastblock_args { char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)]; - char ptr_l_[PADL_(uint32_t *)]; uint32_t * ptr; char ptr_r_[PADR_(uint32_t *)]; + char ptr_l_[PADL_(void *)]; void * ptr; char ptr_r_[PADR_(void *)]; }; struct __realpathat_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; @@ -1826,8 +1809,7 @@ struct close_range_args { char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct rpctls_syscall_args { - char op_l_[PADL_(int)]; int op; char op_r_[PADR_(int)]; - char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char socookie_l_[PADL_(uint64_t)]; uint64_t socookie; char socookie_r_[PADR_(uint64_t)]; }; struct __specialfd_args { char type_l_[PADL_(int)]; int type; char type_r_[PADR_(int)]; @@ -1888,7 +1870,44 @@ struct getrlimitusage_args { char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; char res_l_[PADL_(rlim_t *)]; rlim_t * res; char res_r_[PADR_(rlim_t *)]; }; -int sys_exit(struct thread *, struct exit_args *); +struct fchroot_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; +}; +struct setcred_args { + char flags_l_[PADL_(u_int)]; u_int flags; char flags_r_[PADR_(u_int)]; + char wcred_l_[PADL_(const struct setcred *)]; const struct setcred * wcred; char wcred_r_[PADR_(const struct setcred *)]; + char size_l_[PADL_(size_t)]; size_t size; char size_r_[PADR_(size_t)]; +}; +struct exterrctl_args { + char op_l_[PADL_(u_int)]; u_int op; char op_r_[PADR_(u_int)]; + char flags_l_[PADL_(u_int)]; u_int flags; char flags_r_[PADR_(u_int)]; + char ptr_l_[PADL_(void *)]; void * ptr; char ptr_r_[PADR_(void *)]; +}; +struct inotify_add_watch_at_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char dfd_l_[PADL_(int)]; int dfd; char dfd_r_[PADR_(int)]; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char mask_l_[PADL_(uint32_t)]; uint32_t mask; char mask_r_[PADR_(uint32_t)]; +}; +struct inotify_rm_watch_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char wd_l_[PADL_(int)]; int wd; char wd_r_[PADR_(int)]; +}; +struct getgroups_args { + char gidsetsize_l_[PADL_(int)]; int gidsetsize; char gidsetsize_r_[PADR_(int)]; + char gidset_l_[PADL_(gid_t *)]; gid_t * gidset; char gidset_r_[PADR_(gid_t *)]; +}; +struct setgroups_args { + char gidsetsize_l_[PADL_(int)]; int gidsetsize; char gidsetsize_r_[PADR_(int)]; + char gidset_l_[PADL_(const gid_t *)]; const gid_t * gidset; char gidset_r_[PADR_(const gid_t *)]; +}; +struct jail_attach_jd_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; +}; +struct jail_remove_jd_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; +}; +int sys__exit(struct thread *, struct _exit_args *); int sys_fork(struct thread *, struct fork_args *); int sys_read(struct thread *, struct read_args *); int sys_write(struct thread *, struct write_args *); @@ -1940,14 +1959,10 @@ int sys_umask(struct thread *, struct umask_args *); int sys_chroot(struct thread *, struct chroot_args *); int sys_msync(struct thread *, struct msync_args *); int sys_vfork(struct thread *, struct vfork_args *); -int sys_sbrk(struct thread *, struct sbrk_args *); -int sys_sstk(struct thread *, struct sstk_args *); int sys_munmap(struct thread *, struct munmap_args *); int sys_mprotect(struct thread *, struct mprotect_args *); int sys_madvise(struct thread *, struct madvise_args *); int sys_mincore(struct thread *, struct mincore_args *); -int sys_getgroups(struct thread *, struct getgroups_args *); -int sys_setgroups(struct thread *, struct setgroups_args *); int sys_getpgrp(struct thread *, struct getpgrp_args *); int sys_setpgid(struct thread *, struct setpgid_args *); int sys_setitimer(struct thread *, struct setitimer_args *); @@ -2210,7 +2225,6 @@ int sys_renameat(struct thread *, struct renameat_args *); int sys_symlinkat(struct thread *, struct symlinkat_args *); int sys_unlinkat(struct thread *, struct unlinkat_args *); int sys_posix_openpt(struct thread *, struct posix_openpt_args *); -int sys_gssd_syscall(struct thread *, struct gssd_syscall_args *); int sys_jail_get(struct thread *, struct jail_get_args *); int sys_jail_set(struct thread *, struct jail_set_args *); int sys_jail_remove(struct thread *, struct jail_remove_args *); @@ -2290,6 +2304,15 @@ int sys_timerfd_gettime(struct thread *, struct timerfd_gettime_args *); int sys_timerfd_settime(struct thread *, struct timerfd_settime_args *); int sys_kcmp(struct thread *, struct kcmp_args *); int sys_getrlimitusage(struct thread *, struct getrlimitusage_args *); +int sys_fchroot(struct thread *, struct fchroot_args *); +int sys_setcred(struct thread *, struct setcred_args *); +int sys_exterrctl(struct thread *, struct exterrctl_args *); +int sys_inotify_add_watch_at(struct thread *, struct inotify_add_watch_at_args *); +int sys_inotify_rm_watch(struct thread *, struct inotify_rm_watch_args *); +int sys_getgroups(struct thread *, struct getgroups_args *); +int sys_setgroups(struct thread *, struct setgroups_args *); +int sys_jail_attach_jd(struct thread *, struct jail_attach_jd_args *); +int sys_jail_remove_jd(struct thread *, struct jail_remove_jd_args *); #ifdef COMPAT_43 @@ -2781,7 +2804,23 @@ int freebsd13_swapoff(struct thread *, struct freebsd13_swapoff_args *); #endif /* COMPAT_FREEBSD13 */ -#define SYS_AUE_exit AUE_EXIT + +#ifdef COMPAT_FREEBSD14 + +struct freebsd14_getgroups_args { + char gidsetsize_l_[PADL_(int)]; int gidsetsize; char gidsetsize_r_[PADR_(int)]; + char gidset_l_[PADL_(gid_t *)]; gid_t * gidset; char gidset_r_[PADR_(gid_t *)]; +}; +struct freebsd14_setgroups_args { + char gidsetsize_l_[PADL_(int)]; int gidsetsize; char gidsetsize_r_[PADR_(int)]; + char gidset_l_[PADL_(const gid_t *)]; const gid_t * gidset; char gidset_r_[PADR_(const gid_t *)]; +}; +int freebsd14_getgroups(struct thread *, struct freebsd14_getgroups_args *); +int freebsd14_setgroups(struct thread *, struct freebsd14_setgroups_args *); + +#endif /* COMPAT_FREEBSD14 */ + +#define SYS_AUE__exit AUE_EXIT #define SYS_AUE_fork AUE_FORK #define SYS_AUE_read AUE_READ #define SYS_AUE_write AUE_WRITE @@ -2846,16 +2885,14 @@ int freebsd13_swapoff(struct thread *, struct freebsd13_swapoff_args *); #define SYS_AUE_ogetpagesize AUE_NULL #define SYS_AUE_msync AUE_MSYNC #define SYS_AUE_vfork AUE_VFORK -#define SYS_AUE_sbrk AUE_SBRK -#define SYS_AUE_sstk AUE_SSTK #define SYS_AUE_ommap AUE_MMAP #define SYS_AUE_freebsd11_vadvise AUE_O_VADVISE #define SYS_AUE_munmap AUE_MUNMAP #define SYS_AUE_mprotect AUE_MPROTECT #define SYS_AUE_madvise AUE_MADVISE #define SYS_AUE_mincore AUE_MINCORE -#define SYS_AUE_getgroups AUE_GETGROUPS -#define SYS_AUE_setgroups AUE_SETGROUPS +#define SYS_AUE_freebsd14_getgroups AUE_GETGROUPS +#define SYS_AUE_freebsd14_setgroups AUE_SETGROUPS #define SYS_AUE_getpgrp AUE_GETPGRP #define SYS_AUE_setpgid AUE_SETPGRP #define SYS_AUE_setitimer AUE_SETITIMER @@ -3185,7 +3222,6 @@ int freebsd13_swapoff(struct thread *, struct freebsd13_swapoff_args *); #define SYS_AUE_symlinkat AUE_SYMLINKAT #define SYS_AUE_unlinkat AUE_UNLINKAT #define SYS_AUE_posix_openpt AUE_POSIX_OPENPT -#define SYS_AUE_gssd_syscall AUE_NULL #define SYS_AUE_jail_get AUE_JAIL_GET #define SYS_AUE_jail_set AUE_JAIL_SET #define SYS_AUE_jail_remove AUE_JAIL_REMOVE @@ -3266,6 +3302,15 @@ int freebsd13_swapoff(struct thread *, struct freebsd13_swapoff_args *); #define SYS_AUE_timerfd_settime AUE_TIMERFD #define SYS_AUE_kcmp AUE_NULL #define SYS_AUE_getrlimitusage AUE_NULL +#define SYS_AUE_fchroot AUE_NULL +#define SYS_AUE_setcred AUE_SETCRED +#define SYS_AUE_exterrctl AUE_NULL +#define SYS_AUE_inotify_add_watch_at AUE_INOTIFY +#define SYS_AUE_inotify_rm_watch AUE_INOTIFY +#define SYS_AUE_getgroups AUE_GETGROUPS +#define SYS_AUE_setgroups AUE_SETGROUPS +#define SYS_AUE_jail_attach_jd AUE_JAIL_ATTACH +#define SYS_AUE_jail_remove_jd AUE_JAIL_REMOVE #undef PAD_ #undef PADL_ diff --git a/lib/libc/include/generic-freebsd/sys/systm.h b/lib/libc/include/generic-freebsd/sys/systm.h index 354a239efc4b..0ac452fc13db 100644 --- a/lib/libc/include/generic-freebsd/sys/systm.h +++ b/lib/libc/include/generic-freebsd/sys/systm.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)systm.h 8.7 (Berkeley) 3/29/95 */ #ifndef _SYS_SYSTM_H_ @@ -81,7 +79,7 @@ extern u_long maxphys; /* max raw I/O transfer size */ */ enum VM_GUEST { VM_GUEST_NO = 0, VM_GUEST_VM, VM_GUEST_XEN, VM_GUEST_HV, VM_GUEST_VMWARE, VM_GUEST_KVM, VM_GUEST_BHYVE, VM_GUEST_VBOX, - VM_GUEST_PARALLELS, VM_GUEST_NVMM, VM_LAST }; + VM_GUEST_PARALLELS, VM_GUEST_NVMM, VM_GUEST_LAST }; #endif /* KERNEL */ @@ -101,17 +99,15 @@ struct ucred; #include /* curthread */ #include +extern bool scheduler_stopped; + /* * If we have already panic'd and this is the thread that called * panic(), then don't block on any mutexes but silently succeed. * Otherwise, the kernel will deadlock since the scheduler isn't * going to run the thread that holds any lock we need. */ -#define SCHEDULER_STOPPED_TD(td) ({ \ - MPASS((td) == curthread); \ - __predict_false((td)->td_stopsched); \ -}) -#define SCHEDULER_STOPPED() SCHEDULER_STOPPED_TD(curthread) +#define SCHEDULER_STOPPED() __predict_false(scheduler_stopped) extern const int osreldate; @@ -212,6 +208,16 @@ critical_exit(void) #ifdef EARLY_PRINTF typedef void early_putc_t(int ch); extern early_putc_t *early_putc; +#define CHECK_EARLY_PRINTF(x) \ + __CONCAT(early_printf_, EARLY_PRINTF) == __CONCAT(early_printf_, x) +#define early_printf_1 1 +#define early_printf_mvebu 2 +#define early_printf_ns8250 3 +#define early_printf_pl011 4 +#define early_printf_snps 5 +#define early_printf_sbi 6 +#else +#define CHECK_EARLY_PRINTF(x) 0 #endif int kvprintf(char const *, void (*)(int, void*), void *, int, __va_list) __printflike(1, 0); @@ -296,17 +302,18 @@ void *memmove_early(void * _Nonnull dest, const void * _Nonnull src, size_t n); ((__r >= __len) ? ENAMETOOLONG : 0); \ }) -int copyinstr(const void * __restrict udaddr, - void * _Nonnull __restrict kaddr, size_t len, - size_t * __restrict lencopied); -int copyin(const void * __restrict udaddr, - void * _Nonnull __restrict kaddr, size_t len); -int copyin_nofault(const void * __restrict udaddr, - void * _Nonnull __restrict kaddr, size_t len); -int copyout(const void * _Nonnull __restrict kaddr, - void * __restrict udaddr, size_t len); -int copyout_nofault(const void * _Nonnull __restrict kaddr, - void * __restrict udaddr, size_t len); +int __result_use_check copyinstr(const void * __restrict udaddr, + void * _Nonnull __restrict kaddr, size_t len, + size_t * __restrict lencopied); +int __result_use_check copyin(const void * __restrict udaddr, + void * _Nonnull __restrict kaddr, size_t len); +int __result_use_check copyin_nofault(const void * __restrict udaddr, + void * _Nonnull __restrict kaddr, size_t len); +__nodiscard int copyout(const void * _Nonnull __restrict kaddr, + void * __restrict udaddr, size_t len); +__nodiscard int copyout_nofault( + const void * _Nonnull __restrict kaddr, void * __restrict udaddr, + size_t len); #ifdef SAN_NEEDS_INTERCEPTORS int SAN_INTERCEPTOR(copyin)(const void *, void *, size_t); @@ -324,14 +331,14 @@ long fuword(volatile const void *base); int fuword16(volatile const void *base); int32_t fuword32(volatile const void *base); int64_t fuword64(volatile const void *base); -int fueword(volatile const void *base, long *val); -int fueword32(volatile const void *base, int32_t *val); -int fueword64(volatile const void *base, int64_t *val); -int subyte(volatile void *base, int byte); -int suword(volatile void *base, long word); -int suword16(volatile void *base, int word); -int suword32(volatile void *base, int32_t word); -int suword64(volatile void *base, int64_t word); +int __result_use_check fueword(volatile const void *base, long *val); +int __result_use_check fueword32(volatile const void *base, int32_t *val); +int __result_use_check fueword64(volatile const void *base, int64_t *val); +__nodiscard int subyte(volatile void *base, int byte); +__nodiscard int suword(volatile void *base, long word); +__nodiscard int suword16(volatile void *base, int word); +__nodiscard int suword32(volatile void *base, int32_t word); +__nodiscard int suword64(volatile void *base, int64_t word); uint32_t casuword32(volatile uint32_t *base, uint32_t oldval, uint32_t newval); u_long casuword(volatile u_long *p, u_long oldval, u_long newval); int casueword32(volatile uint32_t *base, uint32_t oldval, uint32_t *oldvalp, @@ -559,17 +566,32 @@ void counted_warning(unsigned *counter, const char *msg); /* * APIs to manage deprecation and obsolescence. */ -void _gone_in(int major, const char *msg); -void _gone_in_dev(device_t dev, int major, const char *msg); +void _gone_in(int major, const char *msg, ...) __printflike(2, 3); +void _gone_in_dev(device_t dev, int major, const char *msg, ...) + __printflike(3, 4); #ifdef NO_OBSOLETE_CODE #define __gone_ok(m, msg) \ _Static_assert(m < P_OSREL_MAJOR(__FreeBSD_version)), \ - "Obsolete code: " msg); + "Obsolete code: " msg) #else #define __gone_ok(m, msg) #endif -#define gone_in(major, msg) __gone_ok(major, msg) _gone_in(major, msg) -#define gone_in_dev(dev, major, msg) __gone_ok(major, msg) _gone_in_dev(dev, major, msg) +#define gone_in(major, msg, ...) do { \ + static bool __read_mostly __gone_in_ ## __LINE__ = true; \ + __gone_ok(major, msg); \ + if (__predict_false(__gone_in_ ## __LINE__)) { \ + __gone_in_ ## __LINE__ = false; \ + _gone_in(major, msg __VA_OPT__(,) __VA_ARGS__); \ + } \ +} while (0) +#define gone_in_dev(dev, major, msg, ...) do { \ + static bool __read_mostly __gone_in_ ## __LINE__ = true; \ + __gone_ok(major, msg); \ + if (__predict_false(__gone_in_ ## __LINE__)) { \ + __gone_in_ ## __LINE__ = false; \ + _gone_in_dev(dev, major, msg __VA_OPT__(,) __VA_ARGS__);\ + } \ +} while (0) #ifdef INVARIANTS #define __diagused diff --git a/lib/libc/include/generic-freebsd/sys/taskqueue.h b/lib/libc/include/generic-freebsd/sys/taskqueue.h index 3e755a538460..e578a1c71d5b 100644 --- a/lib/libc/include/generic-freebsd/sys/taskqueue.h +++ b/lib/libc/include/generic-freebsd/sys/taskqueue.h @@ -215,4 +215,10 @@ struct taskqueue *taskqueue_create_fast(const char *name, int mflags, taskqueue_enqueue_fn enqueue, void *context); +/* + * This queue is used to process asynchronous device events such as + * hot plug insertion and removal of devices. + */ +TASKQUEUE_DECLARE(bus); + #endif /* !_SYS_TASKQUEUE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/thr.h b/lib/libc/include/generic-freebsd/sys/thr.h index b72762846c90..bb754209994e 100644 --- a/lib/libc/include/generic-freebsd/sys/thr.h +++ b/lib/libc/include/generic-freebsd/sys/thr.h @@ -43,6 +43,7 @@ typedef __size_t size_t; #define THR_SUSPENDED 0x0001 /* Create the system scope thread. */ #define THR_SYSTEM_SCOPE 0x0002 +#define THR_C_RUNTIME 0x0004 struct thr_param { void (*start_func)(void *); /* thread entry function. */ diff --git a/lib/libc/include/generic-freebsd/sys/time.h b/lib/libc/include/generic-freebsd/sys/time.h index a8acb6886242..db2e17b0e33a 100644 --- a/lib/libc/include/generic-freebsd/sys/time.h +++ b/lib/libc/include/generic-freebsd/sys/time.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)time.h 8.5 (Berkeley) 5/4/95 */ #ifndef _SYS_TIME_H_ @@ -613,7 +611,9 @@ int tvtohz(struct timeval *tv); #include #include +#ifndef _STANDALONE #include +#endif __BEGIN_DECLS int setitimer(int, const struct itimerval *, struct itimerval *); diff --git a/lib/libc/include/generic-freebsd/sys/timeb.h b/lib/libc/include/generic-freebsd/sys/timeb.h index 53a6b23677c9..9cbe49dd12eb 100644 --- a/lib/libc/include/generic-freebsd/sys/timeb.h +++ b/lib/libc/include/generic-freebsd/sys/timeb.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)timeb.h 8.2 (Berkeley) 1/21/94 */ #ifndef _SYS_TIMEB_H_ diff --git a/lib/libc/include/generic-freebsd/sys/timeffc.h b/lib/libc/include/generic-freebsd/sys/timeffc.h index 42243cce639d..ed633138be27 100644 --- a/lib/libc/include/generic-freebsd/sys/timeffc.h +++ b/lib/libc/include/generic-freebsd/sys/timeffc.h @@ -89,7 +89,7 @@ extern int sysclock_active; * of the kernel tick timer (1/hz [s]). * FFCLOCK_LERP: Linear interpolation of ffclock time to guarantee * monotonic time. - * FFCLOCK_LEAPSEC: Include leap seconds. + * {FB|FF}CLOCK_LEAPSEC: Include leap seconds. * {FB|FF}CLOCK_UPTIME: Time stamp should be relative to system boot, not epoch. */ #define FFCLOCK_FAST 0x00000001 @@ -100,6 +100,7 @@ extern int sysclock_active; #define FBCLOCK_FAST 0x00010000 /* Currently unused. */ #define FBCLOCK_UPTIME 0x00020000 +#define FBCLOCK_LEAPSEC 0x00040000 #define FBCLOCK_MASK 0xffff0000 /* @@ -111,6 +112,7 @@ struct fbclock_info { struct bintime error; struct bintime tick_time; uint64_t th_scale; + long th_tai_offset; int status; }; diff --git a/lib/libc/include/generic-freebsd/sys/times.h b/lib/libc/include/generic-freebsd/sys/times.h index 20617c6f6fb5..eb3ff9b876e6 100644 --- a/lib/libc/include/generic-freebsd/sys/times.h +++ b/lib/libc/include/generic-freebsd/sys/times.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)times.h 8.4 (Berkeley) 1/21/94 */ #ifndef _SYS_TIMES_H_ diff --git a/lib/libc/include/generic-freebsd/sys/timespec.h b/lib/libc/include/generic-freebsd/sys/timespec.h index 513c4a969436..109ee08d2ab7 100644 --- a/lib/libc/include/generic-freebsd/sys/timespec.h +++ b/lib/libc/include/generic-freebsd/sys/timespec.h @@ -27,9 +27,6 @@ * 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. - * - * @(#)time.h 8.5 (Berkeley) 5/4/95 - * from: FreeBSD: src/sys/sys/time.h,v 1.43 2000/03/20 14:09:05 phk Exp */ #ifndef _SYS_TIMESPEC_H_ diff --git a/lib/libc/include/generic-freebsd/sys/timetc.h b/lib/libc/include/generic-freebsd/sys/timetc.h index 7526d680a3ef..a9b351af3b96 100644 --- a/lib/libc/include/generic-freebsd/sys/timetc.h +++ b/lib/libc/include/generic-freebsd/sys/timetc.h @@ -49,7 +49,7 @@ struct timecounter { * This function is optional. It will be called whenever the * timecounter is rewound, and is intended to check for PPS * events. Normal hardware does not need it but timecounters - * which latch PPS in hardware (like sys/pci/xrpu.c) do. + * which latch PPS in hardware do. */ u_int tc_counter_mask; /* This mask should mask off any unimplemented bits. */ @@ -87,7 +87,7 @@ extern int tc_min_ticktock_freq; /* u_int64_t tc_getfrequency(void); void tc_init(struct timecounter *tc); void tc_setclock(struct timespec *ts); -void tc_ticktock(int cnt); +void tc_ticktock(long cnt); void cpu_tick_calibration(void); #ifdef SYSCTL_DECL diff --git a/lib/libc/include/generic-freebsd/sys/timex.h b/lib/libc/include/generic-freebsd/sys/timex.h index 8faa7d724e17..82a124cb9050 100644 --- a/lib/libc/include/generic-freebsd/sys/timex.h +++ b/lib/libc/include/generic-freebsd/sys/timex.h @@ -154,7 +154,7 @@ struct timex { #ifdef __FreeBSD__ #ifdef _KERNEL -void ntp_update_second(int64_t *adjustment, time_t *newsec); +void ntp_update_second(int64_t *adjustment, time_t *newsec, long *tai_off); #else /* !_KERNEL */ #include diff --git a/lib/libc/include/generic-freebsd/sys/ttycom.h b/lib/libc/include/generic-freebsd/sys/ttycom.h index fdb07522cc05..bded540a9133 100644 --- a/lib/libc/include/generic-freebsd/sys/ttycom.h +++ b/lib/libc/include/generic-freebsd/sys/ttycom.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)ttycom.h 8.1 (Berkeley) 3/28/94 */ #ifndef _SYS_TTYCOM_H_ @@ -71,8 +69,8 @@ /* 89-91 conflicts: tun and tap */ #define TIOCTIMESTAMP _IOR('t', 89, struct timeval) /* enable/get timestamp * of last input event */ -#define TIOCMGDTRWAIT _IOR('t', 90, int) /* modem: get wait on close */ -#define TIOCMSDTRWAIT _IOW('t', 91, int) /* modem: set wait on close */ +/* TIOCMGDTRWAIT _IOR('t', 90, int) * was modem: get wait on close */ +/* TIOCMSDTRWAIT _IOW('t', 91, int) * was modem: set wait on close */ /* 92-93 tun and tap */ /* 94-97 conflicts: tun and tap */ #define TIOCDRAIN _IO('t', 94) /* wait till output drained */ diff --git a/lib/libc/include/generic-freebsd/sys/ttydefaults.h b/lib/libc/include/generic-freebsd/sys/ttydefaults.h index b0124d5fc48d..32796d98f322 100644 --- a/lib/libc/include/generic-freebsd/sys/ttydefaults.h +++ b/lib/libc/include/generic-freebsd/sys/ttydefaults.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)ttydefaults.h 8.4 (Berkeley) 1/21/94 */ /* diff --git a/lib/libc/include/generic-freebsd/sys/types.h b/lib/libc/include/generic-freebsd/sys/types.h index 6b1108bbb879..ecdae1410e4b 100644 --- a/lib/libc/include/generic-freebsd/sys/types.h +++ b/lib/libc/include/generic-freebsd/sys/types.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)types.h 8.6 (Berkeley) 2/19/95 */ #ifndef _SYS_TYPES_H_ @@ -299,9 +297,11 @@ typedef struct vm_page *vm_page_t; #if defined(_KERNEL) || defined(_STANDALONE) #if !defined(__bool_true_false_are_defined) && !defined(__cplusplus) #define __bool_true_false_are_defined 1 +#if __STDC_VERSION__ < 202311L #define false 0 #define true 1 typedef _Bool bool; +#endif /* __STDC_VERSION__ < 202311L */ #endif /* !__bool_true_false_are_defined && !__cplusplus */ #endif /* KERNEL || _STANDALONE */ @@ -313,7 +313,9 @@ typedef _Bool bool; #if __BSD_VISIBLE +#ifndef _STANDALONE #include +#endif /* * The major and minor numbers are encoded in dev_t as MMMmmmMm (where diff --git a/lib/libc/include/generic-freebsd/sys/ucoredump.h b/lib/libc/include/generic-freebsd/sys/ucoredump.h new file mode 100644 index 000000000000..e6038c8241d1 --- /dev/null +++ b/lib/libc/include/generic-freebsd/sys/ucoredump.h @@ -0,0 +1,99 @@ +/* + * + * Copyright (c) 2015 Mark Johnston + * Copyright (c) 2025 Kyle Evans + * + * SPDX-License-Identifier: BSD-2-Clause + * + */ + +#ifndef _SYS_UCOREDUMP_H_ +#define _SYS_UCOREDUMP_H_ + +#ifdef _KERNEL + +#include +#include +#include + +/* Coredump output parameters. */ +struct coredump_params; +struct coredump_writer; +struct thread; +struct ucred; + +typedef int coredump_init_fn(const struct coredump_writer *, + const struct coredump_params *); +typedef int coredump_write_fn(const struct coredump_writer *, const void *, size_t, + off_t, enum uio_seg, struct ucred *, size_t *, struct thread *); +typedef int coredump_extend_fn(const struct coredump_writer *, off_t, + struct ucred *); + +struct coredump_vnode_ctx { + struct vnode *vp; + struct ucred *fcred; +}; + +coredump_write_fn core_vn_write; +coredump_extend_fn core_vn_extend; + +struct coredump_writer { + void *ctx; + coredump_init_fn *init_fn; + coredump_write_fn *write_fn; + coredump_extend_fn *extend_fn; +}; + +struct coredump_params { + off_t offset; + struct ucred *active_cred; + struct thread *td; + const struct coredump_writer *cdw; + struct compressor *comp; +}; + +#define CORE_BUF_SIZE (16 * 1024) + +int core_write(struct coredump_params *, const void *, size_t, off_t, + enum uio_seg, size_t *); +int core_output(char *, size_t, off_t, struct coredump_params *, void *); +int sbuf_drain_core_output(void *, const char *, int); + +extern int coredump_pack_fileinfo; +extern int coredump_pack_vmmapinfo; + +extern int compress_user_cores; +extern int compress_user_cores_level; + +typedef int coredumper_probe_fn(struct thread *); + +/* + * Some arbitrary values for coredumper probes to return. The highest priority + * we can find wins. It's somewhat expected that a coredumper may want to bid + * differently based on the process in question. Note that probe functions will + * be called with the proc lock held, so they must not sleep. + */ +#define COREDUMPER_NOMATCH (-1) /* Decline to touch it */ +#define COREDUMPER_GENERIC (0) /* I handle coredumps */ +#define COREDUMPER_SPECIAL (50) /* Special handler */ +#define COREDUMPER_HIGH_PRIORITY (100) /* High-priority handler */ + +/* + * The handle functions will be called with the proc lock held, and should + * return with the proc lock dropped. + */ +typedef int coredumper_handle_fn(struct thread *, off_t); + +struct coredumper { + SLIST_ENTRY(coredumper) cd_entry; + const char *cd_name; + coredumper_probe_fn *cd_probe; + coredumper_handle_fn *cd_handle; + blockcount_t cd_refcount; +}; + +void coredumper_register(struct coredumper *); +void coredumper_unregister(struct coredumper *); + +#endif /* _KERNEL */ +#endif /* _SYS_UCOREDUMP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/ucred.h b/lib/libc/include/generic-freebsd/sys/ucred.h index 0f62d2f0bc91..c8f77d703832 100644 --- a/lib/libc/include/generic-freebsd/sys/ucred.h +++ b/lib/libc/include/generic-freebsd/sys/ucred.h @@ -27,22 +27,36 @@ * 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. - * - * @(#)ucred.h 8.4 (Berkeley) 1/9/95 */ #ifndef _SYS_UCRED_H_ #define _SYS_UCRED_H_ +#include #if defined(_KERNEL) || defined(_WANT_UCRED) #include #include #endif #include -struct loginclass; +#if defined(_KERNEL) || defined(_WANT_UCRED) +/* + * Flags for cr_flags. + */ +#define CRED_FLAG_CAPMODE 0x00000001 /* In capability mode. */ +#define CRED_FLAG_GROUPSET 0x00000002 /* Groups have been set. */ -#define XU_NGROUPS 16 +/* + * Number of groups inlined in 'struct ucred'. It must stay reasonably low as + * it is also used by some functions to allocate an array of this size on the + * stack. + */ +#define CRED_SMALLGROUPS_NB 16 + +struct label; +struct loginclass; +struct prison; +struct uidinfo; /* * Credentials. @@ -57,39 +71,37 @@ struct loginclass; * * See "Credential management" comment in kern_prot.c for more information. */ -#if defined(_KERNEL) || defined(_WANT_UCRED) struct ucred { struct mtx cr_mtx; long cr_ref; /* (c) reference count */ u_int cr_users; /* (c) proc + thread using this cred */ u_int cr_flags; /* credential flags */ struct auditinfo_addr cr_audit; /* Audit properties. */ + int cr_ngroups; /* number of supplementary groups */ #define cr_startcopy cr_uid uid_t cr_uid; /* effective user id */ uid_t cr_ruid; /* real user id */ uid_t cr_svuid; /* saved user id */ - int cr_ngroups; /* number of groups */ + gid_t cr_gid; /* effective group id */ gid_t cr_rgid; /* real group id */ gid_t cr_svgid; /* saved group id */ struct uidinfo *cr_uidinfo; /* per euid resource consumption */ struct uidinfo *cr_ruidinfo; /* per ruid resource consumption */ struct prison *cr_prison; /* jail(2) */ struct loginclass *cr_loginclass; /* login class */ - void *cr_pspare2[2]; /* general use 2 */ + void *cr_pspare2[2]; /* general use 2 */ #define cr_endcopy cr_label struct label *cr_label; /* MAC label */ gid_t *cr_groups; /* groups */ int cr_agroups; /* Available groups */ - gid_t cr_smallgroups[XU_NGROUPS]; /* storage for small groups */ + /* storage for small groups */ + gid_t cr_smallgroups[CRED_SMALLGROUPS_NB]; }; #define NOCRED ((struct ucred *)0) /* no credential available */ #define FSCRED ((struct ucred *)-1) /* filesystem credential */ #endif /* _KERNEL || _WANT_UCRED */ -/* - * Flags for cr_flags. - */ -#define CRED_FLAG_CAPMODE 0x00000001 /* In capability mode. */ +#define XU_NGROUPS 16 /* * This is the external representation of struct ucred. @@ -97,8 +109,26 @@ struct ucred { struct xucred { u_int cr_version; /* structure layout version */ uid_t cr_uid; /* effective user id */ - short cr_ngroups; /* number of groups */ - gid_t cr_groups[XU_NGROUPS]; /* groups */ + short cr_ngroups; /* number of groups (incl. cr_gid). */ + union { + /* + * The effective GID has been the first element of cr_groups[] + * for historical reasons. It should be accessed using the + * 'cr_gid' identifier. Supplementary groups should be accessed + * using cr_sgroups[]. Note that 'cr_ngroups' currently + * includes the effective GID. + * + * XXXOC: On the next API change (requires versioning), please + * replace this union with a true unaliased field 'cr_gid' and + * make sure that cr_groups[]/'cr_ngroups' only account for + * supplementary groups. + */ + struct { + gid_t cr_gid; /* effective group id */ + gid_t cr_sgroups[XU_NGROUPS - 1]; + }; + gid_t cr_groups[XU_NGROUPS]; /* groups */ + }; union { void *_cr_unused1; /* compatibility with old ucred */ pid_t cr_pid; @@ -106,17 +136,77 @@ struct xucred { }; #define XUCRED_VERSION 0 -/* This can be used for both ucred and xucred structures. */ -#define cr_gid cr_groups[0] +struct mac; +/* + * Structure to pass as an argument to the setcred() system call. + */ +struct setcred { + uid_t sc_uid; /* effective user id */ + uid_t sc_ruid; /* real user id */ + uid_t sc_svuid; /* saved user id */ + gid_t sc_gid; /* effective group id */ + gid_t sc_rgid; /* real group id */ + gid_t sc_svgid; /* saved group id */ + u_int sc_pad; /* see 32-bit compat structure */ + u_int sc_supp_groups_nb; /* number of supplementary groups */ + gid_t *sc_supp_groups; /* supplementary groups */ + struct mac *sc_label; /* MAC label */ +}; +/* + * Initializer for 'struct setcred' variables. + */ +#define SETCRED_INITIALIZER { -1, -1, -1, -1, -1, -1, 0, 0, NULL, NULL } + +/* + * Flags to setcred(). + */ +#define SETCREDF_UID (1u << 0) +#define SETCREDF_RUID (1u << 1) +#define SETCREDF_SVUID (1u << 2) +#define SETCREDF_GID (1u << 3) +#define SETCREDF_RGID (1u << 4) +#define SETCREDF_SVGID (1u << 5) +#define SETCREDF_SUPP_GROUPS (1u << 6) +#define SETCREDF_MAC_LABEL (1u << 7) #ifdef _KERNEL -struct proc; +/* + * Masks of the currently valid flags to setcred(). + * + * Please consider reserving some of the high bits in the 'flags' argument for + * versioning when almost all of them are in use. + */ +#define SETCREDF_MASK (SETCREDF_UID | SETCREDF_RUID | SETCREDF_SVUID | \ + SETCREDF_GID | SETCREDF_RGID | SETCREDF_SVGID | SETCREDF_SUPP_GROUPS | \ + SETCREDF_MAC_LABEL) + +struct setcred32 { +#define setcred32_copy_start sc_uid + uid_t sc_uid; + uid_t sc_ruid; + uid_t sc_svuid; + gid_t sc_gid; + gid_t sc_rgid; + gid_t sc_svgid; + u_int sc_pad; + u_int sc_supp_groups_nb; +#define setcred32_copy_end sc_supp_groups + uint32_t sc_supp_groups; /* gid_t [*] */ + uint32_t sc_label; /* struct mac32 [*] */ +}; + struct thread; +/* Common native and 32-bit compatibility entry point. */ +int user_setcred(struct thread *td, const u_int flags, + const void *const uwcred, const size_t size, bool is_32bit); + +struct proc; + struct credbatch { struct ucred *cred; - int users; - int ref; + u_int users; + long ref; }; static inline void @@ -146,9 +236,9 @@ void crcopy(struct ucred *dest, struct ucred *src); struct ucred *crcopysafe(struct proc *p, struct ucred *cr); struct ucred *crdup(struct ucred *cr); void crextend(struct ucred *cr, int n); -void proc_set_cred_init(struct proc *p, struct ucred *cr); -void proc_set_cred(struct proc *p, struct ucred *cr); -void proc_unset_cred(struct proc *p); +void proc_set_cred(struct proc *p, struct ucred *newcred); +bool proc_set_cred_enforce_proc_lim(struct proc *p, struct ucred *newcred); +void proc_unset_cred(struct proc *p, bool decrement_proc_count); void crfree(struct ucred *cr); struct ucred *crcowsync(void); struct ucred *crget(void); @@ -157,9 +247,30 @@ struct ucred *crcowget(struct ucred *cr); void crcowfree(struct thread *td); void cru2x(struct ucred *cr, struct xucred *xcr); void cru2xt(struct thread *td, struct xucred *xcr); -void crsetgroups(struct ucred *cr, int n, gid_t *groups); -bool groupmember(gid_t gid, struct ucred *cred); -bool realgroupmember(gid_t gid, struct ucred *cred); +void crsetgroups(struct ucred *cr, int ngrp, const gid_t *groups); +void crsetgroups_and_egid(struct ucred *cr, int ngrp, const gid_t *groups, + const gid_t default_egid); +bool cr_xids_subset(struct ucred *active_cred, struct ucred *obj_cred); + +/* + * Returns whether gid designates a primary group in cred. + */ +static inline bool +group_is_primary(const gid_t gid, const struct ucred *const cred) +{ + return (gid == cred->cr_groups[0] || gid == cred->cr_rgid || + gid == cred->cr_svgid); +} +bool group_is_supplementary(const gid_t gid, const struct ucred *const cred); +bool groupmember(gid_t gid, const struct ucred *cred); +bool realgroupmember(gid_t gid, const struct ucred *cred); + +#else /* !_KERNEL */ + +__BEGIN_DECLS +int setcred(u_int flags, const struct setcred *wcred, size_t size); +__END_DECLS + #endif /* _KERNEL */ #endif /* !_SYS_UCRED_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/sys/uio.h b/lib/libc/include/generic-freebsd/sys/uio.h index 59a7f55e5469..067f9df3c517 100644 --- a/lib/libc/include/generic-freebsd/sys/uio.h +++ b/lib/libc/include/generic-freebsd/sys/uio.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)uio.h 8.5 (Berkeley) 2/22/94 */ #ifndef _SYS_UIO_H_ @@ -86,12 +84,14 @@ int copyiniov(const struct iovec *iovp, u_int iovcnt, struct iovec **iov, int copyinuio(const struct iovec *iovp, u_int iovcnt, struct uio **uiop); int copyout_map(struct thread *td, vm_offset_t *addr, size_t sz); int copyout_unmap(struct thread *td, vm_offset_t addr, size_t sz); +void exterr_copyout(struct thread *td); int physcopyin(void *src, vm_paddr_t dst, size_t len); int physcopyout(vm_paddr_t src, void *dst, size_t len); int physcopyin_vlist(struct bus_dma_segment *src, off_t offset, vm_paddr_t dst, size_t len); int physcopyout_vlist(vm_paddr_t src, struct bus_dma_segment *dst, off_t offset, size_t len); +void uioadvance(struct uio *, size_t); int uiomove(void *cp, int n, struct uio *uio); int uiomove_frombuf(void *buf, int buflen, struct uio *uio); int uiomove_fromphys(struct vm_page *ma[], vm_offset_t offset, int n, @@ -101,6 +101,10 @@ int uiomove_object(struct vm_object *obj, off_t obj_size, struct uio *uio); #else /* !_KERNEL */ +#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 +#include +#endif + __BEGIN_DECLS ssize_t readv(int, const struct iovec *, int); ssize_t writev(int, const struct iovec *, int); diff --git a/lib/libc/include/generic-freebsd/sys/umtx.h b/lib/libc/include/generic-freebsd/sys/umtx.h index 79c6d23fb389..a600c818df87 100644 --- a/lib/libc/include/generic-freebsd/sys/umtx.h +++ b/lib/libc/include/generic-freebsd/sys/umtx.h @@ -135,6 +135,7 @@ struct umtx_robust_lists_params { __BEGIN_DECLS int _umtx_op(void *obj, int op, u_long val, void *uaddr, void *uaddr2); +int _umtx_op_err(void *obj, int op, u_long val, void *uaddr, void *uaddr2); __END_DECLS diff --git a/lib/libc/include/generic-freebsd/sys/umtxvar.h b/lib/libc/include/generic-freebsd/sys/umtxvar.h index 988eea573eb5..e9309af6a523 100644 --- a/lib/libc/include/generic-freebsd/sys/umtxvar.h +++ b/lib/libc/include/generic-freebsd/sys/umtxvar.h @@ -206,6 +206,7 @@ int umtx_key_get(const void *, int, int, struct umtx_key *); void umtx_key_release(struct umtx_key *); struct umtx_q *umtxq_alloc(void); void umtxq_busy(struct umtx_key *); +void umtxq_busy_unlocked(struct umtx_key *); int umtxq_count(struct umtx_key *); void umtxq_free(struct umtx_q *); struct umtxq_chain *umtxq_getchain(struct umtx_key *); diff --git a/lib/libc/include/generic-freebsd/sys/un.h b/lib/libc/include/generic-freebsd/sys/un.h index 5152ce620b28..ce3c1c821776 100644 --- a/lib/libc/include/generic-freebsd/sys/un.h +++ b/lib/libc/include/generic-freebsd/sys/un.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)un.h 8.3 (Berkeley) 2/19/95 */ #ifndef _SYS_UN_H_ @@ -67,7 +65,6 @@ struct sockaddr_un { #define LOCAL_PEERCRED 1 /* retrieve peer credentials */ #define LOCAL_CREDS 2 /* pass credentials to receiver */ #define LOCAL_CREDS_PERSISTENT 3 /* pass credentials to receiver */ -#define LOCAL_CONNWAIT 4 /* connects block until accepted */ /* Start of reserved space for third-party socket options. */ #define LOCAL_VENDOR SO_VENDOR diff --git a/lib/libc/include/generic-freebsd/sys/unistd.h b/lib/libc/include/generic-freebsd/sys/unistd.h index 5bc91c8d218f..2a779bc4e799 100644 --- a/lib/libc/include/generic-freebsd/sys/unistd.h +++ b/lib/libc/include/generic-freebsd/sys/unistd.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)unistd.h 8.2 (Berkeley) 1/7/94 */ #ifndef _SYS_UNISTD_H_ @@ -95,7 +93,7 @@ #endif /* Define the POSIX.1 version we target for compliance. */ -#define _POSIX_VERSION 200112L +#define _POSIX_VERSION 200809L /* access function */ #define F_OK 0 /* test for existence of file */ @@ -156,6 +154,12 @@ #define _PC_MAC_PRESENT 63 #define _PC_ACL_NFS4 64 #define _PC_DEALLOC_PRESENT 65 +#define _PC_NAMEDATTR_ENABLED 66 +#define _PC_HAS_NAMEDATTR 67 +#define _PC_XATTR_ENABLED _PC_NAMEDATTR_ENABLED /* Solaris Compatible */ +#define _PC_XATTR_EXISTS _PC_HAS_NAMEDATTR /* Solaris Compatible */ +#define _PC_HAS_HIDDENSYSTEM 68 +#define _PC_CLONE_BLKSIZE 69 #endif /* From OpenSolaris, used by SEEK_DATA/SEEK_HOLE. */ @@ -210,6 +214,16 @@ * close_range() options. */ #define CLOSE_RANGE_CLOEXEC (1<<2) +#define CLOSE_RANGE_CLOFORK (1<<3) + +/* + * copy_file_range flags visible to user space. + * High order 8 bits reserved for kernel flags. + * Allocate from bit 23 down, to try and avoid conflicts with + * future Linux flags. + */ +#define COPY_FILE_RANGE_CLONE 0x00800000 /* Require cloning. */ +#define COPY_FILE_RANGE_USERFLAGS (COPY_FILE_RANGE_CLONE) #endif /* __BSD_VISIBLE */ diff --git a/lib/libc/include/generic-freebsd/sys/unpcb.h b/lib/libc/include/generic-freebsd/sys/unpcb.h index 74765ae1789f..762a3d907107 100644 --- a/lib/libc/include/generic-freebsd/sys/unpcb.h +++ b/lib/libc/include/generic-freebsd/sys/unpcb.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)unpcb.h 8.1 (Berkeley) 6/2/93 */ #ifndef _SYS_UNPCB_H_ @@ -95,6 +93,7 @@ struct unpcb { u_int unp_msgcount; /* (g) references from message queue */ u_int unp_gcrefs; /* (g) garbage collector refcount */ ino_t unp_ino; /* (g) fake inode number */ + mode_t unp_mode; /* (g) initial pre-bind() mode */ LIST_ENTRY(unpcb) unp_dead; /* (g) link in dead list */ } __aligned(CACHE_LINE_SIZE); @@ -109,8 +108,6 @@ struct unpcb { #define UNP_HAVEPC 0x001 #define UNP_WANTCRED_ALWAYS 0x002 /* credentials wanted always */ #define UNP_WANTCRED_ONESHOT 0x004 /* credentials wanted once */ -#define UNP_CONNWAIT 0x008 /* connect blocks until accepted */ - #define UNP_WANTCRED_MASK (UNP_WANTCRED_ONESHOT | UNP_WANTCRED_ALWAYS) /* diff --git a/lib/libc/include/generic-freebsd/sys/user.h b/lib/libc/include/generic-freebsd/sys/user.h index 907fc51af04e..1ac68ffa9ed0 100644 --- a/lib/libc/include/generic-freebsd/sys/user.h +++ b/lib/libc/include/generic-freebsd/sys/user.h @@ -29,8 +29,6 @@ * 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. - * - * @(#)user.h 8.2 (Berkeley) 9/23/93 */ #ifndef _SYS_USER_H_ @@ -40,6 +38,7 @@ #ifndef _KERNEL /* stuff that *used* to be included by user.h, or is now needed */ #include +#include #include #include #include @@ -87,7 +86,7 @@ */ #define KI_NSPARE_INT 2 #define KI_NSPARE_LONG 12 -#define KI_NSPARE_PTR 5 +#define KI_NSPARE_PTR 4 #ifndef _KERNEL #ifndef KINFO_PROC_SIZE @@ -213,6 +212,7 @@ struct kinfo_proc { * That way the spare room from both arrays will remain contiguous. */ struct pwddesc *ki_pd; /* pointer to process paths info */ + void *ki_uerrmsg; /* address of the ext err msg place */ void *ki_spareptrs[KI_NSPARE_PTR]; /* spare room for growth */ long ki_sparelongs[KI_NSPARE_LONG]; /* spare room for growth */ long ki_sflag; /* PS_* flags */ @@ -227,7 +227,7 @@ void fill_kinfo_proc(struct proc *, struct kinfo_proc *); * Legacy PS_ flag. This moved to p_flag but is maintained for * compatibility. */ -#define PS_INMEM 0x00001 /* Loaded into memory. */ +#define PS_INMEM 0x00001 /* Loaded into memory, always true. */ /* ki_sessflag values */ #define KI_CTTY 0x00000001 /* controlling tty vnode active */ @@ -265,6 +265,8 @@ struct user { #define KF_TYPE_DEV 12 #define KF_TYPE_EVENTFD 13 #define KF_TYPE_TIMERFD 14 +#define KF_TYPE_INOTIFY 15 +#define KF_TYPE_JAILDESC 16 #define KF_TYPE_UNKNOWN 255 #define KF_VTYPE_VNON 0 @@ -373,7 +375,7 @@ struct kinfo_file { struct sockaddr_storage kf_sa_peer; /* Address of so_pcb. */ uint64_t kf_sock_pcb; - /* Address of inp_ppcb. */ + /* Obsolete! May be reused as a spare. */ uint64_t kf_sock_inpcb; /* Address of unp_conn. */ uint64_t kf_sock_unpconn; @@ -451,11 +453,18 @@ struct kinfo_file { uint32_t kf_timerfd_flags; uint64_t kf_timerfd_addr; } kf_timerfd; + struct { + int32_t kf_jid; + } kf_jail; struct { uint64_t kf_kqueue_addr; int32_t kf_kqueue_count; int32_t kf_kqueue_state; } kf_kqueue; + struct { + uint64_t kf_inotify_npending; + uint64_t kf_inotify_nbpending; + } kf_inotify; } kf_un; }; uint16_t kf_status; /* Status flags. */ @@ -608,7 +617,8 @@ struct kinfo_vmobject { } kvo_type_spec; /* Type-specific union */ uint64_t kvo_me; /* Uniq handle for anon obj */ uint64_t kvo_laundry; /* Number of laundry pages. */ - uint64_t _kvo_qspare[5]; + uint64_t kvo_wired; /* Number of wired pages. */ + uint64_t _kvo_qspare[4]; uint32_t kvo_swapped; /* Number of swapped pages */ uint32_t kvo_flags; uint32_t _kvo_ispare[6]; @@ -625,7 +635,7 @@ struct kinfo_vmobject { #define KKST_MAXLEN 1024 #define KKST_STATE_STACKOK 0 /* Stack is valid. */ -#define KKST_STATE_SWAPPED 1 /* Stack swapped out. */ +#define KKST_STATE_SWAPPED 1 /* Stack swapped out, obsolete. */ #define KKST_STATE_RUNNING 2 /* Stack ephemeral. */ #if defined(__amd64__) || defined(__i386__) @@ -667,6 +677,35 @@ struct kinfo_vm_layout { uintptr_t kvm_spare[12]; }; +#define KNOTE_STATUS_ACTIVE 0x00000001 +#define KNOTE_STATUS_QUEUED 0x00000002 +#define KNOTE_STATUS_DISABLED 0x00000004 +#define KNOTE_STATUS_DETACHED 0x00000008 +#define KNOTE_STATUS_KQUEUE 0x00000010 + +#define KNOTE_EXTDATA_NONE 0 +#define KNOTE_EXTDATA_VNODE 1 +#define KNOTE_EXTDATA_PIPE 2 + +struct kinfo_knote { + int knt_kq_fd; + struct kevent knt_event; + int knt_status; + int knt_extdata; + uint64_t knt_spare0[4]; + union { + struct { + int knt_vnode_type; + uint64_t knt_vnode_fsid; + uint64_t knt_vnode_fileid; + char knt_vnode_fullpath[PATH_MAX]; + } knt_vnode; + struct { + ino_t knt_pipe_ino; + } knt_pipe; + }; +}; + #ifdef _KERNEL /* Flags for kern_proc_out function. */ #define KERN_PROC_NOTHREADS 0x1 @@ -694,6 +733,8 @@ int kern_proc_cwd_out(struct proc *p, struct sbuf *sb, ssize_t maxlen); int kern_proc_out(struct proc *p, struct sbuf *sb, int flags); int kern_proc_vmmap_out(struct proc *p, struct sbuf *sb, ssize_t maxlen, int flags); +int kern_proc_kqueues_out(struct proc *p, struct sbuf *s, size_t maxlen, + bool compat32); int vntype_to_kinfo(int vtype); void pack_kinfo(struct kinfo_file *kif); diff --git a/lib/libc/include/generic-freebsd/sys/utsname.h b/lib/libc/include/generic-freebsd/sys/utsname.h index 0ee5f2995ec8..e664a20255b8 100644 --- a/lib/libc/include/generic-freebsd/sys/utsname.h +++ b/lib/libc/include/generic-freebsd/sys/utsname.h @@ -30,8 +30,6 @@ * 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. - * - * @(#)utsname.h 8.1 (Berkeley) 1/4/94 */ #ifndef _SYS_UTSNAME_H diff --git a/lib/libc/include/generic-freebsd/sys/vmmeter.h b/lib/libc/include/generic-freebsd/sys/vmmeter.h index b595f831336c..8d941f4a694c 100644 --- a/lib/libc/include/generic-freebsd/sys/vmmeter.h +++ b/lib/libc/include/generic-freebsd/sys/vmmeter.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)vmmeter.h 8.2 (Berkeley) 7/10/94 */ #ifndef _SYS_VMMETER_H_ @@ -122,6 +120,7 @@ struct vmmeter { counter_u64_t v_rforkpages; /* (p) pages affected by rfork() */ counter_u64_t v_kthreadpages; /* (p) ... and by kernel fork() */ counter_u64_t v_wire_count; /* (p) pages wired down */ + counter_u64_t v_nofree_count; /* (p) permanently allocated pages */ #define VM_METER_NCOUNTERS \ (offsetof(struct vmmeter, v_page_size) / sizeof(counter_u64_t)) /* @@ -176,6 +175,13 @@ vm_wire_count(void) return (VM_CNT_FETCH(v_wire_count)); } +static inline u_int +vm_nofree_count(void) +{ + + return (VM_CNT_FETCH(v_nofree_count)); +} + /* * Return TRUE if we are under our severe low-free-pages threshold * diff --git a/lib/libc/include/generic-freebsd/sys/vnode.h b/lib/libc/include/generic-freebsd/sys/vnode.h index 24a035d47e65..ff75d451301e 100644 --- a/lib/libc/include/generic-freebsd/sys/vnode.h +++ b/lib/libc/include/generic-freebsd/sys/vnode.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)vnode.h 8.7 (Berkeley) 2/4/94 */ #ifndef _SYS_VNODE_H_ @@ -69,6 +67,11 @@ __enum_uint8_decl(vtype) { VLASTTYPE = VMARKER, }; +/* + * We frequently need to test is something is a device node. + */ +#define VTYPE_ISDEV(vtype) ((vtype) == VCHR || (vtype) == VBLK) + __enum_uint8_decl(vstate) { VSTATE_UNINITIALIZED, VSTATE_CONSTRUCTED, @@ -88,11 +91,13 @@ enum vgetstate { * it from v_data. If non-null, this area is freed in getnewvnode(). */ -struct namecache; struct cache_fpl; +struct inotify_watch; +struct namecache; struct vpollinfo { struct mtx vpi_lock; /* lock to protect below */ + TAILQ_HEAD(, inotify_watch) vpi_inotify; /* list of inotify watchers */ struct selinfo vpi_selinfo; /* identity of poller(s) */ short vpi_events; /* what they are looking for */ short vpi_revents; /* what has happened */ @@ -134,7 +139,7 @@ struct vnode { seqc_t v_seqc; /* i modification count */ uint32_t v_nchash; /* u namecache hash */ u_int v_hash; - struct vop_vector *v_op; /* u vnode operations vector */ + const struct vop_vector *v_op; /* u vnode operations vector */ void *v_data; /* u private data for fs */ /* @@ -199,6 +204,8 @@ struct vnode { int v_seqc_users; /* i modifications pending */ }; +#define VN_ISDEV(vp) VTYPE_ISDEV((vp)->v_type) + #ifndef DEBUG_LOCKS #ifdef _LP64 /* @@ -248,6 +255,11 @@ _Static_assert(sizeof(struct vnode) <= 448, "vnode size crosses 448 bytes"); #define VIRF_MOUNTPOINT 0x0004 /* This vnode is mounted on */ #define VIRF_TEXT_REF 0x0008 /* Executable mappings ref the vnode */ #define VIRF_CROSSMP 0x0010 /* Cross-mp vnode, no locking */ +#define VIRF_NAMEDDIR 0x0020 /* Named attribute directory */ +#define VIRF_NAMEDATTR 0x0040 /* Named attribute */ +#define VIRF_INOTIFY 0x0080 /* This vnode is being watched */ +#define VIRF_INOTIFY_PARENT 0x0100 /* A parent of this vnode may be being + watched */ #define VI_UNUSED0 0x0001 /* unused */ #define VI_MOUNT 0x0002 /* Mount in progress */ @@ -283,7 +295,7 @@ _Static_assert(sizeof(struct vnode) <= 448, "vnode size crosses 448 bytes"); struct vattr { __enum_uint8(vtype) va_type; /* vnode type (for create) */ u_short va_mode; /* files access mode and type */ - u_short va_padding0; + uint16_t va_bsdflags; /* same as st_bsdflags from stat(2) */ uid_t va_uid; /* owner user id */ gid_t va_gid; /* owner group id */ nlink_t va_nlink; /* number of references to file */ @@ -304,6 +316,8 @@ struct vattr { long va_spare; /* remain quad aligned */ }; +#define VATTR_ISDEV(vap) VTYPE_ISDEV((vap)->va_type) + /* * Flags for va_vaflags. */ @@ -533,7 +547,7 @@ extern struct vnodeop_desc *vnodeop_descs[]; #define VOPARG_OFFSETTO(s_type, s_offset, struct_p) \ ((s_type)(((char*)(struct_p)) + (s_offset))) -#ifdef DEBUG_VFS_LOCKS +#ifdef INVARIANTS /* * Support code to aid in debugging VFS locking problems. Not totally * reliable since if the thread sleeps between changing the lock @@ -567,7 +581,7 @@ void assert_vop_unlocked(struct vnode *vp, const char *str); VNPASS(!seqc_in_modify(_vp->v_seqc), _vp); \ } while (0) -#else /* !DEBUG_VFS_LOCKS */ +#else /* !INVARIANTS */ #define ASSERT_VI_LOCKED(vp, str) ((void)0) #define ASSERT_VI_UNLOCKED(vp, str) ((void)0) @@ -578,7 +592,7 @@ void assert_vop_unlocked(struct vnode *vp, const char *str); #define ASSERT_VOP_IN_SEQC(vp) ((void)0) #define ASSERT_VOP_NOT_IN_SEQC(vp) ((void)0) -#endif /* DEBUG_VFS_LOCKS */ +#endif /* INVARIANTS */ /* * This call works for vnodes in the kernel. @@ -667,6 +681,7 @@ char *cache_symlink_alloc(size_t size, int flags); void cache_symlink_free(char *string, size_t size); int cache_symlink_resolve(struct cache_fpl *fpl, const char *string, size_t len); +void cache_vop_inotify(struct vnode *vp, int event, uint32_t cookie); void cache_vop_rename(struct vnode *fdvp, struct vnode *fvp, struct vnode *tdvp, struct vnode *tvp, struct componentname *fcnp, struct componentname *tcnp); void cache_vop_rmdir(struct vnode *dvp, struct vnode *vp); @@ -708,6 +723,7 @@ int speedup_syncer(void); int vn_vptocnp(struct vnode **vp, char *buf, size_t *buflen); int vn_getcwd(char *buf, char **retbuf, size_t *buflen); int vn_fullpath(struct vnode *vp, char **retbuf, char **freebuf); +int vn_fullpath_jail(struct vnode *vp, char **retbuf, char **freebuf); int vn_fullpath_global(struct vnode *vp, char **retbuf, char **freebuf); int vn_fullpath_hardlink(struct vnode *vp, struct vnode *dvp, const char *hdrl_name, size_t hrdl_name_length, char **retbuf, @@ -836,18 +852,15 @@ void vn_seqc_write_end(struct vnode *vp); #define vn_seqc_consistent(vp, seq) seqc_consistent(&(vp)->v_seqc, seq) #define vn_rangelock_unlock(vp, cookie) \ - rangelock_unlock(&(vp)->v_rl, (cookie), VI_MTX(vp)) -#define vn_rangelock_unlock_range(vp, cookie, start, end) \ - rangelock_unlock_range(&(vp)->v_rl, (cookie), (start), (end), \ - VI_MTX(vp)) + rangelock_unlock(&(vp)->v_rl, (cookie)) #define vn_rangelock_rlock(vp, start, end) \ - rangelock_rlock(&(vp)->v_rl, (start), (end), VI_MTX(vp)) + rangelock_rlock(&(vp)->v_rl, (start), (end)) #define vn_rangelock_tryrlock(vp, start, end) \ - rangelock_tryrlock(&(vp)->v_rl, (start), (end), VI_MTX(vp)) + rangelock_tryrlock(&(vp)->v_rl, (start), (end)) #define vn_rangelock_wlock(vp, start, end) \ - rangelock_wlock(&(vp)->v_rl, (start), (end), VI_MTX(vp)) + rangelock_wlock(&(vp)->v_rl, (start), (end)) #define vn_rangelock_trywlock(vp, start, end) \ - rangelock_trywlock(&(vp)->v_rl, (start), (end), VI_MTX(vp)) + rangelock_trywlock(&(vp)->v_rl, (start), (end)) #define vn_irflag_read(vp) atomic_load_short(&(vp)->v_irflag) void vn_irflag_set_locked(struct vnode *vp, short toset); @@ -872,8 +885,10 @@ int vop_stdfsync(struct vop_fsync_args *); int vop_stdgetwritemount(struct vop_getwritemount_args *); int vop_stdgetpages(struct vop_getpages_args *); int vop_stdinactive(struct vop_inactive_args *); -int vop_stdioctl(struct vop_ioctl_args *); int vop_stdneed_inactive(struct vop_need_inactive_args *); +int vop_stdinotify(struct vop_inotify_args *); +int vop_stdinotify_add_watch(struct vop_inotify_add_watch_args *); +int vop_stdioctl(struct vop_ioctl_args *); int vop_stdkqfilter(struct vop_kqfilter_args *); int vop_stdlock(struct vop_lock1_args *); int vop_stdunlock(struct vop_unlock_args *); @@ -913,9 +928,12 @@ int dead_read(struct vop_read_args *ap); int dead_write(struct vop_write_args *ap); /* These are called from within the actual VOPS. */ +void vop_allocate_post(void *a, int rc); +void vop_copy_file_range_post(void *ap, int rc); void vop_close_post(void *a, int rc); void vop_create_pre(void *a); void vop_create_post(void *a, int rc); +void vop_deallocate_post(void *a, int rc); void vop_whiteout_pre(void *a); void vop_whiteout_post(void *a, int rc); void vop_deleteextattr_pre(void *a); @@ -931,7 +949,6 @@ void vop_mknod_post(void *a, int rc); void vop_open_post(void *a, int rc); void vop_read_post(void *a, int rc); void vop_read_pgcache_post(void *ap, int rc); -void vop_readdir_post(void *a, int rc); void vop_reclaim_post(void *a, int rc); void vop_remove_pre(void *a); void vop_remove_post(void *a, int rc); @@ -949,7 +966,7 @@ void vop_symlink_pre(void *a); void vop_symlink_post(void *a, int rc); int vop_sigdefer(struct vop_vector *vop, struct vop_generic_args *a); -#ifdef DEBUG_VFS_LOCKS +#ifdef INVARIANTS void vop_fdatasync_debugpre(void *a); void vop_fdatasync_debugpost(void *a, int rc); void vop_fplookup_vexec_debugpre(void *a); @@ -991,9 +1008,10 @@ void vop_rename_fail(struct vop_rename_args *ap); AUDIT_ARG_VNODE1(ap->a_vp); \ _error = mac_vnode_check_stat(_ap->a_active_cred, _ap->a_file_cred, _ap->a_vp);\ if (__predict_true(_error == 0)) { \ - ap->a_sb->st_padding0 = 0; \ ap->a_sb->st_padding1 = 0; \ bzero(_ap->a_sb->st_spare, sizeof(_ap->a_sb->st_spare)); \ + ap->a_sb->st_filerev = 0; \ + ap->a_sb->st_bsdflags = 0; \ } \ _error; \ }) @@ -1006,7 +1024,36 @@ void vop_rename_fail(struct vop_rename_args *ap); _error; \ }) -#define VOP_WRITE_PRE(ap) \ +#ifdef INVARIANTS +#define vop_readdir_pre_assert(ap) \ + ssize_t nresid, oresid; \ + \ + oresid = (ap)->a_uio->uio_resid; + +#define vop_readdir_post_assert(ap, ret) \ + nresid = (ap)->a_uio->uio_resid; \ + if ((ret) == 0 && (ap)->a_eofflag != NULL) { \ + VNASSERT(oresid == 0 || nresid != oresid || \ + *(ap)->a_eofflag == 1, \ + (ap)->a_vp, ("VOP_READDIR: eofflag not set")); \ + } +#else +#define vop_readdir_pre_assert(ap) +#define vop_readdir_post_assert(ap, ret) +#endif + +#define vop_readdir_pre(ap) do { \ + vop_readdir_pre_assert(ap) + +#define vop_readdir_post(ap, ret) \ + vop_readdir_post_assert(ap, ret); \ + if ((ret) == 0) { \ + VFS_KNOTE_LOCKED((ap)->a_vp, NOTE_READ); \ + INOTIFY((ap)->a_vp, IN_ACCESS); \ + } \ +} while (0) + +#define vop_write_pre(ap) \ struct vattr va; \ int error; \ off_t osize, ooffset, noffset; \ @@ -1020,11 +1067,14 @@ void vop_rename_fail(struct vop_rename_args *ap); osize = (off_t)va.va_size; \ } -#define VOP_WRITE_POST(ap, ret) \ +#define vop_write_post(ap, ret) \ noffset = (ap)->a_uio->uio_offset; \ - if (noffset > ooffset && !VN_KNLIST_EMPTY((ap)->a_vp)) { \ - VFS_KNOTE_LOCKED((ap)->a_vp, NOTE_WRITE \ - | (noffset > osize ? NOTE_EXTEND : 0)); \ + if (noffset > ooffset) { \ + if (!VN_KNLIST_EMPTY((ap)->a_vp)) { \ + VFS_KNOTE_LOCKED((ap)->a_vp, NOTE_WRITE | \ + (noffset > osize ? NOTE_EXTEND : 0)); \ + } \ + INOTIFY((ap)->a_vp, IN_MODIFY); \ } #define VOP_LOCK(vp, flags) VOP_LOCK1(vp, flags, __FILE__, __LINE__) @@ -1084,7 +1134,14 @@ vrefcnt(struct vnode *vp) vref(vp); \ } while (0) +/* + * The caller doesn't know the file size and vnode_create_vobject() should + * determine the size on its own. + */ +#define VNODE_NO_SIZE ((off_t)-1) + int vnode_create_vobject(struct vnode *vp, off_t size, struct thread *td); +int vnode_create_disk_vobject(struct vnode *vp, off_t size, struct thread *td); void vnode_destroy_vobject(struct vnode *vp); extern struct vop_vector fifo_specops; @@ -1190,6 +1247,7 @@ vn_get_state(struct vnode *vp) #define vfs_smr_exit() smr_exit(VFS_SMR()) #define vfs_smr_synchronize() smr_synchronize(VFS_SMR()) #define vfs_smr_entered_load(ptr) smr_entered_load((ptr), VFS_SMR()) +#define VFS_SMR_ENTERED() SMR_ENTERED(VFS_SMR()) #define VFS_SMR_ASSERT_ENTERED() SMR_ASSERT_ENTERED(VFS_SMR()) #define VFS_SMR_ASSERT_NOT_ENTERED() SMR_ASSERT_NOT_ENTERED(VFS_SMR()) #define VFS_SMR_ZONE_SET(zone) uma_zone_set_smr((zone), VFS_SMR()) diff --git a/lib/libc/include/generic-freebsd/sys/wait.h b/lib/libc/include/generic-freebsd/sys/wait.h index 631b3ff54fff..d14631987f8d 100644 --- a/lib/libc/include/generic-freebsd/sys/wait.h +++ b/lib/libc/include/generic-freebsd/sys/wait.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)wait.h 8.2 (Berkeley) 7/10/94 */ #ifndef _SYS_WAIT_H_ diff --git a/lib/libc/include/generic-freebsd/sys/watchdog.h b/lib/libc/include/generic-freebsd/sys/watchdog.h index f01a0c4adcaa..c73be31abf58 100644 --- a/lib/libc/include/generic-freebsd/sys/watchdog.h +++ b/lib/libc/include/generic-freebsd/sys/watchdog.h @@ -32,15 +32,16 @@ #define _SYS_WATCHDOG_H #include +#include #define _PATH_WATCHDOG "fido" -#define WDIOCPATPAT _IOW('W', 42, u_int) /* pat the watchdog */ -#define WDIOC_SETTIMEOUT _IOW('W', 43, int) /* set/reset the timer */ -#define WDIOC_GETTIMEOUT _IOR('W', 44, int) /* get total timeout */ -#define WDIOC_GETTIMELEFT _IOR('W', 45, int) /* get time left */ -#define WDIOC_GETPRETIMEOUT _IOR('W', 46, int) /* get the pre-timeout */ -#define WDIOC_SETPRETIMEOUT _IOW('W', 47, int) /* set the pre-timeout */ +#define WDIOC_PATPAT _IOW('W', 52, sbintime_t) /* pat the watchdog */ +#define WDIOC_SETTIMEOUT _IOW('W', 53, sbintime_t) /* set/reset the timer */ +#define WDIOC_GETTIMEOUT _IOR('W', 54, sbintime_t) /* get total timeout */ +#define WDIOC_GETTIMELEFT _IOR('W', 55, sbintime_t) /* get time left */ +#define WDIOC_GETPRETIMEOUT _IOR('W', 56, sbintime_t) /* get the pre-timeout */ +#define WDIOC_SETPRETIMEOUT _IOW('W', 57, sbintime_t) /* set the pre-timeout */ /* set the action when a pre-timeout occurs see: WD_SOFT_* */ #define WDIOC_SETPRETIMEOUTACT _IOW('W', 48, int) @@ -48,6 +49,8 @@ #define WDIOC_SETSOFT _IOW('W', 49, int) #define WDIOC_SETSOFTTIMEOUTACT _IOW('W', 50, int) +#define WDIOC_CONTROL _IOW('W', 51, int) /* configure watchdog */ + #define WD_ACTIVE 0x8000000 /* * Watchdog reset, timeout set to value in WD_INTERVAL field. @@ -93,6 +96,11 @@ #define WD_TO_64SEC 36 #define WD_TO_128SEC 37 +/* Control options for WDIOC_CONTROL */ +#define WD_CTRL_DISABLE 0x00000000 +#define WD_CTRL_ENABLE 0x00000001 +#define WD_CTRL_RESET 0x00000002 + /* action on pre-timeout trigger */ #define WD_SOFT_PANIC 0x01 /* panic */ #define WD_SOFT_DDB 0x02 /* enter debugger */ @@ -105,11 +113,16 @@ #include typedef void (*watchdog_fn)(void *, u_int, int *); +typedef void (*watchdog_sbt_fn)(void *, sbintime_t, sbintime_t *, int *); EVENTHANDLER_DECLARE(watchdog_list, watchdog_fn); +EVENTHANDLER_DECLARE(watchdog_sbt_list, watchdog_sbt_fn); u_int wdog_kern_last_timeout(void); int wdog_kern_pat(u_int utim); +sbintime_t wdog_kern_last_timeout_sbt(void); +int wdog_kern_pat_sbt(sbintime_t utim); +int wdog_control(int ctrl); /* * The following function pointer is used to attach a software watchdog diff --git a/lib/libc/include/generic-freebsd/sysexits.h b/lib/libc/include/generic-freebsd/sysexits.h index 1e5bda73c204..3fcfe16c5666 100644 --- a/lib/libc/include/generic-freebsd/sysexits.h +++ b/lib/libc/include/generic-freebsd/sysexits.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)sysexits.h 8.1 (Berkeley) 6/2/93 */ #ifndef _SYSEXITS_H_ diff --git a/lib/libc/include/generic-freebsd/syslog.h b/lib/libc/include/generic-freebsd/syslog.h index b6528a384113..3c822d795d52 100644 --- a/lib/libc/include/generic-freebsd/syslog.h +++ b/lib/libc/include/generic-freebsd/syslog.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)syslog.h 8.1 (Berkeley) 6/2/93 */ #ifndef _SYS_SYSLOG_H_ diff --git a/lib/libc/include/generic-freebsd/tar.h b/lib/libc/include/generic-freebsd/tar.h index b834bf24ddc8..14b275e43762 100644 --- a/lib/libc/include/generic-freebsd/tar.h +++ b/lib/libc/include/generic-freebsd/tar.h @@ -30,8 +30,6 @@ * 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. - * - * @(#)tar.h 8.2 (Berkeley) 1/4/94 */ #ifndef _TAR_H diff --git a/lib/libc/include/generic-freebsd/teken/teken.h b/lib/libc/include/generic-freebsd/teken/teken.h deleted file mode 100644 index 8d4d4c14f8d4..000000000000 --- a/lib/libc/include/generic-freebsd/teken/teken.h +++ /dev/null @@ -1,220 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2008-2009 Ed Schouten - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _TEKEN_H_ -#define _TEKEN_H_ - -#include - -/* - * libteken: terminal emulation library. - * - * This library converts an UTF-8 stream of bytes to terminal drawing - * commands. - */ - -typedef uint32_t teken_char_t; -typedef unsigned short teken_unit_t; -typedef unsigned char teken_format_t; -#define TF_BOLD 0x01 /* Bold character. */ -#define TF_UNDERLINE 0x02 /* Underline character. */ -#define TF_BLINK 0x04 /* Blinking character. */ -#define TF_REVERSE 0x08 /* Reverse rendered character. */ -#define TF_CJK_RIGHT 0x10 /* Right-hand side of CJK character. */ -#define TF_IMAGE 0x20 /* This character space has image. */ -typedef unsigned char teken_color_t; -#define TC_BLACK 0 -#define TC_RED 1 -#define TC_GREEN 2 -#define TC_YELLOW 3 -#define TC_BLUE 4 -#define TC_MAGENTA 5 -#define TC_CYAN 6 -#define TC_WHITE 7 -#define TC_NCOLORS 8 -#define TC_LIGHT 8 /* ORed with the others. */ - -typedef struct { - teken_unit_t tp_row; - teken_unit_t tp_col; -} teken_pos_t; -typedef struct { - teken_pos_t tr_begin; - teken_pos_t tr_end; -} teken_rect_t; -typedef struct { - teken_format_t ta_format; - teken_color_t ta_fgcolor; - teken_color_t ta_bgcolor; -} teken_attr_t; -typedef struct { - teken_unit_t ts_begin; - teken_unit_t ts_end; -} teken_span_t; - -typedef struct __teken teken_t; - -typedef void teken_state_t(teken_t *, teken_char_t); - -/* - * Drawing routines supplied by the user. - */ - -typedef void tf_bell_t(void *); -typedef void tf_cursor_t(void *, const teken_pos_t *); -typedef void tf_putchar_t(void *, const teken_pos_t *, teken_char_t, - const teken_attr_t *); -typedef void tf_fill_t(void *, const teken_rect_t *, teken_char_t, - const teken_attr_t *); -typedef void tf_copy_t(void *, const teken_rect_t *, const teken_pos_t *); -typedef void tf_pre_input_t(void *); -typedef void tf_post_input_t(void *); -typedef void tf_param_t(void *, int, unsigned int); -#define TP_SHOWCURSOR 0 -#define TP_KEYPADAPP 1 -#define TP_AUTOREPEAT 2 -#define TP_SWITCHVT 3 -#define TP_132COLS 4 -#define TP_SETBELLPD 5 -#define TP_SETBELLPD_PITCH(pd) ((pd) >> 16) -#define TP_SETBELLPD_DURATION(pd) ((pd) & 0xffff) -#define TP_MOUSE 6 -#define TP_SETBORDER 7 -#define TP_SETLOCALCURSOR 8 -#define TP_SETGLOBALCURSOR 9 -typedef void tf_respond_t(void *, const void *, size_t); - -typedef struct { - tf_bell_t *tf_bell; - tf_cursor_t *tf_cursor; - tf_putchar_t *tf_putchar; - tf_fill_t *tf_fill; - tf_copy_t *tf_copy; - tf_pre_input_t *tf_pre_input; - tf_post_input_t *tf_post_input; - tf_param_t *tf_param; - tf_respond_t *tf_respond; -} teken_funcs_t; - -typedef teken_char_t teken_scs_t(const teken_t *, teken_char_t); - -/* - * Terminal state. - */ - -struct __teken { - const teken_funcs_t *t_funcs; - void *t_softc; - - teken_state_t *t_nextstate; - unsigned int t_stateflags; - -#define T_NUMSIZE 8 - unsigned int t_nums[T_NUMSIZE]; - unsigned int t_curnum; - - teken_pos_t t_cursor; - teken_attr_t t_curattr; - teken_pos_t t_saved_cursor; - teken_attr_t t_saved_curattr; - - teken_attr_t t_defattr; - teken_pos_t t_winsize; - - /* For DECSTBM. */ - teken_span_t t_scrollreg; - /* For DECOM. */ - teken_span_t t_originreg; - -#define T_NUMCOL 160 - unsigned int t_tabstops[T_NUMCOL / (sizeof(unsigned int) * 8)]; - - unsigned int t_utf8_left; - teken_char_t t_utf8_partial; - teken_char_t t_last; - - unsigned int t_curscs; - teken_scs_t *t_saved_curscs; - teken_scs_t *t_scs[2]; -}; - -/* Initialize teken structure. */ -void teken_init(teken_t *, const teken_funcs_t *, void *); - -/* Deliver character input. */ -void teken_input(teken_t *, const void *, size_t); - -/* Get/set teken attributes. */ -const teken_pos_t *teken_get_cursor(const teken_t *); -const teken_attr_t *teken_get_curattr(const teken_t *); -const teken_attr_t *teken_get_defattr(const teken_t *); -void teken_get_defattr_cons25(const teken_t *, int *, int *); -const teken_pos_t *teken_get_winsize(const teken_t *); -void teken_set_cursor(teken_t *, const teken_pos_t *); -void teken_set_curattr(teken_t *, const teken_attr_t *); -void teken_set_defattr(teken_t *, const teken_attr_t *); -void teken_set_winsize(teken_t *, const teken_pos_t *); -void teken_set_winsize_noreset(teken_t *, const teken_pos_t *); - -/* Key input escape sequences. */ -#define TKEY_UP 0x00 -#define TKEY_DOWN 0x01 -#define TKEY_LEFT 0x02 -#define TKEY_RIGHT 0x03 - -#define TKEY_HOME 0x04 -#define TKEY_END 0x05 -#define TKEY_INSERT 0x06 -#define TKEY_DELETE 0x07 -#define TKEY_PAGE_UP 0x08 -#define TKEY_PAGE_DOWN 0x09 - -#define TKEY_F1 0x0a -#define TKEY_F2 0x0b -#define TKEY_F3 0x0c -#define TKEY_F4 0x0d -#define TKEY_F5 0x0e -#define TKEY_F6 0x0f -#define TKEY_F7 0x10 -#define TKEY_F8 0x11 -#define TKEY_F9 0x12 -#define TKEY_F10 0x13 -#define TKEY_F11 0x14 -#define TKEY_F12 0x15 -const char *teken_get_sequence(const teken_t *, unsigned int); - -/* Legacy features. */ -void teken_set_8bit(teken_t *); -void teken_set_cons25(teken_t *); -void teken_set_cons25keys(teken_t *); - -/* Color conversion. */ -teken_color_t teken_256to16(teken_color_t); -teken_color_t teken_256to8(teken_color_t); - -#endif /* !_TEKEN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/termios.h b/lib/libc/include/generic-freebsd/termios.h index d6f7e9c79d05..e2dca44b79a4 100644 --- a/lib/libc/include/generic-freebsd/termios.h +++ b/lib/libc/include/generic-freebsd/termios.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)termios.h 8.3 (Berkeley) 3/28/94 */ #ifndef _TERMIOS_H_ diff --git a/lib/libc/include/generic-freebsd/time.h b/lib/libc/include/generic-freebsd/time.h index 306c85e83285..6e5ec48eabb3 100644 --- a/lib/libc/include/generic-freebsd/time.h +++ b/lib/libc/include/generic-freebsd/time.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)time.h 8.3 (Berkeley) 1/21/94 */ /* @@ -157,6 +155,8 @@ int clock_nanosleep(clockid_t, int, const struct timespec *, struct timespec *); #if __POSIX_VISIBLE >= 199506 char *asctime_r(const struct tm *, char *); char *ctime_r(const time_t *, char *); +#endif +#if __POSIX_VISIBLE >= 199506 || __ISO_C_VISIBLE >= 2023 struct tm *gmtime_r(const time_t *, struct tm *); struct tm *localtime_r(const time_t *, struct tm *); #endif @@ -164,15 +164,18 @@ struct tm *localtime_r(const time_t *, struct tm *); #if __XSI_VISIBLE char *strptime(const char * __restrict, const char * __restrict, struct tm * __restrict); +extern long timezone; +extern int daylight; #endif #if __BSD_VISIBLE -char *timezone(int, int); /* XXX XSI conflict */ time_t timelocal(struct tm * const); time_t timegm(struct tm * const); int timer_oshandle_np(timer_t timerid); time_t time2posix(time_t t); time_t posix2time(time_t t); +struct tm *offtime(const time_t *, long); +struct tm *offtime_r(const time_t *__restrict, long, struct tm *__restrict); #endif /* __BSD_VISIBLE */ #if __POSIX_VISIBLE >= 200809 || defined(_XLOCALE_H_) diff --git a/lib/libc/include/generic-freebsd/timeconv.h b/lib/libc/include/generic-freebsd/timeconv.h index 2432e7e28290..1f6a917d7386 100644 --- a/lib/libc/include/generic-freebsd/timeconv.h +++ b/lib/libc/include/generic-freebsd/timeconv.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)time.h 8.3 (Berkeley) 1/21/94 */ /* diff --git a/lib/libc/include/generic-freebsd/ttyent.h b/lib/libc/include/generic-freebsd/ttyent.h index 95acdcecab93..652527cf5380 100644 --- a/lib/libc/include/generic-freebsd/ttyent.h +++ b/lib/libc/include/generic-freebsd/ttyent.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)ttyent.h 8.1 (Berkeley) 6/2/93 */ #ifndef _TTYENT_H_ diff --git a/lib/libc/include/generic-freebsd/ufs/ffs/ffs_extern.h b/lib/libc/include/generic-freebsd/ufs/ffs/ffs_extern.h index a1772d2b5448..4471cc764712 100644 --- a/lib/libc/include/generic-freebsd/ufs/ffs/ffs_extern.h +++ b/lib/libc/include/generic-freebsd/ufs/ffs/ffs_extern.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)ffs_extern.h 8.6 (Berkeley) 3/30/95 */ #ifndef _UFS_FFS_EXTERN_H @@ -84,7 +82,8 @@ int ffs_inotovp(struct mount *, ino_t, uint64_t, int, struct vnode **, int); int ffs_isblock(struct fs *, uint8_t *, ufs1_daddr_t); int ffs_isfreeblock(struct fs *, uint8_t *, ufs1_daddr_t); -void ffs_oldfscompat_write(struct fs *, struct ufsmount *); +void ffs_oldfscompat_write(struct fs *); +bool ffs_oldfscompat_inode_read(struct fs *, union dinodep, time_t); int ffs_own_mount(const struct mount *mp); int ffs_sbsearch(void *, struct fs **, int, struct malloc_type *, int (*)(void *, off_t, void **, int)); diff --git a/lib/libc/include/generic-freebsd/ufs/ffs/fs.h b/lib/libc/include/generic-freebsd/ufs/ffs/fs.h index 7384b4288a1f..d1cdfe6dfbf8 100644 --- a/lib/libc/include/generic-freebsd/ufs/ffs/fs.h +++ b/lib/libc/include/generic-freebsd/ufs/ffs/fs.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)fs.h 8.13 (Berkeley) 3/21/95 */ #ifndef _UFS_FFS_FS_H_ @@ -413,7 +411,8 @@ struct fs { int64_t fs_unrefs; /* number of unreferenced inodes */ int64_t fs_providersize; /* size of underlying GEOM provider */ int64_t fs_metaspace; /* size of area reserved for metadata */ - int64_t fs_sparecon64[13]; /* old rotation block list head */ + uint64_t fs_save_maxfilesize; /* save old UFS1 maxfilesize */ + int64_t fs_sparecon64[12]; /* old rotation block list head */ int64_t fs_sblockactualloc; /* byte offset of this superblock */ int64_t fs_sblockloc; /* byte offset of standard superblock */ struct csum_total fs_cstotal; /* (u) cylinder summary information */ @@ -426,7 +425,7 @@ struct fs { uint32_t fs_snapinum[FSMAXSNAP];/* list of snapshot inode numbers */ uint32_t fs_avgfilesize; /* expected average file size */ uint32_t fs_avgfpdir; /* expected # of files per directory */ - int32_t fs_save_cgsize; /* save real cg size to use fs_bsize */ + uint32_t fs_available_spare; /* old scratch space */ ufs_time_t fs_mtime; /* Last mount or fsck time. */ int32_t fs_sujfree; /* SUJ free list */ int32_t fs_sparecon32[21]; /* reserved for future constants */ diff --git a/lib/libc/include/generic-freebsd/ufs/ffs/softdep.h b/lib/libc/include/generic-freebsd/ufs/ffs/softdep.h index 29806182f1c4..eb1bed13fcad 100644 --- a/lib/libc/include/generic-freebsd/ufs/ffs/softdep.h +++ b/lib/libc/include/generic-freebsd/ufs/ffs/softdep.h @@ -36,8 +36,6 @@ * 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. - * - * @(#)softdep.h 9.7 (McKusick) 6/21/00 */ #include diff --git a/lib/libc/include/generic-freebsd/ufs/ufs/dinode.h b/lib/libc/include/generic-freebsd/ufs/ufs/dinode.h index a312361207ea..11d3d717d223 100644 --- a/lib/libc/include/generic-freebsd/ufs/ufs/dinode.h +++ b/lib/libc/include/generic-freebsd/ufs/ufs/dinode.h @@ -62,8 +62,6 @@ * 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. - * - * @(#)dinode.h 8.3 (Berkeley) 1/21/94 */ #ifndef _UFS_UFS_DINODE_H_ @@ -113,12 +111,13 @@ typedef int64_t ufs_time_t; #define IFWHT 0160000 /* Whiteout. */ /* - * A dinode contains all the meta-data associated with a UFS2 file. - * This structure defines the on-disk format of a dinode. Since + * Each UFS filesystem version defines the on-disk format of its dinode. + * + * A UFS2 dinode contains all the meta-data associated with a UFS2 file. + * This structure defines the on-disk format of a UFS2 dinode. Since * this structure describes an on-disk structure, all its fields * are defined by types with precise widths. */ - #define UFS_NXADDR 2 /* External addresses in inode. */ #define UFS_NDADDR 12 /* Direct addresses in inode. */ #define UFS_NIADDR 3 /* Indirect addresses in inode. */ @@ -186,11 +185,11 @@ struct ufs1_dinode { uint32_t di_dirdepth; /* 4: IFDIR: depth from root dir */ }; uint64_t di_size; /* 8: File byte count. */ - int32_t di_atime; /* 16: Last access time. */ + uint32_t di_atime; /* 16: Last access time. */ int32_t di_atimensec; /* 20: Last access time. */ - int32_t di_mtime; /* 24: Last modified time. */ + uint32_t di_mtime; /* 24: Last modified time. */ int32_t di_mtimensec; /* 28: Last modified time. */ - int32_t di_ctime; /* 32: Last inode change time. */ + uint32_t di_ctime; /* 32: Last inode change time. */ int32_t di_ctimensec; /* 36: Last inode change time. */ union { struct { @@ -212,4 +211,17 @@ struct ufs1_dinode { #define UFS_LINK_MAX 65500 /* leave a few spare for special values */ +/* + * These structures hold or reference an on-disk dinode. + */ +union dinode { + struct ufs1_dinode dp1; + struct ufs2_dinode dp2; +}; + +union dinodep { + struct ufs1_dinode *dp1; + struct ufs2_dinode *dp2; +}; + #endif /* _UFS_UFS_DINODE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/ufs/ufs/dir.h b/lib/libc/include/generic-freebsd/ufs/ufs/dir.h index 9cea53117cdd..9859593beb78 100644 --- a/lib/libc/include/generic-freebsd/ufs/ufs/dir.h +++ b/lib/libc/include/generic-freebsd/ufs/ufs/dir.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)dir.h 8.2 (Berkeley) 1/21/94 */ #ifndef _UFS_UFS_DIR_H_ diff --git a/lib/libc/include/generic-freebsd/ufs/ufs/inode.h b/lib/libc/include/generic-freebsd/ufs/ufs/inode.h index d380d95444b5..b71f92202940 100644 --- a/lib/libc/include/generic-freebsd/ufs/ufs/inode.h +++ b/lib/libc/include/generic-freebsd/ufs/ufs/inode.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)inode.h 8.9 (Berkeley) 5/14/95 */ #ifndef _UFS_UFS_INODE_H_ @@ -90,10 +88,7 @@ struct inode { /* * The real copy of the on-disk inode. */ - union { - struct ufs1_dinode *din1; /* UFS1 on-disk dinode. */ - struct ufs2_dinode *din2; /* UFS2 on-disk dinode. */ - } dinode_u; + union dinodep i_dp; /* On-disk dinode */ ino_t i_number; /* The identity of the inode. */ uint32_t i_flag; /* flags, see below */ @@ -206,8 +201,8 @@ struct inode { #define i_dirhash i_un.dirhash #define i_snapblklist i_un.snapblklist -#define i_din1 dinode_u.din1 -#define i_din2 dinode_u.din2 +#define i_din1 i_dp.dp1 +#define i_din2 i_dp.dp2 #define ITOUMP(ip) ((ip)->i_ump) #define ITODEV(ip) (ITOUMP(ip)->um_dev) diff --git a/lib/libc/include/generic-freebsd/ufs/ufs/quota.h b/lib/libc/include/generic-freebsd/ufs/ufs/quota.h index 1a8c8f0c74dd..6cb2d099ef1a 100644 --- a/lib/libc/include/generic-freebsd/ufs/ufs/quota.h +++ b/lib/libc/include/generic-freebsd/ufs/ufs/quota.h @@ -30,8 +30,6 @@ * 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. - * - * @(#)quota.h 8.3 (Berkeley) 8/19/94 */ #ifndef _UFS_UFS_QUOTA_H_ diff --git a/lib/libc/include/generic-freebsd/ufs/ufs/ufs_extern.h b/lib/libc/include/generic-freebsd/ufs/ufs/ufs_extern.h index 5db08e03f44d..7578dfff5769 100644 --- a/lib/libc/include/generic-freebsd/ufs/ufs/ufs_extern.h +++ b/lib/libc/include/generic-freebsd/ufs/ufs/ufs_extern.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)ufs_extern.h 8.10 (Berkeley) 5/14/95 */ #ifndef _UFS_UFS_EXTERN_H_ @@ -61,15 +59,15 @@ int ufs_bmap_seekdata(struct vnode *, off_t *); int ufs_checkpath(ino_t, ino_t, struct inode *, struct ucred *, ino_t *); void ufs_dirbad(struct inode *, doff_t, char *); int ufs_dirbadentry(struct vnode *, struct direct *, int); -int ufs_dirempty(struct inode *, ino_t, struct ucred *); +int ufs_dirempty(struct inode *, ino_t, struct ucred *, int); int ufs_extread(struct vop_read_args *); int ufs_extwrite(struct vop_write_args *); void ufs_makedirentry(struct inode *, struct componentname *, struct direct *); int ufs_direnter(struct vnode *, struct vnode *, struct direct *, struct componentname *, struct buf *); -int ufs_dirremove(struct vnode *, struct inode *, int, int); -int ufs_dirrewrite(struct inode *, struct inode *, ino_t, int, int); +int ufs_dirremove(struct vnode *, struct inode *, int, bool); +int ufs_dirrewrite(struct inode *, struct inode *, ino_t, int, u_int); int ufs_lookup_ino(struct vnode *, struct vnode **, struct componentname *, ino_t *); int ufs_getlbns(struct vnode *, ufs2_daddr_t, struct indir *, int *); @@ -95,9 +93,9 @@ int softdep_setup_directory_add(struct buf *, struct inode *, off_t, ino_t, struct buf *, int); void softdep_change_directoryentry_offset(struct buf *, struct inode *, caddr_t, caddr_t, caddr_t, int); -void softdep_setup_remove(struct buf *,struct inode *, struct inode *, int); +void softdep_setup_remove(struct buf *,struct inode *, struct inode *, bool); void softdep_setup_directory_change(struct buf *, struct inode *, - struct inode *, ino_t, int); + struct inode *, ino_t, u_int); void softdep_change_linkcnt(struct inode *); int softdep_slowdown(struct vnode *); void softdep_setup_create(struct inode *, struct inode *); diff --git a/lib/libc/include/generic-freebsd/ufs/ufs/ufsmount.h b/lib/libc/include/generic-freebsd/ufs/ufs/ufsmount.h index 1a5ee2522893..ce82fb7ae0f4 100644 --- a/lib/libc/include/generic-freebsd/ufs/ufs/ufsmount.h +++ b/lib/libc/include/generic-freebsd/ufs/ufs/ufsmount.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)ufsmount.h 8.6 (Berkeley) 3/30/95 */ #ifndef _UFS_UFS_UFSMOUNT_H_ @@ -99,8 +97,6 @@ struct ufsmount { uint64_t um_maxsymlinklen; /* (c) max size of short symlink */ struct mtx um_lock; /* (c) Protects ufsmount & fs */ - struct sx um_checkpath_lock; /* (c) Protects ufs_checkpath() - result */ struct mount_softdeps *um_softdep; /* (c) softdep mgmt structure */ struct vnode *um_quotas[MAXQUOTAS]; /* (q) pointer to quota files */ struct ucred *um_cred[MAXQUOTAS]; /* (q) quota file access cred */ diff --git a/lib/libc/include/generic-freebsd/unistd.h b/lib/libc/include/generic-freebsd/unistd.h index c0d0ccbd2500..ce7dda335d59 100644 --- a/lib/libc/include/generic-freebsd/unistd.h +++ b/lib/libc/include/generic-freebsd/unistd.h @@ -27,19 +27,20 @@ * 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. - * - * @(#)unistd.h 8.12 (Berkeley) 4/27/95 */ #ifndef _UNISTD_H_ #define _UNISTD_H_ -#include #include /* XXX adds too much pollution. */ #include #include #include +#if !defined(_STANDALONE) && defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 +#include +#endif + #ifndef _GID_T_DECLARED typedef __gid_t gid_t; #define _GID_T_DECLARED @@ -291,6 +292,11 @@ typedef __useconds_t useconds_t; #define _SC_NPROCESSORS_CONF 57 #define _SC_NPROCESSORS_ONLN 58 #define _SC_CPUSET_SIZE 122 +#define _SC_UEXTERR_MAXLEN 123 /* user */ +#endif + +#if __POSIX_VISIBLE >= 202405 +#define _SC_NSIG 124 #endif /* Extensions found in Solaris and Linux. */ @@ -506,6 +512,7 @@ int exect(const char *, char * const *, char * const *); int execvP(const char *, const char *, char * const *); int execvpe(const char *, char * const *, char * const *); int feature_present(const char *); +int fchroot(int); char *fflagstostr(u_long); int getdomainname(char *, int); int getentropy(void *, size_t); diff --git a/lib/libc/include/generic-freebsd/utime.h b/lib/libc/include/generic-freebsd/utime.h index 7f82ad6e8d59..95adb12f6ce4 100644 --- a/lib/libc/include/generic-freebsd/utime.h +++ b/lib/libc/include/generic-freebsd/utime.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)utime.h 8.1 (Berkeley) 6/2/93 */ #ifndef _UTIME_H_ diff --git a/lib/libc/include/generic-freebsd/vm/_vm_radix.h b/lib/libc/include/generic-freebsd/vm/_vm_radix.h index f5930a35dc0b..fa71e618180e 100644 --- a/lib/libc/include/generic-freebsd/vm/_vm_radix.h +++ b/lib/libc/include/generic-freebsd/vm/_vm_radix.h @@ -31,16 +31,13 @@ #ifndef __VM_RADIX_H_ #define __VM_RADIX_H_ -/* - * Radix tree node. - */ -struct vm_radix_node; +#include /* - * Radix tree root. + * Radix tree */ struct vm_radix { - struct vm_radix_node *rt_root; + struct pctrie rt_trie; }; #endif /* !__VM_RADIX_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/vm/pmap.h b/lib/libc/include/generic-freebsd/vm/pmap.h index 0bb55fe34bb0..ed1c6e556174 100644 --- a/lib/libc/include/generic-freebsd/vm/pmap.h +++ b/lib/libc/include/generic-freebsd/vm/pmap.h @@ -31,8 +31,6 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)pmap.h 8.1 (Berkeley) 6/11/93 - * * * Copyright (c) 1987, 1990 Carnegie-Mellon University. * All rights reserved. @@ -83,8 +81,8 @@ typedef struct pmap_statistics *pmap_statistics_t; * Each machine-dependent implementation is required to provide: * * vm_memattr_t pmap_page_get_memattr(vm_page_t); - * boolean_t pmap_page_is_mapped(vm_page_t); - * boolean_t pmap_page_is_write_mapped(vm_page_t); + * bool pmap_page_is_mapped(vm_page_t); + * bool pmap_page_is_write_mapped(vm_page_t); * void pmap_page_set_memattr(vm_page_t, vm_memattr_t); */ #include @@ -138,17 +136,17 @@ void pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_paddr_t pmap_extract(pmap_t pmap, vm_offset_t va); vm_page_t pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot); -void pmap_growkernel(vm_offset_t); +int pmap_growkernel(vm_offset_t); void pmap_init(void); -boolean_t pmap_is_modified(vm_page_t m); -boolean_t pmap_is_prefaultable(pmap_t pmap, vm_offset_t va); -boolean_t pmap_is_referenced(vm_page_t m); -boolean_t pmap_is_valid_memattr(pmap_t, vm_memattr_t); +bool pmap_is_modified(vm_page_t m); +bool pmap_is_prefaultable(pmap_t pmap, vm_offset_t va); +bool pmap_is_referenced(vm_page_t m); +bool pmap_is_valid_memattr(pmap_t, vm_memattr_t); vm_offset_t pmap_map(vm_offset_t *, vm_paddr_t, vm_paddr_t, int); int pmap_mincore(pmap_t pmap, vm_offset_t addr, vm_paddr_t *pap); void pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object, vm_pindex_t pindex, vm_size_t size); -boolean_t pmap_page_exists_quick(pmap_t pmap, vm_page_t m); +bool pmap_page_exists_quick(pmap_t pmap, vm_page_t m); void pmap_page_init(vm_page_t m); int pmap_page_wired_mappings(vm_page_t m); int pmap_pinit(pmap_t); diff --git a/lib/libc/include/generic-freebsd/vm/swap_pager.h b/lib/libc/include/generic-freebsd/vm/swap_pager.h index 070d50c3a7a8..8a72a964866c 100644 --- a/lib/libc/include/generic-freebsd/vm/swap_pager.h +++ b/lib/libc/include/generic-freebsd/vm/swap_pager.h @@ -32,8 +32,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)swap_pager.h 7.1 (Berkeley) 12/5/90 */ #ifndef _VM_SWAP_PAGER_H_ @@ -70,13 +68,16 @@ struct swdevt { #ifdef _KERNEL +extern bool swap_pager_almost_full; extern int swap_pager_avail; extern int nsw_cluster_max; struct xswdev; int swap_dev_info(int name, struct xswdev *xs, char *devname, size_t len); void swap_pager_copy(vm_object_t, vm_object_t, vm_pindex_t, int); -vm_pindex_t swap_pager_find_least(vm_object_t object, vm_pindex_t pindex); +bool swap_pager_scan_all_shadowed(vm_object_t object); +vm_pindex_t swap_pager_seek_data(vm_object_t object, vm_pindex_t pindex); +vm_pindex_t swap_pager_seek_hole(vm_object_t object, vm_pindex_t pindex); void swap_pager_freespace(vm_object_t object, vm_pindex_t start, vm_size_t size, vm_size_t *freed); void swap_pager_swap_init(void); diff --git a/lib/libc/include/generic-freebsd/vm/uma.h b/lib/libc/include/generic-freebsd/vm/uma.h index ac67d2924040..d950d3d3ff6c 100644 --- a/lib/libc/include/generic-freebsd/vm/uma.h +++ b/lib/libc/include/generic-freebsd/vm/uma.h @@ -252,6 +252,7 @@ uma_zone_t uma_zcache_create(const char *name, int size, uma_ctor ctor, #define UMA_ZONE_SECONDARY 0x0200 /* Zone is a Secondary Zone */ #define UMA_ZONE_NOBUCKET 0x0400 /* Do not use buckets. */ #define UMA_ZONE_MAXBUCKET 0x0800 /* Use largest buckets. */ +#define UMA_ZONE_NOTRIM 0x1000 /* Don't trim this zone */ #define UMA_ZONE_CACHESPREAD 0x2000 /* * Spread memory start locations across * all possible cache lines. May diff --git a/lib/libc/include/generic-freebsd/vm/vm.h b/lib/libc/include/generic-freebsd/vm/vm.h index d23d52f033b1..1889a461cb8f 100644 --- a/lib/libc/include/generic-freebsd/vm/vm.h +++ b/lib/libc/include/generic-freebsd/vm/vm.h @@ -28,10 +28,6 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)vm.h 8.2 (Berkeley) 12/13/93 - * @(#)vm_prot.h 8.1 (Berkeley) 6/11/93 - * @(#)vm_inherit.h 8.1 (Berkeley) 6/11/93 - * * Copyright (c) 1987, 1990 Carnegie-Mellon University. * All rights reserved. * @@ -80,6 +76,7 @@ typedef u_char vm_prot_t; /* protection codes */ #define VM_PROT_COPY ((vm_prot_t) 0x08) /* copy-on-read */ #define VM_PROT_PRIV_FLAG ((vm_prot_t) 0x10) #define VM_PROT_FAULT_LOOKUP VM_PROT_PRIV_FLAG +#define VM_PROT_NO_PROMOTE VM_PROT_PRIV_FLAG #define VM_PROT_QUICK_NOFAULT VM_PROT_PRIV_FLAG /* same to save bits */ #define VM_PROT_ALL (VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE) @@ -158,6 +155,12 @@ struct kva_md_info { #define SWAP_RESERVE_RLIMIT_ON (1 << 1) #define SWAP_RESERVE_ALLOW_NONWIRED (1 << 2) +#ifdef NUMA +#define __numa_used +#else +#define __numa_used __unused +#endif + #ifdef _KERNEL struct ucred; @@ -167,7 +170,6 @@ bool swap_reserve_by_cred(vm_ooffset_t incr, struct ucred *cred); void swap_reserve_force(vm_ooffset_t incr); void swap_release(vm_ooffset_t decr); void swap_release_by_cred(vm_ooffset_t decr, struct ucred *cred); -void swapper(void); extern struct kva_md_info kmi; #define VA_IS_CLEANMAP(va) \ diff --git a/lib/libc/include/generic-freebsd/vm/vm_domainset.h b/lib/libc/include/generic-freebsd/vm/vm_domainset.h index 38c06b00fa5a..cd03f91eda75 100644 --- a/lib/libc/include/generic-freebsd/vm/vm_domainset.h +++ b/lib/libc/include/generic-freebsd/vm/vm_domainset.h @@ -28,25 +28,33 @@ #ifndef __VM_DOMAINSET_H__ #define __VM_DOMAINSET_H__ +struct pctrie_iter; + struct vm_domainset_iter { struct domainset *di_domain; unsigned int *di_iter; + /* Initialized from 'di_domain', initial value after reset. */ + domainset_t di_valid_mask; + /* Domains to browse in the current phase. */ + domainset_t di_remain_mask; + /* Domains skipped in phase 1 because under 'v_free_min'. */ + domainset_t di_min_mask; vm_pindex_t di_offset; int di_flags; uint16_t di_policy; - domainid_t di_n; bool di_minskip; }; int vm_domainset_iter_page(struct vm_domainset_iter *, struct vm_object *, - int *); -void vm_domainset_iter_page_init(struct vm_domainset_iter *, + int *, struct pctrie_iter *); +int vm_domainset_iter_page_init(struct vm_domainset_iter *, struct vm_object *, vm_pindex_t, int *, int *); int vm_domainset_iter_policy(struct vm_domainset_iter *, int *); -void vm_domainset_iter_policy_init(struct vm_domainset_iter *, +int vm_domainset_iter_policy_init(struct vm_domainset_iter *, struct domainset *, int *, int *); -void vm_domainset_iter_policy_ref_init(struct vm_domainset_iter *, +int vm_domainset_iter_policy_ref_init(struct vm_domainset_iter *, struct domainset_ref *, int *, int *); +void vm_domainset_iter_ignore(struct vm_domainset_iter *, int); int vm_wait_doms(const domainset_t *, int mflags); diff --git a/lib/libc/include/generic-freebsd/vm/vm_extern.h b/lib/libc/include/generic-freebsd/vm/vm_extern.h index 715f6f88686a..f548a6337745 100644 --- a/lib/libc/include/generic-freebsd/vm/vm_extern.h +++ b/lib/libc/include/generic-freebsd/vm/vm_extern.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)vm_extern.h 8.2 (Berkeley) 1/12/94 */ #ifndef _VM_EXTERN_H_ @@ -85,14 +83,16 @@ void kmem_init(vm_offset_t, vm_offset_t); void kmem_init_zero_region(void); void kmeminit(void); -int kernacc(void *, int, int); -int useracc(void *, int, int); +bool kernacc(void *, int, int); +bool useracc(void *, int, int); int vm_fault(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type, int fault_flags, vm_page_t *m_hold); void vm_fault_copy_entry(vm_map_t, vm_map_t, vm_map_entry_t, vm_map_entry_t, vm_ooffset_t *); int vm_fault_disable_pagefaults(void); void vm_fault_enable_pagefaults(int save); +int vm_fault_hold_pages(vm_map_t map, vm_offset_t addr, vm_size_t len, + vm_prot_t prot, vm_page_t *ma, int max_count, int *ppages_count); int vm_fault_quick_hold_pages(vm_map_t map, vm_offset_t addr, vm_size_t len, vm_prot_t prot, vm_page_t *ma, int max_count); int vm_fault_trap(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type, @@ -129,8 +129,6 @@ struct sf_buf *vm_imgact_map_page(vm_object_t object, vm_ooffset_t offset); void vm_imgact_unmap_page(struct sf_buf *sf); void vm_thread_dispose(struct thread *td); int vm_thread_new(struct thread *td, int pages); -void vm_thread_stack_back(struct domainset *ds, vm_offset_t kaddr, - vm_page_t ma[], int npages, int req_class); u_int vm_active_count(void); u_int vm_inactive_count(void); u_int vm_laundry_count(void); diff --git a/lib/libc/include/generic-freebsd/vm/vm_kern.h b/lib/libc/include/generic-freebsd/vm/vm_kern.h index e124ca1f7c4f..0162d894eeb5 100644 --- a/lib/libc/include/generic-freebsd/vm/vm_kern.h +++ b/lib/libc/include/generic-freebsd/vm/vm_kern.h @@ -31,8 +31,6 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)vm_kern.h 8.1 (Berkeley) 6/11/93 - * * * Copyright (c) 1987, 1990 Carnegie-Mellon University. * All rights reserved. @@ -71,13 +69,10 @@ extern struct vm_map exec_map_store; extern struct vm_map pipe_map_store; #define pipe_map (&pipe_map_store) extern struct vmem *kernel_arena; -extern struct vmem *kmem_arena; extern struct vmem *buffer_arena; extern struct vmem *transient_arena; extern struct vmem *memguard_arena; extern u_long vm_kmem_size; extern u_int exec_map_entries; extern u_int exec_map_entry_size; -extern vm_object_t kstack_object; - #endif /* _VM_VM_KERN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/vm/vm_map.h b/lib/libc/include/generic-freebsd/vm/vm_map.h index a188bd2a3471..7fa353f14bbe 100644 --- a/lib/libc/include/generic-freebsd/vm/vm_map.h +++ b/lib/libc/include/generic-freebsd/vm/vm_map.h @@ -31,8 +31,6 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)vm_map.h 8.9 (Berkeley) 5/17/95 - * * * Copyright (c) 1987, 1990 Carnegie-Mellon University. * All rights reserved. @@ -77,7 +75,6 @@ * vm_map_entry_t an entry in an address map. */ -typedef u_char vm_flags_t; typedef u_int vm_eflags_t; /* @@ -96,9 +93,9 @@ union vm_map_object { * and user-exported inheritance and protection information. * Also included is control information for virtual copy operations. * - * For stack gap map entries (MAP_ENTRY_GUARD | MAP_ENTRY_GROWS_DOWN - * or UP), the next_read member is reused as the stack_guard_page - * storage, and offset is the stack protection. + * For stack gap map entries (MAP_ENTRY_GUARD | MAP_ENTRY_STACK_GAP), + * the next_read member is reused as the stack_guard_page storage, and + * offset is the stack protection. */ struct vm_map_entry { struct vm_map_entry *left; /* left child or previous entry */ @@ -141,14 +138,14 @@ struct vm_map_entry { a core */ #define MAP_ENTRY_VN_EXEC 0x00000800 /* text vnode mapping */ #define MAP_ENTRY_GROWS_DOWN 0x00001000 /* top-down stacks */ -#define MAP_ENTRY_GROWS_UP 0x00002000 /* bottom-up stacks */ +#define MAP_ENTRY_UNUSED0 0x00002000 #define MAP_ENTRY_WIRE_SKIPPED 0x00004000 #define MAP_ENTRY_WRITECNT 0x00008000 /* tracked writeable mapping */ #define MAP_ENTRY_GUARD 0x00010000 -#define MAP_ENTRY_STACK_GAP_DN 0x00020000 -#define MAP_ENTRY_STACK_GAP_UP 0x00040000 +#define MAP_ENTRY_STACK_GAP 0x00020000 +#define MAP_ENTRY_UNUSED1 0x00040000 #define MAP_ENTRY_HEADER 0x00080000 #define MAP_ENTRY_SPLIT_BOUNDARY_MASK 0x00300000 @@ -205,14 +202,14 @@ vm_map_entry_system_wired_count(vm_map_entry_t entry) */ struct vm_map { struct vm_map_entry header; /* List of entries */ - struct sx lock; /* Lock for map data */ - struct mtx system_mtx; + union { + struct sx lock; /* Lock for map data */ + struct mtx system_mtx; + }; int nentries; /* Number of entries */ vm_size_t size; /* virtual size */ u_int timestamp; /* Version number */ - u_char needs_wakeup; - u_char system_map; /* (c) Am I a system map? */ - vm_flags_t flags; /* flags for this vm_map */ + u_int flags; /* flags for this vm_map */ vm_map_entry_t root; /* Root of a binary search tree */ pmap_t pmap; /* (c) Physical map */ vm_offset_t anon_loc; @@ -223,16 +220,21 @@ struct vm_map { }; /* - * vm_flags_t values + * vm_map flags values */ -#define MAP_WIREFUTURE 0x01 /* wire all future pages */ -#define MAP_BUSY_WAKEUP 0x02 /* thread(s) waiting on busy state */ -#define MAP_IS_SUB_MAP 0x04 /* has parent */ -#define MAP_ASLR 0x08 /* enabled ASLR */ -#define MAP_ASLR_IGNSTART 0x10 /* ASLR ignores data segment */ -#define MAP_REPLENISH 0x20 /* kmapent zone needs to be refilled */ -#define MAP_WXORX 0x40 /* enforce W^X */ -#define MAP_ASLR_STACK 0x80 /* stack location is randomized */ +#define MAP_WIREFUTURE 0x00000001 /* wire all future pages */ +#define MAP_BUSY_WAKEUP 0x00000002 /* thread(s) waiting on busy + state */ +#define MAP_IS_SUB_MAP 0x00000004 /* has parent */ +#define MAP_ASLR 0x00000008 /* enabled ASLR */ +#define MAP_ASLR_IGNSTART 0x00000010 /* ASLR ignores data segment */ +#define MAP_REPLENISH 0x00000020 /* kmapent zone needs to be + refilled */ +#define MAP_WXORX 0x00000040 /* enforce W^X */ +#define MAP_ASLR_STACK 0x00000080 /* stack location is + randomized */ +#define MAP_NEEDS_WAKEUP 0x40000000 +#define MAP_SYSTEM_MAP 0x80000000 #ifdef _KERNEL #if defined(KLD_MODULE) && !defined(KLD_TIED) @@ -263,7 +265,7 @@ vm_map_pmap(vm_map_t map) } static __inline void -vm_map_modflags(vm_map_t map, vm_flags_t set, vm_flags_t clear) +vm_map_modflags(vm_map_t map, u_int set, u_int clear) { map->flags = (map->flags | set) & ~clear; } @@ -278,6 +280,12 @@ vm_map_range_valid(vm_map_t map, vm_offset_t start, vm_offset_t end) return (true); } +static inline bool +vm_map_is_system(vm_map_t map) +{ + return ((map->flags & MAP_SYSTEM_MAP) != 0); +} + #endif /* KLD_MODULE */ #endif /* _KERNEL */ @@ -378,12 +386,12 @@ long vmspace_resident_count(struct vmspace *vmspace); #define MAP_PREFAULT_MADVISE 0x00000200 /* from (user) madvise request */ #define MAP_WRITECOUNT 0x00000400 #define MAP_REMAP 0x00000800 -#define MAP_STACK_GROWS_DOWN 0x00001000 -#define MAP_STACK_GROWS_UP 0x00002000 +#define MAP_STACK_AREA 0x00001000 +#define MAP_COW_UNUSED0 0x00002000 #define MAP_ACC_CHARGED 0x00004000 #define MAP_ACC_NO_CHARGE 0x00008000 -#define MAP_CREATE_STACK_GAP_UP 0x00010000 -#define MAP_CREATE_STACK_GAP_DN 0x00020000 +#define MAP_COW_UNUSED1 0x00010000 +#define MAP_CREATE_STACK_GAP 0x00020000 #define MAP_VN_EXEC 0x00040000 #define MAP_SPLIT_BOUNDARY_MASK 0x00180000 #define MAP_NO_HINT 0x00200000 @@ -486,6 +494,7 @@ int vm_map_fixed(vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t, vm_size_t, vm_offset_t vm_map_findspace(vm_map_t, vm_offset_t, vm_size_t); int vm_map_inherit (vm_map_t, vm_offset_t, vm_offset_t, vm_inherit_t); void vm_map_init(vm_map_t, pmap_t, vm_offset_t, vm_offset_t); +void vm_map_init_system(vm_map_t, pmap_t, vm_offset_t, vm_offset_t); int vm_map_insert (vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t, vm_offset_t, vm_prot_t, vm_prot_t, int); int vm_map_lookup (vm_map_t *, vm_offset_t, vm_prot_t, vm_map_entry_t *, vm_object_t *, vm_pindex_t *, vm_prot_t *, boolean_t *); diff --git a/lib/libc/include/generic-freebsd/vm/vm_object.h b/lib/libc/include/generic-freebsd/vm/vm_object.h index ddc3b4358e1a..d81cd4b0fb30 100644 --- a/lib/libc/include/generic-freebsd/vm/vm_object.h +++ b/lib/libc/include/generic-freebsd/vm/vm_object.h @@ -31,8 +31,6 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)vm_object.h 8.3 (Berkeley) 1/12/94 - * * * Copyright (c) 1987, 1990 Carnegie-Mellon University. * All rights reserved. @@ -100,7 +98,6 @@ struct vm_object { TAILQ_ENTRY(vm_object) object_list; /* list of all objects */ LIST_HEAD(, vm_object) shadow_head; /* objects that this is a shadow for */ LIST_ENTRY(vm_object) shadow_list; /* chain of shadow objects */ - struct pglist memq; /* list of resident pages */ struct vm_radix rtree; /* root of the resident page radix trie*/ vm_pindex_t size; /* Object size */ struct domainset_ref domain; /* NUMA policy. */ @@ -206,7 +203,6 @@ struct vm_object { #define OBJ_PAGERPRIV2 0x00008000 /* Pager private */ #define OBJ_SYSVSHM 0x00010000 /* SysV SHM */ #define OBJ_POSIXSHM 0x00020000 /* Posix SHM */ -#define OBJ_CDEVH 0x00040000 /* OBJT_DEVICE handle is cdev */ /* * Helpers to perform conversion between vm_object page indexes and offsets. @@ -379,6 +375,8 @@ void vm_object_page_noreuse(vm_object_t object, vm_pindex_t start, void vm_object_page_remove(vm_object_t object, vm_pindex_t start, vm_pindex_t end, int options); boolean_t vm_object_populate(vm_object_t, vm_pindex_t, vm_pindex_t); +void vm_object_prepare_buf_pages(vm_object_t object, vm_page_t *ma_dst, + int count, int *rbehind, int *rahead, vm_page_t *ma_src); void vm_object_print(long addr, boolean_t have_addr, long count, char *modif); void vm_object_reference (vm_object_t); void vm_object_reference_locked(vm_object_t); diff --git a/lib/libc/include/generic-freebsd/vm/vm_page.h b/lib/libc/include/generic-freebsd/vm/vm_page.h index 5f9d222c0bd3..54a32049e2c8 100644 --- a/lib/libc/include/generic-freebsd/vm/vm_page.h +++ b/lib/libc/include/generic-freebsd/vm/vm_page.h @@ -31,8 +31,6 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)vm_page.h 8.2 (Berkeley) 12/13/93 - * * * Copyright (c) 1987, 1990 Carnegie-Mellon University. * All rights reserved. @@ -80,10 +78,6 @@ * A radix tree used to quickly * perform object/offset lookups * - * A list of all pages for a given object, - * so they can be quickly deactivated at - * time of deallocation. - * * An ordered list of pages due for pageout. * * In addition, the structure contains the object @@ -235,7 +229,6 @@ struct vm_page { void *zone; } uma; } plinks; - TAILQ_ENTRY(vm_page) listq; /* pages in same object (O) */ vm_object_t object; /* which object am I in (O) */ vm_pindex_t pindex; /* offset into object (O,P) */ vm_paddr_t phys_addr; /* physical address of page (C) */ @@ -343,50 +336,6 @@ SLIST_HEAD(spglist, vm_page); extern vm_page_t bogus_page; #endif /* _KERNEL */ -extern struct mtx_padalign pa_lock[]; - -#if defined(__arm__) -#define PDRSHIFT PDR_SHIFT -#elif !defined(PDRSHIFT) -#define PDRSHIFT 21 -#endif - -#define pa_index(pa) ((pa) >> PDRSHIFT) -#define PA_LOCKPTR(pa) ((struct mtx *)(&pa_lock[pa_index(pa) % PA_LOCK_COUNT])) -#define PA_LOCKOBJPTR(pa) ((struct lock_object *)PA_LOCKPTR((pa))) -#define PA_LOCK(pa) mtx_lock(PA_LOCKPTR(pa)) -#define PA_TRYLOCK(pa) mtx_trylock(PA_LOCKPTR(pa)) -#define PA_UNLOCK(pa) mtx_unlock(PA_LOCKPTR(pa)) -#define PA_UNLOCK_COND(pa) \ - do { \ - if ((pa) != 0) { \ - PA_UNLOCK((pa)); \ - (pa) = 0; \ - } \ - } while (0) - -#define PA_LOCK_ASSERT(pa, a) mtx_assert(PA_LOCKPTR(pa), (a)) - -#if defined(KLD_MODULE) && !defined(KLD_TIED) -#define vm_page_lock(m) vm_page_lock_KBI((m), LOCK_FILE, LOCK_LINE) -#define vm_page_unlock(m) vm_page_unlock_KBI((m), LOCK_FILE, LOCK_LINE) -#define vm_page_trylock(m) vm_page_trylock_KBI((m), LOCK_FILE, LOCK_LINE) -#else /* !KLD_MODULE */ -#define vm_page_lockptr(m) (PA_LOCKPTR(VM_PAGE_TO_PHYS((m)))) -#define vm_page_lock(m) mtx_lock(vm_page_lockptr((m))) -#define vm_page_unlock(m) mtx_unlock(vm_page_lockptr((m))) -#define vm_page_trylock(m) mtx_trylock(vm_page_lockptr((m))) -#endif -#if defined(INVARIANTS) -#define vm_page_assert_locked(m) \ - vm_page_assert_locked_KBI((m), __FILE__, __LINE__) -#define vm_page_lock_assert(m, a) \ - vm_page_lock_assert_KBI((m), (a), __FILE__, __LINE__) -#else -#define vm_page_assert_locked(m) -#define vm_page_lock_assert(m, a) -#endif - /* * The vm_page's aflags are updated using atomic operations. To set or clear * these flags, the functions vm_page_aflag_set() and vm_page_aflag_clear() @@ -459,6 +408,7 @@ extern struct mtx_padalign pa_lock[]; #define PG_ZERO 0x04 /* page is zeroed */ #define PG_MARKER 0x08 /* special queue marker page */ #define PG_NODUMP 0x10 /* don't include this page in a dump */ +#define PG_NOFREE 0x20 /* page should never be freed. */ /* * Misc constants. @@ -472,6 +422,7 @@ extern struct mtx_padalign pa_lock[]; #include #include +struct pctrie_iter; /* * Each pageable resident page falls into one of five lists: @@ -511,13 +462,15 @@ extern long first_page; /* first physical page number */ vm_page_t PHYS_TO_VM_PAGE(vm_paddr_t pa); /* - * Page allocation parameters for vm_page for the functions - * vm_page_alloc(), vm_page_grab(), vm_page_alloc_contig() and - * vm_page_alloc_freelist(). Some functions support only a subset - * of the flags, and ignore others, see the flags legend. + * vm_page allocation arguments for the functions vm_page_alloc(), + * vm_page_alloc_contig(), vm_page_alloc_noobj(), vm_page_grab(), and + * vm_page_grab_pages(). Each function supports only a subset of the flags. + * See the flags legend. * - * The meaning of VM_ALLOC_ZERO differs slightly between the vm_page_alloc*() - * and the vm_page_grab*() functions. See these functions for details. + * The meaning of VM_ALLOC_ZERO varies: vm_page_alloc_noobj(), vm_page_grab(), + * and vm_page_grab_pages() guarantee that the returned pages are zeroed; in + * contrast vm_page_alloc() and vm_page_alloc_contig() do not, leaving it to + * the caller to test the page's flags for PG_ZERO. * * Bits 0 - 1 define class. * Bits 2 - 15 dedicated for flags. @@ -525,7 +478,7 @@ vm_page_t PHYS_TO_VM_PAGE(vm_paddr_t pa); * (a) - vm_page_alloc() supports the flag. * (c) - vm_page_alloc_contig() supports the flag. * (g) - vm_page_grab() supports the flag. - * (n) - vm_page_alloc_noobj() and vm_page_alloc_freelist() support the flag. + * (n) - vm_page_alloc_noobj() supports the flag. * (p) - vm_page_grab_pages() supports the flag. * Bits above 15 define the count of additional pages that the caller * intends to allocate. @@ -534,26 +487,26 @@ vm_page_t PHYS_TO_VM_PAGE(vm_paddr_t pa); #define VM_ALLOC_INTERRUPT 1 #define VM_ALLOC_SYSTEM 2 #define VM_ALLOC_CLASS_MASK 3 -#define VM_ALLOC_WAITOK 0x0008 /* (acn) Sleep and retry */ -#define VM_ALLOC_WAITFAIL 0x0010 /* (acn) Sleep and return error */ +#define VM_ALLOC_WAITOK 0x0008 /* (gnp) Sleep and retry */ +#define VM_ALLOC_WAITFAIL 0x0010 /* (acgnp) Sleep and return error */ #define VM_ALLOC_WIRED 0x0020 /* (acgnp) Allocate a wired page */ #define VM_ALLOC_ZERO 0x0040 /* (acgnp) Allocate a zeroed page */ #define VM_ALLOC_NORECLAIM 0x0080 /* (c) Do not reclaim after failure */ -#define VM_ALLOC_AVAIL0 0x0100 +#define VM_ALLOC_NOFREE 0x0100 /* (agnp) Page will never be freed */ #define VM_ALLOC_NOBUSY 0x0200 /* (acgp) Do not excl busy the page */ -#define VM_ALLOC_NOCREAT 0x0400 /* (gp) Don't create a page */ +#define VM_ALLOC_NOCREAT 0x0400 /* (gp) Do not allocate a page */ #define VM_ALLOC_AVAIL1 0x0800 -#define VM_ALLOC_IGN_SBUSY 0x1000 /* (gp) Ignore shared busy flag */ -#define VM_ALLOC_NODUMP 0x2000 /* (ag) don't include in dump */ +#define VM_ALLOC_IGN_SBUSY 0x1000 /* (gp) Ignore shared busy state */ +#define VM_ALLOC_NODUMP 0x2000 /* (acgnp) Do not include in dump */ #define VM_ALLOC_SBUSY 0x4000 /* (acgp) Shared busy the page */ #define VM_ALLOC_NOWAIT 0x8000 /* (acgnp) Do not sleep */ #define VM_ALLOC_COUNT_MAX 0xffff #define VM_ALLOC_COUNT_SHIFT 16 #define VM_ALLOC_COUNT_MASK (VM_ALLOC_COUNT(VM_ALLOC_COUNT_MAX)) -#define VM_ALLOC_COUNT(count) ({ \ - KASSERT((count) <= VM_ALLOC_COUNT_MAX, \ - ("%s: invalid VM_ALLOC_COUNT value", __func__)); \ - (count) << VM_ALLOC_COUNT_SHIFT; \ +#define VM_ALLOC_COUNT(count) ({ /* (acgn) Additional pages */ \ + KASSERT((count) <= VM_ALLOC_COUNT_MAX, \ + ("%s: invalid VM_ALLOC_COUNT value", __func__)); \ + (count) << VM_ALLOC_COUNT_SHIFT; \ }) #ifdef M_NOWAIT @@ -577,6 +530,8 @@ malloc2vm_flags(int malloc_flags) pflags |= VM_ALLOC_WAITOK; if ((malloc_flags & M_NORECLAIM)) pflags |= VM_ALLOC_NORECLAIM; + if ((malloc_flags & M_NEVERFREED)) + pflags |= VM_ALLOC_NOFREE; return (pflags); } #endif @@ -593,22 +548,9 @@ malloc2vm_flags(int malloc_flags) #define PS_ALL_VALID 0x2 #define PS_NONE_BUSY 0x4 -bool vm_page_busy_acquire(vm_page_t m, int allocflags); -void vm_page_busy_downgrade(vm_page_t m); -int vm_page_busy_tryupgrade(vm_page_t m); -bool vm_page_busy_sleep(vm_page_t m, const char *msg, int allocflags); -void vm_page_busy_sleep_unlocked(vm_object_t obj, vm_page_t m, - vm_pindex_t pindex, const char *wmesg, int allocflags); -void vm_page_free(vm_page_t m); -void vm_page_free_zero(vm_page_t m); - void vm_page_activate (vm_page_t); void vm_page_advise(vm_page_t m, int advice); vm_page_t vm_page_alloc(vm_object_t, vm_pindex_t, int); -vm_page_t vm_page_alloc_domain(vm_object_t, vm_pindex_t, int, int); -vm_page_t vm_page_alloc_after(vm_object_t, vm_pindex_t, int, vm_page_t); -vm_page_t vm_page_alloc_domain_after(vm_object_t, vm_pindex_t, int, int, - vm_page_t); vm_page_t vm_page_alloc_contig(vm_object_t object, vm_pindex_t pindex, int req, u_long npages, vm_paddr_t low, vm_paddr_t high, u_long alignment, vm_paddr_t boundary, vm_memattr_t memattr); @@ -616,8 +558,10 @@ vm_page_t vm_page_alloc_contig_domain(vm_object_t object, vm_pindex_t pindex, int domain, int req, u_long npages, vm_paddr_t low, vm_paddr_t high, u_long alignment, vm_paddr_t boundary, vm_memattr_t memattr); -vm_page_t vm_page_alloc_freelist(int, int); -vm_page_t vm_page_alloc_freelist_domain(int, int, int); +vm_page_t vm_page_alloc_domain_iter(vm_object_t object, vm_pindex_t pindex, + int domain, int req, struct pctrie_iter *pages); +vm_page_t vm_page_alloc_iter(vm_object_t object, vm_pindex_t pindex, int req, + struct pctrie_iter *pages); vm_page_t vm_page_alloc_noobj(int); vm_page_t vm_page_alloc_noobj_domain(int, int); vm_page_t vm_page_alloc_noobj_contig(int req, u_long npages, vm_paddr_t low, @@ -628,7 +572,26 @@ vm_page_t vm_page_alloc_noobj_contig_domain(int domain, int req, u_long npages, vm_memattr_t memattr); void vm_page_bits_set(vm_page_t m, vm_page_bits_t *bits, vm_page_bits_t set); bool vm_page_blacklist_add(vm_paddr_t pa, bool verbose); +bool vm_page_busy_acquire(vm_page_t m, int allocflags); +void vm_page_busy_downgrade(vm_page_t m); +int vm_page_busy_tryupgrade(vm_page_t m); +bool vm_page_busy_sleep(vm_page_t m, const char *msg, int allocflags); +void vm_page_busy_sleep_unlocked(vm_object_t obj, vm_page_t m, + vm_pindex_t pindex, const char *wmesg, int allocflags); +void vm_page_deactivate(vm_page_t m); +void vm_page_deactivate_noreuse(vm_page_t m); +void vm_page_dequeue(vm_page_t m); +void vm_page_dequeue_deferred(vm_page_t m); +void vm_page_free(vm_page_t m); +void vm_page_free_invalid(vm_page_t m); +int vm_page_free_pages_toq(struct spglist *free, bool update_wire_count); +void vm_page_free_zero(vm_page_t m); +vm_page_t vm_page_getfake(vm_paddr_t paddr, vm_memattr_t memattr); +int vm_page_grab_zero_partial(vm_object_t object, vm_pindex_t pindex, int base, + int end); vm_page_t vm_page_grab(vm_object_t, vm_pindex_t, int); +vm_page_t vm_page_grab_iter(vm_object_t object, vm_pindex_t pindex, + int allocflags, struct pctrie_iter *pages); vm_page_t vm_page_grab_unlocked(vm_object_t, vm_pindex_t, int); int vm_page_grab_pages(vm_object_t object, vm_pindex_t pindex, int allocflags, vm_page_t *ma, int count); @@ -636,37 +599,38 @@ int vm_page_grab_pages_unlocked(vm_object_t object, vm_pindex_t pindex, int allocflags, vm_page_t *ma, int count); int vm_page_grab_valid(vm_page_t *mp, vm_object_t object, vm_pindex_t pindex, int allocflags); +int vm_page_grab_valid_iter(vm_page_t *mp, vm_object_t object, + vm_pindex_t pindex, int allocflags, struct pctrie_iter *pages); int vm_page_grab_valid_unlocked(vm_page_t *mp, vm_object_t object, vm_pindex_t pindex, int allocflags); -void vm_page_deactivate(vm_page_t); -void vm_page_deactivate_noreuse(vm_page_t); -void vm_page_dequeue(vm_page_t m); -void vm_page_dequeue_deferred(vm_page_t m); -vm_page_t vm_page_find_least(vm_object_t, vm_pindex_t); -void vm_page_free_invalid(vm_page_t); -vm_page_t vm_page_getfake(vm_paddr_t paddr, vm_memattr_t memattr); void vm_page_initfake(vm_page_t m, vm_paddr_t paddr, vm_memattr_t memattr); void vm_page_init_marker(vm_page_t marker, int queue, uint16_t aflags); -void vm_page_init_page(vm_page_t m, vm_paddr_t pa, int segind); +void vm_page_init_page(vm_page_t m, vm_paddr_t pa, int segind, int pool); int vm_page_insert (vm_page_t, vm_object_t, vm_pindex_t); void vm_page_invalid(vm_page_t m); +void vm_page_iter_free(struct pctrie_iter *pages, vm_page_t m); +void vm_page_iter_init(struct pctrie_iter *, vm_object_t); +int vm_page_iter_insert(vm_page_t m, vm_object_t, vm_pindex_t, + struct pctrie_iter *); +void vm_page_iter_limit_init(struct pctrie_iter *, vm_object_t, vm_pindex_t); +bool vm_page_iter_remove(struct pctrie_iter *pages, vm_page_t m); +bool vm_page_iter_rename(struct pctrie_iter *old_pages, vm_page_t m, + vm_object_t new_object, vm_pindex_t new_pindex); void vm_page_launder(vm_page_t m); vm_page_t vm_page_lookup(vm_object_t, vm_pindex_t); vm_page_t vm_page_lookup_unlocked(vm_object_t, vm_pindex_t); -vm_page_t vm_page_next(vm_page_t m); void vm_page_pqbatch_drain(void); void vm_page_pqbatch_submit(vm_page_t m, uint8_t queue); bool vm_page_pqstate_commit(vm_page_t m, vm_page_astate_t *old, vm_page_astate_t new); -vm_page_t vm_page_prev(vm_page_t m); -bool vm_page_ps_test(vm_page_t m, int flags, vm_page_t skip_m); +bool vm_page_ps_test(vm_page_t m, int psind, int flags, vm_page_t skip_m); void vm_page_putfake(vm_page_t m); void vm_page_readahead_finish(vm_page_t m); -bool vm_page_reclaim_contig(int req, u_long npages, vm_paddr_t low, +int vm_page_reclaim_contig(int req, u_long npages, vm_paddr_t low, vm_paddr_t high, u_long alignment, vm_paddr_t boundary); -bool vm_page_reclaim_contig_domain(int domain, int req, u_long npages, +int vm_page_reclaim_contig_domain(int domain, int req, u_long npages, vm_paddr_t low, vm_paddr_t high, u_long alignment, vm_paddr_t boundary); -bool vm_page_reclaim_contig_domain_ext(int domain, int req, u_long npages, +int vm_page_reclaim_contig_domain_ext(int domain, int req, u_long npages, vm_paddr_t low, vm_paddr_t high, u_long alignment, vm_paddr_t boundary, int desired_runs); void vm_page_reference(vm_page_t m); @@ -677,7 +641,6 @@ void vm_page_release_locked(vm_page_t m, int flags); vm_page_t vm_page_relookup(vm_object_t, vm_pindex_t); bool vm_page_remove(vm_page_t); bool vm_page_remove_xbusy(vm_page_t); -int vm_page_rename(vm_page_t, vm_object_t, vm_pindex_t); void vm_page_replace(vm_page_t mnew, vm_object_t object, vm_pindex_t pindex, vm_page_t mold); int vm_page_sbusied(vm_page_t m); @@ -706,16 +669,8 @@ int vm_page_is_valid(vm_page_t, int, int); void vm_page_test_dirty(vm_page_t); vm_page_bits_t vm_page_bits(int base, int size); void vm_page_zero_invalid(vm_page_t m, boolean_t setvalid); -int vm_page_free_pages_toq(struct spglist *free, bool update_wire_count); void vm_page_dirty_KBI(vm_page_t m); -void vm_page_lock_KBI(vm_page_t m, const char *file, int line); -void vm_page_unlock_KBI(vm_page_t m, const char *file, int line); -int vm_page_trylock_KBI(vm_page_t m, const char *file, int line); -#if defined(INVARIANTS) || defined(INVARIANT_SUPPORT) -void vm_page_assert_locked_KBI(vm_page_t m, const char *file, int line); -void vm_page_lock_assert_KBI(vm_page_t m, int a, const char *file, int line); -#endif #define vm_page_busy_fetch(m) atomic_load_int(&(m)->busy_lock) @@ -732,9 +687,9 @@ void vm_page_lock_assert_KBI(vm_page_t m, int a, const char *file, int line); #define vm_page_assert_unbusied(m) \ KASSERT((vm_page_busy_fetch(m) & ~VPB_BIT_WAITERS) != \ VPB_CURTHREAD_EXCLUSIVE, \ - ("vm_page_assert_xbusied: page %p busy_lock %#x owned" \ - " by me @ %s:%d", \ - (m), (m)->busy_lock, __FILE__, __LINE__)); \ + ("vm_page_assert_unbusied: page %p busy_lock %#x owned" \ + " by me (%p) @ %s:%d", \ + (m), (m)->busy_lock, curthread, __FILE__, __LINE__)); \ #define vm_page_assert_xbusied_unchecked(m) do { \ KASSERT(vm_page_xbusied(m), \ @@ -746,8 +701,8 @@ void vm_page_lock_assert_KBI(vm_page_t m, int a, const char *file, int line); KASSERT((vm_page_busy_fetch(m) & ~VPB_BIT_WAITERS) == \ VPB_CURTHREAD_EXCLUSIVE, \ ("vm_page_assert_xbusied: page %p busy_lock %#x not owned" \ - " by me @ %s:%d", \ - (m), (m)->busy_lock, __FILE__, __LINE__)); \ + " by me (%p) @ %s:%d", \ + (m), (m)->busy_lock, curthread, __FILE__, __LINE__)); \ } while (0) #define vm_page_busied(m) \ @@ -1018,7 +973,7 @@ vm_page_none_valid(vm_page_t m) } static inline int -vm_page_domain(vm_page_t m) +vm_page_domain(vm_page_t m __numa_used) { #ifdef NUMA int domn, segind; diff --git a/lib/libc/include/generic-freebsd/vm/vm_pageout.h b/lib/libc/include/generic-freebsd/vm/vm_pageout.h index d353c28d31be..6d393195617c 100644 --- a/lib/libc/include/generic-freebsd/vm/vm_pageout.h +++ b/lib/libc/include/generic-freebsd/vm/vm_pageout.h @@ -31,8 +31,6 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)vm_pageout.h 8.2 (Berkeley) 1/12/94 - * * * Copyright (c) 1987, 1990 Carnegie-Mellon University. * All rights reserved. @@ -102,11 +100,8 @@ void vm_wait_domain(int domain); void vm_wait_min(void); void vm_wait_severe(void); -int vm_pageout_flush(vm_page_t *, int, int, int, int *, boolean_t *); +int vm_pageout_flush(vm_page_t *mc, int count, int flags, bool *eio); void vm_pageout_oom(int shortage); -void vm_swapout_run(void); -void vm_swapout_run_idle(void); - #endif /* _KERNEL */ #endif /* _VM_VM_PAGEOUT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/vm/vm_pagequeue.h b/lib/libc/include/generic-freebsd/vm/vm_pagequeue.h index 52a7b1dd39e6..2e387212cf6c 100644 --- a/lib/libc/include/generic-freebsd/vm/vm_pagequeue.h +++ b/lib/libc/include/generic-freebsd/vm/vm_pagequeue.h @@ -31,8 +31,6 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)vm_page.h 8.2 (Berkeley) 12/13/93 - * * * Copyright (c) 1987, 1990 Carnegie-Mellon University. * All rights reserved. @@ -245,23 +243,26 @@ struct vm_domain { } vmd_pgcache[VM_NFREEPOOL]; struct vmem *vmd_kernel_arena; /* (c) per-domain kva R/W arena. */ struct vmem *vmd_kernel_rwx_arena; /* (c) per-domain kva R/W/X arena. */ + struct vmem *vmd_kernel_nofree_arena; /* (c) per-domain kva NOFREE arena. */ u_int vmd_domain; /* (c) Domain number. */ u_int vmd_page_count; /* (c) Total page count. */ long vmd_segs; /* (c) bitmask of the segments */ + struct pglist vmd_nofreeq; /* (f) NOFREE page bump allocator. */ u_int __aligned(CACHE_LINE_SIZE) vmd_free_count; /* (a,f) free page count */ u_int vmd_pageout_deficit; /* (a) Estimated number of pages deficit */ uint8_t vmd_pad[CACHE_LINE_SIZE - (sizeof(u_int) * 2)]; /* Paging control variables, used within single threaded page daemon. */ struct pidctrl vmd_pid; /* Pageout controller. */ - boolean_t vmd_oom; - u_int vmd_inactive_threads; + bool vmd_oom; /* An OOM kill was requested. */ + bool vmd_helper_threads_enabled;/* Use multiple threads to scan. */ + u_int vmd_inactive_threads; /* Number of extra helper threads. */ u_int vmd_inactive_shortage; /* Per-thread shortage. */ blockcount_t vmd_inactive_running; /* Number of inactive threads. */ blockcount_t vmd_inactive_starting; /* Number of threads started. */ - volatile u_int vmd_addl_shortage; /* Shortage accumulator. */ - volatile u_int vmd_inactive_freed; /* Successful inactive frees. */ - volatile u_int vmd_inactive_us; /* Microseconds for above. */ + u_int vmd_addl_shortage; /* (a) Shortage accumulator. */ + u_int vmd_inactive_freed; /* (a) Successful inactive frees. */ + u_int vmd_inactive_us; /* (a) Microseconds for above. */ u_int vmd_inactive_pps; /* Exponential decay frees/second. */ int vmd_oom_seq; int vmd_last_active_scan; @@ -356,6 +357,12 @@ vm_batchqueue_init(struct vm_batchqueue *bq) bq->bq_cnt = 0; } +static inline bool +vm_batchqueue_empty(const struct vm_batchqueue *bq) +{ + return (bq->bq_cnt == 0); +} + static inline int vm_batchqueue_insert(struct vm_batchqueue *bq, vm_page_t m) { diff --git a/lib/libc/include/generic-freebsd/vm/vm_pager.h b/lib/libc/include/generic-freebsd/vm/vm_pager.h index 06eb99fe7d64..84324fb65e2c 100644 --- a/lib/libc/include/generic-freebsd/vm/vm_pager.h +++ b/lib/libc/include/generic-freebsd/vm/vm_pager.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)vm_pager.h 8.4 (Berkeley) 1/12/94 */ /* @@ -295,6 +293,7 @@ struct cdev_pager_ops { int (*cdev_pg_ctor)(void *handle, vm_ooffset_t size, vm_prot_t prot, vm_ooffset_t foff, struct ucred *cred, u_short *color); void (*cdev_pg_dtor)(void *handle); + void (*cdev_pg_path)(void *handle, char *path, size_t len); }; vm_object_t cdev_pager_allocate(void *handle, enum obj_type tp, @@ -302,6 +301,9 @@ vm_object_t cdev_pager_allocate(void *handle, enum obj_type tp, vm_ooffset_t foff, struct ucred *cred); vm_object_t cdev_pager_lookup(void *handle); void cdev_pager_free_page(vm_object_t object, vm_page_t m); +void cdev_mgtdev_pager_free_page(struct pctrie_iter *pages, vm_page_t m); +void cdev_mgtdev_pager_free_pages(vm_object_t object); +void cdev_pager_get_path(vm_object_t object, char *path, size_t sz); struct phys_pager_ops { int (*phys_pg_getpages)(vm_object_t vm_obj, vm_page_t *m, int count, diff --git a/lib/libc/include/generic-freebsd/vm/vm_param.h b/lib/libc/include/generic-freebsd/vm/vm_param.h index a0f6311b4c21..bc4327fa0eaf 100644 --- a/lib/libc/include/generic-freebsd/vm/vm_param.h +++ b/lib/libc/include/generic-freebsd/vm/vm_param.h @@ -31,8 +31,6 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)vm_param.h 8.1 (Berkeley) 6/11/93 - * * * Copyright (c) 1987, 1990 Carnegie-Mellon University. * All rights reserved. @@ -114,14 +112,6 @@ struct xswdev { #define KERN_OUT_OF_BOUNDS 9 #define KERN_RESTART 10 -#ifndef PA_LOCK_COUNT -#ifdef SMP -#define PA_LOCK_COUNT 32 -#else -#define PA_LOCK_COUNT 1 -#endif /* !SMP */ -#endif /* !PA_LOCK_COUNT */ - #ifndef KSTACK_MAX_PAGES #define KSTACK_MAX_PAGES 32 #endif diff --git a/lib/libc/include/generic-freebsd/vm/vm_phys.h b/lib/libc/include/generic-freebsd/vm/vm_phys.h index 6e00638d5dbe..a7e1c14c2ad4 100644 --- a/lib/libc/include/generic-freebsd/vm/vm_phys.h +++ b/lib/libc/include/generic-freebsd/vm/vm_phys.h @@ -61,25 +61,24 @@ extern int *mem_locality; void vm_phys_add_seg(vm_paddr_t start, vm_paddr_t end); vm_page_t vm_phys_alloc_contig(int domain, u_long npages, vm_paddr_t low, vm_paddr_t high, u_long alignment, vm_paddr_t boundary); -vm_page_t vm_phys_alloc_freelist_pages(int domain, int freelist, int pool, - int order); int vm_phys_alloc_npages(int domain, int pool, int npages, vm_page_t ma[]); vm_page_t vm_phys_alloc_pages(int domain, int pool, int order); int vm_phys_domain_match(int prefer, vm_paddr_t low, vm_paddr_t high); -void vm_phys_enqueue_contig(vm_page_t m, u_long npages); +void vm_phys_enqueue_contig(vm_page_t m, int pool, u_long npages); int vm_phys_fictitious_reg_range(vm_paddr_t start, vm_paddr_t end, vm_memattr_t memattr); void vm_phys_fictitious_unreg_range(vm_paddr_t start, vm_paddr_t end); vm_page_t vm_phys_fictitious_to_vm_page(vm_paddr_t pa); int vm_phys_find_range(vm_page_t bounds[], int segind, int domain, u_long npages, vm_paddr_t low, vm_paddr_t high); -void vm_phys_free_contig(vm_page_t m, u_long npages); -void vm_phys_free_pages(vm_page_t m, int order); +void vm_phys_free_contig(vm_page_t m, int pool, u_long npages); +void vm_phys_free_pages(vm_page_t m, int pool, int order); void vm_phys_init(void); vm_page_t vm_phys_paddr_to_vm_page(vm_paddr_t pa); +vm_page_t vm_phys_seg_paddr_to_vm_page(struct vm_phys_seg *seg, vm_paddr_t pa); void vm_phys_register_domains(int ndomains, struct mem_affinity *affinity, int *locality); -bool vm_phys_unfree_page(vm_page_t m); +bool vm_phys_unfree_page(vm_paddr_t pa); int vm_phys_mem_affinity(int f, int t); void vm_phys_early_add_seg(vm_paddr_t start, vm_paddr_t end); vm_paddr_t vm_phys_early_alloc(int domain, size_t alloc_size); @@ -89,7 +88,7 @@ vm_paddr_t vm_phys_avail_size(int i); bool vm_phys_is_dumpable(vm_paddr_t pa); static inline int -vm_phys_domain(vm_paddr_t pa) +vm_phys_domain(vm_paddr_t pa __numa_used) { #ifdef NUMA int i; diff --git a/lib/libc/include/generic-freebsd/vm/vm_radix.h b/lib/libc/include/generic-freebsd/vm/vm_radix.h index e309ca5e5b0a..8f7e7e7ea4d1 100644 --- a/lib/libc/include/generic-freebsd/vm/vm_radix.h +++ b/lib/libc/include/generic-freebsd/vm/vm_radix.h @@ -34,36 +34,327 @@ #include #ifdef _KERNEL +#include +#include +#include -int vm_radix_insert(struct vm_radix *rtree, vm_page_t page); void vm_radix_wait(void); -vm_page_t vm_radix_lookup(struct vm_radix *rtree, vm_pindex_t index); -vm_page_t vm_radix_lookup_ge(struct vm_radix *rtree, vm_pindex_t index); -vm_page_t vm_radix_lookup_le(struct vm_radix *rtree, vm_pindex_t index); -vm_page_t vm_radix_lookup_unlocked(struct vm_radix *rtree, vm_pindex_t index); -void vm_radix_reclaim_allnodes(struct vm_radix *rtree); -vm_page_t vm_radix_remove(struct vm_radix *rtree, vm_pindex_t index); -vm_page_t vm_radix_replace(struct vm_radix *rtree, vm_page_t newpage); void vm_radix_zinit(void); - -/* - * Each search path in the trie terminates at a leaf, which is a pointer to a - * page marked with a set 1-bit. A leaf may be associated with a null pointer - * to indicate no page there. - */ -#define VM_RADIX_ISLEAF 0x1 -#define VM_RADIX_NULL (struct vm_radix_node *)VM_RADIX_ISLEAF +void *vm_radix_node_alloc(struct pctrie *ptree); +void vm_radix_node_free(struct pctrie *ptree, void *node); +extern smr_t vm_radix_smr; static __inline void vm_radix_init(struct vm_radix *rtree) { - rtree->rt_root = VM_RADIX_NULL; + pctrie_init(&rtree->rt_trie); } static __inline bool vm_radix_is_empty(struct vm_radix *rtree) { - return (rtree->rt_root == VM_RADIX_NULL); + return (pctrie_is_empty(&rtree->rt_trie)); +} + +PCTRIE_DEFINE_SMR(VM_RADIX, vm_page, pindex, vm_radix_node_alloc, + vm_radix_node_free, vm_radix_smr); + +/* + * Inserts the key-value pair into the trie, starting search from root. + * Panics if the key already exists. + */ +static __inline int +vm_radix_insert(struct vm_radix *rtree, vm_page_t page) +{ + return (VM_RADIX_PCTRIE_INSERT(&rtree->rt_trie, page)); +} + +/* + * Inserts the key-value pair into the trie, starting search from iterator. + * Panics if the key already exists. + */ +static __inline int +vm_radix_iter_insert(struct pctrie_iter *pages, vm_page_t page) +{ + return (VM_RADIX_PCTRIE_ITER_INSERT(pages, page)); +} + +/* + * Returns the value stored at the index assuming there is an external lock. + * + * If the index is not present, NULL is returned. + */ +static __inline vm_page_t +vm_radix_lookup(struct vm_radix *rtree, vm_pindex_t index) +{ + return (VM_RADIX_PCTRIE_LOOKUP(&rtree->rt_trie, index)); +} + +/* + * Returns the value stored at the index without requiring an external lock. + * + * If the index is not present, NULL is returned. + */ +static __inline vm_page_t +vm_radix_lookup_unlocked(struct vm_radix *rtree, vm_pindex_t index) +{ + return (VM_RADIX_PCTRIE_LOOKUP_UNLOCKED(&rtree->rt_trie, index)); +} + +/* + * Returns the number of contiguous, non-NULL pages read into the ma[] + * array, without requiring an external lock. + */ +static __inline int +vm_radix_lookup_range_unlocked(struct vm_radix *rtree, vm_pindex_t index, + vm_page_t ma[], int count) +{ + return (VM_RADIX_PCTRIE_LOOKUP_RANGE_UNLOCKED(&rtree->rt_trie, index, + ma, count)); +} + +/* + * Returns the number of contiguous, non-NULL pages read into the ma[] + * array, without requiring an external lock. + */ +static __inline int +vm_radix_iter_lookup_range(struct pctrie_iter *pages, vm_pindex_t index, + vm_page_t ma[], int count) +{ + return (VM_RADIX_PCTRIE_ITER_LOOKUP_RANGE(pages, index, ma, count)); +} + +/* + * Initialize an iterator for vm_radix. + */ +static __inline void +vm_radix_iter_init(struct pctrie_iter *pages, struct vm_radix *rtree) +{ + pctrie_iter_init(pages, &rtree->rt_trie); +} + +/* + * Initialize an iterator for vm_radix. + */ +static __inline void +vm_radix_iter_limit_init(struct pctrie_iter *pages, struct vm_radix *rtree, + vm_pindex_t limit) +{ + pctrie_iter_limit_init(pages, &rtree->rt_trie, limit); +} + +/* + * Returns the value stored at the index. + * Requires that access be externally synchronized by a lock. + * + * If the index is not present, NULL is returned. + */ +static __inline vm_page_t +vm_radix_iter_lookup(struct pctrie_iter *pages, vm_pindex_t index) +{ + return (VM_RADIX_PCTRIE_ITER_LOOKUP(pages, index)); +} + +/* + * Returns the value stored 'stride' steps beyond the current position. + * Requires that access be externally synchronized by a lock. + * + * If the index is not present, NULL is returned. + */ +static __inline vm_page_t +vm_radix_iter_stride(struct pctrie_iter *pages, int stride) +{ + return (VM_RADIX_PCTRIE_ITER_STRIDE(pages, stride)); +} + +/* + * Returns the page with the least pindex that is greater than or equal to the + * specified pindex, or NULL if there are no such pages. + * + * Requires that access be externally synchronized by a lock. + */ +static __inline vm_page_t +vm_radix_lookup_ge(struct vm_radix *rtree, vm_pindex_t index) +{ + return (VM_RADIX_PCTRIE_LOOKUP_GE(&rtree->rt_trie, index)); +} + +/* + * Returns the page with the greatest pindex that is less than or equal to the + * specified pindex, or NULL if there are no such pages. + * + * Requires that access be externally synchronized by a lock. + */ +static __inline vm_page_t +vm_radix_lookup_le(struct vm_radix *rtree, vm_pindex_t index) +{ + return (VM_RADIX_PCTRIE_LOOKUP_LE(&rtree->rt_trie, index)); +} + +/* + * Remove the specified index from the trie, and return the value stored at + * that index. If the index is not present, return NULL. + */ +static __inline vm_page_t +vm_radix_remove(struct vm_radix *rtree, vm_pindex_t index) +{ + return (VM_RADIX_PCTRIE_REMOVE_LOOKUP(&rtree->rt_trie, index)); +} + +/* + * Remove the current page from the trie. + */ +static __inline void +vm_radix_iter_remove(struct pctrie_iter *pages) +{ + VM_RADIX_PCTRIE_ITER_REMOVE(pages); +} + +/* + * Reclaim all the interior nodes of the trie, and invoke the callback + * on all the pages, in order. + */ +static __inline void +vm_radix_reclaim_callback(struct vm_radix *rtree, + void (*page_cb)(vm_page_t, void *), void *arg) +{ + VM_RADIX_PCTRIE_RECLAIM_CALLBACK(&rtree->rt_trie, page_cb, arg); +} + +/* + * Initialize an iterator pointing to the page with the least pindex that is + * greater than or equal to the specified pindex, or NULL if there are no such + * pages. Return the page. + * + * Requires that access be externally synchronized by a lock. + */ +static __inline vm_page_t +vm_radix_iter_lookup_ge(struct pctrie_iter *pages, vm_pindex_t index) +{ + return (VM_RADIX_PCTRIE_ITER_LOOKUP_GE(pages, index)); +} + +/* + * Update the iterator to point to the page with the least pindex that is 'jump' + * or more greater than or equal to the current pindex, or NULL if there are no + * such pages. Return the page. + * + * Requires that access be externally synchronized by a lock. + */ +static __inline vm_page_t +vm_radix_iter_jump(struct pctrie_iter *pages, vm_pindex_t jump) +{ + return (VM_RADIX_PCTRIE_ITER_JUMP_GE(pages, jump)); +} + +/* + * Update the iterator to point to the page with the least pindex that is one or + * more greater than the current pindex, or NULL if there are no such pages. + * Return the page. + * + * Requires that access be externally synchronized by a lock. + */ +static __inline vm_page_t +vm_radix_iter_step(struct pctrie_iter *pages) +{ + return (VM_RADIX_PCTRIE_ITER_STEP_GE(pages)); +} + +/* + * Iterate over each non-NULL page from page 'start' to the end of the object. + */ +#define VM_RADIX_FOREACH_FROM(m, pages, start) \ + for (m = vm_radix_iter_lookup_ge(pages, start); m != NULL; \ + m = vm_radix_iter_step(pages)) + +/* + * Iterate over each non-NULL page from the beginning to the end of the object. + */ +#define VM_RADIX_FOREACH(m, pages) VM_RADIX_FOREACH_FROM(m, pages, 0) + +/* + * Initialize an iterator pointing to the page with the greatest pindex that is + * less than or equal to the specified pindex, or NULL if there are no such + * pages. Return the page. + * + * Requires that access be externally synchronized by a lock. + */ +static __inline vm_page_t +vm_radix_iter_lookup_le(struct pctrie_iter *pages, vm_pindex_t index) +{ + return (VM_RADIX_PCTRIE_ITER_LOOKUP_LE(pages, index)); +} + +/* + * Initialize an iterator pointing to the page with the greatest pindex that is + * less than to the specified pindex, or NULL if there are no such + * pages. Return the page. + * + * Requires that access be externally synchronized by a lock. + */ +static __inline vm_page_t +vm_radix_iter_lookup_lt(struct pctrie_iter *pages, vm_pindex_t index) +{ + return (index == 0 ? NULL : vm_radix_iter_lookup_le(pages, index - 1)); +} + +/* + * Update the iterator to point to the page with the pindex that is one greater + * than the current pindex, or NULL if there is no such page. Return the page. + * + * Requires that access be externally synchronized by a lock. + */ +static __inline vm_page_t +vm_radix_iter_next(struct pctrie_iter *pages) +{ + return (VM_RADIX_PCTRIE_ITER_NEXT(pages)); +} + +/* + * Iterate over consecutive non-NULL pages from position 'start' to first NULL + * page. + */ +#define VM_RADIX_FORALL_FROM(m, pages, start) \ + for (m = vm_radix_iter_lookup(pages, start); m != NULL; \ + m = vm_radix_iter_next(pages)) + +/* + * Iterate over consecutive non-NULL pages from the beginning to first NULL + * page. + */ +#define VM_RADIX_FORALL(m, pages) VM_RADIX_FORALL_FROM(m, pages, 0) + +/* + * Update the iterator to point to the page with the pindex that is one less + * than the current pindex, or NULL if there is no such page. Return the page. + * + * Requires that access be externally synchronized by a lock. + */ +static __inline vm_page_t +vm_radix_iter_prev(struct pctrie_iter *pages) +{ + return (VM_RADIX_PCTRIE_ITER_PREV(pages)); +} + +/* + * Return the current page. + * + * Requires that access be externally synchronized by a lock. + */ +static __inline vm_page_t +vm_radix_iter_page(struct pctrie_iter *pages) +{ + return (VM_RADIX_PCTRIE_ITER_VALUE(pages)); +} + +/* + * Replace an existing page in the trie with another one. + * Panics if there is not an old page in the trie at the new page's index. + */ +static __inline vm_page_t +vm_radix_replace(struct vm_radix *rtree, vm_page_t newpage) +{ + return (VM_RADIX_PCTRIE_REPLACE(&rtree->rt_trie, newpage)); } #endif /* _KERNEL */ diff --git a/lib/libc/include/generic-freebsd/vm/vm_reserv.h b/lib/libc/include/generic-freebsd/vm/vm_reserv.h index 271697ea25ff..52ad7176e075 100644 --- a/lib/libc/include/generic-freebsd/vm/vm_reserv.h +++ b/lib/libc/include/generic-freebsd/vm/vm_reserv.h @@ -46,15 +46,16 @@ * The following functions are only to be used by the virtual memory system. */ vm_page_t vm_reserv_alloc_contig(vm_object_t object, vm_pindex_t pindex, - int domain, int req, vm_page_t mpred, u_long npages, - vm_paddr_t low, vm_paddr_t high, u_long alignment, - vm_paddr_t boundary); + int domain, int req, u_long npages, vm_paddr_t low, + vm_paddr_t high, u_long alignment, vm_paddr_t boundary, + struct pctrie_iter *pages); vm_page_t vm_reserv_alloc_page(vm_object_t object, vm_pindex_t pindex, - int domain, int req, vm_page_t mpred); + int domain, int req, struct pctrie_iter *pages); void vm_reserv_break_all(vm_object_t object); boolean_t vm_reserv_free_page(vm_page_t m); void vm_reserv_init(void); bool vm_reserv_is_page_free(vm_page_t m); +bool vm_reserv_is_populated(vm_page_t m, int npages); int vm_reserv_level(vm_page_t m); int vm_reserv_level_iffullpop(vm_page_t m); vm_page_t vm_reserv_reclaim_contig(int domain, u_long npages, diff --git a/lib/libc/include/generic-freebsd/vm/vnode_pager.h b/lib/libc/include/generic-freebsd/vm/vnode_pager.h index 2decab026850..188b30ff885b 100644 --- a/lib/libc/include/generic-freebsd/vm/vnode_pager.h +++ b/lib/libc/include/generic-freebsd/vm/vnode_pager.h @@ -32,8 +32,6 @@ * 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. - * - * @(#)vnode_pager.h 8.1 (Berkeley) 6/11/93 */ #ifndef _VNODE_PAGER_ diff --git a/lib/libc/include/generic-freebsd/wchar.h b/lib/libc/include/generic-freebsd/wchar.h index 8a49f5419c05..b4f6504fbd06 100644 --- a/lib/libc/include/generic-freebsd/wchar.h +++ b/lib/libc/include/generic-freebsd/wchar.h @@ -78,7 +78,7 @@ typedef __size_t size_t; #if __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE #ifndef _VA_LIST_DECLARED -typedef __va_list va_list; +typedef __builtin_va_list va_list; #define _VA_LIST_DECLARED #endif #endif @@ -108,6 +108,14 @@ typedef struct __sFILE FILE; #endif struct tm; +__BEGIN_DECLS +size_t wcslen(const wchar_t *) __pure; +__END_DECLS + +#if !defined(_STANDALONE) && defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 +#include +#endif + __BEGIN_DECLS wint_t btowc(int); wint_t fgetwc(FILE *); @@ -146,7 +154,6 @@ wchar_t *wcscpy(wchar_t * __restrict, const wchar_t * __restrict); size_t wcscspn(const wchar_t *, const wchar_t *) __pure; size_t wcsftime(wchar_t * __restrict, size_t, const wchar_t * __restrict, const struct tm * __restrict); -size_t wcslen(const wchar_t *) __pure; wchar_t *wcsncat(wchar_t * __restrict, const wchar_t * __restrict, size_t); int wcsncmp(const wchar_t *, const wchar_t *, size_t) __pure; diff --git a/lib/libc/include/generic-freebsd/x86/_align.h b/lib/libc/include/generic-freebsd/x86/_align.h index c56e1e6110d2..0a06d280b6a4 100644 --- a/lib/libc/include/generic-freebsd/x86/_align.h +++ b/lib/libc/include/generic-freebsd/x86/_align.h @@ -35,8 +35,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)param.h 5.8 (Berkeley) 6/28/91 */ #ifndef _X86_INCLUDE__ALIGN_H_ diff --git a/lib/libc/include/generic-freebsd/x86/_limits.h b/lib/libc/include/generic-freebsd/x86/_limits.h index 5d0cef1a236b..50ba6e5f48e1 100644 --- a/lib/libc/include/generic-freebsd/x86/_limits.h +++ b/lib/libc/include/generic-freebsd/x86/_limits.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)limits.h 8.3 (Berkeley) 1/4/94 */ #ifndef _MACHINE__LIMITS_H_ diff --git a/lib/libc/include/generic-freebsd/x86/_types.h b/lib/libc/include/generic-freebsd/x86/_types.h index f6c95d32871c..40717048332a 100644 --- a/lib/libc/include/generic-freebsd/x86/_types.h +++ b/lib/libc/include/generic-freebsd/x86/_types.h @@ -32,9 +32,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * From: @(#)ansi.h 8.2 (Berkeley) 1/4/94 - * From: @(#)types.h 8.3 (Berkeley) 1/5/94 */ #ifndef _MACHINE__TYPES_H_ diff --git a/lib/libc/include/generic-freebsd/x86/acpica_machdep.h b/lib/libc/include/generic-freebsd/x86/acpica_machdep.h index 3e7b05a179d9..dc3322d42ede 100644 --- a/lib/libc/include/generic-freebsd/x86/acpica_machdep.h +++ b/lib/libc/include/generic-freebsd/x86/acpica_machdep.h @@ -84,6 +84,8 @@ void madt_parse_interrupt_values(void *entry, extern int madt_found_sci_override; extern int (*apei_nmi)(void); +void acpi_set_root(vm_paddr_t addr); + #endif /* _KERNEL */ #endif /* __ACPICA_MACHDEP_H__ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/x86/apicreg.h b/lib/libc/include/generic-freebsd/x86/apicreg.h index 7d30918b1dc9..3d3840f4ef3f 100644 --- a/lib/libc/include/generic-freebsd/x86/apicreg.h +++ b/lib/libc/include/generic-freebsd/x86/apicreg.h @@ -296,6 +296,8 @@ typedef struct IOAPIC ioapic_t; /* constants relating to APIC ID registers */ #define APIC_ID_MASK 0xff000000 #define APIC_ID_SHIFT 24 +#define APIC_EXT_ID_MASK 0x00fe0000 +#define APIC_EXT_ID_SHIFT 17 #define APIC_ID_CLUSTER 0xf0 #define APIC_ID_CLUSTER_ID 0x0f #define APIC_MAX_CLUSTER 0xe diff --git a/lib/libc/include/generic-freebsd/x86/apicvar.h b/lib/libc/include/generic-freebsd/x86/apicvar.h index 08a5babc6bd5..404cc3da99e1 100644 --- a/lib/libc/include/generic-freebsd/x86/apicvar.h +++ b/lib/libc/include/generic-freebsd/x86/apicvar.h @@ -196,19 +196,21 @@ extern int *apic_cpuids; /* Allow to replace the lapic_ipi_vectored implementation. */ extern void (*ipi_vectored)(u_int, int); +typedef struct ioapic *ioapic_drv_t; + void apic_register_enumerator(struct apic_enumerator *enumerator); -void *ioapic_create(vm_paddr_t addr, int32_t apic_id, int intbase); -int ioapic_disable_pin(void *cookie, u_int pin); -int ioapic_get_vector(void *cookie, u_int pin); -void ioapic_register(void *cookie); -int ioapic_remap_vector(void *cookie, u_int pin, int vector); -int ioapic_set_bus(void *cookie, u_int pin, int bus_type); -int ioapic_set_extint(void *cookie, u_int pin); -int ioapic_set_nmi(void *cookie, u_int pin); -int ioapic_set_polarity(void *cookie, u_int pin, enum intr_polarity pol); -int ioapic_set_triggermode(void *cookie, u_int pin, +ioapic_drv_t ioapic_create(vm_paddr_t addr, int32_t apic_id, int intbase); +int ioapic_disable_pin(ioapic_drv_t cookie, u_int pin); +int ioapic_get_vector(ioapic_drv_t cookie, u_int pin); +void ioapic_register(ioapic_drv_t cookie); +int ioapic_remap_vector(ioapic_drv_t cookie, u_int pin, int vector); +int ioapic_set_bus(ioapic_drv_t cookie, u_int pin, int bus_type); +int ioapic_set_extint(ioapic_drv_t cookie, u_int pin); +int ioapic_set_nmi(ioapic_drv_t cookie, u_int pin); +int ioapic_set_polarity(ioapic_drv_t cookie, u_int pin, enum intr_polarity pol); +int ioapic_set_triggermode(ioapic_drv_t cookie, u_int pin, enum intr_trigger trigger); -int ioapic_set_smi(void *cookie, u_int pin); +int ioapic_set_smi(ioapic_drv_t cookie, u_int pin); void lapic_create(u_int apic_id, int boot_cpu); void lapic_init(vm_paddr_t addr); @@ -229,9 +231,9 @@ void apic_enable_vector(u_int apic_id, u_int vector); void apic_disable_vector(u_int apic_id, u_int vector); void apic_free_vector(u_int apic_id, u_int vector, u_int irq); void lapic_calibrate_timer(void); -int lapic_enable_pmc(void); -void lapic_disable_pmc(void); -void lapic_reenable_pmc(void); +int lapic_enable_pcint(void); +void lapic_disable_pcint(void); +void lapic_reenable_pcint(void); void lapic_enable_cmc(void); int lapic_enable_mca_elvt(void); void lapic_ipi_raw(register_t icrlo, u_int dest); diff --git a/lib/libc/include/generic-freebsd/x86/bus.h b/lib/libc/include/generic-freebsd/x86/bus.h index 53ad81391c4d..194c4c60a4c3 100644 --- a/lib/libc/include/generic-freebsd/x86/bus.h +++ b/lib/libc/include/generic-freebsd/x86/bus.h @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-3-Clause AND BSD-2-ClauseE + * SPDX-License-Identifier: BSD-3-Clause AND BSD-2-Clause * * Copyright (c) KATO Takenori, 1999. * diff --git a/lib/libc/include/generic-freebsd/x86/bus_dma.h b/lib/libc/include/generic-freebsd/x86/bus_dma.h index 03fdf98814a8..2c780a6697b9 100644 --- a/lib/libc/include/generic-freebsd/x86/bus_dma.h +++ b/lib/libc/include/generic-freebsd/x86/bus_dma.h @@ -88,7 +88,7 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, /* * Free a piece of memory and it's allociated dmamap, that was allocated - * via bus_dmamem_alloc. Make the same choice for free/contigfree. + * via bus_dmamem_alloc. */ static inline void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) diff --git a/lib/libc/include/generic-freebsd/x86/busdma_impl.h b/lib/libc/include/generic-freebsd/x86/busdma_impl.h index 1c8775fb84ba..247e77544fa2 100644 --- a/lib/libc/include/generic-freebsd/x86/busdma_impl.h +++ b/lib/libc/include/generic-freebsd/x86/busdma_impl.h @@ -33,28 +33,23 @@ struct bus_dma_tag_common { struct bus_dma_impl *impl; - struct bus_dma_tag_common *parent; bus_size_t alignment; bus_addr_t boundary; bus_addr_t lowaddr; bus_addr_t highaddr; - bus_dma_filter_t *filter; - void *filterarg; bus_size_t maxsize; u_int nsegments; bus_size_t maxsegsz; int flags; bus_dma_lock_t *lockfunc; void *lockfuncarg; - int ref_count; int domain; }; struct bus_dma_impl { int (*tag_create)(bus_dma_tag_t parent, bus_size_t alignment, bus_addr_t boundary, bus_addr_t lowaddr, - bus_addr_t highaddr, bus_dma_filter_t *filter, - void *filterarg, bus_size_t maxsize, int nsegments, + bus_addr_t highaddr, bus_size_t maxsize, int nsegments, bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc, void *lockfuncarg, bus_dma_tag_t *dmat); int (*tag_destroy)(bus_dma_tag_t dmat); @@ -87,13 +82,11 @@ struct bus_dma_impl { #endif }; -int bus_dma_run_filter(struct bus_dma_tag_common *dmat, vm_paddr_t paddr); int common_bus_dma_tag_create(struct bus_dma_tag_common *parent, bus_size_t alignment, bus_addr_t boundary, bus_addr_t lowaddr, bus_addr_t highaddr, - bus_dma_filter_t *filter, void *filterarg, bus_size_t maxsize, - int nsegments, bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc, - void *lockfuncarg, size_t sz, void **dmat); + bus_size_t maxsize, int nsegments, bus_size_t maxsegsz, int flags, + bus_dma_lock_t *lockfunc, void *lockfuncarg, size_t sz, void **dmat); extern struct bus_dma_impl bus_dma_bounce_impl; diff --git a/lib/libc/include/generic-freebsd/x86/dump.h b/lib/libc/include/generic-freebsd/x86/dump.h index 0e730eaf4b13..93d208af956a 100644 --- a/lib/libc/include/generic-freebsd/x86/dump.h +++ b/lib/libc/include/generic-freebsd/x86/dump.h @@ -38,7 +38,11 @@ /* 20 phys_avail entry pairs correspond to 10 pa's */ #define DUMPSYS_MD_PA_NPAIRS 10 +#ifdef __amd64__ +#define DUMPSYS_NUM_AUX_HDRS 1 +#else #define DUMPSYS_NUM_AUX_HDRS 0 +#endif /* How often to check the dump progress bar? */ #define DUMPSYS_PB_CHECK_BITS 24 /* Every 16MB */ @@ -71,12 +75,16 @@ dumpsys_unmap_chunk(vm_paddr_t pa, size_t s, void *va) dumpsys_gen_unmap_chunk(pa, s, va); } +#ifdef __amd64__ +int dumpsys_write_aux_headers(struct dumperinfo *di); +#else static inline int dumpsys_write_aux_headers(struct dumperinfo *di) { return (dumpsys_gen_write_aux_headers(di)); } +#endif static inline int dumpsys(struct dumperinfo *di) diff --git a/lib/libc/include/generic-freebsd/x86/endian.h b/lib/libc/include/generic-freebsd/x86/endian.h index 2e20329bb9aa..d36faaf557ce 100644 --- a/lib/libc/include/generic-freebsd/x86/endian.h +++ b/lib/libc/include/generic-freebsd/x86/endian.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)endian.h 7.8 (Berkeley) 4/3/91 */ #ifndef _MACHINE_ENDIAN_H_ diff --git a/lib/libc/include/generic-freebsd/x86/float.h b/lib/libc/include/generic-freebsd/x86/float.h index 1f6845eea3f4..027082dbe4ee 100644 --- a/lib/libc/include/generic-freebsd/x86/float.h +++ b/lib/libc/include/generic-freebsd/x86/float.h @@ -27,8 +27,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)float.h 7.1 (Berkeley) 5/8/90 */ #ifndef _MACHINE_FLOAT_H_ diff --git a/lib/libc/include/generic-freebsd/x86/fpu.h b/lib/libc/include/generic-freebsd/x86/fpu.h index 8eb8eb6863a5..675183075a42 100644 --- a/lib/libc/include/generic-freebsd/x86/fpu.h +++ b/lib/libc/include/generic-freebsd/x86/fpu.h @@ -28,8 +28,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)npx.h 5.3 (Berkeley) 1/18/91 */ /* @@ -220,6 +218,13 @@ struct savefpu_ymm { */ #define fpu_enable() clts() #define fpu_disable() load_cr0(rcr0() | CR0_TS) + +bool xsave_extfeature_supported(uint64_t feature, bool supervisor); +bool xsave_extension_supported(uint64_t extension); +size_t xsave_area_hdr_offset(void); +size_t xsave_area_offset(uint64_t xstate_bv, uint64_t feature, bool compact, + bool supervisor); +size_t xsave_area_size(uint64_t xstate_bv, bool compact, bool supervisor); #endif #endif /* !_X86_FPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/x86/frame.h b/lib/libc/include/generic-freebsd/x86/frame.h index 8cacd1a714e7..422c038874c3 100644 --- a/lib/libc/include/generic-freebsd/x86/frame.h +++ b/lib/libc/include/generic-freebsd/x86/frame.h @@ -31,8 +31,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)frame.h 5.2 (Berkeley) 1/18/91 */ #ifndef _MACHINE_FRAME_H_ @@ -154,6 +152,7 @@ struct trapframe { #define TF_HASSEGS 0x1 #define TF_HASBASES 0x2 #define TF_HASFPXSTATE 0x4 +#define TF_RESERV0 0x8 /* no tlsbase in the trapframe */ #endif /* __amd64__ */ #endif /* _MACHINE_FRAME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/x86/init.h b/lib/libc/include/generic-freebsd/x86/init.h index b5c4b9168a9c..e8946ae206a8 100644 --- a/lib/libc/include/generic-freebsd/x86/init.h +++ b/lib/libc/include/generic-freebsd/x86/init.h @@ -35,10 +35,10 @@ * hypervisor environment. */ struct init_ops { - caddr_t (*parse_preload_data)(u_int64_t); + void (*parse_preload_data)(u_int64_t); void (*early_clock_source_init)(void); void (*early_delay)(int); - void (*parse_memmap)(caddr_t, vm_paddr_t *, int *); + void (*parse_memmap)(vm_paddr_t *, int *); }; extern struct init_ops init_ops; diff --git a/lib/libc/include/generic-freebsd/x86/intr_machdep.h b/lib/libc/include/generic-freebsd/x86/intr_machdep.h index 6b62eb65c847..ae90cd01e41b 100644 --- a/lib/libc/include/generic-freebsd/x86/intr_machdep.h +++ b/lib/libc/include/generic-freebsd/x86/intr_machdep.h @@ -62,8 +62,6 @@ extern u_int num_msi_irqs; */ #define MSI_INTEL_ADDR_BASE 0xfee00000 -#ifndef LOCORE - typedef void inthand_t(void); #define IDTVEC(name) __CONCAT(X,name) @@ -138,12 +136,12 @@ void elcr_write_trigger(u_int irq, enum intr_trigger trigger); #ifdef SMP void intr_add_cpu(u_int cpu); #endif -int intr_add_handler(const char *name, int vector, driver_filter_t filter, - driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep, - int domain); -int intr_config_intr(int vector, enum intr_trigger trig, +int intr_add_handler(struct intsrc *isrc, const char *name, + driver_filter_t filter, driver_intr_t handler, void *arg, + enum intr_type flags, void **cookiep, int domain); +int intr_config_intr(struct intsrc *isrc, enum intr_trigger trig, enum intr_polarity pol); -int intr_describe(u_int vector, void *ih, const char *descr); +int intr_describe(struct intsrc *isrc, void *ih, const char *descr); void intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame); u_int intr_next_cpu(int domain); struct intsrc *intr_lookup_source(int vector); @@ -165,6 +163,5 @@ int msix_release(int irq); void xen_intr_alloc_irqs(void); #endif -#endif /* !LOCORE */ #endif /* _KERNEL */ #endif /* !__X86_INTR_MACHDEP_H__ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/x86/legacyvar.h b/lib/libc/include/generic-freebsd/x86/legacyvar.h index a17e3b00427f..09ee05b11ad7 100644 --- a/lib/libc/include/generic-freebsd/x86/legacyvar.h +++ b/lib/libc/include/generic-freebsd/x86/legacyvar.h @@ -58,10 +58,14 @@ int legacy_pcib_write_ivar(device_t dev, device_t child, int which, struct resource *legacy_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags); -int legacy_pcib_adjust_resource(device_t dev, device_t child, int type, +int legacy_pcib_adjust_resource(device_t dev, device_t child, struct resource *r, rman_res_t start, rman_res_t end); -int legacy_pcib_release_resource(device_t dev, device_t child, int type, - int rid, struct resource *r); +int legacy_pcib_release_resource(device_t dev, device_t child, + struct resource *r); +int legacy_pcib_activate_resource(device_t dev, device_t child, + struct resource *r); +int legacy_pcib_deactivate_resource(device_t dev, device_t child, + struct resource *r); int legacy_pcib_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs); int legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq); diff --git a/lib/libc/include/generic-freebsd/x86/mca.h b/lib/libc/include/generic-freebsd/x86/mca.h index c5e0f8552db7..9d9b4a1d6f4b 100644 --- a/lib/libc/include/generic-freebsd/x86/mca.h +++ b/lib/libc/include/generic-freebsd/x86/mca.h @@ -44,6 +44,31 @@ struct mca_record { int mr_cpu; }; +enum mca_stat_types { + MCA_T_NONE = 0, + MCA_T_UNCLASSIFIED, + MCA_T_UCODE_ROM_PARITY, + MCA_T_EXTERNAL, + MCA_T_FRC, + MCA_T_INTERNAL_PARITY, + MCA_T_SMM_HANDLER, + MCA_T_INTERNAL_TIMER, + MCA_T_GENERIC_IO, + MCA_T_INTERNAL, + MCA_T_MEMORY, + MCA_T_TLB, + MCA_T_MEMCONTROLLER_GEN, + MCA_T_MEMCONTROLLER_RD, + MCA_T_MEMCONTROLLER_WR, + MCA_T_MEMCONTROLLER_AC, + MCA_T_MEMCONTROLLER_MS, + MCA_T_MEMCONTROLLER_OTHER, + MCA_T_CACHE, + MCA_T_BUS, + MCA_T_UNKNOWN, + MCA_T_COUNT /* Must stay last */ +}; + #ifdef _KERNEL void cmc_intr(void); diff --git a/lib/libc/include/generic-freebsd/x86/metadata.h b/lib/libc/include/generic-freebsd/x86/metadata.h index 357c8ac9ad15..dbe873842141 100644 --- a/lib/libc/include/generic-freebsd/x86/metadata.h +++ b/lib/libc/include/generic-freebsd/x86/metadata.h @@ -34,11 +34,17 @@ #define MODINFOMD_EFI_FB 0x1005 #define MODINFOMD_MODULEP 0x1006 #define MODINFOMD_VBE_FB 0x1007 +#define MODINFOMD_EFI_ARCH 0x1008 +/* + * This is not the same as the UEFI standard EFI_MEMORY_ATTRIBUTES_TABLE, though + * memory_size / descritpr_size entries of EFI_MEMORY_DESCRIPTORS follow this table + * starting at a 16-byte alignment. + */ struct efi_map_header { - uint64_t memory_size; - uint64_t descriptor_size; - uint32_t descriptor_version; + uint64_t memory_size; /* Numnber of bytes that follow */ + uint64_t descriptor_size; /* Size of each EFI_MEMORY_DESCRIPTOR */ + uint32_t descriptor_version; /* Currently '1' */ }; struct efi_fb { diff --git a/lib/libc/include/generic-freebsd/x86/mptable.h b/lib/libc/include/generic-freebsd/x86/mptable.h index ed9c7ddea70b..7a5334ab59b8 100644 --- a/lib/libc/include/generic-freebsd/x86/mptable.h +++ b/lib/libc/include/generic-freebsd/x86/mptable.h @@ -188,16 +188,12 @@ typedef struct CBASMENTRY { #ifdef _KERNEL struct mptable_hostb_softc { -#ifdef NEW_PCIB struct pcib_host_resources sc_host_res; int sc_decodes_vga_io; int sc_decodes_isa_io; -#endif }; -#ifdef NEW_PCIB void mptable_pci_host_res_init(device_t pcib); -#endif int mptable_pci_probe_table(int bus); int mptable_pci_route_interrupt(device_t pcib, device_t dev, int pin); #endif diff --git a/lib/libc/include/generic-freebsd/x86/pci_cfgreg.h b/lib/libc/include/generic-freebsd/x86/pci_cfgreg.h index df03d454b45f..0a331d384c0f 100644 --- a/lib/libc/include/generic-freebsd/x86/pci_cfgreg.h +++ b/lib/libc/include/generic-freebsd/x86/pci_cfgreg.h @@ -58,15 +58,12 @@ extern int cfgmech; rman_res_t hostb_alloc_start(int type, rman_res_t start, rman_res_t end, rman_res_t count); int pcie_cfgregopen(uint64_t base, uint16_t domain, uint8_t minbus, uint8_t maxbus); int pci_cfgregopen(void); -u_int32_t pci_cfgregread_domain(int domain, int bus, int slot, int func, int reg, int bytes); -void pci_cfgregwrite_domain(int domain, int bus, int slot, int func, int reg, u_int32_t data, int bytes); +u_int32_t pci_cfgregread(int domain, int bus, int slot, int func, int reg, int bytes); +void pci_cfgregwrite(int domain, int bus, int slot, int func, int reg, u_int32_t data, int bytes); #ifdef __HAVE_PIR void pci_pir_open(void); int pci_pir_probe(int bus, int require_parse); int pci_pir_route_interrupt(int bus, int device, int func, int pin); #endif -#define pci_cfgregread pci_cfgregread_domain -#define pci_cfgregwrite pci_cfgregwrite_domain - #endif /* !__X86_PCI_CFGREG_H__ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/x86/psl.h b/lib/libc/include/generic-freebsd/x86/psl.h index e60c767b2a5f..38d9c84cd60b 100644 --- a/lib/libc/include/generic-freebsd/x86/psl.h +++ b/lib/libc/include/generic-freebsd/x86/psl.h @@ -30,8 +30,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)psl.h 5.2 (Berkeley) 1/18/91 */ #ifndef _MACHINE_PSL_H_ diff --git a/lib/libc/include/generic-freebsd/x86/ptrace.h b/lib/libc/include/generic-freebsd/x86/ptrace.h index ee0977abb975..6a278413cc0c 100644 --- a/lib/libc/include/generic-freebsd/x86/ptrace.h +++ b/lib/libc/include/generic-freebsd/x86/ptrace.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)ptrace.h 8.1 (Berkeley) 6/11/93 */ #ifndef _MACHINE_PTRACE_H_ @@ -56,6 +54,8 @@ #define PT_SETFSBASE (PT_FIRSTMACH + 8) #define PT_GETGSBASE (PT_FIRSTMACH + 9) #define PT_SETGSBASE (PT_FIRSTMACH + 10) +#define PT_GETTLSBASE (PT_FIRSTMACH + 11) +#define PT_SETTLSBASE (PT_FIRSTMACH + 12) /* Argument structure for PT_GETXSTATE_INFO. */ struct ptrace_xstate_info { diff --git a/lib/libc/include/generic-freebsd/x86/reg.h b/lib/libc/include/generic-freebsd/x86/reg.h index 35c2f9a15e65..31b9b3841fd7 100644 --- a/lib/libc/include/generic-freebsd/x86/reg.h +++ b/lib/libc/include/generic-freebsd/x86/reg.h @@ -31,8 +31,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)reg.h 5.5 (Berkeley) 1/18/91 */ #ifndef _MACHINE_REG_H_ diff --git a/lib/libc/include/generic-freebsd/x86/segments.h b/lib/libc/include/generic-freebsd/x86/segments.h index a51e8affbbd3..7332e4be6ab5 100644 --- a/lib/libc/include/generic-freebsd/x86/segments.h +++ b/lib/libc/include/generic-freebsd/x86/segments.h @@ -31,8 +31,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)segments.h 7.1 (Berkeley) 5/9/91 */ #ifndef _X86_SEGMENTS_H_ diff --git a/lib/libc/include/generic-freebsd/x86/signal.h b/lib/libc/include/generic-freebsd/x86/signal.h index 2d43dfd25bcc..4e15bee2e91c 100644 --- a/lib/libc/include/generic-freebsd/x86/signal.h +++ b/lib/libc/include/generic-freebsd/x86/signal.h @@ -28,8 +28,6 @@ * 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. - * - * @(#)signal.h 8.1 (Berkeley) 6/11/93 */ #ifndef _X86_SIGNAL_H diff --git a/lib/libc/include/generic-freebsd/x86/specialreg.h b/lib/libc/include/generic-freebsd/x86/specialreg.h index deddda0a3bad..6a482d94f0b6 100644 --- a/lib/libc/include/generic-freebsd/x86/specialreg.h +++ b/lib/libc/include/generic-freebsd/x86/specialreg.h @@ -27,8 +27,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)specialreg.h 7.1 (Berkeley) 5/9/91 */ #ifndef _MACHINE_SPECIALREG_H_ @@ -125,6 +123,7 @@ #define XFEATURE_ENABLED_OPMASK 0x00000020 #define XFEATURE_ENABLED_ZMM_HI256 0x00000040 #define XFEATURE_ENABLED_HI16_ZMM 0x00000080 +#define XFEATURE_ENABLED_PT 0x00000100 #define XFEATURE_ENABLED_PKRU 0x00000200 #define XFEATURE_ENABLED_TILECONFIG 0x00020000 #define XFEATURE_ENABLED_TILEDATA 0x00040000 @@ -215,6 +214,7 @@ #define CPUPT_MTC (1 << 3) /* MTC Supported */ #define CPUPT_PRW (1 << 4) /* PTWRITE Supported */ #define CPUPT_PWR (1 << 5) /* Power Event Trace Supported */ +#define CPUPT_DIS_TNT (1 << 8) /* TNT disable supported */ /* Leaf 0 ecx. */ #define CPUPT_TOPA (1 << 0) /* ToPA Output Supported */ @@ -388,6 +388,14 @@ #define CPUID_EXTSTATE_XINUSE 0x00000004 #define CPUID_EXTSTATE_XSAVES 0x00000008 +/* + * CPUID instruction 0xd Processor Extended State Enumeration + * Sub-leaf > 1 ecx info + */ +#define CPUID_EXTSTATE_SUPERVISOR 0x00000001 +#define CPUID_EXTSTATE_ALIGNED 0x00000002 +#define CPUID_EXTSTATE_XFD_SUPPORTED 0x00000004 + /* * AMD extended function 8000_0007h ebx info */ @@ -648,6 +656,12 @@ #define MSR_PAT 0x277 #define MSR_MC0_CTL2 0x280 #define MSR_MTRRdefType 0x2ff +#define MSR_IA_GLOBAL_STATUS 0x38E +#define MSR_IA_GLOBAL_CTRL 0x38F +#define MSR_IA_GLOBAL_OVF_CTRL 0x390 +#define MSR_IA_GLOBAL_STATUS_RESET 0x390 +#define MSR_IA_GLOBAL_STATUS_SET 0x391 +#define GLOBAL_STATUS_FLAG_TRACETOPAPMI (1ULL << 55) #define MSR_MC0_CTL 0x400 #define MSR_MC0_STATUS 0x401 #define MSR_MC0_ADDR 0x402 @@ -775,6 +789,7 @@ #define RTIT_CTL_ADDR2_CFG_M (0xfULL << RTIT_CTL_ADDR2_CFG_S) #define RTIT_CTL_ADDR3_CFG_S 44 #define RTIT_CTL_ADDR3_CFG_M (0xfULL << RTIT_CTL_ADDR3_CFG_S) +#define RTIT_CTL_DIS_TNT (1ULL << 55) #define MSR_IA32_RTIT_STATUS 0x571 /* Tracing Status Register (R/W) */ #define RTIT_STATUS_FILTEREN (1 << 0) #define RTIT_STATUS_CONTEXTEN (1 << 1) @@ -991,7 +1006,7 @@ #define CCR4 0xe8 #define CCR4_IOMASK 0x07 -#define CCR4_MEM 0x08 /* Enables momory bypassing */ +#define CCR4_MEM 0x08 /* Enables memory bypassing */ #define CCR4_DTE 0x10 /* Enables directory table entry cache */ #define CCR4_FASTFPE 0x20 /* Fast FPU exception */ #define CCR4_CPUID 0x80 /* Enables CPUID instruction */ @@ -1011,7 +1026,7 @@ #define PCR0_RSTK 0x01 /* Enables return stack */ #define PCR0_BTB 0x02 /* Enables branch target buffer */ #define PCR0_LOOP 0x04 /* Enables loop */ -#define PCR0_AIS 0x08 /* Enables all instrcutions stalled to +#define PCR0_AIS 0x08 /* Enables all instructions stalled to serialize pipe. */ #define PCR0_MLR 0x10 /* Enables reordering of misaligned loads */ #define PCR0_BTBRT 0x40 /* Enables BTB test register. */ @@ -1165,7 +1180,7 @@ /* * The region control registers specify the attributes associated with - * the ARRx addres regions. + * the ARRx address regions. */ #define RCR0 0xdc #define RCR1 0xdd diff --git a/lib/libc/include/generic-freebsd/x86/sysarch.h b/lib/libc/include/generic-freebsd/x86/sysarch.h index 7f897caa4329..dc22c3636a21 100644 --- a/lib/libc/include/generic-freebsd/x86/sysarch.h +++ b/lib/libc/include/generic-freebsd/x86/sysarch.h @@ -61,6 +61,9 @@ #define AMD64_GET_XFPUSTATE 132 #define AMD64_SET_PKRU 133 #define AMD64_CLEAR_PKRU 134 +#define AMD64_GET_TLSBASE 135 +#define AMD64_SET_TLSBASE 136 +#define AMD64_DISABLE_TLSBASE 137 /* Flags for AMD64_SET_PKRU */ #define AMD64_PKRU_EXCL 0x0001 @@ -140,6 +143,7 @@ int amd64_get_fsbase(void **); int amd64_get_gsbase(void **); int amd64_set_fsbase(void *); int amd64_set_gsbase(void *); +int amd64_set_tlsbase(void *); int x86_pkru_get_perm(unsigned int keyidx, int *access, int *modify); int x86_pkru_set_perm(unsigned int keyidx, int access, int modify); int x86_pkru_protect_range(void *addr, unsigned long len, unsigned int keyidx, diff --git a/lib/libc/include/generic-freebsd/x86/tls.h b/lib/libc/include/generic-freebsd/x86/tls.h index fe42da8c4952..a4f54258a29c 100644 --- a/lib/libc/include/generic-freebsd/x86/tls.h +++ b/lib/libc/include/generic-freebsd/x86/tls.h @@ -36,13 +36,23 @@ struct pthread; +struct dtv_slot { + char *dtvs_tls; +}; + +struct dtv { + uintptr_t dtv_gen; + uintptr_t dtv_size; + struct dtv_slot dtv_slots[]; +}; + /* * Variant II tcb, first two members are required by rtld, * %fs (amd64) / %gs (i386) points to the structure. */ struct tcb { struct tcb *tcb_self; /* required by rtld */ - uintptr_t *tcb_dtv; /* required by rtld */ + struct dtv *tcb_dtv; /* required by rtld */ struct pthread *tcb_thread; }; @@ -59,7 +69,7 @@ static __inline void _tcb_set(struct tcb *tcb) { #ifdef __amd64__ - amd64_set_fsbase(tcb); + amd64_set_tlsbase(tcb); #else i386_set_gsbase(tcb); #endif diff --git a/lib/libc/include/generic-freebsd/x86/trap.h b/lib/libc/include/generic-freebsd/x86/trap.h index d0986944d024..a17cc44f0c27 100644 --- a/lib/libc/include/generic-freebsd/x86/trap.h +++ b/lib/libc/include/generic-freebsd/x86/trap.h @@ -30,8 +30,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)trap.h 5.4 (Berkeley) 5/9/91 */ #ifndef _MACHINE_TRAP_H_ diff --git a/lib/libc/include/generic-freebsd/x86/ucode.h b/lib/libc/include/generic-freebsd/x86/ucode.h index b13a8b94a981..9d258b13698f 100644 --- a/lib/libc/include/generic-freebsd/x86/ucode.h +++ b/lib/libc/include/generic-freebsd/x86/ucode.h @@ -31,6 +31,12 @@ #ifndef _MACHINE_UCODE_H_ #define _MACHINE_UCODE_H_ +#ifdef _KERNEL +#include +#else +#include +#endif + struct ucode_intel_header { uint32_t header_version; int32_t update_revision; @@ -56,7 +62,14 @@ struct ucode_intel_extsig_table { } entries[0]; }; -int ucode_intel_load(void *data, bool unsafe, +typedef enum { SAFE, UNSAFE, EARLY } ucode_load_how; + +const void *ucode_amd_find(const char *path, uint32_t signature, + uint32_t *revision, const uint8_t *fw_data, size_t fw_size, + size_t *selected_sizep); +int ucode_intel_load(const void *data, ucode_load_how unsafe, + uint64_t *nrevp, uint64_t *orevp); +int ucode_amd_load(const void *data, ucode_load_how how, uint64_t *nrevp, uint64_t *orevp); size_t ucode_load_bsp(uintptr_t free); void ucode_load_ap(int cpu); diff --git a/lib/libc/include/generic-freebsd/x86/ucontext.h b/lib/libc/include/generic-freebsd/x86/ucontext.h index 78ed7c6deced..ee13d85dcc76 100644 --- a/lib/libc/include/generic-freebsd/x86/ucontext.h +++ b/lib/libc/include/generic-freebsd/x86/ucontext.h @@ -99,7 +99,9 @@ typedef struct __mcontext { #define _MC_HASSEGS 0x1 #define _MC_HASBASES 0x2 #define _MC_HASFPXSTATE 0x4 -#define _MC_FLAG_MASK (_MC_HASSEGS | _MC_HASBASES | _MC_HASFPXSTATE) +#define _MC_HASTLSBASE 0x8 +#define _MC_FLAG_MASK (_MC_HASSEGS | _MC_HASBASES | _MC_HASFPXSTATE | \ + _MC_HASTLSBASE) typedef struct __mcontext { /* @@ -158,7 +160,9 @@ typedef struct __mcontext { __register_t mc_xfpustate; __register_t mc_xfpustate_len; - long mc_spare[4]; + __register_t mc_tlsbase; + + long mc_spare[3]; } mcontext_t; #endif /* __amd64__ */ diff --git a/lib/libc/include/generic-freebsd/x86/vmware.h b/lib/libc/include/generic-freebsd/x86/vmware.h index 6c8b53cfe3e0..8a44eed6ad06 100644 --- a/lib/libc/include/generic-freebsd/x86/vmware.h +++ b/lib/libc/include/generic-freebsd/x86/vmware.h @@ -31,19 +31,23 @@ #define VMW_HVPORT 0x5658 #define VMW_HVCMD_GETVERSION 10 +#define VMW_HVCMD_GUESTRPC 30 #define VMW_HVCMD_GETHZ 45 #define VMW_HVCMD_GETVCPU_INFO 68 +#define VMW_HVCMD_DEFAULT_PARAM UINT_MAX + #define VMW_VCPUINFO_LEGACY_X2APIC (1 << 3) #define VMW_VCPUINFO_VCPU_RESERVED (1 << 31) static __inline void -vmware_hvcall(u_int cmd, u_int *p) +vmware_hvcall(int chan, u_int cmd, u_int param, u_int *p) { __asm __volatile("inl %w3, %0" : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) - : "0" (VMW_HVMAGIC), "1" (UINT_MAX), "2" (cmd), "3" (VMW_HVPORT) + : "0" (VMW_HVMAGIC), "1" (param), "2" (cmd), + "3" (VMW_HVPORT | (chan << 16)) : "memory"); } diff --git a/lib/libc/include/generic-freebsd/x86/vmware_guestrpc.h b/lib/libc/include/generic-freebsd/x86/vmware_guestrpc.h new file mode 100644 index 000000000000..c6e2dacb28e7 --- /dev/null +++ b/lib/libc/include/generic-freebsd/x86/vmware_guestrpc.h @@ -0,0 +1,37 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2015-2024, Juniper Networks, Inc. + * + * 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 _X86_VMWARE_GUESTRPC_H_ +#define _X86_VMWARE_GUESTRPC_H_ + +struct sbuf; + +int vmware_guestrpc_cmd(struct sbuf *sbufp); +int vmware_guestrpc_set_guestinfo(const char *keyword, const char *val); +int vmware_guestrpc_get_guestinfo(const char *keyword, struct sbuf *sbufp); + +#endif /* _X86_VMWARE_GUESTRPC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/x86/x86_ieeefp.h b/lib/libc/include/generic-freebsd/x86/x86_ieeefp.h index 517b2af4329c..042ddcf2169a 100644 --- a/lib/libc/include/generic-freebsd/x86/x86_ieeefp.h +++ b/lib/libc/include/generic-freebsd/x86/x86_ieeefp.h @@ -32,8 +32,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#) ieeefp.h 1.0 (Berkeley) 9/23/93 */ #ifndef _X86_X86_IEEEFP_H_ diff --git a/lib/libc/include/generic-freebsd/x86/x86_var.h b/lib/libc/include/generic-freebsd/x86/x86_var.h index bde695359880..530786a16144 100644 --- a/lib/libc/include/generic-freebsd/x86/x86_var.h +++ b/lib/libc/include/generic-freebsd/x86/x86_var.h @@ -50,6 +50,7 @@ extern u_int cpu_clflush_line_size; extern u_int cpu_stdext_feature; extern u_int cpu_stdext_feature2; extern u_int cpu_stdext_feature3; +extern u_int cpu_stdext_feature4; extern uint64_t cpu_ia32_arch_caps; extern u_int cpu_high; extern u_int cpu_id; @@ -62,6 +63,7 @@ extern char cpu_vendor[]; extern char cpu_model[]; extern u_int cpu_vendor_id; extern u_int cpu_mon_mwait_flags; +extern u_int cpu_mon_mwait_edx; extern u_int cpu_mon_min_size; extern u_int cpu_mon_max_size; extern u_int cpu_maxphyaddr; @@ -147,7 +149,9 @@ void zenbleed_sanitize_enable(void); void zenbleed_check_and_apply(bool all_cpus); void nmi_call_kdb(u_int cpu, u_int type, struct trapframe *frame); void nmi_call_kdb_smp(u_int type, struct trapframe *frame); -void nmi_handle_intr(u_int type, struct trapframe *frame); +void nmi_register_handler(int (*handler)(struct trapframe *)); +void nmi_remove_handler(int (*handler)(struct trapframe *)); +void nmi_handle_intr(struct trapframe *frame); void pagecopy(void *from, void *to); void printcpuinfo(void); int pti_get_default(void); diff --git a/lib/libc/include/generic-openbsd/a.out.h b/lib/libc/include/generic-openbsd/a.out.h new file mode 100644 index 000000000000..2b6574f4e684 --- /dev/null +++ b/lib/libc/include/generic-openbsd/a.out.h @@ -0,0 +1,156 @@ +/* $OpenBSD: a.out.h,v 1.4 2024/10/16 18:47:48 miod Exp $ */ +/* $NetBSD: a.out.h,v 1.15 1994/10/26 00:55:42 cgd Exp $ */ + +/*- + * Copyright (c) 1993 Theo de Raadt + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)a.out.h 5.6 (Berkeley) 4/30/91 + */ + +#ifndef _AOUT_H_ +#define _AOUT_H_ + +/* + * Legacy a.out structures and defines. + */ + +/* + * Header prepended to each a.out file. + * only manipulate the a_midmag field via the + * N_SETMAGIC/N_GET{MAGIC,MID,FLAG} macros below. + */ +struct exec { + u_int32_t a_midmag; /* htonl(flags<<26|mid<<16|magic) */ + u_int32_t a_text; /* text segment size */ + u_int32_t a_data; /* initialized data size */ + u_int32_t a_bss; /* uninitialized data size */ + u_int32_t a_syms; /* symbol table size */ + u_int32_t a_entry; /* entry point */ + u_int32_t a_trsize; /* text relocation size */ + u_int32_t a_drsize; /* data relocation size */ +}; + +/* a_magic */ +#define OMAGIC 0407 /* old impure format */ +#define NMAGIC 0410 /* read-only text */ +#define ZMAGIC 0413 /* demand load format */ +#define QMAGIC 0314 /* "compact" demand load format; deprecated */ + +/* + * a_flags + */ +#define EX_DYNAMIC 0x20 +#define EX_PIC 0x10 +#define EX_DPMASK 0x30 +/* + * Interpretation of the (a_flags & EX_DPMASK) bits: + * + * 00 traditional executable or object file + * 01 object file contains PIC code (set by `as -k') + * 10 dynamic executable + * 11 position independent executable image + * (eg. a shared library) + * + */ + +/* + * The a.out structure's a_midmag field is a network-byteorder encoding + * of this int + * FFFFFFmmmmmmmmmmMMMMMMMMMMMMMMMM + * Where `F' is 6 bits of flag like EX_DYNAMIC, + * `m' is 10 bits of machine-id like MID_I386, and + * `M' is 16 bits worth of magic number, ie. ZMAGIC. + * The macros below will set/get the needed fields. + */ +#define N_GETMAGIC(ex) \ + ( (((ex).a_midmag)&0xffff0000) ? (ntohl(((ex).a_midmag))&0xffff) : ((ex).a_midmag)) +#define N_GETMAGIC2(ex) \ + ( (((ex).a_midmag)&0xffff0000) ? (ntohl(((ex).a_midmag))&0xffff) : \ + (((ex).a_midmag) | 0x10000) ) +#define N_GETMID(ex) \ + ( (((ex).a_midmag)&0xffff0000) ? ((ntohl(((ex).a_midmag))>>16)&0x03ff) : MID_ZERO ) +#define N_GETFLAG(ex) \ + ( (((ex).a_midmag)&0xffff0000) ? ((ntohl(((ex).a_midmag))>>26)&0x3f) : 0 ) +#define N_SETMAGIC(ex,mag,mid,flag) \ + ( (ex).a_midmag = htonl( (((flag)&0x3f)<<26) | (((mid)&0x03ff)<<16) | \ + (((mag)&0xffff)) ) ) + +#define N_ALIGN(ex,x) \ + (N_GETMAGIC(ex) == ZMAGIC || N_GETMAGIC(ex) == QMAGIC ? \ + ((x) + __LDPGSZ - 1) & ~(__LDPGSZ - 1) : (x)) + +/* Valid magic number check. */ +#define N_BADMAG(ex) \ + (N_GETMAGIC(ex) != NMAGIC && N_GETMAGIC(ex) != OMAGIC && \ + N_GETMAGIC(ex) != ZMAGIC && N_GETMAGIC(ex) != QMAGIC) + +/* Address of the bottom of the text segment. */ +#define N_TXTADDR(ex) (N_GETMAGIC2(ex) == (ZMAGIC|0x10000) ? 0 : __LDPGSZ) + +/* Address of the bottom of the data segment. */ +#define N_DATADDR(ex) \ + (N_GETMAGIC(ex) == OMAGIC ? N_TXTADDR(ex) + (ex).a_text : \ + (N_TXTADDR(ex) + (ex).a_text + __LDPGSZ - 1) & ~(__LDPGSZ - 1)) + +/* Address of the bottom of the bss segment. */ +#define N_BSSADDR(ex) \ + (N_DATADDR(ex) + (ex).a_data) + +/* Text segment offset. */ +#define N_TXTOFF(ex) \ + ( N_GETMAGIC2(ex)==ZMAGIC || N_GETMAGIC2(ex)==(QMAGIC|0x10000) ? \ + 0 : (N_GETMAGIC2(ex)==(ZMAGIC|0x10000) ? __LDPGSZ : \ + sizeof(struct exec)) ) + +/* Data segment offset. */ +#define N_DATOFF(ex) \ + N_ALIGN(ex, N_TXTOFF(ex) + (ex).a_text) + +/* Text relocation table offset. */ +#define N_TRELOFF(ex) \ + (N_DATOFF(ex) + (ex).a_data) + +/* Data relocation table offset. */ +#define N_DRELOFF(ex) \ + (N_TRELOFF(ex) + (ex).a_trsize) + +/* Symbol table offset. */ +#define N_SYMOFF(ex) \ + (N_DRELOFF(ex) + (ex).a_drsize) + +/* String table offset. */ +#define N_STROFF(ex) \ + (N_SYMOFF(ex) + (ex).a_syms) + +#include + +#define _AOUT_INCLUDE_ +#include + +#endif /* !_AOUT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ar.h b/lib/libc/include/generic-openbsd/ar.h new file mode 100644 index 000000000000..f841ae887218 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ar.h @@ -0,0 +1,66 @@ +/* $OpenBSD: ar.h,v 1.3 2003/06/02 19:34:12 millert Exp $ */ +/* $NetBSD: ar.h,v 1.4 1994/10/26 00:55:43 cgd Exp $ */ + +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * This code is derived from software contributed to Berkeley by + * Hugh Smith at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ar.h 8.2 (Berkeley) 1/21/94 + */ + +#ifndef _AR_H_ +#define _AR_H_ + +/* Pre-4BSD archives had these magic numbers in them. */ +#define OARMAG1 0177555 +#define OARMAG2 0177545 + +#define ARMAG "!\n" /* ar "magic number" */ +#define SARMAG 8 /* strlen(ARMAG); */ + +#define AR_EFMT1 "#1/" /* extended format #1 */ + +struct ar_hdr { + char ar_name[16]; /* name */ + char ar_date[12]; /* modification time */ + char ar_uid[6]; /* user id */ + char ar_gid[6]; /* group id */ + char ar_mode[8]; /* octal file permissions */ + char ar_size[10]; /* size in bytes */ +#define ARFMAG "`\n" + char ar_fmag[2]; /* consistency check */ +}; + +#endif /* !_AR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/arpa/ftp.h b/lib/libc/include/generic-openbsd/arpa/ftp.h new file mode 100644 index 000000000000..49a3a72ca26d --- /dev/null +++ b/lib/libc/include/generic-openbsd/arpa/ftp.h @@ -0,0 +1,108 @@ +/* $OpenBSD: ftp.h,v 1.3 2003/06/02 19:34:12 millert Exp $ */ +/* $NetBSD: ftp.h,v 1.3 1994/10/26 00:56:43 cgd Exp $ */ + +/* + * Copyright (c) 1983, 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ftp.h 5.6 (Berkeley) 4/3/91 + */ + +#ifndef _FTP_H_ +#define _FTP_H_ + +/* Definitions for FTP; see RFC-765. */ + +/* + * Reply codes. + */ +#define PRELIM 1 /* positive preliminary */ +#define COMPLETE 2 /* positive completion */ +#define CONTINUE 3 /* positive intermediate */ +#define TRANSIENT 4 /* transient negative completion */ +#define ERROR 5 /* permanent negative completion */ + +/* + * Type codes + */ +#define TYPE_A 1 /* ASCII */ +#define TYPE_E 2 /* EBCDIC */ +#define TYPE_I 3 /* image */ +#define TYPE_L 4 /* local byte size */ + +#ifdef FTP_NAMES +char *typenames[] = {"0", "ASCII", "EBCDIC", "Image", "Local" }; +#endif + +/* + * Form codes + */ +#define FORM_N 1 /* non-print */ +#define FORM_T 2 /* telnet format effectors */ +#define FORM_C 3 /* carriage control (ASA) */ +#ifdef FTP_NAMES +char *formnames[] = {"0", "Nonprint", "Telnet", "Carriage-control" }; +#endif + +/* + * Structure codes + */ +#define STRU_F 1 /* file (no record structure) */ +#define STRU_R 2 /* record structure */ +#define STRU_P 3 /* page structure */ +#ifdef FTP_NAMES +char *strunames[] = {"0", "File", "Record", "Page" }; +#endif + +/* + * Mode types + */ +#define MODE_S 1 /* stream */ +#define MODE_B 2 /* block */ +#define MODE_C 3 /* compressed */ +#ifdef FTP_NAMES +char *modenames[] = {"0", "Stream", "Block", "Compressed" }; +#endif + +/* + * Record Tokens + */ +#define REC_ESC '\377' /* Record-mode Escape */ +#define REC_EOR '\001' /* Record-mode End-of-Record */ +#define REC_EOF '\002' /* Record-mode End-of-File */ + +/* + * Block Header + */ +#define BLK_EOR 0x80 /* Block is End-of-Record */ +#define BLK_EOF 0x40 /* Block is End-of-File */ +#define BLK_ERRORS 0x20 /* Block is suspected of containing errors */ +#define BLK_RESTART 0x10 /* Block is Restart Marker */ + +#define BLK_BYTECOUNT 2 /* Bytes in this block */ + +#endif /* !_FTP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/arpa/inet.h b/lib/libc/include/generic-openbsd/arpa/inet.h new file mode 100644 index 000000000000..85e665b8f7c4 --- /dev/null +++ b/lib/libc/include/generic-openbsd/arpa/inet.h @@ -0,0 +1,147 @@ +/* $OpenBSD: inet.h,v 1.21 2017/02/04 19:16:25 guenther Exp $ */ + +/* + * ++Copyright++ 1983, 1993 + * - + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * - + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * - + * --Copyright-- + */ + +/* + * @(#)inet.h 8.1 (Berkeley) 6/2/93 + * $From: inet.h,v 8.6 1996/08/08 06:54:29 vixie Exp $ + */ + +#ifndef _INET_H_ +#define _INET_H_ + +/* External definitions for functions in inet(3) */ + +#include +#include + +#ifndef htons +#define htons(x) __htobe16(x) +#define htonl(x) __htobe32(x) +#define ntohs(x) __htobe16(x) +#define ntohl(x) __htobe32(x) +#endif + +#ifndef _UINT16_T_DEFINED_ +#define _UINT16_T_DEFINED_ +typedef __uint16_t uint16_t; +#endif + +#ifndef _UINT32_T_DEFINED_ +#define _UINT32_T_DEFINED_ +typedef __uint32_t uint32_t; +#endif + +#ifndef _SOCKLEN_T_DEFINED_ +#define _SOCKLEN_T_DEFINED_ +typedef __socklen_t socklen_t; /* length type for network syscalls */ +#endif + +#ifndef _IN_TYPES_DEFINED_ +#define _IN_TYPES_DEFINED_ +typedef __in_addr_t in_addr_t; /* base type for internet address */ +typedef __in_port_t in_port_t; /* IP port type */ +#endif + +/* + * Buffer lengths for strings containing printable IP addresses + */ +#ifndef INET_ADDRSTRLEN +#define INET_ADDRSTRLEN 16 +#endif +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 46 +#endif + +#ifndef _IN_ADDR_DECLARED +#define _IN_ADDR_DECLARED +/* + * IP Version 4 Internet address (a structure for historical reasons) + */ +struct in_addr { + in_addr_t s_addr; +}; +#endif + + +#if __BSD_VISIBLE +/* need this for the non-standard stuff */ +#ifndef _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED_ +typedef __size_t size_t; +#endif +#endif + + +__BEGIN_DECLS +in_addr_t inet_addr(const char *); +char *inet_ntoa(struct in_addr); +const char *inet_ntop(int, const void *__restrict, char *__restrict, + socklen_t) __attribute__ ((__bounded__(__string__,3,4))); +int inet_pton(int, const char *__restrict, void *__restrict); + +#if __BSD_VISIBLE +int inet_aton(const char *, struct in_addr *); +in_addr_t inet_lnaof(struct in_addr); +struct in_addr inet_makeaddr(in_addr_t , in_addr_t); +char * inet_neta(in_addr_t, char *, size_t) + __attribute__((__bounded__(__string__,2,3))); +in_addr_t inet_netof(struct in_addr); +in_addr_t inet_network(const char *); +char *inet_net_ntop(int, const void *, int, char *, size_t) + __attribute__((__bounded__(__string__,4,5))); +int inet_net_pton(int, const char *, void *, size_t) + __attribute__((__bounded__(__string__,3,4))); +#endif /* __BSD_VISIBLE */ +__END_DECLS + +#endif /* !_INET_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/arpa/nameser.h b/lib/libc/include/generic-openbsd/arpa/nameser.h new file mode 100644 index 000000000000..6951642d6bd6 --- /dev/null +++ b/lib/libc/include/generic-openbsd/arpa/nameser.h @@ -0,0 +1,369 @@ +/* $OpenBSD: nameser.h,v 1.15 2022/12/27 07:44:56 jmc Exp $ */ + +/* + * ++Copyright++ 1983, 1989, 1993 + * - + * Copyright (c) 1983, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * - + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * - + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + * --Copyright-- + */ + +/* + * @(#)nameser.h 8.1 (Berkeley) 6/2/93 + * $From: nameser.h,v 8.11 1996/10/08 04:51:02 vixie Exp $ + */ + +#ifndef _NAMESER_H_ +#define _NAMESER_H_ + +#include + +/* + * revision information. this is the release date in YYYYMMDD format. + * it can change every day so the right thing to do with it is use it + * in preprocessor commands such as "#if (__BIND > 19931104)". do not + * compare for equality; rather, use it to determine whether your resolver + * is new enough to contain a certain feature. + */ + +#define __BIND 19960801 /* interface version stamp */ + +/* + * Define constants based on rfc883 + */ +#define PACKETSZ 512 /* maximum packet size */ +#define MAXDNAME 1025 /* maximum presentation domain name */ +#define MAXCDNAME 255 /* maximum compressed domain name */ +#define MAXLABEL 63 /* maximum length of domain label */ +#define HFIXEDSZ 12 /* #/bytes of fixed data in header */ +#define QFIXEDSZ 4 /* #/bytes of fixed data in query */ +#define RRFIXEDSZ 10 /* #/bytes of fixed data in r record */ +#define INT32SZ 4 /* for systems without 32-bit ints */ +#define INT16SZ 2 /* for systems without 16-bit ints */ +#define INADDRSZ 4 /* IPv4 T_A */ +#define IN6ADDRSZ 16 /* IPv6 T_AAAA */ + +/* + * Internet nameserver port number + */ +#define NAMESERVER_PORT 53 + +/* + * Currently defined opcodes + */ +#define QUERY 0x0 /* standard query */ +#define IQUERY 0x1 /* inverse query */ +#define STATUS 0x2 /* nameserver status query */ +/*#define xxx 0x3*/ /* 0x3 reserved */ +#define NS_NOTIFY_OP 0x4 /* notify secondary of SOA change */ +/* + * Currently defined response codes + */ +#define NOERROR 0 /* no error */ +#define FORMERR 1 /* format error */ +#define SERVFAIL 2 /* server failure */ +#define NXDOMAIN 3 /* non existent domain */ +#define NOTIMP 4 /* not implemented */ +#define REFUSED 5 /* query refused */ + +/* + * Type values for resources and queries + */ +#define T_A 1 /* host address */ +#define T_NS 2 /* authoritative server */ +#define T_MD 3 /* mail destination */ +#define T_MF 4 /* mail forwarder */ +#define T_CNAME 5 /* canonical name */ +#define T_SOA 6 /* start of authority zone */ +#define T_MB 7 /* mailbox domain name */ +#define T_MG 8 /* mail group member */ +#define T_MR 9 /* mail rename name */ +#define T_NULL 10 /* null resource record */ +#define T_WKS 11 /* well known service */ +#define T_PTR 12 /* domain name pointer */ +#define T_HINFO 13 /* host information */ +#define T_MINFO 14 /* mailbox information */ +#define T_MX 15 /* mail routing information */ +#define T_TXT 16 /* text strings */ +#define T_RP 17 /* responsible person */ +#define T_AFSDB 18 /* AFS cell database */ +#define T_X25 19 /* X_25 calling address */ +#define T_ISDN 20 /* ISDN calling address */ +#define T_RT 21 /* router */ +#define T_NSAP 22 /* NSAP address */ +#define T_NSAP_PTR 23 /* reverse NSAP lookup (deprecated) */ +#define T_SIG 24 /* security signature */ +#define T_KEY 25 /* security key */ +#define T_PX 26 /* X.400 mail mapping */ +#define T_GPOS 27 /* geographical position (withdrawn) */ +#define T_AAAA 28 /* IP6 Address */ +#define T_LOC 29 /* Location Information */ +#define T_NXT 30 /* Next Valid Name in Zone */ +#define T_EID 31 /* Endpoint identifier */ +#define T_NIMLOC 32 /* Nimrod locator */ +#define T_SRV 33 /* Server selection */ +#define T_ATMA 34 /* ATM Address */ +#define T_NAPTR 35 /* Naming Authority PoinTeR */ +#define T_KX 36 /* Key Exchanger */ +#define T_CERT 37 /* CERT */ +#define T_A6 38 /* A6 */ +#define T_DNAME 39 /* DNAME */ +#define T_SINK 40 /* SINK */ +#define T_OPT 41 /* OPT pseudo-RR, RFC2671 */ +#define T_APL 42 /* APL */ +#define T_DS 43 /* Delegation Signer */ +#define T_SSHFP 44 /* SSH Key Fingerprint */ +#define T_RRSIG 46 /* RRSIG */ +#define T_NSEC 47 /* NSEC */ +#define T_DNSKEY 48 /* DNSKEY */ + /* non standard */ +#define T_UINFO 100 /* user (finger) information */ +#define T_UID 101 /* user ID */ +#define T_GID 102 /* group ID */ +#define T_UNSPEC 103 /* Unspecified format (binary data) */ + /* Query type values which do not appear in resource records */ +#define T_TKEY 249 /* Transaction Key */ +#define T_TSIG 250 /* Transaction Signature */ +#define T_IXFR 251 /* incremental zone transfer */ +#define T_AXFR 252 /* transfer zone of authority */ +#define T_MAILB 253 /* transfer mailbox records */ +#define T_MAILA 254 /* transfer mail agent records */ +#define T_ANY 255 /* wildcard match */ + +/* + * Values for class field + */ + +#define C_IN 1 /* the arpa internet */ +#define C_CHAOS 3 /* for chaos net (MIT) */ +#define C_HS 4 /* for Hesiod name server (MIT) (XXX) */ + /* Query class values which do not appear in resource records */ +#define C_ANY 255 /* wildcard match */ + +/* + * Flags field of the KEY RR rdata + */ +#define KEYFLAG_TYPEMASK 0xC000 /* Mask for "type" bits */ +#define KEYFLAG_TYPE_AUTH_CONF 0x0000 /* Key usable for both */ +#define KEYFLAG_TYPE_CONF_ONLY 0x8000 /* Key usable for confidentiality */ +#define KEYFLAG_TYPE_AUTH_ONLY 0x4000 /* Key usable for authentication */ +#define KEYFLAG_TYPE_NO_KEY 0xC000 /* No key usable for either; no key */ +/* The type bits can also be interpreted independently, as single bits: */ +#define KEYFLAG_NO_AUTH 0x8000 /* Key not usable for authentication */ +#define KEYFLAG_NO_CONF 0x4000 /* Key not usable for confidentiality */ + +#define KEYFLAG_EXPERIMENTAL 0x2000 /* Security is *mandatory* if bit=0 */ +#define KEYFLAG_RESERVED3 0x1000 /* reserved - must be zero */ +#define KEYFLAG_RESERVED4 0x0800 /* reserved - must be zero */ +#define KEYFLAG_USERACCOUNT 0x0400 /* key is assoc. with a user acct */ +#define KEYFLAG_ENTITY 0x0200 /* key is assoc. with entity eg host */ +#define KEYFLAG_ZONEKEY 0x0100 /* key is zone key for the zone named */ +#define KEYFLAG_IPSEC 0x0080 /* key is for IPsec use (host or user)*/ +#define KEYFLAG_EMAIL 0x0040 /* key is for email (MIME security) */ +#define KEYFLAG_RESERVED10 0x0020 /* reserved - must be zero */ +#define KEYFLAG_RESERVED11 0x0010 /* reserved - must be zero */ +#define KEYFLAG_SIGNATORYMASK 0x000F /* key can sign DNS RR's of same name */ + +#define KEYFLAG_RESERVED_BITMASK ( KEYFLAG_RESERVED3 | \ + KEYFLAG_RESERVED4 | \ + KEYFLAG_RESERVED10| KEYFLAG_RESERVED11) + +/* The Algorithm field of the KEY and SIG RR's is an integer, {1..254} */ +#define ALGORITHM_MD5RSA 1 /* MD5 with RSA */ +#define ALGORITHM_EXPIRE_ONLY 253 /* No alg, no security */ +#define ALGORITHM_PRIVATE_OID 254 /* Key begins with OID indicating alg */ + +/* Signatures */ + /* Size of a mod or exp in bits */ +#define MIN_MD5RSA_KEY_PART_BITS 512 +#define MAX_MD5RSA_KEY_PART_BITS 2552 + /* Total of binary mod and exp, bytes */ +#define MAX_MD5RSA_KEY_BYTES ((MAX_MD5RSA_KEY_PART_BITS+7/8)*2+3) + /* Max length of text sig block */ +#define MAX_KEY_BASE64 (((MAX_MD5RSA_KEY_BYTES+2)/3)*4) + +/* + * EDNS0 Z-field extended flags + */ +#define DNS_MESSAGEEXTFLAG_DO 0x8000U + +/* + * Status return codes for T_UNSPEC conversion routines + */ +#define CONV_SUCCESS 0 +#define CONV_OVERFLOW (-1) +#define CONV_BADFMT (-2) +#define CONV_BADCKSUM (-3) +#define CONV_BADBUFLEN (-4) + +#if !defined(_BYTE_ORDER) || \ + (_BYTE_ORDER != _BIG_ENDIAN && _BYTE_ORDER != _LITTLE_ENDIAN && \ + _BYTE_ORDER != _PDP_ENDIAN) + /* you must determine what the correct bit order is for + * your compiler - the next line is an intentional error + * which will force your compiles to bomb until you fix + * the above macros. + */ +#error "Undefined or invalid _BYTE_ORDER"; +#endif + +/* + * Structure for query header. The order of the fields is machine- and + * compiler-dependent, depending on the byte/bit order and the layout + * of bit fields. We use bit fields only in int variables, as this + * is all ANSI requires. This requires a somewhat confusing rearrangement. + */ + +typedef struct { + unsigned id :16; /* query identification number */ +#if _BYTE_ORDER == _BIG_ENDIAN + /* fields in third byte */ + unsigned qr: 1; /* response flag */ + unsigned opcode: 4; /* purpose of message */ + unsigned aa: 1; /* authoritative answer */ + unsigned tc: 1; /* truncated message */ + unsigned rd: 1; /* recursion desired */ + /* fields in fourth byte */ + unsigned ra: 1; /* recursion available */ + unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */ + unsigned ad: 1; /* authentic data from named */ + unsigned cd: 1; /* checking disabled by resolver */ + unsigned rcode :4; /* response code */ +#endif +#if _BYTE_ORDER == _LITTLE_ENDIAN || _BYTE_ORDER == _PDP_ENDIAN + /* fields in third byte */ + unsigned rd :1; /* recursion desired */ + unsigned tc :1; /* truncated message */ + unsigned aa :1; /* authoritative answer */ + unsigned opcode :4; /* purpose of message */ + unsigned qr :1; /* response flag */ + /* fields in fourth byte */ + unsigned rcode :4; /* response code */ + unsigned cd: 1; /* checking disabled by resolver */ + unsigned ad: 1; /* authentic data from named */ + unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */ + unsigned ra :1; /* recursion available */ +#endif + /* remaining bytes */ + unsigned qdcount :16; /* number of question entries */ + unsigned ancount :16; /* number of answer entries */ + unsigned nscount :16; /* number of authority entries */ + unsigned arcount :16; /* number of resource entries */ +} HEADER; + +/* + * Defines for handling compressed domain names + */ +#define INDIR_MASK 0xc0 + +extern u_int16_t _getshort(const unsigned char *); +extern u_int32_t _getlong(const unsigned char *); + +/* + * Inline versions of get/put short/long. Pointer is advanced. + * + * These macros demonstrate the property of C whereby it can be + * portable or it can be elegant but rarely both. + */ +#define GETSHORT(s, cp) { \ + unsigned char *t_cp = (unsigned char *)(cp); \ + (s) = ((u_int16_t)t_cp[0] << 8) \ + | ((u_int16_t)t_cp[1]) \ + ; \ + (cp) += INT16SZ; \ +} + +#define GETLONG(l, cp) { \ + unsigned char *t_cp = (unsigned char *)(cp); \ + (l) = ((u_int32_t)t_cp[0] << 24) \ + | ((u_int32_t)t_cp[1] << 16) \ + | ((u_int32_t)t_cp[2] << 8) \ + | ((u_int32_t)t_cp[3]) \ + ; \ + (cp) += INT32SZ; \ +} + +#define PUTSHORT(s, cp) { \ + u_int16_t t_s = (u_int16_t)(s); \ + unsigned char *t_cp = (unsigned char *)(cp); \ + *t_cp++ = t_s >> 8; \ + *t_cp = t_s; \ + (cp) += INT16SZ; \ +} + +#define PUTLONG(l, cp) { \ + u_int32_t t_l = (u_int32_t)(l); \ + unsigned char *t_cp = (unsigned char *)(cp); \ + *t_cp++ = t_l >> 24; \ + *t_cp++ = t_l >> 16; \ + *t_cp++ = t_l >> 8; \ + *t_cp = t_l; \ + (cp) += INT32SZ; \ +} + +#endif /* !_NAMESER_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/arpa/telnet.h b/lib/libc/include/generic-openbsd/arpa/telnet.h new file mode 100644 index 000000000000..f0094f2af20e --- /dev/null +++ b/lib/libc/include/generic-openbsd/arpa/telnet.h @@ -0,0 +1,339 @@ +/* $OpenBSD: telnet.h,v 1.7 2003/06/02 19:34:12 millert Exp $ */ +/* $NetBSD: telnet.h,v 1.4 1994/10/26 00:56:46 cgd Exp $ */ + +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)telnet.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _TELNET_H_ +#define _TELNET_H_ + +/* + * Definitions for the TELNET protocol. + */ +#define IAC 255 /* interpret as command: */ +#define DONT 254 /* you are not to use option */ +#define DO 253 /* please, you use option */ +#define WONT 252 /* I won't use option */ +#define WILL 251 /* I will use option */ +#define SB 250 /* interpret as subnegotiation */ +#define GA 249 /* you may reverse the line */ +#define EL 248 /* erase the current line */ +#define EC 247 /* erase the current character */ +#define AYT 246 /* are you there */ +#define AO 245 /* abort output--but let prog finish */ +#define IP 244 /* interrupt process--permanently */ +#define BREAK 243 /* break */ +#define DM 242 /* data mark--for connect. cleaning */ +#define NOP 241 /* nop */ +#define SE 240 /* end sub negotiation */ +#define EOR 239 /* end of record (transparent mode) */ +#define ABORT 238 /* Abort process */ +#define SUSP 237 /* Suspend process */ +#define xEOF 236 /* End of file: EOF is already used... */ + +#define SYNCH 242 /* for telfunc calls */ + +#ifdef TELCMDS +char *telcmds[] = { + "EOF", "SUSP", "ABORT", "EOR", + "SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC", + "EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", + 0 +}; +#else +extern char *telcmds[]; +#endif + +#define TELCMD_FIRST xEOF +#define TELCMD_LAST IAC +#define TELCMD_OK(x) ((unsigned int)(x) <= TELCMD_LAST && \ + (unsigned int)(x) >= TELCMD_FIRST) +#define TELCMD(x) telcmds[(x)-TELCMD_FIRST] + +/* telnet options */ +#define TELOPT_BINARY 0 /* 8-bit data path */ +#define TELOPT_ECHO 1 /* echo */ +#define TELOPT_RCP 2 /* prepare to reconnect */ +#define TELOPT_SGA 3 /* suppress go ahead */ +#define TELOPT_NAMS 4 /* approximate message size */ +#define TELOPT_STATUS 5 /* give status */ +#define TELOPT_TM 6 /* timing mark */ +#define TELOPT_RCTE 7 /* remote controlled transmission and echo */ +#define TELOPT_NAOL 8 /* negotiate about output line width */ +#define TELOPT_NAOP 9 /* negotiate about output page size */ +#define TELOPT_NAOCRD 10 /* negotiate about CR disposition */ +#define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */ +#define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */ +#define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */ +#define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */ +#define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */ +#define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */ +#define TELOPT_XASCII 17 /* extended ascic character set */ +#define TELOPT_LOGOUT 18 /* force logout */ +#define TELOPT_BM 19 /* byte macro */ +#define TELOPT_DET 20 /* data entry terminal */ +#define TELOPT_SUPDUP 21 /* supdup protocol */ +#define TELOPT_SUPDUPOUTPUT 22 /* supdup output */ +#define TELOPT_SNDLOC 23 /* send location */ +#define TELOPT_TTYPE 24 /* terminal type */ +#define TELOPT_EOR 25 /* end or record */ +#define TELOPT_TUID 26 /* TACACS user identification */ +#define TELOPT_OUTMRK 27 /* output marking */ +#define TELOPT_TTYLOC 28 /* terminal location number */ +#define TELOPT_3270REGIME 29 /* 3270 regime */ +#define TELOPT_X3PAD 30 /* X.3 PAD */ +#define TELOPT_NAWS 31 /* window size */ +#define TELOPT_TSPEED 32 /* terminal speed */ +#define TELOPT_LFLOW 33 /* remote flow control */ +#define TELOPT_LINEMODE 34 /* Linemode option */ +#define TELOPT_XDISPLOC 35 /* X Display Location */ +#define TELOPT_OLD_ENVIRON 36 /* Old - Environment variables */ +#define TELOPT_AUTHENTICATION 37/* Authenticate */ +#define TELOPT_ENCRYPT 38 /* Encryption option */ +#define TELOPT_NEW_ENVIRON 39 /* New - Environment variables */ +#define TELOPT_EXOPL 255 /* extended-options-list */ + + +#define NTELOPTS (1+TELOPT_NEW_ENVIRON) +#ifdef TELOPTS +char *telopts[NTELOPTS+1] = { + "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME", + "STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP", + "NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS", + "NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO", + "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT", + "SEND LOCATION", "TERMINAL TYPE", "END OF RECORD", + "TACACS UID", "OUTPUT MARKING", "TTYLOC", + "3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW", + "LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION", + "ENCRYPT", "NEW-ENVIRON", + 0 +}; +#define TELOPT_FIRST TELOPT_BINARY +#define TELOPT_LAST TELOPT_NEW_ENVIRON +#define TELOPT_OK(x) ((unsigned int)(x) <= TELOPT_LAST) +#define TELOPT(x) telopts[(x)-TELOPT_FIRST] +#endif + +/* sub-option qualifiers */ +#define TELQUAL_IS 0 /* option is... */ +#define TELQUAL_SEND 1 /* send option */ +#define TELQUAL_INFO 2 /* ENVIRON: informational version of IS */ +#define TELQUAL_REPLY 2 /* AUTHENTICATION: client version of IS */ +#define TELQUAL_NAME 3 /* AUTHENTICATION: client version of IS */ + +#define LFLOW_OFF 0 /* Disable remote flow control */ +#define LFLOW_ON 1 /* Enable remote flow control */ +#define LFLOW_RESTART_ANY 2 /* Restart output on any char */ +#define LFLOW_RESTART_XON 3 /* Restart output only on XON */ + +/* + * LINEMODE suboptions + */ + +#define LM_MODE 1 +#define LM_FORWARDMASK 2 +#define LM_SLC 3 + +#define MODE_EDIT 0x01 +#define MODE_TRAPSIG 0x02 +#define MODE_ACK 0x04 +#define MODE_SOFT_TAB 0x08 +#define MODE_LIT_ECHO 0x10 + +#define MODE_MASK 0x1f + +/* Not part of protocol, but needed to simplify things... */ +#define MODE_FLOW 0x0100 +#define MODE_ECHO 0x0200 +#define MODE_INBIN 0x0400 +#define MODE_OUTBIN 0x0800 +#define MODE_FORCE 0x1000 + +#define SLC_SYNCH 1 +#define SLC_BRK 2 +#define SLC_IP 3 +#define SLC_AO 4 +#define SLC_AYT 5 +#define SLC_EOR 6 +#define SLC_ABORT 7 +#define SLC_EOF 8 +#define SLC_SUSP 9 +#define SLC_EC 10 +#define SLC_EL 11 +#define SLC_EW 12 +#define SLC_RP 13 +#define SLC_LNEXT 14 +#define SLC_XON 15 +#define SLC_XOFF 16 +#define SLC_FORW1 17 +#define SLC_FORW2 18 +#define SLC_MCL 19 +#define SLC_MCR 20 +#define SLC_MCWL 21 +#define SLC_MCWR 22 +#define SLC_MCBOL 23 +#define SLC_MCEOL 24 +#define SLC_INSRT 25 +#define SLC_OVER 26 +#define SLC_ECR 27 +#define SLC_EWR 28 +#define SLC_EBOL 29 +#define SLC_EEOL 30 + +#define NSLC 30 + +/* + * For backwards compatibility, we define SLC_NAMES to be the + * list of names if SLC_NAMES is not defined. + */ +#define SLC_NAMELIST "0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \ + "ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \ + "LNEXT", "XON", "XOFF", "FORW1", "FORW2", \ + "MCL", "MCR", "MCWL", "MCWR", "MCBOL", \ + "MCEOL", "INSRT", "OVER", "ECR", "EWR", \ + "EBOL", "EEOL", \ + 0 + +#ifdef SLC_NAMES +char *slc_names[] = { + SLC_NAMELIST +}; +#else +extern char *slc_names[]; +#define SLC_NAMES SLC_NAMELIST +#endif + +#define SLC_NAME_OK(x) ((unsigned)(x) > 0 && (unsigned)(x) <= NSLC) +#define SLC_NAME(x) slc_names[x] + +#define SLC_NOSUPPORT 0 +#define SLC_CANTCHANGE 1 +#define SLC_VARIABLE 2 +#define SLC_DEFAULT 3 +#define SLC_LEVELBITS 0x03 + +#define SLC_FUNC 0 +#define SLC_FLAGS 1 +#define SLC_VALUE 2 + +#define SLC_ACK 0x80 +#define SLC_FLUSHIN 0x40 +#define SLC_FLUSHOUT 0x20 + +#define OLD_ENV_VAR 1 +#define OLD_ENV_VALUE 0 +#define NEW_ENV_VAR 0 +#define NEW_ENV_VALUE 1 +#define ENV_ESC 2 +#define ENV_USERVAR 3 + +/* + * AUTHENTICATION suboptions + */ + +/* + * Who is authenticating who ... + */ +#define AUTH_WHO_CLIENT 0 /* Client authenticating server */ +#define AUTH_WHO_SERVER 1 /* Server authenticating client */ +#define AUTH_WHO_MASK 1 + +/* + * amount of authentication done + */ +#define AUTH_HOW_ONE_WAY 0 +#define AUTH_HOW_MUTUAL 2 +#define AUTH_HOW_MASK 2 + +#define AUTHTYPE_NULL 0 +#define AUTHTYPE_KERBEROS_V4 1 +#define AUTHTYPE_KERBEROS_V5 2 +#define AUTHTYPE_SPX 3 +#define AUTHTYPE_MINK 4 +#define AUTHTYPE_CNT 5 + +#define AUTHTYPE_TEST 99 + +#ifdef AUTH_NAMES +char *authtype_names[] = { + "NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK", + 0 +}; +#else +extern char *authtype_names[]; +#endif + +#define AUTHTYPE_NAME_OK(x) ((unsigned int)(x) < AUTHTYPE_CNT) +#define AUTHTYPE_NAME(x) authtype_names[x] + +/* + * ENCRYPTion suboptions + */ +#define ENCRYPT_IS 0 /* I pick encryption type ... */ +#define ENCRYPT_SUPPORT 1 /* I support encryption types ... */ +#define ENCRYPT_REPLY 2 /* Initial setup response */ +#define ENCRYPT_START 3 /* Am starting to send encrypted */ +#define ENCRYPT_END 4 /* Am ending encrypted */ +#define ENCRYPT_REQSTART 5 /* Request you start encrypting */ +#define ENCRYPT_REQEND 6 /* Request you end encrypting */ +#define ENCRYPT_ENC_KEYID 7 +#define ENCRYPT_DEC_KEYID 8 +#define ENCRYPT_CNT 9 + +#define ENCTYPE_ANY 0 +#define ENCTYPE_DES_CFB64 1 +#define ENCTYPE_DES_OFB64 2 +#define ENCTYPE_CNT 3 + +#ifdef ENCRYPT_NAMES +char *encrypt_names[] = { + "IS", "SUPPORT", "REPLY", "START", "END", + "REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID", + 0 +}; +char *enctype_names[] = { + "ANY", "DES_CFB64", "DES_OFB64", + 0 +}; +#else +extern char *encrypt_names[]; +extern char *enctype_names[]; +#endif + + +#define ENCRYPT_NAME_OK(x) ((unsigned int)(x) < ENCRYPT_CNT) +#define ENCRYPT_NAME(x) encrypt_names[x] + +#define ENCTYPE_NAME_OK(x) ((unsigned int)(x) < ENCTYPE_CNT) +#define ENCTYPE_NAME(x) enctype_names[x] + +#endif /* !_TELNET_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/arpa/tftp.h b/lib/libc/include/generic-openbsd/arpa/tftp.h new file mode 100644 index 000000000000..83c5338cc6d0 --- /dev/null +++ b/lib/libc/include/generic-openbsd/arpa/tftp.h @@ -0,0 +1,83 @@ +/* $OpenBSD: tftp.h,v 1.8 2006/07/26 16:43:30 deraadt Exp $ */ +/* $NetBSD: tftp.h,v 1.3 1994/10/26 00:56:48 cgd Exp $ */ + +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tftp.h 5.4 (Berkeley) 4/3/91 + */ + +#ifndef _TFTP_H_ +#define _TFTP_H_ + +/* + * Trivial File Transfer Protocol (IEN-133) + */ +#define SEGSIZE 512 /* data segment size */ +#define SEGSIZE_MIN 8 /* minimal data segment size */ +#define SEGSIZE_MAX 65464 /* maximal data segment size */ + +/* + * Packet types. + */ +#define RRQ 01 /* read request */ +#define WRQ 02 /* write request */ +#define DATA 03 /* data packet */ +#define ACK 04 /* acknowledgement */ +#define ERROR 05 /* error code */ +#define OACK 06 /* option acknowledgement */ + +struct tftphdr { + u_int16_t th_opcode; /* packet type */ + union { + u_int16_t tu_block; /* block # */ + u_int16_t tu_code; /* error code */ + char tu_stuff[1]; /* request packet stuff */ + } th_u; + char th_data[1]; /* data or error string */ +}; + +#define th_block th_u.tu_block +#define th_code th_u.tu_code +#define th_stuff th_u.tu_stuff +#define th_msg th_data + +/* + * Error codes. + */ +#define EUNDEF 0 /* not defined */ +#define ENOTFOUND 1 /* file not found */ +#define EACCESS 2 /* access violation */ +#define ENOSPACE 3 /* disk full or allocation exceeded */ +#define EBADOP 4 /* illegal TFTP operation */ +#define EBADID 5 /* unknown transfer ID */ +#define EEXISTS 6 /* file already exists */ +#define ENOUSER 7 /* no such user */ +#define EOPTNEG 8 /* option negotiation failed */ + +#endif /* !_TFTP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/asr.h b/lib/libc/include/generic-openbsd/asr.h new file mode 100644 index 000000000000..cef6d6baf0fc --- /dev/null +++ b/lib/libc/include/generic-openbsd/asr.h @@ -0,0 +1,90 @@ +/* $OpenBSD: asr.h,v 1.2 2019/10/24 05:57:41 otto Exp $ */ +/* + * Copyright (c) 2012-2014 Eric Faurot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Expected fd conditions + */ +#define ASR_WANT_READ 1 +#define ASR_WANT_WRITE 2 + +/* + * Structure through which asynchronous query results are returned when + * calling asr_run(). + */ +struct asr_result { + /* Fields set if the query is not done yet (asr_run returns 0) */ + int ar_cond; /* ASR_WANT_READ or ASR_WANT_WRITE */ + int ar_fd; /* the fd waiting for io condition */ + int ar_timeout; /* time to wait for in milliseconds */ + + /* Error fields. Depends on the query type. */ + int ar_errno; + int ar_h_errno; + int ar_gai_errno; + int ar_rrset_errno; + + /* Result for res_*_async() calls */ + int ar_count; /* number of answers in the dns reply */ + int ar_rcode; /* response code in the dns reply */ + void *ar_data; /* raw reply packet (must be freed) */ + int ar_datalen; /* reply packet length */ + struct sockaddr_storage ar_ns; /* nameserver that responded */ + + /* Result for other calls. Must be freed properly. */ + struct addrinfo *ar_addrinfo; + struct rrsetinfo *ar_rrsetinfo; + struct hostent *ar_hostent; + struct netent *ar_netent; +}; + +/* + * Asynchronous query management. + */ + +/* Forward declaration. The API uses opaque pointers as query handles. */ +struct asr_query; + +void *asr_resolver_from_string(const char *); +void asr_resolver_free(void *); +int asr_run(struct asr_query *, struct asr_result *); +int asr_run_sync(struct asr_query *, struct asr_result *); +void asr_abort(struct asr_query *); + +/* + * Asynchronous version of the resolver functions. Similar prototypes, with + * an extra context parameter at the end which must currently be set to NULL. + * All functions return a handle suitable for use with the management functions + * above. + */ +struct asr_query *res_send_async(const unsigned char *, int, void *); +struct asr_query *res_query_async(const char *, int, int, void *); +struct asr_query *res_search_async(const char *, int, int, void *); + +struct asr_query *getrrsetbyname_async(const char *, unsigned int, unsigned int, + unsigned int, void *); + +struct asr_query *gethostbyname_async(const char *, void *); +struct asr_query *gethostbyname2_async(const char *, int, void *); +struct asr_query *gethostbyaddr_async(const void *, socklen_t, int, void *); + +struct asr_query *getnetbyname_async(const char *, void *); +struct asr_query *getnetbyaddr_async(in_addr_t, int, void *); + +struct asr_query *getaddrinfo_async(const char *, const char *, + const struct addrinfo *, void *); +struct asr_query *getnameinfo_async(const struct sockaddr *, socklen_t, char *, + size_t, char *, size_t, int, void *); \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/assert.h b/lib/libc/include/generic-openbsd/assert.h new file mode 100644 index 000000000000..88359e24590f --- /dev/null +++ b/lib/libc/include/generic-openbsd/assert.h @@ -0,0 +1,73 @@ +/* $OpenBSD: assert.h,v 1.15 2020/09/06 12:57:25 millert Exp $ */ +/* $NetBSD: assert.h,v 1.6 1994/10/26 00:55:44 cgd Exp $ */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)assert.h 8.2 (Berkeley) 1/21/94 + */ + +/* + * Unlike other ANSI header files, may usefully be included + * multiple times, with and without NDEBUG defined. + */ + +#include + +#undef assert +#undef _assert + +#ifdef NDEBUG +# define assert(e) ((void)0) +# define _assert(e) ((void)0) +#else +# define _assert(e) assert(e) +# if __ISO_C_VISIBLE >= 1999 +# define assert(e) ((e) ? (void)0 : __assert2(__FILE__, __LINE__, __func__, #e)) +# else +# define assert(e) ((e) ? (void)0 : __assert(__FILE__, __LINE__, #e)) +# endif +#endif + +#ifndef _ASSERT_H_ +#define _ASSERT_H_ + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112 +#define static_assert _Static_assert +#endif + +__BEGIN_DECLS +__dead void __assert(const char *, int, const char *); +__dead void __assert2(const char *, int, const char *, const char *); +__END_DECLS +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ber.h b/lib/libc/include/generic-openbsd/ber.h new file mode 100644 index 000000000000..9638118862e4 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ber.h @@ -0,0 +1,153 @@ +/* $OpenBSD: ber.h,v 1.5 2021/10/31 16:42:08 tb Exp $ */ + +/* + * Copyright (c) 2007, 2012 Reyk Floeter + * Copyright (c) 2006, 2007 Claudio Jeker + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _BER_H +#define _BER_H + +struct ber_octetstring { + size_t ostr_len; + const void *ostr_val; +}; + +struct ber_element { + struct ber_element *be_next; + unsigned int be_type; + unsigned int be_encoding; + size_t be_len; + off_t be_offs; + int be_free; + u_int8_t be_class; + void (*be_cb)(void *, size_t); + void *be_cbarg; + union { + struct ber_element *bv_sub; + void *bv_val; + long long bv_numeric; + } be_union; +#define be_sub be_union.bv_sub +#define be_val be_union.bv_val +#define be_numeric be_union.bv_numeric +}; + +struct ber { + off_t br_offs; + u_char *br_wbuf; + u_char *br_wptr; + u_char *br_wend; + u_char *br_rbuf; + u_char *br_rptr; + u_char *br_rend; + + unsigned int (*br_application)(struct ber_element *); +}; + +/* well-known ber_element types */ +#define BER_TYPE_DEFAULT ((unsigned int)-1) +#define BER_TYPE_EOC 0 +#define BER_TYPE_BOOLEAN 1 +#define BER_TYPE_INTEGER 2 +#define BER_TYPE_BITSTRING 3 +#define BER_TYPE_OCTETSTRING 4 +#define BER_TYPE_NULL 5 +#define BER_TYPE_OBJECT 6 +#define BER_TYPE_ENUMERATED 10 +#define BER_TYPE_SEQUENCE 16 +#define BER_TYPE_SET 17 + +/* ber classes */ +#define BER_CLASS_UNIVERSAL 0x0 +#define BER_CLASS_UNIV BER_CLASS_UNIVERSAL +#define BER_CLASS_APPLICATION 0x1 +#define BER_CLASS_APP BER_CLASS_APPLICATION +#define BER_CLASS_CONTEXT 0x2 +#define BER_CLASS_PRIVATE 0x3 +#define BER_CLASS_MASK 0x3 + +/* common definitions */ +#define BER_MIN_OID_LEN 2 /* X.690 section 8.19.5 */ +#define BER_MAX_OID_LEN 128 /* RFC 2578 section 7.1.3 */ +#define BER_MAX_SEQ_ELEMENTS USHRT_MAX /* 65535 */ + +struct ber_oid { + u_int32_t bo_id[BER_MAX_OID_LEN + 1]; + size_t bo_n; +}; + +__BEGIN_DECLS +struct ber_element *ober_get_element(unsigned int); +void ober_set_header(struct ber_element *, int, + unsigned int); +void ober_link_elements(struct ber_element *, + struct ber_element *); +struct ber_element *ober_unlink_elements(struct ber_element *); +void ober_replace_elements(struct ber_element *, + struct ber_element *); +struct ber_element *ober_add_sequence(struct ber_element *); +struct ber_element *ober_add_set(struct ber_element *); +struct ber_element *ober_add_integer(struct ber_element *, long long); +int ober_get_integer(struct ber_element *, long long *); +struct ber_element *ober_add_enumerated(struct ber_element *, long long); +int ober_get_enumerated(struct ber_element *, long long *); +struct ber_element *ober_add_boolean(struct ber_element *, int); +int ober_get_boolean(struct ber_element *, int *); +struct ber_element *ober_add_string(struct ber_element *, const char *); +struct ber_element *ober_add_nstring(struct ber_element *, const char *, + size_t); +struct ber_element *ober_add_ostring(struct ber_element *, + struct ber_octetstring *); +int ober_get_string(struct ber_element *, char **); +int ober_get_nstring(struct ber_element *, void **, + size_t *); +int ober_get_ostring(struct ber_element *, + struct ber_octetstring *); +struct ber_element *ober_add_bitstring(struct ber_element *, const void *, + size_t); +int ober_get_bitstring(struct ber_element *, void **, + size_t *); +struct ber_element *ober_add_null(struct ber_element *); +int ober_get_null(struct ber_element *); +struct ber_element *ober_add_eoc(struct ber_element *); +int ober_get_eoc(struct ber_element *); +struct ber_element *ober_add_oid(struct ber_element *, struct ber_oid *); +struct ber_element *ober_add_noid(struct ber_element *, struct ber_oid *, int); +struct ber_element *ober_add_oidstring(struct ber_element *, const char *); +int ober_get_oid(struct ber_element *, struct ber_oid *); +size_t ober_oid2ber(struct ber_oid *, u_int8_t *, size_t); +int ober_string2oid(const char *, struct ber_oid *); +struct ber_element *ober_printf_elements(struct ber_element *, char *, ...); +int ober_scanf_elements(struct ber_element *, char *, ...); +ssize_t ober_get_writebuf(struct ber *, void **); +ssize_t ober_write_elements(struct ber *, struct ber_element *); +void ober_set_readbuf(struct ber *, void *, size_t); +struct ber_element *ober_read_elements(struct ber *, struct ber_element *); +off_t ober_getpos(struct ber_element *); +struct ber_element *ober_dup(struct ber_element *); +void ober_free_element(struct ber_element *); +void ober_free_elements(struct ber_element *); +size_t ober_calc_len(struct ber_element *); +void ober_set_application(struct ber *, + unsigned int (*)(struct ber_element *)); +void ober_set_writecallback(struct ber_element *, + void (*)(void *, size_t), void *); +void ober_free(struct ber *); +int ober_oid_cmp(struct ber_oid *, struct ber_oid *); + +__END_DECLS + +#endif /* _BER_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/bitstring.h b/lib/libc/include/generic-openbsd/bitstring.h new file mode 100644 index 000000000000..2c30a30923b3 --- /dev/null +++ b/lib/libc/include/generic-openbsd/bitstring.h @@ -0,0 +1,134 @@ +/* $OpenBSD: bitstring.h,v 1.7 2024/08/26 11:52:54 bluhm Exp $ */ +/* $NetBSD: bitstring.h,v 1.5 1997/05/14 15:49:55 pk Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Paul Vixie. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)bitstring.h 8.1 (Berkeley) 7/19/93 + */ + +#ifndef _BITSTRING_H_ +#define _BITSTRING_H_ + +/* modified for SV/AT and bitstring bugfix by M.R.Murphy, 11oct91 + * bitstr_size changed gratuitously, but shorter + * bit_alloc spelling error fixed + * the following were efficient, but didn't work, they've been made to + * work, but are no longer as efficient :-) + * bit_nclear, bit_nset, bit_ffc, bit_ffs + */ +typedef unsigned char bitstr_t; + +/* internal macros */ + /* byte of the bitstring bit is in */ +#define _bit_byte(bit) \ + ((bit) >> 3) + + /* mask for the bit within its byte */ +#define _bit_mask(bit) \ + (1 << ((bit)&0x7)) + +/* external macros */ + /* bytes in a bitstring of nbits bits */ +#define bitstr_size(nbits) \ + (((nbits) + 7) >> 3) + + /* allocate a bitstring */ +#define bit_alloc(nbits) \ + (bitstr_t *)calloc((size_t)bitstr_size(nbits), sizeof(bitstr_t)) + + /* allocate a bitstring on the stack */ +#define bit_decl(name, nbits) \ + ((name)[bitstr_size(nbits)]) + + /* is bit N of bitstring name set? */ +#define bit_test(name, bit) ({ \ + register int __tbit = (bit); \ + ((name)[_bit_byte(__tbit)] & _bit_mask(__tbit)); \ +}) + + /* set bit N of bitstring name */ +#define bit_set(name, bit) do { \ + register int __sbit = (bit); \ + ((name)[_bit_byte(__sbit)] |= _bit_mask(__sbit)); \ +} while(0) + + /* clear bit N of bitstring name */ +#define bit_clear(name, bit) do { \ + register int __cbit = (bit); \ + ((name)[_bit_byte(__cbit)] &= ~_bit_mask(__cbit)); \ +} while(0) + + /* clear bits start ... stop in bitstring */ +#define bit_nclear(name, start, stop) do { \ + register bitstr_t *__name = (name); \ + register int __start = (start), __stop = (stop); \ + while (__start <= __stop) { \ + bit_clear(__name, __start); \ + __start++; \ + } \ +} while(0) + + /* set bits start ... stop in bitstring */ +#define bit_nset(name, start, stop) do { \ + register bitstr_t *__name = (name); \ + register int __start = (start), __stop = (stop); \ + while (__start <= __stop) { \ + bit_set(__name, __start); \ + __start++; \ + } \ +} while(0) + + /* find first bit clear in name */ +#define bit_ffc(name, nbits, value) do { \ + register bitstr_t *__name = (name); \ + register int __bit, __nbits = (nbits), __value = -1; \ + for (__bit = 0; __bit < __nbits; ++__bit) \ + if (!bit_test(__name, __bit)) { \ + __value = __bit; \ + break; \ + } \ + *(value) = __value; \ +} while(0) + + /* find first bit set in name */ +#define bit_ffs(name, nbits, value) do { \ + register bitstr_t *__name = (name); \ + register int __bit, __nbits = (nbits), __value = -1; \ + for (__bit = 0; __bit < __nbits; ++__bit) \ + if (bit_test(__name, __bit)) { \ + __value = __bit; \ + break; \ + } \ + *(value) = __value; \ +} while(0) + +#endif /* !_BITSTRING_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/blf.h b/lib/libc/include/generic-openbsd/blf.h new file mode 100644 index 000000000000..3e41647ce4ad --- /dev/null +++ b/lib/libc/include/generic-openbsd/blf.h @@ -0,0 +1,79 @@ +/* $OpenBSD: blf.h,v 1.8 2021/11/29 01:04:45 djm Exp $ */ +/* + * Blowfish - a fast block cipher designed by Bruce Schneier + * + * Copyright 1997 Niels Provos + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _BLF_H_ +#define _BLF_H_ + +/* Schneier specifies a maximum key length of 56 bytes. + * This ensures that every key bit affects every cipher + * bit. However, the subkeys can hold up to 72 bytes. + * Warning: For normal blowfish encryption only 56 bytes + * of the key affect all cipherbits. + */ + +#define BLF_N 16 /* Number of Subkeys */ +#define BLF_MAXKEYLEN ((BLF_N-2)*4) /* 448 bits */ +#define BLF_MAXUTILIZED ((BLF_N+2)*4) /* 576 bits */ + +/* Blowfish context */ +typedef struct BlowfishContext { + u_int32_t S[4][256]; /* S-Boxes */ + u_int32_t P[BLF_N + 2]; /* Subkeys */ +} blf_ctx; + +/* Raw access to customized Blowfish + * blf_key is just: + * Blowfish_initstate( state ) + * Blowfish_expand0state( state, key, keylen ) + */ + +void Blowfish_encipher(blf_ctx *, u_int32_t *, u_int32_t *); +void Blowfish_decipher(blf_ctx *, u_int32_t *, u_int32_t *); +void Blowfish_initstate(blf_ctx *); +void Blowfish_expand0state(blf_ctx *, const u_int8_t *, u_int16_t); +void Blowfish_expandstate +(blf_ctx *, const u_int8_t *, u_int16_t, const u_int8_t *, u_int16_t); + +/* Standard Blowfish */ + +void blf_key(blf_ctx *, const u_int8_t *, u_int16_t); +void blf_enc(blf_ctx *, u_int32_t *, u_int16_t); +void blf_dec(blf_ctx *, u_int32_t *, u_int16_t); + +void blf_ecb_encrypt(blf_ctx *, u_int8_t *, u_int32_t); +void blf_ecb_decrypt(blf_ctx *, u_int8_t *, u_int32_t); + +void blf_cbc_encrypt(blf_ctx *, u_int8_t *, u_int8_t *, u_int32_t); +void blf_cbc_decrypt(blf_ctx *, u_int8_t *, u_int8_t *, u_int32_t); + +/* Converts u_int8_t to u_int32_t */ +u_int32_t Blowfish_stream2word(const u_int8_t *, u_int16_t , u_int16_t *); + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/bsd_auth.h b/lib/libc/include/generic-openbsd/bsd_auth.h new file mode 100644 index 000000000000..34a09cc13f4d --- /dev/null +++ b/lib/libc/include/generic-openbsd/bsd_auth.h @@ -0,0 +1,105 @@ +/* $OpenBSD: bsd_auth.h,v 1.11 2017/03/09 10:13:03 fcambus Exp $ */ + +/*- + * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Berkeley Software Design, + * Inc. + * 4. The name of Berkeley Software Design, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``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 BERKELEY SOFTWARE DESIGN, INC. 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. + * + * BSDI $From: bsd_auth.h,v 2.3 1999/09/08 22:13:08 prb Exp $ + */ + +#ifndef _BSD_AUTH_H_ +#define _BSD_AUTH_H_ + +#include /* for __va_list */ + +typedef struct auth_session_t auth_session_t; + +typedef enum { + AUTHV_ALL, + AUTHV_CHALLENGE, + AUTHV_CLASS, + AUTHV_NAME, + AUTHV_SERVICE, + AUTHV_STYLE, + AUTHV_INTERACTIVE +} auth_item_t; + +#include +__BEGIN_DECLS +struct passwd; +struct login_cap; + +char *auth_getitem(auth_session_t *, auth_item_t); +int auth_setitem(auth_session_t *, auth_item_t, char *); + +auth_session_t *auth_open(void); +auth_session_t *auth_verify(auth_session_t *, char *, char *, ...) + __attribute__((__sentinel__)); + +auth_session_t *auth_userchallenge(char *, char *, char *, char **); +auth_session_t *auth_usercheck(char *, char *, char *, char *); + +int auth_userresponse(auth_session_t *, char *, int); +int auth_userokay(char *, char *, char *, char *); +int auth_approval(auth_session_t *, struct login_cap *, char *, char *); + +int auth_close(auth_session_t *); +void auth_clean(auth_session_t *); + +char *auth_getvalue(auth_session_t *, char *); +int auth_getstate(auth_session_t *); +char *auth_challenge(auth_session_t *); +void auth_setenv(auth_session_t *); +void auth_clrenv(auth_session_t *); + +void auth_setstate(auth_session_t *, int); +int auth_call(auth_session_t *, char *, ...) + __attribute__((__sentinel__)); + +int auth_setdata(auth_session_t *, void *, size_t); +int auth_setoption(auth_session_t *, char *, char *); +int auth_setpwd(auth_session_t *, struct passwd *); +void auth_set_va_list(auth_session_t *, __va_list); + +struct passwd *auth_getpwd(auth_session_t *); + +quad_t auth_check_expire(auth_session_t *); +quad_t auth_check_change(auth_session_t *); + +void auth_clroptions(auth_session_t *); +void auth_clroption(auth_session_t *, char *); + +char *auth_mkvalue(char *); +void auth_checknologin(struct login_cap *); +int auth_cat(char *); + +__END_DECLS + +#endif /* _BSD_AUTH_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/complex.h b/lib/libc/include/generic-openbsd/complex.h new file mode 100644 index 000000000000..16f72cc34fc1 --- /dev/null +++ b/lib/libc/include/generic-openbsd/complex.h @@ -0,0 +1,120 @@ +/* $OpenBSD: complex.h,v 1.5 2014/03/16 18:38:30 guenther Exp $ */ +/* + * Copyright (c) 2008 Martynas Venckus + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _COMPLEX_H_ +#define _COMPLEX_H_ + +#include + +/* + * C99 + */ +#ifdef __GNUC__ +#if __STDC_VERSION__ < 199901 +#define _Complex __complex__ +#endif +#define _Complex_I 1.0fi +#endif + +#define complex _Complex + +/* XXX switch to _Imaginary_I */ +#undef I +#define I _Complex_I + +__BEGIN_DECLS +/* + * Double versions of C99 functions + */ +double complex cacos(double complex); +double complex casin(double complex); +double complex catan(double complex); +double complex ccos(double complex); +double complex csin(double complex); +double complex ctan(double complex); +double complex cacosh(double complex); +double complex casinh(double complex); +double complex catanh(double complex); +double complex ccosh(double complex); +double complex csinh(double complex); +double complex ctanh(double complex); +double complex cexp(double complex); +double complex clog(double complex); +double cabs(double complex); +double complex cpow(double complex, double complex); +double complex csqrt(double complex); +double carg(double complex); +double cimag(double complex); +double complex conj(double complex); +double complex cproj(double complex); +double creal(double complex); + +/* + * Float versions of C99 functions + */ +float complex cacosf(float complex); +float complex casinf(float complex); +float complex catanf(float complex); +float complex ccosf(float complex); +float complex csinf(float complex); +float complex ctanf(float complex); +float complex cacoshf(float complex); +float complex casinhf(float complex); +float complex catanhf(float complex); +float complex ccoshf(float complex); +float complex csinhf(float complex); +float complex ctanhf(float complex); +float complex cexpf(float complex); +float complex clogf(float complex); +float cabsf(float complex); +float complex cpowf(float complex, float complex); +float complex csqrtf(float complex); +float cargf(float complex); +float cimagf(float complex); +float complex conjf(float complex); +float complex cprojf(float complex); +float crealf(float complex); + +/* + * Long double versions of C99 functions + */ +long double complex cacosl(long double complex); +long double complex casinl(long double complex); +long double complex catanl(long double complex); +long double complex ccosl(long double complex); +long double complex csinl(long double complex); +long double complex ctanl(long double complex); +long double complex cacoshl(long double complex); +long double complex casinhl(long double complex); +long double complex catanhl(long double complex); +long double complex ccoshl(long double complex); +long double complex csinhl(long double complex); +long double complex ctanhl(long double complex); +long double complex cexpl(long double complex); +long double complex clogl(long double complex); +long double cabsl(long double complex); +long double complex cpowl(long double complex, + long double complex); +long double complex csqrtl(long double complex); +long double cargl(long double complex); +long double cimagl(long double complex); +long double complex conjl(long double complex); +long double complex cprojl(long double complex); +long double creall(long double complex); +__END_DECLS + +#endif /* !_COMPLEX_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/cpio.h b/lib/libc/include/generic-openbsd/cpio.h new file mode 100644 index 000000000000..b59bcaacb031 --- /dev/null +++ b/lib/libc/include/generic-openbsd/cpio.h @@ -0,0 +1,59 @@ +/* $OpenBSD: cpio.h,v 1.3 2008/06/26 05:42:04 ray Exp $ */ +/* $NetBSD: cpio.h,v 1.1 1996/02/05 22:34:11 jtc Exp $ */ + +/*- + * Copyright (c) 1996 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by J.T. Conklin. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _CPIO_H_ +#define _CPIO_H_ + +#define C_IRUSR 0000400 +#define C_IWUSR 0000200 +#define C_IXUSR 0000100 +#define C_IRGRP 0000040 +#define C_IWGRP 0000020 +#define C_IXGRP 0000010 +#define C_IROTH 0000004 +#define C_IWOTH 0000002 +#define C_IXOTH 0000001 +#define C_ISUID 0004000 +#define C_ISGID 0002000 +#define C_ISVTX 0001000 +#define C_ISDIR 0040000 +#define C_ISFIFO 0010000 +#define C_ISREG 0100000 +#define C_ISBLK 0060000 +#define C_ISCHR 0020000 +#define C_ISCTG 0110000 +#define C_ISLNK 0120000 +#define C_ISSOCK 0140000 + +#define MAGIC "070707" + +#endif /* _CPIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ctype.h b/lib/libc/include/generic-openbsd/ctype.h new file mode 100644 index 000000000000..dacd82ae9c7c --- /dev/null +++ b/lib/libc/include/generic-openbsd/ctype.h @@ -0,0 +1,309 @@ +/* $OpenBSD: ctype.h,v 1.26 2024/02/04 13:03:18 jca Exp $ */ +/* $NetBSD: ctype.h,v 1.14 1994/10/26 00:55:47 cgd Exp $ */ + +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ctype.h 5.3 (Berkeley) 4/3/91 + */ + +#ifndef _CTYPE_H_ +#define _CTYPE_H_ + +#include + +#define _CTYPE_U 0x01 +#define _CTYPE_L 0x02 +#define _CTYPE_N 0x04 +#define _CTYPE_S 0x08 +#define _CTYPE_P 0x10 +#define _CTYPE_C 0x20 +#define _CTYPE_X 0x40 +#define _CTYPE_B 0x80 + +#if __POSIX_VISIBLE >= 200809 +#ifndef _LOCALE_T_DEFINED_ +#define _LOCALE_T_DEFINED_ +typedef void *locale_t; +#endif +#endif + +__BEGIN_DECLS + +extern const char *_ctype_; +extern const short *_tolower_tab_; +extern const short *_toupper_tab_; + +#if defined(__GNUC__) || defined(_ANSI_LIBRARY) +int isalnum(int); +int isalpha(int); +int iscntrl(int); +int isdigit(int); +int isgraph(int); +int islower(int); +int isprint(int); +int ispunct(int); +int isspace(int); +int isupper(int); +int isxdigit(int); +int tolower(int); +int toupper(int); + +#if __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999 || __POSIX_VISIBLE > 200112 \ + || __XPG_VISIBLE > 600 +int isblank(int); +#endif + +#if __BSD_VISIBLE || __XPG_VISIBLE +int isascii(int); +int toascii(int); +int _tolower(int); +int _toupper(int); +#endif /* __BSD_VISIBLE || __XPG_VISIBLE */ + +#if __POSIX_VISIBLE >= 200809 +int isalnum_l(int, locale_t); +int isalpha_l(int, locale_t); +int isblank_l(int, locale_t); +int iscntrl_l(int, locale_t); +int isdigit_l(int, locale_t); +int isgraph_l(int, locale_t); +int islower_l(int, locale_t); +int isprint_l(int, locale_t); +int ispunct_l(int, locale_t); +int isspace_l(int, locale_t); +int isupper_l(int, locale_t); +int isxdigit_l(int, locale_t); +int tolower_l(int, locale_t); +int toupper_l(int, locale_t); +#endif + +#endif /* __GNUC__ || _ANSI_LIBRARY */ + +#if !defined(_ANSI_LIBRARY) && !defined(__cplusplus) + +__only_inline int isalnum(int _c) +{ + return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c] & + (_CTYPE_U|_CTYPE_L|_CTYPE_N))); +} + +__only_inline int isalpha(int _c) +{ + return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c] & + (_CTYPE_U|_CTYPE_L))); +} + +__only_inline int iscntrl(int _c) +{ + return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c] & _CTYPE_C)); +} + +__only_inline int isdigit(int _c) +{ + return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c] & _CTYPE_N)); +} + +__only_inline int isgraph(int _c) +{ + return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c] & + (_CTYPE_P|_CTYPE_U|_CTYPE_L|_CTYPE_N))); +} + +__only_inline int islower(int _c) +{ + return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c] & _CTYPE_L)); +} + +__only_inline int isprint(int _c) +{ + return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c] & + (_CTYPE_P|_CTYPE_U|_CTYPE_L|_CTYPE_N|_CTYPE_B))); +} + +__only_inline int ispunct(int _c) +{ + return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c] & _CTYPE_P)); +} + +__only_inline int isspace(int _c) +{ + return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c] & _CTYPE_S)); +} + +__only_inline int isupper(int _c) +{ + return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c] & _CTYPE_U)); +} + +__only_inline int isxdigit(int _c) +{ + return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c] & + (_CTYPE_N|_CTYPE_X))); +} + +__only_inline int tolower(int _c) +{ + if ((unsigned int)_c > 255) + return (_c); + return ((_tolower_tab_ + 1)[_c]); +} + +__only_inline int toupper(int _c) +{ + if ((unsigned int)_c > 255) + return (_c); + return ((_toupper_tab_ + 1)[_c]); +} + +#if __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999 || __POSIX_VISIBLE > 200112 \ + || __XPG_VISIBLE > 600 +__only_inline int isblank(int _c) +{ + return (_c == ' ' || _c == '\t'); +} +#endif + +#if __BSD_VISIBLE || __XPG_VISIBLE +__only_inline int isascii(int _c) +{ + return ((unsigned int)_c <= 0177); +} + +__only_inline int toascii(int _c) +{ + return (_c & 0177); +} + +__only_inline int _tolower(int _c) +{ + return (_c - 'A' + 'a'); +} + +__only_inline int _toupper(int _c) +{ + return (_c - 'a' + 'A'); +} +#endif /* __BSD_VISIBLE || __XPG_VISIBLE */ + +#if __POSIX_VISIBLE >= 200809 +__only_inline int +isalnum_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return isalnum(_c); +} + +__only_inline int +isalpha_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return isalpha(_c); +} + +__only_inline int +isblank_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return isblank(_c); +} + +__only_inline int +iscntrl_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return iscntrl(_c); +} + +__only_inline int +isdigit_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return isdigit(_c); +} + +__only_inline int +isgraph_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return isgraph(_c); +} + +__only_inline int +islower_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return islower(_c); +} + +__only_inline int +isprint_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return isprint(_c); +} + +__only_inline int +ispunct_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return ispunct(_c); +} + +__only_inline int +isspace_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return isspace(_c); +} + +__only_inline int +isupper_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return isupper(_c); +} + +__only_inline int +isxdigit_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return isxdigit(_c); +} + +__only_inline int +tolower_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return tolower(_c); +} + +__only_inline int +toupper_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return toupper(_c); +} +#endif /* __POSIX_VISIBLE >= 200809 */ + +#endif /* !_ANSI_LIBRARY */ + +__END_DECLS + +#endif /* !_CTYPE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/db.h b/lib/libc/include/generic-openbsd/db.h new file mode 100644 index 000000000000..13678ac00b83 --- /dev/null +++ b/lib/libc/include/generic-openbsd/db.h @@ -0,0 +1,161 @@ +/* $OpenBSD: db.h,v 1.12 2015/10/17 21:48:42 guenther Exp $ */ +/* $NetBSD: db.h,v 1.13 1994/10/26 00:55:48 cgd Exp $ */ + +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)db.h 8.7 (Berkeley) 6/16/94 + */ + +#ifndef _DB_H_ +#define _DB_H_ + +#include + +#include + +#define RET_ERROR -1 /* Return values. */ +#define RET_SUCCESS 0 +#define RET_SPECIAL 1 + +#define MAX_PAGE_NUMBER 0xffffffff /* >= # of pages in a file */ +typedef u_int32_t pgno_t; +#define MAX_PAGE_OFFSET 65535 /* >= # of bytes in a page */ +typedef u_int16_t indx_t; +#define MAX_REC_NUMBER 0xffffffff /* >= # of records in a tree */ +typedef u_int32_t recno_t; + +/* Key/data structure -- a Data-Base Thang. */ +typedef struct { + void *data; /* data */ + size_t size; /* data length */ +} DBT; + +/* Routine flags. */ +#define R_CURSOR 1 /* del, put, seq */ +#define __R_UNUSED 2 /* UNUSED */ +#define R_FIRST 3 /* seq */ +#define R_IAFTER 4 /* put (RECNO) */ +#define R_IBEFORE 5 /* put (RECNO) */ +#define R_LAST 6 /* seq (BTREE, RECNO) */ +#define R_NEXT 7 /* seq */ +#define R_NOOVERWRITE 8 /* put */ +#define R_PREV 9 /* seq (BTREE, RECNO) */ +#define R_SETCURSOR 10 /* put (RECNO) */ +#define R_RECNOSYNC 11 /* sync (RECNO) */ + +typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE; + +/* + * !!! + * The following flags are included in the dbopen(3) call as part of the + * open(2) flags. In order to avoid conflicts with the open flags, start + * at the top of the 16 or 32-bit number space and work our way down. If + * the open flags were significantly expanded in the future, it could be + * a problem. Wish I'd left another flags word in the dbopen call. + * + * !!! + * None of this stuff is implemented yet. The only reason that it's here + * is so that the access methods can skip copying the key/data pair when + * the DB_LOCK flag isn't set. + */ +#if UINT_MAX > 65535 +#define DB_LOCK 0x20000000 /* Do locking. */ +#define DB_SHMEM 0x40000000 /* Use shared memory. */ +#define DB_TXN 0x80000000 /* Do transactions. */ +#else +#define DB_LOCK 0x2000 /* Do locking. */ +#define DB_SHMEM 0x4000 /* Use shared memory. */ +#define DB_TXN 0x8000 /* Do transactions. */ +#endif + +/* Access method description structure. */ +typedef struct __db { + DBTYPE type; /* Underlying db type. */ + int (*close)(struct __db *); + int (*del)(const struct __db *, const DBT *, unsigned int); + int (*get)(const struct __db *, const DBT *, DBT *, unsigned int); + int (*put)(const struct __db *, DBT *, const DBT *, unsigned int); + int (*seq)(const struct __db *, DBT *, DBT *, unsigned int); + int (*sync)(const struct __db *, unsigned int); + void *internal; /* Access method private. */ + int (*fd)(const struct __db *); +} DB; + +#define BTREEMAGIC 0x053162 +#define BTREEVERSION 3 + +/* Structure used to pass parameters to the btree routines. */ +typedef struct { +#define R_DUP 0x01 /* duplicate keys */ + unsigned long flags; + unsigned int cachesize; /* bytes to cache */ + int maxkeypage; /* maximum keys per page */ + int minkeypage; /* minimum keys per page */ + unsigned int psize; /* page size */ + int (*compare) /* comparison function */ + (const DBT *, const DBT *); + size_t (*prefix) /* prefix function */ + (const DBT *, const DBT *); + int lorder; /* byte order */ +} BTREEINFO; + +#define HASHMAGIC 0x061561 +#define HASHVERSION 2 + +/* Structure used to pass parameters to the hashing routines. */ +typedef struct { + unsigned int bsize; /* bucket size */ + unsigned int ffactor; /* fill factor */ + unsigned int nelem; /* number of elements */ + unsigned int cachesize; /* bytes to cache */ + u_int32_t /* hash function */ + (*hash)(const void *, size_t); + int lorder; /* byte order */ +} HASHINFO; + +/* Structure used to pass parameters to the record routines. */ +typedef struct { +#define R_FIXEDLEN 0x01 /* fixed-length records */ +#define R_NOKEY 0x02 /* key not required */ +#define R_SNAPSHOT 0x04 /* snapshot the input */ + unsigned long flags; + unsigned int cachesize; /* bytes to cache */ + unsigned int psize; /* page size */ + int lorder; /* byte order */ + size_t reclen; /* record length + (fixed-length records) */ + unsigned char bval; /* delimiting byte + (variable-length records) */ + char *bfname; /* btree file name */ +} RECNOINFO; + +__BEGIN_DECLS +DB *dbopen(const char *, int, int, DBTYPE, const void *); +__END_DECLS +#endif /* !_DB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ddb/db_access.h b/lib/libc/include/generic-openbsd/ddb/db_access.h new file mode 100644 index 000000000000..6b5fa5d7997b --- /dev/null +++ b/lib/libc/include/generic-openbsd/ddb/db_access.h @@ -0,0 +1,40 @@ +/* $OpenBSD: db_access.h,v 1.12 2024/02/23 18:19:02 cheloha Exp $ */ +/* $NetBSD: db_access.h,v 1.6 1994/10/09 08:29:57 mycroft Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + * + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ + +/* + * Data access functions for debugger. + */ +db_expr_t db_get_value(vaddr_t, size_t, int); +void db_put_value(vaddr_t, size_t, db_expr_t); + +void db_read_bytes(vaddr_t, size_t, void *); +void db_write_bytes(vaddr_t, size_t, void *); \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ddb/db_break.h b/lib/libc/include/generic-openbsd/ddb/db_break.h new file mode 100644 index 000000000000..63cbd0b59dc2 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ddb/db_break.h @@ -0,0 +1,61 @@ +/* $OpenBSD: db_break.h,v 1.12 2019/11/07 13:16:25 mpi Exp $ */ +/* $NetBSD: db_break.h,v 1.8 1996/02/05 01:56:52 christos Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + * + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ + +#ifndef _DDB_DB_BREAK_H_ +#define _DDB_DB_BREAK_H_ + +#include + +/* + * Breakpoints. + */ +typedef struct db_breakpoint { + vaddr_t address; /* set here */ + int init_count; /* number of times to skip bkpt */ + int count; /* current count */ + int flags; /* flags: */ +#define BKPT_SINGLE_STEP 0x2 /* to simulate single step */ +#define BKPT_TEMP 0x4 /* temporary */ + int bkpt_inst; /* saved instruction at bkpt */ + struct db_breakpoint *link; /* link in in-use or free chain */ +} *db_breakpoint_t; + +db_breakpoint_t db_find_breakpoint(vaddr_t); +void db_set_breakpoints(void); +void db_clear_breakpoints(void); +db_breakpoint_t db_set_temp_breakpoint(vaddr_t); +void db_delete_temp_breakpoint(db_breakpoint_t); +void db_delete_cmd(db_expr_t, int, db_expr_t, char *); +void db_breakpoint_cmd(db_expr_t, int, db_expr_t, char *); +void db_listbreak_cmd(db_expr_t, int, db_expr_t, char *); + +#endif /* _DDB_DB_BREAK_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ddb/db_command.h b/lib/libc/include/generic-openbsd/ddb/db_command.h new file mode 100644 index 000000000000..3a8d81bd960c --- /dev/null +++ b/lib/libc/include/generic-openbsd/ddb/db_command.h @@ -0,0 +1,62 @@ +/* $OpenBSD: db_command.h,v 1.35 2022/04/14 19:47:12 naddy Exp $ */ +/* $NetBSD: db_command.h,v 1.8 1996/02/05 01:56:55 christos Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + * + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ + +/* + * Command loop declarations. + */ +struct db_command; + +void db_error(char *); +void db_skip_to_eol(void); +void db_command_loop(void); +void db_command(const struct db_command **, const struct db_command *); + +extern vaddr_t db_dot, db_last_addr, db_prev, db_next; + +/* + * Command table + */ +struct db_command { + char *name; /* command name */ + /* function to call */ + void (*fcn)(db_expr_t, int, db_expr_t, char *); + int flag; /* extra info: */ +#define CS_OWN 0x1 /* non-standard syntax */ +#define CS_MORE 0x2 /* standard syntax, but may have other + words at end */ +#define CS_SET_DOT 0x100 /* set dot after command */ + const struct db_command *more; /* another level of command */ +}; + +#ifdef DB_MACHINE_COMMANDS +extern const struct db_command db_machine_command_table[]; +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ddb/db_elf.h b/lib/libc/include/generic-openbsd/ddb/db_elf.h new file mode 100644 index 000000000000..a57ca0bfabf6 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ddb/db_elf.h @@ -0,0 +1,48 @@ +/* $OpenBSD: db_elf.h,v 1.3 2024/11/07 16:02:29 miod Exp $ */ +/* $NetBSD: db_elf.c,v 1.13 2000/07/07 21:55:18 jhawk Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +typedef struct { + const char *name; /* symtab name */ + char *start; /* symtab location */ + char *end; + char *private; /* optional machdep pointer */ +} db_symtab_t; + + +#define STAB_TO_SYMSTART(stab) ((Elf_Sym *)((stab)->start)) +#define STAB_TO_SYMEND(stab) ((Elf_Sym *)((stab)->end)) +#define STAB_TO_EHDR(stab) ((Elf_Ehdr *)((stab)->private)) +#define STAB_TO_SHDR(stab, e) ((Elf_Shdr *)((stab)->private + (e)->e_shoff)) + +const char *db_elf_find_strtab(db_symtab_t *); +const char *db_elf_find_section(db_symtab_t *, size_t *, const char *); \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ddb/db_extern.h b/lib/libc/include/generic-openbsd/ddb/db_extern.h new file mode 100644 index 000000000000..02a6650ced79 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ddb/db_extern.h @@ -0,0 +1,64 @@ +/* $OpenBSD: db_extern.h,v 1.22 2024/05/13 01:15:50 jsg Exp $ */ +/* $NetBSD: db_extern.h,v 1.1 1996/02/05 01:57:00 christos Exp $ */ + +/* + * Copyright (c) 1995 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _DDB_DB_EXTERN_H_ +#define _DDB_DB_EXTERN_H_ + +/* db_sym.c */ +void ddb_init(void); + +/* db_examine.c */ +void db_examine_cmd(db_expr_t, int, db_expr_t, char *); +void db_print_cmd(db_expr_t, int, db_expr_t, char *); +void db_search_cmd(db_expr_t, int, db_expr_t, char *); +void db_print_loc_and_inst(vaddr_t); +size_t db_strlcpy(char *, const char *, size_t); + +/* db_expr.c */ +int db_expression(db_expr_t *); + +/* db_hangman.c */ +void db_hangman(db_expr_t, int, db_expr_t, char *); + +/* db_input.c */ +int db_readline(char *, int); + +/* db_trap.c */ +void db_trap(int, int); + +/* db_prof.c */ +int db_prof_enable(void); +void db_prof_disable(void); + +/* db_ctf.c */ +void db_ctf_init(void); + +#endif /* _DDB_DB_EXTERN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ddb/db_interface.h b/lib/libc/include/generic-openbsd/ddb/db_interface.h new file mode 100644 index 000000000000..b13f0be9f350 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ddb/db_interface.h @@ -0,0 +1,86 @@ +/* $OpenBSD: db_interface.h,v 1.28 2024/09/05 08:52:27 bluhm Exp $ */ +/* $NetBSD: db_interface.h,v 1.1 1996/02/05 01:57:03 christos Exp $ */ + +/* + * Copyright (c) 1995 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _DDB_DB_INTERFACE_H_ +#define _DDB_DB_INTERFACE_H_ + +/* arch///db_trace.c */ +void db_stack_trace_print(db_expr_t, int, db_expr_t, char *, + int (*)(const char *, ...)); + +/* arch///db_disasm.c */ +vaddr_t db_disasm(vaddr_t, int); + +/* kern/kern_proc.c */ +void db_kill_cmd(db_expr_t, int, db_expr_t, char *); +void db_show_all_procs(db_expr_t, int, db_expr_t, char *); + +/* kern/kern_clockintr.c */ +void db_show_all_clockintr(db_expr_t, int, db_expr_t, char *); + +/* kern/kern_timeout.c */ +void db_show_callout(db_expr_t, int, db_expr_t, char *); + +struct mount; + +/* kern/vfs_subr.c */ +void vfs_buf_print(void *, int, int (*)(const char *, ...)); +void vfs_vnode_print(void *, int, int (*)(const char *, ...)); +void vfs_mount_print(struct mount *, int, int (*)(const char *, ...)); + +/* kern/subr_pool.c */ +void db_show_all_pools(db_expr_t, int, db_expr_t, char *); + +/* kern/uipc_mbuf.c */ +void m_print(void *, int (*)(const char *, ...)); +void m_print_chain(void *, int, int (*)(const char *, ...)); +void m_print_packet(void *, int, int (*)(const char *, ...)); + +/* kern/uipc_socket.c */ +void so_print(void *, int (*)(const char *, ...)); + +struct rtentry; +int db_show_rtentry(struct rtentry *, void *, unsigned int); +int db_show_rtable(int, unsigned int); + +/* nfs/nfs_debug.c */ +void db_show_all_nfsreqs(db_expr_t, int, db_expr_t, char *); +void nfs_request_print(void *, int, int (*)(const char *, ...)); +void db_show_all_nfsnodes(db_expr_t, int, db_expr_t, char *); +void nfs_node_print(void *, int, int (*)(const char *, ...)); + +/* uvm/uvm_swap.c */ +void swap_print_all(int (*)(const char *, ...)); + +/* arch///db_interface.c */ +void db_machine_init(void); + +#endif /* _DDB_DB_INTERFACE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ddb/db_lex.h b/lib/libc/include/generic-openbsd/ddb/db_lex.h new file mode 100644 index 000000000000..5aeb188575ae --- /dev/null +++ b/lib/libc/include/generic-openbsd/ddb/db_lex.h @@ -0,0 +1,66 @@ +/* $OpenBSD: db_lex.h,v 1.9 2016/04/19 12:23:25 mpi Exp $ */ +/* $NetBSD: db_lex.h,v 1.7 1996/02/05 01:57:07 christos Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + * + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ + +/* + * Lexical analyzer. + */ +int db_read_line(void); +void db_unread_token(int); +int db_read_token(void); +void db_flush_lex(void); +int db_lex(void); + +extern db_expr_t db_tok_number; +#define TOK_STRING_SIZE 120 +extern char db_tok_string[TOK_STRING_SIZE]; + +#define tEOF (-1) +#define tEOL 1 +#define tNUMBER 2 +#define tIDENT 3 +#define tPLUS 4 +#define tMINUS 5 +#define tDOT 6 +#define tSTAR 7 +#define tSLASH 8 +#define tEQ 9 +#define tLPAREN 10 +#define tRPAREN 11 +#define tPCT 12 +#define tHASH 13 +#define tCOMMA 14 +#define tDITTO 15 +#define tDOLLAR 16 +#define tEXCL 17 +#define tSHIFT_L 18 +#define tSHIFT_R 19 +#define tDOTDOT 20 \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ddb/db_output.h b/lib/libc/include/generic-openbsd/ddb/db_output.h new file mode 100644 index 000000000000..9c6aa0719d6c --- /dev/null +++ b/lib/libc/include/generic-openbsd/ddb/db_output.h @@ -0,0 +1,65 @@ +/* $OpenBSD: db_output.h,v 1.17 2021/02/09 14:37:13 jcs Exp $ */ +/* $NetBSD: db_output.h,v 1.9 1996/04/04 05:13:50 cgd Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + * + * Author: David B. Golub, Carnegie Mellon University + * Date: 8/90 + */ + +/* + * Printing routines for kernel debugger. + */ +void db_force_whitespace(void); +void db_putchar(int); +int db_print_position(void); +int db_printf(const char *, ...) + __attribute__((__format__(__kprintf__,1,2))); +int db_vprintf(const char *, va_list) + __attribute__((__format__(__kprintf__,1,0))); +void db_end_line(int); +void db_resize(int, int); + +/* + * This is a replacement for the non-standard %z, %n and %r printf formats + * in db_printf. + * + * db_format(buf, bufsize, val, format, alt, width) + * + * val is the value we want printed. + * format is one of DB_FORMAT_[ZRN] + * alt specifies if we should provide an "alternate" format (# in the printf + * format). + * width is the field width. 0 is the same as no width specifier. + */ +#define DB_FORMAT_Z 1 +#define DB_FORMAT_R 2 +#define DB_FORMAT_N 3 +#define DB_FORMAT_BUF_SIZE 64 /* should be plenty for all formats */ +char *db_format(char *, size_t, long, int, int, int); + +/* XXX - this is the wrong place, but we have no better. */ +void db_stack_dump(void); \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ddb/db_run.h b/lib/libc/include/generic-openbsd/ddb/db_run.h new file mode 100644 index 000000000000..b5354473ac09 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ddb/db_run.h @@ -0,0 +1,66 @@ +/* $OpenBSD: db_run.h,v 1.12 2019/11/06 07:30:08 mpi Exp $ */ +/* $NetBSD: db_run.h,v 1.3 1996/02/05 01:57:14 christos Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + * + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ + +#ifndef _DDB_DB_RUN_ +#define _DDB_DB_RUN_ + +/* + * Commands to run process. + */ +extern int db_inst_count; +extern int db_cmd_loop_done; + +int db_stop_at_pc(db_regs_t *, int *); +void db_restart_at_pc(db_regs_t *, int); +void db_single_step(db_regs_t *); +#ifndef db_set_single_step +void db_set_single_step(db_regs_t *); +#endif +#ifndef db_clear_single_step +void db_clear_single_step(db_regs_t *); +#endif +void db_single_step_cmd(db_expr_t, int, db_expr_t, char *); +void db_trace_until_call_cmd(db_expr_t, int, db_expr_t, char *); +void db_trace_until_matching_cmd(db_expr_t, int, db_expr_t, char *); +void db_continue_cmd(db_expr_t, int, db_expr_t, char *); + +#ifdef SOFTWARE_SSTEP +/* + * I've seen this defined to (0) when it is not needed and then the proto will + * not be correct, so skip it then. + */ +#ifndef getreg_val +extern register_t getreg_val(db_regs_t *, int); +#endif +#endif /* SOFTWARE_SSTEP */ + +#endif /* _DDB_DB_RUN_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ddb/db_sym.h b/lib/libc/include/generic-openbsd/ddb/db_sym.h new file mode 100644 index 000000000000..4d91c1df203f --- /dev/null +++ b/lib/libc/include/generic-openbsd/ddb/db_sym.h @@ -0,0 +1,97 @@ +/* $NetBSD: db_sym.h,v 1.13 2000/05/25 19:57:36 jhawk Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + * + * Author: Alessandro Forin, Carnegie Mellon University + * Date: 8/90 + */ + +#ifndef _DDB_DB_SYM_H_ +#define _DDB_DB_SYM_H_ + +#include +#include + +/* + * Non-stripped symbol tables will have duplicates, for instance + * the same string could match a parameter name, a local var, a + * global var, etc. + * We are most concern with the following matches. + */ +typedef int db_strategy_t; /* search strategy */ + +#define DB_STGY_ANY 0 /* anything goes */ +#define DB_STGY_XTRN 1 /* only external symbols */ +#define DB_STGY_PROC 2 /* only procedures */ + + +/* + * Internal db_forall function calling convention: + * + * (*db_forall_func)(sym, name, suffix, arg); + * + * symbol is the (opaque) symbol pointer, name the name of the symbol, + * suffix a string representing the type, and arg an opaque argument to + * be passed in. + */ +typedef void (db_forall_func_t)(Elf_Sym *, const char *, const char *, void *); + +extern unsigned int db_maxoff; /* like gdb's "max-symbolic-offset" */ + +int db_eqname(const char *, const char *, int); + /* strcmp, modulo leading char */ + +Elf_Sym * db_symbol_by_name(const char *, db_expr_t *); + /* find symbol value given name */ + +Elf_Sym * db_search_symbol(vaddr_t, db_strategy_t, db_expr_t *); + /* find symbol given value */ + +void db_symbol_values(Elf_Sym *, const char **, db_expr_t *); + /* return name and value of symbol */ + +#define db_find_sym_and_offset(val,namep,offp) \ + db_symbol_values(db_search_symbol(val,DB_STGY_ANY,offp),namep,NULL) + /* find name&value given approx val */ + +#define db_find_xtrn_sym_and_offset(val,namep,offp) \ + db_symbol_values(db_search_symbol(val,DB_STGY_XTRN,offp),namep,NULL) + /* ditto, but no locals */ + +void db_printsym(db_expr_t, db_strategy_t, int (*)(const char *, ...)); + /* print closest symbol to a value */ + +int db_elf_sym_init(int, void *, void *, const char *); +Elf_Sym * db_elf_sym_search(vaddr_t, db_strategy_t, db_expr_t *); +int db_elf_line_at_pc(Elf_Sym *, const char **, int *, db_expr_t); +void db_elf_sym_forall(db_forall_func_t db_forall_func, void *); + +bool db_dwarf_line_at_pc(const char *, size_t, uintptr_t, + const char **, const char **, int *); + +int db_ctf_func_numargs(Elf_Sym *); + +#endif /* _DDB_DB_SYM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ddb/db_var.h b/lib/libc/include/generic-openbsd/ddb/db_var.h new file mode 100644 index 000000000000..29dbce1adc0e --- /dev/null +++ b/lib/libc/include/generic-openbsd/ddb/db_var.h @@ -0,0 +1,79 @@ +/* $OpenBSD: db_var.h,v 1.15 2025/05/19 21:48:28 kettenis Exp $ */ + +/* + * Copyright (c) 1996 Michael Shalayeff. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Different parameters/structures/functions + */ + +#ifndef _DDB_DB_VAR_H_ +#define _DDB_DB_VAR_H_ + +#ifndef DB_HISTORY_SIZE +#define DB_HISTORY_SIZE 4000 +#endif + +#define DBCTL_RADIX 1 +#define DBCTL_MAXWIDTH 2 +#define DBCTL_MAXLINE 3 +#define DBCTL_TABSTOP 4 +#define DBCTL_PANIC 5 +#define DBCTL_CONSOLE 6 +#define DBCTL_LOG 7 +#define DBCTL_TRIGGER 8 +#define DBCTL_PROFILE 9 +#define DBCTL_SUSPEND 10 +#define DBCTL_MAXID 11 + +#define CTL_DDB_NAMES { \ + { NULL, 0 }, \ + { "radix", CTLTYPE_INT }, \ + { "max_width", CTLTYPE_INT }, \ + { "max_line", CTLTYPE_INT }, \ + { "tab_stop_width", CTLTYPE_INT },\ + { "panic", CTLTYPE_INT }, \ + { "console", CTLTYPE_INT }, \ + { "log", CTLTYPE_INT }, \ + { "trigger", CTLTYPE_INT }, \ + { "profile", CTLTYPE_INT }, \ + { "suspend", CTLTYPE_INT }, \ +} + +#ifdef _KERNEL +extern int db_radix; +extern int db_max_width; +extern int db_tab_stop_width; +extern int db_max_line; +extern int db_panic; +extern int db_console; +extern int db_log; +extern int db_profile; +extern int db_suspend; + +int ddb_sysctl(int *, u_int, void *, size_t *, void *, size_t, + struct proc *); +#endif + +#endif /* _DDB_DB_VAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ddb/db_variables.h b/lib/libc/include/generic-openbsd/ddb/db_variables.h new file mode 100644 index 000000000000..c3c5cbc67cfc --- /dev/null +++ b/lib/libc/include/generic-openbsd/ddb/db_variables.h @@ -0,0 +1,62 @@ +/* $OpenBSD: db_variables.h,v 1.8 2016/01/25 14:30:30 mpi Exp $ */ +/* $NetBSD: db_variables.h,v 1.5 1996/02/05 01:57:21 christos Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + * + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ + +#ifndef _DB_VARIABLES_H_ +#define _DB_VARIABLES_H_ + +/* + * Debugger variables. + */ +struct db_variable { + char *name; /* Name of variable */ + long *valuep; /* value of variable */ + /* function to call when reading/writing */ + int (*fcn)(struct db_variable *, db_expr_t *, int); +#define DB_VAR_GET 0 +#define DB_VAR_SET 1 +}; +#define FCN_NULL ((int (*)(struct db_variable *, db_expr_t *, int))0) + +extern struct db_variable db_vars[]; /* debugger variables */ +extern struct db_variable *db_evars; +extern struct db_variable db_regs[]; /* machine registers */ +extern struct db_variable *db_eregs; + +int db_find_variable(struct db_variable **); +int db_get_variable(db_expr_t *); +int db_set_variable(db_expr_t); +void db_read_variable(struct db_variable *, db_expr_t *); +void db_write_variable(struct db_variable *, db_expr_t *); +void db_set_cmd(db_expr_t, int, db_expr_t, char *); +int db_var_rw_int(struct db_variable *, db_expr_t *, int); + +#endif /* _DB_VARIABLES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ddb/db_watch.h b/lib/libc/include/generic-openbsd/ddb/db_watch.h new file mode 100644 index 000000000000..8d3c4e0d5eed --- /dev/null +++ b/lib/libc/include/generic-openbsd/ddb/db_watch.h @@ -0,0 +1,56 @@ +/* $OpenBSD: db_watch.h,v 1.11 2019/11/07 13:16:25 mpi Exp $ */ +/* $NetBSD: db_watch.h,v 1.9 1996/02/05 01:57:24 christos Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + * + * Author: David B. Golub, Carnegie Mellon University + * Date: 10/90 + */ + +#ifndef _DDB_DB_WATCH_ +#define _DDB_DB_WATCH_ + +/* + * Watchpoint. + */ +typedef struct db_watchpoint { + vaddr_t loaddr; /* from this address */ + vaddr_t hiaddr; /* to this address */ + struct db_watchpoint *link; /* link in in-use or free chain */ +} *db_watchpoint_t; + +db_watchpoint_t db_watchpoint_alloc(void); +void db_watchpoint_free(db_watchpoint_t); +void db_set_watchpoint(vaddr_t, vsize_t); +void db_delete_watchpoint(vaddr_t); +void db_list_watchpoints(void); +void db_deletewatch_cmd(db_expr_t, int, db_expr_t, char *); +void db_watchpoint_cmd(db_expr_t, int, db_expr_t, char *); +void db_listwatch_cmd(db_expr_t, int, db_expr_t, char *); +void db_set_watchpoints(void); +void db_clear_watchpoints(void); + +#endif /* _DDB_DB_WATCH_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/dirent.h b/lib/libc/include/generic-openbsd/dirent.h new file mode 100644 index 000000000000..895284c4b7fb --- /dev/null +++ b/lib/libc/include/generic-openbsd/dirent.h @@ -0,0 +1,107 @@ +/* $OpenBSD: dirent.h,v 1.35 2024/04/15 15:47:58 florian Exp $ */ +/* $NetBSD: dirent.h,v 1.9 1995/03/26 20:13:37 jtc Exp $ */ + +/*- + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)dirent.h 8.2 (Berkeley) 7/28/94 + */ + +#ifndef _DIRENT_H_ +#define _DIRENT_H_ + +#include + +/* + * POSIX doesn't mandate this, but X/Open XPG 4.2 does. + */ +#if __BSD_VISIBLE || __XPG_VISIBLE >= 400 +#include +#else +#include +#endif + +/* + * The kernel defines the format of directory entries returned by + * the getdents(2) system call. + */ +#include + +#if __BSD_VISIBLE || __XPG_VISIBLE +#define d_ino d_fileno /* backward compatibility */ +#endif + +typedef struct _dirdesc DIR; + +#if __BSD_VISIBLE + +/* definitions for library routines operating on directories. */ +#define DIRBLKSIZ 1024 + +#include + +#endif /* __BSD_VISIBLE */ + +__BEGIN_DECLS +DIR *opendir(const char *); +#if __POSIX_VISIBLE >= 200809 +DIR *fdopendir(int); +#endif +struct dirent *readdir(DIR *); +void rewinddir(DIR *); +int closedir(DIR *); +#if __BSD_VISIBLE +int getdents(int, void *, size_t) + __attribute__ ((__bounded__(__string__,2,3))); +#endif /* __BSD_VISIBLE */ +#if __XPG_VISIBLE +long telldir(DIR *); +void seekdir(DIR *, long); +#endif +#if __POSIX_VISIBLE >= 199506 || __XPG_VISIBLE >= 500 +int readdir_r(DIR *__restrict, struct dirent *__restrict, + struct dirent **__restrict); +#endif +#if __POSIX_VISIBLE >= 200809 +int scandir(const char *, struct dirent ***, int (*)(const struct dirent *), + int (*)(const struct dirent **, const struct dirent **)); +int scandirat(int, const char *, struct dirent ***, + int (*)(const struct dirent *), + int (*)(const struct dirent **, const struct dirent **)); +int alphasort(const struct dirent **, const struct dirent **); +#elif __BSD_VISIBLE +int scandir(const char *, struct dirent ***, int (*)(struct dirent *), + int (*)(const void *, const void *)); +int alphasort(const void *, const void *); +#endif +#if __POSIX_VISIBLE >= 200809 || __XPG_VISIBLE > 600 +int dirfd(DIR *); +#endif +__END_DECLS + +#endif /* !_DIRENT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/dlfcn.h b/lib/libc/include/generic-openbsd/dlfcn.h new file mode 100644 index 000000000000..5097588e7bdf --- /dev/null +++ b/lib/libc/include/generic-openbsd/dlfcn.h @@ -0,0 +1,110 @@ +/* $OpenBSD: dlfcn.h,v 1.17 2024/09/01 04:27:45 guenther Exp $ */ +/* $NetBSD: dlfcn.h,v 1.2 1995/06/05 19:38:00 pk Exp $ */ + +/* + * Copyright (c) 1995 Paul Kranenburg + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Paul Kranenburg. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _DLFCN_H_ +#define _DLFCN_H_ + +#include + +/* Values for dlopen `mode'. */ +#define RTLD_LAZY 1 +#define RTLD_NOW 2 +#define RTLD_GLOBAL 0x100 +#define RTLD_LOCAL 0x000 +#define RTLD_TRACE 0x200 +#define RTLD_NODELETE 0x400 +#define RTLD_NOLOAD 0x800 + +/* + * Special handle arguments for dlsym(). + */ +#define RTLD_NEXT ((void *) -1) /* Search subsequent objects. */ +#define RTLD_DEFAULT ((void *) -2) /* Use default search algorithm. */ +#define RTLD_SELF ((void *) -3) /* Search the caller itself. */ + +#if __BSD_VISIBLE || __POSIX_VISIBLE >= 202405 +/* + * Structure filled in by dladdr(). + */ +typedef struct +#if __BSD_VISIBLE + dl_info +#endif +{ + const char *dli_fname; /* Pathname of shared object. */ + void *dli_fbase; /* Base address of shared object. */ + const char *dli_sname; /* Name of nearest symbol. */ + void *dli_saddr; /* Address of nearest symbol. */ +} Dl_info_t; +#endif /* __BSD_VISIBLE || __POSIX_VISIBLE >= 202405 */ + +#if __BSD_VISIBLE +typedef Dl_info_t Dl_info; + +/* + * dlctl() commands + */ +#define DL_GETERRNO 1 +#define DL_SETSRCHPATH x +#define DL_GETLIST x +#define DL_GETREFCNT x +#define DL_GETLOADADDR x +#define DL_SETTHREADLCK 2 +#define DL_SETBINDLCK 3 +#define DL_REFERENCE 4 + +#define DL_LAZY RTLD_LAZY /* Compat */ + +#endif /* __BSD_VISIBLE */ + + +/* + * User interface to the run-time linker. + */ +__BEGIN_DECLS +void *dlopen(const char *, int); +int dlclose(void *); +void *dlsym(void *__restrict, const char *__restrict); +char *dlerror(void); + +#if __BSD_VISIBLE || __POSIX_VISIBLE >= 202405 +int dladdr(const void *__restrict, Dl_info_t *__restrict); +#endif + +#if __BSD_VISIBLE +int dlctl(void *, int, void *); +#endif /* __BSD_VISIBLE */ + +__END_DECLS + +#endif /* _DLFCN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/elf.h b/lib/libc/include/generic-openbsd/elf.h new file mode 100644 index 000000000000..3b0998883095 --- /dev/null +++ b/lib/libc/include/generic-openbsd/elf.h @@ -0,0 +1,12 @@ +/* $OpenBSD: elf.h,v 1.1 2017/10/17 09:34:52 mpi Exp $ */ + +/* + * Public domain. + */ + +#ifndef _ELF_H_ +#define _ELF_H_ + +#include + +#endif /* _ELF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/elf_abi.h b/lib/libc/include/generic-openbsd/elf_abi.h new file mode 100644 index 000000000000..e722035d3334 --- /dev/null +++ b/lib/libc/include/generic-openbsd/elf_abi.h @@ -0,0 +1,33 @@ +/* $OpenBSD: elf_abi.h,v 1.4 1996/05/22 07:46:22 etheisen Exp $ */ +/* + * Copyright (c) 1996 Erik Theisen + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _ELF_ABI_H_ +#define _ELF_ABI_H_ + +#include + +#endif /* _ELF_ABI_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/endian.h b/lib/libc/include/generic-openbsd/endian.h new file mode 100644 index 000000000000..f4328aa9deae --- /dev/null +++ b/lib/libc/include/generic-openbsd/endian.h @@ -0,0 +1,124 @@ +/* $OpenBSD: endian.h,v 1.25 2014/12/21 04:49:00 guenther Exp $ */ + +/*- + * Copyright (c) 1997 Niklas Hallqvist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Public definitions for little- and big-endian systems. + * This file should be included as in userspace and as + * in the kernel. + * + * System headers that need endian information but that can't or don't + * want to export the public names here should include + * and use the internal names: _BYTE_ORDER, _*_ENDIAN, etc. + */ + +#ifndef _SYS_ENDIAN_H_ +#define _SYS_ENDIAN_H_ + +#include +#include + +/* Public names */ +#define LITTLE_ENDIAN _LITTLE_ENDIAN +#define BIG_ENDIAN _BIG_ENDIAN +#define PDP_ENDIAN _PDP_ENDIAN +#define BYTE_ORDER _BYTE_ORDER + + +/* + * These are specified to be function-like macros to match the spec + */ +#define htobe16(x) __htobe16(x) +#define htobe32(x) __htobe32(x) +#define htobe64(x) __htobe64(x) +#define htole16(x) __htole16(x) +#define htole32(x) __htole32(x) +#define htole64(x) __htole64(x) + +/* POSIX names */ +#define be16toh(x) __htobe16(x) +#define be32toh(x) __htobe32(x) +#define be64toh(x) __htobe64(x) +#define le16toh(x) __htole16(x) +#define le32toh(x) __htole32(x) +#define le64toh(x) __htole64(x) + + +#if __BSD_VISIBLE +#define swap16(x) __swap16(x) +#define swap32(x) __swap32(x) +#define swap64(x) __swap64(x) + +#define swap16_multi(v, n) do { \ + __size_t __swap16_multi_n = (n); \ + __uint16_t *__swap16_multi_v = (v); \ + \ + while (__swap16_multi_n) { \ + *__swap16_multi_v = swap16(*__swap16_multi_v); \ + __swap16_multi_v++; \ + __swap16_multi_n--; \ + } \ +} while (0) + +/* original BSD names */ +#define betoh16(x) __htobe16(x) +#define betoh32(x) __htobe32(x) +#define betoh64(x) __htobe64(x) +#define letoh16(x) __htole16(x) +#define letoh32(x) __htole32(x) +#define letoh64(x) __htole64(x) + +#ifndef htons +/* these were exposed here before */ +#define htons(x) __htobe16(x) +#define htonl(x) __htobe32(x) +#define ntohs(x) __htobe16(x) +#define ntohl(x) __htobe32(x) +#endif + +/* ancient stuff */ +#define NTOHL(x) (x) = ntohl((u_int32_t)(x)) +#define NTOHS(x) (x) = ntohs((u_int16_t)(x)) +#define HTONL(x) (x) = htonl((u_int32_t)(x)) +#define HTONS(x) (x) = htons((u_int16_t)(x)) +#endif /* __BSD_VISIBLE */ + +#ifdef _KERNEL +/* to/from memory conversions */ +#define bemtoh16 __bemtoh16 +#define bemtoh32 __bemtoh32 +#define bemtoh64 __bemtoh64 +#define htobem16 __htobem16 +#define htobem32 __htobem32 +#define htobem64 __htobem64 +#define lemtoh16 __lemtoh16 +#define lemtoh32 __lemtoh32 +#define lemtoh64 __lemtoh64 +#define htolem16 __htolem16 +#define htolem32 __htolem32 +#define htolem64 __htolem64 +#endif /* _KERNEL */ + +#endif /* _SYS_ENDIAN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/err.h b/lib/libc/include/generic-openbsd/err.h new file mode 100644 index 000000000000..e5dda625bcc4 --- /dev/null +++ b/lib/libc/include/generic-openbsd/err.h @@ -0,0 +1,70 @@ +/* $OpenBSD: err.h,v 1.13 2015/08/31 02:53:56 guenther Exp $ */ +/* $NetBSD: err.h,v 1.11 1994/10/26 00:55:52 cgd Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)err.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _ERR_H_ +#define _ERR_H_ + +#include +#include /* for __va_list */ + +__BEGIN_DECLS + +__dead void err(int, const char *, ...) + __attribute__((__format__ (printf, 2, 3))); +__dead void verr(int, const char *, __va_list) + __attribute__((__format__ (printf, 2, 0))); +__dead void errc(int, int, const char *, ...) + __attribute__((__format__ (printf, 3, 4))); +__dead void verrc(int, int, const char *, __va_list) + __attribute__((__format__ (printf, 3, 0))); +__dead void errx(int, const char *, ...) + __attribute__((__format__ (printf, 2, 3))); +__dead void verrx(int, const char *, __va_list) + __attribute__((__format__ (printf, 2, 0))); +void warn(const char *, ...) + __attribute__((__format__ (printf, 1, 2))); +void vwarn(const char *, __va_list) + __attribute__((__format__ (printf, 1, 0))); +void warnc(int, const char *, ...) + __attribute__((__format__ (printf, 2, 3))); +void vwarnc(int, const char *, __va_list) + __attribute__((__format__ (printf, 2, 0))); +void warnx(const char *, ...) + __attribute__((__format__ (printf, 1, 2))); +void vwarnx(const char *, __va_list) + __attribute__((__format__ (printf, 1, 0))); + +__END_DECLS + +#endif /* !_ERR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/errno.h b/lib/libc/include/generic-openbsd/errno.h new file mode 100644 index 000000000000..a60343854617 --- /dev/null +++ b/lib/libc/include/generic-openbsd/errno.h @@ -0,0 +1,59 @@ +/* $OpenBSD: errno.h,v 1.3 2017/08/10 13:34:46 guenther Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)errno.h 8.5 (Berkeley) 1/21/94 + */ + +#ifndef _ERRNO_H_ +#define _ERRNO_H_ + +#include + +__BEGIN_DECLS +#if __BSD_VISIBLE +#ifndef __SYS_ERRLIST +#define __SYS_ERRLIST +extern int sys_nerr; +extern char *sys_errlist[]; +#endif /* __SYS_ERRLIST */ +#endif /* __BSD_VISIBLE */ + +#ifndef errno +int *__errno(void); +#define errno (*__errno()) +#endif /* errno */ +__END_DECLS + +#endif /* _ERRNO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/execinfo.h b/lib/libc/include/generic-openbsd/execinfo.h new file mode 100644 index 000000000000..fd1bd83a1136 --- /dev/null +++ b/lib/libc/include/generic-openbsd/execinfo.h @@ -0,0 +1,45 @@ +/* $OpenBSD: execinfo.h,v 1.1 2021/06/09 19:37:43 mortimer Exp $ */ + +/*- + * Copyright (c) 2012 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _EXECINFO_H_ +#define _EXECINFO_H_ + +#include +#include + +__BEGIN_DECLS +size_t backtrace(void **, size_t); +char **backtrace_symbols(void *const *, size_t); +int backtrace_symbols_fd(void *const *, size_t, int); +char **backtrace_symbols_fmt(void *const *, size_t, const char *); +int backtrace_symbols_fd_fmt(void *const *, size_t, int, const char *); +__END_DECLS + +#endif /* _EXECINFO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/fcntl.h b/lib/libc/include/generic-openbsd/fcntl.h new file mode 100644 index 000000000000..ddd098c940e3 --- /dev/null +++ b/lib/libc/include/generic-openbsd/fcntl.h @@ -0,0 +1,231 @@ +/* $OpenBSD: fcntl.h,v 1.23 2025/08/04 04:59:30 guenther Exp $ */ +/* $NetBSD: fcntl.h,v 1.8 1995/03/26 20:24:12 jtc Exp $ */ + +/*- + * Copyright (c) 1983, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)fcntl.h 8.3 (Berkeley) 1/21/94 + */ + +#ifndef _SYS_FCNTL_H_ +#define _SYS_FCNTL_H_ + +/* + * This file includes the definitions for open and fcntl + * described by POSIX for ; it also includes + * related kernel definitions. + */ + +#include +#ifndef _KERNEL +#include +#endif + +/* + * File status flags: these are used by open(2), fcntl(2). + * They are also used (indirectly) in the kernel file structure f_flags, + * which is a superset of the open/fcntl flags. Open flags and f_flags + * are inter-convertible using OFLAGS(fflags) and FFLAGS(oflags). + * Open/fcntl flags begin with O_; kernel-internal flags begin with F. + */ +/* open-only flags */ +#define O_RDONLY 0x0000 /* open for reading only */ +#define O_WRONLY 0x0001 /* open for writing only */ +#define O_RDWR 0x0002 /* open for reading and writing */ +#define O_ACCMODE 0x0003 /* mask for above modes */ + +/* + * Kernel encoding of open mode; separate read and write bits that are + * independently testable: 1 greater than the above. + * + * XXX + * FREAD and FWRITE are excluded from the #ifdef _KERNEL so that TIOCFLUSH, + * which was documented to use FREAD/FWRITE, continues to work. + */ +#if __BSD_VISIBLE +#define FREAD 0x0001 +#define FWRITE 0x0002 +#endif +#define O_NONBLOCK 0x0004 /* no delay */ +#define O_APPEND 0x0008 /* set append mode */ +#if __BSD_VISIBLE +#define O_SHLOCK 0x0010 /* open with shared file lock */ +#define O_EXLOCK 0x0020 /* open with exclusive file lock */ +#define O_ASYNC 0x0040 /* signal pgrp when data ready */ +#define O_FSYNC 0x0080 /* backwards compatibility */ +#endif +#if __POSIX_VISIBLE >= 199309 || __XPG_VISIBLE >= 420 +#define O_SYNC 0x0080 /* synchronous writes */ +/* + * POSIX 1003.1 permits a higher granularity for synchronous operations + * than we support. Since synchronicity is all or nothing in OpenBSD + * we just define these to be the same as O_SYNC. + */ +#define O_DSYNC O_SYNC /* synchronous data writes */ +#define O_RSYNC O_SYNC /* synchronous reads */ +#endif + +/* defined by POSIX Issue 7 */ +#define O_NOFOLLOW 0x0100 /* if path is a symlink, don't follow */ + +#define O_CREAT 0x0200 /* create if nonexistent */ +#define O_TRUNC 0x0400 /* truncate to zero length */ +#define O_EXCL 0x0800 /* error if already exists */ + +/* defined by POSIX 1003.1; BSD default, this bit is not required */ +#define O_NOCTTY 0x8000 /* don't assign controlling terminal */ + +/* defined by POSIX Issue 7 */ +#define O_CLOEXEC 0x10000 /* atomically set FD_CLOEXEC */ +#define O_DIRECTORY 0x20000 /* fail if not a directory */ + +/* defined by POSIX Issue 8 */ +#define O_CLOFORK 0x40000 /* atomically set FD_CLOFORK */ + +#ifdef _KERNEL +/* + * convert from open() flags to/from fflags; convert O_RD/WR to FREAD/FWRITE. + * For out-of-range values for the flags, be slightly careful (but lossy). + */ +#define FFLAGS(oflags) (((oflags) & ~O_ACCMODE) | (((oflags) + 1) & O_ACCMODE)) +#define OFLAGS(fflags) (((fflags) & ~O_ACCMODE) | (((fflags) - 1) & O_ACCMODE)) + +/* bits to save after open */ +#define FMASK (FREAD|FWRITE|FAPPEND|FASYNC|FFSYNC|FNONBLOCK) +/* bits settable by fcntl(F_SETFL, ...) */ +#define FCNTLFLAGS (FAPPEND|FASYNC|FFSYNC|FNONBLOCK) +#endif + +/* + * The O_* flags used to have only F* names, which were used in the kernel + * and by fcntl. We retain the F* names for the kernel f_flags field + * and for backward compatibility for fcntl. + */ +#if __BSD_VISIBLE +#define FAPPEND O_APPEND /* kernel/compat */ +#define FASYNC O_ASYNC /* kernel/compat */ +#define FFSYNC O_SYNC /* kernel */ +#define FNONBLOCK O_NONBLOCK /* kernel */ +#define FNDELAY O_NONBLOCK /* compat */ +#define O_NDELAY O_NONBLOCK /* compat */ +#endif + +/* + * Constants used for fcntl(2) + */ + +/* command values */ +#define F_DUPFD 0 /* duplicate file descriptor */ +#define F_GETFD 1 /* get file descriptor flags */ +#define F_SETFD 2 /* set file descriptor flags */ +#define F_GETFL 3 /* get file status flags */ +#define F_SETFL 4 /* set file status flags */ +#if __POSIX_VISIBLE >= 200112 || __XPG_VISIBLE >= 500 +#define F_GETOWN 5 /* get SIGIO/SIGURG proc/pgrp */ +#define F_SETOWN 6 /* set SIGIO/SIGURG proc/pgrp */ +#endif +#define F_GETLK 7 /* get record locking information */ +#define F_SETLK 8 /* set record locking information */ +#define F_SETLKW 9 /* F_SETLK; wait if blocked */ +#if __POSIX_VISIBLE >= 200809 +#define F_DUPFD_CLOEXEC 10 /* duplicate with FD_CLOEXEC set */ +#endif +#if __BSD_VISIBLE +#define F_ISATTY 11 /* used by isatty(3) */ +#endif +#if __POSIX_VISIBLE >= 202405 +#define F_DUPFD_CLOFORK 12 /* duplicate with FD_CLOFORK set */ +#endif + +/* file descriptor flags (F_GETFD, F_SETFD) */ +#define FD_CLOEXEC 1 /* close-on-exec flag */ +#if __POSIX_VISIBLE >= 202405 +#define FD_CLOFORK 4 /* close-on-fork flag */ +#endif + +/* record locking flags (F_GETLK, F_SETLK, F_SETLKW) */ +#define F_RDLCK 1 /* shared or read lock */ +#define F_UNLCK 2 /* unlock */ +#define F_WRLCK 3 /* exclusive or write lock */ +#ifdef _KERNEL +#define F_WAIT 0x010 /* Wait until lock is granted */ +#define F_FLOCK 0x020 /* Use flock(2) semantics for lock */ +#define F_POSIX 0x040 /* Use POSIX semantics for lock */ +#define F_INTR 0x080 /* Lock operation interrupted */ +#endif + +/* + * Advisory file segment locking data type - + * information passed to system by user + */ +struct flock { + off_t l_start; /* starting offset */ + off_t l_len; /* len = 0 means until end of file */ + pid_t l_pid; /* lock owner */ + short l_type; /* lock type: read/write, etc. */ + short l_whence; /* type of l_start */ +}; + + +#if __BSD_VISIBLE +/* lock operations for flock(2) */ +#define LOCK_SH 0x01 /* shared file lock */ +#define LOCK_EX 0x02 /* exclusive file lock */ +#define LOCK_NB 0x04 /* don't block when locking */ +#define LOCK_UN 0x08 /* unlock file */ +#endif + +#if __POSIX_VISIBLE >= 200809 +#define AT_FDCWD -100 + +#define AT_EACCESS 0x01 +#define AT_SYMLINK_NOFOLLOW 0x02 +#define AT_SYMLINK_FOLLOW 0x04 +#define AT_REMOVEDIR 0x08 +#endif + +#ifndef _KERNEL +__BEGIN_DECLS +int open(const char *, int, ...); +int creat(const char *, mode_t); +int fcntl(int, int, ...); +#if __BSD_VISIBLE +int flock(int, int); +#endif +#if __POSIX_VISIBLE >= 200809 +int openat(int, const char *, int, ...); +#endif +__END_DECLS +#endif + +#endif /* !_SYS_FCNTL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/fenv.h b/lib/libc/include/generic-openbsd/fenv.h new file mode 100644 index 000000000000..3d6a2b35ad17 --- /dev/null +++ b/lib/libc/include/generic-openbsd/fenv.h @@ -0,0 +1,60 @@ +/* $OpenBSD: fenv.h,v 1.2 2011/05/25 21:46:49 martynas Exp $ */ +/* $NetBSD: fenv.h,v 1.2.4.1 2011/02/08 16:18:55 bouyer Exp $ */ + +/* + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _FENV_H_ +#define _FENV_H_ + +#include +#include + +__BEGIN_DECLS + +int feclearexcept(int); +int fegetexceptflag(fexcept_t *, int); +int feraiseexcept(int); +int fesetexceptflag(const fexcept_t *, int); +int fetestexcept(int); + +int fegetround(void); +int fesetround(int); + +int fegetenv(fenv_t *); +int feholdexcept(fenv_t *); +int fesetenv(const fenv_t *); +int feupdateenv(const fenv_t *); + +#if __BSD_VISIBLE +int feenableexcept(int); +int fedisableexcept(int); +int fegetexcept(void); +#endif /* __BSD_VISIBLE */ + +__END_DECLS + +#endif /* ! _FENV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/float.h b/lib/libc/include/generic-openbsd/float.h new file mode 100644 index 000000000000..e9fd9907c833 --- /dev/null +++ b/lib/libc/include/generic-openbsd/float.h @@ -0,0 +1,95 @@ +/* $OpenBSD: float.h,v 1.1 2012/06/26 16:16:16 deraadt Exp $ */ + +/* + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _FLOAT_H_ +#define _FLOAT_H_ + +#include +#include + +__BEGIN_DECLS +int __flt_rounds(void); +__END_DECLS + +#define FLT_RADIX __FLT_RADIX /* b */ +#define FLT_ROUNDS __FLT_ROUNDS + +#if __ISO_C_VISIBLE >= 1999 +#define FLT_EVAL_METHOD __FLT_EVAL_METHOD /* long double */ +#endif + +#define FLT_MANT_DIG __FLT_MANT_DIG /* p */ +#define FLT_EPSILON __FLT_EPSILON /* b**(1-p) */ +#ifndef FLT_DIG +#define FLT_DIG __FLT_DIG /* floor((p-1)*log10(b))+(b == 10) */ +#endif +#define FLT_MIN_EXP __FLT_MIN_EXP /* emin */ +#ifndef FLT_MIN +#define FLT_MIN __FLT_MIN /* b**(emin-1) */ +#endif +#define FLT_MIN_10_EXP __FLT_MIN_10_EXP /* ceil(log10(b**(emin-1))) */ +#define FLT_MAX_EXP __FLT_MAX_EXP /* emax */ +#ifndef FLT_MAX +#define FLT_MAX __FLT_MAX /* (1-b**(-p))*b**emax */ +#endif +#define FLT_MAX_10_EXP __FLT_MAX_10_EXP /* floor(log10((1-b**(-p))*b**emax)) */ + +#define DBL_MANT_DIG __DBL_MANT_DIG +#define DBL_EPSILON __DBL_EPSILON +#ifndef DBL_DIG +#define DBL_DIG __DBL_DIG +#endif +#define DBL_MIN_EXP __DBL_MIN_EXP +#ifndef DBL_MIN +#define DBL_MIN __DBL_MIN +#endif +#define DBL_MIN_10_EXP __DBL_MIN_10_EXP +#define DBL_MAX_EXP __DBL_MAX_EXP +#ifndef DBL_MAX +#define DBL_MAX __DBL_MAX +#endif +#define DBL_MAX_10_EXP __DBL_MAX_10_EXP + +#define LDBL_MANT_DIG __LDBL_MANT_DIG +#define LDBL_EPSILON __LDBL_EPSILON +#define LDBL_DIG __LDBL_DIG +#define LDBL_MIN_EXP __LDBL_MIN_EXP +#define LDBL_MIN __LDBL_MIN +#define LDBL_MIN_10_EXP __LDBL_MIN_10_EXP +#define LDBL_MAX_EXP __LDBL_MAX_EXP +#define LDBL_MAX __LDBL_MAX +#define LDBL_MAX_10_EXP __LDBL_MAX_10_EXP + +#if __ISO_C_VISIBLE >= 1999 +#define DECIMAL_DIG __DECIMAL_DIG +#endif + +#endif /* _FLOAT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/fnmatch.h b/lib/libc/include/generic-openbsd/fnmatch.h new file mode 100644 index 000000000000..bb0a769261c8 --- /dev/null +++ b/lib/libc/include/generic-openbsd/fnmatch.h @@ -0,0 +1,57 @@ +/* $OpenBSD: fnmatch.h,v 1.8 2005/12/13 00:35:22 millert Exp $ */ +/* $NetBSD: fnmatch.h,v 1.5 1994/10/26 00:55:53 cgd Exp $ */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)fnmatch.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _FNMATCH_H_ +#define _FNMATCH_H_ + +#include + +#define FNM_NOMATCH 1 /* Match failed. */ +#define FNM_NOSYS 2 /* Function not supported (unused). */ + +#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */ +#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */ +#define FNM_PERIOD 0x04 /* Period must be matched by period. */ +#if __BSD_VISIBLE +#define FNM_LEADING_DIR 0x08 /* Ignore / after Imatch. */ +#define FNM_CASEFOLD 0x10 /* Case insensitive search. */ +#define FNM_IGNORECASE FNM_CASEFOLD +#define FNM_FILE_NAME FNM_PATHNAME +#endif + +__BEGIN_DECLS +int fnmatch(const char *, const char *, int); +__END_DECLS + +#endif /* !_FNMATCH_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/fstab.h b/lib/libc/include/generic-openbsd/fstab.h new file mode 100644 index 000000000000..3e511cfcbe88 --- /dev/null +++ b/lib/libc/include/generic-openbsd/fstab.h @@ -0,0 +1,78 @@ +/* $OpenBSD: fstab.h,v 1.5 2003/06/02 19:34:12 millert Exp $ */ +/* $NetBSD: fstab.h,v 1.3 1994/10/26 00:55:53 cgd Exp $ */ + +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)fstab.h 5.12 (Berkeley) 4/3/91 + */ + +#ifndef _FSTAB_H_ +#define _FSTAB_H_ + +/* + * File system table, see fstab(5). + * + * Used by dump, mount, umount, swapon, fsck, df, ... + * + * For ufs fs_spec field is the block special name. Programs that want to + * use the character special name must create that name by prepending a 'r' + * after the right most slash. Quota files are always named "quotas", so + * if type is "rq", then use concatenation of fs_file and "quotas" to locate + * quota file. + */ +#define _PATH_FSTAB "/etc/fstab" +#define FSTAB "/etc/fstab" /* deprecated */ + +#define FSTAB_RW "rw" /* read/write device */ +#define FSTAB_RQ "rq" /* read/write with quotas */ +#define FSTAB_RO "ro" /* read-only device */ +#define FSTAB_SW "sw" /* swap device */ +#define FSTAB_XX "xx" /* ignore totally */ + +struct fstab { + char *fs_spec; /* block special device name */ + char *fs_file; /* file system path prefix */ + char *fs_vfstype; /* File system type, ufs, nfs */ + char *fs_mntops; /* Mount options ala -o */ + char *fs_type; /* FSTAB_* from fs_mntops */ + int fs_freq; /* dump frequency, in days */ + int fs_passno; /* pass number on parallel fsck */ +}; + +#include + +__BEGIN_DECLS +struct fstab *getfsent(void); +struct fstab *getfsspec(const char *); +struct fstab *getfsfile(const char *); +int setfsent(void); +void endfsent(void); +__END_DECLS + +#endif /* !_FSTAB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/fts.h b/lib/libc/include/generic-openbsd/fts.h new file mode 100644 index 000000000000..b174dcda827e --- /dev/null +++ b/lib/libc/include/generic-openbsd/fts.h @@ -0,0 +1,125 @@ +/* $OpenBSD: fts.h,v 1.14 2012/12/05 23:19:57 deraadt Exp $ */ +/* $NetBSD: fts.h,v 1.5 1994/12/28 01:41:50 mycroft Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)fts.h 8.3 (Berkeley) 8/14/94 + */ + +#ifndef _FTS_H_ +#define _FTS_H_ + +typedef struct { + struct _ftsent *fts_cur; /* current node */ + struct _ftsent *fts_child; /* linked list of children */ + struct _ftsent **fts_array; /* sort array */ + dev_t fts_dev; /* starting device # */ + char *fts_path; /* path for this descent */ + int fts_rfd; /* fd for root */ + size_t fts_pathlen; /* sizeof(path) */ + int fts_nitems; /* elements in the sort array */ + int (*fts_compar)(); /* compare function */ + +#define FTS_COMFOLLOW 0x0001 /* follow command line symlinks */ +#define FTS_LOGICAL 0x0002 /* logical walk */ +#define FTS_NOCHDIR 0x0004 /* don't change directories */ +#define FTS_NOSTAT 0x0008 /* don't get stat info */ +#define FTS_PHYSICAL 0x0010 /* physical walk */ +#define FTS_SEEDOT 0x0020 /* return dot and dot-dot */ +#define FTS_XDEV 0x0040 /* don't cross devices */ +#define FTS_OPTIONMASK 0x00ff /* valid user option mask */ + +#define FTS_NAMEONLY 0x1000 /* (private) child names only */ +#define FTS_STOP 0x2000 /* (private) unrecoverable error */ + int fts_options; /* fts_open options, global flags */ +} FTS; + +typedef struct _ftsent { + struct _ftsent *fts_cycle; /* cycle node */ + struct _ftsent *fts_parent; /* parent directory */ + struct _ftsent *fts_link; /* next file in directory */ + long fts_number; /* local numeric value */ + void *fts_pointer; /* local address value */ + char *fts_accpath; /* access path */ + char *fts_path; /* root path */ + int fts_errno; /* errno for this node */ + int fts_symfd; /* fd for symlink */ + size_t fts_pathlen; /* strlen(fts_path) */ + size_t fts_namelen; /* strlen(fts_name) */ + + ino_t fts_ino; /* inode */ + dev_t fts_dev; /* device */ + nlink_t fts_nlink; /* link count */ + +#define FTS_ROOTPARENTLEVEL -1 +#define FTS_ROOTLEVEL 0 +#define FTS_MAXLEVEL 0x7fffffff + int fts_level; /* depth (-1 to N) */ + +#define FTS_D 1 /* preorder directory */ +#define FTS_DC 2 /* directory that causes cycles */ +#define FTS_DEFAULT 3 /* none of the above */ +#define FTS_DNR 4 /* unreadable directory */ +#define FTS_DOT 5 /* dot or dot-dot */ +#define FTS_DP 6 /* postorder directory */ +#define FTS_ERR 7 /* error; errno is set */ +#define FTS_F 8 /* regular file */ +#define FTS_INIT 9 /* initialized only */ +#define FTS_NS 10 /* stat(2) failed */ +#define FTS_NSOK 11 /* no stat(2) requested */ +#define FTS_SL 12 /* symbolic link */ +#define FTS_SLNONE 13 /* symbolic link without target */ + unsigned short fts_info; /* user flags for FTSENT structure */ + +#define FTS_DONTCHDIR 0x01 /* don't chdir .. to the parent */ +#define FTS_SYMFOLLOW 0x02 /* followed a symlink to get here */ + unsigned short fts_flags; /* private flags for FTSENT structure */ + +#define FTS_AGAIN 1 /* read node again */ +#define FTS_FOLLOW 2 /* follow symbolic link */ +#define FTS_NOINSTR 3 /* no instructions */ +#define FTS_SKIP 4 /* discard node */ + unsigned short fts_instr; /* fts_set() instructions */ + + unsigned short fts_spare; /* unused */ + + struct stat *fts_statp; /* stat(2) information */ + char fts_name[1]; /* file name */ +} FTSENT; + +__BEGIN_DECLS +FTSENT *fts_children(FTS *, int); +int fts_close(FTS *); +FTS *fts_open(char * const *, int, + int (*)(const FTSENT **, const FTSENT **)); +FTSENT *fts_read(FTS *); +int fts_set(FTS *, FTSENT *, int); +__END_DECLS + +#endif /* !_FTS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ftw.h b/lib/libc/include/generic-openbsd/ftw.h new file mode 100644 index 000000000000..bed70565abe3 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ftw.h @@ -0,0 +1,60 @@ +/* $OpenBSD: ftw.h,v 1.2 2019/01/25 00:19:25 millert Exp $ */ + +/* + * Copyright (c) 2003 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ + +#ifndef _FTW_H +#define _FTW_H + +#include +#include + +/* + * Valid flags for the 3rd argument to the function that is passed as the + * second argument to ftw(3) and nftw(3). Say it three times fast! + */ +#define FTW_F 0 /* File. */ +#define FTW_D 1 /* Directory. */ +#define FTW_DNR 2 /* Directory without read permission. */ +#define FTW_DP 3 /* Directory with subdirectories visited. */ +#define FTW_NS 4 /* Unknown type; stat() failed. */ +#define FTW_SL 5 /* Symbolic link. */ +#define FTW_SLN 6 /* Sym link that names a nonexistent file. */ + +/* + * Flags for use as the 4th argument to nftw(3). These may be ORed together. + */ +#define FTW_PHYS 0x01 /* Physical walk, don't follow sym links. */ +#define FTW_MOUNT 0x02 /* The walk does not cross a mount point. */ +#define FTW_DEPTH 0x04 /* Subdirs visited before the dir itself. */ +#define FTW_CHDIR 0x08 /* Change to a directory before reading it. */ + +struct FTW { + int base; + int level; +}; + +__BEGIN_DECLS +int ftw(const char *, int (*)(const char *, const struct stat *, int), int); +int nftw(const char *, int (*)(const char *, const struct stat *, int, + struct FTW *), int, int); +__END_DECLS + +#endif /* !_FTW_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/getopt.h b/lib/libc/include/generic-openbsd/getopt.h new file mode 100644 index 000000000000..d1c93e2d5492 --- /dev/null +++ b/lib/libc/include/generic-openbsd/getopt.h @@ -0,0 +1,76 @@ +/* $OpenBSD: getopt.h,v 1.3 2013/11/22 21:32:49 millert Exp $ */ +/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _GETOPT_H_ +#define _GETOPT_H_ + +#include + +/* + * GNU-like getopt_long() + */ +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +struct option { + /* name of long option */ + const char *name; + /* + * one of no_argument, required_argument, and optional_argument: + * whether option takes an argument + */ + int has_arg; + /* if not NULL, set *flag to val when option found */ + int *flag; + /* if flag not NULL, value to set *flag to; else return value */ + int val; +}; + +__BEGIN_DECLS +int getopt_long(int, char * const *, const char *, + const struct option *, int *); +int getopt_long_only(int, char * const *, const char *, + const struct option *, int *); +#ifndef _GETOPT_DEFINED_ +#define _GETOPT_DEFINED_ +int getopt(int, char * const *, const char *); + +extern char *optarg; /* getopt(3) external variables */ +extern int opterr; +extern int optind; +extern int optopt; +extern int optreset; +#endif +__END_DECLS + +#endif /* !_GETOPT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/glob.h b/lib/libc/include/generic-openbsd/glob.h new file mode 100644 index 000000000000..cfb2e3ee8894 --- /dev/null +++ b/lib/libc/include/generic-openbsd/glob.h @@ -0,0 +1,103 @@ +/* $OpenBSD: glob.h,v 1.14 2019/02/04 16:45:40 millert Exp $ */ +/* $NetBSD: glob.h,v 1.5 1994/10/26 00:55:56 cgd Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Guido van Rossum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)glob.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _GLOB_H_ +#define _GLOB_H_ + +#include +#include + +#ifndef _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED_ +typedef __size_t size_t; +#endif + +struct stat; +typedef struct { + size_t gl_pathc; /* Count of total paths so far. */ + size_t gl_matchc; /* Count of paths matching pattern. */ + size_t gl_offs; /* Reserved at beginning of gl_pathv. */ + int gl_flags; /* Copy of flags parameter to glob. */ + char **gl_pathv; /* List of paths matching pattern. */ + struct stat **gl_statv; /* Stat entries corresponding to gl_pathv */ + /* Copy of errfunc parameter to glob. */ + int (*gl_errfunc)(const char *, int); + + /* + * Alternate filesystem access methods for glob; replacement + * versions of closedir(3), readdir(3), opendir(3), stat(2) + * and lstat(2). + */ + void (*gl_closedir)(void *); + struct dirent *(*gl_readdir)(void *); + void *(*gl_opendir)(const char *); + int (*gl_lstat)(const char *, struct stat *); + int (*gl_stat)(const char *, struct stat *); +} glob_t; + +#define GLOB_APPEND 0x0001 /* Append to output from previous call. */ +#define GLOB_DOOFFS 0x0002 /* Use gl_offs. */ +#define GLOB_ERR 0x0004 /* Return on error. */ +#define GLOB_MARK 0x0008 /* Append / to matching directories. */ +#define GLOB_NOCHECK 0x0010 /* Return pattern itself if nothing matches. */ +#define GLOB_NOSORT 0x0020 /* Don't sort. */ +#define GLOB_NOESCAPE 0x1000 /* Disable backslash escaping. */ + +#define GLOB_NOSPACE (-1) /* Malloc call failed. */ +#define GLOB_ABORTED (-2) /* Unignored error. */ +#define GLOB_NOMATCH (-3) /* No match and GLOB_NOCHECK not set. */ +#define GLOB_NOSYS (-4) /* Function not supported. */ + +#if __BSD_VISIBLE +#define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */ +#define GLOB_BRACE 0x0080 /* Expand braces ala csh. */ +#define GLOB_MAGCHAR 0x0100 /* Pattern had globbing characters. */ +#define GLOB_NOMAGIC 0x0200 /* GLOB_NOCHECK without magic chars (csh). */ +#define GLOB_QUOTE 0x0400 /* Quote special chars with \. */ +#define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */ +#define GLOB_LIMIT 0x2000 /* Limit pattern match output to ARG_MAX */ +#define GLOB_KEEPSTAT 0x4000 /* Retain stat data for paths in gl_statv. */ +#define GLOB_ABEND GLOB_ABORTED /* backward compatibility */ +#endif + +__BEGIN_DECLS +int glob(const char *__restrict, int, int (*)(const char *, int), + glob_t *__restrict); +void globfree(glob_t *); +__END_DECLS + +#endif /* !_GLOB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/grp.h b/lib/libc/include/generic-openbsd/grp.h new file mode 100644 index 000000000000..8fb76195d731 --- /dev/null +++ b/lib/libc/include/generic-openbsd/grp.h @@ -0,0 +1,78 @@ +/* $OpenBSD: grp.h,v 1.13 2018/09/13 12:31:15 millert Exp $ */ +/* $NetBSD: grp.h,v 1.7 1995/04/29 05:30:40 cgd Exp $ */ + +/*- + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)grp.h 8.2 (Berkeley) 1/21/94 + */ + +#ifndef _GRP_H_ +#define _GRP_H_ + +#include + +#if __BSD_VISIBLE +#define _PATH_GROUP "/etc/group" +#define _GR_BUF_LEN (1024+200*sizeof(char*)) +#endif + +struct group { + char *gr_name; /* group name */ + char *gr_passwd; /* group password */ + gid_t gr_gid; /* group id */ + char **gr_mem; /* group members */ +}; + +__BEGIN_DECLS +struct group *getgrgid(gid_t); +struct group *getgrnam(const char *); +#if __BSD_VISIBLE || __XPG_VISIBLE +struct group *getgrent(void); +void setgrent(void); +void endgrent(void); +#endif +#if __BSD_VISIBLE || __POSIX_VISIBLE >= 199506 || __XPG_VISIBLE +int getgrgid_r(gid_t, struct group *, char *, + size_t, struct group **); +int getgrnam_r(const char *, struct group *, char *, + size_t, struct group **); +#endif +#if __BSD_VISIBLE +int setgroupent(int); +int gid_from_group(const char *, gid_t *); +const char *group_from_gid(gid_t, int); +#endif +__END_DECLS + +#endif /* !_GRP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/icdb.h b/lib/libc/include/generic-openbsd/icdb.h new file mode 100644 index 000000000000..4136cd6e6d40 --- /dev/null +++ b/lib/libc/include/generic-openbsd/icdb.h @@ -0,0 +1,44 @@ +/* $OpenBSD: icdb.h,v 1.4 2016/09/04 14:51:39 nicm Exp $ */ +/* + * Copyright (c) 2015 Ted Unangst + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _ICDB_H_ +#define _ICDB_H_ + +#include + +__BEGIN_DECLS + +struct icdb; + +struct icdb *icdb_new(uint32_t version, uint32_t nentries, uint32_t entrysize, + uint32_t nkeys, const uint32_t *keysizes, const uint32_t *keyoffsets); + +struct icdb *icdb_open(const char *name, int flags, uint32_t version); +int icdb_get(struct icdb *db, void *entry, uint32_t idx); +int icdb_lookup(struct icdb *db, int keynum, const void *key, void *entry, + uint32_t *idxp); +int icdb_nentries(struct icdb *db); +const void *icdb_entries(struct icdb *db); +int icdb_update(struct icdb *db, const void *entry, int offset); +int icdb_add(struct icdb *db, const void *entry); +int icdb_rehash(struct icdb *db); +int icdb_save(struct icdb *db, int fd); +int icdb_close(struct icdb *db); + +__END_DECLS + +#endif /* !_ICDB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ieeefp.h b/lib/libc/include/generic-openbsd/ieeefp.h new file mode 100644 index 000000000000..3f4c0019a6bd --- /dev/null +++ b/lib/libc/include/generic-openbsd/ieeefp.h @@ -0,0 +1,23 @@ +/* $OpenBSD: ieeefp.h,v 1.4 2009/09/27 21:23:55 martynas Exp $ */ + +/* + * Written by J.T. Conklin, Apr 6, 1995 + * Public domain. + */ + +#ifndef _IEEEFP_H_ +#define _IEEEFP_H_ + +#include +#include + +__BEGIN_DECLS +extern fp_rnd fpgetround(void); +extern fp_rnd fpsetround(fp_rnd); +extern fp_except fpgetmask(void); +extern fp_except fpsetmask(fp_except); +extern fp_except fpgetsticky(void); +extern fp_except fpsetsticky(fp_except); +__END_DECLS + +#endif /* _IEEEFP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ifaddrs.h b/lib/libc/include/generic-openbsd/ifaddrs.h new file mode 100644 index 000000000000..cffb0fe243d4 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ifaddrs.h @@ -0,0 +1,56 @@ +/* $OpenBSD: ifaddrs.h,v 1.4 2004/01/22 21:48:02 espie Exp $ */ + +/* + * Copyright (c) 1995, 1999 + * Berkeley Software Design, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``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 Berkeley Software Design, Inc. 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. + * + * BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp + */ + +#ifndef _IFADDRS_H_ +#define _IFADDRS_H_ + +struct ifaddrs { + struct ifaddrs *ifa_next; + char *ifa_name; + unsigned int ifa_flags; + struct sockaddr *ifa_addr; + struct sockaddr *ifa_netmask; + struct sockaddr *ifa_dstaddr; + void *ifa_data; +}; + +/* + * This may have been defined in . Note that if is + * to be included it must be included before this header file. + */ +#ifndef ifa_broadaddr +#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */ +#endif + +#include + +__BEGIN_DECLS +extern int getifaddrs(struct ifaddrs **); +extern void freeifaddrs(struct ifaddrs *); +__END_DECLS + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/imsg.h b/lib/libc/include/generic-openbsd/imsg.h new file mode 100644 index 000000000000..bda67b7085ad --- /dev/null +++ b/lib/libc/include/generic-openbsd/imsg.h @@ -0,0 +1,175 @@ +/* $OpenBSD: imsg.h,v 1.24 2025/06/05 08:55:07 tb Exp $ */ + +/* + * Copyright (c) 2023 Claudio Jeker + * Copyright (c) 2006, 2007 Pierre-Yves Ritschard + * Copyright (c) 2006, 2007, 2008 Reyk Floeter + * Copyright (c) 2003, 2004 Henning Brauer + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _IMSG_H_ +#define _IMSG_H_ + +#include +#include +#include +#include + +#define IBUF_READ_SIZE 65535 +#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr) +#define MAX_IMSGSIZE 16384 + +struct ibuf { + TAILQ_ENTRY(ibuf) entry; + unsigned char *buf; + size_t size; + size_t max; + size_t wpos; + size_t rpos; + int fd; +}; + +struct ibufqueue; +struct msgbuf; + +struct imsgbuf { + struct msgbuf *w; + pid_t pid; + uint32_t maxsize; + int fd; + int flags; +}; + +struct imsg_hdr { + uint32_t type; + uint32_t len; + uint32_t peerid; + uint32_t pid; +}; + +struct imsg { + struct imsg_hdr hdr; + void *data; + struct ibuf *buf; +}; + +struct iovec; + +/* imsg-buffer.c */ +struct ibuf *ibuf_open(size_t); +struct ibuf *ibuf_dynamic(size_t, size_t); +int ibuf_add(struct ibuf *, const void *, size_t); +int ibuf_add_ibuf(struct ibuf *, const struct ibuf *); +int ibuf_add_zero(struct ibuf *, size_t); +int ibuf_add_n8(struct ibuf *, uint64_t); +int ibuf_add_n16(struct ibuf *, uint64_t); +int ibuf_add_n32(struct ibuf *, uint64_t); +int ibuf_add_n64(struct ibuf *, uint64_t); +int ibuf_add_h16(struct ibuf *, uint64_t); +int ibuf_add_h32(struct ibuf *, uint64_t); +int ibuf_add_h64(struct ibuf *, uint64_t); +int ibuf_add_strbuf(struct ibuf *, const char *, size_t); +void *ibuf_reserve(struct ibuf *, size_t); +void *ibuf_seek(struct ibuf *, size_t, size_t); +int ibuf_set(struct ibuf *, size_t, const void *, size_t); +int ibuf_set_n8(struct ibuf *, size_t, uint64_t); +int ibuf_set_n16(struct ibuf *, size_t, uint64_t); +int ibuf_set_n32(struct ibuf *, size_t, uint64_t); +int ibuf_set_n64(struct ibuf *, size_t, uint64_t); +int ibuf_set_h16(struct ibuf *, size_t, uint64_t); +int ibuf_set_h32(struct ibuf *, size_t, uint64_t); +int ibuf_set_h64(struct ibuf *, size_t, uint64_t); +int ibuf_set_maxsize(struct ibuf *, size_t); +void *ibuf_data(const struct ibuf *); +size_t ibuf_size(const struct ibuf *); +size_t ibuf_left(const struct ibuf *); +int ibuf_truncate(struct ibuf *, size_t); +void ibuf_rewind(struct ibuf *); +void ibuf_close(struct msgbuf *, struct ibuf *); +void ibuf_from_buffer(struct ibuf *, void *, size_t); +void ibuf_from_ibuf(struct ibuf *, const struct ibuf *); +int ibuf_get(struct ibuf *, void *, size_t); +int ibuf_get_ibuf(struct ibuf *, size_t, struct ibuf *); +int ibuf_get_n8(struct ibuf *, uint8_t *); +int ibuf_get_n16(struct ibuf *, uint16_t *); +int ibuf_get_n32(struct ibuf *, uint32_t *); +int ibuf_get_n64(struct ibuf *, uint64_t *); +int ibuf_get_h16(struct ibuf *, uint16_t *); +int ibuf_get_h32(struct ibuf *, uint32_t *); +int ibuf_get_h64(struct ibuf *, uint64_t *); +char *ibuf_get_string(struct ibuf *, size_t); +int ibuf_get_strbuf(struct ibuf *, char *, size_t); +int ibuf_skip(struct ibuf *, size_t); +void ibuf_free(struct ibuf *); +int ibuf_fd_avail(struct ibuf *); +int ibuf_fd_get(struct ibuf *); +void ibuf_fd_set(struct ibuf *, int); +struct msgbuf *msgbuf_new(void); +struct msgbuf *msgbuf_new_reader(size_t, + struct ibuf *(*)(struct ibuf *, void *, int *), void *); +void msgbuf_free(struct msgbuf *); +void msgbuf_clear(struct msgbuf *); +void msgbuf_concat(struct msgbuf *, struct ibufqueue *); +uint32_t msgbuf_queuelen(struct msgbuf *); +int ibuf_write(int, struct msgbuf *); +int msgbuf_write(int, struct msgbuf *); +int ibuf_read(int, struct msgbuf *); +int msgbuf_read(int, struct msgbuf *); +struct ibuf *msgbuf_get(struct msgbuf *); + +struct ibufqueue *ibufq_new(void); +void ibufq_free(struct ibufqueue *); +struct ibuf *ibufq_pop(struct ibufqueue *bufq); +void ibufq_push(struct ibufqueue *, struct ibuf *); +uint32_t ibufq_queuelen(struct ibufqueue *); +void ibufq_concat(struct ibufqueue *, struct ibufqueue *); +void ibufq_flush(struct ibufqueue *); + +/* imsg.c */ +int imsgbuf_init(struct imsgbuf *, int); +void imsgbuf_allow_fdpass(struct imsgbuf *imsgbuf); +int imsgbuf_set_maxsize(struct imsgbuf *, uint32_t); +int imsgbuf_read(struct imsgbuf *); +int imsgbuf_write(struct imsgbuf *); +int imsgbuf_flush(struct imsgbuf *); +void imsgbuf_clear(struct imsgbuf *); +uint32_t imsgbuf_queuelen(struct imsgbuf *); +int imsgbuf_get(struct imsgbuf *, struct imsg *); +ssize_t imsg_get(struct imsgbuf *, struct imsg *); +int imsg_ibufq_pop(struct ibufqueue *, struct imsg *); +void imsg_ibufq_push(struct ibufqueue *, struct imsg *); +int imsg_get_ibuf(struct imsg *, struct ibuf *); +int imsg_get_data(struct imsg *, void *, size_t); +int imsg_get_buf(struct imsg *, void *, size_t); +int imsg_get_strbuf(struct imsg *, char *, size_t); +int imsg_get_fd(struct imsg *); +uint32_t imsg_get_id(struct imsg *); +size_t imsg_get_len(struct imsg *); +pid_t imsg_get_pid(struct imsg *); +uint32_t imsg_get_type(struct imsg *); +int imsg_forward(struct imsgbuf *, struct imsg *); +int imsg_compose(struct imsgbuf *, uint32_t, uint32_t, pid_t, int, + const void *, size_t); +int imsg_composev(struct imsgbuf *, uint32_t, uint32_t, pid_t, int, + const struct iovec *, int); +int imsg_compose_ibuf(struct imsgbuf *, uint32_t, uint32_t, pid_t, + struct ibuf *); +struct ibuf *imsg_create(struct imsgbuf *, uint32_t, uint32_t, pid_t, size_t); +int imsg_add(struct ibuf *, const void *, size_t); +void imsg_close(struct imsgbuf *, struct ibuf *); +void imsg_free(struct imsg *); +int imsg_set_maxsize(struct ibuf *, size_t); + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/inttypes.h b/lib/libc/include/generic-openbsd/inttypes.h new file mode 100644 index 000000000000..e1e55594739d --- /dev/null +++ b/lib/libc/include/generic-openbsd/inttypes.h @@ -0,0 +1,265 @@ +/* $OpenBSD: inttypes.h,v 1.14 2022/07/31 01:27:31 guenther Exp $ */ + +/* + * Copyright (c) 1997, 2005 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _INTTYPES_H_ +#define _INTTYPES_H_ + +#include + +#ifdef __cplusplus +#define __wchar_t wchar_t +#elif __POSIX_VISIBLE >= 200809 && !defined(_WCHAR_T_DEFINED_) +#define _WCHAR_T_DEFINED_ +typedef __wchar_t wchar_t; +#endif + +/* + * 7.8.1 Macros for format specifiers + * + * Each of the following object-like macros expands to a string + * literal containing a conversion specifier, possibly modified by + * a prefix such as hh, h, l, or ll, suitable for use within the + * format argument of a formatted input/output function when + * converting the corresponding integer type. These macro names + * have the general form of PRI (character string literals for the + * fprintf family) or SCN (character string literals for the fscanf + * family), followed by the conversion specifier, followed by a + * name corresponding to a similar typedef name. For example, + * PRIdFAST32 can be used in a format string to print the value of + * an integer of type int_fast32_t. + */ + +/* fprintf macros for signed integers */ +#define PRId8 "d" /* int8_t */ +#define PRId16 "d" /* int16_t */ +#define PRId32 "d" /* int32_t */ +#define PRId64 "lld" /* int64_t */ + +#define PRIdLEAST8 "d" /* int_least8_t */ +#define PRIdLEAST16 "d" /* int_least16_t */ +#define PRIdLEAST32 "d" /* int_least32_t */ +#define PRIdLEAST64 "lld" /* int_least64_t */ + +#define PRIdFAST8 "d" /* int_fast8_t */ +#define PRIdFAST16 "d" /* int_fast16_t */ +#define PRIdFAST32 "d" /* int_fast32_t */ +#define PRIdFAST64 "lld" /* int_fast64_t */ + +#define PRIdMAX "jd" /* intmax_t */ +#define PRIdPTR "ld" /* intptr_t */ + +#define PRIi8 "i" /* int8_t */ +#define PRIi16 "i" /* int16_t */ +#define PRIi32 "i" /* int32_t */ +#define PRIi64 "lli" /* int64_t */ + +#define PRIiLEAST8 "i" /* int_least8_t */ +#define PRIiLEAST16 "i" /* int_least16_t */ +#define PRIiLEAST32 "i" /* int_least32_t */ +#define PRIiLEAST64 "lli" /* int_least64_t */ + +#define PRIiFAST8 "i" /* int_fast8_t */ +#define PRIiFAST16 "i" /* int_fast16_t */ +#define PRIiFAST32 "i" /* int_fast32_t */ +#define PRIiFAST64 "lli" /* int_fast64_t */ + +#define PRIiMAX "ji" /* intmax_t */ +#define PRIiPTR "li" /* intptr_t */ + +/* fprintf macros for unsigned integers */ +#define PRIo8 "o" /* int8_t */ +#define PRIo16 "o" /* int16_t */ +#define PRIo32 "o" /* int32_t */ +#define PRIo64 "llo" /* int64_t */ + +#define PRIoLEAST8 "o" /* int_least8_t */ +#define PRIoLEAST16 "o" /* int_least16_t */ +#define PRIoLEAST32 "o" /* int_least32_t */ +#define PRIoLEAST64 "llo" /* int_least64_t */ + +#define PRIoFAST8 "o" /* int_fast8_t */ +#define PRIoFAST16 "o" /* int_fast16_t */ +#define PRIoFAST32 "o" /* int_fast32_t */ +#define PRIoFAST64 "llo" /* int_fast64_t */ + +#define PRIoMAX "jo" /* intmax_t */ +#define PRIoPTR "lo" /* intptr_t */ + +#define PRIu8 "u" /* uint8_t */ +#define PRIu16 "u" /* uint16_t */ +#define PRIu32 "u" /* uint32_t */ +#define PRIu64 "llu" /* uint64_t */ + +#define PRIuLEAST8 "u" /* uint_least8_t */ +#define PRIuLEAST16 "u" /* uint_least16_t */ +#define PRIuLEAST32 "u" /* uint_least32_t */ +#define PRIuLEAST64 "llu" /* uint_least64_t */ + +#define PRIuFAST8 "u" /* uint_fast8_t */ +#define PRIuFAST16 "u" /* uint_fast16_t */ +#define PRIuFAST32 "u" /* uint_fast32_t */ +#define PRIuFAST64 "llu" /* uint_fast64_t */ + +#define PRIuMAX "ju" /* uintmax_t */ +#define PRIuPTR "lu" /* uintptr_t */ + +#define PRIx8 "x" /* uint8_t */ +#define PRIx16 "x" /* uint16_t */ +#define PRIx32 "x" /* uint32_t */ +#define PRIx64 "llx" /* uint64_t */ + +#define PRIxLEAST8 "x" /* uint_least8_t */ +#define PRIxLEAST16 "x" /* uint_least16_t */ +#define PRIxLEAST32 "x" /* uint_least32_t */ +#define PRIxLEAST64 "llx" /* uint_least64_t */ + +#define PRIxFAST8 "x" /* uint_fast8_t */ +#define PRIxFAST16 "x" /* uint_fast16_t */ +#define PRIxFAST32 "x" /* uint_fast32_t */ +#define PRIxFAST64 "llx" /* uint_fast64_t */ + +#define PRIxMAX "jx" /* uintmax_t */ +#define PRIxPTR "lx" /* uintptr_t */ + +#define PRIX8 "X" /* uint8_t */ +#define PRIX16 "X" /* uint16_t */ +#define PRIX32 "X" /* uint32_t */ +#define PRIX64 "llX" /* uint64_t */ + +#define PRIXLEAST8 "X" /* uint_least8_t */ +#define PRIXLEAST16 "X" /* uint_least16_t */ +#define PRIXLEAST32 "X" /* uint_least32_t */ +#define PRIXLEAST64 "llX" /* uint_least64_t */ + +#define PRIXFAST8 "X" /* uint_fast8_t */ +#define PRIXFAST16 "X" /* uint_fast16_t */ +#define PRIXFAST32 "X" /* uint_fast32_t */ +#define PRIXFAST64 "llX" /* uint_fast64_t */ + +#define PRIXMAX "jX" /* uintmax_t */ +#define PRIXPTR "lX" /* uintptr_t */ + +/* fscanf macros for signed integers */ +#define SCNd8 "hhd" /* int8_t */ +#define SCNd16 "hd" /* int16_t */ +#define SCNd32 "d" /* int32_t */ +#define SCNd64 "lld" /* int64_t */ + +#define SCNdLEAST8 "hhd" /* int_least8_t */ +#define SCNdLEAST16 "hd" /* int_least16_t */ +#define SCNdLEAST32 "d" /* int_least32_t */ +#define SCNdLEAST64 "lld" /* int_least64_t */ + +#define SCNdFAST8 "d" /* int_fast8_t */ +#define SCNdFAST16 "d" /* int_fast16_t */ +#define SCNdFAST32 "d" /* int_fast32_t */ +#define SCNdFAST64 "lld" /* int_fast64_t */ + +#define SCNdMAX "jd" /* intmax_t */ +#define SCNdPTR "ld" /* intptr_t */ + +#define SCNi8 "hhi" /* int8_t */ +#define SCNi16 "hi" /* int16_t */ +#define SCNi32 "i" /* int32_t */ +#define SCNi64 "lli" /* int64_t */ + +#define SCNiLEAST8 "hhi" /* int_least8_t */ +#define SCNiLEAST16 "hi" /* int_least16_t */ +#define SCNiLEAST32 "i" /* int_least32_t */ +#define SCNiLEAST64 "lli" /* int_least64_t */ + +#define SCNiFAST8 "i" /* int_fast8_t */ +#define SCNiFAST16 "i" /* int_fast16_t */ +#define SCNiFAST32 "i" /* int_fast32_t */ +#define SCNiFAST64 "lli" /* int_fast64_t */ + +#define SCNiMAX "ji" /* intmax_t */ +#define SCNiPTR "li" /* intptr_t */ + +/* fscanf macros for unsigned integers */ +#define SCNo8 "hho" /* uint8_t */ +#define SCNo16 "ho" /* uint16_t */ +#define SCNo32 "o" /* uint32_t */ +#define SCNo64 "llo" /* uint64_t */ + +#define SCNoLEAST8 "hho" /* uint_least8_t */ +#define SCNoLEAST16 "ho" /* uint_least16_t */ +#define SCNoLEAST32 "o" /* uint_least32_t */ +#define SCNoLEAST64 "llo" /* uint_least64_t */ + +#define SCNoFAST8 "o" /* uint_fast8_t */ +#define SCNoFAST16 "o" /* uint_fast16_t */ +#define SCNoFAST32 "o" /* uint_fast32_t */ +#define SCNoFAST64 "llo" /* uint_fast64_t */ + +#define SCNoMAX "jo" /* uintmax_t */ +#define SCNoPTR "lo" /* uintptr_t */ + +#define SCNu8 "hhu" /* uint8_t */ +#define SCNu16 "hu" /* uint16_t */ +#define SCNu32 "u" /* uint32_t */ +#define SCNu64 "llu" /* uint64_t */ + +#define SCNuLEAST8 "hhu" /* uint_least8_t */ +#define SCNuLEAST16 "hu" /* uint_least16_t */ +#define SCNuLEAST32 "u" /* uint_least32_t */ +#define SCNuLEAST64 "llu" /* uint_least64_t */ + +#define SCNuFAST8 "u" /* uint_fast8_t */ +#define SCNuFAST16 "u" /* uint_fast16_t */ +#define SCNuFAST32 "u" /* uint_fast32_t */ +#define SCNuFAST64 "llu" /* uint_fast64_t */ + +#define SCNuMAX "ju" /* uintmax_t */ +#define SCNuPTR "lu" /* uintptr_t */ + +#define SCNx8 "hhx" /* uint8_t */ +#define SCNx16 "hx" /* uint16_t */ +#define SCNx32 "x" /* uint32_t */ +#define SCNx64 "llx" /* uint64_t */ + +#define SCNxLEAST8 "hhx" /* uint_least8_t */ +#define SCNxLEAST16 "hx" /* uint_least16_t */ +#define SCNxLEAST32 "x" /* uint_least32_t */ +#define SCNxLEAST64 "llx" /* uint_least64_t */ + +#define SCNxFAST8 "x" /* uint_fast8_t */ +#define SCNxFAST16 "x" /* uint_fast16_t */ +#define SCNxFAST32 "x" /* uint_fast32_t */ +#define SCNxFAST64 "llx" /* uint_fast64_t */ + +#define SCNxMAX "jx" /* uintmax_t */ +#define SCNxPTR "lx" /* uintptr_t */ + +typedef struct { + intmax_t quot; /* quotient */ + intmax_t rem; /* remainder */ +} imaxdiv_t; + +__BEGIN_DECLS +intmax_t imaxabs(intmax_t); +imaxdiv_t imaxdiv(intmax_t, intmax_t); +intmax_t strtoimax(const char *, char **, int); +uintmax_t strtoumax(const char *, char **, int); +intmax_t wcstoimax(const __wchar_t * __restrict, + __wchar_t ** __restrict, int); +uintmax_t wcstoumax(const __wchar_t * __restrict, + __wchar_t ** __restrict, int); +__END_DECLS + +#endif /* _INTTYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/iso646.h b/lib/libc/include/generic-openbsd/iso646.h new file mode 100644 index 000000000000..6608a68a00a7 --- /dev/null +++ b/lib/libc/include/generic-openbsd/iso646.h @@ -0,0 +1,26 @@ +/* $OpenBSD: iso646.h,v 1.3 2001/10/11 00:05:21 espie Exp $ */ +/* $NetBSD: iso646.h,v 1.1 1995/02/17 09:08:10 jtc Exp $ */ + +/* + * Written by J.T. Conklin 02/16/95. + * Public domain. + */ + +#ifndef _ISO646_H_ +#define _ISO646_H_ + +#ifndef __cplusplus +#define and && +#define and_eq &= +#define bitand & +#define bitor | +#define compl ~ +#define not ! +#define not_eq != +#define or || +#define or_eq |= +#define xor ^ +#define xor_eq ^= +#endif + +#endif /* !_ISO646_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/isofs/cd9660/cd9660_extern.h b/lib/libc/include/generic-openbsd/isofs/cd9660/cd9660_extern.h new file mode 100644 index 000000000000..c8a8db6f8cc7 --- /dev/null +++ b/lib/libc/include/generic-openbsd/isofs/cd9660/cd9660_extern.h @@ -0,0 +1,109 @@ +/* $OpenBSD: cd9660_extern.h,v 1.16 2023/07/17 09:41:20 semarie Exp $ */ +/* $NetBSD: cd9660_extern.h,v 1.1 1997/01/24 00:24:53 cgd Exp $ */ + +/*- + * Copyright (c) 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley + * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension + * Support code is derived from software contributed to Berkeley + * by Atsushi Murai (amurai@spec.co.jp). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)iso.h 8.4 (Berkeley) 12/5/94 + */ + +/* + * Definitions used in the kernel for cd9660 file system support. + */ + +/* CD-ROM Format type */ +enum ISO_FTYPE { ISO_FTYPE_DEFAULT, ISO_FTYPE_9660, ISO_FTYPE_RRIP, ISO_FTYPE_ECMA }; + +#ifndef ISOFSMNT_ROOT +#define ISOFSMNT_ROOT 0 +#endif + +struct iso_mnt { + int im_flags; + + struct mount *im_mountp; + dev_t im_dev; + struct vnode *im_devvp; + + int logical_block_size; + int im_bshift; + int im_bmask; + + int volume_space_size; + struct netexport im_export; + + char root[ISODCL (157, 190)]; + int root_extent; + int root_size; + enum ISO_FTYPE iso_ftype; + + int rr_skip; + int rr_skip0; + + int joliet_level; +}; + +#define VFSTOISOFS(mp) ((struct iso_mnt *)((mp)->mnt_data)) + +#define blkoff(imp, loc) ((loc) & (imp)->im_bmask) +#define lblktosize(imp, blk) ((blk) << (imp)->im_bshift) +#define lblkno(imp, loc) ((loc) >> (imp)->im_bshift) +#define blksize(imp, ip, lbn) ((imp)->logical_block_size) + +int cd9660_mount(struct mount *, const char *, void *, + struct nameidata *, struct proc *); +int cd9660_start(struct mount *, int, struct proc *); +int cd9660_unmount(struct mount *, int, struct proc *); +int cd9660_root(struct mount *, struct vnode **); +int cd9660_quotactl(struct mount *, int, uid_t, caddr_t, struct proc *); +int cd9660_statfs(struct mount *, struct statfs *, struct proc *); +int cd9660_sync(struct mount *, int, int, struct ucred *, struct proc *); +int cd9660_vget(struct mount *, ino_t, struct vnode **); +int cd9660_fhtovp(struct mount *, struct fid *, struct vnode **); +int cd9660_vptofh(struct vnode *, struct fid *); +int cd9660_init(struct vfsconf *); +int cd9660_check_export(struct mount *, struct mbuf *, int *, + struct ucred **); + +int cd9660_mountroot(void); + +extern const struct vops cd9660_vops; +extern const struct vops cd9660_specvops; +#ifdef FIFO +extern const struct vops cd9660_fifovops; +#endif + +int isochar(const u_char *, const u_char *, int, u_char *); +int isofncmp(const u_char *, int, const u_char *, int, int); +void isofntrans(u_char *, int, u_char *, u_short *, int, int, int); +cdino_t isodirino(struct iso_directory_record *, struct iso_mnt *); \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/isofs/cd9660/cd9660_node.h b/lib/libc/include/generic-openbsd/isofs/cd9660/cd9660_node.h new file mode 100644 index 000000000000..186c61e2391f --- /dev/null +++ b/lib/libc/include/generic-openbsd/isofs/cd9660/cd9660_node.h @@ -0,0 +1,130 @@ +/* $OpenBSD: cd9660_node.h,v 1.23 2024/05/13 01:15:53 jsg Exp $ */ +/* $NetBSD: cd9660_node.h,v 1.15 1997/04/11 21:52:01 kleink Exp $ */ + +/*- + * Copyright (c) 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley + * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension + * Support code is derived from software contributed to Berkeley + * by Atsushi Murai (amurai@spec.co.jp). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)cd9660_node.h 8.4 (Berkeley) 12/5/94 + */ + +#include + +#define doff_t u_quad_t + +typedef struct { + struct timespec iso_atime; /* time of last access */ + struct timespec iso_mtime; /* time of last modification */ + struct timespec iso_ctime; /* time file changed */ + u_short iso_mode; /* files access mode and type */ + uid_t iso_uid; /* owner user id */ + gid_t iso_gid; /* owner group id */ + short iso_links; /* links of file */ + dev_t iso_rdev; /* Major/Minor number for special */ +} ISO_RRIP_INODE; + +struct iso_node { + struct iso_node *i_next, **i_prev; /* hash chain */ + struct vnode *i_vnode; /* vnode associated with this inode */ + struct vnode *i_devvp; /* vnode for block I/O */ + u_int i_flag; /* see below */ + dev_t i_dev; /* device where inode resides */ + cdino_t i_number; /* the identity of the inode */ + /* we use the actual starting block of the file */ + struct iso_mnt *i_mnt; /* filesystem associated with this inode */ + doff_t i_endoff; /* end of useful stuff in directory */ + doff_t i_diroff; /* offset in dir, where we found last entry */ + doff_t i_offset; /* offset of free space in directory */ + cdino_t i_ino; /* inode number of found directory */ + struct rrwlock i_lock; /* node lock */ + + doff_t iso_extent; /* extent of file */ + doff_t i_size; + /* + * Actual start of data file (may be different from iso_extent, if the + * file has extended attributes). + */ + doff_t iso_start; + + ISO_RRIP_INODE inode; + struct cluster_info i_ci; +}; + +#define i_forw i_chain[0] +#define i_back i_chain[1] + +/* flags */ +#define IN_ACCESS 0x0020 /* inode access time to be updated */ + +#define VTOI(vp) ((struct iso_node *)(vp)->v_data) +#define ITOV(ip) ((ip)->i_vnode) + +/* + * Prototypes for ISOFS vnode operations + */ +int cd9660_lookup(void *); +int cd9660_open(void *); +int cd9660_close(void *); +int cd9660_access(void *); +int cd9660_getattr(void *); +int cd9660_setattr(void *); +int cd9660_read(void *); +int cd9660_ioctl(void *); +int cd9660_mmap(void *); +int cd9660_seek(void *); +int cd9660_readdir(void *); +int cd9660_readlink(void *); +int cd9660_inactive(void *); +int cd9660_reclaim(void *); +int cd9660_link(void *); +int cd9660_symlink(void *); +int cd9660_bmap(void *); +int cd9660_lock(void *); +int cd9660_unlock(void *); +int cd9660_strategy(void *); +int cd9660_print(void *); +int cd9660_islocked(void *); +int cd9660_pathconf(void *); + +int cd9660_bufatoff(struct iso_node *, off_t, char **, struct buf **); + +void cd9660_defattr(struct iso_directory_record *, struct iso_node *, + struct buf *); +void cd9660_deftstamp(struct iso_directory_record *, struct iso_node *, + struct buf *); +struct vnode *cd9660_ihashget(dev_t, cdino_t); +int cd9660_ihashins(struct iso_node *); +void cd9660_ihashrem(struct iso_node *); +int cd9660_tstamp_conv7(u_char *, struct timespec *); +int cd9660_tstamp_conv17(u_char *, struct timespec *); +int cd9660_vget_internal(struct mount *, cdino_t, struct vnode **, int, + struct iso_directory_record *); \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/isofs/cd9660/cd9660_rrip.h b/lib/libc/include/generic-openbsd/isofs/cd9660/cd9660_rrip.h new file mode 100644 index 000000000000..9b3ecf9b945b --- /dev/null +++ b/lib/libc/include/generic-openbsd/isofs/cd9660/cd9660_rrip.h @@ -0,0 +1,139 @@ +/* $OpenBSD: cd9660_rrip.h,v 1.3 2003/06/02 23:28:05 millert Exp $ */ +/* $NetBSD: cd9660_rrip.h,v 1.6 1994/12/13 22:33:24 mycroft Exp $ */ + +/*- + * Copyright (c) 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley + * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension + * Support code is derived from software contributed to Berkeley + * by Atsushi Murai (amurai@spec.co.jp). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)cd9660_rrip.h 8.2 (Berkeley) 12/5/94 + */ + +typedef struct { + char type [ISODCL ( 0, 1)]; + u_char length [ISODCL ( 2, 2)]; /* 711 */ + u_char version [ISODCL ( 3, 3)]; +} ISO_SUSP_HEADER; + +typedef struct { + ISO_SUSP_HEADER h; + char mode [ISODCL ( 4, 11)]; /* 733 */ + char links [ISODCL ( 12, 19)]; /* 733 */ + char uid [ISODCL ( 20, 27)]; /* 733 */ + char gid [ISODCL ( 28, 35)]; /* 733 */ +} ISO_RRIP_ATTR; + +typedef struct { + ISO_SUSP_HEADER h; + char dev_t_high [ISODCL ( 4, 11)]; /* 733 */ + char dev_t_low [ISODCL ( 12, 19)]; /* 733 */ +} ISO_RRIP_DEVICE; + +#define ISO_SUSP_CFLAG_CONTINUE 0x01 +#define ISO_SUSP_CFLAG_CURRENT 0x02 +#define ISO_SUSP_CFLAG_PARENT 0x04 +#define ISO_SUSP_CFLAG_ROOT 0x08 +#define ISO_SUSP_CFLAG_VOLROOT 0x10 +#define ISO_SUSP_CFLAG_HOST 0x20 + +typedef struct { + u_char cflag [ISODCL ( 1, 1)]; + u_char clen [ISODCL ( 2, 2)]; + u_char name [1]; /* XXX */ +} ISO_RRIP_SLINK_COMPONENT; +#define ISO_RRIP_SLSIZ 2 + +typedef struct { + ISO_SUSP_HEADER h; + u_char flags [ISODCL ( 4, 4)]; + u_char component [ISODCL ( 5, 5)]; +} ISO_RRIP_SLINK; + +typedef struct { + ISO_SUSP_HEADER h; + char flags [ISODCL ( 4, 4)]; +} ISO_RRIP_ALTNAME; + +typedef struct { + ISO_SUSP_HEADER h; + char dir_loc [ISODCL ( 4, 11)]; /* 733 */ +} ISO_RRIP_CLINK; + +typedef struct { + ISO_SUSP_HEADER h; + char dir_loc [ISODCL ( 4, 11)]; /* 733 */ +} ISO_RRIP_PLINK; + +typedef struct { + ISO_SUSP_HEADER h; +} ISO_RRIP_RELDIR; + +#define ISO_SUSP_TSTAMP_FORM17 0x80 +#define ISO_SUSP_TSTAMP_FORM7 0x00 +#define ISO_SUSP_TSTAMP_CREAT 0x01 +#define ISO_SUSP_TSTAMP_MODIFY 0x02 +#define ISO_SUSP_TSTAMP_ACCESS 0x04 +#define ISO_SUSP_TSTAMP_ATTR 0x08 +#define ISO_SUSP_TSTAMP_BACKUP 0x10 +#define ISO_SUSP_TSTAMP_EXPIRE 0x20 +#define ISO_SUSP_TSTAMP_EFFECT 0x40 + +typedef struct { + ISO_SUSP_HEADER h; + u_char flags [ISODCL ( 4, 4)]; + u_char time [ISODCL ( 5, 5)]; +} ISO_RRIP_TSTAMP; + +typedef struct { + ISO_SUSP_HEADER h; + u_char flags [ISODCL ( 4, 4)]; +} ISO_RRIP_IDFLAG; + +typedef struct { + ISO_SUSP_HEADER h; + char len_id [ISODCL ( 4, 4)]; + char len_des [ISODCL ( 5, 5)]; + char len_src [ISODCL ( 6, 6)]; + char version [ISODCL ( 7, 7)]; +} ISO_RRIP_EXTREF; + +typedef struct { + ISO_SUSP_HEADER h; + char check [ISODCL ( 4, 5)]; + char skip [ISODCL ( 6, 6)]; +} ISO_RRIP_OFFSET; + +typedef struct { + ISO_SUSP_HEADER h; + char location [ISODCL ( 4, 11)]; + char offset [ISODCL ( 12, 19)]; + char length [ISODCL ( 20, 27)]; +} ISO_RRIP_CONT; \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/isofs/cd9660/iso.h b/lib/libc/include/generic-openbsd/isofs/cd9660/iso.h new file mode 100644 index 000000000000..09b365117ba5 --- /dev/null +++ b/lib/libc/include/generic-openbsd/isofs/cd9660/iso.h @@ -0,0 +1,282 @@ +/* $OpenBSD: iso.h,v 1.16 2021/03/05 07:01:36 jsg Exp $ */ +/* $NetBSD: iso.h,v 1.20 1997/07/07 22:45:34 cgd Exp $ */ + +/*- + * Copyright (c) 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley + * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension + * Support code is derived from software contributed to Berkeley + * by Atsushi Murai (amurai@spec.co.jp). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)iso.h 8.4 (Berkeley) 12/5/94 + */ + +/* + * Definitions describing ISO9660 file system structure, as well as + * the functions necessary to access fields of ISO9660 file system + * structures. + */ + +typedef uint32_t cdino_t; + +#define ISODCL(from, to) (to - from + 1) + +struct iso_volume_descriptor { + char type[ISODCL(1,1)]; /* 711 */ + char id[ISODCL(2,6)]; + char version[ISODCL(7,7)]; + char data[ISODCL(8,2048)]; +}; + +/* volume descriptor types */ +#define ISO_VD_PRIMARY 1 +#define ISO_VD_SUPPLEMENTARY 2 +#define ISO_VD_END 255 + +#define ISO_STANDARD_ID "CD001" +#define ISO_ECMA_ID "CDW01" + +struct iso_primary_descriptor { + char type [ISODCL ( 1, 1)]; /* 711 */ + char id [ISODCL ( 2, 6)]; + char version [ISODCL ( 7, 7)]; /* 711 */ + char unused1 [ISODCL ( 8, 8)]; + char system_id [ISODCL ( 9, 40)]; /* achars */ + char volume_id [ISODCL ( 41, 72)]; /* dchars */ + char unused2 [ISODCL ( 73, 80)]; + char volume_space_size [ISODCL ( 81, 88)]; /* 733 */ + char unused3 [ISODCL ( 89, 120)]; + char volume_set_size [ISODCL (121, 124)]; /* 723 */ + char volume_sequence_number [ISODCL (125, 128)]; /* 723 */ + char logical_block_size [ISODCL (129, 132)]; /* 723 */ + char path_table_size [ISODCL (133, 140)]; /* 733 */ + char type_l_path_table [ISODCL (141, 144)]; /* 731 */ + char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */ + char type_m_path_table [ISODCL (149, 152)]; /* 732 */ + char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */ + char root_directory_record [ISODCL (157, 190)]; /* 9.1 */ + char volume_set_id [ISODCL (191, 318)]; /* dchars */ + char publisher_id [ISODCL (319, 446)]; /* achars */ + char preparer_id [ISODCL (447, 574)]; /* achars */ + char application_id [ISODCL (575, 702)]; /* achars */ + char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */ + char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */ + char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */ + char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */ + char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */ + char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */ + char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */ + char file_structure_version [ISODCL (882, 882)]; /* 711 */ + char unused4 [ISODCL (883, 883)]; + char application_data [ISODCL (884, 1395)]; + char unused5 [ISODCL (1396, 2048)]; +}; +#define ISO_DEFAULT_BLOCK_SHIFT 11 +#define ISO_DEFAULT_BLOCK_SIZE (1< + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * + * Extended and adapted for UDFv2.50+ bij Reinoud Zandijk based on the + * original by Scott Long. + * + * 20030508 Made some small typo and explanatory comments + * 20030510 Added UDF 2.01 structures + * 20030519 Added/correct comments on multi-partitioned logical volume space + * 20050616 Added pseudo overwrite + * 20050624 Added the missing extended attribute types and `magic values'. + * 20051106 Reworked some implementation use parts + * + */ + + +#ifndef _FS_UDF_ECMA167_UDF_H_ +#define _FS_UDF_ECMA167_UDF_H_ + + +/* ecma167-udf.h */ + +/* Volume recognition sequence ECMA 167 rev. 3 16.1 */ +struct vrs_desc { + uint8_t struct_type; + uint8_t identifier[5]; + uint8_t version; + uint8_t data[2041]; +} __packed; + + +#define VRS_NSR02 "NSR02" +#define VRS_NSR03 "NSR03" +#define VRS_BEA01 "BEA01" +#define VRS_TEA01 "TEA01" +#define VRS_CD001 "CD001" +#define VRS_CDW02 "CDW02" + + +/* Structure/definitions/constants a la ECMA 167 rev. 3 */ + + +#define MAX_TAGID_VOLUMES 9 +/* Tag identifiers */ +enum { + TAGID_SPARING_TABLE = 0, + TAGID_PRI_VOL = 1, + TAGID_ANCHOR = 2, + TAGID_VOL = 3, + TAGID_IMP_VOL = 4, + TAGID_PARTITION = 5, + TAGID_LOGVOL = 6, + TAGID_UNALLOC_SPACE = 7, + TAGID_TERM = 8, + TAGID_LOGVOL_INTEGRITY= 9, + TAGID_FSD = 256, + TAGID_FID = 257, + TAGID_ALLOCEXTENT = 258, + TAGID_INDIRECTENTRY = 259, + TAGID_ICB_TERM = 260, + TAGID_FENTRY = 261, + TAGID_EXTATTR_HDR = 262, + TAGID_UNALL_SP_ENTRY = 263, + TAGID_SPACE_BITMAP = 264, + TAGID_PART_INTEGRITY = 265, + TAGID_EXTFENTRY = 266, + TAGID_MAX = 266 +}; + + +enum { + UDF_DOMAIN_FLAG_HARD_WRITE_PROTECT = 1, + UDF_DOMAIN_FLAG_SOFT_WRITE_PROTECT = 2 +}; + + +enum { + UDF_ACCESSTYPE_NOT_SPECIFIED = 0, /* unknown */ + UDF_ACCESSTYPE_PSEUDO_OVERWITE = 0, /* pseudo overwritable, e.g. BD-R's LOW */ + UDF_ACCESSTYPE_READ_ONLY = 1, /* really only readable */ + UDF_ACCESSTYPE_WRITE_ONCE = 2, /* write once and you're done */ + UDF_ACCESSTYPE_REWRITABLE = 3, /* may need extra work to rewrite */ + UDF_ACCESSTYPE_OVERWRITABLE = 4 /* no limits on rewriting; e.g. harddisc*/ +}; + + +/* Descriptor tag [3/7.2] */ +struct desc_tag { + uint16_t id; + uint16_t descriptor_ver; + uint8_t cksum; + uint8_t reserved; + uint16_t serial_num; + uint16_t desc_crc; + uint16_t desc_crc_len; + uint32_t tag_loc; +} __packed; +#define UDF_DESC_TAG_LENGTH 16 + + +/* Recorded Address [4/7.1] */ +struct lb_addr { /* within partition space */ + uint32_t lb_num; + uint16_t part_num; +} __packed; + + +/* Extent Descriptor [3/7.1] */ +struct extent_ad { + uint32_t len; + uint32_t loc; +} __packed; + + +/* Short Allocation Descriptor [4/14.14.1] */ +struct short_ad { + uint32_t len; + uint32_t lb_num; +} __packed; + + +/* Long Allocation Descriptor [4/14.14.2] */ +struct UDF_ADImp_use { + uint16_t flags; + uint32_t unique_id; +} __packed; +#define UDF_ADIMP_FLAGS_EXTENT_ERASED 1 + + +struct long_ad { + uint32_t len; + struct lb_addr loc; /* within a logical volume mapped partition space !! */ + union { + uint8_t bytes[6]; + struct UDF_ADImp_use im_used; + } __packed impl; +} __packed; +#define longad_uniqueid impl.im_used.unique_id + + +/* Extended Allocation Descriptor [4/14.14.3] ; identifies an extent of allocation descriptors ; also in UDF ? */ +struct ext_ad { + uint32_t ex_len; + uint32_t rec_len; + uint32_t inf_len; + struct lb_addr ex_loc; + uint8_t reserved[2]; +} __packed; + + +/* ICB : Information Control Block; positioning */ +union icb { + struct short_ad s_ad; + struct long_ad l_ad; + struct ext_ad e_ad; +} __packed; + + +/* short/long/ext extent have flags encoded in length */ +#define UDF_EXT_ALLOCATED (0<<30) +#define UDF_EXT_FREED (1<<30) +#define UDF_EXT_ALLOCATED_BUT_NOT_USED (1<<30) +#define UDF_EXT_FREE (2<<30) +#define UDF_EXT_REDIRECT (3<<30) +#define UDF_EXT_FLAGS(len) ((len) & (3<<30)) +#define UDF_EXT_LEN(len) ((len) & ((1<<30)-1)) +#define UDF_EXT_MAXLEN ((1<<30)-1) + + +/* Character set spec [1/7.2.1] */ +struct charspec { + uint8_t type; + uint8_t inf[63]; +} __packed; + + +struct pathcomp { + uint8_t type; + uint8_t l_ci; + uint16_t comp_filever; + uint8_t ident[256]; +} __packed; +#define UDF_PATH_COMP_SIZE 4 +#define UDF_PATH_COMP_RESERVED 0 +#define UDF_PATH_COMP_ROOT 1 +#define UDF_PATH_COMP_MOUNTROOT 2 +#define UDF_PATH_COMP_PARENTDIR 3 +#define UDF_PATH_COMP_CURDIR 4 +#define UDF_PATH_COMP_NAME 5 + + +/* Timestamp [1/7.3] */ +struct timestamp { + uint16_t type_tz; + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t centisec; + uint8_t hund_usec; + uint8_t usec; +} __packed; +#define UDF_TIMESTAMP_SIZE 12 + + +/* Entity Identifier [1/7.4] */ +#define UDF_REGID_ID_SIZE 23 +struct regid { + uint8_t flags; + uint8_t id[UDF_REGID_ID_SIZE]; + uint8_t id_suffix[8]; +} __packed; + + +/* ICB Tag [4/14.6] */ +struct icb_tag { + uint32_t prev_num_dirs; + uint16_t strat_type; + uint8_t strat_param[2]; + uint16_t max_num_entries; + uint8_t reserved; + uint8_t file_type; + struct lb_addr parent_icb; + uint16_t flags; +} __packed; +#define UDF_ICB_TAG_FLAGS_ALLOC_MASK 0x03 +#define UDF_ICB_SHORT_ALLOC 0x00 +#define UDF_ICB_LONG_ALLOC 0x01 +#define UDF_ICB_EXT_ALLOC 0x02 +#define UDF_ICB_INTERN_ALLOC 0x03 + +#define UDF_ICB_TAG_FLAGS_DIRORDERED (1<< 3) +#define UDF_ICB_TAG_FLAGS_NONRELOC (1<< 4) +#define UDF_ICB_TAG_FLAGS_CONTIGUOUS (1<< 9) +#define UDF_ICB_TAG_FLAGS_MULTIPLEVERS (1<<12) + +#define UDF_ICB_TAG_FLAGS_SETUID (1<< 6) +#define UDF_ICB_TAG_FLAGS_SETGID (1<< 7) +#define UDF_ICB_TAG_FLAGS_STICKY (1<< 8) + +#define UDF_ICB_FILETYPE_UNKNOWN 0 +#define UDF_ICB_FILETYPE_UNALLOCSPACE 1 +#define UDF_ICB_FILETYPE_PARTINTEGRITY 2 +#define UDF_ICB_FILETYPE_INDIRECTENTRY 3 +#define UDF_ICB_FILETYPE_DIRECTORY 4 +#define UDF_ICB_FILETYPE_RANDOMACCESS 5 +#define UDF_ICB_FILETYPE_BLOCKDEVICE 6 +#define UDF_ICB_FILETYPE_CHARDEVICE 7 +#define UDF_ICB_FILETYPE_EXTATTRREC 8 +#define UDF_ICB_FILETYPE_FIFO 9 +#define UDF_ICB_FILETYPE_SOCKET 10 +#define UDF_ICB_FILETYPE_TERM 11 +#define UDF_ICB_FILETYPE_SYMLINK 12 +#define UDF_ICB_FILETYPE_STREAMDIR 13 +#define UDF_ICB_FILETYPE_VAT 248 +#define UDF_ICB_FILETYPE_REALTIME 249 +#define UDF_ICB_FILETYPE_META_MAIN 250 +#define UDF_ICB_FILETYPE_META_MIRROR 251 + + +/* Anchor Volume Descriptor Pointer [3/10.2] */ +struct anchor_vdp { + struct desc_tag tag; + struct extent_ad main_vds_ex; /* to main volume descriptor set ; 16 sectors min */ + struct extent_ad reserve_vds_ex; /* copy of main volume descriptor set ; 16 sectors min */ +} __packed; + + +/* Volume Descriptor Pointer [3/10.3] */ +struct vol_desc_ptr { + struct desc_tag tag; /* use for extending the volume descriptor space */ + uint32_t vds_number; + struct extent_ad next_vds_ex; /* points to the next block for volume descriptor space */ +} __packed; + + +/* Primary Volume Descriptor [3/10.1] */ +struct pri_vol_desc { + struct desc_tag tag; + uint32_t seq_num; /* MAX prevail */ + uint32_t pvd_num; /* assigned by author; 0 is special as in it may only occur once */ + char vol_id[32]; /* KEY ; main identifier of this disc */ + uint16_t vds_num; /* volume descriptor number; i.e. what volume number is it */ + uint16_t max_vol_seq; /* maximum volume descriptor number known */ + uint16_t ichg_lvl; + uint16_t max_ichg_lvl; + uint32_t charset_list; + uint32_t max_charset_list; + char volset_id[128]; /* KEY ; if part of a multi-disc set or a band of volumes */ + struct charspec desc_charset; /* KEY according to ECMA 167 */ + struct charspec explanatory_charset; + struct extent_ad vol_abstract; + struct extent_ad vol_copyright; + struct regid app_id; + struct timestamp time; + struct regid imp_id; + uint8_t imp_use[64]; + uint32_t prev_vds_loc; /* location of predecessor _lov ? */ + uint16_t flags; /* bit 0 : if set indicates volume set name is meaningful */ + uint8_t reserved[22]; +} __packed; + + +/* UDF specific implementation use part of the implementation use volume descriptor */ +struct udf_lv_info { + struct charspec lvi_charset; + char logvol_id[128]; + + char lvinfo1[36]; + char lvinfo2[36]; + char lvinfo3[36]; + + struct regid impl_id; + uint8_t impl_use[128]; +} __packed; + + +/* Implementation use Volume Descriptor */ +struct impvol_desc { + struct desc_tag tag; + uint32_t seq_num; + struct regid impl_id; + union { + struct udf_lv_info lv_info; + char impl_use[460]; + } __packed _impl_use; +} __packed; + + +/* Logical Volume Descriptor [3/10.6] */ +struct logvol_desc { + struct desc_tag tag; + uint32_t seq_num; /* MAX prevail */ + struct charspec desc_charset; /* KEY */ + char logvol_id[128]; /* KEY */ + uint32_t lb_size; + struct regid domain_id; + union { + struct long_ad fsd_loc; /* to fileset descriptor SEQUENCE */ + uint8_t logvol_content_use[16]; + } __packed _lvd_use; + uint32_t mt_l; /* Partition map length */ + uint32_t n_pm; /* Number of partition maps */ + struct regid imp_id; + uint8_t imp_use[128]; + struct extent_ad integrity_seq_loc; + uint8_t maps[1]; +} __packed; +#define lv_fsd_loc _lvd_use.fsd_loc + +#define UDF_INTEGRITY_OPEN 0 +#define UDF_INTEGRITY_CLOSED 1 + + +#define UDF_PMAP_SIZE 64 + +/* Type 1 Partition Map [3/10.7.2] */ +struct part_map_1 { + uint8_t type; + uint8_t len; + uint16_t vol_seq_num; + uint16_t part_num; +} __packed; + + +/* Type 2 Partition Map [3/10.7.3] */ +struct part_map_2 { + uint8_t type; + uint8_t len; + uint8_t reserved[2]; + struct regid part_id; + uint16_t vol_seq_num; + uint16_t part_num; + uint8_t reserved2[24]; +} __packed; + + +/* Virtual Partition Map [UDF 2.01/2.2.8] */ +struct part_map_virt { + uint8_t type; + uint8_t len; + uint8_t reserved[2]; + struct regid id; + uint16_t vol_seq_num; + uint16_t part_num; + uint8_t reserved1[24]; +} __packed; + + +/* Sparable Partition Map [UDF 2.01/2.2.9] */ +struct part_map_spare { + uint8_t type; + uint8_t len; + uint8_t reserved[2]; + struct regid id; + uint16_t vol_seq_num; + uint16_t part_num; + uint16_t packet_len; + uint8_t n_st; /* Number of redundant sparing tables range 1-4 */ + uint8_t reserved1; + uint32_t st_size; /* size of EACH sparing table */ + uint32_t st_loc[1]; /* locations of sparing tables */ +} __packed; + + +/* Metadata Partition Map [UDF 2.50/2.2.10] */ +struct part_map_meta { + uint8_t type; + uint8_t len; + uint8_t reserved[2]; + struct regid id; + uint16_t vol_seq_num; + uint16_t part_num; + uint32_t meta_file_lbn; /* logical block number for file entry within part_num */ + uint32_t meta_mirror_file_lbn; + uint32_t meta_bitmap_file_lbn; + uint32_t alloc_unit_size; /* allocation unit size in blocks */ + uint16_t alignment_unit_size; /* alignment necessary in blocks */ + uint8_t flags; + uint8_t reserved1[5]; +} __packed; +#define METADATA_DUPLICATED 1 + + +union udf_pmap { + uint8_t data[UDF_PMAP_SIZE]; + struct part_map_1 pm1; + struct part_map_2 pm2; + struct part_map_virt pmv; + struct part_map_spare pms; + struct part_map_meta pmm; +} __packed; + + +/* Sparing Map Entry [UDF 2.01/2.2.11] */ +struct spare_map_entry { + uint32_t org; /* partition relative address */ + uint32_t map; /* absolute disc address (!) can be in partition, but doesn't have to be */ +} __packed; + + +/* Sparing Table [UDF 2.01/2.2.11] */ +struct udf_sparing_table { + struct desc_tag tag; + struct regid id; + uint16_t rt_l; /* Relocation Table len */ + uint8_t reserved[2]; + uint32_t seq_num; + struct spare_map_entry entries[1]; +} __packed; + + +#define UDF_NO_PREV_VAT 0xffffffff +/* UDF 1.50 VAT suffix [UDF 2.2.10 (UDF 1.50 spec)] */ +struct udf_oldvat_tail { + struct regid id; /* "*UDF Virtual Alloc Tbl" */ + uint32_t prev_vat; +} __packed; + + +/* VAT table [UDF 2.0.1/2.2.10] */ +struct udf_vat { + uint16_t header_len; + uint16_t impl_use_len; + char logvol_id[128]; /* newer version of the LVD one */ + uint32_t prev_vat; + uint32_t num_files; + uint32_t num_directories; + uint16_t min_udf_readver; + uint16_t min_udf_writever; + uint16_t max_udf_writever; + uint16_t reserved; + uint8_t data[1]; /* impl.use followed by VAT entries (uint32_t) */ +} __packed; + + +/* Space bitmap descriptor as found in the partition header descriptor */ +struct space_bitmap_desc { + struct desc_tag tag; /* TagId 264 */ + uint32_t num_bits; /* number of bits */ + uint32_t num_bytes; /* bytes that contain it */ + uint8_t data[1]; +} __packed; + + +/* Unalloc space entry as found in the partition header descriptor */ +struct space_entry_desc { + struct desc_tag tag; /* TagId 263 */ + struct icb_tag icbtag; /* type 1 */ + uint32_t l_ad; /* in bytes */ + uint8_t entry[1]; +} __packed; + + +/* Partition header descriptor; in the contents_use of part_desc */ +struct part_hdr_desc { + struct short_ad unalloc_space_table; + struct short_ad unalloc_space_bitmap; + struct short_ad part_integrity_table; /* has to be ZERO for UDF */ + struct short_ad freed_space_table; + struct short_ad freed_space_bitmap; + uint8_t reserved[88]; +} __packed; + + +/* Partition Descriptor [3/10.5] */ +struct part_desc { + struct desc_tag tag; + uint32_t seq_num; /* MAX prevailing */ + uint16_t flags; /* bit 0 : if set the space is allocated */ + uint16_t part_num; /* KEY */ + struct regid contents; + union { + struct part_hdr_desc part_hdr; + uint8_t contents_use[128]; + } _impl_use; + uint32_t access_type; /* R/W, WORM etc. */ + uint32_t start_loc; /* start of partition with given length */ + uint32_t part_len; + struct regid imp_id; + uint8_t imp_use[128]; + uint8_t reserved[156]; +} __packed; +#define pd_part_hdr _impl_use.part_hdr +#define UDF_PART_FLAG_ALLOCATED 1 + + +/* Unallocated Space Descriptor (UDF 2.01/2.2.5) */ +struct unalloc_sp_desc { + struct desc_tag tag; + uint32_t seq_num; /* MAX prevailing */ + uint32_t alloc_desc_num; + struct extent_ad alloc_desc[1]; +} __packed; + + +/* Logical Volume Integrity Descriptor [3/30.10] */ +struct logvolhdr { + uint64_t next_unique_id; + /* rest reserved */ +} __packed; + + +struct udf_logvol_info { + struct regid impl_id; + uint32_t num_files; + uint32_t num_directories; + uint16_t min_udf_readver; + uint16_t min_udf_writever; + uint16_t max_udf_writever; +} __packed; + + +struct logvol_int_desc { + struct desc_tag tag; + struct timestamp time; + uint32_t integrity_type; + struct extent_ad next_extent; + union { + struct logvolhdr logvolhdr; + int8_t reserved[32]; + } __packed _impl_use; + uint32_t num_part; + uint32_t l_iu; + uint32_t tables[1]; /* Freespace table, Sizetable, Implementation use */ +} __packed; +#define lvint_next_unique_id _impl_use.logvolhdr.next_unique_id + + +/* File Set Descriptor [4/14.1] */ +struct fileset_desc { + struct desc_tag tag; + struct timestamp time; + uint16_t ichg_lvl; + uint16_t max_ichg_lvl; + uint32_t charset_list; + uint32_t max_charset_list; + uint32_t fileset_num; /* key! */ + uint32_t fileset_desc_num; + struct charspec logvol_id_charset; + char logvol_id[128]; /* for recovery */ + struct charspec fileset_charset; + char fileset_id[32]; /* Mountpoint !! */ + char copyright_file_id[32]; + char abstract_file_id[32]; + struct long_ad rootdir_icb; /* to rootdir; icb->virtual ? */ + struct regid domain_id; + struct long_ad next_ex; /* to the next fileset_desc extent */ + struct long_ad streamdir_icb; /* streamdir; needed? */ + uint8_t reserved[32]; +} __packed; + + +/* File Identifier Descriptor [4/14.4] */ +struct fileid_desc { + struct desc_tag tag; + uint16_t file_version_num; + uint8_t file_char; + uint8_t l_fi; /* Length of file identifier area */ + struct long_ad icb; + uint16_t l_iu; /* Length of implementation use area */ + uint8_t data[0]; +} __packed; +#define UDF_FID_SIZE 38 +#define UDF_FILE_CHAR_VIS (1 << 0) /* Invisible */ +#define UDF_FILE_CHAR_DIR (1 << 1) /* Directory */ +#define UDF_FILE_CHAR_DEL (1 << 2) /* Deleted */ +#define UDF_FILE_CHAR_PAR (1 << 3) /* Parent Directory */ +#define UDF_FILE_CHAR_META (1 << 4) /* Stream metadata */ + + +/* Extended attributes [4/14.10.1] */ +struct extattrhdr_desc { + struct desc_tag tag; + uint32_t impl_attr_loc; /* offsets within this descriptor */ + uint32_t appl_attr_loc; /* ditto */ +} __packed; +#define UDF_IMPL_ATTR_LOC_NOT_PRESENT 0xffffffff +#define UDF_APPL_ATTR_LOC_NOT_PRESENT 0xffffffff + + +/* Extended attribute entry [4/48.10.2] */ +struct extattr_entry { + uint32_t type; + uint8_t subtype; + uint8_t reserved[3]; + uint32_t a_l; +} __packed; + + +/* Extended attribute entry; type 2048 [4/48.10.8] */ +struct impl_extattr_entry { + struct extattr_entry hdr; + uint32_t iu_l; + struct regid imp_id; + uint8_t data[1]; +} __packed; + + +/* Extended attribute entry; type 65 536 [4/48.10.9] */ +struct appl_extattr_entry { + struct extattr_entry hdr; + uint32_t au_l; + struct regid appl_id; + uint8_t data[1]; +} __packed; + + +/* File Times attribute entry; type 5 or type 6 [4/48.10.5], [4/48.10.6] */ +struct filetimes_extattr_entry { + struct extattr_entry hdr; + uint32_t d_l; /* length of times[] data following */ + uint32_t existence; /* bitmask */ + struct timestamp times[1]; /* in order of ascending bits */ +} __packed; +#define UDF_FILETIMES_ATTR_NO 5 +#define UDF_FILETIMES_FILE_CREATION 1 +#define UDF_FILETIMES_FILE_DELETION 4 +#define UDF_FILETIMES_FILE_EFFECTIVE 8 +#define UDF_FILETIMES_FILE_BACKUPED 16 +#define UDF_FILETIMES_ATTR_SIZE(no) (20 + (no)*sizeof(struct timestamp)) + + +/* Device Specification Extended Attribute [4/4.10.7] */ +struct device_extattr_entry { + struct extattr_entry hdr; + uint32_t iu_l; /* length of implementation use */ + uint32_t major; + uint32_t minor; + uint8_t data[1]; /* UDF: if nonzero length, contain developer ID regid */ +} __packed; +#define UDF_DEVICESPEC_ATTR_NO 12 + + +/* VAT LV extension Extended Attribute [UDF 3.3.4.5.1.3] 1.50 errata */ +struct vatlvext_extattr_entry { + uint64_t unique_id_chk; /* needs to be copy of ICB's */ + uint32_t num_files; + uint32_t num_directories; + char logvol_id[128]; /* replaces logvol name */ +} __packed; + + +/* File Entry [4/14.9] */ +struct file_entry { + struct desc_tag tag; + struct icb_tag icbtag; + uint32_t uid; + uint32_t gid; + uint32_t perm; + uint16_t link_cnt; + uint8_t rec_format; + uint8_t rec_disp_attr; + uint32_t rec_len; + uint64_t inf_len; + uint64_t logblks_rec; + struct timestamp atime; + struct timestamp mtime; + struct timestamp attrtime; + uint32_t ckpoint; + struct long_ad ex_attr_icb; + struct regid imp_id; + uint64_t unique_id; + uint32_t l_ea; /* Length of extended attribute area */ + uint32_t l_ad; /* Length of allocation descriptors */ + uint8_t data[1]; +} __packed; +#define UDF_FENTRY_SIZE 176 +#define UDF_FENTRY_PERM_USER_MASK 0x07 +#define UDF_FENTRY_PERM_GRP_MASK 0xE0 +#define UDF_FENTRY_PERM_OWNER_MASK 0x1C00 + + +/* Extended File Entry [4/48.17] */ +struct extfile_entry { + struct desc_tag tag; + struct icb_tag icbtag; + uint32_t uid; + uint32_t gid; + uint32_t perm; + uint16_t link_cnt; + uint8_t rec_format; + uint8_t rec_disp_attr; + uint32_t rec_len; + uint64_t inf_len; + uint64_t obj_size; + uint64_t logblks_rec; + struct timestamp atime; + struct timestamp mtime; + struct timestamp ctime; + struct timestamp attrtime; + uint32_t ckpoint; + uint32_t reserved1; + struct long_ad ex_attr_icb; + struct long_ad streamdir_icb; + struct regid imp_id; + uint64_t unique_id; + uint32_t l_ea; /* Length of extended attribute area */ + uint32_t l_ad; /* Length of allocation descriptors */ + uint8_t data[1]; +} __packed; +#define UDF_EXTFENTRY_SIZE 216 + + +/* Indirect entry [ecma 48.7] */ +struct indirect_entry { + struct desc_tag tag; + struct icb_tag icbtag; + struct long_ad indirect_icb; +} __packed; + + +/* Allocation extent descriptor [ecma 48.5] */ +struct alloc_ext_entry { + struct desc_tag tag; + uint32_t prev_entry; + uint32_t l_ad; + uint8_t data[1]; +} __packed; + + +union dscrptr { + struct desc_tag tag; + struct anchor_vdp avdp; + struct vol_desc_ptr vdp; + struct pri_vol_desc pvd; + struct logvol_desc lvd; + struct unalloc_sp_desc usd; + struct logvol_int_desc lvid; + struct impvol_desc ivd; + struct part_desc pd; + struct fileset_desc fsd; + struct fileid_desc fid; + struct file_entry fe; + struct extfile_entry efe; + struct extattrhdr_desc eahd; + struct indirect_entry inde; + struct alloc_ext_entry aee; + struct udf_sparing_table spt; + struct space_bitmap_desc sbd; + struct space_entry_desc sed; +} __packed; + +/* Useful defines */ + +#define GETICB(ad_type, fentry, offset) \ + (struct ad_type *)&fentry->data[offset] + +#define GETICBLEN(ad_type, icb) letoh32(((struct ad_type *)(icb))->len) + +#endif /* !_FS_UDF_ECMA167_UDF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/isofs/udf/udf.h b/lib/libc/include/generic-openbsd/isofs/udf/udf.h new file mode 100644 index 000000000000..41e0e5a82a1c --- /dev/null +++ b/lib/libc/include/generic-openbsd/isofs/udf/udf.h @@ -0,0 +1,145 @@ +/* $OpenBSD: udf.h,v 1.21 2016/06/19 11:54:33 natano Exp $ */ + +/* + * Copyright (c) 2001, 2002 Scott Long + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/fs/udf/udf.h,v 1.9 2004/10/29 10:40:58 phk Exp $ + */ + +/* + * Ported to OpenBSD by Pedro Martelletto in February 2005. + */ + +#define UDF_HASHTBLSIZE 100 + +typedef uint32_t udfino_t; + +struct unode { + LIST_ENTRY(unode) u_le; + struct vnode *u_vnode; + struct vnode *u_devvp; + struct umount *u_ump; + struct rrwlock u_lock; + dev_t u_dev; + udfino_t u_ino; + union { + long u_diroff; + long u_vatlen; + } un_u; + struct extfile_entry *u_fentry; +}; + +#define u_diroff un_u.u_diroff +#define u_vatlen un_u.u_vatlen + +struct umount { + int um_flags; + struct mount *um_mountp; + struct vnode *um_devvp; + dev_t um_dev; + int um_bsize; + int um_bshift; + int um_bmask; + uint32_t um_start; + uint32_t um_realstart; + uint32_t um_len; + uint32_t um_reallen; + uint32_t um_meta_start; + uint32_t um_meta_len; + struct unode *um_vat; + struct long_ad um_root_icb; + LIST_HEAD(udf_hash_lh, unode) *um_hashtbl; + SIPHASH_KEY um_hashkey; + u_long um_hashsz; + struct mutex um_hashmtx; + int um_psecs; + int um_stbl_len; + struct udf_sparing_table *um_stbl; +}; + +#define UDF_MNT_FIND_VAT 0x01 /* Indicates a VAT must be found */ +#define UDF_MNT_USES_VAT 0x02 /* Indicates a VAT must be used */ +#define UDF_MNT_USES_META 0x04 /* Indicates we are using a Metadata partition*/ + +#define VTOU(vp) ((struct unode *)((vp)->v_data)) + +#ifdef _KERNEL + +struct udf_dirstream { + struct unode *node; + struct umount *ump; + struct buf *bp; + uint8_t *data; + uint8_t *buf; + int fsize; + int off; + int this_off; + int offset; + int size; + int error; + int fid_fragment; +}; + +#define VFSTOUDFFS(mp) ((struct umount *)((mp)->mnt_data)) + +/* + * The block layer refers to things in terms of 512 byte blocks by default. + * btodb() is expensive, so speed things up. + * Can the block layer be forced to use a different block size? + */ +#define RDSECTOR(devvp, sector, size, bp) \ + bread(devvp, \ + ((daddr_t)(sector) << ump->um_bshift) / DEV_BSIZE, size, bp) + +static __inline int +udf_readlblks(struct umount *ump, int sector, int size, struct buf **bp) +{ + return (RDSECTOR(ump->um_devvp, sector, + (size + ump->um_bmask) & ~ump->um_bmask, bp)); +} + +/* + * Produce a suitable file number from an ICB. The passed in ICB is expected + * to be in little endian (meaning that it hasn't been swapped for big + * endian machines yet). + * If the fileno resolves to 0, we might be in big trouble. + * Assumes the ICB is a long_ad. This struct is compatible with short_ad, + * but not ext_ad. + */ +static __inline udfino_t +udf_getid(struct long_ad *icb) +{ + return (letoh32(icb->loc.lb_num)); +} + +int udf_allocv(struct mount *, struct vnode **, struct proc *); +int udf_hashlookup(struct umount *, udfino_t, int, struct vnode **); +int udf_hashins(struct unode *); +int udf_hashrem(struct unode *); +int udf_checktag(struct desc_tag *, uint16_t); + +typedef uint16_t unicode_t; + +#endif /* _KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/isofs/udf/udf_extern.h b/lib/libc/include/generic-openbsd/isofs/udf/udf_extern.h new file mode 100644 index 000000000000..7af5a7a7384d --- /dev/null +++ b/lib/libc/include/generic-openbsd/isofs/udf/udf_extern.h @@ -0,0 +1,69 @@ +/* $OpenBSD: udf_extern.h,v 1.16 2025/07/07 00:55:15 jsg Exp $ */ + +/* + * Written by Pedro Martelletto in February 2005. + * Public domain. + */ + +#ifdef _KERNEL + +/* + * udf_subr.c + */ +int udf_rawnametounicode(u_int len, char *, unicode_t *); +int udf_vat_get(struct umount *, uint32_t); +int udf_vat_map(struct umount *, uint32_t *); + +/* + * udf_vfsops.c + */ +int udf_init(struct vfsconf *); +int udf_mount(struct mount *, const char *, void *, struct nameidata *, + struct proc *); +int udf_unmount(struct mount *, int, struct proc *); +int udf_start(struct mount *, int, struct proc *); +int udf_root(struct mount *, struct vnode **); +int udf_quotactl(struct mount *, int, uid_t, caddr_t, struct proc *); +int udf_statfs(struct mount *, struct statfs *, struct proc *); +int udf_vget(struct mount *, ino_t, struct vnode **); +int udf_sync(struct mount *, int, int, struct ucred *, struct proc *); +int udf_checkexp(struct mount *, struct mbuf *, int *, struct ucred **); +int udf_fhtovp(struct mount *, struct fid *, struct vnode **); +int udf_vptofh(struct vnode *, struct fid *); + +/* + * udf_vnops.c + */ +int udf_access(void *v); +int udf_getattr(void *v); +int udf_open(void *v); +int udf_close(void *v); +int udf_ioctl(void *v); +int udf_read(void *v); +int udf_readdir(void *v); +int udf_readlink(void *v); +int udf_strategy(void *v); +int udf_bmap(void *v); +int udf_lookup(void *v); +int udf_inactive(void *v); +int udf_reclaim(void *v); +int udf_lock(void *v); +int udf_unlock(void *v); +int udf_pathconf(void *); +int udf_islocked(void *v); +int udf_print(void *v); +int udf_transname(char *, char *, int, struct umount *); +int udf_readatoffset(struct unode *, int *, off_t, struct buf **, + uint8_t **); + +/* + * Memory pools. + */ +extern struct pool udf_trans_pool; +extern struct pool unode_pool; +extern struct pool udf_ds_pool; + +/* Set of UDF vnode operations.*/ +extern const struct vops udf_vops; + +#endif /* _KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/kvm.h b/lib/libc/include/generic-openbsd/kvm.h new file mode 100644 index 000000000000..8fd992cb1be3 --- /dev/null +++ b/lib/libc/include/generic-openbsd/kvm.h @@ -0,0 +1,79 @@ +/* $OpenBSD: kvm.h,v 1.18 2013/10/22 16:40:25 guenther Exp $ */ +/* $NetBSD: kvm.h,v 1.7 1996/04/19 12:02:50 leo Exp $ */ + +/*- + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)kvm.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _KVM_H_ +#define _KVM_H_ + +/* Default version symbol. */ +#define VRS_SYM "_version" +#define VRS_KEY "VERSION" + +/* + * Flag for kvm_open* that disables opening of any files. We're just + * interested in a handle to run sysctls. + */ +#define KVM_NO_FILES 0x80000000 + +#include +#include + +__BEGIN_DECLS + +typedef struct __kvm kvm_t; + +struct kinfo_proc; +int kvm_close(kvm_t *); +int kvm_dump_inval(kvm_t *); +int kvm_dump_mkheader(kvm_t *, off_t); +int kvm_dump_wrtheader(kvm_t *, FILE *, int); +char **kvm_getargv(kvm_t *, const struct kinfo_proc *, int); +char **kvm_getenvv(kvm_t *, const struct kinfo_proc *, int); +char *kvm_geterr(kvm_t *); +int kvm_getloadavg(kvm_t *, double [], int); +struct kinfo_file * + kvm_getfiles(kvm_t *, int, int, size_t, int *); +struct kinfo_proc * + kvm_getprocs(kvm_t *, int, int, size_t, int *); +int kvm_nlist(kvm_t *, struct nlist *); +kvm_t *kvm_open(const char *, const char *, const char *, int, const char *); +kvm_t *kvm_openfiles(const char *, const char *, const char *, + int, char *); +ssize_t kvm_read(kvm_t *, unsigned long, void *, size_t) + __attribute__((__bounded__(__buffer__,3,4))); +ssize_t kvm_write(kvm_t *, unsigned long, const void *, size_t) + __attribute__((__bounded__(__buffer__,3,4))); + +__END_DECLS + +#endif /* !_KVM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/langinfo.h b/lib/libc/include/generic-openbsd/langinfo.h new file mode 100644 index 000000000000..9009ee1d5b79 --- /dev/null +++ b/lib/libc/include/generic-openbsd/langinfo.h @@ -0,0 +1,88 @@ +/* $OpenBSD: langinfo.h,v 1.8 2017/09/05 03:16:13 schwarze Exp $ */ +/* $NetBSD: langinfo.h,v 1.3 1995/04/28 23:30:54 jtc Exp $ */ + +/* + * Written by J.T. Conklin + * Public domain. + */ + +#ifndef _LANGINFO_H_ +#define _LANGINFO_H_ + +#include + +#define D_T_FMT 0 /* String for formatting date and time */ +#define D_FMT 1 /* Date format string */ +#define T_FMT 2 /* Time format string */ +#define T_FMT_AMPM 3 /* Time format string with 12 hour clock */ +#define AM_STR 4 /* Ante Meridiem afix */ +#define PM_STR 5 /* Post Meridiem afix */ + +#define DAY_1 6 /* Name of the first day of the week */ +#define DAY_2 7 +#define DAY_3 8 +#define DAY_4 9 +#define DAY_5 10 +#define DAY_6 11 +#define DAY_7 12 + +#define ABDAY_1 13 /* Abbrev. name of the first day of the week */ +#define ABDAY_2 14 +#define ABDAY_3 15 +#define ABDAY_4 16 +#define ABDAY_5 17 +#define ABDAY_6 18 +#define ABDAY_7 19 + +#define MON_1 20 /* Name of the first month */ +#define MON_2 21 +#define MON_3 22 +#define MON_4 23 +#define MON_5 24 +#define MON_6 25 +#define MON_7 26 +#define MON_8 27 +#define MON_9 28 +#define MON_10 29 +#define MON_11 30 +#define MON_12 31 + +#define ABMON_1 32 /* Abbrev. name of the first month */ +#define ABMON_2 33 +#define ABMON_3 34 +#define ABMON_4 35 +#define ABMON_5 36 +#define ABMON_6 37 +#define ABMON_7 38 +#define ABMON_8 39 +#define ABMON_9 40 +#define ABMON_10 41 +#define ABMON_11 42 +#define ABMON_12 43 + +#define RADIXCHAR 44 /* Radix character */ +#define THOUSEP 45 /* Separator for thousands */ +#define YESSTR 46 /* Affirmative response for yes/no queries */ +#define YESEXPR 47 /* Affirmative response for yes/no queries */ +#define NOSTR 48 /* Negative response for yes/no queries */ +#define NOEXPR 49 /* Negative response for yes/no queries */ +#define CRNCYSTR 50 /* Currency symbol */ + +#define CODESET 51 /* Codeset name */ + +#if __POSIX_VISIBLE >= 200809 +#ifndef _LOCALE_T_DEFINED_ +#define _LOCALE_T_DEFINED_ +typedef void *locale_t; +#endif +#endif + +__BEGIN_DECLS +char *nl_langinfo(nl_item); + +#if __POSIX_VISIBLE >= 200809 +char *nl_langinfo_l(nl_item, locale_t); +#endif +__END_DECLS + +#endif /* _LANGINFO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/libgen.h b/lib/libc/include/generic-openbsd/libgen.h new file mode 100644 index 000000000000..c34a0f408865 --- /dev/null +++ b/lib/libc/include/generic-openbsd/libgen.h @@ -0,0 +1,29 @@ +/* $OpenBSD: libgen.h,v 1.10 2020/10/20 19:30:14 naddy Exp $ */ + +/* + * Copyright (c) 1997 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _LIBGEN_H_ +#define _LIBGEN_H_ + +#include + +__BEGIN_DECLS +char *basename(char *); +char *dirname(char *); +__END_DECLS + +#endif /* _LIBGEN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/limits.h b/lib/libc/include/generic-openbsd/limits.h new file mode 100644 index 000000000000..7b9702ce670d --- /dev/null +++ b/lib/libc/include/generic-openbsd/limits.h @@ -0,0 +1,117 @@ +/* $OpenBSD: limits.h,v 1.19 2015/01/20 22:09:50 tedu Exp $ */ +/* $NetBSD: limits.h,v 1.7 1994/10/26 00:56:00 cgd Exp $ */ + +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)limits.h 5.9 (Berkeley) 4/3/91 + */ + +#ifndef _LIMITS_H_ +#define _LIMITS_H_ + +#include + +#if __POSIX_VISIBLE +#define _POSIX_ARG_MAX 4096 +#define _POSIX_CHILD_MAX 25 +#define _POSIX_LINK_MAX 8 +#define _POSIX_MAX_CANON 255 +#define _POSIX_MAX_INPUT 255 +#define _POSIX_NAME_MAX 14 +#define _POSIX_PATH_MAX 256 +#define _POSIX_PIPE_BUF 512 +#define _POSIX_RE_DUP_MAX 255 +#define _POSIX_SEM_NSEMS_MAX 256 +#define _POSIX_SEM_VALUE_MAX 32767 +#define _POSIX_SSIZE_MAX 32767 +#define _POSIX_STREAM_MAX 8 +#define _POSIX_SYMLINK_MAX 255 +#define _POSIX_SYMLOOP_MAX 8 +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 +#define _POSIX_THREAD_KEYS_MAX 128 +#define _POSIX_THREAD_THREADS_MAX 4 + +#if __POSIX_VISIBLE >= 200112 +#define _POSIX_CLOCKRES_MIN 20000000 +#define _POSIX_NGROUPS_MAX 8 +#define _POSIX_OPEN_MAX 20 +#define _POSIX_TZNAME_MAX 6 +#else +#define _POSIX_NGROUPS_MAX 0 +#define _POSIX_OPEN_MAX 16 +#define _POSIX_TZNAME_MAX 3 +#endif + +#define _POSIX2_BC_BASE_MAX 99 +#define _POSIX2_BC_DIM_MAX 2048 +#define _POSIX2_BC_SCALE_MAX 99 +#define _POSIX2_BC_STRING_MAX 1000 +#define _POSIX2_COLL_WEIGHTS_MAX 2 +#define _POSIX2_EXPR_NEST_MAX 32 +#define _POSIX2_LINE_MAX 2048 +#define _POSIX2_RE_DUP_MAX _POSIX_RE_DUP_MAX +#define _POSIX2_CHARCLASS_NAME_MAX 14 + +#if __POSIX_VISIBLE >= 200112 +#define _POSIX_HOST_NAME_MAX 255 +#define _POSIX_LOGIN_NAME_MAX 9 /* includes trailing NUL */ +#define _POSIX_TTY_NAME_MAX 9 /* includes trailing NUL */ +#endif /* __POSIX_VISIBLE >= 200112 */ +#endif /* __POSIX_VISIBLE */ + +#if __XPG_VISIBLE || __POSIX_VISIBLE >= 200809 +#define NL_ARGMAX 9 +#define NL_LANGMAX 14 +#define NL_MSGMAX 32767 +#define NL_SETMAX 255 +#define NL_TEXTMAX 255 +#endif + +#if __XPG_VISIBLE +# if __XPG_VISIBLE < 600 +# define PASS_MAX 128 /* _PASSWORD_LEN from */ +# define TMP_MAX 0x7fffffff /* more, but don't overflow int */ +# endif + +# if __XPG_VISIBLE < 700 +# define NL_NMAX 1 +# endif + +#define _XOPEN_IOV_MAX 16 +#define _XOPEN_NAME_MAX 255 +#define _XOPEN_PATH_MAX 1024 +#endif /* __XPG_VISIBLE */ + +#include + +#if __POSIX_VISIBLE +#include +#endif + +#endif /* !_LIMITS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/link.h b/lib/libc/include/generic-openbsd/link.h new file mode 100644 index 000000000000..bb8058281071 --- /dev/null +++ b/lib/libc/include/generic-openbsd/link.h @@ -0,0 +1,148 @@ +/* $OpenBSD: link.h,v 1.15 2013/10/19 09:00:18 deraadt Exp $ */ +/* $NetBSD: link.h,v 1.10 1996/01/09 00:00:11 pk Exp $ */ + +/* + * Copyright (c) 1993 Paul Kranenburg + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Paul Kranenburg. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef _LINK_H_ +#define _LINK_H_ + +#ifdef __ELF__ +#include +#endif + +/* + * A `Shared Object Descriptor' describes a shared object that is needed + * to complete the link edit process of the object containing it. + * A list of such objects (chained through `sod_next') is pointed at + * by `sdt_sods' in the section_dispatch_table structure. + */ + +struct sod { /* Shared Object Descriptor */ + long sod_name; /* name (relative to load address) */ + unsigned int sod_library : 1,/* Searched for by library rules */ + sod_reserved : 31; + short sod_major; /* major version number */ + short sod_minor; /* minor version number */ + long sod_next; /* next sod */ +}; + +/* + * `Shared Object Map's are used by the run-time link editor (ld.so) to + * keep track of all shared objects loaded into a process' address space. + * These structures are only used at run-time and do not occur within + * the text or data segment of an executable or shared library. + */ +struct so_map { /* Shared Object Map */ + caddr_t som_addr; /* Address at which object mapped */ + char *som_path; /* Path to mmap'ed file */ + struct so_map *som_next; /* Next map in chain */ + struct sod *som_sod; /* Sod responsible for this map */ + caddr_t som_sodbase; /* Base address of this sod */ + unsigned int som_write : 1; /* Text is currently writable */ + struct _dynamic *som_dynamic; /* _dynamic structure */ + caddr_t som_spd; /* Private data */ +}; + + +/* + * Debug rendezvous struct. Pointer to this is set up in the + * target code pointed by the DT_DEBUG tag. If it is + * defined. + */ +struct r_debug { + int r_version; /* Protocol version. */ + struct link_map *r_map; /* Head of list of loaded objects. */ + + /* + * This is the address of a function internal to the run-time linker, + * that will always be called when the linker begins to map in a + * library or unmap it, and again when the mapping change is complete. + * The debugger can set a breakpoint at this address if it wants to + * notice shared object mapping changes. + */ + unsigned long r_brk; + enum { + /* + * This state value describes the mapping change taking place + * when the `r_brk' address is called. + */ + RT_CONSISTENT, /* Mapping change is complete. */ + RT_ADD, /* Adding a new object. */ + RT_DELETE /* Removing an object mapping. */ + } r_state; + + unsigned long r_ldbase; /* Base address the linker is loaded at. */ +}; + + + +/* + * Maximum number of recognized shared object version numbers. + */ +#define MAXDEWEY 8 + +/* + * Header of the hints file. + */ +struct hints_header { + long hh_magic; +#define HH_MAGIC 011421044151 + long hh_version; /* Interface version number */ +#define LD_HINTS_VERSION_1 1 +#define LD_HINTS_VERSION_2 2 + long hh_hashtab; /* Location of hash table */ + long hh_nbucket; /* Number of buckets in hashtab */ + long hh_strtab; /* Location of strings */ + long hh_strtab_sz; /* Size of strings */ + long hh_ehints; /* End of hints (max offset in file) */ + long hh_dirlist; /* Colon-separated list of srch dirs */ +}; + +#define HH_BADMAG(hdr) ((hdr).hh_magic != HH_MAGIC) + +/* + * Hash table element in hints file. + */ +struct hints_bucket { + /* namex and pathx are indices into the string table */ + int hi_namex; /* Library name */ + int hi_pathx; /* Full path */ + int hi_dewey[MAXDEWEY]; /* The versions */ + int hi_ndewey; /* Number of version numbers */ +#define hi_major hi_dewey[0] +#define hi_minor hi_dewey[1] + int hi_next; /* Next in this bucket */ +}; + +#define _PATH_LD_HINTS "/var/run/ld.so.hints" + +#endif /* _LINK_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/link_elf.h b/lib/libc/include/generic-openbsd/link_elf.h new file mode 100644 index 000000000000..c28b4243d195 --- /dev/null +++ b/lib/libc/include/generic-openbsd/link_elf.h @@ -0,0 +1,42 @@ +/* $OpenBSD: link_elf.h,v 1.8 2022/01/28 04:59:15 guenther Exp $ */ + +/* + * Public domain. + */ + +#ifndef _LINK_ELF_H +#define _LINK_ELF_H + +#include + +#ifndef DT_PROCNUM +#define DT_PROCNUM 0 +#endif + +/* + * struct link_map is a part of the protocol between the debugger and + * ld.so. ld.so may have additional fields in its version of this + * structure but those are ld.so private fields. + */ +struct link_map { + caddr_t l_addr; /* Base address of library */ + const char *l_name; /* Absolute path to library */ + void *l_ld; /* pointer to _DYNAMIC */ + struct link_map *l_next; + struct link_map *l_prev; +}; + +struct dl_phdr_info { + Elf_Addr dlpi_addr; + const char *dlpi_name; + const Elf_Phdr *dlpi_phdr; + Elf_Half dlpi_phnum; +}; + +__BEGIN_DECLS +int dl_iterate_phdr (int (*)(struct dl_phdr_info *, size_t, void *), + void *); +void *dl_unwind_find_exidx(const void *, int *); +__END_DECLS + +#endif /* !_LINK_ELF_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/locale.h b/lib/libc/include/generic-openbsd/locale.h new file mode 100644 index 000000000000..c66620acdd23 --- /dev/null +++ b/lib/libc/include/generic-openbsd/locale.h @@ -0,0 +1,112 @@ +/* $OpenBSD: locale.h,v 1.11 2017/09/05 03:16:13 schwarze Exp $ */ +/* $NetBSD: locale.h,v 1.6 1994/10/26 00:56:02 cgd Exp $ */ + +/* + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)locale.h 5.2 (Berkeley) 2/24/91 + */ + +#ifndef _LOCALE_H_ +#define _LOCALE_H_ + +#include + +struct lconv { + char *decimal_point; + char *thousands_sep; + char *grouping; + char *int_curr_symbol; + char *currency_symbol; + char *mon_decimal_point; + char *mon_thousands_sep; + char *mon_grouping; + char *positive_sign; + char *negative_sign; + char int_frac_digits; + char frac_digits; + char p_cs_precedes; + char p_sep_by_space; + char n_cs_precedes; + char n_sep_by_space; + char p_sign_posn; + char n_sign_posn; + char int_p_cs_precedes; + char int_p_sep_by_space; + char int_n_cs_precedes; + char int_n_sep_by_space; + char int_p_sign_posn; + char int_n_sign_posn; +}; + +#define LC_ALL 0 +#define LC_COLLATE 1 +#define LC_CTYPE 2 +#define LC_MONETARY 3 +#define LC_NUMERIC 4 +#define LC_TIME 5 +#define LC_MESSAGES 6 + +#define _LC_LAST 7 /* marks end */ + +#include + +#if __POSIX_VISIBLE >= 200809 + +#ifndef _LOCALE_T_DEFINED_ +#define _LOCALE_T_DEFINED_ +typedef void *locale_t; +#endif + +#define LC_COLLATE_MASK (1 << LC_COLLATE) +#define LC_CTYPE_MASK (1 << LC_CTYPE) +#define LC_MONETARY_MASK (1 << LC_MONETARY) +#define LC_NUMERIC_MASK (1 << LC_NUMERIC) +#define LC_TIME_MASK (1 << LC_TIME) +#define LC_MESSAGES_MASK (1 << LC_MESSAGES) + +#define LC_ALL_MASK ((1 << _LC_LAST) - 2) + +#define LC_GLOBAL_LOCALE ((locale_t)-1) + +#endif /* __POSIX_VISIBLE >= 200809 */ + + +__BEGIN_DECLS +struct lconv *localeconv(void); +char *setlocale(int, const char *); + +#if __POSIX_VISIBLE >= 200809 +locale_t duplocale(locale_t); +void freelocale(locale_t); +locale_t newlocale(int, const char *, locale_t); +locale_t uselocale(locale_t); +#endif +__END_DECLS + +#endif /* _LOCALE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/login_cap.h b/lib/libc/include/generic-openbsd/login_cap.h new file mode 100644 index 000000000000..d0c1169ee0db --- /dev/null +++ b/lib/libc/include/generic-openbsd/login_cap.h @@ -0,0 +1,111 @@ +/* $OpenBSD: login_cap.h,v 1.19 2022/03/01 01:22:11 tedu Exp $ */ + +/*- + * Copyright (c) 1995,1997 Berkeley Software Design, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Berkeley Software Design, + * Inc. + * 4. The name of Berkeley Software Design, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``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 BERKELEY SOFTWARE DESIGN, INC. 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. + * + * BSDI $From: login_cap.h,v 2.11 1999/09/08 18:11:57 prb Exp $ + */ + +#ifndef _LOGIN_CAP_H_ +#define _LOGIN_CAP_H_ + +#define LOGIN_DEFCLASS "default" +#define LOGIN_DEFSTYLE "passwd" +#define LOGIN_DEFSERVICE "login" +#define LOGIN_DEFUMASK 022 +#define _PATH_LOGIN_CONF "/etc/login.conf" +#define _PATH_LOGIN_CONF_D "/etc/login.conf.d" +#define _PATH_AUTHPROGDIR "/usr/libexec/auth" +#define _PATH_AUTHPROG "/usr/libexec/auth/login_" + +#define LOGIN_SETGROUP 0x0001 /* Set group */ +#define LOGIN_SETLOGIN 0x0002 /* Set login */ +#define LOGIN_SETPATH 0x0004 /* Set path */ +#define LOGIN_SETPRIORITY 0x0008 /* Set priority */ +#define LOGIN_SETRESOURCES 0x0010 /* Set resource limits */ +#define LOGIN_SETUMASK 0x0020 /* Set umask */ +#define LOGIN_SETUSER 0x0040 /* Set user */ +#define LOGIN_SETENV 0x0080 /* Set environment */ +#define LOGIN_SETRTABLE 0x0100 /* Set rtable */ +#define LOGIN_SETALL 0x01ff /* Set all. */ + +#define BI_AUTH "authorize" /* Accepted authentication */ +#define BI_REJECT "reject" /* Rejected authentication */ +#define BI_CHALLENGE "reject challenge" /* Reject with a challenge */ +#define BI_SILENT "reject silent" /* Reject silently */ +#define BI_REMOVE "remove" /* remove file on error */ +#define BI_ROOTOKAY "authorize root" /* root authenticated */ +#define BI_SECURE "authorize secure" /* okay on non-secure line */ +#define BI_SETENV "setenv" /* set environment variable */ +#define BI_UNSETENV "unsetenv" /* unset environment variable */ +#define BI_VALUE "value" /* set local variable */ +#define BI_EXPIRED "reject expired" /* account expired */ +#define BI_PWEXPIRED "reject pwexpired" /* password expired */ +#define BI_FDPASS "fd" /* child is passing an fd */ + +/* + * bits which can be returned by authenticate()/auth_scan() + */ +#define AUTH_OKAY 0x01 /* user authenticated */ +#define AUTH_ROOTOKAY 0x02 /* authenticated as root */ +#define AUTH_SECURE 0x04 /* secure login */ +#define AUTH_SILENT 0x08 /* silent rejection */ +#define AUTH_CHALLENGE 0x10 /* a challenge was given */ +#define AUTH_EXPIRED 0x20 /* account expired */ +#define AUTH_PWEXPIRED 0x40 /* password expired */ + +#define AUTH_ALLOW (AUTH_OKAY | AUTH_ROOTOKAY | AUTH_SECURE) + +typedef struct login_cap { + char *lc_class; + char *lc_cap; + char *lc_style; +} login_cap_t; + +#include +__BEGIN_DECLS +struct passwd; + +login_cap_t *login_getclass(char *); +void login_close(login_cap_t *); +int login_getcapbool(login_cap_t *, char *, unsigned int); +quad_t login_getcapnum(login_cap_t *, char *, quad_t, quad_t); +quad_t login_getcapsize(login_cap_t *, char *, quad_t, quad_t); +char *login_getcapstr(login_cap_t *, char *, char *, char *); +quad_t login_getcaptime(login_cap_t *, char *, quad_t, quad_t); +char *login_getstyle(login_cap_t *, char *, char *); + +int setclasscontext(char *, unsigned int); +int setusercontext(login_cap_t *, struct passwd *, uid_t, unsigned int); + +__END_DECLS + +#endif /* _LOGIN_CAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/machine/_float.h b/lib/libc/include/generic-openbsd/machine/_float.h new file mode 100644 index 000000000000..6c9717939fcb --- /dev/null +++ b/lib/libc/include/generic-openbsd/machine/_float.h @@ -0,0 +1,3 @@ +/* $OpenBSD: _float.h,v 1.1 2012/06/26 16:12:44 deraadt Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/machine/cdefs.h b/lib/libc/include/generic-openbsd/machine/cdefs.h new file mode 100644 index 000000000000..e44353fedfe1 --- /dev/null +++ b/lib/libc/include/generic-openbsd/machine/cdefs.h @@ -0,0 +1,3 @@ +/* $OpenBSD: cdefs.h,v 1.2 2013/03/28 17:30:45 martynas Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/machine/disklabel.h b/lib/libc/include/generic-openbsd/machine/disklabel.h new file mode 100644 index 000000000000..e7758205f60b --- /dev/null +++ b/lib/libc/include/generic-openbsd/machine/disklabel.h @@ -0,0 +1,16 @@ +/* $OpenBSD: disklabel.h,v 1.3 2015/09/30 15:35:30 krw Exp $ */ +/* public domain */ + +/* + * Standard MBR partition scheme, with the label in the second sector + * of the OpenBSD partition. + */ + +#ifndef _MACHINE_DISKLABEL_H_ +#define _MACHINE_DISKLABEL_H_ + +#define LABELSECTOR 1 /* sector containing label */ +#define LABELOFFSET 0 /* offset of label in sector */ +#define MAXPARTITIONS 16 /* number of partitions */ + +#endif /* _MACHINE_DISKLABEL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/machine/elf.h b/lib/libc/include/generic-openbsd/machine/elf.h new file mode 100644 index 000000000000..1cd8fda26a98 --- /dev/null +++ b/lib/libc/include/generic-openbsd/machine/elf.h @@ -0,0 +1,7 @@ +/* $OpenBSD: elf.h,v 1.1 2024/07/14 09:48:48 jca Exp $ */ + +/* + * This file is in the public domain. + */ + +/* Nothing for now */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/machine/fenv.h b/lib/libc/include/generic-openbsd/machine/fenv.h new file mode 100644 index 000000000000..08e89fbf323e --- /dev/null +++ b/lib/libc/include/generic-openbsd/machine/fenv.h @@ -0,0 +1,3 @@ +/* $OpenBSD: fenv.h,v 1.2 2013/06/01 21:20:54 jasper Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/machine/loadfile_machdep.h b/lib/libc/include/generic-openbsd/machine/loadfile_machdep.h new file mode 100644 index 000000000000..1486f8ce5c75 --- /dev/null +++ b/lib/libc/include/generic-openbsd/machine/loadfile_machdep.h @@ -0,0 +1,49 @@ +/* $OpenBSD: loadfile_machdep.h,v 1.2 2015/07/17 20:44:39 miod Exp $ */ +/* $NetBSD: loadfile_machdep.h,v 1.2 2001/10/31 17:20:49 thorpej Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define BOOT_ELF +#define ELFSIZE 64 + +#define LOAD_KERNEL LOAD_ALL +#define COUNT_KERNEL COUNT_ALL + +#define LOADADDR(a) (((u_long)(a)) + offset) +#define ALIGNENTRY(a) ((u_long)(a)) +#define READ(f, b, c) read((f), (void *)LOADADDR(b), (c)) +#define BCOPY(s, d, c) memcpy((void *)LOADADDR(d), (void *)(s), (c)) +#define BZERO(d, c) memset((void *)LOADADDR(d), 0, (c)) +#define WARN(a) (void)(printf a, \ + printf((errno ? ": %s\n" : "\n"), \ + strerror(errno))) +#define PROGRESS(a) (void) printf a +#define ALLOC(a) alloc(a) +#define FREE(a, b) free(a, b) \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/machine/mplock.h b/lib/libc/include/generic-openbsd/machine/mplock.h new file mode 100644 index 000000000000..0630808c58de --- /dev/null +++ b/lib/libc/include/generic-openbsd/machine/mplock.h @@ -0,0 +1,10 @@ +/* $OpenBSD: mplock.h,v 1.4 2017/10/17 14:25:35 visa Exp $ */ + +/* public domain */ + +#ifndef _MACHINE_MPLOCK_H_ +#define _MACHINE_MPLOCK_H_ + +#define __USE_MI_MPLOCK + +#endif /* !_MACHINE_MPLOCK_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/machine/reloc.h b/lib/libc/include/generic-openbsd/machine/reloc.h new file mode 100644 index 000000000000..4eb8c01cf15e --- /dev/null +++ b/lib/libc/include/generic-openbsd/machine/reloc.h @@ -0,0 +1,5 @@ +/* $OpenBSD: reloc.h,v 1.1 2017/08/12 15:33:41 visa Exp $ */ + +/* public domain */ + +#include \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/machine/smbiosvar.h b/lib/libc/include/generic-openbsd/machine/smbiosvar.h new file mode 100644 index 000000000000..34349b6ec955 --- /dev/null +++ b/lib/libc/include/generic-openbsd/machine/smbiosvar.h @@ -0,0 +1,281 @@ +/* $OpenBSD: smbiosvar.h,v 1.14 2025/07/15 01:09:32 jsg Exp $ */ +/* + * Copyright (c) 2006 Gordon Willem Klok + * Copyright (c) 2005 Jordan Hargrave + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_SMBIOSVAR_ +#define _MACHINE_SMBIOSVAR_ + +#define SMBIOS_START 0xf0000 +#define SMBIOS_END 0xfffff + +#define SMBIOS_UUID_NPRESENT 0x1 +#define SMBIOS_UUID_NSET 0x2 + +/* + * Section 3.5 of "UUIDs and GUIDs" found at + * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt + * specifies the string representation of a UUID. + */ +#define SMBIOS_UUID_REP "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" +#define SMBIOS_UUID_REPLEN 37 /* 16 zero padded values, 4 hyphens, 1 null */ + +struct smbios_entry { + uint8_t mjr; + uint8_t min; + uint8_t *addr; + uint16_t len; + uint16_t count; +}; + +struct smbhdr { + uint32_t sig; /* "_SM_" */ + uint8_t checksum; /* Entry point checksum */ + uint8_t len; /* Entry point structure length */ + uint8_t majrev; /* Specification major revision */ + uint8_t minrev; /* Specification minor revision */ + uint16_t mss; /* Maximum Structure Size */ + uint8_t epr; /* Entry Point Revision */ + uint8_t fa[5]; /* value determined by EPR */ + uint8_t sasig[5]; /* Secondary Anchor "_DMI_" */ + uint8_t sachecksum; /* Secondary Checksum */ + uint16_t size; /* Length of structure table in bytes */ + uint32_t addr; /* Structure table address */ + uint16_t count; /* Number of SMBIOS structures */ + uint8_t rev; /* BCD revision */ +} __packed; + +struct smb3hdr { + uint8_t sig[5]; /* "_SM3_" */ + uint8_t checksum; /* Entry point structure checksum */ + uint8_t len; /* Entry point length */ + uint8_t majrev; /* SMBIOS major version */ + uint8_t minrev; /* SMBIOS minor version */ + uint8_t docrev; /* SMBIOS docrev */ + uint8_t epr; /* Entry point revision */ + uint8_t reserved; /* Reserved */ + uint32_t size; /* Structure table maximum size */ + uint64_t addr; /* Structure table address */ +} __packed; + +struct smbtblhdr { + uint8_t type; + uint8_t size; + uint16_t handle; +} __packed; + +struct smbtable { + struct smbtblhdr *hdr; + void *tblhdr; + uint32_t cookie; +}; + +#define SMBIOS_TYPE_BIOS 0 +#define SMBIOS_TYPE_SYSTEM 1 +#define SMBIOS_TYPE_BASEBOARD 2 +#define SMBIOS_TYPE_ENCLOSURE 3 +#define SMBIOS_TYPE_PROCESSOR 4 +#define SMBIOS_TYPE_MEMCTRL 5 +#define SMBIOS_TYPE_MEMMOD 6 +#define SMBIOS_TYPE_CACHE 7 +#define SMBIOS_TYPE_PORT 8 +#define SMBIOS_TYPE_SLOTS 9 +#define SMBIOS_TYPE_OBD 10 +#define SMBIOS_TYPE_OEM 11 +#define SMBIOS_TYPE_SYSCONFOPT 12 +#define SMBIOS_TYPE_BIOSLANG 13 +#define SMBIOS_TYPE_GROUPASSOC 14 +#define SMBIOS_TYPE_SYSEVENTLOG 15 +#define SMBIOS_TYPE_PHYMEM 16 +#define SMBIOS_TYPE_MEMDEV 17 +#define SMBIOS_TYPE_ECCINFO32 18 +#define SMBIOS_TYPE_MEMMAPARRAYADDR 19 +#define SMBIOS_TYPE_MEMMAPDEVADDR 20 +#define SMBIOS_TYPE_INBUILTPOINT 21 +#define SMBIOS_TYPE_PORTBATT 22 +#define SMBIOS_TYPE_SYSRESET 23 +#define SMBIOS_TYPE_HWSECUIRTY 24 +#define SMBIOS_TYPE_PWRCTRL 25 +#define SMBIOS_TYPE_VOLTPROBE 26 +#define SMBIOS_TYPE_COOLING 27 +#define SMBIOS_TYPE_TEMPPROBE 28 +#define SMBIOS_TYPE_CURRENTPROBE 29 +#define SMBIOS_TYPE_OOB_REMOTEACCESS 30 +#define SMBIOS_TYPE_BIS 31 +#define SMBIOS_TYPE_SBI 32 +#define SMBIOS_TYPE_ECCINFO64 33 +#define SMBIOS_TYPE_MGMTDEV 34 +#define SMBIOS_TYPE_MGTDEVCOMP 35 +#define SMBIOS_TYPE_MGTDEVTHRESH 36 +#define SMBIOS_TYPE_MEMCHANNEL 37 +#define SMBIOS_TYPE_IPMIDEV 38 +#define SMBIOS_TYPE_SPS 39 +#define SMBIOS_TYPE_INACTIVE 126 +#define SMBIOS_TYPE_EOT 127 + +/* + * SMBIOS Structure Type 0 "BIOS Information" + * DMTF Specification DSP0134 Section: 3.3.1 p.g. 34 + */ +struct smbios_struct_bios { + uint8_t vendor; /* string */ + uint8_t version; /* string */ + uint16_t startaddr; + uint8_t release; /* string */ + uint8_t romsize; + uint64_t characteristics; + uint32_t charext; + uint8_t major_rel; + uint8_t minor_rel; + uint8_t ecf_mjr_rel; /* embedded controller firmware */ + uint8_t ecf_min_rel; /* embedded controller firmware */ +} __packed; + +/* + * SMBIOS Structure Type 1 "System Information" + * DMTF Specification DSP0134 Section 3.3.2 p.g. 35 + */ + +struct smbios_sys { +/* SMBIOS spec 2.0+ */ + uint8_t vendor; /* string */ + uint8_t product; /* string */ + uint8_t version; /* string */ + uint8_t serial; /* string */ +/* SMBIOS spec 2.1+ */ + uint8_t uuid[16]; + uint8_t wakeup; +/* SMBIOS spec 2.4+ */ + uint8_t sku; /* string */ + uint8_t family; /* string */ +} __packed; + +/* + * SMBIOS Structure Type 2 "Base Board (Module) Information" + * DMTF Specification DSP0134 Section 3.3.3 p.g. 37 + */ +struct smbios_board { + uint8_t vendor; /* string */ + uint8_t product; /* string */ + uint8_t version; /* string */ + uint8_t serial; /* string */ + uint8_t asset; /* string */ + uint8_t feature; /* feature flags */ + uint8_t location; /* location in chassis */ + uint16_t handle; /* chassis handle */ + uint8_t type; /* board type */ + uint8_t noc; /* number of contained objects */ +} __packed; + +/* + * SMBIOS Structure Type 3 "System Enclosure or Chassis" + * DMTF Specification DSP0134 + */ +struct smbios_enclosure { + /* SMBIOS spec 2.0+ */ + uint8_t vendor; /* string */ + uint8_t type; + uint8_t version; /* string */ + uint8_t serial; /* string */ + uint8_t asset_tag; /* string */ + /* SMBIOS spec 2.1+ */ + uint8_t boot_state; + uint8_t psu_state; + uint8_t thermal_state; + uint8_t security_status; + /* SMBIOS spec 2.3+ */ + uint16_t oem_defined; + uint8_t height; + uint8_t no_power_cords; + uint8_t no_contained_element; + uint8_t reclen_contained_element; + uint8_t contained_elements; + /* SMBIOS spec 2.7+ */ + uint8_t sku; /* string */ +} __packed; + +/* + * SMBIOS Structure Type 4 "processor Information" + * DMTF Specification DSP0134 v2.5 Section 3.3.5 p.g. 24 + */ +struct smbios_cpu { + uint8_t cpu_socket_designation; /* string */ + uint8_t cpu_type; + uint8_t cpu_family; + uint8_t cpu_mfg; /* string */ + uint32_t cpu_id_eax; + uint32_t cpu_id_edx; + uint8_t cpu_version; /* string */ + uint8_t cpu_voltage; + uint16_t cpu_clock; + uint16_t cpu_max_speed; + uint16_t cpu_current_speed; + uint8_t cpu_status; +#define SMBIOS_CPUST_POPULATED (1<<6) +#define SMBIOS_CPUST_STATUSMASK (0x07) + uint8_t cpu_upgrade; + uint16_t cpu_l1_handle; + uint16_t cpu_l2_handle; + uint16_t cpu_l3_handle; + uint8_t cpu_serial; /* string */ + uint8_t cpu_asset_tag; /* string */ + uint8_t cpu_part_nr; /* string */ + /* following fields were added in smbios 2.5 */ + uint8_t cpu_core_count; + uint8_t cpu_core_enabled; + uint8_t cpu_thread_count; + uint16_t cpu_characteristics; +} __packed; + +/* + * SMBIOS Structure Type 38 "IPMI Information" + * DMTF Specification DSP0134 Section 3.3.39 p.g. 91 + */ +struct smbios_ipmi { + uint8_t smipmi_if_type; /* IPMI Interface Type */ + uint8_t smipmi_if_rev; /* BCD IPMI Revision */ + uint8_t smipmi_i2c_address; /* I2C address of BMC */ + uint8_t smipmi_nvram_address; /* I2C address of NVRAM + * storage */ + uint64_t smipmi_base_address; /* Base address of BMC (BAR + * format */ + uint8_t smipmi_base_flags; /* Flags field: + * bit 7:6 : register spacing + * 00 = byte + * 01 = dword + * 02 = word + * bit 4 : Lower bit BAR + * bit 3 : IRQ valid + * bit 2 : N/A + * bit 1 : Interrupt polarity + * bit 0 : Interrupt trigger */ + uint8_t smipmi_irq; /* IRQ if applicable */ +} __packed; + +int smbios_find_table(uint8_t, struct smbtable *); +char *smbios_get_string(struct smbtable *, uint8_t, char *, size_t); + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/machine/spinlock.h b/lib/libc/include/generic-openbsd/machine/spinlock.h new file mode 100644 index 000000000000..f3fe78c83412 --- /dev/null +++ b/lib/libc/include/generic-openbsd/machine/spinlock.h @@ -0,0 +1,10 @@ +/* $OpenBSD: spinlock.h,v 1.3 2017/09/05 02:40:54 guenther Exp $ */ + +#ifndef _MACHINE_SPINLOCK_H_ +#define _MACHINE_SPINLOCK_H_ + +#define _ATOMIC_LOCK_UNLOCKED (0) +#define _ATOMIC_LOCK_LOCKED (1) +typedef int _atomic_lock_t; + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/machine/tcb.h b/lib/libc/include/generic-openbsd/machine/tcb.h new file mode 100644 index 000000000000..427e19101a00 --- /dev/null +++ b/lib/libc/include/generic-openbsd/machine/tcb.h @@ -0,0 +1,3 @@ +/* $OpenBSD: tcb.h,v 1.2 2013/06/01 21:20:54 jasper Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/machine/timetc.h b/lib/libc/include/generic-openbsd/machine/timetc.h new file mode 100644 index 000000000000..9af8a41ca23f --- /dev/null +++ b/lib/libc/include/generic-openbsd/machine/timetc.h @@ -0,0 +1,23 @@ +/* $OpenBSD: timetc.h,v 1.1 2020/07/06 13:33:07 pirofti Exp $ */ +/* + * Copyright (c) 2020 Paul Irofti + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TIMETC_H_ +#define _MACHINE_TIMETC_H_ + +#define TC_LAST 0 + +#endif /* _MACHINE_TIMETC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/math.h b/lib/libc/include/generic-openbsd/math.h new file mode 100644 index 000000000000..9cad4b0f74b0 --- /dev/null +++ b/lib/libc/include/generic-openbsd/math.h @@ -0,0 +1,497 @@ +/* $OpenBSD: math.h,v 1.36 2018/03/10 20:52:58 kettenis Exp $ */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * from: @(#)fdlibm.h 5.1 93/09/24 + */ + +#ifndef _MATH_H_ +#define _MATH_H_ + +#include +#include + +__BEGIN_DECLS +/* + * ANSI/POSIX + */ +extern char __infinity[]; +#if __GNUC_PREREQ__(3, 3) +#define HUGE_VAL __builtin_huge_val() +#else /* __GNUC_PREREQ__(3, 3) */ +#define HUGE_VAL (*(double *)(void *)__infinity) +#endif /* __GNUC_PREREQ__(3, 3) */ + +/* + * C99 + */ +#if __ISO_C_VISIBLE >= 1999 +typedef __double_t double_t; +typedef __float_t float_t; + +#if __GNUC_PREREQ__(3, 3) +#define HUGE_VALF __builtin_huge_valf() +#define HUGE_VALL __builtin_huge_vall() +#define INFINITY __builtin_inff() +#define NAN __builtin_nanf("") +#else /* __GNUC_PREREQ__(3, 3) */ +#define HUGE_VALF ((float)HUGE_VAL) +#define HUGE_VALL ((long double)HUGE_VAL) +#define INFINITY HUGE_VALF +extern char __nan[]; +#define NAN (*(float *)(void *)__nan) +#endif /* __GNUC_PREREQ__(3, 3) */ + +#define FP_INFINITE 0x01 +#define FP_NAN 0x02 +#define FP_NORMAL 0x04 +#define FP_SUBNORMAL 0x08 +#define FP_ZERO 0x10 + +#define FP_ILOGB0 (-INT_MAX) +#define FP_ILOGBNAN INT_MAX + +#ifdef __FP_FAST_FMA +#define FP_FAST_FMA 1 +#endif /* __FP_FAST_FMA */ + +#ifdef __FP_FAST_FMAF +#define FP_FAST_FMAF 1 +#endif /* __FP_FAST_FMAF */ + +#ifdef __FP_FAST_FMAL +#define FP_FAST_FMAL 1 +#endif /* __FP_FAST_FMAL */ + +#define MATH_ERRNO 1 +#define MATH_ERREXCEPT 2 +#define math_errhandling MATH_ERREXCEPT + +#define fpclassify(x) \ + ((sizeof (x) == sizeof (float)) ? \ + __fpclassifyf(x) \ + : (sizeof (x) == sizeof (double)) ? \ + __fpclassify(x) \ + : __fpclassifyl(x)) +#define isfinite(x) \ + ((sizeof (x) == sizeof (float)) ? \ + __isfinitef(x) \ + : (sizeof (x) == sizeof (double)) ? \ + __isfinite(x) \ + : __isfinitel(x)) +#define isnormal(x) \ + ((sizeof (x) == sizeof (float)) ? \ + __isnormalf(x) \ + : (sizeof (x) == sizeof (double)) ? \ + __isnormal(x) \ + : __isnormall(x)) +#define signbit(x) \ + ((sizeof (x) == sizeof (float)) ? \ + __signbitf(x) \ + : (sizeof (x) == sizeof (double)) ? \ + __signbit(x) \ + : __signbitl(x)) + +#define isgreater(x, y) (!isunordered((x), (y)) && (x) > (y)) +#define isgreaterequal(x, y) (!isunordered((x), (y)) && (x) >= (y)) +#define isless(x, y) (!isunordered((x), (y)) && (x) < (y)) +#define islessequal(x, y) (!isunordered((x), (y)) && (x) <= (y)) +#define islessgreater(x, y) (!isunordered((x), (y)) && \ + ((x) > (y) || (y) > (x))) +#define isunordered(x, y) (isnan(x) || isnan(y)) +#endif /* __ISO_C_VISIBLE >= 1999 */ + +#define isinf(x) \ + ((sizeof (x) == sizeof (float)) ? \ + __isinff(x) \ + : (sizeof (x) == sizeof (double)) ? \ + __isinf(x) \ + : __isinfl(x)) +#define isnan(x) \ + ((sizeof (x) == sizeof (float)) ? \ + __isnanf(x) \ + : (sizeof (x) == sizeof (double)) ? \ + __isnan(x) \ + : __isnanl(x)) + +/* + * XOPEN/SVID + */ +#if __BSD_VISIBLE || __XPG_VISIBLE +#define M_E ((double)2.7182818284590452354) /* e */ +#define M_LOG2E ((double)1.4426950408889634074) /* log 2e */ +#define M_LOG10E ((double)0.43429448190325182765) /* log 10e */ +#define M_LN2 ((double)0.69314718055994530942) /* log e2 */ +#define M_LN10 ((double)2.30258509299404568402) /* log e10 */ +#define M_PI ((double)3.14159265358979323846) /* pi */ +#define M_PI_2 ((double)1.57079632679489661923) /* pi/2 */ +#define M_PI_4 ((double)0.78539816339744830962) /* pi/4 */ +#define M_1_PI ((double)0.31830988618379067154) /* 1/pi */ +#define M_2_PI ((double)0.63661977236758134308) /* 2/pi */ +#define M_2_SQRTPI ((double)1.12837916709551257390) /* 2/sqrt(pi) */ +#define M_SQRT2 ((double)1.41421356237309504880) /* sqrt(2) */ +#define M_SQRT1_2 ((double)0.70710678118654752440) /* 1/sqrt(2) */ + +#define MAXFLOAT ((float)3.40282346638528860e+38) + +extern int signgam; +#endif /* __BSD_VISIBLE || __XPG_VISIBLE */ + +#if __POSIX_VISIBLE >= 201403 +#define M_El 2.718281828459045235360287471352662498L /* e */ +#define M_LOG2El 1.442695040888963407359924681001892137L /* log 2e */ +#define M_LOG10El 0.434294481903251827651128918916605082L /* log 10e */ +#define M_LN2l 0.693147180559945309417232121458176568L /* log e2 */ +#define M_LN10l 2.302585092994045684017991454684364208L /* log e10 */ +#define M_PIl 3.141592653589793238462643383279502884L /* pi */ +#define M_PI_2l 1.570796326794896619231321691639751442L /* pi/2 */ +#define M_PI_4l 0.785398163397448309615660845819875721L /* pi/4 */ +#define M_1_PIl 0.318309886183790671537767526745028724L /* 1/pi */ +#define M_2_PIl 0.636619772367581343075535053490057448L /* 2/pi */ +#define M_2_SQRTPIl 1.128379167095512573896158903121545172L /* 2/sqrt(pi) */ +#define M_SQRT2l 1.414213562373095048801688724209698079L /* sqrt(2) */ +#define M_SQRT1_2l 0.707106781186547524400844362104849039L /* 1/sqrt(2) */ +#endif /* __POSIX_VISIBLE >= 201403 */ + +#if __BSD_VISIBLE +#define HUGE MAXFLOAT +#endif /* __BSD_VISIBLE */ + +/* + * ANSI/POSIX + */ +double acos(double); +double asin(double); +double atan(double); +double atan2(double, double); +double cos(double); +double sin(double); +double tan(double); + +double cosh(double); +double sinh(double); +double tanh(double); + +double exp(double); +double frexp(double, int *); +double ldexp(double, int); +double log(double); +double log10(double); +double modf(double, double *); + +double pow(double, double); +double sqrt(double); + +double ceil(double); +double fabs(double); +double floor(double); +double fmod(double, double); + +/* + * C99 + */ +#if __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999 || __XPG_VISIBLE +double acosh(double); +double asinh(double); +double atanh(double); + +double exp2(double); +double expm1(double); +int ilogb(double); +double log1p(double); +double log2(double); +double logb(double); +double scalbn(double, int); +double scalbln(double, long int); + +double cbrt(double); +double hypot(double, double); + +double erf(double); +double erfc(double); +double lgamma(double); +double tgamma(double); + +double nearbyint(double); +double rint(double); +long int lrint(double); +long long int llrint(double); +double round(double); +long int lround(double); +long long int llround(double); +double trunc(double); + +double remainder(double, double); +double remquo(double, double, int *); + +double copysign(double, double); +double nan(const char *); +double nextafter(double, double); +double nexttoward(double, long double); + +double fdim(double, double); +double fmax(double, double); +double fmin(double, double); + +double fma(double, double, double); +#endif /* __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999 || __XPG_VISIBLE */ + +#if __BSD_VISIBLE || __XPG_VISIBLE +double j0(double); +double j1(double); +double jn(int, double); +double scalb(double, double); +double y0(double); +double y1(double); +double yn(int, double); +#endif /* __BSD_VISIBLE || __XPG_VISIBLE */ + +#if __BSD_VISIBLE || __XPG_VISIBLE <= 500 +double gamma(double); +#endif /* __BSD_VISIBLE || __XPG_VISIBLE <= 500 */ + +/* + * BSD math library entry points + */ +#if __BSD_VISIBLE +double drem(double, double); +int finite(double); + +/* + * Reentrant version of gamma & lgamma; passes signgam back by reference + * as the second argument; user must allocate space for signgam. + */ +double gamma_r(double, int *); +double lgamma_r(double, int *); + +void sincos(double, double *, double *); + +/* + * IEEE Test Vector + */ +double significand(double); +#endif /* __BSD_VISIBLE */ + +/* + * Float versions of C99 functions + */ +#if __ISO_C_VISIBLE >= 1999 +float acosf(float); +float asinf(float); +float atanf(float); +float atan2f(float, float); +float cosf(float); +float sinf(float); +float tanf(float); + +float acoshf(float); +float asinhf(float); +float atanhf(float); +float coshf(float); +float sinhf(float); +float tanhf(float); + +float expf(float); +float exp2f(float); +float expm1f(float); +float frexpf(float, int *); +int ilogbf(float); +float ldexpf(float, int); +float logf(float); +float log10f(float); +float log1pf(float); +float log2f(float); +float logbf(float); +float modff(float, float *); +float scalbnf(float, int); +float scalblnf(float, long int); + +float cbrtf(float); +float fabsf(float); +float hypotf(float, float); +float powf(float, float); +float sqrtf(float); + +float erff(float); +float erfcf(float); +float lgammaf(float); +float tgammaf(float); + +float ceilf(float); +float floorf(float); +float nearbyintf(float); +float rintf(float); +long int lrintf(float); +long long int llrintf(float); +float roundf(float); +long int lroundf(float); +long long int llroundf(float); +float truncf(float); + +float fmodf(float, float); +float remainderf(float, float); +float remquof(float, float, int *); + +float copysignf(float, float); +float nanf(const char *); +float nextafterf(float, float); +float nexttowardf(float, long double); + +float fdimf(float, float); +float fmaxf(float, float); +float fminf(float, float); + +float fmaf(float, float, float); +#endif /* __ISO_C_VISIBLE >= 1999 */ + +#if __BSD_VISIBLE || __XPG_VISIBLE +float j0f(float); +float j1f(float); +float jnf(int, float); +float scalbf(float, float); +float y0f(float); +float y1f(float); +float ynf(int, float); +#endif /* __BSD_VISIBLE || __XPG_VISIBLE */ + +#if __BSD_VISIBLE || __XPG_VISIBLE <= 500 +float gammaf(float); +#endif /* __BSD_VISIBLE || __XPG_VISIBLE <= 500 */ + +/* + * Float versions of BSD math library entry points + */ +#if __BSD_VISIBLE +float dremf(float, float); +int finitef(float); +int isinff(float); +int isnanf(float); + +/* + * Float versions of reentrant version of gamma & lgamma; passes + * signgam back by reference as the second argument; user must + * allocate space for signgam. + */ +float gammaf_r(float, int *); +float lgammaf_r(float, int *); + +void sincosf(float, float *, float *); + +/* + * Float version of IEEE Test Vector + */ +float significandf(float); +#endif /* __BSD_VISIBLE */ + +/* + * Long double versions of C99 functions + */ +#if __ISO_C_VISIBLE >= 1999 +long double acosl(long double); +long double asinl(long double); +long double atanl(long double); +long double atan2l(long double, long double); +long double cosl(long double); +long double sinl(long double); +long double tanl(long double); + +long double acoshl(long double); +long double asinhl(long double); +long double atanhl(long double); +long double coshl(long double); +long double sinhl(long double); +long double tanhl(long double); + +long double expl(long double); +long double exp2l(long double); +long double expm1l(long double); +long double frexpl(long double, int *); +int ilogbl(long double); +long double ldexpl(long double, int); +long double logl(long double); +long double log10l(long double); +long double log1pl(long double); +long double log2l(long double); +long double logbl(long double); +long double modfl(long double, long double *); +long double scalbnl(long double, int); +long double scalblnl(long double, long int); + +long double cbrtl(long double); +long double fabsl(long double); +long double hypotl(long double, long double); +long double powl(long double, long double); +long double sqrtl(long double); + +long double erfl(long double); +long double erfcl(long double); +long double lgammal(long double); +long double tgammal(long double); + +long double ceill(long double); +long double floorl(long double); +long double nearbyintl(long double); +long double rintl(long double); +long int lrintl(long double); +long long int llrintl(long double); +long double roundl(long double); +long int lroundl(long double); +long long int llroundl(long double); +long double truncl(long double); + +long double fmodl(long double, long double); +long double remainderl(long double, long double); +long double remquol(long double, long double, int *); + +long double copysignl(long double, long double); +long double nanl(const char *); +long double nextafterl(long double, long double); +long double nexttowardl(long double, long double); + +long double fdiml(long double, long double); +long double fmaxl(long double, long double); +long double fminl(long double, long double); + +long double fmal(long double, long double, long double); +#endif /* __ISO_C_VISIBLE >= 1999 */ + +/* + * Long double versions of BSD math library entry points + */ +#if __BSD_VISIBLE +void sincosl(long double, long double *, long double *); +#endif + +/* + * Library implementation + */ +int __fpclassify(double); +int __fpclassifyf(float); +int __fpclassifyl(long double); +int __isfinite(double); +int __isfinitef(float); +int __isfinitel(long double); +int __isinf(double); +int __isinff(float); +int __isinfl(long double); +int __isnan(double); +int __isnanf(float); +int __isnanl(long double); +int __isnormal(double); +int __isnormalf(float); +int __isnormall(long double); +int __signbit(double); +int __signbitf(float); +int __signbitl(long double); +__END_DECLS + +#endif /* !_MATH_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/md5.h b/lib/libc/include/generic-openbsd/md5.h new file mode 100644 index 000000000000..a4623a50efae --- /dev/null +++ b/lib/libc/include/generic-openbsd/md5.h @@ -0,0 +1,49 @@ +/* $OpenBSD: md5.h,v 1.17 2012/12/05 23:19:57 deraadt Exp $ */ + +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + */ + +#ifndef _MD5_H_ +#define _MD5_H_ + +#define MD5_BLOCK_LENGTH 64 +#define MD5_DIGEST_LENGTH 16 +#define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1) + +typedef struct MD5Context { + u_int32_t state[4]; /* state */ + u_int64_t count; /* number of bits, mod 2^64 */ + u_int8_t buffer[MD5_BLOCK_LENGTH]; /* input buffer */ +} MD5_CTX; + +__BEGIN_DECLS +void MD5Init(MD5_CTX *); +void MD5Update(MD5_CTX *, const u_int8_t *, size_t) + __attribute__((__bounded__(__string__,2,3))); +void MD5Pad(MD5_CTX *); +void MD5Final(u_int8_t [MD5_DIGEST_LENGTH], MD5_CTX *) + __attribute__((__bounded__(__minbytes__,1,MD5_DIGEST_LENGTH))); +void MD5Transform(u_int32_t [4], const u_int8_t [MD5_BLOCK_LENGTH]) + __attribute__((__bounded__(__minbytes__,1,4))) + __attribute__((__bounded__(__minbytes__,2,MD5_BLOCK_LENGTH))); +char *MD5End(MD5_CTX *, char *) + __attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH))); +char *MD5File(const char *, char *) + __attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH))); +char *MD5FileChunk(const char *, char *, off_t, off_t) + __attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH))); +char *MD5Data(const u_int8_t *, size_t, char *) + __attribute__((__bounded__(__string__,1,2))) + __attribute__((__bounded__(__minbytes__,3,MD5_DIGEST_STRING_LENGTH))); +__END_DECLS + +#endif /* _MD5_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/memory.h b/lib/libc/include/generic-openbsd/memory.h new file mode 100644 index 000000000000..c3228633f775 --- /dev/null +++ b/lib/libc/include/generic-openbsd/memory.h @@ -0,0 +1,35 @@ +/* $OpenBSD: memory.h,v 1.3 2003/06/02 19:34:12 millert Exp $ */ +/* $NetBSD: memory.h,v 1.3 1994/10/26 00:56:06 cgd Exp $ */ + +/* + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)memory.h 5.5 (Berkeley) 6/1/90 + */ + +#include \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/_float.h b/lib/libc/include/generic-openbsd/mips64/_float.h new file mode 100644 index 000000000000..4bb91f4f9e68 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/_float.h @@ -0,0 +1,71 @@ +/* $OpenBSD: _float.h,v 1.1 2012/06/26 16:12:44 deraadt Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE__FLOAT_H_ +#define _MACHINE__FLOAT_H_ + +#define __FLT_RADIX 2 /* b */ +#define __FLT_ROUNDS __flt_rounds() +#define __FLT_EVAL_METHOD 0 /* no promotions */ + +#define __FLT_MANT_DIG 24 /* p */ +#define __FLT_EPSILON 1.19209290E-07F /* b**(1-p) */ +#define __FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ +#define __FLT_MIN_EXP (-125) /* emin */ +#define __FLT_MIN 1.17549435E-38F /* b**(emin-1) */ +#define __FLT_MIN_10_EXP (-37) /* ceil(log10(b**(emin-1))) */ +#define __FLT_MAX_EXP 128 /* emax */ +#define __FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ +#define __FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ + +#define __DBL_MANT_DIG 53 +#define __DBL_EPSILON 2.2204460492503131E-16 +#define __DBL_DIG 15 +#define __DBL_MIN_EXP (-1021) +#define __DBL_MIN 2.2250738585072014E-308 +#define __DBL_MIN_10_EXP (-307) +#define __DBL_MAX_EXP 1024 +#define __DBL_MAX 1.7976931348623157E+308 +#define __DBL_MAX_10_EXP 308 + +#define __LDBL_MANT_DIG 113 +#define __LDBL_EPSILON 1.92592994438723585305597794258492732e-34L +#define __LDBL_DIG 33 +#define __LDBL_MIN_EXP (-16381) +#define __LDBL_MIN 3.36210314311209350626267781732175260e-4932L +#define __LDBL_MIN_10_EXP (-4931) +#define __LDBL_MAX_EXP 16384 +#define __LDBL_MAX 1.18973149535723176508575932662800702e+4932L +#define __LDBL_MAX_10_EXP 4932 + +#define __DECIMAL_DIG 36 + +#endif /* _MACHINE__FLOAT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/_types.h b/lib/libc/include/generic-openbsd/mips64/_types.h new file mode 100644 index 000000000000..ca5dbe7d7bd2 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/_types.h @@ -0,0 +1,154 @@ +/* $OpenBSD: _types.h,v 1.25 2023/07/02 19:02:28 cheloha Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.3 (Berkeley) 1/5/94 + * @(#)ansi.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _MIPS64__TYPES_H_ +#define _MIPS64__TYPES_H_ + +/* + * _ALIGN(p) rounds p (pointer or byte index) up to a correctly-aligned + * value for all data types (int, long, ...). The result is an + * unsigned long and must be cast to any desired pointer type. + * + * _ALIGNED_POINTER is a boolean macro that checks whether an address + * is valid to fetch data elements of type t from on this architecture. + * This does not reflect the optimal alignment, just the possibility + * (within reasonable limits). + */ +#define _ALIGNBYTES 7 +#define _STACKALIGNBYTES 15 +#define _ALIGN(p) (((unsigned long)(p) + _ALIGNBYTES) & ~_ALIGNBYTES) +#define _ALIGNED_POINTER(p,t) ((((unsigned long)(p)) & (sizeof(t) - 1)) == 0) +#define _MAX_PAGE_SHIFT 14 /* maximum possible PAGE_SHIFT */ + +/* + * We need to handle the various ISA levels for sizes. + */ +#define _MIPS_ISA_MIPS1 1 /* R2000/R3000 */ +#define _MIPS_ISA_MIPS2 2 /* R4000/R6000 */ +#define _MIPS_ISA_MIPS3 3 /* R4000 */ +#define _MIPS_ISA_MIPS4 4 /* TFP (R1x000) */ +#define _MIPS_ISA_MIPS32 32 /* MIPS32 */ +#define _MIPS_ISA_MIPS64 64 /* MIPS64 */ + +/* 7.18.1.1 Exact-width integer types */ +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short __int16_t; +typedef unsigned short __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; +typedef long long __int64_t; +typedef unsigned long long __uint64_t; + +/* 7.18.1.2 Minimum-width integer types */ +typedef __int8_t __int_least8_t; +typedef __uint8_t __uint_least8_t; +typedef __int16_t __int_least16_t; +typedef __uint16_t __uint_least16_t; +typedef __int32_t __int_least32_t; +typedef __uint32_t __uint_least32_t; +typedef __int64_t __int_least64_t; +typedef __uint64_t __uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types */ +typedef __int32_t __int_fast8_t; +typedef __uint32_t __uint_fast8_t; +typedef __int32_t __int_fast16_t; +typedef __uint32_t __uint_fast16_t; +typedef __int32_t __int_fast32_t; +typedef __uint32_t __uint_fast32_t; +typedef __int64_t __int_fast64_t; +typedef __uint64_t __uint_fast64_t; +#define __INT_FAST8_MIN INT32_MIN +#define __INT_FAST16_MIN INT32_MIN +#define __INT_FAST32_MIN INT32_MIN +#define __INT_FAST64_MIN INT64_MIN +#define __INT_FAST8_MAX INT32_MAX +#define __INT_FAST16_MAX INT32_MAX +#define __INT_FAST32_MAX INT32_MAX +#define __INT_FAST64_MAX INT64_MAX +#define __UINT_FAST8_MAX UINT32_MAX +#define __UINT_FAST16_MAX UINT32_MAX +#define __UINT_FAST32_MAX UINT32_MAX +#define __UINT_FAST64_MAX UINT64_MAX + +/* 7.18.1.4 Integer types capable of holding object pointers */ +typedef long __intptr_t; +typedef unsigned long __uintptr_t; + +/* 7.18.1.5 Greatest-width integer types */ +typedef __int64_t __intmax_t; +typedef __uint64_t __uintmax_t; + +/* Register size */ +typedef long __register_t; +typedef long f_register_t; /* XXX */ + +/* VM system types */ +typedef unsigned long __vaddr_t; +typedef unsigned long __paddr_t; +typedef unsigned long __vsize_t; +typedef unsigned long __psize_t; + +/* Standard system types */ +typedef double __double_t; +typedef float __float_t; +typedef long __ptrdiff_t; +typedef unsigned long __size_t; +typedef long __ssize_t; +#if defined(__GNUC__) && __GNUC__ >= 3 +typedef __builtin_va_list __va_list; +#else +typedef char * __va_list; +#endif + +/* Wide character support types */ +#ifndef __cplusplus +typedef int __wchar_t; +#endif +typedef int __wint_t; +typedef int __rune_t; +typedef void * __wctrans_t; +typedef void * __wctype_t; + +#if defined(_KERNEL) +typedef struct label_t { + long val[14]; +} label_t; +#endif + +/* Feature test macros */ +#define __HAVE_EXEC_MD_MAP + +#endif /* _MIPS64__TYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/archtype.h b/lib/libc/include/generic-openbsd/mips64/archtype.h new file mode 100644 index 000000000000..7ab1da2012ed --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/archtype.h @@ -0,0 +1,77 @@ +/* $OpenBSD: archtype.h,v 1.16 2012/10/03 21:44:51 miod Exp $ */ +/* + * Copyright (c) 1997-2004 Opsycon AB, Sweden (www.opsycon.se) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _MIPS64_ARCHTYPE_H_ +#define _MIPS64_ARCHTYPE_H_ +/* + * Define architectural identities for the different Mips machines. + */ +#define ACER_PICA_61 0x0001 /* Acer Labs Pica 61 */ +#define MAGNUM 0x0002 /* Mips MAGNUM R4000 */ +#define DESKSTATION_RPC44 0x0003 /* Deskstation rPC44 */ +#define DESKSTATION_TYNE 0x0004 /* Deskstation Tyne */ +#define NKK_AQUARIUS 0x0005 /* NKK R4{67}00 PC */ +#define NEC_R94 0x0006 /* NEC Magnum class */ +#define SNI_RM200 0x0007 /* Siemens Nixdorf RM200 */ + +#define SGI_IP17 0x0011 /* Crimson */ +#define SGI_IP19 0x0012 /* Onyx (!S model Challenge) */ +#define SGI_IP20 0x0013 /* Indigo */ +#define SGI_IP21 0x0014 /* POWER Challenge, POWER Onyx */ +#define SGI_IP22 0x0015 /* Indy, Indigo2, Challenge S */ +#define SGI_IP25 0x0016 /* POWER Challenge R10k */ +#define SGI_IP26 0x0017 /* POWER Indigo2 R8k */ +#define SGI_IP27 0x0018 /* IP27 Origin200/2000 */ +#define SGI_IP28 0x0019 /* POWER Indigo2 R10k */ +#define SGI_OCTANE 0x001a /* IP30 Octane */ +#define SGI_O2 0x001b /* IP32 O2 */ +#define SGI_IP35 0x001c /* IP35 Origin3x0/3x00/Fuel/Tezro */ + +#define ALGOR_P4032 0x0021 /* ALGORITHMICS P-4032 */ +#define ALGOR_P5064 0x0022 /* ALGORITHMICS P-5064 */ + +#define GALILEO_G9 0x0031 /* Galileo GT-64011 Eval board */ +#define GALILEO_EV64240 0x0032 /* Galileo EV64240 Eval board */ +#define GALILEO_EV64340 0x0033 /* Galileo EV64340 Eval board */ + +#define MOMENTUM_CP7000 0x0041 /* Momentum Ocelot */ +#define MOMENTUM_CP7000G 0x0042 /* Momentum Ocelot-G */ +#define MOMENTUM_JAGUAR 0x0043 /* Momentum Jaguar ATX */ + +#define WG4308 0x0052 /* Willowglen 4308 LMD */ +#define WG4309 0x0053 /* Willowglen 4309 LMD */ +#define WG4409 0x0054 /* Willowglen 4409 LMD */ +#define WG8138 0x0055 /* Willowglen 8138 523x VME card */ +#define WG8168 0x0056 /* Willowglen 8168 5231 VME card */ +#define WG6000 0x0057 /* Willowglen CPU-6000 */ +#define WG7000 0x0058 /* Willowglen CPU-7000 */ +#define WG8200 0x0059 /* Willowglen CPU-8200 */ +#define WG8232 0x005a /* Willowglen CPU-8232 */ + +#define LAGUNA 0x00f1 /* Heurikon Laguna VME board */ + +#endif /* !_MIPS64_ARCHTYPE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/asm.h b/lib/libc/include/generic-openbsd/mips64/asm.h new file mode 100644 index 000000000000..8bc75825519e --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/asm.h @@ -0,0 +1,360 @@ +/* $OpenBSD: asm.h,v 1.27 2021/05/01 16:11:10 visa Exp $ */ + +/* + * Copyright (c) 2001-2002 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#ifndef _MIPS64_ASM_H_ +#define _MIPS64_ASM_H_ + +#include + +#define _MIPS_ISA_MIPS1 1 /* R2000/R3000 */ +#define _MIPS_ISA_MIPS2 2 /* R4000/R6000 */ +#define _MIPS_ISA_MIPS3 3 /* R4000 */ +#define _MIPS_ISA_MIPS4 4 /* TFP (R1x000) */ +#define _MIPS_ISA_MIPS32 32 /* MIPS32 */ +#define _MIPS_ISA_MIPS64 64 /* MIPS64 */ + +#if !defined(ABICALLS) && !defined(_NO_ABICALLS) +#define ABICALLS .abicalls +#endif + +#if defined(ABICALLS) && !defined(_KERNEL) + ABICALLS +#endif + +#define _C_LABEL(x) x /* XXX Obsolete but keep for a while */ + +#if !defined(__MIPSEL__) && !defined(__MIPSEB__) +#error "__MIPSEL__ or __MIPSEB__ must be defined" +#endif +/* + * Define how to access unaligned data word + */ +#if defined(__MIPSEL__) +#define LWLO lwl +#define LWHI lwr +#define SWLO swl +#define SWHI swr +#define LDLO ldl +#define LDHI ldr +#define SDLO sdl +#define SDHI sdr +#endif +#if defined(__MIPSEB__) +#define LWLO lwr +#define LWHI lwl +#define SWLO swr +#define SWHI swl +#define LDLO ldr +#define LDHI ldl +#define SDLO sdr +#define SDHI sdl +#endif + +/* + * Define programming environment for ABI. + */ +#if defined(ABICALLS) && !defined(_KERNEL) && !defined(_STANDALONE) + +#ifndef _MIPS_SIM +#define _MIPS_SIM 1 +#define _ABIO32 1 +#endif +#ifndef _MIPS_ISA +#define _MIPS_ISA 2 +#define _MIPS_ISA_MIPS2 2 +#endif + +#if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32) +#define NARGSAVE 4 + +#define SETUP_GP \ + .set noreorder; \ + .cpload t9; \ + .set reorder; + +#define SAVE_GP(x) \ + .cprestore x + +#define SETUP_GP64(gpoff, name) +#define RESTORE_GP64 +#endif + +#if (_MIPS_SIM == _ABI64) || (_MIPS_SIM == _ABIN32) +#define NARGSAVE 0 + +#define SETUP_GP +#define SAVE_GP(x) +#define SETUP_GP64(gpoff, name) \ + .cpsetup t9, gpoff, name +#define RESTORE_GP64 \ + .cpreturn +#endif + +#define MKFSIZ(narg,locals) (((narg+locals)*REGSZ+31)&(~31)) + +#else /* defined(ABICALLS) && !defined(_KERNEL) */ + +#define NARGSAVE 4 +#define SETUP_GP +#define SAVE_GP(x) + +#define ALIGNSZ 16 /* Stack layout alignment */ +#define FRAMESZ(sz) (((sz) + (ALIGNSZ-1)) & ~(ALIGNSZ-1)) + +#endif + +/* + * Basic register operations based on selected ISA + */ +#if (_MIPS_ISA == _MIPS_ISA_MIPS1 || _MIPS_ISA == _MIPS_ISA_MIPS2 || \ + _MIPS_ISA == _MIPS_ISA_MIPS32) +#define REGSZ 4 /* 32 bit mode register size */ +#define LOGREGSZ 2 /* log rsize */ +#define REG_S sw +#define REG_L lw +#define CF_SZ 24 /* Call frame size */ +#define CF_ARGSZ 16 /* Call frame arg size */ +#define CF_RA_OFFS 20 /* Call ra save offset */ +#endif + +#if (_MIPS_ISA == _MIPS_ISA_MIPS3 || _MIPS_ISA == _MIPS_ISA_MIPS4 || \ + _MIPS_ISA == _MIPS_ISA_MIPS64) +#define REGSZ 8 /* 64 bit mode register size */ +#define LOGREGSZ 3 /* log rsize */ +#define REG_S sd +#define REG_L ld +#define CF_SZ 48 /* Call frame size (multiple of ALIGNSZ) */ +#define CF_ARGSZ 32 /* Call frame arg size */ +#define CF_RA_OFFS 40 /* Call ra save offset */ +#endif + +#ifndef __LP64__ +#define PTR_L lw +#define PTR_S sw +#define PTR_SUB sub +#define PTR_ADD add +#define PTR_SUBU subu +#define PTR_ADDU addu +#define LI li +#define LA la +#define PTR_SLL sll +#define PTR_SRL srl +#define PTR_VAL .word +#else +#define PTR_L ld +#define PTR_S sd +#define PTR_ADD dadd +#define PTR_SUB dsub +#define PTR_SUBU dsubu +#define PTR_ADDU daddu +#define LI dli +#define LA dla +#define PTR_SLL dsll +#define PTR_SRL dsrl +#define PTR_VAL .dword +#endif + +#define NOP nop +#define DMFC0 dmfc0 +#define DMTC0 dmtc0 +#define MFC0 mfc0 +#define MTC0 mtc0 +#define ERET sync; eret + +/* + * Define -pg profile entry code. + */ +#if defined(XGPROF) || defined(XPROF) +#define MCOUNT \ + PTR_SUBU sp, sp, 64; \ + SAVE_GP(16); \ + sd ra, 56(sp); \ + sd gp, 48(sp); \ + .set noat; \ + .set noreorder; \ + move AT, ra; \ + jal _mcount; \ + PTR_SUBU sp, sp, 16; \ + ld ra, 56(sp); \ + PTR_ADDU sp, sp, 64; \ + .set reorder; \ + .set at; +#else +#define MCOUNT +#endif + +/* + * LEAF(x, fsize) + * + * Declare a leaf routine. + */ +#define LEAF(x, fsize) \ + .align 3; \ + .globl x; \ + .ent x, 0; \ +x: ; \ + .frame sp, fsize, ra; \ + SETUP_GP \ + MCOUNT + +#define ALEAF(x) \ + .globl x; \ +x: + +/* + * NLEAF(x) + * + * Declare a non-profiled leaf routine. + */ +#define NLEAF(x, fsize) \ + .align 3; \ + .globl x; \ + .ent x, 0; \ +x: ; \ + .frame sp, fsize, ra; \ + SETUP_GP + +/* + * NON_LEAF(x) + * + * Declare a non-leaf routine (a routine that makes other C calls). + */ +#define NON_LEAF(x, fsize, retpc) \ + .align 3; \ + .globl x; \ + .ent x, 0; \ +x: ; \ + .frame sp, fsize, retpc; \ + SETUP_GP \ + MCOUNT + +/* + * NNON_LEAF(x) + * + * Declare a non-profiled non-leaf routine + * (a routine that makes other C calls). + */ +#define NNON_LEAF(x, fsize, retpc) \ + .align 3; \ + .globl x; \ + .ent x, 0; \ +x: ; \ + .frame sp, fsize, retpc \ + SETUP_GP + +/* + * END(x) + * + * Mark end of a procedure. + */ +#define END(x) \ + .end x + +/* + * STRONG_ALIAS, WEAK_ALIAS + * Create a strong or weak alias. + */ +#define STRONG_ALIAS(alias,sym) \ + .global alias; alias = sym +#define WEAK_ALIAS(alias,sym) \ + .weak alias; alias = sym + + +/* + * Macros to panic and printf from assembly language. + */ +#define PANIC(msg) \ + LA a0, 9f; \ + jal panic; \ + nop ; \ + MSG(msg) + +#define PRINTF(msg) \ + LA a0, 9f; \ + jal printf; \ + nop ; \ + MSG(msg) + +#define MSG(msg) \ + .rdata; \ +9: .asciiz msg; \ + .text + +#define LOAD_XKPHYS(reg, cca) \ + li reg, cca | 0x10; \ + dsll reg, reg, 59 + +#ifdef MULTIPROCESSOR +#define GET_CPU_INFO(ci, tmp) HW_GET_CPU_INFO(ci, tmp) +#else /* MULTIPROCESSOR */ +#define GET_CPU_INFO(ci, tmp) \ + LA ci, cpu_info_primary +#endif /* MULTIPROCESSOR */ + +/* + * Hazards + */ + +#ifdef CPU_OCTEON +/* + * OCTEON clears hazards in hardware. + */ +#define MFC0_HAZARD /* nothing */ +#define MTC0_HAZARD /* nothing */ +#define MTC0_SR_IE_HAZARD /* nothing */ +#define MTC0_SR_CU_HAZARD /* nothing */ +#define TLB_HAZARD /* nothing */ +#endif + +/* Hazard between {d,}mfc0 of COP_0_VADDR */ +#ifndef PRE_MFC0_ADDR_HAZARD +#define PRE_MFC0_ADDR_HAZARD /* nothing */ +#endif + +/* Hazard after {d,}mfc0 from any register */ +#ifndef MFC0_HAZARD +#define MFC0_HAZARD /* nothing */ +#endif +/* Hazard after {d,}mtc0 to any register */ +#ifndef MTC0_HAZARD +#define MTC0_HAZARD NOP; NOP; NOP; NOP +#endif +/* Hazard after {d,}mtc0 to COP_0_SR affecting the state of interrupts */ +#ifndef MTC0_SR_IE_HAZARD +#define MTC0_SR_IE_HAZARD MTC0_HAZARD +#endif +/* Hazard after {d,}mtc0 to COP_0_SR affecting the state of coprocessors */ +#ifndef MTC0_SR_CU_HAZARD +#define MTC0_SR_CU_HAZARD NOP; NOP +#endif + +/* Hazard before and after a tlbp, tlbr, tlbwi or tlbwr instruction */ +#ifndef TLB_HAZARD +#define TLB_HAZARD NOP; NOP +#endif + +#endif /* !_MIPS64_ASM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/atomic.h b/lib/libc/include/generic-openbsd/mips64/atomic.h new file mode 100644 index 000000000000..a5b8737ccb01 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/atomic.h @@ -0,0 +1,214 @@ +/* $OpenBSD: atomic.h,v 1.12 2019/10/28 09:41:37 visa Exp $ */ + +/* Public Domain */ + +#ifndef _MIPS64_ATOMIC_H_ +#define _MIPS64_ATOMIC_H_ + +#if defined(_KERNEL) + +/* wait until the bits to set are clear, and set them */ +static __inline void +atomic_wait_and_setbits_int(volatile unsigned int *uip, unsigned int v) +{ + unsigned int tmp0, tmp1; + + __asm__ volatile ( + "1: ll %0, 0(%2)\n" + " and %1, %0, %3\n" + " bnez %1, 1b\n" + " or %0, %3, %0\n" + " sc %0, 0(%2)\n" + " beqz %0, 1b\n" + " nop\n" : + "=&r"(tmp0), "=&r"(tmp1) : + "r"(uip), "r"(v) : "memory"); +} + +static __inline void +atomic_setbits_int(volatile unsigned int *uip, unsigned int v) +{ + unsigned int tmp; + + __asm__ volatile ( + "1: ll %0, 0(%1)\n" + " or %0, %2, %0\n" + " sc %0, 0(%1)\n" + " beqz %0, 1b\n" + " nop\n" : + "=&r"(tmp) : + "r"(uip), "r"(v) : "memory"); +} + +static __inline void +atomic_clearbits_int(volatile unsigned int *uip, unsigned int v) +{ + unsigned int tmp; + + __asm__ volatile ( + "1: ll %0, 0(%1)\n" + " and %0, %2, %0\n" + " sc %0, 0(%1)\n" + " beqz %0, 1b\n" + " nop\n" : + "=&r"(tmp) : + "r"(uip), "r"(~v) : "memory"); +} + +#endif /* defined(_KERNEL) */ + +static inline unsigned int +_atomic_cas_uint(volatile unsigned int *p, unsigned int o, unsigned int n) +{ + unsigned int rv, wv; + + __asm__ volatile ( + "1: ll %0, %1\n" + " bne %0, %4, 2f\n" + " move %2, %3\n" + " sc %2, %1\n" + " beqz %2, 1b\n" + "2: nop\n" + : "=&r" (rv), "+m" (*p), "=&r" (wv) + : "r" (n), "Ir" (o)); + + return (rv); +} +#define atomic_cas_uint(_p, _o, _n) _atomic_cas_uint((_p), (_o), (_n)) + +static inline unsigned long +_atomic_cas_ulong(volatile unsigned long *p, unsigned long o, unsigned long n) +{ + unsigned long rv, wv; + + __asm__ volatile ( + "1: lld %0, %1\n" + " bne %0, %4, 2f\n" + " move %2, %3\n" + " scd %2, %1\n" + " beqz %2, 1b\n" + "2: nop\n" + : "=&r" (rv), "+m" (*p), "=&r" (wv) + : "r" (n), "Ir" (o)); + + return (rv); +} +#define atomic_cas_ulong(_p, _o, _n) _atomic_cas_ulong((_p), (_o), (_n)) + +static inline void * +_atomic_cas_ptr(volatile void *pp, void *o, void *n) +{ + void * volatile *p = pp; + void *rv, *wv; + + __asm__ volatile ( + "1: lld %0, %1\n" + " bne %0, %4, 2f\n" + " move %2, %3\n" + " scd %2, %1\n" + " beqz %2, 1b\n" + "2: nop\n" + : "=&r" (rv), "+m" (*p), "=&r" (wv) + : "r" (n), "Ir" (o)); + + return (rv); +} +#define atomic_cas_ptr(_p, _o, _n) _atomic_cas_ptr((_p), (_o), (_n)) + + + +static inline unsigned int +_atomic_swap_uint(volatile unsigned int *uip, unsigned int v) +{ + unsigned int o, t; + + __asm__ volatile ( + "1: ll %0, %1\n" + " move %2, %3\n" + " sc %2, %1\n" + " beqz %2, 1b\n" + " nop\n" + : "=&r" (o), "+m" (*uip), "=&r" (t) + : "r" (v)); + + return (o); +} +#define atomic_swap_uint(_p, _v) _atomic_swap_uint((_p), (_v)) + +static inline unsigned long +_atomic_swap_ulong(volatile unsigned long *uip, unsigned long v) +{ + unsigned long o, t; + + __asm__ volatile ( + "1: lld %0, %1\n" + " move %2, %3\n" + " scd %2, %1\n" + " beqz %2, 1b\n" + " nop\n" + : "=&r" (o), "+m" (*uip), "=&r" (t) + : "r" (v)); + + return (o); +} +#define atomic_swap_ulong(_p, _v) _atomic_swap_ulong((_p), (_v)) + + +static inline void * +_atomic_swap_ptr(volatile void *uipp, void *n) +{ + void * volatile *uip = uipp; + void *o, *t; + + __asm__ volatile ( + "1: lld %0, %1\n" + " move %2, %3\n" + " scd %2, %1\n" + " beqz %2, 1b\n" + " nop\n" + : "=&r" (o), "+m" (*uip), "=&r" (t) + : "r" (n)); + + return (o); +} +#define atomic_swap_ptr(_p, _n) _atomic_swap_ptr((_p), (_n)) + +static inline unsigned int +_atomic_add_int_nv(volatile unsigned int *uip, unsigned int v) +{ + unsigned int rv, nv; + + __asm__ volatile ( + "1: ll %0, %1\n" + " addu %2, %0, %3\n" + " sc %2, %1\n" + " beqz %2, 1b\n" + " nop\n" + : "=&r" (rv), "+m" (*uip), "=&r" (nv) + : "Ir" (v)); + + return (rv + v); +} +#define atomic_add_int_nv(_uip, _v) _atomic_add_int_nv((_uip), (_v)) +#define atomic_sub_int_nv(_uip, _v) _atomic_add_int_nv((_uip), 0 - (_v)) + +static inline unsigned long +_atomic_add_long_nv(volatile unsigned long *uip, unsigned long v) +{ + unsigned long rv, nv; + + __asm__ volatile ( + "1: lld %0, %1\n" + " daddu %2, %0, %3\n" + " scd %2, %1\n" + " beqz %2, 1b\n" + " nop\n" + : "=&r" (rv), "+m" (*uip), "=&r" (nv) + : "Ir" (v)); + + return (rv + v); +} +#define atomic_add_long_nv(_uip, _v) _atomic_add_long_nv((_uip), (_v)) +#define atomic_sub_long_nv(_uip, _v) _atomic_add_long_nv((_uip), 0UL - (_v)) + +#endif /* _MIPS64_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/autoconf.h b/lib/libc/include/generic-openbsd/mips64/autoconf.h new file mode 100644 index 000000000000..8a518cca7fc8 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/autoconf.h @@ -0,0 +1,37 @@ +/* $OpenBSD: autoconf.h,v 1.2 2017/06/08 12:02:52 visa Exp $ */ + +/* + * Copyright (c) 2010 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Common defines used by autoconf on all mips64-based platforms. + */ + +#ifndef _MIPS64_AUTOCONF_H_ +#define _MIPS64_AUTOCONF_H_ + +#include /* for struct cpu_hwinfo */ + +struct cpu_attach_args { + struct mainbus_attach_args caa_maa; + struct cpu_hwinfo *caa_hw; +}; + +extern struct cpu_hwinfo bootcpu_hwinfo; + +void unmap_startup(void); + +#endif /* _MIPS64_AUTOCONF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/cache.h b/lib/libc/include/generic-openbsd/mips64/cache.h new file mode 100644 index 000000000000..0f7ba849452b --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/cache.h @@ -0,0 +1,107 @@ +/* $OpenBSD: cache.h,v 1.9 2016/12/21 13:59:57 visa Exp $ */ + +/* + * Copyright (c) 2012 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MIPS64_CACHE_H_ +#define _MIPS64_CACHE_H_ + +/* + * Declare canonical cache functions for a given processor. + * + * The following assumptions are made: + * - only L1 has split instruction and data caches. + * - L1 I$ is virtually indexed. + * + * Processor-specific routines will make extra assumptions. + */ + +#define CACHE_PROTOS(chip) \ +/* Figure out cache configuration */ \ +void chip##_ConfigCache(struct cpu_info *); \ +/* Writeback and invalidate all caches */ \ +void chip##_SyncCache(struct cpu_info *); \ +/* Invalidate all I$ for the given range */ \ +void chip##_InvalidateICache(struct cpu_info *, vaddr_t, size_t); \ +/* Register a given page for I$ invalidation */ \ +void chip##_InvalidateICachePage(struct cpu_info *, vaddr_t); \ +/* Perform postponed I$ invalidation */ \ +void chip##_SyncICache(struct cpu_info *); \ +/* Writeback all D$ for the given page */ \ +void chip##_SyncDCachePage(struct cpu_info *, vaddr_t, paddr_t); \ +/* Writeback all D$ for the (currently mapped) given page */ \ +void chip##_HitSyncDCachePage(struct cpu_info *, vaddr_t, paddr_t); \ +/* Writeback all D$ for the given range */ \ +void chip##_HitSyncDCache(struct cpu_info *, vaddr_t, size_t); \ +/* Invalidate all D$ for the given range */ \ +void chip##_HitInvalidateDCache(struct cpu_info *, vaddr_t, size_t); \ +/* Enforce coherency of the given range */ \ +void chip##_IOSyncDCache(struct cpu_info *, vaddr_t, size_t, int); + +/* + * Cavium Octeon. + */ +CACHE_PROTOS(Octeon) + +void Octeon_lock_secondary_cache(struct cpu_info *, paddr_t, size_t); +void Octeon_unlock_secondary_cache(struct cpu_info *, paddr_t, size_t); + +/* + * STC Loongson 2E and 2F. + */ +CACHE_PROTOS(Loongson2) + +/* + * Loongson 3A and 2Gq. + */ +CACHE_PROTOS(Loongson3) + +/* + * MIPS R4000 and R4400. + */ +CACHE_PROTOS(Mips4k) + +/* + * IDT/QED/PMC-Sierra R4600, R4700, R5000, RM52xx, RM7xxx, RM9xxx. + */ +CACHE_PROTOS(Mips5k) + +/* + * MIPS (SGI, really) R8000. + */ +CACHE_PROTOS(tfp) + +/* + * MIPS/NEC R10000/R120000/R140000/R16000. + */ +CACHE_PROTOS(Mips10k) + +/* + * mips64r2-compliant processors. + */ +CACHE_PROTOS(mips64r2) + +/* + * Values used by the IOSyncDCache routine [which acts as the backend of + * bus_dmamap_sync()]. + */ +#define CACHE_SYNC_R 0 /* WB invalidate, WT invalidate */ +#define CACHE_SYNC_W 1 /* WB writeback, WT unaffected */ +#define CACHE_SYNC_X 2 /* WB writeback + invalidate, WT invalidate */ + +extern vaddr_t cache_valias_mask; + +#endif /* _MIPS64_CACHE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/cdefs.h b/lib/libc/include/generic-openbsd/mips64/cdefs.h new file mode 100644 index 000000000000..685c9d51d52f --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/cdefs.h @@ -0,0 +1,43 @@ +/* $OpenBSD: cdefs.h,v 1.6 2013/03/28 17:30:45 martynas Exp $ */ + +/* + * Copyright (c) 2002-2003 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _MIPS64_CDEFS_H_ +#define _MIPS64_CDEFS_H_ + +#define __strong_alias(alias,sym) \ + __asm__(".global " __STRING(alias) " ; " \ + __STRING(alias) " = " __STRING(sym)) +#define __weak_alias(alias,sym) \ + __asm__(".weak " __STRING(alias) " ; " \ + __STRING(alias) " = " __STRING(sym)) +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning." __STRING(sym) \ + " ; .ascii \"" msg "\" ; .text") +#define __indr_references(sym,msg) /* nothing */ + +#endif /* !_MIPS64_CDEFS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/cpu.h b/lib/libc/include/generic-openbsd/mips64/cpu.h new file mode 100644 index 000000000000..20177a255548 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/cpu.h @@ -0,0 +1,552 @@ +/* $OpenBSD: cpu.h,v 1.151 2025/06/06 00:07:58 deraadt Exp $ */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell and Rick Macklem. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Copyright (C) 1989 Digital Equipment Corporation. + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies. + * Digital Equipment Corporation makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * from: @(#)cpu.h 8.4 (Berkeley) 1/4/94 + */ + +#ifndef _MIPS64_CPU_H_ +#define _MIPS64_CPU_H_ + +#ifndef _LOCORE + +/* + * MIPS32-style segment definitions. + * They only cover the first 512MB of physical addresses. + */ +#define CKSEG0_BASE 0xffffffff80000000UL +#define CKSEG1_BASE 0xffffffffa0000000UL +#define CKSSEG_BASE 0xffffffffc0000000UL +#define CKSEG3_BASE 0xffffffffe0000000UL +#define CKSEG_SIZE 0x0000000020000000UL + +#define CKSEG0_TO_PHYS(x) ((u_long)(x) & (CKSEG_SIZE - 1)) +#define CKSEG1_TO_PHYS(x) ((u_long)(x) & (CKSEG_SIZE - 1)) +#define PHYS_TO_CKSEG0(x) ((u_long)(x) | CKSEG0_BASE) +#define PHYS_TO_CKSEG1(x) ((u_long)(x) | CKSEG1_BASE) + +/* + * MIPS64-style segment definitions. + * These allow for 36 bits of addressable physical memory, thus 64GB. + */ + +/* + * Cache Coherency Attributes. + */ +/* r8k only */ +#define CCA_NC_COPROCESSOR 0UL /* uncached, coprocessor ordered */ +/* common to r4, r5k, r8k and r1xk */ +#define CCA_NC 2UL /* uncached, write-around */ +#define CCA_NONCOHERENT 3UL /* cached, non-coherent, write-back */ +/* r8k, r1xk only */ +#define CCA_COHERENT_EXCL 4UL /* cached, coherent, exclusive */ +#define CCA_COHERENT_EXCLWRITE 5UL /* cached, coherent, exclusive write */ +/* r4k only */ +#define CCA_COHERENT_UPDWRITE 6UL /* cached, coherent, update on write */ +/* r1xk only */ +#define CCA_NC_ACCELERATED 7UL /* uncached accelerated */ + +#ifdef TGT_COHERENT +#define CCA_CACHED CCA_COHERENT_EXCLWRITE +#else +#define CCA_CACHED CCA_NONCOHERENT +#endif + +#define XKSSSEG_BASE 0x4000000000000000UL +#define XKPHYS_BASE 0x8000000000000000UL +#define XKSSEG_BASE 0xc000000000000000UL + +#define XKPHYS_TO_PHYS(x) ((paddr_t)(x) & 0x0000000fffffffffUL) +#define PHYS_TO_XKPHYS(x,c) ((paddr_t)(x) | XKPHYS_BASE | ((c) << 59)) +#define IS_XKPHYS(va) (((va) >> 62) == 2) +#define XKPHYS_TO_CCA(x) (((x) >> 59) & 0x07) + +#endif /* _LOCORE */ + +/* + * Exported definitions unique to mips cpu support. + */ + +#if defined(_KERNEL) && !defined(_LOCORE) + +#include +#include +#include +#include +#include +#include + +struct cpu_hwinfo { + uint32_t c0prid; + uint32_t c1prid; + uint32_t clock; /* Hz */ + uint32_t tlbsize; + uint type; + uint32_t l2size; +}; + +/* + * Cache memory configuration. One struct per cache. + */ +struct cache_info { + uint size; /* total cache size */ + uint linesize; /* line size */ + uint setsize; /* set size */ + uint sets; /* number of sets */ +}; + +struct cpu_info { + struct device *ci_dev; /* our device */ + struct cpu_info *ci_self; /* pointer to this structure */ + struct cpu_info *ci_next; /* next cpu */ + struct proc *ci_curproc; + struct user *ci_curprocpaddr; + struct proc *ci_fpuproc; /* pointer to last proc to use FP */ + uint32_t ci_delayconst; + struct cpu_hwinfo + ci_hw; + +#if defined(MULTIPROCESSOR) + struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM]; +#define __HAVE_UVM_PERCPU + struct uvm_pmr_cache ci_uvm; +#endif + + /* cache information and pending flush state */ + uint ci_cacheconfiguration; + uint64_t ci_cachepending_l1i; + struct cache_info + ci_l1inst, + ci_l1data, + ci_l2, + ci_l3; + + /* function pointers for the cache handling routines */ + void (*ci_SyncCache)(struct cpu_info *); + void (*ci_InvalidateICache)(struct cpu_info *, vaddr_t, + size_t); + void (*ci_InvalidateICachePage)(struct cpu_info *, vaddr_t); + void (*ci_SyncICache)(struct cpu_info *); + void (*ci_SyncDCachePage)(struct cpu_info *, vaddr_t, + paddr_t); + void (*ci_HitSyncDCachePage)(struct cpu_info *, vaddr_t, + paddr_t); + void (*ci_HitSyncDCache)(struct cpu_info *, vaddr_t, size_t); + void (*ci_HitInvalidateDCache)(struct cpu_info *, vaddr_t, + size_t); + void (*ci_IOSyncDCache)(struct cpu_info *, vaddr_t, size_t, + int); + + struct schedstate_percpu + ci_schedstate; + int ci_want_resched; /* need_resched() invoked */ + cpuid_t ci_cpuid; /* our CPU ID */ + uint32_t ci_randseed; /* per cpu random seed */ + volatile int ci_ipl; /* software IPL */ + uint32_t ci_softpending; /* pending soft interrupts */ + int ci_clock_started; + volatile int ci_clock_deferred; /* clock interrupt postponed */ + struct clockqueue + ci_queue; + + struct pmap *ci_curpmap; + uint ci_idepth; /* interrupt depth */ + volatile u_long ci_flags; /* flags; see below */ + volatile int ci_ddb; +#define CI_DDB_RUNNING 0 +#define CI_DDB_SHOULDSTOP 1 +#define CI_DDB_STOPPED 2 +#define CI_DDB_ENTERDDB 3 +#define CI_DDB_INDDB 4 + +#ifdef DIAGNOSTIC + int ci_mutex_level; +#endif +#ifdef GPROF + struct gmonparam *ci_gmon; + struct clockintr ci_gmonclock; +#endif + char ci_panicbuf[512]; +}; + +#define CPUF_PRIMARY 0x01 /* CPU is primary CPU */ +#define CPUF_PRESENT 0x02 /* CPU is present */ +#define CPUF_RUNNING 0x04 /* CPU is running */ + +extern struct cpu_info cpu_info_primary; +extern struct cpu_info *cpu_info_list; +#define CPU_INFO_ITERATOR int +#define CPU_INFO_FOREACH(cii, ci) for (cii = 0, ci = cpu_info_list; \ + ci != NULL; ci = ci->ci_next) + +#define CPU_INFO_UNIT(ci) ((ci)->ci_dev ? (ci)->ci_dev->dv_unit : 0) + +#define cpu_idle_enter() do { /* nothing */ } while (0) +#define cpu_idle_leave() do { /* nothing */ } while (0) +extern void (*cpu_idle_cycle_func)(void); +#define cpu_idle_cycle() (*cpu_idle_cycle_func)() + +#ifdef MULTIPROCESSOR +#define getcurcpu() hw_getcurcpu() +#define setcurcpu(ci) hw_setcurcpu(ci) +extern struct cpu_info *get_cpu_info(int); +#define curcpu() getcurcpu() +#define CPU_IS_PRIMARY(ci) ((ci)->ci_flags & CPUF_PRIMARY) +#define CPU_IS_RUNNING(ci) ((ci)->ci_flags & CPUF_RUNNING) +#define cpu_number() (curcpu()->ci_cpuid) + +void cpu_unidle(struct cpu_info *); +void cpu_boot_secondary_processors(void); +#define cpu_boot_secondary(ci) hw_cpu_boot_secondary(ci) +#define cpu_hatch(ci) hw_cpu_hatch(ci) + +vaddr_t alloc_contiguous_pages(size_t); + +#define MIPS64_IPI_NOP 0x00000001 +#define MIPS64_IPI_RENDEZVOUS 0x00000002 +#define MIPS64_IPI_DDB 0x00000004 +#define MIPS64_NIPIS 3 /* must not exceed 32 */ + +void mips64_ipi_init(void); +void mips64_send_ipi(unsigned int, unsigned int); +void smp_rendezvous_cpus(unsigned long, void (*)(void *), void *arg); + +#include +#else +#define MAXCPUS 1 +#define curcpu() (&cpu_info_primary) +#define CPU_IS_PRIMARY(ci) 1 +#define CPU_IS_RUNNING(ci) 1 +#define cpu_number() 0UL +#define cpu_unidle(ci) +#define get_cpu_info(i) (&cpu_info_primary) +#endif + +#define CPU_BUSY_CYCLE() __asm volatile ("" ::: "memory") + +extern void (*md_initclock)(void); +extern void (*md_startclock)(struct cpu_info *); +extern void (*md_triggerclock)(void); +void cp0_calibrate(struct cpu_info *); + +unsigned int cpu_rnd_messybits(void); + +#include + +/* + * Arguments to hardclock encapsulate the previous machine state in + * an opaque clockframe. + */ +#define clockframe trapframe /* Use normal trap frame */ + +#define SR_KSU_USER 0x00000010 +#define CLKF_USERMODE(framep) ((framep)->sr & SR_KSU_USER) +#define CLKF_PC(framep) ((framep)->pc) +#define CLKF_INTR(framep) (curcpu()->ci_idepth > 1) /* XXX */ + +/* + * This is used during profiling to integrate system time. + */ +#define PROC_PC(p) ((p)->p_md.md_regs->pc) +#define PROC_STACK(p) ((p)->p_md.md_regs->sp) + +/* + * Preempt the current process if in interrupt from user mode, + * or after the current trap/syscall if in system mode. + */ +void need_resched(struct cpu_info *); +#define clear_resched(ci) (ci)->ci_want_resched = 0 + +/* + * Give a profiling tick to the current process when the user profiling + * buffer pages are invalid. On MIPS designs, request an ast to send us + * through trap, marking the proc as needing a profiling tick. + */ +#define need_proftick(p) aston(p) + +/* + * Notify the current process (p) that it has a signal pending, + * process as soon as possible. + */ +void signotify(struct proc *); + +#define aston(p) ((p)->p_md.md_astpending = 1) + +#define mips_sync() __asm__ volatile ("sync" ::: "memory") + +#endif /* _KERNEL && !_LOCORE */ + +#ifdef _KERNEL +/* + * Values for the code field in a break instruction. + */ +#define BREAK_INSTR 0x0000000d +#define BREAK_VAL_MASK 0x03ff0000 +#define BREAK_VAL_SHIFT 16 +#define BREAK_KDB_VAL 512 +#define BREAK_SSTEP_VAL 513 +#define BREAK_BRKPT_VAL 514 +#define BREAK_SOVER_VAL 515 +#define BREAK_DDB_VAL 516 +#define BREAK_FPUEMUL_VAL 517 +#define BREAK_KDB (BREAK_INSTR | (BREAK_KDB_VAL << BREAK_VAL_SHIFT)) +#define BREAK_SSTEP (BREAK_INSTR | (BREAK_SSTEP_VAL << BREAK_VAL_SHIFT)) +#define BREAK_BRKPT (BREAK_INSTR | (BREAK_BRKPT_VAL << BREAK_VAL_SHIFT)) +#define BREAK_SOVER (BREAK_INSTR | (BREAK_SOVER_VAL << BREAK_VAL_SHIFT)) +#define BREAK_DDB (BREAK_INSTR | (BREAK_DDB_VAL << BREAK_VAL_SHIFT)) +#define BREAK_FPUEMUL (BREAK_INSTR | (BREAK_FPUEMUL_VAL << BREAK_VAL_SHIFT)) + +#endif /* _KERNEL */ + +/* + * CTL_MACHDEP definitions. + */ +#define CPU_ALLOWAPERTURE 1 /* allow mmap of /dev/xf86 */ + /* 2 formerly: keyboard reset */ + /* 3 formerly: CPU_LIDSUSPEND */ +#define CPU_LIDACTION 4 /* action caused by lid close */ +#define CPU_MAXID 5 /* number of valid machdep ids */ + +#define CTL_MACHDEP_NAMES { \ + { 0, 0 }, \ + { "allowaperture", CTLTYPE_INT }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "lidaction", CTLTYPE_INT }, \ +} + +/* + * MIPS CPU types (cp_imp). + */ +#define MIPS_R2000 0x01 /* MIPS R2000 CPU ISA I */ +#define MIPS_R3000 0x02 /* MIPS R3000 CPU ISA I */ +#define MIPS_R6000 0x03 /* MIPS R6000 CPU ISA II */ +#define MIPS_R4000 0x04 /* MIPS R4000/4400 CPU ISA III */ +#define MIPS_R3LSI 0x05 /* LSI Logic R3000 derivate ISA I */ +#define MIPS_R6000A 0x06 /* MIPS R6000A CPU ISA II */ +#define MIPS_CN50XX 0x06 /* Cavium OCTEON CN50xx MIPS64R2*/ +#define MIPS_R3IDT 0x07 /* IDT R3000 derivate ISA I */ +#define MIPS_R10000 0x09 /* MIPS R10000/T5 CPU ISA IV */ +#define MIPS_R4200 0x0a /* MIPS R4200 CPU (ICE) ISA III */ +#define MIPS_R4300 0x0b /* NEC VR4300 CPU ISA III */ +#define MIPS_R4100 0x0c /* NEC VR41xx CPU MIPS-16 ISA III */ +#define MIPS_R12000 0x0e /* MIPS R12000 ISA IV */ +#define MIPS_R14000 0x0f /* MIPS R14000 ISA IV */ +#define MIPS_R8000 0x10 /* MIPS R8000 Blackbird/TFP ISA IV */ +#define MIPS_R4600 0x20 /* PMCS R4600 Orion ISA III */ +#define MIPS_R4700 0x21 /* PMCS R4700 Orion ISA III */ +#define MIPS_R3TOSH 0x22 /* Toshiba R3000 based CPU ISA I */ +#define MIPS_R5000 0x23 /* MIPS R5000 CPU ISA IV */ +#define MIPS_RM7000 0x27 /* PMCS RM7000 CPU ISA IV */ +#define MIPS_RM52X0 0x28 /* PMCS RM52X0 CPU ISA IV */ +#define MIPS_RM9000 0x34 /* PMCS RM9000 CPU ISA IV */ +#define MIPS_LOONGSON 0x42 /* STC LoongSon CPU ISA III */ +#define MIPS_VR5400 0x54 /* NEC Vr5400 CPU ISA IV+ */ +#define MIPS_LOONGSON2 0x63 /* STC LoongSon2/3 CPU ISA III+ */ +#define MIPS_CN63XX 0x90 /* Cavium OCTEON II CN6[23]xx MIPS64R2 */ +#define MIPS_CN68XX 0x91 /* Cavium OCTEON II CN68xx MIPS64R2 */ +#define MIPS_CN66XX 0x92 /* Cavium OCTEON II CN66xx MIPS64R2 */ +#define MIPS_CN61XX 0x93 /* Cavium OCTEON II CN6[01]xx MIPS64R2 */ +#define MIPS_CN78XX 0x95 /* Cavium OCTEON III CN7[678]xx MIPS64R2 */ +#define MIPS_CN71XX 0x96 /* Cavium OCTEON III CN7[01]xx MIPS64R2 */ +#define MIPS_CN73XX 0x97 /* Cavium OCTEON III CN7[23]xx MIPS64R2 */ + +/* + * MIPS FPU types. Only soft, rest is the same as cpu type. + */ +#define MIPS_SOFT 0x00 /* Software emulation ISA I */ + + +#if defined(_KERNEL) && !defined(_LOCORE) + +extern register_t protosr; +extern int cpu_has_synced_cp0_count; +extern int cpu_has_userlocal; + +#ifdef FPUEMUL +#define CPU_HAS_FPU(ci) ((ci)->ci_hw.c1prid != 0) +#else +#define CPU_HAS_FPU(ci) 1 +#endif + +struct exec_package; +struct user; + +void tlb_asid_wrap(struct cpu_info *); +void tlb_flush(int); +void tlb_flush_addr(vaddr_t); +void tlb_init(unsigned int); +void tlb_set_page_mask(uint32_t); +void tlb_set_pid(u_int); +void tlb_set_wired(uint32_t); +int tlb_update(vaddr_t, register_t); + +void build_trampoline(vaddr_t, vaddr_t); +void cpu_switchto_asm(struct proc *, struct proc *); +int exec_md_map(struct proc *, struct exec_package *); +void savectx(struct user *, int); + +int copyinsn(struct proc *, vaddr_t, uint32_t *); +void enable_fpu(struct proc *); +void save_fpu(void); +int fpe_branch_emulate(struct proc *, struct trapframe *, uint32_t, + vaddr_t); +void MipsSaveCurFPState(struct proc *); +void MipsSaveCurFPState16(struct proc *); +void MipsSwitchFPState(struct proc *, struct trapframe *); +void MipsSwitchFPState16(struct proc *, struct trapframe *); + +void MipsFPTrap(struct trapframe *); +register_t MipsEmulateBranch(struct trapframe *, vaddr_t, uint32_t, uint32_t); + +int classify_insn(uint32_t); +#define INSNCLASS_NEUTRAL 0 +#define INSNCLASS_CALL 1 +#define INSNCLASS_BRANCH 2 + +/* + * Low level access routines to CPU registers + */ + +void setsoftintr0(void); +void clearsoftintr0(void); +void setsoftintr1(void); +void clearsoftintr1(void); +register_t enableintr(void); +register_t disableintr(void); +register_t getsr(void); +register_t setsr(register_t); + +uint32_t cp0_get_cause(void); +u_int cp0_get_count(void); +register_t cp0_get_config(void); +uint32_t cp0_get_config_1(void); +uint32_t cp0_get_config_2(void); +uint32_t cp0_get_config_3(void); +uint32_t cp0_get_config_4(void); +uint32_t cp0_get_pagegrain(void); +register_t cp0_get_prid(void); +void cp0_reset_cause(register_t); +void cp0_set_compare(u_int); +void cp0_set_config(register_t); +void cp0_set_pagegrain(uint32_t); +void cp0_set_trapbase(register_t); +u_int cp1_get_prid(void); + +static inline uint32_t +cp0_get_hwrena(void) +{ + uint32_t value; + __asm__ volatile ("mfc0 %0, $7" : "=r" (value)); + return value; +} + +static inline void +cp0_set_hwrena(uint32_t value) +{ + __asm__ volatile ("mtc0 %0, $7" : : "r" (value)); +} + +static inline void +cp0_set_userlocal(void *value) +{ + __asm__ volatile ( + " .set push\n" + " .set mips64r2\n" + " dmtc0 %0, $4, 2\n" + " .set pop\n" + : : "r" (value)); +} + +static inline u_long +intr_disable(void) +{ + return disableintr(); +} + +static inline void +intr_restore(u_long sr) +{ + setsr(sr); +} + +/* + * Cache routines (may be overridden) + */ + +#ifndef Mips_SyncCache +#define Mips_SyncCache(ci) \ + ((ci)->ci_SyncCache)(ci) +#endif +#ifndef Mips_InvalidateICache +#define Mips_InvalidateICache(ci, va, l) \ + ((ci)->ci_InvalidateICache)(ci, va, l) +#endif +#ifndef Mips_InvalidateICachePage +#define Mips_InvalidateICachePage(ci, va) \ + ((ci)->ci_InvalidateICachePage)(ci, va) +#endif +#ifndef Mips_SyncICache +#define Mips_SyncICache(ci) \ + ((ci)->ci_SyncICache)(ci) +#endif +#ifndef Mips_SyncDCachePage +#define Mips_SyncDCachePage(ci, va, pa) \ + ((ci)->ci_SyncDCachePage)(ci, va, pa) +#endif +#ifndef Mips_HitSyncDCachePage +#define Mips_HitSyncDCachePage(ci, va, pa) \ + ((ci)->ci_HitSyncDCachePage)(ci, va, pa) +#endif +#ifndef Mips_HitSyncDCache +#define Mips_HitSyncDCache(ci, va, l) \ + ((ci)->ci_HitSyncDCache)(ci, va, l) +#endif +#ifndef Mips_HitInvalidateDCache +#define Mips_HitInvalidateDCache(ci, va, l) \ + ((ci)->ci_HitInvalidateDCache)(ci, va, l) +#endif +#ifndef Mips_IOSyncDCache +#define Mips_IOSyncDCache(ci, va, l, h) \ + ((ci)->ci_IOSyncDCache)(ci, va, l, h) +#endif + +#endif /* _KERNEL && !_LOCORE */ +#endif /* !_MIPS64_CPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/cpustate.h b/lib/libc/include/generic-openbsd/mips64/cpustate.h new file mode 100644 index 000000000000..a6ad1d367624 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/cpustate.h @@ -0,0 +1,150 @@ +/* $OpenBSD: cpustate.h,v 1.11 2015/09/27 18:17:08 miod Exp $ */ + +/* + * Copyright (c) 2002-2003 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#define KERN_REG_SIZE (NUMSAVEREGS * REGSZ) +#define KERN_EXC_FRAME_SIZE (CF_SZ + KERN_REG_SIZE + 16) + +#define SAVE_REG(reg, offs, base, bo) \ + REG_S reg, bo + (REGSZ * offs) (base) + +#define RESTORE_REG(reg, offs, base, bo) \ + REG_L reg, bo + (REGSZ * offs) (base) + +/* + * This macro saves the 'scratch' cpu state on stack. + * Macros are generic so no 'special' instructions! + * a0 will have a pointer to the 'frame' on return. + * a1 will have saved STATUS_REG on return. + * a3 will have the exception pc on 'return'. + * No traps, no interrupts if frame = k1 or k0! + * Temp regs are saved with their register number so + * branch emulation etc works properly. + */ +#define SAVE_CPU(frame, bo) \ + SAVE_REG(AT, AST, frame, bo) ;\ + SAVE_REG(v0, V0, frame, bo) ;\ + SAVE_REG(v1, V1, frame, bo) ;\ + SAVE_REG(a0, A0, frame, bo) ;\ + SAVE_REG(a1, A1, frame, bo) ;\ + SAVE_REG(a2, A2, frame, bo) ;\ + SAVE_REG(a3, A3, frame, bo) ;\ + MFC0 a0, COP_0_CAUSE_REG ;\ + MFC0_HAZARD ;\ + SAVE_REG(a4, A4, frame, bo) ;\ + SAVE_REG(a5, A5, frame, bo) ;\ + MFC0 a1, COP_0_STATUS_REG ;\ + MFC0_HAZARD ;\ + SAVE_REG(a6, A6, frame, bo) ;\ + SAVE_REG(a7, A7, frame, bo) ;\ + PRE_MFC0_ADDR_HAZARD ;\ + DMFC0 a2, COP_0_BAD_VADDR ;\ + MFC0_HAZARD ;\ + SAVE_REG(t0, T0, frame, bo) ;\ + SAVE_REG(t1, T1, frame, bo) ;\ + DMFC0 a3, COP_0_EXC_PC ;\ + MFC0_HAZARD ;\ + SAVE_REG(t2, T2, frame, bo) ;\ + SAVE_REG(t3, T3, frame, bo) ;\ + SAVE_REG(t8, T8, frame, bo) ;\ + SAVE_REG(t9, T9, frame, bo) ;\ + SAVE_REG(gp, GP, frame, bo) ;\ + SAVE_REG(ra, RA, frame, bo) ;\ + mflo v0 ;\ + mfhi v1 ;\ + SAVE_REG(v0, MULLO, frame, bo) ;\ + SAVE_REG(v1, MULHI, frame, bo) ;\ + SAVE_REG(a0, CAUSE, frame, bo) ;\ + SAVE_REG(a1, SR, frame, bo) ;\ + SAVE_REG(a2, BADVADDR, frame, bo) ;\ + SAVE_REG(a3, PC, frame, bo) ;\ + SAVE_REG(sp, SP, frame, bo) ;\ + PTR_ADDU a0, frame, bo ;\ + GET_CPU_INFO(v0, v1) ;\ + lw a2, CI_IPL(v0) ;\ + SAVE_REG(a2, CPL, frame, bo) + +/* + * Save 'callee save' registers in frame to aid DDB. + */ +#define SAVE_CPU_SREG(frame, bo) \ + SAVE_REG(s0, S0, frame, bo) ;\ + SAVE_REG(s1, S1, frame, bo) ;\ + SAVE_REG(s2, S2, frame, bo) ;\ + SAVE_REG(s3, S3, frame, bo) ;\ + SAVE_REG(s4, S4, frame, bo) ;\ + SAVE_REG(s5, S5, frame, bo) ;\ + SAVE_REG(s6, S6, frame, bo) ;\ + SAVE_REG(s7, S7, frame, bo) ;\ + SAVE_REG(s8, S8, frame, bo) + +/* + * Restore cpu state. When called a0 = EXC_PC. + */ +#define RESTORE_CPU(frame, bo) \ + RESTORE_REG(t1, SR, frame, bo) ;\ + RESTORE_REG(t2, MULLO, frame, bo) ;\ + RESTORE_REG(t3, MULHI, frame, bo) ;\ + MTC0 t1, COP_0_STATUS_REG ;\ + MTC0_SR_IE_HAZARD ;\ + mtlo t2 ;\ + mthi t3 ;\ + DMTC0 a0, COP_0_EXC_PC ;\ + MTC0_HAZARD ;\ + RESTORE_REG(AT, AST, frame, bo) ;\ + RESTORE_REG(v0, V0, frame, bo) ;\ + RESTORE_REG(v1, V1, frame, bo) ;\ + RESTORE_REG(a0, A0, frame, bo) ;\ + RESTORE_REG(a1, A1, frame, bo) ;\ + RESTORE_REG(a2, A2, frame, bo) ;\ + RESTORE_REG(a3, A3, frame, bo) ;\ + RESTORE_REG(a4, A4, frame, bo) ;\ + RESTORE_REG(a5, A5, frame, bo) ;\ + RESTORE_REG(a6, A6, frame, bo) ;\ + RESTORE_REG(a7, A7, frame, bo) ;\ + RESTORE_REG(t0, T0, frame, bo) ;\ + RESTORE_REG(t1, T1, frame, bo) ;\ + RESTORE_REG(t2, T2, frame, bo) ;\ + RESTORE_REG(t3, T3, frame, bo) ;\ + RESTORE_REG(t8, T8, frame, bo) ;\ + RESTORE_REG(t9, T9, frame, bo) ;\ + RESTORE_REG(gp, GP, frame, bo) ;\ + RESTORE_REG(ra, RA, frame, bo) + +/* + * Restore 'callee save' registers + */ +#define RESTORE_CPU_SREG(frame, bo) \ + RESTORE_REG(s0, S0, frame, bo) ;\ + RESTORE_REG(s1, S1, frame, bo) ;\ + RESTORE_REG(s2, S2, frame, bo) ;\ + RESTORE_REG(s3, S3, frame, bo) ;\ + RESTORE_REG(s4, S4, frame, bo) ;\ + RESTORE_REG(s5, S5, frame, bo) ;\ + RESTORE_REG(s6, S6, frame, bo) ;\ + RESTORE_REG(s7, S7, frame, bo) ;\ + RESTORE_REG(s8, S8, frame, bo) \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/db_machdep.h b/lib/libc/include/generic-openbsd/mips64/db_machdep.h new file mode 100644 index 000000000000..7dec17ccc290 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/db_machdep.h @@ -0,0 +1,76 @@ +/* $OpenBSD: db_machdep.h,v 1.21 2021/08/30 08:11:12 jasper Exp $ */ + +/* + * Copyright (c) 1998-2003 Opsycon AB (www.opsycon.se) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _MIPS64_DB_MACHDEP_H_ +#define _MIPS64_DB_MACHDEP_H_ + +#include +#include +#include + +#define DB_MACHINE_COMMANDS /* We have machine specific commands */ + +typedef struct trapframe db_regs_t; +extern db_regs_t ddb_regs; + +typedef long db_expr_t; + +#define SOFTWARE_SSTEP /* Need software single step */ +#define SOFTWARE_SSTEP_EMUL /* next_instr_address() emulates 100% */ +vaddr_t next_instr_address(vaddr_t, int); +#define BKPT_SIZE (4) +#define BKPT_SET(ins) (BREAK_DDB) +#define DB_VALID_BREAKPOINT(addr) (((addr) & 3) == 0) + +#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BREAK) +#define IS_WATCHPOINT_TRAP(type, code) (0) /* XXX mips3 watchpoint */ + +#define PC_REGS(regs) ((vaddr_t)(regs)->pc) +#define SET_PC_REGS(regs, value) (regs)->pc = (register_t)(value) + +/* + * Test of instructions to see class. + */ +#define inst_branch(i) (classify_insn(i) == INSNCLASS_BRANCH) +#define inst_trap_return(i) ((i) & 0) +#define inst_call(i) (classify_insn(i) == INSNCLASS_CALL) +#define inst_return(i) ((i) == 0x03e00008) + +void db_machine_init(void); + +int db_enter_ddb(void); +void db_startcpu(int); +void db_stopcpu(int); + +int dbmd_print_insn(uint32_t, vaddr_t, int (*)(const char *, ...)); + +#define DDB_STATE_NOT_RUNNING 0 +#define DDB_STATE_RUNNING 1 +#define DDB_STATE_EXITING 2 + +#endif /* !_MIPS64_DB_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/elf.h b/lib/libc/include/generic-openbsd/mips64/elf.h new file mode 100644 index 000000000000..1cd8fda26a98 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/elf.h @@ -0,0 +1,7 @@ +/* $OpenBSD: elf.h,v 1.1 2024/07/14 09:48:48 jca Exp $ */ + +/* + * This file is in the public domain. + */ + +/* Nothing for now */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/endian.h b/lib/libc/include/generic-openbsd/mips64/endian.h new file mode 100644 index 000000000000..178466dc551c --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/endian.h @@ -0,0 +1,49 @@ +/* $OpenBSD: endian.h,v 1.9 2014/07/12 16:25:08 guenther Exp $ */ + +/* + * Copyright (c) 2001-2002 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _MIPS64_ENDIAN_H_ +#define _MIPS64_ENDIAN_H_ + +#if defined(__MIPSEL__) +#define _BYTE_ORDER _LITTLE_ENDIAN +#endif +#if defined(__MIPSEB__) +#define _BYTE_ORDER _BIG_ENDIAN +#endif + +#if !defined(_BYTE_ORDER) +#error "__MIPSEL__ or __MIPSEB__ must be defined to define BYTE_ORDER!!!" +#endif + +#define __STRICT_ALIGNMENT + +#ifndef __FROM_SYS__ENDIAN +#include +#endif + +#endif /* _MIPS64_ENDIAN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/exec.h b/lib/libc/include/generic-openbsd/mips64/exec.h new file mode 100644 index 000000000000..f946e5fc6843 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/exec.h @@ -0,0 +1,137 @@ +/* $OpenBSD: exec.h,v 1.10 2022/10/28 15:07:25 kettenis Exp $ */ + +/* + * Copyright (c) 1996-2004 Per Fogelstrom, Opsycon AB + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _MIPS64_EXEC_H_ +#define _MIPS64_EXEC_H_ + +#define __LDPGSZ 16384 + +#define ARCH_ELFSIZE 64 +#define ELF_TARG_CLASS ELFCLASS64 + +#if defined(__MIPSEB__) +#define ELF_TARG_DATA ELFDATA2MSB +#else +#define ELF_TARG_DATA ELFDATA2LSB +#endif +#define ELF_TARG_MACH EM_MIPS + +/* Information taken from MIPS ABI supplement */ + +/* Architecture dependent Segment types - p_type */ +#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */ + +/* Architecture dependent d_tag field for Elf32_Dyn. */ +#define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime Linker Interface ID */ +#define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */ +#define DT_MIPS_ICHECKSUM 0x70000003 /* Cksum of ext. str. and com. sizes */ +#define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */ +#define DT_MIPS_FLAGS 0x70000005 /* Flags */ +#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Segment base address */ +#define DT_MIPS_CONFLICT 0x70000008 /* Adr of .conflict section */ +#define DT_MIPS_LIBLIST 0x70000009 /* Address of .liblist section */ +#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local .GOT entries */ +#define DT_MIPS_CONFLICTNO 0x7000000b /* Number of .conflict entries */ +#define DT_MIPS_LIBLISTNO 0x70000010 /* Number of .liblist entries */ +#define DT_MIPS_SYMTABNO 0x70000011 /* Number of .dynsym entries */ +#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */ +#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in .dynsym */ +#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */ +#define DT_MIPS_RLD_MAP 0x70000016 /* Address of debug map pointer */ +#define DT_MIPS_RLD_MAP_REL 0x70000035 /* Relative address of debug map ptr */ + +#define DT_PROCNUM (DT_MIPS_RLD_MAP_REL - DT_LOPROC + 1) + +/* + * Legal values for e_flags field of Elf32_Ehdr. + */ +#define EF_MIPS_NOREORDER 0x00000001 /* .noreorder was used */ +#define EF_MIPS_PIC 0x00000002 /* Contains PIC code */ +#define EF_MIPS_CPIC 0x00000004 /* Uses PIC calling sequence */ +#define EF_MIPS_ABI2 0x00000020 /* -n32 on Irix 6 */ +#define EF_MIPS_32BITMODE 0x00000100 /* 64 bit in 32 bit mode... */ +#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */ +#define E_MIPS_ARCH_1 0x00000000 +#define E_MIPS_ARCH_2 0x10000000 +#define E_MIPS_ARCH_3 0x20000000 +#define E_MIPS_ARCH_4 0x30000000 +#define EF_MIPS_ABI 0x0000f000 /* ABI level */ +#define E_MIPS_ABI_NONE 0x00000000 /* ABI level not set */ +#define E_MIPS_ABI_O32 0x00001000 +#define E_MIPS_ABI_O64 0x00002000 +#define E_MIPS_ABI_EABI32 0x00004000 +#define E_MIPS_ABI_EABI64 0x00004000 + +/* + * Mips special sections. + */ +#define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */ +#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */ +#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */ + +/* + * Legal values for sh_type field of Elf32_Shdr. + */ +#define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link */ +#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols */ +#define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes */ +#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */ +#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information */ +#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */ + +/* + * Legal values for sh_flags field of Elf32_Shdr. + */ +#define SHF_MIPS_GPREL 0x10000000 /* Must be part of global data area */ + +#if 0 +/* + * Entries found in sections of type SHT_MIPS_GPTAB. + */ +typedef union { + struct { + Elf32_Word gt_current_g_value; /* -G val used in compilation */ + Elf32_Word gt_unused; /* Not used */ + } gt_header; /* First entry in section */ + struct { + Elf32_Word gt_g_value; /* If this val were used for -G */ + Elf32_Word gt_bytes; /* This many bytes would be used */ + } gt_entry; /* Subsequent entries in section */ +} Elf32_gptab; + +/* + * Entry found in sections of type SHT_MIPS_REGINFO. + */ +typedef struct { + Elf32_Word ri_gprmask; /* General registers used */ + Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */ + Elf32_Sword ri_gp_value; /* $gp register value */ +} Elf32_RegInfo; +#endif + +#endif /* !_MIPS64_EXEC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/fenv.h b/lib/libc/include/generic-openbsd/mips64/fenv.h new file mode 100644 index 000000000000..6059d900666e --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/fenv.h @@ -0,0 +1,94 @@ +/* $OpenBSD: fenv.h,v 1.3 2011/05/25 21:46:49 martynas Exp $ */ + +/* + * Copyright (c) 2011 Martynas Venckus + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MIPS64_FENV_H_ +#define _MIPS64_FENV_H_ + +/* + * Each symbol representing a floating point exception expands to an integer + * constant expression with values, such that bitwise-inclusive ORs of _all + * combinations_ of the constants result in distinct values. + * + * We use such values that allow direct bitwise operations on FPU registers. + */ +#define FE_INEXACT 0x04 +#define FE_UNDERFLOW 0x08 +#define FE_OVERFLOW 0x10 +#define FE_DIVBYZERO 0x20 +#define FE_INVALID 0x40 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * exception constants defined above. + */ +#define FE_ALL_EXCEPT (FE_INEXACT | FE_UNDERFLOW | FE_OVERFLOW | \ + FE_DIVBYZERO | FE_INVALID) +#define _MASK_SHIFT 5 + +/* + * Each symbol representing the rounding direction, expands to an integer + * constant expression whose value is distinct non-negative value. + * + * We use such values that allow direct bitwise operations on FPU registers. + */ +#define FE_TONEAREST 0x0 +#define FE_TOWARDZERO 0x1 +#define FE_UPWARD 0x2 +#define FE_DOWNWARD 0x3 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * rounding direction constants defined above. + */ +#define _ROUND_MASK (FE_TONEAREST | FE_TOWARDZERO | FE_UPWARD | \ + FE_DOWNWARD) + +/* + * fenv_t represents the entire floating-point environment. + */ +typedef unsigned int fenv_t; + +/* + * The following constant represents the default floating-point environment + * (that is, the one installed at program startup) and has type pointer to + * const-qualified fenv_t. + * + * It can be used as an argument to the functions within the header + * that manage the floating-point environment, namely fesetenv() and + * feupdateenv(). + */ +__BEGIN_DECLS +extern fenv_t __fe_dfl_env; +__END_DECLS +#define FE_DFL_ENV ((const fenv_t *)&__fe_dfl_env) + +/* + * fexcept_t represents the floating-point status flags collectively, including + * any status the implementation associates with the flags. + * + * A floating-point status flag is a system variable whose value is set (but + * never cleared) when a floating-point exception is raised, which occurs as a + * side effect of exceptional floating-point arithmetic to provide auxiliary + * information. + * + * A floating-point control mode is a system variable whose value may be set by + * the user to affect the subsequent behavior of floating-point arithmetic. + */ +typedef unsigned int fexcept_t; + +#endif /* !_MIPS64_FENV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/fpu.h b/lib/libc/include/generic-openbsd/mips64/fpu.h new file mode 100644 index 000000000000..d670aed7bd56 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/fpu.h @@ -0,0 +1,73 @@ +/* $OpenBSD: fpu.h,v 1.2 2012/12/04 05:00:40 deraadt Exp $ */ + +/* + * Copyright (c) 2010 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Layout of the floating-point control/status register (FCR31) + */ + +/* flush denormalized results to zero instead of causing FPCSR_C_E */ +#define FPCSR_FS 0x01000000 + +/* compare condition bits: one bit for MIPS I/II/III, eight bits for MIPS IV */ +#define FPCSR_CONDBIT(c) ((c) == 0 ? 23 : 24 + (c)) +#define FPCSR_CONDVAL(c) (1U << FPCSR_CONDBIT(c)) + +/* cause bits */ +#define FPCSR_C_E 0x00020000 /* unimplemented operation */ +#define FPCSR_C_V 0x00010000 /* invalid operation */ +#define FPCSR_C_Z 0x00008000 /* division by zero */ +#define FPCSR_C_O 0x00004000 /* overflow */ +#define FPCSR_C_U 0x00002000 /* underflow */ +#define FPCSR_C_I 0x00001000 /* inexact */ + +/* enable bits */ +#define FPCSR_E_V 0x00000800 /* invalid operation */ +#define FPCSR_E_Z 0x00000400 /* division by zero */ +#define FPCSR_E_O 0x00000200 /* overflow */ +#define FPCSR_E_U 0x00000100 /* underflow */ +#define FPCSR_E_I 0x00000080 /* inexact */ + +/* flags bits */ +#define FPCSR_F_V 0x00000040 /* invalid operation */ +#define FPCSR_F_Z 0x00000020 /* division by zero */ +#define FPCSR_F_O 0x00000010 /* overflow */ +#define FPCSR_F_U 0x00000008 /* underflow */ +#define FPCSR_F_I 0x00000004 /* inexact */ + +#define FPCSR_C_MASK 0x0003f000 +#define FPCSR_C_SHIFT 12 +#define FPCSR_E_MASK 0x00000f80 +#define FPCSR_E_SHIFT 7 +#define FPCSR_F_MASK 0x0000007c +#define FPCSR_F_SHIFT 2 +#define FPCSR_RM_MASK 0x00000003 /* rounding mode */ + +#ifndef _KERNEL + +/* + * IRIX-compatible interfaces allowing userland to control the state + * of the floating-point control/status register. These are intended + * to let userland control the state of the FS bit. + */ +#include + +__BEGIN_DECLS +int get_fpc_csr(void); +int set_fpc_csr(int); +__END_DECLS +#endif /* _KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/frame.h b/lib/libc/include/generic-openbsd/mips64/frame.h new file mode 100644 index 000000000000..233e911c36a9 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/frame.h @@ -0,0 +1,114 @@ +/* $OpenBSD: frame.h,v 1.8 2021/04/29 12:49:19 visa Exp $ */ + +/* + * Copyright (c) 1998-2003 Opsycon AB (www.opsycon.se) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#ifndef _MIPS64_FRAME_H_ +#define _MIPS64_FRAME_H_ + +/* + * The layout of this *must* match with regnum.h or bad things + * will happen. libc setjmp/longjmp depends on this as well. + */ +struct trapframe { + register_t zero; + register_t ast; + register_t v0; + register_t v1; + register_t a0; + register_t a1; + register_t a2; + register_t a3; + register_t a4; /* ta0 */ + register_t a5; /* ta1 */ + register_t a6; /* ta2 */ + register_t a7; /* ta3 */ + register_t t0; + register_t t1; + register_t t2; + register_t t3; + register_t s0; + register_t s1; + register_t s2; + register_t s3; + register_t s4; + register_t s5; + register_t s6; + register_t s7; + register_t t8; + register_t t9; + register_t k0; + register_t k1; + register_t gp; + register_t sp; + register_t s8; + register_t ra; + register_t sr; + register_t mullo; + register_t mulhi; + register_t badvaddr; + register_t cause; + register_t pc; + register_t ic; /* unused, was RM7000 ICR */ + register_t ipl; + +/* From here and on, only saved user processes. */ + + f_register_t f0; + f_register_t f1; + f_register_t f2; + f_register_t f3; + f_register_t f4; + f_register_t f5; + f_register_t f6; + f_register_t f7; + f_register_t f8; + f_register_t f9; + f_register_t f10; + f_register_t f11; + f_register_t f12; + f_register_t f13; + f_register_t f14; + f_register_t f15; + f_register_t f16; + f_register_t f17; + f_register_t f18; + f_register_t f19; + f_register_t f20; + f_register_t f21; + f_register_t f22; + f_register_t f23; + f_register_t f24; + f_register_t f25; + f_register_t f26; + f_register_t f27; + f_register_t f28; + f_register_t f29; + f_register_t f30; + f_register_t f31; + register_t fsr; +}; + +#endif /* !_MIPS64_FRAME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/ieee.h b/lib/libc/include/generic-openbsd/mips64/ieee.h new file mode 100644 index 000000000000..d96b3479fbec --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/ieee.h @@ -0,0 +1,169 @@ +/* $OpenBSD: ieee.h,v 1.4 2010/01/23 19:11:21 miod Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ieee.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * ieee.h defines the machine-dependent layout of the machine's IEEE + * floating point. It does *not* define (yet?) any of the rounding + * mode bits, exceptions, and so forth. + */ + +/* + * Define the number of bits in each fraction and exponent. + * + * k k+1 + * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented + * + * (-exp_bias+1) + * as fractions that look like 0.fffff x 2 . This means that + * + * -126 + * the number 0.10000 x 2 , for instance, is the same as the normalized + * + * -127 -128 + * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero + * + * -129 + * in the fraction; to represent 2 , we need two, and so on. This + * + * (-exp_bias-fracbits+1) + * implies that the smallest denormalized number is 2 + * + * for whichever format we are talking about: for single precision, for + * + * -126 -149 + * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and + * + * -149 == -127 - 23 + 1. + */ +#define SNG_EXPBITS 8 +#define SNG_FRACBITS 23 + +#define DBL_EXPBITS 11 +#define DBL_FRACHBITS 20 +#define DBL_FRACLBITS 32 +#define DBL_FRACBITS 52 + +#define EXT_EXPBITS 15 +#define EXT_FRACHBITS 16 +#define EXT_FRACHMBITS 32 +#define EXT_FRACLMBITS 32 +#define EXT_FRACLBITS 32 +#define EXT_FRACBITS 112 + +#define EXT_IMPLICIT_NBIT + +#define EXT_TO_ARRAY32(p, a) do { \ + (a)[0] = (uint32_t)(p)->ext_fracl; \ + (a)[1] = (uint32_t)(p)->ext_fraclm; \ + (a)[2] = (uint32_t)(p)->ext_frachm; \ + (a)[3] = (uint32_t)(p)->ext_frach; \ +} while(0) + +struct ieee_single { +#ifdef __MIPSEB__ + u_int sng_sign:1; + u_int sng_exp:8; + u_int sng_frac:23; +#else + u_int sng_frac:23; + u_int sng_exp:8; + u_int sng_sign:1; +#endif +}; + +struct ieee_double { +#ifdef __MIPSEB__ + u_int dbl_sign:1; + u_int dbl_exp:11; + u_int dbl_frach:20; + u_int dbl_fracl; +#else + u_int dbl_fracl; + u_int dbl_frach:20; + u_int dbl_exp:11; + u_int dbl_sign:1; +#endif +}; + +struct ieee_ext { +#ifdef __MIPSEB__ + u_int ext_sign:1; + u_int ext_exp:15; + u_int ext_frach:16; + u_int ext_frachm; + u_int ext_fraclm; + u_int ext_fracl; +#else + u_int ext_fracl; + u_int ext_fraclm; + u_int ext_frachm; + u_int ext_frach:16; + u_int ext_exp:15; + u_int ext_sign:1; +#endif +}; + +/* + * Floats whose exponent is in [1..INFNAN) (of whatever type) are + * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. + * Floats whose exponent is zero are either zero (iff all fraction + * bits are zero) or subnormal values. + * + * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its + * high fraction; if the bit is set, it is a `quiet NaN'. + */ +#define SNG_EXP_INFNAN 255 +#define DBL_EXP_INFNAN 2047 +#define EXT_EXP_INFNAN 32767 + +#if 0 +#define SNG_QUIETNAN (1 << 22) +#define DBL_QUIETNAN (1 << 19) +#define EXT_QUIETNAN (1 << 15) +#endif + +/* + * Exponent biases. + */ +#define SNG_EXP_BIAS 127 +#define DBL_EXP_BIAS 1023 +#define EXT_EXP_BIAS 16383 \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/ieeefp.h b/lib/libc/include/generic-openbsd/mips64/ieeefp.h new file mode 100644 index 000000000000..e3521f45cd0f --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/ieeefp.h @@ -0,0 +1,46 @@ +/* $OpenBSD: ieeefp.h,v 1.4 2011/03/23 16:54:36 pirofti Exp $ */ + +/* + * Written by J.T. Conklin, Apr 11, 1995 + * Public domain. + */ + +#ifndef _MIPS64_IEEEFP_H_ +#define _MIPS64_IEEEFP_H_ + +typedef int fp_except; +#define FP_X_IMP 0x01 /* imprecise (loss of precision) */ +#define FP_X_UFL 0x02 /* underflow exception */ +#define FP_X_OFL 0x04 /* overflow exception */ +#define FP_X_DZ 0x08 /* divide-by-zero exception */ +#define FP_X_INV 0x10 /* invalid operation exception */ + +typedef enum { + FP_RN=0, /* round to nearest representable number */ + FP_RZ=1, /* round to zero (truncate) */ + FP_RP=2, /* round toward positive infinity */ + FP_RM=3 /* round toward negative infinity */ +} fp_rnd; + +#ifdef _KERNEL + +/* + * Defines for the floating-point completion/emulation code. + */ + +#include +#include +#include +#include + +#define float_raise(bits) \ + do { curproc->p_md.md_regs->fsr |= (bits) << FPCSR_C_SHIFT; } while (0) +#define float_set_inexact() float_raise(FP_X_IMP) +#define float_set_invalid() float_raise(FP_X_INV) + +#define float_get_round(csr) (csr & FPCSR_RM_MASK) +#define fpgetround() float_get_round(curproc->p_md.md_regs->fsr) + +#endif + +#endif /* !_MIPS64_IEEEFP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/kcore.h b/lib/libc/include/generic-openbsd/mips64/kcore.h new file mode 100644 index 000000000000..5a69401214af --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/kcore.h @@ -0,0 +1,40 @@ +/* $OpenBSD: kcore.h,v 1.3 2023/01/04 10:59:34 jsg Exp $ */ +/* $NetBSD: kcore.h,v 1.1 1996/03/10 21:55:18 leo Exp $ */ + +/* + * Copyright (c) 1996 Leo Weppelman. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MIPS64_KCORE_H_ +#define _MIPS64_KCORE_H_ + +#define NPHYS_RAM_SEGS 8 + +typedef struct cpu_kcore_hdr { + paddr_t kernel_pa; /* Phys. address of kernel VA 0 */ + int mmutype; + phys_ram_seg_t ram_segs[NPHYS_RAM_SEGS]; +} cpu_kcore_hdr_t; + +#endif /* !_MIPS64_KCORE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/limits.h b/lib/libc/include/generic-openbsd/mips64/limits.h new file mode 100644 index 000000000000..398deda85270 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/limits.h @@ -0,0 +1,53 @@ +/* $OpenBSD: limits.h,v 1.8 2015/04/30 13:42:08 millert Exp $ */ + +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)limits.h 8.3 (Berkeley) 1/4/94 + */ + +#ifndef _MIPS64_LIMITS_H_ +#define _MIPS64_LIMITS_H_ + +#include + +#if __POSIX_VISIBLE || __XPG_VISIBLE +#define SSIZE_MAX LONG_MAX /* max value for a ssize_t */ +#endif + +#if __BSD_VISIBLE +#define SIZE_T_MAX ULONG_MAX /* max value for a size_t (historic) */ + +/* Quads and longs are the same on mips64 */ +#define UQUAD_MAX (ULONG_MAX) /* max value for a uquad_t */ +#define QUAD_MAX (LONG_MAX) /* max value for a quad_t */ +#define QUAD_MIN (LONG_MIN) /* min value for a quad_t */ + +#endif /* __BSD_VISIBLE */ + +#endif /* !_MIPS64_LIMITS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/loongson2.h b/lib/libc/include/generic-openbsd/mips64/loongson2.h new file mode 100644 index 000000000000..ecfab5502497 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/loongson2.h @@ -0,0 +1,65 @@ +/* $OpenBSD: loongson2.h,v 1.4 2013/01/16 20:28:06 miod Exp $ */ + +/* + * Copyright (c) 2009 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MIPS64_LOONGSON2_H_ +#define _MIPS64_LOONGSON2_H_ + +/* + * Loongson 2E/2F specific defines + */ + +/* + * Address Window registers physical addresses + * + * The Loongson 2F processor has an AXI crossbar with four possible bus + * masters, each one having four programmable address windows. + * + * Each window is defined with three 64-bit registers: + * - a base address register, defining the address in the master address + * space (base register). + * - an address mask register, defining which address bits are valid in this + * window. A given address matches a window if (addr & mask) == base. + * - the location of the window base in the target, as well at the target + * number itself (mmap register). The lower 20 bits of the address are + * forced as zeroes regardless of their value in this register. + * The translated address is thus (addr & ~mask) | (mmap & ~0xfffff). + */ + +#define LOONGSON_AWR_BASE_ADDRESS 0x3ff00000 + +#define LOONGSON_AWR_BASE(master, window) \ + (LOONGSON_AWR_BASE_ADDRESS + (window) * 0x08 + (master) * 0x60 + 0x00) +#define LOONGSON_AWR_SIZE(master, window) \ + (LOONGSON_AWR_BASE_ADDRESS + (window) * 0x08 + (master) * 0x60 + 0x20) +#define LOONGSON_AWR_MMAP(master, window) \ + (LOONGSON_AWR_BASE_ADDRESS + (window) * 0x08 + (master) * 0x60 + 0x40) + +/* + * Bits in the diagnostic register + */ + +#define COP_0_DIAG_ITLB_CLEAR 0x04 +#define COP_0_DIAG_BTB_CLEAR 0x02 +#define COP_0_DIAG_RAS_DISABLE 0x01 + +#if defined(_KERNEL) && !defined(_LOCORE) +int loongson2f_cpuspeed(int *); +void loongson2f_setperf(int); +#endif + +#endif /* _MIPS64_LOONGSON2_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/loongson3.h b/lib/libc/include/generic-openbsd/mips64/loongson3.h new file mode 100644 index 000000000000..8b8633e3a428 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/loongson3.h @@ -0,0 +1,108 @@ +/* $OpenBSD: loongson3.h,v 1.3 2017/05/10 16:04:21 visa Exp $ */ + +/* + * Copyright (c) 2016 Visa Hankala + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MIPS64_LOONGSON3_H_ +#define _MIPS64_LOONGSON3_H_ + +/* + * Definitions for Loongson 3A. + */ + +#define LS3_CFG_BASE(node) (0x100000004000ull*(node) + 0x3ff00000) +#define LS3_MEM_BASE(node) (0x100000000000ull*(node)) + +#define LS3_IPI_BASE(n, c) (LS3_CFG_BASE(n) + 0x1000 + 0x100*(c)) +#define LS3_IPI_ISR 0x00 +#define LS3_IPI_IMR 0x04 +#define LS3_IPI_SET 0x08 +#define LS3_IPI_CLEAR 0x0c +#define LS3_IPI_MBOX0 0x20 +#define LS3_IPI_MBOX1 0x28 +#define LS3_IPI_MBOX2 0x30 +#define LS3_IPI_MBOX3 0x38 + +static inline uint32_t +loongson3_get_cpuid(void) +{ + uint32_t tmp; + + asm volatile ( + " .set push\n" + " .set mips64\n" + " mfc0 %0, $15, 1\n" /* EBase */ + " .set pop\n" + : "=r" (tmp)); + + return tmp & 0xf; +} + +#define LS3_COREID(cpuid) ((cpuid) & 3) +#define LS3_NODEID(cpuid) ((cpuid) >> 2) + +/* + * Interrupt router registers + */ + +#define LS3_IRT_ENTRY(node, irq) (LS3_CFG_BASE(node) + 0x1400 + (irq)) +#define LS3_IRT_INTISR(node) (LS3_CFG_BASE(node) + 0x1420) +#define LS3_IRT_INTEN(node) (LS3_CFG_BASE(node) + 0x1424) +#define LS3_IRT_INTENSET(node) (LS3_CFG_BASE(node) + 0x1428) +#define LS3_IRT_INTENCLR(node) (LS3_CFG_BASE(node) + 0x142c) +#define LS3_IRT_INTISR_CORE(node, cpu) (LS3_CFG_BASE(node) + 0x1440 + (cpu)*8) + +/* sys int 0-3 */ +#define LS3_IRT_ENTRY_INT(node, x) LS3_IRT_ENTRY((node), (x)) +/* PCI int 0-3 */ +#define LS3_IRT_ENTRY_PCI(node, x) LS3_IRT_ENTRY((node), 0x04+(x)) +/* LPC int */ +#define LS3_IRT_ENTRY_LPC(node) LS3_IRT_ENTRY((node), 0x0a) +/* HT0 int 0-7 */ +#define LS3_IRT_ENTRY_HT0(node, x) LS3_IRT_ENTRY((node), 0x10+(x)) +/* HT1 int 0-7 */ +#define LS3_IRT_ENTRY_HT1(node, x) LS3_IRT_ENTRY((node), 0x18+(x)) + +#define LS3_IRT_ROUTE(core, intr) ((0x01 << (core)) | (0x10 << (intr))) + +#define LS3_IRQ_INT(x) (x) /* sys int 0-3 */ +#define LS3_IRQ_PCI(x) ((x) + 0x04) /* PCI int 0-3 */ +#define LS3_IRQ_LPC 0x0a /* LPC int */ +#define LS3_IRQ_HT0(x) ((x) + 0x10) /* HT0 int 0-7 */ +#define LS3_IRQ_HT1(x) ((x) + 0x18) /* HT1 int 0-7 */ +#define LS3_IRQ_NUM 32 + +#define LS3_IRQ_IS_HT(irq) ((irq) >= 0x10) + +#define LS3_IRQ_HT_MASK 0xffff0000u + +/* + * Number of HyperTransport interrupt vectors. In reality, each HT interface + * has 256 vectors, but the interrupt code uses only a subset of them. + */ +#define LS3_HT_IRQ_NUM 32 + +/* + * HyperTransport registers + */ + +#define LS3_HT1_MEM_BASE(n) (LS3_MEM_BASE(n)+0x00000e0000000000ull) +#define LS3_HT1_CFG_BASE(n) (LS3_MEM_BASE(n)+0x00000efdfb000000ull) + +#define LS3_HT_ISR_OFFSET(x) (0x80 + (x) * 4) +#define LS3_HT_IMR_OFFSET(x) (0xa0 + (x) * 4) + +#endif /* _MIPS64_LOONGSON3_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/memconf.h b/lib/libc/include/generic-openbsd/mips64/memconf.h new file mode 100644 index 000000000000..208a60d9c5e3 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/memconf.h @@ -0,0 +1,48 @@ +/* $OpenBSD: memconf.h,v 1.7 2011/05/30 22:25:21 oga Exp $ */ + +/* + * Copyright (c) 1996 Per Fogelstrom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Memory config list used by pmap_bootstrap. + */ + +#ifndef _MIPS64_MEMCONF_H_ +#define _MIPS64_MEMCONF_H_ + +struct phys_mem_desc { + uint64_t mem_first_page; + uint64_t mem_last_page; +}; + +#ifdef _KERNEL +#ifndef MAXMEMSEGS +#define MAXMEMSEGS 16 +#endif +extern struct phys_mem_desc mem_layout[]; +int memrange_register(uint64_t, uint64_t, uint64_t); +#endif + +#endif /* !_MIPS64_MEMCONF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/mips_cpu.h b/lib/libc/include/generic-openbsd/mips64/mips_cpu.h new file mode 100644 index 000000000000..02b7f62d4894 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/mips_cpu.h @@ -0,0 +1,282 @@ +/* $OpenBSD: mips_cpu.h,v 1.11 2022/12/11 05:07:25 visa Exp $ */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell and Rick Macklem. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Copyright (C) 1989 Digital Equipment Corporation. + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies. + * Digital Equipment Corporation makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * from: @(#)cpu.h 8.4 (Berkeley) 1/4/94 + */ + +#ifndef _MIPS64_CPUREGS_H_ +#define _MIPS64_CPUREGS_H_ + +#if defined(_KERNEL) || defined(_STANDALONE) + +/* + * Status register. + */ + +#define SR_COP_USABILITY 0x30000000 /* CP0 and CP1 only */ +#define SR_COP_0_BIT 0x10000000 +#define SR_COP_1_BIT 0x20000000 +#define SR_COP_2_BIT 0x40000000 +#define SR_RP 0x08000000 +#define SR_FR_32 0x04000000 +#define SR_RE 0x02000000 +#define SR_DSD 0x01000000 /* Only on R12000 */ +#define SR_BOOT_EXC_VEC 0x00400000 +#define SR_TLB_SHUTDOWN 0x00200000 +#define SR_SOFT_RESET 0x00100000 +#define SR_DIAG_CH 0x00040000 +#define SR_DIAG_CE 0x00020000 +#define SR_DIAG_DE 0x00010000 +#define SR_KX 0x00000080 +#define SR_SX 0x00000040 +#define SR_UX 0x00000020 +#define SR_ERL 0x00000004 +#define SR_EXL 0x00000002 +#define SR_INT_ENAB 0x00000001 + +#define SOFT_INT_MASK_0 0x00000100 +#define SOFT_INT_MASK_1 0x00000200 +#define SR_INT_MASK_0 0x00000400 +#define SR_INT_MASK_1 0x00000800 +#define SR_INT_MASK_2 0x00001000 +#define SR_INT_MASK_3 0x00002000 +#define SR_INT_MASK_4 0x00004000 +#define SR_INT_MASK_5 0x00008000 + +#define SR_XX 0x80000000 +#define SR_KSU_MASK 0x00000018 +#define SR_KSU_SUPER 0x00000008 +#define SR_KSU_KERNEL 0x00000000 +#define SR_INT_MASK 0x0000ff00 +/* SR_KSU_USER is in for CLKF_USERMODE() */ +#ifndef SR_KSU_USER +#define SR_KSU_USER 0x00000010 +#endif + +#define SOFT_INT_MASK (SOFT_INT_MASK_0 | SOFT_INT_MASK_1) + +/* + * Cause register. + */ + +#define CR_BR_DELAY 0x80000000 +#define CR_BR_DELAY_SHIFT 31 +#define CR_EXC_CODE 0x0000007c +#define CR_EXC_CODE_SHIFT 2 +#define CR_COP_ERR 0x30000000 +#define CR_COP1_ERR 0x10000000 +#define CR_COP2_ERR 0x20000000 +#define CR_COP3_ERR 0x20000000 +#define CR_INT_SOFT0 0x00000100 +#define CR_INT_SOFT1 0x00000200 +#define CR_INT_0 0x00000400 +#define CR_INT_1 0x00000800 +#define CR_INT_2 0x00001000 +#define CR_INT_3 0x00002000 +#define CR_INT_4 0x00004000 +#define CR_INT_5 0x00008000 + +#define CR_INT_MASK 0x003fff00 + +/* + * Config register. + */ + +#define CFGR_CCA_MASK 0x00000007 +#define CFGR_CU 0x00000008 +#define CFGR_ICE 0x0000000200000000 +#define CFGR_SMM 0x0000000400000000 + +/* + * Location of exception vectors. + */ + +#define RESET_EXC_VEC (CKSEG1_BASE + 0x1fc00000) +#define TLB_MISS_EXC_VEC (CKSEG1_BASE + 0x00000000) +#define XTLB_MISS_EXC_VEC (CKSEG1_BASE + 0x00000080) +#define CACHE_ERR_EXC_VEC (CKSEG1_BASE + 0x00000100) +#define GEN_EXC_VEC (CKSEG1_BASE + 0x00000180) + +/* + * Coprocessor 0 registers + */ + +/* Common subset */ +#define COP_0_COUNT $9 +#define COP_0_TLB_HI $10 +#define COP_0_STATUS_REG $12 +#define COP_0_CAUSE_REG $13 +#define COP_0_EXC_PC $14 +#define COP_0_PRID $15 +#define COP_0_CONFIG $16 + +/* MIPS64 release 2 */ +#define COP_0_USERLOCAL $4, 2 +#define COP_0_TLB_PG_GRAIN $5, 1 +#define COP_0_EBASE $15, 1 + +/* R4000/5000/10000 */ +#define COP_0_TLB_INDEX $0 +#define COP_0_TLB_RANDOM $1 +#define COP_0_TLB_LO0 $2 +#define COP_0_TLB_LO1 $3 +#define COP_0_TLB_CONTEXT $4 +#define COP_0_TLB_PG_MASK $5 +#define COP_0_TLB_WIRED $6 +#define COP_0_BAD_VADDR $8 +#define COP_0_COMPARE $11 +#define COP_0_LLADDR $17 +#define COP_0_WATCH_LO $18 +#define COP_0_WATCH_HI $19 +#define COP_0_TLB_XCONTEXT $20 +#define COP_0_ECC $26 +#define COP_0_CACHE_ERR $27 +#define COP_0_TAG_LO $28 +#define COP_0_TAG_HI $29 +#define COP_0_ERROR_PC $30 + +/* Loongson-2 specific */ +#define COP_0_DIAG $22 + +/* Octeon specific */ +#define COP_0_CVMCTL $9, 7 +#define COP_0_CVMMEMCTL $11, 7 + +/* + * COP_0_COUNT speed divider. + */ +#if defined(CPU_OCTEON) +#define CP0_CYCLE_DIVIDER 1 +#else +#define CP0_CYCLE_DIVIDER 2 +#endif + +/* + * The floating point version and status registers. + */ +#define FPC_ID $0 +#define FPC_CSR $31 + +/* + * Config1 register + */ +#define CONFIG1_M 0x80000000u +#define CONFIG1_MMUSize1 0x7e000000u +#define CONFIG1_MMUSize1_SHIFT 25 +#define CONFIG1_IS 0x01c00000u +#define CONFIG1_IS_SHIFT 22 +#define CONFIG1_IL 0x00380000u +#define CONFIG1_IL_SHIFT 19 +#define CONFIG1_IA 0x00070000u +#define CONFIG1_IA_SHIFT 16 +#define CONFIG1_DS 0x0000e000u +#define CONFIG1_DS_SHIFT 13 +#define CONFIG1_DL 0x00001c00u +#define CONFIG1_DL_SHIFT 10 +#define CONFIG1_DA 0x00000380u +#define CONFIG1_DA_SHIFT 7 +#define CONFIG1_C2 0x00000040u +#define CONFIG1_MD 0x00000020u +#define CONFIG1_PC 0x00000010u +#define CONFIG1_WR 0x00000008u +#define CONFIG1_CA 0x00000004u +#define CONFIG1_EP 0x00000002u +#define CONFIG1_FP 0x00000001u + +/* + * Config3 register + */ +#define CONFIG3_M 0x80000000 +#define CONFIG3_BPG 0x40000000 +#define CONFIG3_CMGCR 0x20000000 +#define CONFIG3_IPLW 0x00600000 +#define CONFIG3_MMAR 0x001c0000 +#define CONFIG3_MCU 0x00020000 +#define CONFIG3_ISAOnExc 0x00010000 +#define CONFIG3_ISA 0x0000c000 +#define CONFIG3_ULRI 0x00002000 +#define CONFIG3_RXI 0x00001000 +#define CONFIG3_DSP2P 0x00000800 +#define CONFIG3_DSPP 0x00000400 +#define CONFIG3_CTXTC 0x00000200 +#define CONFIG3_ITL 0x00000100 +#define CONFIG3_LPA 0x00000080 +#define CONFIG3_VEIC 0x00000040 +#define CONFIG3_VInt 0x00000020 +#define CONFIG3_SP 0x00000010 +#define CONFIG3_CDMM 0x00000008 +#define CONFIG3_MT 0x00000004 +#define CONFIG3_SM 0x00000002 +#define CONFIG3_TL 0x00000001 + +/* + * Config4 register + */ +#define CONFIG4_M 0x80000000u +#define CONFIG4_IE 0x60000000u +#define CONFIG4_AE 0x10000000u +#define CONFIG4_VTLBSizeExt 0x0f000000u /* when MMUExtDef=3 */ +#define CONFIG4_KScrExist 0x00ff0000u +#define CONFIG4_MMUExtDef 0x0000c000u +#define CONFIG4_MMUExtDef_SHIFT 14 +#define CONFIG4_FTLBPageSize 0x00001f00u /* when MMUExtDef=2 or 3 */ +#define CONFIG4_FTLBWays 0x000000f0u /* when MMUExtDef=2 or 3 */ +#define CONFIG4_FTLBSets 0x0000000fu /* when MMUExtDef=2 or 3 */ +#define CONFIG4_MMUSizeExt 0x000000ffu /* when MMUExtDef=1 */ + +/* + * PageGrain register + */ +#define PGRAIN_RIE 0x80000000 +#define PGRAIN_XIE 0x40000000 +#define PGRAIN_ELPA 0x20000000 +#define PGRAIN_ESP 0x10000000 +#define PGRAIN_IEC 0x08000000 + +/* + * HWREna register + */ +#define HWRENA_ULR 0x20000000u +#define HWRENA_CC 0x00000004u + +#endif /* _KERNEL || _STANDALONE */ + +#endif /* !_MIPS64_CPUREGS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/mips_opcode.h b/lib/libc/include/generic-openbsd/mips64/mips_opcode.h new file mode 100644 index 000000000000..f40d67885bec --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/mips_opcode.h @@ -0,0 +1,347 @@ +/* $OpenBSD: mips_opcode.h,v 1.9 2017/04/20 15:42:26 visa Exp $ */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)mips_opcode.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _MIPS64_MIPS_OPCODE_H_ +#define _MIPS64_MIPS_OPCODE_H_ + +/* + * Define the instruction formats and opcode values for the + * MIPS instruction set. + */ + +/* + * Define the instruction formats. + */ +typedef union { + unsigned word; + +#if BYTE_ORDER == BIG_ENDIAN + struct { + unsigned op: 6; + unsigned rs: 5; + unsigned rt: 5; + unsigned imm: 16; + } IType; + + struct { + unsigned op: 6; + unsigned target: 26; + } JType; + + struct { + unsigned op: 6; + unsigned rs: 5; + unsigned rt: 5; + unsigned rd: 5; + unsigned shamt: 5; + unsigned func: 6; + } RType; + + struct { + unsigned op: 6; /* COP1 */ + unsigned : 1; /* always '1' */ + unsigned fmt: 4; + unsigned ft: 5; + unsigned fs: 5; + unsigned fd: 5; + unsigned func: 6; + } FRType; + + struct { + unsigned op: 6; /* COP1X */ + unsigned fr: 5; + unsigned ft: 5; + unsigned fs: 5; + unsigned fd: 5; + unsigned op4: 3; + unsigned fmt3: 3; + } FQType; +#endif +#if BYTE_ORDER == LITTLE_ENDIAN + struct { + unsigned imm: 16; + unsigned rt: 5; + unsigned rs: 5; + unsigned op: 6; + } IType; + + struct { + unsigned target: 26; + unsigned op: 6; + } JType; + + struct { + unsigned func: 6; + unsigned shamt: 5; + unsigned rd: 5; + unsigned rt: 5; + unsigned rs: 5; + unsigned op: 6; + } RType; + + struct { + unsigned func: 6; + unsigned fd: 5; + unsigned fs: 5; + unsigned ft: 5; + unsigned fmt: 4; + unsigned : 1; /* always '1' */ + unsigned op: 6; /* COP1 */ + } FRType; + + struct { + unsigned fmt3: 3; + unsigned op4: 3; + unsigned fd: 5; + unsigned fs: 5; + unsigned ft: 5; + unsigned fr: 5; + unsigned op: 6; /* COP1X */ + } FQType; +#endif +} InstFmt; + +/* + * Values for the 'op' field. + */ +#define OP_SPECIAL 000 +#define OP_BCOND 001 +#define OP_J 002 +#define OP_JAL 003 +#define OP_BEQ 004 +#define OP_BNE 005 +#define OP_BLEZ 006 +#define OP_BGTZ 007 + +#define OP_ADDI 010 +#define OP_ADDIU 011 +#define OP_SLTI 012 +#define OP_SLTIU 013 +#define OP_ANDI 014 +#define OP_ORI 015 +#define OP_XORI 016 +#define OP_LUI 017 + +#define OP_COP0 020 +#define OP_COP1 021 +#define OP_COP2 022 +#define OP_COP3 023 +#define OP_COP1X 023 +#define OP_BEQL 024 +#define OP_BNEL 025 +#define OP_BLEZL 026 +#define OP_BGTZL 027 + +#define OP_DADDI 030 +#define OP_DADDIU 031 +#define OP_LDL 032 +#define OP_LDR 033 + +#define OP_SPECIAL3 037 + +#define OP_LB 040 +#define OP_LH 041 +#define OP_LWL 042 +#define OP_LW 043 +#define OP_LBU 044 +#define OP_LHU 045 +#define OP_LWR 046 +#define OP_LWU 047 + +#define OP_SB 050 +#define OP_SH 051 +#define OP_SWL 052 +#define OP_SW 053 +#define OP_SDL 054 +#define OP_SDR 055 +#define OP_SWR 056 +#define OP_CACHE 057 + +#define OP_LL 060 +#define OP_LWC1 061 +#define OP_LWC2 062 +#define OP_LWC3 063 +#define OP_PREF 063 +#define OP_LLD 064 +#define OP_LDC1 065 +#define OP_LDC2 066 +#define OP_LD 067 + +#define OP_SC 070 +#define OP_SWC1 071 +#define OP_SWC2 072 +#define OP_SWC3 073 +#define OP_SCD 074 +#define OP_SDC1 075 +#define OP_SDC2 076 +#define OP_SD 077 + +/* + * Values for the 'func' field when 'op' == OP_SPECIAL. + */ +#define OP_SLL 000 +#define OP_MOVCI 001 +#define OP_SRL 002 +#define OP_SRA 003 +#define OP_SLLV 004 +#define OP_SRLV 006 +#define OP_SRAV 007 + +#define OP_JR 010 +#define OP_JALR 011 +#define OP_MOVZ 012 +#define OP_MOVN 013 +#define OP_SYSCALL 014 +#define OP_BREAK 015 +#define OP_SYNC 017 + +#define OP_MFHI 020 +#define OP_MTHI 021 +#define OP_MFLO 022 +#define OP_MTLO 023 +#define OP_DSLLV 024 +#define OP_DSRLV 026 +#define OP_DSRAV 027 + +#define OP_MULT 030 +#define OP_MULTU 031 +#define OP_DIV 032 +#define OP_DIVU 033 +#define OP_DMULT 034 +#define OP_DMULTU 035 +#define OP_DDIV 036 +#define OP_DDIVU 037 + +#define OP_ADD 040 +#define OP_ADDU 041 +#define OP_SUB 042 +#define OP_SUBU 043 +#define OP_AND 044 +#define OP_OR 045 +#define OP_XOR 046 +#define OP_NOR 047 + +#define OP_SLT 052 +#define OP_SLTU 053 +#define OP_DADD 054 +#define OP_DADDU 055 +#define OP_DSUB 056 +#define OP_DSUBU 057 + +#define OP_TGE 060 +#define OP_TGEU 061 +#define OP_TLT 062 +#define OP_TLTU 063 +#define OP_TEQ 064 +#define OP_TNE 066 + +#define OP_DSLL 070 +#define OP_DSRL 072 +#define OP_DSRA 073 +#define OP_DSLL32 074 +#define OP_DSRL32 076 +#define OP_DSRA32 077 + +/* + * Values for the 'rt' field when 'op' == OP_BCOND. + */ +#define OP_BLTZ 000 +#define OP_BGEZ 001 +#define OP_BLTZL 002 +#define OP_BGEZL 003 + +#define OP_TGEI 010 +#define OP_TGEIU 011 +#define OP_TLTI 012 +#define OP_TLTIU 013 +#define OP_TEQI 014 +#define OP_TNEI 016 + +#define OP_BLTZAL 020 +#define OP_BGEZAL 021 +#define OP_BLTZALL 022 +#define OP_BGEZALL 023 + +/* + * Values for the 'rs' field when 'op' == OP_COPz. + */ +#define OP_MF 000 +#define OP_DMF 001 +#define OP_CF 002 +#define OP_MFH 003 +#define OP_MT 004 +#define OP_DMT 005 +#define OP_CT 006 +#define OP_MTH 007 +#define OP_BC 010 +#define OP_C0MISC 020 /* cop0 only */ +#define OP_TFP_C0MISC 030 /* cop0 only on R8000 */ + +/* + * Values for the 'rt' field when 'op' == OP_COPz. + */ +#define COPz_BC_TF_MASK 0x01 +#define COPz_BC_TRUE 0x01 +#define COPz_BC_FALSE 0x00 +#define COPz_BCL_TF_MASK 0x02 +#define COPz_BCL_TRUE 0x02 +#define COPz_BCL_FALSE 0x00 +#define COPz_BC_CC_MASK 0x1c +#define COPz_BC_CC_SHIFT 2 + +/* + * Values for the 'func' field when 'op' == OP_COP1X. + */ +#define OP_LWXC1 000 +#define OP_LDXC1 001 +#define OP_SWXC1 010 +#define OP_SDXC1 011 +#define OP_PREFX 017 + +/* + * Values for the 'op4' field when 'op' == OP_COP1X. + */ +#define OP_MADD 04 +#define OP_MSUB 05 +#define OP_NMADD 06 +#define OP_NMSUB 07 + +/* + * Values for the 'func' field when 'op' == OP_SPECIAL3. + */ +#define OP_RDHWR 073 + +#endif /* !_MIPS64_MIPS_OPCODE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/mplock.h b/lib/libc/include/generic-openbsd/mips64/mplock.h new file mode 100644 index 000000000000..a2c480761ec5 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/mplock.h @@ -0,0 +1,10 @@ +/* $OpenBSD: mplock.h,v 1.2 2017/10/21 06:11:22 visa Exp $ */ + +/* public domain */ + +#ifndef _MACHINE_MPLOCK_H_ +#define _MACHINE_MPLOCK_H_ + +#define __USE_MI_MPLOCK + +#endif /* !_MACHINE_MPLOCK_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/mutex.h b/lib/libc/include/generic-openbsd/mips64/mutex.h new file mode 100644 index 000000000000..f5115c3084e8 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/mutex.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mutex.h,v 1.5 2018/01/25 15:06:29 mpi Exp $ */ + +#define __USE_MI_MUTEX \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/param.h b/lib/libc/include/generic-openbsd/mips64/param.h new file mode 100644 index 000000000000..3420605a0d92 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/param.h @@ -0,0 +1,82 @@ +/* $OpenBSD: param.h,v 1.37 2023/12/14 13:26:49 claudio Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department and Ralph Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MIPS64_PARAM_H_ +#define _MIPS64_PARAM_H_ + +#ifdef _KERNEL +#include +#endif + +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define PAGE_MASK (PAGE_SIZE - 1) + +#ifdef _KERNEL + +#ifndef KERNBASE +#define KERNBASE 0xffffffff80000000L /* start of kernel virtual */ +#endif + +#define NBPG PAGE_SIZE +#define PGSHIFT PAGE_SHIFT +#define PGOFSET PAGE_MASK + +#define USPACE 16384 +#define UPAGES (USPACE >> PAGE_SHIFT) +#if PAGE_SHIFT > 12 +#define USPACE_ALIGN 0 +#else +#define USPACE_ALIGN (2 * PAGE_SIZE) /* align to an even TLB boundary */ +#endif + +#define NMBCLUSTERS (64 * 1024) /* max cluster allocation */ + +#ifndef MSGBUFSIZE +#if PAGE_SHIFT > 12 +#define MSGBUFSIZE PAGE_SIZE +#else +#define MSGBUFSIZE 8192 +#endif +#endif + +#ifndef _LOCORE +#define DELAY(n) delay(n) +void delay(int); +#endif + +#endif /* _KERNEL */ + +#endif /* _MIPS64_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/pcb.h b/lib/libc/include/generic-openbsd/mips64/pcb.h new file mode 100644 index 000000000000..bef10d569cdc --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/pcb.h @@ -0,0 +1,58 @@ +/* $OpenBSD: pcb.h,v 1.10 2021/10/07 12:40:16 visa Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department and Ralph Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Utah Hdr: pcb.h 1.13 89/04/23 + * from: @(#)pcb.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _MIPS64_PCB_H_ +#define _MIPS64_PCB_H_ + +#include + +/* + * MIPS process control block. This is first in the U-area. + */ +struct pcb { + struct trapframe pcb_regs; /* saved CPU and registers */ + struct { + /* val[12] is unused, was RM7000 ICR */ + register_t val[13]; + } pcb_context; /* kernel context for resume */ + int pcb_onfault; /* for copyin/copyout faults */ + void *pcb_segtab; /* copy of pmap pm_segtab */ +}; + +#endif /* !_MIPS64_PCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/pmap.h b/lib/libc/include/generic-openbsd/mips64/pmap.h new file mode 100644 index 000000000000..571adc77b869 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/pmap.h @@ -0,0 +1,228 @@ +/* $OpenBSD: pmap.h,v 1.55 2025/06/02 18:49:04 claudio Exp $ */ + +/* + * Copyright (c) 1987 Carnegie-Mellon University + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)pmap.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _MIPS64_PMAP_H_ +#define _MIPS64_PMAP_H_ + +#include + +#ifdef _KERNEL + +#include + +/* + * The user address space is currently limited to 1TB (0x0 - 0x10000000000). + * + * The user address space is mapped using a two level structure where + * the virtual addresses bits are split in three groups: + * segment:directory:page:offset + * where: + * - offset are the in-page offsets (PAGE_SHIFT bits) + * - page are the third level page table index + * (PMAP_PGSHIFT - Log2(pt_entry_t) bits) + * - directory are the second level page table (directory) index + * (PMAP_PGSHIFT - Log2(void *) bits) + * - segment are the first level page table (segment) index + * (PMAP_PGSHIFT - Log2(void *) bits) + * + * This scheme allows Segment, directory and page tables have the same size + * (1 << PMAP_PGSHIFT bytes, regardless of the pt_entry_t size) to be able to + * share the same allocator. + * + * Note: The kernel doesn't use the same data structures as user programs. + * All the PTE entries are stored in a single array in Sysmap which is + * dynamically allocated at boot time. + */ + +#if defined(MIPS_PTE64) && PAGE_SHIFT == 12 +#error "Cannot use MIPS_PTE64 with 4KB pages." +#endif + +/* + * Size of page table structs (page tables, page directories, + * and segment table) used by this pmap. + */ + +#define PMAP_PGSHIFT 12 +#define PMAP_PGSIZE (1UL << PMAP_PGSHIFT) + +#define NPDEPG (PMAP_PGSIZE / sizeof(void *)) +#define NPTEPG (PMAP_PGSIZE / sizeof(pt_entry_t)) + +/* + * Segment sizes + */ + +#define SEGSHIFT (PAGE_SHIFT+PMAP_PGSHIFT*2-PTE_LOG-3) +#define DIRSHIFT (PAGE_SHIFT+PMAP_PGSHIFT-PTE_LOG) +#define NBSEG (1UL << SEGSHIFT) +#define NBDIR (1UL << DIRSHIFT) +#define SEGOFSET (NBSEG - 1) +#define DIROFSET (NBDIR - 1) + +#define mips_trunc_seg(x) ((vaddr_t)(x) & ~SEGOFSET) +#define mips_trunc_dir(x) ((vaddr_t)(x) & ~DIROFSET) +#define mips_round_seg(x) (((vaddr_t)(x) + SEGOFSET) & ~SEGOFSET) +#define mips_round_dir(x) (((vaddr_t)(x) + DIROFSET) & ~DIROFSET) +#define pmap_segmap(m, v) ((m)->pm_segtab->seg_tab[((v) >> SEGSHIFT)]) + +/* number of segments entries */ +#define PMAP_SEGTABSIZE (PMAP_PGSIZE / sizeof(void *)) + +struct segtab { + pt_entry_t **seg_tab[PMAP_SEGTABSIZE]; +}; + +struct pmap_asid_info { + u_int pma_asid; /* address space tag */ + u_int pma_asidgen; /* TLB PID generation number */ +}; + +/* + * Machine dependent pmap structure. + */ +typedef struct pmap { + struct mutex pm_mtx; /* pmap lock */ + struct mutex pm_swmtx; /* pmap switch lock */ + int pm_count; /* pmap reference count */ + struct pmap_statistics pm_stats; /* pmap statistics */ + struct segtab *pm_segtab; /* pointers to pages of PTEs */ + struct pmap_asid_info pm_asid[1]; /* ASID information */ +} *pmap_t; + +/* + * Compute the sizeof of a pmap structure. Subtract one because one + * ASID info structure is already included in the pmap structure itself. + */ +#define PMAP_SIZEOF(x) \ + (ALIGN(sizeof(struct pmap) + \ + (sizeof(struct pmap_asid_info) * ((x) - 1)))) + +/* machine-dependent pg_flags */ +#define PGF_UNCACHED PG_PMAP0 /* Page is explicitly uncached */ +#define PGF_CACHED PG_PMAP1 /* Page is currently cached */ +#define PGF_ATTR_MOD PG_PMAP2 +#define PGF_ATTR_REF PG_PMAP3 +#define PGF_PRESERVE (PGF_ATTR_MOD | PGF_ATTR_REF) + +#define PMAP_NOCACHE PMAP_MD0 + +extern struct pmap *const kernel_pmap_ptr; + +#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) +#define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count) +#define pmap_kernel() (kernel_pmap_ptr) + +extern pt_entry_t pg_ri; +#define PMAP_CHECK_COPYIN (pg_ri == 0) + +#define PMAP_STEAL_MEMORY /* Enable 'stealing' during boot */ + +#define PMAP_PREFER +extern vaddr_t pmap_prefer_mask; +/* pmap prefer alignment */ +#define PMAP_PREFER_ALIGN() \ + (pmap_prefer_mask ? pmap_prefer_mask + 1 : 0) +/* pmap prefer offset in alignment */ +#define PMAP_PREFER_OFFSET(of) ((of) & pmap_prefer_mask) + +void pmap_bootstrap(void); +int pmap_copyinsn(pmap_t, vaddr_t, uint32_t *); +int pmap_emulate_modify(pmap_t, vaddr_t); +void pmap_page_cache(vm_page_t, u_int); + +#define pmap_init_percpu() do { /* nothing */ } while (0) +#define pmap_unuse_final(p) do { /* nothing yet */ } while (0) +#define pmap_remove_holes(vm) do { /* nothing */ } while (0) + +#define __HAVE_PMAP_DIRECT +vaddr_t pmap_map_direct(vm_page_t); +vm_page_t pmap_unmap_direct(vaddr_t); + +/* + * MD flags to pmap_enter: + */ + +#define PMAP_PA_MASK ~((paddr_t)PAGE_MASK) + +/* Kernel virtual address to page table entry */ +#define kvtopte(va) \ + (Sysmap + (((vaddr_t)(va) - VM_MIN_KERNEL_ADDRESS) >> PAGE_SHIFT)) +/* User virtual address to pte page entry */ +#define uvtopte(va) (((va) >> PAGE_SHIFT) & (NPTEPG -1)) +#define uvtopde(va) (((va) >> DIRSHIFT) & (NPDEPG - 1)) + +static inline pt_entry_t * +pmap_pte_lookup(struct pmap *pmap, vaddr_t va) +{ + pt_entry_t **pde, *pte; + + if ((pde = pmap_segmap(pmap, va)) == NULL) + return NULL; + if ((pte = pde[uvtopde(va)]) == NULL) + return NULL; + return pte + uvtopte(va); +} + +extern pt_entry_t *Sysmap; /* kernel pte table */ +extern u_int Sysmapsize; /* number of pte's in Sysmap */ + +#endif /* _KERNEL */ + +#if !defined(_LOCORE) +typedef struct pv_entry { + struct pv_entry *pv_next; /* next pv_entry */ + struct pmap *pv_pmap; /* pmap where mapping lies */ + vaddr_t pv_va; /* virtual address for mapping */ +} *pv_entry_t; + +struct vm_page_md { + struct mutex pv_mtx; /* pv list lock */ + struct pv_entry pv_ent; /* pv list of this seg */ +}; + +#define VM_MDPAGE_INIT(pg) \ + do { \ + mtx_init(&(pg)->mdpage.pv_mtx, IPL_VM); \ + (pg)->mdpage.pv_ent.pv_next = NULL; \ + (pg)->mdpage.pv_ent.pv_pmap = NULL; \ + (pg)->mdpage.pv_ent.pv_va = 0; \ + } while (0) + +#endif /* !_LOCORE */ + +#endif /* !_MIPS64_PMAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/proc.h b/lib/libc/include/generic-openbsd/mips64/proc.h new file mode 100644 index 000000000000..987d27cd4bfb --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/proc.h @@ -0,0 +1,75 @@ +/* $OpenBSD: proc.h,v 1.11 2017/04/13 03:52:25 guenther Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)proc.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _MIPS64_PROC_H_ +#define _MIPS64_PROC_H_ + +/* + * Machine-dependent part of the proc structure. + */ +struct mdproc { + struct trapframe *md_regs; /* registers on current frame */ + volatile int md_astpending; /* AST pending for this process */ + int md_flags; /* machine-dependent flags */ + vaddr_t md_uarea; /* allocated uarea virtual addr */ + void *md_tcb; /* user-space thread-control-block */ + + /* ptrace fields */ + vaddr_t md_ss_addr; /* single step address */ + uint32_t md_ss_instr; /* saved single step instruction */ + + /* fpu emulation fields */ + vaddr_t md_fppgva; /* vaddr of the branch emulation page */ + vaddr_t md_fpbranchva; /* vaddr of fp branch destination */ + vaddr_t md_fpslotva; /* initial vaddr of delay slot */ + + int32_t md_obsolete[10]; /* Were RM7000-specific data. */ +}; + +/* + * Values for md_flags. + * MDP_FPUSED has two meanings: if the floating point hardware (coprocessor + * #1) is available, it means it has been used; if there is no floating + * point hardware, it means the process is currently running a duplicated + * delay slot, created by the branch emulation logic. + */ +#define MDP_FPUSED 0x00000001 /* floating point coprocessor used */ +#define MDP_PERF 0x00010000 /* Performance counter used */ +#define MDP_WATCH1 0x00020000 /* Watch register 1 used */ +#define MDP_WATCH2 0x00040000 /* Watch register 1 used */ +#define MDP_FORKSAVE 0x0000ffff /* Flags to save when forking */ + +#endif /* !_MIPS64_PROC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/profile.h b/lib/libc/include/generic-openbsd/mips64/profile.h new file mode 100644 index 000000000000..09470a2561e3 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/profile.h @@ -0,0 +1,85 @@ +/* $OpenBSD: profile.h,v 1.5 2019/04/19 09:19:22 visa Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)profile.h 8.1 (Berkeley) 6/10/93 + */ +#ifndef _MIPS64_PROFILE_H_ +#define _MIPS64_PROFILE_H_ + +#define _MCOUNT_DECL static void ___mcount + +/*XXX The cprestore instruction is a "dummy" to shut up as(1). */ + +#define MCOUNT \ + __asm(".globl _mcount;" \ + ".type _mcount,@function;" \ + "_mcount:;" \ + ".set noreorder;" \ + ".set noat;" \ + ".cpload $25;" \ + ".cprestore 4;" \ + "sd $4,16($29);" \ + "sd $5,24($29);" \ + "sd $6,32($29);" \ + "sd $7,40($29);" \ + "sd $1,0($29);" \ + "sd $31,8($29);" \ + "move $5,$31;" \ + ".local ___mcount;" \ + "jal ___mcount;" \ + "move $4,$1;" \ + "ld $4,16($29);" \ + "ld $5,24($29);" \ + "ld $6,32($29);" \ + "ld $7,40($29);" \ + "ld $31,8($29);" \ + "ld $1,0($29);" \ + "daddu $29,$29,16;" \ + "j $31;" \ + "move $31,$1;" \ + ".set reorder;" \ + ".set at"); + +#ifdef _KERNEL +/* + * The following two macros do splhigh and splx respectively. + * They have to be defined this way because these are real + * functions on the MIPS, and we do not want to invoke mcount + * recursively. + */ +#define MCOUNT_ENTER s = _splhigh() + +#define MCOUNT_EXIT _splx(s) +#endif /* _KERNEL */ + +#endif /* !_MIPS64_PROFILE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/pte.h b/lib/libc/include/generic-openbsd/mips64/pte.h new file mode 100644 index 000000000000..cc5c5d0ba198 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/pte.h @@ -0,0 +1,160 @@ +/* $OpenBSD: pte.h,v 1.24 2023/01/11 03:17:56 visa Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department and Ralph Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Utah Hdr: pte.h 1.11 89/09/03 + * from: @(#)pte.h 8.1 (Berkeley) 6/10/93 + */ + +/* + * R4000 and R8000 hardware page table entries + */ + +#ifndef _MIPS64_PTE_H_ +#define _MIPS64_PTE_H_ + +#ifndef _LOCORE + +/* + * Structure defining a TLB entry data set. + */ +struct tlb_entry { + u_int64_t tlb_mask; + u_int64_t tlb_hi; + u_int64_t tlb_lo0; + u_int64_t tlb_lo1; +}; + +u_int tlb_get_pid(void); +void tlb_read(unsigned int, struct tlb_entry *); + +#ifdef MIPS_PTE64 +typedef u_int64_t pt_entry_t; +#else +typedef u_int32_t pt_entry_t; +#endif + +#endif /* _LOCORE */ + +#ifdef MIPS_PTE64 +#define PTE_BITS 64 +#define PTE_LOAD ld +#define PTE_LOG 3 +#define PTE_OFFS 8 +#else +#define PTE_BITS 32 +#define PTE_LOAD lwu +#define PTE_LOG 2 +#define PTE_OFFS 4 +#endif + +#if defined(CPU_MIPS64R2) && !defined(CPU_LOONGSON2) +#define PTE_CLEAR_SWBITS(reg) \ + .set push; \ + .set mips64r2; \ + /* Clear SW bits between PG_XI and PG_FRAMEBITS. */ \ + dins reg, zero, PG_FRAMEBITS, (PTE_BITS - 2 - PG_FRAMEBITS); \ + .set pop +#else +#define PTE_CLEAR_SWBITS(reg) \ + /* Clear SW bits left of PG_FRAMEBITS. */ \ + dsll reg, reg, (64 - PG_FRAMEBITS); \ + dsrl reg, reg, (64 - PG_FRAMEBITS) +#endif + +/* entryhi values */ + +#define PG_HVPN (-2 * PAGE_SIZE) /* Hardware page number mask */ +#define PG_ODDPG PAGE_SIZE + +/* Address space ID */ +#define PG_ASID_MASK 0x00000000000000ff +#define PG_ASID_SHIFT 0 +#define MIN_USER_ASID 1 +#define PG_ASID_COUNT 256 /* Number of available ASID */ + +/* entrylo values */ + +#ifdef MIPS_PTE64 +#define PG_FRAMEBITS 60 +#else +#define PG_FRAMEBITS 28 +#endif +#define PG_FRAME ((1ULL << PG_FRAMEBITS) - (1ULL << PG_SHIFT)) +#define PG_SHIFT 6 + +/* software pte bits - not put in entrylo */ +#define PG_WIRED (1ULL << (PG_FRAMEBITS + 1)) +#define PG_RO (1ULL << (PG_FRAMEBITS + 0)) + +#ifdef CPU_MIPS64R2 +#define PG_RI (1ULL << (PG_FRAMEBITS + 3)) +#define PG_XI (1ULL << (PG_FRAMEBITS + 2)) +#else +#define PG_RI 0x00000000 +#define PG_XI 0x00000000 +#endif + +#define PG_NV 0x00000000 +#define PG_G 0x00000001 +#define PG_V 0x00000002 +#define PG_M 0x00000004 +#define PG_CCA_SHIFT 3 + +#define PG_UNCACHED (CCA_NC << PG_CCA_SHIFT) +#define PG_CACHED_NC (CCA_NONCOHERENT << PG_CCA_SHIFT) +#define PG_CACHED_CE (CCA_COHERENT_EXCL << PG_CCA_SHIFT) +#define PG_CACHED_CEW (CCA_COHERENT_EXCLWRITE << PG_CCA_SHIFT) +#define PG_CACHED (CCA_CACHED << PG_CCA_SHIFT) +#define PG_CACHEMODE (7 << PG_CCA_SHIFT) + +#define PG_PROTMASK (PG_M | PG_RO | PG_RI | PG_XI) + +#define pfn_to_pad(pa) ((((paddr_t)pa) & PG_FRAME) << PG_SHIFT) +#define vad_to_pfn(va) (((va) >> PG_SHIFT) & PG_FRAME) + +#define PG_SIZE_4K 0x00000000 +#define PG_SIZE_16K 0x00006000 +#define PG_SIZE_64K 0x0001e000 +#define PG_SIZE_256K 0x0007e000 +#define PG_SIZE_1M 0x001fe000 +#define PG_SIZE_4M 0x007fe000 +#define PG_SIZE_16M 0x01ffe000 +#if PAGE_SHIFT == 12 +#define TLB_PAGE_MASK PG_SIZE_4K +#elif PAGE_SHIFT == 14 +#define TLB_PAGE_MASK PG_SIZE_16K +#endif + +#endif /* !_MIPS64_PTE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/ptrace.h b/lib/libc/include/generic-openbsd/mips64/ptrace.h new file mode 100644 index 000000000000..000251046bc0 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/ptrace.h @@ -0,0 +1,46 @@ +/* $OpenBSD: ptrace.h,v 1.3 2011/03/23 16:54:36 pirofti Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)ptrace.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _MIPS64_PTRACE_H_ +#define _MIPS64_PTRACE_H_ + +/* + * Machine dependent trace commands. + * + */ + +#define PT_GETREGS (PT_FIRSTMACH+0) +#define PT_SETREGS (PT_FIRSTMACH+1) +#define PT_STEP (PT_FIRSTMACH+2) + +#endif /* !_MIPS64_PTRACE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/reg.h b/lib/libc/include/generic-openbsd/mips64/reg.h new file mode 100644 index 000000000000..38245604ff42 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/reg.h @@ -0,0 +1,54 @@ +/* $OpenBSD: reg.h,v 1.5 2021/10/07 12:32:10 visa Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department and Ralph Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Utah Hdr: reg.h 1.1 90/07/09 + * @(#)reg.h 8.2 (Berkeley) 1/11/94 + */ + +#ifndef _MIPS64_REG_H_ +#define _MIPS64_REG_H_ +/* + * Location of the users' stored + * registers relative to ZERO. + * Usage is p->p_regs[XX]. + * + * must be visible to assembly code. + */ +#include + +struct reg { + register_t r_regs[NREGS]; /* numbered as above */ +}; +#endif /* !_MIPS64_REG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/regdef.h b/lib/libc/include/generic-openbsd/mips64/regdef.h new file mode 100644 index 000000000000..27c56a035a29 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/regdef.h @@ -0,0 +1,77 @@ +/* $OpenBSD: regdef.h,v 1.5 2014/03/10 21:10:36 miod Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell. This file is derived from the MIPS RISC + * Architecture book by Gerry Kane. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)regdef.h 8.1 (Berkeley) 6/10/93 + */ +#ifndef _MIPS64_REGDEF_H_ +#define _MIPS64_REGDEF_H_ + +#define zero $0 /* always zero */ +#define AT $at /* assembler temp */ +#define v0 $2 /* return value */ +#define v1 $3 +#define a0 $4 /* argument registers */ +#define a1 $5 +#define a2 $6 +#define a3 $7 +#define a4 $8 +#define a5 $9 +#define a6 $10 +#define a7 $11 +#define ta0 $8 /* alias */ +#define ta1 $9 +#define ta2 $10 +#define ta3 $11 +#define t0 $12 /* temp registers (not saved across subroutine calls) */ +#define t1 $13 +#define t2 $14 +#define t3 $15 +#define s0 $16 /* saved across subroutine calls (callee saved) */ +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 /* two more temp registers */ +#define t9 $25 +#define k0 $26 /* kernel temporary */ +#define k1 $27 +#define gp $28 /* global pointer */ +#define sp $29 /* stack pointer */ +#define s8 $30 /* one more callee saved */ +#define ra $31 /* return address */ + +#endif /* !_MIPS64_REGDEF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/regnum.h b/lib/libc/include/generic-openbsd/mips64/regnum.h new file mode 100644 index 000000000000..f11f05e222ff --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/regnum.h @@ -0,0 +1,119 @@ +/* $OpenBSD: regnum.h,v 1.4 2014/07/09 12:58:08 miod Exp $ */ + +/* + * Copyright (c) 2001-2002 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _MIPS64_REGNUM_H_ +#define _MIPS64_REGNUM_H_ + +/* + * Location of the saved registers relative to ZERO. + * Usage is p->p_regs[XX]. + */ +#define ZERO 0 +#define AST 1 +#define V0 2 +#define V1 3 +#define A0 4 +#define A1 5 +#define A2 6 +#define A3 7 +#define A4 8 +#define A5 9 +#define A6 10 +#define A7 11 +#define T0 12 +#define T1 13 +#define T2 14 +#define T3 15 +#define S0 16 +#define S1 17 +#define S2 18 +#define S3 19 +#define S4 20 +#define S5 21 +#define S6 22 +#define S7 23 +#define T8 24 +#define T9 25 +#define K0 26 +#define K1 27 +#define GP 28 +#define SP 29 +#define S8 30 +#define RA 31 +#define SR 32 +#define PS SR /* alias for SR */ +#define MULLO 33 +#define MULHI 34 +#define BADVADDR 35 +#define CAUSE 36 +#define PC 37 +#define IC 38 +#define CPL 39 + +#define NUMSAVEREGS 40 /* Number of registers saved in trap */ + +#define FPBASE NUMSAVEREGS +#define F0 (FPBASE+0) +#define F1 (FPBASE+1) +#define F2 (FPBASE+2) +#define F3 (FPBASE+3) +#define F4 (FPBASE+4) +#define F5 (FPBASE+5) +#define F6 (FPBASE+6) +#define F7 (FPBASE+7) +#define F8 (FPBASE+8) +#define F9 (FPBASE+9) +#define F10 (FPBASE+10) +#define F11 (FPBASE+11) +#define F12 (FPBASE+12) +#define F13 (FPBASE+13) +#define F14 (FPBASE+14) +#define F15 (FPBASE+15) +#define F16 (FPBASE+16) +#define F17 (FPBASE+17) +#define F18 (FPBASE+18) +#define F19 (FPBASE+19) +#define F20 (FPBASE+20) +#define F21 (FPBASE+21) +#define F22 (FPBASE+22) +#define F23 (FPBASE+23) +#define F24 (FPBASE+24) +#define F25 (FPBASE+25) +#define F26 (FPBASE+26) +#define F27 (FPBASE+27) +#define F28 (FPBASE+28) +#define F29 (FPBASE+29) +#define F30 (FPBASE+30) +#define F31 (FPBASE+31) +#define FSR (FPBASE+32) + +#define NUMFPREGS 33 + +#define NREGS (NUMSAVEREGS + NUMFPREGS) + +#endif /* !_MIPS64_REGNUM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/reloc.h b/lib/libc/include/generic-openbsd/mips64/reloc.h new file mode 100644 index 000000000000..c25f3c163d7f --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/reloc.h @@ -0,0 +1,54 @@ +/* $OpenBSD: reloc.h,v 1.4 2017/08/13 14:56:09 visa Exp $ */ + +/* + * Copyright (c) 1996-2004 Per Fogelstrom, Opsycon AB + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _MIPS64_RELOC_H_ +#define _MIPS64_RELOC_H_ + +/* + * Mips relocations. + */ + +#define R_MIPS_NONE 0 /* No reloc */ +#define R_MIPS_16 1 /* Direct 16 bit */ +#define R_MIPS_32 2 /* Direct 32 bit */ +#define R_MIPS_REL32 3 /* PC relative 32 bit */ +#define R_MIPS_26 4 /* Direct 26 bit shifted */ +#define R_MIPS_HI16 5 /* High 16 bit */ +#define R_MIPS_LO16 6 /* Low 16 bit */ +#define R_MIPS_GPREL16 7 /* GP relative 16 bit */ +#define R_MIPS_LITERAL 8 /* 16 bit literal entry */ +#define R_MIPS_GOT16 9 /* 16 bit GOT entry */ +#define R_MIPS_PC16 10 /* PC relative 16 bit */ +#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ +#define R_MIPS_GPREL32 12 /* GP relative 32 bit */ + +#define R_MIPS_64 18 + +#define R_MIPS_REL32_64 ((R_MIPS_64 << 8) | R_MIPS_REL32) + +#endif /* !_MIPS64_RELOC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/setjmp.h b/lib/libc/include/generic-openbsd/mips64/setjmp.h new file mode 100644 index 000000000000..a7f81372b643 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/setjmp.h @@ -0,0 +1,15 @@ +/* $OpenBSD: setjmp.h,v 1.4 2018/01/08 16:44:32 visa Exp $ */ + +/* Public domain */ + +#ifndef _MIPS64_SETJMP_H_ +#define _MIPS64_SETJMP_H_ + +#define _JB_MASK (1 * REGSZ) +#define _JB_PC (2 * REGSZ) +#define _JB_REGS (3 * REGSZ) +#define _JB_FPREGS (37 * REGSZ) + +#define _JBLEN 83 /* size, in longs, of a jmp_buf */ + +#endif /* !_MIPS64_SETJMP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/signal.h b/lib/libc/include/generic-openbsd/mips64/signal.h new file mode 100644 index 000000000000..2d6f9c1ad86f --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/signal.h @@ -0,0 +1,70 @@ +/* $OpenBSD: signal.h,v 1.13 2018/01/08 16:44:32 visa Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)signal.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _MIPS64_SIGNAL_H_ +#define _MIPS64_SIGNAL_H_ + +#include +#include + +/* + * Machine-dependent signal definitions + */ +typedef int sig_atomic_t; + +#if __BSD_VISIBLE || __XPG_VISIBLE >= 420 +/* + * Information pushed on stack when a signal is delivered. + * This is used by the kernel to restore state following + * execution of the signal handler. It is also made available + * to the handler to allow it to restore state properly if + * a non-standard exit is performed. + */ +struct sigcontext { + long sc_cookie; + long sc_mask; /* signal mask to restore XXX should be int */ + __register_t sc_pc; /* pc at time of signal */ + __register_t sc_regs[32]; /* processor regs 0 to 31 */ + __register_t mullo; /* mullo and mulhi registers... */ + __register_t mulhi; /* mullo and mulhi registers... */ + f_register_t sc_fpregs[33]; /* fp regs 0 to 31 and csr */ + long sc_fpused; /* fp has been used */ + long sc_fpc_eir; /* floating point exception instruction reg */ + long xxx[8]; /* XXX reserved */ +}; +#endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ + +#endif /* !_MIPS64_SIGNAL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/spinlock.h b/lib/libc/include/generic-openbsd/mips64/spinlock.h new file mode 100644 index 000000000000..4ca59f451781 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/spinlock.h @@ -0,0 +1,11 @@ +/* $OpenBSD: spinlock.h,v 1.5 2017/09/05 02:40:54 guenther Exp $ */ + /* Public domain */ + +#ifndef _MIPS64_SPINLOCK_H_ +#define _MIPS64_SPINLOCK_H_ + +#define _ATOMIC_LOCK_UNLOCKED (0) +#define _ATOMIC_LOCK_LOCKED (1) +typedef int _atomic_lock_t; + +#endif /* !_MIPS64_SPINLOCK_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/sysarch.h b/lib/libc/include/generic-openbsd/mips64/sysarch.h new file mode 100644 index 000000000000..04171b7d5d6a --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/sysarch.h @@ -0,0 +1,52 @@ +/* $OpenBSD: sysarch.h,v 1.2 2012/12/05 23:20:13 deraadt Exp $ */ + +/* + * Copyright (c) 2009 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MIPS64_SYSARCH_H_ +#define _MIPS64_SYSARCH_H_ + +/* + * Architecture specific syscalls (mips64) + */ + +#define MIPS64_CACHEFLUSH 0 + +/* + * Argument structure and defines to mimic IRIX cacheflush() system call + */ + +struct mips64_cacheflush_args { + vaddr_t va; + size_t sz; + int which; +#define ICACHE 0x01 +#define DCACHE 0x02 +#define BCACHE (ICACHE | DCACHE) +}; + +#ifndef _KERNEL + +#include + +__BEGIN_DECLS +int cacheflush(void *, int, int); +int _flush_cache(char *, int, int); +int sysarch(int, void *); +__END_DECLS +#endif /* _KERNEL */ + +#endif /* _MIPS64_SYSARCH_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/tcb.h b/lib/libc/include/generic-openbsd/mips64/tcb.h new file mode 100644 index 000000000000..eb7bf3bce545 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/tcb.h @@ -0,0 +1,66 @@ +/* $OpenBSD: tcb.h,v 1.4 2017/04/20 16:07:52 visa Exp $ */ + +/* + * Copyright (c) 2011 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TCB_H_ +#define _MACHINE_TCB_H_ + +#ifdef _KERNEL + +static inline void +__mips64_set_tcb(struct proc *p, void *tcb) +{ +#ifdef CPU_MIPS64R2 + extern int cpu_has_userlocal; + + if (cpu_has_userlocal) + cp0_set_userlocal(tcb); +#endif + + p->p_md.md_tcb = tcb; +} + +#define TCB_SET(p, addr) __mips64_set_tcb(p, addr) +#define TCB_GET(p) ((p)->p_md.md_tcb) + +#else /* _KERNEL */ + +/* ELF TLS ABI calls for small TCB, with static TLS data after it */ +#define TLS_VARIANT 1 + +static inline void * +__mips64_get_tcb(void) +{ + void *tcb; + + /* + * This invokes emulation in kernel if the system does not implement + * the RDHWR instruction or the UserLocal register. + */ + __asm__ volatile ( + " .set push\n" + " .set mips64r2\n" + " rdhwr %0, $29\n" + " .set pop\n" : "=r" (tcb)); + return tcb; +} + +#define TCB_GET() __mips64_get_tcb() + +#endif /* _KERNEL */ + +#endif /* _MACHINE_TCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/timetc.h b/lib/libc/include/generic-openbsd/mips64/timetc.h new file mode 100644 index 000000000000..8d7039b7063c --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/timetc.h @@ -0,0 +1,23 @@ +/* $OpenBSD: timetc.h,v 1.3 2020/07/18 08:37:43 visa Exp $ */ +/* + * Copyright (c) 2020 Paul Irofti + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MIPS64_TIMETC_H_ +#define _MIPS64_TIMETC_H_ + +#define TC_CP0_COUNT 1 + +#endif /* _MIPS64_TIMETC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/trap.h b/lib/libc/include/generic-openbsd/mips64/trap.h new file mode 100644 index 000000000000..2fff7cd58444 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/trap.h @@ -0,0 +1,127 @@ +/* $OpenBSD: trap.h,v 1.17 2022/01/28 16:20:09 visa Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department and Ralph Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Utah Hdr: trap.h 1.1 90/07/09 + * from: @(#)trap.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _MIPS64_TRAP_H_ +#define _MIPS64_TRAP_H_ + +/* + * Trap codes (ExcCode in the cause register); also known in trap.c for + * name strings. + */ + +#define T_INT 0 /* Interrupt pending */ +#define T_TLB_MOD 1 /* TLB modified fault */ +#define T_TLB_LD_MISS 2 /* TLB miss on load or ifetch */ +#define T_TLB_ST_MISS 3 /* TLB miss on a store */ +#define T_ADDR_ERR_LD 4 /* Address error on a load or ifetch */ +#define T_ADDR_ERR_ST 5 /* Address error on a store */ +#define T_BUS_ERR_IFETCH 6 /* Bus error on an ifetch */ +#define T_BUS_ERR_LD_ST 7 /* Bus error on a load or store */ +#define T_SYSCALL 8 /* System call */ +#define T_BREAK 9 /* Breakpoint */ +#define T_RES_INST 10 /* Reserved instruction exception */ +#define T_COP_UNUSABLE 11 /* Coprocessor unusable */ +#define T_OVFLOW 12 /* Arithmetic overflow */ +#define T_TRAP 13 /* Trap instruction */ +#define T_VCEI 14 /* R4k Virtual coherency instruction */ +#define T_FPE 15 /* Floating point exception */ +#define T_IWATCH 16 /* R4k Inst. Watch address reference */ +#define T_C2E 18 /* R5k Coprocessor 2 exception */ +#define T_MDMX 22 /* R5k MDMX unusable */ +#define T_DWATCH 23 /* Data Watch address reference */ +#define T_MCHECK 24 /* Machine check */ +#define T_CACHEERR 30 /* Cache error */ +#define T_VCED 31 /* R4k Virtual coherency data */ + +#define T_USER 0x20 /* user-mode flag or'ed with type */ + +/* + * Defines for trap handler catching kernel accessing memory. + */ +#define KT_COPYERR 1 /* User space copy error */ +#define KT_KCOPYERR 2 /* Kernel space copy error */ +#define KT_DDBERR 3 /* DDB access error */ + +#ifndef _LOCORE + +#if defined(DDB) || defined(DEBUG) + +struct trapdebug { /* trap history buffer for debugging */ + register_t status; + register_t cause; + register_t vadr; + register_t pc; + register_t ra; + register_t sp; + u_int code; + u_int ipl; +}; + +#define trapdebug_enter(ci, frame, cd) \ +do { \ + register_t sr = disableintr(); \ + u_long cpuid = ci->ci_cpuid; \ + struct trapdebug *t; \ + \ + t = trapdebug + TRAPSIZE * cpuid + trppos[cpuid]; \ + t->status = frame->sr; \ + t->cause = frame->cause; \ + t->vadr = frame->badvaddr; \ + t->pc = frame->pc; \ + t->sp = frame->sp; \ + t->ra = frame->ra; \ + t->ipl = frame->ipl; \ + t->code = cd; \ + if (++trppos[cpuid] == TRAPSIZE) \ + trppos[cpuid] = 0; \ + setsr(sr); \ +} while (0) + +#define TRAPSIZE 10 /* Trap log buffer length */ +extern struct trapdebug trapdebug[MAXCPUS * TRAPSIZE]; +extern uint trppos[MAXCPUS]; + +void trapDump(const char *, int (*)(const char *, ...)); + +#else +#define trapdebug_enter(ci, frame, code) +#endif +#endif /* _LOCORE */ + +#endif /* !_MIPS64_TRAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/mips64/vmparam.h b/lib/libc/include/generic-openbsd/mips64/vmparam.h new file mode 100644 index 000000000000..64dbaaabb8f0 --- /dev/null +++ b/lib/libc/include/generic-openbsd/mips64/vmparam.h @@ -0,0 +1,115 @@ +/* $OpenBSD: vmparam.h,v 1.31 2023/11/16 13:47:22 deraadt Exp $ */ +/* $NetBSD: vmparam.h,v 1.5 1994/10/26 21:10:10 cgd Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department and Ralph Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Utah Hdr: vmparam.h 1.16 91/01/18 + * @(#)vmparam.h 8.2 (Berkeley) 4/22/94 + */ + +#ifndef _MIPS64_VMPARAM_H_ +#define _MIPS64_VMPARAM_H_ + +/* + * Machine dependent constants mips processors. + */ + +#define USRSTACK VM_MAXUSER_ADDRESS /* Start of user stack */ + +/* + * Virtual memory related constants, all in bytes + */ +#ifndef MAXTSIZ +#define MAXTSIZ (128*1024*1024) /* max text size */ +#endif +#ifndef DFLDSIZ +#define DFLDSIZ (128*1024*1024) /* initial data size limit */ +#endif +#ifndef MAXDSIZ +#define MAXDSIZ (16UL*1024*1024*1024) /* max data size */ +#endif +#ifndef BRKSIZ +#define BRKSIZ MAXDSIZ /* heap gap size */ +#endif +#ifndef DFLSSIZ +#define DFLSSIZ (2*1024*1024) /* initial stack size limit */ +#endif +#ifndef MAXSSIZ +#define MAXSSIZ (32*1024*1024) /* max stack size */ +#endif + +#define STACKGAP_RANDOM 256*1024 + +/* + * PTEs for mapping user space into the kernel for physio operations. + * 16 pte's are enough to cover 8 disks * MAXBSIZE. + */ +#ifndef USRIOSIZE +#define USRIOSIZE 32 +#endif + +/* + * PTEs for system V style shared memory. + * This is basically slop for kmempt which we actually allocate (malloc) from. + */ +#ifndef SHMMAXPGS +#define SHMMAXPGS 8192 /* 8mb */ +#endif + +#ifndef VM_PHYSSEG_MAX +#define VM_PHYSSEG_MAX 8 /* Max number of physical memory segments */ +#endif +#ifndef VM_PHYSSEG_STRAT +#define VM_PHYSSEG_STRAT VM_PSTRAT_BSEARCH +#endif +#define VM_PHYSSEG_NOADD + +/* user/kernel map constants */ +#define VM_MIN_ADDRESS ((vaddr_t)0x0000000000004000L) +#define VM_MAXUSER_ADDRESS ((vaddr_t)0x0000010000000000L) +#define VM_MAX_ADDRESS VM_MAXUSER_ADDRESS +#ifdef _KERNEL +#define VM_MIN_STACK_ADDRESS ((vaddr_t)0x000000c000000000L) +#endif +#define VM_MIN_KERNEL_ADDRESS ((vaddr_t)0xc000000000000000L) +#define VM_MAX_KERNEL_ADDRESS ((vaddr_t)0xc000000040000000L) + +/* map PIE into approximately the first quarter of user va space */ +#define VM_PIE_MIN_ADDR PAGE_SIZE +#define VM_PIE_MAX_ADDR (0x4000000000UL) + +/* virtual sizes (bytes) for various kernel submaps */ +#define VM_PHYS_SIZE (USRIOSIZE*PAGE_SIZE) + +#endif /* !_MIPS64_VMPARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/miscfs/fifofs/fifo.h b/lib/libc/include/generic-openbsd/miscfs/fifofs/fifo.h new file mode 100644 index 000000000000..d6345c63b76f --- /dev/null +++ b/lib/libc/include/generic-openbsd/miscfs/fifofs/fifo.h @@ -0,0 +1,54 @@ +/* $OpenBSD: fifo.h,v 1.24 2022/06/26 05:20:42 visa Exp $ */ +/* $NetBSD: fifo.h,v 1.10 1996/02/09 22:40:15 christos Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)fifo.h 8.3 (Berkeley) 8/10/94 + */ +#ifdef FIFO + +/* + * Prototypes for fifo operations on vnodes. + */ +int fifo_ebadf(void *); + +int fifo_open(void *); +int fifo_close(void *); +int fifo_read(void *); +int fifo_write(void *); +int fifo_ioctl(void *); +int fifo_kqfilter(void *); +int fifo_inactive(void *); +int fifo_reclaim(void *); +int fifo_print(void *); +int fifo_pathconf(void *); +int fifo_advlock(void *); + +void fifo_printinfo(struct vnode *); +#endif /* FIFO */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/miscfs/fuse/fusefs.h b/lib/libc/include/generic-openbsd/miscfs/fuse/fusefs.h new file mode 100644 index 000000000000..12210d6f608f --- /dev/null +++ b/lib/libc/include/generic-openbsd/miscfs/fuse/fusefs.h @@ -0,0 +1,85 @@ +/* $OpenBSD: fusefs.h,v 1.15 2025/09/08 17:25:46 helg Exp $ */ +/* + * Copyright (c) 2012-2013 Sylvestre Gallon + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __FUSEFS_H__ +#define __FUSEFS_H__ + +/* sysctl defines */ +#define FUSEFS_OPENDEVS 1 /* # of fuse devices opened */ +#define FUSEFS_INFBUFS 2 /* # of in fbufs */ +#define FUSEFS_WAITFBUFS 3 /* # of fbufs waiting for a response */ +#define FUSEFS_POOL_NBPAGES 4 /* # total fusefs size */ +#define FUSEFS_MAXID 5 /* number of valid fusefs ids */ + +#define FUSEFS_NAMES { \ + { 0, 0}, \ + { "fusefs_open_devices", CTLTYPE_INT }, \ + { "fusefs_fbufs_in", CTLTYPE_INT }, \ + { "fusefs_fbufs_wait", CTLTYPE_INT }, \ + { "fusefs_pool_pages", CTLTYPE_INT }, \ +} + +#ifdef _KERNEL + +struct fuse_msg; + +struct fusefs_mnt { + struct mount *mp; + uint32_t undef_op; + int max_read; + int sess_init; + int allow_other; + dev_t dev; +}; + +#define UNDEF_ACCESS 1<<0 +#define UNDEF_MKDIR 1<<1 +#define UNDEF_CREATE 1<<2 +#define UNDEF_LINK 1<<3 +#define UNDEF_READLINK 1<<4 +#define UNDEF_RMDIR 1<<5 +#define UNDEF_REMOVE 1<<6 +#define UNDEF_SETATTR 1<<7 +#define UNDEF_RENAME 1<<8 +#define UNDEF_SYMLINK 1<<9 +#define UNDEF_MKNOD 1<<10 +#define UNDEF_FLUSH 1<<11 +#define UNDEF_FSYNC 1<<12 + +extern const struct vops fusefs_vops; +extern struct pool fusefs_fbuf_pool; + +/* files helpers. */ +int fusefs_file_open(struct fusefs_mnt *, struct fusefs_node *, enum fufh_type, + int, int, struct proc *); +int fusefs_file_close(struct fusefs_mnt *, struct fusefs_node *, + enum fufh_type, int, int, struct proc *); + +/* device helpers. */ +void fuse_device_cleanup(dev_t); +void fuse_device_queue_fbuf(dev_t, struct fusebuf *); +void fuse_device_set_fmp(struct fusefs_mnt *, int); + +/* + * The root inode is the root of the file system. Inode 0 can't be used for + * normal purposes. + */ +#define FUSE_ROOTINO ((ino_t)1) +#define VFSTOFUSEFS(mp) ((struct fusefs_mnt *)((mp)->mnt_data)) + +#endif /* _KERNEL */ +#endif /* __FUSEFS_H__ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/miscfs/fuse/fusefs_node.h b/lib/libc/include/generic-openbsd/miscfs/fuse/fusefs_node.h new file mode 100644 index 000000000000..c63d51447030 --- /dev/null +++ b/lib/libc/include/generic-openbsd/miscfs/fuse/fusefs_node.h @@ -0,0 +1,70 @@ +/* $OpenBSD: fusefs_node.h,v 1.5 2024/10/31 13:55:21 claudio Exp $ */ +/* + * Copyright (c) 2012-2013 Sylvestre Gallon + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _FUSEFS_NODE_H_ +#define _FUSEFS_NODE_H_ + +#include + +enum fufh_type { + FUFH_INVALID = -1, + FUFH_RDONLY = 0, + FUFH_WRONLY = 1, + FUFH_RDWR = 2, + FUFH_MAXTYPE = 3, +}; + +struct fusefs_filehandle { + uint64_t fh_id; + enum fufh_type fh_type; +}; + +struct fusefs_mnt; +struct fusefs_node { + LIST_ENTRY(fusefs_node) i_hash; /* Hash chain */ + struct vnode *i_vnode;/* Vnode associated with this inode. */ + struct fusefs_mnt *i_ump; + dev_t i_dev; /* Device associated with the inode. */ + ino_t i_number; /* The identity of the inode. */ + struct lockf_state *i_lockf; /* Byte-level lock state. */ + struct rrwlock i_lock; /* Inode lock */ + + /** I/O **/ + struct fusefs_filehandle fufh[FUFH_MAXTYPE]; + + /** meta **/ + off_t filesize; +}; + +#ifdef ITOV +# undef ITOV +#endif +#define ITOV(ip) ((ip)->i_vnode) + +#ifdef VTOI +# undef VTOI +#endif +#define VTOI(vp) ((struct fusefs_node *)(vp)->v_data) + +void fuse_ihashinit(void); +struct vnode *fuse_ihashget(dev_t, ino_t); +int fuse_ihashins(struct fusefs_node *); +void fuse_ihashrem(struct fusefs_node *); + +uint64_t fusefs_fd_get(struct fusefs_node *, enum fufh_type); + +#endif /* _FUSEFS_NODE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/msdosfs/bootsect.h b/lib/libc/include/generic-openbsd/msdosfs/bootsect.h new file mode 100644 index 000000000000..c82070268426 --- /dev/null +++ b/lib/libc/include/generic-openbsd/msdosfs/bootsect.h @@ -0,0 +1,97 @@ +/* $OpenBSD: bootsect.h,v 1.8 2025/08/01 13:00:18 jsg Exp $ */ +/* $NetBSD: bootsect.h,v 1.8 1997/10/17 11:23:29 ws Exp $ */ + +/* + * Written by Paul Popelka (paulp@uts.amdahl.com) + * + * You can do anything you want with this software, just don't say you wrote + * it, and don't remove this notice. + * + * This software is provided "as is". + * + * The author supplies this software to be publicly redistributed on the + * understanding that the author is not responsible for the correct + * functioning of this software in any circumstances and is not liable for + * any damages caused by this software. + * + * October 1992 + */ + +/* + * Format of a boot sector. This is the first sector on a DOS floppy disk + * or the first sector of a partition on a hard disk. But, it is not the + * first sector of a partitioned hard disk. + */ +struct bootsector33 { + u_int8_t bsJump[3]; /* jump inst E9xxxx or EBxx90 */ + int8_t bsOemName[8]; /* OEM name and version */ + int8_t bsBPB[19]; /* BIOS parameter block */ + int8_t bsDriveNumber; /* drive number (0x80) */ + int8_t bsBootCode[479]; /* pad so struct is 512b */ + u_int8_t bsBootSectSig0; + u_int8_t bsBootSectSig1; +#define BOOTSIG0 0x55 +#define BOOTSIG1 0xaa +}; + +struct extboot { + int8_t exDriveNumber; /* drive number (0x80) */ + int8_t exReserved1; /* reserved */ + int8_t exBootSignature; /* ext. boot signature (0x29) */ +#define EXBOOTSIG 0x29 + int8_t exVolumeID[4]; /* volume ID number */ + int8_t exVolumeLabel[11]; /* volume label */ + int8_t exFileSysType[8]; /* fs type (FAT12 or FAT16) */ +}; + +struct bootsector50 { + u_int8_t bsJump[3]; /* jump inst E9xxxx or EBxx90 */ + int8_t bsOemName[8]; /* OEM name and version */ + int8_t bsBPB[25]; /* BIOS parameter block */ + int8_t bsExt[26]; /* Bootsector Extension */ + int8_t bsBootCode[448]; /* pad so structure is 512b */ + u_int8_t bsBootSectSig0; + u_int8_t bsBootSectSig1; +#define BOOTSIG0 0x55 +#define BOOTSIG1 0xaa +}; + +struct bootsector710 { + u_int8_t bsJump[3]; /* jump inst E9xxxx or EBxx90 */ + int8_t bsOEMName[8]; /* OEM name and version */ + int8_t bsBPB[53]; /* BIOS parameter block */ + int8_t bsExt[26]; /* Bootsector Extension */ + int8_t bsBootCode[418]; /* pad so structure is 512b */ + u_int8_t bsBootSectSig2; /* 2 & 3 are only defined for FAT32? */ + u_int8_t bsBootSectSig3; + u_int8_t bsBootSectSig0; + u_int8_t bsBootSectSig1; +#define BOOTSIG0 0x55 +#define BOOTSIG1 0xaa +#define BOOTSIG2 0 +#define BOOTSIG3 0 +}; + +union bootsector { + struct bootsector33 bs33; + struct bootsector50 bs50; + struct bootsector710 bs710; +}; + +#if 0 +/* + * Shorthand for fields in the bpb. + */ +#define bsBytesPerSec bsBPB.bpbBytesPerSec +#define bsSectPerClust bsBPB.bpbSectPerClust +#define bsResSectors bsBPB.bpbResSectors +#define bsFATS bsBPB.bpbFATS +#define bsRootDirEnts bsBPB.bpbRootDirEnts +#define bsSectors bsBPB.bpbSectors +#define bsMedia bsBPB.bpbMedia +#define bsFATsecs bsBPB.bpbFATsecs +#define bsSectPerTrack bsBPB.bpbSectPerTrack +#define bsHeads bsBPB.bpbHeads +#define bsHiddenSecs bsBPB.bpbHiddenSecs +#define bsHugeSectors bsBPB.bpbHugeSectors +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/msdosfs/bpb.h b/lib/libc/include/generic-openbsd/msdosfs/bpb.h new file mode 100644 index 000000000000..b97d271154ba --- /dev/null +++ b/lib/libc/include/generic-openbsd/msdosfs/bpb.h @@ -0,0 +1,187 @@ +/* $OpenBSD: bpb.h,v 1.7 2015/10/23 10:45:31 krw Exp $ */ +/* $NetBSD: bpb.h,v 1.6 1997/10/17 11:23:35 ws Exp $ */ + +/* + * Written by Paul Popelka (paulp@uts.amdahl.com) + * + * You can do anything you want with this software, just don't say you wrote + * it, and don't remove this notice. + * + * This software is provided "as is". + * + * The author supplies this software to be publicly redistributed on the + * understanding that the author is not responsible for the correct + * functioning of this software in any circumstances and is not liable for + * any damages caused by this software. + * + * October 1992 + */ + +/* + * BIOS Parameter Block (BPB) for DOS 3.3 + */ +struct bpb33 { + u_int16_t bpbBytesPerSec; /* bytes per sector */ + u_int8_t bpbSecPerClust; /* sectors per cluster */ + u_int16_t bpbResSectors; /* number of reserved sectors */ + u_int8_t bpbFATs; /* number of FATs */ + u_int16_t bpbRootDirEnts; /* number of root directory entries */ + u_int16_t bpbSectors; /* total number of sectors */ + u_int8_t bpbMedia; /* media descriptor */ + u_int16_t bpbFATsecs; /* number of sectors per FAT */ + u_int16_t bpbSecPerTrack; /* sectors per track */ + u_int16_t bpbHeads; /* number of heads */ + u_int16_t bpbHiddenSecs; /* number of hidden sectors */ +}; + +/* + * BPB for DOS 5.0 The difference is bpbHiddenSecs is a short for DOS 3.3, + * and bpbHugeSectors is not in the 3.3 bpb. + */ +struct bpb50 { + u_int16_t bpbBytesPerSec; /* bytes per sector */ + u_int8_t bpbSecPerClust; /* sectors per cluster */ + u_int16_t bpbResSectors; /* number of reserved sectors */ + u_int8_t bpbFATs; /* number of FATs */ + u_int16_t bpbRootDirEnts; /* number of root directory entries */ + u_int16_t bpbSectors; /* total number of sectors */ + u_int8_t bpbMedia; /* media descriptor */ + u_int16_t bpbFATsecs; /* number of sectors per FAT */ + u_int16_t bpbSecPerTrack; /* sectors per track */ + u_int16_t bpbHeads; /* number of heads */ + u_int32_t bpbHiddenSecs; /* # of hidden sectors */ + u_int32_t bpbHugeSectors; /* # of sectors if bpbSectors == 0 */ +}; + +/* + * BPB for DOS 7.10 (FAT32). This one has a few extensions to bpb50. + */ +struct bpb710 { + u_int16_t bpbBytesPerSec; /* bytes per sector */ + u_int8_t bpbSecPerClust; /* sectors per cluster */ + u_int16_t bpbResSectors; /* number of reserved sectors */ + u_int8_t bpbFATs; /* number of FATs */ + u_int16_t bpbRootDirEnts; /* number of root directory entries */ + u_int16_t bpbSectors; /* total number of sectors */ + u_int8_t bpbMedia; /* media descriptor */ + u_int16_t bpbFATsecs; /* number of sectors per FAT */ + u_int16_t bpbSecPerTrack; /* sectors per track */ + u_int16_t bpbHeads; /* number of heads */ + u_int32_t bpbHiddenSecs; /* # of hidden sectors */ + u_int32_t bpbHugeSectors; /* # of sectors if bpbSectors == 0 */ + u_int32_t bpbBigFATsecs; /* like bpbFATsecs for FAT32 */ + u_int16_t bpbExtFlags; /* extended flags: */ +#define FATNUM 0xf /* mask for numbering active FAT */ +#define FATMIRROR 0x80 /* FAT is mirrored (like it always was) */ + u_int16_t bpbFSVers; /* filesystem version */ +#define FSVERS 0 /* currently only 0 is understood */ + u_int32_t bpbRootClust; /* start cluster for root directory */ + u_int16_t bpbFSInfo; /* filesystem info structure sector */ + u_int16_t bpbBackup; /* backup boot sector */ + /* There is a 12 byte filler here, but we ignore it */ +}; + +/* + * The following structures represent how the bpb's look on disk. shorts + * and longs are just character arrays of the appropriate length. This is + * because the compiler forces shorts and longs to align on word or + * halfword boundaries. + * + * XXX The little-endian code here assumes that the processor can access + * 16-bit and 32-bit quantities on byte boundaries. If this is not true, + * use the macros for the big-endian case. + */ +#include +#if (BYTE_ORDER == LITTLE_ENDIAN) && !defined(__STRICT_ALIGNMENT) +#define getushort(x) *((u_int16_t *)(x)) +#define getulong(x) *((u_int32_t *)(x)) +#define putushort(p, v) (*((u_int16_t *)(p)) = (v)) +#define putulong(p, v) (*((u_int32_t *)(p)) = (v)) +#else +#define getushort(x) (((u_int8_t *)(x))[0] + (((u_int8_t *)(x))[1] << 8)) +#define getulong(x) (((u_int8_t *)(x))[0] + (((u_int8_t *)(x))[1] << 8) \ + + (((u_int8_t *)(x))[2] << 16) \ + + (((u_int8_t *)(x))[3] << 24)) +#define putushort(p, v) (((u_int8_t *)(p))[0] = (v), \ + ((u_int8_t *)(p))[1] = (v) >> 8) +#define putulong(p, v) (((u_int8_t *)(p))[0] = (v), \ + ((u_int8_t *)(p))[1] = (v) >> 8, \ + ((u_int8_t *)(p))[2] = (v) >> 16,\ + ((u_int8_t *)(p))[3] = (v) >> 24) +#endif + +/* + * BIOS Parameter Block (BPB) for DOS 3.3 + */ +struct byte_bpb33 { + int8_t bpbBytesPerSec[2]; /* bytes per sector */ + int8_t bpbSecPerClust; /* sectors per cluster */ + int8_t bpbResSectors[2]; /* number of reserved sectors */ + int8_t bpbFATs; /* number of FATs */ + int8_t bpbRootDirEnts[2]; /* number of root directory entries */ + int8_t bpbSectors[2]; /* total number of sectors */ + int8_t bpbMedia; /* media descriptor */ + int8_t bpbFATsecs[2]; /* number of sectors per FAT */ + int8_t bpbSecPerTrack[2]; /* sectors per track */ + int8_t bpbHeads[2]; /* number of heads */ + int8_t bpbHiddenSecs[2]; /* number of hidden sectors */ +}; + +/* + * BPB for DOS 5.0 The difference is bpbHiddenSecs is a short for DOS 3.3, + * and bpbHugeSectors is not in the 3.3 bpb. + */ +struct byte_bpb50 { + int8_t bpbBytesPerSec[2]; /* bytes per sector */ + int8_t bpbSecPerClust; /* sectors per cluster */ + int8_t bpbResSectors[2]; /* number of reserved sectors */ + int8_t bpbFATs; /* number of FATs */ + int8_t bpbRootDirEnts[2]; /* number of root directory entries */ + int8_t bpbSectors[2]; /* total number of sectors */ + int8_t bpbMedia; /* media descriptor */ + int8_t bpbFATsecs[2]; /* number of sectors per FAT */ + int8_t bpbSecPerTrack[2]; /* sectors per track */ + int8_t bpbHeads[2]; /* number of heads */ + int8_t bpbHiddenSecs[4]; /* number of hidden sectors */ + int8_t bpbHugeSectors[4]; /* # of sectors if bpbSectors == 0 */ +}; + +/* + * BPB for DOS 7.10 (FAT32). This one has a few extensions to bpb50. + */ +struct byte_bpb710 { + u_int8_t bpbBytesPerSec[2]; /* bytes per sector */ + u_int8_t bpbSecPerClust; /* sectors per cluster */ + u_int8_t bpbResSectors[2]; /* number of reserved sectors */ + u_int8_t bpbFATs; /* number of FATs */ + u_int8_t bpbRootDirEnts[2]; /* number of root directory entries */ + u_int8_t bpbSectors[2]; /* total number of sectors */ + u_int8_t bpbMedia; /* media descriptor */ + u_int8_t bpbFATsecs[2]; /* number of sectors per FAT */ + u_int8_t bpbSecPerTrack[2]; /* sectors per track */ + u_int8_t bpbHeads[2]; /* number of heads */ + u_int8_t bpbHiddenSecs[4]; /* # of hidden sectors */ + u_int8_t bpbHugeSectors[4]; /* # of sectors if bpbSectors == 0 */ + u_int8_t bpbBigFATsecs[4]; /* like bpbFATsecs for FAT32 */ + u_int8_t bpbExtFlags[2]; /* extended flags: */ + u_int8_t bpbFSVers[2]; /* filesystem version */ + u_int8_t bpbRootClust[4]; /* start cluster for root directory */ + u_int8_t bpbFSInfo[2]; /* filesystem info structure sector */ + u_int8_t bpbBackup[2]; /* backup boot sector */ + /* There is a 12 byte filler here, but we ignore it */ +}; + +/* + * FAT32 FSInfo block. + */ +struct fsinfo { + u_int8_t fsisig1[4]; + u_int8_t fsifill1[480]; + u_int8_t fsisig2[4]; + u_int8_t fsinfree[4]; + u_int8_t fsinxtfree[4]; + u_int8_t fsifill2[12]; + u_int8_t fsisig3[4]; + u_int8_t fsifill3[508]; + u_int8_t fsisig4[4]; +}; \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/msdosfs/denode.h b/lib/libc/include/generic-openbsd/msdosfs/denode.h new file mode 100644 index 000000000000..9c9d54820348 --- /dev/null +++ b/lib/libc/include/generic-openbsd/msdosfs/denode.h @@ -0,0 +1,309 @@ +/* $OpenBSD: denode.h,v 1.36 2022/08/15 01:47:09 jsg Exp $ */ +/* $NetBSD: denode.h,v 1.24 1997/10/17 11:23:39 ws Exp $ */ + +/*- + * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. + * Copyright (C) 1994, 1995, 1997 TooLs GmbH. + * All rights reserved. + * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + */ +/* + * Written by Paul Popelka (paulp@uts.amdahl.com) + * + * You can do anything you want with this software, just don't say you wrote + * it, and don't remove this notice. + * + * This software is provided "as is". + * + * The author supplies this software to be publicly redistributed on the + * understanding that the author is not responsible for the correct + * functioning of this software in any circumstances and is not liable for + * any damages caused by this software. + * + * October 1992 + */ + +/* + * This is the pc filesystem specific portion of the vnode structure. + * + * To describe a file uniquely the de_dirclust, de_diroffset, and + * de_StartCluster fields are used. + * + * de_dirclust contains the cluster number of the directory cluster + * containing the entry for a file or directory. + * de_diroffset is the index into the cluster for the entry describing + * a file or directory. + * de_StartCluster is the number of the first cluster of the file or directory. + * + * Now to describe the quirks of the pc filesystem. + * - Clusters 0 and 1 are reserved. + * - The first allocatable cluster is 2. + * - The root directory is of fixed size and all blocks that make it up + * are contiguous. + * - Cluster 0 refers to the root directory when it is found in the + * startcluster field of a directory entry that points to another directory. + * - Cluster 0 implies a 0 length file when found in the start cluster field + * of a directory entry that points to a file. + * - You can't use the cluster number 0 to derive the address of the root + * directory. + * - Multiple directory entries can point to a directory. The entry in the + * parent directory points to a child directory. Any directories in the + * child directory contain a ".." entry that points back to the parent. + * The child directory itself contains a "." entry that points to itself. + * - The root directory does not contain a "." or ".." entry. + * - Directory entries for directories are never changed once they are created + * (except when removed). The size stays 0, and the last modification time + * is never changed. This is because so many directory entries can point to + * the physical clusters that make up a directory. It would lead to an + * update nightmare. + * - The length field in a directory entry pointing to a directory contains 0 + * (always). The only way to find the end of a directory is to follow the + * cluster chain until the "last cluster" marker is found. + * + * My extensions to make this house of cards work. These apply only to the in + * memory copy of the directory entry. + * - A reference count for each denode will be kept since dos doesn't keep such + * things. + */ + +/* + * Internal pseudo-offset for (nonexistent) directory entry for the root + * dir in the root dir + */ +#define MSDOSFSROOT_OFS 0x1fffffff + +/* + * The fat cache structure. fc_fsrcn is the filesystem relative cluster + * number that corresponds to the file relative cluster number in this + * structure (fc_frcn). + */ +struct fatcache { + uint32_t fc_frcn; /* file relative cluster number */ + uint32_t fc_fsrcn; /* filesystem relative cluster number */ +}; + +/* + * The fat entry cache as it stands helps make extending files a "quick" + * operation by avoiding having to scan the fat to discover the last + * cluster of the file. The cache also helps sequential reads by + * remembering the last cluster read from the file. This also prevents us + * from having to rescan the fat to find the next cluster to read. This + * cache is probably pretty worthless if a file is opened by multiple + * processes. + */ +#define FC_SIZE 3 /* number of entries in the cache */ +#define FC_LASTMAP 0 /* entry the last call to pcbmap() resolved + * to */ +#define FC_LASTFC 1 /* entry for the last cluster in the file */ +#define FC_OLASTFC 2 /* entry for the previous last cluster */ + +#define FCE_EMPTY 0xffffffff /* doesn't represent an actual cluster # */ + +/* + * Set a slot in the fat cache. + */ +#define fc_setcache(dep, slot, frcn, fsrcn) \ + (dep)->de_fc[slot].fc_frcn = frcn; \ + (dep)->de_fc[slot].fc_fsrcn = fsrcn; + +/* + * This is the in memory variant of a dos directory entry. It is usually + * contained within a vnode. + */ +struct denode { + struct denode *de_next; /* Hash chain forward */ + struct denode **de_prev; /* Hash chain back */ + struct vnode *de_vnode; /* addr of vnode we are part of */ + struct vnode *de_devvp; /* vnode of blk dev we live on */ + uint32_t de_flag; /* flag bits */ + dev_t de_dev; /* device where direntry lives */ + uint32_t de_dirclust; /* cluster of the directory file containing this entry */ + uint32_t de_diroffset; /* offset of this entry in the directory cluster */ + uint32_t de_fndoffset; /* offset of found dir entry */ + int de_fndcnt; /* number of slots before de_fndoffset */ + long de_refcnt; /* reference count */ + struct msdosfsmount *de_pmp; /* addr of our mount struct */ + struct lockf_state *de_lockf; /* byte level lock list */ + struct rrwlock de_lock; /* denode lock */ + u_char de_Name[11]; /* name, from DOS directory entry */ + u_char de_Attributes; /* attributes, from directory entry */ + u_char de_CTimeHundredth; /* creation time, 1/100th of a sec */ + u_short de_CTime; /* creation time */ + u_short de_CDate; /* creation date */ + u_short de_ADate; /* access date */ + u_short de_MTime; /* modification time */ + u_short de_MDate; /* modification date */ + uint32_t de_StartCluster; /* starting cluster of file */ + uint32_t de_FileSize; /* size of file in bytes */ + struct fatcache de_fc[FC_SIZE]; /* fat cache */ +}; + +/* + * Values for the de_flag field of the denode. + */ +#define DE_UPDATE 0x0004 /* Modification time update request. */ +#define DE_CREATE 0x0008 /* Creation time update */ +#define DE_ACCESS 0x0010 /* Access time update */ +#define DE_MODIFIED 0x0020 /* Denode has been modified. */ +#define DE_RENAME 0x0040 /* Denode is in the process of being renamed */ + +/* + * Maximum filename length in Win95 + * Note: Must be < sizeof(dirent.d_name) + */ +#define WIN_MAXLEN 255 + +/* Maximum size of a file on a FAT filesystem */ +#define MSDOSFS_FILESIZE_MAX 0xFFFFFFFFLL + +/* + * Transfer directory entries between internal and external form. + * dep is a struct denode * (internal form), + * dp is a struct direntry * (external form). + */ +#define DE_INTERNALIZE32(dep, dp) \ + ((dep)->de_StartCluster |= getushort((dp)->deHighClust) << 16) +#define DE_INTERNALIZE(dep, dp) \ + (bcopy((dp)->deName, (dep)->de_Name, 8), \ + bcopy((dp)->deExtension, (dep)->de_Name + 8, 3), \ + (dep)->de_Attributes = (dp)->deAttributes, \ + (dep)->de_CTimeHundredth = (dp)->deCTimeHundredth, \ + (dep)->de_CTime = getushort((dp)->deCTime), \ + (dep)->de_CDate = getushort((dp)->deCDate), \ + (dep)->de_ADate = getushort((dp)->deADate), \ + (dep)->de_MTime = getushort((dp)->deMTime), \ + (dep)->de_MDate = getushort((dp)->deMDate), \ + (dep)->de_StartCluster = getushort((dp)->deStartCluster), \ + (dep)->de_FileSize = getulong((dp)->deFileSize), \ + (FAT32((dep)->de_pmp) ? DE_INTERNALIZE32((dep), (dp)) : 0)) + +#define DE_EXTERNALIZE(dp, dep) \ + (bcopy((dep)->de_Name, (dp)->deName, 8), \ + bcopy((dep)->de_Name + 8, (dp)->deExtension, 3), \ + (dp)->deAttributes = (dep)->de_Attributes, \ + (dp)->deLowerCase = CASE_LOWER_BASE | CASE_LOWER_EXT, \ + (dp)->deCTimeHundredth = (dep)->de_CTimeHundredth, \ + putushort((dp)->deCTime, (dep)->de_CTime), \ + putushort((dp)->deCDate, (dep)->de_CDate), \ + putushort((dp)->deADate, (dep)->de_ADate), \ + putushort((dp)->deMTime, (dep)->de_MTime), \ + putushort((dp)->deMDate, (dep)->de_MDate), \ + putushort((dp)->deStartCluster, (dep)->de_StartCluster), \ + putulong((dp)->deFileSize, \ + ((dep)->de_Attributes & ATTR_DIRECTORY) ? 0 : (dep)->de_FileSize),\ + putushort((dp)->deHighClust, \ + FAT32((dep)->de_pmp) ? (dep)->de_StartCluster >> 16 : 0)) + +#define de_forw de_chain[0] +#define de_back de_chain[1] + +#define VTODE(vp) ((struct denode *)(vp)->v_data) +#define DETOV(de) ((de)->de_vnode) + +#define DETIMES(dep, acc, mod, cre) \ + if ((dep)->de_flag & (DE_UPDATE | DE_CREATE | DE_ACCESS)) { \ + (dep)->de_flag |= DE_MODIFIED; \ + if ((dep)->de_flag & DE_UPDATE) { \ + unix2dostime((mod), &(dep)->de_MDate, &(dep)->de_MTime, NULL); \ + (dep)->de_Attributes |= ATTR_ARCHIVE; \ + } \ + if (!((dep)->de_pmp->pm_flags & MSDOSFSMNT_NOWIN95)) { \ + if ((dep)->de_flag & DE_ACCESS) \ + unix2dostime((acc), &(dep)->de_ADate, NULL, NULL); \ + if ((dep)->de_flag & DE_CREATE) \ + unix2dostime((cre), &(dep)->de_CDate, &(dep)->de_CTime, &(dep)->de_CTimeHundredth); \ + } \ + (dep)->de_flag &= ~(DE_UPDATE | DE_CREATE | DE_ACCESS); \ + } + +/* + * This overlays the fid structure (see mount.h) + */ +struct defid { + u_short defid_len; /* length of structure */ + u_short defid_pad; /* force long alignment */ + + uint32_t defid_dirclust; /* cluster this dir entry came from */ + uint32_t defid_dirofs; /* offset of entry within the cluster */ +#if 0 + uint32_t defid_gen; /* generation number */ +#endif +}; + + +#ifdef _KERNEL +/* + * Prototypes for MSDOSFS vnode operations + */ +int msdosfs_lookup(void *); +int msdosfs_create(void *); +int msdosfs_mknod(void *); +int msdosfs_open(void *); +int msdosfs_close(void *); +int msdosfs_access(void *); +int msdosfs_getattr(void *); +int msdosfs_setattr(void *); +int msdosfs_read(void *); +int msdosfs_write(void *); +int msdosfs_ioctl(void *); +int msdosfs_fsync(void *); +int msdosfs_remove(void *); +int msdosfs_link(void *); +int msdosfs_rename(void *); +int msdosfs_mkdir(void *); +int msdosfs_rmdir(void *); +int msdosfs_symlink(void *); +int msdosfs_readdir(void *); +int msdosfs_readlink(void *); +int msdosfs_inactive(void *); +int msdosfs_reclaim(void *); +int msdosfs_lock(void *); +int msdosfs_unlock(void *); +int msdosfs_bmap(void *); +int msdosfs_strategy(void *); +int msdosfs_print(void *); +int msdosfs_islocked(void *); +int msdosfs_advlock(void *); +int msdosfs_pathconf(void *); + +/* + * Internal service routine prototypes. + */ +int createde(struct denode *, struct denode *, struct denode **, struct componentname *); +int deextend(struct denode *, uint32_t, struct ucred *); +int deget(struct msdosfsmount *, uint32_t, uint32_t, struct denode **); +int detrunc(struct denode *, uint32_t, int, struct ucred *, struct proc *); +int deupdat(struct denode *, int); +int doscheckpath(struct denode *, struct denode *); +int dosdirempty(struct denode *); +int readde(struct denode *, struct buf **, struct direntry **); +int readep(struct msdosfsmount *, uint32_t, uint32_t, struct buf **, struct direntry **); +void reinsert(struct denode *); +int removede(struct denode *, struct denode *); +int uniqdosname(struct denode *, struct componentname *, u_char *); +#endif /* _KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/msdosfs/direntry.h b/lib/libc/include/generic-openbsd/msdosfs/direntry.h new file mode 100644 index 000000000000..628bffa15f31 --- /dev/null +++ b/lib/libc/include/generic-openbsd/msdosfs/direntry.h @@ -0,0 +1,134 @@ +/* $OpenBSD: direntry.h,v 1.8 2021/12/23 02:12:52 jsg Exp $ */ +/* $NetBSD: direntry.h,v 1.13 1997/10/17 11:23:45 ws Exp $ */ + +/*- + * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. + * Copyright (C) 1994, 1995, 1997 TooLs GmbH. + * All rights reserved. + * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + */ +/* + * Written by Paul Popelka (paulp@uts.amdahl.com) + * + * You can do anything you want with this software, just don't say you wrote + * it, and don't remove this notice. + * + * This software is provided "as is". + * + * The author supplies this software to be publicly redistributed on the + * understanding that the author is not responsible for the correct + * functioning of this software in any circumstances and is not liable for + * any damages caused by this software. + * + * October 1992 + */ + +/* + * Structure of a dos directory entry. + */ +struct direntry { + u_int8_t deName[8]; /* filename, blank filled */ +#define SLOT_EMPTY 0x00 /* slot has never been used */ +#define SLOT_E5 0x05 /* the real value is 0xe5 */ +#define SLOT_DELETED 0xe5 /* file in this slot deleted */ + u_int8_t deExtension[3]; /* extension, blank filled */ + u_int8_t deAttributes; /* file attributes */ +#define ATTR_NORMAL 0x00 /* normal file */ +#define ATTR_READONLY 0x01 /* file is readonly */ +#define ATTR_HIDDEN 0x02 /* file is hidden */ +#define ATTR_SYSTEM 0x04 /* file is a system file */ +#define ATTR_VOLUME 0x08 /* entry is a volume label */ +#define ATTR_DIRECTORY 0x10 /* entry is a directory name */ +#define ATTR_ARCHIVE 0x20 /* file is new or modified */ + u_int8_t deLowerCase; /* case for base and extension */ +#define CASE_LOWER_BASE 0x08 /* base is lower case */ +#define CASE_LOWER_EXT 0x10 /* extension is lower case */ + u_int8_t deCTimeHundredth; /* create time, 1/100th of a sec */ + u_int8_t deCTime[2]; /* create time */ + u_int8_t deCDate[2]; /* create date */ + u_int8_t deADate[2]; /* access date */ + u_int8_t deHighClust[2]; /* high byte of cluster number */ + u_int8_t deMTime[2]; /* last update time */ + u_int8_t deMDate[2]; /* last update date */ + u_int8_t deStartCluster[2]; /* starting cluster of file */ + u_int8_t deFileSize[4]; /* size of file in bytes */ +}; + +/* + * Structure of a Win95 long name directory entry + */ +struct winentry { + u_int8_t weCnt; +#define WIN_LAST 0x40 +#define WIN_CNT 0x3f + u_int8_t wePart1[10]; + u_int8_t weAttributes; +#define ATTR_WIN95 0x0f + u_int8_t weReserved1; + u_int8_t weChksum; + u_int8_t wePart2[12]; + u_int16_t weReserved2; + u_int8_t wePart3[4]; +}; +#define WIN_CHARS 13 /* Number of chars per winentry */ + +/* + * This is the format of the contents of the deTime field in the direntry + * structure. + * We don't use bitfields because we don't know how compilers for + * arbitrary machines will lay them out. + */ +#define DT_2SECONDS_MASK 0x1F /* seconds divided by 2 */ +#define DT_2SECONDS_SHIFT 0 +#define DT_MINUTES_MASK 0x7E0 /* minutes */ +#define DT_MINUTES_SHIFT 5 +#define DT_HOURS_MASK 0xF800 /* hours */ +#define DT_HOURS_SHIFT 11 + +/* + * This is the format of the contents of the deDate field in the direntry + * structure. + */ +#define DD_DAY_MASK 0x1F /* day of month */ +#define DD_DAY_SHIFT 0 +#define DD_MONTH_MASK 0x1E0 /* month */ +#define DD_MONTH_SHIFT 5 +#define DD_YEAR_MASK 0xFE00 /* year - 1980 */ +#define DD_YEAR_SHIFT 9 + +#ifdef _KERNEL +void unix2dostime(struct timespec *tsp, u_int16_t *ddp, u_int16_t *dtp, u_int8_t *dhp); +void dos2unixtime(u_int dd, u_int dt, u_int dh, struct timespec *tsp); +int dos2unixfn(u_char dn[11], u_char *un, int lower); +int unix2dosfn(u_char *un, u_char dn[11], int unlen, u_int gen); +int unix2winfn(u_char *un, int unlen, struct winentry *wep, int cnt, int chksum); +int winChkName(u_char *un, int unlen, struct winentry *wep, int chksum); +int win2unixfn(struct winentry *wep, struct dirent *dp, int chksum); +u_int8_t winChksum(u_int8_t *name); +int winSlotCnt(u_char *un, int unlen); +#endif /* _KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/msdosfs/fat.h b/lib/libc/include/generic-openbsd/msdosfs/fat.h new file mode 100644 index 000000000000..08ee18a5cb80 --- /dev/null +++ b/lib/libc/include/generic-openbsd/msdosfs/fat.h @@ -0,0 +1,105 @@ +/* $OpenBSD: fat.h,v 1.13 2021/07/11 04:34:13 jsg Exp $ */ +/* $NetBSD: fat.h,v 1.11 1997/10/17 11:23:49 ws Exp $ */ + +/*- + * Copyright (C) 1994, 1997 Wolfgang Solfrank. + * Copyright (C) 1994, 1997 TooLs GmbH. + * All rights reserved. + * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + */ +/* + * Written by Paul Popelka (paulp@uts.amdahl.com) + * + * You can do anything you want with this software, just don't say you wrote + * it, and don't remove this notice. + * + * This software is provided "as is". + * + * The author supplies this software to be publicly redistributed on the + * understanding that the author is not responsible for the correct + * functioning of this software in any circumstances and is not liable for + * any damages caused by this software. + * + * October 1992 + */ + +/* + * Some useful cluster numbers. + */ +#define MSDOSFSROOT 0 /* cluster 0 means the root dir */ +#define CLUST_FREE 0 /* cluster 0 also means a free cluster */ +#define MSDOSFSFREE CLUST_FREE +#define CLUST_FIRST 2 /* first legal cluster number */ +#define CLUST_RSRVD 0xfffffff6 /* reserved cluster range */ +#define CLUST_BAD 0xfffffff7 /* a cluster with a defect */ +#define CLUST_EOFS 0xfffffff8 /* start of eof cluster range */ +#define CLUST_EOFE 0xffffffff /* end of eof cluster range */ +#define CLUST_END CLUST_EOFE /* bigger than any valid cluster */ + +#define FAT12_MASK 0x00000fff /* mask for 12 bit cluster numbers */ +#define FAT16_MASK 0x0000ffff /* mask for 16 bit cluster numbers */ +#define FAT32_MASK 0x0fffffff /* mask for FAT32 cluster numbers */ + +/* + * MSDOSFS: + * Return true if filesystem uses 12 bit fats. Microsoft Programmer's + * Reference says if the maximum cluster number in a filesystem is greater + * than 4084 ((CLUST_RSRVD - CLUST_FIRST) & FAT12_MASK) then we've got a + * 16 bit fat filesystem. While mounting, the result of this test is stored + * in pm_fatentrysize. + */ +#define FAT12(pmp) (pmp->pm_fatmask == FAT12_MASK) +#define FAT16(pmp) (pmp->pm_fatmask == FAT16_MASK) +#define FAT32(pmp) (pmp->pm_fatmask == FAT32_MASK) + +#define MSDOSFSEOF(pmp, cn) ((((cn) | ~(pmp)->pm_fatmask) & CLUST_EOFS) == CLUST_EOFS) + +#ifdef _KERNEL +/* + * These are the values for the function argument to the function + * fatentry(). + */ +#define FAT_GET 0x0001 /* get a fat entry */ +#define FAT_SET 0x0002 /* set a fat entry */ +#define FAT_GET_AND_SET (FAT_GET | FAT_SET) + +/* + * Flags to extendfile: + */ +#define DE_CLEAR 1 /* Zero out the blocks allocated */ + +int pcbmap(struct denode *, uint32_t, daddr_t *, uint32_t *, int *); +int clusterfree(struct msdosfsmount *, uint32_t, uint32_t *); +int clusteralloc(struct msdosfsmount *, uint32_t, uint32_t, uint32_t *, uint32_t *); +int extendfile(struct denode *, uint32_t, struct buf **, uint32_t *, int); +int fatentry(int, struct msdosfsmount *, uint32_t, uint32_t *, uint32_t); +void fc_purge(struct denode *, u_int); +void fc_lookup(struct denode *, uint32_t, uint32_t *, uint32_t *); +int fillinusemap(struct msdosfsmount *); +int freeclusterchain(struct msdosfsmount *, uint32_t); +#endif /* _KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/msdosfs/msdosfsmount.h b/lib/libc/include/generic-openbsd/msdosfs/msdosfsmount.h new file mode 100644 index 000000000000..245ef0d4711f --- /dev/null +++ b/lib/libc/include/generic-openbsd/msdosfs/msdosfsmount.h @@ -0,0 +1,211 @@ +/* $OpenBSD: msdosfsmount.h,v 1.23 2024/05/13 01:15:53 jsg Exp $ */ +/* $NetBSD: msdosfsmount.h,v 1.16 1997/10/17 11:24:24 ws Exp $ */ + +/*- + * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. + * Copyright (C) 1994, 1995, 1997 TooLs GmbH. + * All rights reserved. + * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + */ +/* + * Written by Paul Popelka (paulp@uts.amdahl.com) + * + * You can do anything you want with this software, just don't say you wrote + * it, and don't remove this notice. + * + * This software is provided "as is". + * + * The author supplies this software to be publicly redistributed on the + * understanding that the author is not responsible for the correct + * functioning of this software in any circumstances and is not liable for + * any damages caused by this software. + * + * October 1992 + */ + +/* + * Layout of the mount control block for a msdos file system. + */ +struct msdosfsmount { + struct mount *pm_mountp;/* vfs mount struct for this fs */ + dev_t pm_dev; /* block special device mounted */ + uid_t pm_uid; /* uid to set as owner of the files */ + gid_t pm_gid; /* gid to set as owner of the files */ + mode_t pm_mask; /* mask to and with file protection bits */ + struct vnode *pm_devvp; /* vnode for block device mntd */ + struct bpb50 pm_bpb; /* BIOS parameter blk for this fs */ + uint32_t pm_BlkPerSec; /* # of DEV_BSIZE blocks in MSDOSFS sector */ + uint32_t pm_FATsecs; /* actual number of fat sectors */ + uint32_t pm_fatblk; /* block # of first FAT */ + uint32_t pm_rootdirblk; /* block # (cluster # for FAT32) of root directory number */ + uint32_t pm_rootdirsize; /* size in blocks (not clusters) */ + uint32_t pm_firstcluster; /* block number of first cluster */ + uint32_t pm_nmbrofclusters; /* # of clusters in filesystem */ + uint32_t pm_maxcluster; /* maximum cluster number */ + uint32_t pm_freeclustercount; /* number of free clusters */ + uint32_t pm_cnshift; /* shift file offset right this amount to get a cluster number */ + uint32_t pm_crbomask; /* and a file offset with this mask to get cluster rel offset */ + uint32_t pm_bnshift; /* shift file offset right this amount to get a block number */ + uint32_t pm_bpcluster; /* bytes per cluster */ + uint32_t pm_fmod; /* ~0 if fs is modified, this can rollover to 0 */ + uint32_t pm_fatblocksize; /* size of fat blocks in bytes */ + uint32_t pm_fatblocksec; /* size of fat blocks in sectors */ + uint32_t pm_fatsize; /* size of fat in bytes */ + uint32_t pm_fatmask; /* mask to use for fat numbers */ + uint32_t pm_fsinfo; /* fsinfo block number */ + u_int pm_fatmult; /* these 2 values are used in fat */ + u_int pm_fatdiv; /* offset computation */ + u_int pm_curfat; /* current fat for FAT32 (0 otherwise) */ + u_int *pm_inusemap; /* ptr to bitmap of in-use clusters */ + u_int pm_flags; /* see below */ + struct netexport pm_export; /* export information */ +}; +/* Byte offset in FAT on filesystem pmp, cluster cn */ +#define FATOFS(pmp, cn) ((cn) * (pmp)->pm_fatmult / (pmp)->pm_fatdiv) + +/* + * Mount point flags: + */ +#if 0 + /* Defined in */ +#define MSDOSFSMNT_SHORTNAME 0x01 +#define MSDOSFSMNT_LONGNAME 0x02 +#define MSDOSFSMNT_NOWIN95 0x04 +#endif + +/* All flags above: */ +#define MSDOSFSMNT_MNTOPT \ + (MSDOSFSMNT_SHORTNAME|MSDOSFSMNT_LONGNAME|MSDOSFSMNT_NOWIN95) +#define MSDOSFSMNT_RONLY 0x80000000 /* mounted read-only */ +#define MSDOSFSMNT_WAITONFAT 0x40000000 /* mounted synchronous */ +#define MSDOSFS_FATMIRROR 0x20000000 /* FAT is mirrored */ + +#define VFSTOMSDOSFS(mp) ((struct msdosfsmount *)mp->mnt_data) + +/* Number of bits in one pm_inusemap item: */ +#define N_INUSEBITS (8 * sizeof(u_int)) + +/* + * Shorthand for fields in the bpb contained in the msdosfsmount structure. + */ +#define pm_BytesPerSec pm_bpb.bpbBytesPerSec +#define pm_ResSectors pm_bpb.bpbResSectors +#define pm_FATs pm_bpb.bpbFATs +#define pm_RootDirEnts pm_bpb.bpbRootDirEnts +#define pm_Sectors pm_bpb.bpbSectors +#define pm_Media pm_bpb.bpbMedia +#define pm_SecPerTrack pm_bpb.bpbSecPerTrack +#define pm_Heads pm_bpb.bpbHeads +#define pm_HiddenSects pm_bpb.bpbHiddenSecs +#define pm_HugeSectors pm_bpb.bpbHugeSectors + +/* + * Convert pointer to buffer -> pointer to direntry + */ +#define bptoep(pmp, bp, dirofs) \ + ((struct direntry *)(((bp)->b_data) \ + + ((dirofs) & (pmp)->pm_crbomask))) + +/* + * Convert block number to cluster number + */ +#define de_bn2cn(pmp, bn) \ + ((bn) >> ((pmp)->pm_cnshift - (pmp)->pm_bnshift)) + +/* + * Convert cluster number to block number + */ +#define de_cn2bn(pmp, cn) \ + ((cn) << ((pmp)->pm_cnshift - (pmp)->pm_bnshift)) + +/* + * Convert file offset to cluster number + */ +#define de_cluster(pmp, off) \ + ((off) >> (pmp)->pm_cnshift) + +/* + * Clusters required to hold size bytes + */ +#define de_clcount(pmp, size) \ + (((size) + (pmp)->pm_bpcluster - 1) >> (pmp)->pm_cnshift) + +/* + * Convert file offset to block number + */ +#define de_blk(pmp, off) \ + (de_cn2bn(pmp, de_cluster((pmp), (off)))) + +/* + * Convert cluster number to file offset + */ +#define de_cn2off(pmp, cn) \ + ((cn) << (pmp)->pm_cnshift) + +/* + * Convert block number to file offset + */ +#define de_bn2off(pmp, bn) \ + ((bn) << (pmp)->pm_bnshift) +/* + * Map a cluster number into a filesystem relative block number. + */ +#define cntobn(pmp, cn) \ + (de_cn2bn((pmp), (cn)-CLUST_FIRST) + (pmp)->pm_firstcluster) + +/* + * Calculate block number for directory entry in root dir, offset dirofs + */ +#define roottobn(pmp, dirofs) \ + (de_blk((pmp), (dirofs)) + (pmp)->pm_rootdirblk) + +/* + * Calculate block number for directory entry at cluster dirclu, offset + * dirofs + */ +#define detobn(pmp, dirclu, dirofs) \ + ((dirclu) == MSDOSFSROOT \ + ? roottobn((pmp), (dirofs)) \ + : cntobn((pmp), (dirclu))) + +/* Calculate size of fsinfo block */ +#define fsi_size(pmp) \ + (1024 << ((pmp)->pm_BlkPerSec >> 2)) + +/* + * Prototypes for MSDOSFS virtual filesystem operations + */ +int msdosfs_mount(struct mount *, const char *, void *, struct nameidata *, struct proc *); +int msdosfs_start(struct mount *, int, struct proc *); +int msdosfs_unmount(struct mount *, int, struct proc *); +int msdosfs_root(struct mount *, struct vnode **); +int msdosfs_statfs(struct mount *, struct statfs *, struct proc *); +int msdosfs_sync(struct mount *, int, int, struct ucred *, struct proc *); +int msdosfs_fhtovp(struct mount *, struct fid *, struct vnode **); +int msdosfs_vptofh(struct vnode *, struct fid *); +int msdosfs_init(struct vfsconf *); \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ndbm.h b/lib/libc/include/generic-openbsd/ndbm.h new file mode 100644 index 000000000000..e0cb4db1582e --- /dev/null +++ b/lib/libc/include/generic-openbsd/ndbm.h @@ -0,0 +1,78 @@ +/* $OpenBSD: ndbm.h,v 1.6 2004/05/03 17:27:50 millert Exp $ */ +/* $NetBSD: ndbm.h,v 1.6 1995/07/20 23:31:11 jtc Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ndbm.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _NDBM_H_ +#define _NDBM_H_ + +#include + +/* Map dbm interface onto db(3). */ +#define DBM_RDONLY O_RDONLY + +/* Flags to dbm_store(). */ +#define DBM_INSERT 0 +#define DBM_REPLACE 1 + +/* + * The db(3) support for ndbm(3) always appends this suffix to the + * file name to avoid overwriting the user's original database. + */ +#define DBM_SUFFIX ".db" + +typedef struct { + void *dptr; + size_t dsize; +} datum; + +typedef DB DBM; +#define dbm_pagfno(a) DBM_PAGFNO_NOT_AVAILABLE + +__BEGIN_DECLS +int dbm_clearerr(DBM *); +void dbm_close(DBM *); +int dbm_delete(DBM *, datum); +int dbm_error(DBM *); +datum dbm_fetch(DBM *, datum); +datum dbm_firstkey(DBM *); +datum dbm_nextkey(DBM *); +DBM *dbm_open(const char *, int, mode_t); +int dbm_store(DBM *, datum, datum, int); +int dbm_dirfno(DBM *); +int dbm_rdonly(DBM *); +__END_DECLS + +#endif /* !_NDBM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/art.h b/lib/libc/include/generic-openbsd/net/art.h new file mode 100644 index 000000000000..bf621de83014 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/art.h @@ -0,0 +1,169 @@ +/* $OpenBSD: art.h,v 1.28 2025/07/10 05:28:13 dlg Exp $ */ + +/* + * Copyright (c) 2015 Martin Pieuchot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _NET_ART_H_ +#define _NET_ART_H_ + +/* + * Allotment Routing Table (ART) + * + * Yoichi Hariguchi paper can be found at: + * http://www.hariguchi.org/art/art.pdf + * + * Locking: + * + * Modification (ie, art_insert or art_delete) and iteration + * (art_iter_next, etc) over the ART must be serialised by the caller. + * Lookups (ie, art_match and art_lookup) run within an SMR critical + * section. + * + * Iteration requires serialisation as it manipulates the reference + * counts on tables as it traverses the tree. The iterator maintains + * these references until it runs out of entries. This allows code + * iterating over the ART to release locks in between calls to + * art_iter_open and art_iter_next. The references may be dropped + * early with art_iter_close. + * + * Note, the iterator does not hold a reference to the art_node + * structure or the data hanging off the an_value pointer, they must + * be accounted for separately or their use must be serialised with + * art_delete. + */ + +typedef uintptr_t art_heap_entry; + +/* + * Root of the ART, equivalent to the radix head. + */ + +struct art { + art_heap_entry *art_root; + const unsigned int *art_levels; + unsigned int art_nlevels; + unsigned int art_alen; +}; + +/* + * Allotment Table. + */ +struct art_table { + art_heap_entry *at_heap; + struct art_table *at_parent; /* Parent table */ + + unsigned int at_index; /* Index in the parent table */ + unsigned int at_minfringe; /* Index that fringe begins */ + + unsigned int at_level; /* Level of the table */ + unsigned int at_bits; /* Stride length of the table */ + unsigned int at_offset; /* Sum of parents' stride len */ + + unsigned int at_refcnt; +}; + +#define ART_HEAP_IDX_TABLE 0 +#define ART_HEAP_IDX_DEFAULT 1 + +#define AT_HEAPSIZE(bits) ((1 << ((bits) + 1)) * sizeof(art_heap_entry)) + +/* + * A node is the internal representation of a route entry. + */ +struct art_node { + void *an_value; + union { + struct art_node *an__gc; + uint8_t an__addr[16]; + } an__u; +#define an_gc an__u.an__gc +#define an_addr an__u.an__addr + unsigned int an_plen; +}; + +static inline struct art_table * +art_heap_to_table(art_heap_entry *heap) +{ + return ((struct art_table *)heap[ART_HEAP_IDX_TABLE]); +} + +static inline int +art_heap_entry_is_node(art_heap_entry ahe) +{ + return ((ahe & 1UL) == 0); +} + +static inline struct art_node * +art_heap_entry_to_node(art_heap_entry ahe) +{ + return ((struct art_node *)ahe); +} + +static inline art_heap_entry * +art_heap_entry_to_heap(art_heap_entry ahe) +{ + return ((art_heap_entry *)(ahe & ~1UL)); +} + +static inline art_heap_entry +art_node_to_heap_entry(struct art_node *an) +{ + return ((art_heap_entry)an); +} + +static inline art_heap_entry +art_heap_to_heap_entry(art_heap_entry *heap) +{ + return ((art_heap_entry)heap | 1UL); +} + +#ifdef _KERNEL +void art_boot(void); +struct art *art_alloc(unsigned int); +void art_init(struct art *, unsigned int); +struct art_node *art_insert(struct art *, struct art_node *); +struct art_node *art_delete(struct art *, const void *, unsigned int); +struct art_node *art_match(struct art *, const void *); +struct art_node *art_lookup(struct art *, const void *, unsigned int); +int art_is_empty(struct art *); + +struct art_node *art_get(const uint8_t *, unsigned int); +void art_node_init(struct art_node *, + const uint8_t *, unsigned int); +void art_put(struct art_node *); + +struct art_iter { + struct art *ai_art; + struct art_table *ai_table; + unsigned int ai_j; + unsigned int ai_i; +}; + +struct art_node *art_iter_open(struct art *, struct art_iter *); +struct art_node *art_iter_next(struct art_iter *); +void art_iter_close(struct art_iter *); + +#define ART_FOREACH(_an, _art, _ai) \ + for ((_an) = art_iter_open((_art), (_ai)); \ + (_an) != NULL; \ + (_an) = art_iter_next((_ai))) + +int art_walk(struct art *, + int (*)(struct art_node *, void *), void *); + +#endif /* _KERNEL */ + +#endif /* _NET_ART_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/bfd.h b/lib/libc/include/generic-openbsd/net/bfd.h new file mode 100644 index 000000000000..5319f356a29c --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/bfd.h @@ -0,0 +1,163 @@ +/* $OpenBSD: bfd.h,v 1.14 2025/07/24 00:49:22 jsg Exp $ */ + +/* + * Copyright (c) 2016 Peter Hessler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Support for Bi-directional Forwarding Detection (RFC 5880 / 5881) + */ + +#ifndef _NET_BFD_H_ +#define _NET_BFD_H_ + +/* Public Interface */ + +#define BFD_MODE_ASYNC 1 +#define BFD_MODE_DEMAND 2 + +/* Diagnostic Code (RFC 5880 Page 8) */ +#define BFD_DIAG_NONE 0 +#define BFD_DIAG_EXPIRED 1 +#define BFD_DIAG_ECHO_FAILED 2 +#define BFD_DIAG_NEIGHBOR_SIGDOWN 3 +#define BFD_DIAG_FIB_RESET 4 +#define BFD_DIAG_PATH_DOWN 5 +#define BFD_DIAG_CONCAT_PATH_DOWN 6 +#define BFD_DIAG_ADMIN_DOWN 7 +#define BFD_DIAG_CONCAT_REVERSE_DOWN 8 + +/* State (RFC 5880 Page 8) */ +#define BFD_STATE_ADMINDOWN 0 +#define BFD_STATE_DOWN 1 +#define BFD_STATE_INIT 2 +#define BFD_STATE_UP 3 + +/* Flags (RFC 5880 Page 8) */ +#define BFD_FLAG_P 0x20 +#define BFD_FLAG_F 0x10 +#define BFD_FLAG_C 0x08 +#define BFD_FLAG_A 0x04 +#define BFD_FLAG_D 0x02 +#define BFD_FLAG_M 0x01 + +struct sockaddr_bfd { + uint8_t bs_len; /* total length */ + uint8_t bs_family; /* address family */ + /* above matches sockaddr_storage */ + + /* Sorted for bit boundaries */ + uint16_t bs_mode; + uint32_t bs_localdiscr; + + int64_t bs_uptime; + + int64_t bs_lastuptime; + + uint32_t bs_mintx; + uint32_t bs_minrx; + + uint32_t bs_minecho; + uint32_t bs_localdiag; + + uint32_t bs_remotediscr; + uint32_t bs_remotediag; + + uint16_t bs_multiplier; + uint16_t bs_pad0; + unsigned int bs_state; + unsigned int bs_remotestate; + unsigned int bs_laststate; + unsigned int bs_error; + + /* add padding to reach a power of two */ + uint64_t bs_pad1; +}; + +struct bfd_msghdr { + uint16_t bm_msglen; + uint8_t bm_version; + uint8_t bm_type; + uint16_t bm_hdrlen; + uint16_t bm_index; + + uint16_t bm_tableid; + uint8_t bm_priority; + uint8_t bm_mpls; + int bm_addrs; + int bm_flags; + /* above matches rt_msghdr */ + uint16_t bm_pad0; /* for 4 byte boundary */ + + struct sockaddr_bfd bm_sa; /* bfd msg for userland */ +}; + +#ifdef _KERNEL +/* state machine from RFC 5880 6.8.1*/ +struct bfd_neighbor { + uint32_t bn_lstate; /* SessionState */ + uint32_t bn_rstate; /* RemoteSessionState */ + uint32_t bn_ldiscr; /* LocalDiscr */ + uint32_t bn_rdiscr; /* RemoteDiscr */ + uint32_t bn_ldiag; /* LocalDiag */ + uint32_t bn_rdiag; /* RemoteDiag */ + uint32_t bn_mintx; /* DesiredMinTxInterval */ + uint32_t bn_req_minrx; /* RequiredMinRxInterval */ + uint32_t bn_rminrx; /* RemoteMinRxInterval */ + uint32_t bn_demand; /* DemandMode */ + uint32_t bn_rdemand; /* RemoteDemandMode */ + uint32_t bn_authtype; /* AuthType */ + uint32_t bn_rauthseq; /* RcvAuthSeq */ + uint32_t bn_lauthseq; /* XmitAuthSeq */ + uint32_t bn_authseqknown; /* AuthSeqKnown */ + uint16_t bn_mult; /* DetectMult */ +}; + +struct bfd_config { + TAILQ_ENTRY(bfd_config) bc_entry; + struct socket *bc_so; + struct socket *bc_upcallso; + struct socket *bc_soecho; + struct socket *bc_sosend; + struct rtentry *bc_rt; + struct bfd_neighbor *bc_neighbor; + struct timeval *bc_time; + struct task bc_bfd_task; + struct task bc_bfd_send_task; + struct task bc_upcall_task; + struct task bc_clear_task; + struct timeout bc_timo_rx; + struct timeout bc_timo_tx; + time_t bc_lastuptime; + unsigned int bc_laststate; + unsigned int bc_state; + unsigned int bc_poll; + unsigned int bc_error; + uint32_t bc_minrx; + uint32_t bc_mintx; + uint32_t bc_minecho; + uint16_t bc_multiplier; + uint16_t bc_mode; +}; + +struct sockaddr *bfd2sa(const struct rtentry *, struct sockaddr_bfd *); + +int bfdset(struct rtentry *); +void bfdclear(struct rtentry *); +void bfdinit(void); + +#endif /* _KERNEL */ + +#endif /* _NET_BFD_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/bpf.h b/lib/libc/include/generic-openbsd/net/bpf.h new file mode 100644 index 000000000000..d549a0b2e33b --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/bpf.h @@ -0,0 +1,342 @@ +/* $OpenBSD: bpf.h,v 1.74 2025/03/04 01:01:25 dlg Exp $ */ +/* $NetBSD: bpf.h,v 1.15 1996/12/13 07:57:33 mikel Exp $ */ + +/* + * Copyright (c) 1990, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from the Stanford/CMU enet packet filter, + * (net/enet.c) distributed as part of 4.3BSD, and code contributed + * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence + * Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)bpf.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NET_BPF_H_ +#define _NET_BPF_H_ + +/* BSD style release date */ +#define BPF_RELEASE 199606 + +typedef int32_t bpf_int32; +typedef u_int32_t bpf_u_int32; +/* + * Alignment macros. BPF_WORDALIGN rounds up to the next even multiple of + * BPF_ALIGNMENT (which is at least as much as what a timeval needs). + */ +#define BPF_ALIGNMENT sizeof(u_int32_t) +#define BPF_WORDALIGN(x) (((x) + (BPF_ALIGNMENT - 1)) & ~(BPF_ALIGNMENT - 1)) + +#define BPF_MAXINSNS 512 +#define BPF_MAXBUFSIZE (2 * 1024 * 1024) +#define BPF_MINBUFSIZE 32 + +/* + * Structure for BIOCSETF. + */ +struct bpf_program { + u_int bf_len; + struct bpf_insn *bf_insns; +}; + +/* + * Struct returned by BIOCGSTATS. + */ +struct bpf_stat { + u_int bs_recv; /* number of packets received */ + u_int bs_drop; /* number of packets dropped */ +}; + +/* + * Struct return by BIOCVERSION. This represents the version number of + * the filter language described by the instruction encodings below. + * bpf understands a program iff kernel_major == filter_major && + * kernel_minor >= filter_minor, that is, if the value returned by the + * running kernel has the same major number and a minor number equal + * equal to or less than the filter being downloaded. Otherwise, the + * results are undefined, meaning an error may be returned or packets + * may be accepted haphazardly. + * It has nothing to do with the source code version. + */ +struct bpf_version { + u_short bv_major; + u_short bv_minor; +}; +/* Current version number of filter architecture. */ +#define BPF_MAJOR_VERSION 1 +#define BPF_MINOR_VERSION 1 + +/* + * BPF ioctls + */ +#define BIOCGBLEN _IOR('B',102, u_int) +#define BIOCSBLEN _IOWR('B',102, u_int) +#define BIOCSETF _IOW('B',103, struct bpf_program) +#define BIOCFLUSH _IO('B',104) +#define BIOCPROMISC _IO('B',105) +#define BIOCGDLT _IOR('B',106, u_int) +#define BIOCGETIF _IOR('B',107, struct ifreq) +#define BIOCSETIF _IOW('B',108, struct ifreq) +#define BIOCSRTIMEOUT _IOW('B',109, struct timeval) +#define BIOCGRTIMEOUT _IOR('B',110, struct timeval) +#define BIOCGSTATS _IOR('B',111, struct bpf_stat) +#define BIOCIMMEDIATE _IOW('B',112, u_int) +#define BIOCVERSION _IOR('B',113, struct bpf_version) +#define BIOCSRSIG _IOW('B',114, u_int) +#define BIOCGRSIG _IOR('B',115, u_int) +#define BIOCGHDRCMPLT _IOR('B',116, u_int) +#define BIOCSHDRCMPLT _IOW('B',117, u_int) +#define BIOCLOCK _IO('B',118) +#define BIOCSETWF _IOW('B',119, struct bpf_program) +#define BIOCGFILDROP _IOR('B',120, u_int) +#define BIOCSFILDROP _IOW('B',121, u_int) +#define BIOCSDLT _IOW('B',122, u_int) +#define BIOCGDLTLIST _IOWR('B',123, struct bpf_dltlist) +#define BIOCGDIRFILT _IOR('B',124, u_int) +#define BIOCSDIRFILT _IOW('B',125, u_int) +#define BIOCSWTIMEOUT _IOW('B',126, struct timeval) +#define BIOCGWTIMEOUT _IOR('B',126, struct timeval) +#define BIOCDWTIMEOUT _IO('B',126) +#define BIOCSETFNR _IOW('B',127, struct bpf_program) + +/* + * Direction filters for BIOCSDIRFILT/BIOCGDIRFILT + */ +#define BPF_DIRECTION_IN (1 << 0) +#define BPF_DIRECTION_OUT (1 << 1) + +/* + * Values for BIOCGFILDROP/BIOCSFILDROP + */ +#define BPF_FILDROP_PASS 0 /* capture, pass */ +#define BPF_FILDROP_CAPTURE 1 /* capture, drop */ +#define BPF_FILDROP_DROP 2 /* no capture, drop */ + +struct bpf_timeval { + u_int32_t tv_sec; + u_int32_t tv_usec; +}; + +/* + * Structure prepended to each packet. + */ +struct bpf_hdr { + struct bpf_timeval bh_tstamp; /* time stamp */ + u_int32_t bh_caplen; /* length of captured portion */ + u_int32_t bh_datalen; /* original length of packet */ + u_int16_t bh_hdrlen; /* length of bpf header (this struct + plus alignment padding) */ + u_int16_t bh_ifidx; /* receive interface index */ + + u_int16_t bh_flowid; + u_int8_t bh_flags; +#define BPF_F_PRI_MASK 0x07 +#define BPF_F_FLOWID 0x08 +#define BPF_F_DIR_SHIFT 4 +#define BPF_F_DIR_MASK (0x3 << BPF_F_DIR_SHIFT) +#define BPF_F_DIR_IN (BPF_DIRECTION_IN << BPF_F_DIR_SHIFT) +#define BPF_F_DIR_OUT (BPF_DIRECTION_OUT << BPF_F_DIR_SHIFT) + u_int8_t bh_drops; + u_int16_t bh_csumflags; /* checksum flags */ +}; + +#ifdef _KERNEL +#define SIZEOF_BPF_HDR sizeof(struct bpf_hdr) +#endif + +/* + * Data-link level type codes. + */ +#define DLT_NULL 0 /* no link-layer encapsulation */ +#define DLT_EN10MB 1 /* Ethernet (10Mb) */ +#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */ +#define DLT_AX25 3 /* Amateur Radio AX.25 */ +#define DLT_PRONET 4 /* Proteon ProNET Token Ring */ +#define DLT_CHAOS 5 /* Chaos */ +#define DLT_IEEE802 6 /* IEEE 802 Networks */ +#define DLT_ARCNET 7 /* ARCNET */ +#define DLT_SLIP 8 /* Serial Line IP */ +#define DLT_PPP 9 /* Point-to-point Protocol */ +#define DLT_FDDI 10 /* FDDI */ +#define DLT_ATM_RFC1483 11 /* LLC/SNAP encapsulated atm */ +#define DLT_LOOP 12 /* loopback type (af header) */ +#define DLT_ENC 13 /* IPSEC enc type (af header, spi, flags) */ +#define DLT_RAW 14 /* raw IP */ +#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */ +#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */ +#define DLT_PFSYNC 18 /* Packet filter state syncing */ +#define DLT_PPP_SERIAL 50 /* PPP over Serial with HDLC */ +#define DLT_PPP_ETHER 51 /* PPP over Ethernet; session only w/o ether header */ +#define DLT_C_HDLC 104 /* Cisco HDLC */ +#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */ +#define DLT_PFLOG 117 /* Packet filter logging, by pcap people */ +#define DLT_IEEE802_11_RADIO 127 /* IEEE 802.11 plus WLAN header */ +#define DLT_USER0 147 /* Reserved for private use */ +#define DLT_USER1 148 /* Reserved for private use */ +#define DLT_USER2 149 /* Reserved for private use */ +#define DLT_USER3 150 /* Reserved for private use */ +#define DLT_USER4 151 /* Reserved for private use */ +#define DLT_USER5 152 /* Reserved for private use */ +#define DLT_USER6 153 /* Reserved for private use */ +#define DLT_USER7 154 /* Reserved for private use */ +#define DLT_USER8 155 /* Reserved for private use */ +#define DLT_USER9 156 /* Reserved for private use */ +#define DLT_USER10 157 /* Reserved for private use */ +#define DLT_USER11 158 /* Reserved for private use */ +#define DLT_USER12 159 /* Reserved for private use */ +#define DLT_USER13 160 /* Reserved for private use */ +#define DLT_USER14 161 /* Reserved for private use */ +#define DLT_USER15 162 /* Reserved for private use */ +#define DLT_USBPCAP 249 /* USBPcap */ +#define DLT_MPLS 219 /* MPLS Provider Edge header */ +#define DLT_OPENFLOW 267 /* in-kernel OpenFlow, by pcap */ + +/* + * The instruction encodings. + */ +/* instruction classes */ +#define BPF_CLASS(code) ((code) & 0x07) +#define BPF_LD 0x00 +#define BPF_LDX 0x01 +#define BPF_ST 0x02 +#define BPF_STX 0x03 +#define BPF_ALU 0x04 +#define BPF_JMP 0x05 +#define BPF_RET 0x06 +#define BPF_MISC 0x07 + +/* ld/ldx fields */ +#define BPF_SIZE(code) ((code) & 0x18) +#define BPF_W 0x00 +#define BPF_H 0x08 +#define BPF_B 0x10 +#define BPF_MODE(code) ((code) & 0xe0) +#define BPF_IMM 0x00 +#define BPF_ABS 0x20 +#define BPF_IND 0x40 +#define BPF_MEM 0x60 +#define BPF_LEN 0x80 +#define BPF_MSH 0xa0 +#define BPF_RND 0xc0 + +/* alu/jmp fields */ +#define BPF_OP(code) ((code) & 0xf0) +#define BPF_ADD 0x00 +#define BPF_SUB 0x10 +#define BPF_MUL 0x20 +#define BPF_DIV 0x30 +#define BPF_OR 0x40 +#define BPF_AND 0x50 +#define BPF_LSH 0x60 +#define BPF_RSH 0x70 +#define BPF_NEG 0x80 +#define BPF_JA 0x00 +#define BPF_JEQ 0x10 +#define BPF_JGT 0x20 +#define BPF_JGE 0x30 +#define BPF_JSET 0x40 +#define BPF_SRC(code) ((code) & 0x08) +#define BPF_K 0x00 +#define BPF_X 0x08 + +/* ret - BPF_K and BPF_X also apply */ +#define BPF_RVAL(code) ((code) & 0x18) +#define BPF_A 0x10 + +/* misc */ +#define BPF_MISCOP(code) ((code) & 0xf8) +#define BPF_TAX 0x00 +#define BPF_TXA 0x80 + +/* + * The instruction data structure. + */ +struct bpf_insn { + u_int16_t code; + u_char jt; + u_char jf; + u_int32_t k; +}; + +/* + * Structure to retrieve available DLTs for the interface. + */ +struct bpf_dltlist { + u_int bfl_len; /* number of bfd_list array */ + u_int *bfl_list; /* array of DLTs */ +}; + +/* + * Load operations for _bpf_filter to use against the packet pointer. + */ +struct bpf_ops { + u_int32_t (*ldw)(const void *, u_int32_t, int *); + u_int32_t (*ldh)(const void *, u_int32_t, int *); + u_int32_t (*ldb)(const void *, u_int32_t, int *); +}; + +/* + * Macros for insn array initializers. + */ +#define BPF_STMT(code, k) { (u_int16_t)(code), 0, 0, k } +#define BPF_JUMP(code, k, jt, jf) { (u_int16_t)(code), jt, jf, k } + +__BEGIN_DECLS +u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int) + __bounded((__buffer__, 2, 4)); + +u_int _bpf_filter(const struct bpf_insn *, const struct bpf_ops *, + const void *, u_int); +__END_DECLS + +#ifdef _KERNEL +struct ifnet; +struct mbuf; + +int bpf_validate(struct bpf_insn *, int); +int bpf_mtap(caddr_t, const struct mbuf *, u_int); +int bpf_mtap_hdr(caddr_t, const void *, u_int, const struct mbuf *, u_int); +int bpf_mtap_af(caddr_t, u_int32_t, const struct mbuf *, u_int); +int bpf_mtap_ether(caddr_t, const struct mbuf *, u_int); +int bpf_tap_hdr(caddr_t, const void *, u_int, const void *, u_int, u_int); +void bpfattach(caddr_t *, struct ifnet *, u_int, u_int); +void bpfdetach(struct ifnet *); +void *bpfsattach(caddr_t *, const char *, u_int, u_int); +void *bpfxattach(caddr_t *, const char *, struct ifnet *, u_int, u_int); +void bpfsdetach(void *); +void bpfilterattach(int); + +u_int bpf_mfilter(const struct bpf_insn *, const struct mbuf *, u_int); +#endif /* _KERNEL */ + +/* + * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST). + */ +#define BPF_MEMWORDS 16 + +#endif /* _NET_BPF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/bpfdesc.h b/lib/libc/include/generic-openbsd/net/bpfdesc.h new file mode 100644 index 000000000000..61be132f2bbd --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/bpfdesc.h @@ -0,0 +1,128 @@ +/* $OpenBSD: bpfdesc.h,v 1.50 2024/11/19 23:26:35 dlg Exp $ */ +/* $NetBSD: bpfdesc.h,v 1.11 1995/09/27 18:30:42 thorpej Exp $ */ + +/* + * Copyright (c) 1990, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from the Stanford/CMU enet packet filter, + * (net/enet.c) distributed as part of 4.3BSD, and code contributed + * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence + * Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)bpfdesc.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NET_BPFDESC_H_ +#define _NET_BPFDESC_H_ + +#ifdef _KERNEL + +/* + * Locks used to protect struct members in this file: + * + * m the per-descriptor mutex (bpf_d.bd_mtx) + */ + +struct bpf_program_smr { + struct bpf_program bps_bf; + struct smr_entry bps_smr; +}; + +/* + * Descriptor associated with each open bpf file. + */ +struct bpf_d { + SMR_SLIST_ENTRY(bpf_d) bd_next; /* Linked list of descriptors */ + /* + * Buffer slots: two mbuf clusters buffer the incoming packets. + * The model has three slots. Sbuf is always occupied. + * sbuf (store) - Receive interrupt puts packets here. + * hbuf (hold) - When sbuf is full, put cluster here and + * wakeup read (replace sbuf with fbuf). + * fbuf (free) - When read is done, put cluster here. + * On receiving, if sbuf is full and fbuf is 0, packet is dropped. + */ + struct mutex bd_mtx; /* protect buffer slots below */ + caddr_t bd_sbuf; /* store slot */ + caddr_t bd_hbuf; /* hold slot */ + caddr_t bd_fbuf; /* free slot */ + int bd_slen; /* current length of store buffer */ + int bd_hlen; /* current length of hold buffer */ + int bd_bufsize; /* absolute length of buffers */ + + int bd_in_uiomove; /* for debugging purpose */ + + struct bpf_if *bd_bif; /* interface descriptor */ + uint64_t bd_rtout; /* [m] Read timeout in nanoseconds */ + uint64_t bd_wtout; /* [m] Wait time in nanoseconds */ + u_long bd_nreaders; /* [m] # threads asleep in bpfread() */ + struct bpf_program_smr + *bd_rfilter; /* read filter code */ + struct bpf_program_smr + *bd_wfilter; /* write filter code */ + u_long bd_rcount; /* number of packets received */ + u_long bd_dcount; /* number of packets dropped */ + + u_char bd_promisc; /* true if listening promiscuously */ + u_char bd_state; /* [m] idle, waiting, or timed out */ + u_char bd_locked; /* true if descriptor is locked */ + u_char bd_fildrop; /* true if filtered packets will be dropped */ + u_char bd_dirfilt; /* direction filter */ + int bd_hdrcmplt; /* false to fill in src lladdr automatically */ + int bd_async; /* non-zero if packet reception should generate signal */ + int bd_sig; /* signal to send upon packet reception */ + struct sigio_ref + bd_sigio; /* async I/O registration */ + struct refcnt bd_refcnt; /* reference count */ + struct klist bd_klist; /* list of knotes */ + int bd_unit; /* logical unit number */ + LIST_ENTRY(bpf_d) bd_list; /* descriptor list */ + + struct task bd_wake_task; /* defer pgsigio() and selwakeup() */ + struct timeout bd_wait_tmo; /* delay wakeup after catching pkt */ + + struct smr_entry + bd_smr; +}; + +/* + * Descriptor associated with each attached hardware interface. + */ +struct bpf_if { + TAILQ_ENTRY(bpf_if) bif_next; /* list of all interfaces */ + SMR_SLIST_HEAD(, bpf_d) bif_dlist; /* descriptor list */ + struct bpf_if **bif_driverp; /* pointer into softc */ + u_int bif_dlt; /* link layer type */ + u_int bif_hdrlen; /* length of header (with padding) */ + const char *bif_name; /* name of "subsystem" */ + struct ifnet *bif_ifp; /* corresponding interface */ +}; + +int bpf_setf(struct bpf_d *, struct bpf_program *, u_long); +#endif /* _KERNEL */ +#endif /* _NET_BPFDESC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/ethertypes.h b/lib/libc/include/generic-openbsd/net/ethertypes.h new file mode 100644 index 000000000000..713ae8d95858 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/ethertypes.h @@ -0,0 +1,325 @@ +/* $OpenBSD: ethertypes.h,v 1.20 2025/05/18 04:10:49 dlg Exp $ */ +/* $NetBSD: ethertypes.h,v 1.13 2002/02/10 01:28:32 thorpej Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_ether.h 8.1 (Berkeley) 6/10/93 + */ + +/* + * Ethernet protocol types. + * + * According to "assigned numbers", the Ethernet protocol numbers are also + * used as ARP protocol type numbers. + * + * I factor them out here to avoid pulling all the Ethernet header file + * into the hardware independent ARP code. -is + * + * Additional sources of information: + * http://standards.ieee.org/regauth/ethertype/eth.txt + * http://www.mit.edu/~map/Ethernet/Ethernet.txt + * + */ + +#ifndef _NET_ETHERTYPES_H_ +#define _NET_ETHERTYPES_H_ + +/* + * NOTE: 0x0000-0x05DC (0..1500) are generally IEEE 802.3 length fields. + * However, there are some conflicts. + */ + +#define ETHERTYPE_8023 0x0004 /* IEEE 802.3 packet */ + /* 0x0101 .. 0x1FF Experimental */ +#define ETHERTYPE_PUP 0x0200 /* Xerox PUP protocol - see 0A00 */ +#define ETHERTYPE_PUPAT 0x0200 /* PUP Address Translation - see 0A01 */ +#define ETHERTYPE_SPRITE 0x0500 /* ??? */ + /* 0x0400 Nixdorf */ +#define ETHERTYPE_NS 0x0600 /* XNS */ +#define ETHERTYPE_NSAT 0x0601 /* XNS Address Translation (3Mb only) */ +#define ETHERTYPE_DLOG1 0x0660 /* DLOG (?) */ +#define ETHERTYPE_DLOG2 0x0661 /* DLOG (?) */ +#define ETHERTYPE_IP 0x0800 /* IP protocol */ +#define ETHERTYPE_X75 0x0801 /* X.75 Internet */ +#define ETHERTYPE_NBS 0x0802 /* NBS Internet */ +#define ETHERTYPE_ECMA 0x0803 /* ECMA Internet */ +#define ETHERTYPE_CHAOS 0x0804 /* CHAOSnet */ +#define ETHERTYPE_X25 0x0805 /* X.25 Level 3 */ +#define ETHERTYPE_ARP 0x0806 /* Address resolution protocol */ +#define ETHERTYPE_NSCOMPAT 0x0807 /* XNS Compatibility */ +#define ETHERTYPE_FRARP 0x0808 /* Frame Relay ARP (RFC1701) */ + /* 0x081C Symbolics Private */ + /* 0x0888 - 0x088A Xyplex */ +#define ETHERTYPE_UBDEBUG 0x0900 /* Ungermann-Bass network debugger */ +#define ETHERTYPE_IEEEPUP 0x0A00 /* Xerox IEEE802.3 PUP */ +#define ETHERTYPE_IEEEPUPAT 0x0A01 /* Xerox IEEE802.3 PUP Address Translation */ +#define ETHERTYPE_VINES 0x0BAD /* Banyan VINES */ +#define ETHERTYPE_VINESLOOP 0x0BAE /* Banyan VINES Loopback */ +#define ETHERTYPE_VINESECHO 0x0BAF /* Banyan VINES Echo */ + +/* 0x1000 - 0x100F Berkeley Trailer */ +/* + * The ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL have + * (type-ETHERTYPE_TRAIL)*512 bytes of data followed + * by an ETHER type (as given above) and then the (variable-length) header. + */ +#define ETHERTYPE_TRAIL 0x1000 /* Trailer packet */ +#define ETHERTYPE_NTRAILER 16 + +#define ETHERTYPE_DCA 0x1234 /* DCA - Multicast */ +#define ETHERTYPE_VALID 0x1600 /* VALID system protocol */ +#define ETHERTYPE_DOGFIGHT 0x1989 /* Artificial Horizons ("Aviator" dogfight simulator [on Sun]) */ +#define ETHERTYPE_RCL 0x1995 /* Datapoint Corporation (RCL lan protocol) */ +#define ETHERTYPE_NHRP 0x2001 /* NBMA Next Hop Resolution Protocol (RFC2332) */ + + /* The following 3C0x types + are unregistered: */ +#define ETHERTYPE_NBPVCD 0x3C00 /* 3Com NBP virtual circuit datagram (like XNS SPP) not registered */ +#define ETHERTYPE_NBPSCD 0x3C01 /* 3Com NBP System control datagram not registered */ +#define ETHERTYPE_NBPCREQ 0x3C02 /* 3Com NBP Connect request (virtual cct) not registered */ +#define ETHERTYPE_NBPCRSP 0x3C03 /* 3Com NBP Connect response not registered */ +#define ETHERTYPE_NBPCC 0x3C04 /* 3Com NBP Connect complete not registered */ +#define ETHERTYPE_NBPCLREQ 0x3C05 /* 3Com NBP Close request (virtual cct) not registered */ +#define ETHERTYPE_NBPCLRSP 0x3C06 /* 3Com NBP Close response not registered */ +#define ETHERTYPE_NBPDG 0x3C07 /* 3Com NBP Datagram (like XNS IDP) not registered */ +#define ETHERTYPE_NBPDGB 0x3C08 /* 3Com NBP Datagram broadcast not registered */ +#define ETHERTYPE_NBPCLAIM 0x3C09 /* 3Com NBP Claim NetBIOS name not registered */ +#define ETHERTYPE_NBPDLTE 0x3C0A /* 3Com NBP Delete Netbios name not registered */ +#define ETHERTYPE_NBPRAS 0x3C0B /* 3Com NBP Remote adaptor status request not registered */ +#define ETHERTYPE_NBPRAR 0x3C0C /* 3Com NBP Remote adaptor response not registered */ +#define ETHERTYPE_NBPRST 0x3C0D /* 3Com NBP Reset not registered */ + +#define ETHERTYPE_PCS 0x4242 /* PCS Basic Block Protocol */ +#define ETHERTYPE_IMLBLDIAG 0x424C /* Information Modes Little Big LAN diagnostic */ +#define ETHERTYPE_DIDDLE 0x4321 /* THD - Diddle */ +#define ETHERTYPE_IMLBL 0x4C42 /* Information Modes Little Big LAN */ +#define ETHERTYPE_SIMNET 0x5208 /* BBN Simnet Private */ +#define ETHERTYPE_DECEXPER 0x6000 /* DEC Unassigned, experimental */ +#define ETHERTYPE_MOPDL 0x6001 /* DEC MOP dump/load */ +#define ETHERTYPE_MOPRC 0x6002 /* DEC MOP remote console */ +#define ETHERTYPE_DECnet 0x6003 /* DEC DECNET Phase IV route */ +#define ETHERTYPE_DN ETHERTYPE_DECnet /* libpcap, tcpdump */ +#define ETHERTYPE_LAT 0x6004 /* DEC LAT */ +#define ETHERTYPE_DECDIAG 0x6005 /* DEC diagnostic protocol (at interface initialization?) */ +#define ETHERTYPE_DECCUST 0x6006 /* DEC customer protocol */ +#define ETHERTYPE_SCA 0x6007 /* DEC LAVC, SCA */ +#define ETHERTYPE_AMBER 0x6008 /* DEC AMBER */ +#define ETHERTYPE_DECMUMPS 0x6009 /* DEC MUMPS */ + /* 0x6010 - 0x6014 3Com Corporation */ +#define ETHERTYPE_TRANSETHER 0x6558 /* Trans Ether Bridging (RFC1701)*/ +#define ETHERTYPE_RAWFR 0x6559 /* Raw Frame Relay (RFC1701) */ +#define ETHERTYPE_UBDL 0x7000 /* Ungermann-Bass download */ +#define ETHERTYPE_UBNIU 0x7001 /* Ungermann-Bass NIUs */ +#define ETHERTYPE_UBDIAGLOOP 0x7002 /* Ungermann-Bass diagnostic/loopback */ +#define ETHERTYPE_UBNMC 0x7003 /* Ungermann-Bass ??? (NMC to/from UB Bridge) */ +#define ETHERTYPE_UBBST 0x7005 /* Ungermann-Bass Bridge Spanning Tree */ +#define ETHERTYPE_OS9 0x7007 /* OS/9 Microware */ +#define ETHERTYPE_OS9NET 0x7009 /* OS/9 Net? */ + /* 0x7020 - 0x7029 LRT (England) (now Sintrom) */ +#define ETHERTYPE_RACAL 0x7030 /* Racal-Interlan */ +#define ETHERTYPE_PRIMENTS 0x7031 /* Prime NTS (Network Terminal Service) */ +#define ETHERTYPE_CABLETRON 0x7034 /* Cabletron */ +#define ETHERTYPE_CRONUSVLN 0x8003 /* Cronus VLN */ +#define ETHERTYPE_CRONUS 0x8004 /* Cronus Direct */ +#define ETHERTYPE_HP 0x8005 /* HP Probe */ +#define ETHERTYPE_NESTAR 0x8006 /* Nestar */ +#define ETHERTYPE_ATTSTANFORD 0x8008 /* AT&T/Stanford (local use) */ +#define ETHERTYPE_EXCELAN 0x8010 /* Excelan */ +#define ETHERTYPE_SG_DIAG 0x8013 /* SGI diagnostic type */ +#define ETHERTYPE_SG_NETGAMES 0x8014 /* SGI network games */ +#define ETHERTYPE_SG_RESV 0x8015 /* SGI reserved type */ +#define ETHERTYPE_SG_BOUNCE 0x8016 /* SGI bounce server */ +#define ETHERTYPE_APOLLODOMAIN 0x8019 /* Apollo DOMAIN */ +#define ETHERTYPE_TYMSHARE 0x802E /* Tymeshare */ +#define ETHERTYPE_TIGAN 0x802F /* Tigan, Inc. */ +#define ETHERTYPE_REVARP 0x8035 /* Reverse addr resolution protocol */ +#define ETHERTYPE_AEONIC 0x8036 /* Aeonic Systems */ +#define ETHERTYPE_IPXNEW 0x8037 /* IPX (Novell Netware?) */ +#define ETHERTYPE_LANBRIDGE 0x8038 /* DEC LANBridge */ +#define ETHERTYPE_DSMD 0x8039 /* DEC DSM/DDP */ +#define ETHERTYPE_ARGONAUT 0x803A /* DEC Argonaut Console */ +#define ETHERTYPE_VAXELN 0x803B /* DEC VAXELN */ +#define ETHERTYPE_DECDNS 0x803C /* DEC DNS Naming Service */ +#define ETHERTYPE_ENCRYPT 0x803D /* DEC Ethernet Encryption */ +#define ETHERTYPE_DECDTS 0x803E /* DEC Distributed Time Service */ +#define ETHERTYPE_DECLTM 0x803F /* DEC LAN Traffic Monitor */ +#define ETHERTYPE_DECNETBIOS 0x8040 /* DEC PATHWORKS DECnet NETBIOS Emulation */ +#define ETHERTYPE_DECLAST 0x8041 /* DEC Local Area System Transport */ + /* 0x8042 DEC Unassigned */ +#define ETHERTYPE_PLANNING 0x8044 /* Planning Research Corp. */ + /* 0x8046 - 0x8047 AT&T */ +#define ETHERTYPE_DECAM 0x8048 /* DEC Availability Manager for Distributed Systems DECamds (but someone at DEC says not) */ +#define ETHERTYPE_EXPERDATA 0x8049 /* ExperData */ +#define ETHERTYPE_VEXP 0x805B /* Stanford V Kernel exp. */ +#define ETHERTYPE_VPROD 0x805C /* Stanford V Kernel prod. */ +#define ETHERTYPE_ES 0x805D /* Evans & Sutherland */ +#define ETHERTYPE_LITTLE 0x8060 /* Little Machines */ +#define ETHERTYPE_COUNTERPOINT 0x8062 /* Counterpoint Computers */ + /* 0x8065 - 0x8066 Univ. of Mass @ Amherst */ +#define ETHERTYPE_VEECO 0x8067 /* Veeco Integrated Auto. */ +#define ETHERTYPE_GENDYN 0x8068 /* General Dynamics */ +#define ETHERTYPE_ATT 0x8069 /* AT&T */ +#define ETHERTYPE_AUTOPHON 0x806A /* Autophon */ +#define ETHERTYPE_COMDESIGN 0x806C /* ComDesign */ +#define ETHERTYPE_COMPUGRAPHIC 0x806D /* Compugraphic Corporation */ + /* 0x806E - 0x8077 Landmark Graphics Corp. */ +#define ETHERTYPE_MATRA 0x807A /* Matra */ +#define ETHERTYPE_DDE 0x807B /* Dansk Data Elektronik */ +#define ETHERTYPE_MERIT 0x807C /* Merit Internodal (or Univ of Michigan?) */ + /* 0x807D - 0x807F Vitalink Communications */ +#define ETHERTYPE_VLTLMAN 0x8080 /* Vitalink TransLAN III Management */ + /* 0x8081 - 0x8083 Counterpoint Computers */ + /* 0x8088 - 0x808A Xyplex */ +#define ETHERTYPE_ATALK 0x809B /* AppleTalk */ +#define ETHERTYPE_AT ETHERTYPE_ATALK /* old NetBSD */ +#define ETHERTYPE_APPLETALK ETHERTYPE_ATALK /* HP-UX */ + /* 0x809C - 0x809E Datability */ +#define ETHERTYPE_SPIDER 0x809F /* Spider Systems Ltd. */ + /* 0x80A3 Nixdorf */ + /* 0x80A4 - 0x80B3 Siemens Gammasonics Inc. */ + /* 0x80C0 - 0x80C3 DCA (Digital Comm. Assoc.) Data Exchange Cluster */ + /* 0x80C4 - 0x80C5 Banyan Systems */ +#define ETHERTYPE_PACER 0x80C6 /* Pacer Software */ +#define ETHERTYPE_APPLITEK 0x80C7 /* Applitek Corporation */ + /* 0x80C8 - 0x80CC Intergraph Corporation */ + /* 0x80CD - 0x80CE Harris Corporation */ + /* 0x80CF - 0x80D2 Taylor Instrument */ + /* 0x80D3 - 0x80D4 Rosemount Corporation */ +#define ETHERTYPE_SNA 0x80D5 /* IBM SNA Services over Ethernet */ +#define ETHERTYPE_VARIAN 0x80DD /* Varian Associates */ + /* 0x80DE - 0x80DF TRFS (Integrated Solutions Transparent Remote File System) */ + /* 0x80E0 - 0x80E3 Allen-Bradley */ + /* 0x80E4 - 0x80F0 Datability */ +#define ETHERTYPE_RETIX 0x80F2 /* Retix */ +#define ETHERTYPE_AARP 0x80F3 /* AppleTalk AARP */ + /* 0x80F4 - 0x80F5 Kinetics */ +#define ETHERTYPE_APOLLO 0x80F7 /* Apollo Computer */ +#define ETHERTYPE_VLAN 0x8100 /* IEEE 802.1Q VLAN tagging (XXX conflicts) */ + /* 0x80FF - 0x8101 Wellfleet Communications (XXX conflicts) */ +#define ETHERTYPE_BOFL 0x8102 /* Wellfleet; BOFL (Breath OF Life) pkts [every 5-10 secs.] */ +#define ETHERTYPE_WELLFLEET 0x8103 /* Wellfleet Communications */ + /* 0x8107 - 0x8109 Symbolics Private */ +#define ETHERTYPE_TALARIS 0x812B /* Talaris */ +#define ETHERTYPE_WATERLOO 0x8130 /* Waterloo Microsystems Inc. (XXX which?) */ +#define ETHERTYPE_HAYES 0x8130 /* Hayes Microcomputers (XXX which?) */ +#define ETHERTYPE_VGLAB 0x8131 /* VG Laboratory Systems */ + /* 0x8132 - 0x8137 Bridge Communications */ +#define ETHERTYPE_IPX 0x8137 /* Novell (old) NetWare IPX (ECONFIG E option) */ +#define ETHERTYPE_NOVELL 0x8138 /* Novell, Inc. */ + /* 0x8139 - 0x813D KTI */ +#define ETHERTYPE_MUMPS 0x813F /* M/MUMPS data sharing */ +#define ETHERTYPE_AMOEBA 0x8145 /* Vrije Universiteit (NL) Amoeba 4 RPC (obsolete) */ +#define ETHERTYPE_FLIP 0x8146 /* Vrije Universiteit (NL) FLIP (Fast Local Internet Protocol) */ +#define ETHERTYPE_VURESERVED 0x8147 /* Vrije Universiteit (NL) [reserved] */ +#define ETHERTYPE_LOGICRAFT 0x8148 /* Logicraft */ +#define ETHERTYPE_NCD 0x8149 /* Network Computing Devices */ +#define ETHERTYPE_ALPHA 0x814A /* Alpha Micro */ +#define ETHERTYPE_SNMP 0x814C /* SNMP over Ethernet (see RFC1089) */ + /* 0x814D - 0x814E BIIN */ +#define ETHERTYPE_TEC 0x814F /* Technically Elite Concepts */ +#define ETHERTYPE_RATIONAL 0x8150 /* Rational Corp */ + /* 0x8151 - 0x8153 Qualcomm */ + /* 0x815C - 0x815E Computer Protocol Pty Ltd */ + /* 0x8164 - 0x8166 Charles River Data Systems */ +#define ETHERTYPE_XTP 0x817D /* Protocol Engines XTP */ +#define ETHERTYPE_SGITW 0x817E /* SGI/Time Warner prop. */ +#define ETHERTYPE_HIPPI_FP 0x8180 /* HIPPI-FP encapsulation */ +#define ETHERTYPE_STP 0x8181 /* Scheduled Transfer STP, HIPPI-ST */ + /* 0x8182 - 0x8183 Reserved for HIPPI-6400 */ + /* 0x8184 - 0x818C SGI prop. */ +#define ETHERTYPE_MOTOROLA 0x818D /* Motorola */ +#define ETHERTYPE_NETBEUI 0x8191 /* PowerLAN NetBIOS/NetBEUI (PC) */ + /* 0x819A - 0x81A3 RAD Network Devices */ + /* 0x81B7 - 0x81B9 Xyplex */ + /* 0x81CC - 0x81D5 Apricot Computers */ + /* 0x81D6 - 0x81DD Artisoft Lantastic */ + /* 0x81E6 - 0x81EF Polygon */ + /* 0x81F0 - 0x81F2 Comsat Labs */ + /* 0x81F3 - 0x81F5 SAIC */ + /* 0x81F6 - 0x81F8 VG Analytical */ + /* 0x8203 - 0x8205 QNX Software Systems Ltd. */ + /* 0x8221 - 0x8222 Ascom Banking Systems */ + /* 0x823E - 0x8240 Advanced Encryption Systems */ + /* 0x8263 - 0x826A Charles River Data Systems */ + /* 0x827F - 0x8282 Athena Programming */ + /* 0x829A - 0x829B Inst Ind Info Tech */ + /* 0x829C - 0x82AB Taurus Controls */ + /* 0x82AC - 0x8693 Walker Richer & Quinn */ +#define ETHERTYPE_ACCTON 0x8390 /* Accton Technologies (unregistered) */ +#define ETHERTYPE_TALARISMC 0x852B /* Talaris multicast */ +#define ETHERTYPE_KALPANA 0x8582 /* Kalpana */ + /* 0x8694 - 0x869D Idea Courier */ + /* 0x869E - 0x86A1 Computer Network Tech */ + /* 0x86A3 - 0x86AC Gateway Communications */ +#define ETHERTYPE_SECTRA 0x86DB /* SECTRA */ +#define ETHERTYPE_IPV6 0x86DD /* IP protocol version 6 */ +#define ETHERTYPE_DELTACON 0x86DE /* Delta Controls */ +#define ETHERTYPE_ATOMIC 0x86DF /* ATOMIC */ + /* 0x86E0 - 0x86EF Landis & Gyr Powers */ + /* 0x8700 - 0x8710 Motorola */ +#define ETHERTYPE_RDP 0x8739 /* Control Technology Inc. RDP Without IP */ +#define ETHERTYPE_MICP 0x873A /* Control Technology Inc. Mcast Industrial Ctrl Proto. */ + /* 0x873B - 0x873C Control Technology Inc. Proprietary */ +#define ETHERTYPE_TCPCOMP 0x876B /* TCP/IP Compression (RFC1701) */ +#define ETHERTYPE_IPAS 0x876C /* IP Autonomous Systems (RFC1701) */ +#define ETHERTYPE_SECUREDATA 0x876D /* Secure Data (RFC1701) */ +#define ETHERTYPE_FLOWCONTROL 0x8808 /* 802.3x flow control packet */ +#define ETHERTYPE_SLOW 0x8809 /* 803.3ad slow protocols (LACP/Marker) */ +#define ETHERTYPE_PPP 0x880B /* PPP (obsolete by PPPOE) */ +#define ETHERTYPE_HITACHI 0x8820 /* Hitachi Cable (Optoelectronic Systems Laboratory) */ +#define ETHERTYPE_MPLS 0x8847 /* MPLS Unicast */ +#define ETHERTYPE_MPLS_MCAST 0x8848 /* MPLS Multicast */ +#define ETHERTYPE_AXIS 0x8856 /* Axis Communications AB proprietary bootstrap/config */ +#define ETHERTYPE_PPPOEDISC 0x8863 /* PPP Over Ethernet Discovery Stage */ +#define ETHERTYPE_PPPOE 0x8864 /* PPP Over Ethernet Session Stage */ +#define ETHERTYPE_LANPROBE 0x8888 /* HP LanProbe test? */ +#define ETHERTYPE_EAPOL 0x888E /* 802.1X EAP over LAN */ +#define ETHERTYPE_AOE 0x88A2 /* ATA over Ethernet */ +#define ETHERTYPE_QINQ 0x88A8 /* 802.1ad VLAN stacking */ +#define ETHERTYPE_LLDP 0x88CC /* Link Layer Discovery Protocol */ +#define ETHERTYPE_802_EX1 0x88B5 /* IEEE Std 802 - Local Experimental */ +#define ETHERTYPE_802_EX2 0x88B6 /* IEEE Std 802 - Local Experimental */ +#define ETHERTYPE_MACSEC 0x88e5 /* 802.1AE MACsec */ +#define ETHERTYPE_PBB 0x88e7 /* 802.1Q Provider Backbone Bridging */ +#define ETHERTYPE_PTP 0x88F7 /* IEEE 1588 Precision Time Protocol */ +#define ETHERTYPE_CFM 0x8902 /* 802.1ag Connectivity Fault Management */ +#define ETHERTYPE_NSH 0x894F /* Network Service Header (RFC8300) */ +#define ETHERTYPE_LOOPBACK 0x9000 /* Loopback */ +#define ETHERTYPE_LBACK ETHERTYPE_LOOPBACK /* DEC MOP loopback */ +#define ETHERTYPE_XNSSM 0x9001 /* 3Com (Formerly Bridge Communications), XNS Systems Management */ +#define ETHERTYPE_TCPSM 0x9002 /* 3Com (Formerly Bridge Communications), TCP/IP Systems Management */ +#define ETHERTYPE_BCLOOP 0x9003 /* 3Com (Formerly Bridge Communications), loopback detection */ +#define ETHERTYPE_DEBNI 0xAAAA /* DECNET? Used by VAX 6220 DEBNI */ +#define ETHERTYPE_SONIX 0xFAF5 /* Sonix Arpeggio */ +#define ETHERTYPE_VITAL 0xFF00 /* BBN VITAL-LanBridge cache wakeups */ + /* 0xFF00 - 0xFFOF ISC Bunker Ramo */ + +#define ETHERTYPE_MAX 0xFFFF /* Maximum valid ethernet type, reserved */ + +#endif /* _NET_ETHERTYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/fq_codel.h b/lib/libc/include/generic-openbsd/net/fq_codel.h new file mode 100644 index 000000000000..4564164ae41e --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/fq_codel.h @@ -0,0 +1,51 @@ +/* $OpenBSD: fq_codel.h,v 1.4 2020/06/18 23:29:59 dlg Exp $ */ + +/* + * Copyright (c) 2017 Mike Belopuhov + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _NET_FQ_CODEL_H_ +#define _NET_FQ_CODEL_H_ + +/* compatible with hfsc_pktcntr */ +struct fqcodel_pktcntr { + uint64_t packets; + uint64_t bytes; +}; + +struct fqcodel_stats { + struct fqcodel_pktcntr xmit_cnt; + struct fqcodel_pktcntr drop_cnt; + + uint32_t qlength; + uint32_t qlimit; + + uint32_t flows; + uint32_t _unused; /* padding */ + + uint32_t target; + uint32_t interval; + + /* the values below are used to calculate standard deviation */ + uint64_t delaysum; /* sum of delays, us */ + uint64_t delaysumsq;/* sum of squared delays, us */ +}; + +#ifdef _KERNEL +extern const struct ifq_ops * const ifq_fqcodel_ops; +extern const struct pfq_ops * const pfq_fqcodel_ops; +#endif /* _KERNEL */ + +#endif /* _NET_FQ_CODEL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/frame.h b/lib/libc/include/generic-openbsd/net/frame.h new file mode 100644 index 000000000000..52625a59eacd --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/frame.h @@ -0,0 +1,47 @@ +/* $OpenBSD: frame.h,v 1.1 2024/12/15 11:00:05 dlg Exp $ */ + +/* + * Copyright (c) 2024 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _NET_FRAME_H_ +#define _NET_FRAME_H_ + +#define FRAME_ADDRLEN 8 /* big enough for Ethernet */ +#define FRAME_DATALEN 32 + +struct sockaddr_frame { + uint8_t sfrm_len; + uint8_t sfrm_family; /* AF_FRAME */ + uint16_t sfrm_proto; + unsigned int sfrm_ifindex; + uint8_t sfrm_addr[FRAME_ADDRLEN]; + char sfrm_ifname[IFNAMSIZ]; + uint8_t sfrm_data[FRAME_DATALEN]; +}; + +#define FRAME_RECVDSTADDR 0 /* int */ +#define FRAME_RECVPRIO 1 /* int */ +#define FRAME_ADD_MEMBERSHIP 64 /* struct frame_mreq */ +#define FRAME_DEL_MEMBERSHIP 65 /* struct frame_mreq */ +#define FRAME_SENDPRIO 66 /* int: IF_HDRPRIO_{MIN-MAX,PACKET} */ + +struct frame_mreq { + unsigned int fmr_ifindex; + uint8_t fmr_addr[FRAME_ADDRLEN]; + char fmr_ifname[IFNAMSIZ]; +}; + +#endif /* _NET_FRAME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/hfsc.h b/lib/libc/include/generic-openbsd/net/hfsc.h new file mode 100644 index 000000000000..0e2864cc053a --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/hfsc.h @@ -0,0 +1,122 @@ +/* $OpenBSD: hfsc.h,v 1.14 2025/07/07 00:55:15 jsg Exp $ */ + +/* + * Copyright (c) 2012-2013 Henning Brauer + * Copyright (c) 1997-1999 Carnegie Mellon University. All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation is hereby granted (including for commercial or + * for-profit use), provided that both the copyright notice and this + * permission notice appear in all copies of the software, derivative + * works, or modified versions, and any portions thereof. + * + * THIS SOFTWARE IS EXPERIMENTAL AND IS KNOWN TO HAVE BUGS, SOME OF + * WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON PROVIDES THIS + * SOFTWARE IN ITS ``AS IS'' CONDITION, 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 CARNEGIE MELLON UNIVERSITY 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. + * + * Carnegie Mellon encourages (but does not require) users of this + * software to return any improvements or extensions that they make, + * and to grant Carnegie Mellon the rights to redistribute these + * changes without encumbrance. + */ +#ifndef _HFSC_H_ +#define _HFSC_H_ + +/* hfsc class flags */ +#define HFSC_DEFAULTCLASS 0x1000 /* default class */ + +struct hfsc_pktcntr { + u_int64_t packets; + u_int64_t bytes; +}; + +#define PKTCNTR_INC(cntr, len) \ + do { (cntr)->packets++; (cntr)->bytes += len; } while (0) + +struct hfsc_sc { + u_int m1; /* slope of the first segment in bits/sec */ + u_int d; /* the x-projection of the first segment in msec */ + u_int m2; /* slope of the second segment in bits/sec */ +}; + +/* special class handles */ +#define HFSC_ROOT_CLASS 0x10000 +#define HFSC_DEFAULT_CLASSES 64 +#define HFSC_MAX_CLASSES 65535 + +/* service curve types */ +#define HFSC_REALTIMESC 1 +#define HFSC_LINKSHARINGSC 2 +#define HFSC_UPPERLIMITSC 4 +#define HFSC_DEFAULTSC (HFSC_REALTIMESC|HFSC_LINKSHARINGSC) + +struct hfsc_class_stats { + struct hfsc_pktcntr xmit_cnt; + struct hfsc_pktcntr drop_cnt; + + u_int qlength; + u_int qlimit; + u_int period; + + u_int class_id; + u_int32_t class_handle; + struct hfsc_sc rsc; + struct hfsc_sc fsc; + struct hfsc_sc usc; /* upper limit service curve */ + + u_int64_t total; /* total work in bytes */ + u_int64_t cumul; /* cumulative work in bytes + done by real-time criteria */ + u_int64_t d; /* deadline */ + u_int64_t e; /* eligible time */ + u_int64_t vt; /* virtual time */ + u_int64_t f; /* fit time for upper-limit */ + + /* info helpful for debugging */ + u_int64_t initvt; /* init virtual time */ + u_int64_t vtoff; /* cl_vt_ipoff */ + u_int64_t cvtmax; /* cl_maxvt */ + u_int64_t myf; /* cl_myf */ + u_int64_t cfmin; /* cl_mincf */ + u_int64_t cvtmin; /* cl_mincvt */ + u_int64_t myfadj; /* cl_myfadj */ + u_int64_t vtadj; /* cl_vtadj */ + u_int64_t cur_time; + u_int32_t machclk_freq; + + u_int vtperiod; /* vt period sequence no */ + u_int parentperiod; /* parent's vt period seqno */ + int nactive; /* number of active children */ + + /* red and rio related info */ + int qtype; +/* struct redstats red[3]; */ +}; + +#ifdef _KERNEL +struct ifnet; +struct ifqueue; +struct pf_queuespec; +struct hfsc_if; + +extern const struct ifq_ops * const ifq_hfsc_ops; +extern const struct pfq_ops * const pfq_hfsc_ops; + +#define HFSC_ENABLED(ifq) ((ifq)->ifq_ops == ifq_hfsc_ops) +#define HFSC_DEFAULT_QLIMIT 50 + +void hfsc_initialize(void); + +#endif /* _KERNEL */ +#endif /* _HFSC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if.h b/lib/libc/include/generic-openbsd/net/if.h new file mode 100644 index 000000000000..f6ccd8ad0edc --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if.h @@ -0,0 +1,576 @@ +/* $OpenBSD: if.h,v 1.221 2025/09/09 09:16:18 bluhm Exp $ */ +/* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NET_IF_H_ +#define _NET_IF_H_ + +#include + +/* + * Length of interface external name, including terminating '\0'. + * Note: this is the same size as a generic device's external name. + */ +#define IF_NAMESIZE 16 + +struct if_nameindex { + unsigned int if_index; + char *if_name; +}; + +#ifndef _KERNEL +__BEGIN_DECLS +unsigned int if_nametoindex(const char *); +char *if_indextoname(unsigned int, char *); +struct if_nameindex *if_nameindex(void); +void if_freenameindex(struct if_nameindex *); +__END_DECLS +#endif + +#if __BSD_VISIBLE + +#include +#include +#include + +/* + * Structure used to query names of interface cloners. + */ +struct if_clonereq { + int ifcr_total; /* total cloners (out) */ + int ifcr_count; /* room for this many in user buffer */ + char *ifcr_buffer; /* buffer for cloner names */ +}; + +#define MCLPOOLS 8 /* number of cluster pools */ + +struct if_rxring { + int rxr_adjusted; + u_int rxr_alive; + u_int rxr_cwm; + u_int rxr_lwm; + u_int rxr_hwm; +}; + +struct if_rxring_info { + char ifr_name[16]; /* name of the ring */ + u_int ifr_size; /* size of the packets on the ring */ + struct if_rxring ifr_info; +}; + +/* Structure used in SIOCGIFRXR request. */ +struct if_rxrinfo { + u_int ifri_total; + struct if_rxring_info *ifri_entries; +}; + +/* + * Structure defining statistics and other data kept regarding a network + * interface. + */ +struct if_data { + /* generic interface information */ + u_char ifi_type; /* ethernet, tokenring, etc. */ + u_char ifi_addrlen; /* media address length */ + u_char ifi_hdrlen; /* media header length */ + u_char ifi_link_state; /* current link state */ + u_int32_t ifi_mtu; /* maximum transmission unit */ + u_int32_t ifi_metric; /* routing metric (external only) */ + u_int32_t ifi_rdomain; /* routing instance */ + u_int64_t ifi_baudrate; /* linespeed */ + /* volatile statistics */ + u_int64_t ifi_ipackets; /* packets received on interface */ + u_int64_t ifi_ierrors; /* input errors on interface */ + u_int64_t ifi_opackets; /* packets sent on interface */ + u_int64_t ifi_oerrors; /* output errors on interface */ + u_int64_t ifi_collisions; /* collisions on csma interfaces */ + u_int64_t ifi_ibytes; /* total number of octets received */ + u_int64_t ifi_obytes; /* total number of octets sent */ + u_int64_t ifi_imcasts; /* packets received via multicast */ + u_int64_t ifi_omcasts; /* packets sent via multicast */ + u_int64_t ifi_iqdrops; /* dropped on input, this interface */ + u_int64_t ifi_oqdrops; /* dropped on output, this interface */ + u_int64_t ifi_noproto; /* destined for unsupported protocol */ + u_int32_t ifi_capabilities; /* interface capabilities */ + struct timeval ifi_lastchange; /* last operational state change */ +}; + +#define IFQ_NQUEUES 8 +#define IFQ_MINPRIO 0 +#define IFQ_MAXPRIO IFQ_NQUEUES - 1 +#define IFQ_DEFPRIO 3 +#define IFQ_PRIO2TOS(_p) ((_p) << 5) +#define IFQ_TOS2PRIO(_t) ((_t) >> 5) + +/* + * Values for if_link_state. + */ +#define LINK_STATE_UNKNOWN 0 /* link unknown */ +#define LINK_STATE_INVALID 1 /* link invalid */ +#define LINK_STATE_DOWN 2 /* link is down */ +#define LINK_STATE_KALIVE_DOWN 3 /* keepalive reports down */ +#define LINK_STATE_UP 4 /* link is up */ +#define LINK_STATE_HALF_DUPLEX 5 /* link is up and half duplex */ +#define LINK_STATE_FULL_DUPLEX 6 /* link is up and full duplex */ + +#define LINK_STATE_IS_UP(_s) \ + ((_s) >= LINK_STATE_UP || (_s) == LINK_STATE_UNKNOWN) + +/* + * Status bit descriptions for the various interface types. + */ +struct if_status_description { + u_char ifs_type; + u_char ifs_state; + const char *ifs_string; +}; + +#define LINK_STATE_DESC_MATCH(_ifs, _t, _s) \ + (((_ifs)->ifs_type == (_t) || (_ifs)->ifs_type == 0) && \ + (_ifs)->ifs_state == (_s)) + + +#define LINK_STATE_DESCRIPTIONS { \ + { IFT_ETHER, LINK_STATE_DOWN, "no carrier" }, \ + \ + { IFT_IEEE80211, LINK_STATE_DOWN, "no network" }, \ + \ + { IFT_PPP, LINK_STATE_DOWN, "no carrier" }, \ + \ + { IFT_CARP, LINK_STATE_DOWN, "backup" }, \ + { IFT_CARP, LINK_STATE_UP, "master" }, \ + { IFT_CARP, LINK_STATE_HALF_DUPLEX, "master" }, \ + { IFT_CARP, LINK_STATE_FULL_DUPLEX, "master" }, \ + \ + { 0, LINK_STATE_UP, "active" }, \ + { 0, LINK_STATE_HALF_DUPLEX, "active" }, \ + { 0, LINK_STATE_FULL_DUPLEX, "active" }, \ + \ + { 0, LINK_STATE_UNKNOWN, "unknown" }, \ + { 0, LINK_STATE_INVALID, "invalid" }, \ + { 0, LINK_STATE_DOWN, "down" }, \ + { 0, LINK_STATE_KALIVE_DOWN, "keepalive down" }, \ + { 0, 0, NULL } \ +} + +/* Traditional BSD name for length of interface external name. */ +#define IFNAMSIZ IF_NAMESIZE + +/* + * Length of interface description, including terminating '\0'. + */ +#define IFDESCRSIZE 64 + +/* + * Interface flags can be either owned by the stack or the driver. The + * symbols below document who is toggling which flag. + * + * I immutable after creation + * N written by the stack (upon user request) + * d written by the driver + * c for userland compatibility only + */ +#define IFF_UP 0x1 /* [N] interface is up */ +#define IFF_BROADCAST 0x2 /* [I] broadcast address valid */ +#define IFF_DEBUG 0x4 /* [N] turn on debugging */ +#define IFF_LOOPBACK 0x8 /* [I] is a loopback net */ +#define IFF_POINTOPOINT 0x10 /* [I] is point-to-point link */ +#define IFF_STATICARP 0x20 /* [N] only static ARP */ +#define IFF_RUNNING 0x40 /* [d] resources allocated */ +#define IFF_NOARP 0x80 /* [N] no address resolution protocol */ +#define IFF_PROMISC 0x100 /* [N] receive all packets */ +#define IFF_ALLMULTI 0x200 /* [d] receive all multicast packets */ +#define IFF_OACTIVE 0x400 /* [c] transmission in progress */ +#define IFF_SIMPLEX 0x800 /* [I] can't hear own transmissions */ +#define IFF_LINK0 0x1000 /* [N] per link layer defined bit */ +#define IFF_LINK1 0x2000 /* [N] per link layer defined bit */ +#define IFF_LINK2 0x4000 /* [N] per link layer defined bit */ +#define IFF_MULTICAST 0x8000 /* [I] supports multicast */ + +/* flags set internally only: */ +#define IFF_CANTCHANGE \ + (IFF_BROADCAST|IFF_LOOPBACK|IFF_POINTOPOINT|IFF_RUNNING|IFF_OACTIVE|\ + IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI) + +#define IFXF_MPSAFE 0x1 /* [I] if_start is mpsafe */ +#define IFXF_CLONED 0x2 /* [I] pseudo interface */ +#define IFXF_AUTOCONF6TEMP 0x4 /* [N] v6 temporary addrs enabled */ +#define IFXF_MPLS 0x8 /* [N] supports MPLS */ +#define IFXF_WOL 0x10 /* [N] wake on lan enabled */ +#define IFXF_AUTOCONF6 0x20 /* [N] v6 autoconf enabled */ +#define IFXF_INET6_NOSOII 0x40 /* [N] don't do RFC 7217 */ +#define IFXF_AUTOCONF4 0x80 /* [N] v4 autoconf (aka dhcp) enabled */ +#define IFXF_MONITOR 0x100 /* [N] only used for bpf */ +#define IFXF_LRO 0x200 /* [N] TCP large recv offload */ + +#define IFXF_CANTCHANGE \ + (IFXF_MPSAFE|IFXF_CLONED) + +/* + * Some convenience macros used for setting ifi_baudrate. + */ +#define IF_Kbps(x) ((x) * 1000ULL) /* kilobits/sec. */ +#define IF_Mbps(x) (IF_Kbps((x) * 1000ULL)) /* megabits/sec. */ +#define IF_Gbps(x) (IF_Mbps((x) * 1000ULL)) /* gigabits/sec. */ + +/* Capabilities that interfaces can advertise. */ +#define IFCAP_CSUM_IPv4 0x00000001 /* can do IPv4 header csum */ +#define IFCAP_CSUM_TCPv4 0x00000002 /* can do IPv4/TCP csum */ +#define IFCAP_CSUM_UDPv4 0x00000004 /* can do IPv4/UDP csum */ +#define IFCAP_VLAN_MTU 0x00000010 /* VLAN-compatible MTU */ +#define IFCAP_VLAN_HWTAGGING 0x00000020 /* hardware VLAN tag support */ +#define IFCAP_VLAN_HWOFFLOAD 0x00000040 /* hw offload w/ inline tag */ +#define IFCAP_CSUM_TCPv6 0x00000080 /* can do IPv6/TCP checksums */ +#define IFCAP_CSUM_UDPv6 0x00000100 /* can do IPv6/UDP checksums */ +#define IFCAP_TSOv4 0x00001000 /* IPv4/TCP segment offload */ +#define IFCAP_TSOv6 0x00002000 /* IPv6/TCP segment offload */ +#define IFCAP_LRO 0x00004000 /* TCP large recv offload */ +#define IFCAP_WOL 0x00008000 /* can do wake on lan */ + +#define IFCAP_CSUM_MASK (IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 | \ + IFCAP_CSUM_UDPv4 | IFCAP_CSUM_TCPv6 | IFCAP_CSUM_UDPv6) + +/* symbolic names for terminal (per-protocol) CTL_IFQ_ nodes */ +#define IFQCTL_LEN 1 +#define IFQCTL_MAXLEN 2 +#define IFQCTL_DROPS 3 +#define IFQCTL_CONGESTION 4 +#define IFQCTL_MAXID 5 + +/* sysctl for ifq (per-protocol packet input queue variant of ifqueue) */ +#define CTL_IFQ_NAMES { \ + { 0, 0 }, \ + { "len", CTLTYPE_INT }, \ + { "maxlen", CTLTYPE_INT }, \ + { "drops", CTLTYPE_INT }, \ + { "congestion", CTLTYPE_INT }, \ +} + +/* + * Message format for use in obtaining information about interfaces + * from sysctl and the routing socket. + */ +struct if_msghdr { + u_short ifm_msglen; /* to skip over non-understood messages */ + u_char ifm_version; /* future binary compatibility */ + u_char ifm_type; /* message type */ + u_short ifm_hdrlen; /* sizeof(if_msghdr) to skip over the header */ + u_short ifm_index; /* index for associated ifp */ + u_short ifm_tableid; /* routing table id */ + u_char ifm_pad1; + u_char ifm_pad2; + int ifm_addrs; /* like rtm_addrs */ + int ifm_flags; /* value of if_flags */ + int ifm_xflags; + struct if_data ifm_data;/* statistics and other data about if */ +}; + +/* + * Message format for use in obtaining information about interface addresses + * from sysctl and the routing socket. + */ +struct ifa_msghdr { + u_short ifam_msglen; /* to skip over non-understood messages */ + u_char ifam_version; /* future binary compatibility */ + u_char ifam_type; /* message type */ + u_short ifam_hdrlen; /* sizeof(ifa_msghdr) to skip over the header */ + u_short ifam_index; /* index for associated ifp */ + u_short ifam_tableid; /* routing table id */ + u_char ifam_pad1; + u_char ifam_pad2; + int ifam_addrs; /* like rtm_addrs */ + int ifam_flags; /* value of ifa_flags */ + int ifam_metric; /* value of ifa_metric */ +}; + +/* + * Message format announcing the arrival or departure of a network interface. + */ +struct if_announcemsghdr { + u_short ifan_msglen; /* to skip over non-understood messages */ + u_char ifan_version; /* future binary compatibility */ + u_char ifan_type; /* message type */ + u_short ifan_hdrlen; /* sizeof(if_announcemsghdr) to skip header */ + u_short ifan_index; /* index for associated ifp */ + u_short ifan_what; /* what type of announcement */ + char ifan_name[IFNAMSIZ]; /* if name, e.g. "en0" */ +}; + +#define IFAN_ARRIVAL 0 /* interface arrival */ +#define IFAN_DEPARTURE 1 /* interface departure */ + +/* message format used to pass 80211 interface info */ +struct if_ieee80211_data { + uint8_t ifie_channel; /* IEEE80211_CHAN_MAX == 255 */ + uint8_t ifie_nwid_len; + uint32_t ifie_flags; /* ieee80211com.ic_flags */ + uint32_t ifie_xflags; /* ieee80211com.ic xflags */ + uint8_t ifie_nwid[32]; /* IEEE80211_NWID_LEN */ + uint8_t ifie_addr[6]; /* IEEE80211_ADDR_LEN */ +}; + +struct if_ieee80211_msghdr { + uint16_t ifim_msglen; + uint8_t ifim_version; + uint8_t ifim_type; + uint16_t ifim_hdrlen; + uint16_t ifim_index; + uint16_t ifim_tableid; + + struct if_ieee80211_data ifim_ifie; +}; + +/* message format used to pass interface name to index mappings */ +struct if_nameindex_msg { + unsigned int if_index; + char if_name[IFNAMSIZ]; +}; + +/* + * interface groups + */ + +#define IFG_ALL "all" /* group contains all interfaces */ +#define IFG_EGRESS "egress" /* if(s) default route(s) point to */ + +struct ifg_req { + union { + char ifgrqu_group[IFNAMSIZ]; + char ifgrqu_member[IFNAMSIZ]; + } ifgrq_ifgrqu; +#define ifgrq_group ifgrq_ifgrqu.ifgrqu_group +#define ifgrq_member ifgrq_ifgrqu.ifgrqu_member +}; + +struct ifg_attrib { + int ifg_carp_demoted; +}; + +/* + * Used to lookup groups for an interface + */ +struct ifgroupreq { + char ifgr_name[IFNAMSIZ]; + u_int ifgr_len; + union { + char ifgru_group[IFNAMSIZ]; + struct ifg_req *ifgru_groups; + struct ifg_attrib ifgru_attrib; + } ifgr_ifgru; +#define ifgr_group ifgr_ifgru.ifgru_group +#define ifgr_groups ifgr_ifgru.ifgru_groups +#define ifgr_attrib ifgr_ifgru.ifgru_attrib +}; + +/* + * Interface request structure used for socket + * ioctl's. All interface ioctl's must have parameter + * definitions which begin with ifr_name. The + * remainder may be interface specific. + */ +struct ifreq { + char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + union { + struct sockaddr ifru_addr; + struct sockaddr ifru_dstaddr; + struct sockaddr ifru_broadaddr; + short ifru_flags; + int ifru_metric; + int64_t ifru_vnetid; + uint64_t ifru_media; + caddr_t ifru_data; + unsigned int ifru_index; + } ifr_ifru; +#define ifr_addr ifr_ifru.ifru_addr /* address */ +#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p link */ +#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ +#define ifr_flags ifr_ifru.ifru_flags /* flags */ +#define ifr_metric ifr_ifru.ifru_metric /* metric */ +#define ifr_mtu ifr_ifru.ifru_metric /* mtu (overload) */ +#define ifr_hardmtu ifr_ifru.ifru_metric /* hardmtu (overload) */ +#define ifr_media ifr_ifru.ifru_media /* media options */ +#define ifr_rdomainid ifr_ifru.ifru_metric /* VRF instance (overload) */ +#define ifr_vnetid ifr_ifru.ifru_vnetid /* Virtual Net Id */ +#define ifr_ttl ifr_ifru.ifru_metric /* tunnel TTL (overload) */ +#define ifr_df ifr_ifru.ifru_metric /* tunnel DF (overload) */ +#define ifr_data ifr_ifru.ifru_data /* for use by interface */ +#define ifr_index ifr_ifru.ifru_index /* interface index */ +#define ifr_llprio ifr_ifru.ifru_metric /* link layer priority */ +#define ifr_hdrprio ifr_ifru.ifru_metric /* header prio field config */ +#define ifr_pwe3 ifr_ifru.ifru_metric /* PWE3 type */ +}; + +#define IF_HDRPRIO_MIN IFQ_MINPRIO +#define IF_HDRPRIO_MAX IFQ_MAXPRIO +#define IF_HDRPRIO_PACKET -1 /* use mbuf prio */ +#define IF_HDRPRIO_PAYLOAD -2 /* copy payload prio */ +#define IF_HDRPRIO_OUTER -3 /* use outer prio */ + +#define IF_PWE3_ETHERNET 1 /* ethernet or ethernet tagged */ +#define IF_PWE3_IP 2 /* IP layer 2 */ + +struct ifaliasreq { + char ifra_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + union { + struct sockaddr ifrau_addr; + int ifrau_align; + } ifra_ifrau; +#ifndef ifra_addr +#define ifra_addr ifra_ifrau.ifrau_addr +#endif + struct sockaddr ifra_dstaddr; +#define ifra_broadaddr ifra_dstaddr + struct sockaddr ifra_mask; +}; + +struct ifmediareq { + char ifm_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + uint64_t ifm_current; /* get/set current media options */ + uint64_t ifm_mask; /* don't care mask */ + uint64_t ifm_status; /* media status */ + uint64_t ifm_active; /* active options */ + int ifm_count; /* # entries in ifm_ulist array */ + uint64_t *ifm_ulist; /* media words */ +}; + +struct ifkalivereq { + char ikar_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + int ikar_timeo; + int ikar_cnt; +}; + +/* + * Structure used in SIOCGIFCONF request. + * Used to retrieve interface configuration + * for machine (useful for programs which + * must know all networks accessible). + */ +struct ifconf { + int ifc_len; /* size of associated buffer */ + union { + caddr_t ifcu_buf; + struct ifreq *ifcu_req; + } ifc_ifcu; +#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */ +#define ifc_req ifc_ifcu.ifcu_req /* array of structures returned */ +}; + +/* + * Structure for SIOC[AGD]LIFADDR + */ +struct if_laddrreq { + char iflr_name[IFNAMSIZ]; + unsigned int flags; +#define IFLR_PREFIX 0x8000 /* in: prefix given out: kernel fills id */ + unsigned int prefixlen; /* in/out */ + struct sockaddr_storage addr; /* in/out */ + struct sockaddr_storage dstaddr; /* out */ +}; + +/* SIOCIFAFDETACH */ +struct if_afreq { + char ifar_name[IFNAMSIZ]; + sa_family_t ifar_af; +}; + +/* SIOC[SG]IFPARENT */ +struct if_parent { + char ifp_name[IFNAMSIZ]; + char ifp_parent[IFNAMSIZ]; +}; + +/* SIOCGIFSFFPAGE */ + +#define IFSFF_ADDR_EEPROM 0xa0 +#define IFSFF_ADDR_DDM 0xa2 + +#define IFSFF_DATA_LEN 256 + +struct if_sffpage { + char sff_ifname[IFNAMSIZ]; /* u -> k */ + uint8_t sff_addr; /* u -> k */ + uint8_t sff_page; /* u -> k */ + uint8_t sff_data[IFSFF_DATA_LEN]; /* k -> u */ +}; + +#include + +#ifdef _KERNEL +struct socket; +struct ifnet; +struct ifq_ops; + +void if_alloc_sadl(struct ifnet *); +void if_free_sadl(struct ifnet *); +void if_attach(struct ifnet *); +void if_attach_queues(struct ifnet *, unsigned int); +void if_attach_iqueues(struct ifnet *, unsigned int); +void if_attach_ifq(struct ifnet *, const struct ifq_ops *, void *); +void if_attachhead(struct ifnet *); +void if_deactivate(struct ifnet *); +void if_detach(struct ifnet *); +void if_down(struct ifnet *); +void if_downall(void); +void if_link_state_change(struct ifnet *); +void if_up(struct ifnet *); +void if_getdata(struct ifnet *, struct if_data *); +void ifinit(void); +int ifioctl(struct socket *, u_long, caddr_t, struct proc *); +int ifpromisc(struct ifnet *, int); +int ifsetlro(struct ifnet *, int); +struct ifg_group *if_creategroup(const char *); +int if_addgroup(struct ifnet *, const char *); +int if_delgroup(struct ifnet *, const char *); +void if_group_routechange(const struct sockaddr *, const struct sockaddr *); +struct ifnet *if_unit(const char *); +struct ifnet *if_get(unsigned int); +struct ifnet *if_ref(struct ifnet *); +void if_put(struct ifnet *); +void ifnewlladdr(struct ifnet *); +void if_congestion(void); +int if_congested(void); +__dead void unhandled_af(int); +int if_setlladdr(struct ifnet *, const uint8_t *); +void softnet_init(void); +void softnet_percpu(void); +unsigned int + softnet_count(void); +struct taskq * + net_tq(unsigned int); +void net_tq_barriers(const char *); + +#endif /* _KERNEL */ + +#endif /* __BSD_VISIBLE */ + +#endif /* _NET_IF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_arp.h b/lib/libc/include/generic-openbsd/net/if_arp.h new file mode 100644 index 000000000000..a9d69b750d0d --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_arp.h @@ -0,0 +1,74 @@ +/* $OpenBSD: if_arp.h,v 1.8 2024/10/15 00:41:40 jsg Exp $ */ +/* $NetBSD: if_arp.h,v 1.8 1995/03/08 02:56:52 cgd Exp $ */ + +/* + * Copyright (c) 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_arp.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NET_IF_ARP_H_ +#define _NET_IF_ARP_H_ +/* + * Address Resolution Protocol. + * + * See RFC 826 for protocol description. ARP packets are variable + * in size; the arphdr structure defines the fixed-length portion. + * Protocol type values are the same as those for 10 Mb/s Ethernet. + * It is followed by the variable-sized fields ar_sha, arp_spa, + * arp_tha and arp_tpa in that order, according to the lengths + * specified. Field names used correspond to RFC 826. + */ +struct arphdr { + u_int16_t ar_hrd; /* format of hardware address */ +#define ARPHRD_ETHER 1 /* ethernet hardware format */ +#define ARPHRD_IEEE802 6 /* IEEE 802 hardware format */ +#define ARPHRD_FRELAY 15 /* frame relay hardware format */ +#define ARPHRD_IEEE1394 24 /* IEEE 1394 (FireWire) hardware format */ + u_int16_t ar_pro; /* format of protocol address */ + u_int8_t ar_hln; /* length of hardware address */ + u_int8_t ar_pln; /* length of protocol address */ + u_int16_t ar_op; /* one of: */ +#define ARPOP_REQUEST 1 /* request to resolve address */ +#define ARPOP_REPLY 2 /* response to previous request */ +#define ARPOP_REVREQUEST 3 /* request protocol address given hardware */ +#define ARPOP_REVREPLY 4 /* response giving protocol address */ +#define ARPOP_INVREQUEST 8 /* request to identify peer */ +#define ARPOP_INVREPLY 9 /* response identifying peer */ +/* + * The remaining fields are variable in size, + * according to the sizes above. + */ +#ifdef COMMENT_ONLY + u_int8_t ar_sha[]; /* sender hardware address */ + u_int8_t ar_spa[]; /* sender protocol address */ + u_int8_t ar_tha[]; /* target hardware address */ + u_int8_t ar_tpa[]; /* target protocol address */ +#endif +}; +#endif /* _NET_IF_ARP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_bpe.h b/lib/libc/include/generic-openbsd/net/if_bpe.h new file mode 100644 index 000000000000..1e3d93b7ea3d --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_bpe.h @@ -0,0 +1,26 @@ +/* $OpenBSD: if_bpe.h,v 1.2 2025/03/02 21:28:31 bluhm Exp $ */ + +/* + * Copyright (c) 2018 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _NET_IF_BPE_H +#define _NET_IF_BPE_H + +#ifdef _KERNEL +void bpe_input(struct ifnet *, struct mbuf *, struct netstack *); +#endif + +#endif /* _NET_IF_GRE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_bridge.h b/lib/libc/include/generic-openbsd/net/if_bridge.h new file mode 100644 index 000000000000..f946c669499c --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_bridge.h @@ -0,0 +1,533 @@ +/* $OpenBSD: if_bridge.h,v 1.73 2021/11/11 10:03:10 claudio Exp $ */ + +/* + * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) + * Copyright (c) 2006 Andrew Thompson (thompsa@FreeBSD.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + * + * Effort sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F30602-01-2-0537. + * + */ + +#ifndef _NET_IF_BRIDGE_H_ +#define _NET_IF_BRIDGE_H_ + +#include +#include +#include + +/* + * Bridge control request: add/delete member interfaces. + */ +struct ifbreq { + char ifbr_name[IFNAMSIZ]; /* bridge ifs name */ + char ifbr_ifsname[IFNAMSIZ]; /* member ifs name */ + u_int32_t ifbr_ifsflags; /* member ifs flags */ + u_int32_t ifbr_portno; /* member port number */ + u_int32_t ifbr_protected; /* protected domains */ + + u_int8_t ifbr_state; /* member stp state */ + u_int8_t ifbr_priority; /* member stp priority */ + u_int32_t ifbr_path_cost; /* member stp path cost */ + u_int32_t ifbr_stpflags; /* member stp flags */ + u_int8_t ifbr_proto; /* member stp protocol */ + u_int8_t ifbr_role; /* member stp role */ + u_int32_t ifbr_fwd_trans; /* member stp fwd transitions */ + u_int64_t ifbr_desg_bridge; /* member stp designated bridge */ + u_int32_t ifbr_desg_port; /* member stp designated port */ + u_int64_t ifbr_root_bridge; /* member stp root bridge */ + u_int32_t ifbr_root_cost; /* member stp root cost */ + u_int32_t ifbr_root_port; /* member stp root port */ +}; + +/* SIOCBRDGIFFLGS, SIOCBRDGIFFLGS */ +#define IFBIF_LEARNING 0x0001 /* ifs can learn */ +#define IFBIF_DISCOVER 0x0002 /* ifs sends packets w/unknown dest */ +#define IFBIF_BLOCKNONIP 0x0004 /* ifs blocks non-IP/ARP in/out */ +#define IFBIF_STP 0x0008 /* ifs participates in spanning tree */ +#define IFBIF_BSTP_EDGE 0x0010 /* member stp edge port */ +#define IFBIF_BSTP_AUTOEDGE 0x0020 /* member stp autoedge enabled */ +#define IFBIF_BSTP_PTP 0x0040 /* member stp ptp */ +#define IFBIF_BSTP_AUTOPTP 0x0080 /* member stp autoptp enabled */ +#define IFBIF_SPAN 0x0100 /* ifs is a span port (ro) */ +#define IFBIF_LOCAL 0x1000 /* local port in switch(4) */ +#define IFBIF_RO_MASK 0x0f00 /* read only bits */ + +/* SIOCBRDGFLUSH */ +#define IFBF_FLUSHDYN 0x0 /* flush dynamic addresses only */ +#define IFBF_FLUSHALL 0x1 /* flush all addresses from cache */ + +/* port states */ +#define BSTP_IFSTATE_DISABLED 0 +#define BSTP_IFSTATE_LISTENING 1 +#define BSTP_IFSTATE_LEARNING 2 +#define BSTP_IFSTATE_FORWARDING 3 +#define BSTP_IFSTATE_BLOCKING 4 +#define BSTP_IFSTATE_DISCARDING 5 + +#define BSTP_TCSTATE_ACTIVE 1 +#define BSTP_TCSTATE_DETECTED 2 +#define BSTP_TCSTATE_INACTIVE 3 +#define BSTP_TCSTATE_LEARNING 4 +#define BSTP_TCSTATE_PROPAG 5 +#define BSTP_TCSTATE_ACK 6 +#define BSTP_TCSTATE_TC 7 +#define BSTP_TCSTATE_TCN 8 + +#define BSTP_ROLE_DISABLED 0 +#define BSTP_ROLE_ROOT 1 +#define BSTP_ROLE_DESIGNATED 2 +#define BSTP_ROLE_ALTERNATE 3 +#define BSTP_ROLE_BACKUP 4 + +/* + * Interface list structure + */ +struct ifbifconf { + char ifbic_name[IFNAMSIZ]; /* bridge ifs name */ + u_int32_t ifbic_len; /* buffer size */ + union { + caddr_t ifbicu_buf; + struct ifbreq *ifbicu_req; + } ifbic_ifbicu; +#define ifbic_buf ifbic_ifbicu.ifbicu_buf +#define ifbic_req ifbic_ifbicu.ifbicu_req +}; + +/* + * Bridge address request + */ +struct ifbareq { + char ifba_name[IFNAMSIZ]; /* bridge name */ + char ifba_ifsname[IFNAMSIZ]; /* destination ifs */ + u_int8_t ifba_age; /* address age */ + u_int8_t ifba_flags; /* address flags */ + struct ether_addr ifba_dst; /* destination addr */ + struct sockaddr_storage ifba_dstsa; /* tunnel endpoint */ +}; + +#define IFBAF_TYPEMASK 0x03 /* address type mask */ +#define IFBAF_DYNAMIC 0x00 /* dynamically learned */ +#define IFBAF_STATIC 0x01 /* static address */ + +struct ifbaconf { + char ifbac_name[IFNAMSIZ]; /* bridge ifs name */ + u_int32_t ifbac_len; /* buffer size */ + union { + caddr_t ifbacu_buf; /* buffer */ + struct ifbareq *ifbacu_req; /* request pointer */ + } ifbac_ifbacu; +#define ifbac_buf ifbac_ifbacu.ifbacu_buf +#define ifbac_req ifbac_ifbacu.ifbacu_req +}; + +struct ifbrparam { + char ifbrp_name[IFNAMSIZ]; + union { + u_int32_t ifbrpu_csize; /* cache size */ + int ifbrpu_ctime; /* cache time (sec) */ + u_int16_t ifbrpu_prio; /* bridge priority */ + u_int8_t ifbrpu_hellotime; /* hello time (sec) */ + u_int8_t ifbrpu_fwddelay; /* fwd delay (sec) */ + u_int8_t ifbrpu_maxage; /* max age (sec) */ + u_int8_t ifbrpu_proto; /* bridge protocol */ + u_int8_t ifbrpu_txhc; /* bpdu tx holdcount */ + } ifbrp_ifbrpu; +}; +#define ifbrp_csize ifbrp_ifbrpu.ifbrpu_csize +#define ifbrp_ctime ifbrp_ifbrpu.ifbrpu_ctime +#define ifbrp_prio ifbrp_ifbrpu.ifbrpu_prio +#define ifbrp_proto ifbrp_ifbrpu.ifbrpu_proto +#define ifbrp_txhc ifbrp_ifbrpu.ifbrpu_txhc +#define ifbrp_hellotime ifbrp_ifbrpu.ifbrpu_hellotime +#define ifbrp_fwddelay ifbrp_ifbrpu.ifbrpu_fwddelay +#define ifbrp_maxage ifbrp_ifbrpu.ifbrpu_maxage + +/* Protocol versions */ +#define BSTP_PROTO_ID 0x00 +#define BSTP_PROTO_STP 0x00 +#define BSTP_PROTO_RSTP 0x02 +#define BSTP_PROTO_MAX BSTP_PROTO_RSTP + +/* + * Bridge current operational parameters structure. + */ +struct ifbropreq { + char ifbop_name[IFNAMSIZ]; + u_int8_t ifbop_holdcount; + u_int8_t ifbop_maxage; + u_int8_t ifbop_hellotime; + u_int8_t ifbop_fwddelay; + u_int8_t ifbop_protocol; + u_int16_t ifbop_priority; + u_int64_t ifbop_root_bridge; + u_int16_t ifbop_root_port; + u_int32_t ifbop_root_path_cost; + u_int64_t ifbop_desg_bridge; + struct timeval ifbop_last_tc_time; +}; + +/* + * Bridge mac rules + */ +struct ifbrarpf { + u_int16_t brla_flags; + u_int16_t brla_op; + struct ether_addr brla_sha; + struct in_addr brla_spa; + struct ether_addr brla_tha; + struct in_addr brla_tpa; +}; +#define BRLA_ARP 0x01 +#define BRLA_RARP 0x02 +#define BRLA_SHA 0x10 +#define BRLA_SPA 0x20 +#define BRLA_THA 0x40 +#define BRLA_TPA 0x80 + +struct ifbrlreq { + char ifbr_name[IFNAMSIZ]; /* bridge ifs name */ + char ifbr_ifsname[IFNAMSIZ]; /* member ifs name */ + u_int8_t ifbr_action; /* disposition */ + u_int8_t ifbr_flags; /* flags */ + struct ether_addr ifbr_src; /* source mac */ + struct ether_addr ifbr_dst; /* destination mac */ + char ifbr_tagname[PF_TAG_NAME_SIZE]; /* pf tagname */ + struct ifbrarpf ifbr_arpf; /* arp filter */ +}; +#define BRL_ACTION_BLOCK 0x01 /* block frame */ +#define BRL_ACTION_PASS 0x02 /* pass frame */ +#define BRL_FLAG_IN 0x08 /* input rule */ +#define BRL_FLAG_OUT 0x04 /* output rule */ +#define BRL_FLAG_SRCVALID 0x02 /* src valid */ +#define BRL_FLAG_DSTVALID 0x01 /* dst valid */ + +struct ifbrlconf { + char ifbrl_name[IFNAMSIZ]; /* bridge ifs name */ + char ifbrl_ifsname[IFNAMSIZ];/* member ifs name */ + u_int32_t ifbrl_len; /* buffer size */ + union { + caddr_t ifbrlu_buf; + struct ifbrlreq *ifbrlu_req; + } ifbrl_ifbrlu; +#define ifbrl_buf ifbrl_ifbrlu.ifbrlu_buf +#define ifbrl_req ifbrl_ifbrlu.ifbrlu_req +}; + +#ifdef _KERNEL + +#include + +/* STP port flags */ +#define BSTP_PORT_CANMIGRATE 0x0001 +#define BSTP_PORT_NEWINFO 0x0002 +#define BSTP_PORT_DISPUTED 0x0004 +#define BSTP_PORT_ADMCOST 0x0008 +#define BSTP_PORT_AUTOEDGE 0x0010 +#define BSTP_PORT_AUTOPTP 0x0020 + +/* BPDU priority */ +#define BSTP_PDU_SUPERIOR 1 +#define BSTP_PDU_REPEATED 2 +#define BSTP_PDU_INFERIOR 3 +#define BSTP_PDU_INFERIORALT 4 +#define BSTP_PDU_OTHER 5 + +/* BPDU flags */ +#define BSTP_PDU_PRMASK 0x0c /* Port Role */ +#define BSTP_PDU_PRSHIFT 2 /* Port Role offset */ +#define BSTP_PDU_F_UNKN 0x00 /* Unknown port (00) */ +#define BSTP_PDU_F_ALT 0x01 /* Alt/Backup port (01) */ +#define BSTP_PDU_F_ROOT 0x02 /* Root port (10) */ +#define BSTP_PDU_F_DESG 0x03 /* Designated port (11) */ + +#define BSTP_PDU_STPMASK 0x81 /* strip unused STP flags */ +#define BSTP_PDU_RSTPMASK 0x7f /* strip unused RSTP flags */ +#define BSTP_PDU_F_TC 0x01 /* Topology change */ +#define BSTP_PDU_F_P 0x02 /* Proposal flag */ +#define BSTP_PDU_F_L 0x10 /* Learning flag */ +#define BSTP_PDU_F_F 0x20 /* Forwarding flag */ +#define BSTP_PDU_F_A 0x40 /* Agreement flag */ +#define BSTP_PDU_F_TCA 0x80 /* Topology change ack */ + +/* + * Bridge filtering rules + */ +SIMPLEQ_HEAD(brl_head, brl_node); + +struct brl_node { + SIMPLEQ_ENTRY(brl_node) brl_next; /* next rule */ + struct ether_addr brl_src; /* source mac address */ + struct ether_addr brl_dst; /* destination mac address */ + u_int16_t brl_tag; /* pf tag ID */ + u_int8_t brl_action; /* what to do with match */ + u_int8_t brl_flags; /* comparison flags */ + struct ifbrarpf brl_arpf; /* arp filter */ +}; + +struct bstp_timer { + u_int16_t active; + u_int16_t value; + u_int32_t latched; +}; + +struct bstp_pri_vector { + u_int64_t pv_root_id; + u_int32_t pv_cost; + u_int64_t pv_dbridge_id; + u_int16_t pv_dport_id; + u_int16_t pv_port_id; +}; + +struct bstp_config_unit { + struct bstp_pri_vector cu_pv; + u_int16_t cu_message_age; + u_int16_t cu_max_age; + u_int16_t cu_forward_delay; + u_int16_t cu_hello_time; + u_int8_t cu_message_type; + u_int8_t cu_topology_change_ack; + u_int8_t cu_topology_change; + u_int8_t cu_proposal; + u_int8_t cu_agree; + u_int8_t cu_learning; + u_int8_t cu_forwarding; + u_int8_t cu_role; +}; + +struct bstp_tcn_unit { + u_int8_t tu_message_type; +}; + +struct bstp_port { + LIST_ENTRY(bstp_port) bp_next; + unsigned int bp_ifindex; /* parent interface index */ + struct bstp_state *bp_bs; + struct task bp_ltask; /* if linkstate hook */ + u_int8_t bp_active; + u_int8_t bp_protover; + u_int32_t bp_flags; + u_int32_t bp_path_cost; + u_int16_t bp_port_msg_age; + u_int16_t bp_port_max_age; + u_int16_t bp_port_fdelay; + u_int16_t bp_port_htime; + u_int16_t bp_desg_msg_age; + u_int16_t bp_desg_max_age; + u_int16_t bp_desg_fdelay; + u_int16_t bp_desg_htime; + struct bstp_timer bp_edge_delay_timer; + struct bstp_timer bp_forward_delay_timer; + struct bstp_timer bp_hello_timer; + struct bstp_timer bp_message_age_timer; + struct bstp_timer bp_migrate_delay_timer; + struct bstp_timer bp_recent_backup_timer; + struct bstp_timer bp_recent_root_timer; + struct bstp_timer bp_tc_timer; + struct bstp_config_unit bp_msg_cu; + struct bstp_pri_vector bp_desg_pv; + struct bstp_pri_vector bp_port_pv; + u_int16_t bp_port_id; + u_int8_t bp_state; + u_int8_t bp_tcstate; + u_int8_t bp_role; + u_int8_t bp_infois; + u_int8_t bp_tc_ack; + u_int8_t bp_tc_prop; + u_int8_t bp_fdbflush; + u_int8_t bp_priority; + u_int8_t bp_ptp_link; + u_int8_t bp_agree; + u_int8_t bp_agreed; + u_int8_t bp_sync; + u_int8_t bp_synced; + u_int8_t bp_proposing; + u_int8_t bp_proposed; + u_int8_t bp_operedge; + u_int8_t bp_reroot; + u_int8_t bp_rcvdtc; + u_int8_t bp_rcvdtca; + u_int8_t bp_rcvdtcn; + u_int32_t bp_forward_transitions; + u_int8_t bp_txcount; +}; + +/* + * Software state for each bridge STP. + */ +struct bstp_state { + unsigned int bs_ifindex; + struct bstp_pri_vector bs_bridge_pv; + struct bstp_pri_vector bs_root_pv; + struct bstp_port *bs_root_port; + u_int8_t bs_protover; + u_int16_t bs_migration_delay; + u_int16_t bs_edge_delay; + u_int16_t bs_bridge_max_age; + u_int16_t bs_bridge_fdelay; + u_int16_t bs_bridge_htime; + u_int16_t bs_root_msg_age; + u_int16_t bs_root_max_age; + u_int16_t bs_root_fdelay; + u_int16_t bs_root_htime; + u_int16_t bs_hold_time; + u_int16_t bs_bridge_priority; + u_int8_t bs_txholdcount; + u_int8_t bs_allsynced; + struct timeout bs_bstptimeout; /* stp timeout */ + struct bstp_timer bs_link_timer; + struct timeval bs_last_tc_time; + LIST_HEAD(, bstp_port) bs_bplist; +}; + +/* + * Bridge interface list + * + * Locks used to protect struct members in this file: + * I immutable after creation + * k kernel lock + */ +struct bridge_iflist { + SMR_SLIST_ENTRY(bridge_iflist) bif_next; /* [k] next in list */ + struct bridge_softc *bridge_sc; /* [I] sc backpointer */ + struct bstp_port *bif_stp; /* [I] STP port state */ + struct brl_head bif_brlin; /* [k] input rules */ + struct brl_head bif_brlout; /* [k] output rules */ + struct ifnet *ifp; /* [I] net interface */ + u_int32_t bif_flags; /* member flags */ + u_int32_t bif_protected; /* protected domains */ + struct task bif_dtask; +}; +#define bif_state bif_stp->bp_state + +/* + * XXX ip_ipsp.h's sockaddr_union should be converted to sockaddr * + * passing with correct sa_len, then a good approach for cleaning this + * will become more clear. + */ +union brsockaddr_union { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; +}; + +/* + * Bridge tunnel tagging + */ +struct bridge_tunneltag { + union brsockaddr_union brtag_peer; + union brsockaddr_union brtag_local; + u_int32_t brtag_id; +}; + +/* + * Bridge route node + */ +struct bridge_rtnode { + LIST_ENTRY(bridge_rtnode) brt_next; /* next in list */ + unsigned int brt_ifidx; /* destination ifs */ + u_int8_t brt_flags; /* address flags */ + u_int8_t brt_age; /* age counter */ + struct ether_addr brt_addr; /* dst addr */ + struct bridge_tunneltag brt_tunnel; /* tunnel endpoint */ +}; +#define brt_family brt_tunnel.brtag_peer.sa.sa_family + +#ifndef BRIDGE_RTABLE_SIZE +#define BRIDGE_RTABLE_SIZE 1024 +#endif +#define BRIDGE_RTABLE_MASK (BRIDGE_RTABLE_SIZE - 1) + +/* + * Software state for each bridge + * + * Locks used to protect struct members in this file: + * I immutable after creation + * m per-softc mutex + * k kernel lock + */ +struct bridge_softc { + struct ifnet sc_if; /* the interface */ + uint32_t sc_brtmax; /* [m] max # addresses */ + uint32_t sc_brtcnt; /* [m] current # addrs */ + int sc_brttimeout; /* timeout ticks */ + uint64_t sc_hashkey[2]; /* [I] siphash key */ + struct timeout sc_brtimeout; /* timeout state */ + struct bstp_state *sc_stp; /* stp state */ + SMR_SLIST_HEAD(, bridge_iflist) sc_iflist; /* [k] interface list */ + SMR_SLIST_HEAD(, bridge_iflist) sc_spanlist; /* [k] span ports */ + struct mutex sc_mtx; /* mutex */ + LIST_HEAD(, bridge_rtnode) sc_rts[BRIDGE_RTABLE_SIZE]; /* [m] hash table */ +}; + +extern const u_int8_t bstp_etheraddr[]; +struct llc; + +int bridge_enqueue(struct ifnet *, struct mbuf *); +void bridge_update(struct ifnet *, struct ether_addr *, int); +void bridge_rtdelete(struct bridge_softc *, struct ifnet *, int); +void bridge_rtagenode(struct ifnet *, int); +struct bridge_tunneltag *bridge_tunnel(struct mbuf *); +struct bridge_tunneltag *bridge_tunneltag(struct mbuf *); +void bridge_tunneluntag(struct mbuf *); +void bridge_copyaddr(struct sockaddr *, struct sockaddr *); +void bridge_copytag(struct bridge_tunneltag *, struct bridge_tunneltag *); + +struct bstp_state *bstp_create(void); +void bstp_enable(struct bstp_state *bs, unsigned int); +void bstp_disable(struct bstp_state *bs); +void bstp_destroy(struct bstp_state *); +void bstp_initialization(struct bstp_state *); +void bstp_stop(struct bstp_state *); +int bstp_ioctl(struct ifnet *, u_long, caddr_t); +struct bstp_port *bstp_add(struct bstp_state *, struct ifnet *); +void bstp_delete(struct bstp_port *); +struct mbuf *bstp_input(struct bstp_state *, struct bstp_port *, + struct ether_header *, struct mbuf *); +void bstp_ifstate(void *); +u_int8_t bstp_getstate(struct bstp_state *, struct bstp_port *); +void bstp_ifsflags(struct bstp_port *, u_int); + +int bridgectl_ioctl(struct ifnet *, u_long, caddr_t); +int bridge_rtupdate(struct bridge_softc *, + struct ether_addr *, struct ifnet *, int, u_int8_t, struct mbuf *); +unsigned int bridge_rtlookup(struct ifnet *, + struct ether_addr *, struct mbuf *); +void bridge_rtflush(struct bridge_softc *, int); +void bridge_rtage(void *); + +u_int8_t bridge_filterrule(struct brl_head *, struct ether_header *, + struct mbuf *); +void bridge_flushrule(struct bridge_iflist *); + +void bridge_fragment(struct ifnet *, struct ifnet *, struct ether_header *, + struct mbuf *); +struct bridge_iflist *bridge_getbif(struct ifnet *); +int bridge_findbif(struct bridge_softc *, const char *, + struct bridge_iflist **); + +#endif /* _KERNEL */ +#endif /* _NET_IF_BRIDGE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_dl.h b/lib/libc/include/generic-openbsd/net/if_dl.h new file mode 100644 index 000000000000..6ea4a24620bd --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_dl.h @@ -0,0 +1,101 @@ +/* $OpenBSD: if_dl.h,v 1.13 2023/11/12 17:51:40 bluhm Exp $ */ +/* $NetBSD: if_dl.h,v 1.8 1995/03/26 20:30:13 jtc Exp $ */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_dl.h 8.1 (Berkeley) 6/10/93 + */ + +/* + * A Link-Level Sockaddr may specify the interface in one of two + * ways: either by means of a system-provided index number (computed + * anew and possibly differently on every reboot), or by a human-readable + * string such as "il0" (for managerial convenience). + * + * Census taking actions, such as something akin to SIOCGCONF would return + * both the index and the human name. + * + * High volume transactions (such as giving a link-level ``from'' address + * in a recvfrom or recvmsg call) may be likely only to provide the indexed + * form, (which requires fewer copy operations and less space). + * + * The form and interpretation of the link-level address is purely a matter + * of convention between the device driver and its consumers; however, it is + * expected that all drivers for an interface of a given if_type will agree. + */ + +#ifndef _NET_IF_DL_H_ +#define _NET_IF_DL_H_ + +/* + * Structure of a Link-Level sockaddr: + */ +struct sockaddr_dl { + u_char sdl_len; /* Total length of sockaddr */ + u_char sdl_family; /* AF_LINK */ + u_int16_t sdl_index; /* if != 0, system given index for interface */ + u_char sdl_type; /* interface type */ + u_char sdl_nlen; /* interface name length, no trailing 0 reqd. */ + u_char sdl_alen; /* link level address length */ + u_char sdl_slen; /* link layer selector length, mostly 0 */ + char sdl_data[24]; /* minimum work area, can be larger; + contains both if name and ll address; + big enough for IFNAMSIZ plus 8byte ll addr */ +}; + +#define LLADDR(s) ((caddr_t)((s)->sdl_data + (s)->sdl_nlen)) + +#ifdef _KERNEL + +static inline struct sockaddr_dl * +satosdl(struct sockaddr *sa) +{ + return ((struct sockaddr_dl *)(sa)); +} + +static inline const struct sockaddr_dl * +satosdl_const(const struct sockaddr *sa) +{ + return ((const struct sockaddr_dl *)(sa)); +} + +static inline struct sockaddr * +sdltosa(struct sockaddr_dl *sdl) +{ + return ((struct sockaddr *)(sdl)); +} + +#else /* _KERNEL */ + +__BEGIN_DECLS +char *link_ntoa(const struct sockaddr_dl *); +__END_DECLS + +#endif /* _KERNEL */ +#endif /* _NET_IF_DL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_enc.h b/lib/libc/include/generic-openbsd/net/if_enc.h new file mode 100644 index 000000000000..b2b875f1aefb --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_enc.h @@ -0,0 +1,42 @@ +/* $OpenBSD: if_enc.h,v 1.13 2021/12/01 21:48:00 deraadt Exp $ */ + +/* + * Copyright (c) 2010 Reyk Floeter + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _NET_ENC_H +#define _NET_ENC_H + +#define ENCMTU 1536 /* XXX should be bigger, maybe LOMTU */ +#define ENC_HDRLEN 12 + +struct enchdr { + u_int32_t af; + u_int32_t spi; + u_int32_t flags; /* similar to mbuf m_flags */ +}; + +#ifdef _KERNEL +struct enc_softc { + struct ifnet sc_if; /* virtual interface */ + u_int sc_unit; + struct ifaddr sc_ifa; /* needed to attach rtentry */ +}; + +struct ifnet *enc_getif(u_int, u_int); +struct ifaddr *enc_getifa(u_int, u_int); +#endif /* _KERNEL */ + +#endif /* _NET_ENC_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_etherbridge.h b/lib/libc/include/generic-openbsd/net/if_etherbridge.h new file mode 100644 index 000000000000..57bfe0ad581d --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_etherbridge.h @@ -0,0 +1,102 @@ +/* $OpenBSD: if_etherbridge.h,v 1.5 2024/11/04 00:13:15 jsg Exp $ */ + +/* + * Copyright (c) 2018, 2021 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _NET_ETHERBRIDGE_H_ +#define _NET_ETHERBRIDGE_H_ + +#define ETHERBRIDGE_TABLE_BITS 8 +#define ETHERBRIDGE_TABLE_SIZE (1U << ETHERBRIDGE_TABLE_BITS) +#define ETHERBRIDGE_TABLE_MASK (ETHERBRIDGE_TABLE_SIZE - 1) + +struct etherbridge_ops { + int (*eb_op_port_eq)(void *, void *, void *); + void *(*eb_op_port_take)(void *, void *); + void (*eb_op_port_rele)(void *, void *); + size_t (*eb_op_port_ifname)(void *, char *, size_t, void *); + void (*eb_op_port_sa)(void *, struct sockaddr_storage *, void *); +}; + +struct etherbridge; + +struct eb_entry { + SMR_TAILQ_ENTRY(eb_entry) ebe_lentry; + union { + RBT_ENTRY(eb_entry) _ebe_tentry; + TAILQ_ENTRY(eb_entry) _ebe_qentry; + } _ebe_entries; +#define ebe_tentry _ebe_entries._ebe_tentry +#define ebe_qentry _ebe_entries._ebe_qentry + + uint64_t ebe_addr; + void *ebe_port; + unsigned int ebe_type; +#define EBE_DYNAMIC 0x0 +#define EBE_STATIC 0x1 +#define EBE_DEAD 0xdead + time_t ebe_age; + + struct etherbridge *ebe_etherbridge; + struct smr_entry ebe_smr_entry; +}; + +SMR_TAILQ_HEAD(eb_list, eb_entry); +RBT_HEAD(eb_tree, eb_entry); +TAILQ_HEAD(eb_queue, eb_entry); + +struct etherbridge { + const char *eb_name; + const struct etherbridge_ops *eb_ops; + void *eb_cookie; + + struct mutex eb_lock; + unsigned int eb_num; + unsigned int eb_max; + int eb_max_age; /* seconds */ + struct timeout eb_tmo_age; + + struct eb_list *eb_table; + struct eb_tree eb_tree; + +}; + +int etherbridge_init(struct etherbridge *, const char *, + const struct etherbridge_ops *, void *); +int etherbridge_up(struct etherbridge *); +int etherbridge_down(struct etherbridge *); +void etherbridge_destroy(struct etherbridge *); + +void etherbridge_map(struct etherbridge *, void *, uint64_t); +void etherbridge_map_ea(struct etherbridge *, void *, + const struct ether_addr *); +void *etherbridge_resolve(struct etherbridge *, uint64_t); +void *etherbridge_resolve_ea(struct etherbridge *, + const struct ether_addr *); +void etherbridge_detach_port(struct etherbridge *, void *); + +/* ioctl support */ +int etherbridge_set_max(struct etherbridge *, struct ifbrparam *); +int etherbridge_get_max(struct etherbridge *, struct ifbrparam *); +int etherbridge_set_tmo(struct etherbridge *, struct ifbrparam *); +int etherbridge_get_tmo(struct etherbridge *, struct ifbrparam *); +int etherbridge_rtfind(struct etherbridge *, struct ifbaconf *); +int etherbridge_add_addr(struct etherbridge *, void *, + const struct ether_addr *, unsigned int); +int etherbridge_del_addr(struct etherbridge *, const struct ether_addr *); +void etherbridge_flush(struct etherbridge *, uint32_t); + +#endif /* _NET_ETHERBRIDGE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_etherip.h b/lib/libc/include/generic-openbsd/net/if_etherip.h new file mode 100644 index 000000000000..0f310db10254 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_etherip.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2015 Kazuya GODA + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _NET_IF_ETHERIP_H_ +#define _NET_IF_ETHERIP_H_ + +int etherip_sysctl(int *, uint, void *, size_t *, void *, size_t); +int ip_etherip_output(struct ifnet *, struct mbuf *); +int ip_etherip_input(struct mbuf **, int *, int, int, struct netstack *); + +#ifdef INET6 +int ip6_etherip_output(struct ifnet *, struct mbuf *); +int ip6_etherip_input(struct mbuf **, int *, int, int, struct netstack *); +#endif /* INET6 */ + +#endif /* _NET_IF_ETHERIP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_gif.h b/lib/libc/include/generic-openbsd/net/if_gif.h new file mode 100644 index 000000000000..65f8895b3dc3 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_gif.h @@ -0,0 +1,43 @@ +/* $OpenBSD: if_gif.h,v 1.19 2025/03/02 21:28:31 bluhm Exp $ */ +/* $KAME: if_gif.h,v 1.17 2000/09/11 11:36:41 sumikawa Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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. + */ + +/* + * if_gif.h + */ + +#ifndef _NET_IF_GIF_H_ +#define _NET_IF_GIF_H_ + +int in_gif_input(struct mbuf **, int *, int, int, struct netstack *); +int in6_gif_input(struct mbuf **, int *, int, int, struct netstack *); + +#endif /* _NET_IF_GIF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_gre.h b/lib/libc/include/generic-openbsd/net/if_gre.h new file mode 100644 index 000000000000..01e65156fba6 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_gre.h @@ -0,0 +1,121 @@ +/* $OpenBSD: if_gre.h,v 1.17 2025/03/02 21:28:31 bluhm Exp $ */ +/* $NetBSD: if_gre.h,v 1.5 1999/11/19 20:41:19 thorpej Exp $ */ + +/* + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved + * + * This code is derived from software contributed to The NetBSD Foundation + * by Heiko W.Rupp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _NET_IF_GRE_H +#define _NET_IF_GRE_H + +struct gre_h { + u_int16_t flags; /* GRE flags */ + u_int16_t ptype; /* protocol type of payload typically + Ether protocol type*/ +/* + * from here on: fields are optional, presence indicated by flags + * + u_int_16 checksum checksum (one-complements of GRE header + and payload + Present if (ck_pres | rt_pres == 1). + Valid if (ck_pres == 1). + u_int_16 offset offset from start of routing filed to + first octet of active SRE (see below). + Present if (ck_pres | rt_pres == 1). + Valid if (rt_pres == 1). + u_int_32 key inserted by encapsulator e.g. for + authentication + Present if (key_pres ==1 ). + u_int_32 seq_num Sequence number to allow for packet order + Present if (seq_pres ==1 ). + + struct gre_sre[] routing Routing fields (see below) + Present if (rt_pres == 1) +*/ +} __packed; + +struct greip { + struct ip gi_i; + struct gre_h gi_g; +} __packed; + +#define gi_pr gi_i.ip_p +#define gi_len gi_i.ip_len +#define gi_src gi_i.ip_src +#define gi_dst gi_i.ip_dst +#define gi_ptype gi_g.ptype +#define gi_flags gi_g.flags + +#define GRE_CP 0x8000 /* Checksum Present */ +#define GRE_RP 0x4000 /* Routing Present */ +#define GRE_KP 0x2000 /* Key Present */ +#define GRE_SP 0x1000 /* Sequence Present */ +#define GRE_SS 0x0800 /* Strict Source Route */ + +/* gre_sre defines a Source route Entry. These are needed if packets + * should be routed over more than one tunnel hop by hop + */ + +struct gre_sre { + u_int16_t sre_family; /* address family */ + u_char sre_offset; /* offset to first octet of active entry */ + u_char sre_length; /* number of octets in the SRE. + sre_lengthl==0 -> last entry. */ + u_char *sre_rtinfo; /* the routing information */ +}; + +struct greioctl { + int unit; + struct in_addr addr; +}; + +/* for mobile encaps */ + +struct mobile_h { + u_int16_t proto; /* protocol and S-bit */ + u_int16_t hcrc; /* header checksum */ + u_int32_t odst; /* original destination address */ + u_int32_t osrc; /* original source addr, if S-bit set */ +} __packed; + +struct mobip_h { + struct ip mi; + struct mobile_h mh; +} __packed; + + +#define MOB_H_SIZ_S (sizeof(struct mobile_h) - sizeof(u_int32_t)) +#define MOB_H_SIZ_L (sizeof(struct mobile_h)) +#define MOB_H_SBIT 0x0080 + +#ifdef _KERNEL +int gre_sysctl(int *, u_int, void *, size_t *, void *, size_t); +int gre_input(struct mbuf **, int *, int, int, struct netstack *); +int gre_input6(struct mbuf **, int *, int, int, struct netstack *); +#endif +#endif /* _NET_IF_GRE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_llc.h b/lib/libc/include/generic-openbsd/net/if_llc.h new file mode 100644 index 000000000000..82be68f534e8 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_llc.h @@ -0,0 +1,145 @@ +/* $OpenBSD: if_llc.h,v 1.8 2013/01/17 00:48:04 henning Exp $ */ +/* $NetBSD: if_llc.h,v 1.6 1995/03/08 02:56:57 cgd Exp $ */ + +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_llc.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NET_IF_LLC_H_ +#define _NET_IF_LLC_H_ + +/* + * IEEE 802.2 Link Level Control headers, for use in conjunction with + * 802.{3,4,5} media access control methods. + * + * Headers here do not use bit fields due to shortcomings in many + * compilers. + */ + +struct llc { + u_int8_t llc_dsap; + u_int8_t llc_ssap; + union { + struct { + u_int8_t control; + u_int8_t format_id; + u_int8_t class; + u_int8_t window_x2; + } type_u; + struct { + u_int8_t num_snd_x2; + u_int8_t num_rcv_x2; + } type_i; + struct { + u_int8_t control; + u_int8_t num_rcv_x2; + } type_s; + struct { + u_int8_t control; + struct frmrinfo { + u_int8_t rej_pdu_0; + u_int8_t rej_pdu_1; + u_int8_t frmr_control; + u_int8_t frmr_control_ext; + u_int8_t frmr_cause; + } frmrinfo; + } type_frmr; + struct { + u_int8_t control; + u_int8_t org_code[3]; + u_int16_t ether_type; + } type_snap; + struct { + u_int8_t control; + u_int8_t control_ext; + } type_raw; + } llc_un; +}; +#define llc_control llc_un.type_u.control +#define llc_control_ext llc_un.type_raw.control_ext +#define llc_fid llc_un.type_u.format_id +#define llc_class llc_un.type_u.class +#define llc_window llc_un.type_u.window_x2 +#define llc_frmrinfo llc_un.type_frmr.frmrinfo +#define llc_frmr_pdu0 llc_un.type_frmr.frmrinfo.rej_pdu0 +#define llc_frmr_pdu1 llc_un.type_frmr.frmrinfo.rej_pdu1 +#define llc_frmr_control llc_un.type_frmr.frmrinfo.frmr_control +#define llc_frmr_control_ext llc_un.type_frmr.frmrinfo.frmr_control_ext +#define llc_frmr_cause llc_un.type_frmr.frmrinfo.frmr_control_ext +#define llc_snap llc_un.type_snap + +/* + * Don't use sizeof(struct llc_un) for LLC header sizes + */ +#define LLC_UFRAMELEN 3 +#define LLC_ISFRAMELEN 4 +#define LLC_FRMRLEN 7 +#define LLC_SNAPFRAMELEN 8 + +/* + * Unnumbered LLC format commands + */ +#define LLC_UI 0x3 +#define LLC_UI_P 0x13 +#define LLC_DISC 0x43 +#define LLC_DISC_P 0x53 +#define LLC_UA 0x63 +#define LLC_UA_P 0x73 +#define LLC_TEST 0xe3 +#define LLC_TEST_P 0xf3 +#define LLC_FRMR 0x87 +#define LLC_FRMR_P 0x97 +#define LLC_DM 0x0f +#define LLC_DM_P 0x1f +#define LLC_XID 0xaf +#define LLC_XID_P 0xbf +#define LLC_SABME 0x6f +#define LLC_SABME_P 0x7f + +/* + * Supervisory LLC commands + */ +#define LLC_RR 0x01 +#define LLC_RNR 0x05 +#define LLC_REJ 0x09 + +/* + * Info format - dummy only + */ +#define LLC_INFO 0x00 + +/* + * ISO PDTR 10178 contains among others + */ +#define LLC_8021D_LSAP 0x42 +#define LLC_X25_LSAP 0x7e +#define LLC_SNAP_LSAP 0xaa +#define LLC_ISO_LSAP 0xfe +#endif /* _NET_IF_LLC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_media.h b/lib/libc/include/generic-openbsd/net/if_media.h new file mode 100644 index 000000000000..a365fd1349fb --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_media.h @@ -0,0 +1,972 @@ +/* $OpenBSD: if_media.h,v 1.46 2025/06/13 00:08:16 jsg Exp $ */ +/* $NetBSD: if_media.h,v 1.22 2000/02/17 21:53:16 sommerfeld Exp $ */ + +/*- + * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1997 + * Jonathan Stone and Jason R. Thorpe. All rights reserved. + * + * This software is derived from information provided by Matt Thomas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Jonathan Stone + * and Jason R. Thorpe for the NetBSD Project. + * 4. The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _NET_IF_MEDIA_H_ +#define _NET_IF_MEDIA_H_ + +#ifdef _KERNEL + +struct ifnet; +extern struct mutex ifmedia_mtx; + +#include +/* + * Driver callbacks for media status and change requests. + */ +typedef int (*ifm_change_cb_t)(struct ifnet *); +typedef void (*ifm_stat_cb_t)(struct ifnet *, struct ifmediareq *); + +/* + * Locks used to protect struct members in this file: + * M ifmedia_mtx interface media mutex + */ + +/* + * In-kernel representation of a single supported media type. + */ +struct ifmedia_entry { + TAILQ_ENTRY(ifmedia_entry) ifm_list; + uint64_t ifm_media; /* description of this media attachment */ + u_int ifm_data; /* for driver-specific use */ + void *ifm_aux; /* for driver-specific use */ +}; + +TAILQ_HEAD(ifmedia_list, ifmedia_entry); +/* + * One of these goes into a network interface's softc structure. + * It is used to keep general media state. + */ +struct ifmedia { + uint64_t ifm_mask; /* mask of changes we don't care about */ + uint64_t ifm_media; /* current user-set media word */ + struct ifmedia_entry *ifm_cur; /* [M] currently selected media */ + struct ifmedia_list ifm_list; /* [M] list of all supported media */ + size_t ifm_nwords; /* [M] number of ifm_list entries */ + ifm_change_cb_t ifm_change_cb; /* media change driver callback */ + ifm_stat_cb_t ifm_status_cb; /* media status driver callback */ +}; + +/* Initialize an interface's struct if_media field. */ +void ifmedia_init(struct ifmedia *, uint64_t, ifm_change_cb_t, + ifm_stat_cb_t); + +/* Add one supported medium to a struct ifmedia. */ +void ifmedia_add(struct ifmedia *, uint64_t, int, void *); + +/* Set default media type on initialization. */ +void ifmedia_set(struct ifmedia *, uint64_t); + +/* Common ioctl function for getting/setting media, called by driver. */ +int ifmedia_ioctl(struct ifnet *, struct ifreq *, struct ifmedia *, + u_long); + +/* Locate a media entry */ +int ifmedia_match(struct ifmedia *, uint64_t, uint64_t); + +/* Delete all media for a given media instance */ +void ifmedia_delete_instance(struct ifmedia *, uint64_t); + +/* Compute baudrate for a given media. */ +uint64_t ifmedia_baudrate(uint64_t); +#endif /*_KERNEL */ + +/* + * if_media Options word: + * Bits Use + * ---- ------- + * 0-7 Media subtype MAX SUBTYPE == 255! + * 8-15 Media type + * 16-31 Type specific options + * 32-39 Mode (for multi-mode devices) + * 40-55 Shared (global) options + * 56-63 Instance + */ + +/* + * Ethernet + */ +#define IFM_ETHER 0x0000000000000100ULL +#define IFM_10_T 3 /* 10BaseT - RJ45 */ +#define IFM_10_2 4 /* 10Base2 - Thinnet */ +#define IFM_10_5 5 /* 10Base5 - AUI */ +#define IFM_100_TX 6 /* 100BaseTX - RJ45 */ +#define IFM_100_FX 7 /* 100BaseFX - Fiber */ +#define IFM_100_T4 8 /* 100BaseT4 - 4 pair cat 3 */ +#define IFM_100_VG 9 /* 100VG-AnyLAN */ +#define IFM_100_T2 10 /* 100BaseT2 */ +#define IFM_1000_SX 11 /* 1000BaseSX - multi-mode fiber */ +#define IFM_10_STP 12 /* 10BaseT over shielded TP */ +#define IFM_10_FL 13 /* 10BaseFL - Fiber */ +#define IFM_1000_LX 14 /* 1000baseLX - single-mode fiber */ +#define IFM_1000_CX 15 /* 1000baseCX - 150ohm STP */ +#define IFM_1000_T 16 /* 1000baseT - 4 pair cat 5 */ +#define IFM_1000_TX IFM_1000_T /* for backwards compatibility */ +#define IFM_HPNA_1 17 /* HomePNA 1.0 (1Mb/s) */ +#define IFM_10G_LR 18 /* 10GBase-LR - single-mode fiber */ +#define IFM_10G_SR 19 /* 10GBase-SR - multi-mode fiber */ +#define IFM_10G_CX4 20 /* 10GBase-CX4 - copper */ +#define IFM_2500_SX 21 /* 2500baseSX - multi-mode fiber */ +#define IFM_10G_T 22 /* 10GbaseT cat 6 */ +#define IFM_10G_SFP_CU 23 /* 10G SFP+ direct attached cable */ +#define IFM_10G_LRM 24 /* 10GBase-LRM 850nm Multi-mode */ +#define IFM_40G_CR4 25 /* 40GBase-CR4 */ +#define IFM_40G_SR4 26 /* 40GBase-SR4 */ +#define IFM_40G_LR4 27 /* 40GBase-LR4 */ +#define IFM_1000_KX 28 /* 1000Base-KX backplane */ +#define IFM_10G_KX4 29 /* 10GBase-KX4 backplane */ +#define IFM_10G_KR 30 /* 10GBase-KR backplane */ +#define IFM_10G_CR1 31 /* 10GBase-CR1 Twinax splitter */ +#define IFM_20G_KR2 32 /* 20GBase-KR2 backplane */ +#define IFM_2500_KX 33 /* 2500Base-KX backplane */ +#define IFM_2500_T 34 /* 2500Base-T - RJ45 (NBaseT) */ +#define IFM_5000_T 35 /* 5000Base-T - RJ45 (NBaseT) */ +#define IFM_1000_SGMII 36 /* 1G media interface */ +#define IFM_10G_SFI 37 /* 10G media interface */ +#define IFM_40G_XLPPI 38 /* 40G media interface */ +#define IFM_1000_CX_SGMII 39 /* 1000Base-CX-SGMII */ +#define IFM_40G_KR4 40 /* 40GBase-KR4 */ +#define IFM_10G_ER 41 /* 10GBase-ER */ +#define IFM_100G_CR4 42 /* 100GBase-CR4 */ +#define IFM_100G_SR4 43 /* 100GBase-SR4 */ +#define IFM_100G_KR4 44 /* 100GBase-KR4 */ +#define IFM_100G_LR4 45 /* 100GBase-LR4 */ +#define IFM_56G_R4 46 /* 56GBase-R4 */ +#define IFM_25G_CR 47 /* 25GBase-CR */ +#define IFM_25G_KR 48 /* 25GBase-KR */ +#define IFM_25G_SR 49 /* 25GBase-SR */ +#define IFM_50G_CR2 50 /* 50GBase-CR2 */ +#define IFM_50G_KR2 51 /* 50GBase-KR2 */ +#define IFM_25G_LR 52 /* 25GBase-LR */ +#define IFM_25G_ER 53 /* 25GBase-ER */ +#define IFM_10G_AOC 54 /* 10G Active Optical Cable */ +#define IFM_25G_AOC 55 /* 25G Active Optical Cable */ +#define IFM_40G_AOC 56 /* 40G Active Optical Cable */ +#define IFM_100G_AOC 57 /* 100G Active Optical Cable */ + +#define IFM_ETH_MASTER 0x0000000000010000ULL /* master mode (1000baseT) */ +#define IFM_ETH_RXPAUSE 0x0000000000020000ULL /* receive PAUSE frames */ +#define IFM_ETH_TXPAUSE 0x0000000000040000ULL /* transmit PAUSE frames */ + +/* + * FDDI + */ +#define IFM_FDDI 0x0000000000000300ULL +#define IFM_FDDI_SMF 3 /* Single-mode fiber */ +#define IFM_FDDI_MMF 4 /* Multi-mode fiber */ +#define IFM_FDDI_UTP 5 /* CDDI / UTP */ +#define IFM_FDDI_DA 0x00000100 /* Dual attach / single attach */ + +/* + * IEEE 802.11 Wireless + */ +#define IFM_IEEE80211 0x0000000000000400ULL +#define IFM_IEEE80211_FH1 3 /* Frequency Hopping 1Mbps */ +#define IFM_IEEE80211_FH2 4 /* Frequency Hopping 2Mbps */ +#define IFM_IEEE80211_DS2 5 /* Direct Sequence 2Mbps */ +#define IFM_IEEE80211_DS5 6 /* Direct Sequence 5Mbps*/ +#define IFM_IEEE80211_DS11 7 /* Direct Sequence 11Mbps*/ +#define IFM_IEEE80211_DS1 8 /* Direct Sequence 1Mbps*/ +#define IFM_IEEE80211_DS22 9 /* Direct Sequence 22Mbps */ +#define IFM_IEEE80211_OFDM6 10 /* OFDM 6Mbps */ +#define IFM_IEEE80211_OFDM9 11 /* OFDM 9Mbps */ +#define IFM_IEEE80211_OFDM12 12 /* OFDM 12Mbps */ +#define IFM_IEEE80211_OFDM18 13 /* OFDM 18Mbps */ +#define IFM_IEEE80211_OFDM24 14 /* OFDM 24Mbps */ +#define IFM_IEEE80211_OFDM36 15 /* OFDM 36Mbps */ +#define IFM_IEEE80211_OFDM48 16 /* OFDM 48Mbps */ +#define IFM_IEEE80211_OFDM54 17 /* OFDM 54Mbps */ +#define IFM_IEEE80211_OFDM72 18 /* OFDM 72Mbps */ +#define IFM_IEEE80211_HT_MCS0 19 /* 11n MCS 0 */ +#define IFM_IEEE80211_HT_MCS1 20 /* 11n MCS 1 */ +#define IFM_IEEE80211_HT_MCS2 21 /* 11n MCS 2 */ +#define IFM_IEEE80211_HT_MCS3 22 /* 11n MCS 3 */ +#define IFM_IEEE80211_HT_MCS4 23 /* 11n MCS 4 */ +#define IFM_IEEE80211_HT_MCS5 24 /* 11n MCS 5 */ +#define IFM_IEEE80211_HT_MCS6 25 /* 11n MCS 6 */ +#define IFM_IEEE80211_HT_MCS7 26 /* 11n MCS 7 */ +#define IFM_IEEE80211_HT_MCS8 27 /* 11n MCS 8 */ +#define IFM_IEEE80211_HT_MCS9 28 /* 11n MCS 9 */ +#define IFM_IEEE80211_HT_MCS10 29 /* 11n MCS 10 */ +#define IFM_IEEE80211_HT_MCS11 30 /* 11n MCS 11 */ +#define IFM_IEEE80211_HT_MCS12 31 /* 11n MCS 12 */ +#define IFM_IEEE80211_HT_MCS13 32 /* 11n MCS 13 */ +#define IFM_IEEE80211_HT_MCS14 33 /* 11n MCS 14 */ +#define IFM_IEEE80211_HT_MCS15 34 /* 11n MCS 15 */ +#define IFM_IEEE80211_HT_MCS16 35 /* 11n MCS 16 */ +#define IFM_IEEE80211_HT_MCS17 36 /* 11n MCS 17 */ +#define IFM_IEEE80211_HT_MCS18 37 /* 11n MCS 18 */ +#define IFM_IEEE80211_HT_MCS19 38 /* 11n MCS 19 */ +#define IFM_IEEE80211_HT_MCS20 39 /* 11n MCS 20 */ +#define IFM_IEEE80211_HT_MCS21 40 /* 11n MCS 21 */ +#define IFM_IEEE80211_HT_MCS22 41 /* 11n MCS 22 */ +#define IFM_IEEE80211_HT_MCS23 42 /* 11n MCS 23 */ +#define IFM_IEEE80211_HT_MCS24 43 /* 11n MCS 24 */ +#define IFM_IEEE80211_HT_MCS25 44 /* 11n MCS 25 */ +#define IFM_IEEE80211_HT_MCS26 45 /* 11n MCS 26 */ +#define IFM_IEEE80211_HT_MCS27 46 /* 11n MCS 27 */ +#define IFM_IEEE80211_HT_MCS28 47 /* 11n MCS 28 */ +#define IFM_IEEE80211_HT_MCS29 48 /* 11n MCS 29 */ +#define IFM_IEEE80211_HT_MCS30 49 /* 11n MCS 30 */ +#define IFM_IEEE80211_HT_MCS31 50 /* 11n MCS 31 */ +#define IFM_IEEE80211_HT_MCS32 51 /* 11n MCS 32 */ +#define IFM_IEEE80211_HT_MCS33 52 /* 11n MCS 33 */ +#define IFM_IEEE80211_HT_MCS34 53 /* 11n MCS 34 */ +#define IFM_IEEE80211_HT_MCS35 54 /* 11n MCS 35 */ +#define IFM_IEEE80211_HT_MCS36 55 /* 11n MCS 36 */ +#define IFM_IEEE80211_HT_MCS37 56 /* 11n MCS 37 */ +#define IFM_IEEE80211_HT_MCS38 57 /* 11n MCS 38 */ +#define IFM_IEEE80211_HT_MCS39 58 /* 11n MCS 39 */ +#define IFM_IEEE80211_HT_MCS40 59 /* 11n MCS 40 */ +#define IFM_IEEE80211_HT_MCS41 60 /* 11n MCS 41 */ +#define IFM_IEEE80211_HT_MCS42 61 /* 11n MCS 42 */ +#define IFM_IEEE80211_HT_MCS43 62 /* 11n MCS 43 */ +#define IFM_IEEE80211_HT_MCS44 63 /* 11n MCS 44 */ +#define IFM_IEEE80211_HT_MCS45 64 /* 11n MCS 45 */ +#define IFM_IEEE80211_HT_MCS46 65 /* 11n MCS 46 */ +#define IFM_IEEE80211_HT_MCS47 66 /* 11n MCS 47 */ +#define IFM_IEEE80211_HT_MCS48 67 /* 11n MCS 48 */ +#define IFM_IEEE80211_HT_MCS49 68 /* 11n MCS 49 */ +#define IFM_IEEE80211_HT_MCS50 69 /* 11n MCS 50 */ +#define IFM_IEEE80211_HT_MCS51 70 /* 11n MCS 51 */ +#define IFM_IEEE80211_HT_MCS52 71 /* 11n MCS 52 */ +#define IFM_IEEE80211_HT_MCS53 72 /* 11n MCS 53 */ +#define IFM_IEEE80211_HT_MCS54 73 /* 11n MCS 54 */ +#define IFM_IEEE80211_HT_MCS55 74 /* 11n MCS 55 */ +#define IFM_IEEE80211_HT_MCS56 75 /* 11n MCS 56 */ +#define IFM_IEEE80211_HT_MCS57 76 /* 11n MCS 57 */ +#define IFM_IEEE80211_HT_MCS58 77 /* 11n MCS 58 */ +#define IFM_IEEE80211_HT_MCS59 78 /* 11n MCS 59 */ +#define IFM_IEEE80211_HT_MCS60 79 /* 11n MCS 60 */ +#define IFM_IEEE80211_HT_MCS61 80 /* 11n MCS 61 */ +#define IFM_IEEE80211_HT_MCS62 81 /* 11n MCS 62 */ +#define IFM_IEEE80211_HT_MCS63 82 /* 11n MCS 63 */ +#define IFM_IEEE80211_HT_MCS64 83 /* 11n MCS 64 */ +#define IFM_IEEE80211_HT_MCS65 84 /* 11n MCS 65 */ +#define IFM_IEEE80211_HT_MCS66 85 /* 11n MCS 66 */ +#define IFM_IEEE80211_HT_MCS67 86 /* 11n MCS 67 */ +#define IFM_IEEE80211_HT_MCS68 87 /* 11n MCS 68 */ +#define IFM_IEEE80211_HT_MCS69 88 /* 11n MCS 69 */ +#define IFM_IEEE80211_HT_MCS70 89 /* 11n MCS 70 */ +#define IFM_IEEE80211_HT_MCS71 90 /* 11n MCS 71 */ +#define IFM_IEEE80211_HT_MCS72 91 /* 11n MCS 72 */ +#define IFM_IEEE80211_HT_MCS73 92 /* 11n MCS 73 */ +#define IFM_IEEE80211_HT_MCS74 93 /* 11n MCS 74 */ +#define IFM_IEEE80211_HT_MCS75 94 /* 11n MCS 75 */ +#define IFM_IEEE80211_HT_MCS76 95 /* 11n MCS 76 */ +#define IFM_IEEE80211_VHT_MCS0 96 /* 11ac MCS 0 */ +#define IFM_IEEE80211_VHT_MCS1 97 /* 11ac MCS 1 */ +#define IFM_IEEE80211_VHT_MCS2 98 /* 11ac MCS 2 */ +#define IFM_IEEE80211_VHT_MCS3 99 /* 11ac MCS 3 */ +#define IFM_IEEE80211_VHT_MCS4 100 /* 11ac MCS 4 */ +#define IFM_IEEE80211_VHT_MCS5 101 /* 11ac MCS 5 */ +#define IFM_IEEE80211_VHT_MCS6 102 /* 11ac MCS 6 */ +#define IFM_IEEE80211_VHT_MCS7 103 /* 11ac MCS 7 */ +#define IFM_IEEE80211_VHT_MCS8 104 /* 11ac MCS 8 */ +#define IFM_IEEE80211_VHT_MCS9 105 /* 11ac MCS 9 */ + +#define IFM_IEEE80211_ADHOC 0x0000000000010000ULL /* Operate in Adhoc mode */ +#define IFM_IEEE80211_HOSTAP 0x0000000000020000ULL /* Operate in Host AP mode */ +#define IFM_IEEE80211_IBSS 0x0000000000040000ULL /* Operate in IBSS mode */ +#define IFM_IEEE80211_IBSSMASTER 0x0000000000080000ULL /* Operate as an IBSS master */ +#define IFM_IEEE80211_MONITOR 0x0000000000100000ULL /* Operate in Monitor mode */ + +/* operating mode for multi-mode devices */ +#define IFM_IEEE80211_11A 0x0000000100000000ULL /* 5GHz, OFDM mode */ +#define IFM_IEEE80211_11B 0x0000000200000000ULL /* Direct Sequence mode */ +#define IFM_IEEE80211_11G 0x0000000300000000ULL /* 2GHz, CCK mode */ +#define IFM_IEEE80211_FH 0x0000000400000000ULL /* 2GHz, GFSK mode */ +#define IFM_IEEE80211_11N 0x0000000800000000ULL /* 11n/HT 2GHz/5GHz */ +#define IFM_IEEE80211_11AC 0x0000001000000000ULL /* 11ac/VHT 5GHz */ + +/* + * Digitally multiplexed "Carrier" Serial Interfaces + */ +#define IFM_TDM 0x0000000000000500ULL +#define IFM_TDM_T1 3 /* T1 B8ZS+ESF 24 ts */ +#define IFM_TDM_T1_AMI 4 /* T1 AMI+SF 24 ts */ +#define IFM_TDM_E1 5 /* E1 HDB3+G.703 clearchannel 32 ts */ +#define IFM_TDM_E1_G704 6 /* E1 HDB3+G.703+G.704 channelized 31 ts */ +#define IFM_TDM_E1_AMI 7 /* E1 AMI+G.703 32 ts */ +#define IFM_TDM_E1_AMI_G704 8 /* E1 AMI+G.703+G.704 31 ts */ +#define IFM_TDM_T3 9 /* T3 B3ZS+C-bit 672 ts */ +#define IFM_TDM_T3_M13 10 /* T3 B3ZS+M13 672 ts */ +#define IFM_TDM_E3 11 /* E3 HDB3+G.751 512? ts */ +#define IFM_TDM_E3_G751 12 /* E3 G.751 512 ts */ +#define IFM_TDM_E3_G832 13 /* E3 G.832 512 ts */ +#define IFM_TDM_E1_G704_CRC4 14 /* E1 HDB3+G.703+G.704 31 ts + CRC4 */ +/* + * 6 major ways that networks talk: Drivers enforce independent selection, + * meaning, a driver will ensure that only one of these is set at a time. + * Default is cisco hdlc mode with 32 bit CRC. + */ +#define IFM_TDM_HDLC_CRC16 0x0100 /* Use 16-bit CRC for HDLC instead */ +#define IFM_TDM_PPP 0x0200 /* SPPP (dumb) */ +#define IFM_TDM_FR_ANSI 0x0400 /* Frame Relay + LMI ANSI "Annex D" */ +#define IFM_TDM_FR_CISCO 0x0800 /* Frame Relay + LMI Cisco */ +#define IFM_TDM_FR_ITU 0x1000 /* Frame Relay + LMI ITU "Q933A" */ + +/* operating mode */ +#define IFM_TDM_MASTER 0x0000000100000000ULL /* aka clock source internal */ + +/* + * Common Access Redundancy Protocol + */ +#define IFM_CARP 0x0000000000000600ULL + +/* + * Shared media sub-types + */ +#define IFM_AUTO 0ULL /* Autoselect best media */ +#define IFM_MANUAL 1ULL /* Jumper/dipswitch selects media */ +#define IFM_NONE 2ULL /* Deselect all media */ + +/* + * Shared options + */ +#define IFM_FDX 0x0000010000000000ULL /* Force full duplex */ +#define IFM_HDX 0x0000020000000000ULL /* Force half duplex */ +#define IFM_FLOW 0x0000040000000000ULL /* enable hardware flow control */ +#define IFM_FLAG0 0x0000100000000000ULL /* Driver defined flag */ +#define IFM_FLAG1 0x0000200000000000ULL /* Driver defined flag */ +#define IFM_FLAG2 0x0000400000000000ULL /* Driver defined flag */ +#define IFM_LOOP 0x0000800000000000ULL /* Put hardware in loopback */ + +/* + * Masks + */ +#define IFM_NMASK 0x000000000000ff00ULL /* Network type */ +#define IFM_NSHIFT 8 /* Network type shift */ +#define IFM_TMASK 0x00000000000000ffULL /* Media sub-type */ +#define IFM_TSHIFT 0 /* Sub-type shift */ +#define IFM_IMASK 0xff00000000000000ULL /* Instance */ +#define IFM_ISHIFT 56 /* Instance shift */ +#define IFM_OMASK 0x00000000ffff0000ULL /* Type specific options */ +#define IFM_OSHIFT 16 /* Specific options shift */ +#define IFM_MMASK 0x000000ff00000000ULL /* Mode */ +#define IFM_MSHIFT 32 /* Mode shift */ +#define IFM_GMASK 0x00ffff0000000000ULL /* Global options */ +#define IFM_GSHIFT 40 /* Global options shift */ + +/* Ethernet flow control mask */ +#define IFM_ETH_FMASK (IFM_FLOW|IFM_ETH_RXPAUSE|IFM_ETH_TXPAUSE) + +#define IFM_NMIN IFM_ETHER /* lowest Network type */ +#define IFM_NMAX IFM_NMASK /* highest Network type */ + +/* + * Status bits + */ +#define IFM_AVALID 0x0000000000000001ULL /* Active bit valid */ +#define IFM_ACTIVE 0x0000000000000002ULL /* Interface attached to working net */ + +/* Mask of "status valid" bits, for ifconfig(8). */ +#define IFM_STATUS_VALID IFM_AVALID + +/* List of "status valid" bits, for ifconfig(8). */ +#define IFM_STATUS_VALID_LIST { \ + IFM_AVALID, \ + 0 \ +} + +/* + * Macros to extract various bits of information from the media word. + */ +#define IFM_TYPE(x) ((x) & IFM_NMASK) +#define IFM_SUBTYPE(x) ((x) & IFM_TMASK) +#define IFM_INST(x) (((x) & IFM_IMASK) >> IFM_ISHIFT) +#define IFM_OPTIONS(x) ((x) & (IFM_OMASK|IFM_GMASK)) +#define IFM_MODE(x) ((x) & IFM_MMASK) + +#define IFM_INST_MAX IFM_INST(IFM_IMASK) +#define IFM_INST_ANY ((uint64_t) -1) + +/* + * Macro to create a media word. + * All arguments are IFM_* macros, except 'instance' which is a 64-bit integer. + * XXX 'operating mode' is not included here?!? + */ +#define IFM_MAKEWORD(type, subtype, options, instance) \ + ((type) | (subtype) | (options) | \ + ((uint64_t)(instance) << IFM_ISHIFT)) + +/* + * NetBSD extension not defined in the BSDI API. This is used in various + * places to get the canonical description for a given type/subtype. + * + * In the subtype and mediaopt descriptions, the valid TYPE bits are OR'd + * in to indicate which TYPE the subtype/option corresponds to. If no + * TYPE is present, it is a shared media/mediaopt. + * + * Note that these are parsed case-insensitive. + * + * Order is important. The first matching entry is the canonical name + * for a media type; subsequent matches are aliases. + */ +struct ifmedia_description { + uint64_t ifmt_word; /* word value; may be masked */ + const char *ifmt_string; /* description */ +}; + +#define IFM_TYPE_DESCRIPTIONS { \ + { IFM_ETHER, "Ethernet" }, \ + { IFM_ETHER, "ether" }, \ + { IFM_FDDI, "FDDI" }, \ + { IFM_IEEE80211, "IEEE802.11" }, \ + { IFM_TDM, "TDM" }, \ + { IFM_CARP, "CARP" }, \ + { 0, NULL }, \ +} + +#define IFM_TYPE_MATCH(dt, t) \ + (IFM_TYPE((dt)) == 0 || IFM_TYPE((dt)) == IFM_TYPE((t))) + +#define IFM_SUBTYPE_DESCRIPTIONS { \ + { IFM_AUTO, "autoselect" }, \ + { IFM_AUTO, "auto" }, \ + { IFM_MANUAL, "manual" }, \ + { IFM_NONE, "none" }, \ + \ + { IFM_ETHER|IFM_10_T, "10baseT" }, \ + { IFM_ETHER|IFM_10_T, "10baseT/UTP" }, \ + { IFM_ETHER|IFM_10_T, "UTP" }, \ + { IFM_ETHER|IFM_10_T, "10UTP" }, \ + { IFM_ETHER|IFM_10_2, "10base2" }, \ + { IFM_ETHER|IFM_10_2, "10base2/BNC" }, \ + { IFM_ETHER|IFM_10_2, "BNC" }, \ + { IFM_ETHER|IFM_10_2, "10BNC" }, \ + { IFM_ETHER|IFM_10_5, "10base5" }, \ + { IFM_ETHER|IFM_10_5, "10base5/AUI" }, \ + { IFM_ETHER|IFM_10_5, "AUI" }, \ + { IFM_ETHER|IFM_10_5, "10AUI" }, \ + { IFM_ETHER|IFM_100_TX, "100baseTX" }, \ + { IFM_ETHER|IFM_100_TX, "100TX" }, \ + { IFM_ETHER|IFM_100_FX, "100baseFX" }, \ + { IFM_ETHER|IFM_100_FX, "100FX" }, \ + { IFM_ETHER|IFM_100_T4, "100baseT4" }, \ + { IFM_ETHER|IFM_100_T4, "100T4" }, \ + { IFM_ETHER|IFM_100_VG, "100baseVG" }, \ + { IFM_ETHER|IFM_100_VG, "100VG" }, \ + { IFM_ETHER|IFM_100_T2, "100baseT2" }, \ + { IFM_ETHER|IFM_100_T2, "100T2" }, \ + { IFM_ETHER|IFM_1000_SX, "1000baseSX" }, \ + { IFM_ETHER|IFM_1000_SX, "1000SX" }, \ + { IFM_ETHER|IFM_10_STP, "10baseSTP" }, \ + { IFM_ETHER|IFM_10_STP, "STP" }, \ + { IFM_ETHER|IFM_10_STP, "10STP" }, \ + { IFM_ETHER|IFM_10_FL, "10baseFL" }, \ + { IFM_ETHER|IFM_10_FL, "FL" }, \ + { IFM_ETHER|IFM_10_FL, "10FL" }, \ + { IFM_ETHER|IFM_1000_LX, "1000baseLX" }, \ + { IFM_ETHER|IFM_1000_LX, "1000LX" }, \ + { IFM_ETHER|IFM_1000_CX, "1000baseCX" }, \ + { IFM_ETHER|IFM_1000_CX, "1000CX" }, \ + { IFM_ETHER|IFM_1000_T, "1000baseT" }, \ + { IFM_ETHER|IFM_1000_T, "1000T" }, \ + { IFM_ETHER|IFM_1000_T, "1000baseTX" }, \ + { IFM_ETHER|IFM_1000_T, "1000TX" }, \ + { IFM_ETHER|IFM_HPNA_1, "HomePNA1" }, \ + { IFM_ETHER|IFM_HPNA_1, "HPNA1" }, \ + { IFM_ETHER|IFM_10G_LR, "10GbaseLR" }, \ + { IFM_ETHER|IFM_10G_LR, "10GLR" }, \ + { IFM_ETHER|IFM_10G_LR, "10GBASE-LR" }, \ + { IFM_ETHER|IFM_10G_SR, "10GbaseSR" }, \ + { IFM_ETHER|IFM_10G_SR, "10GSR" }, \ + { IFM_ETHER|IFM_10G_SR, "10GBASE-SR" }, \ + { IFM_ETHER|IFM_10G_CX4, "10GbaseCX4" }, \ + { IFM_ETHER|IFM_10G_CX4, "10GCX4" }, \ + { IFM_ETHER|IFM_10G_CX4, "10GBASE-CX4" }, \ + { IFM_ETHER|IFM_2500_SX, "2500baseSX" }, \ + { IFM_ETHER|IFM_2500_SX, "2500SX" }, \ + { IFM_ETHER|IFM_10G_T, "10GbaseT" }, \ + { IFM_ETHER|IFM_10G_T, "10GT" }, \ + { IFM_ETHER|IFM_10G_T, "10GBASE-T" }, \ + { IFM_ETHER|IFM_10G_SFP_CU, "10GSFP+Cu" }, \ + { IFM_ETHER|IFM_10G_SFP_CU, "10GCu" }, \ + { IFM_ETHER|IFM_10G_LRM, "10GbaseLRM" }, \ + { IFM_ETHER|IFM_10G_LRM, "10GBASE-LRM" }, \ + { IFM_ETHER|IFM_40G_CR4, "40GbaseCR4" }, \ + { IFM_ETHER|IFM_40G_CR4, "40GBASE-CR4" }, \ + { IFM_ETHER|IFM_40G_SR4, "40GbaseSR4" }, \ + { IFM_ETHER|IFM_40G_SR4, "40GBASE-SR4" }, \ + { IFM_ETHER|IFM_40G_LR4, "40GbaseLR4" }, \ + { IFM_ETHER|IFM_40G_LR4, "40GBASE-LR4" }, \ + { IFM_ETHER|IFM_1000_KX, "1000base-KX" }, \ + { IFM_ETHER|IFM_1000_KX, "1000BASE-KX" }, \ + { IFM_ETHER|IFM_10G_KX4, "10GbaseKX4" }, \ + { IFM_ETHER|IFM_10G_KX4, "10GBASE-KX4" }, \ + { IFM_ETHER|IFM_10G_KR, "10GbaseKR" }, \ + { IFM_ETHER|IFM_10G_KR, "10GBASE-KR" }, \ + { IFM_ETHER|IFM_10G_CR1, "10GbaseCR1" }, \ + { IFM_ETHER|IFM_10G_CR1, "10GBASE-CR1" }, \ + { IFM_ETHER|IFM_10G_AOC, "10G-AOC" }, \ + { IFM_ETHER|IFM_20G_KR2, "20GbaseKR2" }, \ + { IFM_ETHER|IFM_20G_KR2, "20GBASE-KR2" }, \ + { IFM_ETHER|IFM_2500_KX, "2500baseKX" }, \ + { IFM_ETHER|IFM_2500_KX, "2500BASE-KX" }, \ + { IFM_ETHER|IFM_2500_T, "2500baseT" }, \ + { IFM_ETHER|IFM_2500_T, "2500BASE-T" }, \ + { IFM_ETHER|IFM_5000_T, "5000baseT" }, \ + { IFM_ETHER|IFM_5000_T, "5000BASE-T" }, \ + { IFM_ETHER|IFM_1000_SGMII, "1000base-SGMII" }, \ + { IFM_ETHER|IFM_1000_SGMII, "1000BASE-SGMII" }, \ + { IFM_ETHER|IFM_10G_SFI, "10GbaseSFI" }, \ + { IFM_ETHER|IFM_10G_SFI, "10GBASE-SFI" }, \ + { IFM_ETHER|IFM_40G_XLPPI, "40GbaseXLPPI" }, \ + { IFM_ETHER|IFM_40G_XLPPI, "40GBASE-XLPPI" }, \ + { IFM_ETHER|IFM_1000_CX_SGMII, "1000baseCX-SGMII" }, \ + { IFM_ETHER|IFM_1000_CX_SGMII, "1000BASE-CX-SGMII" }, \ + { IFM_ETHER|IFM_40G_KR4, "40GbaseKR4" }, \ + { IFM_ETHER|IFM_40G_KR4, "40GBASE-KR4" }, \ + { IFM_ETHER|IFM_40G_AOC, "40G-AOC" }, \ + { IFM_ETHER|IFM_10G_ER, "10GbaseER" }, \ + { IFM_ETHER|IFM_10G_ER, "10GBASE-ER" }, \ + { IFM_ETHER|IFM_100G_CR4, "100GbaseCR4" }, \ + { IFM_ETHER|IFM_100G_CR4, "100GBASE-CR4" }, \ + { IFM_ETHER|IFM_100G_SR4, "100GbaseSR4" }, \ + { IFM_ETHER|IFM_100G_SR4, "100GBASE-SR4" }, \ + { IFM_ETHER|IFM_100G_KR4, "100GbaseKR4" }, \ + { IFM_ETHER|IFM_100G_KR4, "100GBASE-KR4" }, \ + { IFM_ETHER|IFM_100G_LR4, "100GbaseLR4" }, \ + { IFM_ETHER|IFM_100G_LR4, "100GBASE-LR4" }, \ + { IFM_ETHER|IFM_100G_AOC, "100G-AOC" }, \ + { IFM_ETHER|IFM_56G_R4, "56GbaseR4" }, \ + { IFM_ETHER|IFM_56G_R4, "56GBASE-R4" }, \ + { IFM_ETHER|IFM_25G_CR, "25GbaseCR" }, \ + { IFM_ETHER|IFM_25G_CR, "25GBASE-CR" }, \ + { IFM_ETHER|IFM_25G_KR, "25GbaseKR" }, \ + { IFM_ETHER|IFM_25G_KR, "25GBASE-KR" }, \ + { IFM_ETHER|IFM_25G_SR, "25GbaseSR" }, \ + { IFM_ETHER|IFM_25G_SR, "25GBASE-SR" }, \ + { IFM_ETHER|IFM_25G_LR, "25GbaseLR" }, \ + { IFM_ETHER|IFM_25G_LR, "25GBASE-LR" }, \ + { IFM_ETHER|IFM_25G_ER, "25GbaseER" }, \ + { IFM_ETHER|IFM_25G_ER, "25GBASE-ER" }, \ + { IFM_ETHER|IFM_25G_AOC, "25G-AOC" }, \ + { IFM_ETHER|IFM_50G_CR2, "50GbaseCR2" }, \ + { IFM_ETHER|IFM_50G_CR2, "50GBASE-CR2" }, \ + { IFM_ETHER|IFM_50G_KR2, "50GbaseKR2" }, \ + { IFM_ETHER|IFM_50G_KR2, "50GBASE-KR2" }, \ + \ + { IFM_FDDI|IFM_FDDI_SMF, "Single-mode" }, \ + { IFM_FDDI|IFM_FDDI_SMF, "SMF" }, \ + { IFM_FDDI|IFM_FDDI_MMF, "Multi-mode" }, \ + { IFM_FDDI|IFM_FDDI_MMF, "MMF" }, \ + { IFM_FDDI|IFM_FDDI_UTP, "UTP" }, \ + { IFM_FDDI|IFM_FDDI_UTP, "CDDI" }, \ + \ + { IFM_IEEE80211|IFM_IEEE80211_FH1, "FH1" }, \ + { IFM_IEEE80211|IFM_IEEE80211_FH2, "FH2" }, \ + { IFM_IEEE80211|IFM_IEEE80211_DS2, "DS2" }, \ + { IFM_IEEE80211|IFM_IEEE80211_DS5, "DS5" }, \ + { IFM_IEEE80211|IFM_IEEE80211_DS11, "DS11" }, \ + { IFM_IEEE80211|IFM_IEEE80211_DS1, "DS1" }, \ + { IFM_IEEE80211|IFM_IEEE80211_DS22, "DS22" }, \ + { IFM_IEEE80211|IFM_IEEE80211_OFDM6, "OFDM6" }, \ + { IFM_IEEE80211|IFM_IEEE80211_OFDM9, "OFDM9" }, \ + { IFM_IEEE80211|IFM_IEEE80211_OFDM12, "OFDM12" }, \ + { IFM_IEEE80211|IFM_IEEE80211_OFDM18, "OFDM18" }, \ + { IFM_IEEE80211|IFM_IEEE80211_OFDM24, "OFDM24" }, \ + { IFM_IEEE80211|IFM_IEEE80211_OFDM36, "OFDM36" }, \ + { IFM_IEEE80211|IFM_IEEE80211_OFDM48, "OFDM48" }, \ + { IFM_IEEE80211|IFM_IEEE80211_OFDM54, "OFDM54" }, \ + { IFM_IEEE80211|IFM_IEEE80211_OFDM72, "OFDM72" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS0, "HT-MCS0" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS1, "HT-MCS1" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS2, "HT-MCS2" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS3, "HT-MCS3" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS4, "HT-MCS4" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS5, "HT-MCS5" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS6, "HT-MCS6" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS7, "HT-MCS7" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS8, "HT-MCS8" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS9, "HT-MCS9" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS10, "HT-MCS10" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS11, "HT-MCS11" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS12, "HT-MCS12" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS13, "HT-MCS13" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS14, "HT-MCS14" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS15, "HT-MCS15" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS16, "HT-MCS16" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS17, "HT-MCS17" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS18, "HT-MCS18" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS19, "HT-MCS19" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS20, "HT-MCS20" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS21, "HT-MCS21" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS22, "HT-MCS22" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS23, "HT-MCS23" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS24, "HT-MCS24" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS25, "HT-MCS25" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS26, "HT-MCS26" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS27, "HT-MCS27" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS28, "HT-MCS28" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS29, "HT-MCS29" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS30, "HT-MCS30" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS31, "HT-MCS31" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS32, "HT-MCS32" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS33, "HT-MCS33" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS34, "HT-MCS34" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS35, "HT-MCS35" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS36, "HT-MCS36" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS37, "HT-MCS37" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS38, "HT-MCS38" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS39, "HT-MCS39" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS40, "HT-MCS40" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS41, "HT-MCS41" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS42, "HT-MCS42" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS43, "HT-MCS43" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS44, "HT-MCS44" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS45, "HT-MCS45" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS46, "HT-MCS46" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS47, "HT-MCS47" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS48, "HT-MCS48" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS49, "HT-MCS49" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS50, "HT-MCS50" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS51, "HT-MCS51" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS52, "HT-MCS52" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS53, "HT-MCS53" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS54, "HT-MCS54" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS55, "HT-MCS55" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS56, "HT-MCS56" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS57, "HT-MCS57" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS58, "HT-MCS58" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS59, "HT-MCS59" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS60, "HT-MCS60" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS61, "HT-MCS61" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS62, "HT-MCS62" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS63, "HT-MCS63" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS64, "HT-MCS64" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS65, "HT-MCS65" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS66, "HT-MCS66" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS67, "HT-MCS67" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS68, "HT-MCS68" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS69, "HT-MCS69" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS70, "HT-MCS70" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS71, "HT-MCS71" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS72, "HT-MCS72" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS73, "HT-MCS73" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS74, "HT-MCS74" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS75, "HT-MCS75" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS76, "HT-MCS76" }, \ + { IFM_IEEE80211|IFM_IEEE80211_VHT_MCS0, "VHT-MCS0" }, \ + { IFM_IEEE80211|IFM_IEEE80211_VHT_MCS1, "VHT-MCS1" }, \ + { IFM_IEEE80211|IFM_IEEE80211_VHT_MCS2, "VHT-MCS2" }, \ + { IFM_IEEE80211|IFM_IEEE80211_VHT_MCS3, "VHT-MCS3" }, \ + { IFM_IEEE80211|IFM_IEEE80211_VHT_MCS4, "VHT-MCS4" }, \ + { IFM_IEEE80211|IFM_IEEE80211_VHT_MCS5, "VHT-MCS5" }, \ + { IFM_IEEE80211|IFM_IEEE80211_VHT_MCS6, "VHT-MCS6" }, \ + { IFM_IEEE80211|IFM_IEEE80211_VHT_MCS7, "VHT-MCS7" }, \ + { IFM_IEEE80211|IFM_IEEE80211_VHT_MCS8, "VHT-MCS8" }, \ + { IFM_IEEE80211|IFM_IEEE80211_VHT_MCS9, "VHT-MCS9" }, \ + \ + { IFM_TDM|IFM_TDM_T1, "t1" }, \ + { IFM_TDM|IFM_TDM_T1_AMI, "t1-ami" }, \ + { IFM_TDM|IFM_TDM_E1, "e1" }, \ + { IFM_TDM|IFM_TDM_E1_G704, "e1-g.704" }, \ + { IFM_TDM|IFM_TDM_E1_AMI, "e1-ami" }, \ + { IFM_TDM|IFM_TDM_E1_AMI_G704, "e1-ami-g.704" }, \ + { IFM_TDM|IFM_TDM_T3, "t3" }, \ + { IFM_TDM|IFM_TDM_T3_M13, "t3-m13" }, \ + { IFM_TDM|IFM_TDM_E3, "e3" }, \ + { IFM_TDM|IFM_TDM_E3_G751, "e3-g.751" }, \ + { IFM_TDM|IFM_TDM_E3_G832, "e3-g.832" }, \ + { IFM_TDM|IFM_TDM_E1_G704_CRC4, "e1-g.704-crc4" }, \ + \ + { 0, NULL }, \ +} + +#define IFM_MODE_DESCRIPTIONS { \ + { IFM_AUTO, "autoselect" }, \ + { IFM_AUTO, "auto" }, \ + { IFM_IEEE80211|IFM_IEEE80211_11A, "11a" }, \ + { IFM_IEEE80211|IFM_IEEE80211_11B, "11b" }, \ + { IFM_IEEE80211|IFM_IEEE80211_11G, "11g" }, \ + { IFM_IEEE80211|IFM_IEEE80211_FH, "fh" }, \ + { IFM_IEEE80211|IFM_IEEE80211_11N, "11n" }, \ + { IFM_IEEE80211|IFM_IEEE80211_11AC, "11ac" }, \ + { IFM_TDM|IFM_TDM_MASTER, "master" }, \ + { 0, NULL }, \ +} + +#define IFM_OPTION_DESCRIPTIONS { \ + { IFM_FDX, "full-duplex" }, \ + { IFM_FDX, "fdx" }, \ + { IFM_HDX, "half-duplex" }, \ + { IFM_HDX, "hdx" }, \ + { IFM_FLAG0, "flag0" }, \ + { IFM_FLAG1, "flag1" }, \ + { IFM_FLAG2, "flag2" }, \ + { IFM_LOOP, "loopback" }, \ + { IFM_LOOP, "hw-loopback"}, \ + { IFM_LOOP, "loop" }, \ + \ + { IFM_ETHER|IFM_ETH_MASTER, "master" }, \ + { IFM_ETHER|IFM_ETH_RXPAUSE, "rxpause" }, \ + { IFM_ETHER|IFM_ETH_TXPAUSE, "txpause" }, \ + \ + { IFM_FDDI|IFM_FDDI_DA, "dual-attach" }, \ + { IFM_FDDI|IFM_FDDI_DA, "das" }, \ + \ + { IFM_IEEE80211|IFM_IEEE80211_ADHOC, "adhoc" }, \ + { IFM_IEEE80211|IFM_IEEE80211_HOSTAP, "hostap" }, \ + { IFM_IEEE80211|IFM_IEEE80211_IBSS, "ibss" }, \ + { IFM_IEEE80211|IFM_IEEE80211_IBSSMASTER, "ibss-master" }, \ + { IFM_IEEE80211|IFM_IEEE80211_MONITOR, "monitor" }, \ + \ + { IFM_TDM|IFM_TDM_HDLC_CRC16, "hdlc-crc16" }, \ + { IFM_TDM|IFM_TDM_PPP, "ppp" }, \ + { IFM_TDM|IFM_TDM_FR_ANSI, "framerelay-ansi" }, \ + { IFM_TDM|IFM_TDM_FR_CISCO, "framerelay-cisco" }, \ + { IFM_TDM|IFM_TDM_FR_ANSI, "framerelay-itu" }, \ + \ + { 0, NULL }, \ +} + +/* + * Baudrate descriptions for the various media types. + */ +struct ifmedia_baudrate { + uint64_t ifmb_word; /* media word */ + uint64_t ifmb_baudrate; /* corresponding baudrate */ +}; + +#define IFM_BAUDRATE_DESCRIPTIONS { \ + { IFM_ETHER|IFM_10_T, IF_Mbps(10) }, \ + { IFM_ETHER|IFM_10_2, IF_Mbps(10) }, \ + { IFM_ETHER|IFM_10_5, IF_Mbps(10) }, \ + { IFM_ETHER|IFM_100_TX, IF_Mbps(100) }, \ + { IFM_ETHER|IFM_100_FX, IF_Mbps(100) }, \ + { IFM_ETHER|IFM_100_T4, IF_Mbps(100) }, \ + { IFM_ETHER|IFM_100_VG, IF_Mbps(100) }, \ + { IFM_ETHER|IFM_100_T2, IF_Mbps(100) }, \ + { IFM_ETHER|IFM_1000_SX, IF_Mbps(1000) }, \ + { IFM_ETHER|IFM_10_STP, IF_Mbps(10) }, \ + { IFM_ETHER|IFM_10_FL, IF_Mbps(10) }, \ + { IFM_ETHER|IFM_1000_LX, IF_Mbps(1000) }, \ + { IFM_ETHER|IFM_1000_CX, IF_Mbps(1000) }, \ + { IFM_ETHER|IFM_1000_T, IF_Mbps(1000) }, \ + { IFM_ETHER|IFM_HPNA_1, IF_Mbps(1) }, \ + { IFM_ETHER|IFM_10G_LR, IF_Gbps(10) }, \ + { IFM_ETHER|IFM_10G_SR, IF_Gbps(10) }, \ + { IFM_ETHER|IFM_10G_CX4, IF_Gbps(10) }, \ + { IFM_ETHER|IFM_2500_SX, IF_Mbps(2500) }, \ + { IFM_ETHER|IFM_10G_T, IF_Gbps(10) }, \ + { IFM_ETHER|IFM_10G_SFP_CU, IF_Gbps(10) }, \ + \ + { IFM_FDDI|IFM_FDDI_SMF, IF_Mbps(100) }, \ + { IFM_FDDI|IFM_FDDI_MMF, IF_Mbps(100) }, \ + { IFM_FDDI|IFM_FDDI_UTP, IF_Mbps(100) }, \ + \ + { IFM_IEEE80211|IFM_IEEE80211_FH1, IF_Mbps(1) }, \ + { IFM_IEEE80211|IFM_IEEE80211_FH2, IF_Mbps(2) }, \ + { IFM_IEEE80211|IFM_IEEE80211_DS1, IF_Mbps(1) }, \ + { IFM_IEEE80211|IFM_IEEE80211_DS2, IF_Mbps(2) }, \ + { IFM_IEEE80211|IFM_IEEE80211_DS5, IF_Mbps(5) }, \ + { IFM_IEEE80211|IFM_IEEE80211_DS11, IF_Mbps(11) }, \ + { IFM_IEEE80211|IFM_IEEE80211_DS22, IF_Mbps(22) }, \ + { IFM_IEEE80211|IFM_IEEE80211_OFDM6, IF_Mbps(6) }, \ + { IFM_IEEE80211|IFM_IEEE80211_OFDM9, IF_Mbps(9) }, \ + { IFM_IEEE80211|IFM_IEEE80211_OFDM12, IF_Mbps(12) }, \ + { IFM_IEEE80211|IFM_IEEE80211_OFDM18, IF_Mbps(18) }, \ + { IFM_IEEE80211|IFM_IEEE80211_OFDM24, IF_Mbps(24) }, \ + { IFM_IEEE80211|IFM_IEEE80211_OFDM36, IF_Mbps(36) }, \ + { IFM_IEEE80211|IFM_IEEE80211_OFDM48, IF_Mbps(48) }, \ + { IFM_IEEE80211|IFM_IEEE80211_OFDM54, IF_Mbps(54) }, \ + { IFM_IEEE80211|IFM_IEEE80211_OFDM72, IF_Mbps(72) }, \ + /* These HT rates correspond to 20 MHz channel with no SGI. */ \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS0, IF_Kbps(6500) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS1, IF_Mbps(13) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS2, IF_Kbps(19500) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS3, IF_Mbps(26) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS4, IF_Mbps(39) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS5, IF_Mbps(52) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS6, IF_Kbps(58500) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS7, IF_Mbps(65) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS8, IF_Mbps(13) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS9, IF_Mbps(26) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS10, IF_Mbps(39) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS11, IF_Mbps(52) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS12, IF_Mbps(78) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS13, IF_Mbps(104) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS14, IF_Mbps(117) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS15, IF_Mbps(130) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS16, IF_Kbps(19500) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS17, IF_Mbps(39) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS18, IF_Kbps(58500) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS19, IF_Mbps(78) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS20, IF_Mbps(117) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS21, IF_Mbps(156) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS22, IF_Kbps(175500) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS23, IF_Mbps(195) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS24, IF_Mbps(26) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS25, IF_Mbps(52) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS26, IF_Mbps(78) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS27, IF_Mbps(104) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS28, IF_Mbps(156) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS29, IF_Mbps(208) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS30, IF_Mbps(234) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS31, IF_Mbps(260) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS32, IF_Mbps(0) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS33, IF_Mbps(39) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS34, IF_Mbps(52) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS35, IF_Mbps(65) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS36, IF_Kbps(58500) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS37, IF_Mbps(78) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS38, IF_Kbps(97500) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS39, IF_Mbps(52) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS40, IF_Mbps(65) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS41, IF_Mbps(65) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS42, IF_Mbps(78) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS43, IF_Mbps(91) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS44, IF_Mbps(91) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS45, IF_Mbps(104) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS46, IF_Mbps(78) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS47, IF_Kbps(97500) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS48, IF_Kbps(97500) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS49, IF_Mbps(117) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS50, IF_Kbps(136500) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS51, IF_Kbps(136500) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS52, IF_Mbps(156) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS53, IF_Mbps(65) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS54, IF_Mbps(78) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS55, IF_Mbps(91) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS56, IF_Mbps(78) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS57, IF_Mbps(91) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS58, IF_Mbps(104) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS59, IF_Mbps(117) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS60, IF_Mbps(104) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS61, IF_Mbps(117) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS62, IF_Mbps(130) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS63, IF_Mbps(130) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS64, IF_Mbps(143) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS65, IF_Kbps(97500) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS66, IF_Mbps(117) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS67, IF_Kbps(136500) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS68, IF_Mbps(117) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS69, IF_Kbps(136500) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS70, IF_Mbps(156) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS71, IF_Kbps(175500) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS72, IF_Mbps(156) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS73, IF_Kbps(175500) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS74, IF_Mbps(195) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS75, IF_Mbps(195) }, \ + { IFM_IEEE80211|IFM_IEEE80211_HT_MCS76, IF_Kbps(214500) }, \ + /* These VHT rates correspond to 1 SS, no SGI, 40 MHz channel.*/\ + { IFM_IEEE80211|IFM_IEEE80211_VHT_MCS0, IF_Kbps(13500) }, \ + { IFM_IEEE80211|IFM_IEEE80211_VHT_MCS1, IF_Mbps(27) }, \ + { IFM_IEEE80211|IFM_IEEE80211_VHT_MCS2, IF_Kbps(40500) }, \ + { IFM_IEEE80211|IFM_IEEE80211_VHT_MCS3, IF_Mbps(54) }, \ + { IFM_IEEE80211|IFM_IEEE80211_VHT_MCS4, IF_Mbps(81) }, \ + { IFM_IEEE80211|IFM_IEEE80211_VHT_MCS5, IF_Mbps(108) }, \ + { IFM_IEEE80211|IFM_IEEE80211_VHT_MCS6, IF_Kbps(121500) }, \ + { IFM_IEEE80211|IFM_IEEE80211_VHT_MCS7, IF_Mbps(135) }, \ + { IFM_IEEE80211|IFM_IEEE80211_VHT_MCS8, IF_Mbps(162) }, \ + { IFM_IEEE80211|IFM_IEEE80211_VHT_MCS9, IF_Mbps(180) }, \ + \ + { IFM_TDM|IFM_TDM_T1, IF_Kbps(1536) }, \ + { IFM_TDM|IFM_TDM_T1_AMI, IF_Kbps(1536) }, \ + { IFM_TDM|IFM_TDM_E1, IF_Kbps(2048) }, \ + { IFM_TDM|IFM_TDM_E1_G704, IF_Kbps(2048) }, \ + { IFM_TDM|IFM_TDM_E1_AMI, IF_Kbps(2048) }, \ + { IFM_TDM|IFM_TDM_E1_AMI_G704, IF_Kbps(2048) }, \ + { IFM_TDM|IFM_TDM_T3, IF_Kbps(44736) }, \ + { IFM_TDM|IFM_TDM_T3_M13, IF_Kbps(44736) }, \ + { IFM_TDM|IFM_TDM_E3, IF_Kbps(34368) }, \ + { IFM_TDM|IFM_TDM_E3_G751, IF_Kbps(34368) }, \ + { IFM_TDM|IFM_TDM_E3_G832, IF_Kbps(34368) }, \ + { IFM_TDM|IFM_TDM_E1_G704_CRC4, IF_Kbps(2048) }, \ + \ + { 0, 0 }, \ +} + +/* + * Status bit descriptions for the various media types. + */ +struct ifmedia_status_description { + uint64_t ifms_type; + uint64_t ifms_valid; + uint64_t ifms_bit; + const char *ifms_string[2]; +}; + +#define IFM_STATUS_DESC(ifms, bit) \ + (ifms)->ifms_string[((ifms)->ifms_bit & (bit)) ? 1 : 0] + +#define IFM_STATUS_DESCRIPTIONS { \ + { IFM_ETHER, IFM_AVALID, IFM_ACTIVE, \ + { "no carrier", "active" } }, \ + { IFM_FDDI, IFM_AVALID, IFM_ACTIVE, \ + { "no ring", "inserted" } }, \ + { IFM_IEEE80211, IFM_AVALID, IFM_ACTIVE, \ + { "no network", "active" } }, \ + { IFM_TDM, IFM_AVALID, IFM_ACTIVE, \ + { "no carrier", "active" } }, \ + { IFM_CARP, IFM_AVALID, IFM_ACTIVE, \ + { "backup", "master" } }, \ + { 0, 0, 0, \ + { NULL, NULL } } \ +} +#endif /* _NET_IF_MEDIA_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_pflog.h b/lib/libc/include/generic-openbsd/net/if_pflog.h new file mode 100644 index 000000000000..6579d887a346 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_pflog.h @@ -0,0 +1,72 @@ +/* $OpenBSD: if_pflog.h,v 1.29 2021/01/13 09:13:30 mvs Exp $ */ +/* + * Copyright 2001 Niels Provos + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _NET_IF_PFLOG_H_ +#define _NET_IF_PFLOG_H_ + +#include +#include + +#define PFLOG_RULESET_NAME_SIZE 16 + +struct pfloghdr { + u_int8_t length; + sa_family_t af; + u_int8_t action; + u_int8_t reason; + char ifname[IFNAMSIZ]; + char ruleset[PFLOG_RULESET_NAME_SIZE]; + u_int32_t rulenr; + u_int32_t subrulenr; + uid_t uid; + pid_t pid; + uid_t rule_uid; + pid_t rule_pid; + u_int8_t dir; + u_int8_t rewritten; + sa_family_t naf; + u_int8_t pad[1]; + struct pf_addr saddr; + struct pf_addr daddr; + u_int16_t sport; + u_int16_t dport; +}; + +#define PFLOG_HDRLEN sizeof(struct pfloghdr) +/* used to be minus pad, also used as a signature */ +#define PFLOG_REAL_HDRLEN PFLOG_HDRLEN +#define PFLOG_OLD_HDRLEN offsetof(struct pfloghdr, pad) + +#ifdef _KERNEL + +struct pflog_softc { + LIST_ENTRY(pflog_softc) sc_entry; + struct ifnet sc_if; /* the interface */ + int sc_unit; +}; + +#endif /* _KERNEL */ +#endif /* _NET_IF_PFLOG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_pflow.h b/lib/libc/include/generic-openbsd/net/if_pflow.h new file mode 100644 index 000000000000..389e5bf0ebc6 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_pflow.h @@ -0,0 +1,285 @@ +/* $OpenBSD: if_pflow.h,v 1.23 2023/12/16 22:16:02 mvs Exp $ */ + +/* + * Copyright (c) 2008 Henning Brauer + * Copyright (c) 2008 Joerg Goltermann + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _NET_IF_PFLOW_H_ +#define _NET_IF_PFLOW_H_ + +#define PFLOW_ID_LEN sizeof(u_int64_t) + +#define PFLOW_MAXFLOWS 30 +#define PFLOW_ENGINE_TYPE 42 +#define PFLOW_ENGINE_ID 42 +#define PFLOW_MAXBYTES 0xffffffff +#define PFLOW_TIMEOUT 30 +#define PFLOW_TMPL_TIMEOUT 30 /* rfc 5101 10.3.6 (p.40) recommends 600 */ + +#define PFLOW_IPFIX_TMPL_SET_ID 2 + +/* RFC 5102 Information Element Identifiers */ + +#define PFIX_IE_octetDeltaCount 1 +#define PFIX_IE_packetDeltaCount 2 +#define PFIX_IE_protocolIdentifier 4 +#define PFIX_IE_ipClassOfService 5 +#define PFIX_IE_sourceTransportPort 7 +#define PFIX_IE_sourceIPv4Address 8 +#define PFIX_IE_ingressInterface 10 +#define PFIX_IE_destinationTransportPort 11 +#define PFIX_IE_destinationIPv4Address 12 +#define PFIX_IE_egressInterface 14 +#define PFIX_IE_flowEndSysUpTime 21 +#define PFIX_IE_flowStartSysUpTime 22 +#define PFIX_IE_sourceIPv6Address 27 +#define PFIX_IE_destinationIPv6Address 28 +#define PFIX_IE_flowStartMilliseconds 152 +#define PFIX_IE_flowEndMilliseconds 153 + +struct pflow_flow { + u_int32_t src_ip; + u_int32_t dest_ip; + u_int32_t nexthop_ip; + u_int16_t if_index_in; + u_int16_t if_index_out; + u_int32_t flow_packets; + u_int32_t flow_octets; + u_int32_t flow_start; + u_int32_t flow_finish; + u_int16_t src_port; + u_int16_t dest_port; + u_int8_t pad1; + u_int8_t tcp_flags; + u_int8_t protocol; + u_int8_t tos; + u_int16_t src_as; + u_int16_t dest_as; + u_int8_t src_mask; + u_int8_t dest_mask; + u_int16_t pad2; +} __packed; + +struct pflow_set_header { + u_int16_t set_id; + u_int16_t set_length; /* total length of the set, + in octets, including the set header */ +} __packed; + +#define PFLOW_SET_HDRLEN sizeof(struct pflow_set_header) + +struct pflow_tmpl_hdr { + u_int16_t tmpl_id; + u_int16_t field_count; +} __packed; + +struct pflow_tmpl_fspec { + u_int16_t field_id; + u_int16_t len; +} __packed; + +/* update pflow_clone_create() when changing pflow_ipfix_tmpl_ipv4 */ +struct pflow_ipfix_tmpl_ipv4 { + struct pflow_tmpl_hdr h; + struct pflow_tmpl_fspec src_ip; + struct pflow_tmpl_fspec dest_ip; + struct pflow_tmpl_fspec if_index_in; + struct pflow_tmpl_fspec if_index_out; + struct pflow_tmpl_fspec packets; + struct pflow_tmpl_fspec octets; + struct pflow_tmpl_fspec start; + struct pflow_tmpl_fspec finish; + struct pflow_tmpl_fspec src_port; + struct pflow_tmpl_fspec dest_port; + struct pflow_tmpl_fspec tos; + struct pflow_tmpl_fspec protocol; +#define PFLOW_IPFIX_TMPL_IPV4_FIELD_COUNT 12 +#define PFLOW_IPFIX_TMPL_IPV4_ID 256 +} __packed; + +/* update pflow_clone_create() when changing pflow_ipfix_tmpl_v6 */ +struct pflow_ipfix_tmpl_ipv6 { + struct pflow_tmpl_hdr h; + struct pflow_tmpl_fspec src_ip; + struct pflow_tmpl_fspec dest_ip; + struct pflow_tmpl_fspec if_index_in; + struct pflow_tmpl_fspec if_index_out; + struct pflow_tmpl_fspec packets; + struct pflow_tmpl_fspec octets; + struct pflow_tmpl_fspec start; + struct pflow_tmpl_fspec finish; + struct pflow_tmpl_fspec src_port; + struct pflow_tmpl_fspec dest_port; + struct pflow_tmpl_fspec tos; + struct pflow_tmpl_fspec protocol; +#define PFLOW_IPFIX_TMPL_IPV6_FIELD_COUNT 12 +#define PFLOW_IPFIX_TMPL_IPV6_ID 257 +} __packed; + +struct pflow_ipfix_tmpl { + struct pflow_set_header set_header; + struct pflow_ipfix_tmpl_ipv4 ipv4_tmpl; + struct pflow_ipfix_tmpl_ipv6 ipv6_tmpl; +} __packed; + +struct pflow_ipfix_flow4 { + u_int32_t src_ip; /* sourceIPv4Address*/ + u_int32_t dest_ip; /* destinationIPv4Address */ + u_int32_t if_index_in; /* ingressInterface */ + u_int32_t if_index_out; /* egressInterface */ + u_int64_t flow_packets; /* packetDeltaCount */ + u_int64_t flow_octets; /* octetDeltaCount */ + int64_t flow_start; /* flowStartMilliseconds */ + int64_t flow_finish; /* flowEndMilliseconds */ + u_int16_t src_port; /* sourceTransportPort */ + u_int16_t dest_port; /* destinationTransportPort */ + u_int8_t tos; /* ipClassOfService */ + u_int8_t protocol; /* protocolIdentifier */ + /* XXX padding needed? */ +} __packed; + +struct pflow_ipfix_flow6 { + struct in6_addr src_ip; /* sourceIPv6Address */ + struct in6_addr dest_ip; /* destinationIPv6Address */ + u_int32_t if_index_in; /* ingressInterface */ + u_int32_t if_index_out; /* egressInterface */ + u_int64_t flow_packets; /* packetDeltaCount */ + u_int64_t flow_octets; /* octetDeltaCount */ + int64_t flow_start; /* flowStartMilliseconds */ + int64_t flow_finish; /* flowEndMilliseconds */ + u_int16_t src_port; /* sourceTransportPort */ + u_int16_t dest_port; /* destinationTransportPort */ + u_int8_t tos; /* ipClassOfService */ + u_int8_t protocol; /* protocolIdentifier */ + /* XXX padding needed? */ +} __packed; + +#ifdef _KERNEL + +#include + +/* + * Locks used to protect struct members and global data + * I immutable after creation + * m this pflow_softc' `sc_mtx' + * p this pflow_softc' `sc_lock' + */ + +struct pflow_softc { + struct mutex sc_mtx; + struct rwlock sc_lock; + + int sc_dying; /* [p] */ + struct ifnet sc_if; + + unsigned int sc_count; /* [m] */ + unsigned int sc_count4; /* [m] */ + unsigned int sc_count6; /* [m] */ + unsigned int sc_maxcount; /* [m] */ + unsigned int sc_maxcount4; /* [m] */ + unsigned int sc_maxcount6; /* [m] */ + u_int32_t sc_gcounter; /* [m] */ + u_int32_t sc_sequence; /* [m] */ + struct timeout sc_tmo; + struct timeout sc_tmo6; + struct timeout sc_tmo_tmpl; + struct mbuf_queue sc_outputqueue; + struct task sc_outputtask; + struct socket *so; /* [p] */ + struct mbuf *send_nam; /* [p] */ + struct sockaddr *sc_flowsrc; /* [p] */ + struct sockaddr *sc_flowdst; /* [p] */ + struct pflow_ipfix_tmpl sc_tmpl_ipfix; /* [I] */ + u_int8_t sc_version; /* [m] */ + struct mbuf *sc_mbuf; /* [m] current cumulative + mbuf */ + struct mbuf *sc_mbuf6; /* [m] current cumulative + mbuf */ + SMR_SLIST_ENTRY(pflow_softc) sc_next; +}; + +extern struct pflow_softc *pflowif; + +#endif /* _KERNEL */ + +struct pflow_header { + u_int16_t version; + u_int16_t count; + u_int32_t uptime_ms; + u_int32_t time_sec; + u_int32_t time_nanosec; + u_int32_t flow_sequence; + u_int8_t engine_type; + u_int8_t engine_id; + u_int8_t reserved1; + u_int8_t reserved2; +} __packed; + +#define PFLOW_HDRLEN sizeof(struct pflow_header) + +struct pflow_v10_header { + u_int16_t version; + u_int16_t length; + u_int32_t time_sec; + u_int32_t flow_sequence; + u_int32_t observation_dom; +} __packed; + +#define PFLOW_IPFIX_HDRLEN sizeof(struct pflow_v10_header) + +struct pflowstats { + u_int64_t pflow_flows; + u_int64_t pflow_packets; + u_int64_t pflow_onomem; + u_int64_t pflow_oerrors; +}; + +/* Supported flow protocols */ +#define PFLOW_PROTO_5 5 /* original pflow */ +#define PFLOW_PROTO_10 10 /* ipfix */ +#define PFLOW_PROTO_MAX 11 + +#define PFLOW_PROTO_DEFAULT PFLOW_PROTO_5 + +struct pflow_protos { + const char *ppr_name; + u_int8_t ppr_proto; +}; + +#define PFLOW_PROTOS { \ + { "5", PFLOW_PROTO_5 }, \ + { "10", PFLOW_PROTO_10 }, \ +} + +/* + * Configuration structure for SIOCSETPFLOW SIOCGETPFLOW + */ +struct pflowreq { + struct sockaddr_storage flowsrc; + struct sockaddr_storage flowdst; + u_int16_t addrmask; + u_int8_t version; +#define PFLOW_MASK_SRCIP 0x01 +#define PFLOW_MASK_DSTIP 0x02 +#define PFLOW_MASK_VERSION 0x04 +}; + +#ifdef _KERNEL +int export_pflow(struct pf_state *); +int pflow_sysctl(int *, u_int, void *, size_t *, void *, size_t); +#endif /* _KERNEL */ + +#endif /* _NET_IF_PFLOW_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_pfsync.h b/lib/libc/include/generic-openbsd/net/if_pfsync.h new file mode 100644 index 000000000000..70445c414637 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_pfsync.h @@ -0,0 +1,338 @@ +/* $OpenBSD: if_pfsync.h,v 1.65 2025/07/07 00:55:15 jsg Exp $ */ + +/* + * Copyright (c) 2001 Michael Shalayeff + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES 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 MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2008 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _NET_IF_PFSYNC_H_ +#define _NET_IF_PFSYNC_H_ + +#define PFSYNC_VERSION 6 +#define PFSYNC_DFLTTL 255 + +#define PFSYNC_ACT_CLR 0 /* clear all states */ +#define PFSYNC_ACT_OINS 1 /* old insert state */ +#define PFSYNC_ACT_INS_ACK 2 /* ack of inserted state */ +#define PFSYNC_ACT_OUPD 3 /* old update state */ +#define PFSYNC_ACT_UPD_C 4 /* "compressed" update state */ +#define PFSYNC_ACT_UPD_REQ 5 /* request "uncompressed" state */ +#define PFSYNC_ACT_DEL 6 /* delete state */ +#define PFSYNC_ACT_DEL_C 7 /* "compressed" delete state */ +#define PFSYNC_ACT_INS_F 8 /* insert fragment */ +#define PFSYNC_ACT_DEL_F 9 /* delete fragments */ +#define PFSYNC_ACT_BUS 10 /* bulk update status */ +#define PFSYNC_ACT_OTDB 11 /* old TDB replay counter update */ +#define PFSYNC_ACT_EOF 12 /* end of frame - DEPRECATED */ +#define PFSYNC_ACT_INS 13 /* insert state */ +#define PFSYNC_ACT_UPD 14 /* update state */ +#define PFSYNC_ACT_TDB 15 /* TDB replay counter update */ +#define PFSYNC_ACT_MAX 16 + +#define PFSYNC_ACTIONS "CLR ST", \ + "INS ST OLD", \ + "INS ST ACK", \ + "UPD ST OLD", \ + "UPD ST COMP", \ + "UPD ST REQ", \ + "DEL ST", \ + "DEL ST COMP", \ + "INS FR", \ + "DEL FR", \ + "BULK UPD STAT", \ + "UPD TDB OLD", \ + "EOF", \ + "INS ST", \ + "UPD ST", \ + "UPD TDB" + +/* + * A pfsync frame is built from a header followed by several sections which + * are all prefixed with their own subheaders. + * + * | ... | + * | IP header | + * +============================+ + * | pfsync_header | + * +----------------------------+ + * | pfsync_subheader | + * +----------------------------+ + * | first action fields | + * | ... | + * +----------------------------+ + * | pfsync_subheader | + * +----------------------------+ + * | second action fields | + * | ... | + * +============================+ + */ + +/* + * Frame header + */ + +struct pfsync_header { + u_int8_t version; + u_int8_t _pad; + u_int16_t len; /* in bytes */ + u_int8_t pfcksum[PF_MD5_DIGEST_LENGTH]; +} __packed; + +/* + * Frame region subheader + */ + +struct pfsync_subheader { + u_int8_t action; + u_int8_t len; /* in dwords */ + u_int16_t count; +} __packed; + +/* + * CLR + */ + +struct pfsync_clr { + char ifname[IFNAMSIZ]; + u_int32_t creatorid; +} __packed; + +/* + * OINS, OUPD + */ + +/* these messages are deprecated */ + +/* + * INS, UPD, DEL + */ + +/* these use struct pfsync_state in pfvar.h */ + +/* + * INS_ACK + */ + +struct pfsync_ins_ack { + u_int64_t id; + u_int32_t creatorid; +} __packed; + +/* + * UPD_C + */ + +struct pfsync_upd_c { + u_int64_t id; + struct pfsync_state_peer src; + struct pfsync_state_peer dst; + u_int32_t creatorid; + u_int32_t expire; + u_int8_t timeout; + u_int8_t state_flags; + u_int8_t _pad[2]; +} __packed; + +/* + * UPD_REQ + */ + +struct pfsync_upd_req { + u_int64_t id; + u_int32_t creatorid; +} __packed __aligned(4); + +/* + * DEL_C + */ + +struct pfsync_del_c { + u_int64_t id; + u_int32_t creatorid; +} __packed; + +/* + * INS_F, DEL_F + */ + +/* not implemented (yet) */ + +/* + * BUS + */ + +struct pfsync_bus { + u_int32_t creatorid; + u_int32_t endtime; + u_int8_t status; +#define PFSYNC_BUS_START 1 +#define PFSYNC_BUS_END 2 + u_int8_t _pad[3]; +} __packed; + +/* + * TDB + */ +struct pfsync_tdb { + u_int32_t spi; + union sockaddr_union dst; + u_int64_t rpl; + u_int64_t cur_bytes; + u_int8_t sproto; + u_int8_t updates; + u_int16_t rdomain; +} __packed; + +/* + * EOF + */ + +/* this message is deprecated */ + + +#define PFSYNC_HDRLEN sizeof(struct pfsync_header) + + +/* + * Names for PFSYNC sysctl objects + */ +#define PFSYNCCTL_STATS 1 /* PFSYNC stats */ +#define PFSYNCCTL_MAXID 2 + +#define PFSYNCCTL_NAMES { \ + { 0, 0 }, \ + { "stats", CTLTYPE_STRUCT }, \ +} + +struct pfsyncstats { + u_int64_t pfsyncs_ipackets; /* total input packets, IPv4 */ + u_int64_t pfsyncs_ipackets6; /* total input packets, IPv6 */ + u_int64_t pfsyncs_badif; /* not the right interface */ + u_int64_t pfsyncs_badttl; /* TTL is not PFSYNC_DFLTTL */ + u_int64_t pfsyncs_hdrops; /* packets shorter than hdr */ + u_int64_t pfsyncs_badver; /* bad (incl unsupp) version */ + u_int64_t pfsyncs_badact; /* bad action */ + u_int64_t pfsyncs_badlen; /* data length does not match */ + u_int64_t pfsyncs_badauth; /* bad authentication */ + u_int64_t pfsyncs_stale; /* stale state */ + u_int64_t pfsyncs_badval; /* bad values */ + u_int64_t pfsyncs_badstate; /* insert/lookup failed */ + + u_int64_t pfsyncs_opackets; /* total output packets, IPv4 */ + u_int64_t pfsyncs_opackets6; /* total output packets, IPv6 */ + u_int64_t pfsyncs_onomem; /* no memory for an mbuf */ + u_int64_t pfsyncs_oerrors; /* ip output error */ +}; + +/* + * Configuration structure for SIOCSETPFSYNC SIOCGETPFSYNC + */ +struct pfsyncreq { + char pfsyncr_syncdev[IFNAMSIZ]; + struct in_addr pfsyncr_syncpeer; + int pfsyncr_maxupdates; + int pfsyncr_defer; +}; + +#ifdef _KERNEL + +enum pfsync_counters { + pfsyncs_ipackets, + pfsyncs_ipackets6, + pfsyncs_badif, + pfsyncs_badttl, + pfsyncs_hdrops, + pfsyncs_badver, + pfsyncs_badact, + pfsyncs_badlen, + pfsyncs_badauth, + pfsyncs_stale, + pfsyncs_badval, + pfsyncs_badstate, + pfsyncs_opackets, + pfsyncs_opackets6, + pfsyncs_onomem, + pfsyncs_oerrors, + pfsyncs_ncounters, +}; + +/* + * this shows where a pf state is with respect to the syncing. + */ +#define PFSYNC_S_IACK 0x00 +#define PFSYNC_S_UPD_C 0x01 +#define PFSYNC_S_DEL 0x02 +#define PFSYNC_S_INS 0x03 +#define PFSYNC_S_UPD 0x04 +#define PFSYNC_S_COUNT 0x05 + +#define PFSYNC_S_NONE 0xd0 +#define PFSYNC_S_SYNC 0xd1 +#define PFSYNC_S_PFSYNC 0xd2 +#define PFSYNC_S_DEAD 0xde + +int pfsync_input4(struct mbuf **, int *, int, int, + struct netstack *); +int pfsync_sysctl(int *, u_int, void *, size_t *, + void *, size_t); + +#define PFSYNC_SI_IOCTL 0x01 +#define PFSYNC_SI_CKSUM 0x02 +#define PFSYNC_SI_ACK 0x04 +#define PFSYNC_SI_PFSYNC 0x08 + +void pfsync_init_state(struct pf_state *, + const struct pf_state_key *, + const struct pf_state_key *, int); +void pfsync_insert_state(struct pf_state *); +void pfsync_update_state(struct pf_state *); +void pfsync_delete_state(struct pf_state *); +void pfsync_clear_states(u_int32_t, const char *); + +void pfsync_update_tdb(struct tdb *, int); +void pfsync_delete_tdb(struct tdb *); + +int pfsync_defer(struct pf_state *, struct mbuf *); + +int pfsync_is_up(void); +int pfsync_state_in_use(struct pf_state *); +#endif /* _KERNEL */ + +#endif /* _NET_IF_PFSYNC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_ppp.h b/lib/libc/include/generic-openbsd/net/if_ppp.h new file mode 100644 index 000000000000..75f3eb5918dd --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_ppp.h @@ -0,0 +1,154 @@ +/* $OpenBSD: if_ppp.h,v 1.10 2022/01/02 22:36:03 jsg Exp $ */ +/* $NetBSD: if_ppp.h,v 1.11 1996/03/15 02:28:05 paulus Exp $ */ + +/* + * if_ppp.h - Point-to-Point Protocol definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _NET_IF_PPP_H_ +#define _NET_IF_PPP_H_ + +/* + * Packet sizes + */ +#define PPP_MTU 1500 /* Default MTU (size of Info field) */ +#define PPP_MAXMRU 65000 /* Largest MRU we allow */ + +/* + * Bit definitions for flags. + */ +#define SC_COMP_PROT 0x00000001 /* protocol compression (output) */ +#define SC_COMP_AC 0x00000002 /* header compression (output) */ +#define SC_COMP_TCP 0x00000004 /* TCP (VJ) compression (output) */ +#define SC_NO_TCP_CCID 0x00000008 /* disable VJ connection-id comp. */ +#define SC_REJ_COMP_AC 0x00000010 /* reject adrs/ctrl comp. on input */ +#define SC_REJ_COMP_TCP 0x00000020 /* reject TCP (VJ) comp. on input */ +#define SC_CCP_OPEN 0x00000040 /* Look at CCP packets */ +#define SC_CCP_UP 0x00000080 /* May send/recv compressed packets */ +#define SC_DEBUG 0x00010000 /* enable debug messages */ +#define SC_LOG_INPKT 0x00020000 /* log contents of good pkts recvd */ +#define SC_LOG_OUTPKT 0x00040000 /* log contents of pkts sent */ +#define SC_LOG_RAWIN 0x00080000 /* log all chars received */ +#define SC_LOG_FLUSH 0x00100000 /* log all chars flushed */ +#define SC_RCV_B7_0 0x01000000 /* have rcvd char with bit 7 = 0 */ +#define SC_RCV_B7_1 0x02000000 /* have rcvd char with bit 7 = 1 */ +#define SC_RCV_EVNP 0x04000000 /* have rcvd char with even parity */ +#define SC_RCV_ODDP 0x08000000 /* have rcvd char with odd parity */ +#define SC_MASK 0x0fff00ff /* bits that user can change */ + +/* + * State bits in sc_flags, not changeable by user. + */ +#define SC_TIMEOUT 0x00000400 /* timeout is currently pending */ +#define SC_VJ_RESET 0x00000800 /* need to reset VJ decomp */ +#define SC_COMP_RUN 0x00001000 /* compressor has been inited */ +#define SC_DECOMP_RUN 0x00002000 /* decompressor has been inited */ +#define SC_DC_ERROR 0x00004000 /* non-fatal decomp error detected */ +#define SC_DC_FERROR 0x00008000 /* fatal decomp error detected */ +#define SC_TBUSY 0x10000000 /* xmitter doesn't need a packet yet */ +#define SC_PKTLOST 0x20000000 /* have lost or dropped a packet */ +#define SC_FLUSH 0x40000000 /* flush input until next PPP_FLAG */ +#define SC_ESCAPED 0x80000000 /* saw a PPP_ESCAPE */ + +/* + * Ioctl definitions. + */ + +struct npioctl { + int protocol; /* PPP protocol, e.g. PPP_IP */ + enum NPmode mode; +}; + +/* Structure describing a CCP configuration option, for PPPIOCSCOMPRESS */ +struct ppp_option_data { + u_char *ptr; + u_int length; + int transmit; +}; + +struct ifpppstatsreq { + char ifr_name[IFNAMSIZ]; + struct ppp_stats stats; +}; + +struct ifpppcstatsreq { + char ifr_name[IFNAMSIZ]; + struct ppp_comp_stats stats; +}; + +/* + * Ioctl definitions. + */ + +#define PPPIOCGFLAGS _IOR('t', 90, int) /* get configuration flags */ +#define PPPIOCSFLAGS _IOW('t', 89, int) /* set configuration flags */ +#define PPPIOCGASYNCMAP _IOR('t', 88, int) /* get async map */ +#define PPPIOCSASYNCMAP _IOW('t', 87, int) /* set async map */ +#define PPPIOCGUNIT _IOR('t', 86, int) /* get ppp unit number */ +#define PPPIOCGRASYNCMAP _IOR('t', 85, int) /* get receive async map */ +#define PPPIOCSRASYNCMAP _IOW('t', 84, int) /* set receive async map */ +#define PPPIOCGMRU _IOR('t', 83, int) /* get max receive unit */ +#define PPPIOCSMRU _IOW('t', 82, int) /* set max receive unit */ +#define PPPIOCSMAXCID _IOW('t', 81, int) /* set VJ max slot ID */ +#define PPPIOCGXASYNCMAP _IOR('t', 80, ext_accm) /* get extended ACCM */ +#define PPPIOCSXASYNCMAP _IOW('t', 79, ext_accm) /* set extended ACCM */ +#define PPPIOCXFERUNIT _IO('t', 78) /* transfer PPP unit */ +#define PPPIOCSCOMPRESS _IOW('t', 77, struct ppp_option_data) +#define PPPIOCGNPMODE _IOWR('t', 76, struct npioctl) /* get NP mode */ +#define PPPIOCSNPMODE _IOW('t', 75, struct npioctl) /* set NP mode */ +#define PPPIOCGIDLE _IOR('t', 74, struct ppp_idle) /* get idle time */ +#define PPPIOCSPASS _IOW('t', 71, struct bpf_program) /* set pass filter */ +#define PPPIOCSACTIVE _IOW('t', 70, struct bpf_program) /* set active filt */ + +/* + * These two are interface ioctls so that pppstats can do them on + * a socket without having to open the serial device. + */ +#define SIOCGPPPSTATS _IOWR('i', 123, struct ifpppstatsreq) +#define SIOCGPPPCSTATS _IOWR('i', 122, struct ifpppcstatsreq) + +#ifdef _KERNEL +void pppattach(void); +int pppoutput(struct ifnet *, struct mbuf *, struct sockaddr *, + struct rtentry *); +void pppintr(void); +#endif +#endif /* _NET_IF_PPP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_pppoe.h b/lib/libc/include/generic-openbsd/net/if_pppoe.h new file mode 100644 index 000000000000..1eca1f8bb614 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_pppoe.h @@ -0,0 +1,75 @@ +/* $OpenBSD: if_pppoe.h,v 1.11 2025/07/06 23:34:50 jsg Exp $ */ +/* $NetBSD: if_pppoe.h,v 1.5 2003/11/28 08:56:48 keihan Exp $ */ + +/* + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Martin Husemann . + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _NET_IF_PPPOE_H_ +#define _NET_IF_PPPOE_H_ + +#define PPPOE_NAMELEN 512 /* should be enough */ +struct pppoediscparms { + char ifname[IFNAMSIZ]; /* pppoe interface name */ + char eth_ifname[IFNAMSIZ]; /* external ethernet interface name */ + char ac_name[PPPOE_NAMELEN]; /* access concentrator name */ + char service_name[PPPOE_NAMELEN]; /* service name */ +}; + +#define PPPOESETPARMS _IOW('i', 110, struct pppoediscparms) +#define PPPOEGETPARMS _IOWR('i', 111, struct pppoediscparms) + +#define PPPOE_STATE_INITIAL 0 +#define PPPOE_STATE_PADI_SENT 1 +#define PPPOE_STATE_PADR_SENT 2 +#define PPPOE_STATE_SESSION 3 +#define PPPOE_STATE_CLOSING 4 +/* passive */ +#define PPPOE_STATE_PADO_SENT 1 + +struct pppoeconnectionstate { + char ifname[IFNAMSIZ]; /* pppoe interface name */ + u_int state; /* one of the PPPOE_STATE_ states above */ + u_int session_id; /* if state == PPPOE_STATE_SESSION */ + u_int padi_retry_no; /* number of retries already sent */ + u_int padr_retry_no; + + struct timeval session_time; /* time the session was established */ +}; + +#define PPPOEGETSESSION _IOWR('i', 112, struct pppoeconnectionstate) + +#ifdef _KERNEL + +extern struct mbuf_queue pppoediscinq; +extern struct mbuf_queue pppoeinq; + +struct mbuf *pppoe_vinput(struct ifnet *, struct mbuf *, struct netstack *); + +#endif /* _KERNEL */ +#endif /* _NET_IF_PPPOE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_pppvar.h b/lib/libc/include/generic-openbsd/net/if_pppvar.h new file mode 100644 index 000000000000..41c06d6d4218 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_pppvar.h @@ -0,0 +1,178 @@ +/* $OpenBSD: if_pppvar.h,v 1.21 2024/02/28 16:08:34 denis Exp $ */ +/* $NetBSD: if_pppvar.h,v 1.5 1997/01/03 07:23:29 mikel Exp $ */ +/* + * if_pppvar.h - private structures and declarations for PPP. + * + * Copyright (c) 1989-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _NET_IF_PPPVAR_H_ +#define _NET_IF_PPPVAR_H_ + +/* + * Supported network protocols. These values are used for + * indexing sc_npmode. + */ +#define NP_IP 0 /* Internet Protocol */ +#define NP_IPV6 1 /* Internet Protocol v6 */ +#define NUM_NP 2 /* Number of NPs. */ + +struct ppp_pkt; + +struct ppp_pkt_list { + struct mutex pl_mtx; + struct ppp_pkt *pl_head; + struct ppp_pkt *pl_tail; + u_int pl_count; + u_int pl_limit; +}; + +/* + * Structure describing each ppp unit. + */ +struct ppp_softc { + struct ifnet sc_if; /* network-visible interface */ + struct timeout sc_timo; /* timeout control (for ptys) */ + int sc_unit; /* XXX unit number */ + u_int sc_flags; /* control/status bits; see if_ppp.h */ + void *sc_devp; /* pointer to device-dep structure */ + void (*sc_start)(struct ppp_softc *); /* start output proc */ + void (*sc_ctlp)(struct ppp_softc *); /* rcvd control pkt */ + void (*sc_relinq)(struct ppp_softc *); /* relinquish ifunit */ + u_int16_t sc_mru; /* max receive unit */ + pid_t sc_xfer; /* used in transferring unit */ + struct ppp_pkt_list sc_rawq; /* received packets */ + struct mbuf_queue sc_inq; /* queue of input packets for daemon */ + struct ifqueue sc_fastq; /* interactive output packet q */ + struct mbuf *sc_togo; /* output packet ready to go */ + struct mbuf_list sc_npqueue; /* output packets not to be sent yet */ + struct pppstat sc_stats; /* count of bytes/pkts sent/rcvd */ + enum NPmode sc_npmode[NUM_NP]; /* what to do with each NP */ + struct compressor *sc_xcomp; /* transmit compressor */ + void *sc_xc_state; /* transmit compressor state */ + struct compressor *sc_rcomp; /* receive decompressor */ + void *sc_rc_state; /* receive decompressor state */ + time_t sc_last_sent; /* time (secs) last NP pkt sent */ + time_t sc_last_recv; /* time (secs) last NP pkt rcvd */ + struct bpf_program sc_pass_filt; /* filter for packets to pass */ + struct bpf_program sc_active_filt; /* filter for "non-idle" packets */ +#ifdef VJC + struct slcompress *sc_comp; /* vjc control buffer */ +#endif + + /* Device-dependent part for async lines. */ + ext_accm sc_asyncmap; /* async control character map */ + u_int32_t sc_rasyncmap; /* receive async control char map */ + struct mbuf *sc_outm; /* mbuf chain currently being output */ + struct ppp_pkt *sc_pkt; /* pointer to input pkt chain */ + struct ppp_pkt *sc_pktc; /* pointer to current input pkt */ + uint8_t *sc_pktp; /* ptr to next char in input pkt */ + u_int16_t sc_ilen; /* length of input packet so far */ + u_int16_t sc_fcs; /* FCS so far (input) */ + u_int16_t sc_outfcs; /* FCS so far for output packet */ + u_char sc_rawin[16]; /* chars as received */ + int sc_rawin_count; /* # in sc_rawin */ + LIST_ENTRY(ppp_softc) sc_list; /* all ppp interfaces */ +}; + +#ifdef _KERNEL + +struct ppp_pkt_hdr { + struct ppp_pkt *ph_next; /* next in pkt chain */ + struct ppp_pkt *ph_pkt; /* prev in chain or next in list */ + uint16_t ph_len; + uint16_t ph_errmark; +}; + +struct ppp_pkt { + struct ppp_pkt_hdr p_hdr; + uint8_t p_buf[MCLBYTES - sizeof(struct ppp_pkt_hdr)]; +}; + +void ppp_pkt_free(struct ppp_pkt *); + +#define PKT_NEXT(_p) ((_p)->p_hdr.ph_next) +#define PKT_PREV(_p) ((_p)->p_hdr.ph_pkt) +#define PKT_NEXTPKT(_p) ((_p)->p_hdr.ph_pkt) +#define PKT_LEN(_p) ((_p)->p_hdr.ph_len) + +extern struct ppp_softc ppp_softc[]; + +struct ppp_softc *pppalloc(pid_t pid); +void pppdealloc(struct ppp_softc *sc); +int pppioctl(struct ppp_softc *sc, u_long cmd, caddr_t data, + int flag, struct proc *p); +void ppppktin(struct ppp_softc *sc, struct ppp_pkt *pkt, int lost); +struct mbuf *ppp_dequeue(struct ppp_softc *sc); +void ppp_restart(struct ppp_softc *sc); +int pppoutput(struct ifnet *, struct mbuf *, + struct sockaddr *, struct rtentry *); +#endif /* _KERNEL */ +#endif /* _NET_IF_PPPVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_sec.h b/lib/libc/include/generic-openbsd/net/if_sec.h new file mode 100644 index 000000000000..d6892b0d0a8a --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_sec.h @@ -0,0 +1,44 @@ +/* $OpenBSD: if_sec.h,v 1.2 2025/03/04 15:11:30 bluhm Exp $ */ + +/* + * Copyright (c) 2023 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _NET_IF_SEC_H +#define _NET_IF_SEC_H + +#ifdef _KERNEL +struct sec_softc; +struct tdb; + +/* + * let the IPsec stack hand packets to sec(4) for input + */ + +struct sec_softc *sec_get(unsigned int); +void sec_input(struct sec_softc * , int, int, + struct mbuf *, struct netstack *); +void sec_put(struct sec_softc *); + +/* + * let the IPsec stack give tdbs to sec(4) for output + */ + +void sec_tdb_insert(struct tdb *); +void sec_tdb_remove(struct tdb *); + +#endif /* _KERNEL */ + +#endif /* _NET_IF_SEC_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_sppp.h b/lib/libc/include/generic-openbsd/net/if_sppp.h new file mode 100644 index 000000000000..e730e795977e --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_sppp.h @@ -0,0 +1,245 @@ +/* $OpenBSD: if_sppp.h,v 1.31 2025/01/15 06:15:44 dlg Exp $ */ +/* $NetBSD: if_sppp.h,v 1.2.2.1 1999/04/04 06:57:39 explorer Exp $ */ + +/* + * Defines for synchronous PPP link level subroutines. + * + * Copyright (C) 1994 Cronyx Ltd. + * Author: Serge Vakulenko, + * + * Heavily revamped to conform to RFC 1661. + * Copyright (C) 1997, Joerg Wunsch. + * + * 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 FREEBSD PROJECT ``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 FREEBSD PROJECT OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * From: Version 2.0, Fri Oct 6 20:39:21 MSK 1995 + * + * From: if_sppp.h,v 1.8 1997/10/11 11:25:20 joerg Exp + * + * From: Id: if_sppp.h,v 1.7 1998/12/01 20:20:19 hm Exp + */ + +#ifndef _NET_IF_SPPP_H_ +#define _NET_IF_SPPP_H_ + +#define AUTHFLAG_NOCALLOUT 1 /* don't require authentication on callouts */ +#define AUTHFLAG_NORECHALLENGE 2 /* don't re-challenge CHAP */ + +/* + * Don't change the order of this. Ordering the phases this way allows + * for a comparison of ``pp_phase >= PHASE_AUTHENTICATE'' in order to + * know whether LCP is up. + */ +enum ppp_phase { + PHASE_DEAD, PHASE_ESTABLISH, PHASE_TERMINATE, + PHASE_AUTHENTICATE, PHASE_NETWORK +}; + + +#define AUTHMAXLEN 256 /* including terminating '\0' */ +#define AUTHCHALEN 16 /* length of the challenge we send */ + +/* + * Definitions to pass struct sppp data down into the kernel using the + * SIOC[SG]IFGENERIC ioctl interface. + * + * In order to use this, create a struct spppreq, fill in the cmd + * field with SPPPIOGDEFS, and put the address of this structure into + * the ifr_data portion of a struct ifreq. Pass this struct to a + * SIOCGIFGENERIC ioctl. Then replace the cmd field by SPPPIOSDEFS, + * modify the defs field as desired, and pass the struct ifreq now + * to a SIOCSIFGENERIC ioctl. + */ + +struct sauthreq { + int cmd; + u_short proto; /* authentication protocol to use */ + u_short flags; + u_char name[AUTHMAXLEN]; /* system identification name */ + u_char secret[AUTHMAXLEN]; /* secret password */ +}; + +struct spppreq { + int cmd; + enum ppp_phase phase; /* phase we're currently in */ +}; + +#include + +#define IPCP_MAX_DNSSRV 2 +struct sdnsreq { + int cmd; + struct in_addr dns[IPCP_MAX_DNSSRV]; +}; + +#define SPPPIOGDEFS ((int)(('S' << 24) + (1 << 16) + sizeof(struct spppreq))) +#define SPPPIOSDEFS ((int)(('S' << 24) + (2 << 16) + sizeof(struct spppreq))) +#define SPPPIOGMAUTH ((int)(('S' << 24) + (3 << 16) + sizeof(struct sauthreq))) +#define SPPPIOSMAUTH ((int)(('S' << 24) + (4 << 16) + sizeof(struct sauthreq))) +#define SPPPIOGHAUTH ((int)(('S' << 24) + (5 << 16) + sizeof(struct sauthreq))) +#define SPPPIOSHAUTH ((int)(('S' << 24) + (6 << 16) + sizeof(struct sauthreq))) +#define SPPPIOGDNS ((int)(('S' << 24) + (7 << 16) + sizeof(struct sdnsreq))) + + +#ifdef _KERNEL + +#include +#include + +#ifdef INET6 +#include +#endif + +#define IDX_LCP 0 /* idx into state table */ + +struct slcp { + u_long opts; /* LCP options to send (bitfield) */ + u_long magic; /* local magic number */ + u_long mru; /* our max receive unit */ + u_long their_mru; /* their max receive unit */ + u_long protos; /* bitmask of protos that are started */ + u_char echoid; /* id of last keepalive echo request */ + /* restart max values, see RFC 1661 */ + int timeout; /* seconds */ + int max_terminate; + int max_configure; + int max_failure; +}; + +#define IDX_IPCP 1 /* idx into state table */ +#define IDX_IPV6CP 2 + +struct sipcp { + u_long opts; /* IPCP options to send (bitfield) */ + u_int flags; +#define IPCP_HISADDR_SEEN 1 /* have seen his address already */ +#define IPCP_MYADDR_DYN 2 /* my address is dynamically assigned */ +#define IPCP_MYADDR_SEEN 4 /* have seen my address already */ +#define IPCP_HISADDR_DYN 8 /* his address is dynamically assigned */ +#define IPV6CP_MYIFID_DYN 1 /* my ifid is dynamically assigned */ +#define IPV6CP_MYIFID_SEEN 2 /* have seen my suggested ifid */ + u_int32_t saved_hisaddr; /* if hisaddr (IPv4) is dynamic, save + * original one here, in network byte order */ + u_int32_t req_hisaddr; /* remote address requested (IPv4) */ + u_int32_t req_myaddr; /* local address requested (IPv4) */ + struct in_addr dns[IPCP_MAX_DNSSRV]; /* IPv4 DNS servers (RFC 1877) */ +#ifdef INET6 + struct in6_aliasreq req_ifid; /* local ifid requested (IPv6) */ +#endif + struct task set_addr_task; /* set address from process context */ + struct task clear_addr_task; /* clear address from process context */ +}; + +struct sauth { + u_short proto; /* authentication protocol to use */ + u_short flags; + u_char *name; /* system identification name */ + u_char *secret; /* secret password */ +}; + +#define IDX_PAP 3 +#define IDX_CHAP 4 + +#define IDX_COUNT (IDX_CHAP + 1) /* bump this when adding cp's! */ + +struct sppp { + /* NB: pp_if _must_ be first */ + struct ifnet pp_if; /* network interface data */ + struct mbuf_queue pp_cpq; /* PPP control protocol queue */ + struct sppp *pp_next; /* next interface in keepalive list */ + u_int pp_flags; + u_int pp_framebytes; /* number of bytes added by hardware framing */ + u_short pp_alivecnt; /* keepalive packets counter */ + u_short pp_loopcnt; /* loopback detection counter */ + u_int32_t pp_seq; /* local sequence number */ + u_int32_t pp_rseq; /* remote sequence number */ + time_t pp_last_receive; /* peer's last "sign of life" */ + time_t pp_last_activity; /* second of last payload data s/r */ + enum ppp_phase pp_phase; /* phase we're currently in */ + int state[IDX_COUNT]; /* state machine */ + u_char confid[IDX_COUNT]; /* id of last configuration request */ + int rst_counter[IDX_COUNT]; /* restart counter */ + int fail_counter[IDX_COUNT]; /* negotiation failure counter */ + struct timeout ch[IDX_COUNT]; + struct timeout pap_my_to_ch; + struct slcp lcp; /* LCP params */ + struct sipcp ipcp; /* IPCP params */ + struct sipcp ipv6cp; /* IPV6CP params */ + struct sauth myauth; /* auth params, i'm peer */ + struct sauth hisauth; /* auth params, i'm authenticator */ + u_char chap_challenge[AUTHCHALEN]; /* random challenge used by CHAP */ + + /* + * These functions are filled in by sppp_attach(), and are + * expected to be used by the lower layer (hardware) drivers + * in order to communicate the (un)availability of the + * communication link. Lower layer drivers that are always + * ready to communicate (like hardware HDLC) can shortcut + * pp_up from pp_tls, and pp_down from pp_tlf. + */ + void (*pp_up)(struct sppp *sp); + void (*pp_down)(struct sppp *sp); + /* + * These functions need to be filled in by the lower layer + * (hardware) drivers if they request notification from the + * PPP layer whether the link is actually required. They + * correspond to the tls and tlf actions. + */ + void (*pp_tls)(struct sppp *sp); + void (*pp_tlf)(struct sppp *sp); + /* + * These (optional) functions may be filled by the hardware + * driver if any notification of established connections + * (currently: IPCP up) is desired (pp_con) or any internal + * state change of the interface state machine should be + * signaled for monitoring purposes (pp_chg). + */ + void (*pp_con)(struct sppp *sp); + void (*pp_chg)(struct sppp *sp, int new_state); +}; + +#define PP_KEEPALIVE 0x01 /* use keepalive protocol */ + /* 0x02 was PP_CISCO */ + /* 0x04 was PP_TIMO */ +#define PP_CALLIN 0x08 /* we are being called */ +#define PP_NEEDAUTH 0x10 /* remote requested authentication */ +#define PP_NOFRAMING 0x20 /* do not add/expect encapsulation + around PPP frames (i.e. the serial + HDLC like encapsulation, RFC1662) */ + +#define PP_MIN_MRU IP_MSS /* minimal MRU */ +#define PP_MTU 1500 /* default MTU */ +#define PP_MAX_MRU 2048 /* maximal MRU we want to negotiate */ + +void sppp_attach (struct ifnet *ifp); +void sppp_detach (struct ifnet *ifp); +void sppp_input (struct ifnet *ifp, struct mbuf *m); +int sppp_proto_up(struct ifnet *ifp, uint16_t); + +/* Workaround */ +void spppattach (struct ifnet *ifp); +int sppp_ioctl(struct ifnet *ifp, u_long cmd, void *data); + +struct mbuf *sppp_dequeue (struct ifnet *ifp); +int sppp_isempty (struct ifnet *ifp); +void sppp_flush (struct ifnet *ifp); +#endif /* _KERNEL */ +#endif /* _NET_IF_SPPP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_trunk.h b/lib/libc/include/generic-openbsd/net/if_trunk.h new file mode 100644 index 000000000000..eb5c51916f54 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_trunk.h @@ -0,0 +1,255 @@ +/* $OpenBSD: if_trunk.h,v 1.32 2025/03/02 21:28:32 bluhm Exp $ */ + +/* + * Copyright (c) 2005, 2006, 2007 Reyk Floeter + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _NET_TRUNK_H +#define _NET_TRUNK_H + +/* + * Global definitions + */ + +#define TRUNK_MAX_PORTS 32 /* logically */ +#define TRUNK_MAX_NAMESIZE 32 /* name of a protocol */ +#define TRUNK_MAX_STACKING 4 /* maximum number of stacked trunks */ + +/* Port flags */ +#define TRUNK_PORT_SLAVE 0x00000000 /* normal enslaved port */ +#define TRUNK_PORT_MASTER 0x00000001 /* primary port */ +#define TRUNK_PORT_STACK 0x00000002 /* stacked trunk port */ +#define TRUNK_PORT_ACTIVE 0x00000004 /* port is active */ +#define TRUNK_PORT_COLLECTING 0x00000008 /* port is receiving frames */ +#define TRUNK_PORT_DISTRIBUTING 0x00000010 /* port is sending frames */ +#define TRUNK_PORT_DISABLED 0x00000020 /* port is disabled */ +#define TRUNK_PORT_GLOBAL 0x80000000 /* IOCTL: global flag */ +#define TRUNK_PORT_BITS "\20\01MASTER\02STACK\03ACTIVE" \ + "\04COLLECTING\05DISTRIBUTING\06DISABLED" + +/* Supported trunk PROTOs */ +enum trunk_proto { + TRUNK_PROTO_NONE = 0, /* no trunk protocol defined */ + TRUNK_PROTO_ROUNDROBIN = 1, /* simple round robin */ + TRUNK_PROTO_FAILOVER = 2, /* active failover */ + TRUNK_PROTO_LOADBALANCE = 3, /* loadbalance */ + TRUNK_PROTO_BROADCAST = 4, /* broadcast */ + TRUNK_PROTO_LACP = 5, /* 802.3ad LACP */ + TRUNK_PROTO_MAX = 6 +}; + +struct trunk_protos { + const char *tpr_name; + enum trunk_proto tpr_proto; +}; + +#define TRUNK_PROTO_DEFAULT TRUNK_PROTO_ROUNDROBIN +#define TRUNK_PROTOS { \ + { "roundrobin", TRUNK_PROTO_ROUNDROBIN }, \ + { "failover", TRUNK_PROTO_FAILOVER }, \ + { "lacp", TRUNK_PROTO_LACP }, \ + { "loadbalance", TRUNK_PROTO_LOADBALANCE }, \ + { "broadcast", TRUNK_PROTO_BROADCAST }, \ + { "none", TRUNK_PROTO_NONE }, \ + { "default", TRUNK_PROTO_DEFAULT } \ +} + +/* + * Trunk ioctls. + */ + +/* + * LACP current operational parameters structure. + */ +struct lacp_opreq { + u_int16_t actor_prio; + u_int8_t actor_mac[ETHER_ADDR_LEN]; + u_int16_t actor_key; + u_int16_t actor_portprio; + u_int16_t actor_portno; + u_int8_t actor_state; + u_int16_t partner_prio; + u_int8_t partner_mac[ETHER_ADDR_LEN]; + u_int16_t partner_key; + u_int16_t partner_portprio; + u_int16_t partner_portno; + u_int8_t partner_state; +}; + +/* Trunk port settings */ +struct trunk_reqport { + char rp_ifname[IFNAMSIZ]; /* name of the trunk */ + char rp_portname[IFNAMSIZ]; /* name of the port */ + u_int32_t rp_prio; /* port priority */ + u_int32_t rp_flags; /* port flags */ + union { + struct lacp_opreq rpsc_lacp; + } rp_psc; +#define rp_lacpreq rp_psc.rpsc_lacp +}; + +#define SIOCGTRUNKPORT _IOWR('i', 140, struct trunk_reqport) +#define SIOCSTRUNKPORT _IOW('i', 141, struct trunk_reqport) +#define SIOCSTRUNKDELPORT _IOW('i', 142, struct trunk_reqport) + +/* Trunk, ports and options */ +struct trunk_reqall { + char ra_ifname[IFNAMSIZ]; /* name of the trunk */ + u_int ra_proto; /* trunk protocol */ + + size_t ra_size; /* size of buffer */ + struct trunk_reqport *ra_port; /* allocated buffer */ + int ra_ports; /* total port count */ + union { + struct lacp_opreq rpsc_lacp; + } ra_psc; +#define ra_lacpreq ra_psc.rpsc_lacp +}; + +#define SIOCGTRUNK _IOWR('i', 143, struct trunk_reqall) +#define SIOCSTRUNK _IOW('i', 144, struct trunk_reqall) + +/* LACP administrative options */ +struct lacp_adminopts { + u_int8_t lacp_mode; /* active or passive */ + u_int8_t lacp_timeout; /* fast or slow */ + u_int16_t lacp_prio; /* system priority */ + u_int16_t lacp_portprio; /* port priority */ + u_int8_t lacp_ifqprio; /* ifq priority */ +}; + +/* Trunk administrative options */ +struct trunk_opts { + char to_ifname[IFNAMSIZ]; /* name of the trunk */ + u_int to_proto; /* trunk protocol */ + int to_opts; /* option bitmap */ +#define TRUNK_OPT_NONE 0x00 +#define TRUNK_OPT_LACP_MODE 0x01 /* set active bit */ +#define TRUNK_OPT_LACP_TIMEOUT 0x02 /* set timeout bit */ +#define TRUNK_OPT_LACP_SYS_PRIO 0x04 /* set sys_prio bit */ +#define TRUNK_OPT_LACP_PORT_PRIO 0x08 /* set port_prio bit */ +#define TRUNK_OPT_LACP_IFQ_PRIO 0x10 /* set ifq_prio bit */ + + union { + struct lacp_adminopts rpsc_lacp; + } to_psc; +#define to_lacpopts to_psc.rpsc_lacp +}; + +#define SIOCGTRUNKOPTS _IOWR('i', 145, struct trunk_opts) +#define SIOCSTRUNKOPTS _IOW('i', 146, struct trunk_opts) + +#ifdef _KERNEL +/* + * Internal kernel part + */ +struct trunk_softc; +struct trunk_port { + struct ifnet *tp_if; /* physical interface */ + struct trunk_softc *tp_trunk; /* parent trunk */ + u_int8_t tp_lladdr[ETHER_ADDR_LEN]; + caddr_t tp_psc; /* protocol data */ + + u_char tp_iftype; /* interface type */ + u_int32_t tp_prio; /* port priority */ + u_int32_t tp_flags; /* port flags */ + struct task tp_ltask; /* if state hook */ + struct task tp_dtask; /* if detach hook */ + + /* Redirected callbacks */ + int (*tp_ioctl)(struct ifnet *, u_long, caddr_t); + int (*tp_output)(struct ifnet *, struct mbuf *, struct sockaddr *, + struct rtentry *); + void (*tp_input)(struct ifnet *, struct mbuf *, struct netstack *); + + SLIST_ENTRY(trunk_port) tp_entries; +}; + +#define tp_ifname tp_if->if_xname /* interface name */ +#define tp_ifflags tp_if->if_flags /* interface flags */ +#define tp_link_state tp_if->if_link_state /* link state */ +#define tp_capabilities tp_if->if_capabilities /* capabilities */ + +#define TRUNK_PORTACTIVE(_tp) ( \ + LINK_STATE_IS_UP((_tp)->tp_link_state) && \ + (_tp)->tp_ifflags & IFF_UP) + +struct trunk_mc { + union { + struct ether_multi *mcu_enm; + } mc_u; + struct sockaddr_storage mc_addr; + + SLIST_ENTRY(trunk_mc) mc_entries; +}; + +#define mc_enm mc_u.mcu_enm + +struct trunk_ifreq { + union { + struct ifreq ifreq; + struct { + char ifr_name[IFNAMSIZ]; + struct sockaddr_storage ifr_ss; + } ifreq_storage; + } ifreq; +}; + +struct trunk_softc { + struct arpcom tr_ac; /* virtual interface */ + enum trunk_proto tr_proto; /* trunk protocol */ + u_int tr_count; /* number of ports */ + struct trunk_port *tr_primary; /* primary port */ + struct ifmedia tr_media; /* media config */ + caddr_t tr_psc; /* protocol data */ + + SLIST_HEAD(__tplhd, trunk_port) tr_ports; /* list of interfaces */ + SLIST_ENTRY(trunk_softc) tr_entries; + + SLIST_HEAD(__mclhd, trunk_mc) tr_mc_head; /* multicast addresses */ + + /* Trunk protocol callbacks */ + int (*tr_detach)(struct trunk_softc *); + int (*tr_start)(struct trunk_softc *, struct mbuf *); + int (*tr_input)(struct trunk_softc *, struct trunk_port *, + struct mbuf *); + int (*tr_port_create)(struct trunk_port *); + void (*tr_port_destroy)(struct trunk_port *); + void (*tr_linkstate)(struct trunk_port *); + void (*tr_init)(struct trunk_softc *); + void (*tr_stop)(struct trunk_softc *); + void (*tr_req)(struct trunk_softc *, caddr_t); + void (*tr_portreq)(struct trunk_port *, caddr_t); +}; + +#define tr_ifflags tr_ac.ac_if.if_flags /* flags */ +#define tr_ifname tr_ac.ac_if.if_xname /* name */ +#define tr_capabilities tr_ac.ac_if.if_capabilities /* capabilities */ +#define tr_ifindex tr_ac.ac_if.if_index /* int index */ +#define tr_lladdr tr_ac.ac_enaddr /* lladdr */ + +#define IFCAP_TRUNK_MASK 0xffff0000 /* private capabilities */ +#define IFCAP_TRUNK_FULLDUPLEX 0x00010000 /* full duplex with >1 ports */ + +/* Private data used by the loadbalancing protocol */ +struct trunk_lb { + SIPHASH_KEY lb_key; + struct trunk_port *lb_ports[TRUNK_MAX_PORTS]; +}; + +u_int32_t trunk_hashmbuf(struct mbuf *, SIPHASH_KEY *); +#endif /* _KERNEL */ + +#endif /* _NET_TRUNK_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_tun.h b/lib/libc/include/generic-openbsd/net/if_tun.h new file mode 100644 index 000000000000..cb0092197532 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_tun.h @@ -0,0 +1,122 @@ +/* $OpenBSD: if_tun.h,v 1.18 2024/11/17 00:25:07 dlg Exp $ */ + +/* + * Copyright (c) 1988, Julian Onions + * Nottingham University 1987. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _NET_IF_TUN_H_ +#define _NET_IF_TUN_H_ + +#include + +/* + * tun_hdr is a multiple of 4 bytes, but is built out of uint16_t + * fields. This allows it to sit on a 2 byte boundary in front of + * either IP (and MPLS) or Ethernet packets for tun(4) and tap(4) + * interfaces respectively while maintaining the alignment of their + * payloads. + * + * Userland can request the use of the tun_hdr using the TUNSCAP + * ioctl. This ioctl also allows userland to specify which "offload" + * capabilities it is able to accept in packets it will read from the + * kernel. It is acceptable to enable tun_hdr without enabling any + * interface offload capabilities. + * + * Once the tap_hdr is enabled, userland can write packets into the + * kernel with any of the supported features. tun(4)/tap(4) reads + * will unconditionally handle any features specified on the packet, + * regardless of what capabilities were specified by the TUNSCAP + * ioctl. + * + * The tun_hdr can be read from one interface and written directly + * to another without interpretation or modification. + * + * Use of tun_hdr and the associated capabilities are reset when a + * tun(4)/tap(4) device is closed. + */ + +struct tun_hdr { + uint16_t th_flags; +#define TUN_H_PRIO_MASK 0x7 +#define TUN_H_VTAG (1 << 4) /* th_vtag is set */ +#define TUN_H_TCP_MSS (1 << 5) /* Cut TCP frame up by th_mss */ + +#define TUN_H_IPV4_CSUM (1 << 8) +#define TUN_H_TCP_CSUM (1 << 9) +#define TUN_H_UDP_CSUM (1 << 10) +#define TUN_H_ICMP_CSUM (1 << 11) + + uint16_t th_pad; + + uint16_t th_vtag; + uint16_t th_mss; +}; + +#define TUN_OPEN 0x0001 +#define TUN_INITED 0x0002 +#define TUN_RCOLL 0x0004 /* unused */ +#define TUN_IASET 0x0008 +#define TUN_DSTADDR 0x0010 +#define TUN_RWAIT 0x0040 +#define TUN_ASYNC 0x0080 +#define TUN_NBIO 0x0100 +#define TUN_BRDADDR 0x0200 +#define TUN_STAYUP 0x0400 +#define TUN_LAYER2 0x0800 + +#define TUN_READY (TUN_OPEN | TUN_INITED) + +/* Maximum packet size */ +#define TUNMTU 3000 + +/* Maximum receive packet size (hard limit) */ +#define TUNMRU 16384 + +/* iface info */ +struct tuninfo { + u_int mtu; + u_short type; + u_short flags; + u_int baudrate; +}; +#define TUNSIFINFO _IOW('t', 91, struct tuninfo) +#define TUNGIFINFO _IOR('t', 92, struct tuninfo) + +/* ioctl for changing the broadcast/point-to-point status */ +#define TUNSIFMODE _IOW('t', 93, int) + +/* ioctl's for get/set debug */ +#define TUNSDEBUG _IOW('t', 94, int) +#define TUNGDEBUG _IOR('t', 95, int) + +struct tun_capabilities { + uint32_t tun_if_capabilities; /* IFCAP_* from net/if.h */ +}; + +#define TUNSCAP _IOW('t', 196, struct tun_capabilities) +#define TUNGCAP _IOR('t', 196, struct tun_capabilities) +#define TUNDCAP _IO('t', 196) + +#endif /* _NET_IF_TUN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_types.h b/lib/libc/include/generic-openbsd/net/if_types.h new file mode 100644 index 000000000000..e2603d366a1a --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_types.h @@ -0,0 +1,274 @@ +/* $OpenBSD: if_types.h,v 1.24 2022/01/02 22:36:04 jsg Exp $ */ +/* $NetBSD: if_types.h,v 1.17 2000/10/26 06:51:31 onoe Exp $ */ + +/* + * Copyright (c) 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_types.h 8.3 (Berkeley) 4/28/95 + */ + +#ifndef _NET_IF_TYPES_H_ +#define _NET_IF_TYPES_H_ + +/* + * Interface types for benefit of parsing media address headers. + * This list is derived from the SNMP list of ifTypes, originally + * documented in RFC1573, now maintained as: + * + * https://www.iana.org/assignments/ianaiftype-mib + */ + +#define IFT_OTHER 0x01 /* none of the following */ +#define IFT_1822 0x02 /* old-style arpanet imp */ +#define IFT_HDH1822 0x03 /* HDH arpanet imp */ +#define IFT_X25DDN 0x04 /* x25 to imp */ +#define IFT_X25 0x05 /* PDN X25 interface (RFC877) */ +#define IFT_ETHER 0x06 /* Ethernet CSMA/CD */ +#define IFT_ISO88023 0x07 /* CSMA/CD */ +#define IFT_ISO88024 0x08 /* Token Bus */ +#define IFT_ISO88025 0x09 /* Token Ring */ +#define IFT_ISO88026 0x0a /* MAN */ +#define IFT_STARLAN 0x0b +#define IFT_P10 0x0c /* Proteon 10MBit ring */ +#define IFT_P80 0x0d /* Proteon 80MBit ring */ +#define IFT_HY 0x0e /* Hyperchannel */ +#define IFT_FDDI 0x0f +#define IFT_LAPB 0x10 +#define IFT_SDLC 0x11 +#define IFT_T1 0x12 +#define IFT_CEPT 0x13 /* E1 - european T1 */ +#define IFT_ISDNBASIC 0x14 +#define IFT_ISDNPRIMARY 0x15 +#define IFT_PTPSERIAL 0x16 /* Proprietary PTP serial */ +#define IFT_PPP 0x17 /* RFC 1331 */ +#define IFT_LOOP 0x18 /* loopback */ +#define IFT_EON 0x19 /* ISO over IP */ +#define IFT_XETHER 0x1a /* obsolete 3MB experimental ethernet */ +#define IFT_NSIP 0x1b /* XNS over IP */ +#define IFT_SLIP 0x1c /* IP over generic TTY */ +#define IFT_ULTRA 0x1d /* Ultra Technologies */ +#define IFT_DS3 0x1e /* Generic T3 */ +#define IFT_SIP 0x1f /* SMDS */ +#define IFT_FRELAY 0x20 /* Frame Relay DTE only */ +#define IFT_RS232 0x21 +#define IFT_PARA 0x22 /* parallel-port */ +#define IFT_ARCNET 0x23 +#define IFT_ARCNETPLUS 0x24 +#define IFT_ATM 0x25 /* ATM cells */ +#define IFT_MIOX25 0x26 +#define IFT_SONET 0x27 /* SONET or SDH */ +#define IFT_X25PLE 0x28 +#define IFT_ISO88022LLC 0x29 +#define IFT_LOCALTALK 0x2a +#define IFT_SMDSDXI 0x2b +#define IFT_FRELAYDCE 0x2c /* Frame Relay DCE */ +#define IFT_V35 0x2d +#define IFT_HSSI 0x2e +#define IFT_HIPPI 0x2f +#define IFT_MODEM 0x30 /* Generic Modem */ +#define IFT_AAL5 0x31 /* AAL5 over ATM */ +#define IFT_SONETPATH 0x32 +#define IFT_SONETVT 0x33 +#define IFT_SMDSICIP 0x34 /* SMDS InterCarrier Interface */ +#define IFT_PROPVIRTUAL 0x35 /* Proprietary Virtual/internal */ +#define IFT_PROPMUX 0x36 /* Proprietary Multiplexing */ +#define IFT_IEEE80212 0x37 /* 100BaseVG */ +#define IFT_FIBRECHANNEL 0x38 /* Fibre Channel */ +#define IFT_HIPPIINTERFACE 0x39 /* HIPPI interfaces */ +#define IFT_FRAMERELAYINTERCONNECT 0x3a /* Obsolete, use either 0x20 or 0x2c */ +#define IFT_AFLANE8023 0x3b /* ATM Emulated LAN for 802.3 */ +#define IFT_AFLANE8025 0x3c /* ATM Emulated LAN for 802.5 */ +#define IFT_CCTEMUL 0x3d /* ATM Emulated circuit */ +#define IFT_FASTETHER 0x3e /* Fast Ethernet (100BaseT) */ +#define IFT_ISDN 0x3f /* ISDN and X.25 */ +#define IFT_V11 0x40 /* CCITT V.11/X.21 */ +#define IFT_V36 0x41 /* CCITT V.36 */ +#define IFT_G703AT64K 0x42 /* CCITT G703 at 64Kbps */ +#define IFT_G703AT2MB 0x43 /* Obsolete see DS1-MIB */ +#define IFT_QLLC 0x44 /* SNA QLLC */ +#define IFT_FASTETHERFX 0x45 /* Fast Ethernet (100BaseFX) */ +#define IFT_CHANNEL 0x46 /* channel */ +#define IFT_IEEE80211 0x47 /* radio spread spectrum */ +#define IFT_IBM370PARCHAN 0x48 /* IBM System 360/370 OEMI Channel */ +#define IFT_ESCON 0x49 /* IBM Enterprise Systems Connection */ +#define IFT_DLSW 0x4a /* Data Link Switching */ +#define IFT_ISDNS 0x4b /* ISDN S/T interface */ +#define IFT_ISDNU 0x4c /* ISDN U interface */ +#define IFT_LAPD 0x4d /* Link Access Protocol D */ +#define IFT_IPSWITCH 0x4e /* IP Switching Objects */ +#define IFT_RSRB 0x4f /* Remote Source Route Bridging */ +#define IFT_ATMLOGICAL 0x50 /* ATM Logical Port */ +#define IFT_DS0 0x51 /* Digital Signal Level 0 */ +#define IFT_DS0BUNDLE 0x52 /* group of ds0s on the same ds1 */ +#define IFT_BSC 0x53 /* Bisynchronous Protocol */ +#define IFT_ASYNC 0x54 /* Asynchronous Protocol */ +#define IFT_CNR 0x55 /* Combat Net Radio */ +#define IFT_ISO88025DTR 0x56 /* ISO 802.5r DTR */ +#define IFT_EPLRS 0x57 /* Ext Pos Loc Report Sys */ +#define IFT_ARAP 0x58 /* Appletalk Remote Access Protocol */ +#define IFT_PROPCNLS 0x59 /* Proprietary Connectionless Protocol*/ +#define IFT_HOSTPAD 0x5a /* CCITT-ITU X.29 PAD Protocol */ +#define IFT_TERMPAD 0x5b /* CCITT-ITU X.3 PAD Facility */ +#define IFT_FRAMERELAYMPI 0x5c /* Multiproto Interconnect over FR */ +#define IFT_X213 0x5d /* CCITT-ITU X213 */ +#define IFT_ADSL 0x5e /* Asymmetric Digital Subscriber Loop */ +#define IFT_RADSL 0x5f /* Rate-Adapt. Digital Subscriber Loop*/ +#define IFT_SDSL 0x60 /* Symmetric Digital Subscriber Loop */ +#define IFT_VDSL 0x61 /* Very H-Speed Digital Subscrib. Loop*/ +#define IFT_ISO88025CRFPINT 0x62 /* ISO 802.5 CRFP */ +#define IFT_MYRINET 0x63 /* Myricom Myrinet */ +#define IFT_VOICEEM 0x64 /* voice recEive and transMit */ +#define IFT_VOICEFXO 0x65 /* voice Foreign Exchange Office */ +#define IFT_VOICEFXS 0x66 /* voice Foreign Exchange Station */ +#define IFT_VOICEENCAP 0x67 /* voice encapsulation */ +#define IFT_VOICEOVERIP 0x68 /* voice over IP encapsulation */ +#define IFT_ATMDXI 0x69 /* ATM DXI */ +#define IFT_ATMFUNI 0x6a /* ATM FUNI */ +#define IFT_ATMIMA 0x6b /* ATM IMA */ +#define IFT_PPPMULTILINKBUNDLE 0x6c /* PPP Multilink Bundle */ +#define IFT_IPOVERCDLC 0x6d /* IBM ipOverCdlc */ +#define IFT_IPOVERCLAW 0x6e /* IBM Common Link Access to Workstn */ +#define IFT_STACKTOSTACK 0x6f /* IBM stackToStack */ +#define IFT_VIRTUALIPADDRESS 0x70 /* IBM VIPA */ +#define IFT_MPC 0x71 /* IBM multi-protocol channel support */ +#define IFT_IPOVERATM 0x72 /* IBM ipOverAtm */ +#define IFT_ISO88025FIBER 0x73 /* ISO 802.5j Fiber Token Ring */ +#define IFT_TDLC 0x74 /* IBM twinaxial data link control */ +#define IFT_GIGABITETHERNET 0x75 /* Gigabit Ethernet */ +#define IFT_HDLC 0x76 /* HDLC */ +#define IFT_LAPF 0x77 /* LAP F */ +#define IFT_V37 0x78 /* V.37 */ +#define IFT_X25MLP 0x79 /* Multi-Link Protocol */ +#define IFT_X25HUNTGROUP 0x7a /* X25 Hunt Group */ +#define IFT_TRANSPHDLC 0x7b /* Transp HDLC */ +#define IFT_INTERLEAVE 0x7c /* Interleave channel */ +#define IFT_FAST 0x7d /* Fast channel */ +#define IFT_IP 0x7e /* IP (for APPN HPR in IP networks) */ +#define IFT_DOCSCABLEMACLAYER 0x7f /* CATV Mac Layer */ +#define IFT_DOCSCABLEDOWNSTREAM 0x80 /* CATV Downstream interface */ +#define IFT_DOCSCABLEUPSTREAM 0x81 /* CATV Upstream interface */ +#define IFT_A12MPPSWITCH 0x82 /* Avalon Parallel Processor */ +#define IFT_TUNNEL 0x83 /* Encapsulation interface */ +#define IFT_COFFEE 0x84 /* coffee pot */ +#define IFT_CES 0x85 /* Circiut Emulation Service */ +#define IFT_ATMSUBINTERFACE 0x86 /* (x) ATM Sub Interface */ +#define IFT_L2VLAN 0x87 /* Layer 2 Virtual LAN using 802.1Q */ +#define IFT_L3IPVLAN 0x88 /* Layer 3 Virtual LAN - IP Protocol */ +#define IFT_L3IPXVLAN 0x89 /* Layer 3 Virtual LAN - IPX Prot. */ +#define IFT_DIGITALPOWERLINE 0x8a /* IP over Power Lines */ +#define IFT_MEDIAMAILOVERIP 0x8b /* (xxx) Multimedia Mail over IP */ +#define IFT_DTM 0x8c /* Dynamic synchronous Transfer Mode */ +#define IFT_DCN 0x8d /* Data Communications Network */ +#define IFT_IPFORWARD 0x8e /* IP Forwarding Interface */ +#define IFT_MSDSL 0x8f /* Multi-rate Symmetric DSL */ +#define IFT_IEEE1394 0x90 /* IEEE1394 High Performance SerialBus*/ +#define IFT_IFGSN 0x91 /* HIPPI-6400 */ +#define IFT_DVBRCCMACLAYER 0x92 /* DVB-RCC MAC Layer */ +#define IFT_DVBRCCDOWNSTREAM 0x93 /* DVB-RCC Downstream Channel */ +#define IFT_DVBRCCUPSTREAM 0x94 /* DVB-RCC Upstream Channel */ +#define IFT_ATMVIRTUAL 0x95 /* ATM Virtual Interface */ +#define IFT_MPLSTUNNEL 0x96 /* MPLS Tunnel Virtual Interface */ +#define IFT_SRP 0x97 /* Spatial Reuse Protocol */ +#define IFT_VOICEOVERATM 0x98 /* Voice over ATM */ +#define IFT_VOICEOVERFRAMERELAY 0x99 /* Voice Over Frame Relay */ +#define IFT_IDSL 0x9a /* Digital Subscriber Loop over ISDN */ +#define IFT_COMPOSITELINK 0x9b /* Avici Composite Link Interface */ +#define IFT_SS7SIGLINK 0x9c /* SS7 Signaling Link */ +#define IFT_PROPWIRELESSP2P 0x9d /* Prop. P2P wireless interface */ +#define IFT_FRFORWARD 0x9e /* Frame forward Interface */ +#define IFT_RFC1483 0x9f /* Multiprotocol over ATM AAL5 */ +#define IFT_USB 0xa0 /* USB Interface */ +#define IFT_IEEE8023ADLAG 0xa1 /* IEEE 802.3ad Link Aggregate*/ +#define IFT_BGPPOLICYACCOUNTING 0xa2 /* BGP Policy Accounting */ +#define IFT_FRF16MFRBUNDLE 0xa3 /* FRF.16 Multilink Frame Relay*/ +#define IFT_H323GATEKEEPER 0xa4 /* H323 Gatekeeper */ +#define IFT_H323PROXY 0xa5 /* H323 Voice and Video Proxy */ +#define IFT_MPLS 0xa6 /* MPLS */ +#define IFT_MFSIGLINK 0xa7 /* Multi-frequency signaling link */ +#define IFT_HDSL2 0xa8 /* High Bit-Rate DSL, 2nd gen. */ +#define IFT_SHDSL 0xa9 /* Multirate HDSL2 */ +#define IFT_DS1FDL 0xaa /* Facility Data Link (4Kbps) on a DS1*/ +#define IFT_POS 0xab /* Packet over SONET/SDH Interface */ +#define IFT_DVBASILN 0xac /* DVB-ASI Input */ +#define IFT_DVBASIOUT 0xad /* DVB-ASI Output */ +#define IFT_PLC 0xae /* Power Line Communications */ +#define IFT_NFAS 0xaf /* Non-Facility Associated Signaling */ +#define IFT_TR008 0xb0 /* TROO8 */ +#define IFT_GR303RDT 0xb1 /* Remote Digital Terminal */ +#define IFT_GR303IDT 0xb2 /* Integrated Digital Terminal */ +#define IFT_ISUP 0xb3 /* ISUP */ +#define IFT_PROPDOCSWIRELESSMACLAYER 0xb4 /* prop/Wireless MAC Layer */ +#define IFT_PROPDOCSWIRELESSDOWNSTREAM 0xb5 /* prop/Wireless Downstream */ +#define IFT_PROPDOCSWIRELESSUPSTREAM 0xb6 /* prop/Wireless Upstream */ +#define IFT_HIPERLAN2 0xb7 /* HIPERLAN Type 2 Radio Interface */ +#define IFT_PROPBWAP2MP 0xb8 /* PropBroadbandWirelessAccess P2MP*/ +#define IFT_SONETOVERHEADCHANNEL 0xb9 /* SONET Overhead Channel */ +#define IFT_DIGITALWRAPPEROVERHEADCHANNEL 0xba /* Digital Wrapper Overhead */ +#define IFT_AAL2 0xbb /* ATM adaptation layer 2 */ +#define IFT_RADIOMAC 0xbc /* MAC layer over radio links */ +#define IFT_ATMRADIO 0xbd /* ATM over radio links */ +#define IFT_IMT 0xbe /* Inter-Machine Trunks */ +#define IFT_MVL 0xbf /* Multiple Virtual Lines DSL */ +#define IFT_REACHDSL 0xc0 /* Long Reach DSL */ +#define IFT_FRDLCIENDPT 0xc1 /* Frame Relay DLCI End Point */ +#define IFT_ATMVCIENDPT 0xc2 /* ATM VCI End Point */ +#define IFT_OPTICALCHANNEL 0xc3 /* Optical Channel */ +#define IFT_OPTICALTRANSPORT 0xc4 /* Optical Transport */ +#define IFT_PROPATM 0xc5 /* Proprietary ATM */ +#define IFT_VOICEOVERCABLE 0xc6 /* Voice Over Cable Interface */ +#define IFT_INFINIBAND 0xc7 /* Infiniband */ +#define IFT_TELINK 0xc8 /* TE Link */ +#define IFT_Q2931 0xc9 /* Q.2931 */ +#define IFT_VIRTUALTG 0xca /* Virtual Trunk Group */ +#define IFT_SIPTG 0xcb /* SIP Trunk Group */ +#define IFT_SIPSIG 0xcc /* SIP Signaling */ +#define IFT_DOCSCABLEUPSTREAMCHANNEL 0xcd /* CATV Upstream Channel */ +#define IFT_ECONET 0xce /* Acorn Econet */ +#define IFT_PON155 0xcf /* FSAN 155Mb Symmetrical PON interface */ +#define IFT_PON622 0xd0 /* FSAN 622Mb Symmetrical PON interface */ +#define IFT_BRIDGE 0xd1 /* Transparent bridge interface */ +#define IFT_LINEGROUP 0xd2 /* Interface common to multiple lines */ +#define IFT_VOICEEMFGD 0xd3 /* voice E&M Feature Group D */ +#define IFT_VOICEFGDEANA 0xd4 /* voice FGD Exchange Access North American */ +#define IFT_VOICEDID 0xd5 /* voice Direct Inward Dialing */ + +/* private usage... how should we define these? */ +#define IFT_GIF 0xf0 +#define IFT_DUMMY 0xf1 +#define IFT_PVC 0xf2 +#define IFT_FAITH 0xf3 +#define IFT_ENC 0xf4 /* Encapsulation */ +#define IFT_PFLOG 0xf5 /* Packet filter logging */ +#define IFT_PFSYNC 0xf6 /* Packet filter state syncing */ +#define IFT_CARP 0xf7 /* Common Address Redundancy Protocol */ +#define IFT_BLUETOOTH 0xf8 /* Bluetooth */ +#define IFT_PFLOW 0xf9 /* pflow */ +#define IFT_MBIM 0xfa /* Mobile Broadband Interface Model */ +#define IFT_WIREGUARD 0xfb /* WireGuard tunnel */ + +#endif /* _NET_IF_TYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_var.h b/lib/libc/include/generic-openbsd/net/if_var.h new file mode 100644 index 000000000000..f1fb1fb1cdc0 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_var.h @@ -0,0 +1,406 @@ +/* $OpenBSD: if_var.h,v 1.139 2025/07/19 16:40:40 mvs Exp $ */ +/* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */ + +/* + * Copyright (c) 2012-2013 Henning Brauer + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NET_IF_VAR_H_ +#define _NET_IF_VAR_H_ + +#ifdef _KERNEL + +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * Structures defining a network interface, providing a packet + * transport mechanism (ala level 0 of the PUP protocols). + * + * Each interface accepts output datagrams of a specified maximum + * length, and provides higher level routines with input datagrams + * received from its medium. + * + * Output occurs when the routine if_output is called, with four parameters: + * (*ifp->if_output)(ifp, m, dst, rt) + * Here m is the mbuf chain to be sent and dst is the destination address. + * The output routine encapsulates the supplied datagram if necessary, + * and then transmits it on its medium. + * + * On input, each interface unwraps the data received by it, and either + * places it on the input queue of an internetwork datagram routine + * and posts the associated software interrupt, or passes the datagram to a raw + * packet input routine. + * + * Routines exist for locating interfaces by their addresses + * or for locating an interface on a certain network, as well as more general + * routing and gateway routines maintaining information used to locate + * interfaces. These routines live in the files if.c and route.c + */ + +/* + * Locks used to protect struct members in this file: + * I immutable after creation + * d protection left to the driver + * c only used in ioctl or routing socket contexts (kernel lock) + * K kernel lock + * N net lock + * T if_tmplist_lock + * + * For SRP related structures that allow lock-free reads, the write lock + * is indicated below. + */ + +struct rtentry; +struct ifnet; +struct task; +struct cpumem; + +struct netstack { + struct route ns_route; + struct mbuf_list ns_tcp_ml; + struct mbuf_list ns_tcp6_ml; +}; + +/* + * Structure describing a `cloning' interface. + */ +struct if_clone { + LIST_ENTRY(if_clone) ifc_list; /* [I] on list of cloners */ + const char *ifc_name; /* name of device, e.g. `gif' */ + size_t ifc_namelen; /* length of name */ + + int (*ifc_create)(struct if_clone *, int); + int (*ifc_destroy)(struct ifnet *); +}; + +#define IF_CLONE_INITIALIZER(name, create, destroy) \ +{ \ + .ifc_list = { NULL, NULL }, \ + .ifc_name = name, \ + .ifc_namelen = sizeof(name) - 1, \ + .ifc_create = create, \ + .ifc_destroy = destroy, \ +} + +enum if_counters { + ifc_ipackets, /* packets received on interface */ + ifc_ierrors, /* input errors on interface */ + ifc_opackets, /* packets sent on interface */ + ifc_oerrors, /* output errors on interface */ + ifc_collisions, /* collisions on csma interfaces */ + ifc_ibytes, /* total number of octets received */ + ifc_obytes, /* total number of octets sent */ + ifc_imcasts, /* packets received via multicast */ + ifc_omcasts, /* packets sent via multicast */ + ifc_iqdrops, /* dropped on input, this interface */ + ifc_oqdrops, /* dropped on output, this interface */ + ifc_noproto, /* destined for unsupported protocol */ + + ifc_ncounters +}; + +/* + * Structure defining a queue for a network interface. + * + * (Would like to call this struct ``if'', but C isn't PL/1.) + */ +TAILQ_HEAD(ifnet_head, ifnet); /* the actual queue head */ + +struct ifnet { /* and the entries */ + void *if_softc; /* [I] lower-level data for this if */ + struct refcnt if_refcnt; + TAILQ_ENTRY(ifnet) if_list; /* [NK] all struct ifnets are chained */ + TAILQ_ENTRY(ifnet) if_tmplist; /* [T] temporary list */ + TAILQ_HEAD(, ifaddr) if_addrlist; /* [N] list of addresses per if */ + TAILQ_HEAD(, ifmaddr) if_maddrlist; /* [N] list of multicast records */ + TAILQ_HEAD(, ifg_list) if_groups; /* [N] list of groups per if */ + struct task_list if_addrhooks; /* [I] address change callbacks */ + struct task_list if_linkstatehooks; /* [I] link change callbacks*/ + struct task_list if_detachhooks; /* [I] detach callbacks */ + /* [I] check or clean routes (+ or -)'d */ + void (*if_rtrequest)(struct ifnet *, int, struct rtentry *); + char if_xname[IFNAMSIZ]; /* [I] external name (name + unit) */ + int if_pcount; /* [N] # of promiscuous listeners */ + unsigned int if_bridgeidx; /* [K] used by bridge ports */ + caddr_t if_bpf; /* packet filter structure */ + caddr_t if_mcast; /* used by multicast code */ + caddr_t if_mcast6; /* used by IPv6 multicast code */ + caddr_t if_pf_kif; /* pf interface abstraction */ + union { + struct srpl carp_s; /* carp if list (used by !carp ifs) */ + unsigned int carp_idx; /* index of carpdev (used by carp + ifs) */ + } if_carp_ptr; +#define if_carp if_carp_ptr.carp_s +#define if_carpdevidx if_carp_ptr.carp_idx + unsigned int if_index; /* [I] unique index for this if */ + short if_timer; /* time 'til if_watchdog called */ + unsigned short if_flags; /* [N] up/down, broadcast, etc. */ + int if_xflags; /* [N] extra softnet flags */ + + /* Stats and other data about if. Should be in sync with if_data. */ + u_char if_type; + u_char if_addrlen; + u_char if_hdrlen; + u_char if_link_state; + uint32_t if_mtu; + uint32_t if_metric; + uint64_t if_baudrate; + uint32_t if_capabilities; + uint32_t if_rdomain; + struct timeval if_lastchange; /* [c] last op. state change */ + uint64_t if_data_counters[ifc_ncounters]; + + struct cpumem *if_counters; /* per cpu stats */ + uint32_t if_hardmtu; /* [d] maximum MTU device supports */ + char if_description[IFDESCRSIZE]; /* [c] interface description */ + u_short if_rtlabelid; /* [c] next route label */ + uint8_t if_priority; /* [c] route priority offset */ + uint8_t if_llprio; /* [N] link layer priority */ + struct timeout if_slowtimo; /* [I] watchdog timeout */ + struct task if_watchdogtask; /* [I] watchdog task */ + struct task if_linkstatetask; /* [I] task to do route updates */ + + /* procedure handles */ + void (*if_input)(struct ifnet *, struct mbuf *, struct netstack *); + int (*if_bpf_mtap)(caddr_t, const struct mbuf *, u_int); + int (*if_output)(struct ifnet *, struct mbuf *, struct sockaddr *, + struct rtentry *); /* output routine (enqueue) */ + /* link level output function */ + int (*if_ll_output)(struct ifnet *, struct mbuf *, + struct sockaddr *, struct rtentry *); + int (*if_enqueue)(struct ifnet *, struct mbuf *); + void (*if_start)(struct ifnet *); /* initiate output */ + int (*if_ioctl)(struct ifnet *, u_long, caddr_t); /* ioctl hook */ + void (*if_watchdog)(struct ifnet *); /* timer routine */ + int (*if_wol)(struct ifnet *, int); /* WoL routine **/ + + /* queues */ + struct ifqueue if_snd; /* transmit queue */ + struct ifqueue **if_ifqs; /* [I] pointer to an array of sndqs */ + void (*if_qstart)(struct ifqueue *); + unsigned int if_nifqs; /* [I] number of output queues */ + unsigned int if_txmit; /* [c] txmitigation amount */ + + struct ifiqueue if_rcv; /* rx/input queue */ + struct ifiqueue **if_iqs; /* [I] pointer to the array of iqs */ + unsigned int if_niqs; /* [I] number of input queues */ + + struct sockaddr_dl *if_sadl; /* [N] pointer to our sockaddr_dl */ + + struct nd_ifinfo *if_nd; /* [I] IPv6 Neighbor Discovery info */ +}; + +#define if_ipackets if_data_counters[ifc_ipackets] +#define if_ierrors if_data_counters[ifc_ierrors] +#define if_opackets if_data_counters[ifc_opackets] +#define if_oerrors if_data_counters[ifc_oerrors] +#define if_collisions if_data_counters[ifc_collisions] +#define if_ibytes if_data_counters[ifc_ibytes] +#define if_obytes if_data_counters[ifc_obytes] +#define if_imcasts if_data_counters[ifc_imcasts] +#define if_omcasts if_data_counters[ifc_omcasts] +#define if_iqdrops if_data_counters[ifc_iqdrops] +#define if_oqdrops if_data_counters[ifc_oqdrops] +#define if_noproto if_data_counters[ifc_noproto] + +/* + * The ifaddr structure contains information about one address + * of an interface. They are maintained by the different address families, + * are allocated and attached when an address is set, and are linked + * together so all addresses for an interface can be located. + */ +struct ifaddr { + struct sockaddr *ifa_addr; /* address of interface */ + struct sockaddr *ifa_dstaddr; /* other end of p-to-p link */ +#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */ + struct sockaddr *ifa_netmask; /* used to determine subnet */ + struct ifnet *ifa_ifp; /* back-pointer to interface */ + TAILQ_ENTRY(ifaddr) ifa_list; /* [N] list of addresses for + interface */ + u_int ifa_flags; /* interface flags, see below */ + struct refcnt ifa_refcnt; /* number of `rt_ifa` references */ + int ifa_metric; /* cost of going out this interface */ +}; + +#define IFA_ROUTE 0x01 /* Auto-magically installed route */ + +/* + * Interface multicast address. + */ +struct ifmaddr { + struct sockaddr *ifma_addr; /* Protocol address */ + unsigned int ifma_ifidx; /* Index of the interface */ + struct refcnt ifma_refcnt; /* Count of references */ + TAILQ_ENTRY(ifmaddr) ifma_list; /* Per-interface list */ +}; + +/* + * interface groups + */ + +struct ifg_group { + char ifg_group[IFNAMSIZ]; /* [I] group name */ + u_int ifg_refcnt; /* [N] group reference count */ + caddr_t ifg_pf_kif; /* [I] pf interface group */ + int ifg_carp_demoted; /* [K] carp demotion counter */ + TAILQ_HEAD(, ifg_member) ifg_members; /* [N] list of members per group */ + TAILQ_ENTRY(ifg_group) ifg_next; /* [N] all groups are chained */ + + struct refcnt ifg_tmprefcnt; + TAILQ_ENTRY(ifg_group) ifg_tmplist; /* [T] temporary list */ +}; + +struct ifg_member { + TAILQ_ENTRY(ifg_member) ifgm_next; /* [N] all members are chained */ + struct ifnet *ifgm_ifp; /* [I] member interface */ +}; + +struct ifg_list { + struct ifg_group *ifgl_group; /* [I] interface group */ + TAILQ_ENTRY(ifg_list) ifgl_next; /* [N] all groups are chained */ +}; + +#define IFNET_SLOWTIMO 1 /* granularity is 1 second */ + +#define IF_TXMIT_MIN 1 +#define IF_TXMIT_DEFAULT 16 + +/* default interface priorities */ +#define IF_WIRED_DEFAULT_PRIORITY 0 +#define IF_WIRELESS_DEFAULT_PRIORITY 4 +#define IF_WWAN_DEFAULT_PRIORITY 6 +#define IF_CARP_DEFAULT_PRIORITY 15 + +/* + * Network stack input queues. + */ +struct niqueue { + struct mbuf_queue ni_q; + u_int ni_isr; +}; + +#define NIQUEUE_INITIALIZER(_len, _isr) \ + { MBUF_QUEUE_INITIALIZER((_len), IPL_NET), (_isr) } + +int niq_enqueue(struct niqueue *, struct mbuf *); + +#define niq_dequeue(_q) mq_dequeue(&(_q)->ni_q) +#define niq_delist(_q, _ml) mq_delist(&(_q)->ni_q, (_ml)) +#define niq_len(_q) mq_len(&(_q)->ni_q) +#define niq_drops(_q) mq_drops(&(_q)->ni_q) +#define sysctl_niq(_n, _l, _op, _olp, _np, _nl, _niq) \ + sysctl_mq((_n), (_l), (_op), (_olp), (_np), (_nl), &(_niq)->ni_q) + +extern struct rwlock if_tmplist_lock; +extern struct ifnet_head ifnetlist; + +void if_start(struct ifnet *); +int if_enqueue(struct ifnet *, struct mbuf *); +int if_enqueue_ifq(struct ifnet *, struct mbuf *); +void if_input(struct ifnet *, struct mbuf_list *); +void if_vinput(struct ifnet *, struct mbuf *, struct netstack *); +void if_input_process(struct ifnet *, struct mbuf_list *, unsigned int); +int if_input_local(struct ifnet *, struct mbuf *, sa_family_t, + struct netstack *); +int if_output_ml(struct ifnet *, struct mbuf_list *, + struct sockaddr *, struct rtentry *); +int if_output_mq(struct ifnet *, struct mbuf_queue *, unsigned int *, + struct sockaddr *, struct rtentry *); +int if_output_tso(struct ifnet *, struct mbuf **, struct sockaddr *, + struct rtentry *, u_int); +int if_output_local(struct ifnet *, struct mbuf *, sa_family_t); +void if_rtrequest_dummy(struct ifnet *, int, struct rtentry *); +void p2p_rtrequest(struct ifnet *, int, struct rtentry *); +void p2p_input(struct ifnet *, struct mbuf *, struct netstack *); +int p2p_bpf_mtap(caddr_t, const struct mbuf *, u_int); + +struct ifaddr *ifa_ifwithaddr(const struct sockaddr *, u_int); +struct ifaddr *ifa_ifwithdstaddr(const struct sockaddr *, u_int); +struct ifaddr *ifaof_ifpforaddr(const struct sockaddr *, struct ifnet *); +struct ifaddr *ifaref(struct ifaddr *); +void ifafree(struct ifaddr *); + +int if_isconnected(const struct ifnet *, unsigned int); + +void if_clone_attach(struct if_clone *); + +int if_clone_create(const char *, int); +int if_clone_destroy(const char *); + +struct if_clone * + if_clone_lookup(const char *, int *); + +void ifa_add(struct ifnet *, struct ifaddr *); +void ifa_del(struct ifnet *, struct ifaddr *); +void ifa_update_broadaddr(struct ifnet *, struct ifaddr *, + struct sockaddr *); + +void if_addrhook_add(struct ifnet *, struct task *); +void if_addrhook_del(struct ifnet *, struct task *); +void if_addrhooks_run(struct ifnet *); +void if_linkstatehook_add(struct ifnet *, struct task *); +void if_linkstatehook_del(struct ifnet *, struct task *); +void if_detachhook_add(struct ifnet *, struct task *); +void if_detachhook_del(struct ifnet *, struct task *); + +void if_rxr_livelocked(struct if_rxring *); +void if_rxr_init(struct if_rxring *, u_int, u_int); +u_int if_rxr_get(struct if_rxring *, u_int); + +#define if_rxr_put(_r, _c) do { (_r)->rxr_alive -= (_c); } while (0) +#define if_rxr_needrefill(_r) ((_r)->rxr_alive < (_r)->rxr_lwm) +#define if_rxr_inuse(_r) ((_r)->rxr_alive) +#define if_rxr_cwm(_r) ((_r)->rxr_cwm) + +int if_rxr_info_ioctl(struct if_rxrinfo *, u_int, struct if_rxring_info *); +int if_rxr_ioctl(struct if_rxrinfo *, const char *, u_int, + struct if_rxring *); + +void if_counters_alloc(struct ifnet *); +void if_counters_free(struct ifnet *); + +int if_txhprio_l2_check(int); +int if_txhprio_l3_check(int); +int if_rxhprio_l2_check(int); +int if_rxhprio_l3_check(int); + +#endif /* _KERNEL */ + +#endif /* _NET_IF_VAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_vlan_var.h b/lib/libc/include/generic-openbsd/net/if_vlan_var.h new file mode 100644 index 000000000000..fa7b985bebde --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_vlan_var.h @@ -0,0 +1,55 @@ +/* $OpenBSD: if_vlan_var.h,v 1.48 2025/03/02 21:28:32 bluhm Exp $ */ + +/* + * Copyright 1998 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that both the above copyright notice and this + * permission notice appear in all copies, that both the above + * copyright notice and this permission notice appear in all + * supporting documentation, and that the name of M.I.T. not be used + * in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. M.I.T. makes + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS + * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT + * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/net/if_vlan_var.h,v 1.3 1999/08/28 00:48:24 peter Exp $ + */ + +#ifndef _NET_IF_VLAN_VAR_H_ +#define _NET_IF_VLAN_VAR_H_ + +/* sysctl(3) tags, for compatibility purposes */ +#define VLANCTL_PROTO 1 +#define VLANCTL_MAX 2 + +/* + * Configuration structure for SIOCSETVLAN and SIOCGETVLAN ioctls. + */ +struct vlanreq { + char vlr_parent[IFNAMSIZ]; + u_short vlr_tag; +}; + +#ifdef _KERNEL +struct mbuf *vlan_input(struct ifnet *, struct mbuf *, unsigned int *, + struct netstack *); +struct mbuf *vlan_inject(struct mbuf *, uint16_t, uint16_t); +#endif /* _KERNEL */ + +#endif /* _NET_IF_VLAN_VAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/if_wg.h b/lib/libc/include/generic-openbsd/net/if_wg.h new file mode 100644 index 000000000000..5a0534f7701c --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/if_wg.h @@ -0,0 +1,109 @@ +/* $OpenBSD: if_wg.h,v 1.7 2025/07/10 05:28:13 dlg Exp $ */ + +/* + * Copyright (C) 2015-2020 Jason A. Donenfeld . All Rights Reserved. + * Copyright (C) 2019-2020 Matt Dunwoodie + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __IF_WG_H__ +#define __IF_WG_H__ + +#include +#include + + +/* + * This is the public interface to the WireGuard network interface. + * + * It is designed to be used by tools such as ifconfig(8) and wg(8). + */ + +#define WG_KEY_LEN 32 + +/* + * These ioctls do not need a NETLOCK as they use their own locks to serialise + * access. + */ +#define SIOCSWG _IOWR('i', 210, struct wg_data_io) +#define SIOCGWG _IOWR('i', 211, struct wg_data_io) + +#define a_ipv4 a_addr.addr_ipv4 +#define a_ipv6 a_addr.addr_ipv6 + +struct wg_aip_io { + sa_family_t a_af; + int a_cidr; + union wg_aip_addr { + uint8_t addr_bytes; + struct in_addr addr_ipv4; + struct in6_addr addr_ipv6; + } a_addr; +}; + +#define WG_PEER_HAS_PUBLIC (1 << 0) +#define WG_PEER_HAS_PSK (1 << 1) +#define WG_PEER_HAS_PKA (1 << 2) +#define WG_PEER_HAS_ENDPOINT (1 << 3) +#define WG_PEER_REPLACE_AIPS (1 << 4) +#define WG_PEER_REMOVE (1 << 5) +#define WG_PEER_UPDATE (1 << 6) +#define WG_PEER_SET_DESCRIPTION (1 << 7) + +#define p_sa p_endpoint.sa_sa +#define p_sin p_endpoint.sa_sin +#define p_sin6 p_endpoint.sa_sin6 + +struct wg_peer_io { + int p_flags; + int p_protocol_version; + uint8_t p_public[WG_KEY_LEN]; + uint8_t p_psk[WG_KEY_LEN]; + uint16_t p_pka; + union wg_peer_endpoint { + struct sockaddr sa_sa; + struct sockaddr_in sa_sin; + struct sockaddr_in6 sa_sin6; + } p_endpoint; + uint64_t p_txbytes; + uint64_t p_rxbytes; + struct timespec p_last_handshake; /* nanotime */ + char p_description[IFDESCRSIZE]; + size_t p_aips_count; + struct wg_aip_io p_aips[]; +}; + +#define WG_INTERFACE_HAS_PUBLIC (1 << 0) +#define WG_INTERFACE_HAS_PRIVATE (1 << 1) +#define WG_INTERFACE_HAS_PORT (1 << 2) +#define WG_INTERFACE_HAS_RTABLE (1 << 3) +#define WG_INTERFACE_REPLACE_PEERS (1 << 4) + +struct wg_interface_io { + uint8_t i_flags; + in_port_t i_port; + int i_rtable; + uint8_t i_public[WG_KEY_LEN]; + uint8_t i_private[WG_KEY_LEN]; + size_t i_peers_count; + struct wg_peer_io i_peers[]; +}; + +struct wg_data_io { + char wgd_name[IFNAMSIZ]; + size_t wgd_size; /* total size of the memory pointed to by wgd_interface */ + struct wg_interface_io *wgd_interface; +}; + +#endif /* __IF_WG_H__ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/ifq.h b/lib/libc/include/generic-openbsd/net/ifq.h new file mode 100644 index 000000000000..fe5ea079f966 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/ifq.h @@ -0,0 +1,507 @@ +/* $OpenBSD: ifq.h,v 1.44 2025/03/04 01:13:37 dlg Exp $ */ + +/* + * Copyright (c) 2015 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _NET_IFQ_H_ +#define _NET_IFQ_H_ + +struct ifnet; +struct kstat; + +struct ifq_ops; + +struct ifqueue { + struct ifnet *ifq_if; + struct taskq *ifq_softnet; + union { + void *_ifq_softc; + /* + * a rings sndq is found by looking up an array of pointers. + * by default we only have one sndq and the default drivers + * dont use ifq_softc, so we can borrow it for the map until + * we need to allocate a proper map. + */ + struct ifqueue *_ifq_ifqs[1]; + } _ifq_ptr; +#define ifq_softc _ifq_ptr._ifq_softc +#define ifq_ifqs _ifq_ptr._ifq_ifqs + + /* mbuf handling */ + struct mutex ifq_mtx; + const struct ifq_ops *ifq_ops; + void *ifq_q; + struct mbuf_list ifq_free; + unsigned int ifq_len; + unsigned int ifq_oactive; + + /* statistics */ + uint64_t ifq_packets; + uint64_t ifq_bytes; + uint64_t ifq_qdrops; + uint64_t ifq_errors; + uint64_t ifq_mcasts; + uint32_t ifq_oactives; + + struct kstat *ifq_kstat; + + /* work serialisation */ + struct mutex ifq_task_mtx; + struct task_list ifq_task_list; + void *ifq_serializer; + struct task ifq_bundle; + + /* work to be serialised */ + struct task ifq_start; + struct task ifq_restart; + + /* properties */ + unsigned int ifq_maxlen; + unsigned int ifq_idx; +}; + +struct ifiqueue { + struct ifnet *ifiq_if; + caddr_t *ifiq_bpfp; + struct taskq *ifiq_softnet; + union { + void *_ifiq_softc; + struct ifiqueue *_ifiq_ifiqs[1]; + } _ifiq_ptr; +#define ifiq_softc _ifiq_ptr._ifiq_softc +#define ifiq_ifiqs _ifiq_ptr._ifiq_ifiqs + + struct mutex ifiq_mtx; + struct mbuf_list ifiq_ml; + struct task ifiq_task; + unsigned int ifiq_pressure; + + /* counters */ + uint64_t ifiq_packets; + uint64_t ifiq_bytes; + uint64_t ifiq_fdrops; + uint64_t ifiq_qdrops; + uint64_t ifiq_errors; + uint64_t ifiq_mcasts; + uint64_t ifiq_noproto; + + /* number of times a list of packets were put on ifiq_ml */ + uint64_t ifiq_enqueues; + /* number of times a list of packets were pulled off ifiq_ml */ + uint64_t ifiq_dequeues; + + struct kstat *ifiq_kstat; + + /* properties */ + unsigned int ifiq_idx; +}; + +#ifdef _KERNEL + +#define IFQ_MAXLEN 256 + +/* + * + * Interface Send Queues + * + * struct ifqueue sits between the network stack and a drivers + * transmission of packets. The high level view is that when the stack + * has finished generating a packet it hands it to a driver for + * transmission. It does this by queueing the packet on an ifqueue and + * notifying the driver to start transmission of the queued packets. + * + * A network device may have multiple contexts for the transmission + * of packets, ie, independent transmit rings. Such a network device, + * represented by a struct ifnet, would then have multiple ifqueue + * structures, each of which maps to an independent transmit ring. + * + * struct ifqueue also provides the point where conditioning of + * traffic (ie, priq and hfsc) is implemented, and provides some + * infrastructure to assist in the implementation of network drivers. + * + * = ifq API + * + * The ifq API provides functions for three distinct consumers: + * + * 1. The network stack + * 2. Traffic QoS/conditioning implementations + * 3. Network drivers + * + * == Network Stack API + * + * The network stack is responsible for initialising and destroying + * the ifqueue structures, changing the traffic conditioner on an + * interface, enqueuing packets for transmission, and notifying + * the driver to start transmission of a particular ifqueue. + * + * === ifq_init() + * + * During if_attach(), the network stack calls ifq_init to initialise + * the ifqueue structure. By default it configures the priq traffic + * conditioner. + * + * === ifq_destroy() + * + * The network stack calls ifq_destroy() during if_detach to tear down + * the ifqueue structure. It frees the traffic conditioner state, and + * frees any mbufs that were left queued. + * + * === ifq_attach() + * + * ifq_attach() is used to replace the current traffic conditioner on + * the ifqueue. All the pending mbufs are removed from the previous + * conditioner and requeued on the new. + * + * === ifq_idx() + * + * ifq_idx() selects a specific ifqueue from the current ifnet + * structure for use in the transmission of the mbuf. + * + * === ifq_enqueue() + * + * ifq_enqueue() attempts to fit an mbuf onto the ifqueue. The + * current traffic conditioner may drop a packet to make space on the + * queue. + * + * === ifq_start() + * + * Once a packet has been successfully queued with ifq_enqueue(), + * the network card is notified with a call to ifq_start(). + * Calls to ifq_start() run in the ifqueue serialisation context, + * guaranteeing that only one instance of ifp->if_qstart() will be + * running on behalf of a specific ifqueue in the system at any point + * in time. + * + * == Traffic conditioners API + * + * The majority of interaction between struct ifqueue and a traffic + * conditioner occurs via the callbacks a traffic conditioner provides + * in an instance of struct ifq_ops. + * + * XXX document ifqop_* + * + * The ifqueue API implements the locking on behalf of the conditioning + * implementations so conditioners only have to reject or keep mbufs. + * If something needs to inspect a conditioners internals, the queue lock + * needs to be taken to allow for a consistent or safe view. The queue + * lock may be taken and released with ifq_q_enter() and ifq_q_leave(). + * + * === ifq_q_enter() + * + * Code wishing to access a conditioners internals may take the queue + * lock with ifq_q_enter(). The caller must pass a reference to the + * conditioners ifq_ops structure so the infrastructure can ensure the + * caller is able to understand the internals. ifq_q_enter() returns + * a pointer to the conditioners internal structures, or NULL if the + * ifq_ops did not match the current conditioner. + * + * === ifq_q_leave() + * + * The queue lock acquired with ifq_q_enter() is released with + * ifq_q_leave(). + * + * === ifq_mfreem() and ifq_mfreeml() + * + * A goal of the API is to avoid freeing an mbuf while mutexes are + * held. Because the ifq API manages the lock on behalf of the backend + * ifqops, the backend should not directly free mbufs. If a conditioner + * backend needs to drop a packet during the handling of ifqop_deq_begin, + * it may free it by calling ifq_mfreem(). This accounts for the drop, + * and schedules the free of the mbuf outside the hold of ifq_mtx. + * ifq_mfreeml() takes an mbuf list as an argument instead. + * + * + * == Network Driver API + * + * The API used by network drivers is mostly documented in the + * ifq_dequeue(9) manpage except for ifq_serialize(). + * + * === ifq_serialize() + * + * A driver may run arbitrary work in the ifqueue serialiser context + * via ifq_serialize(). The work to be done is represented by a task + * that has been prepared with task_set. + * + * The work will be run in series with any other work dispatched by + * ifq_start(), ifq_restart(), or other ifq_serialize() calls. + * + * Because the work may be run on another CPU, the lifetime of the + * task and the work it represents can extend beyond the end of the + * call to ifq_serialize() that dispatched it. + * + * + * = ifqueue work serialisation + * + * ifqueues provide a mechanism to dispatch work to be run in a single + * context. Work in this mechanism is represented by task structures. + * + * The tasks are run in a context similar to a taskq serviced by a + * single kernel thread, except the work is run immediately by the + * first CPU that dispatches work. If a second CPU attempts to dispatch + * additional tasks while the first is still running, it will be queued + * to be run by the first CPU. The second CPU will return immediately. + * + * = MP Safe Network Drivers + * + * An MP safe network driver is one in which its start routine can be + * called by the network stack without holding the big kernel lock. + * + * == Attach + * + * A driver advertises its ability to run its start routine without + * the kernel lock by setting the IFXF_MPSAFE flag in ifp->if_xflags + * before calling if_attach(). Advertising an MPSAFE start routine + * also implies that the driver understands that a network card can + * have multiple rings or transmit queues, and therefore provides + * if_qstart function (which takes an ifqueue pointer) instead of an + * if_start function (which takes an ifnet pointer). + * + * If the hardware supports multiple transmit rings, it advertises + * support for multiple rings to the network stack with if_attach_queues() + * after the call to if_attach(). if_attach_queues allocates a struct + * ifqueue for each hardware ring, which can then be initialised by + * the driver with data for each ring. + * + * void drv_start(struct ifqueue *); + * + * void + * drv_attach() + * { + * ... + * ifp->if_xflags = IFXF_MPSAFE; + * ifp->if_qstart = drv_start; + * if_attach(ifp); + * + * if_attach_queues(ifp, DRV_NUM_TX_RINGS); + * for (i = 0; i < DRV_NUM_TX_RINGS; i++) { + * struct ifqueue *ifq = ifp->if_ifqs[i]; + * struct drv_tx_ring *ring = &sc->sc_tx_rings[i]; + * + * ifq->ifq_softc = ring; + * ring->ifq = ifq; + * } + * } + * + * The network stack will then call ifp->if_qstart via ifq_start() + * to guarantee there is only one instance of that function running + * for each ifq in the system, and to serialise it with other work + * the driver may provide. + * + * == Initialise + * + * When the stack requests an interface be brought up (ie, drv_ioctl() + * is called to handle SIOCSIFFLAGS with IFF_UP set in ifp->if_flags) + * drivers should set IFF_RUNNING in ifp->if_flags, and then call + * ifq_clr_oactive() against each ifq. + * + * == if_start + * + * ifq_start() checks that IFF_RUNNING is set in ifp->if_flags, that + * ifq_is_oactive() does not return true, and that there are pending + * packets to transmit via a call to ifq_len(). Therefore, drivers are + * no longer responsible for doing this themselves. + * + * If a driver should not transmit packets while its link is down, use + * ifq_purge() to flush pending packets from the transmit queue. + * + * Drivers for hardware should use the following pattern to transmit + * packets: + * + * void + * drv_start(struct ifqueue *ifq) + * { + * struct drv_tx_ring *ring = ifq->ifq_softc; + * struct ifnet *ifp = ifq->ifq_if; + * struct drv_softc *sc = ifp->if_softc; + * struct mbuf *m; + * int kick = 0; + * + * if (NO_LINK) { + * ifq_purge(ifq); + * return; + * } + * + * for (;;) { + * if (NO_SPACE(ring)) { + * ifq_set_oactive(ifq); + * break; + * } + * + * m = ifq_dequeue(ifq); + * if (m == NULL) + * break; + * + * if (drv_encap(sc, ring, m) != 0) { // map and fill ring + * m_freem(m); + * continue; + * } + * + * bpf_mtap(); + * } + * + * drv_kick(ring); // notify hw of new descriptors on the ring + * } + * + * == Transmission completion + * + * The following pattern should be used for transmit queue interrupt + * processing: + * + * void + * drv_txeof(struct drv_tx_ring *ring) + * { + * struct ifqueue *ifq = ring->ifq; + * + * while (COMPLETED_PKTS(ring)) { + * // unmap packets, m_freem() the mbufs. + * } + * + * if (ifq_is_oactive(ifq)) + * ifq_restart(ifq); + * } + * + * == Stop + * + * Bringing an interface down (ie, IFF_UP was cleared in ifp->if_flags) + * should clear IFF_RUNNING in ifp->if_flags, and guarantee the start + * routine is not running before freeing any resources it uses: + * + * void + * drv_down(struct drv_softc *sc) + * { + * struct ifnet *ifp = &sc->sc_if; + * struct ifqueue *ifq; + * int i; + * + * CLR(ifp->if_flags, IFF_RUNNING); + * DISABLE_INTERRUPTS(); + * + * for (i = 0; i < sc->sc_num_queues; i++) { + * ifq = ifp->if_ifqs[i]; + * ifq_barrier(ifq); + * } + * + * intr_barrier(sc->sc_ih); + * + * FREE_RESOURCES(); + * + * for (i = 0; i < sc->sc_num_queues; i++) { + * ifq = ifp->if_ifqs[i]; + * ifq_clr_oactive(ifq); + * } + * } + * + */ + +struct ifq_ops { + unsigned int (*ifqop_idx)(unsigned int, + const struct mbuf *); + struct mbuf *(*ifqop_enq)(struct ifqueue *, struct mbuf *); + struct mbuf *(*ifqop_deq_begin)(struct ifqueue *, void **); + void (*ifqop_deq_commit)(struct ifqueue *, + struct mbuf *, void *); + void (*ifqop_purge)(struct ifqueue *, + struct mbuf_list *); + void *(*ifqop_alloc)(unsigned int, void *); + void (*ifqop_free)(unsigned int, void *); +}; + +extern const struct ifq_ops * const ifq_priq_ops; + +/* + * Interface send queues. + */ + +void ifq_init(struct ifqueue *, struct ifnet *, unsigned int); +void ifq_attach(struct ifqueue *, const struct ifq_ops *, void *); +void ifq_destroy(struct ifqueue *); +void ifq_add_data(struct ifqueue *, struct if_data *); +int ifq_enqueue(struct ifqueue *, struct mbuf *); +void ifq_start(struct ifqueue *); +struct mbuf *ifq_deq_begin(struct ifqueue *); +void ifq_deq_commit(struct ifqueue *, struct mbuf *); +void ifq_deq_rollback(struct ifqueue *, struct mbuf *); +struct mbuf *ifq_dequeue(struct ifqueue *); +int ifq_hdatalen(struct ifqueue *); +void ifq_init_maxlen(struct ifqueue *, unsigned int); +void ifq_mfreem(struct ifqueue *, struct mbuf *); +void ifq_mfreeml(struct ifqueue *, struct mbuf_list *); +unsigned int ifq_purge(struct ifqueue *); +void *ifq_q_enter(struct ifqueue *, const struct ifq_ops *); +void ifq_q_leave(struct ifqueue *, void *); +void ifq_serialize(struct ifqueue *, struct task *); +void ifq_barrier(struct ifqueue *); +void ifq_set_oactive(struct ifqueue *); +void ifq_deq_set_oactive(struct ifqueue *); + +int ifq_deq_sleep(struct ifqueue *, struct mbuf **, int, int, + const char *, volatile unsigned int *, + volatile unsigned int *); + +#define ifq_len(_ifq) READ_ONCE((_ifq)->ifq_len) +#define ifq_empty(_ifq) (ifq_len(_ifq) == 0) + +static inline int +ifq_is_priq(struct ifqueue *ifq) +{ + return (ifq->ifq_ops == ifq_priq_ops); +} + +static inline void +ifq_clr_oactive(struct ifqueue *ifq) +{ + ifq->ifq_oactive = 0; +} + +static inline unsigned int +ifq_is_oactive(struct ifqueue *ifq) +{ + return (ifq->ifq_oactive); +} + +static inline void +ifq_restart(struct ifqueue *ifq) +{ + ifq_serialize(ifq, &ifq->ifq_restart); +} + +static inline unsigned int +ifq_idx(struct ifqueue *ifq, unsigned int nifqs, const struct mbuf *m) +{ + return ((*ifq->ifq_ops->ifqop_idx)(nifqs, m)); +} + +/* ifiq */ + +void ifiq_init(struct ifiqueue *, struct ifnet *, unsigned int); +void ifiq_destroy(struct ifiqueue *); +int ifiq_input(struct ifiqueue *, struct mbuf_list *); +int ifiq_enqueue_qlim(struct ifiqueue *, struct mbuf *, + unsigned int); +void ifiq_add_data(struct ifiqueue *, struct if_data *); + +#define ifiq_len(_ifiq) READ_ONCE(ml_len(&(_ifiq)->ifiq_ml)) +#define ifiq_empty(_ifiq) (ifiq_len(_ifiq) == 0) + +static inline int +ifiq_enqueue(struct ifiqueue *ifiq, struct mbuf *m) +{ + return ifiq_enqueue_qlim(ifiq, m, 0); +} + +#endif /* _KERNEL */ + +#endif /* _NET_IFQ_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/lldp.h b/lib/libc/include/generic-openbsd/net/lldp.h new file mode 100644 index 000000000000..ef3085391d92 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/lldp.h @@ -0,0 +1,67 @@ +/* $OpenBSD: lldp.h,v 1.1 2025/05/02 05:57:02 dlg Exp $ */ + +/* + * Copyright (c) 2025 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _NET_LLDP_H_ +#define _NET_LLDP_H_ + +#define LLDP_TLV_END 0 +#define LLDP_TLV_CHASSIS_ID 1 +#define LLDP_TLV_PORT_ID 2 +#define LLDP_TLV_TTL 3 +#define LLDP_TLV_PORT_DESCR 4 +#define LLDP_TLV_SYSTEM_NAME 5 +#define LLDP_TLV_SYSTEM_DESCR 6 +#define LLDP_TLV_SYSTEM_CAP 7 +#define LLDP_TLV_MANAGEMENT_ADDR 8 +#define LLDP_TLV_ORG 127 + +/* + * Chassis ID subtype enumeration + */ +#define LLDP_CHASSIS_ID_CHASSIS 1 /* Chassis component */ +#define LLDP_CHASSIS_ID_IFALIAS 2 /* Interface alias */ +#define LLDP_CHASSIS_ID_PORT 3 /* Port component */ +#define LLDP_CHASSIS_ID_MACADDR 4 /* MAC address */ +#define LLDP_CHASSIS_ID_ADDR 5 /* Network address */ +#define LLDP_CHASSIS_ID_IFNAME 6 /* Interface name */ +#define LLDP_CHASSIS_ID_LOCAL 7 /* Locally assigned */ + +/* + * Port ID subtype enumeration + */ +#define LLDP_PORT_ID_IFALIAS 1 /* Interface alias */ +#define LLDP_PORT_ID_PORT 2 /* Port component */ +#define LLDP_PORT_ID_MACADDR 3 /* MAC address */ +#define LLDP_PORT_ID_ADDR 4 /* Network address */ +#define LLDP_PORT_ID_IFNAME 5 /* Interface name */ +#define LLDP_PORT_ID_AGENTCID 6 /* Agent circuit ID */ +#define LLDP_PORT_ID_LOCAL 7 /* Locally assigned */ + +/* + * System Capabilities bits + */ +#define LLDP_SYSTEM_CAP_OTHER (1 << 0) +#define LLDP_SYSTEM_CAP_REPEATER (1 << 1) +#define LLDP_SYSTEM_CAP_BRIDGE (1 << 2) +#define LLDP_SYSTEM_CAP_WLAN (1 << 3) +#define LLDP_SYSTEM_CAP_ROUTER (1 << 4) +#define LLDP_SYSTEM_CAP_TELEPHONE (1 << 5) +#define LLDP_SYSTEM_CAP_DOCSIS (1 << 6) +#define LLDP_SYSTEM_CAP_STATION (1 << 7) + +#endif /* _NET_LLDP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/netisr.h b/lib/libc/include/generic-openbsd/net/netisr.h new file mode 100644 index 000000000000..1e515d8b55a0 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/netisr.h @@ -0,0 +1,78 @@ +/* $OpenBSD: netisr.h,v 1.61 2023/07/06 04:55:05 dlg Exp $ */ +/* $NetBSD: netisr.h,v 1.12 1995/08/12 23:59:24 mycroft Exp $ */ + +/* + * Copyright (c) 1980, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)netisr.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NET_NETISR_H_ +#define _NET_NETISR_H_ + +/* + * Each ``pup-level-1'' input queue has a bit in a ``netisr'' status + * word which is used to de-multiplex a single software + * interrupt used for scheduling the network code to calls + * on the lowest level routine of each protocol. + */ +#define NETISR_IP 2 /* same as AF_INET */ +#define NETISR_ARP 18 /* same as AF_LINK */ +#define NETISR_IPV6 24 /* same as AF_INET6 */ +#define NETISR_PIPEX 27 /* for pipex processing */ +#define NETISR_PPP 28 /* for PPP processing */ +#define NETISR_BRIDGE 29 /* for bridge processing */ +#define NETISR_PPPOE 30 /* for pppoe processing */ + +#ifndef _LOCORE +#ifdef _KERNEL + +#include +#include + +extern int netisr; /* scheduling bits for network */ +extern struct task if_input_task_locked; + +void arpintr(void); +void ipintr(void); +void ip6intr(void); +void pppintr(void); +void bridgeintr(void); +void pipexintr(void); +void pppoeintr(void); + +#define schednetisr(anisr) \ +do { \ + atomic_setbits_int(&netisr, (1 << (anisr))); \ + task_add(net_tq(0), &if_input_task_locked); \ +} while (/* CONSTCOND */0) + +#endif /* _KERNEL */ +#endif /*_LOCORE */ + +#endif /* _NET_NETISR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/ofp.h b/lib/libc/include/generic-openbsd/net/ofp.h new file mode 100644 index 000000000000..4ba0e60176cc --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/ofp.h @@ -0,0 +1,897 @@ +/* $OpenBSD: ofp.h,v 1.15 2023/04/11 00:45:09 jsg Exp $ */ + +/* + * Copyright (c) 2013-2016 Reyk Floeter + * Copyright (c) 2016 Kazuya GODA + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _NET_OFP_H_ +#define _NET_OFP_H_ + +#include +#include + +#include +#include +#include + +#define OFP_IFNAMSIZ 16 /* on-wire (not IF_NAMSIZE) */ +#define OFP_ALIGNMENT 8 /* OFP alignment */ +#define OFP_ALIGN(_x) (((_x) + (OFP_ALIGNMENT - 1)) & ~(OFP_ALIGNMENT - 1)) + +struct ofp_header { + uint8_t oh_version; /* OpenFlow version */ + uint8_t oh_type; /* message type */ + uint16_t oh_length; /* message length */ + uint32_t oh_xid; /* transaction Id */ +} __packed; + +/* OpenFlow version */ +#define OFP_V_0 0x00 /* OpenFlow 0.0 */ +#define OFP_V_1_0 0x01 /* OpenFlow 1.0 */ +#define OFP_V_1_1 0x02 /* OpenFlow 1.1 */ +#define OFP_V_1_2 0x03 /* OpenFlow 1.2 */ +#define OFP_V_1_3 0x04 /* OpenFlow 1.3 */ +#define OFP_V_1_4 0x05 /* OpenFlow 1.4 */ +#define OFP_V_1_5 0x06 /* OpenFlow 1.5 */ + +/* OpenFlow message type */ +#define OFP_T_HELLO 0 /* Hello */ +#define OFP_T_ERROR 1 /* Error */ +#define OFP_T_ECHO_REQUEST 2 /* Echo Request */ +#define OFP_T_ECHO_REPLY 3 /* Echo Reply */ +#define OFP_T_EXPERIMENTER 4 /* Vendor/Experimenter */ +#define OFP_T_FEATURES_REQUEST 5 /* Features Request (switch) */ +#define OFP_T_FEATURES_REPLY 6 /* Features Reply (switch) */ +#define OFP_T_GET_CONFIG_REQUEST 7 /* Get Config Request (switch) */ +#define OFP_T_GET_CONFIG_REPLY 8 /* Get Config Reply (switch) */ +#define OFP_T_SET_CONFIG 9 /* Set Config (switch) */ +#define OFP_T_PACKET_IN 10 /* Packet In (async) */ +#define OFP_T_FLOW_REMOVED 11 /* Flow Removed (async) */ +#define OFP_T_PORT_STATUS 12 /* Port Status (async) */ +#define OFP_T_PACKET_OUT 13 /* Packet Out (controller) */ +#define OFP_T_FLOW_MOD 14 /* Flow Mod (controller) */ +#define OFP_T_GROUP_MOD 15 /* Group Mod (controller) */ +#define OFP_T_PORT_MOD 16 /* Port Mod (controller) */ +#define OFP_T_TABLE_MOD 17 /* Table Mod (controller) */ +#define OFP_T_MULTIPART_REQUEST 18 /* Multipart Message Request */ +#define OFP_T_MULTIPART_REPLY 19 /* Multipart Message Request */ +#define OFP_T_BARRIER_REQUEST 20 /* Barrier Request */ +#define OFP_T_BARRIER_REPLY 21 /* Barrier Reply */ +#define OFP_T_QUEUE_GET_CONFIG_REQUEST 22 /* Queue Get Config Request */ +#define OFP_T_QUEUE_GET_CONFIG_REPLY 23 /* Queue Get Config Reply */ +#define OFP_T_ROLE_REQUEST 24 /* Role Request */ +#define OFP_T_ROLE_REPLY 25 /* Role Reply */ +#define OFP_T_GET_ASYNC_REQUEST 26 /* Get Async Request */ +#define OFP_T_GET_ASYNC_REPLY 27 /* Get Async Reply */ +#define OFP_T_SET_ASYNC 28 /* Set Async */ +#define OFP_T_METER_MOD 29 /* Meter Mod */ +#define OFP_T_TYPE_MAX 30 + +/* OpenFlow Hello Message */ +struct ofp_hello_element_header { + uint16_t he_type; + uint16_t he_length; +} __packed; + +#define OFP_HELLO_T_VERSION_BITMAP 1 /* Supported version bitmap */ + +struct ofp_hello_element_versionbitmap { + uint16_t hev_type; + uint16_t hev_length; +} __packed; + +/* Ports */ +#define OFP_PORT_MAX 0xffffff00 /* Maximum number of physical ports */ +#define OFP_PORT_INPUT 0xfffffff8 /* Send back to input port */ +#define OFP_PORT_FLOWTABLE 0xfffffff9 /* Perform actions in flow table */ +#define OFP_PORT_NORMAL 0xfffffffa /* Let switch decide */ +#define OFP_PORT_FLOOD 0xfffffffb /* All non-block ports except input */ +#define OFP_PORT_ALL 0xfffffffc /* All ports except input */ +#define OFP_PORT_CONTROLLER 0xfffffffd /* Send to controller */ +#define OFP_PORT_LOCAL 0xfffffffe /* Local virtual OpenFlow port */ +#define OFP_PORT_ANY 0xffffffff /* No port */ + +/* Switch Config Message (reply) */ +struct ofp_switch_config { + struct ofp_header cfg_oh; /* OpenFlow header */ + uint16_t cfg_flags; /* Configuration flags */ + uint16_t cfg_miss_send_len; /* Max bytes from datapath */ +} __packed; + +/* Switch Config */ +#define OFP_CONFIG_FRAG_NORMAL 0x0000 /* No special frag handling */ +#define OFP_CONFIG_FRAG_DROP 0x0001 /* Drop fragments */ +#define OFP_CONFIG_FRAG_REASM 0x0002 /* Reassemble fragments */ +#define OFP_CONFIG_FRAG_MASK 0x0003 /* Fragment mask */ + +/* Switch port description */ +struct ofp_switch_port { + uint32_t swp_number; /* Switch port number */ + uint8_t swp_pad[4]; /* Padding */ + uint8_t swp_macaddr[ETHER_ADDR_LEN]; /* Port MAC address */ + uint8_t swp_pad2[2]; /* Padding */ + char swp_name[OFP_IFNAMSIZ]; /* Switch port name */ + uint32_t swp_config; /* Configuration flags */ + uint32_t swp_state; /* State flags */ + uint32_t swp_cur; /* Current features */ + uint32_t swp_advertised; /* Advertised by the port */ + uint32_t swp_supported; /* Supported by the port */ + uint32_t swp_peer; /* Advertised by peer */ + uint32_t swp_cur_speed; /* Current port speed in Kbps*/ + uint32_t swp_max_speed; /* Support port max speed in Kbps*/ +} __packed; + +/* Physical port configuration */ +#define OFP_PORTCONFIG_PORT_DOWN 0x1 /* Port is down */ +#define OFP_PORTCONFIG_NO_STP 0x2 /* Disable STP on port */ +#define OFP_PORTCONFIG_NO_RECV 0x4 /* Drop everything except STP */ +#define OFP_PORTCONFIG_NO_RECV_STP 0x8 /* Drop received STP */ +#define OFP_PORTCONFIG_NO_FLOOD 0x10 /* Do not flood to this port */ +#define OFP_PORTCONFIG_NO_FWD 0x20 /* Drop packets to port */ +#define OFP_PORTCONFIG_NO_PACKET_IN 0x40 /* NO PACKET_IN on port */ + +/* Physical port state */ +#define OFP_PORTSTATE_LINK_DOWN 0x1 /* Link not active */ +#define OFP_PORTSTATE_STP_LISTEN 0x000 /* Not learning or forwarding */ +#define OFP_PORTSTATE_STP_LEARN 0x100 /* Learning but not forwarding */ +#define OFP_PORTSTATE_STP_FORWARD 0x200 /* Learning and forwarding */ +#define OFP_PORTSTATE_STP_BLOCK 0x300 /* Not part of spanning tree */ +#define OFP_PORTSTATE_STP_MASK 0x300 /* Spanning tree values */ + +/* Physical port media types */ +#define OFP_PORTMEDIA_10MB_HD 0x1 /* 10 Mb half-duplex */ +#define OFP_PORTMEDIA_10MB_FD 0x2 /* 10 Mb full-duplex */ +#define OFP_PORTMEDIA_100MB_HD 0x4 /* 100 Mb half-duplex */ +#define OFP_PORTMEDIA_100MB_FD 0x8 /* 100 Mb full-duplex */ +#define OFP_PORTMEDIA_1GB_HD 0x10 /* 1 Gb half-duplex */ +#define OFP_PORTMEDIA_1GB_FD 0x20 /* 1 Gb full-duplex */ +#define OFP_PORTMEDIA_10GB_FD 0x40 /* 10 Gb full-duplex */ +#define OFP_PORTMEDIA_COPPER 0x80 /* Copper */ +#define OFP_PORTMEDIA_FIBER 0x100 /* Fiber */ +#define OFP_PORTMEDIA_AUTONEG 0x200 /* Auto-negotiation */ +#define OFP_PORTMEDIA_PAUSE 0x400 /* Pause */ +#define OFP_PORTMEDIA_PAUSE_ASYM 0x800 /* Asymmetric pause */ + +/* Switch Features Message (reply) */ +struct ofp_switch_features { + struct ofp_header swf_oh; /* OpenFlow header */ + uint64_t swf_datapath_id; /* Datapath unique ID */ + uint32_t swf_nbuffers; /* Max packets buffered */ + uint8_t swf_ntables; /* Number of supported tables */ + uint8_t swf_aux_id; /* Identify auxiliary connections */ + uint8_t swf_pad[2]; /* Align to 64 bits */ + uint32_t swf_capabilities; /* Capability flags */ + uint32_t swf_actions; /* Supported action flags */ +} __packed; + +/* Switch capabilities */ +#define OFP_SWCAP_FLOW_STATS 0x1 /* Flow statistics */ +#define OFP_SWCAP_TABLE_STATS 0x2 /* Table statistics */ +#define OFP_SWCAP_PORT_STATS 0x4 /* Port statistics */ +#define OFP_SWCAP_GROUP_STATS 0x8 /* Group statistics */ +#define OFP_SWCAP_IP_REASM 0x20 /* Can reassemble IP frags */ +#define OFP_SWCAP_QUEUE_STATS 0x40 /* Queue statistics */ +#define OFP_SWCAP_ARP_MATCH_IP 0x80 /* Match IP addresses in ARP pkts */ +#define OFP_SWCAP_PORT_BLOCKED 0x100 /* Switch will block ports */ + +/* Flow matching */ +struct ofp_match { + uint16_t om_type; + uint16_t om_length; +} __packed; + +/* Flow matching type */ +#define OFP_MATCH_STANDARD 0 /* Standard match deprecated */ +#define OFP_MATCH_OXM 1 /* OpenFlow Extensible Match */ + +/* Packet-In Message */ +struct ofp_packet_in { + struct ofp_header pin_oh; /* OpenFlow header */ + uint32_t pin_buffer_id; + uint16_t pin_total_len; + uint8_t pin_reason; + uint8_t pin_table_id; + uint64_t pin_cookie; + struct ofp_match pin_match; +} __packed; + +/* Reason */ +#define OFP_PKTIN_REASON_NO_MATCH 0 /* No matching flow */ +#define OFP_PKTIN_REASON_ACTION 1 /* Explicit output */ +#define OFP_PKTIN_REASON_TTL 2 /* Packet has invalid TTL */ + +/* Flow Instruction */ +struct ofp_instruction { + uint16_t i_type; + uint16_t i_len; +} __packed; + +/* Instruction types */ +#define OFP_INSTRUCTION_T_GOTO_TABLE 1 /* Goto-Table */ +#define OFP_INSTRUCTION_T_WRITE_META 2 /* Write-Metadata */ +#define OFP_INSTRUCTION_T_WRITE_ACTIONS 3 /* Write-Actions */ +#define OFP_INSTRUCTION_T_APPLY_ACTIONS 4 /* Apply-Actions */ +#define OFP_INSTRUCTION_T_CLEAR_ACTIONS 5 /* Clear-Actions */ +#define OFP_INSTRUCTION_T_METER 6 /* Meter */ +#define OFP_INSTRUCTION_T_EXPERIMENTER 0xffff /* Experimenter */ + +/* Write-Metadata instruction */ +struct ofp_instruction_write_metadata { + uint16_t iwm_type; + uint16_t iwm_len; + uint8_t iwm_pad[4]; + uint64_t iwm_metadata; + uint64_t iwm_metadata_mask; +} __packed; + +/* Goto-Table instruction */ +struct ofp_instruction_goto_table { + uint16_t igt_type; + uint16_t igt_len; + uint8_t igt_table_id; + uint8_t igt_pad[3]; +} __packed; + +/* Apply-Actions instruction */ +struct ofp_instruction_actions { + uint16_t ia_type; + uint16_t ia_len; + uint8_t ia_pad[4]; +} __packed; + +/* Meter instruction */ +struct ofp_instruction_meter { + uint16_t im_type; + uint16_t im_len; + uint32_t im_meter_id; +} __packed; + +/* Experimenter instruction */ +struct ofp_instruction_experimenter { + uint16_t ie_type; + uint16_t ie_len; + uint32_t ie_experimenter; +} __packed; + +/* Actions */ +#define OFP_ACTION_OUTPUT 0 /* Output to switch port */ +#define OFP_ACTION_COPY_TTL_OUT 11 /* Copy TTL outwards */ +#define OFP_ACTION_COPY_TTL_IN 12 /* Copy TTL inwards */ +#define OFP_ACTION_SET_MPLS_TTL 15 /* MPLS TTL */ +#define OFP_ACTION_DEC_MPLS_TTL 16 /* Decrement MPLS TTL */ +#define OFP_ACTION_PUSH_VLAN 17 /* Push a new VLAN tag */ +#define OFP_ACTION_POP_VLAN 18 /* Pop the outer VLAN tag */ +#define OFP_ACTION_PUSH_MPLS 19 /* Push a new MPLS tag */ +#define OFP_ACTION_POP_MPLS 20 /* Pop the outer MPLS tag */ +#define OFP_ACTION_SET_QUEUE 21 /* Set queue id when outputting to a port */ +#define OFP_ACTION_GROUP 22 /* Apply group */ +#define OFP_ACTION_SET_NW_TTL 23 /* Set IP TTL */ +#define OFP_ACTION_DEC_NW_TTL 24 /* Decrement IP TTL */ +#define OFP_ACTION_SET_FIELD 25 /* Set a header field using OXM TLV format */ +#define OFP_ACTION_PUSH_PBB 26 /* Push a new PBB service tag (I-TAG) */ +#define OFP_ACTION_POP_PBB 27 /* Pop the outer PBB service tag (I-TAG) */ +#define OFP_ACTION_EXPERIMENTER 0xffff /* Vendor-specific action */ + +/* Action Header */ +struct ofp_action_header { + uint16_t ah_type; + uint16_t ah_len; + uint32_t ah_pad; +} __packed; + +/* Output Action */ +struct ofp_action_output { + uint16_t ao_type; + uint16_t ao_len; + uint32_t ao_port; + uint16_t ao_max_len; + uint8_t ao_pad[6]; +} __packed; + +/* Buffer configuration */ +#define OFP_CONTROLLER_MAXLEN_MAX 0xffe5 /* maximum buffer length */ +#define OFP_CONTROLLER_MAXLEN_NO_BUFFER 0xffff /* don't do any buffering */ + +struct ofp_action_mpls_ttl { + uint16_t amt_type; + uint16_t amt_len; + uint8_t amt_ttl; + uint8_t amt_pad[3]; +} __packed; + +struct ofp_action_push { + uint16_t ap_type; + uint16_t ap_len; + uint16_t ap_ethertype; + uint8_t ap_pad[2]; +} __packed; + +struct ofp_action_pop_mpls { + uint16_t apm_type; + uint16_t apm_len; + uint16_t apm_ethertype; + uint8_t apm_pad[2]; +} __packed; + +struct ofp_action_group { + uint16_t ag_type; + uint16_t ag_len; + uint32_t ag_group_id; +} __packed; + +struct ofp_action_nw_ttl { + uint16_t ant_type; + uint16_t ant_len; + uint8_t ant_ttl; + uint8_t ant_pad[3]; +} __packed; + +struct ofp_action_set_field { + uint16_t asf_type; + uint16_t asf_len; + uint8_t asf_field[4]; +} __packed; + +struct ofp_action_set_queue { + uint16_t asq_type; + uint16_t asq_len; + uint32_t asq_queue_id; +} __packed; + +/* Packet-Out Message */ +struct ofp_packet_out { + struct ofp_header pout_oh; /* OpenFlow header */ + uint32_t pout_buffer_id; + uint32_t pout_in_port; + uint16_t pout_actions_len; + uint8_t pout_pad[6]; + struct ofp_action_header pout_actions[0]; + /* Followed by optional packet data if buffer_id == 0xffffffff */ +} __packed; + +/* Special buffer id */ +#define OFP_PKTOUT_NO_BUFFER 0xffffffff /* No buffer id */ + +/* Flow match fields for basic class */ +#define OFP_XM_T_IN_PORT 0 /* Switch input port */ +#define OFP_XM_T_IN_PHY_PORT 1 /* Switch physical input port */ +#define OFP_XM_T_META 2 /* Metadata passed between tables */ +#define OFP_XM_T_ETH_DST 3 /* Ethernet destination address */ +#define OFP_XM_T_ETH_SRC 4 /* Ethernet source address */ +#define OFP_XM_T_ETH_TYPE 5 /* Ethernet frame type */ +#define OFP_XM_T_VLAN_VID 6 /* VLAN id */ +#define OFP_XM_T_VLAN_PCP 7 /* VLAN priority */ +#define OFP_XM_T_IP_DSCP 8 /* IP DSCP (6 bits in ToS field) */ +#define OFP_XM_T_IP_ECN 9 /* IP ECN (2 bits in ToS field) */ +#define OFP_XM_T_IP_PROTO 10 /* IP protocol */ +#define OFP_XM_T_IPV4_SRC 11 /* IPv4 source address */ +#define OFP_XM_T_IPV4_DST 12 /* IPv4 destination address */ +#define OFP_XM_T_TCP_SRC 13 /* TCP source port */ +#define OFP_XM_T_TCP_DST 14 /* TCP destination port */ +#define OFP_XM_T_UDP_SRC 15 /* UDP source port */ +#define OFP_XM_T_UDP_DST 16 /* UDP destination port */ +#define OFP_XM_T_SCTP_SRC 17 /* SCTP source port */ +#define OFP_XM_T_SCTP_DST 18 /* SCTP destination port */ +#define OFP_XM_T_ICMPV4_TYPE 19 /* ICMP type */ +#define OFP_XM_T_ICMPV4_CODE 20 /* ICMP code */ +#define OFP_XM_T_ARP_OP 21 /* ARP opcode */ +#define OFP_XM_T_ARP_SPA 22 /* ARP source IPv4 address */ +#define OFP_XM_T_ARP_TPA 23 /* ARP target IPv4 address */ +#define OFP_XM_T_ARP_SHA 24 /* ARP source hardware address */ +#define OFP_XM_T_ARP_THA 25 /* ARP target hardware address */ +#define OFP_XM_T_IPV6_SRC 26 /* IPv6 source address */ +#define OFP_XM_T_IPV6_DST 27 /* IPv6 destination address */ +#define OFP_XM_T_IPV6_FLABEL 28 /* IPv6 Flow Label */ +#define OFP_XM_T_ICMPV6_TYPE 29 /* ICMPv6 type */ +#define OFP_XM_T_ICMPV6_CODE 30 /* ICMPv6 code */ +#define OFP_XM_T_IPV6_ND_TARGET 31 /* Target address for ND */ +#define OFP_XM_T_IPV6_ND_SLL 32 /* Source link-layer for ND */ +#define OFP_XM_T_IPV6_ND_TLL 33 /* Target link-layer for ND */ +#define OFP_XM_T_MPLS_LABEL 34 /* MPLS label */ +#define OFP_XM_T_MPLS_TC 35 /* MPLS TC */ +#define OFP_XM_T_MPLS_BOS 36 /* MPLS BoS bit */ +#define OFP_XM_T_PBB_ISID 37 /* PBB I-SID */ +#define OFP_XM_T_TUNNEL_ID 38 /* Logical Port Metadata */ +#define OFP_XM_T_IPV6_EXTHDR 39 /* IPv6 Extension Header pseudo-field */ +#define OFP_XM_T_MAX 40 + +/* Flow match fields for nxm1 class */ +#define OFP_XM_NXMT_TUNNEL_ID 38 /* Tunnel Logical Port Metadata */ +#define OFP_XM_NXMT_TUNNEL_IPV4_SRC 31 /* Tunnel IPv4 source address */ +#define OFP_XM_NXMT_TUNNEL_IPV4_DST 32 /* Tunnel IPv4 destination address */ +#define OFP_XM_NXMT_TUNNEL_IPV6_SRC 109 /* Tunnel IPv6 source address */ +#define OFP_XM_NXMT_TUNNEL_IPV6_DST 110 /* Tunnel IPv6 destination address */ + +/* OXM class */ +#define OFP_OXM_C_NXM_0 0x0000 /* NXM 0 */ +#define OFP_OXM_C_NXM_1 0x0001 /* NXM 1 */ +#define OFP_OXM_C_OPENFLOW_BASIC 0x8000 /* OpenFlow Basic */ +#define OFP_OXM_C_OPENFLOW_EXPERIMENTER 0xffff /* OpenFlow Experimenter */ + +/* VLAN matching flag */ +#define OFP_XM_VID_PRESENT 0x1000 /* VLAN ID present */ +#define OFP_XM_VID_NONE 0x0000 /* No VLAN ID */ + +/* IPv6 Extension header pseudo-field flags */ +#define OFP_XM_IPV6_EXTHDR_NONEXT 0x0001 /* "No next header" encountered */ +#define OFP_XM_IPV6_EXTHDR_ESP 0x0002 /* Encrypted Sec Payload header present */ +#define OFP_XM_IPV6_EXTHDR_AUTH 0x0004 /* Authentication header present. */ +#define OFP_XM_IPV6_EXTHDR_DEST 0x0008 /* 1 or 2 dest headers present. */ +#define OFP_XM_IPV6_EXTHDR_FRAG 0x0010 /* Fragment header present. */ +#define OFP_XM_IPV6_EXTHDR_ROUTER 0x0020 /* Router header present. */ +#define OFP_XM_IPV6_EXTHDR_HOP 0x0040 /* Hop-by-hop header present. */ +#define OFP_XM_IPV6_EXTHDR_UNREP 0x0080 /* Unexpected repeats encountered. */ +#define OFP_XM_IPV6_EXTHDR_UNSEQ 0x0100 /* Unexpected sequencing encountered. */ + +struct ofp_ox_match { + uint16_t oxm_class; + uint8_t oxm_fh; + uint8_t oxm_length; + uint8_t oxm_value[0]; +} __packed; + +#define OFP_OXM_GET_FIELD(o) (((o)->oxm_fh) >> 1) +#define OFP_OXM_GET_HASMASK(o) (((o)->oxm_fh) & 0x1) +#define OFP_OXM_SET_FIELD(o, t) (((o)->oxm_fh) = ((t) << 1)) +#define OFP_OXM_SET_HASMASK(o) (((o)->oxm_fh) |= 0x1) + +/* Flow modification commands */ +#define OFP_FLOWCMD_ADD 0 /* Add new flow */ +#define OFP_FLOWCMD_MODIFY 1 /* Modify flow */ +#define OFP_FLOWCMD_MODIFY_STRICT 2 /* Modify flow w/o wildcard */ +#define OFP_FLOWCMD_DELETE 3 /* Delete flow */ +#define OFP_FLOWCMD_DELETE_STRICT 4 /* Delete flow w/o wildcard */ + +/* Flow modification flags */ +#define OFP_FLOWFLAG_SEND_FLOW_REMOVED 0x0001 /* Send flow removed message */ +#define OFP_FLOWFLAG_CHECK_OVERLAP 0x0002 /* Check flow overlap first */ +#define OFP_FLOWFLAG_RESET_COUNTS 0x0004 /* Reset flow packet and byte counters */ +#define OFP_FLOWFLAG_NO_PACKET_COUNTS 0x0008 /* Don't keep track of packet count */ +#define OFP_FLOWFLAG_NO_BYTE_COUNTS 0x0010 /* Don't keep track of byte count */ + +/* Flow modification message */ +struct ofp_flow_mod { + struct ofp_header fm_oh; /* OpenFlow header */ + uint64_t fm_cookie; + uint64_t fm_cookie_mask; + uint8_t fm_table_id; + uint8_t fm_command; + uint16_t fm_idle_timeout; + uint16_t fm_hard_timeout; + uint16_t fm_priority; + uint32_t fm_buffer_id; + uint32_t fm_out_port; + uint32_t fm_out_group; + uint16_t fm_flags; + uint8_t fm_pad[2]; + struct ofp_match fm_match; +} __packed; + +/* Flow removed reasons */ +#define OFP_FLOWREM_REASON_IDLE_TIMEOUT 0 /* Flow idle time exceeded idle_timeout */ +#define OFP_FLOWREM_REASON_HARD_TIMEOUT 1 /* Time exceeded hard_timeout */ +#define OFP_FLOWREM_REASON_DELETE 2 /* Evicted by a DELETE flow mod */ +#define OFP_FLOWREM_REASON_GROUP_DELETE 3 /* Group was removed */ + +/* Flow removed message */ +struct ofp_flow_removed { + struct ofp_header fr_oh; + uint64_t fr_cookie; + uint16_t fr_priority; + uint8_t fr_reason; + uint8_t fr_table_id; + uint32_t fr_duration_sec; + uint32_t fr_duration_nsec; + uint16_t fr_idle_timeout; + uint16_t fr_hard_timeout; + uint64_t fr_packet_count; + uint64_t fr_byte_count; + struct ofp_match fr_match; +} __packed; + +/* Error message */ +struct ofp_error { + struct ofp_header err_oh; + uint16_t err_type; + uint16_t err_code; + uint8_t err_data[0]; + /* Followed by optional data */ +} __packed; +#define OFP_ERRDATA_MAX 64 + +/* Error types */ +#define OFP_ERRTYPE_HELLO_FAILED 0 /* Hello protocol failed */ +#define OFP_ERRTYPE_BAD_REQUEST 1 /* Request was not understood */ +#define OFP_ERRTYPE_BAD_ACTION 2 /* Error in action */ +#define OFP_ERRTYPE_BAD_INSTRUCTION 3 /* Error in instruction list */ +#define OFP_ERRTYPE_BAD_MATCH 4 /* Error in match */ +#define OFP_ERRTYPE_FLOW_MOD_FAILED 5 /* Problem modifying flow */ +#define OFP_ERRTYPE_GROUP_MOD_FAILED 6 /* Problem modifying group */ +#define OFP_ERRTYPE_PORT_MOD_FAILED 7 /* Port mod request failed */ +#define OFP_ERRTYPE_TABLE_MOD_FAILED 8 /* Port mod request failed */ +#define OFP_ERRTYPE_QUEUE_OP_FAILED 9 /* Queue operation failed */ +#define OFP_ERRTYPE_SWITCH_CFG_FAILED 10 /* Switch Config request failed */ +#define OFP_ERRTYPE_ROLE_REQUEST_FAILED 11 /* Controller role request failed */ +#define OFP_ERRTYPE_METER_MOD_FAILED 12 /* Error in meter */ +#define OFP_ERRTYPE_TABLE_FEATURES_FAILED 13 /* Setting table features failed */ +#define OFP_ERRTYPE_EXPERIMENTER 0xffff /* Experimenter error message */ + +/* HELLO error codes */ +#define OFP_ERRHELLO_INCOMPATIBLE 0 /* No compatible version */ +#define OFP_ERRHELLO_EPERM 1 /* Permissions error */ + +/* REQUEST error codes */ +#define OFP_ERRREQ_VERSION 0 /* Version not supported */ +#define OFP_ERRREQ_TYPE 1 /* Type not supported */ +#define OFP_ERRREQ_MULTIPART 2 /* Multipart type not supported */ +#define OFP_ERRREQ_EXPERIMENTER 3 /* Experimenter id not supported */ +#define OFP_ERRREQ_EXP_TYPE 4 /* Experimenter type not supported */ +#define OFP_ERRREQ_EPERM 5 /* Permission error */ +#define OFP_ERRREQ_BAD_LEN 6 /* Wrong request length for type */ +#define OFP_ERRREQ_BUFFER_EMPTY 7 /* Specified buffer has already been used */ +#define OFP_ERRREQ_BUFFER_UNKNOWN 8 /* Specified buffer does not exist */ +#define OFP_ERRREQ_TABLE_ID 9 /* Specified table-id invalid or does not exit */ +#define OFP_ERRREQ_IS_SLAVE 10 /* Denied because controller is slave */ +#define OFP_ERRREQ_PORT 11 /* Invalid port */ +#define OFP_ERRREQ_PACKET 12 /* Invalid packet in packet-out */ +#define OFP_ERRREQ_MULTIPART_OVERFLOW 13 /* Multipart overflowed the assigned buffer */ + +/* ACTION error codes */ +#define OFP_ERRACTION_TYPE 0 /* Unknown or unsupported action type */ +#define OFP_ERRACTION_LEN 1 /* Length problem in actions */ +#define OFP_ERRACTION_EXPERIMENTER 2 /* Unknown experimenter id specified */ +#define OFP_ERRACTION_EXP_TYPE 3 /* Unknown action for experimenter id */ +#define OFP_ERRACTION_OUT_PORT 4 /* Problem validating output port */ +#define OFP_ERRACTION_ARGUMENT 5 /* Bad action argument */ +#define OFP_ERRACTION_EPERM 6 /* Permission error */ +#define OFP_ERRACTION_TOO_MANY 7 /* Can't handle this many actions */ +#define OFP_ERRACTION_BAD_QUEUE 8 /* Problem validating output queue */ +#define OFP_ERRACTION_BAD_OUT_GROUP 9 /* Invalid group id in forward action */ +#define OFP_ERRACTION_MATCH_INCONSISTENT 10 /* Action can't apply or Set-Field failed */ +#define OFP_ERRACTION_UNSUPPORTED_ORDER 11 /* Action order is unsupported for Apply-Actions */ +#define OFP_ERRACTION_TAG 12 /* Actions uses an unsupported tag/encap */ +#define OFP_ERRACTION_SET_TYPE 13 /* Unsupported type in SET_FIELD action */ +#define OFP_ERRACTION_SET_LEN 14 /* Length problem in SET_FIELD action */ +#define OFP_ERRACTION_SET_ARGUMENT 15 /* Bad argument in SET_FIELD action */ + +/* INSTRUCTION error codes */ +#define OFP_ERRINST_UNKNOWN_INST 0 /* Unknown instruction */ +#define OFP_ERRINST_UNSUPPORTED_INST 1 /* Switch or table does not support */ +#define OFP_ERRINST_TABLE_ID 2 /* Invalid Table-ID specified */ +#define OFP_ERRINST_UNSUPP_META 3 /* Metadata value unsupported by datapath */ +#define OFP_ERRINST_UNSUPP_META_MASK 4 /* Metadata mask value unsupported by datapath */ +#define OFP_ERRINST_BAD_EXPERIMENTER 5 /* Unknown experimenter id specified */ +#define OFP_ERRINST_BAD_EXPERIMENTER_TYPE 6 /* Unknown instruction for experimenter id */ +#define OFP_ERRINST_BAD_LEN 7 /* Length problem in instructions */ +#define OFP_ERRINST_EPERM 8 /* Permissions error */ + +/* MATCH error codes */ +#define OFP_ERRMATCH_BAD_TYPE 0 /* Unsupported match type */ +#define OFP_ERRMATCH_BAD_LEN 1 /* Length problem in match */ +#define OFP_ERRMATCH_BAD_TAG 2 /* Match uses an unsupported tag/encap */ +#define OFP_ERRMATCH_BAD_DL_ADDR_MASK 3 /* Unsupported datalink addr mask */ +#define OFP_ERRMATCH_BAD_NW_ADDR_MASK 4 /* Unsupported network addr mask */ +#define OFP_ERRMATCH_BAD_WILDCARDS 5 /* Unsupported combination of fields */ +#define OFP_ERRMATCH_BAD_FIELD 6 /* Unsupported field type in the match */ +#define OFP_ERRMATCH_BAD_VALUE 7 /* Unsupported value in a match field */ +#define OFP_ERRMATCH_BAD_MASK 8 /* Unsupported mask specified in match */ +#define OFP_ERRMATCH_BAD_PREREQ 9 /* A prerequisite was not met */ +#define OFP_ERRMATCH_DUP_FIELD 10 /* A field type was duplicated */ +#define OFP_ERRMATCH_EPERM 11 /* Permissions error */ + +/* FLOW MOD error codes */ +#define OFP_ERRFLOWMOD_UNKNOWN 0 /* Unknown */ +#define OFP_ERRFLOWMOD_TABLE_FULL 1 /* Table is full */ +#define OFP_ERRFLOWMOD_TABLE_ID 2 /* Invalid table id */ +#define OFP_ERRFLOWMOD_OVERLAP 3 /* Overlapping flow */ +#define OFP_ERRFLOWMOD_EPERM 4 /* Permissions error */ +#define OFP_ERRFLOWMOD_BAD_TIMEOUT 5 /* non-zero idle/hard timeout */ +#define OFP_ERRFLOWMOD_BAD_COMMAND 6 /* Unsupported or Unknown command */ +#define OFP_ERRFLOWMOD_BAD_FLAGS 7 /* Unsupported or Unknown flags */ + +/* GROUP MOD error codes */ +#define OFP_ERRGROUPMOD_GROUP_EXISTS 0 /* Already present group */ +#define OFP_ERRGROUPMOD_INVALID_GROUP 1 /* Group specified is invalid */ +#define OFP_ERRGROUPMOD_WEIGHT_UNSUPP 2 /* Switch does not support unequal load sharing */ +#define OFP_ERRGROUPMOD_OUT_OF_GROUPS 3 /* The Group table is full */ +#define OFP_ERRGROUPMOD_OUT_OF_BUCKETS 4 /* The maximum number of action buckets */ +#define OFP_ERRGROUPMOD_CHAINING_UNSUPP 5 /* Switch does not support groups forwarding to groups */ +#define OFP_ERRGROUPMOD_WATCH_UNSUPP 6 /* This group cannot watch the watch_port */ +#define OFP_ERRGROUPMOD_LOOP 7 /* Group entry would cause a loop */ +#define OFP_ERRGROUPMOD_UNKNOWN_GROUP 8 /* MODIFY attempted to modify a non-existent group */ +#define OFP_ERRGROUPMOD_CHAINED_GROUP 9 /* Group not deleted because another group is forwarding to it */ +#define OFP_ERRGROUPMOD_BAD_TYPE 10 /* Unsupported or unknown group type */ +#define OFP_ERRGROUPMOD_BAD_COMMAND 11 /* Unsupported or unknown command */ +#define OFP_ERRGROUPMOD_BAD_BUCKET 12 /* Error in bucket */ +#define OFP_ERRGROUPMOD_BAD_WATCH 13 /* Error in watch port/group */ +#define OFP_ERRGROUPMOD_EPERM 14 /* Permission error */ + +/* GROUP MOD message */ +#define OFP_GROUPCMD_ADD 0 /* Add group */ +#define OFP_GROUPCMD_MODIFY 1 /* Modify group */ +#define OFP_GROUPCMD_DELETE 2 /* Delete group */ + +/* Group types */ +#define OFP_GROUP_T_ALL 0 /* All (multicast/broadcast) group */ +#define OFP_GROUP_T_SELECT 1 /* Select group */ +#define OFP_GROUP_T_INDIRECT 2 /* Indirect group */ +#define OFP_GROUP_T_FAST_FAILOVER 3 /* Fast failover group */ + +/* Special group identifiers */ +#define OFP_GROUP_ID_MAX 0xffffff00 /* Last usable group number */ +#define OFP_GROUP_ID_ALL 0xfffffffc /* Represents all groups for delete command */ +#define OFP_GROUP_ID_ANY 0xffffffff /* Special wildcard: no group specified */ + +struct ofp_bucket { + uint16_t b_len; + uint16_t b_weight; + uint32_t b_watch_port; + uint32_t b_watch_group; + uint8_t b_pad[4]; + struct ofp_action_header b_actions[0]; +} __packed; + +struct ofp_group_mod { + struct ofp_header gm_oh; + uint16_t gm_command; + uint8_t gm_type; + uint8_t gm_pad; + uint32_t gm_group_id; + struct ofp_bucket gm_buckets[0]; +} __packed; + +struct ofp_multipart { + struct ofp_header mp_oh; + uint16_t mp_type; + uint16_t mp_flags; + uint8_t mp_pad[4]; +} __packed; + +#define OFP_MP_FLAG_REQ_MORE 1 /* More requests to follow */ +#define OFP_MP_FLAG_REPLY_MORE 1 /* More replies to follow */ + +/* Multipart types */ +#define OFP_MP_T_DESC 0 /* Description of the switch */ +#define OFP_MP_T_FLOW 1 /* Individual flow statistics */ +#define OFP_MP_T_AGGREGATE 2 /* Aggregate flow statistics */ +#define OFP_MP_T_TABLE 3 /* Flow table statistics */ +#define OFP_MP_T_PORT_STATS 4 /* Port statistics */ +#define OFP_MP_T_QUEUE 5 /* Queue statistics for a port */ +#define OFP_MP_T_GROUP 6 /* Group counter statistics */ +#define OFP_MP_T_GROUP_DESC 7 /* Group description */ +#define OFP_MP_T_GROUP_FEATURES 8 /* Group features */ +#define OFP_MP_T_METER 9 /* Meter statistics */ +#define OFP_MP_T_METER_CONFIG 10 /* Meter configuration */ +#define OFP_MP_T_METER_FEATURES 11 /* Meter features */ +#define OFP_MP_T_TABLE_FEATURES 12 /* Table features */ +#define OFP_MP_T_PORT_DESC 13 /* Port description */ +#define OFP_MP_T_EXPERIMENTER 0xffff /* Experimenter extension */ + +#define OFP_DESC_STR_LEN 256 +#define OFP_SERIAL_NUM_LEN 32 + +struct ofp_desc { + char d_mfr_desc[OFP_DESC_STR_LEN]; + char d_hw_desc[OFP_DESC_STR_LEN]; + char d_sw_desc[OFP_DESC_STR_LEN]; + char d_serial_num[OFP_SERIAL_NUM_LEN]; + char d_dp_desc[OFP_DESC_STR_LEN]; +} __packed; + +/* Flow stats request */ +struct ofp_flow_stats_request { + uint8_t fsr_table_id; + uint8_t fsr_pad[3]; + uint32_t fsr_out_port; + uint32_t fsr_out_group; + uint8_t fsr_pad2[4]; + uint64_t fsr_cookie; + uint64_t fsr_cookie_mask; + struct ofp_match fsr_match; +} __packed; + +/* Flow stats */ +struct ofp_flow_stats { + uint16_t fs_length; + uint8_t fs_table_id; + uint8_t fs_pad; + uint32_t fs_duration_sec; + uint32_t fs_duration_nsec; + uint16_t fs_priority; + uint16_t fs_idle_timeout; + uint16_t fs_hard_timeout; + uint16_t fs_flags; + uint8_t fs_pad2[4]; + uint64_t fs_cookie; + uint64_t fs_packet_count; + uint64_t fs_byte_count; + struct ofp_match fs_match; +} __packed; + +/* Aggregate flow stats request */ +struct ofp_aggregate_stats_request { + uint8_t asr_table_id; + uint8_t asr_pad[3]; + uint32_t asr_out_port; + uint32_t asr_out_group; + uint8_t asr_pad2[4]; + uint64_t asr_cookie; + uint64_t asr_cookie_mask; + struct ofp_match asr_match; +} __packed; + +struct ofp_aggregate_stats { + uint64_t as_packet_count; + uint64_t as_byte_count; + uint32_t as_flow_count; + uint8_t as_pad[4]; +} __packed; + +/* Special table id */ +#define OFP_TABLE_ID_MAX 0xfe /* Last usable table */ +#define OFP_TABLE_ID_ALL 0xff /* Wildcard table */ + +struct ofp_table_stats { + uint8_t ts_table_id; + uint8_t ts_pad[3]; + uint32_t ts_active_count; + uint64_t ts_lookup_count; + uint64_t ts_matched_count; +} __packed; + +/* Table features */ +#define OFP_TABLE_FEATPROP_INSTRUCTION 0 /* Instruction property */ +#define OFP_TABLE_FEATPROP_INSTRUCTION_MISS 1 /* Instruction for table-miss */ +#define OFP_TABLE_FEATPROP_NEXT_TABLES 2 /* Next table property */ +#define OFP_TABLE_FEATPROP_NEXT_TABLES_MISS 3 /* Next table for table-miss */ +#define OFP_TABLE_FEATPROP_WRITE_ACTIONS 4 /* Write actions property */ +#define OFP_TABLE_FEATPROP_WRITE_ACTIONS_MISS 5 /* Write actions for table-miss */ +#define OFP_TABLE_FEATPROP_APPLY_ACTIONS 6 /* Apply actions property */ +#define OFP_TABLE_FEATPROP_APPLY_ACTIONS_MISS 7 /* Apply actions for table-miss */ +#define OFP_TABLE_FEATPROP_MATCH 8 /* Match property */ +#define OFP_TABLE_FEATPROP_WILDCARDS 10 /* Wildcards property */ +#define OFP_TABLE_FEATPROP_WRITE_SETFIELD 12 /* Write set-field property */ +#define OFP_TABLE_FEATPROP_WRITE_SETFIELD_MISS 13 /* Write set-field for table-miss */ +#define OFP_TABLE_FEATPROP_APPLY_SETFIELD 14 /* Apply set-field property */ +#define OFP_TABLE_FEATPROP_APPLY_SETFIELD_MISS 15 /* Apply set-field for table-miss */ +#define OFP_TABLE_FEATPROP_EXPERIMENTER 0xfffe /* Experimenter property */ +#define OFP_TABLE_FEATPROP_EXPERIMENTER_MISS 0xffff /* Experimenter for table-miss */ + +#define OFP_TABLE_MAX_NAME_LEN 32 + +struct ofp_table_features { + uint16_t tf_length; + uint8_t tf_tableid; + uint8_t tf_pad[5]; + char tf_name[OFP_TABLE_MAX_NAME_LEN]; + uint64_t tf_metadata_match; + uint64_t tf_metadata_write; + uint32_t tf_config; + uint32_t tf_max_entries; +} __packed; + +struct ofp_table_feature_property { + uint16_t tp_type; + uint16_t tp_length; +} __packed; + +struct ofp_table_feature_property_instruction { + uint16_t tpi_type; + uint16_t tpi_length; + struct ofp_instruction tpi_instructions[0]; +} __packed; + +struct ofp_table_feature_property_next_tables { + uint16_t tpnt_type; + uint16_t tpnt_length; + uint8_t tpnt_tables[0]; +} __packed; + +struct ofp_table_feature_property_actions { + uint16_t tpa_type; + uint16_t tpa_length; + struct ofp_action_header tpa_actions[0]; +} __packed; + +struct ofp_table_feature_property_oxm { + uint16_t tpoxm_type; + uint16_t tpoxm_length; + uint32_t tpoxm_oxm[0]; +} __packed; + +struct ofp_table_feature_property_experimenter { + uint16_t tfpexp_type; + uint16_t tfpexp_length; + uint32_t tfpexp_experimenter; + uint32_t tfpexp_exp_type; + uint32_t tfpexp_experimenter_data[0]; +} __packed; + +struct ofp_port_stats { + uint32_t pt_port_no; + uint8_t pt_pad[4]; + uint64_t pt_rx_packets; + uint64_t pt_tx_packets; + uint64_t pt_rx_bytes; + uint64_t pt_tx_bytes; + uint64_t pt_rx_dropped; + uint64_t pt_tx_dropped; + uint64_t pt_rx_errors; + uint64_t pt_tx_errors; + uint64_t pt_rx_frame_err; + uint64_t pt_rx_over_err; + uint64_t pt_rx_crc_err; + uint64_t pt_collision; + uint32_t pt_duration_sec; + uint32_t pt_duration_nsec; +} __packed; + +/* Groups stats request */ +struct ofp_group_stats_request { + uint32_t gsr_group_id; + uint8_t gsr_pad[4]; +} __packed; + +struct ofp_bucket_counter { + uint64_t gs_packet_count; + uint64_t gs_byte_count; +} __packed; + +/* Group stats */ +struct ofp_group_stats { + uint16_t gs_length; + uint8_t gs_pad[2]; + uint32_t gs_group_id; + uint32_t gs_ref_count; + uint8_t gs_pad2[4]; + uint64_t gs_packet_count; + uint64_t gs_byte_count; + uint32_t gs_duration_sec; + uint32_t gs_duration_nsec; + struct ofp_bucket_counter gs_bucket_stats[0]; +} __packed; + +/* Group description */ +struct ofp_group_desc { + uint16_t gd_length; + uint8_t gd_type; + uint8_t gd_pad; + uint32_t gd_group_id; + struct ofp_bucket gd_buckets[0]; +} __packed; + +/* + * Implementation-specific definitions that are not part of the spec + */ + +/* OpenFlow finite state machine */ +enum ofp_state { + OFP_STATE_CLOSED, + OFP_STATE_HELLO_WAIT, + OFP_STATE_FEATURE_WAIT, + OFP_STATE_ESTABLISHED +}; + +/* Used by the bpf for DLT_OPENFLOW */ +struct dlt_openflow_hdr { + uint32_t of_direction; + uint64_t of_datapath_id; +} __packed; + +#define DLT_OPENFLOW_TO_SWITCH 1 +#define DLT_OPENFLOW_TO_CONTROLLER 2 + +#endif /* _NET_OFP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/pfkeyv2.h b/lib/libc/include/generic-openbsd/net/pfkeyv2.h new file mode 100644 index 000000000000..5934ba742fa7 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/pfkeyv2.h @@ -0,0 +1,473 @@ +/* $OpenBSD: pfkeyv2.h,v 1.95 2024/05/13 01:15:53 jsg Exp $ */ +/* + * @(#)COPYRIGHT 1.1 (NRL) January 1998 + * + * NRL grants permission for redistribution and use in source and binary + * forms, with or without modification, of the software and documentation + * created at NRL provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgements: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * This product includes software developed at the Information + * Technology Division, US Naval Research Laboratory. + * 4. Neither the name of the NRL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL 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 NRL 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. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the US Naval + * Research Laboratory (NRL). + */ + +#ifndef _NET_PFKEY_V2_H_ +#define _NET_PFKEY_V2_H_ + +#define PF_KEY_V2 2 +#define PFKEYV2_REVISION 199806L + +/* This should be updated whenever the API is altered. */ +#define _OPENBSD_IPSEC_API_VERSION 2 + +#define SADB_RESERVED 0 +#define SADB_GETSPI 1 +#define SADB_UPDATE 2 +#define SADB_ADD 3 +#define SADB_DELETE 4 +#define SADB_GET 5 +#define SADB_ACQUIRE 6 +#define SADB_REGISTER 7 +#define SADB_EXPIRE 8 +#define SADB_FLUSH 9 +#define SADB_DUMP 10 +#define SADB_X_PROMISC 11 +#define SADB_X_ADDFLOW 12 +#define SADB_X_DELFLOW 13 +#define SADB_X_GRPSPIS 14 +#define SADB_X_ASKPOLICY 15 +#define SADB_X_SPDDUMP 16 +#define SADB_MAX 16 + +struct sadb_msg { + uint8_t sadb_msg_version; + uint8_t sadb_msg_type; + uint8_t sadb_msg_errno; + uint8_t sadb_msg_satype; + uint16_t sadb_msg_len; + uint16_t sadb_msg_reserved; + uint32_t sadb_msg_seq; + uint32_t sadb_msg_pid; +}; + +struct sadb_ext { + uint16_t sadb_ext_len; + uint16_t sadb_ext_type; +}; + +struct sadb_sa { + uint16_t sadb_sa_len; + uint16_t sadb_sa_exttype; + uint32_t sadb_sa_spi; + uint8_t sadb_sa_replay; + uint8_t sadb_sa_state; + uint8_t sadb_sa_auth; + uint8_t sadb_sa_encrypt; + uint32_t sadb_sa_flags; +}; + +struct sadb_lifetime { + uint16_t sadb_lifetime_len; + uint16_t sadb_lifetime_exttype; + uint32_t sadb_lifetime_allocations; + uint64_t sadb_lifetime_bytes; + uint64_t sadb_lifetime_addtime; + uint64_t sadb_lifetime_usetime; +}; + +struct sadb_address { + uint16_t sadb_address_len; + uint16_t sadb_address_exttype; + uint32_t sadb_address_reserved; +}; + +struct sadb_key { + uint16_t sadb_key_len; + uint16_t sadb_key_exttype; + uint16_t sadb_key_bits; + uint16_t sadb_key_reserved; +}; + +struct sadb_ident { + uint16_t sadb_ident_len; + uint16_t sadb_ident_exttype; + uint16_t sadb_ident_type; + uint16_t sadb_ident_reserved; + uint64_t sadb_ident_id; +}; + +struct sadb_sens { + uint16_t sadb_sens_len; + uint16_t sadb_sens_exttype; + uint32_t sadb_sens_dpd; + uint8_t sadb_sens_sens_level; + uint8_t sadb_sens_sens_len; + uint8_t sadb_sens_integ_level; + uint8_t sadb_sens_integ_len; + uint32_t sadb_sens_reserved; +}; + +struct sadb_prop { + uint16_t sadb_prop_len; + uint16_t sadb_prop_exttype; + uint8_t sadb_prop_num; + uint8_t sadb_prop_replay; + uint16_t sadb_prop_reserved; +}; + +struct sadb_comb { + uint8_t sadb_comb_auth; + uint8_t sadb_comb_encrypt; + uint16_t sadb_comb_flags; + uint16_t sadb_comb_auth_minbits; + uint16_t sadb_comb_auth_maxbits; + uint16_t sadb_comb_encrypt_minbits; + uint16_t sadb_comb_encrypt_maxbits; + uint32_t sadb_comb_reserved; + uint32_t sadb_comb_soft_allocations; + uint32_t sadb_comb_hard_allocations; + uint64_t sadb_comb_soft_bytes; + uint64_t sadb_comb_hard_bytes; + uint64_t sadb_comb_soft_addtime; + uint64_t sadb_comb_hard_addtime; + uint64_t sadb_comb_soft_usetime; + uint64_t sadb_comb_hard_usetime; +}; + +struct sadb_supported { + uint16_t sadb_supported_len; + uint16_t sadb_supported_exttype; + uint32_t sadb_supported_reserved; +}; + +struct sadb_alg { + uint8_t sadb_alg_id; + uint8_t sadb_alg_ivlen; + uint16_t sadb_alg_minbits; + uint16_t sadb_alg_maxbits; + uint16_t sadb_alg_reserved; +}; + +struct sadb_spirange { + uint16_t sadb_spirange_len; + uint16_t sadb_spirange_exttype; + uint32_t sadb_spirange_min; + uint32_t sadb_spirange_max; + uint32_t sadb_spirange_reserved; +}; + +struct sadb_protocol { + uint16_t sadb_protocol_len; + uint16_t sadb_protocol_exttype; + uint8_t sadb_protocol_proto; + uint8_t sadb_protocol_direction; + uint8_t sadb_protocol_flags; + uint8_t sadb_protocol_reserved2; +}; + +struct sadb_x_policy { + uint16_t sadb_x_policy_len; + uint16_t sadb_x_policy_exttype; + uint32_t sadb_x_policy_seq; +}; + +struct sadb_x_udpencap { + uint16_t sadb_x_udpencap_len; + uint16_t sadb_x_udpencap_exttype; + uint16_t sadb_x_udpencap_port; + uint16_t sadb_x_udpencap_reserved; +}; + +struct sadb_x_tag { + uint16_t sadb_x_tag_len; + uint16_t sadb_x_tag_exttype; + uint32_t sadb_x_tag_taglen; +}; + +struct sadb_x_replay { + uint16_t sadb_x_replay_len; + uint16_t sadb_x_replay_exttype; + uint32_t sadb_x_replay_reserved; + uint64_t sadb_x_replay_count; +}; + +struct sadb_x_rdomain { + uint16_t sadb_x_rdomain_len; + uint16_t sadb_x_rdomain_exttype; + uint16_t sadb_x_rdomain_dom1; + uint16_t sadb_x_rdomain_dom2; +}; + +struct sadb_x_tap { + uint16_t sadb_x_tap_len; + uint16_t sadb_x_tap_exttype; + uint32_t sadb_x_tap_unit; +}; + +struct sadb_x_counter { + uint16_t sadb_x_counter_len; + uint16_t sadb_x_counter_exttype; + uint32_t sadb_x_counter_pad; + uint64_t sadb_x_counter_ipackets; /* Input IPsec packets */ + uint64_t sadb_x_counter_opackets; /* Output IPsec packets */ + uint64_t sadb_x_counter_ibytes; /* Input bytes */ + uint64_t sadb_x_counter_obytes; /* Output bytes */ + uint64_t sadb_x_counter_idrops; /* Dropped on input */ + uint64_t sadb_x_counter_odrops; /* Dropped on output */ + uint64_t sadb_x_counter_idecompbytes; /* Input bytes, decompressed */ + uint64_t sadb_x_counter_ouncompbytes; /* Output bytes, uncompressed */ +}; + +struct sadb_x_mtu { + uint16_t sadb_x_mtu_len; + uint16_t sadb_x_mtu_exttype; + uint32_t sadb_x_mtu_mtu; +}; + +struct sadb_x_iface { + uint16_t sadb_x_iface_len; + uint16_t sadb_x_iface_exttype; + uint32_t sadb_x_iface_unit; + uint8_t sadb_x_iface_direction; + uint8_t sadb_x_iface_reserved[7]; +}; + +#ifdef _KERNEL +#define SADB_X_GETSPROTO(x) \ + ( (x) == SADB_SATYPE_AH ? IPPROTO_AH :\ + (x) == SADB_SATYPE_ESP ? IPPROTO_ESP :\ + (x) == SADB_X_SATYPE_TCPSIGNATURE ? IPPROTO_TCP :\ + (x) == SADB_X_SATYPE_IPCOMP ? IPPROTO_IPCOMP: IPPROTO_IPIP ) +#endif + +#define SADB_EXT_RESERVED 0 +#define SADB_EXT_SA 1 +#define SADB_EXT_LIFETIME_CURRENT 2 +#define SADB_EXT_LIFETIME_HARD 3 +#define SADB_EXT_LIFETIME_SOFT 4 +#define SADB_EXT_ADDRESS_SRC 5 +#define SADB_EXT_ADDRESS_DST 6 +#define SADB_EXT_ADDRESS_PROXY 7 +#define SADB_EXT_KEY_AUTH 8 +#define SADB_EXT_KEY_ENCRYPT 9 +#define SADB_EXT_IDENTITY_SRC 10 +#define SADB_EXT_IDENTITY_DST 11 +#define SADB_EXT_SENSITIVITY 12 +#define SADB_EXT_PROPOSAL 13 +#define SADB_EXT_SUPPORTED_AUTH 14 +#define SADB_EXT_SUPPORTED_ENCRYPT 15 +#define SADB_EXT_SPIRANGE 16 +#define SADB_X_EXT_SRC_MASK 17 +#define SADB_X_EXT_DST_MASK 18 +#define SADB_X_EXT_PROTOCOL 19 +#define SADB_X_EXT_FLOW_TYPE 20 +#define SADB_X_EXT_SRC_FLOW 21 +#define SADB_X_EXT_DST_FLOW 22 +#define SADB_X_EXT_SA2 23 +#define SADB_X_EXT_DST2 24 +#define SADB_X_EXT_POLICY 25 +#define SADB_X_EXT_LOCAL_CREDENTIALS 26 +#define SADB_X_EXT_REMOTE_CREDENTIALS 27 +#define SADB_X_EXT_LOCAL_AUTH 28 +#define SADB_X_EXT_REMOTE_AUTH 29 +#define SADB_X_EXT_SUPPORTED_COMP 30 +#define SADB_X_EXT_UDPENCAP 31 +#define SADB_X_EXT_LIFETIME_LASTUSE 32 +#define SADB_X_EXT_TAG 33 +#define SADB_X_EXT_TAP 34 +#define SADB_X_EXT_SATYPE2 35 +#define SADB_X_EXT_COUNTER 36 +#define SADB_X_EXT_RDOMAIN 37 +#define SADB_X_EXT_MTU 38 +#define SADB_X_EXT_REPLAY 39 +#define SADB_X_EXT_IFACE 40 +#define SADB_EXT_MAX 40 + +/* Fix pfkeyv2.c struct pfkeyv2_socket if SATYPE_MAX > 31 */ +#define SADB_SATYPE_UNSPEC 0 +#define SADB_SATYPE_AH 1 +#define SADB_SATYPE_ESP 2 +#define SADB_SATYPE_RSVP 3 +#define SADB_SATYPE_OSPFV2 4 +#define SADB_SATYPE_RIPV2 5 +#define SADB_SATYPE_MIP 6 +#define SADB_X_SATYPE_IPIP 7 +#define SADB_X_SATYPE_TCPSIGNATURE 8 +#define SADB_X_SATYPE_IPCOMP 9 +#define SADB_SATYPE_MAX 9 + +#define SADB_SASTATE_LARVAL 0 +#define SADB_SASTATE_MATURE 1 +#define SADB_SASTATE_DYING 2 +#define SADB_SASTATE_DEAD 3 +#define SADB_SASTATE_MAX 3 + +#define SADB_AALG_NONE 0 +#define SADB_AALG_MD5HMAC 2 +#define SADB_AALG_SHA1HMAC 3 +#define SADB_X_AALG_SHA2_256 5 +#define SADB_X_AALG_SHA2_384 6 +#define SADB_X_AALG_SHA2_512 7 +#define SADB_X_AALG_RIPEMD160HMAC 8 +#define SADB_X_AALG_AES128GMAC 9 +#define SADB_X_AALG_AES192GMAC 10 +#define SADB_X_AALG_AES256GMAC 11 +#define SADB_X_AALG_CHACHA20POLY1305 12 +#define SADB_AALG_MAX 12 + +#define SADB_EALG_NONE 0 +#define SADB_EALG_3DESCBC 3 +#define SADB_X_EALG_CAST 6 +#define SADB_X_EALG_BLF 7 +#define SADB_EALG_NULL 11 +#define SADB_X_EALG_AES 12 +#define SADB_X_EALG_AESCTR 13 +#define SADB_X_EALG_AESGCM8 18 +#define SADB_X_EALG_AESGCM12 19 +#define SADB_X_EALG_AESGCM16 20 +#define SADB_X_EALG_AESGMAC 21 +#define SADB_X_EALG_CHACHA20POLY1305 22 +#define SADB_EALG_MAX 22 + +#define SADB_X_CALG_NONE 0 +#define SADB_X_CALG_OUI 1 +#define SADB_X_CALG_DEFLATE 2 +#define SADB_X_CALG_MAX 2 + +#define SADB_SAFLAGS_PFS 0x001 /* perfect forward secrecy */ +#define SADB_X_SAFLAGS_TUNNEL 0x004 /* Force tunneling */ +#define SADB_X_SAFLAGS_CHAINDEL 0x008 /* Delete whole SA chain */ +#define SADB_X_SAFLAGS_UDPENCAP 0x200 /* ESP in UDP */ +#define SADB_X_SAFLAGS_ESN 0x400 /* Extended Sequence Number */ + +#define SADB_X_POLICYFLAGS_POLICY 0x0001 /* This is a static policy */ + +#define SADB_IDENTTYPE_RESERVED 0 +#define SADB_IDENTTYPE_PREFIX 1 +#define SADB_IDENTTYPE_FQDN 2 +#define SADB_IDENTTYPE_USERFQDN 3 +#define SADB_IDENTTYPE_ASN1_DN 4 +#define SADB_IDENTTYPE_MAX 4 + +#define SADB_KEY_FLAGS_MAX 0 + +#ifdef _KERNEL +#define PFKEYV2_LIFETIME_HARD 0 +#define PFKEYV2_LIFETIME_SOFT 1 +#define PFKEYV2_LIFETIME_CURRENT 2 +#define PFKEYV2_LIFETIME_LASTUSE 3 + +#define PFKEYV2_IDENTITY_SRC 0 +#define PFKEYV2_IDENTITY_DST 1 + +#define PFKEYV2_ENCRYPTION_KEY 0 +#define PFKEYV2_AUTHENTICATION_KEY 1 + +#define PFKEYV2_SOCKETFLAGS_REGISTERED 1 +#define PFKEYV2_SOCKETFLAGS_PROMISC 2 + +#define PFKEYV2_SENDMESSAGE_UNICAST 1 +#define PFKEYV2_SENDMESSAGE_REGISTERED 2 +#define PFKEYV2_SENDMESSAGE_BROADCAST 3 +#endif /* _KERNEL */ + +#define SADB_X_FLOW_TYPE_USE 1 +#define SADB_X_FLOW_TYPE_ACQUIRE 2 +#define SADB_X_FLOW_TYPE_REQUIRE 3 +#define SADB_X_FLOW_TYPE_BYPASS 4 +#define SADB_X_FLOW_TYPE_DENY 5 +#define SADB_X_FLOW_TYPE_DONTACQ 6 + +#ifdef _KERNEL +struct tdb; +struct socket; +struct mbuf; + +#define EXTLEN(x) (((struct sadb_ext *)(x))->sadb_ext_len * sizeof(uint64_t)) +#define PADUP(x) (((x) + sizeof(uint64_t) - 1) & ~(sizeof(uint64_t) - 1)) + +int pfkeyv2_parsemessage(void *, int, void **); +int pfkeyv2_expire(struct tdb *, u_int16_t); +int pfkeyv2_acquire(struct ipsec_policy *, union sockaddr_union *, + union sockaddr_union *, u_int32_t *, struct sockaddr_encap *); + +int pfkeyv2_get(struct tdb *, void **, void **, int *, int *); +int pfkeyv2_policy(struct ipsec_acquire *, void **, void **, int *); +int pfkeyv2_dosend(struct socket *, void *, int); +int pfkeyv2_sendmessage(void **, int, struct socket *, u_int8_t, int, u_int); +int pfkeyv2_dump_policy(struct ipsec_policy *, void **, void **, int *); +int pfkeyv2_dump_walker(struct tdb *, void *, int); +int pfkeyv2_get_proto_alg(u_int8_t, u_int8_t *, int *); +int pfkeyv2_sysctl(int *, u_int, void *, size_t *, void *, size_t); +int pfkeyv2_sysctl_walker(struct tdb *, void *, int); + +int pfdatatopacket(void *, int, struct mbuf **); + +void export_address(void **, struct sockaddr *); +void export_identities(void **, struct ipsec_ids *, int, void **); +void export_lifetime(void **, struct tdb *, int); +void export_sa(void **, struct tdb *); +void export_flow(void **, u_int8_t, struct sockaddr_encap *, + struct sockaddr_encap *, void **); +void export_key(void **, struct tdb *, int); +void export_udpencap(void **, struct tdb *); +void export_tag(void **, struct tdb *); +void export_replay(void **, struct tdb *); +void export_rdomain(void **, struct tdb *); +void export_mtu(void **, struct tdb *); +void export_tap(void **, struct tdb *); +void export_satype(void **, struct tdb *); +void export_counter(void **, struct tdb *); +void export_iface(void **, struct tdb *); + +void import_address(struct sockaddr *, struct sadb_address *); +void import_identities(struct ipsec_ids **, int, struct sadb_ident *, + struct sadb_ident *); +void import_key(struct ipsecinit *, struct sadb_key *, int); +void import_lifetime(struct tdb *, struct sadb_lifetime *, int); +void import_sa(struct tdb *, struct sadb_sa *, struct ipsecinit *); +int import_flow(struct sockaddr_encap *, struct sockaddr_encap *, + struct sadb_address *, struct sadb_address *, struct sadb_address *, + struct sadb_address *, struct sadb_protocol *, struct sadb_protocol *); +void import_udpencap(struct tdb *, struct sadb_x_udpencap *); +void import_tag(struct tdb *, struct sadb_x_tag *); +void import_rdomain(struct tdb *, struct sadb_x_rdomain *); +void import_tap(struct tdb *, struct sadb_x_tap *); +void import_iface(struct tdb *, struct sadb_x_iface *); + +extern const uint64_t sadb_exts_allowed_out[SADB_MAX+1]; +extern const uint64_t sadb_exts_required_out[SADB_MAX+1]; + +extern struct pool ipsec_policy_pool; +extern struct pool ipsec_acquire_pool; +#endif /* _KERNEL */ + +#endif /* _NET_PFKEY_V2_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/pfvar.h b/lib/libc/include/generic-openbsd/net/pfvar.h new file mode 100644 index 000000000000..96654afc9d5d --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/pfvar.h @@ -0,0 +1,1883 @@ +/* $OpenBSD: pfvar.h,v 1.543 2025/04/14 20:02:34 sf Exp $ */ + +/* + * Copyright (c) 2001 Daniel Hartmeier + * Copyright (c) 2002 - 2013 Henning Brauer + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDERS 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 _NET_PFVAR_H_ +#define _NET_PFVAR_H_ + +#include +#include +#include +#include +#include + +#include + +#include +#include + +struct ip; +struct ip6_hdr; +struct mbuf_list; + +#define PF_TCPS_PROXY_SRC ((TCP_NSTATES)+0) +#define PF_TCPS_PROXY_DST ((TCP_NSTATES)+1) + +#define PF_MD5_DIGEST_LENGTH 16 +#ifdef MD5_DIGEST_LENGTH +#if PF_MD5_DIGEST_LENGTH != MD5_DIGEST_LENGTH +#error md5 digest length mismatch +#endif +#endif + +typedef struct refcnt pf_refcnt_t; +#define PF_REF_INIT(_x) refcnt_init(&(_x)) +#define PF_REF_TAKE(_x) refcnt_take(&(_x)) +#define PF_REF_RELE(_x) refcnt_rele(&(_x)) + +enum { PF_INOUT, PF_IN, PF_OUT, PF_FWD }; +enum { PF_PASS, PF_DROP, PF_SCRUB, PF_NOSCRUB, PF_NAT, PF_NONAT, + PF_BINAT, PF_NOBINAT, PF_RDR, PF_NORDR, PF_SYNPROXY_DROP, PF_DEFER, + PF_MATCH, PF_DIVERT, PF_RT, PF_AFRT }; +enum { PF_TRANS_RULESET, PF_TRANS_TABLE }; +enum { PF_OP_NONE, PF_OP_IRG, PF_OP_EQ, PF_OP_NE, PF_OP_LT, + PF_OP_LE, PF_OP_GT, PF_OP_GE, PF_OP_XRG, PF_OP_RRG }; +enum { PF_CHANGE_NONE, PF_CHANGE_ADD_HEAD, PF_CHANGE_ADD_TAIL, + PF_CHANGE_ADD_BEFORE, PF_CHANGE_ADD_AFTER, + PF_CHANGE_REMOVE, PF_CHANGE_GET_TICKET }; +enum { PF_GET_NONE, PF_GET_CLR_CNTR }; +enum { PF_SK_WIRE, PF_SK_STACK, PF_SK_BOTH }; +enum { PF_PEER_SRC, PF_PEER_DST, PF_PEER_BOTH }; + +/* + * Note about PFTM_*: real indices into pf_rule.timeout[] come before + * PFTM_MAX, special cases afterwards. See pf_state_expires(). + */ +enum { PFTM_TCP_FIRST_PACKET, PFTM_TCP_OPENING, PFTM_TCP_ESTABLISHED, + PFTM_TCP_CLOSING, PFTM_TCP_FIN_WAIT, PFTM_TCP_CLOSED, + PFTM_UDP_FIRST_PACKET, PFTM_UDP_SINGLE, PFTM_UDP_MULTIPLE, + PFTM_ICMP_FIRST_PACKET, PFTM_ICMP_ERROR_REPLY, + PFTM_OTHER_FIRST_PACKET, PFTM_OTHER_SINGLE, + PFTM_OTHER_MULTIPLE, PFTM_FRAG, PFTM_INTERVAL, + PFTM_ADAPTIVE_START, PFTM_ADAPTIVE_END, PFTM_SRC_NODE, + PFTM_TS_DIFF, PFTM_MAX, PFTM_PURGE, PFTM_UNLINKED }; + +/* PFTM default values */ +#define PFTM_TCP_FIRST_PACKET_VAL 120 /* First TCP packet */ +#define PFTM_TCP_OPENING_VAL 30 /* No response yet */ +#define PFTM_TCP_ESTABLISHED_VAL 24*60*60/* Established */ +#define PFTM_TCP_CLOSING_VAL 15 * 60 /* Half closed */ +#define PFTM_TCP_FIN_WAIT_VAL 45 /* Got both FINs */ +#define PFTM_TCP_CLOSED_VAL 90 /* Got a RST */ +#define PFTM_UDP_FIRST_PACKET_VAL 60 /* First UDP packet */ +#define PFTM_UDP_SINGLE_VAL 30 /* Unidirectional */ +#define PFTM_UDP_MULTIPLE_VAL 60 /* Bidirectional */ +#define PFTM_ICMP_FIRST_PACKET_VAL 20 /* First ICMP packet */ +#define PFTM_ICMP_ERROR_REPLY_VAL 10 /* Got error response */ +#define PFTM_OTHER_FIRST_PACKET_VAL 60 /* First packet */ +#define PFTM_OTHER_SINGLE_VAL 30 /* Unidirectional */ +#define PFTM_OTHER_MULTIPLE_VAL 60 /* Bidirectional */ +#define PFTM_FRAG_VAL 60 /* Fragment expire */ +#define PFTM_INTERVAL_VAL 10 /* Expire interval */ +#define PFTM_SRC_NODE_VAL 0 /* Source tracking */ +#define PFTM_TS_DIFF_VAL 30 /* Allowed TS diff */ + +/* + * For each connection (combination of proto,src,dst,af) the number + * of fragments is limited. Over the PFTM_FRAG interval the average + * rate must be less than PF_FRAG_STALE fragments per second. + * Otherwise older fragments are considered stale and are dropped. + */ +#define PF_FRAG_STALE 200 + +/* + * Limit the length of the fragment queue traversal. Remember + * search entry points based on the fragment offset. + */ +#define PF_FRAG_ENTRY_POINTS 16 + +/* + * The number of entries in the fragment queue must be limited + * to avoid DoS by linear searching. Instead of a global limit, + * use a limit per entry point. For large packets these sum up. + */ +#define PF_FRAG_ENTRY_LIMIT 64 + +enum { PF_NOPFROUTE, PF_ROUTETO, PF_DUPTO, PF_REPLYTO }; +enum { PF_LIMIT_STATES, PF_LIMIT_SRC_NODES, PF_LIMIT_FRAGS, + PF_LIMIT_TABLES, PF_LIMIT_TABLE_ENTRIES, PF_LIMIT_PKTDELAY_PKTS, + PF_LIMIT_ANCHORS, PF_LIMIT_MAX }; +#define PF_POOL_IDMASK 0x0f +enum { PF_POOL_NONE, PF_POOL_BITMASK, PF_POOL_RANDOM, + PF_POOL_SRCHASH, PF_POOL_ROUNDROBIN, PF_POOL_LEASTSTATES }; +enum { PF_ADDR_ADDRMASK, PF_ADDR_NOROUTE, PF_ADDR_DYNIFTL, + PF_ADDR_TABLE, PF_ADDR_RTLABEL, PF_ADDR_URPFFAILED, + PF_ADDR_RANGE, PF_ADDR_NONE }; +#define PF_POOL_TYPEMASK 0x0f +#define PF_POOL_STICKYADDR 0x20 +#define PF_WSCALE_FLAG 0x80 +#define PF_WSCALE_MASK 0x0f + +#define PF_POOL_DYNTYPE(_o) \ + ((((_o) & PF_POOL_TYPEMASK) == PF_POOL_ROUNDROBIN) || \ + (((_o) & PF_POOL_TYPEMASK) == PF_POOL_LEASTSTATES) || \ + (((_o) & PF_POOL_TYPEMASK) == PF_POOL_RANDOM) || \ + (((_o) & PF_POOL_TYPEMASK) == PF_POOL_SRCHASH)) + +#define PF_LOG 0x01 +#define PF_LOG_ALL 0x02 +#define PF_LOG_USER 0x04 +#define PF_LOG_FORCE 0x08 +#define PF_LOG_MATCHES 0x10 + +struct pf_addr { + union { + struct in_addr v4; + struct in6_addr v6; + u_int8_t addr8[16]; + u_int16_t addr16[8]; + u_int32_t addr32[4]; + } pfa; /* 128-bit address */ +#define v4 pfa.v4 +#define v6 pfa.v6 +#define addr8 pfa.addr8 +#define addr16 pfa.addr16 +#define addr32 pfa.addr32 +}; + +#define PF_TABLE_NAME_SIZE 32 + +#define PFI_AFLAG_NETWORK 0x01 +#define PFI_AFLAG_BROADCAST 0x02 +#define PFI_AFLAG_PEER 0x04 +#define PFI_AFLAG_MODEMASK 0x07 +#define PFI_AFLAG_NOALIAS 0x08 + +struct pf_addr_wrap { + union { + struct { + struct pf_addr addr; + struct pf_addr mask; + } a; + char ifname[IFNAMSIZ]; + char tblname[PF_TABLE_NAME_SIZE]; + char rtlabelname[RTLABEL_LEN]; + u_int32_t rtlabel; + } v; + union { + struct pfi_dynaddr *dyn; + struct pfr_ktable *tbl; + int dyncnt; + int tblcnt; + } p; + u_int8_t type; /* PF_ADDR_* */ + u_int8_t iflags; /* PFI_AFLAG_* */ +}; + +#ifdef _KERNEL +struct pfi_dynaddr { + TAILQ_ENTRY(pfi_dynaddr) entry; + struct pf_addr pfid_addr4; + struct pf_addr pfid_mask4; + struct pf_addr pfid_addr6; + struct pf_addr pfid_mask6; + struct pfr_ktable *pfid_kt; + struct pfi_kif *pfid_kif; + void *pfid_hook_cookie; + int pfid_net; /* mask or 128 */ + int pfid_acnt4; /* address count IPv4 */ + int pfid_acnt6; /* address count IPv6 */ + sa_family_t pfid_af; /* rule af */ + u_int8_t pfid_iflags; /* PFI_AFLAG_* */ +}; +#endif /* _KERNEL */ + + +/* + * Logging macros + */ + +#ifndef PF_DEBUGNAME +#define PF_DEBUGNAME "pf: " +#endif + +#ifdef _KERNEL +#define DPFPRINTF(n, format, x...) \ + do { \ + if (pf_status.debug >= (n)) { \ + log(n, PF_DEBUGNAME); \ + addlog(format, ##x); \ + addlog("\n"); \ + } \ + } while (0) +#else +#ifdef PFDEBUG +#define DPFPRINTF(n, format, x...) \ + do { \ + fprintf(stderr, format, ##x); \ + fprintf(stderr, "\n"); \ + } while (0) +#else +#define DPFPRINTF(n, format, x...) ((void)0) +#endif /* PFDEBUG */ +#endif /* _KERNEL */ + + +/* + * Address manipulation macros + */ + +#define PF_AEQ(a, b, c) \ + ((c == AF_INET && (a)->addr32[0] == (b)->addr32[0]) || \ + (c == AF_INET6 && \ + (a)->addr32[3] == (b)->addr32[3] && \ + (a)->addr32[2] == (b)->addr32[2] && \ + (a)->addr32[1] == (b)->addr32[1] && \ + (a)->addr32[0] == (b)->addr32[0])) \ + +#define PF_ANEQ(a, b, c) \ + ((c == AF_INET && (a)->addr32[0] != (b)->addr32[0]) || \ + (c == AF_INET6 && \ + ((a)->addr32[3] != (b)->addr32[3] || \ + (a)->addr32[2] != (b)->addr32[2] || \ + (a)->addr32[1] != (b)->addr32[1] || \ + (a)->addr32[0] != (b)->addr32[0]))) \ + +#define PF_AZERO(a, c) \ + ((c == AF_INET && !(a)->addr32[0]) || \ + (c == AF_INET6 && \ + !(a)->addr32[0] && !(a)->addr32[1] && \ + !(a)->addr32[2] && !(a)->addr32[3] )) \ + +#define PF_MISMATCHAW(aw, x, af, neg, ifp, rtid) \ + ( \ + (((aw)->type == PF_ADDR_NOROUTE && \ + pf_routable((x), (af), NULL, (rtid))) || \ + (((aw)->type == PF_ADDR_URPFFAILED && (ifp) != NULL && \ + pf_routable((x), (af), (ifp), (rtid))) || \ + ((aw)->type == PF_ADDR_RTLABEL && \ + !pf_rtlabel_match((x), (af), (aw), (rtid))) || \ + ((aw)->type == PF_ADDR_TABLE && \ + !pfr_match_addr((aw)->p.tbl, (x), (af))) || \ + ((aw)->type == PF_ADDR_DYNIFTL && \ + !pfi_match_addr((aw)->p.dyn, (x), (af))) || \ + ((aw)->type == PF_ADDR_RANGE && \ + !pf_match_addr_range(&(aw)->v.a.addr, \ + &(aw)->v.a.mask, (x), (af))) || \ + ((aw)->type == PF_ADDR_ADDRMASK && \ + !PF_AZERO(&(aw)->v.a.mask, (af)) && \ + !pf_match_addr(0, &(aw)->v.a.addr, \ + &(aw)->v.a.mask, (x), (af))))) != \ + (neg) \ + ) + +struct pf_rule_uid { + uid_t uid[2]; + u_int8_t op; +}; + +struct pf_rule_gid { + uid_t gid[2]; + u_int8_t op; +}; + +struct pf_rule_addr { + struct pf_addr_wrap addr; + u_int16_t port[2]; + u_int8_t neg; + u_int8_t port_op; + u_int16_t weight; +}; + +struct pf_threshold { + u_int32_t limit; +#define PF_THRESHOLD_MULT 1000 +#define PF_THRESHOLD_MAX 0xffffffff / PF_THRESHOLD_MULT + u_int32_t seconds; + u_int32_t count; + u_int32_t last; +}; + +struct pf_poolhashkey { + union { + u_int8_t key8[16]; + u_int16_t key16[8]; + u_int32_t key32[4]; + } pfk; /* 128-bit hash key */ +#define key8 pfk.key8 +#define key16 pfk.key16 +#define key32 pfk.key32 +}; + +struct pf_pool { + struct pf_addr_wrap addr; + struct pf_poolhashkey key; + struct pf_addr counter; + char ifname[IFNAMSIZ]; + struct pfi_kif *kif; + int tblidx; + u_int64_t states; + int curweight; + u_int16_t weight; + u_int16_t proxy_port[2]; + u_int8_t port_op; + u_int8_t opts; +}; + +/* A packed Operating System description for fingerprinting */ +typedef u_int32_t pf_osfp_t; +#define PF_OSFP_ANY ((pf_osfp_t)0) +#define PF_OSFP_UNKNOWN ((pf_osfp_t)-1) +#define PF_OSFP_NOMATCH ((pf_osfp_t)-2) + +struct pf_osfp_entry { + SLIST_ENTRY(pf_osfp_entry) fp_entry; + pf_osfp_t fp_os; + int fp_enflags; +#define PF_OSFP_EXPANDED 0x001 /* expanded entry */ +#define PF_OSFP_GENERIC 0x002 /* generic signature */ +#define PF_OSFP_NODETAIL 0x004 /* no p0f details */ +#define PF_OSFP_LEN 32 + u_char fp_class_nm[PF_OSFP_LEN]; + u_char fp_version_nm[PF_OSFP_LEN]; + u_char fp_subtype_nm[PF_OSFP_LEN]; +}; +#define PF_OSFP_ENTRY_EQ(a, b) \ + ((a)->fp_os == (b)->fp_os && \ + memcmp((a)->fp_class_nm, (b)->fp_class_nm, PF_OSFP_LEN) == 0 && \ + memcmp((a)->fp_version_nm, (b)->fp_version_nm, PF_OSFP_LEN) == 0 && \ + memcmp((a)->fp_subtype_nm, (b)->fp_subtype_nm, PF_OSFP_LEN) == 0) + +/* handle pf_osfp_t packing */ +#define _FP_RESERVED_BIT 1 /* For the special negative #defines */ +#define _FP_UNUSED_BITS 1 +#define _FP_CLASS_BITS 10 /* OS Class (Windows, Linux) */ +#define _FP_VERSION_BITS 10 /* OS version (95, 98, NT, 2.4.54, 3.2) */ +#define _FP_SUBTYPE_BITS 10 /* patch level (NT SP4, SP3, ECN patch) */ +#define PF_OSFP_UNPACK(osfp, class, version, subtype) do { \ + (class) = ((osfp) >> (_FP_VERSION_BITS+_FP_SUBTYPE_BITS)) & \ + ((1 << _FP_CLASS_BITS) - 1); \ + (version) = ((osfp) >> _FP_SUBTYPE_BITS) & \ + ((1 << _FP_VERSION_BITS) - 1);\ + (subtype) = (osfp) & ((1 << _FP_SUBTYPE_BITS) - 1); \ +} while(0) +#define PF_OSFP_PACK(osfp, class, version, subtype) do { \ + (osfp) = ((class) & ((1 << _FP_CLASS_BITS) - 1)) << (_FP_VERSION_BITS \ + + _FP_SUBTYPE_BITS); \ + (osfp) |= ((version) & ((1 << _FP_VERSION_BITS) - 1)) << \ + _FP_SUBTYPE_BITS; \ + (osfp) |= (subtype) & ((1 << _FP_SUBTYPE_BITS) - 1); \ +} while(0) + +/* the fingerprint of an OSes TCP SYN packet */ +typedef u_int64_t pf_tcpopts_t; +struct pf_os_fingerprint { + SLIST_HEAD(pf_osfp_enlist, pf_osfp_entry) fp_oses; /* list of matches */ + pf_tcpopts_t fp_tcpopts; /* packed TCP options */ + u_int16_t fp_wsize; /* TCP window size */ + u_int16_t fp_psize; /* ip->ip_len */ + u_int16_t fp_mss; /* TCP MSS */ + u_int16_t fp_flags; +#define PF_OSFP_WSIZE_MOD 0x0001 /* Window modulus */ +#define PF_OSFP_WSIZE_DC 0x0002 /* Window don't care */ +#define PF_OSFP_WSIZE_MSS 0x0004 /* Window multiple of MSS */ +#define PF_OSFP_WSIZE_MTU 0x0008 /* Window multiple of MTU */ +#define PF_OSFP_PSIZE_MOD 0x0010 /* packet size modulus */ +#define PF_OSFP_PSIZE_DC 0x0020 /* packet size don't care */ +#define PF_OSFP_WSCALE 0x0040 /* TCP window scaling */ +#define PF_OSFP_WSCALE_MOD 0x0080 /* TCP window scale modulus */ +#define PF_OSFP_WSCALE_DC 0x0100 /* TCP window scale dont-care */ +#define PF_OSFP_MSS 0x0200 /* TCP MSS */ +#define PF_OSFP_MSS_MOD 0x0400 /* TCP MSS modulus */ +#define PF_OSFP_MSS_DC 0x0800 /* TCP MSS dont-care */ +#define PF_OSFP_DF 0x1000 /* IPv4 don't fragment bit */ +#define PF_OSFP_TS0 0x2000 /* Zero timestamp */ +#define PF_OSFP_INET6 0x4000 /* IPv6 */ + u_int8_t fp_optcnt; /* TCP option count */ + u_int8_t fp_wscale; /* TCP window scaling */ + u_int8_t fp_ttl; /* IPv4 TTL */ +#define PF_OSFP_MAXTTL_OFFSET 40 +/* TCP options packing */ +#define PF_OSFP_TCPOPT_NOP 0x0 /* TCP NOP option */ +#define PF_OSFP_TCPOPT_WSCALE 0x1 /* TCP window scaling option */ +#define PF_OSFP_TCPOPT_MSS 0x2 /* TCP max segment size opt */ +#define PF_OSFP_TCPOPT_SACK 0x3 /* TCP SACK OK option */ +#define PF_OSFP_TCPOPT_TS 0x4 /* TCP timestamp option */ +#define PF_OSFP_TCPOPT_BITS 3 /* bits used by each option */ +#define PF_OSFP_MAX_OPTS \ + (sizeof(((struct pf_os_fingerprint *)0)->fp_tcpopts) * 8) \ + / PF_OSFP_TCPOPT_BITS + + SLIST_ENTRY(pf_os_fingerprint) fp_next; +}; + +struct pf_osfp_ioctl { + struct pf_osfp_entry fp_os; + pf_tcpopts_t fp_tcpopts; /* packed TCP options */ + u_int16_t fp_wsize; /* TCP window size */ + u_int16_t fp_psize; /* ip->ip_len */ + u_int16_t fp_mss; /* TCP MSS */ + u_int16_t fp_flags; + u_int8_t fp_optcnt; /* TCP option count */ + u_int8_t fp_wscale; /* TCP window scaling */ + u_int8_t fp_ttl; /* IPv4 TTL */ + + int fp_getnum; /* DIOCOSFPGET number */ +}; + +struct pf_rule_actions { + int rtableid; + u_int16_t qid; + u_int16_t pqid; + u_int16_t max_mss; + u_int16_t flags; + u_int16_t delay; + u_int8_t log; + u_int8_t set_tos; + u_int8_t min_ttl; + u_int8_t set_prio[2]; + u_int8_t pad[1]; +}; + +union pf_rule_ptr { + struct pf_rule *ptr; + u_int32_t nr; +}; + +#define PF_ANCHOR_STACK_MAX 64 +#define PF_ANCHOR_NAME_SIZE 64 +#define PF_ANCHOR_MAXPATH (PATH_MAX - PF_ANCHOR_NAME_SIZE - 1) +#define PF_ANCHOR_HIWAT 512 +#define PF_OPTIMIZER_TABLE_PFX "__automatic_" + +struct pf_rule { + struct pf_rule_addr src; + struct pf_rule_addr dst; +#define PF_SKIP_IFP 0 +#define PF_SKIP_DIR 1 +#define PF_SKIP_RDOM 2 +#define PF_SKIP_AF 3 +#define PF_SKIP_PROTO 4 +#define PF_SKIP_SRC_ADDR 5 +#define PF_SKIP_DST_ADDR 6 +#define PF_SKIP_SRC_PORT 7 +#define PF_SKIP_DST_PORT 8 +#define PF_SKIP_COUNT 9 + union pf_rule_ptr skip[PF_SKIP_COUNT]; +#define PF_RULE_LABEL_SIZE 64 + char label[PF_RULE_LABEL_SIZE]; +#define PF_QNAME_SIZE 64 + char ifname[IFNAMSIZ]; + char rcv_ifname[IFNAMSIZ]; + char qname[PF_QNAME_SIZE]; + char pqname[PF_QNAME_SIZE]; +#define PF_TAG_NAME_SIZE 64 + char tagname[PF_TAG_NAME_SIZE]; + char match_tagname[PF_TAG_NAME_SIZE]; + + char overload_tblname[PF_TABLE_NAME_SIZE]; + + TAILQ_ENTRY(pf_rule) entries; + struct pf_pool nat; + struct pf_pool rdr; + struct pf_pool route; + struct pf_threshold pktrate; + + u_int64_t evaluations; + u_int64_t packets[2]; + u_int64_t bytes[2]; + + struct pfi_kif *kif; + struct pfi_kif *rcv_kif; + struct pf_anchor *anchor; + struct pfr_ktable *overload_tbl; + + pf_osfp_t os_fingerprint; + + int rtableid; + int onrdomain; + u_int32_t timeout[PFTM_MAX]; + u_int32_t states_cur; + u_int32_t states_tot; + u_int32_t max_states; + u_int32_t src_nodes; + u_int32_t max_src_nodes; + u_int32_t max_src_states; + u_int32_t max_src_conn; + struct { + u_int32_t limit; + u_int32_t seconds; + } max_src_conn_rate; + u_int32_t qid; + u_int32_t pqid; + u_int32_t rt_listid; + u_int32_t nr; + u_int32_t prob; + uid_t cuid; + pid_t cpid; + + u_int16_t return_icmp; + u_int16_t return_icmp6; + u_int16_t max_mss; + u_int16_t tag; + u_int16_t match_tag; + u_int16_t scrub_flags; + u_int16_t delay; + + struct pf_rule_uid uid; + struct pf_rule_gid gid; + + u_int32_t rule_flag; + u_int8_t action; + u_int8_t direction; + u_int8_t log; + u_int8_t logif; + u_int8_t quick; + u_int8_t ifnot; + u_int8_t match_tag_not; + +#define PF_STATE_NORMAL 0x1 +#define PF_STATE_MODULATE 0x2 +#define PF_STATE_SYNPROXY 0x3 + u_int8_t keep_state; + sa_family_t af; + u_int8_t proto; + u_int16_t type; /* aux. value 256 is legit */ + u_int16_t code; /* aux. value 256 is legit */ + u_int8_t flags; + u_int8_t flagset; + u_int8_t min_ttl; + u_int8_t allow_opts; + u_int8_t rt; + u_int8_t return_ttl; + u_int8_t tos; + u_int8_t set_tos; + u_int8_t anchor_relative; + u_int8_t anchor_wildcard; + +#define PF_FLUSH 0x01 +#define PF_FLUSH_GLOBAL 0x02 + u_int8_t flush; + u_int8_t prio; + u_int8_t set_prio[2]; + sa_family_t naf; + u_int8_t rcvifnot; + + struct { + struct pf_addr addr; + u_int16_t port; + u_int8_t type; + } divert; + + time_t exptime; +}; + +/* rule flags */ +#define PFRULE_DROP 0x0000 +#define PFRULE_RETURNRST 0x0001 +#define PFRULE_FRAGMENT 0x0002 +#define PFRULE_RETURNICMP 0x0004 +#define PFRULE_RETURN 0x0008 +#define PFRULE_NOSYNC 0x0010 +#define PFRULE_SRCTRACK 0x0020 /* track source states */ +#define PFRULE_RULESRCTRACK 0x0040 /* per rule */ +#define PFRULE_SETDELAY 0x0080 + +/* rule flags again */ +#define PFRULE_IFBOUND 0x00010000 /* if-bound */ +#define PFRULE_STATESLOPPY 0x00020000 /* sloppy state tracking */ +#define PFRULE_PFLOW 0x00040000 +#define PFRULE_ONCE 0x00100000 /* one shot rule */ +#define PFRULE_AFTO 0x00200000 /* af-to rule */ +#define PFRULE_EXPIRED 0x00400000 /* one shot rule hit by pkt */ + +#define PFSTATE_HIWAT 100000 /* default state table size */ +#define PFSTATE_ADAPT_START 60000 /* default adaptive timeout start */ +#define PFSTATE_ADAPT_END 120000 /* default adaptive timeout end */ +#define PF_PKTDELAY_MAXPKTS 10000 /* max # of pkts held in delay queue */ + +struct pf_rule_item { + SLIST_ENTRY(pf_rule_item) entry; + struct pf_rule *r; +}; + +SLIST_HEAD(pf_rule_slist, pf_rule_item); + +enum pf_sn_types { PF_SN_NONE, PF_SN_NAT, PF_SN_RDR, PF_SN_ROUTE, PF_SN_MAX }; + +struct pf_src_node { + RB_ENTRY(pf_src_node) entry; + struct pf_addr addr; + struct pf_addr raddr; + union pf_rule_ptr rule; + struct pfi_kif *kif; + u_int64_t bytes[2]; + u_int64_t packets[2]; + u_int32_t states; + u_int32_t conn; + struct pf_threshold conn_rate; + int32_t creation; + int32_t expire; + sa_family_t af; + sa_family_t naf; + u_int8_t type; +}; + +struct pf_sn_item { + SLIST_ENTRY(pf_sn_item) next; + struct pf_src_node *sn; +}; + +SLIST_HEAD(pf_sn_head, pf_sn_item); + +#define PFSNODE_HIWAT 10000 /* default source node table size */ + +struct pf_state_scrub { + struct timeval pfss_last; /* time received last packet */ + u_int32_t pfss_tsecr; /* last echoed timestamp */ + u_int32_t pfss_tsval; /* largest timestamp */ + u_int32_t pfss_tsval0; /* original timestamp */ + u_int16_t pfss_flags; +#define PFSS_TIMESTAMP 0x0001 /* modulate timestamp */ +#define PFSS_PAWS 0x0010 /* stricter PAWS checks */ +#define PFSS_PAWS_IDLED 0x0020 /* was idle too long. no PAWS */ +#define PFSS_DATA_TS 0x0040 /* timestamp on data packets */ +#define PFSS_DATA_NOTS 0x0080 /* no timestamp on data packets */ + u_int8_t pfss_ttl; /* stashed TTL */ + u_int8_t pad; + u_int32_t pfss_ts_mod; /* timestamp modulation */ +}; + +struct pf_state_host { + struct pf_addr addr; + u_int16_t port; + u_int16_t pad; +}; + +struct pf_state_peer { + struct pf_state_scrub *scrub; /* state is scrubbed */ + u_int32_t seqlo; /* Max sequence number sent */ + u_int32_t seqhi; /* Max the other end ACKd + win */ + u_int32_t seqdiff; /* Sequence number modulator */ + u_int16_t max_win; /* largest window (pre scaling) */ + u_int16_t mss; /* Maximum segment size option */ + u_int8_t state; /* active state level */ + u_int8_t wscale; /* window scaling factor */ + u_int8_t tcp_est; /* Did we reach TCPS_ESTABLISHED */ + u_int8_t pad[1]; +}; + +TAILQ_HEAD(pf_state_queue, pf_state); + +/* keep synced with struct pf_state_key, used in RB_FIND */ +struct pf_state_key_cmp { + struct pf_addr addr[2]; + u_int16_t port[2]; + u_int16_t rdomain; + u_int16_t hash; + sa_family_t af; + u_int8_t proto; +}; + +/* keep synced with struct pf_state, used in RB_FIND */ +struct pf_state_cmp { + u_int64_t id; + u_int32_t creatorid; + u_int8_t direction; + u_int8_t pad[3]; +}; + +/* struct pf_state.state_flags */ +#define PFSTATE_ALLOWOPTS 0x0001 +#define PFSTATE_SLOPPY 0x0002 +#define PFSTATE_PFLOW 0x0004 +#define PFSTATE_NOSYNC 0x0008 +#define PFSTATE_ACK 0x0010 +#define PFSTATE_NODF 0x0020 +#define PFSTATE_SETTOS 0x0040 +#define PFSTATE_RANDOMID 0x0080 +#define PFSTATE_SCRUB_TCP 0x0100 +#define PFSTATE_SETPRIO 0x0200 +#define PFSTATE_INP_UNLINKED 0x0400 +#define PFSTATE_SCRUBMASK (PFSTATE_NODF|PFSTATE_RANDOMID|PFSTATE_SCRUB_TCP) +#define PFSTATE_SETMASK (PFSTATE_SETTOS|PFSTATE_SETPRIO) + +/* + * Unified state structures for pulling states out of the kernel + * used by pfsync(4) and the pf(4) ioctl. + */ +struct pfsync_state_scrub { + u_int16_t pfss_flags; + u_int8_t pfss_ttl; /* stashed TTL */ +#define PFSYNC_SCRUB_FLAG_VALID 0x01 + u_int8_t scrub_flag; + u_int32_t pfss_ts_mod; /* timestamp modulation */ +} __packed; + +struct pfsync_state_peer { + struct pfsync_state_scrub scrub; /* state is scrubbed */ + u_int32_t seqlo; /* Max sequence number sent */ + u_int32_t seqhi; /* Max the other end ACKd + win */ + u_int32_t seqdiff; /* Sequence number modulator */ + u_int16_t max_win; /* largest window (pre scaling) */ + u_int16_t mss; /* Maximum segment size option */ + u_int8_t state; /* active state level */ + u_int8_t wscale; /* window scaling factor */ + u_int8_t pad[6]; +} __packed; + +struct pfsync_state_key { + struct pf_addr addr[2]; + u_int16_t port[2]; + u_int16_t rdomain; + sa_family_t af; + u_int8_t pad; +}; + +struct pfsync_state { + u_int64_t id; + char ifname[IFNAMSIZ]; + struct pfsync_state_key key[2]; + struct pfsync_state_peer src; + struct pfsync_state_peer dst; + struct pf_addr rt_addr; + u_int32_t rule; + u_int32_t anchor; + u_int32_t nat_rule; + u_int32_t creation; + u_int32_t expire; + u_int32_t packets[2][2]; + u_int32_t bytes[2][2]; + u_int32_t creatorid; + int32_t rtableid[2]; + u_int16_t max_mss; + sa_family_t af; + u_int8_t proto; + u_int8_t direction; + u_int8_t log; + u_int8_t rt; + u_int8_t timeout; + u_int8_t sync_flags; + u_int8_t updates; + u_int8_t min_ttl; + u_int8_t set_tos; + u_int16_t state_flags; + u_int8_t set_prio[2]; +} __packed; + +#define PFSYNC_FLAG_SRCNODE 0x04 +#define PFSYNC_FLAG_NATSRCNODE 0x08 + +#define pf_state_counter_hton(s,d) do { \ + d[0] = htonl((s>>32)&0xffffffff); \ + d[1] = htonl(s&0xffffffff); \ +} while (0) + +#define pf_state_counter_from_pfsync(s) \ + (((u_int64_t)(s[0])<<32) | (u_int64_t)(s[1])) + +#define pf_state_counter_ntoh(s,d) do { \ + d = ntohl(s[0]); \ + d = d<<32; \ + d += ntohl(s[1]); \ +} while (0) + +TAILQ_HEAD(pf_rulequeue, pf_rule); + +struct pf_anchor; + +struct pf_ruleset { + struct { + struct pf_rulequeue queues[2]; + struct { + struct pf_rulequeue *ptr; + u_int32_t rcount; + u_int32_t version; + int open; + } active, inactive; + } rules; + struct pf_anchor *anchor; + u_int32_t tticket; + int tables; + int topen; +}; + +RB_HEAD(pf_anchor_global, pf_anchor); +RB_HEAD(pf_anchor_node, pf_anchor); +struct pf_anchor { + RB_ENTRY(pf_anchor) entry_global; + RB_ENTRY(pf_anchor) entry_node; + struct pf_anchor *parent; + struct pf_anchor_node children; + char name[PF_ANCHOR_NAME_SIZE]; + char path[PATH_MAX]; + struct pf_ruleset ruleset; + int refcnt; /* anchor rules */ + int match; + struct refcnt ref; /* for transactions */ +}; +RB_PROTOTYPE(pf_anchor_global, pf_anchor, entry_global, pf_anchor_compare) +RB_PROTOTYPE(pf_anchor_node, pf_anchor, entry_node, pf_anchor_compare) + +#define PF_RESERVED_ANCHOR "_pf" + +#define PFR_TFLAG_PERSIST 0x00000001 +#define PFR_TFLAG_CONST 0x00000002 +#define PFR_TFLAG_ACTIVE 0x00000004 +#define PFR_TFLAG_INACTIVE 0x00000008 +#define PFR_TFLAG_REFERENCED 0x00000010 +#define PFR_TFLAG_REFDANCHOR 0x00000020 +#define PFR_TFLAG_COUNTERS 0x00000040 +/* Adjust masks below when adding flags. */ +#define PFR_TFLAG_USRMASK 0x00000043 +#define PFR_TFLAG_SETMASK 0x0000003C +#define PFR_TFLAG_ALLMASK 0x0000007F + +struct pfr_table { + char pfrt_anchor[PATH_MAX]; + char pfrt_name[PF_TABLE_NAME_SIZE]; + u_int32_t pfrt_flags; + u_int8_t pfrt_fback; +}; + +enum { PFR_FB_NONE, PFR_FB_MATCH, PFR_FB_ADDED, PFR_FB_DELETED, + PFR_FB_CHANGED, PFR_FB_CLEARED, PFR_FB_DUPLICATE, + PFR_FB_NOTMATCH, PFR_FB_CONFLICT, PFR_FB_NOCOUNT, PFR_FB_MAX }; + +struct pfr_addr { + union { + struct in_addr _pfra_ip4addr; + struct in6_addr _pfra_ip6addr; + } pfra_u; + char pfra_ifname[IFNAMSIZ]; + u_int32_t pfra_states; + u_int16_t pfra_weight; + u_int8_t pfra_af; + u_int8_t pfra_net; + u_int8_t pfra_not; + u_int8_t pfra_fback; + u_int8_t pfra_type; + u_int8_t pad[7]; +}; +#define pfra_ip4addr pfra_u._pfra_ip4addr +#define pfra_ip6addr pfra_u._pfra_ip6addr + +enum { PFR_DIR_IN, PFR_DIR_OUT, PFR_DIR_MAX }; +enum { PFR_OP_BLOCK, PFR_OP_MATCH, PFR_OP_PASS, PFR_OP_ADDR_MAX, + PFR_OP_TABLE_MAX }; +#define PFR_OP_XPASS PFR_OP_ADDR_MAX + +struct pfr_astats { + struct pfr_addr pfras_a; + u_int64_t pfras_packets[PFR_DIR_MAX][PFR_OP_ADDR_MAX]; + u_int64_t pfras_bytes[PFR_DIR_MAX][PFR_OP_ADDR_MAX]; + time_t pfras_tzero; +}; + +enum { PFR_REFCNT_RULE, PFR_REFCNT_ANCHOR, PFR_REFCNT_MAX }; + +struct pfr_tstats { + struct pfr_table pfrts_t; + u_int64_t pfrts_packets[PFR_DIR_MAX][PFR_OP_TABLE_MAX]; + u_int64_t pfrts_bytes[PFR_DIR_MAX][PFR_OP_TABLE_MAX]; + u_int64_t pfrts_match; + u_int64_t pfrts_nomatch; + time_t pfrts_tzero; + int pfrts_cnt; + int pfrts_refcnt[PFR_REFCNT_MAX]; +}; +#define pfrts_name pfrts_t.pfrt_name +#define pfrts_flags pfrts_t.pfrt_flags + +struct pfr_kcounters { + u_int64_t pfrkc_packets[PFR_DIR_MAX][PFR_OP_ADDR_MAX]; + u_int64_t pfrkc_bytes[PFR_DIR_MAX][PFR_OP_ADDR_MAX]; + u_int64_t states; +}; + +/* + * XXX ip_ipsp.h's sockaddr_union should be converted to sockaddr * + * passing with correct sa_len, then a good approach for cleaning this + * will become more clear. + */ +union pfsockaddr_union { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; +}; + +SLIST_HEAD(pfr_kentryworkq, pfr_kentry); +struct _pfr_kentry { + struct radix_node _pfrke_node[2]; + union pfsockaddr_union _pfrke_sa; + SLIST_ENTRY(pfr_kentry) _pfrke_workq; + SLIST_ENTRY(pfr_kentry) _pfrke_ioq; + struct pfr_kcounters *_pfrke_counters; + time_t _pfrke_tzero; + u_int8_t _pfrke_af; + u_int8_t _pfrke_net; + u_int8_t _pfrke_flags; + u_int8_t _pfrke_type; + u_int8_t _pfrke_fb; +}; +#define PFRKE_FLAG_NOT 0x01 +#define PFRKE_FLAG_MARK 0x02 + +/* pfrke_type */ +enum { PFRKE_PLAIN, PFRKE_ROUTE, PFRKE_COST, PFRKE_MAX }; + +struct pfr_kentry { + union { + struct _pfr_kentry _ke; + } u; +}; +#define pfrke_node u._ke._pfrke_node +#define pfrke_sa u._ke._pfrke_sa +#define pfrke_workq u._ke._pfrke_workq +#define pfrke_ioq u._ke._pfrke_ioq +#define pfrke_counters u._ke._pfrke_counters +#define pfrke_tzero u._ke._pfrke_tzero +#define pfrke_af u._ke._pfrke_af +#define pfrke_net u._ke._pfrke_net +#define pfrke_flags u._ke._pfrke_flags +#define pfrke_type u._ke._pfrke_type +#define pfrke_fb u._ke._pfrke_fb + +struct pfr_kentry_route { + union { + struct _pfr_kentry _ke; + } u; + + struct pfi_kif *kif; + char ifname[IFNAMSIZ]; +}; + +struct pfr_kentry_cost { + union { + struct _pfr_kentry _ke; + } u; + + struct pfi_kif *kif; + char ifname[IFNAMSIZ]; + /* Above overlaps with pfr_kentry route */ + + u_int16_t weight; +}; + +struct pfr_kentry_all { + union { + struct _pfr_kentry _ke; + struct pfr_kentry_route kr; + struct pfr_kentry_cost kc; + } u; +}; +#define pfrke_rkif u.kr.kif +#define pfrke_rifname u.kr.ifname + +SLIST_HEAD(pfr_ktableworkq, pfr_ktable); +RB_HEAD(pfr_ktablehead, pfr_ktable); +struct pfr_ktable { + struct pfr_tstats pfrkt_ts; + RB_ENTRY(pfr_ktable) pfrkt_tree; + SLIST_ENTRY(pfr_ktable) pfrkt_workq; + struct radix_node_head *pfrkt_ip4; + struct radix_node_head *pfrkt_ip6; + struct pfr_ktable *pfrkt_shadow; + struct pfr_ktable *pfrkt_root; + struct pf_ruleset *pfrkt_rs; + long pfrkt_larg; + int pfrkt_nflags; + u_int64_t pfrkt_refcntcost; + u_int16_t pfrkt_gcdweight; + u_int16_t pfrkt_maxweight; +}; +#define pfrkt_t pfrkt_ts.pfrts_t +#define pfrkt_name pfrkt_t.pfrt_name +#define pfrkt_anchor pfrkt_t.pfrt_anchor +#define pfrkt_ruleset pfrkt_t.pfrt_ruleset +#define pfrkt_flags pfrkt_t.pfrt_flags +#define pfrkt_cnt pfrkt_ts.pfrts_cnt +#define pfrkt_refcnt pfrkt_ts.pfrts_refcnt +#define pfrkt_packets pfrkt_ts.pfrts_packets +#define pfrkt_bytes pfrkt_ts.pfrts_bytes +#define pfrkt_match pfrkt_ts.pfrts_match +#define pfrkt_nomatch pfrkt_ts.pfrts_nomatch +#define pfrkt_tzero pfrkt_ts.pfrts_tzero + +RB_HEAD(pfi_ifhead, pfi_kif); + +/* state tables */ +extern struct pf_state_tree pf_statetbl; + +/* keep synced with pfi_kif, used in RB_FIND */ +struct pfi_kif_cmp { + char pfik_name[IFNAMSIZ]; +}; + +struct ifnet; +struct ifg_group; + +struct pfi_kif { + char pfik_name[IFNAMSIZ]; + RB_ENTRY(pfi_kif) pfik_tree; + u_int64_t pfik_packets[2][2][2]; + u_int64_t pfik_bytes[2][2][2]; + time_t pfik_tzero; + int pfik_flags; + int pfik_flags_new; + void *pfik_ah_cookie; + struct ifnet *pfik_ifp; + struct ifg_group *pfik_group; + int pfik_states; + int pfik_rules; + int pfik_routes; + int pfik_srcnodes; + int pfik_flagrefs; + TAILQ_HEAD(, pfi_dynaddr) pfik_dynaddrs; +}; + +enum pfi_kif_refs { + PFI_KIF_REF_NONE, + PFI_KIF_REF_STATE, + PFI_KIF_REF_RULE, + PFI_KIF_REF_ROUTE, + PFI_KIF_REF_SRCNODE, + PFI_KIF_REF_FLAG +}; + +#define PFI_IFLAG_SKIP 0x0100 /* skip filtering on interface */ +#define PFI_IFLAG_ANY 0x0200 /* match any non-loopback interface */ + +/* flags for RDR options */ +#define PF_DPORT_RANGE 0x01 /* Dest port uses range */ +#define PF_RPORT_RANGE 0x02 /* RDR'ed port uses range */ + +/* Reasons code for passing/dropping a packet */ +#define PFRES_MATCH 0 /* Explicit match of a rule */ +#define PFRES_BADOFF 1 /* Bad offset for pull_hdr */ +#define PFRES_FRAG 2 /* Dropping following fragment */ +#define PFRES_SHORT 3 /* Dropping short packet */ +#define PFRES_NORM 4 /* Dropping by normalizer */ +#define PFRES_MEMORY 5 /* Dropped due to lacking mem */ +#define PFRES_TS 6 /* Bad TCP Timestamp (RFC1323) */ +#define PFRES_CONGEST 7 /* Congestion */ +#define PFRES_IPOPTIONS 8 /* IP option */ +#define PFRES_PROTCKSUM 9 /* Protocol checksum invalid */ +#define PFRES_BADSTATE 10 /* State mismatch */ +#define PFRES_STATEINS 11 /* State insertion failure */ +#define PFRES_MAXSTATES 12 /* State limit */ +#define PFRES_SRCLIMIT 13 /* Source node/conn limit */ +#define PFRES_SYNPROXY 14 /* SYN proxy */ +#define PFRES_TRANSLATE 15 /* No translation address available */ +#define PFRES_NOROUTE 16 /* No route found for PBR action */ +#define PFRES_MAX 17 /* total+1 */ + +#define PFRES_NAMES { \ + "match", \ + "bad-offset", \ + "fragment", \ + "short", \ + "normalize", \ + "memory", \ + "bad-timestamp", \ + "congestion", \ + "ip-option", \ + "proto-cksum", \ + "state-mismatch", \ + "state-insert", \ + "state-limit", \ + "src-limit", \ + "synproxy", \ + "translate", \ + "no-route", \ + NULL \ +} + +/* Counters for other things we want to keep track of */ +#define LCNT_STATES 0 /* states */ +#define LCNT_SRCSTATES 1 /* max-src-states */ +#define LCNT_SRCNODES 2 /* max-src-nodes */ +#define LCNT_SRCCONN 3 /* max-src-conn */ +#define LCNT_SRCCONNRATE 4 /* max-src-conn-rate */ +#define LCNT_OVERLOAD_TABLE 5 /* entry added to overload table */ +#define LCNT_OVERLOAD_FLUSH 6 /* state entries flushed */ +#define LCNT_SYNFLOODS 7 /* synfloods detected */ +#define LCNT_SYNCOOKIES_SENT 8 /* syncookies sent */ +#define LCNT_SYNCOOKIES_VALID 9 /* syncookies validated */ +#define LCNT_MAX 10 /* total+1 */ + +#define LCNT_NAMES { \ + "max states per rule", \ + "max-src-states", \ + "max-src-nodes", \ + "max-src-conn", \ + "max-src-conn-rate", \ + "overload table insertion", \ + "overload flush states", \ + "synfloods detected", \ + "syncookies sent", \ + "syncookies validated", \ + NULL \ +} + +/* UDP state enumeration */ +#define PFUDPS_NO_TRAFFIC 0 +#define PFUDPS_SINGLE 1 +#define PFUDPS_MULTIPLE 2 + +#define PFUDPS_NSTATES 3 /* number of state levels */ + +#define PFUDPS_NAMES { \ + "NO_TRAFFIC", \ + "SINGLE", \ + "MULTIPLE", \ + NULL \ +} + +/* Other protocol state enumeration */ +#define PFOTHERS_NO_TRAFFIC 0 +#define PFOTHERS_SINGLE 1 +#define PFOTHERS_MULTIPLE 2 + +#define PFOTHERS_NSTATES 3 /* number of state levels */ + +#define PFOTHERS_NAMES { \ + "NO_TRAFFIC", \ + "SINGLE", \ + "MULTIPLE", \ + NULL \ +} + +#define FCNT_STATE_SEARCH 0 +#define FCNT_STATE_INSERT 1 +#define FCNT_STATE_REMOVALS 2 +#define FCNT_MAX 3 + +#define SCNT_SRC_NODE_SEARCH 0 +#define SCNT_SRC_NODE_INSERT 1 +#define SCNT_SRC_NODE_REMOVALS 2 +#define SCNT_MAX 3 + +#define NCNT_FRAG_SEARCH 0 +#define NCNT_FRAG_INSERT 1 +#define NCNT_FRAG_REMOVALS 2 +#define NCNT_MAX 3 + +#define REASON_SET(a, x) \ + do { \ + if ((void *)(a) != NULL) { \ + *(a) = (x); \ + if (x < PFRES_MAX) \ + pf_status.counters[x]++; \ + } \ + } while (0) + +struct pf_status { + u_int64_t counters[PFRES_MAX]; + u_int64_t lcounters[LCNT_MAX]; /* limit counters */ + u_int64_t fcounters[FCNT_MAX]; + u_int64_t scounters[SCNT_MAX]; + u_int64_t ncounters[NCNT_MAX]; + u_int64_t pcounters[2][2][3]; + u_int64_t bcounters[2][2]; + u_int64_t stateid; + u_int64_t syncookies_inflight[2]; /* unACKed SYNcookies */ + time_t since; + u_int32_t running; + u_int32_t states; + u_int32_t states_halfopen; + u_int32_t src_nodes; + u_int32_t fragments; + u_int32_t debug; + u_int32_t hostid; + u_int32_t reass; /* reassembly */ + u_int8_t syncookies_active; + u_int8_t syncookies_mode; /* never/always/adaptive */ + u_int8_t pad[2]; + char ifname[IFNAMSIZ]; + u_int8_t pf_chksum[PF_MD5_DIGEST_LENGTH]; +}; + +#define PF_REASS_ENABLED 0x01 +#define PF_REASS_NODF 0x02 + +#define PF_SYNCOOKIES_NEVER 0 +#define PF_SYNCOOKIES_ALWAYS 1 +#define PF_SYNCOOKIES_ADAPTIVE 2 +#define PF_SYNCOOKIES_MODE_MAX PF_SYNCOOKIES_ADAPTIVE + +#define PF_SYNCOOKIES_HIWATPCT 25 +#define PF_SYNCOOKIES_LOWATPCT PF_SYNCOOKIES_HIWATPCT/2 + +#define PF_PRIO_ZERO 0xff /* match "prio 0" packets */ + +struct pf_queue_bwspec { + uint64_t absolute; + u_int percent; +}; + +struct pf_queue_scspec { + struct pf_queue_bwspec m1; + struct pf_queue_bwspec m2; + u_int d; +}; + +struct pf_queue_fqspec { + u_int flows; + u_int quantum; + u_int target; + u_int interval; +}; + +struct pf_queuespec { + TAILQ_ENTRY(pf_queuespec) entries; + char qname[PF_QNAME_SIZE]; + char parent[PF_QNAME_SIZE]; + char ifname[IFNAMSIZ]; + struct pf_queue_scspec realtime; + struct pf_queue_scspec linkshare; + struct pf_queue_scspec upperlimit; + struct pf_queue_fqspec flowqueue; + struct pfi_kif *kif; + u_int flags; + u_int qlimit; + u_int32_t qid; + u_int32_t parent_qid; +}; + +#define PFQS_FLOWQUEUE 0x0001 +#define PFQS_ROOTCLASS 0x0002 +#define PFQS_DEFAULT 0x1000 /* maps to HFSC_DEFAULTCLASS */ + +struct priq_opts { + int flags; +}; + +struct hfsc_opts { + /* real-time service curve */ + u_int rtsc_m1; /* slope of the 1st segment in bps */ + u_int rtsc_d; /* the x-projection of m1 in msec */ + u_int rtsc_m2; /* slope of the 2nd segment in bps */ + /* link-sharing service curve */ + u_int lssc_m1; + u_int lssc_d; + u_int lssc_m2; + /* upper-limit service curve */ + u_int ulsc_m1; + u_int ulsc_d; + u_int ulsc_m2; + int flags; +}; + +struct pfq_ops { + void * (*pfq_alloc)(struct ifnet *); + int (*pfq_addqueue)(void *, struct pf_queuespec *); + void (*pfq_free)(void *); + int (*pfq_qstats)(struct pf_queuespec *, void *, int *); + /* Queue manager ops */ + unsigned int (*pfq_qlength)(void *); + struct mbuf * (*pfq_enqueue)(void *, struct mbuf *); + struct mbuf * (*pfq_deq_begin)(void *, void **, struct mbuf_list *); + void (*pfq_deq_commit)(void *, struct mbuf *, void *); + void (*pfq_purge)(void *, struct mbuf_list *); +}; + +struct pf_tagname { + TAILQ_ENTRY(pf_tagname) entries; + char name[PF_TAG_NAME_SIZE]; + u_int16_t tag; + int ref; +}; + +struct pf_divert { + struct pf_addr addr; + u_int16_t port; + u_int16_t rdomain; + u_int8_t type; +}; + +enum pf_divert_types { + PF_DIVERT_NONE, + PF_DIVERT_TO, + PF_DIVERT_REPLY, + PF_DIVERT_PACKET +}; + +struct pf_pktdelay { + struct timeout to; + struct mbuf *m; + u_int ifidx; +}; + +/* Fragment entries reference mbuf clusters, so base the default on that. */ +#define PFFRAG_FRENT_HIWAT (NMBCLUSTERS / 16) /* Number of entries */ +#define PFFRAG_FRAG_HIWAT (NMBCLUSTERS / 32) /* Number of packets */ + +#define PFR_KTABLE_HIWAT 1000 /* Number of tables */ +#define PFR_KENTRY_HIWAT 200000 /* Number of table entries */ +#define PFR_KENTRY_HIWAT_SMALL 100000 /* Number of entries for tiny hosts */ + +/* + * ioctl parameter structures + */ + +struct pfioc_rule { + u_int32_t action; + u_int32_t ticket; + u_int32_t nr; + char anchor[PATH_MAX]; + char anchor_call[PATH_MAX]; + struct pf_rule rule; +}; + +struct pfioc_natlook { + struct pf_addr saddr; + struct pf_addr daddr; + struct pf_addr rsaddr; + struct pf_addr rdaddr; + u_int16_t rdomain; + u_int16_t rrdomain; + u_int16_t sport; + u_int16_t dport; + u_int16_t rsport; + u_int16_t rdport; + sa_family_t af; + u_int8_t proto; + u_int8_t direction; +}; + +struct pfioc_state { + struct pfsync_state state; +}; + +struct pfioc_src_node_kill { + sa_family_t psnk_af; + struct pf_rule_addr psnk_src; + struct pf_rule_addr psnk_dst; + u_int psnk_killed; +}; + +struct pfioc_state_kill { + struct pf_state_cmp psk_pfcmp; + sa_family_t psk_af; + int psk_proto; + struct pf_rule_addr psk_src; + struct pf_rule_addr psk_dst; + char psk_ifname[IFNAMSIZ]; + char psk_label[PF_RULE_LABEL_SIZE]; + u_int psk_killed; + u_int16_t psk_rdomain; +}; + +struct pfioc_states { + size_t ps_len; + union { + caddr_t psu_buf; + struct pfsync_state *psu_states; + } ps_u; +#define ps_buf ps_u.psu_buf +#define ps_states ps_u.psu_states +}; + +struct pfioc_src_nodes { + size_t psn_len; + union { + caddr_t psu_buf; + struct pf_src_node *psu_src_nodes; + } psn_u; +#define psn_buf psn_u.psu_buf +#define psn_src_nodes psn_u.psu_src_nodes +}; + +struct pfioc_tm { + int timeout; + int seconds; +}; + +struct pfioc_limit { + int index; + unsigned limit; +}; + +struct pfioc_ruleset { + u_int32_t nr; + char path[PATH_MAX]; + char name[PF_ANCHOR_NAME_SIZE]; +}; + +struct pfioc_trans { + int size; /* number of elements */ + int esize; /* size of each element in bytes */ + struct pfioc_trans_e { + int type; + char anchor[PATH_MAX]; + u_int32_t ticket; + } *array; +}; + +struct pfioc_queue { + u_int32_t ticket; + u_int nr; + struct pf_queuespec queue; +}; + +struct pfioc_qstats { + u_int32_t ticket; + u_int32_t nr; + struct pf_queuespec queue; + void *buf; + int nbytes; +}; + +#define PFR_FLAG_DUMMY 0x00000002 +#define PFR_FLAG_FEEDBACK 0x00000004 +#define PFR_FLAG_CLSTATS 0x00000008 +#define PFR_FLAG_ADDRSTOO 0x00000010 +#define PFR_FLAG_REPLACE 0x00000020 +#define PFR_FLAG_ALLRSETS 0x00000040 +#define PFR_FLAG_ALLMASK 0x0000007F +#ifdef _KERNEL +#define PFR_FLAG_USERIOCTL 0x10000000 +#endif + +struct pfioc_table { + struct pfr_table pfrio_table; + void *pfrio_buffer; + int pfrio_esize; + int pfrio_size; + int pfrio_size2; + int pfrio_nadd; + int pfrio_ndel; + int pfrio_nchange; + int pfrio_flags; + u_int32_t pfrio_ticket; +}; +#define pfrio_exists pfrio_nadd +#define pfrio_nzero pfrio_nadd +#define pfrio_nmatch pfrio_nadd +#define pfrio_naddr pfrio_size2 +#define pfrio_setflag pfrio_size2 +#define pfrio_clrflag pfrio_nadd + +struct pfioc_iface { + char pfiio_name[IFNAMSIZ]; + void *pfiio_buffer; + int pfiio_esize; + int pfiio_size; + int pfiio_nzero; + int pfiio_flags; +}; + +struct pfioc_synflwats { + u_int32_t hiwat; + u_int32_t lowat; +}; + +/* + * ioctl operations + */ + +#define DIOCSTART _IO ('D', 1) +#define DIOCSTOP _IO ('D', 2) +#define DIOCADDRULE _IOWR('D', 4, struct pfioc_rule) +#define DIOCGETRULES _IOWR('D', 6, struct pfioc_rule) +#define DIOCGETRULE _IOWR('D', 7, struct pfioc_rule) +/* cut 8 - 17 */ +#define DIOCCLRSTATES _IOWR('D', 18, struct pfioc_state_kill) +#define DIOCGETSTATE _IOWR('D', 19, struct pfioc_state) +#define DIOCSETSTATUSIF _IOWR('D', 20, struct pfioc_iface) +#define DIOCGETSTATUS _IOWR('D', 21, struct pf_status) +#define DIOCCLRSTATUS _IOWR('D', 22, struct pfioc_iface) +#define DIOCNATLOOK _IOWR('D', 23, struct pfioc_natlook) +#define DIOCSETDEBUG _IOWR('D', 24, u_int32_t) +#define DIOCGETSTATES _IOWR('D', 25, struct pfioc_states) +#define DIOCCHANGERULE _IOWR('D', 26, struct pfioc_rule) +/* cut 27 - 28 */ +#define DIOCSETTIMEOUT _IOWR('D', 29, struct pfioc_tm) +#define DIOCGETTIMEOUT _IOWR('D', 30, struct pfioc_tm) +#define DIOCADDSTATE _IOWR('D', 37, struct pfioc_state) +/* cut 38 */ +#define DIOCGETLIMIT _IOWR('D', 39, struct pfioc_limit) +#define DIOCSETLIMIT _IOWR('D', 40, struct pfioc_limit) +#define DIOCKILLSTATES _IOWR('D', 41, struct pfioc_state_kill) +/* cut 42 - 57 */ +#define DIOCGETRULESETS _IOWR('D', 58, struct pfioc_ruleset) +#define DIOCGETRULESET _IOWR('D', 59, struct pfioc_ruleset) +#define DIOCRCLRTABLES _IOWR('D', 60, struct pfioc_table) +#define DIOCRADDTABLES _IOWR('D', 61, struct pfioc_table) +#define DIOCRDELTABLES _IOWR('D', 62, struct pfioc_table) +#define DIOCRGETTABLES _IOWR('D', 63, struct pfioc_table) +#define DIOCRGETTSTATS _IOWR('D', 64, struct pfioc_table) +#define DIOCRCLRTSTATS _IOWR('D', 65, struct pfioc_table) +#define DIOCRCLRADDRS _IOWR('D', 66, struct pfioc_table) +#define DIOCRADDADDRS _IOWR('D', 67, struct pfioc_table) +#define DIOCRDELADDRS _IOWR('D', 68, struct pfioc_table) +#define DIOCRSETADDRS _IOWR('D', 69, struct pfioc_table) +#define DIOCRGETADDRS _IOWR('D', 70, struct pfioc_table) +#define DIOCRGETASTATS _IOWR('D', 71, struct pfioc_table) +#define DIOCRCLRASTATS _IOWR('D', 72, struct pfioc_table) +#define DIOCRTSTADDRS _IOWR('D', 73, struct pfioc_table) +#define DIOCRSETTFLAGS _IOWR('D', 74, struct pfioc_table) +#define DIOCRINADEFINE _IOWR('D', 77, struct pfioc_table) +#define DIOCOSFPFLUSH _IO('D', 78) +#define DIOCOSFPADD _IOWR('D', 79, struct pf_osfp_ioctl) +#define DIOCOSFPGET _IOWR('D', 80, struct pf_osfp_ioctl) +#define DIOCXBEGIN _IOWR('D', 81, struct pfioc_trans) +#define DIOCXCOMMIT _IOWR('D', 82, struct pfioc_trans) +#define DIOCXROLLBACK _IOWR('D', 83, struct pfioc_trans) +#define DIOCGETSRCNODES _IOWR('D', 84, struct pfioc_src_nodes) +#define DIOCCLRSRCNODES _IO('D', 85) +#define DIOCSETHOSTID _IOWR('D', 86, u_int32_t) +#define DIOCIGETIFACES _IOWR('D', 87, struct pfioc_iface) +#define DIOCSETIFFLAG _IOWR('D', 89, struct pfioc_iface) +#define DIOCCLRIFFLAG _IOWR('D', 90, struct pfioc_iface) +#define DIOCKILLSRCNODES _IOWR('D', 91, struct pfioc_src_node_kill) +#define DIOCSETREASS _IOWR('D', 92, u_int32_t) +#define DIOCADDQUEUE _IOWR('D', 93, struct pfioc_queue) +#define DIOCGETQUEUES _IOWR('D', 94, struct pfioc_queue) +#define DIOCGETQUEUE _IOWR('D', 95, struct pfioc_queue) +#define DIOCGETQSTATS _IOWR('D', 96, struct pfioc_qstats) +#define DIOCSETSYNFLWATS _IOWR('D', 97, struct pfioc_synflwats) +#define DIOCSETSYNCOOKIES _IOWR('D', 98, u_int8_t) +#define DIOCGETSYNFLWATS _IOWR('D', 99, struct pfioc_synflwats) +#define DIOCXEND _IOWR('D', 100, u_int32_t) + +#ifdef _KERNEL + +struct pf_pdesc; + +RB_HEAD(pf_src_tree, pf_src_node); +RB_PROTOTYPE(pf_src_tree, pf_src_node, entry, pf_src_compare); +extern struct pf_src_tree tree_src_tracking; + +extern struct pf_state_list pf_state_list; + +TAILQ_HEAD(pf_queuehead, pf_queuespec); +extern struct pf_queuehead pf_queues[2]; +extern struct pf_queuehead *pf_queues_active, *pf_queues_inactive; + +extern struct pool pf_src_tree_pl, pf_sn_item_pl, pf_rule_pl; +extern struct pool pf_state_pl, pf_state_key_pl, pf_state_item_pl, + pf_rule_item_pl, pf_queue_pl, + pf_pktdelay_pl, pf_anchor_pl; +extern struct pool pf_state_scrub_pl; +extern struct pf_rule pf_default_rule; + +extern int pf_tbladdr_setup(struct pf_ruleset *, + struct pf_addr_wrap *, int); +extern void pf_tbladdr_remove(struct pf_addr_wrap *); +extern void pf_tbladdr_copyout(struct pf_addr_wrap *); +extern void pf_calc_skip_steps(struct pf_rulequeue *); +extern void pf_purge_expired_src_nodes(void); +extern void pf_remove_state(struct pf_state *); +extern void pf_remove_divert_state(struct inpcb *); +extern void pf_free_state(struct pf_state *); +int pf_insert_src_node(struct pf_src_node **, + struct pf_rule *, enum pf_sn_types, + sa_family_t, struct pf_addr *, + struct pf_addr *, struct pfi_kif *); +void pf_remove_src_node(struct pf_src_node *); +struct pf_src_node *pf_get_src_node(struct pf_state *, + enum pf_sn_types); +void pf_src_tree_remove_state(struct pf_state *); +void pf_state_rm_src_node(struct pf_state *, + struct pf_src_node *); + +extern struct pf_state *pf_find_state_byid(struct pf_state_cmp *); +extern struct pf_state *pf_find_state_all(struct pf_state_key_cmp *, + u_int, int *); +extern void pf_state_export(struct pfsync_state *, + struct pf_state *); +int pf_state_import(const struct pfsync_state *, + int); +int pf_state_alloc_scrub_memory( + const struct pfsync_state_peer *, + struct pf_state_peer *); +extern void pf_print_state(struct pf_state *); +extern void pf_print_flags(u_int8_t); +extern void pf_addrcpy(struct pf_addr *, struct pf_addr *, + sa_family_t); +extern void pf_cksum_fixup(u_int16_t *, u_int16_t, + u_int16_t, u_int8_t); +void pf_rm_rule(struct pf_rulequeue *, + struct pf_rule *); +struct pf_divert *pf_find_divert(struct mbuf *); +int pf_setup_pdesc(struct pf_pdesc *, sa_family_t, + int, struct pfi_kif *, struct mbuf *, + u_short *); + +int pf_test(sa_family_t, int, struct ifnet *, struct mbuf **); + +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); + +void *pf_pull_hdr(struct mbuf *, int, void *, int, u_short *, sa_family_t); +#define PF_HI (true) +#define PF_LO (!PF_HI) +#define PF_ALGNMNT(off) (((off) % 2) == 0 ? PF_HI : PF_LO) +int pf_patch_8(struct pf_pdesc *, u_int8_t *, u_int8_t, bool); +int pf_patch_16(struct pf_pdesc *, u_int16_t *, u_int16_t); +int pf_patch_16_unaligned(struct pf_pdesc *, void *, u_int16_t, bool); +int pf_patch_32(struct pf_pdesc *, u_int32_t *, u_int32_t); +int pf_patch_32_unaligned(struct pf_pdesc *, void *, u_int32_t, bool); +int pflog_packet(struct pf_pdesc *, u_int8_t, struct pf_rule *, + struct pf_rule *, struct pf_ruleset *, struct pf_rule *); +int pf_match_addr(u_int8_t, struct pf_addr *, struct pf_addr *, + struct pf_addr *, sa_family_t); +int pf_match_addr_range(struct pf_addr *, struct pf_addr *, + struct pf_addr *, sa_family_t); +int pf_match(u_int8_t, u_int32_t, u_int32_t, u_int32_t); +int pf_match_port(u_int8_t, u_int16_t, u_int16_t, u_int16_t); +int pf_match_uid(u_int8_t, uid_t, uid_t, uid_t); +int pf_match_gid(u_int8_t, gid_t, gid_t, gid_t); + +struct pf_state_scrub * + pf_state_scrub_get(void); +void pf_state_scrub_put(struct pf_state_scrub *); + +int pf_refragment6(struct mbuf **, struct m_tag *mtag, + struct sockaddr_in6 *, struct ifnet *, struct rtentry *); +void pf_normalize_init(void); +int pf_normalize_ip(struct pf_pdesc *, u_short *); +int pf_normalize_ip6(struct pf_pdesc *, u_short *); +int pf_normalize_tcp(struct pf_pdesc *); +void pf_normalize_tcp_cleanup(struct pf_state *); +int pf_normalize_tcp_init(struct pf_pdesc *, struct pf_state_peer *); +int pf_normalize_tcp_alloc(struct pf_state_peer *); +int pf_normalize_tcp_stateful(struct pf_pdesc *, u_short *, + struct pf_state *, struct pf_state_peer *, struct pf_state_peer *, + int *); +int pf_normalize_mss(struct pf_pdesc *, u_int16_t); +void pf_scrub(struct mbuf *, u_int16_t, sa_family_t, u_int8_t, u_int8_t); +void pf_purge_expired_fragments(void); +int pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *, + int); +int pf_rtlabel_match(struct pf_addr *, sa_family_t, struct pf_addr_wrap *, + int); +int pf_socket_lookup(struct pf_pdesc *); +struct pf_state_key *pf_alloc_state_key(int); +int pf_ouraddr(struct mbuf *); +void pf_pkt_addr_changed(struct mbuf *); +struct inpcb *pf_inp_lookup(struct mbuf *); +void pf_inp_link(struct mbuf *, struct inpcb *); +void pf_inp_unlink(struct inpcb *); +int pf_translate(struct pf_pdesc *, struct pf_addr *, u_int16_t, + struct pf_addr *, u_int16_t, u_int16_t, int); +int pf_translate_af(struct pf_pdesc *); +void pf_route(struct pf_pdesc *, struct pf_state *); +void pf_route6(struct pf_pdesc *, struct pf_state *); +void pf_init_threshold(struct pf_threshold *, u_int32_t, u_int32_t); +int pf_delay_pkt(struct mbuf *, u_int); + +void pfr_initialize(void); +int pfr_match_addr(struct pfr_ktable *, struct pf_addr *, sa_family_t); +void pfr_update_stats(struct pfr_ktable *, struct pf_addr *, + struct pf_pdesc *, int, int); +int pfr_pool_get(struct pf_pool *, struct pf_addr **, + struct pf_addr **, sa_family_t); +int pfr_states_increase(struct pfr_ktable *, struct pf_addr *, int); +int pfr_states_decrease(struct pfr_ktable *, struct pf_addr *, int); +struct pfr_kentry * + pfr_kentry_byaddr(struct pfr_ktable *, struct pf_addr *, sa_family_t, + int); +void pfr_dynaddr_update(struct pfr_ktable *, struct pfi_dynaddr *); +struct pfr_ktable * + pfr_attach_table(struct pf_ruleset *, char *, int); +void pfr_detach_table(struct pfr_ktable *); +int pfr_clr_tables(struct pfr_table *, int *, int); +int pfr_add_tables(struct pfr_table *, int, int *, int); +int pfr_del_tables(struct pfr_table *, int, int *, int); +int pfr_get_tables(struct pfr_table *, struct pfr_table *, int *, int); +int pfr_get_tstats(struct pfr_table *, struct pfr_tstats *, int *, int); +int pfr_clr_tstats(struct pfr_table *, int, int *, int); +int pfr_set_tflags(struct pfr_table *, int, int, int, int *, int *, int); +int pfr_clr_addrs(struct pfr_table *, int *, int); +int pfr_insert_kentry(struct pfr_ktable *, struct pfr_addr *, time_t); +int pfr_add_addrs(struct pfr_table *, struct pfr_addr *, int, int *, + int); +int pfr_del_addrs(struct pfr_table *, struct pfr_addr *, int, int *, + int); +int pfr_set_addrs(struct pfr_table *, struct pfr_addr *, int, int *, + int *, int *, int *, int, u_int32_t); +int pfr_get_addrs(struct pfr_table *, struct pfr_addr *, int *, int); +int pfr_get_astats(struct pfr_table *, struct pfr_astats *, int *, int); +int pfr_clr_astats(struct pfr_table *, struct pfr_addr *, int, int *, + int); +int pfr_tst_addrs(struct pfr_table *, struct pfr_addr *, int, int *, + int); +int pfr_ina_begin(struct pfr_table *, u_int32_t *, int *, int); +int pfr_ina_rollback(struct pfr_table *, u_int32_t, int *, int); +int pfr_ina_commit(struct pfr_table *, u_int32_t, int *, int *, int); +int pfr_ina_define(struct pfr_table *, struct pfr_addr *, int, int *, + int *, u_int32_t, int); +struct pfr_ktable + *pfr_ktable_select_active(struct pfr_ktable *); + +extern struct pfi_kif *pfi_all; + +void pfi_initialize(void); +struct pfi_kif *pfi_kif_alloc(const char *, int); +void pfi_kif_free(struct pfi_kif *); +struct pfi_kif *pfi_kif_find(const char *); +struct pfi_kif *pfi_kif_get(const char *, struct pfi_kif **); +void pfi_kif_ref(struct pfi_kif *, enum pfi_kif_refs); +void pfi_kif_unref(struct pfi_kif *, enum pfi_kif_refs); +int pfi_kif_match(struct pfi_kif *, struct pfi_kif *); +void pfi_attach_ifnet(struct ifnet *); +void pfi_detach_ifnet(struct ifnet *); +void pfi_attach_ifgroup(struct ifg_group *); +void pfi_detach_ifgroup(struct ifg_group *); +void pfi_group_addmember(const char *); +void pfi_group_delmember(const char *); +int pfi_match_addr(struct pfi_dynaddr *, struct pf_addr *, + sa_family_t); +int pfi_dynaddr_setup(struct pf_addr_wrap *, sa_family_t, int); +void pfi_dynaddr_remove(struct pf_addr_wrap *); +void pfi_dynaddr_copyout(struct pf_addr_wrap *); +void pfi_update_status(const char *, struct pf_status *); +void pfi_get_ifaces(const char *, struct pfi_kif *, int *); +int pfi_set_flags(const char *, int); +int pfi_clear_flags(const char *, int); +void pfi_xcommit(void); + +int pf_match_tag(struct mbuf *, struct pf_rule *, int *); +u_int16_t pf_tagname2tag(char *, int); +void pf_tag2tagname(u_int16_t, char *); +void pf_tag_ref(u_int16_t); +void pf_tag_unref(u_int16_t); +void pf_tag_packet(struct mbuf *, int, int); +int pf_addr_compare(const struct pf_addr *, + const struct pf_addr *, sa_family_t); + +const struct pfq_ops + *pf_queue_manager(struct pf_queuespec *); + +extern struct pf_status pf_status; +extern struct pool pf_frent_pl, pf_frag_pl; + +/* + * Protection/ownership of pf_pool_limit: + * I immutable after pfattach() + * p pf_lock + */ + +struct pf_pool_limit { + void *pp; /* [I] */ + unsigned limit; /* [p] */ + unsigned limit_new; /* [p] */ +}; +extern struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX]; + +#endif /* _KERNEL */ + +extern struct pf_anchor_global pf_anchors; +extern struct pf_anchor pf_main_anchor; +#define pf_main_ruleset pf_main_anchor.ruleset + +struct tcphdr; + +/* these ruleset functions can be linked into userland programs (pfctl) */ +void pf_init_ruleset(struct pf_ruleset *); +int pf_anchor_setup(struct pf_rule *, + const struct pf_ruleset *, const char *); +int pf_anchor_copyout(const struct pf_ruleset *, + const struct pf_rule *, struct pfioc_rule *); +void pf_remove_anchor(struct pf_rule *); +void pf_remove_if_empty_ruleset(struct pf_ruleset *); +struct pf_anchor *pf_find_anchor(const char *); +struct pf_ruleset *pf_find_ruleset(const char *); +struct pf_ruleset *pf_get_leaf_ruleset(char *, char **); +struct pf_anchor *pf_create_anchor(struct pf_anchor *, const char *); +struct pf_ruleset *pf_find_or_create_ruleset(const char *); +void pf_anchor_rele(struct pf_anchor *); +struct pf_anchor *pf_anchor_take(struct pf_anchor *); + +/* The fingerprint functions can be linked into userland programs (tcpdump) */ +int pf_osfp_add(struct pf_osfp_ioctl *); +#ifdef _KERNEL +struct pf_osfp_enlist * + pf_osfp_fingerprint(struct pf_pdesc *); +#endif /* _KERNEL */ +struct pf_osfp_enlist * + pf_osfp_fingerprint_hdr(const struct ip *, const struct ip6_hdr *, + const struct tcphdr *); +void pf_osfp_flush(void); +int pf_osfp_get(struct pf_osfp_ioctl *); +void pf_osfp_initialize(void); +int pf_osfp_match(struct pf_osfp_enlist *, pf_osfp_t); +struct pf_os_fingerprint * + pf_osfp_validate(void); + +#ifdef _KERNEL +void pf_print_host(struct pf_addr *, u_int16_t, + sa_family_t); +int pf_get_transaddr(struct pf_rule *, struct pf_pdesc *, + struct pf_src_node **, struct pf_rule **); +int pf_map_addr(sa_family_t, struct pf_rule *, + struct pf_addr *, struct pf_addr *, + struct pf_addr *, struct pf_src_node **, + struct pf_pool *, enum pf_sn_types); +int pf_postprocess_addr(struct pf_state *); + +void pf_mbuf_link_state_key(struct mbuf *, + struct pf_state_key *); +void pf_mbuf_unlink_state_key(struct mbuf *); +void pf_mbuf_link_inpcb(struct mbuf *, struct inpcb *); +void pf_mbuf_unlink_inpcb(struct mbuf *); + +u_int8_t* pf_find_tcpopt(u_int8_t *, u_int8_t *, size_t, + u_int8_t, u_int8_t); +u_int8_t pf_get_wscale(struct pf_pdesc *); +u_int16_t pf_get_mss(struct pf_pdesc *, uint16_t); +struct mbuf * pf_build_tcp(const struct pf_rule *, sa_family_t, + const struct pf_addr *, const struct pf_addr *, + u_int16_t, u_int16_t, u_int32_t, u_int32_t, + u_int8_t, u_int16_t, u_int16_t, u_int8_t, int, + u_int16_t, u_int, u_int, u_short *); +void pf_send_tcp(const struct pf_rule *, sa_family_t, + const struct pf_addr *, const struct pf_addr *, + u_int16_t, u_int16_t, u_int32_t, u_int32_t, + u_int8_t, u_int16_t, u_int16_t, u_int8_t, int, + u_int16_t, u_int, u_short *); +void pf_syncookies_init(void); +int pf_syncookies_setmode(u_int8_t); +int pf_syncookies_setwats(u_int32_t, u_int32_t); +int pf_syncookies_getwats(struct pfioc_synflwats *); +int pf_synflood_check(struct pf_pdesc *); +void pf_syncookie_send(struct pf_pdesc *, u_short *); +u_int8_t pf_syncookie_validate(struct pf_pdesc *); +struct mbuf * pf_syncookie_recreate_syn(struct pf_pdesc *, + u_short *); +#endif /* _KERNEL */ + +#endif /* _NET_PFVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/pfvar_priv.h b/lib/libc/include/generic-openbsd/net/pfvar_priv.h new file mode 100644 index 000000000000..a005b8511ace --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/pfvar_priv.h @@ -0,0 +1,434 @@ +/* $OpenBSD: pfvar_priv.h,v 1.38 2024/09/07 22:41:55 aisha Exp $ */ + +/* + * Copyright (c) 2001 Daniel Hartmeier + * Copyright (c) 2002 - 2013 Henning Brauer + * Copyright (c) 2016 Alexander Bluhm + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDERS 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 _NET_PFVAR_PRIV_H_ +#define _NET_PFVAR_PRIV_H_ + +#ifdef _KERNEL + +#include +#include +#include + +/* + * Locks used to protect struct members in this file: + * L pf_inp_mtx link pf to inp mutex + */ + +struct pfsync_deferral; + +/* + * pf state items - links from pf_state_key to pf_states + */ + +struct pf_state_item { + TAILQ_ENTRY(pf_state_item) + si_entry; + struct pf_state *si_st; +}; + +TAILQ_HEAD(pf_statelisthead, pf_state_item); + +/* + * pf state keys - look up states by address + */ + +struct pf_state_key { + struct pf_addr addr[2]; + u_int16_t port[2]; + u_int16_t rdomain; + u_int16_t hash; + sa_family_t af; + u_int8_t proto; + + RBT_ENTRY(pf_state_key) sk_entry; + struct pf_statelisthead sk_states; + struct pf_state_key *sk_reverse; + struct inpcb *sk_inp; /* [L] */ + pf_refcnt_t sk_refcnt; + u_int8_t sk_removed; +}; + +RBT_HEAD(pf_state_tree, pf_state_key); +RBT_PROTOTYPE(pf_state_tree, pf_state_key, sk_entry, pf_state_compare_key); + +#define PF_REVERSED_KEY(key, family) \ + ((key[PF_SK_WIRE]->af != key[PF_SK_STACK]->af) && \ + (key[PF_SK_WIRE]->af != (family))) + +/* + * pf state + * + * Protection/ownership of pf_state members: + * I immutable after pf_state_insert() + * M pf_state mtx + * P PF_STATE_LOCK + * S pfsync + * L pf_state_list + * g pf_purge gc + */ + +struct pf_state { + u_int64_t id; /* [I] */ + u_int32_t creatorid; /* [I] */ + u_int8_t direction; /* [I] */ + u_int8_t pad[3]; + + TAILQ_ENTRY(pf_state) sync_list; /* [S] */ + struct pfsync_deferral *sync_defer; /* [S] */ + TAILQ_ENTRY(pf_state) entry_list; /* [L] */ + SLIST_ENTRY(pf_state) gc_list; /* [g] */ + RBT_ENTRY(pf_state) entry_id; /* [P] */ + struct pf_state_peer src; + struct pf_state_peer dst; + struct pf_rule_slist match_rules; /* [I] */ + union pf_rule_ptr rule; /* [I] */ + union pf_rule_ptr anchor; /* [I] */ + union pf_rule_ptr natrule; /* [I] */ + struct pf_addr rt_addr; /* [I] */ + struct pf_sn_head src_nodes; /* [I] */ + struct pf_state_key *key[2]; /* [I] stack and wire */ + struct pfi_kif *kif; /* [I] */ + struct mutex mtx; + pf_refcnt_t refcnt; + u_int64_t packets[2]; + u_int64_t bytes[2]; + int32_t creation; /* [I] */ + int32_t expire; + int32_t pfsync_time; /* [S] */ + int rtableid[2]; /* [I] stack and wire */ + u_int16_t qid; /* [I] */ + u_int16_t pqid; /* [I] */ + u_int16_t tag; /* [I] */ + u_int16_t state_flags; /* [M] */ + u_int8_t log; /* [I] */ + u_int8_t timeout; + u_int8_t sync_state; /* [S] PFSYNC_S_x */ + u_int8_t sync_updates; /* [S] */ + u_int8_t min_ttl; /* [I] */ + u_int8_t set_tos; /* [I] */ + u_int8_t set_prio[2]; /* [I] */ + u_int16_t max_mss; /* [I] */ + u_int16_t if_index_in; /* [I] */ + u_int16_t if_index_out; /* [I] */ + u_int16_t delay; /* [I] */ + u_int8_t rt; /* [I] */ +}; + +RBT_HEAD(pf_state_tree_id, pf_state); +RBT_PROTOTYPE(pf_state_tree_id, pf_state, entry_id, pf_state_compare_id); +extern struct pf_state_tree_id tree_id; + +/* + * states are linked into a global list to support the following + * functionality: + * + * - garbage collection + * - pfsync bulk send operations + * - bulk state fetches via the DIOCGETSTATES ioctl + * - bulk state clearing via the DIOCCLRSTATES ioctl + * + * states are inserted into the global pf_state_list once it has also + * been successfully added to the various trees that make up the state + * table. states are only removed from the pf_state_list by the garbage + * collection process. + * + * the pf_state_list head and tail pointers (ie, the pfs_list TAILQ_HEAD + * structure) and the pointers between the entries on the pf_state_list + * are locked separately. at a high level, this allows for insertion + * of new states into the pf_state_list while other contexts (eg, the + * ioctls) are traversing the state items in the list. for garbage + * collection to remove items from the pf_state_list, it has to exclude + * both modifications to the list head and tail pointers, and traversal + * of the links between the states. + * + * the head and tail pointers are protected by a mutex. the pointers + * between states are protected by an rwlock. + * + * because insertions are only made to the end of the list, if we get + * a snapshot of the head and tail of the list and prevent modifications + * to the links between states, we can safely traverse between the + * head and tail entries. subsequent insertions can add entries after + * our view of the tail, but we don't look past our view. + * + * if both locks must be taken, the rwlock protecting the links between + * states is taken before the mutex protecting the head and tail + * pointer. + * + * insertion into the list follows this pattern: + * + * // serialise list head/tail modifications + * mtx_enter(&pf_state_list.pfs_mtx); + * TAILQ_INSERT_TAIL(&pf_state_list.pfs_list, state, entry_list); + * mtx_leave(&pf_state_list.pfs_mtx); + * + * traversal of the list: + * + * // lock against the gc removing an item from the list + * rw_enter_read(&pf_state_list.pfs_rwl); + * + * // get a snapshot view of the ends of the list + * mtx_enter(&pf_state_list.pfs_mtx); + * head = TAILQ_FIRST(&pf_state_list.pfs_list); + * tail = TAILQ_LAST(&pf_state_list.pfs_list, pf_state_queue); + * mtx_leave(&pf_state_list.pfs_mtx); + * + * state = NULL; + * next = head; + * + * while (state != tail) { + * state = next; + * next = TAILQ_NEXT(state, entry_list); + * + * // look at the state + * } + * + * rw_exit_read(&pf_state_list.pfs_rwl); + * + * removing an item from the list: + * + * // wait for iterators (readers) to get out + * rw_enter_write(&pf_state_list.pfs_rwl); + * + * // serialise list head/tail modifications + * mtx_enter(&pf_state_list.pfs_mtx); + * TAILQ_REMOVE(&pf_state_list.pfs_list, state, entry_list); + * mtx_leave(&pf_state_list.pfs_mtx); + * + * rw_exit_write(&pf_state_list.pfs_rwl); + * + * the lock ordering for pf_state_list locks and the rest of the pf + * locks are: + * + * 1. KERNEL_LOCK + * 2. NET_LOCK + * 3. pf_state_list.pfs_rwl + * 4. PF_LOCK + * 5. PF_STATE_LOCK + * 6. pf_state_list.pfs_mtx + */ + +struct pf_state_list { + /* the list of states in the system */ + struct pf_state_queue pfs_list; + + /* serialise pfs_list head/tail access */ + struct mutex pfs_mtx; + + /* serialise access to pointers between pfs_list entries */ + struct rwlock pfs_rwl; +}; + +#define PF_STATE_LIST_INITIALIZER(_pfs) { \ + .pfs_list = TAILQ_HEAD_INITIALIZER(_pfs.pfs_list), \ + .pfs_mtx = MUTEX_INITIALIZER(IPL_SOFTNET), \ + .pfs_rwl = RWLOCK_INITIALIZER("pfstates"), \ +} + +extern struct rwlock pf_lock; + +struct pf_pdesc { + struct { + int done; + uid_t uid; + gid_t gid; + pid_t pid; + } lookup; + u_int64_t tot_len; /* Make Mickey money */ + + struct pf_addr nsaddr; /* src address after NAT */ + struct pf_addr ndaddr; /* dst address after NAT */ + + struct pfi_kif *kif; /* incoming interface */ + struct mbuf *m; /* mbuf containing the packet */ + struct pf_addr *src; /* src address */ + struct pf_addr *dst; /* dst address */ + u_int16_t *pcksum; /* proto cksum */ + u_int16_t *sport; + u_int16_t *dport; + u_int16_t osport; + u_int16_t odport; + u_int16_t hash; + u_int16_t nsport; /* src port after NAT */ + u_int16_t ndport; /* dst port after NAT */ + + u_int32_t off; /* protocol header offset */ + u_int32_t hdrlen; /* protocol header length */ + u_int32_t p_len; /* length of protocol payload */ + u_int32_t extoff; /* extension header offset */ + u_int32_t fragoff; /* fragment header offset */ + u_int32_t jumbolen; /* length from v6 jumbo header */ + u_int32_t badopts; /* v4 options or v6 routing headers */ +#define PF_OPT_OTHER 0x0001 +#define PF_OPT_JUMBO 0x0002 +#define PF_OPT_ROUTER_ALERT 0x0004 + + u_int16_t rdomain; /* original routing domain */ + u_int16_t virtual_proto; +#define PF_VPROTO_FRAGMENT 256 + sa_family_t af; + sa_family_t naf; + u_int8_t proto; + u_int8_t tos; + u_int8_t ttl; + u_int8_t dir; /* direction */ + u_int8_t sidx; /* key index for source */ + u_int8_t didx; /* key index for destination */ + u_int8_t destchg; /* flag set when destination changed */ + u_int8_t pflog; /* flags for packet logging */ + union { + struct tcphdr tcp; + struct udphdr udp; + struct icmp icmp; +#ifdef INET6 + struct icmp6_hdr icmp6; + struct mld_hdr mld; + struct nd_neighbor_solicit nd_ns; +#endif /* INET6 */ + } hdr; +}; + +struct pf_anchor_stackframe { + struct pf_ruleset *sf_rs; + struct pf_rule *sf_anchor; + union { + struct pf_rule *u_r; + struct pf_anchor_stackframe *u_stack_top; + } u; + struct pf_anchor *sf_child; + int sf_jump_target; +}; +#define sf_r u.u_r +#define sf_stack_top u.u_stack_top +enum { + PF_NEXT_RULE, + PF_NEXT_CHILD +}; + +extern struct cpumem *pf_anchor_stack; + +enum pf_trans_type { + PF_TRANS_NONE, + PF_TRANS_GETRULE, + PF_TRANS_MAX +}; + +struct pf_trans { + LIST_ENTRY(pf_trans) pft_entry; + uint32_t pft_unit; /* process id */ + uint64_t pft_ticket; + enum pf_trans_type pft_type; + union { + struct { + u_int32_t gr_version; + struct pf_anchor *gr_anchor; + struct pf_rule *gr_rule; + } u_getrule; + } u; +}; + +#define pftgr_version u.u_getrule.gr_version +#define pftgr_anchor u.u_getrule.gr_anchor +#define pftgr_rule u.u_getrule.gr_rule + +extern struct timeout pf_purge_states_to; +extern struct task pf_purge_task; +extern struct timeout pf_purge_to; + +struct pf_state *pf_state_ref(struct pf_state *); +void pf_state_unref(struct pf_state *); + +extern struct rwlock pf_lock; +extern struct rwlock pf_state_lock; +extern struct mutex pf_frag_mtx; +extern struct mutex pf_inp_mtx; + +#define PF_LOCK() do { \ + rw_enter_write(&pf_lock); \ + } while (0) + +#define PF_UNLOCK() do { \ + PF_ASSERT_LOCKED(); \ + rw_exit_write(&pf_lock); \ + } while (0) + +#define PF_ASSERT_LOCKED() do { \ + if (rw_status(&pf_lock) != RW_WRITE) \ + splassert_fail(RW_WRITE, \ + rw_status(&pf_lock),__func__);\ + } while (0) + +#define PF_ASSERT_UNLOCKED() do { \ + if (rw_status(&pf_lock) == RW_WRITE) \ + splassert_fail(0, rw_status(&pf_lock), __func__);\ + } while (0) + +#define PF_STATE_ENTER_READ() do { \ + rw_enter_read(&pf_state_lock); \ + } while (0) + +#define PF_STATE_EXIT_READ() do { \ + rw_exit_read(&pf_state_lock); \ + } while (0) + +#define PF_STATE_ENTER_WRITE() do { \ + rw_enter_write(&pf_state_lock); \ + } while (0) + +#define PF_STATE_EXIT_WRITE() do { \ + PF_STATE_ASSERT_LOCKED(); \ + rw_exit_write(&pf_state_lock); \ + } while (0) + +#define PF_STATE_ASSERT_LOCKED() do { \ + if (rw_status(&pf_state_lock) != RW_WRITE)\ + splassert_fail(RW_WRITE, \ + rw_status(&pf_state_lock), __func__);\ + } while (0) + +#define PF_FRAG_LOCK() mtx_enter(&pf_frag_mtx) +#define PF_FRAG_UNLOCK() mtx_leave(&pf_frag_mtx) + +/* for copies to/from network byte order */ +void pf_state_peer_hton(const struct pf_state_peer *, + struct pfsync_state_peer *); +void pf_state_peer_ntoh(const struct pfsync_state_peer *, + struct pf_state_peer *); +u_int16_t pf_pkt_hash(sa_family_t, uint8_t, + const struct pf_addr *, const struct pf_addr *, + uint16_t, uint16_t); + +#endif /* _KERNEL */ + +#endif /* _NET_PFVAR_PRIV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/pipex.h b/lib/libc/include/generic-openbsd/net/pipex.h new file mode 100644 index 000000000000..c6b56abf9a50 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/pipex.h @@ -0,0 +1,210 @@ +/* $OpenBSD: pipex.h,v 1.35 2025/03/02 21:28:32 bluhm Exp $ */ + +/* + * Copyright (c) 2009 Internet Initiative Japan Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef NET_PIPEX_H +#define NET_PIPEX_H 1 + +/* + * Names for pipex sysctl objects + */ +#define PIPEXCTL_ENABLE 1 +#define PIPEXCTL_MAXID 2 + +#define PIPEXCTL_NAMES { \ + { 0, 0 }, \ + { "enable", CTLTYPE_INT }, \ +} + +#define PIPEX_PROTO_L2TP 1 /* protocol L2TP */ +#define PIPEX_PROTO_PPTP 2 /* protocol PPTP */ +#define PIPEX_PROTO_PPPOE 3 /* protocol PPPoE */ +#define PIPEX_MAX_LISTREQ 128 /* list request size */ +#define PIPEX_MPPE_KEYLEN 16 + +/* pipex_mppe */ +struct pipex_mppe_req { + int16_t stateless; /* mppe key mode. + 1 for stateless */ + int16_t keylenbits; /* mppe key length(in bits)*/ + u_char master_key[PIPEX_MPPE_KEYLEN]; /* mppe master key */ +}; + +/* pipex statistics */ +struct pipex_statistics { + uint32_t ipackets; /* packets received from tunnel */ + uint32_t ierrors; /* error packets received from tunnel */ + uint64_t ibytes; /* number of received bytes from tunnel */ + uint32_t opackets; /* packets sent to tunnel */ + uint32_t oerrors; /* error packets on sending to tunnel */ + uint64_t obytes; /* number of sent bytes to tunnel */ + + uint32_t idle_time; /* idle time in seconds */ +}; + +struct pipex_session_req { + int pr_protocol; /* tunnel protocol */ +/* u_int pr_rdomain; */ /* rdomain id */ + uint16_t pr_session_id; /* session-id */ + uint16_t pr_peer_session_id; /* peer's session-id */ + uint32_t pr_ppp_flags; /* PPP configuration flags */ +#define PIPEX_PPP_ACFC_ACCEPTED 0x0001 /* ACFC accepted */ +#define PIPEX_PPP_PFC_ACCEPTED 0x0002 /* PFC accepted */ +#define PIPEX_PPP_ACFC_ENABLED 0x0004 /* ACFC enabled */ +#define PIPEX_PPP_PFC_ENABLED 0x0008 /* PFC enabled */ +#define PIPEX_PPP_MPPE_ACCEPTED 0x0010 /* MPPE accepted */ +#define PIPEX_PPP_MPPE_ENABLED 0x0020 /* MPPE enabled */ +#define PIPEX_PPP_MPPE_REQUIRED 0x0040 /* MPPE is required */ +#define PIPEX_PPP_HAS_ACF 0x0080 /* has ACF */ +#define PIPEX_PPP_ADJUST_TCPMSS 0x0100 /* do tcpmss adjustment */ +#define PIPEX_PPP_INGRESS_FILTER 0x0200 /* do ingress filter */ + int8_t pr_ccp_id; /* CCP current packet id */ + int pr_ppp_id; /* PPP Id. */ + uint16_t pr_peer_mru; /* Peer's MRU */ + uint32_t pr_timeout_sec; /* Idle Timer */ + + struct in_addr pr_ip_srcaddr; /* local framed IP-Address */ + struct in_addr pr_ip_address; /* framed IP-Address */ + struct in_addr pr_ip_netmask; /* framed IP-Netmask */ + struct sockaddr_in6 pr_ip6_address; /* framed IPv6-Address */ + int pr_ip6_prefixlen; /* framed IPv6-Prefixlen */ + union { + struct { + uint32_t snd_nxt; /* send next */ + uint32_t rcv_nxt; /* receive next */ + uint32_t snd_una; /* unacked */ + uint32_t rcv_acked; /* recv acked */ + int winsz; /* window size */ + int maxwinsz; /* max window size */ + int peer_maxwinsz; /* peer's max window size */ + } pptp; + struct { + uint32_t option_flags; +#define PIPEX_L2TP_USE_SEQUENCING 0x00000001 + + uint16_t tunnel_id; /* our tunnel-id */ + uint16_t peer_tunnel_id;/* peer's tunnel-id */ + uint32_t ns_nxt; /* send next */ + uint32_t nr_nxt; /* receive next */ + uint32_t ns_una; /* unacked */ + uint32_t nr_acked; /* recv acked */ + uint32_t ipsecflowinfo; /* IPsec flow id for NAT-T */ + } l2tp; + struct { + char over_ifname[IF_NAMESIZE]; /* ethernet ifname */ + } pppoe; + } pr_proto; + struct sockaddr_storage pr_peer_address; /* peer address of tunnel */ + struct sockaddr_storage pr_local_address; /* our address of tunnel */ + struct pipex_mppe_req pr_mppe_recv; /* mppe key for receive */ + struct pipex_mppe_req pr_mppe_send; /* mppe key for send */ +}; + +struct pipex_session_stat_req { + int psr_protocol; /* tunnel protocol */ + uint16_t psr_session_id; /* session-id */ + struct pipex_statistics psr_stat; /* statistics */ +}; +struct pipex_session_close_req { + int psr_protocol; /* tunnel protocol */ + uint16_t psr_session_id; /* session-id */ + struct pipex_statistics psr_stat; /* statistics */ +}; +#define pcr_protocol psr_protocol +#define pcr_session_id psr_session_id +#define pcr_stat psr_stat + +struct pipex_session_list_req { + uint8_t plr_flags; +#define PIPEX_LISTREQ_MORE 0x01 + int plr_ppp_id_count; /* count of PPP id */ + int plr_ppp_id[PIPEX_MAX_LISTREQ]; /* PPP id */ +}; + +/* for pppx(4) */ +struct pppx_hdr { + u_int32_t pppx_proto; /* write: protocol in PIPEX_PROTO_ */ + u_int32_t pppx_id; /* write: session_id, read: ppp_id */ +}; + +struct pipex_session_descr_req { + int pdr_protocol; /* tunnel protocol */ + uint16_t pdr_session_id; /* session-id */ + char pdr_descr[IFDESCRSIZE]; /* description */ +}; + + +/* PIPEX ioctls */ +#define PIPEXASESSION _IOW ('p', 3, struct pipex_session_req) +#define PIPEXDSESSION _IOWR('p', 4, struct pipex_session_close_req) +#define PIPEXGSTAT _IOWR('p', 6, struct pipex_session_stat_req) +#define PIPEXGCLOSED _IOR ('p', 7, struct pipex_session_list_req) +#define PIPEXSIFDESCR _IOW ('p', 8, struct pipex_session_descr_req) + +#ifdef _KERNEL +extern int pipex_enable; + +struct pipex_session; + +__BEGIN_DECLS +void pipex_init(void); + +struct pipex_session *pipex_pppoe_lookup_session(struct mbuf *); +struct mbuf *pipex_pppoe_input(struct mbuf *, + struct pipex_session *, struct netstack *); +struct pipex_session *pipex_pptp_lookup_session(struct mbuf *); +struct mbuf *pipex_pptp_input(struct mbuf *, + struct pipex_session *, struct netstack *); +struct pipex_session *pipex_pptp_userland_lookup_session_ipv4(struct mbuf *, + struct in_addr); +struct pipex_session *pipex_pptp_userland_lookup_session_ipv6(struct mbuf *, + struct in6_addr); +struct pipex_session *pipex_l2tp_userland_lookup_session(struct mbuf *, + struct sockaddr *); +struct mbuf *pipex_pptp_userland_output(struct mbuf *, + struct pipex_session *); +struct pipex_session *pipex_l2tp_lookup_session(struct mbuf *, int, + struct sockaddr *); +struct mbuf *pipex_l2tp_input(struct mbuf *, int off, + struct pipex_session *, uint32_t, + struct netstack *); +struct pipex_session *pipex_l2tp_userland_lookup_session_ipv4(struct mbuf *, + struct in_addr); +struct pipex_session *pipex_l2tp_userland_lookup_session_ipv6(struct mbuf *, + struct in6_addr); +struct mbuf *pipex_l2tp_userland_output(struct mbuf *, + struct pipex_session *); +void pipex_rele_session(struct pipex_session *); +int pipex_ioctl(void *, u_long, caddr_t); +void pipex_session_init_mppe_recv(struct pipex_session *, + int, int, u_char *); +void pipex_session_init_mppe_send(struct pipex_session *, + int, int, u_char *); +__END_DECLS + +#endif /* _KERNEL */ +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/pipex_local.h b/lib/libc/include/generic-openbsd/net/pipex_local.h new file mode 100644 index 000000000000..9fe5ec3d6773 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/pipex_local.h @@ -0,0 +1,478 @@ +/* $OpenBSD: pipex_local.h,v 1.54 2025/03/02 21:28:32 bluhm Exp $ */ + +/* + * Copyright (c) 2009 Internet Initiative Japan Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +extern struct mutex pipex_list_mtx; + +#define PIPEX_PPTP 1 +#define PIPEX_L2TP 1 +#define PIPEX_PPPOE 1 +#define PIPEX_MPPE 1 + +#define PIPEX_REWIND_LIMIT 64 + +#define PIPEX_ENABLED 0x0001 + +/* compile time option constants */ +#ifndef PIPEX_MAX_SESSION +#define PIPEX_MAX_SESSION 512 +#endif +#define PIPEX_HASH_DIV 8 +#define PIPEX_HASH_SIZE (PIPEX_MAX_SESSION/PIPEX_HASH_DIV) +#define PIPEX_HASH_MASK (PIPEX_HASH_SIZE-1) +#define PIPEX_CLOSE_TIMEOUT 30 +#define PIPEX_PPPMINLEN 5 + /* minimum PPP header length is 1 and minimum ppp payload length is 4 */ + +#define PIPEX_MPPE_NOLDKEY 64 /* should be power of two */ +#define PIPEX_MPPE_OLDKEYMASK (PIPEX_MPPE_NOLDKEY - 1) + +/* + * Locks used to protect struct members: + * A atomic operation + * I immutable after creation + * L pipex_list_mtx + * s this pipex_session' `pxs_mtx' + * m this pipex_mppe' `pxm_mtx' + */ + +#ifdef PIPEX_MPPE +/* mppe rc4 key */ +struct pipex_mppe { + struct mutex pxm_mtx; + u_int flags; /* [m] flags, see below */ +#define PIPEX_MPPE_STATELESS 0x01 /* [I] key change mode */ +#define PIPEX_MPPE_RESETREQ 0x02 /* [m] */ + + int16_t keylenbits; /* [I] key length */ + int16_t keylen; /* [I] */ + uint16_t coher_cnt; /* [m] coherency counter */ + struct rc4_ctx rc4ctx; /* [m] */ + u_char master_key[PIPEX_MPPE_KEYLEN]; /* [m] master key of MPPE */ + u_char session_key[PIPEX_MPPE_KEYLEN]; /* [m] session key of MPPE */ + u_char (*old_session_keys)[PIPEX_MPPE_KEYLEN]; + /* [m] old session keys */ +}; +#endif /* PIPEX_MPPE */ + +#ifdef PIPEX_PPPOE +struct pipex_pppoe_session { + u_int over_ifidx; /* [I] ether interface */ +}; +#endif /* PIPEX_PPPOE */ + +#ifdef PIPEX_PPTP +struct pipex_pptp_session { + /* sequence number gap between pipex and userland */ + int32_t snd_gap; /* [s] gap of our sequence */ + int32_t rcv_gap; /* [s] gap of peer's sequence */ + int32_t ul_snd_una; /* [s] userland send acked seq */ + + uint32_t snd_nxt; /* [s] send next */ + uint32_t rcv_nxt; /* [s] receive next */ + uint32_t snd_una; /* [s] send acked sequence */ + uint32_t rcv_acked; /* [s] recv acked sequence */ + + int winsz; /* [I] windows size */ + int maxwinsz; /* [I] max windows size */ + int peer_maxwinsz; /* [I] peer's max windows size */ +}; +#endif /* PIPEX_PPTP */ + +#ifdef PIPEX_L2TP +/* + * L2TP Packet headers + * + * +----+---+----+---+----+--------+ + * |IPv4|UDP|L2TP|PPP|IPv4|Data....| + * +----+---+----+---+----+--------+ + * + * Session Data + * + * IPv4 IP_SRC <-- required for encap. + * IP_DST <-- required for encap. + * + * UDP SPort <-- required for encap. + * DPort <-- required for encap. + * + * L2TP FLAGS <-- only handle TYPE=0 (data) + * Tunnel ID <-- ID per tunnel(NOT a key: differed from RFC) + * Session ID <-- ID per PPP session(KEY to look up session) + * Ns(SEND SEQ) <-- sequence number of packet to send(opt.) + * Nr(RECV SEQ) <-- sequence number of packet to recv(opt.) + * + * - Recv Session lookup key is (Tunnnel ID, Session ID) in RFC. + * - BUT (Session ID) in PIPEX. SESSION ID MUST BE UNIQ. + * + * - We must update (Ns, Nr) of data channel. and we must adjust (Ns, Nr) + * in packets from/to userland. + */ +struct pipex_l2tp_session { + /* KEYS for session lookup (host byte order) */ + uint16_t tunnel_id; /* [I] our tunnel-id */ + uint16_t peer_tunnel_id; /* [I] peer's tunnel-id */ + + uint32_t option_flags; /* [I] protocol options */ + uint32_t ipsecflowinfo; /* [I] IPsec SA flow id for NAT-T */ + + int16_t ns_gap; /* [s] gap between userland and pipex */ + int16_t nr_gap; /* [s] gap between userland and pipex */ + uint16_t ul_ns_una; /* [s] unacked sequence number (userland) */ + + uint16_t ns_nxt; /* [s] next sequence number to send */ + uint16_t ns_una; /* [s] unacked sequence number to send */ + + uint16_t nr_nxt; /* [s] next sequence number to recv */ + uint16_t nr_acked; /* [s] acked sequence number to recv */ +}; +#endif /* PIPEX_L2TP */ + +struct cpumem; + +/* special iterator session */ +struct pipex_session_iterator { + /* Fields below should be in sync with pipex_session structure */ + struct radix_node ps4_rn[2]; + u_int flags; /* [I] flags, see below */ + LIST_ENTRY(pipex_session) session_list; /* [L] all session chain */ +}; + +/* pppac ip-extension session table */ +struct pipex_session { + struct radix_node ps4_rn[2]; + /* [L] tree glue, and other values */ + u_int flags; /* [I] flags, see below */ +#define PIPEX_SFLAGS_MULTICAST 0x01 /* virtual entry for multicast */ +#define PIPEX_SFLAGS_PPPX 0x02 /* interface is + point2point(pppx) */ +#define PIPEX_SFLAGS_ITERATOR 0x04 /* iterator session */ + + LIST_ENTRY(pipex_session) session_list; /* [L] all session chain */ + LIST_ENTRY(pipex_session) state_list; /* [L] state list chain */ + LIST_ENTRY(pipex_session) id_chain; /* [L] id hash chain */ + LIST_ENTRY(pipex_session) peer_addr_chain; + /* [L] peer's address hash chain */ + struct refcnt pxs_refcnt; + struct mutex pxs_mtx; + + u_int state; /* [L] pipex session state */ +#define PIPEX_STATE_INITIAL 0x0000 +#define PIPEX_STATE_OPENED 0x0001 +#define PIPEX_STATE_CLOSE_WAIT 0x0002 +#define PIPEX_STATE_CLOSE_WAIT2 0x0003 +#define PIPEX_STATE_CLOSED 0x0004 + + uint32_t idle_time; /* [L] idle time in seconds */ + + uint16_t protocol; /* [I] tunnel protocol (PK) */ + uint16_t session_id; /* [I] session-id (PK) */ + uint16_t peer_session_id; /* [I] peer's session-id */ + uint16_t peer_mru; /* [I] peer's MRU */ + uint32_t timeout_sec; /* [I] idle timeout */ + int ppp_id; /* [I] PPP id */ + + struct sockaddr_in ip_address; /* [I] remote address (AK) */ + struct sockaddr_in ip_netmask; /* [I] remote address mask (AK) */ + struct sockaddr_in6 ip6_address; /* [I] remote IPv6 address */ + int ip6_prefixlen; /* [I] remote IPv6 prefixlen */ + + u_int ifindex; /* [A] interface index */ + void *ownersc; /* [I] owner context */ + + uint32_t ppp_flags; /* [I] configure flags */ +#ifdef PIPEX_MPPE + int ccp_id; /* [s] CCP packet id */ + struct pipex_mppe + mppe_recv, /* MPPE context for incoming */ + mppe_send; /* MPPE context for outgoing */ +#endif /*PIPEXMPPE */ + + struct cpumem *stat_counters; + + union { +#ifdef PIPEX_PPPOE + struct pipex_pppoe_session pppoe; /* context for PPPoE */ +#endif /* PIPEX_PPPOE */ +#ifdef PIPEX_PPTP + struct pipex_pptp_session pptp; /* context for PPTP */ +#endif /* PIPEX_PPTP */ +#ifdef PIPEX_L2TP + struct pipex_l2tp_session l2tp; +#endif + char _proto_unknown[0]; + } proto; + union { + struct sockaddr sa; + struct sockaddr_in sin4; + struct sockaddr_in6 sin6; + struct sockaddr_dl sdl; + } peer, local; /* [I] */ +}; + +enum pipex_counters { + pxc_ipackets, /* packets received from tunnel */ + pxc_ierrors, /* error packets received from tunnel */ + pxc_ibytes, /* number of received bytes from tunnel */ + pxc_opackets, /* packets sent to tunnel */ + pxc_oerrors, /* error packets on sending to tunnel */ + pxc_obytes, /* number of sent bytes to tunnel */ + pxc_ncounters +}; + +/* gre header */ +struct pipex_gre_header { + uint16_t flags; /* flags and version*/ +#define PIPEX_GRE_KFLAG 0x2000 /* keys present */ +#define PIPEX_GRE_SFLAG 0x1000 /* seq present */ +#define PIPEX_GRE_AFLAG 0x0080 /* ack present */ +#define PIPEX_GRE_VER 0x0001 /* gre version code */ +#define PIPEX_GRE_VERMASK 0x0007 /* gre version mask */ +#define PIPEX_GRE_UNUSEDFLAGS 0xcf78 /* unused at pptp. set 0 in rfc2637 */ + + uint16_t type; +#define PIPEX_GRE_PROTO_PPP 0x880b /* gre/ppp */ + + uint16_t len; /* length not include gre header */ + uint16_t call_id; /* call_id */ +} __packed; + +/* pppoe header */ +struct pipex_pppoe_header { + uint8_t vertype; /* version and type */ +#define PIPEX_PPPOE_VERTYPE 0x11 /* version and type code */ + + uint8_t code; /* code */ +#define PIPEX_PPPOE_CODE_SESSION 0x00 /* code session */ + + uint16_t session_id; /* session id */ + uint16_t length; /* length */ +} __packed; + +/* l2tp header */ +struct pipex_l2tp_header { + uint16_t flagsver; +#define PIPEX_L2TP_FLAG_MASK 0xfff0 +#define PIPEX_L2TP_FLAG_TYPE 0x8000 +#define PIPEX_L2TP_FLAG_LENGTH 0x4000 +#define PIPEX_L2TP_FLAG_SEQUENCE 0x0800 +#define PIPEX_L2TP_FLAG_OFFSET 0x0200 +#define PIPEX_L2TP_FLAG_PRIORITY 0x0100 +#define PIPEX_L2TP_VER_MASK 0x000f +#define PIPEX_L2TP_VER 2 + uint16_t length; /* optional */ + uint16_t tunnel_id; + uint16_t session_id; + /* can be followed by option header */ +} __packed; + +/* l2tp option header */ +struct pipex_l2tp_seq_header { + uint16_t ns; + uint16_t nr; +} __packed; + +struct pipex_l2tp_offset_header { + uint16_t offset_size; + /* uint8_t offset_pad[] */ +} __packed; + +#ifdef PIPEX_DEBUG +#define PIPEX_DBG(a) if (pipex_debug & 1) pipex_session_log a +/* #define PIPEX_MPPE_DBG(a) if (pipex_debug & 1) pipex_session_log a */ +#define PIPEX_MPPE_DBG(a) +#else +#define PIPEX_DBG(a) +#define PIPEX_MPPE_DBG(a) +#endif /* PIPEX_DEBUG */ + +LIST_HEAD(pipex_hash_head, pipex_session); + +extern struct pipex_hash_head pipex_session_list; +extern struct pipex_hash_head pipex_close_wait_list; +extern struct pipex_hash_head pipex_peer_addr_hashtable[]; +extern struct pipex_hash_head pipex_id_hashtable[]; +extern struct pool pipex_session_pool; + + +#define PIPEX_ID_HASHTABLE(key) \ + (&pipex_id_hashtable[(key) & PIPEX_HASH_MASK]) +#define PIPEX_PEER_ADDR_HASHTABLE(key) \ + (&pipex_peer_addr_hashtable[(key) & PIPEX_HASH_MASK]) + +#define GETCHAR(c, cp) do { \ + (c) = *(cp)++; \ +} while (0) + +#define PUTCHAR(s, cp) do { \ + *(cp)++ = (u_char)(s); \ +} while (0) + +#define GETSHORT(s, cp) do { \ + (s) = *(cp)++ << 8; \ + (s) |= *(cp)++; \ +} while (0) + +#define PUTSHORT(s, cp) do { \ + *(cp)++ = (u_char) ((s) >> 8); \ + *(cp)++ = (u_char) (s); \ +} while (0) + +#define GETLONG(l, cp) do { \ + (l) = *(cp)++ << 8; \ + (l) |= *(cp)++; (l) <<= 8; \ + (l) |= *(cp)++; (l) <<= 8; \ + (l) |= *(cp)++; \ +} while (0) + +#define PUTLONG(l, cp) do { \ + *(cp)++ = (u_char) ((l) >> 24); \ + *(cp)++ = (u_char) ((l) >> 16); \ + *(cp)++ = (u_char) ((l) >> 8); \ + *(cp)++ = (u_char) (l); \ +} while (0) + +#define PIPEX_PULLUP(m0, l) \ + if ((m0)->m_len < (l)) { \ + if ((m0)->m_pkthdr.len < (l)) { \ + PIPEX_DBG((NULL, LOG_DEBUG, \ + "<%s> received packet is too short.", \ + __func__)); \ + m_freem(m0); \ + (m0) = NULL; \ + } else { \ + (m0) = m_pullup((m0), (l)); \ + KASSERT((m0) != NULL); \ + } \ + } +#define PIPEX_SEEK_NEXTHDR(ptr, len, t) \ + ((t) (((char *)ptr) + len)) +#define SEQ32_LT(a,b) ((int32_t)((a) - (b)) < 0) +#define SEQ32_LE(a,b) ((int32_t)((a) - (b)) <= 0) +#define SEQ32_GT(a,b) ((int32_t)((a) - (b)) > 0) +#define SEQ32_GE(a,b) ((int32_t)((a) - (b)) >= 0) +#define SEQ32_SUB(a,b) ((int32_t)((a) - (b))) + +#define SEQ16_LT(a,b) ((int16_t)((a) - (b)) < 0) +#define SEQ16_LE(a,b) ((int16_t)((a) - (b)) <= 0) +#define SEQ16_GT(a,b) ((int16_t)((a) - (b)) > 0) +#define SEQ16_GE(a,b) ((int16_t)((a) - (b)) >= 0) +#define SEQ16_SUB(a,b) ((int16_t)((a) - (b))) + +#define pipex_session_is_acfc_accepted(s) \ + (((s)->ppp_flags & PIPEX_PPP_ACFC_ACCEPTED)? 1 : 0) +#define pipex_session_is_pfc_accepted(s) \ + (((s)->ppp_flags & PIPEX_PPP_PFC_ACCEPTED)? 1 : 0) +#define pipex_session_is_acfc_enabled(s) \ + (((s)->ppp_flags & PIPEX_PPP_ACFC_ENABLED)? 1 : 0) +#define pipex_session_is_pfc_enabled(s) \ + (((s)->ppp_flags & PIPEX_PPP_PFC_ENABLED)? 1 : 0) +#define pipex_session_has_acf(s) \ + (((s)->ppp_flags & PIPEX_PPP_HAS_ACF)? 1 : 0) +#define pipex_session_is_mppe_accepted(s) \ + (((s)->ppp_flags & PIPEX_PPP_MPPE_ACCEPTED)? 1 : 0) +#define pipex_session_is_mppe_enabled(s) \ + (((s)->ppp_flags & PIPEX_PPP_MPPE_ENABLED)? 1 : 0) +#define pipex_session_is_mppe_required(s) \ + (((s)->ppp_flags & PIPEX_PPP_MPPE_REQUIRED)? 1 : 0) +#define pipex_mppe_rc4_keybits(r) ((r)->keylen << 3) +#define pipex_session_is_l2tp_data_sequencing_on(s) \ + (((s)->proto.l2tp.option_flags & PIPEX_L2TP_USE_SEQUENCING) ? 1 : 0) + +#define PIPEX_IPGRE_HDRLEN (sizeof(struct ip) + sizeof(struct pipex_gre_header)) +#define PIPEX_TCP_OPTLEN 40 +#define PIPEX_L2TP_MINLEN 8 + +void pipex_destroy_all_sessions (void *); +int pipex_init_session(struct pipex_session **, + struct pipex_session_req *); +int pipex_link_session(struct pipex_session *, + struct ifnet *, void *); +void pipex_unlink_session(struct pipex_session *); +void pipex_unlink_session_locked(struct pipex_session *); +void pipex_export_session_stats(struct pipex_session *, + struct pipex_statistics *); +int pipex_get_stat (struct pipex_session_stat_req *, + void *); +int pipex_get_closed (struct pipex_session_list_req *, + void *); +struct pipex_session *pipex_lookup_by_ip_address_locked (struct in_addr); +struct pipex_session *pipex_lookup_by_ip_address (struct in_addr); +struct pipex_session *pipex_lookup_by_session_id_locked (int, int); +struct pipex_session *pipex_lookup_by_session_id (int, int); +void pipex_ip_output(struct mbuf *, struct pipex_session *); +void pipex_ppp_output(struct mbuf *, struct pipex_session *, + int); +int pipex_ppp_proto(struct mbuf *, struct pipex_session *, + int, int *); +void pipex_ppp_input(struct mbuf *, struct pipex_session *, + int, struct netstack *); +void pipex_ip_input(struct mbuf *, struct pipex_session *, + struct netstack *); +void pipex_ip6_input(struct mbuf *, struct pipex_session *, + struct netstack *); +struct mbuf *pipex_common_input(struct pipex_session *, + struct mbuf *, int, int, int, struct netstack *); + +#ifdef PIPEX_PPPOE +void pipex_pppoe_output (struct mbuf *, struct pipex_session *); +#endif + +#ifdef PIPEX_PPTP +void pipex_pptp_output (struct mbuf *, struct pipex_session *, int, int); +struct pipex_session *pipex_pptp_userland_lookup_session(struct mbuf *, struct sockaddr *); +#endif + +#ifdef PIPEX_L2TP +void pipex_l2tp_output (struct mbuf *, struct pipex_session *); +#endif + +#ifdef PIPEX_MPPE +void pipex_mppe_init (struct pipex_mppe *, int, int, u_char *, int); +void GetNewKeyFromSHA (u_char *, u_char *, int, u_char *); +void pipex_mppe_reduce_key (struct pipex_mppe *); +void mppe_key_change (struct pipex_mppe *); +struct mbuf *pipex_mppe_input (struct mbuf *, + struct pipex_session *); +struct mbuf *pipex_mppe_output (struct mbuf *, + struct pipex_session *, uint16_t); +void pipex_ccp_input (struct mbuf *, struct pipex_session *); +int pipex_ccp_output (struct pipex_session *, int, int); +#endif + +struct mbuf *adjust_tcp_mss (struct mbuf *, int); +struct mbuf *ip_is_idle_packet (struct mbuf *, int *); +void pipex_session_log (struct pipex_session *, int, const char *, ...) __attribute__((__format__(__printf__,3,4))); +uint32_t pipex_sockaddr_hash_key(struct sockaddr *); +int pipex_sockaddr_compar_addr(struct sockaddr *, struct sockaddr *); +void pipex_timer_start (void); +void pipex_timer_stop (void); +void pipex_timer (void *); +struct pipex_session *pipex_iterator(struct pipex_session *, + struct pipex_session_iterator *, void *); \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/ppp-comp.h b/lib/libc/include/generic-openbsd/net/ppp-comp.h new file mode 100644 index 000000000000..c798a8f904ad --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/ppp-comp.h @@ -0,0 +1,173 @@ +/* $OpenBSD: ppp-comp.h,v 1.8 2002/09/13 00:12:07 deraadt Exp $ */ + +/* + * ppp-comp.h - Definitions for doing PPP packet compression. + * + * Copyright (c) 1989-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _NET_PPP_COMP_H_ +#define _NET_PPP_COMP_H_ + +/* + * The following symbols control whether we include code for + * various compression methods. + */ +#ifndef DO_BSD_COMPRESS +#define DO_BSD_COMPRESS 1 /* by default, include BSD-Compress */ +#endif +#ifndef DO_DEFLATE +#define DO_DEFLATE 1 /* by default, include Deflate */ +#endif +#define DO_PREDICTOR_1 0 +#define DO_PREDICTOR_2 0 + +/* + * Structure giving methods for compression/decompression. + */ +#ifdef PACKETPTR +struct compressor { + int compress_proto; /* CCP compression protocol number */ + + /* Allocate space for a compressor (transmit side) */ + void *(*comp_alloc)(u_char *options, int opt_len); + /* Free space used by a compressor */ + void (*comp_free)(void *state); + /* Initialize a compressor */ + int (*comp_init)(void *state, u_char *options, int opt_len, + int unit, int hdrlen, int debug); + /* Reset a compressor */ + void (*comp_reset)(void *state); + /* Compress a packet */ + int (*compress)(void *state, PACKETPTR *mret, + PACKETPTR mp, int orig_len, int max_len); + /* Return compression statistics */ + void (*comp_stat)(void *state, struct compstat *stats); + + /* Allocate space for a decompressor (receive side) */ + void *(*decomp_alloc)(u_char *options, int opt_len); + /* Free space used by a decompressor */ + void (*decomp_free)(void *state); + /* Initialize a decompressor */ + int (*decomp_init)(void *state, u_char *options, int opt_len, + int unit, int hdrlen, int mru, int debug); + /* Reset a decompressor */ + void (*decomp_reset)(void *state); + /* Decompress a packet. */ + int (*decompress)(void *state, PACKETPTR mp, + PACKETPTR *dmpp); + /* Update state for an incompressible packet received */ + void (*incomp)(void *state, PACKETPTR mp); + /* Return decompression statistics */ + void (*decomp_stat)(void *state, struct compstat *stats); +}; +#endif /* PACKETPTR */ + +/* + * Return values for decompress routine. + * We need to make these distinctions so that we can disable certain + * useful functionality, namely sending a CCP reset-request as a result + * of an error detected after decompression. This is to avoid infringing + * a patent held by Motorola. + * Don't you just lurve software patents. + */ +#define DECOMP_OK 0 /* everything went OK */ +#define DECOMP_ERROR 1 /* error detected before decomp. */ +#define DECOMP_FATALERROR 2 /* error detected after decomp. */ + +/* + * CCP codes. + */ +#define CCP_CONFREQ 1 +#define CCP_CONFACK 2 +#define CCP_TERMREQ 5 +#define CCP_TERMACK 6 +#define CCP_RESETREQ 14 +#define CCP_RESETACK 15 + +/* + * Max # bytes for a CCP option + */ +#define CCP_MAX_OPTION_LENGTH 32 + +/* + * Parts of a CCP packet. + */ +#define CCP_CODE(dp) ((dp)[0]) +#define CCP_ID(dp) ((dp)[1]) +#define CCP_LENGTH(dp) (((dp)[2] << 8) + (dp)[3]) +#define CCP_HDRLEN 4 + +#define CCP_OPT_CODE(dp) ((dp)[0]) +#define CCP_OPT_LENGTH(dp) ((dp)[1]) +#define CCP_OPT_MINLEN 2 + +/* + * Definitions for BSD-Compress. + */ +#define CI_BSD_COMPRESS 21 /* config. option for BSD-Compress */ +#define CILEN_BSD_COMPRESS 3 /* length of config. option */ + +/* Macros for handling the 3rd byte of the BSD-Compress config option. */ +#define BSD_NBITS(x) ((x) & 0x1F) /* number of bits requested */ +#define BSD_VERSION(x) ((x) >> 5) /* version of option format */ +#define BSD_CURRENT_VERSION 1 /* current version number */ +#define BSD_MAKE_OPT(v, n) (((v) << 5) | (n)) + +#define BSD_MIN_BITS 9 /* smallest code size supported */ +#define BSD_MAX_BITS 15 /* largest code size supported */ + +/* + * Definitions for Deflate. + */ +#define CI_DEFLATE 26 /* config option for Deflate */ +#define CI_DEFLATE_DRAFT 24 /* value used in original draft RFC */ +#define CILEN_DEFLATE 4 /* length of its config option */ + +#define DEFLATE_MIN_SIZE 8 +#define DEFLATE_MAX_SIZE 15 +#define DEFLATE_METHOD_VAL 8 +#define DEFLATE_SIZE(x) (((x) >> 4) + DEFLATE_MIN_SIZE) +#define DEFLATE_METHOD(x) ((x) & 0x0F) +#define DEFLATE_MAKE_OPT(w) ((((w) - DEFLATE_MIN_SIZE) << 4) \ + + DEFLATE_METHOD_VAL) +#define DEFLATE_CHK_SEQUENCE 0 + +/* + * Definitions for other, as yet unsupported, compression methods. + */ +#define CI_PREDICTOR_1 1 /* config option for Predictor-1 */ +#define CILEN_PREDICTOR_1 2 /* length of its config option */ +#define CI_PREDICTOR_2 2 /* config option for Predictor-2 */ +#define CILEN_PREDICTOR_2 2 /* length of its config option */ + +#endif /* _NET_PPP_COMP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/ppp_defs.h b/lib/libc/include/generic-openbsd/net/ppp_defs.h new file mode 100644 index 000000000000..ac5bee937bbe --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/ppp_defs.h @@ -0,0 +1,170 @@ +/* $OpenBSD: ppp_defs.h,v 1.13 2002/09/13 00:12:07 deraadt Exp $ */ +/* $NetBSD: ppp_defs.h,v 1.1 1995/07/04 06:28:26 paulus Exp $ */ + +/* + * ppp_defs.h - PPP definitions. + * + * Copyright (c) 1989-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _PPP_DEFS_H_ +#define _PPP_DEFS_H_ + +/* + * The basic PPP frame. + */ +#define PPP_HDRLEN 4 /* octets for standard ppp header */ +#define PPP_FCSLEN 2 /* octets for FCS */ +#define PPP_MRU 1500 /* default MRU = max length of info field */ + +#define PPP_ADDRESS(p) (((u_char *)(p))[0]) +#define PPP_CONTROL(p) (((u_char *)(p))[1]) +#define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3]) + +/* + * Significant octet values. + */ +#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ +#define PPP_UI 0x03 /* Unnumbered Information */ +#define PPP_FLAG 0x7e /* Flag Sequence */ +#define PPP_ESCAPE 0x7d /* Asynchronous Control Escape */ +#define PPP_TRANS 0x20 /* Asynchronous transparency modifier */ + +/* + * Protocol field values. + */ +#define PPP_IP 0x21 /* Internet Protocol */ +#define PPP_XNS 0x25 /* Xerox NS */ +#define PPP_AT 0x29 /* AppleTalk Protocol */ +#define PPP_IPX 0x2b /* Internetwork Packet Exchange */ +#define PPP_VJC_COMP 0x2d /* VJ compressed TCP */ +#define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */ +#define PPP_IPV6 0x57 /* Internet Protocol Version 6 */ +#define PPP_COMP 0xfd /* compressed packet */ +#define PPP_IPCP 0x8021 /* IP Control Protocol */ +#define PPP_ATCP 0x8029 /* AppleTalk Control Protocol */ +#define PPP_IPXCP 0x802b /* IPX Control Protocol */ +#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */ +#define PPP_CCP 0x80fd /* Compression Control Protocol */ +#define PPP_LCP 0xc021 /* Link Control Protocol */ +#define PPP_PAP 0xc023 /* Password Authentication Protocol */ +#define PPP_LQR 0xc025 /* Link Quality Report protocol */ +#define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */ +#define PPP_CBCP 0xc029 /* Callback Control Protocol */ + +/* + * Values for FCS calculations. + */ +#define PPP_INITFCS 0xffff /* Initial FCS value */ +#define PPP_GOODFCS 0xf0b8 /* Good final FCS value */ +#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff]) + +/* + * A 32-bit unsigned integral type. + */ +#ifndef __BIT_TYPES_DEFINED__ +#ifdef UINT32_T +typedef UINT32_T u_int32_t; +#else +typedef unsigned int u_int32_t; +typedef unsigned short u_int16_t; +#endif +#endif + +/* + * Extended asyncmap - allows any character to be escaped. + */ +typedef u_int32_t ext_accm[8]; + +/* + * What to do with network protocol (NP) packets. + */ +enum NPmode { + NPMODE_PASS, /* pass the packet through */ + NPMODE_DROP, /* silently drop the packet */ + NPMODE_ERROR, /* return an error */ + NPMODE_QUEUE /* save it up for later. */ +}; + +/* + * Statistics. + */ +struct pppstat { + u_int ppp_ibytes; /* bytes received */ + u_int ppp_ipackets; /* packets received */ + u_int ppp_ierrors; /* receive errors */ + u_int ppp_obytes; /* bytes sent */ + u_int ppp_opackets; /* packets sent */ + u_int ppp_oerrors; /* transmit errors */ +}; + +struct vjstat { + u_int vjs_packets; /* outbound packets */ + u_int vjs_compressed; /* outbound compressed packets */ + u_int vjs_searches; /* searches for connection state */ + u_int vjs_misses; /* times couldn't find conn. state */ + u_int vjs_uncompressedin; /* inbound uncompressed packets */ + u_int vjs_compressedin; /* inbound compressed packets */ + u_int vjs_errorin; /* inbound unknown type packets */ + u_int vjs_tossed; /* inbound packets tossed because of error */ +}; + +struct ppp_stats { + struct pppstat p; /* basic PPP statistics */ + struct vjstat vj; /* VJ header compression statistics */ +}; + +struct compstat { + u_int unc_bytes; /* total uncompressed bytes */ + u_int unc_packets; /* total uncompressed packets */ + u_int comp_bytes; /* compressed bytes */ + u_int comp_packets; /* compressed packets */ + u_int inc_bytes; /* incompressible bytes */ + u_int inc_packets; /* incompressible packets */ + u_int ratio; /* recent compression ratio << 8 */ +}; + +struct ppp_comp_stats { + struct compstat c; /* packet compression statistics */ + struct compstat d; /* packet decompression statistics */ +}; + +/* + * The following structure records the time in seconds since + * the last NP packet was sent or received. + */ +struct ppp_idle { + time_t xmit_idle; /* time since last NP packet sent */ + time_t recv_idle; /* time since last NP packet received */ +}; + +#endif /* _PPP_DEFS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/radix.h b/lib/libc/include/generic-openbsd/net/radix.h new file mode 100644 index 000000000000..b16ea54f86c8 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/radix.h @@ -0,0 +1,112 @@ +/* $OpenBSD: radix.h,v 1.30 2017/06/19 09:42:45 mpi Exp $ */ +/* $NetBSD: radix.h,v 1.8 1996/02/13 22:00:37 christos Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)radix.h 8.2 (Berkeley) 10/31/94 + */ + +#ifndef _NET_RADIX_H_ +#define _NET_RADIX_H_ + +/* + * Radix search tree node layout. + */ + +struct radix_node { + struct radix_mask *rn_mklist; /* list of masks contained in subtree */ + struct radix_node *rn_p; /* parent */ + short rn_b; /* bit offset; -1-index(netmask) */ + char rn_bmask; /* node: mask for bit test*/ + u_char rn_flags; /* enumerated next */ +#define RNF_NORMAL 1 /* leaf contains normal route */ +#define RNF_ROOT 2 /* leaf is root leaf for tree */ +#define RNF_ACTIVE 4 /* This node is alive (for rtfree) */ + union { + struct { /* leaf only data: */ + caddr_t rn_Key; /* object of search */ + caddr_t rn_Mask; /* netmask, if present */ + struct radix_node *rn_Dupedkey; + } rn_leaf; + struct { /* node only data: */ + int rn_Off; /* where to start compare */ + struct radix_node *rn_L;/* progeny */ + struct radix_node *rn_R;/* progeny */ + } rn_node; + } rn_u; +}; + +#define rn_dupedkey rn_u.rn_leaf.rn_Dupedkey +#define rn_key rn_u.rn_leaf.rn_Key +#define rn_mask rn_u.rn_leaf.rn_Mask +#define rn_off rn_u.rn_node.rn_Off +#define rn_l rn_u.rn_node.rn_L +#define rn_r rn_u.rn_node.rn_R + +/* + * Annotations to tree concerning potential routes applying to subtrees. + */ + +struct radix_mask { + short rm_b; /* bit offset; -1-index(netmask) */ + char rm_unused; /* cf. rn_bmask */ + u_char rm_flags; /* cf. rn_flags */ + struct radix_mask *rm_mklist; /* more masks to try */ + union { + caddr_t rmu_mask; /* the mask */ + struct radix_node *rmu_leaf; /* for normal routes */ + } rm_rmu; + int rm_refs; /* # of references to this struct */ +}; + +#define rm_mask rm_rmu.rmu_mask +#define rm_leaf rm_rmu.rmu_leaf /* extra field would make 32 bytes */ + +struct radix_node_head { + struct radix_node *rnh_treetop; + int rnh_addrsize; /* permit, but not require fixed keys */ + int rnh_pktsize; /* permit, but not require fixed keys */ + struct radix_node rnh_nodes[3];/* empty tree for common case */ + u_int rnh_rtableid; +}; + +void rn_init(unsigned int); +int rn_inithead(void **, int); + +int rn_walktree(struct radix_node_head *, + int (*)(struct radix_node *, void *, u_int), void *); + +struct radix_node *rn_addroute(void *, void *, struct radix_node_head *, + struct radix_node [2], u_int8_t); +struct radix_node *rn_delete(void *, void *, struct radix_node_head *, + struct radix_node *); +struct radix_node *rn_lookup(void *, void *, struct radix_node_head *); +struct radix_node *rn_match(void *, struct radix_node_head *); + +#endif /* _NET_RADIX_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/route.h b/lib/libc/include/generic-openbsd/net/route.h new file mode 100644 index 000000000000..b37f7156dcb4 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/route.h @@ -0,0 +1,525 @@ +/* $OpenBSD: route.h,v 1.218 2025/07/14 08:48:51 dlg Exp $ */ +/* $NetBSD: route.h,v 1.9 1996/02/13 22:00:49 christos Exp $ */ + +/* + * Copyright (c) 1980, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)route.h 8.3 (Berkeley) 4/19/94 + */ + +#ifndef _NET_ROUTE_H_ +#define _NET_ROUTE_H_ + +/* + * Locks used to protect struct members in this file: + * I immutable after creation + * N net lock + * X exclusive net lock, or shared net lock + kernel lock + * R rtable lock + * r per route entry mutex rt_mtx + * L arp/nd6/etc lock for updates, net lock for reads + * T rttimer_mtx route timer lists + */ + +/* + * Kernel resident routing tables. + * + * The routing tables are initialized when interface addresses + * are set by making entries for all directly connected interfaces. + */ + +#ifdef _KERNEL +/* + * These numbers are used by reliable protocols for determining + * retransmission behavior and are included in the routing structure. + */ +struct rt_kmetrics { + u_int64_t rmx_pksent; /* packets sent using this route */ + int64_t rmx_expire; /* lifetime for route, e.g. redirect */ + u_int rmx_locks; /* Kernel must leave these values */ + u_int rmx_mtu; /* [a] MTU for this path */ +}; +#endif + +/* + * Huge version for userland compatibility. + */ +struct rt_metrics { + u_int64_t rmx_pksent; /* packets sent using this route */ + int64_t rmx_expire; /* lifetime for route, e.g. redirect */ + u_int rmx_locks; /* Kernel must leave these values */ + u_int rmx_mtu; /* MTU for this path */ + u_int rmx_refcnt; /* # references hold */ + /* some apps may still need these no longer used metrics */ + u_int rmx_hopcount; /* max hops expected */ + u_int rmx_recvpipe; /* inbound delay-bandwidth product */ + u_int rmx_sendpipe; /* outbound delay-bandwidth product */ + u_int rmx_ssthresh; /* outbound gateway buffer limit */ + u_int rmx_rtt; /* estimated round trip time */ + u_int rmx_rttvar; /* estimated rtt variance */ + u_int rmx_pad; +}; + +#ifdef _KERNEL +/* + * rmx_rtt and rmx_rttvar are stored as microseconds; + * RTTTOPRHZ(rtt) converts to a value suitable for use + * by a protocol slowtimo counter. + */ +#define RTM_RTTUNIT 1000000 /* units for rtt, rttvar, as units per sec */ +#define RTTTOPRHZ(r) ((r) / (RTM_RTTUNIT / PR_SLOWHZ)) + +#include +#include +#include + +struct rttimer; + +/* + * We distinguish between routes to hosts and routes to networks, + * preferring the former if available. For each route we infer + * the interface to use from the gateway address supplied when + * the route was entered. Routes that forward packets through + * gateways are marked with RTF_GATEWAY so that the output routines + * know to address the gateway rather than the ultimate destination. + * + * How the RT_gw union is used also depends on RTF_GATEWAY. With + * RTF_GATEWAY set, rt_gwroute points at the rtentry for the rt_gateway + * address. If RTF_GATEWAY is not set, rt_cachecnt contains the + * number of RTF_GATEWAY rtentry structs with their rt_gwroute pointing + * at this rtentry. + */ + +struct rtentry { + struct sockaddr *rt_dest; /* [I] destination */ + struct rtentry *rt_next; /* [R] next mpath entry to our dst */ + struct sockaddr *rt_gateway; /* [X] gateway address */ + struct ifaddr *rt_ifa; /* [N] interface addr to use */ + caddr_t rt_llinfo; /* [L] pointer to link level info or + an MPLS structure */ + struct rtentry *rt_gwroute; /* [X] rtentry for rt_gateway */ + struct rtentry *rt_parent; /* [N] if cloned, parent rtentry */ + LIST_HEAD(, rttimer) rt_timer; /* queue of timeouts for misc funcs */ + struct mutex rt_mtx; /* lock members of this struct */ + struct refcnt rt_refcnt; /* # held references */ + struct rt_kmetrics rt_rmx; /* metrics used by rx'ing protocols */ + unsigned int rt_cachecnt; /* [r] # gateway rtentry refs */ + unsigned int rt_ifidx; /* [N] interface to use */ + unsigned int rt_flags; /* [X] up/down?, host/net */ + int rt_plen; /* [I] prefix length */ + uint16_t rt_labelid; /* [N] route label ID */ + uint8_t rt_priority; /* [N] routing priority to use */ +}; +#define rt_use rt_rmx.rmx_pksent +#define rt_expire rt_rmx.rmx_expire +#define rt_locks rt_rmx.rmx_locks +#define rt_mtu rt_rmx.rmx_mtu + +#endif /* _KERNEL */ + +/* bitmask values for rtm_flags */ +#define RTF_UP 0x1 /* route usable */ +#define RTF_GATEWAY 0x2 /* destination is a gateway */ +#define RTF_HOST 0x4 /* host entry (net otherwise) */ +#define RTF_REJECT 0x8 /* host or net unreachable */ +#define RTF_DYNAMIC 0x10 /* created dynamically (by redirect) */ +#define RTF_MODIFIED 0x20 /* modified dynamically (by redirect) */ +#define RTF_DONE 0x40 /* message confirmed */ +#define RTF_CLONING 0x100 /* generate new routes on use */ +#define RTF_MULTICAST 0x200 /* route associated to a mcast addr. */ +#define RTF_LLINFO 0x400 /* generated by ARP or ND */ +#define RTF_STATIC 0x800 /* manually added */ +#define RTF_BLACKHOLE 0x1000 /* just discard pkts (during updates) */ +#define RTF_PROTO3 0x2000 /* protocol specific routing flag */ +#define RTF_PROTO2 0x4000 /* protocol specific routing flag */ +#define RTF_ANNOUNCE RTF_PROTO2 /* announce L2 entry */ +#define RTF_PROTO1 0x8000 /* protocol specific routing flag */ +#define RTF_CLONED 0x10000 /* this is a cloned route */ +#define RTF_CACHED 0x20000 /* cached by a RTF_GATEWAY entry */ +#define RTF_MPATH 0x40000 /* multipath route or operation */ +#define RTF_MPLS 0x100000 /* MPLS additional infos */ +#define RTF_LOCAL 0x200000 /* route to a local address */ +#define RTF_BROADCAST 0x400000 /* route associated to a bcast addr. */ +#define RTF_CONNECTED 0x800000 /* interface route */ +#define RTF_BFD 0x1000000 /* Link state controlled by BFD */ + +/* mask of RTF flags that are allowed to be modified by RTM_CHANGE */ +#define RTF_FMASK \ + (RTF_LLINFO | RTF_PROTO1 | RTF_PROTO2 | RTF_PROTO3 | RTF_BLACKHOLE | \ + RTF_REJECT | RTF_STATIC | RTF_MPLS | RTF_BFD) + +/* Routing priorities used by the different routing protocols */ +#define RTP_NONE 0 /* unset priority use sane default */ +#define RTP_LOCAL 1 /* local address routes (must be the highest) */ +#define RTP_CONNECTED 4 /* directly connected routes */ +#define RTP_STATIC 8 /* static routes base priority */ +#define RTP_EIGRP 28 /* EIGRP routes */ +#define RTP_OSPF 32 /* OSPF routes */ +#define RTP_ISIS 36 /* IS-IS routes */ +#define RTP_RIP 40 /* RIP routes */ +#define RTP_BGP 48 /* BGP routes */ +#define RTP_DEFAULT 56 /* routes that have nothing set */ +#define RTP_PROPOSAL_STATIC 57 +#define RTP_PROPOSAL_DHCLIENT 58 +#define RTP_PROPOSAL_SLAAC 59 +#define RTP_PROPOSAL_UMB 60 +#define RTP_PROPOSAL_PPP 61 +#define RTP_PROPOSAL_SOLICIT 62 /* request reply of all RTM_PROPOSAL */ +#define RTP_MAX 63 /* maximum priority */ +#define RTP_ANY 64 /* any of the above */ +#define RTP_MASK 0x7f +#define RTP_DOWN 0x80 /* route/link is down */ + +/* + * Routing statistics. + */ +struct rtstat { + u_int32_t rts_badredirect; /* bogus redirect calls */ + u_int32_t rts_dynamic; /* routes created by redirects */ + u_int32_t rts_newgateway; /* routes modified by redirects */ + u_int32_t rts_unreach; /* lookups which failed */ + u_int32_t rts_wildcard; /* lookups satisfied by a wildcard */ +}; + +/* + * Routing Table Info. + */ +struct rt_tableinfo { + u_short rti_tableid; /* routing table id */ + u_short rti_domainid; /* routing domain id */ +}; + +/* + * Structures for routing messages. + */ +struct rt_msghdr { + u_short rtm_msglen; /* to skip over non-understood messages */ + u_char rtm_version; /* future binary compatibility */ + u_char rtm_type; /* message type */ + u_short rtm_hdrlen; /* sizeof(rt_msghdr) to skip over the header */ + u_short rtm_index; /* index for associated ifp */ + u_short rtm_tableid; /* routing table id */ + u_char rtm_priority; /* routing priority */ + u_char rtm_mpls; /* MPLS additional infos */ + int rtm_addrs; /* bitmask identifying sockaddrs in msg */ + int rtm_flags; /* flags, incl. kern & message, e.g. DONE */ + int rtm_fmask; /* bitmask used in RTM_CHANGE message */ + pid_t rtm_pid; /* identify sender */ + int rtm_seq; /* for sender to identify action */ + int rtm_errno; /* why failed */ + u_int rtm_inits; /* which metrics we are initializing */ + struct rt_metrics rtm_rmx; /* metrics themselves */ +}; +/* overload no longer used field */ +#define rtm_use rtm_rmx.rmx_pksent + +#define RTM_VERSION 5 /* Up the ante and ignore older versions */ + +#define RTM_MAXSIZE 2048 /* Maximum size of an accepted route msg */ + +/* values for rtm_type */ +#define RTM_ADD 0x1 /* Add Route */ +#define RTM_DELETE 0x2 /* Delete Route */ +#define RTM_CHANGE 0x3 /* Change Metrics or flags */ +#define RTM_GET 0x4 /* Report Metrics */ +#define RTM_LOSING 0x5 /* Kernel Suspects Partitioning */ +#define RTM_REDIRECT 0x6 /* Told to use different route */ +#define RTM_MISS 0x7 /* Lookup failed on this address */ +#define RTM_RESOLVE 0xb /* req to resolve dst to LL addr */ +#define RTM_NEWADDR 0xc /* address being added to iface */ +#define RTM_DELADDR 0xd /* address being removed from iface */ +#define RTM_IFINFO 0xe /* iface going up/down etc. */ +#define RTM_IFANNOUNCE 0xf /* iface arrival/departure */ +#define RTM_DESYNC 0x10 /* route socket buffer overflow */ +#define RTM_INVALIDATE 0x11 /* Invalidate cache of L2 route */ +#define RTM_BFD 0x12 /* bidirectional forwarding detection */ +#define RTM_PROPOSAL 0x13 /* proposal for resolvd(8) */ +#define RTM_CHGADDRATTR 0x14 /* address attribute change */ +#define RTM_80211INFO 0x15 /* 80211 iface change */ +#define RTM_SOURCE 0x16 /* set source address */ + +#define RTV_MTU 0x1 /* init or lock _mtu */ +#define RTV_HOPCOUNT 0x2 /* init or lock _hopcount */ +#define RTV_EXPIRE 0x4 /* init or lock _expire */ +#define RTV_RPIPE 0x8 /* init or lock _recvpipe */ +#define RTV_SPIPE 0x10 /* init or lock _sendpipe */ +#define RTV_SSTHRESH 0x20 /* init or lock _ssthresh */ +#define RTV_RTT 0x40 /* init or lock _rtt */ +#define RTV_RTTVAR 0x80 /* init or lock _rttvar */ + +/* + * Bitmask values for rtm_addrs. + */ +#define RTA_DST 0x1 /* destination sockaddr present */ +#define RTA_GATEWAY 0x2 /* gateway sockaddr present */ +#define RTA_NETMASK 0x4 /* netmask sockaddr present */ +#define RTA_GENMASK 0x8 /* cloning mask sockaddr present */ +#define RTA_IFP 0x10 /* interface name sockaddr present */ +#define RTA_IFA 0x20 /* interface addr sockaddr present */ +#define RTA_AUTHOR 0x40 /* sockaddr for author of redirect */ +#define RTA_BRD 0x80 /* for NEWADDR, broadcast or p-p dest addr */ +#define RTA_SRC 0x100 /* source sockaddr present */ +#define RTA_SRCMASK 0x200 /* source netmask present */ +#define RTA_LABEL 0x400 /* route label present */ +#define RTA_BFD 0x800 /* bfd present */ +#define RTA_DNS 0x1000 /* DNS Servers sockaddr present */ +#define RTA_STATIC 0x2000 /* RFC 3442 encoded static routes present */ +#define RTA_SEARCH 0x4000 /* RFC 3397 encoded search path present */ + +/* + * Index offsets for sockaddr array for alternate internal encoding. + */ +#define RTAX_DST 0 /* destination sockaddr present */ +#define RTAX_GATEWAY 1 /* gateway sockaddr present */ +#define RTAX_NETMASK 2 /* netmask sockaddr present */ +#define RTAX_GENMASK 3 /* cloning mask sockaddr present */ +#define RTAX_IFP 4 /* interface name sockaddr present */ +#define RTAX_IFA 5 /* interface addr sockaddr present */ +#define RTAX_AUTHOR 6 /* sockaddr for author of redirect */ +#define RTAX_BRD 7 /* for NEWADDR, broadcast or p-p dest addr */ +#define RTAX_SRC 8 /* source sockaddr present */ +#define RTAX_SRCMASK 9 /* source netmask present */ +#define RTAX_LABEL 10 /* route label present */ +#define RTAX_BFD 11 /* bfd present */ +#define RTAX_DNS 12 /* DNS Server(s) sockaddr present */ +#define RTAX_STATIC 13 /* RFC 3442 encoded static routes present */ +#define RTAX_SEARCH 14 /* RFC 3397 encoded search path present */ +#define RTAX_MAX 15 /* size of array to allocate */ + +/* + * setsockopt defines used for the filtering. + */ +#define ROUTE_MSGFILTER 1 /* bitmask to specify which types should be + sent to the client. */ +#define ROUTE_TABLEFILTER 2 /* change routing table the socket is listening + on, RTABLE_ANY listens on all tables. */ +#define ROUTE_PRIOFILTER 3 /* only pass updates with a priority higher or + equal (actual value lower) to the specified + priority. */ +#define ROUTE_FLAGFILTER 4 /* do not pass updates for routes with flags + in this bitmask. */ + +#define ROUTE_FILTER(m) (1 << (m)) +#define RTABLE_ANY 0xffffffff + +#define RTLABEL_LEN 32 + +struct sockaddr_rtlabel { + u_int8_t sr_len; /* total length */ + sa_family_t sr_family; /* address family */ + char sr_label[RTLABEL_LEN]; +}; + +#define RTDNS_LEN 128 + +struct sockaddr_rtdns { + u_int8_t sr_len; /* total length */ + sa_family_t sr_family; /* address family */ + char sr_dns[RTDNS_LEN]; +}; + +#ifdef _KERNEL + +static inline struct sockaddr * +srtdnstosa(struct sockaddr_rtdns *sdns) +{ + return ((struct sockaddr *)(sdns)); +} + +#endif + +#define RTSTATIC_LEN 128 + +struct sockaddr_rtstatic { + u_int8_t sr_len; /* total length */ + sa_family_t sr_family; /* address family */ + char sr_static[RTSTATIC_LEN]; +}; + +#define RTSEARCH_LEN 128 + +struct sockaddr_rtsearch { + u_int8_t sr_len; /* total length */ + sa_family_t sr_family; /* address family */ + char sr_search[RTSEARCH_LEN]; +}; + +struct rt_addrinfo { + int rti_addrs; + const struct sockaddr *rti_info[RTAX_MAX]; + int rti_flags; + struct ifaddr *rti_ifa; + struct rt_msghdr *rti_rtm; + u_char rti_mpls; +}; + +#ifdef __BSD_VISIBLE + +#include + +/* + * A route consists of a destination address and a reference + * to a routing entry. These are often held by protocols + * in their control blocks, e.g. inpcb. + */ +struct route { + struct rtentry *ro_rt; + u_long ro_generation; + u_long ro_tableid; /* u_long because of alignment */ + union { + struct sockaddr ro_dstsa; + struct sockaddr_in ro_dstsin; + struct sockaddr_in6 ro_dstsin6; + }; + union { + struct in_addr ro_srcin; + struct in6_addr ro_srcin6; + }; +}; + +#endif /* __BSD_VISIBLE */ + +#ifdef _KERNEL + +#include + +enum rtstat_counters { + rts_badredirect, /* bogus redirect calls */ + rts_dynamic, /* routes created by redirects */ + rts_newgateway, /* routes modified by redirects */ + rts_unreach, /* lookups which failed */ + rts_wildcard, /* lookups satisfied by a wildcard */ + + rts_ncounters +}; + +static inline void +rtstat_inc(enum rtstat_counters c) +{ + extern struct cpumem *rtcounters; + + counters_inc(rtcounters, c); +} + +/* + * This structure, and the prototypes for the rt_timer_{init,remove_all, + * add,timer} functions all used with the kind permission of BSDI. + * These allow functions to be called for routes at specific times. + */ +struct rttimer_queue { + TAILQ_HEAD(, rttimer) rtq_head; /* [T] */ + LIST_ENTRY(rttimer_queue) rtq_link; /* [T] */ + void (*rtq_func) /* [I] callback */ + (struct rtentry *, u_int); + unsigned long rtq_count; /* [T] */ + int rtq_timeout; /* [T] */ +}; + +const char *rtlabel_id2name_locked(u_int16_t); +const char *rtlabel_id2name(u_int16_t, char *, size_t); +u_int16_t rtlabel_name2id(const char *); +struct sockaddr *rtlabel_id2sa(u_int16_t, struct sockaddr_rtlabel *); +void rtlabel_unref(u_int16_t); + +/* + * Values for additional argument to rtalloc() + */ +#define RT_RESOLVE 1 + +extern struct rtstat rtstat; +extern u_long rtgeneration; + +struct mbuf; +struct socket; +struct ifnet; +struct sockaddr_in6; +struct if_ieee80211_data; +struct bfd_config; + +void route_init(void); +int route_cache(struct route *, const struct in_addr *, + const struct in_addr *, u_int); +struct rtentry *route_mpath(struct route *, const struct in_addr *, + const struct in_addr *, u_int); +int route6_cache(struct route *, const struct in6_addr *, + const struct in6_addr *, u_int); +struct rtentry *route6_mpath(struct route *, const struct in6_addr *, + const struct in6_addr *, u_int); +void rtm_ifchg(struct ifnet *); +void rtm_ifannounce(struct ifnet *, int); +void rtm_bfd(struct bfd_config *); +void rtm_80211info(struct ifnet *, struct if_ieee80211_data *); +void rt_maskedcopy(struct sockaddr *, + struct sockaddr *, struct sockaddr *); +struct sockaddr *rt_plen2mask(const struct rtentry *, struct sockaddr_in6 *); +void rtm_send(struct rtentry *, int, int, unsigned int); +void rtm_addr(int, struct ifaddr *); +void rtm_miss(int, struct rt_addrinfo *, int, uint8_t, u_int, int, u_int); +void rtm_proposal(struct ifnet *, struct rt_addrinfo *, int, uint8_t); +int rt_setgate(struct rtentry *, const struct sockaddr *, u_int); +struct rtentry *rt_getll(struct rtentry *); + +void rt_timer_init(void); +int rt_timer_add(struct rtentry *, + struct rttimer_queue *, u_int); +void rt_timer_remove_all(struct rtentry *); +time_t rt_timer_get_expire(const struct rtentry *); +void rt_timer_queue_init(struct rttimer_queue *, int, + void(*)(struct rtentry *, u_int)); +void rt_timer_queue_change(struct rttimer_queue *, int); +void rt_timer_queue_flush(struct rttimer_queue *); +unsigned long rt_timer_queue_count(struct rttimer_queue *); +void rt_timer_timer(void *); + +int rt_mpls_set(struct rtentry *, const struct sockaddr *, uint8_t); +void rt_mpls_clear(struct rtentry *); + +int rtisvalid(struct rtentry *); +int rt_hash(struct rtentry *, const struct sockaddr *, uint32_t *); +struct rtentry *rtalloc_mpath(const struct sockaddr *, uint32_t *, u_int); +struct rtentry *rtalloc(const struct sockaddr *, int, unsigned int); +void rtref(struct rtentry *); +void rtfree(struct rtentry *); + +int rt_ifa_add(struct ifaddr *, int, struct sockaddr *, unsigned int); +int rt_ifa_del(struct ifaddr *, int, struct sockaddr *, unsigned int); +void rt_ifa_purge(struct ifaddr *); +int rt_ifa_addlocal(struct ifaddr *); +int rt_ifa_dellocal(struct ifaddr *); +void rtredirect(struct sockaddr *, struct sockaddr *, struct sockaddr *, + struct rtentry **, unsigned int); +int rtrequest(int, struct rt_addrinfo *, u_int8_t, struct rtentry **, + u_int); +int rtrequest_delete(struct rt_addrinfo *, u_int8_t, struct ifnet *, + struct rtentry **, u_int); +int rt_if_track(struct ifnet *); +int rt_if_linkstate_change(struct rtentry *, void *, u_int); +int rtdeletemsg(struct rtentry *, struct ifnet *, u_int); +#endif /* _KERNEL */ + +#endif /* _NET_ROUTE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/rtable.h b/lib/libc/include/generic-openbsd/net/rtable.h new file mode 100644 index 000000000000..23ba0b4a24ea --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/rtable.h @@ -0,0 +1,82 @@ +/* $OpenBSD: rtable.h,v 1.36 2025/07/15 09:55:49 dlg Exp $ */ + +/* + * Copyright (c) 2014-2016 Martin Pieuchot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _NET_RTABLE_H_ +#define _NET_RTABLE_H_ + +#include + +struct art; + +/* + * Locks used to protect struct members in this file: + * I immutable after creation + * N net lock + */ + +struct rtable { + struct rwlock r_lock; + struct art *r_art; /* [I] */ + unsigned int r_off; /* [I] Offset of key in bytes */ + + struct sockaddr *r_source; /* [N] use optional src addr */ +}; + +/* + * Newer routing table implementation based on ART (Allotment Routing + * Table). + */ + +#define rt_key(rt) ((rt)->rt_dest) +#define rt_plen(rt) ((rt)->rt_plen) +#define RT_ROOT(rt) (0) + +int rtable_satoplen(sa_family_t, const struct sockaddr *); + +void rtable_init(void); +int rtable_exists(unsigned int); +int rtable_empty(unsigned int); +int rtable_add(unsigned int); +unsigned int rtable_l2(unsigned int); +unsigned int rtable_loindex(unsigned int); +void rtable_l2set(unsigned int, unsigned int, unsigned int); + +int rtable_setsource(unsigned int, int, struct sockaddr *); +struct sockaddr *rtable_getsource(unsigned int, int); +void rtable_clearsource(unsigned int, struct sockaddr *); +struct rtentry *rtable_lookup(unsigned int, const struct sockaddr *, + const struct sockaddr *, const struct sockaddr *, uint8_t); +struct rtentry *rtable_match(unsigned int, const struct sockaddr *, + uint32_t *); +struct rtentry *rtable_iterate(struct rtentry *); +int rtable_insert(unsigned int, struct sockaddr *, + const struct sockaddr *, const struct sockaddr *, uint8_t, + struct rtentry *); +int rtable_delete(unsigned int, const struct sockaddr *, + const struct sockaddr *, struct rtentry *); +int rtable_walk(unsigned int, sa_family_t, struct rtentry **, + int (*)(struct rtentry *, void *, unsigned int), void *); +int rtable_read(unsigned int, sa_family_t, + int (*)(const struct rtentry *, void *, unsigned int), + void *); + +int rtable_mpath_capable(unsigned int, sa_family_t); +int rtable_mpath_reprio(unsigned int, struct sockaddr *, int, + uint8_t, struct rtentry *); + +#endif /* _NET_RTABLE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/slcompress.h b/lib/libc/include/generic-openbsd/net/slcompress.h new file mode 100644 index 000000000000..ee2a6e62580c --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/slcompress.h @@ -0,0 +1,167 @@ +/* $OpenBSD: slcompress.h,v 1.10 2017/01/24 10:08:30 krw Exp $ */ +/* $NetBSD: slcompress.h,v 1.11 1997/05/17 21:12:11 christos Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)slcompress.h 8.1 (Berkeley) 6/10/93 + */ + +/* + * Definitions for tcp compression routines. + * + * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: + * - Initial distribution. + */ + +#ifndef _NET_SLCOMPRESS_H_ +#define _NET_SLCOMPRESS_H_ + +#define MAX_STATES 16 /* must be > 2 and < 256 */ +#define MAX_HDR MLEN /* XXX 4bsd-ism: should really be 128 */ + +/* + * Compressed packet format: + * + * The first octet contains the packet type (top 3 bits), TCP + * 'push' bit, and flags that indicate which of the 4 TCP sequence + * numbers have changed (bottom 5 bits). The next octet is a + * conversation number that associates a saved IP/TCP header with + * the compressed packet. The next two octets are the TCP checksum + * from the original datagram. The next 0 to 15 octets are + * sequence number changes, one change per bit set in the header + * (there may be no changes and there are two special cases where + * the receiver implicitly knows what changed -- see below). + * + * There are 5 numbers which can change (they are always inserted + * in the following order): TCP urgent pointer, window, + * acknowledgement, sequence number and IP ID. (The urgent pointer + * is different from the others in that its value is sent, not the + * change in value.) Since typical use of SLIP links is biased + * toward small packets (see comments on MTU/MSS below), changes + * use a variable length coding with one octet for numbers in the + * range 1 - 255 and 3 octets (0, MSB, LSB) for numbers in the + * range 256 - 65535 or 0. (If the change in sequence number or + * ack is more than 65535, an uncompressed packet is sent.) + */ + +/* + * Packet types (must not conflict with IP protocol version) + * + * The top nibble of the first octet is the packet type. There are + * three possible types: IP (not proto TCP or tcp with one of the + * control flags set); uncompressed TCP (a normal IP/TCP packet but + * with the 8-bit protocol field replaced by an 8-bit connection id -- + * this type of packet syncs the sender & receiver); and compressed + * TCP (described above). + * + * LSB of 4-bit field is TCP "PUSH" bit (a worthless anachronism) and + * is logically part of the 4-bit "changes" field that follows. Top + * three bits are actual packet type. For backward compatibility + * and in the interest of conserving bits, numbers are chosen so the + * IP protocol version number (4) which normally appears in this nibble + * means "IP packet". + */ + +/* packet types */ +#define TYPE_IP 0x40 +#define TYPE_UNCOMPRESSED_TCP 0x70 +#define TYPE_COMPRESSED_TCP 0x80 +#define TYPE_ERROR 0x00 + +/* Bits in first octet of compressed packet */ +#define NEW_C 0x40 /* flag bits for what changed in a packet */ +#define NEW_I 0x20 +#define NEW_S 0x08 +#define NEW_A 0x04 +#define NEW_W 0x02 +#define NEW_U 0x01 + +/* reserved, special-case values of above */ +#define SPECIAL_I (NEW_S|NEW_W|NEW_U) /* echoed interactive traffic */ +#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U) /* unidirectional data */ +#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U) + +#define TCP_PUSH_BIT 0x10 + +#ifdef _KERNEL + +/* + * "state" data for each active tcp conversation on the wire. This is + * basically a copy of the entire IP/TCP header from the last packet + * we saw from the conversation together with a small identifier + * the transmit & receive ends of the line use to locate saved header. + */ +struct cstate { + struct cstate *cs_next; /* next most recently used cstate (xmit only) */ + u_int16_t cs_hlen; /* size of hdr (receive only) */ + u_char cs_id; /* connection # associated with this state */ + u_char cs_filler; + union { + char csu_hdr[MAX_HDR]; + struct ip csu_ip; /* ip/tcp hdr from most recent packet */ + } slcs_u; +}; +#define cs_ip slcs_u.csu_ip +#define cs_hdr slcs_u.csu_hdr + +/* + * all the state data for one serial line (we need one of these + * per line). + */ +struct slcompress { + struct cstate *last_cs; /* most recently used tstate */ + u_char last_recv; /* last rcvd conn. id */ + u_char last_xmit; /* last sent conn. id */ + u_int16_t flags; +#ifndef SL_NO_STATS + int sls_packets; /* outbound packets */ + int sls_compressed; /* outbound compressed packets */ + int sls_searches; /* searches for connection state */ + int sls_misses; /* times couldn't find conn. state */ + int sls_uncompressedin; /* inbound uncompressed packets */ + int sls_compressedin; /* inbound compressed packets */ + int sls_errorin; /* inbound unknown type packets */ + int sls_tossed; /* inbound packets tossed because of error */ +#endif + struct cstate tstate[MAX_STATES]; /* xmit connection states */ + struct cstate rstate[MAX_STATES]; /* receive connection states */ +}; +/* flag values */ +#define SLF_TOSS 1 /* tossing rcvd frames because of input err */ + +void sl_compress_init(struct slcompress *); +void sl_compress_setup(struct slcompress *, int); +u_int sl_compress_tcp(struct mbuf *, + struct ip *, struct slcompress *, int); +int sl_uncompress_tcp(u_char **, int, u_int, struct slcompress *); +int sl_uncompress_tcp_core(u_char *, int, int, u_int, + struct slcompress *, u_char **, u_int *); +#endif /* _KERNEL */ + +#endif /* _NET_SLCOMPRESS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/toeplitz.h b/lib/libc/include/generic-openbsd/net/toeplitz.h new file mode 100644 index 000000000000..91a079d6f81f --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/toeplitz.h @@ -0,0 +1,143 @@ +/* $OpenBSD: toeplitz.h,v 1.11 2023/05/17 10:22:17 dlg Exp $ */ + +/* + * Copyright (c) 2019 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_NET_TOEPLITZ_H_ +#define _SYS_NET_TOEPLITZ_H_ + +#include + +/* + * symmetric toeplitz + */ + +typedef uint16_t stoeplitz_key; + +struct stoeplitz_cache { + uint16_t bytes[256]; +}; + +static __unused inline uint16_t +stoeplitz_cache_entry(const struct stoeplitz_cache *scache, uint8_t byte) +{ + return (scache->bytes[byte]); +} + +void stoeplitz_cache_init(struct stoeplitz_cache *, stoeplitz_key); + +uint16_t stoeplitz_hash_ip4(const struct stoeplitz_cache *, + uint32_t, uint32_t); +uint16_t stoeplitz_hash_ip4port(const struct stoeplitz_cache *, + uint32_t, uint32_t, uint16_t, uint16_t); + +#ifdef INET6 +struct in6_addr; +uint16_t stoeplitz_hash_ip6(const struct stoeplitz_cache *, + const struct in6_addr *, const struct in6_addr *); +uint16_t stoeplitz_hash_ip6port(const struct stoeplitz_cache *, + const struct in6_addr *, const struct in6_addr *, + uint16_t, uint16_t); +#endif + +uint16_t stoeplitz_hash_eaddr(const struct stoeplitz_cache *, + const uint8_t *); + +/* hash a uint16_t in network byte order */ +static __unused inline uint16_t +stoeplitz_hash_n16(const struct stoeplitz_cache *scache, uint16_t n16) +{ + uint16_t hi, lo; + + hi = stoeplitz_cache_entry(scache, n16 >> 8); + lo = stoeplitz_cache_entry(scache, n16); + + return (hi ^ swap16(lo)); +} + +/* hash a uint32_t in network byte order */ +static __unused inline uint16_t +stoeplitz_hash_n32(const struct stoeplitz_cache *scache, uint32_t n32) +{ + return (stoeplitz_hash_n16(scache, n32 ^ (n32 >> 16))); +} + +/* hash a uint16_t in host byte order */ +static __unused inline uint16_t +stoeplitz_hash_h16(const struct stoeplitz_cache *scache, uint16_t h16) +{ + uint16_t lo, hi; + + lo = stoeplitz_cache_entry(scache, h16); + hi = stoeplitz_cache_entry(scache, h16 >> 8); + +#if _BYTE_ORDER == _BIG_ENDIAN + return (hi ^ swap16(lo)); +#else + return (swap16(hi) ^ lo); +#endif +} + +static __unused inline uint16_t +stoeplitz_hash_h32(const struct stoeplitz_cache *scache, uint32_t h32) +{ + return (stoeplitz_hash_h16(scache, h32 ^ (h32 >> 16))); +} + +static __unused inline uint16_t +stoeplitz_hash_h64(const struct stoeplitz_cache *scache, uint64_t h64) +{ + return (stoeplitz_hash_h32(scache, h64 ^ (h64 >> 32))); +} + +/* + * system provided symmetric toeplitz + */ + +#define STOEPLITZ_KEYSEED 0x6d5a + +void stoeplitz_init(void); + +void stoeplitz_to_key(void *, size_t) + __bounded((__buffer__, 1, 2)); + +extern const struct stoeplitz_cache *const stoeplitz_cache; + +#define stoeplitz_n16(_n16) \ + stoeplitz_hash_n16(stoeplitz_cache, (_n16)) +#define stoeplitz_n32(_n32) \ + stoeplitz_hash_n32(stoeplitz_cache, (_n32)) +#define stoeplitz_h16(_h16) \ + stoeplitz_hash_h16(stoeplitz_cache, (_h16)) +#define stoeplitz_h32(_h32) \ + stoeplitz_hash_h32(stoeplitz_cache, (_h32)) +#define stoeplitz_h64(_h64) \ + stoeplitz_hash_h64(stoeplitz_cache, (_h64)) +#define stoeplitz_port(_p) stoeplitz_n16((_p)) +#define stoeplitz_ip4(_sa4, _da4) \ + stoeplitz_hash_ip4(stoeplitz_cache, (_sa4), (_da4)) +#define stoeplitz_ip4port(_sa4, _da4, _sp, _dp) \ + stoeplitz_hash_ip4port(stoeplitz_cache, (_sa4), (_da4), (_sp), (_dp)) +#ifdef INET6 +#define stoeplitz_ip6(_sa6, _da6) \ + stoeplitz_hash_ip6(stoeplitz_cache, (_sa6), (_da6)) +#define stoeplitz_ip6port(_sa6, _da6, _sp, _dp) \ + stoeplitz_hash_ip6port(stoeplitz_cache, (_sa6), (_da6), (_sp), (_dp)) +#endif +#define stoeplitz_eaddr(_ea) \ + stoeplitz_hash_eaddr(stoeplitz_cache, (_ea)) + +#endif /* _SYS_NET_TOEPLITZ_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/trunklacp.h b/lib/libc/include/generic-openbsd/net/trunklacp.h new file mode 100644 index 000000000000..597e804bbcb3 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/trunklacp.h @@ -0,0 +1,316 @@ +/* $OpenBSD: trunklacp.h,v 1.14 2018/08/12 23:50:31 ccardenas Exp $ */ +/* $NetBSD: ieee8023ad_impl.h,v 1.2 2005/12/10 23:21:39 elad Exp $ */ + +/* + * Copyright (c)2005 YAMAMOTO Takashi, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/net/ieee8023ad_lacp.h,v 1.11 2008/03/17 01:26:44 thompsa Exp $ + */ + +#ifndef _NET_TRUNKLACP_H_ +#define _NET_TRUNKLACP_H_ + +/* + * IEEE802.3 slow protocols (on-wire) definitions. + * XXX should be elsewhere. + */ +#define SLOWPROTOCOLS_SUBTYPE_LACP 1 +#define SLOWPROTOCOLS_SUBTYPE_MARKER 2 + +/* + * default administrative values + */ +#define LACP_DEFAULT_MODE 1 /* Active Mode */ +#define LACP_DEFAULT_TIMEOUT 0 /* Slow Timeout */ +#define LACP_DEFAULT_SYSTEM_PRIO 0x8000 /* Medium Priority */ +#define LACP_LOW_SYSTEM_PRIO 0xffff +#define LACP_HIGH_SYSTEM_PRIO 0x0001 +#define LACP_DEFAULT_PORT_PRIO 0x8000 /* Medium Priority */ +#define LACP_LOW_PORT_PRIO 0xffff +#define LACP_HIGH_PORT_PRIO 0x0001 +#define LACP_DEFAULT_IFQ_PRIO 6 + +struct slowprothdr { + u_int8_t sph_subtype; + u_int8_t sph_version; +} __packed; + +/* TLV on-wire structure. */ +struct tlvhdr { + u_int8_t tlv_type; + u_int8_t tlv_length; + /* u_int8_t tlv_value[]; */ +} __packed; + +/* ... and our implementation. */ +#define TLV_SET(tlv, type, length) \ + do { \ + (tlv)->tlv_type = (type); \ + (tlv)->tlv_length = sizeof(*tlv) + (length); \ + } while (/*CONSTCOND*/0) + +struct tlv_template { + u_int8_t tmpl_type; + u_int8_t tmpl_length; +}; + +struct lacp_systemid { + u_int16_t lsi_prio; + u_int8_t lsi_mac[6]; +} __packed; + +struct lacp_portid { + u_int16_t lpi_prio; + u_int16_t lpi_portno; +} __packed; + +struct lacp_peerinfo { + struct lacp_systemid lip_systemid; + u_int16_t lip_key; + struct lacp_portid lip_portid; + u_int8_t lip_state; + u_int8_t lip_resv[3]; +} __packed; + +struct lacp_collectorinfo { + u_int16_t lci_maxdelay; + u_int8_t lci_resv[12]; +} __packed; + +struct lacpdu { + struct ether_header ldu_eh; + struct slowprothdr ldu_sph; + + struct tlvhdr ldu_tlv_actor; + struct lacp_peerinfo ldu_actor; + struct tlvhdr ldu_tlv_partner; + struct lacp_peerinfo ldu_partner; + struct tlvhdr ldu_tlv_collector; + struct lacp_collectorinfo ldu_collector; + struct tlvhdr ldu_tlv_term; + u_int8_t ldu_resv[50]; +} __packed; + +/* + * IEEE802.3ad marker protocol (on-wire) definitions. + */ +struct lacp_markerinfo { + u_int16_t mi_rq_port; + u_int8_t mi_rq_system[ETHER_ADDR_LEN]; + u_int32_t mi_rq_xid; + u_int8_t mi_pad[2]; +} __packed; + +#define LACP_STATE_BITS \ + "\020" \ + "\001ACTIVITY" \ + "\002TIMEOUT" \ + "\003AGGREGATION" \ + "\004SYNC" \ + "\005COLLECTING" \ + "\006DISTRIBUTING" \ + "\007DEFAULTED" \ + "\010EXPIRED" + +#ifdef _KERNEL + +/* + * IEEE802.3ad LACP implementation details. + */ +#define LACP_TIMER_CURRENT_WHILE 0 +#define LACP_TIMER_PERIODIC 1 +#define LACP_TIMER_WAIT_WHILE 2 +#define LACP_NTIMER 3 + +#define LACP_TIMER_ARM(port, timer, val) \ + (port)->lp_timer[(timer)] = (val) +#define LACP_TIMER_DISARM(port, timer) \ + (port)->lp_timer[(timer)] = 0 +#define LACP_TIMER_ISARMED(port, timer) \ + ((port)->lp_timer[(timer)] > 0) + +/* + * IEEE802.3ad LACP protocol definitions. + */ +#define LACP_STATE_ACTIVITY (1<<0) +#define LACP_STATE_TIMEOUT (1<<1) +#define LACP_STATE_AGGREGATION (1<<2) +#define LACP_STATE_SYNC (1<<3) +#define LACP_STATE_COLLECTING (1<<4) +#define LACP_STATE_DISTRIBUTING (1<<5) +#define LACP_STATE_DEFAULTED (1<<6) +#define LACP_STATE_EXPIRED (1<<7) + +#define LACP_PORT_NTT 0x00000001 +#define LACP_PORT_MARK 0x00000002 + +struct markerdu { + struct ether_header mdu_eh; + struct slowprothdr mdu_sph; + + struct tlvhdr mdu_tlv; + struct lacp_markerinfo mdu_info; + struct tlvhdr mdu_tlv_term; + u_int8_t mdu_resv[90]; +} __packed; + +#define MARKER_TYPE_INFO 0x01 +#define MARKER_TYPE_RESPONSE 0x02 + +enum lacp_selected { + LACP_UNSELECTED, + LACP_STANDBY, /* not used in this implementation */ + LACP_SELECTED, +}; + +enum lacp_mux_state { + LACP_MUX_DETACHED, + LACP_MUX_WAITING, + LACP_MUX_ATTACHED, + LACP_MUX_COLLECTING, + LACP_MUX_DISTRIBUTING, +}; + +#define LACP_MAX_PORTS 32 + +struct lacp_portmap { + int pm_count; + struct lacp_port *pm_map[LACP_MAX_PORTS]; +}; + +struct lacp_port { + TAILQ_ENTRY(lacp_port) lp_dist_q; + LIST_ENTRY(lacp_port) lp_next; + struct lacp_softc *lp_lsc; + struct trunk_port *lp_trunk; + struct ifnet *lp_ifp; + struct lacp_peerinfo lp_partner; + struct lacp_peerinfo lp_actor; + struct lacp_markerinfo lp_marker; +#define lp_state lp_actor.lip_state +#define lp_key lp_actor.lip_key +#define lp_systemid lp_actor.lip_systemid + struct timeval lp_last_lacpdu; + int lp_lacpdu_sent; + enum lacp_mux_state lp_mux_state; + enum lacp_selected lp_selected; + int lp_flags; + u_int lp_media; /* XXX redundant */ + int lp_timer[LACP_NTIMER]; + struct mbuf_queue lp_mq; + + struct lacp_aggregator *lp_aggregator; +}; + +struct lacp_aggregator { + TAILQ_ENTRY(lacp_aggregator) la_q; + int la_refcnt; /* num of ports which selected us */ + int la_nports; /* num of distributing ports */ + TAILQ_HEAD(, lacp_port) la_ports; /* distributing ports */ + struct lacp_peerinfo la_partner; + struct lacp_peerinfo la_actor; + int la_pending; /* number of ports in wait_while */ +}; + +struct lacp_admin_def { + u_int8_t lad_mode; /* active or passive */ + u_int8_t lad_timeout; /* fast or slow */ + u_int16_t lad_prio; /* system priority */ + u_int16_t lad_portprio; /* port priority */ + u_int8_t lad_ifqprio; /* ifq priority */ +}; + +struct lacp_softc { + struct trunk_softc *lsc_softc; + struct lacp_aggregator *lsc_active_aggregator; + TAILQ_HEAD(, lacp_aggregator) lsc_aggregators; + int lsc_suppress_distributing; + struct timeout lsc_transit_callout; + struct timeout lsc_callout; + LIST_HEAD(, lacp_port) lsc_ports; + struct lacp_portmap lsc_pmap[2]; + volatile u_int lsc_activemap; + SIPHASH_KEY lsc_hashkey; + struct task lsc_input; + struct lacp_admin_def lsc_admin_defaults; +#define lsc_mode lsc_admin_defaults.lad_mode +#define lsc_timeout lsc_admin_defaults.lad_timeout +#define lsc_sys_prio lsc_admin_defaults.lad_prio +#define lsc_port_prio lsc_admin_defaults.lad_portprio +#define lsc_ifq_prio lsc_admin_defaults.lad_ifqprio +}; + +#define LACP_TYPE_ACTORINFO 1 +#define LACP_TYPE_PARTNERINFO 2 +#define LACP_TYPE_COLLECTORINFO 3 + +/* timeout values (in sec) */ +#define LACP_FAST_PERIODIC_TIME (1) +#define LACP_SLOW_PERIODIC_TIME (30) +#define LACP_SHORT_TIMEOUT_TIME (3 * LACP_FAST_PERIODIC_TIME) +#define LACP_LONG_TIMEOUT_TIME (3 * LACP_SLOW_PERIODIC_TIME) +#define LACP_CHURN_DETECTION_TIME (60) +#define LACP_AGGREGATE_WAIT_TIME (2) +#define LACP_TRANSIT_DELAY 3000 /* in msec */ + +#define LACP_STATE_EQ(s1, s2, mask) \ + ((((s1) ^ (s2)) & (mask)) == 0) + +#define LACP_SYS_PRI(peer) (peer).lip_systemid.lsi_prio + +#define LACP_PORT(_lp) ((struct lacp_port *)(_lp)->tp_psc) +#define LACP_SOFTC(_sc) ((struct lacp_softc *)(_sc)->tr_psc) + +int lacp_input(struct trunk_port *, struct mbuf *); +struct trunk_port *lacp_select_tx_port(struct trunk_softc *, struct mbuf *); +int lacp_attach(struct trunk_softc *); +int lacp_detach(struct trunk_softc *); +void lacp_init(struct trunk_softc *); +void lacp_stop(struct trunk_softc *); +int lacp_port_create(struct trunk_port *); +void lacp_port_destroy(struct trunk_port *); +void lacp_linkstate(struct trunk_port *); +void lacp_req(struct trunk_softc *, caddr_t); +void lacp_portreq(struct trunk_port *, caddr_t); +u_int lacp_port_status(struct trunk_port *); + +/* following constants don't include terminating NUL */ +#define LACP_MACSTR_MAX (2*6 + 5) +#define LACP_SYSTEMPRIOSTR_MAX (4) +#define LACP_SYSTEMIDSTR_MAX (LACP_SYSTEMPRIOSTR_MAX + 1 + LACP_MACSTR_MAX) +#define LACP_PORTPRIOSTR_MAX (4) +#define LACP_PORTNOSTR_MAX (4) +#define LACP_PORTIDSTR_MAX (LACP_PORTPRIOSTR_MAX + 1 + LACP_PORTNOSTR_MAX) +#define LACP_KEYSTR_MAX (4) +#define LACP_PARTNERSTR_MAX \ + (1 + LACP_SYSTEMIDSTR_MAX + 1 + LACP_KEYSTR_MAX + 1 \ + + LACP_PORTIDSTR_MAX + 1) +#define LACP_LAGIDSTR_MAX \ + (1 + LACP_PARTNERSTR_MAX + 1 + LACP_PARTNERSTR_MAX + 1) +#define LACP_STATESTR_MAX (255) /* XXX */ + +#endif /* _KERNEL */ + +#endif /* _NET_TRUNKLACP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/wg_cookie.h b/lib/libc/include/generic-openbsd/net/wg_cookie.h new file mode 100644 index 000000000000..518b18a14a1b --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/wg_cookie.h @@ -0,0 +1,132 @@ +/* $OpenBSD: wg_cookie.h,v 1.2 2020/12/09 05:53:33 tb Exp $ */ +/* + * Copyright (C) 2015-2020 Jason A. Donenfeld . All Rights Reserved. + * Copyright (C) 2019-2020 Matt Dunwoodie + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __COOKIE_H__ +#define __COOKIE_H__ + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#define COOKIE_MAC_SIZE 16 +#define COOKIE_KEY_SIZE 32 +#define COOKIE_NONCE_SIZE XCHACHA20POLY1305_NONCE_SIZE +#define COOKIE_COOKIE_SIZE 16 +#define COOKIE_SECRET_SIZE 32 +#define COOKIE_INPUT_SIZE 32 +#define COOKIE_ENCRYPTED_SIZE (COOKIE_COOKIE_SIZE + COOKIE_MAC_SIZE) + +#define COOKIE_MAC1_KEY_LABEL "mac1----" +#define COOKIE_COOKIE_KEY_LABEL "cookie--" +#define COOKIE_SECRET_MAX_AGE 120 +#define COOKIE_SECRET_LATENCY 5 + +/* Constants for initiation rate limiting */ +#define RATELIMIT_SIZE (1 << 13) +#define RATELIMIT_SIZE_MAX (RATELIMIT_SIZE * 8) +#define NSEC_PER_SEC 1000000000LL +#define INITIATIONS_PER_SECOND 20 +#define INITIATIONS_BURSTABLE 5 +#define INITIATION_COST (NSEC_PER_SEC / INITIATIONS_PER_SECOND) +#define TOKEN_MAX (INITIATION_COST * INITIATIONS_BURSTABLE) +#define ELEMENT_TIMEOUT 1 +#define IPV4_MASK_SIZE 4 /* Use all 4 bytes of IPv4 address */ +#define IPV6_MASK_SIZE 8 /* Use top 8 bytes (/64) of IPv6 address */ + +struct cookie_macs { + uint8_t mac1[COOKIE_MAC_SIZE]; + uint8_t mac2[COOKIE_MAC_SIZE]; +}; + +struct ratelimit_entry { + LIST_ENTRY(ratelimit_entry) r_entry; + sa_family_t r_af; + union { + struct in_addr r_in; +#ifdef INET6 + struct in6_addr r_in6; +#endif + }; + struct timespec r_last_time; /* nanouptime */ + uint64_t r_tokens; +}; + +struct ratelimit { + SIPHASH_KEY rl_secret; + struct pool *rl_pool; + + struct rwlock rl_lock; + LIST_HEAD(, ratelimit_entry) *rl_table; + u_long rl_table_mask; + size_t rl_table_num; + struct timespec rl_last_gc; /* nanouptime */ +}; + +struct cookie_maker { + uint8_t cp_mac1_key[COOKIE_KEY_SIZE]; + uint8_t cp_cookie_key[COOKIE_KEY_SIZE]; + + struct rwlock cp_lock; + uint8_t cp_cookie[COOKIE_COOKIE_SIZE]; + struct timespec cp_birthdate; /* nanouptime */ + int cp_mac1_valid; + uint8_t cp_mac1_last[COOKIE_MAC_SIZE]; +}; + +struct cookie_checker { + struct ratelimit cc_ratelimit_v4; +#ifdef INET6 + struct ratelimit cc_ratelimit_v6; +#endif + + struct rwlock cc_key_lock; + uint8_t cc_mac1_key[COOKIE_KEY_SIZE]; + uint8_t cc_cookie_key[COOKIE_KEY_SIZE]; + + struct rwlock cc_secret_lock; + struct timespec cc_secret_birthdate; /* nanouptime */ + uint8_t cc_secret[COOKIE_SECRET_SIZE]; +}; + +void cookie_maker_init(struct cookie_maker *, uint8_t[COOKIE_INPUT_SIZE]); +int cookie_checker_init(struct cookie_checker *, struct pool *); +void cookie_checker_update(struct cookie_checker *, + uint8_t[COOKIE_INPUT_SIZE]); +void cookie_checker_deinit(struct cookie_checker *); +void cookie_checker_create_payload(struct cookie_checker *, + struct cookie_macs *cm, uint8_t[COOKIE_NONCE_SIZE], + uint8_t [COOKIE_ENCRYPTED_SIZE], struct sockaddr *); +int cookie_maker_consume_payload(struct cookie_maker *, + uint8_t[COOKIE_NONCE_SIZE], uint8_t[COOKIE_ENCRYPTED_SIZE]); +void cookie_maker_mac(struct cookie_maker *, struct cookie_macs *, + void *, size_t); +int cookie_checker_validate_macs(struct cookie_checker *, + struct cookie_macs *, void *, size_t, int, struct sockaddr *); + +#ifdef WGTEST +void cookie_test(); +#endif /* WGTEST */ + +#endif /* __COOKIE_H__ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net/wg_noise.h b/lib/libc/include/generic-openbsd/net/wg_noise.h new file mode 100644 index 000000000000..0e4fe016e76c --- /dev/null +++ b/lib/libc/include/generic-openbsd/net/wg_noise.h @@ -0,0 +1,197 @@ +/* $OpenBSD: wg_noise.h,v 1.3 2024/03/05 17:48:01 mvs Exp $ */ +/* + * Copyright (C) 2015-2020 Jason A. Donenfeld . All Rights Reserved. + * Copyright (C) 2019-2020 Matt Dunwoodie + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __NOISE_H__ +#define __NOISE_H__ + +#include +#include +#include +#include + +#include +#include +#include + +#define NOISE_PUBLIC_KEY_LEN CURVE25519_KEY_SIZE +#define NOISE_SYMMETRIC_KEY_LEN CHACHA20POLY1305_KEY_SIZE +#define NOISE_TIMESTAMP_LEN (sizeof(uint64_t) + sizeof(uint32_t)) +#define NOISE_AUTHTAG_LEN CHACHA20POLY1305_AUTHTAG_SIZE +#define NOISE_HASH_LEN BLAKE2S_HASH_SIZE + +/* Protocol string constants */ +#define NOISE_HANDSHAKE_NAME "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s" +#define NOISE_IDENTIFIER_NAME "WireGuard v1 zx2c4 Jason@zx2c4.com" + +/* Constants for the counter */ +#define COUNTER_BITS_TOTAL 8192 +#define COUNTER_BITS (sizeof(unsigned long) * 8) +#define COUNTER_NUM (COUNTER_BITS_TOTAL / COUNTER_BITS) +#define COUNTER_WINDOW_SIZE (COUNTER_BITS_TOTAL - COUNTER_BITS) + +/* Constants for the keypair */ +#define REKEY_AFTER_MESSAGES (1ull << 60) +#define REJECT_AFTER_MESSAGES (UINT64_MAX - COUNTER_WINDOW_SIZE - 1) +#define REKEY_AFTER_TIME 120 +#define REKEY_AFTER_TIME_RECV 165 +#define REJECT_AFTER_TIME 180 +#define REJECT_INTERVAL (1000000000 / 50) /* fifty times per sec */ +/* 24 = floor(log2(REJECT_INTERVAL)) */ +#define REJECT_INTERVAL_MASK (~((1ull<<24)-1)) + +enum noise_state_hs { + HS_ZEROED = 0, + CREATED_INITIATION, + CONSUMED_INITIATION, + CREATED_RESPONSE, + CONSUMED_RESPONSE, +}; + +struct noise_handshake { + enum noise_state_hs hs_state; + uint32_t hs_local_index; + uint32_t hs_remote_index; + uint8_t hs_e[NOISE_PUBLIC_KEY_LEN]; + uint8_t hs_hash[NOISE_HASH_LEN]; + uint8_t hs_ck[NOISE_HASH_LEN]; +}; + +struct noise_counter { + struct mutex c_mtx; + uint64_t c_send; + uint64_t c_recv; + unsigned long c_backtrack[COUNTER_NUM]; +}; + +struct noise_keypair { + SLIST_ENTRY(noise_keypair) kp_entry; + int kp_valid; + int kp_is_initiator; + uint32_t kp_local_index; + uint32_t kp_remote_index; + uint8_t kp_send[NOISE_SYMMETRIC_KEY_LEN]; + uint8_t kp_recv[NOISE_SYMMETRIC_KEY_LEN]; + struct timespec kp_birthdate; /* nanouptime */ + struct noise_counter kp_ctr; +}; + +struct noise_remote { + uint8_t r_public[NOISE_PUBLIC_KEY_LEN]; + struct noise_local *r_local; + uint8_t r_ss[NOISE_PUBLIC_KEY_LEN]; + + struct rwlock r_handshake_lock; + struct noise_handshake r_handshake; + uint8_t r_psk[NOISE_SYMMETRIC_KEY_LEN]; + uint8_t r_timestamp[NOISE_TIMESTAMP_LEN]; + struct timespec r_last_init; /* nanouptime */ + + struct mutex r_keypair_mtx; + SLIST_HEAD(,noise_keypair) r_unused_keypairs; + struct noise_keypair *r_next, *r_current, *r_previous; + struct noise_keypair r_keypair[3]; /* 3: next, current, previous. */ + +}; + +struct noise_local { + struct rwlock l_identity_lock; + int l_has_identity; + uint8_t l_public[NOISE_PUBLIC_KEY_LEN]; + uint8_t l_private[NOISE_PUBLIC_KEY_LEN]; + + struct noise_upcall { + void *u_arg; + struct noise_remote * + (*u_remote_get)(void *, uint8_t[NOISE_PUBLIC_KEY_LEN]); + uint32_t + (*u_index_set)(void *, struct noise_remote *); + void (*u_index_drop)(void *, uint32_t); + } l_upcall; +}; + +/* Set/Get noise parameters */ +void noise_local_init(struct noise_local *, struct noise_upcall *); +void noise_local_lock_identity(struct noise_local *); +void noise_local_unlock_identity(struct noise_local *); +int noise_local_set_private(struct noise_local *, uint8_t[NOISE_PUBLIC_KEY_LEN]); +int noise_local_keys(struct noise_local *, uint8_t[NOISE_PUBLIC_KEY_LEN], + uint8_t[NOISE_PUBLIC_KEY_LEN]); + +void noise_remote_init(struct noise_remote *, uint8_t[NOISE_PUBLIC_KEY_LEN], + struct noise_local *); +int noise_remote_set_psk(struct noise_remote *, uint8_t[NOISE_SYMMETRIC_KEY_LEN]); +int noise_remote_keys(struct noise_remote *, uint8_t[NOISE_PUBLIC_KEY_LEN], + uint8_t[NOISE_SYMMETRIC_KEY_LEN]); + +/* Should be called anytime noise_local_set_private is called */ +void noise_remote_precompute(struct noise_remote *); + +/* Cryptographic functions */ +int noise_create_initiation( + struct noise_remote *, + uint32_t *s_idx, + uint8_t ue[NOISE_PUBLIC_KEY_LEN], + uint8_t es[NOISE_PUBLIC_KEY_LEN + NOISE_AUTHTAG_LEN], + uint8_t ets[NOISE_TIMESTAMP_LEN + NOISE_AUTHTAG_LEN]); + +int noise_consume_initiation( + struct noise_local *, + struct noise_remote **, + uint32_t s_idx, + uint8_t ue[NOISE_PUBLIC_KEY_LEN], + uint8_t es[NOISE_PUBLIC_KEY_LEN + NOISE_AUTHTAG_LEN], + uint8_t ets[NOISE_TIMESTAMP_LEN + NOISE_AUTHTAG_LEN]); + +int noise_create_response( + struct noise_remote *, + uint32_t *s_idx, + uint32_t *r_idx, + uint8_t ue[NOISE_PUBLIC_KEY_LEN], + uint8_t en[0 + NOISE_AUTHTAG_LEN]); + +int noise_consume_response( + struct noise_remote *, + uint32_t s_idx, + uint32_t r_idx, + uint8_t ue[NOISE_PUBLIC_KEY_LEN], + uint8_t en[0 + NOISE_AUTHTAG_LEN]); + +int noise_remote_begin_session(struct noise_remote *); +void noise_remote_clear(struct noise_remote *); +void noise_remote_expire_current(struct noise_remote *); + +int noise_remote_ready(struct noise_remote *); + +int noise_remote_encrypt( + struct noise_remote *, + uint32_t *r_idx, + uint64_t *nonce, + uint8_t *buf, + size_t buflen); +int noise_remote_decrypt( + struct noise_remote *, + uint32_t r_idx, + uint64_t nonce, + uint8_t *buf, + size_t buflen); + +#ifdef WGTEST +void noise_test(); +#endif /* WGTEST */ + +#endif /* __NOISE_H__ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net80211/ieee80211.h b/lib/libc/include/generic-openbsd/net80211/ieee80211.h new file mode 100644 index 000000000000..12e9748e9f0e --- /dev/null +++ b/lib/libc/include/generic-openbsd/net80211/ieee80211.h @@ -0,0 +1,1117 @@ +/* $OpenBSD: ieee80211.h,v 1.64 2025/08/04 11:39:50 stsp Exp $ */ +/* $NetBSD: ieee80211.h,v 1.6 2004/04/30 23:51:53 dyoung Exp $ */ + +/*- + * Copyright (c) 2001 Atsushi Onoe + * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _NET80211_IEEE80211_H_ +#define _NET80211_IEEE80211_H_ + +/* + * 802.11 protocol definitions. + */ + +#define IEEE80211_ADDR_LEN 6 /* size of 802.11 address */ +/* is 802.11 address multicast/broadcast? */ +#define IEEE80211_IS_MULTICAST(_a) (*(_a) & 0x01) + +/* + * Generic definitions for IEEE 802.11 frames. + */ +struct ieee80211_frame { + u_int8_t i_fc[2]; + u_int8_t i_dur[2]; + u_int8_t i_addr1[IEEE80211_ADDR_LEN]; + u_int8_t i_addr2[IEEE80211_ADDR_LEN]; + u_int8_t i_addr3[IEEE80211_ADDR_LEN]; + u_int8_t i_seq[2]; +} __packed; + +struct ieee80211_qosframe { + u_int8_t i_fc[2]; + u_int8_t i_dur[2]; + u_int8_t i_addr1[IEEE80211_ADDR_LEN]; + u_int8_t i_addr2[IEEE80211_ADDR_LEN]; + u_int8_t i_addr3[IEEE80211_ADDR_LEN]; + u_int8_t i_seq[2]; + u_int8_t i_qos[2]; +} __packed; + +struct ieee80211_htframe { /* 11n */ + u_int8_t i_fc[2]; + u_int8_t i_dur[2]; + u_int8_t i_addr1[IEEE80211_ADDR_LEN]; + u_int8_t i_addr2[IEEE80211_ADDR_LEN]; + u_int8_t i_addr3[IEEE80211_ADDR_LEN]; + u_int8_t i_seq[2]; + u_int8_t i_qos[2]; + u_int8_t i_ht[4]; +} __packed; + +struct ieee80211_frame_addr4 { + u_int8_t i_fc[2]; + u_int8_t i_dur[2]; + u_int8_t i_addr1[IEEE80211_ADDR_LEN]; + u_int8_t i_addr2[IEEE80211_ADDR_LEN]; + u_int8_t i_addr3[IEEE80211_ADDR_LEN]; + u_int8_t i_seq[2]; + u_int8_t i_addr4[IEEE80211_ADDR_LEN]; +} __packed; + +struct ieee80211_qosframe_addr4 { + u_int8_t i_fc[2]; + u_int8_t i_dur[2]; + u_int8_t i_addr1[IEEE80211_ADDR_LEN]; + u_int8_t i_addr2[IEEE80211_ADDR_LEN]; + u_int8_t i_addr3[IEEE80211_ADDR_LEN]; + u_int8_t i_seq[2]; + u_int8_t i_addr4[IEEE80211_ADDR_LEN]; + u_int8_t i_qos[2]; +} __packed; + +struct ieee80211_htframe_addr4 { /* 11n */ + u_int8_t i_fc[2]; + u_int8_t i_dur[2]; + u_int8_t i_addr1[IEEE80211_ADDR_LEN]; + u_int8_t i_addr2[IEEE80211_ADDR_LEN]; + u_int8_t i_addr3[IEEE80211_ADDR_LEN]; + u_int8_t i_seq[2]; + u_int8_t i_addr4[IEEE80211_ADDR_LEN]; + u_int8_t i_qos[2]; + u_int8_t i_ht[4]; +} __packed; + +#define IEEE80211_MAX_FRAME_HDR_LEN (sizeof(struct ieee80211_htframe_addr4)) + +#define IEEE80211_FC0_VERSION_MASK 0x03 +#define IEEE80211_FC0_VERSION_SHIFT 0 +#define IEEE80211_FC0_VERSION_0 0x00 +#define IEEE80211_FC0_TYPE_MASK 0x0c +#define IEEE80211_FC0_TYPE_SHIFT 2 +#define IEEE80211_FC0_TYPE_MGT 0x00 +#define IEEE80211_FC0_TYPE_CTL 0x04 +#define IEEE80211_FC0_TYPE_DATA 0x08 + +#define IEEE80211_FC0_SUBTYPE_MASK 0xf0 +#define IEEE80211_FC0_SUBTYPE_SHIFT 4 +/* for TYPE_MGT */ +#define IEEE80211_FC0_SUBTYPE_ASSOC_REQ 0x00 +#define IEEE80211_FC0_SUBTYPE_ASSOC_RESP 0x10 +#define IEEE80211_FC0_SUBTYPE_REASSOC_REQ 0x20 +#define IEEE80211_FC0_SUBTYPE_REASSOC_RESP 0x30 +#define IEEE80211_FC0_SUBTYPE_PROBE_REQ 0x40 +#define IEEE80211_FC0_SUBTYPE_PROBE_RESP 0x50 +#define IEEE80211_FC0_SUBTYPE_BEACON 0x80 +#define IEEE80211_FC0_SUBTYPE_ATIM 0x90 +#define IEEE80211_FC0_SUBTYPE_DISASSOC 0xa0 +#define IEEE80211_FC0_SUBTYPE_AUTH 0xb0 +#define IEEE80211_FC0_SUBTYPE_DEAUTH 0xc0 +#define IEEE80211_FC0_SUBTYPE_ACTION 0xd0 +#define IEEE80211_FC0_SUBTYPE_ACTION_NOACK 0xe0 /* 11n */ +/* for TYPE_CTL */ +#define IEEE80211_FC0_SUBTYPE_WRAPPER 0x70 /* 11n */ +#define IEEE80211_FC0_SUBTYPE_BAR 0x80 +#define IEEE80211_FC0_SUBTYPE_BA 0x90 +#define IEEE80211_FC0_SUBTYPE_PS_POLL 0xa0 +#define IEEE80211_FC0_SUBTYPE_RTS 0xb0 +#define IEEE80211_FC0_SUBTYPE_CTS 0xc0 +#define IEEE80211_FC0_SUBTYPE_ACK 0xd0 +#define IEEE80211_FC0_SUBTYPE_CF_END 0xe0 +#define IEEE80211_FC0_SUBTYPE_CF_END_ACK 0xf0 +/* for TYPE_DATA (bit combination) */ +#define IEEE80211_FC0_SUBTYPE_DATA 0x00 +#define IEEE80211_FC0_SUBTYPE_DATA_CF_ACK 0x10 +#define IEEE80211_FC0_SUBTYPE_DATA_CF_POLL 0x20 +#define IEEE80211_FC0_SUBTYPE_DATA_CF_ACKPOLL 0x30 +#define IEEE80211_FC0_SUBTYPE_NODATA 0x40 +#define IEEE80211_FC0_SUBTYPE_NODATA_CF_ACK 0x50 +#define IEEE80211_FC0_SUBTYPE_NODATA_CF_POLL 0x60 +#define IEEE80211_FC0_SUBTYPE_NODATA_CF_ACKPOLL 0x70 +#define IEEE80211_FC0_SUBTYPE_QOS 0x80 + +#define IEEE80211_FC1_DIR_MASK 0x03 +#define IEEE80211_FC1_DIR_NODS 0x00 /* STA->STA */ +#define IEEE80211_FC1_DIR_TODS 0x01 /* STA->AP */ +#define IEEE80211_FC1_DIR_FROMDS 0x02 /* AP ->STA */ +#define IEEE80211_FC1_DIR_DSTODS 0x03 /* AP ->AP */ + +#define IEEE80211_FC1_MORE_FRAG 0x04 +#define IEEE80211_FC1_RETRY 0x08 +#define IEEE80211_FC1_PWR_MGT 0x10 +#define IEEE80211_FC1_MORE_DATA 0x20 +#define IEEE80211_FC1_PROTECTED 0x40 +#define IEEE80211_FC1_WEP 0x40 /* pre-RSNA compat */ +#define IEEE80211_FC1_ORDER 0x80 +#define IEEE80211_FC1_BITS \ + "\20\03MORE_FRAG\04RETRY\05PWR_MGT\06MORE_DATA" \ + "\07PROTECTED\08ORDER" + +/* + * Sequence Control field (see 802.11-2012 8.2.4.4). + */ +#define IEEE80211_SEQ_FRAG_MASK 0x000f +#define IEEE80211_SEQ_FRAG_SHIFT 0 +#define IEEE80211_SEQ_SEQ_MASK 0xfff0 +#define IEEE80211_SEQ_SEQ_SHIFT 4 + +#define IEEE80211_NWID_LEN 32 +#define IEEE80211_MMIE_LEN 18 /* 11w */ + +/* + * QoS Control field (see 802.11-2012 8.2.4.5). + */ +#define IEEE80211_QOS_TXOP 0xff00 +#define IEEE80211_QOS_AMSDU 0x0080 /* 11n */ +#define IEEE80211_QOS_ACK_POLICY_NORMAL 0x0000 +#define IEEE80211_QOS_ACK_POLICY_NOACK 0x0020 +#define IEEE80211_QOS_ACK_POLICY_NOEXPLACK 0x0040 +#define IEEE80211_QOS_ACK_POLICY_BA 0x0060 +#define IEEE80211_QOS_ACK_POLICY_MASK 0x0060 +#define IEEE80211_QOS_ACK_POLICY_SHIFT 5 +#define IEEE80211_QOS_EOSP 0x0010 +#define IEEE80211_QOS_TID 0x000f + +/* + * Control frames. + */ +struct ieee80211_frame_min { + u_int8_t i_fc[2]; + u_int8_t i_dur[2]; + u_int8_t i_addr1[IEEE80211_ADDR_LEN]; + u_int8_t i_addr2[IEEE80211_ADDR_LEN]; + /* FCS */ +} __packed; + +struct ieee80211_frame_rts { + u_int8_t i_fc[2]; + u_int8_t i_dur[2]; + u_int8_t i_ra[IEEE80211_ADDR_LEN]; + u_int8_t i_ta[IEEE80211_ADDR_LEN]; + /* FCS */ +} __packed; + +struct ieee80211_frame_cts { + u_int8_t i_fc[2]; + u_int8_t i_dur[2]; + u_int8_t i_ra[IEEE80211_ADDR_LEN]; + /* FCS */ +} __packed; + +struct ieee80211_frame_ack { + u_int8_t i_fc[2]; + u_int8_t i_dur[2]; + u_int8_t i_ra[IEEE80211_ADDR_LEN]; + /* FCS */ +} __packed; + +struct ieee80211_frame_pspoll { + u_int8_t i_fc[2]; + u_int8_t i_aid[2]; + u_int8_t i_bssid[IEEE80211_ADDR_LEN]; + u_int8_t i_ta[IEEE80211_ADDR_LEN]; + /* FCS */ +} __packed; + +struct ieee80211_frame_cfend { /* NB: also CF-End+CF-Ack */ + u_int8_t i_fc[2]; + u_int8_t i_dur[2]; /* should be zero */ + u_int8_t i_ra[IEEE80211_ADDR_LEN]; + u_int8_t i_bssid[IEEE80211_ADDR_LEN]; + /* FCS */ +} __packed; + +#ifdef _KERNEL +static __inline int +ieee80211_has_seq(const struct ieee80211_frame *wh) +{ + return (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != + IEEE80211_FC0_TYPE_CTL; +} + +static __inline int +ieee80211_has_addr4(const struct ieee80211_frame *wh) +{ + return (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == + IEEE80211_FC1_DIR_DSTODS; +} + +static __inline int +ieee80211_has_qos(const struct ieee80211_frame *wh) +{ + return (wh->i_fc[0] & + (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) == + (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS); +} + +static __inline int +ieee80211_has_htc(const struct ieee80211_frame *wh) +{ + return (wh->i_fc[1] & IEEE80211_FC1_ORDER) && + (ieee80211_has_qos(wh) || + (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == + IEEE80211_FC0_TYPE_MGT); +} + +static __inline u_int16_t +ieee80211_get_qos(const struct ieee80211_frame *wh) +{ + const u_int8_t *frm; + + if (ieee80211_has_addr4(wh)) + frm = ((const struct ieee80211_qosframe_addr4 *)wh)->i_qos; + else + frm = ((const struct ieee80211_qosframe *)wh)->i_qos; + + return letoh16(*(const u_int16_t *)frm); +} +#endif /* _KERNEL */ + +/* + * Capability Information field (see 802.11-2012 8.4.1.4). + */ +#define IEEE80211_CAPINFO_ESS 0x0001 +#define IEEE80211_CAPINFO_IBSS 0x0002 +#define IEEE80211_CAPINFO_CF_POLLABLE 0x0004 +#define IEEE80211_CAPINFO_CF_POLLREQ 0x0008 +#define IEEE80211_CAPINFO_PRIVACY 0x0010 +#define IEEE80211_CAPINFO_SHORT_PREAMBLE 0x0020 +#define IEEE80211_CAPINFO_PBCC 0x0040 +#define IEEE80211_CAPINFO_CHNL_AGILITY 0x0080 +#define IEEE80211_CAPINFO_SPECTRUM_MGMT 0x0100 +#define IEEE80211_CAPINFO_QOS 0x0200 +#define IEEE80211_CAPINFO_SHORT_SLOTTIME 0x0400 +#define IEEE80211_CAPINFO_APSD 0x0800 +#define IEEE80211_CAPINFO_RADIO_MEASUREMENT 0x1000 +#define IEEE80211_CAPINFO_DSSSOFDM 0x2000 +#define IEEE80211_CAPINFO_DELAYED_B_ACK 0x4000 +#define IEEE80211_CAPINFO_IMMEDIATE_B_ACK 0x8000 +#define IEEE80211_CAPINFO_BITS \ + "\10\01ESS\02IBSS\03CF_POLLABLE\04CF_POLLREQ" \ + "\05PRIVACY\06SHORT_PREAMBLE\07PBCC\10CHNL_AGILITY" \ + "\11SPECTRUM_MGMT\12QOS\13SHORT_SLOTTIME\14APSD" \ + "\15RADIO_MEASUREMENT\16DSSSOFDM\17DELAYED_B_ACK\20IMMEDIATE_B_ACK" + +/* + * Information element IDs (see 802.11-2012 Table 8.4.2). + */ +enum { + IEEE80211_ELEMID_SSID = 0, + IEEE80211_ELEMID_RATES = 1, + IEEE80211_ELEMID_FHPARMS = 2, + IEEE80211_ELEMID_DSPARMS = 3, + IEEE80211_ELEMID_CFPARMS = 4, + IEEE80211_ELEMID_TIM = 5, + IEEE80211_ELEMID_IBSSPARMS = 6, + IEEE80211_ELEMID_COUNTRY = 7, + IEEE80211_ELEMID_HOPPING_PARMS = 8, + IEEE80211_ELEMID_HOPPING_PATTERN = 9, + IEEE80211_ELEMID_REQUEST = 10, + IEEE80211_ELEMID_QBSS_LOAD = 11, + IEEE80211_ELEMID_EDCAPARMS = 12, + IEEE80211_ELEMID_TSPEC = 13, + IEEE80211_ELEMID_TCLASS = 14, + IEEE80211_ELEMID_SCHEDULE = 15, + IEEE80211_ELEMID_CHALLENGE = 16, + /* 17-31 reserved for challenge text extension */ + IEEE80211_ELEMID_POWER_CONSTRAINT = 32, + IEEE80211_ELEMID_POWER_CAP = 33, + IEEE80211_ELEMID_TPC_REQUEST = 34, + IEEE80211_ELEMID_TPC_REPORT = 35, + IEEE80211_ELEMID_SUPP_CHNLS = 35, + IEEE80211_ELEMID_CSA = 37, /* 11h */ + IEEE80211_ELEMID_MEASUREMENT_REQUEST = 38, /* DFS */ + IEEE80211_ELEMID_MEASUREMENT_REPORT = 39, /* DFS */ + IEEE80211_ELEMID_QUIET = 40, + IEEE80211_ELEMID_IBSS_DFS = 41, + IEEE80211_ELEMID_ERP = 42, + IEEE80211_ELEMID_TS_DELAY = 43, + IEEE80211_ELEMID_TCLAS = 44, + IEEE80211_ELEMID_HTCAPS = 45, /* 11n */ + IEEE80211_ELEMID_QOS_CAP = 46, + /* 47 reserved */ + IEEE80211_ELEMID_RSN = 48, + /* 49 reserved */ + IEEE80211_ELEMID_XRATES = 50, + IEEE80211_ELEMID_AP_CHNL_REPORT = 51, + IEEE80211_ELEMID_NBR_REPORT = 52, + IEEE80211_ELEMID_RCPI = 53, + IEEE80211_ELEMID_MDE = 54, + IEEE80211_ELEMID_FTE = 55, + IEEE80211_ELEMID_TIE = 56, /* 11r */ + IEEE80211_ELEMID_RDE = 57, + IEEE80211_ELEMID_DSE = 58, + IEEE80211_ELEMID_SUPP_OPCLASS = 59, + IEEE80211_ELEMID_XCSA = 60, + IEEE80211_ELEMID_HTOP = 61, /* 11n */ + IEEE80211_ELEMID_SECONDARY_CHANL_OFFSET = 62, /* 11n */ + IEEE80211_ELEMID_AVG_ACCESS_DELAY = 63, + IEEE80211_ELEMID_ANTENNA = 64, + IEEE80211_ELEMID_RSNI = 65, + IEEE80211_ELEMID_MEASUREMENT_PILOT_TX = 66, + IEEE80211_ELEMID_AVAIL_CAPACITY = 67, + IEEE80211_ELEMID_AC_ACCESS_DELAY = 68, + IEEE80211_ELEMID_TIME_ADVERT = 69, + IEEE80211_ELEMID_RM = 70, + IEEE80211_ELEMID_MULTI_BSSID = 71, + IEEE80211_ELEMID_20_40_CBW_COEX = 72, /* 11n */ + IEEE80211_ELEMID_20_40_CBW_INTOLERANT = 73, /* 11n */ + IEEE80211_ELEMID_SCAN_PARAM_OVERLAP = 74, + IEEE80211_ELEMID_RIC = 75, + IEEE80211_ELEMID_MMIE = 76, /* 11w */ + IEEE80211_ELEMID_EVENT_REQUEST = 78, + IEEE80211_ELEMID_EVENT_REPORT = 79, + IEEE80211_ELEMID_DIAG_REQUEST = 80, + IEEE80211_ELEMID_DIAG_REPORT = 81, + IEEE80211_ELEMID_LOCATION_PARMS = 82, + IEEE80211_ELEMID_NONTX_BSSID = 83, + IEEE80211_ELEMID_SSID_LIST = 84, + IEEE80211_ELEMID_MULTI_BSSID_IDX = 85, + IEEE80211_ELEMID_FMS_DESC = 86, + IEEE80211_ELEMID_FMS_REQUEST = 87, + IEEE80211_ELEMID_FMS_RESPONSE = 88, + IEEE80211_ELEMID_QOS_TRAFFIC_CAP = 89, + IEEE80211_ELEMID_MAX_IDLE_PERIOD = 90, + IEEE80211_ELEMID_TFS_REQUEST = 91, + IEEE80211_ELEMID_TFS_RESPONSE = 92, + IEEE80211_ELEMID_WNM_SLEEP = 93, + IEEE80211_ELEMID_TIM_BCAST_REQUEST = 94, + IEEE80211_ELEMID_TIM_BCAST_RESPONSE = 95, + IEEE80211_ELEMID_INTERFERENCE_REPORT = 96, + IEEE80211_ELEMID_CHNL_USAGE = 97, + IEEE80211_ELEMID_TIME_ZONE = 98, + IEEE80211_ELEMID_DMS_REQUEST = 99, + IEEE80211_ELEMID_DMS_RESPONSE = 100, + IEEE80211_ELEMID_LINK_ID = 101, + IEEE80211_ELEMID_WAKE_SCHED = 102, + /* 103 undefined */ + IEEE80211_ELEMID_CHNL_SWITCH_TIMING = 104, + IEEE80211_ELEMID_PTI_CTRL = 105, + IEEE80211_ELEMID_TPU_BUF_STATUS = 106, + IEEE80211_ELEMID_INTERWORKING = 107, + IEEE80211_ELEMID_ADVERT_PROTOCOL = 108, + IEEE80211_ELEMID_EXPEDITED_BW_REQUEST = 109, + IEEE80211_ELEMID_QOS_MAP_SET = 110, + IEEE80211_ELEMID_ROAMING_CONSORTIUM = 111, + IEEE80211_ELEMID_EMERGENCY_ALERT_ID = 112, + IEEE80211_ELEMID_MESHCONF = 113, + IEEE80211_ELEMID_MESHID = 114, + IEEE80211_ELEMID_MESHLINK = 115, + IEEE80211_ELEMID_MESHCNGST = 116, + IEEE80211_ELEMID_MESHPEER = 117, + IEEE80211_ELEMID_MESHCSA = 118, + IEEE80211_ELEMID_MESHAWAKEW = 119, + IEEE80211_ELEMID_MESHBEACONT = 120, + IEEE80211_ELEMID_MCCAOP_SETUP_REQUEST = 121, + IEEE80211_ELEMID_MCCAOP_SETUP_REPLY = 122, + IEEE80211_ELEMID_MCCAOP_ADVERT = 123, + IEEE80211_ELEMID_MCCAOP_TEARDOWN = 124, + IEEE80211_ELEMID_MESHGANN = 125, + IEEE80211_ELEMID_MESHRANN = 126, + IEEE80211_ELEMID_XCAPS = 127, + /* 128-129 reserved */ + IEEE80211_ELEMID_MESHPREQ = 130, + IEEE80211_ELEMID_MESHPREP = 131, + IEEE80211_ELEMID_MESHPERR = 132, + /* 133-136 reserved */ + IEEE80211_ELEMID_MESHPXU = 137, + IEEE80211_ELEMID_MESHPXUC = 138, + IEEE80211_ELEMID_AUTH_MESH_PEERING_XCHG = 139, + IEEE80211_ELEMID_MIC = 140, + IEEE80211_ELEMID_DEST_URI = 141, + IEEE80211_ELEMID_U_APSD_COEX = 142, + /* 143-174 reserved */ + IEEE80211_ELEMID_MCCAOP_ADVERT_OVIEW = 174, + /* 175-190 reserved */ + IEEE80211_ELEMID_VHTCAPS = 191, /* 11ac */ + IEEE80211_ELEMID_VHTOP = 192, /* 11ac */ + IEEE80211_ELEMID_EXT_BSS_LOAD = 193, /* 11ac */ + IEEE80211_ELEMID_WIDEBAND_CHNL_SWITCH = 194, /* 11ac */ + IEEE80211_ELEMID_VHT_TXPOWER = 195, /* 11ac */ + IEEE80211_ELEMID_CHNL_SWITCH_WRAPPER = 196, /* 11ac */ + IEEE80211_ELEMID_AID = 197, /* 11ac */ + IEEE80211_ELEMID_QUIET_CHNL = 198, /* 11ac */ + IEEE80211_ELEMID_OPMODE_NOTIF = 199, /* 11ac */ + /* 200-220 reserved */ + IEEE80211_ELEMID_VENDOR = 221 /* vendor private */ + /* 222-255 reserved */ +}; + +/* + * Action field category values (see 802.11-2012 8.4.1.11 Table 8-38). + */ +enum { + IEEE80211_CATEG_SPECTRUM = 0, + IEEE80211_CATEG_QOS = 1, + IEEE80211_CATEG_DLS = 2, + IEEE80211_CATEG_BA = 3, + IEEE80211_CATEG_PUB = 4, + IEEE80211_CATEG_RADIO_MSRMNT = 5, + IEEE80211_CATEG_FAST_BSS_TRANS = 6, + IEEE80211_CATEG_HT = 7, /* 11n */ + IEEE80211_CATEG_SA_QUERY = 8, /* 11w */ + IEEE80211_CATEG_PROT_DUAL_PUBLIC_ACTION = 9, + IEEE80211_CATEG_WNM = 10, + IEEE80211_CATEG_UNPROT_WNM = 11, + IEEE80211_CATEG_TDLS = 12, + IEEE80211_CATEG_MESH = 13, + IEEE80211_CATEG_MULTIHOP = 14, + IEEE80211_CATEG_SELF_PROT = 15, + /* 16-125 reserved */ + IEEE80211_CATEG_PROT_VENDOR = 126, + IEEE80211_CATEG_VENDOR = 127 + /* 128-255 error */ +}; + +/* + * Block Ack Action field values (see 802.11-2012 8.5.5 Table 8-202). + */ +#define IEEE80211_ACTION_ADDBA_REQ 0 +#define IEEE80211_ACTION_ADDBA_RESP 1 +#define IEEE80211_ACTION_DELBA 2 +/* 3-255 reserved */ + +/* + * SA Query Action field values (see 802.11-2012 8.5.10 Table 8-227). + */ +#define IEEE80211_ACTION_SA_QUERY_REQ 0 +#define IEEE80211_ACTION_SA_QUERY_RESP 1 + +/* + * HT Action field values (see 802.11-2012 8.5.12 Table 8-229). + */ +#define IEEE80211_ACTION_NOTIFYCW 0 +#define IEEE80211_ACTION_SM_PWRSAVE 1 +#define IEEE80211_ACTION_PSMP 2 +#define IEEE80211_ACTION_SET_PCO_PHASE 3 +#define IEEE80211_ACTION_CSI 4 +#define IEEE80211_ACTION_NONCOMPRESSED_BF 5 +#define IEEE80211_ACTION_COMPRESSED_BF 6 +#define IEEE80211_ACTION_ASEL_IDX_FEEDBACK 7 +/* 8-255 reserved */ + +#define IEEE80211_RATE_BASIC 0x80 +#define IEEE80211_RATE_VAL 0x7f +#define IEEE80211_RATE_SIZE 8 /* 802.11 standard */ +#define IEEE80211_RATE_MAXSIZE 15 /* max rates we'll handle */ + +#define IEEE80211_HT_NUM_MCS 77 +#define IEEE80211_VHT_NUM_MCS 10 + +/* + * BlockAck/BlockAckReq Control field (see 802.11-2012 8.3.1.9 Figure 8-25). + */ +#define IEEE80211_BA_ACK_POLICY 0x0001 +#define IEEE80211_BA_MULTI_TID 0x0002 +#define IEEE80211_BA_COMPRESSED 0x0004 +#define IEEE80211_BA_TID_INFO_MASK 0xf000 +#define IEEE80211_BA_TID_INFO_SHIFT 12 + +/* + * ADDBA Parameter Set field (see 802.11-2012 8.4.1.14 Figure 8-48). + */ +#define IEEE80211_ADDBA_AMSDU 0x0001 /* A-MSDU in A-MPDU supported */ +#define IEEE80211_ADDBA_BA_POLICY 0x0002 /* 1=immediate BA 0=delayed BA */ +#define IEEE80211_ADDBA_TID_MASK 0x003c +#define IEEE80211_ADDBA_TID_SHIFT 2 +#define IEEE80211_ADDBA_BUFSZ_MASK 0xffc0 +#define IEEE80211_ADDBA_BUFSZ_SHIFT 6 + +/* + * DELBA Parameter Set field (see 802.11-2012 8.4.1.16 Figure 8-50). + */ +#define IEEE80211_DELBA_INITIATOR 0x0800 +#define IEEE80211_DELBA_TID_INFO_MASK 0xf000 +#define IEEE80211_DELBA_TID_INFO_SHIFT 12 + +/* + * ERP information element parameters (see 802.11-2012 8.4.2.14 Figure 8-95). + */ +#define IEEE80211_ERP_NON_ERP_PRESENT 0x01 +#define IEEE80211_ERP_USE_PROTECTION 0x02 +#define IEEE80211_ERP_BARKER_MODE 0x04 + +/* + * RSN capabilities (see 802.11-2012 8.4.2.27.4). + */ +#define IEEE80211_RSNCAP_PREAUTH 0x0001 +#define IEEE80211_RSNCAP_NOPAIRWISE 0x0002 +#define IEEE80211_RSNCAP_PTKSA_RCNT_MASK 0x000c +#define IEEE80211_RSNCAP_PTKSA_RCNT_SHIFT 2 +#define IEEE80211_RSNCAP_GTKSA_RCNT_MASK 0x0030 +#define IEEE80211_RSNCAP_GTKSA_RCNT_SHIFT 4 +#define IEEE80211_RSNCAP_RCNT1 0 +#define IEEE80211_RSNCAP_RCNT2 1 +#define IEEE80211_RSNCAP_RCNT4 2 +#define IEEE80211_RSNCAP_RCNT16 3 +#define IEEE80211_RSNCAP_MFPR 0x0040 /* 11w */ +#define IEEE80211_RSNCAP_MFPC 0x0080 /* 11w */ +#define IEEE80211_RSNCAP_PEERKEYENA 0x0200 +#define IEEE80211_RSNCAP_SPPAMSDUC 0x0400 /* 11n */ +#define IEEE80211_RSNCAP_SPPAMSDUR 0x0800 /* 11n */ +#define IEEE80211_RSNCAP_PBAC 0x1000 /* 11n */ +#define IEEE80211_RSNCAP_EXTENDED_KEYID 0x2000 + +/* + * HT Capabilities Info (see 802.11-2012 8.4.2.58.2). + */ +#define IEEE80211_HTCAP_LDPC 0x00000001 +#define IEEE80211_HTCAP_CBW20_40 0x00000002 +#define IEEE80211_HTCAP_SMPS_MASK 0x0000000c +#define IEEE80211_HTCAP_SMPS_SHIFT 2 +#define IEEE80211_HTCAP_SMPS_STA 0 +#define IEEE80211_HTCAP_SMPS_DYN 1 +#define IEEE80211_HTCAP_SMPS_DIS 3 +#define IEEE80211_HTCAP_GF 0x00000010 +#define IEEE80211_HTCAP_SGI20 0x00000020 +#define IEEE80211_HTCAP_SGI40 0x00000040 +#define IEEE80211_HTCAP_TXSTBC 0x00000080 +#define IEEE80211_HTCAP_RXSTBC_MASK 0x00000300 +#define IEEE80211_HTCAP_RXSTBC_SHIFT 8 +#define IEEE80211_HTCAP_DELAYEDBA 0x00000400 +#define IEEE80211_HTCAP_AMSDU7935 0x00000800 +#define IEEE80211_HTCAP_DSSSCCK40 0x00001000 +#define IEEE80211_HTCAP_PSMP 0x00002000 +#define IEEE80211_HTCAP_40INTOLERANT 0x00004000 +#define IEEE80211_HTCAP_LSIGTXOPPROT 0x00008000 + +/* + * HT A-MPDU parameters (see 802.11-2012 8.4.2.58.3). + */ +#define IEEE80211_AMPDU_PARAM_LE 0x03 +#define IEEE80211_AMPDU_PARAM_SS 0x1c +#define IEEE80211_AMPDU_PARAM_SS_NONE (0 << 2) +#define IEEE80211_AMPDU_PARAM_SS_0_25 (1 << 2) +#define IEEE80211_AMPDU_PARAM_SS_0_5 (2 << 2) +#define IEEE80211_AMPDU_PARAM_SS_1 (3 << 2) +#define IEEE80211_AMPDU_PARAM_SS_2 (4 << 2) +#define IEEE80211_AMPDU_PARAM_SS_4 (5 << 2) +#define IEEE80211_AMPDU_PARAM_SS_8 (6 << 2) +#define IEEE80211_AMPDU_PARAM_SS_16 (7 << 2) +/* bits 5-7 reserved */ + +/* + * HT Supported MCS Set (see 802.11-2012 8.4.2.58.4). + * This field is 16 bytes in size. Bitmasks given below + * operate on 8 or 16 bit integer subsets of this field + * for use with ieee80211com and ieee80211_node. + */ +/* Bits 0-76: Supported Rx MCS bitmask */ +/* Bits 77-79: Reserved */ +/* Bits 80-89: Highest Rx rate in units of 1MB/s */ +#define IEEE80211_MCS_RX_RATE_HIGH 0x03ff +/* Bits 90-95: Reserved */ +/* Bits 96-100: Tx MCS set */ +#define IEEE80211_TX_MCS_SET_DEFINED 0x01 +#define IEEE80211_TX_RX_MCS_NOT_EQUAL 0x02 +#define IEEE80211_TX_SPATIAL_STREAMS 0x0c +#define IEEE80211_TX_UNEQUAL_MODULATION 0x10 +/* Bits 101-127: Reserved */ + +/* + * HT Extended Capabilities (see 802.11-2012 8.4.2.58.5). + */ +#define IEEE80211_HTXCAP_PCO 0x0001 +#define IEEE80211_HTXCAP_PCOTT_MASK 0x0006 +#define IEEE80211_HTXCAP_PCOTT_SHIFT 1 +#define IEEE80211_HTXCAP_PCOTT_400 1 +#define IEEE80211_HTXCAP_PCOTT_1500 2 +#define IEEE80211_HTXCAP_PCOTT_5000 3 +/* Bits 3-7 are reserved. */ +#define IEEE80211_HTXCAP_MFB_MASK 0x0300 +#define IEEE80211_HTXCAP_MFB_SHIFT 8 +#define IEEE80211_HTXCAP_MFB_NONE 0 +#define IEEE80211_HTXCAP_MFB_UNSOL 2 +#define IEEE80211_HTXCAP_MFB_BOTH 3 +#define IEEE80211_HTXCAP_HTC 0x0400 +#define IEEE80211_HTXCAP_RDRESP 0x0800 +/* Bits 12-15 are reserved. */ + +/* + * Transmit Beamforming (TxBF) Capabilities (see 802.11-2012 8.4.2.58.6). + */ +#define IEEE80211_TXBFCAP_IMPLICIT_RX 0x00000001 +#define IEEE80211_TXBFCAP_RSSC 0x00000002 +#define IEEE80211_TXBFCAP_TSSC 0x00000004 +#define IEEE80211_TXBFCAP_RNDP 0x00000008 +#define IEEE80211_TXBFCAP_TNDP 0x00000010 +#define IEEE80211_TXBFCAP_IMPLICIT_TX 0x00000020 +#define IEEE80211_TXBFCAP_CALIB_MASK 0x000000c0 +#define IEEE80211_TXBFCAP_CALIB_SHIFT 6 +#define IEEE80211_TXBFCAP_TX_CSI 0x00000100 +#define IEEE80211_TXBFCAP_EXPLICIT_NSC 0x00000200 +#define IEEE80211_TXBFCAP_EXPLICIT_CSC 0x00000400 +#define IEEE80211_TXBFCAP_CSI_FB_DELAYED 0x00000800 +#define IEEE80211_TXBFCAP_CSI_FB_IMMEDIATE 0x00001000 +#define IEEE80211_TXBFCAP_EXPLICIT_NB_FB_DELAYED 0x00002000 +#define IEEE80211_TXBFCAP_EXPLICIT_NB_FB_IMMEDIATE 0x00004000 +#define IEEE80211_TXBFCAP_EXPLICIT_CB_FB_DELAYED 0x00008000 +#define IEEE80211_TXBFCAP_EXPLICIT_CB_FB_IMMEDIATE 0x00010000 +#define IEEE80211_TXBFCAP_MINIMAL_GROUPING_1_2 0x00020000 +#define IEEE80211_TXBFCAP_MINIMAL_GROUPING_1_4 0x00040000 +#define IEEE80211_TXBFCAP_CSI_NUM_ANT_MASK 0x00180000 +#define IEEE80211_TXBFCAP_CSI_NUM_ANT_SHIFT 19 +#define IEEE80211_TXBFCAP_NS_NUM_ANT_MASK 0x00600000 +#define IEEE80211_TXBFCAP_NS_NUM_ANT_SHIFT 21 +#define IEEE80211_TXBFCAP_CS_NUM_ANT_MASK 0x01800000 +#define IEEE80211_TXBFCAP_CS_NUM_ANT_SHIFT 23 +#define IEEE80211_TXBFCAP_CSI_NUM_ROWS_MASK 0x06000000 +#define IEEE80211_TXBFCAP_CSI_NUM_ROWS_SHIFT 25 +#define IEEE80211_TXBFCAP_CHANL_ESTIMATE_MASK 0x18000000 +#define IEEE80211_TXBFCAP_CHANL_ESTIMATE_SHIFT 27 + +/* + * Antenna Selection (ASEL) Capability (see 802.11-2012 8.4.2.58.7). + */ +#define IEEE80211_ASELCAP_ASEL 0x01 +#define IEEE80211_ASELCAP_CSIFB_TX 0x02 +#define IEEE80211_ASELCAP_ANT_IDX_FB_TX 0x04 +#define IEEE80211_ASELCAP_CSIFB 0x08 +#define IEEE80211_ASELCAP_ANT_IDX_FB 0x10 +#define IEEE80211_ASELCAP_ASEL_RX 0x20 +#define IEEE80211_ASELCAP_TX_SOUND_PPDU 0x20 +/* Bit 7 is reserved. */ + +/* + * HT Operation element (see 802.11-2012 8.4.2.59). + */ +/* Byte 0 contains primary channel number. */ +/* Byte 1. */ +#define IEEE80211_HTOP0_SCO_MASK 0x03 +#define IEEE80211_HTOP0_SCO_SHIFT 0 +#define IEEE80211_HTOP0_SCO_SCN 0 +#define IEEE80211_HTOP0_SCO_SCA 1 +#define IEEE80211_HTOP0_SCO_SCB 3 +#define IEEE80211_HTOP0_CHW 0x04 +#define IEEE80211_HTOP0_RIFS 0x08 +/* bits 4-7 reserved */ +/* Bytes 2-3. */ +#define IEEE80211_HTOP1_PROT_MASK 0x0003 +#define IEEE80211_HTOP1_PROT_SHIFT 0 +#define IEEE80211_HTOP1_NONGF_STA 0x0004 +/* Bit 3 is reserved. */ +#define IEEE80211_HTOP1_OBSS_NONHT_STA 0x0010 +/* Bits 5-15 are reserved. */ +/* Bytes 4-5. */ +/* Bits 0-5 are reserved. */ +#define IEEE80211_HTOP2_DUALBEACON 0x0040 +#define IEEE80211_HTOP2_DUALCTSPROT 0x0080 +#define IEEE80211_HTOP2_STBCBEACON 0x0100 +#define IEEE80211_HTOP2_LSIGTXOP 0x0200 +#define IEEE80211_HTOP2_PCOACTIVE 0x0400 +#define IEEE80211_HTOP2_PCOPHASE40 0x0800 +/* Bits 12-15 are reserved. */ + +/* + * VHT Capabilities Info (see 802.11ac-2013 8.4.2.160.2). + */ +#define IEEE80211_VHTCAP_MAX_MPDU_LENGTH_MASK 0x00000003 +#define IEEE80211_VHTCAP_MAX_MPDU_LENGTH_SHIFT 0 +#define IEEE80211_VHTCAP_MAX_MPDU_LENGTH_3895 0 +#define IEEE80211_VHTCAP_MAX_MPDU_LENGTH_7991 1 +#define IEEE80211_VHTCAP_MAX_MPDU_LENGTH_11454 2 +#define IEEE80211_VHTCAP_CHAN_WIDTH_MASK 0x0c +#define IEEE80211_VHTCAP_CHAN_WIDTH_SHIFT 2 +#define IEEE80211_VHTCAP_CHAN_WIDTH_80 0 +#define IEEE80211_VHTCAP_CHAN_WIDTH_160 1 +#define IEEE80211_VHTCAP_CHAN_WIDTH_160_8080 2 +#define IEEE80211_VHTCAP_RX_LDPC 0x00000010 +#define IEEE80211_VHTCAP_SGI80 0x00000020 +#define IEEE80211_VHTCAP_SGI160 0x00000040 +#define IEEE80211_VHTCAP_TX_STBC 0x00000080 +#define IEEE80211_VHTCAP_RX_STBC_SS_MASK 0x00000700 +#define IEEE80211_VHTCAP_RX_STBC_SS_SHIFT 8 +#define IEEE80211_VHTCAP_SU_BEAMFORMER 0x00000800 +#define IEEE80211_VHTCAP_SU_BEAMFORMEE 0x00001000 +#define IEEE80211_VHTCAP_BEAMFORMEE_STS_MASK 0x0000e000 +#define IEEE80211_VHTCAP_BEAMFORMEE_STS_SHIFT 13 +#define IEEE80211_VHTCAP_NUM_STS_MASK 0x00070000 +#define IEEE80211_VHTCAP_NUM_STS_SHIFT 16 +#define IEEE80211_VHTCAP_MU_BEAMFORMER 0x00080000 +#define IEEE80211_VHTCAP_MU_BEAMFORMEE 0x00100000 +#define IEEE80211_VHTCAP_TXOP_PS 0x00200000 +#define IEEE80211_VHTCAP_HTC_VHT 0x00400000 +#define IEEE80211_VHTCAP_MAX_AMPDU_LEN_MASK 0x03800000 +#define IEEE80211_VHTCAP_MAX_AMPDU_LEN_SHIFT 23 +#define IEEE80211_VHTCAP_MAX_AMPDU_LEN_8K 0 +#define IEEE80211_VHTCAP_MAX_AMPDU_LEN_16K 1 +#define IEEE80211_VHTCAP_MAX_AMPDU_LEN_32K 2 +#define IEEE80211_VHTCAP_MAX_AMPDU_LEN_64K 3 +#define IEEE80211_VHTCAP_MAX_AMPDU_LEN_128K 4 +#define IEEE80211_VHTCAP_MAX_AMPDU_LEN_256K 5 +#define IEEE80211_VHTCAP_MAX_AMPDU_LEN_512K 6 +#define IEEE80211_VHTCAP_MAX_AMPDU_LEN_1024K 7 +#define IEEE80211_VHTCAP_LINK_ADAPT_MASK 0x0c000000 +#define IEEE80211_VHTCAP_LINK_ADAPT_SHIFT 26 +#define IEEE80211_VHTCAP_LINK_ADAPT_UNSOL_MFB 2 +#define IEEE80211_VHTCAP_LINK_ADAPT_MRQ_MFB 3 +#define IEEE80211_VHTCAP_RX_ANT_PATTERN 0x10000000 +#define IEEE80211_VHTCAP_TX_ANT_PATTERN 0x20000000 + +/* + * VHT-MCS and NSS map (see 802.11ac-2013 8.4.2.160.3, Figure 8-401bs). + * Set of VHT MCS supported for a given number of spatial streams, `n'. + * Used by the VHT capabilities IE and by the basic VHT MSC set in + * the VHT operation IE. + */ +#define IEEE80211_VHT_MCS_FOR_SS_MASK(n) (0x3 << (2*((n)-1))) +#define IEEE80211_VHT_MCS_FOR_SS_SHIFT(n) (2*((n)-1)) +#define IEEE80211_VHT_MCS_0_7 0 +#define IEEE80211_VHT_MCS_0_8 1 +#define IEEE80211_VHT_MCS_0_9 2 +#define IEEE80211_VHT_MCS_SS_NOT_SUPP 3 + +#define IEEE80211_VHT_MAX_LGI_MBIT_S_MASK 0x1fff +#define IEEE80211_VHT_MAX_LGI_MBIT_S_SHIFT 0 + +/* The highest number of spatial streams supported by VHT. */ +#define IEEE80211_VHT_NUM_SS 8 + +/* + * VHT Operation element (see 802.11ac-2013 8.4.2.161). + */ +/* Byte 0. */ +#define IEEE80211_VHTOP0_CHAN_WIDTH_MASK 0x03 +#define IEEE80211_VHTOP0_CHAN_WIDTH_SHIFT 0 +#define IEEE80211_VHTOP0_CHAN_WIDTH_HT 0 +#define IEEE80211_VHTOP0_CHAN_WIDTH_80 1 +#define IEEE80211_VHTOP0_CHAN_WIDTH_160 2 +#define IEEE80211_VHTOP0_CHAN_WIDTH_8080 3 +/* Byte 1 contains channel center frequency index 0 for 80, 80+80, 160 MHz. */ +/* Byte 2 contains channel center frequency index 1 for 80+80 MHz only. */ + +/* + * EDCA Access Categories. + */ +enum ieee80211_edca_ac { + EDCA_AC_BK = 1, /* Background */ + EDCA_AC_BE = 0, /* Best Effort */ + EDCA_AC_VI = 2, /* Video */ + EDCA_AC_VO = 3 /* Voice */ +}; +#define EDCA_NUM_AC 4 + +/* number of TID values (traffic identifier) */ +#define IEEE80211_NUM_TID 16 + +/* Atheros private advanced capabilities info */ +#define ATHEROS_CAP_TURBO_PRIME 0x01 +#define ATHEROS_CAP_COMPRESSION 0x02 +#define ATHEROS_CAP_FAST_FRAME 0x04 +/* bits 3-6 reserved */ +#define ATHEROS_CAP_BOOST 0x80 + +/*- + * Organizationally Unique Identifiers. + * See http://standards.ieee.org/regauth/oui/oui.txt for a list. + */ +#define ATHEROS_OUI ((const u_int8_t[]){ 0x00, 0x03, 0x7f }) +#define BROADCOM_OUI ((const u_int8_t[]){ 0x00, 0x90, 0x4c }) +#define IEEE80211_OUI ((const u_int8_t[]){ 0x00, 0x0f, 0xac }) +#define MICROSOFT_OUI ((const u_int8_t[]){ 0x00, 0x50, 0xf2 }) + +#define IEEE80211_AUTH_ALGORITHM(auth) \ + ((auth)[0] | ((auth)[1] << 8)) +#define IEEE80211_AUTH_TRANSACTION(auth) \ + ((auth)[2] | ((auth)[3] << 8)) +#define IEEE80211_AUTH_STATUS(auth) \ + ((auth)[4] | ((auth)[5] << 8)) + +/* + * Authentication Algorithm Number field (see 7.3.1.1). + */ +#define IEEE80211_AUTH_ALG_OPEN 0x0000 +#define IEEE80211_AUTH_ALG_SHARED 0x0001 +#define IEEE80211_AUTH_ALG_LEAP 0x0080 + +/* + * Authentication Transaction Sequence Number field (see 7.3.1.2). + */ +enum { + IEEE80211_AUTH_OPEN_REQUEST = 1, + IEEE80211_AUTH_OPEN_RESPONSE = 2 +}; +enum { + IEEE80211_AUTH_SHARED_REQUEST = 1, + IEEE80211_AUTH_SHARED_CHALLENGE = 2, + IEEE80211_AUTH_SHARED_RESPONSE = 3, + IEEE80211_AUTH_SHARED_PASS = 4 +}; + +/* + * Reason codes (see Table 22). + */ +enum { + IEEE80211_REASON_UNSPECIFIED = 1, + IEEE80211_REASON_AUTH_EXPIRE = 2, + IEEE80211_REASON_AUTH_LEAVE = 3, + IEEE80211_REASON_ASSOC_EXPIRE = 4, + IEEE80211_REASON_ASSOC_TOOMANY = 5, + IEEE80211_REASON_NOT_AUTHED = 6, + IEEE80211_REASON_NOT_ASSOCED = 7, + IEEE80211_REASON_ASSOC_LEAVE = 8, + IEEE80211_REASON_ASSOC_NOT_AUTHED = 9, + + /* XXX the following two reason codes are not correct */ + IEEE80211_REASON_RSN_REQUIRED = 11, + IEEE80211_REASON_RSN_INCONSISTENT = 12, + + IEEE80211_REASON_IE_INVALID = 13, + IEEE80211_REASON_MIC_FAILURE = 14, + IEEE80211_REASON_4WAY_TIMEOUT = 15, + IEEE80211_REASON_GROUP_TIMEOUT = 16, + IEEE80211_REASON_RSN_DIFFERENT_IE = 17, + IEEE80211_REASON_BAD_GROUP_CIPHER = 18, + IEEE80211_REASON_BAD_PAIRWISE_CIPHER = 19, + IEEE80211_REASON_BAD_AKMP = 20, + IEEE80211_REASON_RSN_IE_VER_UNSUP = 21, + IEEE80211_REASON_RSN_IE_BAD_CAP = 22, + + IEEE80211_REASON_CIPHER_REJ_POLICY = 24, + + IEEE80211_REASON_SETUP_REQUIRED = 38, + IEEE80211_REASON_TIMEOUT = 39 +}; + +/* + * Status codes (see Table 23). + */ +enum { + IEEE80211_STATUS_SUCCESS = 0, + IEEE80211_STATUS_UNSPECIFIED = 1, + IEEE80211_STATUS_CAPINFO = 10, + IEEE80211_STATUS_NOT_ASSOCED = 11, + IEEE80211_STATUS_OTHER = 12, + IEEE80211_STATUS_ALG = 13, + IEEE80211_STATUS_SEQUENCE = 14, + IEEE80211_STATUS_CHALLENGE = 15, + IEEE80211_STATUS_TIMEOUT = 16, + IEEE80211_STATUS_TOOMANY = 17, + IEEE80211_STATUS_BASIC_RATE = 18, + IEEE80211_STATUS_SP_REQUIRED = 19, + IEEE80211_STATUS_PBCC_REQUIRED = 20, + IEEE80211_STATUS_CA_REQUIRED = 21, + IEEE80211_STATUS_TOO_MANY_STATIONS = 22, + IEEE80211_STATUS_RATES = 23, + IEEE80211_STATUS_SHORTSLOT_REQUIRED = 25, + IEEE80211_STATUS_DSSSOFDM_REQUIRED = 26, + + IEEE80211_STATUS_TRY_AGAIN_LATER = 30, + IEEE80211_STATUS_MFP_POLICY = 31, + + IEEE80211_STATUS_REFUSED = 37, + IEEE80211_STATUS_INVALID_PARAM = 38, + + IEEE80211_STATUS_IE_INVALID = 40, + IEEE80211_STATUS_BAD_GROUP_CIPHER = 41, + IEEE80211_STATUS_BAD_PAIRWISE_CIPHER = 42, + IEEE80211_STATUS_BAD_AKMP = 43, + IEEE80211_STATUS_RSN_IE_VER_UNSUP = 44, + + IEEE80211_STATUS_CIPHER_REJ_POLICY = 46 +}; + +#define IEEE80211_WEP_KEYLEN 5 /* 40bit */ +#define IEEE80211_WEP_NKID 4 /* number of key ids */ +#define IEEE80211_CHALLENGE_LEN 128 + +/* WEP header constants */ +#define IEEE80211_WEP_IVLEN 3 /* 24bit */ +#define IEEE80211_WEP_KIDLEN 1 /* 1 octet */ +#define IEEE80211_WEP_CRCLEN 4 /* CRC-32 */ +#define IEEE80211_CRC_LEN 4 +#define IEEE80211_WEP_TOTLEN (IEEE80211_WEP_IVLEN + \ + IEEE80211_WEP_KIDLEN + \ + IEEE80211_WEP_CRCLEN) + +/* + * 802.11i defines an extended IV for use with non-WEP ciphers. + * When the EXTIV bit is set in the key id byte an additional + * 4 bytes immediately follow the IV for TKIP. For CCMP the + * EXTIV bit is likewise set but the 8 bytes represent the + * CCMP header rather than IV+extended-IV. + */ +#define IEEE80211_WEP_EXTIV 0x20 +#define IEEE80211_WEP_EXTIVLEN 4 /* extended IV length */ +#define IEEE80211_WEP_MICLEN 8 /* trailing MIC */ + +/* + * Maximum acceptable MTU is: + * IEEE80211_MAX_LEN - WEP overhead - CRC - + * QoS overhead - RSN/WPA overhead + * Min is arbitrarily chosen > IEEE80211_MIN_LEN. The default + * mtu is Ethernet-compatible; it's set by ether_ifattach. + */ +#define IEEE80211_MTU_MAX 2290 +#define IEEE80211_MTU_MIN 32 + +#define IEEE80211_MAX_LEN (2300 + IEEE80211_CRC_LEN + \ + (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN)) +#define IEEE80211_ACK_LEN \ + (sizeof(struct ieee80211_frame_ack) + IEEE80211_CRC_LEN) +#define IEEE80211_MIN_LEN \ + (sizeof(struct ieee80211_frame_min) + IEEE80211_CRC_LEN) + +/* + * The 802.11 spec says at most 2007 stations may be + * associated at once. For most AP's this is way more + * than is feasible so we use a default of 1800. This + * number may be overridden by the driver and/or by + * user configuration. + */ +#define IEEE80211_AID_MAX 2007 +#define IEEE80211_AID_DEF 1800 +#define IEEE80211_AID(b) ((b) &~ 0xc000) + +/* + * RTS frame length parameters. The default is specified in + * the 802.11 spec. The max may be wrong for jumbo frames. + */ +#define IEEE80211_RTS_DEFAULT 512 +#define IEEE80211_RTS_MIN 1 +#define IEEE80211_RTS_MAX IEEE80211_MAX_LEN + +#define IEEE80211_PLCP_SERVICE 0x00 +#define IEEE80211_PLCP_SERVICE_PBCC 0x08 /* PBCC encoded */ +#define IEEE80211_PLCP_SERVICE_LENEXT 0x80 /* length extension bit */ + +/* One Time Unit (TU) is 1Kus = 1024 microseconds. */ +#define IEEE80211_DUR_TU 1024 + +/* IEEE 802.11b durations for DSSS PHY in microseconds */ +#define IEEE80211_DUR_DS_LONG_PREAMBLE 144 +#define IEEE80211_DUR_DS_SHORT_PREAMBLE 72 +#define IEEE80211_DUR_DS_PREAMBLE_DIFFERENCE \ + (IEEE80211_DUR_DS_LONG_PREAMBLE - IEEE80211_DUR_DS_SHORT_PREAMBLE) +#define IEEE80211_DUR_DS_FAST_PLCPHDR 24 +#define IEEE80211_DUR_DS_SLOW_PLCPHDR 48 +#define IEEE80211_DUR_DS_PLCPHDR_DIFFERENCE \ + (IEEE80211_DUR_DS_SLOW_PLCPHDR - IEEE80211_DUR_DS_FAST_PLCPHDR) +#define IEEE80211_DUR_DS_SLOW_ACK 112 +#define IEEE80211_DUR_DS_FAST_ACK 56 +#define IEEE80211_DUR_DS_SLOW_CTS 112 +#define IEEE80211_DUR_DS_FAST_CTS 56 +#define IEEE80211_DUR_DS_SLOT 20 +#define IEEE80211_DUR_DS_SHSLOT 9 +#define IEEE80211_DUR_DS_SIFS 10 +#define IEEE80211_DUR_DS_PIFS (IEEE80211_DUR_DS_SIFS + IEEE80211_DUR_DS_SLOT) +#define IEEE80211_DUR_DS_DIFS (IEEE80211_DUR_DS_SIFS + \ + 2 * IEEE80211_DUR_DS_SLOT) +#define IEEE80211_DUR_DS_EIFS (IEEE80211_DUR_DS_SIFS + \ + IEEE80211_DUR_DS_SLOW_ACK + \ + IEEE80211_DUR_DS_LONG_PREAMBLE + \ + IEEE80211_DUR_DS_SLOW_PLCPHDR + \ + IEEE80211_DUR_DIFS) + +/* + * The RSNA key descriptor used by IEEE 802.11 does not use the IEEE 802.1X + * key descriptor. Instead, it uses the key descriptor described in 8.5.2. + */ +#define EAPOL_KEY_NONCE_LEN 32 +#define EAPOL_KEY_IV_LEN 16 +#define EAPOL_KEY_MIC_LEN 16 + +struct ieee80211_eapol_key { + u_int8_t version; +#define EAPOL_VERSION 1 + + u_int8_t type; +/* IEEE Std 802.1X-2004, 7.5.4 (only type EAPOL-Key is used here) */ +#define EAP_PACKET 0 +#define EAPOL_START 1 +#define EAPOL_LOGOFF 2 +#define EAPOL_KEY 3 +#define EAPOL_ASF_ALERT 4 + + u_int8_t len[2]; + u_int8_t desc; +/* IEEE Std 802.1X-2004, 7.6.1 */ +#define EAPOL_KEY_DESC_RC4 1 /* deprecated */ +#define EAPOL_KEY_DESC_IEEE80211 2 +#define EAPOL_KEY_DESC_WPA 254 /* non-standard WPA */ + + u_int8_t info[2]; +#define EAPOL_KEY_VERSION_MASK 0x7 +#define EAPOL_KEY_DESC_V1 1 +#define EAPOL_KEY_DESC_V2 2 +#define EAPOL_KEY_DESC_V3 3 /* 11r */ +#define EAPOL_KEY_PAIRWISE (1 << 3) +#define EAPOL_KEY_INSTALL (1 << 6) /* I */ +#define EAPOL_KEY_KEYACK (1 << 7) /* A */ +#define EAPOL_KEY_KEYMIC (1 << 8) /* M */ +#define EAPOL_KEY_SECURE (1 << 9) /* S */ +#define EAPOL_KEY_ERROR (1 << 10) +#define EAPOL_KEY_REQUEST (1 << 11) +#define EAPOL_KEY_ENCRYPTED (1 << 12) +#define EAPOL_KEY_SMK (1 << 13) +/* WPA compatibility */ +#define EAPOL_KEY_WPA_KID_MASK 0x3 +#define EAPOL_KEY_WPA_KID_SHIFT 4 +#define EAPOL_KEY_WPA_TX EAPOL_KEY_INSTALL + + u_int8_t keylen[2]; + u_int8_t replaycnt[8]; + u_int8_t nonce[EAPOL_KEY_NONCE_LEN]; + u_int8_t iv[EAPOL_KEY_IV_LEN]; + u_int8_t rsc[8]; + u_int8_t reserved[8]; + u_int8_t mic[EAPOL_KEY_MIC_LEN]; + u_int8_t paylen[2]; +} __packed; + +/* Pairwise Transient Key (see 8.5.1.2) */ +struct ieee80211_ptk { + u_int8_t kck[16]; /* Key Confirmation Key */ + u_int8_t kek[16]; /* Key Encryption Key */ + u_int8_t tk[32]; /* Temporal Key */ +} __packed; + +#define IEEE80211_PMKID_LEN 16 +#define IEEE80211_SMKID_LEN 16 + +/* + * Key Data Encapsulation (see Table 62). + */ +enum { + IEEE80211_KDE_GTK = 1, + IEEE80211_KDE_MACADDR = 3, + IEEE80211_KDE_PMKID = 4, + IEEE80211_KDE_SMK = 5, + IEEE80211_KDE_NONCE = 6, + IEEE80211_KDE_LIFETIME = 7, + IEEE80211_KDE_ERROR = 8, + IEEE80211_KDE_IGTK = 9 /* 11w */ +}; + +/* + * HT protection modes (see 802.11-2012 8.4.2.59) + */ +enum ieee80211_htprot { + IEEE80211_HTPROT_NONE = 0, /* only 20/40MHz HT STAs exist */ + IEEE80211_HTPROT_NONMEMBER, /* non-HT STA overlaps our channel */ + IEEE80211_HTPROT_20MHZ, /* 20MHz HT STA on a 40MHz channel */ + IEEE80211_HTPROT_NONHT_MIXED /* non-HT STA associated to our BSS */ +}; + +#endif /* _NET80211_IEEE80211_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net80211/ieee80211_amrr.h b/lib/libc/include/generic-openbsd/net80211/ieee80211_amrr.h new file mode 100644 index 000000000000..12d439bc1682 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net80211/ieee80211_amrr.h @@ -0,0 +1,58 @@ +/* $OpenBSD: ieee80211_amrr.h,v 1.4 2007/06/16 13:17:05 damien Exp $ */ + +/*- + * Copyright (c) 2006 + * Damien Bergamini + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef _NET80211_IEEE80211_AMRR_H_ +#define _NET80211_IEEE80211_AMRR_H_ + +/*- + * Naive implementation of the Adaptive Multi Rate Retry algorithm: + * + * "IEEE 802.11 Rate Adaptation: A Practical Approach" + * Mathieu Lacage, Hossein Manshaei, Thierry Turletti + * INRIA Sophia - Projet Planete + * http://www-sop.inria.fr/rapports/sophia/RR-5208.html + */ + +/* + * Rate control settings. + */ +struct ieee80211_amrr { + u_int amrr_min_success_threshold; + u_int amrr_max_success_threshold; +}; + +#define IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD 1 +#define IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD 15 + +/* + * Rate control state for a given node. + */ +struct ieee80211_amrr_node { + u_int amn_success; + u_int amn_recovery; + u_int amn_success_threshold; + u_int amn_txcnt; + u_int amn_retrycnt; +}; + +void ieee80211_amrr_node_init(const struct ieee80211_amrr *, + struct ieee80211_amrr_node *); +void ieee80211_amrr_choose(struct ieee80211_amrr *, struct ieee80211_node *, + struct ieee80211_amrr_node *); + +#endif /* _NET80211_IEEE80211_AMRR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net80211/ieee80211_crypto.h b/lib/libc/include/generic-openbsd/net80211/ieee80211_crypto.h new file mode 100644 index 000000000000..5e3227622965 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net80211/ieee80211_crypto.h @@ -0,0 +1,194 @@ +/* $OpenBSD: ieee80211_crypto.h,v 1.28 2025/03/22 07:24:08 kevlo Exp $ */ + +/*- + * Copyright (c) 2007,2008 Damien Bergamini + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _NET80211_IEEE80211_CRYPTO_H_ +#define _NET80211_IEEE80211_CRYPTO_H_ + +/* + * 802.11 protocol crypto-related definitions. + */ + +/* + * 802.11 ciphers. + */ +enum ieee80211_cipher { + IEEE80211_CIPHER_NONE = 0x00000000, + IEEE80211_CIPHER_USEGROUP = 0x00000001, + IEEE80211_CIPHER_WEP40 = 0x00000002, + IEEE80211_CIPHER_TKIP = 0x00000004, + IEEE80211_CIPHER_CCMP = 0x00000008, + IEEE80211_CIPHER_WEP104 = 0x00000010, + IEEE80211_CIPHER_BIP = 0x00000020 /* 11w */ +}; + +/* + * 802.11 Authentication and Key Management Protocols. + */ +enum ieee80211_akm { + IEEE80211_AKM_NONE = 0x00000000, + IEEE80211_AKM_8021X = 0x00000001, + IEEE80211_AKM_PSK = 0x00000002, + IEEE80211_AKM_SHA256_8021X = 0x00000004, /* 11w */ + IEEE80211_AKM_SHA256_PSK = 0x00000008, /* 11w */ + IEEE80211_AKM_SAE = 0x00000010 +}; + +#define IEEE80211_TKIP_HDRLEN 8 +#define IEEE80211_TKIP_MICLEN 8 +#define IEEE80211_TKIP_ICVLEN 4 +#define IEEE80211_CCMP_HDRLEN 8 +#define IEEE80211_CCMP_MICLEN 8 + +#define IEEE80211_PMK_LEN 32 + +#ifdef _KERNEL + +static __inline int +ieee80211_is_8021x_akm(enum ieee80211_akm akm) +{ + return akm == IEEE80211_AKM_8021X || + akm == IEEE80211_AKM_SHA256_8021X; +} + +static __inline int +ieee80211_is_sha256_akm(enum ieee80211_akm akm) +{ + return akm == IEEE80211_AKM_SHA256_8021X || + akm == IEEE80211_AKM_SHA256_PSK; +} + +struct ieee80211_key { + u_int8_t k_id; /* identifier (0-5) */ + enum ieee80211_cipher k_cipher; + u_int k_flags; +#define IEEE80211_KEY_GROUP 0x00000001 /* group data key */ +#define IEEE80211_KEY_TX 0x00000002 /* Tx+Rx */ +#define IEEE80211_KEY_IGTK 0x00000004 /* integrity group key */ +#define IEEE80211_KEY_SWCRYPTO 0x00000080 /* loaded for software crypto */ + + u_int k_len; + u_int64_t k_rsc[IEEE80211_NUM_TID]; + u_int64_t k_mgmt_rsc; + u_int64_t k_tsc; + u_int8_t k_key[32]; + void *k_priv; +}; + +#define IEEE80211_KEYBUF_SIZE 16 + +/* + * Entry in the PMKSA cache. + */ +struct ieee80211_pmk { + enum ieee80211_akm pmk_akm; + u_int32_t pmk_lifetime; +#define IEEE80211_PMK_INFINITE 0 + + u_int8_t pmk_pmkid[IEEE80211_PMKID_LEN]; + u_int8_t pmk_macaddr[IEEE80211_ADDR_LEN]; + u_int8_t pmk_key[IEEE80211_PMK_LEN]; + + TAILQ_ENTRY(ieee80211_pmk) pmk_next; +}; + +/* forward references */ +struct ieee80211com; +struct ieee80211_node; + +void ieee80211_crypto_attach(struct ifnet *); +void ieee80211_crypto_detach(struct ifnet *); + +void ieee80211_crypto_clear_groupkeys(struct ieee80211com *); +struct ieee80211_key *ieee80211_get_txkey(struct ieee80211com *, + const struct ieee80211_frame *, struct ieee80211_node *); +struct ieee80211_key *ieee80211_get_rxkey(struct ieee80211com *, + struct mbuf *, struct ieee80211_node *); +struct mbuf *ieee80211_encrypt(struct ieee80211com *, struct mbuf *, + struct ieee80211_key *); +struct mbuf *ieee80211_decrypt(struct ieee80211com *, struct mbuf *, + struct ieee80211_node *); + +int ieee80211_set_key(struct ieee80211com *, struct ieee80211_node *, + struct ieee80211_key *); +void ieee80211_delete_key(struct ieee80211com *, struct ieee80211_node *, + struct ieee80211_key *); + +void ieee80211_eapol_key_mic(struct ieee80211_eapol_key *, + const u_int8_t *); +int ieee80211_eapol_key_check_mic(struct ieee80211_eapol_key *, + const u_int8_t *); +#ifndef IEEE80211_STA_ONLY +void ieee80211_eapol_key_encrypt(struct ieee80211com *, + struct ieee80211_eapol_key *, const u_int8_t *); +#endif +int ieee80211_eapol_key_decrypt(struct ieee80211_eapol_key *, + const u_int8_t *); + +struct ieee80211_pmk *ieee80211_pmksa_add(struct ieee80211com *, + enum ieee80211_akm, const u_int8_t *, const u_int8_t *, u_int32_t); +struct ieee80211_pmk *ieee80211_pmksa_find(struct ieee80211com *, + struct ieee80211_node *, const u_int8_t *); +void ieee80211_derive_ptk(enum ieee80211_akm, const u_int8_t *, + const u_int8_t *, const u_int8_t *, const u_int8_t *, + const u_int8_t *, struct ieee80211_ptk *); +int ieee80211_cipher_keylen(enum ieee80211_cipher); + +int ieee80211_wep_set_key(struct ieee80211com *, struct ieee80211_key *); +void ieee80211_wep_delete_key(struct ieee80211com *, + struct ieee80211_key *); +struct mbuf *ieee80211_wep_encrypt(struct ieee80211com *, struct mbuf *, + struct ieee80211_key *); +struct mbuf *ieee80211_wep_decrypt(struct ieee80211com *, struct mbuf *, + struct ieee80211_key *); + +int ieee80211_tkip_set_key(struct ieee80211com *, struct ieee80211_key *); +void ieee80211_tkip_delete_key(struct ieee80211com *, + struct ieee80211_key *); +struct mbuf *ieee80211_tkip_encrypt(struct ieee80211com *, + struct mbuf *, struct ieee80211_key *); +int ieee80211_tkip_get_tsc(uint64_t *, uint64_t **, struct mbuf *, + struct ieee80211_key *); +struct mbuf *ieee80211_tkip_decrypt(struct ieee80211com *, + struct mbuf *, struct ieee80211_key *); +void ieee80211_tkip_mic(struct mbuf *, int, const u_int8_t *, + u_int8_t[IEEE80211_TKIP_MICLEN]); +void ieee80211_michael_mic_failure(struct ieee80211com *, u_int64_t); +#ifndef IEEE80211_STA_ONLY +void ieee80211_michael_mic_failure_timeout(void *); +#endif + +int ieee80211_ccmp_set_key(struct ieee80211com *, struct ieee80211_key *); +void ieee80211_ccmp_delete_key(struct ieee80211com *, + struct ieee80211_key *); +struct mbuf *ieee80211_ccmp_encrypt(struct ieee80211com *, struct mbuf *, + struct ieee80211_key *); +int ieee80211_ccmp_get_pn(uint64_t *, uint64_t **, struct mbuf *, + struct ieee80211_key *); +struct mbuf *ieee80211_ccmp_decrypt(struct ieee80211com *, struct mbuf *, + struct ieee80211_key *); + +int ieee80211_bip_set_key(struct ieee80211com *, struct ieee80211_key *); +void ieee80211_bip_delete_key(struct ieee80211com *, + struct ieee80211_key *); +struct mbuf *ieee80211_bip_encap(struct ieee80211com *, struct mbuf *, + struct ieee80211_key *); +struct mbuf *ieee80211_bip_decap(struct ieee80211com *, struct mbuf *, + struct ieee80211_key *); + +#endif /* _KERNEL */ +#endif /* _NET80211_IEEE80211_CRYPTO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net80211/ieee80211_ioctl.h b/lib/libc/include/generic-openbsd/net80211/ieee80211_ioctl.h new file mode 100644 index 000000000000..f6a31ee3ff39 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net80211/ieee80211_ioctl.h @@ -0,0 +1,429 @@ +/* $OpenBSD: ieee80211_ioctl.h,v 1.44 2025/03/22 07:24:08 kevlo Exp $ */ +/* $NetBSD: ieee80211_ioctl.h,v 1.7 2004/04/30 22:51:04 dyoung Exp $ */ + +/*- + * Copyright (c) 2001 Atsushi Onoe + * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/sys/net80211/ieee80211_ioctl.h,v 1.5 2004/03/30 22:57:57 sam Exp $ + */ +#ifndef _NET80211_IEEE80211_IOCTL_H_ +#define _NET80211_IEEE80211_IOCTL_H_ + +/* + * IEEE 802.11 ioctls. + */ + +/* per-interface statistics */ +struct ieee80211_stats { + u_int32_t is_rx_badversion; /* rx frame with bad version */ + u_int32_t is_rx_tooshort; /* rx frame too short */ + u_int32_t is_rx_wrongbss; /* rx from wrong bssid */ + u_int32_t is_rx_dup; /* rx discard 'cuz dup */ + u_int32_t is_rx_wrongdir; /* rx w/ wrong direction */ + u_int32_t is_rx_mcastecho; /* rx discard 'cuz mcast echo */ + u_int32_t is_rx_notassoc; /* rx discard 'cuz sta !assoc */ + u_int32_t is_rx_nowep; /* rx w/ wep but wep !config */ + u_int32_t is_rx_unencrypted; /* rx w/o wep but wep config */ + u_int32_t is_rx_wepfail; /* rx wep processing failed */ + u_int32_t is_rx_decap; /* rx decapsulation failed */ + u_int32_t is_rx_mgtdiscard; /* rx discard mgt frames */ + u_int32_t is_rx_ctl; /* rx discard ctrl frames */ + u_int32_t is_rx_rstoobig; /* rx rate set truncated */ + u_int32_t is_rx_elem_missing; /* rx required element missing*/ + u_int32_t is_rx_elem_toobig; /* rx element too big */ + u_int32_t is_rx_elem_toosmall; /* rx element too small */ + u_int32_t is_rx_badchan; /* rx frame w/ invalid chan */ + u_int32_t is_rx_chanmismatch; /* rx frame chan mismatch */ + u_int32_t is_rx_nodealloc; /* rx frame dropped */ + u_int32_t is_rx_ssidmismatch; /* rx frame ssid mismatch */ + u_int32_t is_rx_auth_unsupported; /* rx w/ unsupported auth alg */ + u_int32_t is_rx_auth_fail; /* rx sta auth failure */ + u_int32_t is_rx_assoc_bss; /* rx assoc from wrong bssid */ + u_int32_t is_rx_assoc_notauth; /* rx assoc w/o auth */ + u_int32_t is_rx_assoc_capmismatch;/* rx assoc w/ cap mismatch */ + u_int32_t is_rx_assoc_norate; /* rx assoc w/ no rate match */ + u_int32_t is_rx_deauth; /* rx deauthentication */ + u_int32_t is_rx_disassoc; /* rx disassociation */ + u_int32_t is_rx_badsubtype; /* rx frame w/ unknown subtype*/ + u_int32_t is_rx_nombuf; /* rx failed for lack of mbuf */ + u_int32_t is_rx_decryptcrc; /* rx decrypt failed on crc */ + u_int32_t is_rx_ahdemo_mgt; /* rx discard ahdemo mgt frame*/ + u_int32_t is_rx_bad_auth; /* rx bad auth request */ + u_int32_t is_tx_nombuf; /* tx failed for lack of mbuf */ + u_int32_t is_tx_nonode; /* tx failed for no node */ + u_int32_t is_tx_unknownmgt; /* tx of unknown mgt frame */ + u_int32_t is_scan_active; /* active scans started */ + u_int32_t is_scan_passive; /* passive scans started */ + u_int32_t is_node_timeout; /* nodes timed out inactivity */ + u_int32_t is_crypto_nomem; /* no memory for crypto ctx */ + u_int32_t is_rx_assoc_badrsnie; /* rx assoc w/ bad RSN IE */ + u_int32_t is_rx_unauth; /* rx port not valid */ + u_int32_t is_tx_noauth; /* tx port not valid */ + u_int32_t is_rx_eapol_key; /* rx eapol-key frames */ + u_int32_t is_rx_eapol_replay; /* rx replayed eapol frames */ + u_int32_t is_rx_eapol_badmic; /* rx eapol frames w/ bad mic */ + u_int32_t is_rx_remmicfail; /* rx tkip remote mic fails */ + u_int32_t is_rx_locmicfail; /* rx tkip local mic fails */ + u_int32_t is_tkip_replays; + u_int32_t is_tkip_icv_errs; + u_int32_t is_ccmp_replays; + u_int32_t is_ccmp_dec_errs; + u_int32_t is_cmac_replays; + u_int32_t is_cmac_icv_errs; + u_int32_t is_pbac_errs; + u_int32_t is_ht_nego_no_mandatory_mcs; + u_int32_t is_ht_nego_no_basic_mcs; + u_int32_t is_ht_nego_bad_crypto; + u_int32_t is_ht_prot_change; + u_int32_t is_ht_rx_ba_agreements; + u_int32_t is_ht_tx_ba_agreements; + u_int32_t is_ht_rx_frame_below_ba_winstart; + u_int32_t is_ht_rx_frame_above_ba_winend; + u_int32_t is_ht_rx_ba_window_slide; + u_int32_t is_ht_rx_ba_window_jump; + u_int32_t is_ht_rx_ba_no_buf; + u_int32_t is_ht_rx_ba_frame_lost; + u_int32_t is_ht_rx_ba_window_gap_timeout; + u_int32_t is_ht_rx_ba_timeout; + u_int32_t is_ht_tx_ba_timeout; + u_int32_t is_vht_nego_no_mandatory_mcs; + u_int32_t is_vht_nego_no_basic_mcs; +}; + +#define SIOCG80211STATS _IOWR('i', 242, struct ifreq) + +/* network identifier (ESSID), nwid is pointed at by ifr.ifr_data */ +struct ieee80211_nwid { + u_int8_t i_len; + u_int8_t i_nwid[IEEE80211_NWID_LEN]; +}; + +#define SIOCS80211NWID _IOWR('i', 230, struct ifreq) +#define SIOCG80211NWID _IOWR('i', 231, struct ifreq) + +/* network key (WEP), the first member must be matched with struct ifreq */ +struct ieee80211_nwkey { + char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */ + int i_wepon; /* wep enabled flag */ + int i_defkid; /* default encrypt key id */ + struct { + int i_keylen; + u_int8_t *i_keydat; + } i_key[IEEE80211_WEP_NKID]; +}; + +#define IEEE80211_NWKEY_OPEN 0 /* No privacy */ +#define IEEE80211_NWKEY_WEP 1 /* WEP enabled */ +#define IEEE80211_NWKEY_EAP 2 /* EAP enabled */ +#define IEEE80211_NWKEY_PERSIST 0x100 /* designate persist keyset */ + +#define SIOCS80211NWKEY _IOW('i', 232, struct ieee80211_nwkey) +#define SIOCG80211NWKEY _IOWR('i', 233, struct ieee80211_nwkey) + +/* power management parameters */ +struct ieee80211_power { + char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */ + int i_enabled; /* 1 == on, 0 == off */ + int i_maxsleep; /* max sleep in ms */ +}; +#define SIOCS80211POWER _IOW('i', 234, struct ieee80211_power) +#define SIOCG80211POWER _IOWR('i', 235, struct ieee80211_power) + +#define IEEE80211_AUTH_NONE 0 +#define IEEE80211_AUTH_OPEN 1 +#define IEEE80211_AUTH_SHARED 2 + +/* channel request */ +struct ieee80211chanreq { + char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */ + u_int16_t i_channel; +}; + +/* + * Channels are specified by frequency and attributes. + */ +struct ieee80211_chaninfo { + u_int16_t ic_freq; /* setting in MHz */ + u_int16_t ic_flags; /* see below */ +}; + +/* + * Channel attributes. + */ +#define IEEE80211_CHANINFO_2GHZ 0x0080 /* 2 GHz spectrum channel */ +#define IEEE80211_CHANINFO_5GHZ 0x0100 /* 5 GHz spectrum channel */ +#define IEEE80211_CHANINFO_PASSIVE 0x0200 /* Only passive scan allowed */ + +struct ieee80211_chanreq_all { + char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */ + struct ieee80211_chaninfo *i_chans; /* array of 256 elements */ +}; + +#ifndef IEEE80211_CHAN_ANY +#define IEEE80211_CHAN_ANY 0xffff +#endif + +#define SIOCS80211CHANNEL _IOW('i', 238, struct ieee80211chanreq) +#define SIOCG80211CHANNEL _IOWR('i', 239, struct ieee80211chanreq) +#define SIOCG80211ALLCHANS _IOWR('i', 215, struct ieee80211_chanreq_all) + +/* BSS identifier */ +struct ieee80211_bssid { + char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */ + u_int8_t i_bssid[IEEE80211_ADDR_LEN]; +}; + +#define SIOCS80211BSSID _IOW('i', 240, struct ieee80211_bssid) +#define SIOCG80211BSSID _IOWR('i', 241, struct ieee80211_bssid) + +/* transmit power */ +struct ieee80211_txpower { + char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */ + int i_mode; /* auto, manual */ + int16_t i_val; /* dBm */ +}; + +#define SIOCS80211TXPOWER _IOW('i', 243, struct ieee80211_txpower) +#define SIOCG80211TXPOWER _IOWR('i', 244, struct ieee80211_txpower) + +#define IEEE80211_TXPOWER_MODE_FIXED 0 /* fixed tx power value */ +#define IEEE80211_TXPOWER_MODE_AUTO 1 /* auto level control */ + +struct ieee80211_wpapsk { + char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */ + int i_enabled; + u_int8_t i_psk[32]; +}; + +#define SIOCS80211WPAPSK _IOW('i', 245, struct ieee80211_wpapsk) +#define SIOCG80211WPAPSK _IOWR('i', 246, struct ieee80211_wpapsk) + +#define IEEE80211_WPA_PROTO_WPA1 0x01 +#define IEEE80211_WPA_PROTO_WPA2 0x02 + +#define IEEE80211_WPA_CIPHER_NONE 0x00 +#define IEEE80211_WPA_CIPHER_USEGROUP 0x01 +#define IEEE80211_WPA_CIPHER_WEP40 0x02 +#define IEEE80211_WPA_CIPHER_TKIP 0x04 +#define IEEE80211_WPA_CIPHER_CCMP 0x08 +#define IEEE80211_WPA_CIPHER_WEP104 0x10 +#define IEEE80211_WPA_CIPHER_BIP 0x20 + +#define IEEE80211_WPA_AKM_PSK 0x01 +#define IEEE80211_WPA_AKM_8021X 0x02 +#define IEEE80211_WPA_AKM_SHA256_PSK 0x04 +#define IEEE80211_WPA_AKM_SHA256_8021X 0x08 +#define IEEE80211_WPA_AKM_SAE 0x10 + +struct ieee80211_wpaparams { + char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */ + int i_enabled; + u_int i_protos; + u_int i_akms; + u_int i_ciphers; + u_int i_groupcipher; +}; + +#define SIOCS80211WPAPARMS _IOW('i', 247, struct ieee80211_wpaparams) +#define SIOCG80211WPAPARMS _IOWR('i', 248, struct ieee80211_wpaparams) + +struct ieee80211_keyavail { + char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */ + u_int8_t i_macaddr[IEEE80211_ADDR_LEN]; + u_int8_t i_key[32]; + u_int32_t i_lifetime; +}; + +struct ieee80211_keyrun { + char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */ + u_int8_t i_macaddr[IEEE80211_ADDR_LEN]; +}; + +#define SIOCS80211KEYAVAIL _IOW('i', 251, struct ieee80211_keyavail) +#define SIOCS80211KEYRUN _IOW('i', 252, struct ieee80211_keyrun) + +/* scan request (will block) */ +#define IEEE80211_SCAN_TIMEOUT 30 /* timeout in seconds */ + +#define SIOCS80211SCAN _IOW('i', 210, struct ifreq) + +#define SIOCG80211JOINALL _IOWR('i', 218, struct ieee80211_joinreq_all) +#define SIOCS80211JOIN _IOWR('i', 255, struct ifreq) +#define SIOCG80211JOIN _IOWR('i', 0, struct ifreq) + +/* join is pointed at by ifr.ifr_data */ +struct ieee80211_join { + u_int8_t i_len; /* length of i_nwid */ + u_int8_t i_nwid[IEEE80211_NWID_LEN]; + u_int32_t i_flags; + + struct ieee80211_wpaparams i_wpaparams; + struct ieee80211_wpapsk i_wpapsk; + struct ieee80211_nwkey i_nwkey; +}; + +struct ieee80211_joinreq_all { + char ja_ifname[IFNAMSIZ]; + int ja_nodes; /* returned count */ + size_t ja_size; /* size of node buffer */ + struct ieee80211_join *ja_node; /* allocated node buffer */ +}; + + +#define IEEE80211_JOIN_SHOW 0x01 +#define IEEE80211_JOIN_FOUND 0x02 +#define IEEE80211_JOIN_DEL 0x04 +#define IEEE80211_JOIN_NWKEY 0x08 +#define IEEE80211_JOIN_WPA 0x10 +#define IEEE80211_JOIN_WPAPSK 0x20 +#define IEEE80211_JOIN_8021X 0x40 +#define IEEE80211_JOIN_ANY 0x80 +#define IEEE80211_JOIN_DEL_ALL 0x100 + +/* node and requests */ +struct ieee80211_nodereq { + char nr_ifname[IFNAMSIZ]; /* e.g. "ath0" */ + + /* Node address and name information */ + u_int8_t nr_macaddr[IEEE80211_ADDR_LEN]; /* node lladdr */ + u_int8_t nr_bssid[IEEE80211_ADDR_LEN]; /* bssid */ + u_int8_t nr_nwid_len; /* ESSID length */ + u_int8_t nr_nwid[IEEE80211_NWID_LEN]; /* ESSID */ + + /* Channel and rates */ + u_int16_t nr_channel; /* last channel */ + u_int16_t nr_chan_flags; /* channel flags */ + u_int8_t nr_nrates; /* rate count */ + u_int8_t nr_rates[IEEE80211_RATE_MAXSIZE]; /* rate set */ + + /* Node status information */ + int8_t nr_rssi; /* received signal strength */ + int8_t nr_max_rssi; /* maximum rssi */ + u_int8_t nr_tstamp[8]; /* from last received beacon */ + u_int16_t nr_intval; /* beacon interval */ + u_int16_t nr_capinfo; /* capabilities */ + u_int8_t nr_erp; /* 11g only */ + u_int8_t nr_pwrsave; /* power saving mode */ + u_int16_t nr_associd; /* assoc response */ + u_int16_t nr_txseq; /* seq to be transmitted */ + u_int16_t nr_rxseq; /* seq previous received */ + u_int32_t nr_fails; /* failure count to associate */ + u_int32_t nr_inact; /* inactivity mark count */ + u_int8_t nr_txrate; /* index to nr_rates[] */ + u_int16_t nr_state; /* node state in the cache */ + + /* RSN */ + u_int nr_rsnprotos; + u_int nr_rsnciphers; + u_int nr_rsnakms; + + /* Node flags */ + u_int8_t nr_flags; + + /* HT */ + uint16_t nr_htcaps; + uint8_t nr_rxmcs[howmany(80,NBBY)]; + uint16_t nr_max_rxrate; /* in Mb/s, 0 <= rate <= 1023 */ + uint8_t nr_tx_mcs_set; + + /* HT / VHT */ + uint8_t nr_txmcs; + + /* VHT */ + uint8_t nr_vht_ss; + + u_int32_t nr_assoc_fail; /* association failure reasons */ +}; + +#define IEEE80211_NODEREQ_STATE(_s) (1 << _s) +#define IEEE80211_NODEREQ_STATE_BITS \ + "\20\01CACHE\02BSS\03AUTH\04ASSOC\05COLLECT" + +#define IEEE80211_NODEREQ_RSSI(_nr) \ + ((u_int)(((float)(_nr)->nr_rssi / (_nr)->nr_max_rssi) * 100)) + +#define IEEE80211_NODEREQ_STA 0x00 /* station */ +#define IEEE80211_NODEREQ_AP 0x01 /* access point */ +#define IEEE80211_NODEREQ_AP_BSS 0x02 /* current bss access point */ +#define IEEE80211_NODEREQ_COPY 0x04 /* add node with flags */ +#define IEEE80211_NODEREQ_HT 0x08 /* HT negotiated */ +#define IEEE80211_NODEREQ_VHT 0x10 /* VHT negotiated */ + +#define SIOCG80211NODE _IOWR('i', 211, struct ieee80211_nodereq) +#define SIOCS80211NODE _IOW('i', 212, struct ieee80211_nodereq) +#define SIOCS80211DELNODE _IOW('i', 213, struct ieee80211_nodereq) + +#define IEEE80211_NODEREQ_ASSOCFAIL_CHAN 0x01 +#define IEEE80211_NODEREQ_ASSOCFAIL_IBSS 0x02 +#define IEEE80211_NODEREQ_ASSOCFAIL_PRIVACY 0x04 +#define IEEE80211_NODEREQ_ASSOCFAIL_BASIC_RATE 0x08 +#define IEEE80211_NODEREQ_ASSOCFAIL_ESSID 0x10 +#define IEEE80211_NODEREQ_ASSOCFAIL_BSSID 0x20 +#define IEEE80211_NODEREQ_ASSOCFAIL_WPA_PROTO 0x40 +#define IEEE80211_NODEREQ_ASSOCFAIL_WPA_KEY 0x80 +#define IEEE80211_NODEREQ_ASSOCFAIL_BITS \ + "\20\1!CHAN\2!IBSS\3!PRIVACY\4!BASICRATE\5!ESSID\6!BSSID\7!WPAPROTO" \ + "\10!WPAKEY" + +/* get the entire node cache */ +struct ieee80211_nodereq_all { + char na_ifname[IFNAMSIZ]; /* e.g. "ath0" */ + + int na_nodes; /* returned count */ + size_t na_size; /* size of node buffer */ + struct ieee80211_nodereq *na_node; /* allocated node buffer */ + + /* Match nodes by flag */ + u_int8_t na_flags; /* IEEE80211_NODEREQ_* */ +}; + +#define SIOCG80211ALLNODES _IOWR('i', 214, struct ieee80211_nodereq_all) + +/* net80211 specific interface flags */ +#define IEEE80211_F_HIDENWID 0x00000001 /* CONF: hidden ssid mode */ +#define IEEE80211_F_NOBRIDGE 0x00000002 /* CONF: no internal bridging */ +#define IEEE80211_F_HOSTAPMASK 0x00000003 +#define IEEE80211_F_STAYAUTH 0x00000004 /* CONF: ignore deauth */ +#define IEEE80211_F_NOMIMO 0x00000008 /* CONF: disable MIMO */ +#define IEEE80211_F_USERBITS "\20\01HIDENWID\02NOBRIDGE\03STAYAUTH\04NOMIMO" + +struct ieee80211_flags { + const char *f_name; + u_int f_flag; +}; + +#define IEEE80211_FLAGS { \ + { "hidenwid", IEEE80211_F_HIDENWID }, \ + { "nobridge", IEEE80211_F_NOBRIDGE }, \ + { "stayauth", IEEE80211_F_STAYAUTH }, \ + { "nomimo", IEEE80211_F_NOMIMO } \ +} + +#define SIOCG80211FLAGS _IOWR('i', 216, struct ifreq) +#define SIOCS80211FLAGS _IOW('i', 217, struct ifreq) + +#endif /* _NET80211_IEEE80211_IOCTL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net80211/ieee80211_node.h b/lib/libc/include/generic-openbsd/net80211/ieee80211_node.h new file mode 100644 index 000000000000..bdf413bb2d06 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net80211/ieee80211_node.h @@ -0,0 +1,676 @@ +/* $OpenBSD: ieee80211_node.h,v 1.97 2025/08/01 20:39:26 stsp Exp $ */ +/* $NetBSD: ieee80211_node.h,v 1.9 2004/04/30 22:57:32 dyoung Exp $ */ + +/*- + * Copyright (c) 2001 Atsushi Onoe + * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/sys/net80211/ieee80211_node.h,v 1.10 2004/04/05 22:10:26 sam Exp $ + */ +#ifndef _NET80211_IEEE80211_NODE_H_ +#define _NET80211_IEEE80211_NODE_H_ + +#include + +#define IEEE80211_PSCAN_WAIT 5 /* passive scan wait */ +#define IEEE80211_TRANS_WAIT 5 /* transition wait */ +#define IEEE80211_INACT_WAIT 5 /* inactivity timer interval */ +#define IEEE80211_INACT_MAX (300/IEEE80211_INACT_WAIT) +#define IEEE80211_CACHE_SIZE 512 +#define IEEE80211_CACHE_WAIT 30 +#define IEEE80211_INACT_SCAN 10 /* for station mode */ + +struct ieee80211_rateset { + u_int8_t rs_nrates; + u_int8_t rs_rates[IEEE80211_RATE_MAXSIZE]; +}; + +extern const struct ieee80211_rateset ieee80211_std_rateset_11a; +extern const struct ieee80211_rateset ieee80211_std_rateset_11b; +extern const struct ieee80211_rateset ieee80211_std_rateset_11g; + +/* Index into ieee80211_std_ratesets_11n[] array. */ +#define IEEE80211_HT_RATESET_SISO 0 +#define IEEE80211_HT_RATESET_SISO_SGI 1 +#define IEEE80211_HT_RATESET_MIMO2 2 +#define IEEE80211_HT_RATESET_MIMO2_SGI 3 +#define IEEE80211_HT_RATESET_MIMO3 4 +#define IEEE80211_HT_RATESET_MIMO3_SGI 5 +#define IEEE80211_HT_RATESET_MIMO4 6 +#define IEEE80211_HT_RATESET_MIMO4_SGI 7 +#define IEEE80211_HT_RATESET_SISO_40 8 +#define IEEE80211_HT_RATESET_SISO_SGI40 9 +#define IEEE80211_HT_RATESET_MIMO2_40 10 +#define IEEE80211_HT_RATESET_MIMO2_SGI40 11 +#define IEEE80211_HT_RATESET_MIMO3_40 12 +#define IEEE80211_HT_RATESET_MIMO3_SGI40 13 +#define IEEE80211_HT_RATESET_MIMO4_40 14 +#define IEEE80211_HT_RATESET_MIMO4_SGI40 15 +#define IEEE80211_HT_NUM_RATESETS 16 + +/* Maximum number of rates in a HT rateset. */ +#define IEEE80211_HT_RATESET_MAX_NRATES 8 + +/* Number of MCS indices represented by struct ieee80211_ht_rateset. */ +#define IEEE80211_HT_RATESET_NUM_MCS 32 + +struct ieee80211_ht_rateset { + uint32_t nrates; + uint32_t rates[IEEE80211_HT_RATESET_MAX_NRATES]; /* 500 kbit/s units */ + + /* + * This bitmask can only express MCS 0 - MCS 31. + * IEEE 802.11 defined 77 HT MCS in total but common hardware + * implementations tend to support MCS index 0 through 31 only. + */ + uint32_t mcs_mask; + + /* Range of MCS indices represented in this rateset. */ + int min_mcs; + int max_mcs; + + int chan40; + int sgi; +}; + +extern const struct ieee80211_ht_rateset ieee80211_std_ratesets_11n[]; + +/* Index into ieee80211_std_ratesets_11ac[] array. */ +#define IEEE80211_VHT_RATESET_SISO 0 +#define IEEE80211_VHT_RATESET_SISO_SGI 1 +#define IEEE80211_VHT_RATESET_MIMO2 2 +#define IEEE80211_VHT_RATESET_MIMO2_SGI 3 +#define IEEE80211_VHT_RATESET_SISO_40 4 +#define IEEE80211_VHT_RATESET_SISO_40_SGI 5 +#define IEEE80211_VHT_RATESET_MIMO2_40 6 +#define IEEE80211_VHT_RATESET_MIMO2_40_SGI 7 +#define IEEE80211_VHT_RATESET_SISO_80 8 +#define IEEE80211_VHT_RATESET_SISO_80_SGI 9 +#define IEEE80211_VHT_RATESET_MIMO2_80 10 +#define IEEE80211_VHT_RATESET_MIMO2_80_SGI 11 +#define IEEE80211_VHT_NUM_RATESETS 12 + +/* Maximum number of rates in a VHT rateset. */ +#define IEEE80211_VHT_RATESET_MAX_NRATES 10 + +struct ieee80211_vht_rateset { + int idx; /* This rateset's index in ieee80211_std_ratesets_11ac[]. */ + + uint32_t nrates; + uint32_t rates[IEEE80211_VHT_RATESET_MAX_NRATES]; /* 500 kbit/s units */ + + /* Number of spatial streams used by rates in this rateset. */ + int num_ss; + + int chan40; + int chan80; + int sgi; +}; + +extern const struct ieee80211_vht_rateset ieee80211_std_ratesets_11ac[]; + +enum ieee80211_node_state { + IEEE80211_STA_CACHE, /* cached node */ + IEEE80211_STA_BSS, /* ic->ic_bss, the network we joined */ + IEEE80211_STA_AUTH, /* successfully authenticated */ + IEEE80211_STA_ASSOC, /* successfully associated */ + IEEE80211_STA_COLLECT /* This node remains in the cache while + * the driver sends a de-auth message; + * afterward it should be freed to make room + * for a new node. + */ +}; + +#define ieee80211_node_newstate(__ni, __state) \ + do { \ + (__ni)->ni_state = (__state); \ + } while (0) + +enum ieee80211_node_psstate { + IEEE80211_PS_AWAKE, + IEEE80211_PS_DOZE +}; + +#define IEEE80211_PS_MAX_QUEUE 50 /* maximum saved packets */ + +/* Authenticator state machine: 4-Way Handshake (see 8.5.6.1.1) */ +enum { + RSNA_INITIALIZE, + RSNA_AUTHENTICATION, + RSNA_AUTHENTICATION_2, + RSNA_INITPMK, + RSNA_INITPSK, + RSNA_PTKSTART, + RSNA_PTKCALCNEGOTIATING, + RSNA_PTKCALCNEGOTIATING_2, + RSNA_PTKINITNEGOTIATING, + RSNA_PTKINITDONE, + RSNA_DISCONNECT, + RSNA_DISCONNECTED +}; + +/* Authenticator state machine: Group Key Handshake (see 8.5.6.1.2) */ +enum { + RSNA_IDLE, + RSNA_REKEYNEGOTIATING, + RSNA_REKEYESTABLISHED, + RSNA_KEYERROR +}; + +/* Supplicant state machine: 4-Way Handshake (not documented in standard) */ +enum { + RSNA_SUPP_INITIALIZE, /* not expecting any messages */ + RSNA_SUPP_PTKSTART, /* awaiting handshake message 1 */ + RSNA_SUPP_PTKNEGOTIATING, /* got message 1 and derived PTK */ + RSNA_SUPP_PTKDONE /* got message 3 and authenticated AP */ +}; + +struct ieee80211_rxinfo { + u_int32_t rxi_flags; + u_int32_t rxi_tstamp; + int rxi_rssi; + uint8_t rxi_chan; +}; +#define IEEE80211_RXI_HWDEC 0x00000001 +#define IEEE80211_RXI_AMPDU_DONE 0x00000002 +#define IEEE80211_RXI_HWDEC_SAME_PN 0x00000004 +#define IEEE80211_RXI_SAME_SEQ 0x00000008 + +/* Block Acknowledgement Record */ +struct ieee80211_tx_ba { + struct ieee80211_node *ba_ni; /* backpointer for callbacks */ + struct timeout ba_to; + int ba_timeout_val; + int ba_state; +#define IEEE80211_BA_INIT 0 +#define IEEE80211_BA_REQUESTED 1 +#define IEEE80211_BA_AGREED 2 + + /* ADDBA parameter set field for this BA agreement. */ + u_int16_t ba_params; + + /* These values are IEEE802.11 frame sequence numbers (0x0-0xfff) */ + u_int16_t ba_winstart; + u_int16_t ba_winend; + + /* Number of A-MPDU subframes in reorder buffer. */ + u_int16_t ba_winsize; +#define IEEE80211_BA_MAX_WINSZ 64 /* corresponds to maximum ADDBA BUFSZ */ + + u_int8_t ba_token; + + /* Bitmap for ACK'd frames in the current BA window. */ + uint64_t ba_bitmap; +}; + +struct ieee80211_rx_ba { + struct ieee80211_node *ba_ni; /* backpointer for callbacks */ + struct { + struct mbuf *m; + struct ieee80211_rxinfo rxi; + } *ba_buf; + struct timeout ba_to; + int ba_timeout_val; + int ba_state; + u_int16_t ba_params; + u_int16_t ba_winstart; + u_int16_t ba_winend; + u_int16_t ba_winsize; + u_int16_t ba_head; + struct timeout ba_gap_to; +#define IEEE80211_BA_GAP_TIMEOUT 300 /* msec */ + + /* + * Counter for frames forced to wait in the reordering buffer + * due to a leading gap caused by one or more missing frames. + */ + int ba_gapwait; + + /* Counter for consecutive frames which missed the BA window. */ + int ba_winmiss; + /* Sequence number of previous frame which missed the BA window. */ + uint16_t ba_missedsn; + /* Window moves forward after this many frames have missed it. */ +#define IEEE80211_BA_MAX_WINMISS 8 + + uint8_t ba_token; +}; + +/* + * Node specific information. Note that drivers are expected + * to derive from this structure to add device-specific per-node + * state. This is done by overriding the ic_node_* methods in + * the ieee80211com structure. + */ +struct ieee80211_node { + RBT_ENTRY(ieee80211_node) ni_node; + + struct ieee80211com *ni_ic; /* back-pointer */ + + u_int ni_refcnt; + u_int ni_scangen; /* gen# for timeout scan */ + + /* hardware */ + u_int32_t ni_rstamp; /* recv timestamp */ + u_int8_t ni_rssi; /* recv ssi */ + + /* header */ + u_int8_t ni_macaddr[IEEE80211_ADDR_LEN]; + u_int8_t ni_bssid[IEEE80211_ADDR_LEN]; + + /* beacon, probe response */ + u_int8_t ni_tstamp[8]; /* from last rcv'd beacon */ + u_int16_t ni_intval; /* beacon interval */ + u_int16_t ni_capinfo; /* capabilities */ + u_int8_t ni_esslen; + u_int8_t ni_essid[IEEE80211_NWID_LEN]; + struct ieee80211_rateset ni_rates; /* negotiated rate set */ + u_int8_t *ni_country; /* country information XXX */ + struct ieee80211_channel *ni_chan; + u_int8_t ni_erp; /* 11g only */ + + /* DTIM and contention free period (CFP) */ + u_int8_t ni_dtimcount; + u_int8_t ni_dtimperiod; +#ifdef notyet + u_int8_t ni_cfpperiod; /* # of DTIMs between CFPs */ + u_int16_t ni_cfpduremain; /* remaining cfp duration */ + u_int16_t ni_cfpmaxduration;/* max CFP duration in TU */ + u_int16_t ni_nextdtim; /* time to next DTIM */ + u_int16_t ni_timoffset; +#endif + + /* power saving mode */ + u_int8_t ni_pwrsave; + struct mbuf_queue ni_savedq; /* packets queued for pspoll */ + + /* RSN */ + struct timeout ni_eapol_to; + u_int ni_rsn_state; + u_int ni_rsn_supp_state; + u_int ni_rsn_gstate; + u_int ni_rsn_retries; + u_int ni_supported_rsnprotos; + u_int ni_rsnprotos; + u_int ni_supported_rsnakms; + u_int ni_rsnakms; + u_int ni_rsnciphers; + enum ieee80211_cipher ni_rsngroupcipher; + enum ieee80211_cipher ni_rsngroupmgmtcipher; + u_int16_t ni_rsncaps; + enum ieee80211_cipher ni_rsncipher; + u_int8_t ni_nonce[EAPOL_KEY_NONCE_LEN]; + u_int8_t ni_pmk[IEEE80211_PMK_LEN]; + u_int8_t ni_pmkid[IEEE80211_PMKID_LEN]; + u_int64_t ni_replaycnt; + u_int8_t ni_replaycnt_ok; + u_int64_t ni_reqreplaycnt; + u_int8_t ni_reqreplaycnt_ok; + u_int8_t *ni_rsnie; + struct ieee80211_key ni_pairwise_key; + struct ieee80211_ptk ni_ptk; + u_int8_t ni_key_count; + int ni_port_valid; + + /* SA Query */ + u_int16_t ni_sa_query_trid; + struct timeout ni_sa_query_to; + int ni_sa_query_count; + + /* HT capabilities */ + uint16_t ni_htcaps; + uint8_t ni_ampdu_param; + uint8_t ni_rxmcs[howmany(80,NBBY)]; + uint16_t ni_max_rxrate; /* in Mb/s, 0 <= rate <= 1023 */ + uint8_t ni_tx_mcs_set; + uint16_t ni_htxcaps; + uint32_t ni_txbfcaps; + uint8_t ni_aselcaps; + + /* HT operation */ + uint8_t ni_primary_chan; /* XXX corresponds to ni_chan */ + uint8_t ni_htop0; + uint16_t ni_htop1; + uint16_t ni_htop2; + uint8_t ni_basic_mcs[howmany(128,NBBY)]; + + /* VHT capabilities */ + uint32_t ni_vhtcaps; + uint16_t ni_vht_rxmcs; + uint16_t ni_vht_rx_max_lgi_mbit_s; + uint16_t ni_vht_txmcs; + uint16_t ni_vht_tx_max_lgi_mbit_s; + + /* VHT operation */ + uint8_t ni_vht_chan_width; + uint8_t ni_vht_chan_center_freq_idx0; + uint8_t ni_vht_chan_center_freq_idx1; + uint16_t ni_vht_basic_mcs; + + /* Timeout handlers which trigger Tx Block Ack negotiation. */ + struct timeout ni_addba_req_to[IEEE80211_NUM_TID]; + int ni_addba_req_intval[IEEE80211_NUM_TID]; +#define IEEE80211_ADDBA_REQ_INTVAL_MAX 30 /* in seconds */ + + /* Block Ack records */ + struct ieee80211_tx_ba ni_tx_ba[IEEE80211_NUM_TID]; + struct ieee80211_rx_ba ni_rx_ba[IEEE80211_NUM_TID]; + + int ni_txmcs; /* current MCS used for TX */ + int ni_vht_ss; /* VHT # spatial streams */ + + /* others */ + u_int16_t ni_associd; /* assoc response */ + u_int16_t ni_txseq; /* seq to be transmitted */ + u_int16_t ni_rxseq; /* seq previous received */ + u_int16_t ni_qos_txseqs[IEEE80211_NUM_TID]; + u_int16_t ni_qos_rxseqs[IEEE80211_NUM_TID]; + int ni_fails; /* failure count to associate */ + uint32_t ni_assoc_fail; /* assoc failure reasons */ +#define IEEE80211_NODE_ASSOCFAIL_CHAN 0x01 +#define IEEE80211_NODE_ASSOCFAIL_IBSS 0x02 +#define IEEE80211_NODE_ASSOCFAIL_PRIVACY 0x04 +#define IEEE80211_NODE_ASSOCFAIL_BASIC_RATE 0x08 +#define IEEE80211_NODE_ASSOCFAIL_ESSID 0x10 +#define IEEE80211_NODE_ASSOCFAIL_BSSID 0x20 +#define IEEE80211_NODE_ASSOCFAIL_WPA_PROTO 0x40 +#define IEEE80211_NODE_ASSOCFAIL_WPA_KEY 0x80 + + int ni_inact; /* inactivity mark count */ + int ni_txrate; /* index to ni_rates[] */ + int ni_state; + + u_int32_t ni_flags; /* special-purpose state */ +#define IEEE80211_NODE_ERP 0x0001 +#define IEEE80211_NODE_QOS 0x0002 +#define IEEE80211_NODE_REKEY 0x0004 /* GTK rekeying in progress */ +#define IEEE80211_NODE_RXPROT 0x0008 /* RX protection ON */ +#define IEEE80211_NODE_TXPROT 0x0010 /* TX protection ON */ +#define IEEE80211_NODE_TXRXPROT \ + (IEEE80211_NODE_TXPROT | IEEE80211_NODE_RXPROT) +#define IEEE80211_NODE_RXMGMTPROT 0x0020 /* RX MMPDU protection ON */ +#define IEEE80211_NODE_TXMGMTPROT 0x0040 /* TX MMPDU protection ON */ +#define IEEE80211_NODE_MFP 0x0080 /* MFP negotiated */ +#define IEEE80211_NODE_PMK 0x0100 /* ni_pmk set */ +#define IEEE80211_NODE_PMKID 0x0200 /* ni_pmkid set */ +#define IEEE80211_NODE_HT 0x0400 /* HT negotiated */ +#define IEEE80211_NODE_SA_QUERY 0x0800 /* SA Query in progress */ +#define IEEE80211_NODE_SA_QUERY_FAILED 0x1000 /* last SA Query failed */ +#define IEEE80211_NODE_RSN_NEW_PTK 0x2000 /* expecting a new PTK */ +#define IEEE80211_NODE_HT_SGI20 0x4000 /* SGI on 20 MHz negotiated */ +#define IEEE80211_NODE_HT_SGI40 0x8000 /* SGI on 40 MHz negotiated */ +#define IEEE80211_NODE_VHT 0x10000 /* VHT negotiated */ +#define IEEE80211_NODE_HTCAP 0x20000 /* claims to support HT */ +#define IEEE80211_NODE_VHTCAP 0x40000 /* claims to support VHT */ +#define IEEE80211_NODE_VHT_SGI80 0x80000 /* SGI on 80 MHz negotiated */ +#define IEEE80211_NODE_VHT_SGI160 0x100000 /* SGI on 160 MHz negotiated */ + + /* If not NULL, this function gets called when ni_refcnt hits zero. */ + void (*ni_unref_cb)(struct ieee80211com *, + struct ieee80211_node *); + void * ni_unref_arg; + size_t ni_unref_arg_size; +}; + +RBT_HEAD(ieee80211_tree, ieee80211_node); + +struct ieee80211_ess_rbt { + RBT_ENTRY(ieee80211_ess_rbt) ess_rbt; + u_int8_t esslen; + u_int8_t essid[IEEE80211_NWID_LEN]; + struct ieee80211_node *ni2; + struct ieee80211_node *ni5; + struct ieee80211_node *ni; +}; + +RBT_HEAD(ieee80211_ess_tree, ieee80211_ess_rbt); + +static inline void +ieee80211_node_incref(struct ieee80211_node *ni) +{ + int s; + + s = splnet(); + ni->ni_refcnt++; + splx(s); +} + +static inline u_int +ieee80211_node_decref(struct ieee80211_node *ni) +{ + u_int refcnt; + int s; + + s = splnet(); + refcnt = --ni->ni_refcnt; + splx(s); + return refcnt; +} + +static inline struct ieee80211_node * +ieee80211_ref_node(struct ieee80211_node *ni) +{ + ieee80211_node_incref(ni); + return ni; +} + +static inline void +ieee80211_unref_node(struct ieee80211_node **ni) +{ + ieee80211_node_decref(*ni); + *ni = NULL; /* guard against use */ +} + +/* + * Check if the peer supports HT. + * Require a HT capabilities IE and at least one of the mandatory MCS. + * MCS 0-7 are mandatory but some APs have particular MCS disabled. + */ +static inline int +ieee80211_node_supports_ht(struct ieee80211_node *ni) +{ + return ((ni->ni_flags & IEEE80211_NODE_HTCAP) && + ni->ni_rxmcs[0] & 0xff); +} + +/* Check if the peer supports HT short guard interval (SGI) on 20 MHz. */ +static inline int +ieee80211_node_supports_ht_sgi20(struct ieee80211_node *ni) +{ + return ieee80211_node_supports_ht(ni) && + (ni->ni_htcaps & IEEE80211_HTCAP_SGI20); +} + +/* Check if the peer supports HT short guard interval (SGI) on 40 MHz. */ +static inline int +ieee80211_node_supports_ht_sgi40(struct ieee80211_node *ni) +{ + return ieee80211_node_supports_ht(ni) && + (ni->ni_htcaps & IEEE80211_HTCAP_SGI40); +} + +/* Check if the peer can receive frames sent on a 40 MHz channel. */ +static inline int +ieee80211_node_supports_ht_chan40(struct ieee80211_node *ni) +{ + return (ieee80211_node_supports_ht(ni) && + (ni->ni_htcaps & IEEE80211_HTCAP_CBW20_40) && + (ni->ni_htop0 & IEEE80211_HTOP0_CHW)); +} + +/* + * Check if the peer supports VHT. + * Require a VHT capabilities IE and support for VHT MCS with a single + * spatial stream. + */ +static inline int +ieee80211_node_supports_vht(struct ieee80211_node *ni) +{ + uint16_t rx_mcs; + + rx_mcs = (ni->ni_vht_rxmcs & IEEE80211_VHT_MCS_FOR_SS_MASK(1)) >> + IEEE80211_VHT_MCS_FOR_SS_SHIFT(1); + + return ((ni->ni_flags & IEEE80211_NODE_VHTCAP) && + rx_mcs != IEEE80211_VHT_MCS_SS_NOT_SUPP); +} + +/* Check if the peer supports VHT short guard interval (SGI) on 80 MHz. */ +static inline int +ieee80211_node_supports_vht_sgi80(struct ieee80211_node *ni) +{ + return ieee80211_node_supports_vht(ni) && + (ni->ni_vhtcaps & IEEE80211_VHTCAP_SGI80); +} + +/* Check if the peer supports VHT short guard interval (SGI) on 160 MHz. */ +static inline int +ieee80211_node_supports_vht_sgi160(struct ieee80211_node *ni) +{ + return ieee80211_node_supports_vht(ni) && + (ni->ni_vhtcaps & IEEE80211_VHTCAP_SGI160); +} + +/* Check if the peer can receive frames sent on an 80 MHz channel. */ +static inline int +ieee80211_node_supports_vht_chan80(struct ieee80211_node *ni) +{ + uint8_t cap_chan_width, op_chan_width; + + if (!ieee80211_node_supports_vht(ni)) + return 0; + + cap_chan_width = (ni->ni_vhtcaps & IEEE80211_VHTCAP_CHAN_WIDTH_MASK) >> + IEEE80211_VHTCAP_CHAN_WIDTH_SHIFT; + if (cap_chan_width != IEEE80211_VHTCAP_CHAN_WIDTH_80 && + cap_chan_width != IEEE80211_VHTCAP_CHAN_WIDTH_160 && + cap_chan_width != IEEE80211_VHTCAP_CHAN_WIDTH_160_8080) + return 0; + + op_chan_width = (ni->ni_vht_chan_width & + IEEE80211_VHTOP0_CHAN_WIDTH_MASK) >> + IEEE80211_VHTOP0_CHAN_WIDTH_SHIFT; + + return (op_chan_width == IEEE80211_VHTOP0_CHAN_WIDTH_80 || + op_chan_width == IEEE80211_VHTOP0_CHAN_WIDTH_160 || + op_chan_width == IEEE80211_VHTOP0_CHAN_WIDTH_8080); +} + +/* Check if the peer can receive frames sent on a 160 MHz channel. */ +static inline int +ieee80211_node_supports_vht_chan160(struct ieee80211_node *ni) +{ + uint8_t cap_chan_width, op_chan_width; + + if (!ieee80211_node_supports_vht(ni)) + return 0; + + cap_chan_width = (ni->ni_vhtcaps & IEEE80211_VHTCAP_CHAN_WIDTH_MASK) >> + IEEE80211_VHTCAP_CHAN_WIDTH_SHIFT; + if (cap_chan_width != IEEE80211_VHTCAP_CHAN_WIDTH_160) + return 0; + + op_chan_width = (ni->ni_vht_chan_width & + IEEE80211_VHTOP0_CHAN_WIDTH_MASK) >> + IEEE80211_VHTOP0_CHAN_WIDTH_SHIFT; + + return (op_chan_width == IEEE80211_VHTOP0_CHAN_WIDTH_160); +} + +struct ieee80211com; + +typedef void ieee80211_iter_func(void *, struct ieee80211_node *); + +void ieee80211_node_attach(struct ifnet *); +void ieee80211_node_lateattach(struct ifnet *); +void ieee80211_node_detach(struct ifnet *); + +void ieee80211_begin_scan(struct ifnet *); +void ieee80211_next_scan(struct ifnet *); +void ieee80211_end_scan(struct ifnet *); +void ieee80211_reset_scan(struct ifnet *); +struct ieee80211_node *ieee80211_alloc_node(struct ieee80211com *, + const u_int8_t *); +struct ieee80211_node *ieee80211_dup_bss(struct ieee80211com *, + const u_int8_t *); +struct ieee80211_node *ieee80211_find_node(struct ieee80211com *, + const u_int8_t *); +void ieee80211_node_tx_ba_clear(struct ieee80211_node *, int); +void ieee80211_ba_del(struct ieee80211_node *); +struct ieee80211_node *ieee80211_find_rxnode(struct ieee80211com *, + const struct ieee80211_frame *); +struct ieee80211_node *ieee80211_find_txnode(struct ieee80211com *, + const u_int8_t *); +void ieee80211_release_node(struct ieee80211com *, + struct ieee80211_node *); +void ieee80211_node_cleanup(struct ieee80211com *, struct ieee80211_node *); +void ieee80211_free_allnodes(struct ieee80211com *, int); +void ieee80211_iterate_nodes(struct ieee80211com *, + ieee80211_iter_func *, void *); +void ieee80211_clean_cached(struct ieee80211com *); +void ieee80211_clean_nodes(struct ieee80211com *, int); +void ieee80211_setup_htcaps(struct ieee80211_node *, const uint8_t *, + uint8_t); +void ieee80211_clear_htcaps(struct ieee80211_node *); +int ieee80211_setup_htop(struct ieee80211_node *, const uint8_t *, + uint8_t, int); +void ieee80211_setup_vhtcaps(struct ieee80211_node *, const uint8_t *, + uint8_t); +void ieee80211_clear_vhtcaps(struct ieee80211_node *); +int ieee80211_setup_vhtop(struct ieee80211_node *, const uint8_t *, + uint8_t, int); +int ieee80211_setup_rates(struct ieee80211com *, + struct ieee80211_node *, const u_int8_t *, const u_int8_t *, int); +enum ieee80211_phymode ieee80211_node_abg_mode(struct ieee80211com *, + struct ieee80211_node *); +void ieee80211_node_trigger_addba_req(struct ieee80211_node *, int); +void ieee80211_count_longslotsta(void *, struct ieee80211_node *); +void ieee80211_count_nonerpsta(void *, struct ieee80211_node *); +void ieee80211_count_pssta(void *, struct ieee80211_node *); +void ieee80211_count_rekeysta(void *, struct ieee80211_node *); +void ieee80211_node_join(struct ieee80211com *, + struct ieee80211_node *, int); +void ieee80211_node_leave(struct ieee80211com *, + struct ieee80211_node *); +int ieee80211_match_bss(struct ieee80211com *, struct ieee80211_node *, int); +void ieee80211_node_tx_stopped(struct ieee80211com *, struct ieee80211_node *); +struct ieee80211_node *ieee80211_node_choose_bss(struct ieee80211com *, int, + struct ieee80211_node **); +void ieee80211_node_join_bss(struct ieee80211com *, struct ieee80211_node *); +void ieee80211_create_ibss(struct ieee80211com* , + struct ieee80211_channel *); +void ieee80211_notify_dtim(struct ieee80211com *); +void ieee80211_set_tim(struct ieee80211com *, int, int); +void ieee80211_free_node(struct ieee80211com *, struct ieee80211_node *); + +int ieee80211_node_cmp(const struct ieee80211_node *, + const struct ieee80211_node *); +int ieee80211_ess_cmp(const struct ieee80211_ess_rbt *, + const struct ieee80211_ess_rbt *); +RBT_PROTOTYPE(ieee80211_tree, ieee80211_node, ni_node, ieee80211_node_cmp); +RBT_PROTOTYPE(ieee80211_ess_tree, ieee80211_ess_rbt, ess_rbt, ieee80211_ess_cmp); + +#endif /* _NET80211_IEEE80211_NODE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net80211/ieee80211_priv.h b/lib/libc/include/generic-openbsd/net80211/ieee80211_priv.h new file mode 100644 index 000000000000..a6178833b22f --- /dev/null +++ b/lib/libc/include/generic-openbsd/net80211/ieee80211_priv.h @@ -0,0 +1,135 @@ +/* $OpenBSD: ieee80211_priv.h,v 1.5 2009/01/26 19:09:41 damien Exp $ */ + +/*- + * Copyright (c) 2008 Damien Bergamini + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _NET80211_IEEE80211_PRIV_H_ +#define _NET80211_IEEE80211_PRIV_H_ + +#ifdef IEEE80211_DEBUG +extern int ieee80211_debug; +#define DPRINTF(X) do { \ + if (ieee80211_debug) { \ + printf("%s: ", __func__); \ + printf X; \ + } \ +} while(0) +#else +#define DPRINTF(X) +#endif + +#define SEQ_LT(a,b) \ + ((((u_int16_t)(a) - (u_int16_t)(b)) & 0xfff) > 2048) + +#define IEEE80211_AID_SET(b, w) \ + ((w)[IEEE80211_AID(b) / 32] |= (1 << (IEEE80211_AID(b) % 32))) +#define IEEE80211_AID_CLR(b, w) \ + ((w)[IEEE80211_AID(b) / 32] &= ~(1 << (IEEE80211_AID(b) % 32))) +#define IEEE80211_AID_ISSET(b, w) \ + ((w)[IEEE80211_AID(b) / 32] & (1 << (IEEE80211_AID(b) % 32))) + +#define IEEE80211_RSNIE_MAXLEN \ + (2 + /* Version */ \ + 4 + /* Group Data Cipher Suite */ \ + 2 + /* Pairwise Cipher Suite Count */ \ + 4 * 2 + /* Pairwise Cipher Suite List (max 2) */ \ + 2 + /* AKM Suite List Count */ \ + 4 * 4 + /* AKM Suite List (max 4) */ \ + 2 + /* RSN Capabilities */ \ + 2 + /* PMKID Count */ \ + 16 * 1 + /* PMKID List (max 1) */ \ + 4) /* 11w: Group Integrity Cipher Suite */ + +#define IEEE80211_WPAIE_MAXLEN \ + (4 + /* MICROSOFT_OUI */ \ + 2 + /* Version */ \ + 4 + /* Group Cipher Suite */ \ + 2 + /* Pairwise Cipher Suite Count */ \ + 4 * 2 + /* Pairwise Cipher Suite List (max 2) */ \ + 2 + /* AKM Suite List Count */ \ + 4 * 2) /* AKM Suite List (max 2) */ + +struct ieee80211_rsnparams { + u_int16_t rsn_nakms; + u_int32_t rsn_akms; + u_int16_t rsn_nciphers; + u_int32_t rsn_ciphers; + enum ieee80211_cipher rsn_groupcipher; + enum ieee80211_cipher rsn_groupmgmtcipher; + u_int16_t rsn_caps; + u_int8_t rsn_npmkids; + const u_int8_t *rsn_pmkids; +}; + +/* unaligned big endian access */ +#define BE_READ_2(p) \ + ((u_int16_t) \ + ((((const u_int8_t *)(p))[0] << 8) | \ + (((const u_int8_t *)(p))[1]))) + +#define BE_READ_8(p) \ + ((u_int64_t)(p)[0] << 56 | (u_int64_t)(p)[1] << 48 | \ + (u_int64_t)(p)[2] << 40 | (u_int64_t)(p)[3] << 32 | \ + (u_int64_t)(p)[4] << 24 | (u_int64_t)(p)[5] << 16 | \ + (u_int64_t)(p)[6] << 8 | (u_int64_t)(p)[7]) + +#define BE_WRITE_2(p, v) do { \ + ((u_int8_t *)(p))[0] = (v) >> 8; \ + ((u_int8_t *)(p))[1] = (v) & 0xff; \ +} while (0) + +#define BE_WRITE_8(p, v) do { \ + (p)[0] = (v) >> 56; (p)[1] = (v) >> 48; \ + (p)[2] = (v) >> 40; (p)[3] = (v) >> 32; \ + (p)[4] = (v) >> 24; (p)[5] = (v) >> 16; \ + (p)[6] = (v) >> 8; (p)[7] = (v); \ +} while (0) + +/* unaligned little endian access */ +#define LE_READ_2(p) \ + ((u_int16_t) \ + ((((const u_int8_t *)(p))[0]) | \ + (((const u_int8_t *)(p))[1] << 8))) + +#define LE_READ_4(p) \ + ((u_int32_t) \ + ((((const u_int8_t *)(p))[0]) | \ + (((const u_int8_t *)(p))[1] << 8) | \ + (((const u_int8_t *)(p))[2] << 16) | \ + (((const u_int8_t *)(p))[3] << 24))) + +#define LE_READ_6(p) \ + ((u_int64_t)(p)[5] << 40 | (u_int64_t)(p)[4] << 32 | \ + (u_int64_t)(p)[3] << 24 | (u_int64_t)(p)[2] << 16 | \ + (u_int64_t)(p)[1] << 8 | (u_int64_t)(p)[0]) + +#define LE_WRITE_2(p, v) do { \ + ((u_int8_t *)(p))[0] = (v) & 0xff; \ + ((u_int8_t *)(p))[1] = (v) >> 8; \ +} while (0) + +#define LE_WRITE_4(p, v) do { \ + (p)[3] = (v) >> 24; (p)[2] = (v) >> 16; \ + (p)[1] = (v) >> 8; (p)[0] = (v); \ +} while (0) + +#define LE_WRITE_6(p, v) do { \ + (p)[5] = (v) >> 40; (p)[4] = (v) >> 32; \ + (p)[3] = (v) >> 24; (p)[2] = (v) >> 16; \ + (p)[1] = (v) >> 8; (p)[0] = (v); \ +} while (0) + +#endif /* _NET80211_IEEE80211_PRIV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net80211/ieee80211_proto.h b/lib/libc/include/generic-openbsd/net80211/ieee80211_proto.h new file mode 100644 index 000000000000..46443677ce13 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net80211/ieee80211_proto.h @@ -0,0 +1,189 @@ +/* $OpenBSD: ieee80211_proto.h,v 1.50 2025/06/14 08:46:34 jsg Exp $ */ +/* $NetBSD: ieee80211_proto.h,v 1.3 2003/10/13 04:23:56 dyoung Exp $ */ + +/*- + * Copyright (c) 2001 Atsushi Onoe + * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/sys/net80211/ieee80211_proto.h,v 1.4 2003/08/19 22:17:03 sam Exp $ + */ +#ifndef _NET80211_IEEE80211_PROTO_H_ +#define _NET80211_IEEE80211_PROTO_H_ + +/* + * 802.11 protocol implementation definitions. + */ + +enum ieee80211_state { + IEEE80211_S_INIT = 0, /* default state */ + IEEE80211_S_SCAN = 1, /* scanning */ + IEEE80211_S_AUTH = 2, /* try to authenticate */ + IEEE80211_S_ASSOC = 3, /* try to assoc */ + IEEE80211_S_RUN = 4 /* associated */ +}; +#define IEEE80211_S_MAX (IEEE80211_S_RUN+1) + +#define IEEE80211_SEND_MGMT(_ic,_ni,_type,_arg) \ + ((*(_ic)->ic_send_mgmt)(_ic, _ni, _type, _arg, 0)) +/* shortcut */ +#define IEEE80211_SEND_ACTION(_ic,_ni,_categ,_action,_arg) \ + ((*(_ic)->ic_send_mgmt)(_ic, _ni, IEEE80211_FC0_SUBTYPE_ACTION, \ + (_categ) << 16 | (_action), _arg)) + +extern const char * const ieee80211_mgt_subtype_name[]; +extern const char * const ieee80211_state_name[IEEE80211_S_MAX]; +extern const char * const ieee80211_phymode_name[]; + +extern void ieee80211_proto_attach(struct ifnet *); +extern void ieee80211_proto_detach(struct ifnet *); + +struct ieee80211_node; +struct ieee80211_rxinfo; +struct ieee80211_rsnparams; +extern void ieee80211_rtm_80211info_task(void *); +extern void ieee80211_set_link_state(struct ieee80211com *, int); +extern u_int ieee80211_get_hdrlen(const struct ieee80211_frame *); +extern int ieee80211_classify(struct ieee80211com *, struct mbuf *); +extern void ieee80211_inputm(struct ifnet *, struct mbuf *, + struct ieee80211_node *, struct ieee80211_rxinfo *, + struct mbuf_list *); +extern void ieee80211_input(struct ifnet *, struct mbuf *, + struct ieee80211_node *, struct ieee80211_rxinfo *); +extern int ieee80211_output(struct ifnet *, struct mbuf *, struct sockaddr *, + struct rtentry *); +extern void ieee80211_recv_mgmt(struct ieee80211com *, struct mbuf *, + struct ieee80211_node *, struct ieee80211_rxinfo *, int); +extern int ieee80211_send_mgmt(struct ieee80211com *, struct ieee80211_node *, + int, int, int); +extern void ieee80211_eapol_key_input(struct ieee80211com *, struct mbuf *, + struct ieee80211_node *); +extern void ieee80211_tx_compressed_bar(struct ieee80211com *, + struct ieee80211_node *, int, uint16_t); +extern struct mbuf *ieee80211_encap(struct ifnet *, struct mbuf *, + struct ieee80211_node **); +extern struct mbuf *ieee80211_get_rts(struct ieee80211com *, + const struct ieee80211_frame *, u_int16_t); +extern struct mbuf *ieee80211_get_cts_to_self(struct ieee80211com *, + u_int16_t); +extern struct mbuf *ieee80211_get_compressed_bar(struct ieee80211com *, + struct ieee80211_node *, int, uint16_t); +extern struct mbuf *ieee80211_beacon_alloc(struct ieee80211com *, + struct ieee80211_node *); +extern int ieee80211_save_ie(const u_int8_t *, u_int8_t **); +extern void ieee80211_eapol_timeout(void *); +extern int ieee80211_send_4way_msg1(struct ieee80211com *, + struct ieee80211_node *); +extern int ieee80211_send_4way_msg2(struct ieee80211com *, + struct ieee80211_node *, const u_int8_t *, + const struct ieee80211_ptk *); +extern int ieee80211_send_4way_msg3(struct ieee80211com *, + struct ieee80211_node *); +extern int ieee80211_send_4way_msg4(struct ieee80211com *, + struct ieee80211_node *); +extern int ieee80211_send_group_msg1(struct ieee80211com *, + struct ieee80211_node *); +extern int ieee80211_send_group_msg2(struct ieee80211com *, + struct ieee80211_node *, const struct ieee80211_key *); +extern int ieee80211_send_eapol_key_req(struct ieee80211com *, + struct ieee80211_node *, u_int16_t, u_int64_t); +extern int ieee80211_pwrsave(struct ieee80211com *, struct mbuf *, + struct ieee80211_node *); +#define ieee80211_new_state(_ic, _nstate, _arg) \ + (((_ic)->ic_newstate)((_ic), (_nstate), (_arg))) +extern enum ieee80211_edca_ac ieee80211_up_to_ac(struct ieee80211com *, int); +extern u_int8_t *ieee80211_add_capinfo(u_int8_t *, struct ieee80211com *, + const struct ieee80211_node *); +extern u_int8_t *ieee80211_add_ssid(u_int8_t *, const u_int8_t *, u_int); +extern u_int8_t *ieee80211_add_rates(u_int8_t *, + const struct ieee80211_rateset *); +extern u_int8_t *ieee80211_add_ds_params(u_int8_t *, struct ieee80211com *, + const struct ieee80211_node *); +extern u_int8_t *ieee80211_add_tim(u_int8_t *, struct ieee80211com *); +extern u_int8_t *ieee80211_add_ibss_params(u_int8_t *, + const struct ieee80211_node *); +extern u_int8_t *ieee80211_add_edca_params(u_int8_t *, struct ieee80211com *); +extern u_int8_t *ieee80211_add_erp(u_int8_t *, struct ieee80211com *); +extern u_int8_t *ieee80211_add_qos_capability(u_int8_t *, + struct ieee80211com *); +extern u_int8_t *ieee80211_add_rsn(u_int8_t *, struct ieee80211com *, + const struct ieee80211_node *); +extern u_int8_t *ieee80211_add_wpa(u_int8_t *, struct ieee80211com *, + const struct ieee80211_node *); +extern u_int8_t *ieee80211_add_xrates(u_int8_t *, + const struct ieee80211_rateset *); +extern u_int8_t *ieee80211_add_htcaps(u_int8_t *, struct ieee80211com *); +extern u_int8_t *ieee80211_add_htop(u_int8_t *, struct ieee80211com *); +extern u_int8_t *ieee80211_add_vhtcaps(u_int8_t *, struct ieee80211com *); +extern u_int8_t *ieee80211_add_tie(u_int8_t *, u_int8_t, u_int32_t); + +extern int ieee80211_parse_rsn(struct ieee80211com *, const u_int8_t *, + struct ieee80211_rsnparams *); +extern int ieee80211_parse_wpa(struct ieee80211com *, const u_int8_t *, + struct ieee80211_rsnparams *); +extern void ieee80211_print_essid(const u_int8_t *, int); +#ifdef IEEE80211_DEBUG +extern void ieee80211_dump_pkt(const u_int8_t *, int, int, int); +#endif +extern int ieee80211_ibss_merge(struct ieee80211com *, + struct ieee80211_node *, u_int64_t); +extern void ieee80211_reset_erp(struct ieee80211com *); +extern void ieee80211_set_shortslottime(struct ieee80211com *, int); +extern void ieee80211_auth_open_confirm(struct ieee80211com *, + struct ieee80211_node *, uint16_t); +extern void ieee80211_auth_open(struct ieee80211com *, + const struct ieee80211_frame *, struct ieee80211_node *, + struct ieee80211_rxinfo *rs, u_int16_t, u_int16_t); +extern void ieee80211_stop_ampdu_tx(struct ieee80211com *, + struct ieee80211_node *, int); +extern void ieee80211_gtk_rekey_timeout(void *); +extern int ieee80211_keyrun(struct ieee80211com *, u_int8_t *); +extern void ieee80211_setkeys(struct ieee80211com *); +extern void ieee80211_setkeysdone(struct ieee80211com *); +extern void ieee80211_sa_query_timeout(void *); +extern void ieee80211_sa_query_request(struct ieee80211com *, + struct ieee80211_node *); +extern void ieee80211_ht_negotiate(struct ieee80211com *, + struct ieee80211_node *); +extern void ieee80211_vht_negotiate(struct ieee80211com *, + struct ieee80211_node *); +extern void ieee80211_tx_ba_timeout(void *); +extern void ieee80211_rx_ba_timeout(void *); +extern int ieee80211_addba_request(struct ieee80211com *, + struct ieee80211_node *, u_int16_t, u_int8_t); +extern void ieee80211_delba_request(struct ieee80211com *, + struct ieee80211_node *, u_int16_t, u_int8_t, u_int8_t); +extern void ieee80211_addba_req_accept(struct ieee80211com *, + struct ieee80211_node *, uint8_t); +extern void ieee80211_addba_req_refuse(struct ieee80211com *, + struct ieee80211_node *, uint8_t); +extern void ieee80211_addba_resp_accept(struct ieee80211com *, + struct ieee80211_node *, uint8_t); +extern void ieee80211_addba_resp_refuse(struct ieee80211com *, + struct ieee80211_node *, uint8_t, uint16_t); +extern void ieee80211_output_ba_move_window(struct ieee80211com *, + struct ieee80211_node *, uint8_t, uint16_t); + +#endif /* _NET80211_IEEE80211_PROTO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net80211/ieee80211_ra.h b/lib/libc/include/generic-openbsd/net80211/ieee80211_ra.h new file mode 100644 index 000000000000..8ead145b8481 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net80211/ieee80211_ra.h @@ -0,0 +1,82 @@ +/* $OpenBSD: ieee80211_ra.h,v 1.2 2021/10/11 09:01:06 stsp Exp $ */ + +/* + * Copyright (c) 2021 Christian Ehrhardt + * Copyright (c) 2021 Stefan Sperling + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Goodput statistics struct. Measures the effective data rate of an MCS. + * All uint64_t numbers in this struct use fixed-point arithmetic. + */ +struct ieee80211_ra_goodput_stats { + uint64_t measured; /* Most recently measured goodput. */ + uint64_t average; /* Average measured goodput. */ + uint64_t stddeviation; /* Goodput standard deviation. */ + uint64_t loss; /* This rate's loss percentage SFER. */ + uint32_t nprobe_pkts; /* Number of packets in current probe. */ + uint32_t nprobe_fail; /* Number of failed packets. */ +}; + +/* + * Rate adaptation state. + * + * Drivers should not modify any fields of this structure directly. + * Use ieee80211_ra_init() and ieee80211_ra_add_stats() only. + */ +struct ieee80211_ra_node { + /* Bitmaps MCS 0-31. */ + uint32_t valid_probes; + uint32_t valid_rates; + uint32_t candidate_rates; + uint32_t probed_rates; + + /* Probing state. */ + int probing; +#define IEEE80211_RA_NOT_PROBING 0x0 +#define IEEE80211_RA_PROBING_DOWN 0x1 +#define IEEE80211_RA_PROBING_UP 0x2 +#define IEEE80211_RA_PROBING_INTER 0x4 /* combined with UP or DOWN */ + + /* The current best MCS found by probing. */ + int best_mcs; + + /* Goodput statistics for each MCS. */ + struct ieee80211_ra_goodput_stats g[IEEE80211_HT_RATESET_NUM_MCS]; +}; + +/* Initialize rate adaptation state. */ +void ieee80211_ra_node_init(struct ieee80211_ra_node *); + +/* + * Drivers report information about 802.11n/HT Tx attempts here. + * mcs: The HT MCS used during this Tx attempt. + * total: How many Tx attempts (initial attempt + any retries) were made? + * fail: How many of these Tx attempts failed? + */ +void ieee80211_ra_add_stats_ht(struct ieee80211_ra_node *, + struct ieee80211com *, struct ieee80211_node *, + int mcs, unsigned int total, unsigned int fail); + +/* Drivers call this function to update ni->ni_txmcs. */ +void ieee80211_ra_choose(struct ieee80211_ra_node *, + struct ieee80211com *, struct ieee80211_node *); + +/* Get the HT rateset for a particular HT MCS with 40MHz and/or SGI on/off. */ +const struct ieee80211_ht_rateset * ieee80211_ra_get_ht_rateset(int mcs, + int chan40, int sgi); + +/* Check whether SGI should be used. */ +int ieee80211_ra_use_ht_sgi(struct ieee80211_node *); \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net80211/ieee80211_ra_vht.h b/lib/libc/include/generic-openbsd/net80211/ieee80211_ra_vht.h new file mode 100644 index 000000000000..bb49453b3674 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net80211/ieee80211_ra_vht.h @@ -0,0 +1,91 @@ +/* $OpenBSD: ieee80211_ra_vht.h,v 1.1 2022/03/19 10:25:09 stsp Exp $ */ + +/* + * Copyright (c) 2021 Christian Ehrhardt + * Copyright (c) 2021, 2022 Stefan Sperling + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Goodput statistics struct. Measures the effective data rate of a rate. + * All uint64_t numbers in this struct use fixed-point arithmetic. + */ +struct ieee80211_ra_vht_goodput_stats { + uint64_t measured; /* Most recently measured goodput. */ + uint64_t average; /* Average measured goodput. */ + uint64_t stddeviation; /* Goodput standard deviation. */ + uint64_t loss; /* This rate's loss percentage SFER. */ + uint32_t nprobe_pkts; /* Number of packets in current probe. */ + uint32_t nprobe_fail; /* Number of failed packets. */ +}; + +/* + * Rate adaptation state. + * + * Drivers should not modify any fields of this structure directly. + * Use ieee80211_ra_vht_init() and ieee80211_ra_vht_add_stats() only. + */ +struct ieee80211_ra_vht_node { + /* Bitmaps for MCS 0-9 for a given number of spatial streams. */ + uint16_t valid_probes[IEEE80211_VHT_NUM_SS]; + uint16_t valid_rates[IEEE80211_VHT_NUM_SS]; + uint16_t candidate_rates[IEEE80211_VHT_NUM_SS]; + uint16_t probed_rates[IEEE80211_VHT_NUM_SS]; + + /* Maximum usable MCS per given number of spatial streams. */ + int max_mcs[IEEE80211_VHT_NUM_SS]; + + /* Probing state. */ + int probing; +#define IEEE80211_RA_NOT_PROBING 0x0 +#define IEEE80211_RA_PROBING_DOWN 0x1 +#define IEEE80211_RA_PROBING_UP 0x2 +#define IEEE80211_RA_PROBING_INTER 0x4 /* combined with UP or DOWN */ + + /* The current best MCS,NSS found by probing. */ + int best_mcs; + int best_nss; + + /* Goodput statistics for each rate. */ + struct ieee80211_ra_vht_goodput_stats + g[IEEE80211_VHT_NUM_RATESETS][IEEE80211_VHT_RATESET_MAX_NRATES]; +}; + +/* Initialize rate adaptation state. */ +void ieee80211_ra_vht_node_init(struct ieee80211_ra_vht_node *); + +/* + * Drivers report information about 802.11ac/VHT Tx attempts here. + * mcs: The VHT MCS used during this Tx attempt. + * nss: The number of spatial streams used during this Tx attempt. + * total: How many Tx attempts (initial attempt + any retries) were made? + * fail: How many of these Tx attempts failed? + */ +void ieee80211_ra_vht_add_stats(struct ieee80211_ra_vht_node *, + struct ieee80211com *, struct ieee80211_node *, + int mcs, int nss, unsigned int total, unsigned int fail); + +/* Drivers call this function to update ni->ni_txmcs and ni->ni_vht_ss. */ +void ieee80211_ra_vht_choose(struct ieee80211_ra_vht_node *, + struct ieee80211com *, struct ieee80211_node *); + +/* + * Get the VHT rateset for a particular VHT MCS, NSS, with 40MHz, 80MHz, + * and/or SGI on/off. + */ +const struct ieee80211_vht_rateset * ieee80211_ra_vht_get_rateset(int mcs, + int nss, int chan40, int chan80, int sgi); + +/* Check whether SGI should be used. */ +int ieee80211_ra_vht_use_sgi(struct ieee80211_node *); \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net80211/ieee80211_radiotap.h b/lib/libc/include/generic-openbsd/net80211/ieee80211_radiotap.h new file mode 100644 index 000000000000..302030262b70 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net80211/ieee80211_radiotap.h @@ -0,0 +1,215 @@ +/* $OpenBSD: ieee80211_radiotap.h,v 1.17 2022/03/14 15:06:04 stsp Exp $ */ +/* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.3 2004/04/05 22:13:21 sam Exp $ */ +/* $NetBSD: ieee80211_radiotap.h,v 1.9 2004/06/06 04:13:28 dyoung Exp $ */ + +/*- + * Copyright (c) 2003, 2004 David Young. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``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 DAVID + * YOUNG 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 _NET_IF_IEEE80211RADIOTAP_H_ +#define _NET_IF_IEEE80211RADIOTAP_H_ + +/* A generic radio capture format is desirable. There is one for + * Linux, but it is neither rigidly defined (there were not even + * units given for some fields) nor easily extensible. + * + * I suggest the following extensible radio capture format. It is + * based on a bitmap indicating which fields are present. + * + * I am trying to describe precisely what the application programmer + * should expect in the following, and for that reason I tell the + * units and origin of each measurement (where it applies), or else I + * use sufficiently weaselly language ("is a monotonically nondecreasing + * function of...") that I cannot set false expectations for lawyerly + * readers. + */ + +/* XXX tcpdump/libpcap do not tolerate variable-length headers, + * yet, so we pad every radiotap header to 64 bytes. Ugh. + */ +#define IEEE80211_RADIOTAP_HDRLEN 64 + +/* The radio capture header precedes the 802.11 header. */ +struct ieee80211_radiotap_header { + u_int8_t it_version; /* Version 0. Only increases + * for drastic changes, + * introduction of compatible + * new fields does not count. + */ + u_int8_t it_pad; + u_int16_t it_len; /* length of the whole + * header in bytes, including + * it_version, it_pad, + * it_len, and data fields. + */ + u_int32_t it_present; /* A bitmap telling which + * fields are present. Set bit 31 + * (0x80000000) to extend the + * bitmap by another 32 bits. + * Additional extensions are made + * by setting bit 31. + */ +} __packed; + +/* Name Data type Units + * ---- --------- ----- + * + * IEEE80211_RADIOTAP_TSFT u_int64_t microseconds + * + * Value in microseconds of the MAC's 64-bit 802.11 Time + * Synchronization Function timer when the first bit of the + * MPDU arrived at the MAC. For received frames, only. + * + * IEEE80211_RADIOTAP_CHANNEL 2 x u_int16_t MHz, bitmap + * + * Tx/Rx frequency in MHz, followed by flags (see below). + * + * IEEE80211_RADIOTAP_FHSS u_int16_t see below + * + * For frequency-hopping radios, the hop set (first byte) + * and pattern (second byte). + * + * IEEE80211_RADIOTAP_RATE u_int8_t 500kb/s or MCS index + * + * Tx/Rx data rate in units of 500kb/s. If the high bit (0x80) is set + * the remaining bits contain an MCS index instead of a date rate. + * + * IEEE80211_RADIOTAP_DBM_ANTSIGNAL int8_t decibels from + * one milliwatt (dBm) + * + * RF signal power at the antenna, decibel difference from + * one milliwatt. + * + * IEEE80211_RADIOTAP_DBM_ANTNOISE int8_t decibels from + * one milliwatt (dBm) + * + * RF noise power at the antenna, decibel difference from one + * milliwatt. + * + * IEEE80211_RADIOTAP_DB_ANTSIGNAL u_int8_t decibel (dB) + * + * RF signal power at the antenna, decibel difference from an + * arbitrary, fixed reference. + * + * IEEE80211_RADIOTAP_DB_ANTNOISE u_int8_t decibel (dB) + * + * RF noise power at the antenna, decibel difference from an + * arbitrary, fixed reference point. + * + * IEEE80211_RADIOTAP_BARKER_CODE_LOCK u_int16_t unitless + * + * Quality of Barker code lock. Unitless. Monotonically + * nondecreasing with "better" lock strength. Called "Signal + * Quality" in datasheets. (Is there a standard way to measure + * this?) + * + * IEEE80211_RADIOTAP_TX_ATTENUATION u_int16_t unitless + * + * Transmit power expressed as unitless distance from max + * power set at factory calibration. 0 is max power. + * Monotonically nondecreasing with lower power levels. + * + * IEEE80211_RADIOTAP_DB_TX_ATTENUATION u_int16_t decibels (dB) + * + * Transmit power expressed as decibel distance from max power + * set at factory calibration. 0 is max power. Monotonically + * nondecreasing with lower power levels. + * + * IEEE80211_RADIOTAP_DBM_TX_POWER int8_t decibels from + * one milliwatt (dBm) + * + * Transmit power expressed as dBm (decibels from a 1 milliwatt + * reference). This is the absolute power level measured at + * the antenna port. + * + * IEEE80211_RADIOTAP_FLAGS u_int8_t bitmap + * + * Properties of transmitted and received frames. See flags + * defined below. + * + * IEEE80211_RADIOTAP_ANTENNA u_int8_t antenna index + * + * Unitless indication of the Rx/Tx antenna for this packet. + * The first antenna is antenna 0. + * + * IEEE80211_RADIOTAP_FCS u_int32_t data + * + * FCS from frame in network byte order. + * + * IEEE80211_RADIOTAP_RSSI 2x u_int8_t RSSI, max RSSI + * + * A relative Received Signal Strength Index + */ +enum ieee80211_radiotap_type { + IEEE80211_RADIOTAP_TSFT = 0, + IEEE80211_RADIOTAP_FLAGS = 1, + IEEE80211_RADIOTAP_RATE = 2, + IEEE80211_RADIOTAP_CHANNEL = 3, + IEEE80211_RADIOTAP_FHSS = 4, + IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, + IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, + IEEE80211_RADIOTAP_LOCK_QUALITY = 7, + IEEE80211_RADIOTAP_TX_ATTENUATION = 8, + IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9, + IEEE80211_RADIOTAP_DBM_TX_POWER = 10, + IEEE80211_RADIOTAP_ANTENNA = 11, + IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, + IEEE80211_RADIOTAP_DB_ANTNOISE = 13, + IEEE80211_RADIOTAP_FCS = 14, + IEEE80211_RADIOTAP_RSSI = 16, + IEEE80211_RADIOTAP_EXT = 31 +}; + +#ifndef _KERNEL +/* For IEEE80211_RADIOTAP_CHANNEL */ +#define IEEE80211_CHAN_CCK 0x0020 /* CCK channel */ +#define IEEE80211_CHAN_OFDM 0x0040 /* OFDM channel */ +#define IEEE80211_CHAN_2GHZ 0x0080 /* 2 GHz spectrum channel */ +#define IEEE80211_CHAN_5GHZ 0x0100 /* 5 GHz spectrum channel */ +#define IEEE80211_CHAN_PASSIVE 0x0200 /* Only passive scan allowed */ +#define IEEE80211_CHAN_DYN 0x0400 /* Dynamic CCK-OFDM channel */ +#define IEEE80211_CHAN_GFSK 0x0800 /* GFSK channel (FHSS PHY) */ +#define IEEE80211_CHAN_XR 0x1000 /* Extended range OFDM channel */ +#define IEEE80211_CHAN_HT 0x2000 /* 11n/HT channel */ +#define IEEE80211_CHAN_VHT 0x4000 /* 11ac/VHT channel */ +#define IEEE80211_CHAN_40MHZ 0x8000 /* use of 40 MHz is allowed */ +#endif /* !_KERNEL */ + +/* For IEEE80211_RADIOTAP_FLAGS */ +#define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received + * during CFP + */ +#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received + * with short + * preamble + */ +#define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received + * with WEP encryption + */ +#define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received + * with fragmentation + */ +#define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */ + +#endif /* _NET_IF_IEEE80211RADIOTAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net80211/ieee80211_regdomain.h b/lib/libc/include/generic-openbsd/net80211/ieee80211_regdomain.h new file mode 100644 index 000000000000..e4bfc67ef508 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net80211/ieee80211_regdomain.h @@ -0,0 +1,768 @@ +/* $OpenBSD: ieee80211_regdomain.h,v 1.9 2016/01/12 09:28:09 stsp Exp $ */ + +/* + * Copyright (c) 2004, 2005 Reyk Floeter + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _NET80211_IEEE80211_REGDOMAIN_H_ +#define _NET80211_IEEE80211_REGDOMAIN_H_ + +typedef u_int32_t ieee80211_regdomain_t; + +enum ieee80211_regdomain { + DMN_DEFAULT = 0x00, + DMN_NULL_WORLD = 0x03, + DMN_NULL_ETSIB = 0x07, + DMN_NULL_ETSIC = 0x08, + DMN_FCC1_FCCA = 0x10, + DMN_FCC1_WORLD = 0x11, + DMN_FCC2_FCCA = 0x20, + DMN_FCC2_WORLD = 0x21, + DMN_FCC2_ETSIC = 0x22, + DMN_FRANCE_NULL = 0x31, + DMN_FCC3_FCCA = 0x3A, + DMN_ETSI1_WORLD = 0x37, + DMN_ETSI3_ETSIA = 0x32, + DMN_ETSI2_WORLD = 0x35, + DMN_ETSI3_WORLD = 0x36, + DMN_ETSI4_WORLD = 0x30, + DMN_ETSI4_ETSIC = 0x38, + DMN_ETSI5_WORLD = 0x39, + DMN_ETSI6_WORLD = 0x34, + DMN_ETSI_NULL = 0x33, + DMN_MKK1_MKKA = 0x40, + DMN_MKK1_MKKB = 0x41, + DMN_APL4_WORLD = 0x42, + DMN_MKK2_MKKA = 0x43, + DMN_APL_NULL = 0x44, + DMN_APL2_WORLD = 0x45, + DMN_APL2_APLC = 0x46, + DMN_APL3_WORLD = 0x47, + DMN_MKK1_FCCA = 0x48, + DMN_APL2_APLD = 0x49, + DMN_MKK1_MKKA1 = 0x4A, + DMN_MKK1_MKKA2 = 0x4B, + DMN_APL1_WORLD = 0x52, + DMN_APL1_FCCA = 0x53, + DMN_APL1_APLA = 0x54, + DMN_APL1_ETSIC = 0x55, + DMN_APL2_ETSIC = 0x56, + DMN_APL5_WORLD = 0x58, + DMN_WOR0_WORLD = 0x60, + DMN_WOR1_WORLD = 0x61, + DMN_WOR2_WORLD = 0x62, + DMN_WOR3_WORLD = 0x63, + DMN_WOR4_WORLD = 0x64, + DMN_WOR5_ETSIC = 0x65, + DMN_WOR01_WORLD = 0x66, + DMN_WOR02_WORLD = 0x67, + DMN_EU1_WORLD = 0x68, + DMN_WOR9_WORLD = 0x69, + DMN_WORA_WORLD = 0x6A, + + DMN_APL1 = 0xf0000001, + DMN_APL2 = 0xf0000002, + DMN_APL3 = 0xf0000004, + DMN_APL4 = 0xf0000008, + DMN_APL5 = 0xf0000010, + DMN_ETSI1 = 0xf0000020, + DMN_ETSI2 = 0xf0000040, + DMN_ETSI3 = 0xf0000080, + DMN_ETSI4 = 0xf0000100, + DMN_ETSI5 = 0xf0000200, + DMN_ETSI6 = 0xf0000400, + DMN_ETSIA = 0xf0000800, + DMN_ETSIB = 0xf0001000, + DMN_ETSIC = 0xf0002000, + DMN_FCC1 = 0xf0004000, + DMN_FCC2 = 0xf0008000, + DMN_FCC3 = 0xf0010000, + DMN_FCCA = 0xf0020000, + DMN_APLD = 0xf0040000, + DMN_MKK1 = 0xf0080000, + DMN_MKK2 = 0xf0100000, + DMN_MKKA = 0xf0200000, + DMN_NULL = 0xf0400000, + DMN_WORLD = 0xf0800000, + DMN_DEBUG = 0xf1000000 /* used for debugging */ +}; + +#define IEEE80211_DMN(_d) ((_d) & ~0xf0000000) + +struct ieee80211_regdomainname { + u_int32_t rn_domain; + const char *rn_name; +}; + +#define IEEE80211_REGDOMAIN_NAMES { \ + { DMN_APL1, "APL1" }, \ + { DMN_APL1_APLA, "APL1A" }, \ + { DMN_APL1_ETSIC, "APL1_ETSIC" }, \ + { DMN_APL1_FCCA, "APL1_FCCA" }, \ + { DMN_APL1_WORLD, "APL1W" }, \ + { DMN_APL2, "APL2" }, \ + { DMN_APL2_APLC, "APL2C" }, \ + { DMN_APL2_APLD, "APL2D" }, \ + { DMN_APL2_ETSIC, "APL2_ETSIC" }, \ + { DMN_APL2_WORLD, "APL2W" }, \ + { DMN_APL3, "APL3" }, \ + { DMN_APL3_WORLD, "APL3W" }, \ + { DMN_APL4, "APL4" }, \ + { DMN_APL4_WORLD, "APL4W" }, \ + { DMN_APL5, "APL5" }, \ + { DMN_APL5_WORLD, "APL5W" }, \ + { DMN_APLD, "APLD" }, \ + { DMN_APL_NULL, "APL" }, \ + { DMN_DEBUG, "DEBUG" }, \ + { DMN_ETSI1, "ETSI1" }, \ + { DMN_ETSI1_WORLD, "ETSI1W" }, \ + { DMN_ETSI2, "ETSI2" }, \ + { DMN_ETSI2_WORLD, "ETSI2W" }, \ + { DMN_ETSI3, "ETSI3" }, \ + { DMN_ETSI3_ETSIA, "ETSI3A" }, \ + { DMN_ETSI3_WORLD, "ETSI3W," }, \ + { DMN_ETSI4, "ETSI4" }, \ + { DMN_ETSI4_ETSIC, "ETSI4C" }, \ + { DMN_ETSI4_WORLD, "ETSI4W" }, \ + { DMN_ETSI5, "ETSI5" }, \ + { DMN_ETSI5_WORLD, "ETSI5W" }, \ + { DMN_ETSI6, "ETSI6" }, \ + { DMN_ETSI6_WORLD, "ETSI6W" }, \ + { DMN_ETSIA, "ETSIA" }, \ + { DMN_ETSIB, "ETSIB" }, \ + { DMN_ETSIC, "ETSIC" }, \ + { DMN_ETSI_NULL, "ETSI" }, \ + { DMN_EU1_WORLD, "EU1W" }, \ + { DMN_FCC1, "FCC1" }, \ + { DMN_FCC1_FCCA, "FCC1A" }, \ + { DMN_FCC1_WORLD, "FCC1W" }, \ + { DMN_FCC2, "FCC2" }, \ + { DMN_FCC2_ETSIC, "FCC2C" }, \ + { DMN_FCC2_FCCA, "FCC2A" }, \ + { DMN_FCC2_WORLD, "FCC2W" }, \ + { DMN_FCC3, "FCC3" }, \ + { DMN_FCC3_FCCA, "FCC3A" }, \ + { DMN_FCCA, "FCCA" }, \ + { DMN_FRANCE_NULL, "FRANCE" }, \ + { DMN_MKK1, "MKK1" }, \ + { DMN_MKK1_FCCA, "MKK1_FCCA" }, \ + { DMN_MKK1_MKKA, "MKK1A" }, \ + { DMN_MKK1_MKKA1, "MKK1A1" }, \ + { DMN_MKK1_MKKA2, "MKK1A2" }, \ + { DMN_MKK1_MKKB, "MKK1B" }, \ + { DMN_MKK2, "MKK2" }, \ + { DMN_MKK2_MKKA, "MKK2A" }, \ + { DMN_MKKA, "MKKA" }, \ + { DMN_DEFAULT, "NONE" }, \ + { DMN_NULL, "NONE" }, \ + { DMN_NULL_ETSIB, "ETSIB" }, \ + { DMN_NULL_ETSIC, "ETSIC" }, \ + { DMN_WOR01_WORLD, "WOR01W" }, \ + { DMN_WOR02_WORLD, "WOR02W" }, \ + { DMN_WOR0_WORLD, "WOR0W" }, \ + { DMN_WOR1_WORLD, "WOR1W" }, \ + { DMN_WOR2_WORLD, "WOR2W" }, \ + { DMN_WOR3_WORLD, "WOR3W" }, \ + { DMN_WOR4_WORLD, "WOR4W" }, \ + { DMN_WOR5_ETSIC, "WOR5_ETSIC" }, \ + { DMN_WOR9_WORLD, "WOR9W" }, \ + { DMN_WORA_WORLD, "WORAW" }, \ + { DMN_NULL_WORLD, "WORLD" }, \ + { DMN_WORLD, "WORLD" } \ +} + +struct ieee80211_regdomainmap { + u_int16_t rm_domain; + u_int32_t rm_domain_5ghz; + u_int32_t rm_domain_2ghz; +}; + +#define IEEE80211_REGDOMAIN_MAP { \ + { DMN_DEFAULT, DMN_DEBUG, DMN_DEBUG }, \ + { DMN_NULL_WORLD, DMN_NULL, DMN_WORLD }, \ + { DMN_NULL_ETSIB, DMN_NULL, DMN_ETSIB }, \ + { DMN_NULL_ETSIC, DMN_NULL, DMN_ETSIC }, \ + { DMN_FCC1_FCCA, DMN_FCC1, DMN_FCCA }, \ + { DMN_FCC1_WORLD, DMN_FCC1, DMN_WORLD }, \ + { DMN_FCC2_FCCA, DMN_FCC2, DMN_FCCA }, \ + { DMN_FCC2_WORLD, DMN_FCC2, DMN_WORLD }, \ + { DMN_FCC2_ETSIC, DMN_FCC2, DMN_ETSIC }, \ + { DMN_FRANCE_NULL, DMN_ETSI3, DMN_ETSI3 }, \ + { DMN_FCC3_FCCA, DMN_FCC3, DMN_WORLD }, \ + { DMN_ETSI1_WORLD, DMN_ETSI1, DMN_WORLD }, \ + { DMN_ETSI3_ETSIA, DMN_ETSI3, DMN_WORLD }, \ + { DMN_ETSI2_WORLD, DMN_ETSI2, DMN_WORLD }, \ + { DMN_ETSI3_WORLD, DMN_ETSI3, DMN_WORLD }, \ + { DMN_ETSI4_WORLD, DMN_ETSI4, DMN_WORLD }, \ + { DMN_ETSI4_ETSIC, DMN_ETSI4, DMN_ETSIC }, \ + { DMN_ETSI5_WORLD, DMN_ETSI5, DMN_WORLD }, \ + { DMN_ETSI6_WORLD, DMN_ETSI6, DMN_WORLD }, \ + { DMN_ETSI_NULL, DMN_ETSI1, DMN_ETSI1 }, \ + { DMN_MKK1_MKKA, DMN_MKK1, DMN_MKKA }, \ + { DMN_MKK1_MKKB, DMN_MKK1, DMN_MKKA }, \ + { DMN_APL4_WORLD, DMN_APL4, DMN_WORLD }, \ + { DMN_MKK2_MKKA, DMN_MKK2, DMN_MKKA }, \ + { DMN_APL_NULL, DMN_APL1, DMN_NULL }, \ + { DMN_APL2_WORLD, DMN_APL2, DMN_WORLD }, \ + { DMN_APL2_APLC, DMN_APL2, DMN_WORLD }, \ + { DMN_APL3_WORLD, DMN_APL3, DMN_WORLD }, \ + { DMN_MKK1_FCCA, DMN_MKK1, DMN_FCCA }, \ + { DMN_APL2_APLD, DMN_APL2, DMN_APLD }, \ + { DMN_MKK1_MKKA1, DMN_MKK1, DMN_MKKA }, \ + { DMN_MKK1_MKKA2, DMN_MKK1, DMN_MKKA }, \ + { DMN_APL1_WORLD, DMN_APL1, DMN_WORLD }, \ + { DMN_APL1_FCCA, DMN_APL1, DMN_FCCA }, \ + { DMN_APL1_APLA, DMN_APL1, DMN_WORLD }, \ + { DMN_APL1_ETSIC, DMN_APL1, DMN_ETSIC }, \ + { DMN_APL2_ETSIC, DMN_APL2, DMN_ETSIC }, \ + { DMN_APL5_WORLD, DMN_APL5, DMN_WORLD }, \ + { DMN_WOR0_WORLD, DMN_WORLD, DMN_WORLD }, \ + { DMN_WOR1_WORLD, DMN_WORLD, DMN_WORLD }, \ + { DMN_WOR2_WORLD, DMN_WORLD, DMN_WORLD }, \ + { DMN_WOR3_WORLD, DMN_WORLD, DMN_WORLD }, \ + { DMN_WOR4_WORLD, DMN_WORLD, DMN_WORLD }, \ + { DMN_WOR5_ETSIC, DMN_WORLD, DMN_WORLD }, \ + { DMN_WOR01_WORLD, DMN_WORLD, DMN_WORLD }, \ + { DMN_WOR02_WORLD, DMN_WORLD, DMN_WORLD }, \ + { DMN_EU1_WORLD, DMN_ETSI1, DMN_WORLD }, \ + { DMN_WOR9_WORLD, DMN_WORLD, DMN_WORLD }, \ + { DMN_WORA_WORLD, DMN_WORLD, DMN_WORLD }, \ +} + +enum ieee80211_countrycode { + CTRY_DEFAULT = 0, /* Default domain (NA) */ + CTRY_ALBANIA = 8, /* Albania */ + CTRY_ALGERIA = 12, /* Algeria */ + CTRY_ARGENTINA = 32, /* Argentina */ + CTRY_ARMENIA = 51, /* Armenia */ + CTRY_AUSTRALIA = 36, /* Australia */ + CTRY_AUSTRIA = 40, /* Austria */ + CTRY_AZERBAIJAN = 31, /* Azerbaijan */ + CTRY_BAHRAIN = 48, /* Bahrain */ + CTRY_BELARUS = 112, /* Belarus */ + CTRY_BELGIUM = 56, /* Belgium */ + CTRY_BELIZE = 84, /* Belize */ + CTRY_BOLIVIA = 68, /* Bolivia */ + CTRY_BRAZIL = 76, /* Brazil */ + CTRY_BRUNEI_DARUSSALAM = 96, /* Brunei Darussalam */ + CTRY_BULGARIA = 100, /* Bulgaria */ + CTRY_CANADA = 124, /* Canada */ + CTRY_CHILE = 152, /* Chile */ + CTRY_CHINA = 156, /* People's Republic of China */ + CTRY_COLOMBIA = 170, /* Colombia */ + CTRY_COSTA_RICA = 188, /* Costa Rica */ + CTRY_CROATIA = 191, /* Croatia */ + CTRY_CYPRUS = 196, /* Cyprus */ + CTRY_CZECH = 203, /* Czech Republic */ + CTRY_DENMARK = 208, /* Denmark */ + CTRY_DOMINICAN_REPUBLIC = 214, /* Dominican Republic */ + CTRY_ECUADOR = 218, /* Ecuador */ + CTRY_EGYPT = 818, /* Egypt */ + CTRY_EL_SALVADOR = 222, /* El Salvador */ + CTRY_ESTONIA = 233, /* Estonia */ + CTRY_FAEROE_ISLANDS = 234, /* Faeroe Islands */ + CTRY_FINLAND = 246, /* Finland */ + CTRY_FRANCE = 250, /* France */ + CTRY_FRANCE2 = 255, /* France2 */ + CTRY_GEORGIA = 268, /* Georgia */ + CTRY_GERMANY = 276, /* Germany */ + CTRY_GREECE = 300, /* Greece */ + CTRY_GUATEMALA = 320, /* Guatemala */ + CTRY_HONDURAS = 340, /* Honduras */ + CTRY_HONG_KONG = 344, /* Hong Kong S.A.R., P.R.C. */ + CTRY_HUNGARY = 348, /* Hungary */ + CTRY_ICELAND = 352, /* Iceland */ + CTRY_INDIA = 356, /* India */ + CTRY_INDONESIA = 360, /* Indonesia */ + CTRY_IRAN = 364, /* Iran */ + CTRY_IRAQ = 368, /* Iraq */ + CTRY_IRELAND = 372, /* Ireland */ + CTRY_ISRAEL = 376, /* Israel */ + CTRY_ITALY = 380, /* Italy */ + CTRY_JAMAICA = 388, /* Jamaica */ + CTRY_JAPAN = 392, /* Japan */ + CTRY_JAPAN1 = 393, /* Japan (JP1) */ + CTRY_JAPAN2 = 394, /* Japan (JP0) */ + CTRY_JAPAN3 = 395, /* Japan (JP1-1) */ + CTRY_JAPAN4 = 396, /* Japan (JE1) */ + CTRY_JAPAN5 = 397, /* Japan (JE2) */ + CTRY_JORDAN = 400, /* Jordan */ + CTRY_KAZAKHSTAN = 398, /* Kazakhstan */ + CTRY_KENYA = 404, /* Kenya */ + CTRY_KOREA_NORTH = 408, /* North Korea */ + CTRY_KOREA_ROC = 410, /* South Korea */ + CTRY_KOREA_ROC2 = 411, /* South Korea */ + CTRY_KUWAIT = 414, /* Kuwait */ + CTRY_LATVIA = 428, /* Latvia */ + CTRY_LEBANON = 422, /* Lebanon */ + CTRY_LIBYA = 434, /* Libya */ + CTRY_LIECHTENSTEIN = 438, /* Liechtenstein */ + CTRY_LITHUANIA = 440, /* Lithuania */ + CTRY_LUXEMBOURG = 442, /* Luxembourg */ + CTRY_MACAU = 446, /* Macau */ + CTRY_MACEDONIA = 807, /* Republic of Macedonia */ + CTRY_MALAYSIA = 458, /* Malaysia */ + CTRY_MEXICO = 484, /* Mexico */ + CTRY_MONACO = 492, /* Principality of Monaco */ + CTRY_MOROCCO = 504, /* Morocco */ + CTRY_NETHERLANDS = 528, /* Netherlands */ + CTRY_NEW_ZEALAND = 554, /* New Zealand */ + CTRY_NICARAGUA = 558, /* Nicaragua */ + CTRY_NORWAY = 578, /* Norway */ + CTRY_OMAN = 512, /* Oman */ + CTRY_PAKISTAN = 586, /* Islamic Republic of Pakistan */ + CTRY_PANAMA = 591, /* Panama */ + CTRY_PARAGUAY = 600, /* Paraguay */ + CTRY_PERU = 604, /* Peru */ + CTRY_PHILIPPINES = 608, /* Republic of the Philippines */ + CTRY_POLAND = 616, /* Poland */ + CTRY_PORTUGAL = 620, /* Portugal */ + CTRY_PUERTO_RICO = 630, /* Puerto Rico */ + CTRY_QATAR = 634, /* Qatar */ + CTRY_ROMANIA = 642, /* Romania */ + CTRY_RUSSIA = 643, /* Russia */ + CTRY_SAUDI_ARABIA = 682, /* Saudi Arabia */ + CTRY_SINGAPORE = 702, /* Singapore */ + CTRY_SLOVAKIA = 703, /* Slovak Republic */ + CTRY_SLOVENIA = 705, /* Slovenia */ + CTRY_SOUTH_AFRICA = 710, /* South Africa */ + CTRY_SPAIN = 724, /* Spain */ + CTRY_SRI_LANKA = 728, /* Sri Lanka */ + CTRY_SWEDEN = 752, /* Sweden */ + CTRY_SWITZERLAND = 756, /* Switzerland */ + CTRY_SYRIA = 760, /* Syria */ + CTRY_TAIWAN = 158, /* Taiwan */ + CTRY_THAILAND = 764, /* Thailand */ + CTRY_TRINIDAD_Y_TOBAGO = 780, /* Trinidad y Tobago */ + CTRY_TUNISIA = 788, /* Tunisia */ + CTRY_TURKEY = 792, /* Turkey */ + CTRY_UAE = 784, /* U.A.E. */ + CTRY_UKRAINE = 804, /* Ukraine */ + CTRY_UNITED_KINGDOM = 826, /* United Kingdom */ + CTRY_UNITED_STATES = 840, /* United States */ + CTRY_URUGUAY = 858, /* Uruguay */ + CTRY_UZBEKISTAN = 860, /* Uzbekistan */ + CTRY_VENEZUELA = 862, /* Venezuela */ + CTRY_VIET_NAM = 704, /* Viet Nam */ + CTRY_YEMEN = 887, /* Yemen */ + CTRY_ZIMBABWE = 716, /* Zimbabwe */ +}; + +struct ieee80211_countryname { + u_int16_t cn_code; + const char *cn_name; + u_int32_t cn_domain; +}; + +#define IEEE80211_REGDOMAIN_COUNTRY_NAMES { \ + { CTRY_DEFAULT, "00", DMN_DEFAULT }, \ + { CTRY_UAE, "ae", DMN_NULL_WORLD }, \ + { CTRY_ALBANIA, "al", DMN_NULL_WORLD }, \ + { CTRY_ARMENIA, "am", DMN_ETSI4_WORLD }, \ + { CTRY_ARGENTINA, "ar", DMN_APL3_WORLD }, \ + { CTRY_AUSTRIA, "at", DMN_ETSI5_WORLD }, \ + { CTRY_AUSTRALIA, "au", DMN_FCC2_WORLD }, \ + { CTRY_AZERBAIJAN, "az", DMN_ETSI4_WORLD }, \ + { CTRY_BELGIUM, "be", DMN_ETSI4_WORLD }, \ + { CTRY_BULGARIA, "bg", DMN_ETSI6_WORLD }, \ + { CTRY_BAHRAIN, "bh", DMN_NULL_WORLD }, \ + { CTRY_BRUNEI_DARUSSALAM, "bn", DMN_APL1_WORLD }, \ + { CTRY_BOLIVIA, "bo", DMN_APL1_ETSIC }, \ + { CTRY_BRAZIL, "br", DMN_NULL_ETSIC }, \ + { CTRY_BELARUS, "by", DMN_NULL_WORLD }, \ + { CTRY_BELIZE, "bz", DMN_NULL_ETSIC }, \ + { CTRY_CANADA, "ca", DMN_FCC2_FCCA }, \ + { CTRY_SWITZERLAND, "ch", DMN_ETSI2_WORLD }, \ + { CTRY_CHILE, "cl", DMN_APL5_WORLD }, \ + { CTRY_CHINA, "cn", DMN_APL1_WORLD }, \ + { CTRY_COLOMBIA, "co", DMN_FCC1_FCCA }, \ + { CTRY_COSTA_RICA, "cr", DMN_NULL_WORLD }, \ + { CTRY_CYPRUS, "cy", DMN_ETSI1_WORLD }, \ + { CTRY_CZECH, "cz", DMN_ETSI3_WORLD }, \ + { CTRY_GERMANY, "de", DMN_ETSI1_WORLD }, \ + { CTRY_DENMARK, "dk", DMN_ETSI1_WORLD }, \ + { CTRY_DOMINICAN_REPUBLIC, "do", DMN_FCC1_FCCA }, \ + { CTRY_ALGERIA, "dz", DMN_NULL_WORLD }, \ + { CTRY_ECUADOR, "ec", DMN_NULL_WORLD }, \ + { CTRY_ESTONIA, "ee", DMN_ETSI1_WORLD }, \ + { CTRY_EGYPT, "eg", DMN_NULL_WORLD }, \ + { CTRY_SPAIN, "es", DMN_ETSI1_WORLD }, \ + { CTRY_FRANCE2, "f2", DMN_ETSI3_WORLD }, \ + { CTRY_FINLAND, "fi", DMN_ETSI1_WORLD }, \ + { CTRY_FAEROE_ISLANDS, "fo", DMN_NULL_WORLD }, \ + { CTRY_FRANCE, "fr", DMN_ETSI3_WORLD }, \ + { CTRY_GEORGIA, "ge", DMN_ETSI4_WORLD }, \ + { CTRY_GREECE, "gr", DMN_NULL_WORLD }, \ + { CTRY_GUATEMALA, "gt", DMN_FCC1_FCCA }, \ + { CTRY_HONG_KONG, "hk", DMN_FCC2_WORLD }, \ + { CTRY_HONDURAS, "hn", DMN_NULL_WORLD }, \ + { CTRY_CROATIA, "hr", DMN_ETSI3_WORLD }, \ + { CTRY_HUNGARY, "hu", DMN_ETSI2_WORLD }, \ + { CTRY_INDONESIA, "id", DMN_NULL_WORLD }, \ + { CTRY_IRELAND, "ie", DMN_ETSI1_WORLD }, \ + { CTRY_ISRAEL, "il", DMN_NULL_WORLD }, \ + { CTRY_INDIA, "in", DMN_NULL_WORLD }, \ + { CTRY_IRAQ, "iq", DMN_NULL_WORLD }, \ + { CTRY_IRAN, "ir", DMN_APL1_WORLD }, \ + { CTRY_ICELAND, "is", DMN_ETSI1_WORLD }, \ + { CTRY_ITALY, "it", DMN_ETSI1_WORLD }, \ + { CTRY_JAPAN1, "j1", DMN_MKK1_MKKB }, \ + { CTRY_JAPAN2, "j2", DMN_MKK1_FCCA }, \ + { CTRY_JAPAN3, "j3", DMN_MKK2_MKKA }, \ + { CTRY_JAPAN4, "j4", DMN_MKK1_MKKA1 }, \ + { CTRY_JAPAN5, "j5", DMN_MKK1_MKKA2 }, \ + { CTRY_JAMAICA, "jm", DMN_NULL_WORLD }, \ + { CTRY_JORDAN, "jo", DMN_NULL_WORLD }, \ + { CTRY_JAPAN, "jp", DMN_MKK1_MKKA }, \ + { CTRY_KOREA_ROC2, "k2", DMN_APL2_APLD }, \ + { CTRY_KENYA, "ke", DMN_NULL_WORLD }, \ + { CTRY_KOREA_NORTH, "kp", DMN_APL2_WORLD }, \ + { CTRY_KOREA_ROC, "kr", DMN_APL2_WORLD }, \ + { CTRY_KUWAIT, "kw", DMN_NULL_WORLD }, \ + { CTRY_KAZAKHSTAN, "kz", DMN_NULL_WORLD }, \ + { CTRY_LEBANON, "lb", DMN_NULL_WORLD }, \ + { CTRY_LIECHTENSTEIN, "li", DMN_ETSI2_WORLD }, \ + { CTRY_SRI_LANKA, "lk", DMN_NULL_WORLD }, \ + { CTRY_LITHUANIA, "lt", DMN_ETSI1_WORLD }, \ + { CTRY_LUXEMBOURG, "lu", DMN_ETSI1_WORLD }, \ + { CTRY_LATVIA, "lv", DMN_NULL_WORLD }, \ + { CTRY_LIBYA, "ly", DMN_NULL_WORLD }, \ + { CTRY_MOROCCO, "ma", DMN_NULL_WORLD }, \ + { CTRY_MONACO, "mc", DMN_ETSI4_WORLD }, \ + { CTRY_MACEDONIA, "mk", DMN_NULL_WORLD }, \ + { CTRY_MACAU, "mo", DMN_FCC2_WORLD }, \ + { CTRY_MEXICO, "mx", DMN_FCC1_FCCA }, \ + { CTRY_MALAYSIA, "my", DMN_NULL_WORLD }, \ + { CTRY_NICARAGUA, "ni", DMN_NULL_WORLD }, \ + { CTRY_NETHERLANDS, "nl", DMN_ETSI1_WORLD }, \ + { CTRY_NORWAY, "no", DMN_ETSI1_WORLD }, \ + { CTRY_NEW_ZEALAND, "nz", DMN_FCC2_ETSIC }, \ + { CTRY_OMAN, "om", DMN_NULL_WORLD }, \ + { CTRY_PANAMA, "pa", DMN_FCC1_FCCA }, \ + { CTRY_PERU, "pe", DMN_NULL_WORLD }, \ + { CTRY_PHILIPPINES, "ph", DMN_FCC1_WORLD }, \ + { CTRY_PAKISTAN, "pk", DMN_NULL_WORLD }, \ + { CTRY_POLAND, "pl", DMN_ETSI1_WORLD }, \ + { CTRY_PUERTO_RICO, "pr", DMN_FCC1_FCCA }, \ + { CTRY_PORTUGAL, "pt", DMN_ETSI1_WORLD }, \ + { CTRY_PARAGUAY, "py", DMN_NULL_WORLD }, \ + { CTRY_QATAR, "qa", DMN_NULL_WORLD }, \ + { CTRY_ROMANIA, "ro", DMN_NULL_WORLD }, \ + { CTRY_RUSSIA, "ru", DMN_NULL_WORLD }, \ + { CTRY_SAUDI_ARABIA, "sa", DMN_NULL_WORLD }, \ + { CTRY_SWEDEN, "se", DMN_ETSI1_WORLD }, \ + { CTRY_SINGAPORE, "sg", DMN_APL4_WORLD }, \ + { CTRY_SLOVENIA, "si", DMN_ETSI1_WORLD }, \ + { CTRY_SLOVAKIA, "sk", DMN_ETSI3_WORLD }, \ + { CTRY_EL_SALVADOR, "sv", DMN_NULL_WORLD }, \ + { CTRY_SYRIA, "sy", DMN_NULL_WORLD }, \ + { CTRY_THAILAND, "th", DMN_APL2_WORLD }, \ + { CTRY_TUNISIA, "tn", DMN_ETSI3_WORLD }, \ + { CTRY_TURKEY, "tr", DMN_ETSI3_WORLD }, \ + { CTRY_TRINIDAD_Y_TOBAGO, "tt", DMN_ETSI4_WORLD }, \ + { CTRY_TAIWAN, "tw", DMN_APL3_WORLD }, \ + { CTRY_UKRAINE, "ua", DMN_NULL_WORLD }, \ + { CTRY_UNITED_KINGDOM, "uk", DMN_ETSI1_WORLD }, \ + { CTRY_UNITED_STATES, "us", DMN_FCC1_FCCA }, \ + { CTRY_URUGUAY, "uy", DMN_APL2_WORLD }, \ + { CTRY_UZBEKISTAN, "uz", DMN_FCC3_FCCA }, \ + { CTRY_VENEZUELA, "ve", DMN_APL2_ETSIC }, \ + { CTRY_VIET_NAM, "vn", DMN_NULL_WORLD }, \ + { CTRY_YEMEN, "ye", DMN_NULL_WORLD }, \ + { CTRY_SOUTH_AFRICA, "za", DMN_ETSI1_WORLD }, \ + { CTRY_ZIMBABWE, "zw", DMN_NULL_WORLD }, \ +} + +enum ieee80211_ctl { + CTL_11A = 0x00, + CTL_11B = 0x01, + CTL_11G = 0x02, + CTL_TURBO = 0x03, + CTL_TURBO_G = 0x04, + CTL_FCC = 0x10, + CTL_ETSI = 0x30, + CTL_MKK = 0x40, + CTL_NONE = 0xff +}; + +#define IEEE80211_CHANNELS_2GHZ_MIN 2412 /* 2GHz channel 1 */ +#define IEEE80211_CHANNELS_2GHZ_MAX 2732 /* 2GHz channel 26 */ + +struct ieee80211_regchannel { + u_int16_t rc_channel; + u_int32_t rc_domain; + u_int32_t rc_mode; +}; + +#define IEEE80211_CHANNELS_2GHZ { \ + { 2412, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2417, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2422, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2427, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2432, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2437, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2442, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2447, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2452, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2457, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2462, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2467, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2472, DMN_APLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + \ + { 2432, DMN_ETSIB, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2442, DMN_ETSIB, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + \ + { 2412, DMN_ETSIC, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2417, DMN_ETSIC, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2422, DMN_ETSIC, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2427, DMN_ETSIC, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2432, DMN_ETSIC, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2442, DMN_ETSIC, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2447, DMN_ETSIC, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2452, DMN_ETSIC, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2457, DMN_ETSIC, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2462, DMN_ETSIC, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2467, DMN_ETSIC, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2472, DMN_ETSIC, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + \ + { 2412, DMN_FCCA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2417, DMN_FCCA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2422, DMN_FCCA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2427, DMN_FCCA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2432, DMN_FCCA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2442, DMN_FCCA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2447, DMN_FCCA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2452, DMN_FCCA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2457, DMN_FCCA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2462, DMN_FCCA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + \ + { 2412, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2417, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2422, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2427, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2432, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2437, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2442, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2447, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2452, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2457, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2462, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2467, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2472, DMN_MKKA, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2484, DMN_MKKA, IEEE80211_CHAN_CCK }, \ + \ + { 2412, DMN_WORLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2417, DMN_WORLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2422, DMN_WORLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2427, DMN_WORLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2432, DMN_WORLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2442, DMN_WORLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2447, DMN_WORLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2452, DMN_WORLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2457, DMN_WORLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2462, DMN_WORLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2467, DMN_WORLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ + { 2472, DMN_WORLD, IEEE80211_CHAN_CCK|IEEE80211_CHAN_OFDM }, \ +} + +#define IEEE80211_CHANNELS_5GHZ_MIN 5005 /* 5GHz channel 1 */ +#define IEEE80211_CHANNELS_5GHZ_MAX 6100 /* 5GHz channel 220 */ + +#define IEEE80211_CHANNELS_5GHZ { \ + { 5745, DMN_APL1, IEEE80211_CHAN_OFDM }, \ + { 5765, DMN_APL1, IEEE80211_CHAN_OFDM }, \ + { 5785, DMN_APL1, IEEE80211_CHAN_OFDM }, \ + { 5805, DMN_APL1, IEEE80211_CHAN_OFDM }, \ + { 5825, DMN_APL1, IEEE80211_CHAN_OFDM }, \ + \ + { 5745, DMN_APL2, IEEE80211_CHAN_OFDM }, \ + { 5765, DMN_APL2, IEEE80211_CHAN_OFDM }, \ + { 5785, DMN_APL2, IEEE80211_CHAN_OFDM }, \ + { 5805, DMN_APL2, IEEE80211_CHAN_OFDM }, \ + \ + { 5280, DMN_APL3, IEEE80211_CHAN_OFDM }, \ + { 5300, DMN_APL3, IEEE80211_CHAN_OFDM }, \ + { 5320, DMN_APL3, IEEE80211_CHAN_OFDM }, \ + { 5745, DMN_APL3, IEEE80211_CHAN_OFDM }, \ + { 5765, DMN_APL3, IEEE80211_CHAN_OFDM }, \ + { 5785, DMN_APL3, IEEE80211_CHAN_OFDM }, \ + { 5805, DMN_APL3, IEEE80211_CHAN_OFDM }, \ + \ + { 5180, DMN_APL4, IEEE80211_CHAN_OFDM }, \ + { 5200, DMN_APL4, IEEE80211_CHAN_OFDM }, \ + { 5220, DMN_APL4, IEEE80211_CHAN_OFDM }, \ + { 5240, DMN_APL4, IEEE80211_CHAN_OFDM }, \ + { 5745, DMN_APL4, IEEE80211_CHAN_OFDM }, \ + { 5765, DMN_APL4, IEEE80211_CHAN_OFDM }, \ + { 5785, DMN_APL4, IEEE80211_CHAN_OFDM }, \ + { 5805, DMN_APL4, IEEE80211_CHAN_OFDM }, \ + { 5825, DMN_APL4, IEEE80211_CHAN_OFDM }, \ + \ + { 5745, DMN_APL5, IEEE80211_CHAN_OFDM }, \ + { 5765, DMN_APL5, IEEE80211_CHAN_OFDM }, \ + { 5785, DMN_APL5, IEEE80211_CHAN_OFDM }, \ + { 5805, DMN_APL5, IEEE80211_CHAN_OFDM }, \ + { 5825, DMN_APL5, IEEE80211_CHAN_OFDM }, \ + \ + { 5180, DMN_ETSI1, IEEE80211_CHAN_OFDM }, \ + { 5200, DMN_ETSI1, IEEE80211_CHAN_OFDM }, \ + { 5220, DMN_ETSI1, IEEE80211_CHAN_OFDM }, \ + { 5240, DMN_ETSI1, IEEE80211_CHAN_OFDM }, \ + { 5260, DMN_ETSI1, IEEE80211_CHAN_OFDM }, \ + { 5280, DMN_ETSI1, IEEE80211_CHAN_OFDM }, \ + { 5300, DMN_ETSI1, IEEE80211_CHAN_OFDM }, \ + { 5320, DMN_ETSI1, IEEE80211_CHAN_OFDM }, \ + { 5500, DMN_ETSI1, IEEE80211_CHAN_OFDM }, \ + { 5520, DMN_ETSI1, IEEE80211_CHAN_OFDM }, \ + { 5540, DMN_ETSI1, IEEE80211_CHAN_OFDM }, \ + { 5560, DMN_ETSI1, IEEE80211_CHAN_OFDM }, \ + { 5580, DMN_ETSI1, IEEE80211_CHAN_OFDM }, \ + { 5600, DMN_ETSI1, IEEE80211_CHAN_OFDM }, \ + { 5620, DMN_ETSI1, IEEE80211_CHAN_OFDM }, \ + { 5640, DMN_ETSI1, IEEE80211_CHAN_OFDM }, \ + { 5660, DMN_ETSI1, IEEE80211_CHAN_OFDM }, \ + { 5680, DMN_ETSI1, IEEE80211_CHAN_OFDM }, \ + { 5700, DMN_ETSI1, IEEE80211_CHAN_OFDM }, \ + \ + { 5180, DMN_ETSI2, IEEE80211_CHAN_OFDM }, \ + { 5200, DMN_ETSI2, IEEE80211_CHAN_OFDM }, \ + { 5220, DMN_ETSI2, IEEE80211_CHAN_OFDM }, \ + { 5240, DMN_ETSI2, IEEE80211_CHAN_OFDM }, \ + \ + { 5180, DMN_ETSI3, IEEE80211_CHAN_OFDM }, \ + { 5200, DMN_ETSI3, IEEE80211_CHAN_OFDM }, \ + { 5220, DMN_ETSI3, IEEE80211_CHAN_OFDM }, \ + { 5240, DMN_ETSI3, IEEE80211_CHAN_OFDM }, \ + { 5260, DMN_ETSI3, IEEE80211_CHAN_OFDM }, \ + { 5280, DMN_ETSI3, IEEE80211_CHAN_OFDM }, \ + { 5300, DMN_ETSI3, IEEE80211_CHAN_OFDM }, \ + { 5320, DMN_ETSI3, IEEE80211_CHAN_OFDM }, \ + \ + { 5180, DMN_ETSI4, IEEE80211_CHAN_OFDM }, \ + { 5200, DMN_ETSI4, IEEE80211_CHAN_OFDM }, \ + { 5220, DMN_ETSI4, IEEE80211_CHAN_OFDM }, \ + { 5240, DMN_ETSI4, IEEE80211_CHAN_OFDM }, \ + { 5260, DMN_ETSI4, IEEE80211_CHAN_OFDM }, \ + { 5280, DMN_ETSI4, IEEE80211_CHAN_OFDM }, \ + { 5300, DMN_ETSI4, IEEE80211_CHAN_OFDM }, \ + { 5320, DMN_ETSI4, IEEE80211_CHAN_OFDM }, \ + \ + { 5180, DMN_ETSI5, IEEE80211_CHAN_OFDM }, \ + { 5200, DMN_ETSI5, IEEE80211_CHAN_OFDM }, \ + { 5220, DMN_ETSI5, IEEE80211_CHAN_OFDM }, \ + { 5240, DMN_ETSI5, IEEE80211_CHAN_OFDM }, \ + \ + { 5180, DMN_ETSI6, IEEE80211_CHAN_OFDM }, \ + { 5200, DMN_ETSI6, IEEE80211_CHAN_OFDM }, \ + { 5220, DMN_ETSI6, IEEE80211_CHAN_OFDM }, \ + { 5240, DMN_ETSI6, IEEE80211_CHAN_OFDM }, \ + { 5260, DMN_ETSI6, IEEE80211_CHAN_OFDM }, \ + { 5280, DMN_ETSI6, IEEE80211_CHAN_OFDM }, \ + { 5500, DMN_ETSI6, IEEE80211_CHAN_OFDM }, \ + { 5520, DMN_ETSI6, IEEE80211_CHAN_OFDM }, \ + { 5540, DMN_ETSI6, IEEE80211_CHAN_OFDM }, \ + { 5560, DMN_ETSI6, IEEE80211_CHAN_OFDM }, \ + { 5580, DMN_ETSI6, IEEE80211_CHAN_OFDM }, \ + { 5600, DMN_ETSI6, IEEE80211_CHAN_OFDM }, \ + { 5620, DMN_ETSI6, IEEE80211_CHAN_OFDM }, \ + { 5640, DMN_ETSI6, IEEE80211_CHAN_OFDM }, \ + { 5660, DMN_ETSI6, IEEE80211_CHAN_OFDM }, \ + { 5680, DMN_ETSI6, IEEE80211_CHAN_OFDM }, \ + { 5700, DMN_ETSI6, IEEE80211_CHAN_OFDM }, \ + \ + { 5180, DMN_FCC1, IEEE80211_CHAN_OFDM }, \ + { 5200, DMN_FCC1, IEEE80211_CHAN_OFDM }, \ + { 5220, DMN_FCC1, IEEE80211_CHAN_OFDM }, \ + { 5240, DMN_FCC1, IEEE80211_CHAN_OFDM }, \ + { 5260, DMN_FCC1, IEEE80211_CHAN_OFDM }, \ + { 5280, DMN_FCC1, IEEE80211_CHAN_OFDM }, \ + { 5300, DMN_FCC1, IEEE80211_CHAN_OFDM }, \ + { 5320, DMN_FCC1, IEEE80211_CHAN_OFDM }, \ + { 5745, DMN_FCC1, IEEE80211_CHAN_OFDM }, \ + { 5765, DMN_FCC1, IEEE80211_CHAN_OFDM }, \ + { 5785, DMN_FCC1, IEEE80211_CHAN_OFDM }, \ + { 5805, DMN_FCC1, IEEE80211_CHAN_OFDM }, \ + { 5825, DMN_FCC1, IEEE80211_CHAN_OFDM }, \ + \ + { 5180, DMN_FCC2, IEEE80211_CHAN_OFDM }, \ + { 5200, DMN_FCC2, IEEE80211_CHAN_OFDM }, \ + { 5220, DMN_FCC2, IEEE80211_CHAN_OFDM }, \ + { 5240, DMN_FCC2, IEEE80211_CHAN_OFDM }, \ + { 5260, DMN_FCC2, IEEE80211_CHAN_OFDM }, \ + { 5280, DMN_FCC2, IEEE80211_CHAN_OFDM }, \ + { 5300, DMN_FCC2, IEEE80211_CHAN_OFDM }, \ + { 5320, DMN_FCC2, IEEE80211_CHAN_OFDM }, \ + { 5745, DMN_FCC2, IEEE80211_CHAN_OFDM }, \ + { 5765, DMN_FCC2, IEEE80211_CHAN_OFDM }, \ + { 5785, DMN_FCC2, IEEE80211_CHAN_OFDM }, \ + { 5805, DMN_FCC2, IEEE80211_CHAN_OFDM }, \ + { 5825, DMN_FCC2, IEEE80211_CHAN_OFDM }, \ + \ + { 5180, DMN_FCC3, IEEE80211_CHAN_OFDM }, \ + { 5200, DMN_FCC3, IEEE80211_CHAN_OFDM }, \ + { 5220, DMN_FCC3, IEEE80211_CHAN_OFDM }, \ + { 5240, DMN_FCC3, IEEE80211_CHAN_OFDM }, \ + { 5260, DMN_FCC3, IEEE80211_CHAN_OFDM }, \ + { 5280, DMN_FCC3, IEEE80211_CHAN_OFDM }, \ + { 5300, DMN_FCC3, IEEE80211_CHAN_OFDM }, \ + { 5320, DMN_FCC3, IEEE80211_CHAN_OFDM }, \ + { 5500, DMN_FCC3, IEEE80211_CHAN_OFDM }, \ + { 5520, DMN_FCC3, IEEE80211_CHAN_OFDM }, \ + { 5540, DMN_FCC3, IEEE80211_CHAN_OFDM }, \ + { 5560, DMN_FCC3, IEEE80211_CHAN_OFDM }, \ + { 5580, DMN_FCC3, IEEE80211_CHAN_OFDM }, \ + { 5600, DMN_FCC3, IEEE80211_CHAN_OFDM }, \ + { 5620, DMN_FCC3, IEEE80211_CHAN_OFDM }, \ + { 5640, DMN_FCC3, IEEE80211_CHAN_OFDM }, \ + { 5660, DMN_FCC3, IEEE80211_CHAN_OFDM }, \ + { 5680, DMN_FCC3, IEEE80211_CHAN_OFDM }, \ + { 5700, DMN_FCC3, IEEE80211_CHAN_OFDM }, \ + { 5745, DMN_FCC3, IEEE80211_CHAN_OFDM }, \ + { 5765, DMN_FCC3, IEEE80211_CHAN_OFDM }, \ + { 5785, DMN_FCC3, IEEE80211_CHAN_OFDM }, \ + { 5805, DMN_FCC3, IEEE80211_CHAN_OFDM }, \ + { 5825, DMN_FCC3, IEEE80211_CHAN_OFDM }, \ + \ + { 5170, DMN_MKK1, IEEE80211_CHAN_OFDM }, \ + { 5190, DMN_MKK1, IEEE80211_CHAN_OFDM }, \ + { 5210, DMN_MKK1, IEEE80211_CHAN_OFDM }, \ + { 5230, DMN_MKK1, IEEE80211_CHAN_OFDM }, \ + \ + { 5040, DMN_MKK2, IEEE80211_CHAN_OFDM }, \ + { 5060, DMN_MKK2, IEEE80211_CHAN_OFDM }, \ + { 5080, DMN_MKK2, IEEE80211_CHAN_OFDM }, \ + { 5170, DMN_MKK2, IEEE80211_CHAN_OFDM }, \ + { 5190, DMN_MKK2, IEEE80211_CHAN_OFDM }, \ + { 5210, DMN_MKK2, IEEE80211_CHAN_OFDM }, \ + { 5230, DMN_MKK2, IEEE80211_CHAN_OFDM }, \ + \ + { 5180, DMN_WORLD, IEEE80211_CHAN_OFDM }, \ + { 5200, DMN_WORLD, IEEE80211_CHAN_OFDM }, \ + { 5220, DMN_WORLD, IEEE80211_CHAN_OFDM }, \ + { 5240, DMN_WORLD, IEEE80211_CHAN_OFDM }, \ +} + +__BEGIN_DECLS + +extern u_int16_t ieee80211_name2countrycode(const char *); +extern u_int32_t ieee80211_name2regdomain(const char *); +extern const char *ieee80211_countrycode2name(u_int16_t); +extern const char *ieee80211_regdomain2name(u_int32_t); +extern u_int32_t ieee80211_regdomain2flag(u_int16_t, u_int16_t); +extern u_int32_t ieee80211_countrycode2regdomain(u_int16_t); + +__END_DECLS + +#endif /* _NET80211_IEEE80211_REGDOMAIN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net80211/ieee80211_rssadapt.h b/lib/libc/include/generic-openbsd/net80211/ieee80211_rssadapt.h new file mode 100644 index 000000000000..41b8a3248dfe --- /dev/null +++ b/lib/libc/include/generic-openbsd/net80211/ieee80211_rssadapt.h @@ -0,0 +1,103 @@ +/* $OpenBSD: ieee80211_rssadapt.h,v 1.5 2010/07/17 16:25:09 damien Exp $ */ +/* $NetBSD: ieee80211_rssadapt.h,v 1.3 2004/05/06 03:03:20 dyoung Exp $ */ + +/*- + * Copyright (c) 2003, 2004 David Young. All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY David Young ``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 David + * Young 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 _NET80211_IEEE80211_RSSADAPT_H_ +#define _NET80211_IEEE80211_RSSADAPT_H_ + +/* Data-rate adaptation loosely based on "Link Adaptation Strategy + * for IEEE 802.11 WLAN via Received Signal Strength Measurement" + * by Javier del Prado Pavon and Sunghyun Choi. + */ + +/* Buckets for frames 0-128 bytes long, 129-1024, 1025-maximum. */ +#define IEEE80211_RSSADAPT_BKTS 3 +#define IEEE80211_RSSADAPT_BKT0 128 +#define IEEE80211_RSSADAPT_BKTPOWER 3 /* 2**_BKTPOWER */ + +#define ieee80211_rssadapt_thresh_new \ + (ieee80211_rssadapt_thresh_denom - ieee80211_rssadapt_thresh_old) +#define ieee80211_rssadapt_decay_new \ + (ieee80211_rssadapt_decay_denom - ieee80211_rssadapt_decay_old) +#define ieee80211_rssadapt_avgrssi_new \ + (ieee80211_rssadapt_avgrssi_denom - ieee80211_rssadapt_avgrssi_old) + +struct ieee80211_rssadapt_expavgctl { + /* RSS threshold decay. */ + u_int rc_decay_denom; + u_int rc_decay_old; + /* RSS threshold update. */ + u_int rc_thresh_denom; + u_int rc_thresh_old; + /* RSS average update. */ + u_int rc_avgrssi_denom; + u_int rc_avgrssi_old; +}; + +struct ieee80211_rssadapt { + /* exponential average RSSI << 8 */ + u_int16_t ra_avg_rssi; + /* Tx failures in this update interval */ + u_int32_t ra_nfail; + /* Tx successes in this update interval */ + u_int32_t ra_nok; + /* exponential average packets/second */ + u_int32_t ra_pktrate; + /* RSSI threshold for each Tx rate */ + u_int16_t ra_rate_thresh[IEEE80211_RSSADAPT_BKTS] + [IEEE80211_RATE_SIZE]; + struct timeval ra_last_raise; + struct timeval ra_raise_interval; +}; + +/* Properties of a Tx packet, for link adaptation. */ +struct ieee80211_rssdesc { + u_int id_len; /* Tx packet length */ + u_int id_rateidx; /* index into ni->ni_rates */ + struct ieee80211_node *id_node; /* destination STA MAC */ + u_int8_t id_rssi; /* destination STA avg RSS @ + * Tx time + */ +}; + +void ieee80211_rssadapt_updatestats(struct ieee80211_rssadapt *); +void ieee80211_rssadapt_input(struct ieee80211com *, + const struct ieee80211_node *, struct ieee80211_rssadapt *, int); +void ieee80211_rssadapt_lower_rate(struct ieee80211com *, + const struct ieee80211_node *, struct ieee80211_rssadapt *, + const struct ieee80211_rssdesc *); +void ieee80211_rssadapt_raise_rate(struct ieee80211com *, + struct ieee80211_rssadapt *, const struct ieee80211_rssdesc *); +int ieee80211_rssadapt_choose(struct ieee80211_rssadapt *, + const struct ieee80211_rateset *, const struct ieee80211_frame *, + u_int, int, const char *, int); +#ifdef IEEE80211_DEBUG +extern int ieee80211_rssadapt_debug; +#endif /* IEEE80211_DEBUG */ + +#endif /* _NET80211_IEEE80211_RSSADAPT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/net80211/ieee80211_var.h b/lib/libc/include/generic-openbsd/net80211/ieee80211_var.h new file mode 100644 index 000000000000..6b03767eae20 --- /dev/null +++ b/lib/libc/include/generic-openbsd/net80211/ieee80211_var.h @@ -0,0 +1,511 @@ +/* $OpenBSD: ieee80211_var.h,v 1.112 2025/08/01 20:39:26 stsp Exp $ */ +/* $NetBSD: ieee80211_var.h,v 1.7 2004/05/06 03:07:10 dyoung Exp $ */ + +/*- + * Copyright (c) 2001 Atsushi Onoe + * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/sys/net80211/ieee80211_var.h,v 1.15 2004/04/05 22:10:26 sam Exp $ + */ +#ifndef _NET80211_IEEE80211_VAR_H_ +#define _NET80211_IEEE80211_VAR_H_ + +/* + * Definitions for IEEE 802.11 drivers. + */ + +#ifdef SMALL_KERNEL +#define IEEE80211_STA_ONLY 1 +#endif + +#include + +#include +#include +#include /* for ieee80211_stats */ +#include +#include + +#define IEEE80211_CHAN_MAX 255 +#define IEEE80211_CHAN_ANY 0xffff /* token for ``any channel'' */ +#define IEEE80211_CHAN_ANYC \ + ((struct ieee80211_channel *) NULL) + +#define IEEE80211_TXPOWER_MAX 100 /* max power */ +#define IEEE80211_TXPOWER_MIN -50 /* kill radio (if possible) */ + +#define IEEE80211_RSSI_THRES_2GHZ (-60) /* in dBm */ +#define IEEE80211_RSSI_THRES_5GHZ (-70) /* in dBm */ +#define IEEE80211_RSSI_THRES_RATIO_2GHZ 60 /* in percent */ +#define IEEE80211_RSSI_THRES_RATIO_5GHZ 50 /* in percent */ + +#define IEEE80211_BGSCAN_FAIL_MAX 512 /* units of 500 msec */ + +/* + * Missed beacon threshold: An access point has disappeared if this amount + * of consecutive beacons have been missed. + * This value needs to be high enough to avoid frequent re-connects to APs + * which suffer from occasional packet loss, and low enough to avoid a long + * delay before we start scanning when an AP has actually disappeared. + * + * The beacon interval is variable, but generally in the order of 100ms. + * So 30 beacons implies a grace period of about 3 seconds before we start + * searching for a new AP. + */ +#define IEEE80211_BEACON_MISS_THRES 30 /* units of beacons */ + +enum ieee80211_phytype { + IEEE80211_T_DS, /* direct sequence spread spectrum */ + IEEE80211_T_OFDM, /* frequency division multiplexing */ + IEEE80211_T_XR /* extended range mode */ +}; +#define IEEE80211_T_CCK IEEE80211_T_DS /* more common nomenclature */ + +/* XXX not really a mode; there are really multiple PHY's */ +enum ieee80211_phymode { + IEEE80211_MODE_AUTO = 0, /* autoselect */ + IEEE80211_MODE_11A = 1, /* 5GHz, OFDM */ + IEEE80211_MODE_11B = 2, /* 2GHz, CCK */ + IEEE80211_MODE_11G = 3, /* 2GHz, OFDM */ + IEEE80211_MODE_11N = 4, /* 2GHz/5GHz, OFDM/HT */ + IEEE80211_MODE_11AC = 5, /* 5GHz, OFDM/VHT */ +}; +#define IEEE80211_MODE_MAX (IEEE80211_MODE_11AC+1) + +enum ieee80211_opmode { + IEEE80211_M_STA = 1, /* infrastructure station */ +#ifndef IEEE80211_STA_ONLY + IEEE80211_M_IBSS = 0, /* IBSS (adhoc) station */ + IEEE80211_M_AHDEMO = 3, /* Old lucent compatible adhoc demo */ + IEEE80211_M_HOSTAP = 6, /* Software Access Point */ +#endif + IEEE80211_M_MONITOR = 8 /* Monitor mode */ +}; + +/* + * 802.11g protection mode. + */ +enum ieee80211_protmode { + IEEE80211_PROT_NONE = 0, /* no protection */ + IEEE80211_PROT_CTSONLY = 1, /* CTS to self */ + IEEE80211_PROT_RTSCTS = 2 /* RTS-CTS */ +}; + +/* + * Channels are specified by frequency and attributes. + */ +struct ieee80211_channel { + u_int16_t ic_freq; /* setting in MHz */ + u_int16_t ic_flags; /* see below */ + u_int32_t ic_xflags; /* extra flags; see below */ +}; + +/* + * Channel attributes (XXX must keep in sync with radiotap flags). + */ +#define IEEE80211_CHAN_CCK 0x0020 /* CCK channel */ +#define IEEE80211_CHAN_OFDM 0x0040 /* OFDM channel */ +#define IEEE80211_CHAN_2GHZ 0x0080 /* 2 GHz spectrum channel */ +#define IEEE80211_CHAN_5GHZ 0x0100 /* 5 GHz spectrum channel */ +#define IEEE80211_CHAN_PASSIVE 0x0200 /* Only passive scan allowed */ +#define IEEE80211_CHAN_DYN 0x0400 /* Dynamic CCK-OFDM channel */ +#define IEEE80211_CHAN_XR 0x1000 /* Extended range OFDM channel */ +#define IEEE80211_CHAN_HT 0x2000 /* 11n/HT channel */ +#define IEEE80211_CHAN_VHT 0x4000 /* 11ac/VHT channel */ +#define IEEE80211_CHAN_40MHZ 0x8000 /* use of 40 MHz is allowed */ + +/* + * Extra channel flags. + */ +#define IEEE80211_CHANX_80MHZ 0x00000001 /* use of 80 MHz is allowed */ +#define IEEE80211_CHANX_160MHZ 0x00000002 /* use of 160 MHz is allowed */ + +/* + * Useful combinations of channel characteristics. + */ +#define IEEE80211_CHAN_A \ + (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM) +#define IEEE80211_CHAN_B \ + (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK) +#define IEEE80211_CHAN_PUREG \ + (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM) +#define IEEE80211_CHAN_G \ + (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN) + +#define IEEE80211_IS_CHAN_A(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A) +#define IEEE80211_IS_CHAN_B(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B) +#define IEEE80211_IS_CHAN_PUREG(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_PUREG) == IEEE80211_CHAN_PUREG) +#define IEEE80211_IS_CHAN_G(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G) +#define IEEE80211_IS_CHAN_N(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_HT) == IEEE80211_CHAN_HT) +#define IEEE80211_IS_CHAN_AC(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_VHT) == IEEE80211_CHAN_VHT) + +#define IEEE80211_IS_CHAN_2GHZ(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_2GHZ) != 0) +#define IEEE80211_IS_CHAN_5GHZ(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_5GHZ) != 0) +#define IEEE80211_IS_CHAN_OFDM(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_OFDM) != 0) +#define IEEE80211_IS_CHAN_CCK(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_CCK) != 0) +#define IEEE80211_IS_CHAN_XR(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_XR) != 0) + +#define IEEE80211_CHAN_40MHZ_ALLOWED(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_40MHZ) != 0) +#define IEEE80211_CHAN_80MHZ_ALLOWED(_c) \ + (((_c)->ic_xflags & IEEE80211_CHANX_80MHZ) != 0) +#define IEEE80211_CHAN_160MHZ_ALLOWED(_c) \ + (((_c)->ic_xflags & IEEE80211_CHANX_160MHZ) != 0) + +/* + * EDCA AC parameters. + */ +struct ieee80211_edca_ac_params { + u_int8_t ac_ecwmin; /* CWmin = 2^ECWmin - 1 */ + u_int8_t ac_ecwmax; /* CWmax = 2^ECWmax - 1 */ + u_int8_t ac_aifsn; + u_int16_t ac_txoplimit; /* 32TU */ +#define IEEE80211_TXOP_TO_US(txop) ((txop) * 32) + + u_int8_t ac_acm; +}; + +extern const struct ieee80211_edca_ac_params + ieee80211_edca_table[IEEE80211_MODE_MAX][EDCA_NUM_AC]; +extern const struct ieee80211_edca_ac_params + ieee80211_qap_edca_table[IEEE80211_MODE_MAX][EDCA_NUM_AC]; + +#define IEEE80211_DEFRAG_SIZE 3 /* must be >= 3 according to spec */ +/* + * Entry in the fragment cache. + */ +struct ieee80211_defrag { + struct timeout df_to; + struct mbuf *df_m; + u_int16_t df_seq; + u_int8_t df_frag; +}; + +#define IEEE80211_PROTO_NONE 0 +#define IEEE80211_PROTO_RSN (1 << 0) +#define IEEE80211_PROTO_WPA (1 << 1) + +#define IEEE80211_SCAN_UNLOCKED 0x0 +#define IEEE80211_SCAN_LOCKED 0x1 +#define IEEE80211_SCAN_REQUEST 0x2 +#define IEEE80211_SCAN_RESUME 0x4 + +#define IEEE80211_GROUP_NKID 6 + +struct ieee80211_node_switch_bss_arg; + +struct ieee80211com { + struct arpcom ic_ac; + LIST_ENTRY(ieee80211com) ic_list; /* chain of all ieee80211com */ + void (*ic_recv_mgmt)(struct ieee80211com *, + struct mbuf *, struct ieee80211_node *, + struct ieee80211_rxinfo *, int); + int (*ic_send_mgmt)(struct ieee80211com *, + struct ieee80211_node *, int, int, int); + int (*ic_newstate)(struct ieee80211com *, + enum ieee80211_state, int); + int (*ic_newauth)(struct ieee80211com *, + struct ieee80211_node *, int, uint16_t); + void (*ic_newassoc)(struct ieee80211com *, + struct ieee80211_node *, int); + void (*ic_node_leave)(struct ieee80211com *, + struct ieee80211_node *); + void (*ic_updateslot)(struct ieee80211com *); + void (*ic_updateedca)(struct ieee80211com *); + void (*ic_set_tim)(struct ieee80211com *, int, int); + int (*ic_set_key)(struct ieee80211com *, + struct ieee80211_node *, + struct ieee80211_key *); + void (*ic_delete_key)(struct ieee80211com *, + struct ieee80211_node *, + struct ieee80211_key *); + int (*ic_ampdu_tx_start)(struct ieee80211com *, + struct ieee80211_node *, u_int8_t); + void (*ic_ampdu_tx_stop)(struct ieee80211com *, + struct ieee80211_node *, u_int8_t); + int (*ic_ampdu_rx_start)(struct ieee80211com *, + struct ieee80211_node *, u_int8_t); + void (*ic_ampdu_rx_stop)(struct ieee80211com *, + struct ieee80211_node *, u_int8_t); + void (*ic_updateprot)(struct ieee80211com *); + void (*ic_updatechan)(struct ieee80211com *); + void (*ic_updatedtim)(struct ieee80211com *); + int (*ic_bgscan_start)(struct ieee80211com *); + void (*ic_bgscan_done)(struct ieee80211com *, + struct ieee80211_node_switch_bss_arg *, + size_t); + struct timeout ic_bgscan_timeout; + uint32_t ic_bgscan_fail; + u_int8_t ic_myaddr[IEEE80211_ADDR_LEN]; + struct ieee80211_rateset ic_sup_rates[IEEE80211_MODE_MAX]; + struct ieee80211_channel ic_channels[IEEE80211_CHAN_MAX+1]; + u_char ic_chan_avail[howmany(IEEE80211_CHAN_MAX,NBBY)]; + u_char ic_chan_active[howmany(IEEE80211_CHAN_MAX, NBBY)]; + u_char ic_chan_scan[howmany(IEEE80211_CHAN_MAX,NBBY)]; + struct mbuf_queue ic_mgtq; + struct mbuf_queue ic_pwrsaveq; + u_int8_t ic_scan_count; /* count scans */ + u_int32_t ic_flags; /* state flags */ + u_int32_t ic_xflags; /* more flags */ + u_int32_t ic_userflags; /* yet more flags */ + u_int32_t ic_caps; /* capabilities */ + u_int16_t ic_modecaps; /* set of mode capabilities */ + u_int16_t ic_curmode; /* current mode */ + enum ieee80211_phytype ic_phytype; /* XXX wrong for multi-mode */ + enum ieee80211_opmode ic_opmode; /* operation mode */ + enum ieee80211_state ic_state; /* 802.11 state */ + u_int32_t *ic_aid_bitmap; + u_int16_t ic_max_aid; + enum ieee80211_protmode ic_protmode; /* 802.11g/n protection mode */ + struct ifmedia ic_media; /* interface media config */ + caddr_t ic_rawbpf; /* packet filter structure */ + struct ieee80211_node *ic_bss; /* information for this node */ + struct ieee80211_channel *ic_ibss_chan; + int ic_fixed_rate; /* index to ic_sup_rates[] */ + u_int16_t ic_rtsthreshold; + u_int16_t ic_fragthreshold; + u_int ic_scangen; /* gen# for timeout scan */ + struct ieee80211_node *(*ic_node_alloc)(struct ieee80211com *); + void (*ic_node_free)(struct ieee80211com *, + struct ieee80211_node *); + void (*ic_node_copy)(struct ieee80211com *, + struct ieee80211_node *, + const struct ieee80211_node *); + u_int8_t (*ic_node_getrssi)(struct ieee80211com *, + const struct ieee80211_node *); + int (*ic_node_checkrssi)(struct ieee80211com *, + const struct ieee80211_node *); + u_int8_t ic_max_rssi; + struct ieee80211_tree ic_tree; + int ic_nnodes; /* length of ic_nnodes */ + int ic_max_nnodes; /* max length of ic_nnodes */ + u_int16_t ic_lintval; /* listen interval */ + int16_t ic_txpower; /* tx power setting (dBm) */ + int ic_bmissthres; /* beacon miss threshold */ + int ic_mgt_timer; /* mgmt timeout */ +#ifndef IEEE80211_STA_ONLY + struct timeout ic_inact_timeout; /* node inactivity timeout */ + struct timeout ic_node_cache_timeout; +#endif + struct task ic_rtm_80211info_task; + int ic_des_esslen; + u_int8_t ic_des_essid[IEEE80211_NWID_LEN]; + struct ieee80211_channel *ic_des_chan; /* desired channel */ + u_int8_t ic_des_bssid[IEEE80211_ADDR_LEN]; + struct ieee80211_key ic_nw_keys[IEEE80211_GROUP_NKID]; + int ic_def_txkey; /* group data key index */ +#define ic_wep_txkey ic_def_txkey + int ic_igtk_kid; /* IGTK key index */ + u_int32_t ic_iv; /* initial vector for wep */ + struct ieee80211_stats ic_stats; /* statistics */ + struct timeval ic_last_merge_print; /* for rate-limiting + * IBSS merge print-outs + */ + struct ieee80211_edca_ac_params ic_edca_ac[EDCA_NUM_AC]; + u_int ic_edca_updtcount; + u_int16_t ic_tid_noack; + u_int8_t ic_globalcnt[EAPOL_KEY_NONCE_LEN]; + u_int8_t ic_nonce[EAPOL_KEY_NONCE_LEN]; + u_int8_t ic_psk[IEEE80211_PMK_LEN]; + struct timeout ic_rsn_timeout; + time_t ic_tkip_micfail; + u_int64_t ic_tkip_micfail_last_tsc; +#ifndef IEEE80211_STA_ONLY + struct timeout ic_tkip_micfail_timeout; +#endif + + TAILQ_HEAD(, ieee80211_pmk) ic_pmksa; /* PMKSA cache */ + u_int ic_rsnprotos; + u_int ic_rsnakms; + u_int ic_rsnciphers; + enum ieee80211_cipher ic_rsngroupcipher; + enum ieee80211_cipher ic_rsngroupmgmtcipher; + +#ifdef notyet + struct ieee80211_defrag ic_defrag[IEEE80211_DEFRAG_SIZE]; + int ic_defrag_cur; +#endif + + u_int8_t *ic_tim_bitmap; + u_int ic_tim_len; + u_int ic_tim_mcast_pending; + u_int ic_dtim_period; + u_int ic_dtim_count; + + u_int32_t ic_txbfcaps; + u_int16_t ic_htcaps; + u_int8_t ic_ampdu_params; + u_int8_t ic_sup_mcs[howmany(80, NBBY)]; + u_int16_t ic_max_rxrate; /* in Mb/s, 0 <= rate <= 1023 */ + u_int8_t ic_tx_mcs_set; + u_int16_t ic_htxcaps; + u_int8_t ic_aselcaps; + u_int8_t ic_dialog_token; + int ic_fixed_mcs; + + uint32_t ic_vhtcaps; + uint16_t ic_vht_rxmcs; + uint16_t ic_vht_rx_max_lgi_mbit_s; + uint16_t ic_vht_txmcs; + uint16_t ic_vht_tx_max_lgi_mbit_s; + + TAILQ_HEAD(, ieee80211_ess) ic_ess; +}; +#define ic_if ic_ac.ac_if +#define ic_softc ic_if.if_softc + +/* list of APs we want to automatically use */ +/* all data is copied from struct ieee80211com */ +struct ieee80211_ess { + /* nwid */ + int esslen; + u_int8_t essid[IEEE80211_NWID_LEN]; + + /* clear/wep/wpa */ + u_int32_t flags; + + /* nwkey */ + struct ieee80211_key nw_keys[IEEE80211_GROUP_NKID]; + int def_txkey; + + /* wpakey */ + u_int8_t psk[IEEE80211_PMK_LEN]; + u_int rsnprotos; + u_int rsnakms; + u_int rsnciphers; + enum ieee80211_cipher rsngroupcipher; + + TAILQ_ENTRY(ieee80211_ess) ess_next; +}; + +#define IEEE80211_ADDR_EQ(a1,a2) (memcmp(a1,a2,IEEE80211_ADDR_LEN) == 0) +#define IEEE80211_ADDR_COPY(dst,src) memcpy(dst,src,IEEE80211_ADDR_LEN) + +/* ic_flags */ +#define IEEE80211_F_ASCAN 0x00000001 /* STATUS: active scan */ +#define IEEE80211_F_SIBSS 0x00000002 /* STATUS: start IBSS */ +#define IEEE80211_F_WEPON 0x00000100 /* CONF: WEP enabled */ +#define IEEE80211_F_IBSSON 0x00000200 /* CONF: IBSS creation enable */ +#define IEEE80211_F_PMGTON 0x00000400 /* CONF: Power mgmt enable */ +#define IEEE80211_F_DESBSSID 0x00000800 /* CONF: des_bssid is set */ +#define IEEE80211_F_ROAMING 0x00002000 /* CONF: roaming enabled */ +#define IEEE80211_F_TXPMGT 0x00018000 /* STATUS: tx power */ +#define IEEE80211_F_TXPOW_OFF 0x00000000 /* TX Power: radio disabled */ +#define IEEE80211_F_TXPOW_FIXED 0x00008000 /* TX Power: fixed rate */ +#define IEEE80211_F_TXPOW_AUTO 0x00010000 /* TX Power: undefined */ +#define IEEE80211_F_SHSLOT 0x00020000 /* STATUS: short slot time */ +#define IEEE80211_F_SHPREAMBLE 0x00040000 /* STATUS: short preamble */ +#define IEEE80211_F_QOS 0x00080000 /* CONF: QoS enabled */ +#define IEEE80211_F_USEPROT 0x00100000 /* STATUS: protection enabled */ +#define IEEE80211_F_RSNON 0x00200000 /* CONF: RSN enabled */ +#define IEEE80211_F_PSK 0x00400000 /* CONF: pre-shared key set */ +#define IEEE80211_F_COUNTERM 0x00800000 /* STATUS: countermeasures */ +#define IEEE80211_F_MFPR 0x01000000 /* CONF: MFP required */ +#define IEEE80211_F_HTON 0x02000000 /* CONF: HT enabled */ +#define IEEE80211_F_PBAR 0x04000000 /* CONF: PBAC required */ +#define IEEE80211_F_BGSCAN 0x08000000 /* STATUS: background scan */ +#define IEEE80211_F_AUTO_JOIN 0x10000000 /* CONF: auto-join active */ +#define IEEE80211_F_VHTON 0x20000000 /* CONF: VHT enabled */ + +/* ic_xflags */ +#define IEEE80211_F_TX_MGMT_ONLY 0x00000001 /* leave data frames on ifq */ + +/* ic_caps */ +#define IEEE80211_C_WEP 0x00000001 /* CAPABILITY: WEP available */ +#define IEEE80211_C_IBSS 0x00000002 /* CAPABILITY: IBSS available */ +#define IEEE80211_C_PMGT 0x00000004 /* CAPABILITY: Power mgmt */ +#define IEEE80211_C_HOSTAP 0x00000008 /* CAPABILITY: HOSTAP avail */ +#define IEEE80211_C_AHDEMO 0x00000010 /* CAPABILITY: Old Adhoc Demo */ +#define IEEE80211_C_APPMGT 0x00000020 /* CAPABILITY: AP power mgmt */ +#define IEEE80211_C_TXPMGT 0x00000040 /* CAPABILITY: tx power mgmt */ +#define IEEE80211_C_SHSLOT 0x00000080 /* CAPABILITY: short slottime */ +#define IEEE80211_C_SHPREAMBLE 0x00000100 /* CAPABILITY: short preamble */ +#define IEEE80211_C_MONITOR 0x00000200 /* CAPABILITY: monitor mode */ +#define IEEE80211_C_SCANALL 0x00000400 /* CAPABILITY: scan all chan */ +#define IEEE80211_C_QOS 0x00000800 /* CAPABILITY: QoS avail */ +#define IEEE80211_C_RSN 0x00001000 /* CAPABILITY: RSN avail */ +#define IEEE80211_C_MFP 0x00002000 /* CAPABILITY: MFP avail */ +#define IEEE80211_C_RAWCTL 0x00004000 /* CAPABILITY: raw ctl */ +#define IEEE80211_C_SCANALLBAND 0x00008000 /* CAPABILITY: scan all bands */ +#define IEEE80211_C_TX_AMPDU 0x00010000 /* CAPABILITY: send A-MPDU */ +#define IEEE80211_C_ADDBA_OFFLOAD 0x00020000 /* CAPABILITY: ADDBA offload */ + +/* flags for ieee80211_fix_rate() */ +#define IEEE80211_F_DOSORT 0x00000001 /* sort rate list */ +#define IEEE80211_F_DOFRATE 0x00000002 /* use fixed rate */ +#define IEEE80211_F_DONEGO 0x00000004 /* calc negotiated rate */ +#define IEEE80211_F_DODEL 0x00000008 /* delete ignore rate */ + +void ieee80211_ifattach(struct ifnet *); +void ieee80211_ifdetach(struct ifnet *); +void ieee80211_channel_init(struct ifnet *); +void ieee80211_media_init(struct ifnet *, ifm_change_cb_t, ifm_stat_cb_t); +int ieee80211_media_change(struct ifnet *); +void ieee80211_media_status(struct ifnet *, struct ifmediareq *); +int ieee80211_ioctl(struct ifnet *, u_long, caddr_t); +int ieee80211_get_rate(struct ieee80211com *); +void ieee80211_watchdog(struct ifnet *); +int ieee80211_fix_rate(struct ieee80211com *, struct ieee80211_node *, int); +uint64_t ieee80211_rate2media(struct ieee80211com *, int, + enum ieee80211_phymode); +int ieee80211_media2rate(uint64_t); +uint64_t ieee80211_mcs2media(struct ieee80211com *, int, + enum ieee80211_phymode); +int ieee80211_media2mcs(uint64_t); +u_int8_t ieee80211_rate2plcp(u_int8_t, enum ieee80211_phymode); +u_int8_t ieee80211_plcp2rate(u_int8_t, enum ieee80211_phymode); +u_int ieee80211_mhz2ieee(u_int, u_int); +u_int ieee80211_chan2ieee(struct ieee80211com *, + const struct ieee80211_channel *); +u_int ieee80211_ieee2mhz(u_int, u_int); +int ieee80211_min_basic_rate(struct ieee80211com *); +int ieee80211_max_basic_rate(struct ieee80211com *); +int ieee80211_setmode(struct ieee80211com *, enum ieee80211_phymode); +enum ieee80211_phymode ieee80211_next_mode(struct ifnet *); +void ieee80211_disable_wep(struct ieee80211com *); +void ieee80211_disable_rsn(struct ieee80211com *); +int ieee80211_add_ess(struct ieee80211com *, struct ieee80211_join *); +void ieee80211_del_ess(struct ieee80211com *, char *, int, int); +void ieee80211_set_ess(struct ieee80211com *, struct ieee80211_ess *, + struct ieee80211_node *); +void ieee80211_deselect_ess(struct ieee80211com *); +struct ieee80211_ess *ieee80211_get_ess(struct ieee80211com *, const char *, int); +void ieee80211_begin_bgscan(struct ifnet *); + +extern int ieee80211_cache_size; + +#endif /* _NET80211_IEEE80211_VAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netdb.h b/lib/libc/include/generic-openbsd/netdb.h new file mode 100644 index 000000000000..c2dd1b9aa0e1 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netdb.h @@ -0,0 +1,329 @@ +/* $OpenBSD: netdb.h,v 1.33 2015/01/18 20:29:31 deraadt Exp $ */ + +/* + * ++Copyright++ 1980, 1983, 1988, 1993 + * - + * Copyright (c) 1980, 1983, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * - + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * - + * --Copyright-- + */ + +/* + * Copyright (c) 1995, 1996, 1997, 1998, 1999 Craig Metz. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * @(#)netdb.h 8.1 (Berkeley) 6/2/93 + * $From: netdb.h,v 8.7 1996/05/09 05:59:09 vixie Exp $ + */ + +#ifndef _NETDB_H_ +#define _NETDB_H_ + +#include + +#ifndef _SOCKLEN_T_DEFINED_ +#define _SOCKLEN_T_DEFINED_ +typedef __socklen_t socklen_t; /* length type for network syscalls */ +#endif + +#define _PATH_HEQUIV "/etc/hosts.equiv" +#define _PATH_HOSTS "/etc/hosts" +#define _PATH_NETWORKS "/etc/networks" +#define _PATH_PROTOCOLS "/etc/protocols" +#define _PATH_SERVICES "/etc/services" + +/* + * Structures returned by network data base library. All addresses are + * supplied in host order, and returned in network order (suitable for + * use in system calls). + */ +struct hostent { + char *h_name; /* official name of host */ + char **h_aliases; /* alias list */ + int h_addrtype; /* host address type */ + int h_length; /* length of address */ + char **h_addr_list; /* list of addresses from name server */ +#define h_addr h_addr_list[0] /* address, for backward compatibility */ +}; + +/* + * Assumption here is that a network number + * fits in an in_addr_t -- probably a poor one. + */ +struct netent { + char *n_name; /* official name of net */ + char **n_aliases; /* alias list */ + int n_addrtype; /* net address type */ + in_addr_t n_net; /* network # */ +}; + +struct servent { + char *s_name; /* official service name */ + char **s_aliases; /* alias list */ + int s_port; /* port # */ + char *s_proto; /* protocol to use */ +}; + +struct protoent { + char *p_name; /* official protocol name */ + char **p_aliases; /* alias list */ + int p_proto; /* protocol # */ +}; + +#if __BSD_VISIBLE || __POSIX_VISIBLE < 200809 +extern int h_errno; + +/* + * Error return codes from gethostbyname() and gethostbyaddr() + * (left in extern int h_errno). + */ + +#define NETDB_INTERNAL -1 /* see errno */ +#define NETDB_SUCCESS 0 /* no problem */ +#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */ +#define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL */ +#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ +#define NO_DATA 4 /* Valid name, no data record of requested type */ +#define NO_ADDRESS NO_DATA /* no address */ +#endif /* __BSD_VISIBLE || __POSIX_VISIBLE < 200809 */ + +/* Values for getaddrinfo() and getnameinfo() */ +#define AI_PASSIVE 1 /* socket address is intended for bind() */ +#define AI_CANONNAME 2 /* request for canonical name */ +#define AI_NUMERICHOST 4 /* don't ever try hostname lookup */ +#define AI_EXT 8 /* enable non-portable extensions */ +#define AI_NUMERICSERV 16 /* don't ever try servname lookup */ +#define AI_FQDN 32 /* return the FQDN that was resolved */ +#define AI_ADDRCONFIG 64 /* return configured address families only */ +/* valid flags for addrinfo */ +#define AI_MASK \ + (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV | AI_FQDN | \ + AI_ADDRCONFIG) + +#define NI_NUMERICHOST 1 /* return the host address, not the name */ +#define NI_NUMERICSERV 2 /* return the service address, not the name */ +#define NI_NOFQDN 4 /* return a short name if in the local domain */ +#define NI_NAMEREQD 8 /* fail if either host or service name is unknown */ +#define NI_DGRAM 16 /* look up datagram service instead of stream */ +/* #define NI_NUMERICSCOPE 32 return the scope number, not the name */ + +#if __BSD_VISIBLE +#define NI_MAXHOST 256 /* max host name from getnameinfo (MAXHOSTNAMELEN) */ +#define NI_MAXSERV 32 /* max serv. name length returned by getnameinfo */ + +/* + * Scope delimit character (KAME hack) + */ +#define SCOPE_DELIMITER '%' +#endif + +#define EAI_BADFLAGS -1 /* invalid value for ai_flags */ +#define EAI_NONAME -2 /* name or service is not known */ +#define EAI_AGAIN -3 /* temporary failure in name resolution */ +#define EAI_FAIL -4 /* non-recoverable failure in name resolution */ +#define EAI_NODATA -5 /* no address associated with name */ +#define EAI_FAMILY -6 /* ai_family not supported */ +#define EAI_SOCKTYPE -7 /* ai_socktype not supported */ +#define EAI_SERVICE -8 /* service not supported for ai_socktype */ +#define EAI_ADDRFAMILY -9 /* address family for name not supported */ +#define EAI_MEMORY -10 /* memory allocation failure */ +#define EAI_SYSTEM -11 /* system error (code indicated in errno) */ +#define EAI_BADHINTS -12 /* invalid value for hints */ +#define EAI_PROTOCOL -13 /* resolved protocol is unknown */ +#define EAI_OVERFLOW -14 /* argument buffer overflow */ + +struct addrinfo { + int ai_flags; /* input flags */ + int ai_family; /* protocol family for socket */ + int ai_socktype; /* socket type */ + int ai_protocol; /* protocol for socket */ + socklen_t ai_addrlen; /* length of socket-address */ + struct sockaddr *ai_addr; /* socket-address for socket */ + char *ai_canonname; /* canonical name for service location (iff req) */ + struct addrinfo *ai_next; /* pointer to next in list */ +}; + +#if __BSD_VISIBLE +/* + * Flags for getrrsetbyname() + */ +#define RRSET_VALIDATED 1 + +/* + * Return codes for getrrsetbyname() + */ +#define ERRSET_SUCCESS 0 +#define ERRSET_NOMEMORY 1 +#define ERRSET_FAIL 2 +#define ERRSET_INVAL 3 +#define ERRSET_NONAME 4 +#define ERRSET_NODATA 5 + +/* + * Structures used by getrrsetbyname() and freerrset() + */ +struct rdatainfo { + unsigned int rdi_length; /* length of data */ + unsigned char *rdi_data; /* record data */ +}; + +struct rrsetinfo { + unsigned int rri_flags; /* RRSET_VALIDATED ... */ + unsigned int rri_rdclass; /* class number */ + unsigned int rri_rdtype; /* RR type number */ + unsigned int rri_ttl; /* time to live */ + unsigned int rri_nrdatas; /* size of rdatas array */ + unsigned int rri_nsigs; /* size of sigs array */ + char *rri_name; /* canonical name */ + struct rdatainfo *rri_rdatas; /* individual records */ + struct rdatainfo *rri_sigs; /* individual signatures */ +}; + +struct servent_data { + void *fp; + char **aliases; + int maxaliases; + int stayopen; + char *line; +}; + +struct protoent_data { + void *fp; + char **aliases; + int maxaliases; + int stayopen; + char *line; +}; +#endif + +__BEGIN_DECLS +void endhostent(void); +void endnetent(void); +void endprotoent(void); +void endservent(void); +#if __BSD_VISIBLE || __POSIX_VISIBLE < 200809 +struct hostent *gethostbyaddr(const void *, socklen_t, int); +struct hostent *gethostbyname(const char *); +#endif +#if __BSD_VISIBLE +struct hostent *gethostbyname2(const char *, int); +#endif +struct hostent *gethostent(void); +struct netent *getnetbyaddr(in_addr_t, int); +struct netent *getnetbyname(const char *); +struct netent *getnetent(void); +struct protoent *getprotobyname(const char *); +struct protoent *getprotobynumber(int); +struct protoent *getprotoent(void); +struct servent *getservbyname(const char *, const char *); +struct servent *getservbyport(int, const char *); +struct servent *getservent(void); +#if __BSD_VISIBLE +void herror(const char *); +const char *hstrerror(int); +#endif +void sethostent(int); +/* void sethostfile(const char *); */ +void setnetent(int); +void setprotoent(int); +void setservent(int); + +#if __BSD_VISIBLE +void endprotoent_r(struct protoent_data *); +void endservent_r(struct servent_data *); +int getprotobyname_r(const char *, struct protoent *, + struct protoent_data *); +int getprotobynumber_r(int, struct protoent *, + struct protoent_data *); +int getservbyname_r(const char *, const char *, struct servent *, + struct servent_data *); +int getservbyport_r(int, const char *, struct servent *, + struct servent_data *); +int getservent_r(struct servent *, struct servent_data *); +int getprotoent_r(struct protoent *, struct protoent_data *); +void setprotoent_r(int, struct protoent_data *); +void setservent_r(int, struct servent_data *); +#endif + +int getaddrinfo(const char *, const char *, + const struct addrinfo *, struct addrinfo **); +void freeaddrinfo(struct addrinfo *); +int getnameinfo(const struct sockaddr *, socklen_t, + char *, size_t, char *, size_t, int); +const char *gai_strerror(int); + +#if __BSD_VISIBLE +int getrrsetbyname(const char *, unsigned int, unsigned int, unsigned int, struct rrsetinfo **); +void freerrset(struct rrsetinfo *); +#endif +__END_DECLS + +#endif /* !_NETDB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netgroup.h b/lib/libc/include/generic-openbsd/netgroup.h new file mode 100644 index 000000000000..ec48b2d208f5 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netgroup.h @@ -0,0 +1,62 @@ +/* $OpenBSD: netgroup.h,v 1.9 2023/01/04 13:00:11 jsg Exp $ */ +/* + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#ifndef _NETGROUP_H_ +#define _NETGROUP_H_ + +#define _PATH_NETGROUP "/etc/netgroup" + +#define _PATH_NETGROUP_DB "/etc/netgroup.db" + +#define _PATH_NETGROUP_MKDB "/usr/sbin/netgroup_mkdb" + +#define _NG_KEYBYNAME '1' /* stored by name */ +#define _NG_KEYBYUSER '2' /* stored by user */ +#define _NG_KEYBYHOST '3' /* stored by host */ + +#define _NG_ERROR -1 +#define _NG_NONE 0 +#define _NG_NAME 1 +#define _NG_GROUP 2 + +struct netgroup { + char *ng_host; /* host name */ + char *ng_user; /* user name */ + char *ng_domain; /* domain name */ + struct netgroup *ng_next; /* thread */ +}; + +#include + +__BEGIN_DECLS +void setnetgrent(const char *); +int getnetgrent(const char **, const char **, const char **); +void endnetgrent(void); +int innetgr(const char *, const char *, const char *, const char *); +__END_DECLS + +#endif /* !_NETGROUP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/icmp6.h b/lib/libc/include/generic-openbsd/netinet/icmp6.h new file mode 100644 index 000000000000..db378d8086dc --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/icmp6.h @@ -0,0 +1,608 @@ +/* $OpenBSD: icmp6.h,v 1.57 2025/09/16 09:19:43 florian Exp $ */ +/* $KAME: icmp6.h,v 1.84 2003/04/23 10:26:51 itojun Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_ICMP6_H_ +#define _NETINET_ICMP6_H_ + +#define ICMPV6_PLD_MAXLEN 1232 /* IPV6_MMTU - sizeof(struct ip6_hdr) + - sizeof(struct icmp6_hdr) */ + +struct icmp6_hdr { + u_int8_t icmp6_type; /* type field */ + u_int8_t icmp6_code; /* code field */ + u_int16_t icmp6_cksum; /* checksum field */ + union { + u_int32_t icmp6_un_data32[1]; /* type-specific field */ + u_int16_t icmp6_un_data16[2]; /* type-specific field */ + u_int8_t icmp6_un_data8[4]; /* type-specific field */ + } icmp6_dataun; +} __packed; + +#define icmp6_data32 icmp6_dataun.icmp6_un_data32 +#define icmp6_data16 icmp6_dataun.icmp6_un_data16 +#define icmp6_data8 icmp6_dataun.icmp6_un_data8 +#define icmp6_pptr icmp6_data32[0] /* parameter prob */ +#define icmp6_mtu icmp6_data32[0] /* packet too big */ +#define icmp6_id icmp6_data16[0] /* echo request/reply */ +#define icmp6_seq icmp6_data16[1] /* echo request/reply */ +#define icmp6_maxdelay icmp6_data16[0] /* mcast group membership */ + +#define ICMP6_DST_UNREACH 1 /* dest unreachable, codes: */ +#define ICMP6_PACKET_TOO_BIG 2 /* packet too big */ +#define ICMP6_TIME_EXCEEDED 3 /* time exceeded, code: */ +#define ICMP6_PARAM_PROB 4 /* ip6 header bad */ + +#define ICMP6_ECHO_REQUEST 128 /* echo service */ +#define ICMP6_ECHO_REPLY 129 /* echo reply */ +#define MLD_LISTENER_QUERY 130 /* multicast listener query */ +#define MLD_LISTENER_REPORT 131 /* multicast listener report */ +#define MLD_LISTENER_DONE 132 /* multicast listener done */ + +/* RFC2292 decls */ +#define ICMP6_MEMBERSHIP_QUERY 130 /* group membership query */ +#define ICMP6_MEMBERSHIP_REPORT 131 /* group membership report */ +#define ICMP6_MEMBERSHIP_REDUCTION 132 /* group membership termination */ + +#define ND_ROUTER_SOLICIT 133 /* router solicitation */ +#define ND_ROUTER_ADVERT 134 /* router advertisement */ +#define ND_NEIGHBOR_SOLICIT 135 /* neighbor solicitation */ +#define ND_NEIGHBOR_ADVERT 136 /* neighbor advertisement */ +#define ND_REDIRECT 137 /* redirect */ + +#define ICMP6_ROUTER_RENUMBERING 138 /* router renumbering */ + +#define ICMP6_WRUREQUEST 139 /* who are you request */ +#define ICMP6_WRUREPLY 140 /* who are you reply */ +#define ICMP6_FQDN_QUERY 139 /* FQDN query */ +#define ICMP6_FQDN_REPLY 140 /* FQDN reply */ +#define ICMP6_NI_QUERY 139 /* node information request */ +#define ICMP6_NI_REPLY 140 /* node information reply */ +#define MLDV2_LISTENER_REPORT 143 /* RFC3810 listener report */ + +/* The definitions below are experimental. TBA */ +#define MLD_MTRACE_RESP 200 /* mtrace response(to sender) */ +#define MLD_MTRACE 201 /* mtrace messages */ + +#define ICMP6_MAXTYPE 201 + +#define ICMP6_DST_UNREACH_NOROUTE 0 /* no route to destination */ +#define ICMP6_DST_UNREACH_ADMIN 1 /* administratively prohibited */ +#define ICMP6_DST_UNREACH_BEYONDSCOPE 2 /* beyond scope of source address */ +#define ICMP6_DST_UNREACH_ADDR 3 /* address unreachable */ +#define ICMP6_DST_UNREACH_NOPORT 4 /* port unreachable */ + +#define ICMP6_TIME_EXCEED_TRANSIT 0 /* ttl==0 in transit */ +#define ICMP6_TIME_EXCEED_REASSEMBLY 1 /* ttl==0 in reass */ + +#define ICMP6_PARAMPROB_HEADER 0 /* erroneous header field */ +#define ICMP6_PARAMPROB_NEXTHEADER 1 /* unrecognized next header */ +#define ICMP6_PARAMPROB_OPTION 2 /* unrecognized option */ + +#define ICMP6_INFOMSG_MASK 0x80 /* all informational messages */ + +#define ICMP6_NI_SUBJ_IPV6 0 /* Query Subject is an IPv6 address */ +#define ICMP6_NI_SUBJ_FQDN 1 /* Query Subject is a Domain name */ +#define ICMP6_NI_SUBJ_IPV4 2 /* Query Subject is an IPv4 address */ + +#define ICMP6_NI_SUCCESS 0 /* node information successful reply */ +#define ICMP6_NI_REFUSED 1 /* node information request is refused */ +#define ICMP6_NI_UNKNOWN 2 /* unknown Qtype */ + +#define ICMP6_ROUTER_RENUMBERING_COMMAND 0 /* rr command */ +#define ICMP6_ROUTER_RENUMBERING_RESULT 1 /* rr result */ +#define ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET 255 /* rr seq num reset */ + +/* Used in kernel only */ +#define ND_REDIRECT_ONLINK 0 /* redirect to an on-link node */ +#define ND_REDIRECT_ROUTER 1 /* redirect to a better router */ + +/* + * Multicast Listener Discovery + */ +struct mld_hdr { + struct icmp6_hdr mld_icmp6_hdr; + struct in6_addr mld_addr; /* multicast address */ +} __packed; + +/* shortcut macro definitions */ +#define mld_type mld_icmp6_hdr.icmp6_type +#define mld_code mld_icmp6_hdr.icmp6_code +#define mld_cksum mld_icmp6_hdr.icmp6_cksum +#define mld_maxdelay mld_icmp6_hdr.icmp6_data16[0] +#define mld_reserved mld_icmp6_hdr.icmp6_data16[1] + +/* + * Neighbor Discovery + */ + +struct nd_router_solicit { /* router solicitation */ + struct icmp6_hdr nd_rs_hdr; + /* could be followed by options */ +} __packed; + +#define nd_rs_type nd_rs_hdr.icmp6_type +#define nd_rs_code nd_rs_hdr.icmp6_code +#define nd_rs_cksum nd_rs_hdr.icmp6_cksum +#define nd_rs_reserved nd_rs_hdr.icmp6_data32[0] + +struct nd_router_advert { /* router advertisement */ + struct icmp6_hdr nd_ra_hdr; + u_int32_t nd_ra_reachable; /* reachable time */ + u_int32_t nd_ra_retransmit; /* retransmit timer */ + /* could be followed by options */ +} __packed; + +#define nd_ra_type nd_ra_hdr.icmp6_type +#define nd_ra_code nd_ra_hdr.icmp6_code +#define nd_ra_cksum nd_ra_hdr.icmp6_cksum +#define nd_ra_curhoplimit nd_ra_hdr.icmp6_data8[0] +#define nd_ra_flags_reserved nd_ra_hdr.icmp6_data8[1] +#define ND_RA_FLAG_MANAGED 0x80 +#define ND_RA_FLAG_OTHER 0x40 + +#define ND_RA_FLAG_RTPREF_MASK 0x18 /* 00011000 */ + +#define ND_RA_FLAG_RTPREF_HIGH 0x08 /* 00001000 */ +#define ND_RA_FLAG_RTPREF_MEDIUM 0x00 /* 00000000 */ +#define ND_RA_FLAG_RTPREF_LOW 0x18 /* 00011000 */ +#define ND_RA_FLAG_RTPREF_RSV 0x10 /* 00010000 */ + +#define nd_ra_router_lifetime nd_ra_hdr.icmp6_data16[1] + +struct nd_neighbor_solicit { /* neighbor solicitation */ + struct icmp6_hdr nd_ns_hdr; + struct in6_addr nd_ns_target; /*target address */ + /* could be followed by options */ +} __packed; + +#define nd_ns_type nd_ns_hdr.icmp6_type +#define nd_ns_code nd_ns_hdr.icmp6_code +#define nd_ns_cksum nd_ns_hdr.icmp6_cksum +#define nd_ns_reserved nd_ns_hdr.icmp6_data32[0] + +struct nd_neighbor_advert { /* neighbor advertisement */ + struct icmp6_hdr nd_na_hdr; + struct in6_addr nd_na_target; /* target address */ + /* could be followed by options */ +} __packed; + +#define nd_na_type nd_na_hdr.icmp6_type +#define nd_na_code nd_na_hdr.icmp6_code +#define nd_na_cksum nd_na_hdr.icmp6_cksum +#define nd_na_flags_reserved nd_na_hdr.icmp6_data32[0] +#define ND_NA_FLAG_ROUTER htonl(0x80000000) +#define ND_NA_FLAG_SOLICITED htonl(0x40000000) +#define ND_NA_FLAG_OVERRIDE htonl(0x20000000) + +struct nd_redirect { /* redirect */ + struct icmp6_hdr nd_rd_hdr; + struct in6_addr nd_rd_target; /* target address */ + struct in6_addr nd_rd_dst; /* destination address */ + /* could be followed by options */ +} __packed; + +#define nd_rd_type nd_rd_hdr.icmp6_type +#define nd_rd_code nd_rd_hdr.icmp6_code +#define nd_rd_cksum nd_rd_hdr.icmp6_cksum +#define nd_rd_reserved nd_rd_hdr.icmp6_data32[0] + +struct nd_opt_hdr { /* Neighbor discovery option header */ + u_int8_t nd_opt_type; + u_int8_t nd_opt_len; + /* followed by option specific data*/ +} __packed; + +#define ND_OPT_SOURCE_LINKADDR 1 +#define ND_OPT_TARGET_LINKADDR 2 +#define ND_OPT_PREFIX_INFORMATION 3 +#define ND_OPT_REDIRECTED_HEADER 4 +#define ND_OPT_MTU 5 +#define ND_OPT_ROUTE_INFO 24 +#define ND_OPT_RDNSS 25 +#define ND_OPT_DNSSL 31 + +struct nd_opt_prefix_info { /* prefix information */ + u_int8_t nd_opt_pi_type; + u_int8_t nd_opt_pi_len; + u_int8_t nd_opt_pi_prefix_len; + u_int8_t nd_opt_pi_flags_reserved; + u_int32_t nd_opt_pi_valid_time; + u_int32_t nd_opt_pi_preferred_time; + u_int32_t nd_opt_pi_reserved2; + struct in6_addr nd_opt_pi_prefix; +} __packed; + +#define ND_OPT_PI_FLAG_ONLINK 0x80 +#define ND_OPT_PI_FLAG_AUTO 0x40 + +struct nd_opt_rd_hdr { /* redirected header */ + u_int8_t nd_opt_rh_type; + u_int8_t nd_opt_rh_len; + u_int16_t nd_opt_rh_reserved1; + u_int32_t nd_opt_rh_reserved2; + /* followed by IP header and data */ +} __packed; + +struct nd_opt_mtu { /* MTU option */ + u_int8_t nd_opt_mtu_type; + u_int8_t nd_opt_mtu_len; + u_int16_t nd_opt_mtu_reserved; + u_int32_t nd_opt_mtu_mtu; +} __packed; + +struct nd_opt_route_info { /* route info */ + u_int8_t nd_opt_rti_type; + u_int8_t nd_opt_rti_len; + u_int8_t nd_opt_rti_prefixlen; + u_int8_t nd_opt_rti_flags; + u_int32_t nd_opt_rti_lifetime; +} __packed; + +struct nd_opt_rdnss { /* RDNSS option */ + u_int8_t nd_opt_rdnss_type; + u_int8_t nd_opt_rdnss_len; + u_int16_t nd_opt_rdnss_reserved; + u_int32_t nd_opt_rdnss_lifetime; + /* followed by list of recursive DNS servers */ +} __packed; + +struct nd_opt_dnssl { /* DNSSL option */ + u_int8_t nd_opt_dnssl_type; + u_int8_t nd_opt_dnssl_len; + u_int16_t nd_opt_dnssl_reserved; + u_int32_t nd_opt_dnssl_lifetime; + /* followed by list of DNS search domains */ +} __packed; + +/* + * icmp6 namelookup + */ +struct icmp6_namelookup { + struct icmp6_hdr icmp6_nl_hdr; + u_int8_t icmp6_nl_nonce[8]; + int32_t icmp6_nl_ttl; +#if 0 + u_int8_t icmp6_nl_len; + u_int8_t icmp6_nl_name[3]; +#endif + /* could be followed by options */ +} __packed; + +/* + * icmp6 node information + */ +struct icmp6_nodeinfo { + struct icmp6_hdr icmp6_ni_hdr; + u_int8_t icmp6_ni_nonce[8]; + /* could be followed by reply data */ +} __packed; + +#define ni_type icmp6_ni_hdr.icmp6_type +#define ni_code icmp6_ni_hdr.icmp6_code +#define ni_cksum icmp6_ni_hdr.icmp6_cksum +#define ni_qtype icmp6_ni_hdr.icmp6_data16[0] +#define ni_flags icmp6_ni_hdr.icmp6_data16[1] + +#define NI_QTYPE_NOOP 0 /* NOOP */ +#define NI_QTYPE_SUPTYPES 1 /* Supported Qtypes */ +#define NI_QTYPE_FQDN 2 /* FQDN (draft 04) */ +#define NI_QTYPE_DNSNAME 2 /* DNS Name */ +#define NI_QTYPE_NODEADDR 3 /* Node Addresses */ +#define NI_QTYPE_IPV4ADDR 4 /* IPv4 Addresses */ + +#define NI_SUPTYPE_FLAG_COMPRESS htons(0x0001) +#define NI_FQDN_FLAG_VALIDTTL htons(0x0001) + +#define NI_NODEADDR_FLAG_TRUNCATE htons(0x0001) +#define NI_NODEADDR_FLAG_ALL htons(0x0002) +#define NI_NODEADDR_FLAG_COMPAT htons(0x0004) +#define NI_NODEADDR_FLAG_LINKLOCAL htons(0x0008) +#define NI_NODEADDR_FLAG_SITELOCAL htons(0x0010) +#define NI_NODEADDR_FLAG_GLOBAL htons(0x0020) +#define NI_NODEADDR_FLAG_ANYCAST htons(0x0040) /* not in spec */ + +struct ni_reply_fqdn { + u_int32_t ni_fqdn_ttl; /* TTL */ + u_int8_t ni_fqdn_namelen; /* length in octets of the FQDN */ + u_int8_t ni_fqdn_name[3]; /* XXX: alignment */ +} __packed; + +/* + * Router Renumbering. as router-renum-08.txt + */ +struct icmp6_router_renum { /* router renumbering header */ + struct icmp6_hdr rr_hdr; + u_int8_t rr_segnum; + u_int8_t rr_flags; + u_int16_t rr_maxdelay; + u_int32_t rr_reserved; +} __packed; + +#define ICMP6_RR_FLAGS_TEST 0x80 +#define ICMP6_RR_FLAGS_REQRESULT 0x40 +#define ICMP6_RR_FLAGS_FORCEAPPLY 0x20 +#define ICMP6_RR_FLAGS_SPECSITE 0x10 +#define ICMP6_RR_FLAGS_PREVDONE 0x08 + +#define rr_type rr_hdr.icmp6_type +#define rr_code rr_hdr.icmp6_code +#define rr_cksum rr_hdr.icmp6_cksum +#define rr_seqnum rr_hdr.icmp6_data32[0] + +struct rr_pco_match { /* match prefix part */ + u_int8_t rpm_code; + u_int8_t rpm_len; + u_int8_t rpm_ordinal; + u_int8_t rpm_matchlen; + u_int8_t rpm_minlen; + u_int8_t rpm_maxlen; + u_int16_t rpm_reserved; + struct in6_addr rpm_prefix; +} __packed; + +#define RPM_PCO_ADD 1 +#define RPM_PCO_CHANGE 2 +#define RPM_PCO_SETGLOBAL 3 +#define RPM_PCO_MAX 4 + +struct rr_pco_use { /* use prefix part */ + u_int8_t rpu_uselen; + u_int8_t rpu_keeplen; + u_int8_t rpu_ramask; + u_int8_t rpu_raflags; + u_int32_t rpu_vltime; + u_int32_t rpu_pltime; + u_int32_t rpu_flags; + struct in6_addr rpu_prefix; +} __packed; +#define ICMP6_RR_PCOUSE_RAFLAGS_ONLINK 0x80 +#define ICMP6_RR_PCOUSE_RAFLAGS_AUTO 0x40 + +#define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME htonl(0x80000000) +#define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME htonl(0x40000000) + +struct rr_result { /* router renumbering result message */ + u_int16_t rrr_flags; + u_int8_t rrr_ordinal; + u_int8_t rrr_matchedlen; + u_int32_t rrr_ifid; + struct in6_addr rrr_prefix; +} __packed; +#define ICMP6_RR_RESULT_FLAGS_OOB htons(0x0002) +#define ICMP6_RR_RESULT_FLAGS_FORBIDDEN htons(0x0001) + +/* + * icmp6 filter structures. + */ + +struct icmp6_filter { + u_int32_t icmp6_filt[8]; +}; + +#define ICMP6_FILTER_SETPASSALL(filterp) \ + memset(filterp, 0xff, sizeof(struct icmp6_filter)) +#define ICMP6_FILTER_SETBLOCKALL(filterp) \ + memset(filterp, 0x00, sizeof(struct icmp6_filter)) +#define ICMP6_FILTER_SETPASS(type, filterp) \ + (((filterp)->icmp6_filt[(type) >> 5]) |= (1 << ((type) & 31))) +#define ICMP6_FILTER_SETBLOCK(type, filterp) \ + (((filterp)->icmp6_filt[(type) >> 5]) &= ~(1 << ((type) & 31))) +#define ICMP6_FILTER_WILLPASS(type, filterp) \ + ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) != 0) +#define ICMP6_FILTER_WILLBLOCK(type, filterp) \ + ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) == 0) + +/* + * Variables related to this implementation + * of the internet control message protocol version 6. + */ +struct icmp6stat { +/* statistics related to icmp6 packets generated */ + u_int64_t icp6s_error; /* # of calls to icmp6_error */ + u_int64_t icp6s_canterror; /* no error because old was icmp */ + u_int64_t icp6s_toofreq; /* no error because rate limitation */ + u_int64_t icp6s_outhist[256]; +/* statistics related to input message processed */ + u_int64_t icp6s_badcode; /* icmp6_code out of range */ + u_int64_t icp6s_tooshort; /* packet < sizeof(struct icmp6_hdr) */ + u_int64_t icp6s_checksum; /* bad checksum */ + u_int64_t icp6s_badlen; /* calculated bound mismatch */ + /* + * number of responses: this member is inherited from netinet code, but + * for netinet6 code, it is already available in icp6s_outhist[]. + */ + u_int64_t icp6s_reflect; + u_int64_t icp6s_inhist[256]; + u_int64_t icp6s_nd_toomanyopt; /* too many ND options */ + u_int64_t icp6s_odst_unreach_noroute; + u_int64_t icp6s_odst_unreach_admin; + u_int64_t icp6s_odst_unreach_beyondscope; + u_int64_t icp6s_odst_unreach_addr; + u_int64_t icp6s_odst_unreach_noport; + u_int64_t icp6s_opacket_too_big; + u_int64_t icp6s_otime_exceed_transit; + u_int64_t icp6s_otime_exceed_reassembly; + u_int64_t icp6s_oparamprob_header; + u_int64_t icp6s_oparamprob_nextheader; + u_int64_t icp6s_oparamprob_option; + u_int64_t icp6s_oredirect; /* we regard redirect as an error here */ + u_int64_t icp6s_ounknown; + u_int64_t icp6s_pmtuchg; /* path MTU changes */ + u_int64_t icp6s_nd_badopt; /* bad ND options */ + u_int64_t icp6s_badns; /* bad neighbor solicitation */ + u_int64_t icp6s_badna; /* bad neighbor advertisement */ + u_int64_t icp6s_badrs; /* bad router advertisement */ + u_int64_t icp6s_badra; /* bad router advertisement */ + u_int64_t icp6s_badredirect; /* bad redirect message */ +}; + +/* + * Names for ICMP sysctl objects + */ +#define ICMPV6CTL_STATS 1 +#define ICMPV6CTL_REDIRACCEPT 2 /* accept/process redirects */ +#define ICMPV6CTL_REDIRTIMEOUT 3 /* redirect cache time */ +#define ICMPV6CTL_ND6_DELAY 8 +#define ICMPV6CTL_ND6_UMAXTRIES 9 +#define ICMPV6CTL_ND6_MMAXTRIES 10 +#define ICMPV6CTL_ND6_QUEUED 11 +#define ICMPV6CTL_NODEINFO 13 +#define ICMPV6CTL_ERRPPSLIMIT 14 /* ICMPv6 error pps limitation */ +#define ICMPV6CTL_MTUDISC_HIWAT 16 +#define ICMPV6CTL_MTUDISC_LOWAT 17 +#define ICMPV6CTL_MAXID 18 + +#define ICMPV6CTL_NAMES { \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "redirtimeout", CTLTYPE_INT }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "nd6_delay", CTLTYPE_INT }, \ + { "nd6_umaxtries", CTLTYPE_INT }, \ + { "nd6_mmaxtries", CTLTYPE_INT }, \ + { "nd6_queued", CTLTYPE_INT }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "errppslimit", CTLTYPE_INT }, \ + { 0, 0 }, \ + { "mtudisc_hiwat", CTLTYPE_INT }, \ + { "mtudisc_lowat", CTLTYPE_INT }, \ +} + +#define RTF_PROBEMTU RTF_PROTO1 + +#ifdef _KERNEL + +#include + +enum icmp6stat_counters { + icp6s_error, + icp6s_canterror, + icp6s_toofreq, + icp6s_outhist, + icp6s_badcode = icp6s_outhist + 256, + icp6s_tooshort, + icp6s_checksum, + icp6s_badlen, + icp6s_reflect, + icp6s_inhist, + icp6s_nd_toomanyopt = icp6s_inhist + 256, + icp6s_odst_unreach_noroute, + icp6s_odst_unreach_admin, + icp6s_odst_unreach_beyondscope, + icp6s_odst_unreach_addr, + icp6s_odst_unreach_noport, + icp6s_opacket_too_big, + icp6s_otime_exceed_transit, + icp6s_otime_exceed_reassembly, + icp6s_oparamprob_header, + icp6s_oparamprob_nextheader, + icp6s_oparamprob_option, + icp6s_oredirect, + icp6s_ounknown, + icp6s_pmtuchg, + icp6s_nd_badopt, + icp6s_badns, + icp6s_badna, + icp6s_badrs, + icp6s_badra, + icp6s_badredirect, + icp6s_ncounters, +}; + +extern struct cpumem *icmp6counters; + +static inline void +icmp6stat_inc(enum icmp6stat_counters c) +{ + counters_inc(icmp6counters, c); +} + +struct rtentry; +struct rttimer; +struct in6_multi; + +void icmp6_init(void); +struct mbuf *icmp6_do_error(struct mbuf *, int, int, int); +void icmp6_error(struct mbuf *, int, int, int); +int icmp6_input(struct mbuf **, int *, int, int, + struct netstack *); +void icmp6_fasttimo(void); +int icmp6_reflect(struct mbuf **, size_t, struct sockaddr *); +void icmp6_redirect_input(struct mbuf *, int); +void icmp6_redirect_output(struct mbuf *, struct rtentry *); +int icmp6_sysctl(int *, u_int, void *, size_t *, void *, size_t); +struct rtentry *icmp6_mtudisc_clone(struct sockaddr_in6 *, u_int, int); + +struct ip6ctlparam; +void icmp6_mtudisc_update(struct ip6ctlparam *, int); +void icmp6_mtudisc_callback_register(void (*)(struct sockaddr_in6 *, u_int)); + +extern int icmp6_redirtimeout; /* cache time for redirect routes */ + +#endif /* _KERNEL */ +#endif /* _NETINET_ICMP6_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/icmp_var.h b/lib/libc/include/generic-openbsd/netinet/icmp_var.h new file mode 100644 index 000000000000..7aa326ae5c4d --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/icmp_var.h @@ -0,0 +1,111 @@ +/* $OpenBSD: icmp_var.h,v 1.16 2020/08/22 17:55:54 gnezdo Exp $ */ +/* $NetBSD: icmp_var.h,v 1.8 1995/03/26 20:32:19 jtc Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)icmp_var.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_ICMP_VAR_H_ +#define _NETINET_ICMP_VAR_H_ + +/* + * Variables related to this implementation + * of the internet control message protocol. + */ +struct icmpstat { +/* statistics related to icmp packets generated */ + u_long icps_error; /* # of calls to icmp_error */ + u_long icps_toofreq; /* no error because rate limiter */ + u_long icps_oldshort; /* no error because old ip too short */ + u_long icps_oldicmp; /* no error because old was icmp */ + u_long icps_outhist[ICMP_MAXTYPE + 1]; +/* statistics related to input messages processed */ + u_long icps_badcode; /* icmp_code out of range */ + u_long icps_tooshort; /* packet < ICMP_MINLEN */ + u_long icps_checksum; /* bad checksum */ + u_long icps_badlen; /* calculated bound mismatch */ + u_long icps_reflect; /* number of responses */ + u_long icps_bmcastecho; /* rejected broadcast icmps */ + u_long icps_inhist[ICMP_MAXTYPE + 1]; +}; + +/* + * Names for ICMP sysctl objects + */ +#define ICMPCTL_MASKREPL 1 /* allow replies to netmask requests */ +#define ICMPCTL_BMCASTECHO 2 /* reply to icmps to broadcast/mcast */ +#define ICMPCTL_ERRPPSLIMIT 3 /* ICMP error pps limitation */ +#define ICMPCTL_REDIRACCEPT 4 /* Accept redirects from routers */ +#define ICMPCTL_REDIRTIMEOUT 5 /* Remove routes added via redirects */ +#define ICMPCTL_TSTAMPREPL 6 /* allow replies to timestamp requests */ +#define ICMPCTL_STATS 7 /* ICMP statistics */ +#define ICMPCTL_MAXID 8 + +#define ICMPCTL_NAMES { \ + { 0, 0 }, \ + { "maskrepl", CTLTYPE_INT }, \ + { "bmcastecho", CTLTYPE_INT }, \ + { "errppslimit", CTLTYPE_INT }, \ + { "rediraccept", CTLTYPE_INT }, \ + { "redirtimeout", CTLTYPE_INT }, \ + { "tstamprepl", CTLTYPE_INT }, \ + { "stats", CTLTYPE_STRUCT } \ +} + +#ifdef _KERNEL + +#include + +enum icmpstat_counters { + icps_error, + icps_toofreq, + icps_oldshort, + icps_oldicmp, + icps_outhist, + icps_badcode = icps_outhist + ICMP_MAXTYPE + 1, + icps_tooshort, + icps_checksum, + icps_badlen, + icps_reflect, + icps_bmcastecho, + icps_inhist, + icps_ncounters = icps_inhist + ICMP_MAXTYPE + 1 +}; + +extern struct cpumem *icmpcounters; + +static inline void +icmpstat_inc(enum icmpstat_counters c) +{ + counters_inc(icmpcounters, c); +} + +#endif /* _KERNEL */ +#endif /* _NETINET_ICMP_VAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/if_ether.h b/lib/libc/include/generic-openbsd/netinet/if_ether.h new file mode 100644 index 000000000000..35eab7180458 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/if_ether.h @@ -0,0 +1,398 @@ +/* $OpenBSD: if_ether.h,v 1.96 2025/07/07 00:55:15 jsg Exp $ */ +/* $NetBSD: if_ether.h,v 1.22 1996/05/11 13:00:00 mycroft Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_ether.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_IF_ETHER_H_ +#define _NETINET_IF_ETHER_H_ + +/* + * Some basic Ethernet constants. + */ +#define ETHER_ADDR_LEN 6 /* Ethernet address length */ +#define ETHER_TYPE_LEN 2 /* Ethernet type field length */ +#define ETHER_CRC_LEN 4 /* Ethernet CRC length */ +#define ETHER_HDR_LEN ((ETHER_ADDR_LEN * 2) + ETHER_TYPE_LEN) +#define ETHER_MIN_LEN 64 /* Minimum frame length, CRC included */ +#define ETHER_MAX_LEN 1518 /* Maximum frame length, CRC included */ +#define ETHER_MAX_DIX_LEN 1536 /* Maximum DIX frame length */ + +/* + * Some Ethernet extensions. + */ +#define ETHER_VLAN_ENCAP_LEN 4 /* len of 802.1Q VLAN encapsulation */ + +/* + * Mbuf adjust factor to force 32-bit alignment of IP header. + * Drivers should do m_adj(m, ETHER_ALIGN) when setting up a + * receive so the upper layers get the IP header properly aligned + * past the 14-byte Ethernet header. + */ +#define ETHER_ALIGN 2 /* driver adjust for IP hdr alignment */ + +/* + * The maximum supported Ethernet length and some space for encapsulation. + */ +#define ETHER_MAX_HARDMTU_LEN 65435 + +/* + * Ethernet address - 6 octets + */ +struct ether_addr { + u_int8_t ether_addr_octet[ETHER_ADDR_LEN]; +}; + +/* + * The length of the combined header. + */ +struct ether_header { + u_int8_t ether_dhost[ETHER_ADDR_LEN]; + u_int8_t ether_shost[ETHER_ADDR_LEN]; + u_int16_t ether_type; +}; + +/* + * VLAN headers. + */ + +struct ether_vlan_header { + u_char evl_dhost[ETHER_ADDR_LEN]; + u_char evl_shost[ETHER_ADDR_LEN]; + u_int16_t evl_encap_proto; + u_int16_t evl_tag; + u_int16_t evl_proto; +}; + +#define EVL_VLID_MASK 0xFFF +#define EVL_VLID_NULL 0x000 +/* 0x000 and 0xfff are reserved */ +#define EVL_VLID_MIN 0x001 +#define EVL_VLID_MAX 0xFFE +#define EVL_VLANOFTAG(tag) ((tag) & EVL_VLID_MASK) + +#define EVL_PRIO_MAX 7 +#define EVL_PRIO_BITS 13 +#define EVL_PRIOFTAG(tag) (((tag) >> EVL_PRIO_BITS) & 7) + +#define EVL_ENCAPLEN 4 /* length in octets of encapsulation */ + +#include + +#define ETHER_IS_MULTICAST(addr) (*(addr) & 0x01) /* is address mcast/bcast? */ +#define ETHER_IS_BROADCAST(addr) \ + (((addr)[0] & (addr)[1] & (addr)[2] & \ + (addr)[3] & (addr)[4] & (addr)[5]) == 0xff) +#define ETHER_IS_ANYADDR(addr) \ + (((addr)[0] | (addr)[1] | (addr)[2] | \ + (addr)[3] | (addr)[4] | (addr)[5]) == 0x00) +#define ETHER_IS_EQ(a1, a2) (memcmp((a1), (a2), ETHER_ADDR_LEN) == 0) + +/* + * It can be faster to work with ethernet addresses as a uint64_t. + * Provide some constants and functionality centrally to better + * support this. + */ + +#define ETH64_IS_MULTICAST(_e64) ((_e64) & 0x010000000000ULL) +#define ETH64_IS_BROADCAST(_e64) ((_e64) == 0xffffffffffffULL) +#define ETH64_IS_ANYADDR(_e64) ((_e64) == 0x000000000000ULL) + +#define ETH64_8021_RSVD_PREFIX 0x0180c2000000ULL +#define ETH64_8021_RSVD_MASK 0xfffffffffff0ULL +#define ETH64_IS_8021_RSVD(_e64) \ + (((_e64) & ETH64_8021_RSVD_MASK) == ETH64_8021_RSVD_PREFIX) + +/* + * Ethernet MTU constants. + */ +#define ETHERMTU (ETHER_MAX_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN) +#define ETHERMIN (ETHER_MIN_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN) + +/* + * Ethernet CRC32 polynomials (big- and little-endian versions). + */ +#define ETHER_CRC_POLY_LE 0xedb88320 +#define ETHER_CRC_POLY_BE 0x04c11db6 + +/* + * Ethernet Address Resolution Protocol. + * + * See RFC 826 for protocol description. Structure below is adapted + * to resolving internet addresses. Field names used correspond to + * RFC 826. + */ +struct ether_arp { + struct arphdr ea_hdr; /* fixed-size header */ + u_int8_t arp_sha[ETHER_ADDR_LEN]; /* sender hardware address */ + u_int8_t arp_spa[4]; /* sender protocol address */ + u_int8_t arp_tha[ETHER_ADDR_LEN]; /* target hardware address */ + u_int8_t arp_tpa[4]; /* target protocol address */ +}; +#define arp_hrd ea_hdr.ar_hrd +#define arp_pro ea_hdr.ar_pro +#define arp_hln ea_hdr.ar_hln +#define arp_pln ea_hdr.ar_pln +#define arp_op ea_hdr.ar_op + +struct sockaddr_inarp { + u_int8_t sin_len; + u_int8_t sin_family; + u_int16_t sin_port; + struct in_addr sin_addr; + struct in_addr sin_srcaddr; + u_int16_t sin_tos; + u_int16_t sin_other; +#define SIN_PROXY 1 +}; + +/* + * IP and ethernet specific routing flags + */ +#define RTF_USETRAILERS RTF_PROTO1 /* use trailers */ +#define RTF_PERMANENT_ARP RTF_PROTO3 /* only manual overwrite of entry */ + +#ifdef _KERNEL + +#include + +/* + * Macro to map an IP multicast address to an Ethernet multicast address. + * The high-order 25 bits of the Ethernet address are statically assigned, + * and the low-order 23 bits are taken from the low end of the IP address. + */ +#define ETHER_MAP_IP_MULTICAST(ipaddr, enaddr) \ + /* struct in_addr *ipaddr; */ \ + /* u_int8_t enaddr[ETHER_ADDR_LEN]; */ \ +do { \ + (enaddr)[0] = 0x01; \ + (enaddr)[1] = 0x00; \ + (enaddr)[2] = 0x5e; \ + (enaddr)[3] = ((u_int8_t *)ipaddr)[1] & 0x7f; \ + (enaddr)[4] = ((u_int8_t *)ipaddr)[2]; \ + (enaddr)[5] = ((u_int8_t *)ipaddr)[3]; \ +} while (/* CONSTCOND */ 0) + +/* + * Macro to map an IPv6 multicast address to an Ethernet multicast address. + * The high-order 16 bits of the Ethernet address are statically assigned, + * and the low-order 32 bits are taken from the low end of the IPv6 address. + */ +#define ETHER_MAP_IPV6_MULTICAST(ip6addr, enaddr) \ + /* struct in6_addr *ip6addr; */ \ + /* u_int8_t enaddr[ETHER_ADDR_LEN]; */ \ +do { \ + (enaddr)[0] = 0x33; \ + (enaddr)[1] = 0x33; \ + (enaddr)[2] = ((u_int8_t *)ip6addr)[12]; \ + (enaddr)[3] = ((u_int8_t *)ip6addr)[13]; \ + (enaddr)[4] = ((u_int8_t *)ip6addr)[14]; \ + (enaddr)[5] = ((u_int8_t *)ip6addr)[15]; \ +} while (/* CONSTCOND */ 0) + +#include /* for "struct ifnet" */ + +struct ether_brport { + struct mbuf *(*eb_input)(struct ifnet *, struct mbuf *, + uint64_t, void *, struct netstack *); + void (*eb_port_take)(void *); + void (*eb_port_rele)(void *); + void *eb_port; +}; + +/* + * Structure shared between the ethernet driver modules and + * the address resolution code. For example, each ec_softc or il_softc + * begins with this structure. + */ +struct arpcom { + struct ifnet ac_if; /* network-visible interface */ + u_int8_t ac_enaddr[ETHER_ADDR_LEN]; /* ethernet hardware address */ + char ac__pad[2]; /* pad for some machines */ + LIST_HEAD(, ether_multi) ac_multiaddrs; /* list of multicast addrs */ + int ac_multicnt; /* length of ac_multiaddrs */ + int ac_multirangecnt; /* number of mcast ranges */ + + void *ac_trunkport; + const struct ether_brport *ac_brport; +}; + +extern int arpt_keep; /* arp resolved cache expire */ +extern int arpt_down; /* arp down cache expire */ + +extern u_int8_t etherbroadcastaddr[ETHER_ADDR_LEN]; +extern u_int8_t etheranyaddr[ETHER_ADDR_LEN]; +extern u_int8_t ether_ipmulticast_min[ETHER_ADDR_LEN]; +extern u_int8_t ether_ipmulticast_max[ETHER_ADDR_LEN]; + +#ifdef NFSCLIENT +extern unsigned int revarp_ifidx; +#endif /* NFSCLIENT */ + +void revarpinput(struct ifnet *, struct mbuf *, struct netstack *); +void revarprequest(struct ifnet *); +int revarpwhoarewe(struct ifnet *, struct in_addr *, struct in_addr *); +int revarpwhoami(struct in_addr *, struct ifnet *); + +void arpinit(void); +void arpinput(struct ifnet *, struct mbuf *, struct netstack *); +void arprequest(struct ifnet *, u_int32_t *, u_int32_t *, u_int8_t *); +int arpproxy(struct in_addr, unsigned int); +int arpresolve(struct ifnet *, struct rtentry *, struct mbuf *, + struct sockaddr *, u_char *); +void arp_rtrequest(struct ifnet *, int, struct rtentry *); + +void ether_fakeaddr(struct ifnet *); +int ether_addmulti(struct ifreq *, struct arpcom *); +int ether_delmulti(struct ifreq *, struct arpcom *); +int ether_multiaddr(struct sockaddr *, u_int8_t *, u_int8_t *); +void ether_ifattach(struct ifnet *); +void ether_ifdetach(struct ifnet *); +int ether_ioctl(struct ifnet *, struct arpcom *, u_long, caddr_t); +void ether_input(struct ifnet *, struct mbuf *, struct netstack *); +int ether_resolve(struct ifnet *, struct mbuf *, struct sockaddr *, + struct rtentry *, struct ether_header *); +struct mbuf * + ether_encap(struct ifnet *, struct mbuf *, struct sockaddr *, + struct rtentry *, int *); +int ether_output(struct ifnet *, struct mbuf *, struct sockaddr *, + struct rtentry *); +void ether_rtrequest(struct ifnet *, int, struct rtentry *); +char *ether_sprintf(u_char *); + +int ether_brport_isset(struct ifnet *); +void ether_brport_set(struct ifnet *, const struct ether_brport *); +void ether_brport_clr(struct ifnet *); +const struct ether_brport * + ether_brport_get(struct ifnet *); +const struct ether_brport * + ether_brport_get_locked(struct ifnet *); + +uint64_t ether_addr_to_e64(const struct ether_addr *); +void ether_e64_to_addr(struct ether_addr *, uint64_t); + +struct ether_extracted { + struct ether_header *eh; + struct ether_vlan_header *evh; + struct ip *ip4; + struct ip6_hdr *ip6; + struct tcphdr *tcp; + struct udphdr *udp; + u_int iplen; + u_int iphlen; + u_int tcphlen; + u_int paylen; +}; + +void ether_extract_headers(struct mbuf *, struct ether_extracted *); + +/* + * Ethernet multicast address structure. There is one of these for each + * multicast address or range of multicast addresses that we are supposed + * to listen to on a particular interface. They are kept in a linked list, + * rooted in the interface's arpcom structure. (This really has nothing to + * do with ARP, or with the Internet address family, but this appears to be + * the minimally-disrupting place to put it.) + */ +struct ether_multi { + u_int8_t enm_addrlo[ETHER_ADDR_LEN]; /* low or only address of range */ + u_int8_t enm_addrhi[ETHER_ADDR_LEN]; /* high or only address of range */ + struct refcnt enm_refcnt; /* no. claims to this addr/range */ + LIST_ENTRY(ether_multi) enm_list; +}; + +/* + * Structure used by macros below to remember position when stepping through + * all of the ether_multi records. + */ +struct ether_multistep { + struct ether_multi *e_enm; +}; + +/* + * Macro for looking up the ether_multi record for a given range of Ethernet + * multicast addresses connected to a given arpcom structure. If no matching + * record is found, "enm" returns NULL. + */ +#define ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm) \ + /* u_int8_t addrlo[ETHER_ADDR_LEN]; */ \ + /* u_int8_t addrhi[ETHER_ADDR_LEN]; */ \ + /* struct arpcom *ac; */ \ + /* struct ether_multi *enm; */ \ +do { \ + for ((enm) = LIST_FIRST(&(ac)->ac_multiaddrs); \ + (enm) != NULL && \ + (memcmp((enm)->enm_addrlo, (addrlo), ETHER_ADDR_LEN) != 0 ||\ + memcmp((enm)->enm_addrhi, (addrhi), ETHER_ADDR_LEN) != 0); \ + (enm) = LIST_NEXT((enm), enm_list)); \ +} while (/* CONSTCOND */ 0) + +/* + * Macro to step through all of the ether_multi records, one at a time. + * The current position is remembered in "step", which the caller must + * provide. ETHER_FIRST_MULTI(), below, must be called to initialize "step" + * and get the first record. Both macros return a NULL "enm" when there + * are no remaining records. + */ +#define ETHER_NEXT_MULTI(step, enm) \ + /* struct ether_multistep step; */ \ + /* struct ether_multi *enm; */ \ +do { \ + if (((enm) = (step).e_enm) != NULL) \ + (step).e_enm = LIST_NEXT((enm), enm_list); \ +} while (/* CONSTCOND */ 0) + +#define ETHER_FIRST_MULTI(step, ac, enm) \ + /* struct ether_multistep step; */ \ + /* struct arpcom *ac; */ \ + /* struct ether_multi *enm; */ \ +do { \ + (step).e_enm = LIST_FIRST(&(ac)->ac_multiaddrs); \ + ETHER_NEXT_MULTI((step), (enm)); \ +} while (/* CONSTCOND */ 0) + +u_int32_t ether_crc32_le_update(u_int32_t crc, const u_int8_t *, size_t); +u_int32_t ether_crc32_be_update(u_int32_t crc, const u_int8_t *, size_t); +u_int32_t ether_crc32_le(const u_int8_t *, size_t); +u_int32_t ether_crc32_be(const u_int8_t *, size_t); + +#else /* _KERNEL */ + +__BEGIN_DECLS +char *ether_ntoa(const struct ether_addr *); +struct ether_addr *ether_aton(const char *); +int ether_ntohost(char *, struct ether_addr *); +int ether_hostton(const char *, struct ether_addr *); +int ether_line(const char *, struct ether_addr *, char *); +__END_DECLS + +#endif /* _KERNEL */ +#endif /* _NETINET_IF_ETHER_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/igmp.h b/lib/libc/include/generic-openbsd/netinet/igmp.h new file mode 100644 index 000000000000..005f2602bebd --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/igmp.h @@ -0,0 +1,97 @@ +/* $OpenBSD: igmp.h,v 1.6 2003/06/02 23:28:13 millert Exp $ */ +/* $NetBSD: igmp.h,v 1.6 1995/05/31 06:08:21 mycroft Exp $ */ + +/* + * Copyright (c) 1988 Stephen Deering. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Stephen Deering of Stanford University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)igmp.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_IGMP_H_ +#define _NETINET_IGMP_H_ + +/* + * Internet Group Management Protocol (IGMP) definitions. + * + * MULTICAST 1.3 + */ + +/* + * IGMP packet format. + */ +struct igmp { + u_int8_t igmp_type; /* version & type of IGMP message */ + u_int8_t igmp_code; /* code for routing sub-messages */ + u_int16_t igmp_cksum; /* IP-style checksum */ + struct in_addr igmp_group; /* group address being reported */ +}; /* (zero for queries) */ + +#define IGMP_MINLEN 8 + +#define IGMP_HOST_MEMBERSHIP_QUERY 0x11 /* membership query */ +#define IGMP_v1_HOST_MEMBERSHIP_REPORT 0x12 /* v1 membership report */ +#define IGMP_DVMRP 0x13 /* DVMRP routing message */ +#define IGMP_PIM 0x14 /* PIM routing message */ +#define IGMP_v2_HOST_MEMBERSHIP_REPORT 0x16 /* v2 membership report */ +#define IGMP_HOST_LEAVE_MESSAGE 0x17 /* leave-group message */ +#define IGMP_MTRACE_REPLY 0x1e /* traceroute reply */ +#define IGMP_MTRACE_QUERY 0x1f /* traceroute query */ + +#define IGMP_MAX_HOST_REPORT_DELAY 10 /* max delay for response to */ + /* query (in seconds) */ + +#define IGMP_TIMER_SCALE 10 /* denominator for igmp_timer */ + +/* + * States for the IGMP v2 state table. + */ +#define IGMP_DELAYING_MEMBER 1 +#define IGMP_IDLE_MEMBER 2 +#define IGMP_LAZY_MEMBER 3 +#define IGMP_SLEEPING_MEMBER 4 +#define IGMP_AWAKENING_MEMBER 5 + +/* + * States for IGMP router version cache. + */ +#define IGMP_v1_ROUTER 1 +#define IGMP_v2_ROUTER 2 + +/* + * Revert to v2 if we haven't heard from the router in this amount of time. + */ +#define IGMP_AGE_THRESHOLD 540 + +#ifdef _KERNEL +void rti_delete(struct ifnet *); +#endif /* _KERNEL */ +#endif /* _NETINET_IGMP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/igmp_var.h b/lib/libc/include/generic-openbsd/netinet/igmp_var.h new file mode 100644 index 000000000000..06624e9aa49d --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/igmp_var.h @@ -0,0 +1,116 @@ +/* $OpenBSD: igmp_var.h,v 1.16 2025/03/02 21:28:32 bluhm Exp $ */ +/* $NetBSD: igmp_var.h,v 1.9 1996/02/13 23:41:31 christos Exp $ */ + +/* + * Copyright (c) 1988 Stephen Deering. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Stephen Deering of Stanford University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)igmp_var.h 8.1 (Berkeley) 7/19/93 + */ + +#ifndef _NETINET_IGMP_VAR_H_ +#define _NETINET_IGMP_VAR_H_ + +/* + * Internet Group Management Protocol (IGMP), + * implementation-specific definitions. + * + * Written by Steve Deering, Stanford, May 1988. + * Modified by Rosen Sharma, Stanford, Aug 1994. + * Modified by Bill Fenner, Xerox PARC, Feb 1995. + * + * MULTICAST 1.3 + */ + +struct igmpstat { + u_long igps_rcv_total; /* total IGMP messages received */ + u_long igps_rcv_tooshort; /* received with too few bytes */ + u_long igps_rcv_badsum; /* received with bad checksum */ + u_long igps_rcv_queries; /* received membership queries */ + u_long igps_rcv_badqueries; /* received invalid queries */ + u_long igps_rcv_reports; /* received membership reports */ + u_long igps_rcv_badreports; /* received invalid reports */ + u_long igps_rcv_ourreports; /* received reports for our groups */ + u_long igps_snd_reports; /* sent membership reports */ +}; + +/* + * Names for IGMP sysctl objects + */ +#define IGMPCTL_STATS 1 /* IGMP statistics */ +#define IGMPCTL_MAXID 2 + +#define IGMPCTL_NAMES { \ + { 0, 0 }, \ + { "stats", CTLTYPE_STRUCT } \ +} + +#ifdef _KERNEL + +#include + +enum igmpstat_counters { + igps_rcv_total, /* total IGMP messages received */ + igps_rcv_tooshort, /* received with too few bytes */ + igps_rcv_badsum, /* received with bad checksum */ + igps_rcv_queries, /* received membership queries */ + igps_rcv_badqueries, /* received invalid queries */ + igps_rcv_reports, /* received membership reports */ + igps_rcv_badreports, /* received invalid reports */ + igps_rcv_ourreports, /* received reports for our groups */ + igps_snd_reports, /* sent membership reports */ + igps_ncounters +}; + +extern struct cpumem *igmpcounters; + +static inline void +igmpstat_inc(enum igmpstat_counters c) +{ + counters_inc(igmpcounters, c); +} + +/* + * Macro to compute a random timer value between 1 and (IGMP_MAX_REPORTING_ + * DELAY * countdown frequency). We assume that the routine random() + * is defined somewhere (and that it returns a positive number). + */ +#define IGMP_RANDOM_DELAY(X) (arc4random_uniform(X) + 1) + +void igmp_init(void); +int igmp_input(struct mbuf **, int *, int, int, struct netstack *); +void igmp_joingroup(struct in_multi *, struct ifnet *); +void igmp_leavegroup(struct in_multi *, struct ifnet *); +void igmp_fasttimo(void); +void igmp_slowtimo(void); +int igmp_sysctl(int *, u_int, void *, size_t *, void *, size_t); +#endif /* _KERNEL */ +#endif /* _NETINET_IGMP_VAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/in.h b/lib/libc/include/generic-openbsd/netinet/in.h new file mode 100644 index 000000000000..04da1df3c992 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/in.h @@ -0,0 +1,833 @@ +/* $OpenBSD: in.h,v 1.149 2025/03/02 21:28:32 bluhm Exp $ */ +/* $NetBSD: in.h,v 1.20 1996/02/13 23:41:47 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Constants and structures defined by the internet system, + * Per RFC 790, September 1981, and numerous additions. + */ + +#ifndef _NETINET_IN_H_ +#define _NETINET_IN_H_ + +#include + +#ifndef _KERNEL +#include + +/* is pulled in by */ +#ifndef htons +#define htons(x) __htobe16(x) +#define htonl(x) __htobe32(x) +#define ntohs(x) __htobe16(x) +#define ntohl(x) __htobe32(x) +#endif + +#endif /* _KERNEL */ + +#ifndef _SA_FAMILY_T_DEFINED_ +#define _SA_FAMILY_T_DEFINED_ +typedef __sa_family_t sa_family_t; /* sockaddr address family type */ +#endif /* _SA_FAMILY_T_DEFINED_ */ + +#ifndef _IN_TYPES_DEFINED_ +#define _IN_TYPES_DEFINED_ +typedef __in_addr_t in_addr_t; /* base type for internet address */ +typedef __in_port_t in_port_t; /* IP port type */ +#endif + +/* + * Protocols + */ +#define IPPROTO_IP 0 /* dummy for IP */ +#define IPPROTO_HOPOPTS IPPROTO_IP /* Hop-by-hop option header */ +#define IPPROTO_ICMP 1 /* control message protocol */ +#define IPPROTO_IGMP 2 /* group mgmt protocol */ +#define IPPROTO_GGP 3 /* gateway^2 (deprecated) */ +#define IPPROTO_IPIP 4 /* IP inside IP */ +#define IPPROTO_IPV4 IPPROTO_IPIP /* IP inside IP */ +#define IPPROTO_TCP 6 /* tcp */ +#define IPPROTO_EGP 8 /* exterior gateway protocol */ +#define IPPROTO_PUP 12 /* pup */ +#define IPPROTO_UDP 17 /* user datagram protocol */ +#define IPPROTO_IDP 22 /* xns idp */ +#define IPPROTO_TP 29 /* tp-4 w/ class negotiation */ +#define IPPROTO_IPV6 41 /* IPv6 in IPv6 */ +#define IPPROTO_ROUTING 43 /* Routing header */ +#define IPPROTO_FRAGMENT 44 /* Fragmentation/reassembly header */ +#define IPPROTO_RSVP 46 /* resource reservation */ +#define IPPROTO_GRE 47 /* GRE encap, RFCs 1701/1702 */ +#define IPPROTO_ESP 50 /* Encap. Security Payload */ +#define IPPROTO_AH 51 /* Authentication header */ +#define IPPROTO_MOBILE 55 /* IP Mobility, RFC 2004 */ +#define IPPROTO_ICMPV6 58 /* ICMP for IPv6 */ +#define IPPROTO_NONE 59 /* No next header */ +#define IPPROTO_DSTOPTS 60 /* Destination options header */ +#define IPPROTO_EON 80 /* ISO cnlp */ +#define IPPROTO_ETHERIP 97 /* Ethernet in IPv4 */ +#define IPPROTO_ENCAP 98 /* encapsulation header */ +#define IPPROTO_PIM 103 /* Protocol indep. multicast */ +#define IPPROTO_IPCOMP 108 /* IP Payload Comp. Protocol */ +#define IPPROTO_CARP 112 /* CARP */ +#define IPPROTO_SCTP 132 /* SCTP, RFC 4960 */ +#define IPPROTO_UDPLITE 136 /* UDP-Lite, RFC 3828 */ +#define IPPROTO_MPLS 137 /* unicast MPLS packet */ +#define IPPROTO_PFSYNC 240 /* PFSYNC */ +#define IPPROTO_RAW 255 /* raw IP packet */ + +#define IPPROTO_MAX 256 + +/* Only used internally, so it can be outside the range of valid IP protocols */ +#define IPPROTO_DIVERT 258 /* Divert sockets */ + +/* + * From FreeBSD: + * + * Local port number conventions: + * + * When a user does a bind(2) or connect(2) with a port number of zero, + * a non-conflicting local port address is chosen. + * The default range is IPPORT_RESERVED through + * IPPORT_USERRESERVED, although that is settable by sysctl. + * + * A user may set the IPPROTO_IP option IP_PORTRANGE to change this + * default assignment range. + * + * The value IP_PORTRANGE_DEFAULT causes the default behavior. + * + * The value IP_PORTRANGE_HIGH changes the range of candidate port numbers + * into the "high" range. These are reserved for client outbound connections + * which do not want to be filtered by any firewalls. + * + * The value IP_PORTRANGE_LOW changes the range to the "low" are + * that is (by convention) restricted to privileged processes. This + * convention is based on "vouchsafe" principles only. It is only secure + * if you trust the remote host to restrict these ports. + * + * The default range of ports and the high range can be changed by + * sysctl(3). (net.inet.ip.port{hi}{first,last}) + * + * Changing those values has bad security implications if you are + * using a stateless firewall that is allowing packets outside of that + * range in order to allow transparent outgoing connections. + * + * Such a firewall configuration will generally depend on the use of these + * default values. If you change them, you may find your Security + * Administrator looking for you with a heavy object. + */ + +/* + * Ports < IPPORT_RESERVED are reserved for + * privileged processes (e.g. root). + * Ports > IPPORT_USERRESERVED are reserved + * for servers, not necessarily privileged. + */ +#define IPPORT_RESERVED 1024 +#define IPPORT_USERRESERVED 49151 + +/* + * Default local port range to use by setting IP_PORTRANGE_HIGH + */ +#define IPPORT_HIFIRSTAUTO 49152 +#define IPPORT_HILASTAUTO 65535 + +#ifndef _IN_ADDR_DECLARED +#define _IN_ADDR_DECLARED +/* + * IP Version 4 Internet address (a structure for historical reasons) + */ +struct in_addr { + in_addr_t s_addr; +}; +#endif /* _IN_ADDR_DECLARED */ + +/* last return value of *_input(), meaning "all job for this pkt is done". */ +#define IPPROTO_DONE 257 + +/* + * Definitions of bits in internet address integers. + * On subnets, the decomposition of addresses to host and net parts + * is done according to subnet mask, not the masks here. + * + * By byte-swapping the constants, we avoid ever having to byte-swap IP + * addresses inside the kernel. Unfortunately, user-level programs rely + * on these macros not doing byte-swapping. + */ +#ifdef _KERNEL +#define __IPADDR(x) ((u_int32_t) htonl((u_int32_t)(x))) +#else +#define __IPADDR(x) ((u_int32_t)(x)) +#endif /* _KERNEL */ + +#define IN_CLASSA(i) (((u_int32_t)(i) & __IPADDR(0x80000000)) == \ + __IPADDR(0x00000000)) +#define IN_CLASSA_NET __IPADDR(0xff000000) +#define IN_CLASSA_NSHIFT 24 +#define IN_CLASSA_HOST __IPADDR(0x00ffffff) +#define IN_CLASSA_MAX 128 + +#define IN_CLASSB(i) (((u_int32_t)(i) & __IPADDR(0xc0000000)) == \ + __IPADDR(0x80000000)) +#define IN_CLASSB_NET __IPADDR(0xffff0000) +#define IN_CLASSB_NSHIFT 16 +#define IN_CLASSB_HOST __IPADDR(0x0000ffff) +#define IN_CLASSB_MAX 65536 + +#define IN_CLASSC(i) (((u_int32_t)(i) & __IPADDR(0xe0000000)) == \ + __IPADDR(0xc0000000)) +#define IN_CLASSC_NET __IPADDR(0xffffff00) +#define IN_CLASSC_NSHIFT 8 +#define IN_CLASSC_HOST __IPADDR(0x000000ff) + +#define IN_CLASSD(i) (((u_int32_t)(i) & __IPADDR(0xf0000000)) == \ + __IPADDR(0xe0000000)) +/* These ones aren't really net and host fields, but routing needn't know. */ +#define IN_CLASSD_NET __IPADDR(0xf0000000) +#define IN_CLASSD_NSHIFT 28 +#define IN_CLASSD_HOST __IPADDR(0x0fffffff) +#define IN_MULTICAST(i) IN_CLASSD(i) + +#define IN_RFC3021_NET __IPADDR(0xfffffffe) +#define IN_RFC3021_NSHIFT 31 +#define IN_RFC3021_HOST __IPADDR(0x00000001) +#define IN_RFC3021_SUBNET(n) (((u_int32_t)(n) & IN_RFC3021_NET) == \ + IN_RFC3021_NET) + +#define IN_EXPERIMENTAL(i) (((u_int32_t)(i) & __IPADDR(0xf0000000)) == \ + __IPADDR(0xf0000000)) +#define IN_BADCLASS(i) (((u_int32_t)(i) & __IPADDR(0xf0000000)) == \ + __IPADDR(0xf0000000)) + +#define IN_LOCAL_GROUP(i) (((u_int32_t)(i) & __IPADDR(0xffffff00)) == \ + __IPADDR(0xe0000000)) + +#ifdef _KERNEL +#define IN_CLASSFULBROADCAST(i, b) \ + ((IN_CLASSC(b) && (b | IN_CLASSC_HOST) == i) || \ + (IN_CLASSB(b) && (b | IN_CLASSB_HOST) == i) || \ + (IN_CLASSA(b) && (b | IN_CLASSA_HOST) == i)) +#endif /* _KERNEL */ + +#define INADDR_ANY __IPADDR(0x00000000) +#define INADDR_LOOPBACK __IPADDR(0x7f000001) +#define INADDR_BROADCAST __IPADDR(0xffffffff) /* must be masked */ +#ifndef _KERNEL +#define INADDR_NONE __IPADDR(0xffffffff) /* -1 return */ +#endif /* _KERNEL */ + +#define INADDR_UNSPEC_GROUP __IPADDR(0xe0000000) /* 224.0.0.0 */ +#define INADDR_ALLHOSTS_GROUP __IPADDR(0xe0000001) /* 224.0.0.1 */ +#define INADDR_ALLROUTERS_GROUP __IPADDR(0xe0000002) /* 224.0.0.2 */ +#define INADDR_CARP_GROUP __IPADDR(0xe0000012) /* 224.0.0.18 */ +#define INADDR_PFSYNC_GROUP __IPADDR(0xe00000f0) /* 224.0.0.240 */ +#define INADDR_MAX_LOCAL_GROUP __IPADDR(0xe00000ff) /* 224.0.0.255 */ + +#define IN_LOOPBACKNET 127 /* official! */ + +/* + * IP Version 4 socket address. + */ +struct sockaddr_in { + u_int8_t sin_len; + sa_family_t sin_family; + in_port_t sin_port; + struct in_addr sin_addr; + int8_t sin_zero[8]; +}; + +/* + * Structure used to describe IP options. + * Used to store options internally, to pass them to a process, + * or to restore options retrieved earlier. + * The ip_dst is used for the first-hop gateway when using a source route + * (this gets put into the header proper). + */ +struct ip_opts { + struct in_addr ip_dst; /* first hop, 0 w/o src rt */ +#if defined(__cplusplus) + int8_t Ip_opts[40]; /* cannot have same name as class */ +#else + int8_t ip_opts[40]; /* actually variable in size */ +#endif /* defined(__cplusplus) */ +}; + +/* + * Options for use with [gs]etsockopt at the IP level. + * First word of comment is data type; bool is stored in int. + */ +#define IP_OPTIONS 1 /* buf/ip_opts; set/get IP options */ +#define IP_HDRINCL 2 /* int; header is included with data */ +#define IP_TOS 3 /* int; IP type of service and preced. */ +#define IP_TTL 4 /* int; IP time to live */ +#define IP_RECVOPTS 5 /* bool; receive all IP opts w/dgram */ +#define IP_RECVRETOPTS 6 /* bool; receive IP opts for response */ +#define IP_RECVDSTADDR 7 /* bool; receive IP dst addr w/dgram */ +#define IP_RETOPTS 8 /* ip_opts; set/get IP options */ +#define IP_MULTICAST_IF 9 /* in_addr; set/get IP multicast i/f */ +#define IP_MULTICAST_TTL 10 /* u_char; set/get IP multicast ttl */ +#define IP_MULTICAST_LOOP 11 /* u_char; set/get IP multicast loopback */ +#define IP_ADD_MEMBERSHIP 12 /* ip_mreq; add an IP group membership */ +#define IP_DROP_MEMBERSHIP 13 /* ip_mreq; drop an IP group membership */ +#define IP_PORTRANGE 19 /* int; range to choose for unspec port */ +#define IP_AUTH_LEVEL 20 /* int; authentication used */ +#define IP_ESP_TRANS_LEVEL 21 /* int; transport encryption */ +#define IP_ESP_NETWORK_LEVEL 22 /* int; full-packet encryption */ +#define IP_IPSEC_LOCAL_ID 23 /* buf; IPsec local ID */ +#define IP_IPSEC_REMOTE_ID 24 /* buf; IPsec remote ID */ +#define IP_IPSEC_LOCAL_CRED 25 /* buf; was: IPsec local credentials */ +#define IP_IPSEC_REMOTE_CRED 26 /* buf; was: IPsec remote credentials */ +#define IP_IPSEC_LOCAL_AUTH 27 /* buf; was: IPsec local auth material */ +#define IP_IPSEC_REMOTE_AUTH 28 /* buf; was: IPsec remote auth material */ +#define IP_IPCOMP_LEVEL 29 /* int; compression used */ +#define IP_RECVIF 30 /* bool; receive reception if w/dgram */ +#define IP_RECVTTL 31 /* bool; receive IP TTL w/dgram */ +#define IP_MINTTL 32 /* minimum TTL for packet or drop */ +#define IP_RECVDSTPORT 33 /* bool; receive IP dst port w/dgram */ +#define IP_PIPEX 34 /* bool; using PIPEX */ +#define IP_RECVRTABLE 35 /* bool; receive rdomain w/dgram */ +#define IP_IPSECFLOWINFO 36 /* bool; IPsec flow info for dgram */ +#define IP_IPDEFTTL 37 /* int; IP TTL system default */ +#define IP_SENDSRCADDR IP_RECVDSTADDR /* struct in_addr; */ + /* source address to use */ + +#define IP_RTABLE 0x1021 /* int; routing table, see SO_RTABLE */ + +#if __BSD_VISIBLE +/* + * Security levels - IPsec, not IPSO + */ + +#define IPSEC_LEVEL_BYPASS 0x00 /* Bypass policy altogether */ +#define IPSEC_LEVEL_NONE 0x00 /* Send clear, accept any */ +#define IPSEC_LEVEL_AVAIL 0x01 /* Send secure if SA available */ +#define IPSEC_LEVEL_USE 0x02 /* Send secure, accept any */ +#define IPSEC_LEVEL_REQUIRE 0x03 /* Require secure inbound, also use */ +#define IPSEC_LEVEL_UNIQUE 0x04 /* Use outbound SA that is unique */ +#define IPSEC_LEVEL_DEFAULT IPSEC_LEVEL_AVAIL + +#define IPSEC_AUTH_LEVEL_DEFAULT IPSEC_LEVEL_DEFAULT +#define IPSEC_ESP_TRANS_LEVEL_DEFAULT IPSEC_LEVEL_DEFAULT +#define IPSEC_ESP_NETWORK_LEVEL_DEFAULT IPSEC_LEVEL_DEFAULT +#define IPSEC_IPCOMP_LEVEL_DEFAULT IPSEC_LEVEL_DEFAULT + +#endif /* __BSD_VISIBLE */ + +/* + * Defaults and limits for options + */ +#define IP_DEFAULT_MULTICAST_TTL 1 /* normally limit m'casts to 1 hop */ +#define IP_DEFAULT_MULTICAST_LOOP 1 /* normally hear sends if a member */ +/* + * The imo_membership vector for each socket starts at IP_MIN_MEMBERSHIPS + * and is dynamically allocated at run-time, bounded by IP_MAX_MEMBERSHIPS, + * and is reallocated when needed, sized according to a power-of-two increment. + */ +#define IP_MIN_MEMBERSHIPS 15 +#define IP_MAX_MEMBERSHIPS 4095 + +/* + * Argument structure for IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP. + */ +struct ip_mreq { + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_interface; /* local IP address of interface */ +}; + +struct ip_mreqn { + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_address; /* local IP address of interface */ + int imr_ifindex; /* interface index */ +}; + +/* + * Argument for IP_PORTRANGE: + * - which range to search when port is unspecified at bind() or connect() + */ +#define IP_PORTRANGE_DEFAULT 0 /* default range */ +#define IP_PORTRANGE_HIGH 1 /* "high" - request firewall bypass */ +#define IP_PORTRANGE_LOW 2 /* "low" - vouchsafe security */ + +/* + * Buffer lengths for strings containing printable IP addresses + */ +#ifndef INET_ADDRSTRLEN +#define INET_ADDRSTRLEN 16 +#endif /* INET_ADDRSTRLEN */ + + +#if __BSD_VISIBLE +/* + * Definitions for inet sysctl operations. + * + * Third level is protocol number. + * Fourth level is desired variable within that protocol. + */ +#define IPPROTO_MAXID (IPPROTO_DIVERT + 1) /* don't list to IPPROTO_MAX */ + +#define CTL_IPPROTO_NAMES { \ + { "ip", CTLTYPE_NODE }, \ + { "icmp", CTLTYPE_NODE }, \ + { "igmp", CTLTYPE_NODE }, \ + { "ggp", CTLTYPE_NODE }, \ + { "ipip", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { "tcp", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { "egp", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "pup", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "udp", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "gre", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "esp", CTLTYPE_NODE }, \ + { "ah", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "etherip", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "ipcomp", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "carp", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "pfsync", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "divert", CTLTYPE_NODE }, \ +} + +/* + * Names for IP sysctl objects + */ +#define IPCTL_FORWARDING 1 /* act as router */ +#define IPCTL_SENDREDIRECTS 2 /* may send redirects when forwarding */ +#define IPCTL_DEFTTL 3 /* default TTL */ +#define IPCTL_SOURCEROUTE 5 /* may perform source routes */ +#define IPCTL_DIRECTEDBCAST 6 /* default broadcast behavior */ +#define IPCTL_IPPORT_FIRSTAUTO 7 +#define IPCTL_IPPORT_LASTAUTO 8 +#define IPCTL_IPPORT_HIFIRSTAUTO 9 +#define IPCTL_IPPORT_HILASTAUTO 10 +#define IPCTL_IPPORT_MAXQUEUE 11 +#define IPCTL_ENCDEBUG 12 +#define IPCTL_IPSEC_STATS 13 +#define IPCTL_IPSEC_EXPIRE_ACQUIRE 14 /* How long to wait for key mgmt. */ +#define IPCTL_IPSEC_EMBRYONIC_SA_TIMEOUT 15 /* new SA lifetime */ +#define IPCTL_IPSEC_REQUIRE_PFS 16 +#define IPCTL_IPSEC_SOFT_ALLOCATIONS 17 +#define IPCTL_IPSEC_ALLOCATIONS 18 +#define IPCTL_IPSEC_SOFT_BYTES 19 +#define IPCTL_IPSEC_BYTES 20 +#define IPCTL_IPSEC_TIMEOUT 21 +#define IPCTL_IPSEC_SOFT_TIMEOUT 22 +#define IPCTL_IPSEC_SOFT_FIRSTUSE 23 +#define IPCTL_IPSEC_FIRSTUSE 24 +#define IPCTL_IPSEC_ENC_ALGORITHM 25 +#define IPCTL_IPSEC_AUTH_ALGORITHM 26 +#define IPCTL_MTUDISC 27 /* allow path MTU discovery */ +#define IPCTL_MTUDISCTIMEOUT 28 /* allow path MTU discovery */ +#define IPCTL_IPSEC_IPCOMP_ALGORITHM 29 +#define IPCTL_IFQUEUE 30 +#define IPCTL_MFORWARDING 31 +#define IPCTL_MULTIPATH 32 +#define IPCTL_STATS 33 /* IP statistics */ +#define IPCTL_MRTPROTO 34 /* type of multicast */ +#define IPCTL_MRTSTATS 35 +#define IPCTL_ARPQUEUED 36 +#define IPCTL_MRTMFC 37 +#define IPCTL_MRTVIF 38 +#define IPCTL_ARPTIMEOUT 39 +#define IPCTL_ARPDOWN 40 +#define IPCTL_ARPQUEUE 41 +#define IPCTL_MAXID 42 + +#define IPCTL_NAMES { \ + { 0, 0 }, \ + { "forwarding", CTLTYPE_INT }, \ + { "redirect", CTLTYPE_INT }, \ + { "ttl", CTLTYPE_INT }, \ + /* { "mtu", CTLTYPE_INT }, */ { 0, 0 }, \ + { "sourceroute", CTLTYPE_INT }, \ + { "directed-broadcast", CTLTYPE_INT }, \ + { "portfirst", CTLTYPE_INT }, \ + { "portlast", CTLTYPE_INT }, \ + { "porthifirst", CTLTYPE_INT }, \ + { "porthilast", CTLTYPE_INT }, \ + { "maxqueue", CTLTYPE_INT }, \ + { "encdebug", CTLTYPE_INT }, \ + { 0, 0 /* ipsecstat */ }, \ + { "ipsec-expire-acquire", CTLTYPE_INT }, \ + { "ipsec-invalid-life", CTLTYPE_INT }, \ + { "ipsec-pfs", CTLTYPE_INT }, \ + { "ipsec-soft-allocs", CTLTYPE_INT }, \ + { "ipsec-allocs", CTLTYPE_INT }, \ + { "ipsec-soft-bytes", CTLTYPE_INT }, \ + { "ipsec-bytes", CTLTYPE_INT }, \ + { "ipsec-timeout", CTLTYPE_INT }, \ + { "ipsec-soft-timeout", CTLTYPE_INT }, \ + { "ipsec-soft-firstuse", CTLTYPE_INT }, \ + { "ipsec-firstuse", CTLTYPE_INT }, \ + { "ipsec-enc-alg", CTLTYPE_STRING }, \ + { "ipsec-auth-alg", CTLTYPE_STRING }, \ + { "mtudisc", CTLTYPE_INT }, \ + { "mtudisctimeout", CTLTYPE_INT }, \ + { "ipsec-comp-alg", CTLTYPE_STRING }, \ + { "ifq", CTLTYPE_NODE }, \ + { "mforwarding", CTLTYPE_INT }, \ + { "multipath", CTLTYPE_INT }, \ + { "stats", CTLTYPE_STRUCT }, \ + { "mrtproto", CTLTYPE_INT }, \ + { "mrtstats", CTLTYPE_STRUCT }, \ + { "arpqueued", CTLTYPE_INT }, \ + { "mrtmfc", CTLTYPE_STRUCT }, \ + { "mrtvif", CTLTYPE_STRUCT }, \ + { "arptimeout", CTLTYPE_INT }, \ + { "arpdown", CTLTYPE_INT }, \ + { "arpq", CTLTYPE_NODE }, \ +} + +#endif /* __BSD_VISIBLE */ + +/* INET6 stuff */ +#define __KAME_NETINET_IN_H_INCLUDED_ +#include +#undef __KAME_NETINET_IN_H_INCLUDED_ + +#ifndef _KERNEL +#if __BSD_VISIBLE +__BEGIN_DECLS +int bindresvport(int, struct sockaddr_in *); +struct sockaddr; +int bindresvport_sa(int, struct sockaddr *); +__END_DECLS +#endif /* __BSD_VISIBLE */ +#endif /* !_KERNEL */ + +#ifdef _KERNEL +extern const u_char inetctlerrmap[]; +extern const struct in_addr zeroin_addr; + +struct mbuf; +struct sockaddr; +struct sockaddr_in; +struct ifaddr; +struct in_ifaddr; +struct route; +struct netstack; + +void ipv4_input(struct ifnet *, struct mbuf *, struct netstack *); +struct mbuf * + ipv4_check(struct ifnet *, struct mbuf *); + +int in_broadcast(struct in_addr, u_int); +int in_canforward(struct in_addr); +int in_cksum(struct mbuf *, int); +int in4_cksum(struct mbuf *, u_int8_t, int, int); +void in_hdr_cksum_out(struct mbuf *, struct ifnet *); +void in_proto_cksum_out(struct mbuf *, struct ifnet *); +int in_ifcap_cksum(struct mbuf *, struct ifnet *, int); +void in_ifdetach(struct ifnet *); +int in_mask2len(struct in_addr *); +void in_len2mask(struct in_addr *, int); +int in_nam2sin(const struct mbuf *, struct sockaddr_in **); +int in_sa2sin(struct sockaddr *, struct sockaddr_in **); + +char *inet_ntoa(struct in_addr); +int inet_nat64(int, const void *, void *, const void *, u_int8_t); +int inet_nat46(int, const void *, void *, const void *, u_int8_t); + +const char *inet_ntop(int, const void *, char *, socklen_t); +const char *sockaddr_ntop(struct sockaddr *, char *, size_t); + +#define in_hosteq(s,t) ((s).s_addr == (t).s_addr) +#define in_nullhost(x) ((x).s_addr == INADDR_ANY) + +/* + * Convert between address family specific and general structs. + * Inline functions check the source type and are stricter than + * casts or defines. + */ + +static inline struct sockaddr_in * +satosin(struct sockaddr *sa) +{ + return ((struct sockaddr_in *)(sa)); +} + +static inline const struct sockaddr_in * +satosin_const(const struct sockaddr *sa) +{ + return ((const struct sockaddr_in *)(sa)); +} + +static inline struct sockaddr * +sintosa(struct sockaddr_in *sin) +{ + return ((struct sockaddr *)(sin)); +} + +static inline struct in_ifaddr * +ifatoia(struct ifaddr *ifa) +{ + return ((struct in_ifaddr *)(ifa)); +} +#endif /* _KERNEL */ +#endif /* _NETINET_IN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/in_pcb.h b/lib/libc/include/generic-openbsd/netinet/in_pcb.h new file mode 100644 index 000000000000..8bf9271b7441 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/in_pcb.h @@ -0,0 +1,383 @@ +/* $OpenBSD: in_pcb.h,v 1.171 2025/07/14 09:01:52 jsg Exp $ */ +/* $NetBSD: in_pcb.h,v 1.14 1996/02/13 23:42:00 christos Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)in_pcb.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_IN_PCB_H_ +#define _NETINET_IN_PCB_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * Locks used to protect struct members in this file: + * I immutable after creation + * N net lock + * t inpt_mtx pcb table mutex + * L pf_inp_mtx link pf to inp mutex + * s so_lock socket rwlock + */ + +/* + * The pcb table mutex guarantees that all inpcb are consistent and + * that bind(2) and connect(2) create unique combinations of + * laddr/faddr/lport/fport/rtableid. This mutex is used to protect + * both address consistency and inpcb lookup during protocol input. + * All writes to inp_[lf]addr take table mutex. A per socket lock is + * needed, so that socket layer input have a consistent view at these + * values. + * + * In soconnect() and sosend() a per pcb mutex cannot be used. They + * eventually call IP output which takes pf lock which is a sleeping lock. + * Also connect(2) does a route lookup for source selection. There + * route resolve happens, which creates a route, which sends a route + * message, which needs route lock, which is a rw-lock. + * + * On the other hand a mutex should be used in protocol input. It + * does not make sense to do a process switch per packet. Better spin + * until the packet can be processed. + * + * So there are three locks. Table mutex is for writing inp_[lf]addr/port + * and lookup, socket rw-lock to separate sockets in system calls, and + * socket buffer mutex to protect socket receive buffer. Changing + * inp_[lf]addr/port takes both per socket rw-lock and global table mutex. + * Protocol input only reads inp_[lf]addr/port during lookup and is safe. + */ + +struct pf_state_key; + +union inpaddru { + struct in_addr iau_addr; + struct in6_addr iau_addr6; +}; + +/* + * Common structure pcb for internet protocol implementation. + * Here are stored pointers to local and foreign host table + * entries, local and foreign socket numbers, and pointers + * up (to a socket structure) and down (to a protocol-specific) + * control block. + */ +struct inpcb { + struct inpcbtable *inp_table; /* [I] inet queue/hash table */ + TAILQ_ENTRY(inpcb) inp_queue; /* [t] inet PCB queue */ + /* keep fields above in sync with struct inpcb_iterator */ + LIST_ENTRY(inpcb) inp_hash; /* [t] local and foreign hash */ + LIST_ENTRY(inpcb) inp_lhash; /* [t] local port hash */ + union inpaddru inp_faddru; /* [t] Foreign address. */ + union inpaddru inp_laddru; /* [t] Local address. */ +#define inp_faddr inp_faddru.iau_addr +#define inp_faddr6 inp_faddru.iau_addr6 +#define inp_laddr inp_laddru.iau_addr +#define inp_laddr6 inp_laddru.iau_addr6 + u_int16_t inp_fport; /* [t] foreign port */ + u_int16_t inp_lport; /* [t] local port */ + struct socket *inp_socket; /* [I] back pointer to socket */ + caddr_t inp_ppcb; /* [s] pointer to per-protocol pcb */ + struct route inp_route; /* [s] cached route */ + struct refcnt inp_refcnt; /* refcount PCB, delay memory free */ + int inp_flags; /* generic IP/datagram flags */ + union { /* Header prototype. */ + struct ip hu_ip; + struct ip6_hdr hu_ipv6; + } inp_hu; +#define inp_ip inp_hu.hu_ip +#define inp_ipv6 inp_hu.hu_ipv6 + union { + struct mbuf *inp_options; /* IPv4 options */ + struct ip6_pktopts *inp_outputopts6; /* IPv6 options */ + }; + int inp_hops; + union { + struct ip_moptions *mou_mo; + struct ip6_moptions *mou_mo6; + } inp_mou; +#define inp_moptions inp_mou.mou_mo /* [N] IPv4 multicast options */ +#define inp_moptions6 inp_mou.mou_mo6 /* [N] IPv6 multicast options */ + struct ipsec_level inp_seclevel; /* [N] IPsec level of socket */ + u_char inp_ip_minttl; /* minimum TTL or drop */ +#define inp_ip6_minhlim inp_ip_minttl /* minimum Hop Limit or drop */ +#define inp_flowinfo inp_hu.hu_ipv6.ip6_flow + + int inp_cksum6; + struct icmp6_filter *inp_icmp6filt; + struct pf_state_key *inp_pf_sk; /* [L] */ + struct mbuf *(*inp_upcall)(void *, struct mbuf *, + struct ip *, struct ip6_hdr *, void *, int, struct netstack *); + void *inp_upcall_arg; + u_int inp_rtableid; /* [t] */ + int inp_pipex; /* pipex indication */ + uint16_t inp_flowid; /* [s] */ +}; + +LIST_HEAD(inpcbhead, inpcb); + +struct inpcb_iterator { + struct inpcbtable *inp_table; /* [I] always NULL */ + TAILQ_ENTRY(inpcb) inp_queue; /* [t] inet PCB queue */ + /* keep fields above in sync with struct inpcb */ +}; + +static inline int +in_pcb_is_iterator(struct inpcb *inp) +{ + return (inp->inp_table == NULL ? 1 : 0); +} + +struct inpcbtable { + struct mutex inpt_mtx; /* protect queue and hash */ + TAILQ_HEAD(inpthead, inpcb) inpt_queue; /* [t] inet PCB queue */ + struct inpcbhead *inpt_hashtbl; /* [t] local and foreign hash */ + struct inpcbhead *inpt_lhashtbl; /* [t] local port hash */ + SIPHASH_KEY inpt_key, inpt_lkey; /* [I] secrets for hashes */ + u_long inpt_mask, inpt_lmask; /* [t] hash masks */ + int inpt_count, inpt_size; /* [t] queue count, hash size */ +}; + +/* flags in inp_flags: */ +#define INP_RECVOPTS 0x001 /* receive incoming IP options */ +#define INP_RECVRETOPTS 0x002 /* receive IP options for reply */ +#define INP_RECVDSTADDR 0x004 /* receive IP dst address */ + +#define INP_RXDSTOPTS INP_RECVOPTS +#define INP_RXHOPOPTS INP_RECVRETOPTS +#define INP_RXINFO INP_RECVDSTADDR +#define INP_RXSRCRT 0x010 +#define INP_HOPLIMIT 0x020 + +#define INP_HDRINCL 0x008 /* user supplies entire IP header */ +#define INP_HIGHPORT 0x010 /* user wants "high" port binding */ +#define INP_LOWPORT 0x020 /* user wants "low" port binding */ +#define INP_RECVIF 0x080 /* receive incoming interface */ +#define INP_RECVTTL 0x040 /* receive incoming IP TTL */ +#define INP_RECVDSTPORT 0x200 /* receive IP dst addr before rdr */ +#define INP_RECVRTABLE 0x400 /* receive routing table */ +#define INP_IPSECFLOWINFO 0x800 /* receive IPsec flow info */ + +#define INP_CONTROLOPTS (INP_RECVOPTS|INP_RECVRETOPTS|INP_RECVDSTADDR| \ + INP_RXSRCRT|INP_HOPLIMIT|INP_RECVIF|INP_RECVTTL|INP_RECVDSTPORT| \ + INP_RECVRTABLE) + +/* + * These flags' values should be determined by either the transport + * protocol at PRU_BIND, PRU_LISTEN, PRU_CONNECT, etc, or by in_pcb*(). + */ +#define INP_IPV6 0x100 /* socket, proto, domain, family is PF_INET6 */ + +/* + * Flags in inp_flags for IPV6 + */ +#define IN6P_HIGHPORT INP_HIGHPORT /* user wants "high" port */ +#define IN6P_LOWPORT INP_LOWPORT /* user wants "low" port */ +#define IN6P_RECVDSTPORT INP_RECVDSTPORT /* receive IP dst addr before rdr */ +#define IN6P_PKTINFO 0x010000 /* receive IP6 dst and I/F */ +#define IN6P_HOPLIMIT 0x020000 /* receive hoplimit */ +#define IN6P_HOPOPTS 0x040000 /* receive hop-by-hop options */ +#define IN6P_DSTOPTS 0x080000 /* receive dst options after rthdr */ +#define IN6P_RTHDR 0x100000 /* receive routing header */ +#define IN6P_TCLASS 0x400000 /* receive traffic class value */ +#define IN6P_AUTOFLOWLABEL 0x800000 /* attach flowlabel automatically */ + +#define IN6P_ANONPORT 0x4000000 /* port chosen for user */ +#define IN6P_RFC2292 0x40000000 /* used RFC2292 API on the socket */ +#define IN6P_MTU 0x80000000 /* receive path MTU */ + +#define IN6P_MINMTU 0x20000000 /* use minimum MTU */ + +#define IN6P_CONTROLOPTS (IN6P_PKTINFO|IN6P_HOPLIMIT|IN6P_HOPOPTS|\ + IN6P_DSTOPTS|IN6P_RTHDR|\ + IN6P_TCLASS|IN6P_AUTOFLOWLABEL|IN6P_RFC2292|\ + IN6P_MTU|IN6P_RECVDSTPORT) + +#define INPLOOKUP_WILDCARD 1 +#define INPLOOKUP_SETLOCAL 2 +#define INPLOOKUP_IPV6 4 + +#define sotoinpcb(so) ((struct inpcb *)(so)->so_pcb) + +/* macros for handling bitmap of ports not to allocate dynamically */ +#define DP_MAPBITS (sizeof(u_int32_t) * NBBY) +#define DP_MAPSIZE (howmany(65536, DP_MAPBITS)) +#define DP_SET(m, p) ((m)[(p) / DP_MAPBITS] |= (1U << ((p) % DP_MAPBITS))) +#define DP_CLR(m, p) ((m)[(p) / DP_MAPBITS] &= ~(1U << ((p) % DP_MAPBITS))) +#define DP_ISSET(m, p) ((m)[(p) / DP_MAPBITS] & (1U << ((p) % DP_MAPBITS))) + +/* default values for baddynamicports [see ip_init()] */ +#define DEFBADDYNAMICPORTS_TCP { \ + 587, 749, 750, 751, 853, 871, 2049, \ + 6000, 6001, 6002, 6003, 6004, 6005, 6006, 6007, 6008, 6009, 6010, \ + 0 } +#define DEFBADDYNAMICPORTS_UDP { 623, 664, 749, 750, 751, 2049, \ + 3784, 3785, 7784, /* BFD/S-BFD ports */ \ + 0 } + +#define DEFROOTONLYPORTS_TCP { \ + 2049, \ + 0 } +#define DEFROOTONLYPORTS_UDP { \ + 2049, \ + 0 } + +struct baddynamicports { + u_int32_t tcp[DP_MAPSIZE]; + u_int32_t udp[DP_MAPSIZE]; +}; + +#ifdef _KERNEL + +#define IN_PCBLOCK_HOLD 1 +#define IN_PCBLOCK_GRAB 2 + +extern struct inpcbtable rawcbtable, rawin6pcbtable; +extern struct baddynamicports baddynamicports; +extern struct baddynamicports rootonlyports; +extern int in_pcbnotifymiss; + +void in_init(void); +void in_losing(struct inpcb *); +int in_pcballoc(struct socket *, struct inpcbtable *, int); +int in_pcbbind_locked(struct inpcb *, struct mbuf *, const void *, + struct proc *); +int in_pcbbind(struct inpcb *, struct mbuf *, struct proc *); +int in_pcbaddrisavail(const struct inpcb *, struct sockaddr_in *, int, + struct proc *); +int in_pcbconnect(struct inpcb *, struct mbuf *); +void in_pcbdetach(struct inpcb *); +struct socket * + in_pcbsolock(struct inpcb *); +void in_pcbsounlock(struct inpcb *, struct socket *); +struct inpcb * + in_pcbref(struct inpcb *); +void in_pcbunref(struct inpcb *); +void in_pcbdisconnect(struct inpcb *); +struct inpcb * + in_pcb_iterator(struct inpcbtable *, struct inpcb *, + struct inpcb_iterator *); +void in_pcb_iterator_abort(struct inpcbtable *, struct inpcb *, + struct inpcb_iterator *); +struct inpcb * + in_pcblookup(struct inpcbtable *, struct in_addr, u_int, + struct in_addr, u_int, u_int); +struct inpcb * + in_pcblookup_listen(struct inpcbtable *, struct in_addr, u_int, + struct mbuf *, u_int); +#ifdef INET6 +uint64_t in6_pcbhash(struct inpcbtable *, u_int, const struct in6_addr *, + u_short, const struct in6_addr *, u_short); +struct inpcb * + in6_pcblookup(struct inpcbtable *, const struct in6_addr *, + u_int, const struct in6_addr *, u_int, u_int); +struct inpcb * + in6_pcblookup_listen(struct inpcbtable *, struct in6_addr *, u_int, + struct mbuf *, u_int); +int in6_pcbaddrisavail_lock(const struct inpcb *, struct sockaddr_in6 *, + int, struct proc *, int); +int in6_pcbaddrisavail(const struct inpcb *, struct sockaddr_in6 *, int, + struct proc *); +int in6_pcbconnect(struct inpcb *, struct mbuf *); +void in6_setsockaddr(struct inpcb *, struct mbuf *); +void in6_setpeeraddr(struct inpcb *, struct mbuf *); +int in6_sockaddr(struct socket *, struct mbuf *); +int in6_peeraddr(struct socket *, struct mbuf *); +#endif /* INET6 */ +void in_pcbinit(struct inpcbtable *, int); +struct inpcb * + in_pcblookup_local_lock(struct inpcbtable *, const void *, u_int, int, + u_int, int); +void in_pcbnotifyall(struct inpcbtable *, const struct sockaddr_in *, + u_int, int, void (*)(struct inpcb *, int)); +void in_pcbrehash(struct inpcb *); +void in_pcbrtchange(struct inpcb *, int); +void in_setpeeraddr(struct inpcb *, struct mbuf *); +void in_setsockaddr(struct inpcb *, struct mbuf *); +int in_sockaddr(struct socket *, struct mbuf *); +int in_peeraddr(struct socket *, struct mbuf *); +int in_baddynamic(u_int16_t, u_int16_t); +int in_rootonly(u_int16_t, u_int16_t); +int in_pcbselsrc(struct in_addr *, const struct sockaddr_in *, + struct inpcb *); +struct rtentry * + in_pcbrtentry(struct inpcb *); + +/* INET6 stuff */ +struct rtentry * + in6_pcbrtentry(struct inpcb *); +void in6_pcbnotify(struct inpcbtable *, const struct sockaddr_in6 *, + u_int, const struct sockaddr_in6 *, u_int, u_int, int, void *, + void (*)(struct inpcb *, int)); +int in6_selecthlim(const struct inpcb *); +int in_pcbset_rtableid(struct inpcb *, u_int); +int in_pcbset_addr(struct inpcb *, const struct sockaddr *, + const struct sockaddr *, u_int); +int in6_pcbset_addr(struct inpcb *, const struct sockaddr_in6 *, + const struct sockaddr_in6 *, u_int); +void in_pcbunset_faddr(struct inpcb *); +void in_pcbunset_laddr(struct inpcb *); + +#endif /* _KERNEL */ +#endif /* _NETINET_IN_PCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/in_systm.h b/lib/libc/include/generic-openbsd/netinet/in_systm.h new file mode 100644 index 000000000000..0cab0c1e907f --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/in_systm.h @@ -0,0 +1,47 @@ +/* $OpenBSD: in_systm.h,v 1.7 2014/07/13 13:57:56 mpi Exp $ */ +/* $NetBSD: in_systm.h,v 1.8 1995/04/13 06:29:22 cgd Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)in_systm.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_IN_SYSTM_H_ +#define _NETINET_IN_SYSTM_H_ + +/* network byte order */ +typedef u_int16_t n_short; +typedef u_int32_t n_long; +typedef u_int32_t n_time; /* ms since 00:00 GMT */ + +#ifdef _KERNEL +u_int32_t iptime(void); +#endif /* _KERNEL */ + +#endif /* _NETINET_IN_SYSTM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/in_var.h b/lib/libc/include/generic-openbsd/netinet/in_var.h new file mode 100644 index 000000000000..9a419c296b3a --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/in_var.h @@ -0,0 +1,166 @@ +/* $OpenBSD: in_var.h,v 1.41 2018/10/18 15:23:04 cheloha Exp $ */ +/* $NetBSD: in_var.h,v 1.16 1996/02/13 23:42:15 christos Exp $ */ + +/* + * Copyright (c) 1985, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)in_var.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_IN_VAR_H_ +#define _NETINET_IN_VAR_H_ + +#include + +#ifdef _KERNEL +/* + * Interface address, Internet version. One of these structures + * is allocated for each interface with an Internet address. + * The ifaddr structure contains the protocol-independent part + * of the structure and is assumed to be first. + */ +struct in_ifaddr { + struct ifaddr ia_ifa; /* protocol-independent info */ +#define ia_ifp ia_ifa.ifa_ifp +#define ia_flags ia_ifa.ifa_flags + /* ia_net{,mask} in host order */ + u_int32_t ia_net; /* network number of interface */ + u_int32_t ia_netmask; /* mask of net part */ + TAILQ_ENTRY(in_ifaddr) ia_list; /* list of internet addresses */ + struct sockaddr_in ia_addr; /* reserve space for interface name */ + struct sockaddr_in ia_dstaddr; /* reserve space for broadcast addr */ +#define ia_broadaddr ia_dstaddr + struct sockaddr_in ia_sockmask; /* reserve space for general netmask */ + struct in_multi *ia_allhosts; /* multicast address record for + the allhosts multicast group */ +}; +#endif + +struct in_aliasreq { + char ifra_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + union { + struct sockaddr_in ifrau_addr; + int ifrau_align; + } ifra_ifrau; +#ifndef ifra_addr +#define ifra_addr ifra_ifrau.ifrau_addr +#endif + struct sockaddr_in ifra_dstaddr; +#define ifra_broadaddr ifra_dstaddr + struct sockaddr_in ifra_mask; +}; + + +#ifdef _KERNEL +/* + * Macro for finding the internet address structure (in_ifaddr) corresponding + * to a given interface (ifnet structure). + */ +#define IFP_TO_IA(ifp, ia) \ + /* struct ifnet *ifp; */ \ + /* struct in_ifaddr *ia; */ \ +do { \ + struct ifaddr *ifa; \ + NET_ASSERT_LOCKED(); \ + TAILQ_FOREACH(ifa, &(ifp)->if_addrlist, ifa_list) { \ + if (ifa->ifa_addr->sa_family == AF_INET) \ + break; \ + } \ + (ia) = ifatoia(ifa); \ +} while (/* CONSTCOND */ 0) +#endif + +/* + * Per-interface router version information. + */ +struct router_info { + unsigned int rti_ifidx; + int rti_type; /* type of router on this interface */ + int rti_age; /* time since last v1 query */ + LIST_ENTRY(router_info) rti_list; +}; + +#ifdef _KERNEL +/* + * Internet multicast address structure. There is one of these for each IP + * multicast group to which this host belongs on a given network interface. + */ +struct in_multi { + struct ifmaddr inm_ifma; /* Protocol-independent info */ +#define inm_refcnt inm_ifma.ifma_refcnt +#define inm_ifidx inm_ifma.ifma_ifidx + + struct sockaddr_in inm_sin; /* IPv4 multicast address */ +#define inm_addr inm_sin.sin_addr + + u_int inm_state; /* state of membership */ + u_int inm_timer; /* IGMP membership report timer */ + + struct router_info *inm_rti; /* router version info */ +}; + +static __inline struct in_multi * +ifmatoinm(struct ifmaddr *ifma) +{ + return ((struct in_multi *)(ifma)); +} + +/* + * Macro for looking up the in_multi record for a given IP multicast + * address on a given interface. If no matching record is found, "inm" + * returns NULL. + */ +#define IN_LOOKUP_MULTI(addr, ifp, inm) \ + /* struct in_addr addr; */ \ + /* struct ifnet *ifp; */ \ + /* struct in_multi *inm; */ \ +do { \ + struct ifmaddr *ifma; \ + \ + (inm) = NULL; \ + NET_ASSERT_LOCKED(); \ + TAILQ_FOREACH(ifma, &(ifp)->if_maddrlist, ifma_list) \ + if (ifma->ifma_addr->sa_family == AF_INET && \ + ifmatoinm(ifma)->inm_addr.s_addr == (addr).s_addr) {\ + (inm) = ifmatoinm(ifma); \ + break; \ + } \ +} while (/* CONSTCOND */ 0) + +int in_ifinit(struct ifnet *, + struct in_ifaddr *, struct sockaddr_in *, int); +struct in_multi *in_addmulti(struct in_addr *, struct ifnet *); +void in_delmulti(struct in_multi *); +int in_hasmulti(struct in_addr *, struct ifnet *); +void in_ifscrub(struct ifnet *, struct in_ifaddr *); +int in_control(struct socket *, u_long, caddr_t, struct ifnet *); +int in_ioctl(u_long, caddr_t, struct ifnet *, int); +void in_prefixlen2mask(struct in_addr *, int); +#endif + +#endif /* _NETINET_IN_VAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/ip.h b/lib/libc/include/generic-openbsd/netinet/ip.h new file mode 100644 index 000000000000..d4668ac42430 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/ip.h @@ -0,0 +1,233 @@ +/* $OpenBSD: ip.h,v 1.20 2021/12/14 23:47:36 dtucker Exp $ */ +/* $NetBSD: ip.h,v 1.9 1995/05/15 01:22:44 cgd Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ip.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_IP_H_ +#define _NETINET_IP_H_ + +/* + * Definitions for internet protocol version 4. + * Per RFC 791, September 1981. + */ +#define IPVERSION 4 + +/* + * Structure of an internet header, naked of options. + */ +struct ip { +#if _BYTE_ORDER == _LITTLE_ENDIAN + u_int ip_hl:4, /* header length */ + ip_v:4; /* version */ +#endif +#if _BYTE_ORDER == _BIG_ENDIAN + u_int ip_v:4, /* version */ + ip_hl:4; /* header length */ +#endif + u_int8_t ip_tos; /* type of service */ + u_int16_t ip_len; /* total length */ + u_int16_t ip_id; /* identification */ + u_int16_t ip_off; /* fragment offset field */ +#define IP_RF 0x8000 /* reserved fragment flag */ +#define IP_DF 0x4000 /* dont fragment flag */ +#define IP_MF 0x2000 /* more fragments flag */ +#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ + u_int8_t ip_ttl; /* time to live */ + u_int8_t ip_p; /* protocol */ + u_int16_t ip_sum; /* checksum */ + struct in_addr ip_src, ip_dst; /* source and dest address */ +}; + +#define IP_MAXPACKET 65535 /* maximum packet size */ + +/* + * Definitions for IP type of service (ip_tos) + */ +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_RELIABILITY 0x04 +/* IPTOS_LOWCOST 0x02 XXX */ +#if 1 +/* ECN RFC3168 obsoletes RFC2481, and these will be deprecated soon. */ +#define IPTOS_CE 0x01 /* congestion experienced */ +#define IPTOS_ECT 0x02 /* ECN-capable transport */ +#endif + +/* + * Definitions for IP precedence (also in ip_tos) (hopefully unused) + */ +#define IPTOS_PREC_NETCONTROL 0xe0 +#define IPTOS_PREC_INTERNETCONTROL 0xc0 +#define IPTOS_PREC_CRITIC_ECP 0xa0 +#define IPTOS_PREC_FLASHOVERRIDE 0x80 +#define IPTOS_PREC_FLASH 0x60 +#define IPTOS_PREC_IMMEDIATE 0x40 +#define IPTOS_PREC_PRIORITY 0x20 +#define IPTOS_PREC_ROUTINE 0x00 + +/* + * Definitions for DiffServ Codepoints as per RFCs 2474, 3246, 4594 & 8622. + * These are the 6 most significant bits as they appear on the wire, so the + * two least significant bits must be zero. + */ +#define IPTOS_DSCP_CS0 0x00 +#define IPTOS_DSCP_LE 0x04 +#define IPTOS_DSCP_CS1 0x20 +#define IPTOS_DSCP_AF11 0x28 +#define IPTOS_DSCP_AF12 0x30 +#define IPTOS_DSCP_AF13 0x38 +#define IPTOS_DSCP_CS2 0x40 +#define IPTOS_DSCP_AF21 0x48 +#define IPTOS_DSCP_AF22 0x50 +#define IPTOS_DSCP_AF23 0x58 +#define IPTOS_DSCP_CS3 0x60 +#define IPTOS_DSCP_AF31 0x68 +#define IPTOS_DSCP_AF32 0x70 +#define IPTOS_DSCP_AF33 0x78 +#define IPTOS_DSCP_CS4 0x80 +#define IPTOS_DSCP_AF41 0x88 +#define IPTOS_DSCP_AF42 0x90 +#define IPTOS_DSCP_AF43 0x98 +#define IPTOS_DSCP_CS5 0xa0 +#define IPTOS_DSCP_EF 0xb8 +#define IPTOS_DSCP_CS6 0xc0 +#define IPTOS_DSCP_CS7 0xe0 + +/* + * ECN (Explicit Congestion Notification) codepoints in RFC3168 + * mapped to the lower 2 bits of the TOS field. + */ +#define IPTOS_ECN_NOTECT 0x00 /* not-ECT */ +#define IPTOS_ECN_ECT1 0x01 /* ECN-capable transport (1) */ +#define IPTOS_ECN_ECT0 0x02 /* ECN-capable transport (0) */ +#define IPTOS_ECN_CE 0x03 /* congestion experienced */ +#define IPTOS_ECN_MASK 0x03 /* ECN field mask */ + +/* + * Definitions for options. + */ +#define IPOPT_COPIED(o) ((o)&0x80) +#define IPOPT_CLASS(o) ((o)&0x60) +#define IPOPT_NUMBER(o) ((o)&0x1f) + +#define IPOPT_CONTROL 0x00 +#define IPOPT_RESERVED1 0x20 +#define IPOPT_DEBMEAS 0x40 +#define IPOPT_RESERVED2 0x60 + +#define IPOPT_EOL 0 /* end of option list */ +#define IPOPT_NOP 1 /* no operation */ + +#define IPOPT_RR 7 /* record packet route */ +#define IPOPT_TS 68 /* timestamp */ +#define IPOPT_SECURITY 130 /* provide s,c,h,tcc */ +#define IPOPT_LSRR 131 /* loose source route */ +#define IPOPT_SATID 136 /* satnet id */ +#define IPOPT_SSRR 137 /* strict source route */ +#define IPOPT_RA 148 /* router alert */ + +/* + * Offsets to fields in options other than EOL and NOP. + */ +#define IPOPT_OPTVAL 0 /* option ID */ +#define IPOPT_OLEN 1 /* option length */ +#define IPOPT_OFFSET 2 /* offset within option */ +#define IPOPT_MINOFF 4 /* min value of above */ + +/* + * Time stamp option structure. + */ +struct ip_timestamp { + u_int8_t ipt_code; /* IPOPT_TS */ + u_int8_t ipt_len; /* size of structure (variable) */ + u_int8_t ipt_ptr; /* index of current entry */ +#if _BYTE_ORDER == _LITTLE_ENDIAN + u_int ipt_flg:4, /* flags, see below */ + ipt_oflw:4; /* overflow counter */ +#endif +#if _BYTE_ORDER == _BIG_ENDIAN + u_int ipt_oflw:4, /* overflow counter */ + ipt_flg:4; /* flags, see below */ +#endif + union ipt_timestamp { + u_int32_t ipt_time[1]; + struct ipt_ta { + struct in_addr ipt_addr; + u_int32_t ipt_time; + } ipt_ta[1]; + } ipt_timestamp; +}; + +/* flag bits for ipt_flg */ +#define IPOPT_TS_TSONLY 0 /* timestamps only */ +#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */ +#define IPOPT_TS_PRESPEC 3 /* specified modules only */ + +/* bits for security (not byte swapped) */ +#define IPOPT_SECUR_UNCLASS 0x0000 +#define IPOPT_SECUR_CONFID 0xf135 +#define IPOPT_SECUR_EFTO 0x789a +#define IPOPT_SECUR_MMMM 0xbc4d +#define IPOPT_SECUR_RESTR 0xaf13 +#define IPOPT_SECUR_SECRET 0xd788 +#define IPOPT_SECUR_TOPSECRET 0x6bc5 + +/* + * Internet implementation parameters. + */ +#define MAXTTL 255 /* maximum time to live (seconds) */ +#define IPDEFTTL 64 /* default ttl, from RFC 1340 */ +#define IPFRAGTTL 60 /* time to live for frags, slowhz */ +#define IPTTLDEC 1 /* subtracted when forwarding */ + +#define IP_MSS 576 /* default maximum segment size */ + +#ifdef _KERNEL + +/* Maximum length for IP protocol queues */ +#define IPQ_MAXLEN 2048 + +/* + * This is the real IPv4 pseudo header, used for computing the TCP and UDP + * checksums. For the Internet checksum, struct ipovly can be used instead. + * For stronger checksums, the real thing must be used. + */ +struct ippseudo { + struct in_addr ippseudo_src; /* source internet address */ + struct in_addr ippseudo_dst; /* destination internet address */ + u_int8_t ippseudo_pad; /* pad, must be zero */ + u_int8_t ippseudo_p; /* protocol */ + u_int16_t ippseudo_len; /* protocol length */ +}; +#endif /* _KERNEL */ + +#endif /* _NETINET_IP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/ip6.h b/lib/libc/include/generic-openbsd/netinet/ip6.h new file mode 100644 index 000000000000..e80ec228cfb7 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/ip6.h @@ -0,0 +1,293 @@ +/* $OpenBSD: ip6.h,v 1.23 2025/05/27 07:52:49 bluhm Exp $ */ +/* $KAME: ip6.h,v 1.45 2003/06/05 04:46:38 keiichi Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ip.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_IP6_H_ +#define _NETINET_IP6_H_ + +/* + * Definition for internet protocol version 6. + * RFC 2460 + */ + +struct ip6_hdr { + union { + struct ip6_hdrctl { + u_int32_t ip6_un1_flow; /* 20 bits of flow-ID */ + u_int16_t ip6_un1_plen; /* payload length */ + u_int8_t ip6_un1_nxt; /* next header */ + u_int8_t ip6_un1_hlim; /* hop limit */ + } ip6_un1; + u_int8_t ip6_un2_vfc; /* 4 bits version, top 4 bits class */ + } ip6_ctlun; + struct in6_addr ip6_src; /* source address */ + struct in6_addr ip6_dst; /* destination address */ +} __packed; + +#define ip6_vfc ip6_ctlun.ip6_un2_vfc +#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow +#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen +#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt +#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim +#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim + +#define IPV6_VERSION 0x60 +#define IPV6_VERSION_MASK 0xf0 + +#if _BYTE_ORDER == _BIG_ENDIAN +#define IPV6_FLOWINFO_MASK 0x0fffffff /* flow info (28 bits) */ +#define IPV6_FLOWLABEL_MASK 0x000fffff /* flow label (20 bits) */ +#else +#if _BYTE_ORDER == _LITTLE_ENDIAN +#define IPV6_FLOWINFO_MASK 0xffffff0f /* flow info (28 bits) */ +#define IPV6_FLOWLABEL_MASK 0xffff0f00 /* flow label (20 bits) */ +#endif /* _LITTLE_ENDIAN */ +#endif +#if 1 +/* ECN bits proposed by Sally Floyd */ +#define IP6TOS_CE 0x01 /* congestion experienced */ +#define IP6TOS_ECT 0x02 /* ECN-capable transport */ +#endif + +#ifdef _KERNEL +/* + * for IPv6 pseudo header checksum + * XXX nonstandard + */ +struct ip6_hdr_pseudo { + struct in6_addr ip6ph_src; + struct in6_addr ip6ph_dst; + u_int32_t ip6ph_len; + u_int8_t ip6ph_zero[3]; + u_int8_t ip6ph_nxt; +} __packed; +#endif + +/* + * Extension Headers + */ +struct ip6_ext { + u_int8_t ip6e_nxt; + u_int8_t ip6e_len; +} __packed; + +/* Hop-by-Hop options header */ +/* XXX should we pad it to force alignment on an 8-byte boundary? */ +struct ip6_hbh { + u_int8_t ip6h_nxt; /* next header */ + u_int8_t ip6h_len; /* length in units of 8 octets */ + /* followed by options */ +} __packed; + +/* Destination options header */ +/* XXX should we pad it to force alignment on an 8-byte boundary? */ +struct ip6_dest { + u_int8_t ip6d_nxt; /* next header */ + u_int8_t ip6d_len; /* length in units of 8 octets */ + /* followed by options */ +} __packed; + +/* Option types and related macros */ +#define IP6OPT_PAD1 0x00 /* 00 0 00000 */ +#define IP6OPT_PADN 0x01 /* 00 0 00001 */ +#define IP6OPT_JUMBO 0xC2 /* 11 0 00010 = 194 */ +#define IP6OPT_NSAP_ADDR 0xC3 /* 11 0 00011 */ +#define IP6OPT_TUNNEL_LIMIT 0x04 /* 00 0 00100 */ +#define IP6OPT_ROUTER_ALERT 0x05 /* 00 0 00101 (RFC3542, recommended) */ + +#define IP6OPT_RTALERT_LEN 4 +#define IP6OPT_RTALERT_MLD 0 /* Datagram contains an MLD message */ +#define IP6OPT_RTALERT_RSVP 1 /* Datagram contains an RSVP message */ +#define IP6OPT_RTALERT_ACTNET 2 /* contains an Active Networks msg */ +#define IP6OPT_MINLEN 2 + +#define IP6OPT_TYPE(o) ((o) & 0xC0) +#define IP6OPT_TYPE_SKIP 0x00 +#define IP6OPT_TYPE_DISCARD 0x40 +#define IP6OPT_TYPE_FORCEICMP 0x80 +#define IP6OPT_TYPE_ICMP 0xC0 + +#define IP6OPT_MUTABLE 0x20 + +/* IPv6 options: common part */ +struct ip6_opt { + u_int8_t ip6o_type; + u_int8_t ip6o_len; +} __packed; + +/* Jumbo Payload Option */ +struct ip6_opt_jumbo { + u_int8_t ip6oj_type; + u_int8_t ip6oj_len; + u_int8_t ip6oj_jumbo_len[4]; +} __packed; +#define IP6OPT_JUMBO_LEN 6 + +/* NSAP Address Option */ +struct ip6_opt_nsap { + u_int8_t ip6on_type; + u_int8_t ip6on_len; + u_int8_t ip6on_src_nsap_len; + u_int8_t ip6on_dst_nsap_len; + /* followed by source NSAP */ + /* followed by destination NSAP */ +} __packed; + +/* Tunnel Limit Option */ +struct ip6_opt_tunnel { + u_int8_t ip6ot_type; + u_int8_t ip6ot_len; + u_int8_t ip6ot_encap_limit; +} __packed; + +/* Router Alert Option */ +struct ip6_opt_router { + u_int8_t ip6or_type; + u_int8_t ip6or_len; + u_int8_t ip6or_value[2]; +} __packed; +/* Router alert values (in network byte order) */ +#if _BYTE_ORDER == _BIG_ENDIAN +#define IP6_ALERT_MLD 0x0000 +#define IP6_ALERT_RSVP 0x0001 +#define IP6_ALERT_AN 0x0002 +#else +#if _BYTE_ORDER == _LITTLE_ENDIAN +#define IP6_ALERT_MLD 0x0000 +#define IP6_ALERT_RSVP 0x0100 +#define IP6_ALERT_AN 0x0200 +#endif /* _LITTLE_ENDIAN */ +#endif + +/* Routing header */ +struct ip6_rthdr { + u_int8_t ip6r_nxt; /* next header */ + u_int8_t ip6r_len; /* length in units of 8 octets */ + u_int8_t ip6r_type; /* routing type */ + u_int8_t ip6r_segleft; /* segments left */ + /* followed by routing type specific data */ +} __packed; + +/* Type 0 Routing header */ +struct ip6_rthdr0 { + u_int8_t ip6r0_nxt; /* next header */ + u_int8_t ip6r0_len; /* length in units of 8 octets */ + u_int8_t ip6r0_type; /* always zero */ + u_int8_t ip6r0_segleft; /* segments left */ + u_int32_t ip6r0_reserved; /* reserved field */ +} __packed; + +/* Fragment header */ +struct ip6_frag { + u_int8_t ip6f_nxt; /* next header */ + u_int8_t ip6f_reserved; /* reserved field */ + u_int16_t ip6f_offlg; /* offset, reserved, and flag */ + u_int32_t ip6f_ident; /* identification */ +} __packed; + +#if _BYTE_ORDER == _BIG_ENDIAN +#define IP6F_OFF_MASK 0xfff8 /* mask out offset from _offlg */ +#define IP6F_RESERVED_MASK 0x0006 /* reserved bits in ip6f_offlg */ +#define IP6F_MORE_FRAG 0x0001 /* more-fragments flag */ +#else /* _BYTE_ORDER == _LITTLE_ENDIAN */ +#define IP6F_OFF_MASK 0xf8ff /* mask out offset from _offlg */ +#define IP6F_RESERVED_MASK 0x0600 /* reserved bits in ip6f_offlg */ +#define IP6F_MORE_FRAG 0x0100 /* more-fragments flag */ +#endif /* _BYTE_ORDER == _LITTLE_ENDIAN */ + +/* + * Internet implementation parameters. + */ +#define IPV6_MAXHLIM 255 /* maximum hoplimit */ +#define IPV6_DEFHLIM 64 /* default hlim */ +#define IPV6_FRAGTTL 120 /* ttl for fragment packets, in slowtimo tick */ +#define IPV6_HLIMDEC 1 /* subtracted when forwarding */ + +#define IPV6_MMTU 1280 /* minimal MTU and reassembly. 1024 + 256 */ +#define IPV6_MAXPACKET 65535 /* ip6 max packet size without Jumbo payload*/ + +#ifdef _KERNEL +/* + * ip6_exthdr_get() ensures that intermediate protocol header (from "off" + * to "len") is located in single mbuf, on contiguous memory region. + * The pointer to the region will be returned to pointer variable "val", + * with type "typ". + */ + +static inline void * +ip6_exthdr_get(struct mbuf **mp, int off, int len) +{ + struct mbuf *t; + int toff; + + if ((*mp)->m_len >= off + len) + return (mtod(*mp, caddr_t) + off); + + t = m_pulldown(*mp, off, len, &toff); + if (t == NULL) { + *mp = NULL; + return (NULL); + } + return (mtod(t, caddr_t) + toff); +} +#endif /* _KERNEL */ +#endif /* _NETINET_IP6_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/ip_ah.h b/lib/libc/include/generic-openbsd/netinet/ip_ah.h new file mode 100644 index 000000000000..7252eb68d442 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/ip_ah.h @@ -0,0 +1,134 @@ +/* $OpenBSD: ip_ah.h,v 1.37 2020/09/01 01:53:34 gnezdo Exp $ */ +/* + * The authors of this code are John Ioannidis (ji@tla.org), + * Angelos D. Keromytis (kermit@csd.uch.gr) and + * Niels Provos (provos@physnet.uni-hamburg.de). + * + * The original version of this code was written by John Ioannidis + * for BSD/OS in Athens, Greece, in November 1995. + * + * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, + * by Angelos D. Keromytis. + * + * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis + * and Niels Provos. + * + * Additional features in 1999 by Angelos D. Keromytis. + * + * Copyright (C) 1995, 1996, 1997, 1998, 1999 John Ioannidis, + * Angelos D. Keromytis and Niels Provos. + * Copyright (c) 2001 Angelos D. Keromytis. + * + * Permission to use, copy, and modify this software with or without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#ifndef _NETINET_IP_AH_H_ +#define _NETINET_IP_AH_H_ + +struct ahstat { + uint64_t ahs_hdrops; /* Packet shorter than header shows */ + uint64_t ahs_nopf; /* Protocol family not supported */ + uint64_t ahs_notdb; + uint64_t ahs_badkcr; + uint64_t ahs_badauth; + uint64_t ahs_noxform; + uint64_t ahs_qfull; + uint64_t ahs_wrap; + uint64_t ahs_replay; + uint64_t ahs_badauthl; /* Bad authenticator length */ + uint64_t ahs_input; /* Input AH packets */ + uint64_t ahs_output; /* Output AH packets */ + uint64_t ahs_invalid; /* Trying to use an invalid TDB */ + uint64_t ahs_ibytes; /* Input bytes */ + uint64_t ahs_obytes; /* Output bytes */ + uint64_t ahs_toobig; /* Packet got larger than + * IP_MAXPACKET */ + uint64_t ahs_pdrops; /* Packet blocked due to policy */ + uint64_t ahs_crypto; /* Crypto processing failure */ + uint64_t ahs_outfail; /* Packet output failure */ +}; + +struct ah { + u_int8_t ah_nh; + u_int8_t ah_hl; + u_int16_t ah_rv; + u_int32_t ah_spi; + u_int32_t ah_rpl; /* We may not use this, if we're using old xforms */ +}; + +/* Length of base AH header */ +#define AH_FLENGTH 8 + +/* + * Names for AH sysctl objects + */ +#define AHCTL_ENABLE 1 /* Enable AH processing */ +#define AHCTL_STATS 2 /* AH stats */ +#define AHCTL_MAXID 3 + +#define AHCTL_NAMES { \ + { 0, 0 }, \ + { "enable", CTLTYPE_INT }, \ + { "stats", CTLTYPE_STRUCT } \ +} + +#ifdef _KERNEL + +#include + +enum ahstat_counters { + ahs_hdrops, /* Packet shorter than header shows */ + ahs_nopf, /* Protocol family not supported */ + ahs_notdb, + ahs_badkcr, + ahs_badauth, + ahs_noxform, + ahs_qfull, + ahs_wrap, + ahs_replay, + ahs_badauthl, /* Bad authenticator length */ + ahs_input, /* Input AH packets */ + ahs_output, /* Output AH packets */ + ahs_invalid, /* Trying to use an invalid TDB */ + ahs_ibytes, /* Input bytes */ + ahs_obytes, /* Output bytes */ + ahs_toobig, /* Packet got larger than + * IP_MAXPACKET */ + ahs_pdrops, /* Packet blocked due to policy */ + ahs_crypto, /* Crypto processing failure */ + ahs_outfail, /* Packet output failure */ + + ahs_ncounters +}; + +extern struct cpumem *ahcounters; + +static inline void +ahstat_inc(enum ahstat_counters c) +{ + counters_inc(ahcounters, c); +} + +static inline void +ahstat_add(enum ahstat_counters c, uint64_t v) +{ + counters_add(ahcounters, c, v); +} + +extern int ah_enable; + +#endif /* _KERNEL */ +#endif /* _NETINET_IP_AH_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/ip_carp.h b/lib/libc/include/generic-openbsd/netinet/ip_carp.h new file mode 100644 index 000000000000..67bf438c6b28 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/ip_carp.h @@ -0,0 +1,228 @@ +/* $OpenBSD: ip_carp.h,v 1.52 2025/03/02 21:28:32 bluhm Exp $ */ + +/* + * Copyright (c) 2002 Michael Shalayeff. All rights reserved. + * Copyright (c) 2003 Ryan McBride. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES 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 MIND, 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 _NETINET_IP_CARP_H_ +#define _NETINET_IP_CARP_H_ + +/* + * The CARP header layout is as follows: + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |Version| Type | VirtualHostID | AdvSkew | Auth Len | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Demotion | AdvBase | Checksum | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Counter (1) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Counter (2) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | SHA-1 HMAC (1) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | SHA-1 HMAC (2) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | SHA-1 HMAC (3) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | SHA-1 HMAC (4) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | SHA-1 HMAC (5) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ + +struct carp_header { +#if _BYTE_ORDER == _LITTLE_ENDIAN + u_int carp_type:4, + carp_version:4; +#endif +#if _BYTE_ORDER == _BIG_ENDIAN + u_int carp_version:4, + carp_type:4; +#endif + u_int8_t carp_vhid; /* virtual host id */ + u_int8_t carp_advskew; /* advertisement skew */ + u_int8_t carp_authlen; /* size of counter+md, 32bit chunks */ + u_int8_t carp_demote; /* demotion indicator */ + u_int8_t carp_advbase; /* advertisement interval */ + u_int16_t carp_cksum; + u_int32_t carp_counter[2]; + unsigned char carp_md[20]; /* SHA1 HMAC */ +} __packed; + +#define CARP_DFLTTL 255 + +/* carp_version */ +#define CARP_VERSION 2 + +/* carp_type */ +#define CARP_ADVERTISEMENT 0x01 + +#define CARP_KEY_LEN 20 /* a sha1 hash of a passphrase */ + +/* carp_advbase */ +#define CARP_DFLTINTV 1 + +/* + * Statistics. + */ +struct carpstats { + u_int64_t carps_ipackets; /* total input packets, IPv4 */ + u_int64_t carps_ipackets6; /* total input packets, IPv6 */ + u_int64_t carps_badif; /* wrong interface */ + u_int64_t carps_badttl; /* TTL is not CARP_DFLTTL */ + u_int64_t carps_hdrops; /* packets shorter than hdr */ + u_int64_t carps_badsum; /* bad checksum */ + u_int64_t carps_badver; /* bad (incl unsupp) version */ + u_int64_t carps_badlen; /* data length does not match */ + u_int64_t carps_badauth; /* bad authentication */ + u_int64_t carps_badvhid; /* bad VHID */ + u_int64_t carps_badaddrs; /* bad address list */ + + u_int64_t carps_opackets; /* total output packets, IPv4 */ + u_int64_t carps_opackets6; /* total output packets, IPv6 */ + u_int64_t carps_onomem; /* no memory for an mbuf */ + u_int64_t carps_ostates; /* total state updates sent */ + + u_int64_t carps_preempt; /* transitions to master */ +}; + +#define CARPDEVNAMSIZ 16 +#ifdef IFNAMSIZ +#if CARPDEVNAMSIZ != IFNAMSIZ +#error namsiz mismatch +#endif +#endif + +/* + * Configuration structure for SIOCSVH SIOCGVH + */ +struct carpreq { + int carpr_state; +#define CARP_STATES "INIT", "BACKUP", "MASTER" +#define CARP_MAXSTATE 2 +#define CARP_MAXNODES 32 + + char carpr_carpdev[CARPDEVNAMSIZ]; + u_int8_t carpr_vhids[CARP_MAXNODES]; + u_int8_t carpr_advskews[CARP_MAXNODES]; + u_int8_t carpr_states[CARP_MAXNODES]; +#define CARP_BAL_MODES "none", "ip", "ip-stealth", "ip-unicast" +#define CARP_BAL_NONE 0 +#define CARP_BAL_IP 1 +#define CARP_BAL_IPSTEALTH 2 +#define CARP_BAL_IPUNICAST 3 +#define CARP_BAL_MAXID 3 + u_int8_t carpr_balancing; + int carpr_advbase; + unsigned char carpr_key[CARP_KEY_LEN]; + struct in_addr carpr_peer; +}; + +/* + * Names for CARP sysctl objects + */ +#define CARPCTL_ALLOW 1 /* accept incoming CARP packets */ +#define CARPCTL_PREEMPT 2 /* high-pri backup preemption mode */ +#define CARPCTL_LOG 3 /* log bad packets */ +#define CARPCTL_STATS 4 /* CARP stats */ +#define CARPCTL_MAXID 5 + +#define CARPCTL_NAMES { \ + { 0, 0 }, \ + { "allow", CTLTYPE_INT }, \ + { "preempt", CTLTYPE_INT }, \ + { "log", CTLTYPE_INT }, \ + { "stats", CTLTYPE_STRUCT }, \ +} + +#ifdef _KERNEL + +#include +#include + +enum carpstat_counters { + carps_ipackets, + carps_ipackets6, + carps_badif, + carps_badttl, + carps_hdrops, + carps_badsum, + carps_badver, + carps_badlen, + carps_badauth, + carps_badvhid, + carps_badaddrs, + carps_opackets, + carps_opackets6, + carps_onomem, + carps_ostates, + carps_preempt, + carps_ncounters, +}; + +extern struct cpumem *carpcounters; + +static inline void +carpstat_inc(enum carpstat_counters c) +{ + counters_inc(carpcounters, c); +} + +/* + * If two carp interfaces share same physical interface, then we pretend all IP + * addresses belong to single interface. + */ +static inline int +carp_strict_addr_chk(struct ifnet *ifp_a, struct ifnet *ifp_b) +{ + return ((ifp_a->if_type == IFT_CARP && + ifp_b->if_index == ifp_a->if_carpdevidx) || + (ifp_b->if_type == IFT_CARP && + ifp_a->if_index == ifp_b->if_carpdevidx) || + (ifp_a->if_type == IFT_CARP && ifp_b->if_type == IFT_CARP && + ifp_a->if_carpdevidx == ifp_b->if_carpdevidx)); +} + +struct mbuf *carp_input(struct ifnet *, struct mbuf *, uint64_t, + struct netstack *); +int carp_proto_input(struct mbuf **, int *, int, int, + struct netstack *); +void carp_carpdev_state(void *); +void carp_group_demote_adj(struct ifnet *, int, char *); +int carp6_proto_input(struct mbuf **, int *, int, int, + struct netstack *); +int carp_iamatch(struct ifnet *); +int carp_ourether(struct ifnet *, u_int8_t *); +int carp_output(struct ifnet *, struct mbuf *, struct sockaddr *, + struct rtentry *); +int carp_sysctl(int *, u_int, void *, size_t *, void *, size_t); +int carp_lsdrop(struct ifnet *, struct mbuf *, sa_family_t, + u_int32_t *, u_int32_t *, int); +#endif /* _KERNEL */ +#endif /* _NETINET_IP_CARP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/ip_divert.h b/lib/libc/include/generic-openbsd/netinet/ip_divert.h new file mode 100644 index 000000000000..a11dee17cecb --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/ip_divert.h @@ -0,0 +1,93 @@ +/* $OpenBSD: ip_divert.h,v 1.30 2025/06/23 12:05:46 bluhm Exp $ */ + +/* + * Copyright (c) 2009 Michele Marchetto + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _IP_DIVERT_H_ +#define _IP_DIVERT_H_ + +struct divstat { + u_long divs_ipackets; /* total input packets */ + u_long divs_noport; /* no socket on port */ + u_long divs_fullsock; /* not delivered, input socket full */ + u_long divs_opackets; /* total output packets */ + u_long divs_errors; /* generic errors */ +}; + +/* + * Names for divert sysctl objects + */ +#define DIVERTCTL_RECVSPACE 1 /* receive buffer space */ +#define DIVERTCTL_SENDSPACE 2 /* send buffer space */ +#define DIVERTCTL_STATS 3 /* divert statistics */ +#define DIVERTCTL_MAXID 4 + +#define DIVERTCTL_NAMES { \ + { 0, 0 }, \ + { "recvspace", CTLTYPE_INT }, \ + { "sendspace", CTLTYPE_INT }, \ + { "stats", CTLTYPE_STRUCT } \ +} + +#ifdef _KERNEL + +#include + +#define DIVERT_SENDSPACE (65536 + 100) +#define DIVERT_RECVSPACE (65536 + 100) +#define DIVERT_HASHSIZE 128 + +enum divstat_counters { + divs_ipackets, + divs_noport, + divs_fullsock, + divs_opackets, + divs_errors, + divs_ncounters, +}; + +extern struct cpumem *divcounters; + +static inline void +divstat_inc(enum divstat_counters c) +{ + counters_inc(divcounters, c); +} + +extern u_int divert_sendspace; +extern u_int divert_recvspace; +extern struct inpcbtable divbtable, divb6table; +extern const struct pr_usrreqs divert_usrreqs, divert6_usrreqs; + +void divert_init(void); +void divert_packet(struct mbuf *, int, u_int16_t); +int divert_sysctl(int *, u_int, void *, size_t *, void *, size_t); +int divert_sysctl_divstat(void *, size_t *, void *); +int divert_attach(struct socket *, int, int); +int divert_detach(struct socket *); +int divert_bind(struct socket *, struct mbuf *, struct proc *); +int divert_shutdown(struct socket *); +int divert_send(struct socket *, struct mbuf *, struct mbuf *, + struct mbuf *); + +void divert6_init(void); +void divert6_packet(struct mbuf *, int, u_int16_t); +int divert6_attach(struct socket *, int, int); +int divert6_send(struct socket *, struct mbuf *, struct mbuf *, + struct mbuf *); + +#endif /* _KERNEL */ +#endif /* _IP_DIVERT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/ip_ecn.h b/lib/libc/include/generic-openbsd/netinet/ip_ecn.h new file mode 100644 index 000000000000..3e900aa1976f --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/ip_ecn.h @@ -0,0 +1,52 @@ +/* $OpenBSD: ip_ecn.h,v 1.7 2018/11/14 23:55:04 dlg Exp $ */ +/* $KAME: ip_ecn.h,v 1.5 2000/03/27 04:58:38 sumikawa Exp $ */ + +/* + * Copyright (C) 1999 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 _NETINET_IP_ECN_H_ +#define _NETINET_IP_ECN_H_ + +/* + * ECN consideration on tunnel ingress/egress operation. + * http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt + */ + +#define ECN_ALLOWED_IPSEC 2 /* ECN allowed */ +#define ECN_ALLOWED 1 /* ECN allowed */ +#define ECN_FORBIDDEN 0 /* ECN forbidden */ +#define ECN_NOCARE (-1) /* no consideration to ECN */ + +#if defined(_KERNEL) +extern void ip_ecn_ingress(int, u_int8_t *, u_int8_t *); +extern int ip_ecn_egress(int, u_int8_t *, u_int8_t *); +void ip_tos_patch(struct ip *, uint8_t); +#endif /* _KERNEL */ +#endif /* _NETINET_IP_ECN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/ip_esp.h b/lib/libc/include/generic-openbsd/netinet/ip_esp.h new file mode 100644 index 000000000000..79e213447a81 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/ip_esp.h @@ -0,0 +1,141 @@ +/* $OpenBSD: ip_esp.h,v 1.48 2025/01/01 13:44:22 bluhm Exp $ */ +/* + * The authors of this code are John Ioannidis (ji@tla.org), + * Angelos D. Keromytis (kermit@csd.uch.gr) and + * Niels Provos (provos@physnet.uni-hamburg.de). + * + * The original version of this code was written by John Ioannidis + * for BSD/OS in Athens, Greece, in November 1995. + * + * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, + * by Angelos D. Keromytis. + * + * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis + * and Niels Provos. + * + * Additional features in 1999 by Angelos D. Keromytis. + * + * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, + * Angelos D. Keromytis and Niels Provos. + * Copyright (c) 2001 Angelos D. Keromytis. + * + * Permission to use, copy, and modify this software with or without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#ifndef _NETINET_IP_ESP_H_ +#define _NETINET_IP_ESP_H_ + +struct espstat { + uint64_t esps_hdrops; /* Packet shorter than header shows */ + uint64_t esps_nopf; /* Protocol family not supported */ + uint64_t esps_notdb; + uint64_t esps_badkcr; + uint64_t esps_qfull; + uint64_t esps_noxform; + uint64_t esps_badilen; + uint64_t esps_wrap; /* Replay counter wrapped around */ + uint64_t esps_badenc; /* Bad encryption detected */ + uint64_t esps_badauth; /* Only valid for transforms + * with auth */ + uint64_t esps_replay; /* Possible packet replay detected */ + uint64_t esps_input; /* Input ESP packets */ + uint64_t esps_output; /* Output ESP packets */ + uint64_t esps_invalid; /* Trying to use an invalid TDB */ + uint64_t esps_ibytes; /* Input bytes */ + uint64_t esps_obytes; /* Output bytes */ + uint64_t esps_toobig; /* Packet got larger than + * IP_MAXPACKET */ + uint64_t esps_pdrops; /* Packet blocked due to policy */ + uint64_t esps_crypto; /* Crypto processing failure */ + uint64_t esps_udpencin; /* Input ESP-in-UDP packets */ + uint64_t esps_udpencout; /* Output ESP-in-UDP packets */ + uint64_t esps_udpinval; /* Invalid input ESP-in-UDP packets */ + uint64_t esps_udpneeded; /* Trying to use a ESP-in-UDP TDB */ + uint64_t esps_outfail; /* Packet output failure */ +}; + +/* + * Names for ESP sysctl objects + */ +#define ESPCTL_ENABLE 1 /* Enable ESP processing */ +#define ESPCTL_UDPENCAP_ENABLE 2 /* Enable ESP over UDP */ +#define ESPCTL_UDPENCAP_PORT 3 /* UDP port for encapsulation */ +#define ESPCTL_STATS 4 /* ESP Stats */ +#define ESPCTL_MAXID 5 + +#define ESPCTL_NAMES { \ + { 0, 0 }, \ + { "enable", CTLTYPE_INT }, \ + { "udpencap", CTLTYPE_INT }, \ + { "udpencap_port", CTLTYPE_INT }, \ + { "stats", CTLTYPE_STRUCT }, \ +} + +#ifdef _KERNEL + +#include + +enum espstat_counters { + esps_hdrops, /* Packet shorter than header shows */ + esps_nopf, /* Protocol family not supported */ + esps_notdb, + esps_badkcr, + esps_qfull, + esps_noxform, + esps_badilen, + esps_wrap, /* Replay counter wrapped around */ + esps_badenc, /* Bad encryption detected */ + esps_badauth, /* Only valid for transformsx + * with auth */ + esps_replay, /* Possible packet replay detected */ + esps_input, /* Input ESP packets */ + esps_output, /* Output ESP packets */ + esps_invalid, /* Trying to use an invalid TDB */ + esps_ibytes, /* Input bytes */ + esps_obytes, /* Output bytes */ + esps_toobig, /* Packet got larger than + * IP_MAXPACKET */ + esps_pdrops, /* Packet blocked due to policy */ + esps_crypto, /* Crypto processing failure */ + esps_udpencin, /* Input ESP-in-UDP packets */ + esps_udpencout, /* Output ESP-in-UDP packets */ + esps_udpinval, /* Invalid input ESP-in-UDP packets */ + esps_udpneeded, /* Trying to use a ESP-in-UDP TDB */ + esps_outfail, /* Packet output failure */ + + esps_ncounters +}; + +extern struct cpumem *espcounters; + +static inline void +espstat_inc(enum espstat_counters c) +{ + counters_inc(espcounters, c); +} + +static inline void +espstat_add(enum espstat_counters c, uint64_t v) +{ + counters_add(espcounters, c, v); +} + +extern int esp_enable; +extern int udpencap_enable; +extern int udpencap_port; + +#endif /* _KERNEL */ +#endif /* _NETINET_IP_ESP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/ip_ether.h b/lib/libc/include/generic-openbsd/netinet/ip_ether.h new file mode 100644 index 000000000000..d213683626fb --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/ip_ether.h @@ -0,0 +1,111 @@ +/* $OpenBSD: ip_ether.h,v 1.30 2019/10/04 05:00:49 dlg Exp $ */ +/* + * The author of this code is Angelos D. Keromytis (angelos@adk.gr) + * + * This code was written by Angelos D. Keromytis in October 1999. + * + * Copyright (C) 1999-2001 Angelos D. Keromytis. + * + * Permission to use, copy, and modify this software with or without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#ifndef _NETINET_IP_ETHER_H_ +#define _NETINET_IP_ETHER_H_ + +/* + * Ethernet-inside-IP processing. + */ + +struct etheripstat { + u_int64_t etherips_hdrops; /* packet shorter than header shows */ + u_int64_t etherips_qfull; /* bridge queue full, packet dropped */ + u_int64_t etherips_noifdrops; /* no interface/bridge information */ + u_int64_t etherips_pdrops; /* packet dropped due to policy */ + u_int64_t etherips_adrops; /* all other drops */ + u_int64_t etherips_ipackets; /* total input packets */ + u_int64_t etherips_opackets; /* total output packets */ + u_int64_t etherips_ibytes; /* input bytes */ + u_int64_t etherips_obytes; /* output bytes */ +}; + +struct etherip_header { +#if BYTE_ORDER == LITTLE_ENDIAN + u_int eip_res:4; /* reserved */ + u_int eip_ver:4; /* version */ +#endif +#if BYTE_ORDER == BIG_ENDIAN + u_int eip_ver:4; /* version */ + u_int eip_res:4; /* reserved */ +#endif + u_int8_t eip_pad; /* required padding byte */ +} __packed; + +#define ETHERIP_VERSION 0x03 + +/* + * Names for Ether-IP sysctl objects + */ +#define ETHERIPCTL_ALLOW 1 /* accept incoming EtherIP packets */ +#define ETHERIPCTL_STATS 2 /* etherip stats */ +#define ETHERIPCTL_MAXID 3 + +#define ETHERIPCTL_NAMES { \ + { 0, 0 }, \ + { "allow", CTLTYPE_INT }, \ + { "stats", CTLTYPE_STRUCT }, \ +} + +#ifdef _KERNEL + +#include + +enum etheripstat_counters { + etherips_hdrops, /* packet shorter than header shows */ + etherips_qfull, /* bridge queue full, packet dropped */ + etherips_noifdrops, /* no interface/bridge information */ + etherips_pdrops, /* packet dropped due to policy */ + etherips_adrops, /* all other drops */ + etherips_ipackets, /* total input packets */ + etherips_opackets, /* total output packets */ + etherips_ibytes, /* input bytes */ + etherips_obytes, /* output bytes */ + + etherips_ncounters +}; + +extern struct cpumem *etheripcounters; + +static inline void +etheripstat_inc(enum etheripstat_counters c) +{ + counters_inc(etheripcounters, c); +} + +static inline void +etheripstat_add(enum etheripstat_counters c, uint64_t v) +{ + counters_add(etheripcounters, c, v); +} + +static inline void +etheripstat_pkt(enum etheripstat_counters pcounter, + enum etheripstat_counters bcounter, uint64_t v) +{ + counters_pkt(etheripcounters, pcounter, bcounter, v); +} + +#endif /* _KERNEL */ +#endif /* _NETINET_IP_ETHER_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/ip_gre.h b/lib/libc/include/generic-openbsd/netinet/ip_gre.h new file mode 100644 index 000000000000..ed30e3cc6b51 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/ip_gre.h @@ -0,0 +1,62 @@ +/* $OpenBSD: ip_gre.h,v 1.20 2025/01/01 13:44:22 bluhm Exp $ */ +/* $NetBSD: ip_gre.h,v 1.3 1998/10/07 23:33:02 thorpej Exp $ */ + +/* + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Heiko W.Rupp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _NETINET_IP_GRE_H_ +#define _NETINET_IP_GRE_H_ + +/* Protocol number for Cisco's WCCP + * The Internet Draft is: + * draft-forster-wrec-wccp-v1-00.txt + */ +#define GREPROTO_WCCP 0x883e + +/* + * Names for GRE sysctl objects + */ +#define GRECTL_ALLOW 1 /* accept incoming GRE packets */ +#define GRECTL_WCCP 2 /* accept WCCPv1-style GRE packets */ +#define GRECTL_MAXID 3 + +#define GRECTL_NAMES { \ + { 0, 0 }, \ + { "allow", CTLTYPE_INT }, \ + { "wccp", CTLTYPE_INT }, \ +} + +#ifdef _KERNEL + +extern const struct pr_usrreqs gre_usrreqs; + +int gre_send(struct socket *, struct mbuf *, struct mbuf *, + struct mbuf *); +#endif /* _KERNEL */ +#endif /* _NETINET_IP_GRE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/ip_icmp.h b/lib/libc/include/generic-openbsd/netinet/ip_icmp.h new file mode 100644 index 000000000000..601bfa4419c5 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/ip_icmp.h @@ -0,0 +1,246 @@ +/* $OpenBSD: ip_icmp.h,v 1.33 2025/03/02 21:28:32 bluhm Exp $ */ +/* $NetBSD: ip_icmp.h,v 1.10 1996/02/13 23:42:28 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_IP_ICMP_H_ +#define _NETINET_IP_ICMP_H_ + +/* + * Interface Control Message Protocol Definitions. + * Per RFC 792, September 1981. + * RFC 950, August 1985. (Address Mask Request / Reply) + * RFC 1256, September 1991. (Router Advertisement and Solicitation) + * RFC 1108, November 1991. (Param Problem, Missing Req. Option) + * RFC 1393, January 1993. (Traceroute) + * RFC 1475, June 1993. (Datagram Conversion Error) + * RFC 1812, June 1995. (adm prohib, host precedence, precedence cutoff) + * RFC 2002, October 1996. (Mobility changes to Router Advertisement) + */ + +/* + * ICMP Router Advertisement data + */ +struct icmp_ra_addr { + u_int32_t ira_addr; + u_int32_t ira_preference; +}; + +/* + * Structure of an icmp header. + */ +struct icmp { + u_int8_t icmp_type; /* type of message, see below */ + u_int8_t icmp_code; /* type sub code */ + u_int16_t icmp_cksum; /* ones complement cksum of struct */ + union { + u_int8_t ih_pptr; /* ICMP_PARAMPROB */ + struct ih_exthdr { /* RFC4884 extended header */ + u_int8_t iex_pad; + u_int8_t iex_length; + } ih_exthdr; + struct in_addr ih_gwaddr; /* ICMP_REDIRECT */ + struct ih_idseq { + u_int16_t icd_id; + u_int16_t icd_seq; + } ih_idseq; + int32_t ih_void; + + /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */ + struct ih_pmtu { + u_int16_t ipm_void; + u_int16_t ipm_nextmtu; + } ih_pmtu; + + struct ih_rtradv { + u_int8_t irt_num_addrs; + u_int8_t irt_wpa; + u_int16_t irt_lifetime; + } ih_rtradv; + } icmp_hun; +#define icmp_pptr icmp_hun.ih_pptr +#define icmp_length icmp_hun.ih_exthdr.iex_length +#define icmp_gwaddr icmp_hun.ih_gwaddr +#define icmp_id icmp_hun.ih_idseq.icd_id +#define icmp_seq icmp_hun.ih_idseq.icd_seq +#define icmp_void icmp_hun.ih_void +#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void +#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu +#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs +#define icmp_wpa icmp_hun.ih_rtradv.irt_wpa +#define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime + union { + struct id_ts { + u_int32_t its_otime; + u_int32_t its_rtime; + u_int32_t its_ttime; + } id_ts; + struct id_ip { + struct ip idi_ip; + /* options and then 64 bits of data */ + } id_ip; + u_int32_t id_mask; + int8_t id_data[1]; + } icmp_dun; +#define icmp_otime icmp_dun.id_ts.its_otime +#define icmp_rtime icmp_dun.id_ts.its_rtime +#define icmp_ttime icmp_dun.id_ts.its_ttime +#define icmp_ip icmp_dun.id_ip.idi_ip +#define icmp_mask icmp_dun.id_mask +#define icmp_data icmp_dun.id_data +}; + +struct icmp_ext_hdr { + u_int8_t ieh_version; /* only high nibble used */ + u_int8_t ieh_res; /* reserved, must be zero */ + u_int16_t ieh_cksum; /* ones complement cksum of ext hdr */ +}; + +#define ICMP_EXT_HDR_VERSION 0x20 +#define ICMP_EXT_HDR_VMASK 0xf0 +#define ICMP_EXT_OFFSET 128 + +struct icmp_ext_obj_hdr { + u_int16_t ieo_length; /* length of obj incl this header */ + u_int8_t ieo_cnum; /* class number */ + u_int8_t ieo_ctype; /* sub class type */ +}; + +#define ICMP_EXT_MPLS 1 +#define ICMP_EXT_IFINFO 2 + +/* + * For IPv6 transition related ICMP errors. + */ +#define ICMP_V6ADVLENMIN (8 + sizeof(struct ip) + 40) +#define ICMP_V6ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 40) + +/* + * Lower bounds on packet lengths for various types. + * For the error advice packets must first insure that the + * packet is large enough to contain the returned ip header. + * Only then can we do the check to see if 64 bits of packet + * data have been returned, since we need to check the returned + * ip header length. + */ +#define ICMP_MINLEN 8 /* abs minimum */ +#define ICMP_TSLEN (8 + 3 * sizeof (u_int32_t)) /* timestamp */ +#define ICMP_MASKLEN 12 /* address mask */ +#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */ +#define ICMP_ADVLENMAX (8 + 60 + 40) /* maximum */ +#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8) + /* N.B.: must separately check that ip_hl >= 5 */ + +/* + * Definition of type and code field values. + * https://www.iana.org/assignments/icmp-parameters + */ +#define ICMP_ECHOREPLY 0 /* echo reply */ +#define ICMP_UNREACH 3 /* dest unreachable, codes: */ +#define ICMP_UNREACH_NET 0 /* bad net */ +#define ICMP_UNREACH_HOST 1 /* bad host */ +#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */ +#define ICMP_UNREACH_PORT 3 /* bad port */ +#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */ +#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */ +#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */ +#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */ +#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */ +#define ICMP_UNREACH_NET_PROHIB 9 /* for crypto devs */ +#define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */ +#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */ +#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */ +#define ICMP_UNREACH_FILTER_PROHIB 13 /* prohibited access */ +#define ICMP_UNREACH_HOST_PRECEDENCE 14 /* precedence violat'n*/ +#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* precedence cutoff */ +#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */ +#define ICMP_REDIRECT 5 /* shorter route, codes: */ +#define ICMP_REDIRECT_NET 0 /* for network */ +#define ICMP_REDIRECT_HOST 1 /* for host */ +#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */ +#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */ +#define ICMP_ALTHOSTADDR 6 /* alternate host address */ +#define ICMP_ECHO 8 /* echo service */ +#define ICMP_ROUTERADVERT 9 /* router advertisement */ +#define ICMP_ROUTERADVERT_NORMAL 0 /* normal advertisement */ +#define ICMP_ROUTERADVERT_NOROUTE_COMMON 16 /* selective routing */ +#define ICMP_ROUTERSOLICIT 10 /* router solicitation */ +#define ICMP_TIMXCEED 11 /* time exceeded, code: */ +#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */ +#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */ +#define ICMP_PARAMPROB 12 /* ip header bad */ +#define ICMP_PARAMPROB_ERRATPTR 0 /* req. opt. absent */ +#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */ +#define ICMP_PARAMPROB_LENGTH 2 /* bad length */ +#define ICMP_TSTAMP 13 /* timestamp request */ +#define ICMP_TSTAMPREPLY 14 /* timestamp reply */ +#define ICMP_IREQ 15 /* information request */ +#define ICMP_IREQREPLY 16 /* information reply */ +#define ICMP_MASKREQ 17 /* address mask request */ +#define ICMP_MASKREPLY 18 /* address mask reply */ +#define ICMP_TRACEROUTE 30 /* traceroute */ +#define ICMP_DATACONVERR 31 /* data conversion error */ +#define ICMP_MOBILE_REDIRECT 32 /* mobile host redirect */ +#define ICMP_IPV6_WHEREAREYOU 33 /* IPv6 where-are-you */ +#define ICMP_IPV6_IAMHERE 34 /* IPv6 i-am-here */ +#define ICMP_MOBILE_REGREQUEST 35 /* mobile registration req */ +#define ICMP_MOBILE_REGREPLY 36 /* mobile registration reply */ +#define ICMP_SKIP 39 /* SKIP */ +#define ICMP_PHOTURIS 40 /* Photuris */ +#define ICMP_PHOTURIS_UNKNOWN_INDEX 1 /* unknown sec index */ +#define ICMP_PHOTURIS_AUTH_FAILED 2 /* auth failed */ +#define ICMP_PHOTURIS_DECRYPT_FAILED 3 /* decrypt failed */ + +#define ICMP_MAXTYPE 40 + +#define ICMP_INFOTYPE(type) \ + ((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \ + (type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \ + (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \ + (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \ + (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) + +#ifdef _KERNEL +struct mbuf * + icmp_do_error(struct mbuf *, int, int, u_int32_t, int); +void icmp_error(struct mbuf *, int, int, u_int32_t, int); +int icmp_input(struct mbuf **, int *, int, int, struct netstack *); +void icmp_init(void); +int icmp_reflect(struct mbuf *, struct mbuf **, struct in_ifaddr *); +void icmp_send(struct mbuf *, struct mbuf *); +int icmp_sysctl(int *, u_int, void *, size_t *, void *, size_t); +struct rtentry * + icmp_mtudisc_clone(struct in_addr, u_int, int); +void icmp_mtudisc(struct icmp *, u_int); +int icmp_do_exthdr(struct mbuf *, u_int16_t, u_int8_t, void *, size_t); +#endif /* _KERNEL */ +#endif /* _NETINET_IP_ICMP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/ip_ipcomp.h b/lib/libc/include/generic-openbsd/netinet/ip_ipcomp.h new file mode 100644 index 000000000000..c207c338532f --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/ip_ipcomp.h @@ -0,0 +1,126 @@ +/* $OpenBSD: ip_ipcomp.h,v 1.11 2020/09/01 01:53:34 gnezdo Exp $ */ + +/* + * Copyright (c) 2001 Jean-Jacques Bernard-Gundol (jj@wabbitt.org) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* IP payload compression protocol (IPComp), see RFC 2393 */ + +#ifndef _NETINET_IP_IPCOMP_H_ +#define _NETINET_IP_IPCOMP_H_ + +struct ipcompstat { + uint64_t ipcomps_hdrops; /* Packet shorter than header shows */ + uint64_t ipcomps_nopf; /* Protocol family not supported */ + uint64_t ipcomps_notdb; + uint64_t ipcomps_badkcr; + uint64_t ipcomps_qfull; + uint64_t ipcomps_noxform; + uint64_t ipcomps_wrap; + uint64_t ipcomps_input; /* Input IPcomp packets */ + uint64_t ipcomps_output; /* Output IPcomp packets */ + uint64_t ipcomps_invalid; /* Trying to use an invalid + * TDB */ + uint64_t ipcomps_ibytes; /* Input bytes */ + uint64_t ipcomps_obytes; /* Output bytes */ + uint64_t ipcomps_toobig; /* Packet got larger than + * IP_MAXPACKET */ + uint64_t ipcomps_pdrops; /* Packet blocked due to policy */ + uint64_t ipcomps_crypto; /* "Crypto" processing failure */ + uint64_t ipcomps_minlen; /* packets too short for compress */ + uint64_t ipcomps_outfail; /* Packet output failure */ +}; + +/* IPCOMP header */ +struct ipcomp { + u_int8_t ipcomp_nh; /* Next header */ + u_int8_t ipcomp_flags; /* Flags: reserved field: 0 */ + u_int16_t ipcomp_cpi; /* Compression Parameter Index, + * Network order */ +}; + +/* Length of IPCOMP header */ +#define IPCOMP_HLENGTH 4 + +/* + * Names for IPCOMP sysctl objects + */ +#define IPCOMPCTL_ENABLE 1 /* Enable COMP processing */ +#define IPCOMPCTL_STATS 2 /* COMP stats */ +#define IPCOMPCTL_MAXID 3 + +#define IPCOMPCTL_NAMES { \ + { 0, 0 }, \ + { "enable", CTLTYPE_INT }, \ + { "stats", CTLTYPE_STRUCT }, \ +} + +#ifdef _KERNEL + +#include + +enum ipcomp_counters { + ipcomps_hdrops, /* Packet shorter than header shows */ + ipcomps_nopf, /* Protocol family not supported */ + ipcomps_notdb, + ipcomps_badkcr, + ipcomps_qfull, + ipcomps_noxform, + ipcomps_wrap, + ipcomps_input, /* Input IPcomp packets */ + ipcomps_output, /* Output IPcomp packets */ + ipcomps_invalid, /* Trying to use an invalid + * TDB */ + ipcomps_ibytes, /* Input bytes */ + ipcomps_obytes, /* Output bytes */ + ipcomps_toobig, /* Packet got larger than + * IP_MAXPACKET */ + ipcomps_pdrops, /* Packet blocked due to policy */ + ipcomps_crypto, /* "Crypto" processing failure */ + ipcomps_minlen, /* packets too short for compress */ + ipcomps_outfail, /* Packet output failure */ + + ipcomps_ncounters +}; + +extern struct cpumem *ipcompcounters; + +static inline void +ipcompstat_inc(enum ipcomp_counters c) +{ + counters_inc(ipcompcounters, c); +} + +static inline void +ipcompstat_add(enum ipcomp_counters c, uint64_t v) +{ + counters_add(ipcompcounters, c, v); +} + +extern int ipcomp_enable; + +#endif /* _KERNEL */ +#endif /* _NETINET_IP_IPCOMP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/ip_ipip.h b/lib/libc/include/generic-openbsd/netinet/ip_ipip.h new file mode 100644 index 000000000000..d903badc2023 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/ip_ipip.h @@ -0,0 +1,124 @@ +/* $OpenBSD: ip_ipip.h,v 1.15 2025/03/02 21:28:32 bluhm Exp $ */ +/* + * The authors of this code are John Ioannidis (ji@tla.org), + * Angelos D. Keromytis (kermit@csd.uch.gr) and + * Niels Provos (provos@physnet.uni-hamburg.de). + * + * The original version of this code was written by John Ioannidis + * for BSD/OS in Athens, Greece, in November 1995. + * + * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, + * by Angelos D. Keromytis. + * + * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis + * and Niels Provos. + * + * Additional features in 1999 by Angelos D. Keromytis. + * + * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, + * Angelos D. Keromytis and Niels Provos. + * Copyright (c) 2001, Angelos D. Keromytis. + * + * Permission to use, copy, and modify this software with or without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#ifndef _NETINET_IPIP_H_ +#define _NETINET_IPIP_H_ + +/* + * IP-inside-IP processing. + * Not quite all the functionality of RFC-1853, but the main idea is there. + */ + +struct ipipstat { + u_int64_t ipips_ipackets; /* total input packets */ + u_int64_t ipips_opackets; /* total output packets */ + u_int64_t ipips_hdrops; /* packet shorter than header shows */ + u_int64_t ipips_qfull; + u_int64_t ipips_ibytes; + u_int64_t ipips_obytes; + u_int64_t ipips_pdrops; /* packet dropped due to policy */ + u_int64_t ipips_spoof; /* IP spoofing attempts */ + u_int64_t ipips_family; /* Protocol family mismatch */ + u_int64_t ipips_unspec; /* Missing tunnel endpoint address */ +}; + +#define IP4_DEFAULT_TTL 0 +#define IP4_SAME_TTL -1 + +/* + * Names for IPIP sysctl objects + */ +#define IPIPCTL_ALLOW 1 /* accept incoming IP4 packets */ +#define IPIPCTL_STATS 2 /* IPIP stats */ +#define IPIPCTL_MAXID 3 + +#define IPIPCTL_NAMES { \ + { 0, 0 }, \ + { "allow", CTLTYPE_INT }, \ + { "stats", CTLTYPE_STRUCT }, \ +} + +#ifdef _KERNEL + +#include + +enum ipipstat_counters { + ipips_ipackets, + ipips_opackets, + ipips_hdrops, + ipips_qfull, + ipips_ibytes, + ipips_obytes, + ipips_pdrops, + ipips_spoof, + ipips_family, + ipips_unspec, + ipips_ncounters +}; + +extern struct cpumem *ipipcounters; + +static inline void +ipipstat_inc(enum ipipstat_counters c) +{ + counters_inc(ipipcounters, c); +} + +static inline void +ipipstat_add(enum ipipstat_counters c, uint64_t v) +{ + counters_add(ipipcounters, c, v); +} + +static inline void +ipipstat_pkt(enum ipipstat_counters p, enum ipipstat_counters b, uint64_t v) +{ + counters_pkt(ipipcounters, p, b, v); +} + +struct tdb; + +void ipip_init(void); +int ipip_input(struct mbuf **, int *, int, int, struct netstack *); +int ipip_input_if(struct mbuf **, int *, int, int, int, struct ifnet *, + struct netstack *); +int ipip_output(struct mbuf **, struct tdb *); +int ipip_sysctl(int *, u_int, void *, size_t *, void *, size_t); + +extern int ipip_allow; +#endif /* _KERNEL */ +#endif /* _NETINET_IPIP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/ip_ipsp.h b/lib/libc/include/generic-openbsd/netinet/ip_ipsp.h new file mode 100644 index 000000000000..a77dc4b4ce9f --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/ip_ipsp.h @@ -0,0 +1,737 @@ +/* $OpenBSD: ip_ipsp.h,v 1.249 2025/05/09 19:53:41 mvs Exp $ */ +/* + * The authors of this code are John Ioannidis (ji@tla.org), + * Angelos D. Keromytis (kermit@csd.uch.gr), + * Niels Provos (provos@physnet.uni-hamburg.de) and + * Niklas Hallqvist (niklas@appli.se). + * + * The original version of this code was written by John Ioannidis + * for BSD/OS in Athens, Greece, in November 1995. + * + * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, + * by Angelos D. Keromytis. + * + * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis + * and Niels Provos. + * + * Additional features in 1999 by Angelos D. Keromytis and Niklas Hallqvist. + * + * Copyright (c) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, + * Angelos D. Keromytis and Niels Provos. + * Copyright (c) 1999 Niklas Hallqvist. + * Copyright (c) 2001, Angelos D. Keromytis. + * + * Permission to use, copy, and modify this software with or without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#ifndef _NETINET_IPSP_H_ +#define _NETINET_IPSP_H_ + +/* + * Locks used to protect struct members in this file: + * I immutable after creation + * a atomic operations + * N net lock + * A ipsec_acquire_mtx + * F ipsec_flows_mtx + * P ipo_tdb_mtx link policy to TDB global mutex + * D tdb_sadb_mtx SA database global mutex + * m tdb_mtx fields of struct tdb + * S pfsync fields of struct tdb + */ + +/* IPSP global definitions. */ + +#include +#include + +union sockaddr_union { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; +}; + +#define AH_HMAC_MAX_HASHLEN 32 /* 256 bits of authenticator for SHA512 */ +#define AH_HMAC_RPLENGTH 4 /* 32 bits of replay counter */ +#define AH_HMAC_INITIAL_RPL 1 /* Replay counter initial value */ + +/* Authenticator lengths */ +#define AH_MD5_ALEN 16 +#define AH_SHA1_ALEN 20 +#define AH_RMD160_ALEN 20 +#define AH_SHA2_256_ALEN 32 +#define AH_SHA2_384_ALEN 48 +#define AH_SHA2_512_ALEN 64 +#define AH_ALEN_MAX 64 /* Keep updated */ + +/* Reserved SPI numbers */ +#define SPI_LOCAL_USE 0 +#define SPI_RESERVED_MIN 1 +#define SPI_RESERVED_MAX 255 + +/* Reserved CPI numbers */ +#define CPI_RESERVED_MIN 1 +#define CPI_RESERVED_MAX 255 +#define CPI_PRIVATE_MIN 61440 +#define CPI_PRIVATE_MAX 65535 + +/* sysctl default values */ +#define IPSEC_DEFAULT_EMBRYONIC_SA_TIMEOUT 60 /* 1 minute */ +#define IPSEC_DEFAULT_PFS 1 +#define IPSEC_DEFAULT_SOFT_ALLOCATIONS 0 +#define IPSEC_DEFAULT_EXP_ALLOCATIONS 0 +#define IPSEC_DEFAULT_SOFT_BYTES 0 +#define IPSEC_DEFAULT_EXP_BYTES 0 +#define IPSEC_DEFAULT_SOFT_TIMEOUT 80000 +#define IPSEC_DEFAULT_EXP_TIMEOUT 86400 +#define IPSEC_DEFAULT_SOFT_FIRST_USE 3600 +#define IPSEC_DEFAULT_EXP_FIRST_USE 7200 +#define IPSEC_DEFAULT_DEF_ENC "aes" +#define IPSEC_DEFAULT_DEF_AUTH "hmac-sha1" +#define IPSEC_DEFAULT_EXPIRE_ACQUIRE 30 +#define IPSEC_DEFAULT_DEF_COMP "deflate" + +struct sockaddr_encap { + u_int8_t sen_len; /* length */ + u_int8_t sen_family; /* PF_KEY */ + u_int16_t sen_type; /* see SENT_* */ + union { + struct { /* SENT_IP4 */ + u_int8_t Direction; + struct in_addr Src; + struct in_addr Dst; + u_int8_t Proto; + u_int16_t Sport; + u_int16_t Dport; + } Sip4; + + struct { /* SENT_IP6 */ + u_int8_t Direction; + struct in6_addr Src; + struct in6_addr Dst; + u_int8_t Proto; + u_int16_t Sport; + u_int16_t Dport; + } Sip6; + } Sen; +}; + +#define IPSP_DIRECTION_IN 0x1 +#define IPSP_DIRECTION_OUT 0x2 + +struct ipsecstat { + uint64_t ipsec_tunnels; /* Number of active tunnels */ + uint64_t ipsec_prevtunnels; /* Past number of tunnels */ + uint64_t ipsec_ipackets; /* Input IPsec packets */ + uint64_t ipsec_opackets; /* Output IPsec packets */ + uint64_t ipsec_ibytes; /* Input bytes */ + uint64_t ipsec_obytes; /* Output bytes */ + uint64_t ipsec_idecompbytes; /* Input bytes, decompressed */ + uint64_t ipsec_ouncompbytes; /* Output bytes, uncompressed */ + uint64_t ipsec_idrops; /* Dropped on input */ + uint64_t ipsec_odrops; /* Dropped on output */ + uint64_t ipsec_crypto; /* Crypto processing failure */ + uint64_t ipsec_notdb; /* No TDB was found */ + uint64_t ipsec_noxform; /* Crypto error */ + uint64_t ipsec_exctdb; /* TDBs with hardlimit excess */ +}; + +struct ipsec_level { + u_char sl_auth; /* Authentication level */ + u_char sl_esp_trans; /* ESP transport level */ + u_char sl_esp_network; /* ESP network (encapsulation) level */ + u_char sl_ipcomp; /* Compression level */ +}; + +#ifdef _KERNEL + +#include +#include +#include +#include +#include + +enum ipsec_counters { + ipsec_tunnels, + ipsec_prevtunnels, + ipsec_ipackets, + ipsec_opackets, + ipsec_ibytes, + ipsec_obytes, + ipsec_idecompbytes, + ipsec_ouncompbytes, + ipsec_idrops, + ipsec_odrops, + ipsec_crypto, + ipsec_notdb, + ipsec_noxform, + ipsec_exctdb, + ipsec_ncounters +}; + +extern struct cpumem *ipseccounters; + +static inline void +ipsecstat_inc(enum ipsec_counters c) +{ + counters_inc(ipseccounters, c); +} + +static inline void +ipsecstat_dec(enum ipsec_counters c) +{ + counters_dec(ipseccounters, c); +} + +static inline void +ipsecstat_add(enum ipsec_counters c, uint64_t v) +{ + counters_add(ipseccounters, c, v); +} + +static inline void +ipsecstat_pkt(enum ipsec_counters p, enum ipsec_counters b, uint64_t v) +{ + counters_pkt(ipseccounters, p, b, v); +} + +struct m_tag; + +#define sen_data Sen.Data +#define sen_ip_src Sen.Sip4.Src +#define sen_ip_dst Sen.Sip4.Dst +#define sen_proto Sen.Sip4.Proto +#define sen_sport Sen.Sip4.Sport +#define sen_dport Sen.Sip4.Dport +#define sen_direction Sen.Sip4.Direction +#define sen_ip6_src Sen.Sip6.Src +#define sen_ip6_dst Sen.Sip6.Dst +#define sen_ip6_proto Sen.Sip6.Proto +#define sen_ip6_sport Sen.Sip6.Sport +#define sen_ip6_dport Sen.Sip6.Dport +#define sen_ip6_direction Sen.Sip6.Direction + +/* + * The "type" is really part of the address as far as the routing + * system is concerned. By using only one bit in the type field + * for each type, we sort-of make sure that different types of + * encapsulation addresses won't be matched against the wrong type. + * + */ + +#define SENT_IP4 0x0001 /* data is two struct in_addr */ +#define SENT_IP6 0x0002 + +#define SENT_LEN sizeof(struct sockaddr_encap) + +struct ipsec_id { + u_int16_t type; /* Subtype of data */ + int16_t len; /* Length of data following */ +}; + +struct ipsec_ids { + LIST_ENTRY(ipsec_ids) id_gc_list; /* [F] */ + RBT_ENTRY(ipsec_ids) id_node_id; /* [F] */ + RBT_ENTRY(ipsec_ids) id_node_flow; /* [F] */ + struct ipsec_id *id_local; /* [I] */ + struct ipsec_id *id_remote; /* [I] */ + u_int32_t id_flow; /* [I] */ + u_int id_refcount; /* [F] */ + u_int id_gc_ttl; /* [F] */ +}; +RBT_HEAD(ipsec_ids_flows, ipsec_ids); +RBT_HEAD(ipsec_ids_tree, ipsec_ids); + +struct ipsec_acquire { + union sockaddr_union ipa_addr; + u_int32_t ipa_seq; + struct sockaddr_encap ipa_info; + struct sockaddr_encap ipa_mask; + struct refcnt ipa_refcnt; + struct timeout ipa_timeout; + struct ipsec_policy *ipa_policy; /* [A] back pointer */ + TAILQ_ENTRY(ipsec_acquire) ipa_ipo_next; /* [A] per policy */ + TAILQ_ENTRY(ipsec_acquire) ipa_next; /* [A] global list */ +}; + +TAILQ_HEAD(ipsec_acquire_head, ipsec_acquire); + +struct ipsec_policy { + struct radix_node ipo_nodes[2]; /* radix tree glue */ + struct sockaddr_encap ipo_addr; + struct sockaddr_encap ipo_mask; + + union sockaddr_union ipo_src; /* Local address to use */ + union sockaddr_union ipo_dst; /* Remote gateway -- if it's zeroed: + * - on output, we try to + * contact the remote host + * directly (if needed). + * - on input, we accept on if + * the inner source is the + * same as the outer source + * address, or if transport + * mode was used. + */ + + u_int64_t ipo_last_searched; /* [P] Timestamp of lookup */ + + u_int8_t ipo_flags; /* See IPSP_POLICY_* definitions */ + u_int8_t ipo_type; /* USE/ACQUIRE/... */ + u_int8_t ipo_sproto; /* ESP/AH; if zero, use system dflts */ + u_int ipo_rdomain; + + struct refcnt ipo_refcnt; + + struct tdb *ipo_tdb; /* [P] Cached TDB entry */ + + struct ipsec_ids *ipo_ids; + + struct ipsec_acquire_head ipo_acquires; /* [A] List of acquires */ + TAILQ_ENTRY(ipsec_policy) ipo_tdb_next; /* [P] List TDB policies */ + TAILQ_ENTRY(ipsec_policy) ipo_list; /* List of all policies */ +}; + +#define IPSP_POLICY_NONE 0x0000 /* No flags set */ +#define IPSP_POLICY_STATIC 0x0002 /* Static policy */ + +#define IPSP_IPSEC_USE 0 /* Use if existing, don't acquire */ +#define IPSP_IPSEC_ACQUIRE 1 /* Try acquire, let packet through */ +#define IPSP_IPSEC_REQUIRE 2 /* Require SA */ +#define IPSP_PERMIT 3 /* Permit traffic through */ +#define IPSP_DENY 4 /* Deny traffic */ +#define IPSP_IPSEC_DONTACQ 5 /* Require, but don't acquire */ + +/* Identity types */ +#define IPSP_IDENTITY_NONE 0 +#define IPSP_IDENTITY_PREFIX 1 +#define IPSP_IDENTITY_FQDN 2 +#define IPSP_IDENTITY_USERFQDN 3 +#define IPSP_IDENTITY_ASN1_DN 4 + +struct tdb { /* tunnel descriptor block */ + /* + * Each TDB is on three hash tables: one keyed on dst/spi/sproto, + * one keyed on dst/sproto, and one keyed on src/sproto. The first + * is used for finding a specific TDB, the second for finding TDBs + * for outgoing policy matching, and the third for incoming + * policy matching. The following three fields maintain the hash + * queues in those three tables. + */ + struct tdb *tdb_hnext; /* [D] dst/spi/sproto table */ + struct tdb *tdb_dnext; /* [D] dst/sproto table */ + struct tdb *tdb_snext; /* [D] src/sproto table */ + struct tdb *tdb_inext; + struct tdb *tdb_onext; + SIMPLEQ_ENTRY(tdb) tdb_walk; /* [N] temp list for tdb walker */ + + struct refcnt tdb_refcnt; + struct mutex tdb_mtx; + + const struct xformsw *tdb_xform; /* Transform to use */ + const struct enc_xform *tdb_encalgxform; /* Enc algorithm */ + const struct auth_hash *tdb_authalgxform; /* Auth algorithm */ + const struct comp_algo *tdb_compalgxform; /* Compression algo */ + +#define TDBF_UNIQUE 0x00001 /* This should not be used by others */ +#define TDBF_TIMER 0x00002 /* Absolute expiration timer in use */ +#define TDBF_BYTES 0x00004 /* Check the byte counters */ +#define TDBF_ALLOCATIONS 0x00008 /* Check the flows counters */ +#define TDBF_INVALID 0x00010 /* This SPI is not valid yet/anymore */ +#define TDBF_FIRSTUSE 0x00020 /* Expire after first use */ +#define TDBF_DELETED 0x00040 /* This TDB has already been deleted */ +#define TDBF_SOFT_TIMER 0x00080 /* Soft expiration */ +#define TDBF_SOFT_BYTES 0x00100 /* Soft expiration */ +#define TDBF_SOFT_ALLOCATIONS 0x00200 /* Soft expiration */ +#define TDBF_SOFT_FIRSTUSE 0x00400 /* Soft expiration */ +#define TDBF_PFS 0x00800 /* Ask for PFS from Key Mgmt. */ +#define TDBF_TUNNELING 0x01000 /* Force IP-IP encapsulation */ +#define TDBF_USEDTUNNEL 0x10000 /* Appended a tunnel header in past */ +#define TDBF_UDPENCAP 0x20000 /* UDP encapsulation */ +#define TDBF_PFSYNC 0x40000 /* TDB will be synced */ +#define TDBF_PFSYNC_RPL 0x80000 /* Replay counter should be bumped */ +#define TDBF_ESN 0x100000 /* 64-bit sequence numbers (ESN) */ +#define TDBF_PFSYNC_SNAPPED 0x200000 /* entry is being dispatched to peer */ +#define TDBF_IFACE 0x400000 /* entry policy is via sec(4) */ + +#define TDBF_BITS ("\20" \ + "\1UNIQUE\2TIMER\3BYTES\4ALLOCATIONS" \ + "\5INVALID\6FIRSTUSE\7DELETED\10SOFT_TIMER" \ + "\11SOFT_BYTES\12SOFT_ALLOCATIONS\13SOFT_FIRSTUSE\14PFS" \ + "\15TUNNELING" \ + "\21USEDTUNNEL\22UDPENCAP\23PFSYNC\24PFSYNC_RPL" \ + "\25ESN" "\26IFACE") + + u_int32_t tdb_flags; /* [m] Flags related to this TDB */ + + struct timeout tdb_timer_tmo; + struct timeout tdb_first_tmo; + struct timeout tdb_stimer_tmo; + struct timeout tdb_sfirst_tmo; + + u_int32_t tdb_seq; /* Tracking number for PFKEY */ + u_int32_t tdb_exp_allocations; /* Expire after so many flows */ + u_int32_t tdb_soft_allocations; /* Expiration warning */ + u_int32_t tdb_cur_allocations; /* Total number of allocs */ + + u_int64_t tdb_exp_bytes; /* Expire after so many bytes passed */ + u_int64_t tdb_soft_bytes; /* Expiration warning */ + u_int64_t tdb_cur_bytes; /* Current count of bytes */ + + u_int64_t tdb_exp_timeout; /* When does the SPI expire */ + u_int64_t tdb_soft_timeout; /* Send soft-expire warning */ + u_int64_t tdb_established; /* When was SPI established */ + + u_int64_t tdb_first_use; /* When was it first used */ + u_int64_t tdb_soft_first_use; /* Soft warning */ + u_int64_t tdb_exp_first_use; /* Expire if tdb_first_use + + * tdb_exp_first_use <= curtime + */ + + u_int64_t tdb_last_used; /* When was this SA last used */ + u_int64_t tdb_last_marked;/* Last SKIPCRYPTO status change */ + + struct cpumem *tdb_counters; /* stats about this TDB */ + + u_int64_t tdb_cryptoid; /* Crypto session ID */ + + u_int32_t tdb_spi; /* [I] SPI */ + u_int16_t tdb_amxkeylen; /* Raw authentication key length */ + u_int16_t tdb_emxkeylen; /* Raw encryption key length */ + u_int16_t tdb_ivlen; /* IV length */ + u_int8_t tdb_sproto; /* [I] IPsec protocol */ + u_int8_t tdb_wnd; /* Replay window */ + u_int8_t tdb_satype; /* SA type (RFC2367, PF_KEY) */ + u_int8_t tdb_iface_dir; /* [I] sec(4) iface direction */ + + union sockaddr_union tdb_dst; /* [N] Destination address */ + union sockaddr_union tdb_src; /* [N] Source address */ + + u_int8_t *tdb_amxkey; /* Raw authentication key */ + u_int8_t *tdb_emxkey; /* Raw encryption key */ + +#define TDB_REPLAYWASTE 32 +#define TDB_REPLAYMAX (2100+TDB_REPLAYWASTE) + + u_int64_t tdb_rpl; /* Replay counter */ + u_int32_t tdb_seen[howmany(TDB_REPLAYMAX, 32)]; /* Anti-replay window */ + + u_int8_t tdb_iv[4]; /* Used for HALF-IV ESP */ + + struct ipsec_ids *tdb_ids; /* Src/Dst ID for this SA */ + int tdb_ids_swapped; /* XXX */ + + u_int32_t tdb_mtu; /* MTU at this point in the chain */ + u_int64_t tdb_mtutimeout; /* When to ignore this entry */ + + u_int16_t tdb_udpencap_port; /* Peer UDP port */ + + u_int16_t tdb_tag; /* Packet filter tag */ + u_int32_t tdb_tap; /* Alternate enc(4) interface */ + unsigned int tdb_iface; /* [I] sec(4) iface */ + + u_int tdb_rdomain; /* [I] Routing domain */ + u_int tdb_rdomain_post; /* [I] Change domain */ + + struct sockaddr_encap tdb_filter; /* What traffic is acceptable */ + struct sockaddr_encap tdb_filtermask; /* And the mask */ + + TAILQ_HEAD(tdb_policy_head, ipsec_policy) tdb_policy_head; /* [P] */ + TAILQ_ENTRY(tdb) tdb_sync_entry; /* [S] pfsync tdb queue */ + u_int32_t tdb_updates; /* [S] pfsync update counter */ +}; + +enum tdb_counters { + tdb_ipackets, /* Input IPsec packets */ + tdb_opackets, /* Output IPsec packets */ + tdb_ibytes, /* Input bytes */ + tdb_obytes, /* Output bytes */ + tdb_idrops, /* Dropped on input */ + tdb_odrops, /* Dropped on output */ + tdb_idecompbytes, /* Input bytes, decompressed */ + tdb_ouncompbytes, /* Output bytes, uncompressed */ + tdb_ncounters +}; + +static inline void +tdbstat_inc(struct tdb *tdb, enum tdb_counters c) +{ + counters_inc(tdb->tdb_counters, c); +} + +static inline void +tdbstat_add(struct tdb *tdb, enum tdb_counters c, uint64_t v) +{ + counters_add(tdb->tdb_counters, c, v); +} + +static inline void +tdbstat_pkt(struct tdb *tdb, enum tdb_counters pc, enum tdb_counters bc, + uint64_t bytes) +{ + counters_pkt(tdb->tdb_counters, pc, bc, bytes); +} + +struct tdb_ident { + u_int32_t spi; + union sockaddr_union dst; + u_int8_t proto; + u_int rdomain; +}; + +struct tdb_crypto { + union sockaddr_union tc_dst; + u_int64_t tc_rpl; + u_int32_t tc_spi; + int tc_protoff; + int tc_skip; + u_int tc_rdomain; + u_int8_t tc_proto; +}; + +struct ipsecinit { + u_int8_t *ii_enckey; + u_int8_t *ii_authkey; + u_int16_t ii_enckeylen; + u_int16_t ii_authkeylen; + u_int8_t ii_encalg; + u_int8_t ii_authalg; + u_int8_t ii_compalg; +}; + +/* xform IDs */ +#define XF_IP4 1 /* IP inside IP */ +#define XF_AH 2 /* AH */ +#define XF_ESP 3 /* ESP */ +#define XF_TCPSIGNATURE 5 /* TCP MD5 Signature option, RFC 2358 */ +#define XF_IPCOMP 6 /* IPCOMP */ + +/* xform attributes */ +#define XFT_AUTH 0x0001 +#define XFT_CONF 0x0100 +#define XFT_COMP 0x1000 + +#define IPSEC_ZEROES_SIZE 256 /* Larger than an IP6 extension hdr. */ + +struct xformsw { + u_short xf_type; /* Unique ID of xform */ + u_short xf_flags; /* flags (see below) */ + char *xf_name; /* human-readable name */ + int (*xf_attach)(void); /* called at config time */ + int (*xf_init)(struct tdb *, const struct xformsw *, + struct ipsecinit *); + int (*xf_zeroize)(struct tdb *); /* termination */ + int (*xf_input)(struct mbuf **, struct tdb *, int, int, + struct netstack *); + int (*xf_output)(struct mbuf *, struct tdb *, int, int); +}; + +extern int ipsec_in_use; +extern u_int64_t ipsec_last_added; +extern int encdebug; /* enable message reporting */ +extern struct pool tdb_pool; + +extern int ipsec_keep_invalid; /* lifetime of embryonic SAs (in sec) */ +extern int ipsec_require_pfs; /* use Perfect Forward Secrecy */ +extern int ipsec_expire_acquire; /* wait for security assoc. (in sec) */ +extern int ipsec_soft_allocations; /* flows/SA before renegotiation */ +extern int ipsec_exp_allocations; /* num. of flows/SA before it expires */ +extern int ipsec_soft_bytes; /* bytes/SA before renegotiation */ +extern int ipsec_exp_bytes; /* num of bytes/SA before it expires */ +extern int ipsec_soft_timeout; /* seconds/SA before renegotiation */ +extern int ipsec_exp_timeout; /* seconds/SA before it expires */ +extern int ipsec_soft_first_use; /* seconds between 1st asso & renego */ +extern int ipsec_exp_first_use; /* seconds between 1st asso & expire */ + +/* + * Names for IPsec sysctl objects + */ +#define IPSEC_ENCDEBUG IPCTL_ENCDEBUG /* 12 */ +#define IPSEC_STATS IPCTL_IPSEC_STATS /* 13 */ +#define IPSEC_EXPIRE_ACQUIRE IPCTL_IPSEC_EXPIRE_ACQUIRE /* 14 */ +#define IPSEC_EMBRYONIC_SA_TIMEOUT IPCTL_IPSEC_EMBRYONIC_SA_TIMEOUT/* 15 */ +#define IPSEC_REQUIRE_PFS IPCTL_IPSEC_REQUIRE_PFS /* 16 */ +#define IPSEC_SOFT_ALLOCATIONS IPCTL_IPSEC_SOFT_ALLOCATIONS /* 17 */ +#define IPSEC_ALLOCATIONS IPCTL_IPSEC_ALLOCATIONS /* 18 */ +#define IPSEC_SOFT_BYTES IPCTL_IPSEC_SOFT_BYTES /* 19 */ +#define IPSEC_BYTES IPCTL_IPSEC_BYTES /* 20 */ +#define IPSEC_TIMEOUT IPCTL_IPSEC_TIMEOUT /* 21 */ +#define IPSEC_SOFT_TIMEOUT IPCTL_IPSEC_SOFT_TIMEOUT /* 22 */ +#define IPSEC_SOFT_FIRSTUSE IPCTL_IPSEC_SOFT_FIRSTUSE /* 23 */ +#define IPSEC_FIRSTUSE IPCTL_IPSEC_FIRSTUSE /* 24 */ +#define IPSEC_MAXID 25 + +enum { + IPSEC_ENC_AES, + IPSEC_ENC_AESCTR, + IPSEC_ENC_3DES, + IPSEC_ENC_BLOWFISH, + IPSEC_ENC_CAST128, +}; + +enum { + IPSEC_AUTH_HMAC_SHA1, + IPSEC_AUTH_HMAC_RIPEMD160, + IPSEC_AUTH_MD5, + IPSEC_AUTH_SHA2_256, + IPSEC_AUTH_SHA2_384, + IPSEC_AUTH_SHA2_512, +}; + +enum { + IPSEC_COMP_DEFLATE, +}; + +extern int ipsec_def_enc; +extern int ipsec_def_auth; +extern int ipsec_def_comp; + +extern TAILQ_HEAD(ipsec_policy_head, ipsec_policy) ipsec_policy_head; + +extern struct mutex tdb_sadb_mtx; +extern struct mutex ipo_tdb_mtx; + +struct cryptop; + +/* Misc. */ +const char *ipsp_address(union sockaddr_union *, char *, socklen_t); + +/* SPD tables */ +struct radix_node_head *spd_table_add(unsigned int); +struct radix_node_head *spd_table_get(unsigned int); +int spd_table_walk(unsigned int, + int (*walker)(struct ipsec_policy *, void *, unsigned int), void *); + +/* TDB management routines */ +uint32_t reserve_spi(u_int, u_int32_t, u_int32_t, union sockaddr_union *, + union sockaddr_union *, u_int8_t, int *); +struct tdb *gettdb_dir(u_int, u_int32_t, union sockaddr_union *, u_int8_t, int); +#define gettdb(a,b,c,d) gettdb_dir((a),(b),(c),(d),0) +#define gettdb_rev(a,b,c,d) gettdb_dir((a),(b),(c),(d),1) +struct tdb *gettdbbydst(u_int, union sockaddr_union *, u_int8_t, + struct ipsec_ids *, + struct sockaddr_encap *, struct sockaddr_encap *); +struct tdb *gettdbbysrc(u_int, union sockaddr_union *, u_int8_t, + struct ipsec_ids *, + struct sockaddr_encap *, struct sockaddr_encap *); +struct tdb *gettdbbysrcdst_dir(u_int, u_int32_t, union sockaddr_union *, + union sockaddr_union *, u_int8_t, int); +#define gettdbbysrcdst(a,b,c,d,e) gettdbbysrcdst_dir((a),(b),(c),(d),(e),0) +#define gettdbbysrcdst_rev(a,b,c,d,e) gettdbbysrcdst_dir((a),(b),(c),(d),(e),1) +void puttdb(struct tdb *); +void puttdb_locked(struct tdb *); +void tdb_delete(struct tdb *); +struct tdb *tdb_alloc(u_int); +struct tdb *tdb_ref(struct tdb *); +void tdb_unref(struct tdb *); +void tdb_free(struct tdb *); +int tdb_init(struct tdb *, u_int16_t, struct ipsecinit *); +void tdb_unlink(struct tdb *); +void tdb_unlink_locked(struct tdb *); +void tdb_cleanspd(struct tdb *); +void tdb_unbundle(struct tdb *); +void tdb_addtimeouts(struct tdb *); +void tdb_deltimeouts(struct tdb *); +int tdb_walk(u_int, int (*)(struct tdb *, void *, int), void *); +void tdb_printit(void *, int, int (*)(const char *, ...)); + +/* XF_IP4 */ +int ipe4_attach(void); +int ipe4_init(struct tdb *, const struct xformsw *, struct ipsecinit *); +int ipe4_zeroize(struct tdb *); +int ipe4_input(struct mbuf **, struct tdb *, int, int, struct netstack *); + +/* XF_AH */ +int ah_attach(void); +int ah_init(struct tdb *, const struct xformsw *, struct ipsecinit *); +int ah_zeroize(struct tdb *); +int ah_input(struct mbuf **, struct tdb *, int, int, struct netstack *); +int ah_output(struct mbuf *, struct tdb *, int, int); +int ah_sysctl(int *, u_int, void *, size_t *, void *, size_t); + +int ah46_input(struct mbuf **, int *, int, int, struct netstack *); +void ah4_ctlinput(int, struct sockaddr *, u_int, void *); +void udpencap_ctlinput(int, struct sockaddr *, u_int, void *); + +/* XF_ESP */ +int esp_attach(void); +int esp_init(struct tdb *, const struct xformsw *, struct ipsecinit *); +int esp_zeroize(struct tdb *); +int esp_input(struct mbuf **, struct tdb *, int, int, struct netstack *); +int esp_output(struct mbuf *, struct tdb *, int, int); +int esp_sysctl(int *, u_int, void *, size_t *, void *, size_t); + +int esp46_input(struct mbuf **, int *, int, int, struct netstack *); +void esp4_ctlinput(int, struct sockaddr *, u_int, void *); + +/* XF_IPCOMP */ +int ipcomp_attach(void); +int ipcomp_init(struct tdb *, const struct xformsw *, struct ipsecinit *); +int ipcomp_zeroize(struct tdb *); +int ipcomp_input(struct mbuf **, struct tdb *, int, int, struct netstack *); +int ipcomp_output(struct mbuf *, struct tdb *, int, int); +int ipcomp_sysctl(int *, u_int, void *, size_t *, void *, size_t); +int ipcomp46_input(struct mbuf **, int *, int, int, struct netstack *); + +/* XF_TCPSIGNATURE */ +int tcp_signature_tdb_attach(void); +int tcp_signature_tdb_init(struct tdb *, const struct xformsw *, + struct ipsecinit *); +int tcp_signature_tdb_zeroize(struct tdb *); +int tcp_signature_tdb_input(struct mbuf **, struct tdb *, int, int, + struct netstack *); +int tcp_signature_tdb_output(struct mbuf *, struct tdb *, int, int); + +/* Replay window */ +int checkreplaywindow(struct tdb *, u_int64_t, u_int32_t, u_int32_t *, int); + +/* Packet processing */ +#define IPSP_DF_INHERIT -1 +#define IPSP_DF_OFF 0 +#define IPSP_DF_ON 1 + +int ipsp_process_packet(struct mbuf *, struct tdb *, int, int, int); +int ipsp_process_done(struct mbuf *, struct tdb *); +int ipsp_spd_lookup(struct mbuf *, int, int, int, struct tdb *, + const struct ipsec_level *, struct tdb **, struct ipsec_ids *); +int ipsp_is_unspecified(union sockaddr_union); +int ipsp_aux_match(struct tdb *, struct ipsec_ids *, + struct sockaddr_encap *, struct sockaddr_encap *); +int ipsp_ids_match(struct ipsec_ids *, struct ipsec_ids *); +struct ipsec_ids *ipsp_ids_insert(struct ipsec_ids *); +struct ipsec_ids *ipsp_ids_lookup(u_int32_t); +void ipsp_ids_free(struct ipsec_ids *); + +void ipsp_init(void); +void ipsec_init(void); +int ipsec_sysctl(int *, u_int, void *, size_t *, void *, size_t); +int ipsec_common_input(struct mbuf **, int, int, int, int, int, + struct netstack *); +int ipsec_common_input_cb(struct mbuf **, struct tdb *, int, int, + struct netstack *); +int ipsec_input_disabled(struct mbuf **, int *, int, int, + struct netstack *); +int ipsec_protoff(struct mbuf *, int, int); +int ipsec_delete_policy(struct ipsec_policy *); +ssize_t ipsec_hdrsz(struct tdb *); +void ipsec_adjust_mtu(struct mbuf *, u_int32_t); +void ipsec_set_mtu(struct tdb *, u_int32_t); +struct ipsec_acquire *ipsec_get_acquire(u_int32_t); +void ipsec_unref_acquire(struct ipsec_acquire *); +int ipsec_forward_check(struct mbuf *, int, int); +int ipsec_local_check(struct mbuf *, int, int, int); + +#endif /* _KERNEL */ +#endif /* _NETINET_IPSP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/ip_mroute.h b/lib/libc/include/generic-openbsd/netinet/ip_mroute.h new file mode 100644 index 000000000000..d800b3c872b1 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/ip_mroute.h @@ -0,0 +1,261 @@ +/* $OpenBSD: ip_mroute.h,v 1.34 2025/05/09 14:43:47 jan Exp $ */ +/* $NetBSD: ip_mroute.h,v 1.23 2004/04/21 17:49:46 itojun Exp $ */ + +#ifndef _NETINET_IP_MROUTE_H_ +#define _NETINET_IP_MROUTE_H_ + +/* + * Definitions for IP multicast forwarding. + * + * Written by David Waitzman, BBN Labs, August 1988. + * Modified by Steve Deering, Stanford, February 1989. + * Modified by Ajit Thyagarajan, PARC, August 1993. + * Modified by Ajit Thyagarajan, PARC, August 1994. + * Modified by Ahmed Helmy, SGI, June 1996. + * Modified by Pavlin Radoslavov, ICSI, October 2002. + * + * MROUTING Revision: 1.2 + * advanced API support, bandwidth metering and signaling. + */ + +/* + * Multicast Routing set/getsockopt commands. + */ +#define MRT_INIT 100 /* initialize forwarder */ +#define MRT_DONE 101 /* shut down forwarder */ +#define MRT_ADD_VIF 102 /* create virtual interface */ +#define MRT_DEL_VIF 103 /* delete virtual interface */ +#define MRT_ADD_MFC 104 /* insert forwarding cache entry */ +#define MRT_DEL_MFC 105 /* delete forwarding cache entry */ +#define MRT_VERSION 106 /* get kernel version number */ +#define MRT_ASSERT 107 /* enable assert processing */ +#define MRT_API_SUPPORT 109 /* supported MRT API */ +#define MRT_API_CONFIG 110 /* config MRT API */ + +/* + * Types and macros for handling bitmaps with one bit per virtual interface. + */ +#define MAXVIFS 32 +typedef u_int32_t vifbitmap_t; +typedef u_int16_t vifi_t; /* type of a vif index */ + +#define VIFM_SET(n, m) ((m) |= (1 << (n))) +#define VIFM_CLR(n, m) ((m) &= ~(1 << (n))) +#define VIFM_ISSET(n, m) ((m) & (1 << (n))) +#define VIFM_CLRALL(m) ((m) = 0x00000000) +#define VIFM_COPY(mfrom, mto) ((mto) = (mfrom)) +#define VIFM_SAME(m1, m2) ((m1) == (m2)) + +#define VIFF_TUNNEL 0x1 /* vif represents a tunnel end-point */ +#define VIFF_SRCRT 0x2 /* tunnel uses IP src routing */ + +/* + * Argument structure for MRT_ADD_VIF. + * (MRT_DEL_VIF takes a single vifi_t argument.) + */ +struct vifctl { + vifi_t vifc_vifi; /* the index of the vif to be added */ + u_int8_t vifc_flags; /* VIFF_ flags defined above */ + u_int8_t vifc_threshold; /* min ttl required to forward on vif */ + u_int32_t vifc_rate_limit; /* ignored */ + struct in_addr vifc_lcl_addr;/* local interface address */ + struct in_addr vifc_rmt_addr;/* remote address (tunnels only) */ +}; + +/* + * Argument structure for MRT_ADD_MFC and MRT_DEL_MFC. + * XXX if you change this, make sure to change struct mfcctl2 as well. + */ +struct mfcctl { + struct in_addr mfcc_origin; /* ip origin of mcasts */ + struct in_addr mfcc_mcastgrp; /* multicast group associated */ + vifi_t mfcc_parent; /* incoming vif */ + u_int8_t mfcc_ttls[MAXVIFS]; /* forwarding ttls on vifs */ +}; + +/* + * The new argument structure for MRT_ADD_MFC and MRT_DEL_MFC overlays + * and extends the old struct mfcctl. + */ +struct mfcctl2 { + /* the mfcctl fields */ + struct in_addr mfcc_origin; /* ip origin of mcasts */ + struct in_addr mfcc_mcastgrp; /* multicast group associated*/ + vifi_t mfcc_parent; /* incoming vif */ + u_int8_t mfcc_ttls[MAXVIFS]; /* forwarding ttls on vifs */ + + /* extension fields */ + u_int8_t mfcc_flags[MAXVIFS]; /* the MRT_MFC_FLAGS_* flags */ + struct in_addr mfcc_rp; /* the RP address */ +}; +/* + * The advanced-API flags. + * + * The MRT_MFC_FLAGS_XXX API flags are also used as flags + * for the mfcc_flags field. + */ +#define MRT_MFC_FLAGS_DISABLE_WRONGVIF (1 << 0) /* disable WRONGVIF signals */ +#define MRT_MFC_RP (1 << 8) /* enable RP address */ +#define MRT_MFC_BW_UPCALL (1 << 9) /* enable bw upcalls */ +#define MRT_MFC_FLAGS_ALL (MRT_MFC_FLAGS_DISABLE_WRONGVIF) +#define MRT_API_FLAGS_ALL (MRT_MFC_FLAGS_ALL | \ + MRT_MFC_RP | \ + MRT_MFC_BW_UPCALL) + +/* structure used to get all the mfc entries */ +struct mfcinfo { + struct in_addr mfc_origin; /* ip origin of mcasts */ + struct in_addr mfc_mcastgrp; /* multicast group associated */ + vifi_t mfc_parent; /* incoming vif */ + u_long mfc_pkt_cnt; /* pkt count for src-grp */ + u_long mfc_byte_cnt; /* byte count for src-grp */ + u_int8_t mfc_ttls[MAXVIFS]; /* forwarding ttls on vifs */ +}; + +/* structure used to get all the vif entries */ +struct vifinfo { + vifi_t v_vifi; /* the index of the vif to be added */ + u_int8_t v_flags; /* VIFF_ flags defined above */ + u_int8_t v_threshold; /* min ttl required to forward on vif */ + struct in_addr v_lcl_addr; /* local interface address */ + struct in_addr v_rmt_addr; /* remote address (tunnels only) */ + u_long v_pkt_in; /* # pkts in on interface */ + u_long v_pkt_out; /* # pkts out on interface */ + u_long v_bytes_in; /* # bytes in on interface */ + u_long v_bytes_out; /* # bytes out on interface */ +}; + +/* + * Argument structure used by mrouted to get src-grp pkt counts. + */ +struct sioc_sg_req { + struct in_addr src; + struct in_addr grp; + u_long pktcnt; + u_long bytecnt; + u_long wrong_if; +}; + +/* + * Argument structure used by mrouted to get vif pkt counts. + */ +struct sioc_vif_req { + vifi_t vifi; /* vif number */ + u_long icount; /* input packet count on vif */ + u_long ocount; /* output packet count on vif */ + u_long ibytes; /* input byte count on vif */ + u_long obytes; /* output byte count on vif */ +}; + + +/* + * The kernel's multicast routing statistics. + */ +struct mrtstat { + u_long mrts_mfc_lookups; /* # forw. cache hash table hits */ + u_long mrts_mfc_misses; /* # forw. cache hash table misses */ + u_long mrts_upcalls; /* # calls to mrouted */ + u_long mrts_no_route; /* no route for packet's origin */ + u_long mrts_bad_tunnel; /* malformed tunnel options */ + u_long mrts_cant_tunnel; /* no room for tunnel options */ + u_long mrts_wrong_if; /* arrived on wrong interface */ + u_long mrts_upq_ovflw; /* upcall Q overflow */ + u_long mrts_cache_cleanups; /* # entries with no upcalls */ + u_long mrts_drop_sel; /* pkts dropped selectively */ + u_long mrts_q_overflow; /* pkts dropped - Q overflow */ + u_long mrts_pkt2large; /* pkts dropped - size > BKT SIZE */ + u_long mrts_upq_sockfull; /* upcalls dropped - socket full */ +}; + +#ifdef _KERNEL + +enum mrtstat_counters { + mrts_mfc_lookups, + mrts_mfc_misses, + mrts_upcalls, + mrts_no_route, + mrts_bad_tunnel, + mrts_cant_tunnel, + mrts_wrong_if, + mrts_upq_ovflw, + mrts_cache_cleanups, + mrts_drop_sel, + mrts_q_overflow, + mrts_pkt2large, + mrts_upq_sockfull, + mrts_ncounters +}; + +extern struct cpumem *mrtcounters; + +static inline void +mrtstat_inc(enum mrtstat_counters c) +{ + counters_inc(mrtcounters, c); +} + +/* How frequent should we look for expired entries (in seconds). */ +#define MCAST_EXPIRE_FREQUENCY 30 + +extern int ip_mrtproto; + +/* + * The kernel's virtual-interface structure. + */ +struct vif { + vifi_t v_id; /* Virtual interface index */ + u_int8_t v_flags; /* VIFF_ flags defined above */ + u_int8_t v_threshold; /* min ttl required to forward on vif */ + struct in_addr v_lcl_addr; /* local interface address */ + struct in_addr v_rmt_addr; /* remote address (tunnels only) */ + u_long v_pkt_in; /* # pkts in on interface */ + u_long v_pkt_out; /* # pkts out on interface */ + u_long v_bytes_in; /* # bytes in on interface */ + u_long v_bytes_out; /* # bytes out on interface */ +}; + +/* + * The kernel's multicast forwarding cache entry structure. + * (A field for the type of service (mfc_tos) is to be added + * at a future point.) + */ +struct mfc { + vifi_t mfc_parent; /* incoming vif */ + u_long mfc_pkt_cnt; /* pkt count for src-grp */ + u_long mfc_byte_cnt; /* byte count for src-grp */ + u_long mfc_wrong_if; /* wrong if for src-grp */ + uint8_t mfc_ttl; /* route interface ttl */ + uint8_t mfc_flags; /* MRT_MFC_FLAGS_* flags */ + struct in_addr mfc_rp; /* the RP address */ + u_long mfc_expire; /* expire timer */ +}; + +/* + * Structure used to communicate from kernel to multicast router. + * (Note the convenient similarity to an IP packet.) + */ +struct igmpmsg { + u_int32_t unused1; + u_int32_t unused2; + u_int8_t im_msgtype; /* what type of message */ +#define IGMPMSG_NOCACHE 1 /* no MFC in the kernel */ +#define IGMPMSG_WRONGVIF 2 /* packet came from wrong interface */ +#define IGMPMSG_BW_UPCALL 4 /* BW monitoring upcall */ + u_int8_t im_mbz; /* must be zero */ + u_int8_t im_vif; /* vif rec'd on */ + u_int8_t unused3; + struct in_addr im_src, im_dst; +}; + +int ip_mrouter_set(struct socket *, int, struct mbuf *); +int ip_mrouter_get(struct socket *, int, struct mbuf *); +void mrt_init(void); +int mrt_ioctl(struct socket *, u_long, caddr_t); +int mrt_sysctl_vif(void *, size_t *); +int mrt_sysctl_mrtstat(void *, size_t *, void *); +int mrt_sysctl_mfc(void *, size_t *); +int ip_mrouter_done(struct socket *); +void vif_delete(struct ifnet *); + +#endif /* _KERNEL */ +#endif /* _NETINET_IP_MROUTE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/ip_var.h b/lib/libc/include/generic-openbsd/netinet/ip_var.h new file mode 100644 index 000000000000..69ef765c4f46 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/ip_var.h @@ -0,0 +1,289 @@ +/* $OpenBSD: ip_var.h,v 1.123 2025/07/31 09:05:11 mvs Exp $ */ +/* $NetBSD: ip_var.h,v 1.16 1996/02/13 23:43:20 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ip_var.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_IP_VAR_H_ +#define _NETINET_IP_VAR_H_ + +/* + * Structure stored in mbuf in inpcb.ip_options + * and passed to ip_output when ip options are in use. + * The actual length of the options (including ipopt_dst) + * is in m_len. + */ +#define MAX_IPOPTLEN 40 + +/* + * Overlay for ip header used by other protocols (tcp, udp). + */ +struct ipovly { + u_int8_t ih_x1[9]; /* (unused) */ + u_int8_t ih_pr; /* protocol */ + u_int16_t ih_len; /* protocol length */ + struct in_addr ih_src; /* source internet address */ + struct in_addr ih_dst; /* destination internet address */ +}; + +struct ipstat { + u_long ips_total; /* total packets received */ + u_long ips_badsum; /* checksum bad */ + u_long ips_tooshort; /* packet too short */ + u_long ips_toosmall; /* not enough data */ + u_long ips_badhlen; /* ip header length < data size */ + u_long ips_badlen; /* ip length < ip header length */ + u_long ips_fragments; /* fragments received */ + u_long ips_fragdropped; /* frags dropped (dups, out of space) */ + u_long ips_fragtimeout; /* fragments timed out */ + u_long ips_forward; /* packets forwarded */ + u_long ips_cantforward; /* packets rcvd for unreachable dest */ + u_long ips_redirectsent; /* packets forwarded on same net */ + u_long ips_noproto; /* unknown or unsupported protocol */ + u_long ips_delivered; /* datagrams delivered to upper level*/ + u_long ips_localout; /* total ip packets generated here */ + u_long ips_odropped; /* lost output due to nobufs, etc. */ + u_long ips_reassembled; /* total packets reassembled ok */ + u_long ips_fragmented; /* datagrams successfully fragmented */ + u_long ips_ofragments; /* output fragments created */ + u_long ips_cantfrag; /* don't fragment flag was set, etc. */ + u_long ips_badoptions; /* error in option processing */ + u_long ips_noroute; /* packets discarded due to no route */ + u_long ips_badvers; /* ip version != 4 */ + u_long ips_rawout; /* total raw ip packets generated */ + u_long ips_badfrags; /* malformed fragments (bad length) */ + u_long ips_rcvmemdrop; /* frags dropped for lack of memory */ + u_long ips_toolong; /* ip length > max ip packet size */ + u_long ips_nogif; /* no match gif found */ + u_long ips_badaddr; /* invalid address on header */ + u_long ips_inswcsum; /* software checksummed on input */ + u_long ips_outswcsum; /* software checksummed on output */ + u_long ips_notmember; /* multicasts for unregistered groups */ + u_long ips_rtcachehit; /* valid route found in cache */ + u_long ips_rtcachemiss; /* route cache with new destination */ + u_long ips_wrongif; /* packet received on wrong interface */ + u_long ips_idropped; /* lost input due to nobufs, etc. */ +}; + +struct ipoption { + struct in_addr ipopt_dst; /* first-hop dst if source routed */ + int8_t ipopt_list[MAX_IPOPTLEN]; /* options proper */ +}; + +#ifdef _KERNEL + +#include + +enum ipstat_counters { + ips_total, /* total packets received */ + ips_badsum, /* checksum bad */ + ips_tooshort, /* packet too short */ + ips_toosmall, /* not enough data */ + ips_badhlen, /* ip header length < data size */ + ips_badlen, /* ip length < ip header length */ + ips_fragments, /* fragments received */ + ips_fragdropped, /* frags dropped (dups, out of space) */ + ips_fragtimeout, /* fragments timed out */ + ips_forward, /* packets forwarded */ + ips_cantforward, /* packets rcvd for unreachable dest */ + ips_redirectsent, /* packets forwarded on same net */ + ips_noproto, /* unknown or unsupported protocol */ + ips_delivered, /* datagrams delivered to upper level*/ + ips_localout, /* total ip packets generated here */ + ips_odropped, /* lost output packets due to nobufs, etc. */ + ips_reassembled, /* total packets reassembled ok */ + ips_fragmented, /* datagrams successfully fragmented */ + ips_ofragments, /* output fragments created */ + ips_cantfrag, /* don't fragment flag was set, etc. */ + ips_badoptions, /* error in option processing */ + ips_noroute, /* packets discarded due to no route */ + ips_badvers, /* ip version != 4 */ + ips_rawout, /* total raw ip packets generated */ + ips_badfrags, /* malformed fragments (bad length) */ + ips_rcvmemdrop, /* frags dropped for lack of memory */ + ips_toolong, /* ip length > max ip packet size */ + ips_nogif, /* no match gif found */ + ips_badaddr, /* invalid address on header */ + ips_inswcsum, /* software checksummed on input */ + ips_outswcsum, /* software checksummed on output */ + ips_notmember, /* multicasts for unregistered groups */ + ips_rtcachehit, /* valid route to destination found in cache */ + ips_rtcachemiss, /* route cache filled with new destination */ + ips_wrongif, /* packet received on wrong interface */ + ips_idropped, /* lost input packets due to nobufs, etc. */ + + ips_ncounters +}; + +extern struct cpumem *ipcounters; + +static inline void +ipstat_inc(enum ipstat_counters c) +{ + counters_inc(ipcounters, c); +} + +static inline void +ipstat_add(enum ipstat_counters c, uint64_t v) +{ + counters_add(ipcounters, c, v); +} + +/* + * Structure attached to inpcb.ip_moptions and + * passed to ip_output when IP multicast options are in use. + */ +struct ip_moptions { + struct in_multi **imo_membership; /* group memberships */ + unsigned short imo_ifidx; /* ifp index for outgoing multicasts */ + u_int8_t imo_ttl; /* TTL for outgoing multicasts */ + u_int8_t imo_loop; /* 1 => hear sends if a member */ + u_int16_t imo_num_memberships; /* no. memberships this socket */ + u_int16_t imo_max_memberships; /* max memberships this socket */ +}; + +#include + +/* + * Ip reassembly queue structures. + */ +LIST_HEAD(ipqehead, ipqent); +struct ipqent { + LIST_ENTRY(ipqent) ipqe_q; + struct ip *ipqe_ip; + struct mbuf *ipqe_m; /* mbuf contains packet */ + uint16_t ipqe_mff; /* for IP fragmentation */ +}; + +/* + * Ip reassembly queue structure. Each fragment + * being reassembled is attached to one of these structures. + * They are timed out after ipq_ttl drops to 0, and may also + * be reclaimed if memory becomes tight. + */ +struct ipq { + LIST_ENTRY(ipq) ipq_q; /* to other reass headers */ + u_int8_t ipq_ttl; /* time for reass q to live */ + u_int8_t ipq_p; /* protocol of this fragment */ + u_int16_t ipq_id; /* sequence id for reassembly */ + struct ipqehead ipq_fragq; /* to ip fragment queue */ + struct in_addr ipq_src, ipq_dst; +}; + +struct ipoffnxt { + int ion_off; + int ion_nxt; +}; + +/* flags passed to ip_output */ +#define IP_FORWARDING 0x0001 /* most of ip header exists */ +#define IP_RAWOUTPUT 0x0002 /* raw ip header exists */ +#define IP_REDIRECT 0x0004 /* redirected by pf or source route */ +#define IP_FORWARDING_IPSEC 0x0008 /* only packets processed by IPsec */ +#define IP_ALLOWBROADCAST SO_BROADCAST /* can send broadcast packets */ +#define IP_MTUDISC 0x0800 /* pmtu discovery, set DF */ + +extern struct ipstat ipstat; +extern int ip_defttl; /* default IP ttl */ + +#define IPMTUDISCTIMEOUT (10 * 60) /* as per RFC 1191 */ + +extern int ip_mtudisc; /* mtu discovery */ +extern int ip_mtudisc_timeout; /* seconds to timeout mtu discovery */ + +extern int ipport_firstauto; /* min port for port allocation */ +extern int ipport_lastauto; /* max port for port allocation */ +extern int ipport_hifirstauto; /* min dynamic/private port number */ +extern int ipport_hilastauto; /* max dynamic/private port number */ +extern int ip_forwarding; /* enable IP forwarding */ +#ifdef MROUTING +extern int ipmforwarding; /* enable multicast forwarding */ +#endif +extern int ipmultipath; /* enable multipath routing */ +extern int ip_directedbcast; /* accept all broadcast packets */ +extern unsigned int la_hold_total; + +extern const struct pr_usrreqs rip_usrreqs; + +extern struct rttimer_queue ip_mtudisc_timeout_q; +extern struct pool ipqent_pool; +struct rtentry; +struct route; +struct inpcb; +struct ipsec_level; + +int ip_ctloutput(int, struct socket *, int, int, struct mbuf *); +int ip_fragment(struct mbuf *, struct mbuf_list *, struct ifnet *, u_long); +void ip_freemoptions(struct ip_moptions *); +int ip_getmoptions(int, struct ip_moptions *, struct mbuf *); +void ip_init(void); +struct mbuf* + ip_insertoptions(struct mbuf *, struct mbuf *, int *); +int ip_mforward(struct mbuf *, struct ifnet *, int); +int ip_optcopy(struct ip *, struct ip *); +int ip_output(struct mbuf *, struct mbuf *, struct route *, int, + struct ip_moptions *, const struct ipsec_level *, u_int32_t); +u_int16_t + ip_randomid(void); +void ip_send(struct mbuf *); +void ip_send_raw(struct mbuf *); +void ip_slowtimo(void); +struct mbuf * + ip_srcroute(struct mbuf *); +void ip_stripoptions(struct mbuf *); +int ip_sysctl(int *, u_int, void *, size_t *, void *, size_t); +void ip_savecontrol(struct inpcb *, struct mbuf **, struct ip *, + struct mbuf *); +int ip_input_if(struct mbuf **, int *, int, int, struct ifnet *, + struct netstack *); +int ip_deliver(struct mbuf **, int *, int, int, int, struct netstack *); +void ip_forward(struct mbuf *, struct ifnet *, struct route *, int); +int rip_ctloutput(int, struct socket *, int, int, struct mbuf *); +void rip_init(void); +int rip_input(struct mbuf **, int *, int, int, struct netstack *); +int rip_output(struct mbuf *, struct socket *, struct sockaddr *, + struct mbuf *); +struct mbuf * + rip_chkhdr(struct mbuf *, struct mbuf *); +int rip_attach(struct socket *, int, int); +int rip_detach(struct socket *); +int rip_bind(struct socket *, struct mbuf *, struct proc *); +int rip_connect(struct socket *, struct mbuf *); +int rip_disconnect(struct socket *); +int rip_shutdown(struct socket *); +int rip_send(struct socket *, struct mbuf *, struct mbuf *, + struct mbuf *); +#ifdef MROUTING +extern struct socket *ip_mrouter[]; /* multicast routing daemon */ +#endif + +#endif /* _KERNEL */ +#endif /* _NETINET_IP_VAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/tcp.h b/lib/libc/include/generic-openbsd/netinet/tcp.h new file mode 100644 index 000000000000..a1eae184a419 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/tcp.h @@ -0,0 +1,222 @@ +/* $OpenBSD: tcp.h,v 1.24 2023/05/19 01:04:39 guenther Exp $ */ +/* $NetBSD: tcp.h,v 1.8 1995/04/17 05:32:58 cgd Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tcp.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_TCP_H_ +#define _NETINET_TCP_H_ + +#include + +#if __BSD_VISIBLE + +typedef u_int32_t tcp_seq; + +/* + * TCP header. + * Per RFC 793, September, 1981. + */ +struct tcphdr { + u_int16_t th_sport; /* source port */ + u_int16_t th_dport; /* destination port */ + tcp_seq th_seq; /* sequence number */ + tcp_seq th_ack; /* acknowledgement number */ +#if _BYTE_ORDER == _LITTLE_ENDIAN + u_int32_t th_x2:4, /* (unused) */ + th_off:4; /* data offset */ +#endif +#if _BYTE_ORDER == _BIG_ENDIAN + u_int32_t th_off:4, /* data offset */ + th_x2:4; /* (unused) */ +#endif + u_int8_t th_flags; +#define TH_FIN 0x01 +#define TH_SYN 0x02 +#define TH_RST 0x04 +#define TH_PUSH 0x08 +#define TH_ACK 0x10 +#define TH_URG 0x20 +#define TH_ECE 0x40 +#define TH_CWR 0x80 + u_int16_t th_win; /* window */ + u_int16_t th_sum; /* checksum */ + u_int16_t th_urp; /* urgent pointer */ +}; +#define th_reseqlen th_urp /* TCP data length for + resequencing/reassembly */ + +#define TCPOPT_EOL 0 +#define TCPOPT_NOP 1 +#define TCPOPT_MAXSEG 2 +#define TCPOLEN_MAXSEG 4 +#define TCPOPT_WINDOW 3 +#define TCPOLEN_WINDOW 3 +#define TCPOPT_SACK_PERMITTED 4 /* Experimental */ +#define TCPOLEN_SACK_PERMITTED 2 +#define TCPOPT_SACK 5 /* Experimental */ +#define TCPOLEN_SACK 8 /* 2*sizeof(tcp_seq) */ +#define TCPOPT_TIMESTAMP 8 +#define TCPOLEN_TIMESTAMP 10 +#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */ +#define TCPOPT_SIGNATURE 19 +#define TCPOLEN_SIGNATURE 18 +#define TCPOLEN_SIGLEN (TCPOLEN_SIGNATURE+2) /* padding */ + +#define MAX_TCPOPTLEN 40 /* Absolute maximum TCP options len */ + +#define TCPOPT_TSTAMP_HDR \ + (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP) + +/* Option definitions */ +#define TCPOPT_SACK_PERMIT_HDR \ +(TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_SACK_PERMITTED<<8|TCPOLEN_SACK_PERMITTED) +#define TCPOPT_SACK_HDR (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_SACK<<8) +/* Miscellaneous constants */ +#define MAX_SACK_BLKS 6 /* Max # SACK blocks stored at sender side */ +#define TCP_MAX_SACK 3 /* Max # SACKs sent in any segment */ +#define TCP_SACKHOLE_LIMIT 128 /* Max # SACK holes per connection */ + +/* + * Default maximum segment size for TCP. + * With an IP MSS of 576, this is 536, + * but 512 is probably more convenient. + * This should be defined as min(512, IP_MSS - sizeof (struct tcpiphdr)). + */ +#define TCP_MSS 512 + +#define TCP_MAXWIN 65535 /* largest value for (unscaled) window */ + +#define TCP_MAX_WINSHIFT 14 /* maximum window shift */ + +/* + * The TCP_INFO socket option comes from the Linux 2.6 TCP API, and permits + * the caller to query certain information about the state of a TCP + * connection. Provide an overlapping set of fields with the Linux + * implementation, but at the same time add a lot of OpenBSD specific + * extra information. + */ +struct tcp_info { + uint8_t tcpi_state; /* TCP FSM state. */ + uint8_t __tcpi_ca_state; + uint8_t __tcpi_retransmits; + uint8_t __tcpi_probes; + uint8_t __tcpi_backoff; + uint8_t tcpi_options; /* Options enabled on conn. */ +#define TCPI_OPT_TIMESTAMPS 0x01 +#define TCPI_OPT_SACK 0x02 +#define TCPI_OPT_WSCALE 0x04 +#define TCPI_OPT_ECN 0x08 +#define TCPI_OPT_TOE 0x10 + uint8_t tcpi_snd_wscale; /* RFC1323 send shift value. */ + uint8_t tcpi_rcv_wscale; /* RFC1323 recv shift value. */ + + uint32_t tcpi_rto; /* Retransmission timeout (usec). */ + uint32_t __tcpi_ato; + uint32_t tcpi_snd_mss; /* Max segment size for send. */ + uint32_t tcpi_rcv_mss; /* Max segment size for recv. */ + + uint32_t __tcpi_unacked; + uint32_t __tcpi_sacked; + uint32_t __tcpi_lost; + uint32_t __tcpi_retrans; + uint32_t __tcpi_fackets; + + /* Times; measurements in usecs. */ + uint32_t tcpi_last_data_sent; /* since last sent data. */ + uint32_t tcpi_last_ack_sent; /* since last sent ack. */ + uint32_t tcpi_last_data_recv; /* since last recv data. */ + uint32_t tcpi_last_ack_recv; /* since last recv ack. */ + + /* Metrics; variable units. */ + uint32_t __tcpi_pmtu; + uint32_t __tcpi_rcv_ssthresh; + uint32_t tcpi_rtt; /* Smoothed RTT in usecs. */ + uint32_t tcpi_rttvar; /* RTT variance in usecs. */ + uint32_t tcpi_snd_ssthresh; /* Slow start threshold. */ + uint32_t tcpi_snd_cwnd; /* Send congestion window. */ + uint32_t __tcpi_advmss; + uint32_t __tcpi_reordering; + + uint32_t __tcpi_rcv_rtt; + uint32_t tcpi_rcv_space; /* Advertised recv window. */ + + /* + * Members below this point are only set if process is privileged, + * otherwise values will be 0. + */ + + /* FreeBSD/NetBSD extensions to tcp_info. */ + uint32_t tcpi_snd_wnd; /* Advertised send window. */ + uint32_t tcpi_snd_nxt; /* Next egress seqno */ + uint32_t tcpi_rcv_nxt; /* Next ingress seqno */ + uint32_t tcpi_toe_tid; /* HWTID for TOE endpoints */ + uint32_t tcpi_snd_rexmitpack; /* Retransmitted packets */ + uint32_t tcpi_rcv_ooopack; /* Out-of-order packets */ + uint32_t tcpi_snd_zerowin; /* Zero-sized windows sent */ + + /* OpenBSD extensions */ + uint32_t tcpi_rttmin; + uint32_t tcpi_max_sndwnd; + uint32_t tcpi_rcv_adv; + uint32_t tcpi_rcv_up; + uint32_t tcpi_snd_una; + uint32_t tcpi_snd_up; + uint32_t tcpi_snd_wl1; + uint32_t tcpi_snd_wl2; + uint32_t tcpi_snd_max; + uint32_t tcpi_ts_recent; + uint32_t tcpi_ts_recent_age; + uint32_t tcpi_rfbuf_cnt; + uint32_t tcpi_rfbuf_ts; + uint32_t tcpi_so_rcv_sb_cc; + uint32_t tcpi_so_rcv_sb_hiwat; + uint32_t tcpi_so_rcv_sb_lowat; + uint32_t tcpi_so_rcv_sb_wat; + uint32_t tcpi_so_snd_sb_cc; + uint32_t tcpi_so_snd_sb_hiwat; + uint32_t tcpi_so_snd_sb_lowat; + uint32_t tcpi_so_snd_sb_wat; +}; + +#endif /* __BSD_VISIBLE */ + +/* + * User-settable options (used with setsockopt). + */ +#define TCP_NODELAY 0x01 /* don't delay send to coalesce pkts */ +#define TCP_MAXSEG 0x02 /* set maximum segment size */ +#define TCP_MD5SIG 0x04 /* enable TCP MD5 signature option */ +#define TCP_SACK_ENABLE 0x08 /* enable SACKs (if disabled by def.) */ +#define TCP_INFO 0x09 /* retrieve tcp_info structure */ +#define TCP_NOPUSH 0x10 /* don't push last block of write */ + +#endif /* _NETINET_TCP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/tcp_debug.h b/lib/libc/include/generic-openbsd/netinet/tcp_debug.h new file mode 100644 index 000000000000..973b431bbb5a --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/tcp_debug.h @@ -0,0 +1,106 @@ +/* $OpenBSD: tcp_debug.h,v 1.11 2018/05/10 13:30:25 bluhm Exp $ */ +/* $NetBSD: tcp_debug.h,v 1.5 1994/06/29 06:38:38 cgd Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tcp_debug.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_TCP_DEBUG_H_ +#define _NETINET_TCP_DEBUG_H_ + +/* + * Tcp+ip header, after ip options removed. + */ +struct tcpiphdr { + struct ipovly ti_i; /* overlaid ip structure */ + struct tcphdr ti_t; /* tcp header */ +}; +#define ti_x1 ti_i.ih_x1 +#define ti_pr ti_i.ih_pr +#define ti_len ti_i.ih_len +#define ti_src ti_i.ih_src +#define ti_dst ti_i.ih_dst +#define ti_sport ti_t.th_sport +#define ti_dport ti_t.th_dport +#define ti_seq ti_t.th_seq +#define ti_ack ti_t.th_ack +#define ti_x2 ti_t.th_x2 +#define ti_off ti_t.th_off +#define ti_flags ti_t.th_flags +#define ti_win ti_t.th_win +#define ti_sum ti_t.th_sum +#define ti_urp ti_t.th_urp + +struct tcpipv6hdr { + struct ip6_hdr ti6_i; + struct tcphdr ti6_t; +}; + +#define ti6_src ti6_i.ip6_src +#define ti6_dst ti6_i.ip6_dst +#define ti6_plen ti6_i.ip6_plen +#define ti6_sport ti6_t.th_sport +#define ti6_dport ti6_t.th_dport +#define ti6_seq ti6_t.th_seq +#define ti6_ack ti6_t.th_ack +#define ti6_x2 ti6_t.th_x2 +#define ti6_off ti6_t.th_off +#define ti6_flags ti6_t.th_flags +#define ti6_win ti6_t.th_win +#define ti6_sum ti6_t.th_sum +#define ti6_urp ti6_t.th_urp + +struct tcp_debug { + uint32_t td_time; + short td_act; + short td_ostate; + caddr_t td_tcb; + struct tcpiphdr td_ti; + struct tcpipv6hdr td_ti6; + short td_req; + struct tcpcb td_cb; +}; + +#define TA_INPUT 0 +#define TA_OUTPUT 1 +#define TA_USER 2 +#define TA_RESPOND 3 +#define TA_DROP 4 +#define TA_TIMER 5 + +#ifdef TANAMES +const char *tanames[] = + { "input", "output", "user", "respond", "drop", "timer" }; +#endif /* TANAMES */ + +#define TCP_NDEBUG 100 +extern struct tcp_debug tcp_debug[]; +extern int tcp_debx; +#endif /* _NETINET_TCP_DEBUG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/tcp_fsm.h b/lib/libc/include/generic-openbsd/netinet/tcp_fsm.h new file mode 100644 index 000000000000..a6a20c60a37d --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/tcp_fsm.h @@ -0,0 +1,85 @@ +/* $OpenBSD: tcp_fsm.h,v 1.10 2024/12/20 21:30:17 bluhm Exp $ */ +/* $NetBSD: tcp_fsm.h,v 1.6 1994/10/14 16:01:48 mycroft Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tcp_fsm.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_TCP_FSM_H_ +#define _NETINET_TCP_FSM_H_ + +/* + * TCP FSM state definitions. + * Per RFC793, September, 1981. + */ + +#define TCP_NSTATES 11 + +#define TCPS_CLOSED 0 /* closed */ +#define TCPS_LISTEN 1 /* listening for connection */ +#define TCPS_SYN_SENT 2 /* active, have sent syn */ +#define TCPS_SYN_RECEIVED 3 /* have sent and received syn */ +/* states < TCPS_ESTABLISHED are those where connections not established */ +#define TCPS_ESTABLISHED 4 /* established */ +#define TCPS_CLOSE_WAIT 5 /* rcvd fin, waiting for close */ +/* states > TCPS_CLOSE_WAIT are those where user has closed */ +#define TCPS_FIN_WAIT_1 6 /* have closed, sent fin */ +#define TCPS_CLOSING 7 /* closed xchd FIN; await ACK */ +#define TCPS_LAST_ACK 8 /* had fin and close; await FIN ACK */ +/* states > TCPS_CLOSE_WAIT && < TCPS_FIN_WAIT_2 await ACK of FIN */ +#define TCPS_FIN_WAIT_2 9 /* have closed, fin is acked */ +#define TCPS_TIME_WAIT 10 /* in 2*msl quiet wait after close */ + +#define TCPS_HAVERCVDSYN(s) ((s) >= TCPS_SYN_RECEIVED) +#define TCPS_HAVEESTABLISHED(s) ((s) >= TCPS_ESTABLISHED) +#define TCPS_HAVERCVDFIN(s) ((s) >= TCPS_TIME_WAIT) + +#ifdef TCPOUTFLAGS +/* + * Flags used when sending segments in tcp_output. + * Basic flags (TH_RST,TH_ACK,TH_SYN,TH_FIN) are totally + * determined by state, with the proviso that TH_FIN is sent only + * if all data queued for output is included in the segment. + */ +const u_char tcp_outflags[TCP_NSTATES] = { + TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK, + TH_ACK, TH_ACK, + TH_FIN|TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK, TH_ACK, TH_ACK, +}; +#endif /* TCPOUTFLAGS */ + +#ifdef TCPSTATES +const char *const tcpstates[] = { + "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD", + "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING", + "LAST_ACK", "FIN_WAIT_2", "TIME_WAIT", +}; +#endif /* TCPSTATES */ +#endif /* _NETINET_TCP_FSM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/tcp_seq.h b/lib/libc/include/generic-openbsd/netinet/tcp_seq.h new file mode 100644 index 000000000000..b68e2db5b2f9 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/tcp_seq.h @@ -0,0 +1,66 @@ +/* $OpenBSD: tcp_seq.h,v 1.6 2007/06/15 18:23:06 markus Exp $ */ +/* $NetBSD: tcp_seq.h,v 1.6 1995/03/26 20:32:35 jtc Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tcp_seq.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_TCP_SEQ_H_ +#define _NETINET_TCP_SEQ_H_ + +/* + * TCP sequence numbers are 32 bit integers operated + * on with modular arithmetic. These macros can be + * used to compare such integers. + */ +#define SEQ_LT(a,b) ((int)((a)-(b)) < 0) +#define SEQ_LEQ(a,b) ((int)((a)-(b)) <= 0) +#define SEQ_GT(a,b) ((int)((a)-(b)) > 0) +#define SEQ_GEQ(a,b) ((int)((a)-(b)) >= 0) + +/* + * Macros to initialize tcp sequence numbers for + * send and receive from initial send and receive + * sequence numbers. + */ +#define tcp_rcvseqinit(tp) \ + (tp)->rcv_adv = (tp)->rcv_nxt = (tp)->irs + 1 + +#define tcp_sendseqinit(tp) \ + (tp)->snd_una = (tp)->snd_nxt = (tp)->snd_max = (tp)->snd_up = \ + (tp)->iss + +#define TCP_ISSINCR (125*1024) /* increment for tcp_iss each second */ +#define TCP_ISSINCR2 (1*1024*1024) /* increment for tcp_iss each second */ + +#ifdef _KERNEL +extern tcp_seq tcp_iss; /* tcp initial send seq # */ +#endif /* _KERNEL */ +#endif /* _NETINET_TCP_SEQ_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/tcp_timer.h b/lib/libc/include/generic-openbsd/netinet/tcp_timer.h new file mode 100644 index 000000000000..d15427d2f9ce --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/tcp_timer.h @@ -0,0 +1,168 @@ +/* $OpenBSD: tcp_timer.h,v 1.27 2025/06/08 17:06:19 bluhm Exp $ */ +/* $NetBSD: tcp_timer.h,v 1.6 1995/03/26 20:32:37 jtc Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tcp_timer.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_TCP_TIMER_H_ +#define _NETINET_TCP_TIMER_H_ + +/* + * Definitions of the TCP timers. + */ +#define TCPT_REXMT 0 /* retransmit */ +#define TCPT_PERSIST 1 /* retransmit persistence */ +#define TCPT_KEEP 2 /* keep alive */ +#define TCPT_2MSL 3 /* 2*msl quiet time timer */ +#define TCPT_DELACK 4 /* delayed ack timeout */ + +#define TCPT_NTIMERS 5 + +/* + * The TCPT_REXMT timer is used to force retransmissions. + * The TCP has the TCPT_REXMT timer set whenever segments + * have been sent for which ACKs are expected but not yet + * received. If an ACK is received which advances tp->snd_una, + * then the retransmit timer is cleared (if there are no more + * outstanding segments) or reset to the base value (if there + * are more ACKs expected). Whenever the retransmit timer goes off, + * we retransmit one unacknowledged segment, and do a backoff + * on the retransmit timer. + * + * The TCPT_PERSIST timer is used to keep window size information + * flowing even if the window goes shut. If all previous transmissions + * have been acknowledged (so that there are no retransmissions in progress), + * and the window is too small to bother sending anything, then we start + * the TCPT_PERSIST timer. When it expires, if the window is nonzero, + * we go to transmit state. Otherwise, at intervals send a single byte + * into the peer's window to force him to update our window information. + * We do this at most as often as TCPT_PERSMIN time intervals, + * but no more frequently than the current estimate of round-trip + * packet time. The TCPT_PERSIST timer is cleared whenever we receive + * a window update from the peer. + * + * The TCPT_KEEP timer is used to keep connections alive. If an + * connection is idle (no segments received) for TCPTV_KEEP_INIT amount of time, + * but not yet established, then we drop the connection. Once the connection + * is established, if the connection is idle for TCPTV_KEEP_IDLE time + * (and keepalives have been enabled on the socket), we begin to probe + * the connection. We force the peer to send us a segment by sending: + * + * This segment is (deliberately) outside the window, and should elicit + * an ack segment in response from the peer. If, despite the TCPT_KEEP + * initiated segments we cannot elicit a response from a peer in TCPT_MAXIDLE + * amount of time probing, then we drop the connection. + */ + +/* + * Time constants. + */ +#define TCPTV_MSL TCP_TIME(30) /* max seg lifetime (hah!) */ +#define TCPTV_SRTTBASE 0 /* base roundtrip time; + if 0, no idea yet */ +#define TCPTV_SRTTDFLT TCP_TIME(3) /* assumed RTT if no info */ + +#define TCPTV_PERSMIN TCP_TIME(5) /* retransmit persistence */ +#define TCPTV_PERSMAX TCP_TIME(60) /* maximum persist interval */ + +#define TCPTV_KEEPINIT TCP_TIME(75) /* initial connect keep alive */ +#define TCPTV_KEEPIDLE TCP_TIME(120*60) /* dflt time before probing */ +#define TCPTV_KEEPINTVL TCP_TIME(75) /* default probe interval */ +#define TCPTV_KEEPCNT 8 /* max probes before drop */ + +#define TCPTV_MIN TCP_TIME(1) /* minimum allowable value */ +#define TCPTV_REXMTMAX TCP_TIME(64) /* max allowable REXMT value */ + +#define TCP_LINGERTIME 120 /* linger at most 2 minutes */ + +#define TCP_MAXRXTSHIFT 12 /* maximum retransmits */ + +#define TCP_DELACK_MSECS 200 /* time to delay ACK */ + +#ifdef TCPTIMERS +const char *tcptimers[TCPT_NTIMERS] = + { "REXMT", "PERSIST", "KEEP", "2MSL", "DELACK" }; +#endif /* TCPTIMERS */ + +/* + * Init, arm, disarm, and test TCP timers. + */ +#define TCP_TIMER_INIT(tp, timer) \ + timeout_set_flags(&(tp)->t_timer[(timer)], \ + tcp_timer_funcs[(timer)], (tp)->t_inpcb, \ + KCLOCK_NONE, TIMEOUT_PROC | TIMEOUT_MPSAFE) + +#define TCP_TIMER_ARM(tp, timer, msecs) \ +do { \ + SET((tp)->t_flags, TF_TIMER << (timer)); \ + if (timeout_add_msec(&(tp)->t_timer[(timer)], (msecs))) \ + in_pcbref((tp)->t_inpcb); \ +} while (0) + +#define TCP_TIMER_DISARM(tp, timer) \ +do { \ + CLR((tp)->t_flags, TF_TIMER << (timer)); \ + if (timeout_del(&(tp)->t_timer[(timer)])) \ + in_pcbunref((tp)->t_inpcb); \ +} while (0) + +#define TCP_TIMER_ISARMED(tp, timer) \ + ISSET((tp)->t_flags, TF_TIMER << (timer)) + +/* + * Force a time value to be in a certain range. + */ +#define TCPT_RANGESET(tv, value, tvmin, tvmax) \ +do { \ + (tv) = (value); \ + if ((tv) < (tvmin)) \ + (tv) = (tvmin); \ + else if ((tv) > (tvmax)) \ + (tv) = (tvmax); \ +} while (/* CONSTCOND */ 0) + +#ifdef _KERNEL +typedef void (*tcp_timer_func_t)(void *); + +extern const tcp_timer_func_t tcp_timer_funcs[TCPT_NTIMERS]; + +extern int tcp_delack_msecs; /* [I] delayed ACK timeout in millisecs */ +extern int tcp_always_keepalive;/* [a] assume SO_KEEPALIVE always set */ +extern int tcp_keepinit; /* [a] time to keep alive initial SYN packet */ +extern int tcp_keepidle; /* [a] time before keepalive probes begin */ +extern int tcp_keepintvl; /* [a] time between keepalive probes */ +extern int tcp_keepinit_sec; /* [a] copy of above in seconds for sysctl */ +extern int tcp_keepidle_sec; /* [a] copy of above in seconds for sysctl */ +extern int tcp_keepintvl_sec; /* [a] copy of above in seconds for sysctl */ +extern int tcp_ttl; /* time to live for TCP segs */ +extern const int tcp_backoff[]; +#endif /* _KERNEL */ +#endif /* _NETINET_TCP_TIMER_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/tcp_var.h b/lib/libc/include/generic-openbsd/netinet/tcp_var.h new file mode 100644 index 000000000000..616a6ae8338b --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/tcp_var.h @@ -0,0 +1,814 @@ +/* $OpenBSD: tcp_var.h,v 1.196 2025/09/16 17:29:35 bluhm Exp $ */ +/* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tcp_var.h 8.3 (Berkeley) 4/10/94 + */ + +#ifndef _NETINET_TCP_VAR_H_ +#define _NETINET_TCP_VAR_H_ + +#include + +/* + * Kernel variables for tcp. + */ + +struct sackblk { + tcp_seq start; /* start seq no. of sack block */ + tcp_seq end; /* end seq no. */ +}; + +struct sackhole { + tcp_seq start; /* start seq no. of hole */ + tcp_seq end; /* end seq no. */ + int dups; /* number of dup(s)acks for this hole */ + tcp_seq rxmit; /* next seq. no in hole to be retransmitted */ + struct sackhole *next; /* next in list */ +}; + +/* + * TCP sequence queue structures. + */ +TAILQ_HEAD(tcpqehead, tcpqent); +struct tcpqent { + TAILQ_ENTRY(tcpqent) tcpqe_q; + struct tcphdr *tcpqe_tcp; + struct mbuf *tcpqe_m; /* mbuf contains packet */ +}; + +/* + * Tcp control block, one per tcp; fields: + */ +struct tcpcb { + struct tcpqehead t_segq; /* sequencing queue */ + struct timeout t_timer[TCPT_NTIMERS]; /* tcp timers */ + short t_state; /* state of this connection */ + short t_rxtshift; /* log(2) of rexmt exp. backoff */ + int t_rxtcur; /* current retransmit value */ + short t_dupacks; /* consecutive dup acks recd */ + u_short t_maxseg; /* maximum segment size */ + char t_force; /* 1 if forcing out a byte */ + u_int t_flags; +#define TF_ACKNOW 0x0001U /* ack peer immediately */ +#define TF_NODELAY 0x0004U /* don't delay packets to coalesce */ +#define TF_NOOPT 0x0008U /* don't use tcp options */ +#define TF_SENTFIN 0x0010U /* have sent FIN */ +#define TF_REQ_SCALE 0x0020U /* have/will request window scaling */ +#define TF_RCVD_SCALE 0x0040U /* other side has requested scaling */ +#define TF_REQ_TSTMP 0x0080U /* have/will request timestamps */ +#define TF_RCVD_TSTMP 0x0100U /* a timestamp was received in SYN */ +#define TF_SACK_PERMIT 0x0200U /* other side said I could SACK */ +#define TF_SIGNATURE 0x0400U /* require TCP MD5 signature */ +#ifdef TCP_ECN +#define TF_ECN_PERMIT 0x00008000U /* other side said I could ECN */ +#define TF_RCVD_CE 0x00010000U /* send ECE in subsequent segs */ +#define TF_SEND_CWR 0x00020000U /* send CWR in next seg */ +#define TF_DISABLE_ECN 0x00040000U /* disable ECN for this connection */ +#endif +#define TF_LASTIDLE 0x00100000U /* no outstanding ACK on last send */ +#define TF_PMTUD_PEND 0x00400000U /* Path MTU Discovery pending */ +#define TF_NEEDOUTPUT 0x00800000U /* call tcp_output after tcp_input */ +#define TF_NOPUSH 0x02000000U /* don't push */ +#define TF_TMR_REXMT 0x04000000U /* retransmit timer armed */ +#define TF_TMR_PERSIST 0x08000000U /* retransmit persistence timer armed */ +#define TF_TMR_KEEP 0x10000000U /* keep alive timer armed */ +#define TF_TMR_2MSL 0x20000000U /* 2*msl quiet time timer armed */ +#define TF_TMR_DELACK 0x40000000U /* delayed ack timer armed */ +#define TF_TIMER TF_TMR_REXMT /* used to shift with TCPT values */ + + struct mbuf *t_template; /* skeletal packet for transmit */ + struct inpcb *t_inpcb; /* back pointer to internet pcb */ +/* + * The following fields are used as in the protocol specification. + * See RFC793, Dec. 1981, page 21. + */ +/* send sequence variables */ + tcp_seq snd_una; /* send unacknowledged */ + tcp_seq snd_nxt; /* send next */ + tcp_seq snd_up; /* send urgent pointer */ + tcp_seq snd_wl1; /* window update seg seq number */ + tcp_seq snd_wl2; /* window update seg ack number */ + tcp_seq iss; /* initial send sequence number */ + u_long snd_wnd; /* send window */ + int sack_enable; /* enable SACK for this connection */ + int snd_numholes; /* number of holes seen by sender */ + struct sackhole *snd_holes; /* linked list of holes (sorted) */ + tcp_seq snd_last; /* for use in fast recovery */ +/* receive sequence variables */ + u_long rcv_wnd; /* receive window */ + tcp_seq rcv_nxt; /* receive next */ + tcp_seq rcv_up; /* receive urgent pointer */ + tcp_seq irs; /* initial receive sequence number */ + tcp_seq rcv_lastsack; /* last seq number(+1) sack'd by rcv'r*/ + int rcv_numsacks; /* # distinct sack blks present */ + struct sackblk sackblks[MAX_SACK_BLKS]; /* seq nos. of sack blocks */ + +/* + * Additional variables for this implementation. + */ +/* receive variables */ + tcp_seq rcv_adv; /* advertised window */ +/* retransmit variables */ + tcp_seq snd_max; /* highest sequence number sent; + * used to recognize retransmits + */ +/* congestion control (for slow start, source quench, retransmit after loss) */ + u_long snd_cwnd; /* congestion-controlled window */ + u_long snd_ssthresh; /* snd_cwnd size threshold for + * for slow start exponential to + * linear switch + */ + +/* auto-sizing variables */ + uint64_t rfbuf_ts; /* recv buffer autoscaling time stamp */ + u_int rfbuf_cnt; /* recv buffer autoscaling byte count */ + + u_short t_maxopd; /* mss plus options */ + u_short t_peermss; /* peer's maximum segment size */ + +/* + * transmit timing stuff. See below for scale of srtt and rttvar. + * "Variance" is actually smoothed difference. + */ + uint64_t t_rcvtime; /* time last segment received */ + uint64_t t_rcvacktime; /* time last ack received */ + uint64_t t_sndtime; /* time last segment sent */ + uint64_t t_sndacktime; /* time last ack sent */ + uint64_t t_rtttime; /* time we started measuring rtt */ + tcp_seq t_rtseq; /* sequence number being timed */ + int t_srtt; /* smoothed round-trip time */ + int t_rttvar; /* variance in round-trip time */ + u_int t_rttmin; /* minimum rtt allowed */ + u_long max_sndwnd; /* largest window peer has offered */ + +/* out-of-band data */ + char t_oobflags; /* have some */ + char t_iobc; /* input character */ +#define TCPOOB_HAVEDATA 0x01 +#define TCPOOB_HADDATA 0x02 + short t_softerror; /* possible error not yet reported */ + +/* RFC 1323 variables */ + u_char snd_scale; /* window scaling for send window */ + u_char rcv_scale; /* window scaling for recv window */ + u_char request_r_scale; /* pending window scaling */ + u_char requested_s_scale; + uint32_t ts_recent; /* timestamp echo data */ + uint32_t ts_modulate; /* modulation on timestamp */ + uint64_t ts_recent_age; /* when last updated */ + tcp_seq last_ack_sent; + +/* pointer for syn cache entries*/ + LIST_HEAD(, syn_cache) t_sc; /* list of entries by this tcb */ + +/* Path-MTU Discovery Information */ + u_int t_pmtud_mss_acked; /* MSS acked, lower bound for MTU */ + u_int t_pmtud_mtu_sent; /* MTU used, upper bound for MTU */ + tcp_seq t_pmtud_th_seq; /* TCP SEQ from ICMP payload */ + u_int t_pmtud_nextmtu; /* Advertised Next-Hop MTU from ICMP */ + u_short t_pmtud_ip_len; /* IP length from ICMP payload */ + u_short t_pmtud_ip_hl; /* IP header length from ICMP payload */ + + int pf; + +/* maintain a few stats per connection: */ + u_int t_rcvoopack; /* out-of-order packets received */ + u_int t_sndrexmitpack; /* retransmit packets sent */ + u_int t_sndzerowin; /* zero-window updates sent */ +}; + +#define intotcpcb(ip) ((struct tcpcb *)(ip)->inp_ppcb) +#define sototcpcb(so) (intotcpcb(sotoinpcb(so))) + +#ifdef _KERNEL +/* + * Handy way of passing around TCP option info. + */ +struct tcp_opt_info { + int ts_present; + u_int32_t ts_val; + u_int32_t ts_ecr; + u_int16_t maxseg; +}; + +/* + * Data for the TCP compressed state engine. + */ + +/* + * Locks used to protect global data and struct members: + * I immutable after creation + * N net lock + * S syn_cache_mtx tcp syn cache global mutex + * s so_lock socket lock of listen socket + */ + +extern struct mutex syn_cache_mtx; + +#define TCP_SYN_HASH_SIZE 293 +#define TCP_SYN_BUCKET_SIZE 35 + +union syn_cache_sa { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; +}; + +struct syn_cache { + TAILQ_ENTRY(syn_cache) sc_bucketq; /* [S] link on bucket list */ + struct refcnt sc_refcnt; /* ref count list and timer */ + struct timeout sc_timer; /* rexmt timer */ + struct route sc_route; /* [s] cached route */ + long sc_win; /* [I] advertised window */ + struct syn_cache_head *sc_buckethead; /* [S] our bucket index */ + struct syn_cache_set *sc_set; /* [S] our syn cache set */ + u_int64_t sc_timestamp; /* [s] timestamp from SYN */ + u_int32_t sc_hash; /* [S] */ + u_int32_t sc_modulate; /* [I] our timestamp modulator */ + union syn_cache_sa sc_src; /* [I] */ + union syn_cache_sa sc_dst; /* [I] */ + tcp_seq sc_irs; /* [I] */ + tcp_seq sc_iss; /* [I] */ + u_int sc_rtableid; /* [I] */ + u_int sc_rxtcur; /* [S] current rxt timeout */ + u_int sc_rxttot; /* [S] total time spend on queues */ + u_int sc_rxtshift; /* [S] for computing backoff */ + u_int sc_dynflags; /* [S] flags accessed with mutex */ +#define SCF_UNREACH 0x0001U /* we've had an unreach error */ + + u_short sc_fixflags; /* [I] set during initialization */ +#define SCF_TIMESTAMP 0x0010U /* peer will do timestamps */ +#define SCF_SACK_PERMIT 0x0020U /* permit sack */ +#define SCF_ECN_PERMIT 0x0040U /* permit ecn */ +#define SCF_SIGNATURE 0x0080U /* enforce tcp signatures */ + + struct mbuf *sc_ipopts; /* [s] IP options */ + u_int16_t sc_peermaxseg; /* [I] */ + u_int16_t sc_ourmaxseg; /* [I] */ + u_int sc_request_r_scale : 4, /* [I] */ + sc_requested_s_scale : 4; /* [I] */ + + struct inpcb *sc_inplisten; /* [S] inpcb for listening socket */ + LIST_ENTRY(syn_cache) sc_tpq; /* [S] list of entries by same tp */ +}; + +struct syn_cache_head { + TAILQ_HEAD(, syn_cache) sch_bucket; /* [S] bucket entries */ + u_short sch_length; /* [S] # entries in bucket */ +}; + +struct syn_cache_set { + struct syn_cache_head *scs_buckethead; /* [S] */ + long scs_use; /* [S] */ + int scs_size; /* [S] current size of hash table */ + int scs_count; /* [S] */ + u_int32_t scs_random[5]; /* [S] */ +}; + +#endif /* _KERNEL */ + +/* + * The smoothed round-trip time and estimated variance + * are stored as fixed point numbers scaled by the values below. + * For convenience, these scales are also used in smoothing the average + * (smoothed = (1/scale)sample + ((scale-1)/scale)smoothed). + * With these scales, srtt has 5 bits to the right of the binary point, + * and thus an "ALPHA" of 0.875. rttvar has 4 bits to the right of the + * binary point, and is smoothed with an ALPHA of 0.75. + */ +#define TCP_RTT_SHIFT 3 /* shift for srtt; 5 bits frac. */ +#define TCP_RTTVAR_SHIFT 2 /* shift for rttvar; 4 bits */ +#define TCP_RTT_BASE_SHIFT 2 /* remaining 2 bit shift */ +#define TCP_RTT_MAX (1<<18) /* maximum rtt */ + +/* + * The initial retransmission should happen at rtt + 4 * rttvar. + * Because of the way we do the smoothing, srtt and rttvar + * will each average +1/2 tick of bias. When we compute + * the retransmit timer, we want 1/2 tick of rounding and + * 1 extra tick because of +-1/2 tick uncertainty in the + * firing of the timer. The bias will give us exactly the + * 1.5 tick we need. But, because the bias is + * statistical, we have to test that we don't drop below + * the minimum feasible timer (which is 2 ticks). + * This macro assumes that the value of (1 << TCP_RTTVAR_SHIFT) + * is the same as the multiplier for rttvar. + */ +#define TCP_REXMTVAL(tp) \ + ((((tp)->t_srtt >> TCP_RTT_SHIFT) + (tp)->t_rttvar) \ + >> TCP_RTT_BASE_SHIFT) + +/* + * TCP statistics. + * Many of these should be kept per connection, + * but that's inconvenient at the moment. + */ +struct tcpstat { + u_int32_t tcps_connattempt; /* connections initiated */ + u_int32_t tcps_accepts; /* connections accepted */ + u_int32_t tcps_connects; /* connections established */ + u_int32_t tcps_drops; /* connections dropped */ + u_int32_t tcps_conndrops; /* embryonic connections dropped */ + u_int32_t tcps_closed; /* conn. closed (includes drops) */ + u_int32_t tcps_segstimed; /* segs where we tried to get rtt */ + u_int32_t tcps_rttupdated; /* times we succeeded */ + u_int32_t tcps_delack; /* delayed acks sent */ + u_int32_t tcps_timeoutdrop; /* conn. dropped in rxmt timeout */ + u_int32_t tcps_rexmttimeo; /* retransmit timeouts */ + u_int32_t tcps_persisttimeo; /* persist timeouts */ + u_int32_t tcps_persistdrop; /* connections dropped in persist */ + u_int32_t tcps_keeptimeo; /* keepalive timeouts */ + u_int32_t tcps_keepprobe; /* keepalive probes sent */ + u_int32_t tcps_keepdrops; /* connections dropped in keepalive */ + + u_int32_t tcps_sndtotal; /* total packets sent */ + u_int32_t tcps_sndpack; /* data packets sent */ + u_int64_t tcps_sndbyte; /* data bytes sent */ + u_int32_t tcps_sndrexmitpack; /* data packets retransmitted */ + u_int64_t tcps_sndrexmitbyte; /* data bytes retransmitted */ + u_int64_t tcps_sndrexmitfast; /* Fast retransmits */ + u_int32_t tcps_sndacks; /* ack-only packets sent */ + u_int32_t tcps_sndprobe; /* window probes sent */ + u_int32_t tcps_sndurg; /* packets sent with URG only */ + u_int32_t tcps_sndwinup; /* window update-only packets sent */ + u_int32_t tcps_sndctrl; /* control (SYN|FIN|RST) packets sent */ + + u_int32_t tcps_rcvtotal; /* total packets received */ + u_int32_t tcps_rcvpack; /* packets received in sequence */ + u_int64_t tcps_rcvbyte; /* bytes received in sequence */ + u_int32_t tcps_rcvbadsum; /* packets received with ccksum errs */ + u_int32_t tcps_rcvbadoff; /* packets received with bad offset */ + u_int32_t tcps_rcvmemdrop; /* packets dropped for lack of memory */ + u_int32_t tcps_rcvnosec; /* packets dropped for lack of ipsec */ + u_int32_t tcps_rcvshort; /* packets received too short */ + u_int32_t tcps_rcvduppack; /* duplicate-only packets received */ + u_int64_t tcps_rcvdupbyte; /* duplicate-only bytes received */ + u_int32_t tcps_rcvpartduppack; /* packets with some duplicate data */ + u_int64_t tcps_rcvpartdupbyte; /* dup. bytes in part-dup. packets */ + u_int32_t tcps_rcvoopack; /* out-of-order packets received */ + u_int64_t tcps_rcvoobyte; /* out-of-order bytes received */ + u_int32_t tcps_rcvpackafterwin; /* packets with data after window */ + u_int64_t tcps_rcvbyteafterwin; /* bytes rcvd after window */ + u_int32_t tcps_rcvafterclose; /* packets rcvd after "close" */ + u_int32_t tcps_rcvwinprobe; /* rcvd window probe packets */ + u_int32_t tcps_rcvdupack; /* rcvd duplicate acks */ + u_int32_t tcps_rcvacktoomuch; /* rcvd acks for unsent data */ + u_int32_t tcps_rcvacktooold; /* rcvd acks for old data */ + u_int32_t tcps_rcvackpack; /* rcvd ack packets */ + u_int64_t tcps_rcvackbyte; /* bytes acked by rcvd acks */ + u_int32_t tcps_rcvwinupd; /* rcvd window update packets */ + u_int32_t tcps_pawsdrop; /* segments dropped due to PAWS */ + u_int32_t tcps_predack; /* times hdr predict ok for acks */ + u_int32_t tcps_preddat; /* times hdr predict ok for data pkts */ + + u_int32_t tcps_pcbhashmiss; /* input packets missing pcb hash */ + u_int32_t tcps_noport; /* no socket on port */ + u_int32_t tcps_closing; /* inpcb exists, socket is closing */ + u_int32_t tcps_badsyn; /* SYN packet with src==dst rcv'ed */ + u_int32_t tcps_dropsyn; /* SYN packet dropped */ + + u_int32_t tcps_rcvbadsig; /* rcvd bad/missing TCP signatures */ + u_int64_t tcps_rcvgoodsig; /* rcvd good TCP signatures */ + u_int32_t tcps_inswcsum; /* input software-checksummed pkts */ + u_int32_t tcps_outswcsum; /* output software-checksummed pkts */ + + /* ECN stats */ + u_int32_t tcps_ecn_accepts; /* ecn connections accepted */ + u_int32_t tcps_ecn_rcvece; /* # of rcvd ece */ + u_int32_t tcps_ecn_rcvcwr; /* # of rcvd cwr */ + u_int32_t tcps_ecn_rcvce; /* # of rcvd ce in ip header */ + u_int32_t tcps_ecn_sndect; /* # of cwr sent */ + u_int32_t tcps_ecn_sndece; /* # of ece sent */ + u_int32_t tcps_ecn_sndcwr; /* # of cwr sent */ + u_int32_t tcps_cwr_ecn; /* # of cwnd reduced by ecn */ + u_int32_t tcps_cwr_frecovery; /* # of cwnd reduced by fastrecovery */ + u_int32_t tcps_cwr_timeout; /* # of cwnd reduced by timeout */ + + /* These statistics deal with the SYN cache. */ + u_int64_t tcps_sc_added; /* # of entries added */ + u_int64_t tcps_sc_completed; /* # of connections completed */ + u_int64_t tcps_sc_timed_out; /* # of entries timed out */ + u_int64_t tcps_sc_overflowed; /* # dropped due to overflow */ + u_int64_t tcps_sc_reset; /* # dropped due to RST */ + u_int64_t tcps_sc_unreach; /* # dropped due to ICMP unreach */ + u_int64_t tcps_sc_bucketoverflow;/* # dropped due to bucket overflow */ + u_int64_t tcps_sc_aborted; /* # of entries aborted (no mem) */ + u_int64_t tcps_sc_dupesyn; /* # of duplicate SYNs received */ + u_int64_t tcps_sc_dropped; /* # of SYNs dropped (no route/mem) */ + u_int64_t tcps_sc_collisions; /* # of hash collisions */ + u_int64_t tcps_sc_retransmitted;/* # of retransmissions */ + u_int64_t tcps_sc_seedrandom; /* # of syn cache seeds with random */ + u_int64_t tcps_sc_hash_size; /* hash buckets in current syn cache */ + u_int64_t tcps_sc_entry_count; /* # of entries in current syn cache */ + u_int64_t tcps_sc_entry_limit; /* limit of syn cache entries */ + u_int64_t tcps_sc_bucket_maxlen;/* maximum # of entries in any bucket */ + u_int64_t tcps_sc_bucket_limit; /* limit of syn cache bucket list */ + int64_t tcps_sc_uses_left; /* use counter of current syn cache */ + + u_int64_t tcps_conndrained; /* # of connections drained */ + + u_int64_t tcps_sack_recovery_episode; /* SACK recovery episodes */ + u_int64_t tcps_sack_rexmits; /* SACK rexmit segments */ + u_int64_t tcps_sack_rexmit_bytes; /* SACK rexmit bytes */ + u_int64_t tcps_sack_rcv_opts; /* SACK options received */ + u_int64_t tcps_sack_snd_opts; /* SACK options sent */ + u_int64_t tcps_sack_drop_opts; /* SACK options dropped */ + + u_int32_t tcps_outswtso; /* output tso chopped in software */ + u_int32_t tcps_outhwtso; /* output tso processed by hardware */ + u_int32_t tcps_outpkttso; /* packets generated by tso */ + u_int32_t tcps_outbadtso; /* output tso failed, packet dropped */ + u_int32_t tcps_inswlro; /* input lro on pseudo device */ + u_int32_t tcps_inhwlro; /* input lro from hardware */ + u_int32_t tcps_inpktlro; /* packets coalesced by hardware lro */ + u_int32_t tcps_inbadlro; /* input bad lro packets */ +}; + +/* + * Names for TCP sysctl objects. + */ + +#define TCPCTL_RFC1323 1 /* enable RFC1323 timestamps/scaling */ +#define TCPCTL_KEEPINITTIME 2 /* TCPT_KEEP value */ +#define TCPCTL_KEEPIDLE 3 /* allow tcp_keepidle to be changed */ +#define TCPCTL_KEEPINTVL 4 /* allow tcp_keepintvl to be changed */ +#define TCPCTL_SLOWHZ 5 /* return kernel idea of PR_SLOWHZ */ +#define TCPCTL_BADDYNAMIC 6 /* return bad dynamic port bitmap */ +#define TCPCTL_RECVSPACE 7 /* receive buffer space */ +#define TCPCTL_SENDSPACE 8 /* send buffer space */ +#define TCPCTL_IDENT 9 /* get connection owner */ +#define TCPCTL_SACK 10 /* selective acknowledgement, rfc 2018 */ +#define TCPCTL_MSSDFLT 11 /* Default maximum segment size */ +#define TCPCTL_RSTPPSLIMIT 12 /* RST pps limit */ +#define TCPCTL_ACK_ON_PUSH 13 /* ACK immediately on PUSH */ +#define TCPCTL_ECN 14 /* RFC3168 ECN */ +#define TCPCTL_SYN_CACHE_LIMIT 15 /* max size of comp. state engine */ +#define TCPCTL_SYN_BUCKET_LIMIT 16 /* max size of hash bucket */ +#define TCPCTL_RFC3390 17 /* enable/disable RFC3390 increased cwnd */ +#define TCPCTL_REASS_LIMIT 18 /* max entries for tcp reass queues */ +#define TCPCTL_DROP 19 /* drop tcp connection */ +#define TCPCTL_SACKHOLE_LIMIT 20 /* max entries for tcp sack queues */ +#define TCPCTL_STATS 21 /* TCP statistics */ +#define TCPCTL_ALWAYS_KEEPALIVE 22 /* assume SO_KEEPALIVE is always set */ +#define TCPCTL_SYN_USE_LIMIT 23 /* number of uses before reseeding hash */ +#define TCPCTL_ROOTONLY 24 /* return root only port bitmap */ +#define TCPCTL_SYN_HASH_SIZE 25 /* number of buckets in the hash */ +#define TCPCTL_TSO 26 /* enable TCP segmentation offload */ +#define TCPCTL_MAXID 27 + +#define TCPCTL_NAMES { \ + { 0, 0 }, \ + { "rfc1323", CTLTYPE_INT }, \ + { "keepinittime", CTLTYPE_INT }, \ + { "keepidle", CTLTYPE_INT }, \ + { "keepintvl", CTLTYPE_INT }, \ + { NULL, 0 }, \ + { "baddynamic", CTLTYPE_STRUCT }, \ + { NULL, 0 }, \ + { NULL, 0 }, \ + { "ident", CTLTYPE_STRUCT }, \ + { "sack", CTLTYPE_INT }, \ + { "mssdflt", CTLTYPE_INT }, \ + { "rstppslimit", CTLTYPE_INT }, \ + { "ackonpush", CTLTYPE_INT }, \ + { "ecn", CTLTYPE_INT }, \ + { "syncachelimit", CTLTYPE_INT }, \ + { "synbucketlimit", CTLTYPE_INT }, \ + { "rfc3390", CTLTYPE_INT }, \ + { "reasslimit", CTLTYPE_INT }, \ + { "drop", CTLTYPE_STRUCT }, \ + { "sackholelimit", CTLTYPE_INT }, \ + { "stats", CTLTYPE_STRUCT }, \ + { "always_keepalive", CTLTYPE_INT }, \ + { "synuselimit", CTLTYPE_INT }, \ + { "rootonly", CTLTYPE_STRUCT }, \ + { "synhashsize", CTLTYPE_INT }, \ + { "tso", CTLTYPE_INT }, \ +} + +struct tcp_ident_mapping { + struct sockaddr_storage faddr, laddr; + int euid, ruid; + u_int rdomain; +}; + +#ifdef _KERNEL + +#include +#include + +enum tcpstat_counters { + tcps_connattempt, + tcps_accepts, + tcps_connects, + tcps_drops, + tcps_conndrops, + tcps_closed, + tcps_segstimed, + tcps_rttupdated, + tcps_delack, + tcps_timeoutdrop, + tcps_rexmttimeo, + tcps_persisttimeo, + tcps_persistdrop, + tcps_keeptimeo, + tcps_keepprobe, + tcps_keepdrops, + tcps_sndtotal, + tcps_sndpack, + tcps_sndbyte, + tcps_sndrexmitpack, + tcps_sndrexmitbyte, + tcps_sndrexmitfast, + tcps_sndacks, + tcps_sndprobe, + tcps_sndurg, + tcps_sndwinup, + tcps_sndctrl, + tcps_rcvtotal, + tcps_rcvpack, + tcps_rcvbyte, + tcps_rcvbadsum, + tcps_rcvbadoff, + tcps_rcvmemdrop, + tcps_rcvnosec, + tcps_rcvshort, + tcps_rcvduppack, + tcps_rcvdupbyte, + tcps_rcvpartduppack, + tcps_rcvpartdupbyte, + tcps_rcvoopack, + tcps_rcvoobyte, + tcps_rcvpackafterwin, + tcps_rcvbyteafterwin, + tcps_rcvafterclose, + tcps_rcvwinprobe, + tcps_rcvdupack, + tcps_rcvacktoomuch, + tcps_rcvacktooold, + tcps_rcvackpack, + tcps_rcvackbyte, + tcps_rcvwinupd, + tcps_pawsdrop, + tcps_predack, + tcps_preddat, + tcps_pcbhashmiss, + tcps_noport, + tcps_closing, + tcps_badsyn, + tcps_dropsyn, + tcps_rcvbadsig, + tcps_rcvgoodsig, + tcps_inswcsum, + tcps_outswcsum, + tcps_ecn_accepts, + tcps_ecn_rcvece, + tcps_ecn_rcvcwr, + tcps_ecn_rcvce, + tcps_ecn_sndect, + tcps_ecn_sndece, + tcps_ecn_sndcwr, + tcps_cwr_ecn, + tcps_cwr_frecovery, + tcps_cwr_timeout, + tcps_sc_added, + tcps_sc_completed, + tcps_sc_timed_out, + tcps_sc_overflowed, + tcps_sc_reset, + tcps_sc_unreach, + tcps_sc_bucketoverflow, + tcps_sc_aborted, + tcps_sc_dupesyn, + tcps_sc_dropped, + tcps_sc_collisions, + tcps_sc_retransmitted, + tcps_sc_seedrandom, + tcps_sc_hash_size, + tcps_sc_entry_count, + tcps_sc_entry_limit, + tcps_sc_bucket_maxlen, + tcps_sc_bucket_limit, + tcps_sc_uses_left, + tcps_conndrained, + tcps_sack_recovery_episode, + tcps_sack_rexmits, + tcps_sack_rexmit_bytes, + tcps_sack_rcv_opts, + tcps_sack_snd_opts, + tcps_sack_drop_opts, + tcps_outswtso, + tcps_outhwtso, + tcps_outpkttso, + tcps_outbadtso, + tcps_inswlro, + tcps_inhwlro, + tcps_inpktlro, + tcps_inbadlro, + tcps_ncounters, +}; + +extern struct cpumem *tcpcounters; + +static inline void +tcpstat_inc(enum tcpstat_counters c) +{ + int s = splnet(); + counters_inc(tcpcounters, c); + splx(s); +} + +static inline void +tcpstat_add(enum tcpstat_counters c, uint64_t v) +{ + int s = splnet(); + counters_add(tcpcounters, c, v); + splx(s); +} + +static inline void +tcpstat_pkt(enum tcpstat_counters pcounter, enum tcpstat_counters bcounter, + uint64_t v) +{ + int s = splnet(); + counters_pkt(tcpcounters, pcounter, bcounter, v); + splx(s); +} + +extern uint64_t tcp_starttime; + +static inline uint64_t +tcp_now(void) +{ + /* TCP time ticks in 63 bit milliseconds with 63 bit random offset. */ + return tcp_starttime + (getnsecruntime() / 1000000ULL); +} + +#define TCP_TIME(_sec) ((_sec) * 1000) /* tcp_now() is in milliseconds */ + +extern struct mutex tcp_timer_mtx; +extern const struct pr_usrreqs tcp_usrreqs; + +#ifdef INET6 +extern const struct pr_usrreqs tcp6_usrreqs; +#endif + +extern struct pool tcpcb_pool; +extern struct inpcbtable tcbtable, tcb6table; /* queue of active tcpcb's */ +extern int tcp_do_rfc1323; /* [a] enabled/disabled? */ +extern const int tcprexmtthresh; +extern int tcp_mssdflt; /* [a] default maximum segment size */ +extern int tcp_rst_ppslim; /* [a] maximum outgoing RST packet per second */ +extern int tcp_ack_on_push; /* [a] ACK immediately on PUSH */ +extern int tcp_do_sack; /* [a] SACK enabled/disabled */ +extern struct pool sackhl_pool; +extern int tcp_sackhole_limit; /* max entries for tcp sack queues */ +extern int tcp_do_ecn; /* [a] RFC3168 ECN enabled/disabled? */ +extern int tcp_do_rfc3390; /* [a] RFC3390 Increasing TCP Initial Window */ +extern int tcp_do_tso; /* [a] enable TSO for TCP output packets */ + +extern struct pool tcpqe_pool; +extern int tcp_reass_limit; /* max entries for tcp reass queues */ + +extern int tcp_syn_hash_size; /* adjustable size of the hash array */ +extern int tcp_syn_cache_limit; /* max entries for compressed state engine */ +extern int tcp_syn_bucket_limit;/* max entries per hash bucket */ +extern int tcp_syn_use_limit; /* number of uses before reseeding hash */ +extern struct syn_cache_set tcp_syn_cache[]; +extern int tcp_syn_cache_active; /* active syn cache, may be 0 or 1 */ + +struct tdb; + +void tcp_canceltimers(struct tcpcb *); +struct tcpcb * + tcp_close(struct tcpcb *); +int tcp_freeq(struct tcpcb *); +#ifdef INET6 +void tcp6_ctlinput(int, struct sockaddr *, u_int, void *); +#endif +void tcp_ctlinput(int, struct sockaddr *, u_int, void *); +int tcp_ctloutput(int, struct socket *, int, int, struct mbuf *); +struct tcpcb * + tcp_dodisconnect(struct tcpcb *); +struct tcpcb * + tcp_drop(struct tcpcb *, int); +int tcp_dooptions(struct tcpcb *, u_char *, int, struct tcphdr *, + struct mbuf *, int, struct tcp_opt_info *, u_int, uint64_t); +void tcp_init(void); +int tcp_input(struct mbuf **, int *, int, int, struct netstack *); +void tcp_input_mlist(struct mbuf_list *, int); +int tcp_mss(struct tcpcb *, int); +void tcp_mss_update(struct tcpcb *); +void tcp_softlro_glue(struct mbuf_list *, struct mbuf *, struct ifnet *); +u_int tcp_hdrsz(struct tcpcb *); +void tcp_mtudisc(struct inpcb *, int); +void tcp_mtudisc_increase(struct inpcb *, int); +#ifdef INET6 +void tcp6_mtudisc_callback(struct sockaddr_in6 *, u_int); +#endif +struct tcpcb * + tcp_newtcpcb(struct inpcb *, int); +void tcp_notify(struct inpcb *, int); +int tcp_output(struct tcpcb *); +int tcp_softtso_chop(struct mbuf_list *, struct mbuf *, struct ifnet *, + u_int); +int tcp_if_output_tso(struct ifnet *, struct mbuf **, struct sockaddr *, + struct rtentry *, uint32_t, u_int); +void tcp_pulloutofband(struct socket *, u_int, struct mbuf *, int); +int tcp_reass(struct tcpcb *, struct tcphdr *, struct mbuf *, int *); +void tcp_rscale(struct tcpcb *, u_long); +void tcp_respond(struct tcpcb *, caddr_t, struct tcphdr *, tcp_seq, + tcp_seq, int, u_int, uint64_t); +void tcp_setpersist(struct tcpcb *); +void tcp_update_sndspace(struct tcpcb *); +void tcp_update_rcvspace(struct tcpcb *); +void tcp_slowtimo(void); +struct mbuf * + tcp_template(struct tcpcb *); +#ifndef SMALL_KERNEL +void tcp_trace(short, short, struct tcpcb *, struct tcpcb *, caddr_t, + int, int); +#endif +struct tcpcb * + tcp_usrclosed(struct tcpcb *); +int tcp_sysctl(int *, u_int, void *, size_t *, void *, size_t); +int tcp_attach(struct socket *, int, int); +int tcp_detach(struct socket *); +int tcp_bind(struct socket *, struct mbuf *, struct proc *); +int tcp_listen(struct socket *); +int tcp_connect(struct socket *, struct mbuf *); +int tcp_accept(struct socket *, struct mbuf *); +int tcp_disconnect(struct socket *); +int tcp_shutdown(struct socket *); +void tcp_rcvd(struct socket *); +int tcp_send(struct socket *, struct mbuf *, struct mbuf *, + struct mbuf *); +void tcp_abort(struct socket *); +int tcp_sockaddr(struct socket *, struct mbuf *); +int tcp_peeraddr(struct socket *, struct mbuf *); +int tcp_sense(struct socket *, struct stat *); +int tcp_rcvoob(struct socket *, struct mbuf *, int); +int tcp_sendoob(struct socket *, struct mbuf *, struct mbuf *, + struct mbuf *); +void tcp_xmit_timer(struct tcpcb *, int32_t); +void tcp_sack_option(struct tcpcb *,struct tcphdr *,u_char *,int); +void tcp_update_sack_list(struct tcpcb *tp, tcp_seq, tcp_seq); +void tcp_del_sackholes(struct tcpcb *, struct tcphdr *); +void tcp_clean_sackreport(struct tcpcb *tp); +void tcp_sack_adjust(struct tcpcb *tp); +struct sackhole * + tcp_sack_output(struct tcpcb *tp); +#ifdef DEBUG +void tcp_print_holes(struct tcpcb *tp); +#endif +u_long tcp_seq_subtract(u_long, u_long ); +#ifdef TCP_SIGNATURE +int tcp_signature_apply(caddr_t, caddr_t, unsigned int); +int tcp_signature(struct tdb *, int, struct mbuf *, struct tcphdr *, + int, int, char *); +#endif /* TCP_SIGNATURE */ +void tcp_set_iss_tsm(struct tcpcb *); + +void syn_cache_unreach(const struct sockaddr *, const struct sockaddr *, + struct tcphdr *, u_int); +void syn_cache_init(void); +void syn_cache_cleanup(struct tcpcb *); + +#ifdef SMALL_KERNEL +static inline void +tcp_trace(short act, short ostate, struct tcpcb *tp, struct tcpcb *otp, + caddr_t headers, int req, int len) +{ +} +#endif + +#endif /* _KERNEL */ +#endif /* _NETINET_TCP_VAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/udp.h b/lib/libc/include/generic-openbsd/netinet/udp.h new file mode 100644 index 000000000000..2726aee8db18 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/udp.h @@ -0,0 +1,49 @@ +/* $OpenBSD: udp.h,v 1.5 2003/06/02 23:28:15 millert Exp $ */ +/* $NetBSD: udp.h,v 1.6 1995/04/13 06:37:10 cgd Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)udp.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_UDP_H_ +#define _NETINET_UDP_H_ + +/* + * Udp protocol header. + * Per RFC 768, September, 1981. + */ +struct udphdr { + u_int16_t uh_sport; /* source port */ + u_int16_t uh_dport; /* destination port */ + u_int16_t uh_ulen; /* udp length */ + u_int16_t uh_sum; /* udp checksum */ +}; + +#endif /* _NETINET_UDP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet/udp_var.h b/lib/libc/include/generic-openbsd/netinet/udp_var.h new file mode 100644 index 000000000000..c7e3d70b2fc6 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet/udp_var.h @@ -0,0 +1,155 @@ +/* $OpenBSD: udp_var.h,v 1.53 2025/03/02 21:28:32 bluhm Exp $ */ +/* $NetBSD: udp_var.h,v 1.12 1996/02/13 23:44:41 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)udp_var.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_UDP_VAR_H_ +#define _NETINET_UDP_VAR_H_ + +/* + * UDP kernel structures and variables. + */ +struct udpiphdr { + struct ipovly ui_i; /* overlaid ip structure */ + struct udphdr ui_u; /* udp header */ +}; +#define ui_x1 ui_i.ih_x1 +#define ui_pr ui_i.ih_pr +#define ui_len ui_i.ih_len +#define ui_src ui_i.ih_src +#define ui_dst ui_i.ih_dst +#define ui_sport ui_u.uh_sport +#define ui_dport ui_u.uh_dport +#define ui_ulen ui_u.uh_ulen +#define ui_sum ui_u.uh_sum + +struct udpstat { + /* input statistics: */ + u_long udps_ipackets; /* total input packets */ + u_long udps_hdrops; /* packet shorter than header */ + u_long udps_badsum; /* checksum error */ + u_long udps_nosum; /* no checksum */ + u_long udps_badlen; /* data length larger than packet */ + u_long udps_noport; /* no socket on port */ + u_long udps_noportbcast; /* of above, arrived as broadcast */ + u_long udps_nosec; /* dropped for lack of ipsec */ + u_long udps_fullsock; /* not delivered, input socket full */ + u_long udps_pcbhashmiss; /* input packets missing pcb hash */ + u_long udps_inswcsum; /* input software-csummed packets */ + /* output statistics: */ + u_long udps_opackets; /* total output packets */ + u_long udps_outswcsum; /* output software-csummed packets */ +}; + +/* + * Names for UDP sysctl objects + */ +#define UDPCTL_CHECKSUM 1 /* checksum UDP packets */ +#define UDPCTL_BADDYNAMIC 2 /* return bad dynamic port bitmap */ +#define UDPCTL_RECVSPACE 3 /* receive buffer space */ +#define UDPCTL_SENDSPACE 4 /* send buffer space */ +#define UDPCTL_STATS 5 /* UDP statistics */ +#define UDPCTL_ROOTONLY 6 /* root only port bitmap */ +#define UDPCTL_MAXID 7 + +#define UDPCTL_NAMES { \ + { 0, 0 }, \ + { "checksum", CTLTYPE_INT }, \ + { "baddynamic", CTLTYPE_STRUCT }, \ + { "recvspace", CTLTYPE_INT }, \ + { "sendspace", CTLTYPE_INT }, \ + { "stats", CTLTYPE_STRUCT }, \ + { "rootonly", CTLTYPE_STRUCT }, \ +} + +#ifdef _KERNEL + +#include + +enum udpstat_counters { + /* input statistics: */ + udps_ipackets, /* total input packets */ + udps_hdrops, /* packet shorter than header */ + udps_badsum, /* checksum error */ + udps_nosum, /* no checksum */ + udps_badlen, /* data length larger than packet */ + udps_noport, /* no socket on port */ + udps_noportbcast, /* of above, arrived as broadcast */ + udps_nosec, /* dropped for lack of ipsec */ + udps_fullsock, /* not delivered, input socket full */ + udps_pcbhashmiss, /* input packets missing pcb hash */ + udps_inswcsum, /* input software-csummed packets */ + /* output statistics: */ + udps_opackets, /* total output packets */ + udps_outswcsum, /* output software-csummed packets */ + + udps_ncounters +}; + +extern struct cpumem *udpcounters; + +static inline void +udpstat_inc(enum udpstat_counters c) +{ + counters_inc(udpcounters, c); +} + +extern struct inpcbtable udbtable, udb6table; +extern struct udpstat udpstat; + +extern const struct pr_usrreqs udp_usrreqs; + +#ifdef INET6 +extern const struct pr_usrreqs udp6_usrreqs; +#endif + +#ifdef INET6 +void udp6_ctlinput(int, struct sockaddr *, u_int, void *); +#endif /* INET6 */ +void udp_ctlinput(int, struct sockaddr *, u_int, void *); +void udp_init(void); +int udp_input(struct mbuf **, int *, int, int, struct netstack *); +#ifdef INET6 +int udp6_output(struct inpcb *, struct mbuf *, struct mbuf *, + struct mbuf *); +#endif /* INET6 */ +int udp_sysctl(int *, u_int, void *, size_t *, void *, size_t); +int udp_attach(struct socket *, int, int); +int udp_detach(struct socket *); +int udp_bind(struct socket *, struct mbuf *, struct proc *); +int udp_connect(struct socket *, struct mbuf *); +int udp_disconnect(struct socket *); +int udp_shutdown(struct socket *); +int udp_send(struct socket *, struct mbuf *, struct mbuf *, + struct mbuf *); +#endif /* _KERNEL */ +#endif /* _NETINET_UDP_VAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet6/in6.h b/lib/libc/include/generic-openbsd/netinet6/in6.h new file mode 100644 index 000000000000..f1130bdbae94 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet6/in6.h @@ -0,0 +1,685 @@ +/* $OpenBSD: in6.h,v 1.125 2025/09/16 09:19:16 florian Exp $ */ +/* $KAME: in6.h,v 1.83 2001/03/29 02:55:07 jinmei Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)in.h 8.3 (Berkeley) 1/3/94 + */ + +#ifndef __KAME_NETINET_IN_H_INCLUDED_ +#error "do not include netinet6/in6.h directly, include netinet/in.h. see RFC2553" +#endif + +#ifndef _NETINET6_IN6_H_ +#define _NETINET6_IN6_H_ + +/* + * Identification of the network protocol stack + * for *BSD-current/release: http://www.kame.net/dev/cvsweb2.cgi/kame/COVERAGE + * has the table of implementation/integration differences. + */ +#define __KAME__ + +/* + * IPv6 address + */ +struct in6_addr { + union { + u_int8_t __u6_addr8[16]; + u_int16_t __u6_addr16[8]; + u_int32_t __u6_addr32[4]; + } __u6_addr; /* 128-bit IP6 address */ +}; + +#define s6_addr __u6_addr.__u6_addr8 +#ifdef _KERNEL /* XXX nonstandard */ +#define s6_addr8 __u6_addr.__u6_addr8 +#define s6_addr16 __u6_addr.__u6_addr16 +#define s6_addr32 __u6_addr.__u6_addr32 +#endif + +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 46 +#endif + +/* + * Socket address for IPv6 + */ +#if __BSD_VISIBLE +#define SIN6_LEN /* Indicates sockaddr_in6 has a sin6_len field */ +#endif /* __BSD_VISIBLE */ +struct sockaddr_in6 { + u_int8_t sin6_len; /* length of this struct(sa_family_t)*/ + sa_family_t sin6_family; /* AF_INET6 (sa_family_t) */ + in_port_t sin6_port; /* Transport layer port # (in_port_t)*/ + u_int32_t sin6_flowinfo; /* IP6 flow information */ + struct in6_addr sin6_addr; /* IP6 address */ + u_int32_t sin6_scope_id; /* intface scope id */ +}; + + +/* + * Local definition for masks + */ +#ifdef _KERNEL /* XXX nonstandard */ +#define IN6MASK0 {{{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}} +#define IN6MASK32 {{{ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}} +#define IN6MASK64 {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}} +#define IN6MASK96 {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }}} +#define IN6MASK128 {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}} + +extern const struct sockaddr_in6 sa6_any; + +extern const struct in6_addr in6mask0; +extern const struct in6_addr in6mask32; +extern const struct in6_addr in6mask64; +extern const struct in6_addr in6mask96; +extern const struct in6_addr in6mask128; +#endif /* _KERNEL */ + +/* Both kernel and libc define these for use */ +extern const struct in6_addr in6addr_any; +extern const struct in6_addr in6addr_loopback; +extern const struct in6_addr in6addr_intfacelocal_allnodes; +extern const struct in6_addr in6addr_linklocal_allnodes; +extern const struct in6_addr in6addr_linklocal_allrouters; + +#if __BSD_VISIBLE +/* + * Definition of some useful macros to handle IP6 addresses + */ +#define IN6ADDR_ANY_INIT \ + {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}} +#define IN6ADDR_LOOPBACK_INIT \ + {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}} +#define IN6ADDR_NODELOCAL_ALLNODES_INIT \ + {{{ 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}} +#define IN6ADDR_INTFACELOCAL_ALLNODES_INIT \ + {{{ 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}} +#define IN6ADDR_LINKLOCAL_ALLNODES_INIT \ + {{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}} +#define IN6ADDR_LINKLOCAL_ALLROUTERS_INIT \ + {{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }}} + +#define IN6_ARE_ADDR_EQUAL(a, b) \ + (memcmp(&(a)->s6_addr[0], &(b)->s6_addr[0], sizeof(struct in6_addr)) == 0) + +#endif /* __BSD_VISIBLE */ + +/* + * Macros started with IPV6_ADDR is KAME local + */ +#define __IPV6_ADDR_INT32_ONE htonl(1) +#define __IPV6_ADDR_INT32_TWO htonl(2) +#define __IPV6_ADDR_INT32_MNL htonl(0xff010000) +#define __IPV6_ADDR_INT32_MLL htonl(0xff020000) +#define __IPV6_ADDR_INT32_SMP htonl(0x0000ffff) +#define __IPV6_ADDR_INT16_ULL htons(0xfe80) +#define __IPV6_ADDR_INT16_USL htons(0xfec0) +#define __IPV6_ADDR_INT16_MLL htons(0xff02) + +/* + * Unspecified + */ +#define IN6_IS_ADDR_UNSPECIFIED(a) \ + ((*(const u_int32_t *)(const void *)(&(a)->s6_addr[0]) == 0) && \ + (*(const u_int32_t *)(const void *)(&(a)->s6_addr[4]) == 0) && \ + (*(const u_int32_t *)(const void *)(&(a)->s6_addr[8]) == 0) && \ + (*(const u_int32_t *)(const void *)(&(a)->s6_addr[12]) == 0)) + +/* + * Loopback + */ +#define IN6_IS_ADDR_LOOPBACK(a) \ + ((*(const u_int32_t *)(const void *)(&(a)->s6_addr[0]) == 0) && \ + (*(const u_int32_t *)(const void *)(&(a)->s6_addr[4]) == 0) && \ + (*(const u_int32_t *)(const void *)(&(a)->s6_addr[8]) == 0) && \ + (*(const u_int32_t *)(const void *)(&(a)->s6_addr[12]) == __IPV6_ADDR_INT32_ONE)) + +/* + * IPv4 compatible + */ +#define IN6_IS_ADDR_V4COMPAT(a) \ + ((*(const u_int32_t *)(const void *)(&(a)->s6_addr[0]) == 0) && \ + (*(const u_int32_t *)(const void *)(&(a)->s6_addr[4]) == 0) && \ + (*(const u_int32_t *)(const void *)(&(a)->s6_addr[8]) == 0) && \ + (*(const u_int32_t *)(const void *)(&(a)->s6_addr[12]) != 0) && \ + (*(const u_int32_t *)(const void *)(&(a)->s6_addr[12]) != __IPV6_ADDR_INT32_ONE)) + +/* + * Mapped + */ +#define IN6_IS_ADDR_V4MAPPED(a) \ + ((*(const u_int32_t *)(const void *)(&(a)->s6_addr[0]) == 0) && \ + (*(const u_int32_t *)(const void *)(&(a)->s6_addr[4]) == 0) && \ + (*(const u_int32_t *)(const void *)(&(a)->s6_addr[8]) == __IPV6_ADDR_INT32_SMP)) + +/* + * Unicast Scope + * Note that we must check topmost 10 bits only, not 16 bits (see RFC2373). + */ +#define IN6_IS_ADDR_LINKLOCAL(a) \ + (((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0x80)) +#define IN6_IS_ADDR_SITELOCAL(a) \ + (((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0xc0)) + +/* + * Multicast + */ +#define __IPV6_ADDR_MC_SCOPE(a) ((a)->s6_addr[1] & 0x0f) +#define IN6_IS_ADDR_MULTICAST(a) ((a)->s6_addr[0] == 0xff) + +#define __IPV6_ADDR_SCOPE_NODELOCAL 0x01 +#define __IPV6_ADDR_SCOPE_INTFACELOCAL 0x01 +#define __IPV6_ADDR_SCOPE_LINKLOCAL 0x02 +#define __IPV6_ADDR_SCOPE_SITELOCAL 0x05 +#define __IPV6_ADDR_SCOPE_ORGLOCAL 0x08 /* just used in this file */ +#define __IPV6_ADDR_SCOPE_GLOBAL 0x0e + +#define IN6_IS_ADDR_MC_NODELOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && \ + (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_NODELOCAL)) +#define IN6_IS_ADDR_MC_INTFACELOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && \ + (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_INTFACELOCAL)) +#define IN6_IS_ADDR_MC_LINKLOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && \ + (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_LINKLOCAL)) +#define IN6_IS_ADDR_MC_SITELOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && \ + (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_SITELOCAL)) +#define IN6_IS_ADDR_MC_ORGLOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && \ + (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_ORGLOCAL)) +#define IN6_IS_ADDR_MC_GLOBAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && \ + (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_GLOBAL)) + +#ifdef _KERNEL +#define IN6_IS_SCOPE_LINKLOCAL(a) \ + ((IN6_IS_ADDR_LINKLOCAL(a)) || \ + (IN6_IS_ADDR_MC_LINKLOCAL(a))) +#define IN6_IS_SCOPE_EMBED(a) \ + ((IN6_IS_ADDR_LINKLOCAL(a)) || \ + (IN6_IS_ADDR_MC_LINKLOCAL(a)) || \ + (IN6_IS_ADDR_MC_INTFACELOCAL(a))) + +#define IFA6_IS_DEPRECATED(a) \ + ((a)->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME && \ + (u_int32_t)((getuptime() - (a)->ia6_updatetime)) > \ + (a)->ia6_lifetime.ia6t_pltime) +#define IFA6_IS_INVALID(a) \ + ((a)->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME && \ + (u_int32_t)((getuptime() - (a)->ia6_updatetime)) > \ + (a)->ia6_lifetime.ia6t_vltime) + +#endif /* _KERNEL */ + +/* + * Options for use with [gs]etsockopt at the IPV6 level. + * First word of comment is data type; bool is stored in int. + */ +#define IPV6_UNICAST_HOPS 4 /* int; IP6 hops */ +#define IPV6_MULTICAST_IF 9 /* u_int; set/get IP6 multicast i/f */ +#define IPV6_MULTICAST_HOPS 10 /* u_int; set/get IP6 multicast hops */ +#define IPV6_MULTICAST_LOOP 11 /* u_int; set/get IP6 multicast loopback */ +#define IPV6_JOIN_GROUP 12 /* ip6_mreq; join a group membership */ +#define IPV6_LEAVE_GROUP 13 /* ip6_mreq; leave a group membership */ +#define IPV6_PORTRANGE 14 /* int; range to choose for unspec port */ +#if __BSD_VISIBLE +#define ICMP6_FILTER 18 /* icmp6_filter; icmp6 filter */ +#endif + +#define IPV6_CHECKSUM 26 /* int; checksum offset for raw socket */ +#define IPV6_V6ONLY 27 /* bool; make AF_INET6 sockets v6 only */ + +/* new socket options introduced in RFC3542 */ +#define IPV6_RTHDRDSTOPTS 35 /* ip6_dest; send dst option before rthdr */ + +#define IPV6_RECVPKTINFO 36 /* bool; recv if, dst addr */ +#define IPV6_RECVHOPLIMIT 37 /* bool; recv hop limit */ +#define IPV6_RECVRTHDR 38 /* bool; recv routing header */ +#define IPV6_RECVHOPOPTS 39 /* bool; recv hop-by-hop option */ +#define IPV6_RECVDSTOPTS 40 /* bool; recv dst option after rthdr */ + +#define IPV6_USE_MIN_MTU 42 /* bool; send packets at the minimum MTU */ +#define IPV6_RECVPATHMTU 43 /* bool; notify an according MTU */ + +#define IPV6_PATHMTU 44 /* mtuinfo; get the current path MTU (sopt), + 4 bytes int; MTU notification (cmsg) */ + +/* More new socket options introduced in RFC3542 */ +#define IPV6_PKTINFO 46 /* in6_pktinfo; send if, src addr */ +#define IPV6_HOPLIMIT 47 /* int; send hop limit */ +#define IPV6_NEXTHOP 48 /* sockaddr; next hop addr */ +#define IPV6_HOPOPTS 49 /* ip6_hbh; send hop-by-hop option */ +#define IPV6_DSTOPTS 50 /* ip6_dest; send dst option before rthdr */ +#define IPV6_RTHDR 51 /* ip6_rthdr; send routing header */ + +#define IPV6_AUTH_LEVEL 53 /* int; authentication used */ +#define IPV6_ESP_TRANS_LEVEL 54 /* int; transport encryption */ +#define IPV6_ESP_NETWORK_LEVEL 55 /* int; full-packet encryption */ +#if __BSD_VISIBLE +#define IPSEC6_OUTSA 56 /* set the outbound SA for a socket */ +#endif +#define IPV6_RECVTCLASS 57 /* bool; recv traffic class values */ + +#define IPV6_AUTOFLOWLABEL 59 /* bool; attach flowlabel automagically */ +#define IPV6_IPCOMP_LEVEL 60 /* int; compression */ + +#define IPV6_TCLASS 61 /* int; send traffic class value */ +#define IPV6_DONTFRAG 62 /* bool; disable IPv6 fragmentation */ +#define IPV6_PIPEX 63 /* bool; using PIPEX */ + +#define IPV6_RECVDSTPORT 64 /* bool; receive IP dst port w/dgram */ +#define IPV6_MINHOPCOUNT 65 /* int; minimum recv hop limit */ + +#define IPV6_RTABLE 0x1021 /* int; routing table, see SO_RTABLE */ + +/* to define items, should talk with KAME guys first, for *BSD compatibility */ +#define IPV6_RTHDR_LOOSE 0 /* this hop need not be a neighbor */ +#define IPV6_RTHDR_TYPE_0 0 /* IPv6 routing header type 0 */ + +/* + * Defaults and limits for options + */ +#define IPV6_DEFAULT_MULTICAST_HOPS 1 /* normally limit m'casts to 1 hop */ +#define IPV6_DEFAULT_MULTICAST_LOOP 1 /* normally hear sends if a member */ + +/* + * Argument structure for IPV6_JOIN_GROUP and IPV6_LEAVE_GROUP. + */ +struct ipv6_mreq { + struct in6_addr ipv6mr_multiaddr; + unsigned int ipv6mr_interface; +}; + +/* + * IPV6_PKTINFO: Packet information(RFC3542 sec 6) + */ +struct in6_pktinfo { + struct in6_addr ipi6_addr; /* src/dst IPv6 address */ + unsigned int ipi6_ifindex; /* send/recv interface index */ +}; + +/* + * Control structure for IPV6_RECVPATHMTU socket option. + * XXX Not allowed here by POSIX, but required by RFC 3542, so go + * XXX with the code on the pavement. + */ +struct ip6_mtuinfo { + struct sockaddr_in6 ip6m_addr; /* or sockaddr_storage? */ + u_int32_t ip6m_mtu; +}; + +/* + * Argument for IPV6_PORTRANGE: + * - which range to search when port is unspecified at bind() or connect() + */ +#define IPV6_PORTRANGE_DEFAULT 0 /* default range */ +#define IPV6_PORTRANGE_HIGH 1 /* "high" - request firewall bypass */ +#define IPV6_PORTRANGE_LOW 2 /* "low" - vouchsafe security */ + +#ifdef __BSD_VISIBLE + +#ifndef _SOCKLEN_T_DEFINED_ +#define _SOCKLEN_T_DEFINED_ +typedef __socklen_t socklen_t; /* length type for network syscalls */ +#endif + +#endif /* __BSD_VISIBLE */ + +#ifdef _KERNEL +extern const u_char inet6ctlerrmap[]; +extern const struct in6_addr zeroin6_addr; + +struct mbuf; +struct sockaddr; +struct sockaddr_in6; +struct ifaddr; +struct in6_ifaddr; +struct ifnet; +struct rtentry; +struct netstack; + +void ipv6_input(struct ifnet *, struct mbuf *, struct netstack *); +struct mbuf * + ipv6_check(struct ifnet *, struct mbuf *); + +int in6_cksum(struct mbuf *, uint8_t, uint32_t, uint32_t); +void in6_proto_cksum_out(struct mbuf *, struct ifnet *); +int in6_addrscope(const struct in6_addr *); +struct in6_ifaddr *in6_ifawithscope(struct ifnet *, const struct in6_addr *, + u_int, struct rtentry *); +int in6_mask2len(struct in6_addr *, u_char *); +int in6_nam2sin6(const struct mbuf *, struct sockaddr_in6 **); +int in6_sa2sin6(struct sockaddr *, struct sockaddr_in6 **); + +struct ip6_pktopts; +struct ip6_moptions; + +int in6_embedscope(struct in6_addr *, const struct sockaddr_in6 *, + const struct ip6_pktopts *, const struct ip6_moptions *); +void in6_recoverscope(struct sockaddr_in6 *, const struct in6_addr *); +void in6_clearscope(struct in6_addr *); + +/* + * Convert between address family specific and general structs. + * Inline functions check the source type and are stricter than + * casts or defines. + */ + +static inline struct sockaddr_in6 * +satosin6(struct sockaddr *sa) +{ + return ((struct sockaddr_in6 *)(sa)); +} + +static inline const struct sockaddr_in6 * +satosin6_const(const struct sockaddr *sa) +{ + return ((const struct sockaddr_in6 *)(sa)); +} + +static inline struct sockaddr * +sin6tosa(struct sockaddr_in6 *sin6) +{ + return ((struct sockaddr *)(sin6)); +} + +static inline const struct sockaddr * +sin6tosa_const(const struct sockaddr_in6 *sin6) +{ + return ((const struct sockaddr *)(sin6)); +} + +static inline struct in6_ifaddr * +ifatoia6(struct ifaddr *ifa) +{ + return ((struct in6_ifaddr *)(ifa)); +} + +#endif /* _KERNEL */ + +#if __BSD_VISIBLE +/* + * Definitions for inet6 sysctl operations. + * + * Third level is protocol number. + * Fourth level is desired variable within that protocol. + */ +#define IPV6PROTO_MAXID (IPPROTO_DIVERT + 1) /* don't list to IPV6PROTO_MAX */ + +#define CTL_IPV6PROTO_NAMES { \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, \ + { "tcp6", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "udp6", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, \ + { "ip6", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, \ + { "ipsec6", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "icmp6", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ +/*110*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ +/*120*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ +/*130*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ +/*140*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ +/*150*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ +/*160*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ +/*170*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ +/*180*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ +/*190*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ +/*200*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ +/*210*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ +/*220*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ +/*230*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ +/*240*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ +/*250*/ { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "divert", CTLTYPE_NODE }, \ +} + +/* + * Names for IP sysctl objects + */ +#define IPV6CTL_FORWARDING 1 /* act as router */ +#define IPV6CTL_SENDREDIRECTS 2 /* may send redirects when forwarding*/ +#define IPV6CTL_DEFHLIM 3 /* default Hop-Limit */ +#define IPV6CTL_FORWSRCRT 5 /* forward source-routed dgrams */ +#define IPV6CTL_STATS 6 /* stats */ +#define IPV6CTL_MRTSTATS 7 /* multicast forwarding stats */ +#define IPV6CTL_MRTPROTO 8 /* multicast routing protocol */ +#define IPV6CTL_MAXFRAGPACKETS 9 /* max packets reassembly queue */ +#define IPV6CTL_SOURCECHECK 10 /* verify source route and intf */ +#define IPV6CTL_SOURCECHECK_LOGINT 11 /* minimum logging interval */ +#define IPV6CTL_ACCEPT_RTADV 12 +#define IPV6CTL_LOG_INTERVAL 14 +#define IPV6CTL_HDRNESTLIMIT 15 +#define IPV6CTL_DAD_COUNT 16 +#define IPV6CTL_AUTO_FLOWLABEL 17 +#define IPV6CTL_DEFMCASTHLIM 18 +/* 24 to 40: reserved */ +#define IPV6CTL_MAXFRAGS 41 /* max fragments */ +#define IPV6CTL_MFORWARDING 42 +#define IPV6CTL_MULTIPATH 43 +#define IPV6CTL_MCAST_PMTU 44 /* path MTU discovery for multicast */ +#define IPV6CTL_NEIGHBORGCTHRESH 45 +#define IPV6CTL_MAXDYNROUTES 48 +#define IPV6CTL_DAD_PENDING 49 +#define IPV6CTL_MTUDISCTIMEOUT 50 +#define IPV6CTL_IFQUEUE 51 +#define IPV6CTL_MRTMIF 52 +#define IPV6CTL_MRTMFC 53 +#define IPV6CTL_MAXID 54 + +/* New entries should be added here from current IPV6CTL_MAXID value. */ +/* to define items, should talk with KAME guys first, for *BSD compatibility */ + +#define IPV6CTL_NAMES { \ + { 0, 0 }, \ + { "forwarding", CTLTYPE_INT }, \ + { "redirect", CTLTYPE_INT }, \ + { "hlim", CTLTYPE_INT }, \ + { 0, 0 }, \ + { "forwsrcrt", CTLTYPE_INT }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "mrtproto", CTLTYPE_INT }, \ + { "maxfragpackets", CTLTYPE_INT }, \ + { "sourcecheck", CTLTYPE_INT }, \ + { "sourcecheck_logint", CTLTYPE_INT }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "hdrnestlimit", CTLTYPE_INT }, \ + { "dad_count", CTLTYPE_INT }, \ + { 0, 0 }, \ + { "defmcasthlim", CTLTYPE_INT }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "maxfrags", CTLTYPE_INT }, \ + { "mforwarding", CTLTYPE_INT }, \ + { "multipath", CTLTYPE_INT }, \ + { "multicast_mtudisc", CTLTYPE_INT }, \ + { "neighborgcthresh", CTLTYPE_INT }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "maxdynroutes", CTLTYPE_INT }, \ + { "dad_pending", CTLTYPE_INT }, \ + { "mtudisctimeout", CTLTYPE_INT }, \ + { "ifq", CTLTYPE_NODE }, \ + { "mrtmif", CTLTYPE_STRUCT }, \ + { "mrtmfc", CTLTYPE_STRUCT }, \ +} + +__BEGIN_DECLS +struct cmsghdr; + +extern int inet6_opt_init(void *, socklen_t); +extern int inet6_opt_append(void *, socklen_t, int, u_int8_t, + socklen_t, u_int8_t, void **); +extern int inet6_opt_finish(void *, socklen_t, int); +extern int inet6_opt_set_val(void *, int, void *, socklen_t); + +extern int inet6_opt_next(void *, socklen_t, int, u_int8_t *, + socklen_t *, void **); +extern int inet6_opt_find(void *, socklen_t, int, u_int8_t, + socklen_t *, void **); +extern int inet6_opt_get_val(void *, int, void *, socklen_t); + +extern socklen_t inet6_rth_space(int, int); +extern void *inet6_rth_init(void *, socklen_t, int, int); +extern int inet6_rth_add(void *, const struct in6_addr *); +extern int inet6_rth_reverse(const void *, void *); +extern int inet6_rth_segments(const void *); +extern struct in6_addr *inet6_rth_getaddr(const void *, int); +__END_DECLS +#endif /* __BSD_VISIBLE */ + +#endif /* !_NETINET6_IN6_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet6/in6_ifattach.h b/lib/libc/include/generic-openbsd/netinet6/in6_ifattach.h new file mode 100644 index 000000000000..b299d23c9605 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet6/in6_ifattach.h @@ -0,0 +1,42 @@ +/* $OpenBSD: in6_ifattach.h,v 1.10 2019/08/21 15:32:18 florian Exp $ */ +/* $KAME: in6_ifattach.h,v 1.9 2000/04/12 05:35:48 itojun Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 _NETINET6_IN6_IFATTACH_H_ +#define _NETINET6_IN6_IFATTACH_H_ + +#ifdef _KERNEL +int in6_ifattach(struct ifnet *); +void in6_ifdetach(struct ifnet *); +int in6_ifattach_linklocal(struct ifnet *, struct in6_addr *); +#endif /* _KERNEL */ + +#endif /* _NETINET6_IN6_IFATTACH_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet6/in6_var.h b/lib/libc/include/generic-openbsd/netinet6/in6_var.h new file mode 100644 index 000000000000..c928f8f61931 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet6/in6_var.h @@ -0,0 +1,372 @@ +/* $OpenBSD: in6_var.h,v 1.81 2025/05/20 05:51:43 bluhm Exp $ */ +/* $KAME: in6_var.h,v 1.55 2001/02/16 12:49:45 itojun Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1985, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)in_var.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET6_IN6_VAR_H_ +#define _NETINET6_IN6_VAR_H_ + +/* + * Interface address, Internet version. One of these structures + * is allocated for each interface with an Internet address. + * The ifaddr structure contains the protocol-independent part + * of the structure and is assumed to be first. + */ + +/* + * pltime/vltime are just for future reference (required to implements 2 + * hour rule for hosts). they should never be modified by nd6_timeout or + * anywhere else. + * userland -> kernel: accept pltime/vltime + * kernel -> userland: throw up everything + * in kernel: modify preferred/expire only + */ +struct in6_addrlifetime { + time_t ia6t_expire; /* valid lifetime expiration time */ + time_t ia6t_preferred; /* preferred lifetime expiration time */ + u_int32_t ia6t_vltime; /* valid lifetime */ + u_int32_t ia6t_pltime; /* prefix lifetime */ +}; + +#ifdef _KERNEL +struct in6_ifaddr { + struct ifaddr ia_ifa; /* protocol-independent info */ +#define ia_ifp ia_ifa.ifa_ifp +#define ia_flags ia_ifa.ifa_flags + + struct sockaddr_in6 ia_addr; /* interface address */ + struct sockaddr_in6 ia_gwaddr; /* router we learned address from */ + struct sockaddr_in6 ia_dstaddr; /* space for destination addr */ + struct sockaddr_in6 ia_prefixmask; /* prefix mask */ + TAILQ_ENTRY(in6_ifaddr) ia_list; /* list of IP6 addresses */ + int ia6_flags; + + struct in6_addrlifetime ia6_lifetime; + time_t ia6_updatetime; + + /* multicast addresses joined from the kernel */ + LIST_HEAD(, in6_multi_mship) ia6_memberships; +}; +#endif /* _KERNEL */ + +/* + * IPv6 interface statistics, as defined in RFC2465 Ipv6IfStatsEntry (p12). + */ +struct in6_ifstat { + u_int64_t ifs6_in_receive; /* # of total input datagram */ + u_int64_t ifs6_in_hdrerr; /* # of datagrams with invalid hdr */ + u_int64_t ifs6_in_toobig; /* # of datagrams exceeded MTU */ + u_int64_t ifs6_in_noroute; /* # of datagrams with no route */ + u_int64_t ifs6_in_addrerr; /* # of datagrams with invalid dst */ + u_int64_t ifs6_in_protounknown; /* # of datagrams with unknown proto */ + /* NOTE: increment on final dst if */ + u_int64_t ifs6_in_truncated; /* # of truncated datagrams */ + u_int64_t ifs6_in_discard; /* # of discarded datagrams */ + /* NOTE: fragment timeout is not here */ + u_int64_t ifs6_in_deliver; /* # of datagrams delivered to ULP */ + /* NOTE: increment on final dst if */ + u_int64_t ifs6_out_forward; /* # of datagrams forwarded */ + /* NOTE: increment on outgoing if */ + u_int64_t ifs6_out_request; /* # of outgoing datagrams from ULP */ + /* NOTE: does not include forwards */ + u_int64_t ifs6_out_discard; /* # of discarded datagrams */ + u_int64_t ifs6_out_fragok; /* # of datagrams fragmented */ + u_int64_t ifs6_out_fragfail; /* # of datagrams failed on fragment */ + u_int64_t ifs6_out_fragcreat; /* # of fragment datagrams */ + /* NOTE: this is # after fragment */ + u_int64_t ifs6_reass_reqd; /* # of incoming fragmented packets */ + /* NOTE: increment on final dst if */ + u_int64_t ifs6_reass_ok; /* # of reassembled packets */ + /* NOTE: this is # after reass */ + /* NOTE: increment on final dst if */ + u_int64_t ifs6_reass_fail; /* # of reass failures */ + /* NOTE: may not be packet count */ + /* NOTE: increment on final dst if */ + u_int64_t ifs6_in_mcast; /* # of inbound multicast datagrams */ + u_int64_t ifs6_out_mcast; /* # of outbound multicast datagrams */ +}; + +/* + * ICMPv6 interface statistics, as defined in RFC2466 Ipv6IfIcmpEntry. + * XXX: I'm not sure if this file is the right place for this structure... + */ +struct icmp6_ifstat { + /* + * Input statistics + */ + /* ipv6IfIcmpInMsgs, total # of input messages */ + u_int64_t ifs6_in_msg; + /* ipv6IfIcmpInErrors, # of input error messages */ + u_int64_t ifs6_in_error; + /* ipv6IfIcmpInDestUnreachs, # of input dest unreach errors */ + u_int64_t ifs6_in_dstunreach; + /* ipv6IfIcmpInAdminProhibs, # of input administratively prohibited errs */ + u_int64_t ifs6_in_adminprohib; + /* ipv6IfIcmpInTimeExcds, # of input time exceeded errors */ + u_int64_t ifs6_in_timeexceed; + /* ipv6IfIcmpInParmProblems, # of input parameter problem errors */ + u_int64_t ifs6_in_paramprob; + /* ipv6IfIcmpInPktTooBigs, # of input packet too big errors */ + u_int64_t ifs6_in_pkttoobig; + /* ipv6IfIcmpInEchos, # of input echo requests */ + u_int64_t ifs6_in_echo; + /* ipv6IfIcmpInEchoReplies, # of input echo replies */ + u_int64_t ifs6_in_echoreply; + /* ipv6IfIcmpInRouterSolicits, # of input router solicitations */ + u_int64_t ifs6_in_routersolicit; + /* ipv6IfIcmpInRouterAdvertisements, # of input router advertisements */ + u_int64_t ifs6_in_routeradvert; + /* ipv6IfIcmpInNeighborSolicits, # of input neighbor solicitations */ + u_int64_t ifs6_in_neighborsolicit; + /* ipv6IfIcmpInNeighborAdvertisements, # of input neighbor advertisements */ + u_int64_t ifs6_in_neighboradvert; + /* ipv6IfIcmpInRedirects, # of input redirects */ + u_int64_t ifs6_in_redirect; + /* ipv6IfIcmpInGroupMembQueries, # of input MLD queries */ + u_int64_t ifs6_in_mldquery; + /* ipv6IfIcmpInGroupMembResponses, # of input MLD reports */ + u_int64_t ifs6_in_mldreport; + /* ipv6IfIcmpInGroupMembReductions, # of input MLD done */ + u_int64_t ifs6_in_mlddone; + + /* + * Output statistics. We should solve unresolved routing problem... + */ + /* ipv6IfIcmpOutMsgs, total # of output messages */ + u_int64_t ifs6_out_msg; + /* ipv6IfIcmpOutErrors, # of output error messages */ + u_int64_t ifs6_out_error; + /* ipv6IfIcmpOutDestUnreachs, # of output dest unreach errors */ + u_int64_t ifs6_out_dstunreach; + /* ipv6IfIcmpOutAdminProhibs, # of output administratively prohibited errs */ + u_int64_t ifs6_out_adminprohib; + /* ipv6IfIcmpOutTimeExcds, # of output time exceeded errors */ + u_int64_t ifs6_out_timeexceed; + /* ipv6IfIcmpOutParmProblems, # of output parameter problem errors */ + u_int64_t ifs6_out_paramprob; + /* ipv6IfIcmpOutPktTooBigs, # of output packet too big errors */ + u_int64_t ifs6_out_pkttoobig; + /* ipv6IfIcmpOutEchos, # of output echo requests */ + u_int64_t ifs6_out_echo; + /* ipv6IfIcmpOutEchoReplies, # of output echo replies */ + u_int64_t ifs6_out_echoreply; + /* ipv6IfIcmpOutRouterSolicits, # of output router solicitations */ + u_int64_t ifs6_out_routersolicit; + /* ipv6IfIcmpOutRouterAdvertisements, # of output router advertisements */ + u_int64_t ifs6_out_routeradvert; + /* ipv6IfIcmpOutNeighborSolicits, # of output neighbor solicitations */ + u_int64_t ifs6_out_neighborsolicit; + /* ipv6IfIcmpOutNeighborAdvertisements, # of output neighbor advertisements */ + u_int64_t ifs6_out_neighboradvert; + /* ipv6IfIcmpOutRedirects, # of output redirects */ + u_int64_t ifs6_out_redirect; + /* ipv6IfIcmpOutGroupMembQueries, # of output MLD queries */ + u_int64_t ifs6_out_mldquery; + /* ipv6IfIcmpOutGroupMembResponses, # of output MLD reports */ + u_int64_t ifs6_out_mldreport; + /* ipv6IfIcmpOutGroupMembReductions, # of output MLD done */ + u_int64_t ifs6_out_mlddone; +}; + +struct in6_ifreq { + char ifr_name[IFNAMSIZ]; + union { + struct sockaddr_in6 ifru_addr; + struct sockaddr_in6 ifru_dstaddr; + short ifru_flags; + int ifru_flags6; + int ifru_metric; + caddr_t ifru_data; + struct in6_addrlifetime ifru_lifetime; + struct in6_ifstat ifru_stat; + struct icmp6_ifstat ifru_icmp6stat; + } ifr_ifru; +}; + +struct in6_aliasreq { + char ifra_name[IFNAMSIZ]; + union { + struct sockaddr_in6 ifrau_addr; + int ifrau_align; + } ifra_ifrau; +#ifndef ifra_addr +#define ifra_addr ifra_ifrau.ifrau_addr +#endif + struct sockaddr_in6 ifra_dstaddr; + struct sockaddr_in6 ifra_prefixmask; + int ifra_flags; + struct in6_addrlifetime ifra_lifetime; +}; + +/* + * Given a pointer to an in6_ifaddr (ifaddr), + * return a pointer to the addr as a sockaddr_in6 + */ +#define IA6_IN6(ia) (&((ia)->ia_addr.sin6_addr)) +#define IA6_DSTIN6(ia) (&((ia)->ia_dstaddr.sin6_addr)) +#define IA6_MASKIN6(ia) (&((ia)->ia_prefixmask.sin6_addr)) +#define IA6_SIN6(ia) (&((ia)->ia_addr)) +#define IA6_DSTSIN6(ia) (&((ia)->ia_dstaddr)) +#define IFA_IN6(x) (&((struct sockaddr_in6 *)((x)->ifa_addr))->sin6_addr) +#define IFA_DSTIN6(x) (&((struct sockaddr_in6 *)((x)->ifa_dstaddr))->sin6_addr) + +#define SIOCDIFADDR_IN6 _IOW('i', 25, struct in6_ifreq) +#define SIOCAIFADDR_IN6 _IOW('i', 26, struct in6_aliasreq) + +#define SIOCGIFDSTADDR_IN6 _IOWR('i', 34, struct in6_ifreq) +#define SIOCGIFNETMASK_IN6 _IOWR('i', 37, struct in6_ifreq) + +#define SIOCGIFAFLAG_IN6 _IOWR('i', 73, struct in6_ifreq) + +#define SIOCGIFINFO_IN6 _IOWR('i', 108, struct in6_ndireq) +#define SIOCGNBRINFO_IN6 _IOWR('i', 78, struct in6_nbrinfo) + +#define SIOCGIFALIFETIME_IN6 _IOWR('i', 81, struct in6_ifreq) + +#define SIOCGETSGCNT_IN6 _IOWR('u', 106, struct sioc_sg_req6) +#define SIOCGETMIFCNT_IN6 _IOWR('u', 107, struct sioc_mif_req6) + +#define IN6_IFF_ANYCAST 0x01 /* anycast address */ +#define IN6_IFF_TENTATIVE 0x02 /* tentative address */ +#define IN6_IFF_DUPLICATED 0x04 /* DAD detected duplicate */ +#define IN6_IFF_DETACHED 0x08 /* may be detached from the link */ +#define IN6_IFF_DEPRECATED 0x10 /* deprecated address */ +#define IN6_IFF_AUTOCONF 0x40 /* autoconfigurable address. */ +#define IN6_IFF_TEMPORARY 0x80 /* RFC 4941 temporary address */ + +#ifdef _KERNEL +#define IN6_ARE_MASKED_ADDR_EQUAL(d, a, m) ( \ + (((d)->s6_addr32[0] ^ (a)->s6_addr32[0]) & (m)->s6_addr32[0]) == 0 && \ + (((d)->s6_addr32[1] ^ (a)->s6_addr32[1]) & (m)->s6_addr32[1]) == 0 && \ + (((d)->s6_addr32[2] ^ (a)->s6_addr32[2]) & (m)->s6_addr32[2]) == 0 && \ + (((d)->s6_addr32[3] ^ (a)->s6_addr32[3]) & (m)->s6_addr32[3]) == 0 ) + +#define IN6_ARE_SCOPE_CMP(a,b) ((a)-(b)) +#define IN6_ARE_SCOPE_EQUAL(a,b) ((a)==(b)) + +/* + * Multi-cast membership entry. One for each group/ifp that a PCB + * belongs to. + */ +struct in6_multi_mship { + struct in6_multi *i6mm_maddr; /* Multicast address pointer */ + LIST_ENTRY(in6_multi_mship) i6mm_chain; /* multicast options chain */ +}; + +struct in6_multi { + struct ifmaddr in6m_ifma; /* Protocol-independent info */ +#define in6m_refcnt in6m_ifma.ifma_refcnt +#define in6m_ifidx in6m_ifma.ifma_ifidx + + struct sockaddr_in6 in6m_sin; /* IPv6 multicast address */ +#define in6m_addr in6m_sin.sin6_addr + + u_int in6m_state; /* state of membership */ + u_int in6m_timer; /* MLD6 membership report timer */ +}; + +static __inline struct in6_multi * +ifmatoin6m(struct ifmaddr *ifma) +{ + return ((struct in6_multi *)(ifma)); +} + +/* + * Macros for looking up the in6_multi record for a given IP6 multicast + * address on a given interface. If no matching record is found, "in6m" + * returns NULL. + */ +#define IN6_LOOKUP_MULTI(addr, ifp, in6m) \ + /* struct in6_addr addr; */ \ + /* struct ifnet *ifp; */ \ + /* struct in6_multi *in6m; */ \ +do { \ + struct ifmaddr *ifma; \ + \ + (in6m) = NULL; \ + TAILQ_FOREACH(ifma, &(ifp)->if_maddrlist, ifma_list) \ + if (ifma->ifma_addr->sa_family == AF_INET6 && \ + IN6_ARE_ADDR_EQUAL(&ifmatoin6m(ifma)->in6m_addr, \ + &(addr))) { \ + (in6m) = ifmatoin6m(ifma); \ + break; \ + } \ +} while (/* CONSTCOND */ 0) + +struct in6_multi *in6_addmulti(struct in6_addr *, struct ifnet *, int *); +void in6_delmulti(struct in6_multi *); +int in6_hasmulti(struct in6_addr *, struct ifnet *); +struct in6_multi_mship *in6_joingroup(struct ifnet *, struct in6_addr *, int *); +void in6_leavegroup(struct in6_multi_mship *); +int in6_control(struct socket *, u_long, caddr_t, struct ifnet *); +int in6_ioctl(u_long, caddr_t, struct ifnet *, int); +int in6_update_ifa(struct ifnet *, struct in6_aliasreq *, + struct in6_ifaddr *); +void in6_purgeaddr(struct ifaddr *); +int in6if_do_dad(struct ifnet *); +struct in6_ifaddr *in6ifa_ifpforlinklocal(struct ifnet *, int); +struct in6_ifaddr *in6ifa_ifpwithaddr(struct ifnet *, struct in6_addr *); +int in6_addr2scopeid(unsigned int, const struct in6_addr *); +int in6_matchlen(const struct in6_addr *, const struct in6_addr *); +void in6_prefixlen2mask(struct in6_addr *, int); +#endif /* _KERNEL */ + +#endif /* _NETINET6_IN6_VAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet6/ip6_mroute.h b/lib/libc/include/generic-openbsd/netinet6/ip6_mroute.h new file mode 100644 index 000000000000..d88ea2ab61e2 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet6/ip6_mroute.h @@ -0,0 +1,265 @@ +/* $OpenBSD: ip6_mroute.h,v 1.25 2025/05/19 04:54:04 jan Exp $ */ +/* $KAME: ip6_mroute.h,v 1.17 2001/02/10 02:05:52 itojun Exp $ */ + +/* + * Copyright (C) 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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. + */ + +/* + * Definitions for IP multicast forwarding. + * + * Written by David Waitzman, BBN Labs, August 1988. + * Modified by Steve Deering, Stanford, February 1989. + * Modified by Ajit Thyagarajan, PARC, August 1993. + * Modified by Ajit Thyagarajan, PARC, August 1994. + * Modified by Ahmed Helmy, USC, September 1996. + * + * MROUTING Revision: 1.2 + */ + +#ifndef _NETINET6_IP6_MROUTE_H_ +#define _NETINET6_IP6_MROUTE_H_ + +/* + * Multicast Routing set/getsockopt commands. + */ +#define MRT6_DONE 101 /* shut down forwarder */ +#define MRT6_ADD_MIF 102 /* add multicast interface */ +#define MRT6_DEL_MIF 103 /* delete multicast interface */ +#define MRT6_ADD_MFC 104 /* insert forwarding cache entry */ +#define MRT6_DEL_MFC 105 /* delete forwarding cache entry */ +#define MRT6_INIT 108 /* initialize forwarder (mrt6msg) */ + +/* + * Types and macros for handling bitmaps with one bit per multicast interface. + */ +typedef u_short mifi_t; /* type of a mif index */ +#define MAXMIFS 64 + +/* + * Assume inclusion of sys/param.h or sys/select.h for howmany() + */ +#define __NIFBITS (sizeof(uint32_t) * 8) /* bits per mask */ +typedef struct if_set { + uint32_t ifs_bits[howmany(256, __NIFBITS)]; +} if_set; + +#define IF_SET(n, p) \ + ((p)->ifs_bits[(n)/__NIFBITS] |= (1U << ((n) % __NIFBITS))) +#define IF_CLR(n, p) \ + ((p)->ifs_bits[(n)/__NIFBITS] &= ~(1U << ((n) % __NIFBITS))) +#define IF_ISSET(n, p) \ + ((p)->ifs_bits[(n)/__NIFBITS] & (1U << ((n) % __NIFBITS))) +#define IF_COPY(f, t) memcpy(t, f, sizeof(*(f))) +#define IF_ZERO(p) memset(p, 0, sizeof(*(p))) + +/* + * Argument structure for MRT6_ADD_IF. + */ +struct mif6ctl { + mifi_t mif6c_mifi; /* the index of the mif to be added */ + u_char mif6c_flags; /* MIFF_ flags defined below */ + u_short mif6c_pifi; /* the index of the physical IF */ +#ifdef notyet + u_int mif6c_rate_limit; /* max rate */ +#endif +}; + +#define MIFF_REGISTER 0x1 /* mif represents a register end-point */ + +#define MF6C_INCOMPLETE_PARENT ((mifi_t)-1) + +/* + * Argument structure for MRT6_ADD_MFC and MRT6_DEL_MFC + */ +struct mf6cctl { + struct sockaddr_in6 mf6cc_origin; /* IPv6 origin of mcasts */ + struct sockaddr_in6 mf6cc_mcastgrp; /* multicast group associated */ + mifi_t mf6cc_parent; /* incoming ifindex */ + struct if_set mf6cc_ifset; /* set of forwarding ifs */ +}; + +/* structure used to get all the mif entries via sysctl */ +struct mif6info { + struct in6_addr m6_lcl_addr; /* local interface address */ + u_int16_t m6_ifindex; /* interface index */ + u_int64_t m6_pkt_in; /* # pkts in on interface */ + u_int64_t m6_pkt_out; /* # pkts out on interface */ + u_int64_t m6_bytes_in; /* # bytes in on interface */ + u_int64_t m6_bytes_out; /* # bytes out on interface */ + u_int m6_rate_limit; /* max rate */ + mifi_t m6_mifi; + u_char m6_flags; /* MIFF_ flags defined above */ +}; + +/* structure used to get all the mf6c entries via sysctl */ +struct mf6cinfo { + struct sockaddr_in6 mf6c_origin; /* IPv6 origin of mcasts */ + struct sockaddr_in6 mf6c_mcastgrp; /* multicast group associated*/ + mifi_t mf6c_parent; /* incoming IF */ + struct if_set mf6c_ifset; /* set of outgoing IFs */ + + u_int64_t mf6c_pkt_cnt; /* pkt count for src-grp */ + u_int64_t mf6c_byte_cnt; /* byte count for src-grp */ + u_int64_t mf6c_stall_cnt; /* pkt-cnt waiting for route */ +}; + +/* + * The kernel's multicast routing statistics. + */ +struct mrt6stat { + u_int64_t mrt6s_mfc_lookups; /* # forw. cache hash table hits */ + u_int64_t mrt6s_mfc_misses; /* # forw. cache hash table misses */ + u_int64_t mrt6s_upcalls; /* # calls to mrouted */ + u_int64_t mrt6s_no_route; /* no route for packet's origin */ + u_int64_t mrt6s_bad_tunnel; /* malformed tunnel options */ + u_int64_t mrt6s_cant_tunnel; /* no room for tunnel options */ + u_int64_t mrt6s_wrong_if; /* arrived on wrong interface */ + u_int64_t mrt6s_upq_ovflw; /* upcall Q overflow */ + u_int64_t mrt6s_cache_cleanups; /* # entries with no upcalls */ + u_int64_t mrt6s_drop_sel; /* pkts dropped selectively */ + u_int64_t mrt6s_q_overflow; /* pkts dropped - Q overflow */ + u_int64_t mrt6s_pkt2large; /* pkts dropped - size > BKT SIZE */ + u_int64_t mrt6s_upq_sockfull; /* upcalls dropped - socket full */ +}; + +/* + * Structure used to communicate from kernel to multicast router. + * We'll overlay the structure onto an MLD header (not an IPv6 header + * like igmpmsg{} used for IPv4 implementation). This is because this + * structure will be passed via an IPv6 raw socket, on which an application + * will only receive the payload i.e. the data after the IPv6 header and all + * the extension headers. (see Section 3 of draft-ietf-ipngwg-2292bis-01) + */ +struct mrt6msg { +#define MRT6MSG_NOCACHE 1 +#define MRT6MSG_WRONGMIF 2 +#define MRT6MSG_WHOLEPKT 3 /* used for user level encap*/ + u_char im6_mbz; /* must be zero */ + u_char im6_msgtype; /* what type of message */ + u_int16_t im6_mif; /* mif rec'd on */ + u_int32_t im6_pad; /* padding for 64bit arch */ + struct in6_addr im6_src, im6_dst; +}; + +/* + * Argument structure used by multicast routing daemon to get src-grp + * packet counts + */ +struct sioc_sg_req6 { + struct sockaddr_in6 src; + struct sockaddr_in6 grp; + u_int64_t pktcnt; + u_int64_t bytecnt; + u_int64_t wrong_if; +}; + +/* + * Argument structure used by mrouted to get mif pkt counts + */ +struct sioc_mif_req6 { + mifi_t mifi; /* mif number */ + u_int64_t icount; /* Input packet count on mif */ + u_int64_t ocount; /* Output packet count on mif */ + u_int64_t ibytes; /* Input byte count on mif */ + u_int64_t obytes; /* Output byte count on mif */ +}; + +#if defined(_KERNEL) + +enum mrt6stat_counters { + mrt6s_mfc_lookups, + mrt6s_mfc_misses, + mrt6s_upcalls, + mrt6s_no_route, + mrt6s_bad_tunnel, + mrt6s_cant_tunnel, + mrt6s_wrong_if, + mrt6s_upq_ovflw, + mrt6s_cache_cleanups, + mrt6s_drop_sel, + mrt6s_q_overflow, + mrt6s_pkt2large, + mrt6s_upq_sockfull, + mrt6s_ncounters +}; + +extern struct cpumem *mrt6counters; + +static inline void +mrt6stat_inc(enum mrt6stat_counters c) +{ + counters_inc(mrt6counters, c); +} + +/* How frequent should we look for expired entries (in seconds). */ +#define MCAST_EXPIRE_TIMEOUT 30 + +/* + * The kernel's multicast-interface structure. + */ +struct mif6 { + mifi_t m6_mifi; /* mif index */ + u_char m6_flags; /* MIFF_ flags defined above */ + u_int m6_rate_limit; /* max rate */ +#ifdef notyet + struct tbf *m6_tbf; /* token bucket structure at intf. */ +#endif + struct in6_addr m6_lcl_addr; /* local interface address */ + u_int64_t m6_pkt_in; /* # pkts in on interface */ + u_int64_t m6_pkt_out; /* # pkts out on interface */ + u_int64_t m6_bytes_in; /* # bytes in on interface */ + u_int64_t m6_bytes_out; /* # bytes out on interface */ +}; + +/* + * The kernel's multicast forwarding cache entry structure + */ +struct mf6c { + struct sockaddr_in6 mf6c_origin; /* IPv6 origin of mcasts */ + struct sockaddr_in6 mf6c_mcastgrp; /* multicast group associated*/ + mifi_t mf6c_parent; /* incoming IF */ + + u_int64_t mf6c_pkt_cnt; /* pkt count for src-grp */ + u_int64_t mf6c_byte_cnt; /* byte count for src-grp */ + u_int64_t mf6c_wrong_if; /* wrong if for src-grp */ + int mf6c_expire; /* time to clean entry up */ +}; + +int ip6_mrouter_set(int, struct socket *, struct mbuf *); +int ip6_mrouter_get(int, struct socket *, struct mbuf *); +int ip6_mrouter_done(struct socket *); +void ip6_mrouter_detach(struct ifnet *); +void mrt6_init(void); +int mrt6_ioctl(struct socket *, u_long, caddr_t); +int mrt6_sysctl_mif(void *, size_t *); +int mrt6_sysctl_mrt6stat(void *, size_t *, void *); +int mrt6_sysctl_mfc(void *, size_t *); +#endif /* _KERNEL */ + +#endif /* !_NETINET6_IP6_MROUTE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet6/ip6_var.h b/lib/libc/include/generic-openbsd/netinet6/ip6_var.h new file mode 100644 index 000000000000..e35c2be6972d --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet6/ip6_var.h @@ -0,0 +1,380 @@ +/* $OpenBSD: ip6_var.h,v 1.128 2025/09/16 09:19:16 florian Exp $ */ +/* $KAME: ip6_var.h,v 1.33 2000/06/11 14:59:20 jinmei Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ip_var.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET6_IP6_VAR_H_ +#define _NETINET6_IP6_VAR_H_ + +struct ip6stat { + u_int64_t ip6s_total; /* total packets received */ + u_int64_t ip6s_tooshort; /* packet too short */ + u_int64_t ip6s_toosmall; /* not enough data */ + u_int64_t ip6s_fragments; /* fragments received */ + u_int64_t ip6s_fragdropped; /* frags dropped(dups, out of space) */ + u_int64_t ip6s_fragtimeout; /* fragments timed out */ + u_int64_t ip6s_fragoverflow; /* fragments that exceeded limit */ + u_int64_t ip6s_forward; /* packets forwarded */ + u_int64_t ip6s_cantforward; /* packets rcvd for unreachable dest */ + u_int64_t ip6s_redirectsent; /* packets forwarded on same net */ + u_int64_t ip6s_delivered; /* datagrams delivered to upper level*/ + u_int64_t ip6s_localout; /* total ip packets generated here */ + u_int64_t ip6s_odropped; /* lost output due to nobufs, etc. */ + u_int64_t ip6s_reassembled; /* total packets reassembled ok */ + u_int64_t ip6s_fragmented; /* datagrams successfully fragmented */ + u_int64_t ip6s_ofragments; /* output fragments created */ + u_int64_t ip6s_cantfrag; /* don't fragment flag was set, etc. */ + u_int64_t ip6s_badoptions; /* error in option processing */ + u_int64_t ip6s_noroute; /* packets discarded due to no route */ + u_int64_t ip6s_badvers; /* ip6 version != 6 */ + u_int64_t ip6s_rawout; /* total raw ip packets generated */ + u_int64_t ip6s_badscope; /* scope error */ + u_int64_t ip6s_notmember; /* don't join this multicast group */ + u_int64_t ip6s_nxthist[256]; /* next header history */ + u_int64_t ip6s_m1; /* one mbuf */ + u_int64_t ip6s_m2m[32]; /* two or more mbuf */ + u_int64_t ip6s_mext1; /* one ext mbuf */ + u_int64_t ip6s_mext2m; /* two or more ext mbuf */ + u_int64_t ip6s_nogif; /* no match gif found */ + u_int64_t ip6s_toomanyhdr; /* discarded due to too many headers */ + + /* + * statistics for improvement of the source address selection + * algorithm: + * XXX: hardcoded 16 = # of ip6 multicast scope types + 1 + */ + /* number of times that address selection fails */ + u_int64_t ip6s_sources_none; + /* number of times that an address on the outgoing I/F is chosen */ + u_int64_t ip6s_sources_sameif[16]; + /* number of times that an address on a non-outgoing I/F is chosen */ + u_int64_t ip6s_sources_otherif[16]; + /* + * number of times that an address that has the same scope + * from the destination is chosen. + */ + u_int64_t ip6s_sources_samescope[16]; + /* + * number of times that an address that has a different scope + * from the destination is chosen. + */ + u_int64_t ip6s_sources_otherscope[16]; + /* number of times that an deprecated address is chosen */ + u_int64_t ip6s_sources_deprecated[16]; + + u_int64_t ip6s_rtcachehit; /* valid route found in cache */ + u_int64_t ip6s_rtcachemiss; /* route cache with new destination */ + u_int64_t ip6s_wrongif; /* packet received on wrong interface */ + u_int64_t ip6s_idropped; /* lost input due to nobufs, etc. */ +}; + +#ifdef _KERNEL + +/* + * IP6 reassembly queue structure. Each fragment + * being reassembled is attached to one of these structures. + */ +struct ip6q { + TAILQ_ENTRY(ip6q) ip6q_queue; + LIST_HEAD(ip6asfrag_list, ip6asfrag) ip6q_asfrag; + struct in6_addr ip6q_src, ip6q_dst; + int ip6q_unfrglen; /* len of unfragmentable part */ + int ip6q_nfrag; /* # of fragments */ + u_int32_t ip6q_ident; /* fragment identification */ + u_int8_t ip6q_nxt; /* ip6f_nxt in first fragment */ + u_int8_t ip6q_ecn; + u_int8_t ip6q_ttl; /* time to live in slowtimo units */ +}; + +struct ip6asfrag { + LIST_ENTRY(ip6asfrag) ip6af_list; + struct mbuf *ip6af_m; + int ip6af_offset; /* offset in ip6af_m to next header */ + int ip6af_frglen; /* fragmentable part length */ + int ip6af_off; /* fragment offset */ + u_int16_t ip6af_mff; /* more fragment bit in frag off */ +}; + +struct ip6_moptions { + LIST_HEAD(, in6_multi_mship) im6o_memberships; + unsigned short im6o_ifidx; /* ifp index for outgoing multicasts */ + u_char im6o_hlim; /* hoplimit for outgoing multicasts */ + u_char im6o_loop; /* 1 >= hear sends if a member */ +}; + +/* + * Control options for outgoing packets + */ + +/* Routing header related info */ +struct ip6po_rhinfo { + struct ip6_rthdr *ip6po_rhi_rthdr; /* Routing header */ + struct route ip6po_rhi_route; /* Route to the 1st hop */ +}; +#define ip6po_rthdr ip6po_rhinfo.ip6po_rhi_rthdr +#define ip6po_route ip6po_rhinfo.ip6po_rhi_route + +struct ip6_pktopts { + /* Hoplimit for outgoing packets */ + int ip6po_hlim; + + /* Outgoing IF/address information */ + struct in6_pktinfo *ip6po_pktinfo; + + /* Hop-by-Hop options header */ + struct ip6_hbh *ip6po_hbh; + + /* Destination options header (before a routing header) */ + struct ip6_dest *ip6po_dest1; + + /* Routing header related info. */ + struct ip6po_rhinfo ip6po_rhinfo; + + /* Destination options header (after a routing header) */ + struct ip6_dest *ip6po_dest2; + + /* traffic class */ + int ip6po_tclass; + + /* fragment vs PMTU discovery policy */ + int ip6po_minmtu; +#define IP6PO_MINMTU_MCASTONLY -1 /* default: send at min MTU for multicast */ +#define IP6PO_MINMTU_DISABLE 0 /* always perform pmtu disc */ +#define IP6PO_MINMTU_ALL 1 /* always send at min MTU */ + + int ip6po_flags; +#define IP6PO_DONTFRAG 0x04 /* disable fragmentation (IPV6_DONTFRAG) */ +}; + +#include + +enum ip6stat_counters { + ip6s_total, + ip6s_tooshort, + ip6s_toosmall, + ip6s_fragments, + ip6s_fragdropped, + ip6s_fragtimeout, + ip6s_fragoverflow, + ip6s_forward, + ip6s_cantforward, + ip6s_redirectsent, + ip6s_delivered, + ip6s_localout, + ip6s_odropped, + ip6s_reassembled, + ip6s_fragmented, + ip6s_ofragments, + ip6s_cantfrag, + ip6s_badoptions, + ip6s_noroute, + ip6s_badvers, + ip6s_rawout, + ip6s_badscope, + ip6s_notmember, + ip6s_nxthist, + ip6s_m1 = ip6s_nxthist + 256, + ip6s_m2m, + ip6s_mext1 = ip6s_m2m + 32, + ip6s_mext2m, + ip6s_nogif, + ip6s_toomanyhdr, + ip6s_sources_none, + ip6s_sources_sameif, + ip6s_sources_otherif = ip6s_sources_sameif + 16, + ip6s_sources_samescope = ip6s_sources_otherif + 16, + ip6s_sources_otherscope = ip6s_sources_samescope + 16, + ip6s_sources_deprecated = ip6s_sources_otherscope + 16, + ip6s_rtcachehit = ip6s_sources_deprecated + 16, + ip6s_rtcachemiss, + ip6s_wrongif, + ip6s_idropped, + + ip6s_ncounters, +}; + +extern struct cpumem *ip6counters; + +static inline void +ip6stat_inc(enum ip6stat_counters c) +{ + counters_inc(ip6counters, c); +} + +static inline void +ip6stat_add(enum ip6stat_counters c, uint64_t v) +{ + counters_add(ip6counters, c, v); +} + +/* flags passed to ip6_output or ip6_forward as last parameter */ +#define IPV6_UNSPECSRC 0x01 /* allow :: as the source address */ +#define IPV6_FORWARDING 0x02 /* most of IPv6 header exists */ +#define IPV6_MINMTU 0x04 /* use minimum MTU (IPV6_USE_MIN_MTU) */ +#define IPV6_REDIRECT 0x08 /* redirected by pf */ +#define IPV6_FORWARDING_IPSEC 0x10 /* only packets processed by IPsec */ + +extern int ip6_mtudisc_timeout; /* mtu discovery */ +extern struct rttimer_queue icmp6_mtudisc_timeout_q; + +extern int ip6_defhlim; /* default hop limit */ +extern int ip6_defmcasthlim; /* default multicast hop limit */ +extern int ip6_forwarding; /* act as router? */ +extern int ip6_mforwarding; /* act as multicast router? */ +extern int ip6_multipath; /* use multipath routes */ +extern int ip6_sendredirect; /* send ICMPv6 redirect? */ +extern int ip6_mcast_pmtu; /* path MTU discovery for multicast */ +extern int ip6_neighborgcthresh; /* Threshold # of NDP entries for GC */ +extern int ip6_maxdynroutes; /* Max # of routes created via redirect */ + +extern struct socket *ip6_mrouter[RT_TABLEID_MAX + 1]; /* multicast routing daemon */ +extern int ip6_sendredirects; /* send IP redirects when forwarding? */ +extern int ip6_maxfragpackets; /* Maximum packets in reassembly queue */ +extern int ip6_maxfrags; /* Maximum fragments in reassembly queue */ +extern int ip6_hdrnestlimit; /* upper limit of # of extension headers */ +extern int ip6_dad_count; /* DupAddrDetectionTransmits */ +extern int ip6_dad_pending; /* number of currently running DADs */ + +extern const struct pr_usrreqs rip6_usrreqs; + +struct inpcb; +struct ipsec_level; + +int icmp6_ctloutput(int, struct socket *, int, int, struct mbuf *); + +void ip6_init(void); +void ip6intr(void); +int ip6_input_if(struct mbuf **, int *, int, int, struct ifnet *, + struct netstack *); +int ip6_ours_enqueue(struct mbuf **, int *, int); +void ip6_freepcbopts(struct ip6_pktopts *); +void ip6_freemoptions(struct ip6_moptions *); +int ip6_unknown_opt(struct mbuf **, u_int8_t *, int); +int ip6_get_prevhdr(struct mbuf *, int); +int ip6_nexthdr(struct mbuf *, int, int, int *); +int ip6_lasthdr(struct mbuf *, int, int, int *); +int ip6_mforward(struct ip6_hdr *, struct ifnet *, struct mbuf *, int); +int ip6_process_hopopts(struct mbuf **, u_int8_t *, int, u_int32_t *, + u_int32_t *); +void ip6_savecontrol(struct inpcb *, struct mbuf *, struct mbuf **); +int ip6_sysctl(int *, u_int, void *, size_t *, void *, size_t); + +void ip6_forward(struct mbuf *, struct route *, int); + +void ip6_mloopback(struct ifnet *, struct mbuf *, struct sockaddr_in6 *); +int ip6_output(struct mbuf *, struct ip6_pktopts *, struct route *, int, + struct ip6_moptions *, const struct ipsec_level *); +int ip6_fragment(struct mbuf *, struct mbuf_list *, int, u_char, u_long); +int ip6_ctloutput(int, struct socket *, int, int, struct mbuf *); +int ip6_raw_ctloutput(int, struct socket *, int, int, struct mbuf *); +void ip6_initpktopts(struct ip6_pktopts *); +int ip6_setpktopts(struct mbuf *, struct ip6_pktopts *, + struct ip6_pktopts *, int, int); +void ip6_clearpktopts(struct ip6_pktopts *, int); +void ip6_randomid_init(void); +u_int32_t ip6_randomid(void); +void ip6_send(struct mbuf *); + +int route6_input(struct mbuf **, int *, int, int, struct netstack *); + +void frag6_init(void); +int frag6_input(struct mbuf **, int *, int, int, struct netstack *); +int frag6_deletefraghdr(struct mbuf *, int); +void frag6_slowtimo(void); + +void rip6_init(void); +int rip6_input(struct mbuf **, int *, int, int, struct netstack *); +void rip6_ctlinput(int, struct sockaddr *, u_int, void *); +int rip6_ctloutput(int, struct socket *, int, int, struct mbuf *); +int rip6_output(struct mbuf *, struct socket *, struct sockaddr *, + struct mbuf *); +int rip6_attach(struct socket *, int, int); +int rip6_detach(struct socket *); +int rip6_bind(struct socket *, struct mbuf *, struct proc *); +int rip6_connect(struct socket *, struct mbuf *); +int rip6_disconnect(struct socket *); +int rip6_shutdown(struct socket *); +int rip6_send(struct socket *, struct mbuf *, struct mbuf *, + struct mbuf *); +int rip6_sysctl(int *, u_int, void *, size_t *, void *, size_t); + +int dest6_input(struct mbuf **, int *, int, int, struct netstack *); + +int in6_pcbselsrc(const struct in6_addr **, const struct sockaddr_in6 *, + struct inpcb *, struct ip6_pktopts *); +int in6_selectsrc(const struct in6_addr **, const struct sockaddr_in6 *, + struct ip6_moptions *, unsigned int); +struct rtentry *in6_selectroute(const struct in6_addr *, struct ip6_pktopts *, + struct route *, unsigned int rtableid); + +u_int32_t ip6_randomflowlabel(void); + +#ifdef IPSEC +struct tdb; +int ip6_output_ipsec_lookup(struct mbuf *, const struct ipsec_level *, + struct tdb **); +int ip6_output_ipsec_send(struct tdb *, struct mbuf *, struct route *, + u_int, int, int); +#endif /* IPSEC */ + +#endif /* _KERNEL */ + +#endif /* !_NETINET6_IP6_VAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet6/ip6protosw.h b/lib/libc/include/generic-openbsd/netinet6/ip6protosw.h new file mode 100644 index 000000000000..1d1c3df72e5d --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet6/ip6protosw.h @@ -0,0 +1,112 @@ +/* $OpenBSD: ip6protosw.h,v 1.16 2022/02/22 01:02:57 guenther Exp $ */ +/* $KAME: ip6protosw.h,v 1.22 2001/02/08 18:02:08 itojun Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/*- + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)protosw.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _NETINET6_IP6PROTOSW_H_ +#define _NETINET6_IP6PROTOSW_H_ + +/* + * Protocol switch table for IPv6. + * All other definitions should refer to sys/protosw.h + */ + +struct mbuf; +struct sockaddr; +struct socket; +struct domain; +struct proc; +struct ip6_hdr; +struct icmp6_hdr; +struct in6_addr; + +/* + * argument type for the last arg of pr_ctlinput(). + * should be consulted only with AF_INET6 family. + * + * IPv6 ICMP IPv6 [exthdrs] finalhdr payload + * ^ ^ ^ ^ + * | | ip6c_ip6 ip6c_off + * | ip6c_icmp6 + * ip6c_m + * + * ip6c_finaldst usually points to ip6c_ip6->ip6_dst. if the original + * (internal) packet carries a routing header, it may point the final + * destination address in the routing header. + * + * ip6c_src: ip6c_ip6->ip6_src + scope info + flowlabel in ip6c_ip6 + * (beware of flowlabel, if you try to compare it against others) + * ip6c_dst: ip6c_finaldst + scope info + */ +struct ip6ctlparam { + struct mbuf *ip6c_m; /* start of mbuf chain */ + struct icmp6_hdr *ip6c_icmp6; /* icmp6 header of target packet */ + struct ip6_hdr *ip6c_ip6; /* ip6 header of target packet */ + int ip6c_off; /* offset of the target proto header */ + struct sockaddr_in6 *ip6c_src; /* srcaddr w/ additional info */ + struct sockaddr_in6 *ip6c_dst; /* (final) dstaddr w/ additional info */ + struct in6_addr *ip6c_finaldst; /* final destination address */ + void *ip6c_cmdarg; /* control command dependent data */ + u_int8_t ip6c_nxt; /* final next header field */ +}; + +#endif /* !_NETINET6_IP6PROTOSW_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet6/mld6.h b/lib/libc/include/generic-openbsd/netinet6/mld6.h new file mode 100644 index 000000000000..594ce8c4f8ff --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet6/mld6.h @@ -0,0 +1,113 @@ +/* $OpenBSD: mld6.h,v 1.2 2010/03/22 21:29:22 jsg Exp $ */ +/* $FreeBSD: mld6.h,v 1.1 2009/04/29 11:31:23 bms Exp $ */ +/*- + * Copyright (c) 2009 Bruce Simpson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 _NETINET6_MLD6_H_ +#define _NETINET6_MLD6_H_ + +/* + * Multicast Listener Discovery (MLD) definitions. + */ + +/* Minimum length of any MLD protocol message. */ +#define MLD_MINLEN sizeof(struct icmp6_hdr) + +/* + * MLD v2 query format. + * See for struct mld_hdr + * (MLDv1 query and host report format). + */ +struct mldv2_query { + struct icmp6_hdr mld_icmp6_hdr; /* ICMPv6 header */ + struct in6_addr mld_addr; /* address being queried */ + uint8_t mld_misc; /* reserved/suppress/robustness */ + uint8_t mld_qqi; /* querier's query interval */ + uint16_t mld_numsrc; /* number of sources */ + /* followed by 1..numsrc source addresses */ +} __packed; +#define MLD_V2_QUERY_MINLEN sizeof(struct mldv2_query) +#define MLD_MRC_EXP(x) ((ntohs((x)) >> 12) & 0x0007) +#define MLD_MRC_MANT(x) (ntohs((x)) & 0x0fff) +#define MLD_QQIC_EXP(x) (((x) >> 4) & 0x07) +#define MLD_QQIC_MANT(x) ((x) & 0x0f) +#define MLD_QRESV(x) (((x) >> 4) & 0x0f) +#define MLD_SFLAG(x) (((x) >> 3) & 0x01) +#define MLD_QRV(x) ((x) & 0x07) + +/* + * MLDv2 host membership report header. + * mld_type: MLDV2_LISTENER_REPORT + */ +struct mldv2_report { + struct icmp6_hdr mld_icmp6_hdr; + /* followed by 1..numgrps records */ +} __packed; +/* overlaid on struct icmp6_hdr. */ +#define mld_numrecs mld_icmp6_hdr.icmp6_data16[1] + +struct mldv2_record { + uint8_t mr_type; /* record type */ + uint8_t mr_datalen; /* length of auxiliary data */ + uint16_t mr_numsrc; /* number of sources */ + struct in6_addr mr_addr; /* address being reported */ + /* followed by 1..numsrc source addresses */ +} __packed; +#define MLD_V2_REPORT_MAXRECS 65535 + +/* + * MLDv2 report modes. + */ +#define MLD_DO_NOTHING 0 /* don't send a record */ +#define MLD_MODE_IS_INCLUDE 1 /* MODE_IN */ +#define MLD_MODE_IS_EXCLUDE 2 /* MODE_EX */ +#define MLD_CHANGE_TO_INCLUDE_MODE 3 /* TO_IN */ +#define MLD_CHANGE_TO_EXCLUDE_MODE 4 /* TO_EX */ +#define MLD_ALLOW_NEW_SOURCES 5 /* ALLOW_NEW */ +#define MLD_BLOCK_OLD_SOURCES 6 /* BLOCK_OLD */ + +/* + * MLDv2 query types. + */ +#define MLD_V2_GENERAL_QUERY 1 +#define MLD_V2_GROUP_QUERY 2 +#define MLD_V2_GROUP_SOURCE_QUERY 3 + +/* + * Maximum report interval for MLDv1 host membership reports (in seconds) + */ +#define MLD_V1_MAX_RI 10 + +/* + * MLD_TIMER_SCALE denotes that the MLD code field specifies + * time in milliseconds. + */ +#define MLD_TIMER_SCALE 1000 + +#endif /* _NETINET6_MLD6_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet6/mld6_var.h b/lib/libc/include/generic-openbsd/netinet6/mld6_var.h new file mode 100644 index 000000000000..cd4feef7b359 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet6/mld6_var.h @@ -0,0 +1,53 @@ +/* $OpenBSD: mld6_var.h,v 1.6 2008/04/18 06:42:20 djm Exp $ */ +/* $KAME: mld6_var.h,v 1.4 2000/03/25 07:23:54 sumikawa Exp $ */ + +/* + * Copyright (C) 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 _NETINET6_MLD6_VAR_H_ +#define _NETINET6_MLD6_VAR_H_ + +#ifdef _KERNEL + +#define MLD_RANDOM_DELAY(X) (arc4random_uniform(X) + 1) + +/* + * States for MLD stop-listening processing + */ +#define MLD_OTHERLISTENER 0 +#define MLD_IREPORTEDLAST 1 + +void mld6_init(void); +void mld6_input(struct mbuf *, int); +void mld6_start_listening(struct in6_multi *); +void mld6_stop_listening(struct in6_multi *); +void mld6_fasttimeo(void); +#endif /* _KERNEL */ + +#endif /* _NETINET6_MLD6_VAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet6/nd6.h b/lib/libc/include/generic-openbsd/netinet6/nd6.h new file mode 100644 index 000000000000..9a490a9afb5d --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet6/nd6.h @@ -0,0 +1,159 @@ +/* $OpenBSD: nd6.h,v 1.105 2025/09/16 09:19:43 florian Exp $ */ +/* $KAME: nd6.h,v 1.95 2002/06/08 11:31:06 itojun Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 _NETINET6_ND6_H_ +#define _NETINET6_ND6_H_ + +#define ND6_LLINFO_PURGE -3 +#define ND6_LLINFO_NOSTATE -2 +#define ND6_LLINFO_INCOMPLETE 0 +#define ND6_LLINFO_REACHABLE 1 +#define ND6_LLINFO_STALE 2 +#define ND6_LLINFO_DELAY 3 +#define ND6_LLINFO_PROBE 4 + +/* + * Locks used to protect struct members in this file: + * I immutable after creation + * K kernel lock + * m nd6 mutex, needed when net lock is shared + * N net lock + */ + +struct nd_ifinfo { + u_int32_t reachable; /* [N] Reachable Time */ + int recalctm; /* [N] BaseReachable recalc timer */ +}; + +struct in6_nbrinfo { + char ifname[IFNAMSIZ]; /* if name, e.g. "en0" */ + struct in6_addr addr; /* IPv6 address of the neighbor */ + time_t expire; /* lifetime for NDP state transition */ + long asked; /* number of queries already sent for addr */ + int isrouter; /* if it acts as a router */ + int state; /* reachability state */ +}; + +struct in6_ndireq { + char ifname[IFNAMSIZ]; + struct nd_ifinfo ndi; +}; + +/* protocol constants */ +#define MAX_RTR_SOLICITATION_DELAY 1 /*1sec*/ +#define RTR_SOLICITATION_INTERVAL 4 /*4sec*/ +#define MAX_RTR_SOLICITATIONS 3 + +#define ND6_INFINITE_LIFETIME 0xffffffff + +#ifdef _KERNEL + +#include + +struct llinfo_nd6 { + TAILQ_ENTRY(llinfo_nd6) ln_list; /* [m] global nd6_list */ + struct rtentry *ln_rt; /* [I] backpointer to rtentry */ + /* keep fields above in sync with struct llinfo_nd6_iterator */ + struct refcnt ln_refcnt; /* entry refereced by list */ + struct mbuf_queue ln_mq; /* hold packets until resolved */ + struct in6_addr ln_saddr6; /* source of prompting packet */ + long ln_asked; /* number of queries already sent for addr */ + short ln_state; /* reachability state */ + short ln_router; /* 2^0: ND6 router bit */ +}; +#define LN_HOLD_QUEUE 10 +#define LN_HOLD_TOTAL 100 + +struct llinfo_nd6_iterator { + TAILQ_ENTRY(llinfo_nd6) ln_list; /* [m] global nd6_list */ + struct rtentry *ln_rt; /* [I] always NULL */ + /* keep fields above in sync with struct llinfo_nd6 */ +}; + +extern unsigned int ln_hold_total; + +#define ND6_LLINFO_PERMANENT(n) ((n)->ln_rt->rt_expire == 0) + +/* node constants */ +#define REACHABLE_TIME 30000 /* msec */ +#define RETRANS_TIMER 1000 /* msec */ +#define MIN_RANDOM_FACTOR 512 /* 1024 * 0.5 */ +#define MAX_RANDOM_FACTOR 1536 /* 1024 * 1.5 */ +#define ND_COMPUTE_RTIME(x) \ + (((MIN_RANDOM_FACTOR * (x >> 10)) + (arc4random() & \ + ((MAX_RANDOM_FACTOR - MIN_RANDOM_FACTOR) * (x >> 10)))) /1000) + +extern int nd6_delay; +extern int nd6_umaxtries; +extern int nd6_mmaxtries; +extern const int nd6_gctimer; + +struct nd_opts { + struct nd_opt_hdr *nd_opts_src_lladdr; + struct nd_opt_hdr *nd_opts_tgt_lladdr; +}; + +void nd6_init(void); +void nd6_ifattach(struct ifnet *); +void nd6_ifdetach(struct ifnet *); +int nd6_is_addr_neighbor(const struct sockaddr_in6 *, struct ifnet *); +int nd6_options(void *, int, struct nd_opts *); +struct rtentry *nd6_lookup(const struct in6_addr *, int, struct ifnet *, + u_int); +void nd6_llinfo_settimer(const struct llinfo_nd6 *, unsigned int); +void nd6_purge(struct ifnet *); +void nd6_rtrequest(struct ifnet *, int, struct rtentry *); +int nd6_ioctl(u_long, caddr_t, struct ifnet *); +void nd6_cache_lladdr(struct ifnet *, const struct in6_addr *, char *, + int, int, int, int); +int nd6_resolve(struct ifnet *, struct rtentry *, struct mbuf *, + struct sockaddr *, u_char *); +int nd6_need_cache(struct ifnet *); + +void nd6_na_input(struct mbuf *, int, int); +void nd6_na_output(struct ifnet *, const struct in6_addr *, + const struct in6_addr *, u_long, int, struct sockaddr *); +void nd6_ns_input(struct mbuf *, int, int); +void nd6_ns_output(struct ifnet *, const struct in6_addr *, + const struct in6_addr *, const struct in6_addr *, int); +caddr_t nd6_ifptomac(struct ifnet *); +void nd6_dad_start(struct ifaddr *); +void nd6_dad_stop(struct ifaddr *); + +void nd6_rtr_cache(struct mbuf *, int, int, int); + +int rt6_flush(struct in6_addr *, struct ifnet *); + +void nd6_expire_timer_update(struct in6_ifaddr *); +#endif /* _KERNEL */ + +#endif /* _NETINET6_ND6_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netinet6/raw_ip6.h b/lib/libc/include/generic-openbsd/netinet6/raw_ip6.h new file mode 100644 index 000000000000..63b525afa234 --- /dev/null +++ b/lib/libc/include/generic-openbsd/netinet6/raw_ip6.h @@ -0,0 +1,86 @@ +/* $OpenBSD: raw_ip6.h,v 1.4 2017/02/09 15:23:35 jca Exp $ */ +/* $KAME: raw_ip6.h,v 1.2 2001/05/27 13:28:35 itojun Exp $ */ + +/* + * Copyright (C) 2001 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 _NETINET6_RAW_IP6_H_ +#define _NETINET6_RAW_IP6_H_ + +/* + * ICMPv6 stat is counted separately. see netinet/icmp6.h + */ +struct rip6stat { + u_int64_t rip6s_ipackets; /* total input packets */ + u_int64_t rip6s_isum; /* input checksum computations */ + u_int64_t rip6s_badsum; /* of above, checksum error */ + u_int64_t rip6s_nosock; /* no matching socket */ + u_int64_t rip6s_nosockmcast; /* of above, arrived as multicast */ + u_int64_t rip6s_fullsock; /* not delivered, input socket full */ + + u_int64_t rip6s_opackets; /* total output packets */ +}; + +/* + * Names for RIP6 sysctl objects + */ +#define RIPV6CTL_STATS 1 /* RIP6 stats */ +#define RIPV6CTL_MAXID 2 + +#define RIPM6CTL_NAMES { \ + { 0, 0 }, \ + { "stats", CTLTYPE_NODE }, \ +} + +#ifdef _KERNEL + +#include + +enum rip6stat_counters { + rip6s_ipackets, + rip6s_isum, + rip6s_badsum, + rip6s_nosock, + rip6s_nosockmcast, + rip6s_fullsock, + rip6s_opackets, + rip6s_ncounters, +}; + +extern struct cpumem *rip6counters; + +static inline void +rip6stat_inc(enum rip6stat_counters c) +{ + counters_inc(rip6counters, c); +} + +#endif + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/netmpls/mpls.h b/lib/libc/include/generic-openbsd/netmpls/mpls.h new file mode 100644 index 000000000000..cd8a1286642f --- /dev/null +++ b/lib/libc/include/generic-openbsd/netmpls/mpls.h @@ -0,0 +1,166 @@ +/* $OpenBSD: mpls.h,v 1.47 2025/03/02 21:28:32 bluhm Exp $ */ + +/* + * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULARPURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, ORCONSEQUENTIAL + * 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 _NETMPLS_MPLS_H_ +#define _NETMPLS_MPLS_H_ + +/* + * Structure of a SHIM header. + */ +#define MPLS_LABEL_MAX ((1 << 20) - 1) + +struct shim_hdr { + u_int32_t shim_label; /* 20 bit label, 4 bit exp & BoS, 8 bit TTL */ +}; + +#define MPLS_HDRLEN sizeof(struct shim_hdr) + +/* + * By byte-swapping the constants, we avoid ever having to byte-swap IP + * addresses inside the kernel. Unfortunately, user-level programs rely + * on these macros not doing byte-swapping. + */ + +#ifdef _KERNEL +#define __MADDR(x) ((u_int32_t)htonl((u_int32_t)(x))) +#else +#define __MADDR(x) ((u_int32_t)(x)) +#endif + +#define MPLS_LABEL_MASK __MADDR(0xfffff000U) +#define MPLS_LABEL_OFFSET 12 +#define MPLS_EXP_MASK __MADDR(0x00000e00U) +#define MPLS_EXP_OFFSET 9 +#define MPLS_BOS_MASK __MADDR(0x00000100U) +#define MPLS_BOS_OFFSET 8 +#define MPLS_TTL_MASK __MADDR(0x000000ffU) + +#define CW_ZERO_MASK __MADDR(0xf0000000U) +#define CW_FRAG_MASK __MADDR(0x00300000U) + +#define MPLS_BOS_ISSET(l) (((l) & MPLS_BOS_MASK) == MPLS_BOS_MASK) + +/* Reserved label values (RFC3032) */ +#define MPLS_LABEL_IPV4NULL 0 /* IPv4 Explicit NULL Label */ +#define MPLS_LABEL_RTALERT 1 /* Router Alert Label */ +#define MPLS_LABEL_IPV6NULL 2 /* IPv6 Explicit NULL Label */ +#define MPLS_LABEL_IMPLNULL 3 /* Implicit NULL Label */ +/* MPLS_LABEL_RESERVED 4-15 */ /* Values 4-15 are reserved */ +#define MPLS_LABEL_RESERVED_MAX 15 + +/* + * Socket address + */ + +struct sockaddr_mpls { + u_int8_t smpls_len; /* length */ + u_int8_t smpls_family; /* AF_MPLS */ + u_int16_t smpls_pad0; + u_int32_t smpls_label; /* MPLS label */ + u_int32_t smpls_pad1[2]; +}; + +struct rt_mpls { + u_int32_t mpls_label; + u_int8_t mpls_operation; + u_int8_t mpls_exp; +}; + +#define MPLS_OP_LOCAL 0x0 +#define MPLS_OP_POP 0x1 +#define MPLS_OP_PUSH 0x2 +#define MPLS_OP_SWAP 0x4 + +#define MPLS_INKERNEL_LOOP_MAX 16 + +#define satosmpls(sa) ((struct sockaddr_mpls *)(sa)) +#define smplstosa(smpls) ((struct sockaddr *)(smpls)) + +/* + * Names for MPLS sysctl objects + */ +#define MPLSCTL_ENABLE 1 +#define MPLSCTL_DEFTTL 2 +#define MPLSCTL_MAPTTL_IP 5 +#define MPLSCTL_MAPTTL_IP6 6 +#define MPLSCTL_MAXID 7 + +#define MPLSCTL_NAMES { \ + { NULL, 0 }, \ + { NULL, 0 }, \ + { "ttl", CTLTYPE_INT }, \ + { "ifq", CTLTYPE_NODE },\ + { NULL, 0 }, \ + { "mapttl_ip", CTLTYPE_INT }, \ + { "mapttl_ip6", CTLTYPE_INT } \ +} + +#define IMR_TYPE_NONE 0 +#define IMR_TYPE_ETHERNET 1 +#define IMR_TYPE_ETHERNET_TAGGED 2 + +#define IMR_FLAG_CONTROLWORD 0x1 + +struct ifmpwreq { + uint32_t imr_flags; + uint32_t imr_type; /* pseudowire type */ + struct shim_hdr imr_lshim; /* local label */ + struct shim_hdr imr_rshim; /* remote label */ + struct sockaddr_storage imr_nexthop; +}; + +#endif + +#ifdef _KERNEL + +#define MPLS_LABEL2SHIM(_l) (htonl((_l) << MPLS_LABEL_OFFSET)) +#define MPLS_SHIM2LABEL(_s) (ntohl((_s)) >> MPLS_LABEL_OFFSET) + +extern int mpls_defttl; +extern int mpls_mapttl_ip; +extern int mpls_mapttl_ip6; + + +struct mbuf *mpls_shim_pop(struct mbuf *); +struct mbuf *mpls_shim_swap(struct mbuf *, struct rt_mpls *); +struct mbuf *mpls_shim_push(struct mbuf *, struct rt_mpls *); + +struct mbuf *mpls_ip_adjttl(struct mbuf *, u_int8_t); +#ifdef INET6 +struct mbuf *mpls_ip6_adjttl(struct mbuf *, u_int8_t); +#endif + +int mpls_output(struct ifnet *, struct mbuf *, struct sockaddr *, + struct rtentry *); +void mpls_input(struct ifnet *, struct mbuf *, struct netstack *); + +#endif /* _KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/nfs/krpc.h b/lib/libc/include/generic-openbsd/nfs/krpc.h new file mode 100644 index 000000000000..43f50ecf8cfc --- /dev/null +++ b/lib/libc/include/generic-openbsd/nfs/krpc.h @@ -0,0 +1,28 @@ +/* $OpenBSD: krpc.h,v 1.7 2012/12/05 23:20:23 deraadt Exp $ */ +/* $NetBSD: krpc.h,v 1.4 1995/12/19 23:07:11 cgd Exp $ */ + +int krpc_call(struct sockaddr_in *, u_int, u_int, u_int, struct mbuf **, + struct mbuf **, int); +int krpc_portmap(struct sockaddr_in *, u_int, u_int, u_int16_t *); + +struct mbuf *xdr_string_encode(char *, int); +struct mbuf *xdr_string_decode(struct mbuf *, char *, int *); +struct mbuf *xdr_inaddr_encode(struct in_addr *); +struct mbuf *xdr_inaddr_decode(struct mbuf *, struct in_addr *); + +/* RPC definitions for the portmapper. */ +#define PMAPPORT 111 +#define PMAPPROG 100000 +#define PMAPVERS 2 +#define PMAPPROC_NULL 0 +#define PMAPPROC_SET 1 +#define PMAPPROC_UNSET 2 +#define PMAPPROC_GETPORT 3 +#define PMAPPROC_DUMP 4 +#define PMAPPROC_CALLIT 5 + +/* RPC definitions for bootparamd. */ +#define BOOTPARAM_PROG 100026 +#define BOOTPARAM_VERS 1 +#define BOOTPARAM_WHOAMI 1 +#define BOOTPARAM_GETFILE 2 \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/nfs/nfs.h b/lib/libc/include/generic-openbsd/nfs/nfs.h new file mode 100644 index 000000000000..3d47b496ca8d --- /dev/null +++ b/lib/libc/include/generic-openbsd/nfs/nfs.h @@ -0,0 +1,317 @@ +/* $OpenBSD: nfs.h,v 1.54 2024/05/04 10:53:37 jsg Exp $ */ +/* $NetBSD: nfs.h,v 1.10.4.1 1996/05/27 11:23:56 fvdl Exp $ */ + +/* + * Copyright (c) 1989, 1993, 1995 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)nfs.h 8.4 (Berkeley) 5/1/95 + */ + +#ifndef _NFS_NFS_H_ +#define _NFS_NFS_H_ + +#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */ +#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */ +#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */ +#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */ +#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */ +#define NFS_TIMEOUTMUL 2 /* Timeout/Delay multiplier */ +#define NFS_MAXREXMIT 100 /* Stop counting after this many */ +#define NFS_RETRANS 10 /* Num of retrans for soft mounts */ +#define NFS_MAXGRPS 16 /* Max. size of groups list */ +#define NFS_MINATTRTIMO 5 /* Attribute cache timeout in sec */ +#define NFS_MAXATTRTIMO 60 +#define NFS_WSIZE 8192 /* Def. write data size <= 8192 */ +#define NFS_RSIZE 8192 /* Def. read data size <= 8192 */ +#define NFS_READDIRSIZE 8192 /* Def. readdir size */ +#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */ +#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */ +#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */ + +/* + * Ideally, NFS_DIRBLKSIZ should be bigger, but I've seen servers with + * broken NFS/ethernet drivers that won't work with anything bigger (Linux..) + */ +#define NFS_DIRBLKSIZ 1024 /* Must be a multiple of DIRBLKSIZ */ +#define NFS_READDIRBLKSIZ 512 /* Size of read dir blocks. XXX */ + +/* + * Oddballs + */ +#define NFS_CMPFH(n, f, s) \ + ((n)->n_fhsize == (s) && !bcmp((caddr_t)(n)->n_fhp, (caddr_t)(f), (s))) +#define NFS_ISV3(v) (VFSTONFS((v)->v_mount)->nm_flag & NFSMNT_NFSV3) +#define NFS_SRVMAXDATA(n) \ + (((n)->nd_flag & ND_NFSV3) ? (((n)->nd_nam2) ? \ + NFS_MAXDGRAMDATA : NFS_MAXDATA) : NFS_V2MAXDATA) + +/* + * The B_INVAFTERWRITE flag should be set to whatever is required by the + * buffer cache code to say "Invalidate the block after it is written back". + */ +#define B_INVAFTERWRITE B_INVAL + +/* + * Structures for the nfssvc(2) syscall. + * Not that anyone besides nfsd(8) should ever use it. + */ +struct nfsd_args { + int sock; /* Socket to serve */ + caddr_t name; /* Client addr for connection based sockets */ + int namelen; /* Length of name */ +}; + +struct nfsd_srvargs { + struct nfsd *nsd_nfsd; /* Pointer to in kernel nfsd struct */ + uid_t nsd_uid; /* Effective uid mapped to cred */ + u_int32_t nsd_haddr; /* IP address of client */ + struct xucred nsd_cr; /* Cred. uid maps to */ + int nsd_authlen; /* Length of auth string (ret) */ + u_char *nsd_authstr; /* Auth string (ret) */ + int nsd_verflen; /* and the verifier */ + u_char *nsd_verfstr; + struct timeval nsd_timestamp; /* timestamp from verifier */ + u_int32_t nsd_ttl; /* credential ttl (sec) */ +}; + +/* + * Stats structure + */ +struct nfsstats { + uint64_t attrcache_hits; + uint64_t attrcache_misses; + uint64_t lookupcache_hits; + uint64_t lookupcache_misses; + uint64_t direofcache_hits; + uint64_t direofcache_misses; + uint64_t biocache_reads; + uint64_t read_bios; + uint64_t read_physios; + uint64_t biocache_writes; + uint64_t write_bios; + uint64_t write_physios; + uint64_t biocache_readlinks; + uint64_t readlink_bios; + uint64_t biocache_readdirs; + uint64_t readdir_bios; + uint64_t rpccnt[NFS_NPROCS]; + uint64_t rpcretries; + uint64_t srvrpccnt[NFS_NPROCS]; + uint64_t srvrpc_errs; + uint64_t srv_errs; + uint64_t rpcrequests; + uint64_t rpctimeouts; + uint64_t rpcunexpected; + uint64_t rpcinvalid; + uint64_t srvcache_inproghits; + uint64_t srvcache_idemdonehits; + uint64_t srvcache_nonidemdonehits; + uint64_t srvcache_misses; + uint64_t forcedsync; + uint64_t srvnqnfs_leases; + uint64_t srvnqnfs_maxleases; + uint64_t srvnqnfs_getleases; + uint64_t srvvop_writes; +}; + +/* + * Flags for nfssvc() system call. + */ +#define NFSSVC_NFSD 0x004 +#define NFSSVC_ADDSOCK 0x008 + +/* + * fs.nfs sysctl(3) identifiers + */ +#define NFS_NFSSTATS 1 /* struct: struct nfsstats */ +#define NFS_NIOTHREADS 2 /* number of i/o threads */ +#define NFS_MAXID 3 + +#define FS_NFS_NAMES { \ + { 0, 0 }, \ + { "nfsstats", CTLTYPE_STRUCT }, \ + { "iothreads", CTLTYPE_INT } \ +} + +/* + * The set of signals the interrupt an I/O in progress for NFSMNT_INT mounts. + * What should be in this set is open to debate, but I believe that since + * I/O system calls on ufs are never interrupted by signals the set should + * be minimal. My reasoning is that many current programs that use signals + * such as SIGALRM will not expect file I/O system calls to be interrupted + * by them and break. + */ +#ifdef _KERNEL +extern int nfs_niothreads; + +struct uio; struct buf; struct vattr; struct nameidata; /* XXX */ + +#define NFSINT_SIGMASK (sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGKILL)| \ + sigmask(SIGHUP)|sigmask(SIGQUIT)) + +/* + * Socket errors ignored for connectionless sockets?? + * For now, ignore them all + */ +#define NFSIGNORE_SOERROR(s, e) \ + ((e) != EINTR && (e) != ERESTART && (e) != EWOULDBLOCK && \ + ((s) & PR_CONNREQUIRED) == 0) + +/* + * Nfs outstanding request list element + */ +struct nfsreq { + TAILQ_ENTRY(nfsreq) r_chain; + struct mbuf *r_mreq; + struct mbuf *r_mrep; + struct mbuf *r_md; + caddr_t r_dpos; + struct nfsmount *r_nmp; + struct vnode *r_vp; + u_int32_t r_xid; + int r_flags; /* flags on request, see below */ + int r_rexmit; /* current retrans count */ + int r_timer; /* tick counter on reply */ + int r_procnum; /* NFS procedure number */ + int r_rtt; /* RTT for rpc */ + struct proc *r_procp; /* Proc that did I/O system call */ +}; + +/* Flag values for r_flags */ +#define R_TIMING 0x01 /* timing request (in mntp) */ +#define R_SENT 0x02 /* request has been sent */ +#define R_SOFTTERM 0x04 /* soft mnt, too many retries */ +#define R_INTR 0x08 /* intr mnt, signal pending */ +#define R_SOCKERR 0x10 /* Fatal error on socket */ +#define R_TPRINTFMSG 0x20 /* Did a tprintf msg. */ +#define R_MUSTRESEND 0x40 /* Must resend request */ + +/* + * On fast networks, the estimator will try to reduce the + * timeout lower than the latency of the server's disks, + * which results in too many timeouts, so cap the lower + * bound. + */ +#define NFS_MINRTO (NFS_HZ >> 2) + +/* + * Keep the RTO from increasing to unreasonably large values + * when a server is not responding. + */ +#define NFS_MAXRTO (20 * NFS_HZ) + +enum nfs_rto_timers { + NFS_DEFAULT_TIMER, + NFS_GETATTR_TIMER, + NFS_LOOKUP_TIMER, + NFS_READ_TIMER, + NFS_WRITE_TIMER, +}; +#define NFS_MAX_TIMER (NFS_WRITE_TIMER) + +#define NFS_INITRTT (NFS_HZ << 3) + +/* + * Network address hash list element + */ +union nethostaddr { + u_int32_t had_inetaddr; + struct mbuf *had_nam; +}; + +struct nfssvc_sock { + TAILQ_ENTRY(nfssvc_sock) ns_chain; /* List of all nfssvc_sock's */ + struct file *ns_fp; /* fp from the... */ + struct socket *ns_so; /* ...socket this struct wraps */ + struct mbuf *ns_nam; /* MT_SONAME of client */ + struct mbuf *ns_raw; /* head of unpeeked mbufs */ + struct mbuf *ns_rawend; /* tail of unpeeked mbufs */ + struct mbuf *ns_rec; /* queued RPC records */ + struct mbuf *ns_recend; /* last queued RPC record */ + struct mbuf *ns_frag; /* end of record fragment */ + int ns_flag; /* socket status flags */ + int ns_solock; /* lock for connected socket */ + int ns_cc; /* actual chars queued */ + int ns_reclen; /* length of first queued record */ + u_int32_t ns_sref; /* # of refs to this struct */ +}; + +/* Bits for "ns_flag" */ +#define SLP_VALID 0x01 /* connection is usable */ +#define SLP_DOREC 0x02 /* receive operation required */ +#define SLP_NEEDQ 0x04 /* connection has data to queue from socket */ +#define SLP_DISCONN 0x08 /* connection is closed */ +#define SLP_GETSTREAM 0x10 /* extracting RPC from TCP connection */ +#define SLP_LASTFRAG 0x20 /* last fragment received on TCP connection */ +#define SLP_ALLFLAGS 0xff /* convenience */ + +/* + * One of these structures is allocated for each nfsd. + */ +struct nfsd { + TAILQ_ENTRY(nfsd) nfsd_chain; /* List of all nfsd's */ + int nfsd_flag; /* NFSD_ flags */ + struct nfssvc_sock *nfsd_slp; /* Current socket */ + struct proc *nfsd_procp; /* Proc ptr */ + struct nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */ +}; + +/* Bits for "nfsd_flag" */ +#define NFSD_WAITING 0x01 +#define NFSD_REQINPROG 0x02 + +/* + * This structure is used by the server for describing each request. + */ +struct nfsrv_descript { + struct mbuf *nd_mrep; /* Request mbuf list */ + struct mbuf *nd_md; /* Current dissect mbuf */ + struct mbuf *nd_nam; /* and socket addr */ + struct mbuf *nd_nam2; /* return socket addr */ + caddr_t nd_dpos; /* Current dissect pos */ + unsigned int nd_procnum; /* RPC # */ + int nd_flag; /* nd_flag */ + int nd_repstat; /* Reply status */ + u_int32_t nd_retxid; /* Reply xid */ + struct ucred nd_cr; /* Credentials */ +}; + +/* Bits for "nd_flag" */ +#define ND_NFSV3 0x08 + +extern struct pool nfsreqpl; +extern struct pool nfs_node_pool; +extern TAILQ_HEAD(nfsdhead, nfsd) nfsd_head; +extern int nfsd_head_flag; +#define NFSD_CHECKSLP 0x01 + +#endif /* _KERNEL */ +#endif /* _NFS_NFS_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/nfs/nfs_var.h b/lib/libc/include/generic-openbsd/nfs/nfs_var.h new file mode 100644 index 000000000000..73c6f8e0cdbb --- /dev/null +++ b/lib/libc/include/generic-openbsd/nfs/nfs_var.h @@ -0,0 +1,202 @@ +/* $OpenBSD: nfs_var.h,v 1.66 2024/09/09 03:50:14 jsg Exp $ */ +/* $NetBSD: nfs_var.h,v 1.3 1996/02/18 11:53:54 fvdl Exp $ */ + +/* + * Copyright (c) 1996 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * XXX needs and because of typedefs. + */ +#ifndef _NFS_NFS_VAR_H_ +#define _NFS_NFS_VAR_H_ + +#ifdef _KERNEL + +struct nfsnode; +struct sillyrename; +struct componentname; +struct nfs_diskless; +struct nfsm_info; + +/* nfs_bio.c */ +int nfs_bioread(struct vnode *, struct uio *, int, struct ucred *); +int nfs_write(void *); +int nfs_vinvalbuf(struct vnode *, int, struct ucred *, struct proc *); +int nfs_asyncio(struct buf *, int readahead); +int nfs_doio(struct buf *, struct proc *); + +/* nfs_boot.c */ +int nfs_boot_init(struct nfs_diskless *, struct proc *); + +/* nfs_node.c */ +void nfs_ninit(struct nfsmount *); +int nfs_nget(struct mount *, nfsfh_t *, int, struct nfsnode **); +int nfs_inactive(void *); +int nfs_reclaim(void *); + +/* nfs_vnops.c */ +int nfs_readlink(void *); +int nfs_readlinkrpc(struct vnode *, struct uio *, struct ucred *); +int nfs_readrpc(struct vnode *, struct uio *); +int nfs_writerpc(struct vnode *, struct uio *, int *, int *); +int nfs_removeit(struct sillyrename *); +int nfs_writebp(struct buf *, int); + +#define nfs_ioctl ((int (*)(void *))enoioctl) + +/* nfs_serv.c */ +int nfsrv3_access(struct nfsrv_descript *, struct nfssvc_sock *, + struct proc *, struct mbuf **); +int nfsrv_getattr(struct nfsrv_descript *, struct nfssvc_sock *, + struct proc *, struct mbuf **); +int nfsrv_setattr(struct nfsrv_descript *, struct nfssvc_sock *, + struct proc *, struct mbuf **); +int nfsrv_lookup(struct nfsrv_descript *, struct nfssvc_sock *, + struct proc *, struct mbuf **); +int nfsrv_readlink(struct nfsrv_descript *, struct nfssvc_sock *, + struct proc *, struct mbuf **); +int nfsrv_read(struct nfsrv_descript *, struct nfssvc_sock *, + struct proc *, struct mbuf **); +int nfsrv_write(struct nfsrv_descript *, struct nfssvc_sock *, + struct proc *, struct mbuf **); +int nfsrv_create(struct nfsrv_descript *, struct nfssvc_sock *, + struct proc *, struct mbuf **); +int nfsrv_mknod(struct nfsrv_descript *, struct nfssvc_sock *, + struct proc *, struct mbuf **); +int nfsrv_remove(struct nfsrv_descript *, struct nfssvc_sock *, + struct proc *, struct mbuf **); +int nfsrv_rename(struct nfsrv_descript *, struct nfssvc_sock *, + struct proc *, struct mbuf **); +int nfsrv_link(struct nfsrv_descript *, struct nfssvc_sock *, + struct proc *, struct mbuf **); +int nfsrv_symlink(struct nfsrv_descript *, struct nfssvc_sock *, + struct proc *, struct mbuf **); +int nfsrv_mkdir(struct nfsrv_descript *, struct nfssvc_sock *, + struct proc *, struct mbuf **); +int nfsrv_rmdir(struct nfsrv_descript *, struct nfssvc_sock *, + struct proc *, struct mbuf **); +int nfsrv_readdir(struct nfsrv_descript *, struct nfssvc_sock *, + struct proc *, struct mbuf **); +int nfsrv_readdirplus(struct nfsrv_descript *, struct nfssvc_sock *, + struct proc *, struct mbuf **); +int nfsrv_commit(struct nfsrv_descript *, struct nfssvc_sock *, + struct proc *, struct mbuf **); +int nfsrv_statfs(struct nfsrv_descript *, struct nfssvc_sock *, + struct proc *, struct mbuf **); +int nfsrv_fsinfo(struct nfsrv_descript *, struct nfssvc_sock *, + struct proc *, struct mbuf **); +int nfsrv_pathconf(struct nfsrv_descript *, struct nfssvc_sock *, + struct proc *, struct mbuf **); +int nfsrv_null(struct nfsrv_descript *, struct nfssvc_sock *, + struct proc *, struct mbuf **); +int nfsrv_noop(struct nfsrv_descript *, struct nfssvc_sock *, + struct proc *, struct mbuf **); + +/* nfs_socket.c */ +int nfs_connect(struct nfsmount *, struct nfsreq *); +void nfs_disconnect(struct nfsmount *); +int nfs_send(struct socket *, struct mbuf *, struct mbuf *, + struct nfsreq *); +int nfs_request(struct vnode *, int, struct nfsm_info *); +int nfs_rephead(int, struct nfsrv_descript *, struct nfssvc_sock *, int, + struct mbuf **, struct mbuf **); +void nfs_timer(void *); +int nfs_sigintr(struct nfsmount *, struct nfsreq *, struct proc *); +int nfs_sndlock(int *, struct nfsreq *); +void nfs_sndunlock(int *); +void nfsrv_rcv(struct socket *, caddr_t, int); +int nfsrv_dorec(struct nfssvc_sock *, struct nfsd *, + struct nfsrv_descript **); +void nfsrv_wakenfsd(struct nfssvc_sock *); + +/* nfs_srvcache.c */ +void nfsrv_initcache(void ); +int nfsrv_getcache(struct nfsrv_descript *, struct nfssvc_sock *, + struct mbuf **); +void nfsrv_updatecache(struct nfsrv_descript *, int, struct mbuf *); +void nfsrv_cleancache(void); + +/* nfs_srvsubs.c */ +int nfs_namei(struct nameidata *, fhandle_t *, int, struct nfssvc_sock *, + struct mbuf *, struct mbuf **, caddr_t *, struct vnode **, + struct proc *); +void nfsm_adj(struct mbuf *, int, int); +void nfsm_srvwcc(struct nfsrv_descript *, int, struct vattr *, int, + struct vattr *, struct nfsm_info *); +void nfsm_srvpostop_attr(struct nfsrv_descript *, int, struct vattr *, + struct nfsm_info *); +void nfsm_srvfattr(struct nfsrv_descript *, struct vattr *, + struct nfs_fattr *); +int nfsrv_fhtovp(fhandle_t *, int, struct vnode **, struct ucred *, + struct nfssvc_sock *, struct mbuf *, int *); +int netaddr_match(int, union nethostaddr *, struct mbuf *); +int nfsm_srvsattr(struct mbuf **, struct vattr *, struct mbuf *, caddr_t *); + +/* nfs_subs.c */ +struct mbuf *nfsm_reqhead(int); +void nfsm_rpchead(struct nfsreq *, struct ucred *, int); +void *nfsm_build(struct mbuf **, u_int); +int nfsm_mbuftouio(struct mbuf **, struct uio *, int, caddr_t *); +void nfsm_uiotombuf(struct mbuf **, struct uio *, size_t); +void nfsm_strtombuf(struct mbuf **, void *, size_t); +void nfsm_buftombuf(struct mbuf **, void *, size_t); +int nfs_adv(struct mbuf **, caddr_t *, int, int); +int nfs_vfs_init(struct vfsconf *); +int nfs_attrtimeo(struct nfsnode *); +int nfs_loadattrcache(struct vnode **, struct mbuf **, caddr_t *, + struct vattr *); +int nfs_getattrcache(struct vnode *, struct vattr *); +void nfsm_v3attrbuild(struct mbuf **, struct vattr *, int); +int nfsm_disct(struct mbuf **, caddr_t *, int, int, caddr_t *); +void nfs_clearcommit(struct mount *); +int nfs_in_committed_range(struct vnode *, struct buf *); +int nfs_in_tobecommitted_range(struct vnode *, struct buf *); +void nfs_add_committed_range(struct vnode *, struct buf *); +void nfs_del_committed_range(struct vnode *, struct buf *); +void nfs_add_tobecommitted_range(struct vnode *, struct buf *); +void nfs_del_tobecommitted_range(struct vnode *, struct buf *); +void nfs_merge_commit_ranges(struct vnode *); +int nfsrv_errmap(struct nfsrv_descript *, int); +void nfsm_fhtom(struct nfsm_info *, struct vnode *, int); +void nfsm_srvfhtom(struct mbuf **, fhandle_t *, int); + +/* nfs_syscalls.c */ +int sys_nfssvc(struct proc *, void *, register_t *); +void nfsrv_init(int); +void nfs_getset_niothreads(int); + +/* nfs_kq.c */ +int nfs_kqfilter(void *); + +/* Internal NFS utility macros */ +#define mb_offset(m) (mtod((m), caddr_t) + (m)->m_len) +#define nfsm_padlen(s) (nfsm_rndup(s) - (s)) + +#endif /* _KERNEL */ +#endif /* _NFS_NFS_VAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/nfs/nfsdiskless.h b/lib/libc/include/generic-openbsd/nfs/nfsdiskless.h new file mode 100644 index 000000000000..0b9fa1d2db36 --- /dev/null +++ b/lib/libc/include/generic-openbsd/nfs/nfsdiskless.h @@ -0,0 +1,68 @@ +/* $OpenBSD: nfsdiskless.h,v 1.10 2013/09/20 23:51:44 fgsch Exp $ */ +/* $NetBSD: nfsdiskless.h,v 1.9 1996/02/18 11:54:00 fvdl Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)nfsdiskless.h 8.2 (Berkeley) 3/30/95 + */ + +#ifndef _NFS_DISKLESS_H_ +#define _NFS_DISKLESS_H_ + +/* + * Structure that must be initialized for a diskless nfs client. + * This structure is used by nfs_mountroot() to set up the root and swap + * vnodes plus do a partial ifconfig(8) and route(8) so that the critical + * net interface can communicate with the server. + * Whether or not the swap area is nfs mounted is determined + * by the value in swdevt[0]. (equal to NODEV --> swap over nfs) + * Currently only works for AF_INET protocols. + * NB: All fields are stored in net byte order to avoid hassles with + * client/server byte ordering differences. + */ +struct nfs_dlmount { + struct nfs_args ndm_args; + struct sockaddr_in ndm_saddr; /* Address of file server */ + char ndm_host[MNAMELEN]; /* Host name for mount pt */ + u_char ndm_fh[NFSX_V3FHMAX]; /* The file's file handle */ +}; +struct nfs_diskless { + struct sockaddr_in nd_boot; /* Address of boot server */ + struct nfs_dlmount nd_root; /* Mount info for root */ + struct nfs_dlmount nd_swap; /* Mount info for swap */ + struct vnode *sw_vp; +}; + +int nfs_boot_init(struct nfs_diskless *nd, struct proc *procp); +int nfs_boot_getfh(struct sockaddr_in *bpsin, char *key, + struct nfs_dlmount *ndmntp, int retries); +#endif /* _NFS_DISKLESS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/nfs/nfsm_subs.h b/lib/libc/include/generic-openbsd/nfs/nfsm_subs.h new file mode 100644 index 000000000000..d6dcf14622e6 --- /dev/null +++ b/lib/libc/include/generic-openbsd/nfs/nfsm_subs.h @@ -0,0 +1,185 @@ +/* $OpenBSD: nfsm_subs.h,v 1.49 2024/09/11 12:22:34 claudio Exp $ */ +/* $NetBSD: nfsm_subs.h,v 1.10 1996/03/20 21:59:56 fvdl Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)nfsm_subs.h 8.2 (Berkeley) 3/30/95 + */ + + +#ifndef _NFS_NFSM_SUBS_H_ +#define _NFS_NFSM_SUBS_H_ + +struct nfsm_info { + struct mbuf *nmi_mreq; + struct mbuf *nmi_mrep; + + struct proc *nmi_procp; /* XXX XXX XXX */ + struct ucred *nmi_cred; /* XXX XXX XXX */ + + /* Setting up / Tearing down. */ + struct mbuf *nmi_md; + struct mbuf *nmi_mb; + caddr_t nmi_dpos; + + int nmi_v3; + + int *nmi_errorp; +}; + +static inline void * +nfsm_dissect(struct nfsm_info *infop, int s) +{ + caddr_t ret; + int avail, error; + + avail = mtod(infop->nmi_md, caddr_t) + infop->nmi_md->m_len - + infop->nmi_dpos; + if (avail >= s) { + ret = infop->nmi_dpos; + infop->nmi_dpos += s; + return ret; + } + error = nfsm_disct(&infop->nmi_md, &infop->nmi_dpos, s, avail, &ret); + if (error != 0) { + m_freem(infop->nmi_mrep); + infop->nmi_mrep = NULL; + *infop->nmi_errorp = error; + return NULL; + } else { + return ret; + } +} + +#define nfsm_rndup(a) (((a)+3)&(~0x3)) + +static inline int +nfsm_adv(struct nfsm_info *infop, int s) +{ + int avail, error; + + avail = mtod(infop->nmi_md, caddr_t) + infop->nmi_md->m_len - + infop->nmi_dpos; + if (avail >= s) { + infop->nmi_dpos += s; + return 0; + } + error = nfs_adv(&infop->nmi_md, &infop->nmi_dpos, s, avail); + if (error != 0) { + m_freem(infop->nmi_mrep); + infop->nmi_mrep = NULL; + *infop->nmi_errorp = error; + return error; + } + return 0; +} + +static inline int +nfsm_postop_attr(struct nfsm_info *infop, struct vnode **vpp, int *attrflagp) +{ + uint32_t *tl; + struct vnode *ttvp; + int attrflag, error; + + if (infop->nmi_mrep == NULL) + return 0; + + ttvp = *vpp; + tl = (uint32_t *)nfsm_dissect(infop, NFSX_UNSIGNED); + if (tl == NULL) + return 1; /* anything nonzero */ + attrflag = fxdr_unsigned(int, *tl); + if (attrflag != 0) { + error = nfs_loadattrcache(&ttvp, &infop->nmi_md, + &infop->nmi_dpos, NULL); + if (error != 0) { + m_freem(infop->nmi_mrep); + infop->nmi_mrep = NULL; + *infop->nmi_errorp = error; + return error; + } + *vpp = ttvp; + } + *attrflagp = attrflag; + return 0; +} + +static inline int +nfsm_strsiz(struct nfsm_info *infop, int *lenp, int maxlen) +{ + uint32_t *tl = (uint32_t *)nfsm_dissect(infop, NFSX_UNSIGNED); + int len; + if (tl == NULL) + return 1; + len = fxdr_unsigned(int32_t, *tl); + if (len < 0 || len > maxlen) { + m_freem(infop->nmi_mrep); + infop->nmi_mrep = NULL; + *infop->nmi_errorp = EBADRPC; + return 1; + } + *lenp = len; + return 0; +} + +static inline int +nfsm_mtouio(struct nfsm_info *infop, struct uio *uiop, int len) +{ + int error; + + if (len <= 0) + return 0; + + error = nfsm_mbuftouio(&infop->nmi_md, uiop, len, &infop->nmi_dpos); + if (error != 0) { + m_freem(infop->nmi_mrep); + infop->nmi_mrep = NULL; + *infop->nmi_errorp = error; + return error; + } + return 0; +} + +static inline int +nfsm_strtom(struct nfsm_info *infop, char *str, size_t len, size_t maxlen) +{ + if (len > maxlen) { + m_freem(infop->nmi_mreq); + infop->nmi_mreq = NULL; + *infop->nmi_errorp = ENAMETOOLONG; + return 1; + } + nfsm_strtombuf(&infop->nmi_mb, str, len); + return 0; +} + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/nfs/nfsmount.h b/lib/libc/include/generic-openbsd/nfs/nfsmount.h new file mode 100644 index 000000000000..94d988971e9d --- /dev/null +++ b/lib/libc/include/generic-openbsd/nfs/nfsmount.h @@ -0,0 +1,94 @@ +/* $OpenBSD: nfsmount.h,v 1.28 2018/04/09 09:39:53 mpi Exp $ */ +/* $NetBSD: nfsmount.h,v 1.10 1996/02/18 11:54:03 fvdl Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)nfsmount.h 8.3 (Berkeley) 3/30/95 + */ + + +#ifndef _NFS_NFSMOUNT_H_ +#define _NFS_NFSMOUNT_H_ + +/* + * Mount structure. + * One allocated on every NFS mount. + * Holds NFS specific information for mount. + */ +struct nfsmount { + RBT_HEAD(nfs_nodetree, nfsnode) + nm_ntree; /* filehandle/node tree */ + TAILQ_HEAD(reqs, nfsreq) + nm_reqsq; /* request queue for this mount. */ + struct timeout nm_rtimeout; /* timeout (scans/resends nm_reqsq). */ + struct mount *nm_mountp; /* Vfs structure for this filesystem */ + struct vnode *nm_vnode; /* vnode of root dir */ + int nm_flag; /* Flags for soft/hard... */ + int nm_numgrps; /* Max. size of groupslist */ + struct socket *nm_so; /* Rpc socket */ + int nm_sotype; /* Type of socket */ + int nm_soproto; /* and protocol */ + int nm_soflags; /* pr_flags for socket protocol */ + struct mbuf *nm_nam; /* Addr of server */ + int nm_timeo; /* Init timer for NFSMNT_DUMBTIMR */ + int nm_retry; /* Max retries */ + int nm_srtt[NFS_MAX_TIMER]; /* RTT Timers for RPCs */ + int nm_sdrtt[NFS_MAX_TIMER]; + int nm_sent; /* Request send count */ + int nm_cwnd; /* Request send window */ + int nm_timeouts; /* Request timeouts */ + int nm_rsize; /* Max size of read rpc */ + int nm_wsize; /* Max size of write rpc */ + int nm_readdirsize; /* Size of a readdir rpc */ + int nm_readahead; /* Num. of blocks to readahead */ + u_char nm_verf[NFSX_V3WRITEVERF]; /* V3 write verifier */ + u_short nm_acregmin; /* Attr cache file recently modified */ + u_short nm_acregmax; /* ac file not recently modified */ + u_short nm_acdirmin; /* ac for dir recently modified */ + u_short nm_acdirmax; /* ac for dir not recently modified */ +}; + +#ifdef _KERNEL + +/* Convert mount ptr to nfsmount ptr: */ +#define VFSTONFS(mp) ((struct nfsmount *)((mp)->mnt_data)) + +/* Prototypes for NFS mount operations: */ +int nfs_mount(struct mount *, const char *, void *, struct nameidata *, + struct proc *); +int nfs_fsinfo(struct nfsmount *, struct vnode *, struct ucred *, + struct proc *); +void nfs_init(void); + +#endif /* _KERNEL */ + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/nfs/nfsnode.h b/lib/libc/include/generic-openbsd/nfs/nfsnode.h new file mode 100644 index 000000000000..dbc4ccffb760 --- /dev/null +++ b/lib/libc/include/generic-openbsd/nfs/nfsnode.h @@ -0,0 +1,141 @@ +/* $OpenBSD: nfsnode.h,v 1.44 2025/08/28 18:30:08 claudio Exp $ */ +/* $NetBSD: nfsnode.h,v 1.16 1996/02/18 11:54:04 fvdl Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)nfsnode.h 8.9 (Berkeley) 5/14/95 + */ + + +#ifndef _NFS_NFSNODE_H_ +#define _NFS_NFSNODE_H_ + +#ifndef _NFS_NFS_H_ +#include +#endif + +#include + +/* + * Silly rename structure that hangs off the nfsnode until the name + * can be removed by nfs_inactive() + */ +struct sillyrename { + struct ucred *s_cred; + struct vnode *s_dvp; + long s_namlen; + char s_name[24]; +}; + +/* + * The nfsnode is the nfs equivalent to ufs's inode. Any similarity + * is purely coincidental. + * There is a unique nfsnode allocated for each active file, + * each current directory, each mounted-on file, text file, and the root. + * An nfsnode is 'named' by its file handle. (nget/nfs_node.c) + */ +struct nfsnode { + RBT_ENTRY(nfsnode) n_entry; /* filehandle/node tree. */ + u_quad_t n_size; /* Current size of file */ + struct vattr n_vattr; /* Vnode attribute cache */ + time_t n_attrstamp; /* Attr. cache timestamp */ + struct timespec n_mtime; /* Prev modify time. */ + time_t n_ctime; /* Prev create time. */ + nfsfh_t *n_fhp; /* NFS File Handle */ + struct vnode *n_vnode; /* associated vnode */ + struct lockf_state *n_lockf; /* Locking record of file */ + struct rrwlock n_lock; /* NFSnode lock */ + int n_error; /* Save write error value */ + union { + struct timespec nf_atim; /* Special file times */ + nfsuint64 nd_cookieverf; /* Cookie verifier (dir only) */ + } n_un1; + union { + struct timespec nf_mtim; + off_t nd_direof; /* Dir. EOF offset cache */ + } n_un2; + struct sillyrename *n_sillyrename; /* Ptr to silly rename struct */ + short n_fhsize; /* size in bytes, of fh */ + short n_flag; /* Flag for locking.. */ + nfsfh_t n_fh; /* Small File Handle */ + time_t n_accstamp; /* Access cache timestamp */ + uid_t n_accuid; /* Last access requester */ + int n_accmode; /* Last mode requested */ + int n_accerror; /* Last returned error */ + struct ucred *n_rcred; + struct ucred *n_wcred; + + off_t n_pushedlo; /* 1st blk in committed range */ + off_t n_pushedhi; /* Last block in range */ + off_t n_pushlo; /* 1st block in commit range */ + off_t n_pushhi; /* Last block in range */ + struct rwlock n_commitlock; /* Serialize commits */ + int n_commitflags; +}; + +/* + * Values for n_commitflags + */ +#define NFS_COMMIT_PUSH_VALID 0x0001 /* push range valid */ +#define NFS_COMMIT_PUSHED_VALID 0x0002 /* pushed range valid */ + +#define n_atim n_un1.nf_atim +#define n_mtim n_un2.nf_mtim +#define n_cookieverf n_un1.nd_cookieverf +#define n_direofoffset n_un2.nd_direof + +/* + * Flags for n_flag + */ +#define NFLUSHWANT 0x0001 /* Want wakeup from a flush in prog. */ +#define NFLUSHINPROG 0x0002 /* Avoid multiple calls to vinvalbuf() */ +#define NMODIFIED 0x0004 /* Might have a modified buffer in bio */ +#define NWRITEERR 0x0008 /* Flag write errors so close will know */ +#define NACC 0x0100 /* Special file accessed */ +#define NUPD 0x0200 /* Special file updated */ +#define NCHG 0x0400 /* Special file times changed */ + +#define NFS_INVALIDATE_ATTRCACHE(np) ((np)->n_attrstamp = 0) + +/* + * Convert between nfsnode pointers and vnode pointers + */ +#define VTONFS(vp) ((struct nfsnode *)(vp)->v_data) +#define NFSTOV(np) ((np)->n_vnode) + +/* + * Queue head for nfsiod's + */ +extern TAILQ_HEAD(nfs_bufqhead, buf) nfs_bufq; +extern uint32_t nfs_bufqlen, nfs_bufqmax; + +#endif /* _NFS_NFSNODE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/nfs/nfsproto.h b/lib/libc/include/generic-openbsd/nfs/nfsproto.h new file mode 100644 index 000000000000..04fe7be0f4c4 --- /dev/null +++ b/lib/libc/include/generic-openbsd/nfs/nfsproto.h @@ -0,0 +1,415 @@ +/* $OpenBSD: nfsproto.h,v 1.11 2024/04/30 17:06:00 miod Exp $ */ +/* $NetBSD: nfsproto.h,v 1.1 1996/02/18 11:54:06 fvdl Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)nfsproto.h 8.2 (Berkeley) 3/30/95 + */ + +#ifndef _NFS_NFSPROTO_H_ +#define _NFS_NFSPROTO_H_ + +/* + * Constants as defined in the Sun NFS Version 2 and 3 specs. + * "NFS: Network File System Protocol Specification" RFC1094 + * and in the "NFS: Network File System Version 3 Protocol + * Specification" + */ + +#define NFS_PORT 2049 +#define NFS_PROG 100003 +#define NFS_VER2 2 +#define NFS_VER3 3 +#define NFS_VER4 4 +#define NFS_V2MAXDATA 8192 +#define NFS_MAXDGRAMDATA 32768 +#define NFS_MAXDATA MAXBSIZE +#define NFS_MAXPATHLEN 1024 +#define NFS_MAXNAMLEN 255 +#define NFS_MAXPKTHDR 404 +#define NFS_MAXPACKET (NFS_MAXPKTHDR + NFS_MAXDATA) +#define NFS_MINPACKET 20 +#define NFS_FABLKSIZE 512 /* Size in bytes of a block wrt fa_blocks */ + +/* Stat numbers for rpc returns (version 2 and 3) */ +#define NFS_OK 0 +#define NFSERR_PERM 1 +#define NFSERR_NOENT 2 +#define NFSERR_IO 5 +#define NFSERR_NXIO 6 +#define NFSERR_ACCES 13 +#define NFSERR_EXIST 17 +#define NFSERR_XDEV 18 /* Version 3 only */ +#define NFSERR_NODEV 19 +#define NFSERR_NOTDIR 20 +#define NFSERR_ISDIR 21 +#define NFSERR_INVAL 22 /* Version 3 only */ +#define NFSERR_FBIG 27 +#define NFSERR_NOSPC 28 +#define NFSERR_ROFS 30 +#define NFSERR_MLINK 31 /* Version 3 only */ +#define NFSERR_NAMETOL 63 +#define NFSERR_NOTEMPTY 66 +#define NFSERR_DQUOT 69 +#define NFSERR_STALE 70 +#define NFSERR_REMOTE 71 /* Version 3 only */ +#define NFSERR_WFLUSH 99 /* Version 2 only */ +#define NFSERR_BADHANDLE 10001 /* The rest Version 3 only */ +#define NFSERR_NOT_SYNC 10002 +#define NFSERR_BAD_COOKIE 10003 +#define NFSERR_NOTSUPP 10004 +#define NFSERR_TOOSMALL 10005 +#define NFSERR_SERVERFAULT 10006 +#define NFSERR_BADTYPE 10007 +#define NFSERR_JUKEBOX 10008 +#define NFSERR_TRYLATER NFSERR_JUKEBOX +#define NFSERR_STALEWRITEVERF 30001 /* Fake return for nfs_commit() */ + +#define NFSERR_RETVOID 0x20000000 /* Return void, not error */ +#define NFSERR_AUTHERR 0x40000000 /* Mark an authentication error */ +#define NFSERR_RETERR 0x80000000 /* Mark an error return for V3 */ + +/* Sizes in bytes of various nfs rpc components */ +#define NFSX_UNSIGNED 4 + +/* specific to NFS Version 2 */ +#define NFSX_V2FH 32 +#define NFSX_V2FATTR 68 +#define NFSX_V2SATTR 32 +#define NFSX_V2COOKIE 4 +#define NFSX_V2STATFS 20 + +/* specific to NFS Version 3 */ +#define NFSX_V3FH (sizeof (fhandle_t)) /* size this server uses */ +#define NFSX_V3FHMAX 64 /* max. allowed by protocol */ +#define NFSX_V3FATTR 84 +#define NFSX_V3SATTR 60 /* max. all fields filled in */ +#define NFSX_V3SRVSATTR (sizeof (struct nfsv3_sattr)) +#define NFSX_V3POSTOPATTR (NFSX_V3FATTR + NFSX_UNSIGNED) +#define NFSX_V3WCCDATA (NFSX_V3POSTOPATTR + 8 * NFSX_UNSIGNED) +#define NFSX_V3COOKIEVERF 8 +#define NFSX_V3WRITEVERF 8 +#define NFSX_V3CREATEVERF 8 +#define NFSX_V3STATFS 52 +#define NFSX_V3FSINFO 48 +#define NFSX_V3PATHCONF 24 + +/* variants for both versions */ +#define NFSX_FH(v3) ((v3) ? (NFSX_V3FHMAX + NFSX_UNSIGNED) : \ + NFSX_V2FH) +#define NFSX_SRVFH(v3) ((v3) ? NFSX_V3FH : NFSX_V2FH) +#define NFSX_FATTR(v3) ((v3) ? NFSX_V3FATTR : NFSX_V2FATTR) +#define NFSX_PREOPATTR(v3) ((v3) ? (7 * NFSX_UNSIGNED) : 0) +#define NFSX_POSTOPATTR(v3) ((v3) ? (NFSX_V3FATTR + NFSX_UNSIGNED) : 0) +#define NFSX_POSTOPORFATTR(v3) ((v3) ? (NFSX_V3FATTR + NFSX_UNSIGNED) : \ + NFSX_V2FATTR) +#define NFSX_WCCDATA(v3) ((v3) ? NFSX_V3WCCDATA : 0) +#define NFSX_WCCORFATTR(v3) ((v3) ? NFSX_V3WCCDATA : NFSX_V2FATTR) +#define NFSX_SATTR(v3) ((v3) ? NFSX_V3SATTR : NFSX_V2SATTR) +#define NFSX_COOKIEVERF(v3) ((v3) ? NFSX_V3COOKIEVERF : 0) +#define NFSX_WRITEVERF(v3) ((v3) ? NFSX_V3WRITEVERF : 0) +#define NFSX_READDIR(v3) ((v3) ? (5 * NFSX_UNSIGNED) : \ + (2 * NFSX_UNSIGNED)) +#define NFSX_STATFS(v3) ((v3) ? NFSX_V3STATFS : NFSX_V2STATFS) + +/* nfs rpc procedure numbers (before version mapping) */ +#define NFSPROC_NULL 0 +#define NFSPROC_GETATTR 1 +#define NFSPROC_SETATTR 2 +#define NFSPROC_LOOKUP 3 +#define NFSPROC_ACCESS 4 +#define NFSPROC_READLINK 5 +#define NFSPROC_READ 6 +#define NFSPROC_WRITE 7 +#define NFSPROC_CREATE 8 +#define NFSPROC_MKDIR 9 +#define NFSPROC_SYMLINK 10 +#define NFSPROC_MKNOD 11 +#define NFSPROC_REMOVE 12 +#define NFSPROC_RMDIR 13 +#define NFSPROC_RENAME 14 +#define NFSPROC_LINK 15 +#define NFSPROC_READDIR 16 +#define NFSPROC_READDIRPLUS 17 +#define NFSPROC_FSSTAT 18 +#define NFSPROC_FSINFO 19 +#define NFSPROC_PATHCONF 20 +#define NFSPROC_COMMIT 21 +#define NFSPROC_NOOP 22 +#define NFS_NPROCS 23 + +/* Actual Version 2 procedure numbers */ +#define NFSV2PROC_NULL 0 +#define NFSV2PROC_GETATTR 1 +#define NFSV2PROC_SETATTR 2 +#define NFSV2PROC_NOOP 3 +#define NFSV2PROC_ROOT NFSV2PROC_NOOP /* Obsolete */ +#define NFSV2PROC_LOOKUP 4 +#define NFSV2PROC_READLINK 5 +#define NFSV2PROC_READ 6 +#define NFSV2PROC_WRITECACHE NFSV2PROC_NOOP /* Obsolete */ +#define NFSV2PROC_WRITE 8 +#define NFSV2PROC_CREATE 9 +#define NFSV2PROC_REMOVE 10 +#define NFSV2PROC_RENAME 11 +#define NFSV2PROC_LINK 12 +#define NFSV2PROC_SYMLINK 13 +#define NFSV2PROC_MKDIR 14 +#define NFSV2PROC_RMDIR 15 +#define NFSV2PROC_READDIR 16 +#define NFSV2PROC_STATFS 17 + +/* + * Constants used by the Version 3 protocol for various RPCs + */ +#define NFSV3SATTRTIME_DONTCHANGE 0 +#define NFSV3SATTRTIME_TOSERVER 1 +#define NFSV3SATTRTIME_TOCLIENT 2 + +#define NFSV3ACCESS_READ 0x01 +#define NFSV3ACCESS_LOOKUP 0x02 +#define NFSV3ACCESS_MODIFY 0x04 +#define NFSV3ACCESS_EXTEND 0x08 +#define NFSV3ACCESS_DELETE 0x10 +#define NFSV3ACCESS_EXECUTE 0x20 + +#define NFSV3WRITE_UNSTABLE 0 +#define NFSV3WRITE_DATASYNC 1 +#define NFSV3WRITE_FILESYNC 2 + +#define NFSV3CREATE_UNCHECKED 0 +#define NFSV3CREATE_GUARDED 1 +#define NFSV3CREATE_EXCLUSIVE 2 + +#define NFSV3FSINFO_LINK 0x01 +#define NFSV3FSINFO_SYMLINK 0x02 +#define NFSV3FSINFO_HOMOGENEOUS 0x08 +#define NFSV3FSINFO_CANSETTIME 0x10 + +/* Conversion macros */ +#define vtonfsv2_mode(t,m) \ + txdr_unsigned(((t) == VFIFO) ? MAKEIMODE(VCHR, (m)) : \ + MAKEIMODE((t), (m))) +#define vtonfsv3_mode(m) txdr_unsigned((m) & 07777) +#define nfstov_mode(a) (fxdr_unsigned(mode_t, (a))&07777) +#define vtonfsv2_type(a) txdr_unsigned(nfsv2_type[((int32_t)(a))]) +#define vtonfsv3_type(a) txdr_unsigned(nfsv3_type[((int32_t)(a))]) +#define nfsv2tov_type(a) nv2tov_type[fxdr_unsigned(u_int32_t,(a))&0x7] +#define nfsv3tov_type(a) nv3tov_type[fxdr_unsigned(u_int32_t,(a))&0x7] + +/* File types */ +typedef enum { NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5, + NFSOCK=6, NFFIFO=7 } nfstype; + +/* Structs for common parts of the rpc's */ +/* + * File Handle (32 bytes for version 2), variable up to 64 for version 3. + */ +#ifndef NFS_MAXFHSIZE +#define NFS_MAXFHSIZE 64 +#endif +union nfsfh { + fhandle_t fh_generic; + u_char fh_bytes[NFS_MAXFHSIZE]; +}; +typedef union nfsfh nfsfh_t; + +struct nfsv2_time { + u_int32_t nfsv2_sec; + u_int32_t nfsv2_usec; +}; +typedef struct nfsv2_time nfstime2; + +struct nfsv3_time { + u_int32_t nfsv3_sec; + u_int32_t nfsv3_nsec; +}; +typedef struct nfsv3_time nfstime3; + +/* + * Quads are defined as arrays of 2 longs to ensure dense packing for the + * protocol and to facilitate xdr conversion. + */ +struct nfs_uquad { + u_int32_t nfsuquad[2]; +}; +typedef struct nfs_uquad nfsuint64; + +/* + * NFS Version 3 special file number. + */ +struct nfsv3_spec { + u_int32_t specdata1; + u_int32_t specdata2; +}; +typedef struct nfsv3_spec nfsv3spec; + +/* + * File attributes and setable attributes. These structures cover both + * NFS version 2 and the version 3 protocol. Note that the union is only + * used so that one pointer can refer to both variants. These structures + * go out on the wire and must be densely packed, so no quad data types + * are used. (all fields are longs or u_longs or structures of same) + * NB: You can't do sizeof(struct nfs_fattr), you must use the + * NFSX_FATTR(v3) macro. + */ +struct nfs_fattr { + u_int32_t fa_type; + u_int32_t fa_mode; + u_int32_t fa_nlink; + u_int32_t fa_uid; + u_int32_t fa_gid; + union { + struct { + u_int32_t nfsv2fa_size; + u_int32_t nfsv2fa_blocksize; + u_int32_t nfsv2fa_rdev; + u_int32_t nfsv2fa_blocks; + u_int32_t nfsv2fa_fsid; + u_int32_t nfsv2fa_fileid; + nfstime2 nfsv2fa_atime; + nfstime2 nfsv2fa_mtime; + nfstime2 nfsv2fa_ctime; + } fa_nfsv2; + struct { + nfsuint64 nfsv3fa_size; + nfsuint64 nfsv3fa_used; + nfsv3spec nfsv3fa_rdev; + nfsuint64 nfsv3fa_fsid; + nfsuint64 nfsv3fa_fileid; + nfstime3 nfsv3fa_atime; + nfstime3 nfsv3fa_mtime; + nfstime3 nfsv3fa_ctime; + } fa_nfsv3; + } fa_un; +}; + +/* and some ugly defines for accessing union components */ +#define fa2_size fa_un.fa_nfsv2.nfsv2fa_size +#define fa2_blocksize fa_un.fa_nfsv2.nfsv2fa_blocksize +#define fa2_rdev fa_un.fa_nfsv2.nfsv2fa_rdev +#define fa2_blocks fa_un.fa_nfsv2.nfsv2fa_blocks +#define fa2_fsid fa_un.fa_nfsv2.nfsv2fa_fsid +#define fa2_fileid fa_un.fa_nfsv2.nfsv2fa_fileid +#define fa2_atime fa_un.fa_nfsv2.nfsv2fa_atime +#define fa2_mtime fa_un.fa_nfsv2.nfsv2fa_mtime +#define fa2_ctime fa_un.fa_nfsv2.nfsv2fa_ctime +#define fa3_size fa_un.fa_nfsv3.nfsv3fa_size +#define fa3_used fa_un.fa_nfsv3.nfsv3fa_used +#define fa3_rdev fa_un.fa_nfsv3.nfsv3fa_rdev +#define fa3_fsid fa_un.fa_nfsv3.nfsv3fa_fsid +#define fa3_fileid fa_un.fa_nfsv3.nfsv3fa_fileid +#define fa3_atime fa_un.fa_nfsv3.nfsv3fa_atime +#define fa3_mtime fa_un.fa_nfsv3.nfsv3fa_mtime +#define fa3_ctime fa_un.fa_nfsv3.nfsv3fa_ctime + +struct nfsv2_sattr { + u_int32_t sa_mode; + u_int32_t sa_uid; + u_int32_t sa_gid; + u_int32_t sa_size; + nfstime2 sa_atime; + nfstime2 sa_mtime; +}; + +/* + * NFS Version 3 sattr structure for the new node creation case. + */ +struct nfsv3_sattr { + u_int32_t sa_modetrue; + u_int32_t sa_mode; + u_int32_t sa_uidfalse; + u_int32_t sa_gidfalse; + u_int32_t sa_sizefalse; + u_int32_t sa_atimetype; + nfstime3 sa_atime; + u_int32_t sa_mtimetype; + nfstime3 sa_mtime; +}; + +struct nfs_statfs { + union { + struct { + u_int32_t nfsv2sf_tsize; + u_int32_t nfsv2sf_bsize; + u_int32_t nfsv2sf_blocks; + u_int32_t nfsv2sf_bfree; + u_int32_t nfsv2sf_bavail; + } sf_nfsv2; + struct { + nfsuint64 nfsv3sf_tbytes; + nfsuint64 nfsv3sf_fbytes; + nfsuint64 nfsv3sf_abytes; + nfsuint64 nfsv3sf_tfiles; + nfsuint64 nfsv3sf_ffiles; + nfsuint64 nfsv3sf_afiles; + u_int32_t nfsv3sf_invarsec; + } sf_nfsv3; + } sf_un; +}; + +#define sf_tsize sf_un.sf_nfsv2.nfsv2sf_tsize +#define sf_bsize sf_un.sf_nfsv2.nfsv2sf_bsize +#define sf_blocks sf_un.sf_nfsv2.nfsv2sf_blocks +#define sf_bfree sf_un.sf_nfsv2.nfsv2sf_bfree +#define sf_bavail sf_un.sf_nfsv2.nfsv2sf_bavail +#define sf_tbytes sf_un.sf_nfsv3.nfsv3sf_tbytes +#define sf_fbytes sf_un.sf_nfsv3.nfsv3sf_fbytes +#define sf_abytes sf_un.sf_nfsv3.nfsv3sf_abytes +#define sf_tfiles sf_un.sf_nfsv3.nfsv3sf_tfiles +#define sf_ffiles sf_un.sf_nfsv3.nfsv3sf_ffiles +#define sf_afiles sf_un.sf_nfsv3.nfsv3sf_afiles +#define sf_invarsec sf_un.sf_nfsv3.nfsv3sf_invarsec + +struct nfsv3_fsinfo { + u_int32_t fs_rtmax; + u_int32_t fs_rtpref; + u_int32_t fs_rtmult; + u_int32_t fs_wtmax; + u_int32_t fs_wtpref; + u_int32_t fs_wtmult; + u_int32_t fs_dtpref; + nfsuint64 fs_maxfilesize; + nfstime3 fs_timedelta; + u_int32_t fs_properties; +}; + +struct nfsv3_pathconf { + u_int32_t pc_linkmax; + u_int32_t pc_namemax; + u_int32_t pc_notrunc; + u_int32_t pc_chownrestricted; + u_int32_t pc_caseinsensitive; + u_int32_t pc_casepreserving; +}; + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/nfs/nfsrvcache.h b/lib/libc/include/generic-openbsd/nfs/nfsrvcache.h new file mode 100644 index 000000000000..93ee1646289f --- /dev/null +++ b/lib/libc/include/generic-openbsd/nfs/nfsrvcache.h @@ -0,0 +1,81 @@ +/* $OpenBSD: nfsrvcache.h,v 1.8 2013/11/26 20:41:27 beck Exp $ */ +/* $NetBSD: nfsrvcache.h,v 1.10 1996/02/18 11:54:08 fvdl Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)nfsrvcache.h 8.3 (Berkeley) 3/30/95 + */ + +#ifndef _NFS_NFSRVCACHE_H_ +#define _NFS_NFSRVCACHE_H_ + +#define NFSRVCACHESIZ 2048 + +struct nfsrvcache { + TAILQ_ENTRY(nfsrvcache) rc_lru; /* LRU chain */ + LIST_ENTRY(nfsrvcache) rc_hash; /* Hash chain */ + u_int32_t rc_xid; /* rpc id number */ + union { + struct mbuf *ru_repmb; /* Reply mbuf list OR */ + int ru_repstat; /* Reply status */ + } rc_un; + union nethostaddr rc_haddr; /* Host address */ + u_int16_t rc_proc; /* rpc proc number */ + u_char rc_state; /* Current state of request */ + u_char rc_flag; /* Flag bits */ +}; + +#define rc_reply rc_un.ru_repmb +#define rc_status rc_un.ru_repstat +#define rc_inetaddr rc_haddr.had_inetaddr +#define rc_nam rc_haddr.had_nam + +/* Cache entry states */ +#define RC_UNUSED 0 +#define RC_INPROG 1 +#define RC_DONE 2 + +/* Return values */ +#define RC_DROPIT 0 +#define RC_REPLY 1 +#define RC_DOIT 2 +#define RC_CHECKIT 3 + +/* Flag bits */ +#define RC_LOCKED 0x01 +#define RC_WANTED 0x02 +#define RC_REPSTATUS 0x04 +#define RC_REPMBUF 0x08 +#define RC_INETADDR 0x20 +#define RC_NAM 0x40 + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/nfs/rpcv2.h b/lib/libc/include/generic-openbsd/nfs/rpcv2.h new file mode 100644 index 000000000000..a88819ee4726 --- /dev/null +++ b/lib/libc/include/generic-openbsd/nfs/rpcv2.h @@ -0,0 +1,101 @@ +/* $OpenBSD: rpcv2.h,v 1.8 2008/07/04 16:49:28 blambert Exp $ */ +/* $NetBSD: rpcv2.h,v 1.8 1996/02/18 11:54:11 fvdl Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)rpcv2.h 8.2 (Berkeley) 3/30/95 + */ + + +#ifndef _NFS_RPCV2_H_ +#define _NFS_RPCV2_H_ + +/* + * Definitions for Sun RPC Version 2, from + * "RPC: Remote Procedure Call Protocol Specification" RFC1057 + */ + +/* Version # */ +#define RPC_VER2 2 + +/* Authentication */ +#define RPCAUTH_NULL 0 +#define RPCAUTH_UNIX 1 +#define RPCAUTH_SHORT 2 +#define RPCAUTH_KERB4 4 +#define RPCAUTH_MAXSIZ 400 +#define RPCVERF_MAXSIZ 12 /* For Kerb, can actually be 400 */ +#define RPCAUTH_UNIXGIDS 16 + +/* + * Constants associated with authentication flavours. + */ +#define RPCAKN_FULLNAME 0 +#define RPCAKN_NICKNAME 1 + +/* Rpc Constants */ +#define RPC_CALL 0 +#define RPC_REPLY 1 +#define RPC_MSGACCEPTED 0 +#define RPC_MSGDENIED 1 +#define RPC_PROGUNAVAIL 1 +#define RPC_PROGMISMATCH 2 +#define RPC_PROCUNAVAIL 3 +#define RPC_GARBAGE 4 /* I like this one */ +#define RPC_MISMATCH 0 +#define RPC_AUTHERR 1 + +/* Authentication failures */ +#define AUTH_BADCRED 1 +#define AUTH_REJECTCRED 2 +#define AUTH_BADVERF 3 +#define AUTH_REJECTVERF 4 +#define AUTH_TOOWEAK 5 /* Give em wheaties */ + +/* Sizes of rpc header parts */ +#define RPC_SIZ 24 +#define RPC_REPLYSIZ 28 + +/* RPC Prog definitions */ +#define RPCPROG_MNT 100005 +#define RPCMNT_VER1 1 +#define RPCMNT_VER3 3 +#define RPCMNT_MOUNT 1 +#define RPCMNT_DUMP 2 +#define RPCMNT_UMOUNT 3 +#define RPCMNT_UMNTALL 4 +#define RPCMNT_EXPORT 5 +#define RPCMNT_NAMELEN 255 +#define RPCMNT_PATHLEN 1024 +#define RPCPROG_NFS 100003 + +#endif /* _NFS_RPCV2_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/nfs/xdr_subs.h b/lib/libc/include/generic-openbsd/nfs/xdr_subs.h new file mode 100644 index 000000000000..4cafdafbac3e --- /dev/null +++ b/lib/libc/include/generic-openbsd/nfs/xdr_subs.h @@ -0,0 +1,86 @@ +/* $OpenBSD: xdr_subs.h,v 1.10 2015/04/17 04:43:21 guenther Exp $ */ +/* $NetBSD: xdr_subs.h,v 1.11 1996/02/18 11:54:12 fvdl Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)xdr_subs.h 8.3 (Berkeley) 3/30/95 + */ + + +#ifndef _NFS_XDR_SUBS_H_ +#define _NFS_XDR_SUBS_H_ + +/* + * Macros used for conversion to/from xdr representation by nfs... + * These use the MACHINE DEPENDENT routines ntohl, htonl + * As defined by "XDR: External Data Representation Standard" RFC1014 + * + * To simplify the implementation, we use ntohl/htonl even on big-endian + * machines, and count on them being `#define'd away. Some of these + * might be slightly more efficient as quad_t copies on a big-endian, + * but we cannot count on their alignment anyway. + */ + +#define fxdr_unsigned(t, v) ((t)ntohl((int32_t)(v))) +#define txdr_unsigned(v) (htonl((int32_t)(v))) + +#define fxdr_nfsv2time(f, t) do { \ + (t)->tv_sec = ntohl(((struct nfsv2_time *)(f))->nfsv2_sec); \ + if (((struct nfsv2_time *)(f))->nfsv2_usec != 0xffffffff) \ + (t)->tv_nsec = 1000 * ntohl(((struct nfsv2_time *)(f))->nfsv2_usec); \ + else \ + (t)->tv_nsec = 0; \ +} while (0) + +struct nfsv2_time; +void txdr_nfsv2time(const struct timespec *_from, struct nfsv2_time *_to); + +#define fxdr_nfsv3time(f, t) do { \ + (t)->tv_sec = ntohl(((struct nfsv3_time *)(f))->nfsv3_sec); \ + (t)->tv_nsec = ntohl(((struct nfsv3_time *)(f))->nfsv3_nsec); \ +} while (0) +#define txdr_nfsv3time(f, t) do { \ + ((struct nfsv3_time *)(t))->nfsv3_sec = htonl((f)->tv_sec); \ + ((struct nfsv3_time *)(t))->nfsv3_nsec = htonl((f)->tv_nsec); \ +} while (0) + +#define fxdr_hyper(f) \ + ((((u_quad_t)ntohl(((u_int32_t *)(f))[0])) << 32) | \ + (u_quad_t)(ntohl(((u_int32_t *)(f))[1]))) + + +#define txdr_hyper(f, t) do { \ + ((u_int32_t *)(t))[0] = htonl((u_int32_t)((f) >> 32)); \ + ((u_int32_t *)(t))[1] = htonl((u_int32_t)((f) & 0xffffffff)); \ +} while (0) + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/nl_types.h b/lib/libc/include/generic-openbsd/nl_types.h new file mode 100644 index 000000000000..b27328eff4e2 --- /dev/null +++ b/lib/libc/include/generic-openbsd/nl_types.h @@ -0,0 +1,91 @@ +/* $OpenBSD: nl_types.h,v 1.8 2008/06/26 05:42:04 ray Exp $ */ +/* $NetBSD: nl_types.h,v 1.6 1996/05/13 23:11:15 jtc Exp $ */ + +/*- + * Copyright (c) 1996 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by J.T. Conklin. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _NL_TYPES_H_ +#define _NL_TYPES_H_ +#include + +#ifdef _NLS_PRIVATE +/* + * MESSAGE CATALOG FILE FORMAT. + * + * The NetBSD message catalog format is similar to the format used by + * Svr4 systems. The differences are: + * * fixed byte order (big endian) + * * fixed data field sizes + * + * A message catalog contains four data types: a catalog header, one + * or more set headers, one or more message headers, and one or more + * text strings. + */ + +#define _NLS_MAGIC 0xff88ff89 + +struct _nls_cat_hdr { + int32_t __magic; + int32_t __nsets; + int32_t __mem; + int32_t __msg_hdr_offset; + int32_t __msg_txt_offset; +} ; + +struct _nls_set_hdr { + int32_t __setno; /* set number: 0 < x <= NL_SETMAX */ + int32_t __nmsgs; /* number of messages in the set */ + int32_t __index; /* index of first msg_hdr in msg_hdr table */ +} ; + +struct _nls_msg_hdr { + int32_t __msgno; /* msg number: 0 < x <= NL_MSGMAX */ + int32_t __msglen; + int32_t __offset; +} ; + +#endif + +#define NL_SETD 1 +#define NL_CAT_LOCALE 1 + +typedef struct _nl_catd { + void *__data; + int __size; +} *nl_catd; + +typedef long nl_item; + +__BEGIN_DECLS +extern nl_catd catopen(const char *, int); +extern char *catgets(nl_catd, int, int, const char *); +extern int catclose(nl_catd); +__END_DECLS + +#endif /* _NL_TYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/nlist.h b/lib/libc/include/generic-openbsd/nlist.h new file mode 100644 index 000000000000..ed4347216977 --- /dev/null +++ b/lib/libc/include/generic-openbsd/nlist.h @@ -0,0 +1,87 @@ +/* $OpenBSD: nlist.h,v 1.4 2003/06/02 19:34:12 millert Exp $ */ +/* $NetBSD: nlist.h,v 1.5 1994/10/26 00:56:11 cgd Exp $ */ + +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)nlist.h 8.2 (Berkeley) 1/21/94 + */ + +#ifndef _NLIST_H_ +#define _NLIST_H_ + +/* + * Symbol table entry format. The #ifdef's are so that programs including + * nlist.h can initialize nlist structures statically. + */ +struct nlist { +#ifdef _AOUT_INCLUDE_ + union { + char *n_name; /* symbol name (in memory) */ + long n_strx; /* file string table offset (on disk) */ + } n_un; +#else + char *n_name; /* symbol name (in memory) */ +#endif + +#define N_UNDF 0x00 /* undefined */ +#define N_ABS 0x02 /* absolute address */ +#define N_TEXT 0x04 /* text segment */ +#define N_DATA 0x06 /* data segment */ +#define N_BSS 0x08 /* bss segment */ +#define N_INDR 0x0a /* alias definition */ +#define N_SIZE 0x0c /* pseudo type, defines a symbol's size */ +#define N_COMM 0x12 /* common reference */ +#define N_FN 0x1e /* file name (N_EXT on) */ +#define N_WARN 0x1e /* warning message (N_EXT off) */ + +#define N_EXT 0x01 /* external (global) bit, OR'ed in */ +#define N_TYPE 0x1e /* mask for all the type bits */ + unsigned char n_type; /* type defines */ + + char n_other; /* spare */ +#define n_hash n_desc /* used internally by ld(1); XXX */ + short n_desc; /* used by stab entries */ + unsigned long n_value; /* address/value of the symbol */ +}; + +#define N_FORMAT "%08x" /* namelist value format; XXX */ +#define N_STAB 0x0e0 /* mask for debugger symbols -- stab(5) */ + +#include + +__BEGIN_DECLS +int nlist(const char *, struct nlist *); +__END_DECLS + +#endif /* !_NLIST_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ntfs/ntfs.h b/lib/libc/include/generic-openbsd/ntfs/ntfs.h new file mode 100644 index 000000000000..142f0b2ac130 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ntfs/ntfs.h @@ -0,0 +1,315 @@ +/* $OpenBSD: ntfs.h,v 1.19 2022/01/11 03:13:59 jsg Exp $ */ +/* $NetBSD: ntfs.h,v 1.5 2003/04/24 07:50:19 christos Exp $ */ + +/*- + * Copyright (c) 1998, 1999 Semen Ustimenko + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Id: ntfs.h,v 1.5 1999/05/12 09:42:51 semenu Exp + */ + +/*#define NTFS_DEBUG 1*/ +typedef u_int64_t cn_t; +typedef u_int16_t wchar; + +#define BBSIZE 1024 +#define BBOFF ((off_t)(0)) +#define BBLOCK 0 +#define NTFS_MFTINO 0 +#define NTFS_VOLUMEINO 3 +#define NTFS_ATTRDEFINO 4 +#define NTFS_ROOTINO 5 +#define NTFS_BITMAPINO 6 +#define NTFS_BOOTINO 7 +#define NTFS_BADCLUSINO 8 +#define NTFS_UPCASEINO 10 +#define NTFS_MAXFILENAME 255 + +/* + * UFS directories use 32bit inode numbers internally, regardless + * of what the system on top of it uses. + */ +typedef u_int32_t ntfsino_t; + +struct fixuphdr { + u_int32_t fh_magic; + u_int16_t fh_foff; + u_int16_t fh_fnum; +} __packed; + +#define NTFS_AF_INRUN 0x00000001 +struct attrhdr { + u_int32_t a_type; + u_int32_t reclen; + u_int8_t a_flag; + u_int8_t a_namelen; + u_int8_t a_nameoff; + u_int8_t reserved1; + u_int8_t a_compression; + u_int8_t reserved2; + u_int16_t a_index; +} __packed; +#define NTFS_A_STD 0x10 +#define NTFS_A_ATTRLIST 0x20 +#define NTFS_A_NAME 0x30 +#define NTFS_A_VOLUMENAME 0x60 +#define NTFS_A_DATA 0x80 +#define NTFS_A_INDXROOT 0x90 +#define NTFS_A_INDX 0xA0 +#define NTFS_A_INDXBITMAP 0xB0 + +#define NTFS_MAXATTRNAME 255 +struct attr { + struct attrhdr a_hdr; + union { + struct { + u_int16_t a_datalen; + u_int16_t reserved1; + u_int16_t a_dataoff; + u_int16_t a_indexed; + } __packed a_S_r; + struct { + cn_t a_vcnstart; + cn_t a_vcnend; + u_int16_t a_dataoff; + u_int16_t a_compressalg; + u_int32_t reserved1; + u_int64_t a_allocated; + u_int64_t a_datalen; + u_int64_t a_initialized; + } __packed a_S_nr; + } a_S; +} __packed; +#define a_r a_S.a_S_r +#define a_nr a_S.a_S_nr + +typedef struct { + u_int64_t t_create; + u_int64_t t_write; + u_int64_t t_mftwrite; + u_int64_t t_access; +} __packed ntfs_times_t; + +#define NTFS_FFLAG_RDONLY 0x01LL +#define NTFS_FFLAG_HIDDEN 0x02LL +#define NTFS_FFLAG_SYSTEM 0x04LL +#define NTFS_FFLAG_ARCHIVE 0x20LL +#define NTFS_FFLAG_COMPRESSED 0x0800LL +#define NTFS_FFLAG_DIR 0x10000000LL + +struct attr_name { + u_int32_t n_pnumber; /* Parent ntnode */ + u_int32_t reserved; + ntfs_times_t n_times; + u_int64_t n_size; + u_int64_t n_attrsz; + u_int64_t n_flag; + u_int8_t n_namelen; + u_int8_t n_nametype; + u_int16_t n_name[1]; +} __packed; + +#define NTFS_IRFLAG_INDXALLOC 0x00000001 +struct attr_indexroot { + u_int32_t ir_unkn1; /* always 0x30 */ + u_int32_t ir_unkn2; /* always 0x1 */ + u_int32_t ir_size;/* ??? */ + u_int32_t ir_unkn3; /* number of cluster */ + u_int32_t ir_unkn4; /* always 0x10 */ + u_int32_t ir_datalen; /* sizeof something */ + u_int32_t ir_allocated; /* same as above */ + u_int16_t ir_flag;/* ?? always 1 */ + u_int16_t ir_unkn7; +} __packed; + +struct attr_attrlist { + u_int32_t al_type; /* Attribute type */ + u_int16_t reclen; /* length of this entry */ + u_int8_t al_namelen; /* Attribute name len */ + u_int8_t al_nameoff; /* Name offset from entry start */ + u_int64_t al_vcnstart; /* VCN number */ + u_int32_t al_inumber; /* Parent ntnode */ + u_int32_t reserved; + u_int16_t al_index; /* Attribute index in MFT record */ + u_int16_t al_name[1]; /* Name */ +} __packed; + +#define NTFS_INDXMAGIC (u_int32_t)(0x58444E49) +struct attr_indexalloc { + struct fixuphdr ia_fixup; + u_int64_t unknown1; + cn_t ia_bufcn; + u_int16_t ia_hdrsize; + u_int16_t unknown2; + u_int32_t ia_inuse; + u_int32_t ia_allocated; +} __packed; + +#define NTFS_IEFLAG_SUBNODE 0x00000001 +#define NTFS_IEFLAG_LAST 0x00000002 + +struct attr_indexentry { + u_int32_t ie_number; + u_int32_t unknown1; + u_int16_t reclen; + u_int16_t ie_size; + u_int32_t ie_flag;/* 1 - has subnodes, 2 - last */ + u_int32_t ie_fpnumber; + u_int32_t unknown2; + ntfs_times_t ie_ftimes; + u_int64_t ie_fallocated; + u_int64_t ie_fsize; + u_int64_t ie_fflag; + u_int8_t ie_fnamelen; + u_int8_t ie_fnametype; + wchar ie_fname[NTFS_MAXFILENAME]; + /* cn_t ie_bufcn; buffer with subnodes */ +} __packed; + +#define NTFS_FILEMAGIC (u_int32_t)(0x454C4946) +#define NTFS_FRFLAG_DIR 0x0002 +struct filerec { + struct fixuphdr fr_fixup; + u_int8_t reserved[8]; + u_int16_t fr_seqnum; /* Sequence number */ + u_int16_t fr_nlink; + u_int16_t fr_attroff; /* offset to attributes */ + u_int16_t fr_flags; /* 1-nonresident attr, 2-directory */ + u_int32_t fr_size;/* hdr + attributes */ + u_int32_t fr_allocated; /* allocated length of record */ + u_int64_t fr_mainrec; /* main record */ + u_int16_t fr_attrnum; /* maximum attr number + 1 ??? */ +} __packed; + +#define NTFS_ATTRNAME_MAXLEN 0x40 +#define NTFS_ADFLAG_NONRES 0x0080 /* Attrib can be non resident */ +#define NTFS_ADFLAG_INDEX 0x0002 /* Attrib can be indexed */ +struct attrdef { + wchar ad_name[NTFS_ATTRNAME_MAXLEN]; + u_int32_t ad_type; + u_int32_t reserved1[2]; + u_int32_t ad_flag; + u_int64_t ad_minlen; + u_int64_t ad_maxlen; /* -1 for nonlimited */ +} __packed; + +struct ntvattrdef { + char ad_name[0x40]; + int ad_namelen; + u_int32_t ad_type; +} __packed; + +#define NTFS_BBID "NTFS " +#define NTFS_BBIDLEN 8 +struct bootfile { + u_int8_t reserved1[3]; /* asm jmp near ... */ + u_int8_t bf_sysid[8]; /* 'NTFS ' */ + u_int16_t bf_bps; /* bytes per sector */ + u_int8_t bf_spc; /* sectors per cluster */ + u_int8_t reserved2[7]; /* unused (zeroed) */ + u_int8_t bf_media; /* media desc. (0xF8) */ + u_int8_t reserved3[2]; + u_int16_t bf_spt; /* sectors per track */ + u_int16_t bf_heads; /* number of heads */ + u_int8_t reserver4[12]; + u_int64_t bf_spv; /* sectors per volume */ + cn_t bf_mftcn; /* $MFT cluster number */ + cn_t bf_mftmirrcn; /* $MFTMirr cn */ + u_int8_t bf_mftrecsz; /* MFT record size (clust) */ + /* 0xF6 indicates 1/4 */ + u_int32_t bf_ibsz; /* index buffer size */ + u_int32_t bf_volsn; /* volume ser. num. */ +} __packed; + +typedef wchar (ntfs_wget_func_t)(const char **); +typedef int (ntfs_wput_func_t)(char *, size_t, wchar); +typedef int (ntfs_wcmp_func_t)(wchar, wchar); + +/* + * Maximum number of ntnodes to keep in memory. We do not want to leave + * large data structures hanging off vnodes indefinitely and the data + * needed to reload the ntnode should already be in the buffer cache. + */ +#define LOADED_NTNODE_HI 16 +struct ntnode; +TAILQ_HEAD(ntnodeq, ntnode); + +#define NTFS_SYSNODESNUM 0x0B +struct ntfsmount { + struct mount *ntm_mountp; /* filesystem vfs structure */ + struct bootfile ntm_bootfile; + dev_t ntm_dev; /* device mounted */ + struct vnode *ntm_devvp; /* block device mounted vnode */ + struct vnode *ntm_sysvn[NTFS_SYSNODESNUM]; + u_int32_t ntm_bpmftrec; + uid_t ntm_uid; + gid_t ntm_gid; + mode_t ntm_mode; + u_long ntm_flag; + cn_t ntm_cfree; + struct ntvattrdef *ntm_ad; + int ntm_adnum; + struct netexport ntm_export; /* export information */ + ntfs_wget_func_t *ntm_wget; /* decode string to Unicode string */ + ntfs_wput_func_t *ntm_wput; /* encode Unicode string to string */ + ntfs_wcmp_func_t *ntm_wcmp; /* compare to wide characters */ + int ntm_ntnodes; /* Number of loaded ntnodes. */ + struct ntnodeq ntm_ntnodeq; /* Queue of ntnodes (LRU). */ +}; + +#define ntm_mftcn ntm_bootfile.bf_mftcn +#define ntm_mftmirrcn ntm_bootfile.bf_mftmirrcn +#define ntm_mftrecsz ntm_bootfile.bf_mftrecsz +#define ntm_spc ntm_bootfile.bf_spc +#define ntm_bps ntm_bootfile.bf_bps + +#define NTFS_NEXTREC(s, type) ((type)(((caddr_t) s) + (s)->reclen)) + +/* Convert mount ptr to ntfsmount ptr. */ +#define VFSTONTFS(mp) ((struct ntfsmount *)((mp)->mnt_data)) +#define VTONT(v) FTONT(VTOF(v)) +#define VTOF(v) ((struct fnode *)((v)->v_data)) +#define FTOV(f) ((f)->f_vp) +#define FTONT(f) ((f)->f_ip) +#define ntfs_cntobn(cn) (daddr_t)((cn) * (ntmp->ntm_spc)) +#define ntfs_cntob(cn) (off_t)((cn) * (ntmp)->ntm_spc * (ntmp)->ntm_bps) +#define ntfs_btocn(off) (cn_t)((off) / ((ntmp)->ntm_spc * (ntmp)->ntm_bps)) +#define ntfs_btocl(off) (cn_t)((off + ntfs_cntob(1) - 1) / ((ntmp)->ntm_spc * (ntmp)->ntm_bps)) +#define ntfs_btocnoff(off) (off_t)((off) % ((ntmp)->ntm_spc * (ntmp)->ntm_bps)) +#define ntfs_bntob(bn) (int32_t)((bn) * (ntmp)->ntm_bps) + +#ifdef _KERNEL +#if defined(NTFS_DEBUG) +extern int ntfs_debug; +#define DNPRINTF(n, x...) do { if(ntfs_debug >= (n)) printf(x); } while(0) +#define DPRINTF(x...) DNPRINTF(1, x) +#define DDPRINTF(x...) DNPRINTF(2, x) +#else /* NTFS_DEBUG */ +#define DNPRINTF(n, x...) +#define DPRINTF(x...) +#define DDPRINTF(x...) +#endif + +extern const struct vops ntfs_vops; +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ntfs/ntfs_compr.h b/lib/libc/include/generic-openbsd/ntfs/ntfs_compr.h new file mode 100644 index 000000000000..fef525dc3598 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ntfs/ntfs_compr.h @@ -0,0 +1,36 @@ +/* $OpenBSD: ntfs_compr.h,v 1.2 2003/05/20 03:23:11 mickey Exp $ */ +/* $NetBSD: ntfs_compr.h,v 1.1 2002/12/23 17:38:32 jdolecek Exp $ */ + +/*- + * Copyright (c) 1998, 1999 Semen Ustimenko + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Id: ntfs_compr.h,v 1.4 1999/05/12 09:42:55 semenu Exp + */ + +#define NTFS_COMPBLOCK_SIZE 0x1000 +#define NTFS_COMPUNIT_CL 16 + +int ntfs_uncompblock(u_int8_t *, u_int8_t *); +int ntfs_uncompunit(struct ntfsmount *, u_int8_t *, u_int8_t *); \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ntfs/ntfs_ihash.h b/lib/libc/include/generic-openbsd/ntfs/ntfs_ihash.h new file mode 100644 index 000000000000..680c97fbac9d --- /dev/null +++ b/lib/libc/include/generic-openbsd/ntfs/ntfs_ihash.h @@ -0,0 +1,35 @@ +/* $OpenBSD: ntfs_ihash.h,v 1.7 2025/01/13 13:58:41 claudio Exp $ */ +/* $NetBSD: ntfs_ihash.h,v 1.1 2002/12/23 17:38:32 jdolecek Exp $ */ + +/*- + * Copyright (c) 1998, 1999 Semen Ustimenko + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Id: ntfs_ihash.h,v 1.3 1999/05/12 09:42:59 semenu Exp + */ + +void ntfs_nthashinit(void); +struct ntnode *ntfs_nthashlookup(dev_t, ntfsino_t); +int ntfs_nthashins(struct ntnode *); +void ntfs_nthashrem(struct ntnode *); \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ntfs/ntfs_inode.h b/lib/libc/include/generic-openbsd/ntfs/ntfs_inode.h new file mode 100644 index 000000000000..14c7d45ef6fc --- /dev/null +++ b/lib/libc/include/generic-openbsd/ntfs/ntfs_inode.h @@ -0,0 +1,98 @@ +/* $OpenBSD: ntfs_inode.h,v 1.8 2021/03/11 13:31:35 jsg Exp $ */ +/* $NetBSD: ntfs_inode.h,v 1.1 2002/12/23 17:38:33 jdolecek Exp $ */ + +/*- + * Copyright (c) 1998, 1999 Semen Ustimenko + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Id: ntfs_inode.h,v 1.4 1999/05/12 09:43:00 semenu Exp + */ + +#define IN_HASHED 0x0800 /* Inode is on hash list */ +#define IN_LOADED 0x8000 /* ntvattrs loaded */ +#define IN_PRELOADED 0x4000 /* loaded from directory entry */ + +struct ntnode { + struct vnode *i_devvp; /* vnode of blk dev we live on */ + dev_t i_dev; /* Device associated with the inode. */ + + LIST_ENTRY(ntnode) i_hash; + TAILQ_ENTRY(ntnode) i_loaded; + + struct ntnode *i_next; + struct ntnode **i_prev; + + struct ntfsmount *i_mp; + ntfsino_t i_number; + u_int32_t i_flag; + + /* locking */ + struct rwlock i_lock; + int i_usecount; + + LIST_HEAD(,fnode) i_fnlist; + LIST_HEAD(,ntvattr) i_valist; + + long i_nlink; /* MFR */ + u_int64_t i_mainrec; /* MFR */ + u_int32_t i_frflag; /* MFR */ +}; + +#define FN_PRELOADED 0x0001 +#define FN_VALID 0x0002 +#define FN_AATTRNAME 0x0004 /* space allocated for f_attrname */ +struct fnode { + LIST_ENTRY(fnode) f_fnlist; + struct vnode *f_vp; /* Associated vnode */ + struct ntnode *f_ip; /* Associated ntnode */ + u_long f_flag; + + ntfs_times_t f_times; /* $NAME/dirinfo */ + u_int32_t f_pnumber; /* $NAME/dirinfo */ + u_int32_t f_fflag; /* $NAME/dirinfo */ + u_int64_t f_size; /* defattr/dirinfo: */ + u_int64_t f_allocated; /* defattr/dirinfo */ + + u_int32_t f_attrtype; + char *f_attrname; + + /* for ntreaddir */ + u_int32_t f_lastdattr; + u_int32_t f_lastdblnum; + u_int32_t f_lastdoff; + u_int32_t f_lastdnum; + caddr_t f_dirblbuf; + u_int32_t f_dirblsz; +}; + +/* This overlays the fid structure (see ) */ +struct ntfid { + u_int16_t ntfid_len; /* Length of structure. */ + u_int16_t ntfid_pad; /* Force 32-bit alignment. */ + ntfsino_t ntfid_ino; /* File number (ino). */ + u_int8_t ntfid_attr; /* Attribute identifier */ +#ifdef notyet + int32_t ntfid_gen; /* Generation number. */ +#endif +}; \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ntfs/ntfs_subr.h b/lib/libc/include/generic-openbsd/ntfs/ntfs_subr.h new file mode 100644 index 000000000000..40a713d8da1e --- /dev/null +++ b/lib/libc/include/generic-openbsd/ntfs/ntfs_subr.h @@ -0,0 +1,104 @@ +/* $OpenBSD: ntfs_subr.h,v 1.12 2024/05/13 01:15:53 jsg Exp $ */ +/* $NetBSD: ntfs_subr.h,v 1.1 2002/12/23 17:38:33 jdolecek Exp $ */ + +/*- + * Copyright (c) 1998, 1999 Semen Ustimenko + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Id: ntfs_subr.h,v 1.4 1999/05/12 09:43:02 semenu Exp + */ + +#define VA_LOADED 0x0001 +#define VA_PRELOADED 0x0002 + +struct ntvattr { + LIST_ENTRY(ntvattr) va_list; + + u_int32_t va_vflag; + struct vnode *va_vp; + struct ntnode *va_ip; + + u_int32_t va_flag; + u_int32_t va_type; + u_int8_t va_namelen; + char va_name[NTFS_MAXATTRNAME]; + + u_int32_t va_compression; + u_int32_t va_compressalg; + u_int64_t va_datalen; + u_int64_t va_allocated; + cn_t va_vcnstart; + cn_t va_vcnend; + u_int16_t va_index; + union { + struct { + cn_t * cn; + cn_t * cl; + u_long cnt; + } vrun; + caddr_t datap; + struct attr_name *name; + struct attr_indexroot *iroot; + struct attr_indexalloc *ialloc; + } va_d; +}; +#define va_vruncn va_d.vrun.cn +#define va_vruncl va_d.vrun.cl +#define va_vruncnt va_d.vrun.cnt +#define va_datap va_d.datap +#define va_a_name va_d.name +#define va_a_iroot va_d.iroot +#define va_a_ialloc va_d.ialloc + +int ntfs_procfixups( struct ntfsmount *, u_int32_t, caddr_t, size_t ); +int ntfs_parserun( cn_t *, cn_t *, u_int8_t *, u_long, u_long *); +int ntfs_runtocn( cn_t *, struct ntfsmount *, u_int8_t *, u_long, cn_t); +int ntfs_readntvattr_plain( struct ntfsmount *, struct ntnode *, struct ntvattr *, off_t, size_t, void *,size_t *, struct uio *); +int ntfs_readattr_plain( struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *,size_t *, struct uio *); +int ntfs_readattr( struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *, struct uio *); +int ntfs_filesize( struct ntfsmount *, struct fnode *, u_int64_t *, u_int64_t *); +struct timespec ntfs_nttimetounix( u_int64_t ); +int ntfs_runtovrun( cn_t **, cn_t **, u_long *, u_int8_t *); +int ntfs_attrtontvattr( struct ntfsmount *, struct ntvattr **, struct attr * ); +void ntfs_freentvattr( struct ntvattr * ); +int ntfs_isnamepermitted(struct ntfsmount *, struct attr_indexentry * ); +int ntfs_ntvattrrele(struct ntvattr * ); +int ntfs_ntvattrget(struct ntfsmount *, struct ntnode *, u_int32_t, const char *, cn_t , struct ntvattr **); +void ntfs_ntref(struct ntnode *); +void ntfs_ntrele(struct ntnode *); +int ntfs_loadntnode( struct ntfsmount *, struct ntnode * ); +int ntfs_fget(struct ntfsmount *, struct ntnode *, int, char *, struct fnode **); +void ntfs_frele(struct fnode *); +int ntfs_ntreaddir(struct ntfsmount *, struct fnode *, u_int32_t, struct attr_indexentry **, struct proc *); +int ntfs_ntlookupfile(struct ntfsmount *, struct vnode *, struct componentname *, struct vnode **); +int ntfs_ntlookup(struct ntfsmount *, ntfsino_t, struct ntnode **); +int ntfs_ntget(struct ntnode *); +void ntfs_ntput(struct ntnode *); +int ntfs_toupper_use(struct mount *, struct ntfsmount *, struct proc *); +void ntfs_toupper_unuse(struct proc *); + +/* ntfs_conv.c stuff */ +ntfs_wget_func_t ntfs_utf8_wget; +ntfs_wput_func_t ntfs_utf8_wput; +ntfs_wcmp_func_t ntfs_utf8_wcmp; \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ntfs/ntfs_vfsops.h b/lib/libc/include/generic-openbsd/ntfs/ntfs_vfsops.h new file mode 100644 index 000000000000..aa0fa158896f --- /dev/null +++ b/lib/libc/include/generic-openbsd/ntfs/ntfs_vfsops.h @@ -0,0 +1,40 @@ +/* $OpenBSD: ntfs_vfsops.h,v 1.4 2020/02/27 09:10:31 mpi Exp $ */ +/* $NetBSD: ntfs_vfsops.h,v 1.1 2002/12/23 17:38:34 jdolecek Exp $ */ + +/*- + * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Id: ntfs_vfsops.h,v 1.3 1999/05/12 09:43:06 semenu Exp + */ +#define VG_DONTLOADIN 0x0001 /* Tells ntfs_vgetex to do not call */ + /* ntfs_loadntnode() on ntnode, even if */ + /* ntnode not loaded */ +#define VG_DONTVALIDFN 0x0002 /* Tells ntfs_vgetex to do not validate */ + /* fnode */ +#define VG_EXT 0x0004 /* This is not main record */ + +int ntfs_vgetex(struct mount *, ntfsino_t, u_int32_t, char *, u_long, u_long, + struct vnode **); +int ntfs_calccfree(struct ntfsmount *, cn_t *); \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ntfs/ntfsmount.h b/lib/libc/include/generic-openbsd/ntfs/ntfsmount.h new file mode 100644 index 000000000000..1f7043341157 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ntfs/ntfsmount.h @@ -0,0 +1,33 @@ +/* $OpenBSD: ntfsmount.h,v 1.3 2006/05/29 20:40:58 miod Exp $ */ +/* $NetBSD: ntfsmount.h,v 1.1 2002/12/23 17:38:34 jdolecek Exp $ */ + +/*- + * Copyright (c) 1998, 1999 Semen Ustimenko + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Id: ntfsmount.h,v 1.4 1999/05/12 09:43:09 semenu Exp + */ + +#define NTFS_MFLAG_CASEINS 0x00000001 +#define NTFS_MFLAG_ALLNAMES 0x00000002 \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ohash.h b/lib/libc/include/generic-openbsd/ohash.h new file mode 100644 index 000000000000..fdbe7a07878c --- /dev/null +++ b/lib/libc/include/generic-openbsd/ohash.h @@ -0,0 +1,74 @@ +/* $OpenBSD: ohash.h,v 1.2 2014/06/02 18:52:03 deraadt Exp $ */ + +/* Copyright (c) 1999, 2004 Marc Espie + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef OHASH_H +#define OHASH_H + +/* Open hashing support. + * Open hashing was chosen because it is much lighter than other hash + * techniques, and more efficient in most cases. + */ + +/* user-visible data structure */ +struct ohash_info { + ptrdiff_t key_offset; + void *data; /* user data */ + void *(*calloc)(size_t, size_t, void *); + void (*free)(void *, void *); + void *(*alloc)(size_t, void *); +}; + +struct _ohash_record; + +/* private structure. It's there just so you can do a sizeof */ +struct ohash { + struct _ohash_record *t; + struct ohash_info info; + unsigned int size; + unsigned int total; + unsigned int deleted; +}; + +/* For this to be tweakable, we use small primitives, and leave part of the + * logic to the client application. e.g., hashing is left to the client + * application. We also provide a simple table entry lookup that yields + * a hashing table index (opaque) to be used in find/insert/remove. + * The keys are stored at a known position in the client data. + */ +__BEGIN_DECLS +void ohash_init(struct ohash *, unsigned, struct ohash_info *); +void ohash_delete(struct ohash *); + +unsigned int ohash_lookup_interval(struct ohash *, const char *, + const char *, uint32_t); +unsigned int ohash_lookup_memory(struct ohash *, const char *, + size_t, uint32_t) + __attribute__ ((__bounded__(__string__,2,3))); +void *ohash_find(struct ohash *, unsigned int); +void *ohash_remove(struct ohash *, unsigned int); +void *ohash_insert(struct ohash *, unsigned int, void *); +void *ohash_first(struct ohash *, unsigned int *); +void *ohash_next(struct ohash *, unsigned int *); +unsigned int ohash_entries(struct ohash *); + +void *ohash_create_entry(struct ohash_info *, const char *, const char **); +uint32_t ohash_interval(const char *, const char **); + +unsigned int ohash_qlookupi(struct ohash *, const char *, const char **); +unsigned int ohash_qlookup(struct ohash *, const char *); +__END_DECLS +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/paths.h b/lib/libc/include/generic-openbsd/paths.h new file mode 100644 index 000000000000..93e207d2a792 --- /dev/null +++ b/lib/libc/include/generic-openbsd/paths.h @@ -0,0 +1,81 @@ +/* $OpenBSD: paths.h,v 1.26 2019/07/11 03:54:17 tedu Exp $ */ +/* $NetBSD: paths.h,v 1.7 1994/10/26 00:56:12 cgd Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)paths.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _PATHS_H_ +#define _PATHS_H_ + +/* Default search path. */ +#define _PATH_DEFPATH "/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin" +/* All standard utilities path. */ +#define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin" + +#define _PATH_BSHELL "/bin/sh" +#define _PATH_CONSOLE "/dev/console" +#define _PATH_CSHELL "/bin/csh" +#define _PATH_DEFTAPE "/dev/rst0" +#define _PATH_DEVDB "/var/run/dev.db" +#define _PATH_DEVNULL "/dev/null" +#define _PATH_FSIRAND "/sbin/fsirand" +#define _PATH_KLOG "/dev/klog" +#define _PATH_KMEM "/dev/kmem" +#define _PATH_KSHELL "/bin/ksh" +#define _PATH_KSYMS "/dev/ksyms" +#define _PATH_KVMDB "/var/db/kvm_bsd.db" +#define _PATH_LOCALE "/usr/share/locale" +#define _PATH_LOGCONF "/etc/syslog.conf" +#define _PATH_LOGPID "/var/run/syslog.pid" +#define _PATH_MAILDIR "/var/mail" +#define _PATH_MAN "/usr/share/man" +#define _PATH_MEM "/dev/mem" +#define _PATH_NOLOGIN "/etc/nologin" +#define _PATH_RSH "/usr/bin/ssh" +#define _PATH_SENDMAIL "/usr/sbin/sendmail" +#define _PATH_SHELLS "/etc/shells" +#define _PATH_TTY "/dev/tty" +#define _PATH_UNIX "/bsd" +#define _PATH_VI "/usr/bin/vi" + + +/* Provide trailing slash, since mostly used for building pathnames. */ +#define _PATH_BOOTDIR "/usr/mdec/" +#define _PATH_DEV "/dev/" +#define _PATH_DEVFD "/dev/fd/" +#define _PATH_TMP "/tmp/" +#define _PATH_UUCPLOCK "/var/spool/lock/" +#define _PATH_VARDB "/var/db/" +#define _PATH_VAREMPTY "/var/empty/" +#define _PATH_VARRUN "/var/run/" +#define _PATH_VARTMP "/var/tmp/" + +#endif /* !_PATHS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/poll.h b/lib/libc/include/generic-openbsd/poll.h new file mode 100644 index 000000000000..06092f6c0494 --- /dev/null +++ b/lib/libc/include/generic-openbsd/poll.h @@ -0,0 +1,9 @@ +/* $OpenBSD: poll.h,v 1.3 2003/10/29 16:41:13 deraadt Exp $ */ + +/* + * Written by Theo de Raadt, Public Domain + * + * Typical poll() implementations expect poll.h to be in /usr/include. + * However this is not a convenient place for the real definitions. + */ +#include \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/protocols/dumprestore.h b/lib/libc/include/generic-openbsd/protocols/dumprestore.h new file mode 100644 index 000000000000..bb85d08d6f51 --- /dev/null +++ b/lib/libc/include/generic-openbsd/protocols/dumprestore.h @@ -0,0 +1,159 @@ +/* $OpenBSD: dumprestore.h,v 1.11 2021/01/21 00:16:36 mortimer Exp $ */ +/* $NetBSD: dumprestore.h,v 1.14 2005/12/26 19:01:47 perry Exp $ */ + +/* + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)dumprestore.h 8.2 (Berkeley) 1/21/94 + */ + +#ifndef _PROTOCOLS_DUMPRESTORE_H_ +#define _PROTOCOLS_DUMPRESTORE_H_ + +/* + * TP_BSIZE is the size of file blocks on the dump tapes. + * Note that TP_BSIZE must be a multiple of DEV_BSIZE. + * + * NTREC is the number of TP_BSIZE blocks that are written + * in each tape record. HIGHDENSITYTREC is the number of + * TP_BSIZE blocks that are written in each tape record on + * 6250 BPI or higher density tapes. + * + * TP_NINDIR is the number of indirect pointers in a TS_INODE + * or TS_ADDR record. Note that it must be a power of two. + */ +#define TP_BSIZE 1024 +#define NTREC 10 +#define HIGHDENSITYTREC 32 +#define TP_NINDIR (TP_BSIZE/2) +#define LBLSIZE 16 +#define NAMELEN 64 + +#define OFS_MAGIC (int)60011 +#define NFS_MAGIC (int)60012 +#ifndef FS_UFS2_MAGIC +#define FS_UFS2_MAGIC (int)0x19540119 +#endif +#define CHECKSUM (int)84446 + +extern union u_spcl { + char dummy[TP_BSIZE]; + struct s_spcl { + int32_t c_type; /* record type (see below) */ + int32_t c_old_date; /* date of this dump */ + int32_t c_old_ddate; /* date of previous dump */ + int32_t c_volume; /* dump volume number */ + int32_t c_old_tapea; /* logical block of this record */ + uint32_t c_inumber; /* number of inode */ + int32_t c_magic; /* magic number (see above) */ + int32_t c_checksum; /* record checksum */ + union { + struct ufs1_dinode __uc_dinode; + struct { + uint16_t __uc_mode; + int16_t __uc_spare1[3]; + uint64_t __uc_size; + int32_t __uc_old_atime; + int32_t __uc_atimensec; + int32_t __uc_old_mtime; + int32_t __uc_mtimensec; + int32_t __uc_spare2[2]; + int32_t __uc_rdev; + int32_t __uc_birthtimensec; + int64_t __uc_birthtime; + int64_t __uc_atime; + int64_t __uc_mtime; + int32_t __uc_spare4[7]; + uint32_t __uc_file_flags; + int32_t __uc_spare5[2]; + uint32_t __uc_uid; + uint32_t __uc_gid; + int32_t __uc_spare6[2]; + } __uc_ino; + } __c_ino; + int32_t c_count; /* number of valid c_addr entries */ + char c_addr[TP_NINDIR]; /* 1 => data; 0 => hole in inode */ + char c_label[LBLSIZE]; /* dump label */ + int32_t c_level; /* level of this dump */ + char c_filesys[NAMELEN]; /* name of dumped file system */ + char c_dev[NAMELEN]; /* name of dumped device */ + char c_host[NAMELEN]; /* name of dumped host */ + int32_t c_flags; /* additional information */ + int32_t c_old_firstrec; /* first record on volume */ + int64_t c_date; /* date of this dump */ + int64_t c_ddate; /* date of previous dump */ + int64_t c_tapea; /* logical block of this record */ + int64_t c_firstrec; /* first record on volume */ + int32_t c_spare[24]; /* reserved for future uses */ + } s_spcl; +} u_spcl; +#define spcl u_spcl.s_spcl + +#define c_dinode __c_ino.__uc_dinode +#define c_mode __c_ino.__uc_ino.__uc_mode +#define c_spare1 __c_ino.__uc_ino.__uc_spare1 +#define c_size __c_ino.__uc_ino.__uc_size +#define c_old_atime __c_ino.__uc_ino.__uc_old_atime +#define c_atime __c_ino.__uc_ino.__uc_atime +#define c_atimensec __c_ino.__uc_ino.__uc_atimensec +#define c_mtime __c_ino.__uc_ino.__uc_mtime +#define c_mtimensec __c_ino.__uc_ino.__uc_mtimensec +#define c_birthtime __c_ino.__uc_ino.__uc_birthtime +#define c_birthtimensec __c_ino.__uc_ino.__uc_birthtimensec +#define c_old_mtime __c_ino.__uc_ino.__uc_old_mtime +#define c_rdev __c_ino.__uc_ino.__uc_rdev +#define c_file_flags __c_ino.__uc_ino.__uc_file_flags +#define c_uid __c_ino.__uc_ino.__uc_uid +#define c_gid __c_ino.__uc_ino.__uc_gid + +/* + * special record types + */ +#define TS_TAPE 1 /* dump tape header */ +#define TS_INODE 2 /* beginning of file record */ +#define TS_ADDR 4 /* continuation of file record */ +#define TS_BITS 3 /* map of inodes on tape */ +#define TS_CLRI 6 /* map of inodes deleted since last dump */ +#define TS_END 5 /* end of volume marker */ + +/* + * flag values + */ +#define DR_NEWHEADER 0x0001 /* new format tape header */ +#define DR_NEWINODEFMT 0x0002 /* new format inodes on tape */ + +#define DUMPOUTFMT "%-18s %c %s" /* for printf */ + /* name, level, ctime(date) */ +#define DUMPINFMT "%18s %c %[^\n]\n" /* inverse for scanf */ + +#endif /* !_PROTOCOLS_DUMPRESTORE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/protocols/routed.h b/lib/libc/include/generic-openbsd/protocols/routed.h new file mode 100644 index 000000000000..e73756df7c47 --- /dev/null +++ b/lib/libc/include/generic-openbsd/protocols/routed.h @@ -0,0 +1,152 @@ +/* $OpenBSD: routed.h,v 1.3 2003/06/02 19:34:12 millert Exp $ */ + +/*- + * Copyright (c) 1983, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)routed.h 8.1 (Berkeley) 6/2/93 + * + */ + +#ifndef _ROUTED_H_ +#define _ROUTED_H_ + +/* + * Routing Information Protocol + * + * Derived from Xerox NS Routing Information Protocol + * by changing 32-bit net numbers to sockaddr's and + * padding stuff to 32-bit boundaries. + */ + +#define RIPv1 1 +#define RIPv2 2 +#ifndef RIPVERSION +#define RIPVERSION RIPv1 +#endif + +#define RIP_PORT 520 + +#if RIPVERSION == 1 +/* Note that this so called sockaddr has a 2-byte sa_family and no sa_len. + * It is not a UNIX sockaddr, but the shape of an address as defined + * in RIPv1. It is still defined to allow old versions of programs + * such as `gated` to use this file to define RIPv1. + */ +struct netinfo { + struct sockaddr rip_dst; /* destination net/host */ + u_int32_t rip_metric; /* cost of route */ +}; +#else +struct netinfo { + u_int16_t n_family; +#define RIP_AF_INET htons(AF_INET) +#define RIP_AF_UNSPEC 0 +#define RIP_AF_AUTH 0xffff + u_int16_t n_tag; /* optional in RIPv2 */ + u_int32_t n_dst; /* destination net or host */ +#define RIP_DEFAULT 0 + u_int32_t n_mask; /* netmask in RIPv2 */ + u_int32_t n_nhop; /* optional next hop in RIPv2 */ + u_int32_t n_metric; /* cost of route */ +}; +#endif + +/* RIPv2 authentication */ +struct netauth { + u_int16_t a_type; +#define RIP_AUTH_PW htons(2) /* password type */ + union { +#define RIP_AUTH_PW_LEN 16 + int8_t au_pw[RIP_AUTH_PW_LEN]; + } au; +}; + +struct rip { + u_int8_t rip_cmd; /* request/response */ + u_int8_t rip_vers; /* protocol version # */ + u_int16_t rip_res1; /* pad to 32-bit boundary */ + union { /* variable length... */ + struct netinfo ru_nets[1]; + int8_t ru_tracefile[1]; + struct netauth ru_auth[1]; + } ripun; +#define rip_nets ripun.ru_nets +#define rip_tracefile ripun.ru_tracefile +}; + +/* Packet types. + */ +#define RIPCMD_REQUEST 1 /* want info */ +#define RIPCMD_RESPONSE 2 /* responding to request */ +#define RIPCMD_TRACEON 3 /* turn tracing on */ +#define RIPCMD_TRACEOFF 4 /* turn it off */ + +/* Gated extended RIP to include a "poll" command instead of using + * RIPCMD_REQUEST with (RIP_AF_UNSPEC, RIP_DEFAULT). RFC 1058 says + * command 5 is used by Sun Microsystems for its own purposes. + */ +#define RIPCMD_POLL 5 + +#define RIPCMD_MAX 6 + +#ifdef RIPCMDS +char *ripcmds[RIPCMD_MAX] = { + "#0", "REQUEST", "RESPONSE", "TRACEON", "TRACEOFF" +}; +#endif + +#define HOPCNT_INFINITY 16 +#define MAXPACKETSIZE 512 /* max broadcast size */ +#define NETS_LEN ((MAXPACKETSIZE-sizeof(struct rip)) \ + / sizeof(struct netinfo) +1) + +#define INADDR_RIP_GROUP __IPADDR(0xe0000009) /* 224.0.0.9 */ + + +/* Timer values used in managing the routing table. + * + * Complete tables are broadcast every SUPPLY_INTERVAL seconds. + * If changes occur between updates, dynamic updates containing only changes + * may be sent. When these are sent, a timer is set for a random value + * between MIN_WAITTIME and MAX_WAITTIME, and no additional dynamic updates + * are sent until the timer expires. + * + * Every update of a routing entry forces an entry's timer to be reset. + * After EXPIRE_TIME without updates, the entry is marked invalid, + * but held onto until GARBAGE_TIME so that others may see it, to + * "poison" the bad route. + */ +#define SUPPLY_INTERVAL 30 /* time to supply tables */ +#define MIN_WAITTIME 2 /* min sec until next flash updates */ +#define MAX_WAITTIME 5 /* max sec until flash update */ + +#define STALE_TIME 90 /* switch to a new gateway */ +#define EXPIRE_TIME 180 /* time to mark entry invalid */ +#define GARBAGE_TIME 240 /* time to garbage collect */ + +#endif /* !_ROUTED_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/protocols/rwhod.h b/lib/libc/include/generic-openbsd/protocols/rwhod.h new file mode 100644 index 000000000000..9757f71f03f6 --- /dev/null +++ b/lib/libc/include/generic-openbsd/protocols/rwhod.h @@ -0,0 +1,67 @@ +/* $OpenBSD: rwhod.h,v 1.4 2003/06/02 19:34:12 millert Exp $ */ +/* $NetBSD: rwhod.h,v 1.3 1994/10/26 00:56:51 cgd Exp $ */ + +/* + * Copyright (c) 1983 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)rwhod.h 5.6 (Berkeley) 4/3/91 + */ + +#ifndef _RWHOD_H_ +#define _RWHOD_H_ + +/* + * rwho protocol packet format. + */ +struct outmp { + char out_line[8]; /* tty name */ + char out_name[8]; /* user id */ + int32_t out_time; /* time on */ +}; + +struct whod { + char wd_vers; /* protocol version # */ + char wd_type; /* packet type, see below */ + char wd_pad[2]; + int32_t wd_sendtime; /* time stamp by sender */ + int32_t wd_recvtime; /* time stamp applied by receiver */ + char wd_hostname[32]; /* hosts's name */ + int32_t wd_loadav[3]; /* load average as in uptime */ + int32_t wd_boottime; /* time system booted */ + struct whoent { + struct outmp we_utmp; /* active tty info */ + int32_t we_idle; /* tty idle time */ + } wd_we[1024 / sizeof (struct whoent)]; +}; + +#define WHODVERSION 1 +#define WHODTYPE_STATUS 1 /* host status */ + +#define _PATH_RWHODIR "/var/rwho" + +#endif /* !_RWHOD_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/protocols/talkd.h b/lib/libc/include/generic-openbsd/protocols/talkd.h new file mode 100644 index 000000000000..09ba396b112e --- /dev/null +++ b/lib/libc/include/generic-openbsd/protocols/talkd.h @@ -0,0 +1,120 @@ +/* $OpenBSD: talkd.h,v 1.5 2015/01/21 02:23:14 guenther Exp $ */ +/* $NetBSD: talkd.h,v 1.5 1995/03/04 07:59:30 cgd Exp $ */ + +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)talkd.h 5.7 (Berkeley) 4/3/91 + */ + +#ifndef _TALKD_H_ +#define _TALKD_H_ + +/* + * This describes the protocol used by the talk server and clients. + * + * The talk server acts a repository of invitations, responding to + * requests by clients wishing to rendezvous for the purpose of + * holding a conversation. In normal operation, a client, the caller, + * initiates a rendezvous by sending a CTL_MSG to the server of + * type LOOK_UP. This causes the server to search its invitation + * tables to check if an invitation currently exists for the caller + * (to speak to the callee specified in the message). If the lookup + * fails, the caller then sends an ANNOUNCE message causing the server + * to broadcast an announcement on the callee's login ports requesting + * contact. When the callee responds, the local server uses the + * recorded invitation to respond with the appropriate rendezvous + * address and the caller and callee client programs establish a + * stream connection through which the conversation takes place. + */ + +struct osockaddr { + unsigned short sa_family; /* address family */ + char sa_data[14]; /* up to 14 bytes of direct address */ +}; + +/* + * Client->server request message format. + */ +typedef struct { + unsigned char vers; /* protocol version */ + unsigned char type; /* request type, see below */ + unsigned char answer; /* not used */ + unsigned char pad; + u_int32_t id_num; /* message id */ + struct osockaddr addr; /* old (4.3) style */ + struct osockaddr ctl_addr; /* old (4.3) style */ + int32_t pid; /* caller's process id */ +#define NAME_SIZE 12 + char l_name[NAME_SIZE]; /* caller's name */ + char r_name[NAME_SIZE]; /* callee's name */ +#define TTY_SIZE 16 + char r_tty[TTY_SIZE]; /* callee's tty name */ +} CTL_MSG; + +/* + * Server->client response message format. + */ +typedef struct { + unsigned char vers; /* protocol version */ + unsigned char type; /* type of request message, see below */ + unsigned char answer; /* response to request message, + see below */ + unsigned char pad; + u_int32_t id_num; /* message id */ + struct osockaddr addr; /* address for establishing + conversation */ +} CTL_RESPONSE; + +#define TALK_VERSION 1 /* protocol version */ + +/* message type values */ +#define LEAVE_INVITE 0 /* leave invitation with server */ +#define LOOK_UP 1 /* check for invitation by callee */ +#define DELETE 2 /* delete invitation by caller */ +#define ANNOUNCE 3 /* announce invitation by caller */ + +/* answer values */ +#define SUCCESS 0 /* operation completed properly */ +#define NOT_HERE 1 /* callee not logged in */ +#define FAILED 2 /* operation failed for unexplained reason */ +#define MACHINE_UNKNOWN 3 /* caller's machine name unknown */ +#define PERMISSION_DENIED 4 /* callee's tty doesn't permit announce */ +#define UNKNOWN_REQUEST 5 /* request has invalid type value */ +#define BADVERSION 6 /* request has invalid protocol version */ +#define BADADDR 7 /* request has invalid addr value */ +#define BADCTLADDR 8 /* request has invalid ctl_addr value */ + +/* + * Operational parameters. + */ +#define MAX_LIFE 60 /* max time daemon saves invitations */ +/* RING_WAIT should be 10's of seconds less than MAX_LIFE */ +#define RING_WAIT 30 /* time to wait before resending invitation */ + +#endif /* !_TALKD_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/protocols/timed.h b/lib/libc/include/generic-openbsd/protocols/timed.h new file mode 100644 index 000000000000..43104a6baf6a --- /dev/null +++ b/lib/libc/include/generic-openbsd/protocols/timed.h @@ -0,0 +1,101 @@ +/* $OpenBSD: timed.h,v 1.4 2015/01/16 00:27:00 deraadt Exp $ */ +/* $NetBSD: timed.h,v 1.5 1996/04/09 20:40:32 cgd Exp $ */ + +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)timed.h 1.10 (Berkeley) 4/3/91 + */ + +#ifndef _TIMED_H_ +#define _TIMED_H_ + +/* + * Time Synchronization Protocol + */ + +#define TSPVERSION 1 +#define ANYADDR NULL + +struct tsp { + u_int8_t tsp_type; + u_int8_t tsp_vers; + u_int16_t tsp_seq; + union { + struct { + int32_t tv_sec; + int32_t tv_usec; + } tspu_time; + char tspu_hopcnt; + } tsp_u; + char tsp_name[256]; +}; + +#define tsp_time tsp_u.tspu_time +#define tsp_hopcnt tsp_u.tspu_hopcnt + +/* + * Command types. + */ +#define TSP_ANY 0 /* match any types */ +#define TSP_ADJTIME 1 /* send adjtime */ +#define TSP_ACK 2 /* generic acknowledgement */ +#define TSP_MASTERREQ 3 /* ask for master's name */ +#define TSP_MASTERACK 4 /* acknowledge master request */ +#define TSP_SETTIME 5 /* send network time */ +#define TSP_MASTERUP 6 /* inform slaves that master is up */ +#define TSP_SLAVEUP 7 /* slave is up but not polled */ +#define TSP_ELECTION 8 /* advance candidature for master */ +#define TSP_ACCEPT 9 /* support candidature of master */ +#define TSP_REFUSE 10 /* reject candidature of master */ +#define TSP_CONFLICT 11 /* two or more masters present */ +#define TSP_RESOLVE 12 /* masters' conflict resolution */ +#define TSP_QUIT 13 /* reject candidature if master is up */ +#define TSP_DATE 14 /* reset the time (date command) */ +#define TSP_DATEREQ 15 /* remote request to reset the time */ +#define TSP_DATEACK 16 /* acknowledge time setting */ +#define TSP_TRACEON 17 /* turn tracing on */ +#define TSP_TRACEOFF 18 /* turn tracing off */ +#define TSP_MSITE 19 /* find out master's site */ +#define TSP_MSITEREQ 20 /* remote master's site request */ +#define TSP_TEST 21 /* for testing election algo */ +#define TSP_SETDATE 22 /* New from date command */ +#define TSP_SETDATEREQ 23 /* New remote for above */ +#define TSP_LOOP 24 /* loop detection packet */ + +#define TSPTYPENUMBER 25 + +#ifdef TSPTYPES +char *tsptype[TSPTYPENUMBER] = + { "ANY", "ADJTIME", "ACK", "MASTERREQ", "MASTERACK", "SETTIME", "MASTERUP", + "SLAVEUP", "ELECTION", "ACCEPT", "REFUSE", "CONFLICT", "RESOLVE", "QUIT", + "DATE", "DATEREQ", "DATEACK", "TRACEON", "TRACEOFF", "MSITE", "MSITEREQ", + "TEST", "SETDATE", "SETDATEREQ", "LOOP" }; +#endif + +#endif /* !_TIMED_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/pthread.h b/lib/libc/include/generic-openbsd/pthread.h new file mode 100644 index 000000000000..14141e3992e4 --- /dev/null +++ b/lib/libc/include/generic-openbsd/pthread.h @@ -0,0 +1,315 @@ +/* $OpenBSD: pthread.h,v 1.4 2018/03/05 01:15:26 deraadt Exp $ */ + +/* + * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu + * Copyright (c) 1995-1998 by John Birrell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: pthread.h,v 1.13 1999/07/31 08:36:07 rse Exp $ + */ +#ifndef _PTHREAD_H_ +#define _PTHREAD_H_ + +/* + * Header files. + */ +#include +#include +#include +#include +#include + +/* + * Run-time invariant values: + */ +#define PTHREAD_DESTRUCTOR_ITERATIONS 4 +#define PTHREAD_KEYS_MAX 256 +#define PTHREAD_STACK_MIN (1U << _MAX_PAGE_SHIFT) +#define PTHREAD_THREADS_MAX ULONG_MAX + +/* + * Flags for threads and thread attributes. + */ +#define PTHREAD_DETACHED 0x1 +#define PTHREAD_SCOPE_SYSTEM 0x2 +#define PTHREAD_INHERIT_SCHED 0x4 +#define PTHREAD_NOFLOAT 0x8 + +#define PTHREAD_CREATE_DETACHED PTHREAD_DETACHED +#define PTHREAD_CREATE_JOINABLE 0 +#define PTHREAD_SCOPE_PROCESS 0 +#define PTHREAD_EXPLICIT_SCHED 0 + +/* + * Flags for read/write lock attributes + */ +#define PTHREAD_PROCESS_PRIVATE 0 +#define PTHREAD_PROCESS_SHARED 1 + +/* + * Flags for cancelling threads + */ +#define PTHREAD_CANCEL_ENABLE 0 +#define PTHREAD_CANCEL_DISABLE 1 +#define PTHREAD_CANCEL_DEFERRED 0 +#define PTHREAD_CANCEL_ASYNCHRONOUS 2 +#define PTHREAD_CANCELED ((void *) 1) + +/* + * Barrier flags + */ +#define PTHREAD_BARRIER_SERIAL_THREAD -1 + +/* + * Forward structure definitions. + * + * These are mostly opaque to the user. + */ +struct pthread; +struct pthread_attr; +struct pthread_cond; +struct pthread_cond_attr; +struct pthread_mutex; +struct pthread_mutex_attr; +struct pthread_once; +struct pthread_rwlock; +struct pthread_rwlockattr; + +/* + * Primitive system data type definitions required by P1003.1c. + * + * Note that P1003.1c specifies that there are no defined comparison + * or assignment operators for the types pthread_attr_t, pthread_cond_t, + * pthread_condattr_t, pthread_mutex_t, pthread_mutexattr_t. + */ +typedef struct pthread *pthread_t; +typedef struct pthread_attr *pthread_attr_t; +typedef volatile struct pthread_mutex *pthread_mutex_t; +typedef struct pthread_mutex_attr *pthread_mutexattr_t; +typedef struct pthread_cond *pthread_cond_t; +typedef struct pthread_cond_attr *pthread_condattr_t; +typedef int pthread_key_t; +typedef struct pthread_once pthread_once_t; +typedef struct pthread_rwlock *pthread_rwlock_t; +typedef struct pthread_rwlockattr *pthread_rwlockattr_t; +typedef struct pthread_barrier *pthread_barrier_t; +typedef struct pthread_barrierattr *pthread_barrierattr_t; +typedef struct pthread_spinlock *pthread_spinlock_t; + +/* + * Additional type definitions: + * + * Note that P1003.1c reserves the prefixes pthread_ and PTHREAD_ for + * use in header symbols. + */ +typedef void *pthread_addr_t; +typedef void *(*pthread_startroutine_t)(void *); + +/* + * Once definitions. + */ +struct pthread_once { + int state; + pthread_mutex_t mutex; +}; + +/* + * Flags for once initialization. + */ +#define PTHREAD_NEEDS_INIT 0 +#define PTHREAD_DONE_INIT 1 + +/* + * Static once initialization values. + */ +#define PTHREAD_ONCE_INIT { PTHREAD_NEEDS_INIT, PTHREAD_MUTEX_INITIALIZER } + +/* + * Static initialization values. + */ +#define PTHREAD_MUTEX_INITIALIZER NULL +#define PTHREAD_COND_INITIALIZER NULL +#define PTHREAD_RWLOCK_INITIALIZER NULL + +#define PTHREAD_PRIO_NONE 0 +#define PTHREAD_PRIO_INHERIT 1 +#define PTHREAD_PRIO_PROTECT 2 + +/* + * Mutex types. + */ +enum pthread_mutextype { + PTHREAD_MUTEX_ERRORCHECK = 1, /* Error checking mutex */ + PTHREAD_MUTEX_RECURSIVE = 2, /* Recursive mutex */ + PTHREAD_MUTEX_NORMAL = 3, /* No error checking */ + PTHREAD_MUTEX_STRICT_NP = 4, /* Strict error checking */ + PTHREAD_MUTEX_TYPE_MAX +}; + +#define PTHREAD_MUTEX_ERRORCHECK PTHREAD_MUTEX_ERRORCHECK +#define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE +#define PTHREAD_MUTEX_NORMAL PTHREAD_MUTEX_NORMAL +#define PTHREAD_MUTEX_STRICT_NP PTHREAD_MUTEX_STRICT_NP +#define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_STRICT_NP + +/* + * Thread function prototype definitions: + */ +__BEGIN_DECLS +int pthread_atfork(void (*)(void), void (*)(void), void (*)(void)); +int pthread_attr_destroy(pthread_attr_t *); +int pthread_attr_getstack(const pthread_attr_t *, + void **, size_t *); +int pthread_attr_getstacksize(const pthread_attr_t *, size_t *); +int pthread_attr_getstackaddr(const pthread_attr_t *, void **); +int pthread_attr_getguardsize(const pthread_attr_t *, size_t *); +int pthread_attr_getdetachstate(const pthread_attr_t *, int *); +int pthread_attr_init(pthread_attr_t *); +int pthread_attr_setstacksize(pthread_attr_t *, size_t); +int pthread_attr_setstack(pthread_attr_t *, void *, size_t); +int pthread_attr_setstackaddr(pthread_attr_t *, void *); +int pthread_attr_setguardsize(pthread_attr_t *, size_t); +int pthread_attr_setdetachstate(pthread_attr_t *, int); +void pthread_cleanup_pop(int); +void pthread_cleanup_push(void (*) (void *), void *routine_arg); +int pthread_condattr_destroy(pthread_condattr_t *); +int pthread_condattr_init(pthread_condattr_t *); + +int pthread_cond_broadcast(pthread_cond_t *); +int pthread_cond_destroy(pthread_cond_t *); +int pthread_cond_init(pthread_cond_t *, + const pthread_condattr_t *); +int pthread_cond_signal(pthread_cond_t *); +int pthread_cond_timedwait(pthread_cond_t *, + pthread_mutex_t *, const struct timespec *); +int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *); +int pthread_create(pthread_t *, const pthread_attr_t *, + void *(*) (void *), void *); +int pthread_detach(pthread_t); +int pthread_equal(pthread_t, pthread_t); +__dead void pthread_exit(void *); +void *pthread_getspecific(pthread_key_t); +int pthread_join(pthread_t, void **); +int pthread_key_create(pthread_key_t *, + void (*) (void *)); +int pthread_key_delete(pthread_key_t); +int pthread_kill(pthread_t, int); +int pthread_mutexattr_init(pthread_mutexattr_t *); +int pthread_mutexattr_destroy(pthread_mutexattr_t *); +int pthread_mutexattr_gettype(pthread_mutexattr_t *, int *); +int pthread_mutexattr_settype(pthread_mutexattr_t *, int); +int pthread_mutex_destroy(pthread_mutex_t *); +int pthread_mutex_init(pthread_mutex_t *, + const pthread_mutexattr_t *); +int pthread_mutex_lock(pthread_mutex_t *); +int pthread_mutex_timedlock(pthread_mutex_t *, + const struct timespec *); +int pthread_mutex_trylock(pthread_mutex_t *); +int pthread_mutex_unlock(pthread_mutex_t *); +int pthread_once(pthread_once_t *, void (*) (void)); +int pthread_rwlock_destroy(pthread_rwlock_t *); +int pthread_rwlock_init(pthread_rwlock_t *, + const pthread_rwlockattr_t *); +int pthread_rwlock_rdlock(pthread_rwlock_t *); +int pthread_rwlock_timedrdlock(pthread_rwlock_t *, + const struct timespec *); +int pthread_rwlock_timedwrlock(pthread_rwlock_t *, + const struct timespec *); +int pthread_rwlock_tryrdlock(pthread_rwlock_t *); +int pthread_rwlock_trywrlock(pthread_rwlock_t *); +int pthread_rwlock_unlock(pthread_rwlock_t *); +int pthread_rwlock_wrlock(pthread_rwlock_t *); +int pthread_rwlockattr_init(pthread_rwlockattr_t *); +int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *, + int *); +int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int); +int pthread_rwlockattr_destroy(pthread_rwlockattr_t *); +pthread_t pthread_self(void); +int pthread_setspecific(pthread_key_t, const void *); + +int pthread_cancel(pthread_t); +int pthread_setcancelstate(int, int *); +int pthread_setcanceltype(int, int *); +void pthread_testcancel(void); + +int pthread_getprio(pthread_t); +int pthread_setprio(pthread_t, int); +void pthread_yield(void); + +int pthread_mutexattr_getprioceiling(pthread_mutexattr_t *, + int *); +int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *, + int); +int pthread_mutex_getprioceiling(pthread_mutex_t *, int *); +int pthread_mutex_setprioceiling(pthread_mutex_t *, int, int *); + +int pthread_mutexattr_getprotocol(pthread_mutexattr_t *, int *); +int pthread_mutexattr_setprotocol(pthread_mutexattr_t *, int); + +int pthread_condattr_getclock(const pthread_condattr_t *, + clockid_t *); +int pthread_condattr_setclock(pthread_condattr_t *, clockid_t); + +int pthread_attr_getinheritsched(const pthread_attr_t *, int *); +int pthread_attr_getschedparam(const pthread_attr_t *, + struct sched_param *); +int pthread_attr_getschedpolicy(const pthread_attr_t *, int *); +int pthread_attr_getscope(const pthread_attr_t *, int *); +int pthread_attr_setinheritsched(pthread_attr_t *, int); +int pthread_attr_setschedparam(pthread_attr_t *, + const struct sched_param *); +int pthread_attr_setschedpolicy(pthread_attr_t *, int); +int pthread_attr_setscope(pthread_attr_t *, int); +int pthread_getschedparam(pthread_t pthread, int *, + struct sched_param *); +int pthread_setschedparam(pthread_t, int, + const struct sched_param *); +int pthread_getconcurrency(void); +int pthread_setconcurrency(int); +int pthread_barrier_init(pthread_barrier_t *, + pthread_barrierattr_t *, unsigned int); +int pthread_barrier_destroy(pthread_barrier_t *); +int pthread_barrier_wait(pthread_barrier_t *); +int pthread_barrierattr_init(pthread_barrierattr_t *); +int pthread_barrierattr_destroy(pthread_barrierattr_t *); +int pthread_barrierattr_getpshared(pthread_barrierattr_t *, int *); +int pthread_barrierattr_setpshared(pthread_barrierattr_t *, int); +int pthread_spin_init(pthread_spinlock_t *, int); +int pthread_spin_destroy(pthread_spinlock_t *); +int pthread_spin_trylock(pthread_spinlock_t *); +int pthread_spin_lock(pthread_spinlock_t *); +int pthread_spin_unlock(pthread_spinlock_t *); + +#if __POSIX_VISIBLE >= 200112 +int pthread_getcpuclockid(pthread_t, clockid_t *); +#endif +__END_DECLS + +#endif /* _PTHREAD_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/pthread_np.h b/lib/libc/include/generic-openbsd/pthread_np.h new file mode 100644 index 000000000000..3e2298549809 --- /dev/null +++ b/lib/libc/include/generic-openbsd/pthread_np.h @@ -0,0 +1,56 @@ +/* $OpenBSD: pthread_np.h,v 1.3 2019/05/28 10:33:03 jca Exp $ */ +/* + * Copyright (c) 1996-98 John Birrell . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by John Birrell. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#ifndef _PTHREAD_NP_H_ +#define _PTHREAD_NP_H_ + +#include + +/* + * Non-POSIX type definitions: + */ +typedef void (*pthread_switch_routine_t)(pthread_t, pthread_t); + +/* + * Non-POSIX thread function prototype definitions: + */ +__BEGIN_DECLS +int pthread_mutexattr_getkind_np(pthread_mutexattr_t); +int pthread_mutexattr_setkind_np(pthread_mutexattr_t *, int); +void pthread_get_name_np(pthread_t, char *, size_t); +void pthread_set_name_np(pthread_t, const char *); +int pthread_stackseg_np(pthread_t, stack_t *); +int pthread_main_np(void); +__END_DECLS + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/pwd.h b/lib/libc/include/generic-openbsd/pwd.h new file mode 100644 index 000000000000..e94e06937cba --- /dev/null +++ b/lib/libc/include/generic-openbsd/pwd.h @@ -0,0 +1,119 @@ +/* $OpenBSD: pwd.h,v 1.26 2018/09/13 12:31:15 millert Exp $ */ +/* $NetBSD: pwd.h,v 1.9 1996/05/15 21:36:45 jtc Exp $ */ + +/*- + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * Portions Copyright(C) 1995, 1996, Jason Downs. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pwd.h 8.2 (Berkeley) 1/21/94 + */ + +#ifndef _PWD_H_ +#define _PWD_H_ + +#include + +#if __BSD_VISIBLE +#define _PATH_PASSWD "/etc/passwd" +#define _PATH_MASTERPASSWD "/etc/master.passwd" +#define _PATH_MASTERPASSWD_LOCK "/etc/ptmp" + +#define _PATH_MP_DB "/etc/pwd.db" +#define _PATH_SMP_DB "/etc/spwd.db" + +#define _PATH_PWD_MKDB "/usr/sbin/pwd_mkdb" + +#define _PW_KEYBYNAME '1' /* stored by name */ +#define _PW_KEYBYNUM '2' /* stored by entry in the "file" */ +#define _PW_KEYBYUID '3' /* stored by uid */ + +#define _PW_YPTOKEN "__YP!" + +#define _PASSWORD_EFMT1 '_' /* extended encryption format */ + +#define _PASSWORD_LEN 128 /* max length, not counting NUL */ +#define _PW_NAME_LEN 31 /* max length, not counting NUL */ + /* Should be MAXLOGNAME - 1 */ +#define _PW_BUF_LEN 1024 /* length of getpw*_r buffer */ + +#define _PASSWORD_NOUID 0x01 /* flag for no specified uid. */ +#define _PASSWORD_NOGID 0x02 /* flag for no specified gid. */ +#define _PASSWORD_NOCHG 0x04 /* flag for no specified change. */ +#define _PASSWORD_NOEXP 0x08 /* flag for no specified expire. */ + +/* Flags for pw_mkdb(3) */ +#define _PASSWORD_SECUREONLY 0x01 /* only generate spwd.db file */ +#define _PASSWORD_OMITV7 0x02 /* don't generate v7 passwd file */ + +#endif + +struct passwd { + char *pw_name; /* user name */ + char *pw_passwd; /* encrypted password */ + uid_t pw_uid; /* user uid */ + gid_t pw_gid; /* user gid */ + time_t pw_change; /* password change time */ + char *pw_class; /* user access class */ + char *pw_gecos; /* Honeywell login info */ + char *pw_dir; /* home directory */ + char *pw_shell; /* default shell */ + time_t pw_expire; /* account expiration */ +}; + +__BEGIN_DECLS +struct passwd *getpwuid(uid_t); +struct passwd *getpwnam(const char *); +struct passwd *getpwuid_shadow(uid_t); +struct passwd *getpwnam_shadow(const char *); +int getpwnam_r(const char *, struct passwd *, char *, size_t, + struct passwd **); +int getpwuid_r(uid_t, struct passwd *, char *, size_t, + struct passwd **); +#if __BSD_VISIBLE || __XPG_VISIBLE +struct passwd *getpwent(void); +void setpwent(void); +void endpwent(void); +#endif +#if __BSD_VISIBLE +int setpassent(int); +int uid_from_user(const char *, uid_t *); +const char *user_from_uid(uid_t, int); +char *bcrypt_gensalt(u_int8_t); +char *bcrypt(const char *, const char *); +int bcrypt_newhash(const char *, int, char *, size_t); +int bcrypt_checkpass(const char *, const char *); +struct passwd *pw_dup(const struct passwd *); +#endif +__END_DECLS + +#endif /* !_PWD_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/radius.h b/lib/libc/include/generic-openbsd/radius.h new file mode 100644 index 000000000000..482f1cf07c8d --- /dev/null +++ b/lib/libc/include/generic-openbsd/radius.h @@ -0,0 +1,572 @@ +/* $OpenBSD: radius.h,v 1.7 2024/06/29 11:50:31 yasuoka Exp $ */ + +/*- + * Copyright (c) 2009 Internet Initiative Japan Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _RADIUS_H +#define _RADIUS_H + +#define RADIUS_DEFAULT_PORT 1812 +#define RADIUS_ACCT_DEFAULT_PORT 1813 +#define RADIUS_DAE_DEFAULT_PORT 3799 + +/* RADIUS codes */ +#define RADIUS_CODE_ACCESS_REQUEST 1 +#define RADIUS_CODE_ACCESS_ACCEPT 2 +#define RADIUS_CODE_ACCESS_REJECT 3 +#define RADIUS_CODE_ACCOUNTING_REQUEST 4 +#define RADIUS_CODE_ACCOUNTING_RESPONSE 5 +#define RADIUS_CODE_ACCESS_CHALLENGE 11 +#define RADIUS_CODE_STATUS_SERVER 12 +#define RADIUS_CODE_STATUS_CLIENT 13 + +#define RADIUS_CODE_DISCONNECT_REQUEST 40 +#define RADIUS_CODE_DISCONNECT_ACK 41 +#define RADIUS_CODE_DISCONNECT_NAK 42 +#define RADIUS_CODE_COA_REQUEST 43 +#define RADIUS_CODE_COA_ACK 44 +#define RADIUS_CODE_COA_NAK 45 + +/* RADIUS attributes */ +#define RADIUS_TYPE_USER_NAME 1 +#define RADIUS_TYPE_USER_PASSWORD 2 +#define RADIUS_TYPE_CHAP_PASSWORD 3 +#define RADIUS_TYPE_NAS_IP_ADDRESS 4 +#define RADIUS_TYPE_NAS_PORT 5 +#define RADIUS_TYPE_SERVICE_TYPE 6 +#define RADIUS_TYPE_FRAMED_PROTOCOL 7 +#define RADIUS_TYPE_FRAMED_IP_ADDRESS 8 +#define RADIUS_TYPE_FRAMED_IP_NETMASK 9 +#define RADIUS_TYPE_FRAMED_ROUTING 10 +#define RADIUS_TYPE_FILTER_ID 11 +#define RADIUS_TYPE_FRAMED_MTU 12 +#define RADIUS_TYPE_FRAMED_COMPRESSION 13 +#define RADIUS_TYPE_LOGIN_IP_HOST 14 +#define RADIUS_TYPE_LOGIN_SERVICE 15 +#define RADIUS_TYPE_LOGIN_TCP_PORT 16 +/* unassigned 17 */ +#define RADIUS_TYPE_REPLY_MESSAGE 18 +#define RADIUS_TYPE_CALLBACK_NUMBER 19 +#define RADIUS_TYPE_CALLBACK_ID 20 +/* unassigned 21 */ +#define RADIUS_TYPE_FRAMED_ROUTE 22 +#define RADIUS_TYPE_FRAMED_IPX_NETWORK 23 +#define RADIUS_TYPE_STATE 24 +#define RADIUS_TYPE_CLASS 25 +#define RADIUS_TYPE_VENDOR_SPECIFIC 26 +#define RADIUS_TYPE_SESSION_TIMEOUT 27 +#define RADIUS_TYPE_IDLE_TIMEOUT 28 +#define RADIUS_TYPE_TERMINATION_ACTION 29 +#define RADIUS_TYPE_CALLED_STATION_ID 30 +#define RADIUS_TYPE_CALLING_STATION_ID 31 +#define RADIUS_TYPE_NAS_IDENTIFIER 32 +#define RADIUS_TYPE_PROXY_STATE 33 +#define RADIUS_TYPE_LOGIN_LAT_SERVICE 34 +#define RADIUS_TYPE_LOGIN_LAT_NODE 35 +#define RADIUS_TYPE_LOGIN_LAT_GROUP 36 +#define RADIUS_TYPE_FRAMED_APPLETALK_LINK 37 +#define RADIUS_TYPE_FRAMED_APPLETALK_NETWORK 38 +#define RADIUS_TYPE_FRAMED_APPLETALK_ZONE 39 +#define RADIUS_TYPE_ACCT_STATUS_TYPE 40 +#define RADIUS_TYPE_ACCT_DELAY_TIME 41 +#define RADIUS_TYPE_ACCT_INPUT_OCTETS 42 +#define RADIUS_TYPE_ACCT_OUTPUT_OCTETS 43 +#define RADIUS_TYPE_ACCT_SESSION_ID 44 +#define RADIUS_TYPE_ACCT_AUTHENTIC 45 +#define RADIUS_TYPE_ACCT_SESSION_TIME 46 +#define RADIUS_TYPE_ACCT_INPUT_PACKETS 47 +#define RADIUS_TYPE_ACCT_OUTPUT_PACKETS 48 +#define RADIUS_TYPE_ACCT_TERMINATE_CAUSE 49 +#define RADIUS_TYPE_ACCT_MULTI_SESSION_ID 50 +#define RADIUS_TYPE_ACCT_LINK_COUNT 51 +#define RADIUS_TYPE_ACCT_INPUT_GIGAWORDS 52 +#define RADIUS_TYPE_ACCT_OUTPUT_GIGAWORDS 53 +/* unassigned (for accounting) 54 */ +#define RADIUS_TYPE_EVENT_TIMESTAMP 55 +/* unassigned (for accounting) 56 */ +/* unassigned (for accounting) 57 */ +/* unassigned (for accounting) 58 */ +/* unassigned (for accounting) 59 */ +#define RADIUS_TYPE_CHAP_CHALLENGE 60 +#define RADIUS_TYPE_NAS_PORT_TYPE 61 +#define RADIUS_TYPE_PORT_LIMIT 62 +#define RADIUS_TYPE_LOGIN_LAT_PORT 63 +#define RADIUS_TYPE_TUNNEL_TYPE 64 +#define RADIUS_TYPE_TUNNEL_MEDIUM_TYPE 65 +#define RADIUS_TYPE_TUNNEL_CLIENT_ENDPOINT 66 +#define RADIUS_TYPE_TUNNEL_SERVER_ENDPOINT 67 +#define RADIUS_TYPE_ACCT_TUNNEL_CONNECTION 68 +#define RADIUS_TYPE_TUNNEL_PASSWORD 69 +#define RADIUS_TYPE_ARAP_PASSWORD 70 +#define RADIUS_TYPE_ARAP_FEATURES 71 +#define RADIUS_TYPE_ARAP_ZONE_ACCESS 72 +#define RADIUS_TYPE_ARAP_SECURITY 73 +#define RADIUS_TYPE_ARAP_SECURITY_DATA 74 +#define RADIUS_TYPE_PASSWORD_RETRY 75 +#define RADIUS_TYPE_PROMPT 76 +#define RADIUS_TYPE_CONNECT_INFO 77 +#define RADIUS_TYPE_CONFIGURATION_TOKEN 78 +#define RADIUS_TYPE_EAP_MESSAGE 79 +#define RADIUS_TYPE_MESSAGE_AUTHENTICATOR 80 +#define RADIUS_TYPE_TUNNEL_PRIVATE_GROUP_ID 81 +#define RADIUS_TYPE_TUNNEL_ASSIGNMENT_ID 82 +#define RADIUS_TYPE_TUNNEL_PREFERENCE 83 +#define RADIUS_TYPE_ARAP_CHALLENGE_RESPONSE 84 +#define RADIUS_TYPE_ACCT_INTERIM_INTERVAL 85 +#define RADIUS_TYPE_ACCT_TUNNEL_PACKETS_LOST 86 +#define RADIUS_TYPE_NAS_PORT_ID 87 +#define RADIUS_TYPE_FRAMED_POOL 88 +/* unassigned 89 */ +#define RADIUS_TYPE_TUNNEL_CLIENT_AUTH_ID 90 +#define RADIUS_TYPE_TUNNEL_SERVER_AUTH_ID 91 +/* unassigned 92-94 */ +#define RADIUS_TYPE_NAS_IPV6_ADDRESS 95 +#define RADIUS_TYPE_FRAMED_INTERFACE_ID 96 +#define RADIUS_TYPE_FRAMED_IPV6_PREFIX 97 +#define RADIUS_TYPE_LOGIN_IPV6_HOST 98 +#define RADIUS_TYPE_FRAMED_IPV6_ROUTE 99 +#define RADIUS_TYPE_FRAMED_IPV6_POOL 100 + +/* RFC 5176 3.5. Error-Cause */ +#define RADIUS_TYPE_ERROR_CAUSE 101 + +/* RFC 6911 3. Attributes */ +#define RADIUS_TYPE_FRAMED_IPV6_ADDRESS 168 +#define RADIUS_TYPE_DNS_SERVER_IPV6_ADDRESS 169 +#define RADIUS_TYPE_ROUTE_IPV6_INFORMATION 170 +#define RADIUS_TYPE_DELEGATED_IPV6_PREFIX_POOL 171 +#define RADIUS_TYPE_STATEFUL_IPV6_ADDRESS_POOL 172 + + +/* RFC 2865 5.7. Framed-Protocol */ +#define RADIUS_FRAMED_PROTOCOL_PPP 1 /* PPP */ +#define RADIUS_FRAMED_PROTOCOL_SLIP 2 /* SLIP */ +#define RADIUS_FRAMED_PROTOCOL_ARAP 3 /* AppleTalk Remote Access + * Protocol (ARAP) */ +#define RADIUS_FRAMED_PROTOCOL_GANDALF 4 /* Gandalf proprietary + * SingleLink/MultiLink + * protocol */ +#define RADIUS_FRAMED_PROTOCOL_XYLOGICS 5 /* Xylogics proprietary + * IPX/SLIP */ +#define RADIUS_FRAMED_PROTOCOL_X75 6 /* X.75 Synchronous */ + + +/* RFC 2865 5.6. Service-Type */ +#define RADIUS_SERVICE_TYPE_LOGIN 1 +#define RADIUS_SERVICE_TYPE_FRAMED 2 +#define RADIUS_SERVICE_TYPE_CB_LOGIN 3 +#define RADIUS_SERVICE_TYPE_CB_FRAMED 4 +#define RADIUS_SERVICE_TYPE_OUTBOUND 5 +#define RADIUS_SERVICE_TYPE_ADMINISTRATIVE 6 +#define RADIUS_SERVICE_TYPE_NAS_PROMPT 7 +#define RADIUS_SERVICE_TYPE_AUTHENTICAT_ONLY 8 +#define RADIUS_SERVICE_TYPE_CB_NAS_PROMPT 9 +#define RADIUS_SERVICE_TYPE_CALL_CHECK 10 +#define RADIUS_SERVICE_TYPE_CB_ADMINISTRATIVE 11 + + +/* Microsoft vendor specific attributes: see RFC2548*/ +#define RADIUS_VENDOR_MICROSOFT 311 +#define RADIUS_VTYPE_MS_CHAP_RESPONSE 1 +#define RADIUS_VTYPE_MS_CHAP_ERROR 2 +#define RADIUS_VTYPE_MS_CHAP_PW_1 3 +#define RADIUS_VTYPE_MS_CHAP_PW_2 4 +#define RADIUS_VTYPE_MS_CHAP_LM_ENC_PW 5 +#define RADIUS_VTYPE_MS_CHAP_NT_ENC_PW 6 +#define RADIUS_VTYPE_MPPE_ENCRYPTION_POLICY 7 +#define RADIUS_VTYPE_MPPE_ENCRYPTION_TYPES 8 +#define RADIUS_VTYPE_MS_RAS_VENDOR 9 +#define RADIUS_VTYPE_MS_CHAP_CHALLENGE 11 +#define RADIUS_VTYPE_MS_CHAP_MPPE_KEYS 12 +#define RADIUS_VTYPE_MS_BAP_USAGE 13 +#define RADIUS_VTYPE_MS_LINK_UTILIZATION_THRESHOLD 14 +#define RADIUS_VTYPE_MS_LINK_DROP_TIME_LIMIT 15 +#define RADIUS_VTYPE_MPPE_SEND_KEY 16 +#define RADIUS_VTYPE_MPPE_RECV_KEY 17 +#define RADIUS_VTYPE_MS_RAS_VERSION 18 +#define RADIUS_VTYPE_MS_OLD_ARAP_PASSWORD 19 +#define RADIUS_VTYPE_MS_NEW_ARAP_PASSWORD 20 +#define RADIUS_VTYPE_MS_ARAP_PASSWORD_CHANGE_REASON 21 +#define RADIUS_VTYPE_MS_FILTER 22 +#define RADIUS_VTYPE_MS_ACCT_AUTH_TYPE 23 +#define RADIUS_VTYPE_MS_ACCT_EAP_TYPE 24 +#define RADIUS_VTYPE_MS_CHAP2_RESPONSE 25 +#define RADIUS_VTYPE_MS_CHAP2_SUCCESS 26 +#define RADIUS_VTYPE_MS_CHAP2_PW 27 +#define RADIUS_VTYPE_MS_PRIMARY_DNS_SERVER 28 +#define RADIUS_VTYPE_MS_SECONDARY_DNS_SERVER 29 +#define RADIUS_VTYPE_MS_PRIMARY_NBNS_SERVER 30 +#define RADIUS_VTYPE_MS_SECONDARY_NBNS_SERVER 31 +/* unassigned? 32 */ +#define RADIUS_VTYPE_MS_ARAP_CHALLENGE 33 + + +/* RFC 2865 5.41. NAS-Port-Type */ +#define RADIUS_NAS_PORT_TYPE_ASYNC 0 /* Async */ +#define RADIUS_NAS_PORT_TYPE_SYNC 1 /* Sync */ +#define RADIUS_NAS_PORT_TYPE_ISDN_SYNC 2 /* ISDN Sync */ +#define RADIUS_NAS_PORT_TYPE_ISDN_ASYNC_V120 3 /* ISDN Async V.120 */ +#define RADIUS_NAS_PORT_TYPE_ISDN_ASYNC_V110 4 /* ISDN Async V.110 */ +#define RADIUS_NAS_PORT_TYPE_VIRTUAL 5 /* Virtual */ +#define RADIUS_NAS_PORT_TYPE_PIAFS 6 /* PIAFS */ +#define RADIUS_NAS_PORT_TYPE_HDLC_CLEAR_CHANNEL 7 /* HDLC Clear Channel */ +#define RADIUS_NAS_PORT_TYPE_X_25 8 /* X.25 */ +#define RADIUS_NAS_PORT_TYPE_X_75 9 /* X.75 */ +#define RADIUS_NAS_PORT_TYPE_G3_FAX 10 /* G.3 Fax */ +#define RADIUS_NAS_PORT_TYPE_SDSL 11 /* SDSL - Symmetric DSL */ +#define RADIUS_NAS_PORT_TYPE_ADSL_CAP 12 /* ADSL-CAP - Asymmetric + * DSL, Carrierless + * Amplitude Phase + * Modulation */ +#define RADIUS_NAS_PORT_TYPE_ADSL_DMT 13 /* ADSL-DMT - Asymmetric + * DSL, Discrete + * Multi-Tone */ +#define RADIUS_NAS_PORT_TYPE_IDSL 14 /* IDSL - ISDN Digital + * Subscriber Line */ +#define RADIUS_NAS_PORT_TYPE_ETHERNET 15 /* Ethernet */ +#define RADIUS_NAS_PORT_TYPE_XDSL 16 /* xDSL - Digital + * Subscriber Line of + * unknown type */ +#define RADIUS_NAS_PORT_TYPE_CABLE 17 /* Cable */ +#define RADIUS_NAS_PORT_TYPE_WIRELESS 18 /* Wireless - Other */ +#define RADIUS_NAS_PORT_TYPE_WIRELESS_802_11 19 /* Wireless - IEEE + * 802.11 */ + + +/* RFC 2866 5.1. Acct-Status-Type */ +#define RADIUS_ACCT_STATUS_TYPE_START 1 /* Start */ +#define RADIUS_ACCT_STATUS_TYPE_STOP 2 /* Stop */ +#define RADIUS_ACCT_STATUS_TYPE_INTERIM_UPDATE 3 /* Interim-Update */ +#define RADIUS_ACCT_STATUS_TYPE_ACCT_ON 7 /* Accounting-On */ +#define RADIUS_ACCT_STATUS_TYPE_ACCT_OFF 8 /* Accounting-Off */ + + +/* RFC 2866 5.6. Acct-Authentic */ +#define RADIUS_ACCT_AUTHENTIC_RADIUS 1 /* RADIUS */ +#define RADIUS_ACCT_AUTHENTIC_LOCAL 2 /* Local */ +#define RADIUS_ACCT_AUTHENTIC_REMOTE 3 /* Remote */ + + +/* RFC 2866 5.10. Acct-Terminate-Cause */ +#define RADIUS_TERMNATE_CAUSE_USER_REQUEST 1 /* User Request */ +#define RADIUS_TERMNATE_CAUSE_LOST_CARRIER 2 /* Lost Carrier */ +#define RADIUS_TERMNATE_CAUSE_LOST_SERVICE 3 /* Lost Service */ +#define RADIUS_TERMNATE_CAUSE_IDLE_TIMEOUT 4 /* Idle Timeout */ +#define RADIUS_TERMNATE_CAUSE_SESSION_TIMEOUT 5 /* Session Timeout */ +#define RADIUS_TERMNATE_CAUSE_ADMIN_RESET 6 /* Admin Reset */ +#define RADIUS_TERMNATE_CAUSE_ADMIN_REBOOT 7 /* Admin Reboot */ +#define RADIUS_TERMNATE_CAUSE_PORT_ERROR 8 /* Port Error */ +#define RADIUS_TERMNATE_CAUSE_NAS_ERROR 9 /* NAS Error */ +#define RADIUS_TERMNATE_CAUSE_NAS_RESET 10 /* NAS Request */ +#define RADIUS_TERMNATE_CAUSE_NAS_REBOOT 11 /* NAS Reboot */ +#define RADIUS_TERMNATE_CAUSE_PORT_UNNEEDED 12 /* Port Unneeded */ +#define RADIUS_TERMNATE_CAUSE_PORT_PREEMPTED 13 /* Port Preempted */ +#define RADIUS_TERMNATE_CAUSE_PORT_SUSPENDED 14 /* Port Suspended */ +#define RADIUS_TERMNATE_CAUSE_SERVICE_UNAVAIL 15 /* Service Unavailable */ +#define RADIUS_TERMNATE_CAUSE_CALLBACK 16 /* Callback */ +#define RADIUS_TERMNATE_CAUSE_USER_ERROR 17 /* User Error */ +#define RADIUS_TERMNATE_CAUSE_HOST_REQUEST 18 /* Host Request */ + + +/* RFC 2868 3.1. Tunnel-Type */ +#define RADIUS_TUNNEL_TYPE_PPTP 1 /* Point-to-Point Tunneling + * Protocol (PPTP) */ +#define RADIUS_TUNNEL_TYPE_L2F 2 /* Layer Two Forwarding (L2F) */ +#define RADIUS_TUNNEL_TYPE_L2TP 3 /* Layer Two Tunneling + * Protocol (L2TP) */ +#define RADIUS_TUNNEL_TYPE_ATMP 4 /* Ascend Tunnel Management + * Protocol (ATMP) */ +#define RADIUS_TUNNEL_TYPE_VTP 5 /* Virtual Tunneling Protocol + * (VTP) */ +#define RADIUS_TUNNEL_TYPE_AH 6 /* IP Authentication Header in + * the Tunnel-mode (AH) */ +#define RADIUS_TUNNEL_TYPE_IP 7 /* IP-in-IP Encapsulation + * (IP-IP) */ +#define RADIUS_TUNNEL_TYPE_MOBILE 8 /* Minimal IP-in-IP + * Encapsulation (MIN-IP-IP) */ +#define RADIUS_TUNNEL_TYPE_ESP 9 /* IP Encapsulating Security + * Payload in the Tunnel-mode + * (ESP) */ +#define RADIUS_TUNNEL_TYPE_GRE 10 /* Generic Route Encapsulation + * (GRE) */ +#define RADIUS_TUNNEL_TYPE_VDS 11 /* Bay Dial Virtual Services + * (DVS) */ +#define RADIUS_TUNNEL_TYPE_IPIP 12 /* IP-in-IP Tunneling */ + + +/* RFC 2868 3.2. Tunnel-Medium-Type */ +#define RADIUS_TUNNEL_MEDIUM_TYPE_IPV4 1 /* IPv4 (IP version 4) */ +#define RADIUS_TUNNEL_MEDIUM_TYPE_IPV6 2 /* IPv6 (IP version 6) */ +#define RADIUS_TUNNEL_MEDIUM_TYPE_NSAP 3 /* NSAP */ +#define RADIUS_TUNNEL_MEDIUM_TYPE_HDLC 4 /* HDLC (8-bit + * multidrop) */ +#define RADIUS_TUNNEL_MEDIUM_TYPE_BBN1822 5 /* BBN 1822 */ +#define RADIUS_TUNNEL_MEDIUM_TYPE_802 6 /* 802 (includes all 802 + * media plus Ethernet + * "canonical format")*/ +#define RADIUS_TUNNEL_MEDIUM_TYPE_E163 7 /* E.163 (POTS) */ +#define RADIUS_TUNNEL_MEDIUM_TYPE_E164 8 /* E.164 (SMDS, Frame + * Relay, ATM) */ +/* RFC 5167 3.5. Error-Cause */ +/* Residual Session Context Removed */ +#define RADIUS_ERROR_CAUSE_RESIDUAL_SESSION_REMOVED 201 +/* Invalid EAP Packet (Ignored) */ +#define RADIUS_ERROR_CAUSE_INVALID_EAP_PACKET 202 +/* Unsupported Attribute */ +#define RADIUS_ERROR_CAUSE_UNSUPPORTED_ATTRIBUTE 401 +/* Missing Attribute */ +#define RADIUS_ERROR_CAUSE_MISSING_ATTRIBUTE 402 +/* NAS Identification Mismatch */ +#define RADIUS_ERROR_CAUSE_NAS_IDENTIFICATION_MISMATCH 403 +/* Invalid Request */ +#define RADIUS_ERROR_CAUSE_INVALID_REQUEST 404 +/* Unsupported Service */ +#define RADIUS_ERROR_CAUSE_UNSUPPORTED_SERVICE 405 +/* Unsupported Extension */ +#define RADIUS_ERROR_CAUSE_UNSUPPORTED_EXTENSION 406 +/* Invalid Attribute Valu */ +#define RADIUS_ERROR_CAUSE_INVALID_ATTRIBUTE_VALUE 407 +/* Administratively Prohibited */ +#define RADIUS_ERROR_CAUSE_ADMINISTRATIVELY_PROHIBITED 501 +/* Request Not Routable (Proxy) */ +#define RADIUS_ERROR_CAUSE_REQUEST_NOT_ROUTABLE 502 +/* Session Context Not Found */ +#define RADIUS_ERROR_CAUSE_SESSION_NOT_FOUND 503 +/* Session Context Not Removable */ +#define RADIUS_ERROR_CAUSE_SESSION_NOT_REMOVABLE 504 +/* Other Proxy Processing Error */ +#define RADIUS_ERROR_CAUSE_OTHER_PROXY_PROCESSING_ERROR 505 +/* Resources Unavailable */ +#define RADIUS_ERROR_CAUSE_RESOURCES_UNAVAILABLE 506 +/* Request Initiated */ +#define RADIUS_ERROR_CAUSE_REQUEST_INITIATED 507 +/* Multiple Session Selection Unsupported */ +#define RADIUS_ERROR_CAUSE_MULTI_SELECTION_UNSUPPORTED 508 + +#include +#include + +#include +#include + +struct in_addr; +struct in6_addr; + +__BEGIN_DECLS + +/******* packet manipulation support *******/ + +typedef struct _RADIUS_PACKET RADIUS_PACKET; + +/* constructors */ +RADIUS_PACKET *radius_new_request_packet(uint8_t); +RADIUS_PACKET *radius_new_response_packet(uint8_t, const RADIUS_PACKET *); +RADIUS_PACKET *radius_convert_packet(const void *, size_t); + +/* destructor */ +int radius_delete_packet(RADIUS_PACKET *); + +/* accessors - header values */ +uint8_t radius_get_id(const RADIUS_PACKET *); +void radius_update_id(RADIUS_PACKET * packet); +void radius_set_id(RADIUS_PACKET *, uint8_t); +uint8_t radius_get_code(const RADIUS_PACKET *); +void radius_get_authenticator(const RADIUS_PACKET *, void *); +void radius_set_request_packet(RADIUS_PACKET *, + const RADIUS_PACKET *); +const RADIUS_PACKET * + radius_get_request_packet(const RADIUS_PACKET *); +int radius_check_response_authenticator(const RADIUS_PACKET *, + const char *); +int radius_check_accounting_request_authenticator( + const RADIUS_PACKET *, const char *); +uint8_t *radius_get_authenticator_retval(const RADIUS_PACKET *); +uint8_t *radius_get_request_authenticator_retval(const RADIUS_PACKET *); +void radius_set_accounting_request_authenticator(RADIUS_PACKET *, + const char *); +void radius_set_response_authenticator(RADIUS_PACKET *, + const char *); +uint16_t radius_get_length(const RADIUS_PACKET *); +const void *radius_get_data(const RADIUS_PACKET *); + +int radius_get_raw_attr(const RADIUS_PACKET *, uint8_t, void *, + size_t *); +int radius_get_vs_raw_attr(const RADIUS_PACKET *, uint32_t, + uint8_t, void *, size_t *); +int radius_put_raw_attr(RADIUS_PACKET *, uint8_t, const void *, + size_t); +int radius_put_vs_raw_attr(RADIUS_PACKET *, uint32_t, uint8_t, + const void *, size_t); +int radius_get_raw_attr_ptr(const RADIUS_PACKET *, uint8_t, + const void **, size_t *); +int radius_get_vs_raw_attr_ptr(const RADIUS_PACKET *, uint32_t, + uint8_t, const void **, size_t *); +int radius_get_raw_attr_cat(const RADIUS_PACKET *, uint8_t, + void *, size_t *); +int radius_get_vs_raw_attr_cat(const RADIUS_PACKET *, uint32_t, + uint8_t, void *, size_t *); +int radius_put_raw_attr_cat(RADIUS_PACKET *, uint8_t, + const void *, size_t); +int radius_put_vs_raw_attr_cat(RADIUS_PACKET *, uint32_t, uint8_t, + const void *, size_t); +int radius_set_raw_attr(RADIUS_PACKET *, uint8_t, const void *, + size_t); +int radius_set_vs_raw_attr(RADIUS_PACKET *, uint32_t, uint8_t, + const void *, size_t); + +int radius_del_attr_all(RADIUS_PACKET *, uint8_t); +int radius_del_vs_attr_all(RADIUS_PACKET *, uint32_t, uint8_t); + +bool radius_has_attr(const RADIUS_PACKET *, uint8_t); +bool radius_has_vs_attr(const RADIUS_PACKET *, uint32_t, uint8_t); + +/* typed attribute accessor (string) */ +int radius_get_string_attr(const RADIUS_PACKET *, uint8_t, char *, + size_t); +int radius_get_vs_string_attr(const RADIUS_PACKET *, uint32_t, + uint8_t, char *, size_t); +int radius_put_string_attr(RADIUS_PACKET *, uint8_t, const char *); +int radius_put_vs_string_attr(RADIUS_PACKET *, uint32_t, uint8_t, + const char *); + +/* typed attribute accessor (uint16_t) */ +int radius_get_uint16_attr(const RADIUS_PACKET *, + uint8_t, uint16_t *); +int radius_get_vs_uint16_attr(const RADIUS_PACKET *, + uint32_t, uint8_t, uint16_t *); +int radius_put_uint16_attr(RADIUS_PACKET *, + uint8_t, const uint16_t); +int radius_put_vs_uint16_attr(RADIUS_PACKET *, + uint32_t, uint8_t, const uint16_t); +int radius_set_uint16_attr(RADIUS_PACKET *, + uint8_t, const uint16_t); +int radius_set_vs_uint16_attr(RADIUS_PACKET *, + uint32_t, uint8_t, const uint16_t); + +/* typed attribute accessor (uint32_t) */ +int radius_get_uint32_attr(const RADIUS_PACKET *, + uint8_t, uint32_t *); +int radius_get_vs_uint32_attr(const RADIUS_PACKET *, + uint32_t, uint8_t, uint32_t *); +int radius_put_uint32_attr(RADIUS_PACKET *, + uint8_t, const uint32_t); +int radius_put_vs_uint32_attr(RADIUS_PACKET *, + uint32_t, uint8_t, const uint32_t); +int radius_set_uint32_attr(RADIUS_PACKET *, + uint8_t, const uint32_t); +int radius_set_vs_uint32_attr(RADIUS_PACKET *, + uint32_t, uint8_t, const uint32_t); + +/* typed attribute accessor (uint64_t) */ +int radius_get_uint64_attr(const RADIUS_PACKET *, + uint8_t, uint64_t *); +int radius_get_vs_uint64_attr(const RADIUS_PACKET *, + uint32_t, uint8_t, uint64_t *); +int radius_put_uint64_attr(RADIUS_PACKET *, + uint8_t, const uint64_t); +int radius_put_vs_uint64_attr(RADIUS_PACKET *, + uint32_t, uint8_t, const uint64_t); +int radius_set_uint64_attr(RADIUS_PACKET *, + uint8_t, const uint64_t); +int radius_set_vs_uint64_attr(RADIUS_PACKET *, + uint32_t, uint8_t, const uint64_t); + +/* typed attribute accessor (ipv4) */ +int radius_get_ipv4_attr(const RADIUS_PACKET *, + uint8_t, struct in_addr *); +int radius_get_vs_ipv4_attr(const RADIUS_PACKET *, + uint32_t, uint8_t, struct in_addr *); +int radius_put_ipv4_attr(RADIUS_PACKET *, + uint8_t, const struct in_addr); +int radius_put_vs_ipv4_attr(RADIUS_PACKET *, + uint32_t, uint8_t, const struct in_addr); +int radius_set_ipv4_attr(RADIUS_PACKET *, + uint8_t, const struct in_addr); +int radius_set_vs_ipv4_attr(RADIUS_PACKET *, + uint32_t, uint8_t, const struct in_addr); + +/* typed attribute accessor (ipv6) */ +int radius_get_ipv6_attr(const RADIUS_PACKET *, + uint8_t, struct in6_addr *); +int radius_get_vs_ipv6_attr(const RADIUS_PACKET *, + uint32_t, uint8_t, struct in6_addr *); +int radius_put_ipv6_attr(RADIUS_PACKET *, + uint8_t, const struct in6_addr *); +int radius_put_vs_ipv6_attr(RADIUS_PACKET *, + uint32_t, uint8_t, const struct in6_addr *); +int radius_set_ipv6_attr(RADIUS_PACKET *, + uint8_t, const struct in6_addr *); +int radius_set_vs_ipv6_attr(RADIUS_PACKET *, + uint32_t, uint8_t, const struct in6_addr *); + +/* message authenticator */ +int radius_put_message_authenticator(RADIUS_PACKET *, + const char *); +int radius_set_message_authenticator(RADIUS_PACKET *, + const char *); +int radius_check_message_authenticator(RADIUS_PACKET *, + const char *); + +/* encryption */ +int radius_encrypt_user_password_attr(void *, size_t *, + const char *, const void *, const char *); +int radius_decrypt_user_password_attr(char *, size_t, + const void *, size_t, const void *, const char *); +int radius_encrypt_mppe_key_attr(void *, size_t *, + const void *, size_t, const void *, const char *); +int radius_decrypt_mppe_key_attr(void *, size_t *, const void *, + size_t, const void *, const char *); + +/* encrypted attribute */ +int radius_get_user_password_attr(const RADIUS_PACKET *, + char *, size_t, const char *); +int radius_put_user_password_attr(RADIUS_PACKET *, + const char *, const char *); +int radius_get_mppe_send_key_attr(const RADIUS_PACKET *, void *, + size_t *, const char *); +int radius_put_mppe_send_key_attr(RADIUS_PACKET *, + const void *, size_t, const char *); +int radius_get_mppe_recv_key_attr(const RADIUS_PACKET *, + void *, size_t *, const char *); +int radius_put_mppe_recv_key_attr(RADIUS_PACKET *, const void *, + size_t, const char *); + +int radius_get_eap_msk(const RADIUS_PACKET *, void *, size_t *, + const char *); + +/* helpers */ +RADIUS_PACKET *radius_recvfrom(int, int, struct sockaddr *, socklen_t *); +int radius_sendto(int, const RADIUS_PACKET *, int flags, + const struct sockaddr *, socklen_t); +RADIUS_PACKET *radius_recv(int, int); +int radius_send(int, const RADIUS_PACKET *, int); +RADIUS_PACKET *radius_recvmsg(int, struct msghdr *, int); +int radius_sendmsg(int, const RADIUS_PACKET *, + const struct msghdr *, int); + +__END_DECLS + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ranlib.h b/lib/libc/include/generic-openbsd/ranlib.h new file mode 100644 index 000000000000..2e7d5dc8d6e0 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ranlib.h @@ -0,0 +1,49 @@ +/* $OpenBSD: ranlib.h,v 1.3 2003/06/02 19:34:12 millert Exp $ */ +/* $NetBSD: ranlib.h,v 1.4 1994/10/26 00:56:14 cgd Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ranlib.h 5.2 (Berkeley) 4/3/91 + */ + +#ifndef _RANLIB_H_ +#define _RANLIB_H_ + +#define RANLIBMAG "__.SYMDEF" /* archive file name */ +#define RANLIBSKEW 3 /* creation time offset */ + +struct ranlib { + union { + long ran_strx; /* string table index */ + char *ran_name; /* in memory symbol name */ + } ran_un; + long ran_off; /* archive file offset */ +}; + +#endif /* !_RANLIB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/readpassphrase.h b/lib/libc/include/generic-openbsd/readpassphrase.h new file mode 100644 index 000000000000..34cdaa411e87 --- /dev/null +++ b/lib/libc/include/generic-openbsd/readpassphrase.h @@ -0,0 +1,40 @@ +/* $OpenBSD: readpassphrase.h,v 1.6 2019/01/25 00:19:25 millert Exp $ */ + +/* + * Copyright (c) 2000, 2002 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ + +#ifndef _READPASSPHRASE_H_ +#define _READPASSPHRASE_H_ + +#define RPP_ECHO_OFF 0x00 /* Turn off echo (default). */ +#define RPP_ECHO_ON 0x01 /* Leave echo on. */ +#define RPP_REQUIRE_TTY 0x02 /* Fail if there is no tty. */ +#define RPP_FORCELOWER 0x04 /* Force input to lower case. */ +#define RPP_FORCEUPPER 0x08 /* Force input to upper case. */ +#define RPP_SEVENBIT 0x10 /* Strip the high bit from input. */ +#define RPP_STDIN 0x20 /* Read from stdin, not /dev/tty */ + +#include + +__BEGIN_DECLS +char * readpassphrase(const char *, char *, size_t, int); +__END_DECLS + +#endif /* !_READPASSPHRASE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/regex.h b/lib/libc/include/generic-openbsd/regex.h new file mode 100644 index 000000000000..7c0763f81816 --- /dev/null +++ b/lib/libc/include/generic-openbsd/regex.h @@ -0,0 +1,104 @@ +/* $OpenBSD: regex.h,v 1.7 2012/12/05 23:19:57 deraadt Exp $ */ +/* $NetBSD: regex.h,v 1.4.6.1 1996/06/10 18:57:07 explorer Exp $ */ + +/*- + * Copyright (c) 1992 Henry Spencer. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer of the University of Toronto. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)regex.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _REGEX_H_ +#define _REGEX_H_ + +#include + +/* types */ +typedef off_t regoff_t; + +typedef struct { + int re_magic; + size_t re_nsub; /* number of parenthesized subexpressions */ + const char *re_endp; /* end pointer for REG_PEND */ + struct re_guts *re_g; /* none of your business :-) */ +} regex_t; + +typedef struct { + regoff_t rm_so; /* start of match */ + regoff_t rm_eo; /* end of match */ +} regmatch_t; + +/* regcomp() flags */ +#define REG_BASIC 0000 +#define REG_EXTENDED 0001 +#define REG_ICASE 0002 +#define REG_NOSUB 0004 +#define REG_NEWLINE 0010 +#define REG_NOSPEC 0020 +#define REG_PEND 0040 +#define REG_DUMP 0200 + +/* regerror() flags */ +#define REG_NOMATCH 1 +#define REG_BADPAT 2 +#define REG_ECOLLATE 3 +#define REG_ECTYPE 4 +#define REG_EESCAPE 5 +#define REG_ESUBREG 6 +#define REG_EBRACK 7 +#define REG_EPAREN 8 +#define REG_EBRACE 9 +#define REG_BADBR 10 +#define REG_ERANGE 11 +#define REG_ESPACE 12 +#define REG_BADRPT 13 +#define REG_EMPTY 14 +#define REG_ASSERT 15 +#define REG_INVARG 16 +#define REG_ATOI 255 /* convert name to number (!) */ +#define REG_ITOA 0400 /* convert number to name (!) */ + +/* regexec() flags */ +#define REG_NOTBOL 00001 +#define REG_NOTEOL 00002 +#define REG_STARTEND 00004 +#define REG_TRACE 00400 /* tracing of execution */ +#define REG_LARGE 01000 /* force large representation */ +#define REG_BACKR 02000 /* force use of backref code */ + +__BEGIN_DECLS +int regcomp(regex_t *, const char *, int); +size_t regerror(int, const regex_t *, char *, size_t); +int regexec(const regex_t *, const char *, size_t, regmatch_t [], int); +void regfree(regex_t *); +__END_DECLS + +#endif /* !_REGEX_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/resolv.h b/lib/libc/include/generic-openbsd/resolv.h new file mode 100644 index 000000000000..87b870b02894 --- /dev/null +++ b/lib/libc/include/generic-openbsd/resolv.h @@ -0,0 +1,314 @@ +/* $OpenBSD: resolv.h,v 1.23 2021/11/22 20:18:27 jca Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * ++Copyright++ 1983, 1987, 1989, 1993 + * - + * Copyright (c) 1983, 1987, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * - + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * - + * --Copyright-- + */ + +/* + * @(#)resolv.h 8.1 (Berkeley) 6/2/93 + * $From: resolv.h,v 8.17 1996/11/26 10:11:20 vixie Exp $ + */ + +#ifndef _RESOLV_H_ +#define _RESOLV_H_ + +#include +#include +#include + +/* + * Revision information. This is the release date in YYYYMMDD format. + * It can change every day so the right thing to do with it is use it + * in preprocessor commands such as "#if (__RES > 19931104)". Do not + * compare for equality; rather, use it to determine whether your resolver + * is new enough to contain a certain feature. + */ + +#define __RES 19960801 + +/* + * Resolver configuration file. + * Normally not present, but may contain the address of the + * initial name server(s) to query and the domain search list. + */ + +#ifndef _PATH_RESCONF +#define _PATH_RESCONF "/etc/resolv.conf" +#endif + +/* + * Global defines and variables for resolver stub. + */ +#define MAXNS 3 /* max # name servers we'll track */ +#define MAXDFLSRCH 3 /* # default domain levels to try */ +#define MAXDNSRCH 6 /* max # domains in search path */ +#define LOCALDOMAINPARTS 2 /* min levels in name that is "local" */ +#define MAXDNSLUS 4 /* max # of host lookup types */ + +#define RES_TIMEOUT 5 /* min. seconds between retries */ +#define MAXRESOLVSORT 10 /* number of net to sort on */ +#define RES_MAXNDOTS 15 /* should reflect bit field size */ + +struct __res_state { + int retrans; /* retransmission time interval */ + int retry; /* number of times to retransmit */ + unsigned int options; /* option flags - see below. */ + int nscount; /* number of name servers */ + int family[2]; /* specifies which address + * families will be queried and + * in which order */ + struct sockaddr_in + nsaddr_list[MAXNS]; /* address of name server */ +#define nsaddr nsaddr_list[0] /* for backward compatibility */ + unsigned short id; /* current message id */ + char *dnsrch[MAXDNSRCH+1]; /* components of domain to search */ + char defdname[256]; /* default domain (deprecated) */ + unsigned int pfcode; /* RES_PRF_ flags - see below. */ + unsigned ndots:4; /* threshold for initial abs. query */ + unsigned nsort:4; /* number of elements in sort_list[] */ + char unused[3]; + struct { + struct in_addr addr; + u_int32_t mask; + } sort_list[MAXRESOLVSORT]; + char lookups[MAXDNSLUS]; + struct { time_t __res_sec; long __res_nsec; } restimespec; + time_t reschktime; +}; + +#if 1 /* INET6 */ +/* + * replacement of __res_state, separated to keep binary compatibility. + */ +struct __res_state_ext { + struct sockaddr_storage nsaddr_list[MAXNS]; + struct { + int af; /* address family for addr, mask */ + union { + struct in_addr ina; + struct in6_addr in6a; + } addr, mask; + } sort_list[MAXRESOLVSORT]; +}; +#endif + + +/* + * Resolver options (keep these in synch with res_debug.c, please) + */ +#define RES_INIT 0x00000001 /* address initialized */ +#define RES_DEBUG 0x00000002 /* print debug messages */ +#define RES_AAONLY 0x00000004 /* authoritative answers only (!IMPL)*/ +#define RES_USEVC 0x00000008 /* use virtual circuit */ +#define RES_PRIMARY 0x00000010 /* query primary server only (!IMPL) */ +#define RES_IGNTC 0x00000020 /* ignore trucation errors */ +#define RES_RECURSE 0x00000040 /* recursion desired */ +#define RES_DEFNAMES 0x00000080 /* use default domain name */ +#define RES_STAYOPEN 0x00000100 /* Keep TCP socket open */ +#define RES_DNSRCH 0x00000200 /* search up local domain tree */ +#define RES_INSECURE1 0x00000400 /* type 1 security disabled */ +#define RES_INSECURE2 0x00000800 /* type 2 security disabled */ +#define RES_NOALIASES 0x00001000 /* shuts off HOSTALIASES feature */ +#define RES_USE_INET6 0x00002000 /* use/map IPv6 in gethostbyname() */ +/* KAME extensions: use higher bit to avoid conflict with ISC use */ +#define RES_USE_EDNS0 0x40000000 /* use EDNS0 */ +/* DNSSEC extensions: use higher bit to avoid conflict with ISC use */ +#define RES_USE_DNSSEC 0x20000000 /* use DNSSEC using OK bit in OPT */ +#define RES_USE_CD 0x10000000 /* set Checking Disabled flag */ +#define RES_TRUSTAD 0x80000000 /* Request AD, keep it in responses. */ + +#define RES_DEFAULT (RES_RECURSE | RES_DEFNAMES | RES_DNSRCH) + +/* + * Resolver "pfcode" values. Used by dig. + */ +#define RES_PRF_STATS 0x00000001 +/* 0x00000002 */ +#define RES_PRF_CLASS 0x00000004 +#define RES_PRF_CMD 0x00000008 +#define RES_PRF_QUES 0x00000010 +#define RES_PRF_ANS 0x00000020 +#define RES_PRF_AUTH 0x00000040 +#define RES_PRF_ADD 0x00000080 +#define RES_PRF_HEAD1 0x00000100 +#define RES_PRF_HEAD2 0x00000200 +#define RES_PRF_TTLID 0x00000400 +#define RES_PRF_HEADX 0x00000800 +#define RES_PRF_QUERY 0x00001000 +#define RES_PRF_REPLY 0x00002000 +#define RES_PRF_INIT 0x00004000 +/* 0x00008000 */ + +/* hooks are still experimental as of 4.9.2 */ +typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error } + res_sendhookact; + +typedef res_sendhookact (*res_send_qhook)(struct sockaddr_in * const *ns, + const unsigned char **query, + int *querylen, + unsigned char *ans, + int anssiz, + int *resplen); + +typedef res_sendhookact (*res_send_rhook)(const struct sockaddr_in *ns, + const unsigned char *query, + int querylen, + unsigned char *ans, + int anssiz, + int *resplen); + +struct res_sym { + int number; /* Identifying number, like T_MX */ + char * name; /* Its symbolic name, like "MX" */ + char * humanname; /* Its fun name, like "mail exchanger" */ +}; + +extern struct __res_state _res; +#if 1 /* INET6 */ +extern struct __res_state_ext _res_ext; +#endif +extern const struct res_sym __p_class_syms[]; +extern const struct res_sym __p_type_syms[]; + +/* Private routines shared between libc/net, named, nslookup and others. */ +#define res_hnok __res_hnok +#define res_ownok __res_ownok +#define res_mailok __res_mailok +#define res_dnok __res_dnok +#define sym_ntos __sym_ntos +#define b64_ntop __b64_ntop +#define b64_pton __b64_pton +#define dn_skipname __dn_skipname +#define putlong __putlong +#define putshort __putshort +#define p_class __p_class +#define p_type __p_type +#define dn_count_labels __dn_count_labels +#define dn_comp __dn_comp +#define res_randomid __res_randomid +#define res_send __res_send +#define res_opt __res_opt + +#ifdef BIND_RES_POSIX3 +#define dn_expand __dn_expand +#define res_init __res_init +#define res_query __res_query +#define res_search __res_search +#define res_querydomain __res_querydomain +#define res_mkquery __res_mkquery +#endif + +__BEGIN_DECLS +int res_hnok(const char *); +int res_ownok(const char *); +int res_mailok(const char *); +int res_dnok(const char *); +const char * sym_ntos(const struct res_sym *, int, int *); +int b64_ntop(unsigned char const *, size_t, char *, size_t); +int b64_pton(char const *, unsigned char *, size_t); +int dn_skipname(const unsigned char *, + const unsigned char *); +void putlong(u_int32_t, unsigned char *); +void putshort(u_int16_t, unsigned char *); +const char * p_class(int); +const char * p_type(int); +int dn_comp(const char *, unsigned char *, int, + unsigned char **, unsigned char **); +int dn_expand(const unsigned char *, const unsigned char *, + const unsigned char *, char *, int); +int res_init(void); +unsigned int res_randomid(void); +int res_query(const char *, int, int, unsigned char *, int) + __attribute__((__bounded__(__string__,4,5))); +int res_search(const char *, int, int, unsigned char *, int) + __attribute__((__bounded__(__string__,4,5))); +int res_querydomain(const char *, const char *, int, int, + unsigned char *, int) + __attribute__((__bounded__(__string__,5,6))); +int res_mkquery(int, const char *, int, int, + const unsigned char *, int, const unsigned char *, + unsigned char *, int) + __attribute__((__bounded__(__string__,5,6))) + __attribute__((__bounded__(__string__,8,9))); +int res_send(const unsigned char *, int, unsigned char *, + int) + __attribute__((__bounded__(__string__,3,4))); +__END_DECLS + +#endif /* !_RESOLV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/rmd160.h b/lib/libc/include/generic-openbsd/rmd160.h new file mode 100644 index 000000000000..b227c3fc7844 --- /dev/null +++ b/lib/libc/include/generic-openbsd/rmd160.h @@ -0,0 +1,60 @@ +/* $OpenBSD: rmd160.h,v 1.17 2012/12/05 23:19:57 deraadt Exp $ */ +/* + * Copyright (c) 2001 Markus Friedl. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _RMD160_H +#define _RMD160_H + +#define RMD160_BLOCK_LENGTH 64 +#define RMD160_DIGEST_LENGTH 20 +#define RMD160_DIGEST_STRING_LENGTH (RMD160_DIGEST_LENGTH * 2 + 1) + +/* RMD160 context. */ +typedef struct RMD160Context { + u_int32_t state[5]; /* state */ + u_int64_t count; /* number of bits, mod 2^64 */ + u_int8_t buffer[RMD160_BLOCK_LENGTH]; /* input buffer */ +} RMD160_CTX; + +__BEGIN_DECLS +void RMD160Init(RMD160_CTX *); +void RMD160Transform(u_int32_t [5], const u_int8_t [RMD160_BLOCK_LENGTH]) + __attribute__((__bounded__(__minbytes__,1,5))) + __attribute__((__bounded__(__minbytes__,2,RMD160_BLOCK_LENGTH))); +void RMD160Update(RMD160_CTX *, const u_int8_t *, size_t) + __attribute__((__bounded__(__string__,2,3))); +void RMD160Pad(RMD160_CTX *); +void RMD160Final(u_int8_t [RMD160_DIGEST_LENGTH], RMD160_CTX *) + __attribute__((__bounded__(__minbytes__,1,RMD160_DIGEST_LENGTH))); +char *RMD160End(RMD160_CTX *, char *) + __attribute__((__bounded__(__minbytes__,2,RMD160_DIGEST_STRING_LENGTH))); +char *RMD160File(const char *, char *) + __attribute__((__bounded__(__minbytes__,2,RMD160_DIGEST_STRING_LENGTH))); +char *RMD160FileChunk(const char *, char *, off_t, off_t) + __attribute__((__bounded__(__minbytes__,2,RMD160_DIGEST_STRING_LENGTH))); +char *RMD160Data(const u_int8_t *, size_t, char *) + __attribute__((__bounded__(__string__,1,2))) + __attribute__((__bounded__(__minbytes__,3,RMD160_DIGEST_STRING_LENGTH))); +__END_DECLS + +#endif /* _RMD160_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/rpc/auth.h b/lib/libc/include/generic-openbsd/rpc/auth.h new file mode 100644 index 000000000000..60b558ed3903 --- /dev/null +++ b/lib/libc/include/generic-openbsd/rpc/auth.h @@ -0,0 +1,184 @@ +/* $OpenBSD: auth.h,v 1.9 2022/02/14 03:38:59 guenther Exp $ */ +/* $NetBSD: auth.h,v 1.7 1995/04/29 05:27:55 cgd Exp $ */ + +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: @(#)auth.h 1.17 88/02/08 SMI + * @(#)auth.h 2.3 88/08/07 4.0 RPCSRC + */ + +/* + * auth.h, Authentication interface. + * + * The data structures are completely opaque to the client. The client + * is required to pass a AUTH * to routines that create rpc + * "sessions". + */ + +#ifndef _RPC_AUTH_H +#define _RPC_AUTH_H +#include + +#define MAX_AUTH_BYTES 400 +#define MAXNETNAMELEN 255 /* maximum length of network user's name */ + +/* + * Status returned from authentication check + */ +enum auth_stat { + AUTH_OK=0, + /* + * failed at remote end + */ + AUTH_BADCRED=1, /* bogus credentials (seal broken) */ + AUTH_REJECTEDCRED=2, /* client should begin new session */ + AUTH_BADVERF=3, /* bogus verifier (seal broken) */ + AUTH_REJECTEDVERF=4, /* verifier expired or was replayed */ + AUTH_TOOWEAK=5, /* rejected due to security reasons */ + /* + * failed locally + */ + AUTH_INVALIDRESP=6, /* bogus response verifier */ + AUTH_FAILED=7 /* some unknown reason */ +}; + +typedef u_int32_t u_int32; /* 32-bit unsigned integers */ + +union des_block { + struct { + u_int32 high; + u_int32 low; + } key; + char c[8]; +}; +typedef union des_block des_block; +__BEGIN_DECLS +extern bool_t xdr_des_block(XDR *, des_block *); +__END_DECLS + +/* + * Authentication info. Opaque to client. + */ +struct opaque_auth { + enum_t oa_flavor; /* flavor of auth */ + caddr_t oa_base; /* address of more auth stuff */ + unsigned int oa_length; /* not to exceed MAX_AUTH_BYTES */ +}; + + +/* + * Auth handle, interface to client side authenticators. + */ +typedef struct __rpc_auth { + struct opaque_auth ah_cred; + struct opaque_auth ah_verf; + union des_block ah_key; + const struct auth_ops { + void (*ah_nextverf)(struct __rpc_auth *); + /* nextverf & serialize */ + int (*ah_marshal)(struct __rpc_auth *, XDR *); + /* validate varifier */ + int (*ah_validate)(struct __rpc_auth *, + struct opaque_auth *); + /* refresh credentials */ + int (*ah_refresh)(struct __rpc_auth *); + /* destroy this structure */ + void (*ah_destroy)(struct __rpc_auth *); + } *ah_ops; + caddr_t ah_private; +} AUTH; + + +/* + * Authentication ops. + * The ops and the auth handle provide the interface to the authenticators. + * + * AUTH *auth; + * XDR *xdrs; + * struct opaque_auth verf; + */ +#define AUTH_NEXTVERF(auth) \ + ((*((auth)->ah_ops->ah_nextverf))(auth)) +#define auth_nextverf(auth) \ + ((*((auth)->ah_ops->ah_nextverf))(auth)) + +#define AUTH_MARSHALL(auth, xdrs) \ + ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) +#define auth_marshall(auth, xdrs) \ + ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) + +#define AUTH_VALIDATE(auth, verfp) \ + ((*((auth)->ah_ops->ah_validate))((auth), verfp)) +#define auth_validate(auth, verfp) \ + ((*((auth)->ah_ops->ah_validate))((auth), verfp)) + +#define AUTH_REFRESH(auth) \ + ((*((auth)->ah_ops->ah_refresh))(auth)) +#define auth_refresh(auth) \ + ((*((auth)->ah_ops->ah_refresh))(auth)) + +#define AUTH_DESTROY(auth) \ + ((*((auth)->ah_ops->ah_destroy))(auth)) +#define auth_destroy(auth) \ + ((*((auth)->ah_ops->ah_destroy))(auth)) + + +extern struct opaque_auth _null_auth; + + +/* + * These are the various implementations of client side authenticators. + */ + +/* + * Unix style authentication + * AUTH *authunix_create(machname, uid, gid, len, aup_gids) + * char *machname; + * int uid; + * int gid; + * int len; + * int *aup_gids; + */ +__BEGIN_DECLS +struct sockaddr_in; +extern AUTH *authunix_create(char *, int, int, int, int *); +extern AUTH *authunix_create_default(void); +extern AUTH *authnone_create(void); +extern void set_rpc_maxgrouplist(int); +__END_DECLS + +#define AUTH_NONE 0 /* no authentication */ +#define AUTH_NULL 0 /* backward compatibility */ +#define AUTH_UNIX 1 /* unix style (uid, gids) */ +#define AUTH_SHORT 2 /* short hand unix style */ +#define AUTH_DES 3 /* des style (encrypted timestamps) */ + +#endif /* !_RPC_AUTH_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/rpc/auth_unix.h b/lib/libc/include/generic-openbsd/rpc/auth_unix.h new file mode 100644 index 000000000000..29d79a460389 --- /dev/null +++ b/lib/libc/include/generic-openbsd/rpc/auth_unix.h @@ -0,0 +1,84 @@ +/* $OpenBSD: auth_unix.h,v 1.5 2010/09/01 14:43:34 millert Exp $ */ +/* $NetBSD: auth_unix.h,v 1.4 1994/10/26 00:56:56 cgd Exp $ */ + +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: @(#)auth_unix.h 1.8 88/02/08 SMI + * @(#)auth_unix.h 2.2 88/07/29 4.0 RPCSRC + */ + +/* + * auth_unix.h, Protocol for UNIX style authentication parameters for RPC + */ + +/* + * The system is very weak. The client uses no encryption for it + * credentials and only sends null verifiers. The server sends backs + * null verifiers or optionally a verifier that suggests a new short hand + * for the credentials. + */ + +#ifndef _RPC_AUTH_UNIX_H +#define _RPC_AUTH_UNIX_H +#include + +/* The machine name is part of a credential; it may not exceed 255 bytes */ +#define MAX_MACHINE_NAME 255 + +/* gids compose part of a credential; there may not be more than 16 of them */ +#define NGRPS 16 + +/* + * Unix style credentials. + */ +struct authunix_parms { + unsigned long aup_time; + char *aup_machname; + int aup_uid; + int aup_gid; + unsigned int aup_len; + int *aup_gids; +}; + +__BEGIN_DECLS +extern bool_t xdr_authunix_parms(XDR *, struct authunix_parms *); +__END_DECLS + +/* + * If a response verifier has flavor AUTH_SHORT, + * then the body of the response verifier encapsulates the following structure; + * again it is serialized in the obvious fashion. + */ +struct short_hand_verf { + struct opaque_auth new_cred; +}; + +#endif /* !_RPC_AUTH_UNIX_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/rpc/clnt.h b/lib/libc/include/generic-openbsd/rpc/clnt.h new file mode 100644 index 000000000000..2ce2198eba2d --- /dev/null +++ b/lib/libc/include/generic-openbsd/rpc/clnt.h @@ -0,0 +1,362 @@ +/* $OpenBSD: clnt.h,v 1.14 2022/12/27 07:44:56 jmc Exp $ */ +/* $NetBSD: clnt.h,v 1.6 1995/04/29 05:27:58 cgd Exp $ */ + +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: @(#)clnt.h 1.31 88/02/08 SMI + * @(#)clnt.h 2.1 88/07/29 4.0 RPCSRC + */ + +/* + * clnt.h - Client side remote procedure call interface. + */ + +#ifndef _RPC_CLNT_H_ +#define _RPC_CLNT_H_ +#include + +/* + * Rpc calls return an enum clnt_stat. This should be looked at more, + * since each implementation is required to live with this (implementation + * independent) list of errors. + */ +enum clnt_stat { + RPC_SUCCESS=0, /* call succeeded */ + /* + * local errors + */ + RPC_CANTENCODEARGS=1, /* can't encode arguments */ + RPC_CANTDECODERES=2, /* can't decode results */ + RPC_CANTSEND=3, /* failure in sending call */ + RPC_CANTRECV=4, /* failure in receiving result */ + RPC_TIMEDOUT=5, /* call timed out */ + /* + * remote errors + */ + RPC_VERSMISMATCH=6, /* rpc versions not compatible */ + RPC_AUTHERROR=7, /* authentication error */ + RPC_PROGUNAVAIL=8, /* program not available */ + RPC_PROGVERSMISMATCH=9, /* program version mismatched */ + RPC_PROCUNAVAIL=10, /* procedure unavailable */ + RPC_CANTDECODEARGS=11, /* decode arguments error */ + RPC_SYSTEMERROR=12, /* generic "other problem" */ + + /* + * callrpc & clnt_create errors + */ + RPC_UNKNOWNHOST=13, /* unknown host name */ + RPC_UNKNOWNPROTO=17, /* unknown protocol */ + + /* + * _ create errors + */ + RPC_PMAPFAILURE=14, /* the pmapper failed in its call */ + RPC_PROGNOTREGISTERED=15, /* remote program is not registered */ + /* + * unspecified error + */ + RPC_FAILED=16 +}; + + +/* + * Error info. + */ +struct rpc_err { + enum clnt_stat re_status; + union { + int RE_errno; /* related system error */ + enum auth_stat RE_why; /* why the auth error occurred */ + struct { + u_int32_t low; /* lowest version supported */ + u_int32_t high; /* highest version supported */ + } RE_vers; + struct { /* maybe meaningful if RPC_FAILED */ + int32_t s1; + int32_t s2; + } RE_lb; /* life boot & debugging only */ + } ru; +#define re_errno ru.RE_errno +#define re_why ru.RE_why +#define re_vers ru.RE_vers +#define re_lb ru.RE_lb +}; + + +/* + * Client rpc handle. + * Created by individual implementations, see e.g. rpc_udp.c. + * Client is responsible for initializing auth, see e.g. auth_none.c. + */ +typedef struct __rpc_client { + AUTH *cl_auth; /* authenticator */ + const struct clnt_ops { + /* call remote procedure */ + enum clnt_stat (*cl_call)(struct __rpc_client *, + unsigned long, xdrproc_t, caddr_t, + xdrproc_t, caddr_t, struct timeval); + /* abort a call */ + void (*cl_abort)(struct __rpc_client *); + /* get specific error code */ + void (*cl_geterr)(struct __rpc_client *, + struct rpc_err *); + /* frees results */ + bool_t (*cl_freeres)(struct __rpc_client *, + xdrproc_t, caddr_t); + /* destroy this structure */ + void (*cl_destroy)(struct __rpc_client *); + /* the ioctl() of rpc */ + bool_t (*cl_control)(struct __rpc_client *, + unsigned int, void *); + } *cl_ops; + caddr_t cl_private; /* private stuff */ +} CLIENT; + + +/* + * client side rpc interface ops + * + * Parameter types are: + * + */ + +/* + * enum clnt_stat + * CLNT_CALL(rh, proc, xargs, argsp, xres, resp, timeout) + * CLIENT *rh; + * unsigned long proc; + * xdrproc_t xargs; + * caddr_t argsp; + * xdrproc_t xres; + * caddr_t resp; + * struct timeval timeout; + */ +#define CLNT_CALL(rh, proc, xargs, argsp, xres, resp, secs) \ + ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, (caddr_t)argsp, \ + xres, (caddr_t)resp, secs)) +#define clnt_call(rh, proc, xargs, argsp, xres, resp, secs) \ + ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, (caddr_t)argsp, \ + xres, (caddr_t)resp, secs)) + +/* + * void + * CLNT_ABORT(rh); + * CLIENT *rh; + */ +#define CLNT_ABORT(rh) ((*(rh)->cl_ops->cl_abort)(rh)) +#define clnt_abort(rh) ((*(rh)->cl_ops->cl_abort)(rh)) + +/* + * struct rpc_err + * CLNT_GETERR(rh); + * CLIENT *rh; + */ +#define CLNT_GETERR(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp)) +#define clnt_geterr(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp)) + + +/* + * bool_t + * CLNT_FREERES(rh, xres, resp); + * CLIENT *rh; + * xdrproc_t xres; + * caddr_t resp; + */ +#define CLNT_FREERES(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp)) +#define clnt_freeres(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp)) + +/* + * bool_t + * CLNT_CONTROL(cl, request, info) + * CLIENT *cl; + * unsigned int request; + * char *info; + */ +#define CLNT_CONTROL(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in)) +#define clnt_control(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in)) + +/* + * control operations that apply to both udp and tcp transports + */ +#define CLSET_TIMEOUT 1 /* set timeout (timeval) */ +#define CLGET_TIMEOUT 2 /* get timeout (timeval) */ +#define CLGET_SERVER_ADDR 3 /* get server's address (sockaddr) */ +/* + * udp only control operations + */ +#define CLSET_RETRY_TIMEOUT 4 /* set retry timeout (timeval) */ +#define CLGET_RETRY_TIMEOUT 5 /* get retry timeout (timeval) */ +#define CLSET_CONNECTED 6 /* socket is connected, so use send() */ + +/* + * void + * CLNT_DESTROY(rh); + * CLIENT *rh; + */ +#define CLNT_DESTROY(rh) ((*(rh)->cl_ops->cl_destroy)(rh)) +#define clnt_destroy(rh) ((*(rh)->cl_ops->cl_destroy)(rh)) + + +/* + * RPCTEST is a test program which is accessible on every rpc + * transport/port. It is used for testing, performance evaluation, + * and network administration. + */ + +#define RPCTEST_PROGRAM ((unsigned long)1) +#define RPCTEST_VERSION ((unsigned long)1) +#define RPCTEST_NULL_PROC ((unsigned long)2) +#define RPCTEST_NULL_BATCH_PROC ((unsigned long)3) + +/* + * By convention, procedure 0 takes null arguments and returns them + */ + +#define NULLPROC ((unsigned int)0) + +/* + * Below are the client handle creation routines for the various + * implementations of client side rpc. They can return NULL if a + * creation failure occurs. + */ + +/* + * Memory based rpc (for speed check and testing) + * CLIENT * + * clntraw_create(prog, vers) + * unsigned long prog; + * unsigned long vers; + */ +__BEGIN_DECLS +extern CLIENT *clntraw_create(unsigned long, unsigned long); +__END_DECLS + + +/* + * Generic client creation routine. Supported protocols are "udp" and "tcp" + * CLIENT * + * clnt_create(host, prog, vers, prot); + * char *host; -- hostname + * unsigned long prog; -- program number + * unsigned long vers; -- version number + * char *prot; -- protocol + */ +__BEGIN_DECLS +extern CLIENT *clnt_create(char *, unsigned long, unsigned long, char *); +__END_DECLS + + +/* + * TCP based rpc + * CLIENT * + * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) + * struct sockaddr_in *raddr; + * unsigned long prog; + * unsigned long version; + * int *sockp; + * unsigned int sendsz; + * unsigned int recvsz; + */ +__BEGIN_DECLS +extern CLIENT *clnttcp_create(struct sockaddr_in *, unsigned long, + unsigned long, int *, unsigned int, unsigned int); +__END_DECLS + + +/* + * UDP based rpc. + * CLIENT * + * clntudp_create(raddr, program, version, wait, sockp) + * struct sockaddr_in *raddr; + * unsigned long program; + * unsigned long version; + * struct timeval wait; + * int *sockp; + * + * Same as above, but you specify max packet sizes. + * CLIENT * + * clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz) + * struct sockaddr_in *raddr; + * unsigned long program; + * unsigned long version; + * struct timeval wait; + * int *sockp; + * unsigned int sendsz; + * unsigned int recvsz; + */ +__BEGIN_DECLS +extern CLIENT *clntudp_create(struct sockaddr_in *, unsigned long, + unsigned long, struct timeval, int *); +extern CLIENT *clntudp_bufcreate(struct sockaddr_in *, unsigned long, + unsigned long, struct timeval, int *, unsigned int, unsigned int); +__END_DECLS + + +/* + * Print why creation failed + */ +__BEGIN_DECLS +extern void clnt_pcreateerror(char *); /* stderr */ +extern char *clnt_spcreateerror(char *); /* string */ +__END_DECLS + +/* + * Like clnt_perror(), but is more verbose in its output + */ +__BEGIN_DECLS +extern void clnt_perrno(enum clnt_stat); /* stderr */ +extern char *clnt_sperrno(enum clnt_stat); /* string */ +__END_DECLS + +/* + * Print an English error message, given the client error code + */ +__BEGIN_DECLS +extern void clnt_perror(CLIENT *, char *); /* stderr */ +extern char *clnt_sperror(CLIENT *, char *); /* string */ +__END_DECLS + + +/* + * If a creation fails, the following allows the user to figure out why. + */ +struct rpc_createerr { + enum clnt_stat cf_stat; + struct rpc_err cf_error; /* useful when cf_stat == RPC_PMAPFAILURE */ +}; + +extern struct rpc_createerr rpc_createerr; + + +#define UDPMSGSIZE 8800 /* rpc imposed limit on udp msg size */ +#define RPCSMALLMSGSIZE 400 /* a more reasonable packet size */ + +#endif /* !_RPC_CLNT_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/rpc/pmap_clnt.h b/lib/libc/include/generic-openbsd/rpc/pmap_clnt.h new file mode 100644 index 000000000000..c9e7f04a91d0 --- /dev/null +++ b/lib/libc/include/generic-openbsd/rpc/pmap_clnt.h @@ -0,0 +1,85 @@ +/* $OpenBSD: pmap_clnt.h,v 1.7 2010/09/01 14:43:34 millert Exp $ */ +/* $NetBSD: pmap_clnt.h,v 1.5 1994/12/04 01:12:42 cgd Exp $ */ + +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: @(#)pmap_clnt.h 1.11 88/02/08 SMI + * @(#)pmap_clnt.h 2.1 88/07/29 4.0 RPCSRC + */ + +/* + * pmap_clnt.h + * Supplies C routines to get to portmap services. + */ + +/* + * Usage: + * success = pmap_set(program, version, protocol, port); + * success = pmap_unset(program, version); + * port = pmap_getport(address, program, version, protocol); + * head = pmap_getmaps(address); + * clnt_stat = pmap_rmtcall(address, program, version, procedure, + * xdrargs, argsp, xdrres, resp, tout, port_ptr) + * (works for udp only.) + * clnt_stat = clnt_broadcast(program, version, procedure, + * xdrargs, argsp, xdrres, resp, eachresult) + * (like pmap_rmtcall, except the call is broadcasted to all + * locally connected nets. For each valid response received, + * the procedure eachresult is called. Its form is: + * done = eachresult(resp, raddr) + * bool_t done; + * caddr_t resp; + * struct sockaddr_in raddr; + * where resp points to the results of the call and raddr is the + * address if the responder to the broadcast. + */ + +#ifndef _RPC_PMAPCLNT_H +#define _RPC_PMAPCLNT_H +#include + +__BEGIN_DECLS +extern bool_t pmap_set(unsigned long, unsigned long, unsigned int, + int); +extern bool_t pmap_unset(unsigned long, unsigned long); +extern struct pmaplist *pmap_getmaps(struct sockaddr_in *); +extern enum clnt_stat pmap_rmtcall(struct sockaddr_in *, unsigned long, + unsigned long, unsigned long, xdrproc_t, caddr_t, + xdrproc_t, caddr_t, struct timeval, + unsigned long *); +extern enum clnt_stat clnt_broadcast(unsigned long, unsigned long, + unsigned long, xdrproc_t, char *, xdrproc_t, char *, + bool_t (*)(caddr_t, struct sockaddr_in *)); +extern unsigned short pmap_getport(struct sockaddr_in *, unsigned long, + unsigned long, unsigned int); +__END_DECLS + +#endif /* !_RPC_PMAPCLNT_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/rpc/pmap_prot.h b/lib/libc/include/generic-openbsd/rpc/pmap_prot.h new file mode 100644 index 000000000000..4b13fc61e684 --- /dev/null +++ b/lib/libc/include/generic-openbsd/rpc/pmap_prot.h @@ -0,0 +1,106 @@ +/* $OpenBSD: pmap_prot.h,v 1.6 2010/09/01 14:43:34 millert Exp $ */ +/* $NetBSD: pmap_prot.h,v 1.4 1994/10/26 00:57:00 cgd Exp $ */ + +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: @(#)pmap_prot.h 1.14 88/02/08 SMI + * @(#)pmap_prot.h 2.1 88/07/29 4.0 RPCSRC + */ + +/* + * pmap_prot.h + * Protocol for the local binder service, or pmap. + * + * The following procedures are supported by the protocol: + * + * PMAPPROC_NULL() returns () + * takes nothing, returns nothing + * + * PMAPPROC_SET(struct pmap) returns (bool_t) + * TRUE is success, FALSE is failure. Registers the tuple + * [prog, vers, prot, port]. + * + * PMAPPROC_UNSET(struct pmap) returns (bool_t) + * TRUE is success, FALSE is failure. Un-registers pair + * [prog, vers]. prot and port are ignored. + * + * PMAPPROC_GETPORT(struct pmap) returns (unsigned long). + * 0 is failure. Otherwise returns the port number where the pair + * [prog, vers] is registered. It may lie! + * + * PMAPPROC_DUMP() RETURNS (struct pmaplist *) + * + * PMAPPROC_CALLIT(unsigned int, unsigned int, unsigned int, string<>) + * RETURNS (port, string<>); + * usage: encapsulatedresults = PMAPPROC_CALLIT(prog, vers, proc, encapsulatedargs); + * Calls the procedure on the local machine. If it is not registered, + * this procedure is quite; ie it does not return error information!!! + * This procedure only is supported on rpc/udp and calls via + * rpc/udp. This routine only passes null authentication parameters. + * This file has no interface to xdr routines for PMAPPROC_CALLIT. + * + * The service supports remote procedure calls on udp/ip or tcp/ip socket 111. + */ + +#ifndef _RPC_PMAPPROT_H +#define _RPC_PMAPPROT_H +#include + +#define PMAPPORT ((unsigned short)111) +#define PMAPPROG ((unsigned long)100000) +#define PMAPVERS ((unsigned long)2) +#define PMAPVERS_PROTO ((unsigned long)2) +#define PMAPVERS_ORIG ((unsigned long)1) +#define PMAPPROC_NULL ((unsigned long)0) +#define PMAPPROC_SET ((unsigned long)1) +#define PMAPPROC_UNSET ((unsigned long)2) +#define PMAPPROC_GETPORT ((unsigned long)3) +#define PMAPPROC_DUMP ((unsigned long)4) +#define PMAPPROC_CALLIT ((unsigned long)5) + +struct pmap { + unsigned long pm_prog; + unsigned long pm_vers; + unsigned long pm_prot; + unsigned long pm_port; +}; + +struct pmaplist { + struct pmap pml_map; + struct pmaplist *pml_next; +}; + +__BEGIN_DECLS +extern bool_t xdr_pmap(XDR *, struct pmap *); +extern bool_t xdr_pmaplist(XDR *, struct pmaplist **); +__END_DECLS + +#endif /* !_RPC_PMAPPROT_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/rpc/pmap_rmt.h b/lib/libc/include/generic-openbsd/rpc/pmap_rmt.h new file mode 100644 index 000000000000..9be70c44ce4b --- /dev/null +++ b/lib/libc/include/generic-openbsd/rpc/pmap_rmt.h @@ -0,0 +1,65 @@ +/* $OpenBSD: pmap_rmt.h,v 1.5 2010/09/01 14:43:34 millert Exp $ */ +/* $NetBSD: pmap_rmt.h,v 1.4 1994/10/26 00:57:01 cgd Exp $ */ + +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: @(#)pmap_rmt.h 1.2 88/02/08 SMI + * @(#)pmap_rmt.h 2.1 88/07/29 4.0 RPCSRC + */ + +/* + * Structures and XDR routines for parameters to and replies from + * the portmapper remote-call-service. + */ + +#ifndef _RPC_PMAPRMT_H +#define _RPC_PMAPRMT_H +#include + +struct rmtcallargs { + unsigned long prog, vers, proc, arglen; + caddr_t args_ptr; + xdrproc_t xdr_args; +}; + +struct rmtcallres { + unsigned long *port_ptr; + unsigned long resultslen; + caddr_t results_ptr; + xdrproc_t xdr_results; +}; + +__BEGIN_DECLS +extern bool_t xdr_rmtcall_args(XDR *, struct rmtcallargs *); +extern bool_t xdr_rmtcallres(XDR *, struct rmtcallres *); +__END_DECLS + +#endif /* !_RPC_PMAPRMT_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/rpc/rpc.h b/lib/libc/include/generic-openbsd/rpc/rpc.h new file mode 100644 index 000000000000..69d319138029 --- /dev/null +++ b/lib/libc/include/generic-openbsd/rpc/rpc.h @@ -0,0 +1,108 @@ +/* $OpenBSD: rpc.h,v 1.11 2010/09/01 14:43:34 millert Exp $ */ +/* $NetBSD: rpc.h,v 1.5 1994/12/04 01:15:30 cgd Exp $ */ + +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: @(#)rpc.h 1.9 88/02/08 SMI + * @(#)rpc.h 2.4 89/07/11 4.0 RPCSRC + */ + +/* + * rpc.h, Just includes the billions of rpc header files necessary to + * do remote procedure calling. + */ +#ifndef _RPC_RPC_H +#define _RPC_RPC_H + +#include /* some typedefs */ +#include + +/* external data representation interfaces */ +#include /* generic (de)serializer */ + +/* Client side only authentication */ +#include /* generic authenticator (client side) */ + +/* Client side (mostly) remote procedure call */ +#include /* generic rpc stuff */ + +/* Client side (mostly) pmap functions */ +#include /* generic pmap stuff */ + +/* semi-private protocol headers */ +#include /* protocol for rpc messages */ +#include /* protocol for unix style cred */ +/* + * Uncomment-out the next line if you are building the rpc library with + * DES Authentication (see the README file in the secure_rpc/ directory). + */ +#ifdef notdef +#include /* protocol for des style cred */ +#endif + +/* Server side only remote procedure callee */ +#include /* service manager and multiplexer */ +#include /* service side authenticator */ + +/* + * COMMENT OUT THE NEXT INCLUDE (or add to the #ifndef) IF RUNNING ON + * A VERSION OF UNIX THAT USES SUN'S NFS SOURCE. These systems will + * already have the structures defined by included in . + */ +/* routines for parsing /etc/rpc */ + +struct rpcent { + char *r_name; /* name of server for this rpc program */ + char **r_aliases; /* alias list */ + int r_number; /* rpc program number */ +}; + +__BEGIN_DECLS +extern struct rpcent *getrpcbyname(char *); +extern struct rpcent *getrpcbynumber(int); +extern struct rpcent *getrpcent(void); +extern void setrpcent(int); +extern void endrpcent(void); + +extern int get_myaddress(struct sockaddr_in *); +extern int registerrpc(int, int, int, char *(*)(char [UDPMSGSIZE]), + xdrproc_t, xdrproc_t); +extern int callrpc(char *, int, int, int, xdrproc_t, char *, + xdrproc_t , char *); +extern int getrpcport(char *, int, int, int); + +extern bool_t xdr_opaque_auth(XDR *, struct opaque_auth *); + +extern int _rpc_dtablesize(void); + +__END_DECLS + +#endif /* !_RPC_RPC_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/rpc/rpc_des.h b/lib/libc/include/generic-openbsd/rpc/rpc_des.h new file mode 100644 index 000000000000..272ff423ed3b --- /dev/null +++ b/lib/libc/include/generic-openbsd/rpc/rpc_des.h @@ -0,0 +1,134 @@ +/* $OpenBSD: rpc_des.h,v 1.4 2010/09/01 14:43:34 millert Exp $ */ + +/* crypto/des/rpc_des.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@mincom.oz.au). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@mincom.oz.au). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * 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 copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@mincom.oz.au)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* @(#)des.h 2.2 88/08/10 4.0 RPCSRC; from 2.7 88/02/08 SMI */ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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. + */ + +/* + * Generic DES driver interface + * Keep this file hardware independent! + */ + +#define DES_MAXLEN 65536 /* maximum # of bytes to encrypt */ +#define DES_QUICKLEN 16 /* maximum # of bytes to encrypt quickly */ + +#ifdef HEADER_DES_H +#undef ENCRYPT +#undef DECRYPT +#endif + +enum desdir { ENCRYPT, DECRYPT }; +enum desmode { CBC, ECB }; + +/* + * parameters to ioctl call + */ +struct desparams { + unsigned char des_key[8]; /* key (with low bit parity) */ + enum desdir des_dir; /* direction */ + enum desmode des_mode; /* mode */ + unsigned char des_ivec[8]; /* input vector */ + unsigned int des_len; /* number of bytes to crypt */ + union { + unsigned char UDES_data[DES_QUICKLEN]; + unsigned char *UDES_buf; + } UDES; +# define des_data UDES.UDES_data /* direct data here if quick */ +# define des_buf UDES.UDES_buf /* otherwise, pointer to data */ +}; + +/* + * Encrypt an arbitrary sized buffer + */ +#define DESIOCBLOCK _IOWR(d, 6, struct desparams) + +/* + * Encrypt of small amount of data, quickly + */ +#define DESIOCQUICK _IOWR(d, 7, struct desparams) \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/rpc/rpc_msg.h b/lib/libc/include/generic-openbsd/rpc/rpc_msg.h new file mode 100644 index 000000000000..cabe4c54f174 --- /dev/null +++ b/lib/libc/include/generic-openbsd/rpc/rpc_msg.h @@ -0,0 +1,200 @@ +/* $OpenBSD: rpc_msg.h,v 1.7 2014/10/29 04:34:21 guenther Exp $ */ +/* $NetBSD: rpc_msg.h,v 1.5 1995/04/29 05:28:00 cgd Exp $ */ + +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: @(#)rpc_msg.h 1.7 86/07/16 SMI + * @(#)rpc_msg.h 2.1 88/07/29 4.0 RPCSRC + */ + +/* + * rpc_msg.h + * rpc message definition + */ + +#ifndef _RPC_RPCMSG_H +#define _RPC_RPCMSG_H + +#define RPC_MSG_VERSION ((unsigned long) 2) +#define RPC_SERVICE_PORT ((unsigned short) 2048) + +/* + * Bottom up definition of an rpc message. + * NOTE: call and reply use the same overall struct but + * different parts of unions within it. + */ + +enum msg_type { + CALL=0, + REPLY=1 +}; + +enum reply_stat { + MSG_ACCEPTED=0, + MSG_DENIED=1 +}; + +enum accept_stat { + SUCCESS=0, + PROG_UNAVAIL=1, + PROG_MISMATCH=2, + PROC_UNAVAIL=3, + GARBAGE_ARGS=4, + SYSTEM_ERR=5 +}; + +enum reject_stat { + RPC_MISMATCH=0, + AUTH_ERROR=1 +}; + +/* + * Reply part of an rpc exchange + */ + +/* + * Reply to an rpc request that was accepted by the server. + * Note: there could be an error even though the request was + * accepted. + */ +struct accepted_reply { + struct opaque_auth ar_verf; + enum accept_stat ar_stat; + union { + struct { + u_int32_t low; + u_int32_t high; + } AR_versions; + struct { + caddr_t where; + xdrproc_t proc; + } AR_results; + /* and many other null cases */ + } ru; +#define ar_results ru.AR_results +#define ar_vers ru.AR_versions +}; + +/* + * Reply to an rpc request that was rejected by the server. + */ +struct rejected_reply { + enum reject_stat rj_stat; + union { + struct { + u_int32_t low; + u_int32_t high; + } RJ_versions; + enum auth_stat RJ_why; /* why authentication did not work */ + } ru; +#define rj_vers ru.RJ_versions +#define rj_why ru.RJ_why +}; + +/* + * Body of a reply to an rpc request. + */ +struct reply_body { + enum reply_stat rp_stat; + union { + struct accepted_reply RP_ar; + struct rejected_reply RP_dr; + } ru; +#define rp_acpt ru.RP_ar +#define rp_rjct ru.RP_dr +}; + +/* + * Body of an rpc request call. + */ +struct call_body { + u_int32_t cb_rpcvers; /* must be equal to two */ + u_int32_t cb_prog; + u_int32_t cb_vers; + u_int32_t cb_proc; + struct opaque_auth cb_cred; + struct opaque_auth cb_verf; /* protocol specific - provided by client */ +}; + +/* + * The rpc message + */ +struct rpc_msg { + u_int32_t rm_xid; + enum msg_type rm_direction; + union { + struct call_body RM_cmb; + struct reply_body RM_rmb; + } ru; +#define rm_call ru.RM_cmb +#define rm_reply ru.RM_rmb +}; +#define acpted_rply ru.RM_rmb.ru.RP_ar +#define rjcted_rply ru.RM_rmb.ru.RP_dr + +__BEGIN_DECLS +/* + * XDR routine to handle a rpc message. + * xdr_callmsg(xdrs, cmsg) + * XDR *xdrs; + * struct rpc_msg *cmsg; + */ +extern bool_t xdr_callmsg(XDR *, struct rpc_msg *); + +/* + * XDR routine to pre-serialize the static part of a rpc message. + * xdr_callhdr(xdrs, cmsg) + * XDR *xdrs; + * struct rpc_msg *cmsg; + */ +extern bool_t xdr_callhdr(XDR *, struct rpc_msg *); + +/* + * XDR routine to handle a rpc reply. + * xdr_replymsg(xdrs, rmsg) + * XDR *xdrs; + * struct rpc_msg *rmsg; + */ +extern bool_t xdr_replymsg(XDR *, struct rpc_msg *); + +extern bool_t xdr_accepted_reply(XDR *, struct accepted_reply *); +extern bool_t xdr_rejected_reply(XDR *, struct rejected_reply *); + +/* + * Fills in the error part of a reply message. + * _seterr_reply(msg, error) + * struct rpc_msg *msg; + * struct rpc_err *error; + */ +extern void _seterr_reply(struct rpc_msg *, struct rpc_err *); +__END_DECLS + +#endif /* !_RPC_RPCMSG_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/rpc/svc.h b/lib/libc/include/generic-openbsd/rpc/svc.h new file mode 100644 index 000000000000..f505af9fb1f5 --- /dev/null +++ b/lib/libc/include/generic-openbsd/rpc/svc.h @@ -0,0 +1,326 @@ +/* $OpenBSD: svc.h,v 1.17 2022/02/14 03:38:59 guenther Exp $ */ +/* $NetBSD: svc.h,v 1.9 1995/04/29 05:28:01 cgd Exp $ */ + +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: @(#)svc.h 1.20 88/02/08 SMI + * @(#)svc.h 2.2 88/07/29 4.0 RPCSRC + */ + +/* + * svc.h, Server-side remote procedure call interface. + */ + +#ifndef _RPC_SVC_H +#define _RPC_SVC_H +#include +#include + +/* + * This interface must manage two items concerning remote procedure calling: + * + * 1) An arbitrary number of transport connections upon which rpc requests + * are received. The two most notable transports are TCP and UDP; they are + * created and registered by routines in svc_tcp.c and svc_udp.c, respectively; + * they in turn call xprt_register and xprt_unregister. + * + * 2) An arbitrary number of locally registered services. Services are + * described by the following four data: program number, version number, + * "service dispatch" function, a transport handle, and a boolean that + * indicates whether or not the exported program should be registered with a + * local binder service; if true the program's number and version and the + * port number from the transport handle are registered with the binder. + * These data are registered with the rpc svc system via svc_register. + * + * A service's dispatch function is called whenever an rpc request comes in + * on a transport. The request's program and version numbers must match + * those of the registered service. The dispatch function is passed two + * parameters, struct svc_req * and SVCXPRT *, defined below. + */ + +enum xprt_stat { + XPRT_DIED, + XPRT_MOREREQS, + XPRT_IDLE +}; + +/* + * Server side transport handle + */ +typedef struct __rpc_svcxprt { + int xp_sock; + unsigned short xp_port; /* associated port number */ + const struct xp_ops { + /* receive incoming requests */ + bool_t (*xp_recv)(struct __rpc_svcxprt *, + struct rpc_msg *); + /* get transport status */ + enum xprt_stat (*xp_stat)(struct __rpc_svcxprt *); + /* get arguments */ + bool_t (*xp_getargs)(struct __rpc_svcxprt *, xdrproc_t, + caddr_t); + /* send reply */ + bool_t (*xp_reply)(struct __rpc_svcxprt *, struct rpc_msg *); + /* free mem allocated for args */ + bool_t (*xp_freeargs)(struct __rpc_svcxprt *, xdrproc_t, + caddr_t); + /* destroy this struct */ + void (*xp_destroy)(struct __rpc_svcxprt *); + } *xp_ops; + socklen_t xp_addrlen; /* length of remote address */ + struct sockaddr_in xp_raddr; /* remote address */ + struct opaque_auth xp_verf; /* raw response verifier */ + caddr_t xp_p1; /* private */ + caddr_t xp_p2; /* private */ +} SVCXPRT; + +/* + * Approved way of getting address of caller + */ +#define svc_getcaller(x) (&(x)->xp_raddr) + +/* + * Operations defined on an SVCXPRT handle + * + * SVCXPRT *xprt; + * struct rpc_msg *msg; + * xdrproc_t xargs; + * caddr_t argsp; + */ +#define SVC_RECV(xprt, msg) \ + (*(xprt)->xp_ops->xp_recv)((xprt), (msg)) +#define svc_recv(xprt, msg) \ + (*(xprt)->xp_ops->xp_recv)((xprt), (msg)) + +#define SVC_STAT(xprt) \ + (*(xprt)->xp_ops->xp_stat)(xprt) +#define svc_stat(xprt) \ + (*(xprt)->xp_ops->xp_stat)(xprt) + +#define SVC_GETARGS(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp)) +#define svc_getargs(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp)) + +#define SVC_REPLY(xprt, msg) \ + (*(xprt)->xp_ops->xp_reply) ((xprt), (msg)) +#define svc_reply(xprt, msg) \ + (*(xprt)->xp_ops->xp_reply) ((xprt), (msg)) + +#define SVC_FREEARGS(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp)) +#define svc_freeargs(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp)) + +#define SVC_DESTROY(xprt) \ + (*(xprt)->xp_ops->xp_destroy)(xprt) +#define svc_destroy(xprt) \ + (*(xprt)->xp_ops->xp_destroy)(xprt) + + +/* + * Service request + */ +struct svc_req { + u_int32_t rq_prog; /* service program number */ + u_int32_t rq_vers; /* service protocol version */ + u_int32_t rq_proc; /* the desired procedure */ + struct opaque_auth rq_cred; /* raw creds from the wire */ + caddr_t rq_clntcred; /* read only cooked cred */ + SVCXPRT *rq_xprt; /* associated transport */ +}; + + +/* + * Service registration + * + * svc_register(xprt, prog, vers, dispatch, protocol) + * SVCXPRT *xprt; + * unsigned long prog; + * unsigned long vers; + * void (*dispatch)(); + * int protocol; like TCP or UDP, zero means do not register + */ +__BEGIN_DECLS +extern bool_t svc_register(SVCXPRT *, unsigned long, unsigned long, + void (*)(struct svc_req *, SVCXPRT *), int); +__END_DECLS + +/* + * Service un-registration + * + * svc_unregister(prog, vers) + * unsigned long prog; + * unsigned long vers; + */ +__BEGIN_DECLS +extern void svc_unregister(unsigned long, unsigned long); +__END_DECLS + +/* + * Transport registration. + * + * xprt_register(xprt) + * SVCXPRT *xprt; + */ +__BEGIN_DECLS +extern void xprt_register(SVCXPRT *); +__END_DECLS + +/* + * Transport un-register + * + * xprt_unregister(xprt) + * SVCXPRT *xprt; + */ +__BEGIN_DECLS +extern void xprt_unregister(SVCXPRT *); +__END_DECLS + + + + +/* + * When the service routine is called, it must first check to see if it + * knows about the procedure; if not, it should call svcerr_noproc + * and return. If so, it should deserialize its arguments via + * SVC_GETARGS (defined above). If the deserialization does not work, + * svcerr_decode should be called followed by a return. Successful + * decoding of the arguments should be followed the execution of the + * procedure's code and a call to svc_sendreply. + * + * Also, if the service refuses to execute the procedure due to too- + * weak authentication parameters, svcerr_weakauth should be called. + * Note: do not confuse access-control failure with weak authentication! + * + * NB: In pure implementations of rpc, the caller always waits for a reply + * msg. This message is sent when svc_sendreply is called. + * Therefore pure service implementations should always call + * svc_sendreply even if the function logically returns void; use + * xdr.h - xdr_void for the xdr routine. HOWEVER, tcp based rpc allows + * for the abuse of pure rpc via batched calling or pipelining. In the + * case of a batched call, svc_sendreply should NOT be called since + * this would send a return message, which is what batching tries to avoid. + * It is the service/protocol writer's responsibility to know which calls are + * batched and which are not. Warning: responding to batch calls may + * deadlock the caller and server processes! + */ + +__BEGIN_DECLS +extern bool_t svc_sendreply(SVCXPRT *, xdrproc_t, char *); +extern void svcerr_decode(SVCXPRT *); +extern void svcerr_weakauth(SVCXPRT *); +extern void svcerr_noproc(SVCXPRT *); +extern void svcerr_progvers(SVCXPRT *, unsigned long, unsigned long); +extern void svcerr_auth(SVCXPRT *, enum auth_stat); +extern void svcerr_noprog(SVCXPRT *); +extern void svcerr_systemerr(SVCXPRT *); +__END_DECLS + +/* + * Lowest level dispatching -OR- who owns this process anyway. + * Somebody has to wait for incoming requests and then call the correct + * service routine. The routine svc_run does infinite waiting; i.e., + * svc_run never returns. + * Since another (co-existent) package may wish to selectively wait for + * incoming calls or other events outside of the rpc architecture, the + * routine svc_getreq is provided. It must be passed readfds, the + * "in-place" results of a select system call (see select, section 2). + */ + +/* + * Global keeper of rpc service descriptors in use + * dynamic; must be inspected before each call to select + */ +#include /* for fd_set */ +extern fd_set svc_fdset; +#define svc_fds svc_fdset.fds_bits[0] /* compatibility */ +extern struct pollfd *svc_pollfd; +extern int svc_max_pollfd; +extern int svc_maxfd; /* non-standard */ + +/* + * a small program implemented by the svc_rpc implementation itself; + * also see clnt.h for protocol numbers. + */ +extern void rpctest_service(); /* XXX relic? */ + +__BEGIN_DECLS +extern void svc_getreq(int); +extern void svc_getreq_common(int); +extern void svc_getreq_poll(struct pollfd *, const int); +extern void svc_getreqset(fd_set *); +extern void svc_getreqset2(fd_set *, int); +extern void svc_run(void); +__END_DECLS + +/* + * Socket to use on svcxxx_create call to get default socket + */ +#define RPC_ANYSOCK -1 + +/* + * These are the existing service side transport implementations + */ + +/* + * Memory based rpc for testing and timing. + */ +__BEGIN_DECLS +extern SVCXPRT *svcraw_create(void); +__END_DECLS + + +/* + * Udp based rpc. + */ +__BEGIN_DECLS +extern SVCXPRT *svcudp_create(int); +extern SVCXPRT *svcudp_bufcreate(int, unsigned int, unsigned int); +extern int svcudp_enablecache(SVCXPRT *, u_long); +__END_DECLS + + +/* + * Tcp based rpc. + */ +__BEGIN_DECLS +extern SVCXPRT *svctcp_create(int, unsigned int, unsigned int); +__END_DECLS + +/* + * Fd based rpc. + */ +__BEGIN_DECLS +extern SVCXPRT *svcfd_create(int, unsigned int, unsigned int); +__END_DECLS + +#endif /* !_RPC_SVC_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/rpc/svc_auth.h b/lib/libc/include/generic-openbsd/rpc/svc_auth.h new file mode 100644 index 000000000000..5690dbee0966 --- /dev/null +++ b/lib/libc/include/generic-openbsd/rpc/svc_auth.h @@ -0,0 +1 @@ +/* this file intentionally left blank */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/rpc/types.h b/lib/libc/include/generic-openbsd/rpc/types.h new file mode 100644 index 000000000000..50ef3c4dde9d --- /dev/null +++ b/lib/libc/include/generic-openbsd/rpc/types.h @@ -0,0 +1,66 @@ +/* $OpenBSD: types.h,v 1.3 2010/09/01 14:43:34 millert Exp $ */ +/* $NetBSD: types.h,v 1.8 1995/04/29 05:28:05 cgd Exp $ */ + +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: @(#)types.h 1.18 87/07/24 SMI + * @(#)types.h 2.3 88/08/15 4.0 RPCSRC + */ + +/* + * Rpc additions to + */ +#ifndef _RPC_TYPES_H +#define _RPC_TYPES_H + +#define bool_t int32_t +#define enum_t int32_t +#define __dontcare__ -1 + +#ifndef FALSE +# define FALSE (0) +#endif +#ifndef TRUE +# define TRUE (1) +#endif +#ifndef NULL +# define NULL 0 +#endif + +#define mem_alloc(bsize) malloc(bsize) +#define mem_free(ptr, bsize) free(ptr) + +#ifndef makedev /* ie, we haven't already included it */ +#include +#endif +#include + +#endif /* !_RPC_TYPES_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/rpc/xdr.h b/lib/libc/include/generic-openbsd/rpc/xdr.h new file mode 100644 index 000000000000..f323aa2721d2 --- /dev/null +++ b/lib/libc/include/generic-openbsd/rpc/xdr.h @@ -0,0 +1,316 @@ +/* $OpenBSD: xdr.h,v 1.14 2022/12/27 07:44:56 jmc Exp $ */ +/* $NetBSD: xdr.h,v 1.7 1995/04/29 05:28:06 cgd Exp $ */ + +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: @(#)xdr.h 1.19 87/04/22 SMI + * @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC + */ + +/* + * xdr.h, External Data Representation Serialization Routines. + */ + +#ifndef _RPC_XDR_H +#define _RPC_XDR_H +#include + +/* + * XDR provides a conventional way for converting between C data + * types and an external bit-string representation. Library supplied + * routines provide for the conversion on built-in C data types. These + * routines and utility routines defined here are used to help implement + * a type encode/decode routine for each user-defined type. + * + * Each data type provides a single procedure which takes two arguments: + * + * bool_t + * xdrproc(xdrs, argresp) + * XDR *xdrs; + * *argresp; + * + * xdrs is an instance of a XDR handle, to which or from which the data + * type is to be converted. argresp is a pointer to the structure to be + * converted. The XDR handle contains an operation field which indicates + * which of the operations (ENCODE, DECODE * or FREE) is to be performed. + * + * XDR_DECODE may allocate space if the pointer argresp is null. This + * data can be freed with the XDR_FREE operation. + * + * We write only one procedure per data type to make it easy + * to keep the encode and decode procedures for a data type consistent. + * In many cases the same code performs all operations on a user defined type, + * because all the hard work is done in the component type routines. + * decode as a series of calls on the nested data types. + */ + +/* + * Xdr operations. XDR_ENCODE causes the type to be encoded into the + * stream. XDR_DECODE causes the type to be extracted from the stream. + * XDR_FREE can be used to release the space allocated by an XDR_DECODE + * request. + */ +enum xdr_op { + XDR_ENCODE=0, + XDR_DECODE=1, + XDR_FREE=2 +}; + +/* + * This is the number of bytes per unit of external data. + */ +#define BYTES_PER_XDR_UNIT (4) +#define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \ + * BYTES_PER_XDR_UNIT) + +/* + * The XDR handle. + * Contains operation which is being applied to the stream, + * an operations vector for the particular implementation (e.g. see xdr_mem.c), + * and two private fields for the use of the particular implementation. + */ +typedef struct __rpc_xdr { + enum xdr_op x_op; /* operation; fast additional param */ + const struct xdr_ops { + /* get a long from underlying stream */ + bool_t (*x_getlong)(struct __rpc_xdr *, long *); + /* put a long to " */ + bool_t (*x_putlong)(struct __rpc_xdr *, long *); + /* get some bytes from " */ + bool_t (*x_getbytes)(struct __rpc_xdr *, caddr_t, + unsigned int); + /* put some bytes to " */ + bool_t (*x_putbytes)(struct __rpc_xdr *, caddr_t, + unsigned int); + /* returns bytes off from beginning */ + unsigned int (*x_getpostn)(struct __rpc_xdr *); + /* lets you reposition the stream */ + bool_t (*x_setpostn)(struct __rpc_xdr *, unsigned int); + /* buf quick ptr to buffered data */ + int32_t *(*x_inline)(struct __rpc_xdr *, unsigned int); + /* free privates of this xdr_stream */ + void (*x_destroy)(struct __rpc_xdr *); + bool_t (*x_control)(struct __rpc_xdr *, int, void *); + } *x_ops; + caddr_t x_public; /* users' data */ + caddr_t x_private; /* pointer to private data */ + caddr_t x_base; /* private used for position info */ + unsigned int x_handy; /* extra private word */ +} XDR; + +/* + * A xdrproc_t exists for each data type which is to be encoded or decoded. + * + * The second argument to the xdrproc_t is a pointer to an opaque pointer. + * The opaque pointer generally points to a structure of the data type + * to be decoded. If this pointer is 0, then the type routines should + * allocate dynamic storage of the appropriate size and return it. + * + * XXX can't actually prototype it, because some take three args!!! + */ +typedef bool_t (*xdrproc_t)(/* XDR *, void *, unsigned int */); + +/* + * Operations defined on a XDR handle + * + * XDR *xdrs; + * long *longp; + * caddr_t addr; + * unsigned int len; + * unsigned int pos; + */ +#define XDR_GETLONG(xdrs, longp) \ + (*(xdrs)->x_ops->x_getlong)(xdrs, longp) +#define xdr_getlong(xdrs, longp) \ + (*(xdrs)->x_ops->x_getlong)(xdrs, longp) + +#define XDR_PUTLONG(xdrs, longp) \ + (*(xdrs)->x_ops->x_putlong)(xdrs, longp) +#define xdr_putlong(xdrs, longp) \ + (*(xdrs)->x_ops->x_putlong)(xdrs, longp) + +#define XDR_GETBYTES(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) +#define xdr_getbytes(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) + +#define XDR_PUTBYTES(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) +#define xdr_putbytes(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) + +#define XDR_GETPOS(xdrs) \ + (*(xdrs)->x_ops->x_getpostn)(xdrs) +#define xdr_getpos(xdrs) \ + (*(xdrs)->x_ops->x_getpostn)(xdrs) + +#define XDR_SETPOS(xdrs, pos) \ + (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) +#define xdr_setpos(xdrs, pos) \ + (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) + +#define XDR_INLINE(xdrs, len) \ + (*(xdrs)->x_ops->x_inline)(xdrs, len) +#define xdr_inline(xdrs, len) \ + (*(xdrs)->x_ops->x_inline)(xdrs, len) + +#define XDR_DESTROY(xdrs) \ + if ((xdrs)->x_ops->x_destroy) \ + (*(xdrs)->x_ops->x_destroy)(xdrs) +#define xdr_destroy(xdrs) \ + if ((xdrs)->x_ops->x_destroy) \ + (*(xdrs)->x_ops->x_destroy)(xdrs) + +/* + * Support struct for discriminated unions. + * You create an array of xdrdiscrim structures, terminated with + * a entry with a null procedure pointer. The xdr_union routine gets + * the discriminant value and then searches the array of structures + * for a matching value. If a match is found the associated xdr routine + * is called to handle that part of the union. If there is + * no match, then a default routine may be called. + * If there is no match and no default routine it is an error. + */ +#define NULL_xdrproc_t ((xdrproc_t)0) +struct xdr_discrim { + int value; + xdrproc_t proc; +}; + +/* + * In-line routines for fast encode/decode of primitive data types. + * Caveat emptor: these use single memory cycles to get the + * data from the underlying buffer, and will fail to operate + * properly if the data is not aligned. The standard way to use these + * is to say: + * if ((buf = XDR_INLINE(xdrs, count)) == NULL) + * return (FALSE); + * <<< macro calls >>> + * where ``count'' is the number of bytes of data occupied + * by the primitive data types. + * + * N.B. and frozen for all time: each data type here uses 4 bytes + * of external representation. + */ +#define IXDR_GET_LONG(buf) ((long)ntohl((unsigned long)*(buf)++)) +#define IXDR_PUT_LONG(buf, v) (*(buf)++ = (long)htonl((unsigned long)v)) + +#define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf)) +#define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf)) +#define IXDR_GET_U_LONG(buf) ((unsigned long)IXDR_GET_LONG(buf)) +#define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf)) +#define IXDR_GET_U_SHORT(buf) ((unsigned short)IXDR_GET_LONG(buf)) + +#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) + +/* + * These are the "generic" xdr routines. + */ +__BEGIN_DECLS +extern bool_t xdr_void(void); +extern bool_t xdr_int(XDR *, int *); +extern bool_t xdr_u_int(XDR *, unsigned int *); +extern bool_t xdr_long(XDR *, long *); +extern bool_t xdr_u_long(XDR *, unsigned long *); +extern bool_t xdr_short(XDR *, short *); +extern bool_t xdr_u_short(XDR *, unsigned short *); +extern bool_t xdr_int16_t(XDR *, int16_t *); +extern bool_t xdr_u_int16_t(XDR *, u_int16_t *); +extern bool_t xdr_int32_t(XDR *, int32_t *); +extern bool_t xdr_u_int32_t(XDR *, u_int32_t *); +extern bool_t xdr_int64_t(XDR *, int64_t *); +extern bool_t xdr_u_int64_t(XDR *, u_int64_t *); +extern bool_t xdr_bool(XDR *, bool_t *); +extern bool_t xdr_enum(XDR *, enum_t *); +extern bool_t xdr_array(XDR *, char **, unsigned int *, unsigned int, + unsigned int, xdrproc_t); +extern bool_t xdr_bytes(XDR *, char **, unsigned int *, unsigned int); +extern bool_t xdr_opaque(XDR *, caddr_t, unsigned int); +extern bool_t xdr_string(XDR *, char **, unsigned int); +extern bool_t xdr_union(XDR *, enum_t *, char *, struct xdr_discrim *, + xdrproc_t); +extern bool_t xdr_char(XDR *, char *); +extern bool_t xdr_u_char(XDR *, unsigned char *); +extern bool_t xdr_vector(XDR *, char *, unsigned int, unsigned int, + xdrproc_t); +extern bool_t xdr_float(XDR *, float *); +extern bool_t xdr_double(XDR *, double *); +extern bool_t xdr_reference(XDR *, caddr_t *, unsigned int, xdrproc_t); +extern bool_t xdr_pointer(XDR *, caddr_t *, unsigned int, xdrproc_t); +extern bool_t xdr_wrapstring(XDR *, char **); +extern void xdr_free(xdrproc_t, char *); +__END_DECLS + +/* + * Common opaque bytes objects used by many rpc protocols; + * declared here due to commonality. + */ +#define MAX_NETOBJ_SZ 1024 +struct netobj { + unsigned int n_len; + char *n_bytes; +}; +typedef struct netobj netobj; +extern bool_t xdr_netobj(XDR *, struct netobj *); + +/* + * These are the public routines for the various implementations of + * xdr streams. + */ +__BEGIN_DECLS +/* XDR using memory buffers */ +extern void xdrmem_create(XDR *, char *, unsigned int, enum xdr_op); + +#ifdef _STDIO_H_ +/* XDR using stdio library */ +extern void xdrstdio_create(XDR *, FILE *, enum xdr_op); +#endif + +/* XDR pseudo records for tcp */ +extern void xdrrec_create(XDR *, unsigned int, unsigned int, char *, + int (*)(caddr_t, caddr_t, int), + int (*)(caddr_t, caddr_t, int)); + +/* make end of xdr record */ +extern bool_t xdrrec_endofrecord(XDR *, int); + +/* move to beginning of next record */ +extern bool_t xdrrec_skiprecord(XDR *); + +/* true if no more input */ +extern bool_t xdrrec_eof(XDR *); +__END_DECLS + +#endif /* !_RPC_XDR_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sched.h b/lib/libc/include/generic-openbsd/sched.h new file mode 100644 index 000000000000..423754e63197 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sched.h @@ -0,0 +1,75 @@ +/* $OpenBSD: sched.h,v 1.1 2017/10/15 23:40:33 guenther Exp $ */ + +/* sched.h: POSIX 1003.1b Process Scheduling header */ + +/*- + * Copyright (c) 1996, 1997 + * HD Associates, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by HD Associates, Inc + * and Jukka Antero Ukkonen. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES 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 HD ASSOCIATES 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 _SCHED_H_ +#define _SCHED_H_ + +#include /* For pid_t */ +#include /* Per P1003.4 */ + +/* Scheduling policies + */ +#define SCHED_FIFO 1 +#define SCHED_OTHER 2 +#define SCHED_RR 3 + +struct sched_param +{ + int sched_priority; +}; + +__BEGIN_DECLS +#if 0 /* not yet */ +int sched_setparam(pid_t, const struct sched_param *); +int sched_getparam(pid_t, struct sched_param *); + +int sched_setscheduler(pid_t, int, const struct sched_param *); +int sched_getscheduler(pid_t); +#endif + +int sched_yield(void); +int sched_get_priority_max(int); +int sched_get_priority_min(int); + +#if 0 /* not yet */ +struct timespec; +int sched_rr_get_interval(pid_t, struct timespec *); +#endif +__END_DECLS + +#endif /* _SCHED_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/scsi/cd.h b/lib/libc/include/generic-openbsd/scsi/cd.h new file mode 100644 index 000000000000..55009f2d6969 --- /dev/null +++ b/lib/libc/include/generic-openbsd/scsi/cd.h @@ -0,0 +1,273 @@ +/* $OpenBSD: cd.h,v 1.28 2019/11/29 14:06:21 krw Exp $ */ +/* $NetBSD: scsi_cd.h,v 1.6 1996/03/19 03:06:39 mycroft Exp $ */ + +/* + * Written by Julian Elischer (julian@tfs.com) + * for TRW Financial Systems. + * + * TRW Financial Systems, in accordance with their agreement with Carnegie + * Mellon University, makes this software available to CMU to distribute + * or use in any manner that they see fit as long as this message is kept with + * the software. For this reason TFS also grants any other persons or + * organisations permission to use or modify this software. + * + * TFS supplies this software to be publicly redistributed + * on the understanding that TFS is not responsible for the correct + * functioning of this software in any circumstances. + * + * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 + */ +#ifndef _SCSI_CD_H +#define _SCSI_CD_H + +/* + * Define two bits always in the same place in byte 2 (flag byte) + */ +#define CD_RELADDR 0x01 +#define CD_MSF 0x02 + +/* + * SCSI command format + */ + +struct scsi_blank { + u_int8_t opcode; + u_int8_t byte2; +#define BLANK_DISC 0 +#define BLANK_MINIMAL 1 + u_int8_t addr[4]; + u_int8_t unused[5]; + u_int8_t control; +}; + +struct scsi_close_track { + u_int8_t opcode; + u_int8_t flags; +#define CT_IMMED 1 + u_int8_t closefunc; +#define CT_CLOSE_TRACK 1 +#define CT_CLOSE_SESS 2 +#define CT_CLOSE_BORDER 3 + u_int8_t unused; + u_int8_t track[2]; + u_int8_t unused1[3]; + u_int8_t control; +}; + +struct scsi_pause { + u_int8_t opcode; + u_int8_t byte2; + u_int8_t unused[6]; + u_int8_t resume; + u_int8_t control; +}; +#define PA_PAUSE 1 +#define PA_RESUME 0 + +struct scsi_play_msf { + u_int8_t opcode; + u_int8_t byte2; + u_int8_t unused; + u_int8_t start_m; + u_int8_t start_s; + u_int8_t start_f; + u_int8_t end_m; + u_int8_t end_s; + u_int8_t end_f; + u_int8_t control; +}; + +struct scsi_play_track { + u_int8_t opcode; + u_int8_t byte2; + u_int8_t unused[2]; + u_int8_t start_track; + u_int8_t start_index; + u_int8_t unused1; + u_int8_t end_track; + u_int8_t end_index; + u_int8_t control; +}; + +struct scsi_play { + u_int8_t opcode; + u_int8_t byte2; + u_int8_t blk_addr[4]; + u_int8_t unused; + u_int8_t xfer_len[2]; + u_int8_t control; +}; + +struct scsi_play_big { + u_int8_t opcode; + u_int8_t byte2; /* same as above */ + u_int8_t blk_addr[4]; + u_int8_t xfer_len[4]; + u_int8_t unused; + u_int8_t control; +}; + +struct scsi_play_rel_big { + u_int8_t opcode; + u_int8_t byte2; /* same as above */ + u_int8_t blk_addr[4]; + u_int8_t xfer_len[4]; + u_int8_t track; + u_int8_t control; +}; + +struct scsi_read_header { + u_int8_t opcode; + u_int8_t byte2; + u_int8_t blk_addr[4]; + u_int8_t unused; + u_int8_t data_len[2]; + u_int8_t control; +}; + +struct scsi_read_subchannel { + u_int8_t opcode; + u_int8_t byte2; + u_int8_t byte3; +#define SRS_SUBQ 0x40 + u_int8_t subchan_format; + u_int8_t unused[2]; + u_int8_t track; + u_int8_t data_len[2]; + u_int8_t control; +}; + +struct scsi_read_toc { + u_int8_t opcode; + u_int8_t byte2; + u_int8_t unused[4]; + u_int8_t from_track; + u_int8_t data_len[2]; + u_int8_t control; +}; + +struct scsi_read_track_info { + u_int8_t opcode; + u_int8_t addrtype; +#define RTI_LBA 0 +#define RTI_TRACK 1 +#define RTI_BORDER 2 + u_int8_t addr[4]; + u_int8_t unused; + u_int8_t data_len[2]; + u_int8_t control; +}; + +struct scsi_load_unload { + u_int8_t opcode; + u_int8_t reserved; +#define IMMED 0x1 + u_int8_t reserved2[2]; + u_int8_t options; +#define START 0x1 +#define LOUNLO 0x2 + u_int8_t reserved4[3]; + u_int8_t slot; + u_int8_t reserved5[2]; + u_int8_t control; +}; + +struct scsi_set_cd_speed { + u_int8_t opcode; + u_int8_t rotation; +#define ROTATE_CLV 0 +#define ROTATE_CAV 1 + u_int8_t read[2]; + u_int8_t write[2]; + u_int8_t reserved[5]; + u_int8_t control; +}; + +/* + * Opcodes + */ + +#define READ_SUBCHANNEL 0x42 /* cdrom read Subchannel */ +#define READ_TOC 0x43 /* cdrom read TOC */ +#define READ_HEADER 0x44 /* cdrom read header */ +#define PLAY 0x45 /* cdrom play 'play audio' mode */ +#define PLAY_MSF 0x47 /* cdrom play Min,Sec,Frames mode */ +#define PLAY_TRACK 0x48 /* cdrom play track/index mode */ +#define PLAY_TRACK_REL 0x49 /* cdrom play track/index mode */ +#define PAUSE 0x4b /* cdrom pause in 'play audio' mode */ +#define READ_TRACK_INFO 0x52 /* read track/rzone info */ +#define CLOSE_TRACK 0x5b /* close track/rzone/session/border */ +#define BLANK 0xa1 /* cdrom blank */ +#define PLAY_BIG 0xa5 /* cdrom pause in 'play audio' mode */ +#define LOAD_UNLOAD 0xa6 /* cdrom load/unload media */ +#define PLAY_TRACK_REL_BIG 0xa9 /* cdrom play track/index mode */ +#define SET_CD_SPEED 0xbb /* set cdrom read/write speed */ + +/* + * Mode pages + */ + +#define ERR_RECOVERY_PAGE 0x01 +#define WRITE_PARAM_PAGE 0x05 +#define AUDIO_PAGE 0x0e +#define CDVD_CAPABILITIES_PAGE 0x2a + +struct cd_audio_page { + u_int8_t page_code; +#define CD_PAGE_CODE 0x3F +#define CD_PAGE_PS 0x80 + u_int8_t param_len; + u_int8_t flags; +#define CD_PA_SOTC 0x02 +#define CD_PA_IMMED 0x04 + u_int8_t unused[2]; + u_int8_t format_lba; +#define CD_PA_FORMAT_LBA 0x0F +#define CD_PA_APR_VALID 0x80 + u_int8_t lb_per_sec[2]; + struct port_control { + u_int8_t channels; +#define CHANNEL 0x0F +#define CHANNEL_0 1 +#define CHANNEL_1 2 +#define CHANNEL_2 4 +#define CHANNEL_3 8 +#define LEFT_CHANNEL CHANNEL_0 +#define RIGHT_CHANNEL CHANNEL_1 +#define MUTE_CHANNEL 0x0 +#define BOTH_CHANNEL LEFT_CHANNEL | RIGHT_CHANNEL + u_int8_t volume; + } port[4]; +#define LEFT_PORT 0 +#define RIGHT_PORT 1 +}; + +/* + * There are 2352 bytes in a CD digital audio frame. One frame is 1/75 of a + * second, at 44.1kHz sample rate, 16 bits/sample, 2 channels. + * + * The frame data have the two channels interleaved, with the left + * channel first. Samples are little endian 16-bit signed values. + */ +#define CD_DA_BLKSIZ 2352 /* # bytes in CD-DA frame */ +#define CD_NORMAL_DENSITY_CODE 0x00 /* from Toshiba CD-ROM specs */ +#define CD_DA_DENSITY_CODE 0x82 /* from Toshiba CD-ROM specs */ + +struct scsi_read_dvd_structure { + u_int8_t opcode; /* GPCMD_READ_DVD_STRUCTURE */ + u_int8_t reserved; + u_int8_t address[4]; + u_int8_t layer; + u_int8_t format; + u_int8_t length[2]; + u_int8_t agid; /* bottom 6 bits reserved */ + u_int8_t control; +}; + +struct scsi_read_dvd_structure_data { + u_int8_t len[2]; /* Big-endian length of valid data. */ + u_int8_t reserved[2]; + u_int8_t data[2048]; +}; + +#endif /* _SCSI_CD_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/scsi/iscsi.h b/lib/libc/include/generic-openbsd/scsi/iscsi.h new file mode 100644 index 000000000000..99a0c87a02e3 --- /dev/null +++ b/lib/libc/include/generic-openbsd/scsi/iscsi.h @@ -0,0 +1,570 @@ +/* $OpenBSD: iscsi.h,v 1.9 2019/09/27 23:07:42 krw Exp $ */ + +/* + * Copyright (c) 2008 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SCSI_ISCSI_H +#define _SCSI_ISCSI_H + +struct iscsi_pdu { + u_int8_t opcode; + u_int8_t flags; + u_int8_t _reserved1[2]; + + u_int8_t ahslen; + u_int8_t datalen[3]; + + u_int8_t lun[8]; + + u_int32_t itt; + + u_int8_t _reserved2[4]; + + u_int32_t cmdsn; + + u_int32_t expstatsn; + + u_int8_t _reserved3[16]; +} __packed; + +/* + * Initiator opcodes + */ + +#define ISCSI_OP_I_NOP 0x00 +#define ISCSI_OP_SCSI_REQUEST 0x01 +#define ISCSI_OP_TASK_REQUEST 0x02 +#define ISCSI_OP_LOGIN_REQUEST 0x03 +#define ISCSI_OP_TEXT_REQUEST 0x04 +#define ISCSI_OP_DATA_OUT 0x05 +#define ISCSI_OP_LOGOUT_REQUEST 0x06 +#define ISCSI_OP_SNACK_REQUEST 0x10 + +/* + * Target opcodes + */ + +#define ISCSI_OP_T_NOP 0x20 +#define ISCSI_OP_SCSI_RESPONSE 0x21 +#define ISCSI_OP_TASK_RESPONSE 0x22 +#define ISCSI_OP_LOGIN_RESPONSE 0x23 +#define ISCSI_OP_TEXT_RESPONSE 0x24 +#define ISCSI_OP_DATA_IN 0x25 +#define ISCSI_OP_LOGOUT_RESPONSE 0x26 +#define ISCSI_OP_R2T 0x31 +#define ISCSI_OP_ASYNC 0x32 +#define ISCSI_OP_REJECT 0x3f + +#define ISCSI_PDU_OPCODE(_o) ((_o) & 0x3f) +#define ISCSI_PDU_I(_h) ((_h)->opcode & 0x40) +#define ISCSI_PDU_F(_h) ((_h)->flags & 0x80) + +#define ISCSI_OP_F_IMMEDIATE 0x40 + +/* + * various other flags and values + */ +#define ISCSI_ISID_OUI 0x00000000 +#define ISCSI_ISID_EN 0x40000000 +#define ISCSI_ISID_RAND 0x80000000 + +struct iscsi_pdu_scsi_request { + u_int8_t opcode; + u_int8_t flags; + u_int8_t _reserved[2]; + + u_int8_t ahslen; + u_int8_t datalen[3]; + + u_int8_t lun[8]; + + u_int32_t itt; + + u_int32_t bytes; + + u_int32_t cmdsn; + + u_int32_t expstatsn; + + u_int8_t cdb[16]; +} __packed; + +struct iscsi_pdu_scsi_response { + u_int8_t opcode; + u_int8_t flags; + u_int8_t response; + u_int8_t status; + + u_int8_t ahslen; + u_int8_t datalen[3]; + + u_int8_t _reserved[8]; + + u_int32_t itt; + + u_int32_t snack; + + u_int32_t statsn; + + u_int32_t expcmdsn; + + u_int32_t maxcmdsn; + + u_int32_t expdatasn; + + u_int32_t birescount; + + u_int32_t rescount; +} __packed; + +#define ISCSI_SCSI_F_F 0x80 +#define ISCSI_SCSI_F_R 0x40 +#define ISCSI_SCSI_F_W 0x20 + +#define ISCSI_SCSI_ATTR_UNTAGGED 0 +#define ISCSI_SCSI_ATTR_SIMPLE 1 +#define ISCSI_SCSI_ATTR_ORDERED 2 +#define ISCSI_SCSI_ATTR_HEAD_OF_Q 3 +#define ISCSI_SCSI_ATTR_ACA 4 + +#define ISCSI_SCSI_STAT_GOOD 0x00 +#define ISCSI_SCSI_STAT_CHCK_COND 0x02 +/* we don't care about the type of the other error conditions */ + +struct iscsi_pdu_task_request { + u_int8_t opcode; + u_int8_t flags; + u_int8_t reserved[2]; + + u_int8_t ahslen; + u_int8_t datalen[3]; + + u_int8_t lun[8]; + + u_int32_t itt; + + u_int32_t tag; + + u_int32_t cmdsn; + + u_int32_t expstatsn; + + u_int32_t refcmdsn; + + u_int32_t expdatasn; + + u_int8_t _reserved[8]; +} __packed; + +struct iscsi_pdu_task_response { + u_int8_t opcode; + u_int8_t flags; + u_int8_t response; + u_int8_t _reserved1; + + u_int8_t ahslen; + u_int8_t datalen[3]; + + u_int8_t _reserved[8]; + + u_int32_t itt; + + u_int8_t _reserved2[4]; + + u_int32_t statsn; + + u_int32_t expcmdsn; + + u_int32_t maxcmdsn; + + u_int8_t _reserved3[12]; +} __packed; + +struct iscsi_pdu_data_out { + u_int8_t opcode; + u_int8_t flags; + u_int8_t _reserved1[2]; + + u_int8_t ahslen; + u_int8_t datalen[3]; + + u_int8_t lun[8]; + + u_int32_t itt; + + u_int32_t ttt; + + u_int8_t _reserved2[4]; + + u_int32_t expstatsn; + + u_int8_t _reserved3[4]; + + u_int32_t datasn; + + u_int32_t buffer_offs; + + u_int8_t _reserved4[4]; +} __packed; + +struct iscsi_pdu_data_in { + u_int8_t opcode; + u_int8_t flags; + u_int8_t _reserved; + u_int8_t status; + + u_int8_t ahslen; + u_int8_t datalen[3]; + + u_int8_t lun[8]; + + u_int32_t itt; + + u_int32_t ttt; + + u_int32_t statsn; + + u_int32_t expcmdsn; + + u_int32_t maxcmdsn; + + u_int32_t datasn; + + u_int32_t buffer_offs; + + u_int32_t residual; +} __packed; + +struct iscsi_pdu_rt2 { + u_int8_t opcode; + u_int8_t flags; + u_int8_t _reserved1[2]; + + u_int8_t ahslen; + u_int8_t datalen[3]; + + u_int8_t lun[8]; + + u_int32_t itt; + + u_int32_t ttt; + + u_int32_t statsn; + + u_int32_t expcmdsn; + + u_int32_t maxcmdsn; + + u_int32_t r2tsn; + + u_int32_t buffer_offs; + + u_int32_t desired_datalen; +} __packed; + +struct iscsi_pdu_async { + u_int8_t opcode; + u_int8_t flags; + u_int8_t _reserved1[2]; + + u_int8_t ahslen; + u_int8_t datalen[3]; + + u_int8_t lun[8]; + + u_int32_t ffffffff; + + u_int8_t _reserved2[4]; + + u_int32_t statsn; + + u_int32_t expcmdsn; + + u_int32_t maxcmdsn; + + u_int8_t event; + u_int8_t vcode; + u_int16_t param[3]; + + u_int8_t _reserved3[4]; +} __packed; + +struct iscsi_pdu_text_request { + u_int8_t opcode; + u_int8_t flags; + u_int8_t _reserved1[2]; + + u_int8_t ahslen; + u_int8_t datalen[3]; + + u_int8_t lun[8]; + + u_int32_t itt; + + u_int32_t ttt; + + u_int32_t cmdsn; + + u_int32_t expstatsn; + + u_int8_t _reserved2[16]; +} __packed; + +struct iscsi_pdu_text_response { + u_int8_t opcode; + u_int8_t flags; + u_int8_t _reserved1[2]; + + u_int8_t ahslen; + u_int8_t datalen[3]; + + u_int8_t lun[8]; + + u_int32_t itt; + + u_int32_t ttt; + + u_int32_t cmdsn; + + u_int32_t expcmdsn; + + u_int32_t maxcmdsn; + + u_int8_t _reserved2[12]; +} __packed; + +#define ISCSI_TEXT_F_F 0x80 +#define ISCSI_TEXT_F_C 0x40 + +struct iscsi_pdu_login_request { + u_int8_t opcode; + u_int8_t flags; + u_int8_t version_max; + u_int8_t version_min; + + u_int8_t ahslen; + u_int8_t datalen[3]; + + u_int32_t isid_base; + u_int16_t isid_qual; + u_int16_t tsih; + + u_int32_t itt; + + u_int16_t cid; + u_int8_t _reserved1[2]; + + u_int32_t cmdsn; + + u_int32_t expstatsn; + + u_int8_t _reserved2[16]; +} __packed; + +#define ISCSI_LOGIN_F_T 0x80 +#define ISCSI_LOGIN_F_C 0x40 +#define ISCSI_LOGIN_F_CSG(x) (((x) & 0x3) << 2) +#define ISCSI_LOGIN_F_NSG(x) ((x) & 0x3) +#define ISCSI_LOGIN_STG_SECNEG 0 +#define ISCSI_LOGIN_STG_OPNEG 1 +#define ISCSI_LOGIN_STG_FULL 3 + +struct iscsi_pdu_login_response { + u_int8_t opcode; + u_int8_t flags; + u_int8_t version_max; + u_int8_t version_active; + + u_int8_t ahslen; + u_int8_t datalen[3]; + + u_int32_t isid_base; + u_int16_t isid_qual; + u_int16_t tsih; + + u_int32_t itt; + + u_int8_t _reserved1[4]; + + u_int32_t statsn; + + u_int32_t expcmdsn; + + u_int32_t maxcmdsn; + + u_int8_t status_class; + u_int8_t status_detail; + + u_int8_t _reserved2[10]; +} __packed; + +struct iscsi_pdu_logout_request { + u_int8_t opcode; + u_int8_t flags; + u_int8_t _reserved1[2]; + + u_int8_t ahslen; + u_int8_t datalen[3]; + + u_int8_t _reserved2[8]; + + u_int32_t itt; + + u_int16_t cid; + u_int8_t _reserved3[2]; + + u_int32_t cmdsn; + + u_int32_t expstatsn; + + u_int8_t _reserved4[16]; +} __packed; + +#define ISCSI_LOGOUT_F 0x80 +#define ISCSI_LOGOUT_CLOSE_SESS 0 +#define ISCSI_LOGOUT_CLOSE_CONN 1 +#define ISCSI_LOGOUT_RCVRY_CONN 2 + +#define ISCSI_LOGOUT_RESP_SUCCESS 0 +#define ISCSI_LOGOUT_RESP_UNKN_CID 1 +#define ISCSI_LOGOUT_RESP_NO_SUPPORT 2 +#define ISCSI_LOGOUT_RESP_ERROR 3 + +struct iscsi_pdu_logout_response { + u_int8_t opcode; + u_int8_t flags; + u_int8_t response; + u_int8_t _reserved1; + + u_int8_t ahslen; + u_int8_t datalen[3]; + + u_int8_t _reserved2[8]; + + u_int32_t itt; + + u_int8_t _reserved3[4]; + + u_int32_t statsn; + + u_int32_t expcmdsn; + + u_int32_t maxcmdsn; + + u_int8_t _reserved4[4]; + + u_int16_t time2wait; + u_int16_t time2retain; + + u_int8_t _reserved5[4]; +} __packed; + +struct iscsi_pdu_snack_request { + u_int8_t opcode; + u_int8_t flags; + u_int8_t _reserved1[2]; + + u_int8_t ahslen; + u_int8_t datalen[3]; + + u_int8_t lun[8]; + + u_int32_t itt; + + u_int32_t ttt; + + u_int8_t _reserved2[4]; + + u_int32_t expstatsn; + + u_int8_t _reserved3[8]; + + u_int32_t begrun; + + u_int32_t runlength; +} __packed; + +struct iscsi_pdu_reject { + u_int8_t opcode; + u_int8_t flags; + u_int8_t reason; + u_int8_t _reserved1; + + u_int8_t ahslen; + u_int8_t datalen[3]; + + u_int8_t _reserved2[8]; + + u_int32_t ffffffff; + + u_int8_t _reserved3[4]; + + u_int32_t statsn; + + u_int32_t expcmdsn; + + u_int32_t maxcmdsn; + + u_int32_t datasn_r2tsn; + + u_int8_t _reserved4[8]; +} __packed; + +struct iscsi_pdu_nop_out { + u_int8_t opcode; + u_int8_t flags; + u_int8_t _reserved1[2]; + + u_int8_t ahslen; + u_int8_t datalen[3]; + + u_int8_t lun[8]; + + u_int32_t itt; + + u_int32_t ttt; + + u_int32_t cmdsn; + + u_int32_t expstatsn; + + u_int8_t _reserved2[16]; +} __packed; + +struct iscsi_pdu_nop_in { + u_int8_t opcode; + u_int8_t flags; + u_int8_t _reserved1[2]; + + u_int8_t ahslen; + u_int8_t datalen[3]; + + u_int8_t lun[8]; + + u_int32_t itt; + + u_int32_t ttt; + + u_int32_t statsn; + + u_int32_t expcmdsn; + + u_int32_t maxcmdsn; + + u_int8_t _reserved2[12]; +} __packed; + +#endif /* _SCSI_ISCSI_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/scsi/mpathvar.h b/lib/libc/include/generic-openbsd/scsi/mpathvar.h new file mode 100644 index 000000000000..46ed0f70cde9 --- /dev/null +++ b/lib/libc/include/generic-openbsd/scsi/mpathvar.h @@ -0,0 +1,59 @@ +/* $OpenBSD: mpathvar.h,v 1.10 2019/09/27 23:07:42 krw Exp $ */ + +/* + * Copyright (c) 2010 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SCSI_MPATHVAR_H +#define _SCSI_MPATHVAR_H + +struct mpath_group; + +struct mpath_ops { + char op_name[16]; + int (*op_checksense)(struct scsi_xfer *); + void (*op_status)(struct scsi_link *); +}; + +#define MPATH_SENSE_DECLINED 0 /* path driver declined to interpret sense */ +#define MPATH_SENSE_FAILOVER 1 /* sense says controllers have failed over */ + +#define MPATH_S_UNKNOWN -1 +#define MPATH_S_ACTIVE 0 +#define MPATH_S_PASSIVE 1 + +struct mpath_path { + /* the path driver must set these */ + struct scsi_xshandler p_xsh; + struct scsi_link *p_link; + int p_gid; + + /* the following are private to mpath.c */ + TAILQ_ENTRY(mpath_path) p_entry; + struct mpath_group *p_group; + int p_state; +}; + +int mpath_path_probe(struct scsi_link *); +int mpath_path_attach(struct mpath_path *, u_int, + const struct mpath_ops *); +void mpath_path_status(struct mpath_path *, int); +int mpath_path_detach(struct mpath_path *); + +void mpath_start(struct mpath_path *, struct scsi_xfer *); + +struct device *mpath_bootdv(struct device *); + +#endif /* _SCSI_MPATHVAR_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/scsi/safte.h b/lib/libc/include/generic-openbsd/scsi/safte.h new file mode 100644 index 000000000000..ea22b5f55dde --- /dev/null +++ b/lib/libc/include/generic-openbsd/scsi/safte.h @@ -0,0 +1,171 @@ +/* $OpenBSD: safte.h,v 1.9 2020/09/12 15:54:51 krw Exp $ */ + +/* + * Copyright (c) 2005 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SCSI_SAFTE_H +#define _SCSI_SAFTE_H + +/* scsi_inquiry_data.extra */ +struct safte_inq { + u_int8_t uniqueid[7]; + u_int8_t chanid; + u_int8_t ident[6]; +#define SAFTE_IDENT "SAF-TE" +}; + +struct safte_readbuf_cmd { + u_int8_t opcode; /* READ_BUFFER */ + u_int8_t flags; +#define SAFTE_RD_LUNMASK 0xe0 /* the lun should always be 0 */ +#define SAFTE_RD_MODEMASK 0x07 +#define SAFTE_RD_MODE 0x01 /* 0x01 is the SAF-TE command mode */ + u_int8_t bufferid; +#define SAFTE_RD_CONFIG 0x00 /* enclosure configuration */ +#define SAFTE_RD_ENCSTAT 0x01 /* enclosure status */ +#define SAFTE_RD_USAGE 0x02 /* usage statistics */ +#define SAFTE_RD_INSERTS 0x03 /* device insertions */ +#define SAFTE_RD_SLOTSTAT 0x04 /* slot status */ +#define SAFTE_RD_GLOBALS 0x05 /* global flags */ + u_int32_t reserved1; + u_int16_t length; /* transfer length (big endian) */ + u_int8_t reserved2; +} __packed; + +struct safte_writebuf_cmd { + u_int8_t opcode; /* WRITE_BUFFER */ + u_int8_t flags; +#define SAFTE_WR_LUNMASK 0xe0 /* the lun should always be 0 */ +#define SAFTE_WR_MODEMASK 0x07 +#define SAFTE_WR_MODE 0x01 /* 0x01 is the SAF-TE command mode */ + u_int8_t reserved1[5]; + u_int16_t length; /* transfer length (big endian) */ + u_int8_t reserved2; +} __packed; + +#define SAFTE_WRITE_SLOTSTAT 0x10 /* write device slot status */ +#define SAFTE_WRITE_SETID 0x11 /* set scsi id */ +#define SAFTE_WRITE_SLOTOP 0x12 /* perform slot operation */ +#define SAFTE_WRITE_FANSPEED 0x13 /* set fan speed */ +#define SAFTE_WRITE_PWRSUP 0x14 /* activate power supply */ +#define SAFTE_WRITE_GLOBALS 0x15 /* global flags */ + + +/* enclosure configuration */ +struct safte_config { + u_int8_t nfans; /* number of fans */ + u_int8_t npwrsup; /* number of power supplies */ + u_int8_t nslots; /* number of device slots */ + u_int8_t doorlock; /* door lock installed */ + u_int8_t ntemps; /* number of temp sensors */ + u_int8_t alarm; /* audible alarm installed */ + u_int8_t therm; /* temps in C and num of thermostats */ +#define SAFTE_CFG_CELSIUSMASK 0x80 +#define SAFTE_CFG_CELSIUS(a) ((a) & SAFTE_CFG_CELSIUSMASK ? 1 : 0) +#define SAFTE_CFG_NTHERMMASK 0x0f +#define SAFTE_CFG_NTHERM(a) ((a) & SAFTE_CFG_NTHERMMASK) + u_int8_t reserved[56]; /* 7 to 62 */ + u_int8_t vendor_bytes; /* number of vendor specific bytes */ +} __packed; +#define SAFTE_CONFIG_LEN sizeof(struct safte_config) + +/* enclosure status fields */ +/* fan status field */ +#define SAFTE_FAN_OP 0x00 /* operational */ +#define SAFTE_FAN_MF 0x01 /* malfunctioning */ +#define SAFTE_FAN_NOTINST 0x02 /* not installed */ +#define SAFTE_FAN_UNKNOWN 0x80 /* unknown status or unreportable */ + +/* power supply status field */ +#define SAFTE_PWR_OP_ON 0x00 /* operational and on */ +#define SAFTE_PWR_OP_OFF 0x01 /* operational and off */ +#define SAFTE_PWR_MF_ON 0x10 /* malfunctioning and on */ +#define SAFTE_PWR_MF_OFF 0x11 /* malfunctioning and off */ +#define SAFTE_PWR_NOTINST 0x20 /* not present */ +#define SAFTE_PWR_PRESENT 0x21 /* present */ +#define SAFTE_PWR_UNKNOWN 0x80 /* unknown status or unreportable */ + +/* scsi id fields */ +/* are integers, not bitfields */ + +/* door lock status */ +#define SAFTE_DOOR_LOCKED 0x00 /* locked */ +#define SAFTE_DOOR_UNLOCKED 0x01 /* unlocked or uncontrollable */ +#define SAFTE_DOOR_UNKNOWN 0x80 /* unknown status or unreportable */ + +/* speaker status */ +#define SAFTE_SPKR_OFF 0x00 /* off or not installed */ +#define SAFTE_SPKR_ON 0x01 /* speaker is currently on */ + +/* temperature */ +#define SAFTE_TEMP_OFFSET -10 /* -10 to 245 degrees */ + +/* temp out of range */ +#define SAFTE_TEMP_ETA 0x8000 /* any temp alert */ + + +/* usage statistics */ +struct safte_usage { + u_int32_t minutes; /* total number of minutes on */ + u_int32_t cycles; /* total number of power cycles */ + u_int8_t reserved[7]; + u_int8_t vendor_bytes; /* number of vendor specific bytes */ +}; + + +/* device insertions */ +/* u_int16_t * nslots */ + + +/* device slot status */ +#define SAFTE_SLOTSTAT_INSERT (1<<0) /* inserted */ +#define SAFTE_SLOTSTAT_SWAP (1<<1) /* ready to be inserted/removed */ +#define SAFTE_SLOTSTAT_OPER (1<<2) /* ready for operation */ + + +/* global flags */ +struct safte_globals { + u_int8_t flags1; +#define SAFTE_GLOBAL_ALARM (1<<0) /* audible alarm */ +#define SAFTE_GLOBAL_FAILURE (1<<1) /* global failure indication */ +#define SAFTE_GLOBAL_WARNING (1<<2) /* global warning indication */ +#define SAFTE_GLOBAL_POWER (1<<3) /* enclosure power */ +#define SAFTE_GLOBAL_COOLING (1<<4) /* cooling failure */ +#define SAFTE_GLOBAL_PWRFAIL (1<<5) /* power failure */ +#define SAFTE_GLOBAL_DRVFAIL (1<<6) /* drive failure */ +#define SAFTE_GLOBAL_DRVWARN (1<<6) /* drive warning */ + u_int8_t flags2; +#define SAFTE_GLOBAL_ARRAYFAIL (1<<0) /* array failure */ +#define SAFTE_GLOBAL_ARRAYWARN (1<<1) /* array warning */ +#define SAFTE_GLOBAL_LOCK (1<<2) /* enclosure lock */ +#define SAFTE_GLOBAL_IDENTIFY (1<<3) /* identify enclosure */ + u_int8_t flags3; + u_int8_t reserved[13]; +}; + + +/* perform slot operation */ +struct safte_slotop { + u_int8_t opcode; /* SAFTE_WRITE_SLOTOP */ + u_int8_t slot; + u_int8_t flags; +#define SAFTE_SLOTOP_OPERATE (1<<0) /* prepare for operation */ +#define SAFTE_SLOTOP_INSREM (1<<1) /* prepare for insert/removal */ +#define SAFTE_SLOTOP_IDENTIFY (1<<2) /* identify */ + u_int8_t reserved[61]; /* zero these */ +} __packed; + +#endif /* _SCSI_SAFTE_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/scsi/scsi_all.h b/lib/libc/include/generic-openbsd/scsi/scsi_all.h new file mode 100644 index 000000000000..80ac85b5aeac --- /dev/null +++ b/lib/libc/include/generic-openbsd/scsi/scsi_all.h @@ -0,0 +1,663 @@ +/* $OpenBSD: scsi_all.h,v 1.65 2022/01/11 23:10:11 jsg Exp $ */ +/* $NetBSD: scsi_all.h,v 1.10 1996/09/12 01:57:17 thorpej Exp $ */ + +/* + * SCSI general interface description + */ + +/* + * Largely written by Julian Elischer (julian@tfs.com) + * for TRW Financial Systems. + * + * TRW Financial Systems, in accordance with their agreement with Carnegie + * Mellon University, makes this software available to CMU to distribute + * or use in any manner that they see fit as long as this message is kept with + * the software. For this reason TFS also grants any other persons or + * organisations permission to use or modify this software. + * + * TFS supplies this software to be publicly redistributed + * on the understanding that TFS is not responsible for the correct + * functioning of this software in any circumstances. + * + * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 + */ + +#ifndef _SCSI_SCSI_ALL_H +#define _SCSI_SCSI_ALL_H + +/* + * SCSI command format + */ + +/* + * Define some bits that are in ALL (or a lot of) scsi commands + */ +#define SCSI_CTL_LINK 0x01 +#define SCSI_CTL_FLAG 0x02 +#define SCSI_CTL_VENDOR 0xC0 + + +/* + * Some old SCSI devices need the LUN to be set in the top 3 bits of the + * second byte of the CDB. + */ +#define SCSI_CMD_LUN_MASK 0xe0 +#define SCSI_CMD_LUN_SHIFT 5 + + +struct scsi_generic { + u_int8_t opcode; + u_int8_t bytes[15]; +}; + +struct scsi_test_unit_ready { + u_int8_t opcode; + u_int8_t byte2; + u_int8_t unused[3]; + u_int8_t control; +}; + +struct scsi_send_diag { + u_int8_t opcode; + u_int8_t byte2; +#define SSD_UOL 0x01 +#define SSD_DOL 0x02 +#define SSD_SELFTEST 0x04 +#define SSD_PF 0x10 + u_int8_t unused[1]; + u_int8_t paramlen[2]; + u_int8_t control; +}; + +struct scsi_sense { + u_int8_t opcode; + u_int8_t byte2; + u_int8_t unused[2]; + u_int8_t length; + u_int8_t control; +}; + +struct scsi_inquiry { + u_int8_t opcode; + u_int8_t flags; +#define SI_EVPD 0x01 + u_int8_t pagecode; +#define SI_PG_SUPPORTED 0x00 +#define SI_PG_SERIAL 0x80 +#define SI_PG_DEVID 0x83 +#define SI_PG_ATA 0x89 + u_int8_t length[2]; + u_int8_t control; +}; + +struct scsi_mode_sense { + u_int8_t opcode; + u_int8_t byte2; +#define SMS_DBD 0x08 /* Disable Block Descriptors */ + u_int8_t page; +#define SMS_PAGE_CODE 0x3F +#define SMS_PAGE_CTRL 0xC0 +#define SMS_PAGE_CTRL_CURRENT 0x00 +#define SMS_PAGE_CTRL_CHANGEABLE 0x40 +#define SMS_PAGE_CTRL_DEFAULT 0x80 +#define SMS_PAGE_CTRL_SAVED 0xC0 + u_int8_t unused; + u_int8_t length; + u_int8_t control; +}; + +struct scsi_mode_sense_big { + u_int8_t opcode; + u_int8_t byte2; /* same bits as small version */ +#define SMS_LLBAA 0x10 /* plus: Long LBA Accepted */ + u_int8_t page; /* same bits as small version */ + u_int8_t unused[4]; + u_int8_t length[2]; + u_int8_t control; +}; + +struct scsi_mode_select { + u_int8_t opcode; + u_int8_t byte2; +#define SMS_SP 0x01 +#define SMS_PF 0x10 + u_int8_t unused[2]; + u_int8_t length; + u_int8_t control; +}; + +struct scsi_mode_select_big { + u_int8_t opcode; + u_int8_t byte2; /* same bits as small version */ + u_int8_t unused[5]; + u_int8_t length[2]; + u_int8_t control; +}; + +struct scsi_reserve { + u_int8_t opcode; + u_int8_t byte2; + u_int8_t unused[2]; + u_int8_t length; + u_int8_t control; +}; + +struct scsi_release { + u_int8_t opcode; + u_int8_t byte2; + u_int8_t unused[2]; + u_int8_t length; + u_int8_t control; +}; + +struct scsi_prevent { + u_int8_t opcode; + u_int8_t byte2; + u_int8_t unused[2]; + u_int8_t how; + u_int8_t control; +}; +#define PR_PREVENT 0x01 +#define PR_ALLOW 0x00 + +struct scsi_report_luns { + u_int8_t opcode; + u_int8_t unused; + u_int8_t selectreport; +#define REPORT_NORMAL 0x00 +#define REPORT_WELLKNOWN 0x01 +#define REPORT_ALL 0x02 + u_int8_t unused2[3]; + u_int8_t length[4]; + u_int8_t unused4; + u_int8_t control; +}; + +/* + * Opcodes + */ +#define TEST_UNIT_READY 0x00 +#define REQUEST_SENSE 0x03 +#define INQUIRY 0x12 +#define MODE_SELECT 0x15 +#define RESERVE 0x16 +#define RELEASE 0x17 +#define MODE_SENSE 0x1a +#define START_STOP 0x1b +#define RECEIVE_DIAGNOSTIC 0x1c +#define SEND_DIAGNOSTIC 0x1d +#define PREVENT_ALLOW 0x1e +#define POSITION_TO_ELEMENT 0x2b +#define WRITE_BUFFER 0x3b +#define READ_BUFFER 0x3c +#define CHANGE_DEFINITION 0x40 +#define MODE_SELECT_BIG 0x55 +#define MODE_SENSE_BIG 0x5a +#define REPORT_LUNS 0xa0 + +/* + * Sort of an extra one, for SCSI_RESET. + */ +#define GENRETRY 1 + +/* + * Device Types + */ +#define T_DIRECT 0x00 /* Direct access block device (SBC-4) */ +#define T_SEQUENTIAL 0x01 /* Sequential access device (SSC-3) */ +#define T_PRINTER 0x02 /* Printer device (SSC) */ +#define T_PROCESSOR 0x03 /* Processor device (SPC-2) */ +#define T_WORM 0x04 /* Write once device (SBC) */ +#define T_CDROM 0x05 /* CD/DVD device (MMC-5) */ +#define T_SCANNER 0x06 /* Scanner device (Obsolete) */ +#define T_OPTICAL 0x07 /* Optical memory device (SBC) */ +#define T_CHANGER 0x08 /* Media changer device (SMC-3) */ +#define T_COMM 0x09 /* Communications device (Obsolete) */ +#define T_ASC0 0x0a /* Obsolete */ +#define T_ASC1 0x0b /* Obsolete */ +#define T_STORARRAY 0x0c /* Storage Array controller device (RAID) */ +#define T_ENCLOSURE 0x0d /* Enclosure services device (SES) */ +#define T_RDIRECT 0x0e /* Simplified direct access device (RBC) */ +#define T_OCRW 0x0f /* Optical card reader/writer (OCRW) */ +#define T_BCC 0x10 /* Bridge Controller Commands (BCC) */ +#define T_OSD 0x11 /* Object-based Storage device (OSD) */ +#define T_ADC 0x12 /* Automation/Drive Interface (ADC-2) */ +/* 0x13 - 0x1d RESERVED */ +#define T_WELL_KNOWN_LU 0x1e /* Well known logical unit */ +#define T_NODEVICE 0x1F /* Unknown or no device type */ + +#define T_REMOV 1 +#define T_FIXED 0 + +struct scsi_inquiry_data { + u_int8_t device; +#define SID_TYPE 0x1f +#define SID_QUAL 0xe0 +#define SID_QUAL_LU_OK 0x00 +#define SID_QUAL_LU_OFFLINE 0x20 +#define SID_QUAL_RSVD 0x40 +#define SID_QUAL_BAD_LU 0x60 + u_int8_t dev_qual2; +#define SID_QUAL2 0x7f +#define SID_REMOVABLE 0x80 + u_int8_t version; +#define SID_ANSII 0x07 +#define SID_ECMA 0x38 +#define SID_ISO 0xc0 + u_int8_t response_format; +#define SID_RESPONSE_DATA_FMT 0x0f /* < 2 == obsolete, > 2 reserved! */ +#define SID_SCSI2_RESPONSE 0x02 +#define SID_HiSup 0x10 /* Hierarchical LUNs */ +#define SID_NormACA 0x20 /* Normal ACA bit in CCB supported */ +#define SID_TrmIOP 0x40 /* obsolete */ +#define SID_AENC 0x80 /* obsolete */ + u_int8_t additional_length; +#define SID_SCSI2_HDRLEN 5 /* Bytes up to & including additional_length */ +#define SID_SCSI2_ALEN 31 /* Additional bytes of basic SCSI2 info */ + u_int8_t spc3_flags; +#define SPC3_SID_PROTECT 0x01 /* 0 == Type 0, 1 == Type 1, 2 or 3 */ +#define SPC3_SID_RESERVED 0x06 +#define SPC3_SID_3PC 0x08 /* 3rd party copy */ +#define SPC3_SID_TPGS_IMPLICIT 0x10 /* Implicit asymmetric LU access */ +#define SPC3_SID_TPGS_EXPLICIT 0x20 /* Explicit asymmetric LU access */ +#define SPC3_SID_ACC 0x40 /* Access controls controller */ +#define SPC3_SID_SCCS 0x80 /* Embedded storage array controller */ + u_int8_t spc2_flags; +#define SPC2_SID_ADDR16 0x01 /* obsolete */ +#define SPC2_RESERVED 0x06 +#define SPC2_SID_NChngr 0x08 /* obsolete */ +#define SPC2_SID_MultiP 0x10 /* multi-port target */ +#define SPC2_VS 0x20 /* ??? */ +#define SPC2_SID_EncServ 0x40 /* Embedded enclosure services */ +#define SPC2_SID_BQueue 0x80 /* obsolete */ + u_int8_t flags; +#define SID_VS 0x01 /* ??? */ +#define SID_CmdQue 0x02 /* Task management mode supported */ +#define SID_Linked 0x08 /* obsolete */ +#define SID_Sync 0x10 /* obsolete */ +#define SID_WBus16 0x20 /* obsolete */ +#define SID_WBus32 0x40 /* obsolete */ +#define SID_RelAdr 0x80 /* obsolete */ + char vendor[8]; + char product[16]; + char revision[4]; + u_int8_t extra[20]; + u_int8_t reserved[2]; + u_int8_t version_descriptor0[2]; + u_int8_t version_descriptor1[2]; + u_int8_t version_descriptor2[2]; + u_int8_t version_descriptor3[2]; + u_int8_t version_descriptor4[2]; + u_int8_t version_descriptor5[2]; + u_int8_t version_descriptor6[2]; + u_int8_t version_descriptor7[2]; + u_int8_t reserved2[22]; +}; + +struct scsi_vpd_hdr { + u_int8_t device; + u_int8_t page_code; + u_int8_t page_length[2]; +}; + +struct scsi_vpd_serial { + struct scsi_vpd_hdr hdr; + char serial[32]; +}; + +#define VPD_PROTO_ID_FC 0x0 /* Fibre Channel */ +#define VPD_PROTO_ID_SPI 0x1 /* Parallel SCSI */ +#define VPD_PROTO_ID_SSA 0x2 +#define VPD_PROTO_ID_IEEE1394 0x3 +#define VPD_PROTO_ID_SRP 0x4 /* SCSI RDMA Protocol */ +#define VPD_PROTO_ID_ISCSI 0x5 /* Internet SCSI (iSCSI) */ +#define VPD_PROTO_ID_SAS 0x6 /* Serial Attached SCSI */ +#define VPD_PROTO_ID_ADT 0x7 /* Automation/Drive Interface Transport */ +#define VPD_PROTO_ID_ATA 0x7 /* ATA/ATAPI */ +#define VPD_PROTO_ID_NONE 0xf + +struct scsi_vpd_devid_hdr { + u_int8_t pi_code; +#define VPD_DEVID_PI(_f) (((_f) >> 4) & 0x0f) +#define VPD_DEVID_CODE(_f) (((_f) >> 0) & 0x0f) +#define VPD_DEVID_CODE_BINARY 0x1 +#define VPD_DEVID_CODE_ASCII 0x2 +#define VPD_DEVID_CODE_UTF8 0x3 + u_int8_t flags; +#define VPD_DEVID_PIV 0x80 +#define VPD_DEVID_ASSOC(_f) ((_f) & 0x30) +#define VPD_DEVID_ASSOC_LU 0x00 +#define VPD_DEVID_ASSOC_PORT 0x10 +#define VPD_DEVID_ASSOC_TARG 0x20 +#define VPD_DEVID_TYPE(_f) ((_f) & 0x0f) +#define VPD_DEVID_TYPE_VENDOR 0x0 +#define VPD_DEVID_TYPE_T10 0x1 +#define VPD_DEVID_TYPE_EUI64 0x2 +#define VPD_DEVID_TYPE_NAA 0x3 +#define VPD_DEVID_TYPE_RELATIVE 0x4 +#define VPD_DEVID_TYPE_PORT 0x5 +#define VPD_DEVID_TYPE_LU 0x6 +#define VPD_DEVID_TYPE_MD5 0x7 +#define VPD_DEVID_TYPE_NAME 0x8 + u_int8_t reserved; + u_int8_t len; +}; + +struct scsi_vpd_ata { + struct scsi_vpd_hdr hdr; + + u_int8_t _reserved1[4]; + u_int8_t sat_vendor[8]; + u_int8_t sat_product[16]; + u_int8_t sat_revision[4]; + u_int8_t device_signature[20]; + u_int8_t command_code; +#define VPD_ATA_COMMAND_CODE_ATA 0xec +#define VPD_ATA_COMMAND_CODE_ATAPI 0xa1 + u_int8_t _reserved2[3]; + u_int8_t identify[512]; +}; + +struct scsi_read_cap_data { + u_int8_t addr[4]; + u_int8_t length[4]; +}; + +struct scsi_read_cap_data_16 { + u_int8_t addr[8]; + u_int8_t length[4]; + u_int8_t p_type_prot; +#define RC16_PROT_EN 0x01 /* Protection type is 0 when 0 */ +#define RC16_PROT_P_TYPE 0x0e +#define RC16_P_TYPE_1 0x00 /* Protection type 1 */ +#define RC16_P_TYPE_2 0x02 /* Protection type 2 */ +#define RC16_P_TYPE_3 0x04 /* Protection type 3 */ +#define RC16_BASIS 0x30 /* Meaning of addr */ +#define RC16_BASIS_HIGH 0x00 /* highest LBA of zone */ +#define RC16_BASIS_LAST 0x10 /* last LBA on unit */ + u_int8_t logical_per_phys; /* Logical Blks Per Physical Blk Exp */ +#define RC16_LBPPB_EXPONENT 0x0f /* 2**N LB per PB, 0 means unknown */ +#define RC16_PIIPLB_EXPONENT 0xf0 /* 2**N Prot info intervals per LB */ + u_int8_t lowest_aligned[2]; +#define RC16_LALBA 0x3fff /* lowest aligned LBA */ +#define RC16_LBPRZ 0x4000 /* unmapped LBA returns all zeros */ +#define READ_CAP_16_TPRZ 0x4000 /* XXX old name used in driver(s) */ +#define RC16_LBPME 0x8000 /* LB provisioning management enabled */ +#define READ_CAP_16_TPE 0x8000 /* XXX old name used in driver(s) */ + u_int8_t reserved[16]; +}; + +struct scsi_sense_data_unextended { +/* 1*/ u_int8_t error_code; +/* 4*/ u_int8_t block[3]; +}; + +struct scsi_sense_data { +/* 1*/ u_int8_t error_code; +#define SSD_ERRCODE_CURRENT 0x70 +#define SSD_ERRCODE_DEFERRED 0x71 +#define SSD_ERRCODE 0x7F +#define SSD_ERRCODE_VALID 0x80 +/* 2*/ u_int8_t segment; +/* 3*/ u_int8_t flags; +#define SSD_KEY 0x0F +#define SSD_ILI 0x20 +#define SSD_EOM 0x40 +#define SSD_FILEMARK 0x80 +/* 7*/ u_int8_t info[4]; +/* 8*/ u_int8_t extra_len; +/*12*/ u_int8_t cmd_spec_info[4]; +/*13*/ u_int8_t add_sense_code; +/*14*/ u_int8_t add_sense_code_qual; +/*15*/ u_int8_t fru; +/*16*/ u_int8_t sense_key_spec_1; +#define SSD_SCS_VALID 0x80 +#define SSD_SCS_CDB_ERROR 0x40 +#define SSD_SCS_SEGMENT_DESC 0x20 +#define SSD_SCS_VALID_BIT_INDEX 0x08 +#define SSD_SCS_BIT_INDEX 0x07 +/*17*/ u_int8_t sense_key_spec_2; +/*18*/ u_int8_t sense_key_spec_3; +}; + +#define SKEY_NO_SENSE 0x00 +#define SKEY_RECOVERED_ERROR 0x01 +#define SKEY_NOT_READY 0x02 +#define SKEY_MEDIUM_ERROR 0x03 +#define SKEY_HARDWARE_ERROR 0x04 +#define SKEY_ILLEGAL_REQUEST 0x05 +#define SKEY_UNIT_ATTENTION 0x06 +#define SKEY_WRITE_PROTECT 0x07 +#define SKEY_BLANK_CHECK 0x08 +#define SKEY_VENDOR_UNIQUE 0x09 +#define SKEY_COPY_ABORTED 0x0A +#define SKEY_ABORTED_COMMAND 0x0B +#define SKEY_EQUAL 0x0C +#define SKEY_VOLUME_OVERFLOW 0x0D +#define SKEY_MISCOMPARE 0x0E +#define SKEY_RESERVED 0x0F + + +/* Additional sense code info */ +#define ASC_ASCQ(ssd) ((ssd->add_sense_code << 8) | ssd->add_sense_code_qual) + +#define SENSE_FILEMARK_DETECTED 0x0001 +#define SENSE_END_OF_MEDIUM_DETECTED 0x0002 +#define SENSE_SETMARK_DETECTED 0x0003 +#define SENSE_BEGINNING_OF_MEDIUM_DETECTED 0x0004 +#define SENSE_END_OF_DATA_DETECTED 0x0005 +#define SENSE_NOT_READY_BECOMING_READY 0x0401 +#define SENSE_NOT_READY_INIT_REQUIRED 0x0402 +#define SENSE_NOT_READY_FORMAT 0x0404 +#define SENSE_NOT_READY_REBUILD 0x0405 +#define SENSE_NOT_READY_RECALC 0x0406 +#define SENSE_NOT_READY_INPROGRESS 0x0407 +#define SENSE_NOT_READY_LONGWRITE 0x0408 +#define SENSE_NOT_READY_SELFTEST 0x0409 +#define SENSE_POWER_RESET_OR_BUS 0x2900 +#define SENSE_POWER_ON 0x2901 +#define SENSE_BUS_RESET 0x2902 +#define SENSE_BUS_DEVICE_RESET 0x2903 +#define SENSE_DEVICE_INTERNAL_RESET 0x2904 +#define SENSE_TSC_CHANGE_SE 0x2905 +#define SENSE_TSC_CHANGE_LVD 0x2906 +#define SENSE_IT_NEXUS_LOSS 0x2907 +#define SENSE_BAD_MEDIUM 0x3000 +#define SENSE_NR_MEDIUM_UNKNOWN_FORMAT 0x3001 +#define SENSE_NR_MEDIUM_INCOMPATIBLE_FORMAT 0x3002 +#define SENSE_NW_MEDIUM_UNKNOWN_FORMAT 0x3004 +#define SENSE_NW_MEDIUM_INCOMPATIBLE_FORMAT 0x3005 +#define SENSE_NF_MEDIUM_INCOMPATIBLE_FORMAT 0x3006 +#define SENSE_NW_MEDIUM_AC_MISMATCH 0x3008 +#define SENSE_NOMEDIUM 0x3A00 +#define SENSE_NOMEDIUM_TCLOSED 0x3A01 +#define SENSE_NOMEDIUM_TOPEN 0x3A02 +#define SENSE_NOMEDIUM_LOADABLE 0x3A03 +#define SENSE_NOMEDIUM_AUXMEM 0x3A04 +#define SENSE_CARTRIDGE_FAULT 0x5200 +#define SENSE_MEDIUM_REMOVAL_PREVENTED 0x5302 + +struct scsi_blk_desc { + u_int8_t density; + u_int8_t nblocks[3]; + u_int8_t reserved; + u_int8_t blklen[3]; +}; + +struct scsi_direct_blk_desc { + u_int8_t nblocks[4]; + u_int8_t density; + u_int8_t blklen[3]; +}; + +struct scsi_blk_desc_big { + u_int8_t nblocks[8]; + u_int8_t density; + u_int8_t reserved[3]; + u_int8_t blklen[4]; +}; + +struct scsi_mode_header { + u_int8_t data_length; /* Sense data length */ + u_int8_t medium_type; + u_int8_t dev_spec; + u_int8_t blk_desc_len; +}; +#define VALID_MODE_HDR(_x) ((_x)->data_length >= 3) + +struct scsi_mode_header_big { + u_int8_t data_length[2]; /* Sense data length */ + u_int8_t medium_type; + u_int8_t dev_spec; + u_int8_t reserved; +#define LONGLBA 0x01 + u_int8_t reserved2; + u_int8_t blk_desc_len[2]; +}; +#define VALID_MODE_HDR_BIG(_x) (_2btol((_x)->data_length) >= 6) + +/* Both disks and tapes use dev_spec to report READONLY status. */ +#define SMH_DSP_WRITE_PROT 0x80 + +union scsi_mode_sense_buf { + struct scsi_mode_header hdr; + struct scsi_mode_header_big hdr_big; + u_char buf[254]; /* 255 & 256 bytes breaks some devices. */ + /* ahci doesn't like 255, various don't like */ + /* 256 because length must fit in 8 bits. */ +} __packed; /* Ensure sizeof() is 254! */ + +struct scsi_report_luns_data { + u_int8_t length[4]; /* length of LUN inventory, in bytes */ + u_int8_t reserved[4]; /* unused */ + /* + * LUN inventory- we only support the type zero form for now. + */ +#define RPL_LUNDATA_SIZE 8 /* Bytes per lun */ + struct { + u_int8_t lundata[RPL_LUNDATA_SIZE]; + } luns[256]; /* scsi_link->luns is u_int8_t. */ +}; +#define RPL_LUNDATA_T0LUN 1 /* Type 0 LUN is in lundata[1] */ + +struct scsi_lun_array { + uint8_t luns[256]; + int count; + int dumbscan; +}; + +/* + * ATA PASS-THROUGH as per SAT2 + */ + +#define ATA_PASSTHRU_12 0xa1 +#define ATA_PASSTHRU_16 0x85 + +#define ATA_PASSTHRU_PROTO_MASK 0x1e +#define ATA_PASSTHRU_PROTO_HW_RESET 0x00 +#define ATA_PASSTHRU_PROTO_SW_RESET 0x02 +#define ATA_PASSTHRU_PROTO_NON_DATA 0x06 +#define ATA_PASSTHRU_PROTO_PIO_DATAIN 0x08 +#define ATA_PASSTHRU_PROTO_PIO_DATAOUT 0x0a +#define ATA_PASSTHRU_PROTO_DMA 0x0c +#define ATA_PASSTHRU_PROTO_DMA_QUEUED 0x0e +#define ATA_PASSTHRU_PROTO_EXEC_DIAG 0x10 +#define ATA_PASSTHRU_PROTO_NON_DATA_RST 0x12 +#define ATA_PASSTHRU_PROTO_UDMA_DATAIN 0x14 +#define ATA_PASSTHRU_PROTO_UDMA_DATAOUT 0x16 +#define ATA_PASSTHRU_PROTO_FPDMA 0x18 +#define ATA_PASSTHRU_PROTO_RESPONSE 0x1e + +#define ATA_PASSTHRU_T_DIR_MASK 0x08 +#define ATA_PASSTHRU_T_DIR_READ 0x08 +#define ATA_PASSTHRU_T_DIR_WRITE 0x00 + +#define ATA_PASSTHRU_T_LEN_MASK 0x03 +#define ATA_PASSTHRU_T_LEN_NONE 0x00 +#define ATA_PASSTHRU_T_LEN_FEATURES 0x01 +#define ATA_PASSTHRU_T_LEN_SECTOR_COUNT 0x02 +#define ATA_PASSTHRU_T_LEN_TPSIU 0x03 + +struct scsi_ata_passthru_12 { + u_int8_t opcode; + u_int8_t count_proto; + u_int8_t flags; + u_int8_t features; + u_int8_t sector_count; + u_int8_t lba_low; + u_int8_t lba_mid; + u_int8_t lba_high; + u_int8_t device; + u_int8_t command; + u_int8_t _reserved; + u_int8_t control; +}; + +struct scsi_ata_passthru_16 { + u_int8_t opcode; + u_int8_t count_proto; + u_int8_t flags; + u_int8_t features[2]; + u_int8_t sector_count[2]; + u_int8_t lba_low[2]; + u_int8_t lba_mid[2]; + u_int8_t lba_high[2]; + u_int8_t device; + u_int8_t command; + u_int8_t control; +}; + +/* + * SPI status information unit. See section 14.3.5 of SPI-3. + */ +struct scsi_status_iu_header { +/* 2*/ u_int8_t reserved[2]; +/* 3*/ u_int8_t flags; +#define SIU_SNSVALID 0x2 +#define SIU_RSPVALID 0x1 +/* 4*/ u_int8_t status; +/* 8*/ u_int8_t sense_length[4]; +/*12*/ u_int8_t pkt_failures_length[4]; + u_int8_t data[1]; /* OR */ +}; + +#define SIU_PKTFAIL_CODE(siu) ((siu)->data[3]) +#define SIU_PFC_NONE 0x00 +#define SIU_PFC_CIU_FIELDS_INVALID 0x02 +#define SIU_PFC_TMF_NOT_SUPPORTED 0x04 +#define SIU_PFC_TMF_FAILED 0x05 +#define SIU_PFC_INVALID_TYPE_CODE 0x06 +#define SIU_PFC_ILLEGAL_REQUEST 0x07 + +#define SIU_SENSE_LENGTH(siu) (_4btol((siu)->sense_length)) +#define SIU_SENSE_DATA(siu) (((siu)->flags & SIU_RSPVALID) ? \ + &(siu)->data[_4btol((siu)->pkt_failures_length)] : &(siu)->data[0]) + +/* + * Values for 'Task Management Flags' field of SPI command information unit. + * See section 14.3.1 of SPI-3. + */ +#define SIU_TASKMGMT_NONE 0x00 +#define SIU_TASKMGMT_ABORT_TASK 0x01 +#define SIU_TASKMGMT_ABORT_TASK_SET 0x02 +#define SIU_TASKMGMT_CLEAR_TASK_SET 0x04 +#define SIU_TASKMGMT_LUN_RESET 0x08 +#define SIU_TASKMGMT_TARGET_RESET 0x20 +#define SIU_TASKMGMT_CLEAR_ACA 0x40 + +/* + * Status Byte + */ +#define SCSI_OK 0x00 +#define SCSI_CHECK 0x02 +#define SCSI_COND_MET 0x04 +#define SCSI_BUSY 0x08 +#define SCSI_INTERM 0x10 +#define SCSI_INTERM_COND_MET 0x14 +#define SCSI_RESV_CONFLICT 0x18 +#define SCSI_TERMINATED 0x22 +#define SCSI_QUEUE_FULL 0x28 /* Old (Pre SCSI-3) name */ +#define SCSI_TASKSET_FULL 0x28 /* New (SCSI-3) name */ +#define SCSI_ACA_ACTIVE 0x30 + +#endif /* _SCSI_SCSI_ALL_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/scsi/scsi_changer.h b/lib/libc/include/generic-openbsd/scsi/scsi_changer.h new file mode 100644 index 000000000000..cc8f0466f3c4 --- /dev/null +++ b/lib/libc/include/generic-openbsd/scsi/scsi_changer.h @@ -0,0 +1,419 @@ +/* $OpenBSD: scsi_changer.h,v 1.11 2023/04/11 00:45:09 jsg Exp $ */ +/* $NetBSD: scsi_changer.h,v 1.7 1996/04/03 00:25:48 thorpej Exp $ */ + +/* + * Copyright (c) 1996 Jason R. Thorpe + * All rights reserved. + * + * Partially based on an autochanger driver written by Stefan Grefen + * and on an autochanger driver written by the Systems Programming Group + * at the University of Utah Computer Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgements: + * This product includes software developed by Jason R. Thorpe + * for And Communications, http://www.and.com/ + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * SCSI changer interface description + */ + +/* + * Partially derived from software written by Stefan Grefen + * (grefen@goofy.zdv.uni-mainz.de soon grefen@convex.com) + * based on the SCSI System by written Julian Elischer (julian@tfs.com) + * for TRW Financial Systems. + * + * TRW Financial Systems, in accordance with their agreement with Carnegie + * Mellon University, makes this software available to CMU to distribute + * or use in any manner that they see fit as long as this message is kept with + * the software. For this reason TFS also grants any other persons or + * organisations permission to use or modify this software. + * + * TFS supplies this software to be publicly redistributed + * on the understanding that TFS is not responsible for the correct + * functioning of this software in any circumstances. + * + * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 + */ + +#ifndef _SCSI_SCSI_CHANGER_H +#define _SCSI_SCSI_CHANGER_H + +/* + * SCSI command format + */ + +/* + * Exchange the medium in the source element with the medium + * located at the destination element. + */ +struct scsi_exchange_medium { + u_int8_t opcode; +#define EXCHANGE_MEDIUM 0xa6 + u_int8_t byte2; + u_int8_t tea[2]; /* transport element address */ + u_int8_t src[2]; /* source address */ + u_int8_t fdst[2]; /* first destination address */ + u_int8_t sdst[2]; /* second destination address */ + u_int8_t flags; +#define EXCHANGE_MEDIUM_INV1 0x01 +#define EXCHANGE_MEDIUM_INV2 0x02 + u_int8_t control; +}; + +/* + * Cause the medium changer to check all elements for medium and any + * other status relevant to the element. + */ +struct scsi_initialize_elememt_status { + u_int8_t opcode; +#define INITIALIZE_ELEMENT_STATUS 0x07 + u_int8_t byte2; + u_int8_t reserved[3]; + u_int8_t control; +}; + +/* + * Request the changer to move a unit of media from the source element + * to the destination element. + */ +struct scsi_move_medium { + u_int8_t opcode; +#define MOVE_MEDIUM 0xa5 + u_int8_t byte2; + u_int8_t tea[2]; /* transport element address */ + u_int8_t src[2]; /* source element address */ + u_int8_t dst[2]; /* destination element address */ + u_int8_t reserved[2]; + u_int8_t flags; +#define MOVE_MEDIUM_INVERT 0x01 + u_int8_t control; +}; + +/* + * Position the specified transport element (picker) in front of + * the destination element specified. + */ +struct scsi_position_to_element { + u_int8_t opcode; +#define POSITION_TO_ELEMENT 0x2b + u_int8_t byte2; + u_int8_t tea[2]; /* transport element address */ + u_int8_t dst[2]; /* destination element address */ + u_int8_t reserved[2]; + u_int8_t flags; +#define POSITION_TO_ELEMENT_INVERT 0x01 + u_int8_t control; +}; + +/* + * Request that the changer report the status of its internal elements. + */ +struct scsi_read_element_status { + u_int8_t opcode; +#define READ_ELEMENT_STATUS 0xb8 + u_int8_t byte2; +#define READ_ELEMENT_STATUS_VOLTAG 0x10 /* report volume tag info */ + /* ...next 4 bits are an element type code... */ + u_int8_t sea[2]; /* starting element address */ + u_int8_t count[2]; /* number of elements */ + u_int8_t reserved0; + u_int8_t len[3]; /* length of data buffer */ + u_int8_t reserved1; + u_int8_t control; +}; + +struct scsi_request_volume_element_address { + u_int8_t opcode; +#define REQUEST_VOLUME_ELEMENT_ADDRESS 0xb5 + u_int8_t byte2; +#define REQUEST_VOLUME_ELEMENT_ADDRESS_VOLTAG 0x10 + /* ...next 4 bits are an element type code... */ + u_int8_t eaddr[2]; /* element address */ + u_int8_t count[2]; /* number of elements */ + u_int8_t reserved0; + u_int8_t len[3]; /* length of data buffer */ + u_int8_t reserved1; + u_int8_t control; +}; + +/* XXX scsi_release */ + +/* + * Data returned by READ ELEMENT STATUS consists of an 8-byte header + * followed by one or more read_element_status_pages. + */ +struct read_element_status_header { + u_int8_t fear[2]; /* first element address reported */ + u_int8_t count[2]; /* number of elements available */ + u_int8_t reserved; + u_int8_t nbytes[3]; /* byte count of all pages */ +}; + +struct read_element_status_page_header { + u_int8_t type; /* element type code; see type codes below */ + u_int8_t flags; +#define READ_ELEMENT_STATUS_AVOLTAG 0x40 +#define READ_ELEMENT_STATUS_PVOLTAG 0x80 + u_int8_t edl[2]; /* element descriptor length */ + u_int8_t reserved; + u_int8_t nbytes[3]; /* byte count of all descriptors */ +}; + +/* + * Format of a volume tag + */ + +struct volume_tag { + u_int8_t vif[32]; /* volume identification field */ + u_int8_t reserved[2]; + u_int8_t vsn[2]; /* volume sequence number */ +}; + +struct read_element_status_descriptor { + u_int8_t eaddr[2]; /* element address */ + u_int8_t flags1; + +#define READ_ELEMENT_STATUS_FULL 0x01 +#define READ_ELEMENT_STATUS_IMPEXP 0x02 +#define READ_ELEMENT_STATUS_EXCEPT 0x04 +#define READ_ELEMENT_STATUS_ACCESS 0x08 +#define READ_ELEMENT_STATUS_EXENAB 0x10 +#define READ_ELEMENT_STATUS_INENAB 0x20 + +#define READ_ELEMENT_STATUS_MT_MASK1 0x05 +#define READ_ELEMENT_STATUS_ST_MASK1 0x0c +#define READ_ELEMENT_STATUS_IE_MASK1 0x3f +#define READ_ELEMENT_STATUS_DT_MASK1 0x0c + + u_int8_t reserved0; + u_int8_t sense_code; + u_int8_t sense_qual; + + /* + * dt_scsi_flags and dt_scsi_addr are valid only on data transport + * elements. These bytes are undefined for all other element types. + */ + u_int8_t dt_scsi_flags; + +#define READ_ELEMENT_STATUS_DT_LUNMASK 0x07 +#define READ_ELEMENT_STATUS_DT_LUVALID 0x10 +#define READ_ELEMENT_STATUS_DT_IDVALID 0x20 +#define READ_ELEMENT_STATUS_DT_NOTBUS 0x80 + + u_int8_t dt_scsi_addr; + + u_int8_t reserved1; + + u_int8_t flags2; +#define READ_ELEMENT_STATUS_INVERT 0x40 +#define READ_ELEMENT_STATUS_SVALID 0x80 + u_int8_t ssea[2]; /* source storage element address */ + + /* + * bytes 12-47: Primary volume tag information. + * (field omitted if PVOLTAG = 0) + * + * bytes 48-83: Alternate volume tag information. + * (field omitted if AVOLTAG = 0) + */ + + struct volume_tag pvoltag; /* omitted if PVOLTAG == 0 */ + struct volume_tag avoltag; /* omitted if AVOLTAG == 0 */ + + /* + * bytes 84-87: Reserved (moved up if either of the above fields + * are omitted) + * + * bytes 88-end: Vendor-specific: (moved up if either of the + * above fields are missing) + */ +}; + +/* XXX add data returned by REQUEST VOLUME ELEMENT ADDRESS */ + +/* Element type codes */ +#define ELEMENT_TYPE_MASK 0x0f /* Note: these aren't bits */ +#define ELEMENT_TYPE_ALL 0x00 +#define ELEMENT_TYPE_MT 0x01 +#define ELEMENT_TYPE_ST 0x02 +#define ELEMENT_TYPE_IE 0x03 +#define ELEMENT_TYPE_DT 0x04 + +/* + * XXX The following definitions should be common to all SCSI device types. + */ +#define PGCODE_MASK 0x3f /* valid page number bits in pg_code */ +#define PGCODE_PS 0x80 /* indicates page is savable */ + +/* + * Device capabilities page. + * + * This page defines characteristics of the element types in the + * medium changer device. + * + * Note in the definitions below, the following abbreviations are + * used: + * MT Medium transport element (picker) + * ST Storage transport element (slot) + * IE Import/export element (portal) + * DT Data transfer element (tape/disk drive) + */ +#define CAP_PAGE 0x1f +struct page_device_capabilities { + u_int8_t pg_code; /* page code (0x1f) */ + u_int8_t pg_length; /* page length (0x12) */ + + /* + * The STOR_xx bits indicate that an element of a given + * type may provide independent storage for a unit of + * media. The top four bits of this value are reserved. + */ + u_int8_t stor; +#define STOR_MT 0x01 +#define STOR_ST 0x02 +#define STOR_IE 0x04 +#define STOR_DT 0x08 + + u_int8_t reserved0; + + /* + * The MOVE_TO_yy bits indicate the changer supports + * moving a unit of medium from an element of a given type to an + * element of type yy. This is used to determine if a given + * MOVE MEDIUM command is legal. The top four bits of each + * of these values are reserved. + */ + u_int8_t move_from_mt; + u_int8_t move_from_st; + u_int8_t move_from_ie; + u_int8_t move_from_dt; +#define MOVE_TO_MT 0x01 +#define MOVE_TO_ST 0x02 +#define MOVE_TO_IE 0x04 +#define MOVE_TO_DT 0x08 + + u_int8_t reserved1[2]; + + /* + * Similar to above, but for EXCHANGE MEDIUM. + */ + u_int8_t exchange_with_mt; + u_int8_t exchange_with_st; + u_int8_t exchange_with_ie; + u_int8_t exchange_with_dt; +#define EXCHANGE_WITH_MT 0x01 +#define EXCHANGE_WITH_ST 0x02 +#define EXCHANGE_WITH_IE 0x04 +#define EXCHANGE_WITH_DT 0x08 +}; + +/* + * Medium changer element address assignment page. + * + * Some of these fields can be a little confusing, so an explanation + * is in order. + * + * Each component within a medium changer apparatus is called an + * "element". + * + * The "medium transport element address" is the address of the first + * picker (robotic arm). "Number of medium transport elements" tells + * us how many pickers exist in the changer. + * + * The "first storage element address" is the address of the first + * slot in the tape or disk magazine. "Number of storage elements" tells + * us how many slots exist in the changer. + * + * The "first import/export element address" is the address of the first + * medium portal accessible both by the medium changer and an outside + * human operator. This is where the changer might deposit tapes destined + * for some vault. The "number of import/export elements" tells us + * not many of these portals exist in the changer. NOTE: this number may + * be 0. + * + * The "first data transfer element address" is the address of the first + * tape or disk drive in the changer. "Number of data transfer elements" + * tells us how many drives exist in the changer. + */ +#define EA_PAGE 0x1d +struct page_element_address_assignment { + u_int8_t pg_code; /* page code (0x1d) */ + u_int8_t pg_length; /* page length (0x12) */ + + /* Medium transport element address */ + u_int8_t mtea[2]; + + /* Number of medium transport elements */ + u_int8_t nmte[2]; + + /* First storage element address */ + u_int8_t fsea[2]; + + /* Number of storage elements */ + u_int8_t nse[2]; + + /* First import/export element address */ + u_int8_t fieea[2]; + + /* Number of import/export elements */ + u_int8_t niee[2]; + + /* First data transfer element address */ + u_int8_t fdtea[2]; + + /* Number of data transfer elements */ + u_int8_t ndte[2]; + + u_int8_t reserved[2]; +}; + +/* + * Transport geometry parameters page. + * + * Defines whether each medium transport element is a member of a set of + * elements that share a common robotics subsystem and whether the element + * is capable of media rotation. One transport geometry descriptor is + * transferred for each medium transport element, beginning with the first + * medium transport element (other than the default transport element address + * of 0). + */ +#define TGP_PAGE 0x1e +struct page_transport_geometry_parameters { + u_int8_t pg_code; /* page code (0x1e) */ + u_int8_t pg_length; /* page length; variable */ + + /* Transport geometry descriptor(s) are here. */ + + u_int8_t misc; +#define CAN_ROTATE 0x01 + + /* Member number in transport element set. */ + u_int8_t member; +}; + +#endif /* _SCSI_SCSI_CHANGER_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/scsi/scsi_debug.h b/lib/libc/include/generic-openbsd/scsi/scsi_debug.h new file mode 100644 index 000000000000..2798355ae60b --- /dev/null +++ b/lib/libc/include/generic-openbsd/scsi/scsi_debug.h @@ -0,0 +1,76 @@ +/* $OpenBSD: scsi_debug.h,v 1.23 2022/02/28 14:48:11 krw Exp $ */ +/* $NetBSD: scsi_debug.h,v 1.7 1996/10/12 23:23:16 christos Exp $ */ + +/* + * Written by Julian Elischer (julian@tfs.com) + */ +#ifndef _SCSI_SCSI_DEBUG_H +#define _SCSI_SCSI_DEBUG_H +#ifdef _KERNEL + +/* + * These are the new debug bits. (Sat Oct 2 12:46:46 WST 1993) + * the following DEBUG bits are defined to exist in the flags word of + * the scsi_link structure. + */ +#define SDEV_DB1 0x0010 /* scsi commands, errors, data */ +#define SDEV_DB2 0x0020 /* routine flow tracking */ +#define SDEV_DB3 0x0040 /* internal to routine flows */ +#define SDEV_DB4 0x0080 /* level 4 debugging for this dev */ + +#ifdef SCSIDEBUG +/* targets and LUNs we want to debug */ +#ifndef SCSIDEBUG_BUSES +#define SCSIDEBUG_BUSES 0 +#endif /* ~SCSIDBUG_BUSES */ +#ifndef SCSIDEBUG_TARGETS +#define SCSIDEBUG_TARGETS 0 +#endif /* ~SCSIDEBUG_TARGETS */ +#ifndef SCSIDEBUG_LUNS +#define SCSIDEBUG_LUNS 0 +#endif /* ~SCSIDEBUG_LUNS */ +#ifndef SCSIDEBUG_LEVEL +#define SCSIDEBUG_LEVEL (SDEV_DB1|SDEV_DB2) +#endif /* ~SCSIDEBUG_LEVEL */ + +extern u_int32_t scsidebug_buses, scsidebug_targets, scsidebug_luns; +extern int scsidebug_level; + +extern const char *flagnames[]; +extern const char *quirknames[]; +extern const char *devicetypenames[32]; + +struct scsi_xfer; + +void scsi_show_sense(struct scsi_xfer *); +void scsi_show_xs(struct scsi_xfer *); +void scsi_show_mem(u_char *, int); +void scsi_show_flags(u_int32_t, const char **); +void scsi_show_inquiry_header(struct scsi_inquiry_data *); +void scsi_show_inquiry_match(struct scsi_inquiry_data *); + +/* + * This is the usual debug macro for use with the above bits + */ +#define SC_DEBUG(link,Level,Printstuff) do { \ + if ((link)->flags & (Level)) { \ + sc_print_addr(link); \ + printf Printstuff; \ + } \ +} while (0) +#define SC_DEBUGN(link,Level,Printstuff) do { \ + if ((link)->flags & (Level)) { \ + printf Printstuff; \ + } \ +} while (0) +#define SC_DEBUG_SENSE(xs) do { \ + scsi_show_sense(xs); \ +} while (0) +#else +#define SC_DEBUG(link,level,Printstuff) +#define SC_DEBUGN(link,level,Printstuff) +#define SC_DEBUG_SENSE(xs) +#endif /* SCSIDEBUG */ + +#endif /* _KERNEL */ +#endif /* _SCSI_SCSI_DEBUG_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/scsi/scsi_disk.h b/lib/libc/include/generic-openbsd/scsi/scsi_disk.h new file mode 100644 index 000000000000..93f7b696fe47 --- /dev/null +++ b/lib/libc/include/generic-openbsd/scsi/scsi_disk.h @@ -0,0 +1,496 @@ +/* $OpenBSD: scsi_disk.h,v 1.43 2022/01/11 23:10:11 jsg Exp $ */ +/* $NetBSD: scsi_disk.h,v 1.10 1996/07/05 16:19:05 christos Exp $ */ + +/* + * SCSI interface description + */ + +/* + * Some lines of this file come from a file of the name "scsi.h" + * distributed by OSF as part of mach2.5, + * so the following disclaimer has been kept. + * + * Copyright 1990 by Open Software Foundation, + * Grenoble, FRANCE + * + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation, and that the name of OSF or Open Software + * Foundation not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Largely written by Julian Elischer (julian@tfs.com) + * for TRW Financial Systems. + * + * TRW Financial Systems, in accordance with their agreement with Carnegie + * Mellon University, makes this software available to CMU to distribute + * or use in any manner that they see fit as long as this message is kept with + * the software. For this reason TFS also grants any other persons or + * organisations permission to use or modify this software. + * + * TFS supplies this software to be publicly redistributed + * on the understanding that TFS is not responsible for the correct + * functioning of this software in any circumstances. + * + * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 + */ + +/* + * SCSI command format + */ + +#ifndef _SCSI_SCSI_DISK_H +#define _SCSI_SCSI_DISK_H + +/* + * XXX Is this also used by ATAPI? + */ +#define FORMAT_UNIT 0x04 +struct scsi_format_unit { + u_int8_t opcode; + u_int8_t flags; +#define SFU_DLF_MASK 0x07 +#define SFU_CMPLST 0x08 +#define SFU_FMTDATA 0x10 + u_int8_t vendor_specific; + u_int8_t interleave[2]; + u_int8_t control; +}; + +/* + * If the FmtData bit is set, a FORMAT UNIT parameter list is transferred + * to the target during the DATA OUT phase. The parameter list includes + * + * Defect list header + * Initialization pattern descriptor (if any) + * Defect descriptor(s) (if any) + */ + +struct scsi_format_unit_defect_list_header { + u_int8_t reserved; + u_int8_t flags; +#define DLH_VS 0x01 /* vendor specific */ +#define DLH_IMMED 0x02 /* immediate return */ +#define DLH_DSP 0x04 /* disable saving parameters */ +#define DLH_IP 0x08 /* initialization pattern */ +#define DLH_STPF 0x10 /* stop format */ +#define DLH_DCRT 0x20 /* disable certification */ +#define DLH_DPRY 0x40 /* disable primary */ +#define DLH_FOV 0x80 /* format options valid */ + u_int8_t defect_lst_len[2]; +}; + +/* + * See Table 117 of the SCSI-2 specification for a description of + * the IP modifier. + */ +struct scsi_initialization_pattern_descriptor { + u_int8_t ip_modifier; + u_int8_t pattern_type; +#define IP_TYPE_DEFAULT 0x01 +#define IP_TYPE_REPEAT 0x01 + /* 0x02 -> 0x7f: reserved */ + /* 0x80 -> 0xff: vendor-specific */ + u_int8_t pattern_length[2]; +#if 0 + u_int8_t pattern[...]; +#endif /* 0 */ +}; + +/* + * Defect descriptors. These are used as the defect lists in the FORMAT UNIT + * and READ DEFECT DATA commands, and as the translate page of the + * SEND DIAGNOSTIC and RECEIVE DIAGNOSTIC RESULTS commands. + */ + +/* Block format */ +struct scsi_defect_descriptor_bf { + u_int8_t block_address[4]; +}; + +/* Bytes from index format */ +struct scsi_defect_descriptor_bfif { + u_int8_t cylinder[2]; + u_int8_t head; + u_int8_t bytes_from_index[2]; +}; + +/* Physical sector format */ +struct scsi_defect_descriptor_psf { + u_int8_t cylinder[2]; + u_int8_t head; + u_int8_t sector[2]; +}; + + +struct scsi_reassign_blocks { + u_int8_t opcode; + u_int8_t byte2; + u_int8_t unused[3]; + u_int8_t control; +}; + +/* + * XXX Is this also used by ATAPI? + */ +#define REZERO_UNIT 0x01 +struct scsi_rezero_unit { + u_int8_t opcode; + u_int8_t byte2; + u_int8_t reserved[3]; + u_int8_t control; +}; + +struct scsi_rw { + u_int8_t opcode; + u_int8_t addr[3]; +#define SRW_TOPADDR 0x1F /* only 5 bits here */ + u_int8_t length; + u_int8_t control; +}; + +struct scsi_rw_10 { + u_int8_t opcode; + u_int8_t byte2; +#define SRWB_RELADDR 0x01 + u_int8_t addr[4]; + u_int8_t reserved; + u_int8_t length[2]; + u_int8_t control; +}; + +struct scsi_rw_12 { + u_int8_t opcode; + u_int8_t byte2; + u_int8_t addr[4]; + u_int8_t length[4]; + u_int8_t reserved; + u_int8_t control; +}; + +struct scsi_rw_16 { + u_int8_t opcode; + u_int8_t byte2; + u_int8_t addr[8]; + u_int8_t length[4]; + u_int8_t reserved; + u_int8_t control; +}; + +struct scsi_write_same_10 { + u_int8_t opcode; + u_int8_t flags; +#define WRITE_SAME_F_LBDATA (1 << 1) +#define WRITE_SAME_F_PBDATA (1 << 2) + u_int8_t lba[4]; + u_int8_t group_number; + u_int8_t length[2]; + u_int8_t control; +}; + +struct scsi_write_same_16 { + u_int8_t opcode; + u_int8_t flags; +/* includes WRITE SAME 10 flags */ +#define WRITE_SAME_F_UNMAP (1 << 3) +#define WRITE_SAME_F_ANCHOR (1 << 4) + u_int8_t lba[8]; + u_int8_t length[4]; + u_int8_t group_number; + u_int8_t control; +}; + +struct scsi_unmap { + u_int8_t opcode; + u_int8_t anchor; + u_int8_t _reserved[4]; + u_int8_t group_number; + u_int8_t list_len[2]; + u_int8_t control; +}; + +struct scsi_unmap_data { + u_int8_t data_length[2]; + u_int8_t desc_length[2]; + u_int8_t _reserved[4]; + + /* followed by struct scsi_unmap_desc */ +}; + +struct scsi_unmap_desc { + u_int8_t logical_addr[8]; + u_int8_t logical_blocks[4]; + u_int8_t _reserved[4]; +}; + +struct scsi_read_capacity { + u_int8_t opcode; + u_int8_t byte2; + u_int8_t addr[4]; + u_int8_t unused[3]; + u_int8_t control; +}; + +struct scsi_read_capacity_16 { + u_int8_t opcode; + u_int8_t byte2; +#define SRC16_SERVICE_ACTION 0x10 + u_int8_t addr[8]; + u_int8_t length[4]; + u_int8_t reserved; + u_int8_t control; +}; + +struct scsi_start_stop { + u_int8_t opcode; + u_int8_t byte2; + u_int8_t unused[2]; + u_int8_t how; +#define SSS_STOP 0x00 +#define SSS_START 0x01 +#define SSS_LOEJ 0x02 + u_int8_t control; +}; + + +/* + * XXX Does ATAPI have an equivalent? + */ +struct scsi_synchronize_cache { + u_int8_t opcode; + u_int8_t flags; +#define SSC_RELADR 0x01 +#define SSC_IMMED 0x02 + u_int8_t addr[4]; + u_int8_t reserved; + u_int8_t length[2]; + u_int8_t control; +}; + + + +/* + * Disk specific opcodes + */ +#define REASSIGN_BLOCKS 0x07 +#define READ_COMMAND 0x08 +#define WRITE_COMMAND 0x0a +#define READ_CAPACITY 0x25 +#define READ_CAPACITY_16 0x9e +#define READ_10 0x28 +#define WRITE_10 0x2a +#define READ_12 0xa8 +#define WRITE_12 0xaa +#define READ_16 0x88 +#define WRITE_16 0x8a +#define SYNCHRONIZE_CACHE 0x35 +#define WRITE_SAME_10 0x41 +#define WRITE_SAME_16 0x93 +#define UNMAP 0x42 + + +struct scsi_reassign_blocks_data { + u_int8_t reserved[2]; + u_int8_t length[2]; + struct { + u_int8_t dlbaddr[4]; + } defect_descriptor[1]; +}; + +/* Only the lower 6 bits of the pg_code field are used for page #. */ +#define PAGE_DISK_FORMAT 3 +#define PAGE_RIGID_GEOMETRY 4 +#define PAGE_FLEX_GEOMETRY 5 +#define PAGE_REDUCED_GEOMETRY 6 +#define PAGE_CACHING_MODE 8 + +struct page_disk_format { + u_int8_t pg_code; /* page code (should be 3) */ + u_int8_t pg_length; /* page length (should be 0x16) */ + u_int8_t trk_z[2]; /* tracks per zone */ + u_int8_t alt_sec[2]; /* alternate sectors per zone */ + u_int8_t alt_trk_z[2]; /* alternate tracks per zone */ + u_int8_t alt_trk_v[2]; /* alternate tracks per volume */ + u_int8_t ph_sec_t[2]; /* physical sectors per track */ + u_int8_t bytes_s[2]; /* bytes per sector */ + u_int8_t interleave[2]; /* interleave */ + u_int8_t trk_skew[2]; /* track skew factor */ + u_int8_t cyl_skew[2]; /* cylinder skew */ + u_int8_t flags; /* various */ +#define DISK_FMT_SURF 0x10 +#define DISK_FMT_RMB 0x20 +#define DISK_FMT_HSEC 0x40 +#define DISK_FMT_SSEC 0x80 + u_int8_t reserved1; + u_int8_t reserved2; + u_int8_t reserved3; +}; + +struct page_rigid_geometry { + u_int8_t pg_code; /* page code (should be 4) */ + u_int8_t pg_length; /* page length (should be 0x12 or 0x16) */ + u_int8_t ncyl[3]; /* number of cylinders */ + u_int8_t nheads; /* number of heads */ + u_int8_t st_cyl_wp[3]; /* starting cyl., write precomp */ + u_int8_t st_cyl_rwc[3]; /* starting cyl., red. write cur */ + u_int8_t driv_step[2]; /* drive step rate */ + u_int8_t land_zone[3]; /* landing zone cylinder */ + u_int8_t sp_sync_ctl; /* spindle synch control */ +#define SPINDLE_SYNCH_MASK 0x03 /* mask of valid bits */ +#define SPINDLE_SYNCH_NONE 0x00 /* synch disabled or not supported */ +#define SPINDLE_SYNCH_SLAVE 0x01 /* disk is a slave */ +#define SPINDLE_SYNCH_MASTER 0x02 /* disk is a master */ +#define SPINDLE_SYNCH_MCONTROL 0x03 /* disk is a master control */ + u_int8_t rot_offset; /* rotational offset (for spindle synch) */ + u_int8_t reserved1; + u_int8_t rpm[2]; /* media rotation speed */ + u_int8_t reserved2; + u_int8_t reserved3; +}; + +struct page_flex_geometry { + u_int8_t pg_code; /* page code (should be 5) */ + u_int8_t pg_length; /* page length (should be 0x1a or 0x1e) */ + u_int8_t xfr_rate[2]; + u_int8_t nheads; /* number of heads */ + u_int8_t ph_sec_tr; /* physical sectors per track */ + u_int8_t bytes_s[2]; /* bytes per sector */ + u_int8_t ncyl[2]; /* number of cylinders */ + u_int8_t st_cyl_wp[2]; /* start cyl., write precomp */ + u_int8_t st_cyl_rwc[2]; /* start cyl., red. write cur */ + u_int8_t driv_step[2]; /* drive step rate */ + u_int8_t driv_step_w; /* drive step pulse width */ + u_int8_t head_settle[2];/* head settle delay */ + u_int8_t motor_on; /* motor on delay */ + u_int8_t motor_off; /* motor off delay */ + u_int8_t flags; /* various flags */ +#define MOTOR_ON 0x20 /* motor on (pin 16)? */ +#define START_AT_SECTOR_1 0x40 /* start at sector 1 */ +#define READY_VALID 0x20 /* RDY (pin 34) valid */ + u_int8_t step_p_cyl; /* step pulses per cylinder */ + u_int8_t write_pre; /* write precompensation */ + u_int8_t head_load; /* head load delay */ + u_int8_t head_unload; /* head unload delay */ + u_int8_t pin_34_2; /* pin 34 (6) pin 2 (7/11) definition */ + u_int8_t pin_4_1; /* pin 4 (8/9) pin 1 (13) definition */ + u_int8_t rpm[2]; /* media rotation speed */ + u_int8_t reserved1; + u_int8_t reserved2; +}; + +struct page_reduced_geometry { + u_int8_t pg_code; /* page code (should be 6) */ + u_int8_t pg_length; /* page length (should be 0x0B) */ + u_int8_t wcd; /* bit 0 = write cache disable */ + u_int8_t bytes_s[2]; /* bytes per sector */ + u_int8_t sectors[5]; /* total number of sectors */ + u_int8_t pow_perf; /* power/performance level */ + u_int8_t flags; /* various */ +#define LOCK_DISABLED 0x1 +#define FORMAT_DISABLED 0x2 +#define WRITE_DISABLED 0x4 +#define READ_DISABLED 0x8 + u_int8_t reserved; +}; + +struct page_caching_mode { + u_int8_t pg_code; /* page code (should be 8) */ + u_int8_t pg_length; /* page length (should be 0x12) */ + u_int8_t flags; +#define PG_CACHE_FL_RCD (1<<0) +#define PG_CACHE_FL_MF (1<<1) +#define PG_CACHE_FL_WCE (1<<2) +#define PG_CACHE_FL_SIZE (1<<3) +#define PG_CACHE_FL_DISC (1<<4) +#define PG_CACHE_FL_CAP (1<<5) +#define PG_CACHE_FL_ABPF (1<<6) +#define PG_CACHE_FL_IC (1<<7) + u_int8_t priority; +#define PG_CACHE_PRI_DEMAND(_f) ((_f) & 0x0f) +#define PG_CACHE_PRI_WRITE(_f) (((_f) >> 4) & 0x0f) + u_int8_t dis_prefetch_tl[2]; + u_int8_t min_prefetch[2]; + u_int8_t max_prefetch[2]; + u_int8_t max_prefetch_ceil[2]; +}; + +#define SI_PG_DISK_LIMITS 0xb0 /* block limits */ +#define SI_PG_DISK_INFO 0xb1 /* device characteristics */ +#define SI_PG_DISK_THIN 0xb2 /* thin provisioning */ + +struct scsi_vpd_disk_limits { + struct scsi_vpd_hdr hdr; +#define SI_PG_DISK_LIMITS_LEN 0x10 +#define SI_PG_DISK_LIMITS_LEN_THIN 0x3c + + u_int8_t _reserved1[1]; + u_int8_t max_comp_wr_len; + u_int8_t optimal_xfer_granularity[2]; + + u_int8_t max_xfer_len[4]; + + u_int8_t optimal_xfer[4]; + + u_int8_t max_xd_prefetch_len[4]; + + u_int8_t max_unmap_lba_count[4]; + + u_int8_t max_unmap_desc_count[4]; + + u_int8_t optimal_unmap_granularity[4]; + + u_int8_t unmap_granularity_align[4]; +#define SI_PG_DISK_LIMITS_UGAVALID (1U << 31) + + u_int8_t _reserved2[28]; +}; + +struct scsi_vpd_disk_info { + struct scsi_vpd_hdr hdr; + u_int8_t rpm[2]; +#define VPD_DISK_INFO_RPM_UNDEF 0x0000 +#define VPD_DISK_INFO_RPM_NONE 0x0001 + u_int8_t _reserved1[1]; + u_int8_t form_factor; +#define VPD_DISK_INFO_FORM_MASK 0xf +#define VPD_DISK_INFO_FORM_UNDEF 0x0 +#define VPD_DISK_INFO_FORM_5_25 0x1 +#define VPD_DISK_INFO_FORM_3_5 0x2 +#define VPD_DISK_INFO_FORM_2_5 0x3 +#define VPD_DISK_INFO_FORM_1_8 0x4 +#define VPD_DISK_INFO_FORM_LT_1_8 0x5 + u_int8_t _reserved2[56]; +}; + +struct scsi_vpd_disk_thin { + struct scsi_vpd_hdr hdr; + + u_int8_t threshold_exponent; + u_int8_t flags; +#define VPD_DISK_THIN_DP (1 << 0) /* descriptor present */ +#define VPD_DISK_THIN_ANC_SUP (0x7 << 1) +#define VPD_DISK_THIN_ANC_SUP_NO (0x0 << 1) +#define VPD_DISK_THIN_ANC_SUP_YES (0x1 << 1) +#define VPD_DISK_THIN_TPWS (1 << 6) /* WRITE SAME 16 */ +#define VPD_DISK_THIN_TPU (1 << 7) /* UNMAP */ + u_int8_t _reserved1[2]; + + /* followed by a designation descriptor if DP is set */ +}; + +#endif /* _SCSI_SCSI_DISK_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/scsi/scsi_message.h b/lib/libc/include/generic-openbsd/scsi/scsi_message.h new file mode 100644 index 000000000000..132da6165580 --- /dev/null +++ b/lib/libc/include/generic-openbsd/scsi/scsi_message.h @@ -0,0 +1,67 @@ +/* $OpenBSD: scsi_message.h,v 1.10 2019/09/27 23:07:42 krw Exp $ */ + +#ifndef _SCSI_SCSI_MESSAGE_H +#define _SCSI_SCSI_MESSAGE_H + +#define IS1BYTEMSG(m) (((m) != 0x01 && (m) < 0x20) || (m) >= 0x80) +#define IS2BYTEMSG(m) (((m) & 0xf0) == 0x20) +#define ISEXTMSG(m) ((m) == 0x01) + +/* Messages (1 byte) */ /* I/T (M)andatory or (O)ptional */ +#define MSG_CMDCOMPLETE 0x00 /* M/M */ +#define MSG_EXTENDED 0x01 /* O/O */ +#define MSG_SAVEDATAPOINTER 0x02 /* O/O */ +#define MSG_RESTOREPOINTERS 0x03 /* O/O */ +#define MSG_DISCONNECT 0x04 /* O/O */ +#define MSG_INITIATOR_DET_ERR 0x05 /* M/M */ +#define MSG_ABORT 0x06 /* O/M */ +#define MSG_MESSAGE_REJECT 0x07 /* M/M */ +#define MSG_NOOP 0x08 /* M/M */ +#define MSG_PARITY_ERROR 0x09 /* M/M */ +#define MSG_LINK_CMD_COMPLETE 0x0a /* O/O */ +#define MSG_LINK_CMD_COMPLETEF 0x0b /* O/O */ +#define MSG_BUS_DEV_RESET 0x0c /* O/M */ +#define MSG_ABORT_TAG 0x0d /* O/O */ +#define MSG_CLEAR_QUEUE 0x0e /* O/O */ +#define MSG_INIT_RECOVERY 0x0f /* O/O */ +#define MSG_REL_RECOVERY 0x10 /* O/O */ +#define MSG_TERM_IO_PROC 0x11 /* O/O */ +#define MSG_QAS_REQUEST 0x55 /* O/O */ /* SPI3 */ + +/* Messages (2 byte) */ +#define MSG_SIMPLE_Q_TAG 0x20 /* O/O */ +#define MSG_HEAD_OF_Q_TAG 0x21 /* O/O */ +#define MSG_ORDERED_Q_TAG 0x22 /* O/O */ +#define MSG_IGN_WIDE_RESIDUE 0x23 /* O/O */ + +/* Identify message */ /* M/M */ +#define MSG_IDENTIFYFLAG 0x80 +#define MSG_IDENTIFY_DISCFLAG 0x40 +#define MSG_IDENTIFY(lun, disc) (((disc) ? 0xc0 : MSG_IDENTIFYFLAG) | (lun)) +#define MSG_ISIDENTIFY(m) ((m) & MSG_IDENTIFYFLAG) +#define MSG_IDENTIFY_LUNMASK 0x01F + +/* Extended messages (opcode and length) */ +#define MSG_EXT_SDTR 0x01 +#define MSG_EXT_SDTR_LEN 0x03 + +#define MSG_EXT_WDTR 0x03 +#define MSG_EXT_WDTR_LEN 0x02 + +#define MSG_EXT_WDTR_BUS_8_BIT 0x00 +#define MSG_EXT_WDTR_BUS_16_BIT 0x01 +#define MSG_EXT_WDTR_BUS_32_BIT 0x02 + +#define MSG_EXT_PPR 0x04 +#define MSG_EXT_PPR_LEN 0x06 + +#define MSG_EXT_PPR_PCOMP_EN 0x80 +#define MSG_EXT_PPR_RTI 0x40 +#define MSG_EXT_PPR_RD_STRM 0x20 +#define MSG_EXT_PPR_WR_FLOW 0x10 +#define MSG_EXT_PPR_HOLD_MCS 0x08 +#define MSG_EXT_PPR_PROT_QAS 0x04 +#define MSG_EXT_PPR_PROT_DT 0x02 +#define MSG_EXT_PPR_PROT_IUS 0x01 + +#endif /* _SCSI_SCSI_MESSAGE_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/scsi/scsi_tape.h b/lib/libc/include/generic-openbsd/scsi/scsi_tape.h new file mode 100644 index 000000000000..014e28b16d2f --- /dev/null +++ b/lib/libc/include/generic-openbsd/scsi/scsi_tape.h @@ -0,0 +1,240 @@ +/* $OpenBSD: scsi_tape.h,v 1.11 2019/09/27 23:07:42 krw Exp $ */ +/* $NetBSD: scsi_tape.h,v 1.9 1996/05/24 02:04:47 thorpej Exp $ */ + +/* + * Copyright (c) 1994 Charles Hannum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Charles Hannum. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Originally written by Julian Elischer (julian@tfs.com) + * for TRW Financial Systems. + * + * TRW Financial Systems, in accordance with their agreement with Carnegie + * Mellon University, makes this software available to CMU to distribute + * or use in any manner that they see fit as long as this message is kept with + * the software. For this reason TFS also grants any other persons or + * organisations permission to use or modify this software. + * + * TFS supplies this software to be publicly redistributed + * on the understanding that TFS is not responsible for the correct + * functioning of this software in any circumstances. + * + * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 + */ + +/* + * SCSI tape interface description + */ + +#ifndef _SCSI_SCSI_TAPE_H +#define _SCSI_SCSI_TAPE_H + +/* + * SCSI command formats + */ + +#define READ 0x08 +#define WRITE 0x0a +struct scsi_rw_tape { + u_int8_t opcode; + u_int8_t byte2; +#define SRW_FIXED 0x01 + u_int8_t len[3]; + u_int8_t control; +}; + +#define SPACE 0x11 +struct scsi_space { + u_int8_t opcode; + u_int8_t byte2; +#define SS_CODE 0x03 +#define SP_BLKS 0x00 +#define SP_FILEMARKS 0x01 +#define SP_SEQ_FILEMARKS 0x02 +#define SP_EOM 0x03 + u_int8_t number[3]; + u_int8_t control; +}; + +#define WRITE_FILEMARKS 0x10 +struct scsi_write_filemarks { + u_int8_t opcode; + u_int8_t byte2; + u_int8_t number[3]; + u_int8_t control; +}; + +#define REWIND 0x01 +struct scsi_rewind { + u_int8_t opcode; + u_int8_t byte2; +#define SR_IMMED 0x01 + u_int8_t unused[3]; + u_int8_t control; +}; + +#define LOAD 0x1b +struct scsi_load { + u_int8_t opcode; + u_int8_t byte2; +#define SL_IMMED 0x01 + u_int8_t unused[2]; + u_int8_t how; +#define LD_UNLOAD 0x00 +#define LD_LOAD 0x01 +#define LD_RETENSION 0x02 + u_int8_t control; +}; + +#define ERASE 0x19 +struct scsi_erase { + u_int8_t opcode; + u_int8_t byte2; +#define SE_LONG 0x01 +#define SE_IMMED 0x02 + u_int8_t unused[3]; + u_int8_t control; +}; + +#define READ_BLOCK_LIMITS 0x05 +struct scsi_block_limits { + u_int8_t opcode; + u_int8_t byte2; + u_int8_t unused[3]; + u_int8_t control; +}; + +struct scsi_block_limits_data { + u_int8_t reserved; + u_int8_t max_length[3]; /* Most significant */ + u_int8_t min_length[2]; /* Most significant */ +}; + +/* See SCSI-II spec 9.3.3.1 */ +struct scsi_tape_dev_conf_page { + u_int8_t pagecode; /* 0x10 */ + u_int8_t pagelength; /* 0x0e */ + u_int8_t byte2; +#define SMT_CAP 0x40 /* change active partition */ +#define SMT_CAF 0x20 /* change active format */ +#define SMT_AFMASK 0x1f /* active format mask */ + u_int8_t active_partition; + u_int8_t wb_full_ratio; + u_int8_t rb_empty_ratio; + u_int8_t wrdelay_time[2]; + u_int8_t byte8; +#define SMT_DBR 0x80 /* data buffer recovery */ +#define SMT_BIS 0x40 /* block identifiers supported */ +#define SMT_RSMK 0x20 /* report setmarks */ +#define SMT_AVC 0x10 /* automatic velocity control */ +#define SMT_SOCF_MASK 0xc0 /* stop on consecutive formats */ +#define SMT_RBO 0x20 /* recover buffer order */ +#define SMT_REW 0x10 /* report early warning */ + u_int8_t gap_size; + u_int8_t byte10; +#define SMT_EODDEFINED 0xe0 /* EOD defined */ +#define SMT_EEG 0x10 /* enable EOD generation */ +#define SMT_SEW 0x80 /* synchronize at early warning */ + u_int8_t ew_bufsize[3]; + u_int8_t sel_comp_alg; +#define SMT_COMP_NONE 0x00 +#define SMT_COMP_DEFAULT 0x01 + u_int8_t reserved; +}; + +/* defines for the device specific byte in the mode select/sense header */ +#define SMH_DSP_SPEED 0x0F +#define SMH_DSP_BUFF_MODE 0x70 +#define SMH_DSP_BUFF_MODE_OFF 0x00 +#define SMH_DSP_BUFF_MODE_ON 0x10 +#define SMH_DSP_BUFF_MODE_MLTI 0x20 + +/********************************************************************** + from the scsi2 spec + Value Tracks Density(bpi) Code Type Reference Note + 0x1 9 800 NRZI R X3.22-1983 2 + 0x2 9 1600 PE R X3.39-1986 2 + 0x3 9 6250 GCR R X3.54-1986 2 + 0x5 4/9 8000 GCR C X3.136-1986 1 + 0x6 9 3200 PE R X3.157-1987 2 + 0x7 4 6400 IMFM C X3.116-1986 1 + 0x8 4 8000 GCR CS X3.158-1986 1 + 0x9 18 37871 GCR C X3B5/87-099 2 + 0xA 22 6667 MFM C X3B5/86-199 1 + 0xB 4 1600 PE C X3.56-1986 1 + 0xC 24 12690 GCR C HI-TC1 1,5 + 0xD 24 25380 GCR C HI-TC2 1,5 + 0xF 15 10000 GCR C QIC-120 1,5 + 0x10 18 10000 GCR C QIC-150 1,5 + 0x11 26 16000 GCR C QIC-320(525?) 1,5 + 0x12 30 51667 RLL C QIC-1350 1,5 + 0x13 1 61000 DDS CS X3B5/88-185A 4 + 0x14 1 43245 RLL CS X3.202-1991 4 + 0x15 1 45434 RLL CS ECMA TC17 4 + 0x16 48 10000 MFM C X3.193-1990 1 + 0x17 48 42500 MFM C X3B5/91-174 1 + 0x45 73 67733 RLL C QIC3095 + + where Code means: + NRZI Non Return to Zero, change on ones + GCR Group Code Recording + PE Phase Encoded + IMFM Inverted Modified Frequency Modulation + MFM Modified Frequency Modulation + DDS Dat Data Storage + RLL Run Length Encoding + + where Type means: + R Reel-to-Reel + C Cartridge + CS cassette + + where Notes means: + 1 Serial Recorded + 2 Parallel Recorded + 3 Old format know as QIC-11 + 4 Helical Scan + 5 Not ANSI standard, rather industry standard. +********************************************************************/ + +#define HALFINCH_800 0x01 +#define HALFINCH_1600 0x02 +#define HALFINCH_6250 0x03 +#define QIC_11 0x04 /* from Archive 150S Theory of Op. XXX */ +#define QIC_24 0x05 /* may be bad, works for CIPHER ST150S XXX */ +#define QIC_120 0x0f +#define QIC_150 0x10 +#define QIC_320 0x11 +#define QIC_525 0x11 +#define QIC_1320 0x12 +#define DDS 0x13 +#define DAT_1 0x13 +#define QIC_3080 0x29 +#define QIC_3095 0x45 + +#endif /* _SCSI_SCSI_TAPE_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/scsi/scsiconf.h b/lib/libc/include/generic-openbsd/scsi/scsiconf.h new file mode 100644 index 000000000000..d05d6e0c1b40 --- /dev/null +++ b/lib/libc/include/generic-openbsd/scsi/scsiconf.h @@ -0,0 +1,579 @@ +/* $OpenBSD: scsiconf.h,v 1.202 2023/05/10 15:28:26 krw Exp $ */ +/* $NetBSD: scsiconf.h,v 1.35 1997/04/02 02:29:38 mycroft Exp $ */ + +/* + * Copyright (c) 1993, 1994, 1995 Charles Hannum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Charles Hannum. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Originally written by Julian Elischer (julian@tfs.com) + * for TRW Financial Systems for use under the MACH(2.5) operating system. + * + * TRW Financial Systems, in accordance with their agreement with Carnegie + * Mellon University, makes this software available to CMU to distribute + * or use in any manner that they see fit as long as this message is kept with + * the software. For this reason TFS also grants any other persons or + * organisations permission to use or modify this software. + * + * TFS supplies this software to be publicly redistributed + * on the understanding that TFS is not responsible for the correct + * functioning of this software in any circumstances. + * + * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 + */ + +#ifndef _SCSI_SCSICONF_H +#define _SCSI_SCSICONF_H + +#include +#include +#include + +static __inline void _lto2b(u_int32_t val, u_int8_t *bytes); +static __inline void _lto3b(u_int32_t val, u_int8_t *bytes); +static __inline void _lto4b(u_int32_t val, u_int8_t *bytes); +static __inline void _lto8b(u_int64_t val, u_int8_t *bytes); +static __inline u_int32_t _2btol(u_int8_t *bytes); +static __inline u_int32_t _3btol(u_int8_t *bytes); +static __inline u_int32_t _4btol(u_int8_t *bytes); +static __inline u_int64_t _5btol(u_int8_t *bytes); +static __inline u_int64_t _8btol(u_int8_t *bytes); + +static __inline void +_lto2b(u_int32_t val, u_int8_t *bytes) +{ + + bytes[0] = (val >> 8) & 0xff; + bytes[1] = val & 0xff; +} + +static __inline void +_lto3b(u_int32_t val, u_int8_t *bytes) +{ + + bytes[0] = (val >> 16) & 0xff; + bytes[1] = (val >> 8) & 0xff; + bytes[2] = val & 0xff; +} + +static __inline void +_lto4b(u_int32_t val, u_int8_t *bytes) +{ + + bytes[0] = (val >> 24) & 0xff; + bytes[1] = (val >> 16) & 0xff; + bytes[2] = (val >> 8) & 0xff; + bytes[3] = val & 0xff; +} + +static __inline void +_lto8b(u_int64_t val, u_int8_t *bytes) +{ + + bytes[0] = (val >> 56) & 0xff; + bytes[1] = (val >> 48) & 0xff; + bytes[2] = (val >> 40) & 0xff; + bytes[3] = (val >> 32) & 0xff; + bytes[4] = (val >> 24) & 0xff; + bytes[5] = (val >> 16) & 0xff; + bytes[6] = (val >> 8) & 0xff; + bytes[7] = val & 0xff; +} + +static __inline u_int32_t +_2btol(u_int8_t *bytes) +{ + u_int32_t rv; + + rv = (bytes[0] << 8) | bytes[1]; + return rv; +} + +static __inline u_int32_t +_3btol(u_int8_t *bytes) +{ + u_int32_t rv; + + rv = (bytes[0] << 16) | (bytes[1] << 8) | bytes[2]; + return rv; +} + +static __inline u_int32_t +_4btol(u_int8_t *bytes) +{ + u_int32_t rv; + + rv = (bytes[0] << 24) | (bytes[1] << 16) | + (bytes[2] << 8) | bytes[3]; + return rv; +} + +static __inline u_int64_t +_5btol(u_int8_t *bytes) +{ + u_int64_t rv; + + rv = ((u_int64_t)bytes[0] << 32) | + ((u_int64_t)bytes[1] << 24) | + ((u_int64_t)bytes[2] << 16) | + ((u_int64_t)bytes[3] << 8) | + (u_int64_t)bytes[4]; + return rv; +} + +static __inline u_int64_t +_8btol(u_int8_t *bytes) +{ + u_int64_t rv; + + rv = (((u_int64_t)bytes[0]) << 56) | + (((u_int64_t)bytes[1]) << 48) | + (((u_int64_t)bytes[2]) << 40) | + (((u_int64_t)bytes[3]) << 32) | + (((u_int64_t)bytes[4]) << 24) | + (((u_int64_t)bytes[5]) << 16) | + (((u_int64_t)bytes[6]) << 8) | + ((u_int64_t)bytes[7]); + return rv; +} + +#ifdef _KERNEL + +#define DEVID_NONE 0 +#define DEVID_NAA 1 +#define DEVID_EUI 2 +#define DEVID_T10 3 +#define DEVID_SERIAL 4 +#define DEVID_WWN 5 + +struct devid { + u_int8_t d_type; + u_int8_t d_flags; +#define DEVID_F_PRINT (1<<0) + u_int8_t d_refcount; + u_int8_t d_len; + + /* + * the devid struct is basically a header, the actual id is allocated + * immediately after it. + */ +}; + +#define DEVID_CMP(_a, _b) ( \ + (_a) != NULL && (_b) != NULL && \ + ((_a) == (_b) || \ + ((_a)->d_type != DEVID_NONE && \ + (_a)->d_type == (_b)->d_type && \ + (_a)->d_len == (_b)->d_len && \ + bcmp((_a) + 1, (_b) + 1, (_a)->d_len) == 0)) \ +) + +struct devid * devid_alloc(u_int8_t, u_int8_t, u_int8_t, u_int8_t *); +struct devid * devid_copy(struct devid *); +void devid_free(struct devid *); + +/* + * Each existing device (scsibus + target + lun) + * - is described by a scsi_link struct. + * Each scsi_link struct + * - identifies the device's softc and scsi_adapter. + * Each scsi_adapter struct + * - contains pointers to the device's scsi functions. + * Each scsibus_softc has an SLIST + * - holding pointers to the scsi_link structs of devices on that scsi bus. + * Each individual device + * - knows the address of its scsi_link structure. + */ + +struct scsi_xfer; +struct scsi_link; +struct scsibus_softc; + +/* + * Temporary hack + */ +extern int scsi_autoconf; + +/* + * These entrypoints are called by the high-end drivers to get services from + * whatever low-end drivers they are attached to. Each adapter type has one + * of these statically allocated. + */ +struct scsi_adapter { + void (*scsi_cmd)(struct scsi_xfer *); + void (*dev_minphys)(struct buf *, struct scsi_link *); + int (*dev_probe)(struct scsi_link *); + void (*dev_free)(struct scsi_link *); + int (*ioctl)(struct scsi_link *, u_long, caddr_t, int); +}; + +struct scsi_iopool; + +struct scsi_iohandler { + TAILQ_ENTRY(scsi_iohandler) q_entry; + u_int q_state; + + struct scsi_iopool *pool; + void (*handler)(void *, void *); + void *cookie; +}; +TAILQ_HEAD(scsi_runq, scsi_iohandler); + +struct scsi_iopool { + /* access to the IOs */ + void *iocookie; + /* + * Get an IO. This must reserve all resources that are necessary + * to send the transfer to the device. The resources must stay + * reserved during the lifetime of the IO, as the IO may be re-used + * without being io_put(), first. + */ + void *(*io_get)(void *); + void (*io_put)(void *, void *); + + /* the runqueue */ + struct scsi_runq queue; + /* runqueue semaphore */ + u_int running; + /* protection for the runqueue and its semaphore */ + struct mutex mtx; +}; + +struct scsi_xshandler { + struct scsi_iohandler ioh; /* must be first */ + + struct scsi_link *link; + void (*handler)(struct scsi_xfer *); +}; + +/* + * This structure describes the connection between an adapter driver and + * a device driver, and is used by each to call services provided by + * the other, and to allow generic scsi glue code to call these services + * as well. + */ +struct scsi_link { + SLIST_ENTRY(scsi_link) bus_list; + + u_int state; +#define SDEV_S_DYING (1<<1) + + u_int16_t target; /* targ of this dev */ + u_int16_t lun; /* lun of this dev */ + u_int16_t openings; /* available operations per lun */ + u_int64_t port_wwn; /* world wide name of port */ + u_int64_t node_wwn; /* world wide name of node */ + u_int16_t flags; /* flags that all devices have */ +#define SDEV_REMOVABLE 0x0001 /* media is removable */ +#define SDEV_MEDIA_LOADED 0x0002 /* device figures are still valid */ +#define SDEV_READONLY 0x0004 /* device is read-only */ +#define SDEV_OPEN 0x0008 /* at least 1 open session */ +#define SDEV_DBX 0x00f0 /* debugging flags (scsi_debug.h) */ +#define SDEV_EJECTING 0x0100 /* eject on device close */ +#define SDEV_ATAPI 0x0200 /* device is ATAPI */ +#define SDEV_UMASS 0x0400 /* device is UMASS SCSI */ +#define SDEV_VIRTUAL 0x0800 /* device is virtualised on the hba */ +#define SDEV_OWN_IOPL 0x1000 /* scsibus */ +#define SDEV_UFI 0x2000 /* Universal Floppy Interface */ + u_int16_t quirks; /* per-device oddities */ +#define SDEV_AUTOSAVE 0x0001 /* do implicit SAVEDATAPOINTER on disconnect */ +#define SDEV_NOSYNC 0x0002 /* does not grok SDTR */ +#define SDEV_NOWIDE 0x0004 /* does not grok WDTR */ +#define SDEV_NOTAGS 0x0008 /* lies about having tagged queueing */ +#define SDEV_NOSYNCCACHE 0x0010 /* no SYNCHRONIZE_CACHE */ +#define ADEV_NOSENSE 0x0020 /* No request sense - ATAPI */ +#define ADEV_LITTLETOC 0x0040 /* little-endian TOC - ATAPI */ +#define ADEV_NOCAPACITY 0x0080 /* no READ CD CAPACITY */ +#define ADEV_NODOORLOCK 0x0100 /* can't lock door */ + int (*interpret_sense)(struct scsi_xfer *); + void *device_softc; /* needed for call to foo_start */ + struct scsibus_softc *bus; /* link to the scsibus we're on */ + struct scsi_inquiry_data inqdata; /* copy of INQUIRY data from probe */ + struct devid *id; + + struct scsi_runq queue; + u_int running; + u_short pending; + + struct scsi_iopool *pool; +}; + +int scsiprint(void *, const char *); + +/* + * This describes matching information for scsi_inqmatch(). The more things + * match, the higher the configuration priority. + */ +struct scsi_inquiry_pattern { + u_int8_t type; + int removable; + char *vendor; + char *product; + char *revision; +}; + +struct scsibus_attach_args { + const struct scsi_adapter *saa_adapter; + void *saa_adapter_softc; + struct scsi_iopool *saa_pool; + u_int64_t saa_wwpn; + u_int64_t saa_wwnn; + u_int16_t saa_quirks; + u_int16_t saa_flags; + u_int16_t saa_openings; + u_int16_t saa_adapter_target; +#define SDEV_NO_ADAPTER_TARGET 0xffff + u_int16_t saa_adapter_buswidth; + u_int8_t saa_luns; +}; + +/* + * One of these is allocated and filled in for each scsi bus. + * It holds pointers to allow the scsi bus to get to the driver + * that is running each LUN on the bus. + * It also has a template entry which is the prototype struct + * supplied by the adapter driver. This is used to initialise + * the others, before they have the rest of the fields filled in. + */ +struct scsibus_softc { + struct device sc_dev; + SLIST_HEAD(, scsi_link) sc_link_list; + void *sb_adapter_softc; + const struct scsi_adapter *sb_adapter; + struct scsi_iopool *sb_pool; + u_int16_t sb_quirks; + u_int16_t sb_flags; + u_int16_t sb_openings; + u_int16_t sb_adapter_buswidth; + u_int16_t sb_adapter_target; + u_int8_t sb_luns; +}; + +/* + * This is used to pass information from the high-level configuration code + * to the device-specific drivers. + */ +struct scsi_attach_args { + struct scsi_link *sa_sc_link; +}; + +/* + * Each scsi transaction is fully described by one of these structures. + * It includes information about the source of the command and also the + * device and adapter for which the command is destined. + * (via the scsi_link structure) + */ +struct scsi_xfer { + SIMPLEQ_ENTRY(scsi_xfer) xfer_list; + int flags; + struct scsi_link *sc_link; /* all about our device and adapter */ + int retries; /* the number of times to retry */ + int timeout; /* in milliseconds */ + struct scsi_generic cmd; /* The scsi command to execute */ + int cmdlen; /* how long it is */ + u_char *data; /* dma address OR a uio address */ + int datalen; /* data len (blank if uio) */ + size_t resid; /* how much buffer was not touched */ + int error; /* an error value */ + struct buf *bp; /* If we need to associate with a buf */ + struct scsi_sense_data sense; /* 18 bytes*/ + u_int8_t status; /* SCSI status */ + /* + * timeout structure for hba's to use for a command + */ + struct timeout stimeout; + void *cookie; + void (*done)(struct scsi_xfer *); + + void *io; /* adapter io resource */ +}; +SIMPLEQ_HEAD(scsi_xfer_list, scsi_xfer); + +/* + * Per-request Flag values + */ +#define SCSI_NOSLEEP 0x00001 /* don't sleep */ +#define SCSI_POLL 0x00002 /* poll for completion */ +#define SCSI_AUTOCONF 0x00003 /* shorthand for SCSI_POLL | SCSI_NOSLEEP */ +#define ITSDONE 0x00008 /* the transfer is as done as it gets */ +#define SCSI_SILENT 0x00020 /* don't announce NOT READY or MEDIA CHANGE */ +#define SCSI_IGNORE_NOT_READY 0x00040 /* ignore NOT READY */ +#define SCSI_IGNORE_MEDIA_CHANGE 0x00080 /* ignore MEDIA CHANGE */ +#define SCSI_IGNORE_ILLEGAL_REQUEST 0x00100 /* ignore ILLEGAL REQUEST */ +#define SCSI_RESET 0x00200 /* Reset the device in question */ +#define SCSI_DATA_IN 0x00800 /* expect data to come INTO memory */ +#define SCSI_DATA_OUT 0x01000 /* expect data to flow OUT of memory */ +#define SCSI_TARGET 0x02000 /* This defines a TARGET mode op. */ +#define SCSI_ESCAPE 0x04000 /* Escape operation */ +#define SCSI_PRIVATE 0xf0000 /* private to each HBA flags */ + +/* + * Escape op-codes. This provides an extensible setup for operations + * that are not scsi commands. They are intended for modal operations. + */ + +#define SCSI_OP_TARGET 0x0001 +#define SCSI_OP_RESET 0x0002 +#define SCSI_OP_BDINFO 0x0003 + +/* + * Error values an adapter driver may return + */ +#define XS_NOERROR 0 /* there is no error, (sense is invalid) */ +#define XS_SENSE 1 /* Check the returned sense for the error */ +#define XS_DRIVER_STUFFUP 2 /* Driver failed to perform operation */ +#define XS_SELTIMEOUT 3 /* The device timed out.. turned off? */ +#define XS_TIMEOUT 4 /* The Timeout reported was caught by SW */ +#define XS_BUSY 5 /* The device busy, try again later? */ +#define XS_SHORTSENSE 6 /* Check the ATAPI sense for the error */ +#define XS_RESET 8 /* bus was reset; possible retry command */ + +/* + * Possible retries for scsi_test_unit_ready() + */ +#define TEST_READY_RETRIES 5 + +/* + * Possible retries for most SCSI commands. + */ +#define SCSI_RETRIES 4 + +const void *scsi_inqmatch(struct scsi_inquiry_data *, const void *, int, + int, int *); + +void scsi_init(void); +int scsi_test_unit_ready(struct scsi_link *, int, int); +int scsi_inquire(struct scsi_link *, struct scsi_inquiry_data *, int); +int scsi_read_cap_10(struct scsi_link *, struct scsi_read_cap_data *, int); +int scsi_read_cap_16(struct scsi_link *, struct scsi_read_cap_data_16 *, + int); +int scsi_inquire_vpd(struct scsi_link *, void *, u_int, u_int8_t, int); +void scsi_init_inquiry(struct scsi_xfer *, u_int8_t, u_int8_t, + void *, size_t); +int scsi_prevent(struct scsi_link *, int, int); +int scsi_start(struct scsi_link *, int, int); +void scsi_parse_blkdesc(struct scsi_link *, union scsi_mode_sense_buf *, int, + u_int32_t *, u_int64_t *, u_int32_t *); +int scsi_do_mode_sense(struct scsi_link *, int, + union scsi_mode_sense_buf *, void **, int, int, int *); +void scsi_parse_blkdesc(struct scsi_link *, union scsi_mode_sense_buf *, int, + u_int32_t *, u_int64_t *, u_int32_t *); +int scsi_mode_select(struct scsi_link *, int, struct scsi_mode_header *, + int, int); +int scsi_mode_select_big(struct scsi_link *, int, + struct scsi_mode_header_big *, int, int); +void scsi_copy_internal_data(struct scsi_xfer *, void *, size_t); +void scsi_done(struct scsi_xfer *); +int scsi_do_ioctl(struct scsi_link *, u_long, caddr_t, int); +void sc_print_addr(struct scsi_link *); +int scsi_report_luns(struct scsi_link *, int, + struct scsi_report_luns_data *, u_int32_t, int, int); +int scsi_interpret_sense(struct scsi_xfer *); + +void scsi_print_sense(struct scsi_xfer *); +void scsi_strvis(u_char *, u_char *, int); +int scsi_delay(struct scsi_xfer *, int); + +int scsi_probe(struct scsibus_softc *, int, int); +int scsi_probe_bus(struct scsibus_softc *); +int scsi_probe_target(struct scsibus_softc *, int); +int scsi_probe_lun(struct scsibus_softc *, int, int); + +int scsi_detach(struct scsibus_softc *, int, int, int); +int scsi_detach_target(struct scsibus_softc *, int, int); +int scsi_detach_lun(struct scsibus_softc *, int, int, int); + +int scsi_req_probe(struct scsibus_softc *, int, int); +int scsi_req_detach(struct scsibus_softc *, int, int, int); + +int scsi_activate(struct scsibus_softc *, int, int, int); + +struct scsi_link * scsi_get_link(struct scsibus_softc *, int, int); + +#define SID_ANSII_REV(x) ((x)->version & SID_ANSII) +#define SID_RESPONSE_FORMAT(x) ((x)->response_format & SID_RESPONSE_DATA_FMT) + +#define SCSI_REV_0 0x00 /* No conformance to any standard. */ +#define SCSI_REV_1 0x01 /* (Obsolete) SCSI-1 in olden times. */ +#define SCSI_REV_2 0x02 /* (Obsolete) SCSI-2 in olden times. */ +#define SCSI_REV_SPC 0x03 /* ANSI INCITS 301-1997 (SPC). */ +#define SCSI_REV_SPC2 0x04 /* ANSI INCITS 351-2001 (SPC-2) */ +#define SCSI_REV_SPC3 0x05 /* ANSI INCITS 408-2005 (SPC-3) */ +#define SCSI_REV_SPC4 0x06 /* ANSI INCITS 513-2015 (SPC-4) */ +#define SCSI_REV_SPC5 0x07 /* T10/BSR INCITS 503 (SPC-5) */ + +struct scsi_xfer * scsi_xs_get(struct scsi_link *, int); +void scsi_xs_exec(struct scsi_xfer *); +int scsi_xs_sync(struct scsi_xfer *); +void scsi_xs_put(struct scsi_xfer *); + +/* + * iopool stuff + */ +void scsi_iopool_init(struct scsi_iopool *, void *, + void *(*)(void *), void (*)(void *, void *)); +void scsi_iopool_run(struct scsi_iopool *); +void scsi_iopool_destroy(struct scsi_iopool *); +void scsi_link_shutdown(struct scsi_link *); + +void * scsi_io_get(struct scsi_iopool *, int); +void scsi_io_put(struct scsi_iopool *, void *); + +/* + * default io allocator. + */ +#define SCSI_IOPOOL_POISON ((void *)0x5c5) +void * scsi_default_get(void *); +void scsi_default_put(void *, void *); + +/* + * io handler interface + */ +void scsi_ioh_set(struct scsi_iohandler *, struct scsi_iopool *, + void (*)(void *, void *), void *); +int scsi_ioh_add(struct scsi_iohandler *); +int scsi_ioh_del(struct scsi_iohandler *); + +void scsi_xsh_set(struct scsi_xshandler *, struct scsi_link *, + void (*)(struct scsi_xfer *)); +int scsi_xsh_add(struct scsi_xshandler *); +int scsi_xsh_del(struct scsi_xshandler *); + +/* + * utility functions + */ +int scsi_pending_start(struct mutex *, u_int *); +int scsi_pending_finish(struct mutex *, u_int *); + +/* + * Utility functions for SCSI HBA emulation. + */ +void scsi_cmd_rw_decode(struct scsi_generic *, u_int64_t *, u_int32_t *); + +#endif /* _KERNEL */ +#endif /* _SCSI_SCSICONF_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/scsi/sdvar.h b/lib/libc/include/generic-openbsd/scsi/sdvar.h new file mode 100644 index 000000000000..db5fa0a3a50d --- /dev/null +++ b/lib/libc/include/generic-openbsd/scsi/sdvar.h @@ -0,0 +1,77 @@ +/* $OpenBSD: sdvar.h,v 1.52 2020/09/23 15:24:16 krw Exp $ */ +/* $NetBSD: sdvar.h,v 1.7 1998/08/17 00:49:03 mycroft Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Originally written by Julian Elischer (julian@dialix.oz.au) + * for TRW Financial Systems for use under the MACH(2.5) operating system. + * + * TRW Financial Systems, in accordance with their agreement with Carnegie + * Mellon University, makes this software available to CMU to distribute + * or use in any manner that they see fit as long as this message is kept with + * the software. For this reason TFS also grants any other persons or + * organisations permission to use or modify this software. + * + * TFS supplies this software to be publicly redistributed + * on the understanding that TFS is not responsible for the correct + * functioning of this software in any circumstances. + * + * Ported to run under 386BSD by Julian Elischer (julian@dialix.oz.au) Sept 1992 + */ + +#ifndef _SCSI_SDVAR_H +#define _SCSI_SDVAR_H + +#ifdef _KERNEL +struct sd_softc { + struct device sc_dev; + struct disk sc_dk; + struct bufq sc_bufq; + + int flags; +#define SDF_DIRTY 0x20 /* disk is dirty; needs cache flush */ +#define SDF_DYING 0x40 /* dying, when deactivated */ +#define SDF_THIN 0x01 /* disk is thin provisioned */ + struct scsi_link *sc_link; /* contains our targ, lun, etc. */ + struct disk_parms { + u_int32_t heads; /* number of heads */ + u_int32_t cyls; /* number of cylinders */ + u_int32_t sectors; /* number of sectors/track */ + u_int32_t secsize; /* number of bytes/sector */ + u_int64_t disksize; /* total number sectors */ + u_int32_t unmap_sectors; /* maximum sectors/unmap */ + u_int32_t unmap_descs; /* maximum descriptors/unmap */ + } params; + + struct scsi_xshandler sc_xsh; +}; +#endif /* _KERNEL */ +#endif /* _SCSI_SDVAR_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/scsi/ses.h b/lib/libc/include/generic-openbsd/scsi/ses.h new file mode 100644 index 000000000000..9e0247222dd3 --- /dev/null +++ b/lib/libc/include/generic-openbsd/scsi/ses.h @@ -0,0 +1,235 @@ +/* $OpenBSD: ses.h,v 1.11 2024/09/04 07:54:53 mglocker Exp $ */ +/* + * Copyright (c) 2005 Marco Peereboom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _SCSI_SES_H_ +#define _SCSI_SES_H_ + +/* the scsi command */ +struct ses_scsi_diag { + u_int8_t opcode; /* SEND_DIAGNOSTIC or RECEIVE_DIAGNOSTIC */ + u_int8_t flags; +#define SES_DIAG_PCV (1<<0) /* page code valid */ +#define SES_DIAG_PF (1<<4) /* set this bit if page code is valid */ + u_int8_t pgcode; +#define SES_PAGE_CONFIG 0x01 /* Configuration */ +#define SES_PAGE_STATUS 0x02 /* Enclosure Status */ +#define SES_PAGE_EDESC 0x07 /* Element Descriptor */ + u_int16_t length; + u_int8_t control; +} __packed; + + +/* all the different sensor types */ +#define SES_T_UNSPEC 0x00 +#define SES_T_DEVICE 0x01 +#define SES_T_POWERSUPPLY 0x02 +#define SES_T_COOLING 0x03 +#define SES_T_TEMP 0x04 +#define SES_T_DOORLOCK 0x05 +#define SES_T_ALARM 0x06 +#define SES_T_ENC_SRV_CTRL 0x07 +#define SES_T_SCC_CTRL 0x08 +#define SES_T_NONVOL_CACHE 0x09 +#define SES_T_INV_OP_REASON 0x0a +#define SES_T_UPS 0x0b +#define SES_T_DISPLAY 0x0c +#define SES_T_KEYPAD 0x0d +#define SES_T_ENCLOSURE 0x0e +#define SES_T_SCSI_PORT_TRANS 0x0f +#define SES_T_LANGUAGE 0x10 +#define SES_T_COMM_PORT 0x11 +#define SES_T_VOLTAGE 0x12 +#define SES_T_CURRENT 0x13 +#define SES_T_SCSI_TARGET_PORT 0x14 +#define SES_T_SCSI_INIT_PORT 0x15 +#define SES_T_SIMP_SUBENC 0x16 +#define SES_T_ARRAY_DEVICE 0x17 + +#define SES_NUM_TYPES 256 + +/* diagnostic page header */ +struct ses_config_hdr { + u_int8_t pgcode; /* SES_PAGE_CONFIG */ + u_int8_t n_subenc; + u_int16_t length; + u_int32_t gencode; +} __packed; +#define SES_CFG_HDRLEN sizeof(struct ses_config_hdr) + +/* enclosure descriptor header */ +struct ses_enc_hdr { + u_int8_t enc_id; + u_int8_t subenc_id; + u_int8_t n_types; + u_int8_t vendor_len; +} __packed; +#define SES_ENC_HDRLEN sizeof(struct ses_enc_hdr) + +/* enclosure descriptor strings */ +struct ses_enc_desc { + u_int8_t logical_id[8]; /* this isn't a string */ + u_int8_t vendor_id[8]; + u_int8_t prod_id[16]; + u_int8_t prod_rev[4]; + u_int8_t vendor[0]; +} __packed; + +/* type descriptor header */ +struct ses_type_desc { + u_int8_t type; + u_int8_t n_elem; + u_int8_t subenc_id; + u_int8_t desc_len; +} __packed; +#define SES_TYPE_DESCLEN sizeof(struct ses_type_desc) + +/* status page header */ +struct ses_status_hdr { + u_int8_t pgcode; /* SES_PAGE_STATUS */ + u_int8_t flags; +#define SES_STAT_UNRECOV (1<<0) /* unrecoverable error */ +#define SES_STAT_CRIT (1<<1) /* critical error */ +#define SES_STAT_NONCRIT (1<<2) /* noncritical error */ +#define SES_STAT_INFO (1<<3) /* info available */ +#define SES_STAT_INVOP (1<<4) /* invalid operation */ + u_int16_t length; + u_int32_t gencode; +} __packed; +#define SES_STAT_HDRLEN sizeof(struct ses_status_hdr) + +struct ses_status { + u_int8_t com; +#define SES_STAT_CODE_MASK 0x0f +#define SES_STAT_CODE(x) ((x) & SES_STAT_CODE_MASK) +#define SES_STAT_CODE_UNSUP 0x00 /* unsupported */ +#define SES_STAT_CODE_OK 0x01 /* installed and ok */ +#define SES_STAT_CODE_CRIT 0x02 /* critical */ +#define SES_STAT_CODE_NONCRIT 0x03 /* warning */ +#define SES_STAT_CODE_UNREC 0x04 /* unrecoverable */ +#define SES_STAT_CODE_NOTINST 0x05 /* not installed */ +#define SES_STAT_CODE_UNKNOWN 0x06 /* unknown */ +#define SES_STAT_CODE_NOTAVAIL 0x07 /* not available */ +#define SES_STAT_SWAP (1<<4) /* element has been swapped */ +#define SES_STAT_DISABLED (1<<5) /* disabled */ +#define SES_STAT_PRDFAIL (1<<6) /* predicted failure */ +#define SES_STAT_SELECT (1<<7) /* set to modify element */ + + u_int8_t f1; /* use of these flags depends on the SES_T */ + u_int8_t f2; + u_int8_t f3; +} __packed; +#define SES_STAT_ELEMLEN sizeof(struct ses_status) + +/* device status */ +/* f1 is the device address */ +/* f2 */ +#define SES_S_DEV_REPORT (1<<0) /* enc report in progress */ +#define SES_S_DEV_IDENT (1<<1) /* currently identifying */ +#define SES_S_DEV_REMOVE (1<<2) /* ready to remove */ +#define SES_S_DEV_INSERT (1<<3) /* ready to insert */ +#define SES_S_DEV_ENCBYPB (1<<4) /* port B bypassed by enc */ +#define SES_S_DEV_ENCBYPA (1<<5) /* port A bypassed by enc */ +#define SES_S_DEV_DONOTREM (1<<6) /* do not remove */ +#define SES_S_DEV_APPCLBYPA (1<<7) /* port A bypassed by app */ +/* f3 */ +#define SES_S_DEV_DEVBYPB (1<<0) /* port B bypassed by dev */ +#define SES_S_DEV_DEVBYPA (1<<1) /* port A bypassed by dev */ +#define SES_S_DEV_BYPB (1<<2) +#define SES_S_DEV_BYPA (1<<3) +#define SES_S_DEV_OFF (1<<4) /* device is off */ +#define SES_S_DEV_FAULTRQST (1<<5) /* fault indicator rqsted */ +#define SES_S_DEV_FAULTSENSE (1<<6) /* fault sensed */ +#define SES_S_DEV_APPCLBYPB (1<<7) /* port B bypassed by app */ + +/* device configuration */ +/* f1 is reserved */ +/* f2 */ +#define SES_C_DEV_IDENT (1<<1) /* ident */ +#define SES_C_DEV_REMOVE (1<<2) /* remove */ +#define SES_C_DEV_INSERT (1<<3) /* insert */ +#define SES_C_DEV_DONOTREM (1<<6) /* do not remove */ +#define SES_C_DEV_ACTIVE (1<<7) /* active indicator */ +#define SES_C_DEV_F2MASK (SES_C_DEV_IDENT | SES_C_DEV_REMOVE | \ + SES_C_DEV_INSERT | SES_C_DEV_DONOTREM | SES_C_DEV_ACTIVE ) +/* f3 */ +#define SES_C_DEV_BYPB (1<<2) /* port B bypass */ +#define SES_C_DEV_BYPA (1<<3) /* port A bypass */ +#define SES_C_DEV_OFF (1<<4) /* off */ +#define SES_C_DEV_FAULT (1<<5) /* fault indicator */ +#define SES_C_DEV_F3MASK (SES_C_DEV_BYPB | SES_C_DEV_BYPA | \ + SES_C_DEV_OFF | SES_C_DEV_FAULT) + +/* power supply element */ +#define SES_S_PSU_IDENT(d) ((d)->f1 & (1<<6)) /* identify */ +#define SES_S_PSU_DCOC(d) ((d)->f2 & (1<<1)) /* DC over current */ +#define SES_S_PSU_DCUV(d) ((d)->f2 & (1<<2)) /* DC under voltage */ +#define SES_S_PSU_DCOV(d) ((d)->f2 & (1<<3)) /* DC over voltage */ +#define SES_S_PSU_DCFAIL(d) ((d)->f3 & (1<<0)) /* DC fail */ +#define SES_S_PSU_ACFAIL(d) ((d)->f3 & (1<<1)) /* AC fail */ +#define SES_S_PSU_TEMPWARN(d) ((d)->f3 & (1<<2)) /* Temp warn */ +#define SES_S_PSU_OVERTEMP(d) ((d)->f3 & (1<<3)) /* over temp fail */ +#define SES_S_PSU_OFF(d) ((d)->f3 & (1<<4)) /* is the unit off */ +#define SES_S_PSU_RQSTON(d) ((d)->f3 & (1<<5)) /* manually on */ +#define SES_S_PSU_FAIL(d) ((d)->f3 & (1<<6)) /* fail is set on */ + +/* cooling element */ +#define SES_S_COOL_IDENT(d) ((d)->f1 & (1<<6)) /* identify */ +#define SES_S_COOL_SPEED_MASK 0x03 +#define SES_S_COOL_SPEED(d) ((d)->f2 + \ + ((u_int16_t)((d)->f2 & SES_S_COOL_SPEED_MASK) << 8)) +#define SES_S_COOL_FACTOR 10 +#define SES_S_COOL_CODE(d) ((d)->f3 & 0x7) /* actual speed code */ +#define SES_S_COOL_C_STOPPED 0x0 /* stopped */ +#define SES_S_COOL_C_LOW1 0x1 /* lowest speed */ +#define SES_S_COOL_C_LOW2 0x2 /* second lowest speed */ +#define SES_S_COOL_C_LOW3 0x3 /* third lowest speed */ +#define SES_S_COOL_C_INTER 0x4 /* intermediate speed */ +#define SES_S_COOL_C_HI3 0x5 /* third highest speed */ +#define SES_S_COOL_C_HI2 0x6 /* second highest speed */ +#define SES_S_COOL_C_HI1 0x7 /* highest speed */ +#define SES_S_COOL_OFF ((d)->f3 & (1<<4)) /* not cooling */ +#define SES_S_COOL_RQSTON ((d)->f3 & (1<<5)) /* manually on */ +#define SES_S_COOL_FAIL ((d)->f3 & (1<<6)) /* fail indic is on */ + +/* temperature sensor */ +#define SES_S_TEMP_IDENT(d) ((d)->f1 & (1<<7)) /* identify */ +#define SES_S_TEMP(d) ((d)->f2) +#define SES_S_TEMP_OFFSET (-20) +#define SES_S_TEMP_UTWARN ((d)->f3 & (1<<0)) /* under temp warning */ +#define SES_S_TEMP_UTFAIL ((d)->f3 & (1<<1)) /* under temp failure */ +#define SES_S_TEMP_OTWARN ((d)->f3 & (1<<2)) /* over temp warning */ +#define SES_S_TEMP_OTFAIL ((d)->f3 & (1<<3)) /* over temp failure */ + +/* + * the length of the status page is the header and a status element for + * each type plus the number of elements for each type + */ +#define SES_STAT_LEN(t, e) \ + (SES_STAT_HDRLEN + SES_STAT_ELEMLEN * ((t)+(e))) + +#endif /* _SCSI_SES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/search.h b/lib/libc/include/generic-openbsd/search.h new file mode 100644 index 000000000000..b2210203ca00 --- /dev/null +++ b/lib/libc/include/generic-openbsd/search.h @@ -0,0 +1,57 @@ +/* $OpenBSD: search.h,v 1.10 2014/07/18 04:16:09 matthew Exp $ */ +/* $NetBSD: search.h,v 1.9 1995/08/08 21:14:45 jtc Exp $ */ + +/* + * Written by J.T. Conklin + * Public domain. + */ + +#ifndef _SEARCH_H_ +#define _SEARCH_H_ + +#include +#include + +#ifndef _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED_ +typedef __size_t size_t; +#endif + +typedef struct entry { + char *key; + void *data; +} ENTRY; + +typedef enum { + FIND, ENTER +} ACTION; + +typedef enum { + preorder, + postorder, + endorder, + leaf +} VISIT; + +__BEGIN_DECLS +int hcreate(size_t); +void hdestroy(void); +ENTRY *hsearch(ENTRY, ACTION); + +void *lfind(const void *, const void *, size_t *, size_t, + int (*)(const void *, const void *)); +void *lsearch(const void *, void *, size_t *, size_t, + int (*)(const void *, const void *)); +void insque(void *, void *); +void remque(void *); + +void *tdelete(const void * __restrict, void ** __restrict, + int (*)(const void *, const void *)); +void *tfind(const void *, void * const *, + int (*)(const void *, const void *)); +void *tsearch(const void *, void **, + int (*)(const void *, const void *)); +void twalk(const void *, void (*)(const void *, VISIT, int)); +__END_DECLS + +#endif /* !_SEARCH_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/semaphore.h b/lib/libc/include/generic-openbsd/semaphore.h new file mode 100644 index 000000000000..5cd9001c8de4 --- /dev/null +++ b/lib/libc/include/generic-openbsd/semaphore.h @@ -0,0 +1,62 @@ +/* $OpenBSD: semaphore.h,v 1.1 2017/10/15 23:40:33 guenther Exp $ */ + +/* semaphore.h: POSIX 1003.1b semaphores */ + +/*- + * Copyright (c) 1996, 1997 + * HD Associates, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by HD Associates, Inc + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES 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 HD ASSOCIATES 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 _SEMAPHORE_H_ +#define _SEMAPHORE_H_ + +#include + +/* Opaque type definition. */ +struct __sem; +typedef struct __sem *sem_t; +struct timespec; + +#define SEM_FAILED ((sem_t *)0) + +__BEGIN_DECLS +int sem_init(sem_t *, int, unsigned int); +int sem_destroy(sem_t *); +sem_t *sem_open(const char *, int, ...); +int sem_close(sem_t *); +int sem_unlink(const char *); +int sem_wait(sem_t *); +int sem_timedwait(sem_t * __restrict, const struct timespec * __restrict); +int sem_trywait(sem_t *); +int sem_post(sem_t *); +int sem_getvalue(sem_t * __restrict, int * __restrict); +__END_DECLS + +#endif /* _SEMAPHORE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/setjmp.h b/lib/libc/include/generic-openbsd/setjmp.h new file mode 100644 index 000000000000..fd6544b8dc1a --- /dev/null +++ b/lib/libc/include/generic-openbsd/setjmp.h @@ -0,0 +1,67 @@ +/* $OpenBSD: setjmp.h,v 1.7 2016/05/23 00:18:56 guenther Exp $ */ +/* $NetBSD: setjmp.h,v 1.11 1994/12/20 10:35:44 cgd Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)setjmp.h 8.2 (Berkeley) 1/21/94 + */ + +#ifndef _SETJMP_H_ +#define _SETJMP_H_ + +#include +#include + +#if __BSD_VISIBLE || __POSIX_VISIBLE || __XPG_VISIBLE +typedef long sigjmp_buf[_JBLEN + 1]; +#endif /* __BSD_VISIBLE || __POSIX_VISIBLE || __XPG_VISIBLE */ + +typedef long jmp_buf[_JBLEN]; + +__BEGIN_DECLS +__returns_twice int setjmp(jmp_buf); +__dead void longjmp(jmp_buf, int); + +#if __BSD_VISIBLE || __POSIX_VISIBLE || __XPG_VISIBLE +__returns_twice int sigsetjmp(sigjmp_buf, int); +__dead void siglongjmp(sigjmp_buf, int); +#endif /* __BSD_VISIBLE || __POSIX_VISIBLE || __XPG_VISIBLE */ + +#if __BSD_VISIBLE || __XPG_VISIBLE +__returns_twice int _setjmp(jmp_buf); +__dead void _longjmp(jmp_buf, int); +#endif /* __BSD_VISIBLE || __XPG_VISIBLE */ +__END_DECLS + +#endif /* !_SETJMP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sha1.h b/lib/libc/include/generic-openbsd/sha1.h new file mode 100644 index 000000000000..f98d41c8e5c7 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sha1.h @@ -0,0 +1,57 @@ +/* $OpenBSD: sha1.h,v 1.24 2012/12/05 23:19:57 deraadt Exp $ */ + +/* + * SHA-1 in C + * By Steve Reid + * 100% Public Domain + */ + +#ifndef _SHA1_H +#define _SHA1_H + +#define SHA1_BLOCK_LENGTH 64 +#define SHA1_DIGEST_LENGTH 20 +#define SHA1_DIGEST_STRING_LENGTH (SHA1_DIGEST_LENGTH * 2 + 1) + +typedef struct { + u_int32_t state[5]; + u_int64_t count; + u_int8_t buffer[SHA1_BLOCK_LENGTH]; +} SHA1_CTX; + +__BEGIN_DECLS +void SHA1Init(SHA1_CTX *); +void SHA1Pad(SHA1_CTX *); +void SHA1Transform(u_int32_t [5], const u_int8_t [SHA1_BLOCK_LENGTH]) + __attribute__((__bounded__(__minbytes__,1,5))) + __attribute__((__bounded__(__minbytes__,2,SHA1_BLOCK_LENGTH))); +void SHA1Update(SHA1_CTX *, const u_int8_t *, size_t) + __attribute__((__bounded__(__string__,2,3))); +void SHA1Final(u_int8_t [SHA1_DIGEST_LENGTH], SHA1_CTX *) + __attribute__((__bounded__(__minbytes__,1,SHA1_DIGEST_LENGTH))); +char *SHA1End(SHA1_CTX *, char *) + __attribute__((__bounded__(__minbytes__,2,SHA1_DIGEST_STRING_LENGTH))); +char *SHA1File(const char *, char *) + __attribute__((__bounded__(__minbytes__,2,SHA1_DIGEST_STRING_LENGTH))); +char *SHA1FileChunk(const char *, char *, off_t, off_t) + __attribute__((__bounded__(__minbytes__,2,SHA1_DIGEST_STRING_LENGTH))); +char *SHA1Data(const u_int8_t *, size_t, char *) + __attribute__((__bounded__(__string__,1,2))) + __attribute__((__bounded__(__minbytes__,3,SHA1_DIGEST_STRING_LENGTH))); +__END_DECLS + +#define HTONDIGEST(x) do { \ + x[0] = htonl(x[0]); \ + x[1] = htonl(x[1]); \ + x[2] = htonl(x[2]); \ + x[3] = htonl(x[3]); \ + x[4] = htonl(x[4]); } while (0) + +#define NTOHDIGEST(x) do { \ + x[0] = ntohl(x[0]); \ + x[1] = ntohl(x[1]); \ + x[2] = ntohl(x[2]); \ + x[3] = ntohl(x[3]); \ + x[4] = ntohl(x[4]); } while (0) + +#endif /* _SHA1_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sha2.h b/lib/libc/include/generic-openbsd/sha2.h new file mode 100644 index 000000000000..79bc16e3fbe0 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sha2.h @@ -0,0 +1,156 @@ +/* $OpenBSD: sha2.h,v 1.10 2016/09/03 17:00:29 tedu Exp $ */ + +/* + * FILE: sha2.h + * AUTHOR: Aaron D. Gifford + * + * Copyright (c) 2000-2001, Aaron D. Gifford + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 CONTRIBUTOR(S) BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $From: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $ + */ + +#ifndef _SHA2_H +#define _SHA2_H + + +/*** SHA-256/384/512 Various Length Definitions ***********************/ +#define SHA224_BLOCK_LENGTH 64 +#define SHA224_DIGEST_LENGTH 28 +#define SHA224_DIGEST_STRING_LENGTH (SHA224_DIGEST_LENGTH * 2 + 1) +#define SHA256_BLOCK_LENGTH 64 +#define SHA256_DIGEST_LENGTH 32 +#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1) +#define SHA384_BLOCK_LENGTH 128 +#define SHA384_DIGEST_LENGTH 48 +#define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1) +#define SHA512_BLOCK_LENGTH 128 +#define SHA512_DIGEST_LENGTH 64 +#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) +#define SHA512_256_BLOCK_LENGTH 128 +#define SHA512_256_DIGEST_LENGTH 32 +#define SHA512_256_DIGEST_STRING_LENGTH (SHA512_256_DIGEST_LENGTH * 2 + 1) + + +/*** SHA-224/256/384/512 Context Structure *******************************/ +typedef struct _SHA2_CTX { + union { + u_int32_t st32[8]; + u_int64_t st64[8]; + } state; + u_int64_t bitcount[2]; + u_int8_t buffer[SHA512_BLOCK_LENGTH]; +} SHA2_CTX; + +__BEGIN_DECLS +void SHA224Init(SHA2_CTX *); +void SHA224Transform(u_int32_t state[8], const u_int8_t [SHA224_BLOCK_LENGTH]); +void SHA224Update(SHA2_CTX *, const u_int8_t *, size_t) + __attribute__((__bounded__(__string__,2,3))); +void SHA224Pad(SHA2_CTX *); +void SHA224Final(u_int8_t [SHA224_DIGEST_LENGTH], SHA2_CTX *) + __attribute__((__bounded__(__minbytes__,1,SHA224_DIGEST_LENGTH))); +char *SHA224End(SHA2_CTX *, char *) + __attribute__((__bounded__(__minbytes__,2,SHA224_DIGEST_STRING_LENGTH))); +char *SHA224File(const char *, char *) + __attribute__((__bounded__(__minbytes__,2,SHA224_DIGEST_STRING_LENGTH))); +char *SHA224FileChunk(const char *, char *, off_t, off_t) + __attribute__((__bounded__(__minbytes__,2,SHA224_DIGEST_STRING_LENGTH))); +char *SHA224Data(const u_int8_t *, size_t, char *) + __attribute__((__bounded__(__string__,1,2))) + __attribute__((__bounded__(__minbytes__,3,SHA224_DIGEST_STRING_LENGTH))); + +void SHA256Init(SHA2_CTX *); +void SHA256Transform(u_int32_t state[8], const u_int8_t [SHA256_BLOCK_LENGTH]); +void SHA256Update(SHA2_CTX *, const u_int8_t *, size_t) + __attribute__((__bounded__(__string__,2,3))); +void SHA256Pad(SHA2_CTX *); +void SHA256Final(u_int8_t [SHA256_DIGEST_LENGTH], SHA2_CTX *) + __attribute__((__bounded__(__minbytes__,1,SHA256_DIGEST_LENGTH))); +char *SHA256End(SHA2_CTX *, char *) + __attribute__((__bounded__(__minbytes__,2,SHA256_DIGEST_STRING_LENGTH))); +char *SHA256File(const char *, char *) + __attribute__((__bounded__(__minbytes__,2,SHA256_DIGEST_STRING_LENGTH))); +char *SHA256FileChunk(const char *, char *, off_t, off_t) + __attribute__((__bounded__(__minbytes__,2,SHA256_DIGEST_STRING_LENGTH))); +char *SHA256Data(const u_int8_t *, size_t, char *) + __attribute__((__bounded__(__string__,1,2))) + __attribute__((__bounded__(__minbytes__,3,SHA256_DIGEST_STRING_LENGTH))); + +void SHA384Init(SHA2_CTX *); +void SHA384Transform(u_int64_t state[8], const u_int8_t [SHA384_BLOCK_LENGTH]); +void SHA384Update(SHA2_CTX *, const u_int8_t *, size_t) + __attribute__((__bounded__(__string__,2,3))); +void SHA384Pad(SHA2_CTX *); +void SHA384Final(u_int8_t [SHA384_DIGEST_LENGTH], SHA2_CTX *) + __attribute__((__bounded__(__minbytes__,1,SHA384_DIGEST_LENGTH))); +char *SHA384End(SHA2_CTX *, char *) + __attribute__((__bounded__(__minbytes__,2,SHA384_DIGEST_STRING_LENGTH))); +char *SHA384File(const char *, char *) + __attribute__((__bounded__(__minbytes__,2,SHA384_DIGEST_STRING_LENGTH))); +char *SHA384FileChunk(const char *, char *, off_t, off_t) + __attribute__((__bounded__(__minbytes__,2,SHA384_DIGEST_STRING_LENGTH))); +char *SHA384Data(const u_int8_t *, size_t, char *) + __attribute__((__bounded__(__string__,1,2))) + __attribute__((__bounded__(__minbytes__,3,SHA384_DIGEST_STRING_LENGTH))); + +void SHA512Init(SHA2_CTX *); +void SHA512Transform(u_int64_t state[8], const u_int8_t [SHA512_BLOCK_LENGTH]); +void SHA512Update(SHA2_CTX *, const u_int8_t *, size_t) + __attribute__((__bounded__(__string__,2,3))); +void SHA512Pad(SHA2_CTX *); +void SHA512Final(u_int8_t [SHA512_DIGEST_LENGTH], SHA2_CTX *) + __attribute__((__bounded__(__minbytes__,1,SHA512_DIGEST_LENGTH))); +char *SHA512End(SHA2_CTX *, char *) + __attribute__((__bounded__(__minbytes__,2,SHA512_DIGEST_STRING_LENGTH))); +char *SHA512File(const char *, char *) + __attribute__((__bounded__(__minbytes__,2,SHA512_DIGEST_STRING_LENGTH))); +char *SHA512FileChunk(const char *, char *, off_t, off_t) + __attribute__((__bounded__(__minbytes__,2,SHA512_DIGEST_STRING_LENGTH))); +char *SHA512Data(const u_int8_t *, size_t, char *) + __attribute__((__bounded__(__string__,1,2))) + __attribute__((__bounded__(__minbytes__,3,SHA512_DIGEST_STRING_LENGTH))); + +void SHA512_256Init(SHA2_CTX *); +void SHA512_256Transform(u_int64_t state[8], const u_int8_t [SHA512_256_BLOCK_LENGTH]); +void SHA512_256Update(SHA2_CTX *, const u_int8_t *, size_t) + __attribute__((__bounded__(__string__,2,3))); +void SHA512_256Pad(SHA2_CTX *); +void SHA512_256Final(u_int8_t [SHA512_256_DIGEST_LENGTH], SHA2_CTX *) + __attribute__((__bounded__(__minbytes__,1,SHA512_256_DIGEST_LENGTH))); +char *SHA512_256End(SHA2_CTX *, char *) + __attribute__((__bounded__(__minbytes__,2,SHA512_256_DIGEST_STRING_LENGTH))); +char *SHA512_256File(const char *, char *) + __attribute__((__bounded__(__minbytes__,2,SHA512_256_DIGEST_STRING_LENGTH))); +char *SHA512_256FileChunk(const char *, char *, off_t, off_t) + __attribute__((__bounded__(__minbytes__,2,SHA512_256_DIGEST_STRING_LENGTH))); +char *SHA512_256Data(const u_int8_t *, size_t, char *) + __attribute__((__bounded__(__string__,1,2))) + __attribute__((__bounded__(__minbytes__,3,SHA512_256_DIGEST_STRING_LENGTH))); +__END_DECLS + +#endif /* _SHA2_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/signal.h b/lib/libc/include/generic-openbsd/signal.h new file mode 100644 index 000000000000..0ab0dbb2e94a --- /dev/null +++ b/lib/libc/include/generic-openbsd/signal.h @@ -0,0 +1,140 @@ +/* $OpenBSD: signal.h,v 1.26 2018/05/30 13:20:38 bluhm Exp $ */ +/* $NetBSD: signal.h,v 1.8 1996/02/29 00:04:57 jtc Exp $ */ + +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)signal.h 8.3 (Berkeley) 3/30/94 + */ + +#ifndef _USER_SIGNAL_H +#define _USER_SIGNAL_H + +#include + +#if __BSD_VISIBLE || __POSIX_VISIBLE || __XPG_VISIBLE +#include +#endif + +__BEGIN_DECLS +#if __BSD_VISIBLE +extern const char *const sys_signame[_NSIG]; +extern const char *const sys_siglist[_NSIG]; +#endif + +int raise(int); +#if __BSD_VISIBLE || __POSIX_VISIBLE || __XPG_VISIBLE +#if __BSD_VISIBLE || (__XPG_VISIBLE >= 500 && __XPG_VISIBLE < 700) +void (*bsd_signal(int, void (*)(int)))(int); +#endif +int kill(pid_t, int); +int sigaction(int, const struct sigaction *__restrict, + struct sigaction *__restrict); +int sigaddset(sigset_t *, int); +int sigdelset(sigset_t *, int); +int sigemptyset(sigset_t *); +int sigfillset(sigset_t *); +int sigismember(const sigset_t *, int); +int sigpending(sigset_t *); +int sigprocmask(int, const sigset_t *__restrict, sigset_t *__restrict); +#if __POSIX_VISIBLE >= 199506 +int pthread_sigmask(int, const sigset_t *__restrict, sigset_t *__restrict); +#endif +int sigsuspend(const sigset_t *); + +#if !defined(_ANSI_LIBRARY) + +extern int *__errno(void); + +__only_inline int sigaddset(sigset_t *__set, int __signo) +{ + if (__signo <= 0 || __signo >= _NSIG) { + *__errno() = 22; /* EINVAL */ + return -1; + } + *__set |= (1U << ((__signo)-1)); /* sigmask(__signo) */ + return (0); +} + +__only_inline int sigdelset(sigset_t *__set, int __signo) +{ + if (__signo <= 0 || __signo >= _NSIG) { + *__errno() = 22; /* EINVAL */ + return -1; + } + *__set &= ~(1U << ((__signo)-1)); /* sigmask(__signo) */ + return (0); +} + +__only_inline int sigismember(const sigset_t *__set, int __signo) +{ + if (__signo <= 0 || __signo >= _NSIG) { + *__errno() = 22; /* EINVAL */ + return -1; + } + return ((*__set & (1U << ((__signo)-1))) != 0); +} + +__only_inline int sigemptyset(sigset_t *__set) +{ + *__set = 0; + return (0); +} + +__only_inline int sigfillset(sigset_t *__set) +{ + *__set = ~(sigset_t)0; + return (0); +} + +#endif /* !_ANSI_LIBRARY */ + +#if __BSD_VISIBLE || __XPG_VISIBLE >= 420 +int killpg(pid_t, int); +int siginterrupt(int, int); +int sigaltstack(const struct sigaltstack *__restrict, + struct sigaltstack *__restrict); +#if __BSD_VISIBLE +int sigblock(int); +/* This is the traditional BSD sigpause() and not the XPG/POSIX sigpause(). */ +int sigpause(int); +int sigsetmask(int); +int sigvec(int, struct sigvec *, struct sigvec *); +int thrkill(pid_t _tid, int _signum, void *_tcb); +#endif +#endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ +#if __BSD_VISIBLE || __POSIX_VISIBLE >= 199309 || __XPG_VISIBLE >= 500 +int sigwait(const sigset_t *__restrict, int *__restrict); +#endif +#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200809 +void psignal(unsigned int, const char *); +#endif +#endif /* __BSD_VISIBLE || __POSIX_VISIBLE || __XPG_VISIBLE */ +__END_DECLS + +#endif /* !_USER_SIGNAL_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/siphash.h b/lib/libc/include/generic-openbsd/siphash.h new file mode 100644 index 000000000000..99102bd78a41 --- /dev/null +++ b/lib/libc/include/generic-openbsd/siphash.h @@ -0,0 +1,86 @@ +/*- + * Copyright (c) 2013 Andre Oppermann + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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. + * + * $OpenBSD: siphash.h,v 1.5 2025/04/14 08:28:24 claudio Exp $ + */ + +/* + * SipHash is a family of pseudorandom functions (a.k.a. keyed hash functions) + * optimized for speed on short messages returning a 64bit hash/digest value. + * + * The number of rounds is defined during the initialization: + * SipHash24_Init() for the fast and reasonable strong version + * SipHash48_Init() for the strong version (half as fast) + * + * struct SIPHASH_CTX ctx; + * SipHash24_Init(&ctx); + * SipHash_SetKey(&ctx, "16bytes long key"); + * SipHash_Update(&ctx, pointer_to_string, length_of_string); + * SipHash_Final(output, &ctx); + */ + +#ifndef _SIPHASH_H_ +#define _SIPHASH_H_ + +#include +#include + +#define SIPHASH_BLOCK_LENGTH 8 +#define SIPHASH_KEY_LENGTH 16 +#define SIPHASH_DIGEST_LENGTH 8 + +typedef struct _SIPHASH_CTX { + uint64_t v[4]; + uint8_t buf[SIPHASH_BLOCK_LENGTH]; + uint32_t bytes; +} SIPHASH_CTX; + +typedef struct { + uint64_t k0; + uint64_t k1; +} SIPHASH_KEY; + +void SipHash_Init(SIPHASH_CTX *, const SIPHASH_KEY *); +void SipHash_Update(SIPHASH_CTX *, int, int, const void *, size_t); +uint64_t SipHash_End(SIPHASH_CTX *, int, int); +void SipHash_Final(void *, SIPHASH_CTX *, int, int); +uint64_t SipHash(const SIPHASH_KEY *, int, int, const void *, size_t); + +#define SipHash24_Init(_c, _k) SipHash_Init((_c), (_k)) +#define SipHash24_Update(_c, _p, _l) SipHash_Update((_c), 2, 4, (_p), (_l)) +#define SipHash24_End(_d) SipHash_End((_d), 2, 4) +#define SipHash24_Final(_d, _c) SipHash_Final((_d), (_c), 2, 4) +#define SipHash24(_k, _p, _l) SipHash((_k), 2, 4, (_p), (_l)) + +#define SipHash48_Init(_c, _k) SipHash_Init((_c), (_k)) +#define SipHash48_Update(_c, _p, _l) SipHash_Update((_c), 4, 8, (_p), (_l)) +#define SipHash48_End(_d) SipHash_End((_d), 4, 8) +#define SipHash48_Final(_d, _c) SipHash_Final((_d), (_c), 4, 8) +#define SipHash48(_k, _p, _l) SipHash((_k), 4, 8, (_p), (_l)) + +#endif /* _SIPHASH_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sndio.h b/lib/libc/include/generic-openbsd/sndio.h new file mode 100644 index 000000000000..cb7576053beb --- /dev/null +++ b/lib/libc/include/generic-openbsd/sndio.h @@ -0,0 +1,216 @@ +/* $OpenBSD: sndio.h,v 1.15 2024/05/24 15:10:26 ratchov Exp $ */ +/* + * Copyright (c) 2008 Alexandre Ratchov + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef SNDIO_H +#define SNDIO_H + +#include + +/* + * default audio device and MIDI port + */ +#define SIO_DEVANY "default" +#define MIO_PORTANY "default" + +/* + * limits + * + * For now SIOCTL_DISPLAYMAX is 12 byte only. It nicely fits in the + * padding of the sioctl_desc structure: this allows any binary linked + * to the library version with no sioctl_desc->display to work with + * this library version. Currently, any string reported by the lower + * layers fits in the 12-byte buffer. Once larger strings start + * being used (or the ABI changes for any other reason) increase + * SIOCTL_DISPLAYMAX and properly pad the sioctl_desc structure. + */ +#define SIOCTL_NAMEMAX 12 /* max name length */ +#define SIOCTL_DISPLAYMAX 12 /* max display string length */ + +/* + * private ``handle'' structure + */ +struct sio_hdl; +struct mio_hdl; +struct sioctl_hdl; + +/* + * parameters of a full-duplex stream + */ +struct sio_par { + unsigned int bits; /* bits per sample */ + unsigned int bps; /* bytes per sample */ + unsigned int sig; /* 1 = signed, 0 = unsigned */ + unsigned int le; /* 1 = LE, 0 = BE byte order */ + unsigned int msb; /* 1 = MSB, 0 = LSB aligned */ + unsigned int rchan; /* number channels for recording direction */ + unsigned int pchan; /* number channels for playback direction */ + unsigned int rate; /* frames per second */ + unsigned int bufsz; /* end-to-end buffer size */ +#define SIO_IGNORE 0 /* pause during xrun */ +#define SIO_SYNC 1 /* resync after xrun */ +#define SIO_ERROR 2 /* terminate on xrun */ + unsigned int xrun; /* what to do on overruns/underruns */ + unsigned int round; /* optimal bufsz divisor */ + unsigned int appbufsz; /* minimum buffer size */ + int __pad[3]; /* for future use */ + unsigned int __magic; /* for internal/debug purposes only */ +}; + +/* + * capabilities of a stream + */ +struct sio_cap { +#define SIO_NENC 8 +#define SIO_NCHAN 8 +#define SIO_NRATE 16 +#define SIO_NCONF 4 + struct sio_enc { /* allowed sample encodings */ + unsigned int bits; + unsigned int bps; + unsigned int sig; + unsigned int le; + unsigned int msb; + } enc[SIO_NENC]; + unsigned int rchan[SIO_NCHAN]; /* allowed values for rchan */ + unsigned int pchan[SIO_NCHAN]; /* allowed values for pchan */ + unsigned int rate[SIO_NRATE]; /* allowed rates */ + int __pad[7]; /* for future use */ + unsigned int nconf; /* number of elements in confs[] */ + struct sio_conf { + unsigned int enc; /* mask of enc[] indexes */ + unsigned int rchan; /* mask of chan[] indexes (rec) */ + unsigned int pchan; /* mask of chan[] indexes (play) */ + unsigned int rate; /* mask of rate[] indexes */ + } confs[SIO_NCONF]; +}; + +#define SIO_XSTRINGS { "ignore", "sync", "error" } + +/* + * controlled component of the device + */ +struct sioctl_node { + char name[SIOCTL_NAMEMAX]; /* ex. "spkr" */ + int unit; /* optional number or -1 */ +}; + +/* + * description of a control (index, value) pair + */ +struct sioctl_desc { + unsigned int addr; /* control address */ +#define SIOCTL_NONE 0 /* deleted */ +#define SIOCTL_NUM 2 /* integer in the 0..maxval range */ +#define SIOCTL_SW 3 /* on/off switch (0 or 1) */ +#define SIOCTL_VEC 4 /* number, element of vector */ +#define SIOCTL_LIST 5 /* switch, element of a list */ +#define SIOCTL_SEL 6 /* element of a selector */ + unsigned int type; /* one of above */ + char func[SIOCTL_NAMEMAX]; /* function name, ex. "level" */ + char group[SIOCTL_NAMEMAX]; /* group this control belongs to */ + struct sioctl_node node0; /* affected node */ + struct sioctl_node node1; /* dito for SIOCTL_{VEC,LIST,SEL} */ + unsigned int maxval; /* max value */ + char display[SIOCTL_DISPLAYMAX]; /* free-format hint */ +}; + +/* + * mode bitmap + */ +#define SIO_PLAY 1 +#define SIO_REC 2 +#define MIO_OUT 4 +#define MIO_IN 8 +#define SIOCTL_READ 0x100 +#define SIOCTL_WRITE 0x200 + +/* + * default bytes per sample for the given bits per sample + */ +#define SIO_BPS(bits) (((bits) <= 8) ? 1 : (((bits) <= 16) ? 2 : 4)) + +/* + * default value of "sio_par->le" flag + */ +#if BYTE_ORDER == LITTLE_ENDIAN +#define SIO_LE_NATIVE 1 +#else +#define SIO_LE_NATIVE 0 +#endif + +/* + * maximum value of volume, eg. for sio_setvol() + */ +#define SIO_MAXVOL 127 + +#ifdef __cplusplus +extern "C" { +#endif + +struct pollfd; + +void sio_initpar(struct sio_par *); +struct sio_hdl *sio_open(const char *, unsigned int, int); +void sio_close(struct sio_hdl *); +int sio_setpar(struct sio_hdl *, struct sio_par *); +int sio_getpar(struct sio_hdl *, struct sio_par *); +int sio_getcap(struct sio_hdl *, struct sio_cap *); +void sio_onmove(struct sio_hdl *, void (*)(void *, int), void *); +size_t sio_write(struct sio_hdl *, const void *, size_t); +size_t sio_read(struct sio_hdl *, void *, size_t); +int sio_start(struct sio_hdl *); +int sio_stop(struct sio_hdl *); +int sio_flush(struct sio_hdl *); +int sio_nfds(struct sio_hdl *); +int sio_pollfd(struct sio_hdl *, struct pollfd *, int); +int sio_revents(struct sio_hdl *, struct pollfd *); +int sio_eof(struct sio_hdl *); +int sio_setvol(struct sio_hdl *, unsigned int); +int sio_onvol(struct sio_hdl *, void (*)(void *, unsigned int), void *); + +struct mio_hdl *mio_open(const char *, unsigned int, int); +void mio_close(struct mio_hdl *); +size_t mio_write(struct mio_hdl *, const void *, size_t); +size_t mio_read(struct mio_hdl *, void *, size_t); +int mio_nfds(struct mio_hdl *); +int mio_pollfd(struct mio_hdl *, struct pollfd *, int); +int mio_revents(struct mio_hdl *, struct pollfd *); +int mio_eof(struct mio_hdl *); + +struct sioctl_hdl *sioctl_open(const char *, unsigned int, int); +void sioctl_close(struct sioctl_hdl *); +int sioctl_ondesc(struct sioctl_hdl *, + void (*)(void *, struct sioctl_desc *, int), void *); +int sioctl_onval(struct sioctl_hdl *, + void (*)(void *, unsigned int, unsigned int), void *); +int sioctl_setval(struct sioctl_hdl *, unsigned int, unsigned int); +int sioctl_nfds(struct sioctl_hdl *); +int sioctl_pollfd(struct sioctl_hdl *, struct pollfd *, int); +int sioctl_revents(struct sioctl_hdl *, struct pollfd *); +int sioctl_eof(struct sioctl_hdl *); + +int mio_rmidi_getfd(const char *, unsigned int, int); +struct mio_hdl *mio_rmidi_fdopen(int, unsigned int, int); +int sio_sun_getfd(const char *, unsigned int, int); +struct sio_hdl *sio_sun_fdopen(int, unsigned int, int); +int sioctl_sun_getfd(const char *, unsigned int, int); +struct sioctl_hdl *sioctl_sun_fdopen(int, unsigned int, int); + +#ifdef __cplusplus +} +#endif + +#endif /* !defined(SNDIO_H) */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/soundcard.h b/lib/libc/include/generic-openbsd/soundcard.h new file mode 100644 index 000000000000..265990c9ce2f --- /dev/null +++ b/lib/libc/include/generic-openbsd/soundcard.h @@ -0,0 +1,317 @@ +/* $OpenBSD: soundcard.h,v 1.15 2015/01/22 00:07:15 deraadt Exp $ */ +/* $NetBSD: soundcard.h,v 1.11 2001/05/09 21:49:58 augustss Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Lennart Augustsson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * WARNING! WARNING! + * This is an OSS (Linux) audio emulator. + * Use the sndio(7) API for developing new code, and this + * only for compiling Linux programs. + */ + +#ifndef _SOUNDCARD_H_ +#define _SOUNDCARD_H_ + +#ifndef _SYS_IOCTL_H_ +#include +#endif /* !_SYS_IOCTL_H_ */ + +#define SOUND_VERSION 0x030001 + +#define SNDCTL_DSP_RESET _IO ('P', 0) +#define SNDCTL_DSP_SYNC _IO ('P', 1) +#define SNDCTL_DSP_SPEED _IOWR('P', 2, int) +#define SOUND_PCM_READ_RATE _IOR ('P', 2, int) +#define SNDCTL_DSP_STEREO _IOWR('P', 3, int) +#define SNDCTL_DSP_GETBLKSIZE _IOWR('P', 4, int) +#define SNDCTL_DSP_SETFMT _IOWR('P', 5, int) +#define AFMT_QUERY 0x00000000 +#define AFMT_MU_LAW 0x00000001 +#define AFMT_A_LAW 0x00000002 +#define AFMT_IMA_ADPCM 0x00000004 +#define AFMT_U8 0x00000008 +#define AFMT_S16_LE 0x00000010 +#define AFMT_S16_BE 0x00000020 +#define AFMT_S8 0x00000040 +#define AFMT_U16_LE 0x00000080 +#define AFMT_U16_BE 0x00000100 +#define AFMT_MPEG 0x00000200 +#define SNDCTL_DSP_SAMPLESIZE SNDCTL_DSP_SETFMT +#define SOUND_PCM_READ_BITS _IOR ('P', 5, int) +#define SNDCTL_DSP_CHANNELS _IOWR('P', 6, int) +#define SOUND_PCM_WRITE_CHANNELS SNDCTL_DSP_CHANNELS +#define SOUND_PCM_READ_CHANNELS _IOR ('P', 6, int) +#define SOUND_PCM_WRITE_FILTER _IOWR('P', 7, int) +#define SOUND_PCM_READ_FILTER _IOR ('P', 7, int) +#define SNDCTL_DSP_POST _IO ('P', 8) +#define SNDCTL_DSP_SUBDIVIDE _IOWR('P', 9, int) +#define SNDCTL_DSP_SETFRAGMENT _IOWR('P', 10, int) +#define SNDCTL_DSP_GETFMTS _IOR ('P', 11, int) +#define SNDCTL_DSP_GETOSPACE _IOR ('P',12, struct audio_buf_info) +#define SNDCTL_DSP_GETISPACE _IOR ('P',13, struct audio_buf_info) +#define SNDCTL_DSP_NONBLOCK _IO ('P',14) +#define SNDCTL_DSP_GETCAPS _IOR ('P',15, int) +# define DSP_CAP_REVISION 0x000000ff +# define DSP_CAP_DUPLEX 0x00000100 +# define DSP_CAP_REALTIME 0x00000200 +# define DSP_CAP_BATCH 0x00000400 +# define DSP_CAP_COPROC 0x00000800 +# define DSP_CAP_TRIGGER 0x00001000 +# define DSP_CAP_MMAP 0x00002000 +#define SNDCTL_DSP_GETTRIGGER _IOR ('P', 16, int) +#define SNDCTL_DSP_SETTRIGGER _IOW ('P', 16, int) +# define PCM_ENABLE_INPUT 0x00000001 +# define PCM_ENABLE_OUTPUT 0x00000002 +#define SNDCTL_DSP_GETIPTR _IOR ('P', 17, struct count_info) +#define SNDCTL_DSP_GETOPTR _IOR ('P', 18, struct count_info) +#define SNDCTL_DSP_MAPINBUF _IOR ('P', 19, struct buffmem_desc) +#define SNDCTL_DSP_MAPOUTBUF _IOR ('P', 20, struct buffmem_desc) +#define SNDCTL_DSP_SETSYNCRO _IO ('P', 21) +#define SNDCTL_DSP_SETDUPLEX _IO ('P', 22) +#define SNDCTL_DSP_PROFILE _IOW ('P', 23, int) +#define SNDCTL_DSP_GETODELAY _IOR ('P', 24, int) +#define APF_NORMAL 0 +#define APF_NETWORK 1 +#define APF_CPUINTENS 2 + +/* Need native 16 bit format which depends on byte order */ +/* XXX This isn't really a good way, but I don't want to + * include all of endian.h because it contains a lot + * junk symbols. [augustss] + */ +#if __BSD_VISIBLE +#undef __BSD_VISIBLE +#define __BSD_VISIBLE 0 /* avoid dragging in a lot of junk */ +#include +#undef __BSD_VISIBLE +#define __BSD_VISIBLE 1 +#else +#include +#endif +#if _QUAD_LOWWORD == 0 +#define AFMT_S16_NE AFMT_S16_LE +#else +#define AFMT_S16_NE AFMT_S16_BE +#endif + + +/* Aliases */ +#define SOUND_PCM_WRITE_BITS SNDCTL_DSP_SETFMT +#define SOUND_PCM_WRITE_RATE SNDCTL_DSP_SPEED +#define SOUND_PCM_POST SNDCTL_DSP_POST +#define SOUND_PCM_RESET SNDCTL_DSP_RESET +#define SOUND_PCM_SYNC SNDCTL_DSP_SYNC +#define SOUND_PCM_SUBDIVIDE SNDCTL_DSP_SUBDIVIDE +#define SOUND_PCM_SETFRAGMENT SNDCTL_DSP_SETFRAGMENT +#define SOUND_PCM_GETFMTS SNDCTL_DSP_GETFMTS +#define SOUND_PCM_SETFMT SNDCTL_DSP_SETFMT +#define SOUND_PCM_GETOSPACE SNDCTL_DSP_GETOSPACE +#define SOUND_PCM_GETISPACE SNDCTL_DSP_GETISPACE +#define SOUND_PCM_NONBLOCK SNDCTL_DSP_NONBLOCK +#define SOUND_PCM_GETCAPS SNDCTL_DSP_GETCAPS +#define SOUND_PCM_GETTRIGGER SNDCTL_DSP_GETTRIGGER +#define SOUND_PCM_SETTRIGGER SNDCTL_DSP_SETTRIGGER +#define SOUND_PCM_SETSYNCRO SNDCTL_DSP_SETSYNCRO +#define SOUND_PCM_GETIPTR SNDCTL_DSP_GETIPTR +#define SOUND_PCM_GETOPTR SNDCTL_DSP_GETOPTR +#define SOUND_PCM_MAPINBUF SNDCTL_DSP_MAPINBUF +#define SOUND_PCM_MAPOUTBUF SNDCTL_DSP_MAPOUTBUF + +/* Mixer defines */ +#define SOUND_MIXER_FIRST 0 +#define SOUND_MIXER_NRDEVICES 25 + +#define SOUND_MIXER_VOLUME 0 +#define SOUND_MIXER_BASS 1 +#define SOUND_MIXER_TREBLE 2 +#define SOUND_MIXER_SYNTH 3 +#define SOUND_MIXER_PCM 4 +#define SOUND_MIXER_SPEAKER 5 +#define SOUND_MIXER_LINE 6 +#define SOUND_MIXER_MIC 7 +#define SOUND_MIXER_CD 8 +#define SOUND_MIXER_IMIX 9 +#define SOUND_MIXER_ALTPCM 10 +#define SOUND_MIXER_RECLEV 11 +#define SOUND_MIXER_IGAIN 12 +#define SOUND_MIXER_OGAIN 13 +#define SOUND_MIXER_LINE1 14 +#define SOUND_MIXER_LINE2 15 +#define SOUND_MIXER_LINE3 16 +#define SOUND_MIXER_DIGITAL1 17 +#define SOUND_MIXER_DIGITAL2 18 +#define SOUND_MIXER_DIGITAL3 19 +#define SOUND_MIXER_PHONEIN 20 +#define SOUND_MIXER_PHONEOUT 21 +#define SOUND_MIXER_VIDEO 22 +#define SOUND_MIXER_RADIO 23 +#define SOUND_MIXER_MONITOR 24 + +#define SOUND_ONOFF_MIN 28 +#define SOUND_ONOFF_MAX 30 + +#define SOUND_MIXER_NONE 31 + +#define SOUND_DEVICE_LABELS {"Vol ", "Bass ", "Trebl", "Synth", "Pcm ", "Spkr ", "Line ", \ + "Mic ", "CD ", "Mix ", "Pcm2 ", "Rec ", "IGain", "OGain", \ + "Line1", "Line2", "Line3", "Digital1", "Digital2", "Digital3", \ + "PhoneIn", "PhoneOut", "Video", "Radio", "Monitor"} + +#define SOUND_DEVICE_NAMES {"vol", "bass", "treble", "synth", "pcm", "speaker", "line", \ + "mic", "cd", "mix", "pcm2", "rec", "igain", "ogain", \ + "line1", "line2", "line3", "dig1", "dig2", "dig3", \ + "phin", "phout", "video", "radio", "monitor"} + +#define SOUND_MIXER_RECSRC 0xff +#define SOUND_MIXER_DEVMASK 0xfe +#define SOUND_MIXER_RECMASK 0xfd +#define SOUND_MIXER_CAPS 0xfc +#define SOUND_CAP_EXCL_INPUT 1 +#define SOUND_MIXER_STEREODEVS 0xfb + +#define MIXER_READ(dev) _IOR('M', dev, int) + +#define SOUND_MIXER_READ_RECSRC MIXER_READ(SOUND_MIXER_RECSRC) +#define SOUND_MIXER_READ_DEVMASK MIXER_READ(SOUND_MIXER_DEVMASK) +#define SOUND_MIXER_READ_RECMASK MIXER_READ(SOUND_MIXER_RECMASK) +#define SOUND_MIXER_READ_STEREODEVS MIXER_READ(SOUND_MIXER_STEREODEVS) +#define SOUND_MIXER_READ_CAPS MIXER_READ(SOUND_MIXER_CAPS) + +#define SOUND_MIXER_READ_VOLUME MIXER_READ(SOUND_MIXER_VOLUME) +#define SOUND_MIXER_READ_BASS MIXER_READ(SOUND_MIXER_BASS) +#define SOUND_MIXER_READ_TREBLE MIXER_READ(SOUND_MIXER_TREBLE) +#define SOUND_MIXER_READ_SYNTH MIXER_READ(SOUND_MIXER_SYNTH) +#define SOUND_MIXER_READ_PCM MIXER_READ(SOUND_MIXER_PCM) +#define SOUND_MIXER_READ_SPEAKER MIXER_READ(SOUND_MIXER_SPEAKER) +#define SOUND_MIXER_READ_LINE MIXER_READ(SOUND_MIXER_LINE) +#define SOUND_MIXER_READ_MIC MIXER_READ(SOUND_MIXER_MIC) +#define SOUND_MIXER_READ_CD MIXER_READ(SOUND_MIXER_CD) +#define SOUND_MIXER_READ_IMIX MIXER_READ(SOUND_MIXER_IMIX) +#define SOUND_MIXER_READ_ALTPCM MIXER_READ(SOUND_MIXER_ALTPCM) +#define SOUND_MIXER_READ_RECLEV MIXER_READ(SOUND_MIXER_RECLEV) +#define SOUND_MIXER_READ_IGAIN MIXER_READ(SOUND_MIXER_IGAIN) +#define SOUND_MIXER_READ_OGAIN MIXER_READ(SOUND_MIXER_OGAIN) +#define SOUND_MIXER_READ_LINE1 MIXER_READ(SOUND_MIXER_LINE1) +#define SOUND_MIXER_READ_LINE2 MIXER_READ(SOUND_MIXER_LINE2) +#define SOUND_MIXER_READ_LINE3 MIXER_READ(SOUND_MIXER_LINE3) + +#define MIXER_WRITE(dev) _IOW ('M', dev, int) +#define MIXER_WRITE_R(dev) _IOWR('M', dev, int) + +#define SOUND_MIXER_WRITE_RECSRC MIXER_WRITE(SOUND_MIXER_RECSRC) +#define SOUND_MIXER_WRITE_R_RECSRC MIXER_WRITE_R(SOUND_MIXER_RECSRC) + +#define SOUND_MIXER_WRITE_VOLUME MIXER_WRITE(SOUND_MIXER_VOLUME) +#define SOUND_MIXER_WRITE_BASS MIXER_WRITE(SOUND_MIXER_BASS) +#define SOUND_MIXER_WRITE_TREBLE MIXER_WRITE(SOUND_MIXER_TREBLE) +#define SOUND_MIXER_WRITE_SYNTH MIXER_WRITE(SOUND_MIXER_SYNTH) +#define SOUND_MIXER_WRITE_PCM MIXER_WRITE(SOUND_MIXER_PCM) +#define SOUND_MIXER_WRITE_SPEAKER MIXER_WRITE(SOUND_MIXER_SPEAKER) +#define SOUND_MIXER_WRITE_LINE MIXER_WRITE(SOUND_MIXER_LINE) +#define SOUND_MIXER_WRITE_MIC MIXER_WRITE(SOUND_MIXER_MIC) +#define SOUND_MIXER_WRITE_CD MIXER_WRITE(SOUND_MIXER_CD) +#define SOUND_MIXER_WRITE_IMIX MIXER_WRITE(SOUND_MIXER_IMIX) +#define SOUND_MIXER_WRITE_ALTPCM MIXER_WRITE(SOUND_MIXER_ALTPCM) +#define SOUND_MIXER_WRITE_RECLEV MIXER_WRITE(SOUND_MIXER_RECLEV) +#define SOUND_MIXER_WRITE_IGAIN MIXER_WRITE(SOUND_MIXER_IGAIN) +#define SOUND_MIXER_WRITE_OGAIN MIXER_WRITE(SOUND_MIXER_OGAIN) +#define SOUND_MIXER_WRITE_LINE1 MIXER_WRITE(SOUND_MIXER_LINE1) +#define SOUND_MIXER_WRITE_LINE2 MIXER_WRITE(SOUND_MIXER_LINE2) +#define SOUND_MIXER_WRITE_LINE3 MIXER_WRITE(SOUND_MIXER_LINE3) + +#define SOUND_MASK_VOLUME (1 << SOUND_MIXER_VOLUME) +#define SOUND_MASK_BASS (1 << SOUND_MIXER_BASS) +#define SOUND_MASK_TREBLE (1 << SOUND_MIXER_TREBLE) +#define SOUND_MASK_SYNTH (1 << SOUND_MIXER_SYNTH) +#define SOUND_MASK_PCM (1 << SOUND_MIXER_PCM) +#define SOUND_MASK_SPEAKER (1 << SOUND_MIXER_SPEAKER) +#define SOUND_MASK_LINE (1 << SOUND_MIXER_LINE) +#define SOUND_MASK_MIC (1 << SOUND_MIXER_MIC) +#define SOUND_MASK_CD (1 << SOUND_MIXER_CD) +#define SOUND_MASK_IMIX (1 << SOUND_MIXER_IMIX) +#define SOUND_MASK_ALTPCM (1 << SOUND_MIXER_ALTPCM) +#define SOUND_MASK_RECLEV (1 << SOUND_MIXER_RECLEV) +#define SOUND_MASK_IGAIN (1 << SOUND_MIXER_IGAIN) +#define SOUND_MASK_OGAIN (1 << SOUND_MIXER_OGAIN) +#define SOUND_MASK_LINE1 (1 << SOUND_MIXER_LINE1) +#define SOUND_MASK_LINE2 (1 << SOUND_MIXER_LINE2) +#define SOUND_MASK_LINE3 (1 << SOUND_MIXER_LINE3) +#define SOUND_MASK_DIGITAL1 (1 << SOUND_MIXER_DIGITAL1) +#define SOUND_MASK_DIGITAL2 (1 << SOUND_MIXER_DIGITAL2) +#define SOUND_MASK_DIGITAL3 (1 << SOUND_MIXER_DIGITAL3) +#define SOUND_MASK_PHONEIN (1 << SOUND_MIXER_PHONEIN) +#define SOUND_MASK_PHONEOUT (1 << SOUND_MIXER_PHONEOUT) +#define SOUND_MASK_VIDEO (1 << SOUND_MIXER_VIDEO) +#define SOUND_MASK_RADIO (1 << SOUND_MIXER_RADIO) +#define SOUND_MASK_MONITOR (1 << SOUND_MIXER_MONITOR) + +typedef struct mixer_info { + char id[16]; + char name[32]; + int modify_counter; + int fillers[10]; +} mixer_info; + +typedef struct _old_mixer_info { + char id[16]; + char name[32]; +} _old_mixer_info; + +#define SOUND_MIXER_INFO _IOR ('M', 101, mixer_info) +#define SOUND_OLD_MIXER_INFO _IOR ('M', 101, _old_mixer_info) + +#define OSS_GETVERSION _IOR ('M', 118, int) + +typedef struct audio_buf_info { + int fragments; + int fragstotal; + int fragsize; + int bytes; +} audio_buf_info; + +typedef struct count_info { + int bytes; + int blocks; + int ptr; +} count_info; + +typedef struct buffmem_desc { + unsigned int *buffer; + int size; +} buffmem_desc; + +#define ioctl _oss_ioctl + +__BEGIN_DECLS +int _oss_ioctl(int, unsigned long com, ...); +__END_DECLS + +#endif /* !_SOUNDCARD_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/spawn.h b/lib/libc/include/generic-openbsd/spawn.h new file mode 100644 index 000000000000..79f2dd47b767 --- /dev/null +++ b/lib/libc/include/generic-openbsd/spawn.h @@ -0,0 +1,103 @@ +/* $OpenBSD: spawn.h,v 1.3 2015/05/20 22:50:07 millert Exp $ */ +/*- + * Copyright (c) 2008 Ed Schouten + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/include/spawn.h,v 1.3.2.1.6.1 2010/12/21 17:09:25 kensmith Exp $ + */ + +#ifndef _SPAWN_H_ +#define _SPAWN_H_ + +#include +#include + +struct sched_param; + +typedef struct __posix_spawnattr *posix_spawnattr_t; +typedef struct __posix_spawn_file_actions *posix_spawn_file_actions_t; + +#define POSIX_SPAWN_RESETIDS 0x01 +#define POSIX_SPAWN_SETPGROUP 0x02 +#define POSIX_SPAWN_SETSCHEDPARAM 0x04 +#define POSIX_SPAWN_SETSCHEDULER 0x08 +#define POSIX_SPAWN_SETSIGDEF 0x10 +#define POSIX_SPAWN_SETSIGMASK 0x20 + +__BEGIN_DECLS +/* + * Spawn routines + * + * XXX both arrays should be __restrict, but this does not work when GCC + * is invoked with -std=c99. + */ +int posix_spawn(pid_t *__restrict, const char *__restrict, + const posix_spawn_file_actions_t *, const posix_spawnattr_t *__restrict, + char *const [], char *const []); +int posix_spawnp(pid_t *__restrict, const char *__restrict, + const posix_spawn_file_actions_t *, const posix_spawnattr_t *__restrict, + char *const [], char *const []); + +/* + * File descriptor actions + */ +int posix_spawn_file_actions_init(posix_spawn_file_actions_t *); +int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *); + +int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *__restrict, + int, const char *__restrict, int, mode_t); +int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *, int, int); +int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *, int); + +/* + * Spawn attributes + */ +int posix_spawnattr_init(posix_spawnattr_t *); +int posix_spawnattr_destroy(posix_spawnattr_t *); + +int posix_spawnattr_getflags(const posix_spawnattr_t *__restrict, + short *__restrict); +int posix_spawnattr_getpgroup(const posix_spawnattr_t *__restrict, + pid_t *__restrict); +int posix_spawnattr_getschedparam(const posix_spawnattr_t *__restrict, + struct sched_param *__restrict); +int posix_spawnattr_getschedpolicy(const posix_spawnattr_t *__restrict, + int *__restrict); +int posix_spawnattr_getsigdefault(const posix_spawnattr_t *__restrict, + sigset_t *__restrict); +int posix_spawnattr_getsigmask(const posix_spawnattr_t *__restrict, + sigset_t *__restrict); + +int posix_spawnattr_setflags(posix_spawnattr_t *, short); +int posix_spawnattr_setpgroup(posix_spawnattr_t *, pid_t); +int posix_spawnattr_setschedparam(posix_spawnattr_t *__restrict, + const struct sched_param *__restrict); +int posix_spawnattr_setschedpolicy(posix_spawnattr_t *, int); +int posix_spawnattr_setsigdefault(posix_spawnattr_t *__restrict, + const sigset_t *__restrict); +int posix_spawnattr_setsigmask(posix_spawnattr_t *__restrict, + const sigset_t *__restrict); +__END_DECLS + +#endif /* !_SPAWN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/stdarg.h b/lib/libc/include/generic-openbsd/stdarg.h new file mode 100644 index 000000000000..0fbd75bb6e00 --- /dev/null +++ b/lib/libc/include/generic-openbsd/stdarg.h @@ -0,0 +1,45 @@ +/* $OpenBSD: stdarg.h,v 1.10 2020/07/21 23:09:00 daniel Exp $ */ +/* + * Copyright (c) 2003, 2004 Marc espie + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _STDARG_H_ +#define _STDARG_H_ + +#include + +/* Define __gnuc_va_list. */ + +#ifndef __GNUC_VA_LIST +#define __GNUC_VA_LIST +typedef __builtin_va_list __gnuc_va_list; +#endif + +/* Note that the type used in va_arg is supposed to match the + actual type **after default promotions**. + Thus, va_arg (..., short) is not valid. */ + +#define va_start(ap, last) __builtin_va_start((ap), last) +#define va_end(ap) __builtin_va_end((ap)) +#define va_arg(ap, type) __builtin_va_arg((ap), type) +#define __va_copy(dst, src) __builtin_va_copy((dst),(src)) + +typedef __gnuc_va_list va_list; + +#if __ISO_C_VISIBLE >= 1999 +#define va_copy(dst, src) __va_copy((dst), (src)) +#endif + +#endif /* not _STDARG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/stdbool.h b/lib/libc/include/generic-openbsd/stdbool.h new file mode 100644 index 000000000000..f59fd124250a --- /dev/null +++ b/lib/libc/include/generic-openbsd/stdbool.h @@ -0,0 +1,45 @@ +/* $OpenBSD: stdbool.h,v 1.7 2015/09/04 23:47:09 daniel Exp $ */ + +/* + * Written by Marc Espie, September 25, 1999 + * Public domain. + */ + +#ifndef _STDBOOL_H_ +#define _STDBOOL_H_ + +#ifndef __cplusplus + +#if defined(__GNUC__) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901) +/* Support for C99: type _Bool is already built-in. */ +#define false 0 +#define true 1 + +#else +/* `_Bool' type must promote to `int' or `unsigned int'. */ +typedef enum { + false = 0, + true = 1 +} _Bool; + +/* And those constants must also be available as macros. */ +#define false false +#define true true + +#endif + +/* User visible type `bool' is provided as a macro which may be redefined */ +#define bool _Bool + +#else /* __cplusplus */ +#define _Bool bool +#define bool bool +#define false false +#define true true +#endif /* __cplusplus */ + +/* Inform that everything is fine */ +#define __bool_true_false_are_defined 1 + +#endif /* _STDBOOL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/stddef.h b/lib/libc/include/generic-openbsd/stddef.h new file mode 100644 index 000000000000..4d7038050dda --- /dev/null +++ b/lib/libc/include/generic-openbsd/stddef.h @@ -0,0 +1,84 @@ +/* $OpenBSD: stddef.h,v 1.14 2017/01/06 14:36:50 kettenis Exp $ */ +/* $NetBSD: stddef.h,v 1.4 1994/10/26 00:56:26 cgd Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)stddef.h 5.5 (Berkeley) 4/3/91 + */ + +#ifndef _STDDEF_H_ +#define _STDDEF_H_ + +#include +#include +#include + +#ifndef _PTRDIFF_T_DEFINED_ +#define _PTRDIFF_T_DEFINED_ +typedef __ptrdiff_t ptrdiff_t; +#endif + +#ifndef _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED_ +typedef __size_t size_t; +#endif + +/* in C++, wchar_t is a built-in type */ +#if !defined(_WCHAR_T_DEFINED_) && !defined(__cplusplus) +#define _WCHAR_T_DEFINED_ +typedef __wchar_t wchar_t; +#endif + +#ifndef _WINT_T_DEFINED_ +#define _WINT_T_DEFINED_ +typedef __wint_t wint_t; +#endif + +#ifndef _MBSTATE_T_DEFINED_ +#define _MBSTATE_T_DEFINED_ +typedef __mbstate_t mbstate_t; +#endif + +#if __GNUC_PREREQ__(4, 0) +#define offsetof(type, member) __builtin_offsetof(type, member) +#else +#define offsetof(type, member) ((size_t)(&((type *)0)->member)) +#endif + +#if __ISO_C_VISIBLE >= 2011 || __cplusplus >= 201103 +#ifndef __CLANG_MAX_ALIGN_T_DEFINED +#define __CLANG_MAX_ALIGN_T_DEFINED +typedef struct { + long long __max_align_ll __aligned(__alignof__(long long)); + long double __max_align_ld __aligned(__alignof__(long double)); +} max_align_t; +#endif +#endif + +#endif /* _STDDEF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/stdint.h b/lib/libc/include/generic-openbsd/stdint.h new file mode 100644 index 000000000000..c0372ec51c5d --- /dev/null +++ b/lib/libc/include/generic-openbsd/stdint.h @@ -0,0 +1,231 @@ +/* $OpenBSD: stdint.h,v 1.11 2019/01/25 00:19:26 millert Exp $ */ + +/* + * Copyright (c) 1997, 2005 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_STDINT_H_ +#define _SYS_STDINT_H_ + +#include +#include + +#ifndef __BIT_TYPES_DEFINED__ +#define __BIT_TYPES_DEFINED__ +#endif + +/* 7.18.1.1 Exact-width integer types (also in sys/types.h) */ +#ifndef _INT8_T_DEFINED_ +#define _INT8_T_DEFINED_ +typedef __int8_t int8_t; +#endif + +#ifndef _UINT8_T_DEFINED_ +#define _UINT8_T_DEFINED_ +typedef __uint8_t uint8_t; +#endif + +#ifndef _INT16_T_DEFINED_ +#define _INT16_T_DEFINED_ +typedef __int16_t int16_t; +#endif + +#ifndef _UINT16_T_DEFINED_ +#define _UINT16_T_DEFINED_ +typedef __uint16_t uint16_t; +#endif + +#ifndef _INT32_T_DEFINED_ +#define _INT32_T_DEFINED_ +typedef __int32_t int32_t; +#endif + +#ifndef _UINT32_T_DEFINED_ +#define _UINT32_T_DEFINED_ +typedef __uint32_t uint32_t; +#endif + +#ifndef _INT64_T_DEFINED_ +#define _INT64_T_DEFINED_ +typedef __int64_t int64_t; +#endif + +#ifndef _UINT64_T_DEFINED_ +#define _UINT64_T_DEFINED_ +typedef __uint64_t uint64_t; +#endif + +/* 7.18.1.2 Minimum-width integer types */ +typedef __int_least8_t int_least8_t; +typedef __uint_least8_t uint_least8_t; +typedef __int_least16_t int_least16_t; +typedef __uint_least16_t uint_least16_t; +typedef __int_least32_t int_least32_t; +typedef __uint_least32_t uint_least32_t; +typedef __int_least64_t int_least64_t; +typedef __uint_least64_t uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types */ +typedef __int_fast8_t int_fast8_t; +typedef __uint_fast8_t uint_fast8_t; +typedef __int_fast16_t int_fast16_t; +typedef __uint_fast16_t uint_fast16_t; +typedef __int_fast32_t int_fast32_t; +typedef __uint_fast32_t uint_fast32_t; +typedef __int_fast64_t int_fast64_t; +typedef __uint_fast64_t uint_fast64_t; + +/* 7.18.1.4 Integer types capable of holding object pointers */ +#ifndef _INTPTR_T_DEFINED_ +#define _INTPTR_T_DEFINED_ +typedef __intptr_t intptr_t; +#endif + +typedef __uintptr_t uintptr_t; + +/* 7.18.1.5 Greatest-width integer types */ +typedef __intmax_t intmax_t; +typedef __uintmax_t uintmax_t; + +/* + * 7.18.2 Limits of specified-width integer types. + * + * The following object-like macros specify the minimum and maximum limits + * of integer types corresponding to the typedef names defined above. + */ + +/* 7.18.2.1 Limits of exact-width integer types */ +#define INT8_MIN (-0x7f - 1) +#define INT16_MIN (-0x7fff - 1) +#define INT32_MIN (-0x7fffffff - 1) +#define INT64_MIN (-0x7fffffffffffffffLL - 1) + +#define INT8_MAX 0x7f +#define INT16_MAX 0x7fff +#define INT32_MAX 0x7fffffff +#define INT64_MAX 0x7fffffffffffffffLL + +#define UINT8_MAX 0xff +#define UINT16_MAX 0xffff +#define UINT32_MAX 0xffffffffU +#define UINT64_MAX 0xffffffffffffffffULL + +/* 7.18.2.2 Limits of minimum-width integer types */ +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST64_MIN INT64_MIN + +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MAX INT64_MAX + +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +/* 7.18.2.3 Limits of fastest minimum-width integer types */ +#define INT_FAST8_MIN __INT_FAST8_MIN +#define INT_FAST16_MIN __INT_FAST16_MIN +#define INT_FAST32_MIN __INT_FAST32_MIN +#define INT_FAST64_MIN __INT_FAST64_MIN + +#define INT_FAST8_MAX __INT_FAST8_MAX +#define INT_FAST16_MAX __INT_FAST16_MAX +#define INT_FAST32_MAX __INT_FAST32_MAX +#define INT_FAST64_MAX __INT_FAST64_MAX + +#define UINT_FAST8_MAX __UINT_FAST8_MAX +#define UINT_FAST16_MAX __UINT_FAST16_MAX +#define UINT_FAST32_MAX __UINT_FAST32_MAX +#define UINT_FAST64_MAX __UINT_FAST64_MAX + +/* 7.18.2.4 Limits of integer types capable of holding object pointers */ +#ifdef __LP64__ +#define INTPTR_MIN (-0x7fffffffffffffffL - 1) +#define INTPTR_MAX 0x7fffffffffffffffL +#define UINTPTR_MAX 0xffffffffffffffffUL +#else +#define INTPTR_MIN (-0x7fffffffL - 1) +#define INTPTR_MAX 0x7fffffffL +#define UINTPTR_MAX 0xffffffffUL +#endif + +/* 7.18.2.5 Limits of greatest-width integer types */ +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +/* + * 7.18.3 Limits of other integer types. + * + * The following object-like macros specify the minimum and maximum limits + * of integer types corresponding to types specified in other standard + * header files. + */ + +/* Limits of ptrdiff_t */ +#define PTRDIFF_MIN INTPTR_MIN +#define PTRDIFF_MAX INTPTR_MAX + +/* Limits of sig_atomic_t */ +#define SIG_ATOMIC_MIN INT32_MIN +#define SIG_ATOMIC_MAX INT32_MAX + +/* Limit of size_t */ +#ifndef SIZE_MAX +#define SIZE_MAX UINTPTR_MAX +#endif + +/* Limits of wchar_t */ +#ifndef WCHAR_MIN +#define WCHAR_MIN INT32_MIN +#endif +#ifndef WCHAR_MAX +#define WCHAR_MAX INT32_MAX +#endif + +/* Limits of wint_t */ +#define WINT_MIN INT32_MIN +#define WINT_MAX INT32_MAX + +/* + * 7.18.4 Macros for integer constants. + * + * The following function-like macros expand to integer constants + * suitable for initializing objects that have integer types corresponding + * to types defined in . The argument in any instance of + * these macros shall be a decimal, octal, or hexadecimal constant with + * a value that does not exceed the limits for the corresponding type. + */ + +/* 7.18.4.1 Macros for minimum-width integer constants. */ +#define INT8_C(_c) (_c) +#define INT16_C(_c) (_c) +#define INT32_C(_c) (_c) +#define INT64_C(_c) __CONCAT(_c, LL) + +#define UINT8_C(_c) (_c) +#define UINT16_C(_c) (_c) +#define UINT32_C(_c) __CONCAT(_c, U) +#define UINT64_C(_c) __CONCAT(_c, ULL) + +/* 7.18.4.2 Macros for greatest-width integer constants. */ +#define INTMAX_C(_c) __CONCAT(_c, LL) +#define UINTMAX_C(_c) __CONCAT(_c, ULL) + +#endif /* _SYS_STDINT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/stdio.h b/lib/libc/include/generic-openbsd/stdio.h new file mode 100644 index 000000000000..d4840555b250 --- /dev/null +++ b/lib/libc/include/generic-openbsd/stdio.h @@ -0,0 +1,308 @@ +/* $OpenBSD: stdio.h,v 1.57 2025/07/16 15:33:05 yasuoka Exp $ */ +/* $NetBSD: stdio.h,v 1.18 1996/04/25 18:29:21 jtc Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)stdio.h 5.17 (Berkeley) 6/3/91 + */ + +#ifndef _STDIO_H_ +#define _STDIO_H_ + +#include +#include +#include + +#if __BSD_VISIBLE || __POSIX_VISIBLE || __XPG_VISIBLE +#include /* XXX should be removed */ +#endif + +#ifndef _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED_ +typedef __size_t size_t; +#endif + +#ifndef _OFF_T_DEFINED_ +#define _OFF_T_DEFINED_ +typedef __off_t off_t; +#endif + +#define _FSTDIO /* Define for new stdio with functions. */ + +typedef off_t fpos_t; /* stdio file position type */ + +#ifndef _STDFILES_DECLARED +#define _STDFILES_DECLARED +typedef struct __sFILE FILE; +struct __sFstub { long _stub; }; + +__BEGIN_DECLS +extern struct __sFstub __stdin[]; +extern struct __sFstub __stdout[]; +extern struct __sFstub __stderr[]; +__END_DECLS +#endif + +#define stdin ((struct __sFILE *)__stdin) +#define stdout ((struct __sFILE *)__stdout) +#define stderr ((struct __sFILE *)__stderr) + +/* + * The following three definitions are for ANSI C, which took them + * from System V, which brilliantly took internal interface macros and + * made them official arguments to setvbuf(), without renaming them. + * Hence, these ugly _IOxxx names are *supposed* to appear in user code. + * + * Although numbered as their counterparts above, the implementation + * does not rely on this. + */ +#define _IOFBF 0 /* setvbuf should set fully buffered */ +#define _IOLBF 1 /* setvbuf should set line buffered */ +#define _IONBF 2 /* setvbuf should set unbuffered */ + +#define BUFSIZ 1024 /* size of buffer used by setbuf */ + +#define EOF (-1) + +/* + * FOPEN_MAX is a minimum maximum, and should be the number of descriptors + * that the kernel can provide without allocation of a resource that can + * fail without the process sleeping. Do not use this for anything. + */ +#define FOPEN_MAX 20 /* must be <= OPEN_MAX */ +#define FILENAME_MAX 1024 /* must be <= PATH_MAX */ + +/* System V/ANSI C; this is the wrong way to do this, do *not* use these. */ +#if __BSD_VISIBLE || __XPG_VISIBLE +#define P_tmpdir "/tmp/" +#endif +#define L_tmpnam 1024 /* XXX must be == PATH_MAX */ +#define TMP_MAX 0x7fffffff /* more, but don't overflow int */ + +#ifndef SEEK_SET +#define SEEK_SET 0 /* set file offset to offset */ +#endif +#ifndef SEEK_CUR +#define SEEK_CUR 1 /* set file offset to current plus offset */ +#endif +#ifndef SEEK_END +#define SEEK_END 2 /* set file offset to EOF plus offset */ +#endif + +/* + * Functions defined in ANSI C standard. + */ +__BEGIN_DECLS +void clearerr(FILE *); +#if __POSIX_VISIBLE >= 200809 +int dprintf(int, const char * __restrict, ...) + __attribute__((__format__ (printf, 2, 3))) + __attribute__((__nonnull__ (2))); +#endif +int fclose(FILE *); +int feof(FILE *); +int ferror(FILE *); +int fflush(FILE *); +int fgetc(FILE *); +int fgetpos(FILE *, fpos_t *); +char *fgets(char *, int, FILE *) + __attribute__((__bounded__ (__string__,1,2))); +FILE *fopen(const char *, const char *); +int fprintf(FILE *, const char * __restrict, ...); +int fputc(int, FILE *); +int fputs(const char *, FILE *); +size_t fread(void *, size_t, size_t, FILE *) + __attribute__((__bounded__ (__size__,1,3,2))); +FILE *freopen(const char *, const char *, FILE *); +int fscanf(FILE *, const char *, ...); +int fseek(FILE *, long, int); +int fseeko(FILE *, off_t, int); +int fsetpos(FILE *, const fpos_t *); +long ftell(FILE *); +off_t ftello(FILE *); +size_t fwrite(const void *, size_t, size_t, FILE *) + __attribute__((__bounded__ (__size__,1,3,2))); +int getc(FILE *); +int getchar(void); +#if __POSIX_VISIBLE >= 200809 +ssize_t getdelim(char ** __restrict, size_t * __restrict, int, + FILE * __restrict); +ssize_t getline(char ** __restrict, size_t * __restrict, + FILE * __restrict); +#endif +#if __BSD_VISIBLE && !defined(__SYS_ERRLIST) +#define __SYS_ERRLIST + +extern int sys_nerr; /* perror(3) external variables */ +extern char *sys_errlist[]; +#endif +void perror(const char *); +int printf(const char * __restrict, ...); +int putc(int, FILE *); +int putchar(int); +int puts(const char *); +int remove(const char *); +int rename(const char *, const char *); +#if __POSIX_VISIBLE >= 200809 +int renameat(int, const char *, int, const char *); +#endif +void rewind(FILE *); +int scanf(const char *, ...); +void setbuf(FILE *, char *); +int setvbuf(FILE *, char *, int, size_t); +int sprintf(char * __restrict, const char * __restrict, ...); +int sscanf(const char *, const char *, ...); +FILE *tmpfile(void); +char *tmpnam(char *); +int ungetc(int, FILE *); +int vfprintf(FILE *, const char * __restrict, __va_list); +int vprintf(const char * __restrict, __va_list); +int vsprintf(char * __restrict, const char * __restrict, __va_list); +#if __POSIX_VISIBLE >= 200809 +int vdprintf(int, const char * __restrict, __va_list) + __attribute__((__format__ (printf, 2, 0))) + __attribute__((__nonnull__ (2))); +#endif + +#if __ISO_C_VISIBLE >= 1999 || __XPG_VISIBLE >= 500 || __BSD_VISIBLE +int snprintf(char * __restrict, size_t, const char * __restrict, ...) + __attribute__((__format__ (printf, 3, 4))) + __attribute__((__nonnull__ (3))) + __attribute__((__bounded__ (__string__,1,2))); +int vsnprintf(char * __restrict, size_t, const char * __restrict, + __va_list) + __attribute__((__format__ (printf, 3, 0))) + __attribute__((__nonnull__ (3))) + __attribute__((__bounded__(__string__,1,2))); +#endif /* __ISO_C_VISIBLE >= 1999 || __XPG_VISIBLE >= 500 || __BSD_VISIBLE */ + +#if __ISO_C_VISIBLE >= 1999 || __BSD_VISIBLE +int vfscanf(FILE *, const char *, __va_list) + __attribute__((__format__ (scanf, 2, 0))) + __attribute__((__nonnull__ (2))); +int vscanf(const char *, __va_list) + __attribute__((__format__ (scanf, 1, 0))) + __attribute__((__nonnull__ (1))); +int vsscanf(const char *, const char *, __va_list) + __attribute__((__format__ (scanf, 2, 0))) + __attribute__((__nonnull__ (2))); +#endif /* __ISO_C_VISIBLE >= 1999 || __BSD_VISIBLE */ + +__END_DECLS + + +/* + * Functions defined in POSIX 1003.1. + */ +#if __BSD_VISIBLE || __POSIX_VISIBLE || __XPG_VISIBLE +#define L_ctermid 1024 /* size for ctermid(); PATH_MAX */ + +__BEGIN_DECLS +char *ctermid(char *); +FILE *fdopen(int, const char *); +int fileno(FILE *); + +#if __POSIX_VISIBLE >= 199209 +int pclose(FILE *); +FILE *popen(const char *, const char *); +#endif + +#if __POSIX_VISIBLE >= 199506 +void flockfile(FILE *); +int ftrylockfile(FILE *); +void funlockfile(FILE *); + +/* + * These are normally used through macros as defined below, but POSIX + * requires functions as well. + */ +int getc_unlocked(FILE *); +int getchar_unlocked(void); +int putc_unlocked(int, FILE *); +int putchar_unlocked(int); +#endif /* __POSIX_VISIBLE >= 199506 */ + +#if __POSIX_VISIBLE >= 200809 +FILE *fmemopen(void *, size_t, const char *); +FILE *open_memstream(char **, size_t *); +#endif /* __POSIX_VISIBLE >= 200809 */ + +#if __XPG_VISIBLE +char *tempnam(const char *, const char *); +#endif + +#if __POSIX_VISIBLE >= 202405 || __BSD_VISIBLE +int asprintf(char ** __restrict, const char * __restrict, ...) + __attribute__((__format__ (printf, 2, 3))) + __attribute__((__nonnull__ (2))); +int vasprintf(char ** __restrict, const char * __restrict, __va_list) + __attribute__((__format__ (printf, 2, 0))) + __attribute__((__nonnull__ (2))); +#endif /* __POSIX_VISIBLE >= 202405 || __BSD_VISIBLE */ +__END_DECLS + +#endif /* __BSD_VISIBLE || __POSIX_VISIBLE || __XPG_VISIBLE */ + +/* + * Routines that are purely local. + */ +#if __BSD_VISIBLE +__BEGIN_DECLS +int fdclose(FILE *, int *_fdp); +char *fgetln(FILE *, size_t *); +int fpurge(FILE *); +int getw(FILE *); +int putw(int, FILE *); +void setbuffer(FILE *, char *, int); +int setlinebuf(FILE *); +__END_DECLS + +/* + * Stdio function-access interface. + */ +__BEGIN_DECLS +FILE *funopen(const void *, + int (*)(void *, char *, int), + int (*)(void *, const char *, int), + off_t (*)(void *, off_t, int), + int (*)(void *)); +__END_DECLS +#define fropen(cookie, fn) funopen(cookie, fn, 0, 0, 0) +#define fwopen(cookie, fn) funopen(cookie, 0, fn, 0, 0) +#endif /* __BSD_VISIBLE */ + +#define getchar() getc(stdin) +#define putchar(x) putc(x, stdout) +#define getchar_unlocked() getc_unlocked(stdin) +#define putchar_unlocked(c) putc_unlocked(c, stdout) + +#endif /* _STDIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/stdio_ext.h b/lib/libc/include/generic-openbsd/stdio_ext.h new file mode 100644 index 000000000000..28c97f25eb20 --- /dev/null +++ b/lib/libc/include/generic-openbsd/stdio_ext.h @@ -0,0 +1,31 @@ +/* $OpenBSD: stdio_ext.h,v 1.1 2024/08/12 20:56:55 guenther Exp $ */ +/* + * Copyright (c) 2024 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _STDIO_EXT_H_ +#define _STDIO_EXT_H_ + +#include + +size_t __fpending(FILE *); +size_t __freadahead(FILE *); +int __freading(FILE *); +const char *__freadptr(FILE *, size_t *_sizep); +void __freadptrinc(FILE *, size_t _inc); +void __fseterr(FILE *); +int __fwriting(FILE *); + +#endif /* _STDIO_EXT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/stdlib.h b/lib/libc/include/generic-openbsd/stdlib.h new file mode 100644 index 000000000000..a7ffcea8eac3 --- /dev/null +++ b/lib/libc/include/generic-openbsd/stdlib.h @@ -0,0 +1,324 @@ +/* $OpenBSD: stdlib.h,v 1.78 2024/08/03 20:09:24 guenther Exp $ */ +/* $NetBSD: stdlib.h,v 1.25 1995/12/27 21:19:08 jtc Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)stdlib.h 5.13 (Berkeley) 6/4/91 + */ + +#ifndef _STDLIB_H_ +#define _STDLIB_H_ + +#include +#include +#include +#if __BSD_VISIBLE /* for quad_t, etc. (XXX - use protected types) */ +#include +#endif + +#ifndef _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED_ +typedef __size_t size_t; +#endif + +/* in C++, wchar_t is a built-in type */ +#if !defined(_WCHAR_T_DEFINED_) && !defined(__cplusplus) +#define _WCHAR_T_DEFINED_ +typedef __wchar_t wchar_t; +#endif + +typedef struct { + int quot; /* quotient */ + int rem; /* remainder */ +} div_t; + +typedef struct { + long quot; /* quotient */ + long rem; /* remainder */ +} ldiv_t; + +#if __ISO_C_VISIBLE >= 1999 +typedef struct { + long long quot; /* quotient */ + long long rem; /* remainder */ +} lldiv_t; +#endif + +#if __BSD_VISIBLE +typedef struct { + quad_t quot; /* quotient */ + quad_t rem; /* remainder */ +} qdiv_t; +#endif + +#define EXIT_FAILURE 1 +#define EXIT_SUCCESS 0 + +#define RAND_MAX 0x7fffffff + +#define MB_CUR_MAX __mb_cur_max() + +/* + * Some header files may define an abs macro. + * If defined, undef it to prevent a syntax error and issue a warning. + */ +#ifdef abs +#undef abs +#warning abs macro collides with abs() prototype, undefining +#endif + +__BEGIN_DECLS +__dead void abort(void); +int abs(int); +int atexit(void (*)(void)); +double atof(const char *); +int atoi(const char *); +long atol(const char *); +void *bsearch(const void *, const void *, size_t, size_t, + int (*)(const void *, const void *)); +void *calloc(size_t, size_t); +div_t div(int, int); +__dead void exit(int); +__dead void _Exit(int); +void free(void *); +char *getenv(const char *); +long labs(long); +ldiv_t ldiv(long, long); +void *malloc(size_t); +#if __BSD_VISIBLE +void freezero(void *, size_t) + __attribute__ ((__bounded__(__buffer__,1,2))); +void *calloc_conceal(size_t, size_t); +void *malloc_conceal(size_t); +void *recallocarray(void *, size_t, size_t, size_t); +#endif /* __BSD_VISIBLE */ +void qsort(void *, size_t, size_t, int (*)(const void *, const void *)); +int rand(void); +void *realloc(void *, size_t); +void srand(unsigned); +void srand_deterministic(unsigned); +double strtod(const char *__restrict, char **__restrict); +float strtof(const char *__restrict, char **__restrict); +long strtol(const char *__restrict, char **__restrict, int); +long double + strtold(const char *__restrict, char **__restrict); +unsigned long + strtoul(const char *__restrict, char **__restrict, int); +int system(const char *); + +size_t __mb_cur_max(void); +int mblen(const char *, size_t); +size_t mbstowcs(wchar_t *, const char *, size_t); +int wctomb(char *, wchar_t); +int mbtowc(wchar_t *, const char *, size_t); +size_t wcstombs(char *, const wchar_t *, size_t); + +/* + * IEEE Std 1003.1c-95, also adopted by X/Open CAE Spec Issue 5 Version 2 + */ +#if __BSD_VISIBLE || __POSIX_VISIBLE >= 199506 || defined(_REENTRANT) +int rand_r(unsigned int *); +#endif + +#if __BSD_VISIBLE || __XPG_VISIBLE >= 400 +double drand48(void); +double erand48(unsigned short[3]); +long jrand48(unsigned short[3]); +void lcong48(unsigned short[7]); +void lcong48_deterministic(unsigned short[7]); +long lrand48(void); +long mrand48(void); +long nrand48(unsigned short[3]); +unsigned short *seed48(unsigned short[3]); +unsigned short *seed48_deterministic(unsigned short[3]); +void srand48(long); +void srand48_deterministic(long); + +int putenv(char *); +#endif + +/* + * XSI functions marked LEGACY in IEEE Std 1003.1-2001 (POSIX) and + * removed in IEEE Std 1003.1-2008 + */ +#if __BSD_VISIBLE || __XPG_VISIBLE < 700 +char *ecvt(double, int, int *, int *); +char *fcvt(double, int, int *, int *); +char *gcvt(double, int, char *); +#if __BSD_VISIBLE || __XPG_VISIBLE >= 420 +char *mktemp(char *); +#endif +#endif /* __BSD_VISIBLE || __XPG_VISIBLE < 700 */ + +#if __BSD_VISIBLE || __XPG_VISIBLE >= 420 +long a64l(const char *); +char *l64a(long); + +char *initstate(unsigned int, char *, size_t) + __attribute__((__bounded__ (__string__,2,3))); +long random(void); +char *setstate(char *); +void srandom(unsigned int); +void srandom_deterministic(unsigned int); + +char *realpath(const char *, char *) + __attribute__((__bounded__ (__minbytes__,2,1024))); + +/* + * XSI functions marked LEGACY in XPG5 and removed in IEEE Std 1003.1-2001 + */ +#if __BSD_VISIBLE || __XPG_VISIBLE < 600 +int ttyslot(void); +void *valloc(size_t); /* obsoleted by malloc() */ +#endif +#endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ + +/* + * 4.4BSD, then XSI in XPG4.2, then added to POSIX base in IEEE Std 1003.1-2008 + */ +#if __BSD_VISIBLE || __XPG_VISIBLE >= 420 || __POSIX_VISIBLE >= 200809 +int mkstemp(char *); +#endif + +/* + * ISO C99 + */ +#if __ISO_C_VISIBLE >= 1999 +long long + atoll(const char *); +long long + llabs(long long); +lldiv_t + lldiv(long long, long long); +long long + strtoll(const char *__restrict, char **__restrict, int); +unsigned long long + strtoull(const char *__restrict, char **__restrict, int); +#endif + +#if __ISO_C_VISIBLE >= 2011 +void * + aligned_alloc(size_t, size_t); +#endif + +/* + * The Open Group Base Specifications, Issue 6; IEEE Std 1003.1-2001 (POSIX) + */ +#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 +int posix_memalign(void **, size_t, size_t); +int setenv(const char *, const char *, int); +int unsetenv(const char *); +#endif +#if __XPG_VISIBLE >= 420 || __POSIX_VISIBLE >= 200112 +char *ptsname(int); +int grantpt(int); +int unlockpt(int); +#endif +#if __POSIX_VISIBLE >= 200112 +int posix_openpt(int); +#endif + +/* + * The Open Group Base Specifications, Issue 7; IEEE Std 1003.1-2008 (POSIX) + */ +#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200809 +char *mkdtemp(char *); +#endif + +#if __XPG_VISIBLE >= 420 || __POSIX_VISIBLE >= 200809 +int getsubopt(char **, char * const *, char **); +#endif + +/* + * The Open Group Base Specifications, Issue 8 + */ +#if __POSIX_VISIBLE >= 202405 || __BSD_VISIBLE +int mkostemp(char *, int); +void *reallocarray(void *, size_t, size_t); +#endif + +#if __BSD_VISIBLE +#define alloca(n) __builtin_alloca(n) + +char *getbsize(int *, long *); +char *cgetcap(char *, const char *, int); +int cgetclose(void); +int cgetent(char **, char **, const char *); +int cgetfirst(char **, char **); +int cgetmatch(char *, const char *); +int cgetnext(char **, char **); +int cgetnum(char *, const char *, long *); +int cgetset(const char *); +int cgetusedb(int); +int cgetstr(char *, const char *, char **); +int cgetustr(char *, const char *, char **); + +int daemon(int, int); +char *devname(dev_t, mode_t); +int getloadavg(double [], int); + +const char * + getprogname(void); +void setprogname(const char *); + +extern char *suboptarg; /* getsubopt(3) external variable */ + +char * mkdtemps(char *, int); +int mkstemps(char *, int); +int mkostemps(char *, int, int); + +int heapsort(void *, size_t, size_t, int (*)(const void *, const void *)); +int mergesort(void *, size_t, size_t, int (*)(const void *, const void *)); +int radixsort(const unsigned char **, int, const unsigned char *, + unsigned); +int sradixsort(const unsigned char **, int, const unsigned char *, + unsigned); + +void srandomdev(void); +long long + strtonum(const char *, long long, long long, const char **); + +void setproctitle(const char *, ...) + __attribute__((__format__ (__printf__, 1, 2))); + +quad_t qabs(quad_t); +qdiv_t qdiv(quad_t, quad_t); +quad_t strtoq(const char *__restrict, char **__restrict, int); +u_quad_t strtouq(const char *__restrict, char **__restrict, int); + +uint32_t arc4random(void); +uint32_t arc4random_uniform(uint32_t); +void arc4random_buf(void *, size_t) + __attribute__((__bounded__ (__buffer__,1,2))); + +#endif /* __BSD_VISIBLE */ + +__END_DECLS + +#endif /* _STDLIB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/string.h b/lib/libc/include/generic-openbsd/string.h new file mode 100644 index 000000000000..a7a01caac0fa --- /dev/null +++ b/lib/libc/include/generic-openbsd/string.h @@ -0,0 +1,141 @@ +/* $OpenBSD: string.h,v 1.34 2024/08/03 20:13:23 guenther Exp $ */ +/* $NetBSD: string.h,v 1.6 1994/10/26 00:56:30 cgd Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)string.h 5.10 (Berkeley) 3/9/91 + */ + +#ifndef _STRING_H_ +#define _STRING_H_ + +#include +#include +#include + +/* + * POSIX mandates that certain string functions not present in ISO C + * be prototyped in strings.h. Historically, we've included them here. + */ +#if __BSD_VISIBLE +#include +#endif + +#ifndef _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED_ +typedef __size_t size_t; +#endif + +#if __POSIX_VISIBLE >= 200809 +#ifndef _LOCALE_T_DEFINED_ +#define _LOCALE_T_DEFINED_ +typedef void *locale_t; +#endif +#endif + +__BEGIN_DECLS +void *memchr(const void *, int, size_t); +int memcmp(const void *, const void *, size_t); +void *memcpy(void *__restrict, const void *__restrict, size_t) + __attribute__ ((__bounded__(__buffer__,1,3))) + __attribute__ ((__bounded__(__buffer__,2,3))); +void *memmove(void *, const void *, size_t) + __attribute__ ((__bounded__(__buffer__,1,3))) + __attribute__ ((__bounded__(__buffer__,2,3))); +void *memset(void *, int, size_t) + __attribute__ ((__bounded__(__buffer__,1,3))); +char *strcat(char *__restrict, const char *__restrict); +char *strchr(const char *, int); +int strcmp(const char *, const char *); +int strcoll(const char *, const char *); +char *strcpy(char *__restrict, const char *__restrict); +size_t strcspn(const char *, const char *); +char *strerror(int); +size_t strlen(const char *); +char *strncat(char *__restrict, const char *__restrict, size_t) + __attribute__ ((__bounded__(__string__,1,3))); +int strncmp(const char *, const char *, size_t); +char *strncpy(char *__restrict, const char *__restrict, size_t) + __attribute__ ((__bounded__(__string__,1,3))); +char *strpbrk(const char *, const char *); +char *strrchr(const char *, int); +size_t strspn(const char *, const char *); +char *strstr(const char *, const char *); +char *strtok(char *__restrict, const char *__restrict); +char *strtok_r(char *__restrict, const char *__restrict, char **__restrict); +size_t strxfrm(char *__restrict, const char *__restrict, size_t) + __attribute__ ((__bounded__(__string__,1,3))); + +#if __XPG_VISIBLE +void *memccpy(void *__restrict, const void *__restrict, int, size_t) + __attribute__ ((__bounded__(__buffer__,1,4))); +#endif + +#if __POSIX_VISIBLE >= 200112 +int strerror_r(int, char *, size_t) + __attribute__ ((__bounded__(__string__,2,3))); +#endif + +#if __XPG_VISIBLE >= 420 || __POSIX_VISIBLE >= 200809 +char *strdup(const char *); +#endif + +#if __POSIX_VISIBLE >= 200809 +char *stpcpy(char *__restrict, const char *__restrict); +char *stpncpy(char *__restrict, const char *__restrict, size_t); +int strcoll_l(const char *, const char *, locale_t); +char *strerror_l(int, locale_t); +char *strndup(const char *, size_t); +size_t strnlen(const char *, size_t); +char *strsignal(int); +size_t strxfrm_l(char *__restrict, const char *__restrict, size_t, locale_t) + __attribute__ ((__bounded__(__string__,1,3))); +#endif + +#if __POSIX_VISIBLE >= 202405 || __BSD_VISIBLE +void *memmem(const void *, size_t, const void *, size_t); +size_t strlcat(char *__restrict, const char *__restrict, size_t) + __attribute__ ((__bounded__(__string__,1,3))); +size_t strlcpy(char *__restrict, const char *__restrict, size_t) + __attribute__ ((__bounded__(__string__,1,3))); +#endif + +#if __BSD_VISIBLE +void explicit_bzero(void *, size_t) + __attribute__ ((__bounded__(__buffer__,1,2))); +void *memrchr(const void *, int, size_t); +char *strcasestr(const char *, const char *); +void strmode(__mode_t, char *); +char *strsep(char **, const char *); +int timingsafe_bcmp(const void *, const void *, size_t); +int timingsafe_memcmp(const void *, const void *, size_t); +#endif +__END_DECLS + +#endif /* _STRING_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/strings.h b/lib/libc/include/generic-openbsd/strings.h new file mode 100644 index 000000000000..5656d5938368 --- /dev/null +++ b/lib/libc/include/generic-openbsd/strings.h @@ -0,0 +1,83 @@ +/* $OpenBSD: strings.h,v 1.6 2017/09/10 21:50:36 schwarze Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)strings.h 5.8 (Berkeley) 5/15/90 + */ + +#ifndef _STRINGS_H_ +#define _STRINGS_H_ + +#include +#include + +/* + * POSIX mandates that certain string functions not present in ISO C + * be prototyped in strings.h. + */ + +#ifndef _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED_ +typedef __size_t size_t; +#endif + +#if __POSIX_VISIBLE >= 200809 +#ifndef _LOCALE_T_DEFINED_ +#define _LOCALE_T_DEFINED_ +typedef void *locale_t; +#endif +#endif + +__BEGIN_DECLS +#if __BSD_VISIBLE || (__XPG_VISIBLE >= 420 && __POSIX_VISIBLE <= 200112) +/* + * The following functions were removed from IEEE Std 1003.1-2008 + */ +int bcmp(const void *, const void *, size_t); +void bcopy(const void *, void *, size_t) + __attribute__ ((__bounded__(__buffer__,1,3))) + __attribute__ ((__bounded__(__buffer__,2,3))); +void bzero(void *, size_t) + __attribute__ ((__bounded__(__buffer__,1,2))); +char *index(const char *, int); +char *rindex(const char *, int); +#endif + +#if __XPG_VISIBLE >= 420 +int ffs(int); +int strcasecmp(const char *, const char *); +int strncasecmp(const char *, const char *, size_t); +#endif +#if __POSIX_VISIBLE >= 200809 +int strcasecmp_l(const char *, const char *, locale_t); +int strncasecmp_l(const char *, const char *, size_t, locale_t); +#endif +__END_DECLS + +#endif /* _STRINGS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/_endian.h b/lib/libc/include/generic-openbsd/sys/_endian.h new file mode 100644 index 000000000000..570cc6f5644c --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/_endian.h @@ -0,0 +1,179 @@ +/* $OpenBSD: _endian.h,v 1.8 2018/01/11 23:13:37 dlg Exp $ */ + +/*- + * Copyright (c) 1997 Niklas Hallqvist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Internal endianness macros. This pulls in to + * get the correct setting direction for the platform and sets internal + * ('__' prefix) macros appropriately. + */ + +#ifndef _SYS__ENDIAN_H_ +#define _SYS__ENDIAN_H_ + +#include + +#define __FROM_SYS__ENDIAN +#include +#undef __FROM_SYS__ENDIAN + +#define _LITTLE_ENDIAN 1234 +#define _BIG_ENDIAN 4321 +#define _PDP_ENDIAN 3412 + +/* Note that these macros evaluate their arguments several times. */ + +#define __swap16gen(x) \ + (__uint16_t)(((__uint16_t)(x) & 0xffU) << 8 | ((__uint16_t)(x) & 0xff00U) >> 8) + +#define __swap32gen(x) \ + (__uint32_t)(((__uint32_t)(x) & 0xff) << 24 | \ + ((__uint32_t)(x) & 0xff00) << 8 | ((__uint32_t)(x) & 0xff0000) >> 8 |\ + ((__uint32_t)(x) & 0xff000000) >> 24) + +#define __swap64gen(x) \ + (__uint64_t)((((__uint64_t)(x) & 0xff) << 56) | \ + ((__uint64_t)(x) & 0xff00ULL) << 40 | \ + ((__uint64_t)(x) & 0xff0000ULL) << 24 | \ + ((__uint64_t)(x) & 0xff000000ULL) << 8 | \ + ((__uint64_t)(x) & 0xff00000000ULL) >> 8 | \ + ((__uint64_t)(x) & 0xff0000000000ULL) >> 24 | \ + ((__uint64_t)(x) & 0xff000000000000ULL) >> 40 | \ + ((__uint64_t)(x) & 0xff00000000000000ULL) >> 56) + +#ifndef __HAVE_MD_SWAP +static __inline __uint16_t +__swap16md(__uint16_t x) +{ + return (__swap16gen(x)); +} + +static __inline __uint32_t +__swap32md(__uint32_t x) +{ + return (__swap32gen(x)); +} + +static __inline __uint64_t +__swap64md(__uint64_t x) +{ + return (__swap64gen(x)); +} +#endif + +#define __swap16(x) \ + (__uint16_t)(__builtin_constant_p(x) ? __swap16gen(x) : __swap16md(x)) +#define __swap32(x) \ + (__uint32_t)(__builtin_constant_p(x) ? __swap32gen(x) : __swap32md(x)) +#define __swap64(x) \ + (__uint64_t)(__builtin_constant_p(x) ? __swap64gen(x) : __swap64md(x)) + +#if _BYTE_ORDER == _LITTLE_ENDIAN + +#define _QUAD_HIGHWORD 1 +#define _QUAD_LOWWORD 0 + +#define __htobe16 __swap16 +#define __htobe32 __swap32 +#define __htobe64 __swap64 +#define __htole16(x) ((__uint16_t)(x)) +#define __htole32(x) ((__uint32_t)(x)) +#define __htole64(x) ((__uint64_t)(x)) + +#ifdef _KERNEL +#ifdef __HAVE_MD_SWAPIO + +#define __bemtoh16(_x) __mswap16(_x) +#define __bemtoh32(_x) __mswap32(_x) +#define __bemtoh64(_x) __mswap64(_x) + +#define __htobem16(_x, _v) __swapm16((_x), (_v)) +#define __htobem32(_x, _v) __swapm32((_x), (_v)) +#define __htobem64(_x, _v) __swapm64((_x), (_v)) + +#endif /* __HAVE_MD_SWAPIO */ +#endif /* _KERNEL */ +#endif /* _BYTE_ORDER == _LITTLE_ENDIAN */ + +#if _BYTE_ORDER == _BIG_ENDIAN + +#define _QUAD_HIGHWORD 0 +#define _QUAD_LOWWORD 1 + +#define __htobe16(x) ((__uint16_t)(x)) +#define __htobe32(x) ((__uint32_t)(x)) +#define __htobe64(x) ((__uint64_t)(x)) +#define __htole16 __swap16 +#define __htole32 __swap32 +#define __htole64 __swap64 + +#ifdef _KERNEL +#ifdef __HAVE_MD_SWAPIO + +#define __lemtoh16(_x) __mswap16(_x) +#define __lemtoh32(_x) __mswap32(_x) +#define __lemtoh64(_x) __mswap64(_x) + +#define __htolem16(_x, _v) __swapm16((_x), (_v)) +#define __htolem32(_x, _v) __swapm32((_x), (_v)) +#define __htolem64(_x, _v) __swapm64((_x), (_v)) + +#endif /* __HAVE_MD_SWAPIO */ +#endif /* _KERNEL */ +#endif /* _BYTE_ORDER == _BIG_ENDIAN */ + + +#ifdef _KERNEL +/* + * Fill in the __hto[bl]em{16,32,64} and __[bl]emtoh{16,32,64} macros + * that haven't been defined yet + */ + +#ifndef __bemtoh16 +#define __bemtoh16(_x) __htobe16(*(__uint16_t *)(_x)) +#define __bemtoh32(_x) __htobe32(*(__uint32_t *)(_x)) +#define __bemtoh64(_x) __htobe64(*(__uint64_t *)(_x)) +#endif + +#ifndef __htobem16 +#define __htobem16(_x, _v) (*(__uint16_t *)(_x) = __htobe16(_v)) +#define __htobem32(_x, _v) (*(__uint32_t *)(_x) = __htobe32(_v)) +#define __htobem64(_x, _v) (*(__uint64_t *)(_x) = __htobe64(_v)) +#endif + +#ifndef __lemtoh16 +#define __lemtoh16(_x) __htole16(*(__uint16_t *)(_x)) +#define __lemtoh32(_x) __htole32(*(__uint32_t *)(_x)) +#define __lemtoh64(_x) __htole64(*(__uint64_t *)(_x)) +#endif + +#ifndef __htolem16 +#define __htolem16(_x, _v) (*(__uint16_t *)(_x) = __htole16(_v)) +#define __htolem32(_x, _v) (*(__uint32_t *)(_x) = __htole32(_v)) +#define __htolem64(_x, _v) (*(__uint64_t *)(_x) = __htole64(_v)) +#endif +#endif /* _KERNEL */ + +#endif /* _SYS__ENDIAN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/_lock.h b/lib/libc/include/generic-openbsd/sys/_lock.h new file mode 100644 index 000000000000..97c140b27232 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/_lock.h @@ -0,0 +1,71 @@ +/* $OpenBSD: _lock.h,v 1.7 2025/04/14 12:53:54 visa Exp $ */ + +/*- + * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Berkeley Software Design Inc's name may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``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 BERKELEY SOFTWARE DESIGN INC BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: head/sys/sys/_lock.h 179025 2008-05-15 20:10:06Z attilio $ + */ + +#ifndef _SYS__LOCK_H_ +#define _SYS__LOCK_H_ + +#define LO_CLASSFLAGS 0x0000ffff /* Class specific flags. */ +#define LO_INITIALIZED 0x00010000 /* Lock has been initialized. */ +#define LO_WITNESS 0x00020000 /* Should witness monitor this lock. */ +#define LO_RECURSABLE 0x00080000 /* Lock may recurse. */ +#define LO_SLEEPABLE 0x00100000 /* Lock may be held while sleeping. */ +#define LO_UPGRADABLE 0x00200000 /* Lock may be upgraded/downgraded. */ +#define LO_DUPOK 0x00400000 /* Don't check for duplicate acquires */ +#define LO_IS_VNODE 0x00800000 /* Tell WITNESS about a VNODE lock */ +#define LO_CLASSMASK 0x0f000000 /* Class index bitmask. */ +#define LO_HASPARENT 0x40000000 /* If set, non-NULL lo_relative + * points to parent lock. + * If clear, non-NULL lo_relative + * points to child lock. */ + +#define LO_CLASSSHIFT 24 + +enum lock_class_index { + LO_CLASS_KERNEL_LOCK, + LO_CLASS_MUTEX, + LO_CLASS_RWLOCK, + LO_CLASS_RRWLOCK +}; + +struct lock_object { + const struct lock_type *lo_type; + const char *lo_name; /* Individual lock name. */ + struct witness *lo_witness; /* Data for witness. */ + struct lock_object *lo_relative; /* Parent or child lock. */ + unsigned int lo_flags; +}; + +struct lock_type { + const char *lt_name; +}; + +#endif /* !_SYS__LOCK_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/_null.h b/lib/libc/include/generic-openbsd/sys/_null.h new file mode 100644 index 000000000000..f25deb1ba410 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/_null.h @@ -0,0 +1,18 @@ +/* $OpenBSD: _null.h,v 1.2 2016/09/09 22:07:58 millert Exp $ */ + +/* + * Written by Todd C. Miller, September 9, 2016 + * Public domain. + */ + +#ifndef NULL +#if !defined(__cplusplus) +#define NULL ((void *)0) +#elif __cplusplus >= 201103L +#define NULL nullptr +#elif defined(__GNUG__) +#define NULL __null +#else +#define NULL 0L +#endif +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/_time.h b/lib/libc/include/generic-openbsd/sys/_time.h new file mode 100644 index 000000000000..ea9a3a8a75a6 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/_time.h @@ -0,0 +1,85 @@ +/* $OpenBSD: _time.h,v 1.10 2022/10/25 16:30:30 millert Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _SYS__TIME_H_ +#define _SYS__TIME_H_ + +/* Frequency of ticks reported by clock(). */ +#define CLOCKS_PER_SEC 100 + +#if __BSD_VISIBLE +/* + * Per-process and per-thread clocks encode the PID or TID into the + * high bits, with the type in the bottom bits + */ +#define __CLOCK_ENCODE(type,id) ((type) | ((id) << 12)) +#define __CLOCK_TYPE(c) ((c) & 0xfff) +#define __CLOCK_PTID(c) (((c) >> 12) & 0xfffff) +#endif + +#if __POSIX_VISIBLE >= 199309 || __ISO_C_VISIBLE >= 2011 +#ifndef _TIME_T_DEFINED_ +#define _TIME_T_DEFINED_ +typedef __time_t time_t; +#endif + +#ifndef _TIMESPEC_DECLARED +#define _TIMESPEC_DECLARED +struct timespec { + time_t tv_sec; /* seconds */ + long tv_nsec; /* and nanoseconds */ +}; +#endif +#endif + +#if __POSIX_VISIBLE >= 199309 +#define CLOCK_REALTIME 0 +#define CLOCK_PROCESS_CPUTIME_ID 2 +#define CLOCK_MONOTONIC 3 +#define CLOCK_THREAD_CPUTIME_ID 4 +#define CLOCK_UPTIME 5 +#define CLOCK_BOOTTIME 6 + +/* + * Structure defined by POSIX 1003.1b to be like a itimerval, + * but with timespecs. Used in the timer_*() system calls. + */ +struct itimerspec { + struct timespec it_interval; /* timer interval */ + struct timespec it_value; /* timer expiration */ +}; + +#define TIMER_RELTIME 0x0 /* relative timer */ +#define TIMER_ABSTIME 0x1 /* absolute timer */ + +#endif + +#endif /* !_SYS__TIME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/_types.h b/lib/libc/include/generic-openbsd/sys/_types.h new file mode 100644 index 000000000000..2bcce5a08e35 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/_types.h @@ -0,0 +1,77 @@ +/* $OpenBSD: _types.h,v 1.10 2022/08/06 13:31:13 semarie Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.3 (Berkeley) 1/5/94 + */ + +#ifndef _SYS__TYPES_H_ +#define _SYS__TYPES_H_ + +#include + +typedef __int64_t __blkcnt_t; /* blocks allocated for file */ +typedef __int32_t __blksize_t; /* optimal blocksize for I/O */ +typedef __int64_t __clock_t; /* ticks in CLOCKS_PER_SEC */ +typedef __int32_t __clockid_t; /* CLOCK_* identifiers */ +typedef unsigned long __cpuid_t; /* CPU id */ +typedef __int32_t __dev_t; /* device number */ +typedef __uint32_t __fixpt_t; /* fixed point number */ +typedef __uint64_t __fsblkcnt_t; /* file system block count */ +typedef __uint64_t __fsfilcnt_t; /* file system file count */ +typedef __uint32_t __gid_t; /* group id */ +typedef __uint32_t __id_t; /* may contain pid, uid or gid */ +typedef __uint32_t __in_addr_t; /* base type for internet address */ +typedef __uint16_t __in_port_t; /* IP port type */ +typedef __uint64_t __ino_t; /* inode number */ +typedef long __key_t; /* IPC key (for Sys V IPC) */ +typedef __uint32_t __mode_t; /* permissions */ +typedef __uint32_t __nlink_t; /* link count */ +typedef __int64_t __off_t; /* file offset or size */ +typedef __int32_t __pid_t; /* process id */ +typedef __uint64_t __rlim_t; /* resource limit */ +typedef __uint8_t __sa_family_t; /* sockaddr address family type */ +typedef __int32_t __segsz_t; /* segment size */ +typedef __uint32_t __socklen_t; /* length type for network syscalls */ +typedef long __suseconds_t; /* microseconds (signed) */ +typedef __int64_t __time_t; /* epoch time */ +typedef __int32_t __timer_t; /* POSIX timer identifiers */ +typedef __uint32_t __uid_t; /* user id */ +typedef __uint32_t __useconds_t; /* microseconds */ + +/* + * mbstate_t is an opaque object to keep conversion state, during multibyte + * stream conversions. The content must not be referenced by user programs. + */ +typedef union { + char __mbstate8[128]; + __int64_t __mbstateL; /* for alignment */ +} __mbstate_t; + +#endif /* !_SYS__TYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/acct.h b/lib/libc/include/generic-openbsd/sys/acct.h new file mode 100644 index 000000000000..c858ab8e5c3e --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/acct.h @@ -0,0 +1,83 @@ +/* $OpenBSD: acct.h,v 1.16 2024/02/25 00:07:13 deraadt Exp $ */ +/* $NetBSD: acct.h,v 1.16 1995/03/26 20:23:52 jtc Exp $ */ + +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)acct.h 8.3 (Berkeley) 7/10/94 + */ + +#include + +/* + * Accounting structures; these use a comp_t type which is a 3 bits base 8 + * exponent, 13 bit fraction ``floating point'' number. Units are 1/AHZ + * seconds. + */ +typedef u_int16_t comp_t; + +struct acct { + char ac_comm[_MAXCOMLEN]; /* command name, incl NUL */ + comp_t ac_utime; /* user time */ + comp_t ac_stime; /* system time */ + comp_t ac_etime; /* elapsed time */ + comp_t ac_io; /* count of IO blocks */ + time_t ac_btime; /* starting time */ + uid_t ac_uid; /* user id */ + gid_t ac_gid; /* group id */ + u_int32_t ac_mem; /* average memory usage */ + dev_t ac_tty; /* controlling tty, or -1 */ + pid_t ac_pid; /* process id */ + + u_int32_t ac_flag; /* accounting flags */ +#define AFORK 0x00000001 /* fork'd but not exec'd */ +#define AMAP 0x00000004 /* killed by syscall or stack mapping violation */ +#define ACORE 0x00000008 /* dumped core */ +#define AXSIG 0x00000010 /* killed by a signal */ +#define APLEDGE 0x00000020 /* killed due to pledge violation */ +#define ATRAP 0x00000040 /* memory access violation */ +#define AUNVEIL 0x00000080 /* unveil access violation */ +#define APINSYS 0x00000200 /* killed by syscall pin violation */ +#define ABTCFI 0x00000400 /* BT CFI violation */ +}; + +/* + * 1/AHZ is the granularity of the data encoded in the comp_t fields. + * This is not necessarily equal to hz. + */ +#define AHZ 64 + +#ifdef _KERNEL +int acct_process(struct proc *p); +void acct_shutdown(void); +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/ataio.h b/lib/libc/include/generic-openbsd/sys/ataio.h new file mode 100644 index 000000000000..4dd1e389fb3d --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/ataio.h @@ -0,0 +1,48 @@ +/* $OpenBSD: ataio.h,v 1.5 2003/09/26 21:43:32 miod Exp $ */ +/* $NetBSD: ataio.h,v 1.2 1998/11/23 22:58:23 kenh Exp $ */ + +#ifndef _SYS_ATAIO_H_ +#define _SYS_ATAIO_H_ + +#include +#include + +typedef struct atareq { + u_long flags; /* info about the request status and type */ + u_char command; /* command code */ + u_char features; /* feature modifier bits for command */ + u_char sec_count; /* sector count */ + u_char sec_num; /* sector number */ + u_char head; /* head number */ + u_short cylinder; /* cylinder/lba address */ + + caddr_t databuf; /* pointer to I/O data buffer */ + u_long datalen; /* length of data buffer */ + int timeout; /* command timeout */ + u_char retsts; /* return status for the command */ + u_char error; /* error bits */ +} atareq_t; + +/* bit definitions for flags */ +#define ATACMD_READ 0x00000001 +#define ATACMD_WRITE 0x00000002 +#define ATACMD_READREG 0x00000004 + +/* definitions for the return status (retsts) */ +#define ATACMD_OK 0x00 +#define ATACMD_TIMEOUT 0x01 +#define ATACMD_ERROR 0x02 +#define ATACMD_DF 0x03 + +#define ATAIOCCOMMAND _IOWR('Q', 8, atareq_t) + +typedef struct atagettrace { + unsigned int buf_size; /* length of data buffer */ + void *buf; /* pointer to data buffer */ + unsigned int bytes_copied; /* number of bytes copied to buffer */ + unsigned int bytes_left; /* number of bytes left */ +} atagettrace_t; + +#define ATAIOGETTRACE _IOWR('Q', 27, struct atagettrace) + +#endif /* _SYS_ATAIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/atomic.h b/lib/libc/include/generic-openbsd/sys/atomic.h new file mode 100644 index 000000000000..68baa4661f05 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/atomic.h @@ -0,0 +1,293 @@ +/* $OpenBSD: atomic.h,v 1.10 2025/01/03 21:27:41 bluhm Exp $ */ +/* + * Copyright (c) 2014 David Gwynne + * Copyright (c) 2022 Alexander Bluhm + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_ATOMIC_H_ +#define _SYS_ATOMIC_H_ + +#include + +/* + * an arch wanting to provide its own implementations does so by defining + * macros. + */ + +/* + * atomic_cas_* + */ + +#ifndef atomic_cas_uint +static inline unsigned int +atomic_cas_uint(volatile unsigned int *p, unsigned int o, unsigned int n) +{ + return __sync_val_compare_and_swap(p, o, n); +} +#endif + +#ifndef atomic_cas_ulong +static inline unsigned long +atomic_cas_ulong(volatile unsigned long *p, unsigned long o, unsigned long n) +{ + return __sync_val_compare_and_swap(p, o, n); +} +#endif + +#ifndef atomic_cas_ptr +static inline void * +atomic_cas_ptr(volatile void *pp, void *o, void *n) +{ + void * volatile *p = (void * volatile *)pp; + return __sync_val_compare_and_swap(p, o, n); +} +#endif + +/* + * atomic_swap_* + */ + +#ifndef atomic_swap_uint +static inline unsigned int +atomic_swap_uint(volatile unsigned int *p, unsigned int v) +{ + return __sync_lock_test_and_set(p, v); +} +#endif + +#ifndef atomic_swap_ulong +static inline unsigned long +atomic_swap_ulong(volatile unsigned long *p, unsigned long v) +{ + return __sync_lock_test_and_set(p, v); +} +#endif + +#ifndef atomic_swap_ptr +static inline void * +atomic_swap_ptr(volatile void *pp, void *v) +{ + void * volatile *p = (void * volatile *)pp; + return __sync_lock_test_and_set(p, v); +} +#endif + +/* + * atomic_add_*_nv - add and fetch + */ + +#ifndef atomic_add_int_nv +static inline unsigned int +atomic_add_int_nv(volatile unsigned int *p, unsigned int v) +{ + return __sync_add_and_fetch(p, v); +} +#endif + +#ifndef atomic_add_long_nv +static inline unsigned long +atomic_add_long_nv(volatile unsigned long *p, unsigned long v) +{ + return __sync_add_and_fetch(p, v); +} +#endif + +/* + * atomic_add - add + */ + +#ifndef atomic_add_int +#define atomic_add_int(_p, _v) ((void)atomic_add_int_nv((_p), (_v))) +#endif + +#ifndef atomic_add_long +#define atomic_add_long(_p, _v) ((void)atomic_add_long_nv((_p), (_v))) +#endif + +/* + * atomic_inc_*_nv - increment and fetch + */ + +#ifndef atomic_inc_int_nv +#define atomic_inc_int_nv(_p) atomic_add_int_nv((_p), 1) +#endif + +#ifndef atomic_inc_long_nv +#define atomic_inc_long_nv(_p) atomic_add_long_nv((_p), 1) +#endif + +/* + * atomic_inc_* - increment + */ + +#ifndef atomic_inc_int +#define atomic_inc_int(_p) ((void)atomic_inc_int_nv(_p)) +#endif + +#ifndef atomic_inc_long +#define atomic_inc_long(_p) ((void)atomic_inc_long_nv(_p)) +#endif + +/* + * atomic_sub_*_nv - sub and fetch + */ + +#ifndef atomic_sub_int_nv +static inline unsigned int +atomic_sub_int_nv(volatile unsigned int *p, unsigned int v) +{ + return __sync_sub_and_fetch(p, v); +} +#endif + +#ifndef atomic_sub_long_nv +static inline unsigned long +atomic_sub_long_nv(volatile unsigned long *p, unsigned long v) +{ + return __sync_sub_and_fetch(p, v); +} +#endif + +/* + * atomic_sub_* - sub + */ + +#ifndef atomic_sub_int +#define atomic_sub_int(_p, _v) ((void)atomic_sub_int_nv((_p), (_v))) +#endif + +#ifndef atomic_sub_long +#define atomic_sub_long(_p, _v) ((void)atomic_sub_long_nv((_p), (_v))) +#endif + +/* + * atomic_dec_*_nv - decrement and fetch + */ + +#ifndef atomic_dec_int_nv +#define atomic_dec_int_nv(_p) atomic_sub_int_nv((_p), 1) +#endif + +#ifndef atomic_dec_long_nv +#define atomic_dec_long_nv(_p) atomic_sub_long_nv((_p), 1) +#endif + +/* + * atomic_dec_* - decrement + */ + +#ifndef atomic_dec_int +#define atomic_dec_int(_p) ((void)atomic_dec_int_nv(_p)) +#endif + +#ifndef atomic_dec_long +#define atomic_dec_long(_p) ((void)atomic_dec_long_nv(_p)) +#endif + +#ifdef _KERNEL +/* + * atomic_load_* - read from memory + */ + +static inline unsigned int +atomic_load_int(volatile const unsigned int *p) +{ + return *p; +} + +static inline unsigned long +atomic_load_long(volatile const unsigned long *p) +{ + return *p; +} + +/* + * atomic_store_* - write to memory + */ + +static inline void +atomic_store_int(volatile unsigned int *p, unsigned int v) +{ + *p = v; +} + +static inline void +atomic_store_long(volatile unsigned long *p, unsigned long v) +{ + *p = v; +} +#endif /* _KERNEL */ + +/* + * memory barriers + */ + +#ifndef membar_enter +#define membar_enter() __sync_synchronize() +#endif + +#ifndef membar_exit +#define membar_exit() __sync_synchronize() +#endif + +#ifndef membar_producer +#define membar_producer() __sync_synchronize() +#endif + +#ifndef membar_consumer +#define membar_consumer() __sync_synchronize() +#endif + +#ifndef membar_sync +#define membar_sync() __sync_synchronize() +#endif + +#ifndef membar_enter_after_atomic +#define membar_enter_after_atomic() membar_enter() +#endif + +#ifndef membar_exit_before_atomic +#define membar_exit_before_atomic() membar_exit() +#endif + +#ifdef _KERNEL + +/* + * Force any preceding reads to happen before any subsequent reads that + * depend on the value returned by the preceding reads. + */ +static inline void +membar_datadep_consumer(void) +{ +#ifdef __alpha__ + membar_consumer(); +#endif +} + +#define READ_ONCE(x) ({ \ + typeof(x) __tmp = *(volatile typeof(x) *)&(x); \ + membar_datadep_consumer(); \ + __tmp; \ +}) + +#define WRITE_ONCE(x, val) ({ \ + typeof(x) __tmp = (val); \ + *(volatile typeof(x) *)&(x) = __tmp; \ + __tmp; \ +}) + +#endif /* _KERNEL */ + +#endif /* _SYS_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/audioio.h b/lib/libc/include/generic-openbsd/sys/audioio.h new file mode 100644 index 000000000000..b60da96834e2 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/audioio.h @@ -0,0 +1,231 @@ +/* $OpenBSD: audioio.h,v 1.27 2016/09/14 06:12:20 ratchov Exp $ */ +/* $NetBSD: audioio.h,v 1.24 1998/08/13 06:28:41 mrg Exp $ */ + +/* + * Copyright (c) 1991-1993 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Computer Systems + * Engineering Group at Lawrence Berkeley Laboratory. + * 4. Neither the name of the University nor of the Laboratory may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _SYS_AUDIOIO_H_ +#define _SYS_AUDIOIO_H_ + +#define AUMODE_PLAY 0x01 +#define AUMODE_RECORD 0x02 + +#define AUDIO_INITPAR(p) \ + (void)memset((void *)(p), 0xff, sizeof(struct audio_swpar)) + +/* + * argument to AUDIO_SETPAR and AUDIO_GETPAR ioctls + */ +struct audio_swpar { + unsigned int sig; /* if 1, encoding is signed */ + unsigned int le; /* if 1, encoding is little-endian */ + unsigned int bits; /* bits per sample */ + unsigned int bps; /* bytes per sample */ + unsigned int msb; /* if 1, bits are msb-aligned */ + unsigned int rate; /* common play & rec sample rate */ + unsigned int pchan; /* play channels */ + unsigned int rchan; /* rec channels */ + unsigned int nblks; /* number of blocks in play buffer */ + unsigned int round; /* common frames per block */ + unsigned int _spare[6]; +}; + +/* + * argument to AUDIO_GETSTATUS + */ +struct audio_status { + int mode; + int pause; + int active; + int _spare[5]; +}; + +/* + * Parameter for the AUDIO_GETDEV ioctl to determine current + * audio devices. + */ +#define MAX_AUDIO_DEV_LEN 16 +typedef struct audio_device { + char name[MAX_AUDIO_DEV_LEN]; + char version[MAX_AUDIO_DEV_LEN]; + char config[MAX_AUDIO_DEV_LEN]; +} audio_device_t; + +struct audio_pos { + unsigned int play_pos; /* total bytes played */ + unsigned int play_xrun; /* bytes of silence inserted */ + unsigned int rec_pos; /* total bytes recorded */ + unsigned int rec_xrun; /* bytes dropped */ +}; + +/* + * Audio device operations + */ +#define AUDIO_GETDEV _IOR('A', 27, struct audio_device) +#define AUDIO_GETPOS _IOR('A', 35, struct audio_pos) +#define AUDIO_GETPAR _IOR('A', 36, struct audio_swpar) +#define AUDIO_SETPAR _IOWR('A', 37, struct audio_swpar) +#define AUDIO_START _IO('A', 38) +#define AUDIO_STOP _IO('A', 39) +#define AUDIO_GETSTATUS _IOR('A', 40, struct audio_status) + +/* + * Mixer device + */ +#define AUDIO_MIN_GAIN 0 +#define AUDIO_MAX_GAIN 255 + +typedef struct mixer_level { + int num_channels; + u_char level[8]; /* [num_channels] */ +} mixer_level_t; +#define AUDIO_MIXER_LEVEL_MONO 0 +#define AUDIO_MIXER_LEVEL_LEFT 0 +#define AUDIO_MIXER_LEVEL_RIGHT 1 + +/* + * Device operations + */ + +typedef struct audio_mixer_name { + char name[MAX_AUDIO_DEV_LEN]; + int msg_id; +} audio_mixer_name_t; + +typedef struct mixer_devinfo { + int index; + audio_mixer_name_t label; + int type; +#define AUDIO_MIXER_CLASS 0 +#define AUDIO_MIXER_ENUM 1 +#define AUDIO_MIXER_SET 2 +#define AUDIO_MIXER_VALUE 3 + int mixer_class; + int next, prev; +#define AUDIO_MIXER_LAST -1 + union { + struct audio_mixer_enum { + int num_mem; + struct { + audio_mixer_name_t label; + int ord; + } member[32]; + } e; + struct audio_mixer_set { + int num_mem; + struct { + audio_mixer_name_t label; + int mask; + } member[32]; + } s; + struct audio_mixer_value { + audio_mixer_name_t units; + int num_channels; + int delta; + } v; + } un; +} mixer_devinfo_t; + + +typedef struct mixer_ctrl { + int dev; + int type; + union { + int ord; /* enum */ + int mask; /* set */ + mixer_level_t value; /* value */ + } un; +} mixer_ctrl_t; + +/* + * Mixer operations + */ +#define AUDIO_MIXER_READ _IOWR('M', 0, mixer_ctrl_t) +#define AUDIO_MIXER_WRITE _IOWR('M', 1, mixer_ctrl_t) +#define AUDIO_MIXER_DEVINFO _IOWR('M', 2, mixer_devinfo_t) + +/* + * Well known device names + */ +#define AudioNmicrophone "mic" +#define AudioNline "line" +#define AudioNcd "cd" +#define AudioNdac "dac" +#define AudioNaux "aux" +#define AudioNrecord "record" +#define AudioNvolume "volume" +#define AudioNmonitor "monitor" +#define AudioNtreble "treble" +#define AudioNmid "mid" +#define AudioNbass "bass" +#define AudioNbassboost "bassboost" +#define AudioNspeaker "spkr" +#define AudioNheadphone "hp" +#define AudioNoutput "output" +#define AudioNinput "input" +#define AudioNmaster "master" +#define AudioNstereo "stereo" +#define AudioNmono "mono" +#define AudioNloudness "loudness" +#define AudioNspatial "spatial" +#define AudioNsurround "surround" +#define AudioNpseudo "pseudo" +#define AudioNmute "mute" +#define AudioNenhanced "enhanced" +#define AudioNpreamp "preamp" +#define AudioNon "on" +#define AudioNoff "off" +#define AudioNmode "mode" +#define AudioNsource "source" +#define AudioNfmsynth "fmsynth" +#define AudioNwave "wave" +#define AudioNmidi "midi" +#define AudioNmixerout "mixerout" +#define AudioNswap "swap" /* swap left and right channels */ +#define AudioNagc "agc" +#define AudioNdelay "delay" +#define AudioNselect "select" /* select destination */ +#define AudioNvideo "video" +#define AudioNcenter "center" +#define AudioNdepth "depth" +#define AudioNlfe "lfe" +#define AudioNextamp "extamp" + +#define AudioCinputs "inputs" +#define AudioCoutputs "outputs" +#define AudioCrecord "record" +#define AudioCmonitor "monitor" +#define AudioCequalization "equalization" + +#endif /* !_SYS_AUDIOIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/auxv.h b/lib/libc/include/generic-openbsd/sys/auxv.h new file mode 100644 index 000000000000..0a822654e8c2 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/auxv.h @@ -0,0 +1,50 @@ +/* $OpenBSD: auxv.h,v 1.1 2024/07/14 09:48:49 jca Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2017 Michal Meloun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _SYS_AUXV_H_ +#define _SYS_AUXV_H_ + +#include +#include + +/* Values for a_type. */ +#define AT_NULL 0 /* Terminates the vector. */ +#define AT_IGNORE 1 /* Ignored entry. */ +#define AT_PAGESZ 6 /* Page size in bytes. */ +#define AT_HWCAP 25 /* CPU feature flags. */ +#define AT_HWCAP2 26 /* CPU feature flags 2. */ + +#define AT_COUNT 27 /* Count of defined aux entry types. */ + +__BEGIN_DECLS +int elf_aux_info(int aux, void *buf, int buflen); +__END_DECLS + +#endif /* !_SYS_AUXV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/blist.h b/lib/libc/include/generic-openbsd/sys/blist.h new file mode 100644 index 000000000000..2cb91dee5fd7 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/blist.h @@ -0,0 +1,137 @@ +/* $OpenBSD: blist.h,v 1.2 2022/08/06 13:44:04 semarie Exp $ */ +/* DragonFlyBSD:7b80531f545c7d3c51c1660130c71d01f6bccbe0:/sys/sys/blist.h */ +/* + * Copyright (c) 2003,2004 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Matthew Dillon + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDERS 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. + * + * Implements bitmap resource lists. + * + * Usage: + * blist = blist_create(blocks) + * (void) blist_destroy(blist) + * blkno = blist_alloc(blist, count) + * (void) blist_free(blist, blkno, count) + * nblks = blist_fill(blist, blkno, count) + * (void) blist_resize(&blist, count, freeextra) + * + * + * Notes: + * on creation, the entire list is marked reserved. You should + * first blist_free() the sections you want to make available + * for allocation before doing general blist_alloc()/free() + * ops. + * + * SWAPBLK_NONE is returned on failure. This module is typically + * capable of managing up to (2^31) blocks per blist, though + * the memory utilization would be insane if you actually did + * that. Managing something like 512MB worth of 4K blocks + * eats around 32 KBytes of memory. + * + * $FreeBSD: src/sys/sys/blist.h,v 1.2.2.1 2003/01/12 09:23:12 dillon Exp $ + */ + +#ifndef _SYS_BLIST_H_ +#define _SYS_BLIST_H_ + +#ifndef _SYS_TYPES_H_ +#include +#endif + +typedef u_long swblk_t; +typedef u_int64_t u_swblk_t; + +/* + * note: currently use SWAPBLK_NONE as an absolute value rather then + * a flag bit. + */ +#define SWAPBLK_NONE ((swblk_t)-1) + +/* + * blmeta and bl_bitmap_t MUST be a power of 2 in size. + */ + +typedef struct blmeta { + union { + swblk_t bmu_avail; /* space available under us */ + u_swblk_t bmu_bitmap; /* bitmap if we are a leaf */ + } u; + swblk_t bm_bighint; /* biggest contiguous block hint*/ +} blmeta_t; + +typedef struct blist { + swblk_t bl_blocks; /* area of coverage */ + /* XXX int64_t bl_radix */ + swblk_t bl_radix; /* coverage radix */ + swblk_t bl_skip; /* starting skip */ + swblk_t bl_free; /* number of free blocks */ + blmeta_t *bl_root; /* root of radix tree */ + swblk_t bl_rootblks; /* swblk_t blks allocated for tree */ +} *blist_t; + +#define BLIST_META_RADIX (sizeof(u_swblk_t)*8/2) /* 2 bits per */ +#define BLIST_BMAP_RADIX (sizeof(u_swblk_t)*8) /* 1 bit per */ + +/* + * The radix may exceed the size of a 64 bit signed (or unsigned) int + * when the maximal number of blocks is allocated. With a 32-bit swblk_t + * this corresponds to ~1G x PAGE_SIZE = 4096GB. The swap code usually + * divides this by 4, leaving us with a capability of up to four 1TB swap + * devices. + * + * With a 64-bit swblk_t the limitation is some insane number. + * + * NOTE: For now I don't trust that we overflow-detect properly so we divide + * out to ensure that no overflow occurs. + */ + +#if defined(_LP64) +/* swblk_t 64bits */ +#define BLIST_MAXBLKS (0x4000000000000000LL / \ + (BLIST_BMAP_RADIX / BLIST_META_RADIX)) +#else +#define BLIST_MAXBLKS (0x40000000 / \ + (BLIST_BMAP_RADIX / BLIST_META_RADIX)) +#endif + +#define BLIST_MAX_ALLOC BLIST_BMAP_RADIX + +blist_t blist_create(swblk_t); +void blist_destroy(blist_t); +swblk_t blist_alloc(blist_t, swblk_t); +swblk_t blist_allocat(blist_t, swblk_t, swblk_t); +void blist_free(blist_t, swblk_t, swblk_t); +swblk_t blist_fill(blist_t, swblk_t, swblk_t); +void blist_print(blist_t); +void blist_resize(blist_t *, swblk_t, int); +void blist_gapfind(blist_t, swblk_t *, swblk_t *); + +#endif /* _SYS_BLIST_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/buf.h b/lib/libc/include/generic-openbsd/sys/buf.h new file mode 100644 index 000000000000..864be56101f9 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/buf.h @@ -0,0 +1,303 @@ +/* $OpenBSD: buf.h,v 1.120 2025/08/14 16:13:52 beck Exp $ */ +/* $NetBSD: buf.h,v 1.25 1997/04/09 21:12:17 mycroft Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)buf.h 8.7 (Berkeley) 1/21/94 + */ + +#ifndef _SYS_BUF_H_ +#define _SYS_BUF_H_ +#include +#include +#include +#include + +#define NOLIST ((struct buf *)0x87654321) + +struct buf; +struct vnode; + +LIST_HEAD(bufhead, buf); + +/* + * Buffer queues + */ +#define BUFQ_NSCAN_N 128 +#define BUFQ_FIFO 0 +#define BUFQ_NSCAN 1 +#define BUFQ_DEFAULT BUFQ_NSCAN +#define BUFQ_HOWMANY 2 + +/* + * Write limits for bufq - defines high and low water marks for how + * many kva slots are allowed to be consumed to parallelize writes from + * the buffer cache from any individual bufq. + */ +#define BUFQ_HI 128 +#define BUFQ_LOW 64 + +struct bufq_impl; + +struct bufq { + SLIST_ENTRY(bufq) bufq_entries; + struct mutex bufq_mtx; + void *bufq_data; + u_int bufq_outstanding; + u_int bufq_hi; + u_int bufq_low; + int bufq_waiting; + int bufq_stop; + int bufq_type; + const struct bufq_impl *bufq_impl; +}; + +int bufq_init(struct bufq *, int); +void bufq_destroy(struct bufq *); + +void bufq_queue(struct bufq *, struct buf *); +struct buf *bufq_dequeue(struct bufq *); +int bufq_peek(struct bufq *); +void bufq_drain(struct bufq *); + +void bufq_wait(struct bufq *); +void bufq_done(struct bufq *, struct buf *); +void bufq_quiesce(void); +void bufq_restart(void); + +/* fifo */ +SIMPLEQ_HEAD(bufq_fifo_head, buf); +struct bufq_fifo { + SIMPLEQ_ENTRY(buf) bqf_entries; +}; + +/* nscan */ +SIMPLEQ_HEAD(bufq_nscan_head, buf); +struct bufq_nscan { + SIMPLEQ_ENTRY(buf) bqf_entries; +}; + +/* bufq link in struct buf */ +union bufq_data { + struct bufq_fifo bufq_data_fifo; + struct bufq_nscan bufq_data_nscan; +}; + +/* The buffer header describes an I/O operation in the kernel. */ +struct buf { + RBT_ENTRY(buf) b_rbbufs; /* vnode "hash" tree */ + LIST_ENTRY(buf) b_list; /* All allocated buffers. */ + LIST_ENTRY(buf) b_vnbufs; /* Buffer's associated vnode. */ + TAILQ_ENTRY(buf) b_freelist; /* Free list position if not active. */ + int cache; /* which cache are we in */ + struct proc *b_proc; /* Associated proc; NULL if kernel. */ + volatile long b_flags; /* B_* flags. */ + long b_bufsize; /* Allocated buffer size. */ + long b_bcount; /* Valid bytes in buffer. */ + size_t b_resid; /* Remaining I/O. */ + int b_error; /* Errno value. */ + dev_t b_dev; /* Device associated with buffer. */ + caddr_t b_data; /* associated data */ + void *b_saveaddr; /* Original b_data for physio. */ + + TAILQ_ENTRY(buf) b_valist; /* LRU of va to reuse. */ + + union bufq_data b_bufq; + struct bufq *b_bq; /* What bufq this buf is on */ + + struct uvm_object *b_pobj; + struct uvm_object b_uobj; /* Object containing the pages */ + off_t b_poffs; /* Offset within object */ + + daddr_t b_lblkno; /* Logical block number. */ + daddr_t b_blkno; /* Underlying physical block number. */ + /* Function to call upon completion. + * Will be called at splbio(). */ + void (*b_iodone)(struct buf *); + struct vnode *b_vp; /* Device vnode. */ + int b_dirtyoff; /* Offset in buffer of dirty region. */ + int b_dirtyend; /* Offset of end of dirty region. */ + int b_validoff; /* Offset in buffer of valid region. */ + int b_validend; /* Offset of end of valid region. */ +}; + +TAILQ_HEAD(bufqueue, buf); + +struct bufcache { + int64_t hotbufpages; + int64_t warmbufpages; + int64_t cachepages; + struct bufqueue hotqueue; + struct bufqueue coldqueue; + struct bufqueue warmqueue; +}; + +/* + * These flags are kept in b_flags. + */ +#define B_WRITE 0x00000000 /* Write buffer (pseudo flag). */ +#define B_AGE 0x00000001 /* Move to age queue when I/O done. */ +#define B_NEEDCOMMIT 0x00000002 /* Needs committing to stable storage */ +#define B_ASYNC 0x00000004 /* Start I/O, do not wait. */ +#define B_BAD 0x00000008 /* Bad block revectoring in progress. */ +#define B_BUSY 0x00000010 /* I/O in progress. */ +#define B_CACHE 0x00000020 /* Bread found us in the cache. */ +#define B_CALL 0x00000040 /* Call b_iodone from biodone. */ +#define B_DELWRI 0x00000080 /* Delay I/O until buffer reused. */ +#define B_DONE 0x00000100 /* I/O completed. */ +#define B_EINTR 0x00000200 /* I/O was interrupted */ +#define B_ERROR 0x00000400 /* I/O error occurred. */ +#define B_INVAL 0x00000800 /* Does not contain valid info. */ +#define B_NOCACHE 0x00001000 /* Do not cache block after use. */ +#define B_PHYS 0x00002000 /* I/O to user memory. */ +#define B_RAW 0x00004000 /* Set by physio for raw transfers. */ +#define B_READ 0x00008000 /* Read buffer. */ +#define B_WANTED 0x00010000 /* Process wants this buffer. */ +#define B_WRITEINPROG 0x00020000 /* Write in progress. */ +#define B_XXX 0x00040000 /* Debugging flag. */ +#define B_DEFERRED 0x00080000 /* Skipped over for cleaning */ +#define B_SCANNED 0x00100000 /* Block already pushed during sync */ +#define B_PDAEMON 0x00200000 /* I/O started by pagedaemon */ +#define B_RELEASED 0x00400000 /* free this buffer after its kvm */ +#define B_WARM 0x00800000 /* buffer is or has been on the warm queue */ +#define B_COLD 0x01000000 /* buffer is on the cold queue */ +#define B_BC 0x02000000 /* buffer is managed by the cache */ +#define B_DMA 0x04000000 /* buffer is DMA reachable */ + +#define B_BITS "\20\001AGE\002NEEDCOMMIT\003ASYNC\004BAD\005BUSY" \ + "\006CACHE\007CALL\010DELWRI\011DONE\012EINTR\013ERROR" \ + "\014INVAL\015NOCACHE\016PHYS\017RAW\020READ" \ + "\021WANTED\022WRITEINPROG\023XXX(FORMAT)\024DEFERRED" \ + "\025SCANNED\026DAEMON\027RELEASED\030WARM\031COLD\032BC\033DMA" + +/* + * Zero out the buffer's data area. + */ +#define clrbuf(bp) { \ + bzero((bp)->b_data, (bp)->b_bcount); \ + (bp)->b_resid = 0; \ +} + + +/* Flags to low-level allocation routines. */ +#define B_CLRBUF 0x01 /* Request allocated buffer be cleared. */ +#define B_SYNC 0x02 /* Do all allocations synchronously. */ + +struct cluster_info { + daddr_t ci_lastr; /* last read (read-ahead) */ + daddr_t ci_lastw; /* last write (write cluster) */ + daddr_t ci_cstart; /* start block of cluster */ + daddr_t ci_lasta; /* last allocation */ + int ci_clen; /* length of current cluster */ + int ci_ralen; /* Read-ahead length */ + daddr_t ci_maxra; /* last readahead block */ +}; + +#ifdef _KERNEL +__BEGIN_DECLS +/* Kva slots (of size MAXPHYS) reserved for syncer and cleaner. */ +#define RESERVE_SLOTS 4 +/* Buffer cache pages reserved for syncer and cleaner. */ +#define RESERVE_PAGES (RESERVE_SLOTS * MAXPHYS / PAGE_SIZE) +/* Minimum size of the buffer cache, in pages. */ +#define BCACHE_MIN (RESERVE_PAGES * 2) +#define UNCLEAN_PAGES (bcstats.numbufpages - bcstats.numcleanpages) + +extern struct proc *cleanerproc; +extern long bufpages; /* Max number of pages for buffers' data */ +extern struct pool bufpool; +extern struct bufhead bufhead; + +void bawrite(struct buf *); +void bdwrite(struct buf *); +void biodone(struct buf *); +int biowait(struct buf *); +int bread(struct vnode *, daddr_t, int, struct buf **); +int breadn(struct vnode *, daddr_t, int, daddr_t *, int *, int, + struct buf **); +void brelse(struct buf *); +void bufinit(void); +void buf_dirty(struct buf *); +void buf_undirty(struct buf *); +void buf_adjcnt(struct buf *, long); +int bwrite(struct buf *); +struct buf *getblk(struct vnode *, daddr_t, int, int, uint64_t); +struct buf *geteblk(size_t); +struct buf *incore(struct vnode *, daddr_t); + +/* + * bufcache functions + */ +void bufcache_take(struct buf *); +void bufcache_release(struct buf *); + +int buf_flip_high(struct buf *); +void buf_flip_dma(struct buf *); +struct buf *bufcache_getcleanbuf(int, int); +struct buf *bufcache_getdirtybuf(void); + +/* + * buf_kvm_init initializes the kvm handling for buffers. + * buf_acquire sets the B_BUSY flag and ensures that the buffer is + * mapped in the kvm. + * buf_release clears the B_BUSY flag and allows the buffer to become + * unmapped. + * buf_unmap is for internal use only. Unmaps the buffer from kvm. + */ +void buf_mem_init(vsize_t); +void buf_acquire(struct buf *); +void buf_acquire_nomap(struct buf *); +void buf_map(struct buf *); +void buf_release(struct buf *); +int buf_dealloc_mem(struct buf *); +void buf_fix_mapping(struct buf *, vsize_t); +void buf_alloc_pages(struct buf *, vsize_t); +void buf_free_pages(struct buf *); +int buf_realloc_pages(struct buf *, struct uvm_constraint_range *, int); + +void minphys(struct buf *bp); +int physio(void (*strategy)(struct buf *), dev_t dev, int flags, + void (*minphys)(struct buf *), struct uio *uio); +void brelvp(struct buf *); +void reassignbuf(struct buf *); +void bgetvp(struct vnode *, struct buf *); + +void buf_replacevnode(struct buf *, struct vnode *); +void buf_daemon(void *); +void buf_replacevnode(struct buf *, struct vnode *); +int bread_cluster(struct vnode *, daddr_t, int, struct buf **); + +__END_DECLS +#endif /* _KERNEL */ +#endif /* !_SYS_BUF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/cdefs.h b/lib/libc/include/generic-openbsd/sys/cdefs.h new file mode 100644 index 000000000000..2273af8568df --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/cdefs.h @@ -0,0 +1,434 @@ +/* $OpenBSD: cdefs.h,v 1.45 2025/05/13 15:16:43 millert Exp $ */ +/* $NetBSD: cdefs.h,v 1.16 1996/04/03 20:46:39 christos Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Berkeley Software Design, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)cdefs.h 8.7 (Berkeley) 1/21/94 + */ + +#ifndef _SYS_CDEFS_H_ +#define _SYS_CDEFS_H_ + +#include + +/* + * Macro to test if we're using a specific version of gcc or later. + */ +#ifdef __GNUC__ +#define __GNUC_PREREQ__(ma, mi) \ + ((__GNUC__ > (ma)) || (__GNUC__ == (ma) && __GNUC_MINOR__ >= (mi))) +#else +#define __GNUC_PREREQ__(ma, mi) 0 +#endif + +/* + * The __CONCAT macro is used to concatenate parts of symbol names, e.g. + * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo. + * The __CONCAT macro is a bit tricky -- make sure you don't put spaces + * in between its arguments. Do not use __CONCAT on double-quoted strings, + * such as those from the __STRING macro: to concatenate strings just put + * them next to each other. + */ +#if defined(__STDC__) || defined(__cplusplus) +#define __P(protos) protos /* full-blown ANSI C */ +#define __CONCAT(x,y) x ## y +#define __STRING(x) #x + +#define __const const /* define reserved names to standard */ +#define __signed signed +#define __volatile volatile +#if defined(__cplusplus) || defined(__PCC__) +#define __inline inline /* convert to C++ keyword */ +#else +#if !defined(__GNUC__) +#define __inline /* delete GCC keyword */ +#endif /* !__GNUC__ */ +#endif /* !__cplusplus */ + +#else /* !(__STDC__ || __cplusplus) */ +#define __P(protos) () /* traditional C preprocessor */ +#define __CONCAT(x,y) x/**/y +#define __STRING(x) "x" + +#if !defined(__GNUC__) +#define __const /* delete pseudo-ANSI C keywords */ +#define __inline +#define __signed +#define __volatile +#endif /* !__GNUC__ */ +#endif /* !(__STDC__ || __cplusplus) */ + +/* + * GCC1 and some versions of GCC2 declare dead (non-returning) and + * pure (no side effects) functions using "volatile" and "const"; + * unfortunately, these then cause warnings under "-ansi -pedantic". + * GCC >= 2.5 uses the __attribute__((attrs)) style. All of these + * work for GNU C++ (modulo a slight glitch in the C++ grammar in + * the distribution version of 2.5.5). + * + * GCC defines a pure function as depending only on its arguments and + * global variables. Typical examples are strlen and sqrt. + */ + +#if !__GNUC_PREREQ__(2, 5) && !defined(__PCC__) +#define __attribute__(x) /* delete __attribute__ if non-gcc or gcc1 */ +#endif + +#if __GNUC_PREREQ__(2, 5) +#define __dead __attribute__((__noreturn__)) +#elif defined(__GNUC__) +#define __dead __volatile +#else +#define __dead /* delete */ +#endif + +#if __GNUC_PREREQ__(2, 96) +#define __pure __attribute__((__pure__)) +#elif defined(__GNUC__) +#define __pure __const +#else +#define __pure /* delete */ +#endif + +#if __GNUC_PREREQ__(2, 7) +#define __unused __attribute__((__unused__)) +#else +#define __unused /* delete */ +#endif + +#if __GNUC_PREREQ__(3, 1) +#define __used __attribute__((__used__)) +#else +#define __used __unused /* suppress -Wunused warnings */ +#endif + +#if __GNUC_PREREQ__(3,4) +# define __warn_unused_result __attribute__((__warn_unused_result__)) +#else +# define __warn_unused_result /* delete */ +#endif + +#if __GNUC_PREREQ__(3,3) && !defined(__clang__) +# define __bounded(args) __attribute__ ((__bounded__ args )) +#else +# define __bounded(args) /* delete */ +#endif + +/* + * __returns_twice makes the compiler not assume the function + * only returns once. This affects registerisation of variables: + * even local variables need to be in memory across such a call. + * Example: setjmp() + */ +#if __GNUC_PREREQ__(4, 1) +#define __returns_twice __attribute__((returns_twice)) +#else +#define __returns_twice +#endif + +/* + * __only_inline makes the compiler only use this function definition + * for inlining; references that can't be inlined will be left as + * external references instead of generating a local copy. The + * matching library should include a simple extern definition for + * the function to handle those references. c.f. ctype.h + */ +#ifdef __GNUC__ +# if __GNUC_PREREQ__(4, 2) +#define __only_inline extern __inline __attribute__((__gnu_inline__)) +# else +#define __only_inline extern __inline +# endif +#else +#define __only_inline static __inline +#endif + +/* + * GNU C version 2.96 adds explicit branch prediction so that + * the CPU back-end can hint the processor and also so that + * code blocks can be reordered such that the predicted path + * sees a more linear flow, thus improving cache behavior, etc. + * + * The following two macros provide us with a way to utilize this + * compiler feature. Use __predict_true() if you expect the expression + * to evaluate to true, and __predict_false() if you expect the + * expression to evaluate to false. + * + * A few notes about usage: + * + * * Generally, __predict_false() error condition checks (unless + * you have some _strong_ reason to do otherwise, in which case + * document it), and/or __predict_true() `no-error' condition + * checks, assuming you want to optimize for the no-error case. + * + * * Other than that, if you don't know the likelihood of a test + * succeeding from empirical or other `hard' evidence, don't + * make predictions. + * + * * These are meant to be used in places that are run `a lot'. + * It is wasteful to make predictions in code that is run + * seldomly (e.g. at subsystem initialization time) as the + * basic block reordering that this affects can often generate + * larger code. + */ +#if __GNUC_PREREQ__(2, 96) +#define __predict_true(exp) __builtin_expect(((exp) != 0), 1) +#define __predict_false(exp) __builtin_expect(((exp) != 0), 0) +#else +#define __predict_true(exp) ((exp) != 0) +#define __predict_false(exp) ((exp) != 0) +#endif + +/* Delete pseudo-keywords wherever they are not available or needed. */ +#ifndef __dead +#define __dead +#define __pure +#endif + +/* + * The __packed macro indicates that a variable or structure members + * should have the smallest possible alignment, despite any host CPU + * alignment requirements. + * + * The __aligned(x) macro specifies the minimum alignment of a + * variable or structure. + * + * These macros together are useful for describing the layout and + * alignment of messages exchanged with hardware or other systems. + */ + +#if __GNUC_PREREQ__(2, 7) || defined(__PCC__) +#define __packed __attribute__((__packed__)) +#define __aligned(x) __attribute__((__aligned__(x))) +#endif + +#if !__GNUC_PREREQ__(2, 8) +#define __extension__ +#endif + +#if __GNUC_PREREQ__(3, 0) +#define __malloc __attribute__((__malloc__)) +#else +#define __malloc +#endif + +#if defined(__cplusplus) +#define __BEGIN_EXTERN_C extern "C" { +#define __END_EXTERN_C } +#else +#define __BEGIN_EXTERN_C +#define __END_EXTERN_C +#endif + +#if __GNUC_PREREQ__(4, 0) +#define __dso_public __attribute__((__visibility__("default"))) +#define __dso_hidden __attribute__((__visibility__("hidden"))) +#define __BEGIN_PUBLIC_DECLS \ + _Pragma("GCC visibility push(default)") __BEGIN_EXTERN_C +#define __END_PUBLIC_DECLS __END_EXTERN_C _Pragma("GCC visibility pop") +#define __BEGIN_HIDDEN_DECLS \ + _Pragma("GCC visibility push(hidden)") __BEGIN_EXTERN_C +#define __END_HIDDEN_DECLS __END_EXTERN_C _Pragma("GCC visibility pop") +#else +#define __dso_public +#define __dso_hidden +#define __BEGIN_PUBLIC_DECLS __BEGIN_EXTERN_C +#define __END_PUBLIC_DECLS __END_EXTERN_C +#define __BEGIN_HIDDEN_DECLS __BEGIN_EXTERN_C +#define __END_HIDDEN_DECLS __END_EXTERN_C +#endif + +#define __BEGIN_DECLS __BEGIN_EXTERN_C +#define __END_DECLS __END_EXTERN_C + +/* + * "The nice thing about standards is that there are so many to choose from." + * There are a number of "feature test macros" specified by (different) + * standards that determine which interfaces and types the header files + * should expose. + * + * Because of inconsistencies in these macros, we define our own + * set in the private name space that end in _VISIBLE. These are + * always defined and so headers can test their values easily. + * Things can get tricky when multiple feature macros are defined. + * We try to take the union of all the features requested. + * + * The following macros are guaranteed to have a value after cdefs.h + * has been included: + * __POSIX_VISIBLE + * __XPG_VISIBLE + * __ISO_C_VISIBLE + * __BSD_VISIBLE + */ + +/* + * X/Open Portability Guides and Single Unix Specifications. + * _XOPEN_SOURCE XPG3 + * _XOPEN_SOURCE && _XOPEN_VERSION = 4 XPG4 + * _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED = 1 XPG4v2 + * _XOPEN_SOURCE == 500 XPG5 + * _XOPEN_SOURCE == 520 XPG5v2 + * _XOPEN_SOURCE == 600 POSIX 1003.1-2001 with XSI + * _XOPEN_SOURCE == 700 POSIX 1003.1-2008 with XSI + * _XOPEN_SOURCE == 800 POSIX 1003.1-2024 with XSI + * + * The XPG spec implies a specific value for _POSIX_C_SOURCE. + */ +#ifdef _XOPEN_SOURCE +# if (_XOPEN_SOURCE - 0 >= 800) +# define __XPG_VISIBLE 800 +# undef _POSIX_C_SOURCE +# define _POSIX_C_SOURCE 202405L +# elif (_XOPEN_SOURCE - 0 >= 700) +# define __XPG_VISIBLE 700 +# undef _POSIX_C_SOURCE +# define _POSIX_C_SOURCE 200809L +# elif (_XOPEN_SOURCE - 0 >= 600) +# define __XPG_VISIBLE 600 +# undef _POSIX_C_SOURCE +# define _POSIX_C_SOURCE 200112L +# elif (_XOPEN_SOURCE - 0 >= 520) +# define __XPG_VISIBLE 520 +# undef _POSIX_C_SOURCE +# define _POSIX_C_SOURCE 199506L +# elif (_XOPEN_SOURCE - 0 >= 500) +# define __XPG_VISIBLE 500 +# undef _POSIX_C_SOURCE +# define _POSIX_C_SOURCE 199506L +# elif (_XOPEN_SOURCE_EXTENDED - 0 == 1) +# define __XPG_VISIBLE 420 +# elif (_XOPEN_VERSION - 0 >= 4) +# define __XPG_VISIBLE 400 +# else +# define __XPG_VISIBLE 300 +# endif +#endif + +/* + * POSIX macros, these checks must follow the XOPEN ones above. + * + * _POSIX_SOURCE == 1 1003.1-1988 (superseded by _POSIX_C_SOURCE) + * _POSIX_C_SOURCE == 1 1003.1-1990 + * _POSIX_C_SOURCE == 2 1003.2-1992 + * _POSIX_C_SOURCE == 199309L 1003.1b-1993 + * _POSIX_C_SOURCE == 199506L 1003.1c-1995, 1003.1i-1995, + * and the omnibus ISO/IEC 9945-1:1996 + * _POSIX_C_SOURCE == 200112L 1003.1-2001 + * _POSIX_C_SOURCE == 200809L 1003.1-2008 + * _POSIX_C_SOURCE == 202405L 1003.1-2024 + * + * The POSIX spec implies a specific value for __ISO_C_VISIBLE, though + * this may be overridden by the _ISOC99_SOURCE macro later. + */ +#ifdef _POSIX_C_SOURCE +# if (_POSIX_C_SOURCE - 0 >= 202405) +# define __POSIX_VISIBLE 202405 +# define __ISO_C_VISIBLE 2017 +# elif (_POSIX_C_SOURCE - 0 >= 200809) +# define __POSIX_VISIBLE 200809 +# define __ISO_C_VISIBLE 1999 +# elif (_POSIX_C_SOURCE - 0 >= 200112) +# define __POSIX_VISIBLE 200112 +# define __ISO_C_VISIBLE 1999 +# elif (_POSIX_C_SOURCE - 0 >= 199506) +# define __POSIX_VISIBLE 199506 +# define __ISO_C_VISIBLE 1990 +# elif (_POSIX_C_SOURCE - 0 >= 199309) +# define __POSIX_VISIBLE 199309 +# define __ISO_C_VISIBLE 1990 +# elif (_POSIX_C_SOURCE - 0 >= 2) +# define __POSIX_VISIBLE 199209 +# define __ISO_C_VISIBLE 1990 +# else +# define __POSIX_VISIBLE 199009 +# define __ISO_C_VISIBLE 1990 +# endif +#elif defined(_POSIX_SOURCE) +# define __POSIX_VISIBLE 198808 +# define __ISO_C_VISIBLE 0 +#endif + +/* + * _ANSI_SOURCE means to expose ANSI C89 interfaces only. + * If the user defines it in addition to one of the POSIX or XOPEN + * macros, assume the POSIX/XOPEN macro(s) should take precedence. + */ +#if defined(_ANSI_SOURCE) && !defined(__POSIX_VISIBLE) && \ + !defined(__XPG_VISIBLE) +# define __POSIX_VISIBLE 0 +# define __XPG_VISIBLE 0 +# define __ISO_C_VISIBLE 1990 +#endif + +/* + * _ISOC99_SOURCE, _ISOC11_SOURCE, __STDC_VERSION__, and __cplusplus + * override any of the other macros since they are non-exclusive. + */ +#if defined(_ISOC11_SOURCE) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112) || \ + (defined(__cplusplus) && __cplusplus >= 201703) +# undef __ISO_C_VISIBLE +# define __ISO_C_VISIBLE 2011 +#elif defined(_ISOC99_SOURCE) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901) || \ + (defined(__cplusplus) && __cplusplus >= 201103) +# undef __ISO_C_VISIBLE +# define __ISO_C_VISIBLE 1999 +#endif + +/* + * Finally deal with BSD-specific interfaces that are not covered + * by any standards. We expose these when none of the POSIX or XPG + * macros is defined or if the user explicitly asks for them. + */ +#if !defined(_BSD_SOURCE) && \ + (defined(_ANSI_SOURCE) || defined(__XPG_VISIBLE) || defined(__POSIX_VISIBLE)) +# define __BSD_VISIBLE 0 +#endif + +/* + * Default values. + */ +#ifndef __XPG_VISIBLE +# define __XPG_VISIBLE 800 +#endif +#ifndef __POSIX_VISIBLE +# define __POSIX_VISIBLE 202405 +#endif +#ifndef __ISO_C_VISIBLE +# define __ISO_C_VISIBLE 2017 +#endif +#ifndef __BSD_VISIBLE +# define __BSD_VISIBLE 1 +#endif + +#endif /* !_SYS_CDEFS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/cdio.h b/lib/libc/include/generic-openbsd/sys/cdio.h new file mode 100644 index 000000000000..ee88041d66e1 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/cdio.h @@ -0,0 +1,435 @@ +/* $OpenBSD: cdio.h,v 1.17 2017/10/24 09:36:13 jsg Exp $ */ +/* $NetBSD: cdio.h,v 1.11 1996/02/19 18:29:04 scottr Exp $ */ + +#ifndef _SYS_CDIO_H_ +#define _SYS_CDIO_H_ + +#include +#include + +/* Shared between kernel & process */ + +union msf_lba { + struct { + u_char unused; + u_char minute; + u_char second; + u_char frame; + } msf; + u_int32_t lba; + u_char addr[4]; +}; + +struct cd_toc_entry { + u_char nothing1; +#if _BYTE_ORDER == _LITTLE_ENDIAN + u_int control:4; + u_int addr_type:4; +#endif +#if _BYTE_ORDER == _BIG_ENDIAN + u_int addr_type:4; + u_int control:4; +#endif + u_char track; + u_char nothing2; + union msf_lba addr; +}; + +struct cd_sub_channel_header { + u_char nothing1; + u_char audio_status; +#define CD_AS_AUDIO_INVALID 0x00 +#define CD_AS_PLAY_IN_PROGRESS 0x11 +#define CD_AS_PLAY_PAUSED 0x12 +#define CD_AS_PLAY_COMPLETED 0x13 +#define CD_AS_PLAY_ERROR 0x14 +#define CD_AS_NO_STATUS 0x15 + u_char data_len[2]; +}; + +struct cd_sub_channel_q_data { + u_char data_format; +#if _BYTE_ORDER == _LITTLE_ENDIAN + u_int control:4; + u_int addr_type:4; +#endif +#if _BYTE_ORDER == _BIG_ENDIAN + u_int addr_type:4; + u_int control:4; +#endif + u_char track_number; + u_char index_number; + u_char absaddr[4]; + u_char reladdr[4]; +#if _BYTE_ORDER == _LITTLE_ENDIAN + u_int :7; + u_int mc_valid:1; +#endif +#if _BYTE_ORDER == _BIG_ENDIAN + u_int mc_valid:1; + u_int :7; +#endif + u_char mc_number[15]; +#if _BYTE_ORDER == _LITTLE_ENDIAN + u_int :7; + u_int ti_valid:1; +#endif +#if _BYTE_ORDER == _BIG_ENDIAN + u_int ti_valid:1; + u_int :7; +#endif + u_char ti_number[15]; +}; + +struct cd_sub_channel_position_data { + u_char data_format; +#if _BYTE_ORDER == _LITTLE_ENDIAN + u_int control:4; + u_int addr_type:4; +#endif +#if _BYTE_ORDER == _BIG_ENDIAN + u_int addr_type:4; + u_int control:4; +#endif + u_char track_number; + u_char index_number; + union msf_lba absaddr; + union msf_lba reladdr; +}; + +struct cd_sub_channel_media_catalog { + u_char data_format; + u_char nothing1; + u_char nothing2; + u_char nothing3; +#if _BYTE_ORDER == _LITTLE_ENDIAN + u_int :7; + u_int mc_valid:1; +#endif +#if _BYTE_ORDER == _BIG_ENDIAN + u_int mc_valid:1; + u_int :7; +#endif + u_char mc_number[15]; +}; + +struct cd_sub_channel_track_info { + u_char data_format; + u_char nothing1; + u_char track_number; + u_char nothing2; +#if _BYTE_ORDER == _LITTLE_ENDIAN + u_int :7; + u_int ti_valid:1; +#endif +#if _BYTE_ORDER == _BIG_ENDIAN + u_int ti_valid:1; + u_int :7; +#endif + u_char ti_number[15]; +}; + +struct cd_sub_channel_info { + struct cd_sub_channel_header header; + union { + struct cd_sub_channel_q_data q_data; + struct cd_sub_channel_position_data position; + struct cd_sub_channel_media_catalog media_catalog; + struct cd_sub_channel_track_info track_info; + } what; +}; + +/* + * Ioctls for the CD drive + */ +struct ioc_play_track { + u_char start_track; + u_char start_index; + u_char end_track; + u_char end_index; +}; + +#define CDIOCPLAYTRACKS _IOW('c', 1, struct ioc_play_track) +struct ioc_play_blocks { + int blk; + int len; +}; +#define CDIOCPLAYBLOCKS _IOW('c', 2, struct ioc_play_blocks) + +struct ioc_read_subchannel { + u_char address_format; +#define CD_LBA_FORMAT 1 +#define CD_MSF_FORMAT 2 + u_char data_format; +#define CD_SUBQ_DATA 0 +#define CD_CURRENT_POSITION 1 +#define CD_MEDIA_CATALOG 2 +#define CD_TRACK_INFO 3 + u_char track; + int data_len; + struct cd_sub_channel_info *data; +}; +#define CDIOCREADSUBCHANNEL _IOWR('c', 3, struct ioc_read_subchannel) + +struct ioc_toc_header { + u_short len; + u_char starting_track; + u_char ending_track; +}; + +#define CDIOREADTOCHEADER _IOR('c', 4, struct ioc_toc_header) + +struct ioc_read_toc_entry { + u_char address_format; + u_char starting_track; +#define CD_TRACK_LEADOUT 0xaa + u_short data_len; + struct cd_toc_entry *data; +}; +#define CDIOREADTOCENTRIES _IOWR('c', 5, struct ioc_read_toc_entry) +#define CDIOREADTOCENTRYS CDIOREADTOCENTRIES + +/* read LBA start of a given session; 0=last, others not yet supported */ +#define CDIOREADMSADDR _IOWR('c', 6, int) + +struct ioc_patch { + u_char patch[4]; /* one for each channel */ +}; +#define CDIOCSETPATCH _IOW('c', 9, struct ioc_patch) + +struct ioc_vol { + u_char vol[4]; /* one for each channel */ +}; +#define CDIOCGETVOL _IOR('c', 10, struct ioc_vol) +#define CDIOCSETVOL _IOW('c', 11, struct ioc_vol) +#define CDIOCSETMONO _IO('c', 12) +#define CDIOCSETSTEREO _IO('c', 13) +#define CDIOCSETMUTE _IO('c', 14) +#define CDIOCSETLEFT _IO('c', 15) +#define CDIOCSETRIGHT _IO('c', 16) +#define CDIOCSETDEBUG _IO('c', 17) +#define CDIOCCLRDEBUG _IO('c', 18) +#define CDIOCPAUSE _IO('c', 19) +#define CDIOCRESUME _IO('c', 20) +#define CDIOCRESET _IO('c', 21) +#define CDIOCSTART _IO('c', 22) +#define CDIOCSTOP _IO('c', 23) +#define CDIOCEJECT _IO('c', 24) +#define CDIOCALLOW _IO('c', 25) +#define CDIOCPREVENT _IO('c', 26) +#define CDIOCCLOSE _IO('c', 27) + +struct ioc_play_msf { + u_char start_m; + u_char start_s; + u_char start_f; + u_char end_m; + u_char end_s; + u_char end_f; +}; +#define CDIOCPLAYMSF _IOW('c', 25, struct ioc_play_msf) + +struct ioc_load_unload { + u_char options; +#define CD_LU_ABORT 0x1 /* NOTE: These are the same as the ATAPI */ +#define CD_LU_UNLOAD 0x2 /* op values for the LOAD_UNLOAD command */ +#define CD_LU_LOAD 0x3 + u_char slot; +}; +#define CDIOCLOADUNLOAD _IOW('c', 26, struct ioc_load_unload) + +/* DVD definitions */ + +/* DVD-ROM Specific ioctls */ +#define DVD_READ_STRUCT _IOWR('d', 0, union dvd_struct) +#define DVD_WRITE_STRUCT _IOWR('d', 1, union dvd_struct) +#define DVD_AUTH _IOWR('d', 2, union dvd_authinfo) + +#define GPCMD_READ_DVD_STRUCTURE 0xad +#define GPCMD_SEND_DVD_STRUCTURE 0xad +#define GPCMD_REPORT_KEY 0xa4 +#define GPCMD_SEND_KEY 0xa3 + +/* DVD struct types */ +#define DVD_STRUCT_PHYSICAL 0x00 +#define DVD_STRUCT_COPYRIGHT 0x01 +#define DVD_STRUCT_DISCKEY 0x02 +#define DVD_STRUCT_BCA 0x03 +#define DVD_STRUCT_MANUFACT 0x04 + +struct dvd_layer { + u_int8_t book_version; + u_int8_t book_type; + u_int8_t min_rate; + u_int8_t disc_size; + u_int8_t layer_type; + u_int8_t track_path; + u_int8_t nlayers; + u_int8_t track_density; + u_int8_t linear_density; + u_int8_t bca; + u_int32_t start_sector; + u_int32_t end_sector; + u_int32_t end_sector_l0; +}; + +struct dvd_physical { + u_int8_t type; + + u_int8_t layer_num; + struct dvd_layer layer[4]; +}; + +struct dvd_copyright { + u_int8_t type; + + u_int8_t layer_num; + u_int8_t cpst; + u_int8_t rmi; +}; + +struct dvd_disckey { + u_int8_t type; + + u_int8_t agid; + u_int8_t value[2048]; +}; + +struct dvd_bca { + u_int8_t type; + + int len; + u_int8_t value[188]; +}; + +struct dvd_manufact { + u_int8_t type; + + u_int8_t layer_num; + int len; + u_int8_t value[2048]; +}; + +union dvd_struct { + u_int8_t type; + + struct dvd_physical physical; + struct dvd_copyright copyright; + struct dvd_disckey disckey; + struct dvd_bca bca; + struct dvd_manufact manufact; +}; + +/* + * DVD authentication ioctl + */ + +/* Authentication states */ +#define DVD_LU_SEND_AGID 0 +#define DVD_HOST_SEND_CHALLENGE 1 +#define DVD_LU_SEND_KEY1 2 +#define DVD_LU_SEND_CHALLENGE 3 +#define DVD_HOST_SEND_KEY2 4 + +/* Termination states */ +#define DVD_AUTH_ESTABLISHED 5 +#define DVD_AUTH_FAILURE 6 + +/* Other functions */ +#define DVD_LU_SEND_TITLE_KEY 7 +#define DVD_LU_SEND_ASF 8 +#define DVD_INVALIDATE_AGID 9 +#define DVD_LU_SEND_RPC_STATE 10 +#define DVD_HOST_SEND_RPC_STATE 11 + +#if 0 +/* State data */ +typedef u_int8_t dvd_key[5]; /* 40-bit value, MSB is first elem. */ +typedef u_int8_t dvd_challenge[10]; /* 80-bit value, MSB is first elem. */ +#endif + +#define DVD_KEY_SIZE 5 +#define DVD_CHALLENGE_SIZE 10 + +struct dvd_lu_send_agid { + u_int8_t type; + + u_int8_t agid; +}; + +struct dvd_host_send_challenge { + u_int8_t type; + + u_int8_t agid; + u_int8_t chal[DVD_CHALLENGE_SIZE]; +}; + +struct dvd_send_key { + u_int8_t type; + + u_int8_t agid; + u_int8_t key[DVD_KEY_SIZE]; +}; + +struct dvd_lu_send_challenge { + u_int8_t type; + + u_int8_t agid; + u_int8_t chal[DVD_CHALLENGE_SIZE]; +}; + +#define DVD_CPM_NO_COPYRIGHT 0 +#define DVD_CPM_COPYRIGHTED 1 + +#define DVD_CP_SEC_NONE 0 +#define DVD_CP_SEC_EXIST 1 + +#define DVD_CGMS_UNRESTRICTED 0 +#define DVD_CGMS_SINGLE 2 +#define DVD_CGMS_RESTRICTED 3 + +struct dvd_lu_send_title_key { + u_int8_t type; + + u_int8_t agid; + u_int8_t title_key[DVD_KEY_SIZE]; + int lba; + u_int8_t cpm; + u_int8_t cp_sec; + u_int8_t cgms; +}; + +struct dvd_lu_send_asf { + u_int8_t type; + + u_int8_t agid; + u_int8_t asf; +}; + +struct dvd_host_send_rpcstate { + u_int8_t type; + u_int8_t pdrc; +}; + +struct dvd_lu_send_rpcstate { + u_int8_t type; + u_int8_t vra; + u_int8_t ucca; + u_int8_t region_mask; + u_int8_t rpc_scheme; + }; + +union dvd_authinfo { + u_int8_t type; + + struct dvd_lu_send_agid lsa; + struct dvd_host_send_challenge hsc; + struct dvd_send_key lsk; + struct dvd_lu_send_challenge lsc; + struct dvd_send_key hsk; + struct dvd_lu_send_title_key lstk; + struct dvd_lu_send_asf lsasf; + struct dvd_host_send_rpcstate hrpcs; + struct dvd_lu_send_rpcstate lrpcs; +}; +#endif /* !_SYS_CDIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/chio.h b/lib/libc/include/generic-openbsd/sys/chio.h new file mode 100644 index 000000000000..cae798b3c484 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/chio.h @@ -0,0 +1,177 @@ +/* $OpenBSD: chio.h,v 1.9 2025/03/31 08:39:38 jsg Exp $ */ +/* $NetBSD: chio.h,v 1.8 1996/04/03 00:25:21 thorpej Exp $ */ + +/* + * Copyright (c) 1996 Jason R. Thorpe + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgements: + * This product includes software developed by Jason R. Thorpe + * for And Communications, http://www.and.com/ + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _SYS_CHIO_H_ +#define _SYS_CHIO_H_ + +/* + * Element types. Used as "to" and "from" type indicators in move + * and exchange operations. + * + * Note that code in sys/scsi/ch.c relies on these values (uses them + * as offsets in an array, and other evil), so don't muck with them + * unless you know what you're doing. + */ +#define CHET_MT 0 /* medium transport (picker) */ +#define CHET_ST 1 /* storage transport (slot) */ +#define CHET_IE 2 /* import/export (portal) */ +#define CHET_DT 3 /* data transfer (drive) */ + +/* + * Maximum length of a volume identification string + */ +#define CH_VOLTAG_MAXLEN 32 + +/* + * Structure used to execute a MOVE MEDIUM command. + */ +struct changer_move { + int cm_fromtype; /* element type to move from */ + int cm_fromunit; /* logical unit of from element */ + int cm_totype; /* element type to move to */ + int cm_tounit; /* logical unit of to element */ + int cm_flags; /* misc. flags */ +}; + +/* cm_flags */ +#define CM_INVERT 0x01 /* invert media */ + +/* + * Structure used to execute an EXCHANGE MEDIUM command. In an + * exchange operation, the following steps occur: + * + * - media from source is moved to first destination. + * + * - media previously occupying first destination is moved + * to the second destination. + * + * The second destination may or may not be the same as the source. + * In the case of a simple exchange, the source and second destination + * are the same. + */ +struct changer_exchange { + int ce_srctype; /* element type of source */ + int ce_srcunit; /* logical unit of source */ + int ce_fdsttype; /* element type of first destination */ + int ce_fdstunit; /* logical unit of first destination */ + int ce_sdsttype; /* element type of second destination */ + int ce_sdstunit; /* logical unit of second destination */ + int ce_flags; /* misc. flags */ +}; + +/* ce_flags */ +#define CE_INVERT1 0x01 /* invert media 1 */ +#define CE_INVERT2 0x02 /* invert media 2 */ + +/* + * Structure used to execute a POSITION TO ELEMENT command. This + * moves the current picker in front of the specified element. + */ +struct changer_position { + int cp_type; /* element type */ + int cp_unit; /* logical unit of element */ + int cp_flags; /* misc. flags */ +}; + +/* cp_flags */ +#define CP_INVERT 0x01 /* invert picker */ + +/* + * Data returned by CHIOGPARAMS. + */ +struct changer_params { + int cp_curpicker; /* current picker */ + int cp_npickers; /* number of pickers */ + int cp_nslots; /* number of slots */ + int cp_nportals; /* number of import/export portals */ + int cp_ndrives; /* number of drives */ +}; + +struct changer_voltag { + u_char cv_volid[CH_VOLTAG_MAXLEN + 1]; + u_int16_t cv_serial; +}; + +struct changer_element_status { + int ces_type; /* element type */ + u_int8_t ces_flags; /* flags */ + u_int16_t ces_addr; /* logical element address */ + u_int8_t ces_sensecode; /* additional sense code for element */ + u_int8_t ces_sensequal; /* additional sense code qualifier */ + u_int8_t ces_source_type; /* element type of source address */ + u_int16_t ces_source_addr; /* source address of medium */ + struct changer_voltag ces_pvoltag; /* primary voltag */ + struct changer_voltag ces_avoltag; /* alternate voltag */ +}; + +/* + * Command used to get element status. + */ +struct changer_element_status_request { + int cesr_type; /* element type */ + int cesr_flags; +#define CESR_VOLTAGS 0x01 + + struct changer_element_status *cesr_data; /* pre-allocated data storage */ +}; + +/* + * Data returned by CHIOGSTATUS is an array of flags bytes. + * Not all flags have meaning for all element types. + */ +#define CESTATUS_FULL 0x01 /* element is full */ +#define CESTATUS_IMPEXP 0x02 /* media deposited by operator */ +#define CESTATUS_EXCEPT 0x04 /* element in abnormal state */ +#define CESTATUS_ACCESS 0x08 /* media accessible by picker */ +#define CESTATUS_EXENAB 0x10 /* element supports exporting */ +#define CESTATUS_INENAB 0x20 /* element supports importing */ + +#define CESTATUS_PICKER_MASK 0x05 /* flags valid for pickers */ +#define CESTATUS_SLOT_MASK 0x0c /* flags valid for slots */ +#define CESTATUS_PORTAL_MASK 0x3f /* flags valid for portals */ +#define CESTATUS_DRIVE_MASK 0x0c /* flags valid for drives */ + +#define CESTATUS_BITS \ + "\20\6INEAB\5EXENAB\4ACCESS\3EXCEPT\2IMPEXP\1FULL" + +#define CHIOMOVE _IOW('c', 0x41, struct changer_move) +#define CHIOEXCHANGE _IOW('c', 0x42, struct changer_exchange) +#define CHIOPOSITION _IOW('c', 0x43, struct changer_position) +#define CHIOGPICKER _IOR('c', 0x44, int) +#define CHIOSPICKER _IOW('c', 0x45, int) +#define CHIOGPARAMS _IOR('c', 0x46, struct changer_params) +#define CHIOGSTATUS _IOW('c', 0x48, struct changer_element_status_request) + +#endif /* _SYS_CHIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/clockintr.h b/lib/libc/include/generic-openbsd/sys/clockintr.h new file mode 100644 index 000000000000..7432f80dcc64 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/clockintr.h @@ -0,0 +1,144 @@ +/* $OpenBSD: clockintr.h,v 1.29 2024/02/25 19:15:50 cheloha Exp $ */ +/* + * Copyright (c) 2020-2024 Scott Cheloha + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_CLOCKINTR_H_ +#define _SYS_CLOCKINTR_H_ + +#include + +struct clockintr_stat { + uint64_t cs_dispatched; /* total time in dispatch (ns) */ + uint64_t cs_early; /* number of early dispatch calls */ + uint64_t cs_earliness; /* total earliness (ns) */ + uint64_t cs_lateness; /* total lateness (ns) */ + uint64_t cs_prompt; /* number of prompt dispatch calls */ + uint64_t cs_run; /* number of events dispatched */ + uint64_t cs_spurious; /* number of spurious dispatch calls */ +}; + +#ifdef _KERNEL + +#include +#include + +struct clockqueue; +struct clockrequest; +struct cpu_info; + +/* + * Platform API + */ + +struct intrclock { + void *ic_cookie; + void (*ic_rearm)(void *, uint64_t); + void (*ic_trigger)(void *); +}; + +/* + * Schedulable clock interrupt callback. + * + * Struct member protections: + * + * I Immutable after initialization. + * m Parent queue mutex (cl_queue->cq_mtx). + */ +struct clockintr { + uint64_t cl_expiration; /* [m] dispatch time */ + TAILQ_ENTRY(clockintr) cl_alink; /* [m] cq_all glue */ + TAILQ_ENTRY(clockintr) cl_plink; /* [m] cq_pend glue */ + void *cl_arg; /* [I] argument */ + void (*cl_func)(struct clockrequest *, void*, void*); /* [I] callback */ + struct clockqueue *cl_queue; /* [I] parent queue */ + uint32_t cl_flags; /* [m] CLST_* flags */ +}; + +#define CLST_PENDING 0x00000001 /* scheduled to run */ + +/* + * Interface for callback rescheduling requests. + * + * Struct member protections: + * + * I Immutable after initialization. + * o Owned by a single CPU. + */ +struct clockrequest { + uint64_t cr_expiration; /* [o] copy of dispatch time */ + struct clockqueue *cr_queue; /* [I] enclosing queue */ + uint32_t cr_flags; /* [o] CR_* flags */ +}; + +#define CR_RESCHEDULE 0x00000001 /* reschedule upon return */ + +/* + * Per-CPU clock interrupt state. + * + * Struct member protections: + * + * a Modified atomically. + * I Immutable after initialization. + * m Per-queue mutex (cq_mtx). + * o Owned by a single CPU. + */ +struct clockqueue { + struct clockrequest cq_request; /* [o] callback request object */ + struct mutex cq_mtx; /* [a] per-queue mutex */ + uint64_t cq_uptime; /* [o] cached uptime */ + TAILQ_HEAD(, clockintr) cq_all; /* [m] established clockintr list */ + TAILQ_HEAD(, clockintr) cq_pend;/* [m] pending clockintr list */ + struct clockintr *cq_running; /* [m] running clockintr */ + struct clockintr cq_hardclock; /* [o] hardclock handle */ + struct intrclock cq_intrclock; /* [I] local interrupt clock */ + struct clockintr_stat cq_stat; /* [o] dispatch statistics */ + volatile uint32_t cq_gen; /* [o] cq_stat update generation */ + volatile uint32_t cq_dispatch; /* [o] dispatch is running */ + uint32_t cq_flags; /* [m] CQ_* flags; see below */ +}; + +#define CQ_INIT 0x00000001 /* clockintr_cpu_init() done */ +#define CQ_INTRCLOCK 0x00000002 /* intrclock installed */ +#define CQ_IGNORE_REQUEST 0x00000004 /* ignore callback requests */ +#define CQ_NEED_WAKEUP 0x00000008 /* caller at barrier */ +#define CQ_STATE_MASK 0x0000000f + +void clockintr_cpu_init(const struct intrclock *); +int clockintr_dispatch(void *); +void clockintr_trigger(void); + +/* + * Kernel API + */ + +#define CL_BARRIER 0x00000001 /* block if callback is running */ +#define CL_FLAG_MASK 0x00000001 + +uint64_t clockintr_advance(struct clockintr *, uint64_t); +void clockintr_bind(struct clockintr *, struct cpu_info *, + void (*)(struct clockrequest *, void *, void *), void *); +void clockintr_cancel(struct clockintr *); +void clockintr_schedule(struct clockintr *, uint64_t); +void clockintr_stagger(struct clockintr *, uint64_t, uint32_t, uint32_t); +void clockintr_unbind(struct clockintr *, uint32_t); +uint64_t clockrequest_advance(struct clockrequest *, uint64_t); +uint64_t clockrequest_advance_random(struct clockrequest *, uint64_t, uint32_t); +void clockqueue_init(struct clockqueue *); +int sysctl_clockintr(int *, u_int, void *, size_t *, void *, size_t); + +#endif /* _KERNEL */ + +#endif /* !_SYS_CLOCKINTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/conf.h b/lib/libc/include/generic-openbsd/sys/conf.h new file mode 100644 index 000000000000..23bb3e8ea4de --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/conf.h @@ -0,0 +1,620 @@ +/* $OpenBSD: conf.h,v 1.168 2025/09/08 17:25:46 helg Exp $ */ +/* $NetBSD: conf.h,v 1.33 1996/05/03 20:03:32 christos Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)conf.h 8.3 (Berkeley) 1/21/94 + */ + + +#ifndef _SYS_CONF_H_ +#define _SYS_CONF_H_ + +/* + * Definitions of device driver entry switches + */ + +struct buf; +struct proc; +struct tty; +struct uio; +struct knote; + +/* + * Types for d_type + */ +#define D_DISK 1 +#define D_TTY 2 + +/* + * Flags for d_flags + */ +#define D_CLONE 0x0001 /* clone upon open */ + +#ifdef _KERNEL + +#define dev_type_open(n) int n(dev_t, int, int, struct proc *) +#define dev_type_close(n) int n(dev_t, int, int, struct proc *) +#define dev_type_strategy(n) void n(struct buf *) +#define dev_type_ioctl(n) \ + int n(dev_t, u_long, caddr_t, int, struct proc *) + +#define dev_decl(n,t) __CONCAT(dev_type_,t)(__CONCAT(n,t)) +#define dev_init(c,n,t) \ + ((c) > 0 ? __CONCAT(n,t) : (__CONCAT(dev_type_,t)((*))) enxio) + +#endif /* _KERNEL */ + +/* + * Block device switch table + */ +struct bdevsw { + int (*d_open)(dev_t dev, int oflags, int devtype, + struct proc *p); + int (*d_close)(dev_t dev, int fflag, int devtype, + struct proc *p); + void (*d_strategy)(struct buf *bp); + int (*d_ioctl)(dev_t dev, u_long cmd, caddr_t data, + int fflag, struct proc *p); + int (*d_dump)(dev_t dev, daddr_t blkno, caddr_t va, + size_t size); + daddr_t (*d_psize)(dev_t dev); + u_int d_type; + /* u_int d_flags; */ +}; + +#ifdef _KERNEL + +extern struct bdevsw bdevsw[]; + +/* bdevsw-specific types */ +#define dev_type_dump(n) int n(dev_t, daddr_t, caddr_t, size_t) +#define dev_type_size(n) daddr_t n(dev_t) + +/* bdevsw-specific initializations */ +#define dev_size_init(c,n) (c > 0 ? __CONCAT(n,size) : 0) + +#define bdev_decl(n) \ + dev_decl(n,open); dev_decl(n,close); dev_decl(n,strategy); \ + dev_decl(n,ioctl); dev_decl(n,dump); dev_decl(n,size) + +#define bdev_disk_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), \ + dev_init(c,n,strategy), dev_init(c,n,ioctl), \ + dev_init(c,n,dump), dev_size_init(c,n), D_DISK } + +#define bdev_swap_init(c,n) { \ + (dev_type_open((*))) enodev, (dev_type_close((*))) enodev, \ + dev_init(c,n,strategy), (dev_type_ioctl((*))) enodev, \ + (dev_type_dump((*))) enodev, 0 } + +#define bdev_notdef() { \ + (dev_type_open((*))) enodev, (dev_type_close((*))) enodev, \ + (dev_type_strategy((*))) enodev, (dev_type_ioctl((*))) enodev, \ + (dev_type_dump((*))) enodev, 0 } + +#endif + +/* + * Character device switch table + */ +struct cdevsw { + int (*d_open)(dev_t dev, int oflags, int devtype, + struct proc *p); + int (*d_close)(dev_t dev, int fflag, int devtype, + struct proc *); + int (*d_read)(dev_t dev, struct uio *uio, int ioflag); + int (*d_write)(dev_t dev, struct uio *uio, int ioflag); + int (*d_ioctl)(dev_t dev, u_long cmd, caddr_t data, + int fflag, struct proc *p); + int (*d_stop)(struct tty *tp, int rw); + struct tty * + (*d_tty)(dev_t dev); + paddr_t (*d_mmap)(dev_t, off_t, int); + u_int d_type; + u_int d_flags; + int (*d_kqfilter)(dev_t dev, struct knote *kn); +}; + +#ifdef _KERNEL + +extern struct cdevsw cdevsw[]; + +/* cdevsw-specific types */ +#define dev_type_read(n) int n(dev_t, struct uio *, int) +#define dev_type_write(n) int n(dev_t, struct uio *, int) +#define dev_type_stop(n) int n(struct tty *, int) +#define dev_type_tty(n) struct tty *n(dev_t) +#define dev_type_mmap(n) paddr_t n(dev_t, off_t, int) +#define dev_type_kqfilter(n) int n(dev_t, struct knote *) + +#define cdev_decl(n) \ + dev_decl(n,open); dev_decl(n,close); dev_decl(n,read); \ + dev_decl(n,write); dev_decl(n,ioctl); dev_decl(n,stop); \ + dev_decl(n,tty); dev_decl(n,mmap); \ + dev_decl(n,kqfilter) + +/* open, close, read, write, ioctl */ +#define cdev_disk_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \ + 0, (dev_type_mmap((*))) enodev, \ + D_DISK, 0, seltrue_kqfilter } + +/* open, close, read, write, ioctl */ +#define cdev_tape_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \ + 0, (dev_type_mmap((*))) enodev, \ + 0, 0, seltrue_kqfilter } + +/* open, close, read, write, ioctl, stop, tty */ +#define cdev_tty_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), dev_init(c,n,ioctl), dev_init(c,n,stop), \ + dev_init(c,n,tty), (dev_type_mmap((*))) enodev, \ + D_TTY, 0, ttkqfilter } + +/* open, close, read, ioctl, kqfilter */ +#define cdev_mouse_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev , 0, 0, dev_init(c,n,kqfilter) } + +#define cdev_notdef() { \ + (dev_type_open((*))) enodev, (dev_type_close((*))) enodev, \ + (dev_type_read((*))) enodev, (dev_type_write((*))) enodev, \ + (dev_type_ioctl((*))) enodev, (dev_type_stop((*))) enodev, \ + 0, (dev_type_mmap((*))) enodev, 0, 0, seltrue_kqfilter } + +/* open, close, read, write, ioctl, kqfilter -- XXX should be a tty */ +#define cdev_cn_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), dev_init(c,n,ioctl), dev_init(c,n,stop), \ + 0, (dev_type_mmap((*))) enodev, \ + D_TTY, 0, dev_init(c,n,kqfilter) } + +/* open, read, write, ioctl, kqfilter -- XXX should be a tty */ +#define cdev_ctty_init(c,n) { \ + dev_init(c,n,open), (dev_type_close((*))) nullop, dev_init(c,n,read), \ + dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) nullop, \ + 0, (dev_type_mmap((*))) enodev, \ + D_TTY, 0, dev_init(c,n,kqfilter) } + +/* open, close, read, write, ioctl, mmap */ +#define cdev_mm_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, dev_init(c,n,mmap), \ + 0, 0, seltrue_kqfilter } + +/* open, close, read, write, ioctl, tty, kqfilter */ +#define cdev_ptc_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) nullop, \ + dev_init(c,n,tty), (dev_type_mmap((*))) enodev, \ + D_TTY, 0, dev_init(c,n,kqfilter) } + +/* open, close, read, write, ioctl, mmap */ +#define cdev_ptm_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, (dev_type_mmap((*))) enodev } + +/* open, close, read, ioctl, kqfilter XXX should be a generic device */ +#define cdev_log_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev, 0, 0, dev_init(c,n,kqfilter) } + +/* open */ +#define cdev_fd_init(c,n) { \ + dev_init(c,n,open), (dev_type_close((*))) enodev, \ + (dev_type_read((*))) enodev, (dev_type_write((*))) enodev, \ + (dev_type_ioctl((*))) enodev, (dev_type_stop((*))) enodev, \ + 0, (dev_type_mmap((*))) enodev } + +/* open, close, read, write, ioctl, kqfilter -- XXX should be generic device */ +#define cdev_tun_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \ + 0, (dev_type_mmap((*))) enodev, \ + 0, 0, dev_init(c,n,kqfilter) } + +/* open, close, ioctl, kqfilter -- XXX should be generic device */ +#define cdev_vscsi_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), \ + (dev_type_read((*))) enodev, (dev_type_write((*))) enodev, \ + dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \ + 0, (dev_type_mmap((*))) enodev, \ + 0, 0, dev_init(c,n,kqfilter) } + +/* open, close, read, write, ioctl, kqfilter -- XXX should be generic device */ +#define cdev_pppx_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \ + 0, (dev_type_mmap((*))) enodev, \ + 0, 0, dev_init(c,n,kqfilter) } + +/* open, close, read, write, ioctl, kqfilter, cloning -- XXX should be generic device */ +#define cdev_bpf_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \ + 0, (dev_type_mmap((*))) enodev, \ + 0, D_CLONE, dev_init(c,n,kqfilter) } + +/* open, close, ioctl */ +#define cdev_ch_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev } + +/* open, close, ioctl */ +#define cdev_uk_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev } + +/* open, close, read, write, ioctl, kqfilter */ +#define cdev_audio_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev, 0, 0, dev_init(c,n,kqfilter) } + +/* open, close, read, write, ioctl, kqfilter */ +#define cdev_midi_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev, 0, 0, dev_init(c,n,kqfilter) } + +/* open, close, read */ +#define cdev_ksyms_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + (dev_type_write((*))) enodev, (dev_type_ioctl((*))) enodev, \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev, 0, 0, seltrue_kqfilter } + +/* open, close, ioctl */ +#define cdev_kstat_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev } + +/* open, close, read, write, ioctl, stop, tty, mmap, kqfilter */ +#define cdev_wsdisplay_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), dev_init(c,n,ioctl), dev_init(c,n,stop), \ + dev_init(c,n,tty), dev_init(c,n,mmap), \ + D_TTY, 0, dev_init(c,n,kqfilter) } + +/* open, close, read, write, ioctl, kqfilter */ +#define cdev_random_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \ + 0, (dev_type_mmap((*))) enodev, \ + 0, 0, dev_init(c,n,kqfilter) } + +/* open, close, ioctl, nokqfilter */ +#define cdev_usb_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev } + +/* open, close, write */ +#define cdev_ulpt_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + dev_init(c,n,write), (dev_type_ioctl((*))) enodev, \ + (dev_type_stop((*))) enodev, 0, (dev_type_mmap((*))) enodev } + +/* open, close, ioctl */ +#define cdev_pf_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev, 0, D_CLONE } + +/* open, close, read, write, ioctl, kqfilter */ +#define cdev_usbdev_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \ + 0, (dev_type_mmap((*))) enodev, 0, 0, \ + dev_init(c,n,kqfilter) } + +/* open, close, read, write, ioctl, kqfilter */ +#define cdev_fido_init(c,n) { \ + dev_init(c,n,open), dev_init(c,uhid,close), dev_init(c,uhid,read), \ + dev_init(c,uhid,write), dev_init(c,fido,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev, 0, 0, dev_init(c,uhid,kqfilter) } + +/* open, close, read, write, ioctl, kqfilter */ +#define cdev_ujoy_init(c,n) { \ + dev_init(c,n,open), dev_init(c,uhid,close), dev_init(c,uhid,read), \ + dev_init(c,uhid,write), dev_init(c,ujoy,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev, 0, 0, dev_init(c,uhid,kqfilter) } + +/* open, close, init */ +#define cdev_pci_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev } + +/* open, close, ioctl */ +#define cdev_radio_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev } + +/* open, close, ioctl, read, mmap, kqfilter */ +#define cdev_video_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + dev_init(c,n,mmap), 0, 0, dev_init(c,n,kqfilter) } + +/* open, close, write, ioctl */ +#define cdev_spkr_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \ + 0, (dev_type_mmap((*))) enodev, \ + 0, 0, seltrue_kqfilter } + +/* open, close, write */ +#define cdev_lpt_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + dev_init(c,n,write), (dev_type_ioctl((*))) enodev, \ + (dev_type_stop((*))) enodev, 0, (dev_type_mmap((*))) enodev, \ + 0, 0, seltrue_kqfilter } + +/* open, close, read, ioctl, mmap */ +#define cdev_bktr_init(c, n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, dev_init(c,n,mmap), \ + 0, 0, seltrue_kqfilter } + +/* open, close, read, ioctl, kqfilter */ +#define cdev_hotplug_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev, 0, 0, dev_init(c,n,kqfilter) } + +/* open, close, ioctl */ +#define cdev_gpio_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev } + +/* open, close, ioctl */ +#define cdev_bio_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev } + +/* open, close, read, ioctl, mmap, nokqfilter */ +#define cdev_drm_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c, n, read), \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + dev_init(c,n,mmap), 0, D_CLONE, dev_init(c,n,kqfilter) } + +/* open, close, ioctl */ +#define cdev_amdmsr_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev } + +/* open, close, read, write, ioctl */ +#define cdev_fuse_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), (dev_type_ioctl((*))) enodev, \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev, 0, D_CLONE, dev_init(c,n,kqfilter) } + +/* open, close, ioctl */ +#define cdev_pvbus_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), \ + (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, \ + dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev } + +/* open, close, ioctl */ +#define cdev_ipmi_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, (dev_type_mmap((*))) enodev, \ + 0, 0, seltrue_kqfilter } + +/* open, close, ioctl */ +#define cdev_efi_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev } + +/* open, close, ioctl, mmap */ +#define cdev_kcov_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_init(c,n,mmap)), 0, D_CLONE } + +/* open, close, read, ioctl */ +#define cdev_dt_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev, 0, D_CLONE } + +#endif + +/* + * Line discipline switch table + */ +struct linesw { + int (*l_open)(dev_t dev, struct tty *tp, struct proc *p); + int (*l_close)(struct tty *tp, int flags, struct proc *p); + int (*l_read)(struct tty *tp, struct uio *uio, + int flag); + int (*l_write)(struct tty *tp, struct uio *uio, + int flag); + int (*l_ioctl)(struct tty *tp, u_long cmd, caddr_t data, + int flag, struct proc *p); + int (*l_rint)(int c, struct tty *tp); + int (*l_start)(struct tty *tp); + int (*l_modem)(struct tty *tp, int flag); +}; + +#ifdef _KERNEL +extern struct linesw linesw[]; +extern dev_t swdevt[]; /* Swap device table */ +extern const int chrtoblktbl[]; +extern const int nchrtoblktbl; + +struct bdevsw *bdevsw_lookup(dev_t); +dev_t chrtoblk(dev_t); +dev_t blktochr(dev_t); +int iskmemdev(dev_t); +int iszerodev(dev_t); +dev_t getnulldev(void); + +cdev_decl(filedesc); + +cdev_decl(log); + +#define ptstty ptytty +#define ptsioctl ptyioctl +cdev_decl(pts); + +#define ptctty ptytty +#define ptcioctl ptyioctl +cdev_decl(ptc); + +cdev_decl(ptm); + +cdev_decl(ctty); + +cdev_decl(audio); +cdev_decl(drm); +cdev_decl(midi); +cdev_decl(radio); +cdev_decl(video); +cdev_decl(cn); + +bdev_decl(sw); + +bdev_decl(vnd); +cdev_decl(vnd); + +cdev_decl(ch); + +bdev_decl(sd); +cdev_decl(sd); + +cdev_decl(st); + +bdev_decl(cd); +cdev_decl(cd); + +bdev_decl(rd); +cdev_decl(rd); + +bdev_decl(uk); +cdev_decl(uk); + +cdev_decl(dt); + +cdev_decl(diskmap); + +cdev_decl(bpf); + +cdev_decl(pf); + +cdev_decl(tun); +cdev_decl(tap); +cdev_decl(pppx); +cdev_decl(pppac); + +cdev_decl(random); + +cdev_decl(wsdisplay); +cdev_decl(wskbd); +cdev_decl(wsmouse); +cdev_decl(wsmux); + +cdev_decl(ksyms); +cdev_decl(kstat); + +cdev_decl(bio); +cdev_decl(vscsi); + +cdev_decl(bktr); + +cdev_decl(usb); +cdev_decl(ugen); +cdev_decl(uhid); +cdev_decl(fido); +cdev_decl(ujoy); +cdev_decl(ucom); +cdev_decl(ulpt); + +cdev_decl(hotplug); +cdev_decl(gpio); +cdev_decl(amdmsr); +cdev_decl(fuse); +cdev_decl(pvbus); +cdev_decl(ipmi); +cdev_decl(efi); +cdev_decl(kcov); + +#endif + +#endif /* _SYS_CONF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/core.h b/lib/libc/include/generic-openbsd/sys/core.h new file mode 100644 index 000000000000..5facce434367 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/core.h @@ -0,0 +1,99 @@ +/* $OpenBSD: core.h,v 1.9 2024/01/17 22:22:25 kurt Exp $ */ +/* $NetBSD: core.h,v 1.4 1994/10/29 08:20:14 cgd Exp $ */ + +/* + * Copyright (c) 1994 Paul Kranenburg + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Paul Kranenburg. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define COREMAGIC 0507 +#define CORESEGMAGIC 0510 + +/* + * The core structure's c_midmag field (like exec's a_midmag) is a + * network-byteorder encoding of this int + * FFFFFFmmmmmmmmmmMMMMMMMMMMMMMMMM + * Where `F' is 6 bits of flag (currently unused), + * `m' is 10 bits of machine-id, and + * `M' is 16 bits worth of magic number, ie. COREMAGIC. + * The macros below will set/get the needed fields. + */ +#define CORE_GETMAGIC(c) ( ntohl(((c).c_midmag)) & 0xffff ) +#define CORE_GETMID(c) ( (ntohl(((c).c_midmag)) >> 16) & 0x03ff ) +#define CORE_GETFLAG(c) ( (ntohl(((c).c_midmag)) >> 26) & 0x03f ) +#define CORE_SETMAGIC(c,mag,mid,flag) ( (c).c_midmag = htonl ( \ + ( ((flag) & 0x3f) << 26) | \ + ( ((mid) & 0x03ff) << 16) | \ + ( ((mag) & 0xffff) ) ) ) + +/* Flag definitions */ +#define CORE_CPU 1 +#define CORE_DATA 2 +#define CORE_STACK 4 + +#ifndef _KERNEL +/* + * XXX OBSOLETE, NO LONGER USED + * XXX This header file exists to support binutils' netbsd-core format + * XXX which is still needed for the a.out-m88k-openbsd use in luna88k + * XXX boot block creation. + * + * A core file consists of a header followed by a number of segments. + * Each segment is preceded by a `coreseg' structure giving the + * segment's type, the virtual address where the bits resided in + * process address space and the size of the segment. + * + * The core header specifies the lengths of the core header itself and + * each of the following core segment headers to allow for any machine + * dependent alignment requirements. + */ + +struct core { + u_int32_t c_midmag; /* magic, id, flags */ + u_int16_t c_hdrsize; /* Size of this header (machdep algn) */ + u_int16_t c_seghdrsize; /* Size of a segment header */ + u_int32_t c_nseg; /* # of core segments */ + char c_name[_MAXCOMLEN]; /* Copy of p->p_comm, incl NUL */ + u_int32_t c_signo; /* Killing signal */ + u_long c_ucode; /* Hmm ? */ + u_long c_cpusize; /* Size of machine dependent segment */ + u_long c_tsize; /* Size of traditional text segment */ + u_long c_dsize; /* Size of traditional data segment */ + u_long c_ssize; /* Size of traditional stack segment */ +}; + +struct coreseg { + u_int32_t c_midmag; /* magic, id, flags */ + u_long c_addr; /* Virtual address of segment */ + u_long c_size; /* Size of this segment */ +}; + +#else +int coredump_write(void *, enum uio_seg, const void *, size_t, int); +void coredump_unmap(void *, vaddr_t, vaddr_t); +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/ctf.h b/lib/libc/include/generic-openbsd/sys/ctf.h new file mode 100644 index 000000000000..2ce31a7c5e0f --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/ctf.h @@ -0,0 +1,186 @@ +/* $OpenBSD: ctf.h,v 1.5 2017/08/13 14:56:05 nayden Exp $ */ + +/* + * Copyright (c) 2016 Martin Pieuchot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_CTF_H_ +#define _SYS_CTF_H_ + +/* + * CTF ``Compact ANSI-C Type Format'' ABI header file. + */ + +struct ctf_header { + uint16_t cth_magic; + uint8_t cth_version; + uint8_t cth_flags; + uint32_t cth_parlabel; + uint32_t cth_parname; + uint32_t cth_lbloff; + uint32_t cth_objtoff; + uint32_t cth_funcoff; + uint32_t cth_typeoff; + uint32_t cth_stroff; + uint32_t cth_strlen; +}; + +#define CTF_F_COMPRESS (1 << 0) /* zlib compression */ + +struct ctf_lblent { + uint32_t ctl_label; + uint32_t ctl_typeidx; +}; + +struct ctf_stype { + uint32_t cts_name; + uint16_t cts_info; + union { + uint16_t _size; + uint16_t _type; + } _ST; +#define cts_size _ST._size +#define cts_type _ST._type +}; + +struct ctf_type { + struct ctf_stype _ctt_stype; +#define ctt_name _ctt_stype.cts_name +#define ctt_info _ctt_stype.cts_info +#define ctt_size _ctt_stype.cts_size +#define ctt_type _ctt_stype.cts_type + uint32_t ctt_lsizehi; + uint32_t ctt_lsizelo; +}; + +struct ctf_array { + uint16_t cta_contents; + uint16_t cta_index; + uint32_t cta_nelems; +}; + +struct ctf_member { + uint32_t ctm_name; + uint16_t ctm_type; + uint16_t ctm_offset; +}; + +struct ctf_lmember { + struct ctf_member _ctlm_member; +#define ctlm_name _ctlm_member.ctm_name +#define ctlm_type _ctlm_member.ctm_type +#define ctlm_pad0 _ctlm_member.ctm_offset + uint32_t ctlm_offsethi; + uint32_t ctlm_offsetlo; +}; + +#define CTF_LSTRUCT_THRESH 8192 + +struct ctf_enum { + uint32_t cte_name; + int32_t cte_value; +}; + +#define CTF_MAGIC 0xcff1 +#define CTF_VERSION 2 + +#define CTF_MAX_NAME 0x7fffffff +#define CTF_MAX_VLEN 0x03ff +#define CTF_MAX_SIZE 0xfffe +#define CTF_LSIZE_SENT CTF_MAX_SIZE+1 /* sentinel for cts vs ctt */ + +#define CTF_STRTAB_0 0 +#define CTF_STRTAB_1 1 + +/* + * Info macro. + */ +#define CTF_INFO_VLEN(i) (((i) & CTF_MAX_VLEN)) +#define CTF_INFO_ISROOT(i) (((i) & 0x0400) >> 10) +#define CTF_INFO_KIND(i) (((i) & 0xf800) >> 11) +#define CTF_K_UNKNOWN 0 +#define CTF_K_INTEGER 1 +#define CTF_K_FLOAT 2 +#define CTF_K_POINTER 3 +#define CTF_K_ARRAY 4 +#define CTF_K_FUNCTION 5 +#define CTF_K_STRUCT 6 +#define CTF_K_UNION 7 +#define CTF_K_ENUM 8 +#define CTF_K_FORWARD 9 +#define CTF_K_TYPEDEF 10 +#define CTF_K_VOLATILE 11 +#define CTF_K_CONST 12 +#define CTF_K_RESTRICT 13 +#define CTF_K_MAX 31 + +/* + * Integer/Float Encoding macro. + */ +#define _CTF_ENCODING(e) (((e) & 0xff000000) >> 24) +#define _CTF_OFFSET(e) (((e) & 0x00ff0000) >> 16) +#define _CTF_BITS(e) (((e) & 0x0000ffff)) +#define _CTF_DATA(encoding, offset, bits) \ + (((encoding) << 24) | ((offset) << 16) | (bits)) + +#define CTF_INT_ENCODING(e) _CTF_ENCODING(e) +#define CTF_INT_SIGNED (1 << 0) +#define CTF_INT_CHAR (1 << 1) +#define CTF_INT_BOOL (1 << 2) +#define CTF_INT_VARARGS (1 << 3) +#define CTF_INT_OFFSET(e) _CTF_OFFSET(e) +#define CTF_INT_BITS(e) _CTF_BITS(e) +#define CTF_INT_DATA(e, o, b) _CTF_DATA(e, o, b) + +#define CTF_FP_ENCODING(e) _CTF_ENCODING(e) +#define CTF_FP_SINGLE 1 +#define CTF_FP_DOUBLE 2 +#define CTF_FP_CPLX 3 +#define CTF_FP_DCPLX 4 +#define CTF_FP_LDCPLX 5 +#define CTF_FP_LDOUBLE 6 +#define CTF_FP_INTRVL 7 +#define CTF_FP_DINTRVL 8 +#define CTF_FP_LDINTRVL 9 +#define CTF_FP_IMAGRY 10 +#define CTF_FP_DIMAGRY 11 +#define CTF_FP_LDIMAGRY 12 +#define CTF_FP_OFFSET(e) _CTF_OFFSET(e) +#define CTF_FP_BITS(e) _CTF_BITS(e) +#define CTF_FP_DATA(e, o, b) _CTF_DATA(e, o, b) + +/* + * Name reference macro. + */ +#define CTF_NAME_STID(n) ((n) >> 31) +#define CTF_NAME_OFFSET(n) ((n) & CTF_MAX_NAME) + +/* + * Type macro. + */ +#define CTF_SIZE_TO_LSIZE_HI(s) ((uint32_t)((uint64_t)(s) >> 32)) +#define CTF_SIZE_TO_LSIZE_LO(s) ((uint32_t)(s)) +#define CTF_TYPE_LSIZE(t) \ + (((uint64_t)(t)->ctt_lsizehi) << 32 | (t)->ctt_lsizelo) + +/* + * Member macro. + */ +#define CTF_LMEM_OFFSET(m) \ + (((uint64_t)(m)->ctlm_offsethi) << 32 | (m)->ctlm_offsetlo) +#define CTF_OFFSET_TO_LMEMHI(off) ((uint32_t)((uint64_t)(off) >> 32)) +#define CTF_OFFSET_TO_LMEMLO(off) ((uint32_t)(off)) + +#endif /* _SYS_CTF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/device.h b/lib/libc/include/generic-openbsd/sys/device.h new file mode 100644 index 000000000000..58468d7f222d --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/device.h @@ -0,0 +1,245 @@ +/* $OpenBSD: device.h,v 1.70 2025/09/16 12:18:10 hshoexer Exp $ */ +/* $NetBSD: device.h,v 1.15 1996/04/09 20:55:24 cgd Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)device.h 8.2 (Berkeley) 2/17/94 + */ + +#ifndef _SYS_DEVICE_H_ +#define _SYS_DEVICE_H_ + +#include + +/* + * Minimal device structures. + * Note that all ``system'' device types are listed here. + */ +enum devclass { + DV_DULL, /* generic, no special info */ + DV_CPU, /* CPU (carries resource utilization) */ + DV_DISK, /* disk drive (label, etc) */ + DV_IFNET, /* network interface */ + DV_TAPE, /* tape device */ + DV_TTY /* serial line interface (???) */ +}; + +/* + * Actions for ca_activate. + */ +#define DVACT_DEACTIVATE 1 /* deactivate the device */ +#define DVACT_QUIESCE 2 /* warn the device about suspend */ +#define DVACT_SUSPEND 3 /* suspend the device */ +#define DVACT_RESUME 4 /* resume the device */ +#define DVACT_WAKEUP 5 /* tell device to recover after resume */ +#define DVACT_POWERDOWN 6 /* power device down */ + +struct device { + enum devclass dv_class; /* this device's classification */ + TAILQ_ENTRY(device) dv_list; /* entry on list of all devices */ + struct cfdata *dv_cfdata; /* config data that found us */ + int dv_unit; /* device unit number */ + char dv_xname[16]; /* external name (name + unit) */ + struct device *dv_parent; /* pointer to parent device */ + int dv_flags; /* misc. flags; see below */ + int dv_ref; /* ref count */ +}; + +/* dv_flags */ +#define DVF_ACTIVE 0x0001 /* device is activated */ + +TAILQ_HEAD(devicelist, device); + +/* + * Configuration data (i.e., data placed in ioconf.c). + */ +struct cfdata { + const struct cfattach *cf_attach; /* config attachment */ + struct cfdriver *cf_driver; /* config driver */ + short cf_unit; /* unit number */ + short cf_fstate; /* finding state (below) */ + long *cf_loc; /* locators (machine dependent) */ + int cf_flags; /* flags from config */ + short *cf_parents; /* potential parents */ + int cf_locnames; /* start of names */ + short cf_starunit1; /* 1st usable unit number by STAR */ +}; +extern struct cfdata cfdata[]; +#define FSTATE_NOTFOUND 0 /* has not been found */ +#define FSTATE_FOUND 1 /* has been found */ +#define FSTATE_STAR 2 /* duplicable */ +#define FSTATE_DNOTFOUND 3 /* has not been found, and is disabled */ +#define FSTATE_DSTAR 4 /* duplicable, and is disabled */ + +typedef int (*cfmatch_t)(struct device *, void *, void *); +typedef void (*cfscan_t)(struct device *, void *); + +/* + * `configuration' attachment and driver (what the machine-independent + * autoconf uses). As devices are found, they are applied against all + * the potential matches. The one with the best match is taken, and a + * device structure (plus any other data desired) is allocated. Pointers + * to these are placed into an array of pointers. The array itself must + * be dynamic since devices can be found long after the machine is up + * and running. + * + * Devices can have multiple configuration attachments if they attach + * to different attributes (busses, or whatever), to allow specification + * of multiple match and attach functions. There is only one configuration + * driver per driver, so that things like unit numbers and the device + * structure array will be shared. + */ +struct cfattach { + size_t ca_devsize; /* size of dev data (for malloc) */ + cfmatch_t ca_match; /* returns a match level */ + void (*ca_attach)(struct device *, struct device *, void *); + int (*ca_detach)(struct device *, int); + int (*ca_activate)(struct device *, int); +}; + +/* Flags given to config_detach(), and the ca_detach function. */ +#define DETACH_FORCE 0x01 /* force detachment; hardware gone */ +#define DETACH_QUIET 0x02 /* don't print a notice */ + +/* For cd_mode, below */ +#define CD_INDIRECT 1 +#define CD_SKIPHIBERNATE 2 +#define CD_COCOVM 4 /* Allow a device on a VM employing + * confidential computing methods, + * e.g. AMD SEV. */ + +struct cfdriver { + void **cd_devs; /* devices found */ + char *cd_name; /* device name */ + enum devclass cd_class; /* device classification */ + int cd_mode; /* device type subclassification */ + int cd_ndevs; /* size of cd_devs array */ +}; + +/* + * Configuration printing functions, and their return codes. The second + * argument is NULL if the device was configured; otherwise it is the name + * of the parent device. The return value is ignored if the device was + * configured, so most functions can return UNCONF unconditionally. + */ +typedef int (*cfprint_t)(void *, const char *); +#define QUIET 0 /* print nothing */ +#define UNCONF 1 /* print " not configured\n" */ +#define UNSUPP 2 /* print " not supported\n" */ + +/* + * Pseudo-device attach information (function + number of pseudo-devs). + */ +struct pdevinit { + void (*pdev_attach)(int); + int pdev_count; +}; + +#ifdef _KERNEL + +#ifdef DIAGNOSTIC +extern int pdevinit_done; +#endif + +extern struct devicelist alldevs; /* list of all devices */ + +extern int autoconf_verbose; +extern volatile int config_pending; /* semaphore for mountroot */ + +void config_init(void); +void *config_search(cfmatch_t, struct device *, void *); +struct device *config_found_sm(struct device *, void *, cfprint_t, + cfmatch_t); +struct device *config_rootfound(char *, void *); +void config_scan(cfscan_t, struct device *); +struct device *config_attach(struct device *, void *, void *, cfprint_t); +int config_detach(struct device *, int); +int config_detach_children(struct device *, int); +int config_deactivate(struct device *); +int config_suspend(struct device *, int); +int config_suspend_all(int); +int config_activate_children(struct device *, int); +struct device *config_make_softc(struct device *parent, + struct cfdata *cf); +void config_defer(struct device *, void (*)(struct device *)); +void config_pending_incr(void); +void config_pending_decr(void); +void config_mountroot(struct device *, void (*)(struct device *)); +void config_process_deferred_mountroot(void); + +int request_sleep(int); +int sleep_state(void *, int); +#define SLEEP_SUSPEND 0x01 +#define SLEEP_HIBERNATE 0x02 +void sleep_mp(void); +void resume_mp(void); +int sleep_showstate(void *v, int sleepmode); +int sleep_setstate(void *v); +int sleep_resume(void *v); +int gosleep(void *v); +int suspend_finish(void *v); +int resuming(void); + +struct device *device_mainbus(void); +struct device *device_mpath(void); +struct device *device_lookup(struct cfdriver *, int unit); +void device_ref(struct device *); +void device_unref(struct device *); + +struct nam2blk { + char *name; + int maj; +}; + +int findblkmajor(struct device *dv); +char *findblkname(int); +void setroot(struct device *, int, int); +struct device *getdisk(char *str, int len, int defpart, dev_t *devp); +struct device *parsedisk(char *str, int len, int defpart, dev_t *devp); +void device_register(struct device *, void *); +void device_register_wakeup(struct device *); + +int loadfirmware(const char *name, u_char **bufp, size_t *buflen); +#define FIRMWARE_MAX 24*1024*1024 + +/* compatibility definitions */ +#define config_found(d, a, p) config_found_sm((d), (a), (p), NULL) + +#endif /* _KERNEL */ + +#endif /* !_SYS_DEVICE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/dir.h b/lib/libc/include/generic-openbsd/sys/dir.h new file mode 100644 index 000000000000..ef8bb24002a6 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/dir.h @@ -0,0 +1,65 @@ +/* $OpenBSD: dir.h,v 1.5 2003/06/02 23:28:21 millert Exp $ */ +/* $NetBSD: dir.h,v 1.9 1996/10/27 19:27:54 gwr Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)dir.h 8.2 (Berkeley) 1/4/94 + */ + +/* + * The information in this file should be obtained from + * and is provided solely (and temporarily) for backward compatibility. + */ + +#ifndef _SYS_DIR_H_ +#define _SYS_DIR_H_ + +#ifdef _KERNEL +/* This file should only be used by old user-level code. */ +#error "Please use instead" +#endif + +#include + +/* + * Backwards compatibility. + */ +#define direct dirent + +/* + * The DIRSIZ macro gives the minimum record length which will hold + * the directory entry. This requires the amount of space in struct direct + * without the d_name field, plus enough space for the name with a terminating + * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. + */ +#undef DIRSIZ +#define DIRSIZ(dp) \ + ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) + +#endif /* !_SYS_DIR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/dirent.h b/lib/libc/include/generic-openbsd/sys/dirent.h new file mode 100644 index 000000000000..da231d07bf26 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/dirent.h @@ -0,0 +1,100 @@ +/* $OpenBSD: dirent.h,v 1.11 2013/12/13 18:09:27 zhuk Exp $ */ +/* $NetBSD: dirent.h,v 1.12 1996/04/09 20:55:25 cgd Exp $ */ + +/*- + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)dirent.h 8.3 (Berkeley) 8/10/94 + */ + +#ifndef _SYS_DIRENT_H_ +#define _SYS_DIRENT_H_ + +#include + +/* + * The dirent structure defines the format of directory entries returned by + * the getdents(2) system call. + * + * A directory entry has a struct dirent at the front of it, containing its + * inode number, the length of the entry, and the length of the name + * contained in the entry. These are followed by the name padded to a 4 + * byte boundary with null bytes. All names are guaranteed null terminated. + * The maximum length of a name in a directory is MAXNAMLEN. + */ + +struct dirent { + __ino_t d_fileno; /* file number of entry */ + __off_t d_off; /* offset after this entry */ + __uint16_t d_reclen; /* length of this record */ + __uint8_t d_type; /* file type, see below */ + __uint8_t d_namlen; /* length of string in d_name */ + __uint8_t __d_padding[4]; /* suppress padding after d_name */ +#if __BSD_VISIBLE +#define MAXNAMLEN 255 + char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */ +#else + char d_name[255 + 1]; /* name must be no longer than this */ +#endif +}; + +#if __BSD_VISIBLE +/* + * File types + */ +#define DT_UNKNOWN 0 +#define DT_FIFO 1 +#define DT_CHR 2 +#define DT_DIR 4 +#define DT_BLK 6 +#define DT_REG 8 +#define DT_LNK 10 +#define DT_SOCK 12 + +/* + * Convert between stat structure types and directory types. + */ +#define IFTODT(mode) (((mode) & 0170000) >> 12) +#define DTTOIF(dirtype) ((dirtype) << 12) + +#ifdef _KERNEL +/* + * The DIRENT_RECSIZE macro gives the minimum record length which will hold + * a directory entry with a name of the given length, including the terminating + * nul byte, rounded up to proper alignment. + * The DIRENT_SIZE macro does the same when given a pointer to a struct dirent + */ +#define DIRENT_RECSIZE(namelen) \ + ((offsetof(struct dirent, d_name) + (namelen) + 1 + 7) &~ 7) +#define DIRENT_SIZE(dp) \ + DIRENT_RECSIZE((dp)->d_namlen) +#endif + +#endif /* __BSD_VISIBLE */ + +#endif /* _SYS_DIRENT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/disk.h b/lib/libc/include/generic-openbsd/sys/disk.h new file mode 100644 index 000000000000..08c93668d99c --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/disk.h @@ -0,0 +1,158 @@ +/* $OpenBSD: disk.h,v 1.42 2025/09/15 10:33:03 krw Exp $ */ +/* $NetBSD: disk.h,v 1.11 1996/04/28 20:22:50 thorpej Exp $ */ + +/* + * Copyright (c) 1995 Jason R. Thorpe. All rights reserved. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Header: disk.h,v 1.5 92/11/19 04:33:03 torek Exp (LBL) + * + * @(#)disk.h 8.1 (Berkeley) 6/2/93 + */ + +/* + * Disk device structures. + */ + +#include +#include +#include +#include +#include + +struct disklabel; + +#define DS_DISKNAMELEN 16 + +struct diskstats { + char ds_name[DS_DISKNAMELEN]; + int ds_busy; /* busy counter */ + u_int64_t ds_rxfer; /* total number of read transfers */ + u_int64_t ds_wxfer; /* total number of write transfers */ + u_int64_t ds_seek; /* total independent seek operations */ + u_int64_t ds_rbytes; /* total bytes read */ + u_int64_t ds_wbytes; /* total bytes written */ + struct timeval ds_attachtime; /* time disk was attached */ + struct timeval ds_timestamp; /* time of first busy or any unbusy */ + struct timeval ds_time; /* total time spent busy */ +}; + +struct disk { + TAILQ_ENTRY(disk) dk_link; /* link in global disklist */ + struct rwlock dk_lock; /* disk lock */ + struct mutex dk_mtx; /* busy/unbusy mtx */ + char *dk_name; /* disk name */ + struct device *dk_device; /* disk device structure. */ + dev_t dk_devno; /* disk device number. */ + int dk_flags; /* disk flags */ +#define DKF_CONSTRUCTED 0x0001 +#define DKF_OPENED 0x0002 +#define DKF_NOLABELREAD 0x0004 + + /* + * Metrics data; note that some metrics may have no meaning + * on certain types of disks. + */ + int dk_busy; /* busy counter */ + u_int64_t dk_rxfer; /* total number of read transfers */ + u_int64_t dk_wxfer; /* total number of write transfers */ + u_int64_t dk_seek; /* total independent seek operations */ + u_int64_t dk_rbytes; /* total bytes read */ + u_int64_t dk_wbytes; /* total bytes written */ + struct timeval dk_attachtime; /* time disk was attached */ + struct timeval dk_timestamp; /* time of first busy or any unbusy */ + struct timeval dk_time; /* total time spent busy */ + + uint64_t dk_bopenmask; /* block devices open */ + uint64_t dk_copenmask; /* character devices open */ + uint64_t dk_openmask; /* composite (bopen|copen) */ + int dk_state; /* label state ### */ + int dk_blkshift; /* shift to convert DEV_BSIZE to blks*/ + int dk_byteshift; /* shift to convert bytes to blks */ + + /* + * Disk label information. Storage for the in-core disk label + * must be dynamically allocated, otherwise the size of this + * structure becomes machine-dependent. + */ + struct disklabel *dk_label; +}; + +/* states */ +#define DK_CLOSED 0 /* drive is closed */ +#define DK_WANTOPEN 1 /* drive being opened */ +#define DK_WANTOPENRAW 2 /* drive being opened */ +#define DK_RDLABEL 3 /* label being read */ +#define DK_OPEN 4 /* label read, drive open */ +#define DK_OPENRAW 5 /* open without label */ + +/* Disk map flags. */ +#define DM_OPENPART 0x1 /* Open raw partition. */ +#define DM_OPENBLCK 0x2 /* Open block device. */ + +/* + * disklist_head is defined here so that user-land has access to it. + */ +TAILQ_HEAD(disklist_head, disk); /* the disklist is a TAILQ */ + +#ifdef _KERNEL +extern struct disklist_head disklist; /* list of disks attached to system */ +extern int disk_count; /* number of disks in global disklist */ +extern int disk_change; /* disk attached/detached */ + +void disk_init(void); +int disk_construct(struct disk *); +void disk_attach(struct device *, struct disk *); +void disk_detach(struct disk *); +int disk_openpart(struct disk *, int, int, int); +void disk_closepart(struct disk *, int, int); +void disk_gone(int (*)(dev_t, int, int, struct proc *), int); +void disk_busy(struct disk *); +void disk_unbusy(struct disk *, long, daddr_t, int); + +int disk_lock(struct disk *); +void disk_lock_nointr(struct disk *); +void disk_unlock(struct disk *); +struct device *disk_lookup(struct cfdriver *, int); + +char *disk_readlabel(struct disklabel *, dev_t, char *, size_t); + +int disk_map(const char *, char *, int, int); + +int duid_iszero(u_char *); +const char *duid_format(u_char *); +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/disklabel.h b/lib/libc/include/generic-openbsd/sys/disklabel.h new file mode 100644 index 000000000000..a289bc7479e4 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/disklabel.h @@ -0,0 +1,482 @@ +/* $OpenBSD: disklabel.h,v 1.93 2025/09/17 10:16:09 deraadt Exp $ */ +/* $NetBSD: disklabel.h,v 1.41 1996/05/10 23:07:37 mark Exp $ */ + +/* + * Copyright (c) 1987, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)disklabel.h 8.2 (Berkeley) 7/10/94 + */ + +/* + * Disk description table, see disktab(5) + */ +#define _PATH_DISKTAB "/etc/disktab" +#define DISKTAB "/etc/disktab" /* deprecated */ + +/* + * Each disk has a label which includes information about the hardware + * disk geometry, filesystem partitions, and drive specific information. + * The location of the label, as well as the number of partitions the + * label can describe and the number of the "whole disk" (raw) + * partition are machine dependent. + */ +#include + +#include + +/* + * Translate between device numbers and major/disk unit/disk partition. + */ +#define DISKUNIT(dev) (minor(dev) / MAXPARTITIONS) +#define DISKPART(dev) (minor(dev) % MAXPARTITIONS) +#define RAW_PART 2 /* 'c' partition */ +#define DISKMINOR(unit, part) \ + (((unit) * MAXPARTITIONS) + (part)) +#define MAKEDISKDEV(maj, unit, part) \ + (makedev((maj), DISKMINOR((unit), (part)))) +#define DISKLABELDEV(dev) \ + (MAKEDISKDEV(major(dev), DISKUNIT(dev), RAW_PART)) + +#define DISKMAGIC 0x82564557U /* The disk magic number */ + +#define MAXDISKSIZE 0x7fffffffffffLL /* 47 bits of reach */ + +#ifndef _LOCORE +struct disklabel { + u_int32_t d_magic; /* the magic number */ + u_int16_t d_type; /* drive type */ + u_int16_t d_subtype; /* controller/d_type specific */ + char d_typename[16]; /* type name, e.g. "eagle" */ + char d_packname[16]; /* pack identifier */ + + /* disk geometry: */ + u_int32_t d_secsize; /* # of bytes per sector */ + u_int32_t d_nsectors; /* # of data sectors per track */ + u_int32_t d_ntracks; /* # of tracks per cylinder */ + u_int32_t d_ncylinders; /* # of data cylinders per unit */ + u_int32_t d_secpercyl; /* # of data sectors per cylinder */ + u_int32_t d_secperunit; /* # of data sectors (low part) */ + + u_char d_uid[8]; /* Unique label identifier. */ + + /* + * Alternate cylinders include maintenance, replacement, configuration + * description areas, etc. + */ + u_int32_t d_acylinders; /* # of alt. cylinders per unit */ + + /* hardware characteristics: */ + u_int16_t d_bstarth; /* start of useable region (high part) */ + u_int16_t d_bendh; /* size of useable region (high part) */ + u_int32_t d_bstart; /* start of useable region */ + u_int32_t d_bend; /* end of useable region */ + u_int32_t d_flags; /* generic flags */ +#define NDDATA 5 + u_int32_t d_spare4[NDDATA]; + u_int16_t d_secperunith; /* # of data sectors (high part) */ + u_int16_t d_version; /* version # (1=48 bit addressing) */ +#define NSPARE 4 + u_int32_t d_spare[NSPARE]; /* reserved for future use */ + u_int32_t d_magic2; /* the magic number (again) */ + u_int16_t d_checksum; /* xor of data incl. partitions */ + + /* filesystem and partition information: */ + u_int16_t d_npartitions; /* number of partitions in following */ + u_int32_t d_spare2; + u_int32_t d_spare3; + struct partition { /* the partition table */ + u_int32_t p_size; /* number of sectors (low part) */ + u_int32_t p_offset; /* starting sector (low part) */ + u_int16_t p_offseth; /* starting sector (high part) */ + u_int16_t p_sizeh; /* number of sectors (high part) */ + u_int8_t p_fstype; /* filesystem type, see below */ + u_int8_t p_fragblock; /* encoded filesystem frag/block */ + u_int16_t p_cpg; /* UFS: FS cylinders per group */ + } d_partitions[MAXPARTITIONS]; /* actually may be more */ +}; +#endif /* _LOCORE */ + + +#define DISKLABELV1_FFS_FRAGBLOCK(fsize, frag) \ + ((fsize) * (frag) == 0 ? 0 : \ + (((ffs((fsize) * (frag)) - 13) << 3) | (ffs(frag)))) + +#define DISKLABELV1_FFS_BSIZE(i) ((i) == 0 ? 0 : (1 << (((i) >> 3) + 12))) +#define DISKLABELV1_FFS_FRAG(i) ((i) == 0 ? 0 : (1 << (((i) & 0x07) - 1))) +#define DISKLABELV1_FFS_FSIZE(i) (DISKLABELV1_FFS_FRAG(i) == 0 ? 0 : \ + (DISKLABELV1_FFS_BSIZE(i) / DISKLABELV1_FFS_FRAG(i))) + +#define DL_GETPSIZE(p) (((u_int64_t)(p)->p_sizeh << 32) + (p)->p_size) +#define DL_SETPSIZE(p, n) do { \ + u_int64_t __x = (n); \ + (p)->p_sizeh = __x >> 32; \ + (p)->p_size = __x; \ + } while (0) +#define DL_GETPOFFSET(p) (((u_int64_t)(p)->p_offseth << 32) + (p)->p_offset) +#define DL_SETPOFFSET(p, n) do { \ + u_int64_t __x = (n); \ + (p)->p_offseth = __x >> 32; \ + (p)->p_offset = __x; \ + } while (0) + +#define DL_GETDSIZE(d) (((u_int64_t)(d)->d_secperunith << 32) + \ + (d)->d_secperunit) +#define DL_SETDSIZE(d, n) do { \ + u_int64_t __x = (n); \ + (d)->d_secperunith = __x >> 32; \ + (d)->d_secperunit = __x; \ + } while (0) +#define DL_GETBSTART(d) (((u_int64_t)(d)->d_bstarth << 32) + \ + (d)->d_bstart) +#define DL_SETBSTART(d, n) do { \ + u_int64_t __x = (n); \ + (d)->d_bstarth = __x >> 32; \ + (d)->d_bstart = __x; \ + } while (0) +#define DL_GETBEND(d) (((u_int64_t)(d)->d_bendh << 32) + \ + (d)->d_bend) +#define DL_SETBEND(d, n) do { \ + u_int64_t __x = (n); \ + (d)->d_bendh = __x >> 32; \ + (d)->d_bend = __x; \ + } while (0) + +#define DL_BLKSPERSEC(d) ((d)->d_secsize / DEV_BSIZE) +#define DL_SECTOBLK(d, n) ((n) * DL_BLKSPERSEC(d)) +#define DL_BLKTOSEC(d, n) ((n) / DL_BLKSPERSEC(d)) +#define DL_BLKOFFSET(d, n) (((n) % DL_BLKSPERSEC(d)) * DEV_BSIZE) + +static __inline char +DL_PARTNUM2NAME(int partnum) +{ + if (partnum >= MAXPARTITIONS) + return -1; + if (partnum <= 'z' - 'a') + return 'a' + partnum; + else if (partnum - 26 <= 'Z' - 'A') + return 'A' + partnum - 26; + return -1; +} + +static __inline int +DL_PARTNAME2NUM(char partname) +{ + int partnum = -1; + + if (partname >= 'a' && partname <= 'z') + partnum = partname - 'a'; + else if (partname >= 'A' && partname <= 'Z') + partnum = partname - 'A' + 26; + if (partnum >= MAXPARTITIONS) + partnum = -1; + return partnum; +} + +/* d_type values: */ +#define DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */ +#define DTYPE_MSCP 2 /* MSCP */ +#define DTYPE_DEC 3 /* other DEC (rk, rl) */ +#define DTYPE_SCSI 4 /* SCSI */ +#define DTYPE_ESDI 5 /* ESDI interface */ +#define DTYPE_ST506 6 /* ST506 etc. */ +#define DTYPE_HPIB 7 /* CS/80 on HP-IB */ +#define DTYPE_HPFL 8 /* HP Fiber-link */ +#define DTYPE_FLOPPY 10 /* floppy */ +#define DTYPE_CCD 11 /* was: concatenated disk device */ +#define DTYPE_VND 12 /* vnode pseudo-disk */ +#define DTYPE_ATAPI 13 /* ATAPI */ +#define DTYPE_RAID 14 /* was: RAIDframe */ +#define DTYPE_RDROOT 15 /* ram disk root */ + +#ifdef DKTYPENAMES +static const char * const dktypenames[] = { + "unknown", + "SMD", + "MSCP", + "old DEC", + "SCSI", + "ESDI", + "ST506", + "HP-IB", + "HP-FL", + "type 9", + "floppy", + "ccd", /* deprecated */ + "vnd", + "ATAPI", + "RAID", + "rdroot", + NULL +}; +#define DKMAXTYPES (sizeof(dktypenames) / sizeof(dktypenames[0]) - 1) +#endif + +/* + * Filesystem type and version. + * Used to interpret other filesystem-specific + * per-partition information. + */ +#define FS_UNUSED 0 /* unused */ +#define FS_SWAP 1 /* swap */ +#define FS_V6 2 /* Sixth Edition */ +#define FS_V7 3 /* Seventh Edition */ +#define FS_SYSV 4 /* System V */ +#define FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */ +#define FS_V8 6 /* Eighth Edition, 4K blocks */ +#define FS_BSDFFS 7 /* 4.2BSD fast file system */ +#define FS_MSDOS 8 /* MSDOS file system */ +#define FS_BSDLFS 9 /* 4.4BSD log-structured file system */ +#define FS_OTHER 10 /* in use, but unknown/unsupported */ +#define FS_HPFS 11 /* OS/2 high-performance file system */ +#define FS_ISO9660 12 /* ISO 9660, normally CD-ROM */ +#define FS_BOOT 13 /* partition contains bootstrap */ +#define FS_ADOS 14 /* AmigaDOS fast file system */ +#define FS_HFS 15 /* Macintosh HFS */ +#define FS_ADFS 16 /* Acorn Disk Filing System */ +#define FS_EXT2FS 17 /* ext2fs */ +#define FS_CCD 18 /* ccd component */ +#define FS_RAID 19 /* RAIDframe or softraid */ +#define FS_NTFS 20 /* Windows/NT file system */ +#define FS_UDF 21 /* UDF (DVD) filesystem */ + +#ifdef DKTYPENAMES +static const char * const fstypenames[] = { + "unused", + "swap", + "Version6", + "Version7", + "SystemV", + "4.1BSD", + "Eighth-Edition", + "4.2BSD", + "MSDOS", + "4.4LFS", + "unknown", + "HPFS", + "ISO9660", + "boot", + "ADOS", + "HFS", + "ADFS", + "ext2fs", + "ccd", + "RAID", + "NTFS", + "UDF", + NULL +}; + +/* Similar to the above, but used for things like the mount command. */ +static char *fstypesnames[] = { + "", /* 0 */ + "", /* 1 */ + "", /* 2 */ + "", /* 3 */ + "", /* 4 */ + "", /* 5 */ + "", /* 6 */ + "ffs", /* 7 */ + "msdos", /* 8 */ + "lfs", /* 9 */ + "", /* 10 */ + "", /* 11 */ + "cd9660", /* 12 */ + "", /* 13 */ + "ados", /* 14 */ + "", /* 15 */ + "", /* 16 */ + "ext2fs", /* 17 */ + "", /* 18 */ + "", /* 19 */ + "ntfs", /* 20 */ + "udf", /* 21 */ + NULL +}; + +#define FSMAXTYPES (sizeof(fstypenames) / sizeof(fstypenames[0]) - 1) +#endif + +/* + * flags shared by various drives: + */ +#define D_VENDOR 0x08 /* vendor disklabel */ + +#ifndef _LOCORE +/* + * Structure used internally to retrieve information about a partition + * on a disk. + */ +struct partinfo { + struct disklabel *disklab; + struct partition *part; +}; + +/* GUID partition table -- located at sector 1 of some disks. */ +#define GPTSECTOR 1 /* DOS boot block relative sector # */ +#define GPTSIGNATURE 0x5452415020494645LL + /* ASCII string "EFI PART" encoded as 64-bit */ +#define GPTREVISION 0x10000 /* GPT header version 1.0 */ +#define NGPTPARTITIONS 128 +#define GPTPARTATTR_REQUIRED (1ULL << 0) +#define GPTPARTATTR_IGNORE (1ULL << 1) +#define GPTPARTATTR_BOOTABLE (1ULL << 2) +#define GPTPARTATTR_MS_READONLY (1ULL << 60) +#define GPTPARTATTR_MS_SHADOW (1ULL << 61) +#define GPTPARTATTR_MS_HIDDEN (1ULL << 62) +#define GPTPARTATTR_MS_NOAUTOMOUNT (1ULL << 63) + +#define GPTMINHDRSIZE 92 +#define GPTMINPARTSIZE 128 +#define GPTPARTNAMESIZE 36 + +/* all values in the GPT need to be little endian as per UEFI specification */ +struct gpt_header { + u_int64_t gh_sig; /* "EFI PART" */ + u_int32_t gh_rev; /* GPT Version 1.0: 0x00000100 */ + u_int32_t gh_size; /* Little-Endian */ + u_int32_t gh_csum; /* CRC32: with this field as 0 */ + u_int32_t gh_rsvd; /* always zero */ + u_int64_t gh_lba_self; /* LBA of this header */ + u_int64_t gh_lba_alt; /* LBA of alternate header */ + u_int64_t gh_lba_start; /* first usable LBA */ + u_int64_t gh_lba_end; /* last usable LBA */ + struct uuid gh_guid; /* disk GUID used to identify the disk */ + u_int64_t gh_part_lba; /* starting LBA of GPT partition entries */ + u_int32_t gh_part_num; /* # of partition entries */ + u_int32_t gh_part_size; /* size per entry, shall be 128*(2**n) + with n >= 0 */ + u_int32_t gh_part_csum; /* CRC32 checksum of all partition entries: + * starts at gh_part_lba and is computed over + * a byte length of gh_part_num*gh_part_size */ + /* the rest of the block is reserved by UEFI and must be zero */ +}; + +struct gpt_partition { + struct uuid gp_type; /* partition type GUID */ + struct uuid gp_guid; /* unique partition GUID */ + u_int64_t gp_lba_start; /* starting LBA of this partition */ + u_int64_t gp_lba_end; /* ending LBA of this partition, inclusive, + usually odd */ + u_int64_t gp_attrs; /* attribute flags */ + u_int16_t gp_name[GPTPARTNAMESIZE]; /* partition name, utf-16le */ + /* the rest of the GPT partition entry, if any, is reserved by UEFI + and must be zero */ +}; + +#define GPT_UUID_EFI_SYSTEM \ + { 0xc1, 0x2a, 0x73, 0x28, 0xf8, 0x1f, 0x11, 0xd2, \ + 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b } +#define GPT_UUID_OPENBSD \ + { 0x82, 0x4c, 0xc7, 0xa0, 0x36, 0xa8, 0x11, 0xe3, \ + 0x89, 0x0a, 0x95, 0x25, 0x19, 0xad, 0x3f, 0x61 } + +/* DOS partition table -- located at start of some disks. */ +#define DOS_LABELSECTOR 1 +#define DOSBBSECTOR 0 /* DOS boot block relative sector # */ +#define DOSPARTOFF 446 +#define DOSDISKOFF 444 +#define NDOSPART 4 +#define DOSACTIVE 0x80 /* active partition */ + +#define DOSMBR_SIGNATURE (0xaa55) +#define DOSMBR_SIGNATURE_OFF (0x1fe) + +/* Maximum number of Extended Boot Records (EBRs) to traverse. */ +#define DOS_MAXEBR 256 + +struct dos_partition { + u_int8_t dp_flag; /* bootstrap flags */ + u_int8_t dp_shd; /* starting head */ + u_int8_t dp_ssect; /* starting sector */ + u_int8_t dp_scyl; /* starting cylinder */ + u_int8_t dp_typ; /* partition type (see below) */ + u_int8_t dp_ehd; /* end head */ + u_int8_t dp_esect; /* end sector */ + u_int8_t dp_ecyl; /* end cylinder */ + u_int32_t dp_start; /* absolute starting sector number */ + u_int32_t dp_size; /* partition size in sectors */ +}; + +/* Known DOS partition types. */ +#define DOSPTYP_UNUSED 0x00 /* Unused partition */ +#define DOSPTYP_FAT12 0x01 /* 12-bit FAT */ +#define DOSPTYP_FAT16S 0x04 /* 16-bit FAT, less than 32M */ +#define DOSPTYP_EXTEND 0x05 /* Extended; contains sub-partitions */ +#define DOSPTYP_FAT16B 0x06 /* 16-bit FAT, more than 32M */ +#define DOSPTYP_NTFS 0x07 /* NTFS */ +#define DOSPTYP_FAT32 0x0b /* 32-bit FAT */ +#define DOSPTYP_FAT32L 0x0c /* 32-bit FAT, LBA-mapped */ +#define DOSPTYP_FAT16L 0x0e /* 16-bit FAT, LBA-mapped */ +#define DOSPTYP_EXTENDL 0x0f /* Extended, LBA-mapped; (sub-partitions) */ +#define DOSPTYP_ONTRACK 0x54 +#define DOSPTYP_LINUX 0x83 /* That other thing */ +#define DOSPTYP_FREEBSD 0xa5 /* FreeBSD partition type */ +#define DOSPTYP_OPENBSD 0xa6 /* OpenBSD partition type */ +#define DOSPTYP_NETBSD 0xa9 /* NetBSD partition type */ +#define DOSPTYP_EFI 0xee /* EFI Protective Partition */ +#define DOSPTYP_EFISYS 0xef /* EFI System Partition */ + +struct dos_mbr { + u_int8_t dmbr_boot[DOSPARTOFF]; + struct dos_partition dmbr_parts[NDOSPART]; + u_int16_t dmbr_sign; +} __packed; + +#ifdef _KERNEL +void diskerr(struct buf *, char *, char *, int, int, struct disklabel *); +u_int dkcksum(struct disklabel *); +int initdisklabel(struct disklabel *); +int checkdisklabel(dev_t, void *, struct disklabel *, u_int64_t, u_int64_t); +int setdisklabel(struct disklabel *, struct disklabel *, u_int64_t); +int readdisklabel(dev_t, void (*)(struct buf *), struct disklabel *, int); +int writedisklabel(dev_t, void (*)(struct buf *), struct disklabel *); +int bounds_check_with_label(struct buf *, struct disklabel *); +int readdisksector(struct buf *, void (*)(struct buf *), + struct disklabel *, u_int64_t); +int readdoslabel(struct buf *, void (*)(struct buf *), + struct disklabel *, daddr_t *, int); +#ifdef CD9660 +int iso_disklabelspoof(dev_t dev, void (*strat)(struct buf *), + struct disklabel *lp); +#endif +#ifdef UDF +int udf_disklabelspoof(dev_t dev, void (*strat)(struct buf *), + struct disklabel *lp); +#endif +#endif +#endif /* _LOCORE */ + +#if !defined(_KERNEL) && !defined(_LOCORE) + +#include + +__BEGIN_DECLS +struct disklabel *getdiskbyname(const char *); +__END_DECLS + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/dkio.h b/lib/libc/include/generic-openbsd/sys/dkio.h new file mode 100644 index 000000000000..e283329b75f9 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/dkio.h @@ -0,0 +1,86 @@ +/* $OpenBSD: dkio.h,v 1.13 2025/09/17 10:24:25 deraadt Exp $ */ +/* $NetBSD: dkio.h,v 1.1 1996/01/30 18:21:48 thorpej Exp $ */ + +/* + * Copyright (c) 1987, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _SYS_DKIO_H_ +#define _SYS_DKIO_H_ + +#include + +/* + * Disk-specific ioctls. + */ + /* get and set disklabel; DIOCGPART used internally */ +#define DIOCGDINFO _IOR('d', 101, struct disklabel)/* get */ +#define DIOCSDINFO _IOW('d', 102, struct disklabel)/* set */ +#define DIOCWDINFO _IOW('d', 103, struct disklabel)/* set, update disk */ +#define DIOCGPART _IOW('d', 104, struct partinfo) /* get partition */ + +#define DIOCEJECT _IO('d', 112) /* eject removable disk */ +#define DIOCLOCK _IOW('d', 113, int) /* lock/unlock pack */ + +#define DIOCGPDINFO _IOR('d', 114, struct disklabel)/* get physical */ +#define DIOCRLDINFO _IO('d', 115) /* reload disklabel */ + +#if MAXPARTITIONS != 16 +/* XXX temporary to support the transition to more partitions */ +#define O_sizeof_disklabel (offsetof(struct disklabel, d_partitions[16])) +#define O_DIOCGDINFO _IOC(IOC_OUT, 'd', 101, O_sizeof_disklabel) +#endif + +struct dk_inquiry { + char vendor[64]; + char product[128]; + char revision[64]; + char serial[64]; +}; + +#define DIOCINQ _IOR('d', 116, struct dk_inquiry) + +struct dk_cache { + unsigned int wrcache; + unsigned int rdcache; +}; + +#define DIOCGCACHE _IOR('d', 117, struct dk_cache) /* get cache enabled */ +#define DIOCSCACHE _IOW('d', 118, struct dk_cache) /* set cache enabled */ + +struct dk_diskmap { + char *device; + int fd; + int flags; +}; + +#define DIOCMAP _IOWR('d', 119, struct dk_diskmap) + +#define DIOCCACHESYNC _IOW('d', 120, int) /* sync cache (force?) */ + +#endif /* _SYS_DKIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/domain.h b/lib/libc/include/generic-openbsd/sys/domain.h new file mode 100644 index 000000000000..e33db12f711a --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/domain.h @@ -0,0 +1,74 @@ +/* $OpenBSD: domain.h,v 1.25 2024/10/26 05:39:03 jsg Exp $ */ +/* $NetBSD: domain.h,v 1.10 1996/02/09 18:25:07 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)domain.h 8.1 (Berkeley) 6/2/93 + */ + +/* + * Structure per communications domain. + */ + +#ifndef _SOCKLEN_T_DEFINED_ +#define _SOCKLEN_T_DEFINED_ +typedef __socklen_t socklen_t; /* length type for network syscalls */ +#endif + +/* + * Forward structure declarations for function prototypes [sic]. + */ +struct mbuf; + +struct domain { + int dom_family; /* AF_xxx */ + const char *dom_name; + void (*dom_init)(void); /* initialize domain data structures */ + /* externalize access rights */ + int (*dom_externalize)(struct mbuf *, socklen_t, int); + /* dispose of internalized rights */ + void (*dom_dispose)(struct mbuf *); + const struct protosw *dom_protosw, *dom_protoswNPROTOSW; + /* initialize routing table */ + unsigned int dom_sasize; /* size of sockaddr structure */ + unsigned int dom_rtoffset; /* offset of the key, in bytes */ + unsigned int dom_maxplen; /* maximum prefix length, in bits */ +}; + +#ifdef _KERNEL +void domaininit(void); + +extern const struct domain *const domains[]; +extern const struct domain inet6domain; +extern const struct domain inetdomain; +extern const struct domain mplsdomain; +extern const struct domain pfkeydomain; +extern const struct domain routedomain; +extern const struct domain unixdomain; +#endif /* _KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/endian.h b/lib/libc/include/generic-openbsd/sys/endian.h new file mode 100644 index 000000000000..f4328aa9deae --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/endian.h @@ -0,0 +1,124 @@ +/* $OpenBSD: endian.h,v 1.25 2014/12/21 04:49:00 guenther Exp $ */ + +/*- + * Copyright (c) 1997 Niklas Hallqvist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Public definitions for little- and big-endian systems. + * This file should be included as in userspace and as + * in the kernel. + * + * System headers that need endian information but that can't or don't + * want to export the public names here should include + * and use the internal names: _BYTE_ORDER, _*_ENDIAN, etc. + */ + +#ifndef _SYS_ENDIAN_H_ +#define _SYS_ENDIAN_H_ + +#include +#include + +/* Public names */ +#define LITTLE_ENDIAN _LITTLE_ENDIAN +#define BIG_ENDIAN _BIG_ENDIAN +#define PDP_ENDIAN _PDP_ENDIAN +#define BYTE_ORDER _BYTE_ORDER + + +/* + * These are specified to be function-like macros to match the spec + */ +#define htobe16(x) __htobe16(x) +#define htobe32(x) __htobe32(x) +#define htobe64(x) __htobe64(x) +#define htole16(x) __htole16(x) +#define htole32(x) __htole32(x) +#define htole64(x) __htole64(x) + +/* POSIX names */ +#define be16toh(x) __htobe16(x) +#define be32toh(x) __htobe32(x) +#define be64toh(x) __htobe64(x) +#define le16toh(x) __htole16(x) +#define le32toh(x) __htole32(x) +#define le64toh(x) __htole64(x) + + +#if __BSD_VISIBLE +#define swap16(x) __swap16(x) +#define swap32(x) __swap32(x) +#define swap64(x) __swap64(x) + +#define swap16_multi(v, n) do { \ + __size_t __swap16_multi_n = (n); \ + __uint16_t *__swap16_multi_v = (v); \ + \ + while (__swap16_multi_n) { \ + *__swap16_multi_v = swap16(*__swap16_multi_v); \ + __swap16_multi_v++; \ + __swap16_multi_n--; \ + } \ +} while (0) + +/* original BSD names */ +#define betoh16(x) __htobe16(x) +#define betoh32(x) __htobe32(x) +#define betoh64(x) __htobe64(x) +#define letoh16(x) __htole16(x) +#define letoh32(x) __htole32(x) +#define letoh64(x) __htole64(x) + +#ifndef htons +/* these were exposed here before */ +#define htons(x) __htobe16(x) +#define htonl(x) __htobe32(x) +#define ntohs(x) __htobe16(x) +#define ntohl(x) __htobe32(x) +#endif + +/* ancient stuff */ +#define NTOHL(x) (x) = ntohl((u_int32_t)(x)) +#define NTOHS(x) (x) = ntohs((u_int16_t)(x)) +#define HTONL(x) (x) = htonl((u_int32_t)(x)) +#define HTONS(x) (x) = htons((u_int16_t)(x)) +#endif /* __BSD_VISIBLE */ + +#ifdef _KERNEL +/* to/from memory conversions */ +#define bemtoh16 __bemtoh16 +#define bemtoh32 __bemtoh32 +#define bemtoh64 __bemtoh64 +#define htobem16 __htobem16 +#define htobem32 __htobem32 +#define htobem64 __htobem64 +#define lemtoh16 __lemtoh16 +#define lemtoh32 __lemtoh32 +#define lemtoh64 __lemtoh64 +#define htolem16 __htolem16 +#define htolem32 __htolem32 +#define htolem64 __htolem64 +#endif /* _KERNEL */ + +#endif /* _SYS_ENDIAN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/errno.h b/lib/libc/include/generic-openbsd/sys/errno.h new file mode 100644 index 000000000000..220cdf23f615 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/errno.h @@ -0,0 +1,182 @@ +/* $OpenBSD: errno.h,v 1.25 2017/09/05 03:06:26 jsg Exp $ */ +/* $NetBSD: errno.h,v 1.10 1996/01/20 01:33:53 jtc Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)errno.h 8.5 (Berkeley) 1/21/94 + */ + +#include + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* Input/output error */ +#define ENXIO 6 /* Device not configured */ +#define E2BIG 7 /* Argument list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file descriptor */ +#define ECHILD 10 /* No child processes */ +#define EDEADLK 11 /* Resource deadlock avoided */ + /* 11 was EAGAIN */ +#define ENOMEM 12 /* Cannot allocate memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#if __BSD_VISIBLE +#define ENOTBLK 15 /* Block device required */ +#endif +#define EBUSY 16 /* Device busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* Operation not supported by device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* Too many open files in system */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Inappropriate ioctl for device */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ + +/* math software */ +#define EDOM 33 /* Numerical argument out of domain */ +#define ERANGE 34 /* Result too large */ + +/* non-blocking and interrupt i/o */ +#define EAGAIN 35 /* Resource temporarily unavailable */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define EINPROGRESS 36 /* Operation now in progress */ +#define EALREADY 37 /* Operation already in progress */ + +/* ipc/network software -- argument errors */ +#define ENOTSOCK 38 /* Socket operation on non-socket */ +#define EDESTADDRREQ 39 /* Destination address required */ +#define EMSGSIZE 40 /* Message too long */ +#define EPROTOTYPE 41 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 42 /* Protocol not available */ +#define EPROTONOSUPPORT 43 /* Protocol not supported */ +#if __BSD_VISIBLE +#define ESOCKTNOSUPPORT 44 /* Socket type not supported */ +#endif +#define EOPNOTSUPP 45 /* Operation not supported */ +#if __BSD_VISIBLE +#define EPFNOSUPPORT 46 /* Protocol family not supported */ +#endif +#define EAFNOSUPPORT 47 /* Address family not supported by protocol family */ +#define EADDRINUSE 48 /* Address already in use */ +#define EADDRNOTAVAIL 49 /* Can't assign requested address */ + +/* ipc/network software -- operational errors */ +#define ENETDOWN 50 /* Network is down */ +#define ENETUNREACH 51 /* Network is unreachable */ +#define ENETRESET 52 /* Network dropped connection on reset */ +#define ECONNABORTED 53 /* Software caused connection abort */ +#define ECONNRESET 54 /* Connection reset by peer */ +#define ENOBUFS 55 /* No buffer space available */ +#define EISCONN 56 /* Socket is already connected */ +#define ENOTCONN 57 /* Socket is not connected */ +#if __BSD_VISIBLE +#define ESHUTDOWN 58 /* Can't send after socket shutdown */ +#define ETOOMANYREFS 59 /* Too many references: can't splice */ +#endif /* __BSD_VISIBLE */ +#define ETIMEDOUT 60 /* Operation timed out */ +#define ECONNREFUSED 61 /* Connection refused */ + +#define ELOOP 62 /* Too many levels of symbolic links */ +#define ENAMETOOLONG 63 /* File name too long */ + +/* should be rearranged */ +#if __BSD_VISIBLE +#define EHOSTDOWN 64 /* Host is down */ +#endif /* __BSD_VISIBLE */ +#define EHOSTUNREACH 65 /* No route to host */ +#define ENOTEMPTY 66 /* Directory not empty */ + +/* quotas & mush */ +#if __BSD_VISIBLE +#define EPROCLIM 67 /* Too many processes */ +#define EUSERS 68 /* Too many users */ +#endif /* __BSD_VISIBLE */ +#define EDQUOT 69 /* Disk quota exceeded */ + +/* Network File System */ +#define ESTALE 70 /* Stale NFS file handle */ +#if __BSD_VISIBLE +#define EREMOTE 71 /* Too many levels of remote in path */ +#define EBADRPC 72 /* RPC struct is bad */ +#define ERPCMISMATCH 73 /* RPC version wrong */ +#define EPROGUNAVAIL 74 /* RPC program not available */ +#define EPROGMISMATCH 75 /* Program version wrong */ +#define EPROCUNAVAIL 76 /* Bad procedure for program */ +#endif /* __BSD_VISIBLE */ + +#define ENOLCK 77 /* No locks available */ +#define ENOSYS 78 /* Function not implemented */ + +#if __BSD_VISIBLE +#define EFTYPE 79 /* Inappropriate file type or format */ +#define EAUTH 80 /* Authentication error */ +#define ENEEDAUTH 81 /* Need authenticator */ +#define EIPSEC 82 /* IPsec processing failure */ +#define ENOATTR 83 /* Attribute not found */ +#endif /* __BSD_VISIBLE */ +#define EILSEQ 84 /* Illegal byte sequence */ +#if __BSD_VISIBLE +#define ENOMEDIUM 85 /* No medium found */ +#define EMEDIUMTYPE 86 /* Wrong medium type */ +#endif /* __BSD_VISIBLE */ +#define EOVERFLOW 87 /* Value too large to be stored in data type */ +#define ECANCELED 88 /* Operation canceled */ +#define EIDRM 89 /* Identifier removed */ +#define ENOMSG 90 /* No message of desired type */ +#define ENOTSUP 91 /* Not supported */ +#define EBADMSG 92 /* Bad message */ +#define ENOTRECOVERABLE 93 /* State not recoverable */ +#define EOWNERDEAD 94 /* Previous owner died */ +#define EPROTO 95 /* Protocol error */ +#if __BSD_VISIBLE +#define ELAST 95 /* Must be equal largest errno */ +#endif /* __BSD_VISIBLE */ + +#ifdef _KERNEL +/* pseudo-errors returned inside kernel to modify return to process */ +#define ERESTART -1 /* restart syscall */ +#define EJUSTRETURN -2 /* don't modify regs, just return */ +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/evcount.h b/lib/libc/include/generic-openbsd/sys/evcount.h new file mode 100644 index 000000000000..fa3d1e40cd87 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/evcount.h @@ -0,0 +1,56 @@ +/* $OpenBSD: evcount.h,v 1.4 2022/11/10 07:05:41 jmatthew Exp $ */ +/* + * Copyright (c) 2004 Artur Grabowski + * Copyright (c) 2004 Aaron Campbell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __SYS_EVCOUNT_H__ +#define __SYS_EVCOUNT_H__ + +#ifdef _KERNEL + +#include + +struct cpumem; + +struct evcount { + u_int64_t ec_count; /* main counter */ + int ec_id; /* counter ID */ + const char *ec_name; /* counter name */ + void *ec_data; /* user data */ + struct cpumem *ec_percpu; /* per-cpu counter */ + + TAILQ_ENTRY(evcount) next; +}; + +void evcount_attach(struct evcount *, const char *, void *); +void evcount_detach(struct evcount *); +void evcount_inc(struct evcount *); +void evcount_init_percpu(void); +void evcount_percpu(struct evcount *); +int evcount_sysctl(int *, u_int, void *, size_t *, void *, size_t); + +#endif /* _KERNEL */ + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/event.h b/lib/libc/include/generic-openbsd/sys/event.h new file mode 100644 index 000000000000..4235efa23b74 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/event.h @@ -0,0 +1,395 @@ +/* $OpenBSD: event.h,v 1.74 2025/05/10 09:44:39 visa Exp $ */ + +/*- + * Copyright (c) 1999,2000,2001 Jonathan Lemon + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/sys/event.h,v 1.11 2001/02/24 01:41:31 jlemon Exp $ + */ + +#ifndef _SYS_EVENT_H_ +#define _SYS_EVENT_H_ + +#define EVFILT_READ (-1) +#define EVFILT_WRITE (-2) +#define EVFILT_AIO (-3) /* attached to aio requests */ +#define EVFILT_VNODE (-4) /* attached to vnodes */ +#define EVFILT_PROC (-5) /* attached to struct process */ +#define EVFILT_SIGNAL (-6) /* attached to struct process */ +#define EVFILT_TIMER (-7) /* timers */ +#define EVFILT_DEVICE (-8) /* devices */ +#define EVFILT_EXCEPT (-9) /* exceptional conditions */ +#define EVFILT_USER (-10) /* user event */ + +#define EVFILT_SYSCOUNT 10 + +#define EV_SET(kevp, a, b, c, d, e, f) do { \ + struct kevent *__kevp = (kevp); \ + (__kevp)->ident = (a); \ + (__kevp)->filter = (b); \ + (__kevp)->flags = (c); \ + (__kevp)->fflags = (d); \ + (__kevp)->data = (e); \ + (__kevp)->udata = (f); \ +} while(0) + +struct kevent { + __uintptr_t ident; /* identifier for this event */ + short filter; /* filter for event */ + unsigned short flags; /* action flags for kqueue */ + unsigned int fflags; /* filter flag value */ + __int64_t data; /* filter data value */ + void *udata; /* opaque user data identifier */ +}; + +/* actions */ +#define EV_ADD 0x0001 /* add event to kq (implies enable) */ +#define EV_DELETE 0x0002 /* delete event from kq */ +#define EV_ENABLE 0x0004 /* enable event */ +#define EV_DISABLE 0x0008 /* disable event (not reported) */ + +/* flags */ +#define EV_ONESHOT 0x0010 /* only report one occurrence */ +#define EV_CLEAR 0x0020 /* clear event state after reporting */ +#define EV_RECEIPT 0x0040 /* force EV_ERROR on success, data=0 */ +#define EV_DISPATCH 0x0080 /* disable event after reporting */ + +#define EV_SYSFLAGS 0xf800 /* reserved by system */ +#define EV_FLAG1 0x2000 /* filter-specific flag */ + +/* returned values */ +#define EV_EOF 0x8000 /* EOF detected */ +#define EV_ERROR 0x4000 /* error, data contains errno */ + +/* + * data/hint flags for EVFILT_{READ|WRITE}, shared with userspace + */ +#define NOTE_LOWAT 0x0001 /* low water mark */ +#define NOTE_EOF 0x0002 /* return on EOF */ + +/* + * data/hint flags for EVFILT_EXCEPT, shared with userspace and with + * EVFILT_{READ|WRITE} + */ +#define NOTE_OOB 0x0004 /* OOB data on a socket */ + +/* + * data/hint flags for EVFILT_VNODE, shared with userspace + */ +#define NOTE_DELETE 0x0001 /* vnode was removed */ +#define NOTE_WRITE 0x0002 /* data contents changed */ +#define NOTE_EXTEND 0x0004 /* size increased */ +#define NOTE_ATTRIB 0x0008 /* attributes changed */ +#define NOTE_LINK 0x0010 /* link count changed */ +#define NOTE_RENAME 0x0020 /* vnode was renamed */ +#define NOTE_REVOKE 0x0040 /* vnode access was revoked */ +#define NOTE_TRUNCATE 0x0080 /* vnode was truncated */ + +/* + * data/hint flags for EVFILT_PROC, shared with userspace + */ +#define NOTE_EXIT 0x80000000 /* process exited */ +#define NOTE_FORK 0x40000000 /* process forked */ +#define NOTE_EXEC 0x20000000 /* process exec'd */ +#define NOTE_PCTRLMASK 0xf0000000 /* mask for hint bits */ +#define NOTE_PDATAMASK 0x000fffff /* mask for pid */ + +/* additional flags for EVFILT_PROC */ +#define NOTE_TRACK 0x00000001 /* follow across forks */ +#define NOTE_TRACKERR 0x00000002 /* could not track child */ +#define NOTE_CHILD 0x00000004 /* am a child process */ + +/* data/hint flags for EVFILT_DEVICE, shared with userspace */ +#define NOTE_CHANGE 0x00000001 /* device change event */ + +/* additional flags for EVFILT_TIMER */ +#define NOTE_MSECONDS 0x00000000 /* data is milliseconds */ +#define NOTE_SECONDS 0x00000001 /* data is seconds */ +#define NOTE_USECONDS 0x00000002 /* data is microseconds */ +#define NOTE_NSECONDS 0x00000003 /* data is nanoseconds */ +#define NOTE_ABSTIME 0x00000010 /* timeout is absolute */ + +/* + * data/hint flags for EVFILT_USER, shared with userspace + */ +#define NOTE_FFNOP 0x00000000 /* ignore input fflags */ +#define NOTE_FFAND 0x40000000 /* AND fflags */ +#define NOTE_FFOR 0x80000000 /* OR fflags */ +#define NOTE_FFCOPY 0xc0000000 /* copy fflags */ + +#define NOTE_FFCTRLMASK 0xc0000000 /* masks for operations */ +#define NOTE_FFLAGSMASK 0x00ffffff + +#define NOTE_TRIGGER 0x01000000 /* trigger the event */ + +/* + * This is currently visible to userland to work around broken + * programs which pull in or . + */ +#include + +struct klistops; +struct knote; +SLIST_HEAD(knlist, knote); + +struct klist { + struct knlist kl_list; + const struct klistops *kl_ops; + void *kl_arg; +}; + +#ifdef _KERNEL + +/* kernel-only flags */ +#define __EV_SELECT 0x0800 /* match behavior of select */ +#define __EV_POLL 0x1000 /* match behavior of poll */ +#define __EV_HUP EV_FLAG1 /* device or socket disconnected */ + +#define EVFILT_MARKER 0xf /* placemarker for tailq */ + +/* + * hint flag for in-kernel use - must not equal any existing note + */ +#define NOTE_SUBMIT 0x01000000 /* initial knote submission */ + +#define KN_HASHSIZE 64 /* XXX should be tunable */ + +/* + * Flag indicating hint is a signal. Used by EVFILT_SIGNAL, and also + * shared by EVFILT_PROC (all knotes attached to p->p_klist) + */ +#define NOTE_SIGNAL 0x08000000 + +/* + * = Event filter interface + * + * == .f_flags + * + * Defines properties of the event filter: + * + * - FILTEROP_ISFD Each knote of this filter is associated + * with a file descriptor. + * + * - FILTEROP_MPSAFE The kqueue subsystem can invoke .f_attach(), + * .f_detach(), .f_modify() and .f_process() without + * the kernel lock. + * + * == .f_attach() + * + * Attaches the knote to the object. + * + * == .f_detach() + * + * Detaches the knote from the object. The object must not use this knote + * for delivering events after this callback has returned. + * + * == .f_event() + * + * Notifies the filter about an event. Called through knote(). + * + * == .f_modify() + * + * Modifies the knote with new state from the user. + * + * Returns non-zero if the knote has become active. + * + * == .f_process() + * + * Checks if the event is active and returns non-zero if the event should be + * returned to the user. + * + * If kev is non-NULL and the event is active, the callback should store + * the event's state in kev for delivery to the user. + * + * == Concurrency control + * + * The kqueue subsystem serializes calls of .f_attach(), .f_detach(), + * .f_modify() and .f_process(). + */ + +#define FILTEROP_ISFD 0x00000001 /* ident == filedescriptor */ +#define FILTEROP_MPSAFE 0x00000002 /* safe without kernel lock */ + +struct filterops { + int f_flags; + int (*f_attach)(struct knote *kn); + void (*f_detach)(struct knote *kn); + int (*f_event)(struct knote *kn, long hint); + int (*f_modify)(struct kevent *kev, struct knote *kn); + int (*f_process)(struct knote *kn, struct kevent *kev); +}; + +/* + * Locking: + * I immutable after creation + * o object lock + * q kn_kq->kq_lock + */ +struct knote { + SLIST_ENTRY(knote) kn_link; /* for fd */ + SLIST_ENTRY(knote) kn_selnext; /* for struct selinfo */ + TAILQ_ENTRY(knote) kn_tqe; + struct kqueue *kn_kq; /* [I] which queue we are on */ + struct kevent kn_kevent; + int kn_status; /* [q] */ + int kn_sfflags; /* [o] saved filter flags */ + __int64_t kn_sdata; /* [o] saved data field */ + union { + struct file *p_fp; /* file data pointer */ + struct process *p_process; /* process pointer */ + int p_useract; /* user event active */ + } kn_ptr; + const struct filterops *kn_fop; + void *kn_hook; /* [o] */ + unsigned int kn_pollid; /* [I] */ + +#define KN_ACTIVE 0x0001 /* event has been triggered */ +#define KN_QUEUED 0x0002 /* event is on queue */ +#define KN_DISABLED 0x0004 /* event is disabled */ +#define KN_DETACHED 0x0008 /* knote is detached */ +#define KN_PROCESSING 0x0010 /* knote is being processed */ +#define KN_WAITING 0x0020 /* waiting on processing */ + +#define kn_id kn_kevent.ident /* [I] */ +#define kn_filter kn_kevent.filter /* [I] */ +#define kn_flags kn_kevent.flags /* [o] */ +#define kn_fflags kn_kevent.fflags /* [o] */ +#define kn_data kn_kevent.data /* [o] */ +#define kn_udata kn_kevent.udata /* [o] */ +#define kn_fp kn_ptr.p_fp /* [o] */ +}; + +struct klistops { + void (*klo_assertlk)(void *); + int (*klo_lock)(void *); + void (*klo_unlock)(void *, int); +}; + +struct kqueue_scan_state { + struct kqueue *kqs_kq; /* kqueue of this scan */ + struct knote kqs_start; /* start marker */ + struct knote kqs_end; /* end marker */ + int kqs_nevent; /* number of events collected */ + int kqs_queued; /* if set, end marker is + * in queue */ +}; + +struct mutex; +struct proc; +struct rwlock; +struct timespec; + +extern const struct filterops dead_filtops; + +extern void kqpoll_init(unsigned int); +extern void kqpoll_done(unsigned int); +extern void kqpoll_exit(void); +extern void knote(struct klist *list, long hint); +extern void knote_locked(struct klist *list, long hint); +extern void knote_fdclose(struct proc *p, int fd); +extern void knote_processexit(struct process *); +extern void knote_processfork(struct process *, pid_t); +extern void knote_assign(const struct kevent *, struct knote *); +extern void knote_submit(struct knote *, struct kevent *); +extern void kqueue_init(void); +extern void kqueue_init_percpu(void); +extern int kqueue_register(struct kqueue *kq, struct kevent *kev, + unsigned int pollid, struct proc *p); +extern int kqueue_scan(struct kqueue_scan_state *, int, struct kevent *, + struct timespec *, struct proc *, int *); +extern void kqueue_scan_setup(struct kqueue_scan_state *, struct kqueue *); +extern void kqueue_scan_finish(struct kqueue_scan_state *); +extern int filt_seltrue(struct knote *kn, long hint); +extern int seltrue_kqfilter(dev_t, struct knote *); +extern void klist_init(struct klist *, const struct klistops *, void *); +extern void klist_init_mutex(struct klist *, struct mutex *); +extern void klist_init_rwlock(struct klist *, struct rwlock *); +extern void klist_free(struct klist *); +extern void klist_insert(struct klist *, struct knote *); +extern void klist_insert_locked(struct klist *, struct knote *); +extern void klist_remove(struct klist *, struct knote *); +extern void klist_remove_locked(struct klist *, struct knote *); +extern void klist_invalidate(struct klist *); + +static inline int +knote_modify_fn(const struct kevent *kev, struct knote *kn, + int (*f_event)(struct knote *, long)) +{ + knote_assign(kev, kn); + return ((*f_event)(kn, 0)); +} + +static inline int +knote_modify(const struct kevent *kev, struct knote *kn) +{ + return (knote_modify_fn(kev, kn, kn->kn_fop->f_event)); +} + +static inline int +knote_process_fn(struct knote *kn, struct kevent *kev, + int (*f_event)(struct knote *, long)) +{ + int active; + + /* + * If called from kqueue_scan(), skip f_event + * when EV_ONESHOT is set, to preserve old behaviour. + */ + if (kev != NULL && (kn->kn_flags & EV_ONESHOT)) + active = 1; + else + active = (*f_event)(kn, 0); + if (active) + knote_submit(kn, kev); + return (active); +} + +static inline int +knote_process(struct knote *kn, struct kevent *kev) +{ + return (knote_process_fn(kn, kev, kn->kn_fop->f_event)); +} + +static inline int +klist_empty(struct klist *klist) +{ + return (SLIST_EMPTY(&klist->kl_list)); +} + +#else /* !_KERNEL */ + +#include +struct timespec; + +__BEGIN_DECLS +int kqueue(void); +int kqueue1(int flags); +int kevent(int kq, const struct kevent *changelist, int nchanges, + struct kevent *eventlist, int nevents, + const struct timespec *timeout); +__END_DECLS + +#endif /* !_KERNEL */ + +#endif /* !_SYS_EVENT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/eventvar.h b/lib/libc/include/generic-openbsd/sys/eventvar.h new file mode 100644 index 000000000000..4a6ad517fe68 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/eventvar.h @@ -0,0 +1,74 @@ +/* $OpenBSD: eventvar.h,v 1.17 2022/07/09 12:48:21 visa Exp $ */ + +/*- + * Copyright (c) 1999,2000 Jonathan Lemon + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/sys/eventvar.h,v 1.3 2000/05/26 02:06:54 jake Exp $ + */ + +#ifndef _SYS_EVENTVAR_H_ +#define _SYS_EVENTVAR_H_ + +#include +#include +#include + +#define KQ_NEVENTS 8 /* minimize copy{in,out} calls */ +#define KQEXTENT 256 /* linear growth by this amount */ + +/* + * Locking: + * I immutable after creation + * L kqueue_klist_lock + * a atomic operations + * q kq_lock + */ +struct kqueue { + struct mutex kq_lock; /* lock for queue access */ + TAILQ_HEAD(, knote) kq_head; /* [q] list of pending event */ + int kq_count; /* [q] # of pending events */ + struct refcnt kq_refcnt; /* [a] # of references */ + struct klist kq_klist; /* [L] knotes of other kqs */ + struct filedesc *kq_fdp; /* [I] fd table of this kq */ + + LIST_ENTRY(kqueue) kq_next; + + u_int kq_nknotes; /* [q] # of registered knotes */ + + int kq_knlistsize; /* [q] size of kq_knlist */ + struct knlist *kq_knlist; /* [q] list of + * attached knotes */ + u_long kq_knhashmask; /* [q] size of kq_knhash */ + struct knlist *kq_knhash; /* [q] hash table for + * attached knotes */ + struct task kq_task; /* deferring of activation */ + + int kq_state; /* [q] */ +#define KQ_SLEEP 0x02 +#define KQ_DYING 0x04 +#define KQ_TASK 0x08 +}; + +#endif /* !_SYS_EVENTVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/exec.h b/lib/libc/include/generic-openbsd/sys/exec.h new file mode 100644 index 000000000000..368dde8a3630 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/exec.h @@ -0,0 +1,246 @@ +/* $OpenBSD: exec.h,v 1.57 2025/05/24 06:49:16 deraadt Exp $ */ +/* $NetBSD: exec.h,v 1.59 1996/02/09 18:25:09 christos Exp $ */ + +/*- + * Copyright (c) 1994 Christopher G. Demetriou + * Copyright (c) 1993 Theo de Raadt + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)exec.h 8.3 (Berkeley) 1/21/94 + */ + +#ifndef _SYS_EXEC_H_ +#define _SYS_EXEC_H_ + +/* + * The following structure is found at the top of the user stack of each + * user process. The ps program uses it to locate argv and environment + * strings. Programs that wish ps to display other information may modify + * it; normally ps_argvstr points to argv[0], and ps_nargvstr is the same + * as the program's argc. The fields ps_envstr and ps_nenvstr are the + * equivalent for the environment. + */ +struct ps_strings { + char **ps_argvstr; /* first of 0 or more argument strings */ + int ps_nargvstr; /* the number of argument strings */ + char **ps_envstr; /* first of 0 or more environment strings */ + int ps_nenvstr; /* the number of environment strings */ +}; + +/* + * the following structures allow execve() to put together processes + * in a more extensible and cleaner way. + * + * the exec_package struct defines an executable being execve()'d. + * it contains the header, the vmspace-building commands, the vnode + * information, and the arguments associated with the newly-execve'd + * process. + * + * the exec_vmcmd struct defines a command description to be used + * in creating the new process's vmspace. + */ + +struct proc; +struct exec_package; + +typedef int (*exec_makecmds_fcn)(struct proc *, struct exec_package *); + +struct execsw { + u_int es_hdrsz; /* size of header for this format */ + exec_makecmds_fcn es_check; /* function to check exec format */ +}; + +struct exec_vmcmd { + int (*ev_proc)(struct proc *p, struct exec_vmcmd *cmd); + /* procedure to run for region of vmspace */ + u_long ev_len; /* length of the segment to map */ + u_long ev_addr; /* address in the vmspace to place it at */ + struct vnode *ev_vp; /* vnode pointer for the file w/the data */ + u_long ev_offset; /* offset in the file for the data */ + u_int ev_prot; /* protections for segment */ + int ev_flags; +#define VMCMD_RELATIVE 0x0001 /* ev_addr is relative to base entry */ +#define VMCMD_BASE 0x0002 /* marks a base entry */ +#define VMCMD_STACK 0x0004 /* create with UVM_FLAG_STACK */ +#define VMCMD_IMMUTABLE 0x0010 /* create with UVM_ET_IMMUTABLE */ +#define VMCMD_TEXTREL 0x0020 /* terrible binary contains terrible textrel */ +}; + +#define EXEC_DEFAULT_VMCMD_SETSIZE 12 /* # of cmds in set to start */ + +/* exec vmspace-creation command set; see below */ +struct exec_vmcmd_set { + u_int evs_cnt; + u_int evs_used; + struct exec_vmcmd *evs_cmds; + struct exec_vmcmd evs_start[EXEC_DEFAULT_VMCMD_SETSIZE]; +}; + +struct elf_args; +struct exec_package { + char *ep_name; /* file's name */ + void *ep_hdr; /* file's exec header */ + u_int ep_hdrlen; /* length of ep_hdr */ + u_int ep_hdrvalid; /* bytes of ep_hdr that are valid */ + struct nameidata *ep_ndp; /* namei data pointer for lookups */ + struct exec_vmcmd_set ep_vmcmds; /* vmcmds used to build vmspace */ + struct vnode *ep_vp; /* executable's vnode */ + struct vattr *ep_vap; /* executable's attributes */ + u_long ep_taddr; /* process's text address */ + u_long ep_tsize; /* size of process's text */ + u_long ep_daddr; /* process's data(+bss) address */ + u_long ep_dsize; /* size of process's data(+bss) */ + u_long ep_maxsaddr; /* proc's max stack addr ("top") */ + u_long ep_minsaddr; /* proc's min stack addr ("bottom") */ + u_long ep_ssize; /* size of process's stack */ + u_long ep_entry; /* process's entry point */ + u_int ep_flags; /* flags; see below. */ + char **ep_fa; /* a fake args vector for scripts */ + int ep_fd; /* a file descriptor we're holding */ + struct elf_args *ep_args; /* ELF info */ + void *ep_auxinfo; /* userspace auxinfo address */ + char *ep_interp; /* name of interpreter if any */ + vaddr_t ep_pinstart, ep_pinend; /* executable region */ + u_int *ep_pins; /* array of system call offsets */ + int ep_npins; /* entries in array */ +}; +#define EXEC_INDIR 0x0001 /* script handling already done */ +#define EXEC_HASFD 0x0002 /* holding a shell script */ +#define EXEC_HASARGL 0x0004 /* has fake args vector */ +#define EXEC_SKIPARG 0x0008 /* don't copy user-supplied argv[0] */ +#define EXEC_DESTR 0x0010 /* destructive ops performed */ +#define EXEC_WXNEEDED 0x0020 /* executable will violate W^X */ +#define EXEC_NOBTCFI 0x0040 /* no branch target CFI */ +#define EXEC_PROFILE 0x0080 /* profiled binary */ + +#ifdef _KERNEL +/* + * functions used either by execve() or the various cpu-dependent execve() + * hooks. + */ +void vmcmdset_extend(struct exec_vmcmd_set *); +void kill_vmcmds(struct exec_vmcmd_set *evsp); +int vmcmd_map_pagedvn(struct proc *, struct exec_vmcmd *); +int vmcmd_map_readvn(struct proc *, struct exec_vmcmd *); +int vmcmd_map_zero(struct proc *, struct exec_vmcmd *); +int vmcmd_mutable(struct proc *, struct exec_vmcmd *); +int vmcmd_randomize(struct proc *, struct exec_vmcmd *); +int copyargs(struct exec_package *, struct ps_strings *, void *, void *); +void setregs(struct proc *, struct exec_package *, u_long, + struct ps_strings *); +int check_exec(struct proc *, struct exec_package *); +int exec_setup_stack(struct proc *, struct exec_package *); +int exec_process_vmcmds(struct proc *, struct exec_package *); + +void new_vmcmd(struct exec_vmcmd_set *evsp, + int (*proc)(struct proc *p, struct exec_vmcmd *), + u_long len, u_long addr, struct vnode *vp, u_long offset, + u_int prot, int flags); +#define NEW_VMCMD(evsp,proc,len,addr,vp,offset,prot) \ + new_vmcmd(evsp,proc,len,addr,vp,offset,prot, 0); +#define NEW_VMCMD2(evsp,proc,len,addr,vp,offset,prot,flags) \ + new_vmcmd(evsp,proc,len,addr,vp,offset,prot,flags) + +/* Initialize an empty vmcmd set */ +#define VMCMDSET_INIT(vmc) do { \ + (vmc)->evs_cnt = EXEC_DEFAULT_VMCMD_SETSIZE; \ + (vmc)->evs_cmds = (vmc)->evs_start; \ + (vmc)->evs_used = 0; \ +} while (0) + +/* + * Exec function switch: + * + * Note that each makecmds function is responsible for loading the + * exec package with the necessary functions for any exec-type-specific + * handling. + * + * Functions for specific exec types should be defined in their own + * header file. + */ +extern const struct execsw execsw[]; +extern int nexecs; +extern int exec_maxhdrsz; + +/* + * If non-zero, stackgap_random specifies the upper limit of the random gap size + * added to the fixed stack position. Must be n^2. + */ +extern int stackgap_random; + +/* Limit on total PT_OPENBSD_RANDOMIZE bytes. */ +#define ELF_RANDOMIZE_LIMIT 1024*1024 + +#endif /* _KERNEL */ + +/* + * a_mid - keep sorted in numerical order for sanity's sake + * ensure that: 0 < mid < 0x3ff + */ +#define MID_ZERO 0 /* unknown - implementation dependent */ +#define MID_SUN010 1 /* sun 68010/68020 binary */ +#define MID_SUN020 2 /* sun 68020-only binary */ +#define MID_PC386 100 /* 386 PC binary. (so quoth BFD) */ +#define MID_ROMPAOS 104 /* old IBM RT */ +#define MID_I386 134 /* i386 BSD binary */ +#define MID_M68K 135 /* m68k BSD binary with 8K page sizes */ +#define MID_M68K4K 136 /* DO NOT USE: m68k BSD binary with 4K page sizes */ +#define MID_NS32532 137 /* ns32532 */ +#define MID_SPARC 138 /* sparc */ +#define MID_PMAX 139 /* pmax */ +#define MID_VAX1K 140 /* vax 1k page size */ +#define MID_ALPHA 141 /* Alpha BSD binary */ +#define MID_MIPS 142 /* big-endian MIPS */ +#define MID_ARM6 143 /* ARM6 */ +#define MID_SH3 145 /* SH3 */ +#define MID_POWERPC 149 /* big-endian PowerPC */ +#define MID_VAX 150 /* vax */ +#define MID_SPARC64 151 /* LP64 sparc */ +#define MID_MIPS2 152 /* MIPS2 */ +#define MID_M88K 153 /* m88k BSD binary */ +#define MID_HPPA 154 /* hppa */ +#define MID_AMD64 157 /* AMD64 */ +#define MID_MIPS64 158 /* big-endian MIPS64 */ +#define MID_ARM64 159 /* ARM64 */ +#define MID_POWERPC64 160 /* big-endian 64-bit PowerPC */ +#define MID_RISCV64 161 /* Little-endian 64-bit RISC-V */ +#define MID_HP200 200 /* hp200 (68010) BSD binary */ +#define MID_HP300 300 /* hp300 (68020+68881) BSD binary */ +#define MID_HPUX 0x20C /* hp200/300 HP-UX binary */ +#define MID_HPUX800 0x20B /* hp800 HP-UX binary pa1.0 */ +#define MID_HPPA11 0x210 /* hp700 HP-UX binary pa1.1 */ +#define MID_HPPA20 0x214 /* hp700 HP-UX binary pa2.0 */ + +#include + +#endif /* !_SYS_EXEC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/exec_elf.h b/lib/libc/include/generic-openbsd/sys/exec_elf.h new file mode 100644 index 000000000000..2d39ed037dd2 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/exec_elf.h @@ -0,0 +1,843 @@ +/* $OpenBSD: exec_elf.h,v 1.108 2025/07/31 16:09:59 kettenis Exp $ */ +/* + * Copyright (c) 1995, 1996 Erik Theisen. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This is the ELF ABI header file + * formerly known as "elf_abi.h". + */ + +#ifndef _SYS_EXEC_ELF_H_ +#define _SYS_EXEC_ELF_H_ + +#include +#include + +typedef __uint32_t Elf32_Addr; /* Unsigned program address */ +typedef __uint32_t Elf32_Off; /* Unsigned file offset */ +typedef __int32_t Elf32_Sword; /* Signed large integer */ +typedef __uint32_t Elf32_Word; /* Unsigned large integer */ +typedef __uint16_t Elf32_Half; /* Unsigned medium integer */ +typedef __uint64_t Elf32_Lword; + +typedef __uint64_t Elf64_Addr; +typedef __uint64_t Elf64_Off; +typedef __int32_t Elf64_Shalf; + +typedef __int32_t Elf64_Sword; +typedef __uint32_t Elf64_Word; + +typedef __int64_t Elf64_Sxword; +typedef __uint64_t Elf64_Xword; +typedef __uint64_t Elf64_Lword; + +typedef __uint16_t Elf64_Half; + +/* + * e_ident[] identification indexes + * See http://www.sco.com/developers/gabi/latest/ch4.eheader.html + */ +#define EI_MAG0 0 /* file ID */ +#define EI_MAG1 1 /* file ID */ +#define EI_MAG2 2 /* file ID */ +#define EI_MAG3 3 /* file ID */ +#define EI_CLASS 4 /* file class */ +#define EI_DATA 5 /* data encoding */ +#define EI_VERSION 6 /* ELF header version */ +#define EI_OSABI 7 /* OS/ABI ID */ +#define EI_ABIVERSION 8 /* ABI version */ +#define EI_PAD 9 /* start of pad bytes */ +#define EI_NIDENT 16 /* Size of e_ident[] */ + +/* e_ident[] magic number */ +#define ELFMAG0 0x7f /* e_ident[EI_MAG0] */ +#define ELFMAG1 'E' /* e_ident[EI_MAG1] */ +#define ELFMAG2 'L' /* e_ident[EI_MAG2] */ +#define ELFMAG3 'F' /* e_ident[EI_MAG3] */ +#define ELFMAG "\177ELF" /* magic */ +#define SELFMAG 4 /* size of magic */ + +/* e_ident[] file class */ +#define ELFCLASSNONE 0 /* invalid */ +#define ELFCLASS32 1 /* 32-bit objs */ +#define ELFCLASS64 2 /* 64-bit objs */ +#define ELFCLASSNUM 3 /* number of classes */ + +/* e_ident[] data encoding */ +#define ELFDATANONE 0 /* invalid */ +#define ELFDATA2LSB 1 /* Little-Endian */ +#define ELFDATA2MSB 2 /* Big-Endian */ +#define ELFDATANUM 3 /* number of data encode defines */ + +/* e_ident[] Operating System/ABI */ +#define ELFOSABI_SYSV 0 /* UNIX System V ABI */ +#define ELFOSABI_HPUX 1 /* HP-UX operating system */ +#define ELFOSABI_NETBSD 2 /* NetBSD */ +#define ELFOSABI_LINUX 3 /* GNU/Linux */ +#define ELFOSABI_HURD 4 /* GNU/Hurd */ +#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */ +#define ELFOSABI_SOLARIS 6 /* Solaris */ +#define ELFOSABI_MONTEREY 7 /* Monterey */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +/* e_ident */ +#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ + (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ + (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ + (ehdr).e_ident[EI_MAG3] == ELFMAG3) + +/* ELF Header */ +typedef struct elfhdr { + unsigned char e_ident[EI_NIDENT]; /* ELF Identification */ + Elf32_Half e_type; /* object file type */ + Elf32_Half e_machine; /* machine */ + Elf32_Word e_version; /* object file version */ + Elf32_Addr e_entry; /* virtual entry point */ + Elf32_Off e_phoff; /* program header table offset */ + Elf32_Off e_shoff; /* section header table offset */ + Elf32_Word e_flags; /* processor-specific flags */ + Elf32_Half e_ehsize; /* ELF header size */ + Elf32_Half e_phentsize; /* program header entry size */ + Elf32_Half e_phnum; /* number of program header entries */ + Elf32_Half e_shentsize; /* section header entry size */ + Elf32_Half e_shnum; /* number of section header entries */ + Elf32_Half e_shstrndx; /* section header table's "section + header string table" entry offset */ +} Elf32_Ehdr; + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* Id bytes */ + Elf64_Half e_type; /* file type */ + Elf64_Half e_machine; /* machine type */ + Elf64_Word e_version; /* version number */ + Elf64_Addr e_entry; /* entry point */ + Elf64_Off e_phoff; /* Program hdr offset */ + Elf64_Off e_shoff; /* Section hdr offset */ + Elf64_Word e_flags; /* Processor flags */ + Elf64_Half e_ehsize; /* sizeof ehdr */ + Elf64_Half e_phentsize; /* Program header entry size */ + Elf64_Half e_phnum; /* Number of program headers */ + Elf64_Half e_shentsize; /* Section header entry size */ + Elf64_Half e_shnum; /* Number of section headers */ + Elf64_Half e_shstrndx; /* String table index */ +} Elf64_Ehdr; + +/* e_type */ +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* relocatable file */ +#define ET_EXEC 2 /* executable file */ +#define ET_DYN 3 /* shared object file */ +#define ET_CORE 4 /* core file */ +#define ET_NUM 5 /* number of types */ +#define ET_LOPROC 0xff00 /* reserved range for processor */ +#define ET_HIPROC 0xffff /* specific e_type */ + +/* e_machine */ +#define EM_NONE 0 /* No Machine */ +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SPARC */ +#define EM_386 3 /* Intel 80386 */ +#define EM_68K 4 /* Motorola 68000 */ +#define EM_88K 5 /* Motorola 88000 */ +#define EM_486 6 /* Intel 80486 - unused? */ +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS R3000 Big-Endian only */ +/* + * Don't know if EM_MIPS_RS4_BE, + * EM_SPARC64, EM_PARISC, + * or EM_PPC are ABI compliant + */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ +#define EM_SPARC64 11 /* SPARC v9 64-bit unofficial */ +#define EM_PARISC 15 /* HPPA */ +#define EM_SPARC32PLUS 18 /* Enhanced instruction set SPARC */ +#define EM_PPC 20 /* PowerPC */ +#define EM_PPC64 21 /* PowerPC 64 */ +#define EM_ARM 40 /* Advanced RISC Machines ARM */ +#define EM_ALPHA 41 /* DEC ALPHA */ +#define EM_SH 42 /* Hitachi/Renesas Super-H */ +#define EM_SPARCV9 43 /* SPARC version 9 */ +#define EM_IA_64 50 /* Intel IA-64 Processor */ +#define EM_AMD64 62 /* AMD64 architecture */ +#define EM_X86_64 EM_AMD64 +#define EM_VAX 75 /* DEC VAX */ +#define EM_AARCH64 183 /* ARM 64-bit architecture (AArch64) */ +#define EM_RISCV 243 /* RISC-V */ + +/* Non-standard */ +#define EM_ALPHA_EXP 0x9026 /* DEC ALPHA */ +#define EM__LAST__ (EM_ALPHA_EXP + 1) + +/* Version */ +#define EV_NONE 0 /* Invalid */ +#define EV_CURRENT 1 /* Current */ +#define EV_NUM 2 /* number of versions */ + +/* Magic for e_phnum: get real value from sh_info of first section header */ +#define PN_XNUM 0xffff + +/* Section Header */ +typedef struct { + Elf32_Word sh_name; /* name - index into section header + string table section */ + Elf32_Word sh_type; /* type */ + Elf32_Word sh_flags; /* flags */ + Elf32_Addr sh_addr; /* address */ + Elf32_Off sh_offset; /* file offset */ + Elf32_Word sh_size; /* section size */ + Elf32_Word sh_link; /* section header table index link */ + Elf32_Word sh_info; /* extra information */ + Elf32_Word sh_addralign; /* address alignment */ + Elf32_Word sh_entsize; /* section entry size */ +} Elf32_Shdr; + +typedef struct { + Elf64_Word sh_name; /* section name */ + Elf64_Word sh_type; /* section type */ + Elf64_Xword sh_flags; /* section flags */ + Elf64_Addr sh_addr; /* virtual address */ + Elf64_Off sh_offset; /* file offset */ + Elf64_Xword sh_size; /* section size */ + Elf64_Word sh_link; /* link to another */ + Elf64_Word sh_info; /* misc info */ + Elf64_Xword sh_addralign; /* memory alignment */ + Elf64_Xword sh_entsize; /* table entry size */ +} Elf64_Shdr; + +/* Special Section Indexes */ +#define SHN_UNDEF 0 /* undefined */ +#define SHN_LORESERVE 0xff00 /* lower bounds of reserved indexes */ +#define SHN_LOPROC 0xff00 /* reserved range for processor */ +#define SHN_HIPROC 0xff1f /* specific section indexes */ +#define SHN_ABS 0xfff1 /* absolute value */ +#define SHN_COMMON 0xfff2 /* common symbol */ +#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */ +#define SHN_HIRESERVE 0xffff /* upper bounds of reserved indexes */ + +/* sh_type */ +#define SHT_NULL 0 /* inactive */ +#define SHT_PROGBITS 1 /* program defined information */ +#define SHT_SYMTAB 2 /* symbol table section */ +#define SHT_STRTAB 3 /* string table section */ +#define SHT_RELA 4 /* relocation section with addends*/ +#define SHT_HASH 5 /* symbol hash table section */ +#define SHT_DYNAMIC 6 /* dynamic section */ +#define SHT_NOTE 7 /* note section */ +#define SHT_NOBITS 8 /* no space section */ +#define SHT_REL 9 /* relocation section without addends */ +#define SHT_SHLIB 10 /* reserved - purpose unknown */ +#define SHT_DYNSYM 11 /* dynamic symbol table section */ +#define SHT_NUM 12 /* number of section types */ +#define SHT_INIT_ARRAY 14 /* pointers to init functions */ +#define SHT_FINI_ARRAY 15 /* pointers to termination functions */ +#define SHT_PREINIT_ARRAY 16 /* ptrs to funcs called before init */ +#define SHT_GROUP 17 /* defines a section group */ +#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */ +#define SHT_RELR 19 /* relative-only relocation section */ +#define SHT_LOOS 0x60000000 /* reserved range for OS specific */ +#define SHT_SUNW_dof 0x6ffffff4 /* used by dtrace */ +#define SHT_GNU_LIBLIST 0x6ffffff7 /* libraries to be prelinked */ +#define SHT_SUNW_move 0x6ffffffa /* inf for partially init'ed symbols */ +#define SHT_SUNW_syminfo 0x6ffffffc /* ad symbol information */ +#define SHT_SUNW_verdef 0x6ffffffd /* symbol versioning inf */ +#define SHT_SUNW_verneed 0x6ffffffe /* symbol versioning req */ +#define SHT_SUNW_versym 0x6fffffff /* symbol versioning table */ +#define SHT_HIOS 0x6fffffff /* section header types */ +#define SHT_LOPROC 0x70000000 /* reserved range for processor */ +#define SHT_HIPROC 0x7fffffff /* specific section header types */ +#define SHT_LOUSER 0x80000000 /* reserved range for application */ +#define SHT_HIUSER 0xffffffff /* specific indexes */ + +#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table section */ + +/* Section names */ +#define ELF_BSS ".bss" /* uninitialized data */ +#define ELF_DATA ".data" /* initialized data */ +#define ELF_CTF ".SUNW_ctf" /* CTF data */ +#define ELF_DEBUG ".debug" /* debug */ +#define ELF_DYNAMIC ".dynamic" /* dynamic linking information */ +#define ELF_DYNSTR ".dynstr" /* dynamic string table */ +#define ELF_DYNSYM ".dynsym" /* dynamic symbol table */ +#define ELF_FINI ".fini" /* termination code */ +#define ELF_GOT ".got" /* global offset table */ +#define ELF_HASH ".hash" /* symbol hash table */ +#define ELF_INIT ".init" /* initialization code */ +#define ELF_REL_DATA ".rel.data" /* relocation data */ +#define ELF_REL_FINI ".rel.fini" /* relocation termination code */ +#define ELF_REL_INIT ".rel.init" /* relocation initialization code */ +#define ELF_REL_DYN ".rel.dyn" /* relocation dynamic link info */ +#define ELF_REL_RODATA ".rel.rodata" /* relocation read-only data */ +#define ELF_REL_TEXT ".rel.text" /* relocation code */ +#define ELF_RODATA ".rodata" /* read-only data */ +#define ELF_SHSTRTAB ".shstrtab" /* section header string table */ +#define ELF_STRTAB ".strtab" /* string table */ +#define ELF_SYMTAB ".symtab" /* symbol table */ +#define ELF_TEXT ".text" /* code */ +#define ELF_OPENBSDRANDOMDATA ".openbsd.randomdata" /* constant randomdata */ +#define ELF_OPENBSDMUTABLE ".openbsd.mutable" /* mutable bss */ + + +/* Section Attribute Flags - sh_flags */ +#define SHF_WRITE 0x1 /* Writable */ +#define SHF_ALLOC 0x2 /* occupies memory */ +#define SHF_EXECINSTR 0x4 /* executable */ +#define SHF_MERGE 0x10 /* may be merged */ +#define SHF_STRINGS 0x20 /* contains strings */ +#define SHF_INFO_LINK 0x40 /* sh_info holds section index */ +#define SHF_LINK_ORDER 0x80 /* ordering requirements */ +#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required */ +#define SHF_GROUP 0x200 /* member of section group */ +#define SHF_TLS 0x400 /* thread local storage */ +#define SHF_COMPRESSED 0x800 /* contains compressed data */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics */ +#define SHF_MASKPROC 0xf0000000 /* reserved bits for processor */ + /* specific section attributes */ + +/* Symbol Table Entry */ +typedef struct elf32_sym { + Elf32_Word st_name; /* name - index into string table */ + Elf32_Addr st_value; /* symbol value */ + Elf32_Word st_size; /* symbol size */ + unsigned char st_info; /* type and binding */ + unsigned char st_other; /* 0 - no defined meaning */ + Elf32_Half st_shndx; /* section header index */ +} Elf32_Sym; + +typedef struct { + Elf64_Word st_name; /* Symbol name index in str table */ + unsigned char st_info; /* type / binding attrs */ + unsigned char st_other; /* unused */ + Elf64_Half st_shndx; /* section index of symbol */ + Elf64_Addr st_value; /* value of symbol */ + Elf64_Xword st_size; /* size of symbol */ +} Elf64_Sym; + +/* Symbol table index */ +#define STN_UNDEF 0 /* undefined */ + +/* Extract symbol info - st_info */ +#define ELF32_ST_BIND(x) ((x) >> 4) +#define ELF32_ST_TYPE(x) (((unsigned int) x) & 0xf) +#define ELF32_ST_INFO(b,t) (((b) << 4) + ((t) & 0xf)) + +#define ELF64_ST_BIND(x) ((x) >> 4) +#define ELF64_ST_TYPE(x) (((unsigned int) x) & 0xf) +#define ELF64_ST_INFO(b,t) (((b) << 4) + ((t) & 0xf)) + +/* Symbol Binding - ELF32_ST_BIND - st_info */ +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* like global - lower precedence */ +#define STB_NUM 3 /* number of symbol bindings */ +#define STB_LOPROC 13 /* reserved range for processor */ +#define STB_HIPROC 15 /* specific symbol bindings */ + +/* Symbol type - ELF32_ST_TYPE - st_info */ +#define STT_NOTYPE 0 /* not specified */ +#define STT_OBJECT 1 /* data object */ +#define STT_FUNC 2 /* function */ +#define STT_SECTION 3 /* section */ +#define STT_FILE 4 /* file */ +#define STT_TLS 6 /* thread local storage */ +#define STT_LOPROC 13 /* reserved range for processor */ +#define STT_HIPROC 15 /* specific symbol types */ + +/* Extract symbol visibility - st_other */ +#define ELF_ST_VISIBILITY(v) ((v) & 0x3) +#define ELF32_ST_VISIBILITY ELF_ST_VISIBILITY +#define ELF64_ST_VISIBILITY ELF_ST_VISIBILITY + +#define STV_DEFAULT 0 /* Visibility set by binding type */ +#define STV_INTERNAL 1 /* OS specific version of STV_HIDDEN */ +#define STV_HIDDEN 2 /* can only be seen inside own .so */ +#define STV_PROTECTED 3 /* HIDDEN inside, DEFAULT outside */ + +/* Relocation entry with implicit addend */ +typedef struct { + Elf32_Addr r_offset; /* offset of relocation */ + Elf32_Word r_info; /* symbol table index and type */ +} Elf32_Rel; + +/* Relocation entry with explicit addend */ +typedef struct { + Elf32_Addr r_offset; /* offset of relocation */ + Elf32_Word r_info; /* symbol table index and type */ + Elf32_Sword r_addend; +} Elf32_Rela; + +/* Extract relocation info - r_info */ +#define ELF32_R_SYM(i) ((i) >> 8) +#define ELF32_R_TYPE(i) ((unsigned char) (i)) +#define ELF32_R_INFO(s,t) (((s) << 8) + (unsigned char)(t)) + +typedef struct { + Elf64_Addr r_offset; /* where to do it */ + Elf64_Xword r_info; /* index & type of relocation */ +} Elf64_Rel; + +typedef struct { + Elf64_Addr r_offset; /* where to do it */ + Elf64_Xword r_info; /* index & type of relocation */ + Elf64_Sxword r_addend; /* adjustment value */ +} Elf64_Rela; + +#define ELF64_R_SYM(info) ((info) >> 32) +#define ELF64_R_TYPE(info) ((info) & 0xFFFFFFFF) +#define ELF64_R_INFO(s,t) (((s) << 32) + (__uint32_t)(t)) + +#if defined(__mips64__) && defined(__MIPSEL__) +/* + * The 64-bit MIPS ELF ABI uses a slightly different relocation format + * than the regular ELF ABI: the r_info field is split into several + * pieces (see gnu/usr.bin/binutils-2.17/include/elf/mips.h for details). + */ +#undef ELF64_R_SYM +#undef ELF64_R_TYPE +#undef ELF64_R_INFO +#define ELF64_R_TYPE(info) ((__uint64_t)swap32((info) >> 32)) +#define ELF64_R_SYM(info) ((info) & 0xFFFFFFFF) +#define ELF64_R_INFO(s,t) (((__uint64_t)swap32(t) << 32) + (__uint32_t)(s)) +#endif /* __mips64__ && __MIPSEL__ */ + +/* + * Relative Relocation info. + * c.f. decode_relrs() in gnu/llvm/llvm/lib/Object/ELF.cpp + */ +typedef Elf32_Word Elf32_Relr; +typedef Elf64_Xword Elf64_Relr; + +/* Program Header */ +typedef struct { + Elf32_Word p_type; /* segment type */ + Elf32_Off p_offset; /* segment offset */ + Elf32_Addr p_vaddr; /* virtual address of segment */ + Elf32_Addr p_paddr; /* physical address - ignored? */ + Elf32_Word p_filesz; /* number of bytes in file for seg. */ + Elf32_Word p_memsz; /* number of bytes in mem. for seg. */ + Elf32_Word p_flags; /* flags */ + Elf32_Word p_align; /* memory alignment */ +} Elf32_Phdr; + +typedef struct { + Elf64_Word p_type; /* entry type */ + Elf64_Word p_flags; /* flags */ + Elf64_Off p_offset; /* offset */ + Elf64_Addr p_vaddr; /* virtual address */ + Elf64_Addr p_paddr; /* physical address */ + Elf64_Xword p_filesz; /* file size */ + Elf64_Xword p_memsz; /* memory size */ + Elf64_Xword p_align; /* memory & file alignment */ +} Elf64_Phdr; + +/* Segment types - p_type */ +#define PT_NULL 0 /* unused */ +#define PT_LOAD 1 /* loadable segment */ +#define PT_DYNAMIC 2 /* dynamic linking section */ +#define PT_INTERP 3 /* the RTLD */ +#define PT_NOTE 4 /* auxiliary information */ +#define PT_SHLIB 5 /* reserved - purpose undefined */ +#define PT_PHDR 6 /* program header */ +#define PT_TLS 7 /* thread local storage */ +#define PT_LOOS 0x60000000 /* reserved range for OS */ +#define PT_HIOS 0x6fffffff /* specific segment types */ +#define PT_LOPROC 0x70000000 /* reserved range for processor */ +#define PT_HIPROC 0x7fffffff /* specific segment types */ + +#define PT_GNU_EH_FRAME 0x6474e550 /* Exception handling info */ +#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ +#define PT_GNU_PROPERTY 0x6474e553 /* Program property note */ + +#define PT_OPENBSD_MUTABLE 0x65a3dbe5 /* like bss, but not immutable */ +#define PT_OPENBSD_RANDOMIZE 0x65a3dbe6 /* fill with random data */ +#define PT_OPENBSD_WXNEEDED 0x65a3dbe7 /* program performs W^X violations */ +#define PT_OPENBSD_NOBTCFI 0x65a3dbe8 /* no branch target CFI */ +#define PT_OPENBSD_SYSCALLS 0x65a3dbe9 /* syscall locations */ +#define PT_OPENBSD_BOOTDATA 0x65a41be6 /* section for boot arguments */ + +/* Segment flags - p_flags */ +#define PF_X 0x1 /* Executable */ +#define PF_W 0x2 /* Writable */ +#define PF_R 0x4 /* Readable */ +#define PF_MASKOS 0x0ff00000 /* reserved bits for OS */ + /* specific segment flags */ +#define PF_MASKPROC 0xf0000000 /* reserved bits for processor */ + /* specific segment flags */ + +#define PF_OPENBSD_MUTABLE 0x08000000 /* Mutable */ + +#ifdef _KERNEL +#define PF_ISVNODE 0x00100000 /* For coredump segments */ +#endif + +/* Dynamic structure */ +typedef struct { + Elf32_Sword d_tag; /* controls meaning of d_val */ + union { + Elf32_Word d_val; /* Multiple meanings - see d_tag */ + Elf32_Addr d_ptr; /* program virtual address */ + } d_un; +} Elf32_Dyn; + +typedef struct { + Elf64_Xword d_tag; /* controls meaning of d_val */ + union { + Elf64_Addr d_ptr; + Elf64_Xword d_val; + } d_un; +} Elf64_Dyn; + +/* Dynamic Array Tags - d_tag */ +#define DT_NULL 0 /* marks end of _DYNAMIC array */ +#define DT_NEEDED 1 /* string table offset of needed lib */ +#define DT_PLTRELSZ 2 /* size of relocation entries in PLT */ +#define DT_PLTGOT 3 /* address PLT/GOT */ +#define DT_HASH 4 /* address of symbol hash table */ +#define DT_STRTAB 5 /* address of string table */ +#define DT_SYMTAB 6 /* address of symbol table */ +#define DT_RELA 7 /* address of relocation table */ +#define DT_RELASZ 8 /* size of relocation table */ +#define DT_RELAENT 9 /* size of relocation entry */ +#define DT_STRSZ 10 /* size of string table */ +#define DT_SYMENT 11 /* size of symbol table entry */ +#define DT_INIT 12 /* address of initialization func. */ +#define DT_FINI 13 /* address of termination function */ +#define DT_SONAME 14 /* string table offset of shared obj */ +#define DT_RPATH 15 /* string table offset of library + search path */ +#define DT_SYMBOLIC 16 /* start sym search in shared obj. */ +#define DT_REL 17 /* address of rel. tbl. w addends */ +#define DT_RELSZ 18 /* size of DT_REL relocation table */ +#define DT_RELENT 19 /* size of DT_REL relocation entry */ +#define DT_PLTREL 20 /* PLT referenced relocation entry */ +#define DT_DEBUG 21 /* bugger */ +#define DT_TEXTREL 22 /* Allow rel. mod. to unwritable seg */ +#define DT_JMPREL 23 /* add. of PLT's relocation entries */ +#define DT_BIND_NOW 24 /* Bind now regardless of env setting */ +#define DT_INIT_ARRAY 25 /* address of array of init func */ +#define DT_FINI_ARRAY 26 /* address of array of term func */ +#define DT_INIT_ARRAYSZ 27 /* size of array of init func */ +#define DT_FINI_ARRAYSZ 28 /* size of array of term func */ +#define DT_RUNPATH 29 /* strtab offset of lib search path */ +#define DT_FLAGS 30 /* Set of DF_* flags */ +#define DT_ENCODING 31 /* further DT_* follow encoding rules */ +#define DT_PREINIT_ARRAY 32 /* address of array of preinit func */ +#define DT_PREINIT_ARRAYSZ 33 /* size of array of preinit func */ +#define DT_RELRSZ 35 /* size of DT_RELR relocation table */ +#define DT_RELR 36 /* addr of DT_RELR relocation table */ +#define DT_RELRENT 37 /* size of DT_RELR relocation entry */ +#define DT_LOOS 0x6000000d /* reserved range for OS */ +#define DT_HIOS 0x6ffff000 /* specific dynamic array tags */ +#define DT_LOPROC 0x70000000 /* reserved range for processor */ +#define DT_HIPROC 0x7fffffff /* specific dynamic array tags */ + +/* some other useful tags */ +#define DT_GNU_HASH 0x6ffffef5 /* address of GNU hash table */ +#define DT_RELACOUNT 0x6ffffff9 /* if present, number of RELATIVE */ +#define DT_RELCOUNT 0x6ffffffa /* relocs, which must come first */ +#define DT_FLAGS_1 0x6ffffffb + +/* Dynamic Flags - DT_FLAGS .dynamic entry */ +#define DF_ORIGIN 0x00000001 +#define DF_SYMBOLIC 0x00000002 +#define DF_TEXTREL 0x00000004 +#define DF_BIND_NOW 0x00000008 +#define DF_STATIC_TLS 0x00000010 + +/* Dynamic Flags - DT_FLAGS_1 .dynamic entry */ +#define DF_1_NOW 0x00000001 +#define DF_1_GLOBAL 0x00000002 +#define DF_1_GROUP 0x00000004 +#define DF_1_NODELETE 0x00000008 +#define DF_1_LOADFLTR 0x00000010 +#define DF_1_INITFIRST 0x00000020 +#define DF_1_NOOPEN 0x00000040 +#define DF_1_ORIGIN 0x00000080 +#define DF_1_DIRECT 0x00000100 +#define DF_1_TRANS 0x00000200 +#define DF_1_INTERPOSE 0x00000400 +#define DF_1_NODEFLIB 0x00000800 +#define DF_1_NODUMP 0x00001000 +#define DF_1_CONLFAT 0x00002000 +#define DF_1_ENDFILTEE 0x00004000 +#define DF_1_DISPRELDNE 0x00008000 +#define DF_1_DISPRELPND 0x00010000 +#define DF_1_NODIRECT 0x00020000 +#define DF_1_IGNMULDEF 0x00040000 +#define DF_1_NOKSYMS 0x00080000 +#define DF_1_NOHDR 0x00100000 +#define DF_1_EDITED 0x00200000 +#define DF_1_NORELOC 0x00400000 +#define DF_1_SYMINTPOSE 0x00800000 +#define DF_1_GLOBAUDIT 0x01000000 +#define DF_1_SINGLETON 0x02000000 +#define DF_1_PIE 0x08000000 + +/* + * Note header + */ +typedef struct { + Elf32_Word n_namesz; + Elf32_Word n_descsz; + Elf32_Word n_type; +} Elf32_Nhdr; + +typedef struct { + Elf64_Word n_namesz; + Elf64_Word n_descsz; + Elf64_Word n_type; +} Elf64_Nhdr; + +/* + * Note Definitions + */ +typedef struct { + Elf32_Word namesz; + Elf32_Word descsz; + Elf32_Word type; +} Elf32_Note; + +typedef struct { + Elf64_Word namesz; + Elf64_Word descsz; + Elf64_Word type; +} Elf64_Note; + +/* Values for n_type. */ +#define NT_PRSTATUS 1 /* Process status. */ +#define NT_FPREGSET 2 /* Floating point registers. */ +#define NT_PRPSINFO 3 /* Process state info. */ + +/* + * OpenBSD-specific core file information. + * + * OpenBSD ELF core files use notes to provide information about + * the process's state. The note name is "OpenBSD" for information + * that is global to the process, and "OpenBSD@nn", where "nn" is the + * thread ID of the thread that the information belongs to (such as + * register state). + * + * We use the following note identifiers: + * + * NT_OPENBSD_PROCINFO + * Note is a "elfcore_procinfo" structure. + * NT_OPENBSD_AUXV + * Note is a bunch of Auxiliary Vectors, terminated by + * an AT_NULL entry. + * NT_OPENBSD_REGS + * Note is a "reg" structure. + * NT_OPENBSD_FPREGS + * Note is a "fpreg" structure. + * + * Please try to keep the members of the "elfcore_procinfo" structure + * nicely aligned, and if you add elements, add them to the end and + * bump the version. + */ + +#define NT_OPENBSD_PROF 2 + +#define NT_OPENBSD_PROCINFO 10 +#define NT_OPENBSD_AUXV 11 + +#define NT_OPENBSD_REGS 20 +#define NT_OPENBSD_FPREGS 21 +#define NT_OPENBSD_XFPREGS 22 +#define NT_OPENBSD_WCOOKIE 23 +#define NT_OPENBSD_PACMASK 24 + +struct elfcore_procinfo { + /* Version 1 fields start here. */ + uint32_t cpi_version; /* elfcore_procinfo version */ +#define ELFCORE_PROCINFO_VERSION 1 + uint32_t cpi_cpisize; /* sizeof(elfcore_procinfo) */ + uint32_t cpi_signo; /* killing signal */ + uint32_t cpi_sigcode; /* signal code */ + uint32_t cpi_sigpend; /* pending signals */ + uint32_t cpi_sigmask; /* blocked signals */ + uint32_t cpi_sigignore; /* ignored signals */ + uint32_t cpi_sigcatch; /* signals being caught by user */ + int32_t cpi_pid; /* process ID */ + int32_t cpi_ppid; /* parent process ID */ + int32_t cpi_pgrp; /* process group ID */ + int32_t cpi_sid; /* session ID */ + uint32_t cpi_ruid; /* real user ID */ + uint32_t cpi_euid; /* effective user ID */ + uint32_t cpi_svuid; /* saved user ID */ + uint32_t cpi_rgid; /* real group ID */ + uint32_t cpi_egid; /* effective group ID */ + uint32_t cpi_svgid; /* saved group ID */ + int8_t cpi_name[32]; /* copy of pr->ps_comm */ +}; + +/* + * XXX - these _KERNEL items aren't part of the ABI! + */ +#if defined(_KERNEL) || defined(_DYN_LOADER) + +#define ELF32_NO_ADDR ((uint32_t) ~0) /* Indicates addr. not yet filled in */ + +typedef struct { + Elf32_Sword au_id; /* 32-bit id */ + Elf32_Word au_v; /* 32-bit value */ +} Aux32Info; + +#define ELF64_NO_ADDR ((__uint64_t) ~0)/* Indicates addr. not yet filled in */ + +typedef struct { + Elf64_Shalf au_id; /* 32-bit id */ + Elf64_Xword au_v; /* 64-bit value */ +} Aux64Info; + +enum AuxID { + AUX_null = 0, + AUX_ignore = 1, + AUX_execfd = 2, + AUX_phdr = 3, /* &phdr[0] */ + AUX_phent = 4, /* sizeof(phdr[0]) */ + AUX_phnum = 5, /* # phdr entries */ + AUX_pagesz = 6, /* PAGESIZE */ + AUX_base = 7, /* base addr for ld.so or static PIE */ + AUX_flags = 8, /* processor flags */ + AUX_entry = 9, /* a.out entry */ + AUX_hwcap = 25, /* processor flags */ + AUX_hwcap2 = 26, /* processor flags (continued) */ + AUX_sun_uid = 2000, /* euid */ + AUX_sun_ruid = 2001, /* ruid */ + AUX_sun_gid = 2002, /* egid */ + AUX_sun_rgid = 2003, /* rgid */ + AUX_openbsd_timekeep = 4000, /* userland clock_gettime */ +}; + +struct elf_args { + u_long arg_entry; /* program entry point */ + u_long arg_interp; /* Interpreter load address */ + u_long arg_phaddr; /* program header address */ + u_long arg_phentsize; /* Size of program header */ + u_long arg_phnum; /* Number of program headers */ +}; + +#endif + +#if !defined(ELFSIZE) && defined(ARCH_ELFSIZE) +#define ELFSIZE ARCH_ELFSIZE +#endif + +#if defined(ELFSIZE) +#define CONCAT(x,y) __CONCAT(x,y) +#define ELFNAME(x) CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x))) +#define ELFDEFNNAME(x) CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x))) +#endif + +#if defined(ELFSIZE) && (ELFSIZE == 32) +#define Elf_Ehdr Elf32_Ehdr +#define Elf_Phdr Elf32_Phdr +#define Elf_Shdr Elf32_Shdr +#define Elf_Sym Elf32_Sym +#define Elf_Rel Elf32_Rel +#define Elf_RelA Elf32_Rela +#define Elf_Relr Elf32_Relr +#define Elf_Dyn Elf32_Dyn +#define Elf_Half Elf32_Half +#define Elf_Word Elf32_Word +#define Elf_Sword Elf32_Sword +#define Elf_Addr Elf32_Addr +#define Elf_Off Elf32_Off +#define Elf_Nhdr Elf32_Nhdr +#define Elf_Note Elf32_Note + +#define ELF_R_SYM ELF32_R_SYM +#define ELF_R_TYPE ELF32_R_TYPE +#define ELF_R_INFO ELF32_R_INFO +#define ELFCLASS ELFCLASS32 + +#define ELF_ST_BIND ELF32_ST_BIND +#define ELF_ST_TYPE ELF32_ST_TYPE +#define ELF_ST_INFO ELF32_ST_INFO + +#define ELF_NO_ADDR ELF32_NO_ADDR +#define AuxInfo Aux32Info +#elif defined(ELFSIZE) && (ELFSIZE == 64) +#define Elf_Ehdr Elf64_Ehdr +#define Elf_Phdr Elf64_Phdr +#define Elf_Shdr Elf64_Shdr +#define Elf_Sym Elf64_Sym +#define Elf_Rel Elf64_Rel +#define Elf_RelA Elf64_Rela +#define Elf_Relr Elf64_Relr +#define Elf_Dyn Elf64_Dyn +#define Elf_Half Elf64_Half +#define Elf_Word Elf64_Word +#define Elf_Sword Elf64_Sword +#define Elf_Addr Elf64_Addr +#define Elf_Off Elf64_Off +#define Elf_Nhdr Elf64_Nhdr +#define Elf_Note Elf64_Note + +#define ELF_R_SYM ELF64_R_SYM +#define ELF_R_TYPE ELF64_R_TYPE +#define ELF_R_INFO ELF64_R_INFO +#define ELFCLASS ELFCLASS64 + +#define ELF_ST_BIND ELF64_ST_BIND +#define ELF_ST_TYPE ELF64_ST_TYPE +#define ELF_ST_INFO ELF64_ST_INFO + +#define ELF_NO_ADDR ELF64_NO_ADDR +#define AuxInfo Aux64Info +#endif + +#ifndef _KERNEL +extern Elf_Dyn _DYNAMIC[]; +#endif + +#ifdef _KERNEL +/* + * How many entries are in the AuxInfo array we pass to the process? + */ +#define ELF_AUX_ENTRIES 11 +#define ELF_AUX_WORDS (sizeof(AuxInfo) * ELF_AUX_ENTRIES / sizeof(char *)) + +#define ELFROUNDSIZE sizeof(Elf_Word) +#define elfround(x) roundup((x), ELFROUNDSIZE) + +struct exec_package; + +int exec_elf_makecmds(struct proc *, struct exec_package *); +int exec_elf_fixup(struct proc *, struct exec_package *); +int coredump_elf(struct proc *, void *); +int coredump_note_elf_md(struct proc *, void *, const char *, size_t *); +int coredump_writenote_elf(struct proc *, void *, Elf_Note *, + const char *, void *); +#endif /* _KERNEL */ + +#define ELF_TARG_VER 1 /* The ver for which this code is intended */ + +#endif /* _SYS_EXEC_ELF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/exec_script.h b/lib/libc/include/generic-openbsd/sys/exec_script.h new file mode 100644 index 000000000000..2d99321a9913 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/exec_script.h @@ -0,0 +1,43 @@ +/* $OpenBSD: exec_script.h,v 1.6 2018/02/07 20:31:57 tedu Exp $ */ +/* $NetBSD: exec_script.h,v 1.6 1995/03/26 20:24:11 jtc Exp $ */ + +/* + * Copyright (c) 1994 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define EXEC_SCRIPT_MAGIC "#!" +#define EXEC_SCRIPT_MAGICLEN 2 +#define EXEC_SCRIPT_HDRSZ (EXEC_SCRIPT_MAGICLEN + 1 + MAXINTERP + 1) + +#ifdef _KERNEL + +/* the shell script handler's entry in the exec switch */ +int exec_script_makecmds(struct proc *, struct exec_package *); + +#endif /* _KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/extent.h b/lib/libc/include/generic-openbsd/sys/extent.h new file mode 100644 index 000000000000..4fc4b1bdd8ce --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/extent.h @@ -0,0 +1,132 @@ +/* $OpenBSD: extent.h,v 1.15 2024/01/19 22:12:24 kettenis Exp $ */ +/* $NetBSD: extent.h,v 1.6 1997/10/09 07:43:05 jtc Exp $ */ + +/*- + * Copyright (c) 1996 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_EXTENT_H_ +#define _SYS_EXTENT_H_ + +#include + +struct extent_region { + LIST_ENTRY(extent_region) er_link; /* link in region list */ + u_long er_start; /* start of region */ + u_long er_end; /* end of region */ + int er_flags; /* misc. flags */ +}; + +/* er_flags */ +#define ER_ALLOC 0x01 /* region descriptor dynamically allocated */ +#define ER_DISCARD 0x02 /* discard region descriptor after use */ + +struct extent { + char *ex_name; /* name of extent */ + /* allocated regions in extent */ + LIST_HEAD(, extent_region) ex_regions; + u_long ex_start; /* start of extent */ + u_long ex_end; /* end of extent */ + int ex_mtype; /* memory type */ + int ex_flags; /* misc. information */ + + LIST_ENTRY(extent) ex_link; +}; + +struct extent_fixed { + struct extent fex_extent; /* MUST BE FIRST */ + /* freelist of region descriptors */ + LIST_HEAD(, extent_region) fex_freelist; + caddr_t fex_storage; /* storage space for descriptors */ + size_t fex_storagesize; /* size of storage space */ +}; + +/* ex_flags; for internal use only */ +#define EXF_FIXED 0x01 /* extent uses fixed storage */ +#define EXF_NOCOALESCE 0x02 /* coalescing of regions not allowed */ +#define EXF_WANTED 0x04 /* someone asleep on extent */ +#define EXF_FLWANTED 0x08 /* someone asleep on freelist */ + +#define EXF_BITS "\20\4FLWANTED\3WANTED\2NOCOALESCE\1FIXED" + +/* misc. flags passed to extent functions */ +#define EX_NOWAIT 0x0000 /* not safe to sleep */ +#define EX_WAITOK 0x0001 /* safe to sleep */ +#define EX_FAST 0x0002 /* take first fit in extent_alloc() */ +#define EX_CATCH 0x0004 /* catch signals while sleeping */ +#define EX_NOCOALESCE 0x0008 /* create a non-coalescing extent */ +#define EX_MALLOCOK 0x0010 /* safe to call malloc() */ +#define EX_WAITSPACE 0x0020 /* wait for space to become free */ +#define EX_BOUNDZERO 0x0040 /* boundary lines start at 0 */ +#define EX_CONFLICTOK 0x0080 /* allow conflicts */ +#define EX_FILLED 0x0100 /* create a filled extent */ + +/* + * Special place holders for "alignment" and "boundary" arguments, + * in the event the caller doesn't wish to use those features. + */ +#define EX_NOALIGN 1 /* don't do alignment */ +#define EX_NOBOUNDARY 0 /* don't do boundary checking */ + +#if defined(_KERNEL) || defined(_EXTENT_TESTING) +#define EXTENT_FIXED_STORAGE_SIZE(_nregions) \ + (ALIGN(sizeof(struct extent_fixed)) + \ + ((ALIGN(sizeof(struct extent_region))) * \ + (_nregions))) + +void extent_print_all(void); + +struct extent *extent_create(char *, u_long, u_long, int, + caddr_t, size_t, int); +void extent_destroy(struct extent *); +int extent_alloc_subregion(struct extent *, u_long, u_long, + u_long, u_long, u_long, u_long, int, u_long *); +int extent_alloc_subregion_with_descr(struct extent *, u_long, u_long, + u_long, u_long, u_long, u_long, int, struct extent_region *, + u_long *); +int extent_alloc_region(struct extent *, u_long, u_long, int); +int extent_alloc_region_with_descr(struct extent *, u_long, u_long, + int, struct extent_region *); +int extent_free(struct extent *, u_long, u_long, int); +void extent_print(struct extent *); + +/* Simple case of extent_alloc_subregion() */ +#define extent_alloc(_ex, _size, _alignment, _skew, _boundary, \ + _flags, _result) \ + extent_alloc_subregion((_ex), (_ex)->ex_start, (_ex)->ex_end, \ + (_size), (_alignment), (_skew), (_boundary), (_flags), (_result)) + +/* Simple case of extent_alloc_subregion_with_descr() */ +#define extent_alloc_with_descr(_ex, _size, _alignment, _skew, _boundary, \ + _flags, _region, _result) \ + extent_alloc_subregion_with_descr((_ex), (_ex)->ex_start, \ + (_ex)->ex_end, (_size), (_alignment), (_skew), (_boundary), \ + (_flags), (_region), (_result)) +#endif /* _KERNEL || _EXTENT_TESTING */ + +#endif /* ! _SYS_EXTENT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/fcntl.h b/lib/libc/include/generic-openbsd/sys/fcntl.h new file mode 100644 index 000000000000..ddd098c940e3 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/fcntl.h @@ -0,0 +1,231 @@ +/* $OpenBSD: fcntl.h,v 1.23 2025/08/04 04:59:30 guenther Exp $ */ +/* $NetBSD: fcntl.h,v 1.8 1995/03/26 20:24:12 jtc Exp $ */ + +/*- + * Copyright (c) 1983, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)fcntl.h 8.3 (Berkeley) 1/21/94 + */ + +#ifndef _SYS_FCNTL_H_ +#define _SYS_FCNTL_H_ + +/* + * This file includes the definitions for open and fcntl + * described by POSIX for ; it also includes + * related kernel definitions. + */ + +#include +#ifndef _KERNEL +#include +#endif + +/* + * File status flags: these are used by open(2), fcntl(2). + * They are also used (indirectly) in the kernel file structure f_flags, + * which is a superset of the open/fcntl flags. Open flags and f_flags + * are inter-convertible using OFLAGS(fflags) and FFLAGS(oflags). + * Open/fcntl flags begin with O_; kernel-internal flags begin with F. + */ +/* open-only flags */ +#define O_RDONLY 0x0000 /* open for reading only */ +#define O_WRONLY 0x0001 /* open for writing only */ +#define O_RDWR 0x0002 /* open for reading and writing */ +#define O_ACCMODE 0x0003 /* mask for above modes */ + +/* + * Kernel encoding of open mode; separate read and write bits that are + * independently testable: 1 greater than the above. + * + * XXX + * FREAD and FWRITE are excluded from the #ifdef _KERNEL so that TIOCFLUSH, + * which was documented to use FREAD/FWRITE, continues to work. + */ +#if __BSD_VISIBLE +#define FREAD 0x0001 +#define FWRITE 0x0002 +#endif +#define O_NONBLOCK 0x0004 /* no delay */ +#define O_APPEND 0x0008 /* set append mode */ +#if __BSD_VISIBLE +#define O_SHLOCK 0x0010 /* open with shared file lock */ +#define O_EXLOCK 0x0020 /* open with exclusive file lock */ +#define O_ASYNC 0x0040 /* signal pgrp when data ready */ +#define O_FSYNC 0x0080 /* backwards compatibility */ +#endif +#if __POSIX_VISIBLE >= 199309 || __XPG_VISIBLE >= 420 +#define O_SYNC 0x0080 /* synchronous writes */ +/* + * POSIX 1003.1 permits a higher granularity for synchronous operations + * than we support. Since synchronicity is all or nothing in OpenBSD + * we just define these to be the same as O_SYNC. + */ +#define O_DSYNC O_SYNC /* synchronous data writes */ +#define O_RSYNC O_SYNC /* synchronous reads */ +#endif + +/* defined by POSIX Issue 7 */ +#define O_NOFOLLOW 0x0100 /* if path is a symlink, don't follow */ + +#define O_CREAT 0x0200 /* create if nonexistent */ +#define O_TRUNC 0x0400 /* truncate to zero length */ +#define O_EXCL 0x0800 /* error if already exists */ + +/* defined by POSIX 1003.1; BSD default, this bit is not required */ +#define O_NOCTTY 0x8000 /* don't assign controlling terminal */ + +/* defined by POSIX Issue 7 */ +#define O_CLOEXEC 0x10000 /* atomically set FD_CLOEXEC */ +#define O_DIRECTORY 0x20000 /* fail if not a directory */ + +/* defined by POSIX Issue 8 */ +#define O_CLOFORK 0x40000 /* atomically set FD_CLOFORK */ + +#ifdef _KERNEL +/* + * convert from open() flags to/from fflags; convert O_RD/WR to FREAD/FWRITE. + * For out-of-range values for the flags, be slightly careful (but lossy). + */ +#define FFLAGS(oflags) (((oflags) & ~O_ACCMODE) | (((oflags) + 1) & O_ACCMODE)) +#define OFLAGS(fflags) (((fflags) & ~O_ACCMODE) | (((fflags) - 1) & O_ACCMODE)) + +/* bits to save after open */ +#define FMASK (FREAD|FWRITE|FAPPEND|FASYNC|FFSYNC|FNONBLOCK) +/* bits settable by fcntl(F_SETFL, ...) */ +#define FCNTLFLAGS (FAPPEND|FASYNC|FFSYNC|FNONBLOCK) +#endif + +/* + * The O_* flags used to have only F* names, which were used in the kernel + * and by fcntl. We retain the F* names for the kernel f_flags field + * and for backward compatibility for fcntl. + */ +#if __BSD_VISIBLE +#define FAPPEND O_APPEND /* kernel/compat */ +#define FASYNC O_ASYNC /* kernel/compat */ +#define FFSYNC O_SYNC /* kernel */ +#define FNONBLOCK O_NONBLOCK /* kernel */ +#define FNDELAY O_NONBLOCK /* compat */ +#define O_NDELAY O_NONBLOCK /* compat */ +#endif + +/* + * Constants used for fcntl(2) + */ + +/* command values */ +#define F_DUPFD 0 /* duplicate file descriptor */ +#define F_GETFD 1 /* get file descriptor flags */ +#define F_SETFD 2 /* set file descriptor flags */ +#define F_GETFL 3 /* get file status flags */ +#define F_SETFL 4 /* set file status flags */ +#if __POSIX_VISIBLE >= 200112 || __XPG_VISIBLE >= 500 +#define F_GETOWN 5 /* get SIGIO/SIGURG proc/pgrp */ +#define F_SETOWN 6 /* set SIGIO/SIGURG proc/pgrp */ +#endif +#define F_GETLK 7 /* get record locking information */ +#define F_SETLK 8 /* set record locking information */ +#define F_SETLKW 9 /* F_SETLK; wait if blocked */ +#if __POSIX_VISIBLE >= 200809 +#define F_DUPFD_CLOEXEC 10 /* duplicate with FD_CLOEXEC set */ +#endif +#if __BSD_VISIBLE +#define F_ISATTY 11 /* used by isatty(3) */ +#endif +#if __POSIX_VISIBLE >= 202405 +#define F_DUPFD_CLOFORK 12 /* duplicate with FD_CLOFORK set */ +#endif + +/* file descriptor flags (F_GETFD, F_SETFD) */ +#define FD_CLOEXEC 1 /* close-on-exec flag */ +#if __POSIX_VISIBLE >= 202405 +#define FD_CLOFORK 4 /* close-on-fork flag */ +#endif + +/* record locking flags (F_GETLK, F_SETLK, F_SETLKW) */ +#define F_RDLCK 1 /* shared or read lock */ +#define F_UNLCK 2 /* unlock */ +#define F_WRLCK 3 /* exclusive or write lock */ +#ifdef _KERNEL +#define F_WAIT 0x010 /* Wait until lock is granted */ +#define F_FLOCK 0x020 /* Use flock(2) semantics for lock */ +#define F_POSIX 0x040 /* Use POSIX semantics for lock */ +#define F_INTR 0x080 /* Lock operation interrupted */ +#endif + +/* + * Advisory file segment locking data type - + * information passed to system by user + */ +struct flock { + off_t l_start; /* starting offset */ + off_t l_len; /* len = 0 means until end of file */ + pid_t l_pid; /* lock owner */ + short l_type; /* lock type: read/write, etc. */ + short l_whence; /* type of l_start */ +}; + + +#if __BSD_VISIBLE +/* lock operations for flock(2) */ +#define LOCK_SH 0x01 /* shared file lock */ +#define LOCK_EX 0x02 /* exclusive file lock */ +#define LOCK_NB 0x04 /* don't block when locking */ +#define LOCK_UN 0x08 /* unlock file */ +#endif + +#if __POSIX_VISIBLE >= 200809 +#define AT_FDCWD -100 + +#define AT_EACCESS 0x01 +#define AT_SYMLINK_NOFOLLOW 0x02 +#define AT_SYMLINK_FOLLOW 0x04 +#define AT_REMOVEDIR 0x08 +#endif + +#ifndef _KERNEL +__BEGIN_DECLS +int open(const char *, int, ...); +int creat(const char *, mode_t); +int fcntl(int, int, ...); +#if __BSD_VISIBLE +int flock(int, int); +#endif +#if __POSIX_VISIBLE >= 200809 +int openat(int, const char *, int, ...); +#endif +__END_DECLS +#endif + +#endif /* !_SYS_FCNTL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/file.h b/lib/libc/include/generic-openbsd/sys/file.h new file mode 100644 index 000000000000..047f0514c373 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/file.h @@ -0,0 +1,139 @@ +/* $OpenBSD: file.h,v 1.66 2022/06/20 01:39:44 visa Exp $ */ +/* $NetBSD: file.h,v 1.11 1995/03/26 20:24:13 jtc Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)file.h 8.2 (Berkeley) 8/20/94 + */ + +#ifndef _KERNEL +#include + +#else /* _KERNEL */ +#include +#include +#endif /* _KERNEL */ + +#define DTYPE_VNODE 1 /* file */ +#define DTYPE_SOCKET 2 /* communications endpoint */ +#define DTYPE_PIPE 3 /* pipe */ +#define DTYPE_KQUEUE 4 /* event queue */ +#define DTYPE_DMABUF 5 /* DMA buffer (for DRM) */ +#define DTYPE_SYNC 6 /* sync file (for DRM) */ + +#ifdef _KERNEL +struct proc; +struct uio; +struct knote; +struct stat; +struct file; +struct ucred; + +/** + * File operations. + * The following entries could be called without KERNEL_LOCK hold: + * - fo_read + * - fo_write + * - fo_close + */ +struct fileops { + int (*fo_read)(struct file *, struct uio *, int); + int (*fo_write)(struct file *, struct uio *, int); + int (*fo_ioctl)(struct file *, u_long, caddr_t, struct proc *); + int (*fo_kqfilter)(struct file *, struct knote *); + int (*fo_stat)(struct file *, struct stat *, struct proc *); + int (*fo_close)(struct file *, struct proc *); + int (*fo_seek)(struct file *, off_t *, int, struct proc *); +}; +#define FO_POSITION 0x00000001 /* positioned read/write */ + +/* + * Kernel descriptor table. + * One entry for each open kernel vnode and socket. + * + * Locks used to protect struct members in this file: + * I immutable after creation + * F global `fhdlk' mutex + * a atomic operations + * f per file `f_mtx' + * v vnode lock + */ +struct file { + LIST_ENTRY(file) f_list;/* [F] list of active files */ + struct mutex f_mtx; + u_int f_flag; /* [a] see fcntl.h */ + u_int f_iflags; /* [a] internal flags */ + int f_type; /* [I] descriptor type */ + u_int f_count; /* [a] reference count */ + struct ucred *f_cred; /* [I] credentials associated with descriptor */ + const struct fileops *f_ops; /* [I] file operation pointers */ + off_t f_offset; /* [f,v] offset */ + void *f_data; /* [I] private data */ + uint64_t f_rxfer; /* [f] total number of read transfers */ + uint64_t f_wxfer; /* [f] total number of write transfers */ + uint64_t f_seek; /* [f] total independent seek operations */ + uint64_t f_rbytes; /* [f] total bytes read */ + uint64_t f_wbytes; /* [f] total bytes written */ +}; + +#define FIF_HASLOCK 0x01 /* descriptor holds advisory lock */ +#define FIF_INSERTED 0x80 /* present in `filehead' */ + +#define FREF(fp) \ + do { \ + extern void vfs_stall_barrier(void); \ + vfs_stall_barrier(); \ + atomic_inc_int(&(fp)->f_count); \ + } while (0) + +#define FRELE(fp,p) \ + (atomic_dec_int_nv(&fp->f_count) == 0 ? fdrop(fp, p) : 0) + +#define FDUP_MAX_COUNT (UINT_MAX - 2 * MAXCPUS) + +int fdrop(struct file *, struct proc *); + +static inline off_t +foffset(struct file *fp) +{ + off_t offset; + + mtx_enter(&fp->f_mtx); + offset = fp->f_offset; + mtx_leave(&fp->f_mtx); + return (offset); +} + +LIST_HEAD(filelist, file); +extern int maxfiles; /* kernel limit on number of open files */ +extern int numfiles; /* actual number of open files */ +extern const struct fileops socketops; /* socket operations for files */ +extern const struct fileops vnops; /* vnode operations for files */ + +#endif /* _KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/filedesc.h b/lib/libc/include/generic-openbsd/sys/filedesc.h new file mode 100644 index 000000000000..77a2106961bc --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/filedesc.h @@ -0,0 +1,159 @@ +/* $OpenBSD: filedesc.h,v 1.48 2025/08/04 04:59:30 guenther Exp $ */ +/* $NetBSD: filedesc.h,v 1.14 1996/04/09 20:55:28 cgd Exp $ */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)filedesc.h 8.1 (Berkeley) 6/2/93 + */ + +#include +#include +/* + * This structure is used for the management of descriptors. It may be + * shared by multiple processes. + * + * A process is initially started out with NDFILE descriptors stored within + * this structure, selected to be enough for typical applications based on + * the historical limit of 20 open files (and the usage of descriptors by + * shells). If these descriptors are exhausted, a larger descriptor table + * may be allocated, up to a process' resource limit; the internal arrays + * are then unused. The initial expansion is set to NDEXTENT; each time + * it runs out, it is doubled until the resource limit is reached. NDEXTENT + * should be selected to be the biggest multiple of OFILESIZE (see below) + * that will fit in a power-of-two sized piece of memory. + */ +#define NDFILE 20 +#define NDEXTENT 50 /* 250 bytes in 256-byte alloc. */ +#define NDENTRIES 32 /* 32 fds per entry */ +#define NDENTRYMASK (NDENTRIES - 1) +#define NDENTRYSHIFT 5 /* bits per entry */ +#define NDREDUCE(x) (((x) + NDENTRIES - 1) >> NDENTRYSHIFT) +#define NDHISLOTS(x) (NDREDUCE(NDREDUCE(x))) +#define NDLOSLOTS(x) (NDHISLOTS(x) << NDENTRYSHIFT) + +struct kqueue; + +/* + * Locking: + * a atomic operations + * f fd_lock + * f/w fd_lock when writing + * K kernel lock + * m fd_fplock + */ +struct filedesc { + struct file **fd_ofiles; /* [f/w,m] file structures for + * open files */ + char *fd_ofileflags; /* [f] per-process open file flags */ + struct vnode *fd_cdir; /* [K] current directory */ + struct vnode *fd_rdir; /* [K] root directory */ + int fd_nfiles; /* [f] number of open files allocated */ + int fd_openfd; /* [f] number of files currently open */ + u_int *fd_himap; /* [f] each bit points to 32 fds */ + u_int *fd_lomap; /* [f] bitmap of free fds */ + int fd_lastfile; /* [f] high-water mark of fd_ofiles */ + int fd_freefile; /* [f] approx. next free file */ + mode_t fd_cmask; /* [f/w] mask for file creation */ + u_int fd_refcnt; /* [K] reference count */ + struct rwlock fd_lock; /* lock for the file descs */ + struct mutex fd_fplock; /* lock for reading fd_ofiles without + * fd_lock */ + LIST_HEAD(, kqueue) fd_kqlist; /* [f] kqueues attached to this + * filedesc */ + int fd_flags; /* [a] flags on this filedesc */ + u_int fd_nuserevents; /* [a] number of kqueue user events */ +}; + +/* + * Basic allocation of descriptors: + * one of the above, plus arrays for NDFILE descriptors. + */ +struct filedesc0 { + struct filedesc fd_fd; + /* + * These arrays are used when the number of open files is + * <= NDFILE, and are then pointed to by the pointers above. + */ + struct file *fd_dfiles[NDFILE]; + char fd_dfileflags[NDFILE]; + /* + * There arrays are used when the number of open files is + * <= 1024, and are then pointed to by the pointers above. + */ + u_int fd_dhimap[NDENTRIES >> NDENTRYSHIFT]; + u_int fd_dlomap[NDENTRIES]; +}; + +/* + * Per-process open flags. + */ +#define UF_EXCLOSE 0x01 /* auto-close on exec */ +#define UF_PLEDGED 0x02 /* open after pledge(2) */ +#define UF_FORKCLOSE 0x04 /* auto-close on fork */ + +/* + * Flags on the file descriptor table. + */ +#define FD_ADVLOCK 0x01 /* May hold a POSIX adv. lock. */ + +/* + * Storage required per open file descriptor. + */ +#define OFILESIZE (sizeof(struct file *) + sizeof(char)) + +#ifdef _KERNEL +/* + * Kernel global variables and routines. + */ +void filedesc_init(void); +int dupfdopen(struct proc *, int, int); +int fdalloc(struct proc *p, int want, int *result); +void fdexpand(struct proc *); +struct file *fnew(struct proc *_p); +int falloc(struct proc *_p, struct file **_rfp, int *_rfd); +struct filedesc *fdinit(void); +struct filedesc *fdshare(struct process *); +struct filedesc *fdcopy(struct process *); +void fdfree(struct proc *p); +int fdrelease(struct proc *p, int); +void fdinsert(struct filedesc *, int, int, struct file *); +void fdremove(struct filedesc *, int); +void fdprepforexec(struct proc *); +struct file *fd_iterfile(struct file *, struct proc *); +struct file *fd_getfile(struct filedesc *, int); +struct file *fd_getfile_mode(struct filedesc *, int, int); +int fd_checkclosed(struct filedesc *, int, struct file *); + +int closef(struct file *, struct proc *); +int getsock(struct proc *, int, struct file **); + +#define fdplock(fdp) do { NET_ASSERT_UNLOCKED(); rw_enter_write(&(fdp)->fd_lock); } while (0) +#define fdpunlock(fdp) rw_exit_write(&(fdp)->fd_lock) +#define fdpassertlocked(fdp) rw_assert_wrlock(&(fdp)->fd_lock) +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/filio.h b/lib/libc/include/generic-openbsd/sys/filio.h new file mode 100644 index 000000000000..de381f3c6987 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/filio.h @@ -0,0 +1,54 @@ +/* $OpenBSD: filio.h,v 1.5 2007/06/01 22:30:48 deraadt Exp $ */ +/* $NetBSD: filio.h,v 1.5 1994/06/29 06:44:14 cgd Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)filio.h 8.1 (Berkeley) 3/28/94 + */ + +#ifndef _SYS_FILIO_H_ +#define _SYS_FILIO_H_ + +#include + +/* Generic file-descriptor ioctl's. */ +#define FIOCLEX _IO('f', 1) /* set close on exec on fd */ +#define FIONCLEX _IO('f', 2) /* remove close on exec */ +#define FIONREAD _IOR('f', 127, int) /* get # bytes to read */ +#define FIONBIO _IOW('f', 126, int) /* set/clear non-blocking i/o */ +#define FIOASYNC _IOW('f', 125, int) /* set/clear async i/o */ +#define FIOSETOWN _IOW('f', 124, int) /* set owner */ +#define FIOGETOWN _IOR('f', 123, int) /* get owner */ + +#endif /* !_SYS_FILIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/fusebuf.h b/lib/libc/include/generic-openbsd/sys/fusebuf.h new file mode 100644 index 000000000000..80e4e3d94249 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/fusebuf.h @@ -0,0 +1,148 @@ +/* $OpenBSD: fusebuf.h,v 1.16 2025/09/06 06:15:52 helg Exp $ */ +/* + * Copyright (c) 2013 Sylvestre Gallon + * Copyright (c) 2013 Martin Pieuchot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_FUSEBUF_H_ +#define _SYS_FUSEBUF_H_ + +/* + * Maximum size of the read or write buffer sent from the kernel for VFS + * syscalls: read, readdir, readlink, write. + */ +#define FUSEBUFMAXSIZE (4096*1024) + +/* header at beginning of each fusebuf: */ +struct fb_hdr { + SIMPLEQ_ENTRY(fusebuf) fh_next; /* next buffer in chain */ + size_t fh_len; /* Amount of data */ + int fh_err; /* errno to pass back */ + int fh_type; /* type of data */ + ino_t fh_ino; /* Inode of this fusebuf */ + uint64_t fh_uuid; /* Uuid to track the answer */ + pid_t fh_tid; /* calling proc thread id */ + uid_t fh_uid; /* calling proc uid */ + gid_t fh_gid; /* calling proc gid */ + mode_t fh_umask; /* calling proc umask */ +}; + +/* header for fuse file operations (like read/write/mkdir): */ +struct fb_io { + uint64_t fi_fd; /* fd where the io is performed */ + ino_t fi_ino; /* ino for the io */ + off_t fi_off; /* offset for the io */ + size_t fi_len; /* Length of data */ + mode_t fi_mode; /* mode for fd */ + uint32_t fi_flags; /* flags on transfer */ + dev_t fi_rdev; /* dev for mknod */ +}; + +/* + * An operation is issued by the kernel through fuse(4) when the + * userland file system needs to execute an action (mkdir(2), + * link(2), etc). + * + * F_databuf can be superior to FUSELEN for fusefs_read, fusefs_writes and + * fusefs_readdir. If it is the case the transfer will be split in N + * fusebuf with a changing offset in FD_io. + * + * When the userland file system answers to this operation it uses + * the same ID (fh_uuid). + */ +struct fusebuf { + struct fb_hdr fb_hdr; + union { + struct statvfs FD_stat; /* vfs statfs */ + struct stat FD_attr; /* for attr vnops */ + struct fb_io FD_io; /* for file io vnops */ + } FD; + uint8_t *fb_dat; /* data's */ +}; + +#define fb_next fb_hdr.fh_next +#define fb_len fb_hdr.fh_len +#define fb_err fb_hdr.fh_err +#define fb_type fb_hdr.fh_type +#define fb_ino fb_hdr.fh_ino +#define fb_uuid fb_hdr.fh_uuid +#define fb_tid fb_hdr.fh_tid +#define fb_uid fb_hdr.fh_uid +#define fb_gid fb_hdr.fh_gid +#define fb_umask fb_hdr.fh_umask + +#define fb_stat FD.FD_stat +#define fb_attr FD.FD_attr +#define fb_io_fd FD.FD_io.fi_fd +#define fb_io_ino FD.FD_io.fi_ino +#define fb_io_off FD.FD_io.fi_off +#define fb_io_len FD.FD_io.fi_len +#define fb_io_mode FD.FD_io.fi_mode +#define fb_io_flags FD.FD_io.fi_flags +#define fb_io_rdev FD.FD_io.fi_rdev + +/* + * Macros for type conversion + * fbtod(fb,t) - convert fusebuf pointer to data pointer of correct + * type + */ +#define fbtod(fb,t) ((t)((fb)->fb_dat)) + +/* flags needed by setattr */ +#define FUSE_FATTR_MODE (1 << 0) +#define FUSE_FATTR_UID (1 << 1) +#define FUSE_FATTR_GID (1 << 2) +#define FUSE_FATTR_SIZE (1 << 3) +#define FUSE_FATTR_ATIME (1 << 4) +#define FUSE_FATTR_MTIME (1 << 5) +#define FUSE_FATTR_FH (1 << 6) + +/* fusebuf types */ +#define FBT_LOOKUP 0 +#define FBT_GETATTR 1 +#define FBT_SETATTR 2 +#define FBT_READLINK 3 +#define FBT_SYMLINK 4 +#define FBT_MKNOD 5 +#define FBT_MKDIR 6 +#define FBT_UNLINK 7 +#define FBT_RMDIR 8 +#define FBT_RENAME 9 +#define FBT_LINK 10 +#define FBT_OPEN 11 +#define FBT_READ 12 +#define FBT_WRITE 13 +#define FBT_STATFS 14 +#define FBT_RELEASE 16 +#define FBT_FSYNC 17 +#define FBT_FLUSH 18 +#define FBT_INIT 19 +#define FBT_OPENDIR 20 +#define FBT_READDIR 21 +#define FBT_RELEASEDIR 22 +#define FBT_FSYNCDIR 23 +#define FBT_ACCESS 24 +#define FBT_DESTROY 26 +#define FBT_RECLAIM 27 + +#ifdef _KERNEL + +/* fusebuf prototypes */ +struct fusebuf *fb_setup(size_t, ino_t, int, struct proc *); +int fb_queue(dev_t, struct fusebuf *); +void fb_delete(struct fusebuf *); + +#endif /* _KERNEL */ +#endif /* _SYS_FUSEBUF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/futex.h b/lib/libc/include/generic-openbsd/sys/futex.h new file mode 100644 index 000000000000..660d553464ff --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/futex.h @@ -0,0 +1,45 @@ +/* $OpenBSD: futex.h,v 1.3 2025/05/07 00:39:09 dlg Exp $ */ + +/* + * Copyright (c) 2016 Martin Pieuchot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_FUTEX_H_ +#define _SYS_FUTEX_H_ + +#ifndef _KERNEL +#include + +__BEGIN_DECLS +int futex(volatile uint32_t *, int, int, const struct timespec *, + volatile uint32_t *); +__END_DECLS +#endif /* ! _KERNEL */ + +#define FUTEX_OP_MASK 0x007f + +#define FUTEX_WAIT 1 +#define FUTEX_WAKE 2 +#define FUTEX_REQUEUE 3 + +#define FUTEX_FLAG_MASK 0xff80 + +#define FUTEX_PRIVATE_FLAG 0x0080 + +#define FUTEX_WAIT_PRIVATE (FUTEX_WAIT | FUTEX_PRIVATE_FLAG) +#define FUTEX_WAKE_PRIVATE (FUTEX_WAKE | FUTEX_PRIVATE_FLAG) +#define FUTEX_REQUEUE_PRIVATE (FUTEX_REQUEUE | FUTEX_PRIVATE_FLAG) + +#endif /* _SYS_FUTEX_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/gmon.h b/lib/libc/include/generic-openbsd/sys/gmon.h new file mode 100644 index 000000000000..2f1194c02502 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/gmon.h @@ -0,0 +1,182 @@ +/* $OpenBSD: gmon.h,v 1.12 2025/07/16 16:22:58 deraadt Exp $ */ +/* $NetBSD: gmon.h,v 1.5 1996/04/09 20:55:30 cgd Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)gmon.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _SYS_GMON_H_ +#define _SYS_GMON_H_ + +#include +#include + +/* + * Structure prepended to gmon.out profiling data file. + */ +struct gmonhdr { + u_long lpc; /* base pc address of sample buffer */ + u_long hpc; /* max pc address of sampled buffer */ + int ncnt; /* size of sample buffer (plus this header) */ + int version; /* version number */ + int profrate; /* profiling clock rate */ + int totarc; /* space used by arcs */ + int spare[2]; /* reserved */ +}; +#define GMONVERSION 0x00051879 + +/* + * histogram counters are unsigned shorts (according to the kernel). + */ +#define HISTCOUNTER unsigned short + +/* + * fraction of text space to allocate for histogram counters here, 1/2 + */ +#define HISTFRACTION 2 + +/* + * Fraction of text space to allocate for from hash buckets. + * The value of HASHFRACTION is based on the minimum number of bytes + * of separation between two subroutine call points in the object code. + * Given MIN_SUBR_SEPARATION bytes of separation the value of + * HASHFRACTION is calculated as: + * + * HASHFRACTION = MIN_SUBR_SEPARATION / (2 * sizeof(short) - 1); + * + * For example, on the VAX, the shortest two call sequence is: + * + * calls $0,(r0) + * calls $0,(r0) + * + * which is separated by only three bytes, thus HASHFRACTION is + * calculated as: + * + * HASHFRACTION = 3 / (2 * 2 - 1) = 1 + * + * Note that the division above rounds down, thus if MIN_SUBR_FRACTION + * is less than three, this algorithm will not work! + * + * In practice, however, call instructions are rarely at a minimal + * distance. Hence, we will define HASHFRACTION to be 2 across all + * architectures. This saves a reasonable amount of space for + * profiling data structures without (in practice) sacrificing + * any granularity. + */ +#define HASHFRACTION 2 + +/* + * percent of text space to allocate for tostructs with a minimum. + */ +#define ARCDENSITY 2 +#define MINARCS 50 +#define MAXARCS ((1 << (8 * sizeof(HISTCOUNTER))) - 2) + +struct tostruct { + u_long selfpc; + long count; + u_short link; + u_short pad; +}; + +/* + * a raw arc, with pointers to the calling site and + * the called site and a count. + */ +struct rawarc { + u_long raw_frompc; + u_long raw_selfpc; + long raw_count; +}; + +/* + * general rounding functions. + */ +#define ROUNDDOWN(x,y) (((x)/(y))*(y)) +#define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y)) + +/* + * The profiling data structures are housed in this structure. + */ +struct gmonparam { + int state; + u_short *kcount; + u_long kcountsize; + u_short *froms; + u_long fromssize; + struct tostruct *tos; + u_long tossize; + long tolimit; + u_long lowpc; + u_long highpc; + u_long textsize; + u_long hashfraction; + void *outbuf; + size_t outbuflen; + void *rawarcs; + int dirfd; + SLIST_ENTRY(gmonparam) list; +}; + +/* + * Possible states of profiling. + */ +#define GMON_PROF_ON 0 +#define GMON_PROF_BUSY 1 +#define GMON_PROF_ERROR 2 +#define GMON_PROF_OFF 3 + +/* + * Sysctl definitions for extracting profiling information from the kernel. + */ +#define GPROF_STATE 0 /* int: profiling enabling variable */ +#define GPROF_COUNT 1 /* struct: profile tick count buffer */ +#define GPROF_FROMS 2 /* struct: from location hash bucket */ +#define GPROF_TOS 3 /* struct: destination/count structure */ +#define GPROF_GMONPARAM 4 /* struct: profiling parameters (see above) */ + +#ifdef _KERNEL +extern int gmoninit; /* Is the kernel ready for being profiled? */ + +#else /* !_KERNEL */ + +#include + +__BEGIN_DECLS +extern struct gmonparam _gmonparam; +void _mcleanup(void); +void _monstartup(u_long, u_long); +void moncontrol(int); +struct gmonparam *_gmon_alloc(void); +__END_DECLS + +#endif /* !_KERNEL */ + +#endif /* !_SYS_GMON_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/gpio.h b/lib/libc/include/generic-openbsd/sys/gpio.h new file mode 100644 index 000000000000..95cbc9c82e1a --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/gpio.h @@ -0,0 +1,80 @@ +/* $OpenBSD: gpio.h,v 1.8 2011/10/03 20:24:51 matthieu Exp $ */ +/* + * Copyright (c) 2004 Alexander Yurchenko + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_GPIO_H_ +#define _SYS_GPIO_H_ + +/* GPIO pin states */ +#define GPIO_PIN_LOW 0x00 /* low level (logical 0) */ +#define GPIO_PIN_HIGH 0x01 /* high level (logical 1) */ + +/* Max name length of a pin */ +#define GPIOPINMAXNAME 64 + +/* GPIO pin configuration flags */ +#define GPIO_PIN_INPUT 0x0001 /* input direction */ +#define GPIO_PIN_OUTPUT 0x0002 /* output direction */ +#define GPIO_PIN_INOUT 0x0004 /* bi-directional */ +#define GPIO_PIN_OPENDRAIN 0x0008 /* open-drain output */ +#define GPIO_PIN_PUSHPULL 0x0010 /* push-pull output */ +#define GPIO_PIN_TRISTATE 0x0020 /* output disabled */ +#define GPIO_PIN_PULLUP 0x0040 /* internal pull-up enabled */ +#define GPIO_PIN_PULLDOWN 0x0080 /* internal pull-down enabled */ +#define GPIO_PIN_INVIN 0x0100 /* invert input */ +#define GPIO_PIN_INVOUT 0x0200 /* invert output */ +#define GPIO_PIN_USER 0x0400 /* user != 0 can access */ +#define GPIO_PIN_SET 0x8000 /* set for securelevel access */ + +/* GPIO controller description */ +struct gpio_info { + int gpio_npins; /* total number of pins available */ +}; + +/* GPIO pin operation (read/write/toggle) */ +struct gpio_pin_op { + char gp_name[GPIOPINMAXNAME]; /* pin name */ + int gp_pin; /* pin number */ + int gp_value; /* value */ +}; + +/* GPIO pin configuration */ +struct gpio_pin_set { + char gp_name[GPIOPINMAXNAME]; + int gp_pin; + int gp_caps; + int gp_flags; + char gp_name2[GPIOPINMAXNAME]; /* new name */ +}; + +/* Attach/detach device drivers that use GPIO pins */ +struct gpio_attach { + char ga_dvname[16]; /* device name */ + int ga_offset; /* pin number */ + u_int32_t ga_mask; /* binary mask */ + u_int32_t ga_flags; /* flags */ +}; + +#define GPIOINFO _IOR('G', 0, struct gpio_info) +#define GPIOPINREAD _IOWR('G', 1, struct gpio_pin_op) +#define GPIOPINWRITE _IOWR('G', 2, struct gpio_pin_op) +#define GPIOPINTOGGLE _IOWR('G', 3, struct gpio_pin_op) +#define GPIOPINSET _IOWR('G', 4, struct gpio_pin_set) +#define GPIOPINUNSET _IOWR('G', 5, struct gpio_pin_set) +#define GPIOATTACH _IOWR('G', 6, struct gpio_attach) +#define GPIODETACH _IOWR('G', 7, struct gpio_attach) + +#endif /* !_SYS_GPIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/hibernate.h b/lib/libc/include/generic-openbsd/sys/hibernate.h new file mode 100644 index 000000000000..d7e3176f1963 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/hibernate.h @@ -0,0 +1,162 @@ +/* $OpenBSD: hibernate.h,v 1.51 2025/07/05 09:24:37 jsg Exp $ */ + +/* + * Copyright (c) 2011 Ariane van der Steldt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_HIBERNATE_H_ +#define _SYS_HIBERNATE_H_ + +#include +#include +#include +#include + +#define HIB_PHYSSEG_MAX 22 + +#define HIBERNATE_CHUNK_USED 1 +#define HIBERNATE_CHUNK_CONFLICT 2 +#define HIBERNATE_CHUNK_PLACED 4 + +/* Magic number used to indicate hibernate signature block */ +#define HIBERNATE_MAGIC 0x0B5D0B5D + +/* Page skip operations used during unpack */ +#define HIB_MOVE 2 +#define HIB_SKIP 1 + +struct hiballoc_entry; + +/* + * Allocator operates from an arena, that is pre-allocated by the caller. + */ +struct hiballoc_arena { + RBT_HEAD(hiballoc_addr, hiballoc_entry) hib_addrs; +}; + +/* + * Describes a zlib compression stream and its associated hiballoc area + */ +struct hibernate_zlib_state { + z_stream hib_stream; + struct hiballoc_arena hiballoc_arena; +}; + +/* + * Describes a range of physical memory on the machine + */ +struct hibernate_memory_range { + paddr_t base; + paddr_t end; +}; + +/* + * Describes a hibernate chunk structure, used when splitting the memory + * image of the machine into easy-to-manage pieces. + */ +struct hibernate_disk_chunk { + paddr_t base; /* Base of chunk */ + paddr_t end; /* End of chunk */ + daddr_t offset; /* Abs. disk block locating chunk */ + size_t compressed_size; /* Compressed size on disk */ + short flags; /* Flags */ +}; + +#define HIB_INIT -1 +#define HIB_DONE -2 +#define HIB_R 0 +#define HIB_W 1 +typedef int (*hibio_fn)(dev_t, daddr_t, vaddr_t, size_t, int, void *); + +/* + * Used to store information about the hibernation state of the machine, + * such as memory range count and extents, disk sector size, and various + * offsets where things are located on disk. + */ +union hibernate_info { + struct { + u_int32_t magic; + dev_t dev; + size_t nranges; + struct hibernate_memory_range ranges[HIB_PHYSSEG_MAX]; + size_t image_size; + size_t chunk_ctr; + daddr_t sig_offset; + daddr_t chunktable_offset; + daddr_t image_offset; + paddr_t piglet_pa; + vaddr_t piglet_va; + hibio_fn io_func; + void *io_page; + u_int8_t kern_hash[SHA256_DIGEST_LENGTH]; +#ifndef NO_PROPOLICE + long guard; +#endif /* ! NO_PROPOLICE */ + u_int32_t retguard_ofs; + u_int32_t sec_size; + }; + + /* XXX - remove restriction to have the struct fit in a single block */ + char pad[4096]; /* Pad to largest allowable disk sector size in bytes */ +}; + +void *hib_alloc(struct hiballoc_arena*, size_t); +void hib_free(struct hiballoc_arena*, void*); +int hiballoc_init(struct hiballoc_arena*, void*, size_t len); +void uvm_pmr_dirty_everything(void); +int uvm_pmr_alloc_pig(paddr_t*, psize_t, paddr_t); +int uvm_pmr_alloc_piglet(vaddr_t*, paddr_t*, vsize_t, paddr_t); +int uvm_page_rle(paddr_t); +void uvmpd_hibernate(void); + +hibio_fn get_hibernate_io_function(dev_t); +int get_hibernate_info(union hibernate_info *, int); + +int hibernate_zlib_reset(union hibernate_info *, int); +void *hibernate_zlib_alloc(void *, int, int); +void hibernate_zlib_free(void *, void *); +void hibernate_inflate_region(union hibernate_info *, paddr_t, paddr_t, + size_t); +size_t hibernate_deflate(union hibernate_info *, paddr_t, size_t *); +void hibernate_process_chunk(union hibernate_info *, + struct hibernate_disk_chunk *, paddr_t); +int hibernate_inflate_page(int *); + +int hibernate_block_io(union hibernate_info *, daddr_t, size_t, vaddr_t, int); +int hibernate_write_signature(union hibernate_info *); +int hibernate_write_chunktable(union hibernate_info *); +int hibernate_write_chunks(union hibernate_info *); +int hibernate_clear_signature(union hibernate_info *); +int hibernate_compare_signature(union hibernate_info *, + union hibernate_info *); +void hibernate_resume(void); +int hibernate_suspend(void); +int hibernate_read_image(union hibernate_info *); +int hibernate_read_chunks(union hibernate_info *, paddr_t, paddr_t, size_t, + struct hibernate_disk_chunk *); +void hibernate_unpack_image(union hibernate_info *); +void hibernate_populate_resume_pt(union hibernate_info *, paddr_t, paddr_t); +int hibernate_alloc(void); +void hibernate_free(void); +void hib_getentropy(char **, size_t *); + +int hibernate_write(union hibernate_info *, daddr_t, vaddr_t, size_t, int); +void hibernate_sort_ranges(union hibernate_info *); +void hibernate_suspend_bufcache(void); +void hibernate_resume_bufcache(void); + +void preallocate_hibernate_memory(void); + +#endif /* _SYS_HIBERNATE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/hotplug.h b/lib/libc/include/generic-openbsd/sys/hotplug.h new file mode 100644 index 000000000000..29529e12781b --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/hotplug.h @@ -0,0 +1,40 @@ +/* $OpenBSD: hotplug.h,v 1.5 2006/05/28 16:52:34 mk Exp $ */ +/* + * Copyright (c) 2004 Alexander Yurchenko + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_HOTPLUG_H_ +#define _SYS_HOTPLUG_H_ + +/* + * Public interface for enqueuing and dequeueing device + * attachment and detachment notifications. + */ + +#define HOTPLUG_DEVAT 0x01 /* device attached */ +#define HOTPLUG_DEVDT 0x02 /* device detached */ + +struct hotplug_event { + int he_type; /* event type */ + enum devclass he_devclass; /* device class */ + char he_devname[16]; /* device name */ +}; + +#ifdef _KERNEL +void hotplug_device_attach(enum devclass, char *); +void hotplug_device_detach(enum devclass, char *); +#endif + +#endif /* _SYS_HOTPLUG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/intrmap.h b/lib/libc/include/generic-openbsd/sys/intrmap.h new file mode 100644 index 000000000000..de64e1cdd1e1 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/intrmap.h @@ -0,0 +1,33 @@ +/* $OpenBSD: intrmap.h,v 1.4 2025/06/13 09:48:45 jsg Exp $ */ + +/* + * Copyright (c) 2020 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_INTRMAP_H_ +#define _SYS_INTRMAP_H_ + +struct intrmap; + +#define INTRMAP_POWEROF2 (1 << 0) + +struct intrmap *intrmap_create(const struct device *, + unsigned int, unsigned int, unsigned int); +void intrmap_destroy(struct intrmap *); + +unsigned int intrmap_count(const struct intrmap *); +struct cpu_info *intrmap_cpu(const struct intrmap *, unsigned int); + +#endif /* _SYS_INTRMAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/ioccom.h b/lib/libc/include/generic-openbsd/sys/ioccom.h new file mode 100644 index 000000000000..36d9d1da944b --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/ioccom.h @@ -0,0 +1,68 @@ +/* $OpenBSD: ioccom.h,v 1.6 2025/05/02 10:14:46 jsg Exp $ */ +/* $NetBSD: ioccom.h,v 1.4 1994/10/30 21:49:56 cgd Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ioccom.h 8.2 (Berkeley) 3/28/94 + */ + +#ifndef _SYS_IOCCOM_H_ +#define _SYS_IOCCOM_H_ + +/* + * Ioctl's have the command encoded in the lower word, and the size of + * any in or out parameters in the upper word. The high 3 bits of the + * upper word are used to encode the in/out status of the parameter. + */ +#define IOCPARM_MASK 0x1fff /* parameter length, at most 13 bits */ +#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK) +#define IOCBASECMD(x) ((x) & ~(IOCPARM_MASK << 16)) +#define IOCGROUP(x) (((x) >> 8) & 0xff) + +#define IOCPARM_MAX PAGE_SIZE /* max size of ioctl args */ + /* no parameters */ +#define IOC_VOID 0x20000000UL + /* copy parameters out */ +#define IOC_OUT 0x40000000UL + /* copy parameters in */ +#define IOC_IN 0x80000000UL + /* copy parameters in and out */ +#define IOC_INOUT (IOC_IN|IOC_OUT) + /* mask for IN/OUT/VOID */ +#define IOC_DIRMASK 0xe0000000UL + +#define _IOC(inout,group,num,len) \ + (inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num)) +#define _IO(g,n) _IOC(IOC_VOID, (g), (n), 0) +#define _IOR(g,n,t) _IOC(IOC_OUT, (g), (n), sizeof(t)) +#define _IOW(g,n,t) _IOC(IOC_IN, (g), (n), sizeof(t)) +/* this should be _IORW, but stdio got there first */ +#define _IOWR(g,n,t) _IOC(IOC_INOUT, (g), (n), sizeof(t)) + +#endif /* !_SYS_IOCCOM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/ioctl.h b/lib/libc/include/generic-openbsd/sys/ioctl.h new file mode 100644 index 000000000000..0f862b6e8fda --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/ioctl.h @@ -0,0 +1,55 @@ +/* $OpenBSD: ioctl.h,v 1.17 2016/02/28 15:46:19 naddy Exp $ */ +/* $NetBSD: ioctl.h,v 1.20 1996/01/30 18:21:47 thorpej Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ioctl.h 8.6 (Berkeley) 3/28/94 + */ + +#ifndef _SYS_IOCTL_H_ +#define _SYS_IOCTL_H_ + +#include +#include +#include + +#ifndef _KERNEL + +#include + +__BEGIN_DECLS +int ioctl(int, unsigned long, ...); +__END_DECLS +#endif /* !_KERNEL */ +#endif /* !_SYS_IOCTL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/ipc.h b/lib/libc/include/generic-openbsd/sys/ipc.h new file mode 100644 index 000000000000..7f45b5a779e5 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/ipc.h @@ -0,0 +1,95 @@ +/* $OpenBSD: ipc.h,v 1.13 2014/11/15 21:42:50 guenther Exp $ */ +/* $NetBSD: ipc.h,v 1.15 1996/02/09 18:25:12 christos Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ipc.h 8.3 (Berkeley) 1/21/94 + */ + +/* + * SVID compatible ipc.h file + */ +#ifndef _SYS_IPC_H_ +#define _SYS_IPC_H_ + +#include + +struct ipc_perm { + uid_t cuid; /* creator user id */ + gid_t cgid; /* creator group id */ + uid_t uid; /* user id */ + gid_t gid; /* group id */ + mode_t mode; /* r/w permission */ + unsigned short seq; /* sequence # (to generate unique msg/sem/shm id) */ + key_t key; /* user specified msg/sem/shm key */ +}; + +/* common mode bits */ +#define IPC_R 000400 /* read permission */ +#define IPC_W 000200 /* write/alter permission */ +#define IPC_M 010000 /* permission to change control info */ + +/* SVID required constants (same values as system 5) */ +#define IPC_CREAT 001000 /* create entry if key does not exist */ +#define IPC_EXCL 002000 /* fail if key exists */ +#define IPC_NOWAIT 004000 /* error if request must wait */ + +#define IPC_PRIVATE (key_t)0 /* private key */ + +#define IPC_RMID 0 /* remove identifier */ +#define IPC_SET 1 /* set options */ +#define IPC_STAT 2 /* get options */ + +#ifdef _KERNEL +/* Macros to convert between ipc ids and array indices or sequence ids */ +#define IPCID_TO_IX(id) ((id) & 0xffff) +#define IPCID_TO_SEQ(id) (((id) >> 16) & 0xffff) +#define IXSEQ_TO_IPCID(ix,perm) (((perm.seq) << 16) | (ix & 0xffff)) + +struct ucred; + +int ipcperm(struct ucred *, struct ipc_perm *, int); + +#else /* !_KERNEL */ + +__BEGIN_DECLS +key_t ftok(const char *, int); +__END_DECLS +#endif +#endif /* !_SYS_IPC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/kcore.h b/lib/libc/include/generic-openbsd/sys/kcore.h new file mode 100644 index 000000000000..571c9d4ad227 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/kcore.h @@ -0,0 +1,60 @@ +/* $OpenBSD: kcore.h,v 1.2 2023/01/04 10:59:34 jsg Exp $ */ +/* $NetBSD: kcore.h,v 1.1 1996/03/10 21:56:00 leo Exp $ */ + +/* + * Copyright (c) 1996 Leo Weppelman. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _SYS_KCORE_H_ +#define _SYS_KCORE_H_ + +/* + * Definitions for the kernel crash-dump format. The structure of + * the files and headers is borrowed from the 'regular' core files + * as described in . + */ +#define KCORE_MAGIC 0x8fca +#define KCORESEG_MAGIC 0x8fac + +/* + * Description of a memory segment. To make this suitable for sharing + * between all architectures, u_quad_t seems to be the necessary type... + */ +typedef struct { + u_quad_t start; /* Physical start address */ + u_quad_t size; /* Size in bytes */ +} phys_ram_seg_t; + +typedef struct kcore_hdr { + u_int32_t c_midmag; /* Magic, id, flags */ + u_int16_t c_hdrsize; /* Aligned header size */ + u_int16_t c_seghdrsize; /* Aligned seg-header size */ + u_int32_t c_nseg; /* Number of segments */ +} kcore_hdr_t; + +typedef struct kcore_seg { + u_int32_t c_midmag; /* Magic, id, flags */ + u_int32_t c_size; /* Sizeof this segment */ +} kcore_seg_t; + +#endif /* _SYS_KCORE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/kcov.h b/lib/libc/include/generic-openbsd/sys/kcov.h new file mode 100644 index 000000000000..eb3e237f69bc --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/kcov.h @@ -0,0 +1,55 @@ +/* $OpenBSD: kcov.h,v 1.9 2023/07/29 06:52:08 anton Exp $ */ + +/* + * Copyright (c) 2018 Anton Lindqvist + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_KCOV_H_ +#define _SYS_KCOV_H_ + +#include + +#define KIOSETBUFSIZE _IOW('K', 1, unsigned long) +#define KIOENABLE _IOW('K', 2, int) +#define KIODISABLE _IO('K', 3) +#define KIOREMOTEATTACH _IOW('K', 4, struct kio_remote_attach *) + +#define KCOV_MODE_NONE 0 +#define KCOV_MODE_TRACE_PC 1 +#define KCOV_MODE_TRACE_CMP 2 + +#define KCOV_REMOTE_COMMON 0 + +struct kio_remote_attach { + int subsystem; + int id; +}; + +#ifdef _KERNEL + +struct proc; + +extern int kcov_cold; + +void kcov_exit(struct proc *); +int kcov_vnode(struct vnode *); +void kcov_remote_register(int, void *); +void kcov_remote_unregister(int, void *); +void kcov_remote_enter(int, void *); +void kcov_remote_leave(int, void *); + +#endif /* _KERNEL */ + +#endif /* !_SYS_KCOV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/kernel.h b/lib/libc/include/generic-openbsd/sys/kernel.h new file mode 100644 index 000000000000..54966635ee30 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/kernel.h @@ -0,0 +1,61 @@ +/* $OpenBSD: kernel.h,v 1.28 2025/09/25 08:46:50 mvs Exp $ */ +/* $NetBSD: kernel.h,v 1.11 1995/03/03 01:24:16 cgd Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)kernel.h 8.3 (Berkeley) 1/21/94 + */ + +/* Global variables for the kernel. */ + +/* 1.1 */ +extern int hostid; +extern char hostname[MAXHOSTNAMELEN]; +extern int hostnamelen; +extern char domainname[MAXHOSTNAMELEN]; +extern int domainnamelen; + +/* 1.2 */ +extern int utc_offset; /* seconds east of UTC */ + +extern int tick; /* usec per tick (1000000 / hz) */ +extern int tick_nsec; /* nsec per tick */ +extern int ticks; /* # of hardclock ticks */ +extern int hz; /* system clock's frequency */ +extern int stathz; /* statistics clock's frequency */ +extern int profhz; /* profiling clock's frequency */ + +#ifndef HZ +#define HZ 100 +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/kstat.h b/lib/libc/include/generic-openbsd/sys/kstat.h new file mode 100644 index 000000000000..97afc625d9ae --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/kstat.h @@ -0,0 +1,211 @@ +/* $OpenBSD: kstat.h,v 1.6 2025/05/13 21:20:10 kettenis Exp $ */ + +/* + * Copyright (c) 2020 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_KSTAT_H_ +#define _SYS_KSTAT_H_ + +#include + +#define KSTAT_STRLEN 32 + +#define KSTAT_T_RAW 0 +#define KSTAT_T_KV 1 +#define KSTAT_T_COUNTERS 2 + +struct kstat_req { + unsigned int ks_rflags; +#define KSTATIOC_F_IGNVER (1 << 0) + /* the current version of the kstat subsystem */ + unsigned int ks_version; + + uint64_t ks_id; + + char ks_provider[KSTAT_STRLEN]; + unsigned int ks_instance; + char ks_name[KSTAT_STRLEN]; + unsigned int ks_unit; + + struct timespec ks_created; + struct timespec ks_updated; + struct timespec ks_interval; + unsigned int ks_type; + unsigned int ks_state; + + void *ks_data; + size_t ks_datalen; + unsigned int ks_dataver; +}; + +/* ioctls */ + +#define KSTATIOC_VERSION _IOR('k', 1, unsigned int) +#define KSTATIOC_FIND_ID _IOWR('k', 2, struct kstat_req) +#define KSTATIOC_NFIND_ID _IOWR('k', 3, struct kstat_req) +#define KSTATIOC_FIND_PROVIDER _IOWR('k', 4, struct kstat_req) +#define KSTATIOC_NFIND_PROVIDER _IOWR('k', 5, struct kstat_req) +#define KSTATIOC_FIND_NAME _IOWR('k', 6, struct kstat_req) +#define KSTATIOC_NFIND_NAME _IOWR('k', 7, struct kstat_req) + +/* named data */ + +#define KSTAT_KV_NAMELEN 16 +#define KSTAT_KV_ALIGN sizeof(uint64_t) + +enum kstat_kv_type { + KSTAT_KV_T_NULL, + KSTAT_KV_T_BOOL, + KSTAT_KV_T_COUNTER64, + KSTAT_KV_T_COUNTER32, + KSTAT_KV_T_UINT64, + KSTAT_KV_T_INT64, + KSTAT_KV_T_UINT32, + KSTAT_KV_T_INT32, + KSTAT_KV_T_ISTR, /* inline string */ + KSTAT_KV_T_STR, /* trailing string */ + KSTAT_KV_T_BYTES, /* trailing bytes */ + KSTAT_KV_T_TEMP, /* temperature (uK) */ + KSTAT_KV_T_COUNTER16, + KSTAT_KV_T_UINT16, + KSTAT_KV_T_INT16, + KSTAT_KV_T_FREQ, /* frequency (Hz) */ + KSTAT_KV_T_VOLTS_DC, /* voltage (uV DC) */ + KSTAT_KV_T_VOLTS_AC, /* voltage (uV AC) */ + KSTAT_KV_T_AMPS, /* current (uA) */ + KSTAT_KV_T_WATTS, /* power (uW) */ +}; + +/* units only apply to integer types */ +enum kstat_kv_unit { + KSTAT_KV_U_NONE = 0, + KSTAT_KV_U_PACKETS, /* packets */ + KSTAT_KV_U_BYTES, /* bytes */ + KSTAT_KV_U_CYCLES, /* cycles */ +}; + +struct kstat_kv { + char kv_key[KSTAT_KV_NAMELEN]; + union { + char v_istr[16]; + unsigned int v_bool; + uint64_t v_u64; + int64_t v_s64; + uint32_t v_u32; + int32_t v_s32; + uint16_t v_u16; + int16_t v_s16; + size_t v_len; + } kv_v; + enum kstat_kv_type kv_type; + enum kstat_kv_unit kv_unit; +} __aligned(KSTAT_KV_ALIGN); + +#define kstat_kv_istr(_kv) (_kv)->kv_v.v_istr +#define kstat_kv_bool(_kv) (_kv)->kv_v.v_bool +#define kstat_kv_u64(_kv) (_kv)->kv_v.v_u64 +#define kstat_kv_s64(_kv) (_kv)->kv_v.v_s64 +#define kstat_kv_u32(_kv) (_kv)->kv_v.v_u32 +#define kstat_kv_s32(_kv) (_kv)->kv_v.v_s32 +#define kstat_kv_u16(_kv) (_kv)->kv_v.v_u16 +#define kstat_kv_s16(_kv) (_kv)->kv_v.v_s16 +#define kstat_kv_len(_kv) (_kv)->kv_v.v_len +#define kstat_kv_temp(_kv) (_kv)->kv_v.v_u64 +#define kstat_kv_freq(_kv) (_kv)->kv_v.v_u64 +#define kstat_kv_volts(_kv) (_kv)->kv_v.v_u64 +#define kstat_kv_amps(_kv) (_kv)->kv_v.v_u64 +#define kstat_kv_watts(_kv) (_kv)->kv_v.v_u64 + +#ifdef _KERNEL + +#include + +struct kstat_lock_ops; +struct rwlock; + +struct kstat { + uint64_t ks_id; + + const char *ks_provider; + unsigned int ks_instance; + const char *ks_name; + unsigned int ks_unit; + + unsigned int ks_type; + unsigned int ks_flags; +#define KSTAT_F_REALLOC (1 << 0) + unsigned int ks_state; +#define KSTAT_S_CREATED 0 +#define KSTAT_S_INSTALLED 1 + + struct timespec ks_created; + RBT_ENTRY(kstat) ks_id_entry; + RBT_ENTRY(kstat) ks_pv_entry; + RBT_ENTRY(kstat) ks_nm_entry; + + /* the driver can update these between kstat creation and install */ + unsigned int ks_dataver; + void *ks_softc; + void *ks_ptr; + int (*ks_read)(struct kstat *); + int (*ks_copy)(struct kstat *, void *); + + const struct kstat_lock_ops * + ks_lock_ops; + void *ks_lock; + + /* the data that is updated by ks_read */ + void *ks_data; + size_t ks_datalen; + struct timespec ks_updated; + struct timespec ks_interval; +}; + +struct kstat *kstat_create(const char *, unsigned int, + const char *, unsigned int, + unsigned int, unsigned int); + +void kstat_set_rlock(struct kstat *, struct rwlock *); +void kstat_set_wlock(struct kstat *, struct rwlock *); +void kstat_set_mutex(struct kstat *, struct mutex *); +void kstat_set_cpu(struct kstat *, struct cpu_info *); + +int kstat_read_nop(struct kstat *); + +void kstat_install(struct kstat *); +void kstat_remove(struct kstat *); +void kstat_destroy(struct kstat *); + +/* + * kstat_kv api + */ + +#define KSTAT_KV_UNIT_INITIALIZER(_key, _type, _unit) { \ + .kv_key = (_key), \ + .kv_type = (_type), \ + .kv_unit = (_unit), \ +} + +#define KSTAT_KV_INITIALIZER(_key, _type) \ + KSTAT_KV_UNIT_INITIALIZER((_key), (_type), KSTAT_KV_U_NONE) + +void kstat_kv_init(struct kstat_kv *, const char *, enum kstat_kv_type); +void kstat_kv_unit_init(struct kstat_kv *, const char *, + enum kstat_kv_type, enum kstat_kv_unit); + +#endif /* _KERNEL */ + +#endif /* _SYS_KSTAT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/kthread.h b/lib/libc/include/generic-openbsd/sys/kthread.h new file mode 100644 index 000000000000..b6acac804ab2 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/kthread.h @@ -0,0 +1,50 @@ +/* $OpenBSD: kthread.h,v 1.7 2020/02/18 12:13:40 mpi Exp $ */ +/* $NetBSD: kthread.h,v 1.2 1998/11/14 00:08:49 thorpej Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_KTHREAD_H_ +#define _SYS_KTHREAD_H_ + +/* + * Kernel thread handling. + */ + +#ifdef _KERNEL +struct proc; +int kthread_create(void (*)(void *), void *, struct proc **, + const char *); +void kthread_create_deferred(void (*)(void *), void *); +void kthread_run_deferred_queue(void); +void kthread_exit(int) __attribute__((__noreturn__)); +#endif /* _KERNEL */ + +#endif /* _SYS_KTHREAD_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/ktrace.h b/lib/libc/include/generic-openbsd/sys/ktrace.h new file mode 100644 index 000000000000..7a2af2b15998 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/ktrace.h @@ -0,0 +1,277 @@ +/* $OpenBSD: ktrace.h,v 1.50 2024/07/27 02:10:26 guenther Exp $ */ +/* $NetBSD: ktrace.h,v 1.12 1996/02/04 02:12:29 christos Exp $ */ + +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ktrace.h 8.1 (Berkeley) 6/2/93 + */ + +#include +#include +#include +#include + +/* + * operations to ktrace system call (KTROP(op)) + */ +#define KTROP_SET 0 /* set trace points */ +#define KTROP_CLEAR 1 /* clear trace points */ +#define KTROP_CLEARFILE 2 /* stop all tracing to file */ +#define KTROP(o) ((o)&3) /* macro to extract operation */ +/* + * flags (ORed in with operation) + */ +#define KTRFLAG_DESCEND 4 /* perform op on all children too */ + +/* + * ktrace record header + */ +struct ktr_header { + uint ktr_type; /* trace record type */ + pid_t ktr_pid; /* process id */ + pid_t ktr_tid; /* thread id */ + struct timespec ktr_time; /* timestamp */ + char ktr_comm[_MAXCOMLEN]; /* command name, incl NUL */ + size_t ktr_len; /* length of buf */ +}; + +/* + * ktrace record types + */ + + /* + * KTR_START - start of trace record, one per ktrace(KTROP_SET) syscall + */ +#define KTR_START 0x4b545200 /* "KTR" */ + +/* + * KTR_SYSCALL - system call record + */ +#define KTR_SYSCALL 1 +struct ktr_syscall { + int ktr_code; /* syscall number */ + int ktr_argsize; /* size of arguments */ + /* + * followed by ktr_argsize/sizeof(register_t) "register_t"s + */ +}; + +/* + * KTR_SYSRET - return from system call record + */ +#define KTR_SYSRET 2 +struct ktr_sysret { + int ktr_code; + int ktr_error; + /* + * If ktr_error is zero, then followed by retval: register_t for + * all syscalls except lseek(), which uses long long + */ +}; + +/* + * KTR_NAMEI - namei record + */ +#define KTR_NAMEI 3 + /* record contains pathname */ + +/* + * KTR_GENIO - trace generic process i/o + */ +#define KTR_GENIO 4 +struct ktr_genio { + int ktr_fd; + enum uio_rw ktr_rw; + /* + * followed by data successfully read/written + */ +}; + +/* + * KTR_PSIG - trace processed signal + */ +#define KTR_PSIG 5 +struct ktr_psig { + int signo; + sig_t action; + int mask; + int code; + siginfo_t si; +}; + +/* + * KTR_STRUCT - misc. structs + */ +#define KTR_STRUCT 8 + /* + * record contains null-terminated struct name followed by + * struct contents + */ +struct sockaddr; +struct stat; + +/* + * KTR_USER - user record + */ +#define KTR_USER 9 +#define KTR_USER_MAXIDLEN 20 +#define KTR_USER_MAXLEN 2048 /* maximum length of passed data */ +struct ktr_user { + char ktr_id[KTR_USER_MAXIDLEN]; /* string id of caller */ + /* + * Followed by ktr_len - sizeof(struct ktr_user) of user data. + */ +}; + +/* + * KTR_EXECARGS and KTR_EXECENV - args and environment records + */ +#define KTR_EXECARGS 10 +#define KTR_EXECENV 11 + + +/* + * KTR_PLEDGE - details of pledge violation + */ +#define KTR_PLEDGE 12 +struct ktr_pledge { + int error; + int syscall; + uint64_t code; +}; + +/* + * KTR_PINSYSCALL - details of pinsyscall violation + */ +#define KTR_PINSYSCALL 13 +struct ktr_pinsyscall { + int error; + int syscall; + vaddr_t addr; +}; + +/* + * kernel trace points (in ps_traceflag) + */ +#define KTRFAC_MASK 0x00ffffff +#define KTRFAC_SYSCALL (1< + +__BEGIN_DECLS +int ktrace(const char *, int, int, pid_t); +int utrace(const char *, const void *, size_t); +__END_DECLS + +#else + +/* + * Test for kernel trace point + */ +#define KTRPOINT(p, type) \ + ((p)->p_p->ps_traceflag & (1<<(type)) && ((p)->p_flag & P_INKTR) == 0) + +void ktrgenio(struct proc *, int, enum uio_rw, struct iovec *, ssize_t); +void ktrnamei(struct proc *, char *); +void ktrpsig(struct proc *, int, sig_t, int, int, siginfo_t *); +void ktrsyscall(struct proc *, register_t, size_t, register_t []); +void ktrsysret(struct proc *, register_t, int, const register_t [2]); +int ktruser(struct proc *, const char *, const void *, size_t); +void ktrexec(struct proc *, int, const char *, ssize_t); +void ktrpledge(struct proc *, int, uint64_t, int); +void ktrpinsyscall(struct proc *, int, int, vaddr_t); + +void ktrcleartrace(struct process *); +void ktrsettrace(struct process *, int, struct vnode *, struct ucred *); + +void ktrstruct(struct proc *, const char *, const void *, size_t); + +/* please keep these sorted by second argument to ktrstruct() */ +#define ktrabstimespec(p, s) \ + ktrstruct(p, "abstimespec", s, sizeof(struct timespec)) +#define ktrabstimeval(p, s) \ + ktrstruct(p, "abstimeval", s, sizeof(struct timeval)) +#define ktrcmsghdr(p, s, l) \ + ktrstruct(p, "cmsghdr", s, l) +#define ktrfds(p, s, c) \ + ktrstruct(p, "fds", s, (c) * sizeof(int)) +#define ktrfdset(p, s, l) \ + ktrstruct(p, "fdset", s, l) +#define ktrflock(p, s) \ + ktrstruct(p, "flock", s, sizeof(struct flock)) +#define ktriovec(p, s, c) \ + ktrstruct(p, "iovec", s, (c) * sizeof(struct iovec)) +#define ktritimerval(p, s) \ + ktrstruct(p, "itimerval", s, sizeof(struct itimerval)) +#define ktrevent(p, s, c) \ + ktrstruct(p, "kevent", s, (c) * sizeof(struct kevent)) +#define ktrmmsghdr(p, s) \ + ktrstruct(p, "mmsghdr", s, sizeof(struct mmsghdr)) +#define ktrmsghdr(p, s) \ + ktrstruct(p, "msghdr", s, sizeof(struct msghdr)) +#define ktrpollfd(p, s, c) \ + ktrstruct(p, "pollfd", s, (c) * sizeof(struct pollfd)) +#define ktrquota(p, s) \ + ktrstruct(p, "quota", s, sizeof(struct dqblk)) +#define ktrreltimespec(p, s) \ + ktrstruct(p, "reltimespec", s, sizeof(struct timespec)) +#define ktrreltimeval(p, s) \ + ktrstruct(p, "reltimeval", s, sizeof(struct timeval)) +#define ktrrlimit(p, s) \ + ktrstruct(p, "rlimit", s, sizeof(struct rlimit)) +#define ktrrusage(p, s) \ + ktrstruct(p, "rusage", s, sizeof(struct rusage)) +#define ktrsigaction(p, s) \ + ktrstruct(p, "sigaction", s, sizeof(struct sigaction)) +#define ktrsiginfo(p, s) \ + ktrstruct(p, "siginfo", s, sizeof(siginfo_t)) +#define ktrsockaddr(p, s, l) \ + ktrstruct(p, "sockaddr", s, l) +#define ktrstat(p, s) \ + ktrstruct(p, "stat", s, sizeof(struct stat)) + +#endif /* !_KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/limits.h b/lib/libc/include/generic-openbsd/sys/limits.h new file mode 100644 index 000000000000..fc119cae3527 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/limits.h @@ -0,0 +1,125 @@ +/* $OpenBSD: limits.h,v 1.10 2012/06/30 20:21:10 guenther Exp $ */ +/* + * Copyright (c) 2002 Marc Espie. + * + * 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 OPENBSD PROJECT 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 OPENBSD + * PROJECT 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 _SYS_LIMITS_H_ +#define _SYS_LIMITS_H_ + +#include + +/* Common definitions for limits.h. */ + +/* Legacy */ +#include + +#define CHAR_BIT 8 /* number of bits in a char */ + +#define SCHAR_MAX 0x7f /* max value for a signed char */ +#define SCHAR_MIN (-0x7f-1) /* min value for a signed char */ + +#define UCHAR_MAX 0xff /* max value for an unsigned char */ +#ifdef __CHAR_UNSIGNED__ +# define CHAR_MIN 0 /* min value for a char */ +# define CHAR_MAX 0xff /* max value for a char */ +#else +# define CHAR_MAX 0x7f +# define CHAR_MIN (-0x7f-1) +#endif + +#define MB_LEN_MAX 4 /* Allow UTF-8 (RFC 3629) */ + +#define USHRT_MAX 0xffff /* max value for an unsigned short */ +#define SHRT_MAX 0x7fff /* max value for a short */ +#define SHRT_MIN (-0x7fff-1) /* min value for a short */ + +#define UINT_MAX 0xffffffffU /* max value for an unsigned int */ +#define INT_MAX 0x7fffffff /* max value for an int */ +#define INT_MIN (-0x7fffffff-1) /* min value for an int */ + +#ifdef __LP64__ +# define ULONG_MAX 0xffffffffffffffffUL + /* max value for unsigned long */ +# define LONG_MAX 0x7fffffffffffffffL + /* max value for a signed long */ +# define LONG_MIN (-0x7fffffffffffffffL-1) + /* min value for a signed long */ +#else +# define ULONG_MAX 0xffffffffUL /* max value for an unsigned long */ +# define LONG_MAX 0x7fffffffL /* max value for a long */ +# define LONG_MIN (-0x7fffffffL-1)/* min value for a long */ +#endif + +#if __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999 +# define ULLONG_MAX 0xffffffffffffffffULL + /* max value for unsigned long long */ +# define LLONG_MAX 0x7fffffffffffffffLL + /* max value for a signed long long */ +# define LLONG_MIN (-0x7fffffffffffffffLL-1) + /* min value for a signed long long */ +#endif + +#if __BSD_VISIBLE +# define UID_MAX UINT_MAX /* max value for a uid_t */ +# define GID_MAX UINT_MAX /* max value for a gid_t */ +#endif + +#if __XPG_VISIBLE || __POSIX_VISIBLE >= 200809 +# ifdef __LP64__ +# define LONG_BIT 64 +# else +# define LONG_BIT 32 +# endif +# define WORD_BIT 32 +#endif + +#if __XPG_VISIBLE < 600 +# include + +/* XSI defines marked LEGACY in XPG5 and removed in IEEE Std 1003.1-2001 */ +# ifndef FLT_DIG +# define FLT_DIG __FLT_DIG +# endif +# ifndef FLT_MAX +# define FLT_MAX __FLT_MAX +# endif +# ifndef DBL_DIG +# define DBL_DIG __DBL_DIG +# endif +# ifndef DBL_MAX +# define DBL_MAX __DBL_MAX +# endif + +/* XSI defines marked LEGACY in XPG4v2 and removed in XPG5 */ +# if __XPG_VISIBLE < 500 +# ifndef FLT_MIN +# define FLT_MIN __FLT_MIN +# endif +# ifndef DBL_MIN +# define DBL_MIN __DBL_MIN +# endif +# endif + +#endif /* __XPG_VISIBLE < 600 */ + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/lock.h b/lib/libc/include/generic-openbsd/sys/lock.h new file mode 100644 index 000000000000..868be1f65c49 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/lock.h @@ -0,0 +1,55 @@ +/* $OpenBSD: lock.h,v 1.27 2016/06/19 11:54:33 natano Exp $ */ + +/* + * Copyright (c) 1995 + * The Regents of the University of California. All rights reserved. + * + * This code contains ideas from software contributed to Berkeley by + * Avadis Tevanian, Jr., Michael Wayne Young, and the Mach Operating + * System project at Carnegie-Mellon University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)lock.h 8.12 (Berkeley) 5/19/95 + */ + +#ifndef _LOCK_H_ +#define _LOCK_H_ + +#include + +#define LK_EXCLUSIVE RW_WRITE /* exclusive lock */ +#define LK_SHARED RW_READ /* shared lock */ +#define LK_TYPE_MASK (RW_WRITE|RW_READ) /* type of lock sought */ +#define LK_NOWAIT RW_NOSLEEP /* do not sleep to await lock */ +#define LK_RECURSEFAIL RW_RECURSEFAIL /* fail if recursive exclusive lock */ +#define LK_EXCLOTHER RW_WRITE_OTHER /* exclusive lock held by some other thread */ +#define LK_RWFLAGS (RW_WRITE|RW_READ|RW_NOSLEEP|RW_RECURSEFAIL|RW_WRITE_OTHER) + +/* LK_ specific */ +#define LK_DRAIN 0x1000UL /* wait for all lock activity to end */ +#define LK_RETRY 0x2000UL /* vn_lock: retry until locked */ + +#endif /* !_LOCK_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/lockf.h b/lib/libc/include/generic-openbsd/sys/lockf.h new file mode 100644 index 000000000000..61d21d4f211d --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/lockf.h @@ -0,0 +1,45 @@ +/* $OpenBSD: lockf.h,v 1.17 2019/04/20 08:28:59 anton Exp $ */ +/* $NetBSD: lockf.h,v 1.5 1994/06/29 06:44:33 cgd Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Scooter Morris at Genentech Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)lockf.h 8.1 (Berkeley) 6/11/93 + */ + +#ifdef _KERNEL +struct lockf_state; + +void lf_init(void); +int lf_advlock(struct lockf_state **, + off_t, caddr_t, int, struct flock *, int); +void lf_purgelocks(struct lockf_state **); +#endif /* _KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/malloc.h b/lib/libc/include/generic-openbsd/sys/malloc.h new file mode 100644 index 000000000000..dd519d4bbb1c --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/malloc.h @@ -0,0 +1,399 @@ +/* $OpenBSD: malloc.h,v 1.127 2025/02/05 18:29:17 mvs Exp $ */ +/* $NetBSD: malloc.h,v 1.39 1998/07/12 19:52:01 augustss Exp $ */ + +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)malloc.h 8.5 (Berkeley) 5/3/95 + */ + +#ifndef _SYS_MALLOC_H_ +#define _SYS_MALLOC_H_ + +#include + +#define KERN_MALLOC_BUCKETS 1 +#define KERN_MALLOC_BUCKET 2 +#define KERN_MALLOC_KMEMNAMES 3 +#define KERN_MALLOC_KMEMSTATS 4 +#define KERN_MALLOC_MAXID 5 + +#define CTL_KERN_MALLOC_NAMES { \ + { 0, 0 }, \ + { "buckets", CTLTYPE_STRING }, \ + { "bucket", CTLTYPE_NODE }, \ + { "kmemnames", CTLTYPE_STRING }, \ + { "kmemstat", CTLTYPE_NODE }, \ +} + +/* + * flags to malloc + */ +#define M_WAITOK 0x0001 +#define M_NOWAIT 0x0002 +#define M_CANFAIL 0x0004 +#define M_ZERO 0x0008 + +/* + * Types of memory to be allocated + */ +#define M_FREE 0 /* should be on free list */ +/* 1 - free */ +#define M_DEVBUF 2 /* device driver memory */ +/* 3 - free */ +#define M_PCB 4 /* protocol control blocks */ +#define M_RTABLE 5 /* routing tables */ +#define M_PF 6 /* packet filter structures */ +/* 7 - free */ +/* 8 - free */ +#define M_IFADDR 9 /* interface addresses */ +#define M_IFGROUP 10 /* interface groups */ +#define M_SYSCTL 11 /* sysctl persistent buffers */ +#define M_COUNTERS 12 /* per-CPU counters via counters_alloc(9) */ +/* 13 - free */ +#define M_IOCTLOPS 14 /* ioctl data buffers */ +/* 15-18 - free */ +#define M_IOV 19 /* large IOVs */ +#define M_MOUNT 20 /* VFS mount structs */ +/* 21 - free */ +#define M_NFSREQ 22 /* NFS request headers */ +#define M_NFSMNT 23 /* NFS mount structures */ +#define M_LOG 24 /* messages in kernel log stash */ +#define M_VNODE 25 /* Dynamically allocated vnodes */ +/* 26 - free */ +#define M_DQUOT 27 /* UFS quota entries */ +#define M_UFSMNT 28 /* UFS mount structures */ +#define M_SHM 29 /* SVID compatible shared memory segments */ +#define M_VMMAP 30 /* VM map structures */ +#define M_SEM 31 /* SVID compatible semaphores */ +#define M_DIRHASH 32 /* UFS directory hash structures */ +#define M_ACPI 33 /* ACPI structures */ +#define M_VMPMAP 34 /* VM pmap data */ +/* 35-38 - free */ +#define M_FILEDESC 39 /* open file descriptor tables */ +#define M_SIGIO 40 /* sigio structures */ +#define M_PROC 41 /* proc structures */ +#define M_SUBPROC 42 /* proc sub-structures */ +/* 43-45 - free */ +#define M_MFSNODE 46 /* MFS vnode private part */ +/* 47-48 - free */ +#define M_NETADDR 49 /* export host address structures */ +#define M_NFSSVC 50 /* NFS server structures */ +/* 51 - free */ +#define M_NFSD 52 /* NFS server daemon structures */ +#define M_IPMOPTS 53 /* internet multicast options */ +#define M_IPMADDR 54 /* internet multicast addresses */ +#define M_IFMADDR 55 /* link-level multicast addresses */ +#define M_MRTABLE 56 /* multicast routing tables */ +#define M_ISOFSMNT 57 /* ISOFS mount structures */ +#define M_ISOFSNODE 58 /* ISOFS vnode private part */ +#define M_MSDOSFSMNT 59 /* MSDOS FS mount structures */ +#define M_MSDOSFSFAT 60 /* MSDOS FS FAT tables */ +#define M_MSDOSFSNODE 61 /* MSDOS FS vnode private part */ +#define M_TTYS 62 /* allocated tty structures */ +#define M_EXEC 63 /* argument lists & other mem used by exec */ +#define M_MISCFSMNT 64 /* miscellaneous FS mount structures */ +#define M_FUSEFS 65 /* FUSE FS mount structures */ +/* 66-73 - free */ +#define M_PFKEY 74 /* pfkey data */ +#define M_TDB 75 /* transforms database */ +#define M_XDATA 76 /* IPsec data */ +/* 77 - free */ +#define M_PAGEDEP 78 /* file page dependencies */ +#define M_INODEDEP 79 /* inode dependencies */ +#define M_NEWBLK 80 /* new block allocation */ +/* 81-82 - free */ +#define M_INDIRDEP 83 /* indirect block dependencies */ +/* 84-91 - free */ +#define M_VMSWAP 92 /* VM swap structures */ +/* 93-97 - free */ +#define M_UVMAMAP 98 /* UVM amap and related */ +#define M_UVMAOBJ 99 /* UVM aobj and related */ +#define M_PINSYSCALL 100 /* pinsyscall */ +#define M_USB 101 /* USB general */ +#define M_USBDEV 102 /* USB device driver */ +#define M_USBHC 103 /* USB host controller */ +#define M_WITNESS 104 /* witness(4) memory */ +#define M_MEMDESC 105 /* memory range */ +/* 106-107 - free */ +#define M_CRYPTO_DATA 108 /* crypto(9) data buffers */ +/* 109 - free */ +#define M_CREDENTIALS 110 /* ipsec(4) related credentials */ +/* 111-122 - free */ + +/* KAME IPv6 */ +#define M_IP6OPT 123 /* IPv6 options */ +#define M_IP6NDP 124 /* IPv6 Neighbor Discovery structures */ +/* 125-126 - free */ +#define M_TEMP 127 /* miscellaneous temporary data buffers */ + +#define M_NTFSMNT 128 /* NTFS mount structures */ +#define M_NTFSNTNODE 129 /* NTFS ntnode information */ +#define M_NTFSFNODE 130 /* NTFS fnode information */ +#define M_NTFSDIR 131 /* NTFS directory buffers */ +#define M_NTFSNTHASH 132 /* NTFS ntnode hash tables */ +#define M_NTFSNTVATTR 133 /* NTFS file attribute information */ +#define M_NTFSRDATA 134 /* NTFS resident data */ +#define M_NTFSDECOMP 135 /* NTFS decompression temporary storage */ +#define M_NTFSRUN 136 /* NTFS vrun storage */ + +#define M_KEVENT 137 /* kqueue(2) data structures */ + + /* 138 free */ +#define M_SYNCACHE 139 /* SYN cache hash array */ + +#define M_UDFMOUNT 140 /* UDF mount structures */ +#define M_UDFFENTRY 141 /* UDF file entries */ +#define M_UDFFID 142 /* UDF file IDs */ + + /* 143 free */ + +#define M_AGP 144 /* AGP memory */ + +#define M_DRM 145 /* Direct Rendering Manager */ + +#define M_LAST 146 /* Must be last type + 1 */ + +#define INITKMEMNAMES { \ + "free", /* 0 M_FREE */ \ + NULL, \ + "devbuf", /* 2 M_DEVBUF */ \ + NULL, \ + "pcb", /* 4 M_PCB */ \ + "rtable", /* 5 M_RTABLE */ \ + "pf", /* 6 M_PF */ \ + NULL, \ + NULL, \ + "ifaddr", /* 9 M_IFADDR */ \ + "ifgroup", /* 10 M_IFGROUP */ \ + "sysctl", /* 11 M_SYSCTL */ \ + "counters", /* 12 M_COUNTERS */ \ + NULL, \ + "ioctlops", /* 14 M_IOCTLOPS */ \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + "iov", /* 19 M_IOV */ \ + "mount", /* 20 M_MOUNT */ \ + NULL, \ + "NFS req", /* 22 M_NFSREQ */ \ + "NFS mount", /* 23 M_NFSMNT */ \ + "log", /* 24 M_LOG */ \ + "vnodes", /* 25 M_VNODE */ \ + NULL, \ + "UFS quota", /* 27 M_DQUOT */ \ + "UFS mount", /* 28 M_UFSMNT */ \ + "shm", /* 29 M_SHM */ \ + "VM map", /* 30 M_VMMAP */ \ + "sem", /* 31 M_SEM */ \ + "dirhash", /* 32 M_DIRHASH */ \ + "ACPI", /* 33 M_ACPI */ \ + "VM pmap", /* 34 M_VMPMAP */ \ + NULL, /* 35 */ \ + NULL, /* 36 */ \ + NULL, /* 37 */ \ + NULL, \ + "file desc", /* 39 M_FILEDESC */ \ + "sigio", /* 40 M_SIGIO */ \ + "proc", /* 41 M_PROC */ \ + "subproc", /* 42 M_SUBPROC */ \ + NULL, \ + NULL, \ + NULL, \ + "MFS node", /* 46 M_MFSNODE */ \ + NULL, \ + NULL, \ + "Export Host", /* 49 M_NETADDR */ \ + "NFS srvsock", /* 50 M_NFSSVC */ \ + NULL, \ + "NFS daemon", /* 52 M_NFSD */ \ + "ip_moptions", /* 53 M_IPMOPTS */ \ + "in_multi", /* 54 M_IPMADDR */ \ + "ether_multi", /* 55 M_IFMADDR */ \ + "mrt", /* 56 M_MRTABLE */ \ + "ISOFS mount", /* 57 M_ISOFSMNT */ \ + "ISOFS node", /* 58 M_ISOFSNODE */ \ + "MSDOSFS mount", /* 59 M_MSDOSFSMNT */ \ + "MSDOSFS fat", /* 60 M_MSDOSFSFAT */ \ + "MSDOSFS node", /* 61 M_MSDOSFSNODE */ \ + "ttys", /* 62 M_TTYS */ \ + "exec", /* 63 M_EXEC */ \ + "miscfs mount", /* 64 M_MISCFSMNT */ \ + "fusefs mount", /* 65 M_FUSEFS */ \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + "pfkey data", /* 74 M_PFKEY */ \ + "tdb", /* 75 M_TDB */ \ + "xform_data", /* 76 M_XDATA */ \ + NULL, \ + "pagedep", /* 78 M_PAGEDEP */ \ + "inodedep", /* 79 M_INODEDEP */ \ + "newblk", /* 80 M_NEWBLK */ \ + NULL, \ + NULL, \ + "indirdep", /* 83 M_INDIRDEP */ \ + NULL, NULL, NULL, NULL, \ + NULL, NULL, NULL, NULL, \ + "VM swap", /* 92 M_VMSWAP */ \ + NULL, NULL, NULL, NULL, NULL, \ + "UVM amap", /* 98 M_UVMAMAP */ \ + "UVM aobj", /* 99 M_UVMAOBJ */ \ + "pinsyscall", /* 100 M_PINSYSCALL */ \ + "USB", /* 101 M_USB */ \ + "USB device", /* 102 M_USBDEV */ \ + "USB HC", /* 103 M_USBHC */ \ + "witness", /* 104 M_WITNESS */ \ + "memdesc", /* 105 M_MEMDESC */ \ + NULL, /* 106 */ \ + NULL, \ + "crypto data", /* 108 M_CRYPTO_DATA */ \ + NULL, \ + "IPsec creds", /* 110 M_CREDENTIALS */ \ + NULL, NULL, NULL, NULL, \ + NULL, NULL, NULL, NULL, \ + NULL, NULL, NULL, NULL, \ + "ip6_options", /* 123 M_IP6OPT */ \ + "NDP", /* 124 M_IP6NDP */ \ + NULL, \ + NULL, \ + "temp", /* 127 M_TEMP */ \ + "NTFS mount", /* 128 M_NTFSMNT */ \ + "NTFS node", /* 129 M_NTFSNTNODE */ \ + "NTFS fnode", /* 130 M_NTFSFNODE */ \ + "NTFS dir", /* 131 M_NTFSDIR */ \ + "NTFS hash", /* 132 M_NTFSNTHASH */ \ + "NTFS attr", /* 133 M_NTFSNTVATTR */ \ + "NTFS data", /* 134 M_NTFSRDATA */ \ + "NTFS decomp", /* 135 M_NTFSDECOMP */ \ + "NTFS vrun", /* 136 M_NTFSRUN */ \ + "kqueue", /* 137 M_KEVENT */ \ + NULL, /* 138 free */ \ + "SYN cache", /* 139 M_SYNCACHE */ \ + "UDF mount", /* 140 M_UDFMOUNT */ \ + "UDF file entry", /* 141 M_UDFFENTRY */ \ + "UDF file id", /* 142 M_UDFFID */ \ + NULL, /* 143 free */ \ + "AGP Memory", /* 144 M_AGP */ \ + "DRM", /* 145 M_DRM */ \ +} + +struct kmemstats { + long ks_inuse; /* # of packets of this type currently in use */ + long ks_calls; /* total packets of this type ever allocated */ + long ks_memuse; /* total memory held in bytes */ + u_short ks_limblocks; /* number of times blocked for hitting limit */ + long ks_maxused; /* maximum number ever used */ + long ks_limit; /* most that are allowed to exist */ + long ks_size; /* sizes of this thing that are allocated */ + long ks_spare; +}; + +/* + * Array of descriptors that describe the contents of each page + */ +struct kmemusage { + short ku_indx; /* bucket index */ + union { + u_short freecnt;/* for small allocations, free pieces in page */ + u_short pagecnt;/* for large allocations, pages alloced */ + } ku_un; +}; +#define ku_freecnt ku_un.freecnt +#define ku_pagecnt ku_un.pagecnt + +struct kmem_freelist; + +/* + * Set of buckets for each size of memory block that is retained + */ +struct kmembuckets { + XSIMPLEQ_HEAD(, kmem_freelist) kb_freelist; /* list of free blocks */ + u_int64_t kb_calls; /* total calls to allocate this size */ + u_int64_t kb_total; /* total number of blocks allocated */ + u_int64_t kb_totalfree; /* # of free elements in this bucket */ + u_int64_t kb_elmpercl; /* # of elements in this sized allocation */ + u_int64_t kb_highwat; /* high water mark */ + u_int64_t kb_couldfree; /* over high water mark and could free */ +}; + +/* + * Constants for setting the parameters of the kernel memory allocator. + * + * 2 ** MINBUCKET is the smallest unit of memory that will be + * allocated. It must be at least large enough to hold a pointer. + * + * Units of memory less or equal to MAXALLOCSAVE will permanently + * allocate physical memory; requests for these size pieces of + * memory are quite fast. Allocations greater than MAXALLOCSAVE must + * always allocate and free physical memory; requests for these + * size allocations should be done infrequently as they will be slow. + * + * Constraints: PAGE_SIZE <= MAXALLOCSAVE <= 2 ** (MINBUCKET + 14), and + * MAXALLOCSIZE must be a power of two. + */ +#define MINBUCKET 4 /* 4 => min allocation of 16 bytes */ + +#ifdef _KERNEL + +#define MINALLOCSIZE (1 << MINBUCKET) +#define MAXALLOCSAVE (2 * PAGE_SIZE) +#define MALLOC_MAX (65535 * PAGE_SIZE) + +/* + * Turn virtual addresses into kmem map indices + */ +#define kmemxtob(alloc) (kmembase + (alloc) * PAGE_SIZE) +#define btokmemx(addr) (((caddr_t)(addr) - kmembase) / PAGE_SIZE) +#define btokup(addr) (&kmemusage[((caddr_t)(addr) - kmembase) >> PAGE_SHIFT]) + +extern struct kmemstats kmemstats[]; +extern struct kmemusage *kmemusage; +extern char *kmembase; +extern struct kmembuckets bucket[]; + +void *malloc(size_t, int, int); +void *mallocarray(size_t, size_t, int, int); +void free(void *, int, size_t); +int sysctl_malloc(int *, u_int, void *, size_t *, void *, size_t, + struct proc *); + +void malloc_printit(int (*)(const char *, ...)); + +void poison_mem(void *, size_t); +int poison_check(void *, size_t, size_t *, uint32_t *); +uint32_t poison_value(void *); + +#endif /* _KERNEL */ +#endif /* !_SYS_MALLOC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/mbuf.h b/lib/libc/include/generic-openbsd/sys/mbuf.h new file mode 100644 index 000000000000..5774ff06bba1 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/mbuf.h @@ -0,0 +1,571 @@ +/* $OpenBSD: mbuf.h,v 1.267 2025/06/25 20:26:32 miod Exp $ */ +/* $NetBSD: mbuf.h,v 1.19 1996/02/09 18:25:14 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)mbuf.h 8.5 (Berkeley) 2/19/95 + */ + +#ifndef _SYS_MBUF_H_ +#define _SYS_MBUF_H_ + +#include + +/* + * Constants related to network buffer management. + * MCLBYTES must be no larger than PAGE_SIZE (the software page size) and, + * on machines that exchange pages of input or output buffers with mbuf + * clusters (MAPPED_MBUFS), MCLBYTES must also be an integral multiple + * of the hardware page size. + */ +#define MSIZE 256 /* size of an mbuf */ + +/* + * Mbufs are of a single size, MSIZE, which includes overhead. An mbuf may + * add a single "mbuf cluster" of size MCLBYTES, which has no additional + * overhead and is used instead of the internal data area; this is done when + * at least MINCLSIZE of data must be stored. + */ + +#define MLEN (MSIZE - sizeof(struct m_hdr)) /* normal data len */ +#define MHLEN (MLEN - sizeof(struct pkthdr)) /* data len w/pkthdr */ + +#define MAXMCLBYTES (64 * 1024) /* largest cluster from the stack */ +#define MINCLSIZE (MHLEN + MLEN + 1) /* smallest amount to put in cluster */ + +#define MCLSHIFT 11 /* convert bytes to m_buf clusters */ + /* 2K cluster can hold Ether frame */ +#define MCLBYTES (1 << MCLSHIFT) /* size of a m_buf cluster */ + +/* Packet tags structure */ +struct m_tag { + SLIST_ENTRY(m_tag) m_tag_link; /* List of packet tags */ + u_int16_t m_tag_id; /* Tag ID */ + u_int16_t m_tag_len; /* Length of data */ +}; + +/* + * Macros for type conversion + * mtod(m,t) - convert mbuf pointer to data pointer of correct type + */ +#define mtod(m,t) ((t)((m)->m_data)) + +/* header at beginning of each mbuf: */ +struct m_hdr { + struct mbuf *mh_next; /* next buffer in chain */ + struct mbuf *mh_nextpkt; /* next chain in queue/record */ + caddr_t mh_data; /* location of data */ + u_int mh_len; /* amount of data in this mbuf */ + short mh_type; /* type of data in this mbuf */ + u_short mh_flags; /* flags; see below */ +#ifndef __LP64__ + u_int mh_pad; /* pad to 8-byte boundary */ +#endif +}; + +/* pf stuff */ +struct pf_state_key; +struct inpcb; + +struct pkthdr_pf { + struct pf_state_key *statekey; /* pf stackside statekey */ + struct inpcb *inp; /* connected pcb for outgoing packet */ + u_int32_t qid; /* queue id */ + u_int16_t tag; /* tag id */ + u_int16_t delay; /* delay packet by X ms */ + u_int8_t flags; + u_int8_t routed; + u_int8_t prio; + u_int8_t pad[1]; +}; + +/* pkthdr_pf.flags */ +#define PF_TAG_GENERATED 0x01 +#define PF_TAG_SYNCOOKIE_RECREATED 0x02 +#define PF_TAG_TRANSLATE_LOCALHOST 0x04 +#define PF_TAG_DIVERTED 0x08 +#define PF_TAG_DIVERTED_PACKET 0x10 +#define PF_TAG_REROUTE 0x20 +#define PF_TAG_REFRAGMENTED 0x40 /* refragmented ipv6 packet */ +#define PF_TAG_PROCESSED 0x80 /* packet was checked by pf */ + +#ifdef _KERNEL +#define MPF_BITS \ + ("\20\1GENERATED\2SYNCOOKIE_RECREATED\3TRANSLATE_LOCALHOST\4DIVERTED" \ + "\5DIVERTED_PACKET\6REROUTE\7REFRAGMENTED\10PROCESSED") +#endif + +/* record/packet header in first mbuf of chain; valid if M_PKTHDR set */ +struct pkthdr { + void *ph_cookie; /* additional data */ + SLIST_HEAD(, m_tag) ph_tags; /* list of packet tags */ + int64_t ph_timestamp; /* packet timestamp */ + int len; /* total packet length */ + u_int ph_rtableid; /* routing table id */ + u_int ph_ifidx; /* rcv interface index */ + u_int16_t ph_tagsset; /* mtags attached */ + u_int16_t ph_flowid; /* pseudo unique flow id */ + u_int16_t csum_flags; /* checksum flags */ + u_int16_t ether_vtag; /* Ethernet 802.1p+Q vlan tag */ + u_int16_t ph_mss; /* TCP max segment size */ + u_int8_t ph_loopcnt; /* mbuf is looping in kernel */ + u_int8_t ph_family; /* af, used when queueing */ + struct pkthdr_pf pf; +}; + +/* description of external storage mapped into mbuf, valid if M_EXT set */ +struct mbuf_ext { + caddr_t ext_buf; /* start of buffer */ + void *ext_arg; + u_int ext_free_fn; /* index of free function */ + u_int ext_size; /* size of buffer, for ext_free_fn */ + struct mbuf *ext_nextref; + struct mbuf *ext_prevref; +#ifdef DEBUG + const char *ext_ofile; + const char *ext_nfile; + int ext_oline; + int ext_nline; +#endif +}; + +struct mbuf { + struct m_hdr m_hdr; + union { + struct { + struct pkthdr MH_pkthdr; /* M_PKTHDR set */ + union { + struct mbuf_ext MH_ext; /* M_EXT set */ + char MH_databuf[MHLEN]; + } MH_dat; + } MH; + char M_databuf[MLEN]; /* !M_PKTHDR, !M_EXT */ + } M_dat; +}; +#define m_next m_hdr.mh_next +#define m_len m_hdr.mh_len +#define m_data m_hdr.mh_data +#define m_type m_hdr.mh_type +#define m_flags m_hdr.mh_flags +#define m_nextpkt m_hdr.mh_nextpkt +#define m_pkthdr M_dat.MH.MH_pkthdr +#define m_ext M_dat.MH.MH_dat.MH_ext +#define m_pktdat M_dat.MH.MH_dat.MH_databuf +#define m_dat M_dat.M_databuf + +/* mbuf flags */ +#define M_EXT 0x0001 /* has associated external storage */ +#define M_PKTHDR 0x0002 /* start of record */ +#define M_EOR 0x0004 /* end of record */ +#define M_EXTWR 0x0008 /* external storage is writable */ +#define M_PROTO1 0x0010 /* protocol-specific */ + +/* mbuf pkthdr flags, also in m_flags */ +#define M_VLANTAG 0x0020 /* ether_vtag is valid */ +#define M_LOOP 0x0040 /* packet has been sent from local machine */ +#define M_BCAST 0x0100 /* sent/received as link-level broadcast */ +#define M_MCAST 0x0200 /* sent/received as link-level multicast */ +#define M_CONF 0x0400 /* payload was encrypted (ESP-transport) */ +#define M_AUTH 0x0800 /* payload was authenticated (AH or ESP auth) */ +#define M_TUNNEL 0x1000 /* IP-in-IP added by tunnel mode IPsec */ +#define M_ZEROIZE 0x2000 /* Zeroize data part on free */ +#define M_COMP 0x4000 /* header was decompressed */ +#define M_LINK0 0x8000 /* link layer specific flag */ + +#ifdef _KERNEL +#define M_BITS \ + ("\20\1M_EXT\2M_PKTHDR\3M_EOR\4M_EXTWR\5M_PROTO1\6M_VLANTAG\7M_LOOP" \ + "\11M_BCAST\12M_MCAST\13M_CONF\14M_AUTH\15M_TUNNEL" \ + "\16M_ZEROIZE\17M_COMP\20M_LINK0") +#endif + +/* flags copied when copying m_pkthdr */ +#define M_COPYFLAGS (M_PKTHDR|M_EOR|M_PROTO1|M_BCAST|M_MCAST|M_CONF|M_COMP|\ + M_AUTH|M_LOOP|M_TUNNEL|M_LINK0|M_VLANTAG|M_ZEROIZE) + +/* Checksumming flags */ +#define M_IPV4_CSUM_OUT 0x0001 /* IPv4 checksum needed */ +#define M_TCP_CSUM_OUT 0x0002 /* TCP checksum needed */ +#define M_UDP_CSUM_OUT 0x0004 /* UDP checksum needed */ +#define M_IPV4_CSUM_IN_OK 0x0008 /* IPv4 checksum verified */ +#define M_IPV4_CSUM_IN_BAD 0x0010 /* IPv4 checksum bad */ +#define M_TCP_CSUM_IN_OK 0x0020 /* TCP checksum verified */ +#define M_TCP_CSUM_IN_BAD 0x0040 /* TCP checksum bad */ +#define M_UDP_CSUM_IN_OK 0x0080 /* UDP checksum verified */ +#define M_UDP_CSUM_IN_BAD 0x0100 /* UDP checksum bad */ +#define M_ICMP_CSUM_OUT 0x0200 /* ICMP/ICMPv6 checksum needed */ +#define M_ICMP_CSUM_IN_OK 0x0400 /* ICMP/ICMPv6 checksum verified */ +#define M_ICMP_CSUM_IN_BAD 0x0800 /* ICMP/ICMPv6 checksum bad */ +#define M_IPV6_DF_OUT 0x1000 /* don't fragment outgoing IPv6 */ +#define M_TIMESTAMP 0x2000 /* ph_timestamp is set */ +#define M_FLOWID 0x4000 /* ph_flowid is set */ +#define M_TCP_TSO 0x8000 /* TCP Segmentation Offload needed */ + +#ifdef _KERNEL +#define MCS_BITS \ + ("\20\1IPV4_CSUM_OUT\2TCP_CSUM_OUT\3UDP_CSUM_OUT\4IPV4_CSUM_IN_OK" \ + "\5IPV4_CSUM_IN_BAD\6TCP_CSUM_IN_OK\7TCP_CSUM_IN_BAD\10UDP_CSUM_IN_OK" \ + "\11UDP_CSUM_IN_BAD\12ICMP_CSUM_OUT\13ICMP_CSUM_IN_OK\14ICMP_CSUM_IN_BAD" \ + "\15IPV6_NODF_OUT" "\16TIMESTAMP" "\17FLOWID" "\20TCP_TSO") +#endif + +/* mbuf types */ +#define MT_FREE 0 /* should be on free list */ +#define MT_DATA 1 /* dynamic (data) allocation */ +#define MT_HEADER 2 /* packet header */ +#define MT_SONAME 3 /* socket name */ +#define MT_SOOPTS 4 /* socket options */ +#define MT_FTABLE 5 /* fragment reassembly header */ +#define MT_CONTROL 6 /* extra-data protocol message */ +#define MT_OOBDATA 7 /* expedited data */ +#define MT_NTYPES 8 + +/* flags to m_get/MGET */ +#include +#define M_DONTWAIT M_NOWAIT +#define M_WAIT M_WAITOK + +/* + * mbuf allocation/deallocation macros: + * + * MGET(struct mbuf *m, int how, int type) + * allocates an mbuf and initializes it to contain internal data. + * + * MGETHDR(struct mbuf *m, int how, int type) + * allocates an mbuf and initializes it to contain a packet header + * and internal data. + */ +#define MGET(m, how, type) m = m_get((how), (type)) + +#define MGETHDR(m, how, type) m = m_gethdr((how), (type)) + +/* + * Macros for tracking external storage associated with an mbuf. + */ +#ifdef DEBUG +#define MCLREFDEBUGN(m, file, line) do { \ + (m)->m_ext.ext_nfile = (file); \ + (m)->m_ext.ext_nline = (line); \ + } while (/* CONSTCOND */ 0) +#define MCLREFDEBUGO(m, file, line) do { \ + (m)->m_ext.ext_ofile = (file); \ + (m)->m_ext.ext_oline = (line); \ + } while (/* CONSTCOND */ 0) +#else +#define MCLREFDEBUGN(m, file, line) +#define MCLREFDEBUGO(m, file, line) +#endif + +#define MCLISREFERENCED(m) ((m)->m_ext.ext_nextref != (m)) + +#define MCLADDREFERENCE(o, n) m_extref((o), (n)) + +#define MCLINITREFERENCE(m) do { \ + (m)->m_ext.ext_prevref = (m); \ + (m)->m_ext.ext_nextref = (m); \ + MCLREFDEBUGO((m), __FILE__, __LINE__); \ + MCLREFDEBUGN((m), NULL, 0); \ + } while (/* CONSTCOND */ 0) + +/* + * Macros for mbuf external storage. + * + * MEXTADD adds pre-allocated external storage to + * a normal mbuf; the flag M_EXT is set. + * + * MCLGET allocates and adds an mbuf cluster to a normal mbuf; + * the flag M_EXT is set upon success. + */ +#define MEXTADD(m, buf, size, mflags, freefn, arg) do { \ + (m)->m_data = (m)->m_ext.ext_buf = (caddr_t)(buf); \ + (m)->m_flags |= M_EXT | (mflags & M_EXTWR); \ + (m)->m_ext.ext_size = (size); \ + (m)->m_ext.ext_free_fn = (freefn); \ + (m)->m_ext.ext_arg = (arg); \ + MCLINITREFERENCE(m); \ +} while (/* CONSTCOND */ 0) + +#define MCLGET(m, how) (void) m_clget((m), (how), MCLBYTES) +#define MCLGETL(m, how, l) m_clget((m), (how), (l)) + +u_int mextfree_register(void (*)(caddr_t, u_int, void *)); +#define MEXTFREE_POOL 0 + +/* + * Move just m_pkthdr from from to to, + * remove M_PKTHDR and clean flags/tags for from. + */ +#define M_MOVE_HDR(to, from) do { \ + (to)->m_pkthdr = (from)->m_pkthdr; \ + (from)->m_flags &= ~M_PKTHDR; \ + SLIST_INIT(&(from)->m_pkthdr.ph_tags); \ + (from)->m_pkthdr.pf.statekey = NULL; \ +} while (/* CONSTCOND */ 0) + +/* + * MOVE mbuf pkthdr from from to to. + * from must have M_PKTHDR set, and to must be empty. + */ +#define M_MOVE_PKTHDR(to, from) do { \ + (to)->m_flags = ((to)->m_flags & (M_EXT | M_EXTWR)); \ + (to)->m_flags |= (from)->m_flags & M_COPYFLAGS; \ + M_MOVE_HDR((to), (from)); \ + if (((to)->m_flags & M_EXT) == 0) \ + (to)->m_data = (to)->m_pktdat; \ +} while (/* CONSTCOND */ 0) + +/* + * Determine if an mbuf's data area is read-only. This is true for + * non-cluster external storage and for clusters that are being + * referenced by more than one mbuf. + */ +#define M_READONLY(m) \ + (((m)->m_flags & M_EXT) != 0 && \ + (((m)->m_flags & M_EXTWR) == 0 || MCLISREFERENCED(m))) + +/* + * Arrange to prepend space of size plen to mbuf m. + * If a new mbuf must be allocated, how specifies whether to wait. + * If how is M_DONTWAIT and allocation fails, the original mbuf chain + * is freed and m is set to NULL. + */ +#define M_PREPEND(m, plen, how) \ + (m) = m_prepend((m), (plen), (how)) + +/* length to m_copy to copy all */ +#define M_COPYALL 1000000000 + +enum mbstat_counters { + mbs_drops = MT_NTYPES, + mbs_wait, + mbs_drain, + mbs_defrag_alloc, + mbs_prepend_alloc, + mbs_pullup_alloc, + mbs_pullup_copy, + mbs_pulldown_alloc, + mbs_pulldown_copy, + mbs_ncounters +}; + +/* + * Mbuf statistics. + * For statistics related to mbuf and cluster allocations, see also the + * pool headers (mbpool and mclpool). + */ +struct mbstat { + u_long m_drops; /* times failed to find space */ + u_long m_wait; /* times waited for space */ + u_long m_drain; /* times drained protocols for space */ + u_long m_mtypes[MT_NTYPES]; /* type specific mbuf allocations */ + u_long m_defrag_alloc; + u_long m_prepend_alloc; + u_long m_pullup_alloc; + u_long m_pullup_copy; + u_long m_pulldown_alloc; + u_long m_pulldown_copy; +}; + +#include + +struct mbuf_list { + struct mbuf *ml_head; + struct mbuf *ml_tail; + u_int ml_len; +}; + +struct mbuf_queue { + struct mutex mq_mtx; + struct mbuf_list mq_list; + u_int mq_maxlen; + u_int mq_drops; +}; + +#ifdef _KERNEL +struct pool; + +extern long nmbclust; /* limit on the # of clusters */ +extern int max_linkhdr; /* largest link-level header */ +extern int max_protohdr; /* largest protocol header */ +extern int max_hdr; /* largest link+protocol header */ +extern struct cpumem *mbstat; /* mbuf statistics counter */ + +void mbinit(void); +void mbcpuinit(void); +int nmbclust_update(long); +struct mbuf *m_copym(struct mbuf *, int, int, int); +struct mbuf *m_free(struct mbuf *); +struct mbuf *m_get(int, int); +struct mbuf *m_getclr(int, int); +struct mbuf *m_gethdr(int, int); +struct mbuf *m_inithdr(struct mbuf *); +void m_removehdr(struct mbuf *); +void m_resethdr(struct mbuf *); +void m_calchdrlen(struct mbuf *); +int m_defrag(struct mbuf *, int); +struct mbuf *m_prepend(struct mbuf *, int, int); +struct mbuf *m_pulldown(struct mbuf *, int, int, int *); +struct mbuf *m_pullup(struct mbuf *, int); +struct mbuf *m_split(struct mbuf *, int, int); +struct mbuf *m_makespace(struct mbuf *, int, int, int *); +struct mbuf *m_getptr(struct mbuf *, int, int *); +int m_leadingspace(struct mbuf *); +int m_trailingspace(struct mbuf *); +void m_align(struct mbuf *, int); +struct mbuf *m_clget(struct mbuf *, int, u_int); +void m_extref(struct mbuf *, struct mbuf *); +void m_pool_init(struct pool *, u_int, u_int, const char *); +u_int m_pool_used(void); +void m_extfree_pool(caddr_t, u_int, void *); +void m_adj(struct mbuf *, int); +int m_copyback(struct mbuf *, int, int, const void *, int); +struct mbuf *m_freem(struct mbuf *); +void m_purge(struct mbuf *); +void m_copydata(struct mbuf *, int, int, void *); +void m_cat(struct mbuf *, struct mbuf *); +struct mbuf *m_devget(char *, int, int); +int m_apply(struct mbuf *, int, int, + int (*)(caddr_t, caddr_t, unsigned int), caddr_t); +struct mbuf *m_dup_pkt(struct mbuf *, unsigned int, int); +int m_dup_pkthdr(struct mbuf *, struct mbuf *, int); + +void m_microtime(const struct mbuf *, struct timeval *); + +static inline struct mbuf * +m_freemp(struct mbuf **mp) +{ + struct mbuf *m = *mp; + + *mp = NULL; + return m_freem(m); +} + +#include + +static inline void +mbstat_inc(enum mbstat_counters c) +{ + int s = splnet(); + counters_inc(mbstat, c); + splx(s); +} + +/* Packet tag routines */ +struct m_tag *m_tag_get(int, int, int); +void m_tag_prepend(struct mbuf *, struct m_tag *); +void m_tag_delete(struct mbuf *, struct m_tag *); +void m_tag_delete_chain(struct mbuf *); +struct m_tag *m_tag_find(struct mbuf *, int, struct m_tag *); +struct m_tag *m_tag_copy(struct m_tag *, int); +int m_tag_copy_chain(struct mbuf *, struct mbuf *, int); +struct m_tag *m_tag_first(struct mbuf *); +struct m_tag *m_tag_next(struct mbuf *, struct m_tag *); + +/* Packet tag types */ +#define PACKET_TAG_IPSEC_IN_DONE 0x0001 /* IPsec applied, in */ +#define PACKET_TAG_IPSEC_OUT_DONE 0x0002 /* IPsec applied, out */ +#define PACKET_TAG_IPSEC_FLOWINFO 0x0004 /* IPsec flowinfo */ +#define PACKET_TAG_IP_OFFNXT 0x0010 /* IPv4 offset and next proto */ +#define PACKET_TAG_IP6_OFFNXT 0x0020 /* IPv6 offset and next proto */ +#define PACKET_TAG_WIREGUARD 0x0040 /* WireGuard data */ +#define PACKET_TAG_GRE 0x0080 /* GRE processing done */ +#define PACKET_TAG_DLT 0x0100 /* data link layer type */ +#define PACKET_TAG_PF_DIVERT 0x0200 /* pf(4) diverted packet */ +#define PACKET_TAG_PF_REASSEMBLED 0x0800 /* pf reassembled ipv6 packet */ +#define PACKET_TAG_SRCROUTE 0x1000 /* IPv4 source routing options */ +#define PACKET_TAG_TUNNEL 0x2000 /* Tunnel endpoint address */ +#define PACKET_TAG_CARP_BAL_IP 0x4000 /* carp(4) ip balanced marker */ + +#define MTAG_BITS \ + ("\20\1IPSEC_IN_DONE\2IPSEC_OUT_DONE\3IPSEC_FLOWINFO" \ + "\4IPSEC_OUT_CRYPTO_NEEDED\5IPSEC_PENDING_TDB\6BRIDGE\7WG\10GRE\11DLT" \ + "\12PF_DIVERT\14PF_REASSEMBLED\15SRCROUTE\16TUNNEL\17CARP_BAL_IP") + +/* + * Maximum tag payload length (that is excluding the m_tag structure). + * Please make sure to update this value when increasing the payload + * length for an existing packet tag type or when adding a new one that + * has payload larger than the value below. + */ +#define PACKET_TAG_MAXSIZE 80 + +/* Detect mbufs looping in the kernel when spliced too often. */ +#define M_MAXLOOP 128 + +/* + * mbuf lists + */ + +#define MBUF_LIST_INITIALIZER() { NULL, NULL, 0 } + +void ml_init(struct mbuf_list *); +void ml_enqueue(struct mbuf_list *, struct mbuf *); +struct mbuf * ml_dequeue(struct mbuf_list *); +void ml_enlist(struct mbuf_list *, struct mbuf_list *); +struct mbuf * ml_dechain(struct mbuf_list *); +unsigned int ml_purge(struct mbuf_list *); +unsigned int ml_hdatalen(struct mbuf_list *); + +#define ml_len(_ml) ((_ml)->ml_len) +#define ml_empty(_ml) ((_ml)->ml_len == 0) + +#define MBUF_LIST_FIRST(_ml) ((_ml)->ml_head) +#define MBUF_LIST_NEXT(_m) ((_m)->m_nextpkt) + +#define MBUF_LIST_FOREACH(_ml, _m) \ + for ((_m) = MBUF_LIST_FIRST(_ml); \ + (_m) != NULL; \ + (_m) = MBUF_LIST_NEXT(_m)) + +/* + * mbuf queues + */ + +#include + +#define MBUF_QUEUE_INITIALIZER(_maxlen, _ipl) \ + { MUTEX_INITIALIZER(_ipl), MBUF_LIST_INITIALIZER(), (_maxlen), 0 } + +void mq_init(struct mbuf_queue *, u_int, int); +int mq_push(struct mbuf_queue *, struct mbuf *); +int mq_enqueue(struct mbuf_queue *, struct mbuf *); +struct mbuf * mq_dequeue(struct mbuf_queue *); +int mq_enlist(struct mbuf_queue *, struct mbuf_list *); +void mq_delist(struct mbuf_queue *, struct mbuf_list *); +unsigned int mq_purge(struct mbuf_queue *); +unsigned int mq_hdatalen(struct mbuf_queue *); +void mq_set_maxlen(struct mbuf_queue *, u_int); + +#define mq_len(_mq) READ_ONCE((_mq)->mq_list.ml_len) +#define mq_empty(_mq) (mq_len(_mq) == 0) +#define mq_full(_mq) (mq_len((_mq)) >= READ_ONCE((_mq)->mq_maxlen)) +#define mq_drops(_mq) READ_ONCE((_mq)->mq_drops) + +#endif /* _KERNEL */ +#endif /* _SYS_MBUF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/memrange.h b/lib/libc/include/generic-openbsd/sys/memrange.h new file mode 100644 index 000000000000..da26d0901860 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/memrange.h @@ -0,0 +1,96 @@ +/* $OpenBSD: memrange.h,v 1.10 2015/08/18 20:19:32 miod Exp $ */ +/*- + * Copyright (c) 1999 Michael Smith + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Memory range attribute operations, performed on /dev/mem + */ + +/* Memory range attributes */ +#define MDF_UNCACHEABLE (1<<0) /* region not cached */ +#define MDF_WRITECOMBINE (1<<1) /* region supports "write combine" action */ +#define MDF_WRITETHROUGH (1<<2) /* write-through cached */ +#define MDF_WRITEBACK (1<<3) /* write-back cached */ +#define MDF_WRITEPROTECT (1<<4) /* read-only region */ +#define MDF_UNKNOWN (1<<5) /* any state we don't understand */ +#define MDF_ATTRMASK (0x00ffffff) + +#define MDF_FIXBASE (1<<24) /* fixed base */ +#define MDF_FIXLEN (1<<25) /* fixed length */ +#define MDF_FIRMWARE (1<<26) /* set by firmware (XXX not useful?) */ +#define MDF_ACTIVE (1<<27) /* currently active */ +#define MDF_BOGUS (1<<28) /* we don't like it */ +#define MDF_FIXACTIVE (1<<29) /* can't be turned off */ +#define MDF_FORCE (1<<31) /* force risky changes */ + +struct mem_range_desc { + u_int64_t mr_base; + u_int64_t mr_len; + int mr_flags; + char mr_owner[8]; +}; + +struct mem_range_op { + struct mem_range_desc *mo_desc; + int mo_arg[2]; +#define MEMRANGE_SET_UPDATE 0 +#define MEMRANGE_SET_REMOVE 1 + /* XXX want a flag that says "set and undo when I exit" */ +}; + +#define MEMRANGE_GET _IOWR('m', 50, struct mem_range_op) +#define MEMRANGE_SET _IOW('m', 51, struct mem_range_op) + +/* Offset indicating a write combining mapping is requested. */ +#define MEMRANGE_WC_RANGE 0x4000000000000000ULL + +#ifdef _KERNEL + +struct mem_range_softc; +struct mem_range_ops { + void (*init)(struct mem_range_softc *sc); + int (*set)(struct mem_range_softc *sc, + struct mem_range_desc *mrd, int *arg); + void (*initAP)(struct mem_range_softc *sc); + void (*reload)(struct mem_range_softc *sc); +}; + +struct mem_range_softc { + struct mem_range_ops *mr_op; + int mr_cap; + int mr_ndesc; + struct mem_range_desc *mr_desc; +}; + +extern struct mem_range_softc mem_range_softc; + +__BEGIN_DECLS +extern void mem_range_attach(void); +extern int mem_range_attr_get(struct mem_range_desc *mrd, int *arg); +extern int mem_range_attr_set(struct mem_range_desc *mrd, int *arg); +extern void mem_range_AP_init(void); +extern void mem_range_reload(void); +__END_DECLS +#endif /* _KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/mman.h b/lib/libc/include/generic-openbsd/sys/mman.h new file mode 100644 index 000000000000..e6a2f2b3b607 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/mman.h @@ -0,0 +1,166 @@ +/* $OpenBSD: mman.h,v 1.35 2022/10/07 14:59:39 deraadt Exp $ */ +/* $NetBSD: mman.h,v 1.11 1995/03/26 20:24:23 jtc Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)mman.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _KERNEL +#include +#endif + +/* + * Protections are chosen from these bits, or-ed together + */ +#define PROT_NONE 0x00 /* no permissions */ +#define PROT_READ 0x01 /* pages can be read */ +#define PROT_WRITE 0x02 /* pages can be written */ +#define PROT_EXEC 0x04 /* pages can be executed */ + +/* + * Flags contain sharing type and options. + * Sharing types; choose one. + */ +#define MAP_SHARED 0x0001 /* share changes */ +#define MAP_PRIVATE 0x0002 /* changes are private */ + +/* + * Other flags + */ +#define MAP_FIXED 0x0010 /* map addr must be exactly as requested */ +#define __MAP_NOREPLACE 0x0800 /* fail if address not available */ +#define MAP_ANON 0x1000 /* allocated from memory, swap space */ +#define MAP_ANONYMOUS MAP_ANON /* alternate POSIX spelling */ +#define __MAP_NOFAULT 0x2000 +#define MAP_STACK 0x4000 /* mapping is used for a stack */ +#define MAP_CONCEAL 0x8000 /* omit from dumps */ + +#define MAP_FLAGMASK 0xfff7 + +#ifndef _KERNEL +/* + * Legacy defines for userland source compatibility. + * Can be removed once no longer needed in base and ports. + */ +#define MAP_COPY MAP_PRIVATE /* "copy" region at mmap time */ +#define MAP_FILE 0 /* map from file (default) */ +#define MAP_HASSEMAPHORE 0 /* region may contain semaphores */ +#define MAP_INHERIT 0 /* region is retained after exec */ +#define MAP_NOEXTEND 0 /* for MAP_FILE, don't change file size */ +#define MAP_NORESERVE 0 /* Sun: don't reserve needed swap area */ +#define MAP_RENAME 0 /* Sun: rename private pages to file */ +#define MAP_TRYFIXED 0 /* attempt hint address, even within heap */ +#endif + +/* + * Error return from mmap() + */ +#define MAP_FAILED ((void *)-1) + +/* + * POSIX memory advisory values. + * Note: keep consistent with the original definitions below. + */ +#define POSIX_MADV_NORMAL 0 /* no further special treatment */ +#define POSIX_MADV_RANDOM 1 /* expect random page references */ +#define POSIX_MADV_SEQUENTIAL 2 /* expect sequential page references */ +#define POSIX_MADV_WILLNEED 3 /* will need these pages */ +#define POSIX_MADV_DONTNEED 4 /* don't need these pages */ + +#if __BSD_VISIBLE +/* + * Original advice values, equivalent to POSIX definitions, + * and few implementation-specific ones. For in-kernel and historic use. + */ +#define MADV_NORMAL POSIX_MADV_NORMAL +#define MADV_RANDOM POSIX_MADV_RANDOM +#define MADV_SEQUENTIAL POSIX_MADV_SEQUENTIAL +#define MADV_WILLNEED POSIX_MADV_WILLNEED +#define MADV_DONTNEED POSIX_MADV_DONTNEED +#define MADV_SPACEAVAIL 5 /* insure that resources are reserved */ +#define MADV_FREE 6 /* pages are empty, free them */ +#endif + +/* + * Flags to minherit + */ +#define MAP_INHERIT_SHARE 0 /* share with child */ +#define MAP_INHERIT_COPY 1 /* copy into child */ +#define MAP_INHERIT_NONE 2 /* absent from child */ +#define MAP_INHERIT_ZERO 3 /* zero in child */ + +/* + * Flags to msync + */ +#define MS_ASYNC 0x01 /* perform asynchronous writes */ +#define MS_SYNC 0x02 /* perform synchronous writes */ +#define MS_INVALIDATE 0x04 /* invalidate cached data */ + +/* + * Flags to mlockall + */ +#define MCL_CURRENT 0x01 /* lock all pages currently mapped */ +#define MCL_FUTURE 0x02 /* lock all pages mapped in the future */ + +#ifndef _KERNEL +#include + +#ifndef _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED_ +typedef __size_t size_t; +#endif + +#ifndef _OFF_T_DEFINED_ +#define _OFF_T_DEFINED_ +typedef __off_t off_t; +#endif + +__BEGIN_DECLS +void * mmap(void *, size_t, int, int, int, off_t); +int mprotect(void *, size_t, int); +int munmap(void *, size_t); +int msync(void *, size_t, int); +int mlock(const void *, size_t); +int munlock(const void *, size_t); +int mlockall(int); +int munlockall(void); +#if __BSD_VISIBLE +int madvise(void *, size_t, int); +int minherit(void *, size_t, int); +int mimmutable(void *, size_t); +void * mquery(void *, size_t, int, int, int, off_t); +#endif +int posix_madvise(void *, size_t, int); +int shm_open(const char *, int, __mode_t); +int shm_unlink(const char *); +int shm_mkstemp(char *); +__END_DECLS + +#endif /* !_KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/mount.h b/lib/libc/include/generic-openbsd/sys/mount.h new file mode 100644 index 000000000000..f863cb68ff9d --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/mount.h @@ -0,0 +1,639 @@ +/* $OpenBSD: mount.h,v 1.153 2025/01/02 01:19:22 dlg Exp $ */ +/* $NetBSD: mount.h,v 1.48 1996/02/18 11:55:47 fvdl Exp $ */ + +/* + * Copyright (c) 1989, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)mount.h 8.15 (Berkeley) 7/14/94 + */ + +#ifndef _SYS_MOUNT_H_ +#define _SYS_MOUNT_H_ + +#include +#ifndef _KERNEL +#include +#endif +#include +#include + +typedef struct { int32_t val[2]; } fsid_t; /* file system id type */ + +/* + * File identifier. + * These are unique per filesystem on a single machine. + */ +#define MAXFIDSZ 16 + +struct fid { + u_short fid_len; /* length of data in bytes */ + u_short fid_reserved; /* force longword alignment */ + char fid_data[MAXFIDSZ]; /* data (variable length) */ +}; + +/* + * Export arguments for local filesystem mount calls. + */ +struct export_args { + int ex_flags; /* export related flags */ + uid_t ex_root; /* mapping for root uid */ + struct xucred ex_anon; /* mapping for anonymous user */ + struct sockaddr *ex_addr; /* net address to which exported */ + int ex_addrlen; /* and the net address length */ + struct sockaddr *ex_mask; /* mask of valid bits in saddr */ + int ex_masklen; /* and the smask length */ +}; + +/* + * Arguments to mount UFS-based filesystems + */ +struct ufs_args { + char *fspec; /* block special device to mount */ + struct export_args export_info;/* network export information */ +}; + +/* + * Arguments to mount MFS + */ +struct mfs_args { + char *fspec; /* name to export for statfs */ + struct export_args export_info;/* if exported MFSes are supported */ + caddr_t base; /* base of file system in memory */ + u_long size; /* size of file system */ +}; + +/* + * Arguments to mount ISO 9660 filesystems. + */ +struct iso_args { + char *fspec; /* block special device to mount */ + struct export_args export_info;/* network export info */ + int flags; /* mounting flags, see below */ + int sess; /* start sector of session */ +}; + +#define ISOFSMNT_NORRIP 0x00000001 /* disable Rock Ridge Ext.*/ +#define ISOFSMNT_GENS 0x00000002 /* enable generation numbers */ +#define ISOFSMNT_EXTATT 0x00000004 /* enable extended attr. */ +#define ISOFSMNT_NOJOLIET 0x00000008 /* disable Joliet Ext.*/ +#define ISOFSMNT_SESS 0x00000010 /* use iso_args.sess */ + +/* + * Arguments to mount NFS + */ +#define NFS_ARGSVERSION 4 /* change when nfs_args changes */ +struct nfs_args { + int version; /* args structure version number */ + struct sockaddr *addr; /* file server address */ + int addrlen; /* length of address */ + int sotype; /* Socket type */ + int proto; /* and Protocol */ + u_char *fh; /* File handle to be mounted */ + int fhsize; /* Size, in bytes, of fh */ + int flags; /* flags */ + int wsize; /* write size in bytes */ + int rsize; /* read size in bytes */ + int readdirsize; /* readdir size in bytes */ + int timeo; /* initial timeout in .1 secs */ + int retrans; /* times to retry send */ + int maxgrouplist; /* Max. size of group list */ + int readahead; /* # of blocks to readahead */ + int leaseterm; /* Term (sec) of lease */ + int deadthresh; /* Retrans threshold */ + char *hostname; /* server's name */ + int acregmin; /* Attr cache file recently modified */ + int acregmax; /* ac file not recently modified */ + int acdirmin; /* ac for dir recently modified */ + int acdirmax; /* ac for dir not recently modified */ +}; + +/* + * NFS mount option flags + */ +#define NFSMNT_RESVPORT 0x00000000 /* always use reserved ports */ +#define NFSMNT_SOFT 0x00000001 /* soft mount (hard is default) */ +#define NFSMNT_WSIZE 0x00000002 /* set write size */ +#define NFSMNT_RSIZE 0x00000004 /* set read size */ +#define NFSMNT_TIMEO 0x00000008 /* set initial timeout */ +#define NFSMNT_RETRANS 0x00000010 /* set number of request retries */ +#define NFSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */ +#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */ +#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */ +#define NFSMNT_NQNFS 0x00000100 /* Use Nqnfs protocol */ +#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */ +#define NFSMNT_KERB 0x00000400 /* Use Kerberos authentication */ +#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */ +#define NFSMNT_LEASETERM 0x00001000 /* set lease term (nqnfs) */ +#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */ +#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */ +#define NFSMNT_NOAC 0x00008000 /* disable attribute cache */ +#define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */ +#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */ + +/* Flags valid only in mount syscall arguments */ +#define NFSMNT_ACREGMIN 0x00040000 /* acregmin field valid */ +#define NFSMNT_ACREGMAX 0x00080000 /* acregmax field valid */ +#define NFSMNT_ACDIRMIN 0x00100000 /* acdirmin field valid */ +#define NFSMNT_ACDIRMAX 0x00200000 /* acdirmax field valid */ + +/* Flags valid only in kernel */ +#define NFSMNT_INTERNAL 0xfffc0000 /* Bits set internally */ +#define NFSMNT_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */ +#define NFSMNT_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */ +#define NFSMNT_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */ +#define NFSMNT_MNTD 0x00200000 /* Mnt server for mnt point */ +#define NFSMNT_DISMINPROG 0x00400000 /* Dismount in progress */ +#define NFSMNT_DISMNT 0x00800000 /* Dismounted */ +#define NFSMNT_SNDLOCK 0x01000000 /* Send socket lock */ +#define NFSMNT_WANTSND 0x02000000 /* Want above */ +#define NFSMNT_RCVLOCK 0x04000000 /* Rcv socket lock */ +#define NFSMNT_WANTRCV 0x08000000 /* Want above */ +#define NFSMNT_WAITAUTH 0x10000000 /* Wait for authentication */ +#define NFSMNT_HASAUTH 0x20000000 /* Has authenticator */ +#define NFSMNT_WANTAUTH 0x40000000 /* Wants an authenticator */ +#define NFSMNT_AUTHERR 0x80000000 /* Authentication error */ + +/* + * Arguments to mount MSDOS filesystems. + */ +struct msdosfs_args { + char *fspec; /* blocks special holding the fs to mount */ + struct export_args export_info; + /* network export information */ + uid_t uid; /* uid that owns msdosfs files */ + gid_t gid; /* gid that owns msdosfs files */ + mode_t mask; /* mask to be applied for msdosfs perms */ + int flags; /* see below */ +}; + +/* + * Msdosfs mount options: + */ +#define MSDOSFSMNT_SHORTNAME 0x01 /* Force old DOS short names only */ +#define MSDOSFSMNT_LONGNAME 0x02 /* Force Win'95 long names */ +#define MSDOSFSMNT_NOWIN95 0x04 /* Completely ignore Win95 entries */ + +/* + * Arguments to mount ntfs filesystems + */ +struct ntfs_args { + char *fspec; /* block special device to mount */ + struct export_args export_info;/* network export information */ + uid_t uid; /* uid that owns ntfs files */ + gid_t gid; /* gid that owns ntfs files */ + mode_t mode; /* mask to be applied for ntfs perms */ + u_long flag; /* additional flags */ +}; + +/* + * ntfs mount options: + */ +#define NTFS_MFLAG_CASEINS 0x00000001 +#define NTFS_MFLAG_ALLNAMES 0x00000002 + +/* Arguments to mount UDF file systems */ +struct udf_args { + char *fspec; /* Block special device to mount */ + u_int32_t lastblock; /* Special device last block */ +}; + +/* + * Arguments to mount tmpfs file systems + */ +#define TMPFS_ARGS_VERSION 1 +struct tmpfs_args { + int ta_version; + + /* Size counters. */ + ino_t ta_nodes_max; + off_t ta_size_max; + + /* Root node attributes. */ + uid_t ta_root_uid; + gid_t ta_root_gid; + mode_t ta_root_mode; +}; + +/* + * Arguments to mount fusefs filesystems + */ +struct fusefs_args { + char *name; + int fd; + int max_read; + + /* + * FUSE does not allow the file system to be accessed by other users + * unless this option is specified. This is to prevent unintentional + * denial of service to other users if the file system is not + * responding. e.g. user executes df(1) or cron job that scans mounted + * file systems. + */ + int allow_other; +}; + +/* + * file system statistics + */ + +#define MFSNAMELEN 16 /* length of fs type name, including nul */ +#define MNAMELEN 90 /* length of buffer for returned name */ + +/* per-filesystem mount options */ +union mount_info { + struct ufs_args ufs_args; + struct mfs_args mfs_args; + struct nfs_args nfs_args; + struct iso_args iso_args; + struct msdosfs_args msdosfs_args; + struct ntfs_args ntfs_args; + struct tmpfs_args tmpfs_args; + char __align[160]; /* 64-bit alignment and room to grow */ +}; + +/* new statfs structure with mount options and statvfs fields */ +struct statfs { + u_int32_t f_flags; /* copy of mount flags */ + u_int32_t f_bsize; /* file system block size */ + u_int32_t f_iosize; /* optimal transfer block size */ + + /* unit is f_bsize */ + u_int64_t f_blocks; /* total data blocks in file system */ + u_int64_t f_bfree; /* free blocks in fs */ + int64_t f_bavail; /* free blocks avail to non-superuser */ + + u_int64_t f_files; /* total file nodes in file system */ + u_int64_t f_ffree; /* free file nodes in fs */ + int64_t f_favail; /* free file nodes avail to non-root */ + + u_int64_t f_syncwrites; /* count of sync writes since mount */ + u_int64_t f_syncreads; /* count of sync reads since mount */ + u_int64_t f_asyncwrites; /* count of async writes since mount */ + u_int64_t f_asyncreads; /* count of async reads since mount */ + + fsid_t f_fsid; /* file system id */ + u_int32_t f_namemax; /* maximum filename length */ + uid_t f_owner; /* user that mounted the file system */ + u_int64_t f_ctime; /* last mount [-u] time */ + + char f_fstypename[MFSNAMELEN]; /* fs type name */ + char f_mntonname[MNAMELEN]; /* directory on which mounted */ + char f_mntfromname[MNAMELEN]; /* mounted file system */ + char f_mntfromspec[MNAMELEN]; /* special for mount request */ + union mount_info mount_info; /* per-filesystem mount options */ +}; + + +/* + * File system types. + */ +#define MOUNT_FFS "ffs" /* UNIX "Fast" Filesystem */ +#define MOUNT_UFS MOUNT_FFS /* for compatibility */ +#define MOUNT_NFS "nfs" /* Network Filesystem */ +#define MOUNT_MFS "mfs" /* Memory Filesystem */ +#define MOUNT_MSDOS "msdos" /* MSDOS Filesystem */ +#define MOUNT_AFS "afs" /* Andrew Filesystem */ +#define MOUNT_CD9660 "cd9660" /* ISO9660 (aka CDROM) Filesystem */ +#define MOUNT_EXT2FS "ext2fs" /* Second Extended Filesystem */ +#define MOUNT_NCPFS "ncpfs" /* NetWare Network File System */ +#define MOUNT_NTFS "ntfs" /* NTFS */ +#define MOUNT_UDF "udf" /* UDF */ +#define MOUNT_TMPFS "tmpfs" /* tmpfs */ +#define MOUNT_FUSEFS "fuse" /* FUSE */ + +/* + * Structure per mounted file system. Each mounted file system has an + * array of operations and an instance record. The file systems are + * put on a doubly linked list. + */ +struct mount { + TAILQ_ENTRY(mount) mnt_list; /* mount list */ + SLIST_ENTRY(mount) mnt_dounmount; /* unmount work queue */ + const struct vfsops *mnt_op; /* operations on fs */ + struct vfsconf *mnt_vfc; /* configuration info */ + struct vnode *mnt_vnodecovered; /* vnode we mounted on */ + struct vnode *mnt_syncer; /* syncer vnode */ + TAILQ_HEAD(, vnode) mnt_vnodelist; /* list of vnodes this mount */ + struct rwlock mnt_lock; /* mount structure lock */ + struct refcnt mnt_refs; + int mnt_flag; /* flags */ + struct statfs mnt_stat; /* cache of filesystem stats */ + void *mnt_data; /* private data */ +}; + +/* + * Mount flags. + * + * Unmount uses MNT_FORCE flag. + */ +#define MNT_RDONLY 0x00000001 /* read only filesystem */ +#define MNT_SYNCHRONOUS 0x00000002 /* file system written synchronously */ +#define MNT_NOEXEC 0x00000004 /* can't exec from filesystem */ +#define MNT_NOSUID 0x00000008 /* don't honor setuid bits on fs */ +#define MNT_NODEV 0x00000010 /* don't interpret special files */ +#define MNT_NOPERM 0x00000020 /* don't enforce permission checks */ +#define MNT_ASYNC 0x00000040 /* file system written asynchronously */ +#define MNT_WXALLOWED 0x00000800 /* filesystem allows W|X mappings */ + +/* + * exported mount flags. + */ +#define MNT_EXRDONLY 0x00000080 /* exported read only */ +#define MNT_EXPORTED 0x00000100 /* file system is exported */ +#define MNT_DEFEXPORTED 0x00000200 /* exported to the world */ +#define MNT_EXPORTANON 0x00000400 /* use anon uid mapping for everyone */ + +/* + * Flags set by internal operations. + */ +#define MNT_LOCAL 0x00001000 /* filesystem is stored locally */ +#define MNT_QUOTA 0x00002000 /* quotas are enabled on filesystem */ +#define MNT_ROOTFS 0x00004000 /* identifies the root filesystem */ + +/* + * Extra post 4.4BSD-lite2 mount flags. + */ +#define MNT_NOATIME 0x00008000 /* don't update access times on fs */ + +/* + * Mask of flags that are visible to statfs() + */ +#define MNT_VISFLAGMASK 0x0400ffff + +#define MNT_BITS \ + "\20\001RDONLY\002SYNCHRONOUS\003NOEXEC\004NOSUID\005NODEV\006NOPERM" \ + "\007ASYNC\010EXRDONLY\011EXPORTED\012DEFEXPORTED\013EXPORTANON" \ + "\014WXALLOWED\015LOCAL\016QUOTA\017ROOTFS\020NOATIME\021UPDATE" \ + "\022DELEXPORT\023RELOAD\024FORCE\025STALLED\026SWAPPABLE\031UNMOUNT" \ + "\032WANTRDWR\033SOFTDEP\034DOOMED" + +/* + * filesystem control flags. + */ +#define MNT_UPDATE 0x00010000 /* not a real mount, just an update */ +#define MNT_DELEXPORT 0x00020000 /* delete export host lists */ +#define MNT_RELOAD 0x00040000 /* reload filesystem data */ +#define MNT_FORCE 0x00080000 /* force unmount or readonly change */ +#define MNT_STALLED 0x00100000 /* filesystem stalled */ +#define MNT_SWAPPABLE 0x00200000 /* filesystem can be used for swap */ +#define MNT_UNMOUNT 0x01000000 /* unmount in progress */ +#define MNT_WANTRDWR 0x02000000 /* want upgrade to read/write */ +#define MNT_SOFTDEP 0x04000000 /* soft dependencies being done - now ignored */ +#define MNT_DOOMED 0x08000000 /* device behind filesystem is gone */ + +#ifdef _KERNEL +#define MNT_OP_FLAGS (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR) +#endif + +/* + * Flags for various system call interfaces. + * + * waitfor flags to vfs_sync() and getfsstat() + */ +#define MNT_WAIT 1 /* synchronously wait for I/O to complete */ +#define MNT_NOWAIT 2 /* start all I/O, but do not wait for it */ +#define MNT_LAZY 3 /* push data not written by filesystem syncer */ + +/* + * Generic file handle + */ +struct fhandle { + fsid_t fh_fsid; /* File system id of mount point */ + struct fid fh_fid; /* File sys specific id */ +}; +typedef struct fhandle fhandle_t; + +/* + * Sysctl CTL_VFS definitions. + * + * Second level identifier specifies which filesystem. Second level + * identifier VFS_GENERIC returns information about all filesystems. + */ +#define VFS_GENERIC 0 /* generic filesystem information */ +/* + * Third level identifiers for VFS_GENERIC are given below; third + * level identifiers for specific filesystems are given in their + * mount specific header files. + */ +#define VFS_MAXTYPENUM 1 /* int: highest defined filesystem type */ +#define VFS_CONF 2 /* struct: vfsconf for filesystem given + as next argument */ +#define VFS_BCACHESTAT 3 /* struct: buffer cache statistics given + as next argument */ +#define CTL_VFSGENCTL_NAMES { \ + { 0, 0 }, \ + { "maxtypenum", CTLTYPE_INT }, \ + { "conf", CTLTYPE_NODE }, \ + { "bcachestat", CTLTYPE_STRUCT } \ +} + +/* + * Filesystem configuration information. One of these exists for each + * type of filesystem supported by the kernel. These are searched at + * mount time to identify the requested filesystem. + */ +struct vfsconf { + const struct vfsops *vfc_vfsops; /* filesystem operations vector */ + char vfc_name[MFSNAMELEN]; /* filesystem type name */ + int vfc_typenum; /* historic filesystem type number */ + u_int vfc_refcount; /* number mounted of this type */ + int vfc_flags; /* permanent flags */ + size_t vfc_datasize; /* size of data args */ +}; + +/* buffer cache statistics */ +struct bcachestats { + int64_t numbufs; /* number of buffers allocated */ + int64_t numbufpages; /* number of pages in buffer cache */ + int64_t numdirtypages; /* number of dirty free pages */ + int64_t numcleanpages; /* number of clean free pages */ + int64_t pendingwrites; /* number of pending writes */ + int64_t pendingreads; /* number of pending reads */ + int64_t numwrites; /* total writes started */ + int64_t numreads; /* total reads started */ + int64_t cachehits; /* total reads found in cache */ + int64_t busymapped; /* number of busy and mapped buffers */ + int64_t dmapages; /* dma reachable pages in buffer cache */ + int64_t highpages; /* pages above dma region */ + int64_t delwribufs; /* delayed write buffers */ + int64_t kvaslots; /* kva slots total */ + int64_t kvaslots_avail; /* available kva slots */ + int64_t highflips; /* total flips to above DMA */ + int64_t highflops; /* total failed flips to above DMA */ + int64_t dmaflips; /* total flips from high to DMA */ +}; +#ifdef _KERNEL +extern struct bcachestats bcstats; +extern long buflowpages, bufhighpages, bufbackpages; +#define BUFPAGES_DEFICIT (((buflowpages - bcstats.numbufpages) < 0) ? 0 \ + : buflowpages - bcstats.numbufpages) +#define BUFPAGES_INACT (((bcstats.numcleanpages - buflowpages) < 0) ? 0 \ + : bcstats.numcleanpages - buflowpages) +extern int bufcachepercent; +extern void bufadjust(int); +struct uvm_constraint_range; +extern unsigned long bufbackoff(struct uvm_constraint_range*, long); + +/* + * Operations supported on mounted file system. + */ +struct nameidata; +struct mbuf; + +extern int maxvfsconf; /* highest defined filesystem type */ + +struct vfsops { + int (*vfs_mount)(struct mount *mp, const char *path, + void *data, + struct nameidata *ndp, struct proc *p); + int (*vfs_start)(struct mount *mp, int flags, + struct proc *p); + int (*vfs_unmount)(struct mount *mp, int mntflags, + struct proc *p); + int (*vfs_root)(struct mount *mp, struct vnode **vpp); + int (*vfs_quotactl)(struct mount *mp, int cmds, uid_t uid, + caddr_t arg, struct proc *p); + int (*vfs_statfs)(struct mount *mp, struct statfs *sbp, + struct proc *p); + int (*vfs_sync)(struct mount *mp, int waitfor, int stall, + struct ucred *cred, struct proc *p); + int (*vfs_vget)(struct mount *mp, ino_t ino, + struct vnode **vpp); + int (*vfs_fhtovp)(struct mount *mp, struct fid *fhp, + struct vnode **vpp); + int (*vfs_vptofh)(struct vnode *vp, struct fid *fhp); + int (*vfs_init)(struct vfsconf *); + int (*vfs_sysctl)(int *, u_int, void *, size_t *, void *, + size_t, struct proc *); + int (*vfs_checkexp)(struct mount *mp, struct mbuf *nam, + int *extflagsp, struct ucred **credanonp); +}; + +#define VFS_MOUNT(MP, PATH, DATA, NDP, P) \ + (*(MP)->mnt_op->vfs_mount)(MP, PATH, DATA, NDP, P) +#define VFS_START(MP, FLAGS, P) (*(MP)->mnt_op->vfs_start)(MP, FLAGS, P) +#define VFS_UNMOUNT(MP, FORCE, P) (*(MP)->mnt_op->vfs_unmount)(MP, FORCE, P) +#define VFS_ROOT(MP, VPP) (*(MP)->mnt_op->vfs_root)(MP, VPP) +#define VFS_QUOTACTL(MP,C,U,A,P) (*(MP)->mnt_op->vfs_quotactl)(MP, C, U, A, P) +#define VFS_STATFS(MP, SBP, P) (*(MP)->mnt_op->vfs_statfs)(MP, SBP, P) +#define VFS_SYNC(MP, W, S, C, P) (*(MP)->mnt_op->vfs_sync)(MP, W, S, C, P) +#define VFS_VGET(MP, INO, VPP) (*(MP)->mnt_op->vfs_vget)(MP, INO, VPP) +#define VFS_FHTOVP(MP, FIDP, VPP) \ + (*(MP)->mnt_op->vfs_fhtovp)(MP, FIDP, VPP) +#define VFS_VPTOFH(VP, FIDP) (*(VP)->v_mount->mnt_op->vfs_vptofh)(VP, FIDP) +#define VFS_CHECKEXP(MP, NAM, EXFLG, CRED) \ + (*(MP)->mnt_op->vfs_checkexp)(MP, NAM, EXFLG, CRED) + +/* Set up the filesystem operations for vnodes. */ +extern const struct vfsops ffs_vfsops; +extern const struct vfsops mfs_vfsops; +extern const struct vfsops msdosfs_vfsops; +extern const struct vfsops nfs_vfsops; +extern const struct vfsops cd9660_vfsops; +extern const struct vfsops ext2fs_vfsops; +extern const struct vfsops ntfs_vfsops; +extern const struct vfsops udf_vfsops; +extern const struct vfsops fusefs_vfsops; +extern const struct vfsops tmpfs_vfsops; + +#include +#include /* XXX for AF_MAX */ + +/* + * Network address lookup element + */ +struct netcred { + struct radix_node netc_rnodes[2]; + int netc_exflags; + int netc_len; /* size of the allocation */ + struct ucred netc_anon; +}; + +/* + * Network export information + */ +struct netexport { + struct netcred ne_defexported; /* Default export */ + struct radix_node_head *ne_rtable_inet;/* Individual exports */ +}; + +/* + * exported vnode operations + */ +int vfs_busy(struct mount *, int); +#define VB_READ 0x01 +#define VB_WRITE 0x02 +#define VB_NOWAIT 0x04 /* immediately fail on busy lock */ +#define VB_WAIT 0x08 /* sleep fail on busy lock */ +#define VB_DUPOK 0x10 /* permit duplicate mount busying */ + +int vfs_isbusy(struct mount *); +struct mount *vfs_mount_alloc(struct vnode *, struct vfsconf *); +void vfs_mount_free(struct mount *); +int vfs_mount_foreach_vnode(struct mount *, int (*func)(struct vnode *, + void *), void *); +void vfs_getnewfsid(struct mount *); +struct mount *vfs_getvfs(fsid_t *); +int vfs_mountedon(struct vnode *); +int vfs_rootmountalloc(char *, char *, struct mount **); +void vfs_unbusy(struct mount *); +extern TAILQ_HEAD(mntlist, mount) mountlist; +int vfs_stall(struct proc *, int); +void vfs_stall_barrier(void); + + /* process mount export info */ +int vfs_export(struct mount *, struct netexport *, struct export_args *); + /* lookup host in fs export list */ +struct netcred *vfs_export_lookup(struct mount *, struct netexport *, + struct mbuf *); +int vfs_allocate_syncvnode(struct mount *); + +int vfs_syncwait(struct proc *, int); /* sync and wait for complete */ +void vfs_shutdown(struct proc *); /* unmount and sync file systems */ +int dounmount(struct mount *, int, struct proc *); +void vfsinit(void); +struct vfsconf *vfs_byname(const char *); +struct vfsconf *vfs_bytypenum(int); +#else /* _KERNEL */ +__BEGIN_DECLS +int fstatfs(int, struct statfs *); +int getfh(const char *, fhandle_t *); +int getfsstat(struct statfs *, size_t, int); +int getmntinfo(struct statfs **, int); +int mount(const char *, const char *, int, void *); +int statfs(const char *, struct statfs *); +int unmount(const char *, int); +#if __BSD_VISIBLE +struct stat; +int fhopen(const fhandle_t *, int); +int fhstat(const fhandle_t *, struct stat *); +int fhstatfs(const fhandle_t *, struct statfs *); +#endif /* __BSD_VISIBLE */ +__END_DECLS +#endif /* _KERNEL */ +#endif /* !_SYS_MOUNT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/mplock.h b/lib/libc/include/generic-openbsd/sys/mplock.h new file mode 100644 index 000000000000..2a7afbd6e709 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/mplock.h @@ -0,0 +1,74 @@ +/* $OpenBSD: mplock.h,v 1.14 2024/07/03 01:36:50 jsg Exp $ */ + +/* + * Copyright (c) 2004 Niklas Hallqvist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MPLOCK_H_ +#define _MPLOCK_H_ + +#include + +#ifdef __USE_MI_MPLOCK + +#include + +struct __mp_lock_cpu { + u_int mplc_ticket; + u_int mplc_depth; +}; + +struct __mp_lock { + struct __mp_lock_cpu mpl_cpus[MAXCPUS]; + volatile u_int mpl_ticket; + u_int mpl_users; +#ifdef WITNESS + struct lock_object mpl_lock_obj; +#endif +}; + +void ___mp_lock_init(struct __mp_lock *, const struct lock_type *); +void __mp_lock(struct __mp_lock *); +void __mp_unlock(struct __mp_lock *); +int __mp_release_all(struct __mp_lock *); +void __mp_acquire_count(struct __mp_lock *, int); +int __mp_lock_held(struct __mp_lock *, struct cpu_info *); + +#ifdef WITNESS + +#define __mp_lock_init(mpl) do { \ + static const struct lock_type __lock_type = { .lt_name = #mpl };\ + ___mp_lock_init((mpl), &__lock_type); \ +} while (0) + +#else /* WITNESS */ + +#define __mp_lock_init(mpl) ___mp_lock_init((mpl), NULL) + +#endif /* WITNESS */ + +#endif /* __USE_MI_MPLOCK */ + +extern struct __mp_lock kernel_lock; + +#endif /* !_MPLOCK_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/msg.h b/lib/libc/include/generic-openbsd/sys/msg.h new file mode 100644 index 000000000000..a7a4f3a5ba62 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/msg.h @@ -0,0 +1,146 @@ +/* $OpenBSD: msg.h,v 1.24 2024/10/27 22:08:25 jsg Exp $ */ +/* $NetBSD: msg.h,v 1.9 1996/02/09 18:25:18 christos Exp $ */ + +/* + * SVID compatible msg.h file + * + * Author: Daniel Boulet + * + * Copyright 1993 Daniel Boulet and RTMX Inc. + * + * This system call was implemented by Daniel Boulet under contract from RTMX. + * + * Redistribution and use in source forms, with and without modification, + * are permitted provided that this entire comment appears intact. + * + * Redistribution in binary form may occur without any restrictions. + * Obviously, it would be nice if you gave credit where credit is due + * but requiring it would be too onerous. + * + * This software is provided ``AS IS'' without any warranties of any kind. + */ + +#ifndef _SYS_MSG_H_ +#define _SYS_MSG_H_ + +#include + +/* + * The MSG_NOERROR identifier value, the msqid_ds struct and the msg struct + * are as defined by the SV API Intel 386 Processor Supplement. + */ + +#define MSG_NOERROR 010000 /* don't complain about too long msgs */ + +typedef unsigned long msgqnum_t; +typedef unsigned long msglen_t; + +struct msqid_ds { + struct ipc_perm msg_perm; /* msg queue permission bits */ + struct msg *msg_first; /* first message in the queue */ + struct msg *msg_last; /* last message in the queue */ + msglen_t msg_cbytes; /* number of bytes in use on the queue */ + msgqnum_t msg_qnum; /* number of msgs in the queue */ + msglen_t msg_qbytes; /* max # of bytes on the queue */ + pid_t msg_lspid; /* pid of last msgsnd() */ + pid_t msg_lrpid; /* pid of last msgrcv() */ + time_t msg_stime; /* time of last msgsnd() */ + long msg_pad1; + time_t msg_rtime; /* time of last msgrcv() */ + long msg_pad2; + time_t msg_ctime; /* time of last msgctl() */ + long msg_pad3; + long msg_pad4[4]; +}; + +#ifdef _KERNEL +#include + +struct msg { + long msg_type; + size_t msg_len; + struct mbuf *msg_data; + + TAILQ_ENTRY(msg) msg_next; +}; + +struct que { + struct msqid_ds msqid_ds; + int que_ix; /* pseudo-index */ + int que_flags; + int que_references; + + TAILQ_ENTRY(que) que_next; + TAILQ_HEAD(, msg) que_msgs; +}; + +/* for que_flags */ +#define MSGQ_READERS 0x01 +#define MSGQ_WRITERS 0x02 +#define MSGQ_DYING 0x04 + +#define QREF(q) (q)->que_references++ + +#define QRELE(q) do { \ + if (--(q)->que_references == 0 && (q)->que_flags & MSGQ_DYING) \ + wakeup_one(&(q)->que_references); \ +} while (0) + +/* + * Based on the configuration parameters described in an SVR2 (yes, two) + * config(1m) man page. + * + * Each message is broken up and stored in segments that are msgssz bytes + * long. For efficiency reasons, this should be a power of two. Also, + * it doesn't make sense if it is less than 8 or greater than about 256. + * Consequently, msginit in kern/sysv_msg.c checks that msgssz is a power of + * two between 8 and 1024 inclusive (and panic's if it isn't). + */ +struct msginfo { + int msgmax, /* max chars in a message */ + msgmni, /* max message queue identifiers */ + msgmnb, /* max chars in a queue */ + msgtql, /* max messages in system */ + msgssz, /* size of a message segment (see notes above) */ + msgseg; /* number of message segments */ +}; +#ifdef SYSVMSG +extern struct msginfo msginfo; +#endif + +int sysctl_sysvmsg(int *, u_int, void *, size_t *); + +struct msg_sysctl_info { + struct msginfo msginfo; + struct msqid_ds msgids[1]; +}; + +#ifndef MSGSSZ +#define MSGSSZ 8 /* Each segment must be 2^N long */ +#endif +#ifndef MSGSEG +#define MSGSEG 2048 /* must be less than 32767 */ +#endif +#undef MSGMAX /* ALWAYS compute MSGMAX! */ +#define MSGMAX (MSGSSZ*MSGSEG) +#ifndef MSGMNB +#define MSGMNB 2048 /* max # of bytes in a queue */ +#endif +#ifndef MSGMNI +#define MSGMNI 40 +#endif +#ifndef MSGTQL +#define MSGTQL 40 +#endif + +void msginit(void); +#else /* !_KERNEL */ +__BEGIN_DECLS +int msgctl(int, int, struct msqid_ds *); +int msgget(key_t, int); +int msgsnd(int, const void *, size_t, int); +int msgrcv(int, void *, size_t, long, int); +__END_DECLS +#endif + +#endif /* !_SYS_MSG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/msgbuf.h b/lib/libc/include/generic-openbsd/sys/msgbuf.h new file mode 100644 index 000000000000..11395ce60bc9 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/msgbuf.h @@ -0,0 +1,58 @@ +/* $OpenBSD: msgbuf.h,v 1.13 2020/10/25 10:55:42 visa Exp $ */ +/* $NetBSD: msgbuf.h,v 1.8 1995/03/26 20:24:27 jtc Exp $ */ + +/* + * Copyright (c) 1981, 1984, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)msgbuf.h 8.1 (Berkeley) 6/2/93 + */ + +/* + * Locking: + * I immutable after creation + * L log_mtx + * Lw log_mtx for writing + */ +struct msgbuf { +#define MSG_MAGIC 0x063061 + long msg_magic; /* [I] buffer magic value */ + long msg_bufx; /* [L] write pointer */ + long msg_bufr; /* [L] read pointer */ + long msg_bufs; /* [I] real msg_bufc size (bytes) */ + long msg_bufd; /* [L] number of dropped bytes */ + char msg_bufc[1]; /* [Lw] buffer */ +}; +#ifdef _KERNEL +#define CONSBUFSIZE (16 * 1024) /* console message buffer size */ +extern struct msgbuf *msgbufp; +extern struct msgbuf *consbufp; + +void initmsgbuf(caddr_t buf, size_t bufsize); +void initconsbuf(void); +void msgbuf_putchar(struct msgbuf *, const char c); +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/mtio.h b/lib/libc/include/generic-openbsd/sys/mtio.h new file mode 100644 index 000000000000..c8bfe4c6c30e --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/mtio.h @@ -0,0 +1,147 @@ +/* $OpenBSD: mtio.h,v 1.9 2007/06/01 18:44:48 krw Exp $ */ +/* $NetBSD: mtio.h,v 1.14 1997/04/15 06:50:19 lukem Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)mtio.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _SYS_MTIO_H_ +#define _SYS_MTIO_H_ + +/* + * Structures and definitions for mag tape io control commands + */ + +/* structure for MTIOCTOP - mag tape op command */ +struct mtop { + short mt_op; /* operations defined below */ + int mt_count; /* how many of them */ +}; + +/* operations */ +#define MTWEOF 0 /* write an end-of-file record */ +#define MTFSF 1 /* forward space file */ +#define MTBSF 2 /* backward space file */ +#define MTFSR 3 /* forward space record */ +#define MTBSR 4 /* backward space record */ +#define MTREW 5 /* rewind */ +#define MTOFFL 6 /* rewind and put the drive offline */ +#define MTNOP 7 /* no operation, sets status only */ +#define MTRETEN 8 /* retension */ +#define MTERASE 9 /* erase entire tape */ +#define MTEOM 10 /* forward to end of media */ +#define MTNBSF 11 /* backward space to beginning of file */ +#define MTCACHE 12 /* enable controller cache */ +#define MTNOCACHE 13 /* disable controller cache */ +#define MTSETBSIZ 14 /* set block size; 0 for variable */ +#define MTSETDNSTY 15 /* set density code for current mode */ + +/* structure for MTIOCGET - mag tape get status command */ + +struct mtget { + short mt_type; /* type of magtape device */ +/* the following two registers are grossly device dependent */ + short mt_dsreg; /* ``drive status'' register */ + short mt_erreg; /* ``error'' register */ +/* end device-dependent registers */ + short mt_resid; /* residual count */ + int mt_fileno; /* current file number relative to BOT. */ + int mt_blkno; /* current block number relative to BOF. */ + int mt_blksiz; /* current block size */ + int mt_density; /* current density code */ + int mt_mblksiz; /* default block size */ + int mt_mdensity; /* default density code */ +}; + +/* + * Constants for mt_type byte. These are the same + * for controllers compatible with the types listed. + */ +#define MT_ISTS 0x01 /* TS-11 */ +#define MT_ISHT 0x02 /* TM03 Massbus: TE16, TU45, TU77 */ +#define MT_ISTM 0x03 /* TM11/TE10 Unibus */ +#define MT_ISMT 0x04 /* TM78/TU78 Massbus */ +#define MT_ISUT 0x05 /* SI TU-45 emulation on Unibus */ +#define MT_ISCPC 0x06 /* SUN */ +#define MT_ISAR 0x07 /* SUN */ +#define MT_ISTMSCP 0x08 /* DEC TMSCP protocol (TU81, TK50) */ +#define MT_ISCY 0x09 /* CCI Cipher */ +#define MT_ISCT 0x0a /* HP 1/4 tape */ +#define MT_ISFHP 0x0b /* HP 7980 1/2 tape */ +#define MT_ISEXABYTE 0x0c /* Exabyte */ +#define MT_ISEXA8200 0x0c /* Exabyte EXB-8200 */ +#define MT_ISEXA8500 0x0d /* Exabyte EXB-8500 */ +#define MT_ISVIPER1 0x0e /* Archive Viper-150 */ +#define MT_ISPYTHON 0x0f /* Archive Python (DAT) */ +#define MT_ISHPDAT 0x10 /* HP 35450A DAT drive */ +#define MT_ISWANGTEK 0x11 /* WANGTEK 5150ES */ +#define MT_ISCALIPER 0x12 /* Caliper CP150 */ +#define MT_ISWTEK5099 0x13 /* WANGTEK 5099ES */ +#define MT_ISVIPER2525 0x14 /* Archive Viper 2525 */ +#define MT_ISMFOUR 0x11 /* M4 Data 1/2 9track drive */ +#define MT_ISTK50 0x12 /* DEC SCSI TK50 */ +#define MT_ISMT02 0x13 /* Emulex MT02 SCSI tape controller */ + +/* bits defined for the mt_dsreg field */ +#define MT_DS_RDONLY 0x10 /* tape mounted readonly */ +#define MT_DS_MOUNTED 0x03 /* tape mounted (for control opens) */ + +/* mag tape io control commands */ +#define MTIOCTOP _IOW('m', 1, struct mtop) /* do a mag tape op */ +#define MTIOCGET _IOR('m', 2, struct mtget) /* get tape status */ +#define MTIOCIEOT _IO('m', 3) /* ignore EOT error */ +#define MTIOCEEOT _IO('m', 4) /* enable EOT error */ + +/* + * When more SCSI-3 SSC (streaming device) devices are out there + * that support the full 32 byte type 2 structure, we'll have to + * rethink these ioctls to support all the entities they haul into + * the picture (64 bit blocks, logical file record numbers, etc..). + */ +#define MTIOCRDSPOS _IOR('m', 5, u_int32_t) /* get logical blk addr */ +#define MTIOCRDHPOS _IOR('m', 6, u_int32_t) /* get hardware blk addr */ +#define MTIOCSLOCATE _IOW('m', 5, u_int32_t) /* seek to logical blk addr */ +#define MTIOCHLOCATE _IOW('m', 6, u_int32_t) /* seek to hardware blk addr */ + +#ifdef _KERNEL +/* + * minor device number + */ + +#define T_UNIT 003 /* unit selection */ +#define T_NOREWIND 004 /* no rewind on close */ +#define T_DENSEL 030 /* density select */ +#define T_800BPI 000 /* select 800 bpi */ +#define T_1600BPI 010 /* select 1600 bpi */ +#define T_6250BPI 020 /* select 6250 bpi */ +#define T_BADBPI 030 /* undefined selection */ +#endif /* _KERNEL */ + +#endif /* !_SYS_MTIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/mutex.h b/lib/libc/include/generic-openbsd/sys/mutex.h new file mode 100644 index 000000000000..2e66c66adaf5 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/mutex.h @@ -0,0 +1,168 @@ +/* $OpenBSD: mutex.h,v 1.23 2025/07/02 14:36:56 claudio Exp $ */ + +/* + * Copyright (c) 2004 Artur Grabowski + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_MUTEX_H_ +#define _SYS_MUTEX_H_ + +/* + * A mutex is: + * - owned by a cpu. + * - non-recursive. + * - spinning. + * - not providing mutual exclusion between processes, only cpus. + * - providing interrupt blocking when necessary. + * + * Different mutexes can be nested, but not interleaved. This is ok: + * "mtx_enter(foo); mtx_enter(bar); mtx_leave(bar); mtx_leave(foo);" + * This is _not_ ok: + * "mtx_enter(foo); mtx_enter(bar); mtx_leave(foo); mtx_leave(bar);" + */ + +/* + * To prevent lock ordering problems with the kernel lock, we need to + * make sure we block all interrupts that can grab the kernel lock. + * The simplest way to achieve this is to make sure mutexes always + * raise the interrupt priority level to the highest level that has + * interrupts that grab the kernel lock. + */ +#ifdef MULTIPROCESSOR +#define __MUTEX_IPL(ipl) \ + (((ipl) < IPL_MPFLOOR) ? IPL_MPFLOOR : (ipl)) +#else +#define __MUTEX_IPL(ipl) (ipl) +#endif + +#include + +#ifdef __USE_MI_MUTEX + +#include + +struct mutex { + void *volatile mtx_owner; + int mtx_wantipl; + int mtx_oldipl; +#ifdef WITNESS + struct lock_object mtx_lock_obj; +#endif +}; + +#ifdef WITNESS +#define MUTEX_INITIALIZER_FLAGS(ipl, name, flags) \ + { NULL, __MUTEX_IPL((ipl)), IPL_NONE, MTX_LO_INITIALIZER(name, flags) } +#else +#define MUTEX_INITIALIZER_FLAGS(ipl, name, flags) \ + { NULL, __MUTEX_IPL((ipl)), IPL_NONE } +#endif + +void __mtx_init(struct mutex *, int); +#define _mtx_init(mtx, ipl) __mtx_init((mtx), __MUTEX_IPL((ipl))) + +#ifdef DIAGNOSTIC +#define MUTEX_ASSERT_LOCKED(mtx) do { \ + if (((mtx)->mtx_owner != curcpu()) && !(panicstr || db_active)) \ + panic("mutex %p not held in %s", (mtx), __func__); \ +} while (0) + +#define MUTEX_ASSERT_UNLOCKED(mtx) do { \ + if (((mtx)->mtx_owner == curcpu()) && !(panicstr || db_active)) \ + panic("mutex %p held in %s", (mtx), __func__); \ +} while (0) +#else +#define MUTEX_ASSERT_LOCKED(mtx) do { (void)(mtx); } while (0) +#define MUTEX_ASSERT_UNLOCKED(mtx) do { (void)(mtx); } while (0) +#endif + +#define MUTEX_LOCK_OBJECT(mtx) (&(mtx)->mtx_lock_obj) +#define MUTEX_OLDIPL(mtx) (mtx)->mtx_oldipl + +#endif /* __USE_MI_MUTEX */ + + +#define MTX_LO_FLAGS(flags) \ + ((!((flags) & MTX_NOWITNESS) ? LO_WITNESS : 0) | \ + ((flags) & MTX_DUPOK ? LO_DUPOK : 0) | \ + LO_INITIALIZED | (LO_CLASS_MUTEX << LO_CLASSSHIFT)) + +#define __MTX_STRING(x) #x +#define __MTX_S(x) __MTX_STRING(x) +#define __MTX_NAME __FILE__ ":" __MTX_S(__LINE__) + +#define MTX_LO_INITIALIZER(name, flags) \ + { .lo_type = &(const struct lock_type){ .lt_name = __MTX_NAME }, \ + .lo_name = (name), \ + .lo_flags = MTX_LO_FLAGS(flags) } + +#define MTX_NOWITNESS 0x01 +#define MTX_DUPOK 0x02 + +#define MUTEX_INITIALIZER(ipl) \ + MUTEX_INITIALIZER_FLAGS(ipl, __MTX_NAME, 0) + +/* + * Some architectures need to do magic for the ipl, so they need a macro. + */ +#ifndef _mtx_init +void _mtx_init(struct mutex *, int); +#endif + +void mtx_enter(struct mutex *); +int mtx_enter_try(struct mutex *); +void mtx_leave(struct mutex *); + +#define mtx_init(m, ipl) mtx_init_flags(m, ipl, NULL, 0) + +#define mtx_owned(mtx) \ + (((mtx)->mtx_owner == curcpu()) || panicstr || db_active) + +#ifdef WITNESS + +void _mtx_init_flags(struct mutex *, int, const char *, int, + const struct lock_type *); + +#define mtx_init_flags(m, ipl, name, flags) do { \ + static const struct lock_type __lock_type = { .lt_name = #m }; \ + _mtx_init_flags(m, ipl, name, flags, &__lock_type); \ +} while (0) + +#else /* WITNESS */ + +#define mtx_init_flags(m, ipl, name, flags) do { \ + (void)(name); (void)(flags); \ + _mtx_init(m, ipl); \ +} while (0) + +#define _mtx_init_flags(m,i,n,f,t) _mtx_init(m,i) + +#endif /* WITNESS */ + +#if defined(_KERNEL) && defined(DDB) + +struct db_mutex { + struct cpu_info *volatile mtx_owner; + unsigned long mtx_intr_state; +}; + +#define DB_MUTEX_INITIALIZER { NULL, 0 } + +void db_mtx_enter(struct db_mutex *); +void db_mtx_leave(struct db_mutex *); + +#endif /* _KERNEL && DDB */ + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/namei.h b/lib/libc/include/generic-openbsd/sys/namei.h new file mode 100644 index 000000000000..02339cab414d --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/namei.h @@ -0,0 +1,274 @@ +/* $OpenBSD: namei.h,v 1.50 2022/01/11 23:59:55 jsg Exp $ */ +/* $NetBSD: namei.h,v 1.11 1996/02/09 18:25:20 christos Exp $ */ + +/* + * Copyright (c) 1985, 1989, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)namei.h 8.4 (Berkeley) 8/20/94 + */ + +#ifndef _SYS_NAMEI_H_ +#define _SYS_NAMEI_H_ + +#include +#include +#include + +struct unveil; + +/* + * Encapsulation of namei parameters. + */ +struct nameidata { + /* + * Arguments to namei/lookup. + */ + const char *ni_dirp; /* pathname pointer */ + int ni_dirfd; /* dirfd from *at() functions */ + enum uio_seg ni_segflg; /* location of pathname */ + /* u_long ni_nameiop; namei operation */ + /* u_long ni_flags; flags to namei */ + /* struct proc *ni_proc; process requesting lookup */ + /* + * Arguments to lookup. + */ + /* struct ucred *ni_cred; credentials */ + struct vnode *ni_startdir; /* starting directory */ + struct vnode *ni_rootdir; /* logical root directory */ + uint64_t ni_pledge; /* expected pledge for namei */ + u_char ni_unveil; /* required unveil flags for namei */ + /* + * Results: returned from/manipulated by lookup + */ + struct vnode *ni_vp; /* vnode of result */ + struct vnode *ni_dvp; /* vnode of intermediate directory */ + + /* + * Shared between namei and lookup/commit routines. + */ + size_t ni_pathlen; /* remaining chars in path */ + char *ni_next; /* next location in pathname */ + u_long ni_loopcnt; /* count of symlinks encountered */ + struct unveil *ni_unveil_match; /* last matching unveil component */ + + /* + * Lookup parameters: this structure describes the subset of + * information from the nameidata structure that is passed + * through the VOP interface. + */ + struct componentname { + /* + * Arguments to lookup. + */ + u_long cn_nameiop; /* namei operation */ + u_long cn_flags; /* flags to namei */ + struct proc *cn_proc; /* process requesting lookup */ + struct ucred *cn_cred; /* credentials */ + /* + * Shared between lookup and commit routines. + */ + char *cn_pnbuf; /* pathname buffer */ + char *cn_rpbuf; /* realpath buffer */ + size_t cn_rpi; /* realpath index */ + char *cn_nameptr; /* pointer to looked up name */ + long cn_namelen; /* length of looked up component */ + long cn_consume; /* chars to consume in lookup() */ + } ni_cnd; +}; + +#ifdef _KERNEL +/* + * namei operations + */ +#define LOOKUP 0 /* perform name lookup only */ +#define CREATE 1 /* setup for file creation */ +#define DELETE 2 /* setup for file deletion */ +#define RENAME 3 /* setup for file renaming */ +#define OPMASK 3 /* mask for operation */ +/* + * namei operational modifier flags, stored in ni_cnd.flags + */ +#define LOCKLEAF 0x0004 /* lock inode on return */ +#define LOCKPARENT 0x0008 /* want parent vnode returned locked */ +#define WANTPARENT 0x0010 /* want parent vnode returned unlocked */ +#define NOCACHE 0x0020 /* name must not be left in cache */ +#define FOLLOW 0x0040 /* follow symbolic links */ +#define NOFOLLOW 0x0000 /* do not follow symbolic links (pseudo) */ +#define MODMASK 0x00fc /* mask of operational modifiers */ +/* + * Namei parameter descriptors. + * + * SAVENAME may be set by either the callers of namei or by VOP_LOOKUP. + * If the caller of namei sets the flag (for example execve wants to + * know the name of the program that is being executed), then it must + * free the buffer. If VOP_LOOKUP sets the flag, then the buffer must + * be freed by either the commit routine or the VOP_ABORT routine. + * SAVESTART is set only by the callers of namei. It implies SAVENAME + * plus the addition of saving the parent directory that contains the + * name in ni_startdir. It allows repeated calls to lookup for the + * name being sought. The caller is responsible for releasing the + * buffer and for vrele'ing ni_startdir. + */ +#define NOCROSSMOUNT 0x000100 /* do not cross mount points */ +#define RDONLY 0x000200 /* lookup with read-only semantics */ +#define HASBUF 0x000400 /* has allocated pathname buffer */ +#define SAVENAME 0x000800 /* save pathname buffer */ +#define SAVESTART 0x001000 /* save starting directory */ +#define ISDOTDOT 0x002000 /* current component name is .. */ +#define MAKEENTRY 0x004000 /* entry is to be added to name cache */ +#define ISLASTCN 0x008000 /* this is last component of pathname */ +#define ISSYMLINK 0x010000 /* symlink needs interpretation */ +#define REALPATH 0x020000 /* save pathname buffer for realpath */ +#define REQUIREDIR 0x080000 /* must be a directory */ +#define STRIPSLASHES 0x100000 /* strip trailing slashes */ +#define PDIRUNLOCK 0x200000 /* vfs_lookup() unlocked parent dir */ +#define BYPASSUNVEIL 0x400000 /* bypass pledgepath check */ +#define KERNELPATH 0x800000 /* access file as kernel, not process */ + +/* + * Initialization of an nameidata structure. + */ +void ndinitat(struct nameidata *ndp, u_long op, u_long flags, + enum uio_seg segflg, int dirfd, const char *namep, struct proc *p); + +#define NDINITAT(ndp, op, flags, segflg, dirfd, namep, p) \ + ndinitat(ndp, op, flags, segflg, dirfd, namep, p) + +#define NDINIT(ndp, op, flags, segflp, namep, p) \ + ndinitat(ndp, op, flags, segflp, AT_FDCWD, namep, p) + +/* Defined for users of NDINIT(). */ +#define AT_FDCWD -100 +#endif + +/* + * This structure describes the elements in the cache of recent + * names looked up by namei. + */ + +#define NAMECACHE_MAXLEN 31 /* maximum name segment length we bother with */ + +struct namecache { + TAILQ_ENTRY(namecache) nc_lru; /* Regular Entry LRU chain */ + TAILQ_ENTRY(namecache) nc_neg; /* Negative Entry LRU chain */ + RBT_ENTRY(namecache) n_rbcache; /* Namecache rb tree from vnode */ + TAILQ_ENTRY(namecache) nc_me; /* ncp's referring to me */ + struct vnode *nc_dvp; /* vnode of parent of name */ + u_long nc_dvpid; /* capability number of nc_dvp */ + struct vnode *nc_vp; /* vnode the name refers to */ + u_long nc_vpid; /* capability number of nc_vp */ + char nc_nlen; /* length of name */ + char nc_name[NAMECACHE_MAXLEN]; /* segment name */ +}; + +#ifdef _KERNEL +struct namecache_rb_cache; + +int namei(struct nameidata *ndp); +int vfs_lookup(struct nameidata *ndp); +int vfs_relookup(struct vnode *dvp, struct vnode **vpp, + struct componentname *cnp); +void cache_tree_init(struct namecache_rb_cache *); +void cache_purge(struct vnode *); +int cache_lookup(struct vnode *, struct vnode **, struct componentname *); +void cache_enter(struct vnode *, struct vnode *, struct componentname *); +int cache_revlookup(struct vnode *, struct vnode **, char **, char *); +void nchinit(void); +struct mount; +void cache_purgevfs(struct mount *); + +int unveil_add(struct proc *, struct nameidata *, const char *); +void unveil_removevnode(struct vnode *); +ssize_t unveil_find_cover(struct vnode *, struct proc *); +struct unveil *unveil_lookup(struct vnode *, struct process *, ssize_t *); +void unveil_start_relative(struct proc *, struct nameidata *, struct vnode *); +void unveil_check_component(struct proc *, struct nameidata *, struct vnode *); +int unveil_check_final(struct proc *, struct nameidata *); + +extern struct pool namei_pool; + +#endif + +/* + * Stats on usefulness of namei caches. + */ +struct nchstats { + u_int64_t ncs_goodhits; /* hits that we can really use */ + u_int64_t ncs_neghits; /* negative hits that we can use */ + u_int64_t ncs_badhits; /* hits we must drop */ + u_int64_t ncs_falsehits; /* hits with id mismatch */ + u_int64_t ncs_miss; /* misses */ + u_int64_t ncs_long; /* long names that ignore cache */ + u_int64_t ncs_pass2; /* names found with passes == 2 */ + u_int64_t ncs_2passes; /* number of times we attempt it */ + u_int64_t ncs_revhits; /* reverse-cache hits */ + u_int64_t ncs_revmiss; /* reverse-cache misses */ + u_int64_t ncs_dothits; /* hits on '.' lookups */ + u_int64_t ncs_dotdothits; /* hits on '..' lookups */ +}; + +/* These sysctl names are only really used by sysctl(8) */ +#define KERN_NCHSTATS_GOODHITS 1 +#define KERN_NCHSTATS_NEGHITS 2 +#define KERN_NCHSTATS_BADHITS 3 +#define KERN_NCHSTATS_FALSEHITS 4 +#define KERN_NCHSTATS_MISS 5 +#define KERN_NCHSTATS_LONG 6 +#define KERN_NCHSTATS_PASS2 7 +#define KERN_NCHSTATS_2PASSES 8 +#define KERN_NCHSTATS_REVHITS 9 +#define KERN_NCHSTATS_REVMISS 10 +#define KERN_NCHSTATS_DOTHITS 11 +#define KERN_NCHSTATS_DOTDOTHITS 12 +#define KERN_NCHSTATS_MAXID 13 + +#define CTL_KERN_NCHSTATS_NAMES { \ + { 0, 0 }, \ + { "good_hits", CTLTYPE_QUAD }, \ + { "negative_hits", CTLTYPE_QUAD }, \ + { "bad_hits", CTLTYPE_QUAD }, \ + { "false_hits", CTLTYPE_QUAD }, \ + { "misses", CTLTYPE_QUAD }, \ + { "long_names", CTLTYPE_QUAD }, \ + { "pass2", CTLTYPE_QUAD }, \ + { "2passes", CTLTYPE_QUAD }, \ + { "ncs_revhits", CTLTYPE_QUAD }, \ + { "ncs_revmiss", CTLTYPE_QUAD }, \ + { "ncs_dothits", CTLTYPE_QUAD }, \ + { "nch_dotdothits", CTLTYPE_QUAD }, \ +} + +/* Unveil flags for namei */ +#define UNVEIL_READ 0x01 +#define UNVEIL_WRITE 0x02 +#define UNVEIL_CREATE 0x04 +#define UNVEIL_EXEC 0x08 +#define UNVEIL_USERSET 0x10 +#define UNVEIL_MASK 0x0F + +#endif /* !_SYS_NAMEI_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/param.h b/lib/libc/include/generic-openbsd/sys/param.h new file mode 100644 index 000000000000..e86909313f83 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/param.h @@ -0,0 +1,223 @@ +/* $OpenBSD: param.h,v 1.145 2025/09/10 16:00:04 deraadt Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _SYS_PARAM_H_ +#define _SYS_PARAM_H_ + +#define BSD 199306 /* System version (year & month). */ +#define BSD4_3 1 +#define BSD4_4 1 + +/* zig patch: ___OpenBSD and OpenBSDX_Y are defined by the compiler */ +#define OpenBSD ___OpenBSD + +#include + +#ifndef _LOCORE +#include +#endif + +/* + * Machine-independent constants (some used in following include files). + * Redefined constants are from POSIX 1003.1 limits file. + * + * MAXCOMLEN should be >= sizeof(ac_comm) (see ) + * MAXLOGNAME should be >= UT_NAMESIZE (see ) + */ +#include + +#define MAXCOMLEN _MAXCOMLEN-1 /* max command name remembered, without NUL */ +#define MAXINTERP 128 /* max interpreter file name length */ +#define MAXLOGNAME LOGIN_NAME_MAX /* max login name length w/ NUL */ +#define MAXUPRC CHILD_MAX /* max simultaneous processes */ +#define NCARGS ARG_MAX /* max bytes for an exec function */ +#define NGROUPS NGROUPS_MAX /* max number groups */ +#define NOFILE OPEN_MAX /* max open files per process (soft) */ +#define NOFILE_MAX 1024 /* max open files per process (hard) */ +#define NOGROUP 65535 /* marker for empty group set member */ +#define MAXHOSTNAMELEN 256 /* max hostname length w/ NUL */ + +/* More types and definitions used throughout the kernel. */ +#ifdef _KERNEL +#include +#include +#include +#include +#include +#include +#endif + +/* Signals. */ +#include + +/* Machine type dependent parameters. */ +#include +#include + +#ifdef _KERNEL +/* + * Priorities. Note that with 32 run queues, differences less than 4 are + * insignificant. + */ +#define PSWP 0 +#define PVM 4 +#define PINOD 8 +#define PRIBIO 16 +#define PVFS 20 +#endif /* _KERNEL */ +#define PZERO 22 /* No longer magic, shouldn't be here. XXX */ +#ifdef _KERNEL +#define PSOCK 24 +#define PWAIT 32 +#define PLOCK 36 +#define PPAUSE 40 +#define PUSER 50 +#define MAXPRI 127 /* Priorities range from 0 through MAXPRI. */ + +#define PRIMASK 0x0ff +#define PCATCH 0x100 /* OR'd with pri for tsleep to check signals */ +#define PNORELOCK 0x200 /* OR'd with pri for msleep to not reacquire + the mutex */ +#endif /* _KERNEL */ + +#define NODEV (dev_t)(-1) /* non-existent device */ + +#define ALIGNBYTES _ALIGNBYTES +#define ALIGN(p) _ALIGN(p) +#define ALIGNED_POINTER(p,t) _ALIGNED_POINTER(p,t) + +/* + * File system parameters and macros. + * + * The file system is made out of blocks of at most MAXBSIZE units, with + * smaller units (fragments) only in the last direct block. MAXBSIZE + * primarily determines the size of buffers in the buffer pool. It may be + * made larger without any effect on existing file systems; however making + * it smaller makes some file systems unmountable. + */ +#ifdef _KERNEL +#define MAXPHYS (64 * 1024) /* max raw I/O transfer size */ +#endif /* _KERNEL */ +#define MAXBSIZE (64 * 1024) + +#define _DEV_BSHIFT 9 /* log2(DEV_BSIZE) */ +#define DEV_BSIZE (1 << _DEV_BSHIFT) +#ifdef _KERNEL +#define DEV_BSHIFT _DEV_BSHIFT +#define BLKDEV_IOSIZE PAGE_SIZE +#endif /* _KERNEL */ + +/* pages to disk blocks */ +#ifndef ctod +#define ctod(x) ((x) << (PAGE_SHIFT - _DEV_BSHIFT)) +#endif +#ifndef dtoc +#define dtoc(x) ((x) >> (PAGE_SHIFT - _DEV_BSHIFT)) +#endif + +/* bytes to disk blocks */ +#ifndef btodb +#define btodb(x) ((x) >> _DEV_BSHIFT) +#endif +#ifndef dbtob +#define dbtob(x) ((x) << _DEV_BSHIFT) +#endif + +/* + * MAXPATHLEN defines the longest permissible path length after expanding + * symbolic links. It is used to allocate a temporary buffer from the buffer + * pool in which to do the name expansion, hence should be a power of two, + * and must be less than or equal to MAXBSIZE. MAXSYMLINKS defines the + * maximum number of symbolic links that may be expanded in a path name. + * It should be set high enough to allow all legitimate uses, but halt + * infinite loops reasonably quickly. + */ +#define MAXPATHLEN PATH_MAX +#define MAXSYMLINKS SYMLOOP_MAX + +/* Macros to set/clear/test flags. */ +#ifdef _KERNEL +#define SET(t, f) ((t) |= (f)) +#define CLR(t, f) ((t) &= ~(f)) +#define ISSET(t, f) ((t) & (f)) +#endif /* _KERNEL */ + +/* Bit map related macros. */ +#define setbit(a,i) ((a)[(i)>>3] |= 1<<((i)&(NBBY-1))) +#define clrbit(a,i) ((a)[(i)>>3] &= ~(1<<((i)&(NBBY-1)))) +#define isset(a,i) ((a)[(i)>>3] & (1<<((i)&(NBBY-1)))) +#define isclr(a,i) (((a)[(i)>>3] & (1<<((i)&(NBBY-1)))) == 0) + +/* Macros for counting and rounding. */ +#ifndef howmany +#define howmany(x, y) (((x)+((y)-1))/(y)) +#endif +#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) +#define powerof2(x) ((((x)-1)&(x))==0) + +/* Macros for min/max. */ +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + +/* Macros for calculating the offset of a field */ +#if !defined(offsetof) && defined(_KERNEL) +#if __GNUC_PREREQ__(4, 0) +#define offsetof(s, e) __builtin_offsetof(s, e) +#else +#define offsetof(s, e) ((size_t)&((s *)0)->e) +#endif +#endif /* !defined(offsetof) && defined(_KERNEL) */ + +#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) + +/* + * Scale factor for scaled integers used to count %cpu time and load avgs. + * + * The number of CPU `tick's that map to a unique `%age' can be expressed + * by the formula (1 / (2 ^ (FSHIFT - 11))). The maximum load average that + * can be calculated (assuming 32 bits) can be closely approximated using + * the formula (2 ^ (2 * (16 - FSHIFT))) for (FSHIFT < 15). + * + * For the scheduler to maintain a 1:1 mapping of CPU `tick' to `%age', + * FSHIFT must be at least 11; this gives us a maximum load avg of ~1024. + */ +#define _FSHIFT 11 /* bits to right of fixed binary point */ +#ifdef _KERNEL +#define FSHIFT _FSHIFT +#endif +#define FSCALE (1<<_FSHIFT) + +#endif /* !_SYS_PARAM_H_ */ diff --git a/lib/libc/include/generic-openbsd/sys/pciio.h b/lib/libc/include/generic-openbsd/sys/pciio.h new file mode 100644 index 000000000000..1e3b6fcaf21e --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/pciio.h @@ -0,0 +1,86 @@ +/* $OpenBSD: pciio.h,v 1.8 2020/06/22 04:11:37 dlg Exp $ */ + +/*- + * Copyright (c) 1997, Stefan Esser + * Copyright (c) 1997, 1998, 1999, Kenneth D. Merry + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/sys/sys/pciio.h,v 1.5 1999/12/08 17:44:04 ken Exp $ + * + */ + +#ifndef _SYS_PCIIO_H_ +#define _SYS_PCIIO_H_ + +#include + +struct pcisel { + u_int8_t pc_bus; /* bus number */ + u_int8_t pc_dev; /* device on this bus */ + u_int8_t pc_func; /* function on this device */ +}; + +struct pci_io { + struct pcisel pi_sel; /* device to operate on */ + int pi_reg; /* configuration register to examine */ + int pi_width; /* width (in bytes) of read or write */ + u_int32_t pi_data; /* data to write or result of read */ +}; + +struct pci_rom { + struct pcisel pr_sel; + int pr_romlen; + char *pr_rom; +}; + +struct pci_vpd_req { + struct pcisel pv_sel; + int pv_offset; + int pv_count; + uint32_t *pv_data; +}; + +struct pci_vga { + struct pcisel pv_sel; + int pv_lock; + int pv_decode; +}; + +#define PCI_VGA_UNLOCK 0x00 +#define PCI_VGA_LOCK 0x01 +#define PCI_VGA_TRYLOCK 0x02 + +#define PCI_VGA_IO_ENABLE 0x01 +#define PCI_VGA_MEM_ENABLE 0x02 + +#define PCIOCREAD _IOWR('p', 2, struct pci_io) +#define PCIOCWRITE _IOWR('p', 3, struct pci_io) +#define PCIOCGETROMLEN _IOWR('p', 4, struct pci_rom) +#define PCIOCGETROM _IOWR('p', 5, struct pci_rom) +#define PCIOCGETVGA _IOWR('p', 6, struct pci_vga) +#define PCIOCSETVGA _IOWR('p', 7, struct pci_vga) +#define PCIOCREADMASK _IOWR('p', 8, struct pci_io) +#define PCIOCGETVPD _IOWR('p', 9, struct pci_vpd_req) + +#endif /* !_SYS_PCIIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/pclock.h b/lib/libc/include/generic-openbsd/sys/pclock.h new file mode 100644 index 000000000000..594102eb16e9 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/pclock.h @@ -0,0 +1,49 @@ +/* $OpenBSD: pclock.h,v 1.1 2025/05/31 10:24:50 dlg Exp $ */ + +/* + * Copyright (c) 2023 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_PCLOCK_H +#define _SYS_PCLOCK_H + +#include + +struct pc_lock { + volatile unsigned int pcl_gen; +}; + +#ifdef _KERNEL + +#define PC_LOCK_INITIALIZER() { .pcl_gen = 0 } + +void pc_lock_init(struct pc_lock *); + +/* single (non-interlocking) producer */ +unsigned int pc_sprod_enter(struct pc_lock *); +void pc_sprod_leave(struct pc_lock *, unsigned int); + +/* multiple (interlocking) producers */ +unsigned int pc_mprod_enter(struct pc_lock *); +void pc_mprod_leave(struct pc_lock *, unsigned int); + +/* consumer */ +void pc_cons_enter(struct pc_lock *, unsigned int *); +__warn_unused_result int + pc_cons_leave(struct pc_lock *, unsigned int *); + +#endif /* _KERNEL */ + +#endif /* _SYS_PCLOCK_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/percpu.h b/lib/libc/include/generic-openbsd/sys/percpu.h new file mode 100644 index 000000000000..3457bdb0f2ba --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/percpu.h @@ -0,0 +1,199 @@ +/* $OpenBSD: percpu.h,v 1.9 2023/09/16 09:33:27 mpi Exp $ */ + +/* + * Copyright (c) 2016 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_PERCPU_H_ +#define _SYS_PERCPU_H_ + +#ifndef CACHELINESIZE +#define CACHELINESIZE 64 +#endif + +#ifndef __upunused /* this should go in param.h */ +#ifdef MULTIPROCESSOR +#define __upunused +#else +#define __upunused __attribute__((__unused__)) +#endif +#endif + +struct cpumem { + void *mem; +}; + +struct cpumem_iter { + unsigned int cpu; +} __upunused; + +struct counters_ref { + uint64_t g; + uint64_t *c; +}; + +#ifdef _KERNEL + +#include + +struct pool; + +struct cpumem *cpumem_get(struct pool *); +void cpumem_put(struct pool *, struct cpumem *); + +struct cpumem *cpumem_malloc(size_t, int); +struct cpumem *cpumem_malloc_ncpus(struct cpumem *, size_t, int); +void cpumem_free(struct cpumem *, int, size_t); + +void *cpumem_first(struct cpumem_iter *, struct cpumem *); +void *cpumem_next(struct cpumem_iter *, struct cpumem *); + +static inline void * +cpumem_enter(struct cpumem *cm) +{ +#ifdef MULTIPROCESSOR + return (cm[cpu_number()].mem); +#else + return (cm); +#endif +} + +static inline void +cpumem_leave(struct cpumem *cm, void *mem) +{ + /* KDASSERT? */ +} + +#ifdef MULTIPROCESSOR + +#define CPUMEM_BOOT_MEMORY(_name, _sz) \ +static struct { \ + unsigned char mem[_sz]; \ + struct cpumem cpumem; \ +} __aligned(CACHELINESIZE) _name##_boot_cpumem = { \ + .cpumem = { _name##_boot_cpumem.mem } \ +} + +#define CPUMEM_BOOT_INITIALIZER(_name) \ + { &_name##_boot_cpumem.cpumem } + +#else /* MULTIPROCESSOR */ + +#define CPUMEM_BOOT_MEMORY(_name, _sz) \ +static struct { \ + unsigned char mem[_sz]; \ +} __aligned(sizeof(uint64_t)) _name##_boot_cpumem + +#define CPUMEM_BOOT_INITIALIZER(_name) \ + { (struct cpumem *)&_name##_boot_cpumem.mem } + +#endif /* MULTIPROCESSOR */ + +#define CPUMEM_FOREACH(_var, _iter, _cpumem) \ + for ((_var) = cpumem_first((_iter), (_cpumem)); \ + (_var) != NULL; \ + (_var) = cpumem_next((_iter), (_cpumem))) + +/* + * per cpu counters + */ + +struct cpumem *counters_alloc(unsigned int); +struct cpumem *counters_alloc_ncpus(struct cpumem *, unsigned int); +void counters_free(struct cpumem *, unsigned int); +void counters_read(struct cpumem *, uint64_t *, unsigned int, + uint64_t *); +void counters_zero(struct cpumem *, unsigned int); + +static inline uint64_t * +counters_enter(struct counters_ref *ref, struct cpumem *cm) +{ + ref->c = cpumem_enter(cm); +#ifdef MULTIPROCESSOR + ref->g = ++(*ref->c); /* make the generation number odd */ + membar_producer(); + return (ref->c + 1); +#else + return (ref->c); +#endif +} + +static inline void +counters_leave(struct counters_ref *ref, struct cpumem *cm) +{ +#ifdef MULTIPROCESSOR + membar_producer(); + (*ref->c) = ++ref->g; /* make the generation number even again */ +#endif + cpumem_leave(cm, ref->c); +} + +static inline void +counters_inc(struct cpumem *cm, unsigned int c) +{ + struct counters_ref ref; + uint64_t *counters; + + counters = counters_enter(&ref, cm); + counters[c]++; + counters_leave(&ref, cm); +} + +static inline void +counters_dec(struct cpumem *cm, unsigned int c) +{ + struct counters_ref ref; + uint64_t *counters; + + counters = counters_enter(&ref, cm); + counters[c]--; + counters_leave(&ref, cm); +} + +static inline void +counters_add(struct cpumem *cm, unsigned int c, uint64_t v) +{ + struct counters_ref ref; + uint64_t *counters; + + counters = counters_enter(&ref, cm); + counters[c] += v; + counters_leave(&ref, cm); +} + +static inline void +counters_pkt(struct cpumem *cm, unsigned int c, unsigned int b, uint64_t v) +{ + struct counters_ref ref; + uint64_t *counters; + + counters = counters_enter(&ref, cm); + counters[c]++; + counters[b] += v; + counters_leave(&ref, cm); +} + +#ifdef MULTIPROCESSOR +#define COUNTERS_BOOT_MEMORY(_name, _n) \ + CPUMEM_BOOT_MEMORY(_name, ((_n) + 1) * sizeof(uint64_t)) +#else +#define COUNTERS_BOOT_MEMORY(_name, _n) \ + CPUMEM_BOOT_MEMORY(_name, (_n) * sizeof(uint64_t)) +#endif + +#define COUNTERS_BOOT_INITIALIZER(_name) CPUMEM_BOOT_INITIALIZER(_name) + +#endif /* _KERNEL */ +#endif /* _SYS_PERCPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/pipe.h b/lib/libc/include/generic-openbsd/sys/pipe.h new file mode 100644 index 000000000000..38b442b13b40 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/pipe.h @@ -0,0 +1,98 @@ +/* $OpenBSD: pipe.h,v 1.29 2022/07/09 12:48:21 visa Exp $ */ + +/* + * Copyright (c) 1996 John S. Dyson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice immediately at the beginning of the file, without modification, + * this list of conditions, and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Absolutely no warranty of function or purpose is made by the author + * John S. Dyson. + * 4. This work was done expressly for inclusion into FreeBSD. Other use + * is allowed if this notation is included. + * 5. Modifications may be freely made to this file if the above conditions + * are met. + */ + +#ifndef _SYS_PIPE_H_ +#define _SYS_PIPE_H_ + +#ifndef _KERNEL +#include /* for struct timespec */ +#endif /* _KERNEL */ + +#include /* for struct klist */ +#include /* for struct sigio_ref */ + +/* + * Pipe buffer size, keep moderate in value, pipes take kva space. + */ +#ifndef PIPE_SIZE +#define PIPE_SIZE 16384 +#endif + +#ifndef BIG_PIPE_SIZE +#define BIG_PIPE_SIZE (64*1024) +#endif + +/* + * Pipe buffer information. + * Separate in, out, cnt are used to simplify calculations. + * Buffered write is active when the buffer.cnt field is set. + */ +struct pipebuf { + u_int cnt; /* number of chars currently in buffer */ + u_int in; /* in pointer */ + u_int out; /* out pointer */ + u_int size; /* size of buffer */ + caddr_t buffer; /* kva of buffer */ +}; + +/* + * Bits in pipe_state. + */ +#define PIPE_ASYNC 0x004 /* Async? I/O. */ +#define PIPE_WANTR 0x008 /* Reader wants some characters. */ +#define PIPE_WANTW 0x010 /* Writer wants space to put characters. */ +#define PIPE_WANTD 0x020 /* Pipe is wanted to be run-down. */ +#define PIPE_EOF 0x080 /* Pipe is in EOF condition. */ +#define PIPE_LOCK 0x100 /* Thread has exclusive I/O access. */ +#define PIPE_LWANT 0x200 /* Thread wants exclusive I/O access. */ + +struct pipe_pair; + +/* + * Per-pipe data structure. + * Two of these are linked together to produce bi-directional pipes. + * + * Locking: + * I immutable after creation + * S sigio_lock + * p pipe_lock + */ +struct pipe { + struct rwlock *pipe_lock; + struct pipebuf pipe_buffer; /* [p] data storage */ + struct klist pipe_klist; /* [p] list of knotes */ + struct timespec pipe_atime; /* [p] time of last access */ + struct timespec pipe_mtime; /* [p] time of last modify */ + struct timespec pipe_ctime; /* [I] time of status change */ + struct sigio_ref pipe_sigio; /* [S] async I/O registration */ + struct pipe *pipe_peer; /* [p] link with other direction */ + struct pipe_pair *pipe_pair; /* [I] pipe storage */ + u_int pipe_state; /* [p] pipe status info */ + int pipe_busy; /* [p] # readers/writers */ +}; + +#ifdef _KERNEL +void pipe_init(void); +#endif /* _KERNEL */ + +#endif /* !_SYS_PIPE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/pledge.h b/lib/libc/include/generic-openbsd/sys/pledge.h new file mode 100644 index 000000000000..85a1fdc64c19 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/pledge.h @@ -0,0 +1,143 @@ +/* $OpenBSD: pledge.h,v 1.52 2025/07/05 09:24:37 jsg Exp $ */ + +/* + * Copyright (c) 2015 Nicholas Marriott + * Copyright (c) 2015 Theo de Raadt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_PLEDGE_H_ +#define _SYS_PLEDGE_H_ + +/* + * pledge(2) requests + */ +#define PLEDGE_ALWAYS 0xffffffffffffffffULL +#define PLEDGE_RPATH 0x0000000000000001ULL /* allow open for read */ +#define PLEDGE_WPATH 0x0000000000000002ULL /* allow open for write */ +#define PLEDGE_CPATH 0x0000000000000004ULL /* allow creat, mkdir, unlink etc */ +#define PLEDGE_STDIO 0x0000000000000008ULL /* operate on own pid */ +#define PLEDGE_TMPPATH 0x0000000000000010ULL /* for mk*temp() */ +#define PLEDGE_DNS 0x0000000000000020ULL /* DNS services */ +#define PLEDGE_INET 0x0000000000000040ULL /* AF_INET/AF_INET6 sockets */ +#define PLEDGE_FLOCK 0x0000000000000080ULL /* file locking */ +#define PLEDGE_UNIX 0x0000000000000100ULL /* AF_UNIX sockets */ +#define PLEDGE_ID 0x0000000000000200ULL /* allow setuid, setgid, etc */ +#define PLEDGE_TAPE 0x0000000000000400ULL /* Tape ioctl */ +#define PLEDGE_GETPW 0x0000000000000800ULL /* YP enables if ypbind.lock */ +#define PLEDGE_PROC 0x0000000000001000ULL /* fork, waitpid, etc */ +#define PLEDGE_SETTIME 0x0000000000002000ULL /* able to set/adj time/freq */ +#define PLEDGE_FATTR 0x0000000000004000ULL /* allow explicit file st_* mods */ +#define PLEDGE_PROTEXEC 0x0000000000008000ULL /* allow use of PROT_EXEC */ +#define PLEDGE_TTY 0x0000000000010000ULL /* tty setting */ +#define PLEDGE_SENDFD 0x0000000000020000ULL /* AF_UNIX CMSG fd sending */ +#define PLEDGE_RECVFD 0x0000000000040000ULL /* AF_UNIX CMSG fd receiving */ +#define PLEDGE_EXEC 0x0000000000080000ULL /* execve, child is free of pledge */ +#define PLEDGE_ROUTE 0x0000000000100000ULL /* routing lookups */ +#define PLEDGE_MCAST 0x0000000000200000ULL /* multicast joins */ +#define PLEDGE_VMINFO 0x0000000000400000ULL /* vminfo listings */ +#define PLEDGE_PS 0x0000000000800000ULL /* ps listings */ +#define PLEDGE_DISKLABEL 0x0000000002000000ULL /* disklabels */ +#define PLEDGE_PF 0x0000000004000000ULL /* pf ioctls */ +#define PLEDGE_AUDIO 0x0000000008000000ULL /* audio ioctls */ +#define PLEDGE_DPATH 0x0000000010000000ULL /* mknod & mkfifo */ +#define PLEDGE_DRM 0x0000000020000000ULL /* drm ioctls */ +#define PLEDGE_VMM 0x0000000040000000ULL /* vmm ioctls */ +#define PLEDGE_CHOWN 0x0000000080000000ULL /* chown(2) family */ +#define PLEDGE_CHOWNUID 0x0000000100000000ULL /* allow owner/group changes */ +#define PLEDGE_BPF 0x0000000200000000ULL /* bpf ioctl */ +#define PLEDGE_ERROR 0x0000000400000000ULL /* ENOSYS instead of kill */ +#define PLEDGE_WROUTE 0x0000000800000000ULL /* interface address ioctls */ +#define PLEDGE_UNVEIL 0x0000001000000000ULL /* allow unveil() */ +#define PLEDGE_VIDEO 0x0000002000000000ULL /* video ioctls */ + +/* + * Bits outside PLEDGE_USERSET are used by the kernel itself + * to track program behaviours which have been observed. + */ +#define PLEDGE_USERSET 0x0fffffffffffffffULL + +#ifdef PLEDGENAMES +static const struct { + uint64_t bits; + const char *name; +} pledgenames[] = { + { PLEDGE_STDIO, "stdio" }, + { PLEDGE_RPATH, "rpath" }, + { PLEDGE_WPATH, "wpath" }, + { PLEDGE_CPATH, "cpath" }, + { PLEDGE_DPATH, "dpath" }, + { PLEDGE_TMPPATH, "tmppath" }, + { PLEDGE_INET, "inet" }, + { PLEDGE_MCAST, "mcast" }, + { PLEDGE_FATTR, "fattr" }, + { PLEDGE_CHOWNUID, "chown" }, + { PLEDGE_FLOCK, "flock" }, + { PLEDGE_UNIX, "unix" }, + { PLEDGE_DNS, "dns" }, + { PLEDGE_GETPW, "getpw" }, + { PLEDGE_SENDFD, "sendfd" }, + { PLEDGE_RECVFD, "recvfd" }, + { PLEDGE_TAPE, "tape" }, + { PLEDGE_TTY, "tty" }, + { PLEDGE_PROC, "proc" }, + { PLEDGE_EXEC, "exec" }, + { PLEDGE_PROTEXEC, "prot_exec" }, + { PLEDGE_SETTIME, "settime" }, + { PLEDGE_PS, "ps" }, + { PLEDGE_VMINFO, "vminfo" }, + { PLEDGE_ID, "id" }, + { PLEDGE_PF, "pf" }, + { PLEDGE_ROUTE, "route" }, + { PLEDGE_WROUTE, "wroute" }, + { PLEDGE_AUDIO, "audio" }, + { PLEDGE_VIDEO, "video" }, + { PLEDGE_BPF, "bpf" }, + { PLEDGE_UNVEIL, "unveil" }, + { PLEDGE_ERROR, "error" }, + { PLEDGE_DISKLABEL, "disklabel" }, + { PLEDGE_DRM, "drm" }, + { PLEDGE_VMM, "vmm" }, + { 0, NULL }, +}; +#endif + +#ifdef _KERNEL + +int pledge_syscall(struct proc *, int, uint64_t *); +int pledge_fail(struct proc *, int, uint64_t); + +struct nameidata; +int pledge_namei(struct proc *, struct nameidata *, char *); +int pledge_sendfd(struct proc *p, struct file *); +int pledge_recvfd(struct proc *p, struct file *); +int pledge_sysctl(struct proc *p, int namelen, int *name, void *new); +int pledge_chown(struct proc *p, uid_t, gid_t); +int pledge_adjtime(struct proc *p, const void *v); +int pledge_sendit(struct proc *p, const void *to); +int pledge_sockopt(struct proc *p, int set, int level, int optname); +int pledge_socket(struct proc *p, int domain, unsigned int state); +int pledge_ioctl(struct proc *p, long com, struct file *); +int pledge_ioctl_drm(struct proc *p, long com, dev_t device); +int pledge_ioctl_vmm(struct proc *p, long com); +int pledge_ioctl_psp(struct proc *p, long com); +int pledge_flock(struct proc *p); +int pledge_fcntl(struct proc *p, int cmd); +int pledge_swapctl(struct proc *p, int cmd); +int pledge_kill(struct proc *p, pid_t pid); +int pledge_protexec(struct proc *p, int prot); + +#endif /* _KERNEL */ + +#endif /* _SYS_PLEDGE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/poll.h b/lib/libc/include/generic-openbsd/sys/poll.h new file mode 100644 index 000000000000..3536a1e546cf --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/poll.h @@ -0,0 +1,89 @@ +/* $OpenBSD: poll.h,v 1.16 2024/08/04 22:28:08 guenther Exp $ */ + +/* + * Copyright (c) 1996 Theo de Raadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_POLL_H_ +#define _SYS_POLL_H_ + +typedef struct pollfd { + int fd; + short events; + short revents; +} pollfd_t; + +typedef unsigned int nfds_t; + +#define POLLIN 0x0001 +#define POLLPRI 0x0002 +#define POLLOUT 0x0004 +#define POLLERR 0x0008 +#define POLLHUP 0x0010 +#define POLLNVAL 0x0020 +#define POLLRDNORM 0x0040 +#define POLLNORM POLLRDNORM +#define POLLWRNORM POLLOUT +#define POLLRDBAND 0x0080 +#define POLLWRBAND 0x0100 +#ifdef _KERNEL +#define POLL_NOHUP 0x1000 /* internal use only */ +#endif + +#define INFTIM (-1) + +#ifndef _KERNEL +#include + +#if __POSIX_VISIBLE >= 202405 || __BSD_VISIBLE +#include + +#ifndef _SIGSET_T_DEFINED_ +#define _SIGSET_T_DEFINED_ +typedef unsigned int sigset_t; +#endif + +#ifndef _TIME_T_DEFINED_ +#define _TIME_T_DEFINED_ +typedef __time_t time_t; +#endif + +#ifndef _TIMESPEC_DECLARED +#define _TIMESPEC_DECLARED +struct timespec { + time_t tv_sec; /* seconds */ + long tv_nsec; /* and nanoseconds */ +}; +#endif +#endif /* __BSD_VISIBLE */ + +__BEGIN_DECLS +int poll(struct pollfd[], nfds_t, int); +#if __POSIX_VISIBLE >= 202405 || __BSD_VISIBLE +int ppoll(struct pollfd[], nfds_t, const struct timespec * __restrict, const sigset_t * __restrict); +#endif /* __BSD_VISIBLE */ +__END_DECLS +#endif /* _KERNEL */ + +#endif /* !_SYS_POLL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/pool.h b/lib/libc/include/generic-openbsd/sys/pool.h new file mode 100644 index 000000000000..2a5ad6354dae --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/pool.h @@ -0,0 +1,287 @@ +/* $OpenBSD: pool.h,v 1.81 2025/05/21 09:33:49 mvs Exp $ */ +/* $NetBSD: pool.h,v 1.27 2001/06/06 22:00:17 rafal Exp $ */ + +/*- + * Copyright (c) 1997, 1998, 1999, 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg; by Jason R. Thorpe of the Numerical Aerospace + * Simulation Facility, NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_POOL_H_ +#define _SYS_POOL_H_ + +/* + * sysctls. + * kern.pool.npools + * kern.pool.name. + * kern.pool.pool. + */ +#define KERN_POOL_NPOOLS 1 +#define KERN_POOL_NAME 2 +#define KERN_POOL_POOL 3 +#define KERN_POOL_CACHE 4 /* global pool cache info */ +#define KERN_POOL_CACHE_CPUS 5 /* all cpus cache info */ + +struct kinfo_pool { + unsigned int pr_size; /* size of a pool item */ + unsigned int pr_pgsize; /* size of a "page" */ + unsigned int pr_itemsperpage; /* number of items per "page" */ + unsigned int pr_minpages; /* same in page units */ + unsigned int pr_maxpages; /* maximum # of idle pages to keep */ + unsigned int pr_hardlimit; /* hard limit to number of allocated + items */ + + unsigned int pr_npages; /* # of pages allocated */ + unsigned int pr_nout; /* # items currently allocated */ + unsigned int pr_nitems; /* # items in the pool */ + + unsigned long pr_nget; /* # of successful requests */ + unsigned long pr_nput; /* # of releases */ + unsigned long pr_nfail; /* # of unsuccessful requests */ + unsigned long pr_npagealloc; /* # of pages allocated */ + unsigned long pr_npagefree; /* # of pages released */ + unsigned int pr_hiwat; /* max # of pages in pool */ + unsigned long pr_nidle; /* # of idle pages */ +}; + +struct kinfo_pool_cache { + uint64_t pr_ngc; /* # of times a list has been gc'ed */ + unsigned int pr_len; /* current target for list len */ + unsigned int pr_nitems; /* # of idle items in the depot */ + unsigned int pr_contention; /* # of times mtx was busy */ +}; + +/* + * KERN_POOL_CACHE_CPUS provides an array, not a single struct. ie, it + * provides struct kinfo_pool_cache_cpu kppc[ncpusfound]. + */ +struct kinfo_pool_cache_cpu { + unsigned int pr_cpu; /* which cpu this cache is on */ + + /* counters for times items were handled by the cache */ + uint64_t pr_nget; /* # of requests */ + uint64_t pr_nfail; /* # of unsuccessful requests */ + uint64_t pr_nput; /* # of releases */ + + /* counters for times the cache interacted with the pool */ + uint64_t pr_nlget; /* # of list requests */ + uint64_t pr_nlfail; /* # of unsuccessful list requests */ + uint64_t pr_nlput; /* # of list releases */ +}; + +#if defined(_KERNEL) || defined(_LIBKVM) + +#include +#include +#include +#include + +struct pool; +struct pool_request; +struct pool_lock_ops; +TAILQ_HEAD(pool_requests, pool_request); + +struct pool_allocator { + void *(*pa_alloc)(struct pool *, int, int *); + void (*pa_free)(struct pool *, void *); + size_t pa_pagesz; +}; + +/* + * The pa_pagesz member encodes the sizes of pages that can be + * provided by the allocator, and whether the allocations can be + * aligned to their size. + * + * Page sizes can only be powers of two. Each available page size is + * represented by its value set as a bit. e.g., to indicate that an + * allocator can provide 16k and 32k pages you initialise pa_pagesz + * to (32768 | 16384). + * + * If the allocator can provide aligned pages the low bit in pa_pagesz + * is set. The POOL_ALLOC_ALIGNED macro is provided as a convenience. + * + * If pa_pagesz is unset (i.e. 0), POOL_ALLOC_DEFAULT will be used + * instead. + */ + +#define POOL_ALLOC_ALIGNED 1UL +#define POOL_ALLOC_SIZE(_sz, _a) ((_sz) | (_a)) +#define POOL_ALLOC_SIZES(_min, _max, _a) \ + ((_max) | \ + (((_max) - 1) & ~((_min) - 1)) | (_a)) + +#define POOL_ALLOC_DEFAULT \ + POOL_ALLOC_SIZE(PAGE_SIZE, POOL_ALLOC_ALIGNED) + +TAILQ_HEAD(pool_pagelist, pool_page_header); + +struct pool_cache_item; +TAILQ_HEAD(pool_cache_lists, pool_cache_item); +struct cpumem; + +union pool_lock { + struct mutex prl_mtx; + struct rwlock prl_rwlock; +}; + +struct pool { + struct refcnt pr_refcnt; + union pool_lock pr_lock; + const struct pool_lock_ops * + pr_lock_ops; + SIMPLEQ_ENTRY(pool) + pr_poollist; + struct pool_pagelist + pr_emptypages; /* Empty pages */ + struct pool_pagelist + pr_fullpages; /* Full pages */ + struct pool_pagelist + pr_partpages; /* Partially-allocated pages */ + struct pool_page_header * + pr_curpage; + unsigned int pr_size; /* Size of item */ + unsigned int pr_minitems; /* minimum # of items to keep */ + unsigned int pr_minpages; /* same in page units */ + unsigned int pr_maxpages; /* maximum # of idle pages to keep */ + unsigned int pr_npages; /* # of pages allocated */ + unsigned int pr_itemsperpage;/* # items that fit in a page */ + unsigned int pr_slack; /* unused space in a page */ + unsigned int pr_nitems; /* number of available items in pool */ + unsigned int pr_nout; /* # items currently allocated */ + unsigned int pr_hardlimit; /* hard limit to number of allocated + items */ + unsigned int pr_serial; /* unique serial number of the pool */ + unsigned int pr_pgsize; /* Size of a "page" */ + vaddr_t pr_pgmask; /* Mask with an item to get a page */ + struct pool_allocator * + pr_alloc; /* backend allocator */ + const char * pr_wchan; /* tsleep(9) identifier */ +#define PR_WAITOK 0x0001 /* M_WAITOK */ +#define PR_NOWAIT 0x0002 /* M_NOWAIT */ +#define PR_LIMITFAIL 0x0004 /* M_CANFAIL */ +#define PR_ZERO 0x0008 /* M_ZERO */ +#define PR_RWLOCK 0x0010 +#define PR_WANTED 0x0100 + + int pr_flags; + int pr_ipl; + + RBT_HEAD(phtree, pool_page_header) + pr_phtree; + + struct cpumem * pr_cache; + unsigned long pr_cache_magic[2]; + union pool_lock pr_cache_lock; + struct pool_cache_lists + pr_cache_lists; /* list of idle item lists */ + u_int pr_cache_nitems; /* # of idle items */ + u_int pr_cache_items; /* target list length */ + u_int pr_cache_contention; + u_int pr_cache_contention_prev; + uint64_t pr_cache_timestamp; /* time idle list was empty */ + uint64_t pr_cache_ngc; /* # of times the gc released a list */ + int pr_cache_nout; + + u_int pr_align; + u_int pr_maxcolors; /* Cache coloring */ + int pr_phoffset; /* Offset in page of page header */ + + /* + * pool item requests queue + */ + union pool_lock pr_requests_lock; + struct pool_requests + pr_requests; + unsigned int pr_requesting; + + /* + * Instrumentation + */ + unsigned long pr_nget; /* # of successful requests */ + unsigned long pr_nfail; /* # of unsuccessful requests */ + unsigned long pr_nput; /* # of releases */ + unsigned long pr_npagealloc; /* # of pages allocated */ + unsigned long pr_npagefree; /* # of pages released */ + unsigned int pr_hiwat; /* max # of pages in pool */ + unsigned long pr_nidle; /* # of idle pages */ + + /* Physical memory configuration. */ + const struct kmem_pa_mode * + pr_crange; +}; + +#endif /* _KERNEL || _LIBKVM */ + +#ifdef _KERNEL + +extern struct pool_allocator pool_allocator_single; +extern struct pool_allocator pool_allocator_multi; + +struct pool_request { + TAILQ_ENTRY(pool_request) pr_entry; + void (*pr_handler)(struct pool *, void *, void *); + void *pr_cookie; + void *pr_item; +}; + +void pool_init(struct pool *, size_t, u_int, int, int, + const char *, struct pool_allocator *); +void pool_cache_init(struct pool *); +void pool_destroy(struct pool *); +void pool_setlowat(struct pool *, int); +void pool_sethiwat(struct pool *, int); +int pool_sethardlimit(struct pool *, u_int); +void pool_set_constraints(struct pool *, + const struct kmem_pa_mode *mode); + +void *pool_get(struct pool *, int) __malloc; +void pool_request_init(struct pool_request *, + void (*)(struct pool *, void *, void *), void *); +void pool_request(struct pool *, struct pool_request *); +void pool_put(struct pool *, void *); +void pool_wakeup(struct pool *); +int pool_reclaim(struct pool *); +void pool_reclaim_all(void); +int pool_prime(struct pool *, int); + +#ifdef DDB +/* + * Debugging and diagnostic aides. + */ +void pool_printit(struct pool *, const char *, + int (*)(const char *, ...)); +void pool_walk(struct pool *, int, int (*)(const char *, ...), + void (*)(void *, int, int (*)(const char *, ...))); +#endif + +/* the allocator for dma-able memory is a thin layer on top of pool */ +void dma_alloc_init(void); +void *dma_alloc(size_t size, int flags); +void dma_free(void *m, size_t size); +#endif /* _KERNEL */ + +#endif /* _SYS_POOL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/proc.h b/lib/libc/include/generic-openbsd/sys/proc.h new file mode 100644 index 000000000000..e1d6e62bbcd2 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/proc.h @@ -0,0 +1,678 @@ +/* $OpenBSD: proc.h,v 1.397 2025/08/18 04:15:35 dlg Exp $ */ +/* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */ + +/*- + * Copyright (c) 1986, 1989, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)proc.h 8.8 (Berkeley) 1/21/94 + */ + +#ifndef _SYS_PROC_H_ +#define _SYS_PROC_H_ + +#include /* Machine-dependent proc substruct. */ +#include /* For struct selinfo */ +#include /* For LOGIN_NAME_MAX */ +#include +#include /* For struct timeout */ +#include /* For struct klist */ +#include /* For struct mutex */ +#include /* For struct rusage */ +#include /* For struct rwlock */ +#include /* For struct sigio */ +#include /* For struct refcnt */ +#include + +#ifdef _KERNEL +#include +#define __need_process +#endif + +/* + * One structure allocated per session. + */ +struct process; +struct session { + int s_count; /* Ref cnt; pgrps in session. */ + struct process *s_leader; /* Session leader. */ + struct vnode *s_ttyvp; /* Vnode of controlling terminal. */ + struct tty *s_ttyp; /* Controlling terminal. */ + char s_login[LOGIN_NAME_MAX]; /* Setlogin() name. */ + pid_t s_verauthppid; + uid_t s_verauthuid; + struct timeout s_verauthto; +}; + +void zapverauth(/* struct session */ void *); + +/* + * One structure allocated per process group. + */ +struct pgrp { + LIST_ENTRY(pgrp) pg_hash; /* Hash chain. */ + LIST_HEAD(, process) pg_members;/* Pointer to pgrp members. */ + struct session *pg_session; /* Pointer to session. */ + struct sigiolst pg_sigiolst; /* List of sigio structures. */ + pid_t pg_id; /* Pgrp id. */ + int pg_jobc; /* # procs qualifying pgrp for job control */ +}; + +/* + * time usage: accumulated times in ticks + * Each thread is immediately accumulated here. For processes only the + * time of exited threads is accumulated and to get the proper process + * time usage tuagg_get_process() needs to be called. + * Accounting of threads is done lockless by curproc using the tu_pcl + * pc_lock. Code should use tu_enter() and tu_leave() for this. + * The process ps_tu structure is locked by the ps_mtx. + */ +#define TU_UTICKS 0 /* Statclock hits in user mode. */ +#define TU_STICKS 1 /* Statclock hits in system mode. */ +#define TU_ITICKS 2 /* Statclock hits processing intr. */ +#define TU_TICKS_COUNT 3 + +struct tusage { + struct pc_lock tu_pcl; + uint64_t tu_ticks[TU_TICKS_COUNT]; +#define tu_uticks tu_ticks[TU_UTICKS] +#define tu_sticks tu_ticks[TU_STICKS] +#define tu_iticks tu_ticks[TU_ITICKS] + uint64_t tu_ixrss; + uint64_t tu_idrss; + uint64_t tu_isrss; + struct timespec tu_runtime; /* Realtime. */ +}; + +/* + * Description of a process. + * + * These structures contain the information needed to manage a thread of + * control, known in UN*X as a process; it has references to substructures + * containing descriptions of things that the process uses, but may share + * with related processes. + * + * struct process is the higher level process containing information + * shared by all threads in a process, while struct proc contains the + * run-time information needed by threads. + */ +#ifdef __need_process +struct proc; +struct unveil; + +struct pinsyscall { + vaddr_t pn_start; + vaddr_t pn_end; + u_int *pn_pins; /* array of offsets indexed by syscall# */ + int pn_npins; /* number of entries in table */ +}; + +/* + * Locks used to protect struct members in this file: + * I immutable after creation + * a atomic operations + * K kernel lock + * m this process' `ps_mtx' + * p this process' `ps_lock' + * Q kqueue_ps_list_lock + * R rlimit_lock + * S scheduler lock + * T itimer_mtx + */ +struct process { + struct refcnt ps_refcnt; + + /* + * ps_mainproc is the original thread in the process. + * It's only still special for the handling of + * some signal and ptrace behaviors that need to be fixed. + */ + struct proc *ps_mainproc; + struct ucred *ps_ucred; /* Process owner's identity. */ + + LIST_ENTRY(process) ps_list; /* List of all processes. */ + TAILQ_HEAD(,proc) ps_threads; /* [K|m] Threads in this process. */ + + LIST_ENTRY(process) ps_pglist; /* List of processes in pgrp. */ + struct process *ps_pptr; /* [K|m] Pointer to parent process. */ + LIST_ENTRY(process) ps_sibling; /* List of sibling processes. */ + LIST_HEAD(, process) ps_children;/* Pointer to list of children. */ + LIST_ENTRY(process) ps_hash; /* Hash chain. */ + + /* + * An orphan is the child that has been re-parented to the + * debugger as a result of attaching to it. Need to keep + * track of them for parent to be able to collect the exit + * status of what used to be children. + */ + LIST_ENTRY(process) ps_orphan; /* List of orphan processes. */ + LIST_HEAD(, process) ps_orphans;/* Pointer to list of orphans. */ + + struct sigiolst ps_sigiolst; /* List of sigio structures. */ + struct sigacts *ps_sigacts; /* [I] Signal actions, state */ + struct vnode *ps_textvp; /* Vnode of executable. */ + struct filedesc *ps_fd; /* Ptr to open files structure */ + struct vmspace *ps_vmspace; /* Address space */ + pid_t ps_pid; /* [I] Process identifier. */ + + struct rwlock ps_lock; /* per-process rwlock */ + struct mutex ps_mtx; /* per-process mutex */ + +/* The following fields are all zeroed upon creation in process_new. */ +#define ps_startzero ps_klist + struct klist ps_klist; /* [Q,m] knotes attached to process */ + u_int ps_flags; /* [a] PS_* flags. */ + int ps_siglist; /* Signals pending for the process. */ + + struct proc *ps_single; /* [m] Thread for single-threading. */ + struct proc *ps_trapped; /* [m] Thread trapped for ptrace. */ + u_int ps_suspendcnt; /* [m] Number of threads to suspend. */ + u_int ps_exitcnt; /* [m] Number of threads in exit1. */ + + int ps_traceflag; /* Kernel trace points. */ + struct vnode *ps_tracevp; /* Trace to vnode. */ + struct ucred *ps_tracecred; /* Creds for writing trace */ + + u_int ps_xexit; /* Exit status for wait */ + int ps_xsig; /* Stopping or killing signal */ + + pid_t ps_ppid; /* [K|m] Cached parent pid */ + int ps_ptmask; /* Ptrace event mask */ + struct ptrace_state *ps_ptstat;/* Ptrace state */ + struct process *ps_opptr; /* [K|m] Old parent during ptrace. */ + + struct rusage *ps_ru; /* sum of stats for dead threads. */ + struct tusage ps_tu; /* [m] accumul times of dead threads. */ + struct rusage ps_cru; /* sum of stats for reaped children */ + struct itimerspec ps_timer[3]; /* [m] ITIMER_REAL timer */ + /* [T] ITIMER_{VIRTUAL,PROF} timers */ + struct timeout ps_rucheck_to; /* [] resource limit check timer */ + time_t ps_nextxcpu; /* when to send next SIGXCPU, */ + /* in seconds of process runtime */ + + u_int64_t ps_wxcounter; + + struct unveil *ps_uvpaths; /* unveil vnodes and names */ + ssize_t ps_uvvcount; /* count of unveil vnodes held */ + size_t ps_uvncount; /* count of unveil names allocated */ + int ps_uvdone; /* no more unveil is permitted */ + +/* End area that is zeroed on creation. */ +#define ps_endzero ps_startcopy + +/* The following fields are all copied upon creation in process_new. */ +#define ps_startcopy ps_limit + struct plimit *ps_limit; /* [m,R] Process limits. */ + struct pgrp *ps_pgrp; /* [K|m] Pointer to process group. */ + + char ps_comm[_MAXCOMLEN]; /* command name, incl NUL */ + + vaddr_t ps_strings; /* User pointers to argv/env */ + vaddr_t ps_auxinfo; /* User pointer to auxinfo */ + vaddr_t ps_timekeep; /* User pointer to timekeep */ + vaddr_t ps_sigcode; /* [I] User pointer to signal code */ + vaddr_t ps_sigcoderet; /* [I] User ptr to sigreturn retPC */ + u_long ps_sigcookie; /* [I] */ + u_int ps_rtableid; /* [a] Process routing table/domain. */ + u_short ps_iflags; /* [I] flags set at exec time */ +# define PSI_WXNEEDED 0x0001 /* Process allowed to violate W^X */ +# define PSI_NOBTCFI 0x0002 /* No Branch Target CFI */ +# define PSI_PROFILE 0x0004 /* linked with -pg: allow profile(2) */ +# define PSI_BITS \ + ("\20" "\001WXNEEDED" "\002NOBTCFI" "\003PROFILE" ) + char ps_nice; /* Process "nice" value. */ + + struct uprof { /* profile arguments */ + caddr_t pr_base; /* sample buffer base */ + size_t pr_size; /* sample buffer size */ + u_long pr_off; /* pc offset */ + u_int pr_scale; /* pc scaling */ + char *pr_buf; /* total memory buffer */ + size_t pr_buflen; /* ... length */ + struct ucred *pr_ucred; /* cred at first profil(2) call */ + struct vnode *pr_cdir; /* cwd at first profil(2) call */ + } ps_prof; + + u_int32_t ps_acflag; /* Accounting flags. */ + + uint64_t ps_pledge; /* [m] pledge promises */ + uint64_t ps_execpledge; /* [m] execpledge promises */ + + int64_t ps_kbind_cookie; /* [m] */ + u_long ps_kbind_addr; /* [m] */ +/* an address that can't be in userspace or kernelspace */ +#define BOGO_PC (u_long)-1 + + struct pinsyscall ps_pin; /* static or ld.so */ + struct pinsyscall ps_libcpin; /* libc.so, from pinsyscalls(2) */ + +/* End area that is copied on creation. */ +#define ps_endcopy ps_threadcnt + u_int ps_threadcnt; /* [m] Number of threads. */ + + struct timespec ps_start; /* starting uptime. */ + struct timeout ps_realit_to; /* [m] ITIMER_REAL timeout */ +}; + +#define ps_session ps_pgrp->pg_session +#define ps_pgid ps_pgrp->pg_id + +#endif /* __need_process */ + +/* + * These flags are kept in ps_flags. + * + * When adding a new flag, carefully consider whether it should be + * added to PS_FLAGS_INHERITED_ON_FORK. + */ +#define PS_CONTROLT 0x00000001 /* Has a controlling terminal. */ +#define PS_EXEC 0x00000002 /* Process called exec. */ +#define PS_INEXEC 0x00000004 /* Process is doing an exec right now */ +#define PS_EXITING 0x00000008 /* Process is exiting. */ +#define PS_SUGID 0x00000010 /* Had set id privs since last exec. */ +#define PS_SUGIDEXEC 0x00000020 /* last execve() was set[ug]id */ +#define PS_PPWAIT 0x00000040 /* Parent waits for exec/exit. */ +#define PS_ISPWAIT 0x00000080 /* Is parent of PPWAIT child. */ +#define PS_PROFIL 0x00000100 /* Has started profiling. */ +#define PS_TRACED 0x00000200 /* Being ptraced. */ +#define PS_WAITED 0x00000400 /* Stopped proc was waited for. */ +#define PS_COREDUMP 0x00000800 /* Busy coredumping */ +#define PS_SINGLEEXIT 0x00001000 /* Other threads must die. */ +#define PS_SINGLEUNWIND 0x00002000 /* Other threads must unwind. */ +#define PS_NOZOMBIE 0x00004000 /* No signal or zombie at exit. */ +#define PS_STOPPING 0x00008000 /* Just stopped, need sig to parent. */ +#define PS_SYSTEM 0x00010000 /* No sigs, stats or swapping. */ +#define PS_EMBRYO 0x00020000 /* New process, not yet fledged */ +#define PS_ZOMBIE 0x00040000 /* Dead and ready to be waited for */ +#define PS_NOBROADCASTKILL 0x00080000 /* Process excluded from kill -1. */ +#define PS_PLEDGE 0x00100000 /* Has called pledge(2) */ +#define PS_avail2 0x00200000 +#define PS_EXECPLEDGE 0x00400000 /* Has exec pledges */ +#define PS_ORPHAN 0x00800000 /* Process is on an orphan list */ +#define PS_CHROOT 0x01000000 /* Process is chrooted */ +#define PS_avail1 0x02000000 +#define PS_ITIMER 0x04000000 /* Virtual interval timers running */ +#define PS_avail0 0x08000000 +#define PS_WAITEVENT 0x10000000 /* wait(2) event pending */ +#define PS_CONTINUED 0x20000000 /* Continued proc not yet waited for */ +#define PS_STOPPED 0x40000000 /* Stopped process */ +#define PS_TRAPPED 0x80000000 /* Stopped due to tracing event */ + +#define PS_BITS \ + ("\20" "\01CONTROLT" "\02EXEC" "\03INEXEC" "\04EXITING" "\05SUGID" \ + "\06SUGIDEXEC" "\07PPWAIT" "\010ISPWAIT" "\011PROFIL" "\012TRACED" \ + "\013WAITED" "\014COREDUMP" "\015SINGLEEXIT" "\016SINGLEUNWIND" \ + "\017NOZOMBIE" "\020STOPPING" "\021SYSTEM" "\022EMBRYO" "\023ZOMBIE" \ + "\024NOBROADCASTKILL" "\025PLEDGE" "\027EXECPLEDGE" \ + "\030ORPHAN" "\031CHROOT" "\033ITIMER" \ + "\035WAITEVENT" "\036CONTINUED" "\037STOPPED" "\040TRAPPED") + +#define PS_FLAGS_INHERITED_ON_FORK \ + (PS_SUGID | PS_SUGIDEXEC | PS_PLEDGE | PS_EXECPLEDGE | PS_CHROOT) + +struct kcov_dev; +struct lock_list_entry; +struct kqueue; + +struct p_inentry { + u_long ie_serial; + vaddr_t ie_start; + vaddr_t ie_end; +}; + +/* + * Locks used to protect struct members in this file: + * I immutable after creation + * S scheduler lock + * U uidinfolk + * l read only reference, see lim_read_enter() + * o owned (modified only) by this thread + * m this proc's' `p->p_p->ps_mtx' + */ +struct proc { + TAILQ_ENTRY(proc) p_runq; /* [S] current run/sleep queue */ + LIST_ENTRY(proc) p_list; /* List of all threads. */ + + struct process *p_p; /* [I] The process of this thread. */ + TAILQ_ENTRY(proc) p_thr_link; /* [K|m] Threads in a process linkage. */ + + /* substructures: */ + struct filedesc *p_fd; /* copy of p_p->ps_fd */ + struct vmspace *p_vmspace; /* [I] copy of p_p->ps_vmspace */ + struct p_inentry p_spinentry; /* [o] cache for SP check */ + + int p_flag; /* P_* flags. */ + u_char p_spare; /* unused */ + char p_stat; /* [S] S* process status. */ + u_char p_runpri; /* [S] Runqueue priority */ + u_char p_descfd; /* if not 255, fdesc permits this fd */ + + pid_t p_tid; /* Thread identifier. */ + LIST_ENTRY(proc) p_hash; /* Hash chain. */ + +/* The following fields are all zeroed upon creation in fork. */ +#define p_startzero p_dupfd + int p_dupfd; /* Sideways return value from filedescopen. XXX */ + + /* scheduling */ + unsigned int p_cpticks; /* [o] Ticks of cpu time. */ + unsigned int p_cpticks2; /* [K] last times ticks */ + const volatile void *p_wchan; /* [S] Sleep address. */ + struct timeout p_sleep_to;/* timeout for tsleep() */ + const char *p_wmesg; /* [S] Reason for sleep. */ + volatile fixpt_t p_pctcpu; /* [a] %cpu for this thread */ + u_int p_slptime; /* [S] Time since last blocked. */ + struct cpu_info * volatile p_cpu; /* [S] CPU we're running on. */ + + struct rusage p_ru; /* Statistics */ + struct tusage p_tu; /* [o] accumulated times. */ + + struct plimit *p_limit; /* [l] read ref. of p_p->ps_limit */ + struct kcov_dev *p_kd; /* kcov device handle */ + struct lock_list_entry *p_sleeplocks; /* WITNESS lock tracking */ + struct kqueue *p_kq; /* [o] select/poll queue of evts */ + unsigned long p_kq_serial; /* [o] to check against enqueued evts */ + + int p_siglist; /* [a] Signals arrived & not delivered*/ + +/* End area that is zeroed on creation. */ +#define p_endzero p_startcopy + +/* The following fields are all copied upon creation in fork. */ +#define p_startcopy p_sigmask + sigset_t p_sigmask; /* [o] Current signal mask */ + + char p_name[_MAXCOMLEN]; /* thread name, incl NUL */ + u_char p_slppri; /* [S] Sleeping priority */ + u_char p_usrpri; /* [S] Priority based on p_estcpu & ps_nice */ + u_int p_estcpu; /* [S] Time averaged val of p_cpticks */ + int p_pledge_syscall; /* Cache of current syscall */ + uint64_t p_pledge; /* [o] copy of p_p->ps_pledge */ + + struct ucred *p_ucred; /* [o] cached credentials */ + struct sigaltstack p_sigstk; /* sp & on stack state variable */ + + u_long p_prof_addr; /* tmp storage for profiling addr until AST */ + u_long p_prof_ticks; /* tmp storage for profiling ticks until AST */ + +/* End area that is copied on creation. */ +#define p_endcopy p_addr + struct user *p_addr; /* Kernel virtual addr of u-area */ + struct mdproc p_md; /* Any machine-dependent fields. */ + + sigset_t p_oldmask; /* [o] Saved mask from before sigpause */ + int p_sisig; /* For core dump/debugger XXX */ + union sigval p_sigval; /* For core dump/debugger XXX */ + long p_sitrapno; /* For core dump/debugger XXX */ + int p_sicode; /* For core dump/debugger XXX */ +}; + +/* Status values. */ +#define SIDL 1 /* Thread being created by fork. */ +#define SRUN 2 /* Currently runnable. */ +#define SSLEEP 3 /* Sleeping on an address. */ +#define SSTOP 4 /* Debugging or suspension. */ +#define SZOMB 5 /* unused */ +#define SDEAD 6 /* Thread is almost gone */ +#define SONPROC 7 /* Thread is currently on a CPU. */ + +#define P_HASSIBLING(p) ((p)->p_p->ps_threadcnt > 1) + +/* + * These flags are per-thread and kept in p_flag + */ +#define P_INKTR 0x00000001 /* In a ktrace op, don't recurse */ +#define P_PROFPEND 0x00000002 /* SIGPROF needs to be posted */ +#define P_ALRMPEND 0x00000004 /* SIGVTALRM needs to be posted */ +#define P_SIGSUSPEND 0x00000008 /* Need to restore before-suspend mask*/ +#define P_CANTSLEEP 0x00000010 /* insomniac thread */ +#define P_INSCHED 0x00000020 /* Switching scheduler state. */ +#define P_SINTR 0x00000080 /* Sleep is interruptible. */ +#define P_SYSTEM 0x00000200 /* No sigs, stats or swapping. */ +#define P_TIMEOUT 0x00000400 /* Timing out during sleep. */ +#define P_TIMEOUTRAN 0x00000800 /* Timeout handler has finished. */ +#define P_TRACESINGLE 0x00001000 /* Ptrace: keep single threaded. */ +#define P_WEXIT 0x00002000 /* Working on exiting. */ +#define P_OWEUPC 0x00008000 /* Owe proc an addupc() at next ast. */ +#define P_SUSPSINGLE 0x00080000 /* Need to stop for single threading. */ +#define P_THREAD 0x04000000 /* Only a thread, not a real process */ +#define P_SUSPSIG 0x08000000 /* Stopped from signal. */ +#define P_CPUPEG 0x40000000 /* Do not move to another cpu. */ + +#define P_BITS \ + ("\20" "\01INKTR" "\02PROFPEND" "\03ALRMPEND" "\04SIGSUSPEND" \ + "\05CANTSLEEP" "\06INSCHED" "\010SINTR" "\012SYSTEM" "\013TIMEOUT" \ + "\014TIMEOUTRAN" \ + "\015TRACESINGLE" "\016WEXIT" "\020OWEUPC" "\024SUSPSINGLE" \ + "\033THREAD" "\034SUSPSIG" "\037CPUPEG") + +#define THREAD_PID_OFFSET 100000 + +#ifdef _KERNEL + +struct uidinfo { + LIST_ENTRY(uidinfo) ui_hash; /* [U] */ + uid_t ui_uid; /* [I] */ + long ui_proccnt; /* [U] proc structs */ + long ui_lockcnt; /* [U] lockf structs */ +}; + +struct uidinfo *uid_find(uid_t); +void uid_release(struct uidinfo *); + +/* + * We use process IDs <= PID_MAX; PID_MAX + 1 must also fit in a pid_t, + * as it is used to represent "no process group". + * We set PID_MAX to 99999 to keep it in 5 columns in ps + * When exposed to userspace, thread IDs have THREAD_PID_OFFSET + * added to keep them from overlapping the PID range. For them, + * we use a * a (0 .. 2^n] range for cheapness, picking 'n' such + * that 2^n + THREAD_PID_OFFSET and THREAD_PID_OFFSET have + * the same number of columns when printed. + */ +#define PID_MAX 99999 +#define TID_MASK 0x7ffff + +#define NO_PID (PID_MAX+1) + +#define SESS_LEADER(pr) ((pr)->ps_session->s_leader == (pr)) +#define SESSHOLD(s) ((s)->s_count++) +#define SESSRELE(s) do { \ + if (--(s)->s_count == 0) { \ + timeout_del(&(s)->s_verauthto); \ + pool_put(&session_pool, (s)); \ + } \ +} while (/* CONSTCOND */ 0) + +/* + * Flags to fork1(). + */ +#define FORK_FORK 0x00000001 +#define FORK_VFORK 0x00000002 +#define FORK_IDLE 0x00000004 +#define FORK_PPWAIT 0x00000008 +#define FORK_SHAREFILES 0x00000010 +#define FORK_SYSTEM 0x00000020 +#define FORK_NOZOMBIE 0x00000040 +#define FORK_SHAREVM 0x00000080 +#define FORK_PTRACE 0x00000400 + +#define EXIT_NORMAL 0x00000001 +#define EXIT_THREAD 0x00000002 +#define EXIT_THREAD_NOCHECK 0x00000003 + +#define TIDHASH(tid) (&tidhashtbl[(tid) & tidhash]) +extern LIST_HEAD(tidhashhead, proc) *tidhashtbl; +extern u_long tidhash; + +#define PIDHASH(pid) (&pidhashtbl[(pid) & pidhash]) +extern LIST_HEAD(pidhashhead, process) *pidhashtbl; +extern u_long pidhash; + +#define PGRPHASH(pgid) (&pgrphashtbl[(pgid) & pgrphash]) +extern LIST_HEAD(pgrphashhead, pgrp) *pgrphashtbl; +extern u_long pgrphash; + +extern struct proc proc0; /* Process slot for swapper. */ +extern struct process process0; /* Process slot for kernel threads. */ +extern int nprocesses, maxprocess; /* Cur and max number of processes. */ +extern int nthreads, maxthread; /* Cur and max number of threads. */ + +LIST_HEAD(proclist, proc); +LIST_HEAD(processlist, process); +extern struct processlist allprocess; /* List of all processes. */ +extern struct processlist zombprocess; /* List of zombie processes. */ +extern struct proclist allproc; /* List of all threads. */ + +extern struct process *initprocess; /* Process slot for init. */ +extern struct proc *reaperproc; /* Thread slot for reaper. */ +extern struct proc *syncerproc; /* filesystem syncer daemon */ + +extern struct pool process_pool; /* memory pool for processes */ +extern struct pool proc_pool; /* memory pool for procs */ +extern struct pool rusage_pool; /* memory pool for zombies */ +extern struct pool ucred_pool; /* memory pool for ucreds */ +extern struct pool session_pool; /* memory pool for sessions */ +extern struct pool pgrp_pool; /* memory pool for pgrps */ + +void freepid(pid_t); + +struct process *prfind(pid_t); /* Find process by id. */ +struct process *zombiefind(pid_t); /* Find zombie process by id. */ +struct proc *tfind(pid_t); /* Find thread by id. */ +struct pgrp *pgfind(pid_t); /* Find process group by id. */ +struct proc *tfind_user(pid_t, struct process *); + /* Find thread by userspace id. */ +void proc_printit(struct proc *p, const char *modif, + int (*pr)(const char *, ...)); + +int chgproccnt(uid_t uid, int diff); +void enternewpgrp(struct process *, struct pgrp *, struct session *); +void enterthispgrp(struct process *, struct pgrp *); +int inferior(struct process *, struct process *); +void leavepgrp(struct process *); +void killjobc(struct process *); +void preempt(void); +void procinit(void); +void setpriority(struct proc *, uint32_t, uint8_t); +void setrunnable(struct proc *); +void endtsleep(void *); +int wakeup_proc(struct proc *); +void unsleep(struct proc *); +void reaper(void *); +__dead void exit1(struct proc *, int, int, int); +void exit2(struct proc *); +void cpu_fork(struct proc *_curp, struct proc *_child, void *_stack, + void *_tcb, void (*_func)(void *), void *_arg); +void cpu_exit(struct proc *); +void process_initialize(struct process *, struct proc *); +int fork1(struct proc *_curp, int _flags, void (*_func)(void *), + void *_arg, register_t *_retval, struct proc **_newprocp); +int thread_fork(struct proc *_curp, void *_stack, void *_tcb, + pid_t *_tidptr, register_t *_retval); +int groupmember(gid_t, struct ucred *); +void dorefreshcreds(struct process *, struct proc *); +void dosigsuspend(struct proc *, sigset_t); + +static inline void +refreshcreds(struct proc *p) +{ + struct process *pr = p->p_p; + + /* this is an unlocked access to ps_ucred, but the result is benign */ + if (pr->ps_ucred != p->p_ucred) + dorefreshcreds(pr, p); +} + +#define SINGLE_SUSPEND 0x01 /* other threads to stop wherever they are */ +#define SINGLE_UNWIND 0x02 /* other threads to unwind and stop */ +#define SINGLE_EXIT 0x03 /* other threads to unwind and then exit */ +#define SINGLE_MASK 0x0f +/* extra flags for single_thread_set */ +#define SINGLE_DEEP 0x10 /* call is in deep */ + +int single_thread_set(struct proc *, int); +void single_thread_clear(struct proc *); + +int proc_suspend_check(struct proc *, int); +void process_suspend_signal(struct process *); +void process_stop(struct process *, int, int); + +void child_return(void *); + +int proc_cansugid(struct proc *); + +struct cond { + unsigned int c_wait; /* [a] initialized and waiting */ +}; + +#define COND_INITIALIZER() { .c_wait = 1 } + +void proc_trampoline_mi(void); + +/* + * functions to handle sets of cpus. + * + * For now we keep the cpus in ints so that we can use the generic + * atomic ops. + */ +#define CPUSET_ASIZE(x) (((x) - 1)/32 + 1) +#define CPUSET_SSIZE CPUSET_ASIZE(MAXCPUS) +struct cpuset { + int cs_set[CPUSET_SSIZE]; +}; + +void cpuset_init_cpu(struct cpu_info *); + +void cpuset_add(struct cpuset *, struct cpu_info *); +void cpuset_del(struct cpuset *, struct cpu_info *); +int cpuset_isset(struct cpuset *, struct cpu_info *); +void cpuset_copy(struct cpuset *, struct cpuset *); +void cpuset_intersection(struct cpuset *t, struct cpuset *, struct cpuset *); +void cpuset_complement(struct cpuset *, struct cpuset *, struct cpuset *); +int cpuset_cardinality(struct cpuset *); +struct cpu_info *cpuset_first(struct cpuset *); + +static inline unsigned int +tu_enter(struct tusage *tu) +{ + return pc_sprod_enter(&tu->tu_pcl); +} + +static inline void +tu_leave(struct tusage *tu, unsigned int gen) +{ + pc_sprod_leave(&tu->tu_pcl, gen); +} + +#endif /* _KERNEL */ +#endif /* !_SYS_PROC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/protosw.h b/lib/libc/include/generic-openbsd/sys/protosw.h new file mode 100644 index 000000000000..db18f5f66e98 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/protosw.h @@ -0,0 +1,407 @@ +/* $OpenBSD: protosw.h,v 1.72 2025/03/02 21:28:32 bluhm Exp $ */ +/* $NetBSD: protosw.h,v 1.10 1996/04/09 20:55:32 cgd Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)protosw.h 8.1 (Berkeley) 6/2/93 + */ + +/* + * Protocol switch table. + * + * Each protocol has a handle initializing one of these structures, + * which is used for protocol-protocol and system-protocol communication. + * + * A protocol is called through the pr_init entry before any other. + * Thereafter it is called every 200ms through the pr_fasttimo entry and + * every 500ms through the pr_slowtimo for timer based actions. + * + * Protocols pass data between themselves as chains of mbufs using + * the pr_input and pr_send hooks. Pr_input passes data up (towards + * UNIX) and pr_send passes it down (towards the imps); control + * information passes up and down on pr_ctlinput and pr_ctloutput. + * The protocol is responsible for the space occupied by any the + * arguments to these entries and must dispose it. + * + * The userreq routine interfaces protocols to the system and is + * described below. + */ + +#ifndef _SYS_PROTOSW_H_ +#define _SYS_PROTOSW_H_ + +struct mbuf; +struct sockaddr; +struct socket; +struct domain; +struct proc; +struct stat; +struct ifnet; +struct netstack; + +struct pr_usrreqs { + int (*pru_attach)(struct socket *, int, int); + int (*pru_detach)(struct socket *); + int (*pru_bind)(struct socket *, struct mbuf *, struct proc *); + int (*pru_listen)(struct socket *); + int (*pru_connect)(struct socket *, struct mbuf *); + int (*pru_accept)(struct socket *, struct mbuf *); + int (*pru_disconnect)(struct socket *); + int (*pru_shutdown)(struct socket *); + void (*pru_rcvd)(struct socket *); + int (*pru_send)(struct socket *, struct mbuf *, struct mbuf *, + struct mbuf *); + void (*pru_abort)(struct socket *); + int (*pru_control)(struct socket *, u_long, caddr_t, + struct ifnet *); + int (*pru_sense)(struct socket *, struct stat *); + int (*pru_rcvoob)(struct socket *, struct mbuf *, int); + int (*pru_sendoob)(struct socket *, struct mbuf *, struct mbuf *, + struct mbuf *); + int (*pru_sockaddr)(struct socket *, struct mbuf *); + int (*pru_peeraddr)(struct socket *, struct mbuf *); + int (*pru_connect2)(struct socket *, struct socket *); +}; + +struct protosw { + short pr_type; /* socket type used for */ + const struct domain *pr_domain; /* domain protocol a member of */ + short pr_protocol; /* protocol number */ + short pr_flags; /* see below */ + +/* protocol-protocol hooks */ + /* input to protocol (from below) */ + int (*pr_input)(struct mbuf **, int *, int, int, struct netstack *); + /* control input (from below) */ + void (*pr_ctlinput)(int, struct sockaddr *, u_int, void *); + /* control output (from above) */ + int (*pr_ctloutput)(int, struct socket *, int, int, struct mbuf *); + +/* user-protocol hooks */ + const struct pr_usrreqs *pr_usrreqs; + +/* utility hooks */ + void (*pr_init)(void); /* initialization hook */ + void (*pr_fasttimo)(void); /* fast timeout (200ms) */ + void (*pr_slowtimo)(void); /* slow timeout (500ms) */ + /* sysctl for protocol */ + int (*pr_sysctl)(int *, u_int, void *, size_t *, void *, size_t); +}; + +#define PR_SLOWHZ 2 /* 2 slow timeouts per second */ +#define PR_FASTHZ 5 /* 5 fast timeouts per second */ + +/* + * Values for pr_flags. + * PR_ADDR requires PR_ATOMIC; + * PR_ADDR and PR_CONNREQUIRED are mutually exclusive. + */ +#define PR_ATOMIC 0x0001 /* exchange atomic messages only */ +#define PR_ADDR 0x0002 /* addresses given with messages */ +#define PR_CONNREQUIRED 0x0004 /* connection required by protocol */ +#define PR_WANTRCVD 0x0008 /* want PRU_RCVD calls */ +#define PR_RIGHTS 0x0010 /* passes capabilities */ +#define PR_ABRTACPTDIS 0x0020 /* abort on accept(2) to disconnected + socket */ +#define PR_SPLICE 0x0040 /* socket splicing is possible */ +#define PR_MPINPUT 0x0080 /* input runs with shared netlock */ +#define PR_MPSYSCTL 0x0200 /* mp-safe sysctl(2) handler */ + +/* + * The arguments to usrreq are: + * (*protosw[].pr_usrreq)(up, req, m, nam, opt); + * where up is a (struct socket *), req is one of these requests, + * m is a optional mbuf chain containing a message, + * nam is an optional mbuf chain containing an address, + * and opt is a pointer to a socketopt structure or nil. + * The protocol is responsible for disposal of the mbuf chain m, + * the caller is responsible for any space held by nam and opt. + * A non-zero return from usrreq gives an + * UNIX error number which should be passed to higher level software. + */ +#define PRU_ATTACH 0 /* attach protocol to up */ +#define PRU_DETACH 1 /* detach protocol from up */ +#define PRU_BIND 2 /* bind socket to address */ +#define PRU_LISTEN 3 /* listen for connection */ +#define PRU_CONNECT 4 /* establish connection to peer */ +#define PRU_ACCEPT 5 /* accept connection from peer */ +#define PRU_DISCONNECT 6 /* disconnect from peer */ +#define PRU_SHUTDOWN 7 /* won't send any more data */ +#define PRU_RCVD 8 /* have taken data; more room now */ +#define PRU_SEND 9 /* send this data */ +#define PRU_ABORT 10 /* abort (fast DISCONNECT, DETACH) */ +#define PRU_CONTROL 11 /* control operations on protocol */ +#define PRU_SENSE 12 /* return status into m */ +#define PRU_RCVOOB 13 /* retrieve out of band data */ +#define PRU_SENDOOB 14 /* send out of band data */ +#define PRU_SOCKADDR 15 /* fetch socket's address */ +#define PRU_PEERADDR 16 /* fetch peer's address */ +#define PRU_CONNECT2 17 /* connect two sockets */ +/* begin for protocols internal use */ +#define PRU_FASTTIMO 18 /* 200ms timeout */ +#define PRU_SLOWTIMO 19 /* 500ms timeout */ +#define PRU_PROTORCV 20 /* receive from below */ +#define PRU_PROTOSEND 21 /* send to below */ + +#define PRU_NREQ 22 + +#ifdef PRUREQUESTS +const char *prurequests[] = { + "ATTACH", "DETACH", "BIND", "LISTEN", + "CONNECT", "ACCEPT", "DISCONNECT", "SHUTDOWN", + "RCVD", "SEND", "ABORT", "CONTROL", + "SENSE", "RCVOOB", "SENDOOB", "SOCKADDR", + "PEERADDR", "CONNECT2", "FASTTIMO", "SLOWTIMO", + "PROTORCV", "PROTOSEND", +}; +#endif + +/* + * The arguments to the ctlinput routine are + * (*protosw[].pr_ctlinput)(cmd, sa, arg); + * where cmd is one of the commands below, sa is a pointer to a sockaddr, + * and arg is an optional caddr_t argument used within a protocol family. + */ +#define PRC_IFDOWN 0 /* interface transition */ +#define PRC_ROUTEDEAD 1 /* select new route if possible ??? */ +#define PRC_MTUINC 2 /* increase in mtu to host */ +#define PRC_QUENCH2 3 /* DEC congestion bit says slow down */ +#define PRC_QUENCH 4 /* some one said to slow down */ +#define PRC_MSGSIZE 5 /* message size forced drop */ +#define PRC_HOSTDEAD 6 /* host appears to be down */ +#define PRC_HOSTUNREACH 7 /* deprecated (use PRC_UNREACH_HOST) */ +#define PRC_UNREACH_NET 8 /* no route to network */ +#define PRC_UNREACH_HOST 9 /* no route to host */ +#define PRC_UNREACH_PROTOCOL 10 /* dst says bad protocol */ +#define PRC_UNREACH_PORT 11 /* bad port # */ +/* was PRC_UNREACH_NEEDFRAG 12 (use PRC_MSGSIZE) */ +#define PRC_UNREACH_SRCFAIL 13 /* source route failed */ +#define PRC_REDIRECT_NET 14 /* net routing redirect */ +#define PRC_REDIRECT_HOST 15 /* host routing redirect */ +#define PRC_REDIRECT_TOSNET 16 /* redirect for type of service & net */ +#define PRC_REDIRECT_TOSHOST 17 /* redirect for tos & host */ +#define PRC_TIMXCEED_INTRANS 18 /* packet lifetime expired in transit */ +#define PRC_TIMXCEED_REASS 19 /* lifetime expired on reass q */ +#define PRC_PARAMPROB 20 /* header incorrect */ + +#define PRC_NCMDS 21 + +#define PRC_IS_REDIRECT(cmd) \ + ((cmd) >= PRC_REDIRECT_NET && (cmd) <= PRC_REDIRECT_TOSHOST) + +#ifdef PRCREQUESTS +char *prcrequests[] = { + "IFDOWN", "ROUTEDEAD", "MTUINC", "DEC-BIT-QUENCH2", + "QUENCH", "MSGSIZE", "HOSTDEAD", "#7", + "NET-UNREACH", "HOST-UNREACH", "PROTO-UNREACH", "PORT-UNREACH", + "#12", "SRCFAIL-UNREACH", "NET-REDIRECT", "HOST-REDIRECT", + "TOSNET-REDIRECT", "TOSHOST-REDIRECT", "TX-INTRANS", "TX-REASS", + "PARAMPROB" +}; +#endif + +/* + * The arguments to ctloutput are: + * (*protosw[].pr_ctloutput)(req, so, level, optname, optval); + * req is one of the actions listed below, so is a (struct socket *), + * level is an indication of which protocol layer the option is intended. + * optname is a protocol dependent socket option request, + * optval is a pointer to a mbuf-chain pointer, for value-return results. + * The protocol is responsible for disposal of the mbuf chain *optval + * if supplied, + * the caller is responsible for any space held by *optval, when returned. + * A non-zero return from usrreq gives an + * UNIX error number which should be passed to higher level software. + */ +#define PRCO_GETOPT 0 +#define PRCO_SETOPT 1 + +#define PRCO_NCMDS 2 + +#ifdef PRCOREQUESTS +char *prcorequests[] = { + "GETOPT", "SETOPT", +}; +#endif + +#ifdef _KERNEL + +#include +#include + +const struct protosw *pffindproto(int, int, int); +const struct protosw *pffindtype(int, int); +const struct domain *pffinddomain(int); +void pfctlinput(int, struct sockaddr *); + +extern u_char ip_protox[]; +extern const struct protosw inetsw[]; + +#ifdef INET6 +extern u_char ip6_protox[]; +extern const struct protosw inet6sw[]; +#endif /* INET6 */ + +static inline int +pru_attach(struct socket *so, int proto, int wait) +{ + return (*so->so_proto->pr_usrreqs->pru_attach)(so, proto, wait); +} + +static inline int +pru_detach(struct socket *so) +{ + return (*so->so_proto->pr_usrreqs->pru_detach)(so); +} + +static inline int +pru_bind(struct socket *so, struct mbuf *nam, struct proc *p) +{ + if (so->so_proto->pr_usrreqs->pru_bind) + return (*so->so_proto->pr_usrreqs->pru_bind)(so, nam, p); + return (EOPNOTSUPP); +} + +static inline int +pru_listen(struct socket *so) +{ + if (so->so_proto->pr_usrreqs->pru_listen) + return (*so->so_proto->pr_usrreqs->pru_listen)(so); + return (EOPNOTSUPP); +} + +static inline int +pru_connect(struct socket *so, struct mbuf *nam) +{ + if (so->so_proto->pr_usrreqs->pru_connect) + return (*so->so_proto->pr_usrreqs->pru_connect)(so, nam); + return (EOPNOTSUPP); +} + +static inline int +pru_accept(struct socket *so, struct mbuf *nam) +{ + if (so->so_proto->pr_usrreqs->pru_accept) + return (*so->so_proto->pr_usrreqs->pru_accept)(so, nam); + return (EOPNOTSUPP); +} + +static inline int +pru_disconnect(struct socket *so) +{ + if (so->so_proto->pr_usrreqs->pru_disconnect) + return (*so->so_proto->pr_usrreqs->pru_disconnect)(so); + return (EOPNOTSUPP); +} + +static inline int +pru_shutdown(struct socket *so) +{ + return (*so->so_proto->pr_usrreqs->pru_shutdown)(so); +} + +static inline void +pru_rcvd(struct socket *so) +{ + (*so->so_proto->pr_usrreqs->pru_rcvd)(so); +} + +static inline int +pru_send(struct socket *so, struct mbuf *top, struct mbuf *addr, + struct mbuf *control) +{ + return (*so->so_proto->pr_usrreqs->pru_send)(so, top, addr, control); +} + +static inline void +pru_abort(struct socket *so) +{ + (*so->so_proto->pr_usrreqs->pru_abort)(so); +} + +static inline int +pru_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp) +{ + if (so->so_proto->pr_usrreqs->pru_control) + return (*so->so_proto->pr_usrreqs->pru_control)(so, + cmd, data, ifp); + return (EOPNOTSUPP); +} + +static inline int +pru_sense(struct socket *so, struct stat *ub) +{ + if (so->so_proto->pr_usrreqs->pru_sense) + return (*so->so_proto->pr_usrreqs->pru_sense)(so, ub); + return (0); +} + +static inline int +pru_rcvoob(struct socket *so, struct mbuf *m, int flags) +{ + if (so->so_proto->pr_usrreqs->pru_rcvoob) + return (*so->so_proto->pr_usrreqs->pru_rcvoob)(so, m, flags); + return (EOPNOTSUPP); +} + +static inline int +pru_sendoob(struct socket *so, struct mbuf *top, struct mbuf *addr, + struct mbuf *control) +{ + if (so->so_proto->pr_usrreqs->pru_sendoob) + return (*so->so_proto->pr_usrreqs->pru_sendoob)(so, + top, addr, control); + m_freem(top); + m_freem(control); + return (EOPNOTSUPP); +} + +static inline int +pru_sockaddr(struct socket *so, struct mbuf *addr) +{ + return (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, addr); +} + +static inline int +pru_peeraddr(struct socket *so, struct mbuf *addr) +{ + return (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, addr); +} + +static inline int +pru_connect2(struct socket *so1, struct socket *so2) +{ + if (so1->so_proto->pr_usrreqs->pru_connect2) + return (*so1->so_proto->pr_usrreqs->pru_connect2)(so1, so2); + return (EOPNOTSUPP); +} + +#endif + +#endif /* _SYS_PROTOSW_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/ptrace.h b/lib/libc/include/generic-openbsd/sys/ptrace.h new file mode 100644 index 000000000000..54ee9d75d2e1 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/ptrace.h @@ -0,0 +1,137 @@ +/* $OpenBSD: ptrace.h,v 1.16 2020/03/16 11:58:46 mpi Exp $ */ +/* $NetBSD: ptrace.h,v 1.21 1996/02/09 18:25:26 christos Exp $ */ + +/*- + * Copyright (c) 1984, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ptrace.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _SYS_PTRACE_H_ +#define _SYS_PTRACE_H_ + +#define PT_TRACE_ME 0 /* child declares it's being traced */ +#define PT_READ_I 1 /* read word in child's I space */ +#define PT_READ_D 2 /* read word in child's D space */ +#define PT_WRITE_I 4 /* write word in child's I space */ +#define PT_WRITE_D 5 /* write word in child's D space */ +#define PT_CONTINUE 7 /* continue the child */ +#define PT_KILL 8 /* kill the child process */ +#define PT_ATTACH 9 /* attach to running process */ +#define PT_DETACH 10 /* detach from running process */ +#define PT_IO 11 /* do I/O to/from the stopped process. */ + +struct ptrace_io_desc { + int piod_op; /* I/O operation */ + void *piod_offs; /* child offset */ + void *piod_addr; /* parent offset */ + size_t piod_len; /* request length */ +}; + +/* + * Operations in piod_op. + */ +#define PIOD_READ_D 1 /* Read from D space */ +#define PIOD_WRITE_D 2 /* Write to D space */ +#define PIOD_READ_I 3 /* Read from I space */ +#define PIOD_WRITE_I 4 /* Write to I space */ +#define PIOD_READ_AUXV 5 /* Read from aux array */ + +#define PT_SET_EVENT_MASK 12 +#define PT_GET_EVENT_MASK 13 + +typedef struct ptrace_event { + int pe_set_event; +} ptrace_event_t; + +#define PTRACE_FORK 0x0002 /* Report forks */ + +#define PT_GET_PROCESS_STATE 14 + +typedef struct ptrace_state { + int pe_report_event; + pid_t pe_other_pid; + pid_t pe_tid; +} ptrace_state_t; + +#define PT_GET_THREAD_FIRST 15 +#define PT_GET_THREAD_NEXT 16 + +struct ptrace_thread_state { + pid_t pts_tid; +}; + +#define PT_FIRSTMACH 32 /* for machine-specific requests */ +#include /* machine-specific requests, if any */ + +#ifdef _KERNEL + +/* + * There is a bunch of PT_ requests that are machine dependent, but not + * optional. Check if they were defined by MD code here. + */ +#if !defined(PT_GETREGS) || !defined(PT_SETREGS) +#error Machine dependent ptrace not complete. +#endif + +struct reg; +#if defined(PT_GETFPREGS) || defined(PT_SETFPREGS) +struct fpreg; +#endif + +void process_reparent(struct process *_child, struct process *_newparent); +void process_untrace(struct process *_tr); +#ifdef PT_GETFPREGS +int process_read_fpregs(struct proc *_t, struct fpreg *); +#endif +int process_read_regs(struct proc *_t, struct reg *); +int process_set_pc(struct proc *_t, caddr_t _addr); +int process_sstep(struct proc *_t, int _sstep); +#ifdef PT_SETFPREGS +int process_write_fpregs(struct proc *_t, struct fpreg *); +#endif +int process_write_regs(struct proc *_t, struct reg *); +int process_checkioperm(struct proc *_curp, struct process *_tr); +int process_domem(struct proc *_curp, struct process *_tr, struct uio *, + int _req); + +#ifndef FIX_SSTEP +#define FIX_SSTEP(p) +#endif + +#else /* !_KERNEL */ + +#include + +__BEGIN_DECLS +int ptrace(int _request, pid_t _pid, caddr_t _addr, int _data); +__END_DECLS + +#endif /* !_KERNEL */ + +#endif /* !_SYS_PTRACE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/queue.h b/lib/libc/include/generic-openbsd/sys/queue.h new file mode 100644 index 000000000000..db4f22bee5fe --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/queue.h @@ -0,0 +1,633 @@ +/* $OpenBSD: queue.h,v 1.46 2020/12/30 13:33:12 millert Exp $ */ +/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + */ + +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +#include + +/* + * This file defines five types of data structures: singly-linked lists, + * lists, simple queues, tail queues and XOR simple queues. + * + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A simple queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are singly + * linked to save space, so elements can only be removed from the + * head of the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the + * list. A simple queue may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * An XOR simple queue is used in the same way as a regular simple queue. + * The difference is that the head structure also includes a "cookie" that + * is XOR'd with the queue pointer (first, last or next) to generate the + * real pointer value. + * + * For details on the use of these macros, see the queue(3) manual page. + */ + +#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC)) +#define _Q_INVALID ((void *)-1) +#define _Q_INVALIDATE(a) (a) = _Q_INVALID +#else +#define _Q_INVALIDATE(a) +#endif + +/* + * Singly-linked List definitions. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List access methods. + */ +#define SLIST_FIRST(head) ((head)->slh_first) +#define SLIST_END(head) NULL +#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_FOREACH(var, head, field) \ + for((var) = SLIST_FIRST(head); \ + (var) != SLIST_END(head); \ + (var) = SLIST_NEXT(var, field)) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST(head); \ + (var) && ((tvar) = SLIST_NEXT(var, field), 1); \ + (var) = (tvar)) + +/* + * Singly-linked List functions. + */ +#define SLIST_INIT(head) { \ + SLIST_FIRST(head) = SLIST_END(head); \ +} + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + (elm)->field.sle_next = (slistelm)->field.sle_next; \ + (slistelm)->field.sle_next = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.sle_next = (head)->slh_first; \ + (head)->slh_first = (elm); \ +} while (0) + +#define SLIST_REMOVE_AFTER(elm, field) do { \ + (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + (head)->slh_first = (head)->slh_first->field.sle_next; \ +} while (0) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + if ((head)->slh_first == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } else { \ + struct type *curelm = (head)->slh_first; \ + \ + while (curelm->field.sle_next != (elm)) \ + curelm = curelm->field.sle_next; \ + curelm->field.sle_next = \ + curelm->field.sle_next->field.sle_next; \ + } \ + _Q_INVALIDATE((elm)->field.sle_next); \ +} while (0) + +/* + * List definitions. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List access methods. + */ +#define LIST_FIRST(head) ((head)->lh_first) +#define LIST_END(head) NULL +#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_FOREACH(var, head, field) \ + for((var) = LIST_FIRST(head); \ + (var)!= LIST_END(head); \ + (var) = LIST_NEXT(var, field)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST(head); \ + (var) && ((tvar) = LIST_NEXT(var, field), 1); \ + (var) = (tvar)) + +/* + * List functions. + */ +#define LIST_INIT(head) do { \ + LIST_FIRST(head) = LIST_END(head); \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ + (listelm)->field.le_next->field.le_prev = \ + &(elm)->field.le_next; \ + (listelm)->field.le_next = (elm); \ + (elm)->field.le_prev = &(listelm)->field.le_next; \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + (elm)->field.le_next = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &(elm)->field.le_next; \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.le_next = (head)->lh_first) != NULL) \ + (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ + (head)->lh_first = (elm); \ + (elm)->field.le_prev = &(head)->lh_first; \ +} while (0) + +#define LIST_REMOVE(elm, field) do { \ + if ((elm)->field.le_next != NULL) \ + (elm)->field.le_next->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = (elm)->field.le_next; \ + _Q_INVALIDATE((elm)->field.le_prev); \ + _Q_INVALIDATE((elm)->field.le_next); \ +} while (0) + +#define LIST_REPLACE(elm, elm2, field) do { \ + if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ + (elm2)->field.le_next->field.le_prev = \ + &(elm2)->field.le_next; \ + (elm2)->field.le_prev = (elm)->field.le_prev; \ + *(elm2)->field.le_prev = (elm2); \ + _Q_INVALIDATE((elm)->field.le_prev); \ + _Q_INVALIDATE((elm)->field.le_next); \ +} while (0) + +/* + * Simple queue definitions. + */ +#define SIMPLEQ_HEAD(name, type) \ +struct name { \ + struct type *sqh_first; /* first element */ \ + struct type **sqh_last; /* addr of last next element */ \ +} + +#define SIMPLEQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).sqh_first } + +#define SIMPLEQ_ENTRY(type) \ +struct { \ + struct type *sqe_next; /* next element */ \ +} + +/* + * Simple queue access methods. + */ +#define SIMPLEQ_FIRST(head) ((head)->sqh_first) +#define SIMPLEQ_END(head) NULL +#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) +#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) + +#define SIMPLEQ_FOREACH(var, head, field) \ + for((var) = SIMPLEQ_FIRST(head); \ + (var) != SIMPLEQ_END(head); \ + (var) = SIMPLEQ_NEXT(var, field)) + +#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SIMPLEQ_FIRST(head); \ + (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); \ + (var) = (tvar)) + +/* + * Simple queue functions. + */ +#define SIMPLEQ_INIT(head) do { \ + (head)->sqh_first = NULL; \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) + +#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (head)->sqh_first = (elm); \ +} while (0) + +#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.sqe_next = NULL; \ + *(head)->sqh_last = (elm); \ + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (0) + +#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (listelm)->field.sqe_next = (elm); \ +} while (0) + +#define SIMPLEQ_REMOVE_HEAD(head, field) do { \ + if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) + +#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ + if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \ + == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (0) + +#define SIMPLEQ_CONCAT(head1, head2) do { \ + if (!SIMPLEQ_EMPTY((head2))) { \ + *(head1)->sqh_last = (head2)->sqh_first; \ + (head1)->sqh_last = (head2)->sqh_last; \ + SIMPLEQ_INIT((head2)); \ + } \ +} while (0) + +/* + * XOR Simple queue definitions. + */ +#define XSIMPLEQ_HEAD(name, type) \ +struct name { \ + struct type *sqx_first; /* first element */ \ + struct type **sqx_last; /* addr of last next element */ \ + unsigned long sqx_cookie; \ +} + +#define XSIMPLEQ_ENTRY(type) \ +struct { \ + struct type *sqx_next; /* next element */ \ +} + +/* + * XOR Simple queue access methods. + */ +#define XSIMPLEQ_XOR(head, ptr) ((__typeof(ptr))((head)->sqx_cookie ^ \ + (unsigned long)(ptr))) +#define XSIMPLEQ_FIRST(head) XSIMPLEQ_XOR(head, ((head)->sqx_first)) +#define XSIMPLEQ_END(head) NULL +#define XSIMPLEQ_EMPTY(head) (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head)) +#define XSIMPLEQ_NEXT(head, elm, field) XSIMPLEQ_XOR(head, ((elm)->field.sqx_next)) + + +#define XSIMPLEQ_FOREACH(var, head, field) \ + for ((var) = XSIMPLEQ_FIRST(head); \ + (var) != XSIMPLEQ_END(head); \ + (var) = XSIMPLEQ_NEXT(head, var, field)) + +#define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = XSIMPLEQ_FIRST(head); \ + (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \ + (var) = (tvar)) + +/* + * XOR Simple queue functions. + */ +#define XSIMPLEQ_INIT(head) do { \ + arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \ + (head)->sqx_first = XSIMPLEQ_XOR(head, NULL); \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ +} while (0) + +#define XSIMPLEQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.sqx_next = (head)->sqx_first) == \ + XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ + (head)->sqx_first = XSIMPLEQ_XOR(head, (elm)); \ +} while (0) + +#define XSIMPLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL); \ + *(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ +} while (0) + +#define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.sqx_next = (listelm)->field.sqx_next) == \ + XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ + (listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm)); \ +} while (0) + +#define XSIMPLEQ_REMOVE_HEAD(head, field) do { \ + if (((head)->sqx_first = XSIMPLEQ_XOR(head, \ + (head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ +} while (0) + +#define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ + if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head, \ + (elm)->field.sqx_next)->field.sqx_next) \ + == XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = \ + XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ +} while (0) + + +/* + * Tail queue definitions. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} + +/* + * Tail queue access methods. + */ +#define TAILQ_FIRST(head) ((head)->tqh_first) +#define TAILQ_END(head) NULL +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) +/* XXX */ +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) +#define TAILQ_EMPTY(head) \ + (TAILQ_FIRST(head) == TAILQ_END(head)) + +#define TAILQ_FOREACH(var, head, field) \ + for((var) = TAILQ_FIRST(head); \ + (var) != TAILQ_END(head); \ + (var) = TAILQ_NEXT(var, field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST(head); \ + (var) != TAILQ_END(head) && \ + ((tvar) = TAILQ_NEXT(var, field), 1); \ + (var) = (tvar)) + + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for((var) = TAILQ_LAST(head, headname); \ + (var) != TAILQ_END(head); \ + (var) = TAILQ_PREV(var, headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST(head, headname); \ + (var) != TAILQ_END(head) && \ + ((tvar) = TAILQ_PREV(var, headname, field), 1); \ + (var) = (tvar)) + +/* + * Tail queue functions. + */ +#define TAILQ_INIT(head) do { \ + (head)->tqh_first = NULL; \ + (head)->tqh_last = &(head)->tqh_first; \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ + (head)->tqh_first->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.tqe_next = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (listelm)->field.tqe_next = (elm); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_REMOVE(head, elm, field) do { \ + if (((elm)->field.tqe_next) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ + _Q_INVALIDATE((elm)->field.tqe_prev); \ + _Q_INVALIDATE((elm)->field.tqe_next); \ +} while (0) + +#define TAILQ_REPLACE(head, elm, elm2, field) do { \ + if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ + (elm2)->field.tqe_next->field.tqe_prev = \ + &(elm2)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm2)->field.tqe_next; \ + (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ + *(elm2)->field.tqe_prev = (elm2); \ + _Q_INVALIDATE((elm)->field.tqe_prev); \ + _Q_INVALIDATE((elm)->field.tqe_next); \ +} while (0) + +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + } \ +} while (0) + +/* + * Singly-linked Tail queue declarations. + */ +#define STAILQ_HEAD(name, type) \ +struct name { \ + struct type *stqh_first; /* first element */ \ + struct type **stqh_last; /* addr of last next element */ \ +} + +#define STAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first } + +#define STAILQ_ENTRY(type) \ +struct { \ + struct type *stqe_next; /* next element */ \ +} + +/* + * Singly-linked Tail queue access methods. + */ +#define STAILQ_FIRST(head) ((head)->stqh_first) +#define STAILQ_END(head) NULL +#define STAILQ_EMPTY(head) (STAILQ_FIRST(head) == STAILQ_END(head)) +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) + +#define STAILQ_FOREACH(var, head, field) \ + for ((var) = STAILQ_FIRST(head); \ + (var) != STAILQ_END(head); \ + (var) = STAILQ_NEXT(var, field)) + +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = STAILQ_FIRST(head); \ + (var) && ((tvar) = STAILQ_NEXT(var, field), 1); \ + (var) = (tvar)) + +/* + * Singly-linked Tail queue functions. + */ +#define STAILQ_INIT(head) do { \ + STAILQ_FIRST((head)) = NULL; \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_FIRST((head)) = (elm); \ +} while (0) + +#define STAILQ_INSERT_TAIL(head, elm, field) do { \ + STAILQ_NEXT((elm), field) = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((elm), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_NEXT((elm), field) = (elm); \ +} while (0) + +#define STAILQ_REMOVE_HEAD(head, field) do { \ + if ((STAILQ_FIRST((head)) = \ + STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_REMOVE_AFTER(head, elm, field) do { \ + if ((STAILQ_NEXT(elm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_REMOVE(head, elm, type, field) do { \ + if (STAILQ_FIRST((head)) == (elm)) { \ + STAILQ_REMOVE_HEAD((head), field); \ + } else { \ + struct type *curelm = (head)->stqh_first; \ + while (STAILQ_NEXT(curelm, field) != (elm)) \ + curelm = STAILQ_NEXT(curelm, field); \ + STAILQ_REMOVE_AFTER(head, curelm, field); \ + } \ +} while (0) + +#define STAILQ_CONCAT(head1, head2) do { \ + if (!STAILQ_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_INIT((head2)); \ + } \ +} while (0) + +#define STAILQ_LAST(head, type, field) \ + (STAILQ_EMPTY((head)) ? NULL : \ + ((struct type *)(void *) \ + ((char *)((head)->stqh_last) - offsetof(struct type, field)))) + +#endif /* !_SYS_QUEUE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/radioio.h b/lib/libc/include/generic-openbsd/sys/radioio.h new file mode 100644 index 000000000000..de1737d445ae --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/radioio.h @@ -0,0 +1,76 @@ +/* $OpenBSD: radioio.h,v 1.5 2015/01/14 21:15:36 deraadt Exp $ */ +/* $RuOBSD: radioio.h,v 1.4 2001/10/18 16:51:36 pva Exp $ */ + +/* + * Copyright (c) 2001 Maxim Tsyplakov , + * Vladimir Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS 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 _SYS_RADIOIO_H_ +#define _SYS_RADIOIO_H_ + +#include + +#define MIN_FM_FREQ 87500 +#define MAX_FM_FREQ 108000 + +#define MIN_TV_CHAN 0 +#define MAX_TV_CHAN 150 + +#define IF_FREQ 10700 + +struct radio_info { + int mute; + int volume; + int stereo; + int rfreq; /* reference frequency */ + int lock; /* locking field strength during an automatic search */ + u_int32_t freq; /* in kHz */ + u_int32_t caps; /* card capabilities */ +#define RADIO_CAPS_DETECT_STEREO (1<<0) +#define RADIO_CAPS_DETECT_SIGNAL (1<<1) +#define RADIO_CAPS_SET_MONO (1<<2) +#define RADIO_CAPS_HW_SEARCH (1<<3) +#define RADIO_CAPS_HW_AFC (1<<4) +#define RADIO_CAPS_REFERENCE_FREQ (1<<5) +#define RADIO_CAPS_LOCK_SENSITIVITY (1<<6) +#define RADIO_CAPS_RESERVED1 (1<<7) +#define RADIO_CAPS_RESERVED2 (0xFF<<8) +#define RADIO_CARD_TYPE (0xFF<<16) + u_int32_t info; +#define RADIO_INFO_STEREO (1<<0) +#define RADIO_INFO_SIGNAL (1<<1) + u_int32_t tuner_mode; +#define RADIO_TUNER_MODE_RADIO (1<<0) +#define RADIO_TUNER_MODE_TV (1<<1) + u_int32_t chan; + u_int32_t chnlset; +}; + +/* Radio device operations */ +#define RIOCGINFO _IOR('R', 21, struct radio_info) /* get info */ +#define RIOCSINFO _IOWR('R', 22, struct radio_info) /* set info */ +#define RIOCSSRCH _IOW('R', 23, int) /* search up/down */ + +#endif /* _SYS_RADIOIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/reboot.h b/lib/libc/include/generic-openbsd/sys/reboot.h new file mode 100644 index 000000000000..e2a7e0f3a007 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/reboot.h @@ -0,0 +1,109 @@ +/* $OpenBSD: reboot.h,v 1.21 2025/09/16 12:18:10 hshoexer Exp $ */ +/* $NetBSD: reboot.h,v 1.9 1996/04/22 01:23:25 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1988, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)reboot.h 8.2 (Berkeley) 7/10/94 + */ + +#ifndef _SYS_REBOOT_H_ +#define _SYS_REBOOT_H_ + +/* + * Arguments to reboot system call. These are passed to the boot program, + * and then on to init. + */ +#define RB_AUTOBOOT 0 /* flags for system auto-booting itself */ + +#define RB_ASKNAME 0x00001 /* ask for file name to reboot from */ +#define RB_SINGLE 0x00002 /* reboot to single user only */ +#define RB_NOSYNC 0x00004 /* dont sync before reboot */ +#define RB_HALT 0x00008 /* don't reboot, just halt */ +#define RB_INITNAME 0x00010 /* name given for /etc/init (unused) */ +#define RB_DFLTROOT 0x00020 /* use compiled-in rootdev */ +#define RB_KDB 0x00040 /* give control to kernel debugger */ +#define RB_RDONLY 0x00080 /* mount root fs read-only */ +#define RB_DUMP 0x00100 /* dump kernel memory before reboot */ +#define RB_MINIROOT 0x00200 /* mini-root present in memory at boot time */ +#define RB_CONFIG 0x00400 /* change configured devices */ +#define RB_TIMEBAD 0x00800 /* don't call resettodr() in boot() */ +#define RB_POWERDOWN 0x01000 /* attempt to power down machine */ +#define RB_SERCONS 0x02000 /* use serial console if available */ +#define RB_USERREQ 0x04000 /* boot() called at user request (e.g. ddb) */ +#define RB_RESET 0x08000 /* just reset, no cleanup */ +#define RB_GOODRANDOM 0x10000 /* excellent random seed loaded */ +#define RB_UNHIBERNATE 0x20000 /* unhibernate */ +#define RB_COCOVM 0x40000 /* booting confidential VM (e.g. SEV enabled) */ + +/* + * Constants for converting boot-style device number to type, + * adaptor (uba, mba, etc), unit number and partition number. + * Type (== major device number) is in the low byte + * for backward compatibility. Except for that of the "magic + * number", each mask applies to the shifted value. + * Format: + * (4) (4) (4) (4) (8) (8) + * -------------------------------- + * |MA | AD| CT| UN| PART | TYPE | + * -------------------------------- + */ +#define B_ADAPTORSHIFT 24 +#define B_ADAPTORMASK 0x0f +#define B_ADAPTOR(val) (((val) >> B_ADAPTORSHIFT) & B_ADAPTORMASK) +#define B_CONTROLLERSHIFT 20 +#define B_CONTROLLERMASK 0xf +#define B_CONTROLLER(val) (((val)>>B_CONTROLLERSHIFT) & B_CONTROLLERMASK) +#define B_UNITSHIFT 16 +#define B_UNITMASK 0xf +#define B_UNIT(val) (((val) >> B_UNITSHIFT) & B_UNITMASK) +#define B_PARTITIONSHIFT 8 +#define B_PARTITIONMASK 0xff +#define B_PARTITION(val) (((val) >> B_PARTITIONSHIFT) & B_PARTITIONMASK) +#define B_TYPESHIFT 0 +#define B_TYPEMASK 0xff +#define B_TYPE(val) (((val) >> B_TYPESHIFT) & B_TYPEMASK) + +#define B_MAGICMASK 0xf0000000 +#define B_DEVMAGIC 0xa0000000 + +#define MAKEBOOTDEV(type, adaptor, controller, unit, partition) \ + (((type) << B_TYPESHIFT) | ((adaptor) << B_ADAPTORSHIFT) | \ + ((controller) << B_CONTROLLERSHIFT) | ((unit) << B_UNITSHIFT) | \ + ((partition) << B_PARTITIONSHIFT) | B_DEVMAGIC) + +#if defined(_KERNEL) && !defined(_STANDALONE) && !defined(_LOCORE) + +__BEGIN_DECLS +__dead void reboot(int); +__dead void boot(int); +__END_DECLS + +#endif /* _KERNEL */ + +#endif /* !_SYS_REBOOT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/refcnt.h b/lib/libc/include/generic-openbsd/sys/refcnt.h new file mode 100644 index 000000000000..150735d27ddc --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/refcnt.h @@ -0,0 +1,59 @@ +/* $OpenBSD: refcnt.h,v 1.16 2025/08/05 12:52:20 bluhm Exp $ */ + +/* + * Copyright (c) 2015 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_REFCNT_H_ +#define _SYS_REFCNT_H_ + +/* + * Locks used to protect struct members in this file: + * I immutable after creation + * a atomic operations + */ + +struct refcnt { + unsigned int r_refs; /* [a] reference counter */ + int r_traceidx; /* [I] index for dt(4) tracing */ +}; + +#define REFCNT_INITIALIZER() { .r_refs = 1, .r_traceidx = 0 } + +#ifdef _KERNEL + +void refcnt_init(struct refcnt *); +void refcnt_init_trace(struct refcnt *, int); +void refcnt_take(struct refcnt *); +int refcnt_rele(struct refcnt *); +void refcnt_rele_wake(struct refcnt *); +void refcnt_finalize(struct refcnt *, const char *); +unsigned int refcnt_read(const struct refcnt *); + +#define refcnt_shared(_r) (refcnt_read((_r)) > 1) + +/* sorted alphabetically, keep in sync with dev/dt/dt_prov_static.c */ +#define DT_REFCNT_IDX_ETHMULTI 1 +#define DT_REFCNT_IDX_IFADDR 2 +#define DT_REFCNT_IDX_IFMADDR 3 +#define DT_REFCNT_IDX_INPCB 4 +#define DT_REFCNT_IDX_RTENTRY 5 +#define DT_REFCNT_IDX_SOCKET 6 +#define DT_REFCNT_IDX_SYNCACHE 7 +#define DT_REFCNT_IDX_TDB 8 + +#endif /* _KERNEL */ + +#endif /* _SYS_REFCNT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/resource.h b/lib/libc/include/generic-openbsd/sys/resource.h new file mode 100644 index 000000000000..fcef9802bdec --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/resource.h @@ -0,0 +1,128 @@ +/* $OpenBSD: resource.h,v 1.14 2013/10/25 04:42:48 guenther Exp $ */ +/* $NetBSD: resource.h,v 1.14 1996/02/09 18:25:27 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)resource.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _SYS_RESOURCE_H_ +#define _SYS_RESOURCE_H_ + +#include + +/* + * Process priority specifications to get/setpriority. + */ +#define PRIO_MIN (-20) +#define PRIO_MAX 20 + +#define PRIO_PROCESS 0 +#define PRIO_PGRP 1 +#define PRIO_USER 2 + +/* + * Resource utilization information. + */ + +#define RUSAGE_SELF 0 +#define RUSAGE_CHILDREN (-1) +#define RUSAGE_THREAD 1 + +struct rusage { + struct timeval ru_utime; /* user time used */ + struct timeval ru_stime; /* system time used */ + long ru_maxrss; /* max resident set size */ +#define ru_first ru_ixrss + long ru_ixrss; /* integral shared text memory size */ + long ru_idrss; /* integral unshared data " */ + long ru_isrss; /* integral unshared stack " */ + long ru_minflt; /* page reclaims */ + long ru_majflt; /* page faults */ + long ru_nswap; /* swaps */ + long ru_inblock; /* block input operations */ + long ru_oublock; /* block output operations */ + long ru_msgsnd; /* messages sent */ + long ru_msgrcv; /* messages received */ + long ru_nsignals; /* signals received */ + long ru_nvcsw; /* voluntary context switches */ + long ru_nivcsw; /* involuntary " */ +#define ru_last ru_nivcsw +}; + +/* + * Resource limits + */ +#define RLIMIT_CPU 0 /* cpu time in milliseconds */ +#define RLIMIT_FSIZE 1 /* maximum file size */ +#define RLIMIT_DATA 2 /* data size */ +#define RLIMIT_STACK 3 /* stack size */ +#define RLIMIT_CORE 4 /* core file size */ +#define RLIMIT_RSS 5 /* resident set size */ +#define RLIMIT_MEMLOCK 6 /* locked-in-memory address space */ +#define RLIMIT_NPROC 7 /* number of processes */ +#define RLIMIT_NOFILE 8 /* number of open files */ + +#define RLIM_NLIMITS 9 /* number of resource limits */ + +#define RLIM_INFINITY (((rlim_t)1 << 63) - 1) +#define RLIM_SAVED_MAX RLIM_INFINITY +#define RLIM_SAVED_CUR RLIM_INFINITY + +struct rlimit { + rlim_t rlim_cur; /* current (soft) limit */ + rlim_t rlim_max; /* maximum value for rlim_cur */ +}; + +#if __BSD_VISIBLE +/* Load average structure. */ +struct loadavg { + fixpt_t ldavg[3]; + long fscale; +}; +#endif /* __BSD_VISIBLE */ + +#ifdef _KERNEL +extern struct loadavg averunnable; +struct process; +int dosetrlimit(struct proc *, u_int, struct rlimit *); +int donice(struct proc *, struct process *, int); +int dogetrusage(struct proc *, int, struct rusage *); + +#else +__BEGIN_DECLS +int getpriority(int, id_t); +int getrlimit(int, struct rlimit *); +int getrusage(int, struct rusage *); +int setpriority(int, id_t, int); +int setrlimit(int, const struct rlimit *); +__END_DECLS + +#endif /* _KERNEL */ +#endif /* !_SYS_RESOURCE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/resourcevar.h b/lib/libc/include/generic-openbsd/sys/resourcevar.h new file mode 100644 index 000000000000..de6db8037a4a --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/resourcevar.h @@ -0,0 +1,114 @@ +/* $OpenBSD: resourcevar.h,v 1.35 2024/10/24 23:24:58 jsg Exp $ */ +/* $NetBSD: resourcevar.h,v 1.12 1995/11/22 23:01:53 cgd Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)resourcevar.h 8.3 (Berkeley) 2/22/94 + */ + +#ifndef _SYS_RESOURCEVAR_H_ +#define _SYS_RESOURCEVAR_H_ + +#include + +/* + * Kernel shareable process resource limits. Because this structure + * is moderately large but changes infrequently, it is shared + * copy-on-write after forks. + */ +struct plimit { + struct rlimit pl_rlimit[RLIM_NLIMITS]; + struct refcnt pl_refcnt; +}; + +/* add user profiling from AST */ +#define ADDUPROF(p) \ +do { \ + atomic_clearbits_int(&(p)->p_flag, P_OWEUPC); \ + addupc_task((p), (p)->p_prof_addr, (p)->p_prof_ticks); \ + (p)->p_prof_ticks = 0; \ +} while (0) + +#ifdef _KERNEL + +#include /* for KASSERT() */ + +extern uint64_t profclock_period; + +void addupc_intr(struct proc *, u_long, u_long); +void addupc_task(struct proc *, u_long, u_int); +struct clockrequest; +void profclock(struct clockrequest *, void *, void *); +void tuagg_add_process(struct process *, struct proc *); +void tuagg_add_runtime(void); +struct tusage; +void tuagg_get_proc(struct tusage *, struct proc *); +void tuagg_get_process(struct tusage *, struct process *); +void calctsru(struct tusage *, struct timespec *, struct timespec *, + struct timespec *); +void calcru(struct tusage *, struct timeval *, struct timeval *, + struct timeval *); +void lim_startup(struct plimit *); +void lim_free(struct plimit *); +void lim_fork(struct process *, struct process *); +struct plimit *lim_read_enter(void); + +/* + * Finish read access to resource limits. + */ +static inline void +lim_read_leave(struct plimit *limit) +{ + /* nothing */ +} + +/* + * Get the value of the resource limit in current process. + */ +static inline rlim_t +lim_cur(int which) +{ + struct plimit *limit; + rlim_t val; + + KASSERT(which >= 0 && which < RLIM_NLIMITS); + + limit = lim_read_enter(); + val = limit->pl_rlimit[which].rlim_cur; + lim_read_leave(limit); + return (val); +} + +rlim_t lim_cur_proc(struct proc *, int); + +void ruadd(struct rusage *, const struct rusage *); +void rucheck(void *); + +#endif +#endif /* !_SYS_RESOURCEVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/rwlock.h b/lib/libc/include/generic-openbsd/sys/rwlock.h new file mode 100644 index 000000000000..fa5a61a152a2 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/rwlock.h @@ -0,0 +1,251 @@ +/* $OpenBSD: rwlock.h,v 1.34 2025/07/21 20:36:41 bluhm Exp $ */ +/* + * Copyright (c) 2002 Artur Grabowski + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Multiple readers, single writer lock. + * + * Simplistic implementation modelled after rw locks in Solaris. + * + * The rwl_owner has the following layout: + * [ owner or count of readers | wrlock | wrwant | wait ] + * + * When the WAIT bit is set (bit 0), the lock has waiters sleeping on it. + * When the WRWANT bit is set (bit 1), at least one waiter wants a write lock. + * When the WRLOCK bit is set (bit 2) the lock is currently write-locked. + * + * When write locked, the upper bits contain the struct proc * pointer to + * the writer, otherwise they count the number of readers. + * + * We provide a simple machine independent implementation: + * + * void rw_enter_read(struct rwlock *) + * atomically test for RWLOCK_WRLOCK and if not set, increment the lock + * by RWLOCK_READ_INCR. While RWLOCK_WRLOCK is set, loop into rw_enter_wait. + * + * void rw_enter_write(struct rwlock *); + * atomically test for the lock being 0 (it's not possible to have + * owner/read count unset and waiter bits set) and if 0 set the owner to + * the proc and RWLOCK_WRLOCK. While not zero, loop into rw_enter_wait. + * + * void rw_exit_read(struct rwlock *); + * atomically decrement lock by RWLOCK_READ_INCR and unset RWLOCK_WAIT and + * RWLOCK_WRWANT remembering the old value of lock and if RWLOCK_WAIT was set, + * call rw_exit_waiters with the old contents of the lock. + * + * void rw_exit_write(struct rwlock *); + * atomically swap the contents of the lock with 0 and if RWLOCK_WAIT was + * set, call rw_exit_waiters with the old contents of the lock. + */ + +#ifndef _SYS_RWLOCK_H +#define _SYS_RWLOCK_H + +#include + +struct proc; + +struct rwlock { + volatile unsigned long rwl_owner; + volatile unsigned int rwl_waiters; + volatile unsigned int rwl_readers; + const char *rwl_name; +#ifdef WITNESS + struct lock_object rwl_lock_obj; +#endif + int rwl_traceidx; +}; + +#define RWLOCK_LO_FLAGS(flags) \ + ((ISSET(flags, RWL_DUPOK) ? LO_DUPOK : 0) | \ + (ISSET(flags, RWL_NOWITNESS) ? 0 : LO_WITNESS) | \ + (ISSET(flags, RWL_IS_VNODE) ? LO_IS_VNODE : 0) | \ + LO_INITIALIZED | LO_SLEEPABLE | LO_UPGRADABLE | \ + (LO_CLASS_RWLOCK << LO_CLASSSHIFT)) + +#define RRWLOCK_LO_FLAGS(flags) \ + ((ISSET(flags, RWL_DUPOK) ? LO_DUPOK : 0) | \ + (ISSET(flags, RWL_NOWITNESS) ? 0 : LO_WITNESS) | \ + (ISSET(flags, RWL_IS_VNODE) ? LO_IS_VNODE : 0) | \ + LO_INITIALIZED | LO_RECURSABLE | LO_SLEEPABLE | LO_UPGRADABLE | \ + (LO_CLASS_RRWLOCK << LO_CLASSSHIFT)) + +#define RWLOCK_LO_INITIALIZER(name, flags) \ + { .lo_type = &(const struct lock_type){ .lt_name = name }, \ + .lo_name = (name), \ + .lo_flags = RWLOCK_LO_FLAGS(flags) } + +#define RWL_DUPOK 0x01 +#define RWL_NOWITNESS 0x02 +#define RWL_IS_VNODE 0x04 + +#ifdef WITNESS +#define RWLOCK_INITIALIZER(name) \ + { 0, 0, 0, name, .rwl_lock_obj = RWLOCK_LO_INITIALIZER(name, 0), 0 } +#define RWLOCK_INITIALIZER_TRACE(name, trace) \ + { 0, 0, 0, name, .rwl_lock_obj = RWLOCK_LO_INITIALIZER(name, 0), trace } +#else +#define RWLOCK_INITIALIZER(name) \ + { 0, 0, 0, name, 0 } +#define RWLOCK_INITIALIZER_TRACE(name, trace) \ + { 0, 0, 0, name, trace } +#endif + +#define RWLOCK_WRLOCK 0x04UL +#define RWLOCK_MASK 0x07UL + +#define RWLOCK_OWNER(rwl) ((struct proc *)((rwl)->rwl_owner & ~RWLOCK_MASK)) + +#define RWLOCK_READER_SHIFT 3UL +#define RWLOCK_READ_INCR (1UL << RWLOCK_READER_SHIFT) + +#define RW_WRITE 0x0001UL /* exclusive lock */ +#define RW_READ 0x0002UL /* shared lock */ +#define RW_DOWNGRADE 0x0004UL /* downgrade exclusive to shared */ +#define RW_UPGRADE 0x0005UL +#define RW_OPMASK 0x0007UL + +#define RW_INTR 0x0010UL /* interruptible sleep */ +#define RW_NOSLEEP 0x0040UL /* don't wait for the lock */ +#define RW_RECURSEFAIL 0x0080UL /* Fail on recursion for RRW locks. */ +#define RW_DUPOK 0x0100UL /* Permit duplicate lock */ + +/* + * for rw_status() and rrw_status() only: exclusive lock held by + * some other thread + */ +#define RW_WRITE_OTHER 0x0100UL + +/* recursive rwlocks; */ +struct rrwlock { + struct rwlock rrwl_lock; + uint32_t rrwl_wcnt; /* # writers. */ +}; + +#ifdef _KERNEL + +void _rw_init_flags(struct rwlock *, const char *, int, + const struct lock_type *, int); + +#ifdef WITNESS +#define rw_init_flags_trace(rwl, name, flags, trace) do { \ + static const struct lock_type __lock_type = { .lt_name = #rwl };\ + _rw_init_flags(rwl, name, flags, &__lock_type, trace); \ +} while (0) +#define rw_init_flags(rwl, name, flags) do { \ + static const struct lock_type __lock_type = { .lt_name = #rwl };\ + _rw_init_flags(rwl, name, flags, &__lock_type, 0); \ +} while (0) +#define rw_init(rwl, name) rw_init_flags(rwl, name, 0) +#else /* WITNESS */ +#define rw_init_flags_trace(rwl, name, flags, trace) \ + _rw_init_flags(rwl, name, flags, NULL, trace) +#define rw_init_flags(rwl, name, flags) \ + _rw_init_flags(rwl, name, flags, NULL, 0) +#define rw_init(rwl, name) _rw_init_flags(rwl, name, 0, NULL, 0) +#endif /* WITNESS */ + +void rw_enter_read(struct rwlock *); +void rw_enter_write(struct rwlock *); +void rw_exit_read(struct rwlock *); +void rw_exit_write(struct rwlock *); + +#ifdef DIAGNOSTIC +void rw_assert_wrlock(struct rwlock *); +void rw_assert_rdlock(struct rwlock *); +void rw_assert_anylock(struct rwlock *); +void rw_assert_unlocked(struct rwlock *); +#else +#define rw_assert_wrlock(rwl) ((void)0) +#define rw_assert_rdlock(rwl) ((void)0) +#define rw_assert_anylock(rwl) ((void)0) +#define rw_assert_unlocked(rwl) ((void)0) +#endif + +int rw_enter(struct rwlock *, int); +void rw_exit(struct rwlock *); +int rw_status(struct rwlock *); + +static inline int +rw_read_held(struct rwlock *rwl) +{ + return (rw_status(rwl) == RW_READ); +} + +static inline int +rw_write_held(struct rwlock *rwl) +{ + return (rw_status(rwl) == RW_WRITE); +} + +static inline int +rw_lock_held(struct rwlock *rwl) +{ + int status; + + status = rw_status(rwl); + + return (status == RW_READ || status == RW_WRITE); +} + + +void _rrw_init_flags(struct rrwlock *, const char *, int, + const struct lock_type *); +int rrw_enter(struct rrwlock *, int); +void rrw_exit(struct rrwlock *); +int rrw_status(struct rrwlock *); + +#ifdef WITNESS +#define rrw_init_flags(rrwl, name, flags) do { \ + static const struct lock_type __lock_type = { .lt_name = #rrwl };\ + _rrw_init_flags(rrwl, name, flags, &__lock_type); \ +} while (0) +#define rrw_init(rrwl, name) rrw_init_flags(rrwl, name, 0) +#else /* WITNESS */ +#define rrw_init_flags(rrwl, name, flags) \ + _rrw_init_flags(rrwl, name, 0, NULL) +#define rrw_init(rrwl, name) _rrw_init_flags(rrwl, name, 0, NULL) +#endif /* WITNESS */ + + +/* + * Allocated, reference-counted rwlocks + */ + +#ifdef WITNESS +#define rw_obj_alloc_flags(rwl, name, flags) do { \ + static struct lock_type __lock_type = { .lt_name = #rwl }; \ + _rw_obj_alloc_flags(rwl, name, flags, &__lock_type); \ +} while (0) +#else +#define rw_obj_alloc_flags(rwl, name, flags) \ + _rw_obj_alloc_flags(rwl, name, flags, NULL) +#endif +#define rw_obj_alloc(rwl, name) rw_obj_alloc_flags(rwl, name, 0) + +void rw_obj_init(void); +void _rw_obj_alloc_flags(struct rwlock **, const char *, int, + struct lock_type *); +void rw_obj_hold(struct rwlock *); +int rw_obj_free(struct rwlock *); + +/* sorted alphabetically, keep in sync with dev/dt/dt_prov_static.c */ +#define DT_RWLOCK_IDX_NETLOCK 1 +#define DT_RWLOCK_IDX_SOLOCK 2 + +#endif /* _KERNEL */ + +#endif /* _SYS_RWLOCK_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/sched.h b/lib/libc/include/generic-openbsd/sys/sched.h new file mode 100644 index 000000000000..d60605e7100b --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/sched.h @@ -0,0 +1,216 @@ +/* $OpenBSD: sched.h,v 1.77 2025/06/09 10:57:46 claudio Exp $ */ +/* $NetBSD: sched.h,v 1.2 1999/02/28 18:14:58 ross Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Ross Harvey. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1982, 1986, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)kern_clock.c 8.5 (Berkeley) 1/21/94 + */ + +#ifndef _SYS_SCHED_H_ +#define _SYS_SCHED_H_ + +/* + * Posix defines a which may want to include + */ + +/* + * CPU states. + * XXX Not really scheduler state, but no other good place to put + * it right now, and it really is per-CPU. + */ +#define CP_USER 0 +#define CP_NICE 1 +#define CP_SYS 2 +#define CP_SPIN 3 +#define CP_INTR 4 +#define CP_IDLE 5 +#define CPUSTATES 6 + +struct cpustats { + uint64_t cs_time[CPUSTATES]; /* CPU state statistics */ + uint64_t cs_flags; /* see below */ +}; + +#define CPUSTATS_ONLINE 0x0001 /* CPU is schedulable */ + +#ifdef _KERNEL + +#include +#include +#include + +#define SCHED_NQS 32 /* 32 run queues. */ + +struct smr_entry; + +/* + * Per-CPU scheduler state. + * o owned (modified only) by this CPU + */ +struct schedstate_percpu { + struct proc *spc_idleproc; /* idle proc for this cpu */ + TAILQ_HEAD(prochead, proc) spc_qs[SCHED_NQS]; + TAILQ_HEAD(,proc) spc_deadproc; + struct timespec spc_runtime; /* time curproc started running */ + volatile int spc_schedflags; /* flags; see below */ + u_int spc_schedticks; /* ticks for schedclock() */ + struct pc_lock spc_cp_time_lock; + u_int64_t spc_cp_time[CPUSTATES]; /* CPU state statistics */ + + struct clockintr spc_itimer; /* [o] itimer_update handle */ + struct clockintr spc_profclock; /* [o] profclock handle */ + struct clockintr spc_roundrobin;/* [o] roundrobin handle */ + struct clockintr spc_statclock; /* [o] statclock handle */ + + u_int spc_nrun; /* procs on the run queues */ + + volatile uint32_t spc_whichqs; + volatile u_int spc_spinning; /* this cpu is currently spinning */ + + SIMPLEQ_HEAD(, smr_entry) spc_deferred; /* deferred smr calls */ + u_int spc_ndeferred; /* number of deferred smr calls */ + u_int spc_smrdepth; /* level of smr nesting */ + u_char spc_smrexpedite; /* if set, dispatch smr entries + * without delay */ + u_char spc_smrgp; /* this CPU's view of grace period */ + volatile u_char spc_curpriority; /* [o] usrpri of curproc */ +}; + +/* spc_flags */ +#define SPCF_SEENRR 0x0001 /* process has seen roundrobin() */ +#define SPCF_SHOULDYIELD 0x0002 /* process should yield the CPU */ +#define SPCF_SWITCHCLEAR (SPCF_SEENRR|SPCF_SHOULDYIELD) +#define SPCF_SHOULDHALT 0x0004 /* CPU should be vacated */ +#define SPCF_HALTED 0x0008 /* CPU has been halted */ +#define SPCF_PROFCLOCK 0x0010 /* profclock() was started */ +#define SPCF_ITIMER 0x0020 /* itimer_update() was started */ + +#define SCHED_PPQ (128 / SCHED_NQS) /* priorities per queue */ +#define NICE_WEIGHT 2 /* priorities per nice level */ +#define ESTCPULIM(e) min((e), NICE_WEIGHT * PRIO_MAX - SCHED_PPQ) + +extern uint64_t roundrobin_period; + +struct proc; +void schedclock(struct proc *); +struct clockrequest; +void roundrobin(struct clockrequest *, void *, void *); +void scheduler_start(void); +void userret(struct proc *p); + +struct cpu_info; +void sched_init(void); +void sched_init_cpu(struct cpu_info *); +void sched_idle(void *); +void sched_exit(struct proc *); +void sched_toidle(void); +void mi_switch(void); +void cpu_switchto(struct proc *, struct proc *); +struct proc *sched_chooseproc(void); +struct cpu_info *sched_choosecpu(struct proc *); +struct cpu_info *sched_choosecpu_fork(struct proc *parent, int); +void cpu_idle_enter(void); +void cpu_idle_cycle(void); +void cpu_idle_leave(void); +void sched_peg_curproc(struct cpu_info *ci); +void sched_unpeg_curproc(void); +void sched_barrier(struct cpu_info *ci); + +int sysctl_hwsetperf(void *, size_t *, void *, size_t); +int sysctl_hwperfpolicy(void *, size_t *, void *, size_t); +int sysctl_hwsmt(void *, size_t *, void *, size_t); +int sysctl_hwncpuonline(void); + +#ifdef MULTIPROCESSOR +void sched_start_secondary_cpus(void); +void sched_stop_secondary_cpus(void); +#endif + +#define cpu_is_idle(ci) ((ci)->ci_schedstate.spc_whichqs == 0) +int cpu_is_online(struct cpu_info *); + +void setrunqueue(struct cpu_info *, struct proc *, uint8_t); +void remrunqueue(struct proc *); + +/* Chargeback parents for the sins of their children. */ +#define scheduler_wait_hook(parent, child) do { \ + (parent)->p_estcpu = ESTCPULIM((parent)->p_estcpu + (child)->p_estcpu);\ +} while (0) + +/* Allow other processes to progress */ +#define sched_pause(func) do { \ + if (curcpu()->ci_schedstate.spc_schedflags & SPCF_SHOULDYIELD) \ + func(); \ +} while (0) + +extern struct mutex sched_lock; + +#define SCHED_ASSERT_LOCKED() MUTEX_ASSERT_LOCKED(&sched_lock) +#define SCHED_ASSERT_UNLOCKED() MUTEX_ASSERT_UNLOCKED(&sched_lock) + +#define SCHED_LOCK_INIT() mtx_init(&sched_lock, IPL_SCHED) +#define SCHED_LOCK() mtx_enter(&sched_lock) +#define SCHED_UNLOCK() mtx_leave(&sched_lock) + +#endif /* _KERNEL */ +#endif /* _SYS_SCHED_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/scsiio.h b/lib/libc/include/generic-openbsd/sys/scsiio.h new file mode 100644 index 000000000000..90ae749bf4ea --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/scsiio.h @@ -0,0 +1,74 @@ +/* $OpenBSD: scsiio.h,v 1.10 2012/09/05 17:17:47 deraadt Exp $ */ +/* $NetBSD: scsiio.h,v 1.3 1994/06/29 06:45:09 cgd Exp $ */ + +#ifndef _SYS_SCSIIO_H_ +#define _SYS_SCSIIO_H_ + + +#include +#include + +#define SENSEBUFLEN 48 +#define CMDBUFLEN 16 + +typedef struct scsireq { + u_long flags; /* info about the request status and type */ + u_long timeout; + u_char cmd[CMDBUFLEN]; + u_char cmdlen; + caddr_t databuf; /* address in user space of buffer */ + u_long datalen; /* size of user buffer (request) */ + u_long datalen_used; /* size of user buffer (used)*/ + u_char sense[SENSEBUFLEN]; /* returned sense will be in here */ + u_char senselen; /* sensedata request size (MAX of SENSEBUFLEN)*/ + u_char senselen_used; /* return value only */ + u_char status; /* what the scsi status was from the adapter */ + u_char retsts; /* the return status for the command */ + int error; /* error bits */ +} scsireq_t; + +/* bit definitions for flags */ +#define SCCMD_READ 0x00000001 +#define SCCMD_WRITE 0x00000002 +#define SCCMD_IOV 0x00000004 +#define SCCMD_ESCAPE 0x00000010 +#define SCCMD_TARGET 0x00000020 + + +/* definitions for the return status (retsts) */ +#define SCCMD_OK 0x00 +#define SCCMD_TIMEOUT 0x01 +#define SCCMD_BUSY 0x02 +#define SCCMD_SENSE 0x03 +#define SCCMD_UNKNOWN 0x04 + +#define SCIOCCOMMAND _IOWR('Q', 1, scsireq_t) + +#define SC_DB_CMDS 0x00000001 /* show all scsi cmds and errors */ +#define SC_DB_FLOW 0x00000002 /* show routines entered */ +#define SC_DB_FLOW2 0x00000004 /* show path INSIDE routines */ +#define SC_DB_DMA 0x00000008 /* show DMA segments etc */ +#define SCIOCDEBUG _IOW('Q', 2, int) /* from 0 to 15 */ + +struct scsi_addr { + int type; +#define TYPE_SCSI 0 +#define TYPE_ATAPI 1 + int scbus; /* -1 if wildcard */ + int target; /* -1 if wildcard */ + int lun; /* -1 if wildcard */ +}; + +#define SCIOCRESET _IO('Q', 7) /* reset the device */ +#define SCIOCIDENTIFY _IOR('Q', 9, struct scsi_addr) + +struct sbioc_device { + void *sd_cookie; + int sd_target; + int sd_lun; +}; + +#define SBIOCPROBE _IOWR('Q', 127, struct sbioc_device) +#define SBIOCDETACH _IOWR('Q', 128, struct sbioc_device) + +#endif /* _SYS_SCSIIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/select.h b/lib/libc/include/generic-openbsd/sys/select.h new file mode 100644 index 000000000000..7d9a52fc17bd --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/select.h @@ -0,0 +1,137 @@ +/* $OpenBSD: select.h,v 1.17 2016/09/12 19:41:20 guenther Exp $ */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)select.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _SYS_SELECT_H_ +#define _SYS_SELECT_H_ + +#include + +#ifndef _TIMEVAL_DECLARED +#define _TIMEVAL_DECLARED +struct timeval { + time_t tv_sec; /* seconds */ + suseconds_t tv_usec; /* and microseconds */ +}; +#endif + +#ifndef _TIMESPEC_DECLARED +#define _TIMESPEC_DECLARED +struct timespec { + time_t tv_sec; /* seconds */ + long tv_nsec; /* and nanoseconds */ +}; +#endif + +/* + * Select uses bit masks of file descriptors in longs. These macros + * manipulate such bit fields (the filesystem macros use chars). + * FD_SETSIZE may be defined by the user, but the default here should + * be enough for most uses. + */ +#ifndef FD_SETSIZE +#define FD_SETSIZE 1024 +#endif + +/* + * We don't want to pollute the namespace with select(2) internals. + * Non-underscore versions are exposed later #if __BSD_VISIBLE + */ +#define __NBBY 8 /* number of bits in a byte */ +typedef uint32_t __fd_mask; +#define __NFDBITS ((unsigned)(sizeof(__fd_mask) * __NBBY)) /* bits per mask */ +#define __howmany(x, y) (((x) + ((y) - 1)) / (y)) + +typedef struct fd_set { + __fd_mask fds_bits[__howmany(FD_SETSIZE, __NFDBITS)]; +} fd_set; + +static __inline void +__fd_set(int fd, fd_set *p) +{ + p->fds_bits[fd / __NFDBITS] |= (1U << (fd % __NFDBITS)); +} +#define FD_SET(n, p) __fd_set((n), (p)) + +static __inline void +__fd_clr(int fd, fd_set *p) +{ + p->fds_bits[fd / __NFDBITS] &= ~(1U << (fd % __NFDBITS)); +} +#define FD_CLR(n, p) __fd_clr((n), (p)) + +static __inline int +__fd_isset(int fd, const fd_set *p) +{ + return (p->fds_bits[fd / __NFDBITS] & (1U << (fd % __NFDBITS))); +} +#define FD_ISSET(n, p) __fd_isset((n), (p)) + +#if __BSD_VISIBLE +#define FD_COPY(f, t) (void)(*(t) = *(f)) +#endif +#define FD_ZERO(p) do { \ + fd_set *_p = (p); \ + __size_t _n = __howmany(FD_SETSIZE, __NFDBITS); \ + \ + while (_n > 0) \ + _p->fds_bits[--_n] = 0; \ +} while (0) + +#if __BSD_VISIBLE +#define NBBY __NBBY +#define fd_mask __fd_mask +#define NFDBITS __NFDBITS +#ifndef howmany +#define howmany(x, y) __howmany(x, y) +#endif +#endif /* __BSD_VISIBLE */ + +#ifndef _KERNEL +#ifndef _SIGSET_T_DEFINED_ +#define _SIGSET_T_DEFINED_ +typedef unsigned int sigset_t; +#endif + +#ifndef _SELECT_DEFINED_ +#define _SELECT_DEFINED_ +__BEGIN_DECLS +int select(int, fd_set * __restrict, fd_set * __restrict, + fd_set * __restrict, struct timeval * __restrict); +int pselect(int, fd_set * __restrict, fd_set * __restrict, + fd_set * __restrict, const struct timespec * __restrict, + const sigset_t * __restrict); +__END_DECLS +#endif +#endif /* !_KERNEL */ + +#endif /* !_SYS_SELECT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/selinfo.h b/lib/libc/include/generic-openbsd/sys/selinfo.h new file mode 100644 index 000000000000..15b07f3744f9 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/selinfo.h @@ -0,0 +1,51 @@ +/* $OpenBSD: selinfo.h,v 1.6 2022/07/05 15:06:16 visa Exp $ */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)select.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _SYS_SELINFO_H_ +#define _SYS_SELINFO_H_ + +#include /* for struct klist */ + +/* + * Used to maintain information about processes that wish to be + * notified when I/O becomes possible. + */ +struct selinfo { + struct klist si_note; /* kernel note list */ +}; + +#ifdef _KERNEL +void selwakeup(struct selinfo *); +#endif + +#endif /* !_SYS_SELINFO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/sem.h b/lib/libc/include/generic-openbsd/sys/sem.h new file mode 100644 index 000000000000..621ec97144d4 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/sem.h @@ -0,0 +1,192 @@ +/* $OpenBSD: sem.h,v 1.26 2024/10/26 05:39:03 jsg Exp $ */ +/* $NetBSD: sem.h,v 1.8 1996/02/09 18:25:29 christos Exp $ */ + +/* + * SVID compatible sem.h file + * + * Author: Daniel Boulet + */ + +#ifndef _SYS_SEM_H_ +#define _SYS_SEM_H_ + +#ifndef _SYS_IPC_H_ +#include +#endif + +#if __BSD_VISIBLE + +/* sem-specific sysctl variables corresponding to members of struct seminfo */ +#define KERN_SEMINFO_SEMMNI 1 /* int: # of semaphore identifiers */ +#define KERN_SEMINFO_SEMMNS 2 /* int: # of semaphores in system */ +#define KERN_SEMINFO_SEMMNU 3 /* int: # of undo structures in system */ +#define KERN_SEMINFO_SEMMSL 4 /* int: max semaphores per id */ +#define KERN_SEMINFO_SEMOPM 5 /* int: max operations per semop call */ +#define KERN_SEMINFO_SEMUME 6 /* int: max undo entries per process */ +#define KERN_SEMINFO_SEMUSZ 7 /* int: size in bytes of struct undo */ +#define KERN_SEMINFO_SEMVMX 8 /* int: semaphore maximum value */ +#define KERN_SEMINFO_SEMAEM 9 /* int: adjust on exit max value */ +#define KERN_SEMINFO_MAXID 10 /* number of valid semaphore sysctls */ + +#define CTL_KERN_SEMINFO_NAMES { \ + { 0, 0 }, \ + { "semmni", CTLTYPE_INT }, \ + { "semmns", CTLTYPE_INT }, \ + { "semmnu", CTLTYPE_INT }, \ + { "semmsl", CTLTYPE_INT }, \ + { "semopm", CTLTYPE_INT }, \ + { "semume", CTLTYPE_INT }, \ + { "semusz", CTLTYPE_INT }, \ + { "semvmx", CTLTYPE_INT }, \ + { "semaem", CTLTYPE_INT }, \ +} + +#endif /* __BSD_VISIBLE */ + +struct sem { + unsigned short semval; /* semaphore value */ + pid_t sempid; /* pid of last operation */ + unsigned short semncnt; /* # awaiting semval > cval */ + unsigned short semzcnt; /* # awaiting semval = 0 */ +}; + +struct semid_ds { + struct ipc_perm sem_perm; /* operation permission struct */ + struct sem *sem_base; /* pointer to first semaphore in set */ + unsigned short sem_nsems; /* number of sems in set */ + time_t sem_otime; /* last operation time */ + long sem_pad1; /* SVABI/386 says I need this here */ + time_t sem_ctime; /* last change time */ + /* Times measured in secs since */ + /* 00:00:00 GMT, Jan. 1, 1970 */ + long sem_pad2; /* SVABI/386 says I need this here */ + long sem_pad3[4]; /* SVABI/386 says I need this here */ +}; + +/* + * semop's sops parameter structure + */ +struct sembuf { + unsigned short sem_num; /* semaphore # */ + short sem_op; /* semaphore operation */ + short sem_flg; /* operation flags */ +}; +#define SEM_UNDO 010000 + +/* + * semctl's arg parameter structure + */ +union semun { + int val; /* value for SETVAL */ + struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ + unsigned short *array; /* array for GETALL & SETALL */ +}; + +/* + * commands for semctl + */ +#define GETNCNT 3 /* Return the value of semncnt {READ} */ +#define GETPID 4 /* Return the value of sempid {READ} */ +#define GETVAL 5 /* Return the value of semval {READ} */ +#define GETALL 6 /* Return semvals into arg.array {READ} */ +#define GETZCNT 7 /* Return the value of semzcnt {READ} */ +#define SETVAL 8 /* Set the value of semval to arg.val {ALTER} */ +#define SETALL 9 /* Set semvals from arg.array {ALTER} */ + + +/* + * Permissions + */ +#define SEM_A 0200 /* alter permission */ +#define SEM_R 0400 /* read permission */ + + +#ifdef _KERNEL +#include + +/* + * Kernel implementation stuff + */ +#define SEMVMX 32767 /* semaphore maximum value */ +#define SEMAEM 16384 /* adjust on exit max value */ + +/* + * Undo structure (one per process) + */ +struct sem_undo { + SLIST_ENTRY(sem_undo) un_next; /* ptr to next active undo structure */ + struct process *un_proc; /* owner of this structure */ + short un_cnt; /* # of active entries */ + struct undo { + short un_adjval; /* adjust on exit values */ + short un_num; /* semaphore # */ + int un_id; /* semid */ + } un_ent[1]; /* undo entries */ +}; + +/* + * semaphore info struct + */ +struct seminfo { + int semmni, /* # of semaphore identifiers */ + semmns, /* # of semaphores in system */ + semmnu, /* # of undo structures in system */ + semmsl, /* max # of semaphores per id */ + semopm, /* max # of operations per semop call */ + semume, /* max # of undo entries per process */ + semusz, /* size in bytes of undo structure */ + semvmx, /* semaphore maximum value */ + semaem; /* adjust on exit max value */ +}; + +struct sem_sysctl_info { + struct seminfo seminfo; + struct semid_ds semids[1]; +}; + +extern struct seminfo seminfo; + +/* + * Configuration parameters + */ +#ifndef SEMMNI +#define SEMMNI 10 /* # of semaphore identifiers */ +#endif +#ifndef SEMMNS +#define SEMMNS 60 /* # of semaphores in system */ +#endif +#ifndef SEMUME +#define SEMUME 10 /* max # of undo entries per process */ +#endif +#ifndef SEMMNU +#define SEMMNU 30 /* # of undo structures in system */ +#endif + +/* shouldn't need tuning */ +#ifndef SEMMSL +#define SEMMSL SEMMNS /* max # of semaphores per id */ +#endif +#ifndef SEMOPM +#define SEMOPM 100 /* max # of operations per semop call */ +#endif + +/* actual size of an undo structure */ +#define SEMUSZ (sizeof(struct sem_undo)+sizeof(struct undo)*SEMUME) + +extern struct semid_ds **sema; /* semaphore id list */ + +void seminit(void); +void semexit(struct process *); +int sysctl_sysvsem(int *, u_int, void *, size_t *, void *, size_t); +#endif /* _KERNEL */ + +#ifndef _KERNEL +__BEGIN_DECLS +int semctl(int, int, int, ...); +int __semctl(int, int, int, union semun *); +int semget(key_t, int, int); +int semop(int, struct sembuf *, size_t); +__END_DECLS +#endif /* !_KERNEL */ + +#endif /* !_SYS_SEM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/sensors.h b/lib/libc/include/generic-openbsd/sys/sensors.h new file mode 100644 index 000000000000..86cd6a10ec87 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/sensors.h @@ -0,0 +1,179 @@ +/* $OpenBSD: sensors.h,v 1.37 2020/07/15 07:13:57 kettenis Exp $ */ + +/* + * Copyright (c) 2003, 2004 Alexander Yurchenko + * Copyright (c) 2006 Constantine A. Murenin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_SENSORS_H_ +#define _SYS_SENSORS_H_ + +/* Sensor types */ +enum sensor_type { + SENSOR_TEMP, /* temperature (uK) */ + SENSOR_FANRPM, /* fan revolution speed */ + SENSOR_VOLTS_DC, /* voltage (uV DC) */ + SENSOR_VOLTS_AC, /* voltage (uV AC) */ + SENSOR_OHMS, /* resistance */ + SENSOR_WATTS, /* power (uW) */ + SENSOR_AMPS, /* current (uA) */ + SENSOR_WATTHOUR, /* power capacity (uWh) */ + SENSOR_AMPHOUR, /* power capacity (uAh) */ + SENSOR_INDICATOR, /* boolean indicator */ + SENSOR_INTEGER, /* generic integer value */ + SENSOR_PERCENT, /* percent (m%) */ + SENSOR_LUX, /* illuminance (ulx) */ + SENSOR_DRIVE, /* disk */ + SENSOR_TIMEDELTA, /* system time error (nSec) */ + SENSOR_HUMIDITY, /* humidity (m%RH) */ + SENSOR_FREQ, /* frequency (uHz) */ + SENSOR_ANGLE, /* angle (uDegrees) */ + SENSOR_DISTANCE, /* distance (uMeter) */ + SENSOR_PRESSURE, /* pressure (mPa) */ + SENSOR_ACCEL, /* acceleration (u m/s^2) */ + SENSOR_VELOCITY, /* velocity (u m/s) */ + SENSOR_ENERGY, /* energy (uJ) */ + SENSOR_MAX_TYPES +}; + +#ifndef _KERNEL +static const char * const sensor_type_s[SENSOR_MAX_TYPES + 1] = { + "temp", + "fan", + "volt", + "acvolt", + "resistance", + "power", + "current", + "watthour", + "amphour", + "indicator", + "raw", + "percent", + "illuminance", + "drive", + "timedelta", + "humidity", + "frequency", + "angle", + "distance", + "pressure", + "acceleration", + "velocity", + "energy", + "undefined" +}; +#endif /* !_KERNEL */ + +#define SENSOR_DRIVE_EMPTY 1 +#define SENSOR_DRIVE_READY 2 +#define SENSOR_DRIVE_POWERUP 3 +#define SENSOR_DRIVE_ONLINE 4 +#define SENSOR_DRIVE_IDLE 5 +#define SENSOR_DRIVE_ACTIVE 6 +#define SENSOR_DRIVE_REBUILD 7 +#define SENSOR_DRIVE_POWERDOWN 8 +#define SENSOR_DRIVE_FAIL 9 +#define SENSOR_DRIVE_PFAIL 10 + +/* Sensor states */ +enum sensor_status { + SENSOR_S_UNSPEC, /* status is unspecified */ + SENSOR_S_OK, /* status is ok */ + SENSOR_S_WARN, /* status is warning */ + SENSOR_S_CRIT, /* status is critical */ + SENSOR_S_UNKNOWN /* status is unknown */ +}; + +/* Sensor data: + * New fields should be added at the end to encourage backwards compat + */ +struct sensor { + char desc[32]; /* sensor description, may be empty */ + struct timeval tv; /* sensor value last change time */ + int64_t value; /* current value */ + enum sensor_type type; /* sensor type */ + enum sensor_status status; /* sensor status */ + int numt; /* sensor number of .type type */ + int flags; /* sensor flags */ +#define SENSOR_FINVALID 0x0001 /* sensor is invalid */ +#define SENSOR_FUNKNOWN 0x0002 /* sensor value is unknown */ +}; + +/* Sensor device data: + * New fields should be added at the end to encourage backwards compat + */ +struct sensordev { + int num; /* sensordev number */ + char xname[16]; /* unix device name */ + int maxnumt[SENSOR_MAX_TYPES]; + int sensors_count; +}; + +#ifdef _KERNEL + +/* Sensor data */ +struct ksensor { + SLIST_ENTRY(ksensor) list; /* device-scope list */ + char desc[32]; /* sensor description, may be empty */ + struct timeval tv; /* sensor value last change time */ + int64_t value; /* current value */ + enum sensor_type type; /* sensor type */ + enum sensor_status status; /* sensor status */ + int numt; /* sensor number of .type type */ + int flags; /* sensor flags, ie. SENSOR_FINVALID */ +}; +SLIST_HEAD(ksensors_head, ksensor); + +/* Sensor device data */ +struct ksensordev { + SLIST_ENTRY(ksensordev) list; + int num; /* sensordev number */ + char xname[16]; /* unix device name */ + int maxnumt[SENSOR_MAX_TYPES]; + int sensors_count; + struct ksensors_head sensors_list; +}; + +/* struct ksensordev */ +void sensordev_install(struct ksensordev *); +void sensordev_deinstall(struct ksensordev *); +int sensordev_get(int, struct ksensordev **); + +/* struct ksensor */ +void sensor_attach(struct ksensordev *, struct ksensor *); +void sensor_detach(struct ksensordev *, struct ksensor *); +int sensor_find(int, enum sensor_type, int, struct ksensor **); + +/* task scheduling */ +struct sensor_task; +struct sensor_task *sensor_task_register(void *, void (*)(void *), + unsigned int); +void sensor_task_unregister(struct sensor_task *); +void sensor_quiesce(void); +void sensor_restart(void); + +#endif /* _KERNEL */ + +#endif /* !_SYS_SENSORS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/shm.h b/lib/libc/include/generic-openbsd/sys/shm.h new file mode 100644 index 000000000000..b3e2acabdab4 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/shm.h @@ -0,0 +1,150 @@ +/* $OpenBSD: shm.h,v 1.31 2024/10/26 05:39:03 jsg Exp $ */ +/* $NetBSD: shm.h,v 1.20 1996/04/09 20:55:35 cgd Exp $ */ + +/* + * Copyright (c) 1994 Adam Glass + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Adam Glass. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * As defined+described in "X/Open System Interfaces and Headers" + * Issue 4, p. XXX + */ + +#ifndef _SYS_SHM_H_ +#define _SYS_SHM_H_ + +#ifndef _SYS_IPC_H_ +#include +#endif + +#if __BSD_VISIBLE + +/* shm-specific sysctl variables corresponding to members of struct shminfo */ +#define KERN_SHMINFO_SHMMAX 1 /* int: max shm segment size (bytes) */ +#define KERN_SHMINFO_SHMMIN 2 /* int: min shm segment size (bytes) */ +#define KERN_SHMINFO_SHMMNI 3 /* int: max number of shm identifiers */ +#define KERN_SHMINFO_SHMSEG 4 /* int: max shm segments per process */ +#define KERN_SHMINFO_SHMALL 5 /* int: max amount of shm (pages) */ +#define KERN_SHMINFO_MAXID 6 /* number of valid shared memory ids */ + +#define CTL_KERN_SHMINFO_NAMES { \ + { 0, 0 }, \ + { "shmmax", CTLTYPE_INT }, \ + { "shmmin", CTLTYPE_INT }, \ + { "shmmni", CTLTYPE_INT }, \ + { "shmseg", CTLTYPE_INT }, \ + { "shmall", CTLTYPE_INT }, \ +} + +/* + * Old (deprecated) access mode definitions--do not use. + * Provided for compatibility with old code only. + */ +#define SHM_R IPC_R +#define SHM_W IPC_W + +#endif /* __BSD_VISIBLE */ + +/* + * Shared memory operation flags for shmat(2). + */ +#define SHM_RDONLY 010000 /* Attach read-only (else read-write) */ +#define SHM_RND 020000 /* Round attach address to SHMLBA */ + +/* + * Shared memory specific control commands for shmctl(). + * We accept but ignore these (XXX). + */ +#define SHM_LOCK 3 /* Lock segment in memory. */ +#define SHM_UNLOCK 4 /* Unlock a segment locked by SHM_LOCK. */ + +/* + * Segment low boundary address multiple + */ +#define SHMLBA (1U << _MAX_PAGE_SHIFT) + +typedef short shmatt_t; + +struct shmid_ds { + struct ipc_perm shm_perm; /* operation permission structure */ + int shm_segsz; /* size of segment in bytes */ + pid_t shm_lpid; /* process ID of last shm op */ + pid_t shm_cpid; /* process ID of creator */ + shmatt_t shm_nattch; /* number of current attaches */ + time_t shm_atime; /* time of last shmat() */ + long __shm_atimensec; + time_t shm_dtime; /* time of last shmdt() */ + long __shm_dtimensec; + time_t shm_ctime; /* time of last change by shmctl() */ + long __shm_ctimensec; + void *shm_internal; /* implementation specific data */ +}; + +#if __BSD_VISIBLE +/* + * System V style catch-all structure for shared memory constants that + * might be of interest to user programs. Do we really want/need this? + */ +struct shminfo { + int shmmax; /* max shared memory segment size (bytes) */ + int shmmin; /* min shared memory segment size (bytes) */ + int shmmni; /* max number of shared memory identifiers */ + int shmseg; /* max shared memory segments per process */ + int shmall; /* max amount of shared memory (pages) */ +}; + +struct shm_sysctl_info { + struct shminfo shminfo; + struct shmid_ds shmids[1]; +}; +#endif /* __BSD_VISIBLE */ + +#ifdef _KERNEL +extern struct shminfo shminfo; +extern struct shmid_ds **shmsegs; + +struct vmspace; + +void shminit(void); +void shmfork(struct vmspace *, struct vmspace *); +void shmexit(struct vmspace *); +int sysctl_sysvshm(int *, u_int, void *, size_t *, void *, size_t); + +#else /* !_KERNEL */ + +__BEGIN_DECLS +void *shmat(int, const void *, int); +int shmctl(int, int, struct shmid_ds *); +int shmdt(const void *); +int shmget(key_t, size_t, int); +__END_DECLS + +#endif /* !_KERNEL */ + +#endif /* !_SYS_SHM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/siginfo.h b/lib/libc/include/generic-openbsd/sys/siginfo.h new file mode 100644 index 000000000000..45f151144fba --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/siginfo.h @@ -0,0 +1,200 @@ +/* $OpenBSD: siginfo.h,v 1.14 2024/02/21 15:53:07 deraadt Exp $ */ + +/* + * Copyright (c) 1997 Theo de Raadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_SIGINFO_H +#define _SYS_SIGINFO_H + +#include + +union sigval { + int sival_int; /* integer value */ + void *sival_ptr; /* pointer value */ +}; + +/* + * Negative signal codes are reserved for future use for + * user generated signals. + */ +#define SI_FROMUSER(sip) ((sip)->si_code <= 0) +#define SI_FROMKERNEL(sip) ((sip)->si_code > 0) + +#define SI_NOINFO 32767 /* no signal information */ +#define SI_USER 0 /* user generated signal via kill() */ +#define SI_LWP (-1) /* user generated signal via lwp_kill()*/ +#define SI_QUEUE (-2) /* user generated signal via sigqueue()*/ +#define SI_TIMER (-3) /* from timer expiration */ + +#if __POSIX_VISIBLE >= 199309 || __XPG_VISIBLE +/* + * The machine dependent signal codes (SIGILL, SIGFPE, + * SIGSEGV, and SIGBUS) + */ +#define ILL_ILLOPC 1 /* illegal opcode */ +#define ILL_ILLOPN 2 /* illegal operand */ +#define ILL_ILLADR 3 /* illegal addressing mode */ +#define ILL_ILLTRP 4 /* illegal trap */ +#define ILL_PRVOPC 5 /* privileged opcode */ +#define ILL_PRVREG 6 /* privileged register */ +#define ILL_COPROC 7 /* co-processor */ +#define ILL_BADSTK 8 /* bad stack */ +#define ILL_BTCFI 9 /* IBT missing on indirect call */ +#define NSIGILL 9 + +#define EMT_TAGOVF 1 /* tag overflow */ +#define NSIGEMT 1 + +#define FPE_INTDIV 1 /* integer divide by zero */ +#define FPE_INTOVF 2 /* integer overflow */ +#define FPE_FLTDIV 3 /* floating point divide by zero */ +#define FPE_FLTOVF 4 /* floating point overflow */ +#define FPE_FLTUND 5 /* floating point underflow */ +#define FPE_FLTRES 6 /* floating point inexact result */ +#define FPE_FLTINV 7 /* invalid floating point operation */ +#define FPE_FLTSUB 8 /* subscript out of range */ +#define NSIGFPE 8 + +#define SEGV_MAPERR 1 /* address not mapped to object */ +#define SEGV_ACCERR 2 /* invalid permissions */ +#define NSIGSEGV 2 + +#define BUS_ADRALN 1 /* invalid address alignment */ +#define BUS_ADRERR 2 /* non-existent physical address */ +#define BUS_OBJERR 3 /* object specific hardware error */ +#define NSIGBUS 3 + +#endif /* __POSIX_VISIBLE >= 199309 || __XPG_VISIBLE */ + +/* + * SIGTRAP signal codes + */ +#define TRAP_BRKPT 1 /* breakpoint trap */ +#define TRAP_TRACE 2 /* trace trap */ +#define NSIGTRAP 2 + +/* + * SIGCHLD signal codes + */ +#define CLD_EXITED 1 /* child has exited */ +#define CLD_KILLED 2 /* child was killed */ +#define CLD_DUMPED 3 /* child has coredumped */ +#define CLD_TRAPPED 4 /* traced child has stopped */ +#define CLD_STOPPED 5 /* child has stopped on signal */ +#define CLD_CONTINUED 6 /* stopped child has continued */ +#define NSIGCLD 6 + +#if 0 +/* + * SIGPOLL signal codes - not supported + */ +#define POLL_IN 1 /* input available */ +#define POLL_OUT 2 /* output possible */ +#define POLL_MSG 3 /* message available */ +#define POLL_ERR 4 /* I/O error */ +#define POLL_PRI 5 /* high priority input available */ +#define POLL_HUP 6 /* device disconnected */ +#define NSIGPOLL 6 + +/* + * SIGPROF signal codes - not supported + */ +#define PROF_SIG 1 /* have to set code non-zero */ +#define NSIGPROF 1 +#endif + +#define SI_MAXSZ 128 +#define SI_PAD ((SI_MAXSZ / sizeof (int)) - 3) + +#include + +typedef struct { + int si_signo; /* signal from signal.h */ + int si_code; /* code from above */ + int si_errno; /* error from errno.h */ + union { + int _pad[SI_PAD]; /* for future growth */ + struct { /* kill(), SIGCHLD */ + pid_t _pid; /* process ID */ + uid_t _uid; + union { + struct { + union sigval _value; + } _kill; + struct { + clock_t _utime; + clock_t _stime; + int _status; + } _cld; + } _pdata; + } _proc; + struct { /* SIGSEGV, SIGBUS, SIGILL and SIGFPE */ + void *_addr; /* faulting address */ + int _trapno; /* illegal trap number */ + } _fault; +#if 0 + struct { /* SIGPOLL, SIGXFSZ */ + /* fd not currently available for SIGPOLL */ + int _fd; /* file descriptor */ + long _band; + } _file; + struct { /* SIGPROF */ + caddr_t _faddr; /* last fault address */ + timespec _tstamp; /* real time stamp */ + short _syscall; /* current syscall */ + char _nsysarg; /* number of arguments */ + char _fault; /* last fault type */ + long _sysarg[8]; /* syscall arguments */ + long _mstate[17]; /* exactly fills struct*/ + } _prof; +#endif + } _data; +} siginfo_t; + +#define si_pid _data._proc._pid +#define si_uid _data._proc._uid + +#define si_status _data._proc._pdata._cld._status +#define si_stime _data._proc._pdata._cld._stime +#define si_utime _data._proc._pdata._cld._utime +#define si_value _data._proc._pdata._kill._value +#define si_addr _data._fault._addr +#define si_trapno _data._fault._trapno +#define si_fd _data._file._fd +#define si_band _data._file._band + +#define si_tstamp _data._prof._tstamp +#define si_syscall _data._prof._syscall +#define si_nsysarg _data._prof._nsysarg +#define si_sysarg _data._prof._sysarg +#define si_fault _data._prof._fault +#define si_faddr _data._prof._faddr +#define si_mstate _data._prof._mstate + +#if defined(_KERNEL) +void initsiginfo(siginfo_t *, int, u_long, int, union sigval); +#endif + +#endif /* _SYS_SIGINFO_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/sigio.h b/lib/libc/include/generic-openbsd/sys/sigio.h new file mode 100644 index 000000000000..7119f971bf27 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/sigio.h @@ -0,0 +1,95 @@ +/* $OpenBSD: sigio.h,v 1.4 2020/01/08 16:27:42 visa Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)filedesc.h 8.1 (Berkeley) 6/2/93 + * $FreeBSD: head/sys/sys/sigio.h 326023 2017-11-20 19:43:44Z pfg $ + */ + +#ifndef _SYS_SIGIO_H_ +#define _SYS_SIGIO_H_ + +struct sigio; +LIST_HEAD(sigiolst, sigio); + +/* + * sigio registration + * + * Locking: + * S sigio_lock + */ +struct sigio_ref { + struct sigio *sir_sigio; /* [S] associated sigio struct */ +}; + +#ifdef _KERNEL + +/* + * This structure holds the information needed to send a SIGIO or + * a SIGURG signal to a process or process group when new data arrives + * on a device or socket. The structure is placed on an LIST belonging + * to the proc or pgrp so that the entire list may be revoked when the + * process exits or the process group disappears. + * + * Locking: + * I immutable after creation + * S sigio_lock + */ +struct sigio { + union { + struct process *siu_proc; + /* [I] process to receive + * SIGIO/SIGURG */ + struct pgrp *siu_pgrp; /* [I] process group to receive ... */ + } sio_u; + LIST_ENTRY(sigio) sio_pgsigio; /* [S] sigio's for process or group */ + struct sigio_ref *sio_myref; /* [I] location of the pointer that + * holds the reference to + * this structure */ + struct ucred *sio_ucred; /* [I] current credentials */ + pid_t sio_pgid; /* [I] pgid for signals */ +}; +#define sio_proc sio_u.siu_proc +#define sio_pgrp sio_u.siu_pgrp + +static inline void +sigio_init(struct sigio_ref *sir) +{ + sir->sir_sigio = NULL; +} + +void sigio_copy(struct sigio_ref *, struct sigio_ref *); +void sigio_free(struct sigio_ref *); +void sigio_freelist(struct sigiolst *); +void sigio_getown(struct sigio_ref *, u_long, caddr_t); +int sigio_setown(struct sigio_ref *, u_long, caddr_t); + +#endif /* _KERNEL */ + +#endif /* _SYS_SIGIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/signal.h b/lib/libc/include/generic-openbsd/sys/signal.h new file mode 100644 index 000000000000..9303ad8ac2ef --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/signal.h @@ -0,0 +1,202 @@ +/* $OpenBSD: signal.h,v 1.29 2018/04/18 16:05:20 deraadt Exp $ */ +/* $NetBSD: signal.h,v 1.21 1996/02/09 18:25:32 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)signal.h 8.2 (Berkeley) 1/21/94 + */ + +#ifndef _SYS_SIGNAL_H_ +#define _SYS_SIGNAL_H_ + +#include /* sigcontext; codes for SIGILL, SIGFPE */ + +#define _NSIG 33 /* counting 0 (mask is 1-32) */ + +#if __BSD_VISIBLE +#define NSIG _NSIG +#endif + +#define SIGHUP 1 /* hangup */ +#define SIGINT 2 /* interrupt */ +#define SIGQUIT 3 /* quit */ +#define SIGILL 4 /* illegal instruction (not reset when caught) */ +#define SIGTRAP 5 /* trace trap (not reset when caught) */ +#define SIGABRT 6 /* abort() */ +#if __BSD_VISIBLE +#define SIGIOT SIGABRT /* compatibility */ +#define SIGEMT 7 /* EMT instruction */ +#endif +#define SIGFPE 8 /* floating point exception */ +#define SIGKILL 9 /* kill (cannot be caught or ignored) */ +#define SIGBUS 10 /* bus error */ +#define SIGSEGV 11 /* segmentation violation */ +#define SIGSYS 12 /* bad argument to system call */ +#define SIGPIPE 13 /* write on a pipe with no one to read it */ +#define SIGALRM 14 /* alarm clock */ +#define SIGTERM 15 /* software termination signal from kill */ +#define SIGURG 16 /* urgent condition on IO channel */ +#define SIGSTOP 17 /* sendable stop signal not from tty */ +#define SIGTSTP 18 /* stop signal from tty */ +#define SIGCONT 19 /* continue a stopped process */ +#define SIGCHLD 20 /* to parent on child stop or exit */ +#define SIGTTIN 21 /* to readers pgrp upon background tty read */ +#define SIGTTOU 22 /* like TTIN for output if (tp->t_local<OSTOP) */ +#if __BSD_VISIBLE +#define SIGIO 23 /* input/output possible signal */ +#endif +#define SIGXCPU 24 /* exceeded CPU time limit */ +#define SIGXFSZ 25 /* exceeded file size limit */ +#define SIGVTALRM 26 /* virtual time alarm */ +#define SIGPROF 27 /* profiling time alarm */ +#if __BSD_VISIBLE +#define SIGWINCH 28 /* window size changes */ +#define SIGINFO 29 /* information request */ +#endif +#define SIGUSR1 30 /* user defined signal 1 */ +#define SIGUSR2 31 /* user defined signal 2 */ +#if __BSD_VISIBLE +#define SIGTHR 32 /* thread library AST */ +#endif + +/* + * Language spec says we must list exactly one parameter, even though we + * actually supply three. Ugh! + */ +#define SIG_DFL (void (*)(int))0 +#define SIG_IGN (void (*)(int))1 +#define SIG_ERR (void (*)(int))-1 + +#if __POSIX_VISIBLE || __XPG_VISIBLE +#ifndef _SIGSET_T_DEFINED_ +#define _SIGSET_T_DEFINED_ +typedef unsigned int sigset_t; +#endif + +#include + +/* + * Signal vector "template" used in sigaction call. + */ +struct sigaction { + union { /* signal handler */ + void (*__sa_handler)(int); + void (*__sa_sigaction)(int, siginfo_t *, void *); + } __sigaction_u; + sigset_t sa_mask; /* signal mask to apply */ + int sa_flags; /* see signal options below */ +}; + +/* if SA_SIGINFO is set, sa_sigaction is to be used instead of sa_handler. */ +#define sa_handler __sigaction_u.__sa_handler +#define sa_sigaction __sigaction_u.__sa_sigaction + +#if __XPG_VISIBLE >= 500 +#define SA_ONSTACK 0x0001 /* take signal on signal stack */ +#define SA_RESTART 0x0002 /* restart system on signal return */ +#define SA_RESETHAND 0x0004 /* reset to SIG_DFL when taking signal */ +#define SA_NODEFER 0x0010 /* don't mask the signal we're delivering */ +#define SA_NOCLDWAIT 0x0020 /* don't create zombies (assign to pid 1) */ +#endif /* __XPG_VISIBLE >= 500 */ +#define SA_NOCLDSTOP 0x0008 /* do not generate SIGCHLD on child stop */ +#if __POSIX_VISIBLE >= 199309 || __XPG_VISIBLE >= 500 +#define SA_SIGINFO 0x0040 /* generate siginfo_t */ +#endif + +/* + * Flags for sigprocmask: + */ +#define SIG_BLOCK 1 /* block specified signal set */ +#define SIG_UNBLOCK 2 /* unblock specified signal set */ +#define SIG_SETMASK 3 /* set specified signal set */ +#endif /* __POSIX_VISIBLE || __XPG_VISIBLE */ + +#if __BSD_VISIBLE +typedef void (*sig_t)(int); /* type of signal function */ + +/* + * 4.3 compatibility: + * Signal vector "template" used in sigvec call. + */ +struct sigvec { + void (*sv_handler)(int); /* signal handler */ + int sv_mask; /* signal mask to apply */ + int sv_flags; /* see signal options below */ +}; +#define SV_ONSTACK SA_ONSTACK +#define SV_INTERRUPT SA_RESTART /* same bit, opposite sense */ +#define SV_RESETHAND SA_RESETHAND +#define sv_onstack sv_flags /* isn't compatibility wonderful! */ + +/* + * Macro for converting signal number to a mask suitable for + * sigblock(). + */ +#define sigmask(m) (1U << ((m)-1)) + +#define BADSIG SIG_ERR + +#endif /* __BSD_VISIBLE */ + +#if __BSD_VISIBLE || __XPG_VISIBLE >= 420 +/* + * Structure used in sigaltstack call. + */ +typedef struct sigaltstack { + void *ss_sp; /* signal stack base */ + size_t ss_size; /* signal stack length */ + int ss_flags; /* SS_DISABLE and/or SS_ONSTACK */ +} stack_t; +#define SS_ONSTACK 0x0001 /* take signals on alternate stack */ +#define SS_DISABLE 0x0004 /* disable taking signals on alternate stack */ +#define MINSIGSTKSZ (3U << _MAX_PAGE_SHIFT) /* minimum allowable stack */ +#if _MAX_PAGE_SHIFT < 14 /* recommended stack size */ +#define SIGSTKSZ (MINSIGSTKSZ + (1U << _MAX_PAGE_SHIFT) * 4) +#else +#define SIGSTKSZ (MINSIGSTKSZ + (1U << _MAX_PAGE_SHIFT) * 2) +#endif + +typedef struct sigcontext ucontext_t; +#endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ + +#ifndef _KERNEL +/* + * For historical reasons; programs expect signal's return value to be + * defined by . + */ +__BEGIN_DECLS +void (*signal(int, void (*)(int)))(int); +__END_DECLS +#endif /* !_KERNEL */ +#endif /* !_SYS_SIGNAL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/signalvar.h b/lib/libc/include/generic-openbsd/sys/signalvar.h new file mode 100644 index 000000000000..defb09c77a29 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/signalvar.h @@ -0,0 +1,140 @@ +/* $OpenBSD: signalvar.h,v 1.58 2025/03/10 09:28:57 claudio Exp $ */ +/* $NetBSD: signalvar.h,v 1.17 1996/04/22 01:23:31 christos Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)signalvar.h 8.3 (Berkeley) 1/4/94 + */ + +#ifndef _SYS_SIGNALVAR_H_ /* tmp for user.h */ +#define _SYS_SIGNALVAR_H_ + +/* + * Kernel signal definitions and data structures, + * not exported to user programs. + */ + +/* + * Process signal actions and state, needed only within the process + * (not necessarily resident). + * + * Locks used to protect struct members in struct sigacts: + * a atomic operations + * m this process' `ps_mtx' + */ +struct sigacts { + sig_t ps_sigact[NSIG]; /* [m] disposition of signals */ + sigset_t ps_catchmask[NSIG]; /* [m] signals to be blocked */ + sigset_t ps_sigonstack; /* [m] signals to take on sigstack */ + sigset_t ps_sigintr; /* [m] signals interrupt syscalls */ + sigset_t ps_sigreset; /* [m] signals that reset when caught */ + sigset_t ps_siginfo; /* [m] signals that provide siginfo */ + sigset_t ps_sigignore; /* [m] signals being ignored */ + sigset_t ps_sigcatch; /* [m] signals being caught by user */ + int ps_sigflags; /* [a] signal flags, below */ +}; + +/* signal flags */ +#define SAS_NOCLDSTOP 0x01 /* No SIGCHLD when children stop. */ +#define SAS_NOCLDWAIT 0x02 /* No zombies if child dies */ + +/* additional signal action values, used only temporarily/internally */ +#define SIG_CATCH (void (*)(int))2 +#define SIG_HOLD (void (*)(int))3 + +/* + * Check if process p has an unmasked signal pending. + * Return mask of pending signals. + */ +#define SIGPENDING(p) \ + (((p)->p_siglist | (p)->p_p->ps_siglist) & ~(p)->p_sigmask) + +/* + * Signal properties and actions. + */ +#define SA_KILL 0x01 /* terminates process by default */ +#define SA_CORE 0x02 /* ditto and coredumps */ +#define SA_STOP 0x04 /* suspend process */ +#define SA_TTYSTOP 0x08 /* ditto, from tty */ +#define SA_IGNORE 0x10 /* ignore by default */ +#define SA_CONT 0x20 /* continue if suspended */ +#define SA_CANTMASK 0x40 /* non-maskable, catchable */ + +#define sigcantmask (sigmask(SIGKILL) | sigmask(SIGSTOP)) + +#ifdef _KERNEL +enum signal_type { SPROCESS, STHREAD }; + +struct sigio_ref; + +struct sigctx { + sig_t sig_action; + sigset_t sig_catchmask; + int sig_onstack; + int sig_intr; + int sig_reset; + int sig_info; + int sig_ignore; + int sig_catch; + int sig_stop; +}; + +/* + * Machine-independent functions: + */ +int coredump(struct proc *p); +void execsigs(struct proc *p); +int cursig(struct proc *p, struct sigctx *, int); +void pgsigio(struct sigio_ref *sir, int sig, int checkctty); +void pgsignal(struct pgrp *pgrp, int sig, int checkctty); +void psignal(struct proc *p, int sig); +void ptsignal(struct proc *p, int sig, enum signal_type type); +void prsignal(struct process *pr, int sig); +void trapsignal(struct proc *p, int sig, u_long code, int type, + union sigval val); +__dead void sigexit(struct proc *, int); +void sigabort(struct proc *); +int sigismasked(struct proc *, int); +int sigonstack(size_t); +int killpg1(struct proc *, int, int, int); + +void signal_init(void); + +void sigstkinit(struct sigaltstack *); +struct sigacts *sigactsinit(struct process *); +void sigactsfree(struct sigacts *); +void siginit(struct sigacts *); + +/* + * Machine-dependent functions: + */ +int sendsig(sig_t _catcher, int _sig, sigset_t _mask, const siginfo_t *_si, + int _info, int _onstack); +#endif /* _KERNEL */ +#endif /* !_SYS_SIGNALVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/smr.h b/lib/libc/include/generic-openbsd/sys/smr.h new file mode 100644 index 000000000000..30ac0d9f53c0 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/smr.h @@ -0,0 +1,440 @@ +/* $OpenBSD: smr.h,v 1.9 2022/07/25 08:06:44 visa Exp $ */ + +/* + * Copyright (c) 2019 Visa Hankala + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_SMR_H_ +#define _SYS_SMR_H_ + +#include + +struct smr_entry { + SIMPLEQ_ENTRY(smr_entry) smr_list; + void (*smr_func)(void *); + void *smr_arg; +}; + +SIMPLEQ_HEAD(smr_entry_list, smr_entry); + +#ifdef _KERNEL + +#include + +void smr_startup(void); +void smr_startup_thread(void); +void smr_idle(void); +void smr_read_enter(void); +void smr_read_leave(void); + +void smr_call_impl(struct smr_entry *, void (*)(void *), void *, int); +void smr_barrier_impl(int); + +#define smr_call(entry, func, arg) smr_call_impl(entry, func, arg, 0) +#define smr_barrier() smr_barrier_impl(0) +#define smr_flush() smr_barrier_impl(1) + +static inline void +smr_init(struct smr_entry *smr) +{ + smr->smr_func = NULL; + smr->smr_arg = NULL; +} + +#ifdef DIAGNOSTIC +#define SMR_ASSERT_CRITICAL() do { \ + if (panicstr == NULL && !db_active) \ + KASSERT(curcpu()->ci_schedstate.spc_smrdepth > 0); \ +} while (0) +#define SMR_ASSERT_NONCRITICAL() do { \ + if (panicstr == NULL && !db_active) \ + KASSERT(curcpu()->ci_schedstate.spc_smrdepth == 0); \ +} while (0) +#else +#define SMR_ASSERT_CRITICAL() do {} while (0) +#define SMR_ASSERT_NONCRITICAL() do {} while (0) +#endif + +#endif /* _KERNEL */ + +#define SMR_PTR_GET(pptr) READ_ONCE(*pptr) + +#define SMR_PTR_GET_LOCKED(pptr) (*(pptr)) + +#define SMR_PTR_SET_LOCKED(pptr, val) do { \ + membar_producer(); \ + WRITE_ONCE(*pptr, val); \ +} while (0) + +/* + * List implementations for use with safe memory reclamation. + */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + */ + +#include + +/* + * This file defines three types of data structures: singly-linked lists, + * lists, and tail queues. + * + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may only be traversed in the forward direction + * by lock-free readers. + */ + +/* + * Singly-linked List definitions. + */ +#define SMR_SLIST_HEAD(name, type) \ +struct name { \ + struct type *smr_slh_first; /* first element, SMR-protected */\ +} + +#define SMR_SLIST_HEAD_INITIALIZER(head) \ + { .smr_slh_first = NULL } + +#define SMR_SLIST_ENTRY(type) \ +struct { \ + struct type *smr_sle_next; /* next element, SMR-protected */\ +} + +/* + * Singly-linked List access methods. + */ +#define SMR_SLIST_END(head) NULL + +#define SMR_SLIST_FIRST(head) \ + SMR_PTR_GET(&(head)->smr_slh_first) +#define SMR_SLIST_NEXT(elm, field) \ + SMR_PTR_GET(&(elm)->field.smr_sle_next) + +#define SMR_SLIST_FIRST_LOCKED(head) \ + SMR_PTR_GET_LOCKED(&(head)->smr_slh_first) +#define SMR_SLIST_EMPTY_LOCKED(head) \ + (SMR_SLIST_FIRST_LOCKED(head) == SMR_SLIST_END(head)) +#define SMR_SLIST_NEXT_LOCKED(elm, field) \ + SMR_PTR_GET_LOCKED(&(elm)->field.smr_sle_next) + +#define SMR_SLIST_FOREACH(var, head, field) \ + for ((var) = SMR_SLIST_FIRST(head); \ + (var) != SMR_SLIST_END(head); \ + (var) = SMR_SLIST_NEXT(var, field)) + +#define SMR_SLIST_FOREACH_LOCKED(var, head, field) \ + for ((var) = SMR_SLIST_FIRST_LOCKED(head); \ + (var) != SMR_SLIST_END(head); \ + (var) = SMR_SLIST_NEXT_LOCKED(var, field)) + +#define SMR_SLIST_FOREACH_SAFE_LOCKED(var, head, field, tvar) \ + for ((var) = SMR_SLIST_FIRST_LOCKED(head); \ + (var) && ((tvar) = SMR_SLIST_NEXT_LOCKED(var, field), 1); \ + (var) = (tvar)) + +/* + * Singly-linked List functions. + */ +#define SMR_SLIST_INIT(head) do { \ + (head)->smr_slh_first = SMR_SLIST_END(head); \ +} while (0) + +#define SMR_SLIST_INSERT_AFTER_LOCKED(slistelm, elm, field) do { \ + (elm)->field.smr_sle_next = (slistelm)->field.smr_sle_next; \ + membar_producer(); \ + (slistelm)->field.smr_sle_next = (elm); \ +} while (0) + +#define SMR_SLIST_INSERT_HEAD_LOCKED(head, elm, field) do { \ + (elm)->field.smr_sle_next = (head)->smr_slh_first; \ + membar_producer(); \ + (head)->smr_slh_first = (elm); \ +} while (0) + +#define SMR_SLIST_REMOVE_AFTER_LOCKED(elm, field) do { \ + (elm)->field.smr_sle_next = \ + (elm)->field.smr_sle_next->field.smr_sle_next; \ +} while (0) + +#define SMR_SLIST_REMOVE_HEAD_LOCKED(head, field) do { \ + (head)->smr_slh_first = (head)->smr_slh_first->field.smr_sle_next;\ +} while (0) + +#define SMR_SLIST_REMOVE_LOCKED(head, elm, type, field) do { \ + if ((head)->smr_slh_first == (elm)) { \ + SMR_SLIST_REMOVE_HEAD_LOCKED((head), field); \ + } else { \ + struct type *curelm = (head)->smr_slh_first; \ + \ + while (curelm->field.smr_sle_next != (elm)) \ + curelm = curelm->field.smr_sle_next; \ + curelm->field.smr_sle_next = \ + curelm->field.smr_sle_next->field.smr_sle_next; \ + } \ + /* (elm)->field.smr_sle_next must be left intact to allow \ + * any concurrent readers to proceed iteration. */ \ +} while (0) + +/* + * List definitions. + */ +#define SMR_LIST_HEAD(name, type) \ +struct name { \ + struct type *smr_lh_first; /* first element, SMR-protected */\ +} + +#define SMR_LIST_HEAD_INITIALIZER(head) \ + { .smr_lh_first = NULL } + +#define SMR_LIST_ENTRY(type) \ +struct { \ + struct type *smr_le_next; /* next element, SMR-protected */\ + struct type **smr_le_prev; /* address of previous next element */\ +} + +/* + * List access methods. + */ +#define SMR_LIST_END(head) NULL + +#define SMR_LIST_FIRST(head) \ + SMR_PTR_GET(&(head)->smr_lh_first) +#define SMR_LIST_NEXT(elm, field) \ + SMR_PTR_GET(&(elm)->field.smr_le_next) + +#define SMR_LIST_FIRST_LOCKED(head) ((head)->smr_lh_first) +#define SMR_LIST_NEXT_LOCKED(elm, field) ((elm)->field.smr_le_next) +#define SMR_LIST_EMPTY_LOCKED(head) \ + (SMR_LIST_FIRST_LOCKED(head) == SMR_LIST_END(head)) + +#define SMR_LIST_FOREACH(var, head, field) \ + for((var) = SMR_LIST_FIRST(head); \ + (var)!= SMR_LIST_END(head); \ + (var) = SMR_LIST_NEXT(var, field)) + +#define SMR_LIST_FOREACH_LOCKED(var, head, field) \ + for((var) = SMR_LIST_FIRST_LOCKED(head); \ + (var)!= SMR_LIST_END(head); \ + (var) = SMR_LIST_NEXT_LOCKED(var, field)) + +#define SMR_LIST_FOREACH_SAFE_LOCKED(var, head, field, tvar) \ + for ((var) = SMR_LIST_FIRST_LOCKED(head); \ + (var) && ((tvar) = SMR_LIST_NEXT_LOCKED(var, field), 1); \ + (var) = (tvar)) + +/* + * List functions. + */ +#define SMR_LIST_INIT(head) do { \ + (head)->smr_lh_first = SMR_LIST_END(head); \ +} while (0) + +#define SMR_LIST_INSERT_AFTER_LOCKED(listelm, elm, field) do { \ + (elm)->field.smr_le_next = (listelm)->field.smr_le_next; \ + if ((listelm)->field.smr_le_next != NULL) \ + (listelm)->field.smr_le_next->field.smr_le_prev = \ + &(elm)->field.smr_le_next; \ + (elm)->field.smr_le_prev = &(listelm)->field.smr_le_next; \ + membar_producer(); \ + (listelm)->field.smr_le_next = (elm); \ +} while (0) + +#define SMR_LIST_INSERT_BEFORE_LOCKED(listelm, elm, field) do { \ + (elm)->field.smr_le_prev = (listelm)->field.smr_le_prev; \ + (elm)->field.smr_le_next = (listelm); \ + membar_producer(); \ + *(listelm)->field.smr_le_prev = (elm); \ + (listelm)->field.smr_le_prev = &(elm)->field.smr_le_next; \ +} while (0) + +#define SMR_LIST_INSERT_HEAD_LOCKED(head, elm, field) do { \ + (elm)->field.smr_le_next = (head)->smr_lh_first; \ + (elm)->field.smr_le_prev = &(head)->smr_lh_first; \ + if ((head)->smr_lh_first != NULL) \ + (head)->smr_lh_first->field.smr_le_prev = \ + &(elm)->field.smr_le_next; \ + membar_producer(); \ + (head)->smr_lh_first = (elm); \ +} while (0) + +#define SMR_LIST_REMOVE_LOCKED(elm, field) do { \ + if ((elm)->field.smr_le_next != NULL) \ + (elm)->field.smr_le_next->field.smr_le_prev = \ + (elm)->field.smr_le_prev; \ + *(elm)->field.smr_le_prev = (elm)->field.smr_le_next; \ + /* (elm)->field.smr_le_next must be left intact to allow \ + * any concurrent readers to proceed iteration. */ \ +} while (0) + +/* + * Tail queue definitions. + */ +#define SMR_TAILQ_HEAD(name, type) \ +struct name { \ + struct type *smr_tqh_first; /* first element, SMR-protected */\ + struct type **smr_tqh_last; /* last element */ \ +} + +#define SMR_TAILQ_HEAD_INITIALIZER(head) \ + { .smr_tqh_first = NULL, .smr_tqh_last = &(head).smr_tqh_first } + +#define SMR_TAILQ_ENTRY(type) \ +struct { \ + struct type *smr_tqe_next; /* next element, SMR-protected */\ + struct type **smr_tqe_prev; /* address of previous next element */\ +} + +/* + * Tail queue access methods. + */ +#define SMR_TAILQ_END(head) NULL + +#define SMR_TAILQ_FIRST(head) \ + SMR_PTR_GET(&(head)->smr_tqh_first) +#define SMR_TAILQ_NEXT(elm, field) \ + SMR_PTR_GET(&(elm)->field.smr_tqe_next) + +#define SMR_TAILQ_FIRST_LOCKED(head) ((head)->smr_tqh_first) +#define SMR_TAILQ_NEXT_LOCKED(elm, field) ((elm)->field.smr_tqe_next) +#define SMR_TAILQ_LAST_LOCKED(head, headname) \ + (*(((struct headname *)((head)->smr_tqh_last))->smr_tqh_last)) +#define SMR_TAILQ_EMPTY_LOCKED(head) \ + (SMR_TAILQ_FIRST_LOCKED(head) == SMR_TAILQ_END(head)) + +#define SMR_TAILQ_FOREACH(var, head, field) \ + for((var) = SMR_TAILQ_FIRST(head); \ + (var)!= SMR_TAILQ_END(head); \ + (var) = SMR_TAILQ_NEXT(var, field)) + +#define SMR_TAILQ_FOREACH_LOCKED(var, head, field) \ + for((var) = SMR_TAILQ_FIRST_LOCKED(head); \ + (var)!= SMR_TAILQ_END(head); \ + (var) = SMR_TAILQ_NEXT_LOCKED(var, field)) + +#define SMR_TAILQ_FOREACH_SAFE_LOCKED(var, head, field, tvar) \ + for ((var) = SMR_TAILQ_FIRST_LOCKED(head); \ + (var) && ((tvar) = SMR_TAILQ_NEXT_LOCKED(var, field), 1); \ + (var) = (tvar)) + +/* + * Tail queue functions. + */ +#define SMR_TAILQ_INIT(head) do { \ + (head)->smr_tqh_first = SMR_TAILQ_END(head); \ + (head)->smr_tqh_last = &(head)->smr_tqh_first; \ +} while (0) + +#define SMR_TAILQ_INSERT_AFTER_LOCKED(head, listelm, elm, field) do { \ + (elm)->field.smr_tqe_next = (listelm)->field.smr_tqe_next; \ + if ((listelm)->field.smr_tqe_next != NULL) \ + (listelm)->field.smr_tqe_next->field.smr_tqe_prev = \ + &(elm)->field.smr_tqe_next; \ + else \ + (head)->smr_tqh_last = &(elm)->field.smr_tqe_next; \ + (elm)->field.smr_tqe_prev = &(listelm)->field.smr_tqe_next; \ + membar_producer(); \ + (listelm)->field.smr_tqe_next = (elm); \ +} while (0) + +#define SMR_TAILQ_INSERT_BEFORE_LOCKED(listelm, elm, field) do { \ + (elm)->field.smr_tqe_prev = (listelm)->field.smr_tqe_prev; \ + (elm)->field.smr_tqe_next = (listelm); \ + membar_producer(); \ + *(listelm)->field.smr_tqe_prev = (elm); \ + (listelm)->field.smr_tqe_prev = &(elm)->field.smr_tqe_next; \ +} while (0) + +#define SMR_TAILQ_INSERT_HEAD_LOCKED(head, elm, field) do { \ + (elm)->field.smr_tqe_next = (head)->smr_tqh_first; \ + (elm)->field.smr_tqe_prev = &(head)->smr_tqh_first; \ + if ((head)->smr_tqh_first != NULL) \ + (head)->smr_tqh_first->field.smr_tqe_prev = \ + &(elm)->field.smr_tqe_next; \ + else \ + (head)->smr_tqh_last = &(elm)->field.smr_tqe_next; \ + membar_producer(); \ + (head)->smr_tqh_first = (elm); \ +} while (0) + +#define SMR_TAILQ_INSERT_TAIL_LOCKED(head, elm, field) do { \ + (elm)->field.smr_tqe_next = NULL; \ + (elm)->field.smr_tqe_prev = (head)->smr_tqh_last; \ + membar_producer(); \ + *(head)->smr_tqh_last = (elm); \ + (head)->smr_tqh_last = &(elm)->field.smr_tqe_next; \ +} while (0) + +#define SMR_TAILQ_REMOVE_LOCKED(head, elm, field) do { \ + if ((elm)->field.smr_tqe_next != NULL) \ + (elm)->field.smr_tqe_next->field.smr_tqe_prev = \ + (elm)->field.smr_tqe_prev; \ + else \ + (head)->smr_tqh_last = (elm)->field.smr_tqe_prev; \ + *(elm)->field.smr_tqe_prev = (elm)->field.smr_tqe_next; \ + /* (elm)->field.smr_tqe_next must be left intact to allow \ + * any concurrent readers to proceed iteration. */ \ +} while (0) + +#endif /* !_SYS_SMR_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/socket.h b/lib/libc/include/generic-openbsd/sys/socket.h new file mode 100644 index 000000000000..537c0d92867e --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/socket.h @@ -0,0 +1,617 @@ +/* $OpenBSD: socket.h,v 1.108 2025/08/04 04:59:30 guenther Exp $ */ +/* $NetBSD: socket.h,v 1.14 1996/02/09 18:25:36 christos Exp $ */ + +/* + * Copyright (c) 1982, 1985, 1986, 1988, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)socket.h 8.4 (Berkeley) 2/21/94 + */ + +#ifndef _SYS_SOCKET_H_ +#define _SYS_SOCKET_H_ + +/* get the definitions for struct iovec, size_t, ssize_t, and */ +#include + +#if __BSD_VISIBLE +#include /* for off_t, uid_t, and gid_t */ +#endif + +#ifndef _SOCKLEN_T_DEFINED_ +#define _SOCKLEN_T_DEFINED_ +typedef __socklen_t socklen_t; /* length type for network syscalls */ +#endif + +#ifndef _SA_FAMILY_T_DEFINED_ +#define _SA_FAMILY_T_DEFINED_ +typedef __sa_family_t sa_family_t; /* sockaddr address family type */ +#endif + + +/* + * Definitions related to sockets: types, address families, options. + */ + +/* + * Types + */ +#define SOCK_STREAM 1 /* stream socket */ +#define SOCK_DGRAM 2 /* datagram socket */ +#define SOCK_RAW 3 /* raw-protocol interface */ +#define SOCK_RDM 4 /* reliably-delivered message */ +#define SOCK_SEQPACKET 5 /* sequenced packet stream */ +#ifdef _KERNEL +#define SOCK_TYPE_MASK 0x000F /* mask that covers the above */ +#endif + +/* + * Socket creation flags + */ +#if __POSIX_VISIBLE >= 202405 || __BSD_VISIBLE +#define SOCK_CLOEXEC 0x8000 /* set FD_CLOEXEC */ +#define SOCK_NONBLOCK 0x4000 /* set O_NONBLOCK */ +#endif +#if __BSD_VISIBLE +#ifdef _KERNEL +#define SOCK_NONBLOCK_INHERIT 0x2000 /* inherit O_NONBLOCK from listener */ +#endif +#define SOCK_DNS 0x1000 /* set SS_DNS */ +#endif /* __BSD_VISIBLE */ +#if __POSIX_VISIBLE >= 202405 +#define SOCK_CLOFORK 0x0800 /* set FD_CLOFORK */ +#endif + +/* + * Option flags per-socket. + */ +#define SO_DEBUG 0x0001 /* turn on debugging info recording */ +#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ +#define SO_REUSEADDR 0x0004 /* allow local address reuse */ +#define SO_KEEPALIVE 0x0008 /* keep connections alive */ +#define SO_DONTROUTE 0x0010 /* just use interface addresses */ +#define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */ +#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */ +#define SO_LINGER 0x0080 /* linger on close if data present */ +#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */ +#define SO_REUSEPORT 0x0200 /* allow local address & port reuse */ +#define SO_TIMESTAMP 0x0800 /* timestamp received dgram traffic */ +#define SO_BINDANY 0x1000 /* allow bind to any address */ +#define SO_ZEROIZE 0x2000 /* zero out all mbufs sent over socket */ + +/* + * Additional options, not kept in so_options. + */ +#define SO_SNDBUF 0x1001 /* send buffer size */ +#define SO_RCVBUF 0x1002 /* receive buffer size */ +#define SO_SNDLOWAT 0x1003 /* send low-water mark */ +#define SO_RCVLOWAT 0x1004 /* receive low-water mark */ +#define SO_SNDTIMEO 0x1005 /* send timeout */ +#define SO_RCVTIMEO 0x1006 /* receive timeout */ +#define SO_ERROR 0x1007 /* get error status and clear */ +#define SO_TYPE 0x1008 /* get socket type */ +#define SO_RTABLE 0x1021 /* routing table to be used */ +#define SO_PEERCRED 0x1022 /* get connect-time credentials */ +#define SO_SPLICE 0x1023 /* splice data to other socket */ +#define SO_DOMAIN 0x1024 /* get socket domain */ +#define SO_PROTOCOL 0x1025 /* get socket protocol */ + +/* + * Structure used for manipulating linger option. + */ +struct linger { + int l_onoff; /* option on/off */ + int l_linger; /* linger time */ +}; + +#if __BSD_VISIBLE + +#ifndef _TIMEVAL_DECLARED +#define _TIMEVAL_DECLARED +struct timeval { + time_t tv_sec; /* seconds */ + suseconds_t tv_usec; /* and microseconds */ +}; +#endif + +/* + * Structure used for manipulating splice option. + */ +struct splice { + int sp_fd; /* drain socket file descriptor */ + off_t sp_max; /* if set, maximum bytes to splice */ + struct timeval sp_idle; /* idle timeout */ +}; + +/* + * Maximum number of alternate routing tables + */ +#define RT_TABLEID_MAX 255 +#define RT_TABLEID_BITS 8 +#define RT_TABLEID_MASK 0xff + +#endif /* __BSD_VISIBLE */ + +/* + * Level number for (get/set)sockopt() to apply to socket itself. + */ +#define SOL_SOCKET 0xffff /* options for socket level */ + +/* + * Address families. + */ +#define AF_UNSPEC 0 /* unspecified */ +#define AF_UNIX 1 /* local to host */ +#define AF_LOCAL AF_UNIX /* draft POSIX compatibility */ +#define AF_INET 2 /* internetwork: UDP, TCP, etc. */ +#define AF_IMPLINK 3 /* arpanet imp addresses */ +#define AF_PUP 4 /* pup protocols: e.g. BSP */ +#define AF_CHAOS 5 /* mit CHAOS protocols */ +#define AF_NS 6 /* XEROX NS protocols */ +#define AF_ISO 7 /* ISO protocols */ +#define AF_OSI AF_ISO +#define AF_ECMA 8 /* european computer manufacturers */ +#define AF_DATAKIT 9 /* datakit protocols */ +#define AF_CCITT 10 /* CCITT protocols, X.25 etc */ +#define AF_SNA 11 /* IBM SNA */ +#define AF_DECnet 12 /* DECnet */ +#define AF_DLI 13 /* DEC Direct data link interface */ +#define AF_LAT 14 /* LAT */ +#define AF_HYLINK 15 /* NSC Hyperchannel */ +#define AF_APPLETALK 16 /* Apple Talk */ +#define AF_ROUTE 17 /* Internal Routing Protocol */ +#define AF_LINK 18 /* Link layer interface */ +#define pseudo_AF_XTP 19 /* eXpress Transfer Protocol (no AF) */ +#define AF_COIP 20 /* connection-oriented IP, aka ST II */ +#define AF_CNT 21 /* Computer Network Technology */ +#define pseudo_AF_RTIP 22 /* Help Identify RTIP packets */ +#define AF_IPX 23 /* Novell Internet Protocol */ +#define AF_INET6 24 /* IPv6 */ +#define pseudo_AF_PIP 25 /* Help Identify PIP packets */ +#define AF_ISDN 26 /* Integrated Services Digital Network*/ +#define AF_E164 AF_ISDN /* CCITT E.164 recommendation */ +#define AF_NATM 27 /* native ATM access */ +#define AF_ENCAP 28 +#define AF_SIP 29 /* Simple Internet Protocol */ +#define AF_KEY 30 +#define pseudo_AF_HDRCMPLT 31 /* Used by BPF to not rewrite headers + in interface output routine */ +#define AF_BLUETOOTH 32 /* Bluetooth */ +#define AF_MPLS 33 /* MPLS */ +#define pseudo_AF_PFLOW 34 /* pflow */ +#define pseudo_AF_PIPEX 35 /* PIPEX */ +#define AF_FRAME 36 /* frame (Ethernet) sockets */ +#define AF_MAX 37 + +/* + * Structure used by kernel to store most + * addresses. + */ +struct sockaddr { + __uint8_t sa_len; /* total length */ + sa_family_t sa_family; /* address family */ + char sa_data[14]; /* actually longer; address value */ +}; + +/* + * Sockaddr type which can hold any sockaddr type available + * in the system. + * + * Note: __ss_{len,family} is defined in RFC2553. During RFC2553 discussion + * the field name went back and forth between ss_len and __ss_len, + * and RFC2553 specifies it to be __ss_len. openbsd picked ss_len. + * For maximum portability, userland programmer would need to + * (1) make the code never touch ss_len portion (cast it into sockaddr and + * touch sa_len), or (2) add "-Dss_len=__ss_len" into CFLAGS to unify all + * occurrences (including header file) to __ss_len. + */ +struct sockaddr_storage { + __uint8_t ss_len; /* total length */ + sa_family_t ss_family; /* address family */ + unsigned char __ss_pad1[6]; /* align to quad */ + __uint64_t __ss_pad2; /* force alignment for stupid compilers */ + unsigned char __ss_pad3[240]; /* pad to a total of 256 bytes */ +}; + +#ifdef _KERNEL +/* + * Structure used by kernel to pass protocol + * information in raw sockets. + */ +struct sockproto { + unsigned short sp_family; /* address family */ + unsigned short sp_protocol; /* protocol */ +}; +#endif /* _KERNEL */ + +/* + * Protocol families, same as address families for now. + */ +#define PF_UNSPEC AF_UNSPEC +#define PF_LOCAL AF_LOCAL +#define PF_UNIX AF_UNIX +#define PF_INET AF_INET +#define PF_IMPLINK AF_IMPLINK +#define PF_PUP AF_PUP +#define PF_CHAOS AF_CHAOS +#define PF_NS AF_NS +#define PF_ISO AF_ISO +#define PF_OSI AF_ISO +#define PF_ECMA AF_ECMA +#define PF_DATAKIT AF_DATAKIT +#define PF_CCITT AF_CCITT +#define PF_SNA AF_SNA +#define PF_DECnet AF_DECnet +#define PF_DLI AF_DLI +#define PF_LAT AF_LAT +#define PF_HYLINK AF_HYLINK +#define PF_APPLETALK AF_APPLETALK +#define PF_ROUTE AF_ROUTE +#define PF_LINK AF_LINK +#define PF_XTP pseudo_AF_XTP /* really just proto family, no AF */ +#define PF_COIP AF_COIP +#define PF_CNT AF_CNT +#define PF_IPX AF_IPX /* same format as AF_NS */ +#define PF_INET6 AF_INET6 +#define PF_RTIP pseudo_AF_RTIP /* same format as AF_INET */ +#define PF_PIP pseudo_AF_PIP +#define PF_ISDN AF_ISDN +#define PF_NATM AF_NATM +#define PF_ENCAP AF_ENCAP +#define PF_SIP AF_SIP +#define PF_KEY AF_KEY +#define PF_BPF pseudo_AF_HDRCMPLT +#define PF_BLUETOOTH AF_BLUETOOTH +#define PF_MPLS AF_MPLS +#define PF_PFLOW pseudo_AF_PFLOW +#define PF_PIPEX pseudo_AF_PIPEX +#define PF_FRAME AF_FRAME +#define PF_MAX AF_MAX + +/* + * These are the valid values for the "how" field used by shutdown(2). + */ +#define SHUT_RD 0 +#define SHUT_WR 1 +#define SHUT_RDWR 2 + +#if __BSD_VISIBLE +#define SA_LEN(x) ((x)->sa_len) + +/* Read using getsockopt() with SOL_SOCKET, SO_PEERCRED */ +struct sockpeercred { + uid_t uid; /* effective user id */ + gid_t gid; /* effective group id */ + pid_t pid; +}; + +/* + * Definitions for network related sysctl, CTL_NET. + * + * Second level is protocol family. + * Third level is protocol number. + * + * Further levels are defined by the individual families below. + */ +#define NET_MAXID AF_MAX + +#define CTL_NET_NAMES { \ + { 0, 0 }, \ + { "unix", CTLTYPE_NODE }, \ + { "inet", CTLTYPE_NODE }, \ + { "implink", CTLTYPE_NODE }, \ + { "pup", CTLTYPE_NODE }, \ + { "chaos", CTLTYPE_NODE }, \ + { "xerox_ns", CTLTYPE_NODE }, \ + { "iso", CTLTYPE_NODE }, \ + { "ecma", CTLTYPE_NODE }, \ + { "datakit", CTLTYPE_NODE }, \ + { "ccitt", CTLTYPE_NODE }, \ + { "ibm_sna", CTLTYPE_NODE }, \ + { "decnet", CTLTYPE_NODE }, \ + { "dec_dli", CTLTYPE_NODE }, \ + { "lat", CTLTYPE_NODE }, \ + { "hylink", CTLTYPE_NODE }, \ + { "appletalk", CTLTYPE_NODE }, \ + { "route", CTLTYPE_NODE }, \ + { "link", CTLTYPE_NODE }, \ + { "xtp", CTLTYPE_NODE }, \ + { "coip", CTLTYPE_NODE }, \ + { "cnt", CTLTYPE_NODE }, \ + { "rtip", CTLTYPE_NODE }, \ + { "ipx", CTLTYPE_NODE }, \ + { "inet6", CTLTYPE_NODE }, \ + { "pip", CTLTYPE_NODE }, \ + { "isdn", CTLTYPE_NODE }, \ + { "natm", CTLTYPE_NODE }, \ + { "encap", CTLTYPE_NODE }, \ + { "sip", CTLTYPE_NODE }, \ + { "key", CTLTYPE_NODE }, \ + { "bpf", CTLTYPE_NODE }, \ + { "bluetooth", CTLTYPE_NODE }, \ + { "mpls", CTLTYPE_NODE }, \ + { "pflow", CTLTYPE_NODE }, \ + { "pipex", CTLTYPE_NODE }, \ +} + +/* + * PF_ROUTE - Routing table + * + * Four additional levels are defined: + * Fourth: address family, 0 is wildcard + * Fifth: type of info, defined below + * Sixth: flag(s) to mask with for NET_RT_FLAGS + * Seventh: routing table to use (facultative, defaults to 0) + * NET_RT_TABLE has the table id as sixth element. + */ +#define NET_RT_DUMP 1 /* dump; may limit to a.f. */ +#define NET_RT_FLAGS 2 /* by flags, e.g. RESOLVING */ +#define NET_RT_IFLIST 3 /* survey interface list */ +#define NET_RT_STATS 4 /* routing table statistics */ +#define NET_RT_TABLE 5 +#define NET_RT_IFNAMES 6 +#define NET_RT_SOURCE 7 +#define NET_RT_MAXID 8 + +#define CTL_NET_RT_NAMES { \ + { 0, 0 }, \ + { "dump", CTLTYPE_STRUCT }, \ + { "flags", CTLTYPE_STRUCT }, \ + { "iflist", CTLTYPE_STRUCT }, \ + { "stats", CTLTYPE_STRUCT }, \ + { "table", CTLTYPE_STRUCT }, \ + { "ifnames", CTLTYPE_STRUCT }, \ + { "source", CTLTYPE_STRUCT }, \ +} + +/* + * PF_UNIX - unix socket tunables + */ +#define NET_UNIX_INFLIGHT 6 +#define NET_UNIX_DEFERRED 7 +#define NET_UNIX_MAXID 8 + +#define CTL_NET_UNIX_NAMES { \ + { 0, 0 }, \ + { "stream", CTLTYPE_NODE }, \ + { "dgram", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "seqpacket", CTLTYPE_NODE }, \ + { "inflight", CTLTYPE_INT }, \ + { "deferred", CTLTYPE_INT }, \ +} + +#define UNPCTL_RECVSPACE 1 +#define UNPCTL_SENDSPACE 2 +#define NET_UNIX_PROTO_MAXID 3 + +#define CTL_NET_UNIX_PROTO_NAMES { \ + { 0, 0 }, \ + { "recvspace", CTLTYPE_INT }, \ + { "sendspace", CTLTYPE_INT }, \ +} + +/* + * PF_LINK - link layer or device tunables + */ +#define NET_LINK_IFRXQ 1 /* net.link.ifrxq */ +#define NET_LINK_MAXID 2 + +#define CTL_NET_LINK_NAMES { \ + { 0, 0 }, \ + { "ifrxq", CTLTYPE_NODE }, \ +} + +#define NET_LINK_IFRXQ_PRESSURE_RETURN \ + 1 /* net.link.ifrxq.pressure_return */ +#define NET_LINK_IFRXQ_PRESSURE_DROP \ + 2 /* net.link.ifrxq.pressure_drop */ +#define NET_LINK_IFRXQ_MAXID 3 + +#define CTL_NET_LINK_IFRXQ_NAMES { \ + { 0, 0 }, \ + { "pressure_return", CTLTYPE_INT }, \ + { "pressure_drop", CTLTYPE_INT }, \ +} + +/* + * PF_KEY - Key Management + */ +#define NET_KEY_SADB_DUMP 1 /* return SADB */ +#define NET_KEY_SPD_DUMP 2 /* return SPD */ +#define NET_KEY_MAXID 3 + +#define CTL_NET_KEY_NAMES { \ + { 0, 0 }, \ + { "sadb_dump", CTLTYPE_STRUCT }, \ + { "spd_dump", CTLTYPE_STRUCT }, \ +} + +/* + * PF_BPF not really a family, but connected under CTL_NET + */ +#define NET_BPF_BUFSIZE 1 /* default buffer size */ +#define NET_BPF_MAXBUFSIZE 2 /* maximum buffer size */ +#define NET_BPF_MAXID 3 + +#define CTL_NET_BPF_NAMES { \ + { 0, 0 }, \ + { "bufsize", CTLTYPE_INT }, \ + { "maxbufsize", CTLTYPE_INT }, \ +} + +/* + * PF_PFLOW not really a family, but connected under CTL_NET + */ +#define NET_PFLOW_STATS 1 /* statistics */ +#define NET_PFLOW_MAXID 2 + +#define CTL_NET_PFLOW_NAMES { \ + { 0, 0 }, \ + { "stats", CTLTYPE_STRUCT }, \ +} +#endif /* __BSD_VISIBLE */ + +/* + * Maximum queue length specifiable by listen(2). + */ +#define SOMAXCONN 128 + +/* + * Message header for recvmsg and sendmsg calls. + * Used value-result for recvmsg, value only for sendmsg. + */ +struct msghdr { + void *msg_name; /* optional address */ + socklen_t msg_namelen; /* size of address */ + struct iovec *msg_iov; /* scatter/gather array */ + unsigned int msg_iovlen; /* # elements in msg_iov */ + void *msg_control; /* ancillary data, see below */ + socklen_t msg_controllen; /* ancillary data buffer len */ + int msg_flags; /* flags on received message */ +}; + +struct mmsghdr { + struct msghdr msg_hdr; + unsigned int msg_len; +}; + +struct timespec; + +#define MSG_OOB 0x1 /* process out-of-band data */ +#define MSG_PEEK 0x2 /* peek at incoming message */ +#define MSG_DONTROUTE 0x4 /* send without using routing tables */ +#define MSG_EOR 0x8 /* data completes record */ +#define MSG_TRUNC 0x10 /* data discarded before delivery */ +#define MSG_CTRUNC 0x20 /* control data lost before delivery */ +#define MSG_WAITALL 0x40 /* wait for full request or error */ +#define MSG_DONTWAIT 0x80 /* this message should be nonblocking */ +#define MSG_BCAST 0x100 /* this message rec'd as broadcast */ +#define MSG_MCAST 0x200 /* this message rec'd as multicast */ +#define MSG_NOSIGNAL 0x400 /* do not send SIGPIPE */ +#define MSG_CMSG_CLOEXEC 0x800 /* set FD_CLOEXEC on received fds */ +#define MSG_WAITFORONE 0x1000 /* nonblocking but wait for one msg */ +#define MSG_CMSG_CLOFORK 0x2000 /* set FD_CLOFORK on received fds */ + +/* + * Header for ancillary data objects in msg_control buffer. + * Used for additional information with/about a datagram + * not expressible by flags. The format is a sequence + * of message elements headed by cmsghdr structures. + */ +struct cmsghdr { + socklen_t cmsg_len; /* data byte count, including hdr */ + int cmsg_level; /* originating protocol */ + int cmsg_type; /* protocol-specific type */ +/* followed by u_char cmsg_data[]; */ +}; + +/* given pointer to struct cmsghdr, return pointer to data */ +#define CMSG_DATA(cmsg) \ + ((unsigned char *)(cmsg) + _ALIGN(sizeof(struct cmsghdr))) + +/* given pointer to struct cmsghdr, return pointer to next cmsghdr */ +#define CMSG_NXTHDR(mhdr, cmsg) \ + (((char *)(cmsg) + _ALIGN((cmsg)->cmsg_len) + \ + _ALIGN(sizeof(struct cmsghdr)) > \ + ((char *)(mhdr)->msg_control) + (mhdr)->msg_controllen) ? \ + (struct cmsghdr *)NULL : \ + (struct cmsghdr *)((char *)(cmsg) + _ALIGN((cmsg)->cmsg_len))) + +/* + * RFC 2292 requires to check msg_controllen, in case that the kernel returns + * an empty list for some reasons. + */ +#define CMSG_FIRSTHDR(mhdr) \ + ((mhdr)->msg_controllen >= sizeof(struct cmsghdr) ? \ + (struct cmsghdr *)(mhdr)->msg_control : \ + (struct cmsghdr *)NULL) + +/* Round len up to next alignment boundary */ +#ifdef _KERNEL +#define CMSG_ALIGN(n) _ALIGN(n) +#endif + +/* Length of the contents of a control message of length len */ +#define CMSG_LEN(len) (_ALIGN(sizeof(struct cmsghdr)) + (len)) + +/* Length of the space taken up by a padded control message of length len */ +#define CMSG_SPACE(len) (_ALIGN(sizeof(struct cmsghdr)) + _ALIGN(len)) + +/* "Socket"-level control message types: */ +#define SCM_RIGHTS 0x01 /* access rights (array of int) */ +#define SCM_TIMESTAMP 0x04 /* timestamp (struct timeval) */ + +#ifndef _KERNEL + +__BEGIN_DECLS +int accept(int, struct sockaddr *, socklen_t *); +int bind(int, const struct sockaddr *, socklen_t); +int connect(int, const struct sockaddr *, socklen_t); +int getpeername(int, struct sockaddr *, socklen_t *); +int getsockname(int, struct sockaddr *, socklen_t *); +int getsockopt(int, int, int, void *, socklen_t *); +int listen(int, int); +ssize_t recv(int, void *, size_t, int); +ssize_t recvfrom(int, void *, size_t, int, struct sockaddr *, socklen_t *); +ssize_t recvmsg(int, struct msghdr *, int); +int recvmmsg(int, struct mmsghdr *, unsigned int, int, struct timespec *); +ssize_t send(int, const void *, size_t, int); +ssize_t sendto(int, const void *, + size_t, int, const struct sockaddr *, socklen_t); +ssize_t sendmsg(int, const struct msghdr *, int); +int sendmmsg(int, struct mmsghdr *, unsigned int, int); +int setsockopt(int, int, int, const void *, socklen_t); +int shutdown(int, int); +int sockatmark(int); +int socket(int, int, int); +int socketpair(int, int, int, int *); + +#if __POSIX_VISIBLE >= 202405 || __BSD_VISIBLE +int accept4(int, struct sockaddr *__restrict, socklen_t *__restrict, int); +#endif + +#if __BSD_VISIBLE +int getpeereid(int, uid_t *, gid_t *); +int getrtable(void); +int setrtable(int); +#endif /* __BSD_VISIBLE */ + +__END_DECLS + +#else + +static inline struct sockaddr * +sstosa(struct sockaddr_storage *ss) +{ + return ((struct sockaddr *)(ss)); +} + +#endif /* !_KERNEL */ + +#endif /* !_SYS_SOCKET_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/socketvar.h b/lib/libc/include/generic-openbsd/sys/socketvar.h new file mode 100644 index 000000000000..e64f148b1817 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/socketvar.h @@ -0,0 +1,443 @@ +/* $OpenBSD: socketvar.h,v 1.159 2025/07/25 08:58:44 mvs Exp $ */ +/* $NetBSD: socketvar.h,v 1.18 1996/02/09 18:25:38 christos Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)socketvar.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _SYS_SOCKETVAR_H_ +#define _SYS_SOCKETVAR_H_ + +#include +#include +#include /* for struct sigio_ref */ +#include +#include +#include +#include +#include + +#ifndef _SOCKLEN_T_DEFINED_ +#define _SOCKLEN_T_DEFINED_ +typedef __socklen_t socklen_t; /* length type for network syscalls */ +#endif + +TAILQ_HEAD(soqhead, socket); + +/* + * Locks used to protect global data and struct members: + * I immutable after creation + * a atomic + * mr sb_mxt of so_rcv buffer + * ms sb_mtx of so_snd buffer + * m sb_mtx + * br sblock() of so_rcv buffer + * bs sblock() od so_snd buffer + * s solock() + */ + +/* + * Variables for socket splicing, allocated only when needed. + */ +struct sosplice { + struct socket *ssp_socket; /* [mr ms] send data to drain socket */ + struct socket *ssp_soback; /* [ms ms] back ref to source socket */ + off_t ssp_len; /* [mr] number of bytes spliced */ + off_t ssp_max; /* [I] maximum number of bytes */ + struct timeval ssp_idletv; /* [I] idle timeout */ + struct timeout ssp_idleto; + struct task ssp_task; /* task for somove */ +}; + +/* + * Variables for socket buffering. + */ +struct sockbuf { + struct rwlock sb_lock; + struct mutex sb_mtx; +/* The following fields are all zeroed on flush. */ +#define sb_startzero sb_cc + u_long sb_cc; /* [m] actual chars in buffer */ + u_long sb_datacc; /* [m] data only chars in buffer */ + u_long sb_hiwat; /* [m] max actual char count */ + u_long sb_wat; /* [m] default watermark */ + u_long sb_mbcnt; /* [m] chars of mbufs used */ + u_long sb_mbmax; /* [m] max chars of mbufs to use */ + long sb_lowat; /* [m] low water mark */ + struct mbuf *sb_mb; /* [m] the mbuf chain */ + struct mbuf *sb_mbtail; /* [m] the last mbuf in the chain */ + struct mbuf *sb_lastrecord; /* [m] first mbuf of last record in + socket buffer */ + short sb_flags; /* [m] flags, see below */ +/* End area that is zeroed on flush. */ +#define sb_endzero sb_flags + short sb_state; /* [m] socket state on sockbuf */ + uint64_t sb_timeo_nsecs; /* [m] timeout for read/write */ + struct klist sb_klist; /* [m] list of knotes */ +}; + +#define SB_MAX (2*1024*1024) /* default for max chars in sockbuf */ +#define SB_WAIT 0x0001 /* someone is waiting for data/space */ +#define SB_ASYNC 0x0002 /* ASYNC I/O, need signals */ +#define SB_SPLICE 0x0004 /* buffer is splice source or drain */ +#define SB_NOINTR 0x0008 /* operations not interruptible */ + +/* + * Kernel structure per socket. + * Contains send and receive buffer queues, + * handle on protocol and pointer to protocol + * private data and error information. + */ +struct socket { + const struct protosw *so_proto; /* [I] protocol handle */ + struct rwlock so_lock; /* this socket lock */ + struct refcnt so_refcnt; /* references to this socket */ + void *so_pcb; /* [s] protocol control block */ + u_int so_state; /* [s] internal state flags SS_*, + see below */ + short so_type; /* [I] generic type, see socket.h */ + short so_options; /* [s] from socket call, see + socket.h */ + short so_linger; /* [s] time to linger while closing */ +/* + * Variables for connection queueing. + * Socket where accepts occur is so_head in all subsidiary sockets. + * If so_head is 0, socket is not related to an accept. + * For head socket so_q0 queues partially completed connections, + * while so_q is a queue of connections ready to be accepted. + * If a connection is aborted and it has so_head set, then + * it has to be pulled out of either so_q0 or so_q. + * We allow connections to queue up based on current queue lengths + * and limit on number of queued connections for this socket. + * + * Connections queue relies on both socket locks of listening and + * unaccepted sockets. Socket lock of listening socket should be + * always taken first. + */ + struct socket *so_head; /* [s] back pointer to accept socket */ + struct soqhead *so_onq; /* [s] queue (q or q0) that we're on */ + struct soqhead so_q0; /* [s] queue of partial connections */ + struct soqhead so_q; /* [s] queue of incoming connections */ + struct sigio_ref so_sigio; /* async I/O registration */ + TAILQ_ENTRY(socket) so_qe; /* [s] our queue entry (q or q0) */ + short so_q0len; /* [s] partials on so_q0 */ + short so_qlen; /* [s] number of connections on so_q */ + short so_qlimit; /* [s] max number queued connections */ + short so_timeo; /* [s] connection timeout */ + u_long so_oobmark; /* [mr] chars to oob mark */ + u_int so_error; /* [a] error affecting connection */ + + struct sosplice *so_sp; /* [s br] */ + + struct sockbuf so_rcv; + struct sockbuf so_snd; + + void (*so_upcall)(struct socket *, caddr_t, int); /* [s] */ + caddr_t so_upcallarg; /* [s] Arg for above */ + uid_t so_euid; /* [I] who opened the socket */ + uid_t so_ruid; /* [I] */ + gid_t so_egid; /* [I] */ + gid_t so_rgid; /* [I] */ + pid_t so_cpid; /* [I] pid of process that opened + socket */ +}; + +/* + * Socket state bits. + * + * NOTE: The following states should be used with corresponding socket's + * buffer `sb_state' only: + * + * SS_CANTSENDMORE with `so_snd' + * SS_ISSENDING with `so_snd' + * SS_CANTRCVMORE with `so_rcv' + * SS_RCVATMARK with `so_rcv' + */ + +#define SS_NOFDREF 0x001 /* no file table ref any more */ +#define SS_ISCONNECTED 0x002 /* socket connected to a peer */ +#define SS_ISCONNECTING 0x004 /* in process of connecting to peer */ +#define SS_ISDISCONNECTING 0x008 /* in process of disconnecting */ +#define SS_CANTSENDMORE 0x010 /* can't send more data to peer */ +#define SS_CANTRCVMORE 0x020 /* can't receive more data from peer */ +#define SS_RCVATMARK 0x040 /* at mark on input */ +#define SS_ISDISCONNECTED 0x800 /* socket disconnected from peer */ + +#define SS_PRIV 0x080 /* privileged for broadcast, raw... */ +#define SS_CONNECTOUT 0x1000 /* connect, not accept, at this end */ +#define SS_ISSENDING 0x2000 /* hint for lower layer */ +#define SS_DNS 0x4000 /* created using SOCK_DNS socket(2) */ +#define SS_YP 0x8000 /* created using ypconnect(2) */ + +#ifdef _KERNEL + +#include +#include + +struct mbuf; +struct sockaddr; +struct proc; +struct msghdr; +struct stat; +struct knote; + +void soassertlocked(struct socket *); +void soassertlocked_readonly(struct socket *); +void sbmtxassertlocked(struct sockbuf *); + +int soo_read(struct file *, struct uio *, int); +int soo_write(struct file *, struct uio *, int); +int soo_ioctl(struct file *, u_long, caddr_t, struct proc *); +int soo_kqfilter(struct file *, struct knote *); +int soo_close(struct file *, struct proc *); +int soo_stat(struct file *, struct stat *, struct proc *); +void sbappend(struct sockbuf *, struct mbuf *); +void sbappendstream(struct sockbuf *, struct mbuf *); +int sbappendaddr(struct sockbuf *, const struct sockaddr *, struct mbuf *, + struct mbuf *); +int sbappendcontrol(struct sockbuf *, struct mbuf *, struct mbuf *); +void sbappendrecord(struct sockbuf *, struct mbuf *); +void sbcompress(struct sockbuf *, struct mbuf *, struct mbuf *); +struct mbuf * + sbcreatecontrol(const void *, size_t, int, int); +void sbdrop(struct sockbuf *, int); +void sbdroprecord(struct sockbuf *); +void sbflush(struct sockbuf *); +void sbrelease(struct sockbuf *); +int sbcheckreserve(u_long, u_long); +int sbchecklowmem(void); +int sbreserve(struct sockbuf *, u_long); +int sbwait(struct sockbuf *); +void soinit(void); +void soabort(struct socket *); +int soaccept(struct socket *, struct mbuf *); +int sobind(struct socket *, struct mbuf *, struct proc *); +void socantrcvmore(struct socket *); +void socantsendmore(struct socket *); +int soclose(struct socket *, int); +int soconnect(struct socket *, struct mbuf *); +int soconnect2(struct socket *, struct socket *); +int socreate(int, struct socket **, int, int); +int sodisconnect(struct socket *); +struct socket *soalloc(const struct protosw *, int); +void sofree(struct socket *, int); +void sorele(struct socket *); +int sogetopt(struct socket *, int, int, struct mbuf *); +void sohasoutofband(struct socket *); +void soisconnected(struct socket *); +void soisconnecting(struct socket *); +void soisdisconnected(struct socket *); +void soisdisconnecting(struct socket *); +int solisten(struct socket *, int); +struct socket *sonewconn(struct socket *, int, int); +void soqinsque(struct socket *, struct socket *, int); +int soqremque(struct socket *, int); +int soreceive(struct socket *, struct mbuf **, struct uio *, + struct mbuf **, struct mbuf **, int *, socklen_t); +int soreserve(struct socket *, u_long, u_long); +int sosend(struct socket *, struct mbuf *, struct uio *, + struct mbuf *, struct mbuf *, int); +int sosetopt(struct socket *, int, int, struct mbuf *); +int soshutdown(struct socket *, int); +void sowakeup(struct socket *, struct sockbuf *); +void sorwakeup(struct socket *); +void sowwakeup(struct socket *); +int sockargs(struct mbuf **, const void *, size_t, int); + +int sosleep_nsec(struct socket *, void *, int, const char *, uint64_t); +void solock(struct socket *); +void solock_shared(struct socket *); +void solock_nonet(struct socket *); +int solock_persocket(struct socket *); +void solock_pair(struct socket *, struct socket *); +void sounlock(struct socket *); +void sounlock_shared(struct socket *); +void sounlock_nonet(struct socket *); +void sounlock_pair(struct socket *, struct socket *); + +int sendit(struct proc *, int, struct msghdr *, int, register_t *); +int recvit(struct proc *, int, struct msghdr *, caddr_t, register_t *); +int doaccept(struct proc *, int, struct sockaddr *, socklen_t *, int, + register_t *); + +#ifdef SOCKBUF_DEBUG +void sblastrecordchk(struct sockbuf *, const char *); +#define SBLASTRECORDCHK(sb, where) sblastrecordchk((sb), (where)) + +void sblastmbufchk(struct sockbuf *, const char *); +#define SBLASTMBUFCHK(sb, where) sblastmbufchk((sb), (where)) +void sbcheck(struct socket *, struct sockbuf *); +#define SBCHECK(so, sb) sbcheck((so), (sb)) +#else +#define SBLASTRECORDCHK(sb, where) /* nothing */ +#define SBLASTMBUFCHK(sb, where) /* nothing */ +#define SBCHECK(so, sb) /* nothing */ +#endif /* SOCKBUF_DEBUG */ + +/* + * Flags to sblock() + */ +#define SBL_WAIT 0x01 /* Wait if lock not immediately available. */ +#define SBL_NOINTR 0x02 /* Enforce non-interruptible sleep. */ + +int sblock(struct sockbuf *, int); +void sbunlock(struct sockbuf *); + +extern u_long sb_max; +extern struct pool socket_pool; + +static inline struct socket * +soref(struct socket *so) +{ + if (so == NULL) + return NULL; + refcnt_take(&so->so_refcnt); + return so; +} + +/* + * Macros for sockets and socket buffering. + */ + +#define isspliced(so) ((so)->so_sp && (so)->so_sp->ssp_socket) +#define issplicedback(so) ((so)->so_sp && (so)->so_sp->ssp_soback) + +/* + * Do we need to notify the other side when I/O is possible? + */ +static inline int +sb_notify(struct sockbuf *sb) +{ + int rv; + + mtx_enter(&sb->sb_mtx); + rv = ((sb->sb_flags & (SB_WAIT|SB_ASYNC|SB_SPLICE)) != 0 || + !klist_empty(&sb->sb_klist)); + mtx_leave(&sb->sb_mtx); + + return rv; +} + +/* + * How much space is there in a socket buffer (so->so_snd or so->so_rcv)? + * This is problematical if the fields are unsigned, as the space might + * still be negative (cc > hiwat or mbcnt > mbmax). Should detect + * overflow and return 0. + */ + +static inline long +sbspace_locked(struct sockbuf *sb) +{ + sbmtxassertlocked(sb); + + return lmin(sb->sb_hiwat - sb->sb_cc, sb->sb_mbmax - sb->sb_mbcnt); +} + +static inline long +sbspace(struct sockbuf *sb) +{ + long ret; + + mtx_enter(&sb->sb_mtx); + ret = sbspace_locked(sb); + mtx_leave(&sb->sb_mtx); + + return ret; +} + +/* do we have to send all at once on a socket? */ +#define sosendallatonce(so) \ + ((so)->so_proto->pr_flags & PR_ATOMIC) + +/* are we sending on this socket? */ +#define soissending(so) \ + ((so)->so_snd.sb_state & SS_ISSENDING) + +/* can we read something from so? */ +static inline int +soreadable(struct socket *so) +{ + soassertlocked_readonly(so); + if (isspliced(so)) + return 0; + return (so->so_rcv.sb_state & SS_CANTRCVMORE) || + so->so_error || so->so_rcv.sb_cc >= so->so_rcv.sb_lowat; +} + +/* can we write something to so? */ +static inline int +sowriteable(struct socket *so) +{ + soassertlocked_readonly(so); + return ((sbspace(&so->so_snd) >= so->so_snd.sb_lowat && + ((so->so_state & SS_ISCONNECTED) || + (so->so_proto->pr_flags & PR_CONNREQUIRED)==0)) || + (so->so_snd.sb_state & SS_CANTSENDMORE) || so->so_error); +} + +/* adjust counters in sb reflecting allocation of m */ +static inline void +sballoc(struct sockbuf *sb, struct mbuf *m) +{ + sb->sb_cc += m->m_len; + if (m->m_type != MT_CONTROL && m->m_type != MT_SONAME) + sb->sb_datacc += m->m_len; + sb->sb_mbcnt += MSIZE; + if (m->m_flags & M_EXT) + sb->sb_mbcnt += m->m_ext.ext_size; +} + +/* adjust counters in sb reflecting freeing of m */ +static inline void +sbfree(struct sockbuf *sb, struct mbuf *m) +{ + sb->sb_cc -= m->m_len; + if (m->m_type != MT_CONTROL && m->m_type != MT_SONAME) + sb->sb_datacc -= m->m_len; + sb->sb_mbcnt -= MSIZE; + if (m->m_flags & M_EXT) + sb->sb_mbcnt -= m->m_ext.ext_size; +} + +static inline void +sbassertlocked(struct sockbuf *sb) +{ + rw_assert_wrlock(&sb->sb_lock); +} + +#define SB_EMPTY_FIXUP(sb) do { \ + if ((sb)->sb_mb == NULL) { \ + (sb)->sb_mbtail = NULL; \ + (sb)->sb_lastrecord = NULL; \ + } \ +} while (/*CONSTCOND*/0) + +#endif /* _KERNEL */ +#endif /* _SYS_SOCKETVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/sockio.h b/lib/libc/include/generic-openbsd/sys/sockio.h new file mode 100644 index 000000000000..10d85c792363 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/sockio.h @@ -0,0 +1,223 @@ +/* $OpenBSD: sockio.h,v 1.84 2021/11/11 10:03:10 claudio Exp $ */ +/* $NetBSD: sockio.h,v 1.5 1995/08/23 00:40:47 thorpej Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)sockio.h 8.1 (Berkeley) 3/28/94 + */ + +#ifndef _SYS_SOCKIO_H_ +#define _SYS_SOCKIO_H_ + +#include + +/* Socket ioctl's. */ +#define SIOCATMARK _IOR('s', 7, int) /* at oob mark? */ +#define SIOCSPGRP _IOW('s', 8, int) /* set process group */ +#define SIOCGPGRP _IOR('s', 9, int) /* get process group */ + +#define SIOCSIFADDR _IOW('i', 12, struct ifreq) /* set ifnet address */ +#define SIOCGIFADDR _IOWR('i', 33, struct ifreq) /* get ifnet address */ +#define SIOCSIFDSTADDR _IOW('i', 14, struct ifreq) /* set p-p address */ +#define SIOCGIFDSTADDR _IOWR('i', 34, struct ifreq) /* get p-p address */ +#define SIOCSIFFLAGS _IOW('i', 16, struct ifreq) /* set ifnet flags */ +#define SIOCGIFFLAGS _IOWR('i', 17, struct ifreq) /* get ifnet flags */ +#define SIOCGIFBRDADDR _IOWR('i', 35, struct ifreq) /* get broadcast addr */ +#define SIOCSIFBRDADDR _IOW('i', 19, struct ifreq) /* set broadcast addr */ +#define SIOCGIFCONF _IOWR('i', 36, struct ifconf) /* get ifnet list */ +#define SIOCGIFNETMASK _IOWR('i', 37, struct ifreq) /* get net addr mask */ +#define SIOCSIFNETMASK _IOW('i', 22, struct ifreq) /* set net addr mask */ +#define SIOCGIFMETRIC _IOWR('i', 23, struct ifreq) /* get IF metric */ +#define SIOCSIFMETRIC _IOW('i', 24, struct ifreq) /* set IF metric */ +#define SIOCDIFADDR _IOW('i', 25, struct ifreq) /* delete IF addr */ +#define SIOCAIFADDR _IOW('i', 26, struct ifaliasreq)/* add/chg IF alias */ +#define SIOCGIFDATA _IOWR('i', 27, struct ifreq) /* get if_data */ +#define SIOCSIFLLADDR _IOW('i', 31, struct ifreq) /* set link level addr */ + +#define SIOCADDMULTI _IOW('i', 49, struct ifreq) /* add m'cast addr */ +#define SIOCDELMULTI _IOW('i', 50, struct ifreq) /* del m'cast addr */ +#define SIOCGETVIFCNT _IOWR('u', 51, struct sioc_vif_req)/* vif pkt cnt */ +#define SIOCGETSGCNT _IOWR('u', 52, struct sioc_sg_req) /* sg pkt cnt */ + +/* 53 and 54 used to be SIOC[SG]IFMEDIA with a 32 bit media word */ +#define SIOCSIFMEDIA _IOWR('i', 55, struct ifreq) /* set net media */ +#define SIOCGIFMEDIA _IOWR('i', 56, struct ifmediareq) /* get net media */ +#define SIOCGIFSFFPAGE _IOWR('i', 57, struct if_sffpage) /* get SFF page */ + +#define SIOCDIFPHYADDR _IOW('i', 73, struct ifreq) /* delete gif addrs */ +#define SIOCSLIFPHYADDR _IOW('i', 74, struct if_laddrreq) /* set gif addrs */ +#define SIOCGLIFPHYADDR _IOWR('i', 75, struct if_laddrreq) /* get gif addrs */ + +#define SIOCBRDGADD _IOW('i', 60, struct ifbreq) /* add bridge ifs */ +#define SIOCBRDGDEL _IOW('i', 61, struct ifbreq) /* del bridge ifs */ +#define SIOCBRDGGIFFLGS _IOWR('i', 62, struct ifbreq) /* get brdg if flags */ +#define SIOCBRDGSIFFLGS _IOW('i', 63, struct ifbreq) /* set brdg if flags */ +#define SIOCBRDGSCACHE _IOW('i', 64, struct ifbrparam)/* set cache size */ +#define SIOCBRDGGCACHE _IOWR('i', 65, struct ifbrparam)/* get cache size */ +#define SIOCBRDGADDS _IOW('i', 65, struct ifbreq) /* add span port */ +#define SIOCBRDGIFS _IOWR('i', 66, struct ifbreq) /* get member ifs */ +#define SIOCBRDGDELS _IOW('i', 66, struct ifbreq) /* del span port */ +#define SIOCBRDGRTS _IOWR('i', 67, struct ifbaconf) /* get addresses */ +#define SIOCBRDGSADDR _IOWR('i', 68, struct ifbareq) /* set addr flags */ +#define SIOCBRDGSTO _IOW('i', 69, struct ifbrparam)/* cache timeout */ +#define SIOCBRDGGTO _IOWR('i', 70, struct ifbrparam)/* cache timeout */ +#define SIOCBRDGDADDR _IOW('i', 71, struct ifbareq) /* delete addr */ +#define SIOCBRDGFLUSH _IOW('i', 72, struct ifbreq) /* flush addr cache */ +#define SIOCBRDGADDL _IOW('i', 73, struct ifbreq) /* add local port */ +#define SIOCBRDGSIFPROT _IOW('i', 74, struct ifbreq) /* set protected grp */ + +#define SIOCBRDGARL _IOW('i', 77, struct ifbrlreq) /* add bridge rule */ +#define SIOCBRDGFRL _IOW('i', 78, struct ifbrlreq) /* flush brdg rules */ +#define SIOCBRDGGRL _IOWR('i', 79, struct ifbrlconf)/* get bridge rules */ +#define SIOCBRDGGPRI _IOWR('i', 80, struct ifbrparam)/* get priority */ +#define SIOCBRDGSPRI _IOW('i', 80, struct ifbrparam)/* set priority */ +#define SIOCBRDGGHT _IOWR('i', 81, struct ifbrparam)/* get hello time */ +#define SIOCBRDGSHT _IOW('i', 81, struct ifbrparam)/* set hello time */ +#define SIOCBRDGGFD _IOWR('i', 82, struct ifbrparam)/* get forward delay */ +#define SIOCBRDGSFD _IOW('i', 82, struct ifbrparam)/* set forward delay */ +#define SIOCBRDGGMA _IOWR('i', 83, struct ifbrparam)/* get max age */ +#define SIOCBRDGSMA _IOW('i', 83, struct ifbrparam)/* set max age */ +#define SIOCBRDGSIFPRIO _IOW('i', 84, struct ifbreq) /* set if priority */ +#define SIOCBRDGSIFCOST _IOW('i', 85, struct ifbreq) /* set if cost */ + +#define SIOCBRDGGPARAM _IOWR('i', 88, struct ifbropreq)/* get brdg STP parms */ +#define SIOCBRDGSTXHC _IOW('i', 89, struct ifbrparam)/* set tx hold count */ +#define SIOCBRDGSPROTO _IOW('i', 90, struct ifbrparam)/* set protocol */ + +#define SIOCSIFMTU _IOW('i', 127, struct ifreq) /* set ifnet mtu */ +#define SIOCGIFMTU _IOWR('i', 126, struct ifreq) /* get ifnet mtu */ + +#define SIOCIFCREATE _IOW('i', 122, struct ifreq) /* create clone if */ +#define SIOCIFDESTROY _IOW('i', 121, struct ifreq) /* destroy clone if */ +#define SIOCIFGCLONERS _IOWR('i', 120, struct if_clonereq) /* get cloners */ + +#define SIOCAIFGROUP _IOW('i', 135, struct ifgroupreq) /* add an ifgroup */ +#define SIOCGIFGROUP _IOWR('i', 136, struct ifgroupreq) /* get ifgroups */ +#define SIOCDIFGROUP _IOW('i', 137, struct ifgroupreq) /* delete ifgroup */ +#define SIOCGIFGMEMB _IOWR('i', 138, struct ifgroupreq) /* get members */ +#define SIOCGIFGATTR _IOWR('i', 139, struct ifgroupreq) /* get ifgroup attribs */ +#define SIOCSIFGATTR _IOW('i', 140, struct ifgroupreq) /* set ifgroup attribs */ +#define SIOCGIFGLIST _IOWR('i', 141, struct ifgroupreq) /* get ifgroup list */ + +#define SIOCSIFDESCR _IOW('i', 128, struct ifreq) /* set ifnet descr */ +#define SIOCGIFDESCR _IOWR('i', 129, struct ifreq) /* get ifnet descr */ + +#define SIOCSIFRTLABEL _IOW('i', 130, struct ifreq) /* set ifnet rtlabel */ +#define SIOCGIFRTLABEL _IOWR('i', 131, struct ifreq) /* set ifnet rtlabel */ + +#define SIOCSETVLAN _IOW('i', 143, struct ifreq) /* set vlan parent if */ +#define SIOCGETVLAN _IOWR('i', 144, struct ifreq) /* get vlan parent if */ + +#define SIOCSSPPPPARAMS _IOW('i', 147, struct ifreq) /* set pppoe params */ +#define SIOCGSPPPPARAMS _IOWR('i', 148, struct ifreq) /* get pppoe params */ + +#define SIOCDELLABEL _IOW('i', 151, struct ifreq) /* del MPLS label */ +#define SIOCGPWE3 _IOWR('i', 152, struct ifreq) /* get MPLS PWE3 cap */ +#define SIOCSETLABEL _IOW('i', 153, struct ifreq) /* set MPLS label */ +#define SIOCGETLABEL _IOW('i', 154, struct ifreq) /* get MPLS label */ + +#define SIOCSIFPRIORITY _IOW('i', 155, struct ifreq) /* set if priority */ +#define SIOCGIFPRIORITY _IOWR('i', 156, struct ifreq) /* get if priority */ + +#define SIOCSIFXFLAGS _IOW('i', 157, struct ifreq) /* set ifnet xflags */ +#define SIOCGIFXFLAGS _IOWR('i', 158, struct ifreq) /* get ifnet xflags */ + +#define SIOCSIFRDOMAIN _IOW('i', 159, struct ifreq) /* set ifnet VRF id */ +#define SIOCGIFRDOMAIN _IOWR('i', 160, struct ifreq) /* get ifnet VRF id */ + +#define SIOCSLIFPHYRTABLE _IOW('i', 161, struct ifreq) /* set tunnel VRF id */ +#define SIOCGLIFPHYRTABLE _IOWR('i', 162, struct ifreq) /* get tunnel VRF id */ + +#define SIOCSETKALIVE _IOW('i', 163, struct ifkalivereq) +#define SIOCGETKALIVE _IOWR('i', 164, struct ifkalivereq) + +#define SIOCGIFHARDMTU _IOWR('i', 165, struct ifreq) /* get ifnet hardmtu */ + +#define SIOCSVNETID _IOW('i', 166, struct ifreq) /* set virt net id */ +#define SIOCGVNETID _IOWR('i', 167, struct ifreq) /* get virt net id */ + +#define SIOCSLIFPHYTTL _IOW('i', 168, struct ifreq) /* set tunnel ttl */ +#define SIOCGLIFPHYTTL _IOWR('i', 169, struct ifreq) /* get tunnel ttl */ + +#define SIOCGIFRXR _IOW('i', 170, struct ifreq) +#define SIOCIFAFATTACH _IOW('i', 171, struct if_afreq) /* attach given af */ +#define SIOCIFAFDETACH _IOW('i', 172, struct if_afreq) /* detach given af */ + +#define SIOCSETMPWCFG _IOW('i', 173, struct ifreq) /* set mpw config */ +#define SIOCGETMPWCFG _IOWR('i', 174, struct ifreq) /* get mpw config */ + +#define SIOCDVNETID _IOW('i', 175, struct ifreq) /* del virt net id */ + +#define SIOCSIFPAIR _IOW('i', 176, struct ifreq) /* set paired if */ +#define SIOCGIFPAIR _IOWR('i', 177, struct ifreq) /* get paired if */ + +#define SIOCSIFPARENT _IOW('i', 178, struct if_parent) /* set parent if */ +#define SIOCGIFPARENT _IOWR('i', 179, struct if_parent) /* get parent if */ +#define SIOCDIFPARENT _IOW('i', 180, struct ifreq) /* del parent if */ + +#define SIOCSIFLLPRIO _IOW('i', 181, struct ifreq) /* set ifnet llprio */ +#define SIOCGIFLLPRIO _IOWR('i', 182, struct ifreq) /* get ifnet llprio */ + +#define SIOCGUMBINFO _IOWR('i', 190, struct ifreq) /* get MBIM info */ +#define SIOCSUMBPARAM _IOW('i', 191, struct ifreq) /* set MBIM param */ +#define SIOCGUMBPARAM _IOWR('i', 192, struct ifreq) /* get MBIM param */ + +#define SIOCSLIFPHYDF _IOW('i', 193, struct ifreq) /* set tunnel df/nodf */ +#define SIOCGLIFPHYDF _IOWR('i', 194, struct ifreq) /* set tunnel df/nodf */ + +#define SIOCSVNETFLOWID _IOW('i', 195, struct ifreq) /* set vnet flowid */ +#define SIOCGVNETFLOWID _IOWR('i', 196, struct ifreq) /* get vnet flowid */ + +#define SIOCSTXHPRIO _IOW('i', 197, struct ifreq) /* set tx hdr prio */ +#define SIOCGTXHPRIO _IOWR('i', 198, struct ifreq) /* get tx hdr prio */ + +#define SIOCSLIFPHYECN _IOW('i', 199, struct ifreq) /* set ecn copying */ +#define SIOCGLIFPHYECN _IOWR('i', 200, struct ifreq) /* get ecn copying */ + +#define SIOCSRXHPRIO _IOW('i', 219, struct ifreq) /* set rx hdr prio */ +#define SIOCGRXHPRIO _IOWR('i', 219, struct ifreq) /* get rx hdr prio */ + +#define SIOCSPWE3CTRLWORD _IOW('i', 220, struct ifreq) +#define SIOCGPWE3CTRLWORD _IOWR('i', 220, struct ifreq) +#define SIOCSPWE3FAT _IOW('i', 221, struct ifreq) +#define SIOCGPWE3FAT _IOWR('i', 221, struct ifreq) +#define SIOCSPWE3NEIGHBOR _IOW('i', 222, struct if_laddrreq) +#define SIOCGPWE3NEIGHBOR _IOWR('i', 222, struct if_laddrreq) +#define SIOCDPWE3NEIGHBOR _IOW('i', 222, struct ifreq) + +#define SIOCSVH _IOWR('i', 245, struct ifreq) /* set carp param */ +#define SIOCGVH _IOWR('i', 246, struct ifreq) /* get carp param */ + +#define SIOCSETPFSYNC _IOW('i', 247, struct ifreq) +#define SIOCGETPFSYNC _IOWR('i', 248, struct ifreq) + +#define SIOCSETPFLOW _IOW('i', 253, struct ifreq) +#define SIOCGETPFLOW _IOWR('i', 254, struct ifreq) + +#endif /* !_SYS_SOCKIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/softintr.h b/lib/libc/include/generic-openbsd/sys/softintr.h new file mode 100644 index 000000000000..b30da0ababb1 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/softintr.h @@ -0,0 +1,41 @@ +/* $OpenBSD: softintr.h,v 1.1 2025/04/23 15:07:00 visa Exp $ */ + +/* + * Copyright (c) 2025 Visa Hankala + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_SOFTINTR_H_ +#define _SYS_SOFTINTR_H_ + +#ifdef _KERNEL +#ifdef __USE_MI_SOFTINTR + +#define SOFTINTR_CLOCK 0 +#define SOFTINTR_NET 1 +#define SOFTINTR_TTY 2 +#define NSOFTINTR 3 + +#ifndef _LOCORE +void softintr_init(void); +void *softintr_establish(int, void (*)(void *), void *); +void softintr_disestablish(void *); +void softintr_dispatch(int); +void softintr_schedule(void *); +#endif /* !_LOCORE */ + +#endif /* __USE_MI_SOFTINTR */ +#endif /* _KERNEL */ + +#endif /* !_SYS_SOFTINTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/specdev.h b/lib/libc/include/generic-openbsd/sys/specdev.h new file mode 100644 index 000000000000..b769f5881da9 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/specdev.h @@ -0,0 +1,111 @@ +/* $OpenBSD: specdev.h,v 1.41 2022/06/26 05:20:42 visa Exp $ */ +/* $NetBSD: specdev.h,v 1.12 1996/02/13 13:13:01 mycroft Exp $ */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)specdev.h 8.3 (Berkeley) 8/10/94 + */ + +SLIST_HEAD(vnodechain, vnode); + +/* + * This structure defines the information maintained about + * special devices. It is allocated in checkalias and freed + * in vgone. + */ +struct specinfo { + struct vnodechain *si_hashchain; + SLIST_ENTRY(vnode) si_specnext; + struct mount *si_mountpoint; + dev_t si_rdev; + struct lockf_state *si_lockf; + daddr_t si_lastr; + union { + struct vnode *ci_parent; /* pointer back to parent device */ + u_int8_t *ci_bitmap; /* bitmap of devices cloned off us */ + } si_ci; +}; + +struct cloneinfo { + struct vnode *ci_vp; /* cloned vnode */ + void *ci_data; /* original vnode's v_data */ +}; + +/* + * Exported shorthand + */ +#define v_rdev v_specinfo->si_rdev +#define v_hashchain v_specinfo->si_hashchain +#define v_specnext v_specinfo->si_specnext +#define v_specmountpoint v_specinfo->si_mountpoint +#define v_speclockf v_specinfo->si_lockf +#define v_specparent v_specinfo->si_ci.ci_parent +#define v_specbitmap v_specinfo->si_ci.ci_bitmap + +/* + * We use the upper 16 bits of the minor to record the clone instance. + * This gives us 8 bits for encoding the real minor number. + */ +#define CLONE_SHIFT 8 +#define CLONE_MAPSZ 128 + +/* + * Special device management + */ +#define SPECHSZ 64 +#if ((SPECHSZ&(SPECHSZ-1)) == 0) +#define SPECHASH(rdev) (((rdev>>5)+(rdev))&(SPECHSZ-1)) +#else +#define SPECHASH(rdev) (((unsigned)((rdev>>5)+(rdev)))%SPECHSZ) +#endif + +#ifdef _KERNEL + +extern struct vnodechain speclisth[SPECHSZ]; + +/* + * Prototypes for special file operations on vnodes. + */ +int spec_getattr(void *); +int spec_setattr(void *); +int spec_access(void *); +int spec_open(void *); +int spec_close(void *); +int spec_read(void *); +int spec_write(void *); +int spec_ioctl(void *); +int spec_kqfilter(void *); +int spec_fsync(void *); +int spec_inactive(void *); +int spec_strategy(void *); +int spec_print(void *); +int spec_pathconf(void *); +int spec_advlock(void *); + +#endif /* _KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/srp.h b/lib/libc/include/generic-openbsd/sys/srp.h new file mode 100644 index 000000000000..11d846ae795f --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/srp.h @@ -0,0 +1,196 @@ +/* $OpenBSD: srp.h,v 1.16 2025/06/25 20:26:32 miod Exp $ */ + +/* + * Copyright (c) 2014 Jonathan Matthew + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_SRP_H_ +#define _SYS_SRP_H_ + +#include + +#ifndef __upunused +#ifdef MULTIPROCESSOR +#define __upunused +#else +#define __upunused __attribute__((__unused__)) +#endif +#endif /* __upunused */ + +struct srp { + void *ref; +}; + +#define SRP_INITIALIZER() { NULL } + +struct srp_hazard { + struct srp *sh_p; + void *sh_v; +}; + +struct srp_ref { + struct srp_hazard *hz; +} __upunused; + +#define SRP_HAZARD_NUM 16 + +struct srp_gc { + void (*srp_gc_dtor)(void *, void *); + void *srp_gc_cookie; + struct refcnt srp_gc_refcnt; +}; + +#define SRP_GC_INITIALIZER(_d, _c) { (_d), (_c), REFCNT_INITIALIZER() } + +/* + * singly linked list built by following srps + */ + +struct srpl_rc { + void (*srpl_ref)(void *, void *); + struct srp_gc srpl_gc; +}; +#define srpl_cookie srpl_gc.srp_gc_cookie + +#define SRPL_RC_INITIALIZER(_r, _u, _c) { _r, SRP_GC_INITIALIZER(_u, _c) } + +struct srpl { + struct srp sl_head; +}; + +#define SRPL_HEAD(name, type) struct srpl + +#define SRPL_ENTRY(type) \ +struct { \ + struct srp se_next; \ +} + +#ifdef _KERNEL + +void srp_startup(void); +void srp_gc_init(struct srp_gc *, void (*)(void *, void *), void *); +void *srp_swap_locked(struct srp *, void *); +void srp_update_locked(struct srp_gc *, struct srp *, void *); +void *srp_get_locked(struct srp *); + +void srp_init(struct srp *); + +#ifdef MULTIPROCESSOR +void *srp_swap(struct srp *, void *); +void srp_update(struct srp_gc *, struct srp *, void *); +void srp_finalize(void *, const char *); +void *srp_enter(struct srp_ref *, struct srp *); +void *srp_follow(struct srp_ref *, struct srp *); +void srp_leave(struct srp_ref *); +#else /* MULTIPROCESSOR */ + +static inline void * +srp_enter(struct srp_ref *sr, struct srp *srp) +{ + sr->hz = NULL; + return srp->ref; +} + +#define srp_swap(_srp, _v) srp_swap_locked((_srp), (_v)) +#define srp_update(_gc, _srp, _v) srp_update_locked((_gc), (_srp), (_v)) +#define srp_finalize(_v, _wchan) ((void)0) +#define srp_follow(_sr, _srp) srp_enter(_sr, _srp) +#define srp_leave(_sr) do { } while (0) +#endif /* MULTIPROCESSOR */ + + +void srpl_rc_init(struct srpl_rc *, void (*)(void *, void *), + void (*)(void *, void *), void *); + +#define SRPL_INIT(_sl) srp_init(&(_sl)->sl_head) + +#define SRPL_FIRST(_sr, _sl) srp_enter((_sr), &(_sl)->sl_head) +#define SRPL_NEXT(_sr, _e, _ENTRY) srp_enter((_sr), &(_e)->_ENTRY.se_next) +#define SRPL_FOLLOW(_sr, _e, _ENTRY) srp_follow((_sr), &(_e)->_ENTRY.se_next) + +#define SRPL_FOREACH(_c, _sr, _sl, _ENTRY) \ + for ((_c) = SRPL_FIRST(_sr, _sl); \ + (_c) != NULL; \ + (_c) = SRPL_FOLLOW(_sr, _c, _ENTRY)) + +#define SRPL_LEAVE(_sr) srp_leave((_sr)) + +#define SRPL_FIRST_LOCKED(_sl) srp_get_locked(&(_sl)->sl_head) +#define SRPL_EMPTY_LOCKED(_sl) (SRPL_FIRST_LOCKED(_sl) == NULL) + +#define SRPL_NEXT_LOCKED(_e, _ENTRY) \ + srp_get_locked(&(_e)->_ENTRY.se_next) + +#define SRPL_FOREACH_LOCKED(_c, _sl, _ENTRY) \ + for ((_c) = SRPL_FIRST_LOCKED(_sl); \ + (_c) != NULL; \ + (_c) = SRPL_NEXT_LOCKED((_c), _ENTRY)) + +#define SRPL_FOREACH_SAFE_LOCKED(_c, _sl, _ENTRY, _tc) \ + for ((_c) = SRPL_FIRST_LOCKED(_sl); \ + (_c) && ((_tc) = SRPL_NEXT_LOCKED(_c, _ENTRY), 1); \ + (_c) = (_tc)) + +#define SRPL_INSERT_HEAD_LOCKED(_rc, _sl, _e, _ENTRY) do { \ + void *head; \ + \ + srp_init(&(_e)->_ENTRY.se_next); \ + \ + head = SRPL_FIRST_LOCKED(_sl); \ + if (head != NULL) { \ + (_rc)->srpl_ref(&(_rc)->srpl_cookie, head); \ + srp_update_locked(&(_rc)->srpl_gc, \ + &(_e)->_ENTRY.se_next, head); \ + } \ + \ + (_rc)->srpl_ref(&(_rc)->srpl_cookie, _e); \ + srp_update_locked(&(_rc)->srpl_gc, &(_sl)->sl_head, (_e)); \ +} while (0) + +#define SRPL_INSERT_AFTER_LOCKED(_rc, _se, _e, _ENTRY) do { \ + void *next; \ + \ + srp_init(&(_e)->_ENTRY.se_next); \ + \ + next = SRPL_NEXT_LOCKED(_se, _ENTRY); \ + if (next != NULL) { \ + (_rc)->srpl_ref(&(_rc)->srpl_cookie, next); \ + srp_update_locked(&(_rc)->srpl_gc, \ + &(_e)->_ENTRY.se_next, next); \ + } \ + \ + (_rc)->srpl_ref(&(_rc)->srpl_cookie, _e); \ + srp_update_locked(&(_rc)->srpl_gc, \ + &(_se)->_ENTRY.se_next, (_e)); \ +} while (0) + +#define SRPL_REMOVE_LOCKED(_rc, _sl, _e, _type, _ENTRY) do { \ + struct srp *ref; \ + struct _type *c, *n; \ + \ + ref = &(_sl)->sl_head; \ + while ((c = srp_get_locked(ref)) != (_e)) \ + ref = &c->_ENTRY.se_next; \ + \ + n = SRPL_NEXT_LOCKED(c, _ENTRY); \ + if (n != NULL) \ + (_rc)->srpl_ref(&(_rc)->srpl_cookie, n); \ + srp_update_locked(&(_rc)->srpl_gc, ref, n); \ + srp_update_locked(&(_rc)->srpl_gc, &c->_ENTRY.se_next, NULL); \ +} while (0) + +#endif /* _KERNEL */ + +#endif /* _SYS_SRP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/stacktrace.h b/lib/libc/include/generic-openbsd/sys/stacktrace.h new file mode 100644 index 000000000000..aec5d32feb76 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/stacktrace.h @@ -0,0 +1,41 @@ +/* $OpenBSD: stacktrace.h,v 1.4 2023/04/26 16:53:59 claudio Exp $ */ + +/* + * Copyright (c) 2017 Visa Hankala + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_STACKTRACE_H_ +#define _SYS_STACKTRACE_H_ + +#define STACKTRACE_MAX 19 + +struct stacktrace { + unsigned int st_count; + unsigned long st_pc[STACKTRACE_MAX]; +}; + +#ifdef _KERNEL +void stacktrace_print(struct stacktrace *, int (*)(const char *, ...)); +void stacktrace_save_at(struct stacktrace *, unsigned int); +void stacktrace_save_utrace(struct stacktrace *); + +static inline void +stacktrace_save(struct stacktrace *st) +{ + stacktrace_save_at(st, 0); +} +#endif + +#endif /* _SYS_STACKTRACE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/stat.h b/lib/libc/include/generic-openbsd/sys/stat.h new file mode 100644 index 000000000000..578c27ebed26 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/stat.h @@ -0,0 +1,222 @@ +/* $OpenBSD: stat.h,v 1.29 2022/01/11 23:59:55 jsg Exp $ */ +/* $NetBSD: stat.h,v 1.20 1996/05/16 22:17:49 cgd Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)stat.h 8.9 (Berkeley) 8/17/94 + */ + +#ifndef _SYS_STAT_H_ +#define _SYS_STAT_H_ + +#include + +struct stat { + mode_t st_mode; /* inode protection mode */ + dev_t st_dev; /* inode's device */ + ino_t st_ino; /* inode's number */ + nlink_t st_nlink; /* number of hard links */ + uid_t st_uid; /* user ID of the file's owner */ + gid_t st_gid; /* group ID of the file's group */ + dev_t st_rdev; /* device type */ +#if __POSIX_VISIBLE >= 200809 || __BSD_VISIBLE + struct timespec st_atim; /* time of last access */ + struct timespec st_mtim; /* time of last data modification */ + struct timespec st_ctim; /* time of last file status change */ +#else + time_t st_atime; /* time of last access */ + long st_atimensec; /* nsec of last access */ + time_t st_mtime; /* time of last data modification */ + long st_mtimensec; /* nsec of last data modification */ + time_t st_ctime; /* time of last file status change */ + long st_ctimensec; /* nsec of last file status change */ +#endif /* __POSIX_VISIBLE >= 200809 || __BSD_VISIBLE */ + off_t st_size; /* file size, in bytes */ + blkcnt_t st_blocks; /* blocks allocated for file */ + blksize_t st_blksize; /* optimal blocksize for I/O */ + u_int32_t st_flags; /* user defined flags for file */ + u_int32_t st_gen; /* file generation number */ +#if __POSIX_VISIBLE >= 200809 || __BSD_VISIBLE + struct timespec __st_birthtim; /* time of file creation */ +#else + time_t __st_birthtime; /* time of file creation */ + long __st_birthtimensec; /* nsec of file creation */ +#endif /* __POSIX_VISIBLE >= 200809 || __BSD_VISIBLE */ +}; +#if __POSIX_VISIBLE >= 200809 || __BSD_VISIBLE +#define st_atime st_atim.tv_sec +#define st_mtime st_mtim.tv_sec +#define st_ctime st_ctim.tv_sec +#define __st_birthtime __st_birthtim.tv_sec +#endif +#if __BSD_VISIBLE +#define st_atimespec st_atim +#define st_atimensec st_atim.tv_nsec +#define st_mtimespec st_mtim +#define st_mtimensec st_mtim.tv_nsec +#define st_ctimespec st_ctim +#define st_ctimensec st_ctim.tv_nsec +#define __st_birthtimespec __st_birthtim +#define __st_birthtimensec __st_birthtim.tv_nsec +#endif + +#define S_ISUID 0004000 /* set user id on execution */ +#define S_ISGID 0002000 /* set group id on execution */ +#if __BSD_VISIBLE +#define S_ISTXT 0001000 /* sticky bit */ +#endif + +#define S_IRWXU 0000700 /* RWX mask for owner */ +#define S_IRUSR 0000400 /* R for owner */ +#define S_IWUSR 0000200 /* W for owner */ +#define S_IXUSR 0000100 /* X for owner */ + +#if __BSD_VISIBLE +#define S_IREAD S_IRUSR +#define S_IWRITE S_IWUSR +#define S_IEXEC S_IXUSR +#endif + +#define S_IRWXG 0000070 /* RWX mask for group */ +#define S_IRGRP 0000040 /* R for group */ +#define S_IWGRP 0000020 /* W for group */ +#define S_IXGRP 0000010 /* X for group */ + +#define S_IRWXO 0000007 /* RWX mask for other */ +#define S_IROTH 0000004 /* R for other */ +#define S_IWOTH 0000002 /* W for other */ +#define S_IXOTH 0000001 /* X for other */ + +#if __XPG_VISIBLE || __BSD_VISIBLE +#define S_IFMT 0170000 /* type of file mask */ +#define S_IFIFO 0010000 /* named pipe (fifo) */ +#define S_IFCHR 0020000 /* character special */ +#define S_IFDIR 0040000 /* directory */ +#define S_IFBLK 0060000 /* block special */ +#define S_IFREG 0100000 /* regular */ +#define S_IFLNK 0120000 /* symbolic link */ +#define S_IFSOCK 0140000 /* socket */ +#define S_ISVTX 0001000 /* save swapped text even after use */ +#endif + +#define S_ISDIR(m) ((m & 0170000) == 0040000) /* directory */ +#define S_ISCHR(m) ((m & 0170000) == 0020000) /* char special */ +#define S_ISBLK(m) ((m & 0170000) == 0060000) /* block special */ +#define S_ISREG(m) ((m & 0170000) == 0100000) /* regular file */ +#define S_ISFIFO(m) ((m & 0170000) == 0010000) /* fifo */ +#if __POSIX_VISIBLE >= 200112 || __BSD_VISIBLE +#define S_ISLNK(m) ((m & 0170000) == 0120000) /* symbolic link */ +#define S_ISSOCK(m) ((m & 0170000) == 0140000) /* socket */ +#endif + +#if __POSIX_VISIBLE >= 200809 +/* mandated to be present, but permitted to always return zero */ +#define S_TYPEISMQ(m) 0 +#define S_TYPEISSEM(m) 0 +#define S_TYPEISSHM(m) 0 +#endif + +#if __BSD_VISIBLE +#define ACCESSPERMS (S_IRWXU|S_IRWXG|S_IRWXO) /* 00777 */ + /* 07777 */ +#define ALLPERMS (S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO) + /* 00666 */ +#define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) + +#define S_BLKSIZE 512 /* block size used in the stat struct */ + +/* + * Definitions of flags stored in file flags word. + * + * Super-user and owner changeable flags. + */ +#define UF_SETTABLE 0x0000ffff /* mask of owner changeable flags */ +#define UF_NODUMP 0x00000001 /* do not dump file */ +#define UF_IMMUTABLE 0x00000002 /* file may not be changed */ +#define UF_APPEND 0x00000004 /* writes to file may only append */ +#define UF_OPAQUE 0x00000008 /* directory is opaque wrt. union */ +/* + * Super-user changeable flags. + */ +#define SF_SETTABLE 0xffff0000 /* mask of superuser changeable flags */ +#define SF_ARCHIVED 0x00010000 /* file is archived */ +#define SF_IMMUTABLE 0x00020000 /* file may not be changed */ +#define SF_APPEND 0x00040000 /* writes to file may only append */ + +#ifdef _KERNEL +/* + * Shorthand abbreviations of above. + */ +#define OPAQUE (UF_OPAQUE) +#define APPEND (UF_APPEND | SF_APPEND) +#define IMMUTABLE (UF_IMMUTABLE | SF_IMMUTABLE) +#endif /* _KERNEL */ +#endif /* __BSD_VISIBLE */ + +#if __POSIX_VISIBLE >= 200809 +#define UTIME_NOW -2L +#define UTIME_OMIT -1L +#endif /* __POSIX_VISIBLE */ + +#ifndef _KERNEL +__BEGIN_DECLS +int chmod(const char *, mode_t); +int fstat(int, struct stat *); +int mknod(const char *, mode_t, dev_t); +int mkdir(const char *, mode_t); +int mkfifo(const char *, mode_t); +int stat(const char *, struct stat *); +mode_t umask(mode_t); +#if __POSIX_VISIBLE >= 200112L || __XPG_VISIBLE >= 420 || __BSD_VISIBLE +int fchmod(int, mode_t); +int lstat(const char *, struct stat *); +#endif +#if __POSIX_VISIBLE >= 200809 +int fchmodat(int, const char *, mode_t, int); +int fstatat(int, const char *, struct stat *, int); +int mkdirat(int, const char *, mode_t); +int mkfifoat(int, const char *, mode_t); +int mknodat(int, const char *, mode_t, dev_t); +int utimensat(int, const char *, const struct timespec [2], int); +int futimens(int, const struct timespec [2]); +#endif +#if __BSD_VISIBLE +int chflags(const char *, unsigned int); +int chflagsat(int, const char *, unsigned int, int); +int fchflags(int, unsigned int); +int isfdtype(int, int); +#endif +__END_DECLS +#endif +#endif /* !_SYS_STAT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/statvfs.h b/lib/libc/include/generic-openbsd/sys/statvfs.h new file mode 100644 index 000000000000..d5c873bde2da --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/statvfs.h @@ -0,0 +1,48 @@ +/* $OpenBSD: statvfs.h,v 1.4 2022/02/11 15:11:35 millert Exp $ */ + +/* + * Copyright (c) 2008 Otto Moerbeek + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_STATVFS_H_ +#define _SYS_STATVFS_H_ + +#include + +struct statvfs { + unsigned long f_bsize; /* file system block size */ + unsigned long f_frsize; /* fundamental file system block size */ + fsblkcnt_t f_blocks; /* number of blocks (unit f_frsize) */ + fsblkcnt_t f_bfree; /* free blocks in file system */ + fsblkcnt_t f_bavail; /* free blocks for non-root */ + fsfilcnt_t f_files; /* total file inodes */ + fsfilcnt_t f_ffree; /* free file inodes */ + fsfilcnt_t f_favail; /* free file inodes for non-root */ + unsigned long f_fsid; /* file system id */ + unsigned long f_flag; /* bit mask of f_flag values */ + unsigned long f_namemax; /* maximum filename length */ +}; + +#define ST_RDONLY 0x0001UL /* read-only filesystem */ +#define ST_NOSUID 0x0002UL /* nosuid flag set */ + +#ifndef _KERNEL +__BEGIN_DECLS +int fstatvfs(int, struct statvfs *); +int statvfs(const char *, struct statvfs *); +__END_DECLS +#endif /* !_KERNEL */ + +#endif /* !_SYS_STATVFS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/stdarg.h b/lib/libc/include/generic-openbsd/sys/stdarg.h new file mode 100644 index 000000000000..0fbd75bb6e00 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/stdarg.h @@ -0,0 +1,45 @@ +/* $OpenBSD: stdarg.h,v 1.10 2020/07/21 23:09:00 daniel Exp $ */ +/* + * Copyright (c) 2003, 2004 Marc espie + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _STDARG_H_ +#define _STDARG_H_ + +#include + +/* Define __gnuc_va_list. */ + +#ifndef __GNUC_VA_LIST +#define __GNUC_VA_LIST +typedef __builtin_va_list __gnuc_va_list; +#endif + +/* Note that the type used in va_arg is supposed to match the + actual type **after default promotions**. + Thus, va_arg (..., short) is not valid. */ + +#define va_start(ap, last) __builtin_va_start((ap), last) +#define va_end(ap) __builtin_va_end((ap)) +#define va_arg(ap, type) __builtin_va_arg((ap), type) +#define __va_copy(dst, src) __builtin_va_copy((dst),(src)) + +typedef __gnuc_va_list va_list; + +#if __ISO_C_VISIBLE >= 1999 +#define va_copy(dst, src) __va_copy((dst), (src)) +#endif + +#endif /* not _STDARG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/stdint.h b/lib/libc/include/generic-openbsd/sys/stdint.h new file mode 100644 index 000000000000..c0372ec51c5d --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/stdint.h @@ -0,0 +1,231 @@ +/* $OpenBSD: stdint.h,v 1.11 2019/01/25 00:19:26 millert Exp $ */ + +/* + * Copyright (c) 1997, 2005 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_STDINT_H_ +#define _SYS_STDINT_H_ + +#include +#include + +#ifndef __BIT_TYPES_DEFINED__ +#define __BIT_TYPES_DEFINED__ +#endif + +/* 7.18.1.1 Exact-width integer types (also in sys/types.h) */ +#ifndef _INT8_T_DEFINED_ +#define _INT8_T_DEFINED_ +typedef __int8_t int8_t; +#endif + +#ifndef _UINT8_T_DEFINED_ +#define _UINT8_T_DEFINED_ +typedef __uint8_t uint8_t; +#endif + +#ifndef _INT16_T_DEFINED_ +#define _INT16_T_DEFINED_ +typedef __int16_t int16_t; +#endif + +#ifndef _UINT16_T_DEFINED_ +#define _UINT16_T_DEFINED_ +typedef __uint16_t uint16_t; +#endif + +#ifndef _INT32_T_DEFINED_ +#define _INT32_T_DEFINED_ +typedef __int32_t int32_t; +#endif + +#ifndef _UINT32_T_DEFINED_ +#define _UINT32_T_DEFINED_ +typedef __uint32_t uint32_t; +#endif + +#ifndef _INT64_T_DEFINED_ +#define _INT64_T_DEFINED_ +typedef __int64_t int64_t; +#endif + +#ifndef _UINT64_T_DEFINED_ +#define _UINT64_T_DEFINED_ +typedef __uint64_t uint64_t; +#endif + +/* 7.18.1.2 Minimum-width integer types */ +typedef __int_least8_t int_least8_t; +typedef __uint_least8_t uint_least8_t; +typedef __int_least16_t int_least16_t; +typedef __uint_least16_t uint_least16_t; +typedef __int_least32_t int_least32_t; +typedef __uint_least32_t uint_least32_t; +typedef __int_least64_t int_least64_t; +typedef __uint_least64_t uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types */ +typedef __int_fast8_t int_fast8_t; +typedef __uint_fast8_t uint_fast8_t; +typedef __int_fast16_t int_fast16_t; +typedef __uint_fast16_t uint_fast16_t; +typedef __int_fast32_t int_fast32_t; +typedef __uint_fast32_t uint_fast32_t; +typedef __int_fast64_t int_fast64_t; +typedef __uint_fast64_t uint_fast64_t; + +/* 7.18.1.4 Integer types capable of holding object pointers */ +#ifndef _INTPTR_T_DEFINED_ +#define _INTPTR_T_DEFINED_ +typedef __intptr_t intptr_t; +#endif + +typedef __uintptr_t uintptr_t; + +/* 7.18.1.5 Greatest-width integer types */ +typedef __intmax_t intmax_t; +typedef __uintmax_t uintmax_t; + +/* + * 7.18.2 Limits of specified-width integer types. + * + * The following object-like macros specify the minimum and maximum limits + * of integer types corresponding to the typedef names defined above. + */ + +/* 7.18.2.1 Limits of exact-width integer types */ +#define INT8_MIN (-0x7f - 1) +#define INT16_MIN (-0x7fff - 1) +#define INT32_MIN (-0x7fffffff - 1) +#define INT64_MIN (-0x7fffffffffffffffLL - 1) + +#define INT8_MAX 0x7f +#define INT16_MAX 0x7fff +#define INT32_MAX 0x7fffffff +#define INT64_MAX 0x7fffffffffffffffLL + +#define UINT8_MAX 0xff +#define UINT16_MAX 0xffff +#define UINT32_MAX 0xffffffffU +#define UINT64_MAX 0xffffffffffffffffULL + +/* 7.18.2.2 Limits of minimum-width integer types */ +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST64_MIN INT64_MIN + +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MAX INT64_MAX + +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +/* 7.18.2.3 Limits of fastest minimum-width integer types */ +#define INT_FAST8_MIN __INT_FAST8_MIN +#define INT_FAST16_MIN __INT_FAST16_MIN +#define INT_FAST32_MIN __INT_FAST32_MIN +#define INT_FAST64_MIN __INT_FAST64_MIN + +#define INT_FAST8_MAX __INT_FAST8_MAX +#define INT_FAST16_MAX __INT_FAST16_MAX +#define INT_FAST32_MAX __INT_FAST32_MAX +#define INT_FAST64_MAX __INT_FAST64_MAX + +#define UINT_FAST8_MAX __UINT_FAST8_MAX +#define UINT_FAST16_MAX __UINT_FAST16_MAX +#define UINT_FAST32_MAX __UINT_FAST32_MAX +#define UINT_FAST64_MAX __UINT_FAST64_MAX + +/* 7.18.2.4 Limits of integer types capable of holding object pointers */ +#ifdef __LP64__ +#define INTPTR_MIN (-0x7fffffffffffffffL - 1) +#define INTPTR_MAX 0x7fffffffffffffffL +#define UINTPTR_MAX 0xffffffffffffffffUL +#else +#define INTPTR_MIN (-0x7fffffffL - 1) +#define INTPTR_MAX 0x7fffffffL +#define UINTPTR_MAX 0xffffffffUL +#endif + +/* 7.18.2.5 Limits of greatest-width integer types */ +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +/* + * 7.18.3 Limits of other integer types. + * + * The following object-like macros specify the minimum and maximum limits + * of integer types corresponding to types specified in other standard + * header files. + */ + +/* Limits of ptrdiff_t */ +#define PTRDIFF_MIN INTPTR_MIN +#define PTRDIFF_MAX INTPTR_MAX + +/* Limits of sig_atomic_t */ +#define SIG_ATOMIC_MIN INT32_MIN +#define SIG_ATOMIC_MAX INT32_MAX + +/* Limit of size_t */ +#ifndef SIZE_MAX +#define SIZE_MAX UINTPTR_MAX +#endif + +/* Limits of wchar_t */ +#ifndef WCHAR_MIN +#define WCHAR_MIN INT32_MIN +#endif +#ifndef WCHAR_MAX +#define WCHAR_MAX INT32_MAX +#endif + +/* Limits of wint_t */ +#define WINT_MIN INT32_MIN +#define WINT_MAX INT32_MAX + +/* + * 7.18.4 Macros for integer constants. + * + * The following function-like macros expand to integer constants + * suitable for initializing objects that have integer types corresponding + * to types defined in . The argument in any instance of + * these macros shall be a decimal, octal, or hexadecimal constant with + * a value that does not exceed the limits for the corresponding type. + */ + +/* 7.18.4.1 Macros for minimum-width integer constants. */ +#define INT8_C(_c) (_c) +#define INT16_C(_c) (_c) +#define INT32_C(_c) (_c) +#define INT64_C(_c) __CONCAT(_c, LL) + +#define UINT8_C(_c) (_c) +#define UINT16_C(_c) (_c) +#define UINT32_C(_c) __CONCAT(_c, U) +#define UINT64_C(_c) __CONCAT(_c, ULL) + +/* 7.18.4.2 Macros for greatest-width integer constants. */ +#define INTMAX_C(_c) __CONCAT(_c, LL) +#define UINTMAX_C(_c) __CONCAT(_c, ULL) + +#endif /* _SYS_STDINT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/swap.h b/lib/libc/include/generic-openbsd/sys/swap.h new file mode 100644 index 000000000000..4018a7813a78 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/swap.h @@ -0,0 +1,62 @@ +/* $OpenBSD: swap.h,v 1.7 2013/09/30 12:02:30 millert Exp $ */ +/* $NetBSD: swap.h,v 1.2 1998/09/13 14:46:24 christos Exp $ */ + +/* + * Copyright (c) 1995, 1996, 1998 Matthew R. Green, Tobias Weingartner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_SWAP_H_ +#define _SYS_SWAP_H_ + +#include + +/* These structures are used to return swap information for userland */ +struct swapent { + dev_t se_dev; /* device id */ + int se_flags; /* flags */ + int se_nblks; /* total blocks */ + int se_inuse; /* blocks in use */ + int se_priority; /* priority of this device */ + char se_path[PATH_MAX]; /* path name */ +}; + +#ifdef _KERNEL +#define NETDEV (dev_t)(-2) /* network device (for nfs swap) */ +#endif /* _KERNEL */ + +#define SWAP_ON 1 /* begin swapping on device */ +#define SWAP_OFF 2 /* (stop swapping on device) */ +#define SWAP_NSWAP 3 /* how many swap devices ? */ +#define SWAP_STATS 4 /* get device info */ +#define SWAP_CTL 5 /* change priority on device */ +#define SWAP_DUMPDEV 7 /* use this device as dump device */ + +#define SWF_INUSE 0x00000001 /* in use: we have swapped here */ +#define SWF_ENABLE 0x00000002 /* enabled: we can swap here */ +#define SWF_BUSY 0x00000004 /* busy: I/O happening here */ +#define SWF_FAKE 0x00000008 /* fake: still being built */ + +#endif /* _SYS_SWAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/syscall.h b/lib/libc/include/generic-openbsd/sys/syscall.h new file mode 100644 index 000000000000..6aa7b3f897e1 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/syscall.h @@ -0,0 +1,728 @@ +/* $OpenBSD: syscall.h,v 1.283 2025/05/24 06:50:02 deraadt Exp $ */ + +/* + * System call numbers. + * + * DO NOT EDIT-- this file is automatically generated. + * created from; OpenBSD: syscalls.master,v 1.270 2025/05/24 06:49:16 deraadt Exp + */ + +/* syscall: "exit" ret: "void" args: "int" */ +#define SYS_exit 1 + +/* syscall: "fork" ret: "int" args: */ +#define SYS_fork 2 + +/* syscall: "read" ret: "ssize_t" args: "int" "void *" "size_t" */ +#define SYS_read 3 + +/* syscall: "write" ret: "ssize_t" args: "int" "const void *" "size_t" */ +#define SYS_write 4 + +/* syscall: "open" ret: "int" args: "const char *" "int" "..." "mode_t" */ +#define SYS_open 5 + +/* syscall: "close" ret: "int" args: "int" */ +#define SYS_close 6 + +/* syscall: "getentropy" ret: "int" args: "void *" "size_t" */ +#define SYS_getentropy 7 + +/* syscall: "__tfork" ret: "int" args: "const struct __tfork *" "size_t" */ +#define SYS___tfork 8 + +/* syscall: "link" ret: "int" args: "const char *" "const char *" */ +#define SYS_link 9 + +/* syscall: "unlink" ret: "int" args: "const char *" */ +#define SYS_unlink 10 + +/* syscall: "wait4" ret: "pid_t" args: "pid_t" "int *" "int" "struct rusage *" */ +#define SYS_wait4 11 + +/* syscall: "chdir" ret: "int" args: "const char *" */ +#define SYS_chdir 12 + +/* syscall: "fchdir" ret: "int" args: "int" */ +#define SYS_fchdir 13 + +/* syscall: "mknod" ret: "int" args: "const char *" "mode_t" "dev_t" */ +#define SYS_mknod 14 + +/* syscall: "chmod" ret: "int" args: "const char *" "mode_t" */ +#define SYS_chmod 15 + +/* syscall: "chown" ret: "int" args: "const char *" "uid_t" "gid_t" */ +#define SYS_chown 16 + +/* syscall: "break" ret: "int" args: "char *" */ +#define SYS_break 17 + +/* syscall: "getdtablecount" ret: "int" args: */ +#define SYS_getdtablecount 18 + +/* syscall: "getrusage" ret: "int" args: "int" "struct rusage *" */ +#define SYS_getrusage 19 + +/* syscall: "getpid" ret: "pid_t" args: */ +#define SYS_getpid 20 + +/* syscall: "mount" ret: "int" args: "const char *" "const char *" "int" "void *" */ +#define SYS_mount 21 + +/* syscall: "unmount" ret: "int" args: "const char *" "int" */ +#define SYS_unmount 22 + +/* syscall: "setuid" ret: "int" args: "uid_t" */ +#define SYS_setuid 23 + +/* syscall: "getuid" ret: "uid_t" args: */ +#define SYS_getuid 24 + +/* syscall: "geteuid" ret: "uid_t" args: */ +#define SYS_geteuid 25 + +/* syscall: "ptrace" ret: "int" args: "int" "pid_t" "caddr_t" "int" */ +#define SYS_ptrace 26 + +/* syscall: "recvmsg" ret: "ssize_t" args: "int" "struct msghdr *" "int" */ +#define SYS_recvmsg 27 + +/* syscall: "sendmsg" ret: "ssize_t" args: "int" "const struct msghdr *" "int" */ +#define SYS_sendmsg 28 + +/* syscall: "recvfrom" ret: "ssize_t" args: "int" "void *" "size_t" "int" "struct sockaddr *" "socklen_t *" */ +#define SYS_recvfrom 29 + +/* syscall: "accept" ret: "int" args: "int" "struct sockaddr *" "socklen_t *" */ +#define SYS_accept 30 + +/* syscall: "getpeername" ret: "int" args: "int" "struct sockaddr *" "socklen_t *" */ +#define SYS_getpeername 31 + +/* syscall: "getsockname" ret: "int" args: "int" "struct sockaddr *" "socklen_t *" */ +#define SYS_getsockname 32 + +/* syscall: "access" ret: "int" args: "const char *" "int" */ +#define SYS_access 33 + +/* syscall: "chflags" ret: "int" args: "const char *" "u_int" */ +#define SYS_chflags 34 + +/* syscall: "fchflags" ret: "int" args: "int" "u_int" */ +#define SYS_fchflags 35 + +/* syscall: "sync" ret: "void" args: */ +#define SYS_sync 36 + + /* 37 is obsolete msyscall */ +/* syscall: "stat" ret: "int" args: "const char *" "struct stat *" */ +#define SYS_stat 38 + +/* syscall: "getppid" ret: "pid_t" args: */ +#define SYS_getppid 39 + +/* syscall: "lstat" ret: "int" args: "const char *" "struct stat *" */ +#define SYS_lstat 40 + +/* syscall: "dup" ret: "int" args: "int" */ +#define SYS_dup 41 + +/* syscall: "fstatat" ret: "int" args: "int" "const char *" "struct stat *" "int" */ +#define SYS_fstatat 42 + +/* syscall: "getegid" ret: "gid_t" args: */ +#define SYS_getegid 43 + +/* syscall: "ktrace" ret: "int" args: "const char *" "int" "int" "pid_t" */ +#define SYS_ktrace 45 + +/* syscall: "sigaction" ret: "int" args: "int" "const struct sigaction *" "struct sigaction *" */ +#define SYS_sigaction 46 + +/* syscall: "getgid" ret: "gid_t" args: */ +#define SYS_getgid 47 + +/* syscall: "sigprocmask" ret: "int" args: "int" "sigset_t" */ +#define SYS_sigprocmask 48 + +/* syscall: "mmap" ret: "void *" args: "void *" "size_t" "int" "int" "int" "off_t" */ +#define SYS_mmap 49 + +/* syscall: "setlogin" ret: "int" args: "const char *" */ +#define SYS_setlogin 50 + +/* syscall: "acct" ret: "int" args: "const char *" */ +#define SYS_acct 51 + +/* syscall: "sigpending" ret: "int" args: */ +#define SYS_sigpending 52 + +/* syscall: "fstat" ret: "int" args: "int" "struct stat *" */ +#define SYS_fstat 53 + +/* syscall: "ioctl" ret: "int" args: "int" "u_long" "..." "void *" */ +#define SYS_ioctl 54 + +/* syscall: "reboot" ret: "int" args: "int" */ +#define SYS_reboot 55 + +/* syscall: "revoke" ret: "int" args: "const char *" */ +#define SYS_revoke 56 + +/* syscall: "symlink" ret: "int" args: "const char *" "const char *" */ +#define SYS_symlink 57 + +/* syscall: "readlink" ret: "ssize_t" args: "const char *" "char *" "size_t" */ +#define SYS_readlink 58 + +/* syscall: "execve" ret: "int" args: "const char *" "char *const *" "char *const *" */ +#define SYS_execve 59 + +/* syscall: "umask" ret: "mode_t" args: "mode_t" */ +#define SYS_umask 60 + +/* syscall: "chroot" ret: "int" args: "const char *" */ +#define SYS_chroot 61 + +/* syscall: "getfsstat" ret: "int" args: "struct statfs *" "size_t" "int" */ +#define SYS_getfsstat 62 + +/* syscall: "statfs" ret: "int" args: "const char *" "struct statfs *" */ +#define SYS_statfs 63 + +/* syscall: "fstatfs" ret: "int" args: "int" "struct statfs *" */ +#define SYS_fstatfs 64 + +/* syscall: "fhstatfs" ret: "int" args: "const fhandle_t *" "struct statfs *" */ +#define SYS_fhstatfs 65 + +/* syscall: "vfork" ret: "int" args: */ +#define SYS_vfork 66 + +/* syscall: "gettimeofday" ret: "int" args: "struct timeval *" "struct timezone *" */ +#define SYS_gettimeofday 67 + +/* syscall: "settimeofday" ret: "int" args: "const struct timeval *" "const struct timezone *" */ +#define SYS_settimeofday 68 + +/* syscall: "setitimer" ret: "int" args: "int" "const struct itimerval *" "struct itimerval *" */ +#define SYS_setitimer 69 + +/* syscall: "getitimer" ret: "int" args: "int" "struct itimerval *" */ +#define SYS_getitimer 70 + +/* syscall: "select" ret: "int" args: "int" "fd_set *" "fd_set *" "fd_set *" "struct timeval *" */ +#define SYS_select 71 + +/* syscall: "kevent" ret: "int" args: "int" "const struct kevent *" "int" "struct kevent *" "int" "const struct timespec *" */ +#define SYS_kevent 72 + +/* syscall: "munmap" ret: "int" args: "void *" "size_t" */ +#define SYS_munmap 73 + +/* syscall: "mprotect" ret: "int" args: "void *" "size_t" "int" */ +#define SYS_mprotect 74 + +/* syscall: "madvise" ret: "int" args: "void *" "size_t" "int" */ +#define SYS_madvise 75 + +/* syscall: "utimes" ret: "int" args: "const char *" "const struct timeval *" */ +#define SYS_utimes 76 + +/* syscall: "futimes" ret: "int" args: "int" "const struct timeval *" */ +#define SYS_futimes 77 + +/* syscall: "mquery" ret: "void *" args: "void *" "size_t" "int" "int" "int" "off_t" */ +#define SYS_mquery 78 + +/* syscall: "getgroups" ret: "int" args: "int" "gid_t *" */ +#define SYS_getgroups 79 + +/* syscall: "setgroups" ret: "int" args: "int" "const gid_t *" */ +#define SYS_setgroups 80 + +/* syscall: "getpgrp" ret: "int" args: */ +#define SYS_getpgrp 81 + +/* syscall: "setpgid" ret: "int" args: "pid_t" "pid_t" */ +#define SYS_setpgid 82 + +/* syscall: "futex" ret: "int" args: "uint32_t *" "int" "int" "const struct timespec *" "uint32_t *" */ +#define SYS_futex 83 + +/* syscall: "utimensat" ret: "int" args: "int" "const char *" "const struct timespec *" "int" */ +#define SYS_utimensat 84 + +/* syscall: "futimens" ret: "int" args: "int" "const struct timespec *" */ +#define SYS_futimens 85 + +/* syscall: "kbind" ret: "int" args: "const struct __kbind *" "size_t" "int64_t" */ +#define SYS_kbind 86 + +/* syscall: "clock_gettime" ret: "int" args: "clockid_t" "struct timespec *" */ +#define SYS_clock_gettime 87 + +/* syscall: "clock_settime" ret: "int" args: "clockid_t" "const struct timespec *" */ +#define SYS_clock_settime 88 + +/* syscall: "clock_getres" ret: "int" args: "clockid_t" "struct timespec *" */ +#define SYS_clock_getres 89 + +/* syscall: "dup2" ret: "int" args: "int" "int" */ +#define SYS_dup2 90 + +/* syscall: "nanosleep" ret: "int" args: "const struct timespec *" "struct timespec *" */ +#define SYS_nanosleep 91 + +/* syscall: "fcntl" ret: "int" args: "int" "int" "..." "void *" */ +#define SYS_fcntl 92 + +/* syscall: "accept4" ret: "int" args: "int" "struct sockaddr *" "socklen_t *" "int" */ +#define SYS_accept4 93 + +/* syscall: "__thrsleep" ret: "int" args: "const volatile void *" "clockid_t" "const struct timespec *" "void *" "const int *" */ +#define SYS___thrsleep 94 + +/* syscall: "fsync" ret: "int" args: "int" */ +#define SYS_fsync 95 + +/* syscall: "setpriority" ret: "int" args: "int" "id_t" "int" */ +#define SYS_setpriority 96 + +/* syscall: "socket" ret: "int" args: "int" "int" "int" */ +#define SYS_socket 97 + +/* syscall: "connect" ret: "int" args: "int" "const struct sockaddr *" "socklen_t" */ +#define SYS_connect 98 + +/* syscall: "getdents" ret: "int" args: "int" "void *" "size_t" */ +#define SYS_getdents 99 + +/* syscall: "getpriority" ret: "int" args: "int" "id_t" */ +#define SYS_getpriority 100 + +/* syscall: "pipe2" ret: "int" args: "int *" "int" */ +#define SYS_pipe2 101 + +/* syscall: "dup3" ret: "int" args: "int" "int" "int" */ +#define SYS_dup3 102 + +/* syscall: "sigreturn" ret: "int" args: "struct sigcontext *" */ +#define SYS_sigreturn 103 + +/* syscall: "bind" ret: "int" args: "int" "const struct sockaddr *" "socklen_t" */ +#define SYS_bind 104 + +/* syscall: "setsockopt" ret: "int" args: "int" "int" "int" "const void *" "socklen_t" */ +#define SYS_setsockopt 105 + +/* syscall: "listen" ret: "int" args: "int" "int" */ +#define SYS_listen 106 + +/* syscall: "chflagsat" ret: "int" args: "int" "const char *" "u_int" "int" */ +#define SYS_chflagsat 107 + +/* syscall: "pledge" ret: "int" args: "const char *" "const char *" */ +#define SYS_pledge 108 + +/* syscall: "ppoll" ret: "int" args: "struct pollfd *" "u_int" "const struct timespec *" "const sigset_t *" */ +#define SYS_ppoll 109 + +/* syscall: "pselect" ret: "int" args: "int" "fd_set *" "fd_set *" "fd_set *" "const struct timespec *" "const sigset_t *" */ +#define SYS_pselect 110 + +/* syscall: "sigsuspend" ret: "int" args: "int" */ +#define SYS_sigsuspend 111 + +/* syscall: "sendsyslog" ret: "int" args: "const char *" "size_t" "int" */ +#define SYS_sendsyslog 112 + +/* syscall: "unveil" ret: "int" args: "const char *" "const char *" */ +#define SYS_unveil 114 + +/* syscall: "__realpath" ret: "int" args: "const char *" "char *" */ +#define SYS___realpath 115 + +/* syscall: "recvmmsg" ret: "int" args: "int" "struct mmsghdr *" "unsigned int" "int" "struct timespec *" */ +#define SYS_recvmmsg 116 + +/* syscall: "sendmmsg" ret: "int" args: "int" "struct mmsghdr *" "unsigned int" "int" */ +#define SYS_sendmmsg 117 + +/* syscall: "getsockopt" ret: "int" args: "int" "int" "int" "void *" "socklen_t *" */ +#define SYS_getsockopt 118 + +/* syscall: "thrkill" ret: "int" args: "pid_t" "int" "void *" */ +#define SYS_thrkill 119 + +/* syscall: "readv" ret: "ssize_t" args: "int" "const struct iovec *" "int" */ +#define SYS_readv 120 + +/* syscall: "writev" ret: "ssize_t" args: "int" "const struct iovec *" "int" */ +#define SYS_writev 121 + +/* syscall: "kill" ret: "int" args: "int" "int" */ +#define SYS_kill 122 + +/* syscall: "fchown" ret: "int" args: "int" "uid_t" "gid_t" */ +#define SYS_fchown 123 + +/* syscall: "fchmod" ret: "int" args: "int" "mode_t" */ +#define SYS_fchmod 124 + + /* 125 is obsolete orecvfrom */ +/* syscall: "setreuid" ret: "int" args: "uid_t" "uid_t" */ +#define SYS_setreuid 126 + +/* syscall: "setregid" ret: "int" args: "gid_t" "gid_t" */ +#define SYS_setregid 127 + +/* syscall: "rename" ret: "int" args: "const char *" "const char *" */ +#define SYS_rename 128 + + /* 129 is obsolete otruncate */ + /* 130 is obsolete oftruncate */ +/* syscall: "flock" ret: "int" args: "int" "int" */ +#define SYS_flock 131 + +/* syscall: "mkfifo" ret: "int" args: "const char *" "mode_t" */ +#define SYS_mkfifo 132 + +/* syscall: "sendto" ret: "ssize_t" args: "int" "const void *" "size_t" "int" "const struct sockaddr *" "socklen_t" */ +#define SYS_sendto 133 + +/* syscall: "shutdown" ret: "int" args: "int" "int" */ +#define SYS_shutdown 134 + +/* syscall: "socketpair" ret: "int" args: "int" "int" "int" "int *" */ +#define SYS_socketpair 135 + +/* syscall: "mkdir" ret: "int" args: "const char *" "mode_t" */ +#define SYS_mkdir 136 + +/* syscall: "rmdir" ret: "int" args: "const char *" */ +#define SYS_rmdir 137 + + /* 138 is obsolete t32_utimes */ + /* 139 is obsolete 4.2 sigreturn */ +/* syscall: "adjtime" ret: "int" args: "const struct timeval *" "struct timeval *" */ +#define SYS_adjtime 140 + +/* syscall: "getlogin_r" ret: "int" args: "char *" "size_t" */ +#define SYS_getlogin_r 141 + +/* syscall: "getthrname" ret: "int" args: "pid_t" "char *" "size_t" */ +#define SYS_getthrname 142 + +/* syscall: "setthrname" ret: "int" args: "pid_t" "const char *" */ +#define SYS_setthrname 143 + + /* 144 is obsolete ogetrlimit */ + /* 145 is obsolete osetrlimit */ + /* 146 is obsolete pinsyscall */ +/* syscall: "setsid" ret: "int" args: */ +#define SYS_setsid 147 + +/* syscall: "quotactl" ret: "int" args: "const char *" "int" "int" "char *" */ +#define SYS_quotactl 148 + + /* 149 is obsolete oquota */ +/* syscall: "ypconnect" ret: "int" args: "int" */ +#define SYS_ypconnect 150 + +/* syscall: "nfssvc" ret: "int" args: "int" "void *" */ +#define SYS_nfssvc 155 + + /* 156 is obsolete ogetdirentries */ + /* 157 is obsolete statfs25 */ +/* syscall: "pinsyscalls" ret: "int" args: "void *" "size_t" "u_int *" "int" */ +#define SYS_pinsyscalls 158 + +/* syscall: "mimmutable" ret: "int" args: "void *" "size_t" */ +#define SYS_mimmutable 159 + +/* syscall: "waitid" ret: "int" args: "int" "id_t" "siginfo_t *" "int" */ +#define SYS_waitid 160 + +/* syscall: "getfh" ret: "int" args: "const char *" "fhandle_t *" */ +#define SYS_getfh 161 + + /* 162 is obsolete ogetdomainname */ + /* 163 is obsolete osetdomainname */ +/* syscall: "__tmpfd" ret: "int" args: "int" */ +#define SYS___tmpfd 164 + +/* syscall: "sysarch" ret: "int" args: "int" "void *" */ +#define SYS_sysarch 165 + +/* syscall: "lseek" ret: "off_t" args: "int" "off_t" "int" */ +#define SYS_lseek 166 + +/* syscall: "truncate" ret: "int" args: "const char *" "off_t" */ +#define SYS_truncate 167 + +/* syscall: "ftruncate" ret: "int" args: "int" "off_t" */ +#define SYS_ftruncate 168 + +/* syscall: "pread" ret: "ssize_t" args: "int" "void *" "size_t" "off_t" */ +#define SYS_pread 169 + +/* syscall: "pwrite" ret: "ssize_t" args: "int" "const void *" "size_t" "off_t" */ +#define SYS_pwrite 170 + +/* syscall: "preadv" ret: "ssize_t" args: "int" "const struct iovec *" "int" "off_t" */ +#define SYS_preadv 171 + +/* syscall: "pwritev" ret: "ssize_t" args: "int" "const struct iovec *" "int" "off_t" */ +#define SYS_pwritev 172 + + /* 173 is obsolete pad_pread */ + /* 174 is obsolete pad_pwrite */ +/* syscall: "profil" ret: "int" args: "void *" "size_t" "size_t" "u_long" "u_int" "int" */ +#define SYS_profil 175 + +/* syscall: "setgid" ret: "int" args: "gid_t" */ +#define SYS_setgid 181 + +/* syscall: "setegid" ret: "int" args: "gid_t" */ +#define SYS_setegid 182 + +/* syscall: "seteuid" ret: "int" args: "uid_t" */ +#define SYS_seteuid 183 + + /* 184 is obsolete lfs_bmapv */ + /* 185 is obsolete lfs_markv */ + /* 186 is obsolete lfs_segclean */ + /* 187 is obsolete lfs_segwait */ + /* 188 is obsolete stat35 */ + /* 189 is obsolete fstat35 */ +/* syscall: "pathconfat" ret: "long" args: "int" "const char *" "int" "int" */ +#define SYS_pathconfat 190 + +/* syscall: "pathconf" ret: "long" args: "const char *" "int" */ +#define SYS_pathconf 191 + +/* syscall: "fpathconf" ret: "long" args: "int" "int" */ +#define SYS_fpathconf 192 + +/* syscall: "swapctl" ret: "int" args: "int" "const void *" "int" */ +#define SYS_swapctl 193 + +/* syscall: "getrlimit" ret: "int" args: "int" "struct rlimit *" */ +#define SYS_getrlimit 194 + +/* syscall: "setrlimit" ret: "int" args: "int" "const struct rlimit *" */ +#define SYS_setrlimit 195 + + /* 196 is obsolete ogetdirentries48 */ + /* 197 is obsolete pad_mmap */ + /* 198 is obsolete __syscall */ + /* 199 is obsolete pad_lseek */ + /* 200 is obsolete pad_truncate */ + /* 201 is obsolete pad_ftruncate */ +/* syscall: "sysctl" ret: "int" args: "const int *" "u_int" "void *" "size_t *" "void *" "size_t" */ +#define SYS_sysctl 202 + +/* syscall: "mlock" ret: "int" args: "const void *" "size_t" */ +#define SYS_mlock 203 + +/* syscall: "munlock" ret: "int" args: "const void *" "size_t" */ +#define SYS_munlock 204 + + /* 206 is obsolete t32_futimes */ +/* syscall: "getpgid" ret: "pid_t" args: "pid_t" */ +#define SYS_getpgid 207 + + /* 208 is obsolete nnpfspioctl */ +/* syscall: "utrace" ret: "int" args: "const char *" "const void *" "size_t" */ +#define SYS_utrace 209 + +/* syscall: "semget" ret: "int" args: "key_t" "int" "int" */ +#define SYS_semget 221 + + /* 222 is obsolete semop35 */ + /* 223 is obsolete semconfig35 */ +/* syscall: "msgget" ret: "int" args: "key_t" "int" */ +#define SYS_msgget 225 + +/* syscall: "msgsnd" ret: "int" args: "int" "const void *" "size_t" "int" */ +#define SYS_msgsnd 226 + +/* syscall: "msgrcv" ret: "int" args: "int" "void *" "size_t" "long" "int" */ +#define SYS_msgrcv 227 + +/* syscall: "shmat" ret: "void *" args: "int" "const void *" "int" */ +#define SYS_shmat 228 + +/* syscall: "shmdt" ret: "int" args: "const void *" */ +#define SYS_shmdt 230 + + /* 231 is obsolete shmget35 */ + /* 232 is obsolete t32_clock_gettime */ + /* 233 is obsolete t32_clock_settime */ + /* 234 is obsolete t32_clock_getres */ + /* 240 is obsolete t32_nanosleep */ +/* syscall: "minherit" ret: "int" args: "void *" "size_t" "int" */ +#define SYS_minherit 250 + + /* 251 is obsolete rfork */ +/* syscall: "poll" ret: "int" args: "struct pollfd *" "u_int" "int" */ +#define SYS_poll 252 + +/* syscall: "issetugid" ret: "int" args: */ +#define SYS_issetugid 253 + +/* syscall: "lchown" ret: "int" args: "const char *" "uid_t" "gid_t" */ +#define SYS_lchown 254 + +/* syscall: "getsid" ret: "pid_t" args: "pid_t" */ +#define SYS_getsid 255 + +/* syscall: "msync" ret: "int" args: "void *" "size_t" "int" */ +#define SYS_msync 256 + + /* 257 is obsolete semctl35 */ + /* 258 is obsolete shmctl35 */ + /* 259 is obsolete msgctl35 */ +/* syscall: "pipe" ret: "int" args: "int *" */ +#define SYS_pipe 263 + +/* syscall: "fhopen" ret: "int" args: "const fhandle_t *" "int" */ +#define SYS_fhopen 264 + + /* 267 is obsolete pad_preadv */ + /* 268 is obsolete pad_pwritev */ +/* syscall: "kqueue" ret: "int" args: */ +#define SYS_kqueue 269 + +/* syscall: "kqueue1" ret: "int" args: "int" */ +#define SYS_kqueue1 270 + +/* syscall: "mlockall" ret: "int" args: "int" */ +#define SYS_mlockall 271 + +/* syscall: "munlockall" ret: "int" args: */ +#define SYS_munlockall 272 + +/* syscall: "getresuid" ret: "int" args: "uid_t *" "uid_t *" "uid_t *" */ +#define SYS_getresuid 281 + +/* syscall: "setresuid" ret: "int" args: "uid_t" "uid_t" "uid_t" */ +#define SYS_setresuid 282 + +/* syscall: "getresgid" ret: "int" args: "gid_t *" "gid_t *" "gid_t *" */ +#define SYS_getresgid 283 + +/* syscall: "setresgid" ret: "int" args: "gid_t" "gid_t" "gid_t" */ +#define SYS_setresgid 284 + + /* 285 is obsolete sys_omquery */ + /* 286 is obsolete pad_mquery */ +/* syscall: "closefrom" ret: "int" args: "int" */ +#define SYS_closefrom 287 + +/* syscall: "sigaltstack" ret: "int" args: "const struct sigaltstack *" "struct sigaltstack *" */ +#define SYS_sigaltstack 288 + +/* syscall: "shmget" ret: "int" args: "key_t" "size_t" "int" */ +#define SYS_shmget 289 + +/* syscall: "semop" ret: "int" args: "int" "struct sembuf *" "size_t" */ +#define SYS_semop 290 + + /* 291 is obsolete t32_stat */ + /* 292 is obsolete t32_fstat */ + /* 293 is obsolete t32_lstat */ +/* syscall: "fhstat" ret: "int" args: "const fhandle_t *" "struct stat *" */ +#define SYS_fhstat 294 + +/* syscall: "__semctl" ret: "int" args: "int" "int" "int" "union semun *" */ +#define SYS___semctl 295 + +/* syscall: "shmctl" ret: "int" args: "int" "int" "struct shmid_ds *" */ +#define SYS_shmctl 296 + +/* syscall: "msgctl" ret: "int" args: "int" "int" "struct msqid_ds *" */ +#define SYS_msgctl 297 + +/* syscall: "sched_yield" ret: "int" args: */ +#define SYS_sched_yield 298 + +/* syscall: "getthrid" ret: "pid_t" args: */ +#define SYS_getthrid 299 + + /* 300 is obsolete t32___thrsleep */ +/* syscall: "__thrwakeup" ret: "int" args: "const volatile void *" "int" */ +#define SYS___thrwakeup 301 + +/* syscall: "__threxit" ret: "void" args: "pid_t *" */ +#define SYS___threxit 302 + +/* syscall: "__thrsigdivert" ret: "int" args: "sigset_t" "siginfo_t *" "const struct timespec *" */ +#define SYS___thrsigdivert 303 + +/* syscall: "__getcwd" ret: "int" args: "char *" "size_t" */ +#define SYS___getcwd 304 + +/* syscall: "adjfreq" ret: "int" args: "const int64_t *" "int64_t *" */ +#define SYS_adjfreq 305 + + /* 306 is obsolete getfsstat53 */ + /* 307 is obsolete statfs53 */ + /* 308 is obsolete fstatfs53 */ + /* 309 is obsolete fhstatfs53 */ +/* syscall: "setrtable" ret: "int" args: "int" */ +#define SYS_setrtable 310 + +/* syscall: "getrtable" ret: "int" args: */ +#define SYS_getrtable 311 + + /* 312 is obsolete t32_getdirentries */ +/* syscall: "faccessat" ret: "int" args: "int" "const char *" "int" "int" */ +#define SYS_faccessat 313 + +/* syscall: "fchmodat" ret: "int" args: "int" "const char *" "mode_t" "int" */ +#define SYS_fchmodat 314 + +/* syscall: "fchownat" ret: "int" args: "int" "const char *" "uid_t" "gid_t" "int" */ +#define SYS_fchownat 315 + + /* 316 is obsolete t32_fstatat */ +/* syscall: "linkat" ret: "int" args: "int" "const char *" "int" "const char *" "int" */ +#define SYS_linkat 317 + +/* syscall: "mkdirat" ret: "int" args: "int" "const char *" "mode_t" */ +#define SYS_mkdirat 318 + +/* syscall: "mkfifoat" ret: "int" args: "int" "const char *" "mode_t" */ +#define SYS_mkfifoat 319 + +/* syscall: "mknodat" ret: "int" args: "int" "const char *" "mode_t" "dev_t" */ +#define SYS_mknodat 320 + +/* syscall: "openat" ret: "int" args: "int" "const char *" "int" "..." "mode_t" */ +#define SYS_openat 321 + +/* syscall: "readlinkat" ret: "ssize_t" args: "int" "const char *" "char *" "size_t" */ +#define SYS_readlinkat 322 + +/* syscall: "renameat" ret: "int" args: "int" "const char *" "int" "const char *" */ +#define SYS_renameat 323 + +/* syscall: "symlinkat" ret: "int" args: "const char *" "int" "const char *" */ +#define SYS_symlinkat 324 + +/* syscall: "unlinkat" ret: "int" args: "int" "const char *" "int" */ +#define SYS_unlinkat 325 + + /* 326 is obsolete t32_utimensat */ + /* 327 is obsolete t32_futimens */ + /* 328 is obsolete __tfork51 */ +/* syscall: "__set_tcb" ret: "void" args: "void *" */ +#define SYS___set_tcb 329 + +/* syscall: "__get_tcb" ret: "void *" args: */ +#define SYS___get_tcb 330 + +#define SYS_MAXSYSCALL 331 \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/syscall_mi.h b/lib/libc/include/generic-openbsd/sys/syscall_mi.h new file mode 100644 index 000000000000..f633a55fe6e9 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/syscall_mi.h @@ -0,0 +1,259 @@ +/* $OpenBSD: syscall_mi.h,v 1.37 2024/12/27 11:57:16 mpi Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)kern_xxx.c 8.2 (Berkeley) 11/14/93 + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef KTRACE +#include +#endif + +#include "dt.h" +#if NDT > 0 +#include +#endif + +/* + * Check if a system call is entered from precisely correct location + */ +static inline int +pin_check(struct proc *p, register_t code) +{ + extern char sigcodecall[], sigcoderet[], sigcodecall[]; + struct pinsyscall *pin = NULL, *ppin, *plibcpin; + struct process *pr = p->p_p; + vaddr_t addr; + int error = 0; + + /* point at start of syscall instruction */ + addr = (vaddr_t)PROC_PC(p) - (vaddr_t)(sigcoderet - sigcodecall); + ppin = &pr->ps_pin; + plibcpin = &pr->ps_libcpin; + + /* + * System calls come from the following places, checks are ordered + * by most common case: + * 1) dynamic binary: syscalls in libc.so (in the ps_libcpin region) + * 2a) static binary: syscalls in main program (in the ps_pin region) + * 2b) dynamic binary: syscalls in ld.so (in the ps_pin region) + * 3) sigtramp, containing only sigreturn(2) + */ + if (plibcpin->pn_pins && + addr >= plibcpin->pn_start && addr < plibcpin->pn_end) + pin = plibcpin; + else if (ppin->pn_pins && + addr >= ppin->pn_start && addr < ppin->pn_end) + pin = ppin; + else if (PROC_PC(p) == pr->ps_sigcoderet) { + if (code == SYS_sigreturn) + return (0); + error = EPERM; + goto die; + } + if (pin) { + if (code >= pin->pn_npins || pin->pn_pins[code] == 0) + error = ENOSYS; + else if (pin->pn_pins[code] + pin->pn_start == addr) + ; /* correct location */ + else if (pin->pn_pins[code] == (u_int)-1) + ; /* multiple locations, hopefully a boring operation */ + else + error = ENOSYS; + } else + error = ENOSYS; + if (error == 0) + return (0); +die: +#ifdef KTRACE + if (KTRPOINT(p, KTR_PINSYSCALL)) + ktrpinsyscall(p, error, code, addr); +#endif + KERNEL_LOCK(); + /* XXX remove or simplify this uprintf() call after OpenBSD 7.5 release */ + uprintf("%s[%d]: pinsyscalls addr %lx code %ld, pinoff 0x%x " + "(pin%s %d %lx-%lx %lx) (libcpin%s %d %lx-%lx %lx) error %d\n", + p->p_p->ps_comm, p->p_p->ps_pid, addr, code, + (pin && code < pin->pn_npins) ? pin->pn_pins[code] : -1, + pin == ppin ? "(Y)" : "", ppin->pn_npins, + ppin->pn_start, ppin->pn_end, ppin->pn_end - ppin->pn_start, + pin == plibcpin ? "(Y)" : "", plibcpin->pn_npins, + plibcpin->pn_start, plibcpin->pn_end, plibcpin->pn_end - plibcpin->pn_start, + error); + p->p_p->ps_acflag |= APINSYS; + + /* Try to stop threads immediately, because this process is suspect */ + if (P_HASSIBLING(p)) + single_thread_set(p, SINGLE_UNWIND | SINGLE_DEEP); + /* Send uncatchable SIGABRT for coredump */ + sigabort(p); + KERNEL_UNLOCK(); + return (error); +} + +/* + * The MD setup for a system call has been done; here's the MI part. + */ +static inline int +mi_syscall(struct proc *p, register_t code, const struct sysent *callp, + register_t *argp, register_t retval[2]) +{ + uint64_t tval; + int lock = !(callp->sy_flags & SY_NOLOCK); + int error, pledged; + + /* refresh the thread's cache of the process's creds */ + refreshcreds(p); + +#ifdef SYSCALL_DEBUG + KERNEL_LOCK(); + scdebug_call(p, code, argp); + KERNEL_UNLOCK(); +#endif + TRACEPOINT(raw_syscalls, sys_enter, code, NULL); +#if NDT > 0 + DT_ENTER(syscall, code, callp->sy_argsize, argp); +#endif +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSCALL)) { + /* convert to mask, then include with code */ + ktrsyscall(p, code, callp->sy_argsize, argp); + } +#endif + + /* SP must be within MAP_STACK space */ + if (!uvm_map_inentry(p, &p->p_spinentry, PROC_STACK(p), + "[%s]%d/%d sp=%lx inside %lx-%lx: not MAP_STACK\n", + uvm_map_inentry_sp, p->p_vmspace->vm_map.sserial)) + return (EPERM); + + if ((error = pin_check(p, code))) + return (error); + + pledged = (p->p_p->ps_flags & PS_PLEDGE); + if (pledged && (error = pledge_syscall(p, code, &tval))) { + KERNEL_LOCK(); + error = pledge_fail(p, error, tval); + KERNEL_UNLOCK(); + return (error); + } + if (lock) + KERNEL_LOCK(); + error = (*callp->sy_call)(p, argp, retval); + if (lock) + KERNEL_UNLOCK(); + + return (error); +} + +/* + * Finish MI stuff on return, after the registers have been set + */ +static inline void +mi_syscall_return(struct proc *p, register_t code, int error, + const register_t retval[2]) +{ +#ifdef SYSCALL_DEBUG + KERNEL_LOCK(); + scdebug_ret(p, code, error, retval); + KERNEL_UNLOCK(); +#endif +#if NDT > 0 + DT_LEAVE(syscall, code, error, retval[0], retval[1]); +#endif + TRACEPOINT(raw_syscalls, sys_exit, code, NULL); + + userret(p); + +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSRET)) + ktrsysret(p, code, error, retval); +#endif +} + +/* + * Finish MI stuff for a new process/thread to return + */ +static inline void +mi_child_return(struct proc *p) +{ +#if defined(SYSCALL_DEBUG) || defined(KTRACE) || NDT > 0 + int code = (p->p_flag & P_THREAD) ? SYS___tfork : + (p->p_p->ps_flags & PS_PPWAIT) ? SYS_vfork : SYS_fork; + const register_t child_retval[2] = { 0, 1 }; +#endif + + TRACEPOINT(sched, on__cpu, NULL); + +#ifdef SYSCALL_DEBUG + KERNEL_LOCK(); + scdebug_ret(p, code, 0, child_retval); + KERNEL_UNLOCK(); +#endif +#if NDT > 0 + DT_LEAVE(syscall, code, 0, child_retval[0], child_retval[1]); +#endif + TRACEPOINT(raw_syscalls, sys_exit, code, NULL); + + userret(p); + +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSRET)) + ktrsysret(p, code, 0, child_retval); +#endif +} + +/* + * Do the specific processing necessary for an AST + */ +static inline void +mi_ast(struct proc *p, int resched) +{ + if (p->p_flag & P_OWEUPC) { + KERNEL_LOCK(); + ADDUPROF(p); + KERNEL_UNLOCK(); + } + if (resched) + preempt(); + + /* + * XXX could move call to userret() here, but + * hppa calls ast() in syscall return and sh calls + * it after userret() + */ +} \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/syscallargs.h b/lib/libc/include/generic-openbsd/sys/syscallargs.h new file mode 100644 index 000000000000..62f9a6d1e33b --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/syscallargs.h @@ -0,0 +1,1419 @@ +/* $OpenBSD: syscallargs.h,v 1.286 2025/05/24 06:50:02 deraadt Exp $ */ + +/* + * System call argument lists. + * + * DO NOT EDIT-- this file is automatically generated. + * created from; OpenBSD: syscalls.master,v 1.270 2025/05/24 06:49:16 deraadt Exp + */ + +#ifdef syscallarg +#undef syscallarg +#endif + +#define syscallarg(x) \ + union { \ + register_t pad; \ + struct { x datum; } le; \ + struct { \ + int8_t pad[ (sizeof (register_t) < sizeof (x)) \ + ? 0 \ + : sizeof (register_t) - sizeof (x)]; \ + x datum; \ + } be; \ + } + +struct sys_exit_args { + syscallarg(int) rval; +}; + +struct sys_read_args { + syscallarg(int) fd; + syscallarg(void *) buf; + syscallarg(size_t) nbyte; +}; + +struct sys_write_args { + syscallarg(int) fd; + syscallarg(const void *) buf; + syscallarg(size_t) nbyte; +}; + +struct sys_open_args { + syscallarg(const char *) path; + syscallarg(int) flags; + syscallarg(mode_t) mode; +}; + +struct sys_close_args { + syscallarg(int) fd; +}; + +struct sys_getentropy_args { + syscallarg(void *) buf; + syscallarg(size_t) nbyte; +}; + +struct sys___tfork_args { + syscallarg(const struct __tfork *) param; + syscallarg(size_t) psize; +}; + +struct sys_link_args { + syscallarg(const char *) path; + syscallarg(const char *) link; +}; + +struct sys_unlink_args { + syscallarg(const char *) path; +}; + +struct sys_wait4_args { + syscallarg(pid_t) pid; + syscallarg(int *) status; + syscallarg(int) options; + syscallarg(struct rusage *) rusage; +}; + +struct sys_chdir_args { + syscallarg(const char *) path; +}; + +struct sys_fchdir_args { + syscallarg(int) fd; +}; + +struct sys_mknod_args { + syscallarg(const char *) path; + syscallarg(mode_t) mode; + syscallarg(dev_t) dev; +}; + +struct sys_chmod_args { + syscallarg(const char *) path; + syscallarg(mode_t) mode; +}; + +struct sys_chown_args { + syscallarg(const char *) path; + syscallarg(uid_t) uid; + syscallarg(gid_t) gid; +}; + +struct sys_obreak_args { + syscallarg(char *) nsize; +}; + +struct sys_getrusage_args { + syscallarg(int) who; + syscallarg(struct rusage *) rusage; +}; + +struct sys_mount_args { + syscallarg(const char *) type; + syscallarg(const char *) path; + syscallarg(int) flags; + syscallarg(void *) data; +}; + +struct sys_unmount_args { + syscallarg(const char *) path; + syscallarg(int) flags; +}; + +struct sys_setuid_args { + syscallarg(uid_t) uid; +}; + +struct sys_ptrace_args { + syscallarg(int) req; + syscallarg(pid_t) pid; + syscallarg(caddr_t) addr; + syscallarg(int) data; +}; + +struct sys_recvmsg_args { + syscallarg(int) s; + syscallarg(struct msghdr *) msg; + syscallarg(int) flags; +}; + +struct sys_sendmsg_args { + syscallarg(int) s; + syscallarg(const struct msghdr *) msg; + syscallarg(int) flags; +}; + +struct sys_recvfrom_args { + syscallarg(int) s; + syscallarg(void *) buf; + syscallarg(size_t) len; + syscallarg(int) flags; + syscallarg(struct sockaddr *) from; + syscallarg(socklen_t *) fromlenaddr; +}; + +struct sys_accept_args { + syscallarg(int) s; + syscallarg(struct sockaddr *) name; + syscallarg(socklen_t *) anamelen; +}; + +struct sys_getpeername_args { + syscallarg(int) fdes; + syscallarg(struct sockaddr *) asa; + syscallarg(socklen_t *) alen; +}; + +struct sys_getsockname_args { + syscallarg(int) fdes; + syscallarg(struct sockaddr *) asa; + syscallarg(socklen_t *) alen; +}; + +struct sys_access_args { + syscallarg(const char *) path; + syscallarg(int) amode; +}; + +struct sys_chflags_args { + syscallarg(const char *) path; + syscallarg(u_int) flags; +}; + +struct sys_fchflags_args { + syscallarg(int) fd; + syscallarg(u_int) flags; +}; + +struct sys_stat_args { + syscallarg(const char *) path; + syscallarg(struct stat *) ub; +}; + +struct sys_lstat_args { + syscallarg(const char *) path; + syscallarg(struct stat *) ub; +}; + +struct sys_dup_args { + syscallarg(int) fd; +}; + +struct sys_fstatat_args { + syscallarg(int) fd; + syscallarg(const char *) path; + syscallarg(struct stat *) buf; + syscallarg(int) flag; +}; + +struct sys_ktrace_args { + syscallarg(const char *) fname; + syscallarg(int) ops; + syscallarg(int) facs; + syscallarg(pid_t) pid; +}; + +struct sys_sigaction_args { + syscallarg(int) signum; + syscallarg(const struct sigaction *) nsa; + syscallarg(struct sigaction *) osa; +}; + +struct sys_sigprocmask_args { + syscallarg(int) how; + syscallarg(sigset_t) mask; +}; + +struct sys_mmap_args { + syscallarg(void *) addr; + syscallarg(size_t) len; + syscallarg(int) prot; + syscallarg(int) flags; + syscallarg(int) fd; + syscallarg(off_t) pos; +}; + +struct sys_setlogin_args { + syscallarg(const char *) namebuf; +}; + +struct sys_acct_args { + syscallarg(const char *) path; +}; + +struct sys_fstat_args { + syscallarg(int) fd; + syscallarg(struct stat *) sb; +}; + +struct sys_ioctl_args { + syscallarg(int) fd; + syscallarg(u_long) com; + syscallarg(void *) data; +}; + +struct sys_reboot_args { + syscallarg(int) opt; +}; + +struct sys_revoke_args { + syscallarg(const char *) path; +}; + +struct sys_symlink_args { + syscallarg(const char *) path; + syscallarg(const char *) link; +}; + +struct sys_readlink_args { + syscallarg(const char *) path; + syscallarg(char *) buf; + syscallarg(size_t) count; +}; + +struct sys_execve_args { + syscallarg(const char *) path; + syscallarg(char *const *) argp; + syscallarg(char *const *) envp; +}; + +struct sys_umask_args { + syscallarg(mode_t) newmask; +}; + +struct sys_chroot_args { + syscallarg(const char *) path; +}; + +struct sys_getfsstat_args { + syscallarg(struct statfs *) buf; + syscallarg(size_t) bufsize; + syscallarg(int) flags; +}; + +struct sys_statfs_args { + syscallarg(const char *) path; + syscallarg(struct statfs *) buf; +}; + +struct sys_fstatfs_args { + syscallarg(int) fd; + syscallarg(struct statfs *) buf; +}; + +struct sys_fhstatfs_args { + syscallarg(const fhandle_t *) fhp; + syscallarg(struct statfs *) buf; +}; + +struct sys_gettimeofday_args { + syscallarg(struct timeval *) tp; + syscallarg(struct timezone *) tzp; +}; + +struct sys_settimeofday_args { + syscallarg(const struct timeval *) tv; + syscallarg(const struct timezone *) tzp; +}; + +struct sys_setitimer_args { + syscallarg(int) which; + syscallarg(const struct itimerval *) itv; + syscallarg(struct itimerval *) oitv; +}; + +struct sys_getitimer_args { + syscallarg(int) which; + syscallarg(struct itimerval *) itv; +}; + +struct sys_select_args { + syscallarg(int) nd; + syscallarg(fd_set *) in; + syscallarg(fd_set *) ou; + syscallarg(fd_set *) ex; + syscallarg(struct timeval *) tv; +}; + +struct sys_kevent_args { + syscallarg(int) fd; + syscallarg(const struct kevent *) changelist; + syscallarg(int) nchanges; + syscallarg(struct kevent *) eventlist; + syscallarg(int) nevents; + syscallarg(const struct timespec *) timeout; +}; + +struct sys_munmap_args { + syscallarg(void *) addr; + syscallarg(size_t) len; +}; + +struct sys_mprotect_args { + syscallarg(void *) addr; + syscallarg(size_t) len; + syscallarg(int) prot; +}; + +struct sys_madvise_args { + syscallarg(void *) addr; + syscallarg(size_t) len; + syscallarg(int) behav; +}; + +struct sys_utimes_args { + syscallarg(const char *) path; + syscallarg(const struct timeval *) tptr; +}; + +struct sys_futimes_args { + syscallarg(int) fd; + syscallarg(const struct timeval *) tptr; +}; + +struct sys_mquery_args { + syscallarg(void *) addr; + syscallarg(size_t) len; + syscallarg(int) prot; + syscallarg(int) flags; + syscallarg(int) fd; + syscallarg(off_t) pos; +}; + +struct sys_getgroups_args { + syscallarg(int) gidsetsize; + syscallarg(gid_t *) gidset; +}; + +struct sys_setgroups_args { + syscallarg(int) gidsetsize; + syscallarg(const gid_t *) gidset; +}; + +struct sys_setpgid_args { + syscallarg(pid_t) pid; + syscallarg(pid_t) pgid; +}; + +struct sys_futex_args { + syscallarg(uint32_t *) f; + syscallarg(int) op; + syscallarg(int) val; + syscallarg(const struct timespec *) timeout; + syscallarg(uint32_t *) g; +}; + +struct sys_utimensat_args { + syscallarg(int) fd; + syscallarg(const char *) path; + syscallarg(const struct timespec *) times; + syscallarg(int) flag; +}; + +struct sys_futimens_args { + syscallarg(int) fd; + syscallarg(const struct timespec *) times; +}; + +struct sys_kbind_args { + syscallarg(const struct __kbind *) param; + syscallarg(size_t) psize; + syscallarg(int64_t) proc_cookie; +}; + +struct sys_clock_gettime_args { + syscallarg(clockid_t) clock_id; + syscallarg(struct timespec *) tp; +}; + +struct sys_clock_settime_args { + syscallarg(clockid_t) clock_id; + syscallarg(const struct timespec *) tp; +}; + +struct sys_clock_getres_args { + syscallarg(clockid_t) clock_id; + syscallarg(struct timespec *) tp; +}; + +struct sys_dup2_args { + syscallarg(int) from; + syscallarg(int) to; +}; + +struct sys_nanosleep_args { + syscallarg(const struct timespec *) rqtp; + syscallarg(struct timespec *) rmtp; +}; + +struct sys_fcntl_args { + syscallarg(int) fd; + syscallarg(int) cmd; + syscallarg(void *) arg; +}; + +struct sys_accept4_args { + syscallarg(int) s; + syscallarg(struct sockaddr *) name; + syscallarg(socklen_t *) anamelen; + syscallarg(int) flags; +}; + +struct sys___thrsleep_args { + syscallarg(const volatile void *) ident; + syscallarg(clockid_t) clock_id; + syscallarg(const struct timespec *) tp; + syscallarg(void *) lock; + syscallarg(const int *) abort; +}; + +struct sys_fsync_args { + syscallarg(int) fd; +}; + +struct sys_setpriority_args { + syscallarg(int) which; + syscallarg(id_t) who; + syscallarg(int) prio; +}; + +struct sys_socket_args { + syscallarg(int) domain; + syscallarg(int) type; + syscallarg(int) protocol; +}; + +struct sys_connect_args { + syscallarg(int) s; + syscallarg(const struct sockaddr *) name; + syscallarg(socklen_t) namelen; +}; + +struct sys_getdents_args { + syscallarg(int) fd; + syscallarg(void *) buf; + syscallarg(size_t) buflen; +}; + +struct sys_getpriority_args { + syscallarg(int) which; + syscallarg(id_t) who; +}; + +struct sys_pipe2_args { + syscallarg(int *) fdp; + syscallarg(int) flags; +}; + +struct sys_dup3_args { + syscallarg(int) from; + syscallarg(int) to; + syscallarg(int) flags; +}; + +struct sys_sigreturn_args { + syscallarg(struct sigcontext *) sigcntxp; +}; + +struct sys_bind_args { + syscallarg(int) s; + syscallarg(const struct sockaddr *) name; + syscallarg(socklen_t) namelen; +}; + +struct sys_setsockopt_args { + syscallarg(int) s; + syscallarg(int) level; + syscallarg(int) name; + syscallarg(const void *) val; + syscallarg(socklen_t) valsize; +}; + +struct sys_listen_args { + syscallarg(int) s; + syscallarg(int) backlog; +}; + +struct sys_chflagsat_args { + syscallarg(int) fd; + syscallarg(const char *) path; + syscallarg(u_int) flags; + syscallarg(int) atflags; +}; + +struct sys_pledge_args { + syscallarg(const char *) promises; + syscallarg(const char *) execpromises; +}; + +struct sys_ppoll_args { + syscallarg(struct pollfd *) fds; + syscallarg(u_int) nfds; + syscallarg(const struct timespec *) ts; + syscallarg(const sigset_t *) mask; +}; + +struct sys_pselect_args { + syscallarg(int) nd; + syscallarg(fd_set *) in; + syscallarg(fd_set *) ou; + syscallarg(fd_set *) ex; + syscallarg(const struct timespec *) ts; + syscallarg(const sigset_t *) mask; +}; + +struct sys_sigsuspend_args { + syscallarg(int) mask; +}; + +struct sys_sendsyslog_args { + syscallarg(const char *) buf; + syscallarg(size_t) nbyte; + syscallarg(int) flags; +}; + +struct sys_unveil_args { + syscallarg(const char *) path; + syscallarg(const char *) permissions; +}; + +struct sys___realpath_args { + syscallarg(const char *) pathname; + syscallarg(char *) resolved; +}; + +struct sys_recvmmsg_args { + syscallarg(int) s; + syscallarg(struct mmsghdr *) mmsg; + syscallarg(unsigned int) vlen; + syscallarg(int) flags; + syscallarg(struct timespec *) timeout; +}; + +struct sys_sendmmsg_args { + syscallarg(int) s; + syscallarg(struct mmsghdr *) mmsg; + syscallarg(unsigned int) vlen; + syscallarg(int) flags; +}; + +struct sys_getsockopt_args { + syscallarg(int) s; + syscallarg(int) level; + syscallarg(int) name; + syscallarg(void *) val; + syscallarg(socklen_t *) avalsize; +}; + +struct sys_thrkill_args { + syscallarg(pid_t) tid; + syscallarg(int) signum; + syscallarg(void *) tcb; +}; + +struct sys_readv_args { + syscallarg(int) fd; + syscallarg(const struct iovec *) iovp; + syscallarg(int) iovcnt; +}; + +struct sys_writev_args { + syscallarg(int) fd; + syscallarg(const struct iovec *) iovp; + syscallarg(int) iovcnt; +}; + +struct sys_kill_args { + syscallarg(int) pid; + syscallarg(int) signum; +}; + +struct sys_fchown_args { + syscallarg(int) fd; + syscallarg(uid_t) uid; + syscallarg(gid_t) gid; +}; + +struct sys_fchmod_args { + syscallarg(int) fd; + syscallarg(mode_t) mode; +}; + +struct sys_setreuid_args { + syscallarg(uid_t) ruid; + syscallarg(uid_t) euid; +}; + +struct sys_setregid_args { + syscallarg(gid_t) rgid; + syscallarg(gid_t) egid; +}; + +struct sys_rename_args { + syscallarg(const char *) from; + syscallarg(const char *) to; +}; + +struct sys_flock_args { + syscallarg(int) fd; + syscallarg(int) how; +}; + +struct sys_mkfifo_args { + syscallarg(const char *) path; + syscallarg(mode_t) mode; +}; + +struct sys_sendto_args { + syscallarg(int) s; + syscallarg(const void *) buf; + syscallarg(size_t) len; + syscallarg(int) flags; + syscallarg(const struct sockaddr *) to; + syscallarg(socklen_t) tolen; +}; + +struct sys_shutdown_args { + syscallarg(int) s; + syscallarg(int) how; +}; + +struct sys_socketpair_args { + syscallarg(int) domain; + syscallarg(int) type; + syscallarg(int) protocol; + syscallarg(int *) rsv; +}; + +struct sys_mkdir_args { + syscallarg(const char *) path; + syscallarg(mode_t) mode; +}; + +struct sys_rmdir_args { + syscallarg(const char *) path; +}; + +struct sys_adjtime_args { + syscallarg(const struct timeval *) delta; + syscallarg(struct timeval *) olddelta; +}; + +struct sys_getlogin_r_args { + syscallarg(char *) namebuf; + syscallarg(size_t) namelen; +}; + +struct sys_getthrname_args { + syscallarg(pid_t) tid; + syscallarg(char *) name; + syscallarg(size_t) len; +}; + +struct sys_setthrname_args { + syscallarg(pid_t) tid; + syscallarg(const char *) name; +}; + +struct sys_quotactl_args { + syscallarg(const char *) path; + syscallarg(int) cmd; + syscallarg(int) uid; + syscallarg(char *) arg; +}; + +struct sys_ypconnect_args { + syscallarg(int) type; +}; + +struct sys_nfssvc_args { + syscallarg(int) flag; + syscallarg(void *) argp; +}; + +struct sys_pinsyscalls_args { + syscallarg(void *) base; + syscallarg(size_t) len; + syscallarg(u_int *) pins; + syscallarg(int) npins; +}; + +struct sys_mimmutable_args { + syscallarg(void *) addr; + syscallarg(size_t) len; +}; + +struct sys_waitid_args { + syscallarg(int) idtype; + syscallarg(id_t) id; + syscallarg(siginfo_t *) info; + syscallarg(int) options; +}; + +struct sys_getfh_args { + syscallarg(const char *) fname; + syscallarg(fhandle_t *) fhp; +}; + +struct sys___tmpfd_args { + syscallarg(int) flags; +}; + +struct sys_sysarch_args { + syscallarg(int) op; + syscallarg(void *) parms; +}; + +struct sys_lseek_args { + syscallarg(int) fd; + syscallarg(off_t) offset; + syscallarg(int) whence; +}; + +struct sys_truncate_args { + syscallarg(const char *) path; + syscallarg(off_t) length; +}; + +struct sys_ftruncate_args { + syscallarg(int) fd; + syscallarg(off_t) length; +}; + +struct sys_pread_args { + syscallarg(int) fd; + syscallarg(void *) buf; + syscallarg(size_t) nbyte; + syscallarg(off_t) offset; +}; + +struct sys_pwrite_args { + syscallarg(int) fd; + syscallarg(const void *) buf; + syscallarg(size_t) nbyte; + syscallarg(off_t) offset; +}; + +struct sys_preadv_args { + syscallarg(int) fd; + syscallarg(const struct iovec *) iovp; + syscallarg(int) iovcnt; + syscallarg(off_t) offset; +}; + +struct sys_pwritev_args { + syscallarg(int) fd; + syscallarg(const struct iovec *) iovp; + syscallarg(int) iovcnt; + syscallarg(off_t) offset; +}; + +struct sys_profil_args { + syscallarg(void *) buf; + syscallarg(size_t) buflen; + syscallarg(size_t) samplesize; + syscallarg(u_long) offset; + syscallarg(u_int) scale; + syscallarg(int) dirfd; +}; + +struct sys_setgid_args { + syscallarg(gid_t) gid; +}; + +struct sys_setegid_args { + syscallarg(gid_t) egid; +}; + +struct sys_seteuid_args { + syscallarg(uid_t) euid; +}; + +struct sys_pathconfat_args { + syscallarg(int) fd; + syscallarg(const char *) path; + syscallarg(int) name; + syscallarg(int) flag; +}; + +struct sys_pathconf_args { + syscallarg(const char *) path; + syscallarg(int) name; +}; + +struct sys_fpathconf_args { + syscallarg(int) fd; + syscallarg(int) name; +}; + +struct sys_swapctl_args { + syscallarg(int) cmd; + syscallarg(const void *) arg; + syscallarg(int) misc; +}; + +struct sys_getrlimit_args { + syscallarg(int) which; + syscallarg(struct rlimit *) rlp; +}; + +struct sys_setrlimit_args { + syscallarg(int) which; + syscallarg(const struct rlimit *) rlp; +}; + +struct sys_sysctl_args { + syscallarg(const int *) name; + syscallarg(u_int) namelen; + syscallarg(void *) old; + syscallarg(size_t *) oldlenp; + syscallarg(void *) new; + syscallarg(size_t) newlen; +}; + +struct sys_mlock_args { + syscallarg(const void *) addr; + syscallarg(size_t) len; +}; + +struct sys_munlock_args { + syscallarg(const void *) addr; + syscallarg(size_t) len; +}; + +struct sys_getpgid_args { + syscallarg(pid_t) pid; +}; + +struct sys_utrace_args { + syscallarg(const char *) label; + syscallarg(const void *) addr; + syscallarg(size_t) len; +}; + +struct sys_semget_args { + syscallarg(key_t) key; + syscallarg(int) nsems; + syscallarg(int) semflg; +}; + +struct sys_msgget_args { + syscallarg(key_t) key; + syscallarg(int) msgflg; +}; + +struct sys_msgsnd_args { + syscallarg(int) msqid; + syscallarg(const void *) msgp; + syscallarg(size_t) msgsz; + syscallarg(int) msgflg; +}; + +struct sys_msgrcv_args { + syscallarg(int) msqid; + syscallarg(void *) msgp; + syscallarg(size_t) msgsz; + syscallarg(long) msgtyp; + syscallarg(int) msgflg; +}; + +struct sys_shmat_args { + syscallarg(int) shmid; + syscallarg(const void *) shmaddr; + syscallarg(int) shmflg; +}; + +struct sys_shmdt_args { + syscallarg(const void *) shmaddr; +}; + +struct sys_minherit_args { + syscallarg(void *) addr; + syscallarg(size_t) len; + syscallarg(int) inherit; +}; + +struct sys_poll_args { + syscallarg(struct pollfd *) fds; + syscallarg(u_int) nfds; + syscallarg(int) timeout; +}; + +struct sys_lchown_args { + syscallarg(const char *) path; + syscallarg(uid_t) uid; + syscallarg(gid_t) gid; +}; + +struct sys_getsid_args { + syscallarg(pid_t) pid; +}; + +struct sys_msync_args { + syscallarg(void *) addr; + syscallarg(size_t) len; + syscallarg(int) flags; +}; + +struct sys_pipe_args { + syscallarg(int *) fdp; +}; + +struct sys_fhopen_args { + syscallarg(const fhandle_t *) fhp; + syscallarg(int) flags; +}; + +struct sys_kqueue1_args { + syscallarg(int) flags; +}; + +struct sys_mlockall_args { + syscallarg(int) flags; +}; + +struct sys_getresuid_args { + syscallarg(uid_t *) ruid; + syscallarg(uid_t *) euid; + syscallarg(uid_t *) suid; +}; + +struct sys_setresuid_args { + syscallarg(uid_t) ruid; + syscallarg(uid_t) euid; + syscallarg(uid_t) suid; +}; + +struct sys_getresgid_args { + syscallarg(gid_t *) rgid; + syscallarg(gid_t *) egid; + syscallarg(gid_t *) sgid; +}; + +struct sys_setresgid_args { + syscallarg(gid_t) rgid; + syscallarg(gid_t) egid; + syscallarg(gid_t) sgid; +}; + +struct sys_closefrom_args { + syscallarg(int) fd; +}; + +struct sys_sigaltstack_args { + syscallarg(const struct sigaltstack *) nss; + syscallarg(struct sigaltstack *) oss; +}; + +struct sys_shmget_args { + syscallarg(key_t) key; + syscallarg(size_t) size; + syscallarg(int) shmflg; +}; + +struct sys_semop_args { + syscallarg(int) semid; + syscallarg(struct sembuf *) sops; + syscallarg(size_t) nsops; +}; + +struct sys_fhstat_args { + syscallarg(const fhandle_t *) fhp; + syscallarg(struct stat *) sb; +}; + +struct sys___semctl_args { + syscallarg(int) semid; + syscallarg(int) semnum; + syscallarg(int) cmd; + syscallarg(union semun *) arg; +}; + +struct sys_shmctl_args { + syscallarg(int) shmid; + syscallarg(int) cmd; + syscallarg(struct shmid_ds *) buf; +}; + +struct sys_msgctl_args { + syscallarg(int) msqid; + syscallarg(int) cmd; + syscallarg(struct msqid_ds *) buf; +}; + +struct sys___thrwakeup_args { + syscallarg(const volatile void *) ident; + syscallarg(int) n; +}; + +struct sys___threxit_args { + syscallarg(pid_t *) notdead; +}; + +struct sys___thrsigdivert_args { + syscallarg(sigset_t) sigmask; + syscallarg(siginfo_t *) info; + syscallarg(const struct timespec *) timeout; +}; + +struct sys___getcwd_args { + syscallarg(char *) buf; + syscallarg(size_t) len; +}; + +struct sys_adjfreq_args { + syscallarg(const int64_t *) freq; + syscallarg(int64_t *) oldfreq; +}; + +struct sys_setrtable_args { + syscallarg(int) rtableid; +}; + +struct sys_faccessat_args { + syscallarg(int) fd; + syscallarg(const char *) path; + syscallarg(int) amode; + syscallarg(int) flag; +}; + +struct sys_fchmodat_args { + syscallarg(int) fd; + syscallarg(const char *) path; + syscallarg(mode_t) mode; + syscallarg(int) flag; +}; + +struct sys_fchownat_args { + syscallarg(int) fd; + syscallarg(const char *) path; + syscallarg(uid_t) uid; + syscallarg(gid_t) gid; + syscallarg(int) flag; +}; + +struct sys_linkat_args { + syscallarg(int) fd1; + syscallarg(const char *) path1; + syscallarg(int) fd2; + syscallarg(const char *) path2; + syscallarg(int) flag; +}; + +struct sys_mkdirat_args { + syscallarg(int) fd; + syscallarg(const char *) path; + syscallarg(mode_t) mode; +}; + +struct sys_mkfifoat_args { + syscallarg(int) fd; + syscallarg(const char *) path; + syscallarg(mode_t) mode; +}; + +struct sys_mknodat_args { + syscallarg(int) fd; + syscallarg(const char *) path; + syscallarg(mode_t) mode; + syscallarg(dev_t) dev; +}; + +struct sys_openat_args { + syscallarg(int) fd; + syscallarg(const char *) path; + syscallarg(int) flags; + syscallarg(mode_t) mode; +}; + +struct sys_readlinkat_args { + syscallarg(int) fd; + syscallarg(const char *) path; + syscallarg(char *) buf; + syscallarg(size_t) count; +}; + +struct sys_renameat_args { + syscallarg(int) fromfd; + syscallarg(const char *) from; + syscallarg(int) tofd; + syscallarg(const char *) to; +}; + +struct sys_symlinkat_args { + syscallarg(const char *) path; + syscallarg(int) fd; + syscallarg(const char *) link; +}; + +struct sys_unlinkat_args { + syscallarg(int) fd; + syscallarg(const char *) path; + syscallarg(int) flag; +}; + +struct sys___set_tcb_args { + syscallarg(void *) tcb; +}; + +/* + * System call prototypes. + */ + +int sys_exit(struct proc *, void *, register_t *); +int sys_fork(struct proc *, void *, register_t *); +int sys_read(struct proc *, void *, register_t *); +int sys_write(struct proc *, void *, register_t *); +int sys_open(struct proc *, void *, register_t *); +int sys_close(struct proc *, void *, register_t *); +int sys_getentropy(struct proc *, void *, register_t *); +int sys___tfork(struct proc *, void *, register_t *); +int sys_link(struct proc *, void *, register_t *); +int sys_unlink(struct proc *, void *, register_t *); +int sys_wait4(struct proc *, void *, register_t *); +int sys_chdir(struct proc *, void *, register_t *); +int sys_fchdir(struct proc *, void *, register_t *); +int sys_mknod(struct proc *, void *, register_t *); +int sys_chmod(struct proc *, void *, register_t *); +int sys_chown(struct proc *, void *, register_t *); +int sys_obreak(struct proc *, void *, register_t *); +int sys_getdtablecount(struct proc *, void *, register_t *); +int sys_getrusage(struct proc *, void *, register_t *); +int sys_getpid(struct proc *, void *, register_t *); +int sys_mount(struct proc *, void *, register_t *); +int sys_unmount(struct proc *, void *, register_t *); +int sys_setuid(struct proc *, void *, register_t *); +int sys_getuid(struct proc *, void *, register_t *); +int sys_geteuid(struct proc *, void *, register_t *); +#ifdef PTRACE +int sys_ptrace(struct proc *, void *, register_t *); +#else +#endif +int sys_recvmsg(struct proc *, void *, register_t *); +int sys_sendmsg(struct proc *, void *, register_t *); +int sys_recvfrom(struct proc *, void *, register_t *); +int sys_accept(struct proc *, void *, register_t *); +int sys_getpeername(struct proc *, void *, register_t *); +int sys_getsockname(struct proc *, void *, register_t *); +int sys_access(struct proc *, void *, register_t *); +int sys_chflags(struct proc *, void *, register_t *); +int sys_fchflags(struct proc *, void *, register_t *); +int sys_sync(struct proc *, void *, register_t *); +int sys_stat(struct proc *, void *, register_t *); +int sys_getppid(struct proc *, void *, register_t *); +int sys_lstat(struct proc *, void *, register_t *); +int sys_dup(struct proc *, void *, register_t *); +int sys_fstatat(struct proc *, void *, register_t *); +int sys_getegid(struct proc *, void *, register_t *); +#ifdef KTRACE +int sys_ktrace(struct proc *, void *, register_t *); +#else +#endif +int sys_sigaction(struct proc *, void *, register_t *); +int sys_getgid(struct proc *, void *, register_t *); +int sys_sigprocmask(struct proc *, void *, register_t *); +int sys_mmap(struct proc *, void *, register_t *); +int sys_setlogin(struct proc *, void *, register_t *); +#ifdef ACCOUNTING +int sys_acct(struct proc *, void *, register_t *); +#else +#endif +int sys_sigpending(struct proc *, void *, register_t *); +int sys_fstat(struct proc *, void *, register_t *); +int sys_ioctl(struct proc *, void *, register_t *); +int sys_reboot(struct proc *, void *, register_t *); +int sys_revoke(struct proc *, void *, register_t *); +int sys_symlink(struct proc *, void *, register_t *); +int sys_readlink(struct proc *, void *, register_t *); +int sys_execve(struct proc *, void *, register_t *); +int sys_umask(struct proc *, void *, register_t *); +int sys_chroot(struct proc *, void *, register_t *); +int sys_getfsstat(struct proc *, void *, register_t *); +int sys_statfs(struct proc *, void *, register_t *); +int sys_fstatfs(struct proc *, void *, register_t *); +int sys_fhstatfs(struct proc *, void *, register_t *); +int sys_vfork(struct proc *, void *, register_t *); +int sys_gettimeofday(struct proc *, void *, register_t *); +int sys_settimeofday(struct proc *, void *, register_t *); +int sys_setitimer(struct proc *, void *, register_t *); +int sys_getitimer(struct proc *, void *, register_t *); +int sys_select(struct proc *, void *, register_t *); +int sys_kevent(struct proc *, void *, register_t *); +int sys_munmap(struct proc *, void *, register_t *); +int sys_mprotect(struct proc *, void *, register_t *); +int sys_madvise(struct proc *, void *, register_t *); +int sys_utimes(struct proc *, void *, register_t *); +int sys_futimes(struct proc *, void *, register_t *); +int sys_mquery(struct proc *, void *, register_t *); +int sys_getgroups(struct proc *, void *, register_t *); +int sys_setgroups(struct proc *, void *, register_t *); +int sys_getpgrp(struct proc *, void *, register_t *); +int sys_setpgid(struct proc *, void *, register_t *); +int sys_futex(struct proc *, void *, register_t *); +int sys_utimensat(struct proc *, void *, register_t *); +int sys_futimens(struct proc *, void *, register_t *); +int sys_kbind(struct proc *, void *, register_t *); +int sys_clock_gettime(struct proc *, void *, register_t *); +int sys_clock_settime(struct proc *, void *, register_t *); +int sys_clock_getres(struct proc *, void *, register_t *); +int sys_dup2(struct proc *, void *, register_t *); +int sys_nanosleep(struct proc *, void *, register_t *); +int sys_fcntl(struct proc *, void *, register_t *); +int sys_accept4(struct proc *, void *, register_t *); +int sys___thrsleep(struct proc *, void *, register_t *); +int sys_fsync(struct proc *, void *, register_t *); +int sys_setpriority(struct proc *, void *, register_t *); +int sys_socket(struct proc *, void *, register_t *); +int sys_connect(struct proc *, void *, register_t *); +int sys_getdents(struct proc *, void *, register_t *); +int sys_getpriority(struct proc *, void *, register_t *); +int sys_pipe2(struct proc *, void *, register_t *); +int sys_dup3(struct proc *, void *, register_t *); +int sys_sigreturn(struct proc *, void *, register_t *); +int sys_bind(struct proc *, void *, register_t *); +int sys_setsockopt(struct proc *, void *, register_t *); +int sys_listen(struct proc *, void *, register_t *); +int sys_chflagsat(struct proc *, void *, register_t *); +int sys_pledge(struct proc *, void *, register_t *); +int sys_ppoll(struct proc *, void *, register_t *); +int sys_pselect(struct proc *, void *, register_t *); +int sys_sigsuspend(struct proc *, void *, register_t *); +int sys_sendsyslog(struct proc *, void *, register_t *); +int sys_unveil(struct proc *, void *, register_t *); +int sys___realpath(struct proc *, void *, register_t *); +int sys_recvmmsg(struct proc *, void *, register_t *); +int sys_sendmmsg(struct proc *, void *, register_t *); +int sys_getsockopt(struct proc *, void *, register_t *); +int sys_thrkill(struct proc *, void *, register_t *); +int sys_readv(struct proc *, void *, register_t *); +int sys_writev(struct proc *, void *, register_t *); +int sys_kill(struct proc *, void *, register_t *); +int sys_fchown(struct proc *, void *, register_t *); +int sys_fchmod(struct proc *, void *, register_t *); +int sys_setreuid(struct proc *, void *, register_t *); +int sys_setregid(struct proc *, void *, register_t *); +int sys_rename(struct proc *, void *, register_t *); +int sys_flock(struct proc *, void *, register_t *); +int sys_mkfifo(struct proc *, void *, register_t *); +int sys_sendto(struct proc *, void *, register_t *); +int sys_shutdown(struct proc *, void *, register_t *); +int sys_socketpair(struct proc *, void *, register_t *); +int sys_mkdir(struct proc *, void *, register_t *); +int sys_rmdir(struct proc *, void *, register_t *); +int sys_adjtime(struct proc *, void *, register_t *); +int sys_getlogin_r(struct proc *, void *, register_t *); +int sys_getthrname(struct proc *, void *, register_t *); +int sys_setthrname(struct proc *, void *, register_t *); +int sys_setsid(struct proc *, void *, register_t *); +int sys_quotactl(struct proc *, void *, register_t *); +int sys_ypconnect(struct proc *, void *, register_t *); +#if defined(NFSCLIENT) || defined(NFSSERVER) +int sys_nfssvc(struct proc *, void *, register_t *); +#else +#endif +int sys_pinsyscalls(struct proc *, void *, register_t *); +int sys_mimmutable(struct proc *, void *, register_t *); +int sys_waitid(struct proc *, void *, register_t *); +int sys_getfh(struct proc *, void *, register_t *); +int sys___tmpfd(struct proc *, void *, register_t *); +int sys_sysarch(struct proc *, void *, register_t *); +int sys_lseek(struct proc *, void *, register_t *); +int sys_truncate(struct proc *, void *, register_t *); +int sys_ftruncate(struct proc *, void *, register_t *); +int sys_pread(struct proc *, void *, register_t *); +int sys_pwrite(struct proc *, void *, register_t *); +int sys_preadv(struct proc *, void *, register_t *); +int sys_pwritev(struct proc *, void *, register_t *); +int sys_profil(struct proc *, void *, register_t *); +int sys_setgid(struct proc *, void *, register_t *); +int sys_setegid(struct proc *, void *, register_t *); +int sys_seteuid(struct proc *, void *, register_t *); +int sys_pathconfat(struct proc *, void *, register_t *); +int sys_pathconf(struct proc *, void *, register_t *); +int sys_fpathconf(struct proc *, void *, register_t *); +int sys_swapctl(struct proc *, void *, register_t *); +int sys_getrlimit(struct proc *, void *, register_t *); +int sys_setrlimit(struct proc *, void *, register_t *); +int sys_sysctl(struct proc *, void *, register_t *); +int sys_mlock(struct proc *, void *, register_t *); +int sys_munlock(struct proc *, void *, register_t *); +int sys_getpgid(struct proc *, void *, register_t *); +int sys_utrace(struct proc *, void *, register_t *); +#ifdef SYSVSEM +int sys_semget(struct proc *, void *, register_t *); +#else +#endif +#ifdef SYSVMSG +int sys_msgget(struct proc *, void *, register_t *); +int sys_msgsnd(struct proc *, void *, register_t *); +int sys_msgrcv(struct proc *, void *, register_t *); +#else +#endif +#ifdef SYSVSHM +int sys_shmat(struct proc *, void *, register_t *); +int sys_shmdt(struct proc *, void *, register_t *); +#else +#endif +int sys_minherit(struct proc *, void *, register_t *); +int sys_poll(struct proc *, void *, register_t *); +int sys_issetugid(struct proc *, void *, register_t *); +int sys_lchown(struct proc *, void *, register_t *); +int sys_getsid(struct proc *, void *, register_t *); +int sys_msync(struct proc *, void *, register_t *); +int sys_pipe(struct proc *, void *, register_t *); +int sys_fhopen(struct proc *, void *, register_t *); +int sys_kqueue(struct proc *, void *, register_t *); +int sys_kqueue1(struct proc *, void *, register_t *); +int sys_mlockall(struct proc *, void *, register_t *); +int sys_munlockall(struct proc *, void *, register_t *); +int sys_getresuid(struct proc *, void *, register_t *); +int sys_setresuid(struct proc *, void *, register_t *); +int sys_getresgid(struct proc *, void *, register_t *); +int sys_setresgid(struct proc *, void *, register_t *); +int sys_closefrom(struct proc *, void *, register_t *); +int sys_sigaltstack(struct proc *, void *, register_t *); +#ifdef SYSVSHM +int sys_shmget(struct proc *, void *, register_t *); +#else +#endif +#ifdef SYSVSEM +int sys_semop(struct proc *, void *, register_t *); +#else +#endif +int sys_fhstat(struct proc *, void *, register_t *); +#ifdef SYSVSEM +int sys___semctl(struct proc *, void *, register_t *); +#else +#endif +#ifdef SYSVSHM +int sys_shmctl(struct proc *, void *, register_t *); +#else +#endif +#ifdef SYSVMSG +int sys_msgctl(struct proc *, void *, register_t *); +#else +#endif +int sys_sched_yield(struct proc *, void *, register_t *); +int sys_getthrid(struct proc *, void *, register_t *); +int sys___thrwakeup(struct proc *, void *, register_t *); +int sys___threxit(struct proc *, void *, register_t *); +int sys___thrsigdivert(struct proc *, void *, register_t *); +int sys___getcwd(struct proc *, void *, register_t *); +int sys_adjfreq(struct proc *, void *, register_t *); +int sys_setrtable(struct proc *, void *, register_t *); +int sys_getrtable(struct proc *, void *, register_t *); +int sys_faccessat(struct proc *, void *, register_t *); +int sys_fchmodat(struct proc *, void *, register_t *); +int sys_fchownat(struct proc *, void *, register_t *); +int sys_linkat(struct proc *, void *, register_t *); +int sys_mkdirat(struct proc *, void *, register_t *); +int sys_mkfifoat(struct proc *, void *, register_t *); +int sys_mknodat(struct proc *, void *, register_t *); +int sys_openat(struct proc *, void *, register_t *); +int sys_readlinkat(struct proc *, void *, register_t *); +int sys_renameat(struct proc *, void *, register_t *); +int sys_symlinkat(struct proc *, void *, register_t *); +int sys_unlinkat(struct proc *, void *, register_t *); +int sys___set_tcb(struct proc *, void *, register_t *); +int sys___get_tcb(struct proc *, void *, register_t *); \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/sysctl.h b/lib/libc/include/generic-openbsd/sys/sysctl.h new file mode 100644 index 000000000000..39620208b0d8 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/sysctl.h @@ -0,0 +1,1100 @@ +/* $OpenBSD: sysctl.h,v 1.246 2025/07/31 09:05:11 mvs Exp $ */ +/* $NetBSD: sysctl.h,v 1.16 1996/04/09 20:55:36 cgd Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Karels at Berkeley Software Design, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)sysctl.h 8.2 (Berkeley) 3/30/95 + */ + +#ifndef _SYS_SYSCTL_H_ +#define _SYS_SYSCTL_H_ + +#include +#include + +/* + * Definitions for sysctl call. The sysctl call uses a hierarchical name + * for objects that can be examined or modified. The name is expressed as + * a sequence of integers. Like a file path name, the meaning of each + * component depends on its place in the hierarchy. The top-level and kern + * identifiers are defined here, and other identifiers are defined in the + * respective subsystem header files. + */ + +#define CTL_MAXNAME 12 /* largest number of components supported */ + +/* + * Each subsystem defined by sysctl defines a list of variables + * for that subsystem. Each name is either a node with further + * levels defined below it, or it is a leaf of some particular + * type given below. Each sysctl level defines a set of name/type + * pairs to be used by sysctl(1) in manipulating the subsystem. + */ +struct ctlname { + char *ctl_name; /* subsystem name */ + int ctl_type; /* type of name */ +}; +#define CTLTYPE_NODE 1 /* name is a node */ +#define CTLTYPE_INT 2 /* name describes an integer */ +#define CTLTYPE_STRING 3 /* name describes a string */ +#define CTLTYPE_QUAD 4 /* name describes a 64-bit number */ +#define CTLTYPE_STRUCT 5 /* name describes a structure */ + +/* + * Top-level identifiers + */ +#define CTL_UNSPEC 0 /* unused */ +#define CTL_KERN 1 /* "high kernel": proc, limits */ +#define CTL_VM 2 /* virtual memory */ +/* gap for CTL_FS 3 */ +#define CTL_NET 4 /* network, see socket.h */ +#define CTL_DEBUG 5 /* debugging parameters */ +#define CTL_HW 6 /* generic cpu/io */ +#define CTL_MACHDEP 7 /* machine dependent */ +/*define gap 8 was CTL_USER: removed 2013-04 */ +#define CTL_DDB 9 /* DDB user interface, see db_var.h */ +#define CTL_VFS 10 /* VFS sysctl's */ +#define CTL_MAXID 11 /* number of valid top-level ids */ + +#define CTL_NAMES { \ + { 0, 0 }, \ + { "kern", CTLTYPE_NODE }, \ + { "vm", CTLTYPE_NODE }, \ + { "gap", 0 }, \ + { "net", CTLTYPE_NODE }, \ + { "debug", CTLTYPE_NODE }, \ + { "hw", CTLTYPE_NODE }, \ + { "machdep", CTLTYPE_NODE }, \ + { "gap", 0 }, \ + { "ddb", CTLTYPE_NODE }, \ + { "vfs", CTLTYPE_NODE }, \ +} + +/* + * CTL_KERN identifiers + */ +#define KERN_OSTYPE 1 /* string: system version */ +#define KERN_OSRELEASE 2 /* string: system release */ +#define KERN_OSREV 3 /* int: system revision */ +#define KERN_VERSION 4 /* string: compile time info */ +#define KERN_MAXVNODES 5 /* int: max vnodes */ +#define KERN_MAXPROC 6 /* int: max processes */ +#define KERN_MAXFILES 7 /* int: max open files */ +#define KERN_ARGMAX 8 /* int: max arguments to exec */ +#define KERN_SECURELVL 9 /* int: system security level */ +#define KERN_HOSTNAME 10 /* string: hostname */ +#define KERN_HOSTID 11 /* int: host identifier */ +#define KERN_CLOCKRATE 12 /* struct: struct clockinfo */ +/* was KERN_DNSJACKPORT 13 */ +/* was KERN_PROC 14 */ +/* was KERN_FILE 15 */ +#define KERN_PROF 16 /* node: kernel profiling info */ +#define KERN_POSIX1 17 /* int: POSIX.1 version */ +#define KERN_NGROUPS 18 /* int: # of supplemental group ids */ +#define KERN_JOB_CONTROL 19 /* int: is job control available */ +#define KERN_SAVED_IDS 20 /* int: saved set-user/group-ID */ +#define KERN_BOOTTIME 21 /* struct: time kernel was booted */ +#define KERN_DOMAINNAME 22 /* string: (YP) domainname */ +#define KERN_MAXPARTITIONS 23 /* int: number of partitions/disk */ +#define KERN_RAWPARTITION 24 /* int: raw partition number */ +#define KERN_MAXTHREAD 25 /* int: max threads */ +#define KERN_NTHREADS 26 /* int: number of threads */ +#define KERN_OSVERSION 27 /* string: kernel build version */ +#define KERN_SOMAXCONN 28 /* int: listen queue maximum */ +#define KERN_SOMINCONN 29 /* int: half-open controllable param */ +/* was KERN_USERMOUNT 30 */ +/* was KERN_RND 31 */ +#define KERN_NOSUIDCOREDUMP 32 /* int: no setuid coredumps ever */ +#define KERN_FSYNC 33 /* int: file synchronization support */ +#define KERN_SYSVMSG 34 /* int: SysV message queue support */ +#define KERN_SYSVSEM 35 /* int: SysV semaphore support */ +#define KERN_SYSVSHM 36 /* int: SysV shared memory support */ +/* was KERN_ARND 37 */ +#define KERN_MSGBUFSIZE 38 /* int: size of message buffer */ +#define KERN_MALLOCSTATS 39 /* node: malloc statistics */ +#define KERN_CPTIME 40 /* array: cp_time */ +#define KERN_NCHSTATS 41 /* struct: vfs cache statistics */ +#define KERN_FORKSTAT 42 /* struct: fork statistics */ +/* was KERN_NSELCOLL 43 */ +#define KERN_TTY 44 /* node: tty information */ +#define KERN_CCPU 45 /* int: ccpu */ +#define KERN_FSCALE 46 /* int: fscale */ +#define KERN_NPROCS 47 /* int: number of processes */ +#define KERN_MSGBUF 48 /* message buffer, KERN_MSGBUFSIZE */ +#define KERN_POOL 49 /* struct: pool information */ +#define KERN_STACKGAPRANDOM 50 /* int: stackgap_random */ +#define KERN_SYSVIPC_INFO 51 /* struct: SysV sem/shm/msg info */ +#define KERN_ALLOWKMEM 52 /* int: allowkmem */ +#define KERN_WITNESSWATCH 53 /* int: witnesswatch */ +#define KERN_SPLASSERT 54 /* int: splassert */ +#define KERN_PROC_ARGS 55 /* node: proc args and env */ +#define KERN_NFILES 56 /* int: number of open files */ +#define KERN_TTYCOUNT 57 /* int: number of tty devices */ +#define KERN_NUMVNODES 58 /* int: number of vnodes in use */ +#define KERN_MBSTAT 59 /* struct: mbuf statistics */ +#define KERN_WITNESS 60 /* node: witness */ +#define KERN_SEMINFO 61 /* struct: SysV struct seminfo */ +#define KERN_SHMINFO 62 /* struct: SysV struct shminfo */ +#define KERN_INTRCNT 63 /* node: interrupt counters */ +#define KERN_WATCHDOG 64 /* node: watchdog */ +#define KERN_ALLOWDT 65 /* int: allowdt */ +#define KERN_PROC 66 /* struct: process entries */ +#define KERN_MAXCLUSTERS 67 /* number of mclusters */ +#define KERN_EVCOUNT 68 /* node: event counters */ +#define KERN_TIMECOUNTER 69 /* node: timecounter */ +#define KERN_MAXLOCKSPERUID 70 /* int: locks per uid */ +#define KERN_CPTIME2 71 /* array: cp_time2 */ +#define KERN_CACHEPCT 72 /* buffer cache % of physmem */ +#define KERN_FILE 73 /* struct: file entries */ +#define KERN_WXABORT 74 /* int: w^x sigabrt & core */ +#define KERN_CONSDEV 75 /* dev_t: console terminal device */ +#define KERN_NETLIVELOCKS 76 /* int: number of network livelocks */ +#define KERN_POOL_DEBUG 77 /* int: enable pool_debug */ +#define KERN_PROC_CWD 78 /* node: proc cwd */ +#define KERN_PROC_NOBROADCASTKILL 79 /* node: proc no broadcast kill */ +#define KERN_PROC_VMMAP 80 /* node: proc vmmap */ +#define KERN_GLOBAL_PTRACE 81 /* allow ptrace globally */ +#define KERN_CONSBUFSIZE 82 /* int: console message buffer size */ +#define KERN_CONSBUF 83 /* console message buffer */ +#define KERN_AUDIO 84 /* struct: audio properties */ +#define KERN_CPUSTATS 85 /* struct: cpu statistics */ +#define KERN_PFSTATUS 86 /* struct: pf status and stats */ +#define KERN_TIMEOUT_STATS 87 /* struct: timeout status and stats */ +#define KERN_UTC_OFFSET 88 /* int: adjust RTC time to UTC */ +#define KERN_VIDEO 89 /* struct: video properties */ +#define KERN_CLOCKINTR 90 /* node: clockintr */ +#define KERN_AUTOCONF_SERIAL 91 /* int: kernel device tree state serial */ +#define KERN_MAXID 92 /* number of valid kern ids */ + +#define CTL_KERN_NAMES { \ + { 0, 0 }, \ + { "ostype", CTLTYPE_STRING }, \ + { "osrelease", CTLTYPE_STRING }, \ + { "osrevision", CTLTYPE_INT }, \ + { "version", CTLTYPE_STRING }, \ + { "maxvnodes", CTLTYPE_INT }, \ + { "maxproc", CTLTYPE_INT }, \ + { "maxfiles", CTLTYPE_INT }, \ + { "argmax", CTLTYPE_INT }, \ + { "securelevel", CTLTYPE_INT }, \ + { "hostname", CTLTYPE_STRING }, \ + { "hostid", CTLTYPE_INT }, \ + { "clockrate", CTLTYPE_STRUCT }, \ + { "gap", 0 }, \ + { "gap", 0 }, \ + { "gap", 0 }, \ + { "profiling", CTLTYPE_NODE }, \ + { "posix1version", CTLTYPE_INT }, \ + { "ngroups", CTLTYPE_INT }, \ + { "job_control", CTLTYPE_INT }, \ + { "saved_ids", CTLTYPE_INT }, \ + { "boottime", CTLTYPE_STRUCT }, \ + { "domainname", CTLTYPE_STRING }, \ + { "maxpartitions", CTLTYPE_INT }, \ + { "rawpartition", CTLTYPE_INT }, \ + { "maxthread", CTLTYPE_INT }, \ + { "nthreads", CTLTYPE_INT }, \ + { "osversion", CTLTYPE_STRING }, \ + { "somaxconn", CTLTYPE_INT }, \ + { "sominconn", CTLTYPE_INT }, \ + { "gap", 0 }, \ + { "gap", 0 }, \ + { "nosuidcoredump", CTLTYPE_INT }, \ + { "fsync", CTLTYPE_INT }, \ + { "sysvmsg", CTLTYPE_INT }, \ + { "sysvsem", CTLTYPE_INT }, \ + { "sysvshm", CTLTYPE_INT }, \ + { "gap", 0 }, \ + { "msgbufsize", CTLTYPE_INT }, \ + { "malloc", CTLTYPE_NODE }, \ + { "cp_time", CTLTYPE_STRUCT }, \ + { "nchstats", CTLTYPE_STRUCT }, \ + { "forkstat", CTLTYPE_STRUCT }, \ + { "gap", 0 }, \ + { "tty", CTLTYPE_NODE }, \ + { "ccpu", CTLTYPE_INT }, \ + { "fscale", CTLTYPE_INT }, \ + { "nprocs", CTLTYPE_INT }, \ + { "msgbuf", CTLTYPE_STRUCT }, \ + { "pool", CTLTYPE_NODE }, \ + { "stackgap_random", CTLTYPE_INT }, \ + { "sysvipc_info", CTLTYPE_INT }, \ + { "allowkmem", CTLTYPE_INT }, \ + { "witnesswatch", CTLTYPE_INT }, \ + { "splassert", CTLTYPE_INT }, \ + { "procargs", CTLTYPE_NODE }, \ + { "nfiles", CTLTYPE_INT }, \ + { "ttycount", CTLTYPE_INT }, \ + { "numvnodes", CTLTYPE_INT }, \ + { "mbstat", CTLTYPE_STRUCT }, \ + { "witness", CTLTYPE_NODE }, \ + { "seminfo", CTLTYPE_STRUCT }, \ + { "shminfo", CTLTYPE_STRUCT }, \ + { "intrcnt", CTLTYPE_NODE }, \ + { "watchdog", CTLTYPE_NODE }, \ + { "allowdt", CTLTYPE_INT }, \ + { "proc", CTLTYPE_STRUCT }, \ + { "maxclusters", CTLTYPE_INT }, \ + { "evcount", CTLTYPE_NODE }, \ + { "timecounter", CTLTYPE_NODE }, \ + { "maxlocksperuid", CTLTYPE_INT }, \ + { "cp_time2", CTLTYPE_STRUCT }, \ + { "bufcachepercent", CTLTYPE_INT }, \ + { "file", CTLTYPE_STRUCT }, \ + { "wxabort", CTLTYPE_INT }, \ + { "consdev", CTLTYPE_STRUCT }, \ + { "netlivelocks", CTLTYPE_INT }, \ + { "pool_debug", CTLTYPE_INT }, \ + { "proc_cwd", CTLTYPE_NODE }, \ + { "proc_nobroadcastkill", CTLTYPE_NODE }, \ + { "proc_vmmap", CTLTYPE_NODE }, \ + { "global_ptrace", CTLTYPE_INT }, \ + { "consbufsize", CTLTYPE_INT }, \ + { "consbuf", CTLTYPE_STRUCT }, \ + { "audio", CTLTYPE_STRUCT }, \ + { "cpustats", CTLTYPE_STRUCT }, \ + { "pfstatus", CTLTYPE_STRUCT }, \ + { "timeout_stats", CTLTYPE_STRUCT }, \ + { "utc_offset", CTLTYPE_INT }, \ + { "video", CTLTYPE_STRUCT }, \ + { "clockintr", CTLTYPE_NODE }, \ + { "autoconf_serial", CTLTYPE_INT }, \ +} + +/* + * KERN_PROC subtypes + */ +#define KERN_PROC_ALL 0 /* everything but kernel threads */ +#define KERN_PROC_PID 1 /* by process id */ +#define KERN_PROC_PGRP 2 /* by process group id */ +#define KERN_PROC_SESSION 3 /* by session of pid */ +#define KERN_PROC_TTY 4 /* by controlling tty */ +#define KERN_PROC_UID 5 /* by effective uid */ +#define KERN_PROC_RUID 6 /* by real uid */ +#define KERN_PROC_KTHREAD 7 /* also return kernel threads */ +#define KERN_PROC_SHOW_THREADS 0x40000000/* also return normal threads */ + +/* + * KERN_SYSVIPC_INFO subtypes + */ +#define KERN_SYSVIPC_MSG_INFO 1 /* msginfo and msqid_ds */ +#define KERN_SYSVIPC_SEM_INFO 2 /* seminfo and semid_ds */ +#define KERN_SYSVIPC_SHM_INFO 3 /* shminfo and shmid_ds */ + +/* + * KERN_PROC_ARGS subtypes + */ +#define KERN_PROC_ARGV 1 +#define KERN_PROC_NARGV 2 +#define KERN_PROC_ENV 3 +#define KERN_PROC_NENV 4 + +/* + * KERN_AUDIO + */ +#define KERN_AUDIO_RECORD 1 +#define KERN_AUDIO_KBDCONTROL 2 +#define KERN_AUDIO_MAXID 3 + +#define CTL_KERN_AUDIO_NAMES { \ + { 0, 0 }, \ + { "record", CTLTYPE_INT }, \ + { "kbdcontrol", CTLTYPE_INT }, \ +} + +/* + * KERN_VIDEO + */ +#define KERN_VIDEO_RECORD 1 +#define KERN_VIDEO_MAXID 2 + +#define CTL_KERN_VIDEO_NAMES { \ + { 0, 0 }, \ + { "record", CTLTYPE_INT }, \ +} + +/* + * KERN_WITNESS + */ +#define KERN_WITNESS_WATCH 1 /* int: operating mode */ +#define KERN_WITNESS_LOCKTRACE 2 /* int: stack trace saving mode */ +#define KERN_WITNESS_MAXID 3 + +#define CTL_KERN_WITNESS_NAMES { \ + { 0, 0 }, \ + { "watch", CTLTYPE_INT }, \ + { "locktrace", CTLTYPE_INT }, \ +} + +/* + * KERN_PROC subtype ops return arrays of relatively fixed size + * structures of process info. Use 8 byte alignment, and new + * elements should only be added to the end of this structure so + * binary compatibility can be preserved. + */ +#define KI_NGROUPS 16 +#define KI_MAXCOMLEN _MAXCOMLEN /* includes NUL */ +#define KI_WMESGLEN 8 +#define KI_MAXLOGNAME 32 +#define KI_EMULNAMELEN 8 + +#define KI_NOCPU (~(u_int64_t)0) + +struct kinfo_proc { + u_int64_t p_forw; /* PTR: linked run/sleep queue. */ + u_int64_t p_back; + u_int64_t p_paddr; /* PTR: address of proc */ + + u_int64_t p_addr; /* PTR: Kernel virtual addr of u-area */ + u_int64_t p_fd; /* PTR: Ptr to open files structure. */ + u_int64_t p_stats; /* unused, always zero. */ + u_int64_t p_limit; /* PTR: Process limits. */ + u_int64_t p_vmspace; /* PTR: Address space. */ + u_int64_t p_sigacts; /* PTR: Signal actions, state */ + u_int64_t p_sess; /* PTR: session pointer */ + u_int64_t p_tsess; /* PTR: tty session pointer */ + u_int64_t p_ru; /* PTR: Exit information. XXX */ + + int32_t p_eflag; /* LONG: extra kinfo_proc flags */ +#define EPROC_CTTY 0x01 /* controlling tty vnode active */ +#define EPROC_SLEADER 0x02 /* session leader */ +#define EPROC_UNVEIL 0x04 /* has unveil settings */ +#define EPROC_LKUNVEIL 0x08 /* unveil is locked */ + int32_t p_exitsig; /* unused, always zero. */ + int32_t p_flag; /* INT: P_* flags. */ + + int32_t p_pid; /* PID_T: Process identifier. */ + int32_t p_ppid; /* PID_T: Parent process id */ + int32_t p_sid; /* PID_T: session id */ + int32_t p__pgid; /* PID_T: process group id */ + /* XXX: hijacks p_pgid */ + int32_t p_tpgid; /* PID_T: tty process group id */ + + u_int32_t p_uid; /* UID_T: effective user id */ + u_int32_t p_ruid; /* UID_T: real user id */ + u_int32_t p_gid; /* GID_T: effective group id */ + u_int32_t p_rgid; /* GID_T: real group id */ + + u_int32_t p_groups[KI_NGROUPS]; /* GID_T: groups */ + int16_t p_ngroups; /* SHORT: number of groups */ + + int16_t p_jobc; /* SHORT: job control counter */ + u_int32_t p_tdev; /* DEV_T: controlling tty dev */ + + u_int32_t p_estcpu; /* U_INT: Time averaged value of p_cpticks. */ + u_int32_t p_rtime_sec; /* STRUCT TIMEVAL: Real time. */ + u_int32_t p_rtime_usec; /* STRUCT TIMEVAL: Real time. */ + int32_t p_cpticks; /* INT: Ticks of cpu time. */ + u_int32_t p_pctcpu; /* FIXPT_T: %cpu for this process */ + u_int32_t p_swtime; /* unused, always zero */ + u_int32_t p_slptime; /* U_INT: Time since last blocked. */ + int32_t p_schedflags; /* INT: PSCHED_* flags */ + + u_int64_t p_uticks; /* U_QUAD_T: Statclock hits in user mode. */ + u_int64_t p_sticks; /* U_QUAD_T: Statclock hits in system mode. */ + u_int64_t p_iticks; /* U_QUAD_T: Statclock hits processing intr. */ + + u_int64_t p_tracep; /* PTR: Trace to vnode or file */ + int32_t p_traceflag; /* INT: Kernel trace points. */ + + int32_t p_holdcnt; /* INT: If non-zero, don't swap. */ + + int32_t p_siglist; /* INT: Signals arrived but not delivered. */ + u_int32_t p_sigmask; /* SIGSET_T: Current signal mask. */ + u_int32_t p_sigignore; /* SIGSET_T: Signals being ignored. */ + u_int32_t p_sigcatch; /* SIGSET_T: Signals being caught by user. */ + + int8_t p_stat; /* CHAR: S* process status (from LWP). */ + u_int8_t p_priority; /* U_CHAR: Process priority. */ + u_int8_t p_usrpri; /* U_CHAR: User-priority based on p_estcpu and ps_nice. */ + u_int8_t p_nice; /* U_CHAR: Process "nice" value. */ + + u_int16_t p_xstat; /* U_SHORT: Exit status for wait; also stop signal. */ + u_int16_t p_spare; /* U_SHORT: unused */ + + char p_comm[KI_MAXCOMLEN]; + + char p_wmesg[KI_WMESGLEN]; /* wchan message */ + u_int64_t p_wchan; /* PTR: sleep address. */ + + char p_login[KI_MAXLOGNAME]; /* setlogin() name */ + + int32_t p_vm_rssize; /* SEGSZ_T: current resident set size in pages */ + int32_t p_vm_tsize; /* SEGSZ_T: text size (pages) */ + int32_t p_vm_dsize; /* SEGSZ_T: data size (pages) */ + int32_t p_vm_ssize; /* SEGSZ_T: stack size (pages) */ + + int64_t p_uvalid; /* CHAR: following p_u* members from struct user are valid */ + /* XXX 64 bits for alignment */ + u_int64_t p_ustart_sec; /* STRUCT TIMEVAL: starting time. */ + u_int32_t p_ustart_usec; /* STRUCT TIMEVAL: starting time. */ + + u_int32_t p_uutime_sec; /* STRUCT TIMEVAL: user time. */ + u_int32_t p_uutime_usec; /* STRUCT TIMEVAL: user time. */ + u_int32_t p_ustime_sec; /* STRUCT TIMEVAL: system time. */ + u_int32_t p_ustime_usec; /* STRUCT TIMEVAL: system time. */ + + u_int64_t p_uru_maxrss; /* LONG: max resident set size. */ + u_int64_t p_uru_ixrss; /* LONG: integral shared memory size. */ + u_int64_t p_uru_idrss; /* LONG: integral unshared data ". */ + u_int64_t p_uru_isrss; /* LONG: integral unshared stack ". */ + u_int64_t p_uru_minflt; /* LONG: page reclaims. */ + u_int64_t p_uru_majflt; /* LONG: page faults. */ + u_int64_t p_uru_nswap; /* LONG: swaps. */ + u_int64_t p_uru_inblock; /* LONG: block input operations. */ + u_int64_t p_uru_oublock; /* LONG: block output operations. */ + u_int64_t p_uru_msgsnd; /* LONG: messages sent. */ + u_int64_t p_uru_msgrcv; /* LONG: messages received. */ + u_int64_t p_uru_nsignals; /* LONG: signals received. */ + u_int64_t p_uru_nvcsw; /* LONG: voluntary context switches. */ + u_int64_t p_uru_nivcsw; /* LONG: involuntary ". */ + + u_int32_t p_uctime_sec; /* STRUCT TIMEVAL: child u+s time. */ + u_int32_t p_uctime_usec; /* STRUCT TIMEVAL: child u+s time. */ + u_int32_t p_psflags; /* UINT: PS_* flags on the process. */ + u_int32_t p_acflag; /* UINT: Accounting flags. */ + u_int32_t p_svuid; /* UID_T: saved user id */ + u_int32_t p_svgid; /* GID_T: saved group id */ + char p_emul[KI_EMULNAMELEN]; /* syscall emulation name */ + u_int64_t p_rlim_rss_cur; /* RLIM_T: soft limit for rss */ + u_int64_t p_cpuid; /* LONG: CPU id */ + u_int64_t p_vm_map_size; /* VSIZE_T: virtual size */ + int32_t p_tid; /* PID_T: Thread identifier. */ + u_int32_t p_rtableid; /* U_INT: Routing table identifier. */ + + u_int64_t p_pledge; /* U_INT64_T: Pledge flags. */ + char p_name[KI_MAXCOMLEN]; /* thread name */ +}; + +/* + * VM address range entry, matching struct vm_map_entry. Useful for + * debuggers to know process's addresses. + * + * To iterate entries, set the last kve_end as the base address into + * kve_start. + */ +struct kinfo_vmentry { + u_long kve_start; /* vaddr_t */ + u_long kve_end; /* vaddr_t */ + u_long kve_guard; /* vsize_t */ + u_long kve_fspace; /* vsize_t */ + u_long kve_fspace_augment; /* vsize_t */ + u_int64_t kve_offset; /* voff_t */ + int kve_wired_count; + int kve_etype; + int kve_protection; + int kve_max_protection; + int kve_advice; + int kve_inheritance; + u_int8_t kve_flags; /* u_int8_t */ +}; + +/* keep in sync with UVM_ET_* */ +#define KVE_ET_OBJ 0x00000001 +#define KVE_ET_SUBMAP 0x00000002 +#define KVE_ET_COPYONWRITE 0x00000004 +#define KVE_ET_NEEDSCOPY 0x00000008 +#define KVE_ET_HOLE 0x00000010 +#define KVE_ET_NOFAULT 0x00000020 +#define KVE_ET_STACK 0x00000040 +#define KVE_ET_WC 0x00000080 +#define KVE_ET_CONCEAL 0x00000100 +#define KVE_ET_SYSCALL 0x00000200 +#define KVE_ET_FREEMAPPED 0x00000800 + +#define KVE_PROT_NONE 0x00000000 +#define KVE_PROT_READ 0x00000001 +#define KVE_PROT_WRITE 0x00000002 +#define KVE_PROT_EXEC 0x00000004 + +#define KVE_ADV_NORMAL 0x00000000 +#define KVE_ADV_RANDOM 0x00000001 +#define KVE_ADV_SEQUENTIAL 0x00000002 + +#define KVE_INH_SHARE 0x00000000 +#define KVE_INH_COPY 0x00000010 +#define KVE_INH_NONE 0x00000020 +#define KVE_INH_ZERO 0x00000030 + +#define KVE_F_STATIC 0x01 +#define KVE_F_KMEM 0x02 + +#if defined(_KERNEL) || defined(_LIBKVM) + +/* + * Macros for filling in the bulk of a kinfo_proc structure, used + * in the kernel to implement the KERN_PROC sysctl and in userland + * in libkvm to implement reading from kernel crashes. The macro + * arguments are all pointers; by name they are: + * kp - target kinfo_proc structure + * copy_str - a function or macro invoked as copy_str(dst,src,maxlen) + * that has strlcpy or memcpy semantics; the destination is + * pre-filled with zeros; for libkvm, src is a kvm address + * p - source struct proc + * pr - source struct process + * uc - source struct ucreds + * pg - source struct pgrp + * paddr - kernel address of the source struct proc + * praddr - kernel address of the source struct process + * sess - source struct session + * vm - source struct vmspace + * lim - source struct plimits + * sa - source struct sigacts + * There are some members that are not handled by these macros + * because they're too painful to generalize: p_sid, p_tdev, + * p_tpgid, p_tsess, p_vm_rssize, p_u[us]time_{sec,usec}, p_cpuid + */ + +#if defined(_KERNEL) +#define PR_LOCK(pr) mtx_enter(&(pr)->ps_mtx) +#define PR_UNLOCK(pr) mtx_leave(&(pr)->ps_mtx) +#else +#define PR_LOCK(pr) /* nothing */ +#define PR_UNLOCK(pr) /* nothing */ +#endif + +#define _getcompatprio(_p) \ + ((_p)->p_stat == SRUN ? (_p)->p_runpri : \ + ((_p)->p_stat == SSLEEP) ? (_p)->p_slppri : (_p)->p_usrpri) + +#define PTRTOINT64(_x) ((u_int64_t)(u_long)(_x)) + +#define _FILL_KPROC_MIN(a,b) (((a)<(b))?(a):(b)) + +#define FILL_KPROC(kp, copy_str, p, pr, uc, pg, paddr, \ + praddr, sess, vm, lim, sa, tu, isthread, show_addresses) \ +do { \ + memset((kp), 0, sizeof(*(kp))); \ + \ + if (show_addresses) { \ + (kp)->p_paddr = PTRTOINT64(paddr); \ + (kp)->p_fd = PTRTOINT64((pr)->ps_fd); \ + (kp)->p_limit = PTRTOINT64((pr)->ps_limit); \ + (kp)->p_vmspace = PTRTOINT64((pr)->ps_vmspace); \ + (kp)->p_sigacts = PTRTOINT64((pr)->ps_sigacts); \ + (kp)->p_sess = PTRTOINT64((pg)->pg_session); \ + (kp)->p_ru = PTRTOINT64((pr)->ps_ru); \ + } \ + (kp)->p_stats = 0; \ + (kp)->p_exitsig = 0; \ + (kp)->p_flag = (p)->p_flag; \ + (kp)->p_pid = (pr)->ps_pid; \ + (kp)->p_psflags = (pr)->ps_flags; \ + \ + (kp)->p__pgid = (pg)->pg_id; \ + \ + (kp)->p_uid = (uc)->cr_uid; \ + (kp)->p_ruid = (uc)->cr_ruid; \ + (kp)->p_gid = (uc)->cr_gid; \ + (kp)->p_rgid = (uc)->cr_rgid; \ + (kp)->p_svuid = (uc)->cr_svuid; \ + (kp)->p_svgid = (uc)->cr_svgid; \ + \ + memcpy((kp)->p_groups, (uc)->cr_groups, \ + _FILL_KPROC_MIN(sizeof((kp)->p_groups), sizeof((uc)->cr_groups))); \ + (kp)->p_ngroups = (uc)->cr_ngroups; \ + \ + (kp)->p_jobc = (pg)->pg_jobc; \ + \ + (kp)->p_estcpu = (p)->p_estcpu; \ + if (isthread) { \ + (kp)->p_tid = (p)->p_tid + THREAD_PID_OFFSET; \ + strlcpy((kp)->p_name, (p)->p_name, sizeof((kp)->p_name)); \ + } else { \ + (kp)->p_tid = -1; \ + } \ + (kp)->p_rtime_sec = (tu)->tu_runtime.tv_sec; \ + (kp)->p_rtime_usec = (tu)->tu_runtime.tv_nsec/1000; \ + (kp)->p_uticks = (tu)->tu_uticks; \ + (kp)->p_sticks = (tu)->tu_sticks; \ + (kp)->p_iticks = (tu)->tu_iticks; \ + (kp)->p_cpticks = (p)->p_cpticks; \ + \ + if (show_addresses) \ + (kp)->p_tracep = PTRTOINT64((pr)->ps_tracevp); \ + (kp)->p_traceflag = (pr)->ps_traceflag; \ + \ + (kp)->p_siglist = (p)->p_siglist | (pr)->ps_siglist; \ + (kp)->p_sigmask = (p)->p_sigmask; \ + \ + PR_LOCK(pr); \ + (kp)->p_ppid = (pr)->ps_ppid; \ + (kp)->p_sigignore = (sa) ? (sa)->ps_sigignore : 0; \ + (kp)->p_sigcatch = (sa) ? (sa)->ps_sigcatch : 0; \ + \ + if (lim) \ + (kp)->p_rlim_rss_cur = \ + (lim)->pl_rlimit[RLIMIT_RSS].rlim_cur; \ + PR_UNLOCK(pr); \ + \ + (kp)->p_stat = (p)->p_stat; \ + (kp)->p_nice = (pr)->ps_nice; \ + \ + (kp)->p_xstat = W_EXITCODE((pr)->ps_xexit, (pr)->ps_xsig); \ + (kp)->p_acflag = (pr)->ps_acflag; \ + (kp)->p_pledge = (pr)->ps_pledge; \ + \ + strlcpy((kp)->p_emul, "native", sizeof((kp)->p_emul)); \ + strlcpy((kp)->p_comm, (pr)->ps_comm, sizeof((kp)->p_comm)); \ + strlcpy((kp)->p_login, (sess)->s_login, \ + _FILL_KPROC_MIN(sizeof((kp)->p_login), sizeof((sess)->s_login))); \ + \ + if ((sess)->s_ttyvp) \ + (kp)->p_eflag |= EPROC_CTTY; \ + if ((pr)->ps_uvpaths) \ + (kp)->p_eflag |= EPROC_UNVEIL; \ + if ((pr)->ps_uvdone || \ + (((pr)->ps_flags & PS_PLEDGE) && \ + ((pr)->ps_pledge & PLEDGE_UNVEIL) == 0)) \ + (kp)->p_eflag |= EPROC_LKUNVEIL; \ + \ + if (((pr)->ps_flags & (PS_EMBRYO | PS_ZOMBIE)) == 0) { \ + if ((vm) != NULL) { \ + (kp)->p_vm_rssize = (vm)->vm_rssize; \ + (kp)->p_vm_tsize = (vm)->vm_tsize; \ + (kp)->p_vm_dsize = (vm)->vm_dused; \ + (kp)->p_vm_ssize = (vm)->vm_ssize; \ + } \ + (kp)->p_addr = PTRTOINT64((p)->p_addr); \ + (kp)->p_stat = (p)->p_stat; \ + (kp)->p_slptime = (p)->p_slptime; \ + (kp)->p_holdcnt = 1; \ + (kp)->p_priority = _getcompatprio(p); \ + (kp)->p_usrpri = (p)->p_usrpri; \ + if ((p)->p_wchan && (p)->p_wmesg) \ + copy_str((kp)->p_wmesg, (p)->p_wmesg, \ + sizeof((kp)->p_wmesg)); \ + if (show_addresses) \ + (kp)->p_wchan = PTRTOINT64((p)->p_wchan); \ + } \ + \ + if (((pr)->ps_flags & PS_ZOMBIE) == 0) { \ + struct timeval __tv; \ + \ + (kp)->p_uvalid = 1; \ + \ + (kp)->p_uru_maxrss = (p)->p_ru.ru_maxrss; \ + (kp)->p_uru_ixrss = (p)->p_ru.ru_ixrss; \ + (kp)->p_uru_idrss = (p)->p_ru.ru_idrss; \ + (kp)->p_uru_isrss = (p)->p_ru.ru_isrss; \ + (kp)->p_uru_minflt = (p)->p_ru.ru_minflt; \ + (kp)->p_uru_majflt = (p)->p_ru.ru_majflt; \ + (kp)->p_uru_nswap = (p)->p_ru.ru_nswap; \ + (kp)->p_uru_inblock = (p)->p_ru.ru_inblock; \ + (kp)->p_uru_oublock = (p)->p_ru.ru_oublock; \ + (kp)->p_uru_msgsnd = (p)->p_ru.ru_msgsnd; \ + (kp)->p_uru_msgrcv = (p)->p_ru.ru_msgrcv; \ + (kp)->p_uru_nsignals = (p)->p_ru.ru_nsignals; \ + (kp)->p_uru_nvcsw = (p)->p_ru.ru_nvcsw; \ + (kp)->p_uru_nivcsw = (p)->p_ru.ru_nivcsw; \ + \ + timeradd(&(pr)->ps_cru.ru_utime, \ + &(pr)->ps_cru.ru_stime, &__tv); \ + (kp)->p_uctime_sec = __tv.tv_sec; \ + (kp)->p_uctime_usec = __tv.tv_usec; \ + } \ + \ + (kp)->p_cpuid = KI_NOCPU; \ + (kp)->p_rtableid = (pr)->ps_rtableid; \ +} while (0) + +#endif /* defined(_KERNEL) || defined(_LIBKVM) */ + + +/* + * kern.file returns an array of these structures, which are designed + * both to be immune to 32/64 bit emulation issues and to + * provide backwards compatibility. The order differs slightly from + * that of the real struct file, and some fields are taken from other + * structures (struct vnode, struct proc) in order to make the file + * information more useful. + */ +#define KERN_FILE_BYFILE 1 +#define KERN_FILE_BYPID 2 +#define KERN_FILE_BYUID 3 +#define KERN_FILESLOP 10 + +#define KERN_FILE_TEXT -1 +#define KERN_FILE_CDIR -2 +#define KERN_FILE_RDIR -3 +#define KERN_FILE_TRACE -4 + +#define KI_MNAMELEN 96 /* rounded up from 90 */ +#define KI_UNPPATHLEN 104 + +struct kinfo_file { + uint64_t f_fileaddr; /* PTR: address of struct file */ + uint32_t f_flag; /* UINT: flags (see fcntl.h) */ + uint32_t f_iflags; /* UINT: internal flags */ + uint32_t f_type; /* INT: descriptor type */ + uint32_t f_count; /* UINT: reference count */ + uint32_t f_msgcount; /* UINT: references from msg queue */ + uint32_t f_usecount; /* INT: number active users */ + uint64_t f_ucred; /* PTR: creds for descriptor */ + uint32_t f_uid; /* UID_T: descriptor credentials */ + uint32_t f_gid; /* GID_T: descriptor credentials */ + uint64_t f_ops; /* PTR: address of fileops */ + uint64_t f_offset; /* OFF_T: offset */ + uint64_t f_data; /* PTR: descriptor data */ + uint64_t f_rxfer; /* UINT64: number of read xfers */ + uint64_t f_rwfer; /* UINT64: number of write xfers */ + uint64_t f_seek; /* UINT64: number of seek operations */ + uint64_t f_rbytes; /* UINT64: total bytes read */ + uint64_t f_wbytes; /* UINT64: total bytes written */ + + /* information about the vnode associated with this file */ + uint64_t v_un; /* PTR: socket, specinfo, etc */ + uint32_t v_type; /* ENUM: vnode type */ + uint32_t v_tag; /* ENUM: type of underlying data */ + uint32_t v_flag; /* UINT: vnode flags */ + uint32_t va_rdev; /* DEV_T: raw device */ + uint64_t v_data; /* PTR: private data for fs */ + uint64_t v_mount; /* PTR: mount info for fs */ + uint64_t va_fileid; /* LONG: file id */ + uint64_t va_size; /* UINT64_T: file size in bytes */ + uint32_t va_mode; /* MODE_T: file access mode and type */ + uint32_t va_fsid; /* DEV_T: filesystem device */ + char f_mntonname[KI_MNAMELEN]; + + /* socket information */ + uint32_t so_type; /* SHORT: socket type */ + uint32_t so_state; /* SHORT: socket state */ + uint64_t so_pcb; /* PTR: socket pcb */ + /* for non-root: -1 if not NULL */ + uint32_t so_protocol; /* SHORT: socket protocol type */ + uint32_t so_family; /* INT: socket domain family */ + uint64_t inp_ppcb; /* PTR: pointer to per-protocol pcb */ + uint32_t inp_lport; /* SHORT: local inet port */ + uint32_t inp_laddru[4]; /* STRUCT: local inet addr */ + uint32_t inp_fport; /* SHORT: foreign inet port */ + uint32_t inp_faddru[4]; /* STRUCT: foreign inet addr */ + uint64_t unp_conn; /* PTR: connected socket cntrl block */ + + /* pipe information */ + uint64_t pipe_peer; /* PTR: link with other direction */ + uint32_t pipe_state; /* UINT: pipe status info */ + + /* kqueue information */ + uint32_t kq_count; /* INT: number of pending events */ + uint32_t kq_state; /* INT: kqueue status information */ + + uint32_t __unused1; /* INT: unused */ + + /* process information when retrieved via KERN_FILE_BY[PU]ID */ + uint32_t p_pid; /* PID_T: process id */ + int32_t fd_fd; /* INT: descriptor number */ + uint32_t fd_ofileflags; /* CHAR: open file flags */ + uint32_t p_uid; /* UID_T: process credentials */ + uint32_t p_gid; /* GID_T: process credentials */ + uint32_t p_tid; /* PID_T: thread id */ + char p_comm[KI_MAXCOMLEN]; + + /* more socket information */ + uint32_t inp_rtableid; /* UINT: Routing table identifier. */ + uint64_t so_splice; /* PTR: f_data of spliced socket */ + int64_t so_splicelen; /* OFF_T: already spliced count or */ + /* -1 if this is target of splice */ + uint64_t so_rcv_cc; /* LONG: chars in receive buf */ + uint64_t so_snd_cc; /* LONG: chars in send buf */ + uint64_t unp_refs; /* PTR: connected sockets */ + uint64_t unp_nextref; /* PTR: link to next connected socket */ + uint64_t unp_addr; /* PTR: address of the socket address */ + char unp_path[KI_UNPPATHLEN]; + uint32_t inp_proto; /* CHAR: raw protocol id */ + uint32_t t_state; /* SHORT: tcp state */ + uint64_t t_rcv_wnd; /* ULONG: tcp receive window */ + uint64_t t_snd_wnd; /* ULONG: tcp send window */ + uint64_t t_snd_cwnd; /* ULONG: congestion-controlled win */ + + uint32_t va_nlink; /* NLINK_T: number of references to file */ +}; + +/* + * KERN_INTRCNT + */ +#define KERN_INTRCNT_NUM 1 /* int: # intrcnt */ +#define KERN_INTRCNT_CNT 2 /* node: intrcnt */ +#define KERN_INTRCNT_NAME 3 /* node: names */ +#define KERN_INTRCNT_VECTOR 4 /* node: interrupt vector # */ +#define KERN_INTRCNT_MAXID 5 + +#define CTL_KERN_INTRCNT_NAMES { \ + { 0, 0 }, \ + { "nintrcnt", CTLTYPE_INT }, \ + { "intrcnt", CTLTYPE_NODE }, \ + { "intrname", CTLTYPE_NODE }, \ +} + +/* + * KERN_WATCHDOG + */ +#define KERN_WATCHDOG_PERIOD 1 /* int: watchdog period */ +#define KERN_WATCHDOG_AUTO 2 /* int: automatic tickle */ +#define KERN_WATCHDOG_MAXID 3 + +#define CTL_KERN_WATCHDOG_NAMES { \ + { 0, 0 }, \ + { "period", CTLTYPE_INT }, \ + { "auto", CTLTYPE_INT }, \ +} + +/* + * KERN_TIMECOUNTER + */ +#define KERN_TIMECOUNTER_TICK 1 /* int: number of revolutions */ +#define KERN_TIMECOUNTER_TIMESTEPWARNINGS 2 /* int: log a warning when time changes */ +#define KERN_TIMECOUNTER_HARDWARE 3 /* string: tick hardware used */ +#define KERN_TIMECOUNTER_CHOICE 4 /* string: tick hardware used */ +#define KERN_TIMECOUNTER_MAXID 5 + +#define CTL_KERN_TIMECOUNTER_NAMES { \ + { 0, 0 }, \ + { "tick", CTLTYPE_INT }, \ + { "timestepwarnings", CTLTYPE_INT }, \ + { "hardware", CTLTYPE_STRING }, \ + { "choice", CTLTYPE_STRING }, \ +} + +/* + * KERN_CLOCKINTR + */ +#define KERN_CLOCKINTR_STATS 1 /* struct: stats */ +#define KERN_CLOCKINTR_MAXID 2 + +#define CTL_KERN_CLOCKINTR_NAMES { \ + { 0, 0 }, \ + { "stats", CTLTYPE_STRUCT }, \ +} + +/* + * CTL_HW identifiers + */ +#define HW_MACHINE 1 /* string: machine class */ +#define HW_MODEL 2 /* string: specific machine model */ +#define HW_NCPU 3 /* int: number of configured cpus */ +#define HW_BYTEORDER 4 /* int: machine byte order */ +#define HW_PHYSMEM 5 /* int: total memory */ +#define HW_USERMEM 6 /* int: non-kernel memory */ +#define HW_PAGESIZE 7 /* int: software page size */ +#define HW_DISKNAMES 8 /* strings: disk drive names */ +#define HW_DISKSTATS 9 /* struct: diskstats[] */ +#define HW_DISKCOUNT 10 /* int: number of disks */ +#define HW_SENSORS 11 /* node: hardware monitors */ +#define HW_CPUSPEED 12 /* get CPU frequency */ +#define HW_SETPERF 13 /* set CPU performance % */ +#define HW_VENDOR 14 /* string: vendor name */ +#define HW_PRODUCT 15 /* string: product name */ +#define HW_VERSION 16 /* string: hardware version */ +#define HW_SERIALNO 17 /* string: hardware serial number */ +#define HW_UUID 18 /* string: universal unique id */ +#define HW_PHYSMEM64 19 /* quad: total memory */ +#define HW_USERMEM64 20 /* quad: non-kernel memory */ +#define HW_NCPUFOUND 21 /* int: number of cpus found */ +#define HW_ALLOWPOWERDOWN 22 /* allow power button shutdown */ +#define HW_PERFPOLICY 23 /* set performance policy */ +#define HW_SMT 24 /* int: enable SMT/HT/CMT */ +#define HW_NCPUONLINE 25 /* int: number of cpus being used */ +#define HW_POWER 26 /* int: machine has wall-power */ +#define HW_BATTERY 27 /* node: battery */ +#define HW_UCOMNAMES 28 /* strings: ucom names */ +#define HW_MAXID 29 /* number of valid hw ids */ + +#define CTL_HW_NAMES { \ + { 0, 0 }, \ + { "machine", CTLTYPE_STRING }, \ + { "model", CTLTYPE_STRING }, \ + { "ncpu", CTLTYPE_INT }, \ + { "byteorder", CTLTYPE_INT }, \ + { "gap", 0 }, \ + { "gap", 0 }, \ + { "pagesize", CTLTYPE_INT }, \ + { "disknames", CTLTYPE_STRING }, \ + { "diskstats", CTLTYPE_STRUCT }, \ + { "diskcount", CTLTYPE_INT }, \ + { "sensors", CTLTYPE_NODE}, \ + { "cpuspeed", CTLTYPE_INT }, \ + { "setperf", CTLTYPE_INT }, \ + { "vendor", CTLTYPE_STRING }, \ + { "product", CTLTYPE_STRING }, \ + { "version", CTLTYPE_STRING }, \ + { "serialno", CTLTYPE_STRING }, \ + { "uuid", CTLTYPE_STRING }, \ + { "physmem", CTLTYPE_QUAD }, \ + { "usermem", CTLTYPE_QUAD }, \ + { "ncpufound", CTLTYPE_INT }, \ + { "allowpowerdown", CTLTYPE_INT }, \ + { "perfpolicy", CTLTYPE_STRING }, \ + { "smt", CTLTYPE_INT }, \ + { "ncpuonline", CTLTYPE_INT }, \ + { "power", CTLTYPE_INT }, \ + { "battery", CTLTYPE_NODE }, \ + { "ucomnames", CTLTYPE_STRING }, \ +} + +/* + * HW_BATTERY + */ +#define HW_BATTERY_CHARGEMODE 1 /* int: battery charging mode */ +#define HW_BATTERY_CHARGESTART 2 /* int: battery start charge percent */ +#define HW_BATTERY_CHARGESTOP 3 /* int: battery stop charge percent */ +#define HW_BATTERY_MAXID 4 + +#define CTL_HW_BATTERY_NAMES { \ + { 0, 0 }, \ + { "chargemode", CTLTYPE_INT }, \ + { "chargestart", CTLTYPE_INT }, \ + { "chargestop", CTLTYPE_INT }, \ +} + +/* + * CTL_DEBUG definitions + * + * Second level identifier specifies which debug variable. + * Third level identifier specifies which structure component. + */ +#define CTL_DEBUG_NAME 0 /* string: variable name */ +#define CTL_DEBUG_VALUE 1 /* int: variable value */ +#define CTL_DEBUG_MAXID 20 + +#ifdef _KERNEL +#ifdef DEBUG_SYSCTL +/* + * CTL_DEBUG variables. + * + * These are declared as separate variables so that they can be + * individually initialized at the location of their associated + * variable. The loader prevents multiple use by issuing errors + * if a variable is initialized in more than one place. They are + * aggregated into an array in debug_sysctl(), so that it can + * conveniently locate them when queried. If more debugging + * variables are added, they must also be declared here and also + * entered into the array. + */ +struct ctldebug { + char *debugname; /* name of debugging variable */ + int *debugvar; /* pointer to debugging variable */ +}; +#endif /* DEBUG_SYSCTL */ + +/* + * Exported sysctl variable with valid bounds. Both bounds are inclusive to + * allow full range of values. + */ +struct sysctl_bounded_args { + int mib; /* identifier shared with userspace as a CTL_ #define */ + int *var; /* never NULL */ + int minimum; /* checking is disabled if minimum == maximum */ + int maximum; /* read-only variable if minimum > maximum */ +}; + +/* Special case minimum,maximum marker for sysctl_bounded_args. */ +#define SYSCTL_INT_READONLY 1,0 + +/* + * Internal sysctl function calling convention: + * + * (*sysctlfn)(name, namelen, oldval, oldlenp, newval, newlen); + * + * The name parameter points at the next component of the name to be + * interpreted. The namelen parameter is the number of integers in + * the name. + */ +typedef int (sysctlfn)(int *, u_int, void *, size_t *, void *, size_t, struct proc *); + +extern struct rwlock sysctl_lock; + +int sysctl_vslock(void *, size_t); +void sysctl_vsunlock(void *, size_t); + +int sysctl_int_lower(void *, size_t *, void *, size_t, int *); +int sysctl_int(void *, size_t *, void *, size_t, int *); +int sysctl_rdint(void *, size_t *, void *, int); +int sysctl_securelevel_int(void *, size_t *, void *, size_t, int *); +int sysctl_int_bounded(void *, size_t *, void *, size_t, int *, int, int); +int sysctl_bounded_arr(const struct sysctl_bounded_args *, u_int, + int *, u_int, void *, size_t *, void *, size_t); +int sysctl_rdquad(void *, size_t *, void *, int64_t); +int sysctl_string(void *, size_t *, void *, size_t, char *, size_t); +int sysctl_tstring(void *, size_t *, void *, size_t, char *, size_t); +int sysctl__string(void *, size_t *, void *, size_t, char *, size_t, int); +int sysctl_rdstring(void *, size_t *, void *, const char *); +int sysctl_rdstruct(void *, size_t *, void *, const void *, size_t); +int sysctl_struct(void *, size_t *, void *, size_t, void *, size_t); +int sysctl_file(int *, u_int, char *, size_t *, struct proc *); +int sysctl_doproc(int *, u_int, char *, size_t *); +struct mbuf_queue; +int sysctl_mq(int *, u_int, void *, size_t *, void *, size_t, + struct mbuf_queue *); +struct rtentry; +int sysctl_dumpentry(const struct rtentry *, void *, unsigned int); +int sysctl_rtable(int *, u_int, void *, size_t *, void *, size_t); +int sysctl_clockrate(char *, size_t *, void *); +#if defined(GPROF) || defined(DDBPROF) +int sysctl_doprof(int *, u_int, void *, size_t *, void *, size_t); +#endif +int sysctl_dopool(int *, u_int, char *, size_t *); + +int kern_sysctl(int *, u_int, void *, size_t *, void *, size_t, + struct proc *); +int hw_sysctl(int *, u_int, void *, size_t *, void *, size_t, + struct proc *); +#ifdef DEBUG_SYSCTL +int debug_sysctl(int *, u_int, void *, size_t *, void *, size_t, + struct proc *); +#endif +int net_sysctl(int *, u_int, void *, size_t *, void *, size_t, + struct proc *); +int cpu_sysctl(int *, u_int, void *, size_t *, void *, size_t, + struct proc *); +int vfs_sysctl(int *, u_int, void *, size_t *, void *, size_t, + struct proc *); +int sysctl_sysvipc(int *, u_int, void *, size_t *); +int sysctl_wdog(int *, u_int, void *, size_t *, void *, size_t); + +extern int (*cpu_cpuspeed)(int *); +extern void (*cpu_setperf)(int); + +int net_ifiq_sysctl(int *, u_int, void *, size_t *, void *, size_t); +int bpf_sysctl(int *, u_int, void *, size_t *, void *, size_t); +int pflow_sysctl(int *, u_int, void *, size_t *, void *, size_t); +int pipex_sysctl(int *, u_int, void *, size_t *, void *, size_t); +int mpls_sysctl(int *, u_int, void *, size_t *, void *, size_t); +int pf_sysctl(void *, size_t *, void *, size_t); +int uipc_sysctl(int *, u_int, void *, size_t *, void *, size_t); + +#else /* !_KERNEL */ + +__BEGIN_DECLS +int sysctl(const int *, u_int, void *, size_t *, void *, size_t); +__END_DECLS +#endif /* _KERNEL */ +#endif /* !_SYS_SYSCTL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/syslimits.h b/lib/libc/include/generic-openbsd/sys/syslimits.h new file mode 100644 index 000000000000..976941871c29 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/syslimits.h @@ -0,0 +1,83 @@ +/* $OpenBSD: syslimits.h,v 1.16 2024/08/02 01:53:21 guenther Exp $ */ +/* $NetBSD: syslimits.h,v 1.12 1995/10/05 05:26:19 thorpej Exp $ */ + +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)syslimits.h 8.1 (Berkeley) 6/2/93 + */ + +#include + +#if __POSIX_VISIBLE || __XPG_VISIBLE || __BSD_VISIBLE +#define ARG_MAX (512 * 1024) /* max bytes for an exec function */ +#define CHILD_MAX 80 /* max simultaneous processes */ +#define LINK_MAX 32767 /* max file link count */ +#define MAX_CANON 255 /* max bytes in term canon input line */ +#define MAX_INPUT 255 /* max bytes in terminal input */ +#define NAME_MAX 255 /* max bytes in a file name */ +#define NGROUPS_MAX 16 /* max supplemental group id's */ +#define OPEN_MAX 64 /* max open files per process */ +#define PATH_MAX 1024 /* max bytes in pathname */ +#define PIPE_BUF 512 /* max bytes for atomic pipe writes */ +#define SYMLINK_MAX PATH_MAX /* max bytes in a symbolic link */ +#define SYMLOOP_MAX 32 /* max symlinks per path (for loops) */ + +#define BC_BASE_MAX INT_MAX /* max ibase/obase values in bc(1) */ +#define BC_DIM_MAX 65535 /* max array elements in bc(1) */ +#define BC_SCALE_MAX INT_MAX /* max scale value in bc(1) */ +#define BC_STRING_MAX INT_MAX /* max const string length in bc(1) */ +#define COLL_WEIGHTS_MAX 2 /* max weights for order keyword */ +#define EXPR_NEST_MAX 32 /* max expressions nested in expr(1) */ +#define LINE_MAX 2048 /* max bytes in an input line */ +#ifndef RE_DUP_MAX +#define RE_DUP_MAX 255 /* max RE's in interval notation */ +#define SEM_VALUE_MAX UINT_MAX /* max value of a sem_* semaphore */ +#endif + +#if __XPG_VISIBLE +#define IOV_MAX 1024 /* max # of iov's (readv,sendmsg,etc) */ +#define NZERO 20 /* default "nice" */ +#endif /* __XPG_VISIBLE */ + +#endif /* __POSIX_VISIBLE || __XPG_VISIBLE || __BSD_VISIBLE */ + +#if __XPG_VISIBLE >= 500 || __POSIX_VISIBLE >= 199506 || __BSD_VISIBLE +#define TTY_NAME_MAX 260 /* max tty device name length w/ NUL */ +#define LOGIN_NAME_MAX 32 /* max login name length w/ NUL */ +#endif /* __XPG_VISIBLE >= 500 || __POSIX_VISIBLE >= 199506 || __BSD_VISIBLE */ + +#if __POSIX_VISIBLE >= 200112 +#define HOST_NAME_MAX 255 /* max hostname length w/o NUL */ +#endif + +#if __POSIX_VISIBLE >= 202405 +#define GETENTROPY_MAX 256 /* max bytes from getentropy(2) */ +#endif + +#define _MAXCOMLEN 24 /* includes NUL */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/syslog.h b/lib/libc/include/generic-openbsd/sys/syslog.h new file mode 100644 index 000000000000..b4af686209a4 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/syslog.h @@ -0,0 +1,220 @@ +/* $OpenBSD: syslog.h,v 1.19 2023/04/27 23:16:18 gnezdo Exp $ */ +/* $NetBSD: syslog.h,v 1.14 1996/04/03 20:46:44 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)syslog.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _SYS_SYSLOG_H_ +#define _SYS_SYSLOG_H_ + +#define _PATH_LOG "/dev/log" + +#define LIOCSFD _IOW('l', 127, int) /* set sendsyslog() fd */ + +#define LOG_MAXLINE 8192 /* maximum line length */ + +/* + * priorities/facilities are encoded into a single 32-bit quantity, where the + * bottom 3 bits are the priority (0-7) and the top 28 bits are the facility + * (0-big number). Both the priorities and the facilities map roughly + * one-to-one to strings in the syslogd(8) source code. This mapping is + * included in this file. + * + * priorities (these are ordered) + */ +#define LOG_EMERG 0 /* system is unusable */ +#define LOG_ALERT 1 /* action must be taken immediately */ +#define LOG_CRIT 2 /* critical conditions */ +#define LOG_ERR 3 /* error conditions */ +#define LOG_WARNING 4 /* warning conditions */ +#define LOG_NOTICE 5 /* normal but significant condition */ +#define LOG_INFO 6 /* informational */ +#define LOG_DEBUG 7 /* debug-level messages */ + +#define LOG_PRIMASK 0x07 /* mask to extract priority part (internal) */ + /* extract priority */ +#define LOG_PRI(p) ((p) & LOG_PRIMASK) + +#ifdef SYSLOG_NAMES +#define INTERNAL_NOPRI 0x10 /* the "no priority" priority */ + /* mark "facility" */ +#define INTERNAL_MARK (LOG_NFACILITIES<<3) +typedef struct _code { + char *c_name; + int c_val; +} CODE; + +CODE prioritynames[] = { + { "alert", LOG_ALERT }, + { "crit", LOG_CRIT }, + { "debug", LOG_DEBUG }, + { "emerg", LOG_EMERG }, + { "err", LOG_ERR }, + { "error", LOG_ERR }, /* DEPRECATED */ + { "info", LOG_INFO }, + { "none", INTERNAL_NOPRI }, /* INTERNAL */ + { "notice", LOG_NOTICE }, + { "panic", LOG_EMERG }, /* DEPRECATED */ + { "warn", LOG_WARNING }, /* DEPRECATED */ + { "warning", LOG_WARNING }, + { NULL, -1 }, +}; +#endif + +/* facility codes */ +#define LOG_KERN (0<<3) /* kernel messages */ +#define LOG_USER (1<<3) /* random user-level messages */ +#define LOG_MAIL (2<<3) /* mail system */ +#define LOG_DAEMON (3<<3) /* system daemons */ +#define LOG_AUTH (4<<3) /* security/authorization messages */ +#define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */ +#define LOG_LPR (6<<3) /* line printer subsystem */ +#define LOG_NEWS (7<<3) /* network news subsystem */ +#define LOG_UUCP (8<<3) /* UUCP subsystem */ +#define LOG_CRON (9<<3) /* clock daemon */ +#define LOG_AUTHPRIV (10<<3) /* security/authorization messages (private) */ +#define LOG_FTP (11<<3) /* ftp daemon */ + + /* other codes through 15 reserved for system use */ +#define LOG_LOCAL0 (16<<3) /* reserved for local use */ +#define LOG_LOCAL1 (17<<3) /* reserved for local use */ +#define LOG_LOCAL2 (18<<3) /* reserved for local use */ +#define LOG_LOCAL3 (19<<3) /* reserved for local use */ +#define LOG_LOCAL4 (20<<3) /* reserved for local use */ +#define LOG_LOCAL5 (21<<3) /* reserved for local use */ +#define LOG_LOCAL6 (22<<3) /* reserved for local use */ +#define LOG_LOCAL7 (23<<3) /* reserved for local use */ + +#define LOG_NFACILITIES 24 /* current number of facilities */ +#define LOG_FACMASK 0x03f8 /* mask to extract facility part */ + /* facility of pri */ +#define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3) + +#ifdef SYSLOG_NAMES +CODE facilitynames[] = { + { "auth", LOG_AUTH }, + { "authpriv", LOG_AUTHPRIV }, + { "cron", LOG_CRON }, + { "daemon", LOG_DAEMON }, + { "ftp", LOG_FTP }, + { "kern", LOG_KERN }, + { "lpr", LOG_LPR }, + { "mail", LOG_MAIL }, + { "mark", INTERNAL_MARK }, /* INTERNAL */ + { "news", LOG_NEWS }, + { "security", LOG_AUTH }, /* DEPRECATED */ + { "syslog", LOG_SYSLOG }, + { "user", LOG_USER }, + { "uucp", LOG_UUCP }, + { "local0", LOG_LOCAL0 }, + { "local1", LOG_LOCAL1 }, + { "local2", LOG_LOCAL2 }, + { "local3", LOG_LOCAL3 }, + { "local4", LOG_LOCAL4 }, + { "local5", LOG_LOCAL5 }, + { "local6", LOG_LOCAL6 }, + { "local7", LOG_LOCAL7 }, + { NULL, -1 }, +}; +#endif + +/* Used by reentrant functions */ + +struct syslog_data { + int log_stat; + const char *log_tag; + int log_fac; + int log_mask; +}; + +#define SYSLOG_DATA_INIT {0, (const char *)0, LOG_USER, 0xff} + +#ifdef _KERNEL +#define LOG_PRINTF -1 /* pseudo-priority to indicate use of printf */ +#endif + +/* + * arguments to setlogmask. + */ +#define LOG_MASK(pri) (1 << (pri)) /* mask for one priority */ +#define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1) /* all priorities through pri */ + +/* + * Option flags for openlog. + * + * LOG_ODELAY no longer does anything. + * LOG_NDELAY is the inverse of what it used to be. + */ +#define LOG_PID 0x01 /* log the pid with each message */ +#define LOG_CONS 0x02 /* log on the console if errors in sending */ +#define LOG_ODELAY 0x04 /* delay open until first syslog() (default) */ +#define LOG_NDELAY 0x08 /* don't delay open */ +#define LOG_NOWAIT 0x10 /* don't wait for console forks: DEPRECATED */ +#define LOG_PERROR 0x20 /* log to stderr as well */ + +#ifndef _KERNEL + +/* + * Don't use va_list in the vsyslog() prototype. Va_list is typedef'd + * in . Including it here may collide with the utility's includes. + * It's unreasonable for utilities to have to include it to include , + * so we get __va_list from and use it. + */ +#include +#include + +__BEGIN_DECLS +void closelog(void); +void openlog(const char *, int, int); +int setlogmask(int); +void syslog(int, const char *, ...) + __attribute__((__format__(__syslog__,2,3))); +void vsyslog(int, const char *, __va_list); +void closelog_r(struct syslog_data *); +void openlog_r(const char *, int, int, struct syslog_data *); +int setlogmask_r(int, struct syslog_data *); +void syslog_r(int, struct syslog_data *, const char *, ...) + __attribute__((__format__(__syslog__,3,4))); +void vsyslog_r(int, struct syslog_data *, const char *, __va_list); +int sendsyslog(const char *, __size_t, int); +__END_DECLS + +#else /* !_KERNEL */ + +void logpri(int); +void log(int, const char *, ...) + __attribute__((__format__(__kprintf__,2,3))); +int addlog(const char *, ...) + __attribute__((__format__(__kprintf__,1,2))); +void logwakeup(void); + +#endif /* !_KERNEL */ +#endif /* !_SYS_SYSLOG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/systm.h b/lib/libc/include/generic-openbsd/sys/systm.h new file mode 100644 index 000000000000..1a1aad823050 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/systm.h @@ -0,0 +1,449 @@ +/* $OpenBSD: systm.h,v 1.177 2025/07/28 05:08:35 dlg Exp $ */ +/* $NetBSD: systm.h,v 1.50 1996/06/09 04:55:09 briggs Exp $ */ + +/*- + * Copyright (c) 1982, 1988, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)systm.h 8.4 (Berkeley) 2/23/94 + */ + +#ifndef __SYSTM_H__ +#define __SYSTM_H__ + +#include +#include + +/* + * The `securelevel' variable controls the security level of the system. + * It can only be decreased by process 1 (/sbin/init). + * + * Security levels are as follows: + * -1 permanently insecure mode - always run system in level 0 mode. + * 0 insecure mode - immutable and append-only flags may be turned off. + * All devices may be read or written subject to permission modes. + * 1 secure mode - immutable and append-only flags may not be changed; + * raw disks of mounted filesystems, /dev/mem, and /dev/kmem are + * read-only. + * 2 highly secure mode - same as (1) plus raw disks are always + * read-only whether mounted or not. This level precludes tampering + * with filesystems by unmounting them, but also inhibits running + * newfs while the system is secured. + * + * In normal operation, the system runs in level 0 mode while single user + * and in level 1 mode while multiuser. If level 2 mode is desired while + * running multiuser, it can be set in the multiuser startup script + * (/etc/rc.local) using sysctl(1). If it is desired to run the system + * in level 0 mode while multiuser, initialize the variable securelevel + * in /sys/kern/kern_sysctl.c to -1. Note that it is NOT initialized to + * zero as that would allow the vmunix binary to be patched to -1. + * Without initialization, securelevel loads in the BSS area which only + * comes into existence when the kernel is loaded and hence cannot be + * patched by a stalking hacker. + */ +extern int securelevel; /* system security level */ +extern const char *panicstr; /* panic message */ +extern const char version[]; /* system version */ +extern const char copyright[]; /* system copyright */ +extern const char ostype[]; +extern const char osversion[]; +extern const char osrelease[]; +extern int cold; /* cold start flag initialized in locore */ +extern int db_active; /* running currently inside ddb(4) */ + +extern char *hw_vendor; /* sysctl hw.vendor */ +extern char *hw_prod; /* sysctl hw.product */ +extern char *hw_uuid; /* sysctl hw.uuid */ +extern char *hw_serial; /* sysctl hw.serialno */ +extern char *hw_ver; /* sysctl hw.version */ + +extern int ncpus; /* number of CPUs used */ +extern int ncpusfound; /* number of CPUs found */ +extern int nblkdev; /* number of entries in bdevsw */ +extern int nchrdev; /* number of entries in cdevsw */ + +extern int physmem; /* physical memory */ + +extern dev_t dumpdev; /* dump device */ +extern long dumplo; /* offset into dumpdev */ + +extern dev_t rootdev; /* root device */ +extern u_char bootduid[8]; /* boot device disklabel uid */ +extern u_char rootduid[8]; /* root device disklabel uid */ +extern struct vnode *rootvp; /* vnode equivalent to above */ +extern struct device *rootdv; /* device equivalent to above */ + +extern dev_t swapdev; /* swapping device */ +extern struct vnode *swapdev_vp;/* vnode equivalent to above */ + +extern int nowake; /* dead wakeup(9) channel */ + +#ifdef MP_LOCKDEBUG +extern long __mp_lock_spinout; +#endif + +struct proc; +struct process; +#define curproc curcpu()->ci_curproc + +typedef int sy_call_t(struct proc *, void *, register_t *); + +extern const struct sysent { /* system call table */ + short sy_narg; /* number of args */ + short sy_argsize; /* total size of arguments */ + int sy_flags; + sy_call_t *sy_call; /* implementing function */ +} sysent[]; + +#define SY_NOLOCK 0x01 + +#if _BYTE_ORDER == _BIG_ENDIAN +#define SCARG(p, k) ((p)->k.be.datum) /* get arg from args pointer */ +#elif _BYTE_ORDER == _LITTLE_ENDIAN +#define SCARG(p, k) ((p)->k.le.datum) /* get arg from args pointer */ +#else +#error "what byte order is this machine?" +#endif + +#if defined(_KERNEL) && defined(SYSCALL_DEBUG) +void scdebug_call(struct proc *p, register_t code, const register_t retval[]); +void scdebug_ret(struct proc *p, register_t code, int error, + const register_t retval[]); +#endif /* _KERNEL && SYSCALL_DEBUG */ + +extern int boothowto; /* reboot flags, from console subsystem */ + +extern void (*v_putc)(int); /* Virtual console putc routine */ + +/* + * General function declarations. + */ +int nullop(void *); +int enodev(void); +int enosys(void); +int enoioctl(void); +int enxio(void); +int eopnotsupp(void *); + +void *hashinit(int, int, int, u_long *); +void hashfree(void *, int, int); +int sys_nosys(struct proc *, void *, register_t *); + +void panic(const char *, ...) + __attribute__((__noreturn__,__format__(__kprintf__,1,2))); +void __assert(const char *, const char *, int, const char *) + __attribute__((__noreturn__)); +int printf(const char *, ...) + __attribute__((__format__(__kprintf__,1,2))); +void uprintf(const char *, ...) + __attribute__((__format__(__kprintf__,1,2))); +int vprintf(const char *, va_list) + __attribute__((__format__(__kprintf__,1,0))); +int vsnprintf(char *, size_t, const char *, va_list) + __attribute__((__format__(__kprintf__,3,0))); +int snprintf(char *buf, size_t, const char *, ...) + __attribute__((__format__(__kprintf__,3,4))); +struct tty; +void ttyprintf(struct tty *, const char *, ...) + __attribute__((__format__(__kprintf__,2,3))); + +void splassert_fail(int, int, const char *); +extern int splassert_ctl; + +void assertwaitok(void); + +void tablefull(const char *); + +int kcopy(const void *, void *, size_t) + __attribute__ ((__bounded__(__buffer__,1,3))) + __attribute__ ((__bounded__(__buffer__,2,3))); + +void bcopy(const void *, void *, size_t) + __attribute__ ((__bounded__(__buffer__,1,3))) + __attribute__ ((__bounded__(__buffer__,2,3))); +void bzero(void *, size_t) + __attribute__ ((__bounded__(__buffer__,1,2))); +void explicit_bzero(void *, size_t) + __attribute__ ((__bounded__(__buffer__,1,2))); +int bcmp(const void *, const void *, size_t); +void *memcpy(void *, const void *, size_t) + __attribute__ ((__bounded__(__buffer__,1,3))) + __attribute__ ((__bounded__(__buffer__,2,3))); +void *memmove(void *, const void *, size_t) + __attribute__ ((__bounded__(__buffer__,1,3))) + __attribute__ ((__bounded__(__buffer__,2,3))); +void *memset(void *, int, size_t) + __attribute__ ((__bounded__(__buffer__,1,3))); + +int copyinstr(const void *, void *, size_t, size_t *) + __attribute__ ((__bounded__(__string__,2,3))); +int _copyinstr(const void *, void *, size_t, size_t *) + __attribute__ ((__bounded__(__string__,2,3))); +int copyoutstr(const void *, void *, size_t, size_t *); +int copyin(const void *, void *, size_t) + __attribute__ ((__bounded__(__buffer__,2,3))); +int _copyin(const void *, void *, size_t) + __attribute__ ((__bounded__(__buffer__,2,3))); +int copyout(const void *, void *, size_t); +int copyin32(const uint32_t *, uint32_t *); + +void random_start(int); +void enqueue_randomness(unsigned int); +void suspend_randomness(void); +void resume_randomness(char *, size_t); + +struct arc4random_ctx; +void arc4random_buf(void *, size_t) + __attribute__ ((__bounded__(__buffer__,1,2))); +struct arc4random_ctx *arc4random_ctx_new(void); +void arc4random_ctx_free(struct arc4random_ctx *); +void arc4random_ctx_buf(struct arc4random_ctx *, void *, size_t); +u_int32_t arc4random(void); +u_int32_t arc4random_uniform(u_int32_t); + +struct timeval; +struct timespec; +int tvtohz(const struct timeval *); +int tstohz(const struct timespec *); +void realitexpire(void *); + +extern uint64_t hardclock_period; +extern uint64_t statclock_avg; +extern int statclock_is_randomized; + +struct clockframe; +void hardclock(struct clockframe *); + +struct clockrequest; +void statclock(struct clockrequest *, void *, void *); + +void initclocks(void); +void inittodr(time_t); +void resettodr(void); +void cpu_initclocks(void); +void cpu_startclock(void); + +void startprofclock(struct process *); +void stopprofclock(struct process *); +void setstatclockrate(int); +void prof_fork(struct process *); +void prof_exec(struct process *); +void prof_write(struct proc *); + +void start_periodic_resettodr(void); +void stop_periodic_resettodr(void); + +void sleep_setup(const volatile void *, int, const char *); +int sleep_finish(uint64_t, int); +void sleep_queue_init(void); + +struct cond; +void cond_init(struct cond *); +void cond_wait(struct cond *, const char *); +void cond_signal_handler(void *); + +static inline void +cond_signal(struct cond *c) +{ + cond_signal_handler(c); +} + +#define INFSLP UINT64_MAX +#define MAXTSLP (UINT64_MAX - 1) + +struct mutex; +struct rwlock; +void wakeup_n(const volatile void *, int); +void wakeup(const volatile void *); +#define wakeup_one(c) wakeup_n((c), 1) +int tsleep(const volatile void *, int, const char *, int); +int tsleep_nsec(const volatile void *, int, const char *, uint64_t); +int msleep(const volatile void *, struct mutex *, int, const char*, int); +int msleep_nsec(const volatile void *, struct mutex *, int, const char*, + uint64_t); +int rwsleep(const volatile void *, struct rwlock *, int, const char *, int); +int rwsleep_nsec(const volatile void *, struct rwlock *, int, const char *, + uint64_t); +void yield(void); + +void wdog_register(int (*)(void *, int), void *); +void wdog_shutdown(void *); + +/* + * Startup hooks are functions running after the scheduler has started + * but before any threads have been created or root has been mounted. + */ + +struct hook_desc { + TAILQ_ENTRY(hook_desc) hd_list; + void (*hd_fn)(void *); + void *hd_arg; +}; +TAILQ_HEAD(hook_desc_head, hook_desc); + +extern struct hook_desc_head startuphook_list; + +void *hook_establish(struct hook_desc_head *, int, void (*)(void *), void *); +void hook_disestablish(struct hook_desc_head *, void *); +void dohooks(struct hook_desc_head *, int); + +#define HOOK_REMOVE 0x01 +#define HOOK_FREE 0x02 + +#define startuphook_establish(fn, arg) \ + hook_establish(&startuphook_list, 1, (fn), (arg)) +#define startuphook_disestablish(vhook) \ + hook_disestablish(&startuphook_list, (vhook)) +#define dostartuphooks() dohooks(&startuphook_list, HOOK_REMOVE|HOOK_FREE) + +struct uio; +int uiomove(void *, size_t, struct uio *); + +#if defined(_KERNEL) + +#include + +extern struct rwlock netlock; + +/* + * Network stack data structures are, unless stated otherwise, protected + * by the NET_LOCK(). It's a single non-recursive lock for the whole + * subsystem. + */ +#define NET_LOCK() do { rw_enter_write(&netlock); } while (0) +#define NET_UNLOCK() do { rw_exit_write(&netlock); } while (0) + +/* + * Reader version of NET_LOCK(). + * The "softnet" thread should be the only thread processing packets + * without holding an exclusive lock. This is done to allow read-only + * ioctl(2) to not block. + * Shared lock can be grabbed instead of the exclusive version if no field + * protected by the NET_LOCK() is modified by the ioctl/sysctl. + * Socket system call can use shared netlock if it has additional locks + * to protect socket and pcb data structures. + */ +#define NET_LOCK_SHARED() do { rw_enter_read(&netlock); } while (0) +#define NET_UNLOCK_SHARED() do { rw_exit_read(&netlock); } while (0) + +#ifdef DIAGNOSTIC + +#define NET_ASSERT_UNLOCKED() \ +do { \ + int _s = rw_status(&netlock); \ + if ((splassert_ctl > 0) && (_s == RW_WRITE)) \ + splassert_fail(0, RW_WRITE, __func__); \ +} while (0) + +#define NET_ASSERT_LOCKED() \ +do { \ + int _s = rw_status(&netlock); \ + if ((splassert_ctl > 0) && (_s != RW_WRITE && _s != RW_READ)) \ + splassert_fail(RW_READ, _s, __func__); \ +} while (0) + +#define NET_ASSERT_LOCKED_EXCLUSIVE() \ +do { \ + int _s = rw_status(&netlock); \ + if ((splassert_ctl > 0) && (_s != RW_WRITE)) \ + splassert_fail(RW_WRITE, _s, __func__); \ +} while (0) + +#else /* DIAGNOSTIC */ +#define NET_ASSERT_UNLOCKED() do {} while (0) +#define NET_ASSERT_LOCKED() do {} while (0) +#define NET_ASSERT_LOCKED_EXCLUSIVE() do {} while (0) +#endif /* !DIAGNOSTIC */ + +__returns_twice int setjmp(label_t *); +__dead void longjmp(label_t *); +#endif + +void consinit(void); + +void cpu_startup(void); +void cpu_configure(void); +void diskconf(void); + +void powerbutton_event(void); + +int nfs_mountroot(void); +int dk_mountroot(void); +extern int (*mountroot)(void); + +#include + +#define bzero(b, n) __builtin_bzero((b), (n)) +#define memcmp(b1, b2, n) __builtin_memcmp((b1), (b2), (n)) +#define memcpy(d, s, n) __builtin_memcpy((d), (s), (n)) +#define memset(b, c, n) __builtin_memset((b), (c), (n)) +#if (defined(__GNUC__) && __GNUC__ >= 4) +#define memmove(d, s, n) __builtin_memmove((d), (s), (n)) +#endif +#if !defined(__clang__) && (defined(__GNUC__) && __GNUC__ >= 4) +#define bcmp(b1, b2, n) __builtin_bcmp((b1), (b2), (n)) +#define bcopy(s, d, n) __builtin_bcopy((s), (d), (n)) +#endif + +#if defined(DDB) +/* debugger entry points */ +void db_enter(void); /* in DDB only */ +int db_rint(int); +#endif + +#ifdef BOOT_CONFIG +void user_config(void); +#endif + +#if defined(MULTIPROCESSOR) +void _kernel_lock_init(void); +void _kernel_lock(void); +void _kernel_unlock(void); +int _kernel_lock_held(void); + +#define KERNEL_LOCK_INIT() _kernel_lock_init() +#define KERNEL_LOCK() _kernel_lock() +#define KERNEL_UNLOCK() _kernel_unlock() +#define KERNEL_ASSERT_LOCKED() KASSERT(_kernel_lock_held()) +#define KERNEL_ASSERT_UNLOCKED() KASSERT(panicstr || db_active || !_kernel_lock_held()) + +#else /* ! MULTIPROCESSOR */ + +#define KERNEL_LOCK_INIT() /* nothing */ +#define KERNEL_LOCK() /* nothing */ +#define KERNEL_UNLOCK() /* nothing */ +#define KERNEL_ASSERT_LOCKED() /* nothing */ +#define KERNEL_ASSERT_UNLOCKED() /* nothing */ + +#endif /* MULTIPROCESSOR */ + +#endif /* __SYSTM_H__ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/task.h b/lib/libc/include/generic-openbsd/sys/task.h new file mode 100644 index 000000000000..98706b00f3be --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/task.h @@ -0,0 +1,62 @@ +/* $OpenBSD: task.h,v 1.18 2020/08/01 08:40:20 anton Exp $ */ + +/* + * Copyright (c) 2013 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_TASK_H_ +#define _SYS_TASK_H_ + +#include + +struct taskq; + +struct task { + TAILQ_ENTRY(task) t_entry; + void (*t_func)(void *); + void *t_arg; + unsigned int t_flags; +#if 1 /* NKCOV > 0 */ + struct process *t_process; +#endif +}; + +#define TASK_ONQUEUE 1 + +TAILQ_HEAD(task_list, task); + +#define TASKQ_MPSAFE (1 << 0) + +#define TASK_INITIALIZER(_f, _a) {{ NULL, NULL }, (_f), (_a), 0 } + +#ifdef _KERNEL +extern struct taskq *const systq; +extern struct taskq *const systqmp; + +struct taskq *taskq_create(const char *, unsigned int, int, unsigned int); +void taskq_destroy(struct taskq *); +void taskq_barrier(struct taskq *); + +void taskq_del_barrier(struct taskq *, struct task *); + +void task_set(struct task *, void (*)(void *), void *); +int task_add(struct taskq *, struct task *); +int task_del(struct taskq *, struct task *); + +#define task_pending(_t) ((_t)->t_flags & TASK_ONQUEUE) + +#endif /* _KERNEL */ + +#endif /* _SYS_TASK_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/termios.h b/lib/libc/include/generic-openbsd/sys/termios.h new file mode 100644 index 000000000000..3845c34501af --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/termios.h @@ -0,0 +1,304 @@ +/* $OpenBSD: termios.h,v 1.14 2022/12/30 23:41:45 millert Exp $ */ +/* $NetBSD: termios.h,v 1.14 1996/04/09 20:55:41 cgd Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)termios.h 8.3 (Berkeley) 3/28/94 + */ + +#ifndef _SYS_TERMIOS_H_ +#define _SYS_TERMIOS_H_ + +#include + +/* + * Special Control Characters + * + * Index into c_cc[] character array. + * + * Name Subscript Enabled by + */ +#define VEOF 0 /* ICANON */ +#define VEOL 1 /* ICANON */ +#if __BSD_VISIBLE +#define VEOL2 2 /* ICANON */ +#endif +#define VERASE 3 /* ICANON */ +#if __BSD_VISIBLE +#define VWERASE 4 /* ICANON */ +#endif +#define VKILL 5 /* ICANON */ +#if __BSD_VISIBLE +#define VREPRINT 6 /* ICANON */ +#endif +/* 7 spare 1 */ +#define VINTR 8 /* ISIG */ +#define VQUIT 9 /* ISIG */ +#define VSUSP 10 /* ISIG */ +#if __BSD_VISIBLE +#define VDSUSP 11 /* ISIG */ +#endif +#define VSTART 12 /* IXON, IXOFF */ +#define VSTOP 13 /* IXON, IXOFF */ +#if __BSD_VISIBLE +#define VLNEXT 14 /* IEXTEN */ +#define VDISCARD 15 /* IEXTEN */ +#endif +#define VMIN 16 /* !ICANON */ +#define VTIME 17 /* !ICANON */ +#if __BSD_VISIBLE +#define VSTATUS 18 /* ICANON */ +/* 19 spare 2 */ +#endif +#define NCCS 20 + +#define _POSIX_VDISABLE (0377) + +#if __BSD_VISIBLE +#define CCEQ(val, c) (c == val ? val != _POSIX_VDISABLE : 0) +#endif + +/* + * Input flags - software input processing + */ +#define IGNBRK 0x00000001 /* ignore BREAK condition */ +#define BRKINT 0x00000002 /* map BREAK to SIGINT */ +#define IGNPAR 0x00000004 /* ignore (discard) parity errors */ +#define PARMRK 0x00000008 /* mark parity and framing errors */ +#define INPCK 0x00000010 /* enable checking of parity errors */ +#define ISTRIP 0x00000020 /* strip 8th bit off chars */ +#define INLCR 0x00000040 /* map NL into CR */ +#define IGNCR 0x00000080 /* ignore CR */ +#define ICRNL 0x00000100 /* map CR to NL (ala CRMOD) */ +#define IXON 0x00000200 /* enable output flow control */ +#define IXOFF 0x00000400 /* enable input flow control */ +#if __BSD_VISIBLE +#define IXANY 0x00000800 /* any char will restart after stop */ +#define IUCLC 0x00001000 /* translate upper to lower case */ +#define IMAXBEL 0x00002000 /* ring bell on input queue full */ +#endif /* __BSD_VISIBLE */ + +/* + * Output flags - software output processing + */ +#define OPOST 0x00000001 /* enable following output processing */ +#if __XPG_VISIBLE +#define ONLCR 0x00000002 /* map NL to CR-NL (ala CRMOD) */ +#endif +#if __BSD_VISIBLE || __XPG_VISIBLE +#define TABDLY 0x00000004 /* horizontal tab delay mask */ +#define TAB0 0x00000000 /* no tab delay or expansion */ +#define TAB3 0x00000004 /* expand tabs to spaces */ +#if __BSD_VISIBLE +#define OXTABS TAB3 /* BSD name for TAB3 */ +#define ONOEOT 0x00000008 /* discard EOT's (^D) on output */ +#endif +#endif +#if __XPG_VISIBLE +#define OCRNL 0x00000010 /* map CR to NL */ +#define OLCUC 0x00000020 /* translate lower case to upper case */ +#define ONOCR 0x00000040 /* No CR output at column 0 */ +#define ONLRET 0x00000080 /* NL performs the CR function */ +#endif /* __XPG_VISIBLE */ + +/* + * Control flags - hardware control of terminal + */ +#if __BSD_VISIBLE +#define CIGNORE 0x00000001 /* ignore control flags */ +#endif +#define CSIZE 0x00000300 /* character size mask */ +#define CS5 0x00000000 /* 5 bits (pseudo) */ +#define CS6 0x00000100 /* 6 bits */ +#define CS7 0x00000200 /* 7 bits */ +#define CS8 0x00000300 /* 8 bits */ +#define CSTOPB 0x00000400 /* send 2 stop bits */ +#define CREAD 0x00000800 /* enable receiver */ +#define PARENB 0x00001000 /* parity enable */ +#define PARODD 0x00002000 /* odd parity, else even */ +#define HUPCL 0x00004000 /* hang up on last close */ +#define CLOCAL 0x00008000 /* ignore modem status lines */ +#if __BSD_VISIBLE +#define CRTSCTS 0x00010000 /* RTS/CTS full-duplex flow control */ +#define CRTS_IFLOW CRTSCTS /* XXX compat */ +#define CCTS_OFLOW CRTSCTS /* XXX compat */ +#define MDMBUF 0x00100000 /* DTR/DCD hardware flow control */ +#define CHWFLOW (MDMBUF|CRTSCTS) /* all types of hw flow control */ +#endif /* __BSD_VISIBLE */ + +/* + * "Local" flags - dumping ground for other state + * + * Warning: some flags in this structure begin with + * the letter "I" and look like they belong in the + * input flag. + */ + +#if __BSD_VISIBLE +#define ECHOKE 0x00000001 /* visual erase for line kill */ +#endif +#define ECHOE 0x00000002 /* visually erase chars */ +#define ECHOK 0x00000004 /* echo NL after line kill */ +#define ECHO 0x00000008 /* enable echoing */ +#define ECHONL 0x00000010 /* echo NL even if ECHO is off */ +#if __BSD_VISIBLE +#define ECHOPRT 0x00000020 /* visual erase mode for hardcopy */ +#define ECHOCTL 0x00000040 /* echo control chars as ^(Char) */ +#endif +#define ISIG 0x00000080 /* enable signals INTR, QUIT, [D]SUSP */ +#define ICANON 0x00000100 /* canonicalize input lines */ +#if __BSD_VISIBLE +#define ALTWERASE 0x00000200 /* use alternate WERASE algorithm */ +#endif +#define IEXTEN 0x00000400 /* enable DISCARD and LNEXT */ +#define EXTPROC 0x00000800 /* external processing */ +#define TOSTOP 0x00400000 /* stop background jobs from output */ +#if __BSD_VISIBLE +#define FLUSHO 0x00800000 /* output being flushed (state) */ +#define XCASE 0x01000000 /* canonical upper/lower case */ +#define NOKERNINFO 0x02000000 /* no kernel output from VSTATUS */ +#define PENDIN 0x20000000 /* XXX retype pending input (state) */ +#endif +#define NOFLSH 0x80000000 /* don't flush after interrupt */ + +typedef unsigned int tcflag_t; +typedef unsigned char cc_t; +typedef unsigned int speed_t; + +struct termios { + tcflag_t c_iflag; /* input flags */ + tcflag_t c_oflag; /* output flags */ + tcflag_t c_cflag; /* control flags */ + tcflag_t c_lflag; /* local flags */ + cc_t c_cc[NCCS]; /* control chars */ + int c_ispeed; /* input speed */ + int c_ospeed; /* output speed */ +}; + +/* + * Commands passed to tcsetattr() for setting the termios structure. + */ +#define TCSANOW 0 /* make change immediate */ +#define TCSADRAIN 1 /* drain output, then change */ +#define TCSAFLUSH 2 /* drain output, flush input */ +#if __BSD_VISIBLE +#define TCSASOFT 0x10 /* flag - don't alter h.w. state */ +#endif + +/* + * Standard speeds + */ +#define B0 0 +#define B50 50 +#define B75 75 +#define B110 110 +#define B134 134 +#define B150 150 +#define B200 200 +#define B300 300 +#define B600 600 +#define B1200 1200 +#define B1800 1800 +#define B2400 2400 +#define B4800 4800 +#define B9600 9600 +#define B19200 19200 +#define B38400 38400 +#if __BSD_VISIBLE +#define B7200 7200 +#define B14400 14400 +#define B28800 28800 +#define B57600 57600 +#define B76800 76800 +#define B115200 115200 +#define B230400 230400 +#define EXTA 19200 +#define EXTB 38400 +#endif /* __BSD_VISIBLE */ + +#ifndef _KERNEL + +#define TCIFLUSH 1 +#define TCOFLUSH 2 +#define TCIOFLUSH 3 +#define TCOOFF 1 +#define TCOON 2 +#define TCIOFF 3 +#define TCION 4 + +#include + +#if __XPG_VISIBLE >= 420 || __POSIX_VISIBLE >= 200809 +#ifndef _PID_T_DEFINED_ +#define _PID_T_DEFINED_ +typedef __pid_t pid_t; +#endif +#endif + +__BEGIN_DECLS +speed_t cfgetispeed(const struct termios *); +speed_t cfgetospeed(const struct termios *); +int cfsetispeed(struct termios *, speed_t); +int cfsetospeed(struct termios *, speed_t); +int tcgetattr(int, struct termios *); +int tcsetattr(int, int, const struct termios *); +int tcdrain(int); +int tcflow(int, int); +int tcflush(int, int); +int tcsendbreak(int, int); + +#if __XPG_VISIBLE >= 420 || __POSIX_VISIBLE >= 200809 +pid_t tcgetsid(int); +#endif + +#if __BSD_VISIBLE +void cfmakeraw(struct termios *); +int cfsetspeed(struct termios *, speed_t); +#endif /* __BSD_VISIBLE */ +__END_DECLS + +#endif /* !_KERNEL */ + +#if __BSD_VISIBLE +/* + * Include tty ioctl's that aren't just for backwards compatibility + * with the old tty driver. These ioctl definitions were previously + * in . + */ +#include +#endif + +/* + * END OF PROTECTED INCLUDE. + */ +#endif /* !_SYS_TERMIOS_H_ */ + +#if __BSD_VISIBLE +#include +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/time.h b/lib/libc/include/generic-openbsd/sys/time.h new file mode 100644 index 000000000000..7c4a69a85483 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/time.h @@ -0,0 +1,473 @@ +/* $OpenBSD: time.h,v 1.67 2025/06/05 08:49:09 claudio Exp $ */ +/* $NetBSD: time.h,v 1.18 1996/04/23 10:29:33 mycroft Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)time.h 8.2 (Berkeley) 7/10/94 + */ + +#ifndef _SYS_TIME_H_ +#define _SYS_TIME_H_ + +#include + +#ifndef _TIMEVAL_DECLARED +#define _TIMEVAL_DECLARED +/* + * Structure returned by gettimeofday(2) system call, + * and used in other calls. + */ +struct timeval { + time_t tv_sec; /* seconds */ + suseconds_t tv_usec; /* and microseconds */ +}; +#endif + +#ifndef _TIMESPEC_DECLARED +#define _TIMESPEC_DECLARED +/* + * Structure defined by POSIX.1b to be like a timeval. + */ +struct timespec { + time_t tv_sec; /* seconds */ + long tv_nsec; /* and nanoseconds */ +}; +#endif + +#define TIMEVAL_TO_TIMESPEC(tv, ts) do { \ + (ts)->tv_sec = (tv)->tv_sec; \ + (ts)->tv_nsec = (tv)->tv_usec * 1000; \ +} while (0) +#define TIMESPEC_TO_TIMEVAL(tv, ts) do { \ + (tv)->tv_sec = (ts)->tv_sec; \ + (tv)->tv_usec = (ts)->tv_nsec / 1000; \ +} while (0) + +struct timezone { + int tz_minuteswest; /* minutes west of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; +#define DST_NONE 0 /* not on dst */ +#define DST_USA 1 /* USA style dst */ +#define DST_AUST 2 /* Australian style dst */ +#define DST_WET 3 /* Western European dst */ +#define DST_MET 4 /* Middle European dst */ +#define DST_EET 5 /* Eastern European dst */ +#define DST_CAN 6 /* Canada */ + +/* Operations on timevals. */ +#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 +#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) +#define timerisvalid(tvp) \ + ((tvp)->tv_usec >= 0 && (tvp)->tv_usec < 1000000) +#define timercmp(tvp, uvp, cmp) \ + (((tvp)->tv_sec == (uvp)->tv_sec) ? \ + ((tvp)->tv_usec cmp (uvp)->tv_usec) : \ + ((tvp)->tv_sec cmp (uvp)->tv_sec)) +#define timeradd(tvp, uvp, vvp) \ + do { \ + (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \ + (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \ + if ((vvp)->tv_usec >= 1000000) { \ + (vvp)->tv_sec++; \ + (vvp)->tv_usec -= 1000000; \ + } \ + } while (0) +#define timersub(tvp, uvp, vvp) \ + do { \ + (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ + (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ + if ((vvp)->tv_usec < 0) { \ + (vvp)->tv_sec--; \ + (vvp)->tv_usec += 1000000; \ + } \ + } while (0) + +/* Operations on timespecs. */ +#define timespecclear(tsp) (tsp)->tv_sec = (tsp)->tv_nsec = 0 +#define timespecisset(tsp) ((tsp)->tv_sec || (tsp)->tv_nsec) +#define timespecisvalid(tsp) \ + ((tsp)->tv_nsec >= 0 && (tsp)->tv_nsec < 1000000000L) +#define timespeccmp(tsp, usp, cmp) \ + (((tsp)->tv_sec == (usp)->tv_sec) ? \ + ((tsp)->tv_nsec cmp (usp)->tv_nsec) : \ + ((tsp)->tv_sec cmp (usp)->tv_sec)) +#define timespecadd(tsp, usp, vsp) \ + do { \ + (vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec; \ + (vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec; \ + if ((vsp)->tv_nsec >= 1000000000L) { \ + (vsp)->tv_sec++; \ + (vsp)->tv_nsec -= 1000000000L; \ + } \ + } while (0) +#define timespecsub(tsp, usp, vsp) \ + do { \ + (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \ + (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \ + if ((vsp)->tv_nsec < 0) { \ + (vsp)->tv_sec--; \ + (vsp)->tv_nsec += 1000000000L; \ + } \ + } while (0) + +/* + * Names of the interval timers, and structure + * defining a timer setting. + */ +#define ITIMER_REAL 0 +#define ITIMER_VIRTUAL 1 +#define ITIMER_PROF 2 + +struct itimerval { + struct timeval it_interval; /* timer interval */ + struct timeval it_value; /* current value */ +}; + +#if __BSD_VISIBLE +/* + * clock information structure for sysctl({CTL_KERN, KERN_CLOCKRATE}) + */ +struct clockinfo { + int hz; /* clock frequency */ + int tick; /* micro-seconds per hz tick */ + int stathz; /* statistics clock frequency */ + int profhz; /* profiling clock frequency */ +}; +#endif /* __BSD_VISIBLE */ + +#if defined(_KERNEL) || defined(_STANDALONE) || defined (_LIBC) +#include + +/* Time expressed as seconds and fractions of a second + operations on it. */ +struct bintime { + time_t sec; + uint64_t frac; +}; +#endif + +#if defined(_KERNEL) || defined(_STANDALONE) || defined (_LIBC) + +#define bintimecmp(btp, ctp, cmp) \ + ((btp)->sec == (ctp)->sec ? \ + (btp)->frac cmp (ctp)->frac : \ + (btp)->sec cmp (ctp)->sec) + +static inline void +bintimeaddfrac(const struct bintime *bt, uint64_t x, struct bintime *ct) +{ + ct->sec = bt->sec; + if (bt->frac > bt->frac + x) + ct->sec++; + ct->frac = bt->frac + x; +} + +static inline void +bintimeadd(const struct bintime *bt, const struct bintime *ct, + struct bintime *dt) +{ + dt->sec = bt->sec + ct->sec; + if (bt->frac > bt->frac + ct->frac) + dt->sec++; + dt->frac = bt->frac + ct->frac; +} + +static inline void +bintimesub(const struct bintime *bt, const struct bintime *ct, + struct bintime *dt) +{ + dt->sec = bt->sec - ct->sec; + if (bt->frac < bt->frac - ct->frac) + dt->sec--; + dt->frac = bt->frac - ct->frac; +} + +static inline void +TIMECOUNT_TO_BINTIME(u_int count, uint64_t scale, struct bintime *bt) +{ + uint64_t hi64; + + hi64 = count * (scale >> 32); + bt->sec = hi64 >> 32; + bt->frac = hi64 << 32; + bintimeaddfrac(bt, count * (scale & 0xffffffff), bt); +} + +/*- + * Background information: + * + * When converting between timestamps on parallel timescales of differing + * resolutions it is historical and scientific practice to round down rather + * than doing 4/5 rounding. + * + * The date changes at midnight, not at noon. + * + * Even at 15:59:59.999999999 it's not four'o'clock. + * + * time_second ticks after N.999999999 not after N.4999999999 + */ + +static inline uint32_t +FRAC_TO_NSEC(uint64_t frac) +{ + return ((frac >> 32) * 1000000000ULL) >> 32; +} + +static inline void +BINTIME_TO_TIMESPEC(const struct bintime *bt, struct timespec *ts) +{ + ts->tv_sec = bt->sec; + ts->tv_nsec = FRAC_TO_NSEC(bt->frac); +} + +static inline void +TIMESPEC_TO_BINTIME(const struct timespec *ts, struct bintime *bt) +{ + bt->sec = ts->tv_sec; + /* 18446744073 = int(2^64 / 1000000000) */ + bt->frac = (uint64_t)ts->tv_nsec * (uint64_t)18446744073ULL; +} + +static inline void +BINTIME_TO_TIMEVAL(const struct bintime *bt, struct timeval *tv) +{ + tv->tv_sec = bt->sec; + tv->tv_usec = (long)(((uint64_t)1000000 * (uint32_t)(bt->frac >> 32)) >> 32); +} + +static inline void +TIMEVAL_TO_BINTIME(const struct timeval *tv, struct bintime *bt) +{ + bt->sec = (time_t)tv->tv_sec; + /* 18446744073709 = int(2^64 / 1000000) */ + bt->frac = (uint64_t)tv->tv_usec * (uint64_t)18446744073709ULL; +} +#endif + +#if defined(_KERNEL) || defined(_STANDALONE) + +/* + * Functions for looking at our clocks: [get]{bin,nano,micro}[boot|up]time() + * + * Functions without the "get" prefix returns the best timestamp + * we can produce in the given format. + * + * "bin" == struct bintime == seconds + 64 bit fraction of seconds. + * "nano" == struct timespec == seconds + nanoseconds. + * "micro" == struct timeval == seconds + microseconds. + * + * Functions containing "up" returns time relative to boot and + * should be used for calculating time intervals. + * + * Functions containing "boot" return the GMT time at which the + * system booted. + * + * Functions with just "time" return the current GMT time. + * + * Functions with the "get" prefix returns a less precise result + * much faster than the functions without "get" prefix and should + * be used where a precision of 10 msec is acceptable or where + * performance is priority. (NB: "precision", _not_ "resolution" !) + */ + +void bintime(struct bintime *); +void nanotime(struct timespec *); +void microtime(struct timeval *); + +void getnanotime(struct timespec *); +void getmicrotime(struct timeval *); + +void binuptime(struct bintime *); +void nanouptime(struct timespec *); +void microuptime(struct timeval *); + +void getbinuptime(struct bintime *); +void getnanouptime(struct timespec *); +void getmicrouptime(struct timeval *); + +void binboottime(struct bintime *); +void microboottime(struct timeval *); +void nanoboottime(struct timespec *); + +void binruntime(struct bintime *); +void nanoruntime(struct timespec *); + +void getbinruntime(struct bintime *); +uint64_t getnsecruntime(void); + +time_t gettime(void); +time_t getuptime(void); + +uint64_t nsecuptime(void); +uint64_t getnsecuptime(void); + +struct proc; +int clock_gettime(struct proc *, clockid_t, struct timespec *); + +struct clockrequest; +void itimer_update(struct clockrequest *, void *, void *); + +void cancel_all_itimers(void); +int settime(const struct timespec *); +int ratecheck(struct timeval *, const struct timeval *); +int ppsratecheck(struct timeval *, int *, int); + +/* + * "POSIX time" to/from "YY/MM/DD/hh/mm/ss" + */ +struct clock_ymdhms { + u_short dt_year; + u_char dt_mon; + u_char dt_day; + u_char dt_wday; /* Day of week */ + u_char dt_hour; + u_char dt_min; + u_char dt_sec; +}; + +time_t clock_ymdhms_to_secs(struct clock_ymdhms *); +void clock_secs_to_ymdhms(time_t, struct clock_ymdhms *); +/* + * BCD to decimal and decimal to BCD. + */ +#define FROMBCD(x) (((x) >> 4) * 10 + ((x) & 0xf)) +#define TOBCD(x) (((x) / 10 * 16) + ((x) % 10)) + +/* Some handy constants. */ +#define SECDAY 86400L +#define SECYR (SECDAY * 365) + +/* Traditional POSIX base year */ +#define POSIX_BASE_YEAR 1970 + +#include + +static inline void +USEC_TO_TIMEVAL(uint64_t us, struct timeval *tv) +{ + tv->tv_sec = us / 1000000; + tv->tv_usec = us % 1000000; +} + +static inline void +NSEC_TO_TIMEVAL(uint64_t ns, struct timeval *tv) +{ + tv->tv_sec = ns / 1000000000L; + tv->tv_usec = (ns % 1000000000L) / 1000; +} + +static inline uint64_t +TIMEVAL_TO_NSEC(const struct timeval *tv) +{ + uint64_t nsecs; + + if (tv->tv_sec > UINT64_MAX / 1000000000ULL) + return UINT64_MAX; + nsecs = tv->tv_sec * 1000000000ULL; + if (tv->tv_usec * 1000ULL > UINT64_MAX - nsecs) + return UINT64_MAX; + return nsecs + tv->tv_usec * 1000ULL; +} + +static inline void +NSEC_TO_TIMESPEC(uint64_t ns, struct timespec *ts) +{ + ts->tv_sec = ns / 1000000000L; + ts->tv_nsec = ns % 1000000000L; +} + +static inline uint64_t +SEC_TO_NSEC(uint64_t seconds) +{ + if (seconds > UINT64_MAX / 1000000000ULL) + return UINT64_MAX; + return seconds * 1000000000ULL; +} + +static inline uint64_t +MSEC_TO_NSEC(uint64_t milliseconds) +{ + if (milliseconds > UINT64_MAX / 1000000ULL) + return UINT64_MAX; + return milliseconds * 1000000ULL; +} + +static inline uint64_t +USEC_TO_NSEC(uint64_t microseconds) +{ + if (microseconds > UINT64_MAX / 1000ULL) + return UINT64_MAX; + return microseconds * 1000ULL; +} + +static inline uint64_t +TIMESPEC_TO_NSEC(const struct timespec *ts) +{ + if (ts->tv_sec > (UINT64_MAX - ts->tv_nsec) / 1000000000ULL) + return UINT64_MAX; + return ts->tv_sec * 1000000000ULL + ts->tv_nsec; +} + +static inline uint64_t +BINTIME_TO_NSEC(const struct bintime *bt) +{ + return bt->sec * 1000000000ULL + FRAC_TO_NSEC(bt->frac); +} + +extern int tick_nsec; + +static inline uint64_t +TICKS_TO_NSEC(uint64_t ticks) +{ + return ticks * tick_nsec; +} + +#else /* !_KERNEL */ +#include + +#if __BSD_VISIBLE || __XPG_VISIBLE +__BEGIN_DECLS +#if __BSD_VISIBLE +int adjtime(const struct timeval *, struct timeval *); +int adjfreq(const int64_t *, int64_t *); +#endif +#if __XPG_VISIBLE +int futimes(int, const struct timeval *); +int getitimer(int, struct itimerval *); +int gettimeofday(struct timeval *, struct timezone *); +int setitimer(int, const struct itimerval *, struct itimerval *); +int settimeofday(const struct timeval *, const struct timezone *); +int utimes(const char *, const struct timeval *); +#endif /* __XPG_VISIBLE */ +__END_DECLS +#endif /* __BSD_VISIBLE || __XPG_VISIBLE */ + +#endif /* !_KERNEL */ + +#endif /* !_SYS_TIME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/timeout.h b/lib/libc/include/generic-openbsd/sys/timeout.h new file mode 100644 index 000000000000..4bb7ef1555ff --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/timeout.h @@ -0,0 +1,126 @@ +/* $OpenBSD: timeout.h,v 1.51 2025/05/23 23:56:14 dlg Exp $ */ +/* + * Copyright (c) 2000-2001 Artur Grabowski + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_TIMEOUT_H_ +#define _SYS_TIMEOUT_H_ + +#include + +struct circq { + struct circq *next; /* next element */ + struct circq *prev; /* previous element */ +}; + +struct timeout { + struct circq to_list; /* timeout queue, don't move */ + struct timespec to_abstime; /* absolute time to run at */ + void (*to_func)(void *); /* function to call */ + void *to_arg; /* function argument */ +#if 1 /* NKCOV > 0 */ + struct process *to_process; /* kcov identifier */ +#endif + int to_time; /* ticks on event */ + int to_flags; /* misc flags */ + int to_kclock; /* abstime's kernel clock */ +}; + +/* + * flags in the to_flags field. + */ +#define TIMEOUT_PROC 0x01 /* needs a process context */ +#define TIMEOUT_ONQUEUE 0x02 /* on any timeout queue */ +#define TIMEOUT_INITIALIZED 0x04 /* initialized */ +#define TIMEOUT_TRIGGERED 0x08 /* running or ran */ +#define TIMEOUT_MPSAFE 0x10 /* run without kernel lock */ + +struct timeoutstat { + uint64_t tos_added; /* timeout_add*(9) calls */ + uint64_t tos_cancelled; /* dequeued during timeout_del*(9) */ + uint64_t tos_deleted; /* timeout_del*(9) calls */ + uint64_t tos_late; /* run after deadline */ + uint64_t tos_pending; /* number currently ONQUEUE */ + uint64_t tos_readded; /* timeout_add*(9) + already ONQUEUE */ + uint64_t tos_rescheduled; /* bucketed + already SCHEDULED */ + uint64_t tos_run_softclock; /* run from softclock() */ + uint64_t tos_run_thread; /* run from softclock_thread() */ + uint64_t tos_scheduled; /* bucketed during softclock() */ + uint64_t tos_softclocks; /* softclock() calls */ + uint64_t tos_thread_wakeups; /* wakeups in softclock_thread() */ +}; + +#ifdef _KERNEL +int timeout_sysctl(void *, size_t *, void *, size_t); + +/* + * special macros + * + * timeout_pending(to) - is this timeout already scheduled to run? + * timeout_initialized(to) - is this timeout initialized? + */ +#define timeout_pending(to) ((to)->to_flags & TIMEOUT_ONQUEUE) +#define timeout_initialized(to) ((to)->to_flags & TIMEOUT_INITIALIZED) +#define timeout_triggered(to) ((to)->to_flags & TIMEOUT_TRIGGERED) + +#define KCLOCK_NONE (-1) /* dummy clock for sanity checks */ +#define KCLOCK_UPTIME 0 /* uptime clock; time since boot */ +#define KCLOCK_MAX 1 + +#define TIMEOUT_INITIALIZER_FLAGS(_fn, _arg, _kclock, _flags) { \ + .to_list = { NULL, NULL }, \ + .to_abstime = { .tv_sec = 0, .tv_nsec = 0 }, \ + .to_func = (_fn), \ + .to_arg = (_arg), \ + .to_time = 0, \ + .to_flags = (_flags) | TIMEOUT_INITIALIZED, \ + .to_kclock = (_kclock) \ +} + +#define TIMEOUT_INITIALIZER(_f, _a) \ + TIMEOUT_INITIALIZER_FLAGS((_f), (_a), KCLOCK_NONE, 0) + +void timeout_set(struct timeout *, void (*)(void *), void *); +void timeout_set_flags(struct timeout *, void (*)(void *), void *, int, int); +void timeout_set_proc(struct timeout *, void (*)(void *), void *); + +int timeout_add(struct timeout *, int); +int timeout_add_sec(struct timeout *, int); +int timeout_add_msec(struct timeout *, uint64_t); +int timeout_add_usec(struct timeout *, uint64_t); +int timeout_add_nsec(struct timeout *, uint64_t); + +int timeout_abs_ts(struct timeout *, const struct timespec *); + +int timeout_del(struct timeout *); +int timeout_del_barrier(struct timeout *); +void timeout_barrier(struct timeout *); + +void timeout_adjust_ticks(int); +void timeout_hardclock_update(void); +void timeout_startup(void); + +#endif /* _KERNEL */ + +#endif /* _SYS_TIMEOUT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/times.h b/lib/libc/include/generic-openbsd/sys/times.h new file mode 100644 index 000000000000..dec9d906877b --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/times.h @@ -0,0 +1,63 @@ +/* $OpenBSD: times.h,v 1.6 2013/07/06 18:44:21 naddy Exp $ */ +/* $NetBSD: times.h,v 1.8 1995/03/26 20:24:54 jtc Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)times.h 8.4 (Berkeley) 1/21/94 + */ + +#ifndef _SYS_TIMES_H_ +#define _SYS_TIMES_H_ + +#include +#include + +#ifndef _CLOCK_T_DEFINED_ +#define _CLOCK_T_DEFINED_ +typedef __clock_t clock_t; +#endif + +struct tms { + clock_t tms_utime; /* User CPU time */ + clock_t tms_stime; /* System CPU time */ + clock_t tms_cutime; /* User CPU time of terminated child procs */ + clock_t tms_cstime; /* System CPU time of terminated child procs */ +}; + +#ifndef _KERNEL +__BEGIN_DECLS +clock_t times(struct tms *); +__END_DECLS +#endif +#endif /* !_SYS_TIMES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/timetc.h b/lib/libc/include/generic-openbsd/sys/timetc.h new file mode 100644 index 000000000000..9dcb1cf390b0 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/timetc.h @@ -0,0 +1,124 @@ +/* $OpenBSD: timetc.h,v 1.14 2023/02/04 19:19:35 cheloha Exp $ */ + +/* + * Copyright (c) 2000 Poul-Henning Kamp + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * If we meet some day, and you think this stuff is worth it, you + * can buy me a beer in return. Poul-Henning Kamp + */ + +#ifndef _SYS_TIMETC_H_ +#define _SYS_TIMETC_H_ + +#if !defined(_KERNEL) && !defined(_LIBC) +#error "no user-serviceable parts inside" +#endif + +#include +#include + +/*- + * `struct timecounter' is the interface between the hardware which implements + * a timecounter and the MI code which uses this to keep track of time. + * + * A timecounter is a binary counter which has two properties: + * * it runs at a fixed, known frequency. + * * it has sufficient bits to not roll over in less than approximately + * max(2 msec, 2/HZ seconds). (The value 2 here is really 1 + delta, + * for some indeterminate value of delta.) + */ + +struct timecounter; +typedef u_int timecounter_get_t(struct timecounter *); + +/* + * Locks used to protect struct members in this file: + * I immutable after initialization + * T tc_lock + * W windup_mtx + */ + +struct timecounter { + timecounter_get_t *tc_get_timecount; /* [I] */ + /* + * This function reads the counter. It is not required to + * mask any unimplemented bits out, as long as they are + * constant. + */ + u_int tc_counter_mask; /* [I] */ + /* This mask should mask off any unimplemented bits. */ + u_int64_t tc_frequency; /* [I] */ + /* Frequency of the counter in Hz. */ + char *tc_name; /* [I] */ + /* Name of the timecounter. */ + int tc_quality; /* [I] */ + /* + * Used to determine if this timecounter is better than + * another timecounter higher means better. Negative + * means "only use at explicit request". + */ + void *tc_priv; /* [I] */ + /* Pointer to the timecounter's private parts. */ + int tc_user; /* [I] */ + /* Expose this timecounter to userland. */ + SLIST_ENTRY(timecounter) tc_next; /* [I] */ + /* Pointer to the next timecounter. */ + int64_t tc_freq_adj; /* [T,W] */ + /* Current frequency adjustment. */ + u_int64_t tc_precision; /* [I] */ + /* Precision of the counter. Computed in tc_init(). */ +}; + +struct timekeep { + /* set at initialization */ + uint32_t tk_version; /* version number */ + + /* timehands members */ + uint64_t tk_scale; + u_int tk_offset_count; + struct bintime tk_offset; + struct bintime tk_naptime; + struct bintime tk_boottime; + volatile u_int tk_generation; + + /* timecounter members */ + int tk_user; + u_int tk_counter_mask; +}; +#define TK_VERSION 0 + +struct rwlock; +extern struct rwlock tc_lock; + +extern struct timecounter *timecounter; + +extern struct uvm_object *timekeep_object; +extern struct timekeep *timekeep; + +u_int64_t tc_getfrequency(void); +u_int64_t tc_getprecision(void); +void tc_init(struct timecounter *tc); +void tc_reset_quality(struct timecounter *, int); +void tc_setclock(const struct timespec *ts); +void tc_setrealtimeclock(const struct timespec *ts); +void tc_ticktock(void); +void inittimecounter(void); +int sysctl_tc(int *, u_int, void *, size_t *, void *, size_t); +void tc_adjfreq(int64_t *, int64_t *); +void tc_adjtime(int64_t *, int64_t *); + +#endif /* !_SYS_TIMETC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/tprintf.h b/lib/libc/include/generic-openbsd/sys/tprintf.h new file mode 100644 index 000000000000..af0d8812fcbd --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/tprintf.h @@ -0,0 +1,41 @@ +/* $OpenBSD: tprintf.h,v 1.6 2003/08/24 01:27:07 avsm Exp $ */ +/* $NetBSD: tprintf.h,v 1.10 1996/04/09 20:55:43 cgd Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tprintf.h 8.1 (Berkeley) 6/2/93 + */ + +typedef struct session *tpr_t; + +tpr_t tprintf_open(struct proc *); +void tprintf_close(tpr_t); + +void tprintf(tpr_t, const char *fmt, ...) + __attribute__((__format__(__kprintf__,2,3))); \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/tracepoint.h b/lib/libc/include/generic-openbsd/sys/tracepoint.h new file mode 100644 index 000000000000..a50023a13fb8 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/tracepoint.h @@ -0,0 +1,38 @@ +/* $OpenBSD: tracepoint.h,v 1.2 2022/06/28 09:32:28 bluhm Exp $ */ + +/* + * Copyright (c) 2019 Martin Pieuchot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_TRACEPOINT_H_ +#define _SYS_TRACEPOINT_H_ + +#ifdef _KERNEL + +#include "dt.h" +#if NDT > 0 +#include + +#define TRACEPOINT(func, name, args...) DT_STATIC_ENTER(func, name, args) +#define TRACEINDEX(func, index, args...) DT_INDEX_ENTER(func, index, args) + +#else /* NDT > 0 */ + +#define TRACEPOINT(func, name, args...) +#define TRACEINDEX(func, index, args...) + +#endif /* NDT > 0 */ +#endif /* _KERNEL */ +#endif /* _SYS_TRACEPOINT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/tree.h b/lib/libc/include/generic-openbsd/sys/tree.h new file mode 100644 index 000000000000..c8e30cf89601 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/tree.h @@ -0,0 +1,1004 @@ +/* $OpenBSD: tree.h,v 1.31 2023/03/08 04:43:09 guenther Exp $ */ +/* + * Copyright 2002 Niels Provos + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_TREE_H_ +#define _SYS_TREE_H_ + +#include + +/* + * This file defines data structures for different types of trees: + * splay trees and red-black trees. + * + * A splay tree is a self-organizing data structure. Every operation + * on the tree causes a splay to happen. The splay moves the requested + * node to the root of the tree and partly rebalances it. + * + * This has the benefit that request locality causes faster lookups as + * the requested nodes move to the top of the tree. On the other hand, + * every lookup causes memory writes. + * + * The Balance Theorem bounds the total access time for m operations + * and n inserts on an initially empty tree as O((m + n)lg n). The + * amortized cost for a sequence of m accesses to a splay tree is O(lg n); + * + * A red-black tree is a binary search tree with the node color as an + * extra attribute. It fulfills a set of conditions: + * - every search path from the root to a leaf consists of the + * same number of black nodes, + * - each red node (except for the root) has a black parent, + * - each leaf node is black. + * + * Every operation on a red-black tree is bounded as O(lg n). + * The maximum height of a red-black tree is 2lg (n+1). + */ + +#define SPLAY_HEAD(name, type) \ +struct name { \ + struct type *sph_root; /* root of the tree */ \ +} + +#define SPLAY_INITIALIZER(root) \ + { NULL } + +#define SPLAY_INIT(root) do { \ + (root)->sph_root = NULL; \ +} while (0) + +#define SPLAY_ENTRY(type) \ +struct { \ + struct type *spe_left; /* left element */ \ + struct type *spe_right; /* right element */ \ +} + +#define SPLAY_LEFT(elm, field) (elm)->field.spe_left +#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right +#define SPLAY_ROOT(head) (head)->sph_root +#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) + +/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ +#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (0) + +#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (0) + +#define SPLAY_LINKLEFT(head, tmp, field) do { \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ +} while (0) + +#define SPLAY_LINKRIGHT(head, tmp, field) do { \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ +} while (0) + +#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \ + SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \ + SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \ +} while (0) + +/* Generates prototypes and inline functions */ + +#define SPLAY_PROTOTYPE(name, type, field, cmp) \ +void name##_SPLAY(struct name *, struct type *); \ +void name##_SPLAY_MINMAX(struct name *, int); \ +struct type *name##_SPLAY_INSERT(struct name *, struct type *); \ +struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \ + \ +/* Finds the node with the same key as elm */ \ +static __unused __inline struct type * \ +name##_SPLAY_FIND(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) \ + return(NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) \ + return (head->sph_root); \ + return (NULL); \ +} \ + \ +static __unused __inline struct type * \ +name##_SPLAY_NEXT(struct name *head, struct type *elm) \ +{ \ + name##_SPLAY(head, elm); \ + if (SPLAY_RIGHT(elm, field) != NULL) { \ + elm = SPLAY_RIGHT(elm, field); \ + while (SPLAY_LEFT(elm, field) != NULL) { \ + elm = SPLAY_LEFT(elm, field); \ + } \ + } else \ + elm = NULL; \ + return (elm); \ +} \ + \ +static __unused __inline struct type * \ +name##_SPLAY_MIN_MAX(struct name *head, int val) \ +{ \ + name##_SPLAY_MINMAX(head, val); \ + return (SPLAY_ROOT(head)); \ +} + +/* Main splay operation. + * Moves node close to the key of elm to top + */ +#define SPLAY_GENERATE(name, type, field, cmp) \ +struct type * \ +name##_SPLAY_INSERT(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) { \ + SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ + } else { \ + int __comp; \ + name##_SPLAY(head, elm); \ + __comp = (cmp)(elm, (head)->sph_root); \ + if(__comp < 0) { \ + SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\ + SPLAY_RIGHT(elm, field) = (head)->sph_root; \ + SPLAY_LEFT((head)->sph_root, field) = NULL; \ + } else if (__comp > 0) { \ + SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT(elm, field) = (head)->sph_root; \ + SPLAY_RIGHT((head)->sph_root, field) = NULL; \ + } else \ + return ((head)->sph_root); \ + } \ + (head)->sph_root = (elm); \ + return (NULL); \ +} \ + \ +struct type * \ +name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *__tmp; \ + if (SPLAY_EMPTY(head)) \ + return (NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) { \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\ + } else { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\ + name##_SPLAY(head, elm); \ + SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ + } \ + return (elm); \ + } \ + return (NULL); \ +} \ + \ +void \ +name##_SPLAY(struct name *head, struct type *elm) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ + int __comp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while ((__comp = (cmp)(elm, (head)->sph_root))) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) > 0){ \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} \ + \ +/* Splay with either the minimum or the maximum element \ + * Used to find minimum or maximum element in tree. \ + */ \ +void name##_SPLAY_MINMAX(struct name *head, int __comp) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while (1) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp > 0) { \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} + +#define SPLAY_NEGINF -1 +#define SPLAY_INF 1 + +#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y) +#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) +#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) +#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) +#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) +#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) + +#define SPLAY_FOREACH(x, name, head) \ + for ((x) = SPLAY_MIN(name, head); \ + (x) != NULL; \ + (x) = SPLAY_NEXT(name, head, x)) + +/* Macros that define a red-black tree */ +#define RB_HEAD(name, type) \ +struct name { \ + struct type *rbh_root; /* root of the tree */ \ +} + +#define RB_INITIALIZER(root) \ + { NULL } + +#define RB_INIT(root) do { \ + (root)->rbh_root = NULL; \ +} while (0) + +#define RB_BLACK 0 +#define RB_RED 1 +#define RB_ENTRY(type) \ +struct { \ + struct type *rbe_left; /* left element */ \ + struct type *rbe_right; /* right element */ \ + struct type *rbe_parent; /* parent element */ \ + int rbe_color; /* node color */ \ +} + +#define RB_LEFT(elm, field) (elm)->field.rbe_left +#define RB_RIGHT(elm, field) (elm)->field.rbe_right +#define RB_PARENT(elm, field) (elm)->field.rbe_parent +#define RB_COLOR(elm, field) (elm)->field.rbe_color +#define RB_ROOT(head) (head)->rbh_root +#define RB_EMPTY(head) (RB_ROOT(head) == NULL) + +#define RB_SET(elm, parent, field) do { \ + RB_PARENT(elm, field) = parent; \ + RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ + RB_COLOR(elm, field) = RB_RED; \ +} while (0) + +#define RB_SET_BLACKRED(black, red, field) do { \ + RB_COLOR(black, field) = RB_BLACK; \ + RB_COLOR(red, field) = RB_RED; \ +} while (0) + +#ifndef RB_AUGMENT +#define RB_AUGMENT(x) do {} while (0) +#endif + +#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ + (tmp) = RB_RIGHT(elm, field); \ + if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \ + RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_LEFT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ + if ((RB_PARENT(tmp, field))) \ + RB_AUGMENT(RB_PARENT(tmp, field)); \ +} while (0) + +#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \ + (tmp) = RB_LEFT(elm, field); \ + if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \ + RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_RIGHT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ + if ((RB_PARENT(tmp, field))) \ + RB_AUGMENT(RB_PARENT(tmp, field)); \ +} while (0) + +/* Generates prototypes and inline functions */ +#define RB_PROTOTYPE(name, type, field, cmp) \ + RB_PROTOTYPE_INTERNAL(name, type, field, cmp,) +#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \ + RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static) +#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \ +attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \ +attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ +attr struct type *name##_RB_REMOVE(struct name *, struct type *); \ +attr struct type *name##_RB_INSERT(struct name *, struct type *); \ +attr struct type *name##_RB_FIND(struct name *, struct type *); \ +attr struct type *name##_RB_NFIND(struct name *, struct type *); \ +attr struct type *name##_RB_NEXT(struct type *); \ +attr struct type *name##_RB_PREV(struct type *); \ +attr struct type *name##_RB_MINMAX(struct name *, int); \ + \ + +/* Main rb operation. + * Moves node close to the key of elm to top + */ +#define RB_GENERATE(name, type, field, cmp) \ + RB_GENERATE_INTERNAL(name, type, field, cmp,) +#define RB_GENERATE_STATIC(name, type, field, cmp) \ + RB_GENERATE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static) +#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \ +attr void \ +name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ +{ \ + struct type *parent, *gparent, *tmp; \ + while ((parent = RB_PARENT(elm, field)) && \ + RB_COLOR(parent, field) == RB_RED) { \ + gparent = RB_PARENT(parent, field); \ + if (parent == RB_LEFT(gparent, field)) { \ + tmp = RB_RIGHT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_RIGHT(parent, field) == elm) { \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_RIGHT(head, gparent, tmp, field); \ + } else { \ + tmp = RB_LEFT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_LEFT(parent, field) == elm) { \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_LEFT(head, gparent, tmp, field); \ + } \ + } \ + RB_COLOR(head->rbh_root, field) = RB_BLACK; \ +} \ + \ +attr void \ +name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \ +{ \ + struct type *tmp; \ + while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ + elm != RB_ROOT(head)) { \ + if (RB_LEFT(parent, field) == elm) { \ + tmp = RB_RIGHT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\ + struct type *oleft; \ + if ((oleft = RB_LEFT(tmp, field)))\ + RB_COLOR(oleft, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_RIGHT(head, tmp, oleft, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_RIGHT(tmp, field)) \ + RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } else { \ + tmp = RB_LEFT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\ + struct type *oright; \ + if ((oright = RB_RIGHT(tmp, field)))\ + RB_COLOR(oright, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_LEFT(head, tmp, oright, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_LEFT(tmp, field)) \ + RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } \ + } \ + if (elm) \ + RB_COLOR(elm, field) = RB_BLACK; \ +} \ + \ +attr struct type * \ +name##_RB_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *child, *parent, *old = elm; \ + int color; \ + if (RB_LEFT(elm, field) == NULL) \ + child = RB_RIGHT(elm, field); \ + else if (RB_RIGHT(elm, field) == NULL) \ + child = RB_LEFT(elm, field); \ + else { \ + struct type *left; \ + elm = RB_RIGHT(elm, field); \ + while ((left = RB_LEFT(elm, field))) \ + elm = left; \ + child = RB_RIGHT(elm, field); \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ + if (RB_PARENT(elm, field) == old) \ + parent = elm; \ + (elm)->field = (old)->field; \ + if (RB_PARENT(old, field)) { \ + if (RB_LEFT(RB_PARENT(old, field), field) == old)\ + RB_LEFT(RB_PARENT(old, field), field) = elm;\ + else \ + RB_RIGHT(RB_PARENT(old, field), field) = elm;\ + RB_AUGMENT(RB_PARENT(old, field)); \ + } else \ + RB_ROOT(head) = elm; \ + RB_PARENT(RB_LEFT(old, field), field) = elm; \ + if (RB_RIGHT(old, field)) \ + RB_PARENT(RB_RIGHT(old, field), field) = elm; \ + if (parent) { \ + left = parent; \ + do { \ + RB_AUGMENT(left); \ + } while ((left = RB_PARENT(left, field))); \ + } \ + goto color; \ + } \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ +color: \ + if (color == RB_BLACK) \ + name##_RB_REMOVE_COLOR(head, parent, child); \ + return (old); \ +} \ + \ +/* Inserts a node into the RB tree */ \ +attr struct type * \ +name##_RB_INSERT(struct name *head, struct type *elm) \ +{ \ + struct type *tmp; \ + struct type *parent = NULL; \ + int comp = 0; \ + tmp = RB_ROOT(head); \ + while (tmp) { \ + parent = tmp; \ + comp = (cmp)(elm, parent); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + RB_SET(elm, parent, field); \ + if (parent != NULL) { \ + if (comp < 0) \ + RB_LEFT(parent, field) = elm; \ + else \ + RB_RIGHT(parent, field) = elm; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = elm; \ + name##_RB_INSERT_COLOR(head, elm); \ + return (NULL); \ +} \ + \ +/* Finds the node with the same key as elm */ \ +attr struct type * \ +name##_RB_FIND(struct name *head, struct type *elm) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + int comp; \ + while (tmp) { \ + comp = cmp(elm, tmp); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + return (NULL); \ +} \ + \ +/* Finds the first node greater than or equal to the search key */ \ +attr struct type * \ +name##_RB_NFIND(struct name *head, struct type *elm) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + struct type *res = NULL; \ + int comp; \ + while (tmp) { \ + comp = cmp(elm, tmp); \ + if (comp < 0) { \ + res = tmp; \ + tmp = RB_LEFT(tmp, field); \ + } \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + return (res); \ +} \ + \ +attr struct type * \ +name##_RB_NEXT(struct type *elm) \ +{ \ + if (RB_RIGHT(elm, field)) { \ + elm = RB_RIGHT(elm, field); \ + while (RB_LEFT(elm, field)) \ + elm = RB_LEFT(elm, field); \ + } else { \ + if (RB_PARENT(elm, field) && \ + (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ + elm = RB_PARENT(elm, field); \ + else { \ + while (RB_PARENT(elm, field) && \ + (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\ + elm = RB_PARENT(elm, field); \ + elm = RB_PARENT(elm, field); \ + } \ + } \ + return (elm); \ +} \ + \ +attr struct type * \ +name##_RB_PREV(struct type *elm) \ +{ \ + if (RB_LEFT(elm, field)) { \ + elm = RB_LEFT(elm, field); \ + while (RB_RIGHT(elm, field)) \ + elm = RB_RIGHT(elm, field); \ + } else { \ + if (RB_PARENT(elm, field) && \ + (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \ + elm = RB_PARENT(elm, field); \ + else { \ + while (RB_PARENT(elm, field) && \ + (elm == RB_LEFT(RB_PARENT(elm, field), field)))\ + elm = RB_PARENT(elm, field); \ + elm = RB_PARENT(elm, field); \ + } \ + } \ + return (elm); \ +} \ + \ +attr struct type * \ +name##_RB_MINMAX(struct name *head, int val) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + struct type *parent = NULL; \ + while (tmp) { \ + parent = tmp; \ + if (val < 0) \ + tmp = RB_LEFT(tmp, field); \ + else \ + tmp = RB_RIGHT(tmp, field); \ + } \ + return (parent); \ +} + +#define RB_NEGINF -1 +#define RB_INF 1 + +#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) +#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) +#define RB_FIND(name, x, y) name##_RB_FIND(x, y) +#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y) +#define RB_NEXT(name, x, y) name##_RB_NEXT(y) +#define RB_PREV(name, x, y) name##_RB_PREV(y) +#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) +#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) + +#define RB_FOREACH(x, name, head) \ + for ((x) = RB_MIN(name, head); \ + (x) != NULL; \ + (x) = name##_RB_NEXT(x)) + +#define RB_FOREACH_SAFE(x, name, head, y) \ + for ((x) = RB_MIN(name, head); \ + ((x) != NULL) && ((y) = name##_RB_NEXT(x), 1); \ + (x) = (y)) + +#define RB_FOREACH_REVERSE(x, name, head) \ + for ((x) = RB_MAX(name, head); \ + (x) != NULL; \ + (x) = name##_RB_PREV(x)) + +#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \ + for ((x) = RB_MAX(name, head); \ + ((x) != NULL) && ((y) = name##_RB_PREV(x), 1); \ + (x) = (y)) + + +/* + * Copyright (c) 2016 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +struct rb_type { + int (*t_compare)(const void *, const void *); + void (*t_augment)(void *); + unsigned int t_offset; /* offset of rb_entry in type */ +}; + +struct rb_tree { + struct rb_entry *rbt_root; +}; + +struct rb_entry { + struct rb_entry *rbt_parent; + struct rb_entry *rbt_left; + struct rb_entry *rbt_right; + unsigned int rbt_color; +}; + +#define RBT_HEAD(_name, _type) \ +struct _name { \ + struct rb_tree rbh_root; \ +} + +#define RBT_ENTRY(_type) struct rb_entry + +static inline void +_rb_init(struct rb_tree *rbt) +{ + rbt->rbt_root = NULL; +} + +static inline int +_rb_empty(struct rb_tree *rbt) +{ + return (rbt->rbt_root == NULL); +} + +void *_rb_insert(const struct rb_type *, struct rb_tree *, void *); +void *_rb_remove(const struct rb_type *, struct rb_tree *, void *); +void *_rb_find(const struct rb_type *, struct rb_tree *, const void *); +void *_rb_nfind(const struct rb_type *, struct rb_tree *, const void *); +void *_rb_root(const struct rb_type *, struct rb_tree *); +void *_rb_min(const struct rb_type *, struct rb_tree *); +void *_rb_max(const struct rb_type *, struct rb_tree *); +void *_rb_next(const struct rb_type *, void *); +void *_rb_prev(const struct rb_type *, void *); +void *_rb_left(const struct rb_type *, void *); +void *_rb_right(const struct rb_type *, void *); +void *_rb_parent(const struct rb_type *, void *); +void _rb_set_left(const struct rb_type *, void *, void *); +void _rb_set_right(const struct rb_type *, void *, void *); +void _rb_set_parent(const struct rb_type *, void *, void *); +void _rb_poison(const struct rb_type *, void *, unsigned long); +int _rb_check(const struct rb_type *, void *, unsigned long); + +#define RBT_INITIALIZER(_head) { { NULL } } + +#define RBT_PROTOTYPE(_name, _type, _field, _cmp) \ +extern const struct rb_type *const _name##_RBT_TYPE; \ + \ +__unused static inline void \ +_name##_RBT_INIT(struct _name *head) \ +{ \ + _rb_init(&head->rbh_root); \ +} \ + \ +__unused static inline struct _type * \ +_name##_RBT_INSERT(struct _name *head, struct _type *elm) \ +{ \ + return _rb_insert(_name##_RBT_TYPE, &head->rbh_root, elm); \ +} \ + \ +__unused static inline struct _type * \ +_name##_RBT_REMOVE(struct _name *head, struct _type *elm) \ +{ \ + return _rb_remove(_name##_RBT_TYPE, &head->rbh_root, elm); \ +} \ + \ +__unused static inline struct _type * \ +_name##_RBT_FIND(struct _name *head, const struct _type *key) \ +{ \ + return _rb_find(_name##_RBT_TYPE, &head->rbh_root, key); \ +} \ + \ +__unused static inline struct _type * \ +_name##_RBT_NFIND(struct _name *head, const struct _type *key) \ +{ \ + return _rb_nfind(_name##_RBT_TYPE, &head->rbh_root, key); \ +} \ + \ +__unused static inline struct _type * \ +_name##_RBT_ROOT(struct _name *head) \ +{ \ + return _rb_root(_name##_RBT_TYPE, &head->rbh_root); \ +} \ + \ +__unused static inline int \ +_name##_RBT_EMPTY(struct _name *head) \ +{ \ + return _rb_empty(&head->rbh_root); \ +} \ + \ +__unused static inline struct _type * \ +_name##_RBT_MIN(struct _name *head) \ +{ \ + return _rb_min(_name##_RBT_TYPE, &head->rbh_root); \ +} \ + \ +__unused static inline struct _type * \ +_name##_RBT_MAX(struct _name *head) \ +{ \ + return _rb_max(_name##_RBT_TYPE, &head->rbh_root); \ +} \ + \ +__unused static inline struct _type * \ +_name##_RBT_NEXT(struct _type *elm) \ +{ \ + return _rb_next(_name##_RBT_TYPE, elm); \ +} \ + \ +__unused static inline struct _type * \ +_name##_RBT_PREV(struct _type *elm) \ +{ \ + return _rb_prev(_name##_RBT_TYPE, elm); \ +} \ + \ +__unused static inline struct _type * \ +_name##_RBT_LEFT(struct _type *elm) \ +{ \ + return _rb_left(_name##_RBT_TYPE, elm); \ +} \ + \ +__unused static inline struct _type * \ +_name##_RBT_RIGHT(struct _type *elm) \ +{ \ + return _rb_right(_name##_RBT_TYPE, elm); \ +} \ + \ +__unused static inline struct _type * \ +_name##_RBT_PARENT(struct _type *elm) \ +{ \ + return _rb_parent(_name##_RBT_TYPE, elm); \ +} \ + \ +__unused static inline void \ +_name##_RBT_SET_LEFT(struct _type *elm, struct _type *left) \ +{ \ + _rb_set_left(_name##_RBT_TYPE, elm, left); \ +} \ + \ +__unused static inline void \ +_name##_RBT_SET_RIGHT(struct _type *elm, struct _type *right) \ +{ \ + _rb_set_right(_name##_RBT_TYPE, elm, right); \ +} \ + \ +__unused static inline void \ +_name##_RBT_SET_PARENT(struct _type *elm, struct _type *parent) \ +{ \ + _rb_set_parent(_name##_RBT_TYPE, elm, parent); \ +} \ + \ +__unused static inline void \ +_name##_RBT_POISON(struct _type *elm, unsigned long poison) \ +{ \ + _rb_poison(_name##_RBT_TYPE, elm, poison); \ +} \ + \ +__unused static inline int \ +_name##_RBT_CHECK(struct _type *elm, unsigned long poison) \ +{ \ + return _rb_check(_name##_RBT_TYPE, elm, poison); \ +} + +#define RBT_GENERATE_INTERNAL(_name, _type, _field, _cmp, _aug) \ +static int \ +_name##_RBT_COMPARE(const void *lptr, const void *rptr) \ +{ \ + const struct _type *l = lptr, *r = rptr; \ + return _cmp(l, r); \ +} \ +static const struct rb_type _name##_RBT_INFO = { \ + _name##_RBT_COMPARE, \ + _aug, \ + offsetof(struct _type, _field), \ +}; \ +const struct rb_type *const _name##_RBT_TYPE = &_name##_RBT_INFO + +#define RBT_GENERATE_AUGMENT(_name, _type, _field, _cmp, _aug) \ +static void \ +_name##_RBT_AUGMENT(void *ptr) \ +{ \ + struct _type *p = ptr; \ + return _aug(p); \ +} \ +RBT_GENERATE_INTERNAL(_name, _type, _field, _cmp, _name##_RBT_AUGMENT) + +#define RBT_GENERATE(_name, _type, _field, _cmp) \ + RBT_GENERATE_INTERNAL(_name, _type, _field, _cmp, NULL) + +#define RBT_INIT(_name, _head) _name##_RBT_INIT(_head) +#define RBT_INSERT(_name, _head, _elm) _name##_RBT_INSERT(_head, _elm) +#define RBT_REMOVE(_name, _head, _elm) _name##_RBT_REMOVE(_head, _elm) +#define RBT_FIND(_name, _head, _key) _name##_RBT_FIND(_head, _key) +#define RBT_NFIND(_name, _head, _key) _name##_RBT_NFIND(_head, _key) +#define RBT_ROOT(_name, _head) _name##_RBT_ROOT(_head) +#define RBT_EMPTY(_name, _head) _name##_RBT_EMPTY(_head) +#define RBT_MIN(_name, _head) _name##_RBT_MIN(_head) +#define RBT_MAX(_name, _head) _name##_RBT_MAX(_head) +#define RBT_NEXT(_name, _elm) _name##_RBT_NEXT(_elm) +#define RBT_PREV(_name, _elm) _name##_RBT_PREV(_elm) +#define RBT_LEFT(_name, _elm) _name##_RBT_LEFT(_elm) +#define RBT_RIGHT(_name, _elm) _name##_RBT_RIGHT(_elm) +#define RBT_PARENT(_name, _elm) _name##_RBT_PARENT(_elm) +#define RBT_SET_LEFT(_name, _elm, _l) _name##_RBT_SET_LEFT(_elm, _l) +#define RBT_SET_RIGHT(_name, _elm, _r) _name##_RBT_SET_RIGHT(_elm, _r) +#define RBT_SET_PARENT(_name, _elm, _p) _name##_RBT_SET_PARENT(_elm, _p) +#define RBT_POISON(_name, _elm, _p) _name##_RBT_POISON(_elm, _p) +#define RBT_CHECK(_name, _elm, _p) _name##_RBT_CHECK(_elm, _p) + +#define RBT_FOREACH(_e, _name, _head) \ + for ((_e) = RBT_MIN(_name, (_head)); \ + (_e) != NULL; \ + (_e) = RBT_NEXT(_name, (_e))) + +#define RBT_FOREACH_SAFE(_e, _name, _head, _n) \ + for ((_e) = RBT_MIN(_name, (_head)); \ + (_e) != NULL && ((_n) = RBT_NEXT(_name, (_e)), 1); \ + (_e) = (_n)) + +#define RBT_FOREACH_REVERSE(_e, _name, _head) \ + for ((_e) = RBT_MAX(_name, (_head)); \ + (_e) != NULL; \ + (_e) = RBT_PREV(_name, (_e))) + +#define RBT_FOREACH_REVERSE_SAFE(_e, _name, _head, _n) \ + for ((_e) = RBT_MAX(_name, (_head)); \ + (_e) != NULL && ((_n) = RBT_PREV(_name, (_e)), 1); \ + (_e) = (_n)) + +#endif /* _SYS_TREE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/tty.h b/lib/libc/include/generic-openbsd/sys/tty.h new file mode 100644 index 000000000000..cb60f9347624 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/tty.h @@ -0,0 +1,332 @@ +/* $OpenBSD: tty.h,v 1.45 2025/09/25 08:46:50 mvs Exp $ */ +/* $NetBSD: tty.h,v 1.30.4.1 1996/06/02 09:08:13 mrg Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tty.h 8.6 (Berkeley) 1/21/94 + */ + +#include +#include +#include /* For struct selinfo. */ +#include + +#define KERN_TTY_TKNIN 1 /* quad: input chars */ +#define KERN_TTY_TKNOUT 2 /* quad: output chars */ +#define KERN_TTY_TKRAWCC 3 /* quad: input chars, raw mode */ +#define KERN_TTY_TKCANCC 4 /* quad: input char, cooked mode */ +#define KERN_TTY_INFO 5 /* struct: tty stats */ +/* was KERN_TTY_MAXPTYS 6 */ +/* was KERN_TTY_NPTYS 7 */ +#define KERN_TTY_MAXID 8 + +#define CTL_KERN_TTY_NAMES { \ + { 0, 0 }, \ + { "tk_nin", CTLTYPE_QUAD }, \ + { "tk_nout", CTLTYPE_QUAD }, \ + { "tk_rawcc", CTLTYPE_QUAD }, \ + { "tk_cancc", CTLTYPE_QUAD }, \ + { "ttyinfo", CTLTYPE_STRUCT }, \ + { "gap", 0 }, \ + { "gap", 0 }, \ +} + +/* ptmget, for /dev/ptm pty getting ioctl PTMGET */ + +struct ptmget { + int cfd; + int sfd; + char cn[16]; + char sn[16]; +}; +#define PTMGET _IOR('t', 1, struct ptmget) /* get ptys */ +#define PATH_PTMDEV "/dev/ptm" +#define TTY_GID 4 /* XXX evil hardcoding of tty gid */ + +/* + * Clists are actually ring buffers. The c_cc, c_cf, c_cl fields have + * exactly the same behaviour as in true clists. + * if c_cq is NULL, the ring buffer has no TTY_QUOTE functionality + * (but, saves memory and cpu time) + * + * *DON'T* play with c_cs, c_ce, c_cq, or c_cl outside tty_subr.c!!! + */ +struct clist { + int c_cc; /* count of characters in queue */ + int c_cn; /* total ring buffer length */ + u_char *c_cf; /* points to first character */ + u_char *c_cl; /* points to next open character */ + u_char *c_cs; /* start of ring buffer */ + u_char *c_ce; /* c_ce + c_len */ + u_char *c_cq; /* N bits/bytes long, see tty_subr.c */ +}; + +/* + * Per-tty structure. + * + * Should be split in two, into device and tty drivers. + * Glue could be masks of what to echo and circular buffer + * (low, high, timeout). + */ +struct tty { + TAILQ_ENTRY(tty) tty_link; /* Link in global tty list. */ + struct clist t_rawq; /* Device raw input queue. */ + long t_rawcc; /* Raw input queue statistics. */ + struct clist t_canq; /* Device canonical queue. */ + long t_cancc; /* Canonical queue statistics. */ + struct clist t_outq; /* Device output queue. */ + long t_outcc; /* Output queue statistics. */ + int t_qlen; /* Length of above queues */ + u_char t_line; /* Interface to device drivers. */ + dev_t t_dev; /* Device. */ + int t_state; /* Device and driver (TS*) state. */ + int t_flags; /* Tty flags. */ + struct pgrp *t_pgrp; /* Foreground process group. */ + struct session *t_session; /* Enclosing session. */ + struct selinfo t_rsel; /* Tty read/oob select. */ + struct selinfo t_wsel; /* Tty write select. */ + struct termios t_termios; /* Termios state. */ + struct winsize t_winsize; /* Window size. */ + /* Start output. */ + void (*t_oproc)(struct tty *); + /* Set hardware state. */ + int (*t_param)(struct tty *, struct termios *); + /* Set hardware flow control. */ + int (*t_hwiflow)(struct tty *tp, int flag); + void *t_sc; /* XXX: net/if_sl.c:sl_softc. */ + short t_column; /* Tty output column. */ + short t_rocount, t_rocol; /* Tty. */ + short t_hiwat; /* High water mark. */ + short t_lowat; /* Low water mark. */ + short t_gen; /* Generation number. */ + struct timeout t_rstrt_to; /* restart timeout */ + struct timeval t_tv; /* timestamp */ +}; + +/* + * Small version of struct tty exported via sysctl KERN_TTY_INFO + */ +struct itty { + dev_t t_dev; + int t_rawq_c_cc; + int t_canq_c_cc; + int t_outq_c_cc; + short t_hiwat; + short t_lowat; + short t_column; + int t_state; + struct session *t_session; + pid_t t_pgrp_pg_id; + u_char t_line; +}; + +#define t_cc t_termios.c_cc +#define t_cflag t_termios.c_cflag +#define t_iflag t_termios.c_iflag +#define t_ispeed t_termios.c_ispeed +#define t_lflag t_termios.c_lflag +#define t_min t_termios.c_min +#define t_oflag t_termios.c_oflag +#define t_ospeed t_termios.c_ospeed +#define t_time t_termios.c_time + +#define TTIPRI 25 /* Sleep priority for tty reads. */ +#define TTOPRI 26 /* Sleep priority for tty writes. */ + +#define OBUFSIZ 512 +#define TTYHOG(tp) (tp)->t_qlen + +#ifdef _KERNEL +#define TTMAXLOWAT 256 +#define TTMINLOWAT 32 +#define TTMINHIWAT 100 +#define TTHIWATMINSPACE 200 /* Min space above hiwat */ +#endif + +/* These flags are kept in t_state. */ +#define TS_ASLEEP 0x00001 /* Process waiting for tty. */ +#define TS_ASYNC 0x00002 /* Tty in async I/O mode. */ +#define TS_BUSY 0x00004 /* Draining output. */ +#define TS_CARR_ON 0x00008 /* Carrier is present. */ +#define TS_FLUSH 0x00010 /* Outq has been flushed during DMA. */ +#define TS_ISOPEN 0x00020 /* Open has completed. */ +#define TS_TBLOCK 0x00040 /* Further input blocked. */ +#define TS_TIMEOUT 0x00080 /* Wait for output char processing. */ +#define TS_TTSTOP 0x00100 /* Output paused. */ +#define TS_WOPEN 0x00200 /* Open in progress. */ +#define TS_XCLUDE 0x00400 /* Tty requires exclusivity. */ + +/* State for intra-line fancy editing work. */ +#define TS_BKSL 0x00800 /* State for lowercase \ work. */ +#define TS_CNTTB 0x01000 /* Counting tab width, ignore FLUSHO. */ +#define TS_ERASE 0x02000 /* Within a \.../ for PRTRUB. */ +#define TS_LNCH 0x04000 /* Next character is literal. */ +#define TS_TYPEN 0x08000 /* Retyping suspended input (PENDIN). */ +#define TS_LOCAL (TS_BKSL | TS_CNTTB | TS_ERASE | TS_LNCH | TS_TYPEN) + +#define TS_TSTAMPDCDSET 0x10000 /* update timestamp on DCD set */ +#define TS_TSTAMPDCDCLR 0x20000 /* update timestamp on DCD clr */ +#define TS_TSTAMPCTSSET 0x40000 /* update timestamp on CTS set */ +#define TS_TSTAMPCTSCLR 0x80000 /* update timestamp on CTS clr */ + +/* Character type information. */ +#define ORDINARY 0 +#define CONTROL 1 +#define BACKSPACE 2 +#define NEWLINE 3 +#define TAB 4 +#define VTAB 5 +#define RETURN 6 + +struct speedtab { + int sp_speed; /* Speed. */ + int sp_code; /* Code. */ +}; + +/* Modem control commands (driver). */ +#define DMSET 0 +#define DMBIS 1 +#define DMBIC 2 +#define DMGET 3 + +/* Flags on a character passed to ttyinput. */ +#define TTY_CHARMASK 0x000000ff /* Character mask */ +#define TTY_QUOTE 0x00000100 /* Character quoted */ +#define TTY_ERRORMASK 0xff000000 /* Error mask */ +#define TTY_FE 0x01000000 /* Framing error or BREAK condition */ +#define TTY_PE 0x02000000 /* Parity error */ + +/* Is tp controlling terminal for pr? */ +#define isctty(pr, tp) \ + ((pr)->ps_session == (tp)->t_session && (pr)->ps_flags & PS_CONTROLT) + +/* Is pr in background of tp? */ +#define isbackground(pr, tp) \ + (isctty((pr), (tp)) && (pr)->ps_pgrp != (tp)->t_pgrp) + +/* + * ttylist_head is defined here so that user-land has access to it. + */ +TAILQ_HEAD(ttylist_head, tty); /* the ttylist is a TAILQ */ + +#ifdef _KERNEL + +extern int tty_count; /* number of ttys in global ttylist */ + +/* Symbolic sleep message strings. */ +extern char ttyin[], ttyout[], ttopen[], ttclos[], ttybg[]; + +extern int64_t tk_cancc, tk_nin, tk_nout, tk_rawcc; + +int sysctl_tty(int *, u_int, void *, size_t *, void *, size_t); +int sysctl_pty(int *, u_int, void *, size_t *, void *, size_t); + +int b_to_q(u_char *cp, int cc, struct clist *q); +void catq(struct clist *from, struct clist *to); +int getc(struct clist *q); +void ndflush(struct clist *q, int cc); +int ndqb(struct clist *q, int flag); +u_char *firstc(struct clist *clp, int *c, int *cc); +u_char *nextc(struct clist *q, u_char *cp, int *c, int *cc); +int putc(int c, struct clist *q); +int q_to_b(struct clist *q, u_char *cp, int cc); +int unputc(struct clist *q); + +int nullmodem(struct tty *tp, int flag); +int tputchar(int c, struct tty *tp); +int ttioctl(struct tty *tp, u_long com, caddr_t data, int flag, + struct proc *p); +int ttread(struct tty *tp, struct uio *uio, int flag); +void ttrstrt(void *tp); +int ttkqfilter(dev_t dev, struct knote *kn); +void ttsetwater(struct tty *tp); +int ttspeedtab(int speed, const struct speedtab *table); +int ttstart(struct tty *tp); +void ttwakeupwr(struct tty *tp); +void ttwakeup(struct tty *tp); +int ttwrite(struct tty *tp, struct uio *uio, int flag); +void ttychars(struct tty *tp); +int ttycheckoutq(struct tty *tp, int wait); +int ttyclose(struct tty *tp); +void ttyflush(struct tty *tp, int rw); +void ttyinfo(struct tty *tp); +int ttyinput(int c, struct tty *tp); +int ttylclose(struct tty *tp, int flag, struct proc *p); +int ttymodem(struct tty *tp, int flag); +int ttyopen(dev_t device, struct tty *tp, struct proc *p); +int ttyoutput(int c, struct tty *tp); +void ttypend(struct tty *tp); +int ttyretype(struct tty *tp); +int ttyrub(int c, struct tty *tp); +int ttysleep(struct tty *tp, void *chan, int pri, char *wmesg); +int ttysleep_nsec(struct tty *, void *, int, char *, uint64_t); +int ttywait(struct tty *tp); +int ttywflush(struct tty *tp); +void ttytstamp(struct tty *tp, int octs, int ncts, int odcd, int ndcd); + +void tty_init(void); +struct tty *ttymalloc(int); +void ttyfree(struct tty *); + +int cttyopen(dev_t, int, int, struct proc *); +int cttyread(dev_t, struct uio *, int); +int cttywrite(dev_t, struct uio *, int); +int cttyioctl(dev_t, u_long, caddr_t, int, struct proc *); + +void clalloc(struct clist *, int, int); +void clfree(struct clist *); + +int nullioctl(struct tty *, u_long, caddr_t, int, struct proc *); + +int pppopen(dev_t dev, struct tty *, struct proc *); +int pppclose(struct tty *, int, struct proc *); +int ppptioctl(struct tty *, u_long, caddr_t, int, struct proc *); +int pppinput(int c, struct tty *); +int pppstart(struct tty *); +int pppread(struct tty *, struct uio *, int); +int pppwrite(struct tty *, struct uio *, int); + +int nmeaopen(dev_t, struct tty *, struct proc *); +int nmeaclose(struct tty *, int, struct proc *); +int nmeainput(int, struct tty *); + +int mstsopen(dev_t, struct tty *, struct proc *); +int mstsclose(struct tty *, int, struct proc *); +int mstsinput(int, struct tty *); + +int endrunopen(dev_t, struct tty *, struct proc *); +int endrunclose(struct tty *, int, struct proc *); +int endruninput(int, struct tty *); + +#endif /* _KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/ttycom.h b/lib/libc/include/generic-openbsd/sys/ttycom.h new file mode 100644 index 000000000000..757d49a85b64 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/ttycom.h @@ -0,0 +1,151 @@ +/* $OpenBSD: ttycom.h,v 1.17 2018/06/16 13:55:03 deraadt Exp $ */ +/* $NetBSD: ttycom.h,v 1.4 1996/05/19 17:17:53 jonathan Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ttycom.h 8.1 (Berkeley) 3/28/94 + */ + +#ifndef _SYS_TTYCOM_H_ +#define _SYS_TTYCOM_H_ + +#include + +/* Tty ioctl's. */ + +/* + * Window/terminal size structure. This information is stored by the kernel + * in order to provide a consistent interface, but is not used by the kernel. + */ +struct winsize { + unsigned short ws_row; /* rows, in characters */ + unsigned short ws_col; /* columns, in characters */ + unsigned short ws_xpixel; /* horizontal size, pixels */ + unsigned short ws_ypixel; /* vertical size, pixels */ +}; + +struct tstamps { + int ts_set; /* TIOCM_CAR and/or TIOCM_CTS */ + int ts_clr; +}; + +#define TIOCM_LE 0001 /* line enable */ +#define TIOCM_DTR 0002 /* data terminal ready */ +#define TIOCM_RTS 0004 /* request to send */ +#define TIOCM_ST 0010 /* secondary transmit */ +#define TIOCM_SR 0020 /* secondary receive */ +#define TIOCM_CTS 0040 /* clear to send */ +#define TIOCM_CAR 0100 /* carrier detect */ +#define TIOCM_CD TIOCM_CAR +#define TIOCM_RNG 0200 /* ring */ +#define TIOCM_RI TIOCM_RNG +#define TIOCM_DSR 0400 /* data set ready */ + /* 8-10 compat */ +#define TIOCEXCL _IO('t', 13) /* set exclusive use of tty */ +#define TIOCNXCL _IO('t', 14) /* reset exclusive use of tty */ + /* 15 unused */ +#define TIOCFLUSH _IOW('t', 16, int) /* flush buffers */ + /* 17-18 compat */ +#define TIOCGETA _IOR('t', 19, struct termios) /* get termios struct */ +#define TIOCSETA _IOW('t', 20, struct termios) /* set termios struct */ +#define TIOCSETAW _IOW('t', 21, struct termios) /* drain output, set */ +#define TIOCSETAF _IOW('t', 22, struct termios) /* drn out, fls in, set */ +#define TIOCGETD _IOR('t', 26, int) /* get line discipline */ +#define TIOCSETD _IOW('t', 27, int) /* set line discipline */ +#define TIOCSETVERAUTH _IOW('t', 28, int) /* set verified auth */ +#define TIOCCLRVERAUTH _IO('t', 29) /* clear verified auth */ +#define TIOCCHKVERAUTH _IO('t', 30) /* check verified auth */ + /* 127-124 compat */ +#define TIOCSBRK _IO('t', 123) /* set break bit */ +#define TIOCCBRK _IO('t', 122) /* clear break bit */ +#define TIOCSDTR _IO('t', 121) /* set data terminal ready */ +#define TIOCCDTR _IO('t', 120) /* clear data terminal ready */ +#define TIOCGPGRP _IOR('t', 119, int) /* get pgrp of tty */ +#define TIOCSPGRP _IOW('t', 118, int) /* set pgrp of tty */ + /* 117-116 compat */ +#define TIOCOUTQ _IOR('t', 115, int) /* output queue size */ +#define TIOCNOTTY _IO('t', 113) /* void tty association */ +#define TIOCPKT _IOW('t', 112, int) /* pty: set/clear packet mode */ +#define TIOCPKT_DATA 0x00 /* data packet */ +#define TIOCPKT_FLUSHREAD 0x01 /* flush packet */ +#define TIOCPKT_FLUSHWRITE 0x02 /* flush packet */ +#define TIOCPKT_STOP 0x04 /* stop output */ +#define TIOCPKT_START 0x08 /* start output */ +#define TIOCPKT_NOSTOP 0x10 /* no more ^S, ^Q */ +#define TIOCPKT_DOSTOP 0x20 /* now do ^S ^Q */ +#define TIOCPKT_IOCTL 0x40 /* state change of pty driver */ +#define TIOCSTOP _IO('t', 111) /* stop output, like ^S */ +#define TIOCSTART _IO('t', 110) /* start output, like ^Q */ +#define TIOCMSET _IOW('t', 109, int) /* set all modem bits */ +#define TIOCMBIS _IOW('t', 108, int) /* bis modem bits */ +#define TIOCMBIC _IOW('t', 107, int) /* bic modem bits */ +#define TIOCMGET _IOR('t', 106, int) /* get all modem bits */ +#define TIOCREMOTE _IOW('t', 105, int) /* remote input editing */ +#define TIOCGWINSZ _IOR('t', 104, struct winsize) /* get window size */ +#define TIOCSWINSZ _IOW('t', 103, struct winsize) /* set window size */ +#define TIOCUCNTL _IOW('t', 102, int) /* pty: set/clr usr cntl mode */ +#define UIOCCMD(n) _IO('u', n) /* usr cntl op "n" */ +#define TIOCUCNTL_SBRK (TIOCSBRK & 0xff)/* set break bit, usr ctnl */ +#define TIOCUCNTL_CBRK (TIOCCBRK & 0xff)/* clear break bit, usr ctnl */ +#define TIOCSTAT _IO('t', 101) /* generate status message */ +#define TIOCGSID _IOR('t', 99, int) /* get sid of tty */ +#define TIOCCONS _IOW('t', 98, int) /* become virtual console */ +#define TIOCSCTTY _IO('t', 97) /* become controlling tty */ +#define TIOCEXT _IOW('t', 96, int) /* pty: external processing */ +#define TIOCSIG _IOW('t', 95, int) /* pty: generate signal */ +#define TIOCDRAIN _IO('t', 94) /* wait till output drained */ +#define TIOCGFLAGS _IOR('t', 93, int) /* get device flags */ +#define TIOCSFLAGS _IOW('t', 92, int) /* set device flags */ +#define TIOCFLAG_SOFTCAR 0x01 /* ignore hardware carrier */ +#define TIOCFLAG_CLOCAL 0x02 /* set clocal on open */ +#define TIOCFLAG_CRTSCTS 0x04 /* set crtscts on open */ +#define TIOCFLAG_MDMBUF 0x08 /* set mdmbuf on open */ +#define TIOCFLAG_PPS 0x10 /* call hardpps on carrier up */ +#define TIOCGTSTAMP _IOR('t', 91, struct timeval) /* get timestamp */ +#define TIOCSTSTAMP _IOW('t', 90, struct tstamps) /* timestamp reasons */ + +/* Backwards compatibility */ +#define TIOCMODG TIOCMGET +#define TIOCMODS TIOCMSET + +#define TTYDISC 0 /* termios tty line discipline */ +#define TABLDISC 3 /* tablet discipline */ +#define SLIPDISC 4 /* serial IP discipline */ +#define PPPDISC 5 /* ppp discipline */ +#define STRIPDISC 6 /* metricom wireless IP discipline */ +#define NMEADISC 7 /* NMEA0183 discipline */ +#define MSTSDISC 8 /* Meinberg time string discipline */ +#define ENDRUNDISC 9 /* EndRun time format discipline */ + +#endif /* !_SYS_TTYCOM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/ttydefaults.h b/lib/libc/include/generic-openbsd/sys/ttydefaults.h new file mode 100644 index 000000000000..87886c5859ab --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/ttydefaults.h @@ -0,0 +1,95 @@ +/* $OpenBSD: ttydefaults.h,v 1.7 2019/03/12 11:01:25 nicm Exp $ */ +/* $NetBSD: ttydefaults.h,v 1.8 1996/04/09 20:55:45 cgd Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ttydefaults.h 8.4 (Berkeley) 1/21/94 + */ + +/* + * System wide defaults for terminal state. + */ +#ifndef _SYS_TTYDEFAULTS_H_ +#define _SYS_TTYDEFAULTS_H_ + +/* + * Defaults on "first" open. + */ +#define TTYDEF_IFLAG (BRKINT | ICRNL | IMAXBEL | IXON | IXANY) +#define TTYDEF_OFLAG (OPOST | ONLCR) +#define TTYDEF_LFLAG (ECHO | ICANON | ISIG | IEXTEN | ECHOE|ECHOKE|ECHOCTL) +#define TTYDEF_CFLAG (CREAD | CS8 | HUPCL) +#define TTYDEF_SPEED (B9600) + +/* + * Control Character Defaults + */ +#define CTRL(x) (x&037) +#define CEOF CTRL('d') +#define CEOL ((unsigned char)'\377') /* XXX avoid _POSIX_VDISABLE */ +#define CERASE 0177 +#define CINTR CTRL('c') +#define CSTATUS ((unsigned char)'\377') /* XXX avoid _POSIX_VDISABLE */ +#define CKILL CTRL('u') +#define CMIN 1 +#define CQUIT 034 /* FS, ^\ */ +#define CSUSP CTRL('z') +#define CTIME 0 +#define CDSUSP CTRL('y') +#define CSTART CTRL('q') +#define CSTOP CTRL('s') +#define CLNEXT CTRL('v') +#define CDISCARD CTRL('o') +#define CWERASE CTRL('w') +#define CREPRINT CTRL('r') +#define CEOT CEOF +/* compat */ +#define CBRK CEOL +#define CRPRNT CREPRINT +#define CFLUSH CDISCARD + +/* PROTECTED INCLUSION ENDS HERE */ +#endif /* !_SYS_TTYDEFAULTS_H_ */ + +/* + * #define TTYDEFCHARS to include an array of default control characters. + */ +#ifdef TTYDEFCHARS +cc_t ttydefchars[NCCS] = { + CEOF, CEOL, CEOL, CERASE, CWERASE, CKILL, CREPRINT, + _POSIX_VDISABLE, CINTR, CQUIT, CSUSP, CDSUSP, CSTART, CSTOP, CLNEXT, + CDISCARD, CMIN, CTIME, CSTATUS, _POSIX_VDISABLE +}; +#undef TTYDEFCHARS +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/types.h b/lib/libc/include/generic-openbsd/sys/types.h new file mode 100644 index 000000000000..9ea9bab09010 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/types.h @@ -0,0 +1,260 @@ +/* $OpenBSD: types.h,v 1.49 2022/08/06 13:31:13 semarie Exp $ */ +/* $NetBSD: types.h,v 1.29 1996/11/15 22:48:25 jtc Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.4 (Berkeley) 1/21/94 + */ + +#ifndef _SYS_TYPES_H_ +#define _SYS_TYPES_H_ + +#include +#if __BSD_VISIBLE +#include +#else +#include +#endif + +#if __BSD_VISIBLE +typedef unsigned char u_char; +typedef unsigned short u_short; +typedef unsigned int u_int; +typedef unsigned long u_long; + +typedef unsigned char unchar; /* Sys V compatibility */ +typedef unsigned short ushort; /* Sys V compatibility */ +typedef unsigned int uint; /* Sys V compatibility */ +typedef unsigned long ulong; /* Sys V compatibility */ + +typedef __cpuid_t cpuid_t; /* CPU id */ +typedef __register_t register_t; /* register-sized type */ +#endif /* __BSD_VISIBLE */ + +/* + * XXX The exact-width bit types should only be exposed if __BSD_VISIBLE + * but the rest of the includes are not ready for that yet. + */ +#ifndef __BIT_TYPES_DEFINED__ +#define __BIT_TYPES_DEFINED__ +#endif + +#ifndef _INT8_T_DEFINED_ +#define _INT8_T_DEFINED_ +typedef __int8_t int8_t; +#endif + +#ifndef _UINT8_T_DEFINED_ +#define _UINT8_T_DEFINED_ +typedef __uint8_t uint8_t; +#endif + +#ifndef _INT16_T_DEFINED_ +#define _INT16_T_DEFINED_ +typedef __int16_t int16_t; +#endif + +#ifndef _UINT16_T_DEFINED_ +#define _UINT16_T_DEFINED_ +typedef __uint16_t uint16_t; +#endif + +#ifndef _INT32_T_DEFINED_ +#define _INT32_T_DEFINED_ +typedef __int32_t int32_t; +#endif + +#ifndef _UINT32_T_DEFINED_ +#define _UINT32_T_DEFINED_ +typedef __uint32_t uint32_t; +#endif + +#ifndef _INT64_T_DEFINED_ +#define _INT64_T_DEFINED_ +typedef __int64_t int64_t; +#endif + +#ifndef _UINT64_T_DEFINED_ +#define _UINT64_T_DEFINED_ +typedef __uint64_t uint64_t; +#endif + +/* BSD-style unsigned bits types */ +typedef __uint8_t u_int8_t; +typedef __uint16_t u_int16_t; +typedef __uint32_t u_int32_t; +typedef __uint64_t u_int64_t; + +/* quads, deprecated in favor of 64 bit int types */ +typedef __int64_t quad_t; +typedef __uint64_t u_quad_t; + +#if __BSD_VISIBLE +/* VM system types */ +typedef __vaddr_t vaddr_t; +typedef __paddr_t paddr_t; +typedef __vsize_t vsize_t; +typedef __psize_t psize_t; +#endif /* __BSD_VISIBLE */ + +/* Standard system types */ +typedef __blkcnt_t blkcnt_t; /* blocks allocated for file */ +typedef __blksize_t blksize_t; /* optimal blocksize for I/O */ +typedef char * caddr_t; /* core address */ +typedef __int32_t daddr32_t; /* 32-bit disk address */ +typedef __int64_t daddr_t; /* 64-bit disk address */ +typedef __dev_t dev_t; /* device number */ +typedef __fixpt_t fixpt_t; /* fixed point number */ +typedef __gid_t gid_t; /* group id */ +typedef __id_t id_t; /* may contain pid, uid or gid */ +typedef __ino_t ino_t; /* inode number */ +typedef __key_t key_t; /* IPC key (for Sys V IPC) */ +typedef __mode_t mode_t; /* permissions */ +typedef __nlink_t nlink_t; /* link count */ +typedef __rlim_t rlim_t; /* resource limit */ +typedef __segsz_t segsz_t; /* segment size */ +typedef __uid_t uid_t; /* user id */ +typedef __useconds_t useconds_t; /* microseconds */ +typedef __suseconds_t suseconds_t; /* microseconds (signed) */ +typedef __fsblkcnt_t fsblkcnt_t; /* file system block count */ +typedef __fsfilcnt_t fsfilcnt_t; /* file system file count */ + +/* + * The following types may be defined in multiple header files. + */ +#ifndef _CLOCK_T_DEFINED_ +#define _CLOCK_T_DEFINED_ +typedef __clock_t clock_t; +#endif + +#ifndef _CLOCKID_T_DEFINED_ +#define _CLOCKID_T_DEFINED_ +typedef __clockid_t clockid_t; +#endif + +#ifndef _PID_T_DEFINED_ +#define _PID_T_DEFINED_ +typedef __pid_t pid_t; +#endif + +#ifndef _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED_ +typedef __size_t size_t; +#endif + +#ifndef _SSIZE_T_DEFINED_ +#define _SSIZE_T_DEFINED_ +typedef __ssize_t ssize_t; +#endif + +#ifndef _TIME_T_DEFINED_ +#define _TIME_T_DEFINED_ +typedef __time_t time_t; +#endif + +#ifndef _TIMER_T_DEFINED_ +#define _TIMER_T_DEFINED_ +typedef __timer_t timer_t; +#endif + +#ifndef _OFF_T_DEFINED_ +#define _OFF_T_DEFINED_ +typedef __off_t off_t; +#endif + +/* + * These belong in unistd.h, but are placed here too to ensure that + * long arguments will be promoted to off_t if the program fails to + * include that header or explicitly cast them to off_t. + */ +#if __BSD_VISIBLE && !defined(_KERNEL) +__BEGIN_DECLS +off_t lseek(int, off_t, int); +int ftruncate(int, off_t); +int truncate(const char *, off_t); +__END_DECLS +#endif /* __BSD_VISIBLE && !_KERNEL */ + +#if __BSD_VISIBLE +/* Major, minor numbers, dev_t's. */ +#define major(x) (((unsigned)(x) >> 8) & 0xff) +#define minor(x) ((unsigned)((x) & 0xff) | (((x) & 0xffff0000) >> 8)) +#define makedev(x,y) ((dev_t)((((x) & 0xff) << 8) | ((y) & 0xff) | (((y) & 0xffff00) << 8))) +#endif + +#if defined(__STDC__) && defined(_KERNEL) +/* + * Forward structure declarations for function prototypes. We include the + * common structures that cross subsystem boundaries here; others are mostly + * used in the same place that the structure is defined. + */ +struct proc; +struct pgrp; +struct ucred; +struct rusage; +struct file; +struct buf; +struct tty; +struct uio; +#endif + +#ifdef _KERNEL +#if defined(__GNUC__) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901) +/* Support for C99: type _Bool is already built-in. */ +#define false 0 +#define true 1 + +#else +/* `_Bool' type must promote to `int' or `unsigned int'. */ +typedef enum { + false = 0, + true = 1 +} _Bool; + +/* And those constants must also be available as macros. */ +#define false false +#define true true + +#endif + +/* User visible type `bool' is provided as a macro which may be redefined */ +#define bool _Bool + +/* Inform that everything is fine */ +#define __bool_true_false_are_defined 1 + +#endif /* _KERNEL */ + +#endif /* !_SYS_TYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/ucred.h b/lib/libc/include/generic-openbsd/sys/ucred.h new file mode 100644 index 000000000000..6f3bdda198f1 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/ucred.h @@ -0,0 +1,85 @@ +/* $OpenBSD: ucred.h,v 1.14 2022/03/17 14:23:34 visa Exp $ */ +/* $NetBSD: ucred.h,v 1.12 1995/06/01 22:44:50 jtc Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ucred.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _SYS_UCRED_H_ +#define _SYS_UCRED_H_ + +#include +#include + +/* + * Credentials. + */ +struct ucred { + struct refcnt cr_refcnt; /* reference count */ + +/* The following fields are all copied by crset() */ +#define cr_startcopy cr_uid + uid_t cr_uid; /* effective user id */ + uid_t cr_ruid; /* Real user id. */ + uid_t cr_svuid; /* Saved effective user id. */ + gid_t cr_gid; /* effective group id */ + gid_t cr_rgid; /* Real group id. */ + gid_t cr_svgid; /* Saved effective group id. */ + short cr_ngroups; /* number of groups */ + gid_t cr_groups[NGROUPS_MAX]; /* groups */ +}; +#define NOCRED ((struct ucred *)-1) /* no credential available */ +#define FSCRED ((struct ucred *)-2) /* filesystem credential */ + +/* + * Userspace version, for use in syscalls arguments + */ +struct xucred { + uid_t cr_uid; /* user id */ + gid_t cr_gid; /* group id */ + short cr_ngroups; /* number of groups */ + gid_t cr_groups[NGROUPS_MAX]; /* groups */ +}; + +#ifdef _KERNEL + +int crfromxucred(struct ucred *, const struct xucred *); +void crset(struct ucred *, const struct ucred *); +struct ucred *crcopy(struct ucred *cr); +struct ucred *crdup(struct ucred *cr); +void crfree(struct ucred *cr); +struct ucred *crget(void); +struct ucred *crhold(struct ucred *); +int suser(struct proc *p); +int suser_ucred(struct ucred *cred); + +#endif /* _KERNEL */ + +#endif /* !_SYS_UCRED_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/uio.h b/lib/libc/include/generic-openbsd/sys/uio.h new file mode 100644 index 000000000000..5e499be18497 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/uio.h @@ -0,0 +1,107 @@ +/* $OpenBSD: uio.h,v 1.20 2024/10/26 05:39:03 jsg Exp $ */ +/* $NetBSD: uio.h,v 1.12 1996/02/09 18:25:45 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)uio.h 8.5 (Berkeley) 2/22/94 + */ + +#ifndef _SYS_UIO_H_ +#define _SYS_UIO_H_ + +#include +#include + +#ifndef _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED_ +typedef __size_t size_t; +#endif + +#ifndef _SSIZE_T_DEFINED_ +#define _SSIZE_T_DEFINED_ +typedef __ssize_t ssize_t; +#endif + +struct iovec { + void *iov_base; /* Base address. */ + size_t iov_len; /* Length. */ +}; + +#if __BSD_VISIBLE /* needed by kdump */ +enum uio_rw { UIO_READ, UIO_WRITE }; + +/* Segment flag values. */ +enum uio_seg { + UIO_USERSPACE, /* from user data space */ + UIO_SYSSPACE /* from system space */ +}; +#endif /* __BSD_VISIBLE */ + +#ifdef _KERNEL +struct uio { + struct iovec *uio_iov; /* pointer to array of iovecs */ + int uio_iovcnt; /* number of iovecs in array */ + off_t uio_offset; /* offset into file this uio corresponds to */ + size_t uio_resid; /* residual i/o count */ + enum uio_seg uio_segflg; /* see above */ + enum uio_rw uio_rw; /* see above */ + struct proc *uio_procp;/* associated thread or NULL */ +}; + +/* + * Limits + */ +#define UIO_SMALLIOV 8 /* 8 on stack, else malloc */ +#endif /* _KERNEL */ + +#if __BSD_VISIBLE +#define UIO_MAXIOV 1024 /* Deprecated, use IOV_MAX instead */ +#endif + +#ifndef _KERNEL +__BEGIN_DECLS +#if __BSD_VISIBLE +ssize_t preadv(int, const struct iovec *, int, __off_t); +ssize_t pwritev(int, const struct iovec *, int, __off_t); +#endif /* __BSD_VISIBLE */ +ssize_t readv(int, const struct iovec *, int); +ssize_t writev(int, const struct iovec *, int); +__END_DECLS +#else +int ureadc(int c, struct uio *); + +int iovec_copyin(const struct iovec *, struct iovec **, struct iovec *, + unsigned int, size_t *); +void iovec_free(struct iovec *, unsigned int ); +int dofilereadv(struct proc *, int, struct uio *, int, register_t *); +int dofilewritev(struct proc *, int, struct uio *, int, register_t *); + +#endif /* !_KERNEL */ + +#endif /* !_SYS_UIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/un.h b/lib/libc/include/generic-openbsd/sys/un.h new file mode 100644 index 000000000000..07430f116dbf --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/un.h @@ -0,0 +1,65 @@ +/* $OpenBSD: un.h,v 1.14 2015/07/18 15:00:01 guenther Exp $ */ +/* $NetBSD: un.h,v 1.11 1996/02/04 02:12:47 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)un.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _SYS_UN_H_ +#define _SYS_UN_H_ + +#include +#include + +#ifndef _SA_FAMILY_T_DEFINED_ +#define _SA_FAMILY_T_DEFINED_ +typedef __sa_family_t sa_family_t; /* sockaddr address family type */ +#endif + +/* + * Definitions for UNIX IPC domain. + */ +struct sockaddr_un { + unsigned char sun_len; /* sockaddr len excluding NUL */ + sa_family_t sun_family; /* AF_UNIX */ + char sun_path[104]; /* path name (gag) */ +}; + +#ifndef _KERNEL +#if __BSD_VISIBLE + +/* actual length of an initialized sockaddr_un */ +#define SUN_LEN(su) \ + (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) + +#endif /* __BSD_VISIBLE */ + +#endif /* _KERNEL */ +#endif /* !_SYS_UN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/unistd.h b/lib/libc/include/generic-openbsd/sys/unistd.h new file mode 100644 index 000000000000..7a911b4562ec --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/unistd.h @@ -0,0 +1,106 @@ +/* $OpenBSD: unistd.h,v 1.31 2015/07/20 00:56:10 guenther Exp $ */ +/* $NetBSD: unistd.h,v 1.10 1994/06/29 06:46:06 cgd Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)unistd.h 8.2 (Berkeley) 1/7/94 + */ + +#ifndef _SYS_UNISTD_H_ +#define _SYS_UNISTD_H_ + +#include + +#define _POSIX_VDISABLE (0377) +#define _POSIX_ASYNC_IO (-1) +#define _POSIX_PRIO_IO (-1) +#define _POSIX_SYNC_IO (-1) + +/* Define the POSIX.1 version we target for compliance. */ +#define _POSIX_VERSION 200809L + +/* access function */ +#define F_OK 0 /* test for existence of file */ +#define X_OK 0x01 /* test for execute or search permission */ +#define W_OK 0x02 /* test for write permission */ +#define R_OK 0x04 /* test for read permission */ + +/* whence values for lseek(2) */ +#define SEEK_SET 0 /* set file offset to offset */ +#define SEEK_CUR 1 /* set file offset to current plus offset */ +#define SEEK_END 2 /* set file offset to EOF plus offset */ + +#if __BSD_VISIBLE +/* old BSD whence values for lseek(2); renamed by POSIX 1003.1 */ +#define L_SET SEEK_SET +#define L_INCR SEEK_CUR +#define L_XTND SEEK_END + +/* the parameters argument passed to the __tfork() syscall */ +struct __tfork { + void *tf_tcb; + pid_t *tf_tid; + void *tf_stack; +}; + +/* the parameters argument for the kbind() syscall */ +struct __kbind { + void *kb_addr; + size_t kb_size; +}; +#define KBIND_BLOCK_MAX 2 /* powerpc, sparc, and sparc64 need 2 blocks */ +#define KBIND_DATA_MAX 24 /* sparc64 needs 6, four-byte words */ +#endif + +/* the pathconf(2) variable values are part of the ABI */ + +/* configurable pathname variables */ +#define _PC_LINK_MAX 1 +#define _PC_MAX_CANON 2 +#define _PC_MAX_INPUT 3 +#define _PC_NAME_MAX 4 +#define _PC_PATH_MAX 5 +#define _PC_PIPE_BUF 6 +#define _PC_CHOWN_RESTRICTED 7 +#define _PC_NO_TRUNC 8 +#define _PC_VDISABLE 9 +#define _PC_2_SYMLINKS 10 +#define _PC_ALLOC_SIZE_MIN 11 +#define _PC_ASYNC_IO 12 +#define _PC_FILESIZEBITS 13 +#define _PC_PRIO_IO 14 +#define _PC_REC_INCR_XFER_SIZE 15 +#define _PC_REC_MAX_XFER_SIZE 16 +#define _PC_REC_MIN_XFER_SIZE 17 +#define _PC_REC_XFER_ALIGN 18 +#define _PC_SYMLINK_MAX 19 +#define _PC_SYNC_IO 20 +#define _PC_TIMESTAMP_RESOLUTION 21 + +#endif /* !_SYS_UNISTD_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/unpcb.h b/lib/libc/include/generic-openbsd/sys/unpcb.h new file mode 100644 index 000000000000..cae6ebd9b427 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/unpcb.h @@ -0,0 +1,145 @@ +/* $OpenBSD: unpcb.h,v 1.45 2022/11/26 17:51:18 mvs Exp $ */ +/* $NetBSD: unpcb.h,v 1.6 1994/06/29 06:46:08 cgd Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)unpcb.h 8.1 (Berkeley) 6/2/93 + */ + +#include + +/* + * Protocol control block for an active + * instance of a UNIX internal protocol. + * + * A socket may be associated with an vnode in the + * file system. If so, the unp_vnode pointer holds + * a reference count to this vnode, which should be vrele'd + * when the socket goes away. + * + * A socket may be connected to another socket, in which + * case the control block of the socket to which it is connected + * is given by unp_conn. + * + * A socket may be referenced by a number of sockets (e.g. several + * sockets may be connected to a datagram socket.) These sockets + * are in a linked list starting with unp_refs, linked through + * unp_nextref and null-terminated. Note that a socket may be referenced + * by a number of other sockets and may also reference a socket (not + * necessarily one which is referencing it). This generates + * the need for unp_refs and unp_nextref to be separate fields. + * + * Stream sockets keep copies of receive sockbuf sb_cc and sb_mbcnt + * so that changes in the sockbuf may be computed to modify + * back pressure on the sender accordingly. + * + * Locks used to protect struct members: + * I immutable after creation + * G unp_gc_lock + * s socket lock + */ + + +struct unpcb { + struct refcnt unp_refcnt; /* references to this pcb */ + struct socket *unp_socket; /* [I] pointer back to socket */ + struct vnode *unp_vnode; /* [s] if associated with file */ + struct file *unp_file; /* [G] backpointer for unp_gc() */ + struct unpcb *unp_conn; /* [s] control block of connected + socket */ + ino_t unp_ino; /* [s] fake inode number */ + SLIST_HEAD(,unpcb) unp_refs; /* [s] referencing socket linked list */ + SLIST_ENTRY(unpcb) unp_nextref; /* [s] link in unp_refs list */ + struct mbuf *unp_addr; /* [s] bound address of socket */ + long unp_msgcount; /* [G] references from socket rcv buf */ + long unp_gcrefs; /* [G] references from gc */ + int unp_flags; /* [s] this unpcb contains peer eids */ + int unp_gcflags; /* [G] garbage collector flags */ + struct sockpeercred unp_connid;/* [s] id of peer process */ + struct timespec unp_ctime; /* [I] holds creation time */ + LIST_ENTRY(unpcb) unp_link; /* [G] link in per-AF list of sockets */ +}; + +/* + * flag bits in unp_flags + */ +#define UNP_FEIDS 0x01 /* unp_connid contains information */ +#define UNP_FEIDSBIND 0x02 /* unp_connid was set by a bind */ +#define UNP_BINDING 0x04 /* unp is binding now */ +#define UNP_CONNECTING 0x08 /* unp is connecting now */ + +/* + * flag bits in unp_gcflags + */ +#define UNP_GCDEAD 0x01 /* unp could be dead */ + +#define sotounpcb(so) ((struct unpcb *)((so)->so_pcb)) + +#ifdef _KERNEL + +struct stat; + +struct fdpass { + struct file *fp; + int flags; +}; + +extern const struct pr_usrreqs uipc_usrreqs; +extern const struct pr_usrreqs uipc_dgram_usrreqs; + +int uipc_attach(struct socket *, int, int); +int uipc_detach(struct socket *); +int uipc_bind(struct socket *, struct mbuf *, struct proc *); +int uipc_listen(struct socket *); +int uipc_connect(struct socket *, struct mbuf *); +int uipc_accept(struct socket *, struct mbuf *); +int uipc_disconnect(struct socket *); +int uipc_shutdown(struct socket *); +int uipc_dgram_shutdown(struct socket *); +void uipc_rcvd(struct socket *); +int uipc_send(struct socket *, struct mbuf *, struct mbuf *, + struct mbuf *); +int uipc_dgram_send(struct socket *, struct mbuf *, struct mbuf *, + struct mbuf *); +void uipc_abort(struct socket *); +int uipc_sense(struct socket *, struct stat *); +int uipc_sockaddr(struct socket *, struct mbuf *); +int uipc_peeraddr(struct socket *, struct mbuf *); +int uipc_connect2(struct socket *, struct socket *); + +void unp_init(void); +int unp_connect(struct socket *, struct mbuf *, struct proc *); +int unp_connect2(struct socket *, struct socket *); +void unp_detach(struct unpcb *); +void unp_disconnect(struct unpcb *); +void unp_gc(void *); +int unp_externalize(struct mbuf *, socklen_t, int); +int unp_internalize(struct mbuf *, struct proc *); +void unp_dispose(struct mbuf *); +#endif /* _KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/user.h b/lib/libc/include/generic-openbsd/sys/user.h new file mode 100644 index 000000000000..1d80462bd917 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/user.h @@ -0,0 +1,48 @@ +/* $OpenBSD: user.h,v 1.9 2014/07/08 23:31:22 deraadt Exp $ */ +/* $NetBSD: user.h,v 1.10 1996/04/09 20:55:49 cgd Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)user.h 8.2 (Berkeley) 9/23/93 + */ + +#include +#include +#include + +/* + * Per process structure containing data that isn't needed in core + * when the process isn't running (esp. when swapped out). + * This structure may or may not be at the same kernel address + * in all processes. + */ + +struct user { + struct pcb u_pcb; +}; \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/utsname.h b/lib/libc/include/generic-openbsd/sys/utsname.h new file mode 100644 index 000000000000..8f1378962a68 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/utsname.h @@ -0,0 +1,59 @@ +/* $OpenBSD: utsname.h,v 1.6 2013/03/24 17:45:50 deraadt Exp $ */ +/* $NetBSD: utsname.h,v 1.6 1994/06/29 06:46:11 cgd Exp $ */ + +/*- + * Copyright (c) 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chuck Karish of Mindcraft, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)utsname.h 8.1 (Berkeley) 1/4/94 + */ + +#ifndef _SYS_UTSNAME_H +#define _SYS_UTSNAME_H + +#define SYS_NMLN 256 + +struct utsname { + char sysname[SYS_NMLN]; /* Name of this OS. */ + char nodename[SYS_NMLN]; /* Name of this network node. */ + char release[SYS_NMLN]; /* Release level. */ + char version[SYS_NMLN]; /* Version level. */ + char machine[SYS_NMLN]; /* Hardware type. */ +}; + +#include + +#ifndef _KERNEL +__BEGIN_DECLS +int uname(struct utsname *); +__END_DECLS +#endif /* !_KERNEL */ + +#endif /* !_SYS_UTSNAME_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/uuid.h b/lib/libc/include/generic-openbsd/sys/uuid.h new file mode 100644 index 000000000000..c834c09802c5 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/uuid.h @@ -0,0 +1,71 @@ +/* $OpenBSD: uuid.h,v 1.5 2025/07/11 19:12:49 krw Exp $ */ +/* $NetBSD: uuid.h,v 1.5 2008/11/18 14:01:03 joerg Exp $ */ + +/* + * Copyright (c) 2002 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: /repoman/r/ncvs/src/sys/sys/uuid.h,v 1.3 2003/05/31 16:47:07 phk Exp $ + */ + +#ifndef _SYS_UUID_H_ +#define _SYS_UUID_H_ + +/* Length of a node address (an IEEE 802 address). */ +#define _UUID_NODE_LEN 6 + +/* Length of a printed UUID. */ +#define _UUID_BUF_LEN 38 + +/* + * See also: + * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt + * http://www.opengroup.org/onlinepubs/009629399/apdxa.htm + * + * A DCE 1.1 compatible source representation of UUIDs. + */ +struct uuid { + uint32_t time_low; + uint16_t time_mid; + uint16_t time_hi_and_version; + uint8_t clock_seq_hi_and_reserved; + uint8_t clock_seq_low; + uint8_t node[_UUID_NODE_LEN]; +}; + +#ifdef _KERNEL + +#define UUID_NODE_LEN _UUID_NODE_LEN +#define UUID_BUF_LEN _UUID_BUF_LEN + +int uuid_snprintf(char *, size_t, const struct uuid *); +int uuid_printf(const struct uuid *); + +#else /* _KERNEL */ + +typedef struct uuid uuid_t; + +#endif /* _KERNEL */ + +#endif /* _SYS_UUID_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/varargs.h b/lib/libc/include/generic-openbsd/sys/varargs.h new file mode 100644 index 000000000000..0f3d2c690af6 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/varargs.h @@ -0,0 +1,51 @@ +/* $OpenBSD: varargs.h,v 1.4 2020/07/21 23:09:00 daniel Exp $ */ +/* + * Copyright (c) 2003, 2004 Marc espie + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _VARARGS_H_ +#define _VARARGS_H_ + +/* These macros implement traditional (non-ANSI) varargs + for GNU C. */ + +#define va_alist __builtin_va_alist + +#define __va_ellipsis ... + +/* ??? We don't process attributes correctly in K&R argument context. */ +typedef int __builtin_va_alist_t __attribute__((__mode__(__word__))); + +/* ??? It would be nice to get rid of the ellipsis here. It causes + current_function_varargs to be set in cc1. */ +#define va_dcl __builtin_va_alist_t __builtin_va_alist; ... + +/* Define __gnuc_va_list, just as in stdarg.h. */ + +#ifndef __GNUC_VA_LIST +#define __GNUC_VA_LIST +typedef __builtin_va_list __gnuc_va_list; +#endif + +#define va_start(v) __builtin_varargs_start((v)) +#define va_end __builtin_va_end +#define va_arg __builtin_va_arg +#define __va_copy(d,s) __builtin_va_copy((d),(s)) + +/* Define va_list from __gnuc_va_list. */ + +typedef __gnuc_va_list va_list; + +#endif /* _VARARGS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/videoio.h b/lib/libc/include/generic-openbsd/sys/videoio.h new file mode 100644 index 000000000000..361f46c7ae21 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/videoio.h @@ -0,0 +1,6328 @@ +/* $OpenBSD: videoio.h,v 1.26 2025/08/02 09:27:59 kirill Exp $ */ + +/* + * Video for Linux Two header file + * + * Copyright (C) 1999-2012 the contributors + * Copyright (C) 2012 Nokia Corporation + * Contact: Sakari Ailus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Alternatively you can redistribute this file under the terms of the + * BSD license as stated below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. The names of its contributors may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT + * OWNER 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. + * + * Header file for v4l or V4L2 drivers and applications + * with public API. + * All kernel-specific stuff were moved to media/v4l2-dev.h, so + * no #if __KERNEL tests are allowed here + * + * See https://linuxtv.org for more info + * + * Author: Bill Dirks + * Justin Schoeman + * Hans Verkuil + * et al. + */ + +#ifndef _SYS_VIDEOIO_H_ +#define _SYS_VIDEOIO_H_ +#include +#include +#include +/* Inline #include + * (v4l2-common.h was split off from videodev2.h and has the same BSD license.) + * + * Begin of v4l2-common.h + */ +/* + * + * Selection interface definitions + * + */ + +/* Current cropping area */ +#define V4L2_SEL_TGT_CROP 0x0000 +/* Default cropping area */ +#define V4L2_SEL_TGT_CROP_DEFAULT 0x0001 +/* Cropping bounds */ +#define V4L2_SEL_TGT_CROP_BOUNDS 0x0002 +/* Native frame size */ +#define V4L2_SEL_TGT_NATIVE_SIZE 0x0003 +/* Current composing area */ +#define V4L2_SEL_TGT_COMPOSE 0x0100 +/* Default composing area */ +#define V4L2_SEL_TGT_COMPOSE_DEFAULT 0x0101 +/* Composing bounds */ +#define V4L2_SEL_TGT_COMPOSE_BOUNDS 0x0102 +/* Current composing area plus all padding pixels */ +#define V4L2_SEL_TGT_COMPOSE_PADDED 0x0103 + +/* Backward compatibility target definitions --- to be removed. */ +#define V4L2_SEL_TGT_CROP_ACTIVE V4L2_SEL_TGT_CROP +#define V4L2_SEL_TGT_COMPOSE_ACTIVE V4L2_SEL_TGT_COMPOSE +#define V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL V4L2_SEL_TGT_CROP +#define V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL V4L2_SEL_TGT_COMPOSE +#define V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS V4L2_SEL_TGT_CROP_BOUNDS +#define V4L2_SUBDEV_SEL_TGT_COMPOSE_BOUNDS V4L2_SEL_TGT_COMPOSE_BOUNDS + +/* Selection flags */ +#define V4L2_SEL_FLAG_GE (1 << 0) +#define V4L2_SEL_FLAG_LE (1 << 1) +#define V4L2_SEL_FLAG_KEEP_CONFIG (1 << 2) + +struct v4l2_edid { + u_int32_t pad; + u_int32_t start_block; + u_int32_t blocks; + u_int32_t reserved[5]; + u_int8_t *edid; +}; + +/* Backward compatibility target definitions --- to be removed. */ +#define V4L2_SEL_TGT_CROP_ACTIVE V4L2_SEL_TGT_CROP +#define V4L2_SEL_TGT_COMPOSE_ACTIVE V4L2_SEL_TGT_COMPOSE +#define V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL V4L2_SEL_TGT_CROP +#define V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL V4L2_SEL_TGT_COMPOSE +#define V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS V4L2_SEL_TGT_CROP_BOUNDS +#define V4L2_SUBDEV_SEL_TGT_COMPOSE_BOUNDS V4L2_SEL_TGT_COMPOSE_BOUNDS + +/* Backward compatibility flag definitions --- to be removed. */ +#define V4L2_SUBDEV_SEL_FLAG_SIZE_GE V4L2_SEL_FLAG_GE +#define V4L2_SUBDEV_SEL_FLAG_SIZE_LE V4L2_SEL_FLAG_LE +#define V4L2_SUBDEV_SEL_FLAG_KEEP_CONFIG V4L2_SEL_FLAG_KEEP_CONFIG +/* + * End of v4l2-common.h + */ +/* Inline #include + * (v4l2-controls.h was split off from videodev2.h and has the same BSD license.) + * + * Begin of v4l2-controls.h + */ +/* Control classes */ +#define V4L2_CTRL_CLASS_USER 0x00980000 /* Old-style 'user' controls */ +#define V4L2_CTRL_CLASS_CODEC 0x00990000 /* Stateful codec controls */ +#define V4L2_CTRL_CLASS_CAMERA 0x009a0000 /* Camera class controls */ +#define V4L2_CTRL_CLASS_FM_TX 0x009b0000 /* FM Modulator controls */ +#define V4L2_CTRL_CLASS_FLASH 0x009c0000 /* Camera flash controls */ +#define V4L2_CTRL_CLASS_JPEG 0x009d0000 /* JPEG-compression controls */ +#define V4L2_CTRL_CLASS_IMAGE_SOURCE 0x009e0000 /* Image source controls */ +#define V4L2_CTRL_CLASS_IMAGE_PROC 0x009f0000 /* Image processing controls */ +#define V4L2_CTRL_CLASS_DV 0x00a00000 /* Digital Video controls */ +#define V4L2_CTRL_CLASS_FM_RX 0x00a10000 /* FM Receiver controls */ +#define V4L2_CTRL_CLASS_RF_TUNER 0x00a20000 /* RF tuner controls */ +#define V4L2_CTRL_CLASS_DETECT 0x00a30000 /* Detection controls */ +#define V4L2_CTRL_CLASS_CODEC_STATELESS 0x00a40000 /* Stateless codecs controls */ +#define V4L2_CTRL_CLASS_COLORIMETRY 0x00a50000 /* Colorimetry controls */ + +/* User-class control IDs */ + +#define V4L2_CID_BASE (V4L2_CTRL_CLASS_USER | 0x900) +#define V4L2_CID_USER_BASE V4L2_CID_BASE +#define V4L2_CID_USER_CLASS (V4L2_CTRL_CLASS_USER | 1) +#define V4L2_CID_BRIGHTNESS (V4L2_CID_BASE+0) +#define V4L2_CID_CONTRAST (V4L2_CID_BASE+1) +#define V4L2_CID_SATURATION (V4L2_CID_BASE+2) +#define V4L2_CID_HUE (V4L2_CID_BASE+3) +#define V4L2_CID_AUDIO_VOLUME (V4L2_CID_BASE+5) +#define V4L2_CID_AUDIO_BALANCE (V4L2_CID_BASE+6) +#define V4L2_CID_AUDIO_BASS (V4L2_CID_BASE+7) +#define V4L2_CID_AUDIO_TREBLE (V4L2_CID_BASE+8) +#define V4L2_CID_AUDIO_MUTE (V4L2_CID_BASE+9) +#define V4L2_CID_AUDIO_LOUDNESS (V4L2_CID_BASE+10) +#define V4L2_CID_BLACK_LEVEL (V4L2_CID_BASE+11) /* Deprecated */ +#define V4L2_CID_AUTO_WHITE_BALANCE (V4L2_CID_BASE+12) +#define V4L2_CID_DO_WHITE_BALANCE (V4L2_CID_BASE+13) +#define V4L2_CID_RED_BALANCE (V4L2_CID_BASE+14) +#define V4L2_CID_BLUE_BALANCE (V4L2_CID_BASE+15) +#define V4L2_CID_GAMMA (V4L2_CID_BASE+16) +#define V4L2_CID_WHITENESS (V4L2_CID_GAMMA) /* Deprecated */ +#define V4L2_CID_EXPOSURE (V4L2_CID_BASE+17) +#define V4L2_CID_AUTOGAIN (V4L2_CID_BASE+18) +#define V4L2_CID_GAIN (V4L2_CID_BASE+19) +#define V4L2_CID_HFLIP (V4L2_CID_BASE+20) +#define V4L2_CID_VFLIP (V4L2_CID_BASE+21) + +#define V4L2_CID_POWER_LINE_FREQUENCY (V4L2_CID_BASE+24) +enum v4l2_power_line_frequency { + V4L2_CID_POWER_LINE_FREQUENCY_DISABLED = 0, + V4L2_CID_POWER_LINE_FREQUENCY_50HZ = 1, + V4L2_CID_POWER_LINE_FREQUENCY_60HZ = 2, + V4L2_CID_POWER_LINE_FREQUENCY_AUTO = 3, +}; +#define V4L2_CID_HUE_AUTO (V4L2_CID_BASE+25) +#define V4L2_CID_WHITE_BALANCE_TEMPERATURE (V4L2_CID_BASE+26) +#define V4L2_CID_SHARPNESS (V4L2_CID_BASE+27) +#define V4L2_CID_BACKLIGHT_COMPENSATION (V4L2_CID_BASE+28) +#define V4L2_CID_CHROMA_AGC (V4L2_CID_BASE+29) +#define V4L2_CID_COLOR_KILLER (V4L2_CID_BASE+30) +#define V4L2_CID_COLORFX (V4L2_CID_BASE+31) +enum v4l2_colorfx { + V4L2_COLORFX_NONE = 0, + V4L2_COLORFX_BW = 1, + V4L2_COLORFX_SEPIA = 2, + V4L2_COLORFX_NEGATIVE = 3, + V4L2_COLORFX_EMBOSS = 4, + V4L2_COLORFX_SKETCH = 5, + V4L2_COLORFX_SKY_BLUE = 6, + V4L2_COLORFX_GRASS_GREEN = 7, + V4L2_COLORFX_SKIN_WHITEN = 8, + V4L2_COLORFX_VIVID = 9, + V4L2_COLORFX_AQUA = 10, + V4L2_COLORFX_ART_FREEZE = 11, + V4L2_COLORFX_SILHOUETTE = 12, + V4L2_COLORFX_SOLARIZATION = 13, + V4L2_COLORFX_ANTIQUE = 14, + V4L2_COLORFX_SET_CBCR = 15, + V4L2_COLORFX_SET_RGB = 16, +}; +#define V4L2_CID_AUTOBRIGHTNESS (V4L2_CID_BASE+32) +#define V4L2_CID_BAND_STOP_FILTER (V4L2_CID_BASE+33) + +#define V4L2_CID_ROTATE (V4L2_CID_BASE+34) +#define V4L2_CID_BG_COLOR (V4L2_CID_BASE+35) + +#define V4L2_CID_CHROMA_GAIN (V4L2_CID_BASE+36) + +#define V4L2_CID_ILLUMINATORS_1 (V4L2_CID_BASE+37) +#define V4L2_CID_ILLUMINATORS_2 (V4L2_CID_BASE+38) + +#define V4L2_CID_MIN_BUFFERS_FOR_CAPTURE (V4L2_CID_BASE+39) +#define V4L2_CID_MIN_BUFFERS_FOR_OUTPUT (V4L2_CID_BASE+40) + +#define V4L2_CID_ALPHA_COMPONENT (V4L2_CID_BASE+41) +#define V4L2_CID_COLORFX_CBCR (V4L2_CID_BASE+42) +#define V4L2_CID_COLORFX_RGB (V4L2_CID_BASE+43) + +/* last CID + 1 */ +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+44) + +/* USER-class private control IDs */ + +/* + * The base for the meye driver controls. This driver was removed, but + * we keep this define in case any software still uses it. + */ +#define V4L2_CID_USER_MEYE_BASE (V4L2_CID_USER_BASE + 0x1000) + +/* The base for the bttv driver controls. + * We reserve 32 controls for this driver. */ +#define V4L2_CID_USER_BTTV_BASE (V4L2_CID_USER_BASE + 0x1010) + + +/* The base for the s2255 driver controls. + * We reserve 16 controls for this driver. */ +#define V4L2_CID_USER_S2255_BASE (V4L2_CID_USER_BASE + 0x1030) + +/* + * The base for the si476x driver controls. See include/media/drv-intf/si476x.h + * for the list of controls. Total of 16 controls is reserved for this driver + */ +#define V4L2_CID_USER_SI476X_BASE (V4L2_CID_USER_BASE + 0x1040) + +/* The base for the TI VPE driver controls. Total of 16 controls is reserved for + * this driver */ +#define V4L2_CID_USER_TI_VPE_BASE (V4L2_CID_USER_BASE + 0x1050) + +/* The base for the saa7134 driver controls. + * We reserve 16 controls for this driver. */ +#define V4L2_CID_USER_SAA7134_BASE (V4L2_CID_USER_BASE + 0x1060) + +/* The base for the adv7180 driver controls. + * We reserve 16 controls for this driver. */ +#define V4L2_CID_USER_ADV7180_BASE (V4L2_CID_USER_BASE + 0x1070) + +/* The base for the tc358743 driver controls. + * We reserve 16 controls for this driver. */ +#define V4L2_CID_USER_TC358743_BASE (V4L2_CID_USER_BASE + 0x1080) + +/* The base for the max217x driver controls. + * We reserve 32 controls for this driver + */ +#define V4L2_CID_USER_MAX217X_BASE (V4L2_CID_USER_BASE + 0x1090) + +/* The base for the imx driver controls. + * We reserve 16 controls for this driver. */ +#define V4L2_CID_USER_IMX_BASE (V4L2_CID_USER_BASE + 0x10b0) + +/* + * The base for the atmel isc driver controls. + * We reserve 32 controls for this driver. + */ +#define V4L2_CID_USER_ATMEL_ISC_BASE (V4L2_CID_USER_BASE + 0x10c0) + +/* + * The base for the CODA driver controls. + * We reserve 16 controls for this driver. + */ +#define V4L2_CID_USER_CODA_BASE (V4L2_CID_USER_BASE + 0x10e0) +/* + * The base for MIPI CCS driver controls. + * We reserve 128 controls for this driver. + */ +#define V4L2_CID_USER_CCS_BASE (V4L2_CID_USER_BASE + 0x10f0) +/* + * The base for Allegro driver controls. + * We reserve 16 controls for this driver. + */ +#define V4L2_CID_USER_ALLEGRO_BASE (V4L2_CID_USER_BASE + 0x1170) + +/* + * The base for the isl7998x driver controls. + * We reserve 16 controls for this driver. + */ +#define V4L2_CID_USER_ISL7998X_BASE (V4L2_CID_USER_BASE + 0x1180) + +/* + * The base for DW100 driver controls. + * We reserve 16 controls for this driver. + */ +#define V4L2_CID_USER_DW100_BASE (V4L2_CID_USER_BASE + 0x1190) + +/* + * The base for Aspeed driver controls. + * We reserve 16 controls for this driver. + */ +#define V4L2_CID_USER_ASPEED_BASE (V4L2_CID_USER_BASE + 0x11a0) + +/* + * The base for Nuvoton NPCM driver controls. + * We reserve 16 controls for this driver. + */ +#define V4L2_CID_USER_NPCM_BASE (V4L2_CID_USER_BASE + 0x11b0) + +/* + * The base for THine THP7312 driver controls. + * We reserve 32 controls for this driver. + */ +#define V4L2_CID_USER_THP7312_BASE (V4L2_CID_USER_BASE + 0x11c0) + +/* + * The base for the uvc driver controls. + * See linux/uvcvideo.h for the list of controls. + * We reserve 64 controls for this driver. + */ +#define V4L2_CID_USER_UVC_BASE (V4L2_CID_USER_BASE + 0x11e0) + +/* + * The base for Rockchip ISP1 driver controls. + * We reserve 16 controls for this driver. + */ +#define V4L2_CID_USER_RKISP1_BASE (V4L2_CID_USER_BASE + 0x1220) + +/* MPEG-class control IDs */ +/* The MPEG controls are applicable to all codec controls + * and the 'MPEG' part of the define is historical */ + +#define V4L2_CID_CODEC_BASE (V4L2_CTRL_CLASS_CODEC | 0x900) +#define V4L2_CID_CODEC_CLASS (V4L2_CTRL_CLASS_CODEC | 1) + +/* MPEG streams, specific to multiplexed streams */ +#define V4L2_CID_MPEG_STREAM_TYPE (V4L2_CID_CODEC_BASE+0) +enum v4l2_mpeg_stream_type { + V4L2_MPEG_STREAM_TYPE_MPEG2_PS = 0, /* MPEG-2 program stream */ + V4L2_MPEG_STREAM_TYPE_MPEG2_TS = 1, /* MPEG-2 transport stream */ + V4L2_MPEG_STREAM_TYPE_MPEG1_SS = 2, /* MPEG-1 system stream */ + V4L2_MPEG_STREAM_TYPE_MPEG2_DVD = 3, /* MPEG-2 DVD-compatible stream */ + V4L2_MPEG_STREAM_TYPE_MPEG1_VCD = 4, /* MPEG-1 VCD-compatible stream */ + V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD = 5, /* MPEG-2 SVCD-compatible stream */ +}; +#define V4L2_CID_MPEG_STREAM_PID_PMT (V4L2_CID_CODEC_BASE+1) +#define V4L2_CID_MPEG_STREAM_PID_AUDIO (V4L2_CID_CODEC_BASE+2) +#define V4L2_CID_MPEG_STREAM_PID_VIDEO (V4L2_CID_CODEC_BASE+3) +#define V4L2_CID_MPEG_STREAM_PID_PCR (V4L2_CID_CODEC_BASE+4) +#define V4L2_CID_MPEG_STREAM_PES_ID_AUDIO (V4L2_CID_CODEC_BASE+5) +#define V4L2_CID_MPEG_STREAM_PES_ID_VIDEO (V4L2_CID_CODEC_BASE+6) +#define V4L2_CID_MPEG_STREAM_VBI_FMT (V4L2_CID_CODEC_BASE+7) +enum v4l2_mpeg_stream_vbi_fmt { + V4L2_MPEG_STREAM_VBI_FMT_NONE = 0, /* No VBI in the MPEG stream */ + V4L2_MPEG_STREAM_VBI_FMT_IVTV = 1, /* VBI in private packets, IVTV format */ +}; + +/* MPEG audio controls specific to multiplexed streams */ +#define V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ (V4L2_CID_CODEC_BASE+100) +enum v4l2_mpeg_audio_sampling_freq { + V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100 = 0, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000 = 1, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000 = 2, +}; +#define V4L2_CID_MPEG_AUDIO_ENCODING (V4L2_CID_CODEC_BASE+101) +enum v4l2_mpeg_audio_encoding { + V4L2_MPEG_AUDIO_ENCODING_LAYER_1 = 0, + V4L2_MPEG_AUDIO_ENCODING_LAYER_2 = 1, + V4L2_MPEG_AUDIO_ENCODING_LAYER_3 = 2, + V4L2_MPEG_AUDIO_ENCODING_AAC = 3, + V4L2_MPEG_AUDIO_ENCODING_AC3 = 4, +}; +#define V4L2_CID_MPEG_AUDIO_L1_BITRATE (V4L2_CID_CODEC_BASE+102) +enum v4l2_mpeg_audio_l1_bitrate { + V4L2_MPEG_AUDIO_L1_BITRATE_32K = 0, + V4L2_MPEG_AUDIO_L1_BITRATE_64K = 1, + V4L2_MPEG_AUDIO_L1_BITRATE_96K = 2, + V4L2_MPEG_AUDIO_L1_BITRATE_128K = 3, + V4L2_MPEG_AUDIO_L1_BITRATE_160K = 4, + V4L2_MPEG_AUDIO_L1_BITRATE_192K = 5, + V4L2_MPEG_AUDIO_L1_BITRATE_224K = 6, + V4L2_MPEG_AUDIO_L1_BITRATE_256K = 7, + V4L2_MPEG_AUDIO_L1_BITRATE_288K = 8, + V4L2_MPEG_AUDIO_L1_BITRATE_320K = 9, + V4L2_MPEG_AUDIO_L1_BITRATE_352K = 10, + V4L2_MPEG_AUDIO_L1_BITRATE_384K = 11, + V4L2_MPEG_AUDIO_L1_BITRATE_416K = 12, + V4L2_MPEG_AUDIO_L1_BITRATE_448K = 13, +}; +#define V4L2_CID_MPEG_AUDIO_L2_BITRATE (V4L2_CID_CODEC_BASE+103) +enum v4l2_mpeg_audio_l2_bitrate { + V4L2_MPEG_AUDIO_L2_BITRATE_32K = 0, + V4L2_MPEG_AUDIO_L2_BITRATE_48K = 1, + V4L2_MPEG_AUDIO_L2_BITRATE_56K = 2, + V4L2_MPEG_AUDIO_L2_BITRATE_64K = 3, + V4L2_MPEG_AUDIO_L2_BITRATE_80K = 4, + V4L2_MPEG_AUDIO_L2_BITRATE_96K = 5, + V4L2_MPEG_AUDIO_L2_BITRATE_112K = 6, + V4L2_MPEG_AUDIO_L2_BITRATE_128K = 7, + V4L2_MPEG_AUDIO_L2_BITRATE_160K = 8, + V4L2_MPEG_AUDIO_L2_BITRATE_192K = 9, + V4L2_MPEG_AUDIO_L2_BITRATE_224K = 10, + V4L2_MPEG_AUDIO_L2_BITRATE_256K = 11, + V4L2_MPEG_AUDIO_L2_BITRATE_320K = 12, + V4L2_MPEG_AUDIO_L2_BITRATE_384K = 13, +}; +#define V4L2_CID_MPEG_AUDIO_L3_BITRATE (V4L2_CID_CODEC_BASE+104) +enum v4l2_mpeg_audio_l3_bitrate { + V4L2_MPEG_AUDIO_L3_BITRATE_32K = 0, + V4L2_MPEG_AUDIO_L3_BITRATE_40K = 1, + V4L2_MPEG_AUDIO_L3_BITRATE_48K = 2, + V4L2_MPEG_AUDIO_L3_BITRATE_56K = 3, + V4L2_MPEG_AUDIO_L3_BITRATE_64K = 4, + V4L2_MPEG_AUDIO_L3_BITRATE_80K = 5, + V4L2_MPEG_AUDIO_L3_BITRATE_96K = 6, + V4L2_MPEG_AUDIO_L3_BITRATE_112K = 7, + V4L2_MPEG_AUDIO_L3_BITRATE_128K = 8, + V4L2_MPEG_AUDIO_L3_BITRATE_160K = 9, + V4L2_MPEG_AUDIO_L3_BITRATE_192K = 10, + V4L2_MPEG_AUDIO_L3_BITRATE_224K = 11, + V4L2_MPEG_AUDIO_L3_BITRATE_256K = 12, + V4L2_MPEG_AUDIO_L3_BITRATE_320K = 13, +}; +#define V4L2_CID_MPEG_AUDIO_MODE (V4L2_CID_CODEC_BASE+105) +enum v4l2_mpeg_audio_mode { + V4L2_MPEG_AUDIO_MODE_STEREO = 0, + V4L2_MPEG_AUDIO_MODE_JOINT_STEREO = 1, + V4L2_MPEG_AUDIO_MODE_DUAL = 2, + V4L2_MPEG_AUDIO_MODE_MONO = 3, +}; +#define V4L2_CID_MPEG_AUDIO_MODE_EXTENSION (V4L2_CID_CODEC_BASE+106) +enum v4l2_mpeg_audio_mode_extension { + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4 = 0, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_8 = 1, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_12 = 2, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16 = 3, +}; +#define V4L2_CID_MPEG_AUDIO_EMPHASIS (V4L2_CID_CODEC_BASE+107) +enum v4l2_mpeg_audio_emphasis { + V4L2_MPEG_AUDIO_EMPHASIS_NONE = 0, + V4L2_MPEG_AUDIO_EMPHASIS_50_DIV_15_uS = 1, + V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17 = 2, +}; +#define V4L2_CID_MPEG_AUDIO_CRC (V4L2_CID_CODEC_BASE+108) +enum v4l2_mpeg_audio_crc { + V4L2_MPEG_AUDIO_CRC_NONE = 0, + V4L2_MPEG_AUDIO_CRC_CRC16 = 1, +}; +#define V4L2_CID_MPEG_AUDIO_MUTE (V4L2_CID_CODEC_BASE+109) +#define V4L2_CID_MPEG_AUDIO_AAC_BITRATE (V4L2_CID_CODEC_BASE+110) +#define V4L2_CID_MPEG_AUDIO_AC3_BITRATE (V4L2_CID_CODEC_BASE+111) +enum v4l2_mpeg_audio_ac3_bitrate { + V4L2_MPEG_AUDIO_AC3_BITRATE_32K = 0, + V4L2_MPEG_AUDIO_AC3_BITRATE_40K = 1, + V4L2_MPEG_AUDIO_AC3_BITRATE_48K = 2, + V4L2_MPEG_AUDIO_AC3_BITRATE_56K = 3, + V4L2_MPEG_AUDIO_AC3_BITRATE_64K = 4, + V4L2_MPEG_AUDIO_AC3_BITRATE_80K = 5, + V4L2_MPEG_AUDIO_AC3_BITRATE_96K = 6, + V4L2_MPEG_AUDIO_AC3_BITRATE_112K = 7, + V4L2_MPEG_AUDIO_AC3_BITRATE_128K = 8, + V4L2_MPEG_AUDIO_AC3_BITRATE_160K = 9, + V4L2_MPEG_AUDIO_AC3_BITRATE_192K = 10, + V4L2_MPEG_AUDIO_AC3_BITRATE_224K = 11, + V4L2_MPEG_AUDIO_AC3_BITRATE_256K = 12, + V4L2_MPEG_AUDIO_AC3_BITRATE_320K = 13, + V4L2_MPEG_AUDIO_AC3_BITRATE_384K = 14, + V4L2_MPEG_AUDIO_AC3_BITRATE_448K = 15, + V4L2_MPEG_AUDIO_AC3_BITRATE_512K = 16, + V4L2_MPEG_AUDIO_AC3_BITRATE_576K = 17, + V4L2_MPEG_AUDIO_AC3_BITRATE_640K = 18, +}; +#define V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK (V4L2_CID_CODEC_BASE+112) +enum v4l2_mpeg_audio_dec_playback { + V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO = 0, + V4L2_MPEG_AUDIO_DEC_PLAYBACK_STEREO = 1, + V4L2_MPEG_AUDIO_DEC_PLAYBACK_LEFT = 2, + V4L2_MPEG_AUDIO_DEC_PLAYBACK_RIGHT = 3, + V4L2_MPEG_AUDIO_DEC_PLAYBACK_MONO = 4, + V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO = 5, +}; +#define V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK (V4L2_CID_CODEC_BASE+113) + +/* MPEG video controls specific to multiplexed streams */ +#define V4L2_CID_MPEG_VIDEO_ENCODING (V4L2_CID_CODEC_BASE+200) +enum v4l2_mpeg_video_encoding { + V4L2_MPEG_VIDEO_ENCODING_MPEG_1 = 0, + V4L2_MPEG_VIDEO_ENCODING_MPEG_2 = 1, + V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC = 2, +}; +#define V4L2_CID_MPEG_VIDEO_ASPECT (V4L2_CID_CODEC_BASE+201) +enum v4l2_mpeg_video_aspect { + V4L2_MPEG_VIDEO_ASPECT_1x1 = 0, + V4L2_MPEG_VIDEO_ASPECT_4x3 = 1, + V4L2_MPEG_VIDEO_ASPECT_16x9 = 2, + V4L2_MPEG_VIDEO_ASPECT_221x100 = 3, +}; +#define V4L2_CID_MPEG_VIDEO_B_FRAMES (V4L2_CID_CODEC_BASE+202) +#define V4L2_CID_MPEG_VIDEO_GOP_SIZE (V4L2_CID_CODEC_BASE+203) +#define V4L2_CID_MPEG_VIDEO_GOP_CLOSURE (V4L2_CID_CODEC_BASE+204) +#define V4L2_CID_MPEG_VIDEO_PULLDOWN (V4L2_CID_CODEC_BASE+205) +#define V4L2_CID_MPEG_VIDEO_BITRATE_MODE (V4L2_CID_CODEC_BASE+206) +enum v4l2_mpeg_video_bitrate_mode { + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR = 0, + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR = 1, + V4L2_MPEG_VIDEO_BITRATE_MODE_CQ = 2, +}; +#define V4L2_CID_MPEG_VIDEO_BITRATE (V4L2_CID_CODEC_BASE+207) +#define V4L2_CID_MPEG_VIDEO_BITRATE_PEAK (V4L2_CID_CODEC_BASE+208) +#define V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION (V4L2_CID_CODEC_BASE+209) +#define V4L2_CID_MPEG_VIDEO_MUTE (V4L2_CID_CODEC_BASE+210) +#define V4L2_CID_MPEG_VIDEO_MUTE_YUV (V4L2_CID_CODEC_BASE+211) +#define V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE (V4L2_CID_CODEC_BASE+212) +#define V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER (V4L2_CID_CODEC_BASE+213) +#define V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB (V4L2_CID_CODEC_BASE+214) +#define V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE (V4L2_CID_CODEC_BASE+215) +#define V4L2_CID_MPEG_VIDEO_HEADER_MODE (V4L2_CID_CODEC_BASE+216) +enum v4l2_mpeg_video_header_mode { + V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE = 0, + V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME = 1, + +}; +#define V4L2_CID_MPEG_VIDEO_MAX_REF_PIC (V4L2_CID_CODEC_BASE+217) +#define V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE (V4L2_CID_CODEC_BASE+218) +#define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES (V4L2_CID_CODEC_BASE+219) +#define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB (V4L2_CID_CODEC_BASE+220) +#define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE (V4L2_CID_CODEC_BASE+221) +enum v4l2_mpeg_video_multi_slice_mode { + V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE = 0, + V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB = 1, + V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES = 2, + /* Kept for backwards compatibility reasons. Stupid typo... */ + V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB = 1, + V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES = 2, +}; +#define V4L2_CID_MPEG_VIDEO_VBV_SIZE (V4L2_CID_CODEC_BASE+222) +#define V4L2_CID_MPEG_VIDEO_DEC_PTS (V4L2_CID_CODEC_BASE+223) +#define V4L2_CID_MPEG_VIDEO_DEC_FRAME (V4L2_CID_CODEC_BASE+224) +#define V4L2_CID_MPEG_VIDEO_VBV_DELAY (V4L2_CID_CODEC_BASE+225) +#define V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER (V4L2_CID_CODEC_BASE+226) +#define V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE (V4L2_CID_CODEC_BASE+227) +#define V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE (V4L2_CID_CODEC_BASE+228) +#define V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME (V4L2_CID_CODEC_BASE+229) +#define V4L2_CID_MPEG_VIDEO_BASELAYER_PRIORITY_ID (V4L2_CID_CODEC_BASE+230) +#define V4L2_CID_MPEG_VIDEO_AU_DELIMITER (V4L2_CID_CODEC_BASE+231) +#define V4L2_CID_MPEG_VIDEO_LTR_COUNT (V4L2_CID_CODEC_BASE+232) +#define V4L2_CID_MPEG_VIDEO_FRAME_LTR_INDEX (V4L2_CID_CODEC_BASE+233) +#define V4L2_CID_MPEG_VIDEO_USE_LTR_FRAMES (V4L2_CID_CODEC_BASE+234) +#define V4L2_CID_MPEG_VIDEO_DEC_CONCEAL_COLOR (V4L2_CID_CODEC_BASE+235) +#define V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD (V4L2_CID_CODEC_BASE+236) +#define V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE (V4L2_CID_CODEC_BASE+237) +enum v4l2_mpeg_video_intra_refresh_period_type { + V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM = 0, + V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_CYCLIC = 1, +}; + +/* CIDs for the MPEG-2 Part 2 (H.262) codec */ +#define V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL (V4L2_CID_CODEC_BASE+270) +enum v4l2_mpeg_video_mpeg2_level { + V4L2_MPEG_VIDEO_MPEG2_LEVEL_LOW = 0, + V4L2_MPEG_VIDEO_MPEG2_LEVEL_MAIN = 1, + V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH_1440 = 2, + V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH = 3, +}; +#define V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE (V4L2_CID_CODEC_BASE+271) +enum v4l2_mpeg_video_mpeg2_profile { + V4L2_MPEG_VIDEO_MPEG2_PROFILE_SIMPLE = 0, + V4L2_MPEG_VIDEO_MPEG2_PROFILE_MAIN = 1, + V4L2_MPEG_VIDEO_MPEG2_PROFILE_SNR_SCALABLE = 2, + V4L2_MPEG_VIDEO_MPEG2_PROFILE_SPATIALLY_SCALABLE = 3, + V4L2_MPEG_VIDEO_MPEG2_PROFILE_HIGH = 4, + V4L2_MPEG_VIDEO_MPEG2_PROFILE_MULTIVIEW = 5, +}; + +/* CIDs for the FWHT codec as used by the vicodec driver. */ +#define V4L2_CID_FWHT_I_FRAME_QP (V4L2_CID_CODEC_BASE + 290) +#define V4L2_CID_FWHT_P_FRAME_QP (V4L2_CID_CODEC_BASE + 291) + +#define V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP (V4L2_CID_CODEC_BASE+300) +#define V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP (V4L2_CID_CODEC_BASE+301) +#define V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP (V4L2_CID_CODEC_BASE+302) +#define V4L2_CID_MPEG_VIDEO_H263_MIN_QP (V4L2_CID_CODEC_BASE+303) +#define V4L2_CID_MPEG_VIDEO_H263_MAX_QP (V4L2_CID_CODEC_BASE+304) +#define V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP (V4L2_CID_CODEC_BASE+350) +#define V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP (V4L2_CID_CODEC_BASE+351) +#define V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP (V4L2_CID_CODEC_BASE+352) +#define V4L2_CID_MPEG_VIDEO_H264_MIN_QP (V4L2_CID_CODEC_BASE+353) +#define V4L2_CID_MPEG_VIDEO_H264_MAX_QP (V4L2_CID_CODEC_BASE+354) +#define V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM (V4L2_CID_CODEC_BASE+355) +#define V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE (V4L2_CID_CODEC_BASE+356) +#define V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE (V4L2_CID_CODEC_BASE+357) +enum v4l2_mpeg_video_h264_entropy_mode { + V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC = 0, + V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC = 1, +}; +#define V4L2_CID_MPEG_VIDEO_H264_I_PERIOD (V4L2_CID_CODEC_BASE+358) +#define V4L2_CID_MPEG_VIDEO_H264_LEVEL (V4L2_CID_CODEC_BASE+359) +enum v4l2_mpeg_video_h264_level { + V4L2_MPEG_VIDEO_H264_LEVEL_1_0 = 0, + V4L2_MPEG_VIDEO_H264_LEVEL_1B = 1, + V4L2_MPEG_VIDEO_H264_LEVEL_1_1 = 2, + V4L2_MPEG_VIDEO_H264_LEVEL_1_2 = 3, + V4L2_MPEG_VIDEO_H264_LEVEL_1_3 = 4, + V4L2_MPEG_VIDEO_H264_LEVEL_2_0 = 5, + V4L2_MPEG_VIDEO_H264_LEVEL_2_1 = 6, + V4L2_MPEG_VIDEO_H264_LEVEL_2_2 = 7, + V4L2_MPEG_VIDEO_H264_LEVEL_3_0 = 8, + V4L2_MPEG_VIDEO_H264_LEVEL_3_1 = 9, + V4L2_MPEG_VIDEO_H264_LEVEL_3_2 = 10, + V4L2_MPEG_VIDEO_H264_LEVEL_4_0 = 11, + V4L2_MPEG_VIDEO_H264_LEVEL_4_1 = 12, + V4L2_MPEG_VIDEO_H264_LEVEL_4_2 = 13, + V4L2_MPEG_VIDEO_H264_LEVEL_5_0 = 14, + V4L2_MPEG_VIDEO_H264_LEVEL_5_1 = 15, + V4L2_MPEG_VIDEO_H264_LEVEL_5_2 = 16, + V4L2_MPEG_VIDEO_H264_LEVEL_6_0 = 17, + V4L2_MPEG_VIDEO_H264_LEVEL_6_1 = 18, + V4L2_MPEG_VIDEO_H264_LEVEL_6_2 = 19, +}; +#define V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA (V4L2_CID_CODEC_BASE+360) +#define V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA (V4L2_CID_CODEC_BASE+361) +#define V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE (V4L2_CID_CODEC_BASE+362) +enum v4l2_mpeg_video_h264_loop_filter_mode { + V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED = 0, + V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED = 1, + V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY = 2, +}; +#define V4L2_CID_MPEG_VIDEO_H264_PROFILE (V4L2_CID_CODEC_BASE+363) +enum v4l2_mpeg_video_h264_profile { + V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE = 0, + V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE = 1, + V4L2_MPEG_VIDEO_H264_PROFILE_MAIN = 2, + V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED = 3, + V4L2_MPEG_VIDEO_H264_PROFILE_HIGH = 4, + V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10 = 5, + V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422 = 6, + V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE = 7, + V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA = 8, + V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA = 9, + V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA = 10, + V4L2_MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA = 11, + V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE = 12, + V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH = 13, + V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA = 14, + V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH = 15, + V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH = 16, + V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH = 17, +}; +#define V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT (V4L2_CID_CODEC_BASE+364) +#define V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH (V4L2_CID_CODEC_BASE+365) +#define V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE (V4L2_CID_CODEC_BASE+366) +#define V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC (V4L2_CID_CODEC_BASE+367) +enum v4l2_mpeg_video_h264_vui_sar_idc { + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED = 0, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_1x1 = 1, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_12x11 = 2, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_10x11 = 3, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_16x11 = 4, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_40x33 = 5, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_24x11 = 6, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_20x11 = 7, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_32x11 = 8, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_80x33 = 9, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_18x11 = 10, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_15x11 = 11, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_64x33 = 12, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_160x99 = 13, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_4x3 = 14, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_3x2 = 15, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_2x1 = 16, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED = 17, +}; +#define V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING (V4L2_CID_CODEC_BASE+368) +#define V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0 (V4L2_CID_CODEC_BASE+369) +#define V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE (V4L2_CID_CODEC_BASE+370) +enum v4l2_mpeg_video_h264_sei_fp_arrangement_type { + V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_CHECKERBOARD = 0, + V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_COLUMN = 1, + V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_ROW = 2, + V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE = 3, + V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TOP_BOTTOM = 4, + V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TEMPORAL = 5, +}; +#define V4L2_CID_MPEG_VIDEO_H264_FMO (V4L2_CID_CODEC_BASE+371) +#define V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE (V4L2_CID_CODEC_BASE+372) +enum v4l2_mpeg_video_h264_fmo_map_type { + V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES = 0, + V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES = 1, + V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_FOREGROUND_WITH_LEFT_OVER = 2, + V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_BOX_OUT = 3, + V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN = 4, + V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN = 5, + V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_EXPLICIT = 6, +}; +#define V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP (V4L2_CID_CODEC_BASE+373) +#define V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION (V4L2_CID_CODEC_BASE+374) +enum v4l2_mpeg_video_h264_fmo_change_dir { + V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_RIGHT = 0, + V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_LEFT = 1, +}; +#define V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE (V4L2_CID_CODEC_BASE+375) +#define V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH (V4L2_CID_CODEC_BASE+376) +#define V4L2_CID_MPEG_VIDEO_H264_ASO (V4L2_CID_CODEC_BASE+377) +#define V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER (V4L2_CID_CODEC_BASE+378) +#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING (V4L2_CID_CODEC_BASE+379) +#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE (V4L2_CID_CODEC_BASE+380) +enum v4l2_mpeg_video_h264_hierarchical_coding_type { + V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B = 0, + V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P = 1, +}; +#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER (V4L2_CID_CODEC_BASE+381) +#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP (V4L2_CID_CODEC_BASE+382) +#define V4L2_CID_MPEG_VIDEO_H264_CONSTRAINED_INTRA_PREDICTION (V4L2_CID_CODEC_BASE+383) +#define V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET (V4L2_CID_CODEC_BASE+384) +#define V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP (V4L2_CID_CODEC_BASE+385) +#define V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MAX_QP (V4L2_CID_CODEC_BASE+386) +#define V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP (V4L2_CID_CODEC_BASE+387) +#define V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MAX_QP (V4L2_CID_CODEC_BASE+388) +#define V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MIN_QP (V4L2_CID_CODEC_BASE+389) +#define V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MAX_QP (V4L2_CID_CODEC_BASE+390) +#define V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L0_BR (V4L2_CID_CODEC_BASE+391) +#define V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L1_BR (V4L2_CID_CODEC_BASE+392) +#define V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L2_BR (V4L2_CID_CODEC_BASE+393) +#define V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L3_BR (V4L2_CID_CODEC_BASE+394) +#define V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L4_BR (V4L2_CID_CODEC_BASE+395) +#define V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L5_BR (V4L2_CID_CODEC_BASE+396) +#define V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L6_BR (V4L2_CID_CODEC_BASE+397) +#define V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP (V4L2_CID_CODEC_BASE+400) +#define V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP (V4L2_CID_CODEC_BASE+401) +#define V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP (V4L2_CID_CODEC_BASE+402) +#define V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP (V4L2_CID_CODEC_BASE+403) +#define V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP (V4L2_CID_CODEC_BASE+404) +#define V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL (V4L2_CID_CODEC_BASE+405) +enum v4l2_mpeg_video_mpeg4_level { + V4L2_MPEG_VIDEO_MPEG4_LEVEL_0 = 0, + V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B = 1, + V4L2_MPEG_VIDEO_MPEG4_LEVEL_1 = 2, + V4L2_MPEG_VIDEO_MPEG4_LEVEL_2 = 3, + V4L2_MPEG_VIDEO_MPEG4_LEVEL_3 = 4, + V4L2_MPEG_VIDEO_MPEG4_LEVEL_3B = 5, + V4L2_MPEG_VIDEO_MPEG4_LEVEL_4 = 6, + V4L2_MPEG_VIDEO_MPEG4_LEVEL_5 = 7, +}; +#define V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE (V4L2_CID_CODEC_BASE+406) +enum v4l2_mpeg_video_mpeg4_profile { + V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE = 0, + V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE = 1, + V4L2_MPEG_VIDEO_MPEG4_PROFILE_CORE = 2, + V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE_SCALABLE = 3, + V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY = 4, +}; +#define V4L2_CID_MPEG_VIDEO_MPEG4_QPEL (V4L2_CID_CODEC_BASE+407) + +/* Control IDs for VP8 streams + * Although VP8 is not part of MPEG we add these controls to the MPEG class + * as that class is already handling other video compression standards + */ +#define V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS (V4L2_CID_CODEC_BASE+500) +enum v4l2_vp8_num_partitions { + V4L2_CID_MPEG_VIDEO_VPX_1_PARTITION = 0, + V4L2_CID_MPEG_VIDEO_VPX_2_PARTITIONS = 1, + V4L2_CID_MPEG_VIDEO_VPX_4_PARTITIONS = 2, + V4L2_CID_MPEG_VIDEO_VPX_8_PARTITIONS = 3, +}; +#define V4L2_CID_MPEG_VIDEO_VPX_IMD_DISABLE_4X4 (V4L2_CID_CODEC_BASE+501) +#define V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES (V4L2_CID_CODEC_BASE+502) +enum v4l2_vp8_num_ref_frames { + V4L2_CID_MPEG_VIDEO_VPX_1_REF_FRAME = 0, + V4L2_CID_MPEG_VIDEO_VPX_2_REF_FRAME = 1, + V4L2_CID_MPEG_VIDEO_VPX_3_REF_FRAME = 2, +}; +#define V4L2_CID_MPEG_VIDEO_VPX_FILTER_LEVEL (V4L2_CID_CODEC_BASE+503) +#define V4L2_CID_MPEG_VIDEO_VPX_FILTER_SHARPNESS (V4L2_CID_CODEC_BASE+504) +#define V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD (V4L2_CID_CODEC_BASE+505) +#define V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL (V4L2_CID_CODEC_BASE+506) +enum v4l2_vp8_golden_frame_sel { + V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_PREV = 0, + V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_REF_PERIOD = 1, +}; +#define V4L2_CID_MPEG_VIDEO_VPX_MIN_QP (V4L2_CID_CODEC_BASE+507) +#define V4L2_CID_MPEG_VIDEO_VPX_MAX_QP (V4L2_CID_CODEC_BASE+508) +#define V4L2_CID_MPEG_VIDEO_VPX_I_FRAME_QP (V4L2_CID_CODEC_BASE+509) +#define V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP (V4L2_CID_CODEC_BASE+510) + +#define V4L2_CID_MPEG_VIDEO_VP8_PROFILE (V4L2_CID_CODEC_BASE+511) +enum v4l2_mpeg_video_vp8_profile { + V4L2_MPEG_VIDEO_VP8_PROFILE_0 = 0, + V4L2_MPEG_VIDEO_VP8_PROFILE_1 = 1, + V4L2_MPEG_VIDEO_VP8_PROFILE_2 = 2, + V4L2_MPEG_VIDEO_VP8_PROFILE_3 = 3, +}; +/* Deprecated alias for compatibility reasons. */ +#define V4L2_CID_MPEG_VIDEO_VPX_PROFILE V4L2_CID_MPEG_VIDEO_VP8_PROFILE +#define V4L2_CID_MPEG_VIDEO_VP9_PROFILE (V4L2_CID_CODEC_BASE+512) +enum v4l2_mpeg_video_vp9_profile { + V4L2_MPEG_VIDEO_VP9_PROFILE_0 = 0, + V4L2_MPEG_VIDEO_VP9_PROFILE_1 = 1, + V4L2_MPEG_VIDEO_VP9_PROFILE_2 = 2, + V4L2_MPEG_VIDEO_VP9_PROFILE_3 = 3, +}; +#define V4L2_CID_MPEG_VIDEO_VP9_LEVEL (V4L2_CID_CODEC_BASE+513) +enum v4l2_mpeg_video_vp9_level { + V4L2_MPEG_VIDEO_VP9_LEVEL_1_0 = 0, + V4L2_MPEG_VIDEO_VP9_LEVEL_1_1 = 1, + V4L2_MPEG_VIDEO_VP9_LEVEL_2_0 = 2, + V4L2_MPEG_VIDEO_VP9_LEVEL_2_1 = 3, + V4L2_MPEG_VIDEO_VP9_LEVEL_3_0 = 4, + V4L2_MPEG_VIDEO_VP9_LEVEL_3_1 = 5, + V4L2_MPEG_VIDEO_VP9_LEVEL_4_0 = 6, + V4L2_MPEG_VIDEO_VP9_LEVEL_4_1 = 7, + V4L2_MPEG_VIDEO_VP9_LEVEL_5_0 = 8, + V4L2_MPEG_VIDEO_VP9_LEVEL_5_1 = 9, + V4L2_MPEG_VIDEO_VP9_LEVEL_5_2 = 10, + V4L2_MPEG_VIDEO_VP9_LEVEL_6_0 = 11, + V4L2_MPEG_VIDEO_VP9_LEVEL_6_1 = 12, + V4L2_MPEG_VIDEO_VP9_LEVEL_6_2 = 13, +}; + +/* CIDs for HEVC encoding. */ + +#define V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP (V4L2_CID_CODEC_BASE + 600) +#define V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP (V4L2_CID_CODEC_BASE + 601) +#define V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP (V4L2_CID_CODEC_BASE + 602) +#define V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP (V4L2_CID_CODEC_BASE + 603) +#define V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP (V4L2_CID_CODEC_BASE + 604) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIER_QP (V4L2_CID_CODEC_BASE + 605) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE (V4L2_CID_CODEC_BASE + 606) +enum v4l2_mpeg_video_hevc_hier_coding_type { + V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B = 0, + V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P = 1, +}; +#define V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER (V4L2_CID_CODEC_BASE + 607) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_QP (V4L2_CID_CODEC_BASE + 608) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_QP (V4L2_CID_CODEC_BASE + 609) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_QP (V4L2_CID_CODEC_BASE + 610) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_QP (V4L2_CID_CODEC_BASE + 611) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_QP (V4L2_CID_CODEC_BASE + 612) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_QP (V4L2_CID_CODEC_BASE + 613) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L6_QP (V4L2_CID_CODEC_BASE + 614) +#define V4L2_CID_MPEG_VIDEO_HEVC_PROFILE (V4L2_CID_CODEC_BASE + 615) +enum v4l2_mpeg_video_hevc_profile { + V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN = 0, + V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE = 1, + V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10 = 2, +}; +#define V4L2_CID_MPEG_VIDEO_HEVC_LEVEL (V4L2_CID_CODEC_BASE + 616) +enum v4l2_mpeg_video_hevc_level { + V4L2_MPEG_VIDEO_HEVC_LEVEL_1 = 0, + V4L2_MPEG_VIDEO_HEVC_LEVEL_2 = 1, + V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1 = 2, + V4L2_MPEG_VIDEO_HEVC_LEVEL_3 = 3, + V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1 = 4, + V4L2_MPEG_VIDEO_HEVC_LEVEL_4 = 5, + V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1 = 6, + V4L2_MPEG_VIDEO_HEVC_LEVEL_5 = 7, + V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1 = 8, + V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2 = 9, + V4L2_MPEG_VIDEO_HEVC_LEVEL_6 = 10, + V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1 = 11, + V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2 = 12, +}; +#define V4L2_CID_MPEG_VIDEO_HEVC_FRAME_RATE_RESOLUTION (V4L2_CID_CODEC_BASE + 617) +#define V4L2_CID_MPEG_VIDEO_HEVC_TIER (V4L2_CID_CODEC_BASE + 618) +enum v4l2_mpeg_video_hevc_tier { + V4L2_MPEG_VIDEO_HEVC_TIER_MAIN = 0, + V4L2_MPEG_VIDEO_HEVC_TIER_HIGH = 1, +}; +#define V4L2_CID_MPEG_VIDEO_HEVC_MAX_PARTITION_DEPTH (V4L2_CID_CODEC_BASE + 619) +#define V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE (V4L2_CID_CODEC_BASE + 620) +enum v4l2_cid_mpeg_video_hevc_loop_filter_mode { + V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED = 0, + V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_ENABLED = 1, + V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY = 2, +}; +#define V4L2_CID_MPEG_VIDEO_HEVC_LF_BETA_OFFSET_DIV2 (V4L2_CID_CODEC_BASE + 621) +#define V4L2_CID_MPEG_VIDEO_HEVC_LF_TC_OFFSET_DIV2 (V4L2_CID_CODEC_BASE + 622) +#define V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_TYPE (V4L2_CID_CODEC_BASE + 623) +enum v4l2_cid_mpeg_video_hevc_refresh_type { + V4L2_MPEG_VIDEO_HEVC_REFRESH_NONE = 0, + V4L2_MPEG_VIDEO_HEVC_REFRESH_CRA = 1, + V4L2_MPEG_VIDEO_HEVC_REFRESH_IDR = 2, +}; +#define V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_PERIOD (V4L2_CID_CODEC_BASE + 624) +#define V4L2_CID_MPEG_VIDEO_HEVC_LOSSLESS_CU (V4L2_CID_CODEC_BASE + 625) +#define V4L2_CID_MPEG_VIDEO_HEVC_CONST_INTRA_PRED (V4L2_CID_CODEC_BASE + 626) +#define V4L2_CID_MPEG_VIDEO_HEVC_WAVEFRONT (V4L2_CID_CODEC_BASE + 627) +#define V4L2_CID_MPEG_VIDEO_HEVC_GENERAL_PB (V4L2_CID_CODEC_BASE + 628) +#define V4L2_CID_MPEG_VIDEO_HEVC_TEMPORAL_ID (V4L2_CID_CODEC_BASE + 629) +#define V4L2_CID_MPEG_VIDEO_HEVC_STRONG_SMOOTHING (V4L2_CID_CODEC_BASE + 630) +#define V4L2_CID_MPEG_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1 (V4L2_CID_CODEC_BASE + 631) +#define V4L2_CID_MPEG_VIDEO_HEVC_INTRA_PU_SPLIT (V4L2_CID_CODEC_BASE + 632) +#define V4L2_CID_MPEG_VIDEO_HEVC_TMV_PREDICTION (V4L2_CID_CODEC_BASE + 633) +#define V4L2_CID_MPEG_VIDEO_HEVC_WITHOUT_STARTCODE (V4L2_CID_CODEC_BASE + 634) +#define V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD (V4L2_CID_CODEC_BASE + 635) +enum v4l2_cid_mpeg_video_hevc_size_of_length_field { + V4L2_MPEG_VIDEO_HEVC_SIZE_0 = 0, + V4L2_MPEG_VIDEO_HEVC_SIZE_1 = 1, + V4L2_MPEG_VIDEO_HEVC_SIZE_2 = 2, + V4L2_MPEG_VIDEO_HEVC_SIZE_4 = 3, +}; +#define V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_BR (V4L2_CID_CODEC_BASE + 636) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_BR (V4L2_CID_CODEC_BASE + 637) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_BR (V4L2_CID_CODEC_BASE + 638) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_BR (V4L2_CID_CODEC_BASE + 639) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_BR (V4L2_CID_CODEC_BASE + 640) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_BR (V4L2_CID_CODEC_BASE + 641) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L6_BR (V4L2_CID_CODEC_BASE + 642) +#define V4L2_CID_MPEG_VIDEO_REF_NUMBER_FOR_PFRAMES (V4L2_CID_CODEC_BASE + 643) +#define V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR (V4L2_CID_CODEC_BASE + 644) +#define V4L2_CID_MPEG_VIDEO_CONSTANT_QUALITY (V4L2_CID_CODEC_BASE + 645) +#define V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE (V4L2_CID_CODEC_BASE + 646) +enum v4l2_mpeg_video_frame_skip_mode { + V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED = 0, + V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT = 1, + V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT = 2, +}; + +#define V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MIN_QP (V4L2_CID_CODEC_BASE + 647) +#define V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MAX_QP (V4L2_CID_CODEC_BASE + 648) +#define V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MIN_QP (V4L2_CID_CODEC_BASE + 649) +#define V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MAX_QP (V4L2_CID_CODEC_BASE + 650) +#define V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MIN_QP (V4L2_CID_CODEC_BASE + 651) +#define V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MAX_QP (V4L2_CID_CODEC_BASE + 652) + +#define V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY (V4L2_CID_CODEC_BASE + 653) +#define V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE (V4L2_CID_CODEC_BASE + 654) + +#define V4L2_CID_MPEG_VIDEO_AV1_PROFILE (V4L2_CID_CODEC_BASE + 655) +/** + * enum v4l2_mpeg_video_av1_profile - AV1 profiles + * + * @V4L2_MPEG_VIDEO_AV1_PROFILE_MAIN: compliant decoders must be able to decode + * streams with seq_profile equal to 0. + * @V4L2_MPEG_VIDEO_AV1_PROFILE_HIGH: compliant decoders must be able to decode + * streams with seq_profile equal less than or equal to 1. + * @V4L2_MPEG_VIDEO_AV1_PROFILE_PROFESSIONAL: compliant decoders must be able to + * decode streams with seq_profile less than or equal to 2. + * + * Conveys the highest profile a decoder can work with. + */ +enum v4l2_mpeg_video_av1_profile { + V4L2_MPEG_VIDEO_AV1_PROFILE_MAIN = 0, + V4L2_MPEG_VIDEO_AV1_PROFILE_HIGH = 1, + V4L2_MPEG_VIDEO_AV1_PROFILE_PROFESSIONAL = 2, +}; + +#define V4L2_CID_MPEG_VIDEO_AV1_LEVEL (V4L2_CID_CODEC_BASE + 656) +/** + * enum v4l2_mpeg_video_av1_level - AV1 levels + * + * @V4L2_MPEG_VIDEO_AV1_LEVEL_2_0: Level 2.0. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_2_1: Level 2.1. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_2_2: Level 2.2. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_2_3: Level 2.3. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_3_0: Level 3.0. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_3_1: Level 3.1. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_3_2: Level 3.2. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_3_3: Level 3.3. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_4_0: Level 4.0. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_4_1: Level 4.1. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_4_2: Level 4.2. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_4_3: Level 4.3. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_5_0: Level 5.0. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_5_1: Level 5.1. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_5_2: Level 5.2. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_5_3: Level 5.3. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_6_0: Level 6.0. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_6_1: Level 6.1. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_6_2: Level 6.2. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_6_3: Level 6.3. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_7_0: Level 7.0. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_7_1: Level 7.1. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_7_2: Level 7.2. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_7_3: Level 7.3. + * + * Conveys the highest level a decoder can work with. + */ +enum v4l2_mpeg_video_av1_level { + V4L2_MPEG_VIDEO_AV1_LEVEL_2_0 = 0, + V4L2_MPEG_VIDEO_AV1_LEVEL_2_1 = 1, + V4L2_MPEG_VIDEO_AV1_LEVEL_2_2 = 2, + V4L2_MPEG_VIDEO_AV1_LEVEL_2_3 = 3, + + V4L2_MPEG_VIDEO_AV1_LEVEL_3_0 = 4, + V4L2_MPEG_VIDEO_AV1_LEVEL_3_1 = 5, + V4L2_MPEG_VIDEO_AV1_LEVEL_3_2 = 6, + V4L2_MPEG_VIDEO_AV1_LEVEL_3_3 = 7, + + V4L2_MPEG_VIDEO_AV1_LEVEL_4_0 = 8, + V4L2_MPEG_VIDEO_AV1_LEVEL_4_1 = 9, + V4L2_MPEG_VIDEO_AV1_LEVEL_4_2 = 10, + V4L2_MPEG_VIDEO_AV1_LEVEL_4_3 = 11, + + V4L2_MPEG_VIDEO_AV1_LEVEL_5_0 = 12, + V4L2_MPEG_VIDEO_AV1_LEVEL_5_1 = 13, + V4L2_MPEG_VIDEO_AV1_LEVEL_5_2 = 14, + V4L2_MPEG_VIDEO_AV1_LEVEL_5_3 = 15, + + V4L2_MPEG_VIDEO_AV1_LEVEL_6_0 = 16, + V4L2_MPEG_VIDEO_AV1_LEVEL_6_1 = 17, + V4L2_MPEG_VIDEO_AV1_LEVEL_6_2 = 18, + V4L2_MPEG_VIDEO_AV1_LEVEL_6_3 = 19, + + V4L2_MPEG_VIDEO_AV1_LEVEL_7_0 = 20, + V4L2_MPEG_VIDEO_AV1_LEVEL_7_1 = 21, + V4L2_MPEG_VIDEO_AV1_LEVEL_7_2 = 22, + V4L2_MPEG_VIDEO_AV1_LEVEL_7_3 = 23 +}; + +#define V4L2_CID_MPEG_VIDEO_AVERAGE_QP (V4L2_CID_CODEC_BASE + 657) + +/* MPEG-class control IDs specific to the CX2341x driver as defined by V4L2 */ +#define V4L2_CID_CODEC_CX2341X_BASE (V4L2_CTRL_CLASS_CODEC | 0x1000) +#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE (V4L2_CID_CODEC_CX2341X_BASE+0) +enum v4l2_mpeg_cx2341x_video_spatial_filter_mode { + V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL = 0, + V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO = 1, +}; +#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER (V4L2_CID_CODEC_CX2341X_BASE+1) +#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE (V4L2_CID_CODEC_CX2341X_BASE+2) +enum v4l2_mpeg_cx2341x_video_luma_spatial_filter_type { + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF = 0, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR = 1, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_VERT = 2, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_HV_SEPARABLE = 3, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE = 4, +}; +#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE (V4L2_CID_CODEC_CX2341X_BASE+3) +enum v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type { + V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF = 0, + V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR = 1, +}; +#define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE (V4L2_CID_CODEC_CX2341X_BASE+4) +enum v4l2_mpeg_cx2341x_video_temporal_filter_mode { + V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL = 0, + V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO = 1, +}; +#define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER (V4L2_CID_CODEC_CX2341X_BASE+5) +#define V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE (V4L2_CID_CODEC_CX2341X_BASE+6) +enum v4l2_mpeg_cx2341x_video_median_filter_type { + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF = 0, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR = 1, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_VERT = 2, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR_VERT = 3, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG = 4, +}; +#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM (V4L2_CID_CODEC_CX2341X_BASE+7) +#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP (V4L2_CID_CODEC_CX2341X_BASE+8) +#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM (V4L2_CID_CODEC_CX2341X_BASE+9) +#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP (V4L2_CID_CODEC_CX2341X_BASE+10) +#define V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS (V4L2_CID_CODEC_CX2341X_BASE+11) + +/* MPEG-class control IDs specific to the Samsung MFC 5.1 driver as defined by V4L2 */ +#define V4L2_CID_CODEC_MFC51_BASE (V4L2_CTRL_CLASS_CODEC | 0x1100) + +#define V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY (V4L2_CID_CODEC_MFC51_BASE+0) +#define V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE (V4L2_CID_CODEC_MFC51_BASE+1) +#define V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE (V4L2_CID_CODEC_MFC51_BASE+2) +enum v4l2_mpeg_mfc51_video_frame_skip_mode { + V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED = 0, + V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT = 1, + V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT = 2, +}; +#define V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE (V4L2_CID_CODEC_MFC51_BASE+3) +enum v4l2_mpeg_mfc51_video_force_frame_type { + V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_DISABLED = 0, + V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_I_FRAME = 1, + V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_NOT_CODED = 2, +}; +#define V4L2_CID_MPEG_MFC51_VIDEO_PADDING (V4L2_CID_CODEC_MFC51_BASE+4) +#define V4L2_CID_MPEG_MFC51_VIDEO_PADDING_YUV (V4L2_CID_CODEC_MFC51_BASE+5) +#define V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT (V4L2_CID_CODEC_MFC51_BASE+6) +#define V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF (V4L2_CID_CODEC_MFC51_BASE+7) +#define V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_ACTIVITY (V4L2_CID_CODEC_MFC51_BASE+50) +#define V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK (V4L2_CID_CODEC_MFC51_BASE+51) +#define V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_SMOOTH (V4L2_CID_CODEC_MFC51_BASE+52) +#define V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_STATIC (V4L2_CID_CODEC_MFC51_BASE+53) +#define V4L2_CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P (V4L2_CID_CODEC_MFC51_BASE+54) + +/* Camera class control IDs */ + +#define V4L2_CID_CAMERA_CLASS_BASE (V4L2_CTRL_CLASS_CAMERA | 0x900) +#define V4L2_CID_CAMERA_CLASS (V4L2_CTRL_CLASS_CAMERA | 1) + +#define V4L2_CID_EXPOSURE_AUTO (V4L2_CID_CAMERA_CLASS_BASE+1) +enum v4l2_exposure_auto_type { + V4L2_EXPOSURE_AUTO = 0, + V4L2_EXPOSURE_MANUAL = 1, + V4L2_EXPOSURE_SHUTTER_PRIORITY = 2, + V4L2_EXPOSURE_APERTURE_PRIORITY = 3 +}; +#define V4L2_CID_EXPOSURE_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+2) +#define V4L2_CID_EXPOSURE_AUTO_PRIORITY (V4L2_CID_CAMERA_CLASS_BASE+3) + +#define V4L2_CID_PAN_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+4) +#define V4L2_CID_TILT_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+5) +#define V4L2_CID_PAN_RESET (V4L2_CID_CAMERA_CLASS_BASE+6) +#define V4L2_CID_TILT_RESET (V4L2_CID_CAMERA_CLASS_BASE+7) + +#define V4L2_CID_PAN_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+8) +#define V4L2_CID_TILT_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+9) + +#define V4L2_CID_FOCUS_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+10) +#define V4L2_CID_FOCUS_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+11) +#define V4L2_CID_FOCUS_AUTO (V4L2_CID_CAMERA_CLASS_BASE+12) + +#define V4L2_CID_ZOOM_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+13) +#define V4L2_CID_ZOOM_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+14) +#define V4L2_CID_ZOOM_CONTINUOUS (V4L2_CID_CAMERA_CLASS_BASE+15) + +#define V4L2_CID_PRIVACY (V4L2_CID_CAMERA_CLASS_BASE+16) + +#define V4L2_CID_IRIS_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+17) +#define V4L2_CID_IRIS_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+18) + +#define V4L2_CID_AUTO_EXPOSURE_BIAS (V4L2_CID_CAMERA_CLASS_BASE+19) + +#define V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE (V4L2_CID_CAMERA_CLASS_BASE+20) +enum v4l2_auto_n_preset_white_balance { + V4L2_WHITE_BALANCE_MANUAL = 0, + V4L2_WHITE_BALANCE_AUTO = 1, + V4L2_WHITE_BALANCE_INCANDESCENT = 2, + V4L2_WHITE_BALANCE_FLUORESCENT = 3, + V4L2_WHITE_BALANCE_FLUORESCENT_H = 4, + V4L2_WHITE_BALANCE_HORIZON = 5, + V4L2_WHITE_BALANCE_DAYLIGHT = 6, + V4L2_WHITE_BALANCE_FLASH = 7, + V4L2_WHITE_BALANCE_CLOUDY = 8, + V4L2_WHITE_BALANCE_SHADE = 9, +}; + +#define V4L2_CID_WIDE_DYNAMIC_RANGE (V4L2_CID_CAMERA_CLASS_BASE+21) +#define V4L2_CID_IMAGE_STABILIZATION (V4L2_CID_CAMERA_CLASS_BASE+22) + +#define V4L2_CID_ISO_SENSITIVITY (V4L2_CID_CAMERA_CLASS_BASE+23) +#define V4L2_CID_ISO_SENSITIVITY_AUTO (V4L2_CID_CAMERA_CLASS_BASE+24) +enum v4l2_iso_sensitivity_auto_type { + V4L2_ISO_SENSITIVITY_MANUAL = 0, + V4L2_ISO_SENSITIVITY_AUTO = 1, +}; + +#define V4L2_CID_EXPOSURE_METERING (V4L2_CID_CAMERA_CLASS_BASE+25) +enum v4l2_exposure_metering { + V4L2_EXPOSURE_METERING_AVERAGE = 0, + V4L2_EXPOSURE_METERING_CENTER_WEIGHTED = 1, + V4L2_EXPOSURE_METERING_SPOT = 2, + V4L2_EXPOSURE_METERING_MATRIX = 3, +}; + +#define V4L2_CID_SCENE_MODE (V4L2_CID_CAMERA_CLASS_BASE+26) +enum v4l2_scene_mode { + V4L2_SCENE_MODE_NONE = 0, + V4L2_SCENE_MODE_BACKLIGHT = 1, + V4L2_SCENE_MODE_BEACH_SNOW = 2, + V4L2_SCENE_MODE_CANDLE_LIGHT = 3, + V4L2_SCENE_MODE_DAWN_DUSK = 4, + V4L2_SCENE_MODE_FALL_COLORS = 5, + V4L2_SCENE_MODE_FIREWORKS = 6, + V4L2_SCENE_MODE_LANDSCAPE = 7, + V4L2_SCENE_MODE_NIGHT = 8, + V4L2_SCENE_MODE_PARTY_INDOOR = 9, + V4L2_SCENE_MODE_PORTRAIT = 10, + V4L2_SCENE_MODE_SPORTS = 11, + V4L2_SCENE_MODE_SUNSET = 12, + V4L2_SCENE_MODE_TEXT = 13, +}; + +#define V4L2_CID_3A_LOCK (V4L2_CID_CAMERA_CLASS_BASE+27) +#define V4L2_LOCK_EXPOSURE (1 << 0) +#define V4L2_LOCK_WHITE_BALANCE (1 << 1) +#define V4L2_LOCK_FOCUS (1 << 2) + +#define V4L2_CID_AUTO_FOCUS_START (V4L2_CID_CAMERA_CLASS_BASE+28) +#define V4L2_CID_AUTO_FOCUS_STOP (V4L2_CID_CAMERA_CLASS_BASE+29) +#define V4L2_CID_AUTO_FOCUS_STATUS (V4L2_CID_CAMERA_CLASS_BASE+30) +#define V4L2_AUTO_FOCUS_STATUS_IDLE (0 << 0) +#define V4L2_AUTO_FOCUS_STATUS_BUSY (1 << 0) +#define V4L2_AUTO_FOCUS_STATUS_REACHED (1 << 1) +#define V4L2_AUTO_FOCUS_STATUS_FAILED (1 << 2) + +#define V4L2_CID_AUTO_FOCUS_RANGE (V4L2_CID_CAMERA_CLASS_BASE+31) +enum v4l2_auto_focus_range { + V4L2_AUTO_FOCUS_RANGE_AUTO = 0, + V4L2_AUTO_FOCUS_RANGE_NORMAL = 1, + V4L2_AUTO_FOCUS_RANGE_MACRO = 2, + V4L2_AUTO_FOCUS_RANGE_INFINITY = 3, +}; + +#define V4L2_CID_PAN_SPEED (V4L2_CID_CAMERA_CLASS_BASE+32) +#define V4L2_CID_TILT_SPEED (V4L2_CID_CAMERA_CLASS_BASE+33) + +#define V4L2_CID_CAMERA_ORIENTATION (V4L2_CID_CAMERA_CLASS_BASE+34) +#define V4L2_CAMERA_ORIENTATION_FRONT 0 +#define V4L2_CAMERA_ORIENTATION_BACK 1 +#define V4L2_CAMERA_ORIENTATION_EXTERNAL 2 + +#define V4L2_CID_CAMERA_SENSOR_ROTATION (V4L2_CID_CAMERA_CLASS_BASE+35) + +#define V4L2_CID_HDR_SENSOR_MODE (V4L2_CID_CAMERA_CLASS_BASE+36) + +/* FM Modulator class control IDs */ + +#define V4L2_CID_FM_TX_CLASS_BASE (V4L2_CTRL_CLASS_FM_TX | 0x900) +#define V4L2_CID_FM_TX_CLASS (V4L2_CTRL_CLASS_FM_TX | 1) + +#define V4L2_CID_RDS_TX_DEVIATION (V4L2_CID_FM_TX_CLASS_BASE + 1) +#define V4L2_CID_RDS_TX_PI (V4L2_CID_FM_TX_CLASS_BASE + 2) +#define V4L2_CID_RDS_TX_PTY (V4L2_CID_FM_TX_CLASS_BASE + 3) +#define V4L2_CID_RDS_TX_PS_NAME (V4L2_CID_FM_TX_CLASS_BASE + 5) +#define V4L2_CID_RDS_TX_RADIO_TEXT (V4L2_CID_FM_TX_CLASS_BASE + 6) +#define V4L2_CID_RDS_TX_MONO_STEREO (V4L2_CID_FM_TX_CLASS_BASE + 7) +#define V4L2_CID_RDS_TX_ARTIFICIAL_HEAD (V4L2_CID_FM_TX_CLASS_BASE + 8) +#define V4L2_CID_RDS_TX_COMPRESSED (V4L2_CID_FM_TX_CLASS_BASE + 9) +#define V4L2_CID_RDS_TX_DYNAMIC_PTY (V4L2_CID_FM_TX_CLASS_BASE + 10) +#define V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT (V4L2_CID_FM_TX_CLASS_BASE + 11) +#define V4L2_CID_RDS_TX_TRAFFIC_PROGRAM (V4L2_CID_FM_TX_CLASS_BASE + 12) +#define V4L2_CID_RDS_TX_MUSIC_SPEECH (V4L2_CID_FM_TX_CLASS_BASE + 13) +#define V4L2_CID_RDS_TX_ALT_FREQS_ENABLE (V4L2_CID_FM_TX_CLASS_BASE + 14) +#define V4L2_CID_RDS_TX_ALT_FREQS (V4L2_CID_FM_TX_CLASS_BASE + 15) + +#define V4L2_CID_AUDIO_LIMITER_ENABLED (V4L2_CID_FM_TX_CLASS_BASE + 64) +#define V4L2_CID_AUDIO_LIMITER_RELEASE_TIME (V4L2_CID_FM_TX_CLASS_BASE + 65) +#define V4L2_CID_AUDIO_LIMITER_DEVIATION (V4L2_CID_FM_TX_CLASS_BASE + 66) + +#define V4L2_CID_AUDIO_COMPRESSION_ENABLED (V4L2_CID_FM_TX_CLASS_BASE + 80) +#define V4L2_CID_AUDIO_COMPRESSION_GAIN (V4L2_CID_FM_TX_CLASS_BASE + 81) +#define V4L2_CID_AUDIO_COMPRESSION_THRESHOLD (V4L2_CID_FM_TX_CLASS_BASE + 82) +#define V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME (V4L2_CID_FM_TX_CLASS_BASE + 83) +#define V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME (V4L2_CID_FM_TX_CLASS_BASE + 84) + +#define V4L2_CID_PILOT_TONE_ENABLED (V4L2_CID_FM_TX_CLASS_BASE + 96) +#define V4L2_CID_PILOT_TONE_DEVIATION (V4L2_CID_FM_TX_CLASS_BASE + 97) +#define V4L2_CID_PILOT_TONE_FREQUENCY (V4L2_CID_FM_TX_CLASS_BASE + 98) + +#define V4L2_CID_TUNE_PREEMPHASIS (V4L2_CID_FM_TX_CLASS_BASE + 112) +enum v4l2_preemphasis { + V4L2_PREEMPHASIS_DISABLED = 0, + V4L2_PREEMPHASIS_50_uS = 1, + V4L2_PREEMPHASIS_75_uS = 2, +}; +#define V4L2_CID_TUNE_POWER_LEVEL (V4L2_CID_FM_TX_CLASS_BASE + 113) +#define V4L2_CID_TUNE_ANTENNA_CAPACITOR (V4L2_CID_FM_TX_CLASS_BASE + 114) + + +/* Flash and privacy (indicator) light controls */ + +#define V4L2_CID_FLASH_CLASS_BASE (V4L2_CTRL_CLASS_FLASH | 0x900) +#define V4L2_CID_FLASH_CLASS (V4L2_CTRL_CLASS_FLASH | 1) + +#define V4L2_CID_FLASH_LED_MODE (V4L2_CID_FLASH_CLASS_BASE + 1) +enum v4l2_flash_led_mode { + V4L2_FLASH_LED_MODE_NONE, + V4L2_FLASH_LED_MODE_FLASH, + V4L2_FLASH_LED_MODE_TORCH, +}; + +#define V4L2_CID_FLASH_STROBE_SOURCE (V4L2_CID_FLASH_CLASS_BASE + 2) +enum v4l2_flash_strobe_source { + V4L2_FLASH_STROBE_SOURCE_SOFTWARE, + V4L2_FLASH_STROBE_SOURCE_EXTERNAL, +}; + +#define V4L2_CID_FLASH_STROBE (V4L2_CID_FLASH_CLASS_BASE + 3) +#define V4L2_CID_FLASH_STROBE_STOP (V4L2_CID_FLASH_CLASS_BASE + 4) +#define V4L2_CID_FLASH_STROBE_STATUS (V4L2_CID_FLASH_CLASS_BASE + 5) + +#define V4L2_CID_FLASH_TIMEOUT (V4L2_CID_FLASH_CLASS_BASE + 6) +#define V4L2_CID_FLASH_INTENSITY (V4L2_CID_FLASH_CLASS_BASE + 7) +#define V4L2_CID_FLASH_TORCH_INTENSITY (V4L2_CID_FLASH_CLASS_BASE + 8) +#define V4L2_CID_FLASH_INDICATOR_INTENSITY (V4L2_CID_FLASH_CLASS_BASE + 9) + +#define V4L2_CID_FLASH_FAULT (V4L2_CID_FLASH_CLASS_BASE + 10) +#define V4L2_FLASH_FAULT_OVER_VOLTAGE (1 << 0) +#define V4L2_FLASH_FAULT_TIMEOUT (1 << 1) +#define V4L2_FLASH_FAULT_OVER_TEMPERATURE (1 << 2) +#define V4L2_FLASH_FAULT_SHORT_CIRCUIT (1 << 3) +#define V4L2_FLASH_FAULT_OVER_CURRENT (1 << 4) +#define V4L2_FLASH_FAULT_INDICATOR (1 << 5) +#define V4L2_FLASH_FAULT_UNDER_VOLTAGE (1 << 6) +#define V4L2_FLASH_FAULT_INPUT_VOLTAGE (1 << 7) +#define V4L2_FLASH_FAULT_LED_OVER_TEMPERATURE (1 << 8) + +#define V4L2_CID_FLASH_CHARGE (V4L2_CID_FLASH_CLASS_BASE + 11) +#define V4L2_CID_FLASH_READY (V4L2_CID_FLASH_CLASS_BASE + 12) + + +/* JPEG-class control IDs */ + +#define V4L2_CID_JPEG_CLASS_BASE (V4L2_CTRL_CLASS_JPEG | 0x900) +#define V4L2_CID_JPEG_CLASS (V4L2_CTRL_CLASS_JPEG | 1) + +#define V4L2_CID_JPEG_CHROMA_SUBSAMPLING (V4L2_CID_JPEG_CLASS_BASE + 1) +enum v4l2_jpeg_chroma_subsampling { + V4L2_JPEG_CHROMA_SUBSAMPLING_444 = 0, + V4L2_JPEG_CHROMA_SUBSAMPLING_422 = 1, + V4L2_JPEG_CHROMA_SUBSAMPLING_420 = 2, + V4L2_JPEG_CHROMA_SUBSAMPLING_411 = 3, + V4L2_JPEG_CHROMA_SUBSAMPLING_410 = 4, + V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY = 5, +}; +#define V4L2_CID_JPEG_RESTART_INTERVAL (V4L2_CID_JPEG_CLASS_BASE + 2) +#define V4L2_CID_JPEG_COMPRESSION_QUALITY (V4L2_CID_JPEG_CLASS_BASE + 3) + +#define V4L2_CID_JPEG_ACTIVE_MARKER (V4L2_CID_JPEG_CLASS_BASE + 4) +#define V4L2_JPEG_ACTIVE_MARKER_APP0 (1 << 0) +#define V4L2_JPEG_ACTIVE_MARKER_APP1 (1 << 1) +#define V4L2_JPEG_ACTIVE_MARKER_COM (1 << 16) +#define V4L2_JPEG_ACTIVE_MARKER_DQT (1 << 17) +#define V4L2_JPEG_ACTIVE_MARKER_DHT (1 << 18) + + +/* Image source controls */ +#define V4L2_CID_IMAGE_SOURCE_CLASS_BASE (V4L2_CTRL_CLASS_IMAGE_SOURCE | 0x900) +#define V4L2_CID_IMAGE_SOURCE_CLASS (V4L2_CTRL_CLASS_IMAGE_SOURCE | 1) + +#define V4L2_CID_VBLANK (V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 1) +#define V4L2_CID_HBLANK (V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 2) +#define V4L2_CID_ANALOGUE_GAIN (V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 3) +#define V4L2_CID_TEST_PATTERN_RED (V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 4) +#define V4L2_CID_TEST_PATTERN_GREENR (V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 5) +#define V4L2_CID_TEST_PATTERN_BLUE (V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 6) +#define V4L2_CID_TEST_PATTERN_GREENB (V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 7) +#define V4L2_CID_UNIT_CELL_SIZE (V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 8) +#define V4L2_CID_NOTIFY_GAINS (V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 9) + + +/* Image processing controls */ + +#define V4L2_CID_IMAGE_PROC_CLASS_BASE (V4L2_CTRL_CLASS_IMAGE_PROC | 0x900) +#define V4L2_CID_IMAGE_PROC_CLASS (V4L2_CTRL_CLASS_IMAGE_PROC | 1) + +#define V4L2_CID_LINK_FREQ (V4L2_CID_IMAGE_PROC_CLASS_BASE + 1) +#define V4L2_CID_PIXEL_RATE (V4L2_CID_IMAGE_PROC_CLASS_BASE + 2) +#define V4L2_CID_TEST_PATTERN (V4L2_CID_IMAGE_PROC_CLASS_BASE + 3) +#define V4L2_CID_DEINTERLACING_MODE (V4L2_CID_IMAGE_PROC_CLASS_BASE + 4) +#define V4L2_CID_DIGITAL_GAIN (V4L2_CID_IMAGE_PROC_CLASS_BASE + 5) + +/* DV-class control IDs defined by V4L2 */ +#define V4L2_CID_DV_CLASS_BASE (V4L2_CTRL_CLASS_DV | 0x900) +#define V4L2_CID_DV_CLASS (V4L2_CTRL_CLASS_DV | 1) + +#define V4L2_CID_DV_TX_HOTPLUG (V4L2_CID_DV_CLASS_BASE + 1) +#define V4L2_CID_DV_TX_RXSENSE (V4L2_CID_DV_CLASS_BASE + 2) +#define V4L2_CID_DV_TX_EDID_PRESENT (V4L2_CID_DV_CLASS_BASE + 3) +#define V4L2_CID_DV_TX_MODE (V4L2_CID_DV_CLASS_BASE + 4) +enum v4l2_dv_tx_mode { + V4L2_DV_TX_MODE_DVI_D = 0, + V4L2_DV_TX_MODE_HDMI = 1, +}; +#define V4L2_CID_DV_TX_RGB_RANGE (V4L2_CID_DV_CLASS_BASE + 5) +enum v4l2_dv_rgb_range { + V4L2_DV_RGB_RANGE_AUTO = 0, + V4L2_DV_RGB_RANGE_LIMITED = 1, + V4L2_DV_RGB_RANGE_FULL = 2, +}; + +#define V4L2_CID_DV_TX_IT_CONTENT_TYPE (V4L2_CID_DV_CLASS_BASE + 6) +enum v4l2_dv_it_content_type { + V4L2_DV_IT_CONTENT_TYPE_GRAPHICS = 0, + V4L2_DV_IT_CONTENT_TYPE_PHOTO = 1, + V4L2_DV_IT_CONTENT_TYPE_CINEMA = 2, + V4L2_DV_IT_CONTENT_TYPE_GAME = 3, + V4L2_DV_IT_CONTENT_TYPE_NO_ITC = 4, +}; + +#define V4L2_CID_DV_RX_POWER_PRESENT (V4L2_CID_DV_CLASS_BASE + 100) +#define V4L2_CID_DV_RX_RGB_RANGE (V4L2_CID_DV_CLASS_BASE + 101) +#define V4L2_CID_DV_RX_IT_CONTENT_TYPE (V4L2_CID_DV_CLASS_BASE + 102) + +#define V4L2_CID_FM_RX_CLASS_BASE (V4L2_CTRL_CLASS_FM_RX | 0x900) +#define V4L2_CID_FM_RX_CLASS (V4L2_CTRL_CLASS_FM_RX | 1) + +#define V4L2_CID_TUNE_DEEMPHASIS (V4L2_CID_FM_RX_CLASS_BASE + 1) +enum v4l2_deemphasis { + V4L2_DEEMPHASIS_DISABLED = V4L2_PREEMPHASIS_DISABLED, + V4L2_DEEMPHASIS_50_uS = V4L2_PREEMPHASIS_50_uS, + V4L2_DEEMPHASIS_75_uS = V4L2_PREEMPHASIS_75_uS, +}; + +#define V4L2_CID_RDS_RECEPTION (V4L2_CID_FM_RX_CLASS_BASE + 2) +#define V4L2_CID_RDS_RX_PTY (V4L2_CID_FM_RX_CLASS_BASE + 3) +#define V4L2_CID_RDS_RX_PS_NAME (V4L2_CID_FM_RX_CLASS_BASE + 4) +#define V4L2_CID_RDS_RX_RADIO_TEXT (V4L2_CID_FM_RX_CLASS_BASE + 5) +#define V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT (V4L2_CID_FM_RX_CLASS_BASE + 6) +#define V4L2_CID_RDS_RX_TRAFFIC_PROGRAM (V4L2_CID_FM_RX_CLASS_BASE + 7) +#define V4L2_CID_RDS_RX_MUSIC_SPEECH (V4L2_CID_FM_RX_CLASS_BASE + 8) + +#define V4L2_CID_RF_TUNER_CLASS_BASE (V4L2_CTRL_CLASS_RF_TUNER | 0x900) +#define V4L2_CID_RF_TUNER_CLASS (V4L2_CTRL_CLASS_RF_TUNER | 1) + +#define V4L2_CID_RF_TUNER_BANDWIDTH_AUTO (V4L2_CID_RF_TUNER_CLASS_BASE + 11) +#define V4L2_CID_RF_TUNER_BANDWIDTH (V4L2_CID_RF_TUNER_CLASS_BASE + 12) +#define V4L2_CID_RF_TUNER_RF_GAIN (V4L2_CID_RF_TUNER_CLASS_BASE + 32) +#define V4L2_CID_RF_TUNER_LNA_GAIN_AUTO (V4L2_CID_RF_TUNER_CLASS_BASE + 41) +#define V4L2_CID_RF_TUNER_LNA_GAIN (V4L2_CID_RF_TUNER_CLASS_BASE + 42) +#define V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO (V4L2_CID_RF_TUNER_CLASS_BASE + 51) +#define V4L2_CID_RF_TUNER_MIXER_GAIN (V4L2_CID_RF_TUNER_CLASS_BASE + 52) +#define V4L2_CID_RF_TUNER_IF_GAIN_AUTO (V4L2_CID_RF_TUNER_CLASS_BASE + 61) +#define V4L2_CID_RF_TUNER_IF_GAIN (V4L2_CID_RF_TUNER_CLASS_BASE + 62) +#define V4L2_CID_RF_TUNER_PLL_LOCK (V4L2_CID_RF_TUNER_CLASS_BASE + 91) + + +/* Detection-class control IDs defined by V4L2 */ +#define V4L2_CID_DETECT_CLASS_BASE (V4L2_CTRL_CLASS_DETECT | 0x900) +#define V4L2_CID_DETECT_CLASS (V4L2_CTRL_CLASS_DETECT | 1) + +#define V4L2_CID_DETECT_MD_MODE (V4L2_CID_DETECT_CLASS_BASE + 1) +enum v4l2_detect_md_mode { + V4L2_DETECT_MD_MODE_DISABLED = 0, + V4L2_DETECT_MD_MODE_GLOBAL = 1, + V4L2_DETECT_MD_MODE_THRESHOLD_GRID = 2, + V4L2_DETECT_MD_MODE_REGION_GRID = 3, +}; +#define V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD (V4L2_CID_DETECT_CLASS_BASE + 2) +#define V4L2_CID_DETECT_MD_THRESHOLD_GRID (V4L2_CID_DETECT_CLASS_BASE + 3) +#define V4L2_CID_DETECT_MD_REGION_GRID (V4L2_CID_DETECT_CLASS_BASE + 4) + + +/* Stateless CODECs controls */ +#define V4L2_CID_CODEC_STATELESS_BASE (V4L2_CTRL_CLASS_CODEC_STATELESS | 0x900) +#define V4L2_CID_CODEC_STATELESS_CLASS (V4L2_CTRL_CLASS_CODEC_STATELESS | 1) + +#define V4L2_CID_STATELESS_H264_DECODE_MODE (V4L2_CID_CODEC_STATELESS_BASE + 0) +/** + * enum v4l2_stateless_h264_decode_mode - Decoding mode + * + * @V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED: indicates that decoding + * is performed one slice at a time. In this mode, + * V4L2_CID_STATELESS_H264_SLICE_PARAMS must contain the parsed slice + * parameters and the OUTPUT buffer must contain a single slice. + * V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF feature is used + * in order to support multislice frames. + * @V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED: indicates that + * decoding is performed per frame. The OUTPUT buffer must contain + * all slices and also both fields. This mode is typically supported + * by device drivers that are able to parse the slice(s) header(s) + * in hardware. When this mode is selected, + * V4L2_CID_STATELESS_H264_SLICE_PARAMS is not used. + */ +enum v4l2_stateless_h264_decode_mode { + V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED, + V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED, +}; + +#define V4L2_CID_STATELESS_H264_START_CODE (V4L2_CID_CODEC_STATELESS_BASE + 1) +/** + * enum v4l2_stateless_h264_start_code - Start code + * + * @V4L2_STATELESS_H264_START_CODE_NONE: slices are passed + * to the driver without any start code. + * @V4L2_STATELESS_H264_START_CODE_ANNEX_B: slices are passed + * to the driver with an Annex B start code prefix + * (legal start codes can be 3-bytes 0x000001 or 4-bytes 0x00000001). + * This mode is typically supported by device drivers that parse + * the start code in hardware. + */ +enum v4l2_stateless_h264_start_code { + V4L2_STATELESS_H264_START_CODE_NONE, + V4L2_STATELESS_H264_START_CODE_ANNEX_B, +}; + +#define V4L2_H264_SPS_CONSTRAINT_SET0_FLAG 0x01 +#define V4L2_H264_SPS_CONSTRAINT_SET1_FLAG 0x02 +#define V4L2_H264_SPS_CONSTRAINT_SET2_FLAG 0x04 +#define V4L2_H264_SPS_CONSTRAINT_SET3_FLAG 0x08 +#define V4L2_H264_SPS_CONSTRAINT_SET4_FLAG 0x10 +#define V4L2_H264_SPS_CONSTRAINT_SET5_FLAG 0x20 + +#define V4L2_H264_SPS_FLAG_SEPARATE_COLOUR_PLANE 0x01 +#define V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS 0x02 +#define V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO 0x04 +#define V4L2_H264_SPS_FLAG_GAPS_IN_FRAME_NUM_VALUE_ALLOWED 0x08 +#define V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY 0x10 +#define V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD 0x20 +#define V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE 0x40 + +#define V4L2_H264_SPS_HAS_CHROMA_FORMAT(sps) \ + ((sps)->profile_idc == 100 || (sps)->profile_idc == 110 || \ + (sps)->profile_idc == 122 || (sps)->profile_idc == 244 || \ + (sps)->profile_idc == 44 || (sps)->profile_idc == 83 || \ + (sps)->profile_idc == 86 || (sps)->profile_idc == 118 || \ + (sps)->profile_idc == 128 || (sps)->profile_idc == 138 || \ + (sps)->profile_idc == 139 || (sps)->profile_idc == 134 || \ + (sps)->profile_idc == 135) + +#define V4L2_CID_STATELESS_H264_SPS (V4L2_CID_CODEC_STATELESS_BASE + 2) +/** + * struct v4l2_ctrl_h264_sps - H264 sequence parameter set + * + * All the members on this sequence parameter set structure match the + * sequence parameter set syntax as specified by the H264 specification. + * + * @profile_idc: see H264 specification. + * @constraint_set_flags: see H264 specification. + * @level_idc: see H264 specification. + * @seq_parameter_set_id: see H264 specification. + * @chroma_format_idc: see H264 specification. + * @bit_depth_luma_minus8: see H264 specification. + * @bit_depth_chroma_minus8: see H264 specification. + * @log2_max_frame_num_minus4: see H264 specification. + * @pic_order_cnt_type: see H264 specification. + * @log2_max_pic_order_cnt_lsb_minus4: see H264 specification. + * @max_num_ref_frames: see H264 specification. + * @num_ref_frames_in_pic_order_cnt_cycle: see H264 specification. + * @offset_for_ref_frame: see H264 specification. + * @offset_for_non_ref_pic: see H264 specification. + * @offset_for_top_to_bottom_field: see H264 specification. + * @pic_width_in_mbs_minus1: see H264 specification. + * @pic_height_in_map_units_minus1: see H264 specification. + * @flags: see V4L2_H264_SPS_FLAG_{}. + */ +struct v4l2_ctrl_h264_sps { + u_int8_t profile_idc; + u_int8_t constraint_set_flags; + u_int8_t level_idc; + u_int8_t seq_parameter_set_id; + u_int8_t chroma_format_idc; + u_int8_t bit_depth_luma_minus8; + u_int8_t bit_depth_chroma_minus8; + u_int8_t log2_max_frame_num_minus4; + u_int8_t pic_order_cnt_type; + u_int8_t log2_max_pic_order_cnt_lsb_minus4; + u_int8_t max_num_ref_frames; + u_int8_t num_ref_frames_in_pic_order_cnt_cycle; + int32_t offset_for_ref_frame[255]; + int32_t offset_for_non_ref_pic; + int32_t offset_for_top_to_bottom_field; + u_int16_t pic_width_in_mbs_minus1; + u_int16_t pic_height_in_map_units_minus1; + u_int32_t flags; +}; + +#define V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE 0x0001 +#define V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESENT 0x0002 +#define V4L2_H264_PPS_FLAG_WEIGHTED_PRED 0x0004 +#define V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT 0x0008 +#define V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED 0x0010 +#define V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT 0x0020 +#define V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE 0x0040 +#define V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT 0x0080 + +#define V4L2_CID_STATELESS_H264_PPS (V4L2_CID_CODEC_STATELESS_BASE + 3) +/** + * struct v4l2_ctrl_h264_pps - H264 picture parameter set + * + * Except where noted, all the members on this picture parameter set + * structure match the picture parameter set syntax as specified + * by the H264 specification. + * + * In particular, V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT flag + * has a specific meaning. This flag should be set if a non-flat + * scaling matrix applies to the picture. In this case, applications + * are expected to use V4L2_CID_STATELESS_H264_SCALING_MATRIX, + * to pass the values of the non-flat matrices. + * + * @pic_parameter_set_id: see H264 specification. + * @seq_parameter_set_id: see H264 specification. + * @num_slice_groups_minus1: see H264 specification. + * @num_ref_idx_l0_default_active_minus1: see H264 specification. + * @num_ref_idx_l1_default_active_minus1: see H264 specification. + * @weighted_bipred_idc: see H264 specification. + * @pic_init_qp_minus26: see H264 specification. + * @pic_init_qs_minus26: see H264 specification. + * @chroma_qp_index_offset: see H264 specification. + * @second_chroma_qp_index_offset: see H264 specification. + * @flags: see V4L2_H264_PPS_FLAG_{}. + */ +struct v4l2_ctrl_h264_pps { + u_int8_t pic_parameter_set_id; + u_int8_t seq_parameter_set_id; + u_int8_t num_slice_groups_minus1; + u_int8_t num_ref_idx_l0_default_active_minus1; + u_int8_t num_ref_idx_l1_default_active_minus1; + u_int8_t weighted_bipred_idc; + int8_t pic_init_qp_minus26; + int8_t pic_init_qs_minus26; + int8_t chroma_qp_index_offset; + int8_t second_chroma_qp_index_offset; + u_int16_t flags; +}; + +#define V4L2_CID_STATELESS_H264_SCALING_MATRIX (V4L2_CID_CODEC_STATELESS_BASE + 4) +/** + * struct v4l2_ctrl_h264_scaling_matrix - H264 scaling matrices + * + * @scaling_list_4x4: scaling matrix after applying the inverse + * scanning process. Expected list order is Intra Y, Intra Cb, + * Intra Cr, Inter Y, Inter Cb, Inter Cr. The values on each + * scaling list are expected in raster scan order. + * @scaling_list_8x8: scaling matrix after applying the inverse + * scanning process. Expected list order is Intra Y, Inter Y, + * Intra Cb, Inter Cb, Intra Cr, Inter Cr. The values on each + * scaling list are expected in raster scan order. + * + * Note that the list order is different for the 4x4 and 8x8 + * matrices as per the H264 specification, see table 7-2 "Assignment + * of mnemonic names to scaling list indices and specification of + * fall-back rule". + */ +struct v4l2_ctrl_h264_scaling_matrix { + u_int8_t scaling_list_4x4[6][16]; + u_int8_t scaling_list_8x8[6][64]; +}; + +struct v4l2_h264_weight_factors { + int16_t luma_weight[32]; + int16_t luma_offset[32]; + int16_t chroma_weight[32][2]; + int16_t chroma_offset[32][2]; +}; + +#define V4L2_H264_CTRL_PRED_WEIGHTS_REQUIRED(pps, slice) \ + ((((pps)->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED) && \ + ((slice)->slice_type == V4L2_H264_SLICE_TYPE_P || \ + (slice)->slice_type == V4L2_H264_SLICE_TYPE_SP)) || \ + ((pps)->weighted_bipred_idc == 1 && \ + (slice)->slice_type == V4L2_H264_SLICE_TYPE_B)) + +#define V4L2_CID_STATELESS_H264_PRED_WEIGHTS (V4L2_CID_CODEC_STATELESS_BASE + 5) +/** + * struct v4l2_ctrl_h264_pred_weights - Prediction weight table + * + * Prediction weight table, which matches the syntax specified + * by the H264 specification. + * + * @luma_log2_weight_denom: see H264 specification. + * @chroma_log2_weight_denom: see H264 specification. + * @weight_factors: luma and chroma weight factors. + */ +struct v4l2_ctrl_h264_pred_weights { + u_int16_t luma_log2_weight_denom; + u_int16_t chroma_log2_weight_denom; + struct v4l2_h264_weight_factors weight_factors[2]; +}; + +#define V4L2_H264_SLICE_TYPE_P 0 +#define V4L2_H264_SLICE_TYPE_B 1 +#define V4L2_H264_SLICE_TYPE_I 2 +#define V4L2_H264_SLICE_TYPE_SP 3 +#define V4L2_H264_SLICE_TYPE_SI 4 + +#define V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED 0x01 +#define V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH 0x02 + +#define V4L2_H264_TOP_FIELD_REF 0x1 +#define V4L2_H264_BOTTOM_FIELD_REF 0x2 +#define V4L2_H264_FRAME_REF 0x3 + +/** + * struct v4l2_h264_reference - H264 picture reference + * + * @fields: indicates how the picture is referenced. + * Valid values are V4L2_H264_{}_REF. + * @index: index into v4l2_ctrl_h264_decode_params.dpb[]. + */ +struct v4l2_h264_reference { + u_int8_t fields; + u_int8_t index; +}; + +/* + * Maximum DPB size, as specified by section 'A.3.1 Level limits + * common to the Baseline, Main, and Extended profiles'. + */ +#define V4L2_H264_NUM_DPB_ENTRIES 16 +#define V4L2_H264_REF_LIST_LEN (2 * V4L2_H264_NUM_DPB_ENTRIES) + +#define V4L2_CID_STATELESS_H264_SLICE_PARAMS (V4L2_CID_CODEC_STATELESS_BASE + 6) +/** + * struct v4l2_ctrl_h264_slice_params - H264 slice parameters + * + * This structure holds the H264 syntax elements that are specified + * as non-invariant for the slices in a given frame. + * + * Slice invariant syntax elements are contained in struct + * v4l2_ctrl_h264_decode_params. This is done to reduce the API surface + * on frame-based decoders, where slice header parsing is done by the + * hardware. + * + * Slice invariant syntax elements are specified in specification section + * "7.4.3 Slice header semantics". + * + * Except where noted, the members on this struct match the slice header syntax. + * + * @header_bit_size: offset in bits to slice_data() from the beginning of this slice. + * @first_mb_in_slice: see H264 specification. + * @slice_type: see H264 specification. + * @colour_plane_id: see H264 specification. + * @redundant_pic_cnt: see H264 specification. + * @cabac_init_idc: see H264 specification. + * @slice_qp_delta: see H264 specification. + * @slice_qs_delta: see H264 specification. + * @disable_deblocking_filter_idc: see H264 specification. + * @slice_alpha_c0_offset_div2: see H264 specification. + * @slice_beta_offset_div2: see H264 specification. + * @num_ref_idx_l0_active_minus1: see H264 specification. + * @num_ref_idx_l1_active_minus1: see H264 specification. + * @reserved: padding field. Should be zeroed by applications. + * @ref_pic_list0: reference picture list 0 after applying the per-slice modifications. + * @ref_pic_list1: reference picture list 1 after applying the per-slice modifications. + * @flags: see V4L2_H264_SLICE_FLAG_{}. + */ +struct v4l2_ctrl_h264_slice_params { + u_int32_t header_bit_size; + u_int32_t first_mb_in_slice; + u_int8_t slice_type; + u_int8_t colour_plane_id; + u_int8_t redundant_pic_cnt; + u_int8_t cabac_init_idc; + int8_t slice_qp_delta; + int8_t slice_qs_delta; + u_int8_t disable_deblocking_filter_idc; + int8_t slice_alpha_c0_offset_div2; + int8_t slice_beta_offset_div2; + u_int8_t num_ref_idx_l0_active_minus1; + u_int8_t num_ref_idx_l1_active_minus1; + + u_int8_t reserved; + + struct v4l2_h264_reference ref_pic_list0[V4L2_H264_REF_LIST_LEN]; + struct v4l2_h264_reference ref_pic_list1[V4L2_H264_REF_LIST_LEN]; + + u_int32_t flags; +}; + +#define V4L2_H264_DPB_ENTRY_FLAG_VALID 0x01 +#define V4L2_H264_DPB_ENTRY_FLAG_ACTIVE 0x02 +#define V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM 0x04 +#define V4L2_H264_DPB_ENTRY_FLAG_FIELD 0x08 + +/** + * struct v4l2_h264_dpb_entry - H264 decoded picture buffer entry + * + * @reference_ts: timestamp of the V4L2 capture buffer to use as reference. + * The timestamp refers to the timestamp field in struct v4l2_buffer. + * Use v4l2_timeval_to_ns() to convert the struct timeval to a u_int64_t. + * @pic_num: matches PicNum variable assigned during the reference + * picture lists construction process. + * @frame_num: frame identifier which matches frame_num syntax element. + * @fields: indicates how the DPB entry is referenced. Valid values are + * V4L2_H264_{}_REF. + * @reserved: padding field. Should be zeroed by applications. + * @top_field_order_cnt: matches TopFieldOrderCnt picture value. + * @bottom_field_order_cnt: matches BottomFieldOrderCnt picture value. + * Note that picture field is indicated by v4l2_buffer.field. + * @flags: see V4L2_H264_DPB_ENTRY_FLAG_{}. + */ +struct v4l2_h264_dpb_entry { + u_int64_t reference_ts; + u_int32_t pic_num; + u_int16_t frame_num; + u_int8_t fields; + u_int8_t reserved[5]; + int32_t top_field_order_cnt; + int32_t bottom_field_order_cnt; + u_int32_t flags; +}; + +#define V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC 0x01 +#define V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC 0x02 +#define V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD 0x04 +#define V4L2_H264_DECODE_PARAM_FLAG_PFRAME 0x08 +#define V4L2_H264_DECODE_PARAM_FLAG_BFRAME 0x10 + +#define V4L2_CID_STATELESS_H264_DECODE_PARAMS (V4L2_CID_CODEC_STATELESS_BASE + 7) +/** + * struct v4l2_ctrl_h264_decode_params - H264 decoding parameters + * + * @dpb: decoded picture buffer. + * @nal_ref_idc: slice header syntax element. + * @frame_num: slice header syntax element. + * @top_field_order_cnt: matches TopFieldOrderCnt picture value. + * @bottom_field_order_cnt: matches BottomFieldOrderCnt picture value. + * Note that picture field is indicated by v4l2_buffer.field. + * @idr_pic_id: slice header syntax element. + * @pic_order_cnt_lsb: slice header syntax element. + * @delta_pic_order_cnt_bottom: slice header syntax element. + * @delta_pic_order_cnt0: slice header syntax element. + * @delta_pic_order_cnt1: slice header syntax element. + * @dec_ref_pic_marking_bit_size: size in bits of dec_ref_pic_marking() + * syntax element. + * @pic_order_cnt_bit_size: size in bits of pic order count syntax. + * @slice_group_change_cycle: slice header syntax element. + * @reserved: padding field. Should be zeroed by applications. + * @flags: see V4L2_H264_DECODE_PARAM_FLAG_{}. + */ +struct v4l2_ctrl_h264_decode_params { + struct v4l2_h264_dpb_entry dpb[V4L2_H264_NUM_DPB_ENTRIES]; + u_int16_t nal_ref_idc; + u_int16_t frame_num; + int32_t top_field_order_cnt; + int32_t bottom_field_order_cnt; + u_int16_t idr_pic_id; + u_int16_t pic_order_cnt_lsb; + int32_t delta_pic_order_cnt_bottom; + int32_t delta_pic_order_cnt0; + int32_t delta_pic_order_cnt1; + u_int32_t dec_ref_pic_marking_bit_size; + u_int32_t pic_order_cnt_bit_size; + u_int32_t slice_group_change_cycle; + + u_int32_t reserved; + u_int32_t flags; +}; + + +/* Stateless FWHT control, used by the vicodec driver */ + +/* Current FWHT version */ +#define V4L2_FWHT_VERSION 3 + +/* Set if this is an interlaced format */ +#define V4L2_FWHT_FL_IS_INTERLACED _BITUL(0) +/* Set if this is a bottom-first (NTSC) interlaced format */ +#define V4L2_FWHT_FL_IS_BOTTOM_FIRST _BITUL(1) +/* Set if each 'frame' contains just one field */ +#define V4L2_FWHT_FL_IS_ALTERNATE _BITUL(2) +/* + * If V4L2_FWHT_FL_IS_ALTERNATE was set, then this is set if this + * 'frame' is the bottom field, else it is the top field. + */ +#define V4L2_FWHT_FL_IS_BOTTOM_FIELD _BITUL(3) +/* Set if the Y' plane is uncompressed */ +#define V4L2_FWHT_FL_LUMA_IS_UNCOMPRESSED _BITUL(4) +/* Set if the Cb plane is uncompressed */ +#define V4L2_FWHT_FL_CB_IS_UNCOMPRESSED _BITUL(5) +/* Set if the Cr plane is uncompressed */ +#define V4L2_FWHT_FL_CR_IS_UNCOMPRESSED _BITUL(6) +/* Set if the chroma plane is full height, if cleared it is half height */ +#define V4L2_FWHT_FL_CHROMA_FULL_HEIGHT _BITUL(7) +/* Set if the chroma plane is full width, if cleared it is half width */ +#define V4L2_FWHT_FL_CHROMA_FULL_WIDTH _BITUL(8) +/* Set if the alpha plane is uncompressed */ +#define V4L2_FWHT_FL_ALPHA_IS_UNCOMPRESSED _BITUL(9) +/* Set if this is an I Frame */ +#define V4L2_FWHT_FL_I_FRAME _BITUL(10) + +/* A 4-values flag - the number of components - 1 */ +#define V4L2_FWHT_FL_COMPONENTS_NUM_MSK GENMASK(18, 16) +#define V4L2_FWHT_FL_COMPONENTS_NUM_OFFSET 16 + +/* A 4-values flag - the pixel encoding type */ +#define V4L2_FWHT_FL_PIXENC_MSK GENMASK(20, 19) +#define V4L2_FWHT_FL_PIXENC_OFFSET 19 +#define V4L2_FWHT_FL_PIXENC_YUV (1 << V4L2_FWHT_FL_PIXENC_OFFSET) +#define V4L2_FWHT_FL_PIXENC_RGB (2 << V4L2_FWHT_FL_PIXENC_OFFSET) +#define V4L2_FWHT_FL_PIXENC_HSV (3 << V4L2_FWHT_FL_PIXENC_OFFSET) + +#define V4L2_CID_STATELESS_FWHT_PARAMS (V4L2_CID_CODEC_STATELESS_BASE + 100) +/** + * struct v4l2_ctrl_fwht_params - FWHT parameters + * + * @backward_ref_ts: timestamp of the V4L2 capture buffer to use as reference. + * The timestamp refers to the timestamp field in struct v4l2_buffer. + * Use v4l2_timeval_to_ns() to convert the struct timeval to a u_int64_t. + * @version: must be V4L2_FWHT_VERSION. + * @width: width of frame. + * @height: height of frame. + * @flags: FWHT flags (see V4L2_FWHT_FL_*). + * @colorspace: the colorspace (enum v4l2_colorspace). + * @xfer_func: the transfer function (enum v4l2_xfer_func). + * @ycbcr_enc: the Y'CbCr encoding (enum v4l2_ycbcr_encoding). + * @quantization: the quantization (enum v4l2_quantization). + */ +struct v4l2_ctrl_fwht_params { + u_int64_t backward_ref_ts; + u_int32_t version; + u_int32_t width; + u_int32_t height; + u_int32_t flags; + u_int32_t colorspace; + u_int32_t xfer_func; + u_int32_t ycbcr_enc; + u_int32_t quantization; +}; + +/* Stateless VP8 control */ + +#define V4L2_VP8_SEGMENT_FLAG_ENABLED 0x01 +#define V4L2_VP8_SEGMENT_FLAG_UPDATE_MAP 0x02 +#define V4L2_VP8_SEGMENT_FLAG_UPDATE_FEATURE_DATA 0x04 +#define V4L2_VP8_SEGMENT_FLAG_DELTA_VALUE_MODE 0x08 + +/** + * struct v4l2_vp8_segment - VP8 segment-based adjustments parameters + * + * @quant_update: update values for the segment quantizer. + * @lf_update: update values for the loop filter level. + * @segment_probs: branch probabilities of the segment_id decoding tree. + * @padding: padding field. Should be zeroed by applications. + * @flags: see V4L2_VP8_SEGMENT_FLAG_{}. + * + * This structure contains segment-based adjustments related parameters. + * See the 'update_segmentation()' part of the frame header syntax, + * and section '9.3. Segment-Based Adjustments' of the VP8 specification + * for more details. + */ +struct v4l2_vp8_segment { + int8_t quant_update[4]; + int8_t lf_update[4]; + u_int8_t segment_probs[3]; + u_int8_t padding; + u_int32_t flags; +}; + +#define V4L2_VP8_LF_ADJ_ENABLE 0x01 +#define V4L2_VP8_LF_DELTA_UPDATE 0x02 +#define V4L2_VP8_LF_FILTER_TYPE_SIMPLE 0x04 + +/** + * struct v4l2_vp8_loop_filter - VP8 loop filter parameters + * + * @ref_frm_delta: Reference frame signed delta values. + * @mb_mode_delta: MB prediction mode signed delta values. + * @sharpness_level: matches sharpness_level syntax element. + * @level: matches loop_filter_level syntax element. + * @padding: padding field. Should be zeroed by applications. + * @flags: see V4L2_VP8_LF_{}. + * + * This structure contains loop filter related parameters. + * See the 'mb_lf_adjustments()' part of the frame header syntax, + * and section '9.4. Loop Filter Type and Levels' of the VP8 specification + * for more details. + */ +struct v4l2_vp8_loop_filter { + int8_t ref_frm_delta[4]; + int8_t mb_mode_delta[4]; + u_int8_t sharpness_level; + u_int8_t level; + u_int16_t padding; + u_int32_t flags; +}; + +/** + * struct v4l2_vp8_quantization - VP8 quantizattion indices + * + * @y_ac_qi: luma AC coefficient table index. + * @y_dc_delta: luma DC delta vaue. + * @y2_dc_delta: y2 block DC delta value. + * @y2_ac_delta: y2 block AC delta value. + * @uv_dc_delta: chroma DC delta value. + * @uv_ac_delta: chroma AC delta value. + * @padding: padding field. Should be zeroed by applications. + * + * This structure contains the quantization indices present + * in 'quant_indices()' part of the frame header syntax. + * See section '9.6. Dequantization Indices' of the VP8 specification + * for more details. + */ +struct v4l2_vp8_quantization { + u_int8_t y_ac_qi; + int8_t y_dc_delta; + int8_t y2_dc_delta; + int8_t y2_ac_delta; + int8_t uv_dc_delta; + int8_t uv_ac_delta; + u_int16_t padding; +}; + +#define V4L2_VP8_COEFF_PROB_CNT 11 +#define V4L2_VP8_MV_PROB_CNT 19 + +/** + * struct v4l2_vp8_entropy - VP8 update probabilities + * + * @coeff_probs: coefficient probability update values. + * @y_mode_probs: luma intra-prediction probabilities. + * @uv_mode_probs: chroma intra-prediction probabilities. + * @mv_probs: mv decoding probability. + * @padding: padding field. Should be zeroed by applications. + * + * This structure contains the update probabilities present in + * 'token_prob_update()' and 'mv_prob_update()' part of the frame header. + * See section '17.2. Probability Updates' of the VP8 specification + * for more details. + */ +struct v4l2_vp8_entropy { + u_int8_t coeff_probs[4][8][3][V4L2_VP8_COEFF_PROB_CNT]; + u_int8_t y_mode_probs[4]; + u_int8_t uv_mode_probs[3]; + u_int8_t mv_probs[2][V4L2_VP8_MV_PROB_CNT]; + u_int8_t padding[3]; +}; + +/** + * struct v4l2_vp8_entropy_coder_state - VP8 boolean coder state + * + * @range: coder state value for "Range" + * @value: coder state value for "Value" + * @bit_count: number of bits left in range "Value". + * @padding: padding field. Should be zeroed by applications. + * + * This structure contains the state for the boolean coder, as + * explained in section '7. Boolean Entropy Decoder' of the VP8 specification. + */ +struct v4l2_vp8_entropy_coder_state { + u_int8_t range; + u_int8_t value; + u_int8_t bit_count; + u_int8_t padding; +}; + +#define V4L2_VP8_FRAME_FLAG_KEY_FRAME 0x01 +#define V4L2_VP8_FRAME_FLAG_EXPERIMENTAL 0x02 +#define V4L2_VP8_FRAME_FLAG_SHOW_FRAME 0x04 +#define V4L2_VP8_FRAME_FLAG_MB_NO_SKIP_COEFF 0x08 +#define V4L2_VP8_FRAME_FLAG_SIGN_BIAS_GOLDEN 0x10 +#define V4L2_VP8_FRAME_FLAG_SIGN_BIAS_ALT 0x20 + +#define V4L2_VP8_FRAME_IS_KEY_FRAME(hdr) \ + (!!((hdr)->flags & V4L2_VP8_FRAME_FLAG_KEY_FRAME)) + +#define V4L2_CID_STATELESS_VP8_FRAME (V4L2_CID_CODEC_STATELESS_BASE + 200) +/** + * struct v4l2_ctrl_vp8_frame - VP8 frame parameters + * + * @segment: segmentation parameters. See &v4l2_vp8_segment for more details + * @lf: loop filter parameters. See &v4l2_vp8_loop_filter for more details + * @quant: quantization parameters. See &v4l2_vp8_quantization for more details + * @entropy: update probabilities. See &v4l2_vp8_entropy for more details + * @coder_state: boolean coder state. See &v4l2_vp8_entropy_coder_state for more details + * @width: frame width. + * @height: frame height. + * @horizontal_scale: horizontal scaling factor. + * @vertical_scale: vertical scaling factor. + * @version: bitstream version. + * @prob_skip_false: frame header syntax element. + * @prob_intra: frame header syntax element. + * @prob_last: frame header syntax element. + * @prob_gf: frame header syntax element. + * @num_dct_parts: number of DCT coefficients partitions. + * @first_part_size: size of the first partition, i.e. the control partition. + * @first_part_header_bits: size in bits of the first partition header portion. + * @dct_part_sizes: DCT coefficients sizes. + * @last_frame_ts: "last" reference buffer timestamp. + * The timestamp refers to the timestamp field in struct v4l2_buffer. + * Use v4l2_timeval_to_ns() to convert the struct timeval to a u_int64_t. + * @golden_frame_ts: "golden" reference buffer timestamp. + * @alt_frame_ts: "alt" reference buffer timestamp. + * @flags: see V4L2_VP8_FRAME_FLAG_{}. + */ +struct v4l2_ctrl_vp8_frame { + struct v4l2_vp8_segment segment; + struct v4l2_vp8_loop_filter lf; + struct v4l2_vp8_quantization quant; + struct v4l2_vp8_entropy entropy; + struct v4l2_vp8_entropy_coder_state coder_state; + + u_int16_t width; + u_int16_t height; + + u_int8_t horizontal_scale; + u_int8_t vertical_scale; + + u_int8_t version; + u_int8_t prob_skip_false; + u_int8_t prob_intra; + u_int8_t prob_last; + u_int8_t prob_gf; + u_int8_t num_dct_parts; + + u_int32_t first_part_size; + u_int32_t first_part_header_bits; + u_int32_t dct_part_sizes[8]; + + u_int64_t last_frame_ts; + u_int64_t golden_frame_ts; + u_int64_t alt_frame_ts; + + u_int64_t flags; +}; + +/* Stateless MPEG-2 controls */ + +#define V4L2_MPEG2_SEQ_FLAG_PROGRESSIVE 0x01 + +#define V4L2_CID_STATELESS_MPEG2_SEQUENCE (V4L2_CID_CODEC_STATELESS_BASE+220) +/** + * struct v4l2_ctrl_mpeg2_sequence - MPEG-2 sequence header + * + * All the members on this structure match the sequence header and sequence + * extension syntaxes as specified by the MPEG-2 specification. + * + * Fields horizontal_size, vertical_size and vbv_buffer_size are a + * combination of respective _value and extension syntax elements, + * as described in section 6.3.3 "Sequence header". + * + * @horizontal_size: combination of elements horizontal_size_value and + * horizontal_size_extension. + * @vertical_size: combination of elements vertical_size_value and + * vertical_size_extension. + * @vbv_buffer_size: combination of elements vbv_buffer_size_value and + * vbv_buffer_size_extension. + * @profile_and_level_indication: see MPEG-2 specification. + * @chroma_format: see MPEG-2 specification. + * @flags: see V4L2_MPEG2_SEQ_FLAG_{}. + */ +struct v4l2_ctrl_mpeg2_sequence { + u_int16_t horizontal_size; + u_int16_t vertical_size; + u_int32_t vbv_buffer_size; + u_int16_t profile_and_level_indication; + u_int8_t chroma_format; + u_int8_t flags; +}; + +#define V4L2_MPEG2_PIC_CODING_TYPE_I 1 +#define V4L2_MPEG2_PIC_CODING_TYPE_P 2 +#define V4L2_MPEG2_PIC_CODING_TYPE_B 3 +#define V4L2_MPEG2_PIC_CODING_TYPE_D 4 + +#define V4L2_MPEG2_PIC_TOP_FIELD 0x1 +#define V4L2_MPEG2_PIC_BOTTOM_FIELD 0x2 +#define V4L2_MPEG2_PIC_FRAME 0x3 + +#define V4L2_MPEG2_PIC_FLAG_TOP_FIELD_FIRST 0x0001 +#define V4L2_MPEG2_PIC_FLAG_FRAME_PRED_DCT 0x0002 +#define V4L2_MPEG2_PIC_FLAG_CONCEALMENT_MV 0x0004 +#define V4L2_MPEG2_PIC_FLAG_Q_SCALE_TYPE 0x0008 +#define V4L2_MPEG2_PIC_FLAG_INTRA_VLC 0x0010 +#define V4L2_MPEG2_PIC_FLAG_ALT_SCAN 0x0020 +#define V4L2_MPEG2_PIC_FLAG_REPEAT_FIRST 0x0040 +#define V4L2_MPEG2_PIC_FLAG_PROGRESSIVE 0x0080 + +#define V4L2_CID_STATELESS_MPEG2_PICTURE (V4L2_CID_CODEC_STATELESS_BASE+221) +/** + * struct v4l2_ctrl_mpeg2_picture - MPEG-2 picture header + * + * All the members on this structure match the picture header and picture + * coding extension syntaxes as specified by the MPEG-2 specification. + * + * @backward_ref_ts: timestamp of the V4L2 capture buffer to use as + * reference for backward prediction. + * @forward_ref_ts: timestamp of the V4L2 capture buffer to use as + * reference for forward prediction. These timestamp refers to the + * timestamp field in struct v4l2_buffer. Use v4l2_timeval_to_ns() + * to convert the struct timeval to a u_int64_t. + * @flags: see V4L2_MPEG2_PIC_FLAG_{}. + * @f_code: see MPEG-2 specification. + * @picture_coding_type: see MPEG-2 specification. + * @picture_structure: see V4L2_MPEG2_PIC_{}_FIELD. + * @intra_dc_precision: see MPEG-2 specification. + * @reserved: padding field. Should be zeroed by applications. + */ +struct v4l2_ctrl_mpeg2_picture { + u_int64_t backward_ref_ts; + u_int64_t forward_ref_ts; + u_int32_t flags; + u_int8_t f_code[2][2]; + u_int8_t picture_coding_type; + u_int8_t picture_structure; + u_int8_t intra_dc_precision; + u_int8_t reserved[5]; +}; + +#define V4L2_CID_STATELESS_MPEG2_QUANTISATION (V4L2_CID_CODEC_STATELESS_BASE+222) +/** + * struct v4l2_ctrl_mpeg2_quantisation - MPEG-2 quantisation + * + * Quantisation matrices as specified by section 6.3.7 + * "Quant matrix extension". + * + * @intra_quantiser_matrix: The quantisation matrix coefficients + * for intra-coded frames, in zigzag scanning order. It is relevant + * for both luma and chroma components, although it can be superseded + * by the chroma-specific matrix for non-4:2:0 YUV formats. + * @non_intra_quantiser_matrix: The quantisation matrix coefficients + * for non-intra-coded frames, in zigzag scanning order. It is relevant + * for both luma and chroma components, although it can be superseded + * by the chroma-specific matrix for non-4:2:0 YUV formats. + * @chroma_intra_quantiser_matrix: The quantisation matrix coefficients + * for the chominance component of intra-coded frames, in zigzag scanning + * order. Only relevant for 4:2:2 and 4:4:4 YUV formats. + * @chroma_non_intra_quantiser_matrix: The quantisation matrix coefficients + * for the chrominance component of non-intra-coded frames, in zigzag scanning + * order. Only relevant for 4:2:2 and 4:4:4 YUV formats. + */ +struct v4l2_ctrl_mpeg2_quantisation { + u_int8_t intra_quantiser_matrix[64]; + u_int8_t non_intra_quantiser_matrix[64]; + u_int8_t chroma_intra_quantiser_matrix[64]; + u_int8_t chroma_non_intra_quantiser_matrix[64]; +}; + +#define V4L2_CID_STATELESS_HEVC_SPS (V4L2_CID_CODEC_STATELESS_BASE + 400) +#define V4L2_CID_STATELESS_HEVC_PPS (V4L2_CID_CODEC_STATELESS_BASE + 401) +#define V4L2_CID_STATELESS_HEVC_SLICE_PARAMS (V4L2_CID_CODEC_STATELESS_BASE + 402) +#define V4L2_CID_STATELESS_HEVC_SCALING_MATRIX (V4L2_CID_CODEC_STATELESS_BASE + 403) +#define V4L2_CID_STATELESS_HEVC_DECODE_PARAMS (V4L2_CID_CODEC_STATELESS_BASE + 404) +#define V4L2_CID_STATELESS_HEVC_DECODE_MODE (V4L2_CID_CODEC_STATELESS_BASE + 405) +#define V4L2_CID_STATELESS_HEVC_START_CODE (V4L2_CID_CODEC_STATELESS_BASE + 406) +#define V4L2_CID_STATELESS_HEVC_ENTRY_POINT_OFFSETS (V4L2_CID_CODEC_STATELESS_BASE + 407) + +enum v4l2_stateless_hevc_decode_mode { + V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED, + V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED, +}; + +enum v4l2_stateless_hevc_start_code { + V4L2_STATELESS_HEVC_START_CODE_NONE, + V4L2_STATELESS_HEVC_START_CODE_ANNEX_B, +}; + +#define V4L2_HEVC_SLICE_TYPE_B 0 +#define V4L2_HEVC_SLICE_TYPE_P 1 +#define V4L2_HEVC_SLICE_TYPE_I 2 + +#define V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE (1ULL << 0) +#define V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED (1ULL << 1) +#define V4L2_HEVC_SPS_FLAG_AMP_ENABLED (1ULL << 2) +#define V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET (1ULL << 3) +#define V4L2_HEVC_SPS_FLAG_PCM_ENABLED (1ULL << 4) +#define V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED (1ULL << 5) +#define V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT (1ULL << 6) +#define V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED (1ULL << 7) +#define V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED (1ULL << 8) + +/** + * struct v4l2_ctrl_hevc_sps - ITU-T Rec. H.265: Sequence parameter set + * + * @video_parameter_set_id: specifies the value of the + * vps_video_parameter_set_id of the active VPS + * @seq_parameter_set_id: provides an identifier for the SPS for + * reference by other syntax elements + * @pic_width_in_luma_samples: specifies the width of each decoded picture + * in units of luma samples + * @pic_height_in_luma_samples: specifies the height of each decoded picture + * in units of luma samples + * @bit_depth_luma_minus8: this value plus 8specifies the bit depth of the + * samples of the luma array + * @bit_depth_chroma_minus8: this value plus 8 specifies the bit depth of the + * samples of the chroma arrays + * @log2_max_pic_order_cnt_lsb_minus4: this value plus 4 specifies the value of + * the variable MaxPicOrderCntLsb + * @sps_max_dec_pic_buffering_minus1: this value plus 1 specifies the maximum + * required size of the decoded picture + * buffer for the codec video sequence + * @sps_max_num_reorder_pics: indicates the maximum allowed number of pictures + * @sps_max_latency_increase_plus1: not equal to 0 is used to compute the + * value of SpsMaxLatencyPictures array + * @log2_min_luma_coding_block_size_minus3: plus 3 specifies the minimum + * luma coding block size + * @log2_diff_max_min_luma_coding_block_size: specifies the difference between + * the maximum and minimum luma + * coding block size + * @log2_min_luma_transform_block_size_minus2: plus 2 specifies the minimum luma + * transform block size + * @log2_diff_max_min_luma_transform_block_size: specifies the difference between + * the maximum and minimum luma + * transform block size + * @max_transform_hierarchy_depth_inter: specifies the maximum hierarchy + * depth for transform units of + * coding units coded in inter + * prediction mode + * @max_transform_hierarchy_depth_intra: specifies the maximum hierarchy + * depth for transform units of + * coding units coded in intra + * prediction mode + * @pcm_sample_bit_depth_luma_minus1: this value plus 1 specifies the number of + * bits used to represent each of PCM sample + * values of the luma component + * @pcm_sample_bit_depth_chroma_minus1: this value plus 1 specifies the number + * of bits used to represent each of PCM + * sample values of the chroma components + * @log2_min_pcm_luma_coding_block_size_minus3: this value plus 3 specifies the + * minimum size of coding blocks + * @log2_diff_max_min_pcm_luma_coding_block_size: specifies the difference between + * the maximum and minimum size of + * coding blocks + * @num_short_term_ref_pic_sets: specifies the number of st_ref_pic_set() + * syntax structures included in the SPS + * @num_long_term_ref_pics_sps: specifies the number of candidate long-term + * reference pictures that are specified in the SPS + * @chroma_format_idc: specifies the chroma sampling + * @sps_max_sub_layers_minus1: this value plus 1 specifies the maximum number + * of temporal sub-layers + * @reserved: padding field. Should be zeroed by applications. + * @flags: see V4L2_HEVC_SPS_FLAG_{} + */ +struct v4l2_ctrl_hevc_sps { + u_int8_t video_parameter_set_id; + u_int8_t seq_parameter_set_id; + u_int16_t pic_width_in_luma_samples; + u_int16_t pic_height_in_luma_samples; + u_int8_t bit_depth_luma_minus8; + u_int8_t bit_depth_chroma_minus8; + u_int8_t log2_max_pic_order_cnt_lsb_minus4; + u_int8_t sps_max_dec_pic_buffering_minus1; + u_int8_t sps_max_num_reorder_pics; + u_int8_t sps_max_latency_increase_plus1; + u_int8_t log2_min_luma_coding_block_size_minus3; + u_int8_t log2_diff_max_min_luma_coding_block_size; + u_int8_t log2_min_luma_transform_block_size_minus2; + u_int8_t log2_diff_max_min_luma_transform_block_size; + u_int8_t max_transform_hierarchy_depth_inter; + u_int8_t max_transform_hierarchy_depth_intra; + u_int8_t pcm_sample_bit_depth_luma_minus1; + u_int8_t pcm_sample_bit_depth_chroma_minus1; + u_int8_t log2_min_pcm_luma_coding_block_size_minus3; + u_int8_t log2_diff_max_min_pcm_luma_coding_block_size; + u_int8_t num_short_term_ref_pic_sets; + u_int8_t num_long_term_ref_pics_sps; + u_int8_t chroma_format_idc; + u_int8_t sps_max_sub_layers_minus1; + + u_int8_t reserved[6]; + u_int64_t flags; +}; + +#define V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT_ENABLED (1ULL << 0) +#define V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT (1ULL << 1) +#define V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED (1ULL << 2) +#define V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT (1ULL << 3) +#define V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED (1ULL << 4) +#define V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED (1ULL << 5) +#define V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED (1ULL << 6) +#define V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT (1ULL << 7) +#define V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED (1ULL << 8) +#define V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED (1ULL << 9) +#define V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED (1ULL << 10) +#define V4L2_HEVC_PPS_FLAG_TILES_ENABLED (1ULL << 11) +#define V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED (1ULL << 12) +#define V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED (1ULL << 13) +#define V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED (1ULL << 14) +#define V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED (1ULL << 15) +#define V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER (1ULL << 16) +#define V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT (1ULL << 17) +#define V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT (1ULL << 18) +#define V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT (1ULL << 19) +#define V4L2_HEVC_PPS_FLAG_UNIFORM_SPACING (1ULL << 20) + +/** + * struct v4l2_ctrl_hevc_pps - ITU-T Rec. H.265: Picture parameter set + * + * @pic_parameter_set_id: identifies the PPS for reference by other + * syntax elements + * @num_extra_slice_header_bits: specifies the number of extra slice header + * bits that are present in the slice header RBSP + * for coded pictures referring to the PPS. + * @num_ref_idx_l0_default_active_minus1: this value plus 1 specifies the + * inferred value of num_ref_idx_l0_active_minus1 + * @num_ref_idx_l1_default_active_minus1: this value plus 1 specifies the + * inferred value of num_ref_idx_l1_active_minus1 + * @init_qp_minus26: this value plus 26 specifies the initial value of SliceQp Y for + * each slice referring to the PPS + * @diff_cu_qp_delta_depth: specifies the difference between the luma coding + * tree block size and the minimum luma coding block + * size of coding units that convey cu_qp_delta_abs + * and cu_qp_delta_sign_flag + * @pps_cb_qp_offset: specify the offsets to the luma quantization parameter Cb + * @pps_cr_qp_offset: specify the offsets to the luma quantization parameter Cr + * @num_tile_columns_minus1: this value plus 1 specifies the number of tile columns + * partitioning the picture + * @num_tile_rows_minus1: this value plus 1 specifies the number of tile rows partitioning + * the picture + * @column_width_minus1: this value plus 1 specifies the width of the each tile column in + * units of coding tree blocks + * @row_height_minus1: this value plus 1 specifies the height of the each tile row in + * units of coding tree blocks + * @pps_beta_offset_div2: specify the default deblocking parameter offsets for + * beta divided by 2 + * @pps_tc_offset_div2: specify the default deblocking parameter offsets for tC + * divided by 2 + * @log2_parallel_merge_level_minus2: this value plus 2 specifies the value of + * the variable Log2ParMrgLevel + * @reserved: padding field. Should be zeroed by applications. + * @flags: see V4L2_HEVC_PPS_FLAG_{} + */ +struct v4l2_ctrl_hevc_pps { + u_int8_t pic_parameter_set_id; + u_int8_t num_extra_slice_header_bits; + u_int8_t num_ref_idx_l0_default_active_minus1; + u_int8_t num_ref_idx_l1_default_active_minus1; + int8_t init_qp_minus26; + u_int8_t diff_cu_qp_delta_depth; + int8_t pps_cb_qp_offset; + int8_t pps_cr_qp_offset; + u_int8_t num_tile_columns_minus1; + u_int8_t num_tile_rows_minus1; + u_int8_t column_width_minus1[20]; + u_int8_t row_height_minus1[22]; + int8_t pps_beta_offset_div2; + int8_t pps_tc_offset_div2; + u_int8_t log2_parallel_merge_level_minus2; + u_int8_t reserved; + u_int64_t flags; +}; + +#define V4L2_HEVC_DPB_ENTRY_LONG_TERM_REFERENCE 0x01 + +#define V4L2_HEVC_SEI_PIC_STRUCT_FRAME 0 +#define V4L2_HEVC_SEI_PIC_STRUCT_TOP_FIELD 1 +#define V4L2_HEVC_SEI_PIC_STRUCT_BOTTOM_FIELD 2 +#define V4L2_HEVC_SEI_PIC_STRUCT_TOP_BOTTOM 3 +#define V4L2_HEVC_SEI_PIC_STRUCT_BOTTOM_TOP 4 +#define V4L2_HEVC_SEI_PIC_STRUCT_TOP_BOTTOM_TOP 5 +#define V4L2_HEVC_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM 6 +#define V4L2_HEVC_SEI_PIC_STRUCT_FRAME_DOUBLING 7 +#define V4L2_HEVC_SEI_PIC_STRUCT_FRAME_TRIPLING 8 +#define V4L2_HEVC_SEI_PIC_STRUCT_TOP_PAIRED_PREVIOUS_BOTTOM 9 +#define V4L2_HEVC_SEI_PIC_STRUCT_BOTTOM_PAIRED_PREVIOUS_TOP 10 +#define V4L2_HEVC_SEI_PIC_STRUCT_TOP_PAIRED_NEXT_BOTTOM 11 +#define V4L2_HEVC_SEI_PIC_STRUCT_BOTTOM_PAIRED_NEXT_TOP 12 + +#define V4L2_HEVC_DPB_ENTRIES_NUM_MAX 16 + +/** + * struct v4l2_hevc_dpb_entry - HEVC decoded picture buffer entry + * + * @timestamp: timestamp of the V4L2 capture buffer to use as reference. + * @flags: long term flag for the reference frame + * @field_pic: whether the reference is a field picture or a frame. + * @reserved: padding field. Should be zeroed by applications. + * @pic_order_cnt_val: the picture order count of the current picture. + */ +struct v4l2_hevc_dpb_entry { + u_int64_t timestamp; + u_int8_t flags; + u_int8_t field_pic; + u_int16_t reserved; + int32_t pic_order_cnt_val; +}; + +/** + * struct v4l2_hevc_pred_weight_table - HEVC weighted prediction parameters + * + * @delta_luma_weight_l0: the difference of the weighting factor applied + * to the luma prediction value for list 0 + * @luma_offset_l0: the additive offset applied to the luma prediction value + * for list 0 + * @delta_chroma_weight_l0: the difference of the weighting factor applied + * to the chroma prediction values for list 0 + * @chroma_offset_l0: the difference of the additive offset applied to + * the chroma prediction values for list 0 + * @delta_luma_weight_l1: the difference of the weighting factor applied + * to the luma prediction value for list 1 + * @luma_offset_l1: the additive offset applied to the luma prediction value + * for list 1 + * @delta_chroma_weight_l1: the difference of the weighting factor applied + * to the chroma prediction values for list 1 + * @chroma_offset_l1: the difference of the additive offset applied to + * the chroma prediction values for list 1 + * @luma_log2_weight_denom: the base 2 logarithm of the denominator for + * all luma weighting factors + * @delta_chroma_log2_weight_denom: the difference of the base 2 logarithm + * of the denominator for all chroma + * weighting factors + */ +struct v4l2_hevc_pred_weight_table { + int8_t delta_luma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + int8_t luma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + int8_t delta_chroma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]; + int8_t chroma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]; + + int8_t delta_luma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + int8_t luma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + int8_t delta_chroma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]; + int8_t chroma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]; + + u_int8_t luma_log2_weight_denom; + int8_t delta_chroma_log2_weight_denom; +}; + +#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_LUMA (1ULL << 0) +#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_CHROMA (1ULL << 1) +#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_TEMPORAL_MVP_ENABLED (1ULL << 2) +#define V4L2_HEVC_SLICE_PARAMS_FLAG_MVD_L1_ZERO (1ULL << 3) +#define V4L2_HEVC_SLICE_PARAMS_FLAG_CABAC_INIT (1ULL << 4) +#define V4L2_HEVC_SLICE_PARAMS_FLAG_COLLOCATED_FROM_L0 (1ULL << 5) +#define V4L2_HEVC_SLICE_PARAMS_FLAG_USE_INTEGER_MV (1ULL << 6) +#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED (1ULL << 7) +#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED (1ULL << 8) +#define V4L2_HEVC_SLICE_PARAMS_FLAG_DEPENDENT_SLICE_SEGMENT (1ULL << 9) + +/** + * struct v4l2_ctrl_hevc_slice_params - HEVC slice parameters + * + * This control is a dynamically sized 1-dimensional array, + * V4L2_CTRL_FLAG_DYNAMIC_ARRAY flag must be set when using it. + * + * @bit_size: size (in bits) of the current slice data + * @data_byte_offset: offset (in bytes) to the video data in the current slice data + * @num_entry_point_offsets: specifies the number of entry point offset syntax + * elements in the slice header. + * @nal_unit_type: specifies the coding type of the slice (B, P or I) + * @nuh_temporal_id_plus1: minus 1 specifies a temporal identifier for the NAL unit + * @slice_type: see V4L2_HEVC_SLICE_TYPE_{} + * @colour_plane_id: specifies the colour plane associated with the current slice + * @slice_pic_order_cnt: specifies the picture order count + * @num_ref_idx_l0_active_minus1: this value plus 1 specifies the maximum + * reference index for reference picture list 0 + * that may be used to decode the slice + * @num_ref_idx_l1_active_minus1: this value plus 1 specifies the maximum + * reference index for reference picture list 1 + * that may be used to decode the slice + * @collocated_ref_idx: specifies the reference index of the collocated picture used + * for temporal motion vector prediction + * @five_minus_max_num_merge_cand: specifies the maximum number of merging + * motion vector prediction candidates supported in + * the slice subtracted from 5 + * @slice_qp_delta: specifies the initial value of QpY to be used for the coding + * blocks in the slice + * @slice_cb_qp_offset: specifies a difference to be added to the value of pps_cb_qp_offset + * @slice_cr_qp_offset: specifies a difference to be added to the value of pps_cr_qp_offset + * @slice_act_y_qp_offset: screen content extension parameters + * @slice_act_cb_qp_offset: screen content extension parameters + * @slice_act_cr_qp_offset: screen content extension parameters + * @slice_beta_offset_div2: specify the deblocking parameter offsets for beta divided by 2 + * @slice_tc_offset_div2: specify the deblocking parameter offsets for tC divided by 2 + * @pic_struct: indicates whether a picture should be displayed as a frame or as one or + * more fields + * @reserved0: padding field. Should be zeroed by applications. + * @slice_segment_addr: specifies the address of the first coding tree block in + * the slice segment + * @ref_idx_l0: the list of L0 reference elements as indices in the DPB + * @ref_idx_l1: the list of L1 reference elements as indices in the DPB + * @short_term_ref_pic_set_size: specifies the size of short-term reference + * pictures set included in the SPS + * @long_term_ref_pic_set_size: specifies the size of long-term reference + * pictures set include in the SPS + * @pred_weight_table: the prediction weight coefficients for inter-picture + * prediction + * @reserved1: padding field. Should be zeroed by applications. + * @flags: see V4L2_HEVC_SLICE_PARAMS_FLAG_{} + */ +struct v4l2_ctrl_hevc_slice_params { + u_int32_t bit_size; + u_int32_t data_byte_offset; + u_int32_t num_entry_point_offsets; + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ + u_int8_t nal_unit_type; + u_int8_t nuh_temporal_id_plus1; + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ + u_int8_t slice_type; + u_int8_t colour_plane_id; + int32_t slice_pic_order_cnt; + u_int8_t num_ref_idx_l0_active_minus1; + u_int8_t num_ref_idx_l1_active_minus1; + u_int8_t collocated_ref_idx; + u_int8_t five_minus_max_num_merge_cand; + int8_t slice_qp_delta; + int8_t slice_cb_qp_offset; + int8_t slice_cr_qp_offset; + int8_t slice_act_y_qp_offset; + int8_t slice_act_cb_qp_offset; + int8_t slice_act_cr_qp_offset; + int8_t slice_beta_offset_div2; + int8_t slice_tc_offset_div2; + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture timing SEI message */ + u_int8_t pic_struct; + + u_int8_t reserved0[3]; + /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ + u_int32_t slice_segment_addr; + u_int8_t ref_idx_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + u_int8_t ref_idx_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + u_int16_t short_term_ref_pic_set_size; + u_int16_t long_term_ref_pic_set_size; + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: Weighted prediction parameter */ + struct v4l2_hevc_pred_weight_table pred_weight_table; + + u_int8_t reserved1[2]; + u_int64_t flags; +}; + +#define V4L2_HEVC_DECODE_PARAM_FLAG_IRAP_PIC 0x1 +#define V4L2_HEVC_DECODE_PARAM_FLAG_IDR_PIC 0x2 +#define V4L2_HEVC_DECODE_PARAM_FLAG_NO_OUTPUT_OF_PRIOR 0x4 + +/** + * struct v4l2_ctrl_hevc_decode_params - HEVC decode parameters + * + * @pic_order_cnt_val: picture order count + * @short_term_ref_pic_set_size: specifies the size of short-term reference + * pictures set included in the SPS of the first slice + * @long_term_ref_pic_set_size: specifies the size of long-term reference + * pictures set include in the SPS of the first slice + * @num_active_dpb_entries: the number of entries in dpb + * @num_poc_st_curr_before: the number of reference pictures in the short-term + * set that come before the current frame + * @num_poc_st_curr_after: the number of reference pictures in the short-term + * set that come after the current frame + * @num_poc_lt_curr: the number of reference pictures in the long-term set + * @poc_st_curr_before: provides the index of the short term before references + * in DPB array + * @poc_st_curr_after: provides the index of the short term after references + * in DPB array + * @poc_lt_curr: provides the index of the long term references in DPB array + * @num_delta_pocs_of_ref_rps_idx: same as the derived value NumDeltaPocs[RefRpsIdx], + * can be used to parse the RPS data in slice headers + * instead of skipping it with @short_term_ref_pic_set_size. + * @reserved: padding field. Should be zeroed by applications. + * @dpb: the decoded picture buffer, for meta-data about reference frames + * @flags: see V4L2_HEVC_DECODE_PARAM_FLAG_{} + */ +struct v4l2_ctrl_hevc_decode_params { + int32_t pic_order_cnt_val; + u_int16_t short_term_ref_pic_set_size; + u_int16_t long_term_ref_pic_set_size; + u_int8_t num_active_dpb_entries; + u_int8_t num_poc_st_curr_before; + u_int8_t num_poc_st_curr_after; + u_int8_t num_poc_lt_curr; + u_int8_t poc_st_curr_before[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + u_int8_t poc_st_curr_after[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + u_int8_t poc_lt_curr[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + u_int8_t num_delta_pocs_of_ref_rps_idx; + u_int8_t reserved[3]; + struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + u_int64_t flags; +}; + +/** + * struct v4l2_ctrl_hevc_scaling_matrix - HEVC scaling lists parameters + * + * @scaling_list_4x4: scaling list is used for the scaling process for + * transform coefficients. The values on each scaling + * list are expected in raster scan order + * @scaling_list_8x8: scaling list is used for the scaling process for + * transform coefficients. The values on each scaling + * list are expected in raster scan order + * @scaling_list_16x16: scaling list is used for the scaling process for + * transform coefficients. The values on each scaling + * list are expected in raster scan order + * @scaling_list_32x32: scaling list is used for the scaling process for + * transform coefficients. The values on each scaling + * list are expected in raster scan order + * @scaling_list_dc_coef_16x16: scaling list is used for the scaling process + * for transform coefficients. The values on each + * scaling list are expected in raster scan order. + * @scaling_list_dc_coef_32x32: scaling list is used for the scaling process + * for transform coefficients. The values on each + * scaling list are expected in raster scan order. + */ +struct v4l2_ctrl_hevc_scaling_matrix { + u_int8_t scaling_list_4x4[6][16]; + u_int8_t scaling_list_8x8[6][64]; + u_int8_t scaling_list_16x16[6][64]; + u_int8_t scaling_list_32x32[2][64]; + u_int8_t scaling_list_dc_coef_16x16[6]; + u_int8_t scaling_list_dc_coef_32x32[2]; +}; + +#define V4L2_CID_COLORIMETRY_CLASS_BASE (V4L2_CTRL_CLASS_COLORIMETRY | 0x900) +#define V4L2_CID_COLORIMETRY_CLASS (V4L2_CTRL_CLASS_COLORIMETRY | 1) + +#define V4L2_CID_COLORIMETRY_HDR10_CLL_INFO (V4L2_CID_COLORIMETRY_CLASS_BASE + 0) + +struct v4l2_ctrl_hdr10_cll_info { + u_int16_t max_content_light_level; + u_int16_t max_pic_average_light_level; +}; + +#define V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY (V4L2_CID_COLORIMETRY_CLASS_BASE + 1) + +#define V4L2_HDR10_MASTERING_PRIMARIES_X_LOW 5 +#define V4L2_HDR10_MASTERING_PRIMARIES_X_HIGH 37000 +#define V4L2_HDR10_MASTERING_PRIMARIES_Y_LOW 5 +#define V4L2_HDR10_MASTERING_PRIMARIES_Y_HIGH 42000 +#define V4L2_HDR10_MASTERING_WHITE_POINT_X_LOW 5 +#define V4L2_HDR10_MASTERING_WHITE_POINT_X_HIGH 37000 +#define V4L2_HDR10_MASTERING_WHITE_POINT_Y_LOW 5 +#define V4L2_HDR10_MASTERING_WHITE_POINT_Y_HIGH 42000 +#define V4L2_HDR10_MASTERING_MAX_LUMA_LOW 50000 +#define V4L2_HDR10_MASTERING_MAX_LUMA_HIGH 100000000 +#define V4L2_HDR10_MASTERING_MIN_LUMA_LOW 1 +#define V4L2_HDR10_MASTERING_MIN_LUMA_HIGH 50000 + +struct v4l2_ctrl_hdr10_mastering_display { + u_int16_t display_primaries_x[3]; + u_int16_t display_primaries_y[3]; + u_int16_t white_point_x; + u_int16_t white_point_y; + u_int32_t max_display_mastering_luminance; + u_int32_t min_display_mastering_luminance; +}; + +/* Stateless VP9 controls */ + +#define V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED 0x1 +#define V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE 0x2 + +/** + * struct v4l2_vp9_loop_filter - VP9 loop filter parameters + * + * @ref_deltas: contains the adjustment needed for the filter level based on the + * chosen reference frame. If this syntax element is not present in the bitstream, + * users should pass its last value. + * @mode_deltas: contains the adjustment needed for the filter level based on the + * chosen mode. If this syntax element is not present in the bitstream, users should + * pass its last value. + * @level: indicates the loop filter strength. + * @sharpness: indicates the sharpness level. + * @flags: combination of V4L2_VP9_LOOP_FILTER_FLAG_{} flags. + * @reserved: padding field. Should be zeroed by applications. + * + * This structure contains all loop filter related parameters. See sections + * '7.2.8 Loop filter semantics' of the VP9 specification for more details. + */ +struct v4l2_vp9_loop_filter { + int8_t ref_deltas[4]; + int8_t mode_deltas[2]; + u_int8_t level; + u_int8_t sharpness; + u_int8_t flags; + u_int8_t reserved[7]; +}; + +/** + * struct v4l2_vp9_quantization - VP9 quantization parameters + * + * @base_q_idx: indicates the base frame qindex. + * @delta_q_y_dc: indicates the Y DC quantizer relative to base_q_idx. + * @delta_q_uv_dc: indicates the UV DC quantizer relative to base_q_idx. + * @delta_q_uv_ac: indicates the UV AC quantizer relative to base_q_idx. + * @reserved: padding field. Should be zeroed by applications. + * + * Encodes the quantization parameters. See section '7.2.9 Quantization params + * syntax' of the VP9 specification for more details. + */ +struct v4l2_vp9_quantization { + u_int8_t base_q_idx; + int8_t delta_q_y_dc; + int8_t delta_q_uv_dc; + int8_t delta_q_uv_ac; + u_int8_t reserved[4]; +}; + +#define V4L2_VP9_SEGMENTATION_FLAG_ENABLED 0x01 +#define V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP 0x02 +#define V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE 0x04 +#define V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA 0x08 +#define V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE 0x10 + +#define V4L2_VP9_SEG_LVL_ALT_Q 0 +#define V4L2_VP9_SEG_LVL_ALT_L 1 +#define V4L2_VP9_SEG_LVL_REF_FRAME 2 +#define V4L2_VP9_SEG_LVL_SKIP 3 +#define V4L2_VP9_SEG_LVL_MAX 4 + +#define V4L2_VP9_SEGMENT_FEATURE_ENABLED(id) (1 << (id)) +#define V4L2_VP9_SEGMENT_FEATURE_ENABLED_MASK 0xf + +/** + * struct v4l2_vp9_segmentation - VP9 segmentation parameters + * + * @feature_data: data attached to each feature. Data entry is only valid if + * the feature is enabled. The array shall be indexed with segment number as + * the first dimension (0..7) and one of V4L2_VP9_SEG_{} as the second dimension. + * @feature_enabled: bitmask defining which features are enabled in each segment. + * The value for each segment is a combination of V4L2_VP9_SEGMENT_FEATURE_ENABLED(id) + * values where id is one of V4L2_VP9_SEG_LVL_{}. + * @tree_probs: specifies the probability values to be used when decoding a + * Segment-ID. See '5.15. Segmentation map' section of the VP9 specification + * for more details. + * @pred_probs: specifies the probability values to be used when decoding a + * Predicted-Segment-ID. See '6.4.14. Get segment id syntax' section of :ref:`vp9` + * for more details. + * @flags: combination of V4L2_VP9_SEGMENTATION_FLAG_{} flags. + * @reserved: padding field. Should be zeroed by applications. + * + * Encodes the quantization parameters. See section '7.2.10 Segmentation params syntax' of + * the VP9 specification for more details. + */ +struct v4l2_vp9_segmentation { + int16_t feature_data[8][4]; + u_int8_t feature_enabled[8]; + u_int8_t tree_probs[7]; + u_int8_t pred_probs[3]; + u_int8_t flags; + u_int8_t reserved[5]; +}; + +#define V4L2_VP9_FRAME_FLAG_KEY_FRAME 0x001 +#define V4L2_VP9_FRAME_FLAG_SHOW_FRAME 0x002 +#define V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT 0x004 +#define V4L2_VP9_FRAME_FLAG_INTRA_ONLY 0x008 +#define V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV 0x010 +#define V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX 0x020 +#define V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE 0x040 +#define V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING 0x080 +#define V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING 0x100 +#define V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING 0x200 + +#define V4L2_VP9_SIGN_BIAS_LAST 0x1 +#define V4L2_VP9_SIGN_BIAS_GOLDEN 0x2 +#define V4L2_VP9_SIGN_BIAS_ALT 0x4 + +#define V4L2_VP9_RESET_FRAME_CTX_NONE 0 +#define V4L2_VP9_RESET_FRAME_CTX_SPEC 1 +#define V4L2_VP9_RESET_FRAME_CTX_ALL 2 + +#define V4L2_VP9_INTERP_FILTER_EIGHTTAP 0 +#define V4L2_VP9_INTERP_FILTER_EIGHTTAP_SMOOTH 1 +#define V4L2_VP9_INTERP_FILTER_EIGHTTAP_SHARP 2 +#define V4L2_VP9_INTERP_FILTER_BILINEAR 3 +#define V4L2_VP9_INTERP_FILTER_SWITCHABLE 4 + +#define V4L2_VP9_REFERENCE_MODE_SINGLE_REFERENCE 0 +#define V4L2_VP9_REFERENCE_MODE_COMPOUND_REFERENCE 1 +#define V4L2_VP9_REFERENCE_MODE_SELECT 2 + +#define V4L2_VP9_PROFILE_MAX 3 + +#define V4L2_CID_STATELESS_VP9_FRAME (V4L2_CID_CODEC_STATELESS_BASE + 300) +/** + * struct v4l2_ctrl_vp9_frame - VP9 frame decoding control + * + * @lf: loop filter parameters. See &v4l2_vp9_loop_filter for more details. + * @quant: quantization parameters. See &v4l2_vp9_quantization for more details. + * @seg: segmentation parameters. See &v4l2_vp9_segmentation for more details. + * @flags: combination of V4L2_VP9_FRAME_FLAG_{} flags. + * @compressed_header_size: compressed header size in bytes. + * @uncompressed_header_size: uncompressed header size in bytes. + * @frame_width_minus_1: add 1 to it and you'll get the frame width expressed in pixels. + * @frame_height_minus_1: add 1 to it and you'll get the frame height expressed in pixels. + * @render_width_minus_1: add 1 to it and you'll get the expected render width expressed in + * pixels. This is not used during the decoding process but might be used by HW scalers + * to prepare a frame that's ready for scanout. + * @render_height_minus_1: add 1 to it and you'll get the expected render height expressed in + * pixels. This is not used during the decoding process but might be used by HW scalers + * to prepare a frame that's ready for scanout. + * @last_frame_ts: "last" reference buffer timestamp. + * The timestamp refers to the timestamp field in struct v4l2_buffer. + * Use v4l2_timeval_to_ns() to convert the struct timeval to a u_int64_t. + * @golden_frame_ts: "golden" reference buffer timestamp. + * The timestamp refers to the timestamp field in struct v4l2_buffer. + * Use v4l2_timeval_to_ns() to convert the struct timeval to a u_int64_t. + * @alt_frame_ts: "alt" reference buffer timestamp. + * The timestamp refers to the timestamp field in struct v4l2_buffer. + * Use v4l2_timeval_to_ns() to convert the struct timeval to a u_int64_t. + * @ref_frame_sign_bias: a bitfield specifying whether the sign bias is set for a given + * reference frame. Either of V4L2_VP9_SIGN_BIAS_{}. + * @reset_frame_context: specifies whether the frame context should be reset to default values. + * Either of V4L2_VP9_RESET_FRAME_CTX_{}. + * @frame_context_idx: frame context that should be used/updated. + * @profile: VP9 profile. Can be 0, 1, 2 or 3. + * @bit_depth: bits per components. Can be 8, 10 or 12. Note that not all profiles support + * 10 and/or 12 bits depths. + * @interpolation_filter: specifies the filter selection used for performing inter prediction. + * Set to one of V4L2_VP9_INTERP_FILTER_{}. + * @tile_cols_log2: specifies the base 2 logarithm of the width of each tile (where the width + * is measured in units of 8x8 blocks). Shall be less than or equal to 6. + * @tile_rows_log2: specifies the base 2 logarithm of the height of each tile (where the height + * is measured in units of 8x8 blocks). + * @reference_mode: specifies the type of inter prediction to be used. + * Set to one of V4L2_VP9_REFERENCE_MODE_{}. + * @reserved: padding field. Should be zeroed by applications. + */ +struct v4l2_ctrl_vp9_frame { + struct v4l2_vp9_loop_filter lf; + struct v4l2_vp9_quantization quant; + struct v4l2_vp9_segmentation seg; + u_int32_t flags; + u_int16_t compressed_header_size; + u_int16_t uncompressed_header_size; + u_int16_t frame_width_minus_1; + u_int16_t frame_height_minus_1; + u_int16_t render_width_minus_1; + u_int16_t render_height_minus_1; + u_int64_t last_frame_ts; + u_int64_t golden_frame_ts; + u_int64_t alt_frame_ts; + u_int8_t ref_frame_sign_bias; + u_int8_t reset_frame_context; + u_int8_t frame_context_idx; + u_int8_t profile; + u_int8_t bit_depth; + u_int8_t interpolation_filter; + u_int8_t tile_cols_log2; + u_int8_t tile_rows_log2; + u_int8_t reference_mode; + u_int8_t reserved[7]; +}; + +#define V4L2_VP9_NUM_FRAME_CTX 4 + +/** + * struct v4l2_vp9_mv_probs - VP9 Motion vector probability updates + * @joint: motion vector joint probability updates. + * @sign: motion vector sign probability updates. + * @classes: motion vector class probability updates. + * @class0_bit: motion vector class0 bit probability updates. + * @bits: motion vector bits probability updates. + * @class0_fr: motion vector class0 fractional bit probability updates. + * @fr: motion vector fractional bit probability updates. + * @class0_hp: motion vector class0 high precision fractional bit probability updates. + * @hp: motion vector high precision fractional bit probability updates. + * + * This structure contains new values of motion vector probabilities. + * A value of zero in an array element means there is no update of the relevant probability. + * See `struct v4l2_vp9_prob_updates` for details. + */ +struct v4l2_vp9_mv_probs { + u_int8_t joint[3]; + u_int8_t sign[2]; + u_int8_t classes[2][10]; + u_int8_t class0_bit[2]; + u_int8_t bits[2][10]; + u_int8_t class0_fr[2][2][3]; + u_int8_t fr[2][3]; + u_int8_t class0_hp[2]; + u_int8_t hp[2]; +}; + +#define V4L2_CID_STATELESS_VP9_COMPRESSED_HDR (V4L2_CID_CODEC_STATELESS_BASE + 301) + +#define V4L2_VP9_TX_MODE_ONLY_4X4 0 +#define V4L2_VP9_TX_MODE_ALLOW_8X8 1 +#define V4L2_VP9_TX_MODE_ALLOW_16X16 2 +#define V4L2_VP9_TX_MODE_ALLOW_32X32 3 +#define V4L2_VP9_TX_MODE_SELECT 4 + +/** + * struct v4l2_ctrl_vp9_compressed_hdr - VP9 probability updates control + * @tx_mode: specifies the TX mode. Set to one of V4L2_VP9_TX_MODE_{}. + * @tx8: TX 8x8 probability updates. + * @tx16: TX 16x16 probability updates. + * @tx32: TX 32x32 probability updates. + * @coef: coefficient probability updates. + * @skip: skip probability updates. + * @inter_mode: inter mode probability updates. + * @interp_filter: interpolation filter probability updates. + * @is_inter: is inter-block probability updates. + * @comp_mode: compound prediction mode probability updates. + * @single_ref: single ref probability updates. + * @comp_ref: compound ref probability updates. + * @y_mode: Y prediction mode probability updates. + * @uv_mode: UV prediction mode probability updates. + * @partition: partition probability updates. + * @mv: motion vector probability updates. + * + * This structure holds the probabilities update as parsed in the compressed + * header (Spec 6.3). These values represent the value of probability update after + * being translated with inv_map_table[] (see 6.3.5). A value of zero in an array element + * means that there is no update of the relevant probability. + * + * This control is optional and needs to be used when dealing with the hardware which is + * not capable of parsing the compressed header itself. Only drivers which need it will + * implement it. + */ +struct v4l2_ctrl_vp9_compressed_hdr { + u_int8_t tx_mode; + u_int8_t tx8[2][1]; + u_int8_t tx16[2][2]; + u_int8_t tx32[2][3]; + u_int8_t coef[4][2][2][6][6][3]; + u_int8_t skip[3]; + u_int8_t inter_mode[7][3]; + u_int8_t interp_filter[4][2]; + u_int8_t is_inter[4]; + u_int8_t comp_mode[5]; + u_int8_t single_ref[5][2]; + u_int8_t comp_ref[5]; + u_int8_t y_mode[4][9]; + u_int8_t uv_mode[10][9]; + u_int8_t partition[16][3]; + + struct v4l2_vp9_mv_probs mv; +}; + +/* Stateless AV1 controls */ + +#define V4L2_AV1_TOTAL_REFS_PER_FRAME 8 +#define V4L2_AV1_CDEF_MAX 8 +#define V4L2_AV1_NUM_PLANES_MAX 3 /* 1 if monochrome, 3 otherwise */ +#define V4L2_AV1_MAX_SEGMENTS 8 +#define V4L2_AV1_MAX_OPERATING_POINTS (1 << 5) /* 5 bits to encode */ +#define V4L2_AV1_REFS_PER_FRAME 7 +#define V4L2_AV1_MAX_NUM_Y_POINTS (1 << 4) /* 4 bits to encode */ +#define V4L2_AV1_MAX_NUM_CB_POINTS (1 << 4) /* 4 bits to encode */ +#define V4L2_AV1_MAX_NUM_CR_POINTS (1 << 4) /* 4 bits to encode */ +#define V4L2_AV1_AR_COEFFS_SIZE 25 /* (2 * 3 * (3 + 1)) + 1 */ +#define V4L2_AV1_MAX_NUM_PLANES 3 +#define V4L2_AV1_MAX_TILE_COLS 64 +#define V4L2_AV1_MAX_TILE_ROWS 64 +#define V4L2_AV1_MAX_TILE_COUNT 512 + +#define V4L2_AV1_SEQUENCE_FLAG_STILL_PICTURE 0x00000001 +#define V4L2_AV1_SEQUENCE_FLAG_USE_128X128_SUPERBLOCK 0x00000002 +#define V4L2_AV1_SEQUENCE_FLAG_ENABLE_FILTER_INTRA 0x00000004 +#define V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTRA_EDGE_FILTER 0x00000008 +#define V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTERINTRA_COMPOUND 0x00000010 +#define V4L2_AV1_SEQUENCE_FLAG_ENABLE_MASKED_COMPOUND 0x00000020 +#define V4L2_AV1_SEQUENCE_FLAG_ENABLE_WARPED_MOTION 0x00000040 +#define V4L2_AV1_SEQUENCE_FLAG_ENABLE_DUAL_FILTER 0x00000080 +#define V4L2_AV1_SEQUENCE_FLAG_ENABLE_ORDER_HINT 0x00000100 +#define V4L2_AV1_SEQUENCE_FLAG_ENABLE_JNT_COMP 0x00000200 +#define V4L2_AV1_SEQUENCE_FLAG_ENABLE_REF_FRAME_MVS 0x00000400 +#define V4L2_AV1_SEQUENCE_FLAG_ENABLE_SUPERRES 0x00000800 +#define V4L2_AV1_SEQUENCE_FLAG_ENABLE_CDEF 0x00001000 +#define V4L2_AV1_SEQUENCE_FLAG_ENABLE_RESTORATION 0x00002000 +#define V4L2_AV1_SEQUENCE_FLAG_MONO_CHROME 0x00004000 +#define V4L2_AV1_SEQUENCE_FLAG_COLOR_RANGE 0x00008000 +#define V4L2_AV1_SEQUENCE_FLAG_SUBSAMPLING_X 0x00010000 +#define V4L2_AV1_SEQUENCE_FLAG_SUBSAMPLING_Y 0x00020000 +#define V4L2_AV1_SEQUENCE_FLAG_FILM_GRAIN_PARAMS_PRESENT 0x00040000 +#define V4L2_AV1_SEQUENCE_FLAG_SEPARATE_UV_DELTA_Q 0x00080000 + +#define V4L2_CID_STATELESS_AV1_SEQUENCE (V4L2_CID_CODEC_STATELESS_BASE + 500) +/** + * struct v4l2_ctrl_av1_sequence - AV1 Sequence + * + * Represents an AV1 Sequence OBU. See section 5.5 "Sequence header OBU syntax" + * for more details. + * + * @flags: See V4L2_AV1_SEQUENCE_FLAG_{}. + * @seq_profile: specifies the features that can be used in the coded video + * sequence. + * @order_hint_bits: specifies the number of bits used for the order_hint field + * at each frame. + * @bit_depth: the bitdepth to use for the sequence as described in section + * 5.5.2 "Color config syntax". + * @reserved: padding field. Should be zeroed by applications. + * @max_frame_width_minus_1: specifies the maximum frame width minus 1 for the + * frames represented by this sequence header. + * @max_frame_height_minus_1: specifies the maximum frame height minus 1 for the + * frames represented by this sequence header. + */ +struct v4l2_ctrl_av1_sequence { + u_int32_t flags; + u_int8_t seq_profile; + u_int8_t order_hint_bits; + u_int8_t bit_depth; + u_int8_t reserved; + u_int16_t max_frame_width_minus_1; + u_int16_t max_frame_height_minus_1; +}; + +#define V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY (V4L2_CID_CODEC_STATELESS_BASE + 501) +/** + * struct v4l2_ctrl_av1_tile_group_entry - AV1 Tile Group entry + * + * Represents a single AV1 tile inside an AV1 Tile Group. Note that MiRowStart, + * MiRowEnd, MiColStart and MiColEnd can be retrieved from struct + * v4l2_av1_tile_info in struct v4l2_ctrl_av1_frame using tile_row and + * tile_col. See section 6.10.1 "General tile group OBU semantics" for more + * details. + * + * @tile_offset: offset from the OBU data, i.e. where the coded tile data + * actually starts. + * @tile_size: specifies the size in bytes of the coded tile. Equivalent to + * "TileSize" in the AV1 Specification. + * @tile_row: specifies the row of the current tile. Equivalent to "TileRow" in + * the AV1 Specification. + * @tile_col: specifies the col of the current tile. Equivalent to "TileCol" in + * the AV1 Specification. + */ +struct v4l2_ctrl_av1_tile_group_entry { + u_int32_t tile_offset; + u_int32_t tile_size; + u_int32_t tile_row; + u_int32_t tile_col; +}; + +/** + * enum v4l2_av1_warp_model - AV1 Warp Model as described in section 3 + * "Symbols and abbreviated terms" of the AV1 Specification. + * + * @V4L2_AV1_WARP_MODEL_IDENTITY: Warp model is just an identity transform. + * @V4L2_AV1_WARP_MODEL_TRANSLATION: Warp model is a pure translation. + * @V4L2_AV1_WARP_MODEL_ROTZOOM: Warp model is a rotation + symmetric zoom + + * translation. + * @V4L2_AV1_WARP_MODEL_AFFINE: Warp model is a general affine transform. + */ +enum v4l2_av1_warp_model { + V4L2_AV1_WARP_MODEL_IDENTITY = 0, + V4L2_AV1_WARP_MODEL_TRANSLATION = 1, + V4L2_AV1_WARP_MODEL_ROTZOOM = 2, + V4L2_AV1_WARP_MODEL_AFFINE = 3, +}; + +/** + * enum v4l2_av1_reference_frame - AV1 reference frames + * + * @V4L2_AV1_REF_INTRA_FRAME: Intra Frame Reference + * @V4L2_AV1_REF_LAST_FRAME: Last Reference Frame + * @V4L2_AV1_REF_LAST2_FRAME: Last2 Reference Frame + * @V4L2_AV1_REF_LAST3_FRAME: Last3 Reference Frame + * @V4L2_AV1_REF_GOLDEN_FRAME: Golden Reference Frame + * @V4L2_AV1_REF_BWDREF_FRAME: BWD Reference Frame + * @V4L2_AV1_REF_ALTREF2_FRAME: Alternative2 Reference Frame + * @V4L2_AV1_REF_ALTREF_FRAME: Alternative Reference Frame + */ +enum v4l2_av1_reference_frame { + V4L2_AV1_REF_INTRA_FRAME = 0, + V4L2_AV1_REF_LAST_FRAME = 1, + V4L2_AV1_REF_LAST2_FRAME = 2, + V4L2_AV1_REF_LAST3_FRAME = 3, + V4L2_AV1_REF_GOLDEN_FRAME = 4, + V4L2_AV1_REF_BWDREF_FRAME = 5, + V4L2_AV1_REF_ALTREF2_FRAME = 6, + V4L2_AV1_REF_ALTREF_FRAME = 7, +}; + +#define V4L2_AV1_GLOBAL_MOTION_IS_INVALID(ref) (1 << (ref)) + +#define V4L2_AV1_GLOBAL_MOTION_FLAG_IS_GLOBAL 0x1 +#define V4L2_AV1_GLOBAL_MOTION_FLAG_IS_ROT_ZOOM 0x2 +#define V4L2_AV1_GLOBAL_MOTION_FLAG_IS_TRANSLATION 0x4 +/** + * struct v4l2_av1_global_motion - AV1 Global Motion parameters as described in + * section 6.8.17 "Global motion params semantics" of the AV1 specification. + * + * @flags: A bitfield containing the flags per reference frame. See + * V4L2_AV1_GLOBAL_MOTION_FLAG_{} + * @type: The type of global motion transform used. + * @params: this field has the same meaning as "gm_params" in the AV1 + * specification. + * @invalid: bitfield indicating whether the global motion params are invalid + * for a given reference frame. See section 7.11.3.6 Setup shear process and + * the variable "warpValid". Use V4L2_AV1_GLOBAL_MOTION_IS_INVALID(ref) to + * create a suitable mask. + * @reserved: padding field. Should be zeroed by applications. + */ + +struct v4l2_av1_global_motion { + u_int8_t flags[V4L2_AV1_TOTAL_REFS_PER_FRAME]; + enum v4l2_av1_warp_model type[V4L2_AV1_TOTAL_REFS_PER_FRAME]; + int32_t params[V4L2_AV1_TOTAL_REFS_PER_FRAME][6]; + u_int8_t invalid; + u_int8_t reserved[3]; +}; + +/** + * enum v4l2_av1_frame_restoration_type - AV1 Frame Restoration Type + * @V4L2_AV1_FRAME_RESTORE_NONE: no filtering is applied. + * @V4L2_AV1_FRAME_RESTORE_WIENER: Wiener filter process is invoked. + * @V4L2_AV1_FRAME_RESTORE_SGRPROJ: self guided filter process is invoked. + * @V4L2_AV1_FRAME_RESTORE_SWITCHABLE: restoration filter is swichtable. + */ +enum v4l2_av1_frame_restoration_type { + V4L2_AV1_FRAME_RESTORE_NONE = 0, + V4L2_AV1_FRAME_RESTORE_WIENER = 1, + V4L2_AV1_FRAME_RESTORE_SGRPROJ = 2, + V4L2_AV1_FRAME_RESTORE_SWITCHABLE = 3, +}; + +#define V4L2_AV1_LOOP_RESTORATION_FLAG_USES_LR 0x1 +#define V4L2_AV1_LOOP_RESTORATION_FLAG_USES_CHROMA_LR 0x2 + +/** + * struct v4l2_av1_loop_restoration - AV1 Loop Restauration as described in + * section 6.10.15 "Loop restoration params semantics" of the AV1 specification. + * + * @flags: See V4L2_AV1_LOOP_RESTORATION_FLAG_{}. + * @lr_unit_shift: specifies if the luma restoration size should be halved. + * @lr_uv_shift: specifies if the chroma size should be half the luma size. + * @reserved: padding field. Should be zeroed by applications. + * @frame_restoration_type: specifies the type of restoration used for each + * plane. See enum v4l2_av1_frame_restoration_type. + * @loop_restoration_size: specifies the size of loop restoration units in units + * of samples in the current plane. + */ +struct v4l2_av1_loop_restoration { + u_int8_t flags; + u_int8_t lr_unit_shift; + u_int8_t lr_uv_shift; + u_int8_t reserved; + enum v4l2_av1_frame_restoration_type frame_restoration_type[V4L2_AV1_NUM_PLANES_MAX]; + u_int32_t loop_restoration_size[V4L2_AV1_MAX_NUM_PLANES]; +}; + +/** + * struct v4l2_av1_cdef - AV1 CDEF params semantics as described in section + * 6.10.14 "CDEF params semantics" of the AV1 specification + * + * @damping_minus_3: controls the amount of damping in the deringing filter. + * @bits: specifies the number of bits needed to specify which CDEF filter to + * apply. + * @y_pri_strength: specifies the strength of the primary filter. + * @y_sec_strength: specifies the strength of the secondary filter. + * @uv_pri_strength: specifies the strength of the primary filter. + * @uv_sec_strength: specifies the strength of the secondary filter. + */ +struct v4l2_av1_cdef { + u_int8_t damping_minus_3; + u_int8_t bits; + u_int8_t y_pri_strength[V4L2_AV1_CDEF_MAX]; + u_int8_t y_sec_strength[V4L2_AV1_CDEF_MAX]; + u_int8_t uv_pri_strength[V4L2_AV1_CDEF_MAX]; + u_int8_t uv_sec_strength[V4L2_AV1_CDEF_MAX]; +}; + +#define V4L2_AV1_SEGMENTATION_FLAG_ENABLED 0x1 +#define V4L2_AV1_SEGMENTATION_FLAG_UPDATE_MAP 0x2 +#define V4L2_AV1_SEGMENTATION_FLAG_TEMPORAL_UPDATE 0x4 +#define V4L2_AV1_SEGMENTATION_FLAG_UPDATE_DATA 0x8 +#define V4L2_AV1_SEGMENTATION_FLAG_SEG_ID_PRE_SKIP 0x10 + +/** + * enum v4l2_av1_segment_feature - AV1 segment features as described in section + * 3 "Symbols and abbreviated terms" of the AV1 specification. + * + * @V4L2_AV1_SEG_LVL_ALT_Q: Index for quantizer segment feature. + * @V4L2_AV1_SEG_LVL_ALT_LF_Y_V: Index for vertical luma loop filter segment + * feature. + * @V4L2_AV1_SEG_LVL_REF_FRAME: Index for reference frame segment feature. + * @V4L2_AV1_SEG_LVL_REF_SKIP: Index for skip segment feature. + * @V4L2_AV1_SEG_LVL_REF_GLOBALMV: Index for global mv feature. + * @V4L2_AV1_SEG_LVL_MAX: Number of segment features. + */ +enum v4l2_av1_segment_feature { + V4L2_AV1_SEG_LVL_ALT_Q = 0, + V4L2_AV1_SEG_LVL_ALT_LF_Y_V = 1, + V4L2_AV1_SEG_LVL_REF_FRAME = 5, + V4L2_AV1_SEG_LVL_REF_SKIP = 6, + V4L2_AV1_SEG_LVL_REF_GLOBALMV = 7, + V4L2_AV1_SEG_LVL_MAX = 8 +}; + +#define V4L2_AV1_SEGMENT_FEATURE_ENABLED(id) (1 << (id)) + +/** + * struct v4l2_av1_segmentation - AV1 Segmentation params as defined in section + * 6.8.13 "Segmentation params semantics" of the AV1 specification. + * + * @flags: see V4L2_AV1_SEGMENTATION_FLAG_{}. + * @last_active_seg_id: indicates the highest numbered segment id that has some + * enabled feature. This is used when decoding the segment id to only decode + * choices corresponding to used segments. + * @feature_enabled: bitmask defining which features are enabled in each + * segment. Use V4L2_AV1_SEGMENT_FEATURE_ENABLED to build a suitable mask. + * @feature_data: data attached to each feature. Data entry is only valid if the + * feature is enabled + */ +struct v4l2_av1_segmentation { + u_int8_t flags; + u_int8_t last_active_seg_id; + u_int8_t feature_enabled[V4L2_AV1_MAX_SEGMENTS]; + int16_t feature_data[V4L2_AV1_MAX_SEGMENTS][V4L2_AV1_SEG_LVL_MAX]; +}; + +#define V4L2_AV1_LOOP_FILTER_FLAG_DELTA_ENABLED 0x1 +#define V4L2_AV1_LOOP_FILTER_FLAG_DELTA_UPDATE 0x2 +#define V4L2_AV1_LOOP_FILTER_FLAG_DELTA_LF_PRESENT 0x4 +#define V4L2_AV1_LOOP_FILTER_FLAG_DELTA_LF_MULTI 0x8 + +/** + * struct v4l2_av1_loop_filter - AV1 Loop filter params as defined in section + * 6.8.10 "Loop filter semantics" and 6.8.16 "Loop filter delta parameters + * semantics" of the AV1 specification. + * + * @flags: see V4L2_AV1_LOOP_FILTER_FLAG_{} + * @level: an array containing loop filter strength values. Different loop + * filter strength values from the array are used depending on the image plane + * being filtered, and the edge direction (vertical or horizontal) being + * filtered. + * @sharpness: indicates the sharpness level. The loop_filter_level and + * loop_filter_sharpness together determine when a block edge is filtered, and + * by how much the filtering can change the sample values. The loop filter + * process is described in section 7.14 of the AV1 specification. + * @ref_deltas: contains the adjustment needed for the filter level based on the + * chosen reference frame. If this syntax element is not present, it maintains + * its previous value. + * @mode_deltas: contains the adjustment needed for the filter level based on + * the chosen mode. If this syntax element is not present, it maintains its + * previous value. + * @delta_lf_res: specifies the left shift which should be applied to decoded + * loop filter delta values. + */ +struct v4l2_av1_loop_filter { + u_int8_t flags; + u_int8_t level[4]; + u_int8_t sharpness; + int8_t ref_deltas[V4L2_AV1_TOTAL_REFS_PER_FRAME]; + int8_t mode_deltas[2]; + u_int8_t delta_lf_res; +}; + +#define V4L2_AV1_QUANTIZATION_FLAG_DIFF_UV_DELTA 0x1 +#define V4L2_AV1_QUANTIZATION_FLAG_USING_QMATRIX 0x2 +#define V4L2_AV1_QUANTIZATION_FLAG_DELTA_Q_PRESENT 0x4 + +/** + * struct v4l2_av1_quantization - AV1 Quantization params as defined in section + * 6.8.11 "Quantization params semantics" of the AV1 specification. + * + * @flags: see V4L2_AV1_QUANTIZATION_FLAG_{} + * @base_q_idx: indicates the base frame qindex. This is used for Y AC + * coefficients and as the base value for the other quantizers. + * @delta_q_y_dc: indicates the Y DC quantizer relative to base_q_idx. + * @delta_q_u_dc: indicates the U DC quantizer relative to base_q_idx. + * @delta_q_u_ac: indicates the U AC quantizer relative to base_q_idx. + * @delta_q_v_dc: indicates the V DC quantizer relative to base_q_idx. + * @delta_q_v_ac: indicates the V AC quantizer relative to base_q_idx. + * @qm_y: specifies the level in the quantizer matrix that should be used for + * luma plane decoding. + * @qm_u: specifies the level in the quantizer matrix that should be used for + * chroma U plane decoding. + * @qm_v: specifies the level in the quantizer matrix that should be used for + * chroma V plane decoding. + * @delta_q_res: specifies the left shift which should be applied to decoded + * quantizer index delta values. + */ +struct v4l2_av1_quantization { + u_int8_t flags; + u_int8_t base_q_idx; + int8_t delta_q_y_dc; + int8_t delta_q_u_dc; + int8_t delta_q_u_ac; + int8_t delta_q_v_dc; + int8_t delta_q_v_ac; + u_int8_t qm_y; + u_int8_t qm_u; + u_int8_t qm_v; + u_int8_t delta_q_res; +}; + +#define V4L2_AV1_TILE_INFO_FLAG_UNIFORM_TILE_SPACING 0x1 + +/** + * struct v4l2_av1_tile_info - AV1 Tile info as defined in section 6.8.14 "Tile + * info semantics" of the AV1 specification. + * + * @flags: see V4L2_AV1_TILE_INFO_FLAG_{} + * @context_update_tile_id: specifies which tile to use for the CDF update. + * @tile_rows: specifies the number of tiles down the frame. + * @tile_cols: specifies the number of tiles across the frame. + * @mi_col_starts: an array specifying the start column (in units of 4x4 luma + * samples) for each tile across the image. + * @mi_row_starts: an array specifying the start row (in units of 4x4 luma + * samples) for each tile down the image. + * @width_in_sbs_minus_1: specifies the width of a tile minus 1 in units of + * superblocks. + * @height_in_sbs_minus_1: specifies the height of a tile minus 1 in units of + * superblocks. + * @tile_size_bytes: specifies the number of bytes needed to code each tile + * size. + * @reserved: padding field. Should be zeroed by applications. + */ +struct v4l2_av1_tile_info { + u_int8_t flags; + u_int8_t context_update_tile_id; + u_int8_t tile_cols; + u_int8_t tile_rows; + u_int32_t mi_col_starts[V4L2_AV1_MAX_TILE_COLS + 1]; + u_int32_t mi_row_starts[V4L2_AV1_MAX_TILE_ROWS + 1]; + u_int32_t width_in_sbs_minus_1[V4L2_AV1_MAX_TILE_COLS]; + u_int32_t height_in_sbs_minus_1[V4L2_AV1_MAX_TILE_ROWS]; + u_int8_t tile_size_bytes; + u_int8_t reserved[3]; +}; + +/** + * enum v4l2_av1_frame_type - AV1 Frame Type + * + * @V4L2_AV1_KEY_FRAME: Key frame + * @V4L2_AV1_INTER_FRAME: Inter frame + * @V4L2_AV1_INTRA_ONLY_FRAME: Intra-only frame + * @V4L2_AV1_SWITCH_FRAME: Switch frame + */ +enum v4l2_av1_frame_type { + V4L2_AV1_KEY_FRAME = 0, + V4L2_AV1_INTER_FRAME = 1, + V4L2_AV1_INTRA_ONLY_FRAME = 2, + V4L2_AV1_SWITCH_FRAME = 3 +}; + +/** + * enum v4l2_av1_interpolation_filter - AV1 interpolation filter types + * + * @V4L2_AV1_INTERPOLATION_FILTER_EIGHTTAP: eight tap filter + * @V4L2_AV1_INTERPOLATION_FILTER_EIGHTTAP_SMOOTH: eight tap smooth filter + * @V4L2_AV1_INTERPOLATION_FILTER_EIGHTTAP_SHARP: eight tap sharp filter + * @V4L2_AV1_INTERPOLATION_FILTER_BILINEAR: bilinear filter + * @V4L2_AV1_INTERPOLATION_FILTER_SWITCHABLE: filter selection is signaled at + * the block level + * + * See section 6.8.9 "Interpolation filter semantics" of the AV1 specification + * for more details. + */ +enum v4l2_av1_interpolation_filter { + V4L2_AV1_INTERPOLATION_FILTER_EIGHTTAP = 0, + V4L2_AV1_INTERPOLATION_FILTER_EIGHTTAP_SMOOTH = 1, + V4L2_AV1_INTERPOLATION_FILTER_EIGHTTAP_SHARP = 2, + V4L2_AV1_INTERPOLATION_FILTER_BILINEAR = 3, + V4L2_AV1_INTERPOLATION_FILTER_SWITCHABLE = 4, +}; + +/** + * enum v4l2_av1_tx_mode - AV1 Tx mode as described in section 6.8.21 "TX mode + * semantics" of the AV1 specification. + * @V4L2_AV1_TX_MODE_ONLY_4X4: the inverse transform will use only 4x4 + * transforms + * @V4L2_AV1_TX_MODE_LARGEST: the inverse transform will use the largest + * transform size that fits inside the block + * @V4L2_AV1_TX_MODE_SELECT: the choice of transform size is specified + * explicitly for each block. + */ +enum v4l2_av1_tx_mode { + V4L2_AV1_TX_MODE_ONLY_4X4 = 0, + V4L2_AV1_TX_MODE_LARGEST = 1, + V4L2_AV1_TX_MODE_SELECT = 2 +}; + +#define V4L2_AV1_FRAME_FLAG_SHOW_FRAME 0x00000001 +#define V4L2_AV1_FRAME_FLAG_SHOWABLE_FRAME 0x00000002 +#define V4L2_AV1_FRAME_FLAG_ERROR_RESILIENT_MODE 0x00000004 +#define V4L2_AV1_FRAME_FLAG_DISABLE_CDF_UPDATE 0x00000008 +#define V4L2_AV1_FRAME_FLAG_ALLOW_SCREEN_CONTENT_TOOLS 0x00000010 +#define V4L2_AV1_FRAME_FLAG_FORCE_INTEGER_MV 0x00000020 +#define V4L2_AV1_FRAME_FLAG_ALLOW_INTRABC 0x00000040 +#define V4L2_AV1_FRAME_FLAG_USE_SUPERRES 0x00000080 +#define V4L2_AV1_FRAME_FLAG_ALLOW_HIGH_PRECISION_MV 0x00000100 +#define V4L2_AV1_FRAME_FLAG_IS_MOTION_MODE_SWITCHABLE 0x00000200 +#define V4L2_AV1_FRAME_FLAG_USE_REF_FRAME_MVS 0x00000400 +#define V4L2_AV1_FRAME_FLAG_DISABLE_FRAME_END_UPDATE_CDF 0x00000800 +#define V4L2_AV1_FRAME_FLAG_ALLOW_WARPED_MOTION 0x00001000 +#define V4L2_AV1_FRAME_FLAG_REFERENCE_SELECT 0x00002000 +#define V4L2_AV1_FRAME_FLAG_REDUCED_TX_SET 0x00004000 +#define V4L2_AV1_FRAME_FLAG_SKIP_MODE_ALLOWED 0x00008000 +#define V4L2_AV1_FRAME_FLAG_SKIP_MODE_PRESENT 0x00010000 +#define V4L2_AV1_FRAME_FLAG_FRAME_SIZE_OVERRIDE 0x00020000 +#define V4L2_AV1_FRAME_FLAG_BUFFER_REMOVAL_TIME_PRESENT 0x00040000 +#define V4L2_AV1_FRAME_FLAG_FRAME_REFS_SHORT_SIGNALING 0x00080000 + +#define V4L2_CID_STATELESS_AV1_FRAME (V4L2_CID_CODEC_STATELESS_BASE + 502) +/** + * struct v4l2_ctrl_av1_frame - Represents an AV1 Frame Header OBU. + * + * @tile_info: tile info + * @quantization: quantization params + * @segmentation: segmentation params + * @superres_denom: the denominator for the upscaling ratio. + * @loop_filter: loop filter params + * @cdef: cdef params + * @skip_mode_frame: specifies the frames to use for compound prediction when + * skip_mode is equal to 1. + * @primary_ref_frame: specifies which reference frame contains the CDF values + * and other state that should be loaded at the start of the frame. + * @loop_restoration: loop restoration params + * @global_motion: global motion params + * @flags: see V4L2_AV1_FRAME_FLAG_{} + * @frame_type: specifies the AV1 frame type + * @order_hint: specifies OrderHintBits least significant bits of the expected + * output order for this frame. + * @upscaled_width: the upscaled width. + * @interpolation_filter: specifies the filter selection used for performing + * inter prediction. + * @tx_mode: specifies how the transform size is determined. + * @frame_width_minus_1: add 1 to get the frame's width. + * @frame_height_minus_1: add 1 to get the frame's height + * @render_width_minus_1: add 1 to get the render width of the frame in luma + * samples. + * @render_height_minus_1: add 1 to get the render height of the frame in luma + * samples. + * @current_frame_id: specifies the frame id number for the current frame. Frame + * id numbers are additional information that do not affect the decoding + * process, but provide decoders with a way of detecting missing reference + * frames so that appropriate action can be taken. + * @buffer_removal_time: specifies the frame removal time in units of DecCT clock + * ticks counted from the removal time of the last random access point for + * operating point opNum. + * @reserved: padding field. Should be zeroed by applications. + * @order_hints: specifies the expected output order hint for each reference + * frame. This field corresponds to the OrderHints variable from the + * specification (section 5.9.2 "Uncompressed header syntax"). As such, this is + * only used for non-intra frames and ignored otherwise. order_hints[0] is + * always ignored. + * @reference_frame_ts: the V4L2 timestamp of the reference frame slots. + * @ref_frame_idx: used to index into @reference_frame_ts when decoding + * inter-frames. The meaning of this array is the same as in the specification. + * The timestamp refers to the timestamp field in struct v4l2_buffer. Use + * v4l2_timeval_to_ns() to convert the struct timeval to a u_int64_t. + * @refresh_frame_flags: contains a bitmask that specifies which reference frame + * slots will be updated with the current frame after it is decoded. + */ +struct v4l2_ctrl_av1_frame { + struct v4l2_av1_tile_info tile_info; + struct v4l2_av1_quantization quantization; + u_int8_t superres_denom; + struct v4l2_av1_segmentation segmentation; + struct v4l2_av1_loop_filter loop_filter; + struct v4l2_av1_cdef cdef; + u_int8_t skip_mode_frame[2]; + u_int8_t primary_ref_frame; + struct v4l2_av1_loop_restoration loop_restoration; + struct v4l2_av1_global_motion global_motion; + u_int32_t flags; + enum v4l2_av1_frame_type frame_type; + u_int32_t order_hint; + u_int32_t upscaled_width; + enum v4l2_av1_interpolation_filter interpolation_filter; + enum v4l2_av1_tx_mode tx_mode; + u_int32_t frame_width_minus_1; + u_int32_t frame_height_minus_1; + u_int16_t render_width_minus_1; + u_int16_t render_height_minus_1; + + u_int32_t current_frame_id; + u_int32_t buffer_removal_time[V4L2_AV1_MAX_OPERATING_POINTS]; + u_int8_t reserved[4]; + u_int32_t order_hints[V4L2_AV1_TOTAL_REFS_PER_FRAME]; + u_int64_t reference_frame_ts[V4L2_AV1_TOTAL_REFS_PER_FRAME]; + int8_t ref_frame_idx[V4L2_AV1_REFS_PER_FRAME]; + u_int8_t refresh_frame_flags; +}; + +#define V4L2_AV1_FILM_GRAIN_FLAG_APPLY_GRAIN 0x1 +#define V4L2_AV1_FILM_GRAIN_FLAG_UPDATE_GRAIN 0x2 +#define V4L2_AV1_FILM_GRAIN_FLAG_CHROMA_SCALING_FROM_LUMA 0x4 +#define V4L2_AV1_FILM_GRAIN_FLAG_OVERLAP 0x8 +#define V4L2_AV1_FILM_GRAIN_FLAG_CLIP_TO_RESTRICTED_RANGE 0x10 + +#define V4L2_CID_STATELESS_AV1_FILM_GRAIN (V4L2_CID_CODEC_STATELESS_BASE + 505) +/** + * struct v4l2_ctrl_av1_film_grain - AV1 Film Grain parameters. + * + * Film grain parameters as specified by section 6.8.20 of the AV1 Specification. + * + * @flags: see V4L2_AV1_FILM_GRAIN_{}. + * @cr_mult: represents a multiplier for the cr component used in derivation of + * the input index to the cr component scaling function. + * @grain_seed: specifies the starting value for the pseudo-random numbers used + * during film grain synthesis. + * @film_grain_params_ref_idx: indicates which reference frame contains the + * film grain parameters to be used for this frame. + * @num_y_points: specifies the number of points for the piece-wise linear + * scaling function of the luma component. + * @point_y_value: represents the x (luma value) coordinate for the i-th point + * of the piecewise linear scaling function for luma component. The values are + * signaled on the scale of 0..255. In case of 10 bit video, these values + * correspond to luma values divided by 4. In case of 12 bit video, these values + * correspond to luma values divided by 16. + * @point_y_scaling: represents the scaling (output) value for the i-th point + * of the piecewise linear scaling function for luma component. + * @num_cb_points: specifies the number of points for the piece-wise linear + * scaling function of the cb component. + * @point_cb_value: represents the x coordinate for the i-th point of the + * piece-wise linear scaling function for cb component. The values are signaled + * on the scale of 0..255. + * @point_cb_scaling: represents the scaling (output) value for the i-th point + * of the piecewise linear scaling function for cb component. + * @num_cr_points: specifies represents the number of points for the piece-wise + * linear scaling function of the cr component. + * @point_cr_value: represents the x coordinate for the i-th point of the + * piece-wise linear scaling function for cr component. The values are signaled + * on the scale of 0..255. + * @point_cr_scaling: represents the scaling (output) value for the i-th point + * of the piecewise linear scaling function for cr component. + * @grain_scaling_minus_8: represents the shift – 8 applied to the values of the + * chroma component. The grain_scaling_minus_8 can take values of 0..3 and + * determines the range and quantization step of the standard deviation of film + * grain. + * @ar_coeff_lag: specifies the number of auto-regressive coefficients for luma + * and chroma. + * @ar_coeffs_y_plus_128: specifies auto-regressive coefficients used for the Y + * plane. + * @ar_coeffs_cb_plus_128: specifies auto-regressive coefficients used for the U + * plane. + * @ar_coeffs_cr_plus_128: specifies auto-regressive coefficients used for the V + * plane. + * @ar_coeff_shift_minus_6: specifies the range of the auto-regressive + * coefficients. Values of 0, 1, 2, and 3 correspond to the ranges for + * auto-regressive coefficients of [-2, 2), [-1, 1), [-0.5, 0.5) and [-0.25, + * 0.25) respectively. + * @grain_scale_shift: specifies how much the Gaussian random numbers should be + * scaled down during the grain synthesis process. + * @cb_mult: represents a multiplier for the cb component used in derivation of + * the input index to the cb component scaling function. + * @cb_luma_mult: represents a multiplier for the average luma component used in + * derivation of the input index to the cb component scaling function. + * @cr_luma_mult: represents a multiplier for the average luma component used in + * derivation of the input index to the cr component scaling function. + * @cb_offset: represents an offset used in derivation of the input index to the + * cb component scaling function. + * @cr_offset: represents an offset used in derivation of the input index to the + * cr component scaling function. + * @reserved: padding field. Should be zeroed by applications. + */ +struct v4l2_ctrl_av1_film_grain { + u_int8_t flags; + u_int8_t cr_mult; + u_int16_t grain_seed; + u_int8_t film_grain_params_ref_idx; + u_int8_t num_y_points; + u_int8_t point_y_value[V4L2_AV1_MAX_NUM_Y_POINTS]; + u_int8_t point_y_scaling[V4L2_AV1_MAX_NUM_Y_POINTS]; + u_int8_t num_cb_points; + u_int8_t point_cb_value[V4L2_AV1_MAX_NUM_CB_POINTS]; + u_int8_t point_cb_scaling[V4L2_AV1_MAX_NUM_CB_POINTS]; + u_int8_t num_cr_points; + u_int8_t point_cr_value[V4L2_AV1_MAX_NUM_CR_POINTS]; + u_int8_t point_cr_scaling[V4L2_AV1_MAX_NUM_CR_POINTS]; + u_int8_t grain_scaling_minus_8; + u_int8_t ar_coeff_lag; + u_int8_t ar_coeffs_y_plus_128[V4L2_AV1_AR_COEFFS_SIZE]; + u_int8_t ar_coeffs_cb_plus_128[V4L2_AV1_AR_COEFFS_SIZE]; + u_int8_t ar_coeffs_cr_plus_128[V4L2_AV1_AR_COEFFS_SIZE]; + u_int8_t ar_coeff_shift_minus_6; + u_int8_t grain_scale_shift; + u_int8_t cb_mult; + u_int8_t cb_luma_mult; + u_int8_t cr_luma_mult; + u_int16_t cb_offset; + u_int16_t cr_offset; + u_int8_t reserved[4]; +}; + +/* MPEG-compression definitions kept for backwards compatibility */ +#define V4L2_CTRL_CLASS_MPEG V4L2_CTRL_CLASS_CODEC +#define V4L2_CID_MPEG_CLASS V4L2_CID_CODEC_CLASS +#define V4L2_CID_MPEG_BASE V4L2_CID_CODEC_BASE +#define V4L2_CID_MPEG_CX2341X_BASE V4L2_CID_CODEC_CX2341X_BASE +#define V4L2_CID_MPEG_MFC51_BASE V4L2_CID_CODEC_MFC51_BASE +/* + * End of v4l2-controls.h + */ + +#ifndef __user +#define __user +#endif + +/* + * Common stuff for both V4L1 and V4L2 + * Moved from videodev.h + */ +#define VIDEO_MAX_FRAME 32 +#define VIDEO_MAX_PLANES 8 + +/* + * M I S C E L L A N E O U S + */ + +/* Four-character-code (FOURCC) */ +#define v4l2_fourcc(a, b, c, d)\ + ((u_int32_t)(a) | ((u_int32_t)(b) << 8) | ((u_int32_t)(c) << 16) | ((u_int32_t)(d) << 24)) +#define v4l2_fourcc_be(a, b, c, d) (v4l2_fourcc(a, b, c, d) | (1U << 31)) + +/* + * E N U M S + */ +enum v4l2_field { + V4L2_FIELD_ANY = 0, /* driver can choose from none, + top, bottom, interlaced + depending on whatever it thinks + is approximate ... */ + V4L2_FIELD_NONE = 1, /* this device has no fields ... */ + V4L2_FIELD_TOP = 2, /* top field only */ + V4L2_FIELD_BOTTOM = 3, /* bottom field only */ + V4L2_FIELD_INTERLACED = 4, /* both fields interlaced */ + V4L2_FIELD_SEQ_TB = 5, /* both fields sequential into one + buffer, top-bottom order */ + V4L2_FIELD_SEQ_BT = 6, /* same as above + bottom-top order */ + V4L2_FIELD_ALTERNATE = 7, /* both fields alternating into + separate buffers */ + V4L2_FIELD_INTERLACED_TB = 8, /* both fields interlaced, top field + first and the top field is + transmitted first */ + V4L2_FIELD_INTERLACED_BT = 9, /* both fields interlaced, top field + first and the bottom field is + transmitted first */ +}; +#define V4L2_FIELD_HAS_TOP(field) \ + ((field) == V4L2_FIELD_TOP ||\ + (field) == V4L2_FIELD_INTERLACED ||\ + (field) == V4L2_FIELD_INTERLACED_TB ||\ + (field) == V4L2_FIELD_INTERLACED_BT ||\ + (field) == V4L2_FIELD_SEQ_TB ||\ + (field) == V4L2_FIELD_SEQ_BT) +#define V4L2_FIELD_HAS_BOTTOM(field) \ + ((field) == V4L2_FIELD_BOTTOM ||\ + (field) == V4L2_FIELD_INTERLACED ||\ + (field) == V4L2_FIELD_INTERLACED_TB ||\ + (field) == V4L2_FIELD_INTERLACED_BT ||\ + (field) == V4L2_FIELD_SEQ_TB ||\ + (field) == V4L2_FIELD_SEQ_BT) +#define V4L2_FIELD_HAS_BOTH(field) \ + ((field) == V4L2_FIELD_INTERLACED ||\ + (field) == V4L2_FIELD_INTERLACED_TB ||\ + (field) == V4L2_FIELD_INTERLACED_BT ||\ + (field) == V4L2_FIELD_SEQ_TB ||\ + (field) == V4L2_FIELD_SEQ_BT) +#define V4L2_FIELD_HAS_T_OR_B(field) \ + ((field) == V4L2_FIELD_BOTTOM ||\ + (field) == V4L2_FIELD_TOP ||\ + (field) == V4L2_FIELD_ALTERNATE) +#define V4L2_FIELD_IS_INTERLACED(field) \ + ((field) == V4L2_FIELD_INTERLACED ||\ + (field) == V4L2_FIELD_INTERLACED_TB ||\ + (field) == V4L2_FIELD_INTERLACED_BT) +#define V4L2_FIELD_IS_SEQUENTIAL(field) \ + ((field) == V4L2_FIELD_SEQ_TB ||\ + (field) == V4L2_FIELD_SEQ_BT) + +enum v4l2_buf_type { + V4L2_BUF_TYPE_VIDEO_CAPTURE = 1, + V4L2_BUF_TYPE_VIDEO_OUTPUT = 2, + V4L2_BUF_TYPE_VIDEO_OVERLAY = 3, + V4L2_BUF_TYPE_VBI_CAPTURE = 4, + V4L2_BUF_TYPE_VBI_OUTPUT = 5, + V4L2_BUF_TYPE_SLICED_VBI_CAPTURE = 6, + V4L2_BUF_TYPE_SLICED_VBI_OUTPUT = 7, + V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8, + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE = 9, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE = 10, + V4L2_BUF_TYPE_SDR_CAPTURE = 11, + V4L2_BUF_TYPE_SDR_OUTPUT = 12, + V4L2_BUF_TYPE_META_CAPTURE = 13, + V4L2_BUF_TYPE_META_OUTPUT = 14, + /* + * Note: V4L2_TYPE_IS_VALID and V4L2_TYPE_IS_OUTPUT must + * be updated if a new type is added. + */ + /* Deprecated, do not use */ + V4L2_BUF_TYPE_PRIVATE = 0x80, +}; + +#define V4L2_TYPE_IS_VALID(type) \ + ((type) >= V4L2_BUF_TYPE_VIDEO_CAPTURE &&\ + (type) <= V4L2_BUF_TYPE_META_OUTPUT) + +#define V4L2_TYPE_IS_MULTIPLANAR(type) \ + ((type) == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE \ + || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) + +#define V4L2_TYPE_IS_OUTPUT(type) \ + ((type) == V4L2_BUF_TYPE_VIDEO_OUTPUT \ + || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE \ + || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY \ + || (type) == V4L2_BUF_TYPE_VBI_OUTPUT \ + || (type) == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT \ + || (type) == V4L2_BUF_TYPE_SDR_OUTPUT \ + || (type) == V4L2_BUF_TYPE_META_OUTPUT) + +#define V4L2_TYPE_IS_CAPTURE(type) \ + (V4L2_TYPE_IS_VALID(type) && !V4L2_TYPE_IS_OUTPUT(type)) + +enum v4l2_tuner_type { + V4L2_TUNER_RADIO = 1, + V4L2_TUNER_ANALOG_TV = 2, + V4L2_TUNER_DIGITAL_TV = 3, + V4L2_TUNER_SDR = 4, + V4L2_TUNER_RF = 5, +}; + +/* Deprecated, do not use */ +#define V4L2_TUNER_ADC V4L2_TUNER_SDR + +enum v4l2_memory { + V4L2_MEMORY_MMAP = 1, + V4L2_MEMORY_USERPTR = 2, + V4L2_MEMORY_OVERLAY = 3, + V4L2_MEMORY_DMABUF = 4, +}; + +/* see also http://vektor.theorem.ca/graphics/ycbcr/ */ +enum v4l2_colorspace { + /* + * Default colorspace, i.e. let the driver figure it out. + * Can only be used with video capture. + */ + V4L2_COLORSPACE_DEFAULT = 0, + + /* SMPTE 170M: used for broadcast NTSC/PAL SDTV */ + V4L2_COLORSPACE_SMPTE170M = 1, + + /* Obsolete pre-1998 SMPTE 240M HDTV standard, superseded by Rec 709 */ + V4L2_COLORSPACE_SMPTE240M = 2, + + /* Rec.709: used for HDTV */ + V4L2_COLORSPACE_REC709 = 3, + + /* + * Deprecated, do not use. No driver will ever return this. This was + * based on a misunderstanding of the bt878 datasheet. + */ + V4L2_COLORSPACE_BT878 = 4, + + /* + * NTSC 1953 colorspace. This only makes sense when dealing with + * really, really old NTSC recordings. Superseded by SMPTE 170M. + */ + V4L2_COLORSPACE_470_SYSTEM_M = 5, + + /* + * EBU Tech 3213 PAL/SECAM colorspace. + */ + V4L2_COLORSPACE_470_SYSTEM_BG = 6, + + /* + * Effectively shorthand for V4L2_COLORSPACE_SRGB, V4L2_YCBCR_ENC_601 + * and V4L2_QUANTIZATION_FULL_RANGE. To be used for (Motion-)JPEG. + */ + V4L2_COLORSPACE_JPEG = 7, + + /* For RGB colorspaces such as produces by most webcams. */ + V4L2_COLORSPACE_SRGB = 8, + + /* opRGB colorspace */ + V4L2_COLORSPACE_OPRGB = 9, + + /* BT.2020 colorspace, used for UHDTV. */ + V4L2_COLORSPACE_BT2020 = 10, + + /* Raw colorspace: for RAW unprocessed images */ + V4L2_COLORSPACE_RAW = 11, + + /* DCI-P3 colorspace, used by cinema projectors */ + V4L2_COLORSPACE_DCI_P3 = 12, +}; + +/* + * Determine how COLORSPACE_DEFAULT should map to a proper colorspace. + * This depends on whether this is a SDTV image (use SMPTE 170M), an + * HDTV image (use Rec. 709), or something else (use sRGB). + */ +#define V4L2_MAP_COLORSPACE_DEFAULT(is_sdtv, is_hdtv) \ + ((is_sdtv) ? V4L2_COLORSPACE_SMPTE170M : \ + ((is_hdtv) ? V4L2_COLORSPACE_REC709 : V4L2_COLORSPACE_SRGB)) + +enum v4l2_xfer_func { + /* + * Mapping of V4L2_XFER_FUNC_DEFAULT to actual transfer functions + * for the various colorspaces: + * + * V4L2_COLORSPACE_SMPTE170M, V4L2_COLORSPACE_470_SYSTEM_M, + * V4L2_COLORSPACE_470_SYSTEM_BG, V4L2_COLORSPACE_REC709 and + * V4L2_COLORSPACE_BT2020: V4L2_XFER_FUNC_709 + * + * V4L2_COLORSPACE_SRGB, V4L2_COLORSPACE_JPEG: V4L2_XFER_FUNC_SRGB + * + * V4L2_COLORSPACE_OPRGB: V4L2_XFER_FUNC_OPRGB + * + * V4L2_COLORSPACE_SMPTE240M: V4L2_XFER_FUNC_SMPTE240M + * + * V4L2_COLORSPACE_RAW: V4L2_XFER_FUNC_NONE + * + * V4L2_COLORSPACE_DCI_P3: V4L2_XFER_FUNC_DCI_P3 + */ + V4L2_XFER_FUNC_DEFAULT = 0, + V4L2_XFER_FUNC_709 = 1, + V4L2_XFER_FUNC_SRGB = 2, + V4L2_XFER_FUNC_OPRGB = 3, + V4L2_XFER_FUNC_SMPTE240M = 4, + V4L2_XFER_FUNC_NONE = 5, + V4L2_XFER_FUNC_DCI_P3 = 6, + V4L2_XFER_FUNC_SMPTE2084 = 7, +}; + +/* + * Determine how XFER_FUNC_DEFAULT should map to a proper transfer function. + * This depends on the colorspace. + */ +#define V4L2_MAP_XFER_FUNC_DEFAULT(colsp) \ + ((colsp) == V4L2_COLORSPACE_OPRGB ? V4L2_XFER_FUNC_OPRGB : \ + ((colsp) == V4L2_COLORSPACE_SMPTE240M ? V4L2_XFER_FUNC_SMPTE240M : \ + ((colsp) == V4L2_COLORSPACE_DCI_P3 ? V4L2_XFER_FUNC_DCI_P3 : \ + ((colsp) == V4L2_COLORSPACE_RAW ? V4L2_XFER_FUNC_NONE : \ + ((colsp) == V4L2_COLORSPACE_SRGB || (colsp) == V4L2_COLORSPACE_JPEG ? \ + V4L2_XFER_FUNC_SRGB : V4L2_XFER_FUNC_709))))) + +enum v4l2_ycbcr_encoding { + /* + * Mapping of V4L2_YCBCR_ENC_DEFAULT to actual encodings for the + * various colorspaces: + * + * V4L2_COLORSPACE_SMPTE170M, V4L2_COLORSPACE_470_SYSTEM_M, + * V4L2_COLORSPACE_470_SYSTEM_BG, V4L2_COLORSPACE_SRGB, + * V4L2_COLORSPACE_OPRGB and V4L2_COLORSPACE_JPEG: V4L2_YCBCR_ENC_601 + * + * V4L2_COLORSPACE_REC709 and V4L2_COLORSPACE_DCI_P3: V4L2_YCBCR_ENC_709 + * + * V4L2_COLORSPACE_BT2020: V4L2_YCBCR_ENC_BT2020 + * + * V4L2_COLORSPACE_SMPTE240M: V4L2_YCBCR_ENC_SMPTE240M + */ + V4L2_YCBCR_ENC_DEFAULT = 0, + + /* ITU-R 601 -- SDTV */ + V4L2_YCBCR_ENC_601 = 1, + + /* Rec. 709 -- HDTV */ + V4L2_YCBCR_ENC_709 = 2, + + /* ITU-R 601/EN 61966-2-4 Extended Gamut -- SDTV */ + V4L2_YCBCR_ENC_XV601 = 3, + + /* Rec. 709/EN 61966-2-4 Extended Gamut -- HDTV */ + V4L2_YCBCR_ENC_XV709 = 4, + + /* + * sYCC (Y'CbCr encoding of sRGB), identical to ENC_601. It was added + * originally due to a misunderstanding of the sYCC standard. It should + * not be used, instead use V4L2_YCBCR_ENC_601. + */ + V4L2_YCBCR_ENC_SYCC = 5, + + /* BT.2020 Non-constant Luminance Y'CbCr */ + V4L2_YCBCR_ENC_BT2020 = 6, + + /* BT.2020 Constant Luminance Y'CbcCrc */ + V4L2_YCBCR_ENC_BT2020_CONST_LUM = 7, + + /* SMPTE 240M -- Obsolete HDTV */ + V4L2_YCBCR_ENC_SMPTE240M = 8, +}; + +/* + * enum v4l2_hsv_encoding values should not collide with the ones from + * enum v4l2_ycbcr_encoding. + */ +enum v4l2_hsv_encoding { + + /* Hue mapped to 0 - 179 */ + V4L2_HSV_ENC_180 = 128, + + /* Hue mapped to 0-255 */ + V4L2_HSV_ENC_256 = 129, +}; + +/* + * Determine how YCBCR_ENC_DEFAULT should map to a proper Y'CbCr encoding. + * This depends on the colorspace. + */ +#define V4L2_MAP_YCBCR_ENC_DEFAULT(colsp) \ + (((colsp) == V4L2_COLORSPACE_REC709 || \ + (colsp) == V4L2_COLORSPACE_DCI_P3) ? V4L2_YCBCR_ENC_709 : \ + ((colsp) == V4L2_COLORSPACE_BT2020 ? V4L2_YCBCR_ENC_BT2020 : \ + ((colsp) == V4L2_COLORSPACE_SMPTE240M ? V4L2_YCBCR_ENC_SMPTE240M : \ + V4L2_YCBCR_ENC_601))) + +enum v4l2_quantization { + /* + * The default for R'G'B' quantization is always full range. + * For Y'CbCr the quantization is always limited range, except + * for COLORSPACE_JPEG: this is full range. + */ + V4L2_QUANTIZATION_DEFAULT = 0, + V4L2_QUANTIZATION_FULL_RANGE = 1, + V4L2_QUANTIZATION_LIM_RANGE = 2, +}; + +/* + * Determine how QUANTIZATION_DEFAULT should map to a proper quantization. + * This depends on whether the image is RGB or not, the colorspace. + * The Y'CbCr encoding is not used anymore, but is still there for backwards + * compatibility. + */ +#define V4L2_MAP_QUANTIZATION_DEFAULT(is_rgb_or_hsv, colsp, ycbcr_enc) \ + (((is_rgb_or_hsv) || (colsp) == V4L2_COLORSPACE_JPEG) ? \ + V4L2_QUANTIZATION_FULL_RANGE : V4L2_QUANTIZATION_LIM_RANGE) + +/* + * Deprecated names for opRGB colorspace (IEC 61966-2-5) + * + * WARNING: Please don't use these deprecated defines in your code, as + * there is a chance we have to remove them in the future. + */ +#define V4L2_COLORSPACE_ADOBERGB V4L2_COLORSPACE_OPRGB +#define V4L2_XFER_FUNC_ADOBERGB V4L2_XFER_FUNC_OPRGB + +enum v4l2_priority { + V4L2_PRIORITY_UNSET = 0, /* not initialized */ + V4L2_PRIORITY_BACKGROUND = 1, + V4L2_PRIORITY_INTERACTIVE = 2, + V4L2_PRIORITY_RECORD = 3, + V4L2_PRIORITY_DEFAULT = V4L2_PRIORITY_INTERACTIVE, +}; + +struct v4l2_rect { + int32_t left; + int32_t top; + u_int32_t width; + u_int32_t height; +}; + +struct v4l2_fract { + u_int32_t numerator; + u_int32_t denominator; +}; + +struct v4l2_area { + u_int32_t width; + u_int32_t height; +}; + +/** + * struct v4l2_capability - Describes V4L2 device caps returned by VIDIOC_QUERYCAP + * + * @driver: name of the driver module (e.g. "bttv") + * @card: name of the card (e.g. "Hauppauge WinTV") + * @bus_info: name of the bus (e.g. "PCI:" + pci_name(pci_dev) ) + * @version: KERNEL_VERSION + * @capabilities: capabilities of the physical device as a whole + * @device_caps: capabilities accessed via this particular device (node) + * @reserved: reserved fields for future extensions + */ +struct v4l2_capability { + u_int8_t driver[16]; + u_int8_t card[32]; + u_int8_t bus_info[32]; + u_int32_t version; + u_int32_t capabilities; + u_int32_t device_caps; + u_int32_t reserved[3]; +}; + +/* Values for 'capabilities' field */ +#define V4L2_CAP_VIDEO_CAPTURE 0x00000001 /* Is a video capture device */ +#define V4L2_CAP_VIDEO_OUTPUT 0x00000002 /* Is a video output device */ +#define V4L2_CAP_VIDEO_OVERLAY 0x00000004 /* Can do video overlay */ +#define V4L2_CAP_VBI_CAPTURE 0x00000010 /* Is a raw VBI capture device */ +#define V4L2_CAP_VBI_OUTPUT 0x00000020 /* Is a raw VBI output device */ +#define V4L2_CAP_SLICED_VBI_CAPTURE 0x00000040 /* Is a sliced VBI capture device */ +#define V4L2_CAP_SLICED_VBI_OUTPUT 0x00000080 /* Is a sliced VBI output device */ +#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */ +#define V4L2_CAP_VIDEO_OUTPUT_OVERLAY 0x00000200 /* Can do video output overlay */ +#define V4L2_CAP_HW_FREQ_SEEK 0x00000400 /* Can do hardware frequency seek */ +#define V4L2_CAP_RDS_OUTPUT 0x00000800 /* Is an RDS encoder */ + +/* Is a video capture device that supports multiplanar formats */ +#define V4L2_CAP_VIDEO_CAPTURE_MPLANE 0x00001000 +/* Is a video output device that supports multiplanar formats */ +#define V4L2_CAP_VIDEO_OUTPUT_MPLANE 0x00002000 +/* Is a video mem-to-mem device that supports multiplanar formats */ +#define V4L2_CAP_VIDEO_M2M_MPLANE 0x00004000 +/* Is a video mem-to-mem device */ +#define V4L2_CAP_VIDEO_M2M 0x00008000 + +#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */ +#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */ +#define V4L2_CAP_RADIO 0x00040000 /* is a radio device */ +#define V4L2_CAP_MODULATOR 0x00080000 /* has a modulator */ + +#define V4L2_CAP_SDR_CAPTURE 0x00100000 /* Is a SDR capture device */ +#define V4L2_CAP_EXT_PIX_FORMAT 0x00200000 /* Supports the extended pixel format */ +#define V4L2_CAP_SDR_OUTPUT 0x00400000 /* Is a SDR output device */ +#define V4L2_CAP_META_CAPTURE 0x00800000 /* Is a metadata capture device */ + +#define V4L2_CAP_READWRITE 0x01000000 /* read/write systemcalls */ +#define V4L2_CAP_EDID 0x02000000 /* Is an EDID-only device */ +#define V4L2_CAP_STREAMING 0x04000000 /* streaming I/O ioctls */ +#define V4L2_CAP_META_OUTPUT 0x08000000 /* Is a metadata output device */ + +#define V4L2_CAP_TOUCH 0x10000000 /* Is a touch device */ + +#define V4L2_CAP_IO_MC 0x20000000 /* Is input/output controlled by the media controller */ + +#define V4L2_CAP_DEVICE_CAPS 0x80000000 /* sets device capabilities field */ + +/* + * V I D E O I M A G E F O R M A T + */ +struct v4l2_pix_format { + u_int32_t width; + u_int32_t height; + u_int32_t pixelformat; + u_int32_t field; /* enum v4l2_field */ + u_int32_t bytesperline; /* for padding, zero if unused */ + u_int32_t sizeimage; + u_int32_t colorspace; /* enum v4l2_colorspace */ + u_int32_t priv; /* private data, depends on pixelformat */ + u_int32_t flags; /* format flags (V4L2_PIX_FMT_FLAG_*) */ + union { + /* enum v4l2_ycbcr_encoding */ + u_int32_t ycbcr_enc; + /* enum v4l2_hsv_encoding */ + u_int32_t hsv_enc; + }; + u_int32_t quantization; /* enum v4l2_quantization */ + u_int32_t xfer_func; /* enum v4l2_xfer_func */ +}; + +/* Pixel format FOURCC depth Description */ + +/* RGB formats (1 or 2 bytes per pixel) */ +#define V4L2_PIX_FMT_RGB332 v4l2_fourcc('R', 'G', 'B', '1') /* 8 RGB-3-3-2 */ +#define V4L2_PIX_FMT_RGB444 v4l2_fourcc('R', '4', '4', '4') /* 16 xxxxrrrr ggggbbbb */ +#define V4L2_PIX_FMT_ARGB444 v4l2_fourcc('A', 'R', '1', '2') /* 16 aaaarrrr ggggbbbb */ +#define V4L2_PIX_FMT_XRGB444 v4l2_fourcc('X', 'R', '1', '2') /* 16 xxxxrrrr ggggbbbb */ +#define V4L2_PIX_FMT_RGBA444 v4l2_fourcc('R', 'A', '1', '2') /* 16 rrrrgggg bbbbaaaa */ +#define V4L2_PIX_FMT_RGBX444 v4l2_fourcc('R', 'X', '1', '2') /* 16 rrrrgggg bbbbxxxx */ +#define V4L2_PIX_FMT_ABGR444 v4l2_fourcc('A', 'B', '1', '2') /* 16 aaaabbbb ggggrrrr */ +#define V4L2_PIX_FMT_XBGR444 v4l2_fourcc('X', 'B', '1', '2') /* 16 xxxxbbbb ggggrrrr */ +#define V4L2_PIX_FMT_BGRA444 v4l2_fourcc('G', 'A', '1', '2') /* 16 bbbbgggg rrrraaaa */ +#define V4L2_PIX_FMT_BGRX444 v4l2_fourcc('B', 'X', '1', '2') /* 16 bbbbgggg rrrrxxxx */ +#define V4L2_PIX_FMT_RGB555 v4l2_fourcc('R', 'G', 'B', 'O') /* 16 RGB-5-5-5 */ +#define V4L2_PIX_FMT_ARGB555 v4l2_fourcc('A', 'R', '1', '5') /* 16 ARGB-1-5-5-5 */ +#define V4L2_PIX_FMT_XRGB555 v4l2_fourcc('X', 'R', '1', '5') /* 16 XRGB-1-5-5-5 */ +#define V4L2_PIX_FMT_RGBA555 v4l2_fourcc('R', 'A', '1', '5') /* 16 RGBA-5-5-5-1 */ +#define V4L2_PIX_FMT_RGBX555 v4l2_fourcc('R', 'X', '1', '5') /* 16 RGBX-5-5-5-1 */ +#define V4L2_PIX_FMT_ABGR555 v4l2_fourcc('A', 'B', '1', '5') /* 16 ABGR-1-5-5-5 */ +#define V4L2_PIX_FMT_XBGR555 v4l2_fourcc('X', 'B', '1', '5') /* 16 XBGR-1-5-5-5 */ +#define V4L2_PIX_FMT_BGRA555 v4l2_fourcc('B', 'A', '1', '5') /* 16 BGRA-5-5-5-1 */ +#define V4L2_PIX_FMT_BGRX555 v4l2_fourcc('B', 'X', '1', '5') /* 16 BGRX-5-5-5-1 */ +#define V4L2_PIX_FMT_RGB565 v4l2_fourcc('R', 'G', 'B', 'P') /* 16 RGB-5-6-5 */ +#define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R', 'G', 'B', 'Q') /* 16 RGB-5-5-5 BE */ +#define V4L2_PIX_FMT_ARGB555X v4l2_fourcc_be('A', 'R', '1', '5') /* 16 ARGB-5-5-5 BE */ +#define V4L2_PIX_FMT_XRGB555X v4l2_fourcc_be('X', 'R', '1', '5') /* 16 XRGB-5-5-5 BE */ +#define V4L2_PIX_FMT_RGB565X v4l2_fourcc('R', 'G', 'B', 'R') /* 16 RGB-5-6-5 BE */ + +/* RGB formats (3 or 4 bytes per pixel) */ +#define V4L2_PIX_FMT_BGR666 v4l2_fourcc('B', 'G', 'R', 'H') /* 18 BGR-6-6-6 */ +#define V4L2_PIX_FMT_BGR24 v4l2_fourcc('B', 'G', 'R', '3') /* 24 BGR-8-8-8 */ +#define V4L2_PIX_FMT_RGB24 v4l2_fourcc('R', 'G', 'B', '3') /* 24 RGB-8-8-8 */ +#define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B', 'G', 'R', '4') /* 32 BGR-8-8-8-8 */ +#define V4L2_PIX_FMT_ABGR32 v4l2_fourcc('A', 'R', '2', '4') /* 32 BGRA-8-8-8-8 */ +#define V4L2_PIX_FMT_XBGR32 v4l2_fourcc('X', 'R', '2', '4') /* 32 BGRX-8-8-8-8 */ +#define V4L2_PIX_FMT_BGRA32 v4l2_fourcc('R', 'A', '2', '4') /* 32 ABGR-8-8-8-8 */ +#define V4L2_PIX_FMT_BGRX32 v4l2_fourcc('R', 'X', '2', '4') /* 32 XBGR-8-8-8-8 */ +#define V4L2_PIX_FMT_RGB32 v4l2_fourcc('R', 'G', 'B', '4') /* 32 RGB-8-8-8-8 */ +#define V4L2_PIX_FMT_RGBA32 v4l2_fourcc('A', 'B', '2', '4') /* 32 RGBA-8-8-8-8 */ +#define V4L2_PIX_FMT_RGBX32 v4l2_fourcc('X', 'B', '2', '4') /* 32 RGBX-8-8-8-8 */ +#define V4L2_PIX_FMT_ARGB32 v4l2_fourcc('B', 'A', '2', '4') /* 32 ARGB-8-8-8-8 */ +#define V4L2_PIX_FMT_XRGB32 v4l2_fourcc('B', 'X', '2', '4') /* 32 XRGB-8-8-8-8 */ +#define V4L2_PIX_FMT_RGBX1010102 v4l2_fourcc('R', 'X', '3', '0') /* 32 RGBX-10-10-10-2 */ +#define V4L2_PIX_FMT_RGBA1010102 v4l2_fourcc('R', 'A', '3', '0') /* 32 RGBA-10-10-10-2 */ +#define V4L2_PIX_FMT_ARGB2101010 v4l2_fourcc('A', 'R', '3', '0') /* 32 ARGB-2-10-10-10 */ + +/* RGB formats (6 or 8 bytes per pixel) */ +#define V4L2_PIX_FMT_BGR48_12 v4l2_fourcc('B', '3', '1', '2') /* 48 BGR 12-bit per component */ +#define V4L2_PIX_FMT_BGR48 v4l2_fourcc('B', 'G', 'R', '6') /* 48 BGR 16-bit per component */ +#define V4L2_PIX_FMT_RGB48 v4l2_fourcc('R', 'G', 'B', '6') /* 48 RGB 16-bit per component */ +#define V4L2_PIX_FMT_ABGR64_12 v4l2_fourcc('B', '4', '1', '2') /* 64 BGRA 12-bit per component */ + +/* Grey formats */ +#define V4L2_PIX_FMT_GREY v4l2_fourcc('G', 'R', 'E', 'Y') /* 8 Greyscale */ +#define V4L2_PIX_FMT_Y4 v4l2_fourcc('Y', '0', '4', ' ') /* 4 Greyscale */ +#define V4L2_PIX_FMT_Y6 v4l2_fourcc('Y', '0', '6', ' ') /* 6 Greyscale */ +#define V4L2_PIX_FMT_Y10 v4l2_fourcc('Y', '1', '0', ' ') /* 10 Greyscale */ +#define V4L2_PIX_FMT_Y12 v4l2_fourcc('Y', '1', '2', ' ') /* 12 Greyscale */ +#define V4L2_PIX_FMT_Y012 v4l2_fourcc('Y', '0', '1', '2') /* 12 Greyscale */ +#define V4L2_PIX_FMT_Y14 v4l2_fourcc('Y', '1', '4', ' ') /* 14 Greyscale */ +#define V4L2_PIX_FMT_Y16 v4l2_fourcc('Y', '1', '6', ' ') /* 16 Greyscale */ +#define V4L2_PIX_FMT_Y16_BE v4l2_fourcc_be('Y', '1', '6', ' ') /* 16 Greyscale BE */ + +/* Grey bit-packed formats */ +#define V4L2_PIX_FMT_Y10BPACK v4l2_fourcc('Y', '1', '0', 'B') /* 10 Greyscale bit-packed */ +#define V4L2_PIX_FMT_Y10P v4l2_fourcc('Y', '1', '0', 'P') /* 10 Greyscale, MIPI RAW10 packed */ +#define V4L2_PIX_FMT_IPU3_Y10 v4l2_fourcc('i', 'p', '3', 'y') /* IPU3 packed 10-bit greyscale */ +#define V4L2_PIX_FMT_Y12P v4l2_fourcc('Y', '1', '2', 'P') /* 12 Greyscale, MIPI RAW12 packed */ +#define V4L2_PIX_FMT_Y14P v4l2_fourcc('Y', '1', '4', 'P') /* 14 Greyscale, MIPI RAW14 packed */ + +/* Palette formats */ +#define V4L2_PIX_FMT_PAL8 v4l2_fourcc('P', 'A', 'L', '8') /* 8 8-bit palette */ + +/* Chrominance formats */ +#define V4L2_PIX_FMT_UV8 v4l2_fourcc('U', 'V', '8', ' ') /* 8 UV 4:4 */ + +/* Luminance+Chrominance formats */ +#define V4L2_PIX_FMT_YUYV v4l2_fourcc('Y', 'U', 'Y', 'V') /* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_YYUV v4l2_fourcc('Y', 'Y', 'U', 'V') /* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U') /* 16 YVU 4:2:2 */ +#define V4L2_PIX_FMT_UYVY v4l2_fourcc('U', 'Y', 'V', 'Y') /* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_VYUY v4l2_fourcc('V', 'Y', 'U', 'Y') /* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_Y41P v4l2_fourcc('Y', '4', '1', 'P') /* 12 YUV 4:1:1 */ +#define V4L2_PIX_FMT_YUV444 v4l2_fourcc('Y', '4', '4', '4') /* 16 xxxxyyyy uuuuvvvv */ +#define V4L2_PIX_FMT_YUV555 v4l2_fourcc('Y', 'U', 'V', 'O') /* 16 YUV-5-5-5 */ +#define V4L2_PIX_FMT_YUV565 v4l2_fourcc('Y', 'U', 'V', 'P') /* 16 YUV-5-6-5 */ +#define V4L2_PIX_FMT_YUV24 v4l2_fourcc('Y', 'U', 'V', '3') /* 24 YUV-8-8-8 */ +#define V4L2_PIX_FMT_YUV32 v4l2_fourcc('Y', 'U', 'V', '4') /* 32 YUV-8-8-8-8 */ +#define V4L2_PIX_FMT_AYUV32 v4l2_fourcc('A', 'Y', 'U', 'V') /* 32 AYUV-8-8-8-8 */ +#define V4L2_PIX_FMT_XYUV32 v4l2_fourcc('X', 'Y', 'U', 'V') /* 32 XYUV-8-8-8-8 */ +#define V4L2_PIX_FMT_VUYA32 v4l2_fourcc('V', 'U', 'Y', 'A') /* 32 VUYA-8-8-8-8 */ +#define V4L2_PIX_FMT_VUYX32 v4l2_fourcc('V', 'U', 'Y', 'X') /* 32 VUYX-8-8-8-8 */ +#define V4L2_PIX_FMT_YUVA32 v4l2_fourcc('Y', 'U', 'V', 'A') /* 32 YUVA-8-8-8-8 */ +#define V4L2_PIX_FMT_YUVX32 v4l2_fourcc('Y', 'U', 'V', 'X') /* 32 YUVX-8-8-8-8 */ +#define V4L2_PIX_FMT_M420 v4l2_fourcc('M', '4', '2', '0') /* 12 YUV 4:2:0 2 lines y, 1 line uv interleaved */ +#define V4L2_PIX_FMT_YUV48_12 v4l2_fourcc('Y', '3', '1', '2') /* 48 YUV 4:4:4 12-bit per component */ + +/* + * YCbCr packed format. For each Y2xx format, xx bits of valid data occupy the MSBs + * of the 16 bit components, and 16-xx bits of zero padding occupy the LSBs. + */ +#define V4L2_PIX_FMT_Y210 v4l2_fourcc('Y', '2', '1', '0') /* 32 YUYV 4:2:2 */ +#define V4L2_PIX_FMT_Y212 v4l2_fourcc('Y', '2', '1', '2') /* 32 YUYV 4:2:2 */ +#define V4L2_PIX_FMT_Y216 v4l2_fourcc('Y', '2', '1', '6') /* 32 YUYV 4:2:2 */ + +/* two planes -- one Y, one Cr + Cb interleaved */ +#define V4L2_PIX_FMT_NV12 v4l2_fourcc('N', 'V', '1', '2') /* 12 Y/CbCr 4:2:0 */ +#define V4L2_PIX_FMT_NV21 v4l2_fourcc('N', 'V', '2', '1') /* 12 Y/CrCb 4:2:0 */ +#define V4L2_PIX_FMT_NV15 v4l2_fourcc('N', 'V', '1', '5') /* 15 Y/CbCr 4:2:0 10-bit packed */ +#define V4L2_PIX_FMT_NV16 v4l2_fourcc('N', 'V', '1', '6') /* 16 Y/CbCr 4:2:2 */ +#define V4L2_PIX_FMT_NV61 v4l2_fourcc('N', 'V', '6', '1') /* 16 Y/CrCb 4:2:2 */ +#define V4L2_PIX_FMT_NV20 v4l2_fourcc('N', 'V', '2', '0') /* 20 Y/CbCr 4:2:2 10-bit packed */ +#define V4L2_PIX_FMT_NV24 v4l2_fourcc('N', 'V', '2', '4') /* 24 Y/CbCr 4:4:4 */ +#define V4L2_PIX_FMT_NV42 v4l2_fourcc('N', 'V', '4', '2') /* 24 Y/CrCb 4:4:4 */ +#define V4L2_PIX_FMT_P010 v4l2_fourcc('P', '0', '1', '0') /* 24 Y/CbCr 4:2:0 10-bit per component */ +#define V4L2_PIX_FMT_P012 v4l2_fourcc('P', '0', '1', '2') /* 24 Y/CbCr 4:2:0 12-bit per component */ + +/* two non contiguous planes - one Y, one Cr + Cb interleaved */ +#define V4L2_PIX_FMT_NV12M v4l2_fourcc('N', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 */ +#define V4L2_PIX_FMT_NV21M v4l2_fourcc('N', 'M', '2', '1') /* 21 Y/CrCb 4:2:0 */ +#define V4L2_PIX_FMT_NV16M v4l2_fourcc('N', 'M', '1', '6') /* 16 Y/CbCr 4:2:2 */ +#define V4L2_PIX_FMT_NV61M v4l2_fourcc('N', 'M', '6', '1') /* 16 Y/CrCb 4:2:2 */ +#define V4L2_PIX_FMT_P012M v4l2_fourcc('P', 'M', '1', '2') /* 24 Y/CbCr 4:2:0 12-bit per component */ + +/* three planes - Y Cb, Cr */ +#define V4L2_PIX_FMT_YUV410 v4l2_fourcc('Y', 'U', 'V', '9') /* 9 YUV 4:1:0 */ +#define V4L2_PIX_FMT_YVU410 v4l2_fourcc('Y', 'V', 'U', '9') /* 9 YVU 4:1:0 */ +#define V4L2_PIX_FMT_YUV411P v4l2_fourcc('4', '1', '1', 'P') /* 12 YVU411 planar */ +#define V4L2_PIX_FMT_YUV420 v4l2_fourcc('Y', 'U', '1', '2') /* 12 YUV 4:2:0 */ +#define V4L2_PIX_FMT_YVU420 v4l2_fourcc('Y', 'V', '1', '2') /* 12 YVU 4:2:0 */ +#define V4L2_PIX_FMT_YUV422P v4l2_fourcc('4', '2', '2', 'P') /* 16 YVU422 planar */ + +/* three non contiguous planes - Y, Cb, Cr */ +#define V4L2_PIX_FMT_YUV420M v4l2_fourcc('Y', 'M', '1', '2') /* 12 YUV420 planar */ +#define V4L2_PIX_FMT_YVU420M v4l2_fourcc('Y', 'M', '2', '1') /* 12 YVU420 planar */ +#define V4L2_PIX_FMT_YUV422M v4l2_fourcc('Y', 'M', '1', '6') /* 16 YUV422 planar */ +#define V4L2_PIX_FMT_YVU422M v4l2_fourcc('Y', 'M', '6', '1') /* 16 YVU422 planar */ +#define V4L2_PIX_FMT_YUV444M v4l2_fourcc('Y', 'M', '2', '4') /* 24 YUV444 planar */ +#define V4L2_PIX_FMT_YVU444M v4l2_fourcc('Y', 'M', '4', '2') /* 24 YVU444 planar */ + +/* Tiled YUV formats */ +#define V4L2_PIX_FMT_NV12_4L4 v4l2_fourcc('V', 'T', '1', '2') /* 12 Y/CbCr 4:2:0 4x4 tiles */ +#define V4L2_PIX_FMT_NV12_16L16 v4l2_fourcc('H', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 16x16 tiles */ +#define V4L2_PIX_FMT_NV12_32L32 v4l2_fourcc('S', 'T', '1', '2') /* 12 Y/CbCr 4:2:0 32x32 tiles */ +#define V4L2_PIX_FMT_NV15_4L4 v4l2_fourcc('V', 'T', '1', '5') /* 15 Y/CbCr 4:2:0 10-bit 4x4 tiles */ +#define V4L2_PIX_FMT_P010_4L4 v4l2_fourcc('T', '0', '1', '0') /* 12 Y/CbCr 4:2:0 10-bit 4x4 macroblocks */ +#define V4L2_PIX_FMT_NV12_8L128 v4l2_fourcc('A', 'T', '1', '2') /* Y/CbCr 4:2:0 8x128 tiles */ +#define V4L2_PIX_FMT_NV12_10BE_8L128 v4l2_fourcc_be('A', 'X', '1', '2') /* Y/CbCr 4:2:0 10-bit 8x128 tiles */ + +/* Tiled YUV formats, non contiguous planes */ +#define V4L2_PIX_FMT_NV12MT v4l2_fourcc('T', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 64x32 tiles */ +#define V4L2_PIX_FMT_NV12MT_16X16 v4l2_fourcc('V', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 16x16 tiles */ +#define V4L2_PIX_FMT_NV12M_8L128 v4l2_fourcc('N', 'A', '1', '2') /* Y/CbCr 4:2:0 8x128 tiles */ +#define V4L2_PIX_FMT_NV12M_10BE_8L128 v4l2_fourcc_be('N', 'T', '1', '2') /* Y/CbCr 4:2:0 10-bit 8x128 tiles */ + +/* Bayer formats - see http://www.siliconimaging.com/RGB%20Bayer.htm */ +#define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B', 'A', '8', '1') /* 8 BGBG.. GRGR.. */ +#define V4L2_PIX_FMT_SGBRG8 v4l2_fourcc('G', 'B', 'R', 'G') /* 8 GBGB.. RGRG.. */ +#define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G', 'R', 'B', 'G') /* 8 GRGR.. BGBG.. */ +#define V4L2_PIX_FMT_SRGGB8 v4l2_fourcc('R', 'G', 'G', 'B') /* 8 RGRG.. GBGB.. */ +#define V4L2_PIX_FMT_SBGGR10 v4l2_fourcc('B', 'G', '1', '0') /* 10 BGBG.. GRGR.. */ +#define V4L2_PIX_FMT_SGBRG10 v4l2_fourcc('G', 'B', '1', '0') /* 10 GBGB.. RGRG.. */ +#define V4L2_PIX_FMT_SGRBG10 v4l2_fourcc('B', 'A', '1', '0') /* 10 GRGR.. BGBG.. */ +#define V4L2_PIX_FMT_SRGGB10 v4l2_fourcc('R', 'G', '1', '0') /* 10 RGRG.. GBGB.. */ + /* 10bit raw bayer packed, 5 bytes for every 4 pixels */ +#define V4L2_PIX_FMT_SBGGR10P v4l2_fourcc('p', 'B', 'A', 'A') +#define V4L2_PIX_FMT_SGBRG10P v4l2_fourcc('p', 'G', 'A', 'A') +#define V4L2_PIX_FMT_SGRBG10P v4l2_fourcc('p', 'g', 'A', 'A') +#define V4L2_PIX_FMT_SRGGB10P v4l2_fourcc('p', 'R', 'A', 'A') + /* 10bit raw bayer a-law compressed to 8 bits */ +#define V4L2_PIX_FMT_SBGGR10ALAW8 v4l2_fourcc('a', 'B', 'A', '8') +#define V4L2_PIX_FMT_SGBRG10ALAW8 v4l2_fourcc('a', 'G', 'A', '8') +#define V4L2_PIX_FMT_SGRBG10ALAW8 v4l2_fourcc('a', 'g', 'A', '8') +#define V4L2_PIX_FMT_SRGGB10ALAW8 v4l2_fourcc('a', 'R', 'A', '8') + /* 10bit raw bayer DPCM compressed to 8 bits */ +#define V4L2_PIX_FMT_SBGGR10DPCM8 v4l2_fourcc('b', 'B', 'A', '8') +#define V4L2_PIX_FMT_SGBRG10DPCM8 v4l2_fourcc('b', 'G', 'A', '8') +#define V4L2_PIX_FMT_SGRBG10DPCM8 v4l2_fourcc('B', 'D', '1', '0') +#define V4L2_PIX_FMT_SRGGB10DPCM8 v4l2_fourcc('b', 'R', 'A', '8') +#define V4L2_PIX_FMT_SBGGR12 v4l2_fourcc('B', 'G', '1', '2') /* 12 BGBG.. GRGR.. */ +#define V4L2_PIX_FMT_SGBRG12 v4l2_fourcc('G', 'B', '1', '2') /* 12 GBGB.. RGRG.. */ +#define V4L2_PIX_FMT_SGRBG12 v4l2_fourcc('B', 'A', '1', '2') /* 12 GRGR.. BGBG.. */ +#define V4L2_PIX_FMT_SRGGB12 v4l2_fourcc('R', 'G', '1', '2') /* 12 RGRG.. GBGB.. */ + /* 12bit raw bayer packed, 3 bytes for every 2 pixels */ +#define V4L2_PIX_FMT_SBGGR12P v4l2_fourcc('p', 'B', 'C', 'C') +#define V4L2_PIX_FMT_SGBRG12P v4l2_fourcc('p', 'G', 'C', 'C') +#define V4L2_PIX_FMT_SGRBG12P v4l2_fourcc('p', 'g', 'C', 'C') +#define V4L2_PIX_FMT_SRGGB12P v4l2_fourcc('p', 'R', 'C', 'C') +#define V4L2_PIX_FMT_SBGGR14 v4l2_fourcc('B', 'G', '1', '4') /* 14 BGBG.. GRGR.. */ +#define V4L2_PIX_FMT_SGBRG14 v4l2_fourcc('G', 'B', '1', '4') /* 14 GBGB.. RGRG.. */ +#define V4L2_PIX_FMT_SGRBG14 v4l2_fourcc('G', 'R', '1', '4') /* 14 GRGR.. BGBG.. */ +#define V4L2_PIX_FMT_SRGGB14 v4l2_fourcc('R', 'G', '1', '4') /* 14 RGRG.. GBGB.. */ + /* 14bit raw bayer packed, 7 bytes for every 4 pixels */ +#define V4L2_PIX_FMT_SBGGR14P v4l2_fourcc('p', 'B', 'E', 'E') +#define V4L2_PIX_FMT_SGBRG14P v4l2_fourcc('p', 'G', 'E', 'E') +#define V4L2_PIX_FMT_SGRBG14P v4l2_fourcc('p', 'g', 'E', 'E') +#define V4L2_PIX_FMT_SRGGB14P v4l2_fourcc('p', 'R', 'E', 'E') +#define V4L2_PIX_FMT_SBGGR16 v4l2_fourcc('B', 'Y', 'R', '2') /* 16 BGBG.. GRGR.. */ +#define V4L2_PIX_FMT_SGBRG16 v4l2_fourcc('G', 'B', '1', '6') /* 16 GBGB.. RGRG.. */ +#define V4L2_PIX_FMT_SGRBG16 v4l2_fourcc('G', 'R', '1', '6') /* 16 GRGR.. BGBG.. */ +#define V4L2_PIX_FMT_SRGGB16 v4l2_fourcc('R', 'G', '1', '6') /* 16 RGRG.. GBGB.. */ + +/* HSV formats */ +#define V4L2_PIX_FMT_HSV24 v4l2_fourcc('H', 'S', 'V', '3') +#define V4L2_PIX_FMT_HSV32 v4l2_fourcc('H', 'S', 'V', '4') + +/* compressed formats */ +#define V4L2_PIX_FMT_MJPEG v4l2_fourcc('M', 'J', 'P', 'G') /* Motion-JPEG */ +#define V4L2_PIX_FMT_JPEG v4l2_fourcc('J', 'P', 'E', 'G') /* JFIF JPEG */ +#define V4L2_PIX_FMT_DV v4l2_fourcc('d', 'v', 's', 'd') /* 1394 */ +#define V4L2_PIX_FMT_MPEG v4l2_fourcc('M', 'P', 'E', 'G') /* MPEG-1/2/4 Multiplexed */ +#define V4L2_PIX_FMT_H264 v4l2_fourcc('H', '2', '6', '4') /* H264 with start codes */ +#define V4L2_PIX_FMT_H264_NO_SC v4l2_fourcc('A', 'V', 'C', '1') /* H264 without start codes */ +#define V4L2_PIX_FMT_H264_MVC v4l2_fourcc('M', '2', '6', '4') /* H264 MVC */ +#define V4L2_PIX_FMT_H263 v4l2_fourcc('H', '2', '6', '3') /* H263 */ +#define V4L2_PIX_FMT_MPEG1 v4l2_fourcc('M', 'P', 'G', '1') /* MPEG-1 ES */ +#define V4L2_PIX_FMT_MPEG2 v4l2_fourcc('M', 'P', 'G', '2') /* MPEG-2 ES */ +#define V4L2_PIX_FMT_MPEG2_SLICE v4l2_fourcc('M', 'G', '2', 'S') /* MPEG-2 parsed slice data */ +#define V4L2_PIX_FMT_MPEG4 v4l2_fourcc('M', 'P', 'G', '4') /* MPEG-4 part 2 ES */ +#define V4L2_PIX_FMT_XVID v4l2_fourcc('X', 'V', 'I', 'D') /* Xvid */ +#define V4L2_PIX_FMT_VC1_ANNEX_G v4l2_fourcc('V', 'C', '1', 'G') /* SMPTE 421M Annex G compliant stream */ +#define V4L2_PIX_FMT_VC1_ANNEX_L v4l2_fourcc('V', 'C', '1', 'L') /* SMPTE 421M Annex L compliant stream */ +#define V4L2_PIX_FMT_VP8 v4l2_fourcc('V', 'P', '8', '0') /* VP8 */ +#define V4L2_PIX_FMT_VP8_FRAME v4l2_fourcc('V', 'P', '8', 'F') /* VP8 parsed frame */ +#define V4L2_PIX_FMT_VP9 v4l2_fourcc('V', 'P', '9', '0') /* VP9 */ +#define V4L2_PIX_FMT_VP9_FRAME v4l2_fourcc('V', 'P', '9', 'F') /* VP9 parsed frame */ +#define V4L2_PIX_FMT_HEVC v4l2_fourcc('H', 'E', 'V', 'C') /* HEVC aka H.265 */ +#define V4L2_PIX_FMT_FWHT v4l2_fourcc('F', 'W', 'H', 'T') /* Fast Walsh Hadamard Transform (vicodec) */ +#define V4L2_PIX_FMT_FWHT_STATELESS v4l2_fourcc('S', 'F', 'W', 'H') /* Stateless FWHT (vicodec) */ +#define V4L2_PIX_FMT_H264_SLICE v4l2_fourcc('S', '2', '6', '4') /* H264 parsed slices */ +#define V4L2_PIX_FMT_HEVC_SLICE v4l2_fourcc('S', '2', '6', '5') /* HEVC parsed slices */ +#define V4L2_PIX_FMT_AV1_FRAME v4l2_fourcc('A', 'V', '1', 'F') /* AV1 parsed frame */ +#define V4L2_PIX_FMT_SPK v4l2_fourcc('S', 'P', 'K', '0') /* Sorenson Spark */ +#define V4L2_PIX_FMT_RV30 v4l2_fourcc('R', 'V', '3', '0') /* RealVideo 8 */ +#define V4L2_PIX_FMT_RV40 v4l2_fourcc('R', 'V', '4', '0') /* RealVideo 9 & 10 */ + +/* Vendor-specific formats */ +#define V4L2_PIX_FMT_CPIA1 v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */ +#define V4L2_PIX_FMT_WNVA v4l2_fourcc('W', 'N', 'V', 'A') /* Winnov hw compress */ +#define V4L2_PIX_FMT_SN9C10X v4l2_fourcc('S', '9', '1', '0') /* SN9C10x compression */ +#define V4L2_PIX_FMT_SN9C20X_I420 v4l2_fourcc('S', '9', '2', '0') /* SN9C20x YUV 4:2:0 */ +#define V4L2_PIX_FMT_PWC1 v4l2_fourcc('P', 'W', 'C', '1') /* pwc older webcam */ +#define V4L2_PIX_FMT_PWC2 v4l2_fourcc('P', 'W', 'C', '2') /* pwc newer webcam */ +#define V4L2_PIX_FMT_ET61X251 v4l2_fourcc('E', '6', '2', '5') /* ET61X251 compression */ +#define V4L2_PIX_FMT_SPCA501 v4l2_fourcc('S', '5', '0', '1') /* YUYV per line */ +#define V4L2_PIX_FMT_SPCA505 v4l2_fourcc('S', '5', '0', '5') /* YYUV per line */ +#define V4L2_PIX_FMT_SPCA508 v4l2_fourcc('S', '5', '0', '8') /* YUVY per line */ +#define V4L2_PIX_FMT_SPCA561 v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */ +#define V4L2_PIX_FMT_PAC207 v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */ +#define V4L2_PIX_FMT_MR97310A v4l2_fourcc('M', '3', '1', '0') /* compressed BGGR bayer */ +#define V4L2_PIX_FMT_JL2005BCD v4l2_fourcc('J', 'L', '2', '0') /* compressed RGGB bayer */ +#define V4L2_PIX_FMT_SN9C2028 v4l2_fourcc('S', 'O', 'N', 'X') /* compressed GBRG bayer */ +#define V4L2_PIX_FMT_SQ905C v4l2_fourcc('9', '0', '5', 'C') /* compressed RGGB bayer */ +#define V4L2_PIX_FMT_PJPG v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */ +#define V4L2_PIX_FMT_OV511 v4l2_fourcc('O', '5', '1', '1') /* ov511 JPEG */ +#define V4L2_PIX_FMT_OV518 v4l2_fourcc('O', '5', '1', '8') /* ov518 JPEG */ +#define V4L2_PIX_FMT_STV0680 v4l2_fourcc('S', '6', '8', '0') /* stv0680 bayer */ +#define V4L2_PIX_FMT_TM6000 v4l2_fourcc('T', 'M', '6', '0') /* tm5600/tm60x0 */ +#define V4L2_PIX_FMT_CIT_YYVYUY v4l2_fourcc('C', 'I', 'T', 'V') /* one line of Y then 1 line of VYUY */ +#define V4L2_PIX_FMT_KONICA420 v4l2_fourcc('K', 'O', 'N', 'I') /* YUV420 planar in blocks of 256 pixels */ +#define V4L2_PIX_FMT_JPGL v4l2_fourcc('J', 'P', 'G', 'L') /* JPEG-Lite */ +#define V4L2_PIX_FMT_SE401 v4l2_fourcc('S', '4', '0', '1') /* se401 janggu compressed rgb */ +#define V4L2_PIX_FMT_S5C_UYVY_JPG v4l2_fourcc('S', '5', 'C', 'I') /* S5C73M3 interleaved UYVY/JPEG */ +#define V4L2_PIX_FMT_Y8I v4l2_fourcc('Y', '8', 'I', ' ') /* Greyscale 8-bit L/R interleaved */ +#define V4L2_PIX_FMT_Y12I v4l2_fourcc('Y', '1', '2', 'I') /* Greyscale 12-bit L/R interleaved */ +#define V4L2_PIX_FMT_Y16I v4l2_fourcc('Y', '1', '6', 'I') /* Greyscale 16-bit L/R interleaved */ +#define V4L2_PIX_FMT_Z16 v4l2_fourcc('Z', '1', '6', ' ') /* Depth data 16-bit */ +#define V4L2_PIX_FMT_MT21C v4l2_fourcc('M', 'T', '2', '1') /* Mediatek compressed block mode */ +#define V4L2_PIX_FMT_MM21 v4l2_fourcc('M', 'M', '2', '1') /* Mediatek 8-bit block mode, two non-contiguous planes */ +#define V4L2_PIX_FMT_MT2110T v4l2_fourcc('M', 'T', '2', 'T') /* Mediatek 10-bit block tile mode */ +#define V4L2_PIX_FMT_MT2110R v4l2_fourcc('M', 'T', '2', 'R') /* Mediatek 10-bit block raster mode */ +#define V4L2_PIX_FMT_INZI v4l2_fourcc('I', 'N', 'Z', 'I') /* Intel Planar Greyscale 10-bit and Depth 16-bit */ +#define V4L2_PIX_FMT_CNF4 v4l2_fourcc('C', 'N', 'F', '4') /* Intel 4-bit packed depth confidence information */ +#define V4L2_PIX_FMT_HI240 v4l2_fourcc('H', 'I', '2', '4') /* BTTV 8-bit dithered RGB */ +#define V4L2_PIX_FMT_QC08C v4l2_fourcc('Q', '0', '8', 'C') /* Qualcomm 8-bit compressed */ +#define V4L2_PIX_FMT_QC10C v4l2_fourcc('Q', '1', '0', 'C') /* Qualcomm 10-bit compressed */ +#define V4L2_PIX_FMT_AJPG v4l2_fourcc('A', 'J', 'P', 'G') /* Aspeed JPEG */ +#define V4L2_PIX_FMT_HEXTILE v4l2_fourcc('H', 'X', 'T', 'L') /* Hextile compressed */ + +/* 10bit raw packed, 32 bytes for every 25 pixels, last LSB 6 bits unused */ +#define V4L2_PIX_FMT_IPU3_SBGGR10 v4l2_fourcc('i', 'p', '3', 'b') /* IPU3 packed 10-bit BGGR bayer */ +#define V4L2_PIX_FMT_IPU3_SGBRG10 v4l2_fourcc('i', 'p', '3', 'g') /* IPU3 packed 10-bit GBRG bayer */ +#define V4L2_PIX_FMT_IPU3_SGRBG10 v4l2_fourcc('i', 'p', '3', 'G') /* IPU3 packed 10-bit GRBG bayer */ +#define V4L2_PIX_FMT_IPU3_SRGGB10 v4l2_fourcc('i', 'p', '3', 'r') /* IPU3 packed 10-bit RGGB bayer */ + +/* Raspberry Pi PiSP compressed formats. */ +#define V4L2_PIX_FMT_PISP_COMP1_RGGB v4l2_fourcc('P', 'C', '1', 'R') /* PiSP 8-bit mode 1 compressed RGGB bayer */ +#define V4L2_PIX_FMT_PISP_COMP1_GRBG v4l2_fourcc('P', 'C', '1', 'G') /* PiSP 8-bit mode 1 compressed GRBG bayer */ +#define V4L2_PIX_FMT_PISP_COMP1_GBRG v4l2_fourcc('P', 'C', '1', 'g') /* PiSP 8-bit mode 1 compressed GBRG bayer */ +#define V4L2_PIX_FMT_PISP_COMP1_BGGR v4l2_fourcc('P', 'C', '1', 'B') /* PiSP 8-bit mode 1 compressed BGGR bayer */ +#define V4L2_PIX_FMT_PISP_COMP1_MONO v4l2_fourcc('P', 'C', '1', 'M') /* PiSP 8-bit mode 1 compressed monochrome */ +#define V4L2_PIX_FMT_PISP_COMP2_RGGB v4l2_fourcc('P', 'C', '2', 'R') /* PiSP 8-bit mode 2 compressed RGGB bayer */ +#define V4L2_PIX_FMT_PISP_COMP2_GRBG v4l2_fourcc('P', 'C', '2', 'G') /* PiSP 8-bit mode 2 compressed GRBG bayer */ +#define V4L2_PIX_FMT_PISP_COMP2_GBRG v4l2_fourcc('P', 'C', '2', 'g') /* PiSP 8-bit mode 2 compressed GBRG bayer */ +#define V4L2_PIX_FMT_PISP_COMP2_BGGR v4l2_fourcc('P', 'C', '2', 'B') /* PiSP 8-bit mode 2 compressed BGGR bayer */ +#define V4L2_PIX_FMT_PISP_COMP2_MONO v4l2_fourcc('P', 'C', '2', 'M') /* PiSP 8-bit mode 2 compressed monochrome */ + +/* Renesas RZ/V2H CRU packed formats. 64-bit units with contiguous pixels */ +#define V4L2_PIX_FMT_RAW_CRU10 v4l2_fourcc('C', 'R', '1', '0') +#define V4L2_PIX_FMT_RAW_CRU12 v4l2_fourcc('C', 'R', '1', '2') +#define V4L2_PIX_FMT_RAW_CRU14 v4l2_fourcc('C', 'R', '1', '4') +#define V4L2_PIX_FMT_RAW_CRU20 v4l2_fourcc('C', 'R', '2', '0') + +/* SDR formats - used only for Software Defined Radio devices */ +#define V4L2_SDR_FMT_CU8 v4l2_fourcc('C', 'U', '0', '8') /* IQ u8 */ +#define V4L2_SDR_FMT_CU16LE v4l2_fourcc('C', 'U', '1', '6') /* IQ u16le */ +#define V4L2_SDR_FMT_CS8 v4l2_fourcc('C', 'S', '0', '8') /* complex s8 */ +#define V4L2_SDR_FMT_CS14LE v4l2_fourcc('C', 'S', '1', '4') /* complex s14le */ +#define V4L2_SDR_FMT_RU12LE v4l2_fourcc('R', 'U', '1', '2') /* real u12le */ +#define V4L2_SDR_FMT_PCU16BE v4l2_fourcc('P', 'C', '1', '6') /* planar complex u16be */ +#define V4L2_SDR_FMT_PCU18BE v4l2_fourcc('P', 'C', '1', '8') /* planar complex u18be */ +#define V4L2_SDR_FMT_PCU20BE v4l2_fourcc('P', 'C', '2', '0') /* planar complex u20be */ + +/* Touch formats - used for Touch devices */ +#define V4L2_TCH_FMT_DELTA_TD16 v4l2_fourcc('T', 'D', '1', '6') /* 16-bit signed deltas */ +#define V4L2_TCH_FMT_DELTA_TD08 v4l2_fourcc('T', 'D', '0', '8') /* 8-bit signed deltas */ +#define V4L2_TCH_FMT_TU16 v4l2_fourcc('T', 'U', '1', '6') /* 16-bit unsigned touch data */ +#define V4L2_TCH_FMT_TU08 v4l2_fourcc('T', 'U', '0', '8') /* 8-bit unsigned touch data */ + +/* Meta-data formats */ +#define V4L2_META_FMT_VSP1_HGO v4l2_fourcc('V', 'S', 'P', 'H') /* R-Car VSP1 1-D Histogram */ +#define V4L2_META_FMT_VSP1_HGT v4l2_fourcc('V', 'S', 'P', 'T') /* R-Car VSP1 2-D Histogram */ +#define V4L2_META_FMT_UVC v4l2_fourcc('U', 'V', 'C', 'H') /* UVC Payload Header metadata */ +#define V4L2_META_FMT_D4XX v4l2_fourcc('D', '4', 'X', 'X') /* D4XX Payload Header metadata */ +#define V4L2_META_FMT_UVC_MSXU_1_5 v4l2_fourcc('U', 'V', 'C', 'M') /* UVC MSXU metadata */ +#define V4L2_META_FMT_VIVID v4l2_fourcc('V', 'I', 'V', 'D') /* Vivid Metadata */ + +/* Vendor specific - used for RK_ISP1 camera sub-system */ +#define V4L2_META_FMT_RK_ISP1_PARAMS v4l2_fourcc('R', 'K', '1', 'P') /* Rockchip ISP1 3A Parameters */ +#define V4L2_META_FMT_RK_ISP1_STAT_3A v4l2_fourcc('R', 'K', '1', 'S') /* Rockchip ISP1 3A Statistics */ +#define V4L2_META_FMT_RK_ISP1_EXT_PARAMS v4l2_fourcc('R', 'K', '1', 'E') /* Rockchip ISP1 3a Extensible Parameters */ + +/* Vendor specific - used for C3_ISP */ +#define V4L2_META_FMT_C3ISP_PARAMS v4l2_fourcc('C', '3', 'P', 'M') /* Amlogic C3 ISP Parameters */ +#define V4L2_META_FMT_C3ISP_STATS v4l2_fourcc('C', '3', 'S', 'T') /* Amlogic C3 ISP Statistics */ + +/* Vendor specific - used for RaspberryPi PiSP */ +#define V4L2_META_FMT_RPI_BE_CFG v4l2_fourcc('R', 'P', 'B', 'C') /* PiSP BE configuration */ +#define V4L2_META_FMT_RPI_FE_CFG v4l2_fourcc('R', 'P', 'F', 'C') /* PiSP FE configuration */ +#define V4L2_META_FMT_RPI_FE_STATS v4l2_fourcc('R', 'P', 'F', 'S') /* PiSP FE stats */ + +/* priv field value to indicates that subsequent fields are valid. */ +#define V4L2_PIX_FMT_PRIV_MAGIC 0xfeedcafe + +/* Flags */ +#define V4L2_PIX_FMT_FLAG_PREMUL_ALPHA 0x00000001 +#define V4L2_PIX_FMT_FLAG_SET_CSC 0x00000002 + +/* + * F O R M A T E N U M E R A T I O N + */ +struct v4l2_fmtdesc { + u_int32_t index; /* Format number */ + u_int32_t type; /* enum v4l2_buf_type */ + u_int32_t flags; + u_int8_t description[32]; /* Description string */ + u_int32_t pixelformat; /* Format fourcc */ + u_int32_t mbus_code; /* Media bus code */ + u_int32_t reserved[3]; +}; + +#define V4L2_FMT_FLAG_COMPRESSED 0x0001 +#define V4L2_FMT_FLAG_EMULATED 0x0002 +#define V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM 0x0004 +#define V4L2_FMT_FLAG_DYN_RESOLUTION 0x0008 +#define V4L2_FMT_FLAG_ENC_CAP_FRAME_INTERVAL 0x0010 +#define V4L2_FMT_FLAG_CSC_COLORSPACE 0x0020 +#define V4L2_FMT_FLAG_CSC_XFER_FUNC 0x0040 +#define V4L2_FMT_FLAG_CSC_YCBCR_ENC 0x0080 +#define V4L2_FMT_FLAG_CSC_HSV_ENC V4L2_FMT_FLAG_CSC_YCBCR_ENC +#define V4L2_FMT_FLAG_CSC_QUANTIZATION 0x0100 +#define V4L2_FMT_FLAG_META_LINE_BASED 0x0200 + +/* Format description flag, to be ORed with the index */ +#define V4L2_FMTDESC_FLAG_ENUM_ALL 0x80000000 + + /* Frame Size and frame rate enumeration */ +/* + * F R A M E S I Z E E N U M E R A T I O N + */ +enum v4l2_frmsizetypes { + V4L2_FRMSIZE_TYPE_DISCRETE = 1, + V4L2_FRMSIZE_TYPE_CONTINUOUS = 2, + V4L2_FRMSIZE_TYPE_STEPWISE = 3, +}; + +struct v4l2_frmsize_discrete { + u_int32_t width; /* Frame width [pixel] */ + u_int32_t height; /* Frame height [pixel] */ +}; + +struct v4l2_frmsize_stepwise { + u_int32_t min_width; /* Minimum frame width [pixel] */ + u_int32_t max_width; /* Maximum frame width [pixel] */ + u_int32_t step_width; /* Frame width step size [pixel] */ + u_int32_t min_height; /* Minimum frame height [pixel] */ + u_int32_t max_height; /* Maximum frame height [pixel] */ + u_int32_t step_height; /* Frame height step size [pixel] */ +}; + +struct v4l2_frmsizeenum { + u_int32_t index; /* Frame size number */ + u_int32_t pixel_format; /* Pixel format */ + u_int32_t type; /* Frame size type the device supports. */ + + union { /* Frame size */ + struct v4l2_frmsize_discrete discrete; + struct v4l2_frmsize_stepwise stepwise; + }; + + u_int32_t reserved[2]; /* Reserved space for future use */ +}; + +/* + * F R A M E R A T E E N U M E R A T I O N + */ +enum v4l2_frmivaltypes { + V4L2_FRMIVAL_TYPE_DISCRETE = 1, + V4L2_FRMIVAL_TYPE_CONTINUOUS = 2, + V4L2_FRMIVAL_TYPE_STEPWISE = 3, +}; + +struct v4l2_frmival_stepwise { + struct v4l2_fract min; /* Minimum frame interval [s] */ + struct v4l2_fract max; /* Maximum frame interval [s] */ + struct v4l2_fract step; /* Frame interval step size [s] */ +}; + +struct v4l2_frmivalenum { + u_int32_t index; /* Frame format index */ + u_int32_t pixel_format; /* Pixel format */ + u_int32_t width; /* Frame width */ + u_int32_t height; /* Frame height */ + u_int32_t type; /* Frame interval type the device supports. */ + + union { /* Frame interval */ + struct v4l2_fract discrete; + struct v4l2_frmival_stepwise stepwise; + }; + + u_int32_t reserved[2]; /* Reserved space for future use */ +}; + +/* + * T I M E C O D E + */ +struct v4l2_timecode { + u_int32_t type; + u_int32_t flags; + u_int8_t frames; + u_int8_t seconds; + u_int8_t minutes; + u_int8_t hours; + u_int8_t userbits[4]; +}; + +/* Type */ +#define V4L2_TC_TYPE_24FPS 1 +#define V4L2_TC_TYPE_25FPS 2 +#define V4L2_TC_TYPE_30FPS 3 +#define V4L2_TC_TYPE_50FPS 4 +#define V4L2_TC_TYPE_60FPS 5 + +/* Flags */ +#define V4L2_TC_FLAG_DROPFRAME 0x0001 /* "drop-frame" mode */ +#define V4L2_TC_FLAG_COLORFRAME 0x0002 +#define V4L2_TC_USERBITS_field 0x000C +#define V4L2_TC_USERBITS_USERDEFINED 0x0000 +#define V4L2_TC_USERBITS_8BITCHARS 0x0008 +/* The above is based on SMPTE timecodes */ + +struct v4l2_jpegcompression { + int quality; + + int APPn; /* Number of APP segment to be written, + * must be 0..15 */ + int APP_len; /* Length of data in JPEG APPn segment */ + char APP_data[60]; /* Data in the JPEG APPn segment. */ + + int COM_len; /* Length of data in JPEG COM segment */ + char COM_data[60]; /* Data in JPEG COM segment */ + + u_int32_t jpeg_markers; /* Which markers should go into the JPEG + * output. Unless you exactly know what + * you do, leave them untouched. + * Including less markers will make the + * resulting code smaller, but there will + * be fewer applications which can read it. + * The presence of the APP and COM marker + * is influenced by APP_len and COM_len + * ONLY, not by this property! */ + +#define V4L2_JPEG_MARKER_DHT (1<<3) /* Define Huffman Tables */ +#define V4L2_JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */ +#define V4L2_JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ +#define V4L2_JPEG_MARKER_COM (1<<6) /* Comment segment */ +#define V4L2_JPEG_MARKER_APP (1<<7) /* App segment, driver will + * always use APP0 */ +}; + +/* + * M E M O R Y - M A P P I N G B U F F E R S + */ + +struct v4l2_requestbuffers { + u_int32_t count; + u_int32_t type; /* enum v4l2_buf_type */ + u_int32_t memory; /* enum v4l2_memory */ + u_int32_t capabilities; + u_int8_t flags; + u_int8_t reserved[3]; +}; + +#define V4L2_MEMORY_FLAG_NON_COHERENT (1 << 0) + +/* capabilities for struct v4l2_requestbuffers and v4l2_create_buffers */ +#define V4L2_BUF_CAP_SUPPORTS_MMAP (1 << 0) +#define V4L2_BUF_CAP_SUPPORTS_USERPTR (1 << 1) +#define V4L2_BUF_CAP_SUPPORTS_DMABUF (1 << 2) +#define V4L2_BUF_CAP_SUPPORTS_REQUESTS (1 << 3) +#define V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS (1 << 4) +#define V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF (1 << 5) +#define V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS (1 << 6) +#define V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS (1 << 7) +#define V4L2_BUF_CAP_SUPPORTS_REMOVE_BUFS (1 << 8) + +/** + * struct v4l2_plane - plane info for multi-planar buffers + * @bytesused: number of bytes occupied by data in the plane (payload) + * @length: size of this plane (NOT the payload) in bytes + * @m.mem_offset: when memory in the associated struct v4l2_buffer is + * V4L2_MEMORY_MMAP, equals the offset from the start of + * the device memory for this plane (or is a "cookie" that + * should be passed to mmap() called on the video node) + * @m.userptr: when memory is V4L2_MEMORY_USERPTR, a userspace pointer + * pointing to this plane + * @m.fd: when memory is V4L2_MEMORY_DMABUF, a userspace file + * descriptor associated with this plane + * @m: union of @mem_offset, @userptr and @fd + * @data_offset: offset in the plane to the start of data; usually 0, + * unless there is a header in front of the data + * @reserved: drivers and applications must zero this array + * + * Multi-planar buffers consist of one or more planes, e.g. an YCbCr buffer + * with two planes can have one plane for Y, and another for interleaved CbCr + * components. Each plane can reside in a separate memory buffer, or even in + * a completely separate memory node (e.g. in embedded devices). + */ +struct v4l2_plane { + u_int32_t bytesused; + u_int32_t length; + union { + u_int32_t mem_offset; + unsigned long userptr; + int32_t fd; + } m; + u_int32_t data_offset; + u_int32_t reserved[11]; +}; + +/** + * struct v4l2_buffer - video buffer info + * @index: id number of the buffer + * @type: enum v4l2_buf_type; buffer type (type == *_MPLANE for + * multiplanar buffers); + * @bytesused: number of bytes occupied by data in the buffer (payload); + * unused (set to 0) for multiplanar buffers + * @flags: buffer informational flags + * @field: enum v4l2_field; field order of the image in the buffer + * @timestamp: frame timestamp + * @timecode: frame timecode + * @sequence: sequence count of this frame + * @memory: enum v4l2_memory; the method, in which the actual video data is + * passed + * @m.offset: for non-multiplanar buffers with memory == V4L2_MEMORY_MMAP; + * offset from the start of the device memory for this plane, + * (or a "cookie" that should be passed to mmap() as offset) + * @m.userptr: for non-multiplanar buffers with memory == V4L2_MEMORY_USERPTR; + * a userspace pointer pointing to this buffer + * @m.fd: for non-multiplanar buffers with memory == V4L2_MEMORY_DMABUF; + * a userspace file descriptor associated with this buffer + * @m.planes: for multiplanar buffers; userspace pointer to the array of plane + * info structs for this buffer + * @m: union of @offset, @userptr, @planes and @fd + * @length: size in bytes of the buffer (NOT its payload) for single-plane + * buffers (when type != *_MPLANE); number of elements in the + * planes array for multi-plane buffers + * @reserved2: drivers and applications must zero this field + * @request_fd: fd of the request that this buffer should use + * @reserved: for backwards compatibility with applications that do not know + * about @request_fd + * + * Contains data exchanged by application and driver using one of the Streaming + * I/O methods. + */ +struct v4l2_buffer { + u_int32_t index; + u_int32_t type; + u_int32_t bytesused; + u_int32_t flags; + u_int32_t field; + struct timeval timestamp; + struct v4l2_timecode timecode; + u_int32_t sequence; + + /* memory location */ + u_int32_t memory; + union { + u_int32_t offset; + unsigned long userptr; + struct v4l2_plane *planes; + int32_t fd; + } m; + u_int32_t length; + u_int32_t reserved2; + union { + int32_t request_fd; + u_int32_t reserved; + }; +}; + +/** + * v4l2_timeval_to_ns - Convert timeval to nanoseconds + * @tv: pointer to the timeval variable to be converted + * + * Returns the scalar nanosecond representation of the timeval + * parameter. + */ +static inline u_int64_t v4l2_timeval_to_ns(const struct timeval *tv) +{ + return (u_int64_t)tv->tv_sec * 1000000000ULL + tv->tv_usec * 1000; +} + +/* Flags for 'flags' field */ +/* Buffer is mapped (flag) */ +#define V4L2_BUF_FLAG_MAPPED 0x00000001 +/* Buffer is queued for processing */ +#define V4L2_BUF_FLAG_QUEUED 0x00000002 +/* Buffer is ready */ +#define V4L2_BUF_FLAG_DONE 0x00000004 +/* Image is a keyframe (I-frame) */ +#define V4L2_BUF_FLAG_KEYFRAME 0x00000008 +/* Image is a P-frame */ +#define V4L2_BUF_FLAG_PFRAME 0x00000010 +/* Image is a B-frame */ +#define V4L2_BUF_FLAG_BFRAME 0x00000020 +/* Buffer is ready, but the data contained within is corrupted. */ +#define V4L2_BUF_FLAG_ERROR 0x00000040 +/* Buffer is added to an unqueued request */ +#define V4L2_BUF_FLAG_IN_REQUEST 0x00000080 +/* timecode field is valid */ +#define V4L2_BUF_FLAG_TIMECODE 0x00000100 +/* Don't return the capture buffer until OUTPUT timestamp changes */ +#define V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF 0x00000200 +/* Buffer is prepared for queuing */ +#define V4L2_BUF_FLAG_PREPARED 0x00000400 +/* Cache handling flags */ +#define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE 0x00000800 +#define V4L2_BUF_FLAG_NO_CACHE_CLEAN 0x00001000 +/* Timestamp type */ +#define V4L2_BUF_FLAG_TIMESTAMP_MASK 0x0000e000 +#define V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN 0x00000000 +#define V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC 0x00002000 +#define V4L2_BUF_FLAG_TIMESTAMP_COPY 0x00004000 +/* Timestamp sources. */ +#define V4L2_BUF_FLAG_TSTAMP_SRC_MASK 0x00070000 +#define V4L2_BUF_FLAG_TSTAMP_SRC_EOF 0x00000000 +#define V4L2_BUF_FLAG_TSTAMP_SRC_SOE 0x00010000 +/* mem2mem encoder/decoder */ +#define V4L2_BUF_FLAG_LAST 0x00100000 +/* request_fd is valid */ +#define V4L2_BUF_FLAG_REQUEST_FD 0x00800000 + +/** + * struct v4l2_exportbuffer - export of video buffer as DMABUF file descriptor + * + * @index: id number of the buffer + * @type: enum v4l2_buf_type; buffer type (type == *_MPLANE for + * multiplanar buffers); + * @plane: index of the plane to be exported, 0 for single plane queues + * @flags: flags for newly created file, currently only O_CLOEXEC is + * supported, refer to manual of open syscall for more details + * @fd: file descriptor associated with DMABUF (set by driver) + * @reserved: drivers and applications must zero this array + * + * Contains data used for exporting a video buffer as DMABUF file descriptor. + * The buffer is identified by a 'cookie' returned by VIDIOC_QUERYBUF + * (identical to the cookie used to mmap() the buffer to userspace). All + * reserved fields must be set to zero. The field reserved0 is expected to + * become a structure 'type' allowing an alternative layout of the structure + * content. Therefore this field should not be used for any other extensions. + */ +struct v4l2_exportbuffer { + u_int32_t type; /* enum v4l2_buf_type */ + u_int32_t index; + u_int32_t plane; + u_int32_t flags; + int32_t fd; + u_int32_t reserved[11]; +}; + +/* + * O V E R L A Y P R E V I E W + */ +struct v4l2_framebuffer { + u_int32_t capability; + u_int32_t flags; +/* FIXME: in theory we should pass something like PCI device + memory + * region + offset instead of some physical address */ + void *base; + struct { + u_int32_t width; + u_int32_t height; + u_int32_t pixelformat; + u_int32_t field; /* enum v4l2_field */ + u_int32_t bytesperline; /* for padding, zero if unused */ + u_int32_t sizeimage; + u_int32_t colorspace; /* enum v4l2_colorspace */ + u_int32_t priv; /* reserved field, set to 0 */ + } fmt; +}; +/* Flags for the 'capability' field. Read only */ +#define V4L2_FBUF_CAP_EXTERNOVERLAY 0x0001 +#define V4L2_FBUF_CAP_CHROMAKEY 0x0002 +#define V4L2_FBUF_CAP_LIST_CLIPPING 0x0004 +#define V4L2_FBUF_CAP_BITMAP_CLIPPING 0x0008 +#define V4L2_FBUF_CAP_LOCAL_ALPHA 0x0010 +#define V4L2_FBUF_CAP_GLOBAL_ALPHA 0x0020 +#define V4L2_FBUF_CAP_LOCAL_INV_ALPHA 0x0040 +#define V4L2_FBUF_CAP_SRC_CHROMAKEY 0x0080 +/* Flags for the 'flags' field. */ +#define V4L2_FBUF_FLAG_PRIMARY 0x0001 +#define V4L2_FBUF_FLAG_OVERLAY 0x0002 +#define V4L2_FBUF_FLAG_CHROMAKEY 0x0004 +#define V4L2_FBUF_FLAG_LOCAL_ALPHA 0x0008 +#define V4L2_FBUF_FLAG_GLOBAL_ALPHA 0x0010 +#define V4L2_FBUF_FLAG_LOCAL_INV_ALPHA 0x0020 +#define V4L2_FBUF_FLAG_SRC_CHROMAKEY 0x0040 + +struct v4l2_clip { + struct v4l2_rect c; + struct v4l2_clip __user *next; +}; + +struct v4l2_window { + struct v4l2_rect w; + u_int32_t field; /* enum v4l2_field */ + u_int32_t chromakey; + struct v4l2_clip *clips; + u_int32_t clipcount; + void __user *bitmap; + u_int8_t global_alpha; +}; + +/* + * C A P T U R E P A R A M E T E R S + */ +struct v4l2_captureparm { + u_int32_t capability; /* Supported modes */ + u_int32_t capturemode; /* Current mode */ + struct v4l2_fract timeperframe; /* Time per frame in seconds */ + u_int32_t extendedmode; /* Driver-specific extensions */ + u_int32_t readbuffers; /* # of buffers for read */ + u_int32_t reserved[4]; +}; + +/* Flags for 'capability' and 'capturemode' fields */ +#define V4L2_MODE_HIGHQUALITY 0x0001 /* High quality imaging mode */ +#define V4L2_CAP_TIMEPERFRAME 0x1000 /* timeperframe field is supported */ + +struct v4l2_outputparm { + u_int32_t capability; /* Supported modes */ + u_int32_t outputmode; /* Current mode */ + struct v4l2_fract timeperframe; /* Time per frame in seconds */ + u_int32_t extendedmode; /* Driver-specific extensions */ + u_int32_t writebuffers; /* # of buffers for write */ + u_int32_t reserved[4]; +}; + +/* + * I N P U T I M A G E C R O P P I N G + */ +struct v4l2_cropcap { + u_int32_t type; /* enum v4l2_buf_type */ + struct v4l2_rect bounds; + struct v4l2_rect defrect; + struct v4l2_fract pixelaspect; +}; + +struct v4l2_crop { + u_int32_t type; /* enum v4l2_buf_type */ + struct v4l2_rect c; +}; + +/** + * struct v4l2_selection - selection info + * @type: buffer type (do not use *_MPLANE types) + * @target: Selection target, used to choose one of possible rectangles; + * defined in v4l2-common.h; V4L2_SEL_TGT_* . + * @flags: constraints flags, defined in v4l2-common.h; V4L2_SEL_FLAG_*. + * @r: coordinates of selection window + * @reserved: for future use, rounds structure size to 64 bytes, set to zero + * + * Hardware may use multiple helper windows to process a video stream. + * The structure is used to exchange this selection areas between + * an application and a driver. + */ +struct v4l2_selection { + u_int32_t type; + u_int32_t target; + u_int32_t flags; + struct v4l2_rect r; + u_int32_t reserved[9]; +}; + + +/* + * A N A L O G V I D E O S T A N D A R D + */ + +typedef u_int64_t v4l2_std_id; + +/* + * Attention: Keep the V4L2_STD_* bit definitions in sync with + * include/dt-bindings/display/sdtv-standards.h SDTV_STD_* bit definitions. + */ +/* one bit for each */ +#define V4L2_STD_PAL_B ((v4l2_std_id)0x00000001) +#define V4L2_STD_PAL_B1 ((v4l2_std_id)0x00000002) +#define V4L2_STD_PAL_G ((v4l2_std_id)0x00000004) +#define V4L2_STD_PAL_H ((v4l2_std_id)0x00000008) +#define V4L2_STD_PAL_I ((v4l2_std_id)0x00000010) +#define V4L2_STD_PAL_D ((v4l2_std_id)0x00000020) +#define V4L2_STD_PAL_D1 ((v4l2_std_id)0x00000040) +#define V4L2_STD_PAL_K ((v4l2_std_id)0x00000080) + +#define V4L2_STD_PAL_M ((v4l2_std_id)0x00000100) +#define V4L2_STD_PAL_N ((v4l2_std_id)0x00000200) +#define V4L2_STD_PAL_Nc ((v4l2_std_id)0x00000400) +#define V4L2_STD_PAL_60 ((v4l2_std_id)0x00000800) + +#define V4L2_STD_NTSC_M ((v4l2_std_id)0x00001000) /* BTSC */ +#define V4L2_STD_NTSC_M_JP ((v4l2_std_id)0x00002000) /* EIA-J */ +#define V4L2_STD_NTSC_443 ((v4l2_std_id)0x00004000) +#define V4L2_STD_NTSC_M_KR ((v4l2_std_id)0x00008000) /* FM A2 */ + +#define V4L2_STD_SECAM_B ((v4l2_std_id)0x00010000) +#define V4L2_STD_SECAM_D ((v4l2_std_id)0x00020000) +#define V4L2_STD_SECAM_G ((v4l2_std_id)0x00040000) +#define V4L2_STD_SECAM_H ((v4l2_std_id)0x00080000) +#define V4L2_STD_SECAM_K ((v4l2_std_id)0x00100000) +#define V4L2_STD_SECAM_K1 ((v4l2_std_id)0x00200000) +#define V4L2_STD_SECAM_L ((v4l2_std_id)0x00400000) +#define V4L2_STD_SECAM_LC ((v4l2_std_id)0x00800000) + +/* ATSC/HDTV */ +#define V4L2_STD_ATSC_8_VSB ((v4l2_std_id)0x01000000) +#define V4L2_STD_ATSC_16_VSB ((v4l2_std_id)0x02000000) + +/* FIXME: + Although std_id is 64 bits, there is an issue on PPC32 architecture that + makes switch(u_int64_t) to break. So, there's a hack on v4l2-common.c rounding + this value to 32 bits. + As, currently, the max value is for V4L2_STD_ATSC_16_VSB (30 bits wide), + it should work fine. However, if needed to add more than two standards, + v4l2-common.c should be fixed. + */ + +/* + * Some macros to merge video standards in order to make live easier for the + * drivers and V4L2 applications + */ + +/* + * "Common" NTSC/M - It should be noticed that V4L2_STD_NTSC_443 is + * Missing here. + */ +#define V4L2_STD_NTSC (V4L2_STD_NTSC_M |\ + V4L2_STD_NTSC_M_JP |\ + V4L2_STD_NTSC_M_KR) +/* Secam macros */ +#define V4L2_STD_SECAM_DK (V4L2_STD_SECAM_D |\ + V4L2_STD_SECAM_K |\ + V4L2_STD_SECAM_K1) +/* All Secam Standards */ +#define V4L2_STD_SECAM (V4L2_STD_SECAM_B |\ + V4L2_STD_SECAM_G |\ + V4L2_STD_SECAM_H |\ + V4L2_STD_SECAM_DK |\ + V4L2_STD_SECAM_L |\ + V4L2_STD_SECAM_LC) +/* PAL macros */ +#define V4L2_STD_PAL_BG (V4L2_STD_PAL_B |\ + V4L2_STD_PAL_B1 |\ + V4L2_STD_PAL_G) +#define V4L2_STD_PAL_DK (V4L2_STD_PAL_D |\ + V4L2_STD_PAL_D1 |\ + V4L2_STD_PAL_K) +/* + * "Common" PAL - This macro is there to be compatible with the old + * V4L1 concept of "PAL": /BGDKHI. + * Several PAL standards are missing here: /M, /N and /Nc + */ +#define V4L2_STD_PAL (V4L2_STD_PAL_BG |\ + V4L2_STD_PAL_DK |\ + V4L2_STD_PAL_H |\ + V4L2_STD_PAL_I) +/* Chroma "agnostic" standards */ +#define V4L2_STD_B (V4L2_STD_PAL_B |\ + V4L2_STD_PAL_B1 |\ + V4L2_STD_SECAM_B) +#define V4L2_STD_G (V4L2_STD_PAL_G |\ + V4L2_STD_SECAM_G) +#define V4L2_STD_H (V4L2_STD_PAL_H |\ + V4L2_STD_SECAM_H) +#define V4L2_STD_L (V4L2_STD_SECAM_L |\ + V4L2_STD_SECAM_LC) +#define V4L2_STD_GH (V4L2_STD_G |\ + V4L2_STD_H) +#define V4L2_STD_DK (V4L2_STD_PAL_DK |\ + V4L2_STD_SECAM_DK) +#define V4L2_STD_BG (V4L2_STD_B |\ + V4L2_STD_G) +#define V4L2_STD_MN (V4L2_STD_PAL_M |\ + V4L2_STD_PAL_N |\ + V4L2_STD_PAL_Nc |\ + V4L2_STD_NTSC) + +/* Standards where MTS/BTSC stereo could be found */ +#define V4L2_STD_MTS (V4L2_STD_NTSC_M |\ + V4L2_STD_PAL_M |\ + V4L2_STD_PAL_N |\ + V4L2_STD_PAL_Nc) + +/* Standards for Countries with 60Hz Line frequency */ +#define V4L2_STD_525_60 (V4L2_STD_PAL_M |\ + V4L2_STD_PAL_60 |\ + V4L2_STD_NTSC |\ + V4L2_STD_NTSC_443) +/* Standards for Countries with 50Hz Line frequency */ +#define V4L2_STD_625_50 (V4L2_STD_PAL |\ + V4L2_STD_PAL_N |\ + V4L2_STD_PAL_Nc |\ + V4L2_STD_SECAM) + +#define V4L2_STD_ATSC (V4L2_STD_ATSC_8_VSB |\ + V4L2_STD_ATSC_16_VSB) +/* Macros with none and all analog standards */ +#define V4L2_STD_UNKNOWN 0 +#define V4L2_STD_ALL (V4L2_STD_525_60 |\ + V4L2_STD_625_50) + +struct v4l2_standard { + u_int32_t index; + v4l2_std_id id; + u_int8_t name[24]; + struct v4l2_fract frameperiod; /* Frames, not fields */ + u_int32_t framelines; + u_int32_t reserved[4]; +}; + +/* + * D V B T T I M I N G S + */ + +/** struct v4l2_bt_timings - BT.656/BT.1120 timing data + * @width: total width of the active video in pixels + * @height: total height of the active video in lines + * @interlaced: Interlaced or progressive + * @polarities: Positive or negative polarities + * @pixelclock: Pixel clock in HZ. Ex. 74.25MHz->74250000 + * @hfrontporch:Horizontal front porch in pixels + * @hsync: Horizontal Sync length in pixels + * @hbackporch: Horizontal back porch in pixels + * @vfrontporch:Vertical front porch in lines + * @vsync: Vertical Sync length in lines + * @vbackporch: Vertical back porch in lines + * @il_vfrontporch:Vertical front porch for the even field + * (aka field 2) of interlaced field formats + * @il_vsync: Vertical Sync length for the even field + * (aka field 2) of interlaced field formats + * @il_vbackporch:Vertical back porch for the even field + * (aka field 2) of interlaced field formats + * @standards: Standards the timing belongs to + * @flags: Flags + * @picture_aspect: The picture aspect ratio (hor/vert). + * @cea861_vic: VIC code as per the CEA-861 standard. + * @hdmi_vic: VIC code as per the HDMI standard. + * @reserved: Reserved fields, must be zeroed. + * + * A note regarding vertical interlaced timings: height refers to the total + * height of the active video frame (= two fields). The blanking timings refer + * to the blanking of each field. So the height of the total frame is + * calculated as follows: + * + * tot_height = height + vfrontporch + vsync + vbackporch + + * il_vfrontporch + il_vsync + il_vbackporch + * + * The active height of each field is height / 2. + */ +struct v4l2_bt_timings { + u_int32_t width; + u_int32_t height; + u_int32_t interlaced; + u_int32_t polarities; + u_int64_t pixelclock; + u_int32_t hfrontporch; + u_int32_t hsync; + u_int32_t hbackporch; + u_int32_t vfrontporch; + u_int32_t vsync; + u_int32_t vbackporch; + u_int32_t il_vfrontporch; + u_int32_t il_vsync; + u_int32_t il_vbackporch; + u_int32_t standards; + u_int32_t flags; + struct v4l2_fract picture_aspect; + u_int8_t cea861_vic; + u_int8_t hdmi_vic; + u_int8_t reserved[46]; +} __attribute__ ((packed)); + +/* Interlaced or progressive format */ +#define V4L2_DV_PROGRESSIVE 0 +#define V4L2_DV_INTERLACED 1 + +/* Polarities. If bit is not set, it is assumed to be negative polarity */ +#define V4L2_DV_VSYNC_POS_POL 0x00000001 +#define V4L2_DV_HSYNC_POS_POL 0x00000002 + +/* Timings standards */ +#define V4L2_DV_BT_STD_CEA861 (1 << 0) /* CEA-861 Digital TV Profile */ +#define V4L2_DV_BT_STD_DMT (1 << 1) /* VESA Discrete Monitor Timings */ +#define V4L2_DV_BT_STD_CVT (1 << 2) /* VESA Coordinated Video Timings */ +#define V4L2_DV_BT_STD_GTF (1 << 3) /* VESA Generalized Timings Formula */ +#define V4L2_DV_BT_STD_SDI (1 << 4) /* SDI Timings */ + +/* Flags */ + +/* + * CVT/GTF specific: timing uses reduced blanking (CVT) or the 'Secondary + * GTF' curve (GTF). In both cases the horizontal and/or vertical blanking + * intervals are reduced, allowing a higher resolution over the same + * bandwidth. This is a read-only flag. + */ +#define V4L2_DV_FL_REDUCED_BLANKING (1 << 0) +/* + * CEA-861 specific: set for CEA-861 formats with a framerate of a multiple + * of six. These formats can be optionally played at 1 / 1.001 speed. + * This is a read-only flag. + */ +#define V4L2_DV_FL_CAN_REDUCE_FPS (1 << 1) +/* + * CEA-861 specific: only valid for video transmitters, the flag is cleared + * by receivers. + * If the framerate of the format is a multiple of six, then the pixelclock + * used to set up the transmitter is divided by 1.001 to make it compatible + * with 60 Hz based standards such as NTSC and PAL-M that use a framerate of + * 29.97 Hz. Otherwise this flag is cleared. If the transmitter can't generate + * such frequencies, then the flag will also be cleared. + */ +#define V4L2_DV_FL_REDUCED_FPS (1 << 2) +/* + * Specific to interlaced formats: if set, then field 1 is really one half-line + * longer and field 2 is really one half-line shorter, so each field has + * exactly the same number of half-lines. Whether half-lines can be detected + * or used depends on the hardware. + */ +#define V4L2_DV_FL_HALF_LINE (1 << 3) +/* + * If set, then this is a Consumer Electronics (CE) video format. Such formats + * differ from other formats (commonly called IT formats) in that if RGB + * encoding is used then by default the RGB values use limited range (i.e. + * use the range 16-235) as opposed to 0-255. All formats defined in CEA-861 + * except for the 640x480 format are CE formats. + */ +#define V4L2_DV_FL_IS_CE_VIDEO (1 << 4) +/* Some formats like SMPTE-125M have an interlaced signal with a odd + * total height. For these formats, if this flag is set, the first + * field has the extra line. If not, it is the second field. + */ +#define V4L2_DV_FL_FIRST_FIELD_EXTRA_LINE (1 << 5) +/* + * If set, then the picture_aspect field is valid. Otherwise assume that the + * pixels are square, so the picture aspect ratio is the same as the width to + * height ratio. + */ +#define V4L2_DV_FL_HAS_PICTURE_ASPECT (1 << 6) +/* + * If set, then the cea861_vic field is valid and contains the Video + * Identification Code as per the CEA-861 standard. + */ +#define V4L2_DV_FL_HAS_CEA861_VIC (1 << 7) +/* + * If set, then the hdmi_vic field is valid and contains the Video + * Identification Code as per the HDMI standard (HDMI Vendor Specific + * InfoFrame). + */ +#define V4L2_DV_FL_HAS_HDMI_VIC (1 << 8) +/* + * CEA-861 specific: only valid for video receivers. + * If set, then HW can detect the difference between regular FPS and + * 1000/1001 FPS. Note: This flag is only valid for HDMI VIC codes with + * the V4L2_DV_FL_CAN_REDUCE_FPS flag set. + */ +#define V4L2_DV_FL_CAN_DETECT_REDUCED_FPS (1 << 9) + +/* A few useful defines to calculate the total blanking and frame sizes */ +#define V4L2_DV_BT_BLANKING_WIDTH(bt) \ + ((bt)->hfrontporch + (bt)->hsync + (bt)->hbackporch) +#define V4L2_DV_BT_FRAME_WIDTH(bt) \ + ((bt)->width + V4L2_DV_BT_BLANKING_WIDTH(bt)) +#define V4L2_DV_BT_BLANKING_HEIGHT(bt) \ + ((bt)->vfrontporch + (bt)->vsync + (bt)->vbackporch + \ + ((bt)->interlaced ? \ + ((bt)->il_vfrontporch + (bt)->il_vsync + (bt)->il_vbackporch) : 0)) +#define V4L2_DV_BT_FRAME_HEIGHT(bt) \ + ((bt)->height + V4L2_DV_BT_BLANKING_HEIGHT(bt)) + +/** struct v4l2_dv_timings - DV timings + * @type: the type of the timings + * @bt: BT656/1120 timings + */ +struct v4l2_dv_timings { + u_int32_t type; + union { + struct v4l2_bt_timings bt; + u_int32_t reserved[32]; + }; +} __attribute__ ((packed)); + +/* Values for the type field */ +#define V4L2_DV_BT_656_1120 0 /* BT.656/1120 timing type */ + + +/** struct v4l2_enum_dv_timings - DV timings enumeration + * @index: enumeration index + * @pad: the pad number for which to enumerate timings (used with + * v4l-subdev nodes only) + * @reserved: must be zeroed + * @timings: the timings for the given index + */ +struct v4l2_enum_dv_timings { + u_int32_t index; + u_int32_t pad; + u_int32_t reserved[2]; + struct v4l2_dv_timings timings; +}; + +/** struct v4l2_bt_timings_cap - BT.656/BT.1120 timing capabilities + * @min_width: width in pixels + * @max_width: width in pixels + * @min_height: height in lines + * @max_height: height in lines + * @min_pixelclock: Pixel clock in HZ. Ex. 74.25MHz->74250000 + * @max_pixelclock: Pixel clock in HZ. Ex. 74.25MHz->74250000 + * @standards: Supported standards + * @capabilities: Supported capabilities + * @reserved: Must be zeroed + */ +struct v4l2_bt_timings_cap { + u_int32_t min_width; + u_int32_t max_width; + u_int32_t min_height; + u_int32_t max_height; + u_int64_t min_pixelclock; + u_int64_t max_pixelclock; + u_int32_t standards; + u_int32_t capabilities; + u_int32_t reserved[16]; +} __attribute__ ((packed)); + +/* Supports interlaced formats */ +#define V4L2_DV_BT_CAP_INTERLACED (1 << 0) +/* Supports progressive formats */ +#define V4L2_DV_BT_CAP_PROGRESSIVE (1 << 1) +/* Supports CVT/GTF reduced blanking */ +#define V4L2_DV_BT_CAP_REDUCED_BLANKING (1 << 2) +/* Supports custom formats */ +#define V4L2_DV_BT_CAP_CUSTOM (1 << 3) + +/** struct v4l2_dv_timings_cap - DV timings capabilities + * @type: the type of the timings (same as in struct v4l2_dv_timings) + * @pad: the pad number for which to query capabilities (used with + * v4l-subdev nodes only) + * @bt: the BT656/1120 timings capabilities + */ +struct v4l2_dv_timings_cap { + u_int32_t type; + u_int32_t pad; + u_int32_t reserved[2]; + union { + struct v4l2_bt_timings_cap bt; + u_int32_t raw_data[32]; + }; +}; + + +/* + * V I D E O I N P U T S + */ +struct v4l2_input { + u_int32_t index; /* Which input */ + u_int8_t name[32]; /* Label */ + u_int32_t type; /* Type of input */ + u_int32_t audioset; /* Associated audios (bitfield) */ + u_int32_t tuner; /* Tuner index */ + v4l2_std_id std; + u_int32_t status; + u_int32_t capabilities; + u_int32_t reserved[3]; +}; + +/* Values for the 'type' field */ +#define V4L2_INPUT_TYPE_TUNER 1 +#define V4L2_INPUT_TYPE_CAMERA 2 +#define V4L2_INPUT_TYPE_TOUCH 3 + +/* field 'status' - general */ +#define V4L2_IN_ST_NO_POWER 0x00000001 /* Attached device is off */ +#define V4L2_IN_ST_NO_SIGNAL 0x00000002 +#define V4L2_IN_ST_NO_COLOR 0x00000004 + +/* field 'status' - sensor orientation */ +/* If sensor is mounted upside down set both bits */ +#define V4L2_IN_ST_HFLIP 0x00000010 /* Frames are flipped horizontally */ +#define V4L2_IN_ST_VFLIP 0x00000020 /* Frames are flipped vertically */ + +/* field 'status' - analog */ +#define V4L2_IN_ST_NO_H_LOCK 0x00000100 /* No horizontal sync lock */ +#define V4L2_IN_ST_COLOR_KILL 0x00000200 /* Color killer is active */ +#define V4L2_IN_ST_NO_V_LOCK 0x00000400 /* No vertical sync lock */ +#define V4L2_IN_ST_NO_STD_LOCK 0x00000800 /* No standard format lock */ + +/* field 'status' - digital */ +#define V4L2_IN_ST_NO_SYNC 0x00010000 /* No synchronization lock */ +#define V4L2_IN_ST_NO_EQU 0x00020000 /* No equalizer lock */ +#define V4L2_IN_ST_NO_CARRIER 0x00040000 /* Carrier recovery failed */ + +/* field 'status' - VCR and set-top box */ +#define V4L2_IN_ST_MACROVISION 0x01000000 /* Macrovision detected */ +#define V4L2_IN_ST_NO_ACCESS 0x02000000 /* Conditional access denied */ +#define V4L2_IN_ST_VTR 0x04000000 /* VTR time constant */ + +/* capabilities flags */ +#define V4L2_IN_CAP_DV_TIMINGS 0x00000002 /* Supports S_DV_TIMINGS */ +#define V4L2_IN_CAP_CUSTOM_TIMINGS V4L2_IN_CAP_DV_TIMINGS /* For compatibility */ +#define V4L2_IN_CAP_STD 0x00000004 /* Supports S_STD */ +#define V4L2_IN_CAP_NATIVE_SIZE 0x00000008 /* Supports setting native size */ + +/* + * V I D E O O U T P U T S + */ +struct v4l2_output { + u_int32_t index; /* Which output */ + u_int8_t name[32]; /* Label */ + u_int32_t type; /* Type of output */ + u_int32_t audioset; /* Associated audios (bitfield) */ + u_int32_t modulator; /* Associated modulator */ + v4l2_std_id std; + u_int32_t capabilities; + u_int32_t reserved[3]; +}; +/* Values for the 'type' field */ +#define V4L2_OUTPUT_TYPE_MODULATOR 1 +#define V4L2_OUTPUT_TYPE_ANALOG 2 +#define V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY 3 + +/* capabilities flags */ +#define V4L2_OUT_CAP_DV_TIMINGS 0x00000002 /* Supports S_DV_TIMINGS */ +#define V4L2_OUT_CAP_CUSTOM_TIMINGS V4L2_OUT_CAP_DV_TIMINGS /* For compatibility */ +#define V4L2_OUT_CAP_STD 0x00000004 /* Supports S_STD */ +#define V4L2_OUT_CAP_NATIVE_SIZE 0x00000008 /* Supports setting native size */ + +/* + * C O N T R O L S + */ +struct v4l2_control { + u_int32_t id; + int32_t value; +}; + +struct v4l2_ext_control { + u_int32_t id; + u_int32_t size; + u_int32_t reserved2[1]; + union { + int32_t value; + int64_t value64; + char __user *string; + u_int8_t __user *p_u8; + u_int16_t __user *p_u16; + u_int32_t __user *p_u32; + int32_t __user *p_s32; + int64_t __user *p_s64; + struct v4l2_area __user *p_area; + struct v4l2_rect __user *p_rect; + struct v4l2_ctrl_h264_sps __user *p_h264_sps; + struct v4l2_ctrl_h264_pps __user *p_h264_pps; + struct v4l2_ctrl_h264_scaling_matrix __user *p_h264_scaling_matrix; + struct v4l2_ctrl_h264_pred_weights __user *p_h264_pred_weights; + struct v4l2_ctrl_h264_slice_params __user *p_h264_slice_params; + struct v4l2_ctrl_h264_decode_params __user *p_h264_decode_params; + struct v4l2_ctrl_fwht_params __user *p_fwht_params; + struct v4l2_ctrl_vp8_frame __user *p_vp8_frame; + struct v4l2_ctrl_mpeg2_sequence __user *p_mpeg2_sequence; + struct v4l2_ctrl_mpeg2_picture __user *p_mpeg2_picture; + struct v4l2_ctrl_mpeg2_quantisation __user *p_mpeg2_quantisation; + struct v4l2_ctrl_vp9_compressed_hdr __user *p_vp9_compressed_hdr_probs; + struct v4l2_ctrl_vp9_frame __user *p_vp9_frame; + struct v4l2_ctrl_hevc_sps __user *p_hevc_sps; + struct v4l2_ctrl_hevc_pps __user *p_hevc_pps; + struct v4l2_ctrl_hevc_slice_params __user *p_hevc_slice_params; + struct v4l2_ctrl_hevc_scaling_matrix __user *p_hevc_scaling_matrix; + struct v4l2_ctrl_hevc_decode_params __user *p_hevc_decode_params; + struct v4l2_ctrl_av1_sequence __user *p_av1_sequence; + struct v4l2_ctrl_av1_tile_group_entry __user *p_av1_tile_group_entry; + struct v4l2_ctrl_av1_frame __user *p_av1_frame; + struct v4l2_ctrl_av1_film_grain __user *p_av1_film_grain; + struct v4l2_ctrl_hdr10_cll_info __user *p_hdr10_cll_info; + struct v4l2_ctrl_hdr10_mastering_display __user *p_hdr10_mastering_display; + void __user *ptr; + } __attribute__ ((packed)); +} __attribute__ ((packed)); + +struct v4l2_ext_controls { + union { + u_int32_t ctrl_class; + u_int32_t which; + }; + u_int32_t count; + u_int32_t error_idx; + int32_t request_fd; + u_int32_t reserved[1]; + struct v4l2_ext_control *controls; +}; + +#define V4L2_CTRL_ID_MASK (0x0fffffff) +#define V4L2_CTRL_ID2CLASS(id) ((id) & 0x0fff0000UL) +#define V4L2_CTRL_ID2WHICH(id) ((id) & 0x0fff0000UL) +#define V4L2_CTRL_DRIVER_PRIV(id) (((id) & 0xffff) >= 0x1000) +#define V4L2_CTRL_MAX_DIMS (4) +#define V4L2_CTRL_WHICH_CUR_VAL 0 +#define V4L2_CTRL_WHICH_DEF_VAL 0x0f000000 +#define V4L2_CTRL_WHICH_REQUEST_VAL 0x0f010000 +#define V4L2_CTRL_WHICH_MIN_VAL 0x0f020000 +#define V4L2_CTRL_WHICH_MAX_VAL 0x0f030000 + +enum v4l2_ctrl_type { + V4L2_CTRL_TYPE_INTEGER = 1, + V4L2_CTRL_TYPE_BOOLEAN = 2, + V4L2_CTRL_TYPE_MENU = 3, + V4L2_CTRL_TYPE_BUTTON = 4, + V4L2_CTRL_TYPE_INTEGER64 = 5, + V4L2_CTRL_TYPE_CTRL_CLASS = 6, + V4L2_CTRL_TYPE_STRING = 7, + V4L2_CTRL_TYPE_BITMASK = 8, + V4L2_CTRL_TYPE_INTEGER_MENU = 9, + + /* Compound types are >= 0x0100 */ + V4L2_CTRL_COMPOUND_TYPES = 0x0100, + V4L2_CTRL_TYPE_U8 = 0x0100, + V4L2_CTRL_TYPE_U16 = 0x0101, + V4L2_CTRL_TYPE_U32 = 0x0102, + V4L2_CTRL_TYPE_AREA = 0x0106, + V4L2_CTRL_TYPE_RECT = 0x0107, + + V4L2_CTRL_TYPE_HDR10_CLL_INFO = 0x0110, + V4L2_CTRL_TYPE_HDR10_MASTERING_DISPLAY = 0x0111, + + V4L2_CTRL_TYPE_H264_SPS = 0x0200, + V4L2_CTRL_TYPE_H264_PPS = 0x0201, + V4L2_CTRL_TYPE_H264_SCALING_MATRIX = 0x0202, + V4L2_CTRL_TYPE_H264_SLICE_PARAMS = 0x0203, + V4L2_CTRL_TYPE_H264_DECODE_PARAMS = 0x0204, + V4L2_CTRL_TYPE_H264_PRED_WEIGHTS = 0x0205, + + V4L2_CTRL_TYPE_FWHT_PARAMS = 0x0220, + + V4L2_CTRL_TYPE_VP8_FRAME = 0x0240, + + V4L2_CTRL_TYPE_MPEG2_QUANTISATION = 0x0250, + V4L2_CTRL_TYPE_MPEG2_SEQUENCE = 0x0251, + V4L2_CTRL_TYPE_MPEG2_PICTURE = 0x0252, + + V4L2_CTRL_TYPE_VP9_COMPRESSED_HDR = 0x0260, + V4L2_CTRL_TYPE_VP9_FRAME = 0x0261, + + V4L2_CTRL_TYPE_HEVC_SPS = 0x0270, + V4L2_CTRL_TYPE_HEVC_PPS = 0x0271, + V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS = 0x0272, + V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX = 0x0273, + V4L2_CTRL_TYPE_HEVC_DECODE_PARAMS = 0x0274, + + V4L2_CTRL_TYPE_AV1_SEQUENCE = 0x280, + V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY = 0x281, + V4L2_CTRL_TYPE_AV1_FRAME = 0x282, + V4L2_CTRL_TYPE_AV1_FILM_GRAIN = 0x283, +}; + +/* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */ +struct v4l2_queryctrl { + u_int32_t id; + u_int32_t type; /* enum v4l2_ctrl_type */ + u_int8_t name[32]; /* Whatever */ + int32_t minimum; /* Note signedness */ + int32_t maximum; + int32_t step; + int32_t default_value; + u_int32_t flags; + u_int32_t reserved[2]; +}; + +/* Used in the VIDIOC_QUERY_EXT_CTRL ioctl for querying extended controls */ +struct v4l2_query_ext_ctrl { + u_int32_t id; + u_int32_t type; + char name[32]; + int64_t minimum; + int64_t maximum; + u_int64_t step; + int64_t default_value; + u_int32_t flags; + u_int32_t elem_size; + u_int32_t elems; + u_int32_t nr_of_dims; + u_int32_t dims[V4L2_CTRL_MAX_DIMS]; + u_int32_t reserved[32]; +}; + +/* Used in the VIDIOC_QUERYMENU ioctl for querying menu items */ +struct v4l2_querymenu { + u_int32_t id; + u_int32_t index; + union { + u_int8_t name[32]; /* Whatever */ + int64_t value; + }; + u_int32_t reserved; +} __attribute__ ((packed)); + +/* Control flags */ +#define V4L2_CTRL_FLAG_DISABLED 0x0001 +#define V4L2_CTRL_FLAG_GRABBED 0x0002 +#define V4L2_CTRL_FLAG_READ_ONLY 0x0004 +#define V4L2_CTRL_FLAG_UPDATE 0x0008 +#define V4L2_CTRL_FLAG_INACTIVE 0x0010 +#define V4L2_CTRL_FLAG_SLIDER 0x0020 +#define V4L2_CTRL_FLAG_WRITE_ONLY 0x0040 +#define V4L2_CTRL_FLAG_VOLATILE 0x0080 +#define V4L2_CTRL_FLAG_HAS_PAYLOAD 0x0100 +#define V4L2_CTRL_FLAG_EXECUTE_ON_WRITE 0x0200 +#define V4L2_CTRL_FLAG_MODIFY_LAYOUT 0x0400 +#define V4L2_CTRL_FLAG_DYNAMIC_ARRAY 0x0800 +#define V4L2_CTRL_FLAG_HAS_WHICH_MIN_MAX 0x1000 + +/* Query flags, to be ORed with the control ID */ +#define V4L2_CTRL_FLAG_NEXT_CTRL 0x80000000 +#define V4L2_CTRL_FLAG_NEXT_COMPOUND 0x40000000 + +/* User-class control IDs defined by V4L2 */ +#define V4L2_CID_MAX_CTRLS 1024 +/* IDs reserved for driver specific controls */ +#define V4L2_CID_PRIVATE_BASE 0x08000000 + + +/* + * T U N I N G + */ +struct v4l2_tuner { + u_int32_t index; + u_int8_t name[32]; + u_int32_t type; /* enum v4l2_tuner_type */ + u_int32_t capability; + u_int32_t rangelow; + u_int32_t rangehigh; + u_int32_t rxsubchans; + u_int32_t audmode; + int32_t signal; + int32_t afc; + u_int32_t reserved[4]; +}; + +struct v4l2_modulator { + u_int32_t index; + u_int8_t name[32]; + u_int32_t capability; + u_int32_t rangelow; + u_int32_t rangehigh; + u_int32_t txsubchans; + u_int32_t type; /* enum v4l2_tuner_type */ + u_int32_t reserved[3]; +}; + +/* Flags for the 'capability' field */ +#define V4L2_TUNER_CAP_LOW 0x0001 +#define V4L2_TUNER_CAP_NORM 0x0002 +#define V4L2_TUNER_CAP_HWSEEK_BOUNDED 0x0004 +#define V4L2_TUNER_CAP_HWSEEK_WRAP 0x0008 +#define V4L2_TUNER_CAP_STEREO 0x0010 +#define V4L2_TUNER_CAP_LANG2 0x0020 +#define V4L2_TUNER_CAP_SAP 0x0020 +#define V4L2_TUNER_CAP_LANG1 0x0040 +#define V4L2_TUNER_CAP_RDS 0x0080 +#define V4L2_TUNER_CAP_RDS_BLOCK_IO 0x0100 +#define V4L2_TUNER_CAP_RDS_CONTROLS 0x0200 +#define V4L2_TUNER_CAP_FREQ_BANDS 0x0400 +#define V4L2_TUNER_CAP_HWSEEK_PROG_LIM 0x0800 +#define V4L2_TUNER_CAP_1HZ 0x1000 + +/* Flags for the 'rxsubchans' field */ +#define V4L2_TUNER_SUB_MONO 0x0001 +#define V4L2_TUNER_SUB_STEREO 0x0002 +#define V4L2_TUNER_SUB_LANG2 0x0004 +#define V4L2_TUNER_SUB_SAP 0x0004 +#define V4L2_TUNER_SUB_LANG1 0x0008 +#define V4L2_TUNER_SUB_RDS 0x0010 + +/* Values for the 'audmode' field */ +#define V4L2_TUNER_MODE_MONO 0x0000 +#define V4L2_TUNER_MODE_STEREO 0x0001 +#define V4L2_TUNER_MODE_LANG2 0x0002 +#define V4L2_TUNER_MODE_SAP 0x0002 +#define V4L2_TUNER_MODE_LANG1 0x0003 +#define V4L2_TUNER_MODE_LANG1_LANG2 0x0004 + +struct v4l2_frequency { + u_int32_t tuner; + u_int32_t type; /* enum v4l2_tuner_type */ + u_int32_t frequency; + u_int32_t reserved[8]; +}; + +#define V4L2_BAND_MODULATION_VSB (1 << 1) +#define V4L2_BAND_MODULATION_FM (1 << 2) +#define V4L2_BAND_MODULATION_AM (1 << 3) + +struct v4l2_frequency_band { + u_int32_t tuner; + u_int32_t type; /* enum v4l2_tuner_type */ + u_int32_t index; + u_int32_t capability; + u_int32_t rangelow; + u_int32_t rangehigh; + u_int32_t modulation; + u_int32_t reserved[9]; +}; + +struct v4l2_hw_freq_seek { + u_int32_t tuner; + u_int32_t type; /* enum v4l2_tuner_type */ + u_int32_t seek_upward; + u_int32_t wrap_around; + u_int32_t spacing; + u_int32_t rangelow; + u_int32_t rangehigh; + u_int32_t reserved[5]; +}; + +/* + * R D S + */ + +struct v4l2_rds_data { + u_int8_t lsb; + u_int8_t msb; + u_int8_t block; +} __attribute__ ((packed)); + +#define V4L2_RDS_BLOCK_MSK 0x7 +#define V4L2_RDS_BLOCK_A 0 +#define V4L2_RDS_BLOCK_B 1 +#define V4L2_RDS_BLOCK_C 2 +#define V4L2_RDS_BLOCK_D 3 +#define V4L2_RDS_BLOCK_C_ALT 4 +#define V4L2_RDS_BLOCK_INVALID 7 + +#define V4L2_RDS_BLOCK_CORRECTED 0x40 +#define V4L2_RDS_BLOCK_ERROR 0x80 + +/* + * A U D I O + */ +struct v4l2_audio { + u_int32_t index; + u_int8_t name[32]; + u_int32_t capability; + u_int32_t mode; + u_int32_t reserved[2]; +}; + +/* Flags for the 'capability' field */ +#define V4L2_AUDCAP_STEREO 0x00001 +#define V4L2_AUDCAP_AVL 0x00002 + +/* Flags for the 'mode' field */ +#define V4L2_AUDMODE_AVL 0x00001 + +struct v4l2_audioout { + u_int32_t index; + u_int8_t name[32]; + u_int32_t capability; + u_int32_t mode; + u_int32_t reserved[2]; +}; + +/* + * M P E G S E R V I C E S + */ +#if 1 +#define V4L2_ENC_IDX_FRAME_I (0) +#define V4L2_ENC_IDX_FRAME_P (1) +#define V4L2_ENC_IDX_FRAME_B (2) +#define V4L2_ENC_IDX_FRAME_MASK (0xf) + +struct v4l2_enc_idx_entry { + u_int64_t offset; + u_int64_t pts; + u_int32_t length; + u_int32_t flags; + u_int32_t reserved[2]; +}; + +#define V4L2_ENC_IDX_ENTRIES (64) +struct v4l2_enc_idx { + u_int32_t entries; + u_int32_t entries_cap; + u_int32_t reserved[4]; + struct v4l2_enc_idx_entry entry[V4L2_ENC_IDX_ENTRIES]; +}; + + +#define V4L2_ENC_CMD_START (0) +#define V4L2_ENC_CMD_STOP (1) +#define V4L2_ENC_CMD_PAUSE (2) +#define V4L2_ENC_CMD_RESUME (3) + +/* Flags for V4L2_ENC_CMD_STOP */ +#define V4L2_ENC_CMD_STOP_AT_GOP_END (1 << 0) + +struct v4l2_encoder_cmd { + u_int32_t cmd; + u_int32_t flags; + union { + struct { + u_int32_t data[8]; + } raw; + }; +}; + +/* Decoder commands */ +#define V4L2_DEC_CMD_START (0) +#define V4L2_DEC_CMD_STOP (1) +#define V4L2_DEC_CMD_PAUSE (2) +#define V4L2_DEC_CMD_RESUME (3) +#define V4L2_DEC_CMD_FLUSH (4) + +/* Flags for V4L2_DEC_CMD_START */ +#define V4L2_DEC_CMD_START_MUTE_AUDIO (1 << 0) + +/* Flags for V4L2_DEC_CMD_PAUSE */ +#define V4L2_DEC_CMD_PAUSE_TO_BLACK (1 << 0) + +/* Flags for V4L2_DEC_CMD_STOP */ +#define V4L2_DEC_CMD_STOP_TO_BLACK (1 << 0) +#define V4L2_DEC_CMD_STOP_IMMEDIATELY (1 << 1) + +/* Play format requirements (returned by the driver): */ + +/* The decoder has no special format requirements */ +#define V4L2_DEC_START_FMT_NONE (0) +/* The decoder requires full GOPs */ +#define V4L2_DEC_START_FMT_GOP (1) + +/* The structure must be zeroed before use by the application + This ensures it can be extended safely in the future. */ +struct v4l2_decoder_cmd { + u_int32_t cmd; + u_int32_t flags; + union { + struct { + u_int64_t pts; + } stop; + + struct { + /* 0 or 1000 specifies normal speed, + 1 specifies forward single stepping, + -1 specifies backward single stepping, + >1: playback at speed/1000 of the normal speed, + <-1: reverse playback at (-speed/1000) of the normal speed. */ + int32_t speed; + u_int32_t format; + } start; + + struct { + u_int32_t data[16]; + } raw; + }; +}; +#endif + + +/* + * D A T A S E R V I C E S ( V B I ) + * + * Data services API by Michael Schimek + */ + +/* Raw VBI */ +struct v4l2_vbi_format { + u_int32_t sampling_rate; /* in 1 Hz */ + u_int32_t offset; + u_int32_t samples_per_line; + u_int32_t sample_format; /* V4L2_PIX_FMT_* */ + int32_t start[2]; + u_int32_t count[2]; + u_int32_t flags; /* V4L2_VBI_* */ + u_int32_t reserved[2]; /* must be zero */ +}; + +/* VBI flags */ +#define V4L2_VBI_UNSYNC (1 << 0) +#define V4L2_VBI_INTERLACED (1 << 1) + +/* ITU-R start lines for each field */ +#define V4L2_VBI_ITU_525_F1_START (1) +#define V4L2_VBI_ITU_525_F2_START (264) +#define V4L2_VBI_ITU_625_F1_START (1) +#define V4L2_VBI_ITU_625_F2_START (314) + +/* Sliced VBI + * + * This implements is a proposal V4L2 API to allow SLICED VBI + * required for some hardware encoders. It should change without + * notice in the definitive implementation. + */ + +struct v4l2_sliced_vbi_format { + u_int16_t service_set; + /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field + service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field + (equals frame lines 313-336 for 625 line video + standards, 263-286 for 525 line standards) */ + u_int16_t service_lines[2][24]; + u_int32_t io_size; + u_int32_t reserved[2]; /* must be zero */ +}; + +/* Teletext World System Teletext + (WST), defined on ITU-R BT.653-2 */ +#define V4L2_SLICED_TELETEXT_B (0x0001) +/* Video Program System, defined on ETS 300 231*/ +#define V4L2_SLICED_VPS (0x0400) +/* Closed Caption, defined on EIA-608 */ +#define V4L2_SLICED_CAPTION_525 (0x1000) +/* Wide Screen System, defined on ITU-R BT1119.1 */ +#define V4L2_SLICED_WSS_625 (0x4000) + +#define V4L2_SLICED_VBI_525 (V4L2_SLICED_CAPTION_525) +#define V4L2_SLICED_VBI_625 (V4L2_SLICED_TELETEXT_B | V4L2_SLICED_VPS | V4L2_SLICED_WSS_625) + +struct v4l2_sliced_vbi_cap { + u_int16_t service_set; + /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field + service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field + (equals frame lines 313-336 for 625 line video + standards, 263-286 for 525 line standards) */ + u_int16_t service_lines[2][24]; + u_int32_t type; /* enum v4l2_buf_type */ + u_int32_t reserved[3]; /* must be 0 */ +}; + +struct v4l2_sliced_vbi_data { + u_int32_t id; + u_int32_t field; /* 0: first field, 1: second field */ + u_int32_t line; /* 1-23 */ + u_int32_t reserved; /* must be 0 */ + u_int8_t data[48]; +}; + +/* + * Sliced VBI data inserted into MPEG Streams + */ + +/* + * V4L2_MPEG_STREAM_VBI_FMT_IVTV: + * + * Structure of payload contained in an MPEG 2 Private Stream 1 PES Packet in an + * MPEG-2 Program Pack that contains V4L2_MPEG_STREAM_VBI_FMT_IVTV Sliced VBI + * data + * + * Note, the MPEG-2 Program Pack and Private Stream 1 PES packet header + * definitions are not included here. See the MPEG-2 specifications for details + * on these headers. + */ + +/* Line type IDs */ +#define V4L2_MPEG_VBI_IVTV_TELETEXT_B (1) +#define V4L2_MPEG_VBI_IVTV_CAPTION_525 (4) +#define V4L2_MPEG_VBI_IVTV_WSS_625 (5) +#define V4L2_MPEG_VBI_IVTV_VPS (7) + +struct v4l2_mpeg_vbi_itv0_line { + u_int8_t id; /* One of V4L2_MPEG_VBI_IVTV_* above */ + u_int8_t data[42]; /* Sliced VBI data for the line */ +} __attribute__ ((packed)); + +struct v4l2_mpeg_vbi_itv0 { + u_int32_t linemask[2]; /* Bitmasks of VBI service lines present */ + struct v4l2_mpeg_vbi_itv0_line line[35]; +} __attribute__ ((packed)); + +struct v4l2_mpeg_vbi_ITV0 { + struct v4l2_mpeg_vbi_itv0_line line[36]; +} __attribute__ ((packed)); + +#define V4L2_MPEG_VBI_IVTV_MAGIC0 "itv0" +#define V4L2_MPEG_VBI_IVTV_MAGIC1 "ITV0" + +struct v4l2_mpeg_vbi_fmt_ivtv { + u_int8_t magic[4]; + union { + struct v4l2_mpeg_vbi_itv0 itv0; + struct v4l2_mpeg_vbi_ITV0 ITV0; + }; +} __attribute__ ((packed)); + +/* + * A G G R E G A T E S T R U C T U R E S + */ + +/** + * struct v4l2_plane_pix_format - additional, per-plane format definition + * @sizeimage: maximum size in bytes required for data, for which + * this plane will be used + * @bytesperline: distance in bytes between the leftmost pixels in two + * adjacent lines + * @reserved: drivers and applications must zero this array + */ +struct v4l2_plane_pix_format { + u_int32_t sizeimage; + u_int32_t bytesperline; + u_int16_t reserved[6]; +} __attribute__ ((packed)); + +/** + * struct v4l2_pix_format_mplane - multiplanar format definition + * @width: image width in pixels + * @height: image height in pixels + * @pixelformat: little endian four character code (fourcc) + * @field: enum v4l2_field; field order (for interlaced video) + * @colorspace: enum v4l2_colorspace; supplemental to pixelformat + * @plane_fmt: per-plane information + * @num_planes: number of planes for this format + * @flags: format flags (V4L2_PIX_FMT_FLAG_*) + * @ycbcr_enc: enum v4l2_ycbcr_encoding, Y'CbCr encoding + * @hsv_enc: enum v4l2_hsv_encoding, HSV encoding + * @quantization: enum v4l2_quantization, colorspace quantization + * @xfer_func: enum v4l2_xfer_func, colorspace transfer function + * @reserved: drivers and applications must zero this array + */ +struct v4l2_pix_format_mplane { + u_int32_t width; + u_int32_t height; + u_int32_t pixelformat; + u_int32_t field; + u_int32_t colorspace; + + struct v4l2_plane_pix_format plane_fmt[VIDEO_MAX_PLANES]; + u_int8_t num_planes; + u_int8_t flags; + union { + u_int8_t ycbcr_enc; + u_int8_t hsv_enc; + }; + u_int8_t quantization; + u_int8_t xfer_func; + u_int8_t reserved[7]; +} __attribute__ ((packed)); + +/** + * struct v4l2_sdr_format - SDR format definition + * @pixelformat: little endian four character code (fourcc) + * @buffersize: maximum size in bytes required for data + * @reserved: drivers and applications must zero this array + */ +struct v4l2_sdr_format { + u_int32_t pixelformat; + u_int32_t buffersize; + u_int8_t reserved[24]; +} __attribute__ ((packed)); + +/** + * struct v4l2_meta_format - metadata format definition + * @dataformat: little endian four character code (fourcc) + * @buffersize: maximum size in bytes required for data + * @width: number of data units of data per line (valid for line + * based formats only, see format documentation) + * @height: number of lines of data per buffer (valid for line based + * formats only) + * @bytesperline: offset between the beginnings of two adjacent lines in + * bytes (valid for line based formats only) + */ +struct v4l2_meta_format { + u_int32_t dataformat; + u_int32_t buffersize; + u_int32_t width; + u_int32_t height; + u_int32_t bytesperline; +} __attribute__ ((packed)); + +/** + * struct v4l2_format - stream data format + * @type: enum v4l2_buf_type; type of the data stream + * @fmt.pix: definition of an image format + * @fmt.pix_mp: definition of a multiplanar image format + * @fmt.win: definition of an overlaid image + * @fmt.vbi: raw VBI capture or output parameters + * @fmt.sliced: sliced VBI capture or output parameters + * @fmt.raw_data: placeholder for future extensions and custom formats + * @fmt: union of @pix, @pix_mp, @win, @vbi, @sliced, @sdr, + * @meta and @raw_data + */ +struct v4l2_format { + u_int32_t type; + union { + struct v4l2_pix_format pix; /* V4L2_BUF_TYPE_VIDEO_CAPTURE */ + struct v4l2_pix_format_mplane pix_mp; /* V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE */ + struct v4l2_window win; /* V4L2_BUF_TYPE_VIDEO_OVERLAY */ + struct v4l2_vbi_format vbi; /* V4L2_BUF_TYPE_VBI_CAPTURE */ + struct v4l2_sliced_vbi_format sliced; /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */ + struct v4l2_sdr_format sdr; /* V4L2_BUF_TYPE_SDR_CAPTURE */ + struct v4l2_meta_format meta; /* V4L2_BUF_TYPE_META_CAPTURE */ + u_int8_t raw_data[200]; /* user-defined */ + } fmt; +}; + +/* Stream type-dependent parameters + */ +struct v4l2_streamparm { + u_int32_t type; /* enum v4l2_buf_type */ + union { + struct v4l2_captureparm capture; + struct v4l2_outputparm output; + u_int8_t raw_data[200]; /* user-defined */ + } parm; +}; + +/* + * E V E N T S + */ + +#define V4L2_EVENT_ALL 0 +#define V4L2_EVENT_VSYNC 1 +#define V4L2_EVENT_EOS 2 +#define V4L2_EVENT_CTRL 3 +#define V4L2_EVENT_FRAME_SYNC 4 +#define V4L2_EVENT_SOURCE_CHANGE 5 +#define V4L2_EVENT_MOTION_DET 6 +#define V4L2_EVENT_PRIVATE_START 0x08000000 + +/* Payload for V4L2_EVENT_VSYNC */ +struct v4l2_event_vsync { + /* Can be V4L2_FIELD_ANY, _NONE, _TOP or _BOTTOM */ + u_int8_t field; +} __attribute__ ((packed)); + +/* Payload for V4L2_EVENT_CTRL */ +#define V4L2_EVENT_CTRL_CH_VALUE (1 << 0) +#define V4L2_EVENT_CTRL_CH_FLAGS (1 << 1) +#define V4L2_EVENT_CTRL_CH_RANGE (1 << 2) +#define V4L2_EVENT_CTRL_CH_DIMENSIONS (1 << 3) + +struct v4l2_event_ctrl { + u_int32_t changes; + u_int32_t type; + union { + int32_t value; + int64_t value64; + }; + u_int32_t flags; + int32_t minimum; + int32_t maximum; + int32_t step; + int32_t default_value; +}; + +struct v4l2_event_frame_sync { + u_int32_t frame_sequence; +}; + +#define V4L2_EVENT_SRC_CH_RESOLUTION (1 << 0) + +struct v4l2_event_src_change { + u_int32_t changes; +}; + +#define V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ (1 << 0) + +/** + * struct v4l2_event_motion_det - motion detection event + * @flags: if V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ is set, then the + * frame_sequence field is valid. + * @frame_sequence: the frame sequence number associated with this event. + * @region_mask: which regions detected motion. + */ +struct v4l2_event_motion_det { + u_int32_t flags; + u_int32_t frame_sequence; + u_int32_t region_mask; +}; + +struct v4l2_event { + u_int32_t type; + union { + struct v4l2_event_vsync vsync; + struct v4l2_event_ctrl ctrl; + struct v4l2_event_frame_sync frame_sync; + struct v4l2_event_src_change src_change; + struct v4l2_event_motion_det motion_det; + u_int8_t data[64]; + } u; + u_int32_t pending; + u_int32_t sequence; + struct timespec timestamp; + u_int32_t id; + u_int32_t reserved[8]; +}; + +#define V4L2_EVENT_SUB_FL_SEND_INITIAL (1 << 0) +#define V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK (1 << 1) + +struct v4l2_event_subscription { + u_int32_t type; + u_int32_t id; + u_int32_t flags; + u_int32_t reserved[5]; +}; + +/* + * A D V A N C E D D E B U G G I N G + * + * NOTE: EXPERIMENTAL API, NEVER RELY ON THIS IN APPLICATIONS! + * FOR DEBUGGING, TESTING AND INTERNAL USE ONLY! + */ + +/* VIDIOC_DBG_G_REGISTER and VIDIOC_DBG_S_REGISTER */ + +#define V4L2_CHIP_MATCH_BRIDGE 0 /* Match against chip ID on the bridge (0 for the bridge) */ +#define V4L2_CHIP_MATCH_SUBDEV 4 /* Match against subdev index */ + +/* The following four defines are no longer in use */ +#define V4L2_CHIP_MATCH_HOST V4L2_CHIP_MATCH_BRIDGE +#define V4L2_CHIP_MATCH_I2C_DRIVER 1 /* Match against I2C driver name */ +#define V4L2_CHIP_MATCH_I2C_ADDR 2 /* Match against I2C 7-bit address */ +#define V4L2_CHIP_MATCH_AC97 3 /* Match against ancillary AC97 chip */ + +struct v4l2_dbg_match { + u_int32_t type; /* Match type */ + union { /* Match this chip, meaning determined by type */ + u_int32_t addr; + char name[32]; + }; +} __attribute__ ((packed)); + +struct v4l2_dbg_register { + struct v4l2_dbg_match match; + u_int32_t size; /* register size in bytes */ + u_int64_t reg; + u_int64_t val; +} __attribute__ ((packed)); + +#define V4L2_CHIP_FL_READABLE (1 << 0) +#define V4L2_CHIP_FL_WRITABLE (1 << 1) + +/* VIDIOC_DBG_G_CHIP_INFO */ +struct v4l2_dbg_chip_info { + struct v4l2_dbg_match match; + char name[32]; + u_int32_t flags; + u_int32_t reserved[32]; +} __attribute__ ((packed)); + +/** + * struct v4l2_create_buffers - VIDIOC_CREATE_BUFS argument + * @index: on return, index of the first created buffer + * @count: entry: number of requested buffers, + * return: number of created buffers + * @memory: enum v4l2_memory; buffer memory type + * @format: frame format, for which buffers are requested + * @capabilities: capabilities of this buffer type. + * @flags: additional buffer management attributes (ignored unless the + * queue has V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS capability + * and configured for MMAP streaming I/O). + * @max_num_buffers: if V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS capability flag is set + * this field indicate the maximum possible number of buffers + * for this queue. + * @reserved: future extensions + */ +struct v4l2_create_buffers { + u_int32_t index; + u_int32_t count; + u_int32_t memory; + struct v4l2_format format; + u_int32_t capabilities; + u_int32_t flags; + u_int32_t max_num_buffers; + u_int32_t reserved[5]; +}; + +/** + * struct v4l2_remove_buffers - VIDIOC_REMOVE_BUFS argument + * @index: the first buffer to be removed + * @count: number of buffers to removed + * @type: enum v4l2_buf_type + * @reserved: future extensions + */ +struct v4l2_remove_buffers { + u_int32_t index; + u_int32_t count; + u_int32_t type; + u_int32_t reserved[13]; +}; + +/* + * I O C T L C O D E S F O R V I D E O D E V I C E S + * + */ +#define VIDIOC_QUERYCAP _IOR('V', 0, struct v4l2_capability) +#define VIDIOC_ENUM_FMT _IOWR('V', 2, struct v4l2_fmtdesc) +#define VIDIOC_G_FMT _IOWR('V', 4, struct v4l2_format) +#define VIDIOC_S_FMT _IOWR('V', 5, struct v4l2_format) +#define VIDIOC_REQBUFS _IOWR('V', 8, struct v4l2_requestbuffers) +#define VIDIOC_QUERYBUF _IOWR('V', 9, struct v4l2_buffer) +#define VIDIOC_G_FBUF _IOR('V', 10, struct v4l2_framebuffer) +#define VIDIOC_S_FBUF _IOW('V', 11, struct v4l2_framebuffer) +#define VIDIOC_OVERLAY _IOW('V', 14, int) +#define VIDIOC_QBUF _IOWR('V', 15, struct v4l2_buffer) +#define VIDIOC_EXPBUF _IOWR('V', 16, struct v4l2_exportbuffer) +#define VIDIOC_DQBUF _IOWR('V', 17, struct v4l2_buffer) +#define VIDIOC_STREAMON _IOW('V', 18, int) +#define VIDIOC_STREAMOFF _IOW('V', 19, int) +#define VIDIOC_G_PARM _IOWR('V', 21, struct v4l2_streamparm) +#define VIDIOC_S_PARM _IOWR('V', 22, struct v4l2_streamparm) +#define VIDIOC_G_STD _IOR('V', 23, v4l2_std_id) +#define VIDIOC_S_STD _IOW('V', 24, v4l2_std_id) +#define VIDIOC_ENUMSTD _IOWR('V', 25, struct v4l2_standard) +#define VIDIOC_ENUMINPUT _IOWR('V', 26, struct v4l2_input) +#define VIDIOC_G_CTRL _IOWR('V', 27, struct v4l2_control) +#define VIDIOC_S_CTRL _IOWR('V', 28, struct v4l2_control) +#define VIDIOC_G_TUNER _IOWR('V', 29, struct v4l2_tuner) +#define VIDIOC_S_TUNER _IOW('V', 30, struct v4l2_tuner) +#define VIDIOC_G_AUDIO _IOR('V', 33, struct v4l2_audio) +#define VIDIOC_S_AUDIO _IOW('V', 34, struct v4l2_audio) +#define VIDIOC_QUERYCTRL _IOWR('V', 36, struct v4l2_queryctrl) +#define VIDIOC_QUERYMENU _IOWR('V', 37, struct v4l2_querymenu) +#define VIDIOC_G_INPUT _IOR('V', 38, int) +#define VIDIOC_S_INPUT _IOWR('V', 39, int) +#define VIDIOC_G_EDID _IOWR('V', 40, struct v4l2_edid) +#define VIDIOC_S_EDID _IOWR('V', 41, struct v4l2_edid) +#define VIDIOC_G_OUTPUT _IOR('V', 46, int) +#define VIDIOC_S_OUTPUT _IOWR('V', 47, int) +#define VIDIOC_ENUMOUTPUT _IOWR('V', 48, struct v4l2_output) +#define VIDIOC_G_AUDOUT _IOR('V', 49, struct v4l2_audioout) +#define VIDIOC_S_AUDOUT _IOW('V', 50, struct v4l2_audioout) +#define VIDIOC_G_MODULATOR _IOWR('V', 54, struct v4l2_modulator) +#define VIDIOC_S_MODULATOR _IOW('V', 55, struct v4l2_modulator) +#define VIDIOC_G_FREQUENCY _IOWR('V', 56, struct v4l2_frequency) +#define VIDIOC_S_FREQUENCY _IOW('V', 57, struct v4l2_frequency) +#define VIDIOC_CROPCAP _IOWR('V', 58, struct v4l2_cropcap) +#define VIDIOC_G_CROP _IOWR('V', 59, struct v4l2_crop) +#define VIDIOC_S_CROP _IOW('V', 60, struct v4l2_crop) +#define VIDIOC_G_JPEGCOMP _IOR('V', 61, struct v4l2_jpegcompression) +#define VIDIOC_S_JPEGCOMP _IOW('V', 62, struct v4l2_jpegcompression) +#define VIDIOC_QUERYSTD _IOR('V', 63, v4l2_std_id) +#define VIDIOC_TRY_FMT _IOWR('V', 64, struct v4l2_format) +#define VIDIOC_ENUMAUDIO _IOWR('V', 65, struct v4l2_audio) +#define VIDIOC_ENUMAUDOUT _IOWR('V', 66, struct v4l2_audioout) +#define VIDIOC_G_PRIORITY _IOR('V', 67, u_int32_t) /* enum v4l2_priority */ +#define VIDIOC_S_PRIORITY _IOW('V', 68, u_int32_t) /* enum v4l2_priority */ +#define VIDIOC_G_SLICED_VBI_CAP _IOWR('V', 69, struct v4l2_sliced_vbi_cap) +#define VIDIOC_LOG_STATUS _IO('V', 70) +#define VIDIOC_G_EXT_CTRLS _IOWR('V', 71, struct v4l2_ext_controls) +#define VIDIOC_S_EXT_CTRLS _IOWR('V', 72, struct v4l2_ext_controls) +#define VIDIOC_TRY_EXT_CTRLS _IOWR('V', 73, struct v4l2_ext_controls) +#define VIDIOC_ENUM_FRAMESIZES _IOWR('V', 74, struct v4l2_frmsizeenum) +#define VIDIOC_ENUM_FRAMEINTERVALS _IOWR('V', 75, struct v4l2_frmivalenum) +#define VIDIOC_G_ENC_INDEX _IOR('V', 76, struct v4l2_enc_idx) +#define VIDIOC_ENCODER_CMD _IOWR('V', 77, struct v4l2_encoder_cmd) +#define VIDIOC_TRY_ENCODER_CMD _IOWR('V', 78, struct v4l2_encoder_cmd) + +/* + * Experimental, meant for debugging, testing and internal use. + * Only implemented if CONFIG_VIDEO_ADV_DEBUG is defined. + * You must be root to use these ioctls. Never use these in applications! + */ +#define VIDIOC_DBG_S_REGISTER _IOW('V', 79, struct v4l2_dbg_register) +#define VIDIOC_DBG_G_REGISTER _IOWR('V', 80, struct v4l2_dbg_register) + +#define VIDIOC_S_HW_FREQ_SEEK _IOW('V', 82, struct v4l2_hw_freq_seek) +#define VIDIOC_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings) +#define VIDIOC_G_DV_TIMINGS _IOWR('V', 88, struct v4l2_dv_timings) +#define VIDIOC_DQEVENT _IOR('V', 89, struct v4l2_event) +#define VIDIOC_SUBSCRIBE_EVENT _IOW('V', 90, struct v4l2_event_subscription) +#define VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 91, struct v4l2_event_subscription) +#define VIDIOC_CREATE_BUFS _IOWR('V', 92, struct v4l2_create_buffers) +#define VIDIOC_PREPARE_BUF _IOWR('V', 93, struct v4l2_buffer) +#define VIDIOC_G_SELECTION _IOWR('V', 94, struct v4l2_selection) +#define VIDIOC_S_SELECTION _IOWR('V', 95, struct v4l2_selection) +#define VIDIOC_DECODER_CMD _IOWR('V', 96, struct v4l2_decoder_cmd) +#define VIDIOC_TRY_DECODER_CMD _IOWR('V', 97, struct v4l2_decoder_cmd) +#define VIDIOC_ENUM_DV_TIMINGS _IOWR('V', 98, struct v4l2_enum_dv_timings) +#define VIDIOC_QUERY_DV_TIMINGS _IOR('V', 99, struct v4l2_dv_timings) +#define VIDIOC_DV_TIMINGS_CAP _IOWR('V', 100, struct v4l2_dv_timings_cap) +#define VIDIOC_ENUM_FREQ_BANDS _IOWR('V', 101, struct v4l2_frequency_band) + +/* + * Experimental, meant for debugging, testing and internal use. + * Never use this in applications! + */ +#define VIDIOC_DBG_G_CHIP_INFO _IOWR('V', 102, struct v4l2_dbg_chip_info) + +#define VIDIOC_QUERY_EXT_CTRL _IOWR('V', 103, struct v4l2_query_ext_ctrl) +#define VIDIOC_REMOVE_BUFS _IOWR('V', 104, struct v4l2_remove_buffers) + + +/* Reminder: when adding new ioctls please add support for them to + drivers/media/v4l2-core/v4l2-compat-ioctl32.c as well! */ + +#define BASE_VIDIOC_PRIVATE 192 /* 192-255 are private */ + +/* Deprecated definitions kept for backwards compatibility */ +#define V4L2_PIX_FMT_HM12 V4L2_PIX_FMT_NV12_16L16 +#define V4L2_PIX_FMT_SUNXI_TILED_NV12 V4L2_PIX_FMT_NV12_32L32 +/* + * This capability was never implemented, anyone using this cap should drop it + * from their code. + */ +#define V4L2_CAP_ASYNCIO 0x02000000 + +#endif /* _SYS_VIDEOIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/vmmeter.h b/lib/libc/include/generic-openbsd/sys/vmmeter.h new file mode 100644 index 000000000000..547065fe13f1 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/vmmeter.h @@ -0,0 +1,97 @@ +/* $OpenBSD: vmmeter.h,v 1.15 2016/07/27 14:44:59 tedu Exp $ */ +/* $NetBSD: vmmeter.h,v 1.9 1995/03/26 20:25:04 jtc Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vmmeter.h 8.2 (Berkeley) 7/10/94 + */ + +#ifndef __VMMETER_H__ +#define __VMMETER_H__ + +/* + * System wide statistics counters. Look in for the + * UVM equivalent. + */ + +/* systemwide totals computed every five seconds */ +struct vmtotal { + u_int16_t t_rq; /* length of the run queue */ + u_int16_t t_dw; /* jobs in ``disk wait'' (neg priority) */ + u_int16_t t_pw; /* jobs in page wait */ + u_int16_t t_sl; /* jobs sleeping in core */ + u_int16_t t_sw; /* swapped out runnable/short block jobs */ + u_int32_t t_vm; /* total virtual memory */ + u_int32_t t_avm; /* active virtual memory */ + u_int32_t t_rm; /* total real memory in use */ + u_int32_t t_arm; /* active real memory */ + u_int32_t t_vmshr; /* shared virtual memory */ + u_int32_t t_avmshr; /* active shared virtual memory */ + u_int32_t t_rmshr; /* shared real memory */ + u_int32_t t_armshr; /* active shared real memory */ + u_int32_t t_free; /* free memory pages */ +}; + +/* + * Fork/vfork/__tfork accounting. + */ +struct forkstat { + uint32_t cntfork; /* number of fork() calls */ + uint32_t cntvfork; /* number of vfork() calls */ + uint32_t cnttfork; /* number of __tfork() calls */ + uint32_t cntkthread; /* number of kernel threads created */ + uint64_t sizfork; /* VM pages affected by fork() */ + uint64_t sizvfork; /* VM pages affected by vfork() */ + uint64_t siztfork; /* VM pages affected by __tfork() */ + uint64_t sizkthread; /* VM pages affected by kernel threads */ +}; + +/* These sysctl names are only really used by sysctl(8) */ +#define KERN_FORKSTAT_FORK 1 +#define KERN_FORKSTAT_VFORK 2 +#define KERN_FORKSTAT_TFORK 3 +#define KERN_FORKSTAT_KTHREAD 4 +#define KERN_FORKSTAT_SIZFORK 5 +#define KERN_FORKSTAT_SIZVFORK 6 +#define KERN_FORKSTAT_SIZTFORK 7 +#define KERN_FORKSTAT_SIZKTHREAD 8 +#define KERN_FORKSTAT_MAXID 9 + +#define CTL_KERN_FORKSTAT_NAMES { \ + { 0, 0 }, \ + { "forks", CTLTYPE_INT }, \ + { "vforks", CTLTYPE_INT }, \ + { "tforks", CTLTYPE_INT }, \ + { "kthreads", CTLTYPE_INT }, \ + { "fork_pages", CTLTYPE_INT }, \ + { "vfork_pages", CTLTYPE_INT }, \ + { "tfork_pages", CTLTYPE_INT }, \ + { "kthread_pages", CTLTYPE_INT }, \ +} +#endif /* __VMMETER_H__ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/vnode.h b/lib/libc/include/generic-openbsd/sys/vnode.h new file mode 100644 index 000000000000..656c10118b09 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/vnode.h @@ -0,0 +1,650 @@ +/* $OpenBSD: vnode.h,v 1.179 2025/09/25 09:05:47 mpi Exp $ */ +/* $NetBSD: vnode.h,v 1.38 1996/02/29 20:59:05 cgd Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vnode.h 8.11 (Berkeley) 11/21/94 + */ + +#ifndef _SYS_VNODE_H_ +#define _SYS_VNODE_H_ + +#include +#include +#include +#include +#include + +/* + * The vnode is the focus of all file activity in UNIX. There is a + * unique vnode allocated for each active file, each current directory, + * each mounted-on file, text file, and the root. + */ + +/* + * Vnode types. VNON means no type. + */ +enum vtype { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO, VBAD }; + +#define VTYPE_NAMES \ + "VNON", "VREG", "VDIR", "VBLK", "VCHR", "VLNK", "VSOCK", "VFIFO", "VBAD" + +/* + * Vnode tag types. + * These are for the benefit of external programs only (e.g., pstat) + * and should NEVER be inspected by the kernel. + * + * Note that v_tag is actually used to tell MFS from FFS, and EXT2FS from + * the rest, so don't believe the above comment! + */ +enum vtagtype { + VT_NON, VT_UFS, VT_NFS, VT_MFS, VT_MSDOSFS, + VT_PORTAL, VT_PROCFS, VT_AFS, VT_ISOFS, VT_ADOSFS, + VT_EXT2FS, VT_VFS, VT_NTFS, VT_UDF, VT_FUSEFS, VT_TMPFS, +}; + +#define VTAG_NAMES \ + "NON", "UFS", "NFS", "MFS", "MSDOSFS", \ + "unused", "unused", "unused", "ISOFS", "unused", \ + "EXT2FS", "VFS", "NTFS", "UDF", "FUSEFS", "TMPFS" + +/* + * Each underlying filesystem allocates its own private area and hangs + * it from v_data. If non-null, this area is freed in getnewvnode(). + */ +LIST_HEAD(buflists, buf); + +RBT_HEAD(buf_rb_bufs, buf); + +struct namecache; +RBT_HEAD(namecache_rb_cache, namecache); + +/* + * Locks used to protect struct members in struct vnode: + * a atomic + * V vnode_mtx + * B IPL_BIO + */ +struct uvm_vnode; +struct vnode { + struct uvm_vnode *v_uvm; /* uvm data */ + const struct vops *v_op; /* vnode operations vector */ + enum vtype v_type; /* vnode type */ + enum vtagtype v_tag; /* type of underlying data */ + u_int v_flag; /* vnode flags (see below) */ + u_int v_lflag; /* [V] lock vnode flags */ + u_int v_usecount; /* reference count of users */ + u_int v_uvcount; /* unveil references */ + u_int v_writecount; /* reference count of writers */ + u_int v_lockcount; /* [V] # threads waiting on lock */ + + u_int v_bioflag; /* [B] flags accessed in interrupts */ + u_int v_holdcnt; /* [B] buffer references */ + u_int v_id; /* capability identifier */ + struct mount *v_mount; /* ptr to vfs we are in */ + TAILQ_ENTRY(vnode) v_freelist; /* [B] vnode freelist */ + TAILQ_ENTRY(vnode) v_mntvnodes; /* vnodes for mount point */ + struct buf_rb_bufs v_bufs_tree;/* [B] lookup of all bufs */ + struct buflists v_cleanblkhd; /* [B] clean blocklist head */ + struct buflists v_dirtyblkhd; /* [B] dirty blocklist head */ + u_int v_numoutput; /* [B] num of writes in progress */ + LIST_ENTRY(vnode) v_synclist; /* [B] vnode with dirty buffers */ + union { + struct mount *vu_mountedhere;/* ptr to mounted vfs (VDIR) */ + struct socket *vu_socket; /* unix ipc (VSOCK) */ + struct specinfo *vu_specinfo; /* device (VCHR, VBLK) */ + struct fifoinfo *vu_fifoinfo; /* fifo (VFIFO) */ + } v_un; + + /* VFS namecache */ + struct namecache_rb_cache v_nc_tree; + TAILQ_HEAD(, namecache) v_cache_dst; /* cache entries to us */ + + void *v_data; /* private data for fs */ + struct klist v_klist; /* identity of poller(s) */ +}; +#define v_mountedhere v_un.vu_mountedhere +#define v_socket v_un.vu_socket +#define v_specinfo v_un.vu_specinfo +#define v_fifoinfo v_un.vu_fifoinfo + +/* + * Vnode flags. + */ +#define VROOT 0x0001 /* root of its file system */ +#define VTEXT 0x0002 /* vnode is a pure text prototype */ +#define VSYSTEM 0x0004 /* vnode being used by kernel */ +#define VISTTY 0x0008 /* vnode represents a tty */ +#define VXLOCK 0x0100 /* vnode is locked to change underlying type */ +#define VXWANT 0x0200 /* process is waiting for vnode */ +#define VCLONED 0x0400 /* vnode was cloned */ +#define VALIASED 0x0800 /* vnode has an alias */ +#define VLARVAL 0x1000 /* vnode data not yet set up by higher level */ +#define VLOCKSWORK 0x4000 /* FS supports locking discipline */ +#define VCLONE 0x8000 /* vnode is a clone */ + +/* + * (v_bioflag) Flags that may be manipulated by interrupt handlers + */ +#define VBIOWAIT 0x0001 /* waiting for output to complete */ +#define VBIOONSYNCLIST 0x0002 /* Vnode is on syncer worklist */ +#define VBIOONFREELIST 0x0004 /* Vnode is on a free list */ +#define VBIOERROR 0x0008 /* A write failed */ + +/* + * Vnode attributes. A field value of VNOVAL represents a field whose value + * is unavailable (getattr) or which is not to be changed (setattr). For + * the timespec fields, only the tv_nsec member needs to be set to VNOVAL: + * if tv_nsec != VNOVAL then both tv_sec and tv_nsec are valid. + */ +struct vattr { + enum vtype va_type; /* vnode type (for create) */ + mode_t va_mode; /* files access mode and type */ + nlink_t va_nlink; /* number of references to file */ + uid_t va_uid; /* owner user id */ + gid_t va_gid; /* owner group id */ + long va_fsid; /* file system id (dev for now) */ + u_quad_t va_fileid; /* file id */ + u_quad_t va_size; /* file size in bytes */ + long va_blocksize; /* blocksize preferred for i/o */ + struct timespec va_atime; /* time of last access */ + struct timespec va_mtime; /* time of last modification */ + struct timespec va_ctime; /* time file changed */ + u_long va_gen; /* generation number of file */ + u_long va_flags; /* flags defined for file */ + dev_t va_rdev; /* device the special file represents */ + u_quad_t va_bytes; /* bytes of disk space held by file */ + u_quad_t va_filerev; /* file modification number */ + u_int va_vaflags; /* operations flags, see below */ + long va_spare; /* remain quad aligned */ +}; + +/* + * Flags for va_vaflags. + */ +#define VA_UTIMES_NULL 0x01 /* utimes argument was NULL */ +#define VA_EXCLUSIVE 0x02 /* exclusive create request */ +#define VA_UTIMES_CHANGE 0x04 /* ctime should be updated */ +/* + * Flags for ioflag. + */ +#define IO_UNIT 0x01 /* do I/O as atomic unit */ +#define IO_APPEND 0x02 /* append write to end */ +#define IO_SYNC 0x04 /* do I/O synchronously */ +#define IO_NODELOCKED 0x08 /* underlying node already locked */ +#define IO_NDELAY 0x10 /* FNDELAY flag set in file table */ +#define IO_NOLIMIT 0x20 /* don't enforce limits on i/o */ +#define IO_NOCACHE 0x40 /* don't cache result of this i/o */ + +/* + * Modes. Some values same as Ixxx entries from inode.h for now. + */ +#define VSUID 04000 /* set user id on execution */ +#define VSGID 02000 /* set group id on execution */ +#define VSVTX 01000 /* save swapped text even after use */ +#define VREAD 00400 /* read, write, execute permissions */ +#define VWRITE 00200 +#define VEXEC 00100 + +/* + * Token indicating no attribute value yet assigned. + */ +#define VNOVAL (-1) + +#ifdef _KERNEL +RBT_PROTOTYPE(buf_rb_bufs, buf, b_rbbufs, rb_buf_compare); +/* + * Convert between vnode types and inode formats (since POSIX.1 + * defines mode word of stat structure in terms of inode formats). + */ +extern enum vtype iftovt_tab[]; +extern int vttoif_tab[]; +#define IFTOVT(mode) (iftovt_tab[((mode) & S_IFMT) >> 12]) +#define VTTOIF(indx) (vttoif_tab[(int)(indx)]) +#define MAKEIMODE(indx, mode) (int)(VTTOIF(indx) | (mode)) + +/* + * Flags to various vnode functions. + */ +#define SKIPSYSTEM 0x0001 /* vflush: skip vnodes marked VSYSTEM */ +#define FORCECLOSE 0x0002 /* vflush: force file closure */ +#define WRITECLOSE 0x0004 /* vflush: only close writeable files */ +#define DOCLOSE 0x0008 /* vclean: close active files */ +#define IGNORECLEAN 0x0010 /* vflush: ignore clean vnodes */ +#define V_SAVE 0x0001 /* vinvalbuf: sync file first */ +#define V_SAVEMETA 0x0002 /* vinvalbuf: leave indirect blocks */ + +#define REVOKEALL 0x0001 /* vop_revoke: revoke all aliases */ + + +#define VN_KNOTE(vp, b) \ + knote_locked(&vp->v_klist, (b)) + +/* + * Global vnode data. + */ +extern struct vnode *rootvnode; /* root (i.e. "/") vnode */ +extern int initialvnodes; /* XXX number of vnodes to start */ +extern int maxvnodes; /* XXX number of vnodes to allocate */ +extern int syncdelay; /* seconds to delay syncing vnodes */ +extern int rushjob; /* # of slots syncer should run ASAP */ +extern struct mutex vnode_mtx; +extern void vhold(struct vnode *); +extern void vdrop(struct vnode *); + +/* vnode operations */ +struct vops { + int (*vop_lock)(void *); + int (*vop_unlock)(void *); + int (*vop_islocked)(void *); + int (*vop_abortop)(void *); + int (*vop_access)(void *); + int (*vop_advlock)(void *); + int (*vop_bmap)(void *); + int (*vop_bwrite)(void *); + int (*vop_close)(void *); + int (*vop_create)(void *); + int (*vop_fsync)(void *); + int (*vop_getattr)(void *); + int (*vop_inactive)(void *); + int (*vop_ioctl)(void *); + int (*vop_link)(void *); + int (*vop_lookup)(void *); + int (*vop_mknod)(void *); + int (*vop_open)(void *); + int (*vop_pathconf)(void *); + int (*vop_print)(void *); + int (*vop_read)(void *); + int (*vop_readdir)(void *); + int (*vop_readlink)(void *); + int (*vop_reclaim)(void *); + int (*vop_remove)(void *); + int (*vop_rename)(void *); + int (*vop_revoke)(void *); + int (*vop_mkdir)(void *); + int (*vop_rmdir)(void *); + int (*vop_setattr)(void *); + int (*vop_strategy)(void *); + int (*vop_symlink)(void *); + int (*vop_write)(void *); + int (*vop_kqfilter)(void *); +}; + +extern const struct vops dead_vops; +extern const struct vops spec_vops; + +struct vop_generic_args { + void *a_garbage; + /* Other data probably follows; */ +}; + +struct vop_islocked_args { + struct vnode *a_vp; +}; +int VOP_ISLOCKED(struct vnode *); + +struct vop_lookup_args { + struct vnode *a_dvp; + struct vnode **a_vpp; + struct componentname *a_cnp; +}; +int VOP_LOOKUP(struct vnode *, struct vnode **, struct componentname *); + +struct vop_create_args { + struct vnode *a_dvp; + struct vnode **a_vpp; + struct componentname *a_cnp; + struct vattr *a_vap; +}; +int VOP_CREATE(struct vnode *, struct vnode **, struct componentname *, + struct vattr *); + +struct vop_mknod_args { + struct vnode *a_dvp; + struct vnode **a_vpp; + struct componentname *a_cnp; + struct vattr *a_vap; +}; +int VOP_MKNOD(struct vnode *, struct vnode **, struct componentname *, + struct vattr *); + +struct vop_open_args { + struct vnode *a_vp; + int a_mode; + struct ucred *a_cred; + struct proc *a_p; +}; +int VOP_OPEN(struct vnode *, int, struct ucred *, struct proc *); + +struct vop_close_args { + struct vnode *a_vp; + int a_fflag; + struct ucred *a_cred; + struct proc *a_p; +}; +int VOP_CLOSE(struct vnode *, int, struct ucred *, struct proc *); + +struct vop_access_args { + struct vnode *a_vp; + int a_mode; + struct ucred *a_cred; + struct proc *a_p; +}; +int VOP_ACCESS(struct vnode *, int, struct ucred *, struct proc *); + +struct vop_getattr_args { + struct vnode *a_vp; + struct vattr *a_vap; + struct ucred *a_cred; + struct proc *a_p; +}; +int VOP_GETATTR(struct vnode *, struct vattr *, struct ucred *, struct proc *); + +struct vop_setattr_args { + struct vnode *a_vp; + struct vattr *a_vap; + struct ucred *a_cred; + struct proc *a_p; +}; +int VOP_SETATTR(struct vnode *, struct vattr *, struct ucred *, struct proc *); + +struct vop_read_args { + struct vnode *a_vp; + struct uio *a_uio; + int a_ioflag; + struct ucred *a_cred; +}; +int VOP_READ(struct vnode *, struct uio *, int, struct ucred *); + +struct vop_write_args { + struct vnode *a_vp; + struct uio *a_uio; + int a_ioflag; + struct ucred *a_cred; +}; +int VOP_WRITE(struct vnode *, struct uio *, int, struct ucred *); + +struct vop_ioctl_args { + struct vnode *a_vp; + u_long a_command; + void *a_data; + int a_fflag; + struct ucred *a_cred; + struct proc *a_p; +}; +int VOP_IOCTL(struct vnode *, u_long, void *, int, struct ucred *, + struct proc *); + +struct vop_kqfilter_args { + struct vnode *a_vp; + int a_fflag; + struct knote *a_kn; +}; +int VOP_KQFILTER(struct vnode *, int, struct knote *); + +struct vop_revoke_args { + struct vnode *a_vp; + int a_flags; +}; +int VOP_REVOKE(struct vnode *, int); + +struct vop_fsync_args { + struct vnode *a_vp; + struct ucred *a_cred; + int a_waitfor; + struct proc *a_p; +}; +int VOP_FSYNC(struct vnode *, struct ucred *, int, struct proc *); + +struct vop_remove_args { + struct vnode *a_dvp; + struct vnode *a_vp; + struct componentname *a_cnp; +}; +int VOP_REMOVE(struct vnode *, struct vnode *, struct componentname *); + +struct vop_link_args { + struct vnode *a_dvp; + struct vnode *a_vp; + struct componentname *a_cnp; +}; +int VOP_LINK(struct vnode *, struct vnode *, struct componentname *); + +struct vop_rename_args { + struct vnode *a_fdvp; + struct vnode *a_fvp; + struct componentname *a_fcnp; + struct vnode *a_tdvp; + struct vnode *a_tvp; + struct componentname *a_tcnp; +}; +int VOP_RENAME(struct vnode *, struct vnode *, struct componentname *, + struct vnode *, struct vnode *, struct componentname *); + +struct vop_mkdir_args { + struct vnode *a_dvp; + struct vnode **a_vpp; + struct componentname *a_cnp; + struct vattr *a_vap; +}; +int VOP_MKDIR(struct vnode *, struct vnode **, struct componentname *, + struct vattr *); + +struct vop_rmdir_args { + struct vnode *a_dvp; + struct vnode *a_vp; + struct componentname *a_cnp; +}; +int VOP_RMDIR(struct vnode *, struct vnode *, struct componentname *); + +struct vop_symlink_args { + struct vnode *a_dvp; + struct vnode **a_vpp; + struct componentname *a_cnp; + struct vattr *a_vap; + char *a_target; +}; +int VOP_SYMLINK(struct vnode *, struct vnode **, struct componentname *, + struct vattr *, char *); + +struct vop_readdir_args { + struct vnode *a_vp; + struct uio *a_uio; + struct ucred *a_cred; + int *a_eofflag; +}; +int VOP_READDIR(struct vnode *, struct uio *, struct ucred *, int *); + +struct vop_readlink_args { + struct vnode *a_vp; + struct uio *a_uio; + struct ucred *a_cred; +}; +int VOP_READLINK(struct vnode *, struct uio *, struct ucred *); + +struct vop_abortop_args { + struct vnode *a_dvp; + struct componentname *a_cnp; +}; +int VOP_ABORTOP(struct vnode *, struct componentname *); + +struct vop_inactive_args { + struct vnode *a_vp; + struct proc *a_p; +}; +int VOP_INACTIVE(struct vnode *, struct proc *); + +struct vop_reclaim_args { + struct vnode *a_vp; + struct proc *a_p; +}; +int VOP_RECLAIM(struct vnode *, struct proc *); + +struct vop_lock_args { + struct vnode *a_vp; + int a_flags; +}; +int VOP_LOCK(struct vnode *, int); + +struct vop_unlock_args { + struct vnode *a_vp; +}; +int VOP_UNLOCK(struct vnode *); + +struct vop_bmap_args { + struct vnode *a_vp; + daddr_t a_bn; + struct vnode **a_vpp; + daddr_t *a_bnp; + int *a_runp; +}; +int VOP_BMAP(struct vnode *, daddr_t, struct vnode **, daddr_t *, int *); + +struct vop_print_args { + struct vnode *a_vp; +}; +int VOP_PRINT(struct vnode *); + +struct vop_pathconf_args { + struct vnode *a_vp; + int a_name; + register_t *a_retval; +}; +int VOP_PATHCONF(struct vnode *, int, register_t *); + +struct vop_advlock_args { + struct vnode *a_vp; + void *a_id; + int a_op; + struct flock *a_fl; + int a_flags; +}; +int VOP_ADVLOCK(struct vnode *, void *, int, struct flock *, int); + +struct vop_strategy_args { + struct vnode *a_vp; + struct buf *a_bp; +}; +int VOP_STRATEGY(struct vnode *, struct buf *); + +/* Special cases: */ +struct vop_bwrite_args { + struct buf *a_bp; +}; +int VOP_BWRITE(struct buf *); +/* End of special cases. */ + + +/* Public vnode manipulation functions. */ +struct file; +struct mount; +struct nameidata; +struct proc; +struct stat; +struct statfs; +struct ucred; +struct uio; +struct vattr; +struct vnode; + +/* vfs_subr */ +int bdevvp(dev_t, struct vnode **); +int cdevvp(dev_t, struct vnode **); +struct vnode *checkalias(struct vnode *, dev_t, struct mount *); +int getnewvnode(enum vtagtype, struct mount *, const struct vops *, + struct vnode **); +int vaccess(enum vtype, mode_t, uid_t, gid_t, mode_t, struct ucred *); +int vnoperm(struct vnode *); +void vattr_null(struct vattr *); +void vdevgone(int, int, int, enum vtype); +int vcount(struct vnode *); +int vfinddev(dev_t, enum vtype, struct vnode **); +void vflushbuf(struct vnode *, int); +int vflush(struct mount *, struct vnode *, int); +int vget(struct vnode *, int); +void vgone(struct vnode *); +void vgonel(struct vnode *, struct proc *); +int vinvalbuf(struct vnode *, int, struct ucred *, struct proc *, + int, uint64_t); +void vntblinit(void); +int vwaitforio(struct vnode *, int, char *, uint64_t); +void vwakeup(struct vnode *); +void vput(struct vnode *); +int vrecycle(struct vnode *, struct proc *); +int vrele(struct vnode *); +void vref(struct vnode *); +void vprint(char *, struct vnode *); +void copy_statfs_info(struct statfs *, const struct mount *); + +/* vfs_getcwd.c */ +#define GETCWD_CHECK_ACCESS 0x0001 +int vfs_getcwd_scandir(struct vnode **, struct vnode **, char **, char *, + struct proc *); +int vfs_getcwd_common(struct vnode *, struct vnode *, char **, char *, int, + int, struct proc *); +int vfs_getcwd_getcache(struct vnode **, struct vnode **, char **, char *); + +/* vfs_default.c */ +int vop_generic_abortop(void *); +int vop_generic_badop(void *); +int vop_generic_bmap(void *); +int vop_generic_bwrite(void *); +int vop_generic_revoke(void *); +int vop_generic_lookup(void *); + +/* vfs_vnops.c */ +int vn_isunder(struct vnode *, struct vnode *, struct proc *); +int vn_close(struct vnode *, int, struct ucred *, struct proc *); +int vn_open(struct nameidata *, int, int); +int vn_rdwr(enum uio_rw, struct vnode *, caddr_t, int, off_t, + enum uio_seg, int, struct ucred *, size_t *, struct proc *); +int vn_stat(struct vnode *, struct stat *, struct proc *); +int vn_statfile(struct file *, struct stat *, struct proc *); +int vn_lock(struct vnode *, int); +int vn_writechk(struct vnode *); +int vn_fsizechk(struct vnode *, struct uio *, int, ssize_t *); +int vn_ioctl(struct file *, u_long, caddr_t, struct proc *); +void vn_marktext(struct vnode *); + +/* vfs_sync.c */ +void syncer_thread(void *); +void vn_initialize_syncerd(void); +void vn_syncer_add_to_worklist(struct vnode *, int); + +/* misc */ +int getvnode(struct proc *, int, struct file **); + +/* uvm */ +void uvm_vnp_setsize(struct vnode *, off_t); +void uvm_vnp_sync(struct mount *); +int uvm_vnp_uncache(struct vnode *); + + +#endif /* _KERNEL */ +#endif /* _SYS_VNODE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/wait.h b/lib/libc/include/generic-openbsd/sys/wait.h new file mode 100644 index 000000000000..f4dd7d83d1d7 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/wait.h @@ -0,0 +1,120 @@ +/* $OpenBSD: wait.h,v 1.20 2022/12/19 00:22:11 guenther Exp $ */ +/* $NetBSD: wait.h,v 1.11 1996/04/09 20:55:51 cgd Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)wait.h 8.2 (Berkeley) 7/10/94 + */ + +#ifndef _SYS_WAIT_H_ +#define _SYS_WAIT_H_ + +#include +#include + +/* + * This file holds definitions relevant to the wait4 system call + * and the alternate interfaces that use it (wait, wait3, waitpid). + */ + +/* + * Macros to test the exit status returned by wait + * and extract the relevant values. + */ +#define _WSTATUS(x) ((x) & 0177) +#define _WSTOPPED 0177 /* _WSTATUS if process is stopped */ +#define _WCONTINUED 0177777 /* process has continued */ +#define WIFSTOPPED(x) (((x) & 0xff) == _WSTOPPED) +#define WSTOPSIG(x) (int)(((unsigned)(x) >> 8) & 0xff) +#define WIFSIGNALED(x) (_WSTATUS(x) != _WSTOPPED && _WSTATUS(x) != 0) +#define WTERMSIG(x) (_WSTATUS(x)) +#define WIFEXITED(x) (_WSTATUS(x) == 0) +#define WEXITSTATUS(x) (int)(((unsigned)(x) >> 8) & 0xff) +#define WIFCONTINUED(x) (((x) & _WCONTINUED) == _WCONTINUED) +#if __XPG_VISIBLE +#define WCOREFLAG 0200 +#define WCOREDUMP(x) ((x) & WCOREFLAG) + +#define W_EXITCODE(ret, sig) ((ret) << 8 | (sig)) +#define W_STOPCODE(sig) ((sig) << 8 | _WSTOPPED) +#endif + +/* + * Option bits for the third argument of wait4. WNOHANG causes the + * wait to not hang if there are no stopped or terminated processes, rather + * returning an error indication in this case (pid==0). WUNTRACED + * indicates that the caller should receive status about untraced children + * which stop due to signals. If children are stopped and a wait without + * this option is done, it is as though they were still running... nothing + * about them is returned. WNOWAIT only requests information about zombie, + * leaving the proc around, available for later waits. + */ +#define WNOHANG 0x01 /* don't hang in wait */ +#define WUNTRACED 0x02 /* report stopped-by-signal processes */ +#define WCONTINUED 0x08 /* report job control continued processes */ +#if __POSIX_VISIBLE >= 200809 || __XPG_VISIBLE >= 420 +#define WEXITED 0x04 /* report exited processes */ +#define WSTOPPED WUNTRACED +#define WNOWAIT 0x10 /* poll only */ +#define WTRAPPED 0x20 /* report stopped-by-tracing processes */ + +typedef enum { + P_ALL, + P_PGID, + P_PID +} idtype_t; +#endif + +#if __BSD_VISIBLE +/* + * Tokens for special values of the "pid" parameter to wait4. + */ +#define WAIT_ANY (-1) /* any process */ +#define WAIT_MYPGRP 0 /* any process in my process group */ +#endif /* __BSD_VISIBLE */ + +#ifndef _KERNEL +#include + +__BEGIN_DECLS +struct rusage; /* forward declaration */ + +pid_t wait(int *); +pid_t waitpid(pid_t, int *, int); +#if __POSIX_VISIBLE >= 200809 || __XPG_VISIBLE >= 420 +int waitid(idtype_t, id_t, siginfo_t *, int); +#endif +#if __BSD_VISIBLE +pid_t wait3(int *, int, struct rusage *); +pid_t wait4(pid_t, int *, int, struct rusage *); +#endif /* __BSD_VISIBLE */ +__END_DECLS +#endif /* !_KERNEL */ + +#endif /* !_SYS_WAIT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/witness.h b/lib/libc/include/generic-openbsd/sys/witness.h new file mode 100644 index 000000000000..231ed70b5ebe --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/witness.h @@ -0,0 +1,165 @@ +/* $OpenBSD: witness.h,v 1.7 2025/07/05 09:24:37 jsg Exp $ */ + +/*- + * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Berkeley Software Design Inc's name may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``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 BERKELEY SOFTWARE DESIGN INC BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from BSDI Id: mutex.h,v 2.7.2.35 2000/04/27 03:10:26 cp + * $FreeBSD: head/sys/sys/lock.h 313908 2017-02-18 01:52:10Z mjg $ + */ + +#ifndef _SYS_WITNESS_H_ +#define _SYS_WITNESS_H_ + +#include + +/* + * Lock classes are statically assigned an index into the global lock_classes + * array. Debugging code looks up the lock class for a given lock object + * by indexing the array. + */ +#define LO_CLASSINDEX(lock) \ + ((((lock)->lo_flags) & LO_CLASSMASK) >> LO_CLASSSHIFT) +#define LOCK_CLASS(lock) \ + (lock_classes[LO_CLASSINDEX((lock))]) +#define LOCK_CLASS_MAX \ + (LO_CLASSMASK >> LO_CLASSSHIFT) + +/* + * Option flags passed to lock operations that witness also needs to know + * about or that are generic across all locks. + */ +#define LOP_NEWORDER 0x00000001 /* Define a new lock order. */ +#define LOP_QUIET 0x00000002 /* Don't log locking operations. */ +#define LOP_TRYLOCK 0x00000004 /* Don't check lock order. */ +#define LOP_EXCLUSIVE 0x00000008 /* Exclusive lock. */ +#define LOP_DUPOK 0x00000010 /* Don't check for duplicate acquires */ + +/* Flags passed to witness_assert. */ +#define LA_MASKASSERT 0x000000ff /* Mask for witness defined asserts. */ +#define LA_UNLOCKED 0x00000000 /* Lock is unlocked. */ +#define LA_LOCKED 0x00000001 /* Lock is at least share locked. */ +#define LA_SLOCKED 0x00000002 /* Lock is exactly share locked. */ +#define LA_XLOCKED 0x00000004 /* Lock is exclusively locked. */ +#define LA_RECURSED 0x00000008 /* Lock is recursed. */ +#define LA_NOTRECURSED 0x00000010 /* Lock is not recursed. */ + +#ifdef _KERNEL + +void witness_initialize(void); +void witness_init(struct lock_object *, const struct lock_type *); +int witness_defineorder(struct lock_object *, struct lock_object *); +void witness_checkorder(struct lock_object *, int, struct lock_object *); +void witness_lock(struct lock_object *, int); +void witness_upgrade(struct lock_object *, int); +void witness_downgrade(struct lock_object *, int); +void witness_unlock(struct lock_object *, int); +void witness_setrelative(struct lock_object *, struct lock_object *, int); +int witness_warn(int, struct lock_object *, const char *, ...); +void witness_assert(const struct lock_object *, int); +void witness_display_spinlock(struct lock_object *, struct proc *, + int (*)(const char *, ...)); +void witness_norelease(struct lock_object *); +void witness_releaseok(struct lock_object *); +void witness_thread_exit(struct proc *); +int witness_sysctl(int *, u_int, void *, size_t *, void *, size_t); +int witness_sysctl_watch(void *, size_t *, void *, size_t); + +#ifdef WITNESS + +/* Flags for witness_warn(). */ +#define WARN_KERNELOK 0x01 /* Kernel lock is exempt from this check. */ +#define WARN_PANIC 0x02 /* Panic if check fails. */ +#define WARN_SLEEPOK 0x04 /* Sleepable locks are exempt from check. */ + +#define WITNESS_INITIALIZE() \ + witness_initialize() + +#define WITNESS_INIT(lock, type) \ + witness_init((lock), (type)) + +#define WITNESS_CHECKORDER(lock, flags, interlock) \ + witness_checkorder((lock), (flags), (interlock)) + +#define WITNESS_DEFINEORDER(lock1, lock2) \ + witness_defineorder((struct lock_object *)(lock1), \ + (struct lock_object *)(lock2)) + +#define WITNESS_LOCK(lock, flags) \ + witness_lock((lock), (flags)) + +#define WITNESS_UPGRADE(lock, flags) \ + witness_upgrade((lock), (flags)) + +#define WITNESS_DOWNGRADE(lock, flags) \ + witness_downgrade((lock), (flags)) + +#define WITNESS_UNLOCK(lock, flags) \ + witness_unlock((lock), (flags)) + +/* Set permitted child lock for lock. */ +#define WITNESS_SETCHILD(lock, child) \ + witness_setrelative((lock), (child), 0) + +/* Set permitted parent lock for lock. */ +#define WITNESS_SETPARENT(lock, parent) \ + witness_setrelative((lock), (parent), 1) + +#define WITNESS_CHECK(flags, lock, fmt, ...) \ + witness_warn((flags), (lock), (fmt), ## __VA_ARGS__) + +#define WITNESS_WARN(flags, lock, fmt, ...) \ + witness_warn((flags), (lock), (fmt), ## __VA_ARGS__) + +#define WITNESS_NORELEASE(lock) \ + witness_norelease(&(lock)->lock_object) + +#define WITNESS_RELEASEOK(lock) \ + witness_releaseok(&(lock)->lock_object) + +#define WITNESS_THREAD_EXIT(p) \ + witness_thread_exit((p)) + +#else /* WITNESS */ +#define WITNESS_INITIALIZE() (void)0 +#define WITNESS_INIT(lock, type) (void)0 +#define WITNESS_DEFINEORDER(lock1, lock2) 0 +#define WITNESS_CHECKORDER(lock, flagsi, interlock) (void)0 +#define WITNESS_LOCK(lock, flags) (void)0 +#define WITNESS_UPGRADE(lock, flags) (void)0 +#define WITNESS_DOWNGRADE(lock, flags) (void)0 +#define WITNESS_UNLOCK(lock, flags) (void)0 +#define WITNESS_SETCHILD(lock, child) (void)0 +#define WITNESS_SETPARENT(lock, parent) (void)0 +#define WITNESS_CHECK(flags, lock, fmt, ...) 0 +#define WITNESS_WARN(flags, lock, fmt, ...) (void)0 +#define WITNESS_NORELEASE(lock) (void)0 +#define WITNESS_RELEASEOK(lock) (void)0 +#define WITNESS_THREAD_EXIT(p) (void)0 +#endif /* WITNESS */ + +#endif /* _KERNEL */ +#endif /* _SYS_WITNESS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sys/xcall.h b/lib/libc/include/generic-openbsd/sys/xcall.h new file mode 100644 index 000000000000..b4ec9d497ad7 --- /dev/null +++ b/lib/libc/include/generic-openbsd/sys/xcall.h @@ -0,0 +1,84 @@ +/* $OpenBSD: xcall.h,v 1.1 2025/07/13 05:45:21 dlg Exp $ */ + +/* + * Copyright (c) 2025 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * CPU crosscall API + * + * Work to execute on a CPU is wrapped in a struct xcall, which is + * like a task or timeout. Each CPU (in an MP kernel) has an array + * of pointers to xcall structs. The local CPU uses CAS ops to try + * and swap their xcall onto one of the slots on the remote CPU, + * and will spin until space becomes available. Once the xcall has + * been added, an IPI is sent to the remote CPU to kick of processing + * of the array. The xcall IPI handler defers processing of the + * xcall array to a low IPL level using a softintr handler. + * + * To implement this API on an architecture requires the following: + * + * 1. A device has to depend on the xcall attribute to have the + * xcall code included in the kernel build. e.g., on amd64 the cpu + * device depends on the xcall attribute, as defined in + * src/sys/arch/amd64/conf/files.amd64: + * + * device cpu: xcall + * + * The rest of the changes are only necessary for MULTIPROCESSOR builds: + * + * 2. struct cpu_info has to have a `struct xcall_cpu ci_xcall` member. + * + * 3. cpu_xcall_establish has to be called against each cpu_info struct. + * + * 4. cpu_xcall_ipi has to be provided by machine/intr.h. + * + * 5. The MD xcall IPI handler has to call cpu_xcall_dispatch. + */ + +#ifndef _SYS_XCALL_H +#define _SYS_XCALL_H + +struct xcall { + void (*xc_func)(void *); + void *xc_arg; +}; + +/* MD code adds this to struct cpu_info as ci_xcall */ +struct xcall_cpu { + struct xcall *xci_xcalls[4]; + void *xci_softintr; +}; + +#ifdef _KERNEL +#define XCALL_INITIALIZER(_f, _a) { \ + .xc_func = _f, \ + .xc_arg = _a, \ +} + +void cpu_xcall_set(struct xcall *, void (*)(void *), void *); +void cpu_xcall(struct cpu_info *, struct xcall *); + +void cpu_xcall_sync(struct cpu_info *, void (*)(void *), void *, + const char *); + +/* MD cpu setup calls this */ +void cpu_xcall_establish(struct cpu_info *); +/* MD ipi handler calls this */ +void cpu_xcall_dispatch(struct cpu_info *); + +#endif /* _KERNEL */ + +#endif /* _SYS_XCALL_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/sysexits.h b/lib/libc/include/generic-openbsd/sysexits.h new file mode 100644 index 000000000000..c78c27e7e18d --- /dev/null +++ b/lib/libc/include/generic-openbsd/sysexits.h @@ -0,0 +1,119 @@ +/* $OpenBSD: sysexits.h,v 1.5 2003/06/02 19:34:12 millert Exp $ */ +/* $NetBSD: sysexits.h,v 1.4 1994/10/26 00:56:33 cgd Exp $ */ + +/* + * Copyright (c) 1987 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)sysexits.h 4.8 (Berkeley) 4/3/91 + */ + +#ifndef _SYSEXITS_H_ +#define _SYSEXITS_H_ + +/* + * SYSEXITS.H -- Exit status codes for system programs. + * + * This include file attempts to categorize possible error + * exit statuses for system programs, notably delivermail + * and the Berkeley network. + * + * Error numbers begin at EX__BASE to reduce the possibility of + * clashing with other exit statuses that random programs may + * already return. The meaning of the codes is approximately + * as follows: + * + * EX_USAGE -- The command was used incorrectly, e.g., with + * the wrong number of arguments, a bad flag, a bad + * syntax in a parameter, or whatever. + * EX_DATAERR -- The input data was incorrect in some way. + * This should only be used for user's data & not + * system files. + * EX_NOINPUT -- An input file (not a system file) did not + * exist or was not readable. This could also include + * errors like "No message" to a mailer (if it cared + * to catch it). + * EX_NOUSER -- The user specified did not exist. This might + * be used for mail addresses or remote logins. + * EX_NOHOST -- The host specified did not exist. This is used + * in mail addresses or network requests. + * EX_UNAVAILABLE -- A service is unavailable. This can occur + * if a support program or file does not exist. This + * can also be used as a catchall message when something + * you wanted to do doesn't work, but you don't know + * why. + * EX_SOFTWARE -- An internal software error has been detected. + * This should be limited to non-operating system related + * errors as possible. + * EX_OSERR -- An operating system error has been detected. + * This is intended to be used for such things as "cannot + * fork", "cannot create pipe", or the like. It includes + * things like getuid returning a user that does not + * exist in the passwd file. + * EX_OSFILE -- Some system file (e.g., /etc/passwd, /var/run/utmp, + * etc.) does not exist, cannot be opened, or has some + * sort of error (e.g., syntax error). + * EX_CANTCREAT -- A (user specified) output file cannot be + * created. + * EX_IOERR -- An error occurred while doing I/O on some file. + * EX_TEMPFAIL -- temporary failure, indicating something that + * is not really an error. In sendmail, this means + * that a mailer (e.g.) could not create a connection, + * and the request should be reattempted later. + * EX_PROTOCOL -- the remote system returned something that + * was "not possible" during a protocol exchange. + * EX_NOPERM -- You did not have sufficient permission to + * perform the operation. This is not intended for + * file system problems, which should use EX_NOINPUT or + * EX_CANTCREAT, but rather for higher level permissions. + * EX_CONFIG -- Something was found in an unconfigured or + * misconfigured state. + */ + +#define EX_OK 0 /* successful termination */ + +#define EX__BASE 64 /* base value for error messages */ + +#define EX_USAGE 64 /* command line usage error */ +#define EX_DATAERR 65 /* data format error */ +#define EX_NOINPUT 66 /* cannot open input */ +#define EX_NOUSER 67 /* addressee unknown */ +#define EX_NOHOST 68 /* host name unknown */ +#define EX_UNAVAILABLE 69 /* service unavailable */ +#define EX_SOFTWARE 70 /* internal software error */ +#define EX_OSERR 71 /* system error (e.g., can't fork) */ +#define EX_OSFILE 72 /* critical OS file missing */ +#define EX_CANTCREAT 73 /* can't create (user) output file */ +#define EX_IOERR 74 /* input/output error */ +#define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */ +#define EX_PROTOCOL 76 /* remote error in protocol */ +#define EX_NOPERM 77 /* permission denied */ +#define EX_CONFIG 78 /* configuration error */ + +#define EX__MAX 78 /* maximum listed value */ + +#endif /* !_SYSEXITS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/syslog.h b/lib/libc/include/generic-openbsd/syslog.h new file mode 100644 index 000000000000..b4af686209a4 --- /dev/null +++ b/lib/libc/include/generic-openbsd/syslog.h @@ -0,0 +1,220 @@ +/* $OpenBSD: syslog.h,v 1.19 2023/04/27 23:16:18 gnezdo Exp $ */ +/* $NetBSD: syslog.h,v 1.14 1996/04/03 20:46:44 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)syslog.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _SYS_SYSLOG_H_ +#define _SYS_SYSLOG_H_ + +#define _PATH_LOG "/dev/log" + +#define LIOCSFD _IOW('l', 127, int) /* set sendsyslog() fd */ + +#define LOG_MAXLINE 8192 /* maximum line length */ + +/* + * priorities/facilities are encoded into a single 32-bit quantity, where the + * bottom 3 bits are the priority (0-7) and the top 28 bits are the facility + * (0-big number). Both the priorities and the facilities map roughly + * one-to-one to strings in the syslogd(8) source code. This mapping is + * included in this file. + * + * priorities (these are ordered) + */ +#define LOG_EMERG 0 /* system is unusable */ +#define LOG_ALERT 1 /* action must be taken immediately */ +#define LOG_CRIT 2 /* critical conditions */ +#define LOG_ERR 3 /* error conditions */ +#define LOG_WARNING 4 /* warning conditions */ +#define LOG_NOTICE 5 /* normal but significant condition */ +#define LOG_INFO 6 /* informational */ +#define LOG_DEBUG 7 /* debug-level messages */ + +#define LOG_PRIMASK 0x07 /* mask to extract priority part (internal) */ + /* extract priority */ +#define LOG_PRI(p) ((p) & LOG_PRIMASK) + +#ifdef SYSLOG_NAMES +#define INTERNAL_NOPRI 0x10 /* the "no priority" priority */ + /* mark "facility" */ +#define INTERNAL_MARK (LOG_NFACILITIES<<3) +typedef struct _code { + char *c_name; + int c_val; +} CODE; + +CODE prioritynames[] = { + { "alert", LOG_ALERT }, + { "crit", LOG_CRIT }, + { "debug", LOG_DEBUG }, + { "emerg", LOG_EMERG }, + { "err", LOG_ERR }, + { "error", LOG_ERR }, /* DEPRECATED */ + { "info", LOG_INFO }, + { "none", INTERNAL_NOPRI }, /* INTERNAL */ + { "notice", LOG_NOTICE }, + { "panic", LOG_EMERG }, /* DEPRECATED */ + { "warn", LOG_WARNING }, /* DEPRECATED */ + { "warning", LOG_WARNING }, + { NULL, -1 }, +}; +#endif + +/* facility codes */ +#define LOG_KERN (0<<3) /* kernel messages */ +#define LOG_USER (1<<3) /* random user-level messages */ +#define LOG_MAIL (2<<3) /* mail system */ +#define LOG_DAEMON (3<<3) /* system daemons */ +#define LOG_AUTH (4<<3) /* security/authorization messages */ +#define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */ +#define LOG_LPR (6<<3) /* line printer subsystem */ +#define LOG_NEWS (7<<3) /* network news subsystem */ +#define LOG_UUCP (8<<3) /* UUCP subsystem */ +#define LOG_CRON (9<<3) /* clock daemon */ +#define LOG_AUTHPRIV (10<<3) /* security/authorization messages (private) */ +#define LOG_FTP (11<<3) /* ftp daemon */ + + /* other codes through 15 reserved for system use */ +#define LOG_LOCAL0 (16<<3) /* reserved for local use */ +#define LOG_LOCAL1 (17<<3) /* reserved for local use */ +#define LOG_LOCAL2 (18<<3) /* reserved for local use */ +#define LOG_LOCAL3 (19<<3) /* reserved for local use */ +#define LOG_LOCAL4 (20<<3) /* reserved for local use */ +#define LOG_LOCAL5 (21<<3) /* reserved for local use */ +#define LOG_LOCAL6 (22<<3) /* reserved for local use */ +#define LOG_LOCAL7 (23<<3) /* reserved for local use */ + +#define LOG_NFACILITIES 24 /* current number of facilities */ +#define LOG_FACMASK 0x03f8 /* mask to extract facility part */ + /* facility of pri */ +#define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3) + +#ifdef SYSLOG_NAMES +CODE facilitynames[] = { + { "auth", LOG_AUTH }, + { "authpriv", LOG_AUTHPRIV }, + { "cron", LOG_CRON }, + { "daemon", LOG_DAEMON }, + { "ftp", LOG_FTP }, + { "kern", LOG_KERN }, + { "lpr", LOG_LPR }, + { "mail", LOG_MAIL }, + { "mark", INTERNAL_MARK }, /* INTERNAL */ + { "news", LOG_NEWS }, + { "security", LOG_AUTH }, /* DEPRECATED */ + { "syslog", LOG_SYSLOG }, + { "user", LOG_USER }, + { "uucp", LOG_UUCP }, + { "local0", LOG_LOCAL0 }, + { "local1", LOG_LOCAL1 }, + { "local2", LOG_LOCAL2 }, + { "local3", LOG_LOCAL3 }, + { "local4", LOG_LOCAL4 }, + { "local5", LOG_LOCAL5 }, + { "local6", LOG_LOCAL6 }, + { "local7", LOG_LOCAL7 }, + { NULL, -1 }, +}; +#endif + +/* Used by reentrant functions */ + +struct syslog_data { + int log_stat; + const char *log_tag; + int log_fac; + int log_mask; +}; + +#define SYSLOG_DATA_INIT {0, (const char *)0, LOG_USER, 0xff} + +#ifdef _KERNEL +#define LOG_PRINTF -1 /* pseudo-priority to indicate use of printf */ +#endif + +/* + * arguments to setlogmask. + */ +#define LOG_MASK(pri) (1 << (pri)) /* mask for one priority */ +#define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1) /* all priorities through pri */ + +/* + * Option flags for openlog. + * + * LOG_ODELAY no longer does anything. + * LOG_NDELAY is the inverse of what it used to be. + */ +#define LOG_PID 0x01 /* log the pid with each message */ +#define LOG_CONS 0x02 /* log on the console if errors in sending */ +#define LOG_ODELAY 0x04 /* delay open until first syslog() (default) */ +#define LOG_NDELAY 0x08 /* don't delay open */ +#define LOG_NOWAIT 0x10 /* don't wait for console forks: DEPRECATED */ +#define LOG_PERROR 0x20 /* log to stderr as well */ + +#ifndef _KERNEL + +/* + * Don't use va_list in the vsyslog() prototype. Va_list is typedef'd + * in . Including it here may collide with the utility's includes. + * It's unreasonable for utilities to have to include it to include , + * so we get __va_list from and use it. + */ +#include +#include + +__BEGIN_DECLS +void closelog(void); +void openlog(const char *, int, int); +int setlogmask(int); +void syslog(int, const char *, ...) + __attribute__((__format__(__syslog__,2,3))); +void vsyslog(int, const char *, __va_list); +void closelog_r(struct syslog_data *); +void openlog_r(const char *, int, int, struct syslog_data *); +int setlogmask_r(int, struct syslog_data *); +void syslog_r(int, struct syslog_data *, const char *, ...) + __attribute__((__format__(__syslog__,3,4))); +void vsyslog_r(int, struct syslog_data *, const char *, __va_list); +int sendsyslog(const char *, __size_t, int); +__END_DECLS + +#else /* !_KERNEL */ + +void logpri(int); +void log(int, const char *, ...) + __attribute__((__format__(__kprintf__,2,3))); +int addlog(const char *, ...) + __attribute__((__format__(__kprintf__,1,2))); +void logwakeup(void); + +#endif /* !_KERNEL */ +#endif /* !_SYS_SYSLOG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/tar.h b/lib/libc/include/generic-openbsd/tar.h new file mode 100644 index 000000000000..ec0a54b2f30d --- /dev/null +++ b/lib/libc/include/generic-openbsd/tar.h @@ -0,0 +1,66 @@ +/* $OpenBSD: tar.h,v 1.3 2008/06/26 05:42:04 ray Exp $ */ +/* $NetBSD: tar.h,v 1.1 1996/02/05 22:34:13 jtc Exp $ */ + +/*- + * Copyright (c) 1996 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by J.T. Conklin. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TAR_H_ +#define _TAR_H_ + +#define TMAGIC "ustar" +#define TMAGLEN 6 +#define TVERSION "00" +#define TVERSLEN 2 + +/* Typeflag field definitions */ +#define REGTYPE '0' +#define AREGTYPE '\0' +#define LNKTYPE '1' +#define SYMTYPE '2' +#define CHRTYPE '3' +#define BLKTYPE '4' +#define DIRTYPE '5' +#define FIFOTYPE '6' +#define CONTTYPE '7' + +/* Mode field bit definitions */ +#define TSUID 04000 +#define TSGID 02000 +#define TSVTX 01000 +#define TUREAD 00400 +#define TUWRITE 00200 +#define TUEXEC 00100 +#define TGREAD 00040 +#define TGWRITE 00020 +#define TGEXEC 00010 +#define TOREAD 00004 +#define TOWRITE 00002 +#define TOEXEC 00001 + +#endif /* _TAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/termios.h b/lib/libc/include/generic-openbsd/termios.h new file mode 100644 index 000000000000..3845c34501af --- /dev/null +++ b/lib/libc/include/generic-openbsd/termios.h @@ -0,0 +1,304 @@ +/* $OpenBSD: termios.h,v 1.14 2022/12/30 23:41:45 millert Exp $ */ +/* $NetBSD: termios.h,v 1.14 1996/04/09 20:55:41 cgd Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)termios.h 8.3 (Berkeley) 3/28/94 + */ + +#ifndef _SYS_TERMIOS_H_ +#define _SYS_TERMIOS_H_ + +#include + +/* + * Special Control Characters + * + * Index into c_cc[] character array. + * + * Name Subscript Enabled by + */ +#define VEOF 0 /* ICANON */ +#define VEOL 1 /* ICANON */ +#if __BSD_VISIBLE +#define VEOL2 2 /* ICANON */ +#endif +#define VERASE 3 /* ICANON */ +#if __BSD_VISIBLE +#define VWERASE 4 /* ICANON */ +#endif +#define VKILL 5 /* ICANON */ +#if __BSD_VISIBLE +#define VREPRINT 6 /* ICANON */ +#endif +/* 7 spare 1 */ +#define VINTR 8 /* ISIG */ +#define VQUIT 9 /* ISIG */ +#define VSUSP 10 /* ISIG */ +#if __BSD_VISIBLE +#define VDSUSP 11 /* ISIG */ +#endif +#define VSTART 12 /* IXON, IXOFF */ +#define VSTOP 13 /* IXON, IXOFF */ +#if __BSD_VISIBLE +#define VLNEXT 14 /* IEXTEN */ +#define VDISCARD 15 /* IEXTEN */ +#endif +#define VMIN 16 /* !ICANON */ +#define VTIME 17 /* !ICANON */ +#if __BSD_VISIBLE +#define VSTATUS 18 /* ICANON */ +/* 19 spare 2 */ +#endif +#define NCCS 20 + +#define _POSIX_VDISABLE (0377) + +#if __BSD_VISIBLE +#define CCEQ(val, c) (c == val ? val != _POSIX_VDISABLE : 0) +#endif + +/* + * Input flags - software input processing + */ +#define IGNBRK 0x00000001 /* ignore BREAK condition */ +#define BRKINT 0x00000002 /* map BREAK to SIGINT */ +#define IGNPAR 0x00000004 /* ignore (discard) parity errors */ +#define PARMRK 0x00000008 /* mark parity and framing errors */ +#define INPCK 0x00000010 /* enable checking of parity errors */ +#define ISTRIP 0x00000020 /* strip 8th bit off chars */ +#define INLCR 0x00000040 /* map NL into CR */ +#define IGNCR 0x00000080 /* ignore CR */ +#define ICRNL 0x00000100 /* map CR to NL (ala CRMOD) */ +#define IXON 0x00000200 /* enable output flow control */ +#define IXOFF 0x00000400 /* enable input flow control */ +#if __BSD_VISIBLE +#define IXANY 0x00000800 /* any char will restart after stop */ +#define IUCLC 0x00001000 /* translate upper to lower case */ +#define IMAXBEL 0x00002000 /* ring bell on input queue full */ +#endif /* __BSD_VISIBLE */ + +/* + * Output flags - software output processing + */ +#define OPOST 0x00000001 /* enable following output processing */ +#if __XPG_VISIBLE +#define ONLCR 0x00000002 /* map NL to CR-NL (ala CRMOD) */ +#endif +#if __BSD_VISIBLE || __XPG_VISIBLE +#define TABDLY 0x00000004 /* horizontal tab delay mask */ +#define TAB0 0x00000000 /* no tab delay or expansion */ +#define TAB3 0x00000004 /* expand tabs to spaces */ +#if __BSD_VISIBLE +#define OXTABS TAB3 /* BSD name for TAB3 */ +#define ONOEOT 0x00000008 /* discard EOT's (^D) on output */ +#endif +#endif +#if __XPG_VISIBLE +#define OCRNL 0x00000010 /* map CR to NL */ +#define OLCUC 0x00000020 /* translate lower case to upper case */ +#define ONOCR 0x00000040 /* No CR output at column 0 */ +#define ONLRET 0x00000080 /* NL performs the CR function */ +#endif /* __XPG_VISIBLE */ + +/* + * Control flags - hardware control of terminal + */ +#if __BSD_VISIBLE +#define CIGNORE 0x00000001 /* ignore control flags */ +#endif +#define CSIZE 0x00000300 /* character size mask */ +#define CS5 0x00000000 /* 5 bits (pseudo) */ +#define CS6 0x00000100 /* 6 bits */ +#define CS7 0x00000200 /* 7 bits */ +#define CS8 0x00000300 /* 8 bits */ +#define CSTOPB 0x00000400 /* send 2 stop bits */ +#define CREAD 0x00000800 /* enable receiver */ +#define PARENB 0x00001000 /* parity enable */ +#define PARODD 0x00002000 /* odd parity, else even */ +#define HUPCL 0x00004000 /* hang up on last close */ +#define CLOCAL 0x00008000 /* ignore modem status lines */ +#if __BSD_VISIBLE +#define CRTSCTS 0x00010000 /* RTS/CTS full-duplex flow control */ +#define CRTS_IFLOW CRTSCTS /* XXX compat */ +#define CCTS_OFLOW CRTSCTS /* XXX compat */ +#define MDMBUF 0x00100000 /* DTR/DCD hardware flow control */ +#define CHWFLOW (MDMBUF|CRTSCTS) /* all types of hw flow control */ +#endif /* __BSD_VISIBLE */ + +/* + * "Local" flags - dumping ground for other state + * + * Warning: some flags in this structure begin with + * the letter "I" and look like they belong in the + * input flag. + */ + +#if __BSD_VISIBLE +#define ECHOKE 0x00000001 /* visual erase for line kill */ +#endif +#define ECHOE 0x00000002 /* visually erase chars */ +#define ECHOK 0x00000004 /* echo NL after line kill */ +#define ECHO 0x00000008 /* enable echoing */ +#define ECHONL 0x00000010 /* echo NL even if ECHO is off */ +#if __BSD_VISIBLE +#define ECHOPRT 0x00000020 /* visual erase mode for hardcopy */ +#define ECHOCTL 0x00000040 /* echo control chars as ^(Char) */ +#endif +#define ISIG 0x00000080 /* enable signals INTR, QUIT, [D]SUSP */ +#define ICANON 0x00000100 /* canonicalize input lines */ +#if __BSD_VISIBLE +#define ALTWERASE 0x00000200 /* use alternate WERASE algorithm */ +#endif +#define IEXTEN 0x00000400 /* enable DISCARD and LNEXT */ +#define EXTPROC 0x00000800 /* external processing */ +#define TOSTOP 0x00400000 /* stop background jobs from output */ +#if __BSD_VISIBLE +#define FLUSHO 0x00800000 /* output being flushed (state) */ +#define XCASE 0x01000000 /* canonical upper/lower case */ +#define NOKERNINFO 0x02000000 /* no kernel output from VSTATUS */ +#define PENDIN 0x20000000 /* XXX retype pending input (state) */ +#endif +#define NOFLSH 0x80000000 /* don't flush after interrupt */ + +typedef unsigned int tcflag_t; +typedef unsigned char cc_t; +typedef unsigned int speed_t; + +struct termios { + tcflag_t c_iflag; /* input flags */ + tcflag_t c_oflag; /* output flags */ + tcflag_t c_cflag; /* control flags */ + tcflag_t c_lflag; /* local flags */ + cc_t c_cc[NCCS]; /* control chars */ + int c_ispeed; /* input speed */ + int c_ospeed; /* output speed */ +}; + +/* + * Commands passed to tcsetattr() for setting the termios structure. + */ +#define TCSANOW 0 /* make change immediate */ +#define TCSADRAIN 1 /* drain output, then change */ +#define TCSAFLUSH 2 /* drain output, flush input */ +#if __BSD_VISIBLE +#define TCSASOFT 0x10 /* flag - don't alter h.w. state */ +#endif + +/* + * Standard speeds + */ +#define B0 0 +#define B50 50 +#define B75 75 +#define B110 110 +#define B134 134 +#define B150 150 +#define B200 200 +#define B300 300 +#define B600 600 +#define B1200 1200 +#define B1800 1800 +#define B2400 2400 +#define B4800 4800 +#define B9600 9600 +#define B19200 19200 +#define B38400 38400 +#if __BSD_VISIBLE +#define B7200 7200 +#define B14400 14400 +#define B28800 28800 +#define B57600 57600 +#define B76800 76800 +#define B115200 115200 +#define B230400 230400 +#define EXTA 19200 +#define EXTB 38400 +#endif /* __BSD_VISIBLE */ + +#ifndef _KERNEL + +#define TCIFLUSH 1 +#define TCOFLUSH 2 +#define TCIOFLUSH 3 +#define TCOOFF 1 +#define TCOON 2 +#define TCIOFF 3 +#define TCION 4 + +#include + +#if __XPG_VISIBLE >= 420 || __POSIX_VISIBLE >= 200809 +#ifndef _PID_T_DEFINED_ +#define _PID_T_DEFINED_ +typedef __pid_t pid_t; +#endif +#endif + +__BEGIN_DECLS +speed_t cfgetispeed(const struct termios *); +speed_t cfgetospeed(const struct termios *); +int cfsetispeed(struct termios *, speed_t); +int cfsetospeed(struct termios *, speed_t); +int tcgetattr(int, struct termios *); +int tcsetattr(int, int, const struct termios *); +int tcdrain(int); +int tcflow(int, int); +int tcflush(int, int); +int tcsendbreak(int, int); + +#if __XPG_VISIBLE >= 420 || __POSIX_VISIBLE >= 200809 +pid_t tcgetsid(int); +#endif + +#if __BSD_VISIBLE +void cfmakeraw(struct termios *); +int cfsetspeed(struct termios *, speed_t); +#endif /* __BSD_VISIBLE */ +__END_DECLS + +#endif /* !_KERNEL */ + +#if __BSD_VISIBLE +/* + * Include tty ioctl's that aren't just for backwards compatibility + * with the old tty driver. These ioctl definitions were previously + * in . + */ +#include +#endif + +/* + * END OF PROTECTED INCLUDE. + */ +#endif /* !_SYS_TERMIOS_H_ */ + +#if __BSD_VISIBLE +#include +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/tgmath.h b/lib/libc/include/generic-openbsd/tgmath.h new file mode 100644 index 000000000000..70460a8ebc50 --- /dev/null +++ b/lib/libc/include/generic-openbsd/tgmath.h @@ -0,0 +1,169 @@ +/* $OpenBSD: tgmath.h,v 1.1 2011/07/08 19:28:06 martynas Exp $ */ + +/*- + * Copyright (c) 2004 Stefan Farfeleder. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/include/tgmath.h,v 1.5 2007/02/02 18:30:23 schweikh Exp $ + */ + +#ifndef _TGMATH_H_ +#define _TGMATH_H_ + +#include +#include + +/* + * This implementation of requires two implementation-dependent + * macros to be defined: + * __tg_impl_simple(x, y, z, fn, fnf, fnl, ...) + * Invokes fnl() if the corresponding real type of x, y or z is long + * double, fn() if it is double or any has an integer type, and fnf() + * otherwise. + * __tg_impl_full(x, y, z, fn, fnf, fnl, cfn, cfnf, cfnl, ...) + * Invokes [c]fnl() if the corresponding real type of x, y or z is long + * double, [c]fn() if it is double or any has an integer type, and + * [c]fnf() otherwise. The function with the 'c' prefix is called if + * any of x, y or z is a complex number. + * Both macros call the chosen function with all additional arguments passed + * to them, as given by __VA_ARGS__. + * + * Note that these macros cannot be implemented with C's ?: operator, + * because the return type of the whole expression would incorrectly be long + * double complex regardless of the argument types. + */ + +#if __GNUC_PREREQ__(3, 1) +#define __tg_type(e, t) __builtin_types_compatible_p(__typeof__(e), t) +#define __tg_type3(e1, e2, e3, t) \ + (__tg_type(e1, t) || __tg_type(e2, t) || __tg_type(e3, t)) +#define __tg_type_corr(e1, e2, e3, t) \ + (__tg_type3(e1, e2, e3, t) || __tg_type3(e1, e2, e3, t _Complex)) +#define __tg_integer(e1, e2, e3) \ + (((__typeof__(e1))1.5 == 1) || ((__typeof__(e2))1.5 == 1) || \ + ((__typeof__(e3))1.5 == 1)) +#define __tg_is_complex(e1, e2, e3) \ + (__tg_type3(e1, e2, e3, float _Complex) || \ + __tg_type3(e1, e2, e3, double _Complex) || \ + __tg_type3(e1, e2, e3, long double _Complex) || \ + __tg_type3(e1, e2, e3, __typeof__(_Complex_I))) + +#define __tg_impl_simple(x, y, z, fn, fnf, fnl, ...) \ + __builtin_choose_expr(__tg_type_corr(x, y, z, long double), \ + fnl(__VA_ARGS__), __builtin_choose_expr( \ + __tg_type_corr(x, y, z, double) || __tg_integer(x, y, z),\ + fn(__VA_ARGS__), fnf(__VA_ARGS__))) + +#define __tg_impl_full(x, y, z, fn, fnf, fnl, cfn, cfnf, cfnl, ...) \ + __builtin_choose_expr(__tg_is_complex(x, y, z), \ + __tg_impl_simple(x, y, z, cfn, cfnf, cfnl, __VA_ARGS__), \ + __tg_impl_simple(x, y, z, fn, fnf, fnl, __VA_ARGS__)) + +#else /* __GNUC__ */ +#error " not implemented for this compiler" +#endif /* !__GNUC__ */ + +/* Macros to save lots of repetition below */ +#define __tg_simple(x, fn) \ + __tg_impl_simple(x, x, x, fn, fn##f, fn##l, x) +#define __tg_simple2(x, y, fn) \ + __tg_impl_simple(x, x, y, fn, fn##f, fn##l, x, y) +#define __tg_simplev(x, fn, ...) \ + __tg_impl_simple(x, x, x, fn, fn##f, fn##l, __VA_ARGS__) +#define __tg_full(x, fn) \ + __tg_impl_full(x, x, x, fn, fn##f, fn##l, c##fn, c##fn##f, c##fn##l, x) + +/* 7.22#4 -- These macros expand to real or complex functions, depending on + * the type of their arguments. */ +#define acos(x) __tg_full(x, acos) +#define asin(x) __tg_full(x, asin) +#define atan(x) __tg_full(x, atan) +#define acosh(x) __tg_full(x, acosh) +#define asinh(x) __tg_full(x, asinh) +#define atanh(x) __tg_full(x, atanh) +#define cos(x) __tg_full(x, cos) +#define sin(x) __tg_full(x, sin) +#define tan(x) __tg_full(x, tan) +#define cosh(x) __tg_full(x, cosh) +#define sinh(x) __tg_full(x, sinh) +#define tanh(x) __tg_full(x, tanh) +#define exp(x) __tg_full(x, exp) +#define log(x) __tg_full(x, log) +#define pow(x, y) __tg_impl_full(x, x, y, pow, powf, powl, \ + cpow, cpowf, cpowl, x, y) +#define sqrt(x) __tg_full(x, sqrt) + +/* "The corresponding type-generic macro for fabs and cabs is fabs." */ +#define fabs(x) __tg_impl_full(x, x, x, fabs, fabsf, fabsl, \ + cabs, cabsf, cabsl, x) + +/* 7.22#5 -- These macros are only defined for arguments with real type. */ +#define atan2(x, y) __tg_simple2(x, y, atan2) +#define cbrt(x) __tg_simple(x, cbrt) +#define ceil(x) __tg_simple(x, ceil) +#define copysign(x, y) __tg_simple2(x, y, copysign) +#define erf(x) __tg_simple(x, erf) +#define erfc(x) __tg_simple(x, erfc) +#define exp2(x) __tg_simple(x, exp2) +#define expm1(x) __tg_simple(x, expm1) +#define fdim(x, y) __tg_simple2(x, y, fdim) +#define floor(x) __tg_simple(x, floor) +#define fma(x, y, z) __tg_impl_simple(x, y, z, fma, fmaf, fmal, x, y, z) +#define fmax(x, y) __tg_simple2(x, y, fmax) +#define fmin(x, y) __tg_simple2(x, y, fmin) +#define fmod(x, y) __tg_simple2(x, y, fmod) +#define frexp(x, y) __tg_simplev(x, frexp, x, y) +#define hypot(x, y) __tg_simple2(x, y, hypot) +#define ilogb(x) __tg_simple(x, ilogb) +#define ldexp(x, y) __tg_simplev(x, ldexp, x, y) +#define lgamma(x) __tg_simple(x, lgamma) +#define llrint(x) __tg_simple(x, llrint) +#define llround(x) __tg_simple(x, llround) +#define log10(x) __tg_simple(x, log10) +#define log1p(x) __tg_simple(x, log1p) +#define log2(x) __tg_simple(x, log2) +#define logb(x) __tg_simple(x, logb) +#define lrint(x) __tg_simple(x, lrint) +#define lround(x) __tg_simple(x, lround) +#define nearbyint(x) __tg_simple(x, nearbyint) +#define nextafter(x, y) __tg_simple2(x, y, nextafter) +#define nexttoward(x, y) __tg_simplev(x, nexttoward, x, y) +#define remainder(x, y) __tg_simple2(x, y, remainder) +#define remquo(x, y, z) __tg_impl_simple(x, x, y, remquo, remquof, \ + remquol, x, y, z) +#define rint(x) __tg_simple(x, rint) +#define round(x) __tg_simple(x, round) +#define scalbn(x, y) __tg_simplev(x, scalbn, x, y) +#define scalbln(x, y) __tg_simplev(x, scalbln, x, y) +#define tgamma(x) __tg_simple(x, tgamma) +#define trunc(x) __tg_simple(x, trunc) + +/* 7.22#6 -- These macros always expand to complex functions. */ +#define carg(x) __tg_simple(x, carg) +#define cimag(x) __tg_simple(x, cimag) +#define conj(x) __tg_simple(x, conj) +#define cproj(x) __tg_simple(x, cproj) +#define creal(x) __tg_simple(x, creal) + +#endif /* !_TGMATH_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/tib.h b/lib/libc/include/generic-openbsd/tib.h new file mode 100644 index 000000000000..063c9a94a6f8 --- /dev/null +++ b/lib/libc/include/generic-openbsd/tib.h @@ -0,0 +1,264 @@ +/* $OpenBSD: tib.h,v 1.10 2023/12/08 19:14:36 miod Exp $ */ +/* + * Copyright (c) 2011,2014 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Thread Information Block (TIB) and Thread Local Storage (TLS) handling + * (the TCB, Thread Control Block, is part of the TIB) + */ + +#ifndef _TIB_H_ +#define _TIB_H_ + +#include +#include + +#include + + +/* + * This header defines struct tib and at least eight macros: + * TLS_VARIANT + * Either 1 or 2 (Actually defined by ) + * + * TCB_SET(tcb) + * Set the TCB pointer for this thread to 'tcb' + * + * TCB_GET() + * Return the TCB pointer for this thread + * + * TCB_TO_TIB(tcb) + * Given a TCB pointer, return the matching TIB pointer + * + * TIB_TO_TCB(tib) + * Given a TIB pointer, return the matching TCB pointer + * + * TIB_INIT(tib, dtv, thread) + * Initializes a TIB for a new thread, using the supplied + * values for its dtv and thread pointers + * + * TIB_GET() + * Short-hand for TCB_TO_TIB(TCB_GET()) + * + * TIB_EXTRA_ALIGN + * On TLS variant 2 archs, what alignment is sufficient + * for the extra space that will be used for struct pthread? + * + * The following functions are provided by either ld.so (dynamic) or + * libc (static) for allocating and freeing a common memory block that + * will hold both the TIB and the pthread structure: + * _dl_allocate_tib(sizeof(struct pthread)) + * Allocates a combined TIB and pthread memory region. + * The argument is the amount of space to reserve + * for the pthread structure. Returns a pointer to + * the TIB inside the allocated block. + * + * _dl_free_tib(tib, sizeof(struct pthread)) + * Frees a TIB and pthread block previously allocated + * with _dl_allocate_tib(). Must be passed the return + * value of that previous call. + */ + +/* + * Regarding : + * - it must define the TLS_VARIANT macro + * - it may define TCB_OFFSET if the TCB address in the kernel and/or + * register is offset from the actual TCB address. TCB_OFFSET > 0 + * means the kernel/register points to *after* the real data. + * - if there's a faster way to get or set the TCB pointer for the thread + * than the __{get,set}_tcb() syscalls, it should define either or both + * the TCB_{GET,SET} macros to do so. + */ + + +/* All archs but mips64 have fast TCB_GET() and don't need caching */ +#ifndef __mips64__ +# define TCB_HAVE_MD_GET 1 +#endif +#ifdef TCB_SET +# define TCB_HAVE_MD_SET 1 +#else +# define TCB_SET(tcb) __set_tcb(tcb) +#endif +#ifndef TCB_OFFSET +# define TCB_OFFSET 0 +#endif + +/* + * tib_cantcancel values is non-zero if the thread should skip all + * cancellation processing + */ +#define CANCEL_DISABLED 1 +#define CANCEL_DYING 2 + +/* + * tib_cancel_point is non-zero if we're in a cancel point; its modified + * by the cancel point code and read by the cancellation signal handler + */ +#define CANCEL_POINT 1 +#define CANCEL_POINT_DELAYED 2 + + +#if TLS_VARIANT == 1 +/* + * ABI specifies that the static TLS data starts two words after the + * (notional) thread pointer, with the first of those two words being + * the TLS dtv pointer. The other (second) word is reserved for the + * implementation, so we place the pointer to the thread structure there, + * but we place our actual thread bits before the TCB, at negative offsets + * from the TCB pointer. Ergo, memory is laid out, low to high, as: + * + * [pthread structure] + * TIB { + * ...cancelation and other int-sized info... + * int errno + * void *locale + * TCB (- TCB_OFFSET) { + * void *dtv + * struct pthread *thread + * } + * } + * static TLS data + */ + +struct tib { + void *tib_atexit; + int tib_thread_flags; /* internal to libpthread */ + pid_t tib_tid; + int tib_cantcancel; + int tib_cancel_point; + int tib_canceled; + int tib_errno; + void *tib_locale; +#ifdef __powerpc64__ + void *tib_thread; + void *tib_dtv; /* internal to the runtime linker */ +#else + void *tib_dtv; /* internal to the runtime linker */ + void *tib_thread; +#endif +}; + + +#elif TLS_VARIANT == 2 +/* + * ABI specifies that the static TLS data occupies the memory before + * the TCB pointer, at negative offsets, and that on i386 and amd64 + * the word the TCB points to contains a pointer to itself. So, + * we place errno and our thread bits after that. Memory is laid + * out, low to high, as: + * static TLS data + * TIB { + * TCB (- TCB_OFFSET) { + * self pointer [i386/amd64 only] + * void *dtv + * } + * struct pthread *thread + * void *locale + * int errno + * ...cancelation and other int-sized info... + * } + * [pthread structure] + */ + +struct tib { +#if defined(__i386) || defined(__amd64) + struct tib *__tib_self; +# define __tib_tcb __tib_self +#endif + void *tib_dtv; /* internal to the runtime linker */ + void *tib_thread; + void *tib_locale; + int tib_errno; + int tib_canceled; + int tib_cancel_point; + int tib_cantcancel; + pid_t tib_tid; + int tib_thread_flags; /* internal to libpthread */ + void *tib_atexit; +}; + +#if defined(__i386) || defined(__amd64) +# define _TIB_PREP(tib) \ + ((void)((tib)->__tib_self = (tib))) +#endif + +#define TIB_EXTRA_ALIGN sizeof(void *) + +#else +# error "unknown TLS variant" +#endif + +/* nothing to do by default */ +#ifndef _TIB_PREP +# define _TIB_PREP(tib) ((void)0) +#endif + +#define TIB_INIT(tib, dtv, thread) do { \ + (tib)->tib_thread = (thread); \ + (tib)->tib_atexit = NULL; \ + (tib)->tib_locale = NULL; \ + (tib)->tib_cantcancel = 0; \ + (tib)->tib_cancel_point = 0; \ + (tib)->tib_canceled = 0; \ + (tib)->tib_dtv = (dtv); \ + (tib)->tib_errno = 0; \ + (tib)->tib_thread_flags = 0; \ + _TIB_PREP(tib); \ + } while (0) + +#ifndef __tib_tcb +# define __tib_tcb tib_dtv +#endif +#define _TIBO_TCB (offsetof(struct tib, __tib_tcb) + TCB_OFFSET) + +#define TCB_TO_TIB(tcb) ((struct tib *)((char *)(tcb) - _TIBO_TCB)) +#define TIB_TO_TCB(tib) ((char *)(tib) + _TIBO_TCB) +#define TIB_GET() TCB_TO_TIB(TCB_GET()) + + +__BEGIN_DECLS +struct dl_info; +struct dl_phdr_info; +struct dl_cb_0 { + void *(*dl_allocate_tib)(size_t); + void (*dl_free_tib)(void *, size_t); + void (*dl_clean_boot)(void); + void *(*dlopen)(const char *, int); + int (*dlclose)(void *); + void *(*dlsym)(void *, const char *); + int (*dladdr)(const void *, struct dl_info *); + int (*dlctl)(void *, int, void *); + char *(*dlerror)(void); + int (*dl_iterate_phdr)(int (*)(struct dl_phdr_info *, + size_t, void *), void *); +}; + +#define DL_CB_CUR 0 +typedef struct dl_cb_0 dl_cb; + +/* type of function passed to init functions that returns a dl_cb */ +typedef const void *dl_cb_cb(int _version); + +void *_dl_allocate_tib(size_t _extra) __dso_public; +void _dl_free_tib(void *_tib, size_t _extra) __dso_public; + +/* The actual syscalls */ +void *__get_tcb(void); +void __set_tcb(void *_tcb); +__END_DECLS + +#endif /* _TIB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/time.h b/lib/libc/include/generic-openbsd/time.h new file mode 100644 index 000000000000..2762f0f1dcba --- /dev/null +++ b/lib/libc/include/generic-openbsd/time.h @@ -0,0 +1,178 @@ +/* $OpenBSD: time.h,v 1.32 2022/10/25 16:30:30 millert Exp $ */ +/* $NetBSD: time.h,v 1.9 1994/10/26 00:56:35 cgd Exp $ */ + +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)time.h 5.12 (Berkeley) 3/9/91 + */ + +#ifndef _TIME_H_ +#define _TIME_H_ + +#include +#include +#include +#include + +#ifndef _CLOCK_T_DEFINED_ +#define _CLOCK_T_DEFINED_ +typedef __clock_t clock_t; +#endif + +#ifndef _TIME_T_DEFINED_ +#define _TIME_T_DEFINED_ +typedef __time_t time_t; +#endif + +#ifndef _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED_ +typedef __size_t size_t; +#endif + +#if __POSIX_VISIBLE > 0 && __POSIX_VISIBLE < 200112 || __BSD_VISIBLE +/* + * Frequency of the clock ticks reported by times(). Deprecated - use + * sysconf(_SC_CLK_TCK) instead. (Removed in 1003.1-2001.) + */ +#define CLK_TCK 100 +#endif + +#if __POSIX_VISIBLE >= 199309 +#ifndef _CLOCKID_T_DEFINED_ +#define _CLOCKID_T_DEFINED_ +typedef __clockid_t clockid_t; +#endif + +#ifndef _TIMER_T_DEFINED_ +#define _TIMER_T_DEFINED_ +typedef __timer_t timer_t; +#endif +#endif + +#if __POSIX_VISIBLE >= 200112 +#ifndef _PID_T_DEFINED_ +#define _PID_T_DEFINED_ +typedef __pid_t pid_t; +#endif +#endif + +#if __POSIX_VISIBLE >= 200809 +#ifndef _LOCALE_T_DEFINED_ +#define _LOCALE_T_DEFINED_ +typedef void *locale_t; +#endif +#endif + +struct tm { + int tm_sec; /* seconds after the minute [0-60] */ + int tm_min; /* minutes after the hour [0-59] */ + int tm_hour; /* hours since midnight [0-23] */ + int tm_mday; /* day of the month [1-31] */ + int tm_mon; /* months since January [0-11] */ + int tm_year; /* years since 1900 */ + int tm_wday; /* days since Sunday [0-6] */ + int tm_yday; /* days since January 1 [0-365] */ + int tm_isdst; /* Daylight Saving Time flag */ + long tm_gmtoff; /* offset from UTC in seconds */ + char *tm_zone; /* timezone abbreviation */ +}; + +__BEGIN_DECLS +char *asctime(const struct tm *); +clock_t clock(void); +char *ctime(const time_t *); +double difftime(time_t, time_t); +struct tm *gmtime(const time_t *); +struct tm *localtime(const time_t *); +time_t mktime(struct tm *); +size_t strftime(char *__restrict, size_t, const char *__restrict, + const struct tm *__restrict) + __attribute__ ((__bounded__(__string__,1,2))); +time_t time(time_t *); + +#if __XPG_VISIBLE >= 300 +extern int daylight; +extern long timezone; +#endif +#if __XPG_VISIBLE >= 400 +char *strptime(const char *__restrict, const char *__restrict, + struct tm *__restrict); +#endif + +#if __POSIX_VISIBLE >= 199506 +char *asctime_r(const struct tm *__restrict, char *__restrict) + __attribute__ ((__bounded__(__minbytes__,2,26))); +char *ctime_r(const time_t *, char *) + __attribute__ ((__bounded__(__minbytes__,2,26))); +struct tm *gmtime_r(const time_t *__restrict, struct tm *__restrict); +struct tm *localtime_r(const time_t *__restrict, struct tm *__restrict); +#endif + +#if __POSIX_VISIBLE +extern char *tzname[2]; +void tzset(void); +#endif + +#if __POSIX_VISIBLE >= 199309 +int clock_getres(clockid_t, struct timespec *); +int clock_gettime(clockid_t, struct timespec *); +int clock_settime(clockid_t, const struct timespec *); +int nanosleep(const struct timespec *, struct timespec *); +#endif + +#if __POSIX_VISIBLE >= 200112 +int clock_getcpuclockid(pid_t, clockid_t *); +#endif + +#if __POSIX_VISIBLE >= 200809 +size_t strftime_l(char *__restrict, size_t, const char *__restrict, + const struct tm *__restrict, locale_t) + __attribute__ ((__bounded__(__string__,1,2))); +#endif + +#if __ISO_C_VISIBLE >= 2011 +#define TIME_UTC 1 /* time elapsed since epoch */ +int timespec_get(struct timespec *_ts, int _base); +#endif + +#if __BSD_VISIBLE +void tzsetwall(void); +time_t timelocal(struct tm *); +time_t timegm(struct tm *); +time_t timeoff(struct tm *, const long); +#endif +__END_DECLS + +#endif /* !_TIME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ttyent.h b/lib/libc/include/generic-openbsd/ttyent.h new file mode 100644 index 000000000000..39c97dd775dd --- /dev/null +++ b/lib/libc/include/generic-openbsd/ttyent.h @@ -0,0 +1,73 @@ +/* $OpenBSD: ttyent.h,v 1.4 2003/06/02 19:34:12 millert Exp $ */ +/* $NetBSD: ttyent.h,v 1.5 1994/10/26 00:56:36 cgd Exp $ */ + +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ttyent.h 5.7 (Berkeley) 4/3/91 + */ + +#ifndef _TTYENT_H_ +#define _TTYENT_H_ + +#define _PATH_TTYS "/etc/ttys" + +#define _TTYS_OFF "off" +#define _TTYS_ON "on" +#define _TTYS_SECURE "secure" +#define _TTYS_WINDOW "window" +#define _TTYS_LOCAL "local" +#define _TTYS_RTSCTS "rtscts" +#define _TTYS_SOFTCAR "softcar" +#define _TTYS_MDMBUF "mdmbuf" + +struct ttyent { + char *ty_name; /* terminal device name */ + char *ty_getty; /* command to execute, usually getty */ + char *ty_type; /* terminal type for termcap */ +#define TTY_ON 0x01 /* enable logins (start ty_getty program) */ +#define TTY_SECURE 0x02 /* allow uid of 0 to login */ +#define TTY_LOCAL 0x04 /* set 'CLOCAL' on open (dev. specific) */ +#define TTY_RTSCTS 0x08 /* set 'CRTSCTS' on open (dev. specific) */ +#define TTY_SOFTCAR 0x10 /* ignore hardware carrier (dev. spec.) */ +#define TTY_MDMBUF 0x20 /* set 'MDMBUF' on open (dev. specific) */ + int ty_status; /* status flags */ + char *ty_window; /* command to start up window manager */ + char *ty_comment; /* comment field */ +}; + +#include + +__BEGIN_DECLS +struct ttyent *getttyent(void); +struct ttyent *getttynam(const char *); +int setttyent(void); +int endttyent(void); +__END_DECLS + +#endif /* !_TTYENT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uchar.h b/lib/libc/include/generic-openbsd/uchar.h new file mode 100644 index 000000000000..543a4251fd1b --- /dev/null +++ b/lib/libc/include/generic-openbsd/uchar.h @@ -0,0 +1,40 @@ +/* $OpenBSD: uchar.h,v 1.2 2023/09/05 23:16:01 schwarze Exp $ */ +/* + * Written by Ingo Schwarze + * and placed in the public domain on March 19, 2022. + */ + +#ifndef _UCHAR_H_ +#define _UCHAR_H_ + +#include +#include + +#ifndef _MBSTATE_T_DEFINED_ +#define _MBSTATE_T_DEFINED_ +typedef __mbstate_t mbstate_t; +#endif + +#ifndef _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED_ +typedef __size_t size_t; +#endif + +#define __STDC_UTF_16__ 1 +#define __STDC_UTF_32__ 1 + +#if !defined(__cplusplus) || __cplusplus < 201103L +typedef __uint16_t char16_t; +typedef __uint32_t char32_t; +#endif + +__BEGIN_DECLS +size_t mbrtoc16(char16_t * __restrict, const char * __restrict, size_t, + mbstate_t * __restrict); +size_t c16rtomb(char * __restrict, char16_t, mbstate_t * __restrict); +size_t mbrtoc32(char32_t * __restrict, const char * __restrict, size_t, + mbstate_t * __restrict); +size_t c32rtomb(char * __restrict, char32_t, mbstate_t * __restrict); +__END_DECLS + +#endif /* !_UCHAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ufs/ext2fs/ext2fs.h b/lib/libc/include/generic-openbsd/ufs/ext2fs/ext2fs.h new file mode 100644 index 000000000000..2290e2e3106a --- /dev/null +++ b/lib/libc/include/generic-openbsd/ufs/ext2fs/ext2fs.h @@ -0,0 +1,449 @@ +/* $OpenBSD: ext2fs.h,v 1.27 2024/07/15 13:27:36 martijn Exp $ */ +/* $NetBSD: ext2fs.h,v 1.10 2000/01/28 16:00:23 bouyer Exp $ */ + +/* + * Copyright (c) 1997 Manuel Bouyer. + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)fs.h 8.10 (Berkeley) 10/27/94 + * Modified for ext2fs by Manuel Bouyer. + */ + +#include + +/* + * Each disk drive contains some number of file systems. + * A file system consists of a number of cylinder groups. + * Each cylinder group has inodes and data. + * + * A file system is described by its super-block, which in turn + * describes the cylinder groups. The super-block is critical + * data and is replicated in each cylinder group to protect against + * catastrophic loss. This is done at `newfs' time and the critical + * super-block data does not change, so the copies need not be + * referenced further unless disaster strikes. + * + * The first boot and super blocks are given in absolute disk addresses. + * The byte-offset forms are preferred, as they don't imply a sector size. + */ +#define BBSIZE 1024 +#define SBSIZE 1024 +#define BBOFF ((off_t)(0)) +#define SBOFF ((off_t)(BBOFF + BBSIZE)) +#define BBLOCK ((daddr_t)(0)) +#define SBLOCK ((daddr_t)(BBLOCK + BBSIZE / DEV_BSIZE)) + +/* + * Inodes are, like in UFS, 32-bit unsigned integers and therefore ufsino_t. + * Disk blocks are 32-bit, if the filesystem isn't operating in 64-bit mode + * (the incompatible ext4 64BIT flag). More work is needed to properly use + * daddr_t as the disk block data type on both BE and LE architectures. + * XXX disk blocks are simply u_int32_t for now. + */ + +/* + * MINBSIZE is the smallest allowable block size. + * MINBSIZE must be big enough to hold a cylinder group block, + * thus changes to (struct cg) must keep its size within MINBSIZE. + * Note that super blocks are always of size SBSIZE, + * and that both SBSIZE and MAXBSIZE must be >= MINBSIZE. + * FSIZE means fragment size. + */ +#define LOG_MINBSIZE 10 +#define MINBSIZE (1 << LOG_MINBSIZE) +#define LOG_MINFSIZE 10 +#define MINFSIZE (1 << LOG_MINFSIZE) + +/* + * The path name on which the file system is mounted is maintained + * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in + * the super block for this name. + */ +#define MAXMNTLEN 512 + +/* + * MINFREE gives the minimum acceptable percentage of file system + * blocks which may be free. If the freelist drops below this level + * only the superuser may continue to allocate blocks. This may + * be set to 0 if no reserve of free blocks is deemed necessary, + * however throughput drops by fifty percent if the file system + * is run at between 95% and 100% full; thus the minimum default + * value of fs_minfree is 5%. However, to get good clustering + * performance, 10% is a better choice. hence we use 10% as our + * default value. With 10% free space, fragmentation is not a + * problem, so we choose to optimize for time. + */ +#define MINFREE 5 + +/* + * Super block for an ext2fs file system. + */ +struct ext2fs { + u_int32_t e2fs_icount; /* Inode count */ + u_int32_t e2fs_bcount; /* blocks count */ + u_int32_t e2fs_rbcount; /* reserved blocks count */ + u_int32_t e2fs_fbcount; /* free blocks count */ + u_int32_t e2fs_ficount; /* free inodes count */ + u_int32_t e2fs_first_dblock; /* first data block */ + u_int32_t e2fs_log_bsize; /* block size = 1024*(2^e2fs_log_bsize) */ + u_int32_t e2fs_log_fsize; /* fragment size log2 */ + u_int32_t e2fs_bpg; /* blocks per group */ + u_int32_t e2fs_fpg; /* frags per group */ + u_int32_t e2fs_ipg; /* inodes per group */ + u_int32_t e2fs_mtime; /* mount time */ + u_int32_t e2fs_wtime; /* write time */ + u_int16_t e2fs_mnt_count; /* mount count */ + u_int16_t e2fs_max_mnt_count; /* max mount count */ + u_int16_t e2fs_magic; /* magic number */ + u_int16_t e2fs_state; /* file system state */ + u_int16_t e2fs_beh; /* behavior on errors */ + u_int16_t e2fs_minrev; /* minor revision level */ + u_int32_t e2fs_lastfsck; /* time of last fsck */ + u_int32_t e2fs_fsckintv; /* max time between fscks */ + u_int32_t e2fs_creator; /* creator OS */ + u_int32_t e2fs_rev; /* revision level */ + u_int16_t e2fs_ruid; /* default uid for reserved blocks */ + u_int16_t e2fs_rgid; /* default gid for reserved blocks */ + /* EXT2_DYNAMIC_REV superblocks */ + u_int32_t e2fs_first_ino; /* first non-reserved inode */ + u_int16_t e2fs_inode_size; /* size of inode structure */ + u_int16_t e2fs_block_group_nr; /* block grp number of this sblk*/ + u_int32_t e2fs_features_compat; /* compatible feature set */ + u_int32_t e2fs_features_incompat; /* incompatible feature set */ + u_int32_t e2fs_features_rocompat; /* RO-compatible feature set */ + u_int8_t e2fs_uuid[16]; /* 128-bit uuid for volume */ + char e2fs_vname[16]; /* volume name */ + char e2fs_fsmnt[64]; /* name mounted on */ + u_int32_t e2fs_algo; /* For compression */ + u_int8_t e2fs_prealloc; /* # of blocks to preallocate */ + u_int8_t e2fs_dir_prealloc; /* # of blocks to preallocate for dir */ + u_int16_t e2fs_reserved_ngdb; /* # of reserved gd blocks for resize */ + /* Ext3 JBD2 journaling. */ + u_int8_t e2fs_journal_uuid[16]; + u_int32_t e2fs_journal_ino; + u_int32_t e2fs_journal_dev; + u_int32_t e2fs_last_orphan; /* start of list of inodes to delete */ + u_int32_t e2fs_hash_seed[4]; /* htree hash seed */ + u_int8_t e2fs_def_hash_version; + u_int8_t e2fs_journal_backup_type; + u_int16_t e2fs_gdesc_size; + u_int32_t e2fs_default_mount_opts; + u_int32_t e2fs_first_meta_bg; + u_int32_t e2fs_mkfs_time; + u_int32_t e2fs_journal_backup[17]; + u_int32_t e2fs_bcount_hi; /* high bits of blocks count */ + u_int32_t e2fs_rbcount_hi; /* high bits of reserved blocks count */ + u_int32_t e2fs_fbcount_hi; /* high bits of free blocks count */ + u_int16_t e2fs_min_extra_isize; /* all inodes have some bytes */ + u_int16_t e2fs_want_extra_isize;/* inodes must reserve some bytes */ + u_int32_t e2fs_flags; /* miscellaneous flags */ + u_int16_t e2fs_raid_stride; /* RAID stride */ + u_int16_t e2fs_mmpintv; /* seconds to wait in MMP checking */ + u_int64_t e2fs_mmpblk; /* block for multi-mount protection */ + u_int32_t e2fs_raid_stripe_wid; /* blocks on data disks (N * stride) */ + u_int8_t e2fs_log_gpf; /* FLEX_BG group size */ + u_int8_t e2fs_chksum_type; /* metadata checksum algorithm used */ + u_int8_t e2fs_encrypt; /* versioning level for encryption */ + u_int8_t e2fs_reserved_pad; + u_int64_t e2fs_kbytes_written; /* number of lifetime kilobytes */ + u_int32_t e2fs_snapinum; /* inode number of active snapshot */ + u_int32_t e2fs_snapid; /* sequential ID of active snapshot */ + u_int64_t e2fs_snaprbcount; /* rsvd blocks for active snapshot */ + u_int32_t e2fs_snaplist; /* inode number for on-disk snapshot */ + u_int32_t e2fs_errcount; /* number of file system errors */ + u_int32_t e2fs_first_errtime; /* first time an error happened */ + u_int32_t e2fs_first_errino; /* inode involved in first error */ + u_int64_t e2fs_first_errblk; /* block involved of first error */ + u_int8_t e2fs_first_errfunc[32];/* function where error happened */ + u_int32_t e2fs_first_errline; /* line number where error happened */ + u_int32_t e2fs_last_errtime; /* most recent time of an error */ + u_int32_t e2fs_last_errino; /* inode involved in last error */ + u_int32_t e2fs_last_errline; /* line number where error happened */ + u_int64_t e2fs_last_errblk; /* block involved of last error */ + u_int8_t e2fs_last_errfunc[32];/* function where error happened */ + u_int8_t e2fs_mount_opts[64]; + u_int32_t e2fs_usrquota_inum; /* inode for tracking user quota */ + u_int32_t e2fs_grpquota_inum; /* inode for tracking group quota */ + u_int32_t e2fs_overhead_clusters;/* overhead blocks/clusters */ + u_int32_t e2fs_backup_bgs[2]; /* groups with sparse_super2 SBs */ + u_int8_t e2fs_encrypt_algos[4];/* encryption algorithms in use */ + u_int8_t e2fs_encrypt_pw_salt[16];/* salt used for string2key */ + u_int32_t e2fs_lpf_ino; /* location of the lost+found inode */ + u_int32_t e2fs_proj_quota_inum; /* inode for tracking project quota */ + u_int32_t e2fs_chksum_seed; /* checksum seed */ + u_int32_t e2fs_reserved[98]; /* padding to the end of the block */ + u_int32_t e2fs_sbchksum; /* superblock checksum */ +}; + + +/* in-memory data for ext2fs */ +struct m_ext2fs { + struct ext2fs e2fs; + u_char e2fs_fsmnt[MAXMNTLEN]; /* name mounted on */ + int8_t e2fs_ronly; /* mounted read-only flag */ + int8_t e2fs_fmod; /* super block modified flag */ + int32_t e2fs_fsize; /* fragment size */ + int32_t e2fs_bsize; /* block size */ + int32_t e2fs_bshift; /* ``lblkno'' calc of logical blkno */ + int32_t e2fs_bmask; /* ``blkoff'' calc of blk offsets */ + int64_t e2fs_qbmask; /* ~fs_bmask - for use with quad size */ + int32_t e2fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */ + int32_t e2fs_ncg; /* number of cylinder groups */ + int32_t e2fs_ngdb; /* number of group descriptor block */ + int32_t e2fs_ipb; /* number of inodes per block */ + int32_t e2fs_itpg; /* number of inode table per group */ + off_t e2fs_maxfilesize; /* depends on LARGE/HUGE flags */ + struct ext2_gd *e2fs_gd; /* group descriptors */ +}; + +static inline int +e2fs_overflow(struct m_ext2fs *fs, off_t lower, off_t value) +{ + return (value < lower || value > fs->e2fs_maxfilesize); +} + +/* + * Filesystem identification + */ +#define E2FS_MAGIC 0xef53 /* the ext2fs magic number */ +#define E2FS_REV0 0 /* revision levels */ +#define E2FS_REV1 1 /* revision levels */ + +/* compatible/incompatible features */ +#define EXT2F_COMPAT_PREALLOC 0x0001 +#define EXT2F_COMPAT_IMAGIC_INODES 0x0002 +#define EXT2F_COMPAT_HAS_JOURNAL 0x0004 +#define EXT2F_COMPAT_EXT_ATTR 0x0008 +#define EXT2F_COMPAT_RESIZE 0x0010 +#define EXT2F_COMPAT_DIR_INDEX 0x0020 +#define EXT2F_COMPAT_SPARSE_SUPER2 0x0200 + +#define EXT2F_ROCOMPAT_SPARSE_SUPER 0x0001 +#define EXT2F_ROCOMPAT_LARGE_FILE 0x0002 +#define EXT2F_ROCOMPAT_BTREE_DIR 0x0004 +#define EXT2F_ROCOMPAT_HUGE_FILE 0x0008 +#define EXT2F_ROCOMPAT_GDT_CSUM 0x0010 +#define EXT2F_ROCOMPAT_DIR_NLINK 0x0020 +#define EXT2F_ROCOMPAT_EXTRA_ISIZE 0x0040 +#define EXT2F_ROCOMPAT_QUOTA 0x0100 +#define EXT2F_ROCOMPAT_BIGALLOC 0x0200 +#define EXT2F_ROCOMPAT_METADATA_CKSUM 0x0400 +#define EXT2F_ROCOMPAT_READONLY 0x1000 +#define EXT2F_ROCOMPAT_PROJECT 0x2000 + +#define EXT2F_INCOMPAT_COMP 0x0001 +#define EXT2F_INCOMPAT_FTYPE 0x0002 +#define EXT2F_INCOMPAT_RECOVER 0x0004 +#define EXT2F_INCOMPAT_JOURNAL_DEV 0x0008 +#define EXT2F_INCOMPAT_META_BG 0x0010 +#define EXT2F_INCOMPAT_EXTENTS 0x0040 +#define EXT2F_INCOMPAT_64BIT 0x0080 +#define EXT2F_INCOMPAT_MMP 0x0100 +#define EXT2F_INCOMPAT_FLEX_BG 0x0200 +#define EXT2F_INCOMPAT_EA_INODE 0x0400 +#define EXT2F_INCOMPAT_DIRDATA 0x1000 +#define EXT2F_INCOMPAT_CSUM_SEED 0x2000 +#define EXT2F_INCOMPAT_LARGEDIR 0x4000 +#define EXT2F_INCOMPAT_INLINE_DATA 0x8000 +#define EXT2F_INCOMPAT_ENCRYPT 0x10000 + +struct ext2_feature { + uint32_t mask; + const char *name; +}; + +static const struct ext2_feature ro_compat[] = { + { EXT2F_ROCOMPAT_SPARSE_SUPER, "sparse_super" }, + { EXT2F_ROCOMPAT_LARGE_FILE, "large_file" }, + { EXT2F_ROCOMPAT_BTREE_DIR, "btree_dir" }, + { EXT2F_ROCOMPAT_HUGE_FILE, "huge_file" }, + { EXT2F_ROCOMPAT_GDT_CSUM, "uninit_bg" }, + { EXT2F_ROCOMPAT_DIR_NLINK, "dir_nlink" }, + { EXT2F_ROCOMPAT_EXTRA_ISIZE, "extra_isize" }, + { EXT2F_ROCOMPAT_QUOTA, "quota" }, + { EXT2F_ROCOMPAT_BIGALLOC, "bigalloc" }, + { EXT2F_ROCOMPAT_METADATA_CKSUM, "metadata_csum" }, + { EXT2F_ROCOMPAT_READONLY, "read-only" }, + { EXT2F_ROCOMPAT_PROJECT, "project" } +}; + +static const struct ext2_feature incompat[] = { + { EXT2F_INCOMPAT_COMP, "compression" }, + { EXT2F_INCOMPAT_FTYPE, "filetype" }, + { EXT2F_INCOMPAT_RECOVER, "needs_recovery" }, + { EXT2F_INCOMPAT_JOURNAL_DEV, "journal_dev" }, + { EXT2F_INCOMPAT_META_BG, "meta_bg" }, + { EXT2F_INCOMPAT_EXTENTS, "extents" }, + { EXT2F_INCOMPAT_64BIT, "64bit" }, + { EXT2F_INCOMPAT_MMP, "mmp" }, + { EXT2F_INCOMPAT_FLEX_BG, "flex_bg" }, + { EXT2F_INCOMPAT_EA_INODE, "ea_inode" }, + { EXT2F_INCOMPAT_DIRDATA, "dirdata" }, + { EXT2F_INCOMPAT_CSUM_SEED, "metadata_csum_seed" }, + { EXT2F_INCOMPAT_LARGEDIR, "large_dir" }, + { EXT2F_INCOMPAT_INLINE_DATA, "inline_data" }, + { EXT2F_INCOMPAT_ENCRYPT, "encrypt" } +}; + +/* features supported in this implementation */ +#define EXT2F_COMPAT_SUPP 0x0000 +#define EXT2F_ROCOMPAT_SUPP (EXT2F_ROCOMPAT_SPARSE_SUPER | \ + EXT2F_ROCOMPAT_LARGE_FILE) +#define EXT2F_INCOMPAT_SUPP (EXT2F_INCOMPAT_FTYPE) +#define EXT4F_RO_INCOMPAT_SUPP (EXT2F_INCOMPAT_EXTENTS | \ + EXT2F_INCOMPAT_FLEX_BG | \ + EXT2F_INCOMPAT_META_BG | \ + EXT2F_INCOMPAT_RECOVER) + +/* + * Definitions of behavior on errors + */ +#define E2FS_BEH_CONTINUE 1 /* continue operation */ +#define E2FS_BEH_READONLY 2 /* remount fs read only */ +#define E2FS_BEH_PANIC 3 /* cause panic */ +#define E2FS_BEH_DEFAULT E2FS_BEH_CONTINUE + +/* + * OS identification + */ +#define E2FS_OS_LINUX 0 +#define E2FS_OS_HURD 1 +#define E2FS_OS_MASIX 2 + +/* + * Filesystem clean flags + */ +#define E2FS_ISCLEAN 0x01 +#define E2FS_ERRORS 0x02 + +/* ext2 file system block group descriptor */ + +struct ext2_gd { + u_int32_t ext2bgd_b_bitmap; /* blocks bitmap block */ + u_int32_t ext2bgd_i_bitmap; /* inodes bitmap block */ + u_int32_t ext2bgd_i_tables; /* inodes table block */ + u_int16_t ext2bgd_nbfree; /* number of free blocks */ + u_int16_t ext2bgd_nifree; /* number of free inodes */ + u_int16_t ext2bgd_ndirs; /* number of directories */ + u_int16_t reserved; + u_int32_t reserved2[3]; +}; + +/* + * If the EXT2F_ROCOMPAT_SPARSE_SUPER flag is set, the cylinder group has a + * copy of the super and cylinder group descriptors blocks only if it's + * a power of 3, 5 or 7 + */ + +static __inline__ int cg_has_sb(int) __attribute__((__unused__)); +static __inline int +cg_has_sb(int i) +{ + int a3 ,a5 , a7; + + if (i == 0 || i == 1) + return 1; + for (a3 = 3, a5 = 5, a7 = 7; + a3 <= i || a5 <= i || a7 <= i; + a3 *= 3, a5 *= 5, a7 *= 7) + if (i == a3 || i == a5 || i == a7) + return 1; + return 0; +} + +/* + * Ext2 metadata is stored in little-endian byte order. + * JBD2 journal used in ext3 and ext4 is big-endian! + */ +#if BYTE_ORDER == LITTLE_ENDIAN +#define e2fs_sbload(old, new) memcpy((new), (old), SBSIZE); +#define e2fs_cgload(old, new, size) memcpy((new), (old), (size)); +#define e2fs_sbsave(old, new) memcpy((new), (old), SBSIZE); +#define e2fs_cgsave(old, new, size) memcpy((new), (old), (size)); +#else +void e2fs_sb_bswap(struct ext2fs *, struct ext2fs *); +void e2fs_cg_bswap(struct ext2_gd *, struct ext2_gd *, int); +#define e2fs_sbload(old, new) e2fs_sb_bswap((old), (new)) +#define e2fs_cgload(old, new, size) e2fs_cg_bswap((old), (new), (size)); +#define e2fs_sbsave(old, new) e2fs_sb_bswap((old), (new)) +#define e2fs_cgsave(old, new, size) e2fs_cg_bswap((old), (new), (size)); +#endif + +/* + * Turn file system block numbers into disk block addresses. + * This maps file system blocks to device size blocks. + */ +#define fsbtodb(fs, b) ((b) << (fs)->e2fs_fsbtodb) +#define dbtofsb(fs, b) ((b) >> (fs)->e2fs_fsbtodb) + +/* + * Macros for handling inode numbers: + * inode number to file system block offset. + * inode number to cylinder group number. + * inode number to file system block address. + */ +#define ino_to_cg(fs, x) (((x) - 1) / (fs)->e2fs.e2fs_ipg) +#define ino_to_fsba(fs, x) \ + ((fs)->e2fs_gd[ino_to_cg(fs, x)].ext2bgd_i_tables + \ + (((x)-1) % (fs)->e2fs.e2fs_ipg)/(fs)->e2fs_ipb) +#define ino_to_fsbo(fs, x) (((x)-1) % (fs)->e2fs_ipb) + +/* + * Give cylinder group number for a file system block. + * Give cylinder group block number for a file system block. + */ +#define dtog(fs, d) (((d) - (fs)->e2fs.e2fs_first_dblock) / (fs)->e2fs.e2fs_fpg) +#define dtogd(fs, d) \ + (((d) - (fs)->e2fs.e2fs_first_dblock) % (fs)->e2fs.e2fs_fpg) + +/* + * The following macros optimize certain frequently calculated + * quantities by using shifts and masks in place of divisions + * modulos and multiplications. + */ +#define blkoff(fs, loc) /* calculates (loc % fs->e2fs_bsize) */ \ + ((loc) & (fs)->e2fs_qbmask) +#define lblktosize(fs, blk) /* calculates (blk * fs->e2fs_bsize) */ \ + ((blk) << (fs)->e2fs_bshift) +#define lblkno(fs, loc) /* calculates (loc / fs->e2fs_bsize) */ \ + ((loc) >> (fs)->e2fs_bshift) +#define blkroundup(fs, size) /* calculates roundup(size, fs->e2fs_bsize) */ \ + (((size) + (fs)->e2fs_qbmask) & (fs)->e2fs_bmask) +#define fragroundup(fs, size) /* calculates roundup(size, fs->e2fs_bsize) */ \ + (((size) + (fs)->e2fs_qbmask) & (fs)->e2fs_bmask) +/* + * Determine the number of available frags given a + * percentage to hold in reserve. + */ +#define freespace(fs) \ + ((fs)->e2fs.e2fs_fbcount - (fs)->e2fs.e2fs_rbcount) + +/* + * Number of indirects in a file system block. + */ +#define NINDIR(fs) ((fs)->e2fs_bsize / sizeof(u_int32_t)) \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ufs/ext2fs/ext2fs_dinode.h b/lib/libc/include/generic-openbsd/ufs/ext2fs/ext2fs_dinode.h new file mode 100644 index 000000000000..0b5972ecd2f8 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ufs/ext2fs/ext2fs_dinode.h @@ -0,0 +1,166 @@ +/* $OpenBSD: ext2fs_dinode.h,v 1.17 2014/07/31 17:37:52 pelikan Exp $ */ +/* $NetBSD: ext2fs_dinode.h,v 1.6 2000/01/26 16:21:33 bouyer Exp $ */ + +/* + * Copyright (c) 1997 Manuel Bouyer. + * Copyright (c) 1982, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)dinode.h 8.6 (Berkeley) 9/13/94 + * Modified for ext2fs by Manuel Bouyer. + */ + +#include +#include /* for ufsino_t */ + +/* + * The root inode is the root of the file system. Inode 0 can't be used for + * normal purposes and bad blocks are normally linked to inode 1, thus + * the root inode is 2. + * Inode 3 to 10 are reserved in ext2fs. + */ +#define EXT2_ROOTINO ((ufsino_t)2) +#define EXT2_RESIZEINO ((ufsino_t)7) +#define EXT2_FIRSTINO ((ufsino_t)11) + +/* + * A dinode contains all the meta-data associated with a UFS file. + * This structure defines the on-disk format of a dinode. Since + * this structure describes an on-disk structure, all its fields + * are defined by types with precise widths. + */ + +#define NDADDR 12 /* Direct addresses in inode. */ +#define NIADDR 3 /* Indirect addresses in inode. */ + +#define EXT2_MAXSYMLINKLEN ((NDADDR+NIADDR) * sizeof (u_int32_t)) + +struct ext2fs_dinode { + u_int16_t e2di_mode; /* 0: IFMT, permissions; see below. */ + u_int16_t e2di_uid_low; /* 2: owner UID, bits 15:0 */ + u_int32_t e2di_size; /* 4: file size (bytes) bits 31:0 */ + u_int32_t e2di_atime; /* 8: Access time */ + u_int32_t e2di_ctime; /* 12: Change time */ + u_int32_t e2di_mtime; /* 16: Modification time */ + u_int32_t e2di_dtime; /* 20: Deletion time */ + u_int16_t e2di_gid_low; /* 24: Owner GID, lowest bits */ + u_int16_t e2di_nlink; /* 26: File link count */ + u_int32_t e2di_nblock; /* 28: blocks count */ + u_int32_t e2di_flags; /* 32: status flags (chflags) */ + u_int32_t e2di_version_lo; /* 36: inode version, bits 31:0 */ + u_int32_t e2di_blocks[NDADDR+NIADDR]; /* 40: disk blocks */ + u_int32_t e2di_gen; /* 100: generation number */ + u_int32_t e2di_facl; /* 104: file ACL, bits 31:0 */ + u_int32_t e2di_size_hi; /* 108: file size (bytes), bits 63:32 */ + u_int32_t e2di_faddr; /* 112: fragment address (obsolete) */ + u_int16_t e2di_nblock_hi; /* 116: blocks count, bits 47:32 */ + u_int16_t e2di_facl_hi; /* 118: file ACL, bits 47:32 */ + u_int16_t e2di_uid_high; /* 120: owner UID, bits 31:16 */ + u_int16_t e2di_gid_high; /* 122: owner GID, bits 31:16 */ + u_int16_t e2di_chksum_lo; /* 124: inode checksum, bits 15:0 */ + u_int16_t e2di__reserved; /* 126: unused */ + u_int16_t e2di_isize; /* 128: size of this inode */ + u_int16_t e2di_chksum_hi; /* 130: inode checksum, bits 31:16 */ + u_int32_t e2di_x_ctime; /* 132: extra Change time */ + u_int32_t e2di_x_mtime; /* 136: extra Modification time */ + u_int32_t e2di_x_atime; /* 140: extra Access time */ + u_int32_t e2di_crtime; /* 144: Creation (birth) time */ + u_int32_t e2di_x_crtime; /* 148: extra Creation (birth) time */ + u_int32_t e2di_version_hi; /* 152: inode version, bits 63:31 */ +}; + +#define E2MAXSYMLINKLEN ((NDADDR + NIADDR) * sizeof(u_int32_t)) + +/* File permissions. */ +#define EXT2_IEXEC 0000100 /* Executable. */ +#define EXT2_IWRITE 0000200 /* Writeable. */ +#define EXT2_IREAD 0000400 /* Readable. */ +#define EXT2_ISVTX 0001000 /* Sticky bit. */ +#define EXT2_ISGID 0002000 /* Set-gid. */ +#define EXT2_ISUID 0004000 /* Set-uid. */ + +/* File types. */ +#define EXT2_IFMT 0170000 /* Mask of file type. */ +#define EXT2_IFIFO 0010000 /* Named pipe (fifo). */ +#define EXT2_IFCHR 0020000 /* Character device. */ +#define EXT2_IFDIR 0040000 /* Directory file. */ +#define EXT2_IFBLK 0060000 /* Block device. */ +#define EXT2_IFREG 0100000 /* Regular file. */ +#define EXT2_IFLNK 0120000 /* Symbolic link. */ +#define EXT2_IFSOCK 0140000 /* UNIX domain socket. */ + +/* file flags */ +#define EXT2_SECRM 0x00000001 /* Secure deletion */ +#define EXT2_UNRM 0x00000002 /* Undelete */ +#define EXT2_COMPR 0x00000004 /* Compress file */ +#define EXT2_SYNC 0x00000008 /* Synchronous updates */ +#define EXT2_IMMUTABLE 0x00000010 /* Immutable file */ +#define EXT2_APPEND 0x00000020 /* writes to file may only append */ +#define EXT2_NODUMP 0x00000040 /* do not dump file */ +#define EXT2_NOATIME 0x00000080 /* do not update access time */ +#define EXT4_INDEX 0x00001000 /* hash-indexed directory */ +#define EXT4_JOURNAL_DATA 0x00004000 /* file data should be journaled */ +#define EXT4_DIRSYNC 0x00010000 /* all dirent updates done synchronously */ +#define EXT4_TOPDIR 0x00020000 /* top of directory hierarchies */ +#define EXT4_HUGE_FILE 0x00040000 /* nblocks unit is fsb, not db */ +#define EXT4_EXTENTS 0x00080000 /* inode uses extents */ +#define EXT4_EOFBLOCKS 0x00400000 /* blocks allocated beyond EOF */ + +/* Size of on-disk inode. */ +#define EXT2_REV0_DINODE_SIZE 128 +#define EXT2_DINODE_SIZE(fs) ((fs)->e2fs.e2fs_rev > E2FS_REV0 ? \ + (fs)->e2fs.e2fs_inode_size : \ + EXT2_REV0_DINODE_SIZE) + +/* + * The e2di_blocks fields may be overlaid with other information for + * file types that do not have associated disk storage. Block + * and character devices overlay the first data block with their + * dev_t value. Short symbolic links place their path in the + * di_db area. + */ + +#define e2di_rdev e2di_blocks[0] +#define e2di_shortlink e2di_blocks + +/* e2fs needs byte swapping on big-endian systems */ +#if BYTE_ORDER == LITTLE_ENDIAN +# define e2fs_iload(fs, old, new) \ + memcpy((new),(old), MIN(EXT2_DINODE_SIZE(fs), sizeof(*new))) +# define e2fs_isave(fs, old, new) \ + memcpy((new),(old), MIN(EXT2_DINODE_SIZE(fs), sizeof(*new))) +#else +struct m_ext2fs; +void e2fs_i_bswap(struct m_ext2fs *, struct ext2fs_dinode *, struct ext2fs_dinode *); +# define e2fs_iload(fs, old, new) e2fs_i_bswap((fs), (old), (new)) +# define e2fs_isave(fs, old, new) e2fs_i_bswap((fs), (old), (new)) +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ufs/ext2fs/ext2fs_dir.h b/lib/libc/include/generic-openbsd/ufs/ext2fs/ext2fs_dir.h new file mode 100644 index 000000000000..b47408f6b057 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ufs/ext2fs/ext2fs_dir.h @@ -0,0 +1,170 @@ +/* $OpenBSD: ext2fs_dir.h,v 1.12 2024/01/09 03:16:00 guenther Exp $ */ +/* $NetBSD: ext2fs_dir.h,v 1.4 2000/01/28 16:00:23 bouyer Exp $ */ + +/* + * Copyright (c) 1997 Manuel Bouyer. + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)dir.h 8.4 (Berkeley) 8/10/94 + * Modified for ext2fs by Manuel Bouyer. + */ + +#ifndef _EXT2FS_DIR_H_ +#define _EXT2FS_DIR_H_ + +/* + * Theoretically, directories can be more than 2Gb in length, however, in + * practice this seems unlikely. So, we define the type doff_t as a 32-bit + * quantity to keep down the cost of doing lookup on a 32-bit machine. + */ +#define doff_t int32_t +#define EXT2FS_MAXDIRSIZE (0x7fffffff) + +/* + * A directory consists of some number of blocks of e2fs_bsize bytes. + * + * Each block contains some number of directory entry + * structures, which are of variable length. Each directory entry has + * a struct direct at the front of it, containing its inode number, + * the length of the entry, and the length of the name contained in + * the entry. These are followed by the name padded to a 4 byte boundary + * with null bytes. All names are guaranteed null terminated. + * The maximum length of a name in a directory is EXT2FS_MAXNAMLEN. + * + * The macro EXT2FS_DIRSIZ(dp) gives the amount of space required to + * represent a directory entry. Free space in a directory is represented by + * entries which have dp->e2d_reclen > DIRSIZ(dp). All d2fs_bsize bytes + * in a directory block are claimed by the directory entries. This + * usually results in the last entry in a directory having a large + * dp->e2d_reclen. When entries are deleted from a directory, the + * space is returned to the previous entry in the same directory + * block by increasing its dp->e2d_reclen. If the first entry of + * a directory block is free, then its dp->e2d_ino is set to 0. + * Entries other than the first in a directory do not normally have + * dp->e2d_ino set to 0. + * Ext2 rev 0 has a 16 bits e2d_namlen. For Ext2 rev 1 this has been split + * into a 8 bits e2d_namlen and 8 bits e2d_type (looks like ffs, isnt't it ? :) + * It's safe to use this for rev 0 as well because all ext2 are little-endian. + */ + +#define EXT2FS_MAXNAMLEN 255 + +struct ext2fs_direct { + u_int32_t e2d_ino; /* inode number of entry */ + u_int16_t e2d_reclen; /* length of this record */ + u_int8_t e2d_namlen; /* length of string in d_name */ + u_int8_t e2d_type; /* file type */ + char e2d_name[EXT2FS_MAXNAMLEN];/* name with length <= EXT2FS_MAXNAMLEN */ +}; + +enum slotstatus { + NONE, + COMPACT, + FOUND +}; + +struct ext2fs_searchslot { + enum slotstatus slotstatus; + doff_t slotoffset; /* offset of area with free space */ + int slotsize; /* size of area at slotoffset */ + int slotfreespace; /* amount of space free in slot */ + int slotneeded; /* sizeof the entry we are seeking */ +}; + +/* Ext2 directory file types (not the same as FFS. Sigh. */ +#define EXT2_FT_UNKNOWN 0 +#define EXT2_FT_REG_FILE 1 +#define EXT2_FT_DIR 2 +#define EXT2_FT_CHRDEV 3 +#define EXT2_FT_BLKDEV 4 +#define EXT2_FT_FIFO 5 +#define EXT2_FT_SOCK 6 +#define EXT2_FT_SYMLINK 7 + +#define EXT2_FT_MAX 8 + +#define E2IFTODT(mode) (((mode) & 0170000) >> 12) + +static __inline__ u_int8_t inot2ext2dt(u_int16_t) + __attribute__((__unused__)); +static __inline__ u_int8_t +inot2ext2dt(u_int16_t type) +{ + switch(type) { + case E2IFTODT(EXT2_IFIFO): + return EXT2_FT_FIFO; + case E2IFTODT(EXT2_IFCHR): + return EXT2_FT_CHRDEV; + case E2IFTODT(EXT2_IFDIR): + return EXT2_FT_DIR; + case E2IFTODT(EXT2_IFBLK): + return EXT2_FT_BLKDEV; + case E2IFTODT(EXT2_IFREG): + return EXT2_FT_REG_FILE; + case E2IFTODT(EXT2_IFLNK): + return EXT2_FT_SYMLINK; + case E2IFTODT(EXT2_IFSOCK): + return EXT2_FT_SOCK; + default: + return 0; + } +} + +/* + * The EXT2FS_DIRSIZ macro gives the minimum record length which will hold + * the directory entryfor a name len "len" (without the terminating null byte). + * This requires the amount of space in struct direct + * without the d_name field, plus enough space for the name without a + * terminating null byte, rounded up to a 4 byte boundary. + */ +#define EXT2FS_DIRSIZ(len) \ + (( 8 + len + 3) &~ 3) + +/* + * Template for manipulating directories. Should use struct direct's, + * but the name field is EXT2FS_MAXNAMLEN - 1, and this just won't do. + */ +struct ext2fs_dirtemplate { + u_int32_t dot_ino; + int16_t dot_reclen; + u_int8_t dot_namlen; + u_int8_t dot_type; + char dot_name[4]; /* must be multiple of 4 */ + u_int32_t dotdot_ino; + int16_t dotdot_reclen; + u_int8_t dotdot_namlen; + u_int8_t dotdot_type; + char dotdot_name[4]; /* ditto */ +}; + +#endif /* !_EXT2FS_DIR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ufs/ext2fs/ext2fs_extents.h b/lib/libc/include/generic-openbsd/ufs/ext2fs/ext2fs_extents.h new file mode 100644 index 000000000000..a682d681b194 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ufs/ext2fs/ext2fs_extents.h @@ -0,0 +1,99 @@ +/*- + * Copyright (c) 2012, 2010 Zheng Liu + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: head/sys/fs/ext2fs/ext2_extents.h 262623 2014-02-28 21:25:32Z pfg $ + */ +#ifndef _FS_EXT2FS_EXT2_EXTENTS_H_ +#define _FS_EXT2FS_EXT2_EXTENTS_H_ + +#include + +#define EXT4_EXT_MAGIC 0xf30a + +#define EXT4_EXT_CACHE_NO 0 +#define EXT4_EXT_CACHE_GAP 1 +#define EXT4_EXT_CACHE_IN 2 + +/* + * Ext4 file system extent on disk. + */ +struct ext4_extent { + uint32_t e_blk; /* first logical block */ + uint16_t e_len; /* number of blocks */ + uint16_t e_start_hi; /* high 16 bits of physical block */ + uint32_t e_start_lo; /* low 32 bits of physical block */ +}; + +/* + * Extent index on disk. + */ +struct ext4_extent_index { + uint32_t ei_blk; /* indexes logical blocks */ + uint32_t ei_leaf_lo; /* points to physical block of the + * next level */ + uint16_t ei_leaf_hi; /* high 16 bits of physical block */ + uint16_t ei_unused; +}; + +/* + * Extent tree header. + */ +struct ext4_extent_header { + uint16_t eh_magic; /* magic number: 0xf30a */ + uint16_t eh_ecount; /* number of valid entries */ + uint16_t eh_max; /* capacity of store in entries */ + uint16_t eh_depth; /* the depth of extent tree */ + uint32_t eh_gen; /* generation of extent tree */ +}; + +/* + * Save cached extent. + */ +struct ext4_extent_cache { + daddr_t ec_start; /* extent start */ + uint32_t ec_blk; /* logical block */ + uint32_t ec_len; + uint32_t ec_type; +}; + +/* + * Save path to some extent. + */ +struct ext4_extent_path { + uint16_t ep_depth; + struct buf *ep_bp; + struct ext4_extent *ep_ext; + struct ext4_extent_index *ep_index; + struct ext4_extent_header *ep_header; +}; + +struct inode; +struct m_ext2fs; +int ext4_ext_in_cache(struct inode *, daddr_t, struct ext4_extent *); +void ext4_ext_put_cache(struct inode *, struct ext4_extent *, int); +struct ext4_extent_path *ext4_ext_find_extent(struct m_ext2fs *fs, + struct inode *, daddr_t, struct ext4_extent_path *); + +#endif /* !_FS_EXT2FS_EXT2_EXTENTS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ufs/ext2fs/ext2fs_extern.h b/lib/libc/include/generic-openbsd/ufs/ext2fs/ext2fs_extern.h new file mode 100644 index 000000000000..c581077cf447 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ufs/ext2fs/ext2fs_extern.h @@ -0,0 +1,146 @@ +/* $OpenBSD: ext2fs_extern.h,v 1.40 2025/07/07 00:55:15 jsg Exp $ */ +/* $NetBSD: ext2fs_extern.h,v 1.1 1997/06/11 09:33:55 bouyer Exp $ */ + +/*- + * Copyright (c) 1997 Manuel Bouyer. + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ffs_extern.h 8.3 (Berkeley) 4/16/94 + * Modified for ext2fs by Manuel Bouyer. + */ + +struct buf; +struct fid; +struct m_ext2fs; +struct inode; +struct mount; +struct nameidata; +struct proc; +struct statfs; +struct timeval; +struct ucred; +struct ufsmount; +struct uio; +struct vnode; +struct vfsconf; +struct mbuf; +struct componentname; + +extern struct pool ext2fs_inode_pool; /* memory pool for inodes */ +extern struct pool ext2fs_dinode_pool; /* memory pool for dinodes */ + +__BEGIN_DECLS + +/* ext2fs_alloc.c */ +int ext2fs_alloc(struct inode *, u_int32_t, u_int32_t , struct ucred *, + u_int32_t *); +int ext2fs_inode_alloc(struct inode *, mode_t mode, struct ucred *, + struct vnode **); +daddr_t ext2fs_blkpref(struct inode *, u_int32_t, int, u_int32_t *); +void ext2fs_blkfree(struct inode *, u_int32_t); +void ext2fs_inode_free(struct inode *, ufsino_t, mode_t); + +/* ext2fs_balloc.c */ +int ext2fs_buf_alloc(struct inode *, u_int32_t, int, struct ucred *, + struct buf **, int); + +/* ext2fs_bmap.c */ +int ext2fs_bmap(void *); + +/* ext2fs_inode.c */ +u_int64_t ext2fs_size(struct inode *); +int ext2fs_init(struct vfsconf *); +int ext2fs_setsize(struct inode *, u_int64_t); +int ext2fs_update(struct inode *ip, int waitfor); +int ext2fs_truncate(struct inode *, off_t, int, struct ucred *); +int ext2fs_inactive(void *); + +/* ext2fs_lookup.c */ +int ext2fs_readdir(void *); +int ext2fs_lookup(void *); +int ext2fs_direnter(struct inode *, struct vnode *, struct componentname *); +int ext2fs_dirremove(struct vnode *, struct componentname *); +int ext2fs_dirrewrite(struct inode *, struct inode *, struct componentname *); +int ext2fs_dirempty(struct inode *, ufsino_t, struct ucred *); +int ext2fs_checkpath(struct inode *, struct inode *, struct ucred *); + +/* ext2fs_subr.c */ +int ext2fs_bufatoff(struct inode *, off_t, char **, struct buf **); +int ext2fs_vinit(struct mount *, struct vnode **); + +/* ext2fs_vfsops.c */ +int ext2fs_mountroot(void); +int ext2fs_mount(struct mount *, const char *, void *, struct nameidata *, + struct proc *); +int ext2fs_reload(struct mount *, struct ucred *, struct proc *); +int ext2fs_mountfs(struct vnode *, struct mount *, struct proc *); +int ext2fs_unmount(struct mount *, int, struct proc *); +int ext2fs_flushfiles(struct mount *, int, struct proc *); +int ext2fs_statfs(struct mount *, struct statfs *, struct proc *); +int ext2fs_sync(struct mount *, int, int, struct ucred *, struct proc *); +int ext2fs_vget(struct mount *, ino_t, struct vnode **); +int ext2fs_fhtovp(struct mount *, struct fid *, struct vnode **); +int ext2fs_vptofh(struct vnode *, struct fid *); +int ext2fs_sbupdate(struct ufsmount *, int); +int ext2fs_cgupdate(struct ufsmount *, int); + +/* ext2fs_readwrite.c */ +int ext2fs_read(void *); +int ext2fs_write(void *); + +/* ext2fs_vnops.c */ +int ext2fs_create(void *); +int ext2fs_mknod(void *); +int ext2fs_open(void *); +int ext2fs_access(void *); +int ext2fs_getattr(void *); +int ext2fs_setattr(void *); +int ext2fs_remove(void *); +int ext2fs_link(void *); +int ext2fs_rename(void *); +int ext2fs_mkdir(void *); +int ext2fs_rmdir(void *); +int ext2fs_symlink(void *); +int ext2fs_readlink(void *); +int ext2fs_pathconf(void *); +int ext2fs_advlock(void *); +int ext2fs_makeinode(int, struct vnode *, struct vnode **, + struct componentname *cnp); +int ext2fs_fsync(void *); +int ext2fs_reclaim(void *); +int ext2fsfifo_reclaim(void *); + +__END_DECLS + +#define IS_EXT2_VNODE(vp) (vp->v_tag == VT_EXT2FS) + +extern const struct vops ext2fs_vops; +extern const struct vops ext2fs_specvops; +#ifdef FIFO +extern const struct vops ext2fs_fifovops; +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ufs/ffs/ffs_extern.h b/lib/libc/include/generic-openbsd/ufs/ffs/ffs_extern.h new file mode 100644 index 000000000000..99a45c6fe4b4 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ufs/ffs/ffs_extern.h @@ -0,0 +1,170 @@ +/* $OpenBSD: ffs_extern.h,v 1.51 2024/10/08 02:58:26 jsg Exp $ */ +/* $NetBSD: ffs_extern.h,v 1.4 1996/02/09 22:22:22 christos Exp $ */ + +/* + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ffs_extern.h 8.3 (Berkeley) 4/16/94 + */ + +#define FFS_CLUSTERREAD 1 /* cluster reading enabled */ +#define FFS_CLUSTERWRITE 2 /* cluster writing enabled */ +#define FFS_REALLOCBLKS 3 /* block reallocation enabled */ +#define FFS_ASYNCFREE 4 /* asynchronous block freeing enabled */ +#define FFS_MAX_SOFTDEPS 5 /* maximum structs before slowdown */ +#define FFS_SD_TICKDELAY 6 /* ticks to pause during slowdown */ +#define FFS_SD_WORKLIST_PUSH 7 /* # of worklist cleanups */ +#define FFS_SD_BLK_LIMIT_PUSH 8 /* # of times block limit neared */ +#define FFS_SD_INO_LIMIT_PUSH 9 /* # of times inode limit neared */ +#define FFS_SD_BLK_LIMIT_HIT 10 /* # of times block slowdown imposed */ +#define FFS_SD_INO_LIMIT_HIT 11 /* # of times inode slowdown imposed */ +#define FFS_SD_SYNC_LIMIT_HIT 12 /* # of synchronous slowdowns imposed */ +#define FFS_SD_INDIR_BLK_PTRS 13 /* bufs redirtied as indir ptrs not written */ +#define FFS_SD_INODE_BITMAP 14 /* bufs redirtied as inode bitmap not written */ +#define FFS_SD_DIRECT_BLK_PTRS 15 /* bufs redirtied as direct ptrs not written */ +#define FFS_SD_DIR_ENTRY 16 /* bufs redirtied as dir entry cannot write */ +#define FFS_DIRHASH_DIRSIZE 17 /* min directory size, in bytes */ +#define FFS_DIRHASH_MAXMEM 18 /* max kvm to use, in bytes */ +#define FFS_DIRHASH_MEM 19 /* current mem usage, in bytes */ +#define FFS_MAXID 20 /* number of valid ffs ids */ + +#define FFS_NAMES { \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "dirhash_dirsize", CTLTYPE_INT }, \ + { "dirhash_maxmem", CTLTYPE_INT }, \ + { "dirhash_mem", CTLTYPE_INT }, \ +} + +struct buf; +struct fid; +struct fs; +struct inode; +struct mount; +struct nameidata; +struct proc; +struct statfs; +struct timeval; +struct ucred; +struct ufsmount; +struct vfsconf; +struct uio; +struct vnode; +struct mbuf; +struct cg; +struct vop_vfree_args; + +extern const struct vops ffs_vops; +extern const struct vops ffs_specvops; +extern const struct vops ffs_fifovops; + +/* ffs_alloc.c */ +int ffs_alloc(struct inode *, daddr_t, daddr_t , int, struct ucred *, + daddr_t *); +int ffs_realloccg(struct inode *, daddr_t, daddr_t, int, int , + struct ucred *, struct buf **, daddr_t *); +int ffs_inode_alloc(struct inode *, mode_t, struct ucred *, struct vnode **); +int ffs_inode_free(struct inode *, ufsino_t, mode_t); +int ffs_freefile(struct inode *, ufsino_t, mode_t); + +int32_t ffs1_blkpref(struct inode *, daddr_t, int, int32_t *); +#ifdef FFS2 +int64_t ffs2_blkpref(struct inode *, daddr_t, int, int64_t *); +#endif +void ffs_blkfree(struct inode *, daddr_t, long); +void ffs_clusteracct(struct fs *, struct cg *, daddr_t, int); + +/* ffs_balloc.c */ +int ffs_balloc(struct inode *, off_t, int, struct ucred *, int, struct buf **); + +/* ffs_inode.c */ +int ffs_init(struct vfsconf *); +int ffs_update(struct inode *, int); +int ffs_truncate(struct inode *, off_t, int, struct ucred *); + +/* ffs_subr.c */ +int ffs_bufatoff(struct inode *, off_t, char **, struct buf **); +void ffs_fragacct(struct fs *, int, int32_t[], int); +int ffs_isfreeblock(struct fs *, u_char *, daddr_t); +int ffs_isblock(struct fs *, u_char *, daddr_t); +void ffs_clrblock(struct fs *, u_char *, daddr_t); +void ffs_setblock(struct fs *, u_char *, daddr_t); +int ffs_vinit(struct mount *, struct vnode **); + +/* ffs_vfsops.c */ +int ffs_mountroot(void); +int ffs_mount(struct mount *, const char *, void *, struct nameidata *, + struct proc *); +int ffs_reload(struct mount *, struct ucred *, struct proc *); +int ffs_mountfs(struct vnode *, struct mount *, struct proc *); +int ffs_oldfscompat(struct fs *); +int ffs_unmount(struct mount *, int, struct proc *); +int ffs_flushfiles(struct mount *, int, struct proc *); +int ffs_statfs(struct mount *, struct statfs *, struct proc *); +int ffs_sync(struct mount *, int, int, struct ucred *, struct proc *); +int ffs_vget(struct mount *, ino_t, struct vnode **); +int ffs_fhtovp(struct mount *, struct fid *, struct vnode **); +int ffs_vptofh(struct vnode *, struct fid *); +int ffs_sysctl(int *, u_int, void *, size_t *, void *, size_t, + struct proc *); +int ffs_sbupdate(struct ufsmount *, int); + +/* ffs_vnops.c */ +int ffs_read(void *); +int ffs_write(void *); +int ffs_fsync(void *); +int ffs_reclaim(void *); +int ffsfifo_reclaim(void *); + +/* + * Soft dependency function prototypes. + */ + +struct vop_vfree_args; +struct vop_fsync_args; + +extern struct pool ffs_ino_pool; /* memory pool for inodes */ +extern struct pool ffs_dinode1_pool; /* memory pool for UFS1 dinodes */ +#ifdef FFS2 +extern struct pool ffs_dinode2_pool; /* memory pool for UFS2 dinodes */ +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ufs/ffs/fs.h b/lib/libc/include/generic-openbsd/ufs/ffs/fs.h new file mode 100644 index 000000000000..688b167ef2e8 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ufs/ffs/fs.h @@ -0,0 +1,591 @@ +/* $OpenBSD: fs.h,v 1.45 2024/02/03 18:51:58 beck Exp $ */ +/* $NetBSD: fs.h,v 1.6 1995/04/12 21:21:02 mycroft Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)fs.h 8.10 (Berkeley) 10/27/94 + */ + +/* + * Each disk drive contains some number of file systems. + * A file system consists of a number of cylinder groups. + * Each cylinder group has inodes and data. + * + * A file system is described by its super-block, which in turn + * describes the cylinder groups. The super-block is critical + * data and is replicated in each cylinder group to protect against + * catastrophic loss. This is done at `newfs' time and the critical + * super-block data does not change, so the copies need not be + * referenced further unless disaster strikes. + * + * For file system fs, the offsets of the various blocks of interest + * are given in the super block as: + * [fs->fs_sblkno] Super-block + * [fs->fs_cblkno] Cylinder group block + * [fs->fs_iblkno] Inode blocks + * [fs->fs_dblkno] Data blocks + * The beginning of cylinder group cg in fs, is given by + * the ``cgbase(fs, cg)'' macro. + * + * The first boot and super blocks are given in absolute disk addresses. + * The byte-offset forms are preferred, as they don't imply a sector size. + */ +#define BBSIZE 8192 +#define SBSIZE 8192 +#define BBOFF ((off_t)(0)) +#define SBOFF ((off_t)(BBOFF + BBSIZE)) +#define BBLOCK ((daddr_t)(0)) +#define SBLOCK ((daddr_t)(BBLOCK + BBSIZE / DEV_BSIZE)) +#define SBLOCK_UFS1 8192 +#define SBLOCK_UFS2 65536 +#define SBLOCK_PIGGY 262144 +#define SBLOCKSIZE 8192 +#define SBLOCKSEARCH \ + { SBLOCK_UFS2, SBLOCK_UFS1, SBLOCK_PIGGY, -1 } + +/* + * Addresses stored in inodes are capable of addressing fragments + * of `blocks'. File system blocks of at most size MAXBSIZE can + * be optionally broken into 2, 4, or 8 pieces, each of which is + * addressable; these pieces may be DEV_BSIZE, or some multiple of + * a DEV_BSIZE unit. + * + * Large files consist of exclusively large data blocks. To avoid + * undue wasted disk space, the last data block of a small file may be + * allocated as only as many fragments of a large block as are + * necessary. The file system format retains only a single pointer + * to such a fragment, which is a piece of a single large block that + * has been divided. The size of such a fragment is determinable from + * information in the inode, using the ``blksize(fs, ip, lbn)'' macro. + * + * The file system records space availability at the fragment level; + * to determine block availability, aligned fragments are examined. + */ + +#define MAXFRAG 8 + +/* + * MINBSIZE is the smallest allowable block size. + * In order to insure that it is possible to create files of size + * 2^32 with only two levels of indirection, MINBSIZE is set to 4096. + * MINBSIZE must be big enough to hold a cylinder group block, + * thus changes to (struct cg) must keep its size within MINBSIZE. + * Note that super blocks are always of size SBSIZE, + * and that both SBSIZE and MAXBSIZE must be >= MINBSIZE. + */ +#define MINBSIZE 4096 + +/* + * The path name on which the file system is mounted is maintained + * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in + * the super block for this name. + */ +#define MAXMNTLEN 468 + +/* + * The volume name for this file system is kept in fs_volname. + * MAXVOLLEN defines the length of the buffer allocated. + */ +#define MAXVOLLEN 32 + +/* + * There is a 128-byte region in the superblock reserved for in-core + * pointers to summary information. Originally this included an array + * of pointers to blocks of struct csum; now there are just three + * pointers and the remaining space is padded with fs_ocsp[]. + * + * NOCSPTRS determines the size of this padding. One pointer (fs_csp) + * is taken away to point to a contiguous array of struct csum for + * all cylinder groups; a second (fs_maxcluster) points to an array + * of cluster sizes that is computed as cylinder groups are inspected, + * and the third points to an array that tracks the creation of new + * directories. + */ +#define NOCSPTRS ((128 / sizeof(void *)) - 4) + +/* + * A summary of contiguous blocks of various sizes is maintained + * in each cylinder group. Normally this is set by the initial + * value of fs_maxcontig. To conserve space, a maximum summary size + * is set by FS_MAXCONTIG. + */ +#define FS_MAXCONTIG 16 + +/* + * MINFREE gives the minimum acceptable percentage of file system + * blocks which may be free. If the freelist drops below this level + * only the superuser may continue to allocate blocks. This may + * be set to 0 if no reserve of free blocks is deemed necessary, + * however throughput drops by fifty percent if the file system + * is run at between 95% and 100% full; thus the minimum default + * value of fs_minfree is 5%. However, to get good clustering + * performance, 10% is a better choice. With 5% free space, + * fragmentation is not a problem, so we choose to optimize for time. + */ +#define MINFREE 5 +#define DEFAULTOPT FS_OPTTIME + +/* + * The directory preference algorithm(dirpref) can be tuned by adjusting + * the following parameters which tell the system the average file size + * and the average number of files per directory. These defaults are well + * selected for typical filesystems, but may need to be tuned for odd + * cases like filesystems being used for squid caches or news spools. + */ +#define AVFILESIZ 16384 /* expected average file size */ +#define AFPDIR 64 /* expected number of files per directory */ + +/* + * Size of superblock space reserved for snapshots. + */ +#define FSMAXSNAP 20 + +/* + * Per cylinder group information; summarized in blocks allocated + * from first cylinder group data blocks. These blocks have to be + * read in from fs_csaddr (size fs_cssize) in addition to the + * super block. + */ +struct csum { + int32_t cs_ndir; /* number of directories */ + int32_t cs_nbfree; /* number of free blocks */ + int32_t cs_nifree; /* number of free inodes */ + int32_t cs_nffree; /* number of free frags */ +}; + +struct csum_total { + int64_t cs_ndir; /* number of directories */ + int64_t cs_nbfree; /* number of free blocks */ + int64_t cs_nifree; /* number of free inodes */ + int64_t cs_nffree; /* number of free frags */ + int64_t cs_spare[4]; /* future expansion */ +}; + +/* + * Super block for an FFS file system. + */ +struct fs { + int32_t fs_firstfield; /* historic file system linked list, */ + int32_t fs_unused_1; /* used for incore super blocks */ + int32_t fs_sblkno; /* addr of super-block / frags */ + int32_t fs_cblkno; /* offset of cyl-block / frags */ + int32_t fs_iblkno; /* offset of inode-blocks / frags */ + int32_t fs_dblkno; /* offset of first data / frags */ + int32_t fs_cgoffset; /* cylinder group offset in cylinder */ + int32_t fs_cgmask; /* used to calc mod fs_ntrak */ + int32_t fs_ffs1_time; /* last time written */ + int32_t fs_ffs1_size; /* # of blocks in fs / frags */ + int32_t fs_ffs1_dsize; /* # of data blocks in fs */ + u_int32_t fs_ncg; /* # of cylinder groups */ + int32_t fs_bsize; /* size of basic blocks / bytes */ + int32_t fs_fsize; /* size of frag blocks / bytes */ + int32_t fs_frag; /* # of frags in a block in fs */ +/* these are configuration parameters */ + int32_t fs_minfree; /* minimum percentage of free blocks */ + int32_t fs_rotdelay; /* # of ms for optimal next block */ + int32_t fs_rps; /* disk revolutions per second */ +/* these fields can be computed from the others */ + int32_t fs_bmask; /* ``blkoff'' calc of blk offsets */ + int32_t fs_fmask; /* ``fragoff'' calc of frag offsets */ + int32_t fs_bshift; /* ``lblkno'' calc of logical blkno */ + int32_t fs_fshift; /* ``numfrags'' calc # of frags */ +/* these are configuration parameters */ + int32_t fs_maxcontig; /* max # of contiguous blks */ + int32_t fs_maxbpg; /* max # of blks per cyl group */ +/* these fields can be computed from the others */ + int32_t fs_fragshift; /* block to frag shift */ + int32_t fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */ + int32_t fs_sbsize; /* actual size of super block */ + int32_t fs_csmask; /* csum block offset (now unused) */ + int32_t fs_csshift; /* csum block number (now unused) */ + int32_t fs_nindir; /* value of NINDIR */ + u_int32_t fs_inopb; /* inodes per file system block */ + int32_t fs_nspf; /* DEV_BSIZE sectors per frag */ +/* yet another configuration parameter */ + int32_t fs_optim; /* optimization preference, see below */ +/* these fields are derived from the hardware */ + int32_t fs_npsect; /* DEV_BSIZE sectors/track + spares */ + int32_t fs_interleave; /* DEV_BSIZE sector interleave */ + int32_t fs_trackskew; /* sector 0 skew, per track */ +/* fs_id takes the space of the unused fs_headswitch and fs_trkseek fields */ + int32_t fs_id[2]; /* unique filesystem id */ +/* sizes determined by number of cylinder groups and their sizes */ + int32_t fs_ffs1_csaddr; /* blk addr of cyl grp summary area */ + int32_t fs_cssize; /* cyl grp summary area size / bytes */ + int32_t fs_cgsize; /* cyl grp block size / bytes */ +/* these fields are derived from the hardware */ + int32_t fs_ntrak; /* tracks per cylinder */ + int32_t fs_nsect; /* DEV_BSIZE sectors per track */ + int32_t fs_spc; /* DEV_BSIZE sectors per cylinder */ +/* this comes from the disk driver partitioning */ + int32_t fs_ncyl; /* cylinders in file system */ +/* these fields can be computed from the others */ + int32_t fs_cpg; /* cylinders per group */ + u_int32_t fs_ipg; /* inodes per group */ + int32_t fs_fpg; /* blocks per group * fs_frag */ +/* this data must be re-computed after crashes */ + struct csum fs_ffs1_cstotal; /* cylinder summary information */ +/* these fields are cleared at mount time */ + int8_t fs_fmod; /* super block modified flag */ + int8_t fs_clean; /* file system is clean flag */ + int8_t fs_ronly; /* mounted read-only flag */ + int8_t fs_ffs1_flags; /* see FS_ below */ + u_char fs_fsmnt[MAXMNTLEN]; /* name mounted on */ + u_char fs_volname[MAXVOLLEN]; /* volume name */ + u_int64_t fs_swuid; /* system-wide uid */ + int32_t fs_pad; /* due to alignment of fs_swuid */ +/* these fields retain the current block allocation info */ + int32_t fs_cgrotor; /* last cg searched */ + void *fs_ocsp[NOCSPTRS]; /* padding; was list of fs_cs buffers */ + u_int8_t *fs_contigdirs; /* # of contiguously allocated dirs */ + struct csum *fs_csp; /* cg summary info buffer for fs_cs */ + int32_t *fs_maxcluster; /* max cluster in each cyl group */ + u_char *fs_active; /* reserved for snapshots */ + int32_t fs_cpc; /* cyl per cycle in postbl */ +/* this area is only allocated if fs_ffs1_flags & FS_FLAGS_UPDATED */ + int32_t fs_maxbsize; /* maximum blocking factor permitted */ + int64_t fs_spareconf64[17]; /* old rotation block list head */ + int64_t fs_sblockloc; /* offset of standard super block */ + struct csum_total fs_cstotal; /* cylinder summary information */ + int64_t fs_time; /* time last written */ + int64_t fs_size; /* number of blocks in fs */ + int64_t fs_dsize; /* number of data blocks in fs */ + int64_t fs_csaddr; /* blk addr of cyl grp summary area */ + int64_t fs_pendingblocks; /* blocks in process of being freed */ + u_int32_t fs_pendinginodes; /* inodes in process of being freed */ + u_int32_t fs_snapinum[FSMAXSNAP];/* space reserved for snapshots */ +/* back to stuff that has been around a while */ + u_int32_t fs_avgfilesize; /* expected average file size */ + u_int32_t fs_avgfpdir; /* expected # of files per directory */ + int32_t fs_sparecon[26]; /* reserved for future constants */ + u_int32_t fs_flags; /* see FS_ flags below */ + int32_t fs_fscktime; /* last time fsck(8)ed */ + int32_t fs_contigsumsize; /* size of cluster summary array */ + int32_t fs_maxsymlinklen; /* max length of an internal symlink */ + int32_t fs_inodefmt; /* format of on-disk inodes */ + u_int64_t fs_maxfilesize; /* maximum representable file size */ + int64_t fs_qbmask; /* ~fs_bmask - for use with quad size */ + int64_t fs_qfmask; /* ~fs_fmask - for use with quad size */ + int32_t fs_state; /* validate fs_clean field */ + int32_t fs_postblformat; /* format of positional layout tables */ + int32_t fs_nrpos; /* number of rotational positions */ + int32_t fs_postbloff; /* (u_int16) rotation block list head */ + int32_t fs_rotbloff; /* (u_int8) blocks for each rotation */ + int32_t fs_magic; /* magic number */ + u_int8_t fs_space[1]; /* list of blocks for each rotation */ +/* actually longer */ +}; + +/* + * Filesystem identification + */ +#define FS_MAGIC 0x011954 /* the fast filesystem magic number */ +#define FS_UFS1_MAGIC 0x011954 /* the fast filesystem magic number */ +#define FS_UFS2_MAGIC 0x19540119 /* UFS fast filesystem magic number */ +#define FS_OKAY 0x7c269d38 /* superblock checksum */ +#define FS_42INODEFMT -1 /* 4.2BSD inode format */ +#define FS_44INODEFMT 2 /* 4.4BSD inode format */ + +/* + * Filesystem clean flags + */ +#define FS_ISCLEAN 0x01 +#define FS_WASCLEAN 0x02 + +/* + * Preference for optimization. + */ +#define FS_OPTTIME 0 /* minimize allocation time */ +#define FS_OPTSPACE 1 /* minimize disk fragmentation */ + +/* + * Filesystem flags. + */ +#define FS_UNCLEAN 0x01 /* filesystem not clean at mount */ +/* + * The following flag is used to detect a FFS1 file system that had its flags + * moved to the new (FFS2) location for compatibility. + */ +#define FS_FLAGS_UPDATED 0x80 /* file system has FFS2-like flags */ + +/* + * Rotational layout table format types + */ +#define FS_42POSTBLFMT -1 /* 4.2BSD rotational table format */ +#define FS_DYNAMICPOSTBLFMT 1 /* dynamic rotational table format */ +/* + * Macros for access to superblock array structures + */ +#define fs_rotbl(fs) \ + (((fs)->fs_postblformat == FS_42POSTBLFMT) \ + ? ((fs)->fs_space) \ + : ((u_int8_t *)((u_int8_t *)(fs) + (fs)->fs_rotbloff))) + +/* + * The size of a cylinder group is calculated by CGSIZE. The maximum size + * is limited by the fact that cylinder groups are at most one block. + * Its size is derived from the size of the maps maintained in the + * cylinder group and the (struct cg) size. + */ +#define CGSIZE(fs) \ + /* base cg */ (sizeof(struct cg) + sizeof(int32_t) + \ + /* blktot size */ (fs)->fs_cpg * sizeof(int32_t) + \ + /* blks size */ (fs)->fs_cpg * (fs)->fs_nrpos * sizeof(int16_t) + \ + /* inode map */ howmany((fs)->fs_ipg, NBBY) + \ + /* block map */ howmany((fs)->fs_fpg, NBBY) + \ + /* if present */ ((fs)->fs_contigsumsize <= 0 ? 0 : \ + /* cluster sum */ (fs)->fs_contigsumsize * sizeof(int32_t) + \ + /* cluster map */ howmany(fragstoblks(fs, (fs)->fs_fpg), NBBY))) + +/* + * Convert cylinder group to base address of its global summary info. + */ +#define fs_cs(fs, indx) fs_csp[indx] + +/* + * Cylinder group block for a file system. + */ +#define CG_MAGIC 0x090255 +struct cg { + int32_t cg_firstfield; /* historic cyl groups linked list */ + int32_t cg_magic; /* magic number */ + int32_t cg_time; /* time last written */ + u_int32_t cg_cgx; /* we are the cgx'th cylinder group */ + int16_t cg_ncyl; /* number of cyl's this cg */ + int16_t cg_niblk; /* number of inode blocks this cg */ + u_int32_t cg_ndblk; /* number of data blocks this cg */ + struct csum cg_cs; /* cylinder summary information */ + u_int32_t cg_rotor; /* position of last used block */ + u_int32_t cg_frotor; /* position of last used frag */ + u_int32_t cg_irotor; /* position of last used inode */ + u_int32_t cg_frsum[MAXFRAG]; /* counts of available frags */ + int32_t cg_btotoff; /* (int32) block totals per cylinder */ + int32_t cg_boff; /* (u_int16) free block positions */ + u_int32_t cg_iusedoff; /* (u_int8) used inode map */ + u_int32_t cg_freeoff; /* (u_int8) free block map */ + u_int32_t cg_nextfreeoff; /* (u_int8) next available space */ + u_int32_t cg_clustersumoff; /* (u_int32) counts of avail clusters */ + u_int32_t cg_clusteroff; /* (u_int8) free cluster map */ + u_int32_t cg_nclusterblks; /* number of clusters this cg */ + u_int32_t cg_ffs2_niblk; /* number of inode blocks this cg */ + u_int32_t cg_initediblk; /* last initialized inode */ + int32_t cg_sparecon32[3]; /* reserved for future use */ + int64_t cg_ffs2_time; /* time last written */ + int64_t cg_sparecon64[3]; /* reserved for future use */ +/* actually longer */ +}; + +/* + * Macros for access to cylinder group array structures + */ +#define cg_blktot(cgp) \ + (((cgp)->cg_magic != CG_MAGIC) \ + ? (((struct ocg *)(cgp))->cg_btot) \ + : ((int32_t *)((u_int8_t *)(cgp) + (cgp)->cg_btotoff))) +#define cg_blks(fs, cgp, cylno) \ + (((cgp)->cg_magic != CG_MAGIC) \ + ? (((struct ocg *)(cgp))->cg_b[cylno]) \ + : ((int16_t *)((u_int8_t *)(cgp) + \ + (cgp)->cg_boff) + (cylno) * (fs)->fs_nrpos)) +#define cg_inosused(cgp) \ + (((cgp)->cg_magic != CG_MAGIC) \ + ? (((struct ocg *)(cgp))->cg_iused) \ + : ((u_int8_t *)((u_int8_t *)(cgp) + (cgp)->cg_iusedoff))) +#define cg_blksfree(cgp) \ + (((cgp)->cg_magic != CG_MAGIC) \ + ? (((struct ocg *)(cgp))->cg_free) \ + : ((u_int8_t *)((u_int8_t *)(cgp) + (cgp)->cg_freeoff))) +#define cg_chkmagic(cgp) \ + ((cgp)->cg_magic == CG_MAGIC || ((struct ocg *)(cgp))->cg_magic == CG_MAGIC) +#define cg_clustersfree(cgp) \ + ((u_int8_t *)((u_int8_t *)(cgp) + (cgp)->cg_clusteroff)) +#define cg_clustersum(cgp) \ + ((int32_t *)((u_int8_t *)(cgp) + (cgp)->cg_clustersumoff)) + +/* + * The following structure is defined + * for compatibility with old file systems. + */ +struct ocg { + int32_t cg_firstfield; /* historic linked list of cyl groups */ + int32_t cg_unused_1; /* used for incore cyl groups */ + int32_t cg_time; /* time last written */ + int32_t cg_cgx; /* we are the cgx'th cylinder group */ + int16_t cg_ncyl; /* number of cyl's this cg */ + int16_t cg_niblk; /* number of inode blocks this cg */ + int32_t cg_ndblk; /* number of data blocks this cg */ + struct csum cg_cs; /* cylinder summary information */ + int32_t cg_rotor; /* position of last used block */ + int32_t cg_frotor; /* position of last used frag */ + int32_t cg_irotor; /* position of last used inode */ + int32_t cg_frsum[8]; /* counts of available frags */ + int32_t cg_btot[32]; /* block totals per cylinder */ + int16_t cg_b[32][8]; /* positions of free blocks */ + u_int8_t cg_iused[256]; /* used inode map */ + int32_t cg_magic; /* magic number */ + u_int8_t cg_free[1]; /* free block map */ +/* actually longer */ +}; + +/* + * Turn file system block numbers into disk block addresses. + * This maps file system blocks to DEV_BSIZE (a.k.a. 512-byte) size disk + * blocks. + */ +#define fsbtodb(fs, b) ((b) << (fs)->fs_fsbtodb) +#define dbtofsb(fs, b) ((b) >> (fs)->fs_fsbtodb) + +/* + * Cylinder group macros to locate things in cylinder groups. + * They calc file system addresses of cylinder group data structures. + */ +#define cgbase(fs, c) ((daddr_t)(fs)->fs_fpg * (c)) +#define cgdata(fs, c) (cgdmin(fs, c) + (fs)->fs_minfree) /* data zone */ +#define cgmeta(fs, c) (cgdmin(fs, c)) /* meta data */ +#define cgdmin(fs, c) (cgstart(fs, c) + (fs)->fs_dblkno) /* 1st data */ +#define cgimin(fs, c) (cgstart(fs, c) + (fs)->fs_iblkno) /* inode blk */ +#define cgsblock(fs, c) (cgstart(fs, c) + (fs)->fs_sblkno) /* super blk */ +#define cgtod(fs, c) (cgstart(fs, c) + (fs)->fs_cblkno) /* cg block */ +#define cgstart(fs, c) \ + (cgbase(fs, c) + (fs)->fs_cgoffset * ((c) & ~((fs)->fs_cgmask))) + +/* + * Macros for handling inode numbers: + * inode number to file system block offset. + * inode number to cylinder group number. + * inode number to file system block address. + */ +#define ino_to_cg(fs, x) ((x) / (fs)->fs_ipg) +#define ino_to_fsba(fs, x) \ + ((daddr_t)(cgimin(fs, ino_to_cg(fs, x)) + \ + (blkstofrags((fs), (((x) % (fs)->fs_ipg) / INOPB(fs)))))) +#define ino_to_fsbo(fs, x) ((x) % INOPB(fs)) + +/* + * Give cylinder group number for a file system block. + * Give frag block number in cylinder group for a file system block. + */ +#define dtog(fs, d) ((d) / (fs)->fs_fpg) +#define dtogd(fs, d) ((d) % (fs)->fs_fpg) + +/* + * Extract the bits for a block from a map. + * Compute the cylinder and rotational position of a cyl block addr. + */ +#define blkmap(fs, map, loc) \ + (((map)[(loc) / NBBY] >> ((loc) % NBBY)) & (0xff >> (NBBY - (fs)->fs_frag))) +#define cbtocylno(fs, bno) \ + (fsbtodb(fs, bno) / (fs)->fs_spc) +#define cbtorpos(fs, bno) \ + ((fs)->fs_nrpos <= 1 ? 0 : \ + (fsbtodb(fs, bno) % (fs)->fs_spc / (fs)->fs_nsect * (fs)->fs_trackskew + \ + fsbtodb(fs, bno) % (fs)->fs_spc % (fs)->fs_nsect * (fs)->fs_interleave) % \ + (fs)->fs_nsect * (fs)->fs_nrpos / (fs)->fs_npsect) + +/* + * The following macros optimize certain frequently calculated + * quantities by using shifts and masks in place of divisions + * modulos and multiplications. + */ +#define blkoff(fs, loc) /* calculates (loc % fs->fs_bsize) */ \ + ((loc) & (fs)->fs_qbmask) +#define fragoff(fs, loc) /* calculates (loc % fs->fs_fsize) */ \ + ((loc) & (fs)->fs_qfmask) +#define lblktosize(fs, blk) /* calculates ((off_t)blk * fs->fs_bsize) */ \ + ((off_t)(blk) << (fs)->fs_bshift) +#define lblkno(fs, loc) /* calculates (loc / fs->fs_bsize) */ \ + ((loc) >> (fs)->fs_bshift) +#define numfrags(fs, loc) /* calculates (loc / fs->fs_fsize) */ \ + ((loc) >> (fs)->fs_fshift) +#define blkroundup(fs, size) /* calculates roundup(size, fs->fs_bsize) */ \ + (((size) + (fs)->fs_qbmask) & (fs)->fs_bmask) +#define fragroundup(fs, size) /* calculates roundup(size, fs->fs_fsize) */ \ + (((size) + (fs)->fs_qfmask) & (fs)->fs_fmask) +#define fragstoblks(fs, frags) /* calculates (frags / fs->fs_frag) */ \ + ((frags) >> (fs)->fs_fragshift) +#define blkstofrags(fs, blks) /* calculates (blks * fs->fs_frag) */ \ + ((blks) << (fs)->fs_fragshift) +#define fragnum(fs, fsb) /* calculates (fsb % fs->fs_frag) */ \ + ((fsb) & ((fs)->fs_frag - 1)) +#define blknum(fs, fsb) /* calculates rounddown(fsb, fs->fs_frag) */ \ + ((fsb) &~ ((fs)->fs_frag - 1)) + +/* + * Determine the number of available frags given a + * percentage to hold in reserve. + */ +#define freespace(fs, percentreserved) \ + (blkstofrags((fs), (fs)->fs_cstotal.cs_nbfree) + \ + (fs)->fs_cstotal.cs_nffree - ((fs)->fs_dsize * (percentreserved) / 100)) + +/* + * Determining the size of a file block in the file system. + */ +#define blksize(fs, ip, lbn) \ + (((lbn) >= NDADDR || DIP((ip), size) >= ((lbn) + 1) << (fs)->fs_bshift) \ + ? (u_int64_t)(fs)->fs_bsize \ + : (fragroundup(fs, blkoff(fs, DIP((ip), size))))) +#define dblksize(fs, dip, lbn) \ + (((lbn) >= NDADDR || (dip)->di_size >= ((lbn) + 1) << (fs)->fs_bshift) \ + ? (u_int64_t)(fs)->fs_bsize \ + : (fragroundup(fs, blkoff(fs, (dip)->di_size)))) + +#define sblksize(fs, size, lbn) \ + (((lbn) >= NDADDR || (size) >= ((lbn) + 1) << (fs)->fs_bshift) \ + ? (u_int64_t)(fs)->fs_bsize \ + : (fragroundup(fs, blkoff(fs, (size))))) + + +/* + * Number of disk sectors per block/fragment; assumes DEV_BSIZE byte + * sector size. + */ +#define NSPB(fs) ((fs)->fs_nspf << (fs)->fs_fragshift) +#define NSPF(fs) ((fs)->fs_nspf) + +/* Number of inodes per file system block (fs->fs_bsize) */ +#define INOPB(fs) ((fs)->fs_inopb) +/* Number of inodes per file system fragment (fs->fs_fsize) */ +#define INOPF(fs) ((fs)->fs_inopb >> (fs)->fs_fragshift) + +/* + * Number of indirects in a file system block. + */ +#define NINDIR(fs) ((fs)->fs_nindir) + +/* Maximum file size the kernel allows. + * Even though ffs can handle files up to 16TB, we do limit the max file + * to 2^31 pages to prevent overflow of a 32-bit unsigned int. The buffer + * cache has its own checks but a little added paranoia never hurts. + */ +#define FS_KERNMAXFILESIZE(pgsiz, fs) ((u_int64_t)0x80000000 * \ + MIN((pgsiz), (fs)->fs_bsize) - 1) + +extern const int inside[], around[]; +extern const u_char *fragtbl[]; \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ufs/mfs/mfs_extern.h b/lib/libc/include/generic-openbsd/ufs/mfs/mfs_extern.h new file mode 100644 index 000000000000..6ae7703437b1 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ufs/mfs/mfs_extern.h @@ -0,0 +1,63 @@ +/* $OpenBSD: mfs_extern.h,v 1.22 2021/10/02 08:51:41 semarie Exp $ */ +/* $NetBSD: mfs_extern.h,v 1.4 1996/02/09 22:31:27 christos Exp $ */ + +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)mfs_extern.h 8.2 (Berkeley) 6/16/94 + */ + +struct buf; +struct mount; +struct nameidata; +struct proc; +struct statfs; +struct ucred; +struct vnode; +struct vfsconf; +struct mbuf; +struct mfsnode; + +extern const struct vops mfs_vops; + +/* mfs_vfsops.c */ +int mfs_mount(struct mount *, const char *, void *, struct nameidata *, + struct proc *); +int mfs_start(struct mount *, int, struct proc *); +int mfs_init(struct vfsconf *); +int mfs_checkexp(struct mount *, struct mbuf *, int *, struct ucred **); + +/* mfs_vnops.c */ +int mfs_open(void *); +int mfs_ioctl(void *); +int mfs_strategy(void *); +void mfs_doio(struct mfsnode *, struct buf *); +int mfs_close(void *); +int mfs_inactive(void *); +int mfs_reclaim(void *); +int mfs_print(void *); \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ufs/mfs/mfsnode.h b/lib/libc/include/generic-openbsd/ufs/mfs/mfsnode.h new file mode 100644 index 000000000000..cf33fad913ec --- /dev/null +++ b/lib/libc/include/generic-openbsd/ufs/mfs/mfsnode.h @@ -0,0 +1,53 @@ +/* $OpenBSD: mfsnode.h,v 1.15 2016/11/07 00:26:33 guenther Exp $ */ +/* $NetBSD: mfsnode.h,v 1.3 1996/02/09 22:31:31 christos Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)mfsnode.h 8.2 (Berkeley) 8/11/93 + */ + +/* + * This structure defines the control data for the memory based file system. + */ + +struct mfsnode { + struct vnode *mfs_vnode; /* vnode associated with this mfsnode */ + struct bufq mfs_bufq; /* bufq for MFS I/O */ + caddr_t mfs_baseoff; /* base of file system in memory */ + long mfs_size; /* size of memory file system */ + pid_t mfs_tid; /* supporting thread's tid */ + struct buf *mfs_buflist; /* list of I/O requests */ + int mfs_shutdown; /* shutdown request */ +}; + +/* + * Convert between mfsnode pointers and vnode pointers + */ +#define VTOMFS(vp) ((struct mfsnode *)(vp)->v_data) +#define MFSTOV(mfsp) ((mfsp)->mfs_vnode) \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ufs/ufs/dinode.h b/lib/libc/include/generic-openbsd/ufs/ufs/dinode.h new file mode 100644 index 000000000000..bfb626a301f2 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ufs/ufs/dinode.h @@ -0,0 +1,156 @@ +/* $OpenBSD: dinode.h,v 1.19 2020/05/28 15:48:29 otto Exp $ */ +/* $NetBSD: dinode.h,v 1.7 1995/06/15 23:22:48 cgd Exp $ */ + +/* + * Copyright (c) 1982, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)dinode.h 8.9 (Berkeley) 3/29/95 + */ + +#ifndef _UFS_DINODE_H_ +#define _UFS_DINODE_H_ + +/* + * UFS directories use 32bit inode numbers internally, regardless + * of what the system on top of it uses. + */ +typedef u_int32_t ufsino_t; + +/* + * The root inode is the root of the file system. Inode 0 can't be used for + * normal purposes and historically bad blocks were linked to inode 1, thus + * the root inode is 2. (Inode 1 is no longer used for this purpose, however + * numerous dump tapes make this assumption, so we are stuck with it). + */ +#define ROOTINO ((ufsino_t)2) + +/* + * A dinode contains all the meta-data associated with a UFS file. + * This structure defines the on-disk format of a dinode. Since + * this structure describes an on-disk structure, all its fields + * are defined by types with precise widths. + */ +#define NXADDR 2 /* External addresses in inode */ +#define NDADDR 12 /* Direct addresses in inode. */ +#define NIADDR 3 /* Indirect addresses in inode. */ + +struct ufs1_dinode { + u_int16_t di_mode; /* 0: IFMT, permissions; see below. */ + int16_t di_nlink; /* 2: File link count. */ + union { + u_int16_t oldids[2]; /* 4: Ffs: old user and group ids. */ + u_int32_t inumber; /* 4: Lfs: inode number. */ + } di_u; + u_int64_t di_size; /* 8: File byte count. */ + int32_t di_atime; /* 16: Last access time. */ + int32_t di_atimensec; /* 20: Last access time. */ + int32_t di_mtime; /* 24: Last modified time. */ + int32_t di_mtimensec; /* 28: Last modified time. */ + int32_t di_ctime; /* 32: Last inode change time. */ + int32_t di_ctimensec; /* 36: Last inode change time. */ + int32_t di_db[NDADDR]; /* 40: Direct disk blocks. */ + int32_t di_ib[NIADDR]; /* 88: Indirect disk blocks. */ + u_int32_t di_flags; /* 100: Status flags (chflags). */ + int32_t di_blocks; /* 104: Blocks actually held. */ + u_int32_t di_gen; /* 108: Generation number. */ + u_int32_t di_uid; /* 112: File owner. */ + u_int32_t di_gid; /* 116: File group. */ + int32_t di_spare[2]; /* 120: Reserved; currently unused */ +}; + +struct ufs2_dinode { + u_int16_t di_mode; /* 0: IFMT, permissions; see below. */ + int16_t di_nlink; /* 2: File link count. */ + u_int32_t di_uid; /* 4: File owner. */ + u_int32_t di_gid; /* 8: File group. */ + u_int32_t di_blksize; /* 12: Inode blocksize. */ + u_int64_t di_size; /* 16: File byte count. */ + u_int64_t di_blocks; /* 24: Bytes actually held. */ + int64_t di_atime; /* 32: Last access time. */ + int64_t di_mtime; /* 40: Last modified time. */ + int64_t di_ctime; /* 48: Last inode change time. */ + int64_t di_birthtime; /* 56: Inode creation time. */ + int32_t di_mtimensec; /* 64: Last modified time. */ + int32_t di_atimensec; /* 68: Last access time. */ + int32_t di_ctimensec; /* 72: Last inode change time. */ + int32_t di_birthnsec; /* 76: Inode creation time. */ + int32_t di_gen; /* 80: Generation number. */ + u_int32_t di_kernflags; /* 84: Kernel flags. */ + u_int32_t di_flags; /* 88: Status flags (chflags). */ + int32_t di_extsize; /* 92: External attributes block. */ + int64_t di_extb[NXADDR];/* 96: External attributes block. */ + int64_t di_db[NDADDR]; /* 112: Direct disk blocks. */ + int64_t di_ib[NIADDR]; /* 208: Indirect disk blocks. */ + int64_t di_spare[3]; /* 232: Reserved; currently unused */ +}; + +/* + * The di_db fields may be overlaid with other information for + * file types that do not have associated disk storage. Block + * and character devices overlay the first data block with their + * dev_t value. Short symbolic links place their path in the + * di_db area. + */ +#define di_inumber di_u.inumber +#define di_ogid di_u.oldids[1] +#define di_ouid di_u.oldids[0] +#define di_rdev di_db[0] +#define di_shortlink di_db + +#define MAXSYMLINKLEN_UFS1 ((NDADDR + NIADDR) * sizeof(int32_t)) +#define MAXSYMLINKLEN_UFS2 ((NDADDR + NIADDR) * sizeof(int64_t)) + +#define MAXSYMLINKLEN(ip) \ + ((ip)->i_ump->um_fstype == UM_UFS1) ? \ + MAXSYMLINKLEN_UFS1 : MAXSYMLINKLEN_UFS2 + +/* File permissions. */ +#define IEXEC 0000100 /* Executable. */ +#define IWRITE 0000200 /* Writeable. */ +#define IREAD 0000400 /* Readable. */ +#define ISVTX 0001000 /* Sticky bit. */ +#define ISGID 0002000 /* Set-gid. */ +#define ISUID 0004000 /* Set-uid. */ + +/* File types. */ +#define IFMT 0170000 /* Mask of file type. */ +#define IFIFO 0010000 /* Named pipe (fifo). */ +#define IFCHR 0020000 /* Character device. */ +#define IFDIR 0040000 /* Directory file. */ +#define IFBLK 0060000 /* Block device. */ +#define IFREG 0100000 /* Regular file. */ +#define IFLNK 0120000 /* Symbolic link. */ +#define IFSOCK 0140000 /* UNIX domain socket. */ +#define IFWHT 0160000 /* Whiteout. */ + +#endif /* _UFS_DINODE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ufs/ufs/dir.h b/lib/libc/include/generic-openbsd/ufs/ufs/dir.h new file mode 100644 index 000000000000..8ce82cc0889b --- /dev/null +++ b/lib/libc/include/generic-openbsd/ufs/ufs/dir.h @@ -0,0 +1,134 @@ +/* $OpenBSD: dir.h,v 1.13 2024/01/09 03:15:59 guenther Exp $ */ +/* $NetBSD: dir.h,v 1.8 1996/03/09 19:42:41 scottr Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)dir.h 8.4 (Berkeley) 8/10/94 + */ + +#ifndef _DIR_H_ +#define _DIR_H_ + +/* + * Theoretically, directories can be more than 2Gb in length, however, in + * practice this seems unlikely. So, we define the type doff_t as a 32-bit + * quantity to keep down the cost of doing lookup on a 32-bit machine. + */ +#define doff_t int32_t +#define MAXDIRSIZE (0x7fffffff) + +/* + * A directory consists of some number of blocks of DIRBLKSIZ + * bytes, where DIRBLKSIZ is chosen such that it can be transferred + * to disk in a single atomic operation (e.g. 512 bytes on most machines). + * + * Each DIRBLKSIZ byte block contains some number of directory entry + * structures, which are of variable length. Each directory entry has + * a struct direct at the front of it, containing its inode number, + * the length of the entry, and the length of the name contained in + * the entry. These are followed by the name padded to a 4 byte boundary + * with null bytes. All names are guaranteed null terminated. + * The maximum length of a name in a directory is MAXNAMLEN. + * + * The macro DIRSIZ(dp) gives the amount of space required to represent + * a directory entry. Free space in a directory is represented by + * entries which have dp->d_reclen > DIRSIZ(dp). All DIRBLKSIZ bytes + * in a directory block are claimed by the directory entries. This + * usually results in the last entry in a directory having a large + * dp->d_reclen. When entries are deleted from a directory, the + * space is returned to the previous entry in the same directory + * block by increasing its dp->d_reclen. If the first entry of + * a directory block is free, then its dp->d_ino is set to 0. + * Entries other than the first in a directory do not normally have + * dp->d_ino set to 0. + */ +#define DIRBLKSIZ DEV_BSIZE +#define MAXNAMLEN 255 + +struct direct { + u_int32_t d_ino; /* inode number of entry */ + u_int16_t d_reclen; /* length of this record */ + u_int8_t d_type; /* file type, see below */ + u_int8_t d_namlen; /* length of string in d_name */ + char d_name[MAXNAMLEN + 1];/* name with length <= MAXNAMLEN */ +}; + +/* + * File types + */ +#define DT_UNKNOWN 0 +#define DT_FIFO 1 +#define DT_CHR 2 +#define DT_DIR 4 +#define DT_BLK 6 +#define DT_REG 8 +#define DT_LNK 10 +#define DT_SOCK 12 + +/* + * Convert between stat structure types and directory types. + */ +#define IFTODT(mode) (((mode) & 0170000) >> 12) +#define DTTOIF(dirtype) ((dirtype) << 12) + +/* + * The DIRSIZ macro gives the minimum record length which will hold + * the directory entry. This requires the amount of space in struct direct + * without the d_name field, plus enough space for the name with a terminating + * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. + */ +#define DIR_ROUNDUP 4 /* Directory name roundup size */ +#define DIRECTSIZ(namlen) \ + ((offsetof(struct direct, d_name) + \ + ((namlen)+1)*sizeof(((struct direct *)0)->d_name[0]) + 3) & ~3) +#define DIRSIZ(dp) \ + ((sizeof(struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) + +/* + * Template for manipulating directories. Should use struct direct's, + * but the name field is MAXNAMLEN - 1, and this just won't do. + */ +struct dirtemplate { + u_int32_t dot_ino; + int16_t dot_reclen; + u_int8_t dot_type; + u_int8_t dot_namlen; + char dot_name[4]; /* must be multiple of 4 */ + u_int32_t dotdot_ino; + int16_t dotdot_reclen; + u_int8_t dotdot_type; + u_int8_t dotdot_namlen; + char dotdot_name[4]; /* ditto */ +}; +#endif /* !_DIR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ufs/ufs/dirhash.h b/lib/libc/include/generic-openbsd/ufs/ufs/dirhash.h new file mode 100644 index 000000000000..642460480396 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ufs/ufs/dirhash.h @@ -0,0 +1,132 @@ +/* $OpenBSD: dirhash.h,v 1.9 2024/10/14 02:20:01 jsg Exp $ */ +/* + * Copyright (c) 2001 Ian Dowse. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/ufs/ufs/dirhash.h,v 1.4 2003/01/01 18:48:59 schweikh Exp $ + */ + +#ifndef _UFS_UFS_DIRHASH_H_ +#define _UFS_UFS_DIRHASH_H_ + +#include + +/* + * For fast operations on large directories, we maintain a hash + * that maps the file name to the offset of the directory entry within + * the directory file. + * + * The hashing uses a dumb spillover to the next free slot on + * collisions, so we must keep the utilisation low to avoid + * long linear searches. Deleted entries that are not the last + * in a chain must be marked DIRHASH_DEL. + * + * We also maintain information about free space in each block + * to speed up creations. + */ +#define DIRHASH_EMPTY (-1) /* entry unused */ +#define DIRHASH_DEL (-2) /* deleted entry; may be part of chain */ + +#define DIRALIGN 4 +#define DH_NFSTATS (DIRECTSIZ(MAXNAMLEN + 1) / DIRALIGN) + /* max DIRALIGN words in a directory entry */ + +/* + * Dirhash uses a score mechanism to achieve a hybrid between a + * least-recently-used and a least-often-used algorithm for entry + * recycling. The score is incremented when a directory is used, and + * decremented when the directory is a candidate for recycling. When + * the score reaches zero, the hash is recycled. Hashes are linked + * together on a TAILQ list, and hashes with higher scores filter + * towards the tail (most recently used) end of the list. + * + * New hash entries are given an initial score of DH_SCOREINIT and are + * placed at the most-recently-used end of the list. This helps a lot + * in the worst-case case scenario where every directory access is + * to a directory that is not hashed (i.e. the working set of hash + * candidates is much larger than the configured memory limit). In this + * case it limits the number of hash builds to 1/DH_SCOREINIT of the + * number of accesses. + */ +#define DH_SCOREINIT 8 /* initial dh_score when dirhash built */ +#define DH_SCOREMAX 64 /* max dh_score value */ + +/* + * The main hash table has 2 levels. It is an array of pointers to + * blocks of DH_NBLKOFF offsets. + */ +#define DH_BLKOFFSHIFT 8 +#define DH_NBLKOFF (1 << DH_BLKOFFSHIFT) +#define DH_BLKOFFMASK (DH_NBLKOFF - 1) + +#define DH_ENTRY(dh, slot) \ + ((dh)->dh_hash[(slot) >> DH_BLKOFFSHIFT][(slot) & DH_BLKOFFMASK]) + +struct dirhash { + struct rwlock dh_mtx; /* protects all fields except dh_list */ + doff_t **dh_hash; /* the hash array (2-level) */ + int dh_narrays; /* number of entries in dh_hash */ + int dh_hlen; /* total slots in the 2-level hash array */ + int dh_hused; /* entries in use */ + + /* Free space statistics. XXX assumes DIRBLKSIZ is 512. */ + u_int8_t *dh_blkfree; /* free DIRALIGN words in each dir block */ + int dh_nblk; /* size of dh_blkfree array */ + int dh_dirblks; /* number of DIRBLKSIZ blocks in dir */ + int dh_firstfree[DH_NFSTATS + 1]; /* first blk with N words free */ + + int dh_seqopt; /* sequential access optimisation enabled */ + doff_t dh_seqoff; /* sequential access optimisation offset */ + + int dh_score; /* access count for this dirhash */ + + int dh_onlist; /* true if on the ufsdirhash_list chain */ + + /* Protected by ufsdirhash_mtx. */ + TAILQ_ENTRY(dirhash) dh_list; /* chain of all dirhashes */ +}; + +extern int ufs_mindirhashsize; +extern int ufs_dirhashmaxmem; +extern int ufs_dirhashmem; + +/* + * Dirhash functions. + */ +void ufsdirhash_init(void); +void ufsdirhash_uninit(void); +int ufsdirhash_build(struct inode *); +doff_t ufsdirhash_findfree(struct inode *, int, int *); +doff_t ufsdirhash_enduseful(struct inode *); +int ufsdirhash_lookup(struct inode *, char *, int, doff_t *, struct buf **, + doff_t *); +void ufsdirhash_newblk(struct inode *, doff_t); +void ufsdirhash_add(struct inode *, struct direct *, doff_t); +void ufsdirhash_remove(struct inode *, struct direct *, doff_t); +void ufsdirhash_move(struct inode *, struct direct *, doff_t, doff_t); +void ufsdirhash_dirtrunc(struct inode *, doff_t); +void ufsdirhash_free(struct inode *); + +void ufsdirhash_checkblock(struct inode *, char *, doff_t); + +#endif /* !_UFS_UFS_DIRHASH_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ufs/ufs/inode.h b/lib/libc/include/generic-openbsd/ufs/ufs/inode.h new file mode 100644 index 000000000000..7d253d1b24f3 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ufs/ufs/inode.h @@ -0,0 +1,344 @@ +/* $OpenBSD: inode.h,v 1.54 2024/02/03 18:51:58 beck Exp $ */ +/* $NetBSD: inode.h,v 1.8 1995/06/15 23:22:50 cgd Exp $ */ + +/* + * Copyright (c) 1982, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)inode.h 8.5 (Berkeley) 7/8/94 + */ + +#include +#include +#include +#include +#include +#include + + +/* + * Per-filesystem inode extensions. + */ +struct ext2fs_inode_ext { + u_int32_t ext2fs_last_lblk; /* last logical blk allocated */ + u_int32_t ext2fs_last_blk; /* last blk allocated on disk */ + u_int32_t ext2fs_effective_uid; /* effective inode uid */ + u_int32_t ext2fs_effective_gid; /* effective inode gid */ + struct ext4_extent_cache ext2fs_extent_cache; +}; + +/* + * The inode is used to describe each active (or recently active) file in the + * UFS filesystem. It is composed of two types of information. The first part + * is the information that is needed only while the file is active (such as + * the identity of the file and linkage to speed its lookup). The second part + * is * the permanent meta-data associated with the file which is read in + * from the permanent dinode from long term storage when the file becomes + * active, and is put back when the file is no longer being used. + */ +struct inode { + LIST_ENTRY(inode) i_hash; /* Hash chain */ + struct vnode *i_vnode;/* Vnode associated with this inode. */ + struct ufsmount *i_ump; + u_int32_t i_flag; /* flags, see below */ + dev_t i_dev; /* Device associated with the inode. */ + ufsino_t i_number; /* The identity of the inode. */ + int i_effnlink; /* i_nlink when I/O completes */ + + union { /* Associated filesystem. */ + struct fs *fs; /* FFS */ + struct m_ext2fs *e2fs; /* EXT2FS */ + } inode_u; + +#define i_fs inode_u.fs +#define i_e2fs inode_u.e2fs + + struct cluster_info i_ci; + struct dquot *i_dquot[MAXQUOTAS]; /* Dquot structures. */ + u_quad_t i_modrev; /* Revision level for NFS lease. */ + struct lockf_state *i_lockf; /* Byte-level lock state. */ + struct rrwlock i_lock;/* Inode lock */ + + /* + * Side effects; used during directory lookup. + */ + int32_t i_count; /* Size of free slot in directory. */ + doff_t i_endoff; /* End of useful stuff in directory. */ + doff_t i_diroff; /* Offset in dir, where we found last entry. */ + doff_t i_offset; /* Offset of free space in directory. */ + ufsino_t i_ino; /* Inode number of found directory. */ + u_int32_t i_reclen; /* Size of found directory entry. */ + /* + * Inode extensions + */ + union { + /* Other extensions could go here... */ + struct ext2fs_inode_ext e2fs; + struct dirhash *dirhash; + } inode_ext; + +#define i_e2fs_last_lblk inode_ext.e2fs.ext2fs_last_lblk +#define i_e2fs_last_blk inode_ext.e2fs.ext2fs_last_blk +#define i_e2fs_uid inode_ext.e2fs.ext2fs_effective_uid +#define i_e2fs_gid inode_ext.e2fs.ext2fs_effective_gid +#define i_e2fs_ext_cache inode_ext.e2fs.ext2fs_extent_cache +#define i_dirhash inode_ext.dirhash + + /* + * The on-disk dinode itself. + */ + union { + struct ufs1_dinode *ffs1_din; + struct ufs2_dinode *ffs2_din; + struct ext2fs_dinode *e2fs_din; + } dinode_u; + +#define i_din1 dinode_u.ffs1_din +#define i_din2 dinode_u.ffs2_din +#define i_e2din dinode_u.e2fs_din + + struct inode_vtbl *i_vtbl; +}; + +struct inode_vtbl { + int (* iv_truncate)(struct inode *, off_t, int, + struct ucred *); + int (* iv_update)(struct inode *, int waitfor); + int (* iv_inode_alloc)(struct inode *, mode_t mode, + struct ucred *, struct vnode **); + int (* iv_inode_free)(struct inode *, ufsino_t ino, mode_t mode); + int (* iv_buf_alloc)(struct inode *, off_t, int, struct ucred *, + int, struct buf **); + int (* iv_bufatoff)(struct inode *, off_t offset, char **res, + struct buf **bpp); +}; + +#define UFS_TRUNCATE(ip, off, flags, cred) \ + ((ip)->i_vtbl->iv_truncate)((ip), (off), (flags), (cred)) + +#define UFS_UPDATE(ip, sync) \ + ((ip)->i_vtbl->iv_update)((ip), (sync)) + +#define UFS_INODE_ALLOC(pip, mode, cred, vpp) \ + ((pip)->i_vtbl->iv_inode_alloc)((pip), (mode), (cred), (vpp)) + +#define UFS_INODE_FREE(pip, ino, mode) \ + ((pip)->i_vtbl->iv_inode_free)((pip), (ino), (mode)) + +#define UFS_BUF_ALLOC(ip, startoffset, size, cred, flags, bpp) \ + ((ip)->i_vtbl->iv_buf_alloc)((ip), (startoffset), (size), (cred), \ + (flags), (bpp)) + +#define UFS_BUFATOFF(ip, offset, res, bpp) \ + ((ip)->i_vtbl->iv_bufatoff)((ip), (offset), (res), (bpp)) + +#define i_ffs1_atime i_din1->di_atime +#define i_ffs1_atimensec i_din1->di_atimensec +#define i_ffs1_blocks i_din1->di_blocks +#define i_ffs1_ctime i_din1->di_ctime +#define i_ffs1_ctimensec i_din1->di_ctimensec +#define i_ffs1_db i_din1->di_db +#define i_ffs1_flags i_din1->di_flags +#define i_ffs1_gen i_din1->di_gen +#define i_ffs1_gid i_din1->di_gid +#define i_ffs1_ib i_din1->di_ib +#define i_ffs1_mode i_din1->di_mode +#define i_ffs1_mtime i_din1->di_mtime +#define i_ffs1_mtimensec i_din1->di_mtimensec +#define i_ffs1_nlink i_din1->di_nlink +#define i_ffs1_rdev i_din1->di_rdev +#define i_ffs1_shortlink i_din1->di_shortlink +#define i_ffs1_size i_din1->di_size +#define i_ffs1_uid i_din1->di_uid + +#define i_ffs2_atime i_din2->di_atime +#define i_ffs2_atimensec i_din2->di_atimensec +#define i_ffs2_blocks i_din2->di_blocks +#define i_ffs2_blksize i_din2->di_blksize +#define i_ffs2_ctime i_din2->di_ctime +#define i_ffs2_ctimensec i_din2->di_ctimensec +#define i_ffs2_db i_din2->di_db +#define i_ffs2_flags i_din2->di_flags +#define i_ffs2_gen i_din2->di_gen +#define i_ffs2_gid i_din2->di_gid +#define i_ffs2_ib i_din2->di_ib +#define i_ffs2_mode i_din2->di_mode +#define i_ffs2_mtime i_din2->di_mtime +#define i_ffs2_mtimensec i_din2->di_mtimensec +#define i_ffs2_nlink i_din2->di_nlink +#define i_ffs2_rdev i_din2->di_rdev +#define i_ffs2_size i_din2->di_size +#define i_ffs2_uid i_din2->di_uid + +#ifndef _KERNEL +/* + * These are here purely for backwards compatibility for userland. + * They allow direct references to FFS structures using the old names. + */ +#define i_atime i_din1->di_atime +#define i_atimensec i_din1->di_atimensec +#define i_blocks i_din1->di_blocks +#define i_ctime i_din1->di_ctime +#define i_ctimensec i_din1->di_ctimensec +#define i_db i_din1->di_db +#define i_flags i_din1->di_flags +#define i_gen i_din1->di_gen +#define i_gid i_din1->di_gid +#define i_ib i_din1->di_ib +#define i_mode i_din1->di_mode +#define i_mtime i_din1->di_mtime +#define i_mtimensec i_din1->di_mtimensec +#define i_nlink i_din1->di_nlink +#define i_rdev i_din1->di_rdev +#define i_shortlink i_din1->di_shortlink +#define i_size i_din1->di_size +#define i_uid i_din1->di_uid +#endif /* _KERNEL */ + +#define i_e2fs_mode i_e2din->e2di_mode +#define i_e2fs_size i_e2din->e2di_size +#define i_e2fs_atime i_e2din->e2di_atime +#define i_e2fs_ctime i_e2din->e2di_ctime +#define i_e2fs_mtime i_e2din->e2di_mtime +#define i_e2fs_dtime i_e2din->e2di_dtime +#define i_e2fs_nlink i_e2din->e2di_nlink +#define i_e2fs_nblock i_e2din->e2di_nblock +#define i_e2fs_flags i_e2din->e2di_flags +#define i_e2fs_blocks i_e2din->e2di_blocks +#define i_e2fs_gen i_e2din->e2di_gen +#define i_e2fs_facl i_e2din->e2di_facl +#define i_e2fs_size_hi i_e2din->e2di_size_hi +#define i_e2fs_faddr i_e2din->e2di_faddr +#define i_e2fs_nblock_hi i_e2din->e2di_nblock_hi +#define i_e2fs_faddr_hi i_e2din->e2di_faddr_hi +#define i_e2fs_uid_low i_e2din->e2di_uid_low +#define i_e2fs_gid_low i_e2din->e2di_gid_low +#define i_e2fs_uid_high i_e2din->e2di_uid_high +#define i_e2fs_gid_high i_e2din->e2di_gid_high + +/* These flags are kept in i_flag. */ +#define IN_ACCESS 0x0001 /* Access time update request. */ +#define IN_CHANGE 0x0002 /* Inode change time update request. */ +#define IN_UPDATE 0x0004 /* Modification time update request */ +#define IN_MODIFIED 0x0008 /* Inode has been modified. */ +#define IN_RENAME 0x0010 /* Inode is being renamed. */ +#define IN_SHLOCK 0x0020 /* File has shared lock. */ +#define IN_EXLOCK 0x0040 /* File has exclusive lock. */ +#define IN_LAZYMOD 0x0080 /* Modified, but don't write yet. */ +#define IN_HASHED 0x0100 /* Inode is on the hash chain */ + +#define i_devvp i_ump->um_devvp + +#ifdef _KERNEL + +/* + * The DIP macros are used to access fields in the dinode. + */ + +#ifdef FFS2 +#define DIP(ip, field) \ + (((ip)->i_ump->um_fstype == UM_UFS1) ? \ + (ip)->i_ffs1_##field : (ip)->i_ffs2_##field) +#else +#define DIP(ip, field) \ + ((ip)->i_ffs1_##field) +#endif + +#ifdef FFS2 +#define DIP_OP(ip, field, op, value) \ + do { \ + if ((ip)->i_ump->um_fstype == UM_UFS1) \ + (ip)->i_ffs1_##field op (value); \ + else \ + (ip)->i_ffs2_##field op (value); \ + } while (0) +#else +#define DIP_OP(ip, field, op, value) \ + do { \ + (ip)->i_ffs1_##field op (value); \ + } while (0) +#endif + +#define DIP_ASSIGN(ip, field, value) DIP_OP(ip, field, =, value) +#define DIP_ADD(ip, field, value) DIP_OP(ip, field, +=, value) +#define DIP_AND(ip, field, value) DIP_OP(ip, field, &=, value) +#define DIP_OR(ip, field, value) DIP_OP(ip, field, |=, value) + +#ifdef FFS2 +#define SHORTLINK(ip) \ + (((ip)->i_ump->um_fstype == UM_UFS1) ? \ + (caddr_t)(ip)->i_ffs1_db : (caddr_t)(ip)->i_ffs2_db) +#else +#define SHORTLINK(ip) \ + ((caddr_t)(ip)->i_ffs1_db) +#endif + +/* + * Structure used to pass around logical block paths generated by + * ufs_getlbns and used by truncate and bmap code. + */ +struct indir { + daddr_t in_lbn; /* Logical block number. */ + int in_off; /* Offset in buffer. */ + int in_exists; /* Flag if the block exists. */ +}; + +/* Convert between inode pointers and vnode pointers. */ +#define VTOI(vp) ((struct inode *)(vp)->v_data) +#define ITOV(ip) ((ip)->i_vnode) + +#define EXT2FS_ITIMES(ip) do { \ + if ((ip)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) { \ + (ip)->i_flag |= IN_MODIFIED; \ + if ((ip)->i_flag & IN_ACCESS) \ + (ip)->i_e2fs_atime = gettime(); \ + if ((ip)->i_flag & IN_UPDATE) \ + (ip)->i_e2fs_mtime = gettime(); \ + if ((ip)->i_flag & IN_CHANGE) { \ + (ip)->i_e2fs_ctime = gettime(); \ + (ip)->i_modrev++; \ + } \ + (ip)->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE); \ + } \ +} while (0) + +/* Determine if soft dependencies are being done */ +#define DOINGASYNC(vp) ((vp)->v_mount->mnt_flag & MNT_ASYNC) + +/* This overlays the fid structure (see mount.h). */ +struct ufid { + u_int16_t ufid_len; /* Length of structure. */ + u_int16_t ufid_pad; /* Force 32-bit alignment. */ + ufsino_t ufid_ino; /* File number (ino). */ + u_int32_t ufid_gen; /* Generation number. */ +}; +#endif /* _KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ufs/ufs/quota.h b/lib/libc/include/generic-openbsd/ufs/ufs/quota.h new file mode 100644 index 000000000000..c00330a7732e --- /dev/null +++ b/lib/libc/include/generic-openbsd/ufs/ufs/quota.h @@ -0,0 +1,149 @@ +/* $OpenBSD: quota.h,v 1.12 2013/07/03 04:58:40 guenther Exp $ */ +/* $NetBSD: quota.h,v 1.6 1995/03/26 20:38:17 jtc Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Robert Elz at The University of Melbourne. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)quota.h 8.3 (Berkeley) 8/19/94 + */ + +#ifndef _QUOTA_ +#define _QUOTA_ + +/* + * Definitions for disk quotas imposed on the average user + * (big brother finally hits UNIX). + * + * The following constants define the amount of time given a user before the + * soft limits are treated as hard limits (usually resulting in an allocation + * failure). The timer is started when the user crosses their soft limit, it + * is reset when they go below their soft limit. + */ +#define MAX_IQ_TIME (7*24*60*60) /* seconds in 1 week */ +#define MAX_DQ_TIME (7*24*60*60) /* seconds in 1 week */ + +/* + * The following constants define the usage of the quota file array in the + * ufsmount structure and dquot array in the inode structure. The semantics + * of the elements of these arrays are defined in the routine getinoquota; + * the remainder of the quota code treats them generically and need not be + * inspected when changing the size of the array. + */ +#define MAXQUOTAS 2 +#define USRQUOTA 0 /* element used for user quotas */ +#define GRPQUOTA 1 /* element used for group quotas */ + +/* + * Definitions for the default names of the quotas files. + */ +#define INITQFNAMES { \ + "user", /* USRQUOTA */ \ + "group", /* GRPQUOTA */ \ + "undefined", \ +} +#define QUOTAFILENAME "quota" +#define QUOTAGROUP "operator" + +/* + * Command definitions for the 'quotactl' system call. The commands are + * broken into a main command defined below and a subcommand that is used + * to convey the type of quota that is being manipulated (see above). + */ +#define SUBCMDMASK 0x00ff +#define SUBCMDSHIFT 8 +#define QCMD(cmd, type) (((cmd) << SUBCMDSHIFT) | ((type) & SUBCMDMASK)) + +#define Q_QUOTAON 0x0100 /* enable quotas */ +#define Q_QUOTAOFF 0x0200 /* disable quotas */ +#define Q_GETQUOTA 0x0300 /* get limits and usage */ +#define Q_SETQUOTA 0x0400 /* set limits and usage */ +#define Q_SETUSE 0x0500 /* set usage */ +#define Q_SYNC 0x0600 /* sync disk copy of a filesystems quotas */ + +/* + * The following structure defines the format of the disk quota file + * (as it appears on disk) - the file is an array of these structures + * indexed by user or group number. The setquota system call establishes + * the vnode for each quota file (a pointer is retained in the ufsmount + * structure). + */ +struct dqblk { + u_int32_t dqb_bhardlimit; /* absolute limit on disk blks alloc */ + u_int32_t dqb_bsoftlimit; /* preferred limit on disk blks */ + u_int32_t dqb_curblocks; /* current block count */ + u_int32_t dqb_ihardlimit; /* maximum # allocated inodes + 1 */ + u_int32_t dqb_isoftlimit; /* preferred inode limit */ + u_int32_t dqb_curinodes; /* current # allocated inodes */ + /* XXX 2038 */ + u_int32_t dqb_btime; /* time limit for excessive disk use */ + u_int32_t dqb_itime; /* time limit for excessive files */ +}; + +#ifdef _KERNEL +/* + * Flags to ufs_quota_{alloc,free}_{blocks,inode}2 + */ +enum ufs_quota_flags { + UFS_QUOTA_NOUID = 0x1, /* Don't change UID quota */ + UFS_QUOTA_NOGID = 0x2, /* Don't change GID quota */ + UFS_QUOTA_FORCE = 0x1000 /* don't check limits - just change it */ +}; /* Change GID */ + +struct dquot; +struct inode; +struct mount; +struct proc; +struct ucred; +struct ufsmount; +struct vnode; +__BEGIN_DECLS +#define ufs_quota_alloc_blocks(i, c, cr) ufs_quota_alloc_blocks2(i, c, cr, 0) +#define ufs_quota_free_blocks(i, c, cr) ufs_quota_free_blocks2(i, c, cr, 0) +#define ufs_quota_alloc_inode(i, cr) ufs_quota_alloc_inode2(i, cr, 0) +#define ufs_quota_free_inode(i, cr) ufs_quota_free_inode2(i, cr, 0) +int ufs_quota_alloc_blocks2(struct inode *, daddr_t, struct ucred *, enum ufs_quota_flags); +int ufs_quota_free_blocks2(struct inode *, daddr_t, struct ucred *, enum ufs_quota_flags); +int ufs_quota_alloc_inode2(struct inode *, struct ucred *, enum ufs_quota_flags); +int ufs_quota_free_inode2(struct inode *, struct ucred *, enum ufs_quota_flags); + +int ufs_quota_delete(struct inode *); + +int getinoquota(struct inode *); +int quotaoff(struct proc *, struct mount *, int); +int qsync(struct mount *mp); +int ufs_quotactl(struct mount *, int, uid_t, caddr_t, struct proc *); + +void ufs_quota_init(void); + +__END_DECLS +#endif /* _KERNEL */ + +#endif /* _QUOTA_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ufs/ufs/ufs_extern.h b/lib/libc/include/generic-openbsd/ufs/ufs/ufs_extern.h new file mode 100644 index 000000000000..aba1b8846793 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ufs/ufs/ufs_extern.h @@ -0,0 +1,132 @@ +/* $OpenBSD: ufs_extern.h,v 1.41 2024/07/07 01:39:06 jsg Exp $ */ +/* $NetBSD: ufs_extern.h,v 1.5 1996/02/09 22:36:03 christos Exp $ */ + +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ufs_extern.h 8.6 (Berkeley) 8/10/94 + */ + +struct buf; +struct componentname; +struct direct; +struct disklabel; +struct dquot; +struct fid; +struct flock; +struct indir; +struct inode; +struct mbuf; +struct mount; +struct nameidata; +struct proc; +struct ucred; +struct ufs_args; +struct ufsmount; +struct uio; +struct vattr; +struct vfsconf; +struct vnode; + +int ufs_access(void *); +int ufs_advlock(void *); +int ufs_bmap(void *); +int ufs_close(void *); +int ufs_create(void *); +int ufs_getattr(void *); +int ufs_inactive(void *); +int ufs_ioctl(void *); +int ufs_islocked(void *); +int ufs_link(void *); +int ufs_lock(void *); +int ufs_lookup(void *); +int ufs_mkdir(void *); +int ufs_mknod(void *); +int ufs_open(void *); +int ufs_pathconf(void *); +int ufs_print(void *); +int ufs_readdir(void *); +int ufs_readlink(void *); +int ufs_remove(void *); +int ufs_rename(void *); +int ufs_rmdir(void *); +int ufs_kqfilter(void *); +int ufs_setattr(void *); +int ufs_strategy(void *); +int ufs_symlink(void *); +int ufs_unlock(void *); +int ufsspec_close(void *); +int ufsspec_read(void *); +int ufsspec_write(void *); + +#ifdef FIFO +int ufsfifo_read(void *); +int ufsfifo_write(void *); +int ufsfifo_close(void *); +#endif + +/* ufs_bmap.c */ +int ufs_bmaparray(struct vnode *, daddr_t, daddr_t *, struct indir *, + int *, int *); +int ufs_getlbns(struct vnode *, daddr_t, struct indir *, int *); + +/* ufs_ihash.c */ +void ufs_ihashinit(void); +struct vnode *ufs_ihashget(dev_t, ufsino_t); +int ufs_ihashins(struct inode *); +void ufs_ihashrem(struct inode *); + +/* ufs_inode.c */ +int ufs_init(struct vfsconf *); +int ufs_reclaim(struct vnode *); + +/* ufs_lookup.c */ +void ufs_dirbad(struct inode *, doff_t, char *); +int ufs_dirbadentry(struct vnode *, struct direct *, int); +void ufs_makedirentry(struct inode *, struct componentname *, + struct direct *); +int ufs_direnter(struct vnode *, struct vnode *, struct direct *, + struct componentname *, struct buf *); +int ufs_dirremove(struct vnode *, struct inode *, int, int); +int ufs_dirrewrite(struct inode *, struct inode *, + ufsino_t, int, int); +int ufs_dirempty(struct inode *, ufsino_t, struct ucred *); +int ufs_checkpath(struct inode *, struct inode *, struct ucred *); + +/* ufs_vfsops.c */ +int ufs_start(struct mount *, int, struct proc *); +int ufs_root(struct mount *, struct vnode **); +int ufs_quotactl(struct mount *, int, uid_t, caddr_t, struct proc *); +int ufs_fhtovp(struct mount *, struct ufid *, struct vnode **); +int ufs_check_export(struct mount *, struct mbuf *, int *, + struct ucred **); + +/* ufs_vnops.c */ +void ufs_itimes(struct vnode *); +int ufs_makeinode(int, struct vnode *, struct vnode **, + struct componentname *); \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/ufs/ufs/ufsmount.h b/lib/libc/include/generic-openbsd/ufs/ufs/ufsmount.h new file mode 100644 index 000000000000..47d82b8559f6 --- /dev/null +++ b/lib/libc/include/generic-openbsd/ufs/ufs/ufsmount.h @@ -0,0 +1,94 @@ +/* $OpenBSD: ufsmount.h,v 1.13 2016/02/27 18:50:38 natano Exp $ */ +/* $NetBSD: ufsmount.h,v 1.4 1994/12/21 20:00:23 mycroft Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ufsmount.h 8.4 (Berkeley) 10/27/94 + */ + +struct buf; +struct inode; +struct nameidata; +struct timeval; +struct ucred; +struct uio; +struct vnode; +struct netexport; + +/* This structure describes the UFS specific mount structure data. */ +struct ufsmount { + struct mount *um_mountp; /* filesystem vfs structure */ + dev_t um_dev; /* device mounted */ + struct vnode *um_devvp; /* block device mounted vnode */ + u_long um_fstype; /* type of file system */ + + union { /* pointer to superblock */ + struct fs *fs; /* FFS */ + struct m_ext2fs *e2fs; /* EXT2FS */ + } ufsmount_u; +#define um_fs ufsmount_u.fs +#define um_e2fs ufsmount_u.e2fs +#define um_e2fsb ufsmount_u.e2fs->s_es + + struct vnode *um_quotas[MAXQUOTAS]; /* pointer to quota files */ + struct ucred *um_cred[MAXQUOTAS]; /* quota file access cred */ + u_long um_nindir; /* indirect ptrs per block */ + u_long um_bptrtodb; /* indir ptr to disk block */ + u_long um_seqinc; /* inc between seq blocks */ + time_t um_btime[MAXQUOTAS]; /* block quota time limit */ + time_t um_itime[MAXQUOTAS]; /* inode quota time limit */ + char um_qflags[MAXQUOTAS]; /* quota specific flags */ + struct netexport um_export; /* export information */ + u_int64_t um_savedmaxfilesize; /* XXX - limit maxfilesize */ + u_int um_maxsymlinklen; /* max size of short symlink */ +}; + +/* + * Filesystem types + */ +#define UM_UFS1 1 +#define UM_UFS2 2 +#define UM_EXT2FS 3 + +/* + * Flags describing the state of quotas. + */ +#define QTF_OPENING 0x01 /* Q_QUOTAON in progress */ +#define QTF_CLOSING 0x02 /* Q_QUOTAOFF in progress */ + +/* Convert mount ptr to ufsmount ptr. */ +#define VFSTOUFS(mp) ((struct ufsmount *)((mp)->mnt_data)) + +/* + * Macros to access file system parameters in the ufsmount structure. + * Used by ufs_bmap. + */ +#define MNINDIR(ump) ((ump)->um_nindir) +#define blkptrtodb(ump, b) ((b) << (ump)->um_bptrtodb) +#define is_sequential(ump, a, b) ((b) == (a) + ump->um_seqinc) \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/unistd.h b/lib/libc/include/generic-openbsd/unistd.h new file mode 100644 index 000000000000..115e53fda23f --- /dev/null +++ b/lib/libc/include/generic-openbsd/unistd.h @@ -0,0 +1,541 @@ +/* $OpenBSD: unistd.h,v 1.112 2025/05/24 06:49:16 deraadt Exp $ */ +/* $NetBSD: unistd.h,v 1.26.4.1 1996/05/28 02:31:51 mrg Exp $ */ + +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)unistd.h 5.13 (Berkeley) 6/17/91 + */ + +#ifndef _UNISTD_H_ +#define _UNISTD_H_ + +#include +#include +#include + +#define STDIN_FILENO 0 /* standard input file descriptor */ +#define STDOUT_FILENO 1 /* standard output file descriptor */ +#define STDERR_FILENO 2 /* standard error file descriptor */ + +#if __XPG_VISIBLE || __POSIX_VISIBLE >= 200112 +#define F_ULOCK 0 /* unlock locked section */ +#define F_LOCK 1 /* lock a section for exclusive use */ +#define F_TLOCK 2 /* test and lock a section for exclusive use */ +#define F_TEST 3 /* test a section for locks by other procs */ +#endif + +/* + * POSIX options and option groups we unconditionally do or don't + * implement. Please keep this list in alphabetical order. + * + * Anything which is defined as zero below **must** have an + * implementation for the corresponding sysconf() which is able to + * determine conclusively whether or not the feature is supported. + * Anything which is defined as other than -1 below **must** have + * complete headers, types, and function declarations as specified by + * the POSIX standard; however, if the relevant sysconf() function + * returns -1, the functions may be stubbed out. + */ +#define _POSIX_ADVISORY_INFO (-1) +#define _POSIX_ASYNCHRONOUS_IO (-1) +#define _POSIX_BARRIERS 200112L +#define _POSIX_CHOWN_RESTRICTED 1 +#define _POSIX_CLOCK_SELECTION (-1) +#define _POSIX_CPUTIME 200809L +#define _POSIX_FSYNC 200112L +#define _POSIX_IPV6 0 +#define _POSIX_JOB_CONTROL 1 +#define _POSIX_MAPPED_FILES 200112L +#define _POSIX_MEMLOCK 200112L +#define _POSIX_MEMLOCK_RANGE 200112L +#define _POSIX_MEMORY_PROTECTION 200112L +#define _POSIX_MESSAGE_PASSING (-1) +#define _POSIX_MONOTONIC_CLOCK 200112L +#define _POSIX_NO_TRUNC 1 +#define _POSIX_PRIORITIZED_IO (-1) +#define _POSIX_PRIORITY_SCHEDULING (-1) +#define _POSIX_RAW_SOCKETS 200112L +#define _POSIX_READER_WRITER_LOCKS 200112L +#define _POSIX_REALTIME_SIGNALS (-1) +#define _POSIX_REGEXP 1 +#define _POSIX_SAVED_IDS 1 +#define _POSIX_SEMAPHORES 200112L +#define _POSIX_SHARED_MEMORY_OBJECTS 200809L +#define _POSIX_SHELL 1 +#define _POSIX_SPAWN 200112L +#define _POSIX_SPIN_LOCKS 200112L +#define _POSIX_SPORADIC_SERVER (-1) +#define _POSIX_SYNCHRONIZED_IO (-1) +#define _POSIX_THREAD_ATTR_STACKADDR 200112L +#define _POSIX_THREAD_ATTR_STACKSIZE 200112L +#define _POSIX_THREAD_CPUTIME 200809L +#define _POSIX_THREAD_PRIO_INHERIT (-1) +#define _POSIX_THREAD_PRIO_PROTECT (-1) +#define _POSIX_THREAD_PRIORITY_SCHEDULING (-1) +#define _POSIX_THREAD_PROCESS_SHARED (-1) +#define _POSIX_THREAD_ROBUST_PRIO_INHERIT (-1) +#define _POSIX_THREAD_ROBUST_PRIO_PROTECT (-1) +#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L +#define _POSIX_THREAD_SPORADIC_SERVER (-1) +#define _POSIX_THREADS 200112L +#define _POSIX_TIMEOUTS 200112L +#define _POSIX_TIMERS (-1) +#define _POSIX_TRACE (-1) +#define _POSIX_TRACE_EVENT_FILTER (-1) +#define _POSIX_TRACE_INHERIT (-1) +#define _POSIX_TRACE_LOG (-1) +#define _POSIX_TYPED_MEMORY_OBJECTS (-1) +#define _POSIX2_C_BIND 200112L +#define _POSIX2_C_DEV (-1) /* need C99 utility */ +#define _POSIX2_CHAR_TERM 1 +#define _POSIX2_FORT_DEV (-1) /* need fort77 utility */ +#define _POSIX2_FORT_RUN (-1) /* need asa utility */ +#define _POSIX2_LOCALEDEF (-1) +#define _POSIX2_PBS (-1) +#define _POSIX2_PBS_ACCOUNTING (-1) +#define _POSIX2_PBS_CHECKPOINT (-1) +#define _POSIX2_PBS_LOCATE (-1) +#define _POSIX2_PBS_MESSAGE (-1) +#define _POSIX2_PBS_TRACK (-1) +#define _POSIX2_SW_DEV 200112L +#define _POSIX2_UPE 200112L +#define _POSIX_V6_ILP32_OFF32 (-1) +#define _POSIX_V6_ILP32_OFFBIG 0 +#define _POSIX_V6_LP64_OFF64 0 +#define _POSIX_V6_LPBIG_OFFBIG 0 +#define _POSIX_V7_ILP32_OFF32 (-1) +#define _POSIX_V7_ILP32_OFFBIG 0 +#define _POSIX_V7_LP64_OFF64 0 +#define _POSIX_V7_LPBIG_OFFBIG 0 + +#define _XOPEN_CRYPT 1 +#define _XOPEN_ENH_I18N (-1) /* mandatory in XSI */ +#define _XOPEN_LEGACY (-1) +#define _XOPEN_REALTIME (-1) +#define _XOPEN_REALTIME_THREADS (-1) +#define _XOPEN_SHM 1 +#define _XOPEN_STREAMS (-1) +#define _XOPEN_UUCP (-1) +#define _XOPEN_UNIX (-1) + +/* Define the POSIX.2 version we target for compliance. */ +#define _POSIX2_VERSION 200809L + +/* the sysconf(3) variable values are part of the ABI */ + +/* configurable system variables */ +#define _SC_ARG_MAX 1 +#define _SC_CHILD_MAX 2 +#define _SC_CLK_TCK 3 +#define _SC_NGROUPS_MAX 4 +#define _SC_OPEN_MAX 5 +#define _SC_JOB_CONTROL 6 +#define _SC_SAVED_IDS 7 +#define _SC_VERSION 8 +#define _SC_BC_BASE_MAX 9 +#define _SC_BC_DIM_MAX 10 +#define _SC_BC_SCALE_MAX 11 +#define _SC_BC_STRING_MAX 12 +#define _SC_COLL_WEIGHTS_MAX 13 +#define _SC_EXPR_NEST_MAX 14 +#define _SC_LINE_MAX 15 +#define _SC_RE_DUP_MAX 16 +#define _SC_2_VERSION 17 +#define _SC_2_C_BIND 18 +#define _SC_2_C_DEV 19 +#define _SC_2_CHAR_TERM 20 +#define _SC_2_FORT_DEV 21 +#define _SC_2_FORT_RUN 22 +#define _SC_2_LOCALEDEF 23 +#define _SC_2_SW_DEV 24 +#define _SC_2_UPE 25 +#define _SC_STREAM_MAX 26 +#define _SC_TZNAME_MAX 27 +#define _SC_PAGESIZE 28 +#define _SC_PAGE_SIZE _SC_PAGESIZE /* 1170 compatibility */ +#define _SC_FSYNC 29 +#define _SC_XOPEN_SHM 30 +#define _SC_SEM_NSEMS_MAX 31 +#define _SC_SEM_VALUE_MAX 32 +#define _SC_HOST_NAME_MAX 33 +#define _SC_MONOTONIC_CLOCK 34 +#define _SC_2_PBS 35 +#define _SC_2_PBS_ACCOUNTING 36 +#define _SC_2_PBS_CHECKPOINT 37 +#define _SC_2_PBS_LOCATE 38 +#define _SC_2_PBS_MESSAGE 39 +#define _SC_2_PBS_TRACK 40 +#define _SC_ADVISORY_INFO 41 +#define _SC_AIO_LISTIO_MAX 42 +#define _SC_AIO_MAX 43 +#define _SC_AIO_PRIO_DELTA_MAX 44 +#define _SC_ASYNCHRONOUS_IO 45 +#define _SC_ATEXIT_MAX 46 +#define _SC_BARRIERS 47 +#define _SC_CLOCK_SELECTION 48 +#define _SC_CPUTIME 49 +#define _SC_DELAYTIMER_MAX 50 +#define _SC_IOV_MAX 51 +#define _SC_IPV6 52 +#define _SC_MAPPED_FILES 53 +#define _SC_MEMLOCK 54 +#define _SC_MEMLOCK_RANGE 55 +#define _SC_MEMORY_PROTECTION 56 +#define _SC_MESSAGE_PASSING 57 +#define _SC_MQ_OPEN_MAX 58 +#define _SC_MQ_PRIO_MAX 59 +#define _SC_PRIORITIZED_IO 60 +#define _SC_PRIORITY_SCHEDULING 61 +#define _SC_RAW_SOCKETS 62 +#define _SC_READER_WRITER_LOCKS 63 +#define _SC_REALTIME_SIGNALS 64 +#define _SC_REGEXP 65 +#define _SC_RTSIG_MAX 66 +#define _SC_SEMAPHORES 67 +#define _SC_SHARED_MEMORY_OBJECTS 68 +#define _SC_SHELL 69 +#define _SC_SIGQUEUE_MAX 70 +#define _SC_SPAWN 71 +#define _SC_SPIN_LOCKS 72 +#define _SC_SPORADIC_SERVER 73 +#define _SC_SS_REPL_MAX 74 +#define _SC_SYNCHRONIZED_IO 75 +#define _SC_SYMLOOP_MAX 76 +#define _SC_THREAD_ATTR_STACKADDR 77 +#define _SC_THREAD_ATTR_STACKSIZE 78 +#define _SC_THREAD_CPUTIME 79 +#define _SC_THREAD_DESTRUCTOR_ITERATIONS 80 +#define _SC_THREAD_KEYS_MAX 81 +#define _SC_THREAD_PRIO_INHERIT 82 +#define _SC_THREAD_PRIO_PROTECT 83 +#define _SC_THREAD_PRIORITY_SCHEDULING 84 +#define _SC_THREAD_PROCESS_SHARED 85 +#define _SC_THREAD_ROBUST_PRIO_INHERIT 86 +#define _SC_THREAD_ROBUST_PRIO_PROTECT 87 +#define _SC_THREAD_SPORADIC_SERVER 88 +#define _SC_THREAD_STACK_MIN 89 +#define _SC_THREAD_THREADS_MAX 90 +#define _SC_THREADS 91 +#define _SC_TIMEOUTS 92 +#define _SC_TIMER_MAX 93 +#define _SC_TIMERS 94 +#define _SC_TRACE 95 +#define _SC_TRACE_EVENT_FILTER 96 +#define _SC_TRACE_EVENT_NAME_MAX 97 +#define _SC_TRACE_INHERIT 98 +#define _SC_TRACE_LOG 99 +#define _SC_GETGR_R_SIZE_MAX 100 +#define _SC_GETPW_R_SIZE_MAX 101 +#define _SC_LOGIN_NAME_MAX 102 +#define _SC_THREAD_SAFE_FUNCTIONS 103 +#define _SC_TRACE_NAME_MAX 104 +#define _SC_TRACE_SYS_MAX 105 +#define _SC_TRACE_USER_EVENT_MAX 106 +#define _SC_TTY_NAME_MAX 107 +#define _SC_TYPED_MEMORY_OBJECTS 108 +#define _SC_V6_ILP32_OFF32 109 +#define _SC_V6_ILP32_OFFBIG 110 +#define _SC_V6_LP64_OFF64 111 +#define _SC_V6_LPBIG_OFFBIG 112 +#define _SC_V7_ILP32_OFF32 113 +#define _SC_V7_ILP32_OFFBIG 114 +#define _SC_V7_LP64_OFF64 115 +#define _SC_V7_LPBIG_OFFBIG 116 +#define _SC_XOPEN_CRYPT 117 +#define _SC_XOPEN_ENH_I18N 118 +#define _SC_XOPEN_LEGACY 119 +#define _SC_XOPEN_REALTIME 120 +#define _SC_XOPEN_REALTIME_THREADS 121 +#define _SC_XOPEN_STREAMS 122 +#define _SC_XOPEN_UNIX 123 +#define _SC_XOPEN_UUCP 124 +#define _SC_XOPEN_VERSION 125 + +#define _SC_PHYS_PAGES 500 +#define _SC_AVPHYS_PAGES 501 +#define _SC_NPROCESSORS_CONF 502 +#define _SC_NPROCESSORS_ONLN 503 + +/* configurable system strings */ +#define _CS_PATH 1 +#define _CS_POSIX_V6_ILP32_OFF32_CFLAGS 2 +#define _CS_POSIX_V6_ILP32_OFF32_LDFLAGS 3 +#define _CS_POSIX_V6_ILP32_OFF32_LIBS 4 +#define _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS 5 +#define _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS 6 +#define _CS_POSIX_V6_ILP32_OFFBIG_LIBS 7 +#define _CS_POSIX_V6_LP64_OFF64_CFLAGS 8 +#define _CS_POSIX_V6_LP64_OFF64_LDFLAGS 9 +#define _CS_POSIX_V6_LP64_OFF64_LIBS 10 +#define _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS 11 +#define _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS 12 +#define _CS_POSIX_V6_LPBIG_OFFBIG_LIBS 13 +#define _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS 14 +#define _CS_V6_ENV 15 +#define _CS_POSIX_V7_ILP32_OFF32_CFLAGS 16 +#define _CS_POSIX_V7_ILP32_OFF32_LDFLAGS 17 +#define _CS_POSIX_V7_ILP32_OFF32_LIBS 18 +#define _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS 19 +#define _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS 20 +#define _CS_POSIX_V7_ILP32_OFFBIG_LIBS 21 +#define _CS_POSIX_V7_LP64_OFF64_CFLAGS 22 +#define _CS_POSIX_V7_LP64_OFF64_LDFLAGS 23 +#define _CS_POSIX_V7_LP64_OFF64_LIBS 24 +#define _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS 25 +#define _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS 26 +#define _CS_POSIX_V7_LPBIG_OFFBIG_LIBS 27 +#define _CS_POSIX_V7_THREADS_CFLAGS 28 +#define _CS_POSIX_V7_THREADS_LDFLAGS 29 +#define _CS_POSIX_V7_WIDTH_RESTRICTED_ENVS 30 +#define _CS_V7_ENV 31 + +#ifndef _INTPTR_T_DEFINED_ +#define _INTPTR_T_DEFINED_ +typedef __intptr_t intptr_t; +#endif + +__BEGIN_DECLS +__dead void _exit(int); +int access(const char *, int); +unsigned int alarm(unsigned int); +int chdir(const char *); +int chown(const char *, uid_t, gid_t); +int close(int); +int dup(int); +int dup2(int, int); +int execl(const char *, const char *, ...) + __attribute__((__sentinel__)); +int execle(const char *, const char *, ...); +int execlp(const char *, const char *, ...) + __attribute__((__sentinel__)); +int execv(const char *, char *const *); +int execve(const char *, char *const *, char *const *); +int execvp(const char *, char *const *); +#if __BSD_VISIBLE +int execvpe(const char *, char *const *, char *const *); +#endif +pid_t fork(void); +long fpathconf(int, int); +char *getcwd(char *, size_t) + __attribute__((__bounded__(__string__,1,2))); +gid_t getegid(void); +uid_t geteuid(void); +gid_t getgid(void); +int getgroups(int, gid_t *); +char *getlogin(void); +pid_t getpgrp(void); +pid_t getpid(void); +pid_t getppid(void); +uid_t getuid(void); +int isatty(int); +int link(const char *, const char *); +off_t lseek(int, off_t, int); +long pathconf(const char *, int); +#if __BSD_VISIBLE +long pathconfat(int, const char *, int, int); +#endif +int pause(void); +int pipe(int *); +ssize_t read(int, void *, size_t) + __attribute__((__bounded__(__buffer__,2,3))); +int rmdir(const char *); +int setgid(gid_t); +int setuid(uid_t); +unsigned int sleep(unsigned int); +long sysconf(int); +pid_t tcgetpgrp(int); +int tcsetpgrp(int, pid_t); +char *ttyname(int); +int unlink(const char *); +ssize_t write(int, const void *, size_t) + __attribute__((__bounded__(__buffer__,2,3))); + +#if __POSIX_VISIBLE || __XPG_VISIBLE >= 300 +pid_t setsid(void); +int setpgid(pid_t, pid_t); +#endif + +#if __POSIX_VISIBLE >= 199209 || __XPG_VISIBLE +size_t confstr(int, char *, size_t) + __attribute__((__bounded__(__string__,2,3))); +#ifndef _GETOPT_DEFINED_ +#define _GETOPT_DEFINED_ +int getopt(int, char * const *, const char *); +extern char *optarg; /* getopt(3) external variables */ +extern int opterr, optind, optopt, optreset; +#endif /* _GETOPT_DEFINED_ */ +#endif + +#if __POSIX_VISIBLE >= 199506 || __XPG_VISIBLE +int fsync(int); +int ftruncate(int, off_t); +int getlogin_r(char *, size_t) + __attribute__((__bounded__(__string__,1,2))); +ssize_t readlink(const char * __restrict, char * __restrict, size_t) + __attribute__ ((__bounded__(__string__,2,3))); +#endif +#if __POSIX_VISIBLE >= 199506 +int fdatasync(int); +#endif + +#if __XPG_VISIBLE || __BSD_VISIBLE +char *crypt(const char *, const char *); +int fchdir(int); +int fchown(int, uid_t, gid_t); +long gethostid(void); +char *getwd(char *) + __attribute__ ((__bounded__(__minbytes__,1,1024))); +int lchown(const char *, uid_t, gid_t); +int mkstemp(char *); +char *mktemp(char *); +int nice(int); +int setregid(gid_t, gid_t); +int setreuid(uid_t, uid_t); +void swab(const void *__restrict, void *__restrict, ssize_t); +void sync(void); +int truncate(const char *, off_t); +useconds_t ualarm(useconds_t, useconds_t); +int usleep(useconds_t); +pid_t vfork(void); +#endif + +#if __POSIX_VISIBLE >= 200809 || __XPG_VISIBLE >= 420 +pid_t getpgid(pid_t); +pid_t getsid(pid_t); +#endif + +#if __XPG_VISIBLE >= 500 +ssize_t pread(int, void *, size_t, off_t) + __attribute__((__bounded__(__buffer__,2,3))); +ssize_t pwrite(int, const void *, size_t, off_t) + __attribute__((__bounded__(__buffer__,2,3))); +int ttyname_r(int, char *, size_t) + __attribute__((__bounded__(__string__,2,3))); +#endif + +#if __BSD_VISIBLE || __XPG_VISIBLE <= 500 +/* Interfaces withdrawn by X/Open Issue 5 Version 0 */ +int brk(void *); +int chroot(const char *); +int getdtablesize(void); +int getpagesize(void); +char *getpass(const char *); +void *sbrk(int); +#endif + +#if __POSIX_VISIBLE >= 200112 || __XPG_VISIBLE >= 420 +int lockf(int, int, off_t); +#endif + +#if __POSIX_VISIBLE >= 200112 || __XPG_VISIBLE >= 420 || __BSD_VISIBLE +int symlink(const char *, const char *); +int gethostname(char *, size_t) + __attribute__ ((__bounded__(__string__,1,2))); +int setegid(gid_t); +int seteuid(uid_t); +#endif + +#if __POSIX_VISIBLE >= 200809 +int faccessat(int, const char *, int, int); +int fchownat(int, const char *, uid_t, gid_t, int); +int linkat(int, const char *, int, const char *, int); +ssize_t readlinkat(int, const char *, char *, size_t) + __attribute__ ((__bounded__(__string__,3,4))); +int symlinkat(const char *, int, const char *); +int unlinkat(int, const char *, int); +#endif + +#if __POSIX_VISIBLE >= 202405 || __BSD_VISIBLE +int getentropy(void *, size_t); +#endif +#if __XPG_VISIBLE >= 800 || __BSD_VISIBLE +int getresgid(gid_t *, gid_t *, gid_t *); +int getresuid(uid_t *, uid_t *, uid_t *); +int setresgid(gid_t, gid_t, gid_t); +int setresuid(uid_t, uid_t, uid_t); +#endif + +#if __BSD_VISIBLE +int dup3(int, int, int); +int pipe2(int [2], int); +#endif + +#if __BSD_VISIBLE +int acct(const char *); +int closefrom(int); +int crypt_checkpass(const char *, const char *); +int crypt_newhash(const char *, const char *, char *, size_t); +void endusershell(void); +char *fflagstostr(u_int32_t); +int getdomainname(char *, size_t) + __attribute__ ((__bounded__(__string__,1,2))); +int getdtablecount(void); +int getgrouplist(const char *, gid_t, gid_t *, int *); +mode_t getmode(const void *, mode_t); +pid_t getthrid(void); +int getthrname(pid_t, char *, size_t); +char *getusershell(void); +int initgroups(const char *, gid_t); +int issetugid(void); +char *mkdtemp(char *); +int mkstemps(char *, int); +int nfssvc(int, void *); +int profil(void *, size_t, size_t, unsigned long, unsigned int, int) + __attribute__ ((__bounded__(__string__,1,2))); +int quotactl(const char *, int, int, char *); +int rcmd(char **, int, const char *, + const char *, const char *, int *); +int rcmd_af(char **, int, const char *, + const char *, const char *, int *, int); +int rcmdsh(char **, int, const char *, + const char *, const char *, char *); +int reboot(int); +int revoke(const char *); +int rresvport(int *); +int rresvport_af(int *, int); +int ruserok(const char *, int, const char *, const char *); +int setdomainname(const char *, size_t); +int setgroups(int, const gid_t *); +int sethostid(long); +int sethostname(const char *, size_t); +int setlogin(const char *); +void *setmode(const char *); +int setpgrp(pid_t _pid, pid_t _pgrp); /* BSD compat version */ +int setthrname(pid_t, const char *); +void setusershell(void); +int strtofflags(char **, u_int32_t *, u_int32_t *); +int swapctl(int cmd, const void *arg, int misc); +int pledge(const char *, const char *); +int unveil(const char *, const char *); +pid_t __tfork_thread(const struct __tfork *, size_t, void (*)(void *), + void *); +#endif /* __BSD_VISIBLE */ +__END_DECLS + +#endif /* !_UNISTD_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/usbhid.h b/lib/libc/include/generic-openbsd/usbhid.h new file mode 100644 index 000000000000..3fa9afccf091 --- /dev/null +++ b/lib/libc/include/generic-openbsd/usbhid.h @@ -0,0 +1,100 @@ +/* $OpenBSD: usbhid.h,v 1.9 2021/05/30 19:54:52 jcs Exp $ */ +/* $NetBSD: usbhid.h,v 1.1 2001/12/28 17:45:27 augustss Exp $ */ + +/* + * Copyright (c) 1999 Lennart Augustsson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +typedef struct report_desc *report_desc_t; + +typedef struct hid_data *hid_data_t; + +typedef enum hid_kind { + hid_input, hid_output, hid_feature, hid_collection, hid_endcollection +} hid_kind_t; + +typedef struct hid_item { + /* Global */ + uint32_t _usage_page; + int32_t logical_minimum; + int32_t logical_maximum; + int32_t physical_minimum; + int32_t physical_maximum; + int32_t unit_exponent; + int32_t unit; + int32_t report_size; + int32_t report_ID; +#define NO_REPORT_ID 0 + int32_t report_count; + /* Local */ + uint32_t usage; + int32_t usage_minimum; + int32_t usage_maximum; + int32_t designator_index; + int32_t designator_minimum; + int32_t designator_maximum; + int32_t string_index; + int32_t string_minimum; + int32_t string_maximum; + int32_t set_delimiter; + /* Misc */ + int32_t collection; + int collevel; + enum hid_kind kind; + uint32_t flags; + /* Location */ + uint32_t pos; + /* unused */ + struct hid_item *next; +} hid_item_t; + +#define HID_PAGE(u) (((u) >> 16) & 0xffff) +#define HID_USAGE(u) ((u) & 0xffff) + +/* Obtaining a report descriptor, descr.c: */ +report_desc_t hid_get_report_desc(int file); +report_desc_t hid_use_report_desc(unsigned char *data, unsigned int size); +void hid_dispose_report_desc(report_desc_t); +void hid_get_report_desc_data(report_desc_t, uint8_t **, uint32_t *); + +/* Parsing of a HID report descriptor, parse.c: */ +hid_data_t hid_start_parse(report_desc_t d, int kindset, int id); +void hid_end_parse(hid_data_t s); +int hid_get_item(hid_data_t s, hid_item_t *h); +int hid_report_size(report_desc_t d, enum hid_kind k, int id); +int hid_locate(report_desc_t d, unsigned int usage, enum hid_kind k, + hid_item_t *h, int id); + +/* Conversion to/from usage names, usage.c: */ +const char *hid_usage_page(int i); +const char *hid_usage_in_page(unsigned int u); +void hid_init(const char *file); +int hid_start(const char *file); +int hid_parse_usage_in_page(const char *name); +int hid_parse_usage_page(const char *name); + +/* Extracting/insertion of data, data.c: */ +int32_t hid_get_data(const void *p, const hid_item_t *h); +void hid_set_data(void *p, const hid_item_t *h, int32_t data); \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/util.h b/lib/libc/include/generic-openbsd/util.h new file mode 100644 index 000000000000..dc9305f58be0 --- /dev/null +++ b/lib/libc/include/generic-openbsd/util.h @@ -0,0 +1,129 @@ +/* $OpenBSD: util.h,v 1.38 2022/05/11 17:23:56 millert Exp $ */ +/* $NetBSD: util.h,v 1.2 1996/05/16 07:00:22 thorpej Exp $ */ + +/*- + * Copyright (c) 1995 + * The Regents of the University of California. All rights reserved. + * Portions Copyright (c) 1996, Jason Downs. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _UTIL_H_ +#define _UTIL_H_ + +#include + +/* + * fparseln() specific operation flags. + */ +#define FPARSELN_UNESCESC 0x01 +#define FPARSELN_UNESCCONT 0x02 +#define FPARSELN_UNESCCOMM 0x04 +#define FPARSELN_UNESCREST 0x08 +#define FPARSELN_UNESCALL 0x0f + +/* + * opendev() specific operation flags. + */ +#define OPENDEV_PART 0x01 /* Try to open the raw partition. */ +#define OPENDEV_BLCK 0x04 /* Open block, not character device. */ + +/* + * uu_lock(3) specific flags. + */ +#define UU_LOCK_INUSE (1) +#define UU_LOCK_OK (0) +#define UU_LOCK_OPEN_ERR (-1) +#define UU_LOCK_READ_ERR (-2) +#define UU_LOCK_CREAT_ERR (-3) +#define UU_LOCK_WRITE_ERR (-4) +#define UU_LOCK_LINK_ERR (-5) +#define UU_LOCK_TRY_ERR (-6) +#define UU_LOCK_OWNER_ERR (-7) + +/* + * fmt_scaled(3) specific flags. + */ +#define FMT_SCALED_STRSIZE 7 /* minus sign, 4 digits, suffix, null byte */ + +/* + * stub struct definitions. + */ +struct __sFILE; +struct login_cap; +struct passwd; +struct termios; +struct utmp; +struct winsize; + +__BEGIN_DECLS +char *fparseln(struct __sFILE *, size_t *, size_t *, const char[3], int); +void login(struct utmp *); +int login_tty(int); +int logout(const char *); +void logwtmp(const char *, const char *, const char *); +int opendev(const char *, int, int, char **); +int pidfile(const char *); +void pw_setdir(const char *); +char *pw_file(const char *); +int pw_lock(int); +int pw_mkdb(char *, int); +int pw_abort(void); +void pw_init(void); +void pw_edit(int, const char *); +void pw_prompt(void); +void pw_copy(int, int, const struct passwd *, const struct passwd *); +int pw_scan(char *, struct passwd *, int *); +__dead void pw_error(const char *, int, int); +int getptmfd(void); +int openpty(int *, int *, char *, const struct termios *, + const struct winsize *); +int fdopenpty(int, int *, int *, char *, const struct termios *, + const struct winsize *); +int opendisk(const char *, int, char *, size_t, int); +pid_t forkpty(int *, char *, const struct termios *, const struct winsize *); +pid_t fdforkpty(int, int *, char *, const struct termios *, + const struct winsize *); +int getmaxpartitions(void); +int getrawpartition(void); +void login_fbtab(const char *, uid_t, gid_t); +int login_check_expire(struct __sFILE *, struct passwd *, char *, int); +char *readlabelfs(char *, int); +const char *uu_lockerr(int); +int uu_lock(const char *); +int uu_lock_txfr(const char *, pid_t); +int uu_unlock(const char *); +int fmt_scaled(long long, char *); +int scan_scaled(char *, long long *); +int isduid(const char *, int); +int pkcs5_pbkdf2(const char *, size_t, const uint8_t *, size_t, + uint8_t *, size_t, unsigned int); +int bcrypt_pbkdf(const char *, size_t, const uint8_t *, size_t, + uint8_t *, size_t, unsigned int); + +__END_DECLS + +#endif /* !_UTIL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/utime.h b/lib/libc/include/generic-openbsd/utime.h new file mode 100644 index 000000000000..3132ff9bc1a0 --- /dev/null +++ b/lib/libc/include/generic-openbsd/utime.h @@ -0,0 +1,55 @@ +/* $OpenBSD: utime.h,v 1.7 2013/04/02 05:16:14 guenther Exp $ */ +/* $NetBSD: utime.h,v 1.3 1994/10/26 00:56:39 cgd Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)utime.h 5.4 (Berkeley) 4/3/91 + */ + +#ifndef _UTIME_H_ +#define _UTIME_H_ + +#include +#include + +#ifndef _TIME_T_DEFINED_ +#define _TIME_T_DEFINED_ +typedef __time_t time_t; +#endif + +struct utimbuf { + time_t actime; /* Access time */ + time_t modtime; /* Modification time */ +}; + +__BEGIN_DECLS +int utime(const char *, const struct utimbuf *); +__END_DECLS + +#endif /* !_UTIME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/utmp.h b/lib/libc/include/generic-openbsd/utmp.h new file mode 100644 index 000000000000..f4f6a761beaf --- /dev/null +++ b/lib/libc/include/generic-openbsd/utmp.h @@ -0,0 +1,69 @@ +/* $OpenBSD: utmp.h,v 1.6 2014/01/08 06:50:57 guenther Exp $ */ +/* $NetBSD: utmp.h,v 1.6 1994/10/26 00:56:40 cgd Exp $ */ + +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)utmp.h 8.2 (Berkeley) 1/21/94 + */ + +#ifndef _UTMP_H_ +#define _UTMP_H_ + +#define _PATH_UTMP "/var/run/utmp" +#define _PATH_WTMP "/var/log/wtmp" +#define _PATH_LASTLOG "/var/log/lastlog" + +#define UT_NAMESIZE 32 +#define UT_LINESIZE 8 +#define UT_HOSTSIZE 256 + +/* + * Note that these are *not* C strings and thus are not + * guaranteed to be NUL-terminated. + */ + +struct lastlog { + time_t ll_time; + char ll_line[UT_LINESIZE]; + char ll_host[UT_HOSTSIZE]; +}; + +struct utmp { + char ut_line[UT_LINESIZE]; + char ut_name[UT_NAMESIZE]; + char ut_host[UT_HOSTSIZE]; + time_t ut_time; +}; + +#endif /* !_UTMP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uuid.h b/lib/libc/include/generic-openbsd/uuid.h new file mode 100644 index 000000000000..e0e0152d050f --- /dev/null +++ b/lib/libc/include/generic-openbsd/uuid.h @@ -0,0 +1,69 @@ +/* $OpenBSD: uuid.h,v 1.1 2014/08/31 09:36:36 miod Exp $ */ +/* $NetBSD: uuid.h,v 1.2 2008/04/23 07:52:32 plunky Exp $ */ + +/* + * Copyright (c) 2002 Marcel Moolenaar + * Copyright (c) 2002 Hiten Mahesh Pandya + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/include/uuid.h,v 1.2 2002/11/05 10:55:16 jmallett Exp $ + */ + +#ifndef _UUID_H_ +#define _UUID_H_ + +#include +#include + +/* Status codes returned by the functions. */ +#define uuid_s_ok 0 +#define uuid_s_bad_version 1 +#define uuid_s_invalid_string_uuid 2 +#define uuid_s_no_memory 3 + +/* Length of a printed UUID. */ +#define UUID_BUF_LEN _UUID_BUF_LEN + +/* Length of a UUID. */ +#define UUID_STR_LEN 36 + +#include + +__BEGIN_DECLS +int32_t uuid_compare(const uuid_t *, const uuid_t *, uint32_t *); +void uuid_create(uuid_t *, uint32_t *); +void uuid_create_nil(uuid_t *, uint32_t *); +int32_t uuid_equal(const uuid_t *, const uuid_t *, uint32_t *); +void uuid_from_string(const char *, uuid_t *, uint32_t *); +uint16_t uuid_hash(const uuid_t *, uint32_t *); +int32_t uuid_is_nil(const uuid_t *, uint32_t *); +void uuid_to_string(const uuid_t *, char **, uint32_t *); + +void uuid_enc_le(void *, const uuid_t *); +void uuid_dec_le(const void *, uuid_t *); +void uuid_enc_be(void *, const uuid_t *); +void uuid_dec_be(const void *, uuid_t *); +__END_DECLS + +#endif /* _UUID_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uvm/uvm.h b/lib/libc/include/generic-openbsd/uvm/uvm.h new file mode 100644 index 000000000000..e66f26f12b0f --- /dev/null +++ b/lib/libc/include/generic-openbsd/uvm/uvm.h @@ -0,0 +1,143 @@ +/* $OpenBSD: uvm.h,v 1.73 2024/04/02 08:39:17 deraadt Exp $ */ +/* $NetBSD: uvm.h,v 1.24 2000/11/27 08:40:02 chs Exp $ */ + +/* + * Copyright (c) 1997 Charles D. Cranor and Washington University. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: Id: uvm.h,v 1.1.2.14 1998/02/02 20:07:19 chuck Exp + */ + +#ifndef _UVM_UVM_H_ +#define _UVM_UVM_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * uvm structure (vm global state: collected in one structure for ease + * of reference...) + * + * Locks used to protect struct members in this file: + * Q uvm.pageqlock + * F uvm.fpageqlock + */ +struct uvm { + /* vm_page related parameters */ + + /* vm_page queues */ + struct pglist page_active; /* [Q] allocated pages, in use */ + struct pglist page_inactive; /* [Q] pages inactive (reclaim/free) */ + /* Lock order: pageqlock, then fpageqlock. */ + struct mutex pageqlock; /* [] lock for active/inactive page q */ + struct mutex fpageqlock; /* [] lock for free page q + pdaemon */ + boolean_t page_init_done; /* TRUE if uvm_page_init() finished */ + struct uvm_pmr_control pmr_control; /* [F] pmemrange data */ + + /* page daemon trigger */ + int pagedaemon; /* daemon sleeps on this */ + struct proc *pagedaemon_proc; /* daemon's pid */ + + /* aiodone daemon trigger */ + int aiodoned; /* daemon sleeps on this */ + struct proc *aiodoned_proc; /* daemon's pid */ + struct mutex aiodoned_lock; + + /* static kernel map entry pool */ + SLIST_HEAD(, vm_map_entry) kentry_free; /* free page pool */ + + /* aio_done is locked by uvm.aiodoned_lock. */ + TAILQ_HEAD(, buf) aio_done; /* done async i/o reqs */ + + /* kernel object: to support anonymous pageable kernel memory */ + struct uvm_object *kernel_object; +}; + +/* + * vm_map_entry etype bits: + */ +#define UVM_ET_OBJ 0x0001 /* it is a uvm_object */ +#define UVM_ET_SUBMAP 0x0002 /* it is a vm_map submap */ +#define UVM_ET_COPYONWRITE 0x0004 /* copy_on_write */ +#define UVM_ET_NEEDSCOPY 0x0008 /* needs_copy */ +#define UVM_ET_HOLE 0x0010 /* no backend */ +#define UVM_ET_NOFAULT 0x0020 /* don't fault */ +#define UVM_ET_STACK 0x0040 /* this is a stack */ +#define UVM_ET_WC 0x0080 /* write combining */ +#define UVM_ET_CONCEAL 0x0100 /* omit from dumps */ +#define UVM_ET_IMMUTABLE 0x0400 /* entry may not be changed */ +#define UVM_ET_FREEMAPPED 0x8000 /* map entry is on free list (DEBUG) */ + +#define UVM_ET_ISOBJ(E) (((E)->etype & UVM_ET_OBJ) != 0) +#define UVM_ET_ISSUBMAP(E) (((E)->etype & UVM_ET_SUBMAP) != 0) +#define UVM_ET_ISCOPYONWRITE(E) (((E)->etype & UVM_ET_COPYONWRITE) != 0) +#define UVM_ET_ISNEEDSCOPY(E) (((E)->etype & UVM_ET_NEEDSCOPY) != 0) +#define UVM_ET_ISHOLE(E) (((E)->etype & UVM_ET_HOLE) != 0) +#define UVM_ET_ISNOFAULT(E) (((E)->etype & UVM_ET_NOFAULT) != 0) +#define UVM_ET_ISSTACK(E) (((E)->etype & UVM_ET_STACK) != 0) +#define UVM_ET_ISWC(E) (((E)->etype & UVM_ET_WC) != 0) +#define UVM_ET_ISCONCEAL(E) (((E)->etype & UVM_ET_CONCEAL) != 0) + +#ifdef _KERNEL + +/* + * holds all the internal UVM data + */ +extern struct uvm uvm; + +/* + * UVM_PAGE_OWN: track page ownership (only if UVM_PAGE_TRKOWN) + */ + +#if defined(UVM_PAGE_TRKOWN) +#define UVM_PAGE_OWN(PG, TAG) uvm_page_own(PG, TAG) +#else +#define UVM_PAGE_OWN(PG, TAG) /* nothing */ +#endif /* UVM_PAGE_TRKOWN */ + +/* + * uvm_map internal functions. + * Used by uvm_map address selectors. + */ +struct vm_map_entry *uvm_map_entrybyaddr(struct uvm_map_addr *, vaddr_t); +int uvm_map_isavail(struct vm_map *, + struct uvm_addr_state *, + struct vm_map_entry **, struct vm_map_entry**, + vaddr_t, vsize_t); +struct uvm_addr_state *uvm_map_uaddr(struct vm_map *, vaddr_t); +struct uvm_addr_state *uvm_map_uaddr_e(struct vm_map *, struct vm_map_entry *); + +#define VMMAP_FREE_START(_entry) ((_entry)->end + (_entry)->guard) +#define VMMAP_FREE_END(_entry) ((_entry)->end + (_entry)->guard + \ + (_entry)->fspace) + +#endif /* _KERNEL */ + +#endif /* _UVM_UVM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uvm/uvm_addr.h b/lib/libc/include/generic-openbsd/uvm/uvm_addr.h new file mode 100644 index 000000000000..c4191bed51c5 --- /dev/null +++ b/lib/libc/include/generic-openbsd/uvm/uvm_addr.h @@ -0,0 +1,115 @@ +/* $OpenBSD: uvm_addr.h,v 1.8 2024/07/04 04:52:10 jsg Exp $ */ + +/* + * Copyright (c) 2011 Ariane van der Steldt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _UVM_UVM_ADDR_H_ +#define _UVM_UVM_ADDR_H_ + +/* + * Address selection logic. + * + * Address selection is just that: selection. These functions may make no + * changes to the map, except for their own state (which is passed as a + * uaddr_state pointer). + */ + + +/* + * UVM address selection base state. + * + * Each uvm address algorithm requires these parameters: + * - lower bound address (page aligned) + * - upper bound address (page aligned) + * - function address pointers + */ +struct uvm_addr_state { + vaddr_t uaddr_minaddr; + vaddr_t uaddr_maxaddr; + const struct uvm_addr_functions *uaddr_functions; +}; + +/* + * This structure describes one algorithm implementation. + * + * Each algorithm is described in terms of: + * - uaddr_select: an address selection algorithm + * - uaddr_free_insert: a freelist insertion function (optional) + * - uaddr_free_remove: a freelist deletion function (optional) + * - uaddr_destroy: a destructor for the algorithm state + */ +struct uvm_addr_functions { + int (*uaddr_select)(struct vm_map *map, + struct uvm_addr_state *uaddr, + struct vm_map_entry **entry_out, vaddr_t *addr_out, + vsize_t sz, vaddr_t align, vaddr_t offset, + vm_prot_t prot, vaddr_t hint); + void (*uaddr_free_insert)(struct vm_map *map, + struct uvm_addr_state *uaddr_state, + struct vm_map_entry *entry); + void (*uaddr_free_remove)(struct vm_map *map, + struct uvm_addr_state *uaddr_state, + struct vm_map_entry *entry); + void (*uaddr_destroy)(struct uvm_addr_state *uaddr_state); + void (*uaddr_print)(struct uvm_addr_state *uaddr_state, boolean_t full, + int (*pr)(const char *, ...)); + + const char* uaddr_name; /* Name of the allocator. */ +}; + + +#ifdef _KERNEL + +void uvm_addr_init(void); +void uvm_addr_destroy(struct uvm_addr_state *); +int uvm_addr_linsearch(struct vm_map *, + struct uvm_addr_state *, struct vm_map_entry **, + vaddr_t *addr_out, vaddr_t, vsize_t, + vaddr_t, vaddr_t, int, vaddr_t, vaddr_t, + vsize_t, vsize_t); +int uvm_addr_invoke(struct vm_map *, + struct uvm_addr_state *, struct vm_map_entry **, + struct vm_map_entry **, vaddr_t*, + vsize_t, vaddr_t, vaddr_t, vm_prot_t, vaddr_t); +#if 0 +struct uvm_addr_state *uaddr_lin_create(vaddr_t, vaddr_t); +#endif +struct uvm_addr_state *uaddr_rnd_create(vaddr_t, vaddr_t); +#ifndef SMALL_KERNEL +struct uvm_addr_state *uaddr_bestfit_create(vaddr_t, vaddr_t); +struct uvm_addr_state *uaddr_pivot_create(vaddr_t, vaddr_t); +struct uvm_addr_state *uaddr_stack_brk_create(vaddr_t, vaddr_t); +#endif /* SMALL_KERNEL */ +int uvm_addr_fitspace(vaddr_t *, vaddr_t *, + vaddr_t, vaddr_t, vsize_t, vaddr_t, vaddr_t, + vsize_t, vsize_t); + +#if defined(DEBUG) || defined(DDB) +void uvm_addr_print(struct uvm_addr_state *, const char *, + boolean_t, int (*pr)(const char *, ...)); +#endif /* DEBUG || DDB */ + +/* + * Kernel bootstrap allocator. + */ +RBT_HEAD(uaddr_free_rbtree, vm_map_entry); +RBT_PROTOTYPE(uaddr_free_rbtree, vm_map_entry, dfree.rbtree, + uvm_mapent_fspace_cmp); + +extern struct uvm_addr_state uaddr_kbootstrap; + +#endif /* _KERNEL */ +#endif /* _UVM_UVM_ADDR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uvm/uvm_amap.h b/lib/libc/include/generic-openbsd/uvm/uvm_amap.h new file mode 100644 index 000000000000..bf8cb644f51e --- /dev/null +++ b/lib/libc/include/generic-openbsd/uvm/uvm_amap.h @@ -0,0 +1,265 @@ +/* $OpenBSD: uvm_amap.h,v 1.36 2025/05/25 01:52:00 gnezdo Exp $ */ +/* $NetBSD: uvm_amap.h,v 1.14 2001/02/18 21:19:08 chs Exp $ */ + +/* + * Copyright (c) 1997 Charles D. Cranor and Washington University. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _UVM_UVM_AMAP_H_ +#define _UVM_UVM_AMAP_H_ + +/* + * uvm_amap.h: general amap interface and amap implementation-specific info + */ + +/* + * an amap structure contains pointers to a set of anons that are + * mapped together in virtual memory (an anon is a single page of + * anonymous virtual memory -- see uvm_anon.h). in uvm we hide the + * details of the implementation of amaps behind a general amap + * interface. this allows us to change the amap implementation + * without having to touch the rest of the code. this file is divided + * into two parts: the definition of the uvm amap interface and the + * amap implementation-specific definitions. + */ + +#ifdef _KERNEL + +/* + * part 1: amap interface + */ + +/* + * forward definition of vm_amap structure. only amap + * implementation-specific code should directly access the fields of + * this structure. + */ + +struct vm_amap; + +/* + * prototypes for the amap interface + */ + + /* ensure amap can store anon */ +void amap_populate(struct vm_aref *, vaddr_t); + /* add an anon to an amap */ +int amap_add(struct vm_aref *, vaddr_t, struct vm_anon *, + boolean_t); + /* allocate a new amap */ +struct vm_amap *amap_alloc(vaddr_t, int, int); + /* clear amap needs-copy flag */ +void amap_copy(vm_map_t, vm_map_entry_t, int, boolean_t, vaddr_t, + vaddr_t); + /* resolve all COW faults now */ +void amap_cow_now(vm_map_t, vm_map_entry_t); + /* free amap */ +void amap_free(struct vm_amap *); + /* init amap module (at boot time) */ +void amap_init(void); + /* lookup an anon @ offset in amap */ +struct vm_anon *amap_lookup(struct vm_aref *, vaddr_t); + /* lookup multiple anons */ +void amap_lookups(struct vm_aref *, vaddr_t, struct vm_anon **, int); + /* add a reference to an amap */ +void amap_ref(struct vm_amap *, vaddr_t, vsize_t, int); + /* split reference to amap into two */ +void amap_splitref(struct vm_aref *, struct vm_aref *, vaddr_t); + /* remove an anon from an amap */ +void amap_unadd(struct vm_aref *, vaddr_t); + /* drop reference to an amap */ +void amap_unref(struct vm_amap *, vaddr_t, vsize_t, int); + /* remove all anons from amap */ +void amap_wipeout(struct vm_amap *); +boolean_t amap_swap_off(int, int); + +/* + * amap flag values + */ + +#define AMAP_SHARED 0x1 /* amap is shared */ +#define AMAP_REFALL 0x2 /* amap_ref: reference entire amap */ +#define AMAP_SWAPOFF 0x4 /* amap_swap_off() is in progress */ + +#endif /* _KERNEL */ + +/**********************************************************************/ + +/* + * part 2: amap implementation-specific info + */ + +/* + * we currently provide an array-based amap implementation. in this + * implementation we track split references so that we don't lose track of + * references during partial unmaps. + */ + +/* + * here is the definition of the vm_amap structure and helper structures for + * this implementation. + */ + +struct vm_amap_chunk { + TAILQ_ENTRY(vm_amap_chunk) ac_list; + int ac_baseslot; + uint16_t ac_usedmap; + uint16_t ac_nslot; + struct vm_anon *ac_anon[]; +}; + +struct vm_amap { + struct rwlock *am_lock; /* lock for all vm_amap flags */ + int am_ref; /* reference count */ + int am_flags; /* flags */ + int am_nslot; /* # of slots currently in map */ + int am_nused; /* # of slots currently in use */ + int *am_ppref; /* per page reference count (if !NULL) */ + LIST_ENTRY(vm_amap) am_list; + + union { + struct { + struct vm_amap_chunk **amn_buckets; + TAILQ_HEAD(, vm_amap_chunk) amn_chunks; + int amn_nbuckets; /* # of buckets */ + int amn_ncused; /* # of chunkers currently in use */ + int amn_hashshift; /* shift count to hash slot to bucket */ + } ami_normal; + + /* + * MUST be last element in vm_amap because it contains a + * variably sized array element. + */ + struct vm_amap_chunk ami_small; + } am_impl; + +#define am_buckets am_impl.ami_normal.amn_buckets +#define am_chunks am_impl.ami_normal.amn_chunks +#define am_nbuckets am_impl.ami_normal.amn_nbuckets +#define am_ncused am_impl.ami_normal.amn_ncused +#define am_hashshift am_impl.ami_normal.amn_hashshift + +#define am_small am_impl.ami_small +}; + +/* + * The entries in an amap are called slots. For example an amap that + * covers four pages is said to have four slots. + * + * The slots of an amap are clustered into chunks of UVM_AMAP_CHUNK + * slots each. The data structure of a chunk is vm_amap_chunk. + * Every chunk contains an array of pointers to vm_anon, and a bitmap + * is used to represent which of the slots are in use. + * + * Small amaps of up to UVM_AMAP_CHUNK slots have the chunk directly + * embedded in the amap structure. + * + * amaps with more slots are normal amaps and organize chunks in a hash + * table. The hash table is organized as an array of buckets. + * All chunks of the amap are additionally stored in a linked list. + * Chunks that belong to the same hash bucket are stored in the list + * consecutively. When all slots in a chunk are unused, the chunk is freed. + * + * For large amaps, the bucket array can grow large. See the description + * below how large bucket arrays are avoided. + */ + +/* + * defines for handling of large sparse amaps: + * + * one of the problems of array-based amaps is that if you allocate a + * large sparsely-used area of virtual memory you end up allocating + * large arrays that, for the most part, don't get used. this is a + * problem for BSD in that the kernel likes to make these types of + * allocations to "reserve" memory for possible future use. + * + * for example, the kernel allocates (reserves) a large chunk of user + * VM for possible stack growth. most of the time only a page or two + * of this VM is actually used. since the stack is anonymous memory + * it makes sense for it to live in an amap, but if we allocated an + * amap for the entire stack range we could end up wasting a large + * amount of malloc'd KVM. + * + * for example, on the i386 at boot time we allocate two amaps for the stack + * of /sbin/init: + * 1. a 7680 slot amap at protection PROT_NONE (reserve space for stack) + * 2. a 512 slot amap at protection PROT_READ|PROT_WRITE (top of stack) + * + * most of the array allocated for the amaps for this is never used. + * the amap interface provides a way for us to avoid this problem by + * allowing amap_copy() to break larger amaps up into smaller sized + * chunks (controlled by the "canchunk" option). we use this feature + * to reduce our memory usage with the BSD stack management. if we + * are asked to create an amap with more than UVM_AMAP_LARGE slots in it, + * we attempt to break it up into a UVM_AMAP_CHUNK sized amap if the + * "canchunk" flag is set. + * + * so, in the i386 example, the 7680 slot area is never referenced so + * nothing gets allocated (amap_copy is never called because the protection + * is zero). the 512 slot area for the top of the stack is referenced. + * the chunking code breaks it up into 16 slot chunks (hopefully a single + * 16 slot chunk is enough to handle the whole stack). + */ + +#define UVM_AMAP_LARGE 256 /* # of slots in "large" amap */ +#define UVM_AMAP_CHUNK 16 /* # of slots to chunk large amaps in */ + +#define UVM_AMAP_SMALL(amap) ((amap)->am_nslot <= UVM_AMAP_CHUNK) +#define UVM_AMAP_SLOTIDX(slot) ((slot) % UVM_AMAP_CHUNK) +#define UVM_AMAP_BUCKET(amap, slot) \ + (((slot) / UVM_AMAP_CHUNK) >> (amap)->am_hashshift) + +#ifdef _KERNEL + +/* + * macros + */ + +/* AMAP_B2SLOT: convert byte offset to slot */ +#define AMAP_B2SLOT(S,B) { \ + KASSERT(((B) & (PAGE_SIZE - 1)) == 0); \ + (S) = (B) >> PAGE_SHIFT; \ +} + +#define AMAP_CHUNK_FOREACH(chunk, amap) \ + for (chunk = (UVM_AMAP_SMALL(amap) ? \ + &(amap)->am_small : TAILQ_FIRST(&(amap)->am_chunks)); \ + (chunk) != NULL; (chunk) = TAILQ_NEXT(chunk, ac_list)) + +#define AMAP_BASE_SLOT(slot) \ + (((slot) / UVM_AMAP_CHUNK) * UVM_AMAP_CHUNK) + +/* + * flags macros + */ + +#define amap_flags(AMAP) ((AMAP)->am_flags) +#define amap_refs(AMAP) ((AMAP)->am_ref) + +#define amap_lock(AMAP, RWLT) rw_enter((AMAP)->am_lock, (RWLT)) +#define amap_unlock(AMAP) rw_exit((AMAP)->am_lock) + +#endif /* _KERNEL */ + +#endif /* _UVM_UVM_AMAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uvm/uvm_anon.h b/lib/libc/include/generic-openbsd/uvm/uvm_anon.h new file mode 100644 index 000000000000..a852f72d7244 --- /dev/null +++ b/lib/libc/include/generic-openbsd/uvm/uvm_anon.h @@ -0,0 +1,103 @@ +/* $OpenBSD: uvm_anon.h,v 1.23 2025/04/16 09:16:48 mpi Exp $ */ +/* $NetBSD: uvm_anon.h,v 1.13 2000/12/27 09:17:04 chs Exp $ */ + +/* + * Copyright (c) 1997 Charles D. Cranor and Washington University. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _UVM_UVM_ANON_H_ +#define _UVM_UVM_ANON_H_ + +/* + * anonymous memory management + * + * anonymous virtual memory is short term virtual memory that goes away + * when the processes referencing it go away. an anonymous page of + * virtual memory is described by the following data structure: + */ + +struct vm_anon { + struct rwlock *an_lock; + + struct vm_page *an_page; /* if in RAM */ + int an_ref; /* reference count */ + + /* + * Drum swap slot # (if != 0) [if we hold an_page, PG_BUSY] + */ + int an_swslot; + +#if defined(MULTIPROCESSOR) && defined(__LP64__) + /* + * The per-CPU pool caching code requires pool item to be + * at least the size of struct pool_cache_item. + */ + long unused; +#endif +}; + +/* + * for active vm_anon's the data can be in one of the following state: + * [1] in a vm_page with no backing store allocated yet, [2] in a vm_page + * with backing store allocated, or [3] paged out to backing store + * (no vm_page). + * + * for pageout in case [2]: if the page has been modified then we must + * flush it out to backing store, otherwise we can just dump the + * vm_page. + */ + +/* + * anons are grouped together in anonymous memory maps, or amaps. + * amaps are defined in uvm_amap.h. + */ + +/* + * processes reference anonymous virtual memory maps with an anonymous + * reference structure: + * Note that the offset field indicates which part of the amap we are + * referencing. + * Locked by vm_map lock. + */ + +struct vm_aref { + int ar_pageoff; /* page offset into amap we start */ + struct vm_amap *ar_amap; /* pointer to amap */ +}; + +#ifdef _KERNEL +struct vm_anon *uvm_analloc(void); +void uvm_anfree_list(struct vm_anon *, struct pglist *); +void uvm_anon_release(struct vm_anon *); +void uvm_anwait(void); +void uvm_anon_init(void); +void uvm_anon_init_percpu(void); +void uvm_anon_dropswap(struct vm_anon *); +boolean_t uvm_anon_pagein(struct vm_amap *, struct vm_anon *); + +#define uvm_anfree(an) uvm_anfree_list((an), NULL) + +#endif /* _KERNEL */ + +#endif /* _UVM_UVM_ANON_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uvm/uvm_aobj.h b/lib/libc/include/generic-openbsd/uvm/uvm_aobj.h new file mode 100644 index 000000000000..1fc48ca548bc --- /dev/null +++ b/lib/libc/include/generic-openbsd/uvm/uvm_aobj.h @@ -0,0 +1,77 @@ +/* $OpenBSD: uvm_aobj.h,v 1.20 2023/05/13 09:24:59 mpi Exp $ */ +/* $NetBSD: uvm_aobj.h,v 1.10 2000/01/11 06:57:49 chs Exp $ */ + +/* + * Copyright (c) 1998 Chuck Silvers, Charles D. Cranor and + * Washington University. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: Id: uvm_aobj.h,v 1.1.2.4 1998/02/06 05:19:28 chs Exp + */ +/* + * uvm_aobj.h: anonymous memory uvm_object pager + * + * author: Chuck Silvers + * started: Jan-1998 + * + * - design mostly from Chuck Cranor + */ + +#ifndef _UVM_UVM_AOBJ_H_ +#define _UVM_UVM_AOBJ_H_ + +/* + * flags + */ + +/* flags for uao_create: can only be used one time (at bootup) */ +#define UAO_FLAG_KERNOBJ 0x1 /* create kernel object */ +#define UAO_FLAG_KERNSWAP 0x2 /* enable kernel swap */ +#define UAO_FLAG_CANFAIL 0x4 /* creation can fail */ + +/* internal flags */ +#define UAO_FLAG_NOSWAP 0x8 /* aobj can't swap (kernel obj only!) */ + +#ifdef _KERNEL + +/* + * prototypes + */ + +void uao_init(void); +int uao_set_swslot(struct uvm_object *, int, int); +int uao_find_swslot(struct uvm_object *, int); +int uao_dropswap(struct uvm_object *, int); +int uao_swap_off(int, int); +int uao_shrink(struct uvm_object *, int); +int uao_grow(struct uvm_object *, int); + +/* + * globals + */ + +extern const struct uvm_pagerops aobj_pager; + +#endif /* _KERNEL */ + +#endif /* _UVM_UVM_AOBJ_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uvm/uvm_ddb.h b/lib/libc/include/generic-openbsd/uvm/uvm_ddb.h new file mode 100644 index 000000000000..e8b85f4ed8bf --- /dev/null +++ b/lib/libc/include/generic-openbsd/uvm/uvm_ddb.h @@ -0,0 +1,46 @@ +/* $OpenBSD: uvm_ddb.h,v 1.14 2015/02/05 23:51:06 mpi Exp $ */ +/* $NetBSD: uvm_ddb.h,v 1.5 2000/11/25 06:27:59 chs Exp $ */ + +/* + * Copyright (c) 1997 Charles D. Cranor and Washington University. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _UVM_UVM_DDB_H_ +#define _UVM_UVM_DDB_H_ + +#ifdef _KERNEL + +#ifdef DDB +void uvm_map_printit(vm_map_t, boolean_t, + int (*)(const char *, ...)); +void uvm_object_printit(struct uvm_object *, boolean_t, + int (*)(const char *, ...)); +void uvm_page_printit(struct vm_page *, boolean_t, + int (*)(const char *, ...)); +void uvmexp_print(int (*)(const char *, ...)); +#endif /* DDB */ + +#endif /* _KERNEL */ + +#endif /* _UVM_UVM_DDB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uvm/uvm_device.h b/lib/libc/include/generic-openbsd/uvm/uvm_device.h new file mode 100644 index 000000000000..677d411eed3a --- /dev/null +++ b/lib/libc/include/generic-openbsd/uvm/uvm_device.h @@ -0,0 +1,71 @@ +/* $OpenBSD: uvm_device.h,v 1.11 2014/07/11 16:35:40 jsg Exp $ */ +/* $NetBSD: uvm_device.h,v 1.9 2000/05/28 10:21:55 drochner Exp $ */ + +/* + * Copyright (c) 1997 Charles D. Cranor and Washington University. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: Id: uvm_device.h,v 1.1.2.2 1997/10/03 17:39:44 chuck Exp + */ + +#ifndef _UVM_UVM_DEVICE_H_ +#define _UVM_UVM_DEVICE_H_ + +/* + * uvm_device.h + * + * device handle into the VM system. + */ + +/* + * the uvm_device structure. object is put at the top of the data structure. + * this allows: + * (struct uvm_device *) == (struct uvm_object *) + */ + +struct uvm_device { + struct uvm_object u_obj; /* the actual VM object */ + int u_flags; /* flags [LOCKED BY UDV_LOCK!] */ + dev_t u_device; /* our device */ + LIST_ENTRY(uvm_device) u_list; /* list of device objects */ +}; + +/* + * u_flags values + */ + +#define UVM_DEVICE_HOLD 0x1 /* someone has a "hold" on it */ +#define UVM_DEVICE_WANTED 0x2 /* someone wants to put a "hold" on */ + +#ifdef _KERNEL + +/* + * prototypes + */ + +struct uvm_object *udv_attach(dev_t, vm_prot_t, voff_t, vsize_t); +struct uvm_object *udv_attach_drm(dev_t, vm_prot_t, voff_t, vsize_t); + +#endif /* _KERNEL */ + +#endif /* _UVM_UVM_DEVICE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uvm/uvm_extern.h b/lib/libc/include/generic-openbsd/uvm/uvm_extern.h new file mode 100644 index 000000000000..f3575f0bfc1d --- /dev/null +++ b/lib/libc/include/generic-openbsd/uvm/uvm_extern.h @@ -0,0 +1,456 @@ +/* $OpenBSD: uvm_extern.h,v 1.184 2025/06/03 08:38:17 mpi Exp $ */ +/* $NetBSD: uvm_extern.h,v 1.57 2001/03/09 01:02:12 chs Exp $ */ + +/* + * Copyright (c) 1997 Charles D. Cranor and Washington University. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1991, 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vm_extern.h 8.5 (Berkeley) 5/3/95 + */ + +#ifndef _UVM_UVM_EXTERN_H_ +#define _UVM_UVM_EXTERN_H_ + +typedef int vm_fault_t; + +typedef int vm_inherit_t; /* XXX: inheritance codes */ +typedef off_t voff_t; /* XXX: offset within a uvm_object */ + +struct vm_map_entry; +typedef struct vm_map_entry *vm_map_entry_t; + +struct vm_map; +typedef struct vm_map *vm_map_t; + +struct vm_page; +typedef struct vm_page *vm_page_t; + +/* + * Bit assignments assigned by UVM_MAPFLAG() and extracted by + * UVM_{PROTECTION,INHERIT,MAXPROTECTION,ADVICE}(): + * bits 0-2 protection + * bit 3 unused + * bits 4-5 inheritance + * bits 6-7 unused + * bits 8-10 max protection + * bit 11 unused + * bits 12-14 advice + * bit 15 unused + * bits 16-N flags + */ + +/* protections bits */ +#define PROT_MASK (PROT_READ | PROT_WRITE | PROT_EXEC) + +/* inherit codes */ +#define MAP_INHERIT_MASK 0x3 /* inherit mask */ + +typedef int vm_prot_t; + +#define MADV_MASK 0x7 /* mask */ + +/* mapping flags */ +#define UVM_FLAG_FIXED 0x0010000 /* find space */ +#define UVM_FLAG_OVERLAY 0x0020000 /* establish overlay */ +#define UVM_FLAG_NOMERGE 0x0040000 /* don't merge map entries */ +#define UVM_FLAG_COPYONW 0x0080000 /* set copy_on_write flag */ +#define UVM_FLAG_TRYLOCK 0x0100000 /* fail if we can not lock map */ +#define UVM_FLAG_HOLE 0x0200000 /* no backend */ +#define UVM_FLAG_QUERY 0x0400000 /* do everything, except actual execution */ +#define UVM_FLAG_NOFAULT 0x0800000 /* don't fault */ +#define UVM_FLAG_UNMAP 0x1000000 /* unmap to make space */ +#define UVM_FLAG_STACK 0x2000000 /* page may contain a stack */ +#define UVM_FLAG_WC 0x4000000 /* write combining */ +#define UVM_FLAG_CONCEAL 0x8000000 /* omit from dumps */ +#define UVM_FLAG_SIGALTSTACK 0x20000000 /* sigaltstack validation required */ + +/* macros to extract info */ +#define UVM_PROTECTION(X) ((X) & PROT_MASK) +#define UVM_INHERIT(X) (((X) >> 4) & MAP_INHERIT_MASK) +#define UVM_MAXPROTECTION(X) (((X) >> 8) & PROT_MASK) +#define UVM_ADVICE(X) (((X) >> 12) & MADV_MASK) + +#define UVM_MAPFLAG(prot, maxprot, inh, advice, flags) \ + ((prot) | ((maxprot) << 8) | ((inh) << 4) | ((advice) << 12) | (flags)) + +/* magic offset value */ +#define UVM_UNKNOWN_OFFSET ((voff_t) -1) + /* offset not known(obj) or don't care(!obj) */ + +/* + * the following defines are for uvm_km_kmemalloc's flags + */ +#define UVM_KMF_NOWAIT 0x1 /* matches M_NOWAIT */ +#define UVM_KMF_VALLOC 0x2 /* allocate VA only */ +#define UVM_KMF_CANFAIL 0x4 /* caller handles failure */ +#define UVM_KMF_ZERO 0x08 /* zero pages */ +#define UVM_KMF_TRYLOCK UVM_FLAG_TRYLOCK /* try locking only */ + +/* + * flags for uvm_pagealloc() + */ +#define UVM_PGA_USERESERVE 0x0001 /* ok to use reserve pages */ +#define UVM_PGA_ZERO 0x0002 /* returned page must be zeroed */ + +/* + * flags for uvm_pglistalloc() also used by uvm_pmr_getpages() + */ +#define UVM_PLA_WAITOK 0x0001 /* may sleep */ +#define UVM_PLA_NOWAIT 0x0002 /* can't sleep (need one of the two) */ +#define UVM_PLA_ZERO 0x0004 /* zero all pages before returning */ +#define UVM_PLA_TRYCONTIG 0x0008 /* try to allocate contig physmem */ +#define UVM_PLA_FAILOK 0x0010 /* caller can handle failure */ +#define UVM_PLA_NOWAKE 0x0020 /* don't wake page daemon on failure */ +#define UVM_PLA_USERESERVE 0x0040 /* can allocate from kernel reserve */ + +/* + * lockflags that control the locking behavior of various functions. + */ +#define UVM_LK_ENTER 0x00000001 /* map locked on entry */ +#define UVM_LK_EXIT 0x00000002 /* leave map locked on exit */ + +/* + * flags to uvm_page_physload. + */ +#define PHYSLOAD_DEVICE 0x01 /* don't add to the page queue */ + +#include +#include +#include + +#ifdef _KERNEL +struct buf; +struct pglist; +struct vmspace; +struct pmap; +#endif + +#include + +#include +#include +#include +#include + +#ifdef _KERNEL +#include +#include +#endif + +/* + * Shareable process virtual address space. + * May eventually be merged with vm_map. + * Several fields are temporary (text, data stuff). + * + * Locks used to protect struct members in this file: + * K kernel lock + * I immutable after creation + * a atomic operations + * v vm_map's lock + */ +struct vmspace { + struct vm_map vm_map; /* VM address map */ + int vm_refcnt; /* [a] number of references */ + caddr_t vm_shm; /* SYS5 shared memory private data XXX */ +/* we copy from vm_startcopy to the end of the structure on fork */ +#define vm_startcopy vm_rssize + segsz_t vm_rssize; /* current resident set size in pages */ + segsz_t vm_swrss; /* resident set size before last swap */ + segsz_t vm_tsize; /* text size (pages) XXX */ + segsz_t vm_dsize; /* data size (pages) XXX */ + segsz_t vm_dused; /* data segment length (pages) XXX */ + segsz_t vm_ssize; /* [v] stack size (pages) */ + caddr_t vm_taddr; /* [I] user virtual address of text */ + caddr_t vm_daddr; /* [I] user virtual address of data */ + caddr_t vm_maxsaddr; /* [I] user VA at max stack growth */ + caddr_t vm_minsaddr; /* [I] user VA at top of stack */ +}; + +/* + * uvm_constraint_range's: + * MD code is allowed to setup constraint ranges for memory allocators, the + * primary use for this is to keep allocation for certain memory consumers + * such as mbuf pools within address ranges that are reachable by devices + * that perform DMA. + * + * It is also to discourage memory allocations from being satisfied from ranges + * such as the ISA memory range, if they can be satisfied with allocation + * from other ranges. + * + * the MD ranges are defined in arch/ARCH/ARCH/machdep.c + */ +struct uvm_constraint_range { + paddr_t ucr_low; + paddr_t ucr_high; +}; + +#ifdef _KERNEL + +#include +extern struct uvmexp uvmexp; + +/* Constraint ranges, set by MD code. */ +extern struct uvm_constraint_range isa_constraint; +extern struct uvm_constraint_range dma_constraint; +extern struct uvm_constraint_range no_constraint; +extern struct uvm_constraint_range *uvm_md_constraints[]; + +/* + * the various kernel maps, owned by MD code + */ +extern struct vm_map *exec_map; +extern struct vm_map *kernel_map; +extern struct vm_map *kmem_map; +extern struct vm_map *phys_map; + +/* base of kernel virtual memory */ +extern vaddr_t vm_min_kernel_address; + +#define vm_resident_count(vm) (pmap_resident_count((vm)->vm_map.pmap)) + +struct plimit; + +void vmapbuf(struct buf *, vsize_t); +void vunmapbuf(struct buf *, vsize_t); +struct uvm_object *uao_create(vsize_t, int); +void uao_detach(struct uvm_object *); +void uao_reference(struct uvm_object *); +int uvm_fault(vm_map_t, vaddr_t, vm_fault_t, vm_prot_t); + +vaddr_t uvm_uarea_alloc(void); +void uvm_uarea_free(struct proc *); +void uvm_purge(void); +void uvm_exit(struct process *); +void uvm_init_limits(struct plimit *); +boolean_t uvm_kernacc(caddr_t, size_t, int); + +int uvm_vslock(struct proc *, caddr_t, size_t, + vm_prot_t); +void uvm_vsunlock(struct proc *, caddr_t, size_t); +int uvm_vslock_device(struct proc *, void *, size_t, + vm_prot_t, void **); +void uvm_vsunlock_device(struct proc *, void *, size_t, + void *); +void uvm_init(void); +void uvm_init_percpu(void); +int uvm_io(vm_map_t, struct uio *, int); + +#define UVM_IO_FIXPROT 0x01 + +void uvm_km_free(vm_map_t, vaddr_t, vsize_t); +vaddr_t uvm_km_kmemalloc_pla(struct vm_map *, + struct uvm_object *, vsize_t, vsize_t, int, + paddr_t, paddr_t, paddr_t, paddr_t, int); +#define uvm_km_kmemalloc(map, obj, sz, flags) \ + uvm_km_kmemalloc_pla(map, obj, sz, 0, flags, 0, (paddr_t)-1, 0, 0, 0) +struct vm_map *uvm_km_suballoc(vm_map_t, vaddr_t *, vaddr_t *, + vsize_t, int, boolean_t, vm_map_t); +/* + * Allocation mode for virtual space. + * + * kv_map - pointer to the pointer to the map we're allocating from. + * kv_align - alignment. + * kv_wait - wait for free space in the map if it's full. The default + * allocators don't wait since running out of space in kernel_map and + * kmem_map is usually fatal. Special maps like exec_map are specifically + * limited, so waiting for space in them is necessary. + * kv_singlepage - use the single page allocator. + * kv_executable - map the physical pages with PROT_EXEC. + */ +struct kmem_va_mode { + struct vm_map **kv_map; + vsize_t kv_align; + char kv_wait; + char kv_singlepage; +}; + +/* + * Allocation mode for physical pages. + * + * kp_constraint - allocation constraint for physical pages. + * kp_object - if the pages should be allocated from an object. + * kp_align - physical alignment of the first page in the allocation. + * kp_boundary - boundary that the physical addresses can't cross if + * the allocation is contiguous. + * kp_nomem - don't allocate any backing pages. + * kp_maxseg - maximal amount of contiguous segments. + * kp_zero - zero the returned memory. + * kp_pageable - allocate pageable memory. + */ +struct kmem_pa_mode { + struct uvm_constraint_range *kp_constraint; + struct uvm_object **kp_object; + paddr_t kp_align; + paddr_t kp_boundary; + int kp_maxseg; + char kp_nomem; + char kp_zero; + char kp_pageable; +}; + +/* + * Dynamic allocation parameters. Stuff that changes too often or too much + * to create separate va and pa modes for. + * + * kd_waitok - is it ok to sleep? + * kd_trylock - don't sleep on map locks. + * kd_prefer - offset to feed to PMAP_PREFER + * kd_slowdown - special parameter for the singlepage va allocator + * that tells the caller to sleep if possible to let the singlepage + * allocator catch up. + */ +struct kmem_dyn_mode { + voff_t kd_prefer; + int *kd_slowdown; + char kd_waitok; + char kd_trylock; +}; + +#define KMEM_DYN_INITIALIZER { UVM_UNKNOWN_OFFSET, NULL, 0, 0 } + +/* + * Notice that for kv_ waiting has a different meaning. It's only supposed + * to be used for very space constrained maps where waiting is a way + * to throttle some other operation. + * The exception is kv_page which needs to wait relatively often. + * All kv_ except kv_intrsafe will potentially sleep. + */ +extern const struct kmem_va_mode kv_any; +extern const struct kmem_va_mode kv_intrsafe; +extern const struct kmem_va_mode kv_page; + +extern const struct kmem_pa_mode kp_dirty; +extern const struct kmem_pa_mode kp_zero; +extern const struct kmem_pa_mode kp_dma; +extern const struct kmem_pa_mode kp_dma_contig; +extern const struct kmem_pa_mode kp_dma_zero; +extern const struct kmem_pa_mode kp_pageable; +extern const struct kmem_pa_mode kp_none; + +extern const struct kmem_dyn_mode kd_waitok; +extern const struct kmem_dyn_mode kd_nowait; +extern const struct kmem_dyn_mode kd_trylock; + +void *km_alloc(size_t, const struct kmem_va_mode *, + const struct kmem_pa_mode *, + const struct kmem_dyn_mode *); +void km_free(void *, size_t, const struct kmem_va_mode *, + const struct kmem_pa_mode *); +int uvm_map(vm_map_t, vaddr_t *, vsize_t, + struct uvm_object *, voff_t, vsize_t, unsigned int); +int uvm_mapanon(vm_map_t, vaddr_t *, vsize_t, vsize_t, unsigned int); +int uvm_map_pageable(vm_map_t, vaddr_t, + vaddr_t, boolean_t, int); +int uvm_map_pageable_all(vm_map_t, int, vsize_t); +boolean_t uvm_map_checkprot(vm_map_t, vaddr_t, + vaddr_t, vm_prot_t); +int uvm_map_protect(vm_map_t, vaddr_t, + vaddr_t, vm_prot_t, int etype, boolean_t, boolean_t); +struct vmspace *uvmspace_alloc(vaddr_t, vaddr_t, + boolean_t, boolean_t); +void uvmspace_init(struct vmspace *, struct pmap *, + vaddr_t, vaddr_t, boolean_t, boolean_t); +void uvmspace_exec(struct proc *, vaddr_t, vaddr_t); +struct vmspace *uvmspace_fork(struct process *); +void uvmspace_addref(struct vmspace *); +void uvmspace_purge(struct vmspace *); +void uvmspace_free(struct vmspace *); +struct vmspace *uvmspace_share(struct process *); +int uvm_sysctl(int *, u_int, void *, size_t *, + void *, size_t, struct proc *); +struct vm_page *uvm_pagealloc(struct uvm_object *, + voff_t, struct vm_anon *, int); +int uvm_pagealloc_multi(struct uvm_object *, voff_t, + vsize_t, int); +void uvm_pagerealloc(struct vm_page *, + struct uvm_object *, voff_t); +int uvm_pagerealloc_multi(struct uvm_object *, voff_t, + vsize_t, int, struct uvm_constraint_range *); +/* Actually, uvm_page_physload takes PF#s which need their own type */ +void uvm_page_physload(paddr_t, paddr_t, paddr_t, + paddr_t, int); +void uvm_setpagesize(void); +void uvm_shutdown(void); +void uvm_aio_biodone(struct buf *); +void uvm_aio_aiodone(struct buf *); +void uvm_pageout(void *); +void uvm_aiodone_daemon(void *); +void uvm_wait(const char *); +int uvm_pglistalloc(psize_t, paddr_t, paddr_t, + paddr_t, paddr_t, struct pglist *, int, int); +void uvm_pglistfree(struct pglist *); +void uvm_pmr_use_inc(paddr_t, paddr_t); +void uvm_swap_init(void); +typedef int uvm_coredump_setup_cb(int _nsegment, void *_cookie); +typedef int uvm_coredump_walk_cb(vaddr_t _start, vaddr_t _realend, + vaddr_t _end, vm_prot_t _prot, int _isvnode, + int _nsegment, void *_cookie); +int uvm_coredump_walkmap(struct proc *_p, + uvm_coredump_setup_cb *_setup, + uvm_coredump_walk_cb *_walk, void *_cookie); +void uvm_grow(struct proc *, vaddr_t); +void uvm_pagezero_thread(void *); +void kmeminit_nkmempages(void); +void kmeminit(void); +extern u_int nkmempages; + +struct vnode; +struct uvm_object *uvn_attach(struct vnode *, vm_prot_t); + +struct process; +struct kinfo_vmentry; +int fill_vmmap(struct process *, struct kinfo_vmentry *, + size_t *); + +#endif /* _KERNEL */ + +#endif /* _UVM_UVM_EXTERN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uvm/uvm_fault.h b/lib/libc/include/generic-openbsd/uvm/uvm_fault.h new file mode 100644 index 000000000000..c8fa50c66871 --- /dev/null +++ b/lib/libc/include/generic-openbsd/uvm/uvm_fault.h @@ -0,0 +1,83 @@ +/* $OpenBSD: uvm_fault.h,v 1.16 2020/11/06 11:52:39 mpi Exp $ */ +/* $NetBSD: uvm_fault.h,v 1.14 2000/06/26 14:21:17 mrg Exp $ */ + +/* + * Copyright (c) 1997 Charles D. Cranor and Washington University. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: Id: uvm_fault.h,v 1.1.2.2 1997/12/08 16:07:12 chuck Exp + */ + +#ifndef _UVM_UVM_FAULT_H_ +#define _UVM_UVM_FAULT_H_ + +/* + * fault types + */ + +#define VM_FAULT_INVALID ((vm_fault_t) 0x0) /* invalid mapping */ +#define VM_FAULT_PROTECT ((vm_fault_t) 0x1) /* protection */ +#define VM_FAULT_WIRE ((vm_fault_t) 0x2) /* wire mapping */ + +/* + * fault data structures + */ + +/* + * uvm_faultinfo: to load one of these fill in all orig_* fields and + * then call uvmfault_lookup on it. + */ + + +struct uvm_faultinfo { + vm_map_t orig_map; /* IN: original map */ + vaddr_t orig_rvaddr; /* IN: original rounded VA */ + vsize_t orig_size; /* IN: original size of interest */ + vm_map_t map; /* map (could be a submap) */ + unsigned int mapv; /* map's version number */ + vm_map_entry_t entry; /* map entry (from 'map') */ + vsize_t size; /* size of interest */ +}; + +#ifdef _KERNEL + +/* + * fault prototypes + */ + +void uvmfault_init(void); + +boolean_t uvmfault_lookup(struct uvm_faultinfo *, boolean_t); +boolean_t uvmfault_relock(struct uvm_faultinfo *); +void uvmfault_unlockall(struct uvm_faultinfo *, struct vm_amap *, + struct uvm_object *); +int uvmfault_anonget(struct uvm_faultinfo *, struct vm_amap *, + struct vm_anon *); + +int uvm_fault_wire(vm_map_t, vaddr_t, vaddr_t, vm_prot_t); +void uvm_fault_unwire(vm_map_t, vaddr_t, vaddr_t); +void uvm_fault_unwire_locked(vm_map_t, vaddr_t, vaddr_t); + +#endif /* _KERNEL */ + +#endif /* _UVM_UVM_FAULT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uvm/uvm_glue.h b/lib/libc/include/generic-openbsd/uvm/uvm_glue.h new file mode 100644 index 000000000000..e59e2b01121b --- /dev/null +++ b/lib/libc/include/generic-openbsd/uvm/uvm_glue.h @@ -0,0 +1,44 @@ +/* $OpenBSD: uvm_glue.h,v 1.11 2025/06/02 18:49:04 claudio Exp $ */ +/* $NetBSD: uvm_glue.h,v 1.6 1999/06/21 17:25:11 thorpej Exp $ */ + +/* + * Copyright (c) 1997 Charles D. Cranor and Washington University. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: Id: uvm_glue.h,v 1.1.2.1 1997/08/14 19:10:48 chuck Exp + */ + +#ifndef _UVM_UVM_GLUE_H_ +#define _UVM_UVM_GLUE_H_ + +#ifdef _KERNEL + +/* + * uvm_glue.h + */ + +struct vm_page *uvm_atopg(vaddr_t); + +#endif /* _KERNEL */ + +#endif /* _UVM_UVM_GLUE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uvm/uvm_km.h b/lib/libc/include/generic-openbsd/uvm/uvm_km.h new file mode 100644 index 000000000000..6b3cf3b41a2a --- /dev/null +++ b/lib/libc/include/generic-openbsd/uvm/uvm_km.h @@ -0,0 +1,82 @@ +/* $OpenBSD: uvm_km.h,v 1.15 2017/05/11 00:42:05 dlg Exp $ */ +/* $NetBSD: uvm_km.h,v 1.9 1999/06/21 17:25:11 thorpej Exp $ */ + +/* + * Copyright (c) 1997 Charles D. Cranor and Washington University. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: Id: uvm_km.h,v 1.1.2.2 1997/12/30 12:03:15 mrg Exp + */ + +#ifndef _UVM_UVM_KM_H_ +#define _UVM_UVM_KM_H_ + +/* + * uvm_km.h + */ + +#ifdef _KERNEL + +#include + +/* + * prototypes + */ + +void uvm_km_init(vaddr_t, vaddr_t, vaddr_t); +void uvm_km_page_init(void); +void uvm_km_page_lateinit(void); +void uvm_km_pgremove(struct uvm_object *, vaddr_t, vaddr_t); +void uvm_km_pgremove_intrsafe(vaddr_t, vaddr_t); + +#if !defined(__HAVE_PMAP_DIRECT) + +#define UVM_KM_PAGES_LOWAT_MAX (2048) +#define UVM_KM_PAGES_HIWAT_MAX (4 * UVM_KM_PAGES_LOWAT_MAX) + +struct uvm_km_free_page { + struct uvm_km_free_page *next; +}; +struct uvm_km_pages { + struct mutex mtx; + + /* Low and high water mark for addresses. */ + int lowat; + int hiwat; + + /* Kernel address pool. */ + int free; + vaddr_t page[UVM_KM_PAGES_HIWAT_MAX]; + + struct uvm_km_free_page *freelist; + int freelistlen; + + struct proc *km_proc; +}; + +extern struct uvm_km_pages uvm_km_pages; +#endif /* _HAVE_PMAP_DIRECT */ + +#endif /* _KERNEL */ + +#endif /* _UVM_UVM_KM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uvm/uvm_map.h b/lib/libc/include/generic-openbsd/uvm/uvm_map.h new file mode 100644 index 000000000000..3b32a318db19 --- /dev/null +++ b/lib/libc/include/generic-openbsd/uvm/uvm_map.h @@ -0,0 +1,434 @@ +/* $OpenBSD: uvm_map.h,v 1.96 2025/09/14 13:06:02 mpi Exp $ */ +/* $NetBSD: uvm_map.h,v 1.24 2001/02/18 21:19:08 chs Exp $ */ + +/* + * Copyright (c) 2011 Ariane van der Steldt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * Copyright (c) 1997 Charles D. Cranor and Washington University. + * Copyright (c) 1991, 1993, The Regents of the University of California. + * + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * The Mach Operating System project at Carnegie-Mellon University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vm_map.h 8.3 (Berkeley) 3/15/94 + * from: Id: uvm_map.h,v 1.1.2.3 1998/02/07 01:16:55 chs Exp + * + * + * Copyright (c) 1987, 1990 Carnegie-Mellon University. + * All rights reserved. + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#ifndef _UVM_UVM_MAP_H_ +#define _UVM_UVM_MAP_H_ + +#include +#include + +#ifdef _KERNEL + +/* + * UVM_MAP_CLIP_START: ensure that the entry begins at or after + * the starting address, if it doesn't we split the entry. + * + * => map must be locked by caller + */ + +#define UVM_MAP_CLIP_START(_map, _entry, _addr) \ + do { \ + KASSERT((_entry)->end + (_entry)->fspace > (_addr)); \ + if ((_entry)->start < (_addr)) \ + uvm_map_clip_start((_map), (_entry), (_addr)); \ + } while (0) + +/* + * UVM_MAP_CLIP_END: ensure that the entry ends at or before + * the ending address, if it doesn't we split the entry. + * + * => map must be locked by caller + */ + +#define UVM_MAP_CLIP_END(_map, _entry, _addr) \ + do { \ + KASSERT((_entry)->start < (_addr)); \ + if ((_entry)->end > (_addr)) \ + uvm_map_clip_end((_map), (_entry), (_addr)); \ + } while (0) + +/* + * extract flags + */ +#define UVM_EXTRACT_FIXPROT 0x8 /* set prot to maxprot as we go */ + +#endif /* _KERNEL */ + +#include + +/* + * Address map entries consist of start and end addresses, + * a VM object (or sharing map) and offset into that object, + * and user-exported inheritance and protection information. + * Also included is control information for virtual copy operations. + */ +struct vm_map_entry { + union { + RBT_ENTRY(vm_map_entry) addr_entry; /* address tree */ + SLIST_ENTRY(vm_map_entry) addr_kentry; + } daddrs; + + union { + RBT_ENTRY(vm_map_entry) rbtree; /* Link freespace tree. */ + TAILQ_ENTRY(vm_map_entry) tailq;/* Link freespace queue. */ + TAILQ_ENTRY(vm_map_entry) deadq;/* dead entry queue */ + } dfree; + +#define uvm_map_entry_start_copy start + vaddr_t start; /* start address */ + vaddr_t end; /* end address */ + + vsize_t guard; /* bytes in guard */ + vsize_t fspace; /* free space */ + + union { + struct uvm_object *uvm_obj; /* uvm object */ + struct vm_map *sub_map; /* belongs to another map */ + } object; /* object I point to */ + voff_t offset; /* offset into object */ + struct vm_aref aref; /* anonymous overlay */ + int etype; /* entry type */ + vm_prot_t protection; /* protection code */ + vm_prot_t max_protection; /* maximum protection */ + vm_inherit_t inheritance; /* inheritance */ + int wired_count; /* can be paged if == 0 */ + int advice; /* madvise advice */ +#define uvm_map_entry_stop_copy flags + u_int8_t flags; /* flags */ + +#define UVM_MAP_STATIC 0x01 /* static map entry */ +#define UVM_MAP_KMEM 0x02 /* from kmem entry pool */ + + vsize_t fspace_augment; /* max(fspace) in subtree */ +}; + +#define VM_MAPENT_ISWIRED(entry) ((entry)->wired_count != 0) + +TAILQ_HEAD(uvm_map_deadq, vm_map_entry); /* dead entry queue */ +RBT_HEAD(uvm_map_addr, vm_map_entry); +#ifdef _KERNEL +RBT_PROTOTYPE(uvm_map_addr, vm_map_entry, daddrs.addr_entry, + uvm_mapentry_addrcmp); +#endif + +/* + * A Map is a rbtree of map entries, kept sorted by address. + * In addition, free space entries are also kept in a rbtree, + * indexed by free size. + * + * + * + * LOCKING PROTOCOL NOTES: + * ----------------------- + * + * VM map locking is a little complicated. There are both shared + * and exclusive locks on maps. However, it is sometimes required + * to unlock a VM map (to prevent lock ordering issues) without + * allowing any other thread to modify it. + * + * In order to prevent this scenario, we introduce the notion of + * a `busy' map. A `busy' map is unlocked, but other threads + * attempting to write-lock wait for this flag to clear before + * entering the lock manager. A map may only be marked busy + * when the map is write-locked and may only be marked unbusy by + * the thread which marked it busy. + * + * Access to the map `flags' member is controlled by the `flags_lock' + * simple lock. Note that some flags are static (set once at map + * creation time, and never changed), and thus require no locking + * to check those flags. All flags which are r/w must be set or + * cleared while the `flags_lock' is asserted. Additional locking + * requirements are: + * + * VM_MAP_PAGEABLE r/o static flag; no locking required + * + * VM_MAP_INTRSAFE r/o static flag; no locking required + * + * VM_MAP_WIREFUTURE r/w; may only be set or cleared when + * map is write-locked. may be tested + * without asserting `flags_lock'. + * + * VM_MAP_GUARDPAGES r/o; must be specified at map + * initialization time. + * If set, guards will appear between + * automatic allocations. + * No locking required. + * + * VM_MAP_ISVMSPACE r/o; set by uvmspace_alloc. + * Signifies that this map is a vmspace. + * (The implementation treats all maps + * without this bit as kernel maps.) + * No locking required. + * + * + * All automatic allocations (uvm_map without MAP_FIXED) will allocate + * from vm_map.free. + * If that allocation fails: + * - vmspace maps will spill over into vm_map.bfree, + * - all other maps will call uvm_map_kmem_grow() to increase the arena. + * + * vmspace maps have their data, brk() and stack arenas automatically + * updated when uvm_map() is invoked without MAP_FIXED. + * The spill over arena (vm_map.bfree) will contain the space in the brk() + * and stack ranges. + * Kernel maps never have a bfree arena and this tree will always be empty. + * + * + * read_locks and write_locks are used in lock debugging code. + * + * Locks used to protect struct members in this file: + * a atomic operations + * I immutable after creation or exec(2) + * v `vm_map_lock' (this map `lock' or `mtx') + * f flags_lock + */ +struct vm_map { + struct pmap *pmap; /* [I] Physical map */ + u_long sserial; /* [v] # stack changes */ + + struct uvm_map_addr addr; /* [v] Entry tree, by addr */ + + vsize_t size; /* virtual size */ + int ref_count; /* [a] Reference count */ + int flags; /* [f] flags */ + unsigned int timestamp; /* Version number */ + struct proc *busy; /* [f] thread holding map busy*/ + unsigned int nbusy; /* [f] waiters for busy */ + + vaddr_t min_offset; /* [I] First address in map. */ + vaddr_t max_offset; /* [I] Last address in map. */ + + /* + * Allocation overflow regions. + */ + vaddr_t b_start; /* [v] Start for brk() alloc. */ + vaddr_t b_end; /* [v] End for brk() alloc. */ + vaddr_t s_start; /* [v] Start for stack alloc. */ + vaddr_t s_end; /* [v] End for stack alloc. */ + + /* + * Special address selectors. + * + * The uaddr_exe mapping is used if: + * - protX is selected + * - the pointer is not NULL + * + * If uaddr_exe is not used, the other mappings are checked in + * order of appearance. + * If a hint is given, the selection will only be used if the hint + * falls in the range described by the mapping. + * + * The states are pointers because: + * - they may not all be in use + * - the struct size for different schemes is variable + * + * The uaddr_brk_stack selector will select addresses that are in + * the brk/stack area of the map. + */ + struct uvm_addr_state *uaddr_exe; /* Executable selector. */ + struct uvm_addr_state *uaddr_any[4]; /* More selectors. */ + struct uvm_addr_state *uaddr_brk_stack; /* Brk/stack selector. */ + +#define UVM_MAP_CHECK_COPYIN_MAX 4 /* main, sigtramp, ld.so, libc.so */ + struct uvm_check_copyin { + vaddr_t start, end; + } check_copyin[UVM_MAP_CHECK_COPYIN_MAX]; + int check_copyin_count; + + /* + * XXX struct mutex changes size because of compile options, so + * place after fields which are inspected by libkvm / procmap(1) + */ + struct rwlock lock; /* Non-intrsafe lock */ + struct mutex mtx; /* Intrsafe lock */ + struct mutex flags_lock; /* flags lock */ +}; + +/* vm_map flags */ +#define VM_MAP_PAGEABLE 0x01 /* ro: entries are pageable */ +#define VM_MAP_INTRSAFE 0x02 /* ro: interrupt safe map */ +#define VM_MAP_WIREFUTURE 0x04 /* rw: wire future mappings */ +#define VM_MAP_GUARDPAGES 0x20 /* rw: add guard pgs to map */ +#define VM_MAP_ISVMSPACE 0x40 /* ro: map is a vmspace */ +#define VM_MAP_PINSYSCALL_ONCE 0x100 /* rw: pinsyscall done */ + +/* Number of kernel maps and entries to statically allocate */ +#define MAX_KMAPENT 1024 /* Sufficient to make it to the scheduler. */ + +#ifdef _KERNEL +/* + * globals: + */ + +extern vaddr_t uvm_maxkaddr; + +/* + * protos: the following prototypes define the interface to vm_map + */ + +void uvm_map_deallocate(struct vm_map *); + +int uvm_map_clean(struct vm_map *, vaddr_t, vaddr_t, int); +void uvm_map_clip_start(struct vm_map *, struct vm_map_entry *, + vaddr_t); +void uvm_map_clip_end(struct vm_map *, struct vm_map_entry *, + vaddr_t); +int uvm_map_extract(struct vm_map *, vaddr_t, vsize_t, + vaddr_t *, int); +struct vm_map * uvm_map_create(pmap_t, vaddr_t, vaddr_t, int); +vaddr_t uvm_map_pie(vaddr_t); +vaddr_t uvm_map_hint(struct vmspace *, vm_prot_t, vaddr_t, vaddr_t); +int uvm_map_check_copyin_add(struct vm_map *, vaddr_t, vaddr_t); +int uvm_map_immutable(struct vm_map *, vaddr_t, vaddr_t, int); +int uvm_map_inherit(struct vm_map *, vaddr_t, vaddr_t, vm_inherit_t); +int uvm_map_advice(struct vm_map *, vaddr_t, vaddr_t, int); +void uvm_map_init(void); +boolean_t uvm_map_lookup_entry(struct vm_map *, vaddr_t, vm_map_entry_t *); +boolean_t uvm_map_is_stack_remappable(struct vm_map *, vaddr_t, vsize_t, int); +int uvm_map_remap_as_stack(struct proc *, vaddr_t, vsize_t); +void uvm_map_setup(struct vm_map *, pmap_t, vaddr_t, vaddr_t, int); +int uvm_map_submap(struct vm_map *, vaddr_t, vaddr_t, + struct vm_map *); +void uvm_unmap(struct vm_map *, vaddr_t, vaddr_t); +void uvm_unmap_detach(struct uvm_map_deadq *, int); +int uvm_unmap_remove(struct vm_map*, vaddr_t, vaddr_t, + struct uvm_map_deadq *, boolean_t, boolean_t, boolean_t); +void uvm_map_set_uaddr(struct vm_map*, struct uvm_addr_state**, + struct uvm_addr_state*); +int uvm_map_mquery(struct vm_map*, vaddr_t*, vsize_t, voff_t, int); + + +struct p_inentry; + +int uvm_map_inentry_sp(vm_map_entry_t); +boolean_t uvm_map_inentry(struct proc *, struct p_inentry *, vaddr_t addr, + const char *fmt, int (*fn)(vm_map_entry_t), u_long serial); + +struct kinfo_vmentry; + +int uvm_map_fill_vmmap(struct vm_map *, struct kinfo_vmentry *, + size_t *); + +/* + * VM map locking operations. + */ + +boolean_t vm_map_lock_try_ln(struct vm_map*, char*, int); +void vm_map_lock_ln(struct vm_map*, char*, int); +void vm_map_lock_read_ln(struct vm_map*, char*, int); +void vm_map_unlock_ln(struct vm_map*, char*, int); +void vm_map_unlock_read_ln(struct vm_map*, char*, int); +boolean_t vm_map_upgrade_ln(struct vm_map*, char*, int); +void vm_map_downgrade_ln(struct vm_map*, char*, int); +void vm_map_busy_ln(struct vm_map*, char*, int); +void vm_map_unbusy_ln(struct vm_map*, char*, int); +void vm_map_assert_anylock_ln(struct vm_map*, char*, int); +void vm_map_assert_wrlock_ln(struct vm_map*, char*, int); + +#ifdef DIAGNOSTIC +#define vm_map_lock_try(map) vm_map_lock_try_ln(map, __FILE__, __LINE__) +#define vm_map_lock(map) vm_map_lock_ln(map, __FILE__, __LINE__) +#define vm_map_lock_read(map) vm_map_lock_read_ln(map, __FILE__, __LINE__) +#define vm_map_unlock(map) vm_map_unlock_ln(map, __FILE__, __LINE__) +#define vm_map_unlock_read(map) vm_map_unlock_read_ln(map, __FILE__, __LINE__) +#define vm_map_upgrade(map) vm_map_upgrade_ln(map, __FILE__, __LINE__) +#define vm_map_downgrade(map) vm_map_downgrade_ln(map, __FILE__, __LINE__) +#define vm_map_busy(map) vm_map_busy_ln(map, __FILE__, __LINE__) +#define vm_map_unbusy(map) vm_map_unbusy_ln(map, __FILE__, __LINE__) +#define vm_map_assert_anylock(map) \ + vm_map_assert_anylock_ln(map, __FILE__, __LINE__) +#define vm_map_assert_wrlock(map) \ + vm_map_assert_wrlock_ln(map, __FILE__, __LINE__) +#else +#define vm_map_lock_try(map) vm_map_lock_try_ln(map, NULL, 0) +#define vm_map_lock(map) vm_map_lock_ln(map, NULL, 0) +#define vm_map_lock_read(map) vm_map_lock_read_ln(map, NULL, 0) +#define vm_map_unlock(map) vm_map_unlock_ln(map, NULL, 0) +#define vm_map_unlock_read(map) vm_map_unlock_read_ln(map, NULL, 0) +#define vm_map_upgrade(map) vm_map_upgrade_ln(map, NULL, 0) +#define vm_map_downgrade(map) vm_map_downgrade_ln(map, NULL, 0) +#define vm_map_busy(map) vm_map_busy_ln(map, NULL, 0) +#define vm_map_unbusy(map) vm_map_unbusy_ln(map, NULL, 0) +#define vm_map_assert_anylock(map) vm_map_assert_anylock_ln(map, NULL, 0) +#define vm_map_assert_wrlock(map) vm_map_assert_wrlock_ln(map, NULL, 0) +#endif + +void uvm_map_lock_entry(struct vm_map_entry *); +void uvm_map_unlock_entry(struct vm_map_entry *); + +#endif /* _KERNEL */ + +/* + * Functions implemented as macros + */ +#define vm_map_min(map) ((map)->min_offset) +#define vm_map_max(map) ((map)->max_offset) +#define vm_map_pmap(map) ((map)->pmap) + +#endif /* _UVM_UVM_MAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uvm/uvm_object.h b/lib/libc/include/generic-openbsd/uvm/uvm_object.h new file mode 100644 index 000000000000..af9e887576d2 --- /dev/null +++ b/lib/libc/include/generic-openbsd/uvm/uvm_object.h @@ -0,0 +1,126 @@ +/* $OpenBSD: uvm_object.h,v 1.30 2022/09/04 06:49:11 jsg Exp $ */ +/* $NetBSD: uvm_object.h,v 1.11 2001/03/09 01:02:12 chs Exp $ */ + +/* + * Copyright (c) 1997 Charles D. Cranor and Washington University. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: Id: uvm_object.h,v 1.1.2.2 1998/01/04 22:44:51 chuck Exp + */ + +#ifndef _UVM_UVM_OBJECT_H_ +#define _UVM_UVM_OBJECT_H_ + +/* + * The UVM memory object interface. Notes: + * + * A UVM memory object represents a list of pages, which are managed by + * the object's pager operations (uvm_object::pgops). All pages belonging + * to an object are owned by it and thus protected by the object lock. + * + * The lock (uvm_object::vmobjlock) may be shared amongst the UVM objects. + * By default, the lock is allocated dynamically using rw_obj_init() cache. + * Lock sharing is normally used when there is an underlying object. For + * example, vnode representing a file may have an underlying node, which + * is the case for tmpfs and layered file systems. In such case, vnode's + * UVM object and the underlying UVM object shares the lock. + * + * The reference count is managed atomically for the anonymous UVM objects. + * For other objects, it is arbitrary (may use the lock or atomics). + */ + +struct uvm_object { + struct rwlock *vmobjlock; /* lock on object */ + const struct uvm_pagerops *pgops; /* pager ops */ + RBT_HEAD(uvm_objtree, vm_page) memt; /* pages in object */ + int uo_npages; /* # of pages in memt */ + int uo_refs; /* reference count */ +}; + +/* + * UVM_OBJ_KERN is a 'special' uo_refs value which indicates that the + * object is a kernel memory object rather than a normal one (kernel + * memory objects don't have reference counts -- they never die). + * + * this value is used to detected kernel object mappings at uvm_unmap() + * time. normally when an object is unmapped its pages eventually become + * deactivated and then paged out and/or freed. this is not useful + * for kernel objects... when a kernel object is unmapped we always want + * to free the resources associated with the mapping. UVM_OBJ_KERN + * allows us to decide which type of unmapping we want to do. + * + * in addition, we have kernel objects which may be used in an + * interrupt context. these objects get their mappings entered + * with pmap_kenter*() and removed with pmap_kremove(), which + * are safe to call in interrupt context, and must be used ONLY + * for wired kernel mappings in these objects and their associated + * maps. + */ +#define UVM_OBJ_KERN (-2) + +#define UVM_OBJ_IS_KERN_OBJECT(uobj) \ + ((uobj)->uo_refs == UVM_OBJ_KERN) + +#ifdef _KERNEL + +extern const struct uvm_pagerops uvm_vnodeops; +extern const struct uvm_pagerops uvm_deviceops; +extern const struct uvm_pagerops pmap_pager; +extern const struct uvm_pagerops bufcache_pager; + +/* For object trees */ +int uvm_pagecmp(const struct vm_page *, const struct vm_page *); +RBT_PROTOTYPE(uvm_objtree, vm_page, objt, uvm_pagecmp) + +#define UVM_OBJ_IS_VNODE(uobj) \ + ((uobj)->pgops == &uvm_vnodeops) + +#define UVM_OBJ_IS_DEVICE(uobj) \ + ((uobj)->pgops == &uvm_deviceops) + +#define UVM_OBJ_IS_VTEXT(uobj) \ + ((uobj)->pgops == &uvm_vnodeops && \ + ((struct vnode *)uobj)->v_flag & VTEXT) + +#define UVM_OBJ_IS_AOBJ(uobj) \ + ((uobj)->pgops == &aobj_pager) + +#define UVM_OBJ_IS_PMAP(uobj) \ + ((uobj)->pgops == &pmap_pager) + +#define UVM_OBJ_IS_BUFCACHE(uobj) \ + ((uobj)->pgops == &bufcache_pager) + +#define UVM_OBJ_IS_DUMMY(uobj) \ + (UVM_OBJ_IS_PMAP(uobj) || UVM_OBJ_IS_BUFCACHE(uobj)) + +void uvm_obj_init(struct uvm_object *, const struct uvm_pagerops *, int); +void uvm_obj_destroy(struct uvm_object *); +void uvm_obj_setlock(struct uvm_object *, struct rwlock *); +int uvm_obj_wire(struct uvm_object *, voff_t, voff_t, struct pglist *); +void uvm_obj_unwire(struct uvm_object *, voff_t, voff_t); +void uvm_obj_free(struct uvm_object *); + +#endif /* _KERNEL */ + +#endif /* _UVM_UVM_OBJECT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uvm/uvm_page.h b/lib/libc/include/generic-openbsd/uvm/uvm_page.h new file mode 100644 index 000000000000..146292310144 --- /dev/null +++ b/lib/libc/include/generic-openbsd/uvm/uvm_page.h @@ -0,0 +1,301 @@ +/* $OpenBSD: uvm_page.h,v 1.73 2025/03/10 18:54:38 mpi Exp $ */ +/* $NetBSD: uvm_page.h,v 1.19 2000/12/28 08:24:55 chs Exp $ */ + +/* + * Copyright (c) 1997 Charles D. Cranor and Washington University. + * Copyright (c) 1991, 1993, The Regents of the University of California. + * + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * The Mach Operating System project at Carnegie-Mellon University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vm_page.h 7.3 (Berkeley) 4/21/91 + * from: Id: uvm_page.h,v 1.1.2.6 1998/02/04 02:31:42 chuck Exp + * + * + * Copyright (c) 1987, 1990 Carnegie-Mellon University. + * All rights reserved. + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#ifndef _UVM_UVM_PAGE_H_ +#define _UVM_UVM_PAGE_H_ + +/* + * uvm_page.h + */ + +/* + * Resident memory system definitions. + */ + +/* + * Management of resident (logical) pages. + * + * A small structure is kept for each resident + * page, indexed by page number. Each structure + * contains a list used for manipulating pages, and + * a tree structure for in object/offset lookups + * + * In addition, the structure contains the object + * and offset to which this page belongs (for pageout), + * and sundry status bits. + * + * Locks used to protect struct members in this file: + * I immutable after creation + * a atomic operations + * Q uvm.pageqlock + * F uvm.fpageqlock + * o owner lock (uobject->vmobjlock or uanon->an_lock) + */ + +TAILQ_HEAD(pglist, vm_page); + +struct vm_page { + TAILQ_ENTRY(vm_page) pageq; /* [Q] LRU or free page queue */ + RBT_ENTRY(vm_page) objt; /* [o] object tree */ + + struct vm_anon *uanon; /* [o] anon */ + struct uvm_object *uobject; /* [o] object */ + voff_t offset; /* [o] offset into object */ + + uint32_t pg_flags; /* [a] object flags */ + + uint32_t pg_version; /* version count */ + uint32_t wire_count; /* [o] wired down map refs */ + + paddr_t phys_addr; /* [I] physical address */ + psize_t fpgsz; /* [F] free page range size */ + + struct vm_page_md mdpage; /* pmap-specific data */ + +#if defined(UVM_PAGE_TRKOWN) + /* debugging fields to track page ownership */ + pid_t owner; /* thread that set PG_BUSY */ + char *owner_tag; /* why it was set busy */ +#endif +}; + +/* + * These are the flags defined for vm_page. + * + * Note: PG_FILLED and PG_DIRTY are added for the filesystems. + */ + +/* + * locking rules: + * PQ_ ==> lock by page queue lock + * PQ_FREE is locked by free queue lock and is mutex with all other PQs + * pg_flags may only be changed using the atomic operations. + * + * PG_ZERO is used to indicate that a page has been pre-zero'd. This flag + * is only set when the page is on no queues, and is cleared when the page + * is placed on the free list. + */ + +#define PG_BUSY 0x00000001 /* page is locked */ +#define PG_WANTED 0x00000002 /* someone is waiting for page */ +#define PG_TABLED 0x00000004 /* page is in VP table */ +#define PG_CLEAN 0x00000008 /* page has not been modified */ +#define PG_CLEANCHK 0x00000010 /* clean bit has been checked */ +#define PG_RELEASED 0x00000020 /* page released while paging */ +#define PG_FAKE 0x00000040 /* page is not yet initialized */ +#define PG_RDONLY 0x00000080 /* page must be mapped read-only */ +#define PG_ZERO 0x00000100 /* page is pre-zero'd */ +#define PG_DEV 0x00000200 /* page is in device space, lay off */ +#define PG_MASK 0x0000ffff + +#define PQ_FREE 0x00010000 /* page is on free list */ +#define PQ_INACTIVE 0x00020000 /* page is in inactive list */ +#define PQ_ACTIVE 0x00040000 /* page is in active list */ +#define PQ_ITER 0x00080000 /* page is an iterator marker */ +#define PQ_ANON 0x00100000 /* page is part of an anon, rather + than an uvm_object */ +#define PQ_AOBJ 0x00200000 /* page is part of an anonymous + uvm_object */ +#define PQ_SWAPBACKED (PQ_ANON|PQ_AOBJ) +#define PQ_ENCRYPT 0x00400000 /* page needs {en,de}cryption */ +#define PQ_MASK 0x00ff0000 + +#define PG_PMAP0 0x01000000 /* Used by some pmaps. */ +#define PG_PMAP1 0x02000000 /* Used by some pmaps. */ +#define PG_PMAP2 0x04000000 /* Used by some pmaps. */ +#define PG_PMAP3 0x08000000 /* Used by some pmaps. */ +#define PG_PMAP4 0x10000000 /* Used by some pmaps. */ +#define PG_PMAP5 0x20000000 /* Used by some pmaps. */ +#define PG_PMAPMASK 0x3f000000 + +/* + * physical memory layout structure + * + * MD vmparam.h must #define: + * VM_PHYSSEG_MAX = max number of physical memory segments we support + * (if this is "1" then we revert to a "contig" case) + * VM_PHYSSEG_STRAT: memory sort/search options (for VM_PHYSSEG_MAX > 1) + * - VM_PSTRAT_RANDOM: linear search (random order) + * - VM_PSTRAT_BSEARCH: binary search (sorted by address) + * - VM_PSTRAT_BIGFIRST: linear search (sorted by largest segment first) + * - others? + * XXXCDC: eventually we should purge all left-over global variables... + */ +#define VM_PSTRAT_RANDOM 1 +#define VM_PSTRAT_BSEARCH 2 +#define VM_PSTRAT_BIGFIRST 3 + +/* + * vm_physmemseg: describes one segment of physical memory + */ +struct vm_physseg { + paddr_t start; /* PF# of first page in segment */ + paddr_t end; /* (PF# of last page in segment) + 1 */ + paddr_t avail_start; /* PF# of first free page in segment */ + paddr_t avail_end; /* (PF# of last free page in segment) +1 */ + struct vm_page *pgs; /* vm_page structures (from start) */ + struct vm_page *lastpg; /* vm_page structure for end */ +}; + +#ifdef _KERNEL + +/* + * physical memory config is stored in vm_physmem. + */ + +extern struct vm_physseg vm_physmem[VM_PHYSSEG_MAX]; +extern int vm_nphysseg; + +/* + * prototypes: the following prototypes define the interface to pages + */ + +void uvm_page_init(vaddr_t *, vaddr_t *); +#if defined(UVM_PAGE_TRKOWN) +void uvm_page_own(struct vm_page *, char *); +#endif +#if !defined(PMAP_STEAL_MEMORY) +boolean_t uvm_page_physget(paddr_t *); +#endif + +void uvm_pageactivate(struct vm_page *); +void uvm_pagedequeue(struct vm_page *); +vaddr_t uvm_pageboot_alloc(vsize_t); +void uvm_pagecopy(struct vm_page *, struct vm_page *); +void uvm_pagedeactivate(struct vm_page *); +void uvm_pageclean(struct vm_page *); +void uvm_pagefree(struct vm_page *); +void uvm_page_unbusy(struct vm_page **, int); +struct vm_page *uvm_pagelookup(struct uvm_object *, voff_t); +void uvm_pageunwire(struct vm_page *); +void uvm_pagewait(struct vm_page *, struct rwlock *, const char *); +void uvm_pagewire(struct vm_page *); +void uvm_pagezero(struct vm_page *); +void uvm_pagealloc_pg(struct vm_page *, struct uvm_object *, + voff_t, struct vm_anon *); + +struct uvm_constraint_range; /* XXX move to uvm_extern.h? */ +psize_t uvm_pagecount(struct uvm_constraint_range*); + +#if VM_PHYSSEG_MAX == 1 +/* + * Inline functions for archs where function calls are expensive. + */ +/* + * vm_physseg_find: find vm_physseg structure that belongs to a PA + */ +static inline int +vm_physseg_find(paddr_t pframe, int *offp) +{ + /* 'contig' case */ + if (pframe >= vm_physmem[0].start && pframe < vm_physmem[0].end) { + if (offp) + *offp = pframe - vm_physmem[0].start; + return 0; + } + return -1; +} + +/* + * PHYS_TO_VM_PAGE: find vm_page for a PA. used by MI code to get vm_pages + * back from an I/O mapping (ugh!). used in some MD code as well. + */ +static inline struct vm_page * +PHYS_TO_VM_PAGE(paddr_t pa) +{ + paddr_t pf = atop(pa); + int off; + int psi; + + psi = vm_physseg_find(pf, &off); + + return ((psi == -1) ? NULL : &vm_physmem[psi].pgs[off]); +} +#else +/* if VM_PHYSSEG_MAX > 1 they're not inline, they're in uvm_page.c. */ +struct vm_page *PHYS_TO_VM_PAGE(paddr_t); +int vm_physseg_find(paddr_t, int *); +#endif + +/* + * macros + */ + +#define uvm_lock_pageq() mtx_enter(&uvm.pageqlock) +#define uvm_unlock_pageq() mtx_leave(&uvm.pageqlock) +#define uvm_lock_fpageq() mtx_enter(&uvm.fpageqlock) +#define uvm_unlock_fpageq() mtx_leave(&uvm.fpageqlock) + +#define UVM_PAGEZERO_TARGET (uvmexp.free / 8) + +#define VM_PAGE_TO_PHYS(pg) ((pg)->phys_addr) + +#define VM_PAGE_IS_FREE(pg) ((pg)->pg_flags & PQ_FREE) + +#define PADDR_IS_DMA_REACHABLE(paddr) \ + (dma_constraint.ucr_low <= paddr && dma_constraint.ucr_high > paddr) + +#endif /* _KERNEL */ + +#endif /* _UVM_UVM_PAGE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uvm/uvm_pager.h b/lib/libc/include/generic-openbsd/uvm/uvm_pager.h new file mode 100644 index 000000000000..f9449680c1eb --- /dev/null +++ b/lib/libc/include/generic-openbsd/uvm/uvm_pager.h @@ -0,0 +1,173 @@ +/* $OpenBSD: uvm_pager.h,v 1.33 2021/10/12 07:38:22 mpi Exp $ */ +/* $NetBSD: uvm_pager.h,v 1.20 2000/11/27 08:40:05 chs Exp $ */ + +/* + * Copyright (c) 1997 Charles D. Cranor and Washington University. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: Id: uvm_pager.h,v 1.1.2.14 1998/01/13 19:00:50 chuck Exp + */ + +/* + * Copyright (c) 1990 University of Utah. + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vm_pager.h 8.5 (Berkeley) 7/7/94 + */ + +#ifndef _UVM_UVM_PAGER_H_ +#define _UVM_UVM_PAGER_H_ + +#ifdef _KERNEL + +struct uvm_pagerops { + /* init pager */ + void (*pgo_init)(void); + /* add reference to obj */ + void (*pgo_reference)(struct uvm_object *); + /* drop reference to obj */ + void (*pgo_detach)(struct uvm_object *); + /* special nonstd fault fn */ + int (*pgo_fault)(struct uvm_faultinfo *, vaddr_t, + vm_page_t *, int, int, vm_fault_t, + vm_prot_t, int); + /* flush pages out of obj */ + boolean_t (*pgo_flush)(struct uvm_object *, voff_t, + voff_t, int); + /* get/read page */ + int (*pgo_get)(struct uvm_object *, voff_t, + vm_page_t *, int *, int, vm_prot_t, int, int); + /* put/write page */ + int (*pgo_put)(struct uvm_object *, vm_page_t *, + int, boolean_t); + /* return range of cluster */ + void (*pgo_cluster)(struct uvm_object *, voff_t, + voff_t *, voff_t *); + /* make "put" cluster */ + struct vm_page ** (*pgo_mk_pcluster)(struct uvm_object *, + struct vm_page **, int *, struct vm_page *, + int, voff_t, voff_t); +}; + +/* pager flags [mostly for flush] */ + +#define PGO_CLEANIT 0x001 /* write dirty pages to backing store */ +#define PGO_SYNCIO 0x002 /* if PGO_CLEANIT: use sync I/O? */ +#define PGO_DEACTIVATE 0x004 /* deactivate flushed pages */ +#define PGO_FREE 0x008 /* free flushed pages */ +/* if PGO_FREE is not set then the pages stay where they are. */ + +#define PGO_ALLPAGES 0x010 /* flush whole object/get all pages */ +#define PGO_DOACTCLUST 0x020 /* flag to mk_pcluster to include active */ +#define PGO_LOCKED 0x040 /* fault data structures are locked [get] */ +#define PGO_PDFREECLUST 0x080 /* daemon's free cluster flag [uvm_pager_put] */ +#define PGO_REALLOCSWAP 0x100 /* reallocate swap area [pager_dropcluster] */ +#define PGO_NOWAIT 0x200 /* do not wait for inode lock */ + +/* page we are not interested in getting */ +#define PGO_DONTCARE ((struct vm_page *) -1L) /* [get only] */ + +/* + * prototypes + */ + +void uvm_pager_dropcluster(struct uvm_object *, struct vm_page *, + struct vm_page **, int *, int); +void uvm_pager_init(void); +int uvm_pager_put(struct uvm_object *, struct vm_page *, + struct vm_page ***, int *, int, voff_t, voff_t); + + +vaddr_t uvm_pagermapin(struct vm_page **, int, int); +void uvm_pagermapout(vaddr_t, int); +struct vm_page **uvm_mk_pcluster(struct uvm_object *, struct vm_page **, + int *, struct vm_page *, int, voff_t, voff_t); + +/* Flags to uvm_pagermapin() */ +#define UVMPAGER_MAPIN_WAITOK 0x01 /* it's okay to wait */ +#define UVMPAGER_MAPIN_READ 0x02 /* host <- device */ +#define UVMPAGER_MAPIN_WRITE 0x00 /* device -> host (pseudo flag) */ + +/* + * get/put return values + * OK operation was successful + * BAD specified data was out of the accepted range + * FAIL specified data was in range, but doesn't exist + * PEND operations was initiated but not completed + * ERROR error while accessing data that is in range and exists + * AGAIN temporary resource shortage prevented operation from happening + * UNLOCK unlock the map and try again + * REFAULT [uvm_fault internal use only!] unable to relock data structures, + * thus the mapping needs to be reverified before we can proceed + */ +#define VM_PAGER_OK 0 +#define VM_PAGER_BAD 1 +#define VM_PAGER_FAIL 2 +#define VM_PAGER_PEND 3 +#define VM_PAGER_ERROR 4 +#define VM_PAGER_AGAIN 5 +#define VM_PAGER_UNLOCK 6 +#define VM_PAGER_REFAULT 7 + +/* + * XXX + * this is needed until the device strategy interface + * is changed to do physically-addressed i/o. + */ + +#ifndef PAGER_MAP_SIZE +#define PAGER_MAP_SIZE (16 * 1024 * 1024) +#endif + +#endif /* _KERNEL */ + +#endif /* _UVM_UVM_PAGER_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uvm/uvm_param.h b/lib/libc/include/generic-openbsd/uvm/uvm_param.h new file mode 100644 index 000000000000..f21919792ea7 --- /dev/null +++ b/lib/libc/include/generic-openbsd/uvm/uvm_param.h @@ -0,0 +1,91 @@ +/* $OpenBSD: uvm_param.h,v 1.18 2015/02/07 08:21:24 miod Exp $ */ +/* $NetBSD: uvm_param.h,v 1.5 2001/03/09 01:02:12 chs Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * The Mach Operating System project at Carnegie-Mellon University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vm_param.h 8.2 (Berkeley) 1/9/95 + * + * + * Copyright (c) 1987, 1990 Carnegie-Mellon University. + * All rights reserved. + * + * Authors: Avadis Tevanian, Jr., Michael Wayne Young + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +/* + * Machine independent virtual memory parameters. + */ + +#ifndef _VM_PARAM_ +#define _VM_PARAM_ + +#ifdef _KERNEL + +#include + +typedef int boolean_t; +#define TRUE 1 +#define FALSE 0 + +#define DEFAULT_PAGE_SIZE 4096 + +#define atop(x) ((x) >> PAGE_SHIFT) +#define ptoa(x) ((paddr_t)(x) << PAGE_SHIFT) +#define round_page(x) (((x) + PAGE_MASK) & ~PAGE_MASK) +#define trunc_page(x) ((x) & ~PAGE_MASK) + +#if !defined(VM_KERNEL_SPACE_SIZE) +#define VM_KERNEL_SPACE_SIZE (VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS) +#endif + +#endif /* _KERNEL */ +#endif /* _VM_PARAM_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uvm/uvm_percpu.h b/lib/libc/include/generic-openbsd/uvm/uvm_percpu.h new file mode 100644 index 000000000000..78a9548e56cf --- /dev/null +++ b/lib/libc/include/generic-openbsd/uvm/uvm_percpu.h @@ -0,0 +1,48 @@ +/* $OpenBSD: uvm_percpu.h,v 1.3 2024/05/01 12:54:27 mpi Exp $ */ + +/* + * Copyright (c) 2024 Martin Pieuchot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _UVM_UVM_PCPU_H_ +#define _UVM_UVM_PCPU_H_ + +struct vm_page; + +/* + * The number of pages per magazine should be large enough to get rid of the + * contention in the pmemrange allocator during concurrent page faults and + * small enough to limit fragmentation. + */ +#define UVM_PMR_CACHEMAGSZ 8 + +/* + * Magazine + */ +struct uvm_pmr_cache_item { + struct vm_page *upci_pages[UVM_PMR_CACHEMAGSZ]; + int upci_npages; /* # of pages in magazine */ +}; + +/* + * Per-CPU cache of physical pages. + */ +struct uvm_pmr_cache { + struct uvm_pmr_cache_item upc_magz[2]; /* magazines */ + int upc_actv; /* index of active magazine */ + +}; + +#endif /* _UVM_UVM_PCPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uvm/uvm_pmap.h b/lib/libc/include/generic-openbsd/uvm/uvm_pmap.h new file mode 100644 index 000000000000..b653fbb19d94 --- /dev/null +++ b/lib/libc/include/generic-openbsd/uvm/uvm_pmap.h @@ -0,0 +1,195 @@ +/* $OpenBSD: uvm_pmap.h,v 1.37 2025/06/02 18:49:04 claudio Exp $ */ +/* $NetBSD: uvm_pmap.h,v 1.1 2000/06/27 09:00:14 mrg Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * The Mach Operating System project at Carnegie-Mellon University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pmap.h 8.1 (Berkeley) 6/11/93 + * + * + * Copyright (c) 1987, 1990 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Avadis Tevanian, Jr. + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +/* + * Machine address mapping definitions -- machine-independent + * section. [For machine-dependent section, see "machine/pmap.h".] + */ + +#ifndef _PMAP_VM_ +#define _PMAP_VM_ + +struct proc; /* for pmap_activate()/pmap_deactivate() proto */ + +/* + * Each machine dependent implementation is expected to + * keep certain statistics. They may do this anyway they + * so choose, but are expected to return the statistics + * in the following structure. + */ +struct pmap_statistics { + long resident_count; /* # of pages mapped (total)*/ + long wired_count; /* # of pages wired */ +}; +typedef struct pmap_statistics *pmap_statistics_t; + +#include + +/* + * Flags passed to pmap_enter(). Note the bottom 3 bits are PROT_* + * bits, used to indicate the access type that was made (to seed modified + * and referenced information). + */ +#define PMAP_WIRED 0x00000010 /* wired mapping */ +#define PMAP_CANFAIL 0x00000020 /* can fail if resource shortage */ +#define PMAP_MD0 0x00000040 /* Machine dependant */ +#define PMAP_MD1 0x00000080 /* Machine dependant */ +#define PMAP_MD2 0x00000100 /* Machine dependant */ +#define PMAP_MD3 0x00000200 /* Machine dependant */ + +#ifndef PMAP_WC +#define PMAP_WC 0 +#endif + +#ifndef PMAP_PREFER +#define PMAP_PREFER_ALIGN() 0 +#define PMAP_PREFER_OFFSET(off) 0 +#endif + +#ifdef _KERNEL +__BEGIN_DECLS +#ifndef pmap_activate +void pmap_activate(struct proc *); +#endif +#ifndef pmap_deactivate +void pmap_deactivate(struct proc *); +#endif +#ifndef pmap_unwire +void pmap_unwire(pmap_t, vaddr_t); +#endif + +#if !defined(pmap_clear_modify) +boolean_t pmap_clear_modify(struct vm_page *); +#endif +#if !defined(pmap_clear_reference) +boolean_t pmap_clear_reference(struct vm_page *); +#endif + +#if !defined(pmap_copy_page) +void pmap_copy_page(struct vm_page *, struct vm_page *); +#endif +struct pmap *pmap_create(void); +void pmap_destroy(pmap_t); +int pmap_enter(pmap_t, + vaddr_t, paddr_t, vm_prot_t, int); +boolean_t pmap_extract(pmap_t, vaddr_t, paddr_t *); +#if defined(PMAP_GROWKERNEL) +vaddr_t pmap_growkernel(vaddr_t); +#endif + +void pmap_init(void); + +void pmap_kenter_pa(vaddr_t, paddr_t, vm_prot_t); +void pmap_kremove(vaddr_t, vsize_t); +#if !defined(pmap_is_modified) +boolean_t pmap_is_modified(struct vm_page *); +#endif +#if !defined(pmap_is_referenced) +boolean_t pmap_is_referenced(struct vm_page *); +#endif + +void pmap_page_protect(struct vm_page *, vm_prot_t); + +#if !defined(pmap_proc_iflush) +void pmap_proc_iflush(struct process *, vaddr_t, vsize_t); +#endif +void pmap_protect(pmap_t, vaddr_t, vaddr_t, vm_prot_t); +#if !defined(pmap_reference) +void pmap_reference(pmap_t); +#endif +#if !defined(pmap_remove) +void pmap_remove(pmap_t, vaddr_t, vaddr_t); +#endif +#if !defined(pmap_remove_holes) +void pmap_remove_holes(struct vmspace *); +#endif +#if !defined(pmap_update) +void pmap_update(pmap_t); +#endif +#if !defined(pmap_zero_page) +void pmap_zero_page(struct vm_page *); +#endif + +#if defined(PMAP_STEAL_MEMORY) +vaddr_t pmap_steal_memory(vsize_t, vaddr_t *, vaddr_t *); +#else +void pmap_virtual_space(vaddr_t *, vaddr_t *); +#endif + +#if defined(__HAVE_PMAP_POPULATE) +void pmap_populate(pmap_t, vaddr_t); +#endif + +#if defined(__HAVE_PMAP_PURGE) +void pmap_purge(struct proc *); +#endif + +/* nested pmaps are used in i386/amd64 vmm */ +#ifndef pmap_nested +#define pmap_nested(pm) 0 +#endif + +__END_DECLS +#endif /* kernel*/ + +#endif /* _PMAP_VM_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uvm/uvm_pmemrange.h b/lib/libc/include/generic-openbsd/uvm/uvm_pmemrange.h new file mode 100644 index 000000000000..49af017d9633 --- /dev/null +++ b/lib/libc/include/generic-openbsd/uvm/uvm_pmemrange.h @@ -0,0 +1,165 @@ +/* $OpenBSD: uvm_pmemrange.h,v 1.19 2024/11/07 11:12:46 mpi Exp $ */ + +/* + * Copyright (c) 2009 Ariane van der Steldt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * uvm_pmemrange.h: describe and manage free physical memory. + */ + +#ifndef _UVM_UVM_PMEMRANGE_H_ +#define _UVM_UVM_PMEMRANGE_H_ + +RBT_HEAD(uvm_pmr_addr, vm_page); +RBT_HEAD(uvm_pmr_size, vm_page); + +/* + * Page types available: + * - DIRTY: this page may contain random data. + * - ZERO: this page has been zeroed. + */ +#define UVM_PMR_MEMTYPE_DIRTY 0 +#define UVM_PMR_MEMTYPE_ZERO 1 +#define UVM_PMR_MEMTYPE_MAX 2 + +/* + * An address range of memory. + */ +struct uvm_pmemrange { + struct uvm_pmr_addr addr; /* Free page chunks, sorted by addr. */ + struct uvm_pmr_size size[UVM_PMR_MEMTYPE_MAX]; + /* Free page chunks, sorted by size. */ + TAILQ_HEAD(, vm_page) single[UVM_PMR_MEMTYPE_MAX]; + /* single page regions (uses pageq) */ + + paddr_t low; /* Start of address range (pgno). */ + paddr_t high; /* End +1 (pgno). */ + int use; /* Use counter. */ + psize_t nsegs; /* Current range count. */ + + TAILQ_ENTRY(uvm_pmemrange) pmr_use; + /* pmr, sorted by use */ + RBT_ENTRY(uvm_pmemrange) pmr_addr; + /* pmr, sorted by address */ +}; + +/* + * Description of failing memory allocation. + * + * Every descriptor corresponds to a request for the page daemon to release + * pages in a given memory range. There is one global descriptor for nowait + * allocations, all others are sitting on the stack of processes waiting for + * physical pages. + * + * There are multiple ways physical pages can become available: + * [1] unmanaged pages are released by shrinkers (bufbackoff(), drmbackoff()...) + * [2] page daemon drops them (we notice because they are freed) + * [3] a process calls free or exit + * + * The buffer cache and page daemon can decide that they don't have the + * ability to make pages available in the requested range. In that case, + * the FAIL bit will be set. + * XXX There's a possibility that a page is no longer on the queues but + * XXX has not yet been freed, or that a page was busy. + * XXX Also, wired pages are not considered for paging, so they could + * XXX cause a failure that may be recoverable. + * + * Locks used to protect struct members in this file: + * F uvm_lock_fpageq + * I immutable after creation + */ +struct uvm_pmalloc { + TAILQ_ENTRY(uvm_pmalloc) pmq; /* [F] next request */ + struct uvm_constraint_range pm_constraint; /* [I] memory range */ + psize_t pm_size; /* [I] # pages */ + int pm_flags; /* [F] states flags */ +}; + +/* + * Indicate to the page daemon that a nowait call failed and it should + * recover at least some memory in the most restricted region (assumed + * to be dma_constraint). + */ +extern struct uvm_pmalloc nowait_pma; /* [F] */ + + +/* + * uvm_pmalloc flags. + */ +#define UVM_PMA_LINKED 0x01 /* uvm_pmalloc is on list */ +#define UVM_PMA_BUSY 0x02 /* entry is busy with fpageq unlocked */ +#define UVM_PMA_FAIL 0x10 /* page daemon cannot free pages */ +#define UVM_PMA_FREED 0x20 /* at least one page in the range was freed */ + +RBT_HEAD(uvm_pmemrange_addr, uvm_pmemrange); +TAILQ_HEAD(uvm_pmemrange_use, uvm_pmemrange); + +/* + * pmr control structure. Contained in uvm.pmr_control. + */ +struct uvm_pmr_control { + struct uvm_pmemrange_addr addr; + struct uvm_pmemrange_use use; + + /* Only changed while fpageq is locked. */ + TAILQ_HEAD(, uvm_pmalloc) allocs; +}; + +void uvm_pmr_freepages(struct vm_page *, psize_t); +void uvm_pmr_freepageq(struct pglist *); +int uvm_pmr_getpages(psize_t, paddr_t, paddr_t, paddr_t, paddr_t, + int, int, struct pglist *); +void uvm_pmr_init(void); +int uvm_wait_pla(paddr_t, paddr_t, paddr_t, int); +void uvm_wakeup_pla(paddr_t, psize_t); + +#if defined(DDB) || defined(DEBUG) +int uvm_pmr_isfree(struct vm_page *pg); +#endif + +/* + * Internal tree logic. + */ + +int uvm_pmr_addr_cmp(const struct vm_page *, const struct vm_page *); +int uvm_pmr_size_cmp(const struct vm_page *, const struct vm_page *); + +RBT_PROTOTYPE(uvm_pmr_addr, vm_page, objt, uvm_pmr_addr_cmp); +RBT_PROTOTYPE(uvm_pmr_size, vm_page, objt, uvm_pmr_size_cmp); +RBT_PROTOTYPE(uvm_pmemrange_addr, uvm_pmemrange, pmr_addr, + uvm_pmemrange_addr_cmp); + +struct vm_page *uvm_pmr_insert_addr(struct uvm_pmemrange *, + struct vm_page *, int); +void uvm_pmr_insert_size(struct uvm_pmemrange *, + struct vm_page *); +struct vm_page *uvm_pmr_insert(struct uvm_pmemrange *, + struct vm_page *, int); +void uvm_pmr_remove_addr(struct uvm_pmemrange *, + struct vm_page *); +void uvm_pmr_remove_size(struct uvm_pmemrange *, + struct vm_page *); +void uvm_pmr_remove(struct uvm_pmemrange *, + struct vm_page *); +struct vm_page *uvm_pmr_extract_range(struct uvm_pmemrange *, + struct vm_page *, paddr_t, paddr_t, + struct pglist *); +struct vm_page *uvm_pmr_cache_get(int); +void uvm_pmr_cache_put(struct vm_page *); +unsigned int uvm_pmr_cache_drain(void); + + +#endif /* _UVM_UVM_PMEMRANGE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uvm/uvm_swap.h b/lib/libc/include/generic-openbsd/uvm/uvm_swap.h new file mode 100644 index 000000000000..d3eb55d061f7 --- /dev/null +++ b/lib/libc/include/generic-openbsd/uvm/uvm_swap.h @@ -0,0 +1,58 @@ +/* $OpenBSD: uvm_swap.h,v 1.20 2023/10/27 19:18:53 mpi Exp $ */ +/* $NetBSD: uvm_swap.h,v 1.5 2000/01/11 06:57:51 chs Exp $ */ + +/* + * Copyright (c) 1997 Matthew R. Green + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Id: uvm_swap.h,v 1.1.2.6 1997/12/15 05:39:31 mrg Exp + */ + +#ifndef _UVM_UVM_SWAP_H_ +#define _UVM_UVM_SWAP_H_ + +#define SWCLUSTPAGES (MAXBSIZE >> PAGE_SHIFT) +#define SWSLOT_BAD (-1) + +#ifdef _KERNEL + +int uvm_swap_get(struct vm_page *, int, int); +int uvm_swap_put(int, struct vm_page **, int, int); +int uvm_swap_alloc(int *, boolean_t); +void uvm_swap_free(int, int); +void uvm_swap_markbad(int, int); +int uvm_swapisfilled(void); +int uvm_swapisfull(void); +void uvm_swap_freepages(struct vm_page **, int); +#ifdef HIBERNATE +int uvm_hibswap(dev_t, u_long *, u_long *); +#endif /* HIBERNATE */ +#ifdef UVM_SWAP_ENCRYPT +void uvm_swap_initcrypt_all(void); +void uvm_swap_finicrypt_all(void); +#endif + +#endif /* _KERNEL */ + +#endif /* _UVM_UVM_SWAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uvm/uvm_swap_encrypt.h b/lib/libc/include/generic-openbsd/uvm/uvm_swap_encrypt.h new file mode 100644 index 000000000000..3b46dfa05b32 --- /dev/null +++ b/lib/libc/include/generic-openbsd/uvm/uvm_swap_encrypt.h @@ -0,0 +1,85 @@ +/* $OpenBSD: uvm_swap_encrypt.h,v 1.14 2024/11/07 09:04:55 jsg Exp $ */ + +/* + * Copyright 1999 Niels Provos + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _UVM_SWAP_ENCRYPT_H +#define _UVM_SWAP_ENCRYPT_H + +#define SWPENC_ENABLE 0 +#define SWPENC_CREATED 1 +#define SWPENC_DELETED 2 +#define SWPENC_MAXID 3 + +#define CTL_SWPENC_NAMES { \ + { "enable", CTLTYPE_INT }, \ + { "keyscreated", CTLTYPE_INT }, \ + { "keysdeleted", CTLTYPE_INT }, \ +} + +#define SWAP_KEY_SIZE 4 /* 128-bit keys */ + +struct swap_key { + u_int32_t key[SWAP_KEY_SIZE]; /* secret key for swap range */ + u_int16_t refcount; /* pages that still need it */ +}; + +int swap_encrypt_ctl(int *, u_int, void *, size_t *, void *, size_t, + struct proc *); + +void swap_encrypt(struct swap_key *,caddr_t, caddr_t, u_int64_t, size_t); +void swap_decrypt(struct swap_key *,caddr_t, caddr_t, u_int64_t, size_t); + +void swap_key_cleanup(struct swap_key *); +void swap_key_prepare(struct swap_key *, int); + +void swap_key_create(struct swap_key *); +void swap_key_delete(struct swap_key *); + +static inline void +swap_key_get(struct swap_key *key) +{ + if (key->refcount == 0) + swap_key_create(key); + key->refcount++; +} + +static inline void +swap_key_put(struct swap_key *key) +{ + key->refcount--; + if (key->refcount == 0) + swap_key_delete(key); +} + +extern int uvm_doswapencrypt; /* swapencrypt enabled/disabled */ +extern int swap_encrypt_initialized; + +#endif /* _UVM_SWAP_ENCRYPT_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uvm/uvm_vnode.h b/lib/libc/include/generic-openbsd/uvm/uvm_vnode.h new file mode 100644 index 000000000000..37db256a05d8 --- /dev/null +++ b/lib/libc/include/generic-openbsd/uvm/uvm_vnode.h @@ -0,0 +1,100 @@ +/* $OpenBSD: uvm_vnode.h,v 1.22 2025/09/25 09:05:47 mpi Exp $ */ +/* $NetBSD: uvm_vnode.h,v 1.9 2000/03/26 20:54:48 kleink Exp $ */ + +/* + * + * Copyright (c) 1997 Charles D. Cranor and Washington University. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Charles D. Cranor and + * Washington University. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: Id: uvm_vnode.h,v 1.1.2.4 1997/10/03 21:18:24 chuck Exp + */ + +#ifndef _UVM_UVM_VNODE_H_ +#define _UVM_UVM_VNODE_H_ + +/* + * uvm_vnode.h + * + * vnode handle into the VM system. + */ + +struct vnode; + +/* + * the uvm_vnode structure. + * + * Locks used to protect struct members in this file: + * I immutable after creation + * K kernel lock + * S uvn_sync_lock + * v u_obj's vmobjlock + */ +struct uvm_vnode { + struct uvm_object u_obj; /* the actual VM object */ + struct vnode *u_vnode; /* [I] pointer back to vnode */ + int u_flags; /* [v] flags */ + int u_nio; /* [v] number of running I/O requests */ + voff_t u_size; /* [v] size of object */ + + LIST_ENTRY(uvm_vnode) u_wlist; /* [K] list of writeable vnode objs */ + + SIMPLEQ_ENTRY(uvm_vnode) u_syncq; /* [S] vnode objs due for a "sync" */ +}; + +/* + * u_flags values + */ +#define UVM_VNODE_VALID 0x001 /* we are attached to the vnode */ +#define UVM_VNODE_CANPERSIST 0x002 /* we can persist after ref == 0 */ +#define UVM_VNODE_ALOCK 0x004 /* uvn_attach is locked out */ +#define UVM_VNODE_DYING 0x008 /* final detach/terminate in + progress */ +#define UVM_VNODE_RELKILL 0x010 /* uvn should be killed by releasepg + when final i/o is done */ +#define UVM_VNODE_WANTED 0x020 /* someone is waiting for alock, + dying, or relkill to clear */ +#define UVM_VNODE_VNISLOCKED 0x040 /* underlying vnode struct is locked + (valid when DYING is true) */ +#define UVM_VNODE_IOSYNC 0x080 /* I/O sync in progress ... setter + sleeps on &uvn->u_nio */ +#define UVM_VNODE_IOSYNCWANTED 0x100 /* a process is waiting for the + i/o sync to clear so it can do + i/o */ +#define UVM_VNODE_WRITEABLE 0x200 /* uvn has pages that are writeable */ + +/* + * UVM_VNODE_BLOCKED: any condition that should new processes from + * touching the vnode [set WANTED and sleep to wait for it to clear] + */ +#define UVM_VNODE_BLOCKED (UVM_VNODE_ALOCK|UVM_VNODE_DYING|UVM_VNODE_RELKILL) + +void uvm_vnp_obj_alloc(struct vnode *); +void uvm_vnp_terminate(struct vnode *); + +#endif /* _UVM_UVM_VNODE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/uvm/uvmexp.h b/lib/libc/include/generic-openbsd/uvm/uvmexp.h new file mode 100644 index 000000000000..54fcb47a9de0 --- /dev/null +++ b/lib/libc/include/generic-openbsd/uvm/uvmexp.h @@ -0,0 +1,203 @@ +/* $OpenBSD: uvmexp.h,v 1.19 2025/03/10 19:52:57 miod Exp $ */ + +#ifndef _UVM_UVMEXP_ +#define _UVM_UVMEXP_ + +/* + * CTL_VM identifiers + */ +#define VM_METER 1 /* struct vmmeter */ +#define VM_LOADAVG 2 /* struct loadavg */ +#define VM_PSSTRINGS 3 /* PSSTRINGS */ +#define VM_UVMEXP 4 /* struct uvmexp */ +#define VM_SWAPENCRYPT 5 /* int */ +#define VM_NKMEMPAGES 6 /* int - # kmem_map pages */ +#define VM_ANONMIN 7 +#define VM_VTEXTMIN 8 +#define VM_VNODEMIN 9 +#define VM_MAXSLP 10 +#define VM_USPACE 11 +#define VM_MALLOC_CONF 12 /* config for userland malloc */ +#define VM_MAXID 13 /* number of valid vm ids */ + +#define CTL_VM_NAMES { \ + { 0, 0 }, \ + { "vmmeter", CTLTYPE_STRUCT }, \ + { "loadavg", CTLTYPE_STRUCT }, \ + { "psstrings", CTLTYPE_STRUCT }, \ + { "uvmexp", CTLTYPE_STRUCT }, \ + { "swapencrypt", CTLTYPE_NODE }, \ + { "nkmempages", CTLTYPE_INT }, \ + { "anonmin", CTLTYPE_INT }, \ + { "vtextmin", CTLTYPE_INT }, \ + { "vnodemin", CTLTYPE_INT }, \ + { "maxslp", CTLTYPE_INT }, \ + { "uspace", CTLTYPE_INT }, \ + { "malloc_conf", CTLTYPE_STRING }, \ +} + +/* + * uvmexp: global data structures that are exported to parts of the kernel + * other than the vm system. + * + * Locks used to protect struct members in this file: + * a atomic operations + * I immutable after creation + * K kernel lock + * F uvm_lock_fpageq + * L uvm_lock_pageq + * S uvm_swap_data_lock + * p copy of per-CPU counters, used only by userland. + */ +struct uvmexp { + /* vm_page constants */ + int pagesize; /* size of a page (PAGE_SIZE): must be power of 2 */ + int pagemask; /* page mask */ + int pageshift; /* page shift */ + + /* vm_page counters */ + int npages; /* [I] number of pages we manage */ + int free; /* [F] number of free pages */ + int active; /* [L] # of active pages */ + int inactive; /* [L] # of pages that we free'd but may want back */ + int paging; /* [a] # of pages in the process of being paged out */ + int wired; /* [a] number of wired pages */ + + int zeropages; /* [F] number of zero'd pages */ + int reserve_pagedaemon; /* [I] # of pages reserved for pagedaemon */ + int reserve_kernel; /* [I] # of pages reserved for kernel */ + int percpucaches; /* [a] # of pages in per-CPU caches */ + int vnodepages; /* XXX # of pages used by vnode page cache */ + int vtextpages; /* XXX # of pages used by vtext vnodes */ + + /* pageout params */ + int freemin; /* [I] min number of free pages */ + int freetarg; /* [I] target number of free pages */ + int inactarg; /* target number of inactive pages */ + int wiredmax; /* [I] max number of wired pages */ + int anonmin; /* min threshold for anon pages */ + int vtextmin; /* min threshold for vtext pages */ + int vnodemin; /* min threshold for vnode pages */ + int anonminpct; /* min percent anon pages */ + int vtextminpct;/* min percent vtext pages */ + int vnodeminpct;/* min percent vnode pages */ + + /* swap */ + int nswapdev; /* [S] number of configured swap devices in system */ + int swpages; /* [S] number of PAGE_SIZE'ed swap pages */ + int swpginuse; /* [S] number of swap pages in use */ + int swpgonly; /* [a] number of swap pages in use, not also in RAM */ + int nswget; /* [a] number of swap pages moved from disk to RAM */ + int nanon; /* XXX number total of anon's in system */ + int unused05; /* formerly nanonneeded */ + int unused06; /* formerly nfreeanon */ + + /* stat counters */ + int faults; /* [p] page fault count */ + int traps; /* trap count */ + int intrs; /* interrupt count */ + int swtch; /* context switch count */ + int softs; /* software interrupt count */ + int syscalls; /* system calls */ + int pageins; /* [p] pagein operation count */ + /* pageouts are in pdpageouts below */ + int pcphit; /* [a] # of pagealloc from per-CPU cache */ + int pcpmiss; /* [a] # of times a per-CPU cache was empty */ + int pgswapin; /* pages swapped in */ + int pgswapout; /* pages swapped out */ + int forks; /* forks */ + int forks_ppwait; /* forks where parent waits */ + int forks_sharevm; /* forks where vmspace is shared */ + int pga_zerohit; /* pagealloc where zero wanted and zero + was available */ + int pga_zeromiss; /* pagealloc where zero wanted and zero + not available */ + int unused09; /* formerly zeroaborts */ + + /* fault subcounters */ + int fltnoram; /* [p] # of times fault was out of ram */ + int fltnoanon; /* [p] # of times fault was out of anons */ + int fltnoamap; /* [p] # of times fault was out of amap chunks */ + int fltpgwait; /* [p] # of times fault had to wait on a page */ + int fltpgrele; /* [p] # of times fault found a released page */ + int fltrelck; /* [p] # of times fault relock is a success */ + int fltnorelck; /* [p] # of times fault relock failed */ + int fltanget; /* [p] # of times fault gets anon page */ + int fltanretry; /* [p] # of times fault retrys an anon get */ + int fltamcopy; /* [p] # of times fault clears "needs copy" */ + int fltnamap; /* [p] # of times fault maps a neighbor anon page */ + int fltnomap; /* [p] # of times fault maps a neighbor obj page */ + int fltlget; /* [p] # of times fault does a locked pgo_get */ + int fltget; /* [p] # of times fault does an unlocked get */ + int flt_anon; /* [p] # of times fault anon (case 1a) */ + int flt_acow; /* [p] # of times fault anon cow (case 1b) */ + int flt_obj; /* [p] # of times fault is on object page (2a) */ + int flt_prcopy; /* [p] # of times fault promotes with copy (2b) */ + int flt_przero; /* [p] # of times fault promotes with zerofill (2b) */ + int fltup; /* [p] # of times fault upgrade is a success */ + int fltnoup; /* [p] # of times fault upgrade failed */ + + /* daemon counters */ + int pdwoke; /* [F] # of times daemon woke up */ + int pdrevs; /* number of times daemon scanned for free pages */ + int pdswout; /* number of times daemon called for swapout */ + int pdfreed; /* number of pages daemon freed since boot */ + int pdscans; /* number of pages daemon scanned since boot */ + int pdanscan; /* number of anonymous pages scanned by daemon */ + int pdobscan; /* number of object pages scanned by daemon */ + int pdreact; /* number of pages daemon reactivated since boot */ + int pdbusy; /* number of times daemon found a busy page */ + int pdpageouts; /* number of times daemon started a pageout */ + int pdpending; /* number of times daemon got a pending pagout */ + int pddeact; /* number of pages daemon deactivates */ + + int unused13; /* formerly pdrevtext */ + + int fpswtch; /* FPU context switches */ + int kmapent; /* number of kernel map entries */ +}; + +struct _ps_strings { + void *val; +}; + +#ifdef _KERNEL + +/* + * Per-cpu UVM counters. + */ +extern struct cpumem *uvmexp_counters; + +enum uvm_exp_counters { + /* stat counters */ + faults, /* page fault count */ + pageins, /* pagein operation count */ + + /* fault subcounters */ + flt_noram, /* number of times fault was out of ram */ + flt_noanon, /* number of times fault was out of anons */ + flt_noamap, /* number of times fault was out of amap chunks */ + flt_pgwait, /* number of times fault had to wait on a page */ + flt_pgrele, /* number of times fault found a released page */ + flt_relck, /* number of times fault relock is a success */ + flt_norelck, /* number of times fault relock failed */ + flt_anget, /* number of times fault gets anon page */ + flt_anretry, /* number of times fault retrys an anon get */ + flt_amcopy, /* number of times fault clears "needs copy" */ + flt_namap, /* number of times fault maps a neighbor anon page */ + flt_nomap, /* number of times fault maps a neighbor obj page */ + flt_lget, /* number of times fault does a locked pgo_get */ + flt_get, /* number of times fault does an unlocked get */ + flt_anon, /* number of times fault anon (case 1a) */ + flt_acow, /* number of times fault anon cow (case 1b) */ + flt_obj, /* number of times fault is on object page (2a) */ + flt_prcopy, /* number of times fault promotes with copy (2b) */ + flt_przero, /* number of times fault promotes with zerofill (2b) */ + flt_up, /* number of times fault upgrade is a success */ + flt_noup, /* number of times fault upgrade failed */ + + exp_ncounters +}; + +#endif /* _KERNEL */ +#endif /*_UVM_UVMEXP_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/varargs.h b/lib/libc/include/generic-openbsd/varargs.h new file mode 100644 index 000000000000..0f3d2c690af6 --- /dev/null +++ b/lib/libc/include/generic-openbsd/varargs.h @@ -0,0 +1,51 @@ +/* $OpenBSD: varargs.h,v 1.4 2020/07/21 23:09:00 daniel Exp $ */ +/* + * Copyright (c) 2003, 2004 Marc espie + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _VARARGS_H_ +#define _VARARGS_H_ + +/* These macros implement traditional (non-ANSI) varargs + for GNU C. */ + +#define va_alist __builtin_va_alist + +#define __va_ellipsis ... + +/* ??? We don't process attributes correctly in K&R argument context. */ +typedef int __builtin_va_alist_t __attribute__((__mode__(__word__))); + +/* ??? It would be nice to get rid of the ellipsis here. It causes + current_function_varargs to be set in cc1. */ +#define va_dcl __builtin_va_alist_t __builtin_va_alist; ... + +/* Define __gnuc_va_list, just as in stdarg.h. */ + +#ifndef __GNUC_VA_LIST +#define __GNUC_VA_LIST +typedef __builtin_va_list __gnuc_va_list; +#endif + +#define va_start(v) __builtin_varargs_start((v)) +#define va_end __builtin_va_end +#define va_arg __builtin_va_arg +#define __va_copy(d,s) __builtin_va_copy((d),(s)) + +/* Define va_list from __gnuc_va_list. */ + +typedef __gnuc_va_list va_list; + +#endif /* _VARARGS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/vis.h b/lib/libc/include/generic-openbsd/vis.h new file mode 100644 index 000000000000..132089a724c8 --- /dev/null +++ b/lib/libc/include/generic-openbsd/vis.h @@ -0,0 +1,93 @@ +/* $OpenBSD: vis.h,v 1.15 2015/07/20 01:52:27 millert Exp $ */ +/* $NetBSD: vis.h,v 1.4 1994/10/26 00:56:41 cgd Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vis.h 5.9 (Berkeley) 4/3/91 + */ + +#ifndef _VIS_H_ +#define _VIS_H_ + +/* + * to select alternate encoding format + */ +#define VIS_OCTAL 0x01 /* use octal \ddd format */ +#define VIS_CSTYLE 0x02 /* use \[nrft0..] where appropriate */ + +/* + * to alter set of characters encoded (default is to encode all + * non-graphic except space, tab, and newline). + */ +#define VIS_SP 0x04 /* also encode space */ +#define VIS_TAB 0x08 /* also encode tab */ +#define VIS_NL 0x10 /* also encode newline */ +#define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL) +#define VIS_SAFE 0x20 /* only encode "unsafe" characters */ +#define VIS_DQ 0x200 /* backslash-escape double quotes */ +#define VIS_ALL 0x400 /* encode all characters */ + +/* + * other + */ +#define VIS_NOSLASH 0x40 /* inhibit printing '\' */ +#define VIS_GLOB 0x100 /* encode glob(3) magics and '#' */ + +/* + * unvis return codes + */ +#define UNVIS_VALID 1 /* character valid */ +#define UNVIS_VALIDPUSH 2 /* character valid, push back passed char */ +#define UNVIS_NOCHAR 3 /* valid sequence, no character produced */ +#define UNVIS_SYNBAD -1 /* unrecognized escape sequence */ +#define UNVIS_ERROR -2 /* decoder in unknown state (unrecoverable) */ + +/* + * unvis flags + */ +#define UNVIS_END 1 /* no more characters */ + +#include + +__BEGIN_DECLS +char *vis(char *, int, int, int); +int strvis(char *, const char *, int); +int stravis(char **, const char *, int); +int strnvis(char *, const char *, size_t, int) + __attribute__ ((__bounded__(__string__,1,3))); +int strvisx(char *, const char *, size_t, int) + __attribute__ ((__bounded__(__string__,1,3))); +int strunvis(char *, const char *); +int unvis(char *, char, int *, int); +ssize_t strnunvis(char *, const char *, size_t) + __attribute__ ((__bounded__(__string__,1,3))); + +__END_DECLS + +#endif /* !_VIS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/wchar.h b/lib/libc/include/generic-openbsd/wchar.h new file mode 100644 index 000000000000..bfcefc4340d7 --- /dev/null +++ b/lib/libc/include/generic-openbsd/wchar.h @@ -0,0 +1,253 @@ +/* $OpenBSD: wchar.h,v 1.34 2025/07/16 15:33:05 yasuoka Exp $ */ +/* $NetBSD: wchar.h,v 1.16 2003/03/07 07:11:35 tshiozak Exp $ */ + +/*- + * Copyright (c)1999 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Julian Coleman. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _WCHAR_H_ +#define _WCHAR_H_ + +#include +#include +#include + +#ifndef _STDFILES_DECLARED +#define _STDFILES_DECLARED +typedef struct __sFILE FILE; +struct __sFstub { long _stub; }; + +__BEGIN_DECLS +extern struct __sFstub __stdin[]; +extern struct __sFstub __stdout[]; +extern struct __sFstub __stderr[]; +__END_DECLS +#endif + +#if !defined(_WCHAR_T_DEFINED_) && !defined(__cplusplus) +#define _WCHAR_T_DEFINED_ +typedef __wchar_t wchar_t; +#endif + +#ifndef _MBSTATE_T_DEFINED_ +#define _MBSTATE_T_DEFINED_ +typedef __mbstate_t mbstate_t; +#endif + +#ifndef _WINT_T_DEFINED_ +#define _WINT_T_DEFINED_ +typedef __wint_t wint_t; +#endif + +#ifndef _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED_ +typedef __size_t size_t; +#endif + +#ifndef WEOF +#define WEOF ((wint_t)-1) +#endif + +#ifndef WCHAR_MIN +#define WCHAR_MIN (-0x7fffffff - 1) +#endif +#ifndef WCHAR_MAX +#define WCHAR_MAX 0x7fffffff +#endif + +#if __POSIX_VISIBLE >= 200809 +#ifndef _LOCALE_T_DEFINED_ +#define _LOCALE_T_DEFINED_ +typedef void *locale_t; +#endif +#endif + +__BEGIN_DECLS +wint_t btowc(int); +size_t mbrlen(const char * __restrict, size_t, mbstate_t * __restrict); +size_t mbrtowc(wchar_t * __restrict, const char * __restrict, size_t, + mbstate_t * __restrict); +int mbsinit(const mbstate_t *); +size_t mbsrtowcs(wchar_t * __restrict, const char ** __restrict, size_t, + mbstate_t * __restrict) + __attribute__ ((__bounded__(__wcstring__,1,3))); +size_t wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict); +wchar_t *wcscat(wchar_t * __restrict, const wchar_t * __restrict); +wchar_t *wcschr(const wchar_t *, wchar_t); +int wcscmp(const wchar_t *, const wchar_t *); +int wcscoll(const wchar_t *, const wchar_t *); +wchar_t *wcscpy(wchar_t * __restrict, const wchar_t * __restrict); +size_t wcscspn(const wchar_t *, const wchar_t *); +size_t wcslen(const wchar_t *); +wchar_t *wcsncat(wchar_t * __restrict, const wchar_t * __restrict, + size_t) + __attribute__ ((__bounded__(__wcstring__,1,3))); +int wcsncmp(const wchar_t *, const wchar_t *, size_t); +wchar_t *wcsncpy(wchar_t * __restrict , const wchar_t * __restrict, + size_t) + __attribute__ ((__bounded__(__wcstring__,1,3))); +wchar_t *wcspbrk(const wchar_t *, const wchar_t *); +wchar_t *wcsrchr(const wchar_t *, wchar_t); +size_t wcsrtombs(char * __restrict, const wchar_t ** __restrict, size_t, + mbstate_t * __restrict) + __attribute__ ((__bounded__(__wcstring__,1,3))); +size_t wcsspn(const wchar_t *, const wchar_t *); +wchar_t *wcsstr(const wchar_t *, const wchar_t *); +wchar_t *wcstok(wchar_t * __restrict, const wchar_t * __restrict, + wchar_t ** __restrict); +size_t wcsxfrm(wchar_t *, const wchar_t *, size_t); +wchar_t *wcswcs(const wchar_t *, const wchar_t *); +wchar_t *wmemchr(const wchar_t *, wchar_t, size_t); +int wmemcmp(const wchar_t *, const wchar_t *, size_t); +wchar_t *wmemcpy(wchar_t * __restrict, const wchar_t * __restrict, + size_t) + __attribute__ ((__bounded__(__wcstring__,1,3))) + __attribute__ ((__bounded__(__wcstring__,2,3))); +wchar_t *wmemmove(wchar_t *, const wchar_t *, size_t) + __attribute__ ((__bounded__(__wcstring__,1,3))) + __attribute__ ((__bounded__(__wcstring__,2,3))); +wchar_t *wmemset(wchar_t *, wchar_t, size_t) + __attribute__ ((__bounded__(__wcstring__,1,3))); + +int wcswidth(const wchar_t *, size_t); +int wctob(wint_t); +int wcwidth(wchar_t); + +double wcstod(const wchar_t * __restrict, wchar_t ** __restrict); +long int wcstol(const wchar_t * __restrict, wchar_t ** __restrict, int base); +unsigned long int wcstoul(const wchar_t * __restrict, wchar_t ** __restrict, + int base); + +#if __POSIX_VISIBLE >= 200809 +FILE *open_wmemstream(wchar_t **, size_t *); + +int wcscoll_l(const wchar_t *, const wchar_t *, locale_t); +wchar_t *wcsdup(const wchar_t *); +int wcscasecmp(const wchar_t *, const wchar_t *); +int wcscasecmp_l(const wchar_t *, const wchar_t *, locale_t); +size_t wcsnlen(const wchar_t *, size_t); +int wcsncasecmp(const wchar_t *, const wchar_t *, size_t); +int wcsncasecmp_l(const wchar_t *, const wchar_t *, size_t, locale_t); +size_t wcsxfrm_l(wchar_t *, const wchar_t *, size_t, locale_t); + +size_t mbsnrtowcs(wchar_t * __restrict, const char ** __restrict, size_t, + size_t, mbstate_t * __restrict) + __attribute__ ((__bounded__(__wcstring__,1,4))); +size_t wcsnrtombs(char * __restrict, const wchar_t ** __restrict, size_t, + size_t, mbstate_t * __restrict) + __attribute__ ((__bounded__(__wcstring__,1,4))); +#endif + +#if __ISO_C_VISIBLE >= 1999 +float wcstof(const wchar_t * __restrict, wchar_t ** __restrict); +long double wcstold(const wchar_t * __restrict, wchar_t ** __restrict); + +struct tm; +size_t wcsftime(wchar_t * __restrict, size_t, const wchar_t *__restrict, + const struct tm *__restrict); +#endif + +#if !defined(__STRICT_ANSI__) || __ISO_C_VISIBLE >= 1999 +long long int wcstoll(const wchar_t * __restrict, + wchar_t ** __restrict, int base); +unsigned long long int wcstoull(const wchar_t * __restrict, + wchar_t ** __restrict, int base); +#endif + +wint_t ungetwc(wint_t, FILE *); +wint_t fgetwc(FILE *); +wchar_t *fgetws(wchar_t * __restrict, int, FILE * __restrict) + __attribute__ ((__bounded__(__wcstring__,1,2))); +wint_t getwc(FILE *); +wint_t getwchar(void); +wint_t fputwc(wchar_t, FILE *); +int fputws(const wchar_t * __restrict, FILE * __restrict); +wint_t putwc(wchar_t, FILE *); +wint_t putwchar(wchar_t); + +int fwide(FILE *, int); + +int fwprintf(FILE * __restrict, const wchar_t * __restrict, ...); +int swprintf(wchar_t * __restrict, size_t, const wchar_t * __restrict, ...); +int vfwprintf(FILE * __restrict, const wchar_t * __restrict, __va_list); +int vswprintf(wchar_t * __restrict, size_t, const wchar_t * __restrict, + __va_list); +int vwprintf(const wchar_t * __restrict, __va_list); +int wprintf(const wchar_t * __restrict, ...); + +int fwscanf(FILE * __restrict, const wchar_t * __restrict, ...); +int swscanf(const wchar_t * __restrict, const wchar_t * __restrict, ...); +int vfwscanf(FILE * __restrict, const wchar_t * __restrict, __va_list); +int vswscanf(const wchar_t * __restrict, const wchar_t * __restrict, __va_list); +int vwscanf(const wchar_t * __restrict, __va_list); +int wscanf(const wchar_t * __restrict, ...); + +#if __POSIX_VISIBLE >= 202405 || __BSD_VISIBLE +size_t wcslcat(wchar_t * __restrict, const wchar_t * __restrict, size_t) + __attribute__ ((__bounded__(__wcstring__,1,3))); +size_t wcslcpy(wchar_t * __restrict, const wchar_t * __restrict, size_t) + __attribute__ ((__bounded__(__wcstring__,1,3))); +#endif + +#if __BSD_VISIBLE +wchar_t *fgetwln(FILE * __restrict, size_t * __restrict); +#endif + +#define getwc(f) fgetwc(f) +#define getwchar() getwc((FILE *)__stdin) +#define putwc(wc, f) fputwc((wc), (f)) +#define putwchar(wc) putwc((wc), (FILE *)__stdout) +__END_DECLS + +#endif /* !_WCHAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-openbsd/wctype.h b/lib/libc/include/generic-openbsd/wctype.h new file mode 100644 index 000000000000..0d95b5fb2c95 --- /dev/null +++ b/lib/libc/include/generic-openbsd/wctype.h @@ -0,0 +1,107 @@ +/* $OpenBSD: wctype.h,v 1.6 2017/09/05 03:16:13 schwarze Exp $ */ +/* $NetBSD: wctype.h,v 1.5 2003/03/02 22:18:11 tshiozak Exp $ */ + +/*- + * Copyright (c)1999 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * citrus Id: wctype.h,v 1.4 2000/12/21 01:50:21 itojun Exp + */ + +#ifndef _WCTYPE_H_ +#define _WCTYPE_H_ + +#include +#include + +#ifndef _WINT_T_DEFINED_ +#define _WINT_T_DEFINED_ +typedef __wint_t wint_t; +#endif + +#ifndef _WCTRANS_T_DEFINED_ +#define _WCTRANS_T_DEFINED_ +typedef __wctrans_t wctrans_t; +#endif + +#ifndef _WCTYPE_T_DEFINED_ +#define _WCTYPE_T_DEFINED_ +typedef __wctype_t wctype_t; +#endif + +#ifndef WEOF +#define WEOF ((wint_t)-1) +#endif + +#if __POSIX_VISIBLE >= 200809 +#ifndef _LOCALE_T_DEFINED_ +#define _LOCALE_T_DEFINED_ +typedef void *locale_t; +#endif +#endif + +__BEGIN_DECLS +int iswalnum(wint_t); +int iswalpha(wint_t); +int iswblank(wint_t); +int iswcntrl(wint_t); +int iswdigit(wint_t); +int iswgraph(wint_t); +int iswlower(wint_t); +int iswprint(wint_t); +int iswpunct(wint_t); +int iswspace(wint_t); +int iswupper(wint_t); +int iswxdigit(wint_t); +int iswctype(wint_t, wctype_t); +wint_t towctrans(wint_t, wctrans_t); +wint_t towlower(wint_t); +wint_t towupper(wint_t); +wctrans_t wctrans(const char *); +wctype_t wctype(const char *); + +#if __POSIX_VISIBLE >= 200809 +int iswalnum_l(wint_t, locale_t); +int iswalpha_l(wint_t, locale_t); +int iswblank_l(wint_t, locale_t); +int iswcntrl_l(wint_t, locale_t); +int iswdigit_l(wint_t, locale_t); +int iswgraph_l(wint_t, locale_t); +int iswlower_l(wint_t, locale_t); +int iswprint_l(wint_t, locale_t); +int iswpunct_l(wint_t, locale_t); +int iswspace_l(wint_t, locale_t); +int iswupper_l(wint_t, locale_t); +int iswxdigit_l(wint_t, locale_t); +int iswctype_l(wint_t, wctype_t, locale_t); +wint_t towctrans_l(wint_t, wctrans_t, locale_t); +wint_t towlower_l(wint_t, locale_t); +wint_t towupper_l(wint_t, locale_t); +wctrans_t wctrans_l(const char *, locale_t); +wctype_t wctype_l(const char *, locale_t); +#endif + +__END_DECLS + +#endif /* _WCTYPE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/frame.h b/lib/libc/include/mips64-openbsd-none/frame.h new file mode 100644 index 000000000000..f8295979a3c4 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/frame.h @@ -0,0 +1,3 @@ +/* $OpenBSD: frame.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/_types.h b/lib/libc/include/mips64-openbsd-none/machine/_types.h new file mode 100644 index 000000000000..12dbcd35ee5f --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/_types.h @@ -0,0 +1,3 @@ +/* $OpenBSD: _types.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/asm.h b/lib/libc/include/mips64-openbsd-none/machine/asm.h new file mode 100644 index 000000000000..a7660ee6410b --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/asm.h @@ -0,0 +1,9 @@ +/* $OpenBSD: asm.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ + +#ifdef MULTIPROCESSOR +#define HW_GET_CPU_INFO(ci, tmp) \ + dmfc0 ci, COP_0_ERROR_PC +#endif + +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/atomic.h b/lib/libc/include/mips64-openbsd-none/machine/atomic.h new file mode 100644 index 000000000000..1d56c3a0008c --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/atomic.h @@ -0,0 +1,45 @@ +/* $OpenBSD: atomic.h,v 1.3 2020/07/08 15:53:59 visa Exp $ */ + +/* + * Copyright (c) 2017 Visa Hankala + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _OCTEON_ATOMIC_H_ +#define _OCTEON_ATOMIC_H_ + +#ifdef _KERNEL + +static inline void +octeon_syncw(void) +{ + __asm__ volatile ( + " .set push\n" + " .set arch=octeon\n" + /* Issue the barrier twice to work around CN3xxx erratum Core-401. + * A single syncw might not enforce write ordering properly. */ + " syncw\n" + " syncw\n" + " .set pop\n" + : : : "memory"); +} + +#define membar_consumer() __asm__ volatile ("" : : : "memory") +#define membar_producer() octeon_syncw() + +#endif /* _KERNEL */ + +#include + +#endif /* !_OCTEON_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/autoconf.h b/lib/libc/include/mips64-openbsd-none/machine/autoconf.h new file mode 100644 index 000000000000..0b9aa66be992 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/autoconf.h @@ -0,0 +1,58 @@ +/* $OpenBSD: autoconf.h,v 1.4 2019/07/12 03:03:48 visa Exp $ */ + +/* + * Copyright (c) 2001-2003 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * Definitions used by autoconfiguration. + */ + +#ifndef _MACHINE_AUTOCONF_H_ +#define _MACHINE_AUTOCONF_H_ + +#include + +struct mainbus_attach_args { + const char *maa_name; +}; + +extern struct device *bootdv; +extern char bootdev[]; +extern char uboot_rootdev[]; +extern enum devclass bootdev_class; + +#include + +void com_fdt_init_cons(void); +void parse_uboot_root(const char *); + +extern unsigned int octeon_ver; +#define OCTEON_1 0 +#define OCTEON_PLUS 1 +#define OCTEON_2 2 +#define OCTEON_3 3 + +#endif /* _MACHINE_AUTOCONF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/bus.h b/lib/libc/include/mips64-openbsd-none/machine/bus.h new file mode 100644 index 000000000000..257157af06db --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/bus.h @@ -0,0 +1,510 @@ +/* $OpenBSD: bus.h,v 1.8 2020/04/14 17:35:28 kettenis Exp $ */ + +/* + * Copyright (c) 2003-2004 Opsycon AB Sweden. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BUS_H_ +#define _MACHINE_BUS_H_ + +#ifdef __STDC__ +#define CAT(a,b) a##b +#define CAT3(a,b,c) a##b##c +#else +#define CAT(a,b) a/**/b +#define CAT3(a,b,c) a/**/b/**/c +#endif + +/* + * Bus access types. + */ +struct mips_bus_space; +typedef u_long bus_addr_t; +typedef u_long bus_size_t; +typedef u_long bus_space_handle_t; +typedef struct mips_bus_space *bus_space_tag_t; +typedef struct mips_bus_space bus_space_t; + +struct mips_bus_space { + bus_addr_t bus_base; + void *bus_private; + u_int8_t (*_space_read_1)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_1)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int8_t); + u_int16_t (*_space_read_2)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_2)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int16_t); + u_int32_t (*_space_read_4)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_4)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int32_t); + u_int64_t (*_space_read_8)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_8)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int64_t); + void (*_space_read_raw_2)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_2)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + void (*_space_read_raw_4)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_4)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + void (*_space_read_raw_8)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_8)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + int (*_space_map)(bus_space_tag_t , bus_addr_t, + bus_size_t, int, bus_space_handle_t *); + void (*_space_unmap)(bus_space_tag_t, bus_space_handle_t, + bus_size_t); + int (*_space_subregion)(bus_space_tag_t, bus_space_handle_t, + bus_size_t, bus_size_t, bus_space_handle_t *); + void * (*_space_vaddr)(bus_space_tag_t, bus_space_handle_t); +}; + +#define bus_space_read_1(t, h, o) (*(t)->_space_read_1)((t), (h), (o)) +#define bus_space_read_2(t, h, o) (*(t)->_space_read_2)((t), (h), (o)) +#define bus_space_read_4(t, h, o) (*(t)->_space_read_4)((t), (h), (o)) +#define bus_space_read_8(t, h, o) (*(t)->_space_read_8)((t), (h), (o)) + +#define bus_space_write_1(t, h, o, v) (*(t)->_space_write_1)((t), (h), (o), (v)) +#define bus_space_write_2(t, h, o, v) (*(t)->_space_write_2)((t), (h), (o), (v)) +#define bus_space_write_4(t, h, o, v) (*(t)->_space_write_4)((t), (h), (o), (v)) +#define bus_space_write_8(t, h, o, v) (*(t)->_space_write_8)((t), (h), (o), (v)) + +#define bus_space_read_raw_multi_2(t, h, a, b, l) \ + (*(t)->_space_read_raw_2)((t), (h), (a), (b), (l)) +#define bus_space_read_raw_multi_4(t, h, a, b, l) \ + (*(t)->_space_read_raw_4)((t), (h), (a), (b), (l)) +#define bus_space_read_raw_multi_8(t, h, a, b, l) \ + (*(t)->_space_read_raw_8)((t), (h), (a), (b), (l)) + +#define bus_space_write_raw_multi_2(t, h, a, b, l) \ + (*(t)->_space_write_raw_2)((t), (h), (a), (b), (l)) +#define bus_space_write_raw_multi_4(t, h, a, b, l) \ + (*(t)->_space_write_raw_4)((t), (h), (a), (b), (l)) +#define bus_space_write_raw_multi_8(t, h, a, b, l) \ + (*(t)->_space_write_raw_8)((t), (h), (a), (b), (l)) + +#define bus_space_map(t, o, s, c, p) (*(t)->_space_map)((t), (o), (s), (c), (p)) +#define bus_space_unmap(t, h, s) (*(t)->_space_unmap)((t), (h), (s)) +#define bus_space_subregion(t, h, o, s, p) \ + (*(t)->_space_subregion)((t), (h), (o), (s), (p)) + +#define BUS_SPACE_MAP_CACHEABLE 0x01 +#define BUS_SPACE_MAP_KSEG0 0x02 +#define BUS_SPACE_MAP_LINEAR 0x04 +#define BUS_SPACE_MAP_PREFETCHABLE 0x08 + +#define bus_space_vaddr(t, h) (*(t)->_space_vaddr)((t), (h)) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_multi(n,m) \ +static __inline void \ +CAT(bus_space_read_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t o, CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) \ + *x++ = CAT(bus_space_read_,n)(bst, bsh, o); \ +} + +bus_space_read_multi(1,8) +bus_space_read_multi(2,16) +bus_space_read_multi(4,32) +bus_space_read_multi(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_region(n,m) \ +static __inline void \ +CAT(bus_space_read_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) { \ + *x++ = CAT(bus_space_read_,n)(bst, bsh, ba); \ + ba += (n); \ + } \ +} + +bus_space_read_region(1,8) +bus_space_read_region(2,16) +bus_space_read_region(4,32) +bus_space_read_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_raw_region(n,m) \ +static __inline void \ +CAT(bus_space_read_raw_region_,n)(bus_space_tag_t bst, \ + bus_space_handle_t bsh, \ + bus_addr_t ba, u_int8_t *x, size_t cnt) \ +{ \ + cnt >>= ((n) >> 1); \ + while (cnt--) { \ + CAT(bus_space_read_raw_multi_,n)(bst, bsh, ba, x, (n)); \ + ba += (n); \ + x += (n); \ + } \ +} + +bus_space_read_raw_region(2,16) +bus_space_read_raw_region(4,32) +bus_space_read_raw_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_multi(n,m) \ +static __inline void \ +CAT(bus_space_write_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t o, const CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) \ + CAT(bus_space_write_,n)(bst, bsh, o, *x++); \ +} + +bus_space_write_multi(1,8) +bus_space_write_multi(2,16) +bus_space_write_multi(4,32) +bus_space_write_multi(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_region(n,m) \ +static __inline void \ +CAT(bus_space_write_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, const CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) { \ + CAT(bus_space_write_,n)(bst, bsh, ba, *x++); \ + ba += (n); \ + } \ +} + +bus_space_write_region(1,8) +bus_space_write_region(2,16) +bus_space_write_region(4,32) +bus_space_write_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_raw_region(n,m) \ +static __inline void \ +CAT(bus_space_write_raw_region_,n)(bus_space_tag_t bst, \ + bus_space_handle_t bsh, \ + bus_addr_t ba, const u_int8_t *x, size_t cnt) \ +{ \ + cnt >>= ((n) >> 1); \ + while (cnt--) { \ + CAT(bus_space_write_raw_multi_,n)(bst, bsh, ba, x, (n)); \ + ba += (n); \ + x += (n); \ + } \ +} + +bus_space_write_raw_region(2,16) +bus_space_write_raw_region(4,32) +bus_space_write_raw_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_set_region(n,m) \ +static __inline void \ +CAT(bus_space_set_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(u_int,m,_t) x, size_t cnt) \ +{ \ + while (cnt--) { \ + CAT(bus_space_write_,n)(bst, bsh, ba, x); \ + ba += (n); \ + } \ +} + +bus_space_set_region(1,8) +bus_space_set_region(2,16) +bus_space_set_region(4,32) +bus_space_set_region(8,64) + +/*----------------------------------------------------------------------------*/ +static __inline void +bus_space_copy_1(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + char *s = (char *)(h1 + o1); + char *d = (char *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + + +static __inline void +bus_space_copy_2(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + short *s = (short *)(h1 + o1); + short *d = (short *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + +static __inline void +bus_space_copy_4(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + int *s = (int *)(h1 + o1); + int *d = (int *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + +static __inline void +bus_space_copy_8(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + int64_t *s = (int64_t *)(h1 + o1); + int64_t *d = (int64_t *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + +/*----------------------------------------------------------------------------*/ +/* + * Bus read/write barrier methods. + * + * void bus_space_barrier(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * bus_size_t len, int flags); + * + */ +static inline void +bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, + bus_size_t length, int flags) +{ + __asm__ volatile ("sync" ::: "memory"); +} +#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ +#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ + +#define BUS_DMA_WAITOK 0x0000 +#define BUS_DMA_NOWAIT 0x0001 +#define BUS_DMA_ALLOCNOW 0x0002 +#define BUS_DMA_COHERENT 0x0008 +#define BUS_DMA_BUS1 0x0010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x0020 +#define BUS_DMA_BUS3 0x0040 +#define BUS_DMA_BUS4 0x0080 +#define BUS_DMA_READ 0x0100 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x0200 /* mapping is memory -> device only */ +#define BUS_DMA_STREAMING 0x0400 /* hint: sequential, unidirectional */ +#define BUS_DMA_ZERO 0x0800 /* zero memory in dmamem_alloc */ +#define BUS_DMA_NOCACHE 0x1000 +#define BUS_DMA_64BIT 0x2000 /* device handles 64bit dva */ + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct proc; +struct uio; + +#define BUS_DMASYNC_POSTREAD 0x0001 +#define BUS_DMASYNC_POSTWRITE 0x0002 +#define BUS_DMASYNC_PREREAD 0x0004 +#define BUS_DMASYNC_PREWRITE 0x0008 + +typedef struct machine_bus_dma_tag *bus_dma_tag_t; +typedef struct machine_bus_dmamap *bus_dmamap_t; + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +struct machine_bus_dma_segment { + bus_addr_t ds_addr; /* DMA address */ + bus_size_t ds_len; /* length of transfer */ + + paddr_t _ds_paddr; /* CPU address */ + vaddr_t _ds_vaddr; /* CPU address */ +}; +typedef struct machine_bus_dma_segment bus_dma_segment_t; + +/* + * bus_dma_tag_t + * + * A machine-dependent opaque type describing the implementation of + * DMA for a given bus. + */ + +struct machine_bus_dma_tag { + void *_cookie; /* cookie used in the guts */ + + /* + * DMA mapping methods. + */ + int (*_dmamap_create)(bus_dma_tag_t , bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); + void (*_dmamap_destroy)(bus_dma_tag_t , bus_dmamap_t); + int (*_dmamap_load)(bus_dma_tag_t , bus_dmamap_t, void *, + bus_size_t, struct proc *, int); + int (*_dmamap_load_mbuf)(bus_dma_tag_t , bus_dmamap_t, + struct mbuf *, int); + int (*_dmamap_load_uio)(bus_dma_tag_t , bus_dmamap_t, + struct uio *, int); + int (*_dmamap_load_raw)(bus_dma_tag_t , bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); + int (*_dmamap_load_buffer)(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int, paddr_t *, int *, int); + void (*_dmamap_unload)(bus_dma_tag_t , bus_dmamap_t); + void (*_dmamap_sync)(bus_dma_tag_t , bus_dmamap_t, + bus_addr_t, bus_size_t, int); + + /* + * DMA memory utility functions. + */ + int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); + void (*_dmamem_free)(bus_dma_tag_t, bus_dma_segment_t *, int); + int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); + void (*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t); + paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, + int, off_t, int, int); + + /* + * internal memory address translation information. + */ + bus_addr_t (*_pa_to_device)(paddr_t); + paddr_t (*_device_to_pa)(bus_addr_t); + bus_addr_t _dma_mask; +}; + +#define bus_dmamap_create(t, s, n, m, b, f, p) \ + (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) +#define bus_dmamap_destroy(t, p) \ + (*(t)->_dmamap_destroy)((t), (p)) +#define bus_dmamap_load(t, m, b, s, p, f) \ + (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) +#define bus_dmamap_load_mbuf(t, m, b, f) \ + (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) +#define bus_dmamap_load_uio(t, m, u, f) \ + (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) +#define bus_dmamap_load_raw(t, m, sg, n, s, f) \ + (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) +#define bus_dmamap_unload(t, p) \ + (*(t)->_dmamap_unload)((t), (p)) +#define bus_dmamap_sync(t, p, a, l, o) \ + (void)((t)->_dmamap_sync ? \ + (*(t)->_dmamap_sync)((t), (p), (a), (l), (o)) : (void)0) + +#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ + (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f)) +#define bus_dmamem_free(t, sg, n) \ + (*(t)->_dmamem_free)((t), (sg), (n)) +#define bus_dmamem_map(t, sg, n, s, k, f) \ + (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f)) +#define bus_dmamem_unmap(t, k, s) \ + (*(t)->_dmamem_unmap)((t), (k), (s)) +#define bus_dmamem_mmap(t, sg, n, o, p, f) \ + (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f)) + +int _dmamap_create(bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); +void _dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); +int _dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); +int _dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *, int); +int _dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, struct uio *, int); +int _dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); +int _dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int, paddr_t *, int *, int); +void _dmamap_unload(bus_dma_tag_t, bus_dmamap_t); +void _dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, + bus_size_t, int); + +int _dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); +void _dmamem_free(bus_dma_tag_t, bus_dma_segment_t *, int); +int _dmamem_map(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); +void _dmamem_unmap(bus_dma_tag_t, caddr_t, size_t); +paddr_t _dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, int, int); +int _dmamem_alloc_range(bus_dma_tag_t, bus_size_t, bus_size_t, bus_size_t, + bus_dma_segment_t *, int, int *, int, paddr_t, paddr_t); + +/* + * bus_dmamap_t + * + * Describes a DMA mapping. + */ +struct machine_bus_dmamap { + /* + * PRIVATE MEMBERS: not for use by machine-independent code. + */ + bus_size_t _dm_size; /* largest DMA transfer mappable */ + int _dm_segcnt; /* number of segs this map can map */ + bus_size_t _dm_maxsegsz; /* largest possible segment */ + bus_size_t _dm_boundary; /* don't cross this */ + int _dm_flags; /* misc. flags */ + + void *_dm_cookie; /* cookie for bus-specific functions */ + + /* + * PUBLIC MEMBERS: these are used by machine-independent code. + */ + bus_size_t dm_mapsize; /* size of the mapping */ + int dm_nsegs; /* # valid segments in mapping */ + bus_dma_segment_t dm_segs[1]; /* segments; variable length */ +}; + +int generic_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, + bus_space_handle_t *); +void generic_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t); +int generic_space_region(bus_space_tag_t, bus_space_handle_t, bus_size_t, + bus_size_t, bus_space_handle_t *); +void *generic_space_vaddr(bus_space_tag_t, bus_space_handle_t); +uint8_t generic_space_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint16_t generic_space_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint32_t generic_space_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint64_t generic_space_read_8(bus_space_tag_t, bus_space_handle_t, bus_size_t); +void generic_space_read_raw_2(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint8_t); +void generic_space_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint16_t); +void generic_space_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint32_t); +void generic_space_write_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint64_t); +void generic_space_write_raw_2(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); +void generic_space_read_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); +void generic_space_read_raw_8(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_raw_8(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); + +#endif /* _MACHINE_BUS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/conf.h b/lib/libc/include/mips64-openbsd-none/machine/conf.h new file mode 100644 index 000000000000..df1ce719b234 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/conf.h @@ -0,0 +1,55 @@ +/* $OpenBSD: conf.h,v 1.4 2022/06/28 14:43:50 visa Exp $ */ +/* $NetBSD: conf.h,v 1.2 1996/05/05 19:28:34 christos Exp $ */ + +/* + * Copyright (c) 1996 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _OCTEON_CONF_H_ +#define _OCTEON_CONF_H_ + +#include + +/* open, close, ioctl */ +#define cdev_octboot_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) nullop, 0, \ + (dev_type_mmap((*))) enodev } + +/* open, close, ioctl */ +#define cdev_openprom_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) nullop, 0, \ + (dev_type_mmap((*))) enodev } + +cdev_decl(octboot); +cdev_decl(openprom); + +#endif /* _OCTEON_CONF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/cpu.h b/lib/libc/include/mips64-openbsd-none/machine/cpu.h new file mode 100644 index 000000000000..e5e26d7837a1 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/cpu.h @@ -0,0 +1,106 @@ +/* $OpenBSD: cpu.h,v 1.12 2018/02/18 14:50:08 visa Exp $ */ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell and Rick Macklem. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Copyright (C) 1989 Digital Equipment Corporation. + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies. + * Digital Equipment Corporation makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * from: @(#)cpu.h 8.4 (Berkeley) 1/4/94 + */ + +#ifndef _MACHINE_CPU_H_ +#define _MACHINE_CPU_H_ + +#ifdef _KERNEL + +#define OCTEON_MAXCPUS 16 + +#if defined(MULTIPROCESSOR) && !defined(_LOCORE) +#define MAXCPUS OCTEON_MAXCPUS +struct cpu_info; +void hw_cpu_boot_secondary(struct cpu_info *); +void hw_cpu_hatch(struct cpu_info *); +void hw_cpu_spinup_trampoline(struct cpu_info *); +int hw_ipi_intr_establish(int (*)(void *), u_long); +void hw_ipi_intr_set(u_long); +void hw_ipi_intr_clear(u_long); + +/* Keep in sync with HW_GET_CPU_INFO(). */ +static inline struct cpu_info * +hw_getcurcpu(void) +{ + struct cpu_info *ci; + __asm__ volatile ("dmfc0 %0, $30" /* ErrorEPC */ : "=r" (ci)); + return ci; +} + +static inline void +hw_setcurcpu(struct cpu_info *ci) +{ + __asm__ volatile ("dmtc0 %0, $30" /* ErrorEPC */ : : "r" (ci)); +} +#endif /* MULTIPROCESSOR && !_LOCORE */ + +#define CACHELINESIZE 128 + +/* + * No need to use the per-cpu_info function pointers, as we only support + * one processor type. + */ +#define Mips_SyncCache(ci) \ + Octeon_SyncCache((ci)) +#define Mips_InvalidateICache(ci, va, l) \ + Octeon_InvalidateICache((ci), (va), (l)) +#define Mips_InvalidateICachePage(ci, va) \ + Octeon_InvalidateICachePage((ci), (va)) +#define Mips_SyncICache(ci) \ + Octeon_SyncICache((ci)) +#define Mips_SyncDCachePage(ci, va, pa) \ + Octeon_SyncDCachePage((ci), (va), (pa)) +#define Mips_HitSyncDCachePage(ci, va, pa) \ + Octeon_SyncDCachePage((ci), (va), (pa)) +#define Mips_HitSyncDCache(ci, va, l) \ + Octeon_HitSyncDCache((ci), (va), (l)) +#define Mips_IOSyncDCache(ci, va, l, h) \ + Octeon_IOSyncDCache((ci), (va), (l), (h)) +#define Mips_HitInvalidateDCache(ci, va, l) \ + Octeon_HitInvalidateDCache((ci), (va), (l)) + +#endif/* _KERNEL */ + +#include + +#endif /* !_MACHINE_CPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/cpustate.h b/lib/libc/include/mips64-openbsd-none/machine/cpustate.h new file mode 100644 index 000000000000..d0dcf0e7c043 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/cpustate.h @@ -0,0 +1,3 @@ +/* $OpenBSD: cpustate.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/db_machdep.h b/lib/libc/include/mips64-openbsd-none/machine/db_machdep.h new file mode 100644 index 000000000000..3a3271b42382 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/db_machdep.h @@ -0,0 +1,3 @@ +/* $OpenBSD: db_machdep.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/elf.h b/lib/libc/include/mips64-openbsd-none/machine/elf.h new file mode 100644 index 000000000000..5918df727bda --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/elf.h @@ -0,0 +1,3 @@ +/* $OpenBSD: elf.h,v 1.1 2024/07/14 19:33:59 miod Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/endian.h b/lib/libc/include/mips64-openbsd-none/machine/endian.h new file mode 100644 index 000000000000..2bfd2b1abd1c --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/endian.h @@ -0,0 +1,3 @@ +/* $OpenBSD: endian.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/exec.h b/lib/libc/include/mips64-openbsd-none/machine/exec.h new file mode 100644 index 000000000000..498f7f2ecac3 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/exec.h @@ -0,0 +1,3 @@ +/* $OpenBSD: exec.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/fdt.h b/lib/libc/include/mips64-openbsd-none/machine/fdt.h new file mode 100644 index 000000000000..4033bc9a0c80 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/fdt.h @@ -0,0 +1,40 @@ +/* $OpenBSD: fdt.h,v 1.2 2018/08/06 10:52:30 patrick Exp $ */ + +/* + * Copyright (c) 2016 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __OCTEON_FDT_H__ +#define __OCTEON_FDT_H__ + +#include + +struct fdt_attach_args { + const char *fa_name; + int fa_node; + bus_space_tag_t fa_iot; + bus_dma_tag_t fa_dmat; + struct fdt_reg *fa_reg; + int fa_nreg; + uint32_t *fa_intr; + int fa_nintr; + int fa_acells; + int fa_scells; +}; + +#define fdt_intr_establish octeon_intr_establish_fdt +#define fdt_intr_disestablish octeon_intr_disestablish_fdt + +#endif /* __OCTEON_FDT_H__ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/fpu.h b/lib/libc/include/mips64-openbsd-none/machine/fpu.h new file mode 100644 index 000000000000..3d415d39b475 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/fpu.h @@ -0,0 +1,3 @@ +/* $OpenBSD: fpu.h,v 1.1 2010/10/03 06:03:57 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/frame.h b/lib/libc/include/mips64-openbsd-none/machine/frame.h new file mode 100644 index 000000000000..f8295979a3c4 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/frame.h @@ -0,0 +1,3 @@ +/* $OpenBSD: frame.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/ieee.h b/lib/libc/include/mips64-openbsd-none/machine/ieee.h new file mode 100644 index 000000000000..8a538bc8eb50 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/ieee.h @@ -0,0 +1,3 @@ +/* $OpenBSD: ieee.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/ieeefp.h b/lib/libc/include/mips64-openbsd-none/machine/ieeefp.h new file mode 100644 index 000000000000..2060e7a21f34 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/ieeefp.h @@ -0,0 +1,3 @@ +/* $OpenBSD: ieeefp.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/intr.h b/lib/libc/include/mips64-openbsd-none/machine/intr.h new file mode 100644 index 000000000000..eef4afc72890 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/intr.h @@ -0,0 +1,186 @@ +/* $OpenBSD: intr.h,v 1.23 2025/05/10 10:01:03 visa Exp $ */ + +/* + * Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _MACHINE_INTR_H_ +#define _MACHINE_INTR_H_ + +#define __USE_MI_SOFTINTR + +#include + +/* + * The interrupt level ipl is a logical level; per-platform interrupt + * code will turn it into the appropriate hardware interrupt masks + * values. + * + * Interrupt sources on the CPU are kept enabled regardless of the + * current ipl value; individual hardware sources interrupting while + * logically masked are masked on the fly, remembered as pending, and + * unmasked at the first splx() opportunity. + * + * An exception to this rule is the clock interrupt. Clock interrupts + * are always allowed to happen, but will (of course!) not be serviced + * if logically masked. The reason for this is that clocks usually sit on + * INT5 and cannot be easily masked if external hardware masking is used. + */ + +/* Interrupt priority `levels'; not mutually exclusive. */ +#define IPL_NONE 0 /* nothing */ +#define IPL_SOFTINT 1 /* soft interrupts */ +#define IPL_SOFTCLOCK 1 /* soft clock interrupts */ +#define IPL_SOFTNET 2 /* soft network interrupts */ +#define IPL_SOFTTTY 3 /* soft terminal interrupts */ +#define IPL_SOFTHIGH IPL_SOFTTTY /* highest level of soft interrupts */ +#define IPL_BIO 4 /* block I/O */ +#define IPL_AUDIO IPL_BIO +#define IPL_NET 5 /* network */ +#define IPL_TTY 6 /* terminal */ +#define IPL_VM 7 /* memory allocation */ +#define IPL_CLOCK 8 /* clock */ +#define IPL_SCHED IPL_CLOCK +#define IPL_HIGH 9 /* everything */ +#define IPL_IPI 10 /* interprocessor interrupt */ +#define NIPLS 11 /* number of levels */ + +#define IPL_MPFLOOR IPL_TTY + +/* Interrupt priority 'flags'. */ +#define IPL_MPSAFE 0x100 + +/* Interrupt sharing types. */ +#define IST_NONE 0 /* none */ +#define IST_PULSE 1 /* pulsed */ +#define IST_EDGE 2 /* edge-triggered */ +#define IST_LEVEL 3 /* level-triggered */ + +#ifndef _LOCORE + +void softintr(int); + +#define splbio() splraise(IPL_BIO) +#define splnet() splraise(IPL_NET) +#define spltty() splraise(IPL_TTY) +#define splaudio() splraise(IPL_AUDIO) +#define splvm() splraise(IPL_VM) +#define splclock() splraise(IPL_CLOCK) +#define splsched() splraise(IPL_SCHED) +#define splhigh() splraise(IPL_HIGH) + +#define splsoftclock() splraise(IPL_SOFTCLOCK) +#define splsoftnet() splraise(IPL_SOFTNET) +#define splstatclock() splhigh() + +#define spl0() spllower(0) + +void splinit(void); + +#ifdef DIAGNOSTIC +/* + * Although this function is implemented in MI code, it must be in this MD + * header because we don't want this header to include MI includes. + */ +void splassert_fail(int, int, const char *); +extern int splassert_ctl; +void splassert_check(int, const char *); +#define splassert(__wantipl) do { \ + if (splassert_ctl > 0) { \ + splassert_check(__wantipl, __func__); \ + } \ +} while (0) +#define splsoftassert(wantipl) splassert(wantipl) +#else +#define splassert(X) +#define splsoftassert(X) +#endif + +void register_splx_handler(void (*)(int)); +int splraise(int); +void splx(int); +int spllower(int); + +void intr_barrier(void *); + +/* + * Low level interrupt dispatcher registration data. + */ + +/* Schedule priorities for base interrupts (CPU) */ +#define INTPRI_IPI 0 +#define INTPRI_CLOCK 1 +/* other values are system-specific */ + +#define NLOWINT 16 /* Number of low level registrations possible */ + +extern uint32_t idle_mask; + +struct trapframe; +void set_intr(int, uint32_t, uint32_t(*)(uint32_t, struct trapframe *)); + +uint32_t updateimask(uint32_t); +void dosoftint(void); + +struct intr_controller { + void *ic_cookie; + void (*ic_init)(void); + void *(*ic_establish)(int, int, int (*)(void *), void *, + const char *); + void *(*ic_establish_fdt_idx)(void *, int, int, int, + int (*)(void *), void *, const char *); + void (*ic_disestablish)(void *); + void (*ic_intr_barrier)(void *); + +#ifdef MULTIPROCESSOR + int (*ic_ipi_establish)(int (*)(void *), cpuid_t); + void (*ic_ipi_set)(cpuid_t); + void (*ic_ipi_clear)(cpuid_t); +#endif /* MULTIPROCESSOR */ + + int ic_node; + int ic_phandle; + LIST_ENTRY(intr_controller) ic_list; +}; + +#ifdef MULTIPROCESSOR +#define ENABLEIPI() updateimask(~CR_INT_1) /* enable IPI interrupt level */ +#endif + +void *octeon_intr_establish(int, int, int (*)(void *), + void *, const char *); +void octeon_intr_disestablish(void *); +void octeon_intr_init(void); +void octeon_intr_register(struct intr_controller *); + +void *octeon_intr_establish_fdt(int, int, int (*)(void *), + void *, const char *); +void *octeon_intr_establish_fdt_idx(int, int, int, int (*)(void *), + void *, const char *); +void octeon_intr_disestablish_fdt(void *); + +#endif /* _LOCORE */ + +#endif /* _MACHINE_INTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/kcore.h b/lib/libc/include/mips64-openbsd-none/machine/kcore.h new file mode 100644 index 000000000000..b221eb2048f0 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/kcore.h @@ -0,0 +1,3 @@ +/* $OpenBSD: kcore.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/limits.h b/lib/libc/include/mips64-openbsd-none/machine/limits.h new file mode 100644 index 000000000000..06574d0acb3c --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/limits.h @@ -0,0 +1,3 @@ +/* $OpenBSD: limits.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/memconf.h b/lib/libc/include/mips64-openbsd-none/machine/memconf.h new file mode 100644 index 000000000000..ec2791c749fb --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/memconf.h @@ -0,0 +1,3 @@ +/* $OpenBSD: memconf.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/mips_opcode.h b/lib/libc/include/mips64-openbsd-none/machine/mips_opcode.h new file mode 100644 index 000000000000..865ce02ebee4 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/mips_opcode.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mips_opcode.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/mplock.h b/lib/libc/include/mips64-openbsd-none/machine/mplock.h new file mode 100644 index 000000000000..f15d10954559 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/mplock.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mplock.h,v 1.2 2015/09/09 15:48:52 visa Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/mutex.h b/lib/libc/include/mips64-openbsd-none/machine/mutex.h new file mode 100644 index 000000000000..9a15499276d2 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/mutex.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mutex.h,v 1.3 2015/07/08 13:37:31 dlg Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/octboot.h b/lib/libc/include/mips64-openbsd-none/machine/octboot.h new file mode 100644 index 000000000000..1a889f7b6ac7 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/octboot.h @@ -0,0 +1,36 @@ +/* $OpenBSD: octboot.h,v 1.2 2020/05/26 13:21:58 visa Exp $ */ + +/* + * Copyright (c) 2019-2020 Visa Hankala + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _OCTEON_OCTBOOT_H_ +#define _OCTEON_OCTBOOT_H_ + +#include + +#define OCTBOOT_MAX_ARGS 8 /* maximum number of boot arguments */ + +struct octboot_kexec_args { + char *kimg; /* kernel image buffer */ + size_t klen; /* size of kernel image */ + char *argv[OCTBOOT_MAX_ARGS]; + /* kernel boot arguments */ +}; + +#define OBIOC_KEXEC _IOW('O', 1, struct octboot_kexec_args) +#define OBIOC_GETROOTDEV _IOR('O', 2, char[PATH_MAX]) + +#endif /* !_OCTEON_OCTBOOT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/octeon_model.h b/lib/libc/include/mips64-openbsd-none/machine/octeon_model.h new file mode 100644 index 000000000000..cac7c19ef93b --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/octeon_model.h @@ -0,0 +1,87 @@ +/* $OpenBSD: octeon_model.h,v 1.9 2024/06/26 01:40:49 jsg Exp $ */ + +/* + * Copyright (c) 2007 + * Internet Initiative Japan, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MIPS_OCTEON_MODEL_H_ +#define _MIPS_OCTEON_MODEL_H_ + +#define OCTEON_MODEL_CN38XX_REV1 0x000d0000 +#define OCTEON_MODEL_CN38XX_REV2 0x000d0001 +#define OCTEON_MODEL_CN38XX_REV3 0x000d0003 +#define OCTEON_MODEL_CN3100 0x000d0100 +#define OCTEON_MODEL_CN3020 0x000d0110 +#define OCTEON_MODEL_CN3010 0x000d0200 +#define OCTEON_MODEL_CN3005 0x000d0210 +#define OCTEON_MODEL_CN5010 0x000d0600 +#define OCTEON_MODEL_CN5010_PASS1_1 0x000d0601 +#define OCTEON_MODEL_CN61XX_PASS1_0 0x000d9300 +#define OCTEON_MODEL_CN61XX_PASS1_1 0x000d9301 + +#define OCTEON_MODEL_MASK 0x00ffff10 +#define OCTEON_MODEL_REV_MASK 0x00ffff1f +#define OCTEON_MODEL_FAMILY_MASK 0x00ffff00 +#define OCTEON_MODEL_FAMILY_REV_MASK 0x00ffff0f + +#define OCTEON_MODEL_FAMILY_CN58XX 0x000d0300 +#define OCTEON_MODEL_FAMILY_CN56XX 0x000d0400 +#define OCTEON_MODEL_FAMILY_CN38XX 0x000d0000 +#define OCTEON_MODEL_FAMILY_CN31XX 0x000d0100 +#define OCTEON_MODEL_FAMILY_CN30XX 0x000d0200 +#define OCTEON_MODEL_FAMILY_CN50XX 0x000d0600 +#define OCTEON_MODEL_FAMILY_CN63XX 0x000d9000 +#define OCTEON_MODEL_FAMILY_CN68XX 0x000d9100 +#define OCTEON_MODEL_FAMILY_CN66XX 0x000d9200 +#define OCTEON_MODEL_FAMILY_CN61XX 0x000d9300 +#define OCTEON_MODEL_FAMILY_CN78XX 0x000d9500 +#define OCTEON_MODEL_FAMILY_CN71XX 0x000d9600 +#define OCTEON_MODEL_FAMILY_CN73XX 0x000d9700 + +/* + * get chip id + */ +static inline uint32_t +octeon_get_chipid(void) +{ + uint32_t tmp; + + asm volatile ( + " .set push \n" + " .set mips64 \n" + " .set noreorder \n" + " mfc0 %0, $15, 0 \n" + " .set pop \n" + : "=&r"(tmp) : ); + + return(tmp); +} + +#define octeon_model(id) ((id) & OCTEON_MODEL_MASK) +#define octeon_model_revision(id) ((id) & OCTEON_MODEL_REV_MASK) +#define octeon_model_family(id) ((id) & OCTEON_MODEL_FAMILY_MASK) +#define octeon_model_family_revision(id) ((id) & OCTEON_MODEL_FAMILY_REV_MASK) + +#endif \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/octeonreg.h b/lib/libc/include/mips64-openbsd-none/machine/octeonreg.h new file mode 100644 index 000000000000..af75e6d7fbb4 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/octeonreg.h @@ -0,0 +1,198 @@ +/* $OpenBSD: octeonreg.h,v 1.11 2020/07/11 15:18:08 visa Exp $ */ + +/* + * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.com). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _MACHINE_OCTEONREG_H_ +#define _MACHINE_OCTEONREG_H_ + +#define OCTEON_CF_BASE 0x1D000800ULL +#define OCTEON_CIU3_BASE 0x1010000000000ULL +#define OCTEON_CIU_BASE 0x1070000000000ULL +#define OCTEON_CIU_SIZE 0x7000 +#define OCTEON_MIO_BOOT_BASE 0x1180000000000ULL +#define OCTEON_UART0_BASE 0x1180000000800ULL +#define OCTEON_UART1_BASE 0x1180000000C00ULL +#define OCTEON_RNG_BASE 0x1400000000000ULL +#define OCTEON_AMDCF_BASE 0x1dc00000ULL + +#define MIO_BOOT_REG_CFG0 0x0 +#define MIO_BOOT_REG_CFG(x) (MIO_BOOT_REG_CFG0+((x)*8)) +#define BOOT_CFG_BASE_MASK 0xFFFF +#define BOOT_CFG_BASE_SHIFT 16 +#define BOOT_CFG_WIDTH_MASK 0x10000000 +#define BOOT_CFG_WIDTH_SHIFT 28 + +#define CIU_INT_WORKQ0 0 +#define CIU_INT_WORKQ1 1 +#define CIU_INT_WORKQ2 2 +#define CIU_INT_WORKQ3 3 +#define CIU_INT_WORKQ4 4 +#define CIU_INT_WORKQ5 5 +#define CIU_INT_WORKQ6 6 +#define CIU_INT_WORKQ7 7 +#define CIU_INT_WORKQ8 8 +#define CIU_INT_WORKQ9 9 +#define CIU_INT_WORKQ10 10 +#define CIU_INT_WORKQ11 11 +#define CIU_INT_WORKQ12 12 +#define CIU_INT_WORKQ13 13 +#define CIU_INT_WORKQ14 14 +#define CIU_INT_WORKQ15 15 +#define CIU_INT_GPIO0 16 +#define CIU_INT_GPIO1 17 +#define CIU_INT_GPIO2 18 +#define CIU_INT_GPIO3 19 +#define CIU_INT_GPIO4 20 +#define CIU_INT_GPIO5 21 +#define CIU_INT_GPIO6 22 +#define CIU_INT_GPIO7 23 +#define CIU_INT_GPIO8 24 +#define CIU_INT_GPIO9 25 +#define CIU_INT_GPIO10 26 +#define CIU_INT_GPIO11 27 +#define CIU_INT_GPIO12 28 +#define CIU_INT_GPIO13 29 +#define CIU_INT_GPIO14 30 +#define CIU_INT_GPIO15 31 +#define CIU_INT_MBOX0 32 +#define CIU_INT_MBOX1 33 +#define CIU_INT_MBOX(x) (CIU_INT_MBOX0+(x)) +#define CIU_INT_UART0 34 +#define CIU_INT_UART1 35 +#define CIU_INT_PCI_INTA 36 +#define CIU_INT_PCI_INTB 37 +#define CIU_INT_PCI_INTC 38 +#define CIU_INT_PCI_INTD 39 +#define CIU_INT_PCI_MSIA 40 +#define CIU_INT_PCI_MSIB 41 +#define CIU_INT_PCI_MSIC 42 +#define CIU_INT_PCI_MSID 43 +#define CIU_INT_44 44 +#define CIU_INT_TWSI 45 +#define CIU_INT_RML 46 +#define CIU_INT_TRACE 47 +#define CIU_INT_GMX_DRP0 48 +#define CIU_INT_GMX_DRP1 49 +#define CIU_INT_IPD_DRP 50 +#define CIU_INT_KEY_ZERO 51 +#define CIU_INT_TIMER0 52 +#define CIU_INT_TIMER1 53 +#define CIU_INT_TIMER2 54 +#define CIU_INT_TIMER3 55 +#define CIU_INT_USB 56 +#define CIU_INT_PCM 57 +#define CIU_INT_MPI 58 +#define CIU_INT_TWSI2 59 +#define CIU_INT_POWIQ 60 +#define CIU_INT_IPDPPTHR 61 +#define CIU_INT_MII0 62 +#define CIU_INT_BOOTDMA 63 + +#define CIU_INT0_SUM0 0x00000000 +#define CIU_INT1_SUM0 0x00000008 +#define CIU_INT2_SUM0 0x00000010 +#define CIU_INT3_SUM0 0x00000018 +#define CIU_IP2_SUM0(x) (CIU_INT0_SUM0+(0x10 * (x))) +#define CIU_IP3_SUM0(x) (CIU_INT1_SUM0+(0x10 * (x))) +#define CIU_INT32_SUM0 0x00000100 +#define CIU_INT32_SUM1 0x00000108 +#define CIU_INT0_EN0 0x00000200 +#define CIU_INT1_EN0 0x00000210 +#define CIU_INT2_EN0 0x00000220 +#define CIU_INT3_EN0 0x00000230 +#define CIU_IP2_EN0(x) (CIU_INT0_EN0+(0x20 * (x))) +#define CIU_IP3_EN0(x) (CIU_INT1_EN0+(0x20 * (x))) +#define CIU_INT32_EN0 0x00000400 +#define CIU_INT0_EN1 0x00000208 +#define CIU_INT1_EN1 0x00000218 +#define CIU_INT2_EN1 0x00000228 +#define CIU_INT3_EN1 0x00000238 +#define CIU_INT32_EN1 0x00000408 +#define CIU_IP2_EN1(x) (CIU_INT0_EN1+(0x20 * (x))) +#define CIU_IP3_EN1(x) (CIU_INT1_EN1+(0x20 * (x))) +#define CIU_TIM0 0x00000480 +#define CIU_TIM1 0x00000488 +#define CIU_TIM2 0x00000490 +#define CIU_TIM3 0x00000498 +#define CIU_WDOG0 0x00000500 +#define CIU_WDOG1 0x00000508 +#define CIU_PP_POKE0 0x00000580 +#define CIU_PP_POKE1 0x00000588 +#define CIU_MBOX_SET0 0x00000600 +#define CIU_MBOX_SET1 0x00000608 +#define CIU_MBOX_SET(x) (CIU_MBOX_SET0+(0x08 * (x))) +#define CIU_MBOX_CLR0 0x00000680 +#define CIU_MBOX_CLR1 0x00000688 +#define CIU_MBOX_CLR(x) (CIU_MBOX_CLR0+(0x08 * (x))) +#define CIU_PP_RST 0x00000700 +#define CIU_PP_DBG 0x00000708 +#define CIU_GSTOP 0x00000710 +#define CIU_NMI 0x00000718 +#define CIU_DINT 0x00000720 +#define CIU_FUSE 0x00000728 +#define CIU_BIST 0x00000730 +#define CIU_SOFT_BIST 0x00000738 +#define CIU_SOFT_RST 0x00000740 +#define CIU_SOFT_PRST 0x00000748 +#define CIU_PCI_INTA 0x00000750 +#define CIU_INT0_SUM4 0x00000C00 +#define CIU_INT1_SUM4 0x00000C08 +#define CIU_INT0_EN4_0 0x00000C80 +#define CIU_INT1_EN4_0 0x00000C90 +#define CIU_INT0_EN4_1 0x00000C88 +#define CIU_INT1_EN4_1 0x00000C98 +#define CIU_IP4_SUM2(x) (0x00008c00 + 8 * (x)) +#define CIU_IP4_EN2(x) (0x0000a400 + 8 * (x)) + +#define CIU3_FUSE 0x000001a0 + +#define FPA3_CLK_COUNT 0x12800000000f0ULL + +/* OCTEON II */ +#define MIO_RST_BOOT 0x1180000001600ULL +#define MIO_RST_BOOT_C_MUL_SHIFT 30 +#define MIO_RST_BOOT_C_MUL_MASK 0x7f +#define MIO_RST_BOOT_PNR_MUL_SHIFT 24 +#define MIO_RST_BOOT_PNR_MUL_MASK 0x3f + +#define MIO_RST_CTL(x) (0x1180000001618ULL + 8 * (x)) +#define MIO_RST_CTL_PRTMODE 0x0000000000000030ULL + +/* OCTEON III */ +#define RST_BOOT 0x1180006001600ULL +#define RST_BOOT_C_MUL_SHIFT 30 +#define RST_BOOT_C_MUL_MASK 0x7f +#define RST_BOOT_PNR_MUL_SHIFT 24 +#define RST_BOOT_PNR_MUL_MASK 0x3f +#define RST_CTL(x) (0x1180006001640ULL + 8 * (x)) +#define RST_CTL_RST_DONE 0x0000000000000100ULL +#define RST_CTL_HOST_MODE 0x0000000000000040ULL +#define RST_SOFT_RST 0x1180006001680ULL + +#define OCTEON_IO_REF_CLOCK 50000000 /* 50MHz */ + +#endif /* !_MACHINE_OCTEONREG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/octeonvar.h b/lib/libc/include/mips64-openbsd-none/machine/octeonvar.h new file mode 100644 index 000000000000..cc0f782bf38e --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/octeonvar.h @@ -0,0 +1,498 @@ +/* $OpenBSD: octeonvar.h,v 1.54 2022/08/29 02:01:18 jsg Exp $ */ +/* $NetBSD: maltavar.h,v 1.3 2002/03/18 10:10:16 simonb Exp $ */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MIPS_OCTEON_OCTEONVAR_H_ +#define _MIPS_OCTEON_OCTEONVAR_H_ + +#include + +/* XXX elsewhere */ +#define _ASM_PROLOGUE \ + " .set push \n" \ + " .set noreorder \n" +#define _ASM_PROLOGUE_MIPS64 \ + _ASM_PROLOGUE \ + " .set mips64 \n" +#define _ASM_PROLOGUE_OCTEON \ + _ASM_PROLOGUE \ + " .set arch=octeon \n" +#define _ASM_EPILOGUE \ + " .set pop \n" +/* + * subbits = __BITS64_GET(XXX, bits); + * bits = __BITS64_SET(XXX, subbits); + */ +#ifndef __BITS64_GET +#define __BITS64_GET(name, bits) \ + (((uint64_t)(bits) & name) >> name##_SHIFT) +#endif +#ifndef __BITS64_SET +#define __BITS64_SET(name, subbits) \ + (((uint64_t)(subbits) << name##_SHIFT) & name) +#endif + +struct octeon_config { + bus_space_tag_t mc_iobus_bust; + bus_space_tag_t mc_bootbus_bust; + + bus_dma_tag_t mc_iobus_dmat; + bus_dma_tag_t mc_bootbus_dmat; +}; + +#define GPIO_CONFIG_MD_OUTPUT_SEL_MASK (GPIO_CONFIG_MD0 | GPIO_CONFIG_MD1) +#define GPIO_CONFIG_MD_USB0_VBUS_CTRL GPIO_CONFIG_MD0 +#define GPIO_CONFIG_MD_USB1_VBUS_CTRL GPIO_CONFIG_MD1 + +/* + * FPA map + */ + +#define OCTEON_POOL_NO_PKT 0 +#define OCTEON_POOL_NO_WQE 1 +#define OCTEON_POOL_NO_CMD 2 +#define OCTEON_POOL_NO_SG 3 +#define OCTEON_POOL_NO_XXX_4 4 +#define OCTEON_POOL_NO_XXX_5 5 +#define OCTEON_POOL_NO_XXX_6 6 +#define OCTEON_POOL_NO_DUMP 7 /* FPA debug dump */ + +#define OCTEON_POOL_SIZE_PKT 1920 /* 128 x 15 */ +#define OCTEON_POOL_SIZE_WQE 128 /* 128 x 1 */ +#define OCTEON_POOL_SIZE_CMD 1024 /* 128 x 8 */ +#define OCTEON_POOL_SIZE_SG 128 /* 128 x 1 */ +#define OCTEON_POOL_SIZE_XXX_4 0 +#define OCTEON_POOL_SIZE_XXX_5 0 +#define OCTEON_POOL_SIZE_XXX_6 0 +#define OCTEON_POOL_SIZE_XXX_7 0 + +#define OCTEON_POOL_NELEMS_PKT 4096 +#define OCTEON_POOL_NELEMS_WQE 4096 +#define OCTEON_POOL_NELEMS_CMD 32 +#define OCTEON_POOL_NELEMS_SG 4096 +#define OCTEON_POOL_NELEMS_XXX_4 0 +#define OCTEON_POOL_NELEMS_XXX_5 0 +#define OCTEON_POOL_NELEMS_XXX_6 0 +#define OCTEON_POOL_NELEMS_XXX_7 0 + +/* + * CVMSEG (``scratch'') memory map + */ +struct octeon_cvmseg_map { + uint64_t csm_pow_intr; + + struct octeon_cvmseg_ether_map { + uint64_t csm_ether_fau_done; + } csm_ether[12/* XXX */]; +} __packed; +#define OCTEON_CVMSEG_OFFSET(entry) \ + offsetof(struct octeon_cvmseg_map, entry) +#define OCTEON_CVMSEG_ETHER_OFFSET(n, entry) \ + (offsetof(struct octeon_cvmseg_map, csm_ether) + \ + sizeof(struct octeon_cvmseg_ether_map) * (n) + \ + offsetof(struct octeon_cvmseg_ether_map, entry)) + +/* + * FAU register map + * + * => FAU registers exist in FAU unit + * => devices (PKO) can access these registers + * => CPU can read those values after loading them into CVMSEG + */ +struct octeon_fau_map { + struct { + /* PKO command index */ + uint64_t _fau_map_port_pkocmdidx; + /* send requested */ + uint64_t _fau_map_port_txreq; + /* send completed */ + uint64_t _fau_map_port_txdone; + /* XXX */ + uint64_t _fau_map_port_pad; + } __packed _fau_map_port[3]; +}; + +/* + * POW qos/group map + */ + +#define OCTEON_POW_QOS_PIP 0 +#define OCTEON_POW_QOS_CORE1 1 +#define OCTEON_POW_QOS_XXX_2 2 +#define OCTEON_POW_QOS_XXX_3 3 +#define OCTEON_POW_QOS_XXX_4 4 +#define OCTEON_POW_QOS_XXX_5 5 +#define OCTEON_POW_QOS_XXX_6 6 +#define OCTEON_POW_QOS_XXX_7 7 + +#define OCTEON_POW_GROUP_MAX 16 + +enum cnmac_stat { + cnmac_stat_rx_toto_gmx, + cnmac_stat_rx_totp_gmx, + cnmac_stat_rx_toto_pip, + cnmac_stat_rx_totp_pip, + cnmac_stat_rx_h64, + cnmac_stat_rx_h127, + cnmac_stat_rx_h255, + cnmac_stat_rx_h511, + cnmac_stat_rx_h1023, + cnmac_stat_rx_h1518, + cnmac_stat_rx_hmax, + cnmac_stat_rx_bcast, + cnmac_stat_rx_mcast, + cnmac_stat_rx_qdpo, + cnmac_stat_rx_qdpp, + cnmac_stat_rx_fcs, + cnmac_stat_rx_frag, + cnmac_stat_rx_undersz, + cnmac_stat_rx_jabber, + cnmac_stat_rx_oversz, + cnmac_stat_rx_raw, + cnmac_stat_rx_bad, + cnmac_stat_rx_drop, + cnmac_stat_rx_ctl, + cnmac_stat_rx_dmac, + cnmac_stat_tx_toto, + cnmac_stat_tx_totp, + cnmac_stat_tx_hmin, + cnmac_stat_tx_h64, + cnmac_stat_tx_h127, + cnmac_stat_tx_h255, + cnmac_stat_tx_h511, + cnmac_stat_tx_h1023, + cnmac_stat_tx_h1518, + cnmac_stat_tx_hmax, + cnmac_stat_tx_bcast, + cnmac_stat_tx_mcast, + cnmac_stat_tx_coll, + cnmac_stat_tx_defer, + cnmac_stat_tx_scol, + cnmac_stat_tx_mcol, + cnmac_stat_tx_ctl, + cnmac_stat_tx_uflow, + cnmac_stat_count +}; + +#if defined(_KERNEL) || defined(_STANDALONE) +#define OCTEON_ARGV_MAX 64 + +/* + * OCTEON board types recognized by OpenBSD/octeon. + * + * It is fine to use BOARD_UNKNOWN when the board does not need + * special treatment. + */ +enum octeon_board { + BOARD_UNKNOWN, + BOARD_CHECKPOINT_N100, + BOARD_CN3010_EVB_HS5, + BOARD_DLINK_DSR_500, + BOARD_NETGEAR_UTM25, + BOARD_RHINOLABS_UTM8, + BOARD_UBIQUITI_E100, + BOARD_UBIQUITI_E120, + BOARD_UBIQUITI_E200, + BOARD_UBIQUITI_E220, + BOARD_UBIQUITI_E300, + BOARD_UBIQUITI_E1000, +}; + +struct boot_desc { + uint32_t desc_ver; + uint32_t desc_size; + uint64_t stack_top; + uint64_t heap_start; + uint64_t heap_end; + uint64_t __unused17; + uint64_t __unused16; + uint32_t __unused18; + uint32_t __unused15; + uint32_t __unused14; + uint32_t argc; + uint32_t argv[OCTEON_ARGV_MAX]; + uint32_t flags; + uint32_t core_mask; + uint32_t dram_size; + uint32_t phy_mem_desc_addr; + uint32_t debugger_flag_addr; + uint32_t eclock; + uint32_t __unused10; + uint32_t __unused9; + uint16_t __unused8; + uint8_t __unused7; + uint8_t __unused6; + uint16_t __unused5; + uint8_t __unused4; + uint8_t __unused3; + uint8_t __unused2[20]; + uint8_t __unused1[6]; + uint8_t __unused0; + uint64_t boot_info_addr; +}; + +struct boot_info { + uint32_t ver_major; + uint32_t ver_minor; + uint64_t stack_top; + uint64_t heap_start; + uint64_t heap_end; + uint64_t boot_desc_addr; + uint32_t exception_base_addr; + uint32_t stack_size; + uint32_t flags; + uint32_t core_mask; + uint32_t dram_size; + uint32_t phys_mem_desc_addr; + uint32_t debugger_flags_addr; + uint32_t eclock; + uint32_t dclock; + uint32_t __unused0; + uint16_t board_type; + uint8_t board_rev_major; + uint8_t board_rev_minor; + uint16_t __unused1; + uint8_t __unused2; + uint8_t __unused3; + char board_serial[20]; + uint8_t mac_addr_base[6]; + uint8_t mac_addr_count; + uint64_t cf_common_addr; + uint64_t cf_attr_addr; + uint64_t led_display_addr; + uint32_t dfaclock; + uint32_t config_flags; + /* The fields below are available when ver_minor >= 3. */ + uint64_t fdt_addr; +}; + +struct octeon_bootmem_desc { + uint32_t lock; + uint32_t flags; + uint64_t head_addr; + uint32_t major_version; + uint32_t minor_version; + uint64_t app_data_addr; + uint64_t app_data_size; + uint32_t named_block_num_blocks; + uint32_t named_block_name_len; + uint64_t named_block_array_addr; +}; + +struct octeon_bootmem_block { + uint64_t next; + uint64_t size; +}; + +extern enum octeon_board octeon_board; +extern struct boot_desc *octeon_boot_desc; +extern struct boot_info *octeon_boot_info; + +#ifdef _KERNEL +/* Device capabilities advertised in boot_info->config_flags */ +#define BOOTINFO_CFG_FLAG_PCI_HOST (1ull << 0) +#define BOOTINFO_CFG_FLAG_PCI_TARGET (1ull << 1) +#define BOOTINFO_CFG_FLAG_DEBUG (1ull << 2) +#define BOOTINFO_CFG_FLAG_NO_MAGIC (1ull << 3) + +#define BOOTMEM_BLOCK_ALIGN 16 +#define BOOTMEM_BLOCK_MASK (BOOTMEM_BLOCK_ALIGN - 1) +#define BOOTMEM_BLOCK_MIN_SIZE 16 + +int bootmem_alloc_region(paddr_t, size_t); +void bootmem_free(paddr_t, size_t); + +int octeon_ioclock_speed(void); + +#endif /* _KERNEL */ +#endif /* _KERNEL || _STANDALONE */ + +static inline int +ffs64(uint64_t val) +{ + int ret; + + __asm volatile ( \ + _ASM_PROLOGUE_MIPS64 + " dclz %0, %1 \n" + _ASM_EPILOGUE + : "=r"(ret) : "r"(val)); + return 64 - ret; +} + +static inline int +ffs32(uint32_t val) +{ + int ret; + + __asm volatile ( \ + _ASM_PROLOGUE_MIPS64 + " clz %0, %1 \n" + _ASM_EPILOGUE + : "=r"(ret) : "r"(val)); + return 32 - ret; +} + +static inline uint64_t +octeon_xkphys_read_8(paddr_t address) +{ + volatile uint64_t *p = + (volatile uint64_t *)(PHYS_TO_XKPHYS(address, CCA_NC)); + return (*p); +} + +#define MIO_BOOT_BIST_STAT 0x00011800000000f8ULL +static inline void +octeon_xkphys_write_8(paddr_t address, uint64_t value) +{ + *(volatile uint64_t *)(PHYS_TO_XKPHYS(address, CCA_NC)) = value; + + /* + * It seems an immediate read is necessary when doing a write to an RSL + * register in order to complete the write. + * We use MIO_BOOT_BIST_STAT because it's apparently the fastest + * write. + */ + + /* + * XXX + * This if would be better written as: + * if ((address & 0xffffff0000000000ULL) == OCTEON_MIO_BOOT_BASE) { + * but octeonreg.h can't be included here and we want this inlined + * + * Note that the SDK masks with 0x7ffff but that doesn't make sense. + * This is a physical address. + */ + if (((address >> 40) & 0xfffff) == (0x118)) { + value = *(volatile uint64_t *) + (PHYS_TO_XKPHYS(MIO_BOOT_BIST_STAT, CCA_NC)); + } +} + +static inline void +octeon_iobdma_write_8(uint64_t value) +{ + uint64_t addr = 0xffffffffffffa200ULL; + + *(volatile uint64_t *)addr = value; +} + +static inline void +octeon_lmtdma_write_8(off_t offset, uint64_t value) +{ + *(volatile uint64_t *)(0xffffffffffffa400ULL + offset) = value; +} + +static inline uint64_t +octeon_cvmseg_read_8(size_t offset) +{ + return *(volatile uint64_t *)(0xffffffffffff8000ULL + offset); +} + +static inline void +octeon_cvmseg_write_8(size_t offset, uint64_t value) +{ + *(volatile uint64_t *)(0xffffffffffff8000ULL + offset) = value; +} + +static inline uint32_t +octeon_get_coreid(void) +{ + uint32_t coreid; + + __asm volatile ( + _ASM_PROLOGUE_OCTEON + " rdhwr %0, $0\n" + _ASM_EPILOGUE + : "=r" (coreid)); + return coreid; +} + +static inline uint64_t +octeon_get_cycles(void) +{ + uint64_t tmp; + + __asm volatile ( + _ASM_PROLOGUE_MIPS64 + " dmfc0 %[tmp], $9, 6 \n" + _ASM_EPILOGUE + : [tmp]"=&r"(tmp)); + return tmp; +} + +static inline uint64_t +octeon_get_cvmctl(void) +{ + uint64_t tmp; + + __asm volatile ( + _ASM_PROLOGUE_OCTEON + " dmfc0 %[tmp], $9, 7 \n" + _ASM_EPILOGUE + : [tmp]"=r"(tmp)); + return tmp; +} + +static inline uint64_t +octeon_get_cvmmemctl(void) +{ + uint64_t tmp; + + __asm volatile ( + _ASM_PROLOGUE_OCTEON + " dmfc0 %[tmp], $11, 7 \n" + _ASM_EPILOGUE + : [tmp]"=r"(tmp)); + return tmp; +} + +static inline void +octeon_set_cvmmemctl(uint64_t val) +{ + __asm volatile ( + _ASM_PROLOGUE_OCTEON + " dmtc0 %[tmp], $11, 7 \n" + _ASM_EPILOGUE + : : [tmp]"r"(val) : "memory"); +} + +static inline void +octeon_synciobdma(void) +{ + __asm volatile ( + _ASM_PROLOGUE_OCTEON + " synciobdma\n" + _ASM_EPILOGUE + : : : "memory"); +} + +#endif /* _MIPS_OCTEON_OCTEONVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/openpromio.h b/lib/libc/include/mips64-openbsd-none/machine/openpromio.h new file mode 100644 index 000000000000..c33fb937a0e0 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/openpromio.h @@ -0,0 +1,57 @@ +/* $OpenBSD: openpromio.h,v 1.1 2016/07/05 12:53:40 visa Exp $ */ +/* $NetBSD: openpromio.h,v 1.1.1.1 1998/06/20 04:58:52 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)openpromio.h 8.1 (Berkeley) 6/11/93 + */ + +struct opiocdesc { + int op_nodeid; /* passed or returned node id */ + int op_namelen; /* length of op_name */ + char *op_name; /* pointer to field name */ + int op_buflen; /* length of op_buf (value-result) */ + char *op_buf; /* pointer to field value */ +}; + +#define OPIOCGET _IOWR('O', 1, struct opiocdesc) /* get openprom field */ +#define OPIOCSET _IOW('O', 2, struct opiocdesc) /* set openprom field */ +#define OPIOCNEXTPROP _IOWR('O', 3, struct opiocdesc) /* get next property */ +#define OPIOCGETOPTNODE _IOR('O', 4, int) /* get openprom field */ +#define OPIOCGETNEXT _IOWR('O', 5, int) /* get next node of node */ +#define OPIOCGETCHILD _IOWR('O', 6, int) /* get first child of node */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/param.h b/lib/libc/include/mips64-openbsd-none/machine/param.h new file mode 100644 index 000000000000..336a6523083a --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/param.h @@ -0,0 +1,22 @@ +/* $OpenBSD: param.h,v 1.5 2018/08/09 12:19:32 patrick Exp $ */ + +/* Public Domain */ + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ + +#define MACHINE "octeon" +#define _MACHINE octeon +#define MACHINE_ARCH "mips64" +#define _MACHINE_ARCH mips64 +#define MID_MACHINE MID_MIPS64 + +#define PAGE_SHIFT 14 + +#include + +#ifdef _KERNEL +#define __HAVE_FDT +#endif + +#endif /* _MACHINE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/pcb.h b/lib/libc/include/mips64-openbsd-none/machine/pcb.h new file mode 100644 index 000000000000..d48bd4724790 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/pcb.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pcb.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/pci_machdep.h b/lib/libc/include/mips64-openbsd-none/machine/pci_machdep.h new file mode 100644 index 000000000000..b3aa0341f118 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/pci_machdep.h @@ -0,0 +1,133 @@ +/* $OpenBSD: pci_machdep.h,v 1.13 2024/05/20 23:13:33 jsg Exp $ */ + +/* + * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include + +typedef struct mips_pci_chipset *pci_chipset_tag_t; + +typedef u_int64_t pcitag_t; +#define PCITAG_NODE(x) ((x) >> 32) +#define PCITAG_OFFSET(x) ((x) & 0xffffffff) + +typedef u_long pci_intr_handle_t; + +struct pci_attach_args; + +/* + * mips-specific PCI structure and type definitions. + * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE. + */ +struct mips_pci_chipset { + void *pc_conf_v; + void (*pc_attach_hook)(struct device *, + struct device *, struct pcibus_attach_args *); + int (*pc_bus_maxdevs)(void *, int); + pcitag_t (*pc_make_tag)(void *, int, int, int); + void (*pc_decompose_tag)(void *, pcitag_t, int *, + int *, int *); + int (*pc_conf_size)(void *, pcitag_t); + pcireg_t (*pc_conf_read)(void *, pcitag_t, int); + void (*pc_conf_write)(void *, pcitag_t, int, pcireg_t); + + void *pc_intr_v; + int (*pc_intr_map)(struct pci_attach_args *, + pci_intr_handle_t *); + const char *(*pc_intr_string)(void *, pci_intr_handle_t); + void *(*pc_intr_establish)(void *, pci_intr_handle_t, + int, int (*)(void *), void *, char *); + void (*pc_intr_disestablish)(void *, void *); +}; + +/* + * Functions provided to machine-independent PCI code. + */ +//#define DEBUG_PCI_CONF + +#define pci_attach_hook(p, s, pba) \ + (*(pba)->pba_pc->pc_attach_hook)((p), (s), (pba)) +#define pci_bus_maxdevs(c, b) \ + (*(c)->pc_bus_maxdevs)((c)->pc_conf_v, (b)) +#define pci_make_tag(c, b, d, f) \ + (*(c)->pc_make_tag)((c)->pc_conf_v, (b), (d), (f)) +#define pci_decompose_tag(c, t, bp, dp, fp) \ + (*(c)->pc_decompose_tag)((c)->pc_conf_v, (t), (bp), (dp), (fp)) + +#define pci_conf_size(c, t) \ + (*(c)->pc_conf_size)((c)->pc_conf_v, (t)) + +#ifdef DEBUG_PCI_CONF +static inline pcireg_t +pci_conf_read_db(void *cookie, pcitag_t tag, int reg, + const char *file, const char *func, int line) +{ + struct mips_pci_chipset *pc = cookie; + pcireg_t val; + + val = (*(pc)->pc_conf_read)(pc->pc_conf_v, tag, reg); + printf("%s:%s:%d:pci_conf_read(%llx,%x) = %x\n", file, func, line, + tag, reg, val); + return val; +} + +static inline void +pci_conf_write_db(void *cookie, pcitag_t tag, int reg, pcireg_t val, + const char *file, const char *func, int line) +{ + struct mips_pci_chipset *pc = cookie; + + printf("%s:%s:%d:pci_conf_write(%llx,%x,%x)\n", file, func, line, + tag, reg, val); + (*(pc)->pc_conf_write)(pc->pc_conf_v, tag, reg, val); +} + + +#define pci_conf_read(c, t, r) \ + pci_conf_read_db(c, t, r, __FILE__, __FUNCTION__, __LINE__) +#define pci_conf_write(c, t, r, v) \ + pci_conf_write_db(c, t, r, v, __FILE__, __FUNCTION__, __LINE__) +#else +#define pci_conf_read(c, t, r) \ + (*(c)->pc_conf_read)((c)->pc_conf_v, (t), (r)) +#define pci_conf_write(c, t, r, v) \ + (*(c)->pc_conf_write)((c)->pc_conf_v, (t), (r), (v)) +#endif +#define pci_intr_map(c, ihp) \ + (*(c)->pa_pc->pc_intr_map)((c), (ihp)) +#define pci_intr_map_msi(c, ihp) (-1) +#define pci_intr_map_msix(c, vec, ihp) (-1) +#define pci_intr_string(c, ih) \ + (*(c)->pc_intr_string)((c)->pc_intr_v, (ih)) +#define pci_intr_establish(c, ih, l, h, a, nm) \ + (*(c)->pc_intr_establish)((c)->pc_intr_v, (ih), (l), (h), (a), (nm)) +#define pci_intr_disestablish(c, iv) \ + (*(c)->pc_intr_disestablish)((c)->pc_intr_v, (iv)) +#define pci_probe_device_hook(c, a) (0) + +#define pci_min_powerstate(c, t) (PCI_PMCSR_STATE_D3) +#define pci_set_powerstate_md(c, t, s, p) + +#define pci_dev_postattach(a, b) \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/pmap.h b/lib/libc/include/mips64-openbsd-none/machine/pmap.h new file mode 100644 index 000000000000..93a59c2555e1 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/pmap.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pmap.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/proc.h b/lib/libc/include/mips64-openbsd-none/machine/proc.h new file mode 100644 index 000000000000..feb4d625ead2 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/proc.h @@ -0,0 +1,3 @@ +/* $OpenBSD: proc.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/profile.h b/lib/libc/include/mips64-openbsd-none/machine/profile.h new file mode 100644 index 000000000000..f6b93ca73c98 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/profile.h @@ -0,0 +1,3 @@ +/* $OpenBSD: profile.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/pte.h b/lib/libc/include/mips64-openbsd-none/machine/pte.h new file mode 100644 index 000000000000..a1543ff6ce2e --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/pte.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pte.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/ptrace.h b/lib/libc/include/mips64-openbsd-none/machine/ptrace.h new file mode 100644 index 000000000000..be18759bdae6 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/ptrace.h @@ -0,0 +1,3 @@ +/* $OpenBSD: ptrace.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/reg.h b/lib/libc/include/mips64-openbsd-none/machine/reg.h new file mode 100644 index 000000000000..b21b51b97883 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/reg.h @@ -0,0 +1,3 @@ +/* $OpenBSD: reg.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/regdef.h b/lib/libc/include/mips64-openbsd-none/machine/regdef.h new file mode 100644 index 000000000000..dc004a4ce80d --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/regdef.h @@ -0,0 +1,3 @@ +/* $OpenBSD: regdef.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/regnum.h b/lib/libc/include/mips64-openbsd-none/machine/regnum.h new file mode 100644 index 000000000000..b20d7d3c3f04 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/regnum.h @@ -0,0 +1,3 @@ +/* $OpenBSD: regnum.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/setjmp.h b/lib/libc/include/mips64-openbsd-none/machine/setjmp.h new file mode 100644 index 000000000000..bdd733d22dcb --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/setjmp.h @@ -0,0 +1,3 @@ +/* $OpenBSD: setjmp.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/signal.h b/lib/libc/include/mips64-openbsd-none/machine/signal.h new file mode 100644 index 000000000000..2a21ca635862 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/signal.h @@ -0,0 +1,3 @@ +/* $OpenBSD: signal.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/simplebusvar.h b/lib/libc/include/mips64-openbsd-none/machine/simplebusvar.h new file mode 100644 index 000000000000..32763ebfc8a9 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/simplebusvar.h @@ -0,0 +1,34 @@ +/* $OpenBSD: simplebusvar.h,v 1.1 2023/09/22 01:10:43 jsg Exp $ */ + +/* + * Copyright (c) 2016 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +struct simplebus_softc { + struct device sc_dev; + int sc_node; + bus_space_tag_t sc_iot; + bus_dma_tag_t sc_dmat; + int sc_acells; + int sc_scells; + int sc_pacells; + int sc_pscells; + bus_space_t sc_bus; + int *sc_ranges; + int sc_rangeslen; + int sc_early; +}; + +extern void simplebus_attach(struct device *, struct device *, void *); \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/spinlock.h b/lib/libc/include/mips64-openbsd-none/machine/spinlock.h new file mode 100644 index 000000000000..800fc6eeb1a1 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/spinlock.h @@ -0,0 +1,3 @@ +/* $OpenBSD: spinlock.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/sysarch.h b/lib/libc/include/mips64-openbsd-none/machine/sysarch.h new file mode 100644 index 000000000000..05bc15167666 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/sysarch.h @@ -0,0 +1,3 @@ +/* $OpenBSD: sysarch.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/timetc.h b/lib/libc/include/mips64-openbsd-none/machine/timetc.h new file mode 100644 index 000000000000..d3d291c815ca --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/timetc.h @@ -0,0 +1,23 @@ +/* $OpenBSD: timetc.h,v 1.2 2020/07/18 08:37:43 visa Exp $ */ +/* + * Copyright (c) 2020 Paul Irofti + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TIMETC_H_ +#define _MACHINE_TIMETC_H_ + +#include + +#endif /* _MACHINE_TIMETC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/trap.h b/lib/libc/include/mips64-openbsd-none/machine/trap.h new file mode 100644 index 000000000000..7ed252bd110b --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/trap.h @@ -0,0 +1,3 @@ +/* $OpenBSD: trap.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/machine/vmparam.h b/lib/libc/include/mips64-openbsd-none/machine/vmparam.h new file mode 100644 index 000000000000..336c1cf70f00 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/machine/vmparam.h @@ -0,0 +1,11 @@ +/* $OpenBSD: vmparam.h,v 1.3 2017/07/30 16:09:53 visa Exp $ */ +/* public domain */ +#ifndef _MACHINE_VMPARAM_H_ +#define _MACHINE_VMPARAM_H_ + +#define VM_PHYSSEG_MAX 8 /* Max number of physical memory segments */ +#define VM_PHYSSEG_STRAT VM_PSTRAT_BIGFIRST + +#include + +#endif /* _MACHINE_VMPARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/_float.h b/lib/libc/include/mips64-openbsd-none/octeon/_float.h new file mode 100644 index 000000000000..6c9717939fcb --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/_float.h @@ -0,0 +1,3 @@ +/* $OpenBSD: _float.h,v 1.1 2012/06/26 16:12:44 deraadt Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/_types.h b/lib/libc/include/mips64-openbsd-none/octeon/_types.h new file mode 100644 index 000000000000..12dbcd35ee5f --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/_types.h @@ -0,0 +1,3 @@ +/* $OpenBSD: _types.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/asm.h b/lib/libc/include/mips64-openbsd-none/octeon/asm.h new file mode 100644 index 000000000000..a7660ee6410b --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/asm.h @@ -0,0 +1,9 @@ +/* $OpenBSD: asm.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ + +#ifdef MULTIPROCESSOR +#define HW_GET_CPU_INFO(ci, tmp) \ + dmfc0 ci, COP_0_ERROR_PC +#endif + +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/atomic.h b/lib/libc/include/mips64-openbsd-none/octeon/atomic.h new file mode 100644 index 000000000000..1d56c3a0008c --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/atomic.h @@ -0,0 +1,45 @@ +/* $OpenBSD: atomic.h,v 1.3 2020/07/08 15:53:59 visa Exp $ */ + +/* + * Copyright (c) 2017 Visa Hankala + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _OCTEON_ATOMIC_H_ +#define _OCTEON_ATOMIC_H_ + +#ifdef _KERNEL + +static inline void +octeon_syncw(void) +{ + __asm__ volatile ( + " .set push\n" + " .set arch=octeon\n" + /* Issue the barrier twice to work around CN3xxx erratum Core-401. + * A single syncw might not enforce write ordering properly. */ + " syncw\n" + " syncw\n" + " .set pop\n" + : : : "memory"); +} + +#define membar_consumer() __asm__ volatile ("" : : : "memory") +#define membar_producer() octeon_syncw() + +#endif /* _KERNEL */ + +#include + +#endif /* !_OCTEON_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/autoconf.h b/lib/libc/include/mips64-openbsd-none/octeon/autoconf.h new file mode 100644 index 000000000000..0b9aa66be992 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/autoconf.h @@ -0,0 +1,58 @@ +/* $OpenBSD: autoconf.h,v 1.4 2019/07/12 03:03:48 visa Exp $ */ + +/* + * Copyright (c) 2001-2003 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * Definitions used by autoconfiguration. + */ + +#ifndef _MACHINE_AUTOCONF_H_ +#define _MACHINE_AUTOCONF_H_ + +#include + +struct mainbus_attach_args { + const char *maa_name; +}; + +extern struct device *bootdv; +extern char bootdev[]; +extern char uboot_rootdev[]; +extern enum devclass bootdev_class; + +#include + +void com_fdt_init_cons(void); +void parse_uboot_root(const char *); + +extern unsigned int octeon_ver; +#define OCTEON_1 0 +#define OCTEON_PLUS 1 +#define OCTEON_2 2 +#define OCTEON_3 3 + +#endif /* _MACHINE_AUTOCONF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/bus.h b/lib/libc/include/mips64-openbsd-none/octeon/bus.h new file mode 100644 index 000000000000..257157af06db --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/bus.h @@ -0,0 +1,510 @@ +/* $OpenBSD: bus.h,v 1.8 2020/04/14 17:35:28 kettenis Exp $ */ + +/* + * Copyright (c) 2003-2004 Opsycon AB Sweden. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BUS_H_ +#define _MACHINE_BUS_H_ + +#ifdef __STDC__ +#define CAT(a,b) a##b +#define CAT3(a,b,c) a##b##c +#else +#define CAT(a,b) a/**/b +#define CAT3(a,b,c) a/**/b/**/c +#endif + +/* + * Bus access types. + */ +struct mips_bus_space; +typedef u_long bus_addr_t; +typedef u_long bus_size_t; +typedef u_long bus_space_handle_t; +typedef struct mips_bus_space *bus_space_tag_t; +typedef struct mips_bus_space bus_space_t; + +struct mips_bus_space { + bus_addr_t bus_base; + void *bus_private; + u_int8_t (*_space_read_1)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_1)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int8_t); + u_int16_t (*_space_read_2)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_2)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int16_t); + u_int32_t (*_space_read_4)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_4)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int32_t); + u_int64_t (*_space_read_8)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_8)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int64_t); + void (*_space_read_raw_2)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_2)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + void (*_space_read_raw_4)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_4)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + void (*_space_read_raw_8)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_8)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + int (*_space_map)(bus_space_tag_t , bus_addr_t, + bus_size_t, int, bus_space_handle_t *); + void (*_space_unmap)(bus_space_tag_t, bus_space_handle_t, + bus_size_t); + int (*_space_subregion)(bus_space_tag_t, bus_space_handle_t, + bus_size_t, bus_size_t, bus_space_handle_t *); + void * (*_space_vaddr)(bus_space_tag_t, bus_space_handle_t); +}; + +#define bus_space_read_1(t, h, o) (*(t)->_space_read_1)((t), (h), (o)) +#define bus_space_read_2(t, h, o) (*(t)->_space_read_2)((t), (h), (o)) +#define bus_space_read_4(t, h, o) (*(t)->_space_read_4)((t), (h), (o)) +#define bus_space_read_8(t, h, o) (*(t)->_space_read_8)((t), (h), (o)) + +#define bus_space_write_1(t, h, o, v) (*(t)->_space_write_1)((t), (h), (o), (v)) +#define bus_space_write_2(t, h, o, v) (*(t)->_space_write_2)((t), (h), (o), (v)) +#define bus_space_write_4(t, h, o, v) (*(t)->_space_write_4)((t), (h), (o), (v)) +#define bus_space_write_8(t, h, o, v) (*(t)->_space_write_8)((t), (h), (o), (v)) + +#define bus_space_read_raw_multi_2(t, h, a, b, l) \ + (*(t)->_space_read_raw_2)((t), (h), (a), (b), (l)) +#define bus_space_read_raw_multi_4(t, h, a, b, l) \ + (*(t)->_space_read_raw_4)((t), (h), (a), (b), (l)) +#define bus_space_read_raw_multi_8(t, h, a, b, l) \ + (*(t)->_space_read_raw_8)((t), (h), (a), (b), (l)) + +#define bus_space_write_raw_multi_2(t, h, a, b, l) \ + (*(t)->_space_write_raw_2)((t), (h), (a), (b), (l)) +#define bus_space_write_raw_multi_4(t, h, a, b, l) \ + (*(t)->_space_write_raw_4)((t), (h), (a), (b), (l)) +#define bus_space_write_raw_multi_8(t, h, a, b, l) \ + (*(t)->_space_write_raw_8)((t), (h), (a), (b), (l)) + +#define bus_space_map(t, o, s, c, p) (*(t)->_space_map)((t), (o), (s), (c), (p)) +#define bus_space_unmap(t, h, s) (*(t)->_space_unmap)((t), (h), (s)) +#define bus_space_subregion(t, h, o, s, p) \ + (*(t)->_space_subregion)((t), (h), (o), (s), (p)) + +#define BUS_SPACE_MAP_CACHEABLE 0x01 +#define BUS_SPACE_MAP_KSEG0 0x02 +#define BUS_SPACE_MAP_LINEAR 0x04 +#define BUS_SPACE_MAP_PREFETCHABLE 0x08 + +#define bus_space_vaddr(t, h) (*(t)->_space_vaddr)((t), (h)) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_multi(n,m) \ +static __inline void \ +CAT(bus_space_read_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t o, CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) \ + *x++ = CAT(bus_space_read_,n)(bst, bsh, o); \ +} + +bus_space_read_multi(1,8) +bus_space_read_multi(2,16) +bus_space_read_multi(4,32) +bus_space_read_multi(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_region(n,m) \ +static __inline void \ +CAT(bus_space_read_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) { \ + *x++ = CAT(bus_space_read_,n)(bst, bsh, ba); \ + ba += (n); \ + } \ +} + +bus_space_read_region(1,8) +bus_space_read_region(2,16) +bus_space_read_region(4,32) +bus_space_read_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_raw_region(n,m) \ +static __inline void \ +CAT(bus_space_read_raw_region_,n)(bus_space_tag_t bst, \ + bus_space_handle_t bsh, \ + bus_addr_t ba, u_int8_t *x, size_t cnt) \ +{ \ + cnt >>= ((n) >> 1); \ + while (cnt--) { \ + CAT(bus_space_read_raw_multi_,n)(bst, bsh, ba, x, (n)); \ + ba += (n); \ + x += (n); \ + } \ +} + +bus_space_read_raw_region(2,16) +bus_space_read_raw_region(4,32) +bus_space_read_raw_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_multi(n,m) \ +static __inline void \ +CAT(bus_space_write_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t o, const CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) \ + CAT(bus_space_write_,n)(bst, bsh, o, *x++); \ +} + +bus_space_write_multi(1,8) +bus_space_write_multi(2,16) +bus_space_write_multi(4,32) +bus_space_write_multi(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_region(n,m) \ +static __inline void \ +CAT(bus_space_write_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, const CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) { \ + CAT(bus_space_write_,n)(bst, bsh, ba, *x++); \ + ba += (n); \ + } \ +} + +bus_space_write_region(1,8) +bus_space_write_region(2,16) +bus_space_write_region(4,32) +bus_space_write_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_raw_region(n,m) \ +static __inline void \ +CAT(bus_space_write_raw_region_,n)(bus_space_tag_t bst, \ + bus_space_handle_t bsh, \ + bus_addr_t ba, const u_int8_t *x, size_t cnt) \ +{ \ + cnt >>= ((n) >> 1); \ + while (cnt--) { \ + CAT(bus_space_write_raw_multi_,n)(bst, bsh, ba, x, (n)); \ + ba += (n); \ + x += (n); \ + } \ +} + +bus_space_write_raw_region(2,16) +bus_space_write_raw_region(4,32) +bus_space_write_raw_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_set_region(n,m) \ +static __inline void \ +CAT(bus_space_set_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(u_int,m,_t) x, size_t cnt) \ +{ \ + while (cnt--) { \ + CAT(bus_space_write_,n)(bst, bsh, ba, x); \ + ba += (n); \ + } \ +} + +bus_space_set_region(1,8) +bus_space_set_region(2,16) +bus_space_set_region(4,32) +bus_space_set_region(8,64) + +/*----------------------------------------------------------------------------*/ +static __inline void +bus_space_copy_1(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + char *s = (char *)(h1 + o1); + char *d = (char *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + + +static __inline void +bus_space_copy_2(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + short *s = (short *)(h1 + o1); + short *d = (short *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + +static __inline void +bus_space_copy_4(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + int *s = (int *)(h1 + o1); + int *d = (int *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + +static __inline void +bus_space_copy_8(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + int64_t *s = (int64_t *)(h1 + o1); + int64_t *d = (int64_t *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + +/*----------------------------------------------------------------------------*/ +/* + * Bus read/write barrier methods. + * + * void bus_space_barrier(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * bus_size_t len, int flags); + * + */ +static inline void +bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, + bus_size_t length, int flags) +{ + __asm__ volatile ("sync" ::: "memory"); +} +#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ +#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ + +#define BUS_DMA_WAITOK 0x0000 +#define BUS_DMA_NOWAIT 0x0001 +#define BUS_DMA_ALLOCNOW 0x0002 +#define BUS_DMA_COHERENT 0x0008 +#define BUS_DMA_BUS1 0x0010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x0020 +#define BUS_DMA_BUS3 0x0040 +#define BUS_DMA_BUS4 0x0080 +#define BUS_DMA_READ 0x0100 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x0200 /* mapping is memory -> device only */ +#define BUS_DMA_STREAMING 0x0400 /* hint: sequential, unidirectional */ +#define BUS_DMA_ZERO 0x0800 /* zero memory in dmamem_alloc */ +#define BUS_DMA_NOCACHE 0x1000 +#define BUS_DMA_64BIT 0x2000 /* device handles 64bit dva */ + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct proc; +struct uio; + +#define BUS_DMASYNC_POSTREAD 0x0001 +#define BUS_DMASYNC_POSTWRITE 0x0002 +#define BUS_DMASYNC_PREREAD 0x0004 +#define BUS_DMASYNC_PREWRITE 0x0008 + +typedef struct machine_bus_dma_tag *bus_dma_tag_t; +typedef struct machine_bus_dmamap *bus_dmamap_t; + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +struct machine_bus_dma_segment { + bus_addr_t ds_addr; /* DMA address */ + bus_size_t ds_len; /* length of transfer */ + + paddr_t _ds_paddr; /* CPU address */ + vaddr_t _ds_vaddr; /* CPU address */ +}; +typedef struct machine_bus_dma_segment bus_dma_segment_t; + +/* + * bus_dma_tag_t + * + * A machine-dependent opaque type describing the implementation of + * DMA for a given bus. + */ + +struct machine_bus_dma_tag { + void *_cookie; /* cookie used in the guts */ + + /* + * DMA mapping methods. + */ + int (*_dmamap_create)(bus_dma_tag_t , bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); + void (*_dmamap_destroy)(bus_dma_tag_t , bus_dmamap_t); + int (*_dmamap_load)(bus_dma_tag_t , bus_dmamap_t, void *, + bus_size_t, struct proc *, int); + int (*_dmamap_load_mbuf)(bus_dma_tag_t , bus_dmamap_t, + struct mbuf *, int); + int (*_dmamap_load_uio)(bus_dma_tag_t , bus_dmamap_t, + struct uio *, int); + int (*_dmamap_load_raw)(bus_dma_tag_t , bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); + int (*_dmamap_load_buffer)(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int, paddr_t *, int *, int); + void (*_dmamap_unload)(bus_dma_tag_t , bus_dmamap_t); + void (*_dmamap_sync)(bus_dma_tag_t , bus_dmamap_t, + bus_addr_t, bus_size_t, int); + + /* + * DMA memory utility functions. + */ + int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); + void (*_dmamem_free)(bus_dma_tag_t, bus_dma_segment_t *, int); + int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); + void (*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t); + paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, + int, off_t, int, int); + + /* + * internal memory address translation information. + */ + bus_addr_t (*_pa_to_device)(paddr_t); + paddr_t (*_device_to_pa)(bus_addr_t); + bus_addr_t _dma_mask; +}; + +#define bus_dmamap_create(t, s, n, m, b, f, p) \ + (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) +#define bus_dmamap_destroy(t, p) \ + (*(t)->_dmamap_destroy)((t), (p)) +#define bus_dmamap_load(t, m, b, s, p, f) \ + (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) +#define bus_dmamap_load_mbuf(t, m, b, f) \ + (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) +#define bus_dmamap_load_uio(t, m, u, f) \ + (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) +#define bus_dmamap_load_raw(t, m, sg, n, s, f) \ + (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) +#define bus_dmamap_unload(t, p) \ + (*(t)->_dmamap_unload)((t), (p)) +#define bus_dmamap_sync(t, p, a, l, o) \ + (void)((t)->_dmamap_sync ? \ + (*(t)->_dmamap_sync)((t), (p), (a), (l), (o)) : (void)0) + +#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ + (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f)) +#define bus_dmamem_free(t, sg, n) \ + (*(t)->_dmamem_free)((t), (sg), (n)) +#define bus_dmamem_map(t, sg, n, s, k, f) \ + (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f)) +#define bus_dmamem_unmap(t, k, s) \ + (*(t)->_dmamem_unmap)((t), (k), (s)) +#define bus_dmamem_mmap(t, sg, n, o, p, f) \ + (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f)) + +int _dmamap_create(bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); +void _dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); +int _dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); +int _dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *, int); +int _dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, struct uio *, int); +int _dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); +int _dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int, paddr_t *, int *, int); +void _dmamap_unload(bus_dma_tag_t, bus_dmamap_t); +void _dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, + bus_size_t, int); + +int _dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); +void _dmamem_free(bus_dma_tag_t, bus_dma_segment_t *, int); +int _dmamem_map(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); +void _dmamem_unmap(bus_dma_tag_t, caddr_t, size_t); +paddr_t _dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, int, int); +int _dmamem_alloc_range(bus_dma_tag_t, bus_size_t, bus_size_t, bus_size_t, + bus_dma_segment_t *, int, int *, int, paddr_t, paddr_t); + +/* + * bus_dmamap_t + * + * Describes a DMA mapping. + */ +struct machine_bus_dmamap { + /* + * PRIVATE MEMBERS: not for use by machine-independent code. + */ + bus_size_t _dm_size; /* largest DMA transfer mappable */ + int _dm_segcnt; /* number of segs this map can map */ + bus_size_t _dm_maxsegsz; /* largest possible segment */ + bus_size_t _dm_boundary; /* don't cross this */ + int _dm_flags; /* misc. flags */ + + void *_dm_cookie; /* cookie for bus-specific functions */ + + /* + * PUBLIC MEMBERS: these are used by machine-independent code. + */ + bus_size_t dm_mapsize; /* size of the mapping */ + int dm_nsegs; /* # valid segments in mapping */ + bus_dma_segment_t dm_segs[1]; /* segments; variable length */ +}; + +int generic_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, + bus_space_handle_t *); +void generic_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t); +int generic_space_region(bus_space_tag_t, bus_space_handle_t, bus_size_t, + bus_size_t, bus_space_handle_t *); +void *generic_space_vaddr(bus_space_tag_t, bus_space_handle_t); +uint8_t generic_space_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint16_t generic_space_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint32_t generic_space_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint64_t generic_space_read_8(bus_space_tag_t, bus_space_handle_t, bus_size_t); +void generic_space_read_raw_2(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint8_t); +void generic_space_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint16_t); +void generic_space_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint32_t); +void generic_space_write_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint64_t); +void generic_space_write_raw_2(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); +void generic_space_read_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); +void generic_space_read_raw_8(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_raw_8(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); + +#endif /* _MACHINE_BUS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/cdefs.h b/lib/libc/include/mips64-openbsd-none/octeon/cdefs.h new file mode 100644 index 000000000000..e44353fedfe1 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/cdefs.h @@ -0,0 +1,3 @@ +/* $OpenBSD: cdefs.h,v 1.2 2013/03/28 17:30:45 martynas Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/conf.h b/lib/libc/include/mips64-openbsd-none/octeon/conf.h new file mode 100644 index 000000000000..df1ce719b234 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/conf.h @@ -0,0 +1,55 @@ +/* $OpenBSD: conf.h,v 1.4 2022/06/28 14:43:50 visa Exp $ */ +/* $NetBSD: conf.h,v 1.2 1996/05/05 19:28:34 christos Exp $ */ + +/* + * Copyright (c) 1996 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _OCTEON_CONF_H_ +#define _OCTEON_CONF_H_ + +#include + +/* open, close, ioctl */ +#define cdev_octboot_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) nullop, 0, \ + (dev_type_mmap((*))) enodev } + +/* open, close, ioctl */ +#define cdev_openprom_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) nullop, 0, \ + (dev_type_mmap((*))) enodev } + +cdev_decl(octboot); +cdev_decl(openprom); + +#endif /* _OCTEON_CONF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/cpu.h b/lib/libc/include/mips64-openbsd-none/octeon/cpu.h new file mode 100644 index 000000000000..e5e26d7837a1 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/cpu.h @@ -0,0 +1,106 @@ +/* $OpenBSD: cpu.h,v 1.12 2018/02/18 14:50:08 visa Exp $ */ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell and Rick Macklem. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Copyright (C) 1989 Digital Equipment Corporation. + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies. + * Digital Equipment Corporation makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * from: @(#)cpu.h 8.4 (Berkeley) 1/4/94 + */ + +#ifndef _MACHINE_CPU_H_ +#define _MACHINE_CPU_H_ + +#ifdef _KERNEL + +#define OCTEON_MAXCPUS 16 + +#if defined(MULTIPROCESSOR) && !defined(_LOCORE) +#define MAXCPUS OCTEON_MAXCPUS +struct cpu_info; +void hw_cpu_boot_secondary(struct cpu_info *); +void hw_cpu_hatch(struct cpu_info *); +void hw_cpu_spinup_trampoline(struct cpu_info *); +int hw_ipi_intr_establish(int (*)(void *), u_long); +void hw_ipi_intr_set(u_long); +void hw_ipi_intr_clear(u_long); + +/* Keep in sync with HW_GET_CPU_INFO(). */ +static inline struct cpu_info * +hw_getcurcpu(void) +{ + struct cpu_info *ci; + __asm__ volatile ("dmfc0 %0, $30" /* ErrorEPC */ : "=r" (ci)); + return ci; +} + +static inline void +hw_setcurcpu(struct cpu_info *ci) +{ + __asm__ volatile ("dmtc0 %0, $30" /* ErrorEPC */ : : "r" (ci)); +} +#endif /* MULTIPROCESSOR && !_LOCORE */ + +#define CACHELINESIZE 128 + +/* + * No need to use the per-cpu_info function pointers, as we only support + * one processor type. + */ +#define Mips_SyncCache(ci) \ + Octeon_SyncCache((ci)) +#define Mips_InvalidateICache(ci, va, l) \ + Octeon_InvalidateICache((ci), (va), (l)) +#define Mips_InvalidateICachePage(ci, va) \ + Octeon_InvalidateICachePage((ci), (va)) +#define Mips_SyncICache(ci) \ + Octeon_SyncICache((ci)) +#define Mips_SyncDCachePage(ci, va, pa) \ + Octeon_SyncDCachePage((ci), (va), (pa)) +#define Mips_HitSyncDCachePage(ci, va, pa) \ + Octeon_SyncDCachePage((ci), (va), (pa)) +#define Mips_HitSyncDCache(ci, va, l) \ + Octeon_HitSyncDCache((ci), (va), (l)) +#define Mips_IOSyncDCache(ci, va, l, h) \ + Octeon_IOSyncDCache((ci), (va), (l), (h)) +#define Mips_HitInvalidateDCache(ci, va, l) \ + Octeon_HitInvalidateDCache((ci), (va), (l)) + +#endif/* _KERNEL */ + +#include + +#endif /* !_MACHINE_CPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/cpustate.h b/lib/libc/include/mips64-openbsd-none/octeon/cpustate.h new file mode 100644 index 000000000000..d0dcf0e7c043 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/cpustate.h @@ -0,0 +1,3 @@ +/* $OpenBSD: cpustate.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/db_machdep.h b/lib/libc/include/mips64-openbsd-none/octeon/db_machdep.h new file mode 100644 index 000000000000..3a3271b42382 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/db_machdep.h @@ -0,0 +1,3 @@ +/* $OpenBSD: db_machdep.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/disklabel.h b/lib/libc/include/mips64-openbsd-none/octeon/disklabel.h new file mode 100644 index 000000000000..e7758205f60b --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/disklabel.h @@ -0,0 +1,16 @@ +/* $OpenBSD: disklabel.h,v 1.3 2015/09/30 15:35:30 krw Exp $ */ +/* public domain */ + +/* + * Standard MBR partition scheme, with the label in the second sector + * of the OpenBSD partition. + */ + +#ifndef _MACHINE_DISKLABEL_H_ +#define _MACHINE_DISKLABEL_H_ + +#define LABELSECTOR 1 /* sector containing label */ +#define LABELOFFSET 0 /* offset of label in sector */ +#define MAXPARTITIONS 16 /* number of partitions */ + +#endif /* _MACHINE_DISKLABEL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/elf.h b/lib/libc/include/mips64-openbsd-none/octeon/elf.h new file mode 100644 index 000000000000..5918df727bda --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/elf.h @@ -0,0 +1,3 @@ +/* $OpenBSD: elf.h,v 1.1 2024/07/14 19:33:59 miod Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/endian.h b/lib/libc/include/mips64-openbsd-none/octeon/endian.h new file mode 100644 index 000000000000..2bfd2b1abd1c --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/endian.h @@ -0,0 +1,3 @@ +/* $OpenBSD: endian.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/exec.h b/lib/libc/include/mips64-openbsd-none/octeon/exec.h new file mode 100644 index 000000000000..498f7f2ecac3 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/exec.h @@ -0,0 +1,3 @@ +/* $OpenBSD: exec.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/fdt.h b/lib/libc/include/mips64-openbsd-none/octeon/fdt.h new file mode 100644 index 000000000000..4033bc9a0c80 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/fdt.h @@ -0,0 +1,40 @@ +/* $OpenBSD: fdt.h,v 1.2 2018/08/06 10:52:30 patrick Exp $ */ + +/* + * Copyright (c) 2016 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __OCTEON_FDT_H__ +#define __OCTEON_FDT_H__ + +#include + +struct fdt_attach_args { + const char *fa_name; + int fa_node; + bus_space_tag_t fa_iot; + bus_dma_tag_t fa_dmat; + struct fdt_reg *fa_reg; + int fa_nreg; + uint32_t *fa_intr; + int fa_nintr; + int fa_acells; + int fa_scells; +}; + +#define fdt_intr_establish octeon_intr_establish_fdt +#define fdt_intr_disestablish octeon_intr_disestablish_fdt + +#endif /* __OCTEON_FDT_H__ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/fenv.h b/lib/libc/include/mips64-openbsd-none/octeon/fenv.h new file mode 100644 index 000000000000..08e89fbf323e --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/fenv.h @@ -0,0 +1,3 @@ +/* $OpenBSD: fenv.h,v 1.2 2013/06/01 21:20:54 jasper Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/fpu.h b/lib/libc/include/mips64-openbsd-none/octeon/fpu.h new file mode 100644 index 000000000000..3d415d39b475 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/fpu.h @@ -0,0 +1,3 @@ +/* $OpenBSD: fpu.h,v 1.1 2010/10/03 06:03:57 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/frame.h b/lib/libc/include/mips64-openbsd-none/octeon/frame.h new file mode 100644 index 000000000000..f8295979a3c4 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/frame.h @@ -0,0 +1,3 @@ +/* $OpenBSD: frame.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/ieee.h b/lib/libc/include/mips64-openbsd-none/octeon/ieee.h new file mode 100644 index 000000000000..8a538bc8eb50 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/ieee.h @@ -0,0 +1,3 @@ +/* $OpenBSD: ieee.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/ieeefp.h b/lib/libc/include/mips64-openbsd-none/octeon/ieeefp.h new file mode 100644 index 000000000000..2060e7a21f34 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/ieeefp.h @@ -0,0 +1,3 @@ +/* $OpenBSD: ieeefp.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/intr.h b/lib/libc/include/mips64-openbsd-none/octeon/intr.h new file mode 100644 index 000000000000..eef4afc72890 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/intr.h @@ -0,0 +1,186 @@ +/* $OpenBSD: intr.h,v 1.23 2025/05/10 10:01:03 visa Exp $ */ + +/* + * Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _MACHINE_INTR_H_ +#define _MACHINE_INTR_H_ + +#define __USE_MI_SOFTINTR + +#include + +/* + * The interrupt level ipl is a logical level; per-platform interrupt + * code will turn it into the appropriate hardware interrupt masks + * values. + * + * Interrupt sources on the CPU are kept enabled regardless of the + * current ipl value; individual hardware sources interrupting while + * logically masked are masked on the fly, remembered as pending, and + * unmasked at the first splx() opportunity. + * + * An exception to this rule is the clock interrupt. Clock interrupts + * are always allowed to happen, but will (of course!) not be serviced + * if logically masked. The reason for this is that clocks usually sit on + * INT5 and cannot be easily masked if external hardware masking is used. + */ + +/* Interrupt priority `levels'; not mutually exclusive. */ +#define IPL_NONE 0 /* nothing */ +#define IPL_SOFTINT 1 /* soft interrupts */ +#define IPL_SOFTCLOCK 1 /* soft clock interrupts */ +#define IPL_SOFTNET 2 /* soft network interrupts */ +#define IPL_SOFTTTY 3 /* soft terminal interrupts */ +#define IPL_SOFTHIGH IPL_SOFTTTY /* highest level of soft interrupts */ +#define IPL_BIO 4 /* block I/O */ +#define IPL_AUDIO IPL_BIO +#define IPL_NET 5 /* network */ +#define IPL_TTY 6 /* terminal */ +#define IPL_VM 7 /* memory allocation */ +#define IPL_CLOCK 8 /* clock */ +#define IPL_SCHED IPL_CLOCK +#define IPL_HIGH 9 /* everything */ +#define IPL_IPI 10 /* interprocessor interrupt */ +#define NIPLS 11 /* number of levels */ + +#define IPL_MPFLOOR IPL_TTY + +/* Interrupt priority 'flags'. */ +#define IPL_MPSAFE 0x100 + +/* Interrupt sharing types. */ +#define IST_NONE 0 /* none */ +#define IST_PULSE 1 /* pulsed */ +#define IST_EDGE 2 /* edge-triggered */ +#define IST_LEVEL 3 /* level-triggered */ + +#ifndef _LOCORE + +void softintr(int); + +#define splbio() splraise(IPL_BIO) +#define splnet() splraise(IPL_NET) +#define spltty() splraise(IPL_TTY) +#define splaudio() splraise(IPL_AUDIO) +#define splvm() splraise(IPL_VM) +#define splclock() splraise(IPL_CLOCK) +#define splsched() splraise(IPL_SCHED) +#define splhigh() splraise(IPL_HIGH) + +#define splsoftclock() splraise(IPL_SOFTCLOCK) +#define splsoftnet() splraise(IPL_SOFTNET) +#define splstatclock() splhigh() + +#define spl0() spllower(0) + +void splinit(void); + +#ifdef DIAGNOSTIC +/* + * Although this function is implemented in MI code, it must be in this MD + * header because we don't want this header to include MI includes. + */ +void splassert_fail(int, int, const char *); +extern int splassert_ctl; +void splassert_check(int, const char *); +#define splassert(__wantipl) do { \ + if (splassert_ctl > 0) { \ + splassert_check(__wantipl, __func__); \ + } \ +} while (0) +#define splsoftassert(wantipl) splassert(wantipl) +#else +#define splassert(X) +#define splsoftassert(X) +#endif + +void register_splx_handler(void (*)(int)); +int splraise(int); +void splx(int); +int spllower(int); + +void intr_barrier(void *); + +/* + * Low level interrupt dispatcher registration data. + */ + +/* Schedule priorities for base interrupts (CPU) */ +#define INTPRI_IPI 0 +#define INTPRI_CLOCK 1 +/* other values are system-specific */ + +#define NLOWINT 16 /* Number of low level registrations possible */ + +extern uint32_t idle_mask; + +struct trapframe; +void set_intr(int, uint32_t, uint32_t(*)(uint32_t, struct trapframe *)); + +uint32_t updateimask(uint32_t); +void dosoftint(void); + +struct intr_controller { + void *ic_cookie; + void (*ic_init)(void); + void *(*ic_establish)(int, int, int (*)(void *), void *, + const char *); + void *(*ic_establish_fdt_idx)(void *, int, int, int, + int (*)(void *), void *, const char *); + void (*ic_disestablish)(void *); + void (*ic_intr_barrier)(void *); + +#ifdef MULTIPROCESSOR + int (*ic_ipi_establish)(int (*)(void *), cpuid_t); + void (*ic_ipi_set)(cpuid_t); + void (*ic_ipi_clear)(cpuid_t); +#endif /* MULTIPROCESSOR */ + + int ic_node; + int ic_phandle; + LIST_ENTRY(intr_controller) ic_list; +}; + +#ifdef MULTIPROCESSOR +#define ENABLEIPI() updateimask(~CR_INT_1) /* enable IPI interrupt level */ +#endif + +void *octeon_intr_establish(int, int, int (*)(void *), + void *, const char *); +void octeon_intr_disestablish(void *); +void octeon_intr_init(void); +void octeon_intr_register(struct intr_controller *); + +void *octeon_intr_establish_fdt(int, int, int (*)(void *), + void *, const char *); +void *octeon_intr_establish_fdt_idx(int, int, int, int (*)(void *), + void *, const char *); +void octeon_intr_disestablish_fdt(void *); + +#endif /* _LOCORE */ + +#endif /* _MACHINE_INTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/kcore.h b/lib/libc/include/mips64-openbsd-none/octeon/kcore.h new file mode 100644 index 000000000000..b221eb2048f0 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/kcore.h @@ -0,0 +1,3 @@ +/* $OpenBSD: kcore.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/limits.h b/lib/libc/include/mips64-openbsd-none/octeon/limits.h new file mode 100644 index 000000000000..06574d0acb3c --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/limits.h @@ -0,0 +1,3 @@ +/* $OpenBSD: limits.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/loadfile_machdep.h b/lib/libc/include/mips64-openbsd-none/octeon/loadfile_machdep.h new file mode 100644 index 000000000000..1486f8ce5c75 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/loadfile_machdep.h @@ -0,0 +1,49 @@ +/* $OpenBSD: loadfile_machdep.h,v 1.2 2015/07/17 20:44:39 miod Exp $ */ +/* $NetBSD: loadfile_machdep.h,v 1.2 2001/10/31 17:20:49 thorpej Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define BOOT_ELF +#define ELFSIZE 64 + +#define LOAD_KERNEL LOAD_ALL +#define COUNT_KERNEL COUNT_ALL + +#define LOADADDR(a) (((u_long)(a)) + offset) +#define ALIGNENTRY(a) ((u_long)(a)) +#define READ(f, b, c) read((f), (void *)LOADADDR(b), (c)) +#define BCOPY(s, d, c) memcpy((void *)LOADADDR(d), (void *)(s), (c)) +#define BZERO(d, c) memset((void *)LOADADDR(d), 0, (c)) +#define WARN(a) (void)(printf a, \ + printf((errno ? ": %s\n" : "\n"), \ + strerror(errno))) +#define PROGRESS(a) (void) printf a +#define ALLOC(a) alloc(a) +#define FREE(a, b) free(a, b) \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/memconf.h b/lib/libc/include/mips64-openbsd-none/octeon/memconf.h new file mode 100644 index 000000000000..ec2791c749fb --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/memconf.h @@ -0,0 +1,3 @@ +/* $OpenBSD: memconf.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/mips_opcode.h b/lib/libc/include/mips64-openbsd-none/octeon/mips_opcode.h new file mode 100644 index 000000000000..865ce02ebee4 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/mips_opcode.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mips_opcode.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/mplock.h b/lib/libc/include/mips64-openbsd-none/octeon/mplock.h new file mode 100644 index 000000000000..f15d10954559 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/mplock.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mplock.h,v 1.2 2015/09/09 15:48:52 visa Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/mutex.h b/lib/libc/include/mips64-openbsd-none/octeon/mutex.h new file mode 100644 index 000000000000..9a15499276d2 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/mutex.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mutex.h,v 1.3 2015/07/08 13:37:31 dlg Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/octboot.h b/lib/libc/include/mips64-openbsd-none/octeon/octboot.h new file mode 100644 index 000000000000..1a889f7b6ac7 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/octboot.h @@ -0,0 +1,36 @@ +/* $OpenBSD: octboot.h,v 1.2 2020/05/26 13:21:58 visa Exp $ */ + +/* + * Copyright (c) 2019-2020 Visa Hankala + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _OCTEON_OCTBOOT_H_ +#define _OCTEON_OCTBOOT_H_ + +#include + +#define OCTBOOT_MAX_ARGS 8 /* maximum number of boot arguments */ + +struct octboot_kexec_args { + char *kimg; /* kernel image buffer */ + size_t klen; /* size of kernel image */ + char *argv[OCTBOOT_MAX_ARGS]; + /* kernel boot arguments */ +}; + +#define OBIOC_KEXEC _IOW('O', 1, struct octboot_kexec_args) +#define OBIOC_GETROOTDEV _IOR('O', 2, char[PATH_MAX]) + +#endif /* !_OCTEON_OCTBOOT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/octeon_model.h b/lib/libc/include/mips64-openbsd-none/octeon/octeon_model.h new file mode 100644 index 000000000000..cac7c19ef93b --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/octeon_model.h @@ -0,0 +1,87 @@ +/* $OpenBSD: octeon_model.h,v 1.9 2024/06/26 01:40:49 jsg Exp $ */ + +/* + * Copyright (c) 2007 + * Internet Initiative Japan, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MIPS_OCTEON_MODEL_H_ +#define _MIPS_OCTEON_MODEL_H_ + +#define OCTEON_MODEL_CN38XX_REV1 0x000d0000 +#define OCTEON_MODEL_CN38XX_REV2 0x000d0001 +#define OCTEON_MODEL_CN38XX_REV3 0x000d0003 +#define OCTEON_MODEL_CN3100 0x000d0100 +#define OCTEON_MODEL_CN3020 0x000d0110 +#define OCTEON_MODEL_CN3010 0x000d0200 +#define OCTEON_MODEL_CN3005 0x000d0210 +#define OCTEON_MODEL_CN5010 0x000d0600 +#define OCTEON_MODEL_CN5010_PASS1_1 0x000d0601 +#define OCTEON_MODEL_CN61XX_PASS1_0 0x000d9300 +#define OCTEON_MODEL_CN61XX_PASS1_1 0x000d9301 + +#define OCTEON_MODEL_MASK 0x00ffff10 +#define OCTEON_MODEL_REV_MASK 0x00ffff1f +#define OCTEON_MODEL_FAMILY_MASK 0x00ffff00 +#define OCTEON_MODEL_FAMILY_REV_MASK 0x00ffff0f + +#define OCTEON_MODEL_FAMILY_CN58XX 0x000d0300 +#define OCTEON_MODEL_FAMILY_CN56XX 0x000d0400 +#define OCTEON_MODEL_FAMILY_CN38XX 0x000d0000 +#define OCTEON_MODEL_FAMILY_CN31XX 0x000d0100 +#define OCTEON_MODEL_FAMILY_CN30XX 0x000d0200 +#define OCTEON_MODEL_FAMILY_CN50XX 0x000d0600 +#define OCTEON_MODEL_FAMILY_CN63XX 0x000d9000 +#define OCTEON_MODEL_FAMILY_CN68XX 0x000d9100 +#define OCTEON_MODEL_FAMILY_CN66XX 0x000d9200 +#define OCTEON_MODEL_FAMILY_CN61XX 0x000d9300 +#define OCTEON_MODEL_FAMILY_CN78XX 0x000d9500 +#define OCTEON_MODEL_FAMILY_CN71XX 0x000d9600 +#define OCTEON_MODEL_FAMILY_CN73XX 0x000d9700 + +/* + * get chip id + */ +static inline uint32_t +octeon_get_chipid(void) +{ + uint32_t tmp; + + asm volatile ( + " .set push \n" + " .set mips64 \n" + " .set noreorder \n" + " mfc0 %0, $15, 0 \n" + " .set pop \n" + : "=&r"(tmp) : ); + + return(tmp); +} + +#define octeon_model(id) ((id) & OCTEON_MODEL_MASK) +#define octeon_model_revision(id) ((id) & OCTEON_MODEL_REV_MASK) +#define octeon_model_family(id) ((id) & OCTEON_MODEL_FAMILY_MASK) +#define octeon_model_family_revision(id) ((id) & OCTEON_MODEL_FAMILY_REV_MASK) + +#endif \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/octeonreg.h b/lib/libc/include/mips64-openbsd-none/octeon/octeonreg.h new file mode 100644 index 000000000000..af75e6d7fbb4 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/octeonreg.h @@ -0,0 +1,198 @@ +/* $OpenBSD: octeonreg.h,v 1.11 2020/07/11 15:18:08 visa Exp $ */ + +/* + * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.com). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _MACHINE_OCTEONREG_H_ +#define _MACHINE_OCTEONREG_H_ + +#define OCTEON_CF_BASE 0x1D000800ULL +#define OCTEON_CIU3_BASE 0x1010000000000ULL +#define OCTEON_CIU_BASE 0x1070000000000ULL +#define OCTEON_CIU_SIZE 0x7000 +#define OCTEON_MIO_BOOT_BASE 0x1180000000000ULL +#define OCTEON_UART0_BASE 0x1180000000800ULL +#define OCTEON_UART1_BASE 0x1180000000C00ULL +#define OCTEON_RNG_BASE 0x1400000000000ULL +#define OCTEON_AMDCF_BASE 0x1dc00000ULL + +#define MIO_BOOT_REG_CFG0 0x0 +#define MIO_BOOT_REG_CFG(x) (MIO_BOOT_REG_CFG0+((x)*8)) +#define BOOT_CFG_BASE_MASK 0xFFFF +#define BOOT_CFG_BASE_SHIFT 16 +#define BOOT_CFG_WIDTH_MASK 0x10000000 +#define BOOT_CFG_WIDTH_SHIFT 28 + +#define CIU_INT_WORKQ0 0 +#define CIU_INT_WORKQ1 1 +#define CIU_INT_WORKQ2 2 +#define CIU_INT_WORKQ3 3 +#define CIU_INT_WORKQ4 4 +#define CIU_INT_WORKQ5 5 +#define CIU_INT_WORKQ6 6 +#define CIU_INT_WORKQ7 7 +#define CIU_INT_WORKQ8 8 +#define CIU_INT_WORKQ9 9 +#define CIU_INT_WORKQ10 10 +#define CIU_INT_WORKQ11 11 +#define CIU_INT_WORKQ12 12 +#define CIU_INT_WORKQ13 13 +#define CIU_INT_WORKQ14 14 +#define CIU_INT_WORKQ15 15 +#define CIU_INT_GPIO0 16 +#define CIU_INT_GPIO1 17 +#define CIU_INT_GPIO2 18 +#define CIU_INT_GPIO3 19 +#define CIU_INT_GPIO4 20 +#define CIU_INT_GPIO5 21 +#define CIU_INT_GPIO6 22 +#define CIU_INT_GPIO7 23 +#define CIU_INT_GPIO8 24 +#define CIU_INT_GPIO9 25 +#define CIU_INT_GPIO10 26 +#define CIU_INT_GPIO11 27 +#define CIU_INT_GPIO12 28 +#define CIU_INT_GPIO13 29 +#define CIU_INT_GPIO14 30 +#define CIU_INT_GPIO15 31 +#define CIU_INT_MBOX0 32 +#define CIU_INT_MBOX1 33 +#define CIU_INT_MBOX(x) (CIU_INT_MBOX0+(x)) +#define CIU_INT_UART0 34 +#define CIU_INT_UART1 35 +#define CIU_INT_PCI_INTA 36 +#define CIU_INT_PCI_INTB 37 +#define CIU_INT_PCI_INTC 38 +#define CIU_INT_PCI_INTD 39 +#define CIU_INT_PCI_MSIA 40 +#define CIU_INT_PCI_MSIB 41 +#define CIU_INT_PCI_MSIC 42 +#define CIU_INT_PCI_MSID 43 +#define CIU_INT_44 44 +#define CIU_INT_TWSI 45 +#define CIU_INT_RML 46 +#define CIU_INT_TRACE 47 +#define CIU_INT_GMX_DRP0 48 +#define CIU_INT_GMX_DRP1 49 +#define CIU_INT_IPD_DRP 50 +#define CIU_INT_KEY_ZERO 51 +#define CIU_INT_TIMER0 52 +#define CIU_INT_TIMER1 53 +#define CIU_INT_TIMER2 54 +#define CIU_INT_TIMER3 55 +#define CIU_INT_USB 56 +#define CIU_INT_PCM 57 +#define CIU_INT_MPI 58 +#define CIU_INT_TWSI2 59 +#define CIU_INT_POWIQ 60 +#define CIU_INT_IPDPPTHR 61 +#define CIU_INT_MII0 62 +#define CIU_INT_BOOTDMA 63 + +#define CIU_INT0_SUM0 0x00000000 +#define CIU_INT1_SUM0 0x00000008 +#define CIU_INT2_SUM0 0x00000010 +#define CIU_INT3_SUM0 0x00000018 +#define CIU_IP2_SUM0(x) (CIU_INT0_SUM0+(0x10 * (x))) +#define CIU_IP3_SUM0(x) (CIU_INT1_SUM0+(0x10 * (x))) +#define CIU_INT32_SUM0 0x00000100 +#define CIU_INT32_SUM1 0x00000108 +#define CIU_INT0_EN0 0x00000200 +#define CIU_INT1_EN0 0x00000210 +#define CIU_INT2_EN0 0x00000220 +#define CIU_INT3_EN0 0x00000230 +#define CIU_IP2_EN0(x) (CIU_INT0_EN0+(0x20 * (x))) +#define CIU_IP3_EN0(x) (CIU_INT1_EN0+(0x20 * (x))) +#define CIU_INT32_EN0 0x00000400 +#define CIU_INT0_EN1 0x00000208 +#define CIU_INT1_EN1 0x00000218 +#define CIU_INT2_EN1 0x00000228 +#define CIU_INT3_EN1 0x00000238 +#define CIU_INT32_EN1 0x00000408 +#define CIU_IP2_EN1(x) (CIU_INT0_EN1+(0x20 * (x))) +#define CIU_IP3_EN1(x) (CIU_INT1_EN1+(0x20 * (x))) +#define CIU_TIM0 0x00000480 +#define CIU_TIM1 0x00000488 +#define CIU_TIM2 0x00000490 +#define CIU_TIM3 0x00000498 +#define CIU_WDOG0 0x00000500 +#define CIU_WDOG1 0x00000508 +#define CIU_PP_POKE0 0x00000580 +#define CIU_PP_POKE1 0x00000588 +#define CIU_MBOX_SET0 0x00000600 +#define CIU_MBOX_SET1 0x00000608 +#define CIU_MBOX_SET(x) (CIU_MBOX_SET0+(0x08 * (x))) +#define CIU_MBOX_CLR0 0x00000680 +#define CIU_MBOX_CLR1 0x00000688 +#define CIU_MBOX_CLR(x) (CIU_MBOX_CLR0+(0x08 * (x))) +#define CIU_PP_RST 0x00000700 +#define CIU_PP_DBG 0x00000708 +#define CIU_GSTOP 0x00000710 +#define CIU_NMI 0x00000718 +#define CIU_DINT 0x00000720 +#define CIU_FUSE 0x00000728 +#define CIU_BIST 0x00000730 +#define CIU_SOFT_BIST 0x00000738 +#define CIU_SOFT_RST 0x00000740 +#define CIU_SOFT_PRST 0x00000748 +#define CIU_PCI_INTA 0x00000750 +#define CIU_INT0_SUM4 0x00000C00 +#define CIU_INT1_SUM4 0x00000C08 +#define CIU_INT0_EN4_0 0x00000C80 +#define CIU_INT1_EN4_0 0x00000C90 +#define CIU_INT0_EN4_1 0x00000C88 +#define CIU_INT1_EN4_1 0x00000C98 +#define CIU_IP4_SUM2(x) (0x00008c00 + 8 * (x)) +#define CIU_IP4_EN2(x) (0x0000a400 + 8 * (x)) + +#define CIU3_FUSE 0x000001a0 + +#define FPA3_CLK_COUNT 0x12800000000f0ULL + +/* OCTEON II */ +#define MIO_RST_BOOT 0x1180000001600ULL +#define MIO_RST_BOOT_C_MUL_SHIFT 30 +#define MIO_RST_BOOT_C_MUL_MASK 0x7f +#define MIO_RST_BOOT_PNR_MUL_SHIFT 24 +#define MIO_RST_BOOT_PNR_MUL_MASK 0x3f + +#define MIO_RST_CTL(x) (0x1180000001618ULL + 8 * (x)) +#define MIO_RST_CTL_PRTMODE 0x0000000000000030ULL + +/* OCTEON III */ +#define RST_BOOT 0x1180006001600ULL +#define RST_BOOT_C_MUL_SHIFT 30 +#define RST_BOOT_C_MUL_MASK 0x7f +#define RST_BOOT_PNR_MUL_SHIFT 24 +#define RST_BOOT_PNR_MUL_MASK 0x3f +#define RST_CTL(x) (0x1180006001640ULL + 8 * (x)) +#define RST_CTL_RST_DONE 0x0000000000000100ULL +#define RST_CTL_HOST_MODE 0x0000000000000040ULL +#define RST_SOFT_RST 0x1180006001680ULL + +#define OCTEON_IO_REF_CLOCK 50000000 /* 50MHz */ + +#endif /* !_MACHINE_OCTEONREG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/octeonvar.h b/lib/libc/include/mips64-openbsd-none/octeon/octeonvar.h new file mode 100644 index 000000000000..cc0f782bf38e --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/octeonvar.h @@ -0,0 +1,498 @@ +/* $OpenBSD: octeonvar.h,v 1.54 2022/08/29 02:01:18 jsg Exp $ */ +/* $NetBSD: maltavar.h,v 1.3 2002/03/18 10:10:16 simonb Exp $ */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MIPS_OCTEON_OCTEONVAR_H_ +#define _MIPS_OCTEON_OCTEONVAR_H_ + +#include + +/* XXX elsewhere */ +#define _ASM_PROLOGUE \ + " .set push \n" \ + " .set noreorder \n" +#define _ASM_PROLOGUE_MIPS64 \ + _ASM_PROLOGUE \ + " .set mips64 \n" +#define _ASM_PROLOGUE_OCTEON \ + _ASM_PROLOGUE \ + " .set arch=octeon \n" +#define _ASM_EPILOGUE \ + " .set pop \n" +/* + * subbits = __BITS64_GET(XXX, bits); + * bits = __BITS64_SET(XXX, subbits); + */ +#ifndef __BITS64_GET +#define __BITS64_GET(name, bits) \ + (((uint64_t)(bits) & name) >> name##_SHIFT) +#endif +#ifndef __BITS64_SET +#define __BITS64_SET(name, subbits) \ + (((uint64_t)(subbits) << name##_SHIFT) & name) +#endif + +struct octeon_config { + bus_space_tag_t mc_iobus_bust; + bus_space_tag_t mc_bootbus_bust; + + bus_dma_tag_t mc_iobus_dmat; + bus_dma_tag_t mc_bootbus_dmat; +}; + +#define GPIO_CONFIG_MD_OUTPUT_SEL_MASK (GPIO_CONFIG_MD0 | GPIO_CONFIG_MD1) +#define GPIO_CONFIG_MD_USB0_VBUS_CTRL GPIO_CONFIG_MD0 +#define GPIO_CONFIG_MD_USB1_VBUS_CTRL GPIO_CONFIG_MD1 + +/* + * FPA map + */ + +#define OCTEON_POOL_NO_PKT 0 +#define OCTEON_POOL_NO_WQE 1 +#define OCTEON_POOL_NO_CMD 2 +#define OCTEON_POOL_NO_SG 3 +#define OCTEON_POOL_NO_XXX_4 4 +#define OCTEON_POOL_NO_XXX_5 5 +#define OCTEON_POOL_NO_XXX_6 6 +#define OCTEON_POOL_NO_DUMP 7 /* FPA debug dump */ + +#define OCTEON_POOL_SIZE_PKT 1920 /* 128 x 15 */ +#define OCTEON_POOL_SIZE_WQE 128 /* 128 x 1 */ +#define OCTEON_POOL_SIZE_CMD 1024 /* 128 x 8 */ +#define OCTEON_POOL_SIZE_SG 128 /* 128 x 1 */ +#define OCTEON_POOL_SIZE_XXX_4 0 +#define OCTEON_POOL_SIZE_XXX_5 0 +#define OCTEON_POOL_SIZE_XXX_6 0 +#define OCTEON_POOL_SIZE_XXX_7 0 + +#define OCTEON_POOL_NELEMS_PKT 4096 +#define OCTEON_POOL_NELEMS_WQE 4096 +#define OCTEON_POOL_NELEMS_CMD 32 +#define OCTEON_POOL_NELEMS_SG 4096 +#define OCTEON_POOL_NELEMS_XXX_4 0 +#define OCTEON_POOL_NELEMS_XXX_5 0 +#define OCTEON_POOL_NELEMS_XXX_6 0 +#define OCTEON_POOL_NELEMS_XXX_7 0 + +/* + * CVMSEG (``scratch'') memory map + */ +struct octeon_cvmseg_map { + uint64_t csm_pow_intr; + + struct octeon_cvmseg_ether_map { + uint64_t csm_ether_fau_done; + } csm_ether[12/* XXX */]; +} __packed; +#define OCTEON_CVMSEG_OFFSET(entry) \ + offsetof(struct octeon_cvmseg_map, entry) +#define OCTEON_CVMSEG_ETHER_OFFSET(n, entry) \ + (offsetof(struct octeon_cvmseg_map, csm_ether) + \ + sizeof(struct octeon_cvmseg_ether_map) * (n) + \ + offsetof(struct octeon_cvmseg_ether_map, entry)) + +/* + * FAU register map + * + * => FAU registers exist in FAU unit + * => devices (PKO) can access these registers + * => CPU can read those values after loading them into CVMSEG + */ +struct octeon_fau_map { + struct { + /* PKO command index */ + uint64_t _fau_map_port_pkocmdidx; + /* send requested */ + uint64_t _fau_map_port_txreq; + /* send completed */ + uint64_t _fau_map_port_txdone; + /* XXX */ + uint64_t _fau_map_port_pad; + } __packed _fau_map_port[3]; +}; + +/* + * POW qos/group map + */ + +#define OCTEON_POW_QOS_PIP 0 +#define OCTEON_POW_QOS_CORE1 1 +#define OCTEON_POW_QOS_XXX_2 2 +#define OCTEON_POW_QOS_XXX_3 3 +#define OCTEON_POW_QOS_XXX_4 4 +#define OCTEON_POW_QOS_XXX_5 5 +#define OCTEON_POW_QOS_XXX_6 6 +#define OCTEON_POW_QOS_XXX_7 7 + +#define OCTEON_POW_GROUP_MAX 16 + +enum cnmac_stat { + cnmac_stat_rx_toto_gmx, + cnmac_stat_rx_totp_gmx, + cnmac_stat_rx_toto_pip, + cnmac_stat_rx_totp_pip, + cnmac_stat_rx_h64, + cnmac_stat_rx_h127, + cnmac_stat_rx_h255, + cnmac_stat_rx_h511, + cnmac_stat_rx_h1023, + cnmac_stat_rx_h1518, + cnmac_stat_rx_hmax, + cnmac_stat_rx_bcast, + cnmac_stat_rx_mcast, + cnmac_stat_rx_qdpo, + cnmac_stat_rx_qdpp, + cnmac_stat_rx_fcs, + cnmac_stat_rx_frag, + cnmac_stat_rx_undersz, + cnmac_stat_rx_jabber, + cnmac_stat_rx_oversz, + cnmac_stat_rx_raw, + cnmac_stat_rx_bad, + cnmac_stat_rx_drop, + cnmac_stat_rx_ctl, + cnmac_stat_rx_dmac, + cnmac_stat_tx_toto, + cnmac_stat_tx_totp, + cnmac_stat_tx_hmin, + cnmac_stat_tx_h64, + cnmac_stat_tx_h127, + cnmac_stat_tx_h255, + cnmac_stat_tx_h511, + cnmac_stat_tx_h1023, + cnmac_stat_tx_h1518, + cnmac_stat_tx_hmax, + cnmac_stat_tx_bcast, + cnmac_stat_tx_mcast, + cnmac_stat_tx_coll, + cnmac_stat_tx_defer, + cnmac_stat_tx_scol, + cnmac_stat_tx_mcol, + cnmac_stat_tx_ctl, + cnmac_stat_tx_uflow, + cnmac_stat_count +}; + +#if defined(_KERNEL) || defined(_STANDALONE) +#define OCTEON_ARGV_MAX 64 + +/* + * OCTEON board types recognized by OpenBSD/octeon. + * + * It is fine to use BOARD_UNKNOWN when the board does not need + * special treatment. + */ +enum octeon_board { + BOARD_UNKNOWN, + BOARD_CHECKPOINT_N100, + BOARD_CN3010_EVB_HS5, + BOARD_DLINK_DSR_500, + BOARD_NETGEAR_UTM25, + BOARD_RHINOLABS_UTM8, + BOARD_UBIQUITI_E100, + BOARD_UBIQUITI_E120, + BOARD_UBIQUITI_E200, + BOARD_UBIQUITI_E220, + BOARD_UBIQUITI_E300, + BOARD_UBIQUITI_E1000, +}; + +struct boot_desc { + uint32_t desc_ver; + uint32_t desc_size; + uint64_t stack_top; + uint64_t heap_start; + uint64_t heap_end; + uint64_t __unused17; + uint64_t __unused16; + uint32_t __unused18; + uint32_t __unused15; + uint32_t __unused14; + uint32_t argc; + uint32_t argv[OCTEON_ARGV_MAX]; + uint32_t flags; + uint32_t core_mask; + uint32_t dram_size; + uint32_t phy_mem_desc_addr; + uint32_t debugger_flag_addr; + uint32_t eclock; + uint32_t __unused10; + uint32_t __unused9; + uint16_t __unused8; + uint8_t __unused7; + uint8_t __unused6; + uint16_t __unused5; + uint8_t __unused4; + uint8_t __unused3; + uint8_t __unused2[20]; + uint8_t __unused1[6]; + uint8_t __unused0; + uint64_t boot_info_addr; +}; + +struct boot_info { + uint32_t ver_major; + uint32_t ver_minor; + uint64_t stack_top; + uint64_t heap_start; + uint64_t heap_end; + uint64_t boot_desc_addr; + uint32_t exception_base_addr; + uint32_t stack_size; + uint32_t flags; + uint32_t core_mask; + uint32_t dram_size; + uint32_t phys_mem_desc_addr; + uint32_t debugger_flags_addr; + uint32_t eclock; + uint32_t dclock; + uint32_t __unused0; + uint16_t board_type; + uint8_t board_rev_major; + uint8_t board_rev_minor; + uint16_t __unused1; + uint8_t __unused2; + uint8_t __unused3; + char board_serial[20]; + uint8_t mac_addr_base[6]; + uint8_t mac_addr_count; + uint64_t cf_common_addr; + uint64_t cf_attr_addr; + uint64_t led_display_addr; + uint32_t dfaclock; + uint32_t config_flags; + /* The fields below are available when ver_minor >= 3. */ + uint64_t fdt_addr; +}; + +struct octeon_bootmem_desc { + uint32_t lock; + uint32_t flags; + uint64_t head_addr; + uint32_t major_version; + uint32_t minor_version; + uint64_t app_data_addr; + uint64_t app_data_size; + uint32_t named_block_num_blocks; + uint32_t named_block_name_len; + uint64_t named_block_array_addr; +}; + +struct octeon_bootmem_block { + uint64_t next; + uint64_t size; +}; + +extern enum octeon_board octeon_board; +extern struct boot_desc *octeon_boot_desc; +extern struct boot_info *octeon_boot_info; + +#ifdef _KERNEL +/* Device capabilities advertised in boot_info->config_flags */ +#define BOOTINFO_CFG_FLAG_PCI_HOST (1ull << 0) +#define BOOTINFO_CFG_FLAG_PCI_TARGET (1ull << 1) +#define BOOTINFO_CFG_FLAG_DEBUG (1ull << 2) +#define BOOTINFO_CFG_FLAG_NO_MAGIC (1ull << 3) + +#define BOOTMEM_BLOCK_ALIGN 16 +#define BOOTMEM_BLOCK_MASK (BOOTMEM_BLOCK_ALIGN - 1) +#define BOOTMEM_BLOCK_MIN_SIZE 16 + +int bootmem_alloc_region(paddr_t, size_t); +void bootmem_free(paddr_t, size_t); + +int octeon_ioclock_speed(void); + +#endif /* _KERNEL */ +#endif /* _KERNEL || _STANDALONE */ + +static inline int +ffs64(uint64_t val) +{ + int ret; + + __asm volatile ( \ + _ASM_PROLOGUE_MIPS64 + " dclz %0, %1 \n" + _ASM_EPILOGUE + : "=r"(ret) : "r"(val)); + return 64 - ret; +} + +static inline int +ffs32(uint32_t val) +{ + int ret; + + __asm volatile ( \ + _ASM_PROLOGUE_MIPS64 + " clz %0, %1 \n" + _ASM_EPILOGUE + : "=r"(ret) : "r"(val)); + return 32 - ret; +} + +static inline uint64_t +octeon_xkphys_read_8(paddr_t address) +{ + volatile uint64_t *p = + (volatile uint64_t *)(PHYS_TO_XKPHYS(address, CCA_NC)); + return (*p); +} + +#define MIO_BOOT_BIST_STAT 0x00011800000000f8ULL +static inline void +octeon_xkphys_write_8(paddr_t address, uint64_t value) +{ + *(volatile uint64_t *)(PHYS_TO_XKPHYS(address, CCA_NC)) = value; + + /* + * It seems an immediate read is necessary when doing a write to an RSL + * register in order to complete the write. + * We use MIO_BOOT_BIST_STAT because it's apparently the fastest + * write. + */ + + /* + * XXX + * This if would be better written as: + * if ((address & 0xffffff0000000000ULL) == OCTEON_MIO_BOOT_BASE) { + * but octeonreg.h can't be included here and we want this inlined + * + * Note that the SDK masks with 0x7ffff but that doesn't make sense. + * This is a physical address. + */ + if (((address >> 40) & 0xfffff) == (0x118)) { + value = *(volatile uint64_t *) + (PHYS_TO_XKPHYS(MIO_BOOT_BIST_STAT, CCA_NC)); + } +} + +static inline void +octeon_iobdma_write_8(uint64_t value) +{ + uint64_t addr = 0xffffffffffffa200ULL; + + *(volatile uint64_t *)addr = value; +} + +static inline void +octeon_lmtdma_write_8(off_t offset, uint64_t value) +{ + *(volatile uint64_t *)(0xffffffffffffa400ULL + offset) = value; +} + +static inline uint64_t +octeon_cvmseg_read_8(size_t offset) +{ + return *(volatile uint64_t *)(0xffffffffffff8000ULL + offset); +} + +static inline void +octeon_cvmseg_write_8(size_t offset, uint64_t value) +{ + *(volatile uint64_t *)(0xffffffffffff8000ULL + offset) = value; +} + +static inline uint32_t +octeon_get_coreid(void) +{ + uint32_t coreid; + + __asm volatile ( + _ASM_PROLOGUE_OCTEON + " rdhwr %0, $0\n" + _ASM_EPILOGUE + : "=r" (coreid)); + return coreid; +} + +static inline uint64_t +octeon_get_cycles(void) +{ + uint64_t tmp; + + __asm volatile ( + _ASM_PROLOGUE_MIPS64 + " dmfc0 %[tmp], $9, 6 \n" + _ASM_EPILOGUE + : [tmp]"=&r"(tmp)); + return tmp; +} + +static inline uint64_t +octeon_get_cvmctl(void) +{ + uint64_t tmp; + + __asm volatile ( + _ASM_PROLOGUE_OCTEON + " dmfc0 %[tmp], $9, 7 \n" + _ASM_EPILOGUE + : [tmp]"=r"(tmp)); + return tmp; +} + +static inline uint64_t +octeon_get_cvmmemctl(void) +{ + uint64_t tmp; + + __asm volatile ( + _ASM_PROLOGUE_OCTEON + " dmfc0 %[tmp], $11, 7 \n" + _ASM_EPILOGUE + : [tmp]"=r"(tmp)); + return tmp; +} + +static inline void +octeon_set_cvmmemctl(uint64_t val) +{ + __asm volatile ( + _ASM_PROLOGUE_OCTEON + " dmtc0 %[tmp], $11, 7 \n" + _ASM_EPILOGUE + : : [tmp]"r"(val) : "memory"); +} + +static inline void +octeon_synciobdma(void) +{ + __asm volatile ( + _ASM_PROLOGUE_OCTEON + " synciobdma\n" + _ASM_EPILOGUE + : : : "memory"); +} + +#endif /* _MIPS_OCTEON_OCTEONVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/openpromio.h b/lib/libc/include/mips64-openbsd-none/octeon/openpromio.h new file mode 100644 index 000000000000..c33fb937a0e0 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/openpromio.h @@ -0,0 +1,57 @@ +/* $OpenBSD: openpromio.h,v 1.1 2016/07/05 12:53:40 visa Exp $ */ +/* $NetBSD: openpromio.h,v 1.1.1.1 1998/06/20 04:58:52 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)openpromio.h 8.1 (Berkeley) 6/11/93 + */ + +struct opiocdesc { + int op_nodeid; /* passed or returned node id */ + int op_namelen; /* length of op_name */ + char *op_name; /* pointer to field name */ + int op_buflen; /* length of op_buf (value-result) */ + char *op_buf; /* pointer to field value */ +}; + +#define OPIOCGET _IOWR('O', 1, struct opiocdesc) /* get openprom field */ +#define OPIOCSET _IOW('O', 2, struct opiocdesc) /* set openprom field */ +#define OPIOCNEXTPROP _IOWR('O', 3, struct opiocdesc) /* get next property */ +#define OPIOCGETOPTNODE _IOR('O', 4, int) /* get openprom field */ +#define OPIOCGETNEXT _IOWR('O', 5, int) /* get next node of node */ +#define OPIOCGETCHILD _IOWR('O', 6, int) /* get first child of node */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/param.h b/lib/libc/include/mips64-openbsd-none/octeon/param.h new file mode 100644 index 000000000000..336a6523083a --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/param.h @@ -0,0 +1,22 @@ +/* $OpenBSD: param.h,v 1.5 2018/08/09 12:19:32 patrick Exp $ */ + +/* Public Domain */ + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ + +#define MACHINE "octeon" +#define _MACHINE octeon +#define MACHINE_ARCH "mips64" +#define _MACHINE_ARCH mips64 +#define MID_MACHINE MID_MIPS64 + +#define PAGE_SHIFT 14 + +#include + +#ifdef _KERNEL +#define __HAVE_FDT +#endif + +#endif /* _MACHINE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/pcb.h b/lib/libc/include/mips64-openbsd-none/octeon/pcb.h new file mode 100644 index 000000000000..d48bd4724790 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/pcb.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pcb.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/pci_machdep.h b/lib/libc/include/mips64-openbsd-none/octeon/pci_machdep.h new file mode 100644 index 000000000000..b3aa0341f118 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/pci_machdep.h @@ -0,0 +1,133 @@ +/* $OpenBSD: pci_machdep.h,v 1.13 2024/05/20 23:13:33 jsg Exp $ */ + +/* + * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include + +typedef struct mips_pci_chipset *pci_chipset_tag_t; + +typedef u_int64_t pcitag_t; +#define PCITAG_NODE(x) ((x) >> 32) +#define PCITAG_OFFSET(x) ((x) & 0xffffffff) + +typedef u_long pci_intr_handle_t; + +struct pci_attach_args; + +/* + * mips-specific PCI structure and type definitions. + * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE. + */ +struct mips_pci_chipset { + void *pc_conf_v; + void (*pc_attach_hook)(struct device *, + struct device *, struct pcibus_attach_args *); + int (*pc_bus_maxdevs)(void *, int); + pcitag_t (*pc_make_tag)(void *, int, int, int); + void (*pc_decompose_tag)(void *, pcitag_t, int *, + int *, int *); + int (*pc_conf_size)(void *, pcitag_t); + pcireg_t (*pc_conf_read)(void *, pcitag_t, int); + void (*pc_conf_write)(void *, pcitag_t, int, pcireg_t); + + void *pc_intr_v; + int (*pc_intr_map)(struct pci_attach_args *, + pci_intr_handle_t *); + const char *(*pc_intr_string)(void *, pci_intr_handle_t); + void *(*pc_intr_establish)(void *, pci_intr_handle_t, + int, int (*)(void *), void *, char *); + void (*pc_intr_disestablish)(void *, void *); +}; + +/* + * Functions provided to machine-independent PCI code. + */ +//#define DEBUG_PCI_CONF + +#define pci_attach_hook(p, s, pba) \ + (*(pba)->pba_pc->pc_attach_hook)((p), (s), (pba)) +#define pci_bus_maxdevs(c, b) \ + (*(c)->pc_bus_maxdevs)((c)->pc_conf_v, (b)) +#define pci_make_tag(c, b, d, f) \ + (*(c)->pc_make_tag)((c)->pc_conf_v, (b), (d), (f)) +#define pci_decompose_tag(c, t, bp, dp, fp) \ + (*(c)->pc_decompose_tag)((c)->pc_conf_v, (t), (bp), (dp), (fp)) + +#define pci_conf_size(c, t) \ + (*(c)->pc_conf_size)((c)->pc_conf_v, (t)) + +#ifdef DEBUG_PCI_CONF +static inline pcireg_t +pci_conf_read_db(void *cookie, pcitag_t tag, int reg, + const char *file, const char *func, int line) +{ + struct mips_pci_chipset *pc = cookie; + pcireg_t val; + + val = (*(pc)->pc_conf_read)(pc->pc_conf_v, tag, reg); + printf("%s:%s:%d:pci_conf_read(%llx,%x) = %x\n", file, func, line, + tag, reg, val); + return val; +} + +static inline void +pci_conf_write_db(void *cookie, pcitag_t tag, int reg, pcireg_t val, + const char *file, const char *func, int line) +{ + struct mips_pci_chipset *pc = cookie; + + printf("%s:%s:%d:pci_conf_write(%llx,%x,%x)\n", file, func, line, + tag, reg, val); + (*(pc)->pc_conf_write)(pc->pc_conf_v, tag, reg, val); +} + + +#define pci_conf_read(c, t, r) \ + pci_conf_read_db(c, t, r, __FILE__, __FUNCTION__, __LINE__) +#define pci_conf_write(c, t, r, v) \ + pci_conf_write_db(c, t, r, v, __FILE__, __FUNCTION__, __LINE__) +#else +#define pci_conf_read(c, t, r) \ + (*(c)->pc_conf_read)((c)->pc_conf_v, (t), (r)) +#define pci_conf_write(c, t, r, v) \ + (*(c)->pc_conf_write)((c)->pc_conf_v, (t), (r), (v)) +#endif +#define pci_intr_map(c, ihp) \ + (*(c)->pa_pc->pc_intr_map)((c), (ihp)) +#define pci_intr_map_msi(c, ihp) (-1) +#define pci_intr_map_msix(c, vec, ihp) (-1) +#define pci_intr_string(c, ih) \ + (*(c)->pc_intr_string)((c)->pc_intr_v, (ih)) +#define pci_intr_establish(c, ih, l, h, a, nm) \ + (*(c)->pc_intr_establish)((c)->pc_intr_v, (ih), (l), (h), (a), (nm)) +#define pci_intr_disestablish(c, iv) \ + (*(c)->pc_intr_disestablish)((c)->pc_intr_v, (iv)) +#define pci_probe_device_hook(c, a) (0) + +#define pci_min_powerstate(c, t) (PCI_PMCSR_STATE_D3) +#define pci_set_powerstate_md(c, t, s, p) + +#define pci_dev_postattach(a, b) \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/pmap.h b/lib/libc/include/mips64-openbsd-none/octeon/pmap.h new file mode 100644 index 000000000000..93a59c2555e1 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/pmap.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pmap.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/proc.h b/lib/libc/include/mips64-openbsd-none/octeon/proc.h new file mode 100644 index 000000000000..feb4d625ead2 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/proc.h @@ -0,0 +1,3 @@ +/* $OpenBSD: proc.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/profile.h b/lib/libc/include/mips64-openbsd-none/octeon/profile.h new file mode 100644 index 000000000000..f6b93ca73c98 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/profile.h @@ -0,0 +1,3 @@ +/* $OpenBSD: profile.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/pte.h b/lib/libc/include/mips64-openbsd-none/octeon/pte.h new file mode 100644 index 000000000000..a1543ff6ce2e --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/pte.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pte.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/ptrace.h b/lib/libc/include/mips64-openbsd-none/octeon/ptrace.h new file mode 100644 index 000000000000..be18759bdae6 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/ptrace.h @@ -0,0 +1,3 @@ +/* $OpenBSD: ptrace.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/reg.h b/lib/libc/include/mips64-openbsd-none/octeon/reg.h new file mode 100644 index 000000000000..b21b51b97883 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/reg.h @@ -0,0 +1,3 @@ +/* $OpenBSD: reg.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/regdef.h b/lib/libc/include/mips64-openbsd-none/octeon/regdef.h new file mode 100644 index 000000000000..dc004a4ce80d --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/regdef.h @@ -0,0 +1,3 @@ +/* $OpenBSD: regdef.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/regnum.h b/lib/libc/include/mips64-openbsd-none/octeon/regnum.h new file mode 100644 index 000000000000..b20d7d3c3f04 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/regnum.h @@ -0,0 +1,3 @@ +/* $OpenBSD: regnum.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/reloc.h b/lib/libc/include/mips64-openbsd-none/octeon/reloc.h new file mode 100644 index 000000000000..4eb8c01cf15e --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/reloc.h @@ -0,0 +1,5 @@ +/* $OpenBSD: reloc.h,v 1.1 2017/08/12 15:33:41 visa Exp $ */ + +/* public domain */ + +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/setjmp.h b/lib/libc/include/mips64-openbsd-none/octeon/setjmp.h new file mode 100644 index 000000000000..bdd733d22dcb --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/setjmp.h @@ -0,0 +1,3 @@ +/* $OpenBSD: setjmp.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/signal.h b/lib/libc/include/mips64-openbsd-none/octeon/signal.h new file mode 100644 index 000000000000..2a21ca635862 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/signal.h @@ -0,0 +1,3 @@ +/* $OpenBSD: signal.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/simplebusvar.h b/lib/libc/include/mips64-openbsd-none/octeon/simplebusvar.h new file mode 100644 index 000000000000..32763ebfc8a9 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/simplebusvar.h @@ -0,0 +1,34 @@ +/* $OpenBSD: simplebusvar.h,v 1.1 2023/09/22 01:10:43 jsg Exp $ */ + +/* + * Copyright (c) 2016 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +struct simplebus_softc { + struct device sc_dev; + int sc_node; + bus_space_tag_t sc_iot; + bus_dma_tag_t sc_dmat; + int sc_acells; + int sc_scells; + int sc_pacells; + int sc_pscells; + bus_space_t sc_bus; + int *sc_ranges; + int sc_rangeslen; + int sc_early; +}; + +extern void simplebus_attach(struct device *, struct device *, void *); \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/spinlock.h b/lib/libc/include/mips64-openbsd-none/octeon/spinlock.h new file mode 100644 index 000000000000..800fc6eeb1a1 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/spinlock.h @@ -0,0 +1,3 @@ +/* $OpenBSD: spinlock.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/sysarch.h b/lib/libc/include/mips64-openbsd-none/octeon/sysarch.h new file mode 100644 index 000000000000..05bc15167666 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/sysarch.h @@ -0,0 +1,3 @@ +/* $OpenBSD: sysarch.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/tcb.h b/lib/libc/include/mips64-openbsd-none/octeon/tcb.h new file mode 100644 index 000000000000..427e19101a00 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/tcb.h @@ -0,0 +1,3 @@ +/* $OpenBSD: tcb.h,v 1.2 2013/06/01 21:20:54 jasper Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/timetc.h b/lib/libc/include/mips64-openbsd-none/octeon/timetc.h new file mode 100644 index 000000000000..d3d291c815ca --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/timetc.h @@ -0,0 +1,23 @@ +/* $OpenBSD: timetc.h,v 1.2 2020/07/18 08:37:43 visa Exp $ */ +/* + * Copyright (c) 2020 Paul Irofti + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TIMETC_H_ +#define _MACHINE_TIMETC_H_ + +#include + +#endif /* _MACHINE_TIMETC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/trap.h b/lib/libc/include/mips64-openbsd-none/octeon/trap.h new file mode 100644 index 000000000000..7ed252bd110b --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/trap.h @@ -0,0 +1,3 @@ +/* $OpenBSD: trap.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64-openbsd-none/octeon/vmparam.h b/lib/libc/include/mips64-openbsd-none/octeon/vmparam.h new file mode 100644 index 000000000000..336c1cf70f00 --- /dev/null +++ b/lib/libc/include/mips64-openbsd-none/octeon/vmparam.h @@ -0,0 +1,11 @@ +/* $OpenBSD: vmparam.h,v 1.3 2017/07/30 16:09:53 visa Exp $ */ +/* public domain */ +#ifndef _MACHINE_VMPARAM_H_ +#define _MACHINE_VMPARAM_H_ + +#define VM_PHYSSEG_MAX 8 /* Max number of physical memory segments */ +#define VM_PHYSSEG_STRAT VM_PSTRAT_BIGFIRST + +#include + +#endif /* _MACHINE_VMPARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/frame.h b/lib/libc/include/mips64el-openbsd-none/frame.h new file mode 100644 index 000000000000..d14827e33c0e --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/frame.h @@ -0,0 +1,3 @@ +/* $OpenBSD: frame.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/_float.h b/lib/libc/include/mips64el-openbsd-none/loongson/_float.h new file mode 100644 index 000000000000..6c9717939fcb --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/_float.h @@ -0,0 +1,3 @@ +/* $OpenBSD: _float.h,v 1.1 2012/06/26 16:12:44 deraadt Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/_types.h b/lib/libc/include/mips64el-openbsd-none/loongson/_types.h new file mode 100644 index 000000000000..327e3d3e38ff --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/_types.h @@ -0,0 +1,3 @@ +/* $OpenBSD: _types.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/apmvar.h b/lib/libc/include/mips64el-openbsd-none/loongson/apmvar.h new file mode 100644 index 000000000000..99c4026f9660 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/apmvar.h @@ -0,0 +1,127 @@ +/* $OpenBSD: apmvar.h,v 1.6 2019/01/22 02:36:30 phessler Exp $ */ + +/* + * Copyright (c) 2001 Alexander Guy + * Copyright (c) 1995 John T. Kohl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _MACHINE_APMVAR_H_ +#define _MACHINE_APMVAR_H_ + +#include + +/* Advanced Power Management (v1.0 and v1.1 specification) + * functions/defines/etc. + */ + +/* These definitions make up the heart of the user-land interface + * to the APM devices. + */ + +#define APM_AC_OFF 0x00 +#define APM_AC_ON 0x01 +#define APM_AC_BACKUP 0x02 +#define APM_AC_UNKNOWN 0xff +#define APM_BATT_HIGH 0x00 +#define APM_BATT_LOW 0x01 +#define APM_BATT_CRITICAL 0x02 +#define APM_BATT_CHARGING 0x03 +#define APM_BATT_UNKNOWN 0xff +#define APM_BATT_LIFE_UNKNOWN 0xff + +#define APM_NOEVENT 0x0000 +#define APM_STANDBY_REQ 0x0001 +#define APM_SUSPEND_REQ 0x0002 +#define APM_NORMAL_RESUME 0x0003 +#define APM_CRIT_RESUME 0x0004 /* suspend/resume happened + without us */ +#define APM_BATTERY_LOW 0x0005 +#define APM_POWER_CHANGE 0x0006 +#define APM_UPDATE_TIME 0x0007 +#define APM_CRIT_SUSPEND_REQ 0x0008 +#define APM_USER_STANDBY_REQ 0x0009 +#define APM_USER_SUSPEND_REQ 0x000A +#define APM_SYS_STANDBY_RESUME 0x000B +#define APM_CAPABILITY_CHANGE 0x000C /* apm v1.2 */ +#define APM_USER_HIBERNATE_REQ 0x000D +#define APM_EVENT_MASK 0xffff + +#define APM_EVENT_COMPOSE(t,i) ((((i) & 0x7fff) << 16)|((t) & APM_EVENT_MASK)) +#define APM_EVENT_TYPE(e) ((e) & APM_EVENT_MASK) +#define APM_EVENT_INDEX(e) ((e) >> 16) + +/* + * LP (Laptop Package) + * + * Copyright (C) 1994 by HOSOKAWA Tatsumi + * + * This software may be used, modified, copied, and distributed, in + * both source and binary form provided that the above copyright and + * these terms are retained. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with its + * use. + * + * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) + */ + +#define APM_BATTERY_ABSENT 4 + +struct apm_power_info { + u_char battery_state; + u_char ac_state; + u_char battery_life; + u_char spare1; + u_int minutes_left; /* estimate */ + u_int spare2[6]; +}; + +struct apm_ctl { + u_int dev; + u_int mode; +}; + +#define APM_IOC_REJECT _IOW('A', 0, struct apm_event_info) /* reject request # */ +#define APM_IOC_STANDBY _IO('A', 1) /* put system into standby */ +#define APM_IOC_SUSPEND _IO('A', 2) /* put system into suspend */ +#define APM_IOC_GETPOWER _IOR('A', 3, struct apm_power_info) /* fetch battery state */ +#define APM_IOC_DEV_CTL _IOW('A', 5, struct apm_ctl) /* put device into mode */ +#define APM_IOC_PRN_CTL _IOW('A', 6, int ) /* driver power status msg */ +#define APM_PRINT_ON 0 /* driver power status displayed */ +#define APM_PRINT_OFF 1 /* driver power status not displayed */ +#define APM_PRINT_PCT 2 /* driver power status only displayed + if the percentage changes */ +#define APM_IOC_STANDBY_REQ _IO('A', 7) /* request standby */ +#define APM_IOC_SUSPEND_REQ _IO('A', 8) /* request suspend */ +#define APM_IOC_HIBERNATE _IO('A', 9) /* put system into hibernate */ + +#ifdef _KERNEL +void apm_setinfohook(int (*)(struct apm_power_info *)); +int apm_record_event(u_int, const char *, const char *); +#endif + +#endif /* _MACHINE_APMVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/asm.h b/lib/libc/include/mips64el-openbsd-none/loongson/asm.h new file mode 100644 index 000000000000..63eab175139b --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/asm.h @@ -0,0 +1,9 @@ +/* $OpenBSD: asm.h,v 1.2 2016/11/18 15:38:14 visa Exp $ */ +/* public domain */ + +#ifdef MULTIPROCESSOR +#define HW_GET_CPU_INFO(ci, tmp) \ + dmfc0 ci, COP_0_ERROR_PC +#endif + +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/atomic.h b/lib/libc/include/mips64el-openbsd-none/loongson/atomic.h new file mode 100644 index 000000000000..19aa2fd4f69b --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/atomic.h @@ -0,0 +1,3 @@ +/* $OpenBSD: atomic.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/autoconf.h b/lib/libc/include/mips64el-openbsd-none/loongson/autoconf.h new file mode 100644 index 000000000000..7292105a5be8 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/autoconf.h @@ -0,0 +1,124 @@ +/* $OpenBSD: autoconf.h,v 1.17 2017/05/21 13:00:53 visa Exp $ */ + +/* + * Copyright (c) 2001-2003 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * Definitions used by autoconfiguration. + */ + +#ifndef _MACHINE_AUTOCONF_H_ +#define _MACHINE_AUTOCONF_H_ + +#include + +struct bonito_config; +struct htb_config; +struct mips_isa_chipset; + +/* + * List of legacy I/O ranges. + */ +struct legacy_io_range { + bus_addr_t start; + bus_size_t end; /* inclusive */ +}; + +/* + * Per platform information. + */ +struct platform { + int system_type; +#define LOONGSON_2E 0x0000 /* Generic Loongson 2E system */ +#define LOONGSON_YEELOONG 0x0001 /* Lemote Yeeloong */ +#define LOONGSON_GDIUM 0x0002 /* EMTEC Gdium Liberty */ +#define LOONGSON_FULOONG 0x0003 /* Lemote Fuloong */ +#define LOONGSON_LYNLOONG 0x0004 /* Lemote Lynloong */ +#define LOONGSON_EBT700 0x0005 /* eBenton EBT700 */ +#define LOONGSON_3A 0x0066 /* Loongson 2Gq or 3A based system */ + + char *vendor; + char *product; + + const struct bonito_config *bonito_config; + const struct htb_config *htb_config; + struct mips_isa_chipset *isa_chipset; + const struct legacy_io_range *legacy_io_ranges; + + void (*setup)(void); + void (*device_register)(struct device *, + void *); + + void (*powerdown)(void); + void (*reset)(void); + int (*suspend)(void); + int (*resume)(void); + +#ifdef MULTIPROCESSOR + void (*config_secondary_cpus)( + struct device *, cfprint_t); + void (*boot_secondary_cpu)( + struct cpu_info *); + int (*ipi_establish)(int (*)(void *), + cpuid_t); + void (*ipi_set)(cpuid_t); + void (*ipi_clear)(cpuid_t); +#endif /* MULTIPROCESSOR */ +}; + +#define LOONGSON_MAXCPUS 16 + +extern const struct platform *sys_platform; +extern void *loongson_videobios; +extern uint loongson_cpumask; +extern uint loongson_ver; +extern int nnodes; + +#ifdef MULTIPROCESSOR +extern uint64_t cpu_spinup_a0; +extern uint64_t cpu_spinup_sp; +#endif + +struct mainbus_attach_args { + const char *maa_name; +}; + +extern struct device *bootdv; +extern char bootdev[]; +extern enum devclass bootdev_class; + +extern bus_space_tag_t early_mem_t; +extern bus_space_tag_t early_io_t; + +#define REGVAL8(x) *((volatile uint8_t *)PHYS_TO_XKPHYS((x), CCA_NC)) +#define REGVAL32(x) *((volatile uint32_t *)PHYS_TO_XKPHYS((x), CCA_NC)) +#define REGVAL64(x) *((volatile uint64_t *)PHYS_TO_XKPHYS((x), CCA_NC)) + +#define REGVAL(x) REGVAL32(x) + +#include + +#endif /* _MACHINE_AUTOCONF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/bus.h b/lib/libc/include/mips64el-openbsd-none/loongson/bus.h new file mode 100644 index 000000000000..24430920dde3 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/bus.h @@ -0,0 +1,513 @@ +/* $OpenBSD: bus.h,v 1.8 2020/04/14 17:35:28 kettenis Exp $ */ + +/* + * Copyright (c) 2003-2004 Opsycon AB Sweden. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BUS_H_ +#define _MACHINE_BUS_H_ + +#ifdef __STDC__ +#define CAT(a,b) a##b +#define CAT3(a,b,c) a##b##c +#else +#define CAT(a,b) a/**/b +#define CAT3(a,b,c) a/**/b/**/c +#endif + +/* + * Bus access types. + */ +struct mips_bus_space; +typedef u_long bus_addr_t; +typedef u_long bus_size_t; +typedef u_long bus_space_handle_t; +typedef struct mips_bus_space *bus_space_tag_t; + +struct mips_bus_space { + bus_addr_t bus_base; + void *bus_private; + u_int8_t (*_space_read_1)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_1)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int8_t); + u_int16_t (*_space_read_2)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_2)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int16_t); + u_int32_t (*_space_read_4)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_4)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int32_t); + u_int64_t (*_space_read_8)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_8)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int64_t); + void (*_space_read_raw_2)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_2)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + void (*_space_read_raw_4)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_4)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + void (*_space_read_raw_8)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_8)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + int (*_space_map)(bus_space_tag_t , bus_addr_t, + bus_size_t, int, bus_space_handle_t *); + void (*_space_unmap)(bus_space_tag_t, bus_space_handle_t, + bus_size_t); + int (*_space_subregion)(bus_space_tag_t, bus_space_handle_t, + bus_size_t, bus_size_t, bus_space_handle_t *); + void * (*_space_vaddr)(bus_space_tag_t, bus_space_handle_t); + paddr_t (*_space_mmap)(bus_space_tag_t, bus_addr_t, off_t, + int, int); +}; + +#define bus_space_read_1(t, h, o) (*(t)->_space_read_1)((t), (h), (o)) +#define bus_space_read_2(t, h, o) (*(t)->_space_read_2)((t), (h), (o)) +#define bus_space_read_4(t, h, o) (*(t)->_space_read_4)((t), (h), (o)) +#define bus_space_read_8(t, h, o) (*(t)->_space_read_8)((t), (h), (o)) + +#define bus_space_write_1(t, h, o, v) (*(t)->_space_write_1)((t), (h), (o), (v)) +#define bus_space_write_2(t, h, o, v) (*(t)->_space_write_2)((t), (h), (o), (v)) +#define bus_space_write_4(t, h, o, v) (*(t)->_space_write_4)((t), (h), (o), (v)) +#define bus_space_write_8(t, h, o, v) (*(t)->_space_write_8)((t), (h), (o), (v)) + +#define bus_space_read_raw_multi_2(t, h, a, b, l) \ + (*(t)->_space_read_raw_2)((t), (h), (a), (b), (l)) +#define bus_space_read_raw_multi_4(t, h, a, b, l) \ + (*(t)->_space_read_raw_4)((t), (h), (a), (b), (l)) +#define bus_space_read_raw_multi_8(t, h, a, b, l) \ + (*(t)->_space_read_raw_8)((t), (h), (a), (b), (l)) + +#define bus_space_write_raw_multi_2(t, h, a, b, l) \ + (*(t)->_space_write_raw_2)((t), (h), (a), (b), (l)) +#define bus_space_write_raw_multi_4(t, h, a, b, l) \ + (*(t)->_space_write_raw_4)((t), (h), (a), (b), (l)) +#define bus_space_write_raw_multi_8(t, h, a, b, l) \ + (*(t)->_space_write_raw_8)((t), (h), (a), (b), (l)) + +#define bus_space_map(t, o, s, c, p) (*(t)->_space_map)((t), (o), (s), (c), (p)) +#define bus_space_unmap(t, h, s) (*(t)->_space_unmap)((t), (h), (s)) +#define bus_space_subregion(t, h, o, s, p) \ + (*(t)->_space_subregion)((t), (h), (o), (s), (p)) + +#define BUS_SPACE_MAP_CACHEABLE 0x01 +#define BUS_SPACE_MAP_LINEAR 0x02 +#define BUS_SPACE_MAP_PREFETCHABLE 0x04 + +#define bus_space_vaddr(t, h) (*(t)->_space_vaddr)((t), (h)) +#define bus_space_mmap(t, a, o, p, f) \ + (*(t)->_space_mmap)((t), (a), (o), (p), (f)) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_multi(n,m) \ +static __inline void \ +CAT(bus_space_read_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t o, CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) \ + *x++ = CAT(bus_space_read_,n)(bst, bsh, o); \ +} + +bus_space_read_multi(1,8) +bus_space_read_multi(2,16) +bus_space_read_multi(4,32) +bus_space_read_multi(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_region(n,m) \ +static __inline void \ +CAT(bus_space_read_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) { \ + *x++ = CAT(bus_space_read_,n)(bst, bsh, ba); \ + ba += (n); \ + } \ +} + +bus_space_read_region(1,8) +bus_space_read_region(2,16) +bus_space_read_region(4,32) +bus_space_read_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_raw_region(n,m) \ +static __inline void \ +CAT(bus_space_read_raw_region_,n)(bus_space_tag_t bst, \ + bus_space_handle_t bsh, \ + bus_addr_t ba, u_int8_t *x, size_t cnt) \ +{ \ + cnt >>= ((n) >> 1); \ + while (cnt--) { \ + CAT(bus_space_read_raw_multi_,n)(bst, bsh, ba, x, (n)); \ + ba += (n); \ + x += (n); \ + } \ +} + +bus_space_read_raw_region(2,16) +bus_space_read_raw_region(4,32) +bus_space_read_raw_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_multi(n,m) \ +static __inline void \ +CAT(bus_space_write_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t o, const CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) \ + CAT(bus_space_write_,n)(bst, bsh, o, *x++); \ +} + +bus_space_write_multi(1,8) +bus_space_write_multi(2,16) +bus_space_write_multi(4,32) +bus_space_write_multi(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_region(n,m) \ +static __inline void \ +CAT(bus_space_write_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, const CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) { \ + CAT(bus_space_write_,n)(bst, bsh, ba, *x++); \ + ba += (n); \ + } \ +} + +bus_space_write_region(1,8) +bus_space_write_region(2,16) +bus_space_write_region(4,32) +bus_space_write_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_raw_region(n,m) \ +static __inline void \ +CAT(bus_space_write_raw_region_,n)(bus_space_tag_t bst, \ + bus_space_handle_t bsh, \ + bus_addr_t ba, const u_int8_t *x, size_t cnt) \ +{ \ + cnt >>= ((n) >> 1); \ + while (cnt--) { \ + CAT(bus_space_write_raw_multi_,n)(bst, bsh, ba, x, (n)); \ + ba += (n); \ + x += (n); \ + } \ +} + +bus_space_write_raw_region(2,16) +bus_space_write_raw_region(4,32) +bus_space_write_raw_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_set_region(n,m) \ +static __inline void \ +CAT(bus_space_set_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(u_int,m,_t) x, size_t cnt) \ +{ \ + while (cnt--) { \ + CAT(bus_space_write_,n)(bst, bsh, ba, x); \ + ba += (n); \ + } \ +} + +bus_space_set_region(1,8) +bus_space_set_region(2,16) +bus_space_set_region(4,32) +bus_space_set_region(8,64) + +/*----------------------------------------------------------------------------*/ +static __inline void +bus_space_copy_1(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + char *s = (char *)(h1 + o1); + char *d = (char *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + + +static __inline void +bus_space_copy_2(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + short *s = (short *)(h1 + o1); + short *d = (short *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + +static __inline void +bus_space_copy_4(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + int *s = (int *)(h1 + o1); + int *d = (int *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + +static __inline void +bus_space_copy_8(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + int64_t *s = (int64_t *)(h1 + o1); + int64_t *d = (int64_t *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + +int generic_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, + bus_space_handle_t *); +void generic_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t); +int generic_space_region(bus_space_tag_t, bus_space_handle_t, bus_size_t, + bus_size_t, bus_space_handle_t *); +void *generic_space_vaddr(bus_space_tag_t, bus_space_handle_t); +uint8_t generic_space_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint16_t generic_space_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint32_t generic_space_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint64_t generic_space_read_8(bus_space_tag_t, bus_space_handle_t, bus_size_t); +void generic_space_read_raw_2(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint8_t); +void generic_space_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint16_t); +void generic_space_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint32_t); +void generic_space_write_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint64_t); +void generic_space_write_raw_2(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); +void generic_space_read_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); +void generic_space_read_raw_8(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_raw_8(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); +paddr_t generic_space_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int); + +/*----------------------------------------------------------------------------*/ +/* + * Bus read/write barrier methods. + * + * void bus_space_barrier(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * bus_size_t len, int flags); + * + */ +static inline void +bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, + bus_size_t length, int flags) +{ + __asm__ volatile ("sync" ::: "memory"); +} +#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ +#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ + +#define BUS_DMA_WAITOK 0x0000 +#define BUS_DMA_NOWAIT 0x0001 +#define BUS_DMA_ALLOCNOW 0x0002 +#define BUS_DMA_COHERENT 0x0008 +#define BUS_DMA_BUS1 0x0010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x0020 +#define BUS_DMA_BUS3 0x0040 +#define BUS_DMA_BUS4 0x0080 +#define BUS_DMA_READ 0x0100 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x0200 /* mapping is memory -> device only */ +#define BUS_DMA_STREAMING 0x0400 /* hint: sequential, unidirectional */ +#define BUS_DMA_ZERO 0x0800 /* zero memory in dmamem_alloc */ +#define BUS_DMA_NOCACHE 0x1000 +#define BUS_DMA_64BIT 0x2000 /* device handles 64bit dva */ + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct proc; +struct uio; + +#define BUS_DMASYNC_POSTREAD 0x0001 +#define BUS_DMASYNC_POSTWRITE 0x0002 +#define BUS_DMASYNC_PREREAD 0x0004 +#define BUS_DMASYNC_PREWRITE 0x0008 + +typedef struct machine_bus_dma_tag *bus_dma_tag_t; +typedef struct machine_bus_dmamap *bus_dmamap_t; + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +struct machine_bus_dma_segment { + bus_addr_t ds_addr; /* DMA address */ + bus_size_t ds_len; /* length of transfer */ + + paddr_t _ds_paddr; /* CPU address */ + vaddr_t _ds_vaddr; /* CPU address */ +}; +typedef struct machine_bus_dma_segment bus_dma_segment_t; + +/* + * bus_dma_tag_t + * + * A machine-dependent opaque type describing the implementation of + * DMA for a given bus. + */ + +struct machine_bus_dma_tag { + void *_cookie; /* cookie used in the guts */ + + /* + * DMA mapping methods. + */ + int (*_dmamap_create)(bus_dma_tag_t , bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); + void (*_dmamap_destroy)(bus_dma_tag_t , bus_dmamap_t); + int (*_dmamap_load)(bus_dma_tag_t , bus_dmamap_t, void *, + bus_size_t, struct proc *, int); + int (*_dmamap_load_mbuf)(bus_dma_tag_t , bus_dmamap_t, + struct mbuf *, int); + int (*_dmamap_load_uio)(bus_dma_tag_t , bus_dmamap_t, + struct uio *, int); + int (*_dmamap_load_raw)(bus_dma_tag_t , bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); + int (*_dmamap_load_buffer)(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int, paddr_t *, int *, int); + void (*_dmamap_unload)(bus_dma_tag_t , bus_dmamap_t); + void (*_dmamap_sync)(bus_dma_tag_t , bus_dmamap_t, + bus_addr_t, bus_size_t, int); + + /* + * DMA memory utility functions. + */ + int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); + void (*_dmamem_free)(bus_dma_tag_t, bus_dma_segment_t *, int); + int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); + void (*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t); + paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, + int, off_t, int, int); + + /* + * internal memory address translation information. + */ + bus_addr_t (*_pa_to_device)(paddr_t); + paddr_t (*_device_to_pa)(bus_addr_t); + bus_addr_t _dma_mask; +}; + +#define bus_dmamap_create(t, s, n, m, b, f, p) \ + (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) +#define bus_dmamap_destroy(t, p) \ + (*(t)->_dmamap_destroy)((t), (p)) +#define bus_dmamap_load(t, m, b, s, p, f) \ + (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) +#define bus_dmamap_load_mbuf(t, m, b, f) \ + (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) +#define bus_dmamap_load_uio(t, m, u, f) \ + (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) +#define bus_dmamap_load_raw(t, m, sg, n, s, f) \ + (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) +#define bus_dmamap_unload(t, p) \ + (*(t)->_dmamap_unload)((t), (p)) +#define bus_dmamap_sync(t, p, a, l, o) \ + (void)((t)->_dmamap_sync ? \ + (*(t)->_dmamap_sync)((t), (p), (a), (l), (o)) : (void)0) + +#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ + (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f)) +#define bus_dmamem_free(t, sg, n) \ + (*(t)->_dmamem_free)((t), (sg), (n)) +#define bus_dmamem_map(t, sg, n, s, k, f) \ + (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f)) +#define bus_dmamem_unmap(t, k, s) \ + (*(t)->_dmamem_unmap)((t), (k), (s)) +#define bus_dmamem_mmap(t, sg, n, o, p, f) \ + (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f)) + +int _dmamap_create(bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); +void _dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); +int _dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); +int _dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *, int); +int _dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, struct uio *, int); +int _dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); +int _dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int, paddr_t *, int *, int); +void _dmamap_unload(bus_dma_tag_t, bus_dmamap_t); +void _dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, + bus_size_t, int); + +int _dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); +void _dmamem_free(bus_dma_tag_t, bus_dma_segment_t *, int); +int _dmamem_map(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); +void _dmamem_unmap(bus_dma_tag_t, caddr_t, size_t); +paddr_t _dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, int, int); +int _dmamem_alloc_range(bus_dma_tag_t, bus_size_t, bus_size_t, bus_size_t, + bus_dma_segment_t *, int, int *, int, paddr_t, paddr_t); + +/* + * bus_dmamap_t + * + * Describes a DMA mapping. + */ +struct machine_bus_dmamap { + /* + * PRIVATE MEMBERS: not for use by machine-independent code. + */ + bus_size_t _dm_size; /* largest DMA transfer mappable */ + int _dm_segcnt; /* number of segs this map can map */ + bus_size_t _dm_maxsegsz; /* largest possible segment */ + bus_size_t _dm_boundary; /* don't cross this */ + int _dm_flags; /* misc. flags */ + + void *_dm_cookie; /* cookie for bus-specific functions */ + + /* + * PUBLIC MEMBERS: these are used by machine-independent code. + */ + bus_size_t dm_mapsize; /* size of the mapping */ + int dm_nsegs; /* # valid segments in mapping */ + bus_dma_segment_t dm_segs[1]; /* segments; variable length */ +}; + +#endif /* _MACHINE_BUS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/cdefs.h b/lib/libc/include/mips64el-openbsd-none/loongson/cdefs.h new file mode 100644 index 000000000000..e44353fedfe1 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/cdefs.h @@ -0,0 +1,3 @@ +/* $OpenBSD: cdefs.h,v 1.2 2013/03/28 17:30:45 martynas Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/conf.h b/lib/libc/include/mips64el-openbsd-none/loongson/conf.h new file mode 100644 index 000000000000..8eafed12d428 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/conf.h @@ -0,0 +1,42 @@ +/* $OpenBSD: conf.h,v 1.4 2022/06/28 14:43:50 visa Exp $ */ +/* $NetBSD: conf.h,v 1.2 1996/05/05 19:28:34 christos Exp $ */ + +/* + * Copyright (c) 1996 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +/* open, close, write, ioctl, kqueue */ +#define cdev_apm_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev, 0, 0, dev_init(c,n,kqfilter) } + +cdev_decl(apm); \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/cpu.h b/lib/libc/include/mips64el-openbsd-none/loongson/cpu.h new file mode 100644 index 000000000000..d3d84bf3dbf9 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/cpu.h @@ -0,0 +1,103 @@ +/* $OpenBSD: cpu.h,v 1.8 2017/07/30 16:05:24 visa Exp $ */ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell and Rick Macklem. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Copyright (C) 1989 Digital Equipment Corporation. + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies. + * Digital Equipment Corporation makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * from: @(#)cpu.h 8.4 (Berkeley) 1/4/94 + */ + +#ifdef _KERNEL + +#if defined(MULTIPROCESSOR) && !defined(_LOCORE) +#define MAXCPUS 4 +struct cpu_info; +struct cpu_info *hw_getcurcpu(void); +void hw_setcurcpu(struct cpu_info *); +void hw_cpu_boot_secondary(struct cpu_info *); +void hw_cpu_hatch(struct cpu_info *); +void hw_cpu_spinup_trampoline(struct cpu_info *); +int hw_ipi_intr_establish(int (*)(void *), u_long); +void hw_ipi_intr_set(u_long); +void hw_ipi_intr_clear(u_long); +#endif /* MULTIPROCESSOR && !_LOCORE */ + +#if defined(CPU_LOONGSON2) && !defined(CPU_LOONGSON3) +#define Mips_SyncCache(ci) \ + Loongson2_SyncCache((ci)) +#define Mips_InvalidateICache(ci, va, l) \ + Loongson2_InvalidateICache((ci), (va), (l)) +#define Mips_InvalidateICachePage(ci, va) \ + Loongson2_InvalidateICachePage((ci), (va)) +#define Mips_SyncICache(ci) \ + Loongson2_SyncICache((ci)) +#define Mips_SyncDCachePage(ci, va, pa) \ + Loongson2_SyncDCachePage((ci), (va), (pa)) +#define Mips_HitSyncDCachePage(ci, va, pa) \ + Loongson2_SyncDCachePage((ci), (va), (pa)) +#define Mips_HitSyncDCache(ci, va, l) \ + Loongson2_HitSyncDCache((ci), (va), (l)) +#define Mips_IOSyncDCache(ci, va, l, h) \ + Loongson2_IOSyncDCache((ci), (va), (l), (h)) +#define Mips_HitInvalidateDCache(ci, va, l) \ + Loongson2_HitInvalidateDCache((ci), (va), (l)) +#endif + +#if defined(CPU_LOONGSON3) && !defined(CPU_LOONGSON2) +#define Mips_SyncCache(ci) \ + Loongson3_SyncCache((ci)) +#define Mips_InvalidateICache(ci, va, l) \ + Loongson3_InvalidateICache((ci), (va), (l)) +#define Mips_InvalidateICachePage(ci, va) \ + Loongson3_InvalidateICachePage((ci), (va)) +#define Mips_SyncICache(ci) \ + Loongson3_SyncICache((ci)) +#define Mips_SyncDCachePage(ci, va, pa) \ + Loongson3_SyncDCachePage((ci), (va), (pa)) +#define Mips_HitSyncDCachePage(ci, va, pa) \ + Loongson3_SyncDCachePage((ci), (va), (pa)) +#define Mips_HitSyncDCache(ci, va, l) \ + Loongson3_HitSyncDCache((ci), (va), (l)) +#define Mips_IOSyncDCache(ci, va, l, h) \ + Loongson3_IOSyncDCache((ci), (va), (l), (h)) +#define Mips_HitInvalidateDCache(ci, va, l) \ + Loongson3_HitInvalidateDCache((ci), (va), (l)) +#endif + +#endif /* _KERNEL */ + +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/cpustate.h b/lib/libc/include/mips64el-openbsd-none/loongson/cpustate.h new file mode 100644 index 000000000000..f5aff1a41b08 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/cpustate.h @@ -0,0 +1,3 @@ +/* $OpenBSD: cpustate.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/db_machdep.h b/lib/libc/include/mips64el-openbsd-none/loongson/db_machdep.h new file mode 100644 index 000000000000..3759d833718e --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/db_machdep.h @@ -0,0 +1,3 @@ +/* $OpenBSD: db_machdep.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/disklabel.h b/lib/libc/include/mips64el-openbsd-none/loongson/disklabel.h new file mode 100644 index 000000000000..e7758205f60b --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/disklabel.h @@ -0,0 +1,16 @@ +/* $OpenBSD: disklabel.h,v 1.3 2015/09/30 15:35:30 krw Exp $ */ +/* public domain */ + +/* + * Standard MBR partition scheme, with the label in the second sector + * of the OpenBSD partition. + */ + +#ifndef _MACHINE_DISKLABEL_H_ +#define _MACHINE_DISKLABEL_H_ + +#define LABELSECTOR 1 /* sector containing label */ +#define LABELOFFSET 0 /* offset of label in sector */ +#define MAXPARTITIONS 16 /* number of partitions */ + +#endif /* _MACHINE_DISKLABEL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/elf.h b/lib/libc/include/mips64el-openbsd-none/loongson/elf.h new file mode 100644 index 000000000000..5918df727bda --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/elf.h @@ -0,0 +1,3 @@ +/* $OpenBSD: elf.h,v 1.1 2024/07/14 19:33:59 miod Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/endian.h b/lib/libc/include/mips64el-openbsd-none/loongson/endian.h new file mode 100644 index 000000000000..2e7392a0828e --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/endian.h @@ -0,0 +1,3 @@ +/* $OpenBSD: endian.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/exec.h b/lib/libc/include/mips64el-openbsd-none/loongson/exec.h new file mode 100644 index 000000000000..53433783f0c0 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/exec.h @@ -0,0 +1,3 @@ +/* $OpenBSD: exec.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/fenv.h b/lib/libc/include/mips64el-openbsd-none/loongson/fenv.h new file mode 100644 index 000000000000..08e89fbf323e --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/fenv.h @@ -0,0 +1,3 @@ +/* $OpenBSD: fenv.h,v 1.2 2013/06/01 21:20:54 jasper Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/fpu.h b/lib/libc/include/mips64el-openbsd-none/loongson/fpu.h new file mode 100644 index 000000000000..19ee8af41438 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/fpu.h @@ -0,0 +1,3 @@ +/* $OpenBSD: fpu.h,v 1.1 2010/09/17 00:34:04 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/frame.h b/lib/libc/include/mips64el-openbsd-none/loongson/frame.h new file mode 100644 index 000000000000..d14827e33c0e --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/frame.h @@ -0,0 +1,3 @@ +/* $OpenBSD: frame.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/hibernate.h b/lib/libc/include/mips64el-openbsd-none/loongson/hibernate.h new file mode 100644 index 000000000000..f0a99c6df6e3 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/hibernate.h @@ -0,0 +1,33 @@ +/* $OpenBSD: hibernate.h,v 1.3 2018/06/21 07:33:30 mlarkin Exp $ */ + +/* + * Copyright (c) 2013 Paul Irofti. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +#include + +/* Loongson hibernate support structures and functions */ + +int get_hibernate_info_md(union hibernate_info *); +void hibernate_flush(void); +void hibernate_enter_resume_mapping(vaddr_t, paddr_t, int); +int hibernate_inflate_skip(union hibernate_info *, paddr_t); +int hibernate_suspend(void); +void hibernate_switch_stack_machdep(void); +void hibernate_resume_machdep(vaddr_t); +void hibernate_activate_resume_pt_machdep(void); +void hibernate_enable_intr_machdep(void); +void hibernate_disable_intr_machdep(void); \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/hibernate_var.h b/lib/libc/include/mips64el-openbsd-none/loongson/hibernate_var.h new file mode 100644 index 000000000000..de84657a4b51 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/hibernate_var.h @@ -0,0 +1,39 @@ +/* $OpenBSD: hibernate_var.h,v 1.1 2013/06/02 21:46:04 pirofti Exp $ */ + +/* + * Copyright (c) 2013 Paul Irofti. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* Loongson hibernate support definitions */ + +#define PAGE_MASK_4M ((256 * PAGE_SIZE) - 1) + +#define PIGLET_PAGE_MASK ~((paddr_t)PAGE_MASK_4M) + +/* + * Steal hibernate pages right after the first page which is reserved + * for the exception area. + * */ +#define HIBERNATE_STACK_PAGE (PAGE_SIZE * 1) +#define HIBERNATE_INFLATE_PAGE (PAGE_SIZE * 2) +#define HIBERNATE_COPY_PAGE (PAGE_SIZE * 3) +#define HIBERNATE_HIBALLOC_PAGE (PAGE_SIZE * 4) + +#define HIBERNATE_RESERVED_PAGES 4 + +/* Use 4MB hibernation chunks */ +#define HIBERNATE_CHUNK_SIZE 0x400000 + +#define HIBERNATE_CHUNK_TABLE_SIZE 0x100000 \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/ieee.h b/lib/libc/include/mips64el-openbsd-none/loongson/ieee.h new file mode 100644 index 000000000000..d390acb3c59f --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/ieee.h @@ -0,0 +1,3 @@ +/* $OpenBSD: ieee.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/ieeefp.h b/lib/libc/include/mips64el-openbsd-none/loongson/ieeefp.h new file mode 100644 index 000000000000..17e880358e20 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/ieeefp.h @@ -0,0 +1,3 @@ +/* $OpenBSD: ieeefp.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/intr.h b/lib/libc/include/mips64el-openbsd-none/loongson/intr.h new file mode 100644 index 000000000000..64d103bc39aa --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/intr.h @@ -0,0 +1,193 @@ +/* $OpenBSD: intr.h,v 1.19 2025/05/10 10:01:03 visa Exp $ */ + +/* + * Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _MACHINE_INTR_H_ +#define _MACHINE_INTR_H_ + +#define __USE_MI_SOFTINTR + +#include + +/* + * The interrupt level ipl is a logical level; per-platform interrupt + * code will turn it into the appropriate hardware interrupt masks + * values. + * + * Interrupt sources on the CPU are kept enabled regardless of the + * current ipl value; individual hardware sources interrupting while + * logically masked are masked on the fly, remembered as pending, and + * unmasked at the first splx() opportunity. + * + * An exception to this rule is the clock interrupt. Clock interrupts + * are always allowed to happen, but will (of course!) not be serviced + * if logically masked. The reason for this is that clocks usually sit on + * INT5 and cannot be easily masked if external hardware masking is used. + */ + +/* Interrupt priority `levels'; not mutually exclusive. */ +#define IPL_NONE 0 /* nothing */ +#define IPL_SOFTINT 1 /* soft interrupts */ +#define IPL_SOFTCLOCK 1 /* soft clock interrupts */ +#define IPL_SOFTNET 2 /* soft network interrupts */ +#define IPL_SOFTTTY 3 /* soft terminal interrupts */ +#define IPL_SOFTHIGH IPL_SOFTTTY /* highest level of soft interrupts */ +#define IPL_BIO 4 /* block I/O */ +#define IPL_AUDIO IPL_BIO +#define IPL_NET 5 /* network */ +#define IPL_TTY 6 /* terminal */ +#define IPL_VM 7 /* memory allocation */ +#define IPL_CLOCK 8 /* clock */ +#define IPL_STATCLOCK IPL_CLOCK +#define IPL_SCHED 9 /* everything */ +#define IPL_HIGH 9 /* everything */ +#define IPL_IPI 10 /* interprocessor interrupt */ +#define NIPLS 11 /* number of levels */ + +#define IPL_MPFLOOR IPL_TTY + +/* Interrupt priority 'flags'. */ +#define IPL_MPSAFE 0x100 + +/* Interrupt sharing types. */ +#define IST_NONE 0 /* none */ +#define IST_PULSE 1 /* pulsed */ +#define IST_EDGE 2 /* edge-triggered */ +#define IST_LEVEL 3 /* level-triggered */ + +#ifndef _LOCORE + +void softintr(int); + +#define splbio() splraise(IPL_BIO) +#define splnet() splraise(IPL_NET) +#define spltty() splraise(IPL_TTY) +#define splaudio() splraise(IPL_AUDIO) +#define splclock() splraise(IPL_CLOCK) +#define splvm() splraise(IPL_VM) +#define splhigh() splraise(IPL_HIGH) + +#define splsoftclock() splraise(IPL_SOFTCLOCK) +#define splsoftnet() splraise(IPL_SOFTNET) +#define splstatclock() splhigh() + +#define splsched() splhigh() +#define spl0() spllower(0) + +void splinit(void); + +#ifdef DIAGNOSTIC +/* + * Although this function is implemented in MI code, it must be in this MD + * header because we don't want this header to include MI includes. + */ +void splassert_fail(int, int, const char *); +extern int splassert_ctl; +void splassert_check(int, const char *); +#define splassert(__wantipl) do { \ + if (splassert_ctl > 0) { \ + splassert_check(__wantipl, __func__); \ + } \ +} while (0) +#define splsoftassert(wantipl) splassert(wantipl) +#else +#define splassert(X) +#define splsoftassert(X) +#endif + +void register_splx_handler(void (*)(int)); +int splraise(int); +void splx(int); +int spllower(int); + +/* + * Interrupt control struct used by interrupt dispatchers + * to hold interrupt handler info. + */ + +#include + +struct intrhand { + struct intrhand *ih_next; + int (*ih_fun)(void *); + void *ih_arg; + int ih_level; + int ih_irq; + int ih_flags; +#define IH_MPSAFE 0x01 + struct evcount ih_count; +}; + +void intr_barrier(void *); + +/* + * Low level interrupt dispatcher registration data. + */ + +/* Schedule priorities for base interrupts (CPU) */ +#define INTPRI_IPI 0 +#define INTPRI_CLOCK 1 +/* other values are system-specific */ + +#define NLOWINT 4 /* Number of low level registrations possible */ + +extern uint32_t idle_mask; + +struct trapframe; +void set_intr(int, uint32_t, uint32_t(*)(uint32_t, struct trapframe *)); + +uint32_t updateimask(uint32_t); +void dosoftint(void); + +#ifdef MULTIPROCESSOR +extern uint32_t ipi_mask; +#define ENABLEIPI() updateimask(~ipi_mask) +#endif + +struct pic { + void (*pic_eoi)(int); + void (*pic_mask)(int); + void (*pic_unmask)(int); +}; + +#ifdef CPU_LOONGSON3 + +void loongson3_intr_init(void); +void *loongson3_intr_establish(int, int, int (*)(void *), void*, + const char *); +void loongson3_intr_disestablish(void *); +void *loongson3_ht_intr_establish(int, int, int (*)(void *), void*, + const char *); +void loongson3_ht_intr_disestablish(void *); + +void loongson3_register_ht_pic(const struct pic *); + +#endif /* CPU_LOONGSON3 */ + +#endif /* _LOCORE */ + +#endif /* _MACHINE_INTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/isa_machdep.h b/lib/libc/include/mips64el-openbsd-none/loongson/isa_machdep.h new file mode 100644 index 000000000000..201c218bd3fb --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/isa_machdep.h @@ -0,0 +1,51 @@ +/* $OpenBSD: isa_machdep.h,v 1.2 2010/05/08 21:59:56 miod Exp $ */ + +/* + * Copyright (c) 2007 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice, this permission notice, and the disclaimer below + * appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_ISA_MACHDEP_H_ +#define _MACHINE_ISA_MACHDEP_H_ + +#include + +#define __NO_ISA_INTR_CHECK + +typedef struct mips_isa_chipset *isa_chipset_tag_t; + +struct mips_isa_chipset { + void *ic_v; + + void (*ic_attach_hook)(struct device *, struct device *, + struct isabus_attach_args *); + void *(*ic_intr_establish)(void *, int, int, int, int (*)(void *), + void *, char *); + void (*ic_intr_disestablish)(void *, void *); +}; + +#define isa_attach_hook(p, s, iba) \ + (*(iba)->iba_ic->ic_attach_hook)((p), (s), (iba)) +#define isa_intr_establish(c, i, t, l, f, a, n) \ + (*(c)->ic_intr_establish)((c)->ic_v, (i), (t), (l), (f), (a), (n)) +#define isa_intr_disestablish(c, h) \ + (*(c)->ic_intr_disestablish)((c)->ic_v, (h)) + +void loongson_generic_isa_attach_hook(struct device *, struct device *, + struct isabus_attach_args *); +void loongson_isa_specific_eoi(int); +void loongson_set_isa_imr(uint); + +#endif \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/kcore.h b/lib/libc/include/mips64el-openbsd-none/loongson/kcore.h new file mode 100644 index 000000000000..c38fa9f7f6e0 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/kcore.h @@ -0,0 +1,3 @@ +/* $OpenBSD: kcore.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/limits.h b/lib/libc/include/mips64el-openbsd-none/loongson/limits.h new file mode 100644 index 000000000000..12007d997ad2 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/limits.h @@ -0,0 +1,3 @@ +/* $OpenBSD: limits.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/loadfile_machdep.h b/lib/libc/include/mips64el-openbsd-none/loongson/loadfile_machdep.h new file mode 100644 index 000000000000..1486f8ce5c75 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/loadfile_machdep.h @@ -0,0 +1,49 @@ +/* $OpenBSD: loadfile_machdep.h,v 1.2 2015/07/17 20:44:39 miod Exp $ */ +/* $NetBSD: loadfile_machdep.h,v 1.2 2001/10/31 17:20:49 thorpej Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define BOOT_ELF +#define ELFSIZE 64 + +#define LOAD_KERNEL LOAD_ALL +#define COUNT_KERNEL COUNT_ALL + +#define LOADADDR(a) (((u_long)(a)) + offset) +#define ALIGNENTRY(a) ((u_long)(a)) +#define READ(f, b, c) read((f), (void *)LOADADDR(b), (c)) +#define BCOPY(s, d, c) memcpy((void *)LOADADDR(d), (void *)(s), (c)) +#define BZERO(d, c) memset((void *)LOADADDR(d), 0, (c)) +#define WARN(a) (void)(printf a, \ + printf((errno ? ": %s\n" : "\n"), \ + strerror(errno))) +#define PROGRESS(a) (void) printf a +#define ALLOC(a) alloc(a) +#define FREE(a, b) free(a, b) \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/loongson2.h b/lib/libc/include/mips64el-openbsd-none/loongson/loongson2.h new file mode 100644 index 000000000000..05688a8e0f9c --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/loongson2.h @@ -0,0 +1,3 @@ +/* $OpenBSD: loongson2.h,v 1.1.1.1 2009/08/06 20:51:44 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/loongson3.h b/lib/libc/include/mips64el-openbsd-none/loongson/loongson3.h new file mode 100644 index 000000000000..bcbe6ca7018f --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/loongson3.h @@ -0,0 +1,3 @@ +/* $OpenBSD: loongson3.h,v 1.1 2016/11/06 10:20:33 visa Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/memconf.h b/lib/libc/include/mips64el-openbsd-none/loongson/memconf.h new file mode 100644 index 000000000000..c7782048ac7e --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/memconf.h @@ -0,0 +1,3 @@ +/* $OpenBSD: memconf.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/mips_opcode.h b/lib/libc/include/mips64el-openbsd-none/loongson/mips_opcode.h new file mode 100644 index 000000000000..5b5cbc3494fd --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/mips_opcode.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mips_opcode.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/mplock.h b/lib/libc/include/mips64el-openbsd-none/loongson/mplock.h new file mode 100644 index 000000000000..dc963887f82c --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/mplock.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mplock.h,v 1.1 2017/01/19 14:51:02 visa Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/mutex.h b/lib/libc/include/mips64el-openbsd-none/loongson/mutex.h new file mode 100644 index 000000000000..8003e465f6b6 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/mutex.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mutex.h,v 1.2 2015/07/08 13:37:31 dlg Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/param.h b/lib/libc/include/mips64el-openbsd-none/loongson/param.h new file mode 100644 index 000000000000..cd410bd602a4 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/param.h @@ -0,0 +1,31 @@ +/* $OpenBSD: param.h,v 1.3 2013/03/23 16:12:23 deraadt Exp $ */ + +/* Public Domain */ + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ + +#define MACHINE "loongson" +#define _MACHINE loongson +#define MACHINE_ARCH "mips64el" /* not the canonical endianness */ +#define _MACHINE_ARCH mips64el +#define MACHINE_CPU "mips64" +#define _MACHINE_CPU mips64 +#define MID_MACHINE MID_MIPS64 + +#ifdef _KERNEL + +/* + * The Loongson level 1 cache expects software to prevent virtual + * aliases. Unfortunately, since this cache is physically tagged, + * this would require all virtual address to have the same bits 14 + * and 13 as their physical addresses, which is not something the + * kernel can guarantee unless the page size is at least 16KB. + */ +#define PAGE_SHIFT 14 + +#endif /* _KERNEL */ + +#include + +#endif /* _MACHINE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/pcb.h b/lib/libc/include/mips64el-openbsd-none/loongson/pcb.h new file mode 100644 index 000000000000..e48bfc2f316c --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/pcb.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pcb.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/pci_machdep.h b/lib/libc/include/mips64el-openbsd-none/loongson/pci_machdep.h new file mode 100644 index 000000000000..ade283806c11 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/pci_machdep.h @@ -0,0 +1,101 @@ +/* $OpenBSD: pci_machdep.h,v 1.10 2016/05/04 14:30:01 kettenis Exp $ */ + +/* + * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +typedef struct mips_pci_chipset *pci_chipset_tag_t; +typedef u_long pcitag_t; +typedef u_long pci_intr_handle_t; + +struct pci_attach_args; + +/* + * mips-specific PCI structure and type definitions. + * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE. + */ +struct mips_pci_chipset { + void *pc_conf_v; + void (*pc_attach_hook)(struct device *, + struct device *, struct pcibus_attach_args *); + int (*pc_bus_maxdevs)(void *, int); + pcitag_t (*pc_make_tag)(void *, int, int, int); + void (*pc_decompose_tag)(void *, pcitag_t, int *, + int *, int *); + int (*pc_conf_size)(void *, pcitag_t); + pcireg_t (*pc_conf_read)(void *, pcitag_t, int); + void (*pc_conf_write)(void *, pcitag_t, int, pcireg_t); + + void *pc_intr_v; + int (*pc_intr_map)(struct pci_attach_args *, pci_intr_handle_t *); + const char *(*pc_intr_string)(void *, pci_intr_handle_t); + void *(*pc_intr_establish)(void *, pci_intr_handle_t, + int, int (*)(void *), void *, char *); + void (*pc_intr_disestablish)(void *, void *); +}; + +/* + * Functions provided to machine-independent PCI code. + */ +#define pci_attach_hook(p, s, pba) \ + (*(pba)->pba_pc->pc_attach_hook)((p), (s), (pba)) +#define pci_bus_maxdevs(c, b) \ + (*(c)->pc_bus_maxdevs)((c)->pc_conf_v, (b)) +#define pci_make_tag(c, b, d, f) \ + (*(c)->pc_make_tag)((c)->pc_conf_v, (b), (d), (f)) +#define pci_decompose_tag(c, t, bp, dp, fp) \ + (*(c)->pc_decompose_tag)((c)->pc_conf_v, (t), (bp), (dp), (fp)) +#define pci_conf_size(c, t) \ + (*(c)->pc_conf_size)((c)->pc_conf_v, (t)) +#define pci_conf_read(c, t, r) \ + (*(c)->pc_conf_read)((c)->pc_conf_v, (t), (r)) +#define pci_conf_write(c, t, r, v) \ + (*(c)->pc_conf_write)((c)->pc_conf_v, (t), (r), (v)) +#define pci_intr_map(c, ihp) \ + (*(c)->pa_pc->pc_intr_map)((c), (ihp)) +#define pci_intr_map_msi(c, ihp) (-1) +#define pci_intr_map_msix(c, vec, ihp) (-1) +#define pci_intr_string(c, ih) \ + (*(c)->pc_intr_string)((c)->pc_intr_v, (ih)) +#define pci_intr_establish(c, ih, l, h, a, nm) \ + (*(c)->pc_intr_establish)((c)->pc_intr_v, (ih), (l), (h), (a), (nm)) +#define pci_intr_disestablish(c, iv) \ + (*(c)->pc_intr_disestablish)((c)->pc_intr_v, (iv)) +#define pci_probe_device_hook(c, a) (0) + +#define pci_min_powerstate(c, t) (PCI_PMCSR_STATE_D3) +#define pci_set_powerstate_md(c, t, s, p) + +/* PCI view of CPU memory */ +extern paddr_t loongson_dma_base; + +/* + * Functions used during early system configuration. + */ + +extern pcitag_t (*pci_make_tag_early)(int, int, int); +extern pcireg_t (*pci_conf_read_early)(pcitag_t, int); + +#define pci_dev_postattach(a, b) \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/pmap.h b/lib/libc/include/mips64el-openbsd-none/loongson/pmap.h new file mode 100644 index 000000000000..eda0b11a3c63 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/pmap.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pmap.h,v 1.1.1.1 2009/07/31 09:26:26 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/pmon.h b/lib/libc/include/mips64el-openbsd-none/loongson/pmon.h new file mode 100644 index 000000000000..7729adb4680a --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/pmon.h @@ -0,0 +1,209 @@ +/* $OpenBSD: pmon.h,v 1.5 2017/05/21 13:00:53 visa Exp $ */ + +/* + * Copyright (c) 2009, 2012 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_PMON_H_ +#define _MACHINE_PMON_H_ + +#if defined(_KERNEL) || defined(_STANDALONE) + +/* + * PMON2000 callvec definitions + */ + +/* 32-bit compatible types */ +typedef uint32_t pmon_size_t; +typedef int32_t pmon_ssize_t; +typedef int64_t pmon_off_t; + +int pmon_open(const char *, int, ...); +int pmon_close(int); +int pmon_read(int, void *, pmon_size_t); +pmon_ssize_t pmon_write(int, const void *, pmon_size_t); +pmon_off_t pmon_lseek(int, pmon_off_t, int); +int pmon_printf(const char *, ...); +void pmon_cacheflush(void); +char * pmon_gets(char *); + +#define PMON_MAXLN 256 /* internal gets() size limit */ + +extern int32_t pmon_callvec; + +const char *pmon_getarg(const int); +void pmon_init(int32_t, int32_t, int32_t, int32_t, uint32_t); + +#define PMON_ENVTYPE_ENVP 0 +#define PMON_ENVTYPE_EFI 1 +int pmon_getenvtype(void); + +/* + * The new environment interface is a /salmigondis/ of badly thought-out + * structs put together, pretending to be inspired by EFI but conveniently + * omitting key EFI structs because they are deemed non-applicable to + * MIPS systems. + * Of course, some fields are absolute addresses, while others are relative + * pointers, to add to the confusion. + */ + +struct pmon_env_reset { + void (*cold_boot)(void); /* not filled */ + void (*warm_boot)(void); + void (*boot)(unsigned int); /* not filled */ + void (*poweroff)(void); +}; + +/* all values are offsets relative to the beginning of the struct */ +struct pmon_env_ptr { + uint64_t offs_mem; + uint64_t offs_cpu; + uint64_t offs_sys; + uint64_t offs_irq; + uint64_t offs_iface; + uint64_t offs_special; + uint64_t offs_device; +}; + +struct pmon_env_smbios { + uint16_t version; + uint64_t vga_bios; + struct pmon_env_ptr ptrs; +}; + +struct pmon_env_efi { + uint64_t mps; /* not filled */ + uint64_t acpi; /* not filled */ + uint64_t acpi20; /* not filled */ + struct pmon_env_smbios bios; + uint64_t sal_systab; /* not filled */ + uint64_t bootinfo; /* not filled */ +}; + +struct pmon_env { + struct pmon_env_efi efi; + struct pmon_env_reset reset; +}; + +#define PMON_MEM_MAX 128 +struct pmon_env_mem_entry { + uint32_t node; + uint32_t type; +#define PMON_MEM_SYSTEM_LOW 1 /* physical memory <= 256 MB */ +#define PMON_MEM_SYSTEM_HIGH 2 /* physical memory > 256 MB */ +#define PMON_MEM_RESERVED 3 +#define PMON_MEM_PCI_IO 4 +#define PMON_MEM_PCI_MEM 5 +#define PMON_MEM_CPU_REGISTERS 6 +#define PMON_MEM_VIDEO_ROM 7 +#define PMON_MEM_OTHER_ROM 8 +#define PMON_MEM_ACPI_TABLE 9 + uint64_t address; + uint32_t size; +}; +struct pmon_env_mem { + uint16_t version; /* not filled */ + uint32_t nentries; + uint32_t mem_freq; + struct pmon_env_mem_entry mem_map[PMON_MEM_MAX]; +} __packed; + +struct pmon_env_cpu { + uint16_t version; /* not filled */ + uint32_t prid; /* cop0 PrID */ + uint32_t cputype; +/* 0 and 1 are supposedly intended for 2E and 2F, which do NOT provide this + interface; moreover Linux and PMON disagree on the values and have 2E and + 2F swapped. */ +#define PMON_CPUTYPE_LS3A 2 +#define PMON_CPUTYPE_LS3B 3 +#define PMON_CPUTYPE_LS1A 4 +#define PMON_CPUTYPE_LS1B 5 + uint32_t node; /* total number of NUMA nodes */ + uint16_t coreid; /* boot CPU core id */ + uint16_t reserved_cores; /* mask of reserved cores */ + uint32_t speed; + uint32_t ncpus; +} __packed; + +struct pmon_env_sys { + uint16_t version; /* not filled */ + uint32_t ccnuma_smp; + uint32_t double_channel; +} __packed; + +struct pmon_env_irq { + uint16_t version; /* not filled */ + uint16_t size; /* not filled */ + uint16_t rtr_bus; /* not filled */ + uint16_t rtr_devfn; /* not filled */ + uint32_t vendor; /* not filled */ + uint32_t device; /* not filled */ + uint32_t pic_type; +#define PMON_IRQ_PIC_HT 0 +#define PMON_IRQ_PIC_I8259 1 + uint64_t ht_interrupt_bit; + uint64_t ht_enable; + uint32_t node; + uint64_t pci_memory_space_start; + uint64_t pci_memory_space_end; + uint64_t pci_io_space_start; /* not filled */ + uint64_t pci_io_space_end; /* not filled */ + uint64_t pci_cfg_space; /* not filled */ +} __packed; + +struct pmon_env_iface { + uint16_t version; +#define PMON_IFACE_VERSION 0x0001 + uint16_t size; + uint8_t flag; + char description[64]; /* firmware version */ +} __packed; + +#define PMON_RESOURCE_MAX 128 +struct pmon_env_resource { + uint64_t start; + uint64_t end; + char name[64]; + uint32_t flags; +}; +struct pmon_env_special { + uint16_t version; + char name[64]; + uint32_t type; + struct pmon_env_resource resource[PMON_RESOURCE_MAX]; +}; + +struct pmon_env_device { + char name[64]; /* system description */ + uint32_t nentries; + struct pmon_env_resource resource[PMON_RESOURCE_MAX]; +}; + +const char *pmon_getenv(const char *); + +const struct pmon_env_reset *pmon_get_env_reset(void); +const struct pmon_env_smbios *pmon_get_env_smbios(void); +const struct pmon_env_mem *pmon_get_env_mem(void); +const struct pmon_env_cpu *pmon_get_env_cpu(void); +const struct pmon_env_sys *pmon_get_env_sys(void); +const struct pmon_env_irq *pmon_get_env_irq(void); +const struct pmon_env_iface *pmon_get_env_iface(void); +const struct pmon_env_special *pmon_get_env_special(void); +const struct pmon_env_device *pmon_get_env_device(void); + +#endif /* _KERNEL || _STANDALONE */ + +#endif /* _MACHINE_PMON_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/proc.h b/lib/libc/include/mips64el-openbsd-none/loongson/proc.h new file mode 100644 index 000000000000..27b68200cf3e --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/proc.h @@ -0,0 +1,3 @@ +/* $OpenBSD: proc.h,v 1.1.1.1 2009/07/31 09:26:26 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/profile.h b/lib/libc/include/mips64el-openbsd-none/loongson/profile.h new file mode 100644 index 000000000000..d258d1147b2d --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/profile.h @@ -0,0 +1,3 @@ +/* $OpenBSD: profile.h,v 1.1.1.1 2009/07/31 09:26:26 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/pte.h b/lib/libc/include/mips64el-openbsd-none/loongson/pte.h new file mode 100644 index 000000000000..24c761d66477 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/pte.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pte.h,v 1.1.1.1 2009/07/31 09:26:26 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/ptrace.h b/lib/libc/include/mips64el-openbsd-none/loongson/ptrace.h new file mode 100644 index 000000000000..bd8e88672533 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/ptrace.h @@ -0,0 +1,3 @@ +/* $OpenBSD: ptrace.h,v 1.1.1.1 2009/07/31 09:26:26 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/reg.h b/lib/libc/include/mips64el-openbsd-none/loongson/reg.h new file mode 100644 index 000000000000..aeecc496fedc --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/reg.h @@ -0,0 +1,3 @@ +/* $OpenBSD: reg.h,v 1.1.1.1 2009/07/31 09:26:26 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/regdef.h b/lib/libc/include/mips64el-openbsd-none/loongson/regdef.h new file mode 100644 index 000000000000..03ae54124e76 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/regdef.h @@ -0,0 +1,3 @@ +/* $OpenBSD: regdef.h,v 1.1.1.1 2009/07/31 09:26:26 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/regnum.h b/lib/libc/include/mips64el-openbsd-none/loongson/regnum.h new file mode 100644 index 000000000000..e371c1ed202e --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/regnum.h @@ -0,0 +1,3 @@ +/* $OpenBSD: regnum.h,v 1.1.1.1 2009/07/31 09:26:26 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/reloc.h b/lib/libc/include/mips64el-openbsd-none/loongson/reloc.h new file mode 100644 index 000000000000..4eb8c01cf15e --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/reloc.h @@ -0,0 +1,5 @@ +/* $OpenBSD: reloc.h,v 1.1 2017/08/12 15:33:41 visa Exp $ */ + +/* public domain */ + +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/setjmp.h b/lib/libc/include/mips64el-openbsd-none/loongson/setjmp.h new file mode 100644 index 000000000000..c834f0409a59 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/setjmp.h @@ -0,0 +1,3 @@ +/* $OpenBSD: setjmp.h,v 1.1.1.1 2009/07/31 09:26:26 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/signal.h b/lib/libc/include/mips64el-openbsd-none/loongson/signal.h new file mode 100644 index 000000000000..7f4d38dee765 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/signal.h @@ -0,0 +1,3 @@ +/* $OpenBSD: signal.h,v 1.1.1.1 2009/07/31 09:26:26 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/spinlock.h b/lib/libc/include/mips64el-openbsd-none/loongson/spinlock.h new file mode 100644 index 000000000000..63f58612b808 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/spinlock.h @@ -0,0 +1,3 @@ +/* $OpenBSD: spinlock.h,v 1.1.1.1 2009/07/31 09:26:26 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/sysarch.h b/lib/libc/include/mips64el-openbsd-none/loongson/sysarch.h new file mode 100644 index 000000000000..6dac08a77bf5 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/sysarch.h @@ -0,0 +1,3 @@ +/* $OpenBSD: sysarch.h,v 1.1.1.1 2009/11/22 18:12:44 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/tcb.h b/lib/libc/include/mips64el-openbsd-none/loongson/tcb.h new file mode 100644 index 000000000000..427e19101a00 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/tcb.h @@ -0,0 +1,3 @@ +/* $OpenBSD: tcb.h,v 1.2 2013/06/01 21:20:54 jasper Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/timetc.h b/lib/libc/include/mips64el-openbsd-none/loongson/timetc.h new file mode 100644 index 000000000000..d3d291c815ca --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/timetc.h @@ -0,0 +1,23 @@ +/* $OpenBSD: timetc.h,v 1.2 2020/07/18 08:37:43 visa Exp $ */ +/* + * Copyright (c) 2020 Paul Irofti + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TIMETC_H_ +#define _MACHINE_TIMETC_H_ + +#include + +#endif /* _MACHINE_TIMETC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/trap.h b/lib/libc/include/mips64el-openbsd-none/loongson/trap.h new file mode 100644 index 000000000000..c700eedba183 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/trap.h @@ -0,0 +1,3 @@ +/* $OpenBSD: trap.h,v 1.1.1.1 2009/07/31 09:26:26 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/loongson/vmparam.h b/lib/libc/include/mips64el-openbsd-none/loongson/vmparam.h new file mode 100644 index 000000000000..c6c4b75cfe65 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/loongson/vmparam.h @@ -0,0 +1,11 @@ +/* $OpenBSD: vmparam.h,v 1.5 2017/05/21 13:00:53 visa Exp $ */ +/* public domain */ +#ifndef _MACHINE_VMPARAM_H_ +#define _MACHINE_VMPARAM_H_ + +#define VM_PHYSSEG_MAX 8 /* Max number of physical memory segments */ +#define VM_PHYSSEG_STRAT VM_PSTRAT_BIGFIRST + +#include + +#endif /* _MACHINE_VMPARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/_types.h b/lib/libc/include/mips64el-openbsd-none/machine/_types.h new file mode 100644 index 000000000000..327e3d3e38ff --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/_types.h @@ -0,0 +1,3 @@ +/* $OpenBSD: _types.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/apmvar.h b/lib/libc/include/mips64el-openbsd-none/machine/apmvar.h new file mode 100644 index 000000000000..99c4026f9660 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/apmvar.h @@ -0,0 +1,127 @@ +/* $OpenBSD: apmvar.h,v 1.6 2019/01/22 02:36:30 phessler Exp $ */ + +/* + * Copyright (c) 2001 Alexander Guy + * Copyright (c) 1995 John T. Kohl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _MACHINE_APMVAR_H_ +#define _MACHINE_APMVAR_H_ + +#include + +/* Advanced Power Management (v1.0 and v1.1 specification) + * functions/defines/etc. + */ + +/* These definitions make up the heart of the user-land interface + * to the APM devices. + */ + +#define APM_AC_OFF 0x00 +#define APM_AC_ON 0x01 +#define APM_AC_BACKUP 0x02 +#define APM_AC_UNKNOWN 0xff +#define APM_BATT_HIGH 0x00 +#define APM_BATT_LOW 0x01 +#define APM_BATT_CRITICAL 0x02 +#define APM_BATT_CHARGING 0x03 +#define APM_BATT_UNKNOWN 0xff +#define APM_BATT_LIFE_UNKNOWN 0xff + +#define APM_NOEVENT 0x0000 +#define APM_STANDBY_REQ 0x0001 +#define APM_SUSPEND_REQ 0x0002 +#define APM_NORMAL_RESUME 0x0003 +#define APM_CRIT_RESUME 0x0004 /* suspend/resume happened + without us */ +#define APM_BATTERY_LOW 0x0005 +#define APM_POWER_CHANGE 0x0006 +#define APM_UPDATE_TIME 0x0007 +#define APM_CRIT_SUSPEND_REQ 0x0008 +#define APM_USER_STANDBY_REQ 0x0009 +#define APM_USER_SUSPEND_REQ 0x000A +#define APM_SYS_STANDBY_RESUME 0x000B +#define APM_CAPABILITY_CHANGE 0x000C /* apm v1.2 */ +#define APM_USER_HIBERNATE_REQ 0x000D +#define APM_EVENT_MASK 0xffff + +#define APM_EVENT_COMPOSE(t,i) ((((i) & 0x7fff) << 16)|((t) & APM_EVENT_MASK)) +#define APM_EVENT_TYPE(e) ((e) & APM_EVENT_MASK) +#define APM_EVENT_INDEX(e) ((e) >> 16) + +/* + * LP (Laptop Package) + * + * Copyright (C) 1994 by HOSOKAWA Tatsumi + * + * This software may be used, modified, copied, and distributed, in + * both source and binary form provided that the above copyright and + * these terms are retained. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with its + * use. + * + * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) + */ + +#define APM_BATTERY_ABSENT 4 + +struct apm_power_info { + u_char battery_state; + u_char ac_state; + u_char battery_life; + u_char spare1; + u_int minutes_left; /* estimate */ + u_int spare2[6]; +}; + +struct apm_ctl { + u_int dev; + u_int mode; +}; + +#define APM_IOC_REJECT _IOW('A', 0, struct apm_event_info) /* reject request # */ +#define APM_IOC_STANDBY _IO('A', 1) /* put system into standby */ +#define APM_IOC_SUSPEND _IO('A', 2) /* put system into suspend */ +#define APM_IOC_GETPOWER _IOR('A', 3, struct apm_power_info) /* fetch battery state */ +#define APM_IOC_DEV_CTL _IOW('A', 5, struct apm_ctl) /* put device into mode */ +#define APM_IOC_PRN_CTL _IOW('A', 6, int ) /* driver power status msg */ +#define APM_PRINT_ON 0 /* driver power status displayed */ +#define APM_PRINT_OFF 1 /* driver power status not displayed */ +#define APM_PRINT_PCT 2 /* driver power status only displayed + if the percentage changes */ +#define APM_IOC_STANDBY_REQ _IO('A', 7) /* request standby */ +#define APM_IOC_SUSPEND_REQ _IO('A', 8) /* request suspend */ +#define APM_IOC_HIBERNATE _IO('A', 9) /* put system into hibernate */ + +#ifdef _KERNEL +void apm_setinfohook(int (*)(struct apm_power_info *)); +int apm_record_event(u_int, const char *, const char *); +#endif + +#endif /* _MACHINE_APMVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/asm.h b/lib/libc/include/mips64el-openbsd-none/machine/asm.h new file mode 100644 index 000000000000..63eab175139b --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/asm.h @@ -0,0 +1,9 @@ +/* $OpenBSD: asm.h,v 1.2 2016/11/18 15:38:14 visa Exp $ */ +/* public domain */ + +#ifdef MULTIPROCESSOR +#define HW_GET_CPU_INFO(ci, tmp) \ + dmfc0 ci, COP_0_ERROR_PC +#endif + +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/atomic.h b/lib/libc/include/mips64el-openbsd-none/machine/atomic.h new file mode 100644 index 000000000000..19aa2fd4f69b --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/atomic.h @@ -0,0 +1,3 @@ +/* $OpenBSD: atomic.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/autoconf.h b/lib/libc/include/mips64el-openbsd-none/machine/autoconf.h new file mode 100644 index 000000000000..7292105a5be8 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/autoconf.h @@ -0,0 +1,124 @@ +/* $OpenBSD: autoconf.h,v 1.17 2017/05/21 13:00:53 visa Exp $ */ + +/* + * Copyright (c) 2001-2003 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * Definitions used by autoconfiguration. + */ + +#ifndef _MACHINE_AUTOCONF_H_ +#define _MACHINE_AUTOCONF_H_ + +#include + +struct bonito_config; +struct htb_config; +struct mips_isa_chipset; + +/* + * List of legacy I/O ranges. + */ +struct legacy_io_range { + bus_addr_t start; + bus_size_t end; /* inclusive */ +}; + +/* + * Per platform information. + */ +struct platform { + int system_type; +#define LOONGSON_2E 0x0000 /* Generic Loongson 2E system */ +#define LOONGSON_YEELOONG 0x0001 /* Lemote Yeeloong */ +#define LOONGSON_GDIUM 0x0002 /* EMTEC Gdium Liberty */ +#define LOONGSON_FULOONG 0x0003 /* Lemote Fuloong */ +#define LOONGSON_LYNLOONG 0x0004 /* Lemote Lynloong */ +#define LOONGSON_EBT700 0x0005 /* eBenton EBT700 */ +#define LOONGSON_3A 0x0066 /* Loongson 2Gq or 3A based system */ + + char *vendor; + char *product; + + const struct bonito_config *bonito_config; + const struct htb_config *htb_config; + struct mips_isa_chipset *isa_chipset; + const struct legacy_io_range *legacy_io_ranges; + + void (*setup)(void); + void (*device_register)(struct device *, + void *); + + void (*powerdown)(void); + void (*reset)(void); + int (*suspend)(void); + int (*resume)(void); + +#ifdef MULTIPROCESSOR + void (*config_secondary_cpus)( + struct device *, cfprint_t); + void (*boot_secondary_cpu)( + struct cpu_info *); + int (*ipi_establish)(int (*)(void *), + cpuid_t); + void (*ipi_set)(cpuid_t); + void (*ipi_clear)(cpuid_t); +#endif /* MULTIPROCESSOR */ +}; + +#define LOONGSON_MAXCPUS 16 + +extern const struct platform *sys_platform; +extern void *loongson_videobios; +extern uint loongson_cpumask; +extern uint loongson_ver; +extern int nnodes; + +#ifdef MULTIPROCESSOR +extern uint64_t cpu_spinup_a0; +extern uint64_t cpu_spinup_sp; +#endif + +struct mainbus_attach_args { + const char *maa_name; +}; + +extern struct device *bootdv; +extern char bootdev[]; +extern enum devclass bootdev_class; + +extern bus_space_tag_t early_mem_t; +extern bus_space_tag_t early_io_t; + +#define REGVAL8(x) *((volatile uint8_t *)PHYS_TO_XKPHYS((x), CCA_NC)) +#define REGVAL32(x) *((volatile uint32_t *)PHYS_TO_XKPHYS((x), CCA_NC)) +#define REGVAL64(x) *((volatile uint64_t *)PHYS_TO_XKPHYS((x), CCA_NC)) + +#define REGVAL(x) REGVAL32(x) + +#include + +#endif /* _MACHINE_AUTOCONF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/bus.h b/lib/libc/include/mips64el-openbsd-none/machine/bus.h new file mode 100644 index 000000000000..24430920dde3 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/bus.h @@ -0,0 +1,513 @@ +/* $OpenBSD: bus.h,v 1.8 2020/04/14 17:35:28 kettenis Exp $ */ + +/* + * Copyright (c) 2003-2004 Opsycon AB Sweden. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BUS_H_ +#define _MACHINE_BUS_H_ + +#ifdef __STDC__ +#define CAT(a,b) a##b +#define CAT3(a,b,c) a##b##c +#else +#define CAT(a,b) a/**/b +#define CAT3(a,b,c) a/**/b/**/c +#endif + +/* + * Bus access types. + */ +struct mips_bus_space; +typedef u_long bus_addr_t; +typedef u_long bus_size_t; +typedef u_long bus_space_handle_t; +typedef struct mips_bus_space *bus_space_tag_t; + +struct mips_bus_space { + bus_addr_t bus_base; + void *bus_private; + u_int8_t (*_space_read_1)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_1)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int8_t); + u_int16_t (*_space_read_2)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_2)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int16_t); + u_int32_t (*_space_read_4)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_4)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int32_t); + u_int64_t (*_space_read_8)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_8)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int64_t); + void (*_space_read_raw_2)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_2)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + void (*_space_read_raw_4)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_4)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + void (*_space_read_raw_8)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_8)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + int (*_space_map)(bus_space_tag_t , bus_addr_t, + bus_size_t, int, bus_space_handle_t *); + void (*_space_unmap)(bus_space_tag_t, bus_space_handle_t, + bus_size_t); + int (*_space_subregion)(bus_space_tag_t, bus_space_handle_t, + bus_size_t, bus_size_t, bus_space_handle_t *); + void * (*_space_vaddr)(bus_space_tag_t, bus_space_handle_t); + paddr_t (*_space_mmap)(bus_space_tag_t, bus_addr_t, off_t, + int, int); +}; + +#define bus_space_read_1(t, h, o) (*(t)->_space_read_1)((t), (h), (o)) +#define bus_space_read_2(t, h, o) (*(t)->_space_read_2)((t), (h), (o)) +#define bus_space_read_4(t, h, o) (*(t)->_space_read_4)((t), (h), (o)) +#define bus_space_read_8(t, h, o) (*(t)->_space_read_8)((t), (h), (o)) + +#define bus_space_write_1(t, h, o, v) (*(t)->_space_write_1)((t), (h), (o), (v)) +#define bus_space_write_2(t, h, o, v) (*(t)->_space_write_2)((t), (h), (o), (v)) +#define bus_space_write_4(t, h, o, v) (*(t)->_space_write_4)((t), (h), (o), (v)) +#define bus_space_write_8(t, h, o, v) (*(t)->_space_write_8)((t), (h), (o), (v)) + +#define bus_space_read_raw_multi_2(t, h, a, b, l) \ + (*(t)->_space_read_raw_2)((t), (h), (a), (b), (l)) +#define bus_space_read_raw_multi_4(t, h, a, b, l) \ + (*(t)->_space_read_raw_4)((t), (h), (a), (b), (l)) +#define bus_space_read_raw_multi_8(t, h, a, b, l) \ + (*(t)->_space_read_raw_8)((t), (h), (a), (b), (l)) + +#define bus_space_write_raw_multi_2(t, h, a, b, l) \ + (*(t)->_space_write_raw_2)((t), (h), (a), (b), (l)) +#define bus_space_write_raw_multi_4(t, h, a, b, l) \ + (*(t)->_space_write_raw_4)((t), (h), (a), (b), (l)) +#define bus_space_write_raw_multi_8(t, h, a, b, l) \ + (*(t)->_space_write_raw_8)((t), (h), (a), (b), (l)) + +#define bus_space_map(t, o, s, c, p) (*(t)->_space_map)((t), (o), (s), (c), (p)) +#define bus_space_unmap(t, h, s) (*(t)->_space_unmap)((t), (h), (s)) +#define bus_space_subregion(t, h, o, s, p) \ + (*(t)->_space_subregion)((t), (h), (o), (s), (p)) + +#define BUS_SPACE_MAP_CACHEABLE 0x01 +#define BUS_SPACE_MAP_LINEAR 0x02 +#define BUS_SPACE_MAP_PREFETCHABLE 0x04 + +#define bus_space_vaddr(t, h) (*(t)->_space_vaddr)((t), (h)) +#define bus_space_mmap(t, a, o, p, f) \ + (*(t)->_space_mmap)((t), (a), (o), (p), (f)) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_multi(n,m) \ +static __inline void \ +CAT(bus_space_read_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t o, CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) \ + *x++ = CAT(bus_space_read_,n)(bst, bsh, o); \ +} + +bus_space_read_multi(1,8) +bus_space_read_multi(2,16) +bus_space_read_multi(4,32) +bus_space_read_multi(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_region(n,m) \ +static __inline void \ +CAT(bus_space_read_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) { \ + *x++ = CAT(bus_space_read_,n)(bst, bsh, ba); \ + ba += (n); \ + } \ +} + +bus_space_read_region(1,8) +bus_space_read_region(2,16) +bus_space_read_region(4,32) +bus_space_read_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_raw_region(n,m) \ +static __inline void \ +CAT(bus_space_read_raw_region_,n)(bus_space_tag_t bst, \ + bus_space_handle_t bsh, \ + bus_addr_t ba, u_int8_t *x, size_t cnt) \ +{ \ + cnt >>= ((n) >> 1); \ + while (cnt--) { \ + CAT(bus_space_read_raw_multi_,n)(bst, bsh, ba, x, (n)); \ + ba += (n); \ + x += (n); \ + } \ +} + +bus_space_read_raw_region(2,16) +bus_space_read_raw_region(4,32) +bus_space_read_raw_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_multi(n,m) \ +static __inline void \ +CAT(bus_space_write_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t o, const CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) \ + CAT(bus_space_write_,n)(bst, bsh, o, *x++); \ +} + +bus_space_write_multi(1,8) +bus_space_write_multi(2,16) +bus_space_write_multi(4,32) +bus_space_write_multi(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_region(n,m) \ +static __inline void \ +CAT(bus_space_write_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, const CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) { \ + CAT(bus_space_write_,n)(bst, bsh, ba, *x++); \ + ba += (n); \ + } \ +} + +bus_space_write_region(1,8) +bus_space_write_region(2,16) +bus_space_write_region(4,32) +bus_space_write_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_raw_region(n,m) \ +static __inline void \ +CAT(bus_space_write_raw_region_,n)(bus_space_tag_t bst, \ + bus_space_handle_t bsh, \ + bus_addr_t ba, const u_int8_t *x, size_t cnt) \ +{ \ + cnt >>= ((n) >> 1); \ + while (cnt--) { \ + CAT(bus_space_write_raw_multi_,n)(bst, bsh, ba, x, (n)); \ + ba += (n); \ + x += (n); \ + } \ +} + +bus_space_write_raw_region(2,16) +bus_space_write_raw_region(4,32) +bus_space_write_raw_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_set_region(n,m) \ +static __inline void \ +CAT(bus_space_set_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(u_int,m,_t) x, size_t cnt) \ +{ \ + while (cnt--) { \ + CAT(bus_space_write_,n)(bst, bsh, ba, x); \ + ba += (n); \ + } \ +} + +bus_space_set_region(1,8) +bus_space_set_region(2,16) +bus_space_set_region(4,32) +bus_space_set_region(8,64) + +/*----------------------------------------------------------------------------*/ +static __inline void +bus_space_copy_1(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + char *s = (char *)(h1 + o1); + char *d = (char *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + + +static __inline void +bus_space_copy_2(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + short *s = (short *)(h1 + o1); + short *d = (short *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + +static __inline void +bus_space_copy_4(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + int *s = (int *)(h1 + o1); + int *d = (int *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + +static __inline void +bus_space_copy_8(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + int64_t *s = (int64_t *)(h1 + o1); + int64_t *d = (int64_t *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + +int generic_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, + bus_space_handle_t *); +void generic_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t); +int generic_space_region(bus_space_tag_t, bus_space_handle_t, bus_size_t, + bus_size_t, bus_space_handle_t *); +void *generic_space_vaddr(bus_space_tag_t, bus_space_handle_t); +uint8_t generic_space_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint16_t generic_space_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint32_t generic_space_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint64_t generic_space_read_8(bus_space_tag_t, bus_space_handle_t, bus_size_t); +void generic_space_read_raw_2(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint8_t); +void generic_space_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint16_t); +void generic_space_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint32_t); +void generic_space_write_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint64_t); +void generic_space_write_raw_2(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); +void generic_space_read_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); +void generic_space_read_raw_8(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_raw_8(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); +paddr_t generic_space_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int); + +/*----------------------------------------------------------------------------*/ +/* + * Bus read/write barrier methods. + * + * void bus_space_barrier(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * bus_size_t len, int flags); + * + */ +static inline void +bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, + bus_size_t length, int flags) +{ + __asm__ volatile ("sync" ::: "memory"); +} +#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ +#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ + +#define BUS_DMA_WAITOK 0x0000 +#define BUS_DMA_NOWAIT 0x0001 +#define BUS_DMA_ALLOCNOW 0x0002 +#define BUS_DMA_COHERENT 0x0008 +#define BUS_DMA_BUS1 0x0010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x0020 +#define BUS_DMA_BUS3 0x0040 +#define BUS_DMA_BUS4 0x0080 +#define BUS_DMA_READ 0x0100 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x0200 /* mapping is memory -> device only */ +#define BUS_DMA_STREAMING 0x0400 /* hint: sequential, unidirectional */ +#define BUS_DMA_ZERO 0x0800 /* zero memory in dmamem_alloc */ +#define BUS_DMA_NOCACHE 0x1000 +#define BUS_DMA_64BIT 0x2000 /* device handles 64bit dva */ + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct proc; +struct uio; + +#define BUS_DMASYNC_POSTREAD 0x0001 +#define BUS_DMASYNC_POSTWRITE 0x0002 +#define BUS_DMASYNC_PREREAD 0x0004 +#define BUS_DMASYNC_PREWRITE 0x0008 + +typedef struct machine_bus_dma_tag *bus_dma_tag_t; +typedef struct machine_bus_dmamap *bus_dmamap_t; + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +struct machine_bus_dma_segment { + bus_addr_t ds_addr; /* DMA address */ + bus_size_t ds_len; /* length of transfer */ + + paddr_t _ds_paddr; /* CPU address */ + vaddr_t _ds_vaddr; /* CPU address */ +}; +typedef struct machine_bus_dma_segment bus_dma_segment_t; + +/* + * bus_dma_tag_t + * + * A machine-dependent opaque type describing the implementation of + * DMA for a given bus. + */ + +struct machine_bus_dma_tag { + void *_cookie; /* cookie used in the guts */ + + /* + * DMA mapping methods. + */ + int (*_dmamap_create)(bus_dma_tag_t , bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); + void (*_dmamap_destroy)(bus_dma_tag_t , bus_dmamap_t); + int (*_dmamap_load)(bus_dma_tag_t , bus_dmamap_t, void *, + bus_size_t, struct proc *, int); + int (*_dmamap_load_mbuf)(bus_dma_tag_t , bus_dmamap_t, + struct mbuf *, int); + int (*_dmamap_load_uio)(bus_dma_tag_t , bus_dmamap_t, + struct uio *, int); + int (*_dmamap_load_raw)(bus_dma_tag_t , bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); + int (*_dmamap_load_buffer)(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int, paddr_t *, int *, int); + void (*_dmamap_unload)(bus_dma_tag_t , bus_dmamap_t); + void (*_dmamap_sync)(bus_dma_tag_t , bus_dmamap_t, + bus_addr_t, bus_size_t, int); + + /* + * DMA memory utility functions. + */ + int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); + void (*_dmamem_free)(bus_dma_tag_t, bus_dma_segment_t *, int); + int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); + void (*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t); + paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, + int, off_t, int, int); + + /* + * internal memory address translation information. + */ + bus_addr_t (*_pa_to_device)(paddr_t); + paddr_t (*_device_to_pa)(bus_addr_t); + bus_addr_t _dma_mask; +}; + +#define bus_dmamap_create(t, s, n, m, b, f, p) \ + (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) +#define bus_dmamap_destroy(t, p) \ + (*(t)->_dmamap_destroy)((t), (p)) +#define bus_dmamap_load(t, m, b, s, p, f) \ + (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) +#define bus_dmamap_load_mbuf(t, m, b, f) \ + (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) +#define bus_dmamap_load_uio(t, m, u, f) \ + (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) +#define bus_dmamap_load_raw(t, m, sg, n, s, f) \ + (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) +#define bus_dmamap_unload(t, p) \ + (*(t)->_dmamap_unload)((t), (p)) +#define bus_dmamap_sync(t, p, a, l, o) \ + (void)((t)->_dmamap_sync ? \ + (*(t)->_dmamap_sync)((t), (p), (a), (l), (o)) : (void)0) + +#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ + (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f)) +#define bus_dmamem_free(t, sg, n) \ + (*(t)->_dmamem_free)((t), (sg), (n)) +#define bus_dmamem_map(t, sg, n, s, k, f) \ + (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f)) +#define bus_dmamem_unmap(t, k, s) \ + (*(t)->_dmamem_unmap)((t), (k), (s)) +#define bus_dmamem_mmap(t, sg, n, o, p, f) \ + (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f)) + +int _dmamap_create(bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); +void _dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); +int _dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); +int _dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *, int); +int _dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, struct uio *, int); +int _dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); +int _dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int, paddr_t *, int *, int); +void _dmamap_unload(bus_dma_tag_t, bus_dmamap_t); +void _dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, + bus_size_t, int); + +int _dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); +void _dmamem_free(bus_dma_tag_t, bus_dma_segment_t *, int); +int _dmamem_map(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); +void _dmamem_unmap(bus_dma_tag_t, caddr_t, size_t); +paddr_t _dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, int, int); +int _dmamem_alloc_range(bus_dma_tag_t, bus_size_t, bus_size_t, bus_size_t, + bus_dma_segment_t *, int, int *, int, paddr_t, paddr_t); + +/* + * bus_dmamap_t + * + * Describes a DMA mapping. + */ +struct machine_bus_dmamap { + /* + * PRIVATE MEMBERS: not for use by machine-independent code. + */ + bus_size_t _dm_size; /* largest DMA transfer mappable */ + int _dm_segcnt; /* number of segs this map can map */ + bus_size_t _dm_maxsegsz; /* largest possible segment */ + bus_size_t _dm_boundary; /* don't cross this */ + int _dm_flags; /* misc. flags */ + + void *_dm_cookie; /* cookie for bus-specific functions */ + + /* + * PUBLIC MEMBERS: these are used by machine-independent code. + */ + bus_size_t dm_mapsize; /* size of the mapping */ + int dm_nsegs; /* # valid segments in mapping */ + bus_dma_segment_t dm_segs[1]; /* segments; variable length */ +}; + +#endif /* _MACHINE_BUS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/conf.h b/lib/libc/include/mips64el-openbsd-none/machine/conf.h new file mode 100644 index 000000000000..8eafed12d428 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/conf.h @@ -0,0 +1,42 @@ +/* $OpenBSD: conf.h,v 1.4 2022/06/28 14:43:50 visa Exp $ */ +/* $NetBSD: conf.h,v 1.2 1996/05/05 19:28:34 christos Exp $ */ + +/* + * Copyright (c) 1996 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +/* open, close, write, ioctl, kqueue */ +#define cdev_apm_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev, 0, 0, dev_init(c,n,kqfilter) } + +cdev_decl(apm); \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/cpu.h b/lib/libc/include/mips64el-openbsd-none/machine/cpu.h new file mode 100644 index 000000000000..d3d84bf3dbf9 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/cpu.h @@ -0,0 +1,103 @@ +/* $OpenBSD: cpu.h,v 1.8 2017/07/30 16:05:24 visa Exp $ */ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell and Rick Macklem. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Copyright (C) 1989 Digital Equipment Corporation. + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies. + * Digital Equipment Corporation makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * from: @(#)cpu.h 8.4 (Berkeley) 1/4/94 + */ + +#ifdef _KERNEL + +#if defined(MULTIPROCESSOR) && !defined(_LOCORE) +#define MAXCPUS 4 +struct cpu_info; +struct cpu_info *hw_getcurcpu(void); +void hw_setcurcpu(struct cpu_info *); +void hw_cpu_boot_secondary(struct cpu_info *); +void hw_cpu_hatch(struct cpu_info *); +void hw_cpu_spinup_trampoline(struct cpu_info *); +int hw_ipi_intr_establish(int (*)(void *), u_long); +void hw_ipi_intr_set(u_long); +void hw_ipi_intr_clear(u_long); +#endif /* MULTIPROCESSOR && !_LOCORE */ + +#if defined(CPU_LOONGSON2) && !defined(CPU_LOONGSON3) +#define Mips_SyncCache(ci) \ + Loongson2_SyncCache((ci)) +#define Mips_InvalidateICache(ci, va, l) \ + Loongson2_InvalidateICache((ci), (va), (l)) +#define Mips_InvalidateICachePage(ci, va) \ + Loongson2_InvalidateICachePage((ci), (va)) +#define Mips_SyncICache(ci) \ + Loongson2_SyncICache((ci)) +#define Mips_SyncDCachePage(ci, va, pa) \ + Loongson2_SyncDCachePage((ci), (va), (pa)) +#define Mips_HitSyncDCachePage(ci, va, pa) \ + Loongson2_SyncDCachePage((ci), (va), (pa)) +#define Mips_HitSyncDCache(ci, va, l) \ + Loongson2_HitSyncDCache((ci), (va), (l)) +#define Mips_IOSyncDCache(ci, va, l, h) \ + Loongson2_IOSyncDCache((ci), (va), (l), (h)) +#define Mips_HitInvalidateDCache(ci, va, l) \ + Loongson2_HitInvalidateDCache((ci), (va), (l)) +#endif + +#if defined(CPU_LOONGSON3) && !defined(CPU_LOONGSON2) +#define Mips_SyncCache(ci) \ + Loongson3_SyncCache((ci)) +#define Mips_InvalidateICache(ci, va, l) \ + Loongson3_InvalidateICache((ci), (va), (l)) +#define Mips_InvalidateICachePage(ci, va) \ + Loongson3_InvalidateICachePage((ci), (va)) +#define Mips_SyncICache(ci) \ + Loongson3_SyncICache((ci)) +#define Mips_SyncDCachePage(ci, va, pa) \ + Loongson3_SyncDCachePage((ci), (va), (pa)) +#define Mips_HitSyncDCachePage(ci, va, pa) \ + Loongson3_SyncDCachePage((ci), (va), (pa)) +#define Mips_HitSyncDCache(ci, va, l) \ + Loongson3_HitSyncDCache((ci), (va), (l)) +#define Mips_IOSyncDCache(ci, va, l, h) \ + Loongson3_IOSyncDCache((ci), (va), (l), (h)) +#define Mips_HitInvalidateDCache(ci, va, l) \ + Loongson3_HitInvalidateDCache((ci), (va), (l)) +#endif + +#endif /* _KERNEL */ + +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/cpustate.h b/lib/libc/include/mips64el-openbsd-none/machine/cpustate.h new file mode 100644 index 000000000000..f5aff1a41b08 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/cpustate.h @@ -0,0 +1,3 @@ +/* $OpenBSD: cpustate.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/db_machdep.h b/lib/libc/include/mips64el-openbsd-none/machine/db_machdep.h new file mode 100644 index 000000000000..3759d833718e --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/db_machdep.h @@ -0,0 +1,3 @@ +/* $OpenBSD: db_machdep.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/elf.h b/lib/libc/include/mips64el-openbsd-none/machine/elf.h new file mode 100644 index 000000000000..5918df727bda --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/elf.h @@ -0,0 +1,3 @@ +/* $OpenBSD: elf.h,v 1.1 2024/07/14 19:33:59 miod Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/endian.h b/lib/libc/include/mips64el-openbsd-none/machine/endian.h new file mode 100644 index 000000000000..2e7392a0828e --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/endian.h @@ -0,0 +1,3 @@ +/* $OpenBSD: endian.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/exec.h b/lib/libc/include/mips64el-openbsd-none/machine/exec.h new file mode 100644 index 000000000000..53433783f0c0 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/exec.h @@ -0,0 +1,3 @@ +/* $OpenBSD: exec.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/fpu.h b/lib/libc/include/mips64el-openbsd-none/machine/fpu.h new file mode 100644 index 000000000000..19ee8af41438 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/fpu.h @@ -0,0 +1,3 @@ +/* $OpenBSD: fpu.h,v 1.1 2010/09/17 00:34:04 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/frame.h b/lib/libc/include/mips64el-openbsd-none/machine/frame.h new file mode 100644 index 000000000000..d14827e33c0e --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/frame.h @@ -0,0 +1,3 @@ +/* $OpenBSD: frame.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/hibernate.h b/lib/libc/include/mips64el-openbsd-none/machine/hibernate.h new file mode 100644 index 000000000000..f0a99c6df6e3 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/hibernate.h @@ -0,0 +1,33 @@ +/* $OpenBSD: hibernate.h,v 1.3 2018/06/21 07:33:30 mlarkin Exp $ */ + +/* + * Copyright (c) 2013 Paul Irofti. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +#include + +/* Loongson hibernate support structures and functions */ + +int get_hibernate_info_md(union hibernate_info *); +void hibernate_flush(void); +void hibernate_enter_resume_mapping(vaddr_t, paddr_t, int); +int hibernate_inflate_skip(union hibernate_info *, paddr_t); +int hibernate_suspend(void); +void hibernate_switch_stack_machdep(void); +void hibernate_resume_machdep(vaddr_t); +void hibernate_activate_resume_pt_machdep(void); +void hibernate_enable_intr_machdep(void); +void hibernate_disable_intr_machdep(void); \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/hibernate_var.h b/lib/libc/include/mips64el-openbsd-none/machine/hibernate_var.h new file mode 100644 index 000000000000..de84657a4b51 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/hibernate_var.h @@ -0,0 +1,39 @@ +/* $OpenBSD: hibernate_var.h,v 1.1 2013/06/02 21:46:04 pirofti Exp $ */ + +/* + * Copyright (c) 2013 Paul Irofti. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* Loongson hibernate support definitions */ + +#define PAGE_MASK_4M ((256 * PAGE_SIZE) - 1) + +#define PIGLET_PAGE_MASK ~((paddr_t)PAGE_MASK_4M) + +/* + * Steal hibernate pages right after the first page which is reserved + * for the exception area. + * */ +#define HIBERNATE_STACK_PAGE (PAGE_SIZE * 1) +#define HIBERNATE_INFLATE_PAGE (PAGE_SIZE * 2) +#define HIBERNATE_COPY_PAGE (PAGE_SIZE * 3) +#define HIBERNATE_HIBALLOC_PAGE (PAGE_SIZE * 4) + +#define HIBERNATE_RESERVED_PAGES 4 + +/* Use 4MB hibernation chunks */ +#define HIBERNATE_CHUNK_SIZE 0x400000 + +#define HIBERNATE_CHUNK_TABLE_SIZE 0x100000 \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/ieee.h b/lib/libc/include/mips64el-openbsd-none/machine/ieee.h new file mode 100644 index 000000000000..d390acb3c59f --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/ieee.h @@ -0,0 +1,3 @@ +/* $OpenBSD: ieee.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/ieeefp.h b/lib/libc/include/mips64el-openbsd-none/machine/ieeefp.h new file mode 100644 index 000000000000..17e880358e20 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/ieeefp.h @@ -0,0 +1,3 @@ +/* $OpenBSD: ieeefp.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/intr.h b/lib/libc/include/mips64el-openbsd-none/machine/intr.h new file mode 100644 index 000000000000..64d103bc39aa --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/intr.h @@ -0,0 +1,193 @@ +/* $OpenBSD: intr.h,v 1.19 2025/05/10 10:01:03 visa Exp $ */ + +/* + * Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _MACHINE_INTR_H_ +#define _MACHINE_INTR_H_ + +#define __USE_MI_SOFTINTR + +#include + +/* + * The interrupt level ipl is a logical level; per-platform interrupt + * code will turn it into the appropriate hardware interrupt masks + * values. + * + * Interrupt sources on the CPU are kept enabled regardless of the + * current ipl value; individual hardware sources interrupting while + * logically masked are masked on the fly, remembered as pending, and + * unmasked at the first splx() opportunity. + * + * An exception to this rule is the clock interrupt. Clock interrupts + * are always allowed to happen, but will (of course!) not be serviced + * if logically masked. The reason for this is that clocks usually sit on + * INT5 and cannot be easily masked if external hardware masking is used. + */ + +/* Interrupt priority `levels'; not mutually exclusive. */ +#define IPL_NONE 0 /* nothing */ +#define IPL_SOFTINT 1 /* soft interrupts */ +#define IPL_SOFTCLOCK 1 /* soft clock interrupts */ +#define IPL_SOFTNET 2 /* soft network interrupts */ +#define IPL_SOFTTTY 3 /* soft terminal interrupts */ +#define IPL_SOFTHIGH IPL_SOFTTTY /* highest level of soft interrupts */ +#define IPL_BIO 4 /* block I/O */ +#define IPL_AUDIO IPL_BIO +#define IPL_NET 5 /* network */ +#define IPL_TTY 6 /* terminal */ +#define IPL_VM 7 /* memory allocation */ +#define IPL_CLOCK 8 /* clock */ +#define IPL_STATCLOCK IPL_CLOCK +#define IPL_SCHED 9 /* everything */ +#define IPL_HIGH 9 /* everything */ +#define IPL_IPI 10 /* interprocessor interrupt */ +#define NIPLS 11 /* number of levels */ + +#define IPL_MPFLOOR IPL_TTY + +/* Interrupt priority 'flags'. */ +#define IPL_MPSAFE 0x100 + +/* Interrupt sharing types. */ +#define IST_NONE 0 /* none */ +#define IST_PULSE 1 /* pulsed */ +#define IST_EDGE 2 /* edge-triggered */ +#define IST_LEVEL 3 /* level-triggered */ + +#ifndef _LOCORE + +void softintr(int); + +#define splbio() splraise(IPL_BIO) +#define splnet() splraise(IPL_NET) +#define spltty() splraise(IPL_TTY) +#define splaudio() splraise(IPL_AUDIO) +#define splclock() splraise(IPL_CLOCK) +#define splvm() splraise(IPL_VM) +#define splhigh() splraise(IPL_HIGH) + +#define splsoftclock() splraise(IPL_SOFTCLOCK) +#define splsoftnet() splraise(IPL_SOFTNET) +#define splstatclock() splhigh() + +#define splsched() splhigh() +#define spl0() spllower(0) + +void splinit(void); + +#ifdef DIAGNOSTIC +/* + * Although this function is implemented in MI code, it must be in this MD + * header because we don't want this header to include MI includes. + */ +void splassert_fail(int, int, const char *); +extern int splassert_ctl; +void splassert_check(int, const char *); +#define splassert(__wantipl) do { \ + if (splassert_ctl > 0) { \ + splassert_check(__wantipl, __func__); \ + } \ +} while (0) +#define splsoftassert(wantipl) splassert(wantipl) +#else +#define splassert(X) +#define splsoftassert(X) +#endif + +void register_splx_handler(void (*)(int)); +int splraise(int); +void splx(int); +int spllower(int); + +/* + * Interrupt control struct used by interrupt dispatchers + * to hold interrupt handler info. + */ + +#include + +struct intrhand { + struct intrhand *ih_next; + int (*ih_fun)(void *); + void *ih_arg; + int ih_level; + int ih_irq; + int ih_flags; +#define IH_MPSAFE 0x01 + struct evcount ih_count; +}; + +void intr_barrier(void *); + +/* + * Low level interrupt dispatcher registration data. + */ + +/* Schedule priorities for base interrupts (CPU) */ +#define INTPRI_IPI 0 +#define INTPRI_CLOCK 1 +/* other values are system-specific */ + +#define NLOWINT 4 /* Number of low level registrations possible */ + +extern uint32_t idle_mask; + +struct trapframe; +void set_intr(int, uint32_t, uint32_t(*)(uint32_t, struct trapframe *)); + +uint32_t updateimask(uint32_t); +void dosoftint(void); + +#ifdef MULTIPROCESSOR +extern uint32_t ipi_mask; +#define ENABLEIPI() updateimask(~ipi_mask) +#endif + +struct pic { + void (*pic_eoi)(int); + void (*pic_mask)(int); + void (*pic_unmask)(int); +}; + +#ifdef CPU_LOONGSON3 + +void loongson3_intr_init(void); +void *loongson3_intr_establish(int, int, int (*)(void *), void*, + const char *); +void loongson3_intr_disestablish(void *); +void *loongson3_ht_intr_establish(int, int, int (*)(void *), void*, + const char *); +void loongson3_ht_intr_disestablish(void *); + +void loongson3_register_ht_pic(const struct pic *); + +#endif /* CPU_LOONGSON3 */ + +#endif /* _LOCORE */ + +#endif /* _MACHINE_INTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/isa_machdep.h b/lib/libc/include/mips64el-openbsd-none/machine/isa_machdep.h new file mode 100644 index 000000000000..201c218bd3fb --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/isa_machdep.h @@ -0,0 +1,51 @@ +/* $OpenBSD: isa_machdep.h,v 1.2 2010/05/08 21:59:56 miod Exp $ */ + +/* + * Copyright (c) 2007 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice, this permission notice, and the disclaimer below + * appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_ISA_MACHDEP_H_ +#define _MACHINE_ISA_MACHDEP_H_ + +#include + +#define __NO_ISA_INTR_CHECK + +typedef struct mips_isa_chipset *isa_chipset_tag_t; + +struct mips_isa_chipset { + void *ic_v; + + void (*ic_attach_hook)(struct device *, struct device *, + struct isabus_attach_args *); + void *(*ic_intr_establish)(void *, int, int, int, int (*)(void *), + void *, char *); + void (*ic_intr_disestablish)(void *, void *); +}; + +#define isa_attach_hook(p, s, iba) \ + (*(iba)->iba_ic->ic_attach_hook)((p), (s), (iba)) +#define isa_intr_establish(c, i, t, l, f, a, n) \ + (*(c)->ic_intr_establish)((c)->ic_v, (i), (t), (l), (f), (a), (n)) +#define isa_intr_disestablish(c, h) \ + (*(c)->ic_intr_disestablish)((c)->ic_v, (h)) + +void loongson_generic_isa_attach_hook(struct device *, struct device *, + struct isabus_attach_args *); +void loongson_isa_specific_eoi(int); +void loongson_set_isa_imr(uint); + +#endif \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/kcore.h b/lib/libc/include/mips64el-openbsd-none/machine/kcore.h new file mode 100644 index 000000000000..c38fa9f7f6e0 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/kcore.h @@ -0,0 +1,3 @@ +/* $OpenBSD: kcore.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/limits.h b/lib/libc/include/mips64el-openbsd-none/machine/limits.h new file mode 100644 index 000000000000..12007d997ad2 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/limits.h @@ -0,0 +1,3 @@ +/* $OpenBSD: limits.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/loongson2.h b/lib/libc/include/mips64el-openbsd-none/machine/loongson2.h new file mode 100644 index 000000000000..05688a8e0f9c --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/loongson2.h @@ -0,0 +1,3 @@ +/* $OpenBSD: loongson2.h,v 1.1.1.1 2009/08/06 20:51:44 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/loongson3.h b/lib/libc/include/mips64el-openbsd-none/machine/loongson3.h new file mode 100644 index 000000000000..bcbe6ca7018f --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/loongson3.h @@ -0,0 +1,3 @@ +/* $OpenBSD: loongson3.h,v 1.1 2016/11/06 10:20:33 visa Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/memconf.h b/lib/libc/include/mips64el-openbsd-none/machine/memconf.h new file mode 100644 index 000000000000..c7782048ac7e --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/memconf.h @@ -0,0 +1,3 @@ +/* $OpenBSD: memconf.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/mips_opcode.h b/lib/libc/include/mips64el-openbsd-none/machine/mips_opcode.h new file mode 100644 index 000000000000..5b5cbc3494fd --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/mips_opcode.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mips_opcode.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/mplock.h b/lib/libc/include/mips64el-openbsd-none/machine/mplock.h new file mode 100644 index 000000000000..dc963887f82c --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/mplock.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mplock.h,v 1.1 2017/01/19 14:51:02 visa Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/mutex.h b/lib/libc/include/mips64el-openbsd-none/machine/mutex.h new file mode 100644 index 000000000000..8003e465f6b6 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/mutex.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mutex.h,v 1.2 2015/07/08 13:37:31 dlg Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/param.h b/lib/libc/include/mips64el-openbsd-none/machine/param.h new file mode 100644 index 000000000000..cd410bd602a4 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/param.h @@ -0,0 +1,31 @@ +/* $OpenBSD: param.h,v 1.3 2013/03/23 16:12:23 deraadt Exp $ */ + +/* Public Domain */ + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ + +#define MACHINE "loongson" +#define _MACHINE loongson +#define MACHINE_ARCH "mips64el" /* not the canonical endianness */ +#define _MACHINE_ARCH mips64el +#define MACHINE_CPU "mips64" +#define _MACHINE_CPU mips64 +#define MID_MACHINE MID_MIPS64 + +#ifdef _KERNEL + +/* + * The Loongson level 1 cache expects software to prevent virtual + * aliases. Unfortunately, since this cache is physically tagged, + * this would require all virtual address to have the same bits 14 + * and 13 as their physical addresses, which is not something the + * kernel can guarantee unless the page size is at least 16KB. + */ +#define PAGE_SHIFT 14 + +#endif /* _KERNEL */ + +#include + +#endif /* _MACHINE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/pcb.h b/lib/libc/include/mips64el-openbsd-none/machine/pcb.h new file mode 100644 index 000000000000..e48bfc2f316c --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/pcb.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pcb.h,v 1.1.1.1 2009/07/31 09:26:25 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/pci_machdep.h b/lib/libc/include/mips64el-openbsd-none/machine/pci_machdep.h new file mode 100644 index 000000000000..ade283806c11 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/pci_machdep.h @@ -0,0 +1,101 @@ +/* $OpenBSD: pci_machdep.h,v 1.10 2016/05/04 14:30:01 kettenis Exp $ */ + +/* + * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +typedef struct mips_pci_chipset *pci_chipset_tag_t; +typedef u_long pcitag_t; +typedef u_long pci_intr_handle_t; + +struct pci_attach_args; + +/* + * mips-specific PCI structure and type definitions. + * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE. + */ +struct mips_pci_chipset { + void *pc_conf_v; + void (*pc_attach_hook)(struct device *, + struct device *, struct pcibus_attach_args *); + int (*pc_bus_maxdevs)(void *, int); + pcitag_t (*pc_make_tag)(void *, int, int, int); + void (*pc_decompose_tag)(void *, pcitag_t, int *, + int *, int *); + int (*pc_conf_size)(void *, pcitag_t); + pcireg_t (*pc_conf_read)(void *, pcitag_t, int); + void (*pc_conf_write)(void *, pcitag_t, int, pcireg_t); + + void *pc_intr_v; + int (*pc_intr_map)(struct pci_attach_args *, pci_intr_handle_t *); + const char *(*pc_intr_string)(void *, pci_intr_handle_t); + void *(*pc_intr_establish)(void *, pci_intr_handle_t, + int, int (*)(void *), void *, char *); + void (*pc_intr_disestablish)(void *, void *); +}; + +/* + * Functions provided to machine-independent PCI code. + */ +#define pci_attach_hook(p, s, pba) \ + (*(pba)->pba_pc->pc_attach_hook)((p), (s), (pba)) +#define pci_bus_maxdevs(c, b) \ + (*(c)->pc_bus_maxdevs)((c)->pc_conf_v, (b)) +#define pci_make_tag(c, b, d, f) \ + (*(c)->pc_make_tag)((c)->pc_conf_v, (b), (d), (f)) +#define pci_decompose_tag(c, t, bp, dp, fp) \ + (*(c)->pc_decompose_tag)((c)->pc_conf_v, (t), (bp), (dp), (fp)) +#define pci_conf_size(c, t) \ + (*(c)->pc_conf_size)((c)->pc_conf_v, (t)) +#define pci_conf_read(c, t, r) \ + (*(c)->pc_conf_read)((c)->pc_conf_v, (t), (r)) +#define pci_conf_write(c, t, r, v) \ + (*(c)->pc_conf_write)((c)->pc_conf_v, (t), (r), (v)) +#define pci_intr_map(c, ihp) \ + (*(c)->pa_pc->pc_intr_map)((c), (ihp)) +#define pci_intr_map_msi(c, ihp) (-1) +#define pci_intr_map_msix(c, vec, ihp) (-1) +#define pci_intr_string(c, ih) \ + (*(c)->pc_intr_string)((c)->pc_intr_v, (ih)) +#define pci_intr_establish(c, ih, l, h, a, nm) \ + (*(c)->pc_intr_establish)((c)->pc_intr_v, (ih), (l), (h), (a), (nm)) +#define pci_intr_disestablish(c, iv) \ + (*(c)->pc_intr_disestablish)((c)->pc_intr_v, (iv)) +#define pci_probe_device_hook(c, a) (0) + +#define pci_min_powerstate(c, t) (PCI_PMCSR_STATE_D3) +#define pci_set_powerstate_md(c, t, s, p) + +/* PCI view of CPU memory */ +extern paddr_t loongson_dma_base; + +/* + * Functions used during early system configuration. + */ + +extern pcitag_t (*pci_make_tag_early)(int, int, int); +extern pcireg_t (*pci_conf_read_early)(pcitag_t, int); + +#define pci_dev_postattach(a, b) \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/pmap.h b/lib/libc/include/mips64el-openbsd-none/machine/pmap.h new file mode 100644 index 000000000000..eda0b11a3c63 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/pmap.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pmap.h,v 1.1.1.1 2009/07/31 09:26:26 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/pmon.h b/lib/libc/include/mips64el-openbsd-none/machine/pmon.h new file mode 100644 index 000000000000..7729adb4680a --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/pmon.h @@ -0,0 +1,209 @@ +/* $OpenBSD: pmon.h,v 1.5 2017/05/21 13:00:53 visa Exp $ */ + +/* + * Copyright (c) 2009, 2012 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_PMON_H_ +#define _MACHINE_PMON_H_ + +#if defined(_KERNEL) || defined(_STANDALONE) + +/* + * PMON2000 callvec definitions + */ + +/* 32-bit compatible types */ +typedef uint32_t pmon_size_t; +typedef int32_t pmon_ssize_t; +typedef int64_t pmon_off_t; + +int pmon_open(const char *, int, ...); +int pmon_close(int); +int pmon_read(int, void *, pmon_size_t); +pmon_ssize_t pmon_write(int, const void *, pmon_size_t); +pmon_off_t pmon_lseek(int, pmon_off_t, int); +int pmon_printf(const char *, ...); +void pmon_cacheflush(void); +char * pmon_gets(char *); + +#define PMON_MAXLN 256 /* internal gets() size limit */ + +extern int32_t pmon_callvec; + +const char *pmon_getarg(const int); +void pmon_init(int32_t, int32_t, int32_t, int32_t, uint32_t); + +#define PMON_ENVTYPE_ENVP 0 +#define PMON_ENVTYPE_EFI 1 +int pmon_getenvtype(void); + +/* + * The new environment interface is a /salmigondis/ of badly thought-out + * structs put together, pretending to be inspired by EFI but conveniently + * omitting key EFI structs because they are deemed non-applicable to + * MIPS systems. + * Of course, some fields are absolute addresses, while others are relative + * pointers, to add to the confusion. + */ + +struct pmon_env_reset { + void (*cold_boot)(void); /* not filled */ + void (*warm_boot)(void); + void (*boot)(unsigned int); /* not filled */ + void (*poweroff)(void); +}; + +/* all values are offsets relative to the beginning of the struct */ +struct pmon_env_ptr { + uint64_t offs_mem; + uint64_t offs_cpu; + uint64_t offs_sys; + uint64_t offs_irq; + uint64_t offs_iface; + uint64_t offs_special; + uint64_t offs_device; +}; + +struct pmon_env_smbios { + uint16_t version; + uint64_t vga_bios; + struct pmon_env_ptr ptrs; +}; + +struct pmon_env_efi { + uint64_t mps; /* not filled */ + uint64_t acpi; /* not filled */ + uint64_t acpi20; /* not filled */ + struct pmon_env_smbios bios; + uint64_t sal_systab; /* not filled */ + uint64_t bootinfo; /* not filled */ +}; + +struct pmon_env { + struct pmon_env_efi efi; + struct pmon_env_reset reset; +}; + +#define PMON_MEM_MAX 128 +struct pmon_env_mem_entry { + uint32_t node; + uint32_t type; +#define PMON_MEM_SYSTEM_LOW 1 /* physical memory <= 256 MB */ +#define PMON_MEM_SYSTEM_HIGH 2 /* physical memory > 256 MB */ +#define PMON_MEM_RESERVED 3 +#define PMON_MEM_PCI_IO 4 +#define PMON_MEM_PCI_MEM 5 +#define PMON_MEM_CPU_REGISTERS 6 +#define PMON_MEM_VIDEO_ROM 7 +#define PMON_MEM_OTHER_ROM 8 +#define PMON_MEM_ACPI_TABLE 9 + uint64_t address; + uint32_t size; +}; +struct pmon_env_mem { + uint16_t version; /* not filled */ + uint32_t nentries; + uint32_t mem_freq; + struct pmon_env_mem_entry mem_map[PMON_MEM_MAX]; +} __packed; + +struct pmon_env_cpu { + uint16_t version; /* not filled */ + uint32_t prid; /* cop0 PrID */ + uint32_t cputype; +/* 0 and 1 are supposedly intended for 2E and 2F, which do NOT provide this + interface; moreover Linux and PMON disagree on the values and have 2E and + 2F swapped. */ +#define PMON_CPUTYPE_LS3A 2 +#define PMON_CPUTYPE_LS3B 3 +#define PMON_CPUTYPE_LS1A 4 +#define PMON_CPUTYPE_LS1B 5 + uint32_t node; /* total number of NUMA nodes */ + uint16_t coreid; /* boot CPU core id */ + uint16_t reserved_cores; /* mask of reserved cores */ + uint32_t speed; + uint32_t ncpus; +} __packed; + +struct pmon_env_sys { + uint16_t version; /* not filled */ + uint32_t ccnuma_smp; + uint32_t double_channel; +} __packed; + +struct pmon_env_irq { + uint16_t version; /* not filled */ + uint16_t size; /* not filled */ + uint16_t rtr_bus; /* not filled */ + uint16_t rtr_devfn; /* not filled */ + uint32_t vendor; /* not filled */ + uint32_t device; /* not filled */ + uint32_t pic_type; +#define PMON_IRQ_PIC_HT 0 +#define PMON_IRQ_PIC_I8259 1 + uint64_t ht_interrupt_bit; + uint64_t ht_enable; + uint32_t node; + uint64_t pci_memory_space_start; + uint64_t pci_memory_space_end; + uint64_t pci_io_space_start; /* not filled */ + uint64_t pci_io_space_end; /* not filled */ + uint64_t pci_cfg_space; /* not filled */ +} __packed; + +struct pmon_env_iface { + uint16_t version; +#define PMON_IFACE_VERSION 0x0001 + uint16_t size; + uint8_t flag; + char description[64]; /* firmware version */ +} __packed; + +#define PMON_RESOURCE_MAX 128 +struct pmon_env_resource { + uint64_t start; + uint64_t end; + char name[64]; + uint32_t flags; +}; +struct pmon_env_special { + uint16_t version; + char name[64]; + uint32_t type; + struct pmon_env_resource resource[PMON_RESOURCE_MAX]; +}; + +struct pmon_env_device { + char name[64]; /* system description */ + uint32_t nentries; + struct pmon_env_resource resource[PMON_RESOURCE_MAX]; +}; + +const char *pmon_getenv(const char *); + +const struct pmon_env_reset *pmon_get_env_reset(void); +const struct pmon_env_smbios *pmon_get_env_smbios(void); +const struct pmon_env_mem *pmon_get_env_mem(void); +const struct pmon_env_cpu *pmon_get_env_cpu(void); +const struct pmon_env_sys *pmon_get_env_sys(void); +const struct pmon_env_irq *pmon_get_env_irq(void); +const struct pmon_env_iface *pmon_get_env_iface(void); +const struct pmon_env_special *pmon_get_env_special(void); +const struct pmon_env_device *pmon_get_env_device(void); + +#endif /* _KERNEL || _STANDALONE */ + +#endif /* _MACHINE_PMON_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/proc.h b/lib/libc/include/mips64el-openbsd-none/machine/proc.h new file mode 100644 index 000000000000..27b68200cf3e --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/proc.h @@ -0,0 +1,3 @@ +/* $OpenBSD: proc.h,v 1.1.1.1 2009/07/31 09:26:26 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/profile.h b/lib/libc/include/mips64el-openbsd-none/machine/profile.h new file mode 100644 index 000000000000..d258d1147b2d --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/profile.h @@ -0,0 +1,3 @@ +/* $OpenBSD: profile.h,v 1.1.1.1 2009/07/31 09:26:26 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/pte.h b/lib/libc/include/mips64el-openbsd-none/machine/pte.h new file mode 100644 index 000000000000..24c761d66477 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/pte.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pte.h,v 1.1.1.1 2009/07/31 09:26:26 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/ptrace.h b/lib/libc/include/mips64el-openbsd-none/machine/ptrace.h new file mode 100644 index 000000000000..bd8e88672533 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/ptrace.h @@ -0,0 +1,3 @@ +/* $OpenBSD: ptrace.h,v 1.1.1.1 2009/07/31 09:26:26 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/reg.h b/lib/libc/include/mips64el-openbsd-none/machine/reg.h new file mode 100644 index 000000000000..aeecc496fedc --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/reg.h @@ -0,0 +1,3 @@ +/* $OpenBSD: reg.h,v 1.1.1.1 2009/07/31 09:26:26 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/regdef.h b/lib/libc/include/mips64el-openbsd-none/machine/regdef.h new file mode 100644 index 000000000000..03ae54124e76 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/regdef.h @@ -0,0 +1,3 @@ +/* $OpenBSD: regdef.h,v 1.1.1.1 2009/07/31 09:26:26 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/regnum.h b/lib/libc/include/mips64el-openbsd-none/machine/regnum.h new file mode 100644 index 000000000000..e371c1ed202e --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/regnum.h @@ -0,0 +1,3 @@ +/* $OpenBSD: regnum.h,v 1.1.1.1 2009/07/31 09:26:26 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/setjmp.h b/lib/libc/include/mips64el-openbsd-none/machine/setjmp.h new file mode 100644 index 000000000000..c834f0409a59 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/setjmp.h @@ -0,0 +1,3 @@ +/* $OpenBSD: setjmp.h,v 1.1.1.1 2009/07/31 09:26:26 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/signal.h b/lib/libc/include/mips64el-openbsd-none/machine/signal.h new file mode 100644 index 000000000000..7f4d38dee765 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/signal.h @@ -0,0 +1,3 @@ +/* $OpenBSD: signal.h,v 1.1.1.1 2009/07/31 09:26:26 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/spinlock.h b/lib/libc/include/mips64el-openbsd-none/machine/spinlock.h new file mode 100644 index 000000000000..63f58612b808 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/spinlock.h @@ -0,0 +1,3 @@ +/* $OpenBSD: spinlock.h,v 1.1.1.1 2009/07/31 09:26:26 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/sysarch.h b/lib/libc/include/mips64el-openbsd-none/machine/sysarch.h new file mode 100644 index 000000000000..6dac08a77bf5 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/sysarch.h @@ -0,0 +1,3 @@ +/* $OpenBSD: sysarch.h,v 1.1.1.1 2009/11/22 18:12:44 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/timetc.h b/lib/libc/include/mips64el-openbsd-none/machine/timetc.h new file mode 100644 index 000000000000..d3d291c815ca --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/timetc.h @@ -0,0 +1,23 @@ +/* $OpenBSD: timetc.h,v 1.2 2020/07/18 08:37:43 visa Exp $ */ +/* + * Copyright (c) 2020 Paul Irofti + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TIMETC_H_ +#define _MACHINE_TIMETC_H_ + +#include + +#endif /* _MACHINE_TIMETC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/trap.h b/lib/libc/include/mips64el-openbsd-none/machine/trap.h new file mode 100644 index 000000000000..c700eedba183 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/trap.h @@ -0,0 +1,3 @@ +/* $OpenBSD: trap.h,v 1.1.1.1 2009/07/31 09:26:26 miod Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/mips64el-openbsd-none/machine/vmparam.h b/lib/libc/include/mips64el-openbsd-none/machine/vmparam.h new file mode 100644 index 000000000000..c6c4b75cfe65 --- /dev/null +++ b/lib/libc/include/mips64el-openbsd-none/machine/vmparam.h @@ -0,0 +1,11 @@ +/* $OpenBSD: vmparam.h,v 1.5 2017/05/21 13:00:53 visa Exp $ */ +/* public domain */ +#ifndef _MACHINE_VMPARAM_H_ +#define _MACHINE_VMPARAM_H_ + +#define VM_PHYSSEG_MAX 8 /* Max number of physical memory segments */ +#define VM_PHYSSEG_STRAT VM_PSTRAT_BIGFIRST + +#include + +#endif /* _MACHINE_VMPARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-freebsd-eabihf/machine/sigframe.h b/lib/libc/include/powerpc-freebsd-eabihf/machine/sigframe.h deleted file mode 100644 index 72447f3e6978..000000000000 --- a/lib/libc/include/powerpc-freebsd-eabihf/machine/sigframe.h +++ /dev/null @@ -1,39 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1999 Marcel Moolenaar - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _MACHINE_SIGFRAME_H_ -#define _MACHINE_SIGFRAME_H_ 1 - -struct sigframe { - ucontext_t sf_uc; - siginfo_t sf_si; -}; - -#endif /* _MACHINE_SIGFRAME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/frame.h b/lib/libc/include/powerpc-openbsd-eabihf/frame.h new file mode 100644 index 000000000000..9edae57f9556 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/frame.h @@ -0,0 +1,3 @@ +/* $OpenBSD: frame.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/_float.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/_float.h new file mode 100644 index 000000000000..1bf34fd14e39 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/_float.h @@ -0,0 +1,3 @@ +/* $OpenBSD: _float.h,v 1.1 2012/06/26 16:12:44 deraadt Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/_types.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/_types.h new file mode 100644 index 000000000000..e896392602ef --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/_types.h @@ -0,0 +1,4 @@ +/* $OpenBSD: _types.h,v 1.1 2006/01/06 18:50:09 millert Exp $ */ + +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/apmvar.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/apmvar.h new file mode 100644 index 000000000000..4aa7952d46bc --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/apmvar.h @@ -0,0 +1,122 @@ +/* $OpenBSD: apmvar.h,v 1.10 2019/01/22 02:36:30 phessler Exp $ */ + +/* + * Copyright (c) 2001 Alexander Guy + * Copyright (c) 1995 John T. Kohl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _MACHINE_APMVAR_H_ +#define _MACHINE_APMVAR_H_ + +#include + +/* Advanced Power Management (v1.0 and v1.1 specification) + * functions/defines/etc. + */ + +/* These definitions make up the heart of the user-land interface + * to the APM devices. + */ + +#define APM_AC_OFF 0x00 +#define APM_AC_ON 0x01 +#define APM_AC_BACKUP 0x02 +#define APM_AC_UNKNOWN 0xff +#define APM_BATT_HIGH 0x00 +#define APM_BATT_LOW 0x01 +#define APM_BATT_CRITICAL 0x02 +#define APM_BATT_CHARGING 0x03 +#define APM_BATT_UNKNOWN 0xff +#define APM_BATT_LIFE_UNKNOWN 0xff + +#define APM_NOEVENT 0x0000 +#define APM_STANDBY_REQ 0x0001 +#define APM_SUSPEND_REQ 0x0002 +#define APM_NORMAL_RESUME 0x0003 +#define APM_CRIT_RESUME 0x0004 /* suspend/resume happened + without us */ +#define APM_BATTERY_LOW 0x0005 +#define APM_POWER_CHANGE 0x0006 +#define APM_UPDATE_TIME 0x0007 +#define APM_CRIT_SUSPEND_REQ 0x0008 +#define APM_USER_STANDBY_REQ 0x0009 +#define APM_USER_SUSPEND_REQ 0x000A +#define APM_SYS_STANDBY_RESUME 0x000B +#define APM_CAPABILITY_CHANGE 0x000C /* apm v1.2 */ +#define APM_USER_HIBERNATE_REQ 0x000D +#define APM_EVENT_MASK 0xffff + +#define APM_EVENT_COMPOSE(t,i) ((((i) & 0x7fff) << 16)|((t) & APM_EVENT_MASK)) +#define APM_EVENT_TYPE(e) ((e) & APM_EVENT_MASK) +#define APM_EVENT_INDEX(e) ((e) >> 16) + +/* + * LP (Laptop Package) + * + * Copyright (C) 1994 by HOSOKAWA Tatsumi + * + * This software may be used, modified, copied, and distributed, in + * both source and binary form provided that the above copyright and + * these terms are retained. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with its + * use. + * + * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) + */ + +#define APM_BATTERY_ABSENT 4 + +struct apm_power_info { + u_char battery_state; + u_char ac_state; + u_char battery_life; + u_char spare1; + u_int minutes_left; /* estimate */ + u_int spare2[6]; +}; + +struct apm_ctl { + u_int dev; + u_int mode; +}; + +#define APM_IOC_REJECT _IOW('A', 0, struct apm_event_info) /* reject request # */ +#define APM_IOC_STANDBY _IO('A', 1) /* put system into standby */ +#define APM_IOC_SUSPEND _IO('A', 2) /* put system into suspend */ +#define APM_IOC_GETPOWER _IOR('A', 3, struct apm_power_info) /* fetch battery state */ +#define APM_IOC_DEV_CTL _IOW('A', 5, struct apm_ctl) /* put device into mode */ +#define APM_IOC_PRN_CTL _IOW('A', 6, int ) /* driver power status msg */ +#define APM_PRINT_ON 0 /* driver power status displayed */ +#define APM_PRINT_OFF 1 /* driver power status not displayed */ +#define APM_PRINT_PCT 2 /* driver power status only displayed + if the percentage changes */ +#define APM_IOC_STANDBY_REQ _IO('A', 7) /* request standby */ +#define APM_IOC_SUSPEND_REQ _IO('A', 8) /* request suspend */ +#define APM_IOC_HIBERNATE _IO('A', 9) /* put system into hibernate */ + +#endif /* _MACHINE_APMVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/asm.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/asm.h new file mode 100644 index 000000000000..ea7bd91fc3ef --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/asm.h @@ -0,0 +1,3 @@ +/* $OpenBSD: asm.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/atomic.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/atomic.h new file mode 100644 index 000000000000..bd432ef8ec29 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/atomic.h @@ -0,0 +1,10 @@ +/* $OpenBSD: atomic.h,v 1.3 2011/03/23 16:54:36 pirofti Exp $ */ + +/* Public Domain */ + +#ifndef _MACHINE_ATOMIC_H_ +#define _MACHINE_ATOMIC_H_ + +#include + +#endif /* _MACHINE_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/autoconf.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/autoconf.h new file mode 100644 index 000000000000..3ec5c80d9edb --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/autoconf.h @@ -0,0 +1,72 @@ +/* $OpenBSD: autoconf.h,v 1.13 2024/05/22 05:51:49 jsg Exp $ */ + +/* + * Copyright (c) 1997 Per Fogelstrom + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/* + * Machine-dependent structures of autoconfiguration + */ + +#ifndef _MACHINE_AUTOCONF_H_ +#define _MACHINE_AUTOCONF_H_ + +#include + +struct confargs { + char *ca_name; + bus_space_tag_t ca_iot; + bus_dma_tag_t ca_dmat; + u_int32_t ca_node; + int ca_nreg; + u_int32_t *ca_reg; + int ca_nintr; + int32_t *ca_intr; + u_int ca_baseaddr; + +}; + +int badaddr(void *, u_int32_t); + +typedef int (time_read_t)(time_t *sec); +typedef int (time_write_t)(time_t sec); + +extern time_read_t *time_read; +extern time_write_t *time_write; + +typedef int mac_intr_handle_t; +typedef void *(intr_establish_t)(void *, mac_intr_handle_t, + int, int, int (*func)(void *), void *, const char *); +typedef void (intr_disestablish_t)(void *, void *); +struct cpu_info; +typedef void (intr_send_ipi_t)(struct cpu_info *, int); + +intr_establish_t mac_intr_establish; +intr_disestablish_t mac_intr_disestablish; +extern intr_establish_t *intr_establish_func; +extern intr_disestablish_t *intr_disestablish_func; +extern intr_send_ipi_t *intr_send_ipi_func; + + +#endif /* _MACHINE_AUTOCONF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/bus.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/bus.h new file mode 100644 index 000000000000..0787b6818331 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/bus.h @@ -0,0 +1,643 @@ +/* $OpenBSD: bus.h,v 1.27 2024/05/22 05:51:49 jsg Exp $ */ + +/* + * Copyright (c) 1997 Per Fogelstrom. All rights reserved. + * Copyright (c) 1996 Niklas Hallqvist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BUS_H_ +#define _MACHINE_BUS_H_ + +#include + +#ifdef __STDC__ +#define CAT(a,b) a##b +#define CAT3(a,b,c) a##b##c +#else +#define CAT(a,b) a/**/b +#define CAT3(a,b,c) a/**/b/**/c +#endif + +/* + * Bus access types. + */ +typedef u_long bus_addr_t; +typedef u_long bus_size_t; +typedef u_long bus_space_handle_t; +typedef struct ppc_bus_space *bus_space_tag_t; + +struct ppc_bus_space { + u_int32_t bus_base; + u_int32_t bus_size; + u_int8_t bus_io; /* IO or memory */ +}; +#define POWERPC_BUS_TAG_BASE(x) ((x)->bus_base) + +/* + * Access methods for bus resources + */ +int bus_space_map(bus_space_tag_t t, bus_addr_t addr, + bus_size_t size, int flags, bus_space_handle_t *bshp); +void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t size); +int bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp); +int bus_space_alloc(bus_space_tag_t tag, bus_addr_t rstart, + bus_addr_t rend, bus_size_t size, bus_size_t alignment, + bus_size_t boundary, int flags, bus_addr_t *addrp, + bus_space_handle_t *handlep); +void bus_space_free(bus_space_tag_t tag, bus_space_handle_t handle, + bus_size_t size); +paddr_t bus_space_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int); + +#define BUS_SPACE_MAP_CACHEABLE 0x01 +#define BUS_SPACE_MAP_LINEAR 0x02 +#define BUS_SPACE_MAP_PREFETCHABLE 0x04 + +/* + * void *bus_space_vaddr(bus_space_tag_t, bus_space_handle_t); + * + * Get the kernel virtual address for the mapped bus space. + * Only allowed for regions mapped with BUS_SPACE_MAP_LINEAR. + */ +#define bus_space_vaddr(t, h) ((void *)(h)) + +#define bus_space_read(n,m) \ +static __inline CAT3(u_int,m,_t) \ +CAT(bus_space_read_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba) \ +{ \ + return CAT3(in,m,rb)((volatile CAT3(u_int,m,_t) *)(bsh + (ba))); \ +} + +bus_space_read(1,8) +bus_space_read(2,16) +bus_space_read(4,32) + +#define bus_space_read_8 !!! bus_space_read_8 unimplemented !!! + +#define bus_space_write(n,m) \ +static __inline void \ +CAT(bus_space_write_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(u_int,m,_t) x) \ +{ \ + CAT3(out,m,rb)((volatile CAT3(u_int,m,_t) *)(bsh + (ba)), x); \ +} + +bus_space_write(1,8) +bus_space_write(2,16) +bus_space_write(4,32) + +#define bus_space_write_8 !!! bus_space_write_8 unimplemented !!! + +#define bus_space_read_raw(n,m) \ +static __inline CAT3(u_int,m,_t) \ +CAT(bus_space_read_raw_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba) \ +{ \ + return CAT(in,m)((volatile CAT3(u_int,m,_t) *)(bsh + (ba))); \ +} + +bus_space_read_raw(1,8) +bus_space_read_raw(2,16) +bus_space_read_raw(4,32) + +#define bus_space_read_raw_8 !!! bus_space_read_raw_8 unimplemented !!! + +#define bus_space_write_raw(n,m) \ +static __inline void \ +CAT(bus_space_write_raw_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(u_int,m,_t) x) \ +{ \ + CAT(out,m)((volatile CAT3(u_int,m,_t) *)(bsh + (ba)), x); \ +} + +bus_space_write_raw(1,8) +bus_space_write_raw(2,16) +bus_space_write_raw(4,32) + +#define bus_space_write_raw_8 !!! bus_space_write_raw_8 unimplemented !!! + +#define bus_space_read_multi(n, m) \ +static __inline void \ +CAT(bus_space_read_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t ba, CAT3(u_int,m,_t) *buf, bus_size_t cnt) \ +{ \ + while (cnt--) \ + *buf++ = CAT(bus_space_read_,n)(bst, bsh, ba); \ +} + +bus_space_read_multi(1,8) +bus_space_read_multi(2,16) +bus_space_read_multi(4,32) + +#define bus_space_read_multi_8 !!! bus_space_read_multi_8 not implemented !!! + + +#define bus_space_write_multi_8 !!! bus_space_write_multi_8 not implemented !!! + +#define bus_space_write_multi(n, m) \ +static __inline void \ +CAT(bus_space_write_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t ba, const CAT3(u_int,m,_t) *buf, bus_size_t cnt) \ +{ \ + while (cnt--) \ + CAT(bus_space_write_,n)(bst, bsh, ba, *buf++); \ +} + +bus_space_write_multi(1,8) +bus_space_write_multi(2,16) +bus_space_write_multi(4,32) + +#define bus_space_write_multi_8 !!! bus_space_write_multi_8 not implemented !!! + +/* + * void bus_space_read_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t *addr, size_t count); + * + * Read `count' 1, 2, 4, or 8 byte quantities from bus space + * described by tag/handle and starting at `offset' and copy into + * buffer provided. + */ +#define __BA(t, h, o) ((void *)((h) + (o))) + +static __inline void +bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int8_t *addr, size_t count) +{ + volatile u_int8_t *s = __BA(tag, bsh, offset); + + while (count--) + *addr++ = *s++; + __asm volatile("eieio; sync"); +} + +static __inline void +bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int16_t *addr, size_t count) +{ + volatile u_int16_t *s = __BA(tag, bsh, offset); + + while (count--) + __asm volatile("lhbrx %0, 0, %1" : + "=r"(*addr++) : "r"(s++)); + __asm volatile("eieio; sync"); +} + +static __inline void +bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int32_t *addr, size_t count) +{ + volatile u_int32_t *s = __BA(tag, bsh, offset); + + while (count--) + __asm volatile("lwbrx %0, 0, %1" : + "=r"(*addr++) : "r"(s++)); + __asm volatile("eieio; sync"); +} + +#if 0 /* Cause a link error for bus_space_read_region_8 */ +#define bus_space_read_region_8 !!! unimplemented !!! +#endif + + +/* + * void bus_space_write_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_intN_t *addr, size_t count); + * + * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided + * to bus space described by tag/handle starting at `offset'. + */ + +static __inline void +bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, const u_int8_t *addr, size_t count) +{ + volatile u_int8_t *d = __BA(tag, bsh, offset); + + while (count--) + *d++ = *addr++; + __asm volatile("eieio; sync"); +} + +static __inline void +bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, const u_int16_t *addr, size_t count) +{ + volatile u_int16_t *d = __BA(tag, bsh, offset); + + while (count--) + __asm volatile("sthbrx %0, 0, %1" :: + "r"(*addr++), "r"(d++)); + __asm volatile("eieio; sync"); +} + +static __inline void +bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, const u_int32_t *addr, size_t count) +{ + volatile u_int32_t *d = __BA(tag, bsh, offset); + + while (count--) + __asm volatile("stwbrx %0, 0, %1" :: + "r"(*addr++), "r"(d++)); + __asm volatile("eieio; sync"); +} + +#if 0 +#define bus_space_write_region_8 !!! bus_space_write_region_8 unimplemented !!! +#endif + +/* + * void bus_space_read_raw_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t *addr, size_t count); + * + * Read `count' bytes from bus space described by tag/handle and starting + * at `offset' and copy into buffer provided w/o bus-host byte swapping. + */ + +static __inline void +bus_space_read_raw_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int8_t *addr, size_t count) +{ + volatile u_int16_t *s = __BA(tag, bsh, offset); + u_int16_t *laddr = (void *)addr; + + count = count >> 1; + + while (count--) + *laddr++ = *s++; + __asm volatile("eieio; sync"); +} + +static __inline void +bus_space_read_raw_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int8_t *addr, size_t count) +{ + volatile u_int32_t *s = __BA(tag, bsh, offset); + u_int32_t *laddr = (void *)addr; + + count = count >> 2; + + while (count--) + *laddr++ = *s++; + __asm volatile("eieio; sync"); +} + +#if 0 /* Cause a link error for bus_space_read_raw_region_8 */ +#define bus_space_read_raw_region_8 \ + !!! bus_space_read_raw_region_8 unimplemented !!! +#endif + + +/* + * void bus_space_write_raw_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_intN_t *addr, size_t count); + * + * Write `count' bytes from the buffer provided to bus space described + * by tag/handle starting at `offset' w/o host-bus byte swapping. + */ + +static __inline void +bus_space_write_raw_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, const u_int8_t *addr, size_t count) +{ + volatile u_int16_t *d = __BA(tag, bsh, offset); + const u_int16_t *laddr = (void *)addr; + + count = count >> 1; + + while (count--) + *d++ = *laddr++; + __asm volatile("eieio; sync"); +} + +static __inline void +bus_space_write_raw_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, const u_int8_t *addr, size_t count) +{ + volatile u_int32_t *d = __BA(tag, bsh, offset); + const u_int32_t *laddr = (void *)addr; + + count = count >> 2; + + while (count--) + *d++ = *laddr++; + __asm volatile("eieio; sync"); +} + +#if 0 +#define bus_space_write_raw_region_8 \ + !!! bus_space_write_raw_region_8 unimplemented !!! +#endif + +/* + * void bus_space_set_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, u_intN_t val, + * size_t count); + * + * Write the 1, 2, 4, or 8 byte value `val' to bus space described + * by tag/handle/offset `count' times. + */ +static __inline void bus_space_set_multi_1(bus_space_tag_t, + bus_space_handle_t, bus_size_t, u_int8_t, size_t); +static __inline void bus_space_set_multi_2(bus_space_tag_t, + bus_space_handle_t, bus_size_t, u_int16_t, size_t); +static __inline void bus_space_set_multi_4(bus_space_tag_t, + bus_space_handle_t, bus_size_t, u_int32_t, size_t); + +static __inline void +bus_space_set_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int8_t val, size_t count) +{ + volatile u_int8_t *d = __BA(tag, bsh, offset); + + while (count--) + *d = val; + __asm__ volatile("eieio; sync"); +} + +static __inline void +bus_space_set_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int16_t val, size_t count) +{ + volatile u_int16_t *d = __BA(tag, bsh, offset); + + while (count--) + __asm__ volatile("sthbrx %0, 0, %1" :: + "r"(val), "r"(d)); + __asm__ volatile("eieio; sync"); +} + +static __inline void +bus_space_set_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int32_t val, size_t count) +{ + volatile u_int32_t *d = __BA(tag, bsh, offset); + + while (count--) + __asm__ volatile("stwbrx %0, 0, %1" :: + "r"(val), "r"(d)); + __asm__ volatile("eieio; sync"); +} + +#define bus_space_set_multi_8 !!! bus_space_set_multi_8 unimplemented !!! + +/* These are OpenBSD extensions to the general NetBSD bus interface. */ +void +bus_space_read_raw_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_addr_t ba, u_int8_t *dst, bus_size_t size); +void +bus_space_read_raw_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_addr_t ba, u_int8_t *dst, bus_size_t size); +#define bus_space_read_raw_multi_8 \ + !!! bus_space_read_raw_multi_8 not implemented !!! + +void +bus_space_write_raw_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_addr_t ba, const u_int8_t *src, bus_size_t size); +void +bus_space_write_raw_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_addr_t ba, const u_int8_t *src, bus_size_t size); +#define bus_space_write_raw_multi_8 \ + !!! bus_space_write_raw_multi_8 not implemented !!! + +void +bus_space_set_region_1(bus_space_tag_t bst, bus_space_handle_t h, bus_size_t o, + u_int8_t val, bus_size_t c); +void +bus_space_set_region_2(bus_space_tag_t bst, bus_space_handle_t h, bus_size_t o, + u_int16_t val, bus_size_t c); +void +bus_space_set_region_4(bus_space_tag_t bst, bus_space_handle_t h, bus_size_t o, + u_int32_t val, bus_size_t c); +#define bus_space_set_region_8 \ + !!! bus_space_set_region_8 not implemented !!! + +void +bus_space_copy_1(void *v, bus_space_handle_t h1, bus_space_handle_t h2, + bus_size_t o1, bus_size_t o2, bus_size_t c); +void +bus_space_copy_2(void *v, bus_space_handle_t h1, bus_space_handle_t h2, + bus_size_t o1, bus_size_t o2, bus_size_t c); +void +bus_space_copy_4(void *v, bus_space_handle_t h1, bus_space_handle_t h2, + bus_size_t o1, bus_size_t o2, bus_size_t c); +#define bus_space_copy_8 \ + !!! bus_space_copy_8 not implemented !!! + +/* + * Bus read/write barrier methods. + * + * void bus_space_barrier(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * bus_size_t len, int flags); + * + * Note: powerpc does not currently implement barriers, but we must + * provide the flags to MI code. + * the processor does have eieio which is effectively the barrier + * operator, however due to how memory is mapped this should? not + * be required. + */ +#define bus_space_barrier(t, h, o, l, f) \ + ((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f))) +#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ +#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ + +#define BUS_DMA_WAITOK 0x0000 /* safe to sleep (pseudo-flag) */ +#define BUS_DMA_NOWAIT 0x0001 /* not safe to sleep */ +#define BUS_DMA_ALLOCNOW 0x0002 /* perform resource allocation now */ +#define BUS_DMA_COHERENT 0x0008 /* hint: map memory DMA coherent */ +#define BUS_DMA_BUS1 0x0010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x0020 +#define BUS_DMA_BUS3 0x0040 +#define BUS_DMA_BUS4 0x0080 +#define BUS_DMA_READ 0x0100 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x0200 /* mapping is memory -> device only */ +#define BUS_DMA_STREAMING 0x0400 /* hint: sequential, unidirectional */ +#define BUS_DMA_ZERO 0x0800 /* zero memory in dmamem_alloc */ +#define BUS_DMA_NOCACHE 0x1000 /* map memory uncached */ +#define BUS_DMA_64BIT 0x2000 /* device handles 64bit dva */ + + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct proc; +struct uio; + +#define BUS_DMASYNC_POSTREAD 0x01 +#define BUS_DMASYNC_POSTWRITE 0x02 +#define BUS_DMASYNC_PREREAD 0x04 +#define BUS_DMASYNC_PREWRITE 0x08 + +typedef struct powerpc_bus_dma_tag *bus_dma_tag_t; +typedef struct powerpc_bus_dmamap *bus_dmamap_t; + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +struct powerpc_bus_dma_segment { + bus_addr_t ds_addr; /* DMA address */ + bus_size_t ds_len; /* length of transfer */ +}; +typedef struct powerpc_bus_dma_segment bus_dma_segment_t; + +/* + * bus_dma_tag_t + * + * A machine-dependent opaque type describing the implementation of + * DMA for a given bus. + */ + +struct powerpc_bus_dma_tag { + void *_cookie; /* cookie used in the guts */ + + /* + * DMA mapping methods. + */ + int (*_dmamap_create)(bus_dma_tag_t , bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); + void (*_dmamap_destroy)(bus_dma_tag_t , bus_dmamap_t); + int (*_dmamap_load)(bus_dma_tag_t , bus_dmamap_t, void *, + bus_size_t, struct proc *, int); + int (*_dmamap_load_mbuf)(bus_dma_tag_t , bus_dmamap_t, + struct mbuf *, int); + int (*_dmamap_load_uio)(bus_dma_tag_t , bus_dmamap_t, + struct uio *, int); + int (*_dmamap_load_raw)(bus_dma_tag_t , bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); + void (*_dmamap_unload)(bus_dma_tag_t , bus_dmamap_t); + void (*_dmamap_sync)(bus_dma_tag_t , bus_dmamap_t, + bus_addr_t, bus_size_t, int); + + /* + * DMA memory utility functions. + */ + int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); + int (*_dmamem_alloc_range)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int, + bus_addr_t, bus_addr_t); + void (*_dmamem_free)(bus_dma_tag_t, bus_dma_segment_t *, int); + int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); + void (*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t); + paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, + int, off_t, int, int); +}; + +#define bus_dmamap_create(t, s, n, m, b, f, p) \ + (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) +#define bus_dmamap_destroy(t, p) \ + (*(t)->_dmamap_destroy)((t), (p)) +#define bus_dmamap_load(t, m, b, s, p, f) \ + (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) +#define bus_dmamap_load_mbuf(t, m, b, f) \ + (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) +#define bus_dmamap_load_uio(t, m, u, f) \ + (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) +#define bus_dmamap_load_raw(t, m, sg, n, s, f) \ + (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) +#define bus_dmamap_unload(t, p) \ + (*(t)->_dmamap_unload)((t), (p)) +#define bus_dmamap_sync(t, p, a, l, o) \ + (void)((t)->_dmamap_sync ? \ + (*(t)->_dmamap_sync)((t), (p), (a), (l), (o)) : (void)0) + +#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ + (*(t)->_dmamem_alloc)((t)->_cookie, (s), (a), (b), (sg), (n), (r), (f)) +#define bus_dmamem_alloc_range(t, s, a, b, sg, n, r, f, l, h) \ + (*(t)->_dmamem_alloc_range)((t), (s), (a), (b), (sg), \ + (n), (r), (f), (l), (h)) +#define bus_dmamem_free(t, sg, n) \ + (*(t)->_dmamem_free)((t)->_cookie, (sg), (n)) +#define bus_dmamem_map(t, sg, n, s, k, f) \ + (*(t)->_dmamem_map)((t)->_cookie, (sg), (n), (s), (k), (f)) +#define bus_dmamem_unmap(t, k, s) \ + (*(t)->_dmamem_unmap)((t)->_cookie, (k), (s)) +#define bus_dmamem_mmap(t, sg, n, o, p, f) \ + (*(t)->_dmamem_mmap)((t)->_cookie, (sg), (n), (o), (p), (f)) + +int _dmamap_create(bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); +void _dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); +int _dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); +int _dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *, int); +int _dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, struct uio *, int); +int _dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); +void _dmamap_unload(bus_dma_tag_t, bus_dmamap_t); +void _dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, bus_size_t, + int); + +int _dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); +int _dmamem_alloc_range( bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int, + bus_addr_t, bus_addr_t); +void _dmamem_free(bus_dma_tag_t, bus_dma_segment_t *, int); +int _dmamem_map(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); +void _dmamem_unmap(bus_dma_tag_t, caddr_t, size_t); +paddr_t _dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, int, int); + +/* + * bus_dmamap_t + * + * Describes a DMA mapping. + */ +struct powerpc_bus_dmamap { + /* + * PRIVATE MEMBERS: not for use by machine-independent code. + */ + bus_size_t _dm_size; /* largest DMA transfer mappable */ + int _dm_segcnt; /* number of segs this map can map */ + bus_size_t _dm_maxsegsz; /* largest possible segment */ + bus_size_t _dm_boundary; /* don't cross this */ + int _dm_flags; /* misc. flags */ + + void *_dm_cookie; /* cookie for bus-specific functions */ + + /* + * PUBLIC MEMBERS: these are used by machine-independent code. + */ + bus_size_t dm_mapsize; /* size of the mapping */ + int dm_nsegs; /* # valid segments in mapping */ + bus_dma_segment_t dm_segs[1]; /* segments; variable length */ +}; + +#endif /* _MACHINE_BUS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/cdefs.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/cdefs.h new file mode 100644 index 000000000000..4e15edb0a4fd --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/cdefs.h @@ -0,0 +1,3 @@ +/* $OpenBSD: cdefs.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/conf.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/conf.h new file mode 100644 index 000000000000..370b2c67c56d --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/conf.h @@ -0,0 +1,56 @@ +/* $OpenBSD: conf.h,v 1.15 2022/06/28 14:43:50 visa Exp $ */ +/* $NetBSD: conf.h,v 1.2 1996/05/05 19:28:34 christos Exp $ */ + +/* + * Copyright (c) 1996 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#define mmread mmrw +#define mmwrite mmrw +cdev_decl(mm); + +/* open, close, write, ioctl, kqueue */ +#define cdev_apm_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev, 0, 0, dev_init(c,n,kqfilter) } + +cdev_decl(apm); +cdev_decl(zs); + +/* open, close, ioctl */ +#define cdev_openprom_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) nullop, 0, \ + (dev_type_mmap((*))) enodev } + +cdev_decl(openprom); \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/cpu.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/cpu.h new file mode 100644 index 000000000000..9b938b2a8d56 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/cpu.h @@ -0,0 +1,76 @@ +/* $OpenBSD: cpu.h,v 1.15 2022/10/21 22:42:36 gkoehler Exp $ */ +/* $NetBSD: cpu.h,v 1.1 1996/09/30 16:34:21 ws Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _MACHINE_CPU_H_ +#define _MACHINE_CPU_H_ + +/* + * CTL_MACHDEP definitions. + */ +#define CPU_ALLOWAPERTURE 1 /* allow mmap of /dev/xf86 */ +#define CPU_ALTIVEC 2 /* altivec is present */ +#define CPU_LIDACTION 3 /* action caused by lid close */ +#define CPU_PWRACTION 4 /* action caused by power button */ +#define CPU_MAXID 5 /* number of valid machdep ids */ + +#define CTL_MACHDEP_NAMES { \ + { 0, 0 }, \ + { "allowaperture", CTLTYPE_INT }, \ + { "altivec", CTLTYPE_INT }, \ + { "lidaction", CTLTYPE_INT }, \ + { "pwraction", CTLTYPE_INT }, \ +} + +#ifdef _KERNEL + +#include + +/* Frequency scaling */ +#define FREQ_FULL 0 +#define FREQ_HALF 1 +#define FREQ_QUARTER 2 /* Supported only on IBM 970MP */ + +extern u_int32_t ppc_curfreq; +extern u_int32_t ppc_maxfreq; +extern int ppc_altivec; + +extern void (*ppc64_slew_voltage)(u_int); + +extern u_int32_t ticks_per_sec; +extern u_int32_t ns_per_tick; + +extern int lid_action; +extern int pwr_action; + +#endif /* _KERNEL */ +#endif /* _MACHINE_CPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/db_machdep.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/db_machdep.h new file mode 100644 index 000000000000..525dade241bf --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/db_machdep.h @@ -0,0 +1,3 @@ +/* $OpenBSD: db_machdep.h,v 1.7 2016/03/05 17:41:55 mpi Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/disklabel.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/disklabel.h new file mode 100644 index 000000000000..aca83dc5eb6d --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/disklabel.h @@ -0,0 +1,90 @@ +/* $OpenBSD: disklabel.h,v 1.16 2015/09/30 15:13:54 krw Exp $ */ + +/* + * Copyright (c) 1994 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_DISKLABEL_H_ +#define _MACHINE_DISKLABEL_H_ + +#define LABELSECTOR 1 /* sector containing label */ +#define LABELOFFSET 0 /* offset of label in sector */ +#define MAXPARTITIONS 16 /* number of partitions */ + +/* HFS/DPME */ + +/* partition map structure from Inside Macintosh: Devices, SCSI Manager + * pp. 13-14. The partition map always begins on physical block 1. + * + * With the exception of block 0, all blocks on the disk must belong to + * exactly one partition. The partition map itself belongs to a partition + * of type `APPLE_PARTITION_MAP', and is not limited in size by anything + * other than available disk space. The partition map is not necessarily + * the first partition listed. + */ +struct part_map_entry { +#define PART_ENTRY_MAGIC 0x504d + u_int16_t pmSig; /* partition signature */ + u_int16_t pmSigPad; /* (reserved) */ + u_int32_t pmMapBlkCnt; /* number of blocks in partition map */ + u_int32_t pmPyPartStart; /* first physical block of partition */ + u_int32_t pmPartBlkCnt; /* number of blocks in partition */ + char pmPartName[32]; /* partition name */ + char pmPartType[32]; /* partition type */ + u_int32_t pmLgDataStart; /* first logical block of data area */ + u_int32_t pmDataCnt; /* number of blocks in data area */ + u_int32_t pmPartStatus; /* partition status information */ + u_int32_t pmLgBootStart; /* first logical block of boot code */ + u_int32_t pmBootSize; /* size of boot code, in bytes */ + u_int32_t pmBootLoad; /* boot code load address */ + u_int32_t pmBootLoad2; /* (reserved) */ + u_int32_t pmBootEntry; /* boot code entry point */ + u_int32_t pmBootEntry2; /* (reserved) */ + u_int32_t pmBootCksum; /* boot code checksum */ + char pmProcessor[16]; /* processor type (e.g. "68020") */ + u_int8_t pmBootArgs[128]; /* A/UX boot arguments */ + /* we do not index the disk image as an array, + * leave out the on disk padding + */ +#if 0 + u_int8_t pad[248]; /* pad to end of block */ +#endif +}; + +#define PART_TYPE_DRIVER "APPLE_DRIVER" +#define PART_TYPE_DRIVER43 "APPLE_DRIVER43" +#define PART_TYPE_DRIVERATA "APPLE_DRIVER_ATA" +#define PART_TYPE_DRIVERIOKIT "APPLE_DRIVER_IOKIT" +#define PART_TYPE_FWDRIVER "APPLE_FWDRIVER" +#define PART_TYPE_FWB_COMPONENT "FWB DRIVER COMPONENTS" +#define PART_TYPE_FREE "APPLE_FREE" +#define PART_TYPE_MAC "APPLE_HFS" +#define PART_TYPE_OPENBSD "OPENBSD" + +#endif /* _MACHINE_DISKLABEL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/elf.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/elf.h new file mode 100644 index 000000000000..ed920f5d1ecf --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/elf.h @@ -0,0 +1,3 @@ +/* $OpenBSD: elf.h,v 1.1 2024/07/14 19:33:59 miod Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/endian.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/endian.h new file mode 100644 index 000000000000..4bc2fa0df57d --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/endian.h @@ -0,0 +1,3 @@ +/* $OpenBSD: endian.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/exec.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/exec.h new file mode 100644 index 000000000000..b283c6dd5f40 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/exec.h @@ -0,0 +1,3 @@ +/* $OpenBSD: exec.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/fenv.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/fenv.h new file mode 100644 index 000000000000..63244974f96c --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/fenv.h @@ -0,0 +1,3 @@ +/* $OpenBSD: fenv.h,v 1.2 2013/06/01 21:20:54 jasper Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/fpu.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/fpu.h new file mode 100644 index 000000000000..b3c92c2976a7 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/fpu.h @@ -0,0 +1,3 @@ +/* $OpenBSD: fpu.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/frame.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/frame.h new file mode 100644 index 000000000000..9edae57f9556 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/frame.h @@ -0,0 +1,3 @@ +/* $OpenBSD: frame.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/ieee.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/ieee.h new file mode 100644 index 000000000000..46e05aeea462 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/ieee.h @@ -0,0 +1,3 @@ +/* $OpenBSD: ieee.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/ieeefp.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/ieeefp.h new file mode 100644 index 000000000000..d42b97756f0a --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/ieeefp.h @@ -0,0 +1,3 @@ +/* $OpenBSD: ieeefp.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/intr.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/intr.h new file mode 100644 index 000000000000..e1a6b65ddc6d --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/intr.h @@ -0,0 +1,10 @@ +/* $OpenBSD: intr.h,v 1.9 2014/04/01 20:27:14 mpi Exp $ */ + +#include + +#ifndef _LOCORE +extern int intr_shared_edge; + +void install_extint(void (*handler)(void)); +void openpic_set_priority(int, int); +#endif \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/kcore.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/kcore.h new file mode 100644 index 000000000000..0f3da93e3835 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/kcore.h @@ -0,0 +1,3 @@ +/* $OpenBSD: kcore.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/limits.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/limits.h new file mode 100644 index 000000000000..3b2a85e186ec --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/limits.h @@ -0,0 +1,3 @@ +/* $OpenBSD: limits.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/loadfile_machdep.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/loadfile_machdep.h new file mode 100644 index 000000000000..5ec3bc68fac0 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/loadfile_machdep.h @@ -0,0 +1,49 @@ +/* $OpenBSD: loadfile_machdep.h,v 1.4 2015/07/17 20:44:39 miod Exp $ */ +/* $NetBSD: loadfile_machdep.h,v 1.1 1999/04/29 03:17:12 tsubai Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define BOOT_ELF +#define ELFSIZE 32 + +#define LOAD_KERNEL LOAD_ALL +#define COUNT_KERNEL COUNT_ALL + +#define LOADADDR(a) (((u_long)(a)) + offset) +#define ALIGNENTRY(a) ((u_long)(a)) +#define READ(f, b, c) read((f), (void *)LOADADDR(b), (c)) +#define BCOPY(s, d, c) memcpy((void *)LOADADDR(d), (void *)(s), (c)) +#define BZERO(d, c) memset((void *)LOADADDR(d), 0, (c)) +#define WARN(a) (void)(printf a, \ + printf((errno ? ": %s\n" : "\n"), \ + strerror(errno))) +#define PROGRESS(a) (void) printf a +#define ALLOC(a) alloc(a) +#define FREE(a, b) free(a, b) \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/mplock.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/mplock.h new file mode 100644 index 000000000000..7e82ab4902a5 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/mplock.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mplock.h,v 1.3 2015/06/26 11:15:32 dlg Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/mutex.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/mutex.h new file mode 100644 index 000000000000..06bd20011dae --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/mutex.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mutex.h,v 1.1 2007/03/22 19:26:28 kettenis Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/openpromio.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/openpromio.h new file mode 100644 index 000000000000..1b69c531fe40 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/openpromio.h @@ -0,0 +1,57 @@ +/* $OpenBSD: openpromio.h,v 1.1 2007/11/12 19:23:26 kettenis Exp $ */ +/* $NetBSD: openpromio.h,v 1.1.1.1 1998/06/20 04:58:52 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)openpromio.h 8.1 (Berkeley) 6/11/93 + */ + +struct opiocdesc { + int op_nodeid; /* passed or returned node id */ + int op_namelen; /* length of op_name */ + char *op_name; /* pointer to field name */ + int op_buflen; /* length of op_buf (value-result) */ + char *op_buf; /* pointer to field value */ +}; + +#define OPIOCGET _IOWR('O', 1, struct opiocdesc) /* get openprom field */ +#define OPIOCSET _IOW('O', 2, struct opiocdesc) /* set openprom field */ +#define OPIOCNEXTPROP _IOWR('O', 3, struct opiocdesc) /* get next property */ +#define OPIOCGETOPTNODE _IOR('O', 4, int) /* get openprom field */ +#define OPIOCGETNEXT _IOWR('O', 5, int) /* get next node of node */ +#define OPIOCGETCHILD _IOWR('O', 6, int) /* get first child of node */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/param.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/param.h new file mode 100644 index 000000000000..1aeadbe686a0 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/param.h @@ -0,0 +1,52 @@ +/* $OpenBSD: param.h,v 1.6 2014/04/07 16:29:06 deraadt Exp $ */ + +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ + +#ifdef _KERNEL +#ifndef _LOCORE +#include +#endif /* _LOCORE */ +#endif + +#include + +#define MACHINE "macppc" +#define _MACHINE macppc + +#define KERNBASE 0x100000 + +#define MSGBUFSIZE (4 * PAGE_SIZE) + +#endif /* _MACHINE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/pcb.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/pcb.h new file mode 100644 index 000000000000..ae453583b2f2 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/pcb.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pcb.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/pci_machdep.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/pci_machdep.h new file mode 100644 index 000000000000..443fe240afa0 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/pci_machdep.h @@ -0,0 +1,108 @@ +/* $OpenBSD: pci_machdep.h,v 1.4 2019/12/05 12:46:54 mpi Exp $ */ +/* $NetBSD: pci_machdep.h,v 1.7 2001/07/20 00:07:14 eeh Exp $ */ + +/* + * Copyright (c) 1999 Matthew R. Green + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_PCI_MACHDEP_H_ +#define _MACHINE_PCI_MACHDEP_H_ + +extern struct powerpc_bus_dma_tag pci_bus_dma_tag; + +/* + * Forward declarations. + */ +struct pci_attach_args; + +/* + * define some bits used to glue into the common PCI code. + */ + +typedef struct ppc_pci_chipset *pci_chipset_tag_t; + +typedef unsigned long pci_intr_handle_t; + +/* + * The stuuuuuuupid allegedly MI PCI code expects pcitag_t to be a + * scalar type. But we really need to store both the OFW node and + * the bus/device/function info in it. (We'd like to store more, + * like all the ofw properties, but we don't need to.) Luckily, + * both are 32-bit values, so we can squeeze them into a u_int64_t + * with a little help from some macros. + */ + +#define PCITAG_NODE(x) (int)(((x)>>32)&0xffffffff) +#define PCITAG_OFFSET(x) ((x)&0xffffffff) +#define PCITAG_BUS(t) ((PCITAG_OFFSET(t)>>16)&0xff) +#define PCITAG_DEV(t) ((PCITAG_OFFSET(t)>>11)&0x1f) +#define PCITAG_FUN(t) ((PCITAG_OFFSET(t)>>8)&0x7) +#define PCITAG_CREATE(n,b,d,f) (((uint64_t)(n)<<32)|((b)<<16)|((d)<<11)|((f)<<8)) +typedef uint64_t pcitag_t; + +struct ppc_pci_chipset { + void *pc_conf_v; + int pc_node; + int busnode[256]; + + pcireg_t (*pc_conf_read)(void *, pcitag_t, int); + void (*pc_conf_write)(void *, pcitag_t, int, pcireg_t); +}; + + +void pci_attach_hook(struct device *, struct device *, + struct pcibus_attach_args *); +int pci_bus_maxdevs(pci_chipset_tag_t, int); +pcitag_t pci_make_tag(pci_chipset_tag_t, int, int, int); +void pci_decompose_tag(pci_chipset_tag_t, pcitag_t, int *, int *, + int *); +int pci_conf_size(pci_chipset_tag_t, pcitag_t); +pcireg_t pci_conf_read(pci_chipset_tag_t, pcitag_t, int); +void pci_conf_write(pci_chipset_tag_t, pcitag_t, int, pcireg_t); +int pci_intr_map(struct pci_attach_args *, pci_intr_handle_t *); +int pci_intr_map_msi(struct pci_attach_args *, pci_intr_handle_t *); +#define pci_intr_map_msix(p, vec, ihp) (-1) +int pci_intr_line(pci_chipset_tag_t, pci_intr_handle_t); +const char *pci_intr_string(pci_chipset_tag_t, pci_intr_handle_t); +void *pci_intr_establish(pci_chipset_tag_t, pci_intr_handle_t, + int, int (*)(void *), void *, const char *); +void pci_intr_disestablish(pci_chipset_tag_t, void *); +int pci_ether_hw_addr(pci_chipset_tag_t, uint8_t *); + +#define pci_probe_device_hook(c, a) (0) + +#define pci_min_powerstate(c, t) (PCI_PMCSR_STATE_D3) +#define pci_set_powerstate_md(c, t, s, p) + +#define pci_dev_postattach(a, b) + +int ofw_intr_map(int, uint32_t *, uint32_t *); +int ofw_enumerate_pcibus(struct pci_softc *, + int (*match)(struct pci_attach_args *), + struct pci_attach_args *); + +#define PCI_MACHDEP_ENUMERATE_BUS ofw_enumerate_pcibus + +#endif /* _MACHINE_PCI_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/pio.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/pio.h new file mode 100644 index 000000000000..551a29a60388 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/pio.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pio.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/pmap.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/pmap.h new file mode 100644 index 000000000000..3bff9d021440 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/pmap.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pmap.h,v 1.5 2005/11/07 02:19:46 brad Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/proc.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/proc.h new file mode 100644 index 000000000000..9fb584cd31e6 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/proc.h @@ -0,0 +1,3 @@ +/* $OpenBSD: proc.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/profile.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/profile.h new file mode 100644 index 000000000000..6ef4ef31dd36 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/profile.h @@ -0,0 +1,3 @@ +/* $OpenBSD: profile.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/psl.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/psl.h new file mode 100644 index 000000000000..75712e28fa05 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/psl.h @@ -0,0 +1,3 @@ +/* $OpenBSD: psl.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/pte.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/pte.h new file mode 100644 index 000000000000..effc458c15b4 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/pte.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pte.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/ptrace.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/ptrace.h new file mode 100644 index 000000000000..8853814e4c0b --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/ptrace.h @@ -0,0 +1,3 @@ +/* $OpenBSD: ptrace.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/rbus_machdep.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/rbus_machdep.h new file mode 100644 index 000000000000..1c0cb27000d2 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/rbus_machdep.h @@ -0,0 +1,62 @@ +/* $OpenBSD: rbus_machdep.h,v 1.6 2011/03/23 16:54:36 pirofti Exp $ */ +/* $NetBSD: rbus_machdep.h,v 1.2 1999/10/15 06:43:05 haya Exp $ */ + +/* + * Copyright (c) 1999 + * HAYAKAWA Koichi. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#if !defined _MACHINE_RBUS_MACHDEP_H_ +#define _MACHINE_RBUS_MACHDEP_H_ + +struct pci_attach_args; /* XXX */ + +void _bus_space_unmap(bus_space_tag_t, bus_space_handle_t, + bus_size_t, bus_addr_t *); + +#define md_space_map(rbt, physaddr, size, flags, bshp) \ + bus_space_map((rbt)->rb_bt, (physaddr), (size), (flags), (bshp)) + +/* XXX */ +bus_addr_t bus_space_unmap_p(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t size); + + +#define md_space_unmap(rbt, bsh, size, adrp) \ + do { \ + *adrp = bus_space_unmap_p((rbt)->rb_bt, (bsh), (size)); \ + if ((rbt)->rb_bt->bus_io) { \ + *adrp = *adrp & 0xffff; \ + } \ + } while (0) + +rbus_tag_t rbus_pccbb_parent_io(struct device *self, + struct pci_attach_args *pa); +rbus_tag_t rbus_pccbb_parent_mem(struct device *self, + struct pci_attach_args *pa); + +void pccbb_attach_hook(struct device *, struct device *, + struct pci_attach_args *); + +#endif /* _MACHINE_RBUS_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/reg.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/reg.h new file mode 100644 index 000000000000..8162e439ce62 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/reg.h @@ -0,0 +1,3 @@ +/* $OpenBSD: reg.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/reloc.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/reloc.h new file mode 100644 index 000000000000..faca641c794e --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/reloc.h @@ -0,0 +1,3 @@ +/* $OpenBSD: reloc.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/setjmp.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/setjmp.h new file mode 100644 index 000000000000..da9cc287b3f9 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/setjmp.h @@ -0,0 +1,3 @@ +/* $OpenBSD: setjmp.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/signal.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/signal.h new file mode 100644 index 000000000000..fc14275006d4 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/signal.h @@ -0,0 +1,3 @@ +/* $OpenBSD: signal.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/spinlock.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/spinlock.h new file mode 100644 index 000000000000..37b542933587 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/spinlock.h @@ -0,0 +1,3 @@ +/* $OpenBSD: spinlock.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/tcb.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/tcb.h new file mode 100644 index 000000000000..406394c9402c --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/tcb.h @@ -0,0 +1,3 @@ +/* $OpenBSD: tcb.h,v 1.2 2013/06/01 21:20:54 jasper Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/timetc.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/timetc.h new file mode 100644 index 000000000000..20d9dfb763ac --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/timetc.h @@ -0,0 +1,23 @@ +/* $OpenBSD: timetc.h,v 1.2 2020/07/17 20:15:43 gkoehler Exp $ */ +/* + * Copyright (c) 2020 Paul Irofti + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TIMETC_H_ +#define _MACHINE_TIMETC_H_ + +#define TC_TB 1 + +#endif /* _MACHINE_TIMETC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/trap.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/trap.h new file mode 100644 index 000000000000..4ceaa94f2bdb --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/trap.h @@ -0,0 +1,3 @@ +/* $OpenBSD: trap.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/vmparam.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/vmparam.h new file mode 100644 index 000000000000..a8578e273403 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/vmparam.h @@ -0,0 +1,99 @@ +/* $OpenBSD: vmparam.h,v 1.33 2024/01/30 16:43:22 deraadt Exp $ */ +/* $NetBSD: vmparam.h,v 1.1 1996/09/30 16:34:38 ws Exp $ */ + +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MACHINE_VMPARAM_H +#define MACHINE_VMPARAM_H + +#define USRSTACK VM_MAXUSER_ADDRESS + +#ifndef MAXTSIZ +#define MAXTSIZ (128*1024*1024) /* max text size */ +#endif + +#ifndef DFLDSIZ +#define DFLDSIZ (64*1024*1024) /* default data size */ +#endif + +#ifndef MAXDSIZ +#define MAXDSIZ (2UL*1024*1024*1024) /* max data size */ +#endif + +#ifndef BRKSIZ +#define BRKSIZ MAXDSIZ /* heap gap size */ +#endif + +#ifndef DFLSSIZ +#define DFLSSIZ (2*1024*1024) /* default stack size */ +#endif + +#ifndef MAXSSIZ +#define MAXSSIZ (32*1024*1024) /* max stack size */ +#endif + +#define STACKGAP_RANDOM 256*1024 + +/* + * Size of shared memory map + */ +#ifndef SHMMAXPGS +#define SHMMAXPGS 8192 /* 32mb */ +#endif + +/* + * Size of User Raw I/O map + */ +#define USRIOSIZE 1024 + +/* + * Would like to have MAX addresses = 0, but this doesn't (currently) work + */ +#define VM_MIN_ADDRESS ((vaddr_t)PAGE_SIZE) +#define VM_MAXUSER_ADDRESS ((vaddr_t)0xfffff000) +#define VM_MAX_ADDRESS VM_MAXUSER_ADDRESS +#define VM_MIN_KERNEL_ADDRESS ((vaddr_t)(PPC_KERNEL_SR << ADDR_SR_SHIFT)) + +/* map PIE into approximately the first quarter of user va space */ +#define VM_PIE_MIN_ADDR PAGE_SIZE +#define VM_PIE_MAX_ADDR 0x40000000 + +#define VM_KERN_ADDRESS_SIZE (PPC_SEGMENT_LENGTH - (32 * 1024 * 1024)) +#define VM_MAX_KERNEL_ADDRESS (VM_MIN_KERNEL_ADDRESS + VM_KERN_ADDRESS_SIZE) + +#define VM_PHYS_SIZE (USRIOSIZE * PAGE_SIZE) + +#define VM_PHYSSEG_MAX 32 /* actually we could have this many segments */ +#define VM_PHYSSEG_STRAT VM_PSTRAT_BSEARCH +#define VM_PHYSSEG_NOADD /* can't add RAM after vm_mem_init */ + +#endif \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/machine/z8530var.h b/lib/libc/include/powerpc-openbsd-eabihf/machine/z8530var.h new file mode 100644 index 000000000000..275214fc2d6e --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/machine/z8530var.h @@ -0,0 +1,152 @@ +/* $OpenBSD: z8530var.h,v 1.11 2024/05/22 05:51:49 jsg Exp $ */ +/* $NetBSD: z8530var.h,v 1.5 2002/03/17 19:40:45 atatat Exp $ */ + +/* + * Copyright (c) 1994 Gordon W. Ross + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)zsvar.h 8.1 (Berkeley) 6/11/93 + */ + +#include +#include + +/* + * Clock source info structure, added here so xzs_chanstate works + */ +struct zsclksrc { + long clk; /* clock rate, in MHz, present on signal line */ + int flags; /* Specifies how this source can be used + (RTxC divided, RTxC BRG, PCLK BRG, TRxC divided) + and also if the source is "external" and if it + is changeable (by an ioctl ex.). The + source usage flags are used by the tty + child. The other bits tell zsloadchannelregs + if it should call an md signal source + changing routine. ZSC_VARIABLE says if + an ioctl should be able to change the + clock rate.*/ +}; +#define ZSC_PCLK 0x01 +#define ZSC_RTXBRG 0x02 +#define ZSC_RTXDIV 0x04 +#define ZSC_TRXDIV 0x08 +#define ZSC_VARIABLE 0x40 +#define ZSC_EXTERN 0x80 + +#define ZSC_BRG 0x03 +#define ZSC_DIV 0x0c + + +/* + * These are the machine-dependent (extended) variants of + * struct zs_chanstate and struct zsc_softc + */ +struct xzs_chanstate { + /* machine-independent part (First!)*/ + struct zs_chanstate xzs_cs; + /* machine-dependent extensions */ + int cs_hwflags; + int cs_chip; /* type of chip */ + /* Clock source info... */ + int cs_clock_count; /* how many signal sources available */ + struct zsclksrc cs_clocks[4]; /* info on available signal sources */ + long cs_cclk_flag; /* flag for current clock source */ + long cs_pclk_flag; /* flag for pending clock source */ + int cs_csource; /* current source # */ + int cs_psource; /* pending source # */ +}; + +struct zsc_softc { + struct device zsc_dev; /* base device */ + struct zs_chanstate *zsc_cs[2]; /* channel A and B soft state */ + /* Machine-dependent part follows... */ + void *zsc_softintr; + struct xzs_chanstate xzsc_xcs_store[2]; + dbdma_regmap_t *zsc_txdmareg[2]; + dbdma_command_t *zsc_txdmacmd[2]; + /* XXX tx only, for now */ +}; + +/* + * Functions to read and write individual registers in a channel. + * The ZS chip requires a 1.6 uSec. recovery time between accesses, + * and the Sun3 hardware does NOT take care of this for you. + * MacII hardware DOES take care of the delay for us. :-) + * XXX - Then these should be inline functions! -gwr + * Some clock-chirped macs lose serial ports. It could be that the + * hardware delay is tied to the CPU speed, and that the minimum delay + * no longer's respected. For them, ZS_DELAY might help. + * XXX - no one seems to want to try and check this -wrs + */ + +u_char zs_read_reg(struct zs_chanstate *cs, u_char reg); +u_char zs_read_csr(struct zs_chanstate *cs); +u_char zs_read_data(struct zs_chanstate *cs); + +void zs_write_reg(struct zs_chanstate *cs, u_char reg, u_char val); +void zs_write_csr(struct zs_chanstate *cs, u_char val); +void zs_write_data(struct zs_chanstate *cs, u_char val); + +/* XXX - Could define splzs() here instead of in psl.h */ +#define splzs spltty + +/* Hook for MD ioctl support */ +int zsmdioctl(struct zs_chanstate *cs, u_long cmd, caddr_t data); +/* XXX - This is a bit gross... */ +/* +#define ZS_MD_IOCTL(cs, cmd, data) zsmdioctl(cs, cmd, data) +*/ + +/* Callback for "external" clock sources */ +void zsmd_setclock(struct zs_chanstate *cs); +#define ZS_MD_SETCLK(cs) zsmd_setclock(cs) + +#define PCLK (9600 * 384) /* PCLK pin input clock rate */ + +/* The layout of this is hardware-dependent (padding, order). */ +struct zschan { + volatile u_char zc_csr; /* ctrl,status, and indirect access */ + u_char zc_xxx0[15]; + volatile u_char zc_data; /* data */ + u_char zc_xxx1[15]; +}; + +#ifndef ZSCCF_CHANNEL +#define ZSCCF_CHANNEL 0 +#define ZSCCF_CHANNEL_DEFAULT -1 +#endif \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/_float.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/_float.h new file mode 100644 index 000000000000..1bf34fd14e39 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/_float.h @@ -0,0 +1,3 @@ +/* $OpenBSD: _float.h,v 1.1 2012/06/26 16:12:44 deraadt Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/_types.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/_types.h new file mode 100644 index 000000000000..e896392602ef --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/_types.h @@ -0,0 +1,4 @@ +/* $OpenBSD: _types.h,v 1.1 2006/01/06 18:50:09 millert Exp $ */ + +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/apmvar.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/apmvar.h new file mode 100644 index 000000000000..4aa7952d46bc --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/apmvar.h @@ -0,0 +1,122 @@ +/* $OpenBSD: apmvar.h,v 1.10 2019/01/22 02:36:30 phessler Exp $ */ + +/* + * Copyright (c) 2001 Alexander Guy + * Copyright (c) 1995 John T. Kohl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _MACHINE_APMVAR_H_ +#define _MACHINE_APMVAR_H_ + +#include + +/* Advanced Power Management (v1.0 and v1.1 specification) + * functions/defines/etc. + */ + +/* These definitions make up the heart of the user-land interface + * to the APM devices. + */ + +#define APM_AC_OFF 0x00 +#define APM_AC_ON 0x01 +#define APM_AC_BACKUP 0x02 +#define APM_AC_UNKNOWN 0xff +#define APM_BATT_HIGH 0x00 +#define APM_BATT_LOW 0x01 +#define APM_BATT_CRITICAL 0x02 +#define APM_BATT_CHARGING 0x03 +#define APM_BATT_UNKNOWN 0xff +#define APM_BATT_LIFE_UNKNOWN 0xff + +#define APM_NOEVENT 0x0000 +#define APM_STANDBY_REQ 0x0001 +#define APM_SUSPEND_REQ 0x0002 +#define APM_NORMAL_RESUME 0x0003 +#define APM_CRIT_RESUME 0x0004 /* suspend/resume happened + without us */ +#define APM_BATTERY_LOW 0x0005 +#define APM_POWER_CHANGE 0x0006 +#define APM_UPDATE_TIME 0x0007 +#define APM_CRIT_SUSPEND_REQ 0x0008 +#define APM_USER_STANDBY_REQ 0x0009 +#define APM_USER_SUSPEND_REQ 0x000A +#define APM_SYS_STANDBY_RESUME 0x000B +#define APM_CAPABILITY_CHANGE 0x000C /* apm v1.2 */ +#define APM_USER_HIBERNATE_REQ 0x000D +#define APM_EVENT_MASK 0xffff + +#define APM_EVENT_COMPOSE(t,i) ((((i) & 0x7fff) << 16)|((t) & APM_EVENT_MASK)) +#define APM_EVENT_TYPE(e) ((e) & APM_EVENT_MASK) +#define APM_EVENT_INDEX(e) ((e) >> 16) + +/* + * LP (Laptop Package) + * + * Copyright (C) 1994 by HOSOKAWA Tatsumi + * + * This software may be used, modified, copied, and distributed, in + * both source and binary form provided that the above copyright and + * these terms are retained. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with its + * use. + * + * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) + */ + +#define APM_BATTERY_ABSENT 4 + +struct apm_power_info { + u_char battery_state; + u_char ac_state; + u_char battery_life; + u_char spare1; + u_int minutes_left; /* estimate */ + u_int spare2[6]; +}; + +struct apm_ctl { + u_int dev; + u_int mode; +}; + +#define APM_IOC_REJECT _IOW('A', 0, struct apm_event_info) /* reject request # */ +#define APM_IOC_STANDBY _IO('A', 1) /* put system into standby */ +#define APM_IOC_SUSPEND _IO('A', 2) /* put system into suspend */ +#define APM_IOC_GETPOWER _IOR('A', 3, struct apm_power_info) /* fetch battery state */ +#define APM_IOC_DEV_CTL _IOW('A', 5, struct apm_ctl) /* put device into mode */ +#define APM_IOC_PRN_CTL _IOW('A', 6, int ) /* driver power status msg */ +#define APM_PRINT_ON 0 /* driver power status displayed */ +#define APM_PRINT_OFF 1 /* driver power status not displayed */ +#define APM_PRINT_PCT 2 /* driver power status only displayed + if the percentage changes */ +#define APM_IOC_STANDBY_REQ _IO('A', 7) /* request standby */ +#define APM_IOC_SUSPEND_REQ _IO('A', 8) /* request suspend */ +#define APM_IOC_HIBERNATE _IO('A', 9) /* put system into hibernate */ + +#endif /* _MACHINE_APMVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/asm.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/asm.h new file mode 100644 index 000000000000..ea7bd91fc3ef --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/asm.h @@ -0,0 +1,3 @@ +/* $OpenBSD: asm.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/atomic.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/atomic.h new file mode 100644 index 000000000000..bd432ef8ec29 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/atomic.h @@ -0,0 +1,10 @@ +/* $OpenBSD: atomic.h,v 1.3 2011/03/23 16:54:36 pirofti Exp $ */ + +/* Public Domain */ + +#ifndef _MACHINE_ATOMIC_H_ +#define _MACHINE_ATOMIC_H_ + +#include + +#endif /* _MACHINE_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/autoconf.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/autoconf.h new file mode 100644 index 000000000000..3ec5c80d9edb --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/autoconf.h @@ -0,0 +1,72 @@ +/* $OpenBSD: autoconf.h,v 1.13 2024/05/22 05:51:49 jsg Exp $ */ + +/* + * Copyright (c) 1997 Per Fogelstrom + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/* + * Machine-dependent structures of autoconfiguration + */ + +#ifndef _MACHINE_AUTOCONF_H_ +#define _MACHINE_AUTOCONF_H_ + +#include + +struct confargs { + char *ca_name; + bus_space_tag_t ca_iot; + bus_dma_tag_t ca_dmat; + u_int32_t ca_node; + int ca_nreg; + u_int32_t *ca_reg; + int ca_nintr; + int32_t *ca_intr; + u_int ca_baseaddr; + +}; + +int badaddr(void *, u_int32_t); + +typedef int (time_read_t)(time_t *sec); +typedef int (time_write_t)(time_t sec); + +extern time_read_t *time_read; +extern time_write_t *time_write; + +typedef int mac_intr_handle_t; +typedef void *(intr_establish_t)(void *, mac_intr_handle_t, + int, int, int (*func)(void *), void *, const char *); +typedef void (intr_disestablish_t)(void *, void *); +struct cpu_info; +typedef void (intr_send_ipi_t)(struct cpu_info *, int); + +intr_establish_t mac_intr_establish; +intr_disestablish_t mac_intr_disestablish; +extern intr_establish_t *intr_establish_func; +extern intr_disestablish_t *intr_disestablish_func; +extern intr_send_ipi_t *intr_send_ipi_func; + + +#endif /* _MACHINE_AUTOCONF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/bus.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/bus.h new file mode 100644 index 000000000000..0787b6818331 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/bus.h @@ -0,0 +1,643 @@ +/* $OpenBSD: bus.h,v 1.27 2024/05/22 05:51:49 jsg Exp $ */ + +/* + * Copyright (c) 1997 Per Fogelstrom. All rights reserved. + * Copyright (c) 1996 Niklas Hallqvist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BUS_H_ +#define _MACHINE_BUS_H_ + +#include + +#ifdef __STDC__ +#define CAT(a,b) a##b +#define CAT3(a,b,c) a##b##c +#else +#define CAT(a,b) a/**/b +#define CAT3(a,b,c) a/**/b/**/c +#endif + +/* + * Bus access types. + */ +typedef u_long bus_addr_t; +typedef u_long bus_size_t; +typedef u_long bus_space_handle_t; +typedef struct ppc_bus_space *bus_space_tag_t; + +struct ppc_bus_space { + u_int32_t bus_base; + u_int32_t bus_size; + u_int8_t bus_io; /* IO or memory */ +}; +#define POWERPC_BUS_TAG_BASE(x) ((x)->bus_base) + +/* + * Access methods for bus resources + */ +int bus_space_map(bus_space_tag_t t, bus_addr_t addr, + bus_size_t size, int flags, bus_space_handle_t *bshp); +void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t size); +int bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp); +int bus_space_alloc(bus_space_tag_t tag, bus_addr_t rstart, + bus_addr_t rend, bus_size_t size, bus_size_t alignment, + bus_size_t boundary, int flags, bus_addr_t *addrp, + bus_space_handle_t *handlep); +void bus_space_free(bus_space_tag_t tag, bus_space_handle_t handle, + bus_size_t size); +paddr_t bus_space_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int); + +#define BUS_SPACE_MAP_CACHEABLE 0x01 +#define BUS_SPACE_MAP_LINEAR 0x02 +#define BUS_SPACE_MAP_PREFETCHABLE 0x04 + +/* + * void *bus_space_vaddr(bus_space_tag_t, bus_space_handle_t); + * + * Get the kernel virtual address for the mapped bus space. + * Only allowed for regions mapped with BUS_SPACE_MAP_LINEAR. + */ +#define bus_space_vaddr(t, h) ((void *)(h)) + +#define bus_space_read(n,m) \ +static __inline CAT3(u_int,m,_t) \ +CAT(bus_space_read_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba) \ +{ \ + return CAT3(in,m,rb)((volatile CAT3(u_int,m,_t) *)(bsh + (ba))); \ +} + +bus_space_read(1,8) +bus_space_read(2,16) +bus_space_read(4,32) + +#define bus_space_read_8 !!! bus_space_read_8 unimplemented !!! + +#define bus_space_write(n,m) \ +static __inline void \ +CAT(bus_space_write_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(u_int,m,_t) x) \ +{ \ + CAT3(out,m,rb)((volatile CAT3(u_int,m,_t) *)(bsh + (ba)), x); \ +} + +bus_space_write(1,8) +bus_space_write(2,16) +bus_space_write(4,32) + +#define bus_space_write_8 !!! bus_space_write_8 unimplemented !!! + +#define bus_space_read_raw(n,m) \ +static __inline CAT3(u_int,m,_t) \ +CAT(bus_space_read_raw_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba) \ +{ \ + return CAT(in,m)((volatile CAT3(u_int,m,_t) *)(bsh + (ba))); \ +} + +bus_space_read_raw(1,8) +bus_space_read_raw(2,16) +bus_space_read_raw(4,32) + +#define bus_space_read_raw_8 !!! bus_space_read_raw_8 unimplemented !!! + +#define bus_space_write_raw(n,m) \ +static __inline void \ +CAT(bus_space_write_raw_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(u_int,m,_t) x) \ +{ \ + CAT(out,m)((volatile CAT3(u_int,m,_t) *)(bsh + (ba)), x); \ +} + +bus_space_write_raw(1,8) +bus_space_write_raw(2,16) +bus_space_write_raw(4,32) + +#define bus_space_write_raw_8 !!! bus_space_write_raw_8 unimplemented !!! + +#define bus_space_read_multi(n, m) \ +static __inline void \ +CAT(bus_space_read_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t ba, CAT3(u_int,m,_t) *buf, bus_size_t cnt) \ +{ \ + while (cnt--) \ + *buf++ = CAT(bus_space_read_,n)(bst, bsh, ba); \ +} + +bus_space_read_multi(1,8) +bus_space_read_multi(2,16) +bus_space_read_multi(4,32) + +#define bus_space_read_multi_8 !!! bus_space_read_multi_8 not implemented !!! + + +#define bus_space_write_multi_8 !!! bus_space_write_multi_8 not implemented !!! + +#define bus_space_write_multi(n, m) \ +static __inline void \ +CAT(bus_space_write_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t ba, const CAT3(u_int,m,_t) *buf, bus_size_t cnt) \ +{ \ + while (cnt--) \ + CAT(bus_space_write_,n)(bst, bsh, ba, *buf++); \ +} + +bus_space_write_multi(1,8) +bus_space_write_multi(2,16) +bus_space_write_multi(4,32) + +#define bus_space_write_multi_8 !!! bus_space_write_multi_8 not implemented !!! + +/* + * void bus_space_read_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t *addr, size_t count); + * + * Read `count' 1, 2, 4, or 8 byte quantities from bus space + * described by tag/handle and starting at `offset' and copy into + * buffer provided. + */ +#define __BA(t, h, o) ((void *)((h) + (o))) + +static __inline void +bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int8_t *addr, size_t count) +{ + volatile u_int8_t *s = __BA(tag, bsh, offset); + + while (count--) + *addr++ = *s++; + __asm volatile("eieio; sync"); +} + +static __inline void +bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int16_t *addr, size_t count) +{ + volatile u_int16_t *s = __BA(tag, bsh, offset); + + while (count--) + __asm volatile("lhbrx %0, 0, %1" : + "=r"(*addr++) : "r"(s++)); + __asm volatile("eieio; sync"); +} + +static __inline void +bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int32_t *addr, size_t count) +{ + volatile u_int32_t *s = __BA(tag, bsh, offset); + + while (count--) + __asm volatile("lwbrx %0, 0, %1" : + "=r"(*addr++) : "r"(s++)); + __asm volatile("eieio; sync"); +} + +#if 0 /* Cause a link error for bus_space_read_region_8 */ +#define bus_space_read_region_8 !!! unimplemented !!! +#endif + + +/* + * void bus_space_write_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_intN_t *addr, size_t count); + * + * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided + * to bus space described by tag/handle starting at `offset'. + */ + +static __inline void +bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, const u_int8_t *addr, size_t count) +{ + volatile u_int8_t *d = __BA(tag, bsh, offset); + + while (count--) + *d++ = *addr++; + __asm volatile("eieio; sync"); +} + +static __inline void +bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, const u_int16_t *addr, size_t count) +{ + volatile u_int16_t *d = __BA(tag, bsh, offset); + + while (count--) + __asm volatile("sthbrx %0, 0, %1" :: + "r"(*addr++), "r"(d++)); + __asm volatile("eieio; sync"); +} + +static __inline void +bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, const u_int32_t *addr, size_t count) +{ + volatile u_int32_t *d = __BA(tag, bsh, offset); + + while (count--) + __asm volatile("stwbrx %0, 0, %1" :: + "r"(*addr++), "r"(d++)); + __asm volatile("eieio; sync"); +} + +#if 0 +#define bus_space_write_region_8 !!! bus_space_write_region_8 unimplemented !!! +#endif + +/* + * void bus_space_read_raw_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t *addr, size_t count); + * + * Read `count' bytes from bus space described by tag/handle and starting + * at `offset' and copy into buffer provided w/o bus-host byte swapping. + */ + +static __inline void +bus_space_read_raw_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int8_t *addr, size_t count) +{ + volatile u_int16_t *s = __BA(tag, bsh, offset); + u_int16_t *laddr = (void *)addr; + + count = count >> 1; + + while (count--) + *laddr++ = *s++; + __asm volatile("eieio; sync"); +} + +static __inline void +bus_space_read_raw_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int8_t *addr, size_t count) +{ + volatile u_int32_t *s = __BA(tag, bsh, offset); + u_int32_t *laddr = (void *)addr; + + count = count >> 2; + + while (count--) + *laddr++ = *s++; + __asm volatile("eieio; sync"); +} + +#if 0 /* Cause a link error for bus_space_read_raw_region_8 */ +#define bus_space_read_raw_region_8 \ + !!! bus_space_read_raw_region_8 unimplemented !!! +#endif + + +/* + * void bus_space_write_raw_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_intN_t *addr, size_t count); + * + * Write `count' bytes from the buffer provided to bus space described + * by tag/handle starting at `offset' w/o host-bus byte swapping. + */ + +static __inline void +bus_space_write_raw_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, const u_int8_t *addr, size_t count) +{ + volatile u_int16_t *d = __BA(tag, bsh, offset); + const u_int16_t *laddr = (void *)addr; + + count = count >> 1; + + while (count--) + *d++ = *laddr++; + __asm volatile("eieio; sync"); +} + +static __inline void +bus_space_write_raw_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, const u_int8_t *addr, size_t count) +{ + volatile u_int32_t *d = __BA(tag, bsh, offset); + const u_int32_t *laddr = (void *)addr; + + count = count >> 2; + + while (count--) + *d++ = *laddr++; + __asm volatile("eieio; sync"); +} + +#if 0 +#define bus_space_write_raw_region_8 \ + !!! bus_space_write_raw_region_8 unimplemented !!! +#endif + +/* + * void bus_space_set_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, u_intN_t val, + * size_t count); + * + * Write the 1, 2, 4, or 8 byte value `val' to bus space described + * by tag/handle/offset `count' times. + */ +static __inline void bus_space_set_multi_1(bus_space_tag_t, + bus_space_handle_t, bus_size_t, u_int8_t, size_t); +static __inline void bus_space_set_multi_2(bus_space_tag_t, + bus_space_handle_t, bus_size_t, u_int16_t, size_t); +static __inline void bus_space_set_multi_4(bus_space_tag_t, + bus_space_handle_t, bus_size_t, u_int32_t, size_t); + +static __inline void +bus_space_set_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int8_t val, size_t count) +{ + volatile u_int8_t *d = __BA(tag, bsh, offset); + + while (count--) + *d = val; + __asm__ volatile("eieio; sync"); +} + +static __inline void +bus_space_set_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int16_t val, size_t count) +{ + volatile u_int16_t *d = __BA(tag, bsh, offset); + + while (count--) + __asm__ volatile("sthbrx %0, 0, %1" :: + "r"(val), "r"(d)); + __asm__ volatile("eieio; sync"); +} + +static __inline void +bus_space_set_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int32_t val, size_t count) +{ + volatile u_int32_t *d = __BA(tag, bsh, offset); + + while (count--) + __asm__ volatile("stwbrx %0, 0, %1" :: + "r"(val), "r"(d)); + __asm__ volatile("eieio; sync"); +} + +#define bus_space_set_multi_8 !!! bus_space_set_multi_8 unimplemented !!! + +/* These are OpenBSD extensions to the general NetBSD bus interface. */ +void +bus_space_read_raw_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_addr_t ba, u_int8_t *dst, bus_size_t size); +void +bus_space_read_raw_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_addr_t ba, u_int8_t *dst, bus_size_t size); +#define bus_space_read_raw_multi_8 \ + !!! bus_space_read_raw_multi_8 not implemented !!! + +void +bus_space_write_raw_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_addr_t ba, const u_int8_t *src, bus_size_t size); +void +bus_space_write_raw_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_addr_t ba, const u_int8_t *src, bus_size_t size); +#define bus_space_write_raw_multi_8 \ + !!! bus_space_write_raw_multi_8 not implemented !!! + +void +bus_space_set_region_1(bus_space_tag_t bst, bus_space_handle_t h, bus_size_t o, + u_int8_t val, bus_size_t c); +void +bus_space_set_region_2(bus_space_tag_t bst, bus_space_handle_t h, bus_size_t o, + u_int16_t val, bus_size_t c); +void +bus_space_set_region_4(bus_space_tag_t bst, bus_space_handle_t h, bus_size_t o, + u_int32_t val, bus_size_t c); +#define bus_space_set_region_8 \ + !!! bus_space_set_region_8 not implemented !!! + +void +bus_space_copy_1(void *v, bus_space_handle_t h1, bus_space_handle_t h2, + bus_size_t o1, bus_size_t o2, bus_size_t c); +void +bus_space_copy_2(void *v, bus_space_handle_t h1, bus_space_handle_t h2, + bus_size_t o1, bus_size_t o2, bus_size_t c); +void +bus_space_copy_4(void *v, bus_space_handle_t h1, bus_space_handle_t h2, + bus_size_t o1, bus_size_t o2, bus_size_t c); +#define bus_space_copy_8 \ + !!! bus_space_copy_8 not implemented !!! + +/* + * Bus read/write barrier methods. + * + * void bus_space_barrier(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * bus_size_t len, int flags); + * + * Note: powerpc does not currently implement barriers, but we must + * provide the flags to MI code. + * the processor does have eieio which is effectively the barrier + * operator, however due to how memory is mapped this should? not + * be required. + */ +#define bus_space_barrier(t, h, o, l, f) \ + ((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f))) +#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ +#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ + +#define BUS_DMA_WAITOK 0x0000 /* safe to sleep (pseudo-flag) */ +#define BUS_DMA_NOWAIT 0x0001 /* not safe to sleep */ +#define BUS_DMA_ALLOCNOW 0x0002 /* perform resource allocation now */ +#define BUS_DMA_COHERENT 0x0008 /* hint: map memory DMA coherent */ +#define BUS_DMA_BUS1 0x0010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x0020 +#define BUS_DMA_BUS3 0x0040 +#define BUS_DMA_BUS4 0x0080 +#define BUS_DMA_READ 0x0100 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x0200 /* mapping is memory -> device only */ +#define BUS_DMA_STREAMING 0x0400 /* hint: sequential, unidirectional */ +#define BUS_DMA_ZERO 0x0800 /* zero memory in dmamem_alloc */ +#define BUS_DMA_NOCACHE 0x1000 /* map memory uncached */ +#define BUS_DMA_64BIT 0x2000 /* device handles 64bit dva */ + + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct proc; +struct uio; + +#define BUS_DMASYNC_POSTREAD 0x01 +#define BUS_DMASYNC_POSTWRITE 0x02 +#define BUS_DMASYNC_PREREAD 0x04 +#define BUS_DMASYNC_PREWRITE 0x08 + +typedef struct powerpc_bus_dma_tag *bus_dma_tag_t; +typedef struct powerpc_bus_dmamap *bus_dmamap_t; + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +struct powerpc_bus_dma_segment { + bus_addr_t ds_addr; /* DMA address */ + bus_size_t ds_len; /* length of transfer */ +}; +typedef struct powerpc_bus_dma_segment bus_dma_segment_t; + +/* + * bus_dma_tag_t + * + * A machine-dependent opaque type describing the implementation of + * DMA for a given bus. + */ + +struct powerpc_bus_dma_tag { + void *_cookie; /* cookie used in the guts */ + + /* + * DMA mapping methods. + */ + int (*_dmamap_create)(bus_dma_tag_t , bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); + void (*_dmamap_destroy)(bus_dma_tag_t , bus_dmamap_t); + int (*_dmamap_load)(bus_dma_tag_t , bus_dmamap_t, void *, + bus_size_t, struct proc *, int); + int (*_dmamap_load_mbuf)(bus_dma_tag_t , bus_dmamap_t, + struct mbuf *, int); + int (*_dmamap_load_uio)(bus_dma_tag_t , bus_dmamap_t, + struct uio *, int); + int (*_dmamap_load_raw)(bus_dma_tag_t , bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); + void (*_dmamap_unload)(bus_dma_tag_t , bus_dmamap_t); + void (*_dmamap_sync)(bus_dma_tag_t , bus_dmamap_t, + bus_addr_t, bus_size_t, int); + + /* + * DMA memory utility functions. + */ + int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); + int (*_dmamem_alloc_range)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int, + bus_addr_t, bus_addr_t); + void (*_dmamem_free)(bus_dma_tag_t, bus_dma_segment_t *, int); + int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); + void (*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t); + paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, + int, off_t, int, int); +}; + +#define bus_dmamap_create(t, s, n, m, b, f, p) \ + (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) +#define bus_dmamap_destroy(t, p) \ + (*(t)->_dmamap_destroy)((t), (p)) +#define bus_dmamap_load(t, m, b, s, p, f) \ + (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) +#define bus_dmamap_load_mbuf(t, m, b, f) \ + (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) +#define bus_dmamap_load_uio(t, m, u, f) \ + (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) +#define bus_dmamap_load_raw(t, m, sg, n, s, f) \ + (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) +#define bus_dmamap_unload(t, p) \ + (*(t)->_dmamap_unload)((t), (p)) +#define bus_dmamap_sync(t, p, a, l, o) \ + (void)((t)->_dmamap_sync ? \ + (*(t)->_dmamap_sync)((t), (p), (a), (l), (o)) : (void)0) + +#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ + (*(t)->_dmamem_alloc)((t)->_cookie, (s), (a), (b), (sg), (n), (r), (f)) +#define bus_dmamem_alloc_range(t, s, a, b, sg, n, r, f, l, h) \ + (*(t)->_dmamem_alloc_range)((t), (s), (a), (b), (sg), \ + (n), (r), (f), (l), (h)) +#define bus_dmamem_free(t, sg, n) \ + (*(t)->_dmamem_free)((t)->_cookie, (sg), (n)) +#define bus_dmamem_map(t, sg, n, s, k, f) \ + (*(t)->_dmamem_map)((t)->_cookie, (sg), (n), (s), (k), (f)) +#define bus_dmamem_unmap(t, k, s) \ + (*(t)->_dmamem_unmap)((t)->_cookie, (k), (s)) +#define bus_dmamem_mmap(t, sg, n, o, p, f) \ + (*(t)->_dmamem_mmap)((t)->_cookie, (sg), (n), (o), (p), (f)) + +int _dmamap_create(bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); +void _dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); +int _dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); +int _dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *, int); +int _dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, struct uio *, int); +int _dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); +void _dmamap_unload(bus_dma_tag_t, bus_dmamap_t); +void _dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, bus_size_t, + int); + +int _dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); +int _dmamem_alloc_range( bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int, + bus_addr_t, bus_addr_t); +void _dmamem_free(bus_dma_tag_t, bus_dma_segment_t *, int); +int _dmamem_map(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); +void _dmamem_unmap(bus_dma_tag_t, caddr_t, size_t); +paddr_t _dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, int, int); + +/* + * bus_dmamap_t + * + * Describes a DMA mapping. + */ +struct powerpc_bus_dmamap { + /* + * PRIVATE MEMBERS: not for use by machine-independent code. + */ + bus_size_t _dm_size; /* largest DMA transfer mappable */ + int _dm_segcnt; /* number of segs this map can map */ + bus_size_t _dm_maxsegsz; /* largest possible segment */ + bus_size_t _dm_boundary; /* don't cross this */ + int _dm_flags; /* misc. flags */ + + void *_dm_cookie; /* cookie for bus-specific functions */ + + /* + * PUBLIC MEMBERS: these are used by machine-independent code. + */ + bus_size_t dm_mapsize; /* size of the mapping */ + int dm_nsegs; /* # valid segments in mapping */ + bus_dma_segment_t dm_segs[1]; /* segments; variable length */ +}; + +#endif /* _MACHINE_BUS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/cdefs.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/cdefs.h new file mode 100644 index 000000000000..4e15edb0a4fd --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/cdefs.h @@ -0,0 +1,3 @@ +/* $OpenBSD: cdefs.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/conf.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/conf.h new file mode 100644 index 000000000000..370b2c67c56d --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/conf.h @@ -0,0 +1,56 @@ +/* $OpenBSD: conf.h,v 1.15 2022/06/28 14:43:50 visa Exp $ */ +/* $NetBSD: conf.h,v 1.2 1996/05/05 19:28:34 christos Exp $ */ + +/* + * Copyright (c) 1996 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#define mmread mmrw +#define mmwrite mmrw +cdev_decl(mm); + +/* open, close, write, ioctl, kqueue */ +#define cdev_apm_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev, 0, 0, dev_init(c,n,kqfilter) } + +cdev_decl(apm); +cdev_decl(zs); + +/* open, close, ioctl */ +#define cdev_openprom_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) nullop, 0, \ + (dev_type_mmap((*))) enodev } + +cdev_decl(openprom); \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/cpu.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/cpu.h new file mode 100644 index 000000000000..9b938b2a8d56 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/cpu.h @@ -0,0 +1,76 @@ +/* $OpenBSD: cpu.h,v 1.15 2022/10/21 22:42:36 gkoehler Exp $ */ +/* $NetBSD: cpu.h,v 1.1 1996/09/30 16:34:21 ws Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _MACHINE_CPU_H_ +#define _MACHINE_CPU_H_ + +/* + * CTL_MACHDEP definitions. + */ +#define CPU_ALLOWAPERTURE 1 /* allow mmap of /dev/xf86 */ +#define CPU_ALTIVEC 2 /* altivec is present */ +#define CPU_LIDACTION 3 /* action caused by lid close */ +#define CPU_PWRACTION 4 /* action caused by power button */ +#define CPU_MAXID 5 /* number of valid machdep ids */ + +#define CTL_MACHDEP_NAMES { \ + { 0, 0 }, \ + { "allowaperture", CTLTYPE_INT }, \ + { "altivec", CTLTYPE_INT }, \ + { "lidaction", CTLTYPE_INT }, \ + { "pwraction", CTLTYPE_INT }, \ +} + +#ifdef _KERNEL + +#include + +/* Frequency scaling */ +#define FREQ_FULL 0 +#define FREQ_HALF 1 +#define FREQ_QUARTER 2 /* Supported only on IBM 970MP */ + +extern u_int32_t ppc_curfreq; +extern u_int32_t ppc_maxfreq; +extern int ppc_altivec; + +extern void (*ppc64_slew_voltage)(u_int); + +extern u_int32_t ticks_per_sec; +extern u_int32_t ns_per_tick; + +extern int lid_action; +extern int pwr_action; + +#endif /* _KERNEL */ +#endif /* _MACHINE_CPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/db_machdep.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/db_machdep.h new file mode 100644 index 000000000000..525dade241bf --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/db_machdep.h @@ -0,0 +1,3 @@ +/* $OpenBSD: db_machdep.h,v 1.7 2016/03/05 17:41:55 mpi Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/disklabel.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/disklabel.h new file mode 100644 index 000000000000..aca83dc5eb6d --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/disklabel.h @@ -0,0 +1,90 @@ +/* $OpenBSD: disklabel.h,v 1.16 2015/09/30 15:13:54 krw Exp $ */ + +/* + * Copyright (c) 1994 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_DISKLABEL_H_ +#define _MACHINE_DISKLABEL_H_ + +#define LABELSECTOR 1 /* sector containing label */ +#define LABELOFFSET 0 /* offset of label in sector */ +#define MAXPARTITIONS 16 /* number of partitions */ + +/* HFS/DPME */ + +/* partition map structure from Inside Macintosh: Devices, SCSI Manager + * pp. 13-14. The partition map always begins on physical block 1. + * + * With the exception of block 0, all blocks on the disk must belong to + * exactly one partition. The partition map itself belongs to a partition + * of type `APPLE_PARTITION_MAP', and is not limited in size by anything + * other than available disk space. The partition map is not necessarily + * the first partition listed. + */ +struct part_map_entry { +#define PART_ENTRY_MAGIC 0x504d + u_int16_t pmSig; /* partition signature */ + u_int16_t pmSigPad; /* (reserved) */ + u_int32_t pmMapBlkCnt; /* number of blocks in partition map */ + u_int32_t pmPyPartStart; /* first physical block of partition */ + u_int32_t pmPartBlkCnt; /* number of blocks in partition */ + char pmPartName[32]; /* partition name */ + char pmPartType[32]; /* partition type */ + u_int32_t pmLgDataStart; /* first logical block of data area */ + u_int32_t pmDataCnt; /* number of blocks in data area */ + u_int32_t pmPartStatus; /* partition status information */ + u_int32_t pmLgBootStart; /* first logical block of boot code */ + u_int32_t pmBootSize; /* size of boot code, in bytes */ + u_int32_t pmBootLoad; /* boot code load address */ + u_int32_t pmBootLoad2; /* (reserved) */ + u_int32_t pmBootEntry; /* boot code entry point */ + u_int32_t pmBootEntry2; /* (reserved) */ + u_int32_t pmBootCksum; /* boot code checksum */ + char pmProcessor[16]; /* processor type (e.g. "68020") */ + u_int8_t pmBootArgs[128]; /* A/UX boot arguments */ + /* we do not index the disk image as an array, + * leave out the on disk padding + */ +#if 0 + u_int8_t pad[248]; /* pad to end of block */ +#endif +}; + +#define PART_TYPE_DRIVER "APPLE_DRIVER" +#define PART_TYPE_DRIVER43 "APPLE_DRIVER43" +#define PART_TYPE_DRIVERATA "APPLE_DRIVER_ATA" +#define PART_TYPE_DRIVERIOKIT "APPLE_DRIVER_IOKIT" +#define PART_TYPE_FWDRIVER "APPLE_FWDRIVER" +#define PART_TYPE_FWB_COMPONENT "FWB DRIVER COMPONENTS" +#define PART_TYPE_FREE "APPLE_FREE" +#define PART_TYPE_MAC "APPLE_HFS" +#define PART_TYPE_OPENBSD "OPENBSD" + +#endif /* _MACHINE_DISKLABEL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/elf.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/elf.h new file mode 100644 index 000000000000..ed920f5d1ecf --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/elf.h @@ -0,0 +1,3 @@ +/* $OpenBSD: elf.h,v 1.1 2024/07/14 19:33:59 miod Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/endian.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/endian.h new file mode 100644 index 000000000000..4bc2fa0df57d --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/endian.h @@ -0,0 +1,3 @@ +/* $OpenBSD: endian.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/exec.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/exec.h new file mode 100644 index 000000000000..b283c6dd5f40 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/exec.h @@ -0,0 +1,3 @@ +/* $OpenBSD: exec.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/fenv.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/fenv.h new file mode 100644 index 000000000000..63244974f96c --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/fenv.h @@ -0,0 +1,3 @@ +/* $OpenBSD: fenv.h,v 1.2 2013/06/01 21:20:54 jasper Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/fpu.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/fpu.h new file mode 100644 index 000000000000..b3c92c2976a7 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/fpu.h @@ -0,0 +1,3 @@ +/* $OpenBSD: fpu.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/frame.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/frame.h new file mode 100644 index 000000000000..9edae57f9556 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/frame.h @@ -0,0 +1,3 @@ +/* $OpenBSD: frame.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/ieee.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/ieee.h new file mode 100644 index 000000000000..46e05aeea462 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/ieee.h @@ -0,0 +1,3 @@ +/* $OpenBSD: ieee.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/ieeefp.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/ieeefp.h new file mode 100644 index 000000000000..d42b97756f0a --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/ieeefp.h @@ -0,0 +1,3 @@ +/* $OpenBSD: ieeefp.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/intr.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/intr.h new file mode 100644 index 000000000000..e1a6b65ddc6d --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/intr.h @@ -0,0 +1,10 @@ +/* $OpenBSD: intr.h,v 1.9 2014/04/01 20:27:14 mpi Exp $ */ + +#include + +#ifndef _LOCORE +extern int intr_shared_edge; + +void install_extint(void (*handler)(void)); +void openpic_set_priority(int, int); +#endif \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/kcore.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/kcore.h new file mode 100644 index 000000000000..0f3da93e3835 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/kcore.h @@ -0,0 +1,3 @@ +/* $OpenBSD: kcore.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/limits.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/limits.h new file mode 100644 index 000000000000..3b2a85e186ec --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/limits.h @@ -0,0 +1,3 @@ +/* $OpenBSD: limits.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/loadfile_machdep.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/loadfile_machdep.h new file mode 100644 index 000000000000..5ec3bc68fac0 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/loadfile_machdep.h @@ -0,0 +1,49 @@ +/* $OpenBSD: loadfile_machdep.h,v 1.4 2015/07/17 20:44:39 miod Exp $ */ +/* $NetBSD: loadfile_machdep.h,v 1.1 1999/04/29 03:17:12 tsubai Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define BOOT_ELF +#define ELFSIZE 32 + +#define LOAD_KERNEL LOAD_ALL +#define COUNT_KERNEL COUNT_ALL + +#define LOADADDR(a) (((u_long)(a)) + offset) +#define ALIGNENTRY(a) ((u_long)(a)) +#define READ(f, b, c) read((f), (void *)LOADADDR(b), (c)) +#define BCOPY(s, d, c) memcpy((void *)LOADADDR(d), (void *)(s), (c)) +#define BZERO(d, c) memset((void *)LOADADDR(d), 0, (c)) +#define WARN(a) (void)(printf a, \ + printf((errno ? ": %s\n" : "\n"), \ + strerror(errno))) +#define PROGRESS(a) (void) printf a +#define ALLOC(a) alloc(a) +#define FREE(a, b) free(a, b) \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/mplock.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/mplock.h new file mode 100644 index 000000000000..7e82ab4902a5 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/mplock.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mplock.h,v 1.3 2015/06/26 11:15:32 dlg Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/mutex.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/mutex.h new file mode 100644 index 000000000000..06bd20011dae --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/mutex.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mutex.h,v 1.1 2007/03/22 19:26:28 kettenis Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/openpromio.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/openpromio.h new file mode 100644 index 000000000000..1b69c531fe40 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/openpromio.h @@ -0,0 +1,57 @@ +/* $OpenBSD: openpromio.h,v 1.1 2007/11/12 19:23:26 kettenis Exp $ */ +/* $NetBSD: openpromio.h,v 1.1.1.1 1998/06/20 04:58:52 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)openpromio.h 8.1 (Berkeley) 6/11/93 + */ + +struct opiocdesc { + int op_nodeid; /* passed or returned node id */ + int op_namelen; /* length of op_name */ + char *op_name; /* pointer to field name */ + int op_buflen; /* length of op_buf (value-result) */ + char *op_buf; /* pointer to field value */ +}; + +#define OPIOCGET _IOWR('O', 1, struct opiocdesc) /* get openprom field */ +#define OPIOCSET _IOW('O', 2, struct opiocdesc) /* set openprom field */ +#define OPIOCNEXTPROP _IOWR('O', 3, struct opiocdesc) /* get next property */ +#define OPIOCGETOPTNODE _IOR('O', 4, int) /* get openprom field */ +#define OPIOCGETNEXT _IOWR('O', 5, int) /* get next node of node */ +#define OPIOCGETCHILD _IOWR('O', 6, int) /* get first child of node */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/param.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/param.h new file mode 100644 index 000000000000..1aeadbe686a0 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/param.h @@ -0,0 +1,52 @@ +/* $OpenBSD: param.h,v 1.6 2014/04/07 16:29:06 deraadt Exp $ */ + +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ + +#ifdef _KERNEL +#ifndef _LOCORE +#include +#endif /* _LOCORE */ +#endif + +#include + +#define MACHINE "macppc" +#define _MACHINE macppc + +#define KERNBASE 0x100000 + +#define MSGBUFSIZE (4 * PAGE_SIZE) + +#endif /* _MACHINE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/pcb.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/pcb.h new file mode 100644 index 000000000000..ae453583b2f2 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/pcb.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pcb.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/pci_machdep.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/pci_machdep.h new file mode 100644 index 000000000000..443fe240afa0 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/pci_machdep.h @@ -0,0 +1,108 @@ +/* $OpenBSD: pci_machdep.h,v 1.4 2019/12/05 12:46:54 mpi Exp $ */ +/* $NetBSD: pci_machdep.h,v 1.7 2001/07/20 00:07:14 eeh Exp $ */ + +/* + * Copyright (c) 1999 Matthew R. Green + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_PCI_MACHDEP_H_ +#define _MACHINE_PCI_MACHDEP_H_ + +extern struct powerpc_bus_dma_tag pci_bus_dma_tag; + +/* + * Forward declarations. + */ +struct pci_attach_args; + +/* + * define some bits used to glue into the common PCI code. + */ + +typedef struct ppc_pci_chipset *pci_chipset_tag_t; + +typedef unsigned long pci_intr_handle_t; + +/* + * The stuuuuuuupid allegedly MI PCI code expects pcitag_t to be a + * scalar type. But we really need to store both the OFW node and + * the bus/device/function info in it. (We'd like to store more, + * like all the ofw properties, but we don't need to.) Luckily, + * both are 32-bit values, so we can squeeze them into a u_int64_t + * with a little help from some macros. + */ + +#define PCITAG_NODE(x) (int)(((x)>>32)&0xffffffff) +#define PCITAG_OFFSET(x) ((x)&0xffffffff) +#define PCITAG_BUS(t) ((PCITAG_OFFSET(t)>>16)&0xff) +#define PCITAG_DEV(t) ((PCITAG_OFFSET(t)>>11)&0x1f) +#define PCITAG_FUN(t) ((PCITAG_OFFSET(t)>>8)&0x7) +#define PCITAG_CREATE(n,b,d,f) (((uint64_t)(n)<<32)|((b)<<16)|((d)<<11)|((f)<<8)) +typedef uint64_t pcitag_t; + +struct ppc_pci_chipset { + void *pc_conf_v; + int pc_node; + int busnode[256]; + + pcireg_t (*pc_conf_read)(void *, pcitag_t, int); + void (*pc_conf_write)(void *, pcitag_t, int, pcireg_t); +}; + + +void pci_attach_hook(struct device *, struct device *, + struct pcibus_attach_args *); +int pci_bus_maxdevs(pci_chipset_tag_t, int); +pcitag_t pci_make_tag(pci_chipset_tag_t, int, int, int); +void pci_decompose_tag(pci_chipset_tag_t, pcitag_t, int *, int *, + int *); +int pci_conf_size(pci_chipset_tag_t, pcitag_t); +pcireg_t pci_conf_read(pci_chipset_tag_t, pcitag_t, int); +void pci_conf_write(pci_chipset_tag_t, pcitag_t, int, pcireg_t); +int pci_intr_map(struct pci_attach_args *, pci_intr_handle_t *); +int pci_intr_map_msi(struct pci_attach_args *, pci_intr_handle_t *); +#define pci_intr_map_msix(p, vec, ihp) (-1) +int pci_intr_line(pci_chipset_tag_t, pci_intr_handle_t); +const char *pci_intr_string(pci_chipset_tag_t, pci_intr_handle_t); +void *pci_intr_establish(pci_chipset_tag_t, pci_intr_handle_t, + int, int (*)(void *), void *, const char *); +void pci_intr_disestablish(pci_chipset_tag_t, void *); +int pci_ether_hw_addr(pci_chipset_tag_t, uint8_t *); + +#define pci_probe_device_hook(c, a) (0) + +#define pci_min_powerstate(c, t) (PCI_PMCSR_STATE_D3) +#define pci_set_powerstate_md(c, t, s, p) + +#define pci_dev_postattach(a, b) + +int ofw_intr_map(int, uint32_t *, uint32_t *); +int ofw_enumerate_pcibus(struct pci_softc *, + int (*match)(struct pci_attach_args *), + struct pci_attach_args *); + +#define PCI_MACHDEP_ENUMERATE_BUS ofw_enumerate_pcibus + +#endif /* _MACHINE_PCI_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/pio.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/pio.h new file mode 100644 index 000000000000..551a29a60388 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/pio.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pio.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/pmap.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/pmap.h new file mode 100644 index 000000000000..3bff9d021440 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/pmap.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pmap.h,v 1.5 2005/11/07 02:19:46 brad Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/proc.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/proc.h new file mode 100644 index 000000000000..9fb584cd31e6 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/proc.h @@ -0,0 +1,3 @@ +/* $OpenBSD: proc.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/profile.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/profile.h new file mode 100644 index 000000000000..6ef4ef31dd36 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/profile.h @@ -0,0 +1,3 @@ +/* $OpenBSD: profile.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/psl.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/psl.h new file mode 100644 index 000000000000..75712e28fa05 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/psl.h @@ -0,0 +1,3 @@ +/* $OpenBSD: psl.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/pte.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/pte.h new file mode 100644 index 000000000000..effc458c15b4 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/pte.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pte.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/ptrace.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/ptrace.h new file mode 100644 index 000000000000..8853814e4c0b --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/ptrace.h @@ -0,0 +1,3 @@ +/* $OpenBSD: ptrace.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/rbus_machdep.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/rbus_machdep.h new file mode 100644 index 000000000000..1c0cb27000d2 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/rbus_machdep.h @@ -0,0 +1,62 @@ +/* $OpenBSD: rbus_machdep.h,v 1.6 2011/03/23 16:54:36 pirofti Exp $ */ +/* $NetBSD: rbus_machdep.h,v 1.2 1999/10/15 06:43:05 haya Exp $ */ + +/* + * Copyright (c) 1999 + * HAYAKAWA Koichi. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#if !defined _MACHINE_RBUS_MACHDEP_H_ +#define _MACHINE_RBUS_MACHDEP_H_ + +struct pci_attach_args; /* XXX */ + +void _bus_space_unmap(bus_space_tag_t, bus_space_handle_t, + bus_size_t, bus_addr_t *); + +#define md_space_map(rbt, physaddr, size, flags, bshp) \ + bus_space_map((rbt)->rb_bt, (physaddr), (size), (flags), (bshp)) + +/* XXX */ +bus_addr_t bus_space_unmap_p(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t size); + + +#define md_space_unmap(rbt, bsh, size, adrp) \ + do { \ + *adrp = bus_space_unmap_p((rbt)->rb_bt, (bsh), (size)); \ + if ((rbt)->rb_bt->bus_io) { \ + *adrp = *adrp & 0xffff; \ + } \ + } while (0) + +rbus_tag_t rbus_pccbb_parent_io(struct device *self, + struct pci_attach_args *pa); +rbus_tag_t rbus_pccbb_parent_mem(struct device *self, + struct pci_attach_args *pa); + +void pccbb_attach_hook(struct device *, struct device *, + struct pci_attach_args *); + +#endif /* _MACHINE_RBUS_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/reg.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/reg.h new file mode 100644 index 000000000000..8162e439ce62 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/reg.h @@ -0,0 +1,3 @@ +/* $OpenBSD: reg.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/reloc.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/reloc.h new file mode 100644 index 000000000000..faca641c794e --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/reloc.h @@ -0,0 +1,3 @@ +/* $OpenBSD: reloc.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/setjmp.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/setjmp.h new file mode 100644 index 000000000000..da9cc287b3f9 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/setjmp.h @@ -0,0 +1,3 @@ +/* $OpenBSD: setjmp.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/signal.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/signal.h new file mode 100644 index 000000000000..fc14275006d4 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/signal.h @@ -0,0 +1,3 @@ +/* $OpenBSD: signal.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/spinlock.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/spinlock.h new file mode 100644 index 000000000000..37b542933587 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/spinlock.h @@ -0,0 +1,3 @@ +/* $OpenBSD: spinlock.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/tcb.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/tcb.h new file mode 100644 index 000000000000..406394c9402c --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/tcb.h @@ -0,0 +1,3 @@ +/* $OpenBSD: tcb.h,v 1.2 2013/06/01 21:20:54 jasper Exp $ */ +/* public domain */ +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/timetc.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/timetc.h new file mode 100644 index 000000000000..20d9dfb763ac --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/timetc.h @@ -0,0 +1,23 @@ +/* $OpenBSD: timetc.h,v 1.2 2020/07/17 20:15:43 gkoehler Exp $ */ +/* + * Copyright (c) 2020 Paul Irofti + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TIMETC_H_ +#define _MACHINE_TIMETC_H_ + +#define TC_TB 1 + +#endif /* _MACHINE_TIMETC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/trap.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/trap.h new file mode 100644 index 000000000000..4ceaa94f2bdb --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/trap.h @@ -0,0 +1,3 @@ +/* $OpenBSD: trap.h,v 1.1 2001/09/01 15:49:06 drahn Exp $ */ + +#include \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/vmparam.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/vmparam.h new file mode 100644 index 000000000000..a8578e273403 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/vmparam.h @@ -0,0 +1,99 @@ +/* $OpenBSD: vmparam.h,v 1.33 2024/01/30 16:43:22 deraadt Exp $ */ +/* $NetBSD: vmparam.h,v 1.1 1996/09/30 16:34:38 ws Exp $ */ + +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MACHINE_VMPARAM_H +#define MACHINE_VMPARAM_H + +#define USRSTACK VM_MAXUSER_ADDRESS + +#ifndef MAXTSIZ +#define MAXTSIZ (128*1024*1024) /* max text size */ +#endif + +#ifndef DFLDSIZ +#define DFLDSIZ (64*1024*1024) /* default data size */ +#endif + +#ifndef MAXDSIZ +#define MAXDSIZ (2UL*1024*1024*1024) /* max data size */ +#endif + +#ifndef BRKSIZ +#define BRKSIZ MAXDSIZ /* heap gap size */ +#endif + +#ifndef DFLSSIZ +#define DFLSSIZ (2*1024*1024) /* default stack size */ +#endif + +#ifndef MAXSSIZ +#define MAXSSIZ (32*1024*1024) /* max stack size */ +#endif + +#define STACKGAP_RANDOM 256*1024 + +/* + * Size of shared memory map + */ +#ifndef SHMMAXPGS +#define SHMMAXPGS 8192 /* 32mb */ +#endif + +/* + * Size of User Raw I/O map + */ +#define USRIOSIZE 1024 + +/* + * Would like to have MAX addresses = 0, but this doesn't (currently) work + */ +#define VM_MIN_ADDRESS ((vaddr_t)PAGE_SIZE) +#define VM_MAXUSER_ADDRESS ((vaddr_t)0xfffff000) +#define VM_MAX_ADDRESS VM_MAXUSER_ADDRESS +#define VM_MIN_KERNEL_ADDRESS ((vaddr_t)(PPC_KERNEL_SR << ADDR_SR_SHIFT)) + +/* map PIE into approximately the first quarter of user va space */ +#define VM_PIE_MIN_ADDR PAGE_SIZE +#define VM_PIE_MAX_ADDR 0x40000000 + +#define VM_KERN_ADDRESS_SIZE (PPC_SEGMENT_LENGTH - (32 * 1024 * 1024)) +#define VM_MAX_KERNEL_ADDRESS (VM_MIN_KERNEL_ADDRESS + VM_KERN_ADDRESS_SIZE) + +#define VM_PHYS_SIZE (USRIOSIZE * PAGE_SIZE) + +#define VM_PHYSSEG_MAX 32 /* actually we could have this many segments */ +#define VM_PHYSSEG_STRAT VM_PSTRAT_BSEARCH +#define VM_PHYSSEG_NOADD /* can't add RAM after vm_mem_init */ + +#endif \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/macppc/z8530var.h b/lib/libc/include/powerpc-openbsd-eabihf/macppc/z8530var.h new file mode 100644 index 000000000000..275214fc2d6e --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/macppc/z8530var.h @@ -0,0 +1,152 @@ +/* $OpenBSD: z8530var.h,v 1.11 2024/05/22 05:51:49 jsg Exp $ */ +/* $NetBSD: z8530var.h,v 1.5 2002/03/17 19:40:45 atatat Exp $ */ + +/* + * Copyright (c) 1994 Gordon W. Ross + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)zsvar.h 8.1 (Berkeley) 6/11/93 + */ + +#include +#include + +/* + * Clock source info structure, added here so xzs_chanstate works + */ +struct zsclksrc { + long clk; /* clock rate, in MHz, present on signal line */ + int flags; /* Specifies how this source can be used + (RTxC divided, RTxC BRG, PCLK BRG, TRxC divided) + and also if the source is "external" and if it + is changeable (by an ioctl ex.). The + source usage flags are used by the tty + child. The other bits tell zsloadchannelregs + if it should call an md signal source + changing routine. ZSC_VARIABLE says if + an ioctl should be able to change the + clock rate.*/ +}; +#define ZSC_PCLK 0x01 +#define ZSC_RTXBRG 0x02 +#define ZSC_RTXDIV 0x04 +#define ZSC_TRXDIV 0x08 +#define ZSC_VARIABLE 0x40 +#define ZSC_EXTERN 0x80 + +#define ZSC_BRG 0x03 +#define ZSC_DIV 0x0c + + +/* + * These are the machine-dependent (extended) variants of + * struct zs_chanstate and struct zsc_softc + */ +struct xzs_chanstate { + /* machine-independent part (First!)*/ + struct zs_chanstate xzs_cs; + /* machine-dependent extensions */ + int cs_hwflags; + int cs_chip; /* type of chip */ + /* Clock source info... */ + int cs_clock_count; /* how many signal sources available */ + struct zsclksrc cs_clocks[4]; /* info on available signal sources */ + long cs_cclk_flag; /* flag for current clock source */ + long cs_pclk_flag; /* flag for pending clock source */ + int cs_csource; /* current source # */ + int cs_psource; /* pending source # */ +}; + +struct zsc_softc { + struct device zsc_dev; /* base device */ + struct zs_chanstate *zsc_cs[2]; /* channel A and B soft state */ + /* Machine-dependent part follows... */ + void *zsc_softintr; + struct xzs_chanstate xzsc_xcs_store[2]; + dbdma_regmap_t *zsc_txdmareg[2]; + dbdma_command_t *zsc_txdmacmd[2]; + /* XXX tx only, for now */ +}; + +/* + * Functions to read and write individual registers in a channel. + * The ZS chip requires a 1.6 uSec. recovery time between accesses, + * and the Sun3 hardware does NOT take care of this for you. + * MacII hardware DOES take care of the delay for us. :-) + * XXX - Then these should be inline functions! -gwr + * Some clock-chirped macs lose serial ports. It could be that the + * hardware delay is tied to the CPU speed, and that the minimum delay + * no longer's respected. For them, ZS_DELAY might help. + * XXX - no one seems to want to try and check this -wrs + */ + +u_char zs_read_reg(struct zs_chanstate *cs, u_char reg); +u_char zs_read_csr(struct zs_chanstate *cs); +u_char zs_read_data(struct zs_chanstate *cs); + +void zs_write_reg(struct zs_chanstate *cs, u_char reg, u_char val); +void zs_write_csr(struct zs_chanstate *cs, u_char val); +void zs_write_data(struct zs_chanstate *cs, u_char val); + +/* XXX - Could define splzs() here instead of in psl.h */ +#define splzs spltty + +/* Hook for MD ioctl support */ +int zsmdioctl(struct zs_chanstate *cs, u_long cmd, caddr_t data); +/* XXX - This is a bit gross... */ +/* +#define ZS_MD_IOCTL(cs, cmd, data) zsmdioctl(cs, cmd, data) +*/ + +/* Callback for "external" clock sources */ +void zsmd_setclock(struct zs_chanstate *cs); +#define ZS_MD_SETCLK(cs) zsmd_setclock(cs) + +#define PCLK (9600 * 384) /* PCLK pin input clock rate */ + +/* The layout of this is hardware-dependent (padding, order). */ +struct zschan { + volatile u_char zc_csr; /* ctrl,status, and indirect access */ + u_char zc_xxx0[15]; + volatile u_char zc_data; /* data */ + u_char zc_xxx1[15]; +}; + +#ifndef ZSCCF_CHANNEL +#define ZSCCF_CHANNEL 0 +#define ZSCCF_CHANNEL_DEFAULT -1 +#endif \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/_float.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/_float.h new file mode 100644 index 000000000000..31988cbf8629 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/_float.h @@ -0,0 +1,71 @@ +/* $OpenBSD: _float.h,v 1.1 2012/06/26 16:12:44 deraadt Exp $ */ + +/* + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE__FLOAT_H_ +#define _MACHINE__FLOAT_H_ + +#define __FLT_RADIX 2 /* b */ +#define __FLT_ROUNDS __flt_rounds() +#define __FLT_EVAL_METHOD 0 /* no promotions */ + +#define __FLT_MANT_DIG 24 /* p */ +#define __FLT_EPSILON 1.19209290E-07F /* b**(1-p) */ +#define __FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ +#define __FLT_MIN_EXP (-125) /* emin */ +#define __FLT_MIN 1.17549435E-38F /* b**(emin-1) */ +#define __FLT_MIN_10_EXP (-37) /* ceil(log10(b**(emin-1))) */ +#define __FLT_MAX_EXP 128 /* emax */ +#define __FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ +#define __FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ + +#define __DBL_MANT_DIG 53 +#define __DBL_EPSILON 2.2204460492503131E-16 +#define __DBL_DIG 15 +#define __DBL_MIN_EXP (-1021) +#define __DBL_MIN 2.2250738585072014E-308 +#define __DBL_MIN_10_EXP (-307) +#define __DBL_MAX_EXP 1024 +#define __DBL_MAX 1.7976931348623157E+308 +#define __DBL_MAX_10_EXP 308 + +#define __LDBL_MANT_DIG DBL_MANT_DIG +#define __LDBL_EPSILON DBL_EPSILON +#define __LDBL_DIG DBL_DIG +#define __LDBL_MIN_EXP DBL_MIN_EXP +#define __LDBL_MIN DBL_MIN +#define __LDBL_MIN_10_EXP DBL_MIN_10_EXP +#define __LDBL_MAX_EXP DBL_MAX_EXP +#define __LDBL_MAX DBL_MAX +#define __LDBL_MAX_10_EXP DBL_MAX_10_EXP + +#define __DECIMAL_DIG 17 + +#endif /* _MACHINE__FLOAT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/_types.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/_types.h new file mode 100644 index 000000000000..e3d855f9a0db --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/_types.h @@ -0,0 +1,141 @@ +/* $OpenBSD: _types.h,v 1.25 2023/07/02 19:02:28 cheloha Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.3 (Berkeley) 1/5/94 + * @(#)ansi.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _POWERPC__TYPES_H_ +#define _POWERPC__TYPES_H_ + +#if defined(_KERNEL) +typedef struct label_t { + long val[25]; +} label_t; +#endif + +/* + * _ALIGN(p) rounds p (pointer or byte index) up to a correctly-aligned + * value for all data types (int, long, ...). The result is an + * unsigned long and must be cast to any desired pointer type. + * + * _ALIGNED_POINTER is a boolean macro that checks whether an address + * is valid to fetch data elements of type t from on this architecture. + * This does not reflect the optimal alignment, just the possibility + * (within reasonable limits). + */ +#define _ALIGNBYTES (sizeof(double) - 1) +#define _STACKALIGNBYTES 15 +#define _ALIGN(p) (((unsigned long)(p) + _ALIGNBYTES) & ~_ALIGNBYTES) +#define _ALIGNED_POINTER(p,t) ((((unsigned long)(p)) & (sizeof(t) - 1)) == 0) +#define _MAX_PAGE_SHIFT 12 /* same as PAGE_SHIFT */ + +/* 7.18.1.1 Exact-width integer types */ +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short __int16_t; +typedef unsigned short __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; +typedef long long __int64_t; +typedef unsigned long long __uint64_t; + +/* 7.18.1.2 Minimum-width integer types */ +typedef __int8_t __int_least8_t; +typedef __uint8_t __uint_least8_t; +typedef __int16_t __int_least16_t; +typedef __uint16_t __uint_least16_t; +typedef __int32_t __int_least32_t; +typedef __uint32_t __uint_least32_t; +typedef __int64_t __int_least64_t; +typedef __uint64_t __uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types */ +typedef __int32_t __int_fast8_t; +typedef __uint32_t __uint_fast8_t; +typedef __int32_t __int_fast16_t; +typedef __uint32_t __uint_fast16_t; +typedef __int32_t __int_fast32_t; +typedef __uint32_t __uint_fast32_t; +typedef __int64_t __int_fast64_t; +typedef __uint64_t __uint_fast64_t; +#define __INT_FAST8_MIN INT32_MIN +#define __INT_FAST16_MIN INT32_MIN +#define __INT_FAST32_MIN INT32_MIN +#define __INT_FAST64_MIN INT64_MIN +#define __INT_FAST8_MAX INT32_MAX +#define __INT_FAST16_MAX INT32_MAX +#define __INT_FAST32_MAX INT32_MAX +#define __INT_FAST64_MAX INT64_MAX +#define __UINT_FAST8_MAX UINT32_MAX +#define __UINT_FAST16_MAX UINT32_MAX +#define __UINT_FAST32_MAX UINT32_MAX +#define __UINT_FAST64_MAX UINT64_MAX + +/* 7.18.1.4 Integer types capable of holding object pointers */ +typedef long __intptr_t; +typedef unsigned long __uintptr_t; + +/* 7.18.1.5 Greatest-width integer types */ +typedef __int64_t __intmax_t; +typedef __uint64_t __uintmax_t; + +/* Register size */ +typedef long __register_t; + +/* VM system types */ +typedef unsigned long __vaddr_t; +typedef unsigned long __paddr_t; +typedef unsigned long __vsize_t; +typedef unsigned long __psize_t; + +/* Standard system types */ +typedef double __double_t; +typedef float __float_t; +typedef long __ptrdiff_t; +typedef unsigned long __size_t; +typedef long __ssize_t; +#if defined(__GNUC__) && __GNUC__ >= 3 +typedef __builtin_va_list __va_list; +#else +struct __va_list_tag; +typedef struct __va_list_tag * __va_list; +#endif + +/* Wide character support types */ +#ifndef __cplusplus +typedef int __wchar_t; +#endif +typedef int __wint_t; +typedef int __rune_t; +typedef void * __wctrans_t; +typedef void * __wctype_t; + +#endif /* _POWERPC__TYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/asm.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/asm.h new file mode 100644 index 000000000000..87f1863b3c24 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/asm.h @@ -0,0 +1,127 @@ +/* $OpenBSD: asm.h,v 1.19 2023/02/03 06:13:08 miod Exp $ */ +/* $NetBSD: asm.h,v 1.1 1996/09/30 16:34:20 ws Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 _POWERPC_ASM_H_ +#define _POWERPC_ASM_H_ + +#define _C_LABEL(x) x +#define _ASM_LABEL(x) x + +#ifdef __STDC__ +# define _TMP_LABEL(x) .L_ ## x +#else +# define _TMP_LABEL(x) .L_/**/x +#endif + +#define _ENTRY_NB(x) \ + .text; .align 2; .type x,@function; x: +#define _ENTRY(x) .globl x; _ENTRY_NB(x) + +#if defined(PROF) || defined(GPROF) +# define _PROF_PROLOGUE(y) \ + .section ".data"; \ + .align 2; \ +_TMP_LABEL(y):; \ + .long 0; \ + .section ".text"; \ + mflr 0; \ + addis 11, 11, _TMP_LABEL(y)@ha; \ + stw 0, 4(1); \ + addi 0, 11,_TMP_LABEL(y)@l; \ + bl _mcount; +#else +# define _PROF_PROLOGUE(y) +#endif + +#define ENTRY(y) _ENTRY(y); _PROF_PROLOGUE(y) +#define ENTRY_NB(y) _ENTRY_NB(y); _PROF_PROLOGUE(y) +#define ASENTRY(y) _ENTRY(y); _PROF_PROLOGUE(y) +#define END(y) .size y, . - y + +#define STRONG_ALIAS(alias,sym) \ + .global alias; .set alias,sym +#define WEAK_ALIAS(alias,sym) \ + .weak alias; .set alias,sym + +#if defined(_RET_PROTECTOR) +# if defined(__PIC__) +# define RETGUARD_LOAD_RANDOM(x, reg) \ + bcl 20, 31, 66f; \ +66: mflr reg; \ + addis reg, reg, (__retguard_ ## x - 66b)@ha; \ + lwz reg, ((__retguard_ ## x - 66b)@l)(reg) +# else +# define RETGUARD_LOAD_RANDOM(x, reg) \ + lis reg, (__retguard_ ## x)@ha; \ + lwz reg, ((__retguard_ ## x)@l)(reg) +# endif +# define RETGUARD_SETUP(x, reg, retreg) \ + mflr retreg; \ + RETGUARD_SETUP_LATE(x, reg, retreg) +# define RETGUARD_SETUP_LATE(x, reg, retreg) \ + RETGUARD_SYMBOL(x); \ + RETGUARD_LOAD_RANDOM(x, reg); \ + xor reg, reg, retreg +# define RETGUARD_CHECK(x, reg, retreg) \ + xor reg, reg, retreg; \ + RETGUARD_LOAD_RANDOM(x, %r10); \ + mtlr retreg; \ + twne reg, %r10 +# define RETGUARD_SAVE(reg, loc) \ + stw reg, loc +# define RETGUARD_LOAD(reg, loc) \ + lwz reg, loc +# define RETGUARD_SYMBOL(x) \ + .ifndef __retguard_ ## x; \ + .hidden __retguard_ ## x; \ + .type __retguard_ ## x,@object; \ + .pushsection .openbsd.randomdata.retguard,"aw",@progbits; \ + .weak __retguard_ ## x; \ + .p2align 2; \ + __retguard_ ## x: ; \ + .long 0; \ + .size __retguard_ ## x, 4; \ + .popsection; \ + .endif +#else +# define RETGUARD_LOAD_RANDOM(x, reg) +# define RETGUARD_SETUP(x, reg, retreg) +# define RETGUARD_SETUP_LATE(x, reg, retreg) +# define RETGUARD_CHECK(x, reg, retreg) +# define RETGUARD_SAVE(reg, loc) +# define RETGUARD_LOAD(reg, loc) +# define RETGUARD_SYMBOL(x) +#endif + +#endif /* !_POWERPC_ASM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/atomic.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/atomic.h new file mode 100644 index 000000000000..045305155158 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/atomic.h @@ -0,0 +1,292 @@ +/* $OpenBSD: atomic.h,v 1.13 2022/08/29 02:01:18 jsg Exp $ */ + +/* + * Copyright (c) 2015 Martin Pieuchot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +#ifndef _POWERPC_ATOMIC_H_ +#define _POWERPC_ATOMIC_H_ + +#if defined(_KERNEL) + +static __inline void +atomic_setbits_int(volatile unsigned int *uip, unsigned int v) +{ + unsigned int tmp; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " or %0, %1, %0 \n" + " stwcx. %0, 0, %2 \n" + " bne- 1b \n" + " sync" : "=&r" (tmp) : "r" (v), "r" (uip) : "cc", "memory"); +} + +static __inline void +atomic_clearbits_int(volatile unsigned int *uip, unsigned int v) +{ + unsigned int tmp; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " andc %0, %0, %1 \n" + " stwcx. %0, 0, %2 \n" + " bne- 1b \n" + " sync" : "=&r" (tmp) : "r" (v), "r" (uip) : "cc", "memory"); +} + +#endif /* defined(_KERNEL) */ + +static inline unsigned int +_atomic_cas_uint(volatile unsigned int *p, unsigned int o, unsigned int n) +{ + unsigned int rv; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " cmpw 0, %0, %4 \n" + " bne- 2f \n" + " stwcx. %3, 0, %2 \n" + " bne- 1b \n" + "2: \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (n), "r" (o) + : "cc"); + + return (rv); +} +#define atomic_cas_uint(_p, _o, _n) _atomic_cas_uint((_p), (_o), (_n)) + +static inline unsigned long +_atomic_cas_ulong(volatile unsigned long *p, unsigned long o, unsigned long n) +{ + unsigned long rv; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " cmpw 0, %0, %4 \n" + " bne- 2f \n" + " stwcx. %3, 0, %2 \n" + " bne- 1b \n" + "2: \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (n), "r" (o) + : "cc"); + + return (rv); +} +#define atomic_cas_ulong(_p, _o, _n) _atomic_cas_ulong((_p), (_o), (_n)) + +static inline void * +_atomic_cas_ptr(volatile void *pp, void *o, void *n) +{ + void * volatile *p = pp; + void *rv; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " cmpw 0, %0, %4 \n" + " bne- 2f \n" + " stwcx. %3, 0, %2 \n" + " bne- 1b \n" + "2: \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (n), "r" (o) + : "cc"); + + return (rv); +} +#define atomic_cas_ptr(_p, _o, _n) _atomic_cas_ptr((_p), (_o), (_n)) + +static inline unsigned int +_atomic_swap_uint(volatile unsigned int *p, unsigned int v) +{ + unsigned int rv; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " stwcx. %3, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (v) + : "cc"); + + return (rv); +} +#define atomic_swap_uint(_p, _v) _atomic_swap_uint((_p), (_v)) + +static inline unsigned long +_atomic_swap_ulong(volatile unsigned long *p, unsigned long v) +{ + unsigned long rv; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " stwcx. %3, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (v) + : "cc"); + + return (rv); +} +#define atomic_swap_ulong(_p, _v) _atomic_swap_ulong((_p), (_v)) + +static inline void * +_atomic_swap_ptr(volatile void *pp, void *v) +{ + void * volatile *p = pp; + void *rv; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " stwcx. %3, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (v) + : "cc"); + + return (rv); +} +#define atomic_swap_ptr(_p, _v) _atomic_swap_ptr((_p), (_v)) + +static inline unsigned int +_atomic_add_int_nv(volatile unsigned int *p, unsigned int v) +{ + unsigned int rv; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " add %0, %3, %0 \n" + " stwcx. %0, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (v) + : "cc", "xer"); + + return (rv); +} +#define atomic_add_int_nv(_p, _v) _atomic_add_int_nv((_p), (_v)) + +static inline unsigned long +_atomic_add_long_nv(volatile unsigned long *p, unsigned long v) +{ + unsigned long rv; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " add %0, %3, %0 \n" + " stwcx. %0, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (v) + : "cc", "xer"); + + return (rv); +} +#define atomic_add_long_nv(_p, _v) _atomic_add_long_nv((_p), (_v)) + +static inline unsigned int +_atomic_sub_int_nv(volatile unsigned int *p, unsigned int v) +{ + unsigned int rv; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " subf %0, %3, %0 \n" + " stwcx. %0, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (v) + : "cc", "xer"); + + return (rv); +} +#define atomic_sub_int_nv(_p, _v) _atomic_sub_int_nv((_p), (_v)) + +static inline unsigned long +_atomic_sub_long_nv(volatile unsigned long *p, unsigned long v) +{ + unsigned long rv; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " subf %0, %3, %0 \n" + " stwcx. %0, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (v) + : "cc", "xer"); + + return (rv); +} +#define atomic_sub_long_nv(_p, _v) _atomic_sub_long_nv((_p), (_v)) + +static inline unsigned int +_atomic_addic_int_nv(volatile unsigned int *p, unsigned int v) +{ + unsigned int rv; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " addic %0, %0, %3 \n" + " stwcx. %0, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "i" (v) + : "cc", "xer"); + + return (rv); +} +#define atomic_inc_int_nv(_p) _atomic_addic_int_nv((_p), 1) +#define atomic_dec_int_nv(_p) _atomic_addic_int_nv((_p), -1) + +static inline unsigned long +_atomic_addic_long_nv(volatile unsigned long *p, unsigned long v) +{ + unsigned long rv; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " addic %0, %0, %3 \n" + " stwcx. %0, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "i" (v) + : "cc", "xer"); + + return (rv); +} +#define atomic_inc_long_nv(_p) _atomic_addic_long_nv((_p), 1) +#define atomic_dec_long_nv(_p) _atomic_addic_long_nv((_p), -1) + +#define __membar(_f) do { __asm volatile(_f ::: "memory"); } while (0) + +#if defined(MULTIPROCESSOR) || !defined(_KERNEL) +#define membar_enter() __membar("isync") +#define membar_exit() __membar("sync") +#define membar_producer() __membar("sync") +#define membar_consumer() __membar("isync") +#define membar_sync() __membar("sync") +#else +#define membar_enter() __membar("") +#define membar_exit() __membar("") +#define membar_producer() __membar("") +#define membar_consumer() __membar("") +#define membar_sync() __membar("") +#endif + +#endif /* _POWERPC_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/bat.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/bat.h new file mode 100644 index 000000000000..dbd22251019c --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/bat.h @@ -0,0 +1,72 @@ +/* $OpenBSD: bat.h,v 1.6 2015/03/31 16:00:38 mpi Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 _POWERPC_BAT_H_ +#define _POWERPC_BAT_H_ + +struct bat { + u_int32_t batu; + u_int32_t batl; +}; + +#define BATU(vaddr,len) (((vaddr)&0xf0000000)|(len)|0x2) +#define BATL(raddr,wimg) (((raddr)&0xf0000000)|(wimg)|0x2) + +#define BAT_W 0x40 +#define BAT_I 0x20 +#define BAT_M 0x10 +#define BAT_G 0x08 + +#define BAT_BL_128K 0x00000000 +#define BAT_BL_256K 0x00000004 +#define BAT_BL_512K 0x0000000c +#define BAT_BL_1M 0x0000001c +#define BAT_BL_2M 0x0000003c +#define BAT_BL_4M 0x0000007c +#define BAT_BL_8M 0x000000fc +#define BAT_BL_16M 0x000001fc +#define BAT_BL_32M 0x000003fc +#define BAT_BL_64M 0x000007fc +#define BAT_BL_128M 0x00000ffc +#define BAT_BL_256M 0x00001ffc +/* Extended Block Lengths (7455+) */ +#define BAT_BL_512M 0x00003ffc +#define BAT_BL_1G 0x00007ffc +#define BAT_BL_2G 0x0000fffc +#define BAT_BL_4G 0x0001fffc + +#ifdef _KERNEL +extern struct bat battable[16]; +#endif + +#endif /* _POWERPC_BAT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/cdefs.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/cdefs.h new file mode 100644 index 000000000000..f84970e7aa04 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/cdefs.h @@ -0,0 +1,21 @@ +/* $OpenBSD: cdefs.h,v 1.7 2013/03/28 17:30:45 martynas Exp $ */ + +/* + * Written by J.T. Conklin 01/17/95. + * Public domain. + */ + +#ifndef _POWERPC_CDEFS_H_ +#define _POWERPC_CDEFS_H_ + +#define __strong_alias(alias,sym) \ + __asm__(".global " __STRING(alias) " ; " \ + __STRING(alias) " = " __STRING(sym)) +#define __weak_alias(alias,sym) \ + __asm__(".weak " __STRING(alias) " ; " \ + __STRING(alias) " = " __STRING(sym)) +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning." __STRING(sym) \ + " ; .ascii \"" msg "\" ; .text") + +#endif /* !_POWERPC_CDEFS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/cpu.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/cpu.h new file mode 100644 index 000000000000..4ce4264905f2 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/cpu.h @@ -0,0 +1,473 @@ +/* $OpenBSD: cpu.h,v 1.80 2025/04/07 15:43:00 gkoehler Exp $ */ +/* $NetBSD: cpu.h,v 1.1 1996/09/30 16:34:21 ws Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 _POWERPC_CPU_H_ +#define _POWERPC_CPU_H_ + +#include + +#include +#include +#include +#include + +struct cpu_info { + struct device *ci_dev; /* our device */ + struct schedstate_percpu ci_schedstate; /* scheduler state */ + + struct proc *ci_curproc; + + struct pcb *ci_curpcb; + struct pmap *ci_curpm; + struct proc *ci_fpuproc; + struct proc *ci_vecproc; + int ci_cpuid; + + volatile int ci_want_resched; + volatile int ci_cpl; + volatile int ci_ipending; + volatile int ci_dec_deferred; + + volatile int ci_flags; +#define CI_FLAGS_SLEEPING 2 + +#if defined(MULTIPROCESSOR) + struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM]; +#endif + + int ci_idepth; + char *ci_intstk; +#define CPUSAVE_LEN 8 + register_t ci_tempsave[CPUSAVE_LEN]; + register_t ci_ddbsave[CPUSAVE_LEN]; +#define DISISAVE_LEN 4 + register_t ci_disisave[DISISAVE_LEN]; + + struct clockqueue ci_queue; + + volatile int ci_ddb_paused; +#define CI_DDB_RUNNING 0 +#define CI_DDB_SHOULDSTOP 1 +#define CI_DDB_STOPPED 2 +#define CI_DDB_ENTERDDB 3 +#define CI_DDB_INDDB 4 + + u_int32_t ci_randseed; + +#ifdef DIAGNOSTIC + int ci_mutex_level; +#endif +#ifdef GPROF + struct gmonparam *ci_gmon; + struct clockintr ci_gmonclock; +#endif + char ci_panicbuf[512]; +}; + +static __inline struct cpu_info * +curcpu(void) +{ + struct cpu_info *ci; + + __asm volatile ("mfsprg %0,0" : "=r"(ci)); + return ci; +} + +#define curpcb (curcpu()->ci_curpcb) +#define curpm (curcpu()->ci_curpm) + +#define CPU_INFO_UNIT(ci) ((ci)->ci_dev ? (ci)->ci_dev->dv_unit : 0) + +#ifdef MULTIPROCESSOR + +#define PPC_MAXPROCS 4 + +static __inline int +cpu_number(void) +{ + int pir; + + pir = curcpu()->ci_cpuid; + return pir; +} + +void cpu_boot_secondary_processors(void); + +#define CPU_IS_PRIMARY(ci) ((ci)->ci_cpuid == 0) +#define CPU_IS_RUNNING(ci) 1 +#define CPU_INFO_ITERATOR int +#define CPU_INFO_FOREACH(cii, ci) \ + for (cii = 0, ci = &cpu_info[0]; cii < ncpusfound; cii++, ci++) + +void cpu_unidle(struct cpu_info *); + +#else + +#define PPC_MAXPROCS 1 + +#define cpu_number() 0 + +#define CPU_IS_PRIMARY(ci) 1 +#define CPU_IS_RUNNING(ci) 1 +#define CPU_INFO_ITERATOR int +#define CPU_INFO_FOREACH(cii, ci) \ + for (cii = 0, ci = curcpu(); ci != NULL; ci = NULL) + +#define cpu_unidle(ci) + +#endif + +#define CPU_BUSY_CYCLE() do {} while (0) + +#define MAXCPUS PPC_MAXPROCS + +extern struct cpu_info cpu_info[PPC_MAXPROCS]; + +#define CLKF_USERMODE(frame) (((frame)->srr1 & PSL_PR) != 0) +#define CLKF_PC(frame) ((frame)->srr0) +#define CLKF_INTR(frame) ((frame)->depth > 1) + +extern int ppc_cpuidle; +extern int ppc_proc_is_64b; +extern int ppc_nobat; + +void cpu_bootstrap(void); + +static inline unsigned int +cpu_rnd_messybits(void) +{ + unsigned int hi, lo; + + __asm volatile("mftbu %0; mftb %1" : "=r" (hi), "=r" (lo)); + + return (hi ^ lo); +} + +/* + * This is used during profiling to integrate system time. + */ +#define PROC_PC(p) (trapframe(p)->srr0) +#define PROC_STACK(p) (trapframe(p)->fixreg[1]) + +void delay(unsigned); +#define DELAY(n) delay(n) + +#define aston(p) ((p)->p_md.md_astpending = 1) + +/* + * Preempt the current process if in interrupt from user mode, + * or after the current trap/syscall if in system mode. + */ +#define need_resched(ci) \ +do { \ + ci->ci_want_resched = 1; \ + if (ci->ci_curproc != NULL) \ + aston(ci->ci_curproc); \ +} while (0) +#define clear_resched(ci) (ci)->ci_want_resched = 0 + +#define need_proftick(p) aston(p) + +void signotify(struct proc *); + +extern char *bootpath; + +#ifndef CACHELINESIZE +#define CACHELINESIZE 32 /* For now XXX */ +#endif + +static __inline void +syncicache(void *from, size_t len) +{ + size_t by, i; + + by = CACHELINESIZE; + i = 0; + do { + __asm volatile ("dcbst %0,%1" :: "r"(from), "r"(i)); + i += by; + } while (i < len); + __asm volatile ("sync"); + i = 0; + do { + __asm volatile ("icbi %0,%1" :: "r"(from), "r"(i)); + i += by; + } while (i < len); + __asm volatile ("sync; isync"); +} + +static __inline void +invdcache(void *from, int len) +{ + int l; + char *p = from; + + len = len + (((u_int32_t) from) & (CACHELINESIZE - 1)); + l = len; + + do { + __asm volatile ("dcbi 0,%0" :: "r"(p)); + p += CACHELINESIZE; + } while ((l -= CACHELINESIZE) > 0); + __asm volatile ("sync"); +} + +static __inline void +flushdcache(void *from, int len) +{ + int l; + char *p = from; + + len = len + (((u_int32_t) from) & (CACHELINESIZE - 1)); + l = len; + + do { + __asm volatile ("dcbf 0,%0" :: "r"(p)); + p += CACHELINESIZE; + } while ((l -= CACHELINESIZE) > 0); + __asm volatile ("sync"); +} + +#define FUNC_SPR(n, name) \ +static __inline u_int32_t ppc_mf ## name(void) \ +{ \ + u_int32_t ret; \ + __asm volatile ("mfspr %0," # n : "=r" (ret)); \ + return ret; \ +} \ +static __inline void ppc_mt ## name(u_int32_t val) \ +{ \ + __asm volatile ("mtspr "# n ",%0" :: "r" (val)); \ +} \ + +FUNC_SPR(0, mq) +FUNC_SPR(1, xer) +FUNC_SPR(4, rtcu) +FUNC_SPR(5, rtcl) +FUNC_SPR(8, lr) +FUNC_SPR(9, ctr) +FUNC_SPR(18, dsisr) +FUNC_SPR(19, dar) +FUNC_SPR(22, dec) +FUNC_SPR(25, sdr1) +FUNC_SPR(26, srr0) +FUNC_SPR(27, srr1) +FUNC_SPR(256, vrsave) +FUNC_SPR(272, sprg0) +FUNC_SPR(273, sprg1) +FUNC_SPR(274, sprg2) +FUNC_SPR(275, sprg3) +FUNC_SPR(280, asr) +FUNC_SPR(282, ear) +FUNC_SPR(287, pvr) +FUNC_SPR(311, hior) +FUNC_SPR(528, ibat0u) +FUNC_SPR(529, ibat0l) +FUNC_SPR(530, ibat1u) +FUNC_SPR(531, ibat1l) +FUNC_SPR(532, ibat2u) +FUNC_SPR(533, ibat2l) +FUNC_SPR(534, ibat3u) +FUNC_SPR(535, ibat3l) +FUNC_SPR(560, ibat4u) +FUNC_SPR(561, ibat4l) +FUNC_SPR(562, ibat5u) +FUNC_SPR(563, ibat5l) +FUNC_SPR(564, ibat6u) +FUNC_SPR(565, ibat6l) +FUNC_SPR(566, ibat7u) +FUNC_SPR(567, ibat7l) +FUNC_SPR(536, dbat0u) +FUNC_SPR(537, dbat0l) +FUNC_SPR(538, dbat1u) +FUNC_SPR(539, dbat1l) +FUNC_SPR(540, dbat2u) +FUNC_SPR(541, dbat2l) +FUNC_SPR(542, dbat3u) +FUNC_SPR(543, dbat3l) +FUNC_SPR(568, dbat4u) +FUNC_SPR(569, dbat4l) +FUNC_SPR(570, dbat5u) +FUNC_SPR(571, dbat5l) +FUNC_SPR(572, dbat6u) +FUNC_SPR(573, dbat6l) +FUNC_SPR(574, dbat7u) +FUNC_SPR(575, dbat7l) +FUNC_SPR(1009, hid1) +FUNC_SPR(1010, iabr) +FUNC_SPR(1017, l2cr) +FUNC_SPR(1018, l3cr) +FUNC_SPR(1013, dabr) +FUNC_SPR(1023, pir) + +static __inline u_int32_t +ppc_mftbl(void) +{ + int ret; + __asm volatile ("mftb %0" : "=r" (ret)); + return ret; +} + + +static __inline u_int64_t +ppc_mftb(void) +{ + u_long scratch; + u_int64_t tb; + + __asm volatile ("1: mftbu %0; mftb %L0; mftbu %1;" + " cmpw 0,%0,%1; bne 1b" : "=r"(tb), "=r"(scratch)); + return tb; +} + +static __inline void +ppc_mttb(u_int64_t tb) +{ + __asm volatile ("mttbl %0" :: "r"(0)); + __asm volatile ("mttbu %0" :: "r"((u_int32_t)(tb >> 32))); + __asm volatile ("mttbl %0" :: "r"((u_int32_t)(tb & 0xffffffff))); +} + +static __inline u_int32_t +ppc_mfmsr(void) +{ + int ret; + __asm volatile ("mfmsr %0" : "=r" (ret)); + return ret; +} + +static __inline void +ppc_mtmsr(u_int32_t val) +{ + __asm volatile ("mtmsr %0" :: "r" (val)); +} + +static __inline void +ppc_mtsrin(u_int32_t val, u_int32_t sn_shifted) +{ + __asm volatile ("mtsrin %0,%1" :: "r"(val), "r"(sn_shifted)); +} + +u_int64_t ppc64_mfscomc(void); +void ppc_mtscomc(u_int32_t); +void ppc64_mtscomc(u_int64_t); +u_int64_t ppc64_mfscomd(void); +void ppc_mtscomd(u_int32_t); +u_int32_t ppc_mfhid0(void); +void ppc_mthid0(u_int32_t); +u_int64_t ppc64_mfhid1(void); +void ppc64_mthid1(u_int64_t); +u_int64_t ppc64_mfhid4(void); +void ppc64_mthid4(u_int64_t); +u_int64_t ppc64_mfhid5(void); +void ppc64_mthid5(u_int64_t); + +#include + +/* + * General functions to enable and disable interrupts + * without having inlined assembly code in many functions. + */ +static __inline void +ppc_intr_enable(int enable) +{ + u_int32_t msr; + if (enable != 0) { + msr = ppc_mfmsr(); + msr |= PSL_EE; + ppc_mtmsr(msr); + } +} + +static __inline int +ppc_intr_disable(void) +{ + u_int32_t emsr, dmsr; + emsr = ppc_mfmsr(); + dmsr = emsr & ~PSL_EE; + ppc_mtmsr(dmsr); + return (emsr & PSL_EE); +} + +static inline void +intr_enable(void) +{ + ppc_mtmsr(ppc_mfmsr() | PSL_EE); +} + +static __inline u_long +intr_disable(void) +{ + return ppc_intr_disable(); +} + +static __inline void +intr_restore(u_long s) +{ + ppc_intr_enable(s); +} + +int ppc_cpuspeed(int *); + +/* + * PowerPC CPU types + */ +#define PPC_CPU_MPC601 1 +#define PPC_CPU_MPC603 3 +#define PPC_CPU_MPC604 4 +#define PPC_CPU_MPC603e 6 +#define PPC_CPU_MPC603ev 7 +#define PPC_CPU_MPC750 8 +#define PPC_CPU_MPC604ev 9 +#define PPC_CPU_MPC7400 12 +#define PPC_CPU_IBM970 0x0039 +#define PPC_CPU_IBM970FX 0x003c +#define PPC_CPU_IBM970MP 0x0044 +#define PPC_CPU_IBM750FX 0x7000 +#define PPC_CPU_MPC7410 0x800c +#define PPC_CPU_MPC7447A 0x8003 +#define PPC_CPU_MPC7448 0x8004 +#define PPC_CPU_MPC7450 0x8000 +#define PPC_CPU_MPC7455 0x8001 +#define PPC_CPU_MPC7457 0x8002 +#define PPC_CPU_MPC83xx 0x8083 + +/* + * This needs to be included late since it relies on definitions higher + * up in this file. + */ +#if defined(MULTIPROCESSOR) && defined(_KERNEL) +#include +#endif + +#endif /* _POWERPC_CPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/db_machdep.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/db_machdep.h new file mode 100644 index 000000000000..2f853f74879d --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/db_machdep.h @@ -0,0 +1,102 @@ +/* $OpenBSD: db_machdep.h,v 1.32 2022/01/28 18:37:40 gkoehler Exp $*/ +/* $NetBSD: db_machdep.h,v 1.13 1996/04/29 20:50:08 leo Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +/* + * Machine-dependent defines for new kernel debugger. + */ +#ifndef _POWERPC_DB_MACHDEP_H_ +#define _POWERPC_DB_MACHDEP_H_ + +#include +#include +#include +#include + +typedef long db_expr_t; /* expression - signed */ +typedef struct trapframe db_regs_t; +extern db_regs_t ddb_regs; /* register state */ + +#define PC_REGS(regs) ((regs)->srr0) +#define SET_PC_REGS(regs, value) PC_REGS(regs) = (value) + +#define BKPT_INST 0x7C810808 /* breakpoint instruction */ + +#define BKPT_SIZE (4) /* size of breakpoint inst */ +#define BKPT_SET(inst) (BKPT_INST) + +#define db_clear_single_step(regs) ((regs)->srr1 &= ~PSL_SE) +#define db_set_single_step(regs) ((regs)->srr1 |= PSL_SE) + +#define T_BREAKPOINT 0xffff +#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BREAKPOINT) + +#ifdef T_WATCHPOINT +#define IS_WATCHPOINT_TRAP(type, code) ((type) == T_WATCHPOINT) +#else +#define IS_WATCHPOINT_TRAP(type, code) 0 +#endif + +#define M_RTS 0xfc0007fe +#define I_RTS 0x4c000020 +#define M_BC 0xfc000000 +#define I_BC 0x40000000 +#define M_B 0xfc000000 +#define I_B 0x50000000 +#define M_RFI 0xfc0007fe +#define I_RFI 0x4c000064 + +#define inst_trap_return(ins) (((ins)&M_RFI) == I_RFI) +#define inst_return(ins) (((ins)&M_RTS) == I_RTS) +#define inst_call(ins) (((ins)&M_BC ) == I_BC || \ + ((ins)&M_B ) == I_B ) + +#ifdef _KERNEL + +int db_enter_ddb(void); +void db_startcpu(int); +void db_stopcpu(int); +void ppc_ipi_db(struct cpu_info *); + +void kdb_kintr(void *); +void db_save_regs(struct trapframe *frame); +void ddb_trap(void); +db_expr_t db_dumpframe(u_int32_t pframe, int (*pr)(const char *, ...)); + +#define DDB_STATE_NOT_RUNNING 0 +#define DDB_STATE_RUNNING 1 +#define DDB_STATE_EXITING 2 + +/* + * We define some of our own commands + */ +#define DB_MACHINE_COMMANDS + +#endif /* _KERNEL */ + +#endif /* _POWERPC_DB_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/elf.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/elf.h new file mode 100644 index 000000000000..d1a121fff937 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/elf.h @@ -0,0 +1,66 @@ +/* $OpenBSD: elf.h,v 1.3 2025/02/19 18:25:03 jca Exp $ */ + +/* + * This file is in the public domain. + */ + +#ifndef _MACHINE_ELF_H_ +#define _MACHINE_ELF_H_ + +/* + * CPU Feature Attributes + * + * These are defined in the PowerPC ELF ABI for the AT_HWCAP vector, + * and are exported to userland via the elf_aux_info(3) function. + */ + +#ifdef _KERNEL +# define __HAVE_CPU_HWCAP +# define __HAVE_CPU_HWCAP2 +extern unsigned long hwcap; +extern unsigned long hwcap2; +#endif /* _KERNEL */ + +#define PPC_FEATURE_32 0x80000000 /* Always true */ +#define PPC_FEATURE_64 0x40000000 /* Defined on a 64-bit CPU */ +#define PPC_FEATURE_601_INSTR 0x20000000 +#define PPC_FEATURE_HAS_ALTIVEC 0x10000000 +#define PPC_FEATURE_HAS_FPU 0x08000000 +#define PPC_FEATURE_HAS_MMU 0x04000000 +#define PPC_FEATURE_UNIFIED_CACHE 0x01000000 +#define PPC_FEATURE_HAS_SPE 0x00800000 +#define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000 +#define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000 +#define PPC_FEATURE_NO_TB 0x00100000 +#define PPC_FEATURE_POWER4 0x00080000 +#define PPC_FEATURE_POWER5 0x00040000 +#define PPC_FEATURE_POWER5_PLUS 0x00020000 +#define PPC_FEATURE_CELL 0x00010000 +#define PPC_FEATURE_BOOKE 0x00008000 +#define PPC_FEATURE_SMT 0x00004000 +#define PPC_FEATURE_ICACHE_SNOOP 0x00002000 +#define PPC_FEATURE_ARCH_2_05 0x00001000 +#define PPC_FEATURE_HAS_DFP 0x00000400 +#define PPC_FEATURE_POWER6_EXT 0x00000200 +#define PPC_FEATURE_ARCH_2_06 0x00000100 +#define PPC_FEATURE_HAS_VSX 0x00000080 +#define PPC_FEATURE_TRUE_LE 0x00000002 +#define PPC_FEATURE_PPC_LE 0x00000001 + +#define PPC_FEATURE2_ARCH_2_07 0x80000000 +#define PPC_FEATURE2_HTM 0x40000000 +#define PPC_FEATURE2_DSCR 0x20000000 +#define PPC_FEATURE2_EBB 0x10000000 +#define PPC_FEATURE2_ISEL 0x08000000 +#define PPC_FEATURE2_TAR 0x04000000 +#define PPC_FEATURE2_HAS_VEC_CRYPTO 0x02000000 +#define PPC_FEATURE2_HTM_NOSC 0x01000000 +#define PPC_FEATURE2_ARCH_3_00 0x00800000 +#define PPC_FEATURE2_HAS_IEEE128 0x00400000 +#define PPC_FEATURE2_DARN 0x00200000 +#define PPC_FEATURE2_SCV 0x00100000 +#define PPC_FEATURE2_HTM_NOSUSPEND 0x00080000 +#define PPC_FEATURE2_ARCH_3_1 0x00040000 +#define PPC_FEATURE2_MMA 0x00020000 + +#endif /* !_MACHINE_ELF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/endian.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/endian.h new file mode 100644 index 000000000000..6e97b5fbdcd3 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/endian.h @@ -0,0 +1,37 @@ +/* $OpenBSD: endian.h,v 1.22 2024/05/07 14:26:48 naddy Exp $ */ + +/*- + * Copyright (c) 1997 Niklas Hallqvist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _POWERPC_ENDIAN_H_ +#define _POWERPC_ENDIAN_H_ + +#undef _BIG_ENDIAN /* XXX - gcc may define _BIG_ENDIAN too */ +#define _BYTE_ORDER _BIG_ENDIAN + +#ifndef __FROM_SYS__ENDIAN +#include +#endif + +#endif /* _POWERPC_ENDIAN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/exec.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/exec.h new file mode 100644 index 000000000000..7ecfa3a6ded6 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/exec.h @@ -0,0 +1,46 @@ +/* $OpenBSD: exec.h,v 1.16 2021/03/11 11:16:59 jsg Exp $ */ + +/* + * Copyright (c) 1997 Per Fogelstrom, Opsycon AB. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: exec.h,v 1.16 2021/03/11 11:16:59 jsg Exp $ + */ + +#ifndef _POWERPC_EXEC_H_ +#define _POWERPC_EXEC_H_ + +#define __LDPGSZ 4096 /* linker page size */ + +#define ARCH_ELFSIZE 32 + +#define ELF_TARG_CLASS ELFCLASS32 +#define ELF_TARG_DATA ELFDATA2MSB +#define ELF_TARG_MACH EM_PPC + +/* Processor specific dynamic tag values. */ +#define DT_PPC_GOT 0x70000000 + +#define DT_PROCNUM (DT_PPC_GOT - DT_LOPROC + 1) + +#endif /* _POWERPC_EXEC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/fenv.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/fenv.h new file mode 100644 index 000000000000..dd0f8d80c902 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/fenv.h @@ -0,0 +1,96 @@ +/* $OpenBSD: fenv.h,v 1.3 2011/05/25 21:46:49 martynas Exp $ */ + +/* + * Copyright (c) 2011 Martynas Venckus + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _POWERPC_FENV_H_ +#define _POWERPC_FENV_H_ + +/* + * Each symbol representing a floating point exception expands to an integer + * constant expression with values, such that bitwise-inclusive ORs of _all + * combinations_ of the constants result in distinct values. + * + * We use such values that allow direct bitwise operations on FPU registers. + */ +#define FE_INEXACT 0x02000000 +#define FE_DIVBYZERO 0x04000000 +#define FE_UNDERFLOW 0x08000000 +#define FE_OVERFLOW 0x10000000 +#define FE_INVALID 0x20000000 +#define _FE_INVALID_SOFT 0x00000400 +#define _FE_INVALID_ALL 0x01f80700 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * exception constants defined above. + */ +#define FE_ALL_EXCEPT (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | \ + FE_OVERFLOW | FE_INVALID) +#define _MASK_SHIFT 22 + +/* + * Each symbol representing the rounding direction, expands to an integer + * constant expression whose value is distinct non-negative value. + * + * We use such values that allow direct bitwise operations on FPU registers. + */ +#define FE_TONEAREST 0x0 +#define FE_TOWARDZERO 0x1 +#define FE_UPWARD 0x2 +#define FE_DOWNWARD 0x3 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * rounding direction constants defined above. + */ +#define _ROUND_MASK (FE_TONEAREST | FE_TOWARDZERO | FE_UPWARD | \ + FE_DOWNWARD) + +/* + * fenv_t represents the entire floating-point environment. + */ +typedef unsigned int fenv_t; + +/* + * The following constant represents the default floating-point environment + * (that is, the one installed at program startup) and has type pointer to + * const-qualified fenv_t. + * + * It can be used as an argument to the functions within the header + * that manage the floating-point environment, namely fesetenv() and + * feupdateenv(). + */ +__BEGIN_DECLS +extern fenv_t __fe_dfl_env; +__END_DECLS +#define FE_DFL_ENV ((const fenv_t *)&__fe_dfl_env) + +/* + * fexcept_t represents the floating-point status flags collectively, including + * any status the implementation associates with the flags. + * + * A floating-point status flag is a system variable whose value is set (but + * never cleared) when a floating-point exception is raised, which occurs as a + * side effect of exceptional floating-point arithmetic to provide auxiliary + * information. + * + * A floating-point control mode is a system variable whose value may be set by + * the user to affect the subsequent behavior of floating-point arithmetic. + */ +typedef unsigned int fexcept_t; + +#endif /* !_POWERPC_FENV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/fpu.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/fpu.h new file mode 100644 index 000000000000..5018d672d82f --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/fpu.h @@ -0,0 +1,71 @@ +/* $OpenBSD: fpu.h,v 1.6 2005/10/09 14:52:12 drahn Exp $ */ + +/*- + * Copyright (C) 1996 Wolfgang Solfrank. + * Copyright (C) 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 _POWERPC_FPU_H_ +#define _POWERPC_FPU_H_ + +#define FPCSR_FX 0x80000000 +#define FPCSR_FEX 0x40000000 +#define FPCSR_VX 0x20000000 +#define FPCSR_OX 0x10000000 +#define FPCSR_UX 0x08000000 +#define FPCSR_ZX 0x04000000 +#define FPCSR_XX 0x02000000 +#define FPCSR_VXSNAN 0x01000000 +#define FPCSR_VXISI 0x00800000 +#define FPCSR_VXIDI 0x00400000 +#define FPCSR_VXZDZ 0x00200000 +#define FPCSR_VXIMZ 0x00100000 +#define FPCSR_VXVC 0x00080000 +#define FPCSR_FR 0x00040000 +#define FPCSR_FI 0x00020000 +#define FPCSR_FPRF 0x0001f000 +#define FPCSR_C 0x00010000 +#define FPCSR_FPCC 0x0000f000 +#define FPCSR_FL 0x00008000 +#define FPCSR_FG 0x00004000 +#define FPCSR_FE 0x00002000 +#define FPCSR_FU 0x00001000 +#define FPCSR_VXSOFT 0x00000400 +#define FPCSR_VXSQRT 0x00000200 +#define FPCSR_VXCVI 0x00000100 +#define FPCSR_VE 0x00000080 +#define FPCSR_OE 0x00000040 +#define FPCSR_UE 0x00000020 +#define FPCSR_ZE 0x00000010 +#define FPCSR_XE 0x00000008 +#define FPCSR_NI 0x00000004 +#define FPCSR_RN 0x00000003 + +void enable_fpu(struct proc *p); +void save_fpu(void); +#endif /* _POWERPC_FPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/frame.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/frame.h new file mode 100644 index 000000000000..90edbe7a184b --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/frame.h @@ -0,0 +1,79 @@ +/* $OpenBSD: frame.h,v 1.8 2024/11/05 21:47:00 miod Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 _POWERPC_FRAME_H_ +#define _POWERPC_FRAME_H_ + +/* + * This is to ensure alignment of the stackpointer + */ +#define FRAMELEN roundup(sizeof(struct trapframe) + 8, 16) +#define trapframe(p) ((struct trapframe *)((void *)(p)->p_addr + USPACE - FRAMELEN + 8)) + +struct switchframe { + register_t sp; + int fill; + int user_sr; + int cr; + register_t fixreg2; + register_t fixreg[19]; /* R13-R31 */ +}; + +struct clockframe { + register_t srr1; + register_t srr0; + int unused; + int depth; +}; + +/* + * Call frame for PowerPC used during fork. + */ +struct callframe { + register_t sp; + register_t lr; + register_t r30; + register_t r31; +}; + +struct sigframe { + int sf_signum; + siginfo_t *sf_sip; + struct sigcontext sf_sc; + siginfo_t sf_si; +}; + +struct fpsig { + double f[14]; /* f0 - f13 are volatile */ + double fpscr; +}; +#endif /* _POWERPC_FRAME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/hid.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/hid.h new file mode 100644 index 000000000000..970012500558 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/hid.h @@ -0,0 +1,158 @@ +/* $OpenBSD: hid.h,v 1.1 2013/10/31 08:26:12 mpi Exp $ */ + +/*- + * Copyright (c) 2000 Tsubai Masanari. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: hid.h,v 1.2 2001/08/22 21:05:25 matt Exp $ + */ + +#ifndef _POWERPC_HID_H_ +#define _POWERPC_HID_H_ + +/* Hardware Implementation Dependent registers for the PowerPC */ + +#define HID0_EMCP 0x80000000 /* Enable machine check pin */ +#define HID0_DBP 0x40000000 /* Disable 60x bus parity generation */ +#define HID0_EBA 0x20000000 /* Enable 60x bus address parity checking */ +#define HID0_EBD 0x10000000 /* Enable 60x bus data parity checking */ +#define HID0_BCLK 0x08000000 /* CLK_OUT clock type selection */ +#define HID0_EICE 0x04000000 /* Enable ICE output */ +#define HID0_TBEN 0x04000000 /* Time base enable (7450) */ +#define HID0_ECLK 0x02000000 /* CLK_OUT clock type selection */ +#define HID0_PAR 0x01000000 /* Disable precharge of ARTRY */ +#define HID0_STEN 0x01000000 /* Software table search enable (7450) */ +#define HID0_DEEPNAP 0x01000000 /* Enable deep nap mode (970) */ +#define HID0_HBATEN 0x00800000 /* High BAT enable (74[45][578]) */ +#define HID0_DOZE 0x00800000 /* Enable doze mode */ +#define HID0_NAP 0x00400000 /* Enable nap mode */ +#define HID0_SLEEP 0x00200000 /* Enable sleep mode */ +#define HID0_DPM 0x00100000 /* Enable Dynamic power management */ +#define HID0_RISEG 0x00080000 /* Read I-SEG */ +#define HID0_TG 0x00040000 /* Timebase Granularity (OEA64) */ +#define HID0_BHTCLR 0x00040000 /* Clear branch history table (7450) */ +#define HID0_EIEC 0x00040000 /* Enable internal error checking */ +#define HID0_XAEN 0x00020000 /* Enable eXtended Addressing (7450) */ +#define HID0_NHR 0x00010000 /* Not hard reset */ +#define HID0_ICE 0x00008000 /* Enable i-cache */ +#define HID0_DCE 0x00004000 /* Enable d-cache */ +#define HID0_ILOCK 0x00002000 /* i-cache lock */ +#define HID0_DLOCK 0x00001000 /* d-cache lock */ +#define HID0_ICFI 0x00000800 /* i-cache flush invalidate */ +#define HID0_DCFI 0x00000400 /* d-cache flush invalidate */ +#define HID0_SPD 0x00000200 /* Disable speculative cache access */ +#define HID0_XBSEN 0x00000100 /* Extended BAT block-size enable (7457) */ +#define HID0_IFEM 0x00000100 /* Enable M-bit for I-fetch */ +#define HID0_XBSEN 0x00000100 /* Extended BAT block size enable (7455+) */ +#define HID0_SGE 0x00000080 /* Enable store gathering */ +#define HID0_DCFA 0x00000040 /* Data cache flush assist */ +#define HID0_BTIC 0x00000020 /* Enable BTIC */ +#define HID0_LRSTK 0x00000010 /* Link register stack enable (7450) */ +#define HID0_ABE 0x00000008 /* Enable address broadcast */ +#define HID0_FOLD 0x00000008 /* Branch folding enable (7450) */ +#define HID0_BHT 0x00000004 /* Enable branch history table */ +#define HID0_BTCD 0x00000002 /* Branch target addr cache disable (604) */ +#define HID0_NOPTI 0x00000001 /* No-op the dcbt(st) */ + +#define HID0_603_BITMASK \ + "\20" \ + "\040EMCP\037DBP\036EBA\035EBD\034BCLK\033EICE\032ECLK\031PAR" \ + "\030DOZE\027NAP\026SLEEP\025DPM\024RISEG\023EIEC\022res\021NHR" \ + "\020ICE\017DCE\016ILOCK\015DLOCK\014ICFI\013DCFI\012SPD\011IFEM" \ + "\010SGE\007DCFA\006BTIC\005FBIOB\004ABE\003BHT\002NOPDST\001NOPTI" + +#define HID0_7450_BITMASK \ + "\20" \ + "\040EMCP\037b1\036b2\035b3\034b4\033TBEN\032b6\031STEN" \ + "\030HBATEN\027NAP\026SLEEP\025DPM\024b12\023BHTCLR\022XAEN\021NHR" \ + "\020ICE\017DCE\016ILOCK\015DLOCK\014ICFI\013DCFI\012SPD\011XBSEN" \ + "\010SGE\007b25\006BTIC\005LRSTK\004FOLD\003BHT\002NOPDST\001NOPTI" + +#define HID0_970_BITMASK \ + "\20" \ + "\040ONEPPC\037SINGLE\036ISYNCSC\035SERGP\031DEEPNAP\030DOZE" \ + "\027NAP\025DPM\023TG\022HANGDETECT\021NHR\020INORDER" \ + "\016TBCTRL\015TBEN\012CIABREN\011HDICEEN" \ + "\010ENTHERM\001ENATTN" + +/* + * HID0 bit definitions per cpu model + * + * bit 603 604 750 7400 7410 7450 7457 + * 0 EMCP EMCP EMCP EMCP EMCP - - + * 1 - ECP DBP - - - - + * 2 EBA EBA EBA EBA EDA - - + * 3 EBD EBD EBD EBD EBD - - + * 4 SBCLK - BCLK BCKL BCLK - - + * 5 EICE - - - - TBEN TBEN + * 6 ECLK - ECLK ECLK ECLK - - + * 7 PAR PAR PAR PAR PAR STEN STEN + * 8 DOZE - DOZE DOZE DOZE - HBATEN + * 9 NAP - NAP NAP NAP NAP NAP + * 10 SLEEP - SLEEP SLEEP SLEEP SLEEP SLEEP + * 11 DPM - DPM DPM DPM DPM DPM + * 12 RISEG - - RISEG - - - + * 13 - - - EIEC EIEC BHTCLR BHTCLR + * 14 - - - - - XAEN XAEN + * 15 - NHR NHR NHR NHR NHR NHR + * 16 ICE ICE ICE ICE ICE ICE ICE + * 17 DCE DCE DCE DCE DCE DCE DCE + * 18 ILOCK ILOCK ILOCK ILOCK ILOCK ILOCK ILOCK + * 19 DLOCK DLOCK DLOCK DLOCK DLOCK DLOCK DLOCK + * 20 ICFI ICFI ICFI ICFI ICFI ICFI ICFI + * 21 DCFI DCFI DCFI DCFI DCFI DCFI DCFI + * 22 - - SPD SPD SPG SPD SPD + * 23 - - IFEM IFTT IFTT - XBSEN + * 24 - SIE SGE SGE SGE SGE SGE + * 25 - - DCFA DCFA DCFA - - + * 26 - - BTIC BTIC BTIC BTIC BTIC + * 27 FBIOB - - - - LRSTK LRSTK + * 28 - - ABE - - FOLD FOLD + * 29 - BHT BHT BHT BHT BHT BHT + * 30 - - - NOPDST NOPDST NOPDST NOPDST + * 31 NOOPTI - NOOPTI NOPTI NOPTI NOPTI NOPTI + * + * 604: ECP = Enable cache parity checking + * 604: SIE = Serial instruction execution disable + * 604: BTCD = Branch target address cache disable + * 7450: TBEN = Time Base Enable + * 7450: STEN = Software table lookup enable + * 7450: BHTCLR = Branch history clear + * 7450: XAEN = Extended Addressing Enabled + * 7450: LRSTK = Link Register Stack Enable + * 7450: FOLD = Branch folding enable + * 7457: HBATEN = High BAT Enable + * 7457: XBSEN = Extended BAT Block Size Enable + */ + +#define HID1_EMCP 0x80000000 /* Machine Check Signal Enable */ +#define HID1_EBA 0x20000000 /* 60x bus address parity checking */ +#define HID1_EBD 0x10000000 /* 60x bus data parity checking */ +#define HID1_BCLK 0x08000000 /* CLK_OUT */ +#define HID1_ECLK 0x02000000 /* CLK_OUT */ +#define HID1_PAR 0x01000000 /* Disable precharge for ... */ +#define HID1_DFS4 0x00800000 /* Dynamic freq scaling / 4 (7448) */ +#define HID1_DFS2 0x00400000 /* Dynamic freq scaling / 2 (7447A) */ + +#endif /* _POWERPC_HID_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/ieee.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/ieee.h new file mode 100644 index 000000000000..30d5caed1d9a --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/ieee.h @@ -0,0 +1,119 @@ +/* $OpenBSD: ieee.h,v 1.5 2008/09/07 20:36:07 martynas Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ieee.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * ieee.h defines the machine-dependent layout of the machine's IEEE + * floating point. It does *not* define (yet?) any of the rounding + * mode bits, exceptions, and so forth. + */ + +/* + * Define the number of bits in each fraction and exponent. + * + * k k+1 + * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented + * + * (-exp_bias+1) + * as fractions that look like 0.fffff x 2 . This means that + * + * -126 + * the number 0.10000 x 2 , for instance, is the same as the normalized + * + * -127 -128 + * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero + * + * -129 + * in the fraction; to represent 2 , we need two, and so on. This + * + * (-exp_bias-fracbits+1) + * implies that the smallest denormalized number is 2 + * + * for whichever format we are talking about: for single precision, for + * + * -126 -149 + * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and + * + * -149 == -127 - 23 + 1. + */ +#define SNG_EXPBITS 8 +#define SNG_FRACBITS 23 + +#define DBL_EXPBITS 11 +#define DBL_FRACHBITS 20 +#define DBL_FRACLBITS 32 +#define DBL_FRACBITS 52 + +struct ieee_single { + u_int sng_sign:1; + u_int sng_exp:8; + u_int sng_frac:23; +}; + +struct ieee_double { + u_int dbl_sign:1; + u_int dbl_exp:11; + u_int dbl_frach:20; + u_int dbl_fracl; +}; + +/* + * Floats whose exponent is in [1..INFNAN) (of whatever type) are + * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. + * Floats whose exponent is zero are either zero (iff all fraction + * bits are zero) or subnormal values. + * + * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its + * high fraction; if the bit is set, it is a `quiet NaN'. + */ +#define SNG_EXP_INFNAN 255 +#define DBL_EXP_INFNAN 2047 + +#if 0 +#define SNG_QUIETNAN (1 << 22) +#define DBL_QUIETNAN (1 << 19) +#endif + +/* + * Exponent biases. + */ +#define SNG_EXP_BIAS 127 +#define DBL_EXP_BIAS 1023 \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/ieeefp.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/ieeefp.h new file mode 100644 index 000000000000..c6f38a7a8832 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/ieeefp.h @@ -0,0 +1,25 @@ +/* $OpenBSD: ieeefp.h,v 1.7 2004/05/03 16:53:24 drahn Exp $ */ +/* $NetBSD: ieeefp.h,v 1.2 1999/07/07 01:52:26 danw Exp $ */ +/* + * Written by J.T. Conklin, Apr 6, 1995 + * Public domain. + */ + +#ifndef _POWERPC_IEEEFP_H_ +#define _POWERPC_IEEEFP_H_ + +typedef int fp_except; +#define FP_X_IMP 0x01 /* imprecise (loss of precision) */ +#define FP_X_DZ 0x02 /* divide-by-zero exception */ +#define FP_X_UFL 0x04 /* underflow exception */ +#define FP_X_OFL 0x08 /* overflow exception */ +#define FP_X_INV 0x10 /* invalid operation exception */ + +typedef enum { + FP_RN=0, /* round to nearest representable number */ + FP_RZ=1, /* round to zero (truncate) */ + FP_RP=2, /* round toward positive infinity */ + FP_RM=3 /* round toward negative infinity */ +} fp_rnd; + +#endif /* _POWERPC_IEEEFP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/intr.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/intr.h new file mode 100644 index 000000000000..552a8e48d2b2 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/intr.h @@ -0,0 +1,170 @@ +/* $OpenBSD: intr.h,v 1.57 2025/05/10 09:54:17 visa Exp $ */ + +/* + * Copyright (c) 1997 Per Fogelstrom, Opsycon AB and RTMX Inc, USA. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed under OpenBSD by + * Per Fogelstrom, Opsycon AB, Sweden for RTMX Inc, North Carolina USA. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _POWERPC_INTR_H_ +#define _POWERPC_INTR_H_ + +#define IPL_NONE 0 +#define IPL_SOFTCLOCK 2 +#define IPL_SOFTNET 3 +#define IPL_SOFTTTY 4 +#define IPL_BIO 5 +#define IPL_NET 6 +#define IPL_TTY 7 +#define IPL_VM 8 +#define IPL_AUDIO 9 +#define IPL_CLOCK 10 +#define IPL_SCHED 11 +#define IPL_HIGH 12 +#define IPL_NUM 13 + +#define IPL_MPFLOOR IPL_TTY +#define IPL_MPSAFE 0x100 + +#define IST_NONE 0 +#define IST_PULSE 1 +#define IST_EDGE 2 +#define IST_LEVEL 3 + +#define __USE_MI_SOFTINTR + +#include + +#if defined(_KERNEL) && !defined(_LOCORE) + +#include +#include + +#define PPC_NIRQ 66 +#define PPC_CLK_IRQ 64 +#define PPC_STAT_IRQ 65 + +int splraise(int); +int spllower(int); +void splx(int); + +typedef int (ppc_splraise_t) (int); +typedef int (ppc_spllower_t) (int); +typedef void (ppc_splx_t) (int); + +extern struct ppc_intr_func { + ppc_splraise_t *raise; + ppc_spllower_t *lower; + ppc_splx_t *x; +}ppc_intr_func; + +extern int ppc_smask[IPL_NUM]; + +void ppc_smask_init(void); +char *ppc_intr_typename(int type); + +void do_pending_int(void); + +/* SPL asserts */ +#ifdef DIAGNOSTIC +/* + * Although this function is implemented in MI code, it must be in this MD + * header because we don't want this header to include MI includes. + */ +void splassert_fail(int, int, const char *); +extern int splassert_ctl; +void splassert_check(int, const char *); +#define splassert(__wantipl) do { \ + if (splassert_ctl > 0) { \ + splassert_check(__wantipl, __func__); \ + } \ +} while (0) +#define splsoftassert(wantipl) splassert(wantipl) +#else +#define splassert(wantipl) do { /* nada */ } while (0) +#define splsoftassert(wantipl) do { /* nada */ } while (0) +#endif + +#define set_sint(p) atomic_setbits_int(&curcpu()->ci_ipending, p) + +#define splbio() splraise(IPL_BIO) +#define splnet() splraise(IPL_NET) +#define spltty() splraise(IPL_TTY) +#define splaudio() splraise(IPL_AUDIO) +#define splclock() splraise(IPL_CLOCK) +#define splvm() splraise(IPL_VM) +#define splsched() splhigh() +#define splstatclock() splhigh() +#define splsoftclock() splraise(IPL_SOFTCLOCK) +#define splsoftnet() splraise(IPL_SOFTNET) +#define splsofttty() splraise(IPL_SOFTTTY) + +#define SI_TO_IRQBIT(x) (1 << (x)) + +void softintr(int); +void dosoftint(int); + +#define splhigh() splraise(IPL_HIGH) +#define spl0() spllower(IPL_NONE) + +/* + * Interrupt control struct used to control the ICU setup. + */ + +struct intrhand { + TAILQ_ENTRY(intrhand) ih_list; + int (*ih_fun)(void *); + void *ih_arg; + struct evcount ih_count; + int ih_type; + int ih_level; + int ih_flags; + int ih_irq; + const char *ih_what; +}; + +struct intrq { + TAILQ_HEAD(, intrhand) iq_list; /* handler list */ + int iq_ipl; /* IPL_ to mask while handling */ + int iq_ist; /* share type */ +}; + +extern int ppc_configed_intr_cnt; +#define MAX_PRECONF_INTR 16 +extern struct intrhand ppc_configed_intr[MAX_PRECONF_INTR]; + +void intr_barrier(void *); + +#define PPC_IPI_NOP 0 +#define PPC_IPI_DDB 1 + +void ppc_send_ipi(struct cpu_info *, int); + +#endif /* _LOCORE */ +#endif /* _POWERPC_INTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/kcore.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/kcore.h new file mode 100644 index 000000000000..d7df5d2d2971 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/kcore.h @@ -0,0 +1,46 @@ +/* $OpenBSD: kcore.h,v 1.4 2005/12/17 07:31:26 miod Exp $ */ +/* $NetBSD: kcore.h,v 1.1 1996/09/30 16:34:26 ws Exp $ */ + +/*- + * Copyright (C) 1996 Wolfgang Solfrank. + * Copyright (C) 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 _POWERPC_KCORE_H_ +#define _POWERPC_KCORE_H_ + +#define NPHYS_RAM_SEGS 4 + +typedef struct cpu_kcore_hdr { + paddr_t ptable; /* Phys address of page table */ + paddr_t potable; /* Phys address of page overflow table */ + phys_ram_seg_t ram_segs[NPHYS_RAM_SEGS]; +} cpu_kcore_hdr_t; + +#endif /* _POWERPC_KCORE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/limits.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/limits.h new file mode 100644 index 000000000000..399509a33adb --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/limits.h @@ -0,0 +1,52 @@ +/* $OpenBSD: limits.h,v 1.18 2015/04/30 13:42:08 millert Exp $ */ +/* $NetBSD: limits.h,v 1.1 1996/09/30 16:34:28 ws Exp $ */ + +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 _POWERPC_LIMITS_H_ +#define _POWERPC_LIMITS_H_ + +#include + +#if __POSIX_VISIBLE || __XPG_VISIBLE +#define SSIZE_MAX LONG_MAX /* max value for a ssize_t */ +#endif + +#if __BSD_VISIBLE +#define SIZE_T_MAX ULONG_MAX /* max value for a size_t (historic) */ + +#define UQUAD_MAX 0xffffffffffffffffULL /* max unsigned quad */ +#define QUAD_MAX 0x7fffffffffffffffLL /* max signed quad */ +#define QUAD_MIN (-0x7fffffffffffffffLL-1) /* min signed quad */ +#endif /* __BSD_VISIBLE */ + +#endif /* _POWERPC_LIMITS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/mplock.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/mplock.h new file mode 100644 index 000000000000..1c6d42553dfe --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/mplock.h @@ -0,0 +1,52 @@ +/* $OpenBSD: mplock.h,v 1.7 2024/09/04 07:54:51 mglocker Exp $ */ + +/* + * Copyright (c) 2004 Niklas Hallqvist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _POWERPC_MPLOCK_H_ +#define _POWERPC_MPLOCK_H_ + +#define __USE_MI_MPLOCK + +/* + * __ppc_lock exists because pte_spill_r() can't use __mp_lock. + * Really simple spinlock implementation with recursive capabilities. + * Correctness is paramount, no fanciness allowed. + */ + +struct __ppc_lock { + struct cpu_info *volatile mpl_cpu; + long mpl_count; +}; + +#ifndef _LOCORE + +#define PPC_LOCK_INITIALIZER { NULL, 0 } + +void __ppc_lock(struct __ppc_lock *); +void __ppc_unlock(struct __ppc_lock *); + +#endif + +#endif /* !_POWERPC_MPLOCK_H */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/mutex.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/mutex.h new file mode 100644 index 000000000000..a3f8e6dd1965 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/mutex.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mutex.h,v 1.9 2018/01/25 15:06:29 mpi Exp $ */ + +#define __USE_MI_MUTEX \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/param.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/param.h new file mode 100644 index 000000000000..435fcbea4cdf --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/param.h @@ -0,0 +1,74 @@ +/* $OpenBSD: param.h,v 1.39 2023/12/14 13:26:49 claudio Exp $ */ + +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 _POWERPC_PARAM_H_ +#define _POWERPC_PARAM_H_ + +#ifdef _KERNEL +#ifndef _LOCORE +#include +#endif /* _LOCORE */ +#endif + +#define MACHINE_ARCH "powerpc" +#define _MACHINE_ARCH powerpc +#define MID_MACHINE MID_POWERPC + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define PAGE_MASK (PAGE_SIZE - 1) + +#ifdef _KERNEL + +#define NBPG PAGE_SIZE +#define PGSHIFT PAGE_SHIFT +#define PGOFSET PAGE_MASK + +#define UPAGES 4 /* pages of u-area */ +#define USPACE (UPAGES * PAGE_SIZE) /* total size of u-area */ +#define USPACE_ALIGN 0 /* u-area alignment 0-none */ + +#define NMBCLUSTERS (32 * 1024) /* max cluster allocation */ + +/* + * Fixed segments + */ +#define PPC_USER_SR 13 +#define PPC_KERNEL_SR 14 +#define PPC_KERNEL_SEG0 0xfffff0 +#define PPC_KERNEL_SEGMENT (PPC_KERNEL_SEG0 + PPC_KERNEL_SR) +#define PPC_USER_ADDR ((void *)(PPC_USER_SR << ADDR_SR_SHIFT)) + +#endif /* _KERNEL */ + +#endif /* _POWERPC_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/pcb.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/pcb.h new file mode 100644 index 000000000000..4bfd679c4783 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/pcb.h @@ -0,0 +1,67 @@ +/* $OpenBSD: pcb.h,v 1.15 2015/07/29 18:52:44 miod Exp $ */ +/* $NetBSD: pcb.h,v 1.1 1996/09/30 16:34:29 ws Exp $ */ + +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 _POWERPC_PCB_H_ +#define _POWERPC_PCB_H_ + +#include + + +typedef struct __faultbuf { + int pc; + int sp; + int cr; + int regs[20]; +} faultbuf; + +struct pcb { + struct pmap *pcb_pm; /* pmap of our vmspace */ + struct pmap *pcb_pmreal; /* real address of above */ + register_t pcb_sp; /* saved SP */ + faultbuf *pcb_onfault; /* For use during copyin/copyout */ + int pcb_flags; +#define PCB_FPU 1 /* Process had FPU initialized */ + struct fpu { + double fpr[32]; + double fpcsr; /* FPCSR stored as double for easier access */ + } pcb_fpu; /* Floating point processor */ + struct vreg *pcb_vr; /* Vector unit */ + struct cpu_info *pcb_fpcpu; + struct cpu_info *pcb_veccpu; +}; + +#ifdef _KERNEL +extern struct proc *fpuproc; +int setfault(faultbuf *env) __returns_twice; +#endif +#endif /* _POWERPC_PCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/pio.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/pio.h new file mode 100644 index 000000000000..3b9e4602b4d9 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/pio.h @@ -0,0 +1,181 @@ +/* $OpenBSD: pio.h,v 1.9 2002/09/15 09:01:59 deraadt Exp $ */ + +/* + * Copyright (c) 1997 Per Fogelstrom, Opsycon AB and RTMX Inc, USA. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed under OpenBSD by + * Per Fogelstrom Opsycon AB for RTMX Inc, North Carolina, USA. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _POWERPC_PIO_H_ +#define _POWERPC_PIO_H_ +/* + * I/O macros. + */ +void *mapiodev(paddr_t pa, psize_t len); +void unmapiodev(void * va, psize_t len); + +static __inline void +__outb(volatile u_int8_t *a, int v) +{ + *a = v; + __asm__ volatile("eieio"); +} + +static __inline void +__outw(volatile u_int16_t *a, u_int16_t v) +{ + *a = v; + __asm__ volatile("eieio"); +} + +static __inline void +__outl(volatile u_int32_t *a, int v) +{ + *a = v; + __asm__ volatile("eieio"); +} + +static __inline void +__outwrb(volatile u_int16_t *a, u_int16_t v) +{ + u_int32_t _p_ = (u_int32_t)a; + + __asm__ volatile("sthbrx %0, 0, %1" :: "r"(v), "r"(_p_)); + __asm__ volatile("eieio"); +} + +static __inline void +__outlrb(volatile u_int32_t *a, u_int32_t v) +{ + u_int32_t _p_ = (u_int32_t)a; + + __asm__ volatile("stwbrx %0, 0, %1" :: "r"(v), "r"(_p_)); + __asm__ volatile("eieio"); +} + +static __inline u_int8_t +__inb(volatile u_int8_t *a) +{ + u_int8_t _v_; + + __asm__ volatile("eieio"); + _v_ = *a; + return _v_; +} + +static __inline u_int16_t +__inw(volatile u_int16_t *a) +{ + u_int16_t _v_; + + __asm__ volatile("eieio"); + _v_ = *a; + return _v_; +} + +static __inline u_int32_t +__inl(volatile u_int32_t *a) +{ + u_int32_t _v_; + + __asm__ volatile("eieio"); + _v_ = *a; + return _v_; +} + +static __inline u_int16_t +__inwrb(volatile u_int16_t *a) +{ + u_int16_t _v_; + u_int32_t _p_ = (u_int32_t)a; + + __asm__ volatile("eieio"); + __asm__ volatile("lhbrx %0, 0, %1" : "=r"(_v_) : "r"(_p_)); + return _v_; +} + +static __inline u_int32_t +__inlrb(volatile u_int32_t *a) +{ + u_int32_t _v_; + u_int32_t _p_ = (u_int32_t)a; + + __asm__ volatile("eieio"); + __asm__ volatile("lwbrx %0, 0, %1" : "=r"(_v_) : "r"(_p_)); + return _v_; +} + + +#define outb(a,v) (__outb((volatile u_int8_t *)(a), v)) +#define out8(a,v) outb(a,v) +#define outw(a,v) (__outw((volatile u_int16_t *)(a), v)) +#define out16(a,v) outw(a,v) +#define outl(a,v) (__outl((volatile u_int32_t *)(a), v)) +#define out32(a,v) outl(a,v) +#define inb(a) (__inb((volatile u_int8_t *)(a))) +#define in8(a) inb(a) +#define inw(a) (__inw((volatile u_int16_t *)(a))) +#define in16(a) inw(a) +#define inl(a) (__inl((volatile u_int32_t *)(a))) +#define in32(a) inl(a) + +#define out8rb(a,v) outb(a,v) +#define outwrb(a,v) (__outwrb((volatile u_int16_t *)(a), v)) +#define out16rb(a,v) outwrb(a,v) +#define outlrb(a,v) (__outlrb((volatile u_int32_t *)(a), v)) +#define out32rb(a,v) outlrb(a,v) +#define in8rb(a) inb(a) +#define inwrb(a) (__inwrb((volatile u_int16_t *)(a))) +#define in16rb(a) inwrb(a) +#define inlrb(a) (__inlrb((volatile u_int32_t *)(a))) +#define in32rb(a) inlrb(a) + +#ifdef DEBUG_SPEC +static __inline void +__flash_led(bits, count) + int bits; +{ + int i, v = 0; + + if(bits == 0) { + v = 1; bits = 3; + } + bits &= 3; + count += count; + v |= (*(volatile u_int8_t *)(MPC106_V_ISA_IO_SPACE + 0x01f4)) & ~3; + while(count--) { + v ^= bits; + for(i = 100000; i > 0; i--) + *(volatile u_int8_t *)(MPC106_V_ISA_IO_SPACE + 0x01f4) = v; + } + *(u_int8_t *)(MPC106_V_ISA_IO_SPACE + 0x01f4) &= ~3; +} +#endif /* DEBUG */ + +#endif /*_POWERPC_PIO_H_*/ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/pmap.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/pmap.h new file mode 100644 index 000000000000..4311f9d15929 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/pmap.h @@ -0,0 +1,186 @@ +/* $OpenBSD: pmap.h,v 1.66 2024/06/18 12:37:29 jsg Exp $ */ +/* $NetBSD: pmap.h,v 1.1 1996/09/30 16:34:29 ws Exp $ */ + +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 _POWERPC_PMAP_H_ +#define _POWERPC_PMAP_H_ + +#include + +/* + * Segment registers + */ +#ifndef _LOCORE +typedef u_int sr_t; +#endif /* _LOCORE */ +#define SR_TYPE 0x80000000 +#define SR_SUKEY 0x40000000 +#define SR_PRKEY 0x20000000 +#define SR_NOEXEC 0x10000000 +#define SR_VSID 0x00ffffff +/* + * bit + * 3 2 2 2 2 1 1 1 1 1 0 + * 1 8 7 4 0 9 6 5 2 1 0 + * |XXXX|XXXX XXXX|XXXX XXXX|XXXX XXXX XXXX + * + * bits 28 - 31 contain SR + * bits 20 - 27 contain L1 for VtoP translation + * bits 12 - 19 contain L2 for VtoP translation + * bits 0 - 11 contain page offset + */ +#ifndef _LOCORE +/* V->P mapping data */ +#define VP_SR_SIZE 16 +#define VP_SR_MASK (VP_SR_SIZE-1) +#define VP_SR_POS 28 +#define VP_IDX1_SIZE 256 +#define VP_IDX1_MASK (VP_IDX1_SIZE-1) +#define VP_IDX1_POS 20 +#define VP_IDX2_SIZE 256 +#define VP_IDX2_MASK (VP_IDX2_SIZE-1) +#define VP_IDX2_POS 12 + +/* cache flags */ +#define PMAP_CACHE_DEFAULT 0 /* WB cache managed mem, devices not */ +#define PMAP_CACHE_CI 1 /* cache inhibit */ +#define PMAP_CACHE_WT 2 /* writethru */ +#define PMAP_CACHE_WB 3 /* writeback */ + +#include +#include + +#ifdef _KERNEL + +/* + * Pmap stuff + */ +struct pmap { + sr_t pm_sr[16]; /* segments used in this pmap */ + struct pmapvp *pm_vp[VP_SR_SIZE]; /* virtual to physical table */ + u_int32_t pm_exec[16]; /* segments used in this pmap */ + int pm_refs; /* ref count */ + struct pmap_statistics pm_stats; /* pmap statistics */ + struct mutex pm_mtx; /* protect VP table */ +}; + +/* + * Segment handling stuff + */ +#define PPC_SEGMENT_LENGTH 0x10000000 +#define PPC_SEGMENT_MASK 0xf0000000 + +/* + * Some system constants + */ +#ifndef NPMAPS +#define NPMAPS 32768 /* Number of pmaps in system */ +#endif + +typedef struct pmap *pmap_t; + +extern struct pmap kernel_pmap_; +#define pmap_kernel() (&kernel_pmap_) + + +#define pmap_clear_modify(pg) pmap_clear_attrs((pg), PG_PMAP_MOD) +#define pmap_clear_reference(pg) pmap_clear_attrs((pg), PG_PMAP_REF) +#define pmap_is_modified(pg) pmap_test_attrs((pg), PG_PMAP_MOD) +#define pmap_is_referenced(pg) pmap_test_attrs((pg), PG_PMAP_REF) + +#define pmap_unwire(pm, va) +#define pmap_update(pmap) /* nothing (yet) */ + +#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) + +/* + * Alternate mapping methods for pool. + * Really simple. 0x0->0x80000000 contain 1->1 mappings of the physical + * memory. - XXX + */ +#define pmap_map_direct(pg) ((vaddr_t)VM_PAGE_TO_PHYS(pg)) +#define pmap_unmap_direct(va) PHYS_TO_VM_PAGE((paddr_t)va) +#define __HAVE_PMAP_DIRECT + +void pmap_bootstrap(u_int kernelstart, u_int kernelend); +void pmap_enable_mmu(); + +int pmap_clear_attrs(struct vm_page *, unsigned int); +int pmap_test_attrs(struct vm_page *, unsigned int); + +void pmap_release(struct pmap *); + +#ifdef ALTIVEC +int pmap_copyinsn(pmap_t, vaddr_t, uint32_t *); +#endif + +void pmap_real_memory(vaddr_t *start, vsize_t *size); + +int pte_spill_v(struct pmap *pm, u_int32_t va, u_int32_t dsisr, int exec_fault); +int reserve_dumppages(caddr_t p); + +#define pmap_init_percpu() do { /* nothing */ } while (0) +#define pmap_unuse_final(p) /* nothing */ +#define pmap_remove_holes(vm) do { /* nothing */ } while (0) + +#define PMAP_CHECK_COPYIN (ppc_proc_is_64b == 0) + +#define PMAP_STEAL_MEMORY + +#define PG_PMAP_MOD PG_PMAP0 +#define PG_PMAP_REF PG_PMAP1 +#define PG_PMAP_EXE PG_PMAP2 +#define PG_PMAP_UC PG_PMAP3 + +/* + * MD flags that we use for pmap_enter (in the pa): + */ +#define PMAP_PA_MASK ~((paddr_t)PAGE_MASK) /* to remove the flags */ +#define PMAP_NOCACHE 0x1 /* map uncached */ +#define PMAP_WT 0x2 /* map write-through */ + +#endif /* _KERNEL */ + +struct vm_page_md { + struct mutex pv_mtx; + LIST_HEAD(,pte_desc) pv_list; +}; + +#define VM_MDPAGE_INIT(pg) do { \ + mtx_init(&(pg)->mdpage.pv_mtx, IPL_VM); \ + LIST_INIT(&((pg)->mdpage.pv_list)); \ +} while (0) + +#endif /* _LOCORE */ + +#endif /* _POWERPC_PMAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/powerpc.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/powerpc.h new file mode 100644 index 000000000000..39eac3da6683 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/powerpc.h @@ -0,0 +1,53 @@ +/* $OpenBSD: powerpc.h,v 1.8 2014/04/01 20:42:39 mpi Exp $ */ +/* $NetBSD: powerpc.h,v 1.1 1996/09/30 16:34:30 ws Exp $ */ + +/* + * Copyright (C) 1996 Wolfgang Solfrank. + * Copyright (C) 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 _POWERPC_POWERPC_H_ +#define _POWERPC_POWERPC_H_ + +struct mem_region { + vaddr_t start; + vsize_t size; +}; + +void ppc_mem_regions(struct mem_region **, struct mem_region **); + +struct dumpmem { + vaddr_t start; + vsize_t end; +}; + +extern struct dumpmem dumpmem[VM_PHYSSEG_MAX]; +extern u_int ndumpmem; + +#endif /* _POWERPC_POWERPC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/proc.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/proc.h new file mode 100644 index 000000000000..03f932b2b4de --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/proc.h @@ -0,0 +1,45 @@ +/* $OpenBSD: proc.h,v 1.8 2017/04/13 03:52:25 guenther Exp $ */ +/* $NetBSD: proc.h,v 1.1 1996/09/30 16:34:31 ws Exp $ */ + +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 _POWERPC_PROC_H_ +#define _POWERPC_PROC_H_ + +/* + * Machine-dependent part of the proc structure + */ +struct mdproc { + volatile int md_astpending; +}; + +#endif /* _POWERPC_PROC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/profile.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/profile.h new file mode 100644 index 000000000000..19c9818c87f1 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/profile.h @@ -0,0 +1,78 @@ +/* $OpenBSD: profile.h,v 1.7 2013/08/19 08:39:30 mpi Exp $ */ + +/* + * Copyright (c) 1998 Dale Rahn. + * All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#define MCOUNT \ + __asm__(" \ + .section \".text\" \n\ + .align 2 \n\ + .globl _mcount \n\ + .type _mcount,@function \n\ + _mcount: \n\ + lwz 11, 4(1) \n\ + mflr 0 \n\ + stw 0, 4(1) \n\ + stwu 1, -48(1) \n\ + stw 3, 8(1) \n\ + stw 4, 12(1) \n\ + stw 5, 16(1) \n\ + stw 6, 20(1) \n\ + stw 7, 24(1) \n\ + stw 8, 28(1) \n\ + stw 9, 32(1) \n\ + stw 10,36(1) \n\ + stw 11,40(1) \n\ + mr 4, 0 \n\ + mr 3, 11 \n\ + bl __mcount \n\ + lwz 3, 8(1) \n\ + lwz 4, 12(1) \n\ + lwz 5, 16(1) \n\ + lwz 6, 20(1) \n\ + lwz 7, 24(1) \n\ + lwz 8, 28(1) \n\ + lwz 9, 32(1) \n\ + lwz 10,36(1) \n\ + lwz 11,40(1) \n\ + addi 1, 1, 48 \n\ + lwz 0, 4(1) \n\ + mtlr 11 \n\ + stw 11, 4(1) \n\ + mtctr 0 \n\ + bctr \n\ + .Lfe2: \n\ + .size _mcount, .Lfe2-_mcount \n\ + "); +#define _MCOUNT_DECL static void __mcount +#ifdef _KERNEL +#define MCOUNT_ENTER \ + __asm volatile("mfmsr %0" : "=r"(s)); \ + s &= ~PSL_POW; \ + __asm volatile("mtmsr %0" :: "r"(s & ~PSL_EE)) + +#define MCOUNT_EXIT \ + __asm volatile("mtmsr %0" :: "r"(s)) +#endif /* _KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/psl.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/psl.h new file mode 100644 index 000000000000..020a93e43fcb --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/psl.h @@ -0,0 +1,78 @@ +/* $OpenBSD: psl.h,v 1.5 2001/11/13 14:31:52 drahn Exp $ */ +/* $NetBSD: psl.h,v 1.1 1996/09/30 16:34:32 ws Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 _POWERPC_PSL_H_ +#define _POWERPC_PSL_H_ + +/* + * Flags in MSR: + */ +#define PSL_VEC 0x02000000 /* AltiVec vector unit available */ +#define PSL_POW 0x00040000 +#define PSL_ILE 0x00010000 +#define PSL_EE 0x00008000 +#define PSL_PR 0x00004000 +#define PSL_FP 0x00002000 +#define PSL_ME 0x00001000 +#define PSL_FE0 0x00000800 +#define PSL_SE 0x00000400 +#define PSL_BE 0x00000200 +#define PSL_FE1 0x00000100 +#define PSL_IP 0x00000040 +#define PSL_IR 0x00000020 +#define PSL_DR 0x00000010 +#define PSL_RI 0x00000002 +#define PSL_LE 0x00000001 + +/* + * Floating-point exception modes: + */ +#define PSL_FE_DIS 0 +#define PSL_FE_NONREC PSL_FE1 +#define PSL_FE_REC PSL_FE0 +#define PSL_FE_PREC (PSL_FE0 | PSL_FE1) +#define PSL_FE_DFLT PSL_FE_DIS + +/* + * Note that PSL_POW and PSL_ILE are not in the saved copy of the MSR + */ +#define PSL_MBO 0 +#define PSL_MBZ 0 + +#define PSL_USERSET (PSL_EE | PSL_PR | PSL_ME | PSL_IR | PSL_DR | PSL_RI) + +#define PSL_USERSTATIC (PSL_USERSET | PSL_IP | 0x87c0008c) + +#include + +#endif /* _POWERPC_PSL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/pte.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/pte.h new file mode 100644 index 000000000000..239b19bd1904 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/pte.h @@ -0,0 +1,129 @@ +/* $OpenBSD: pte.h,v 1.11 2023/01/31 01:27:58 gkoehler Exp $ */ +/* $NetBSD: pte.h,v 1.1 1996/09/30 16:34:32 ws Exp $ */ + +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 _POWERPC_PTE_H_ +#define _POWERPC_PTE_H_ + +/* + * Page Table Entries + */ +#ifndef _LOCORE +struct pte_32 { + u_int32_t pte_hi; + u_int32_t pte_lo; +}; +struct pte_64 { + u_int64_t pte_hi; + u_int64_t pte_lo; +}; +#endif /* _LOCORE */ + +/* 32 bit */ +/* High word: */ +#define PTE_VALID_32 0x80000000 +#define PTE_VSID_SHIFT_32 7 +#define PTE_HID_32 0x00000040 +#define PTE_API_32 0x0000003f + /* Low word: */ +#define PTE_RPGN_32 0xfffff000 +#define PTE_REF_32 0x00000100 +#define PTE_CHG_32 0x00000080 +#define PTE_WIM_32 0x00000078 +#define PTE_W_32 0x00000040 +#define PTE_EXE_32 0x00000040 /* only used in pmap_attr, same as PTE_W */ +#define PTE_I_32 0x00000020 +#define PTE_M_32 0x00000010 +#define PTE_G_32 0x00000008 +#define PTE_PP_32 0x00000003 +#define PTE_RO_32 0x00000003 +#define PTE_RW_32 0x00000002 + + +/* 64 bit */ +/* High doubleword: */ +#define PTE_VALID_64 0x0000000000000001ULL +#define PTE_AVPN_SHIFT_64 7 +#define PTE_AVPN_64 0xffffffffffffff80ULL +#define PTE_API_SHIFT_64 7 +#define PTE_API_64 0x0000000000000f80ULL +#define PTE_VSID_SHIFT_64 12 +#define PTE_VSID_64 0xfffffffffffff000ULL +#define PTE_HID_64 0x0000000000000002ULL +/* Low word: */ +#define PTE_RPGN_64 0x3ffffffffffff000ULL +#define PTE_AC_64 0x0000000000000200ULL +#define PTE_REF_64 0x0000000000000100ULL +#define PTE_CHG_64 0x0000000000000080ULL +#define PTE_WIMG_64 0x0000000000000078ULL +#define PTE_W_64 0x0000000000000040ULL +#define PTE_EXE_64 PTE_W +#define PTE_I_64 0x0000000000000020ULL +#define PTE_M_64 0x0000000000000010ULL +#define PTE_G_64 0x0000000000000008ULL +#define PTE_N_64 0x0000000000000004ULL +#define PTE_PP_64 0x0000000000000003ULL +#define PTE_RO_64 0x0000000000000003ULL +#define PTE_RW_64 0x0000000000000002ULL + +/* + * Extract bits from address + */ +#define ADDR_SR_SHIFT 28 +#define ADDR_PIDX 0x0ffff000 +#define ADDR_PIDX_SHIFT 12 +#define ADDR_API_SHIFT_32 22 +#define ADDR_API_SHIFT_64 16 +#define ADDR_POFF 0x00000fff + +/* + * Bits in DSISR: + */ +#define DSISR_DIRECT 0x80000000 +#define DSISR_NOTFOUND 0x40000000 +#define DSISR_PROTECT 0x08000000 +#define DSISR_INVRX 0x04000000 +#define DSISR_STORE 0x02000000 +#define DSISR_DABR 0x00400000 +#define DSISR_SEGMENT 0x00200000 +#define DSISR_EAR 0x00100000 + +/* + * Bits in SRR1 on ISI: + */ +#define ISSRR1_NOTFOUND 0x40000000 +#define ISSRR1_DIRECT 0x10000000 +#define ISSRR1_PROTECT 0x08000000 +#define ISSRR1_SEGMENT 0x00200000 + +#endif /* _POWERPC_PTE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/ptrace.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/ptrace.h new file mode 100644 index 000000000000..862dac3282b4 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/ptrace.h @@ -0,0 +1,45 @@ +/* $OpenBSD: ptrace.h,v 1.3 2006/05/15 21:02:44 kettenis Exp $ */ +/* $NetBSD: ptrace.h,v 1.7 1995/01/26 19:47:10 mycroft Exp $ */ + +/* + * Copyright (c) 1993 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _POWERPC_PTRACE_H_ +#define _POWERPC_PTRACE_H_ + +/* + * powerpc-dependent ptrace definitions + */ +#define PT_STEP (PT_FIRSTMACH + 0) +#define PT_GETREGS (PT_FIRSTMACH + 1) +#define PT_SETREGS (PT_FIRSTMACH + 2) +#define PT_GETFPREGS (PT_FIRSTMACH + 3) +#define PT_SETFPREGS (PT_FIRSTMACH + 4) + +#endif /* !_POWERPC_PTRACE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/reg.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/reg.h new file mode 100644 index 000000000000..76fae6878bc1 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/reg.h @@ -0,0 +1,76 @@ +/* $OpenBSD: reg.h,v 1.11 2014/09/08 01:47:06 guenther Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)reg.h 5.5 (Berkeley) 1/18/91 + */ + +#ifndef _POWERPC_REG_H_ +#define _POWERPC_REG_H_ + +/* + * Struct reg, used for ptrace and in signal contexts + * Note that in signal contexts, it's represented as an array. + * That array has to look exactly like 'struct reg' though. + */ + +struct reg { + u_int32_t gpr[32]; + u_int64_t fpr[32]; + u_int32_t pc; + u_int32_t ps; + u_int32_t cnd; + u_int32_t lr; + u_int32_t cnt; + u_int32_t xer; + u_int32_t mq; +}; + +struct fpreg { + u_int64_t fpr[32]; + u_int32_t fpscr; +}; + +struct vreg { + u_int32_t vreg[32][4]; + u_int64_t vscr; + u_int32_t vrsave; + u_int32_t pad; +}; + +#ifdef _KERNEL +void save_vec(struct proc *); +void enable_vec(struct proc *); +extern struct proc *ppc_vecproc; +extern struct pool ppc_vecpl; +#endif /* _KERNEL */ +#endif /* !_POWERPC_REG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/reloc.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/reloc.h new file mode 100644 index 000000000000..4142aadeea9a --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/reloc.h @@ -0,0 +1,91 @@ +/* $OpenBSD: reloc.h,v 1.4 2011/03/23 16:54:36 pirofti Exp $ */ +/* $NetBSD: reloc.h,v 1.1 1996/09/30 16:34:33 ws Exp $ */ + +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 _POWERPC_RELOC_H_ +#define _POWERPC_RELOC_H_ + +/* + * Quite a number of relocation types + */ +enum reloc_type { + RELOC_NONE, + RELOC_32, + RELOC_24, + RELOC_16, + RELOC_16_LO, + RELOC_16_HI, /* RELOC_ADDIS = 5 */ + RELOC_16_HA, + RELOC_14, + RELOC_14_TAKEN, + RELOC_14_NTAKEN, + RELOC_REL24, /* RELOC_BRANCH = 10 */ + RELOC_REL14, + RELOC_REL14_TAKEN, + RELOC_REL14_NTAKEN, + RELOC_GOT16, + RELOC_GOT16_LO, + RELOC_GOT16_HI, + RELOC_GOT16_HA, + RELOC_PLT24, + RELOC_COPY, + RELOC_GLOB_DAT, + RELOC_JMP_SLOT, + RELOC_RELATIVE, + RELOC_LOCAL24PC, + RELOC_U32, + RELOC_U16, + RELOC_REL32, + RELOC_PLT32, + RELOC_PLTREL32, + RELOC_PLT16_LO, + RELOC_PLT16_HI, + RELOC_PLT16_HA, + /* ABI defines this as 32nd entry, but we ignore this, at least for now */ + RELOC_SDAREL, + + RELOC_TLSC = 67, + RELOC_DTPMOD32, + RELOC_TPREL16, + RELOC_TPREL16_LO, + RELOC_TPREL16_HI, + RELOC_TPREL16_HA, + RELOC_TPREL32, + RELOC_DTPREL16, + RELOC_DTPREL16_LO, + RELOC_DTPREL16_HI, + RELOC_DTPREL16_HA, + RELOC_DTPREL32, + RELOC_MAX +}; + +#endif /* _POWERPC_RELOC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/setjmp.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/setjmp.h new file mode 100644 index 000000000000..aa4351855d87 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/setjmp.h @@ -0,0 +1,4 @@ +/* $OpenBSD: setjmp.h,v 1.2 2001/03/29 18:52:19 drahn Exp $ */ +/* $NetBSD: setjmp.h,v 1.1 1996/09/30 16:34:34 ws Exp $ */ + +#define _JBLEN 100 \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/signal.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/signal.h new file mode 100644 index 000000000000..8cbb54002cb8 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/signal.h @@ -0,0 +1,72 @@ +/* $OpenBSD: signal.h,v 1.9 2016/05/10 18:39:47 deraadt Exp $ */ +/* $NetBSD: signal.h,v 1.1 1996/09/30 16:34:34 ws Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 _POWERPC_SIGNAL_H_ +#define _POWERPC_SIGNAL_H_ + +#include + +typedef int sig_atomic_t; + +#if __BSD_VISIBLE || __XPG_VISIBLE >= 420 +#include + +/* + * We have to save all registers on every trap, because + * 1. user could attach this process every time + * 2. we must be able to restore all user registers in case of fork + * Actually, we do not save the fp registers on trap, since + * these are not used by the kernel. They are saved only when switching + * between processes using the FPU. + * + */ +struct trapframe { + __register_t fixreg[32]; + __register_t lr; + __register_t cr; + __register_t xer; + __register_t ctr; + int srr0; + int srr1; + int dar; /* dar & dsisr are only filled on a DSI trap */ + int dsisr; + __register_t exc; +}; + +struct sigcontext { + long sc_cookie; + int sc_mask; /* saved signal mask */ + struct trapframe sc_frame; /* saved registers */ +}; +#endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ +#endif /* _POWERPC_SIGNAL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/spinlock.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/spinlock.h new file mode 100644 index 000000000000..66d10ac571ac --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/spinlock.h @@ -0,0 +1,10 @@ +/* $OpenBSD: spinlock.h,v 1.4 2017/09/05 02:40:54 guenther Exp $ */ + +#ifndef _POWERPC_SPINLOCK_H_ +#define _POWERPC_SPINLOCK_H_ + +#define _ATOMIC_LOCK_UNLOCKED (0) +#define _ATOMIC_LOCK_LOCKED (1) +typedef int _atomic_lock_t; + +#endif \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/tcb.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/tcb.h new file mode 100644 index 000000000000..b9a1108d5445 --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/tcb.h @@ -0,0 +1,42 @@ +/* $OpenBSD: tcb.h,v 1.6 2019/07/02 20:42:45 kettenis Exp $ */ + +/* + * Copyright (c) 2011 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TCB_H_ +#define _MACHINE_TCB_H_ + +#ifdef _KERNEL + +#define TCB_GET(p) \ + ((void *)trapframe(p)->fixreg[2]) +#define TCB_SET(p, addr) \ + (trapframe(p)->fixreg[2] = (__register_t)(addr)) + +#else /* _KERNEL */ + +/* ELF TLS ABI calls for small TCB, with static TLS data after it */ +#define TLS_VARIANT 1 + +/* powerpc offsets the TCB pointer 0x7000 bytes after the data */ +#define TCB_OFFSET 0x7000 + +register void *__tcb __asm__ ("r2"); +#define TCB_GET() (__tcb) +#define TCB_SET(tcb) ((__tcb) = (tcb)) + +#endif /* _KERNEL */ +#endif /* _MACHINE_TCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc-openbsd-eabihf/powerpc/trap.h b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/trap.h new file mode 100644 index 000000000000..93abaa4f421c --- /dev/null +++ b/lib/libc/include/powerpc-openbsd-eabihf/powerpc/trap.h @@ -0,0 +1,87 @@ +/* $OpenBSD: trap.h,v 1.9 2022/10/22 00:58:56 gkoehler Exp $ */ +/* $NetBSD: trap.h,v 1.1 1996/09/30 16:34:35 ws Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 _POWERPC_TRAP_H_ +#define _POWERPC_TRAP_H_ + +#define EXC_RSVD 0x0000 /* Reserved */ +#define EXC_RST 0x0100 /* Reset */ +#define EXC_MCHK 0x0200 /* Machine Check */ +#define EXC_DSI 0x0300 /* Data Storage Interrupt */ +#define EXC_ISI 0x0400 /* Instruction Storage Interrupt */ +#define EXC_EXI 0x0500 /* External Interrupt */ +#define EXC_ALI 0x0600 /* Alignment Interrupt */ +#define EXC_PGM 0x0700 /* Program Interrupt */ +#define EXC_FPU 0x0800 /* Floating-point Unavailable */ +#define EXC_DECR 0x0900 /* Decrementer Interrupt */ +#define EXC_SC 0x0c00 /* System Call */ +#define EXC_TRC 0x0d00 /* Trace */ +#define EXC_FPA 0x0e00 /* Floating-point Assist */ +#define EXC_PERF 0x0f00 /* Performance Monitoring */ +#define EXC_VEC 0x0f20 /* AltiVec Unavailable */ +#define EXC_BPT 0x1300 /* Instruction Breakpoint */ +#define EXC_SMI 0x1400 /* System Management Interrupt */ +#define EXC_VECAST_G4 0x1600 /* AltiVec Assist */ +#define EXC_VECAST_G5 0x1700 /* AltiVec Assist */ + +/* And these are only on the 603: */ +#define EXC_IMISS 0x1000 /* Instruction translation miss */ +#define EXC_DLMISS 0x1100 /* Data load translation miss */ +#define EXC_DSMISS 0x1200 /* Data store translation miss */ + +#define EXC_END 0x3000 /* End of exception vectors */ + +#define EXC_AST 0x3000 /* Fake AST vector */ + +/* Trap was in user mode */ +#define EXC_USER 0x10000 + +/* + * EXC_ALI sets bits in the DSISR and DAR to provide enough + * information to recover from the unaligned access without needing to + * parse the offending instruction. This includes certain bits of the + * opcode, and information about what registers are used. The opcode + * indicator values below come from Appendix F of Book III of "The + * PowerPC Architecture". + */ + +#define EXC_ALI_OPCODE_INDICATOR(dsisr) ((dsisr >> 10) & 0x7f) +#define EXC_ALI_LFD 0x09 +#define EXC_ALI_STFD 0x0b +#define EXC_ALI_DCBZ 0x5f + +/* Macros to extract register information */ +#define EXC_ALI_RST(dsisr) ((dsisr >> 5) & 0x1f) /* source or target */ +#define EXC_ALI_RA(dsisr) (dsisr & 0x1f) + +#endif /* _POWERPC_TRAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/dev/powermac_nvram/powermac_nvramvar.h b/lib/libc/include/powerpc64-freebsd-none/dev/powermac_nvram/powermac_nvramvar.h similarity index 100% rename from lib/libc/include/generic-freebsd/dev/powermac_nvram/powermac_nvramvar.h rename to lib/libc/include/powerpc64-freebsd-none/dev/powermac_nvram/powermac_nvramvar.h diff --git a/lib/libc/include/powerpc64-freebsd-none/fenv.h b/lib/libc/include/powerpc64-freebsd-none/fenv.h new file mode 100644 index 000000000000..1838590a9950 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/fenv.h @@ -0,0 +1,305 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2004-2005 David Schultz + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _FENV_H_ +#define _FENV_H_ + +#include +#include + +#ifndef __fenv_static +#define __fenv_static static +#endif + +typedef __uint32_t fenv_t; +typedef __uint32_t fexcept_t; + +/* Exception flags */ +#ifdef __SPE__ +#define FE_OVERFLOW 0x00000100 +#define FE_UNDERFLOW 0x00000200 +#define FE_DIVBYZERO 0x00000400 +#define FE_INVALID 0x00000800 +#define FE_INEXACT 0x00001000 + +#define FE_ALL_INVALID FE_INVALID + +#define _FPUSW_SHIFT 6 +#else +#define FE_INEXACT 0x02000000 +#define FE_DIVBYZERO 0x04000000 +#define FE_UNDERFLOW 0x08000000 +#define FE_OVERFLOW 0x10000000 +#define FE_INVALID 0x20000000 /* all types of invalid FP ops */ + +/* + * The PowerPC architecture has extra invalid flags that indicate the + * specific type of invalid operation occurred. These flags may be + * tested, set, and cleared---but not masked---separately. All of + * these bits are cleared when FE_INVALID is cleared, but only + * FE_VXSOFT is set when FE_INVALID is explicitly set in software. + */ +#define FE_VXCVI 0x00000100 /* invalid integer convert */ +#define FE_VXSQRT 0x00000200 /* square root of a negative */ +#define FE_VXSOFT 0x00000400 /* software-requested exception */ +#define FE_VXVC 0x00080000 /* ordered comparison involving NaN */ +#define FE_VXIMZ 0x00100000 /* inf * 0 */ +#define FE_VXZDZ 0x00200000 /* 0 / 0 */ +#define FE_VXIDI 0x00400000 /* inf / inf */ +#define FE_VXISI 0x00800000 /* inf - inf */ +#define FE_VXSNAN 0x01000000 /* operation on a signalling NaN */ +#define FE_ALL_INVALID (FE_VXCVI | FE_VXSQRT | FE_VXSOFT | FE_VXVC | \ + FE_VXIMZ | FE_VXZDZ | FE_VXIDI | FE_VXISI | \ + FE_VXSNAN | FE_INVALID) + +#define _FPUSW_SHIFT 22 +#endif +#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ + FE_ALL_INVALID | FE_OVERFLOW | FE_UNDERFLOW) + +/* Rounding modes */ +#define FE_TONEAREST 0x0000 +#define FE_TOWARDZERO 0x0001 +#define FE_UPWARD 0x0002 +#define FE_DOWNWARD 0x0003 +#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ + FE_UPWARD | FE_TOWARDZERO) + +__BEGIN_DECLS + +/* Default floating-point environment */ +extern const fenv_t __fe_dfl_env; +#define FE_DFL_ENV (&__fe_dfl_env) + +/* We need to be able to map status flag positions to mask flag positions */ +#define _ENABLE_MASK ((FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ + FE_OVERFLOW | FE_UNDERFLOW) >> _FPUSW_SHIFT) + +#ifndef _SOFT_FLOAT +#ifdef __SPE__ +#define __mffs(__env) \ + __asm __volatile("mfspr %0, 512" : "=r" ((__env)->__bits.__reg)) +#define __mtfsf(__env) \ + __asm __volatile("mtspr 512,%0;isync" :: "r" ((__env).__bits.__reg)) +#else +#define __mffs(__env) \ + __asm __volatile("mffs %0" : "=f" ((__env)->__d)) +#define __mtfsf(__env) \ + __asm __volatile("mtfsf 255,%0" :: "f" ((__env).__d)) +#endif +#else +#define __mffs(__env) +#define __mtfsf(__env) +#endif + +union __fpscr { + double __d; + struct { +#if _BYTE_ORDER == _LITTLE_ENDIAN + fenv_t __reg; + __uint32_t __junk; +#else + __uint32_t __junk; + fenv_t __reg; +#endif + } __bits; +}; + +__fenv_static inline int +feclearexcept(int __excepts) +{ + union __fpscr __r; + + if (__excepts & FE_INVALID) + __excepts |= FE_ALL_INVALID; + __mffs(&__r); + __r.__bits.__reg &= ~__excepts; + __mtfsf(__r); + return (0); +} + +__fenv_static inline int +fegetexceptflag(fexcept_t *__flagp, int __excepts) +{ + union __fpscr __r; + + __mffs(&__r); + *__flagp = __r.__bits.__reg & __excepts; + return (0); +} + +__fenv_static inline int +fesetexceptflag(const fexcept_t *__flagp, int __excepts) +{ + union __fpscr __r; + + if (__excepts & FE_INVALID) + __excepts |= FE_ALL_INVALID; + __mffs(&__r); + __r.__bits.__reg &= ~__excepts; + __r.__bits.__reg |= *__flagp & __excepts; + __mtfsf(__r); + return (0); +} + +#ifdef __SPE__ +extern int feraiseexcept(int __excepts); +#else +__fenv_static inline int +feraiseexcept(int __excepts) +{ + union __fpscr __r; + + if (__excepts & FE_INVALID) + __excepts |= FE_VXSOFT; + __mffs(&__r); + __r.__bits.__reg |= __excepts; + __mtfsf(__r); + return (0); +} +#endif + +__fenv_static inline int +fetestexcept(int __excepts) +{ + union __fpscr __r; + + __mffs(&__r); + return (__r.__bits.__reg & __excepts); +} + +__fenv_static inline int +fegetround(void) +{ + union __fpscr __r; + + __mffs(&__r); + return (__r.__bits.__reg & _ROUND_MASK); +} + +__fenv_static inline int +fesetround(int __round) +{ + union __fpscr __r; + + if (__round & ~_ROUND_MASK) + return (-1); + __mffs(&__r); + __r.__bits.__reg &= ~_ROUND_MASK; + __r.__bits.__reg |= __round; + __mtfsf(__r); + return (0); +} + +__fenv_static inline int +fegetenv(fenv_t *__envp) +{ + union __fpscr __r; + + __mffs(&__r); + *__envp = __r.__bits.__reg; + return (0); +} + +__fenv_static inline int +feholdexcept(fenv_t *__envp) +{ + union __fpscr __r; + + __mffs(&__r); + *__envp = __r.__bits.__reg; + __r.__bits.__reg &= ~(FE_ALL_EXCEPT | _ENABLE_MASK); + __mtfsf(__r); + return (0); +} + +__fenv_static inline int +fesetenv(const fenv_t *__envp) +{ + union __fpscr __r; + + __r.__bits.__reg = *__envp; + __mtfsf(__r); + return (0); +} + +__fenv_static inline int +feupdateenv(const fenv_t *__envp) +{ + union __fpscr __r; + + __mffs(&__r); + __r.__bits.__reg &= FE_ALL_EXCEPT; + __r.__bits.__reg |= *__envp; + __mtfsf(__r); + return (0); +} + +#if __BSD_VISIBLE + +__fenv_static inline int +feenableexcept(int __mask) +{ + union __fpscr __r; + fenv_t __oldmask; + + __mffs(&__r); + __oldmask = __r.__bits.__reg; + __r.__bits.__reg |= (__mask & FE_ALL_EXCEPT) >> _FPUSW_SHIFT; + __mtfsf(__r); + return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT); +} + +__fenv_static inline int +fedisableexcept(int __mask) +{ + union __fpscr __r; + fenv_t __oldmask; + + __mffs(&__r); + __oldmask = __r.__bits.__reg; + __r.__bits.__reg &= ~((__mask & FE_ALL_EXCEPT) >> _FPUSW_SHIFT); + __mtfsf(__r); + return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT); +} + +/* We currently provide no external definition of fegetexcept(). */ +static inline int +fegetexcept(void) +{ + union __fpscr __r; + + __mffs(&__r); + return ((__r.__bits.__reg & _ENABLE_MASK) << _FPUSW_SHIFT); +} + +#endif /* __BSD_VISIBLE */ + +__END_DECLS + +#endif /* !_FENV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-freebsd-none/float.h b/lib/libc/include/powerpc64-freebsd-none/float.h new file mode 100644 index 000000000000..a832240666f0 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/float.h @@ -0,0 +1,98 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * from: FreeBSD: src/sys/i386/include/float.h,v 1.8 1999/08/28 00:44:11 + */ + +#ifndef _MACHINE_FLOAT_H_ +#define _MACHINE_FLOAT_H_ 1 + +#include + +#ifndef _SOFT_FLOAT +__BEGIN_DECLS +extern int __flt_rounds(void); +__END_DECLS +#define FLT_ROUNDS __flt_rounds() +#else +#define FLT_ROUNDS (-1) +#endif + +#define FLT_RADIX 2 /* b */ +#if __ISO_C_VISIBLE >= 1999 +#define FLT_EVAL_METHOD 0 +#define DECIMAL_DIG 17 /* max precision in decimal digits */ +#endif + +#define FLT_MANT_DIG 24 /* p */ +#define FLT_EPSILON 1.19209290E-07F /* b**(1-p) */ +#define FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ +#define FLT_MIN_EXP (-125) /* emin */ +#define FLT_MIN 1.17549435E-38F /* b**(emin-1) */ +#define FLT_MIN_10_EXP (-37) /* ceil(log10(b**(emin-1))) */ +#define FLT_MAX_EXP 128 /* emax */ +#define FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ +#define FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ +#if __ISO_C_VISIBLE >= 2011 +#define FLT_TRUE_MIN 1.40129846E-45F /* b**(emin-p) */ +#define FLT_DECIMAL_DIG 9 /* ceil(1+p*log10(b)) */ +#define FLT_HAS_SUBNORM 1 +#endif /* __ISO_C_VISIBLE >= 2011 */ + +#define DBL_MANT_DIG 53 +#define DBL_EPSILON 2.2204460492503131E-16 +#define DBL_DIG 15 +#define DBL_MIN_EXP (-1021) +#define DBL_MIN 2.2250738585072014E-308 +#define DBL_MIN_10_EXP (-307) +#define DBL_MAX_EXP 1024 +#define DBL_MAX 1.7976931348623157E+308 +#define DBL_MAX_10_EXP 308 +#if __ISO_C_VISIBLE >= 2011 +#define DBL_TRUE_MIN 4.9406564584124654E-324 +#define DBL_DECIMAL_DIG 17 +#define DBL_HAS_SUBNORM 1 +#endif /* __ISO_C_VISIBLE >= 2011 */ + +#define LDBL_MANT_DIG DBL_MANT_DIG +#define LDBL_EPSILON ((long double)DBL_EPSILON) +#define LDBL_DIG DBL_DIG +#define LDBL_MIN_EXP DBL_MIN_EXP +#define LDBL_MIN ((long double)DBL_MIN) +#define LDBL_MIN_10_EXP DBL_MIN_10_EXP +#define LDBL_MAX_EXP DBL_MAX_EXP +#define LDBL_MAX ((long double)DBL_MAX) +#define LDBL_MAX_10_EXP DBL_MAX_10_EXP +#if __ISO_C_VISIBLE >= 2011 +#define LDBL_TRUE_MIN ((long double)DBL_TRUE_MIN) +#define LDBL_DECIMAL_DIG DBL_DECIMAL_DIG +#define LDBL_HAS_SUBNORM DBL_HAS_SUBNORM +#endif /* __ISO_C_VISIBLE >= 2011 */ + +#endif /* _MACHINE_FLOAT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-freebsd-none/floatingpoint.h b/lib/libc/include/powerpc64-freebsd-none/floatingpoint.h new file mode 100644 index 000000000000..d2c7e15ad2e8 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/floatingpoint.h @@ -0,0 +1,37 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2004 Suleiman Souhlal + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY DAVID O'BRIEN AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _FLOATINGPOINT_H_ +#define _FLOATINGPOINT_H_ + +#include + +#endif /* !_FLOATINGPOINT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/_align.h b/lib/libc/include/powerpc64-freebsd-none/machine/_align.h new file mode 100644 index 000000000000..d42a79c96f4a --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/_align.h @@ -0,0 +1,51 @@ +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (c) 2001 David E. O'Brien + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _POWERPC_INCLUDE__ALIGN_H_ +#define _POWERPC_INCLUDE__ALIGN_H_ + +/* + * Round p (pointer or byte index) up to a correctly-aligned value + * for all data types (int, long, ...). The result is unsigned int + * and must be cast to any desired pointer type. + */ +#define _ALIGNBYTES (sizeof(register_t) - 1) +#define _ALIGN(p) (((uintptr_t)(p) + _ALIGNBYTES) & ~_ALIGNBYTES) + +#endif /* !_POWERPC_INCLUDE__ALIGN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/_bus.h b/lib/libc/include/powerpc64-freebsd-none/machine/_bus.h new file mode 100644 index 000000000000..5bc548592d14 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/_bus.h @@ -0,0 +1,30 @@ +/*- + * Copyright (c) 2005 The FreeBSD Foundation. + * + * SPDX-License-Identifier: BSD-2-Clause + * + * Derived in part from NetBSD's bus.h files by (alphabetically): + * Christopher G. Demetriou + * Charles M. Hannum + * Jason Thorpe + * The NetBSD Foundation. + */ + +#ifndef POWERPC_INCLUDE__BUS_H +#define POWERPC_INCLUDE__BUS_H + +#include + +/* + * Bus address and size types + */ +typedef vm_paddr_t bus_addr_t; +typedef vm_size_t bus_size_t; + +/* + * Access methods for bus resources and address space. + */ +typedef struct bus_space *bus_space_tag_t; +typedef vm_offset_t bus_space_handle_t; + +#endif /* POWERPC_INCLUDE__BUS_H */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/_inttypes.h b/lib/libc/include/powerpc64-freebsd-none/machine/_inttypes.h new file mode 100644 index 000000000000..770c91e43415 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/_inttypes.h @@ -0,0 +1,222 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Klaus Klein. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * From: $NetBSD: int_fmtio.h,v 1.2 2001/04/26 16:25:21 kleink Exp $ + */ + +#ifndef _MACHINE_INTTYPES_H_ +#define _MACHINE_INTTYPES_H_ + +/* + * Macros for format specifiers. + */ + +#ifdef __LP64__ +#define __PRI64 "l" +#define __PRIptr "l" +#else +#define __PRI64 "ll" +#define __PRIptr +#endif + +/* fprintf(3) macros for signed integers. */ + +#define PRId8 "d" /* int8_t */ +#define PRId16 "d" /* int16_t */ +#define PRId32 "d" /* int32_t */ +#define PRId64 __PRI64"d" /* int64_t */ +#define PRIdLEAST8 "d" /* int_least8_t */ +#define PRIdLEAST16 "d" /* int_least16_t */ +#define PRIdLEAST32 "d" /* int_least32_t */ +#define PRIdLEAST64 __PRI64"d" /* int_least64_t */ +#define PRIdFAST8 "d" /* int_fast8_t */ +#define PRIdFAST16 "d" /* int_fast16_t */ +#define PRIdFAST32 "d" /* int_fast32_t */ +#define PRIdFAST64 __PRI64"d" /* int_fast64_t */ +#define PRIdMAX "jd" /* intmax_t */ +#define PRIdPTR __PRIptr"d" /* intptr_t */ + +#define PRIi8 "i" /* int8_t */ +#define PRIi16 "i" /* int16_t */ +#define PRIi32 "i" /* int32_t */ +#define PRIi64 __PRI64"i" /* int64_t */ +#define PRIiLEAST8 "i" /* int_least8_t */ +#define PRIiLEAST16 "i" /* int_least16_t */ +#define PRIiLEAST32 "i" /* int_least32_t */ +#define PRIiLEAST64 __PRI64"i" /* int_least64_t */ +#define PRIiFAST8 "i" /* int_fast8_t */ +#define PRIiFAST16 "i" /* int_fast16_t */ +#define PRIiFAST32 "i" /* int_fast32_t */ +#define PRIiFAST64 __PRI64"i" /* int_fast64_t */ +#define PRIiMAX "ji" /* intmax_t */ +#define PRIiPTR __PRIptr"i" /* intptr_t */ + +/* fprintf(3) macros for unsigned integers. */ + +#define PRIo8 "o" /* uint8_t */ +#define PRIo16 "o" /* uint16_t */ +#define PRIo32 "o" /* uint32_t */ +#define PRIo64 __PRI64"o" /* uint64_t */ +#define PRIoLEAST8 "o" /* uint_least8_t */ +#define PRIoLEAST16 "o" /* uint_least16_t */ +#define PRIoLEAST32 "o" /* uint_least32_t */ +#define PRIoLEAST64 __PRI64"o" /* uint_least64_t */ +#define PRIoFAST8 "o" /* uint_fast8_t */ +#define PRIoFAST16 "o" /* uint_fast16_t */ +#define PRIoFAST32 "o" /* uint_fast32_t */ +#define PRIoFAST64 __PRI64"o" /* uint_fast64_t */ +#define PRIoMAX "jo" /* uintmax_t */ +#define PRIoPTR __PRIptr"o" /* uintptr_t */ + +#define PRIu8 "u" /* uint8_t */ +#define PRIu16 "u" /* uint16_t */ +#define PRIu32 "u" /* uint32_t */ +#define PRIu64 __PRI64"u" /* uint64_t */ +#define PRIuLEAST8 "u" /* uint_least8_t */ +#define PRIuLEAST16 "u" /* uint_least16_t */ +#define PRIuLEAST32 "u" /* uint_least32_t */ +#define PRIuLEAST64 __PRI64"u" /* uint_least64_t */ +#define PRIuFAST8 "u" /* uint_fast8_t */ +#define PRIuFAST16 "u" /* uint_fast16_t */ +#define PRIuFAST32 "u" /* uint_fast32_t */ +#define PRIuFAST64 __PRI64"u" /* uint_fast64_t */ +#define PRIuMAX "ju" /* uintmax_t */ +#define PRIuPTR __PRIptr"u" /* uintptr_t */ + +#define PRIx8 "x" /* uint8_t */ +#define PRIx16 "x" /* uint16_t */ +#define PRIx32 "x" /* uint32_t */ +#define PRIx64 __PRI64"x" /* uint64_t */ +#define PRIxLEAST8 "x" /* uint_least8_t */ +#define PRIxLEAST16 "x" /* uint_least16_t */ +#define PRIxLEAST32 "x" /* uint_least32_t */ +#define PRIxLEAST64 __PRI64"x" /* uint_least64_t */ +#define PRIxFAST8 "x" /* uint_fast8_t */ +#define PRIxFAST16 "x" /* uint_fast16_t */ +#define PRIxFAST32 "x" /* uint_fast32_t */ +#define PRIxFAST64 __PRI64"x" /* uint_fast64_t */ +#define PRIxMAX "jx" /* uintmax_t */ +#define PRIxPTR __PRIptr"x" /* uintptr_t */ + +#define PRIX8 "X" /* uint8_t */ +#define PRIX16 "X" /* uint16_t */ +#define PRIX32 "X" /* uint32_t */ +#define PRIX64 __PRI64"X" /* uint64_t */ +#define PRIXLEAST8 "X" /* uint_least8_t */ +#define PRIXLEAST16 "X" /* uint_least16_t */ +#define PRIXLEAST32 "X" /* uint_least32_t */ +#define PRIXLEAST64 __PRI64"X" /* uint_least64_t */ +#define PRIXFAST8 "X" /* uint_fast8_t */ +#define PRIXFAST16 "X" /* uint_fast16_t */ +#define PRIXFAST32 "X" /* uint_fast32_t */ +#define PRIXFAST64 __PRI64"X" /* uint_fast64_t */ +#define PRIXMAX "jX" /* uintmax_t */ +#define PRIXPTR __PRIptr"X" /* uintptr_t */ + +/* fscanf(3) macros for signed integers. */ + +#define SCNd8 "hhd" /* int8_t */ +#define SCNd16 "hd" /* int16_t */ +#define SCNd32 "d" /* int32_t */ +#define SCNd64 __PRI64"d" /* int64_t */ +#define SCNdLEAST8 "hhd" /* int_least8_t */ +#define SCNdLEAST16 "hd" /* int_least16_t */ +#define SCNdLEAST32 "d" /* int_least32_t */ +#define SCNdLEAST64 __PRI64"d" /* int_least64_t */ +#define SCNdFAST8 "d" /* int_fast8_t */ +#define SCNdFAST16 "d" /* int_fast16_t */ +#define SCNdFAST32 "d" /* int_fast32_t */ +#define SCNdFAST64 __PRI64"d" /* int_fast64_t */ +#define SCNdMAX "jd" /* intmax_t */ +#define SCNdPTR __PRIptr"d" /* intptr_t */ + +#define SCNi8 "hhi" /* int8_t */ +#define SCNi16 "hi" /* int16_t */ +#define SCNi32 "i" /* int32_t */ +#define SCNi64 __PRI64"i" /* int64_t */ +#define SCNiLEAST8 "hhi" /* int_least8_t */ +#define SCNiLEAST16 "hi" /* int_least16_t */ +#define SCNiLEAST32 "i" /* int_least32_t */ +#define SCNiLEAST64 __PRI64"i" /* int_least64_t */ +#define SCNiFAST8 "i" /* int_fast8_t */ +#define SCNiFAST16 "i" /* int_fast16_t */ +#define SCNiFAST32 "i" /* int_fast32_t */ +#define SCNiFAST64 __PRI64"i" /* int_fast64_t */ +#define SCNiMAX "ji" /* intmax_t */ +#define SCNiPTR __PRIptr"i" /* intptr_t */ + +/* fscanf(3) macros for unsigned integers. */ + +#define SCNo8 "hho" /* uint8_t */ +#define SCNo16 "ho" /* uint16_t */ +#define SCNo32 "o" /* uint32_t */ +#define SCNo64 __PRI64"o" /* uint64_t */ +#define SCNoLEAST8 "hho" /* uint_least8_t */ +#define SCNoLEAST16 "ho" /* uint_least16_t */ +#define SCNoLEAST32 "o" /* uint_least32_t */ +#define SCNoLEAST64 __PRI64"o" /* uint_least64_t */ +#define SCNoFAST8 "o" /* uint_fast8_t */ +#define SCNoFAST16 "o" /* uint_fast16_t */ +#define SCNoFAST32 "o" /* uint_fast32_t */ +#define SCNoFAST64 __PRI64"o" /* uint_fast64_t */ +#define SCNoMAX "jo" /* uintmax_t */ +#define SCNoPTR __PRIptr"o" /* uintptr_t */ + +#define SCNu8 "hhu" /* uint8_t */ +#define SCNu16 "hu" /* uint16_t */ +#define SCNu32 "u" /* uint32_t */ +#define SCNu64 __PRI64"u" /* uint64_t */ +#define SCNuLEAST8 "hhu" /* uint_least8_t */ +#define SCNuLEAST16 "hu" /* uint_least16_t */ +#define SCNuLEAST32 "u" /* uint_least32_t */ +#define SCNuLEAST64 __PRI64"u" /* uint_least64_t */ +#define SCNuFAST8 "u" /* uint_fast8_t */ +#define SCNuFAST16 "u" /* uint_fast16_t */ +#define SCNuFAST32 "u" /* uint_fast32_t */ +#define SCNuFAST64 __PRI64"u" /* uint_fast64_t */ +#define SCNuMAX "ju" /* uintmax_t */ +#define SCNuPTR __PRIptr"u" /* uintptr_t */ + +#define SCNx8 "hhx" /* uint8_t */ +#define SCNx16 "hx" /* uint16_t */ +#define SCNx32 "x" /* uint32_t */ +#define SCNx64 __PRI64"x" /* uint64_t */ +#define SCNxLEAST8 "hhx" /* uint_least8_t */ +#define SCNxLEAST16 "hx" /* uint_least16_t */ +#define SCNxLEAST32 "x" /* uint_least32_t */ +#define SCNxLEAST64 __PRI64"x" /* uint_least64_t */ +#define SCNxFAST8 "x" /* uint_fast8_t */ +#define SCNxFAST16 "x" /* uint_fast16_t */ +#define SCNxFAST32 "x" /* uint_fast32_t */ +#define SCNxFAST64 __PRI64"x" /* uint_fast64_t */ +#define SCNxMAX "jx" /* uintmax_t */ +#define SCNxPTR __PRIptr"x" /* uintptr_t */ + +#endif /* !_MACHINE_INTTYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/_limits.h b/lib/libc/include/powerpc64-freebsd-none/machine/_limits.h new file mode 100644 index 000000000000..e8451d22fef1 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/_limits.h @@ -0,0 +1,96 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE__LIMITS_H_ +#define _MACHINE__LIMITS_H_ + +/* + * According to ANSI (section 2.2.4.2), the values below must be usable by + * #if preprocessing directives. Additionally, the expression must have the + * same type as would an expression that is an object of the corresponding + * type converted according to the integral promotions. The subtraction for + * INT_MIN, etc., is so the value is not unsigned; e.g., 0x80000000 is an + * unsigned int for 32-bit two's complement ANSI compilers (section 3.1.3.2). + */ + +#define __CHAR_BIT 8 /* number of bits in a char */ + +#define __SCHAR_MAX 0x7f /* max value for a signed char */ +#define __SCHAR_MIN (-0x7f - 1) /* min value for a signed char */ + +#define __UCHAR_MAX 0xff /* max value for an unsigned char */ + +#define __USHRT_MAX 0xffff /* max value for an unsigned short */ +#define __SHRT_MAX 0x7fff /* max value for a short */ +#define __SHRT_MIN (-0x7fff - 1) /* min value for a short */ + +#define __UINT_MAX 0xffffffff /* max value for an unsigned int */ +#define __INT_MAX 0x7fffffff /* max value for an int */ +#define __INT_MIN (-0x7fffffff - 1) /* min value for an int */ + +#ifdef __LP64__ +#define __ULONG_MAX 0xffffffffffffffff +#define __LONG_MAX 0x7fffffffffffffff +#define __LONG_MIN (-0x7fffffffffffffff - 1) +#define __LONG_BIT 64 +#else +#define __ULONG_MAX 0xffffffffUL /* max value for an unsigned long */ +#define __LONG_MAX 0x7fffffffL /* max value for a long */ +#define __LONG_MIN (-0x7fffffffL - 1) /* min value for a long */ +#define __LONG_BIT 32 +#endif + +#define __ULLONG_MAX 0xffffffffffffffffULL +#define __LLONG_MAX 0x7fffffffffffffffLL /* max value for a long long */ +#define __LLONG_MIN (-0x7fffffffffffffffLL - 1) /* min for a long long */ + +#ifdef __LP64__ +#define __SSIZE_MAX __LONG_MAX /* max value for a ssize_t */ +#define __SIZE_T_MAX __ULONG_MAX /* max value for a size_t */ +#else +#define __SSIZE_MAX __INT_MAX /* max value for a ssize_t */ +#define __SIZE_T_MAX __UINT_MAX /* max value for a size_t */ +#endif + +#define __OFF_MAX __LLONG_MAX /* max value for an off_t */ +#define __OFF_MIN __LLONG_MIN /* min value for an off_t */ + +/* Quads and long longs are the same size. Ensure they stay in sync. */ +#define __UQUAD_MAX __ULLONG_MAX /* max value for a uquad_t */ +#define __QUAD_MAX __LLONG_MAX /* max value for a quad_t */ +#define __QUAD_MIN __LLONG_MIN /* min value for a quad_t */ + +#define __WORD_BIT 32 + +/* Minimum signal stack size. */ +#define __MINSIGSTKSZ (512 * 4) + +#endif /* !_MACHINE__LIMITS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/_stdint.h b/lib/libc/include/powerpc64-freebsd-none/machine/_stdint.h new file mode 100644 index 000000000000..6111b8467c09 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/_stdint.h @@ -0,0 +1,200 @@ +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (c) 2001, 2002 Mike Barcroft + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Klaus Klein. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE__STDINT_H_ +#define _MACHINE__STDINT_H_ + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) + +#define INT8_C(c) (c) +#define INT16_C(c) (c) +#define INT32_C(c) (c) + +#define UINT8_C(c) (c) +#define UINT16_C(c) (c) +#define UINT32_C(c) (c ## U) + +#ifdef __LP64__ +#define INT64_C(c) (c ## L) +#define UINT64_C(c) (c ## UL) +#else +#define INT64_C(c) (c ## LL) +#define UINT64_C(c) (c ## ULL) +#endif + +#define INTMAX_C(c) INT64_C(c) +#define UINTMAX_C(c) UINT64_C(c) + +#endif /* !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) */ + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) + +#ifndef __INT64_C +#ifdef __LP64__ +#define __INT64_C(c) (c ## L) +#define __UINT64_C(c) (c ## UL) +#else +#define __INT64_C(c) (c ## LL) +#define __UINT64_C(c) (c ## ULL) +#endif +#endif + +/* + * ISO/IEC 9899:1999 + * 7.18.2.1 Limits of exact-width integer types + */ +/* Minimum values of exact-width signed integer types. */ +#define INT8_MIN (-0x7f-1) +#define INT16_MIN (-0x7fff-1) +#define INT32_MIN (-0x7fffffff-1) +#define INT64_MIN (-__INT64_C(0x7fffffffffffffff)-1) + +/* Maximum values of exact-width signed integer types. */ +#define INT8_MAX 0x7f +#define INT16_MAX 0x7fff +#define INT32_MAX 0x7fffffff +#define INT64_MAX __INT64_C(0x7fffffffffffffff) + +/* Maximum values of exact-width unsigned integer types. */ +#define UINT8_MAX 0xff +#define UINT16_MAX 0xffff +#define UINT32_MAX 0xffffffff +#define UINT64_MAX __UINT64_C(0xffffffffffffffff) + +/* + * ISO/IEC 9899:1999 + * 7.18.2.2 Limits of minimum-width integer types + */ +/* Minimum values of minimum-width signed integer types. */ +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST64_MIN INT64_MIN + +/* Maximum values of minimum-width signed integer types. */ +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MAX INT64_MAX + +/* Maximum values of minimum-width unsigned integer types. */ +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +/* + * ISO/IEC 9899:1999 + * 7.18.2.3 Limits of fastest minimum-width integer types + */ +/* Minimum values of fastest minimum-width signed integer types. */ +#define INT_FAST8_MIN INT32_MIN +#define INT_FAST16_MIN INT32_MIN +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST64_MIN INT64_MIN + +/* Maximum values of fastest minimum-width signed integer types. */ +#define INT_FAST8_MAX INT32_MAX +#define INT_FAST16_MAX INT32_MAX +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MAX INT64_MAX + +/* Maximum values of fastest minimum-width unsigned integer types. */ +#define UINT_FAST8_MAX UINT32_MAX +#define UINT_FAST16_MAX UINT32_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +/* + * ISO/IEC 9899:1999 + * 7.18.2.4 Limits of integer types capable of holding object pointers + */ +#ifdef __LP64__ +#define INTPTR_MIN INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX +#else +#define INTPTR_MIN INT32_MIN +#define INTPTR_MAX INT32_MAX +#define UINTPTR_MAX UINT32_MAX +#endif + +/* + * ISO/IEC 9899:1999 + * 7.18.2.5 Limits of greatest-width integer types + */ +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +/* + * ISO/IEC 9899:1999 + * 7.18.3 Limits of other integer types + */ +#ifdef __LP64__ +/* Limits of ptrdiff_t. */ +#define PTRDIFF_MIN INT64_MIN +#define PTRDIFF_MAX INT64_MAX + +/* Limits of sig_atomic_t. */ +#define SIG_ATOMIC_MIN INT64_MIN +#define SIG_ATOMIC_MAX INT64_MAX + +/* Limit of size_t. */ +#define SIZE_MAX UINT64_MAX +#else +/* Limits of ptrdiff_t. */ +#define PTRDIFF_MIN INT32_MIN +#define PTRDIFF_MAX INT32_MAX + +/* Limits of sig_atomic_t. */ +#define SIG_ATOMIC_MIN INT32_MIN +#define SIG_ATOMIC_MAX INT32_MAX + +/* Limit of size_t. */ +#define SIZE_MAX UINT32_MAX +#endif + +/* Limits of wint_t. */ +#define WINT_MIN INT32_MIN +#define WINT_MAX INT32_MAX + +#endif /* !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) */ + +#endif /* !_MACHINE__STDINT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/_types.h b/lib/libc/include/powerpc64-freebsd-none/machine/_types.h new file mode 100644 index 000000000000..00294d9f9857 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/_types.h @@ -0,0 +1,89 @@ +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (c) 2002 Mike Barcroft + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE__TYPES_H_ +#define _MACHINE__TYPES_H_ + +#ifndef _SYS__TYPES_H_ +#error do not include this header, use sys/_types.h +#endif + +/* + * Standard type definitions. + */ +typedef __uint32_t __clock_t; /* clock()... */ +#ifndef _STANDALONE +typedef double __double_t; +typedef float __float_t; +#endif +#ifdef __LP64__ +typedef __int64_t __critical_t; +#else +typedef __int32_t __critical_t; +#endif +typedef __int32_t __int_fast8_t; +typedef __int32_t __int_fast16_t; +typedef __int32_t __int_fast32_t; +typedef __int64_t __int_fast64_t; +#ifdef __LP64__ +typedef __int64_t __register_t; +typedef __int64_t __segsz_t; /* segment size (in pages) */ +#else +typedef __int32_t __register_t; +typedef __int32_t __segsz_t; /* segment size (in pages) */ +#endif +typedef __int64_t __time_t; /* time()... */ +typedef __uint32_t __uint_fast8_t; +typedef __uint32_t __uint_fast16_t; +typedef __uint32_t __uint_fast32_t; +typedef __uint64_t __uint_fast64_t; +#ifdef __LP64__ +typedef __uint64_t __u_register_t; +typedef __uint64_t __vm_paddr_t; +#else +typedef __uint32_t __u_register_t; +#ifdef BOOKE +typedef __uint64_t __vm_paddr_t; +#else +typedef __uint32_t __vm_paddr_t; +#endif +#endif +typedef int ___wchar_t; + +#define __WCHAR_MIN __INT_MIN /* min value for a wchar_t */ +#define __WCHAR_MAX __INT_MAX /* max value for a wchar_t */ + +#endif /* !_MACHINE__TYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/altivec.h b/lib/libc/include/powerpc64-freebsd-none/machine/altivec.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/altivec.h rename to lib/libc/include/powerpc64-freebsd-none/machine/altivec.h diff --git a/lib/libc/include/generic-freebsd/machine/asm.h b/lib/libc/include/powerpc64-freebsd-none/machine/asm.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/asm.h rename to lib/libc/include/powerpc64-freebsd-none/machine/asm.h diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/atomic.h b/lib/libc/include/powerpc64-freebsd-none/machine/atomic.h new file mode 100644 index 000000000000..6be658483ef5 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/atomic.h @@ -0,0 +1,1183 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2008 Marcel Moolenaar + * Copyright (c) 2001 Benno Rice + * Copyright (c) 2001 David E. O'Brien + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_ATOMIC_H_ +#define _MACHINE_ATOMIC_H_ + +#include + +#ifndef __powerpc64__ +#include +#endif + +/* + * The __ATOMIC_REL/ACQ() macros provide memory barriers only in conjunction + * with the atomic lXarx/stXcx. sequences below. They are not exposed outside + * of this file. See also Appendix B.2 of Book II of the architecture manual. + * + * Note that not all Book-E processors accept the light-weight sync variant. + * In particular, early models of E500 cores are known to wedge. Bank on all + * 64-bit capable CPUs to accept lwsync properly and pressimize 32-bit CPUs + * to use the heavier-weight sync. + */ + +#ifdef __powerpc64__ +#define mb() __asm __volatile("sync" : : : "memory") +#define rmb() __asm __volatile("lwsync" : : : "memory") +#define wmb() __asm __volatile("lwsync" : : : "memory") +#define __ATOMIC_REL() __asm __volatile("lwsync" : : : "memory") +#define __ATOMIC_ACQ() __asm __volatile("isync" : : : "memory") +#else +#define mb() __asm __volatile("sync" : : : "memory") +#define rmb() __asm __volatile("sync" : : : "memory") +#define wmb() __asm __volatile("sync" : : : "memory") +#define __ATOMIC_REL() __asm __volatile("sync" : : : "memory") +#define __ATOMIC_ACQ() __asm __volatile("isync" : : : "memory") +#endif + +static __inline void +powerpc_lwsync(void) +{ + +#ifdef __powerpc64__ + __asm __volatile("lwsync" : : : "memory"); +#else + __asm __volatile("sync" : : : "memory"); +#endif +} + +/* + * atomic_add(p, v) + * { *p += v; } + */ + +#define __atomic_add_int(p, v, t) \ + __asm __volatile( \ + "1: lwarx %0, 0, %2\n" \ + " add %0, %3, %0\n" \ + " stwcx. %0, 0, %2\n" \ + " bne- 1b\n" \ + : "=&r" (t), "=m" (*p) \ + : "r" (p), "r" (v), "m" (*p) \ + : "cr0", "memory") \ + /* __atomic_add_int */ + +#ifdef __powerpc64__ +#define __atomic_add_long(p, v, t) \ + __asm __volatile( \ + "1: ldarx %0, 0, %2\n" \ + " add %0, %3, %0\n" \ + " stdcx. %0, 0, %2\n" \ + " bne- 1b\n" \ + : "=&r" (t), "=m" (*p) \ + : "r" (p), "r" (v), "m" (*p) \ + : "cr0", "memory") \ + /* __atomic_add_long */ +#else +#define __atomic_add_long(p, v, t) \ + __asm __volatile( \ + "1: lwarx %0, 0, %2\n" \ + " add %0, %3, %0\n" \ + " stwcx. %0, 0, %2\n" \ + " bne- 1b\n" \ + : "=&r" (t), "=m" (*p) \ + : "r" (p), "r" (v), "m" (*p) \ + : "cr0", "memory") \ + /* __atomic_add_long */ +#endif + +#define _ATOMIC_ADD(type) \ + static __inline void \ + atomic_add_##type(volatile u_##type *p, u_##type v) { \ + u_##type t; \ + __atomic_add_##type(p, v, t); \ + } \ + \ + static __inline void \ + atomic_add_acq_##type(volatile u_##type *p, u_##type v) { \ + u_##type t; \ + __atomic_add_##type(p, v, t); \ + __ATOMIC_ACQ(); \ + } \ + \ + static __inline void \ + atomic_add_rel_##type(volatile u_##type *p, u_##type v) { \ + u_##type t; \ + __ATOMIC_REL(); \ + __atomic_add_##type(p, v, t); \ + } \ + /* _ATOMIC_ADD */ + +_ATOMIC_ADD(int) +_ATOMIC_ADD(long) + +#define atomic_add_32 atomic_add_int +#define atomic_add_acq_32 atomic_add_acq_int +#define atomic_add_rel_32 atomic_add_rel_int + +#ifdef __powerpc64__ +#define atomic_add_64 atomic_add_long +#define atomic_add_acq_64 atomic_add_acq_long +#define atomic_add_rel_64 atomic_add_rel_long + +#define atomic_add_ptr atomic_add_long +#define atomic_add_acq_ptr atomic_add_acq_long +#define atomic_add_rel_ptr atomic_add_rel_long +#else +#define atomic_add_ptr atomic_add_int +#define atomic_add_acq_ptr atomic_add_acq_int +#define atomic_add_rel_ptr atomic_add_rel_int +#endif +#undef _ATOMIC_ADD +#undef __atomic_add_long +#undef __atomic_add_int + +/* + * atomic_clear(p, v) + * { *p &= ~v; } + */ + +#define __atomic_clear_int(p, v, t) \ + __asm __volatile( \ + "1: lwarx %0, 0, %2\n" \ + " andc %0, %0, %3\n" \ + " stwcx. %0, 0, %2\n" \ + " bne- 1b\n" \ + : "=&r" (t), "=m" (*p) \ + : "r" (p), "r" (v), "m" (*p) \ + : "cr0", "memory") \ + /* __atomic_clear_int */ + +#ifdef __powerpc64__ +#define __atomic_clear_long(p, v, t) \ + __asm __volatile( \ + "1: ldarx %0, 0, %2\n" \ + " andc %0, %0, %3\n" \ + " stdcx. %0, 0, %2\n" \ + " bne- 1b\n" \ + : "=&r" (t), "=m" (*p) \ + : "r" (p), "r" (v), "m" (*p) \ + : "cr0", "memory") \ + /* __atomic_clear_long */ +#else +#define __atomic_clear_long(p, v, t) \ + __asm __volatile( \ + "1: lwarx %0, 0, %2\n" \ + " andc %0, %0, %3\n" \ + " stwcx. %0, 0, %2\n" \ + " bne- 1b\n" \ + : "=&r" (t), "=m" (*p) \ + : "r" (p), "r" (v), "m" (*p) \ + : "cr0", "memory") \ + /* __atomic_clear_long */ +#endif + +#define _ATOMIC_CLEAR(type) \ + static __inline void \ + atomic_clear_##type(volatile u_##type *p, u_##type v) { \ + u_##type t; \ + __atomic_clear_##type(p, v, t); \ + } \ + \ + static __inline void \ + atomic_clear_acq_##type(volatile u_##type *p, u_##type v) { \ + u_##type t; \ + __atomic_clear_##type(p, v, t); \ + __ATOMIC_ACQ(); \ + } \ + \ + static __inline void \ + atomic_clear_rel_##type(volatile u_##type *p, u_##type v) { \ + u_##type t; \ + __ATOMIC_REL(); \ + __atomic_clear_##type(p, v, t); \ + } \ + /* _ATOMIC_CLEAR */ + +_ATOMIC_CLEAR(int) +_ATOMIC_CLEAR(long) + +#define atomic_clear_32 atomic_clear_int +#define atomic_clear_acq_32 atomic_clear_acq_int +#define atomic_clear_rel_32 atomic_clear_rel_int + +#ifdef __powerpc64__ +#define atomic_clear_64 atomic_clear_long +#define atomic_clear_acq_64 atomic_clear_acq_long +#define atomic_clear_rel_64 atomic_clear_rel_long + +#define atomic_clear_ptr atomic_clear_long +#define atomic_clear_acq_ptr atomic_clear_acq_long +#define atomic_clear_rel_ptr atomic_clear_rel_long +#else +#define atomic_clear_ptr atomic_clear_int +#define atomic_clear_acq_ptr atomic_clear_acq_int +#define atomic_clear_rel_ptr atomic_clear_rel_int +#endif +#undef _ATOMIC_CLEAR +#undef __atomic_clear_long +#undef __atomic_clear_int + +/* + * atomic_cmpset(p, o, n) + */ +/* TODO -- see below */ + +/* + * atomic_load_acq(p) + */ +/* TODO -- see below */ + +/* + * atomic_readandclear(p) + */ +/* TODO -- see below */ + +/* + * atomic_set(p, v) + * { *p |= v; } + */ + +#define __atomic_set_int(p, v, t) \ + __asm __volatile( \ + "1: lwarx %0, 0, %2\n" \ + " or %0, %3, %0\n" \ + " stwcx. %0, 0, %2\n" \ + " bne- 1b\n" \ + : "=&r" (t), "=m" (*p) \ + : "r" (p), "r" (v), "m" (*p) \ + : "cr0", "memory") \ + /* __atomic_set_int */ + +#ifdef __powerpc64__ +#define __atomic_set_long(p, v, t) \ + __asm __volatile( \ + "1: ldarx %0, 0, %2\n" \ + " or %0, %3, %0\n" \ + " stdcx. %0, 0, %2\n" \ + " bne- 1b\n" \ + : "=&r" (t), "=m" (*p) \ + : "r" (p), "r" (v), "m" (*p) \ + : "cr0", "memory") \ + /* __atomic_set_long */ +#else +#define __atomic_set_long(p, v, t) \ + __asm __volatile( \ + "1: lwarx %0, 0, %2\n" \ + " or %0, %3, %0\n" \ + " stwcx. %0, 0, %2\n" \ + " bne- 1b\n" \ + : "=&r" (t), "=m" (*p) \ + : "r" (p), "r" (v), "m" (*p) \ + : "cr0", "memory") \ + /* __atomic_set_long */ +#endif + +#define _ATOMIC_SET(type) \ + static __inline void \ + atomic_set_##type(volatile u_##type *p, u_##type v) { \ + u_##type t; \ + __atomic_set_##type(p, v, t); \ + } \ + \ + static __inline void \ + atomic_set_acq_##type(volatile u_##type *p, u_##type v) { \ + u_##type t; \ + __atomic_set_##type(p, v, t); \ + __ATOMIC_ACQ(); \ + } \ + \ + static __inline void \ + atomic_set_rel_##type(volatile u_##type *p, u_##type v) { \ + u_##type t; \ + __ATOMIC_REL(); \ + __atomic_set_##type(p, v, t); \ + } \ + /* _ATOMIC_SET */ + +_ATOMIC_SET(int) +_ATOMIC_SET(long) + +#define atomic_set_32 atomic_set_int +#define atomic_set_acq_32 atomic_set_acq_int +#define atomic_set_rel_32 atomic_set_rel_int + +#ifdef __powerpc64__ +#define atomic_set_64 atomic_set_long +#define atomic_set_acq_64 atomic_set_acq_long +#define atomic_set_rel_64 atomic_set_rel_long + +#define atomic_set_ptr atomic_set_long +#define atomic_set_acq_ptr atomic_set_acq_long +#define atomic_set_rel_ptr atomic_set_rel_long +#else +#define atomic_set_ptr atomic_set_int +#define atomic_set_acq_ptr atomic_set_acq_int +#define atomic_set_rel_ptr atomic_set_rel_int +#endif +#undef _ATOMIC_SET +#undef __atomic_set_long +#undef __atomic_set_int + +/* + * atomic_subtract(p, v) + * { *p -= v; } + */ + +#define __atomic_subtract_int(p, v, t) \ + __asm __volatile( \ + "1: lwarx %0, 0, %2\n" \ + " subf %0, %3, %0\n" \ + " stwcx. %0, 0, %2\n" \ + " bne- 1b\n" \ + : "=&r" (t), "=m" (*p) \ + : "r" (p), "r" (v), "m" (*p) \ + : "cr0", "memory") \ + /* __atomic_subtract_int */ + +#ifdef __powerpc64__ +#define __atomic_subtract_long(p, v, t) \ + __asm __volatile( \ + "1: ldarx %0, 0, %2\n" \ + " subf %0, %3, %0\n" \ + " stdcx. %0, 0, %2\n" \ + " bne- 1b\n" \ + : "=&r" (t), "=m" (*p) \ + : "r" (p), "r" (v), "m" (*p) \ + : "cr0", "memory") \ + /* __atomic_subtract_long */ +#else +#define __atomic_subtract_long(p, v, t) \ + __asm __volatile( \ + "1: lwarx %0, 0, %2\n" \ + " subf %0, %3, %0\n" \ + " stwcx. %0, 0, %2\n" \ + " bne- 1b\n" \ + : "=&r" (t), "=m" (*p) \ + : "r" (p), "r" (v), "m" (*p) \ + : "cr0", "memory") \ + /* __atomic_subtract_long */ +#endif + +#define _ATOMIC_SUBTRACT(type) \ + static __inline void \ + atomic_subtract_##type(volatile u_##type *p, u_##type v) { \ + u_##type t; \ + __atomic_subtract_##type(p, v, t); \ + } \ + \ + static __inline void \ + atomic_subtract_acq_##type(volatile u_##type *p, u_##type v) { \ + u_##type t; \ + __atomic_subtract_##type(p, v, t); \ + __ATOMIC_ACQ(); \ + } \ + \ + static __inline void \ + atomic_subtract_rel_##type(volatile u_##type *p, u_##type v) { \ + u_##type t; \ + __ATOMIC_REL(); \ + __atomic_subtract_##type(p, v, t); \ + } \ + /* _ATOMIC_SUBTRACT */ + +_ATOMIC_SUBTRACT(int) +_ATOMIC_SUBTRACT(long) + +#define atomic_subtract_32 atomic_subtract_int +#define atomic_subtract_acq_32 atomic_subtract_acq_int +#define atomic_subtract_rel_32 atomic_subtract_rel_int + +#ifdef __powerpc64__ +#define atomic_subtract_64 atomic_subtract_long +#define atomic_subtract_acq_64 atomic_subract_acq_long +#define atomic_subtract_rel_64 atomic_subtract_rel_long + +#define atomic_subtract_ptr atomic_subtract_long +#define atomic_subtract_acq_ptr atomic_subtract_acq_long +#define atomic_subtract_rel_ptr atomic_subtract_rel_long +#else +#define atomic_subtract_ptr atomic_subtract_int +#define atomic_subtract_acq_ptr atomic_subtract_acq_int +#define atomic_subtract_rel_ptr atomic_subtract_rel_int +#endif +#undef _ATOMIC_SUBTRACT +#undef __atomic_subtract_long +#undef __atomic_subtract_int + +/* + * atomic_store_rel(p, v) + */ +/* TODO -- see below */ + +/* + * Old/original implementations that still need revisiting. + */ + +static __inline u_int +atomic_readandclear_int(volatile u_int *addr) +{ + u_int result,temp; + + __asm __volatile ( + "\tsync\n" /* drain writes */ + "1:\tlwarx %0, 0, %3\n\t" /* load old value */ + "li %1, 0\n\t" /* load new value */ + "stwcx. %1, 0, %3\n\t" /* attempt to store */ + "bne- 1b\n\t" /* spin if failed */ + : "=&r"(result), "=&r"(temp), "=m" (*addr) + : "r" (addr), "m" (*addr) + : "cr0", "memory"); + + return (result); +} + +#ifdef __powerpc64__ +static __inline u_long +atomic_readandclear_long(volatile u_long *addr) +{ + u_long result,temp; + + __asm __volatile ( + "\tsync\n" /* drain writes */ + "1:\tldarx %0, 0, %3\n\t" /* load old value */ + "li %1, 0\n\t" /* load new value */ + "stdcx. %1, 0, %3\n\t" /* attempt to store */ + "bne- 1b\n\t" /* spin if failed */ + : "=&r"(result), "=&r"(temp), "=m" (*addr) + : "r" (addr), "m" (*addr) + : "cr0", "memory"); + + return (result); +} +#endif + +#define atomic_readandclear_32 atomic_readandclear_int + +#ifdef __powerpc64__ +#define atomic_readandclear_64 atomic_readandclear_long + +#define atomic_readandclear_ptr atomic_readandclear_long +#else +static __inline u_long +atomic_readandclear_long(volatile u_long *addr) +{ + + return ((u_long)atomic_readandclear_int((volatile u_int *)addr)); +} + +#define atomic_readandclear_ptr atomic_readandclear_int +#endif + +/* + * We assume that a = b will do atomic loads and stores. + */ +#define ATOMIC_STORE_LOAD(TYPE) \ +static __inline u_##TYPE \ +atomic_load_acq_##TYPE(const volatile u_##TYPE *p) \ +{ \ + u_##TYPE v; \ + \ + v = *p; \ + powerpc_lwsync(); \ + return (v); \ +} \ + \ +static __inline void \ +atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v) \ +{ \ + \ + powerpc_lwsync(); \ + *p = v; \ +} + +ATOMIC_STORE_LOAD(int) + +#define atomic_load_acq_32 atomic_load_acq_int +#define atomic_store_rel_32 atomic_store_rel_int + +#ifdef __powerpc64__ +ATOMIC_STORE_LOAD(long) + +#define atomic_load_acq_64 atomic_load_acq_long +#define atomic_store_rel_64 atomic_store_rel_long + +#define atomic_load_acq_ptr atomic_load_acq_long +#define atomic_store_rel_ptr atomic_store_rel_long +#else +static __inline u_long +atomic_load_acq_long(const volatile u_long *addr) +{ + + return ((u_long)atomic_load_acq_int((const volatile u_int *)addr)); +} + +static __inline void +atomic_store_rel_long(volatile u_long *addr, u_long val) +{ + + atomic_store_rel_int((volatile u_int *)addr, (u_int)val); +} + +#define atomic_load_acq_ptr atomic_load_acq_int +#define atomic_store_rel_ptr atomic_store_rel_int +#endif +#undef ATOMIC_STORE_LOAD + +/* + * Atomically compare the value stored at *p with cmpval and if the + * two values are equal, update the value of *p with newval. Returns + * zero if the compare failed, nonzero otherwise. + */ +#ifdef ISA_206_ATOMICS +static __inline int +atomic_cmpset_char(volatile u_char *p, u_char cmpval, u_char newval) +{ + int ret; + + __asm __volatile ( + "1:\tlbarx %0, 0, %2\n\t" /* load old value */ + "cmplw %3, %0\n\t" /* compare */ + "bne- 2f\n\t" /* exit if not equal */ + "stbcx. %4, 0, %2\n\t" /* attempt to store */ + "bne- 1b\n\t" /* spin if failed */ + "li %0, 1\n\t" /* success - retval = 1 */ + "b 3f\n\t" /* we've succeeded */ + "2:\n\t" + "stbcx. %0, 0, %2\n\t" /* clear reservation (74xx) */ + "li %0, 0\n\t" /* failure - retval = 0 */ + "3:\n\t" + : "=&r" (ret), "=m" (*p) + : "r" (p), "r" (cmpval), "r" (newval), "m" (*p) + : "cr0", "memory"); + + return (ret); +} + +static __inline int +atomic_cmpset_short(volatile u_short *p, u_short cmpval, u_short newval) +{ + int ret; + + __asm __volatile ( + "1:\tlharx %0, 0, %2\n\t" /* load old value */ + "cmplw %3, %0\n\t" /* compare */ + "bne- 2f\n\t" /* exit if not equal */ + "sthcx. %4, 0, %2\n\t" /* attempt to store */ + "bne- 1b\n\t" /* spin if failed */ + "li %0, 1\n\t" /* success - retval = 1 */ + "b 3f\n\t" /* we've succeeded */ + "2:\n\t" + "sthcx. %0, 0, %2\n\t" /* clear reservation (74xx) */ + "li %0, 0\n\t" /* failure - retval = 0 */ + "3:\n\t" + : "=&r" (ret), "=m" (*p) + : "r" (p), "r" (cmpval), "r" (newval), "m" (*p) + : "cr0", "memory"); + + return (ret); +} +#else +static __inline int +atomic_cmpset_masked(uint32_t *p, uint32_t cmpval, uint32_t newval, + uint32_t mask) +{ + int ret; + uint32_t tmp; + + __asm __volatile ( + "1:\tlwarx %2, 0, %3\n\t" /* load old value */ + "and %0, %2, %7\n\t" + "cmplw %4, %0\n\t" /* compare */ + "bne- 2f\n\t" /* exit if not equal */ + "andc %2, %2, %7\n\t" + "or %2, %2, %5\n\t" + "stwcx. %2, 0, %3\n\t" /* attempt to store */ + "bne- 1b\n\t" /* spin if failed */ + "li %0, 1\n\t" /* success - retval = 1 */ + "b 3f\n\t" /* we've succeeded */ + "2:\n\t" + "stwcx. %2, 0, %3\n\t" /* clear reservation (74xx) */ + "li %0, 0\n\t" /* failure - retval = 0 */ + "3:\n\t" + : "=&r" (ret), "=m" (*p), "+&r" (tmp) + : "r" (p), "r" (cmpval), "r" (newval), "m" (*p), + "r" (mask) + : "cr0", "memory"); + + return (ret); +} + +#define _atomic_cmpset_masked_word(a,o,v,m) atomic_cmpset_masked(a, o, v, m) +#endif + +static __inline int +atomic_cmpset_int(volatile u_int* p, u_int cmpval, u_int newval) +{ + int ret; + + __asm __volatile ( + "1:\tlwarx %0, 0, %2\n\t" /* load old value */ + "cmplw %3, %0\n\t" /* compare */ + "bne- 2f\n\t" /* exit if not equal */ + "stwcx. %4, 0, %2\n\t" /* attempt to store */ + "bne- 1b\n\t" /* spin if failed */ + "li %0, 1\n\t" /* success - retval = 1 */ + "b 3f\n\t" /* we've succeeded */ + "2:\n\t" + "stwcx. %0, 0, %2\n\t" /* clear reservation (74xx) */ + "li %0, 0\n\t" /* failure - retval = 0 */ + "3:\n\t" + : "=&r" (ret), "=m" (*p) + : "r" (p), "r" (cmpval), "r" (newval), "m" (*p) + : "cr0", "memory"); + + return (ret); +} +static __inline int +atomic_cmpset_long(volatile u_long* p, u_long cmpval, u_long newval) +{ + int ret; + + __asm __volatile ( + #ifdef __powerpc64__ + "1:\tldarx %0, 0, %2\n\t" /* load old value */ + "cmpld %3, %0\n\t" /* compare */ + "bne- 2f\n\t" /* exit if not equal */ + "stdcx. %4, 0, %2\n\t" /* attempt to store */ + #else + "1:\tlwarx %0, 0, %2\n\t" /* load old value */ + "cmplw %3, %0\n\t" /* compare */ + "bne- 2f\n\t" /* exit if not equal */ + "stwcx. %4, 0, %2\n\t" /* attempt to store */ + #endif + "bne- 1b\n\t" /* spin if failed */ + "li %0, 1\n\t" /* success - retval = 1 */ + "b 3f\n\t" /* we've succeeded */ + "2:\n\t" + #ifdef __powerpc64__ + "stdcx. %0, 0, %2\n\t" /* clear reservation (74xx) */ + #else + "stwcx. %0, 0, %2\n\t" /* clear reservation (74xx) */ + #endif + "li %0, 0\n\t" /* failure - retval = 0 */ + "3:\n\t" + : "=&r" (ret), "=m" (*p) + : "r" (p), "r" (cmpval), "r" (newval), "m" (*p) + : "cr0", "memory"); + + return (ret); +} + +#define ATOMIC_CMPSET_ACQ_REL(type) \ + static __inline int \ + atomic_cmpset_acq_##type(volatile u_##type *p, \ + u_##type cmpval, u_##type newval)\ + {\ + u_##type retval; \ + retval = atomic_cmpset_##type(p, cmpval, newval);\ + __ATOMIC_ACQ();\ + return (retval);\ + }\ + static __inline int \ + atomic_cmpset_rel_##type(volatile u_##type *p, \ + u_##type cmpval, u_##type newval)\ + {\ + __ATOMIC_REL();\ + return (atomic_cmpset_##type(p, cmpval, newval));\ + }\ + struct hack + +ATOMIC_CMPSET_ACQ_REL(int); +ATOMIC_CMPSET_ACQ_REL(long); + +#ifdef ISA_206_ATOMICS +#define atomic_cmpset_8 atomic_cmpset_char +#endif +#define atomic_cmpset_acq_8 atomic_cmpset_acq_char +#define atomic_cmpset_rel_8 atomic_cmpset_rel_char + +#ifdef ISA_206_ATOMICS +#define atomic_cmpset_16 atomic_cmpset_short +#endif +#define atomic_cmpset_acq_16 atomic_cmpset_acq_short +#define atomic_cmpset_rel_16 atomic_cmpset_rel_short + +#define atomic_cmpset_32 atomic_cmpset_int +#define atomic_cmpset_acq_32 atomic_cmpset_acq_int +#define atomic_cmpset_rel_32 atomic_cmpset_rel_int + +#ifdef __powerpc64__ +#define atomic_cmpset_64 atomic_cmpset_long +#define atomic_cmpset_acq_64 atomic_cmpset_acq_long +#define atomic_cmpset_rel_64 atomic_cmpset_rel_long + +#define atomic_cmpset_ptr atomic_cmpset_long +#define atomic_cmpset_acq_ptr atomic_cmpset_acq_long +#define atomic_cmpset_rel_ptr atomic_cmpset_rel_long +#else +#define atomic_cmpset_ptr atomic_cmpset_int +#define atomic_cmpset_acq_ptr atomic_cmpset_acq_int +#define atomic_cmpset_rel_ptr atomic_cmpset_rel_int +#endif + +/* + * Atomically compare the value stored at *p with *cmpval and if the + * two values are equal, update the value of *p with newval. Returns + * zero if the compare failed and sets *cmpval to the read value from *p, + * nonzero otherwise. + */ +#ifdef ISA_206_ATOMICS +static __inline int +atomic_fcmpset_char(volatile u_char *p, u_char *cmpval, u_char newval) +{ + int ret; + + __asm __volatile ( + "lbarx %0, 0, %3\n\t" /* load old value */ + "cmplw %4, %0\n\t" /* compare */ + "bne- 1f\n\t" /* exit if not equal */ + "stbcx. %5, 0, %3\n\t" /* attempt to store */ + "bne- 1f\n\t" /* exit if failed */ + "li %0, 1\n\t" /* success - retval = 1 */ + "b 2f\n\t" /* we've succeeded */ + "1:\n\t" + "stbcx. %0, 0, %3\n\t" /* clear reservation (74xx) */ + "stbx %0, 0, %7\n\t" + "li %0, 0\n\t" /* failure - retval = 0 */ + "2:\n\t" + : "=&r" (ret), "=m" (*p), "=m" (*cmpval) + : "r" (p), "r" (*cmpval), "r" (newval), "m" (*p), "r"(cmpval) + : "cr0", "memory"); + + return (ret); +} + +static __inline int +atomic_fcmpset_short(volatile u_short *p, u_short *cmpval, u_short newval) +{ + int ret; + + __asm __volatile ( + "lharx %0, 0, %3\n\t" /* load old value */ + "cmplw %4, %0\n\t" /* compare */ + "bne- 1f\n\t" /* exit if not equal */ + "sthcx. %5, 0, %3\n\t" /* attempt to store */ + "bne- 1f\n\t" /* exit if failed */ + "li %0, 1\n\t" /* success - retval = 1 */ + "b 2f\n\t" /* we've succeeded */ + "1:\n\t" + "sthcx. %0, 0, %3\n\t" /* clear reservation (74xx) */ + "sthx %0, 0, %7\n\t" + "li %0, 0\n\t" /* failure - retval = 0 */ + "2:\n\t" + : "=&r" (ret), "=m" (*p), "=m" (*cmpval) + : "r" (p), "r" (*cmpval), "r" (newval), "m" (*p), "r"(cmpval) + : "cr0", "memory"); + + return (ret); +} +#endif /* ISA_206_ATOMICS */ + +static __inline int +atomic_fcmpset_int(volatile u_int *p, u_int *cmpval, u_int newval) +{ + int ret; + + __asm __volatile ( + "lwarx %0, 0, %3\n\t" /* load old value */ + "cmplw %4, %0\n\t" /* compare */ + "bne- 1f\n\t" /* exit if not equal */ + "stwcx. %5, 0, %3\n\t" /* attempt to store */ + "bne- 1f\n\t" /* exit if failed */ + "li %0, 1\n\t" /* success - retval = 1 */ + "b 2f\n\t" /* we've succeeded */ + "1:\n\t" + "stwcx. %0, 0, %3\n\t" /* clear reservation (74xx) */ + "stwx %0, 0, %7\n\t" + "li %0, 0\n\t" /* failure - retval = 0 */ + "2:\n\t" + : "=&r" (ret), "=m" (*p), "=m" (*cmpval) + : "r" (p), "r" (*cmpval), "r" (newval), "m" (*p), "r"(cmpval) + : "cr0", "memory"); + + return (ret); +} +static __inline int +atomic_fcmpset_long(volatile u_long *p, u_long *cmpval, u_long newval) +{ + int ret; + + __asm __volatile ( + #ifdef __powerpc64__ + "ldarx %0, 0, %3\n\t" /* load old value */ + "cmpld %4, %0\n\t" /* compare */ + "bne- 1f\n\t" /* exit if not equal */ + "stdcx. %5, 0, %3\n\t" /* attempt to store */ + #else + "lwarx %0, 0, %3\n\t" /* load old value */ + "cmplw %4, %0\n\t" /* compare */ + "bne- 1f\n\t" /* exit if not equal */ + "stwcx. %5, 0, %3\n\t" /* attempt to store */ + #endif + "bne- 1f\n\t" /* exit if failed */ + "li %0, 1\n\t" /* success - retval = 1 */ + "b 2f\n\t" /* we've succeeded */ + "1:\n\t" + #ifdef __powerpc64__ + "stdcx. %0, 0, %3\n\t" /* clear reservation (74xx) */ + "stdx %0, 0, %7\n\t" + #else + "stwcx. %0, 0, %3\n\t" /* clear reservation (74xx) */ + "stwx %0, 0, %7\n\t" + #endif + "li %0, 0\n\t" /* failure - retval = 0 */ + "2:\n\t" + : "=&r" (ret), "=m" (*p), "=m" (*cmpval) + : "r" (p), "r" (*cmpval), "r" (newval), "m" (*p), "r"(cmpval) + : "cr0", "memory"); + + return (ret); +} + +#define ATOMIC_FCMPSET_ACQ_REL(type) \ + static __inline int \ + atomic_fcmpset_acq_##type(volatile u_##type *p, \ + u_##type *cmpval, u_##type newval)\ + {\ + u_##type retval; \ + retval = atomic_fcmpset_##type(p, cmpval, newval);\ + __ATOMIC_ACQ();\ + return (retval);\ + }\ + static __inline int \ + atomic_fcmpset_rel_##type(volatile u_##type *p, \ + u_##type *cmpval, u_##type newval)\ + {\ + __ATOMIC_REL();\ + return (atomic_fcmpset_##type(p, cmpval, newval));\ + }\ + struct hack + +ATOMIC_FCMPSET_ACQ_REL(int); +ATOMIC_FCMPSET_ACQ_REL(long); + +#ifdef ISA_206_ATOMICS +#define atomic_fcmpset_8 atomic_fcmpset_char +#endif +#define atomic_fcmpset_acq_8 atomic_fcmpset_acq_char +#define atomic_fcmpset_rel_8 atomic_fcmpset_rel_char + +#ifdef ISA_206_ATOMICS +#define atomic_fcmpset_16 atomic_fcmpset_short +#endif +#define atomic_fcmpset_acq_16 atomic_fcmpset_acq_short +#define atomic_fcmpset_rel_16 atomic_fcmpset_rel_short + +#define atomic_fcmpset_32 atomic_fcmpset_int +#define atomic_fcmpset_acq_32 atomic_fcmpset_acq_int +#define atomic_fcmpset_rel_32 atomic_fcmpset_rel_int + +#ifdef __powerpc64__ +#define atomic_fcmpset_64 atomic_fcmpset_long +#define atomic_fcmpset_acq_64 atomic_fcmpset_acq_long +#define atomic_fcmpset_rel_64 atomic_fcmpset_rel_long + +#define atomic_fcmpset_ptr atomic_fcmpset_long +#define atomic_fcmpset_acq_ptr atomic_fcmpset_acq_long +#define atomic_fcmpset_rel_ptr atomic_fcmpset_rel_long +#else +#define atomic_fcmpset_ptr atomic_fcmpset_int +#define atomic_fcmpset_acq_ptr atomic_fcmpset_acq_int +#define atomic_fcmpset_rel_ptr atomic_fcmpset_rel_int +#endif + +static __inline u_int +atomic_fetchadd_int(volatile u_int *p, u_int v) +{ + u_int value; + + do { + value = *p; + } while (!atomic_cmpset_int(p, value, value + v)); + return (value); +} + +static __inline u_long +atomic_fetchadd_long(volatile u_long *p, u_long v) +{ + u_long value; + + do { + value = *p; + } while (!atomic_cmpset_long(p, value, value + v)); + return (value); +} + +static __inline u_int +atomic_swap_32(volatile u_int *p, u_int v) +{ + u_int prev; + + __asm __volatile( + "1: lwarx %0,0,%2\n" + " stwcx. %3,0,%2\n" + " bne- 1b\n" + : "=&r" (prev), "+m" (*(volatile u_int *)p) + : "r" (p), "r" (v) + : "cr0", "memory"); + + return (prev); +} + +#ifdef __powerpc64__ +static __inline u_long +atomic_swap_64(volatile u_long *p, u_long v) +{ + u_long prev; + + __asm __volatile( + "1: ldarx %0,0,%2\n" + " stdcx. %3,0,%2\n" + " bne- 1b\n" + : "=&r" (prev), "+m" (*(volatile u_long *)p) + : "r" (p), "r" (v) + : "cr0", "memory"); + + return (prev); +} +#endif + +#define atomic_fetchadd_32 atomic_fetchadd_int +#define atomic_swap_int atomic_swap_32 + +#ifdef __powerpc64__ +#define atomic_fetchadd_64 atomic_fetchadd_long +#define atomic_swap_long atomic_swap_64 +#define atomic_swap_ptr atomic_swap_64 +#else +#define atomic_swap_long(p,v) atomic_swap_32((volatile u_int *)(p), v) +#define atomic_swap_ptr(p,v) atomic_swap_32((volatile u_int *)(p), v) +#endif + +static __inline int +atomic_testandset_int(volatile u_int *p, u_int v) +{ + u_int m = (1u << (v & 0x1f)); + u_int res; + u_int tmp; + + __asm __volatile( + "1: lwarx %0,0,%3\n" + " and %1,%0,%4\n" + " or %0,%0,%4\n" + " stwcx. %0,0,%3\n" + " bne- 1b\n" + : "=&r"(tmp), "=&r"(res), "+m"(*p) + : "r"(p), "r"(m) + : "cr0", "memory"); + + return (res != 0); +} + +static __inline int +atomic_testandclear_int(volatile u_int *p, u_int v) +{ + u_int m = (1u << (v & 0x1f)); + u_int res; + u_int tmp; + + __asm __volatile( + "1: lwarx %0,0,%3\n" + " and %1,%0,%4\n" + " andc %0,%0,%4\n" + " stwcx. %0,0,%3\n" + " bne- 1b\n" + : "=&r"(tmp), "=&r"(res), "+m"(*p) + : "r"(p), "r"(m) + : "cr0", "memory"); + + return (res != 0); +} + +#ifdef __powerpc64__ +static __inline int +atomic_testandset_long(volatile u_long *p, u_int v) +{ + u_long m = (1ul << (v & 0x3f)); + u_long res; + u_long tmp; + + __asm __volatile( + "1: ldarx %0,0,%3\n" + " and %1,%0,%4\n" + " or %0,%0,%4\n" + " stdcx. %0,0,%3\n" + " bne- 1b\n" + : "=&r"(tmp), "=&r"(res), "+m"(*(volatile u_long *)p) + : "r"(p), "r"(m) + : "cr0", "memory"); + + return (res != 0); +} + +static __inline int +atomic_testandclear_long(volatile u_long *p, u_int v) +{ + u_long m = (1ul << (v & 0x3f)); + u_long res; + u_long tmp; + + __asm __volatile( + "1: ldarx %0,0,%3\n" + " and %1,%0,%4\n" + " andc %0,%0,%4\n" + " stdcx. %0,0,%3\n" + " bne- 1b\n" + : "=&r"(tmp), "=&r"(res), "+m"(*p) + : "r"(p), "r"(m) + : "cr0", "memory"); + + return (res != 0); +} +#else +static __inline int +atomic_testandset_long(volatile u_long *p, u_int v) +{ + return (atomic_testandset_int((volatile u_int *)p, v)); +} + +static __inline int +atomic_testandclear_long(volatile u_long *p, u_int v) +{ + return (atomic_testandclear_int((volatile u_int *)p, v)); +} +#endif + +#define atomic_testandclear_32 atomic_testandclear_int +#define atomic_testandset_32 atomic_testandset_int + +static __inline int +atomic_testandset_acq_long(volatile u_long *p, u_int v) +{ + u_int a = atomic_testandset_long(p, v); + __ATOMIC_ACQ(); + return (a); +} + +#ifdef __powerpc64__ +#define atomic_testandclear_ptr atomic_testandclear_long +#define atomic_testandset_ptr atomic_testandset_long +#else +#define atomic_testandclear_ptr(p,v) \ + atomic_testandclear_32((volatile u_int *)(p), v) +#define atomic_testandset_ptr(p,v) \ + atomic_testandset_32((volatile u_int *)(p), v) +#endif + +static __inline void +atomic_thread_fence_acq(void) +{ + + powerpc_lwsync(); +} + +static __inline void +atomic_thread_fence_rel(void) +{ + + powerpc_lwsync(); +} + +static __inline void +atomic_thread_fence_acq_rel(void) +{ + + powerpc_lwsync(); +} + +static __inline void +atomic_thread_fence_seq_cst(void) +{ + + __asm __volatile("sync" : : : "memory"); +} + +#ifndef ISA_206_ATOMICS +#include +#define atomic_cmpset_char atomic_cmpset_8 +#define atomic_cmpset_short atomic_cmpset_16 +#define atomic_fcmpset_char atomic_fcmpset_8 +#define atomic_fcmpset_short atomic_fcmpset_16 +#define atomic_set_short atomic_set_16 +#define atomic_clear_short atomic_clear_16 +#else + +static __inline void +atomic_set_short(volatile u_short *p, u_short bit) +{ + u_short v; + + v = atomic_load_short(p); + for (;;) { + if (atomic_fcmpset_16(p, &v, v | bit)) + break; + } +} + +static __inline void +atomic_clear_short(volatile u_short *p, u_short bit) +{ + u_short v; + + v = atomic_load_short(p); + for (;;) { + if (atomic_fcmpset_16(p, &v, v & ~bit)) + break; + } +} + +#define atomic_set_16 atomic_set_short +#define atomic_clear_16 atomic_clear_short + +#endif /* ISA_206_ATOMICS */ + +/* These need sys/_atomic_subword.h on non-ISA-2.06-atomic platforms. */ +ATOMIC_CMPSET_ACQ_REL(char); +ATOMIC_CMPSET_ACQ_REL(short); + +ATOMIC_FCMPSET_ACQ_REL(char); +ATOMIC_FCMPSET_ACQ_REL(short); + +#undef __ATOMIC_REL +#undef __ATOMIC_ACQ + +#endif /* ! _MACHINE_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/bat.h b/lib/libc/include/powerpc64-freebsd-none/machine/bat.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/bat.h rename to lib/libc/include/powerpc64-freebsd-none/machine/bat.h diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/bus.h b/lib/libc/include/powerpc64-freebsd-none/machine/bus.h new file mode 100644 index 000000000000..74b14ddfd53e --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/bus.h @@ -0,0 +1,493 @@ +/* $NetBSD: bus.h,v 1.11 2003/07/28 17:35:54 thorpej Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-2-Clause AND BSD-4-Clause + * + * Copyright (c) 1996, 1997, 1998, 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1996 Charles M. Hannum. All rights reserved. + * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BUS_H_ +#define _MACHINE_BUS_H_ + +#include + +#define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t) + +#define BUS_SPACE_MAXADDR_24BIT 0xFFFFFFUL +#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFFUL +#define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFFUL +#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFFUL + +#ifdef __powerpc64__ +#define BUS_SPACE_MAXADDR 0xFFFFFFFFFFFFFFFFUL +#define BUS_SPACE_MAXSIZE 0xFFFFFFFFFFFFFFFFUL +#else +#ifdef BOOKE +#define BUS_SPACE_MAXADDR 0xFFFFFFFFFULL +#define BUS_SPACE_MAXSIZE 0xFFFFFFFFUL +#else +#define BUS_SPACE_MAXADDR 0xFFFFFFFFUL +#define BUS_SPACE_MAXSIZE 0xFFFFFFFFUL +#endif +#endif + +#define BUS_SPACE_MAP_CACHEABLE 0x01 +#define BUS_SPACE_MAP_LINEAR 0x02 +#define BUS_SPACE_MAP_PREFETCHABLE 0x04 + +#define BUS_SPACE_UNRESTRICTED (~0) + +#define BUS_SPACE_BARRIER_READ 0x01 +#define BUS_SPACE_BARRIER_WRITE 0x02 + +struct bus_space_access; + +struct bus_space { + /* mapping/unmapping */ + int (*bs_map)(bus_addr_t, bus_size_t, int, + bus_space_handle_t *); + void (*bs_unmap)(bus_space_handle_t, bus_size_t); + int (*bs_subregion)(bus_space_handle_t, bus_size_t, + bus_size_t, bus_space_handle_t *); + + /* allocation/deallocation */ + int (*bs_alloc)(bus_addr_t, bus_addr_t, bus_size_t, + bus_size_t, bus_size_t, int, bus_addr_t *, bus_space_handle_t *); + void (*bs_free)(bus_space_handle_t, bus_size_t); + + void (*bs_barrier)(bus_space_handle_t, bus_size_t, + bus_size_t, int); + + /* Read single. */ + uint8_t (*bs_r_1)(bus_space_handle_t, bus_size_t); + uint16_t (*bs_r_2)(bus_space_handle_t, bus_size_t); + uint32_t (*bs_r_4)(bus_space_handle_t, bus_size_t); + uint64_t (*bs_r_8)(bus_space_handle_t, bus_size_t); + + uint16_t (*bs_r_s_2)(bus_space_handle_t, bus_size_t); + uint32_t (*bs_r_s_4)(bus_space_handle_t, bus_size_t); + uint64_t (*bs_r_s_8)(bus_space_handle_t, bus_size_t); + + /* read multiple */ + void (*bs_rm_1)(bus_space_handle_t, bus_size_t, uint8_t *, + bus_size_t); + void (*bs_rm_2)(bus_space_handle_t, bus_size_t, uint16_t *, + bus_size_t); + void (*bs_rm_4)(bus_space_handle_t, bus_size_t, uint32_t *, + bus_size_t); + void (*bs_rm_8)(bus_space_handle_t, bus_size_t, uint64_t *, + bus_size_t); + + void (*bs_rm_s_2)(bus_space_handle_t, bus_size_t, uint16_t *, + bus_size_t); + void (*bs_rm_s_4)(bus_space_handle_t, bus_size_t, uint32_t *, + bus_size_t); + void (*bs_rm_s_8)(bus_space_handle_t, bus_size_t, uint64_t *, + bus_size_t); + + /* read region */ + void (*bs_rr_1)(bus_space_handle_t, bus_size_t, uint8_t *, + bus_size_t); + void (*bs_rr_2)(bus_space_handle_t, bus_size_t, uint16_t *, + bus_size_t); + void (*bs_rr_4)(bus_space_handle_t, bus_size_t, uint32_t *, + bus_size_t); + void (*bs_rr_8)(bus_space_handle_t, bus_size_t, uint64_t *, + bus_size_t); + + void (*bs_rr_s_2)(bus_space_handle_t, bus_size_t, uint16_t *, + bus_size_t); + void (*bs_rr_s_4)(bus_space_handle_t, bus_size_t, uint32_t *, + bus_size_t); + void (*bs_rr_s_8)(bus_space_handle_t, bus_size_t, uint64_t *, + bus_size_t); + + /* write */ + void (*bs_w_1)(bus_space_handle_t, bus_size_t, uint8_t); + void (*bs_w_2)(bus_space_handle_t, bus_size_t, uint16_t); + void (*bs_w_4)(bus_space_handle_t, bus_size_t, uint32_t); + void (*bs_w_8)(bus_space_handle_t, bus_size_t, uint64_t); + + void (*bs_w_s_2)(bus_space_handle_t, bus_size_t, uint16_t); + void (*bs_w_s_4)(bus_space_handle_t, bus_size_t, uint32_t); + void (*bs_w_s_8)(bus_space_handle_t, bus_size_t, uint64_t); + + /* write multiple */ + void (*bs_wm_1)(bus_space_handle_t, bus_size_t, + const uint8_t *, bus_size_t); + void (*bs_wm_2)(bus_space_handle_t, bus_size_t, + const uint16_t *, bus_size_t); + void (*bs_wm_4)(bus_space_handle_t, bus_size_t, + const uint32_t *, bus_size_t); + void (*bs_wm_8)(bus_space_handle_t, bus_size_t, + const uint64_t *, bus_size_t); + + void (*bs_wm_s_2)(bus_space_handle_t, bus_size_t, + const uint16_t *, bus_size_t); + void (*bs_wm_s_4)(bus_space_handle_t, bus_size_t, + const uint32_t *, bus_size_t); + void (*bs_wm_s_8)(bus_space_handle_t, bus_size_t, + const uint64_t *, bus_size_t); + + /* write region */ + void (*bs_wr_1)(bus_space_handle_t, bus_size_t, + const uint8_t *, bus_size_t); + void (*bs_wr_2)(bus_space_handle_t, bus_size_t, + const uint16_t *, bus_size_t); + void (*bs_wr_4)(bus_space_handle_t, bus_size_t, + const uint32_t *, bus_size_t); + void (*bs_wr_8)(bus_space_handle_t, bus_size_t, + const uint64_t *, bus_size_t); + + void (*bs_wr_s_2)(bus_space_handle_t, bus_size_t, + const uint16_t *, bus_size_t); + void (*bs_wr_s_4)(bus_space_handle_t, bus_size_t, + const uint32_t *, bus_size_t); + void (*bs_wr_s_8)(bus_space_handle_t, bus_size_t, + const uint64_t *, bus_size_t); + + /* set multiple */ + void (*bs_sm_1)(bus_space_handle_t, bus_size_t, uint8_t, + bus_size_t); + void (*bs_sm_2)(bus_space_handle_t, bus_size_t, uint16_t, + bus_size_t); + void (*bs_sm_4)(bus_space_handle_t, bus_size_t, uint32_t, + bus_size_t); + void (*bs_sm_8)(bus_space_handle_t, bus_size_t, uint64_t, + bus_size_t); + + void (*bs_sm_s_2)(bus_space_handle_t, bus_size_t, uint16_t, + bus_size_t); + void (*bs_sm_s_4)(bus_space_handle_t, bus_size_t, uint32_t, + bus_size_t); + void (*bs_sm_s_8)(bus_space_handle_t, bus_size_t, uint64_t, + bus_size_t); + + /* set region */ + void (*bs_sr_1)(bus_space_handle_t, bus_size_t, uint8_t, + bus_size_t); + void (*bs_sr_2)(bus_space_handle_t, bus_size_t, uint16_t, + bus_size_t); + void (*bs_sr_4)(bus_space_handle_t, bus_size_t, uint32_t, + bus_size_t); + void (*bs_sr_8)(bus_space_handle_t, bus_size_t, uint64_t, + bus_size_t); + + void (*bs_sr_s_2)(bus_space_handle_t, bus_size_t, uint16_t, + bus_size_t); + void (*bs_sr_s_4)(bus_space_handle_t, bus_size_t, uint32_t, + bus_size_t); + void (*bs_sr_s_8)(bus_space_handle_t, bus_size_t, uint64_t, + bus_size_t); + + /* copy region */ + void (*bs_cr_1)(bus_space_handle_t, bus_size_t, + bus_space_handle_t, bus_size_t, bus_size_t); + void (*bs_cr_2)(bus_space_handle_t, bus_size_t, + bus_space_handle_t, bus_size_t, bus_size_t); + void (*bs_cr_4)(bus_space_handle_t, bus_size_t, + bus_space_handle_t, bus_size_t, bus_size_t); + void (*bs_cr_8)(bus_space_handle_t, bus_size_t, + bus_space_handle_t, bus_size_t, bus_size_t); + + void (*bs_cr_s_2)(bus_space_handle_t, bus_size_t, + bus_space_handle_t, bus_size_t, bus_size_t); + void (*bs_cr_s_4)(bus_space_handle_t, bus_size_t, + bus_space_handle_t, bus_size_t, bus_size_t); + void (*bs_cr_s_8)(bus_space_handle_t, bus_size_t, + bus_space_handle_t, bus_size_t, bus_size_t); +}; + +extern struct bus_space bs_be_tag; +extern struct bus_space bs_le_tag; + +#define __bs_c(a,b) __CONCAT(a,b) +#define __bs_opname(op,size) __bs_c(__bs_c(__bs_c(bs_,op),_),size) + +#define __bs_rs(sz, t, h, o) \ + (*(t)->__bs_opname(r,sz))(h, o) +#define __bs_ws(sz, t, h, o, v) \ + (*(t)->__bs_opname(w,sz))(h, o, v) +#define __bs_nonsingle(type, sz, t, h, o, a, c) \ + (*(t)->__bs_opname(type,sz))(h, o, a, c) +#define __bs_set(type, sz, t, h, o, v, c) \ + (*(t)->__bs_opname(type,sz))(h, o, v, c) +#define __bs_copy(sz, t, h1, o1, h2, o2, cnt) \ + (*(t)->__bs_opname(c,sz))(h1, o1, h2, o2, cnt) + +/* + * Mapping and unmapping operations. + */ +#define bus_space_map(t, a, s, c, hp) (*(t)->bs_map)(a, s, c, hp) +#define bus_space_unmap(t, h, s) (*(t)->bs_unmap)(h, s) +#define bus_space_subregion(t, h, o, s, hp) (*(t)->bs_subregion)(h, o, s, hp) + +/* + * Allocation and deallocation operations. + */ +#define bus_space_alloc(t, rs, re, s, a, b, c, ap, hp) \ + (*(t)->bs_alloc)(rs, re, s, a, b, c, ap, hp) +#define bus_space_free(t, h, s) \ + (*(t)->bs_free)(h, s) + +/* + * Bus barrier operations. + */ +#define bus_space_barrier(t, h, o, l, f) (*(t)->bs_barrier)(h, o, l, f) + +/* + * Bus read (single) operations. + */ +#define bus_space_read_1(t, h, o) __bs_rs(1,t,h,o) +#define bus_space_read_2(t, h, o) __bs_rs(2,t,h,o) +#define bus_space_read_4(t, h, o) __bs_rs(4,t,h,o) +#define bus_space_read_8(t, h, o) __bs_rs(8,t,h,o) + +#define bus_space_read_stream_1 bus_space_read_1 +#define bus_space_read_stream_2(t, h, o) __bs_rs(s_2,t,h,o) +#define bus_space_read_stream_4(t, h, o) __bs_rs(s_4,t,h,o) +#define bus_space_read_stream_8(t, h, o) __bs_rs(s_8,t,h,o) + +/* + * Bus read multiple operations. + */ +#define bus_space_read_multi_1(t, h, o, a, c) \ + __bs_nonsingle(rm,1,(t),(h),(o),(a),(c)) +#define bus_space_read_multi_2(t, h, o, a, c) \ + __bs_nonsingle(rm,2,(t),(h),(o),(a),(c)) +#define bus_space_read_multi_4(t, h, o, a, c) \ + __bs_nonsingle(rm,4,(t),(h),(o),(a),(c)) +#define bus_space_read_multi_8(t, h, o, a, c) \ + __bs_nonsingle(rm,8,(t),(h),(o),(a),(c)) + +#define bus_space_read_multi_stream_1 bus_space_read_multi_1 +#define bus_space_read_multi_stream_2(t, h, o, a, c) \ + __bs_nonsingle(rm,s_2,(t),(h),(o),(a),(c)) +#define bus_space_read_multi_stream_4(t, h, o, a, c) \ + __bs_nonsingle(rm,s_4,(t),(h),(o),(a),(c)) +#define bus_space_read_multi_stream_8(t, h, o, a, c) \ + __bs_nonsingle(rm,s_8,(t),(h),(o),(a),(c)) + +/* + * Bus read region operations. + */ +#define bus_space_read_region_1(t, h, o, a, c) \ + __bs_nonsingle(rr,1,(t),(h),(o),(a),(c)) +#define bus_space_read_region_2(t, h, o, a, c) \ + __bs_nonsingle(rr,2,(t),(h),(o),(a),(c)) +#define bus_space_read_region_4(t, h, o, a, c) \ + __bs_nonsingle(rr,4,(t),(h),(o),(a),(c)) +#define bus_space_read_region_8(t, h, o, a, c) \ + __bs_nonsingle(rr,8,(t),(h),(o),(a),(c)) + +#define bus_space_read_region_stream_1 bus_space_read_region_1 +#define bus_space_read_region_stream_2(t, h, o, a, c) \ + __bs_nonsingle(rr,s_2,(t),(h),(o),(a),(c)) +#define bus_space_read_region_stream_4(t, h, o, a, c) \ + __bs_nonsingle(rr,s_4,(t),(h),(o),(a),(c)) +#define bus_space_read_region_stream_8(t, h, o, a, c) \ + __bs_nonsingle(rr,s_8,(t),(h),(o),(a),(c)) + +/* + * Bus write (single) operations. + */ +#define bus_space_write_1(t, h, o, v) __bs_ws(1,(t),(h),(o),(v)) +#define bus_space_write_2(t, h, o, v) __bs_ws(2,(t),(h),(o),(v)) +#define bus_space_write_4(t, h, o, v) __bs_ws(4,(t),(h),(o),(v)) +#define bus_space_write_8(t, h, o, v) __bs_ws(8,(t),(h),(o),(v)) + +#define bus_space_write_stream_1 bus_space_write_1 +#define bus_space_write_stream_2(t, h, o, v) __bs_ws(s_2,(t),(h),(o),(v)) +#define bus_space_write_stream_4(t, h, o, v) __bs_ws(s_4,(t),(h),(o),(v)) +#define bus_space_write_stream_8(t, h, o, v) __bs_ws(s_8,(t),(h),(o),(v)) + +/* + * Bus write multiple operations. + */ +#define bus_space_write_multi_1(t, h, o, a, c) \ + __bs_nonsingle(wm,1,(t),(h),(o),(a),(c)) +#define bus_space_write_multi_2(t, h, o, a, c) \ + __bs_nonsingle(wm,2,(t),(h),(o),(a),(c)) +#define bus_space_write_multi_4(t, h, o, a, c) \ + __bs_nonsingle(wm,4,(t),(h),(o),(a),(c)) +#define bus_space_write_multi_8(t, h, o, a, c) \ + __bs_nonsingle(wm,8,(t),(h),(o),(a),(c)) + +#define bus_space_write_multi_stream_1 bus_space_write_multi_1 +#define bus_space_write_multi_stream_2(t, h, o, a, c) \ + __bs_nonsingle(wm,s_2,(t),(h),(o),(a),(c)) +#define bus_space_write_multi_stream_4(t, h, o, a, c) \ + __bs_nonsingle(wm,s_4,(t),(h),(o),(a),(c)) +#define bus_space_write_multi_stream_8(t, h, o, a, c) \ + __bs_nonsingle(wm,s_8,(t),(h),(o),(a),(c)) + +/* + * Bus write region operations. + */ +#define bus_space_write_region_1(t, h, o, a, c) \ + __bs_nonsingle(wr,1,(t),(h),(o),(a),(c)) +#define bus_space_write_region_2(t, h, o, a, c) \ + __bs_nonsingle(wr,2,(t),(h),(o),(a),(c)) +#define bus_space_write_region_4(t, h, o, a, c) \ + __bs_nonsingle(wr,4,(t),(h),(o),(a),(c)) +#define bus_space_write_region_8(t, h, o, a, c) \ + __bs_nonsingle(wr,8,(t),(h),(o),(a),(c)) + +#define bus_space_write_region_stream_1 bus_space_write_region_1 +#define bus_space_write_region_stream_2(t, h, o, a, c) \ + __bs_nonsingle(wr,s_2,(t),(h),(o),(a),(c)) +#define bus_space_write_region_stream_4(t, h, o, a, c) \ + __bs_nonsingle(wr,s_4,(t),(h),(o),(a),(c)) +#define bus_space_write_region_stream_8(t, h, o, a, c) \ + __bs_nonsingle(wr,s_8,(t),(h),(o),(a),(c)) + +/* + * Set multiple operations. + */ +#define bus_space_set_multi_1(t, h, o, v, c) \ + __bs_set(sm,1,(t),(h),(o),(v),(c)) +#define bus_space_set_multi_2(t, h, o, v, c) \ + __bs_set(sm,2,(t),(h),(o),(v),(c)) +#define bus_space_set_multi_4(t, h, o, v, c) \ + __bs_set(sm,4,(t),(h),(o),(v),(c)) +#define bus_space_set_multi_8(t, h, o, v, c) \ + __bs_set(sm,8,(t),(h),(o),(v),(c)) + +#define bus_space_set_multi_stream_1 bus_space_set_multi_1 +#define bus_space_set_multi_stream_2(t, h, o, v, c) \ + __bs_set(sm,s_2,(t),(h),(o),(v),(c)) +#define bus_space_set_multi_stream_4(t, h, o, v, c) \ + __bs_set(sm,s_4,(t),(h),(o),(v),(c)) +#define bus_space_set_multi_stream_8(t, h, o, v, c) \ + __bs_set(sm,s_8,(t),(h),(o),(v),(c)) + +/* + * Set region operations. + */ +#define bus_space_set_region_1(t, h, o, v, c) \ + __bs_set(sr,1,(t),(h),(o),(v),(c)) +#define bus_space_set_region_2(t, h, o, v, c) \ + __bs_set(sr,2,(t),(h),(o),(v),(c)) +#define bus_space_set_region_4(t, h, o, v, c) \ + __bs_set(sr,4,(t),(h),(o),(v),(c)) +#define bus_space_set_region_8(t, h, o, v, c) \ + __bs_set(sr,8,(t),(h),(o),(v),(c)) + +#define bus_space_set_region_stream_1 bus_space_set_region_1 +#define bus_space_set_region_stream_2(t, h, o, v, c) \ + __bs_set(sr,s_2,(t),(h),(o),(v),(c)) +#define bus_space_set_region_stream_4(t, h, o, v, c) \ + __bs_set(sr,s_4,(t),(h),(o),(v),(c)) +#define bus_space_set_region_stream_8(t, h, o, v, c) \ + __bs_set(sr,s_8,(t),(h),(o),(v),(c)) + +#if 0 +/* + * Copy operations. + */ +#define bus_space_copy_region_1(t, h1, o1, h2, o2, c) \ + __bs_copy(1, t, h1, o1, h2, o2, c) +#define bus_space_copy_region_2(t, h1, o1, h2, o2, c) \ + __bs_copy(2, t, h1, o1, h2, o2, c) +#define bus_space_copy_region_4(t, h1, o1, h2, o2, c) \ + __bs_copy(4, t, h1, o1, h2, o2, c) +#define bus_space_copy_region_8(t, h1, o1, h2, o2, c) \ + __bs_copy(8, t, h1, o1, h2, o2, c) + +#define bus_space_copy_region_stream_1 bus_space_copy_region_1 +#define bus_space_copy_region_stream_2(t, h1, o1, h2, o2, c) \ + __bs_copy(s_2, t, h1, o1, h2, o2, c) +#define bus_space_copy_region_stream_4(t, h1, o1, h2, o2, c) \ + __bs_copy(s_4, t, h1, o1, h2, o2, c) +#define bus_space_copy_region_stream_8(t, h1, o1, h2, o2, c) \ + __bs_copy(s_8, t, h1, o1, h2, o2, c) +#endif + +#define BUS_PEEK_FUNC(width, type) \ + static inline int \ + bus_space_peek_##width(bus_space_tag_t tag, \ + bus_space_handle_t hnd, bus_size_t offset, type *value) \ + { \ + type tmp; \ + tmp = bus_space_read_##width(tag, hnd, offset); \ + *value = (type)tmp; \ + return (0); \ + } +BUS_PEEK_FUNC(1, uint8_t) +BUS_PEEK_FUNC(2, uint16_t) +BUS_PEEK_FUNC(4, uint32_t) +BUS_PEEK_FUNC(8, uint64_t) + +#define BUS_POKE_FUNC(width, type) \ + static inline int \ + bus_space_poke_##width(bus_space_tag_t tag, \ + bus_space_handle_t hnd, bus_size_t offset, type value) \ + { \ + bus_space_write_##width(tag, hnd, offset, value); \ + return (0); \ + } +BUS_POKE_FUNC(1, uint8_t) +BUS_POKE_FUNC(2, uint16_t) +BUS_POKE_FUNC(4, uint32_t) +BUS_POKE_FUNC(8, uint64_t) + +#include + +#endif /* _MACHINE_BUS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/bus_dma.h b/lib/libc/include/powerpc64-freebsd-none/machine/bus_dma.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/bus_dma.h rename to lib/libc/include/powerpc64-freebsd-none/machine/bus_dma.h diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/clock.h b/lib/libc/include/powerpc64-freebsd-none/machine/clock.h new file mode 100644 index 000000000000..9998037028b5 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/clock.h @@ -0,0 +1,18 @@ +/*- + * Kernel interface to machine-dependent clock driver. + * Garrett Wollman, September 1994. + * This file is in the public domain. + */ + +#ifndef _MACHINE_CLOCK_H_ +#define _MACHINE_CLOCK_H_ + +#ifdef _KERNEL + +struct trapframe; + +void decr_intr(struct trapframe *); + +#endif + +#endif /* !_MACHINE_CLOCK_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/counter.h b/lib/libc/include/powerpc64-freebsd-none/machine/counter.h similarity index 99% rename from lib/libc/include/generic-freebsd/machine/counter.h rename to lib/libc/include/powerpc64-freebsd-none/machine/counter.h index 18618faf6cd4..b996a3d07e2c 100644 --- a/lib/libc/include/generic-freebsd/machine/counter.h +++ b/lib/libc/include/powerpc64-freebsd-none/machine/counter.h @@ -100,6 +100,8 @@ counter_u64_add(counter_u64_t c, int64_t inc) #else /* !64bit */ +#include + #define counter_enter() critical_enter() #define counter_exit() critical_exit() diff --git a/lib/libc/include/generic-freebsd/machine/cpu.h b/lib/libc/include/powerpc64-freebsd-none/machine/cpu.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/cpu.h rename to lib/libc/include/powerpc64-freebsd-none/machine/cpu.h diff --git a/lib/libc/include/generic-freebsd/machine/cpufunc.h b/lib/libc/include/powerpc64-freebsd-none/machine/cpufunc.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/cpufunc.h rename to lib/libc/include/powerpc64-freebsd-none/machine/cpufunc.h diff --git a/lib/libc/include/generic-freebsd/machine/db_machdep.h b/lib/libc/include/powerpc64-freebsd-none/machine/db_machdep.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/db_machdep.h rename to lib/libc/include/powerpc64-freebsd-none/machine/db_machdep.h diff --git a/lib/libc/include/generic-freebsd/machine/dbdma.h b/lib/libc/include/powerpc64-freebsd-none/machine/dbdma.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/dbdma.h rename to lib/libc/include/powerpc64-freebsd-none/machine/dbdma.h diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/dump.h b/lib/libc/include/powerpc64-freebsd-none/machine/dump.h new file mode 100644 index 000000000000..68051ae782c0 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/dump.h @@ -0,0 +1,73 @@ +/*- + * Copyright (c) 2014 EMC Corp. + * Author: Conrad Meyer + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_DUMP_H_ +#define _MACHINE_DUMP_H_ + +#define KERNELDUMP_ARCH_VERSION KERNELDUMP_POWERPC_VERSION +#define EM_VALUE ELF_ARCH /* Defined in powerpc/include/elf.h */ +#define DUMPSYS_MD_PA_NPAIRS (PHYS_AVAIL_SZ + 1) +#define DUMPSYS_NUM_AUX_HDRS 0 + +/* How often to check the dump progress bar? */ +#define DUMPSYS_PB_CHECK_BITS 20 /* Every 1MB */ + +void dumpsys_pa_init(void); +void dumpsys_unmap_chunk(vm_paddr_t, size_t, void *); +size_t dumpsys_scan_pmap(struct bitset *); +void *dumpsys_dump_pmap_init(unsigned blkpgs); +void *dumpsys_dump_pmap(void *ctx, void *buf, u_long *nbytes); + +static inline struct dump_pa * +dumpsys_pa_next(struct dump_pa *p) +{ + + return (dumpsys_gen_pa_next(p)); +} + +static inline void +dumpsys_wbinv_all(void) +{ + + dumpsys_gen_wbinv_all(); +} + +static inline int +dumpsys_write_aux_headers(struct dumperinfo *di) +{ + + return (dumpsys_gen_write_aux_headers(di)); +} + +static inline int +dumpsys(struct dumperinfo *di) +{ + + return (dumpsys_generic(di)); +} + +#endif /* !_MACHINE_DUMP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/efi.h b/lib/libc/include/powerpc64-freebsd-none/machine/efi.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/efi.h rename to lib/libc/include/powerpc64-freebsd-none/machine/efi.h diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/elf.h b/lib/libc/include/powerpc64-freebsd-none/machine/elf.h new file mode 100644 index 000000000000..b643c6592160 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/elf.h @@ -0,0 +1,146 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2001 David E. O'Brien + * Copyright (c) 1996-1997 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_ELF_H_ +#define _MACHINE_ELF_H_ 1 + +/* + * EABI ELF definitions for the PowerPC architecture. + * See "PowerPC Embedded Application Binary Interface, 32-Bit Impliementation" + * [ppc-eabi-1995-01.pdf] for details. + */ + +#ifndef __ELF_WORD_SIZE +#ifdef __powerpc64__ +#define __ELF_WORD_SIZE 64 /* Used by */ +#else +#define __ELF_WORD_SIZE 32 /* Used by */ +#endif +#endif + +#include /* Definitions common to all 32 bit architectures. */ +#include /* Definitions common to all 64 bit architectures. */ +#include + +#if __ELF_WORD_SIZE == 64 +#define ELF_ARCH EM_PPC64 +#define ELF_MACHINE_OK(x) ((x) == EM_PPC64) +#else +#define ELF_ARCH EM_PPC +#define ELF_ARCH32 EM_PPC +#define ELF_MACHINE_OK(x) ((x) == EM_PPC) +#endif + +/* + * Auxiliary vector entries for passing information to the interpreter. + * + * The PowerPC supplement to the SVR4 ABI specification names this "auxv_t", + * but POSIX lays claim to all symbols ending with "_t". + */ + +typedef struct { /* Auxiliary vector entry on initial stack */ + int a_type; /* Entry type. */ + union { +#ifdef __powerpc64__ + int a_val; /* Integer value */ +#else + long a_val; /* Integer value. */ + void *a_ptr; /* Address. */ + void (*a_fcn)(void); /* Function pointer (not used). */ +#endif + } a_un; +} Elf32_Auxinfo; + +typedef struct { /* Auxiliary vector entry on initial stack */ + long a_type; /* Entry type. */ + union { + long a_val; /* Integer value. */ + void *a_ptr; /* Address. */ + void (*a_fcn)(void); /* Function pointer (not used). */ + } a_un; +} Elf64_Auxinfo; + +__ElfType(Auxinfo); + +/* + * Relocation types. + */ + +#define R_PPC_COUNT 37 /* Count of defined relocation types. */ + + /* Count of defined relocation types. */ +#define R_PPC_EMB_COUNT (R_PPC_EMB_RELSDA - R_PPC_EMB_NADDR32 + 1) + +/* Define "machine" characteristics */ +#if BYTE_ORDER == LITTLE_ENDIAN +#define ELF_TARG_DATA ELFDATA2LSB +#else +#define ELF_TARG_DATA ELFDATA2MSB +#endif +#if __ELF_WORD_SIZE == 64 +#define ELF_TARG_CLASS ELFCLASS64 +#define ELF_TARG_MACH EM_PPC64 +#define ELF_TARG_VER 1 +#else +#define ELF_TARG_CLASS ELFCLASS32 +#define ELF_TARG_MACH EM_PPC +#define ELF_TARG_VER 1 +#endif + +#define ET_DYN_LOAD_ADDR 0x01010000 + +#define AT_OLD_NULL AT_NULL +#define AT_OLD_IGNORE AT_IGNORE +#define AT_OLD_EXECFD AT_EXECFD +#define AT_OLD_PHDR AT_PHDR +#define AT_OLD_PHENT AT_PHENT +#define AT_OLD_PHNUM AT_PHNUM +#define AT_OLD_PAGESZ AT_PAGESZ +#define AT_OLD_BASE AT_BASE +#define AT_OLD_FLAGS AT_FLAGS +#define AT_OLD_ENTRY AT_ENTRY +#define AT_OLD_NOTELF AT_NOTELF +#define AT_OLD_UID AT_UID +#define AT_OLD_EUID AT_EUID +#define AT_OLD_EXECPATH 13 +#define AT_OLD_CANARY 14 +#define AT_OLD_CANARYLEN 15 +#define AT_OLD_OSRELDATE 16 +#define AT_OLD_NCPUS 17 +#define AT_OLD_PAGESIZES 18 +#define AT_OLD_PAGESIZESLEN 19 +#define AT_OLD_STACKPROT 21 +#define AT_OLD_TIMEKEEP AT_TIMEKEEP +#define AT_OLD_EHDRFLAGS AT_EHDRFLAGS +#define AT_OLD_HWCAP AT_HWCAP +#define AT_OLD_HWCAP2 AT_HWCAP2 + +#define AT_OLD_COUNT 27 /* Count of defined aux entry types. */ + +#endif /* !_MACHINE_ELF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/endian.h b/lib/libc/include/powerpc64-freebsd-none/machine/endian.h new file mode 100644 index 000000000000..11f5bb5fd838 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/endian.h @@ -0,0 +1,38 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1987, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_ENDIAN_H_ +#define _MACHINE_ENDIAN_H_ + +#include +#include + +#endif /* !_MACHINE_ENDIAN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/exec.h b/lib/libc/include/powerpc64-freebsd-none/machine/exec.h new file mode 100644 index 000000000000..8a2c6bd93612 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/exec.h @@ -0,0 +1,37 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2001 David E. O'Brien + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_EXEC_H_ +#define _MACHINE_EXEC_H_ + +#define __LDPGSZ 4096 + +#endif /* !_MACHINE_EXEC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/float.h b/lib/libc/include/powerpc64-freebsd-none/machine/float.h new file mode 100644 index 000000000000..a832240666f0 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/float.h @@ -0,0 +1,98 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * from: FreeBSD: src/sys/i386/include/float.h,v 1.8 1999/08/28 00:44:11 + */ + +#ifndef _MACHINE_FLOAT_H_ +#define _MACHINE_FLOAT_H_ 1 + +#include + +#ifndef _SOFT_FLOAT +__BEGIN_DECLS +extern int __flt_rounds(void); +__END_DECLS +#define FLT_ROUNDS __flt_rounds() +#else +#define FLT_ROUNDS (-1) +#endif + +#define FLT_RADIX 2 /* b */ +#if __ISO_C_VISIBLE >= 1999 +#define FLT_EVAL_METHOD 0 +#define DECIMAL_DIG 17 /* max precision in decimal digits */ +#endif + +#define FLT_MANT_DIG 24 /* p */ +#define FLT_EPSILON 1.19209290E-07F /* b**(1-p) */ +#define FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ +#define FLT_MIN_EXP (-125) /* emin */ +#define FLT_MIN 1.17549435E-38F /* b**(emin-1) */ +#define FLT_MIN_10_EXP (-37) /* ceil(log10(b**(emin-1))) */ +#define FLT_MAX_EXP 128 /* emax */ +#define FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ +#define FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ +#if __ISO_C_VISIBLE >= 2011 +#define FLT_TRUE_MIN 1.40129846E-45F /* b**(emin-p) */ +#define FLT_DECIMAL_DIG 9 /* ceil(1+p*log10(b)) */ +#define FLT_HAS_SUBNORM 1 +#endif /* __ISO_C_VISIBLE >= 2011 */ + +#define DBL_MANT_DIG 53 +#define DBL_EPSILON 2.2204460492503131E-16 +#define DBL_DIG 15 +#define DBL_MIN_EXP (-1021) +#define DBL_MIN 2.2250738585072014E-308 +#define DBL_MIN_10_EXP (-307) +#define DBL_MAX_EXP 1024 +#define DBL_MAX 1.7976931348623157E+308 +#define DBL_MAX_10_EXP 308 +#if __ISO_C_VISIBLE >= 2011 +#define DBL_TRUE_MIN 4.9406564584124654E-324 +#define DBL_DECIMAL_DIG 17 +#define DBL_HAS_SUBNORM 1 +#endif /* __ISO_C_VISIBLE >= 2011 */ + +#define LDBL_MANT_DIG DBL_MANT_DIG +#define LDBL_EPSILON ((long double)DBL_EPSILON) +#define LDBL_DIG DBL_DIG +#define LDBL_MIN_EXP DBL_MIN_EXP +#define LDBL_MIN ((long double)DBL_MIN) +#define LDBL_MIN_10_EXP DBL_MIN_10_EXP +#define LDBL_MAX_EXP DBL_MAX_EXP +#define LDBL_MAX ((long double)DBL_MAX) +#define LDBL_MAX_10_EXP DBL_MAX_10_EXP +#if __ISO_C_VISIBLE >= 2011 +#define LDBL_TRUE_MIN ((long double)DBL_TRUE_MIN) +#define LDBL_DECIMAL_DIG DBL_DECIMAL_DIG +#define LDBL_HAS_SUBNORM DBL_HAS_SUBNORM +#endif /* __ISO_C_VISIBLE >= 2011 */ + +#endif /* _MACHINE_FLOAT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/floatingpoint.h b/lib/libc/include/powerpc64-freebsd-none/machine/floatingpoint.h new file mode 100644 index 000000000000..d2c7e15ad2e8 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/floatingpoint.h @@ -0,0 +1,37 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2004 Suleiman Souhlal + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY DAVID O'BRIEN AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _FLOATINGPOINT_H_ +#define _FLOATINGPOINT_H_ + +#include + +#endif /* !_FLOATINGPOINT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/fpu.h b/lib/libc/include/powerpc64-freebsd-none/machine/fpu.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/fpu.h rename to lib/libc/include/powerpc64-freebsd-none/machine/fpu.h diff --git a/lib/libc/include/generic-freebsd/machine/frame.h b/lib/libc/include/powerpc64-freebsd-none/machine/frame.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/frame.h rename to lib/libc/include/powerpc64-freebsd-none/machine/frame.h diff --git a/lib/libc/include/generic-freebsd/machine/gdb_machdep.h b/lib/libc/include/powerpc64-freebsd-none/machine/gdb_machdep.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/gdb_machdep.h rename to lib/libc/include/powerpc64-freebsd-none/machine/gdb_machdep.h diff --git a/lib/libc/include/generic-freebsd/machine/hid.h b/lib/libc/include/powerpc64-freebsd-none/machine/hid.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/hid.h rename to lib/libc/include/powerpc64-freebsd-none/machine/hid.h diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/ieee.h b/lib/libc/include/powerpc64-freebsd-none/machine/ieee.h new file mode 100644 index 000000000000..91686834c153 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/ieee.h @@ -0,0 +1,141 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * from: NetBSD: ieee.h,v 1.1.1.1 1998/06/20 04:58:51 eeh Exp + */ + +#ifndef _MACHINE_IEEE_H_ +#define _MACHINE_IEEE_H_ + +/* + * ieee.h defines the machine-dependent layout of the machine's IEEE + * floating point. It does *not* define (yet?) any of the rounding + * mode bits, exceptions, and so forth. + */ + +/* + * Define the number of bits in each fraction and exponent. + * + * k k+1 + * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented + * + * (-exp_bias+1) + * as fractions that look like 0.fffff x 2 . This means that + * + * -126 + * the number 0.10000 x 2 , for instance, is the same as the normalized + * + * -127 -128 + * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero + * + * -129 + * in the fraction; to represent 2 , we need two, and so on. This + * + * (-exp_bias-fracbits+1) + * implies that the smallest denormalized number is 2 + * + * for whichever format we are talking about: for single precision, for + * + * -126 -149 + * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and + * + * -149 == -127 - 23 + 1. + */ +#define SNG_EXPBITS 8 +#define SNG_FRACBITS 23 + +#define DBL_EXPBITS 11 +#define DBL_FRACBITS 52 + +#ifdef notyet +#define E80_EXPBITS 15 +#define E80_FRACBITS 64 +#endif + +#define EXT_EXPBITS 15 +#define EXT_FRACBITS 112 + +struct ieee_single { + u_int sng_sign:1; + u_int sng_exp:8; + u_int sng_frac:23; +}; + +struct ieee_double { + u_int dbl_sign:1; + u_int dbl_exp:11; + u_int dbl_frach:20; + u_int dbl_fracl; +}; + +struct ieee_ext { + u_int ext_sign:1; + u_int ext_exp:15; + u_int ext_frach:16; + u_int ext_frachm; + u_int ext_fraclm; + u_int ext_fracl; +}; + +/* + * Floats whose exponent is in [1..INFNAN) (of whatever type) are + * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. + * Floats whose exponent is zero are either zero (iff all fraction + * bits are zero) or subnormal values. + * + * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its + * high fraction; if the bit is set, it is a `quiet NaN'. + */ +#define SNG_EXP_INFNAN 255 +#define DBL_EXP_INFNAN 2047 +#define EXT_EXP_INFNAN 32767 + +#if 0 +#define SNG_QUIETNAN (1 << 22) +#define DBL_QUIETNAN (1 << 19) +#define EXT_QUIETNAN (1 << 15) +#endif + +/* + * Exponent biases. + */ +#define SNG_EXP_BIAS 127 +#define DBL_EXP_BIAS 1023 +#define EXT_EXP_BIAS 16383 + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/ieeefp.h b/lib/libc/include/powerpc64-freebsd-none/machine/ieeefp.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/ieeefp.h rename to lib/libc/include/powerpc64-freebsd-none/machine/ieeefp.h diff --git a/lib/libc/include/generic-freebsd/machine/ifunc.h b/lib/libc/include/powerpc64-freebsd-none/machine/ifunc.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/ifunc.h rename to lib/libc/include/powerpc64-freebsd-none/machine/ifunc.h diff --git a/lib/libc/include/generic-freebsd/machine/intr_machdep.h b/lib/libc/include/powerpc64-freebsd-none/machine/intr_machdep.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/intr_machdep.h rename to lib/libc/include/powerpc64-freebsd-none/machine/intr_machdep.h diff --git a/lib/libc/include/generic-freebsd/machine/kdb.h b/lib/libc/include/powerpc64-freebsd-none/machine/kdb.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/kdb.h rename to lib/libc/include/powerpc64-freebsd-none/machine/kdb.h diff --git a/lib/libc/include/generic-freebsd/machine/machdep.h b/lib/libc/include/powerpc64-freebsd-none/machine/machdep.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/machdep.h rename to lib/libc/include/powerpc64-freebsd-none/machine/machdep.h diff --git a/lib/libc/include/generic-freebsd/machine/md_var.h b/lib/libc/include/powerpc64-freebsd-none/machine/md_var.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/md_var.h rename to lib/libc/include/powerpc64-freebsd-none/machine/md_var.h diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/metadata.h b/lib/libc/include/powerpc64-freebsd-none/machine/metadata.h new file mode 100644 index 000000000000..e82eb2790b10 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/metadata.h @@ -0,0 +1,38 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2001 Jake Burkholder. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_METADATA_H_ +#define _MACHINE_METADATA_H_ + +#define MODINFOMD_ENVP 0x1001 +#define MODINFOMD_HOWTO 0x1002 +#define MODINFOMD_KERNEND 0x1003 +#define MODINFOMD_BOOTINFO 0x1004 +#define MODINFOMD_DTBP 0x1005 + +#endif /* !_MACHINE_METADATA_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/minidump.h b/lib/libc/include/powerpc64-freebsd-none/machine/minidump.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/minidump.h rename to lib/libc/include/powerpc64-freebsd-none/machine/minidump.h diff --git a/lib/libc/include/generic-freebsd/machine/mmuvar.h b/lib/libc/include/powerpc64-freebsd-none/machine/mmuvar.h similarity index 95% rename from lib/libc/include/generic-freebsd/machine/mmuvar.h rename to lib/libc/include/powerpc64-freebsd-none/machine/mmuvar.h index ee8265eec204..0eecb51adf90 100644 --- a/lib/libc/include/generic-freebsd/machine/mmuvar.h +++ b/lib/libc/include/powerpc64-freebsd-none/machine/mmuvar.h @@ -60,17 +60,17 @@ typedef void (*pmap_enter_object_t)(pmap_t, vm_offset_t, vm_offset_t, typedef void (*pmap_enter_quick_t)(pmap_t, vm_offset_t, vm_page_t, vm_prot_t); typedef vm_paddr_t (*pmap_extract_t)(pmap_t, vm_offset_t); typedef vm_page_t (*pmap_extract_and_hold_t)(pmap_t, vm_offset_t, vm_prot_t); -typedef void (*pmap_growkernel_t)(vm_offset_t); +typedef int (*pmap_growkernel_nopanic_t)(vm_offset_t); typedef void (*pmap_init_t)(void); -typedef boolean_t (*pmap_is_modified_t)(vm_page_t); -typedef boolean_t (*pmap_is_prefaultable_t)(pmap_t, vm_offset_t); -typedef boolean_t (*pmap_is_referenced_t)(vm_page_t); +typedef bool (*pmap_is_modified_t)(vm_page_t); +typedef bool (*pmap_is_prefaultable_t)(pmap_t, vm_offset_t); +typedef bool (*pmap_is_referenced_t)(vm_page_t); typedef int (*pmap_ts_referenced_t)(vm_page_t); typedef vm_offset_t (*pmap_map_t)(vm_offset_t *, vm_paddr_t, vm_paddr_t, int); typedef void (*pmap_object_init_pt_t)(pmap_t, vm_offset_t, vm_object_t, vm_pindex_t, vm_size_t); -typedef boolean_t (*pmap_page_exists_quick_t)(pmap_t, vm_page_t); -typedef boolean_t (*pmap_page_is_mapped_t)(vm_page_t); +typedef bool (*pmap_page_exists_quick_t)(pmap_t, vm_page_t); +typedef bool (*pmap_page_is_mapped_t)(vm_page_t); typedef void (*pmap_page_init_t)(vm_page_t); typedef int (*pmap_page_wired_mappings_t)(vm_page_t); typedef void (*pmap_pinit0_t)(pmap_t); @@ -130,7 +130,7 @@ struct pmap_funcs { pmap_enter_quick_t enter_quick; pmap_extract_t extract; pmap_extract_and_hold_t extract_and_hold; - pmap_growkernel_t growkernel; + pmap_growkernel_nopanic_t growkernel_nopanic; pmap_init_t init; pmap_is_modified_t is_modified; pmap_is_prefaultable_t is_prefaultable; diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/ofw_machdep.h b/lib/libc/include/powerpc64-freebsd-none/machine/ofw_machdep.h new file mode 100644 index 000000000000..1b059dd08cab --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/ofw_machdep.h @@ -0,0 +1,57 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2001 by Thomas Moestl . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_OFW_MACHDEP_H_ +#define _MACHINE_OFW_MACHDEP_H_ + +#include +#include +#include +#include +#include + +struct mem_region; +struct numa_mem_region; + +typedef uint32_t cell_t; + +void OF_getetheraddr(device_t dev, u_char *addr); + +void OF_initial_setup(void *fdt_ptr, void *junk, int (*openfirm)(void *)); +bool OF_bootstrap(void); + +void OF_reboot(void); + +void ofw_mem_regions(struct mem_region *, int *, struct mem_region *, int *); +void ofw_numa_mem_regions(struct numa_mem_region *, int *); +void ofw_quiesce(void); /* Must be called before VM is up! */ +void ofw_save_trap_vec(char *); +int ofw_pcibus_get_domain(device_t dev, device_t child, int *domain); +int ofw_pcibus_get_cpus(device_t dev, device_t child, enum cpu_sets op, + size_t setsize, cpuset_t *cpuset); + +#endif /* _MACHINE_OFW_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/openpicreg.h b/lib/libc/include/powerpc64-freebsd-none/machine/openpicreg.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/openpicreg.h rename to lib/libc/include/powerpc64-freebsd-none/machine/openpicreg.h diff --git a/lib/libc/include/generic-freebsd/machine/openpicvar.h b/lib/libc/include/powerpc64-freebsd-none/machine/openpicvar.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/openpicvar.h rename to lib/libc/include/powerpc64-freebsd-none/machine/openpicvar.h diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/param.h b/lib/libc/include/powerpc64-freebsd-none/machine/param.h new file mode 100644 index 000000000000..f4fc0a2efa62 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/param.h @@ -0,0 +1,150 @@ +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (c) 2001 David E. O'Brien + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _POWERPC_INCLUDE_PARAM_H_ +#define _POWERPC_INCLUDE_PARAM_H_ + +/* + * Machine dependent constants for PowerPC + */ + +#include + +#ifndef MACHINE +#define MACHINE "powerpc" +#endif +#ifndef MACHINE_ARCH +#ifdef __powerpc64__ +#if defined(__LITTLE_ENDIAN__) +#define MACHINE_ARCH "powerpc64le" +#else +#define MACHINE_ARCH "powerpc64" +#endif +#else +#ifdef __SPE__ +#define MACHINE_ARCH "powerpcspe" +#else +#define MACHINE_ARCH "powerpc" +#endif +#endif +#endif +#define MID_MACHINE MID_POWERPC +#ifdef __powerpc64__ +#ifndef MACHINE_ARCH32 +#define MACHINE_ARCH32 "powerpc" +#endif +#endif + +#ifdef SMP +#ifndef MAXCPU +#define MAXCPU 256 +#endif +#else +#define MAXCPU 1 +#endif + +#ifndef MAXMEMDOM +#define MAXMEMDOM 8 +#endif + +#define ALIGNBYTES _ALIGNBYTES +#define ALIGN(p) _ALIGN(p) +/* + * ALIGNED_POINTER is a boolean macro that checks whether an address + * is valid to fetch data elements of type t from on this architecture. + * This does not reflect the optimal alignment, just the possibility + * (within reasonable limits). + */ +#define ALIGNED_POINTER(p, t) ((((uintptr_t)(p)) & (sizeof (t) - 1)) == 0) + +/* + * CACHE_LINE_SIZE is the compile-time maximum cache line size for an + * architecture. It should be used with appropriate caution. + */ +#define CACHE_LINE_SHIFT 7 +#define CACHE_LINE_SIZE (1 << CACHE_LINE_SHIFT) + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) /* Page size */ +#define PAGE_MASK (PAGE_SIZE - 1) +#define NPTEPG (PAGE_SIZE/(sizeof (pt_entry_t))) +#define NPDEPG (PAGE_SIZE/(sizeof (pt_entry_t))) + +#define L1_PAGE_SIZE_SHIFT 39 +#define L1_PAGE_SIZE (1UL<> PAGE_SHIFT) +#define powerpc_ptob(x) ((x) << PAGE_SHIFT) + +#define btoc(x) ((vm_offset_t)(((x)+PAGE_MASK)>>PAGE_SHIFT)) + +#endif /* !_POWERPC_INCLUDE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/pcb.h b/lib/libc/include/powerpc64-freebsd-none/machine/pcb.h new file mode 100644 index 000000000000..a6f003b67de7 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/pcb.h @@ -0,0 +1,129 @@ +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + * + * $NetBSD: pcb.h,v 1.4 2000/06/04 11:57:17 tsubai Exp $ + */ + +#ifndef _MACHINE_PCB_H_ +#define _MACHINE_PCB_H_ + +#include + +#include + +#ifndef _STANDALONE +struct pcb { + register_t pcb_context[20]; /* non-volatile r12-r31 */ + register_t pcb_cr; /* Condition register */ + register_t pcb_sp; /* stack pointer */ + register_t pcb_toc; /* toc pointer */ + register_t pcb_lr; /* link register */ + register_t pcb_dscr; /* dscr value */ + register_t pcb_fscr; + register_t pcb_tar; + struct pmap *pcb_pm; /* pmap of our vmspace */ + jmp_buf *pcb_onfault; /* For use during + copyin/copyout */ + int pcb_flags; +#define PCB_FPU 0x1 /* Process uses FPU */ +#define PCB_FPREGS 0x2 /* Process had FPU registers initialized */ +#define PCB_VEC 0x4 /* Process uses Altivec */ +#define PCB_VSX 0x8 /* Process had VSX initialized */ +#define PCB_CDSCR 0x10 /* Process had Custom DSCR initialized */ +#define PCB_HTM 0x20 /* Process had HTM initialized */ +#define PCB_CFSCR 0x40 /* Process had FSCR updated */ +#define PCB_KERN_FPU 0x80 /* Kernel is using FPU/Vector unit */ +#define PCB_KERN_FPU_NOSAVE 0x100 /* FPU/Vec state not saved for kernel use */ +#define PCB_VECREGS 0x200 /* Process had Altivec registers initialized */ + struct fpu { + union { + uint32_t vsr[4]; + double fpr; + } fpr[32]; + double fpscr; /* FPSCR stored as double for easier access */ + } pcb_fpu; /* Floating point processor */ + unsigned int pcb_fpcpu; /* which CPU had our FPU + stuff. */ + struct vec { + uint32_t vr[32][4]; + uint32_t spare[2]; + uint32_t vrsave; + uint32_t vscr; /* aligned at vector element 3 */ + } pcb_vec __aligned(16); /* Vector processor */ + unsigned int pcb_veccpu; /* which CPU had our vector + stuff. */ + struct htm { + uint64_t tfhar; + uint64_t texasr; + uint64_t tfiar; + } pcb_htm; + + struct ebb { + uint64_t ebbhr; + uint64_t ebbrr; + uint64_t bescr; + } pcb_ebb; + + struct lmon { + uint64_t lmrr; + uint64_t lmser; + } pcb_lm; + + union { + struct { + vm_offset_t usr_segm; /* Base address */ + register_t usr_vsid; /* USER_SR segment */ + } aim; + struct { + register_t dbcr0; + } booke; + } pcb_cpu; + vm_offset_t pcb_lastill; /* Last illegal instruction */ +}; +#endif + +#ifdef _KERNEL + +struct trapframe; + +#ifndef curpcb +extern struct pcb *curpcb; +#endif + +extern struct pmap *curpm; +extern struct proc *fpuproc; + +void makectx(struct trapframe *, struct pcb *); +void savectx(struct pcb *) __returns_twice; + +#endif +#endif /* _MACHINE_PCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/pcpu.h b/lib/libc/include/powerpc64-freebsd-none/machine/pcpu.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/pcpu.h rename to lib/libc/include/powerpc64-freebsd-none/machine/pcpu.h diff --git a/lib/libc/include/generic-freebsd/machine/pio.h b/lib/libc/include/powerpc64-freebsd-none/machine/pio.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/pio.h rename to lib/libc/include/powerpc64-freebsd-none/machine/pio.h diff --git a/lib/libc/include/generic-freebsd/machine/platform.h b/lib/libc/include/powerpc64-freebsd-none/machine/platform.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/platform.h rename to lib/libc/include/powerpc64-freebsd-none/machine/platform.h diff --git a/lib/libc/include/generic-freebsd/machine/platformvar.h b/lib/libc/include/powerpc64-freebsd-none/machine/platformvar.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/platformvar.h rename to lib/libc/include/powerpc64-freebsd-none/machine/platformvar.h diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/pmap.h b/lib/libc/include/powerpc64-freebsd-none/machine/pmap.h new file mode 100644 index 000000000000..e83a788689cf --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/pmap.h @@ -0,0 +1,361 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause AND BSD-4-Clause + * + * Copyright (C) 2006 Semihalf, Marian Balakowicz + * All rights reserved. + * + * Adapted for Freescale's e500 core CPUs. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: $NetBSD: pmap.h,v 1.17 2000/03/30 16:18:24 jdolecek Exp $ + */ + +#ifndef _MACHINE_PMAP_H_ +#define _MACHINE_PMAP_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __powerpc64__ +#include +#endif + +/* + * The radix page table structure is described by levels 1-4. + * See Fig 33. on p. 1002 of Power ISA v3.0B + * + * Page directories and tables must be size aligned. + */ + +/* Root page directory - 64k -- each entry covers 512GB */ +typedef uint64_t pml1_entry_t; +/* l2 page directory - 4k -- each entry covers 1GB */ +typedef uint64_t pml2_entry_t; +/* l3 page directory - 4k -- each entry covers 2MB */ +typedef uint64_t pml3_entry_t; +/* l4 page directory - 256B/4k -- each entry covers 64k/4k */ +typedef uint64_t pml4_entry_t; + +typedef uint64_t pt_entry_t; + +struct pmap; +typedef struct pmap *pmap_t; + +#define PMAP_ENTER_QUICK_LOCKED 0x10000000 + +#if !defined(NPMAPS) +#define NPMAPS 32768 +#endif /* !defined(NPMAPS) */ + +struct slbtnode; + +struct pvo_entry { + LIST_ENTRY(pvo_entry) pvo_vlink; /* Link to common virt page */ +#ifndef __powerpc64__ + LIST_ENTRY(pvo_entry) pvo_olink; /* Link to overflow entry */ +#endif + union { + RB_ENTRY(pvo_entry) pvo_plink; /* Link to pmap entries */ + SLIST_ENTRY(pvo_entry) pvo_dlink; /* Link to delete enty */ + }; + struct { +#ifndef __powerpc64__ + /* 32-bit fields */ + pte_t pte; +#endif + /* 64-bit fields */ + uintptr_t slot; + vm_paddr_t pa; + vm_prot_t prot; + } pvo_pte; + pmap_t pvo_pmap; /* Owning pmap */ + vm_offset_t pvo_vaddr; /* VA of entry */ + uint64_t pvo_vpn; /* Virtual page number */ +}; +LIST_HEAD(pvo_head, pvo_entry); +SLIST_HEAD(pvo_dlist, pvo_entry); +RB_HEAD(pvo_tree, pvo_entry); +int pvo_vaddr_compare(struct pvo_entry *, struct pvo_entry *); +RB_PROTOTYPE(pvo_tree, pvo_entry, pvo_plink, pvo_vaddr_compare); + +/* Used by 32-bit PMAP */ +#define PVO_PTEGIDX_MASK 0x007UL /* which PTEG slot */ +#define PVO_PTEGIDX_VALID 0x008UL /* slot is valid */ +/* Used by 64-bit PMAP */ +#define PVO_HID 0x008UL /* PVO entry in alternate hash*/ +/* Used by both */ +#define PVO_WIRED 0x010UL /* PVO entry is wired */ +#define PVO_MANAGED 0x020UL /* PVO entry is managed */ +#define PVO_BOOTSTRAP 0x080UL /* PVO entry allocated during + bootstrap */ +#define PVO_DEAD 0x100UL /* waiting to be deleted */ +#define PVO_LARGE 0x200UL /* large page */ +#define PVO_VADDR(pvo) ((pvo)->pvo_vaddr & ~ADDR_POFF) +#define PVO_PTEGIDX_GET(pvo) ((pvo)->pvo_vaddr & PVO_PTEGIDX_MASK) +#define PVO_PTEGIDX_ISSET(pvo) ((pvo)->pvo_vaddr & PVO_PTEGIDX_VALID) +#define PVO_PTEGIDX_CLR(pvo) \ + ((void)((pvo)->pvo_vaddr &= ~(PVO_PTEGIDX_VALID|PVO_PTEGIDX_MASK))) +#define PVO_PTEGIDX_SET(pvo, i) \ + ((void)((pvo)->pvo_vaddr |= (i)|PVO_PTEGIDX_VALID)) +#define PVO_VSID(pvo) ((pvo)->pvo_vpn >> 16) + +struct pmap { + struct pmap_statistics pm_stats; + struct mtx pm_mtx; + cpuset_t pm_active; + union { + struct { + #ifdef __powerpc64__ + struct slbtnode *pm_slb_tree_root; + struct slb **pm_slb; + int pm_slb_len; + #else + register_t pm_sr[16]; + #endif + + struct pmap *pmap_phys; + struct pvo_tree pmap_pvo; + }; +#ifdef __powerpc64__ + /* Radix support */ + struct { + pml1_entry_t *pm_pml1; /* KVA of root page directory */ + struct vm_radix pm_radix; /* spare page table pages */ + TAILQ_HEAD(,pv_chunk) pm_pvchunk; /* list of mappings in pmap */ + uint64_t pm_pid; /* PIDR value */ + int pm_flags; + }; +#endif + struct { + /* TID to identify this pmap entries in TLB */ + tlbtid_t pm_tid[MAXCPU]; + +#ifdef __powerpc64__ + /* + * Page table directory, + * array of pointers to page directories. + */ + pte_t ****pm_root; +#else + /* + * Page table directory, + * array of pointers to page tables. + */ + pte_t **pm_pdir; + + /* List of allocated ptbl bufs (ptbl kva regions). */ + TAILQ_HEAD(, ptbl_buf) pm_ptbl_list; +#endif + }; + } __aligned(CACHE_LINE_SIZE); +}; + +/* + * pv_entries are allocated in chunks per-process. This avoids the + * need to track per-pmap assignments. + */ +#define _NPCPV 126 +#define _NPCM howmany(_NPCPV, 64) + +#define PV_CHUNK_HEADER \ + pmap_t pc_pmap; \ + TAILQ_ENTRY(pv_chunk) pc_list; \ + uint64_t pc_map[_NPCM]; /* bitmap; 1 = free */ \ + TAILQ_ENTRY(pv_chunk) pc_lru; + +struct pv_entry { + pmap_t pv_pmap; + vm_offset_t pv_va; + TAILQ_ENTRY(pv_entry) pv_link; +}; +typedef struct pv_entry *pv_entry_t; + +struct pv_chunk_header { + PV_CHUNK_HEADER +}; +struct pv_chunk { + PV_CHUNK_HEADER + uint64_t reserved; + struct pv_entry pc_pventry[_NPCPV]; +}; + +struct md_page { + union { + struct { + volatile int32_t mdpg_attrs; + vm_memattr_t mdpg_cache_attrs; + struct pvo_head mdpg_pvoh; + int pv_gen; /* (p) */ + }; + struct { + int pv_tracked; + }; + }; + TAILQ_HEAD(, pv_entry) pv_list; /* (p) */ +}; + +#ifdef AIM +#define pmap_page_get_memattr(m) ((m)->md.mdpg_cache_attrs) +#else +#define pmap_page_get_memattr(m) VM_MEMATTR_DEFAULT +#endif /* AIM */ + +/* + * Return the VSID corresponding to a given virtual address. + * If no VSID is currently defined, it will allocate one, and add + * it to a free slot if available. + * + * NB: The PMAP MUST be locked already. + */ +uint64_t va_to_vsid(pmap_t pm, vm_offset_t va); + +/* Lock-free, non-allocating lookup routines */ +uint64_t kernel_va_to_slbv(vm_offset_t va); +struct slb *user_va_to_slb_entry(pmap_t pm, vm_offset_t va); + +uint64_t allocate_user_vsid(pmap_t pm, uint64_t esid, int large); +void free_vsid(pmap_t pm, uint64_t esid, int large); +void slb_insert_user(pmap_t pm, struct slb *slb); +void slb_insert_kernel(uint64_t slbe, uint64_t slbv); + +struct slbtnode *slb_alloc_tree(void); +void slb_free_tree(pmap_t pm); +struct slb **slb_alloc_user_cache(void); +void slb_free_user_cache(struct slb **); + +extern struct pmap kernel_pmap_store; +#define kernel_pmap (&kernel_pmap_store) + +#ifdef _KERNEL + +#define PMAP_LOCK(pmap) mtx_lock(&(pmap)->pm_mtx) +#define PMAP_LOCK_ASSERT(pmap, type) \ + mtx_assert(&(pmap)->pm_mtx, (type)) +#define PMAP_LOCK_DESTROY(pmap) mtx_destroy(&(pmap)->pm_mtx) +#define PMAP_LOCK_INIT(pmap) mtx_init(&(pmap)->pm_mtx, \ + (pmap == kernel_pmap) ? "kernelpmap" : \ + "pmap", NULL, MTX_DEF | MTX_DUPOK) +#define PMAP_LOCKED(pmap) mtx_owned(&(pmap)->pm_mtx) +#define PMAP_MTX(pmap) (&(pmap)->pm_mtx) +#define PMAP_TRYLOCK(pmap) mtx_trylock(&(pmap)->pm_mtx) +#define PMAP_UNLOCK(pmap) mtx_unlock(&(pmap)->pm_mtx) + +#define pmap_page_is_write_mapped(m) (((m)->a.flags & PGA_WRITEABLE) != 0) + +#define pmap_vm_page_alloc_check(m) + +void pmap_bootstrap(vm_offset_t, vm_offset_t); +void pmap_kenter(vm_offset_t va, vm_paddr_t pa); +void pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, vm_memattr_t); +void pmap_kremove(vm_offset_t); +void *pmap_mapdev(vm_paddr_t, vm_size_t); +void *pmap_mapdev_attr(vm_paddr_t, vm_size_t, vm_memattr_t); +void pmap_unmapdev(void *, vm_size_t); +void pmap_page_set_memattr(vm_page_t, vm_memattr_t); +int pmap_change_attr(vm_offset_t, vm_size_t, vm_memattr_t); +int pmap_map_user_ptr(pmap_t pm, volatile const void *uaddr, + void **kaddr, size_t ulen, size_t *klen); +int pmap_decode_kernel_ptr(vm_offset_t addr, int *is_user, + vm_offset_t *decoded_addr); +void pmap_deactivate(struct thread *); +vm_paddr_t pmap_kextract(vm_offset_t); +int pmap_dev_direct_mapped(vm_paddr_t, vm_size_t); +bool pmap_mmu_install(char *name, int prio); +void pmap_mmu_init(void); +const char *pmap_mmu_name(void); +bool pmap_ps_enabled(pmap_t pmap); +int pmap_nofault(pmap_t pmap, vm_offset_t va, vm_prot_t flags); +bool pmap_page_is_mapped(vm_page_t m); +#define pmap_map_delete(pmap, sva, eva) pmap_remove(pmap, sva, eva) + +void pmap_page_array_startup(long count); + +#define vtophys(va) pmap_kextract((vm_offset_t)(va)) + +extern vm_offset_t virtual_avail; +extern vm_offset_t virtual_end; +extern caddr_t crashdumpmap; + +extern vm_offset_t msgbuf_phys; + +extern int pmap_bootstrapped; +extern int radix_mmu; +extern int superpages_enabled; + +#ifdef AIM +void pmap_early_io_map_init(void); +#endif +vm_offset_t pmap_early_io_map(vm_paddr_t pa, vm_size_t size); +void pmap_early_io_unmap(vm_offset_t va, vm_size_t size); +void pmap_track_page(pmap_t pmap, vm_offset_t va); +void pmap_page_print_mappings(vm_page_t m); +void pmap_tlbie_all(void); + +static inline int +pmap_vmspace_copy(pmap_t dst_pmap __unused, pmap_t src_pmap __unused) +{ + + return (0); +} + +#endif + +#endif /* !_MACHINE_PMAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/pmc_mdep.h b/lib/libc/include/powerpc64-freebsd-none/machine/pmc_mdep.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/pmc_mdep.h rename to lib/libc/include/powerpc64-freebsd-none/machine/pmc_mdep.h diff --git a/lib/libc/include/generic-freebsd/machine/proc.h b/lib/libc/include/powerpc64-freebsd-none/machine/proc.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/proc.h rename to lib/libc/include/powerpc64-freebsd-none/machine/proc.h diff --git a/lib/libc/include/generic-freebsd/machine/profile.h b/lib/libc/include/powerpc64-freebsd-none/machine/profile.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/profile.h rename to lib/libc/include/powerpc64-freebsd-none/machine/profile.h diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/psl.h b/lib/libc/include/powerpc64-freebsd-none/machine/psl.h new file mode 100644 index 000000000000..b8aed73f27df --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/psl.h @@ -0,0 +1,101 @@ +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + * + * $NetBSD: psl.h,v 1.5 2000/11/19 19:52:37 matt Exp $ + */ + +#ifndef _MACHINE_PSL_H_ +#define _MACHINE_PSL_H_ + +/* + * Machine State Register (MSR) - All cores + */ +#define PSL_VEC 0x02000000UL /* AltiVec/SPE vector unit available */ +#define PSL_VSX 0x00800000UL /* Vector-Scalar unit available */ +#define PSL_EE 0x00008000UL /* external interrupt enable */ +#define PSL_PR 0x00004000UL /* privilege mode (1 == user) */ +#define PSL_FP 0x00002000UL /* floating point enable */ +#define PSL_ME 0x00001000UL /* machine check enable */ +#define PSL_FE0 0x00000800UL /* floating point interrupt mode 0 */ +#define PSL_FE1 0x00000100UL /* floating point interrupt mode 1 */ +#define PSL_PMM 0x00000004UL /* performance monitor mark */ +#define PSL_RI 0x00000002UL /* recoverable interrupt */ + +/* Machine State Register - Book-E cores */ +#ifdef __powerpc64__ +#define PSL_CM 0x80000000UL /* Computation Mode (64-bit) */ +#endif + +#define PSL_GS 0x10000000UL /* Guest state */ +#define PSL_UCLE 0x04000000UL /* User mode cache lock enable */ +#define PSL_WE 0x00040000UL /* Wait state enable */ +#define PSL_CE 0x00020000UL /* Critical interrupt enable */ +#define PSL_UBLE 0x00000400UL /* BTB lock enable - e500 only */ +#define PSL_DWE 0x00000400UL /* Debug Wait Enable - 440 only*/ +#define PSL_DE 0x00000200UL /* Debug interrupt enable */ +#define PSL_IS 0x00000020UL /* Instruction address space */ +#define PSL_DS 0x00000010UL /* Data address space */ + +/* Machine State Register (MSR) - AIM cores */ +#ifdef __powerpc64__ +#define PSL_SF 0x8000000000000000UL /* 64-bit addressing */ +#define PSL_HV 0x1000000000000000UL /* hyper-privileged mode */ +#endif + +#define PSL_POW 0x00040000UL /* power management */ +#define PSL_ILE 0x00010000UL /* interrupt endian mode (1 == le) */ +#define PSL_SE 0x00000400UL /* single-step trace enable */ +#define PSL_BE 0x00000200UL /* branch trace enable */ +#define PSL_IP 0x00000040UL /* interrupt prefix - 601 only */ +#define PSL_IR 0x00000020UL /* instruction address relocation */ +#define PSL_DR 0x00000010UL /* data address relocation */ +#define PSL_LE 0x00000001UL /* endian mode (1 == le) */ + +/* + * Floating-point exception modes: + */ +#define PSL_FE_DIS 0 /* none */ +#define PSL_FE_NONREC PSL_FE1 /* imprecise non-recoverable */ +#define PSL_FE_REC PSL_FE0 /* imprecise recoverable */ +#define PSL_FE_PREC (PSL_FE0 | PSL_FE1) /* precise */ +#define PSL_FE_DFLT PSL_FE_PREC /* default == precise */ + +#ifndef LOCORE +extern register_t psl_kernset; /* Default MSR values for kernel */ +extern register_t psl_userset; /* Default MSR values for userland */ +#ifdef __powerpc64__ +extern register_t psl_userset32; /* Default user MSR values for 32-bit */ +#endif +extern register_t psl_userstatic; /* Bits of SRR1 userland may not set */ +#endif + +#endif /* _MACHINE_PSL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/pte.h b/lib/libc/include/powerpc64-freebsd-none/machine/pte.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/pte.h rename to lib/libc/include/powerpc64-freebsd-none/machine/pte.h diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/ptrace.h b/lib/libc/include/powerpc64-freebsd-none/machine/ptrace.h new file mode 100644 index 000000000000..64bd0b7b7ab1 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/ptrace.h @@ -0,0 +1,42 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2014 Justin Hibbits + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_PTRACE_H_ +#define _MACHINE_PTRACE_H_ + +#define __HAVE_PTRACE_MACHDEP + +#define PT_GETVRREGS (PT_FIRSTMACH + 0) +#define PT_SETVRREGS (PT_FIRSTMACH + 1) +#define PT_GETVSRREGS (PT_FIRSTMACH + 2) +#define PT_SETVSRREGS (PT_FIRSTMACH + 3) + +#endif \ No newline at end of file diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/reg.h b/lib/libc/include/powerpc64-freebsd-none/machine/reg.h new file mode 100644 index 000000000000..b3be9b413b0a --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/reg.h @@ -0,0 +1,87 @@ +/* $NetBSD: reg.h,v 1.4 2000/06/04 09:30:44 tsubai Exp $ */ + +#ifndef _POWERPC_REG_H_ +#define _POWERPC_REG_H_ + +#include + +/* Must match struct trapframe */ +struct reg { + __register_t fixreg[32]; + __register_t lr; + __register_t cr; + __register_t xer; + __register_t ctr; + __register_t pc; +}; + +struct fpreg { + double fpreg[32]; + double fpscr; +}; + +/* Must match pcb.pcb_vec */ +struct vmxreg { + __uint32_t vr[32][4]; + __uint32_t pad[2]; + __uint32_t vrsave; + __uint32_t vscr; +}; + +struct dbreg { + unsigned int junk; +}; + +#ifdef __LP64__ +/* Must match struct trapframe */ +struct reg32 { + __int32_t fixreg[32]; + __int32_t lr; + __int32_t cr; + __int32_t xer; + __int32_t ctr; + __int32_t pc; +}; + +struct fpreg32 { + struct fpreg data; +}; + +struct vmxreg32 { + struct vmxreg data; +}; + +struct dbreg32 { + struct dbreg data; +}; + +#define __HAVE_REG32 +#endif + +#ifdef _KERNEL +/* + * XXX these interfaces are MI, so they should be declared in a MI place. + */ +int fill_regs(struct thread *, struct reg *); +int set_regs(struct thread *, struct reg *); +int fill_fpregs(struct thread *, struct fpreg *); +int set_fpregs(struct thread *, struct fpreg *); +int fill_dbregs(struct thread *, struct dbreg *); +int set_dbregs(struct thread *, struct dbreg *); + +#ifdef COMPAT_FREEBSD32 +struct image_params; + +int fill_regs32(struct thread *, struct reg32 *); +int set_regs32(struct thread *, struct reg32 *); +void ppc32_setregs(struct thread *, struct image_params *, uintptr_t); + +#define fill_fpregs32(td, reg) fill_fpregs(td,(struct fpreg *)reg) +#define set_fpregs32(td, reg) set_fpregs(td,(struct fpreg *)reg) +#define fill_dbregs32(td, reg) fill_dbregs(td,(struct dbreg *)reg) +#define set_dbregs32(td, reg) set_dbregs(td,(struct dbreg *)reg) +#endif + +#endif + +#endif /* _POWERPC_REG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/reloc.h b/lib/libc/include/powerpc64-freebsd-none/machine/reloc.h new file mode 100644 index 000000000000..592510637e39 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/reloc.h @@ -0,0 +1,30 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1998 John Birrell . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/resource.h b/lib/libc/include/powerpc64-freebsd-none/machine/resource.h new file mode 100644 index 000000000000..db8a89b516cc --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/resource.h @@ -0,0 +1,51 @@ +/*- + * Copyright 1998 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that both the above copyright notice and this + * permission notice appear in all copies, that both the above + * copyright notice and this permission notice appear in all + * supporting documentation, and that the name of M.I.T. not be used + * in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. M.I.T. makes + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS + * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT + * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_RESOURCE_H_ +#define _MACHINE_RESOURCE_H_ 1 + +/* + * Definitions of resource types for Intel Architecture machines + * with support for legacy ISA devices and drivers. + */ + +#define SYS_RES_IRQ 1 /* interrupt lines */ +#define SYS_RES_DRQ 2 /* isa dma lines */ +#define SYS_RES_MEMORY 3 /* i/o memory */ +#define SYS_RES_IOPORT 4 /* i/o ports */ +#define PCI_RES_BUS 5 /* PCI bus numbers */ + +/* + * A powerpc-specific resource flag to request little-endian bus tags + * for a resource. + */ + +#define RF_LITTLEENDIAN RF_SPARE1 + +#endif /* !_MACHINE_RESOURCE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/rtas.h b/lib/libc/include/powerpc64-freebsd-none/machine/rtas.h similarity index 99% rename from lib/libc/include/generic-freebsd/machine/rtas.h rename to lib/libc/include/powerpc64-freebsd-none/machine/rtas.h index 0c27e31fb6b9..2ee4dc9f406f 100644 --- a/lib/libc/include/generic-freebsd/machine/rtas.h +++ b/lib/libc/include/powerpc64-freebsd-none/machine/rtas.h @@ -29,7 +29,6 @@ #ifndef _MACHINE_RTAS_H_ #define _MACHINE_RTAS_H_ -#include #include #include diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/sdt_machdep.h b/lib/libc/include/powerpc64-freebsd-none/machine/sdt_machdep.h new file mode 100644 index 000000000000..f1f09c2ceba4 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/sdt_machdep.h @@ -0,0 +1,12 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 Mark Johnston + */ + +#ifndef _SYS_SDT_MACHDEP_H_ +#define _SYS_SDT_MACHDEP_H_ + +#define _SDT_ASM_PATCH_INSTR "nop" + +#endif \ No newline at end of file diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/setjmp.h b/lib/libc/include/powerpc64-freebsd-none/machine/setjmp.h new file mode 100644 index 000000000000..fcc287508602 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/setjmp.h @@ -0,0 +1,27 @@ +/*- + * $NetBSD: setjmp.h,v 1.3 1998/09/16 23:51:27 thorpej Exp $ + */ + +#ifndef _MACHINE_SETJMP_H_ +#define _MACHINE_SETJMP_H_ + +#include + +#ifdef _KERNEL +#define _JBLEN 25 /* Kernel doesn't save FP and Altivec regs */ +#else +#define _JBLEN 100 +#endif + +/* + * jmp_buf and sigjmp_buf are encapsulated in different structs to force + * compile-time diagnostics for mismatches. The structs are the same + * internally to avoid some run-time errors for mismatches. + */ +#if __BSD_VISIBLE || __POSIX_VISIBLE || __XSI_VISIBLE +typedef struct _sigjmp_buf { long _sjb[_JBLEN + 1]; } sigjmp_buf[1]; +#endif + +typedef struct _jmp_buf { long _jb[_JBLEN + 1]; } jmp_buf[1]; + +#endif /* !_MACHINE_SETJMP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/signal.h b/lib/libc/include/powerpc64-freebsd-none/machine/signal.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/signal.h rename to lib/libc/include/powerpc64-freebsd-none/machine/signal.h diff --git a/lib/libc/include/generic-freebsd/machine/slb.h b/lib/libc/include/powerpc64-freebsd-none/machine/slb.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/slb.h rename to lib/libc/include/powerpc64-freebsd-none/machine/slb.h diff --git a/lib/libc/include/generic-freebsd/machine/smp.h b/lib/libc/include/powerpc64-freebsd-none/machine/smp.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/smp.h rename to lib/libc/include/powerpc64-freebsd-none/machine/smp.h diff --git a/lib/libc/include/generic-freebsd/machine/spr.h b/lib/libc/include/powerpc64-freebsd-none/machine/spr.h similarity index 99% rename from lib/libc/include/generic-freebsd/machine/spr.h rename to lib/libc/include/powerpc64-freebsd-none/machine/spr.h index 8e3c4fc936fe..587fa4ed24ba 100644 --- a/lib/libc/include/generic-freebsd/machine/spr.h +++ b/lib/libc/include/powerpc64-freebsd-none/machine/spr.h @@ -162,6 +162,11 @@ #define FSCR_DSCR 0x0000000000000004 /* DSCR available in PR state */ #define SPR_UAMOR 0x09d /* User Authority Mask Override Register */ #define SPR_DPDES 0x0b0 /* .6. Directed Privileged Doorbell Exception State Register */ +#define SPR_HFSCR 0xbe /* Hypervisor Facility Status and Control Register */ +#define HFSCR_BHRB 0x0000000000000010 /* BHRB instructions */ +#define HFSCR_PM 0x0000000000000008 /* Performance monitor SPRs */ +#define HFSCR_VECVSX 0x0000000000000002 /* Vector and VSX facilities */ +#define HFSCR_FP 0x0000000000000001 /* Floating Point facility */ #define SPR_USPRG0 0x100 /* 4.8 User SPR General 0 */ #define SPR_VRSAVE 0x100 /* .6. AltiVec VRSAVE */ #define SPR_SPRG0 0x110 /* 468 SPR General 0 */ diff --git a/lib/libc/include/generic-freebsd/machine/sr.h b/lib/libc/include/powerpc64-freebsd-none/machine/sr.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/sr.h rename to lib/libc/include/powerpc64-freebsd-none/machine/sr.h diff --git a/lib/libc/include/generic-freebsd/machine/stack.h b/lib/libc/include/powerpc64-freebsd-none/machine/stack.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/stack.h rename to lib/libc/include/powerpc64-freebsd-none/machine/stack.h diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/sysarch.h b/lib/libc/include/powerpc64-freebsd-none/machine/sysarch.h new file mode 100644 index 000000000000..e1911def3572 --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/sysarch.h @@ -0,0 +1,43 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1993 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_SYSARCH_H_ +#define _MACHINE_SYSARCH_H_ + +#ifndef _KERNEL +#include + +__BEGIN_DECLS +int sysarch(int, void *); +__END_DECLS +#endif + +#endif /* !_MACHINE_SYSARCH_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/tlb.h b/lib/libc/include/powerpc64-freebsd-none/machine/tlb.h similarity index 100% rename from lib/libc/include/generic-freebsd/machine/tlb.h rename to lib/libc/include/powerpc64-freebsd-none/machine/tlb.h diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/tls.h b/lib/libc/include/powerpc64-freebsd-none/machine/tls.h new file mode 100644 index 000000000000..6dea3eb3a99f --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/tls.h @@ -0,0 +1,66 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2004 by Peter Grehan. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_TLS_H_ +#define _MACHINE_TLS_H_ + +#include + +#define TLS_DTV_OFFSET 0x8000 +#define TLS_TCB_ALIGN TLS_TCB_SIZE +#define TLS_TP_OFFSET 0x7000 + +static __inline void +_tcb_set(struct tcb *tcb) +{ +#ifdef __powerpc64__ + __asm __volatile("mr 13,%0" :: + "r" ((uint8_t *)tcb + TLS_TP_OFFSET + TLS_TCB_SIZE)); +#else + __asm __volatile("mr 2,%0" :: + "r" ((uint8_t *)tcb + TLS_TP_OFFSET + TLS_TCB_SIZE)); +#endif +} + +static __inline struct tcb * +_tcb_get(void) +{ + struct tcb *tcb; + +#ifdef __powerpc64__ + __asm __volatile("addi %0,13,%1" : "=r" (tcb) : + "i" (-(TLS_TP_OFFSET + TLS_TCB_SIZE))); +#else + __asm __volatile("addi %0,2,%1" : "=r" (tcb) : + "i" (-(TLS_TP_OFFSET + TLS_TCB_SIZE))); +#endif + return (tcb); +} + +#endif /* !_MACHINE_TLS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/trap.h b/lib/libc/include/powerpc64-freebsd-none/machine/trap.h new file mode 100644 index 000000000000..7326ba17c5cd --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/trap.h @@ -0,0 +1,160 @@ +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + * + * $NetBSD: trap.h,v 1.7 2002/02/22 13:51:40 kleink Exp $ + */ + +#ifndef _POWERPC_TRAP_H_ +#define _POWERPC_TRAP_H_ + +#define EXC_RSVD 0x0000 /* Reserved */ +#define EXC_RST 0x0100 /* Reset; all but IBM4xx */ +#define EXC_MCHK 0x0200 /* Machine Check */ +#define EXC_DSI 0x0300 /* Data Storage Interrupt */ +#define EXC_DSE 0x0380 /* Data Segment Interrupt */ +#define EXC_ISI 0x0400 /* Instruction Storage Interrupt */ +#define EXC_ISE 0x0480 /* Instruction Segment Interrupt */ +#define EXC_EXI 0x0500 /* External Interrupt */ +#define EXC_ALI 0x0600 /* Alignment Interrupt */ +#define EXC_PGM 0x0700 /* Program Interrupt */ +#define EXC_FPU 0x0800 /* Floating-point Unavailable */ +#define EXC_DECR 0x0900 /* Decrementer Interrupt */ +#define EXC_SC 0x0c00 /* System Call */ +#define EXC_TRC 0x0d00 /* Trace */ +#define EXC_FPA 0x0e00 /* Floating-point Assist */ + +/* The following is only available on the 601: */ +#define EXC_RUNMODETRC 0x2000 /* Run Mode/Trace Exception */ + +/* The following are only available on 970(G5): */ +#define EXC_VECAST_G5 0x1700 /* AltiVec Assist */ + +/* The following are only available on 7400(G4): */ +#define EXC_VEC 0x0f20 /* AltiVec Unavailable */ +#define EXC_VECAST_G4 0x1600 /* AltiVec Assist */ + +/* The following are only available on 604/750/7400: */ +#define EXC_PERF 0x0f00 /* Performance Monitoring */ +#define EXC_BPT 0x1300 /* Instruction Breakpoint */ +#define EXC_SMI 0x1400 /* System Managment Interrupt */ + +/* The following are only available on 750/7400: */ +#define EXC_THRM 0x1700 /* Thermal Management Interrupt */ + +/* And these are only on the 603: */ +#define EXC_IMISS 0x1000 /* Instruction translation miss */ +#define EXC_DLMISS 0x1100 /* Data load translation miss */ +#define EXC_DSMISS 0x1200 /* Data store translation miss */ + +/* Power ISA 2.06+: */ +#define EXC_HDSI 0x0e00 /* Hypervisor Data Storage */ +#define EXC_HISI 0x0e20 /* Hypervisor Instruction Storage */ +#define EXC_HEA 0x0e40 /* Hypervisor Emulation Assistance */ +#define EXC_HMI 0x0e60 /* Hypervisor Maintenance */ +#define EXC_VSX 0x0f40 /* VSX Unavailable */ + +/* Power ISA 2.07+: */ +#define EXC_FAC 0x0f60 /* Facility Unavailable */ +#define EXC_HFAC 0x0f80 /* Hypervisor Facility Unavailable */ + +/* Power ISA 3.0+: */ +#define EXC_HVI 0x0ea0 /* Hypervisor Virtualization */ + +/* The following are available on 4xx and 85xx */ +#define EXC_CRIT 0x0100 /* Critical Input Interrupt */ +#define EXC_PIT 0x1000 /* Programmable Interval Timer */ +#define EXC_FIT 0x1010 /* Fixed Interval Timer */ +#define EXC_WDOG 0x1020 /* Watchdog Timer */ +#define EXC_DTMISS 0x1100 /* Data TLB Miss */ +#define EXC_ITMISS 0x1200 /* Instruction TLB Miss */ +#define EXC_APU 0x1300 /* Auxiliary Processing Unit */ +#define EXC_DEBUG 0x2f10 /* Debug trap */ +#define EXC_VECAST_E 0x2f20 /* Altivec Assist (Book-E) */ +#define EXC_SPFPD 0x2f30 /* SPE Floating-point Data */ +#define EXC_SPFPR 0x2f40 /* SPE Floating-point Round */ + +/* POWER8 */ +#define EXC_SOFT_PATCH 0x1500 /* POWER8 Soft Patch Exception */ + +#define EXC_LAST 0x2f00 /* Last possible exception vector */ + +#define EXC_AST 0x3000 /* Fake AST vector */ + +/* Trap was in user mode */ +#define EXC_USER 0x10000 + +/* + * EXC_ALI sets bits in the DSISR and DAR to provide enough + * information to recover from the unaligned access without needing to + * parse the offending instruction. This includes certain bits of the + * opcode, and information about what registers are used. The opcode + * indicator values below come from Appendix F of Book III of "The + * PowerPC Architecture". + */ + +#define EXC_ALI_OPCODE_INDICATOR(dsisr) ((dsisr >> 10) & 0x7f) +#define EXC_ALI_LFD 0x09 +#define EXC_ALI_STFD 0x0b + +/* Macros to extract register information */ +#define EXC_ALI_RST(dsisr) ((dsisr >> 5) & 0x1f) /* source or target */ +#define EXC_ALI_RA(dsisr) (dsisr & 0x1f) +#define EXC_ALI_INST_RST(instr) ((instr >> 21) & 0x1f) + +/* + * SRR1 bits for program exception traps. These identify what caused + * the program exception. See section 6.5.9 of the Power ISA Version + * 2.05. + */ + +#define EXC_PGM_FPENABLED (1UL << 20) +#define EXC_PGM_ILLEGAL (1UL << 19) +#define EXC_PGM_PRIV (1UL << 18) +#define EXC_PGM_TRAP (1UL << 17) + +/* DTrace trap opcode. */ +#define EXC_DTRACE 0x7ffff808 + +/* Magic pointer to store TOC base and other info for trap handlers on ppc64 */ +#define TRAP_ENTRY 0x1e8 +#define TRAP_GENTRAP 0x1f0 +#define TRAP_TOCBASE 0x1f8 + +#ifndef LOCORE +struct trapframe; +struct thread; +extern int (*hmi_handler)(struct trapframe *); +void trap(struct trapframe *); +int ppc_instr_emulate(struct trapframe *, struct thread *); +#endif + +#endif /* _POWERPC_TRAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/generic-freebsd/machine/ucontext.h b/lib/libc/include/powerpc64-freebsd-none/machine/ucontext.h similarity index 98% rename from lib/libc/include/generic-freebsd/machine/ucontext.h rename to lib/libc/include/powerpc64-freebsd-none/machine/ucontext.h index 01a14ce3a6b8..c7a858f7d1f2 100644 --- a/lib/libc/include/generic-freebsd/machine/ucontext.h +++ b/lib/libc/include/powerpc64-freebsd-none/machine/ucontext.h @@ -41,6 +41,7 @@ typedef struct __mcontext { int mc_flags; #define _MC_FP_VALID 0x01 #define _MC_AV_VALID 0x02 +#define _MC_VS_VALID 0x04 int mc_onstack; /* saved onstack flag */ int mc_len; /* sizeof(__mcontext) */ __uint64_t mc_avec[32*2]; /* vector register file */ @@ -56,6 +57,7 @@ typedef struct __mcontext32 { int mc_flags; #define _MC_FP_VALID 0x01 #define _MC_AV_VALID 0x02 +#define _MC_VS_VALID 0x04 int mc_onstack; /* saved onstack flag */ int mc_len; /* sizeof(__mcontext) */ uint64_t mc_avec[32*2]; /* vector register file */ diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/vdso.h b/lib/libc/include/powerpc64-freebsd-none/machine/vdso.h new file mode 100644 index 000000000000..2a3e6f6dfd8f --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/vdso.h @@ -0,0 +1,43 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright 2012 Konstantin Belousov . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _POWERPC_VDSO_H +#define _POWERPC_VDSO_H + +#define VDSO_TIMEHANDS_MD \ + uint32_t th_res[8]; + +#define VDSO_TH_ALGO_PPC_TB VDSO_TH_ALGO_1 + +#ifdef _KERNEL +#ifdef COMPAT_FREEBSD32 + +#define VDSO_TIMEHANDS_MD32 VDSO_TIMEHANDS_MD + +#endif +#endif +#endif \ No newline at end of file diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/vm.h b/lib/libc/include/powerpc64-freebsd-none/machine/vm.h new file mode 100644 index 000000000000..fa397b398c8d --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/vm.h @@ -0,0 +1,45 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2009 Alan L. Cox + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_VM_H_ +#define _MACHINE_VM_H_ + +#include + +/* Memory attributes. */ +#define VM_MEMATTR_DEFAULT 0 +#define VM_MEMATTR_UNCACHEABLE 0x01 +#define VM_MEMATTR_CACHEABLE 0x02 +#define VM_MEMATTR_WRITE_COMBINING 0x04 +#define VM_MEMATTR_WRITE_BACK 0x08 +#define VM_MEMATTR_WRITE_THROUGH 0x10 +#define VM_MEMATTR_PREFETCHABLE 0x20 + +#define VM_MEMATTR_DEVICE VM_MEMATTR_DEFAULT + +#endif /* !_MACHINE_VM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-freebsd-none/machine/vmparam.h b/lib/libc/include/powerpc64-freebsd-none/machine/vmparam.h new file mode 100644 index 000000000000..7f49714b108b --- /dev/null +++ b/lib/libc/include/powerpc64-freebsd-none/machine/vmparam.h @@ -0,0 +1,327 @@ +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + * + * $NetBSD: vmparam.h,v 1.11 2000/02/11 19:25:16 thorpej Exp $ + */ + +#ifndef _MACHINE_VMPARAM_H_ +#define _MACHINE_VMPARAM_H_ + +#ifndef LOCORE +#include +#endif + +#define USRSTACK SHAREDPAGE + +#ifndef MAXTSIZ +#define MAXTSIZ (1*1024*1024*1024) /* max text size */ +#endif + +#ifndef DFLDSIZ +#define DFLDSIZ (128*1024*1024) /* default data size */ +#endif + +#ifndef MAXDSIZ +#ifdef __powerpc64__ +#define MAXDSIZ (32UL*1024*1024*1024) /* max data size */ +#else +#define MAXDSIZ (1*1024*1024*1024) /* max data size */ +#endif +#endif + +#ifndef DFLSSIZ +#define DFLSSIZ (8*1024*1024) /* default stack size */ +#endif + +#ifndef MAXSSIZ +#ifdef __powerpc64__ +#define MAXSSIZ (512*1024*1024) /* max stack size */ +#else +#define MAXSSIZ (64*1024*1024) /* max stack size */ +#endif +#endif + +#ifdef AIM +#define VM_MAXUSER_ADDRESS32 0xfffff000 +#else +#define VM_MAXUSER_ADDRESS32 0x7ffff000 +#endif + +/* + * Would like to have MAX addresses = 0, but this doesn't (currently) work + */ +#ifdef __powerpc64__ +/* + * Virtual addresses of things. Derived from the page directory and + * page table indexes from pmap.h for precision. + * + * kernel map should be able to start at 0xc008000000000000 - + * but at least the functional simulator doesn't like it + * + * 0x0000000000000000 - 0x000fffffffffffff user map + * 0xc000000000000000 - 0xc007ffffffffffff direct map + * 0xc008000000000000 - 0xc00fffffffffffff kernel map + * + */ +#define VM_MIN_ADDRESS 0x0000000000000000 +#define VM_MAXUSER_ADDRESS 0x000fffffc0000000 +#define VM_MAX_ADDRESS 0xc00fffffffffffff +#define VM_MIN_KERNEL_ADDRESS 0xc008000000000000 +#define VM_MAX_KERNEL_ADDRESS 0xc0080007ffffffff +#define VM_MAX_SAFE_KERNEL_ADDRESS VM_MAX_KERNEL_ADDRESS +#else +#define VM_MIN_ADDRESS 0 +#define VM_MAXUSER_ADDRESS VM_MAXUSER_ADDRESS32 +#define VM_MAX_ADDRESS 0xffffffff +#endif + +#define SHAREDPAGE (VM_MAXUSER_ADDRESS - PAGE_SIZE) + +#define FREEBSD32_SHAREDPAGE (VM_MAXUSER_ADDRESS32 - PAGE_SIZE) +#define FREEBSD32_USRSTACK FREEBSD32_SHAREDPAGE + +#define KERNBASE 0x00100100 /* start of kernel virtual */ + +#define UMA_MD_SMALL_ALLOC + +#ifdef AIM +#ifndef __powerpc64__ +#define VM_MIN_KERNEL_ADDRESS ((vm_offset_t)KERNEL_SR << ADDR_SR_SHFT) +#define VM_MAX_SAFE_KERNEL_ADDRESS (VM_MIN_KERNEL_ADDRESS + 2*SEGMENT_LENGTH -1) +#define VM_MAX_KERNEL_ADDRESS (VM_MIN_KERNEL_ADDRESS + 3*SEGMENT_LENGTH - 1) +#endif + +/* + * Use the direct-mapped BAT registers for UMA small allocs. This + * takes pressure off the small amount of available KVA. + */ +#define UMA_USE_DMAP + +#else /* Book-E */ + +/* Use the direct map for UMA small allocs on powerpc64. */ +#ifdef __powerpc64__ +#define UMA_USE_DMAP +#else +#define VM_MIN_KERNEL_ADDRESS 0xc0000000 +#define VM_MAX_KERNEL_ADDRESS 0xffffefff +#define VM_MAX_SAFE_KERNEL_ADDRESS VM_MAX_KERNEL_ADDRESS +#endif + +#endif /* AIM/E500 */ + +#if !defined(LOCORE) +struct pmap_physseg { + struct pv_entry *pvent; + char *attrs; +}; +#endif + +#ifdef __powerpc64__ +#define VM_PHYSSEG_MAX 63 /* 1? */ +#else +#define VM_PHYSSEG_MAX 16 /* 1? */ +#endif + +#define PHYS_AVAIL_SZ 256 /* Allows up to 16GB Ram on pSeries with + * logical memory block size of 64MB. + * For more Ram increase the lmb or this value. + */ + +/* XXX This is non-sensical. Phys avail should hold contiguous regions. */ +#define PHYS_AVAIL_ENTRIES PHYS_AVAIL_SZ + +/* + * The physical address space is densely populated on 32-bit systems, + * but may not be on 64-bit ones. + */ +#ifdef __powerpc64__ +#define VM_PHYSSEG_SPARSE +#else +#define VM_PHYSSEG_DENSE +#endif + +/* + * Create two free page pools: VM_FREEPOOL_DEFAULT is the default pool + * from which physical pages are allocated and VM_FREEPOOL_DIRECT is + * the pool from which physical pages for small UMA objects are + * allocated. + */ +#define VM_NFREEPOOL 2 +#define VM_FREEPOOL_DEFAULT 0 +#define VM_FREEPOOL_DIRECT 1 + +/* + * Create one free page list. + */ +#define VM_NFREELIST 1 +#define VM_FREELIST_DEFAULT 0 + +#ifdef __powerpc64__ +/* The largest allocation size is 16MB. */ +#define VM_NFREEORDER 13 +#else +/* The largest allocation size is 4MB. */ +#define VM_NFREEORDER 11 +#endif + +#ifndef VM_NRESERVLEVEL +#ifdef __powerpc64__ +/* Enable superpage reservations: 1 level. */ +#define VM_NRESERVLEVEL 1 +#else +/* Disable superpage reservations. */ +#define VM_NRESERVLEVEL 0 +#endif +#endif + +#ifndef VM_LEVEL_0_ORDER +/* Level 0 reservations consist of 512 (RPT) or 4096 (HPT) pages. */ +#define VM_LEVEL_0_ORDER vm_level_0_order +#ifndef __ASSEMBLER__ +extern int vm_level_0_order; +#endif +#endif + +#ifndef VM_LEVEL_0_ORDER_MAX +#define VM_LEVEL_0_ORDER_MAX 12 +#endif + +#ifndef VM_INITIAL_PAGEIN +#define VM_INITIAL_PAGEIN 16 +#endif + +#ifndef SGROWSIZ +#define SGROWSIZ (128UL*1024) /* amount to grow stack */ +#endif + +/* + * How many physical pages per kmem arena virtual page. + */ +#ifndef VM_KMEM_SIZE_SCALE +#define VM_KMEM_SIZE_SCALE (3) +#endif + +/* + * Optional floor (in bytes) on the size of the kmem arena. + */ +#ifndef VM_KMEM_SIZE_MIN +#define VM_KMEM_SIZE_MIN (12 * 1024 * 1024) +#endif + +/* + * Optional ceiling (in bytes) on the size of the kmem arena: 40% of the + * usable KVA space. + */ +#ifndef VM_KMEM_SIZE_MAX +#define VM_KMEM_SIZE_MAX ((VM_MAX_SAFE_KERNEL_ADDRESS - \ + VM_MIN_KERNEL_ADDRESS + 1) * 2 / 5) +#endif + +#ifdef __powerpc64__ +#define ZERO_REGION_SIZE (2 * 1024 * 1024) /* 2MB */ +#else +#define ZERO_REGION_SIZE (64 * 1024) /* 64KB */ +#endif + +/* + * On 32-bit OEA, the only purpose for which sf_buf is used is to implement + * an opaque pointer required by the machine-independent parts of the kernel. + * That pointer references the vm_page that is "mapped" by the sf_buf. The + * actual mapping is provided by the direct virtual-to-physical mapping. + * + * On OEA64 and Book-E, we need to do something a little more complicated. Use + * the runtime-detected hw_direct_map to pick between the two cases. Our + * friends in vm_machdep.c will do the same to ensure nothing gets confused. + */ +#define SFBUF +#define SFBUF_NOMD + +/* + * We (usually) have a direct map of all physical memory, so provide + * a macro to use to get the kernel VA address for a given PA. Check the + * value of PMAP_HAS_PMAP before using. + */ +#ifndef LOCORE +#ifdef __powerpc64__ +#define DMAP_BASE_ADDRESS 0xc000000000000000UL +#define DMAP_MIN_ADDRESS DMAP_BASE_ADDRESS +#define DMAP_MAX_ADDRESS 0xc007ffffffffffffUL +#else +#define DMAP_BASE_ADDRESS 0x00000000UL +#define DMAP_MAX_ADDRESS 0xbfffffffUL +#endif +#endif + +#if defined(__powerpc64__) || defined(BOOKE) +/* + * powerpc64 and Book-E will provide their own page array allocators. + * + * On AIM, this will allocate a single virtual array, with pages from the + * correct memory domains. + * On Book-E this will let us put the array in TLB1, removing the need for TLB + * thrashing. + * + * VM_MIN_KERNEL_ADDRESS is just a dummy. It will get set by the MMU driver. + */ +#define PA_MIN_ADDRESS VM_MIN_KERNEL_ADDRESS +#define PMAP_HAS_PAGE_ARRAY 1 +#endif + +#if defined(__powerpc64__) +/* + * Need a page dump array for minidump. + */ +#define MINIDUMP_PAGE_TRACKING 1 +#define MINIDUMP_STARTUP_PAGE_TRACKING 1 +#else +/* + * No minidump with 32-bit powerpc. + */ +#define MINIDUMP_PAGE_TRACKING 0 +#define MINIDUMP_STARTUP_PAGE_TRACKING 0 +#endif + +#define PMAP_HAS_DMAP (hw_direct_map) +#define PHYS_TO_DMAP(x) ({ \ + KASSERT(hw_direct_map, ("Direct map not provided by PMAP")); \ + (x) | DMAP_BASE_ADDRESS; }) +#define DMAP_TO_PHYS(x) ({ \ + KASSERT(hw_direct_map, ("Direct map not provided by PMAP")); \ + (x) &~ DMAP_BASE_ADDRESS; }) + +/* + * No non-transparent large page support in the pmap. + */ +#define PMAP_HAS_LARGEPAGES 0 + +#endif /* _MACHINE_VMPARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/frame.h b/lib/libc/include/powerpc64-openbsd-none/frame.h new file mode 100644 index 000000000000..afb0dfa2956a --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/frame.h @@ -0,0 +1,104 @@ +/* $OpenBSD: frame.h,v 1.5 2020/07/13 22:37:37 kettenis Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 _MACHDEP_FRAME_H +#define _MACHDEP_FRAME_H + +/* + * We have to save all registers on every trap, because + * 1. user could attach this process every time + * 2. we must be able to restore all user registers in case of fork + * Actually, we do not save the fp registers on trap, since + * these are not used by the kernel. They are saved only when switching + * between processes using the FPU. + * + */ +struct trapframe { + __register_t fixreg[32]; + __register_t lr; + __register_t cr; + __register_t xer; + __register_t ctr; + __register_t srr0; + __register_t srr1; + __register_t vrsave; + __register_t dar; /* dar & dsisr are only filled on a DSI trap */ + __register_t dsisr; + __register_t exc; +}; + +/* + * This is to ensure alignment of the stackpointer + */ +#define FRAMELEN roundup(sizeof(struct trapframe) + 32, 16) + +struct callframe { + register_t cf_sp; + register_t cf_cr; + register_t cf_lr; + register_t cf_toc; +}; + +struct sigframe { + int sf_signum; + siginfo_t *sf_sip; + struct sigcontext sf_sc; + siginfo_t sf_si; +}; + +struct switchframe { + register_t sf_sp; + register_t sf_cr; + register_t sf_lr; /* unused */ + register_t sf_toc; /* unused */ + register_t sf_r14; + register_t sf_r15; + register_t sf_r16; + register_t sf_r17; + register_t sf_r18; + register_t sf_r19; + register_t sf_r20; + register_t sf_r21; + register_t sf_r22; + register_t sf_r23; + register_t sf_r24; + register_t sf_r25; + register_t sf_r26; + register_t sf_r27; + register_t sf_r28; + register_t sf_r29; + register_t sf_r30; + register_t sf_r31; +}; + +#endif /* _MACHDEP_FRAME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/_float.h b/lib/libc/include/powerpc64-openbsd-none/machine/_float.h new file mode 100644 index 000000000000..14a56d926e32 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/_float.h @@ -0,0 +1,71 @@ +/* $OpenBSD: _float.h,v 1.1 2020/06/01 00:13:37 drahn Exp $ */ + +/* + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE__FLOAT_H_ +#define _MACHINE__FLOAT_H_ + +#define __FLT_RADIX 2 /* b */ +#define __FLT_ROUNDS __flt_rounds() +#define __FLT_EVAL_METHOD 0 /* no promotions */ + +#define __FLT_MANT_DIG 24 /* p */ +#define __FLT_EPSILON 1.19209290E-07F /* b**(1-p) */ +#define __FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ +#define __FLT_MIN_EXP (-125) /* emin */ +#define __FLT_MIN 1.17549435E-38F /* b**(emin-1) */ +#define __FLT_MIN_10_EXP (-37) /* ceil(log10(b**(emin-1))) */ +#define __FLT_MAX_EXP 128 /* emax */ +#define __FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ +#define __FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ + +#define __DBL_MANT_DIG 53 +#define __DBL_EPSILON 2.2204460492503131E-16 +#define __DBL_DIG 15 +#define __DBL_MIN_EXP (-1021) +#define __DBL_MIN 2.2250738585072014E-308 +#define __DBL_MIN_10_EXP (-307) +#define __DBL_MAX_EXP 1024 +#define __DBL_MAX 1.7976931348623157E+308 +#define __DBL_MAX_10_EXP 308 + +#define __LDBL_MANT_DIG DBL_MANT_DIG +#define __LDBL_EPSILON DBL_EPSILON +#define __LDBL_DIG DBL_DIG +#define __LDBL_MIN_EXP DBL_MIN_EXP +#define __LDBL_MIN DBL_MIN +#define __LDBL_MIN_10_EXP DBL_MIN_10_EXP +#define __LDBL_MAX_EXP DBL_MAX_EXP +#define __LDBL_MAX DBL_MAX +#define __LDBL_MAX_10_EXP DBL_MAX_10_EXP + +#define __DECIMAL_DIG 17 + +#endif /* _MACHINE__FLOAT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/_types.h b/lib/libc/include/powerpc64-openbsd-none/machine/_types.h new file mode 100644 index 000000000000..c8b810163d81 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/_types.h @@ -0,0 +1,145 @@ +/* $OpenBSD: _types.h,v 1.4 2023/07/02 19:02:28 cheloha Exp $ */ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.3 (Berkeley) 1/5/94 + * @(#)ansi.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _MACHINE__TYPES_H_ +#define _MACHINE__TYPES_H_ + +#if defined(_KERNEL) +typedef struct label_t { + long val[22]; +} label_t; +#endif + +/* + * _ALIGN(p) rounds p (pointer or byte index) up to a correctly-aligned + * value for all data types (int, long, ...). The result is an + * unsigned long and must be cast to any desired pointer type. + * + * _ALIGNED_POINTER is a boolean macro that checks whether an address + * is valid to fetch data elements of type t from on this architecture. + * This does not reflect the optimal alignment, just the possibility + * (within reasonable limits). + */ +#define _ALIGNBYTES (sizeof(long) - 1) +#define _STACKALIGNBYTES 15 +#define _ALIGN(p) (((unsigned long)(p) + _ALIGNBYTES) & ~_ALIGNBYTES) +#define _ALIGNED_POINTER(p,t) ((((unsigned long)(p)) & (sizeof(t) - 1)) == 0) +#define _MAX_PAGE_SHIFT 12 /* same as PAGE_SHIFT */ + +/* 7.18.1.1 Exact-width integer types */ +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short __int16_t; +typedef unsigned short __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; +/* LONGLONG */ +typedef long long __int64_t; +/* LONGLONG */ +typedef unsigned long long __uint64_t; + +/* 7.18.1.2 Minimum-width integer types */ +typedef __int8_t __int_least8_t; +typedef __uint8_t __uint_least8_t; +typedef __int16_t __int_least16_t; +typedef __uint16_t __uint_least16_t; +typedef __int32_t __int_least32_t; +typedef __uint32_t __uint_least32_t; +typedef __int64_t __int_least64_t; +typedef __uint64_t __uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types */ +typedef __int32_t __int_fast8_t; +typedef __uint32_t __uint_fast8_t; +typedef __int32_t __int_fast16_t; +typedef __uint32_t __uint_fast16_t; +typedef __int32_t __int_fast32_t; +typedef __uint32_t __uint_fast32_t; +typedef __int64_t __int_fast64_t; +typedef __uint64_t __uint_fast64_t; +#define __INT_FAST8_MIN INT32_MIN +#define __INT_FAST16_MIN INT32_MIN +#define __INT_FAST32_MIN INT32_MIN +#define __INT_FAST64_MIN INT64_MIN +#define __INT_FAST8_MAX INT32_MAX +#define __INT_FAST16_MAX INT32_MAX +#define __INT_FAST32_MAX INT32_MAX +#define __INT_FAST64_MAX INT64_MAX +#define __UINT_FAST8_MAX UINT32_MAX +#define __UINT_FAST16_MAX UINT32_MAX +#define __UINT_FAST32_MAX UINT32_MAX +#define __UINT_FAST64_MAX UINT64_MAX + +/* 7.18.1.4 Integer types capable of holding object pointers */ +typedef long __intptr_t; +typedef unsigned long __uintptr_t; + +/* 7.18.1.5 Greatest-width integer types */ +typedef __int64_t __intmax_t; +typedef __uint64_t __uintmax_t; + +/* Register size */ +typedef long __register_t; + +/* VM system types */ +typedef unsigned long __vaddr_t; +typedef unsigned long __paddr_t; +typedef unsigned long __vsize_t; +typedef unsigned long __psize_t; + +/* Standard system types */ +typedef double __double_t; +typedef float __float_t; +typedef long __ptrdiff_t; +typedef unsigned long __size_t; +typedef long __ssize_t; +#if defined(__GNUC__) && __GNUC__ >= 3 +typedef __builtin_va_list __va_list; +#else +typedef char * __va_list; +#endif + +/* Wide character support types */ +#ifndef __cplusplus +#ifdef __WCHAR_UNSIGNED__ +typedef unsigned int __wchar_t; +#else +typedef int __wchar_t; +#endif +#endif +typedef int __wint_t; +typedef int __rune_t; +typedef void * __wctrans_t; +typedef void * __wctype_t; + +#endif /* _MACHINE__TYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/apmvar.h b/lib/libc/include/powerpc64-openbsd-none/machine/apmvar.h new file mode 100644 index 000000000000..2c911df088a2 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/apmvar.h @@ -0,0 +1,122 @@ +/* $OpenBSD: apmvar.h,v 1.1 2020/07/15 22:46:51 deraadt Exp $ */ + +/* + * Copyright (c) 2001 Alexander Guy + * Copyright (c) 1995 John T. Kohl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _POWERPC64_APMVAR_H_ +#define _POWERPC64_APMVAR_H_ + +#include + +/* Advanced Power Management (v1.0 and v1.1 specification) + * functions/defines/etc. + */ + +/* These definitions make up the heart of the user-land interface + * to the APM devices. + */ + +#define APM_AC_OFF 0x00 +#define APM_AC_ON 0x01 +#define APM_AC_BACKUP 0x02 +#define APM_AC_UNKNOWN 0xff +#define APM_BATT_HIGH 0x00 +#define APM_BATT_LOW 0x01 +#define APM_BATT_CRITICAL 0x02 +#define APM_BATT_CHARGING 0x03 +#define APM_BATT_UNKNOWN 0xff +#define APM_BATT_LIFE_UNKNOWN 0xff + +#define APM_NOEVENT 0x0000 +#define APM_STANDBY_REQ 0x0001 +#define APM_SUSPEND_REQ 0x0002 +#define APM_NORMAL_RESUME 0x0003 +#define APM_CRIT_RESUME 0x0004 /* suspend/resume happened + without us */ +#define APM_BATTERY_LOW 0x0005 +#define APM_POWER_CHANGE 0x0006 +#define APM_UPDATE_TIME 0x0007 +#define APM_CRIT_SUSPEND_REQ 0x0008 +#define APM_USER_STANDBY_REQ 0x0009 +#define APM_USER_SUSPEND_REQ 0x000A +#define APM_SYS_STANDBY_RESUME 0x000B +#define APM_CAPABILITY_CHANGE 0x000C /* apm v1.2 */ +#define APM_USER_HIBERNATE_REQ 0x000D +#define APM_EVENT_MASK 0xffff + +#define APM_EVENT_COMPOSE(t,i) ((((i) & 0x7fff) << 16)|((t) & APM_EVENT_MASK)) +#define APM_EVENT_TYPE(e) ((e) & APM_EVENT_MASK) +#define APM_EVENT_INDEX(e) ((e) >> 16) + +/* + * LP (Laptop Package) + * + * Copyright (C) 1994 by HOSOKAWA Tatsumi + * + * This software may be used, modified, copied, and distributed, in + * both source and binary form provided that the above copyright and + * these terms are retained. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with its + * use. + * + * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) + */ + +#define APM_BATTERY_ABSENT 4 + +struct apm_power_info { + u_char battery_state; + u_char ac_state; + u_char battery_life; + u_char spare1; + u_int minutes_left; /* estimate */ + u_int spare2[6]; +}; + +struct apm_ctl { + u_int dev; + u_int mode; +}; + +#define APM_IOC_REJECT _IOW('A', 0, struct apm_event_info) /* reject request # */ +#define APM_IOC_STANDBY _IO('A', 1) /* put system into standby */ +#define APM_IOC_SUSPEND _IO('A', 2) /* put system into suspend */ +#define APM_IOC_GETPOWER _IOR('A', 3, struct apm_power_info) /* fetch battery state */ +#define APM_IOC_DEV_CTL _IOW('A', 5, struct apm_ctl) /* put device into mode */ +#define APM_IOC_PRN_CTL _IOW('A', 6, int ) /* driver power status msg */ +#define APM_PRINT_ON 0 /* driver power status displayed */ +#define APM_PRINT_OFF 1 /* driver power status not displayed */ +#define APM_PRINT_PCT 2 /* driver power status only displayed + if the percentage changes */ +#define APM_IOC_STANDBY_REQ _IO('A', 7) /* request standby */ +#define APM_IOC_SUSPEND_REQ _IO('A', 8) /* request suspend */ +#define APM_IOC_HIBERNATE _IO('A', 9) /* put system into hibernate */ + +#endif /* _POWERPC64_APMVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/asm.h b/lib/libc/include/powerpc64-openbsd-none/machine/asm.h new file mode 100644 index 000000000000..b630e137aa8c --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/asm.h @@ -0,0 +1,100 @@ +/* $OpenBSD: asm.h,v 1.7 2022/12/07 23:25:59 guenther Exp $ */ + +/* + * Copyright (c) 2020 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _POWERPC64_ASM_H_ +#define _POWERPC64_ASM_H_ + +#define _C_LABEL(x) x +#define _ASM_LABEL(x) x + +#define _TMP_LABEL(x) .L_ ## x +#define _GEP_LABEL(x) .L_ ## x ## _gep0 +#define _LEP_LABEL(x) .L_ ## x ## _lep0 + +#define _ENTRY(x) \ + .text; .align 2; .globl x; .type x,@function; x: \ + _GEP_LABEL(x): \ + addis %r2, %r12, .TOC.-_GEP_LABEL(x)@ha; \ + addi %r2, %r2, .TOC.-_GEP_LABEL(x)@l; \ + _LEP_LABEL(x): \ + .localentry x, _LEP_LABEL(x)-_GEP_LABEL(x); + +#if defined(PROF) || defined(GPROF) +# define _PROF_PROLOGUE(y) \ + .section ".data"; \ + .align 2; \ +_TMP_LABEL(y):; \ + .long 0; \ + .section ".text"; \ + mflr %r0; \ + addis %r11, %r2, _TMP_LABEL(y)@toc@ha; \ + std %r0, 8(%r1); \ + addi %r0, %r11, _TMP_LABEL(y)@toc@l; \ + bl _mcount; +#else +# define _PROF_PROLOGUE(y) +#endif + +#define ENTRY(y) _ENTRY(y); _PROF_PROLOGUE(y) +#define ASENTRY(y) _ENTRY(y); _PROF_PROLOGUE(y) +#define END(y) .size y, . - y + +#define STRONG_ALIAS(alias,sym) \ + .global alias; .set alias,sym +#define WEAK_ALIAS(alias,sym) \ + .weak alias; .set alias,sym + +#if defined(_RET_PROTECTOR) +# define RETGUARD_SETUP(x, reg) \ + RETGUARD_SYMBOL(x); \ + mflr %r0; \ + addis reg, %r2, (__retguard_ ## x)@toc@ha; \ + ld reg, ((__retguard_ ## x)@toc@l)(reg); \ + xor reg, reg, %r0 +# define RETGUARD_CHECK(x, reg) \ + mflr %r0; \ + xor reg, reg, %r0; \ + addis %r12, %r2, (__retguard_ ## x)@toc@ha; \ + ld %r12, ((__retguard_ ## x)@toc@l)(%r12); \ + tdne reg, %r12 +# define RETGUARD_SAVE(reg, loc) \ + std reg, loc +# define RETGUARD_LOAD(reg, loc) \ + ld reg, loc +# define RETGUARD_SYMBOL(x) \ + .ifndef __retguard_ ## x; \ + .hidden __retguard_ ## x; \ + .type __retguard_ ## x,@object; \ + .pushsection .openbsd.randomdata.retguard,"aw",@progbits; \ + .weak __retguard_ ## x; \ + .p2align 3; \ + __retguard_ ## x: ; \ + .quad 0; \ + .size __retguard_ ## x, 8; \ + .popsection; \ + .endif +#else +# define RETGUARD_SETUP(x, reg) +# define RETGUARD_CHECK(x, reg) +# define RETGUARD_SAVE(reg, loc) +# define RETGUARD_LOAD(reg, loc) +# define RETGUARD_SYMBOL(x) +#endif + + +#endif /* !_POWERPC64_ASM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/atomic.h b/lib/libc/include/powerpc64-openbsd-none/machine/atomic.h new file mode 100644 index 000000000000..277291b92677 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/atomic.h @@ -0,0 +1,292 @@ +/* $OpenBSD: atomic.h,v 1.3 2022/08/29 02:01:18 jsg Exp $ */ + +/* + * Copyright (c) 2015 Martin Pieuchot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +#ifndef _MACHINE_ATOMIC_H_ +#define _MACHINE_ATOMIC_H_ + +#if defined(_KERNEL) + +static __inline void +atomic_setbits_int(volatile unsigned int *uip, unsigned int v) +{ + unsigned int tmp; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " or %0, %1, %0 \n" + " stwcx. %0, 0, %2 \n" + " bne- 1b \n" + " sync" : "=&r" (tmp) : "r" (v), "r" (uip) : "cc", "memory"); +} + +static __inline void +atomic_clearbits_int(volatile unsigned int *uip, unsigned int v) +{ + unsigned int tmp; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " andc %0, %0, %1 \n" + " stwcx. %0, 0, %2 \n" + " bne- 1b \n" + " sync" : "=&r" (tmp) : "r" (v), "r" (uip) : "cc", "memory"); +} + +#endif /* defined(_KERNEL) */ + +static inline unsigned int +_atomic_cas_uint(volatile unsigned int *p, unsigned int o, unsigned int n) +{ + unsigned int rv; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " cmpw 0, %0, %4 \n" + " bne- 2f \n" + " stwcx. %3, 0, %2 \n" + " bne- 1b \n" + "2: \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (n), "r" (o) + : "cc"); + + return (rv); +} +#define atomic_cas_uint(_p, _o, _n) _atomic_cas_uint((_p), (_o), (_n)) + +static inline unsigned long +_atomic_cas_ulong(volatile unsigned long *p, unsigned long o, unsigned long n) +{ + unsigned long rv; + + __asm volatile ( + "1: ldarx %0, 0, %2 \n" + " cmpd 0, %0, %4 \n" + " bne- 2f \n" + " stdcx. %3, 0, %2 \n" + " bne- 1b \n" + "2: \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (n), "r" (o) + : "cc"); + + return (rv); +} +#define atomic_cas_ulong(_p, _o, _n) _atomic_cas_ulong((_p), (_o), (_n)) + +static inline void * +_atomic_cas_ptr(volatile void *pp, void *o, void *n) +{ + void * volatile *p = pp; + void *rv; + + __asm volatile ( + "1: ldarx %0, 0, %2 \n" + " cmpd 0, %0, %4 \n" + " bne- 2f \n" + " stdcx. %3, 0, %2 \n" + " bne- 1b \n" + "2: \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (n), "r" (o) + : "cc"); + + return (rv); +} +#define atomic_cas_ptr(_p, _o, _n) _atomic_cas_ptr((_p), (_o), (_n)) + +static inline unsigned int +_atomic_swap_uint(volatile unsigned int *p, unsigned int v) +{ + unsigned int rv; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " stwcx. %3, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (v) + : "cc"); + + return (rv); +} +#define atomic_swap_uint(_p, _v) _atomic_swap_uint((_p), (_v)) + +static inline unsigned long +_atomic_swap_ulong(volatile unsigned long *p, unsigned long v) +{ + unsigned long rv; + + __asm volatile ( + "1: ldarx %0, 0, %2 \n" + " stdcx. %3, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (v) + : "cc"); + + return (rv); +} +#define atomic_swap_ulong(_p, _v) _atomic_swap_ulong((_p), (_v)) + +static inline void * +_atomic_swap_ptr(volatile void *pp, void *v) +{ + void * volatile *p = pp; + void *rv; + + __asm volatile ( + "1: ldarx %0, 0, %2 \n" + " stdcx. %3, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (v) + : "cc"); + + return (rv); +} +#define atomic_swap_ptr(_p, _v) _atomic_swap_ptr((_p), (_v)) + +static inline unsigned int +_atomic_add_int_nv(volatile unsigned int *p, unsigned int v) +{ + unsigned int rv; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " add %0, %3, %0 \n" + " stwcx. %0, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (v) + : "cc", "xer"); + + return (rv); +} +#define atomic_add_int_nv(_p, _v) _atomic_add_int_nv((_p), (_v)) + +static inline unsigned long +_atomic_add_long_nv(volatile unsigned long *p, unsigned long v) +{ + unsigned long rv; + + __asm volatile ( + "1: ldarx %0, 0, %2 \n" + " add %0, %3, %0 \n" + " stdcx. %0, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (v) + : "cc", "xer"); + + return (rv); +} +#define atomic_add_long_nv(_p, _v) _atomic_add_long_nv((_p), (_v)) + +static inline unsigned int +_atomic_sub_int_nv(volatile unsigned int *p, unsigned int v) +{ + unsigned int rv; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " subf %0, %3, %0 \n" + " stwcx. %0, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (v) + : "cc", "xer"); + + return (rv); +} +#define atomic_sub_int_nv(_p, _v) _atomic_sub_int_nv((_p), (_v)) + +static inline unsigned long +_atomic_sub_long_nv(volatile unsigned long *p, unsigned long v) +{ + unsigned long rv; + + __asm volatile ( + "1: ldarx %0, 0, %2 \n" + " subf %0, %3, %0 \n" + " stdcx. %0, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (v) + : "cc", "xer"); + + return (rv); +} +#define atomic_sub_long_nv(_p, _v) _atomic_sub_long_nv((_p), (_v)) + +static inline unsigned int +_atomic_addic_int_nv(volatile unsigned int *p, unsigned int v) +{ + unsigned int rv; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " addic %0, %0, %3 \n" + " stwcx. %0, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "i" (v) + : "cc", "xer"); + + return (rv); +} +#define atomic_inc_int_nv(_p) _atomic_addic_int_nv((_p), 1) +#define atomic_dec_int_nv(_p) _atomic_addic_int_nv((_p), -1) + +static inline unsigned long +_atomic_addic_long_nv(volatile unsigned long *p, unsigned long v) +{ + unsigned long rv; + + __asm volatile ( + "1: ldarx %0, 0, %2 \n" + " addic %0, %0, %3 \n" + " stdcx. %0, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "i" (v) + : "cc", "xer"); + + return (rv); +} +#define atomic_inc_long_nv(_p) _atomic_addic_long_nv((_p), 1) +#define atomic_dec_long_nv(_p) _atomic_addic_long_nv((_p), -1) + +#define __membar(_f) do { __asm volatile(_f ::: "memory"); } while (0) + +#if defined(MULTIPROCESSOR) || !defined(_KERNEL) +#define membar_enter() __membar("isync") +#define membar_exit() __membar("sync") +#define membar_producer() __membar("sync") +#define membar_consumer() __membar("isync") +#define membar_sync() __membar("sync") +#else +#define membar_enter() __membar("") +#define membar_exit() __membar("") +#define membar_producer() __membar("") +#define membar_consumer() __membar("") +#define membar_sync() __membar("") +#endif + +#endif /* _MACHINE_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/bus.h b/lib/libc/include/powerpc64-openbsd-none/machine/bus.h new file mode 100644 index 000000000000..626dcdbbcac3 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/bus.h @@ -0,0 +1,532 @@ +/* $OpenBSD: bus.h,v 1.5 2020/11/15 23:13:00 kettenis Exp $ */ +/* + * Copyright (c) 2003-2004 Opsycon AB Sweden. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BUS_H_ +#define _MACHINE_BUS_H_ + +#define CAT(a,b) a##b +#define CAT3(a,b,c) a##b##c + +/* + * Bus access types. + */ +struct bus_space; +typedef u_long bus_addr_t; +typedef u_long bus_size_t; +typedef u_long bus_space_handle_t; +typedef struct bus_space *bus_space_tag_t; +typedef struct bus_space bus_space_t; + +struct bus_space { + bus_addr_t bus_base; + void *bus_private; + uint8_t (*_space_read_1)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_1)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, uint8_t); + uint16_t (*_space_read_2)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_2)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, uint16_t); + uint32_t (*_space_read_4)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_4)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, uint32_t); + uint64_t (*_space_read_8)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_8)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, uint64_t); + void (*_space_read_raw_2)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); + void (*_space_write_raw_2)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); + void (*_space_read_raw_4)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); + void (*_space_write_raw_4)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); + void (*_space_read_raw_8)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); + void (*_space_write_raw_8)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); + int (*_space_map)(bus_space_tag_t , bus_addr_t, + bus_size_t, int, bus_space_handle_t *); + void (*_space_unmap)(bus_space_tag_t, bus_space_handle_t, + bus_size_t); + int (*_space_subregion)(bus_space_tag_t, bus_space_handle_t, + bus_size_t, bus_size_t, bus_space_handle_t *); + void * (*_space_vaddr)(bus_space_tag_t, bus_space_handle_t); + paddr_t (*_space_mmap)(bus_space_tag_t, bus_addr_t, off_t, + int, int); +}; + +#define bus_space_read_1(t, h, o) (*(t)->_space_read_1)((t), (h), (o)) +#define bus_space_read_2(t, h, o) (*(t)->_space_read_2)((t), (h), (o)) +#define bus_space_read_4(t, h, o) (*(t)->_space_read_4)((t), (h), (o)) +#define bus_space_read_8(t, h, o) (*(t)->_space_read_8)((t), (h), (o)) + +#define bus_space_write_1(t, h, o, v) (*(t)->_space_write_1)((t), (h), (o), (v)) +#define bus_space_write_2(t, h, o, v) (*(t)->_space_write_2)((t), (h), (o), (v)) +#define bus_space_write_4(t, h, o, v) (*(t)->_space_write_4)((t), (h), (o), (v)) +#define bus_space_write_8(t, h, o, v) (*(t)->_space_write_8)((t), (h), (o), (v)) + +#define bus_space_read_raw_2(t, h, o) \ + generic_space_read_2((t), (h), (o)) +#define bus_space_read_raw_4(t, h, o) \ + generic_space_read_4((t), (h), (o)) +#define bus_space_read_raw_8(t, h, o) \ + generic_space_read_8((t), (h), (o)) + +#define bus_space_write_raw_2(t, h, o, v) \ + generic_space_write_2((t), (h), (o), (v)) +#define bus_space_write_raw_4(t, h, o, v) \ + generic_space_write_4((t), (h), (o), (v)) +#define bus_space_write_raw_8(t, h, o, v) \ + generic_space_write_8((t), (h), (o), (v)) + +#define bus_space_read_raw_multi_2(t, h, a, b, l) \ + (*(t)->_space_read_raw_2)((t), (h), (a), (b), (l)) +#define bus_space_read_raw_multi_4(t, h, a, b, l) \ + (*(t)->_space_read_raw_4)((t), (h), (a), (b), (l)) +#define bus_space_read_raw_multi_8(t, h, a, b, l) \ + (*(t)->_space_read_raw_8)((t), (h), (a), (b), (l)) + +#define bus_space_write_raw_multi_2(t, h, a, b, l) \ + (*(t)->_space_write_raw_2)((t), (h), (a), (b), (l)) +#define bus_space_write_raw_multi_4(t, h, a, b, l) \ + (*(t)->_space_write_raw_4)((t), (h), (a), (b), (l)) +#define bus_space_write_raw_multi_8(t, h, a, b, l) \ + (*(t)->_space_write_raw_8)((t), (h), (a), (b), (l)) + +#define bus_space_map(t, o, s, c, p) (*(t)->_space_map)((t), (o), (s), (c), (p)) +#define bus_space_unmap(t, h, s) (*(t)->_space_unmap)((t), (h), (s)) +#define bus_space_subregion(t, h, o, s, p) \ + (*(t)->_space_subregion)((t), (h), (o), (s), (p)) + +#define BUS_SPACE_MAP_CACHEABLE 0x01 +#define BUS_SPACE_MAP_KSEG0 0x02 +#define BUS_SPACE_MAP_LINEAR 0x04 +#define BUS_SPACE_MAP_PREFETCHABLE 0x08 + +#define bus_space_vaddr(t, h) (*(t)->_space_vaddr)((t), (h)) +#define bus_space_mmap(t, a, o, p, f) \ + (*(t)->_space_mmap)((t), (a), (o), (p), (f)) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_multi(n,m) \ +static __inline void \ +CAT(bus_space_read_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t o, CAT3(uint,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) \ + *x++ = CAT(bus_space_read_,n)(bst, bsh, o); \ +} + +bus_space_read_multi(1,8) +bus_space_read_multi(2,16) +bus_space_read_multi(4,32) +bus_space_read_multi(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_region(n,m) \ +static __inline void \ +CAT(bus_space_read_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(uint,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) { \ + *x++ = CAT(bus_space_read_,n)(bst, bsh, ba); \ + ba += (n); \ + } \ +} + +bus_space_read_region(1,8) +bus_space_read_region(2,16) +bus_space_read_region(4,32) +bus_space_read_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_raw_region(n,m) \ +static __inline void \ +CAT(bus_space_read_raw_region_,n)(bus_space_tag_t bst, \ + bus_space_handle_t bsh, \ + bus_addr_t ba, uint8_t *x, size_t cnt) \ +{ \ + cnt >>= ((n) >> 1); \ + while (cnt--) { \ + CAT(bus_space_read_raw_multi_,n)(bst, bsh, ba, x, (n)); \ + ba += (n); \ + x += (n); \ + } \ +} + +bus_space_read_raw_region(2,16) +bus_space_read_raw_region(4,32) +bus_space_read_raw_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_multi(n,m) \ +static __inline void \ +CAT(bus_space_write_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t o, const CAT3(uint,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) \ + CAT(bus_space_write_,n)(bst, bsh, o, *x++); \ +} + +bus_space_write_multi(1,8) +bus_space_write_multi(2,16) +bus_space_write_multi(4,32) +bus_space_write_multi(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_region(n,m) \ +static __inline void \ +CAT(bus_space_write_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, const CAT3(uint,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) { \ + CAT(bus_space_write_,n)(bst, bsh, ba, *x++); \ + ba += (n); \ + } \ +} + +bus_space_write_region(1,8) +bus_space_write_region(2,16) +bus_space_write_region(4,32) +bus_space_write_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_raw_region(n,m) \ +static __inline void \ +CAT(bus_space_write_raw_region_,n)(bus_space_tag_t bst, \ + bus_space_handle_t bsh, \ + bus_addr_t ba, const uint8_t *x, size_t cnt) \ +{ \ + cnt >>= ((n) >> 1); \ + while (cnt--) { \ + CAT(bus_space_write_raw_multi_,n)(bst, bsh, ba, x, (n)); \ + ba += (n); \ + x += (n); \ + } \ +} + +bus_space_write_raw_region(2,16) +bus_space_write_raw_region(4,32) +bus_space_write_raw_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_set_region(n,m) \ +static __inline void \ +CAT(bus_space_set_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(uint,m,_t) x, size_t cnt) \ +{ \ + while (cnt--) { \ + CAT(bus_space_write_,n)(bst, bsh, ba, x); \ + ba += (n); \ + } \ +} + +bus_space_set_region(1,8) +bus_space_set_region(2,16) +bus_space_set_region(4,32) +bus_space_set_region(8,64) + +/*----------------------------------------------------------------------------*/ +static __inline void +bus_space_copy_1(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + char *s = (char *)(h1 + o1); + char *d = (char *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + + +static __inline void +bus_space_copy_2(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + short *s = (short *)(h1 + o1); + short *d = (short *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + +static __inline void +bus_space_copy_4(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + int *s = (int *)(h1 + o1); + int *d = (int *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + +static __inline void +bus_space_copy_8(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + int64_t *s = (int64_t *)(h1 + o1); + int64_t *d = (int64_t *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + +/*----------------------------------------------------------------------------*/ +/* + * Bus read/write barrier methods. + * + * void bus_space_barrier(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * bus_size_t len, int flags); + * + */ +static inline void +bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, + bus_size_t length, int flags) +{ + __asm__ volatile ("eieio" ::: "memory"); +} +#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ +#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ + +#define BUS_DMA_WAITOK 0x0000 +#define BUS_DMA_NOWAIT 0x0001 +#define BUS_DMA_ALLOCNOW 0x0002 +#define BUS_DMA_COHERENT 0x0008 +#define BUS_DMA_BUS1 0x0010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x0020 +#define BUS_DMA_BUS3 0x0040 +#define BUS_DMA_BUS4 0x0080 +#define BUS_DMA_READ 0x0100 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x0200 /* mapping is memory -> device only */ +#define BUS_DMA_STREAMING 0x0400 /* hint: sequential, unidirectional */ +#define BUS_DMA_ZERO 0x0800 /* zero memory in dmamem_alloc */ +#define BUS_DMA_NOCACHE 0x1000 +#define BUS_DMA_64BIT 0x2000 /* device handles 64bit dva */ + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct proc; +struct uio; + +#define BUS_DMASYNC_POSTREAD 0x0001 +#define BUS_DMASYNC_POSTWRITE 0x0002 +#define BUS_DMASYNC_PREREAD 0x0004 +#define BUS_DMASYNC_PREWRITE 0x0008 + +typedef struct machine_bus_dma_tag *bus_dma_tag_t; +typedef struct machine_bus_dmamap *bus_dmamap_t; + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +struct machine_bus_dma_segment { + bus_addr_t ds_addr; /* DMA address */ + bus_size_t ds_len; /* length of transfer */ + + paddr_t _ds_paddr; /* CPU address */ + vaddr_t _ds_vaddr; /* CPU address */ +}; +typedef struct machine_bus_dma_segment bus_dma_segment_t; + +/* + * bus_dma_tag_t + * + * A machine-dependent opaque type describing the implementation of + * DMA for a given bus. + */ + +struct machine_bus_dma_tag { + void *_cookie; /* cookie used in the guts */ + int _flags; /* misc. flags */ + + /* + * DMA mapping methods. + */ + int (*_dmamap_create)(bus_dma_tag_t , bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); + void (*_dmamap_destroy)(bus_dma_tag_t , bus_dmamap_t); + int (*_dmamap_load)(bus_dma_tag_t , bus_dmamap_t, void *, + bus_size_t, struct proc *, int); + int (*_dmamap_load_mbuf)(bus_dma_tag_t , bus_dmamap_t, + struct mbuf *, int); + int (*_dmamap_load_uio)(bus_dma_tag_t , bus_dmamap_t, + struct uio *, int); + int (*_dmamap_load_raw)(bus_dma_tag_t , bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); + int (*_dmamap_load_buffer)(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int, paddr_t *, int *, int); + void (*_dmamap_unload)(bus_dma_tag_t , bus_dmamap_t); + void (*_dmamap_sync)(bus_dma_tag_t , bus_dmamap_t, + bus_addr_t, bus_size_t, int); + + /* + * DMA memory utility functions. + */ + int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); + void (*_dmamem_free)(bus_dma_tag_t, bus_dma_segment_t *, int); + int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); + void (*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t); + paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, + int, off_t, int, int); + + /* + * internal memory address translation information. + */ + bus_addr_t _dma_mask; +}; + +#define bus_dmamap_create(t, s, n, m, b, f, p) \ + (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) +#define bus_dmamap_destroy(t, p) \ + (*(t)->_dmamap_destroy)((t), (p)) +#define bus_dmamap_load(t, m, b, s, p, f) \ + (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) +#define bus_dmamap_load_mbuf(t, m, b, f) \ + (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) +#define bus_dmamap_load_uio(t, m, u, f) \ + (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) +#define bus_dmamap_load_raw(t, m, sg, n, s, f) \ + (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) +#define bus_dmamap_unload(t, p) \ + (*(t)->_dmamap_unload)((t), (p)) +#define bus_dmamap_sync(t, p, a, l, o) \ + (void)((t)->_dmamap_sync ? \ + (*(t)->_dmamap_sync)((t), (p), (a), (l), (o)) : (void)0) + +#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ + (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f)) +#define bus_dmamem_free(t, sg, n) \ + (*(t)->_dmamem_free)((t), (sg), (n)) +#define bus_dmamem_map(t, sg, n, s, k, f) \ + (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f)) +#define bus_dmamem_unmap(t, k, s) \ + (*(t)->_dmamem_unmap)((t), (k), (s)) +#define bus_dmamem_mmap(t, sg, n, o, p, f) \ + (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f)) + +int _dmamap_create(bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); +void _dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); +int _dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); +int _dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *, int); +int _dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, struct uio *, int); +int _dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); +int _dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int, paddr_t *, int *, int); +void _dmamap_unload(bus_dma_tag_t, bus_dmamap_t); +void _dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, + bus_size_t, int); + +int _dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); +void _dmamem_free(bus_dma_tag_t, bus_dma_segment_t *, int); +int _dmamem_map(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); +void _dmamem_unmap(bus_dma_tag_t, caddr_t, size_t); +paddr_t _dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, int, int); +int _dmamem_alloc_range(bus_dma_tag_t, bus_size_t, bus_size_t, bus_size_t, + bus_dma_segment_t *, int, int *, int, paddr_t, paddr_t); + +/* + * bus_dmamap_t + * + * Describes a DMA mapping. + */ +struct machine_bus_dmamap { + /* + * PRIVATE MEMBERS: not for use by machine-independent code. + */ + bus_size_t _dm_size; /* largest DMA transfer mappable */ + int _dm_segcnt; /* number of segs this map can map */ + bus_size_t _dm_maxsegsz; /* largest possible segment */ + bus_size_t _dm_boundary; /* don't cross this */ + int _dm_flags; /* misc. flags */ + + void *_dm_cookie; /* cookie for bus-specific functions */ + + /* + * PUBLIC MEMBERS: these are used by machine-independent code. + */ + bus_size_t dm_mapsize; /* size of the mapping */ + int dm_nsegs; /* # valid segments in mapping */ + bus_dma_segment_t dm_segs[1]; /* segments; variable length */ +}; + +int generic_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, + bus_space_handle_t *); +void generic_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t); +int generic_space_region(bus_space_tag_t, bus_space_handle_t, bus_size_t, + bus_size_t, bus_space_handle_t *); +void *generic_space_vaddr(bus_space_tag_t, bus_space_handle_t); +paddr_t generic_space_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int); +uint8_t generic_space_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint16_t generic_space_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint32_t generic_space_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint64_t generic_space_read_8(bus_space_tag_t, bus_space_handle_t, bus_size_t); +void generic_space_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint8_t); +void generic_space_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint16_t); +void generic_space_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint32_t); +void generic_space_write_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint64_t); +void generic_space_read_raw_2(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_raw_2(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); +void generic_space_read_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); +void generic_space_read_raw_8(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_raw_8(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); + +uint16_t little_space_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint32_t little_space_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint64_t little_space_read_8(bus_space_tag_t, bus_space_handle_t, bus_size_t); +void little_space_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint16_t); +void little_space_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint32_t); +void little_space_write_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint64_t); + +#endif /* _MACHINE_BUS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/cdefs.h b/lib/libc/include/powerpc64-openbsd-none/machine/cdefs.h new file mode 100644 index 000000000000..dcf667bff9e3 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/cdefs.h @@ -0,0 +1,21 @@ +/* $OpenBSD: cdefs.h,v 1.1 2020/05/16 17:11:14 kettenis Exp $ */ + +/* + * Written by J.T. Conklin 01/17/95. + * Public domain. + */ + +#ifndef _MACHINE_CDEFS_H_ +#define _MACHINE_CDEFS_H_ + +#define __strong_alias(alias,sym) \ + __asm__(".global " __STRING(alias) " ; " __STRING(alias) \ + " = " __STRING(sym)) +#define __weak_alias(alias,sym) \ + __asm__(".weak " __STRING(alias) " ; " __STRING(alias) \ + " = " __STRING(sym)) +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning." __STRING(sym) \ + " ; .ascii \"" msg "\" ; .text") + +#endif /* !_MACHINE_CDEFS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/conf.h b/lib/libc/include/powerpc64-openbsd-none/machine/conf.h new file mode 100644 index 000000000000..bed3c41fe6fd --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/conf.h @@ -0,0 +1,24 @@ +#include + +#define mmread mmrw +#define mmwrite mmrw +cdev_decl(mm); + +cdev_decl(opalcons); + +/* open, close, ioctl */ +#define cdev_kexec_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) nullop, 0, \ + (dev_type_mmap((*))) enodev } + +/* open, close, ioctl */ +#define cdev_openprom_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) nullop, 0, \ + (dev_type_mmap((*))) enodev } + +cdev_decl(kexec); +cdev_decl(openprom); \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/cpu.h b/lib/libc/include/powerpc64-openbsd-none/machine/cpu.h new file mode 100644 index 000000000000..f5e0e18115e2 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/cpu.h @@ -0,0 +1,234 @@ +/* $OpenBSD: cpu.h,v 1.39 2024/11/28 18:54:36 gkoehler Exp $ */ + +/* + * Copyright (c) 2020 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_CPU_H_ +#define _MACHINE_CPU_H_ + +/* + * User-visible definitions + */ + +/* + * CTL_MACHDEP definitions. + */ +#define CPU_ALTIVEC 1 /* altivec is present */ +#define CPU_MAXID 2 /* number of valid machdep ids */ + +#define CTL_MACHDEP_NAMES { \ + { 0, 0 }, \ + { "altivec", CTLTYPE_INT }, \ +} + +#ifdef _KERNEL + +/* + * Kernel-only definitions + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct cpu_info { + struct device *ci_dev; + struct cpu_info *ci_next; + struct schedstate_percpu ci_schedstate; + + uint32_t ci_cpuid; + uint32_t ci_pir; + int ci_node; + + struct proc *ci_curproc; + struct pcb *ci_curpcb; + + struct slb ci_kernel_slb[32]; + paddr_t ci_user_slb_pa; + register_t ci_slbsave[18]; + char ci_slbstack[1024]; + +#define CPUSAVE_LEN 9 + register_t ci_tempsave[CPUSAVE_LEN]; + register_t ci_idle_sp_save; + + struct clockqueue ci_queue; + + volatile int ci_cpl; + volatile int ci_dec_deferred; + uint32_t ci_ipending; + uint32_t ci_idepth; +#ifdef DIAGNOSTIC + int ci_mutex_level; +#endif + int ci_want_resched; + + uint32_t ci_randseed; + +#ifdef MULTIPROCESSOR + struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM]; + void *ci_initstack_end; + void *ci_ipi; + int ci_ipi_reason; + volatile int ci_flags; +#endif + +#ifdef DDB + volatile int ci_ddb_paused; +#define CI_DDB_RUNNING 0 +#define CI_DDB_SHOULDSTOP 1 +#define CI_DDB_STOPPED 2 +#define CI_DDB_ENTERDDB 3 +#define CI_DDB_INDDB 4 +#endif + char ci_panicbuf[512]; +}; + +#define CPUF_PRIMARY (1 << 0) +#define CPUF_AP (1 << 1) +#define CPUF_IDENTIFY (1 << 2) +#define CPUF_IDENTIFIED (1 << 3) +#define CPUF_PRESENT (1 << 4) +#define CPUF_GO (1 << 5) +#define CPUF_RUNNING (1 << 6) + +extern struct cpu_info cpu_info[]; +extern struct cpu_info *cpu_info_primary; + +static __inline struct cpu_info * +curcpu(void) +{ + struct cpu_info *ci; + __asm volatile ("mfsprg0 %0" : "=r"(ci)); + return ci; +} + +#define CPU_INFO_ITERATOR int + +#ifndef MULTIPROCESSOR + +#define MAXCPUS 1 +#define CPU_IS_PRIMARY(ci) 1 +#define CPU_IS_RUNNING(ci) 1 +#define cpu_number() 0 + +#define CPU_INFO_UNIT(ci) 0 +#define CPU_INFO_FOREACH(cii, ci) \ + for (cii = 0, ci = curcpu(); ci != NULL; ci = NULL) + +#define cpu_kick(ci) +#define cpu_unidle(ci) + +#else + +#define MAXCPUS 48 +#define CPU_IS_PRIMARY(ci) ((ci) == cpu_info_primary) +#define CPU_IS_RUNNING(ci) ((ci)->ci_flags & CPUF_RUNNING) +#define cpu_number() (curcpu()->ci_cpuid) + +#define CPU_INFO_UNIT(ci) ((ci)->ci_dev ? (ci)->ci_dev->dv_unit : 0) +#define CPU_INFO_FOREACH(cii, ci) \ + for (cii = 0, ci = &cpu_info[0]; cii < ncpus; cii++, ci++) + +void cpu_kick(struct cpu_info *); +void cpu_unidle(struct cpu_info *); +void cpu_boot_secondary_processors(void); + +extern void (*ul_setperf)(int); +void mp_setperf(int); + +#endif + +#define clockframe trapframe + +#define CLKF_INTR(frame) (curcpu()->ci_idepth > 1) +#define CLKF_USERMODE(frame) (frame->srr1 & PSL_PR) +#define CLKF_PC(frame) (frame->srr0) + +#define aston(p) ((p)->p_md.md_astpending = 1) +#define need_proftick(p) aston(p) + +void signotify(struct proc *); + +#define CPU_BUSY_CYCLE() __asm volatile ("" ::: "memory") + +#define curpcb curcpu()->ci_curpcb + +void cpu_init_features(void); +void cpu_init(void); + +#define cpu_idle_enter() do { /* nothing */ } while (0) +#define cpu_idle_leave() do { /* nothing */ } while (0) +extern uint64_t cpu_idle_state_psscr; +extern void (*cpu_idle_cycle_fcn)(void); + +static inline unsigned int +cpu_rnd_messybits(void) +{ + uint64_t tb; + + __asm volatile("mftb %0" : "=r" (tb)); + return ((tb >> 32) ^ tb); +} + +void need_resched(struct cpu_info *); +#define clear_resched(ci) ((ci)->ci_want_resched = 0) + +void delay(u_int); +#define DELAY(x) delay(x) + +#define PROC_STACK(p) ((p)->p_md.md_regs->fixreg[1]) +#define PROC_PC(p) ((p)->p_md.md_regs->srr0) + +void proc_trampoline(void); + +static inline void +intr_enable(void) +{ + mtmsr(mfmsr() | PSL_EE); +} + +static inline u_long +intr_disable(void) +{ + u_long msr; + + msr = mfmsr(); + mtmsr(msr & ~PSL_EE); + return msr; +} + +static inline void +intr_restore(u_long msr) +{ + mtmsr(msr); +} + +#endif /* _KERNEL */ + +#ifdef MULTIPROCESSOR +#include +#endif /* MULTIPROCESSOR */ + +#endif /* _MACHINE_CPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/cpufunc.h b/lib/libc/include/powerpc64-openbsd-none/machine/cpufunc.h new file mode 100644 index 000000000000..161e89a9b878 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/cpufunc.h @@ -0,0 +1,222 @@ +/* $OpenBSD: cpufunc.h,v 1.11 2023/01/25 09:53:53 kettenis Exp $ */ + +/* + * Copyright (c) 2020 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_CPUFUNC_H_ +#define _MACHINE_CPUFUNC_H_ + +static inline void +eieio(void) +{ + __asm volatile ("eieio" ::: "memory"); +} + +static inline void +isync(void) +{ + __asm volatile ("isync" ::: "memory"); +} + +static inline void +ptesync(void) +{ + __asm volatile ("ptesync" ::: "memory"); +} + +static inline void +sync(void) +{ + __asm volatile ("sync" ::: "memory"); +} + +static inline void +slbia(void) +{ + __asm volatile ("slbia"); +} + +static inline void +slbie(uint64_t esid) +{ + __asm volatile ("slbie %0" :: "r"(esid)); +} + +static inline uint64_t +slbmfee(uint64_t entry) +{ + uint64_t value; + __asm volatile ("slbmfee %0, %1" : "=r"(value) : "r"(entry)); + return value; +} + +static inline void +slbmte(uint64_t slbv, uint64_t slbe) +{ + __asm volatile ("slbmte %0, %1" :: "r"(slbv), "r"(slbe)); +} + +static inline void +tlbie(uint64_t ava) +{ + __asm volatile ("tlbie %0, %1" :: "r"(ava), "r"(0)); +} + +static inline void +tlbiel(uint64_t ava) +{ + __asm volatile ("tlbiel %0" :: "r"(ava)); +} + +static inline void +tlbsync(void) +{ + __asm volatile ("tlbsync" ::: "memory"); +} + +static inline uint64_t +mfmsr(void) +{ + uint64_t value; + __asm volatile ("mfmsr %0" : "=r"(value)); + return value; +} + +static inline void +mtmsr(uint64_t value) +{ + __asm volatile ("mtmsr %0" :: "r"(value)); +} + +static inline uint64_t +mftb(void) +{ + uint64_t value; + __asm volatile ("mftb %0" : "=r"(value)); + return value; +} + +static inline uint32_t +mfdsisr(void) +{ + uint32_t value; + __asm volatile ("mfdsisr %0" : "=r"(value)); + return value; +} + +static inline uint64_t +mfdar(void) +{ + uint64_t value; + __asm volatile ("mfdar %0" : "=r"(value)); + return value; +} + +static inline void +mtdec(uint32_t value) +{ + __asm volatile ("mtdec %0" :: "r"(value)); +} + +static inline void +mtsdr1(uint64_t value) +{ + __asm volatile ("mtsdr1 %0" :: "r"(value)); +} + +static inline void +mtamr(uint64_t value) +{ + __asm volatile ("mtspr 29, %0" :: "r"(value)); +} + +static inline void +mtfscr(uint64_t value) +{ + __asm volatile ("mtspr 153, %0" :: "r"(value)); +} + +static inline void +mtuamor(uint64_t value) +{ + __asm volatile ("mtspr 157, %0" :: "r"(value)); +} + +static inline uint32_t +mfpvr(void) +{ + uint32_t value; + __asm volatile ("mfspr %0, 287" : "=r"(value)); + return value; +} + +static inline uint64_t +mflpcr(void) +{ + uint64_t value; + __asm volatile ("mfspr %0, 318" : "=r"(value)); + return value; +} + +static inline void +mtlpcr(uint64_t value) +{ + __asm volatile ("mtspr 318, %0" :: "r"(value)); +} + +#define LPCR_PECE 0x000040000001f000UL +#define LPCR_LPES 0x0000000000000008UL +#define LPCR_HVICE 0x0000000000000002UL + +static inline void +mtamor(uint64_t value) +{ + __asm volatile ("mtspr 349, %0" :: "r"(value)); +} + +static inline void +mtptcr(uint64_t value) +{ + __asm volatile ("mtspr 464, %0" :: "r"(value)); +} + +static inline uint64_t +mfpmsr(void) +{ + uint64_t value; + __asm volatile ("mfspr %0, 853" : "=r"(value)); + return value; +} + +static inline void +mtpmcr(uint64_t value) +{ + __asm volatile ("mtspr 884, %0" :: "r"(value)); +} + +static inline uint32_t +mfpir(void) +{ + uint32_t value; + __asm volatile ("mfspr %0, 1023" : "=r"(value)); + return value; +} + +extern int cacheline_size; + +void __syncicache(void *, size_t); + +#endif /* _MACHINE_CPUFUNC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/db_machdep.h b/lib/libc/include/powerpc64-openbsd-none/machine/db_machdep.h new file mode 100644 index 000000000000..caf96c25d30a --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/db_machdep.h @@ -0,0 +1,86 @@ +/* $OpenBSD: db_machdep.h,v 1.6 2021/08/30 08:11:12 jasper Exp $*/ +/* $NetBSD: db_machdep.h,v 1.13 1996/04/29 20:50:08 leo Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +/* + * Machine-dependent defines for new kernel debugger. + */ +#ifndef _MACHINE_DB_MACHDEP_H_ +#define _MACHINE_DB_MACHDEP_H_ + +#include +#include +#include +#include + +typedef long db_expr_t; /* expression - signed */ +typedef struct trapframe db_regs_t; +extern db_regs_t ddb_regs; /* register state */ + +#define PC_REGS(regs) ((regs)->srr0) +#define SET_PC_REGS(regs, value) PC_REGS(regs) = (value) + +#define BKPT_INST 0x7C810808 /* breakpoint instruction */ + +#define BKPT_SIZE (4) /* size of breakpoint inst */ +#define BKPT_SET(inst) (BKPT_INST) + +#define db_clear_single_step(regs) ((regs)->srr1 &= ~PSL_SE) +#define db_set_single_step(regs) ((regs)->srr1 |= PSL_SE) + +#define T_BREAKPOINT 0xffff +#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BREAKPOINT) +#define IS_WATCHPOINT_TRAP(type, code) 0 + +#define M_RTS 0xfc0007fe +#define I_RTS 0x4c000020 +#define M_BC 0xfc000000 +#define I_BC 0x40000000 +#define M_B 0xfc000000 +#define I_B 0x50000000 +#define M_RFI 0xfc0007fe +#define I_RFI 0x4c000064 + +#define inst_trap_return(ins) (((ins)&M_RFI) == I_RFI) +#define inst_return(ins) (((ins)&M_RTS) == I_RTS) +#define inst_call(ins) (((ins)&M_BC ) == I_BC || \ + ((ins)&M_B ) == I_B ) + +struct trapframe; +void db_ktrap(int, db_regs_t *); + +#define DDB_STATE_NOT_RUNNING 0 +#define DDB_STATE_RUNNING 1 +#define DDB_STATE_EXITING 2 + +/* + * We define some of our own commands + */ +#define DB_MACHINE_COMMANDS + +#endif /* _MACHINE_DB_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/disklabel.h b/lib/libc/include/powerpc64-openbsd-none/machine/disklabel.h new file mode 100644 index 000000000000..3d198e06b98e --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/disklabel.h @@ -0,0 +1,26 @@ +/* $OpenBSD: disklabel.h,v 1.1 2020/05/16 17:11:14 kettenis Exp $ */ + +/* + * Copyright (c) 2014 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_DISKLABEL_H_ +#define _MACHINE_DISKLABEL_H_ + +#define LABELSECTOR 1 /* sector containing label */ +#define LABELOFFSET 0 /* offset of label in sector */ +#define MAXPARTITIONS 16 /* number of partitions */ + +#endif /* _MACHINE_DISKLABEL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/elf.h b/lib/libc/include/powerpc64-openbsd-none/machine/elf.h new file mode 100644 index 000000000000..d1a121fff937 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/elf.h @@ -0,0 +1,66 @@ +/* $OpenBSD: elf.h,v 1.3 2025/02/19 18:25:03 jca Exp $ */ + +/* + * This file is in the public domain. + */ + +#ifndef _MACHINE_ELF_H_ +#define _MACHINE_ELF_H_ + +/* + * CPU Feature Attributes + * + * These are defined in the PowerPC ELF ABI for the AT_HWCAP vector, + * and are exported to userland via the elf_aux_info(3) function. + */ + +#ifdef _KERNEL +# define __HAVE_CPU_HWCAP +# define __HAVE_CPU_HWCAP2 +extern unsigned long hwcap; +extern unsigned long hwcap2; +#endif /* _KERNEL */ + +#define PPC_FEATURE_32 0x80000000 /* Always true */ +#define PPC_FEATURE_64 0x40000000 /* Defined on a 64-bit CPU */ +#define PPC_FEATURE_601_INSTR 0x20000000 +#define PPC_FEATURE_HAS_ALTIVEC 0x10000000 +#define PPC_FEATURE_HAS_FPU 0x08000000 +#define PPC_FEATURE_HAS_MMU 0x04000000 +#define PPC_FEATURE_UNIFIED_CACHE 0x01000000 +#define PPC_FEATURE_HAS_SPE 0x00800000 +#define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000 +#define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000 +#define PPC_FEATURE_NO_TB 0x00100000 +#define PPC_FEATURE_POWER4 0x00080000 +#define PPC_FEATURE_POWER5 0x00040000 +#define PPC_FEATURE_POWER5_PLUS 0x00020000 +#define PPC_FEATURE_CELL 0x00010000 +#define PPC_FEATURE_BOOKE 0x00008000 +#define PPC_FEATURE_SMT 0x00004000 +#define PPC_FEATURE_ICACHE_SNOOP 0x00002000 +#define PPC_FEATURE_ARCH_2_05 0x00001000 +#define PPC_FEATURE_HAS_DFP 0x00000400 +#define PPC_FEATURE_POWER6_EXT 0x00000200 +#define PPC_FEATURE_ARCH_2_06 0x00000100 +#define PPC_FEATURE_HAS_VSX 0x00000080 +#define PPC_FEATURE_TRUE_LE 0x00000002 +#define PPC_FEATURE_PPC_LE 0x00000001 + +#define PPC_FEATURE2_ARCH_2_07 0x80000000 +#define PPC_FEATURE2_HTM 0x40000000 +#define PPC_FEATURE2_DSCR 0x20000000 +#define PPC_FEATURE2_EBB 0x10000000 +#define PPC_FEATURE2_ISEL 0x08000000 +#define PPC_FEATURE2_TAR 0x04000000 +#define PPC_FEATURE2_HAS_VEC_CRYPTO 0x02000000 +#define PPC_FEATURE2_HTM_NOSC 0x01000000 +#define PPC_FEATURE2_ARCH_3_00 0x00800000 +#define PPC_FEATURE2_HAS_IEEE128 0x00400000 +#define PPC_FEATURE2_DARN 0x00200000 +#define PPC_FEATURE2_SCV 0x00100000 +#define PPC_FEATURE2_HTM_NOSUSPEND 0x00080000 +#define PPC_FEATURE2_ARCH_3_1 0x00040000 +#define PPC_FEATURE2_MMA 0x00020000 + +#endif /* !_MACHINE_ELF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/endian.h b/lib/libc/include/powerpc64-openbsd-none/machine/endian.h new file mode 100644 index 000000000000..2a92d0b2fda9 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/endian.h @@ -0,0 +1,37 @@ +/* $OpenBSD: endian.h,v 1.3 2024/05/07 14:26:48 naddy Exp $ */ + +/*- + * Copyright (c) 1997 Niklas Hallqvist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_ENDIAN_H_ +#define _MACHINE_ENDIAN_H_ + +#undef _BIG_ENDIAN /* XXX - gcc may define _BIG_ENDIAN too */ +#define _BYTE_ORDER _BIG_ENDIAN + +#ifndef __FROM_SYS__ENDIAN +#include +#endif + +#endif /* _MACHINE_ENDIAN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/exec.h b/lib/libc/include/powerpc64-openbsd-none/machine/exec.h new file mode 100644 index 000000000000..219d93c1d06c --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/exec.h @@ -0,0 +1,36 @@ +/* $OpenBSD: exec.h,v 1.4 2021/03/11 11:16:59 jsg Exp $ */ + +/* + * Copyright (c) 2014 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_EXEC_H_ +#define _MACHINE_EXEC_H_ + +#define __LDPGSZ 4096 + +#define ARCH_ELFSIZE 64 + +#define ELF_TARG_CLASS ELFCLASS64 +#define ELF_TARG_DATA ELFDATA2MSB +#define ELF_TARG_MACH EM_PPC64 + +/* Processor specific dynamic tag values. */ +#define DT_PPC64_GLINK 0x70000000 +#define DT_PPC64_OPT 0x70000003 + +#define DT_PROCNUM (DT_PPC64_OPT - DT_LOPROC + 1) + +#endif \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/fdt.h b/lib/libc/include/powerpc64-openbsd-none/machine/fdt.h new file mode 100644 index 000000000000..0401cf75fb9b --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/fdt.h @@ -0,0 +1,39 @@ +/* $OpenBSD: fdt.h,v 1.2 2020/10/30 13:07:48 kettenis Exp $ */ +/* + * Copyright (c) 2016 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_FDT_H_ +#define _MACHINE_FDT_H_ + +#include + +struct fdt_attach_args { + const char *fa_name; + int fa_node; + bus_space_tag_t fa_iot; + bus_dma_tag_t fa_dmat; + struct fdt_reg *fa_reg; + int fa_nreg; + uint32_t *fa_intr; + int fa_nintr; + int fa_acells; + int fa_scells; +}; + +extern int stdout_node; +extern int stdout_speed; + +#endif /* _MACHINE_FDT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/fenv.h b/lib/libc/include/powerpc64-openbsd-none/machine/fenv.h new file mode 100644 index 000000000000..aadeaabeeec4 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/fenv.h @@ -0,0 +1,96 @@ +/* $OpenBSD: fenv.h,v 1.1 2020/06/28 08:19:34 kettenis Exp $ */ + +/* + * Copyright (c) 2011 Martynas Venckus + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_FENV_H_ +#define _MACHINE_FENV_H_ + +/* + * Each symbol representing a floating point exception expands to an integer + * constant expression with values, such that bitwise-inclusive ORs of _all + * combinations_ of the constants result in distinct values. + * + * We use such values that allow direct bitwise operations on FPU registers. + */ +#define FE_INEXACT 0x02000000 +#define FE_DIVBYZERO 0x04000000 +#define FE_UNDERFLOW 0x08000000 +#define FE_OVERFLOW 0x10000000 +#define FE_INVALID 0x20000000 +#define _FE_INVALID_SOFT 0x00000400 +#define _FE_INVALID_ALL 0x01f80700 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * exception constants defined above. + */ +#define FE_ALL_EXCEPT (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | \ + FE_OVERFLOW | FE_INVALID) +#define _MASK_SHIFT 22 + +/* + * Each symbol representing the rounding direction, expands to an integer + * constant expression whose value is distinct non-negative value. + * + * We use such values that allow direct bitwise operations on FPU registers. + */ +#define FE_TONEAREST 0x0 +#define FE_TOWARDZERO 0x1 +#define FE_UPWARD 0x2 +#define FE_DOWNWARD 0x3 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * rounding direction constants defined above. + */ +#define _ROUND_MASK (FE_TONEAREST | FE_TOWARDZERO | FE_UPWARD | \ + FE_DOWNWARD) + +/* + * fenv_t represents the entire floating-point environment. + */ +typedef unsigned int fenv_t; + +/* + * The following constant represents the default floating-point environment + * (that is, the one installed at program startup) and has type pointer to + * const-qualified fenv_t. + * + * It can be used as an argument to the functions within the header + * that manage the floating-point environment, namely fesetenv() and + * feupdateenv(). + */ +__BEGIN_DECLS +extern fenv_t __fe_dfl_env; +__END_DECLS +#define FE_DFL_ENV ((const fenv_t *)&__fe_dfl_env) + +/* + * fexcept_t represents the floating-point status flags collectively, including + * any status the implementation associates with the flags. + * + * A floating-point status flag is a system variable whose value is set (but + * never cleared) when a floating-point exception is raised, which occurs as a + * side effect of exceptional floating-point arithmetic to provide auxiliary + * information. + * + * A floating-point control mode is a system variable whose value may be set by + * the user to affect the subsequent behavior of floating-point arithmetic. + */ +typedef unsigned int fexcept_t; + +#endif /* !_MACHINE_FENV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/fpu.h b/lib/libc/include/powerpc64-openbsd-none/machine/fpu.h new file mode 100644 index 000000000000..c9637f3bc561 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/fpu.h @@ -0,0 +1,17 @@ +/* $OpenBSD: fpu.h,v 1.4 2022/03/24 18:42:05 kettenis Exp $ */ + +/* public domain */ + +#ifndef _MACHINE_FPU_H +#define _MACHINE_FPU_H + +#ifdef _KERNEL + +void save_vsx(struct proc *); +void restore_vsx(struct proc *); + +int fpu_sigcode(struct proc *); + +#endif + +#endif /* _MACHINE_FPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/frame.h b/lib/libc/include/powerpc64-openbsd-none/machine/frame.h new file mode 100644 index 000000000000..afb0dfa2956a --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/frame.h @@ -0,0 +1,104 @@ +/* $OpenBSD: frame.h,v 1.5 2020/07/13 22:37:37 kettenis Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 _MACHDEP_FRAME_H +#define _MACHDEP_FRAME_H + +/* + * We have to save all registers on every trap, because + * 1. user could attach this process every time + * 2. we must be able to restore all user registers in case of fork + * Actually, we do not save the fp registers on trap, since + * these are not used by the kernel. They are saved only when switching + * between processes using the FPU. + * + */ +struct trapframe { + __register_t fixreg[32]; + __register_t lr; + __register_t cr; + __register_t xer; + __register_t ctr; + __register_t srr0; + __register_t srr1; + __register_t vrsave; + __register_t dar; /* dar & dsisr are only filled on a DSI trap */ + __register_t dsisr; + __register_t exc; +}; + +/* + * This is to ensure alignment of the stackpointer + */ +#define FRAMELEN roundup(sizeof(struct trapframe) + 32, 16) + +struct callframe { + register_t cf_sp; + register_t cf_cr; + register_t cf_lr; + register_t cf_toc; +}; + +struct sigframe { + int sf_signum; + siginfo_t *sf_sip; + struct sigcontext sf_sc; + siginfo_t sf_si; +}; + +struct switchframe { + register_t sf_sp; + register_t sf_cr; + register_t sf_lr; /* unused */ + register_t sf_toc; /* unused */ + register_t sf_r14; + register_t sf_r15; + register_t sf_r16; + register_t sf_r17; + register_t sf_r18; + register_t sf_r19; + register_t sf_r20; + register_t sf_r21; + register_t sf_r22; + register_t sf_r23; + register_t sf_r24; + register_t sf_r25; + register_t sf_r26; + register_t sf_r27; + register_t sf_r28; + register_t sf_r29; + register_t sf_r30; + register_t sf_r31; +}; + +#endif /* _MACHDEP_FRAME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/ieee.h b/lib/libc/include/powerpc64-openbsd-none/machine/ieee.h new file mode 100644 index 000000000000..3755c7eac557 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/ieee.h @@ -0,0 +1,119 @@ +/* $OpenBSD: ieee.h,v 1.1 2020/06/01 00:13:37 drahn Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ieee.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * ieee.h defines the machine-dependent layout of the machine's IEEE + * floating point. It does *not* define (yet?) any of the rounding + * mode bits, exceptions, and so forth. + */ + +/* + * Define the number of bits in each fraction and exponent. + * + * k k+1 + * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented + * + * (-exp_bias+1) + * as fractions that look like 0.fffff x 2 . This means that + * + * -126 + * the number 0.10000 x 2 , for instance, is the same as the normalized + * + * -127 -128 + * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero + * + * -129 + * in the fraction; to represent 2 , we need two, and so on. This + * + * (-exp_bias-fracbits+1) + * implies that the smallest denormalized number is 2 + * + * for whichever format we are talking about: for single precision, for + * + * -126 -149 + * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and + * + * -149 == -127 - 23 + 1. + */ +#define SNG_EXPBITS 8 +#define SNG_FRACBITS 23 + +#define DBL_EXPBITS 11 +#define DBL_FRACHBITS 20 +#define DBL_FRACLBITS 32 +#define DBL_FRACBITS 52 + +struct ieee_single { + u_int sng_sign:1; + u_int sng_exp:8; + u_int sng_frac:23; +}; + +struct ieee_double { + u_int dbl_sign:1; + u_int dbl_exp:11; + u_int dbl_frach:20; + u_int dbl_fracl; +}; + +/* + * Floats whose exponent is in [1..INFNAN) (of whatever type) are + * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. + * Floats whose exponent is zero are either zero (iff all fraction + * bits are zero) or subnormal values. + * + * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its + * high fraction; if the bit is set, it is a `quiet NaN'. + */ +#define SNG_EXP_INFNAN 255 +#define DBL_EXP_INFNAN 2047 + +#if 0 +#define SNG_QUIETNAN (1 << 22) +#define DBL_QUIETNAN (1 << 19) +#endif + +/* + * Exponent biases. + */ +#define SNG_EXP_BIAS 127 +#define DBL_EXP_BIAS 1023 \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/ieeefp.h b/lib/libc/include/powerpc64-openbsd-none/machine/ieeefp.h new file mode 100644 index 000000000000..6b379119518c --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/ieeefp.h @@ -0,0 +1,25 @@ +/* $OpenBSD: ieeefp.h,v 1.1 2020/06/01 00:13:37 drahn Exp $ */ +/* $NetBSD: ieeefp.h,v 1.2 1999/07/07 01:52:26 danw Exp $ */ +/* + * Written by J.T. Conklin, Apr 6, 1995 + * Public domain. + */ + +#ifndef _POWERPC_IEEEFP_H_ +#define _POWERPC_IEEEFP_H_ + +typedef int fp_except; +#define FP_X_IMP 0x01 /* imprecise (loss of precision) */ +#define FP_X_DZ 0x02 /* divide-by-zero exception */ +#define FP_X_UFL 0x04 /* underflow exception */ +#define FP_X_OFL 0x08 /* overflow exception */ +#define FP_X_INV 0x10 /* invalid operation exception */ + +typedef enum { + FP_RN=0, /* round to nearest representable number */ + FP_RZ=1, /* round to zero (truncate) */ + FP_RP=2, /* round toward positive infinity */ + FP_RM=3 /* round toward negative infinity */ +} fp_rnd; + +#endif /* _POWERPC_IEEEFP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/intr.h b/lib/libc/include/powerpc64-openbsd-none/machine/intr.h new file mode 100644 index 000000000000..e6a70160ba3d --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/intr.h @@ -0,0 +1,135 @@ +/* $OpenBSD: intr.h,v 1.16 2025/04/26 11:10:28 visa Exp $ */ + +/* + * Copyright (c) 2020 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_INTR_H_ +#define _MACHINE_INTR_H_ + +#define __USE_MI_SOFTINTR + +#include +#include + +struct cpu_info; +struct trapframe; + +#define IPL_NONE 0 +#define IPL_SOFTCLOCK 2 +#define IPL_SOFTNET 3 +#define IPL_SOFTTTY 4 +#define IPL_BIO 5 +#define IPL_NET 6 +#define IPL_TTY 7 +#define IPL_VM IPL_TTY +#define IPL_AUDIO 8 +#define IPL_CLOCK 9 +#define IPL_STATCLOCK IPL_CLOCK +#define IPL_SCHED IPL_CLOCK +#define IPL_HIGH IPL_CLOCK +#define IPL_IPI 10 +#define NIPL 11 + +#define IPL_MPFLOOR IPL_TTY +/* Interrupt priority 'flags'. */ +#define IPL_IRQMASK 0xf /* priority only */ +#define IPL_FLAGMASK 0xf00 /* flags only*/ +#define IPL_MPSAFE 0x100 /* 'mpsafe' interrupt, no kernel lock */ + +int splraise(int); +int spllower(int); +void splx(int); + +void softintr(int); + +#define spl0() spllower(IPL_NONE) +#define splsoftclock() splraise(IPL_SOFTCLOCK) +#define splsoftnet() splraise(IPL_SOFTNET) +#define splsofttty() splraise(IPL_SOFTTTY) +#define splbio() splraise(IPL_BIO) +#define splnet() splraise(IPL_NET) +#define spltty() splraise(IPL_TTY) +#define splvm() splraise(IPL_VM) +#define splclock() splraise(IPL_CLOCK) +#define splstatclock() splraise(IPL_STATCLOCK) +#define splsched() splraise(IPL_SCHED) +#define splhigh() splraise(IPL_HIGH) + +#ifdef DIAGNOSTIC +/* + * Although this function is implemented in MI code, it must be in this MD + * header because we don't want this header to include MI includes. + */ +void splassert_fail(int, int, const char *); +extern int splassert_ctl; +void splassert_check(int, const char *); +#define splassert(__wantipl) do { \ + if (splassert_ctl > 0) { \ + splassert_check(__wantipl, __func__); \ + } \ +} while (0) +#define splsoftassert(wantipl) splassert(wantipl) +#else +#define splassert(wantipl) do { /* nothing */ } while (0) +#define splsoftassert(wantipl) do { /* nothing */ } while (0) +#endif + +void intr_init(void); + +#define intr_barrier(x) + +#define IST_EDGE 0 +#define IST_LEVEL 1 + +void *intr_establish(uint32_t, int, int, struct cpu_info *, + int (*)(void *), void *, const char *); + +#define IPI_NOP 0 +#define IPI_DDB (1 << 0) +#define IPI_SETPERF (1 << 1) + +void intr_send_ipi(struct cpu_info *, int); + +extern void (*_exi)(struct trapframe *); +extern void (*_hvi)(struct trapframe *); +extern void *(*_intr_establish)(uint32_t, int, int, struct cpu_info *, + int (*)(void *), void *, const char *); +extern void (*_intr_send_ipi)(void *); +extern void (*_setipl)(int); + +struct interrupt_controller { + int ic_node; + void *ic_cookie; + void *(*ic_establish)(void *, int *, int, struct cpu_info *, + int (*)(void *), void *, char *); + void (*ic_send_ipi)(void *); + + LIST_ENTRY(interrupt_controller) ic_list; + uint32_t ic_phandle; + uint32_t ic_cells; +}; + +void interrupt_controller_register(struct interrupt_controller *); + +void *fdt_intr_establish_idx_cpu(int, int, int, struct cpu_info *, + int (*)(void *), void *, char *); +void *fdt_intr_establish_imap(int, int *, int, int, int (*)(void *), + void *, char *); +void *fdt_intr_establish_imap_cpu(int, int *, int, int, + struct cpu_info *, int (*)(void *), void *, char *); +void fdt_intr_disestablish(void *); + +#endif /* _MACHINE_INTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/kcore.h b/lib/libc/include/powerpc64-openbsd-none/machine/kcore.h new file mode 100644 index 000000000000..c94e37366eb8 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/kcore.h @@ -0,0 +1 @@ +/* Empty */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/kexec.h b/lib/libc/include/powerpc64-openbsd-none/machine/kexec.h new file mode 100644 index 000000000000..e909bfcc3e7c --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/kexec.h @@ -0,0 +1,36 @@ +/* $OpenBSD: kexec.h,v 1.3 2020/07/18 10:23:44 kettenis Exp $ */ + +/* + * Copyright (c) 2019-2020 Visa Hankala + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_KEXEC_H_ +#define _MACHINE_KEXEC_H_ + +#include + +#define KEXEC_MAX_ARGS 8 /* maximum number of boot arguments */ + +struct kexec_args { + char *kimg; /* kernel image buffer */ + size_t klen; /* size of kernel image */ + int boothowto; + u_char bootduid[8]; +}; + +#define KIOC_KEXEC _IOW('K', 1, struct kexec_args) +#define KIOC_GETBOOTDUID _IOR('K', 2, u_char[8]) + +#endif /* _MACHINE_KEXEC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/limits.h b/lib/libc/include/powerpc64-openbsd-none/machine/limits.h new file mode 100644 index 000000000000..d2c0f2eaf30a --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/limits.h @@ -0,0 +1,55 @@ +/* $OpenBSD: limits.h,v 1.1 2020/05/16 17:11:14 kettenis Exp $ */ + +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)limits.h 7.2 (Berkeley) 6/28/90 + */ + +#ifndef _MACHINE_LIMITS_H_ +#define _MACHINE_LIMITS_H_ + +#include + +#if __POSIX_VISIBLE || __XPG_VISIBLE +#ifndef SIZE_MAX +#define SIZE_MAX ULONG_MAX /* max value for a size_t */ +#endif +#define SSIZE_MAX LONG_MAX /* max value for a ssize_t */ +#endif + +#if __BSD_VISIBLE +#define SIZE_T_MAX ULONG_MAX /* max value for a size_t (historic) */ + +#define UQUAD_MAX 0xffffffffffffffffULL /* max unsigned quad */ +#define QUAD_MAX 0x7fffffffffffffffLL /* max signed quad */ +#define QUAD_MIN (-0x7fffffffffffffffLL-1) /* min signed quad */ + +#endif /* __BSD_VISIBLE */ + +#endif /* _MACHINE_LIMITS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/mplock.h b/lib/libc/include/powerpc64-openbsd-none/machine/mplock.h new file mode 100644 index 000000000000..1856d8925a4e --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/mplock.h @@ -0,0 +1,10 @@ +/* $OpenBSD: mplock.h,v 1.1 2020/07/22 11:08:01 kettenis Exp $ */ + +/* public domain */ + +#ifndef _MACHINE_MPLOCK_H_ +#define _MACHINE_MPLOCK_H_ + +#define __USE_MI_MPLOCK + +#endif /* !_MACHINE_MPLOCK_H */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/mutex.h b/lib/libc/include/powerpc64-openbsd-none/machine/mutex.h new file mode 100644 index 000000000000..9f22aee173be --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/mutex.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mutex.h,v 1.1 2020/05/16 17:11:14 kettenis Exp $ */ + +#define __USE_MI_MUTEX \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/opal.h b/lib/libc/include/powerpc64-openbsd-none/machine/opal.h new file mode 100644 index 000000000000..98106675bbf2 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/opal.h @@ -0,0 +1,238 @@ +/* $OpenBSD: opal.h,v 1.19 2021/01/23 12:10:08 kettenis Exp $ */ + +/* + * Copyright (c) 2020 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_OPAL_H_ +#define _MACHINE_OPAL_H_ + +/* Tokens. */ +#define OPAL_TEST 0 +#define OPAL_CONSOLE_WRITE 1 +#define OPAL_CONSOLE_READ 2 +#define OPAL_RTC_READ 3 +#define OPAL_RTC_WRITE 4 +#define OPAL_CEC_POWER_DOWN 5 +#define OPAL_CEC_REBOOT 6 +#define OPAL_HANDLE_INTERRUPT 9 +#define OPAL_POLL_EVENTS 10 +#define OPAL_PCI_CONFIG_READ_WORD 15 +#define OPAL_PCI_CONFIG_WRITE_WORD 18 +#define OPAL_SET_XIVE 19 +#define OPAL_GET_XIVE 20 +#define OPAL_PCI_EEH_FREEZE_STATUS 23 +#define OPAL_PCI_EEH_FREEZE_CLEAR 26 +#define OPAL_PCI_PHB_MMIO_ENABLE 27 +#define OPAL_PCI_SET_PHB_MEM_WINDOW 28 +#define OPAL_PCI_MAP_PE_MMIO_WINDOW 29 +#define OPAL_PCI_SET_PE 31 +#define OPAL_PCI_SET_XIVE_PE 37 +#define OPAL_GET_MSI_32 39 +#define OPAL_GET_MSI_64 40 +#define OPAL_START_CPU 41 +#define OPAL_PCI_MAP_PE_DMA_WINDOW 44 +#define OPAL_PCI_MAP_PE_DMA_WINDOW_REAL 45 +#define OPAL_PCI_RESET 49 +#define OPAL_REINIT_CPUS 70 +#define OPAL_CHECK_TOKEN 80 +#define OPAL_SENSOR_READ 88 +#define OPAL_IPMI_SEND 107 +#define OPAL_IPMI_RECV 108 +#define OPAL_CONSOLE_FLUSH 117 +#define OPAL_XIVE_RESET 128 +#define OPAL_XIVE_GET_IRQ_INFO 129 +#define OPAL_XIVE_GET_IRQ_CONFIG 131 +#define OPAL_XIVE_SET_IRQ_CONFIG 131 +#define OPAL_XIVE_GET_QUEUE_INFO 132 +#define OPAL_XIVE_SET_QUEUE_INFO 133 +#define OPAL_XIVE_GET_VP_INFO 137 +#define OPAL_XIVE_SET_VP_INFO 138 +#define OPAL_XIVE_DUMP 142 +#define OPAL_SENSOR_READ_U64 162 + +/* Return codes. */ +#define OPAL_SUCCESS 0 +#define OPAL_PARAMETER -1 +#define OPAL_BUSY -2 +#define OPAL_PARTIAL -3 +#define OPAL_CONSTRAINED -4 +#define OPAL_CLOSED -5 +#define OPAL_HARDWARE -6 +#define OPAL_UNSUPPORTED -7 +#define OPAL_PERMISSION -8 +#define OPAL_NO_MEM -9 +#define OPAL_RESOURCE -10 +#define OPAL_INTERNAL_ERROR -11 +#define OPAL_BUSY_EVENT -12 +#define OPAL_HARDWARE_FROZEN -13 +#define OPAL_WRONG_STATE -14 +#define OPAL_ASYNC_COMPLETION -15 +#define OPAL_EMPTY -16 + +/* OPAL_POLL_EVENT */ +#define OPAL_EVENT_CONSOLE_OUTPUT 0x00000008 +#define OPAL_EVENT_CONSOLE_INPUT 0x00000010 + +/* OPAL_PCI_EEH_FREEZE_CLEAR */ +#define OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO 1 +#define OPAL_EEH_ACTION_CLEAR_FREEZE_DMA 2 +#define OPAL_EEH_ACTION_CLEAR_FREEZE_ALL 3 + +/* OPAL_PCI_PHB_MMIO_ENABLE */ +#define OPAL_M32_WINDOW_TYPE 1 +#define OPAL_M64_WINDOW_TYPE 2 +#define OPAL_IO_WINDOW_TYPE 3 +#define OPAL_DISABLE_M64 0 +#define OPAL_ENABLE_M64_SPLIT 1 +#define OPAL_ENABLE_M64_NON_SPLIT 2 + +/* OPAL_PCIE_SET_PE */ +#define OPAL_IGNORE_RID_BUS_NUMBER 0 +#define OPAL_IGNORE_RID_DEVICE_NUMBER 0 +#define OPAL_COMPARE_RID_DEVICE_NUMBER 1 +#define OPAL_IGNORE_RID_FUNCTION_NUMBER 0 +#define OPAL_COMPARE_RID_FUNCTION_NUMBER 1 +#define OPAL_UNMAP_PE 0 +#define OPAL_MAP_PE 1 + +/* OPAL_PCI_RESET */ +#define OPAL_RESET_PHB_COMPLETE 1 +#define OPAL_RESET_PCI_LINK 2 +#define OPAL_RESET_PHB_ERROR 3 +#define OPAL_RESET_PCI_HOT 4 +#define OPAL_RESET_PCI_FUNDAMENTAL 5 +#define OPAL_RESET_PCI_IODA_TABLE 6 +#define OPAL_DEASSERT_RESET 0 +#define OPAL_ASSERT_RESET 1 + +/* OPAL_REINIT_CPUS */ +#define OPAL_REINIT_CPUS_HILE_BE 0x00000001 +#define OPAL_REINIT_CPUS_HILE_LE 0x00000002 +#define OPAL_REINIT_CPUS_MMU_HASH 0x00000004 +#define OPAL_REINIT_CPUS_MMU_RADIX 0x00000008 +#define OPAL_REINIT_CPUS_TM_SUSPEND_DISABLED 0x00000010 + +/* OPAL_CHECK_TOKEN */ +#define OPAL_TOKEN_ABSENT 0 +#define OPAL_TOKEN_PRESENT 1 + +/* OPAL_IPMI_SEND/RECV */ +#define OPAL_IPMI_MSG_FORMAT_VERSION_1 1 + +#ifndef _LOCORE +struct opal_ipmi_msg { + uint8_t version; + uint8_t netfn; + uint8_t cmd; + uint8_t data[0]; +}; +#endif + +/* OPAL_XIVE_RESET */ +#define OPAL_XIVE_MODE_EMU 0 +#define OPAL_XIVE_MODE_EXPL 1 + +/* OPAL_XIVE_GET_IRQ_INFO */ +#define OPAL_XIVE_IRQ_TRIGGER_PAGE 0x00000001 +#define OPAL_XIVE_IRQ_STORE_EOI 0x00000002 +#define OPAL_XIVE_IRQ_LSI 0x00000004 +#define OPAL_XIVE_IRQ_SHIFT_BUG 0x00000008 +#define OPAL_XIVE_IRQ_MASK_VIA_FW 0x00000010 +#define OPAL_XIVE_IRQ_EOI_VIA_FW 0x00000020 + +/* OPAL_XIVE_GET_QUEUE_INFO */ +#define OPAL_XIVE_EQ_ENABLED 0x00000001 +#define OPAL_XIVE_EQ_ALWAYS_NOTIFY 0x00000002 +#define OPAL_XIVE_EQ_ESCALATE 0x00000004 + +/* OPAL_XIVE_GET_VP_INFO */ +#define OPAL_XIVE_VP_ENABLED 0x00000001 +#define OPAL_XIVE_VP_SINGLE_ESCALATION 0x00000002 + +/* OPAL_XIVE_DUMP */ +#define XIVE_DUMP_TM_HYP 0x00000000 +#define XIVE_DUMP_TM_POOL 0x00000001 +#define XIVE_DUMP_TM_OS 0x00000002 +#define XIVE_DUMP_TM_USER 0x00000003 +#define XIVE_DUMP_VP 0x00000004 +#define XIVE_DUMP_EMU_STATE 0x00000005 + +#ifndef _LOCORE + +void *opal_phys(void *); + +int64_t opal_test(uint64_t); +int64_t opal_console_write(int64_t, int64_t *, const uint8_t *); +int64_t opal_console_read(int64_t, int64_t *, uint8_t *); +int64_t opal_rtc_read(uint32_t *, uint64_t *); +int64_t opal_rtc_write(uint32_t, uint64_t); +int64_t opal_cec_power_down(uint64_t); +int64_t opal_cec_reboot(void); +int64_t opal_handle_interrupt(uint32_t, uint64_t *); +int64_t opal_poll_events(uint64_t *); +int64_t opal_pci_config_read_word(uint64_t, uint64_t, uint64_t, uint32_t *); +int64_t opal_pci_config_write_word(uint64_t, uint64_t, uint64_t, uint32_t); +int64_t opal_set_xive(uint32_t, uint16_t, uint8_t); +int64_t opal_get_xive(uint32_t, uint16_t *, uint8_t *); +int64_t opal_pci_eeh_freeze_status(uint64_t, uint64_t, uint8_t *, + uint16_t *, uint64_t *); +int64_t opal_pci_eeh_freeze_clear(uint64_t, uint64_t, uint64_t); +int64_t opal_pci_phb_mmio_enable(uint64_t, uint16_t, uint16_t, uint16_t); +int64_t opal_pci_set_phb_mem_window(uint64_t, uint16_t, uint16_t, + uint64_t, uint64_t, uint64_t); +int64_t opal_pci_map_pe_mmio_window(uint64_t, uint64_t, uint16_t, + uint16_t, uint16_t); +int64_t opal_pci_set_pe(uint64_t, uint64_t, uint64_t, uint8_t, uint8_t, + uint8_t, uint8_t); +int64_t opal_pci_set_xive_pe(uint64_t, uint64_t, uint32_t); +int64_t opal_get_msi_32(uint64_t, uint32_t, uint32_t, uint8_t, + uint32_t *, uint32_t *); +int64_t opal_get_msi_64(uint64_t, uint32_t, uint32_t, uint8_t, + uint64_t *, uint32_t *); +int64_t opal_start_cpu(uint64_t, uint64_t); +int64_t opal_pci_map_pe_dma_window(uint64_t, uint64_t, uint16_t, uint16_t, + uint64_t, uint64_t, uint64_t); +int64_t opal_pci_map_pe_dma_window_real(uint64_t, uint64_t, uint16_t, + uint64_t, uint64_t); +int64_t opal_pci_reset(uint64_t, uint8_t, uint8_t); +int64_t opal_reinit_cpus(uint64_t); +int64_t opal_check_token(uint64_t); +int64_t opal_sensor_read(uint32_t, int, uint32_t *); +int64_t opal_ipmi_send(uint64_t, struct opal_ipmi_msg *, uint64_t); +int64_t opal_ipmi_recv(uint64_t, struct opal_ipmi_msg *, uint64_t *); +int64_t opal_console_flush(uint64_t); +int64_t opal_xive_reset(uint64_t); +int64_t opal_xive_get_irq_info(uint32_t, uint64_t *, uint64_t *, + uint64_t *, uint32_t *, uint32_t *); +int64_t opal_xive_get_irq_config(uint32_t, uint64_t *, uint8_t *, uint32_t *); +int64_t opal_xive_set_irq_config(uint32_t, uint64_t, uint8_t, uint32_t); +int64_t opal_xive_get_queue_info(uint64_t, uint8_t, uint64_t *, + uint64_t *, uint64_t *, uint32_t *, uint64_t *); +int64_t opal_xive_set_queue_info(uint64_t, uint8_t, uint64_t, + uint64_t, uint64_t); +int64_t opal_xive_get_vp_info(uint64_t, uint64_t *, uint64_t *, + uint64_t *, uint32_t *); +int64_t opal_xive_set_vp_info(uint64_t, uint64_t, uint64_t); +int64_t opal_xive_dump(uint32_t, uint32_t); +int64_t opal_sensor_read_u64(uint32_t, int, uint64_t *); + +void opal_printf(const char *fmt, ...); + +void *opal_intr_establish(uint64_t, int, int (*)(void *), void *); + +#endif + +#endif /* _MACHINE_OPAL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/openpromio.h b/lib/libc/include/powerpc64-openbsd-none/machine/openpromio.h new file mode 100644 index 000000000000..e4f9fce47b1b --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/openpromio.h @@ -0,0 +1,57 @@ +/* $OpenBSD: openpromio.h,v 1.1 2020/06/27 21:39:05 kettenis Exp $ */ +/* $NetBSD: openpromio.h,v 1.1.1.1 1998/06/20 04:58:52 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)openpromio.h 8.1 (Berkeley) 6/11/93 + */ + +struct opiocdesc { + int op_nodeid; /* passed or returned node id */ + int op_namelen; /* length of op_name */ + char *op_name; /* pointer to field name */ + int op_buflen; /* length of op_buf (value-result) */ + char *op_buf; /* pointer to field value */ +}; + +#define OPIOCGET _IOWR('O', 1, struct opiocdesc) /* get openprom field */ +#define OPIOCSET _IOW('O', 2, struct opiocdesc) /* set openprom field */ +#define OPIOCNEXTPROP _IOWR('O', 3, struct opiocdesc) /* get next property */ +#define OPIOCGETOPTNODE _IOR('O', 4, int) /* get openprom field */ +#define OPIOCGETNEXT _IOWR('O', 5, int) /* get next node of node */ +#define OPIOCGETCHILD _IOWR('O', 6, int) /* get first child of node */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/param.h b/lib/libc/include/powerpc64-openbsd-none/machine/param.h new file mode 100644 index 000000000000..00b5dc20577c --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/param.h @@ -0,0 +1,80 @@ +/* $OpenBSD: param.h,v 1.3 2025/07/07 18:33:37 kettenis Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ + +#ifdef _KERNEL +#ifndef _LOCORE +#include +#endif +#endif + +#define _MACHINE powerpc64 +#define MACHINE "powerpc64" +#define _MACHINE_ARCH powerpc64 +#define MACHINE_ARCH "powerpc64" +#define MID_MACHINE MID_POWERPC64 + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define PAGE_MASK (PAGE_SIZE - 1) + +#define KERNBASE 0xffffff8000000000ULL /* start of kernel virtual space */ + +#ifdef _KERNEL + +#define NBPG PAGE_SIZE /* bytes/page */ +#define PGSHIFT PAGE_SHIFT /* LOG2(PAGE_SIZE) */ +#define PGOFSET PAGE_MASK /* byte offset into page */ + +#define UPAGES 6 /* pages of u-area */ +#define USPACE (UPAGES * PAGE_SIZE) /* total size of u-area */ +#define USPACE_ALIGN 0 /* u-area alignment 0-none */ +#define __HAVE_USPACE_GUARD + +#define NMBCLUSTERS (64 * 1024) /* max cluster allocation */ + +#ifndef MSGBUFSIZE +#define MSGBUFSIZE (16 * PAGE_SIZE) /* default message buffer size */ +#endif + +#define STACKALIGNBYTES (32 - 1) +#define STACKALIGN(p) ((u_long)(p) &~ STACKALIGNBYTES) + +#define __HAVE_FDT + +#endif /* _KERNEL */ + +#endif /* _MACHINE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/pcb.h b/lib/libc/include/powerpc64-openbsd-none/machine/pcb.h new file mode 100644 index 000000000000..58948188ec59 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/pcb.h @@ -0,0 +1,37 @@ +/* $OpenBSD: pcb.h,v 1.8 2021/01/09 13:14:02 kettenis Exp $ */ + +/* + * Copyright (c) 2020 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_PCB_H_ +#define _MACHINE_PCB_H_ + +#include +#include + +struct pcb { + register_t pcb_sp; + u_int pcb_flags; +#define PCB_FPU 0x000000001 +#define PCB_VEC 0x000000002 +#define PCB_VSX 0x000000004 + struct slb pcb_slb[32]; + vaddr_t pcb_onfault; + vaddr_t pcb_userva; + struct fpreg pcb_fpstate; +}; + +#endif /* _MACHINE_PCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/pci_machdep.h b/lib/libc/include/powerpc64-openbsd-none/machine/pci_machdep.h new file mode 100644 index 000000000000..0f0168282f43 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/pci_machdep.h @@ -0,0 +1,134 @@ +/* $OpenBSD: pci_machdep.h,v 1.6 2024/05/22 05:51:49 jsg Exp $ */ + +/* + * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +typedef struct ppc64_pci_chipset *pci_chipset_tag_t; +typedef uint64_t pcitag_t; + +#define PCITAG_NODE(x) ((x) >> 32) +#define PCITAG_OFFSET(x) ((x) & 0xffffffff) + +/* Supported interrupt types. */ +#define PCI_NONE 0 +#define PCI_INTX 1 +#define PCI_MSI32 2 +#define PCI_MSI64 3 +#define PCI_MSIX 4 + +typedef struct { + pci_chipset_tag_t ih_pc; + pcitag_t ih_tag; + int ih_intrpin; + int ih_type; +} pci_intr_handle_t; + +struct pci_attach_args; + +/* + * powerpc64-specific PCI structure and type definitions. + * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE. + */ +struct ppc64_pci_chipset { + void *pc_conf_v; + void (*pc_attach_hook)(struct device *, + struct device *, struct pcibus_attach_args *); + int (*pc_bus_maxdevs)(void *, int); + pcitag_t (*pc_make_tag)(void *, int, int, int); + void (*pc_decompose_tag)(void *, pcitag_t, int *, + int *, int *); + int (*pc_conf_size)(void *, pcitag_t); + pcireg_t (*pc_conf_read)(void *, pcitag_t, int); + void (*pc_conf_write)(void *, pcitag_t, int, pcireg_t); + + void *pc_intr_v; + int (*pc_intr_map)(struct pci_attach_args *, + pci_intr_handle_t *); + int (*pc_intr_map_msi)(struct pci_attach_args *, + pci_intr_handle_t *); + int (*pc_intr_map_msix)(struct pci_attach_args *, + int, pci_intr_handle_t *); + const char *(*pc_intr_string)(void *, pci_intr_handle_t); + void *(*pc_intr_establish)(void *, pci_intr_handle_t, + int, struct cpu_info *, int (*)(void *), void *, + char *); + void (*pc_intr_disestablish)(void *, void *); +}; + +/* + * Functions provided to machine-independent PCI code. + */ +#define pci_attach_hook(p, s, pba) \ + (*(pba)->pba_pc->pc_attach_hook)((p), (s), (pba)) +#define pci_bus_maxdevs(c, b) \ + (*(c)->pc_bus_maxdevs)((c)->pc_conf_v, (b)) +#define pci_make_tag(c, b, d, f) \ + (*(c)->pc_make_tag)((c)->pc_conf_v, (b), (d), (f)) +#define pci_decompose_tag(c, t, bp, dp, fp) \ + (*(c)->pc_decompose_tag)((c)->pc_conf_v, (t), (bp), (dp), (fp)) +#define pci_conf_size(c, t) \ + (*(c)->pc_conf_size)((c)->pc_conf_v, (t)) +#define pci_conf_read(c, t, r) \ + (*(c)->pc_conf_read)((c)->pc_conf_v, (t), (r)) +#define pci_conf_write(c, t, r, v) \ + (*(c)->pc_conf_write)((c)->pc_conf_v, (t), (r), (v)) +#define pci_intr_map(c, ihp) \ + (*(c)->pa_pc->pc_intr_map)((c), (ihp)) +#define pci_intr_map_msi(c, ihp) \ + (*(c)->pa_pc->pc_intr_map_msi)((c), (ihp)) +#define pci_intr_map_msix(c, vec, ihp) \ + (*(c)->pa_pc->pc_intr_map_msix)((c), (vec), (ihp)) +#define pci_intr_string(c, ih) \ + (*(c)->pc_intr_string)((c)->pc_intr_v, (ih)) +#define pci_intr_establish(c, ih, l, h, a, nm) \ + (*(c)->pc_intr_establish)((c)->pc_intr_v, (ih), (l), NULL, (h), (a),\ + (nm)) +#define pci_intr_establish_cpu(c, ih, l, ci, h, a, nm) \ + (*(c)->pc_intr_establish)((c)->pc_intr_v, (ih), (l), (ci), (h), (a),\ + (nm)) +#define pci_intr_disestablish(c, iv) \ + (*(c)->pc_intr_disestablish)((c)->pc_intr_v, (iv)) +#define pci_probe_device_hook(c, a) (0) + +#define pci_min_powerstate(c, t) (PCI_PMCSR_STATE_D3) +#define pci_set_powerstate_md(c, t, s, p) + +#define pci_dev_postattach(a, b) + +void pci_mcfg_init(bus_space_tag_t, bus_addr_t, int, int, int); + +void pci_msi_enable(pci_chipset_tag_t, pcitag_t, bus_addr_t, uint32_t); +void pci_msix_enable(pci_chipset_tag_t, pcitag_t, bus_space_tag_t, + int, bus_addr_t, uint32_t); +int _pci_intr_map_msi(struct pci_attach_args *, pci_intr_handle_t *); +int _pci_intr_map_msix(struct pci_attach_args *, int, pci_intr_handle_t *); + +#define __HAVE_PCI_MSIX + +int pci_msix_table_map(pci_chipset_tag_t, pcitag_t, + bus_space_tag_t, bus_space_handle_t *); +void pci_msix_table_unmap(pci_chipset_tag_t, pcitag_t, + bus_space_tag_t, bus_space_handle_t); \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/pmap.h b/lib/libc/include/powerpc64-openbsd-none/machine/pmap.h new file mode 100644 index 000000000000..661c2cf34dd4 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/pmap.h @@ -0,0 +1,98 @@ +/* $OpenBSD: pmap.h,v 1.19 2023/12/11 22:12:53 kettenis Exp $ */ + +/* + * Copyright (c) 2020 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_PMAP_H_ +#define _MACHINE_PMAP_H_ + +#include +#include + +#ifdef _KERNEL + +#include + +/* V->P mapping data */ +#define VP_IDX1_CNT 256 +#define VP_IDX1_MASK (VP_IDX1_CNT - 1) +#define VP_IDX1_POS 20 +#define VP_IDX2_CNT 256 +#define VP_IDX2_MASK (VP_IDX2_CNT - 1) +#define VP_IDX2_POS 12 + +struct pmap { + LIST_HEAD(,slb_desc) pm_slbd; + int pm_refs; + struct pmap_statistics pm_stats; + struct mutex pm_mtx; +}; + +typedef struct pmap *pmap_t; + +#define PG_PMAP_MOD PG_PMAP0 +#define PG_PMAP_REF PG_PMAP1 +#define PG_PMAP_EXE PG_PMAP2 +#define PG_PMAP_UC PG_PMAP3 + +#define PMAP_CACHE_DEFAULT 0 +#define PMAP_CACHE_CI 1 /* cache inhibit */ +#define PMAP_CACHE_WB 3 /* write-back cached */ + +/* + * MD flags that we use for pmap_enter (in the pa): + */ +#define PMAP_PA_MASK ~((paddr_t)PAGE_MASK) /* to remove the flags */ +#define PMAP_NOCACHE 0x1 /* map uncached */ + +extern struct pmap kernel_pmap_store; + +#define pmap_kernel() (&kernel_pmap_store) +#define pmap_resident_count(pm) ((pm)->pm_stats.resident_count) +#define pmap_wired_count(pm) ((pm)->pm_stats.wired_count) + +#define pmap_init_percpu() do { /* nothing */ } while (0) +#define pmap_unuse_final(p) +#define pmap_remove_holes(vm) +#define pmap_update(pm) + +void pmap_bootstrap(void); +void pmap_bootstrap_cpu(void); + +int pmap_slbd_fault(pmap_t, vaddr_t); +int pmap_slbd_enter(pmap_t, vaddr_t); +int pmap_set_user_slb(pmap_t, vaddr_t, vaddr_t *, vsize_t *); +void pmap_clear_user_slb(void); +void pmap_unset_user_slb(void); + +#ifdef DDB +struct pte; +struct pte *pmap_get_kernel_pte(vaddr_t); +#endif + +#endif /* _KERNEL */ + +struct vm_page_md { + struct mutex pv_mtx; + LIST_HEAD(,pte_desc) pv_list; +}; + +#define VM_MDPAGE_INIT(pg) do { \ + mtx_init(&(pg)->mdpage.pv_mtx, IPL_VM); \ + LIST_INIT(&((pg)->mdpage.pv_list)); \ +} while (0) + +#endif /* _MACHINE_PMAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/proc.h b/lib/libc/include/powerpc64-openbsd-none/machine/proc.h new file mode 100644 index 000000000000..da21008f744a --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/proc.h @@ -0,0 +1,46 @@ +/* $OpenBSD: proc.h,v 1.3 2020/06/22 16:58:20 kettenis Exp $ */ + +/* + * Copyright (c) 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)proc.h 7.1 (Berkeley) 5/15/91 + */ + +#ifndef _MACHINE_PROC_H_ +#define _MACHINE_PROC_H_ + +/* + * Machine-dependent part of the proc structure for arm64. + */ +struct mdproc { + struct trapframe *md_regs; + volatile int md_astpending; + paddr_t md_user_slb_pa; +}; + +#endif /* _MACHINE_PROC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/profile.h b/lib/libc/include/powerpc64-openbsd-none/machine/profile.h new file mode 100644 index 000000000000..a27eeba08c8a --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/profile.h @@ -0,0 +1,70 @@ +/* $OpenBSD: profile.h,v 1.1 2020/06/25 01:55:14 drahn Exp $ */ + +/* + * Copyright (c) 2020 Dale Rahn drahn@openbsd.org + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * mcount frame size skips over the red zone (288B) (calling function may use) + * and 128 bytes of local storage (32 bytes of reserved and 96 of our storage + * this function assumes it will only every call the local __mcount function + */ +#define MCOUNT \ +__asm__(" \n"\ + " .section \".text\" \n"\ + " .p2align 2 \n"\ + " .globl _mcount \n"\ + " .local __mcount \n"\ + " .type _mcount,@function \n"\ + "_mcount: \n"\ + ".L_mcount_gep0: \n"\ + " addis %r2, %r12, .TOC.-.L_mcount_gep0@ha; \n"\ + " addi %r2, %r2, .TOC.-.L_mcount_gep0@l; \n"\ + ".L_mcount_lep0: \n"\ + ".localentry _mcount, .L_mcount_lep0-.L_mcount_gep0; \n"\ + " ld %r11,16(%r1) \n"\ + " mflr %r0 \n"\ + " std %r0, 16(%r1) \n"\ + " stdu %r1,-(288+128)(%r1) \n"\ + " std %r3, 32(%r1) \n"\ + " std %r4, 40(%r1) \n"\ + " std %r5, 48(%r1) \n"\ + " std %r6, 56(%r1) \n"\ + " std %r7, 64(%r1) \n"\ + " std %r8, 72(%r1) \n"\ + " std %r9, 80(%r1) \n"\ + " std %r10,88(%r1) \n"\ + " std %r11,96(%r1) \n"\ + " mr %r4, %r0 \n"\ + " mr %r3, %r11 \n"\ + " bl __mcount \n"\ + " nop \n"\ + " ld %r3, 32(%r1) \n"\ + " ld %r4, 40(%r1) \n"\ + " ld %r5, 48(%r1) \n"\ + " ld %r6, 56(%r1) \n"\ + " ld %r7, 64(%r1) \n"\ + " ld %r8, 72(%r1) \n"\ + " ld %r9, 80(%r1) \n"\ + " ld %r10,88(%r1) \n"\ + " ld %r11,96(%r1) \n"\ + " addi %r1, %r1, (288+128) \n"\ + " ld %r0, 16(%r1) \n"\ + " std %r11,16(%r1) \n"\ + " mtlr %r0 \n"\ + " blr \n"\ + " .size _mcount, .-_mcount \n"\ + ); +#define _MCOUNT_DECL static void __mcount \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/psl.h b/lib/libc/include/powerpc64-openbsd-none/machine/psl.h new file mode 100644 index 000000000000..13f2e488a542 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/psl.h @@ -0,0 +1,88 @@ +/* $OpenBSD: psl.h,v 1.3 2021/01/09 13:14:02 kettenis Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + * + * $NetBSD: psl.h,v 1.5 2000/11/19 19:52:37 matt Exp $ + */ + +#ifndef _MACHINE_PSL_H_ +#define _MACHINE_PSL_H_ + +/* + * Machine State Register (MSR) - All cores + */ +#define PSL_VEC 0x02000000UL /* AltiVec/SPE vector unit available */ +#define PSL_VSX 0x00800000UL /* Vector-Scalar unit available */ +#define PSL_EE 0x00008000UL /* external interrupt enable */ +#define PSL_PR 0x00004000UL /* privilege mode (1 == user) */ +#define PSL_FP 0x00002000UL /* floating point enable */ +#define PSL_ME 0x00001000UL /* machine check enable */ +#define PSL_FE0 0x00000800UL /* floating point interrupt mode 0 */ +#define PSL_FE1 0x00000100UL /* floating point interrupt mode 1 */ +#define PSL_PMM 0x00000004UL /* performance monitor mark */ +#define PSL_RI 0x00000002UL /* recoverable interrupt */ + +#define PSL_GS 0x10000000UL /* Guest state */ +#define PSL_UCLE 0x04000000UL /* User mode cache lock enable */ +#define PSL_WE 0x00040000UL /* Wait state enable */ +#define PSL_CE 0x00020000UL /* Critical interrupt enable */ +#define PSL_UBLE 0x00000400UL /* BTB lock enable - e500 only */ +#define PSL_DWE 0x00000400UL /* Debug Wait Enable - 440 only*/ +#define PSL_DE 0x00000200UL /* Debug interrupt enable */ +#define PSL_IS 0x00000020UL /* Instruction address space */ +#define PSL_DS 0x00000010UL /* Data address space */ + +#define PSL_SF 0x8000000000000000UL /* 64-bit addressing */ +#define PSL_HV 0x1000000000000000UL /* hyper-privileged mode */ + +#define PSL_POW 0x00040000UL /* power management */ +#define PSL_ILE 0x00010000UL /* interrupt endian mode (1 == le) */ +#define PSL_SE 0x00000400UL /* single-step trace enable */ +#define PSL_BE 0x00000200UL /* branch trace enable */ +#define PSL_IP 0x00000040UL /* interrupt prefix - 601 only */ +#define PSL_IR 0x00000020UL /* instruction address relocation */ +#define PSL_DR 0x00000010UL /* data address relocation */ +#define PSL_LE 0x00000001UL /* endian mode (1 == le) */ + +/* + * Floating-point exception modes: + */ +#define PSL_FE_DIS 0 /* none */ +#define PSL_FE_NONREC PSL_FE1 /* imprecise non-recoverable */ +#define PSL_FE_REC PSL_FE0 /* imprecise recoverable */ +#define PSL_FE_PREC (PSL_FE0 | PSL_FE1) /* precise */ +#define PSL_FE_DFLT PSL_FE_DIS /* default == none */ + +#define PSL_FPU (PSL_FP | PSL_FE_PREC) + +#endif /* _MACHINE_PSL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/pte.h b/lib/libc/include/powerpc64-openbsd-none/machine/pte.h new file mode 100644 index 000000000000..b3e199c63501 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/pte.h @@ -0,0 +1,80 @@ +/* $OpenBSD: pte.h,v 1.8 2023/01/25 09:53:53 kettenis Exp $ */ + +/* + * Copyright (c) 2020 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_PTE_H_ +#define _MACHINE_PTE_H_ + +/* + * Page Table Entry bits that should work for all 64-bit POWER CPUs as + * well as the PowerPC 970. + */ + +struct pte { + uint64_t pte_hi; + uint64_t pte_lo; +}; + +/* High doubleword: */ +#define PTE_VALID 0x0000000000000001ULL +#define PTE_HID 0x0000000000000002ULL +#define PTE_WIRED 0x0000000000000008ULL /* SW */ +#define PTE_AVPN 0x3fffffffffffff80ULL +#define PTE_VSID_SHIFT 12 + +/* Low doubleword: */ +#define PTE_PP 0x0000000000000003ULL +#define PTE_RO 0x0000000000000003ULL +#define PTE_RW 0x0000000000000002ULL +#define PTE_N 0x0000000000000004ULL +#define PTE_G 0x0000000000000008ULL +#define PTE_M 0x0000000000000010ULL +#define PTE_I 0x0000000000000020ULL +#define PTE_W 0x0000000000000040ULL +#define PTE_CHG 0x0000000000000080ULL +#define PTE_REF 0x0000000000000100ULL +#define PTE_AC 0x0000000000000200ULL +#define PTE_RPGN 0x0ffffffffffff000ULL + +#define ADDR_PIDX 0x000000000ffff000ULL +#define ADDR_PIDX_SHIFT 12 +#define ADDR_ESID_SHIFT 28 +#define ADDR_VSID_SHIFT 28 + +struct pate { + uint64_t pate_htab; + uint64_t pate_prt; +}; + +#define SLBE_ESID_SHIFT 28 +#define SLBE_VALID 0x0000000008000000UL + +#define SLBV_VSID_SHIFT 12 + +struct slb { + uint64_t slb_slbe; + uint64_t slb_slbv; +}; + +#define VSID_VRMA 0x1ffffff + +#define USER_ADDR 0xcfffffff00000000ULL +#define USER_ESID (USER_ADDR >> ADDR_ESID_SHIFT) +#define SEGMENT_SIZE (256 * 1024 * 1024ULL) +#define SEGMENT_MASK (SEGMENT_SIZE - 1) + +#endif /* _MACHINE_PTE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/ptrace.h b/lib/libc/include/powerpc64-openbsd-none/machine/ptrace.h new file mode 100644 index 000000000000..b77303a8fa1b --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/ptrace.h @@ -0,0 +1,44 @@ +/* $OpenBSD: ptrace.h,v 1.1 2020/05/16 17:11:14 kettenis Exp $ */ + +/* + * Copyright (c) 1993 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _POWERPC_PTRACE_H_ +#define _POWERPC_PTRACE_H_ + +/* + * powerpc64-dependent ptrace definitions + */ +#define PT_STEP (PT_FIRSTMACH + 0) +#define PT_GETREGS (PT_FIRSTMACH + 1) +#define PT_SETREGS (PT_FIRSTMACH + 2) +#define PT_GETFPREGS (PT_FIRSTMACH + 3) +#define PT_SETFPREGS (PT_FIRSTMACH + 4) + +#endif /* !_POWERPC_PTRACE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/reg.h b/lib/libc/include/powerpc64-openbsd-none/machine/reg.h new file mode 100644 index 000000000000..037633d10aef --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/reg.h @@ -0,0 +1,39 @@ +/* $OpenBSD: reg.h,v 1.3 2020/07/14 09:41:30 kettenis Exp $ */ + +/* + * Copyright (c) 2020 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_REG_H_ +#define _MACHINE_REG_H_ + +struct reg { + uint64_t r_reg[32]; + uint64_t r_lr; + uint64_t r_cr; + uint64_t r_xer; + uint64_t r_ctr; + uint64_t r_pc; + uint64_t r_ps; +}; + +struct fpreg { + __uint128_t fp_vsx[64]; + uint64_t fp_fpscr; + uint64_t fp_vscr; + uint64_t fp_vrsave; +}; + +#endif /* !_MACHINE_REG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/reloc.h b/lib/libc/include/powerpc64-openbsd-none/machine/reloc.h new file mode 100644 index 000000000000..f233ce24dc3b --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/reloc.h @@ -0,0 +1,148 @@ +/* $OpenBSD: reloc.h,v 1.2 2020/07/18 16:41:43 kettenis Exp $ */ + +/* + * Copyright (c) 2020 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_RELOC_H_ +#define _MACHINE_RELOC_H_ + +#define R_PPC64_NONE 0 +#define R_PPC64_ADDR32 1 +#define R_PPC64_ADDR24 2 +#define R_PPC64_ADDR16 3 +#define R_PPC64_ADDR16_LO 4 +#define R_PPC64_ADDR16_HI 5 +#define R_PPC64_ADDR16_HA 6 +#define R_PPC64_ADDR14 7 + +#define R_PPC64_REL24 10 +#define R_PPC64_REL14 11 + +#define R_PPC64_GOT16 14 +#define R_PPC64_GOT16_LO 15 +#define R_PPC64_GOT16_HI 16 +#define R_PPC64_GOT16_HA 17 + +#define R_PPC64_COPY 19 +#define R_PPC64_GLOB_DAT 20 +#define R_PPC64_JMP_SLOT 21 +#define R_PPC64_RELATIVE 22 + +#define R_PPC64_UADDR32 24 +#define R_PPC64_UADDR16 25 +#define R_PPC64_REL32 26 +#define R_PPC64_PLT32 27 +#define R_PPC64_PLTREL32 28 +#define R_PPC64_PLT16_LO 29 +#define R_PPC64_PLT16_HI 30 +#define R_PPC64_PLT16_HA 31 + +#define R_PPC64_SECTOFF 33 +#define R_PPC64_SECTOFF_LO 34 +#define R_PPC64_SECTOFF_HI 35 +#define R_PPC64_SECTOFF_HA 36 +#define R_PPC64_REL30 37 +#define R_PPC64_ADDR64 38 +#define R_PPC64_ADDR16_HIGHER 39 +#define R_PPC64_ADDR16_HIGHERA 40 +#define R_PPC64_ADDR16_HIGHEST 41 +#define R_PPC64_ADDR16_HIGHESTA 42 +#define R_PPC64_UADDR64 43 +#define R_PPC64_REL64 44 +#define R_PPC64_PLT64 45 +#define R_PPC64_PLTREL64 46 +#define R_PPC64_TOC16 47 +#define R_PPC64_TOC16_LO 48 +#define R_PPC64_TOC16_HI 49 +#define R_PPC64_TOC16_HA 50 +#define R_PPC64_TOC 51 +#define R_PPC64_PLTGOT16 52 +#define R_PPC64_PLTGOT16_LO 53 +#define R_PPC64_PLTGOT16_HI 54 +#define R_PPC64_PLTGOT16_HA 55 +#define R_PPC64_ADDR16_DS 56 +#define R_PPC64_ADDR16_LO_DS 57 +#define R_PPC64_GOT16_DS 58 +#define R_PPC64_GOT16_LO_DS 59 +#define R_PPC64_PLT16_LO_DS 60 +#define R_PPC64_SECTOFF_DS 61 +#define R_PPC64_SECTOFF_LO_DS 62 +#define R_PPC64_TOC16_DS 63 +#define R_PPC64_TOC16_LO_DS 64 +#define R_PPC64_PLTGOT16_DS 65 +#define R_PPC64_PLTGOT16_LO_DS 66 +#define R_PPC64_TLS 67 +#define R_PPC64_DTPMOD64 68 +#define R_PPC64_TPREL16 69 +#define R_PPC64_TPREL16_LO 70 +#define R_PPC64_TPREL16_HI 71 +#define R_PPC64_TPREL16_HA 72 +#define R_PPC64_TPREL64 73 +#define R_PPC64_DTPREL16 74 +#define R_PPC64_DTPREL16_LO 75 +#define R_PPC64_DTPREL16_HI 76 +#define R_PPC64_DTPREL16_HA 77 +#define R_PPC64_DTPREL64 78 +#define R_PPC64_GOT_TLSGD16 79 +#define R_PPC64_GOT_TLSGD16_LO 80 +#define R_PPC64_GOT_TLSGD16_HI 81 +#define R_PPC64_GOT_TLSGD16_HA 82 +#define R_PPC64_GOT_TLSD16 83 +#define R_PPC64_GOT_TLSD16_LO 84 +#define R_PPC64_GOT_TLSD16_HI 85 +#define R_PPC64_GOT_TLSD16_HA 86 +#define R_PPC64_GOT_TPREL16_DS 87 +#define R_PPC64_GOT_TPREL16_LO_DS 88 +#define R_PPC64_GOT_TPREL16_HI 89 +#define R_PPC64_GOT_TPREL16_HA 90 +#define R_PPC64_GOT_DTPREL16_DS 91 +#define R_PPC64_GOT_DTPREL16_LO_DS 92 +#define R_PPC64_GOT_DTPREL16_HI 93 +#define R_PPC64_GOT_DTPREL16_HA 94 +#define R_PPC64_TPREL16_DS 95 +#define R_PPC64_TPREL16_LO_DS 96 +#define R_PPC64_TPREL16_HIGHER 97 +#define R_PPC64_TPREL16_HIGHERA 98 +#define R_PPC64_TPREL16_HIGHEST 99 +#define R_PPC64_TPREL16_HIGHESTA 100 +#define R_PPC64_DTPREL16_DS 101 +#define R_PPC64_DTPREL16_LO_DS 102 +#define R_PPC64_DTPREL16_HIGHER 103 +#define R_PPC64_DTPREL16_HIGHERA 104 +#define R_PPC64_DTPREL16_HIGHEST 105 +#define R_PPC64_DTPREL16_HIGHESTA 106 +#define R_PPC64_TLSGD 107 +#define R_PPC64_TLSLD 108 +#define R_PPC64_TOCSAVE 109 +#define R_PPC64_ADDR16_HIGH 110 +#define R_PPC64_ADDR16_HIGHA 111 +#define R_PPC64_TPREL16_HIGH 112 +#define R_PPC64_TPREL16_HIGHA 113 +#define R_PPC64_DTPREL16_HIGH 114 +#define R_PPC64_DTPREL16_HIGHA 115 +#define R_PPC64_REL24_NOTOC 116 +#define R_PPC64_ADDR64_LOCAL 117 +#define R_PPC64_ENTRY 118 + +#define R_PPC64_IRELATIVE 248 +#define R_PPC64_REL16 249 +#define R_PPC64_REL16_LO 250 +#define R_PPC64_REL16_HI 251 +#define R_PPC64_REL16_HA 252 +#define R_PPC64_GNU_VTINHERIT 253 +#define R_PPC64_GNU_VTENTRY 254 + +#endif /* _MACHINE_RELOC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/setjmp.h b/lib/libc/include/powerpc64-openbsd-none/machine/setjmp.h new file mode 100644 index 000000000000..02b53f759f42 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/setjmp.h @@ -0,0 +1,4 @@ +/* $OpenBSD: setjmp.h,v 1.1 2020/06/25 05:01:16 drahn Exp $ */ +/* $NetBSD: setjmp.h,v 1.1 1996/09/30 16:34:34 ws Exp $ */ + +#define _JBLEN 208 \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/signal.h b/lib/libc/include/powerpc64-openbsd-none/machine/signal.h new file mode 100644 index 000000000000..68710820a2be --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/signal.h @@ -0,0 +1,65 @@ +/* $OpenBSD: signal.h,v 1.5 2020/07/13 22:37:37 kettenis Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 _MACHDEP_SIGNAL_H_ +#define _MACHDEP_SIGNAL_H_ + +#include + +typedef int sig_atomic_t; + +#if __BSD_VISIBLE || __XPG_VISIBLE >= 420 + +#include + +struct sigcontext { + long sc_cookie; + int sc_mask; /* saved signal mask */ + __register_t sc_reg[32]; /* saved registers */ + __register_t sc_lr; + __register_t sc_cr; + __register_t sc_xer; + __register_t sc_ctr; + __register_t sc_pc; + __register_t sc_ps; + __register_t sc_vrsave; + __uint128_t sc_vsx[64]; + __uint64_t sc_fpscr; + __uint64_t sc_vscr; +}; + +#define sc_sp sc_reg[1] + +#endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ + +#endif /* _MACHDEP_SIGNAL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/smbiosvar.h b/lib/libc/include/powerpc64-openbsd-none/machine/smbiosvar.h new file mode 100644 index 000000000000..60200682ad10 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/smbiosvar.h @@ -0,0 +1,278 @@ +/* $OpenBSD: smbiosvar.h,v 1.3 2025/07/15 01:09:32 jsg Exp $ */ +/* + * Copyright (c) 2006 Gordon Willem Klok + * Copyright (c) 2005 Jordan Hargrave + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_SMBIOSVAR_ +#define _MACHINE_SMBIOSVAR_ + +#define SMBIOS_UUID_NPRESENT 0x1 +#define SMBIOS_UUID_NSET 0x2 + +/* + * Section 3.5 of "UUIDs and GUIDs" found at + * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt + * specifies the string representation of a UUID. + */ +#define SMBIOS_UUID_REP "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" +#define SMBIOS_UUID_REPLEN 37 /* 16 zero padded values, 4 hyphens, 1 null */ + +struct smbios_entry { + uint8_t mjr; + uint8_t min; + uint8_t *addr; + uint16_t len; + uint16_t count; +}; + +struct smbhdr { + uint32_t sig; /* "_SM_" */ + uint8_t checksum; /* Entry point checksum */ + uint8_t len; /* Entry point structure length */ + uint8_t majrev; /* Specification major revision */ + uint8_t minrev; /* Specification minor revision */ + uint16_t mss; /* Maximum Structure Size */ + uint8_t epr; /* Entry Point Revision */ + uint8_t fa[5]; /* value determined by EPR */ + uint8_t sasig[5]; /* Secondary Anchor "_DMI_" */ + uint8_t sachecksum; /* Secondary Checksum */ + uint16_t size; /* Length of structure table in bytes */ + uint32_t addr; /* Structure table address */ + uint16_t count; /* Number of SMBIOS structures */ + uint8_t rev; /* BCD revision */ +} __packed; + +struct smb3hdr { + uint8_t sig[5]; /* "_SM3_" */ + uint8_t checksum; /* Entry point structure checksum */ + uint8_t len; /* Entry point length */ + uint8_t majrev; /* SMBIOS major version */ + uint8_t minrev; /* SMBIOS minor version */ + uint8_t docrev; /* SMBIOS docrev */ + uint8_t epr; /* Entry point revision */ + uint8_t reserved; /* Reserved */ + uint32_t size; /* Structure table maximum size */ + uint64_t addr; /* Structure table address */ +} __packed; + +struct smbtblhdr { + uint8_t type; + uint8_t size; + uint16_t handle; +} __packed; + +struct smbtable { + struct smbtblhdr *hdr; + void *tblhdr; + uint32_t cookie; +}; + +#define SMBIOS_TYPE_BIOS 0 +#define SMBIOS_TYPE_SYSTEM 1 +#define SMBIOS_TYPE_BASEBOARD 2 +#define SMBIOS_TYPE_ENCLOSURE 3 +#define SMBIOS_TYPE_PROCESSOR 4 +#define SMBIOS_TYPE_MEMCTRL 5 +#define SMBIOS_TYPE_MEMMOD 6 +#define SMBIOS_TYPE_CACHE 7 +#define SMBIOS_TYPE_PORT 8 +#define SMBIOS_TYPE_SLOTS 9 +#define SMBIOS_TYPE_OBD 10 +#define SMBIOS_TYPE_OEM 11 +#define SMBIOS_TYPE_SYSCONFOPT 12 +#define SMBIOS_TYPE_BIOSLANG 13 +#define SMBIOS_TYPE_GROUPASSOC 14 +#define SMBIOS_TYPE_SYSEVENTLOG 15 +#define SMBIOS_TYPE_PHYMEM 16 +#define SMBIOS_TYPE_MEMDEV 17 +#define SMBIOS_TYPE_ECCINFO32 18 +#define SMBIOS_TYPE_MEMMAPARRAYADDR 19 +#define SMBIOS_TYPE_MEMMAPDEVADDR 20 +#define SMBIOS_TYPE_INBUILTPOINT 21 +#define SMBIOS_TYPE_PORTBATT 22 +#define SMBIOS_TYPE_SYSRESET 23 +#define SMBIOS_TYPE_HWSECUIRTY 24 +#define SMBIOS_TYPE_PWRCTRL 25 +#define SMBIOS_TYPE_VOLTPROBE 26 +#define SMBIOS_TYPE_COOLING 27 +#define SMBIOS_TYPE_TEMPPROBE 28 +#define SMBIOS_TYPE_CURRENTPROBE 29 +#define SMBIOS_TYPE_OOB_REMOTEACCESS 30 +#define SMBIOS_TYPE_BIS 31 +#define SMBIOS_TYPE_SBI 32 +#define SMBIOS_TYPE_ECCINFO64 33 +#define SMBIOS_TYPE_MGMTDEV 34 +#define SMBIOS_TYPE_MGTDEVCOMP 35 +#define SMBIOS_TYPE_MGTDEVTHRESH 36 +#define SMBIOS_TYPE_MEMCHANNEL 37 +#define SMBIOS_TYPE_IPMIDEV 38 +#define SMBIOS_TYPE_SPS 39 +#define SMBIOS_TYPE_INACTIVE 126 +#define SMBIOS_TYPE_EOT 127 + +/* + * SMBIOS Structure Type 0 "BIOS Information" + * DMTF Specification DSP0134 Section: 3.3.1 p.g. 34 + */ +struct smbios_struct_bios { + uint8_t vendor; /* string */ + uint8_t version; /* string */ + uint16_t startaddr; + uint8_t release; /* string */ + uint8_t romsize; + uint64_t characteristics; + uint32_t charext; + uint8_t major_rel; + uint8_t minor_rel; + uint8_t ecf_mjr_rel; /* embedded controller firmware */ + uint8_t ecf_min_rel; /* embedded controller firmware */ +} __packed; + +/* + * SMBIOS Structure Type 1 "System Information" + * DMTF Specification DSP0134 Section 3.3.2 p.g. 35 + */ + +struct smbios_sys { +/* SMBIOS spec 2.0+ */ + uint8_t vendor; /* string */ + uint8_t product; /* string */ + uint8_t version; /* string */ + uint8_t serial; /* string */ +/* SMBIOS spec 2.1+ */ + uint8_t uuid[16]; + uint8_t wakeup; +/* SMBIOS spec 2.4+ */ + uint8_t sku; /* string */ + uint8_t family; /* string */ +} __packed; + +/* + * SMBIOS Structure Type 2 "Base Board (Module) Information" + * DMTF Specification DSP0134 Section 3.3.3 p.g. 37 + */ +struct smbios_board { + uint8_t vendor; /* string */ + uint8_t product; /* string */ + uint8_t version; /* string */ + uint8_t serial; /* string */ + uint8_t asset; /* string */ + uint8_t feature; /* feature flags */ + uint8_t location; /* location in chassis */ + uint16_t handle; /* chassis handle */ + uint8_t type; /* board type */ + uint8_t noc; /* number of contained objects */ +} __packed; + +/* + * SMBIOS Structure Type 3 "System Enclosure or Chassis" + * DMTF Specification DSP0134 + */ +struct smbios_enclosure { + /* SMBIOS spec 2.0+ */ + uint8_t vendor; /* string */ + uint8_t type; + uint8_t version; /* string */ + uint8_t serial; /* string */ + uint8_t asset_tag; /* string */ + /* SMBIOS spec 2.1+ */ + uint8_t boot_state; + uint8_t psu_state; + uint8_t thermal_state; + uint8_t security_status; + /* SMBIOS spec 2.3+ */ + uint16_t oem_defined; + uint8_t height; + uint8_t no_power_cords; + uint8_t no_contained_element; + uint8_t reclen_contained_element; + uint8_t contained_elements; + /* SMBIOS spec 2.7+ */ + uint8_t sku; /* string */ +} __packed; + +/* + * SMBIOS Structure Type 4 "processor Information" + * DMTF Specification DSP0134 v2.5 Section 3.3.5 p.g. 24 + */ +struct smbios_cpu { + uint8_t cpu_socket_designation; /* string */ + uint8_t cpu_type; + uint8_t cpu_family; + uint8_t cpu_mfg; /* string */ + uint32_t cpu_id_eax; + uint32_t cpu_id_edx; + uint8_t cpu_version; /* string */ + uint8_t cpu_voltage; + uint16_t cpu_clock; + uint16_t cpu_max_speed; + uint16_t cpu_current_speed; + uint8_t cpu_status; +#define SMBIOS_CPUST_POPULATED (1<<6) +#define SMBIOS_CPUST_STATUSMASK (0x07) + uint8_t cpu_upgrade; + uint16_t cpu_l1_handle; + uint16_t cpu_l2_handle; + uint16_t cpu_l3_handle; + uint8_t cpu_serial; /* string */ + uint8_t cpu_asset_tag; /* string */ + uint8_t cpu_part_nr; /* string */ + /* following fields were added in smbios 2.5 */ + uint8_t cpu_core_count; + uint8_t cpu_core_enabled; + uint8_t cpu_thread_count; + uint16_t cpu_characteristics; +} __packed; + +/* + * SMBIOS Structure Type 38 "IPMI Information" + * DMTF Specification DSP0134 Section 3.3.39 p.g. 91 + */ +struct smbios_ipmi { + uint8_t smipmi_if_type; /* IPMI Interface Type */ + uint8_t smipmi_if_rev; /* BCD IPMI Revision */ + uint8_t smipmi_i2c_address; /* I2C address of BMC */ + uint8_t smipmi_nvram_address; /* I2C address of NVRAM + * storage */ + uint64_t smipmi_base_address; /* Base address of BMC (BAR + * format */ + uint8_t smipmi_base_flags; /* Flags field: + * bit 7:6 : register spacing + * 00 = byte + * 01 = dword + * 02 = word + * bit 4 : Lower bit BAR + * bit 3 : IRQ valid + * bit 2 : N/A + * bit 1 : Interrupt polarity + * bit 0 : Interrupt trigger */ + uint8_t smipmi_irq; /* IRQ if applicable */ +} __packed; + +int smbios_find_table(uint8_t, struct smbtable *); +char *smbios_get_string(struct smbtable *, uint8_t, char *, size_t); + +#endif \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/spinlock.h b/lib/libc/include/powerpc64-openbsd-none/machine/spinlock.h new file mode 100644 index 000000000000..98555de9676f --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/spinlock.h @@ -0,0 +1,26 @@ +/* $OpenBSD: spinlock.h,v 1.1 2020/05/16 17:11:14 kettenis Exp $ */ + +/* + * Copyright (c) 2014 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_SPINLOCK_H_ +#define _MACHINE_SPINLOCK_H_ + +#define _ATOMIC_LOCK_UNLOCKED (0) +#define _ATOMIC_LOCK_LOCKED (1) +typedef int _atomic_lock_t; + +#endif \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/tcb.h b/lib/libc/include/powerpc64-openbsd-none/machine/tcb.h new file mode 100644 index 000000000000..879efa9de8ec --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/tcb.h @@ -0,0 +1,42 @@ +/* $OpenBSD: tcb.h,v 1.4 2020/07/14 16:48:13 kettenis Exp $ */ + +/* + * Copyright (c) 2011 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TCB_H_ +#define _MACHINE_TCB_H_ + +#ifdef _KERNEL + +#define TCB_GET(p) \ + ((void *)(p)->p_md.md_regs->fixreg[13]) +#define TCB_SET(p, addr) \ + ((p)->p_md.md_regs->fixreg[13] = (__register_t)(addr)) + +#else /* _KERNEL */ + +/* ELF TLS ABI calls for small TCB, with static TLS data after it */ +#define TLS_VARIANT 1 + +/* powerpc offsets the TCB pointer 0x7000 bytes after the data */ +#define TCB_OFFSET 0x7008 + +register void *__tcb __asm__ ("r13"); +#define TCB_GET() (__tcb) +#define TCB_SET(tcb) ((__tcb) = (tcb)) + +#endif /* _KERNEL */ +#endif /* _MACHINE_TCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/timetc.h b/lib/libc/include/powerpc64-openbsd-none/machine/timetc.h new file mode 100644 index 000000000000..9c07a63a5247 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/timetc.h @@ -0,0 +1,23 @@ +/* $OpenBSD: timetc.h,v 1.2 2022/11/05 16:23:02 cheloha Exp $ */ +/* + * Copyright (c) 2020 Paul Irofti + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TIMETC_H_ +#define _MACHINE_TIMETC_H_ + +#define TC_TB 1 + +#endif /* _MACHINE_TIMETC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/trap.h b/lib/libc/include/powerpc64-openbsd-none/machine/trap.h new file mode 100644 index 000000000000..7e1ef37d2998 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/trap.h @@ -0,0 +1,158 @@ +/* $OpenBSD: trap.h,v 1.9 2022/05/19 05:43:48 miod Exp $ */ +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + * + * $NetBSD: trap.h,v 1.7 2002/02/22 13:51:40 kleink Exp $ + */ + +#ifndef _MACHINE_TRAP_H_ +#define _MACHINE_TRAP_H_ + +#define EXC_RSVD 0x0000 /* Reserved */ +#define EXC_RST 0x0100 /* Reset; all but IBM4xx */ +#define EXC_MCHK 0x0200 /* Machine Check */ +#define EXC_DSI 0x0300 /* Data Storage Interrupt */ +#define EXC_DSE 0x0380 /* Data Segment Interrupt */ +#define EXC_ISI 0x0400 /* Instruction Storage Interrupt */ +#define EXC_ISE 0x0480 /* Instruction Segment Interrupt */ +#define EXC_EXI 0x0500 /* External Interrupt */ +#define EXC_ALI 0x0600 /* Alignment Interrupt */ +#define EXC_PGM 0x0700 /* Program Interrupt */ +#define EXC_FPU 0x0800 /* Floating-point Unavailable */ +#define EXC_DECR 0x0900 /* Decrementer Interrupt */ +#define EXC_SC 0x0c00 /* System Call */ +#define EXC_TRC 0x0d00 /* Trace */ +#define EXC_FPA 0x0e00 /* Floating-point Assist */ + +/* The following is only available on the 601: */ +#define EXC_RUNMODETRC 0x2000 /* Run Mode/Trace Exception */ + +/* The following are only available on 970(G5): */ +#define EXC_VECAST_G5 0x1700 /* AltiVec Assist */ + +/* The following are only available on 7400(G4): */ +#define EXC_VEC 0x0f20 /* AltiVec Unavailable */ +#define EXC_VECAST_G4 0x1600 /* AltiVec Assist */ + +/* The following are only available on 604/750/7400: */ +#define EXC_PERF 0x0f00 /* Performance Monitoring */ +#define EXC_BPT 0x1300 /* Instruction Breakpoint */ +#define EXC_SMI 0x1400 /* System Management Interrupt */ + +/* The following are only available on 750/7400: */ +#define EXC_THRM 0x1700 /* Thermal Management Interrupt */ + +/* And these are only on the 603: */ +#define EXC_IMISS 0x1000 /* Instruction translation miss */ +#define EXC_DLMISS 0x1100 /* Data load translation miss */ +#define EXC_DSMISS 0x1200 /* Data store translation miss */ + +/* Power ISA 2.06+: */ +#define EXC_HDSI 0x0e00 /* Hypervisor Data Storage */ +#define EXC_HISI 0x0e20 /* Hypervisor Instruction Storage */ +#define EXC_HEA 0x0e40 /* Hypervisor Emulation Assistance */ +#define EXC_HMI 0x0e60 /* Hypervisor Maintenance */ +#define EXC_VSX 0x0f40 /* VSX Unavailable */ + +/* Power ISA 2.07+: */ +#define EXC_FAC 0x0f60 /* Facility Unavailable */ +#define EXC_HFAC 0x0f80 /* Hypervisor Facility Unavailable */ + +/* Power ISA 3.0+: */ +#define EXC_HVI 0x0ea0 /* Hypervisor Virtualization */ + +/* The following are available on 4xx and 85xx */ +#define EXC_CRIT 0x0100 /* Critical Input Interrupt */ +#define EXC_PIT 0x1000 /* Programmable Interval Timer */ +#define EXC_FIT 0x1010 /* Fixed Interval Timer */ +#define EXC_WDOG 0x1020 /* Watchdog Timer */ +#define EXC_DTMISS 0x1100 /* Data TLB Miss */ +#define EXC_ITMISS 0x1200 /* Instruction TLB Miss */ +#define EXC_APU 0x1300 /* Auxiliary Processing Unit */ +#define EXC_DEBUG 0x2f10 /* Debug trap */ +#define EXC_VECAST_E 0x2f20 /* Altivec Assist (Book-E) */ +#define EXC_SPFPD 0x2f30 /* SPE Floating-point Data */ +#define EXC_SPFPR 0x2f40 /* SPE Floating-point Round */ + +/* POWER8 */ +#define EXC_SOFT_PATCH 0x1500 /* POWER8 Soft Patch Exception */ + +#define EXC_END 0x3000 /* End of exception vectors */ + +#define EXC_AST 0x3000 /* Fake AST vector */ + +/* Trap was in user mode */ +#define EXC_USER 0x10000 + + +/* + * EXC_ALI sets bits in the DSISR and DAR to provide enough + * information to recover from the unaligned access without needing to + * parse the offending instruction. This includes certain bits of the + * opcode, and information about what registers are used. The opcode + * indicator values below come from Appendix F of Book III of "The + * PowerPC Architecture". + */ + +#define EXC_ALI_OPCODE_INDICATOR(dsisr) ((dsisr >> 10) & 0x7f) +#define EXC_ALI_LFD 0x09 +#define EXC_ALI_STFD 0x0b + +/* Macros to extract register information */ +#define EXC_ALI_RST(dsisr) ((dsisr >> 5) & 0x1f) /* source or target */ +#define EXC_ALI_RA(dsisr) (dsisr & 0x1f) +#define EXC_ALI_INST_RST(instr) ((instr >> 21) & 0x1f) + +/* + * SRR1 bits for program exception traps. These identify what caused + * the program exception. See section 6.5.9 of the Power ISA Version + * 2.05. + */ + +#define EXC_PGM_FPENABLED (1UL << 20) +#define EXC_PGM_ILLEGAL (1UL << 19) +#define EXC_PGM_PRIV (1UL << 18) +#define EXC_PGM_TRAP (1UL << 17) + +/* + * DSISR bits. + */ + +#define DSISR_STORE (1UL << 25) + +/* Magic pointers to store trap handler entry points */ +#define TRAP_ENTRY 0x1f8 +#define TRAP_HVENTRY 0x1f0 +#define TRAP_SLBENTRY 0x1e8 +#define TRAP_RSTENTRY 0x1e0 + +#endif /* _MACHINE_TRAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/machine/vmparam.h b/lib/libc/include/powerpc64-openbsd-none/machine/vmparam.h new file mode 100644 index 000000000000..4cad35a1a2ef --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/machine/vmparam.h @@ -0,0 +1,53 @@ +/* + * Machine dependent constants for powerpc64. + */ + +#define USRSTACK VM_MAXUSER_ADDRESS + +/* + * Virtual memory related constants, all in bytes + */ +#define MAXTSIZ ((paddr_t)256*1024*1024) /* max text size */ +#ifndef DFLDSIZ +#define DFLDSIZ ((paddr_t)512*1024*1024) /* initial data size limit */ +#endif +#ifndef MAXDSIZ +#define MAXDSIZ ((paddr_t)32*1024*1024*1024) /* max data size */ +#endif +#ifndef BRKSIZ +#define BRKSIZ ((paddr_t)16*1024*1024*1024) /* heap gap size */ +#endif +#ifndef DFLSSIZ +#define DFLSSIZ ((paddr_t)2*1024*1024) /* initial stack size limit */ +#endif +#ifndef MAXSSIZ +#define MAXSSIZ ((paddr_t)32*1024*1024) /* max stack size */ +#endif + +#define STACKGAP_RANDOM 256*1024 + +/* + * Size of shared memory map + */ +#ifndef SHMMAXPGS +#define SHMMAXPGS 1024 +#endif + +/* + * Size of User Raw I/O map + */ +#define USRIOSIZE 300 + +#define VM_PHYS_SIZE (USRIOSIZE * PAGE_SIZE) + +#define VM_PHYSSEG_MAX 32 +#define VM_PHYSSEG_STRAT VM_PSTRAT_BSEARCH + +#define VM_MIN_ADDRESS ((vaddr_t)PAGE_SIZE) +#define VM_MAXUSER_ADDRESS 0xbffffffffffff000UL +#define VM_MAX_ADDRESS 0xffffffffffffffffUL +#ifdef _KERNEL +#define VM_MIN_STACK_ADDRESS 0x9000000000000000UL +#endif +#define VM_MIN_KERNEL_ADDRESS 0xc000000000000000UL +#define VM_MAX_KERNEL_ADDRESS 0xc0000007ffffffffUL \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/_float.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/_float.h new file mode 100644 index 000000000000..14a56d926e32 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/_float.h @@ -0,0 +1,71 @@ +/* $OpenBSD: _float.h,v 1.1 2020/06/01 00:13:37 drahn Exp $ */ + +/* + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE__FLOAT_H_ +#define _MACHINE__FLOAT_H_ + +#define __FLT_RADIX 2 /* b */ +#define __FLT_ROUNDS __flt_rounds() +#define __FLT_EVAL_METHOD 0 /* no promotions */ + +#define __FLT_MANT_DIG 24 /* p */ +#define __FLT_EPSILON 1.19209290E-07F /* b**(1-p) */ +#define __FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ +#define __FLT_MIN_EXP (-125) /* emin */ +#define __FLT_MIN 1.17549435E-38F /* b**(emin-1) */ +#define __FLT_MIN_10_EXP (-37) /* ceil(log10(b**(emin-1))) */ +#define __FLT_MAX_EXP 128 /* emax */ +#define __FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ +#define __FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ + +#define __DBL_MANT_DIG 53 +#define __DBL_EPSILON 2.2204460492503131E-16 +#define __DBL_DIG 15 +#define __DBL_MIN_EXP (-1021) +#define __DBL_MIN 2.2250738585072014E-308 +#define __DBL_MIN_10_EXP (-307) +#define __DBL_MAX_EXP 1024 +#define __DBL_MAX 1.7976931348623157E+308 +#define __DBL_MAX_10_EXP 308 + +#define __LDBL_MANT_DIG DBL_MANT_DIG +#define __LDBL_EPSILON DBL_EPSILON +#define __LDBL_DIG DBL_DIG +#define __LDBL_MIN_EXP DBL_MIN_EXP +#define __LDBL_MIN DBL_MIN +#define __LDBL_MIN_10_EXP DBL_MIN_10_EXP +#define __LDBL_MAX_EXP DBL_MAX_EXP +#define __LDBL_MAX DBL_MAX +#define __LDBL_MAX_10_EXP DBL_MAX_10_EXP + +#define __DECIMAL_DIG 17 + +#endif /* _MACHINE__FLOAT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/_types.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/_types.h new file mode 100644 index 000000000000..c8b810163d81 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/_types.h @@ -0,0 +1,145 @@ +/* $OpenBSD: _types.h,v 1.4 2023/07/02 19:02:28 cheloha Exp $ */ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.3 (Berkeley) 1/5/94 + * @(#)ansi.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _MACHINE__TYPES_H_ +#define _MACHINE__TYPES_H_ + +#if defined(_KERNEL) +typedef struct label_t { + long val[22]; +} label_t; +#endif + +/* + * _ALIGN(p) rounds p (pointer or byte index) up to a correctly-aligned + * value for all data types (int, long, ...). The result is an + * unsigned long and must be cast to any desired pointer type. + * + * _ALIGNED_POINTER is a boolean macro that checks whether an address + * is valid to fetch data elements of type t from on this architecture. + * This does not reflect the optimal alignment, just the possibility + * (within reasonable limits). + */ +#define _ALIGNBYTES (sizeof(long) - 1) +#define _STACKALIGNBYTES 15 +#define _ALIGN(p) (((unsigned long)(p) + _ALIGNBYTES) & ~_ALIGNBYTES) +#define _ALIGNED_POINTER(p,t) ((((unsigned long)(p)) & (sizeof(t) - 1)) == 0) +#define _MAX_PAGE_SHIFT 12 /* same as PAGE_SHIFT */ + +/* 7.18.1.1 Exact-width integer types */ +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short __int16_t; +typedef unsigned short __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; +/* LONGLONG */ +typedef long long __int64_t; +/* LONGLONG */ +typedef unsigned long long __uint64_t; + +/* 7.18.1.2 Minimum-width integer types */ +typedef __int8_t __int_least8_t; +typedef __uint8_t __uint_least8_t; +typedef __int16_t __int_least16_t; +typedef __uint16_t __uint_least16_t; +typedef __int32_t __int_least32_t; +typedef __uint32_t __uint_least32_t; +typedef __int64_t __int_least64_t; +typedef __uint64_t __uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types */ +typedef __int32_t __int_fast8_t; +typedef __uint32_t __uint_fast8_t; +typedef __int32_t __int_fast16_t; +typedef __uint32_t __uint_fast16_t; +typedef __int32_t __int_fast32_t; +typedef __uint32_t __uint_fast32_t; +typedef __int64_t __int_fast64_t; +typedef __uint64_t __uint_fast64_t; +#define __INT_FAST8_MIN INT32_MIN +#define __INT_FAST16_MIN INT32_MIN +#define __INT_FAST32_MIN INT32_MIN +#define __INT_FAST64_MIN INT64_MIN +#define __INT_FAST8_MAX INT32_MAX +#define __INT_FAST16_MAX INT32_MAX +#define __INT_FAST32_MAX INT32_MAX +#define __INT_FAST64_MAX INT64_MAX +#define __UINT_FAST8_MAX UINT32_MAX +#define __UINT_FAST16_MAX UINT32_MAX +#define __UINT_FAST32_MAX UINT32_MAX +#define __UINT_FAST64_MAX UINT64_MAX + +/* 7.18.1.4 Integer types capable of holding object pointers */ +typedef long __intptr_t; +typedef unsigned long __uintptr_t; + +/* 7.18.1.5 Greatest-width integer types */ +typedef __int64_t __intmax_t; +typedef __uint64_t __uintmax_t; + +/* Register size */ +typedef long __register_t; + +/* VM system types */ +typedef unsigned long __vaddr_t; +typedef unsigned long __paddr_t; +typedef unsigned long __vsize_t; +typedef unsigned long __psize_t; + +/* Standard system types */ +typedef double __double_t; +typedef float __float_t; +typedef long __ptrdiff_t; +typedef unsigned long __size_t; +typedef long __ssize_t; +#if defined(__GNUC__) && __GNUC__ >= 3 +typedef __builtin_va_list __va_list; +#else +typedef char * __va_list; +#endif + +/* Wide character support types */ +#ifndef __cplusplus +#ifdef __WCHAR_UNSIGNED__ +typedef unsigned int __wchar_t; +#else +typedef int __wchar_t; +#endif +#endif +typedef int __wint_t; +typedef int __rune_t; +typedef void * __wctrans_t; +typedef void * __wctype_t; + +#endif /* _MACHINE__TYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/apmvar.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/apmvar.h new file mode 100644 index 000000000000..2c911df088a2 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/apmvar.h @@ -0,0 +1,122 @@ +/* $OpenBSD: apmvar.h,v 1.1 2020/07/15 22:46:51 deraadt Exp $ */ + +/* + * Copyright (c) 2001 Alexander Guy + * Copyright (c) 1995 John T. Kohl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _POWERPC64_APMVAR_H_ +#define _POWERPC64_APMVAR_H_ + +#include + +/* Advanced Power Management (v1.0 and v1.1 specification) + * functions/defines/etc. + */ + +/* These definitions make up the heart of the user-land interface + * to the APM devices. + */ + +#define APM_AC_OFF 0x00 +#define APM_AC_ON 0x01 +#define APM_AC_BACKUP 0x02 +#define APM_AC_UNKNOWN 0xff +#define APM_BATT_HIGH 0x00 +#define APM_BATT_LOW 0x01 +#define APM_BATT_CRITICAL 0x02 +#define APM_BATT_CHARGING 0x03 +#define APM_BATT_UNKNOWN 0xff +#define APM_BATT_LIFE_UNKNOWN 0xff + +#define APM_NOEVENT 0x0000 +#define APM_STANDBY_REQ 0x0001 +#define APM_SUSPEND_REQ 0x0002 +#define APM_NORMAL_RESUME 0x0003 +#define APM_CRIT_RESUME 0x0004 /* suspend/resume happened + without us */ +#define APM_BATTERY_LOW 0x0005 +#define APM_POWER_CHANGE 0x0006 +#define APM_UPDATE_TIME 0x0007 +#define APM_CRIT_SUSPEND_REQ 0x0008 +#define APM_USER_STANDBY_REQ 0x0009 +#define APM_USER_SUSPEND_REQ 0x000A +#define APM_SYS_STANDBY_RESUME 0x000B +#define APM_CAPABILITY_CHANGE 0x000C /* apm v1.2 */ +#define APM_USER_HIBERNATE_REQ 0x000D +#define APM_EVENT_MASK 0xffff + +#define APM_EVENT_COMPOSE(t,i) ((((i) & 0x7fff) << 16)|((t) & APM_EVENT_MASK)) +#define APM_EVENT_TYPE(e) ((e) & APM_EVENT_MASK) +#define APM_EVENT_INDEX(e) ((e) >> 16) + +/* + * LP (Laptop Package) + * + * Copyright (C) 1994 by HOSOKAWA Tatsumi + * + * This software may be used, modified, copied, and distributed, in + * both source and binary form provided that the above copyright and + * these terms are retained. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with its + * use. + * + * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) + */ + +#define APM_BATTERY_ABSENT 4 + +struct apm_power_info { + u_char battery_state; + u_char ac_state; + u_char battery_life; + u_char spare1; + u_int minutes_left; /* estimate */ + u_int spare2[6]; +}; + +struct apm_ctl { + u_int dev; + u_int mode; +}; + +#define APM_IOC_REJECT _IOW('A', 0, struct apm_event_info) /* reject request # */ +#define APM_IOC_STANDBY _IO('A', 1) /* put system into standby */ +#define APM_IOC_SUSPEND _IO('A', 2) /* put system into suspend */ +#define APM_IOC_GETPOWER _IOR('A', 3, struct apm_power_info) /* fetch battery state */ +#define APM_IOC_DEV_CTL _IOW('A', 5, struct apm_ctl) /* put device into mode */ +#define APM_IOC_PRN_CTL _IOW('A', 6, int ) /* driver power status msg */ +#define APM_PRINT_ON 0 /* driver power status displayed */ +#define APM_PRINT_OFF 1 /* driver power status not displayed */ +#define APM_PRINT_PCT 2 /* driver power status only displayed + if the percentage changes */ +#define APM_IOC_STANDBY_REQ _IO('A', 7) /* request standby */ +#define APM_IOC_SUSPEND_REQ _IO('A', 8) /* request suspend */ +#define APM_IOC_HIBERNATE _IO('A', 9) /* put system into hibernate */ + +#endif /* _POWERPC64_APMVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/asm.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/asm.h new file mode 100644 index 000000000000..b630e137aa8c --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/asm.h @@ -0,0 +1,100 @@ +/* $OpenBSD: asm.h,v 1.7 2022/12/07 23:25:59 guenther Exp $ */ + +/* + * Copyright (c) 2020 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _POWERPC64_ASM_H_ +#define _POWERPC64_ASM_H_ + +#define _C_LABEL(x) x +#define _ASM_LABEL(x) x + +#define _TMP_LABEL(x) .L_ ## x +#define _GEP_LABEL(x) .L_ ## x ## _gep0 +#define _LEP_LABEL(x) .L_ ## x ## _lep0 + +#define _ENTRY(x) \ + .text; .align 2; .globl x; .type x,@function; x: \ + _GEP_LABEL(x): \ + addis %r2, %r12, .TOC.-_GEP_LABEL(x)@ha; \ + addi %r2, %r2, .TOC.-_GEP_LABEL(x)@l; \ + _LEP_LABEL(x): \ + .localentry x, _LEP_LABEL(x)-_GEP_LABEL(x); + +#if defined(PROF) || defined(GPROF) +# define _PROF_PROLOGUE(y) \ + .section ".data"; \ + .align 2; \ +_TMP_LABEL(y):; \ + .long 0; \ + .section ".text"; \ + mflr %r0; \ + addis %r11, %r2, _TMP_LABEL(y)@toc@ha; \ + std %r0, 8(%r1); \ + addi %r0, %r11, _TMP_LABEL(y)@toc@l; \ + bl _mcount; +#else +# define _PROF_PROLOGUE(y) +#endif + +#define ENTRY(y) _ENTRY(y); _PROF_PROLOGUE(y) +#define ASENTRY(y) _ENTRY(y); _PROF_PROLOGUE(y) +#define END(y) .size y, . - y + +#define STRONG_ALIAS(alias,sym) \ + .global alias; .set alias,sym +#define WEAK_ALIAS(alias,sym) \ + .weak alias; .set alias,sym + +#if defined(_RET_PROTECTOR) +# define RETGUARD_SETUP(x, reg) \ + RETGUARD_SYMBOL(x); \ + mflr %r0; \ + addis reg, %r2, (__retguard_ ## x)@toc@ha; \ + ld reg, ((__retguard_ ## x)@toc@l)(reg); \ + xor reg, reg, %r0 +# define RETGUARD_CHECK(x, reg) \ + mflr %r0; \ + xor reg, reg, %r0; \ + addis %r12, %r2, (__retguard_ ## x)@toc@ha; \ + ld %r12, ((__retguard_ ## x)@toc@l)(%r12); \ + tdne reg, %r12 +# define RETGUARD_SAVE(reg, loc) \ + std reg, loc +# define RETGUARD_LOAD(reg, loc) \ + ld reg, loc +# define RETGUARD_SYMBOL(x) \ + .ifndef __retguard_ ## x; \ + .hidden __retguard_ ## x; \ + .type __retguard_ ## x,@object; \ + .pushsection .openbsd.randomdata.retguard,"aw",@progbits; \ + .weak __retguard_ ## x; \ + .p2align 3; \ + __retguard_ ## x: ; \ + .quad 0; \ + .size __retguard_ ## x, 8; \ + .popsection; \ + .endif +#else +# define RETGUARD_SETUP(x, reg) +# define RETGUARD_CHECK(x, reg) +# define RETGUARD_SAVE(reg, loc) +# define RETGUARD_LOAD(reg, loc) +# define RETGUARD_SYMBOL(x) +#endif + + +#endif /* !_POWERPC64_ASM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/atomic.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/atomic.h new file mode 100644 index 000000000000..277291b92677 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/atomic.h @@ -0,0 +1,292 @@ +/* $OpenBSD: atomic.h,v 1.3 2022/08/29 02:01:18 jsg Exp $ */ + +/* + * Copyright (c) 2015 Martin Pieuchot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +#ifndef _MACHINE_ATOMIC_H_ +#define _MACHINE_ATOMIC_H_ + +#if defined(_KERNEL) + +static __inline void +atomic_setbits_int(volatile unsigned int *uip, unsigned int v) +{ + unsigned int tmp; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " or %0, %1, %0 \n" + " stwcx. %0, 0, %2 \n" + " bne- 1b \n" + " sync" : "=&r" (tmp) : "r" (v), "r" (uip) : "cc", "memory"); +} + +static __inline void +atomic_clearbits_int(volatile unsigned int *uip, unsigned int v) +{ + unsigned int tmp; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " andc %0, %0, %1 \n" + " stwcx. %0, 0, %2 \n" + " bne- 1b \n" + " sync" : "=&r" (tmp) : "r" (v), "r" (uip) : "cc", "memory"); +} + +#endif /* defined(_KERNEL) */ + +static inline unsigned int +_atomic_cas_uint(volatile unsigned int *p, unsigned int o, unsigned int n) +{ + unsigned int rv; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " cmpw 0, %0, %4 \n" + " bne- 2f \n" + " stwcx. %3, 0, %2 \n" + " bne- 1b \n" + "2: \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (n), "r" (o) + : "cc"); + + return (rv); +} +#define atomic_cas_uint(_p, _o, _n) _atomic_cas_uint((_p), (_o), (_n)) + +static inline unsigned long +_atomic_cas_ulong(volatile unsigned long *p, unsigned long o, unsigned long n) +{ + unsigned long rv; + + __asm volatile ( + "1: ldarx %0, 0, %2 \n" + " cmpd 0, %0, %4 \n" + " bne- 2f \n" + " stdcx. %3, 0, %2 \n" + " bne- 1b \n" + "2: \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (n), "r" (o) + : "cc"); + + return (rv); +} +#define atomic_cas_ulong(_p, _o, _n) _atomic_cas_ulong((_p), (_o), (_n)) + +static inline void * +_atomic_cas_ptr(volatile void *pp, void *o, void *n) +{ + void * volatile *p = pp; + void *rv; + + __asm volatile ( + "1: ldarx %0, 0, %2 \n" + " cmpd 0, %0, %4 \n" + " bne- 2f \n" + " stdcx. %3, 0, %2 \n" + " bne- 1b \n" + "2: \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (n), "r" (o) + : "cc"); + + return (rv); +} +#define atomic_cas_ptr(_p, _o, _n) _atomic_cas_ptr((_p), (_o), (_n)) + +static inline unsigned int +_atomic_swap_uint(volatile unsigned int *p, unsigned int v) +{ + unsigned int rv; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " stwcx. %3, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (v) + : "cc"); + + return (rv); +} +#define atomic_swap_uint(_p, _v) _atomic_swap_uint((_p), (_v)) + +static inline unsigned long +_atomic_swap_ulong(volatile unsigned long *p, unsigned long v) +{ + unsigned long rv; + + __asm volatile ( + "1: ldarx %0, 0, %2 \n" + " stdcx. %3, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (v) + : "cc"); + + return (rv); +} +#define atomic_swap_ulong(_p, _v) _atomic_swap_ulong((_p), (_v)) + +static inline void * +_atomic_swap_ptr(volatile void *pp, void *v) +{ + void * volatile *p = pp; + void *rv; + + __asm volatile ( + "1: ldarx %0, 0, %2 \n" + " stdcx. %3, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (v) + : "cc"); + + return (rv); +} +#define atomic_swap_ptr(_p, _v) _atomic_swap_ptr((_p), (_v)) + +static inline unsigned int +_atomic_add_int_nv(volatile unsigned int *p, unsigned int v) +{ + unsigned int rv; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " add %0, %3, %0 \n" + " stwcx. %0, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (v) + : "cc", "xer"); + + return (rv); +} +#define atomic_add_int_nv(_p, _v) _atomic_add_int_nv((_p), (_v)) + +static inline unsigned long +_atomic_add_long_nv(volatile unsigned long *p, unsigned long v) +{ + unsigned long rv; + + __asm volatile ( + "1: ldarx %0, 0, %2 \n" + " add %0, %3, %0 \n" + " stdcx. %0, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (v) + : "cc", "xer"); + + return (rv); +} +#define atomic_add_long_nv(_p, _v) _atomic_add_long_nv((_p), (_v)) + +static inline unsigned int +_atomic_sub_int_nv(volatile unsigned int *p, unsigned int v) +{ + unsigned int rv; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " subf %0, %3, %0 \n" + " stwcx. %0, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (v) + : "cc", "xer"); + + return (rv); +} +#define atomic_sub_int_nv(_p, _v) _atomic_sub_int_nv((_p), (_v)) + +static inline unsigned long +_atomic_sub_long_nv(volatile unsigned long *p, unsigned long v) +{ + unsigned long rv; + + __asm volatile ( + "1: ldarx %0, 0, %2 \n" + " subf %0, %3, %0 \n" + " stdcx. %0, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "r" (v) + : "cc", "xer"); + + return (rv); +} +#define atomic_sub_long_nv(_p, _v) _atomic_sub_long_nv((_p), (_v)) + +static inline unsigned int +_atomic_addic_int_nv(volatile unsigned int *p, unsigned int v) +{ + unsigned int rv; + + __asm volatile ( + "1: lwarx %0, 0, %2 \n" + " addic %0, %0, %3 \n" + " stwcx. %0, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "i" (v) + : "cc", "xer"); + + return (rv); +} +#define atomic_inc_int_nv(_p) _atomic_addic_int_nv((_p), 1) +#define atomic_dec_int_nv(_p) _atomic_addic_int_nv((_p), -1) + +static inline unsigned long +_atomic_addic_long_nv(volatile unsigned long *p, unsigned long v) +{ + unsigned long rv; + + __asm volatile ( + "1: ldarx %0, 0, %2 \n" + " addic %0, %0, %3 \n" + " stdcx. %0, 0, %2 \n" + " bne- 1b \n" + : "=&r" (rv), "+m" (*p) + : "r" (p), "i" (v) + : "cc", "xer"); + + return (rv); +} +#define atomic_inc_long_nv(_p) _atomic_addic_long_nv((_p), 1) +#define atomic_dec_long_nv(_p) _atomic_addic_long_nv((_p), -1) + +#define __membar(_f) do { __asm volatile(_f ::: "memory"); } while (0) + +#if defined(MULTIPROCESSOR) || !defined(_KERNEL) +#define membar_enter() __membar("isync") +#define membar_exit() __membar("sync") +#define membar_producer() __membar("sync") +#define membar_consumer() __membar("isync") +#define membar_sync() __membar("sync") +#else +#define membar_enter() __membar("") +#define membar_exit() __membar("") +#define membar_producer() __membar("") +#define membar_consumer() __membar("") +#define membar_sync() __membar("") +#endif + +#endif /* _MACHINE_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/bus.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/bus.h new file mode 100644 index 000000000000..626dcdbbcac3 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/bus.h @@ -0,0 +1,532 @@ +/* $OpenBSD: bus.h,v 1.5 2020/11/15 23:13:00 kettenis Exp $ */ +/* + * Copyright (c) 2003-2004 Opsycon AB Sweden. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BUS_H_ +#define _MACHINE_BUS_H_ + +#define CAT(a,b) a##b +#define CAT3(a,b,c) a##b##c + +/* + * Bus access types. + */ +struct bus_space; +typedef u_long bus_addr_t; +typedef u_long bus_size_t; +typedef u_long bus_space_handle_t; +typedef struct bus_space *bus_space_tag_t; +typedef struct bus_space bus_space_t; + +struct bus_space { + bus_addr_t bus_base; + void *bus_private; + uint8_t (*_space_read_1)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_1)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, uint8_t); + uint16_t (*_space_read_2)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_2)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, uint16_t); + uint32_t (*_space_read_4)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_4)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, uint32_t); + uint64_t (*_space_read_8)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_8)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, uint64_t); + void (*_space_read_raw_2)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); + void (*_space_write_raw_2)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); + void (*_space_read_raw_4)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); + void (*_space_write_raw_4)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); + void (*_space_read_raw_8)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); + void (*_space_write_raw_8)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); + int (*_space_map)(bus_space_tag_t , bus_addr_t, + bus_size_t, int, bus_space_handle_t *); + void (*_space_unmap)(bus_space_tag_t, bus_space_handle_t, + bus_size_t); + int (*_space_subregion)(bus_space_tag_t, bus_space_handle_t, + bus_size_t, bus_size_t, bus_space_handle_t *); + void * (*_space_vaddr)(bus_space_tag_t, bus_space_handle_t); + paddr_t (*_space_mmap)(bus_space_tag_t, bus_addr_t, off_t, + int, int); +}; + +#define bus_space_read_1(t, h, o) (*(t)->_space_read_1)((t), (h), (o)) +#define bus_space_read_2(t, h, o) (*(t)->_space_read_2)((t), (h), (o)) +#define bus_space_read_4(t, h, o) (*(t)->_space_read_4)((t), (h), (o)) +#define bus_space_read_8(t, h, o) (*(t)->_space_read_8)((t), (h), (o)) + +#define bus_space_write_1(t, h, o, v) (*(t)->_space_write_1)((t), (h), (o), (v)) +#define bus_space_write_2(t, h, o, v) (*(t)->_space_write_2)((t), (h), (o), (v)) +#define bus_space_write_4(t, h, o, v) (*(t)->_space_write_4)((t), (h), (o), (v)) +#define bus_space_write_8(t, h, o, v) (*(t)->_space_write_8)((t), (h), (o), (v)) + +#define bus_space_read_raw_2(t, h, o) \ + generic_space_read_2((t), (h), (o)) +#define bus_space_read_raw_4(t, h, o) \ + generic_space_read_4((t), (h), (o)) +#define bus_space_read_raw_8(t, h, o) \ + generic_space_read_8((t), (h), (o)) + +#define bus_space_write_raw_2(t, h, o, v) \ + generic_space_write_2((t), (h), (o), (v)) +#define bus_space_write_raw_4(t, h, o, v) \ + generic_space_write_4((t), (h), (o), (v)) +#define bus_space_write_raw_8(t, h, o, v) \ + generic_space_write_8((t), (h), (o), (v)) + +#define bus_space_read_raw_multi_2(t, h, a, b, l) \ + (*(t)->_space_read_raw_2)((t), (h), (a), (b), (l)) +#define bus_space_read_raw_multi_4(t, h, a, b, l) \ + (*(t)->_space_read_raw_4)((t), (h), (a), (b), (l)) +#define bus_space_read_raw_multi_8(t, h, a, b, l) \ + (*(t)->_space_read_raw_8)((t), (h), (a), (b), (l)) + +#define bus_space_write_raw_multi_2(t, h, a, b, l) \ + (*(t)->_space_write_raw_2)((t), (h), (a), (b), (l)) +#define bus_space_write_raw_multi_4(t, h, a, b, l) \ + (*(t)->_space_write_raw_4)((t), (h), (a), (b), (l)) +#define bus_space_write_raw_multi_8(t, h, a, b, l) \ + (*(t)->_space_write_raw_8)((t), (h), (a), (b), (l)) + +#define bus_space_map(t, o, s, c, p) (*(t)->_space_map)((t), (o), (s), (c), (p)) +#define bus_space_unmap(t, h, s) (*(t)->_space_unmap)((t), (h), (s)) +#define bus_space_subregion(t, h, o, s, p) \ + (*(t)->_space_subregion)((t), (h), (o), (s), (p)) + +#define BUS_SPACE_MAP_CACHEABLE 0x01 +#define BUS_SPACE_MAP_KSEG0 0x02 +#define BUS_SPACE_MAP_LINEAR 0x04 +#define BUS_SPACE_MAP_PREFETCHABLE 0x08 + +#define bus_space_vaddr(t, h) (*(t)->_space_vaddr)((t), (h)) +#define bus_space_mmap(t, a, o, p, f) \ + (*(t)->_space_mmap)((t), (a), (o), (p), (f)) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_multi(n,m) \ +static __inline void \ +CAT(bus_space_read_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t o, CAT3(uint,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) \ + *x++ = CAT(bus_space_read_,n)(bst, bsh, o); \ +} + +bus_space_read_multi(1,8) +bus_space_read_multi(2,16) +bus_space_read_multi(4,32) +bus_space_read_multi(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_region(n,m) \ +static __inline void \ +CAT(bus_space_read_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(uint,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) { \ + *x++ = CAT(bus_space_read_,n)(bst, bsh, ba); \ + ba += (n); \ + } \ +} + +bus_space_read_region(1,8) +bus_space_read_region(2,16) +bus_space_read_region(4,32) +bus_space_read_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_raw_region(n,m) \ +static __inline void \ +CAT(bus_space_read_raw_region_,n)(bus_space_tag_t bst, \ + bus_space_handle_t bsh, \ + bus_addr_t ba, uint8_t *x, size_t cnt) \ +{ \ + cnt >>= ((n) >> 1); \ + while (cnt--) { \ + CAT(bus_space_read_raw_multi_,n)(bst, bsh, ba, x, (n)); \ + ba += (n); \ + x += (n); \ + } \ +} + +bus_space_read_raw_region(2,16) +bus_space_read_raw_region(4,32) +bus_space_read_raw_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_multi(n,m) \ +static __inline void \ +CAT(bus_space_write_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t o, const CAT3(uint,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) \ + CAT(bus_space_write_,n)(bst, bsh, o, *x++); \ +} + +bus_space_write_multi(1,8) +bus_space_write_multi(2,16) +bus_space_write_multi(4,32) +bus_space_write_multi(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_region(n,m) \ +static __inline void \ +CAT(bus_space_write_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, const CAT3(uint,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) { \ + CAT(bus_space_write_,n)(bst, bsh, ba, *x++); \ + ba += (n); \ + } \ +} + +bus_space_write_region(1,8) +bus_space_write_region(2,16) +bus_space_write_region(4,32) +bus_space_write_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_raw_region(n,m) \ +static __inline void \ +CAT(bus_space_write_raw_region_,n)(bus_space_tag_t bst, \ + bus_space_handle_t bsh, \ + bus_addr_t ba, const uint8_t *x, size_t cnt) \ +{ \ + cnt >>= ((n) >> 1); \ + while (cnt--) { \ + CAT(bus_space_write_raw_multi_,n)(bst, bsh, ba, x, (n)); \ + ba += (n); \ + x += (n); \ + } \ +} + +bus_space_write_raw_region(2,16) +bus_space_write_raw_region(4,32) +bus_space_write_raw_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_set_region(n,m) \ +static __inline void \ +CAT(bus_space_set_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(uint,m,_t) x, size_t cnt) \ +{ \ + while (cnt--) { \ + CAT(bus_space_write_,n)(bst, bsh, ba, x); \ + ba += (n); \ + } \ +} + +bus_space_set_region(1,8) +bus_space_set_region(2,16) +bus_space_set_region(4,32) +bus_space_set_region(8,64) + +/*----------------------------------------------------------------------------*/ +static __inline void +bus_space_copy_1(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + char *s = (char *)(h1 + o1); + char *d = (char *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + + +static __inline void +bus_space_copy_2(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + short *s = (short *)(h1 + o1); + short *d = (short *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + +static __inline void +bus_space_copy_4(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + int *s = (int *)(h1 + o1); + int *d = (int *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + +static __inline void +bus_space_copy_8(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + int64_t *s = (int64_t *)(h1 + o1); + int64_t *d = (int64_t *)(h2 + o2); + + while (c--) + *d++ = *s++; +} + +/*----------------------------------------------------------------------------*/ +/* + * Bus read/write barrier methods. + * + * void bus_space_barrier(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * bus_size_t len, int flags); + * + */ +static inline void +bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, + bus_size_t length, int flags) +{ + __asm__ volatile ("eieio" ::: "memory"); +} +#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ +#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ + +#define BUS_DMA_WAITOK 0x0000 +#define BUS_DMA_NOWAIT 0x0001 +#define BUS_DMA_ALLOCNOW 0x0002 +#define BUS_DMA_COHERENT 0x0008 +#define BUS_DMA_BUS1 0x0010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x0020 +#define BUS_DMA_BUS3 0x0040 +#define BUS_DMA_BUS4 0x0080 +#define BUS_DMA_READ 0x0100 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x0200 /* mapping is memory -> device only */ +#define BUS_DMA_STREAMING 0x0400 /* hint: sequential, unidirectional */ +#define BUS_DMA_ZERO 0x0800 /* zero memory in dmamem_alloc */ +#define BUS_DMA_NOCACHE 0x1000 +#define BUS_DMA_64BIT 0x2000 /* device handles 64bit dva */ + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct proc; +struct uio; + +#define BUS_DMASYNC_POSTREAD 0x0001 +#define BUS_DMASYNC_POSTWRITE 0x0002 +#define BUS_DMASYNC_PREREAD 0x0004 +#define BUS_DMASYNC_PREWRITE 0x0008 + +typedef struct machine_bus_dma_tag *bus_dma_tag_t; +typedef struct machine_bus_dmamap *bus_dmamap_t; + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +struct machine_bus_dma_segment { + bus_addr_t ds_addr; /* DMA address */ + bus_size_t ds_len; /* length of transfer */ + + paddr_t _ds_paddr; /* CPU address */ + vaddr_t _ds_vaddr; /* CPU address */ +}; +typedef struct machine_bus_dma_segment bus_dma_segment_t; + +/* + * bus_dma_tag_t + * + * A machine-dependent opaque type describing the implementation of + * DMA for a given bus. + */ + +struct machine_bus_dma_tag { + void *_cookie; /* cookie used in the guts */ + int _flags; /* misc. flags */ + + /* + * DMA mapping methods. + */ + int (*_dmamap_create)(bus_dma_tag_t , bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); + void (*_dmamap_destroy)(bus_dma_tag_t , bus_dmamap_t); + int (*_dmamap_load)(bus_dma_tag_t , bus_dmamap_t, void *, + bus_size_t, struct proc *, int); + int (*_dmamap_load_mbuf)(bus_dma_tag_t , bus_dmamap_t, + struct mbuf *, int); + int (*_dmamap_load_uio)(bus_dma_tag_t , bus_dmamap_t, + struct uio *, int); + int (*_dmamap_load_raw)(bus_dma_tag_t , bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); + int (*_dmamap_load_buffer)(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int, paddr_t *, int *, int); + void (*_dmamap_unload)(bus_dma_tag_t , bus_dmamap_t); + void (*_dmamap_sync)(bus_dma_tag_t , bus_dmamap_t, + bus_addr_t, bus_size_t, int); + + /* + * DMA memory utility functions. + */ + int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); + void (*_dmamem_free)(bus_dma_tag_t, bus_dma_segment_t *, int); + int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); + void (*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t); + paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, + int, off_t, int, int); + + /* + * internal memory address translation information. + */ + bus_addr_t _dma_mask; +}; + +#define bus_dmamap_create(t, s, n, m, b, f, p) \ + (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) +#define bus_dmamap_destroy(t, p) \ + (*(t)->_dmamap_destroy)((t), (p)) +#define bus_dmamap_load(t, m, b, s, p, f) \ + (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) +#define bus_dmamap_load_mbuf(t, m, b, f) \ + (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) +#define bus_dmamap_load_uio(t, m, u, f) \ + (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) +#define bus_dmamap_load_raw(t, m, sg, n, s, f) \ + (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) +#define bus_dmamap_unload(t, p) \ + (*(t)->_dmamap_unload)((t), (p)) +#define bus_dmamap_sync(t, p, a, l, o) \ + (void)((t)->_dmamap_sync ? \ + (*(t)->_dmamap_sync)((t), (p), (a), (l), (o)) : (void)0) + +#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ + (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f)) +#define bus_dmamem_free(t, sg, n) \ + (*(t)->_dmamem_free)((t), (sg), (n)) +#define bus_dmamem_map(t, sg, n, s, k, f) \ + (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f)) +#define bus_dmamem_unmap(t, k, s) \ + (*(t)->_dmamem_unmap)((t), (k), (s)) +#define bus_dmamem_mmap(t, sg, n, o, p, f) \ + (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f)) + +int _dmamap_create(bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); +void _dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); +int _dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); +int _dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *, int); +int _dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, struct uio *, int); +int _dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); +int _dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int, paddr_t *, int *, int); +void _dmamap_unload(bus_dma_tag_t, bus_dmamap_t); +void _dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, + bus_size_t, int); + +int _dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); +void _dmamem_free(bus_dma_tag_t, bus_dma_segment_t *, int); +int _dmamem_map(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); +void _dmamem_unmap(bus_dma_tag_t, caddr_t, size_t); +paddr_t _dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, int, int); +int _dmamem_alloc_range(bus_dma_tag_t, bus_size_t, bus_size_t, bus_size_t, + bus_dma_segment_t *, int, int *, int, paddr_t, paddr_t); + +/* + * bus_dmamap_t + * + * Describes a DMA mapping. + */ +struct machine_bus_dmamap { + /* + * PRIVATE MEMBERS: not for use by machine-independent code. + */ + bus_size_t _dm_size; /* largest DMA transfer mappable */ + int _dm_segcnt; /* number of segs this map can map */ + bus_size_t _dm_maxsegsz; /* largest possible segment */ + bus_size_t _dm_boundary; /* don't cross this */ + int _dm_flags; /* misc. flags */ + + void *_dm_cookie; /* cookie for bus-specific functions */ + + /* + * PUBLIC MEMBERS: these are used by machine-independent code. + */ + bus_size_t dm_mapsize; /* size of the mapping */ + int dm_nsegs; /* # valid segments in mapping */ + bus_dma_segment_t dm_segs[1]; /* segments; variable length */ +}; + +int generic_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, + bus_space_handle_t *); +void generic_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t); +int generic_space_region(bus_space_tag_t, bus_space_handle_t, bus_size_t, + bus_size_t, bus_space_handle_t *); +void *generic_space_vaddr(bus_space_tag_t, bus_space_handle_t); +paddr_t generic_space_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int); +uint8_t generic_space_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint16_t generic_space_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint32_t generic_space_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint64_t generic_space_read_8(bus_space_tag_t, bus_space_handle_t, bus_size_t); +void generic_space_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint8_t); +void generic_space_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint16_t); +void generic_space_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint32_t); +void generic_space_write_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint64_t); +void generic_space_read_raw_2(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_raw_2(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); +void generic_space_read_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); +void generic_space_read_raw_8(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_raw_8(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); + +uint16_t little_space_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint32_t little_space_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint64_t little_space_read_8(bus_space_tag_t, bus_space_handle_t, bus_size_t); +void little_space_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint16_t); +void little_space_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint32_t); +void little_space_write_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint64_t); + +#endif /* _MACHINE_BUS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/cdefs.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/cdefs.h new file mode 100644 index 000000000000..dcf667bff9e3 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/cdefs.h @@ -0,0 +1,21 @@ +/* $OpenBSD: cdefs.h,v 1.1 2020/05/16 17:11:14 kettenis Exp $ */ + +/* + * Written by J.T. Conklin 01/17/95. + * Public domain. + */ + +#ifndef _MACHINE_CDEFS_H_ +#define _MACHINE_CDEFS_H_ + +#define __strong_alias(alias,sym) \ + __asm__(".global " __STRING(alias) " ; " __STRING(alias) \ + " = " __STRING(sym)) +#define __weak_alias(alias,sym) \ + __asm__(".weak " __STRING(alias) " ; " __STRING(alias) \ + " = " __STRING(sym)) +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning." __STRING(sym) \ + " ; .ascii \"" msg "\" ; .text") + +#endif /* !_MACHINE_CDEFS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/conf.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/conf.h new file mode 100644 index 000000000000..bed3c41fe6fd --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/conf.h @@ -0,0 +1,24 @@ +#include + +#define mmread mmrw +#define mmwrite mmrw +cdev_decl(mm); + +cdev_decl(opalcons); + +/* open, close, ioctl */ +#define cdev_kexec_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) nullop, 0, \ + (dev_type_mmap((*))) enodev } + +/* open, close, ioctl */ +#define cdev_openprom_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) nullop, 0, \ + (dev_type_mmap((*))) enodev } + +cdev_decl(kexec); +cdev_decl(openprom); \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/cpu.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/cpu.h new file mode 100644 index 000000000000..f5e0e18115e2 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/cpu.h @@ -0,0 +1,234 @@ +/* $OpenBSD: cpu.h,v 1.39 2024/11/28 18:54:36 gkoehler Exp $ */ + +/* + * Copyright (c) 2020 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_CPU_H_ +#define _MACHINE_CPU_H_ + +/* + * User-visible definitions + */ + +/* + * CTL_MACHDEP definitions. + */ +#define CPU_ALTIVEC 1 /* altivec is present */ +#define CPU_MAXID 2 /* number of valid machdep ids */ + +#define CTL_MACHDEP_NAMES { \ + { 0, 0 }, \ + { "altivec", CTLTYPE_INT }, \ +} + +#ifdef _KERNEL + +/* + * Kernel-only definitions + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct cpu_info { + struct device *ci_dev; + struct cpu_info *ci_next; + struct schedstate_percpu ci_schedstate; + + uint32_t ci_cpuid; + uint32_t ci_pir; + int ci_node; + + struct proc *ci_curproc; + struct pcb *ci_curpcb; + + struct slb ci_kernel_slb[32]; + paddr_t ci_user_slb_pa; + register_t ci_slbsave[18]; + char ci_slbstack[1024]; + +#define CPUSAVE_LEN 9 + register_t ci_tempsave[CPUSAVE_LEN]; + register_t ci_idle_sp_save; + + struct clockqueue ci_queue; + + volatile int ci_cpl; + volatile int ci_dec_deferred; + uint32_t ci_ipending; + uint32_t ci_idepth; +#ifdef DIAGNOSTIC + int ci_mutex_level; +#endif + int ci_want_resched; + + uint32_t ci_randseed; + +#ifdef MULTIPROCESSOR + struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM]; + void *ci_initstack_end; + void *ci_ipi; + int ci_ipi_reason; + volatile int ci_flags; +#endif + +#ifdef DDB + volatile int ci_ddb_paused; +#define CI_DDB_RUNNING 0 +#define CI_DDB_SHOULDSTOP 1 +#define CI_DDB_STOPPED 2 +#define CI_DDB_ENTERDDB 3 +#define CI_DDB_INDDB 4 +#endif + char ci_panicbuf[512]; +}; + +#define CPUF_PRIMARY (1 << 0) +#define CPUF_AP (1 << 1) +#define CPUF_IDENTIFY (1 << 2) +#define CPUF_IDENTIFIED (1 << 3) +#define CPUF_PRESENT (1 << 4) +#define CPUF_GO (1 << 5) +#define CPUF_RUNNING (1 << 6) + +extern struct cpu_info cpu_info[]; +extern struct cpu_info *cpu_info_primary; + +static __inline struct cpu_info * +curcpu(void) +{ + struct cpu_info *ci; + __asm volatile ("mfsprg0 %0" : "=r"(ci)); + return ci; +} + +#define CPU_INFO_ITERATOR int + +#ifndef MULTIPROCESSOR + +#define MAXCPUS 1 +#define CPU_IS_PRIMARY(ci) 1 +#define CPU_IS_RUNNING(ci) 1 +#define cpu_number() 0 + +#define CPU_INFO_UNIT(ci) 0 +#define CPU_INFO_FOREACH(cii, ci) \ + for (cii = 0, ci = curcpu(); ci != NULL; ci = NULL) + +#define cpu_kick(ci) +#define cpu_unidle(ci) + +#else + +#define MAXCPUS 48 +#define CPU_IS_PRIMARY(ci) ((ci) == cpu_info_primary) +#define CPU_IS_RUNNING(ci) ((ci)->ci_flags & CPUF_RUNNING) +#define cpu_number() (curcpu()->ci_cpuid) + +#define CPU_INFO_UNIT(ci) ((ci)->ci_dev ? (ci)->ci_dev->dv_unit : 0) +#define CPU_INFO_FOREACH(cii, ci) \ + for (cii = 0, ci = &cpu_info[0]; cii < ncpus; cii++, ci++) + +void cpu_kick(struct cpu_info *); +void cpu_unidle(struct cpu_info *); +void cpu_boot_secondary_processors(void); + +extern void (*ul_setperf)(int); +void mp_setperf(int); + +#endif + +#define clockframe trapframe + +#define CLKF_INTR(frame) (curcpu()->ci_idepth > 1) +#define CLKF_USERMODE(frame) (frame->srr1 & PSL_PR) +#define CLKF_PC(frame) (frame->srr0) + +#define aston(p) ((p)->p_md.md_astpending = 1) +#define need_proftick(p) aston(p) + +void signotify(struct proc *); + +#define CPU_BUSY_CYCLE() __asm volatile ("" ::: "memory") + +#define curpcb curcpu()->ci_curpcb + +void cpu_init_features(void); +void cpu_init(void); + +#define cpu_idle_enter() do { /* nothing */ } while (0) +#define cpu_idle_leave() do { /* nothing */ } while (0) +extern uint64_t cpu_idle_state_psscr; +extern void (*cpu_idle_cycle_fcn)(void); + +static inline unsigned int +cpu_rnd_messybits(void) +{ + uint64_t tb; + + __asm volatile("mftb %0" : "=r" (tb)); + return ((tb >> 32) ^ tb); +} + +void need_resched(struct cpu_info *); +#define clear_resched(ci) ((ci)->ci_want_resched = 0) + +void delay(u_int); +#define DELAY(x) delay(x) + +#define PROC_STACK(p) ((p)->p_md.md_regs->fixreg[1]) +#define PROC_PC(p) ((p)->p_md.md_regs->srr0) + +void proc_trampoline(void); + +static inline void +intr_enable(void) +{ + mtmsr(mfmsr() | PSL_EE); +} + +static inline u_long +intr_disable(void) +{ + u_long msr; + + msr = mfmsr(); + mtmsr(msr & ~PSL_EE); + return msr; +} + +static inline void +intr_restore(u_long msr) +{ + mtmsr(msr); +} + +#endif /* _KERNEL */ + +#ifdef MULTIPROCESSOR +#include +#endif /* MULTIPROCESSOR */ + +#endif /* _MACHINE_CPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/cpufunc.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/cpufunc.h new file mode 100644 index 000000000000..161e89a9b878 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/cpufunc.h @@ -0,0 +1,222 @@ +/* $OpenBSD: cpufunc.h,v 1.11 2023/01/25 09:53:53 kettenis Exp $ */ + +/* + * Copyright (c) 2020 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_CPUFUNC_H_ +#define _MACHINE_CPUFUNC_H_ + +static inline void +eieio(void) +{ + __asm volatile ("eieio" ::: "memory"); +} + +static inline void +isync(void) +{ + __asm volatile ("isync" ::: "memory"); +} + +static inline void +ptesync(void) +{ + __asm volatile ("ptesync" ::: "memory"); +} + +static inline void +sync(void) +{ + __asm volatile ("sync" ::: "memory"); +} + +static inline void +slbia(void) +{ + __asm volatile ("slbia"); +} + +static inline void +slbie(uint64_t esid) +{ + __asm volatile ("slbie %0" :: "r"(esid)); +} + +static inline uint64_t +slbmfee(uint64_t entry) +{ + uint64_t value; + __asm volatile ("slbmfee %0, %1" : "=r"(value) : "r"(entry)); + return value; +} + +static inline void +slbmte(uint64_t slbv, uint64_t slbe) +{ + __asm volatile ("slbmte %0, %1" :: "r"(slbv), "r"(slbe)); +} + +static inline void +tlbie(uint64_t ava) +{ + __asm volatile ("tlbie %0, %1" :: "r"(ava), "r"(0)); +} + +static inline void +tlbiel(uint64_t ava) +{ + __asm volatile ("tlbiel %0" :: "r"(ava)); +} + +static inline void +tlbsync(void) +{ + __asm volatile ("tlbsync" ::: "memory"); +} + +static inline uint64_t +mfmsr(void) +{ + uint64_t value; + __asm volatile ("mfmsr %0" : "=r"(value)); + return value; +} + +static inline void +mtmsr(uint64_t value) +{ + __asm volatile ("mtmsr %0" :: "r"(value)); +} + +static inline uint64_t +mftb(void) +{ + uint64_t value; + __asm volatile ("mftb %0" : "=r"(value)); + return value; +} + +static inline uint32_t +mfdsisr(void) +{ + uint32_t value; + __asm volatile ("mfdsisr %0" : "=r"(value)); + return value; +} + +static inline uint64_t +mfdar(void) +{ + uint64_t value; + __asm volatile ("mfdar %0" : "=r"(value)); + return value; +} + +static inline void +mtdec(uint32_t value) +{ + __asm volatile ("mtdec %0" :: "r"(value)); +} + +static inline void +mtsdr1(uint64_t value) +{ + __asm volatile ("mtsdr1 %0" :: "r"(value)); +} + +static inline void +mtamr(uint64_t value) +{ + __asm volatile ("mtspr 29, %0" :: "r"(value)); +} + +static inline void +mtfscr(uint64_t value) +{ + __asm volatile ("mtspr 153, %0" :: "r"(value)); +} + +static inline void +mtuamor(uint64_t value) +{ + __asm volatile ("mtspr 157, %0" :: "r"(value)); +} + +static inline uint32_t +mfpvr(void) +{ + uint32_t value; + __asm volatile ("mfspr %0, 287" : "=r"(value)); + return value; +} + +static inline uint64_t +mflpcr(void) +{ + uint64_t value; + __asm volatile ("mfspr %0, 318" : "=r"(value)); + return value; +} + +static inline void +mtlpcr(uint64_t value) +{ + __asm volatile ("mtspr 318, %0" :: "r"(value)); +} + +#define LPCR_PECE 0x000040000001f000UL +#define LPCR_LPES 0x0000000000000008UL +#define LPCR_HVICE 0x0000000000000002UL + +static inline void +mtamor(uint64_t value) +{ + __asm volatile ("mtspr 349, %0" :: "r"(value)); +} + +static inline void +mtptcr(uint64_t value) +{ + __asm volatile ("mtspr 464, %0" :: "r"(value)); +} + +static inline uint64_t +mfpmsr(void) +{ + uint64_t value; + __asm volatile ("mfspr %0, 853" : "=r"(value)); + return value; +} + +static inline void +mtpmcr(uint64_t value) +{ + __asm volatile ("mtspr 884, %0" :: "r"(value)); +} + +static inline uint32_t +mfpir(void) +{ + uint32_t value; + __asm volatile ("mfspr %0, 1023" : "=r"(value)); + return value; +} + +extern int cacheline_size; + +void __syncicache(void *, size_t); + +#endif /* _MACHINE_CPUFUNC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/db_machdep.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/db_machdep.h new file mode 100644 index 000000000000..caf96c25d30a --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/db_machdep.h @@ -0,0 +1,86 @@ +/* $OpenBSD: db_machdep.h,v 1.6 2021/08/30 08:11:12 jasper Exp $*/ +/* $NetBSD: db_machdep.h,v 1.13 1996/04/29 20:50:08 leo Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +/* + * Machine-dependent defines for new kernel debugger. + */ +#ifndef _MACHINE_DB_MACHDEP_H_ +#define _MACHINE_DB_MACHDEP_H_ + +#include +#include +#include +#include + +typedef long db_expr_t; /* expression - signed */ +typedef struct trapframe db_regs_t; +extern db_regs_t ddb_regs; /* register state */ + +#define PC_REGS(regs) ((regs)->srr0) +#define SET_PC_REGS(regs, value) PC_REGS(regs) = (value) + +#define BKPT_INST 0x7C810808 /* breakpoint instruction */ + +#define BKPT_SIZE (4) /* size of breakpoint inst */ +#define BKPT_SET(inst) (BKPT_INST) + +#define db_clear_single_step(regs) ((regs)->srr1 &= ~PSL_SE) +#define db_set_single_step(regs) ((regs)->srr1 |= PSL_SE) + +#define T_BREAKPOINT 0xffff +#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BREAKPOINT) +#define IS_WATCHPOINT_TRAP(type, code) 0 + +#define M_RTS 0xfc0007fe +#define I_RTS 0x4c000020 +#define M_BC 0xfc000000 +#define I_BC 0x40000000 +#define M_B 0xfc000000 +#define I_B 0x50000000 +#define M_RFI 0xfc0007fe +#define I_RFI 0x4c000064 + +#define inst_trap_return(ins) (((ins)&M_RFI) == I_RFI) +#define inst_return(ins) (((ins)&M_RTS) == I_RTS) +#define inst_call(ins) (((ins)&M_BC ) == I_BC || \ + ((ins)&M_B ) == I_B ) + +struct trapframe; +void db_ktrap(int, db_regs_t *); + +#define DDB_STATE_NOT_RUNNING 0 +#define DDB_STATE_RUNNING 1 +#define DDB_STATE_EXITING 2 + +/* + * We define some of our own commands + */ +#define DB_MACHINE_COMMANDS + +#endif /* _MACHINE_DB_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/disklabel.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/disklabel.h new file mode 100644 index 000000000000..3d198e06b98e --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/disklabel.h @@ -0,0 +1,26 @@ +/* $OpenBSD: disklabel.h,v 1.1 2020/05/16 17:11:14 kettenis Exp $ */ + +/* + * Copyright (c) 2014 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_DISKLABEL_H_ +#define _MACHINE_DISKLABEL_H_ + +#define LABELSECTOR 1 /* sector containing label */ +#define LABELOFFSET 0 /* offset of label in sector */ +#define MAXPARTITIONS 16 /* number of partitions */ + +#endif /* _MACHINE_DISKLABEL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/elf.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/elf.h new file mode 100644 index 000000000000..d1a121fff937 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/elf.h @@ -0,0 +1,66 @@ +/* $OpenBSD: elf.h,v 1.3 2025/02/19 18:25:03 jca Exp $ */ + +/* + * This file is in the public domain. + */ + +#ifndef _MACHINE_ELF_H_ +#define _MACHINE_ELF_H_ + +/* + * CPU Feature Attributes + * + * These are defined in the PowerPC ELF ABI for the AT_HWCAP vector, + * and are exported to userland via the elf_aux_info(3) function. + */ + +#ifdef _KERNEL +# define __HAVE_CPU_HWCAP +# define __HAVE_CPU_HWCAP2 +extern unsigned long hwcap; +extern unsigned long hwcap2; +#endif /* _KERNEL */ + +#define PPC_FEATURE_32 0x80000000 /* Always true */ +#define PPC_FEATURE_64 0x40000000 /* Defined on a 64-bit CPU */ +#define PPC_FEATURE_601_INSTR 0x20000000 +#define PPC_FEATURE_HAS_ALTIVEC 0x10000000 +#define PPC_FEATURE_HAS_FPU 0x08000000 +#define PPC_FEATURE_HAS_MMU 0x04000000 +#define PPC_FEATURE_UNIFIED_CACHE 0x01000000 +#define PPC_FEATURE_HAS_SPE 0x00800000 +#define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000 +#define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000 +#define PPC_FEATURE_NO_TB 0x00100000 +#define PPC_FEATURE_POWER4 0x00080000 +#define PPC_FEATURE_POWER5 0x00040000 +#define PPC_FEATURE_POWER5_PLUS 0x00020000 +#define PPC_FEATURE_CELL 0x00010000 +#define PPC_FEATURE_BOOKE 0x00008000 +#define PPC_FEATURE_SMT 0x00004000 +#define PPC_FEATURE_ICACHE_SNOOP 0x00002000 +#define PPC_FEATURE_ARCH_2_05 0x00001000 +#define PPC_FEATURE_HAS_DFP 0x00000400 +#define PPC_FEATURE_POWER6_EXT 0x00000200 +#define PPC_FEATURE_ARCH_2_06 0x00000100 +#define PPC_FEATURE_HAS_VSX 0x00000080 +#define PPC_FEATURE_TRUE_LE 0x00000002 +#define PPC_FEATURE_PPC_LE 0x00000001 + +#define PPC_FEATURE2_ARCH_2_07 0x80000000 +#define PPC_FEATURE2_HTM 0x40000000 +#define PPC_FEATURE2_DSCR 0x20000000 +#define PPC_FEATURE2_EBB 0x10000000 +#define PPC_FEATURE2_ISEL 0x08000000 +#define PPC_FEATURE2_TAR 0x04000000 +#define PPC_FEATURE2_HAS_VEC_CRYPTO 0x02000000 +#define PPC_FEATURE2_HTM_NOSC 0x01000000 +#define PPC_FEATURE2_ARCH_3_00 0x00800000 +#define PPC_FEATURE2_HAS_IEEE128 0x00400000 +#define PPC_FEATURE2_DARN 0x00200000 +#define PPC_FEATURE2_SCV 0x00100000 +#define PPC_FEATURE2_HTM_NOSUSPEND 0x00080000 +#define PPC_FEATURE2_ARCH_3_1 0x00040000 +#define PPC_FEATURE2_MMA 0x00020000 + +#endif /* !_MACHINE_ELF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/endian.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/endian.h new file mode 100644 index 000000000000..2a92d0b2fda9 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/endian.h @@ -0,0 +1,37 @@ +/* $OpenBSD: endian.h,v 1.3 2024/05/07 14:26:48 naddy Exp $ */ + +/*- + * Copyright (c) 1997 Niklas Hallqvist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_ENDIAN_H_ +#define _MACHINE_ENDIAN_H_ + +#undef _BIG_ENDIAN /* XXX - gcc may define _BIG_ENDIAN too */ +#define _BYTE_ORDER _BIG_ENDIAN + +#ifndef __FROM_SYS__ENDIAN +#include +#endif + +#endif /* _MACHINE_ENDIAN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/exec.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/exec.h new file mode 100644 index 000000000000..219d93c1d06c --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/exec.h @@ -0,0 +1,36 @@ +/* $OpenBSD: exec.h,v 1.4 2021/03/11 11:16:59 jsg Exp $ */ + +/* + * Copyright (c) 2014 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_EXEC_H_ +#define _MACHINE_EXEC_H_ + +#define __LDPGSZ 4096 + +#define ARCH_ELFSIZE 64 + +#define ELF_TARG_CLASS ELFCLASS64 +#define ELF_TARG_DATA ELFDATA2MSB +#define ELF_TARG_MACH EM_PPC64 + +/* Processor specific dynamic tag values. */ +#define DT_PPC64_GLINK 0x70000000 +#define DT_PPC64_OPT 0x70000003 + +#define DT_PROCNUM (DT_PPC64_OPT - DT_LOPROC + 1) + +#endif \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/fdt.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/fdt.h new file mode 100644 index 000000000000..0401cf75fb9b --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/fdt.h @@ -0,0 +1,39 @@ +/* $OpenBSD: fdt.h,v 1.2 2020/10/30 13:07:48 kettenis Exp $ */ +/* + * Copyright (c) 2016 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_FDT_H_ +#define _MACHINE_FDT_H_ + +#include + +struct fdt_attach_args { + const char *fa_name; + int fa_node; + bus_space_tag_t fa_iot; + bus_dma_tag_t fa_dmat; + struct fdt_reg *fa_reg; + int fa_nreg; + uint32_t *fa_intr; + int fa_nintr; + int fa_acells; + int fa_scells; +}; + +extern int stdout_node; +extern int stdout_speed; + +#endif /* _MACHINE_FDT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/fenv.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/fenv.h new file mode 100644 index 000000000000..aadeaabeeec4 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/fenv.h @@ -0,0 +1,96 @@ +/* $OpenBSD: fenv.h,v 1.1 2020/06/28 08:19:34 kettenis Exp $ */ + +/* + * Copyright (c) 2011 Martynas Venckus + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_FENV_H_ +#define _MACHINE_FENV_H_ + +/* + * Each symbol representing a floating point exception expands to an integer + * constant expression with values, such that bitwise-inclusive ORs of _all + * combinations_ of the constants result in distinct values. + * + * We use such values that allow direct bitwise operations on FPU registers. + */ +#define FE_INEXACT 0x02000000 +#define FE_DIVBYZERO 0x04000000 +#define FE_UNDERFLOW 0x08000000 +#define FE_OVERFLOW 0x10000000 +#define FE_INVALID 0x20000000 +#define _FE_INVALID_SOFT 0x00000400 +#define _FE_INVALID_ALL 0x01f80700 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * exception constants defined above. + */ +#define FE_ALL_EXCEPT (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | \ + FE_OVERFLOW | FE_INVALID) +#define _MASK_SHIFT 22 + +/* + * Each symbol representing the rounding direction, expands to an integer + * constant expression whose value is distinct non-negative value. + * + * We use such values that allow direct bitwise operations on FPU registers. + */ +#define FE_TONEAREST 0x0 +#define FE_TOWARDZERO 0x1 +#define FE_UPWARD 0x2 +#define FE_DOWNWARD 0x3 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * rounding direction constants defined above. + */ +#define _ROUND_MASK (FE_TONEAREST | FE_TOWARDZERO | FE_UPWARD | \ + FE_DOWNWARD) + +/* + * fenv_t represents the entire floating-point environment. + */ +typedef unsigned int fenv_t; + +/* + * The following constant represents the default floating-point environment + * (that is, the one installed at program startup) and has type pointer to + * const-qualified fenv_t. + * + * It can be used as an argument to the functions within the header + * that manage the floating-point environment, namely fesetenv() and + * feupdateenv(). + */ +__BEGIN_DECLS +extern fenv_t __fe_dfl_env; +__END_DECLS +#define FE_DFL_ENV ((const fenv_t *)&__fe_dfl_env) + +/* + * fexcept_t represents the floating-point status flags collectively, including + * any status the implementation associates with the flags. + * + * A floating-point status flag is a system variable whose value is set (but + * never cleared) when a floating-point exception is raised, which occurs as a + * side effect of exceptional floating-point arithmetic to provide auxiliary + * information. + * + * A floating-point control mode is a system variable whose value may be set by + * the user to affect the subsequent behavior of floating-point arithmetic. + */ +typedef unsigned int fexcept_t; + +#endif /* !_MACHINE_FENV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/fpu.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/fpu.h new file mode 100644 index 000000000000..c9637f3bc561 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/fpu.h @@ -0,0 +1,17 @@ +/* $OpenBSD: fpu.h,v 1.4 2022/03/24 18:42:05 kettenis Exp $ */ + +/* public domain */ + +#ifndef _MACHINE_FPU_H +#define _MACHINE_FPU_H + +#ifdef _KERNEL + +void save_vsx(struct proc *); +void restore_vsx(struct proc *); + +int fpu_sigcode(struct proc *); + +#endif + +#endif /* _MACHINE_FPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/frame.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/frame.h new file mode 100644 index 000000000000..afb0dfa2956a --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/frame.h @@ -0,0 +1,104 @@ +/* $OpenBSD: frame.h,v 1.5 2020/07/13 22:37:37 kettenis Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 _MACHDEP_FRAME_H +#define _MACHDEP_FRAME_H + +/* + * We have to save all registers on every trap, because + * 1. user could attach this process every time + * 2. we must be able to restore all user registers in case of fork + * Actually, we do not save the fp registers on trap, since + * these are not used by the kernel. They are saved only when switching + * between processes using the FPU. + * + */ +struct trapframe { + __register_t fixreg[32]; + __register_t lr; + __register_t cr; + __register_t xer; + __register_t ctr; + __register_t srr0; + __register_t srr1; + __register_t vrsave; + __register_t dar; /* dar & dsisr are only filled on a DSI trap */ + __register_t dsisr; + __register_t exc; +}; + +/* + * This is to ensure alignment of the stackpointer + */ +#define FRAMELEN roundup(sizeof(struct trapframe) + 32, 16) + +struct callframe { + register_t cf_sp; + register_t cf_cr; + register_t cf_lr; + register_t cf_toc; +}; + +struct sigframe { + int sf_signum; + siginfo_t *sf_sip; + struct sigcontext sf_sc; + siginfo_t sf_si; +}; + +struct switchframe { + register_t sf_sp; + register_t sf_cr; + register_t sf_lr; /* unused */ + register_t sf_toc; /* unused */ + register_t sf_r14; + register_t sf_r15; + register_t sf_r16; + register_t sf_r17; + register_t sf_r18; + register_t sf_r19; + register_t sf_r20; + register_t sf_r21; + register_t sf_r22; + register_t sf_r23; + register_t sf_r24; + register_t sf_r25; + register_t sf_r26; + register_t sf_r27; + register_t sf_r28; + register_t sf_r29; + register_t sf_r30; + register_t sf_r31; +}; + +#endif /* _MACHDEP_FRAME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/ieee.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/ieee.h new file mode 100644 index 000000000000..3755c7eac557 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/ieee.h @@ -0,0 +1,119 @@ +/* $OpenBSD: ieee.h,v 1.1 2020/06/01 00:13:37 drahn Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ieee.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * ieee.h defines the machine-dependent layout of the machine's IEEE + * floating point. It does *not* define (yet?) any of the rounding + * mode bits, exceptions, and so forth. + */ + +/* + * Define the number of bits in each fraction and exponent. + * + * k k+1 + * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented + * + * (-exp_bias+1) + * as fractions that look like 0.fffff x 2 . This means that + * + * -126 + * the number 0.10000 x 2 , for instance, is the same as the normalized + * + * -127 -128 + * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero + * + * -129 + * in the fraction; to represent 2 , we need two, and so on. This + * + * (-exp_bias-fracbits+1) + * implies that the smallest denormalized number is 2 + * + * for whichever format we are talking about: for single precision, for + * + * -126 -149 + * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and + * + * -149 == -127 - 23 + 1. + */ +#define SNG_EXPBITS 8 +#define SNG_FRACBITS 23 + +#define DBL_EXPBITS 11 +#define DBL_FRACHBITS 20 +#define DBL_FRACLBITS 32 +#define DBL_FRACBITS 52 + +struct ieee_single { + u_int sng_sign:1; + u_int sng_exp:8; + u_int sng_frac:23; +}; + +struct ieee_double { + u_int dbl_sign:1; + u_int dbl_exp:11; + u_int dbl_frach:20; + u_int dbl_fracl; +}; + +/* + * Floats whose exponent is in [1..INFNAN) (of whatever type) are + * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. + * Floats whose exponent is zero are either zero (iff all fraction + * bits are zero) or subnormal values. + * + * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its + * high fraction; if the bit is set, it is a `quiet NaN'. + */ +#define SNG_EXP_INFNAN 255 +#define DBL_EXP_INFNAN 2047 + +#if 0 +#define SNG_QUIETNAN (1 << 22) +#define DBL_QUIETNAN (1 << 19) +#endif + +/* + * Exponent biases. + */ +#define SNG_EXP_BIAS 127 +#define DBL_EXP_BIAS 1023 \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/ieeefp.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/ieeefp.h new file mode 100644 index 000000000000..6b379119518c --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/ieeefp.h @@ -0,0 +1,25 @@ +/* $OpenBSD: ieeefp.h,v 1.1 2020/06/01 00:13:37 drahn Exp $ */ +/* $NetBSD: ieeefp.h,v 1.2 1999/07/07 01:52:26 danw Exp $ */ +/* + * Written by J.T. Conklin, Apr 6, 1995 + * Public domain. + */ + +#ifndef _POWERPC_IEEEFP_H_ +#define _POWERPC_IEEEFP_H_ + +typedef int fp_except; +#define FP_X_IMP 0x01 /* imprecise (loss of precision) */ +#define FP_X_DZ 0x02 /* divide-by-zero exception */ +#define FP_X_UFL 0x04 /* underflow exception */ +#define FP_X_OFL 0x08 /* overflow exception */ +#define FP_X_INV 0x10 /* invalid operation exception */ + +typedef enum { + FP_RN=0, /* round to nearest representable number */ + FP_RZ=1, /* round to zero (truncate) */ + FP_RP=2, /* round toward positive infinity */ + FP_RM=3 /* round toward negative infinity */ +} fp_rnd; + +#endif /* _POWERPC_IEEEFP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/intr.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/intr.h new file mode 100644 index 000000000000..e6a70160ba3d --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/intr.h @@ -0,0 +1,135 @@ +/* $OpenBSD: intr.h,v 1.16 2025/04/26 11:10:28 visa Exp $ */ + +/* + * Copyright (c) 2020 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_INTR_H_ +#define _MACHINE_INTR_H_ + +#define __USE_MI_SOFTINTR + +#include +#include + +struct cpu_info; +struct trapframe; + +#define IPL_NONE 0 +#define IPL_SOFTCLOCK 2 +#define IPL_SOFTNET 3 +#define IPL_SOFTTTY 4 +#define IPL_BIO 5 +#define IPL_NET 6 +#define IPL_TTY 7 +#define IPL_VM IPL_TTY +#define IPL_AUDIO 8 +#define IPL_CLOCK 9 +#define IPL_STATCLOCK IPL_CLOCK +#define IPL_SCHED IPL_CLOCK +#define IPL_HIGH IPL_CLOCK +#define IPL_IPI 10 +#define NIPL 11 + +#define IPL_MPFLOOR IPL_TTY +/* Interrupt priority 'flags'. */ +#define IPL_IRQMASK 0xf /* priority only */ +#define IPL_FLAGMASK 0xf00 /* flags only*/ +#define IPL_MPSAFE 0x100 /* 'mpsafe' interrupt, no kernel lock */ + +int splraise(int); +int spllower(int); +void splx(int); + +void softintr(int); + +#define spl0() spllower(IPL_NONE) +#define splsoftclock() splraise(IPL_SOFTCLOCK) +#define splsoftnet() splraise(IPL_SOFTNET) +#define splsofttty() splraise(IPL_SOFTTTY) +#define splbio() splraise(IPL_BIO) +#define splnet() splraise(IPL_NET) +#define spltty() splraise(IPL_TTY) +#define splvm() splraise(IPL_VM) +#define splclock() splraise(IPL_CLOCK) +#define splstatclock() splraise(IPL_STATCLOCK) +#define splsched() splraise(IPL_SCHED) +#define splhigh() splraise(IPL_HIGH) + +#ifdef DIAGNOSTIC +/* + * Although this function is implemented in MI code, it must be in this MD + * header because we don't want this header to include MI includes. + */ +void splassert_fail(int, int, const char *); +extern int splassert_ctl; +void splassert_check(int, const char *); +#define splassert(__wantipl) do { \ + if (splassert_ctl > 0) { \ + splassert_check(__wantipl, __func__); \ + } \ +} while (0) +#define splsoftassert(wantipl) splassert(wantipl) +#else +#define splassert(wantipl) do { /* nothing */ } while (0) +#define splsoftassert(wantipl) do { /* nothing */ } while (0) +#endif + +void intr_init(void); + +#define intr_barrier(x) + +#define IST_EDGE 0 +#define IST_LEVEL 1 + +void *intr_establish(uint32_t, int, int, struct cpu_info *, + int (*)(void *), void *, const char *); + +#define IPI_NOP 0 +#define IPI_DDB (1 << 0) +#define IPI_SETPERF (1 << 1) + +void intr_send_ipi(struct cpu_info *, int); + +extern void (*_exi)(struct trapframe *); +extern void (*_hvi)(struct trapframe *); +extern void *(*_intr_establish)(uint32_t, int, int, struct cpu_info *, + int (*)(void *), void *, const char *); +extern void (*_intr_send_ipi)(void *); +extern void (*_setipl)(int); + +struct interrupt_controller { + int ic_node; + void *ic_cookie; + void *(*ic_establish)(void *, int *, int, struct cpu_info *, + int (*)(void *), void *, char *); + void (*ic_send_ipi)(void *); + + LIST_ENTRY(interrupt_controller) ic_list; + uint32_t ic_phandle; + uint32_t ic_cells; +}; + +void interrupt_controller_register(struct interrupt_controller *); + +void *fdt_intr_establish_idx_cpu(int, int, int, struct cpu_info *, + int (*)(void *), void *, char *); +void *fdt_intr_establish_imap(int, int *, int, int, int (*)(void *), + void *, char *); +void *fdt_intr_establish_imap_cpu(int, int *, int, int, + struct cpu_info *, int (*)(void *), void *, char *); +void fdt_intr_disestablish(void *); + +#endif /* _MACHINE_INTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/kcore.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/kcore.h new file mode 100644 index 000000000000..c94e37366eb8 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/kcore.h @@ -0,0 +1 @@ +/* Empty */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/kexec.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/kexec.h new file mode 100644 index 000000000000..e909bfcc3e7c --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/kexec.h @@ -0,0 +1,36 @@ +/* $OpenBSD: kexec.h,v 1.3 2020/07/18 10:23:44 kettenis Exp $ */ + +/* + * Copyright (c) 2019-2020 Visa Hankala + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_KEXEC_H_ +#define _MACHINE_KEXEC_H_ + +#include + +#define KEXEC_MAX_ARGS 8 /* maximum number of boot arguments */ + +struct kexec_args { + char *kimg; /* kernel image buffer */ + size_t klen; /* size of kernel image */ + int boothowto; + u_char bootduid[8]; +}; + +#define KIOC_KEXEC _IOW('K', 1, struct kexec_args) +#define KIOC_GETBOOTDUID _IOR('K', 2, u_char[8]) + +#endif /* _MACHINE_KEXEC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/limits.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/limits.h new file mode 100644 index 000000000000..d2c0f2eaf30a --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/limits.h @@ -0,0 +1,55 @@ +/* $OpenBSD: limits.h,v 1.1 2020/05/16 17:11:14 kettenis Exp $ */ + +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)limits.h 7.2 (Berkeley) 6/28/90 + */ + +#ifndef _MACHINE_LIMITS_H_ +#define _MACHINE_LIMITS_H_ + +#include + +#if __POSIX_VISIBLE || __XPG_VISIBLE +#ifndef SIZE_MAX +#define SIZE_MAX ULONG_MAX /* max value for a size_t */ +#endif +#define SSIZE_MAX LONG_MAX /* max value for a ssize_t */ +#endif + +#if __BSD_VISIBLE +#define SIZE_T_MAX ULONG_MAX /* max value for a size_t (historic) */ + +#define UQUAD_MAX 0xffffffffffffffffULL /* max unsigned quad */ +#define QUAD_MAX 0x7fffffffffffffffLL /* max signed quad */ +#define QUAD_MIN (-0x7fffffffffffffffLL-1) /* min signed quad */ + +#endif /* __BSD_VISIBLE */ + +#endif /* _MACHINE_LIMITS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/mplock.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/mplock.h new file mode 100644 index 000000000000..1856d8925a4e --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/mplock.h @@ -0,0 +1,10 @@ +/* $OpenBSD: mplock.h,v 1.1 2020/07/22 11:08:01 kettenis Exp $ */ + +/* public domain */ + +#ifndef _MACHINE_MPLOCK_H_ +#define _MACHINE_MPLOCK_H_ + +#define __USE_MI_MPLOCK + +#endif /* !_MACHINE_MPLOCK_H */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/mutex.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/mutex.h new file mode 100644 index 000000000000..9f22aee173be --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/mutex.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mutex.h,v 1.1 2020/05/16 17:11:14 kettenis Exp $ */ + +#define __USE_MI_MUTEX \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/opal.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/opal.h new file mode 100644 index 000000000000..98106675bbf2 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/opal.h @@ -0,0 +1,238 @@ +/* $OpenBSD: opal.h,v 1.19 2021/01/23 12:10:08 kettenis Exp $ */ + +/* + * Copyright (c) 2020 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_OPAL_H_ +#define _MACHINE_OPAL_H_ + +/* Tokens. */ +#define OPAL_TEST 0 +#define OPAL_CONSOLE_WRITE 1 +#define OPAL_CONSOLE_READ 2 +#define OPAL_RTC_READ 3 +#define OPAL_RTC_WRITE 4 +#define OPAL_CEC_POWER_DOWN 5 +#define OPAL_CEC_REBOOT 6 +#define OPAL_HANDLE_INTERRUPT 9 +#define OPAL_POLL_EVENTS 10 +#define OPAL_PCI_CONFIG_READ_WORD 15 +#define OPAL_PCI_CONFIG_WRITE_WORD 18 +#define OPAL_SET_XIVE 19 +#define OPAL_GET_XIVE 20 +#define OPAL_PCI_EEH_FREEZE_STATUS 23 +#define OPAL_PCI_EEH_FREEZE_CLEAR 26 +#define OPAL_PCI_PHB_MMIO_ENABLE 27 +#define OPAL_PCI_SET_PHB_MEM_WINDOW 28 +#define OPAL_PCI_MAP_PE_MMIO_WINDOW 29 +#define OPAL_PCI_SET_PE 31 +#define OPAL_PCI_SET_XIVE_PE 37 +#define OPAL_GET_MSI_32 39 +#define OPAL_GET_MSI_64 40 +#define OPAL_START_CPU 41 +#define OPAL_PCI_MAP_PE_DMA_WINDOW 44 +#define OPAL_PCI_MAP_PE_DMA_WINDOW_REAL 45 +#define OPAL_PCI_RESET 49 +#define OPAL_REINIT_CPUS 70 +#define OPAL_CHECK_TOKEN 80 +#define OPAL_SENSOR_READ 88 +#define OPAL_IPMI_SEND 107 +#define OPAL_IPMI_RECV 108 +#define OPAL_CONSOLE_FLUSH 117 +#define OPAL_XIVE_RESET 128 +#define OPAL_XIVE_GET_IRQ_INFO 129 +#define OPAL_XIVE_GET_IRQ_CONFIG 131 +#define OPAL_XIVE_SET_IRQ_CONFIG 131 +#define OPAL_XIVE_GET_QUEUE_INFO 132 +#define OPAL_XIVE_SET_QUEUE_INFO 133 +#define OPAL_XIVE_GET_VP_INFO 137 +#define OPAL_XIVE_SET_VP_INFO 138 +#define OPAL_XIVE_DUMP 142 +#define OPAL_SENSOR_READ_U64 162 + +/* Return codes. */ +#define OPAL_SUCCESS 0 +#define OPAL_PARAMETER -1 +#define OPAL_BUSY -2 +#define OPAL_PARTIAL -3 +#define OPAL_CONSTRAINED -4 +#define OPAL_CLOSED -5 +#define OPAL_HARDWARE -6 +#define OPAL_UNSUPPORTED -7 +#define OPAL_PERMISSION -8 +#define OPAL_NO_MEM -9 +#define OPAL_RESOURCE -10 +#define OPAL_INTERNAL_ERROR -11 +#define OPAL_BUSY_EVENT -12 +#define OPAL_HARDWARE_FROZEN -13 +#define OPAL_WRONG_STATE -14 +#define OPAL_ASYNC_COMPLETION -15 +#define OPAL_EMPTY -16 + +/* OPAL_POLL_EVENT */ +#define OPAL_EVENT_CONSOLE_OUTPUT 0x00000008 +#define OPAL_EVENT_CONSOLE_INPUT 0x00000010 + +/* OPAL_PCI_EEH_FREEZE_CLEAR */ +#define OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO 1 +#define OPAL_EEH_ACTION_CLEAR_FREEZE_DMA 2 +#define OPAL_EEH_ACTION_CLEAR_FREEZE_ALL 3 + +/* OPAL_PCI_PHB_MMIO_ENABLE */ +#define OPAL_M32_WINDOW_TYPE 1 +#define OPAL_M64_WINDOW_TYPE 2 +#define OPAL_IO_WINDOW_TYPE 3 +#define OPAL_DISABLE_M64 0 +#define OPAL_ENABLE_M64_SPLIT 1 +#define OPAL_ENABLE_M64_NON_SPLIT 2 + +/* OPAL_PCIE_SET_PE */ +#define OPAL_IGNORE_RID_BUS_NUMBER 0 +#define OPAL_IGNORE_RID_DEVICE_NUMBER 0 +#define OPAL_COMPARE_RID_DEVICE_NUMBER 1 +#define OPAL_IGNORE_RID_FUNCTION_NUMBER 0 +#define OPAL_COMPARE_RID_FUNCTION_NUMBER 1 +#define OPAL_UNMAP_PE 0 +#define OPAL_MAP_PE 1 + +/* OPAL_PCI_RESET */ +#define OPAL_RESET_PHB_COMPLETE 1 +#define OPAL_RESET_PCI_LINK 2 +#define OPAL_RESET_PHB_ERROR 3 +#define OPAL_RESET_PCI_HOT 4 +#define OPAL_RESET_PCI_FUNDAMENTAL 5 +#define OPAL_RESET_PCI_IODA_TABLE 6 +#define OPAL_DEASSERT_RESET 0 +#define OPAL_ASSERT_RESET 1 + +/* OPAL_REINIT_CPUS */ +#define OPAL_REINIT_CPUS_HILE_BE 0x00000001 +#define OPAL_REINIT_CPUS_HILE_LE 0x00000002 +#define OPAL_REINIT_CPUS_MMU_HASH 0x00000004 +#define OPAL_REINIT_CPUS_MMU_RADIX 0x00000008 +#define OPAL_REINIT_CPUS_TM_SUSPEND_DISABLED 0x00000010 + +/* OPAL_CHECK_TOKEN */ +#define OPAL_TOKEN_ABSENT 0 +#define OPAL_TOKEN_PRESENT 1 + +/* OPAL_IPMI_SEND/RECV */ +#define OPAL_IPMI_MSG_FORMAT_VERSION_1 1 + +#ifndef _LOCORE +struct opal_ipmi_msg { + uint8_t version; + uint8_t netfn; + uint8_t cmd; + uint8_t data[0]; +}; +#endif + +/* OPAL_XIVE_RESET */ +#define OPAL_XIVE_MODE_EMU 0 +#define OPAL_XIVE_MODE_EXPL 1 + +/* OPAL_XIVE_GET_IRQ_INFO */ +#define OPAL_XIVE_IRQ_TRIGGER_PAGE 0x00000001 +#define OPAL_XIVE_IRQ_STORE_EOI 0x00000002 +#define OPAL_XIVE_IRQ_LSI 0x00000004 +#define OPAL_XIVE_IRQ_SHIFT_BUG 0x00000008 +#define OPAL_XIVE_IRQ_MASK_VIA_FW 0x00000010 +#define OPAL_XIVE_IRQ_EOI_VIA_FW 0x00000020 + +/* OPAL_XIVE_GET_QUEUE_INFO */ +#define OPAL_XIVE_EQ_ENABLED 0x00000001 +#define OPAL_XIVE_EQ_ALWAYS_NOTIFY 0x00000002 +#define OPAL_XIVE_EQ_ESCALATE 0x00000004 + +/* OPAL_XIVE_GET_VP_INFO */ +#define OPAL_XIVE_VP_ENABLED 0x00000001 +#define OPAL_XIVE_VP_SINGLE_ESCALATION 0x00000002 + +/* OPAL_XIVE_DUMP */ +#define XIVE_DUMP_TM_HYP 0x00000000 +#define XIVE_DUMP_TM_POOL 0x00000001 +#define XIVE_DUMP_TM_OS 0x00000002 +#define XIVE_DUMP_TM_USER 0x00000003 +#define XIVE_DUMP_VP 0x00000004 +#define XIVE_DUMP_EMU_STATE 0x00000005 + +#ifndef _LOCORE + +void *opal_phys(void *); + +int64_t opal_test(uint64_t); +int64_t opal_console_write(int64_t, int64_t *, const uint8_t *); +int64_t opal_console_read(int64_t, int64_t *, uint8_t *); +int64_t opal_rtc_read(uint32_t *, uint64_t *); +int64_t opal_rtc_write(uint32_t, uint64_t); +int64_t opal_cec_power_down(uint64_t); +int64_t opal_cec_reboot(void); +int64_t opal_handle_interrupt(uint32_t, uint64_t *); +int64_t opal_poll_events(uint64_t *); +int64_t opal_pci_config_read_word(uint64_t, uint64_t, uint64_t, uint32_t *); +int64_t opal_pci_config_write_word(uint64_t, uint64_t, uint64_t, uint32_t); +int64_t opal_set_xive(uint32_t, uint16_t, uint8_t); +int64_t opal_get_xive(uint32_t, uint16_t *, uint8_t *); +int64_t opal_pci_eeh_freeze_status(uint64_t, uint64_t, uint8_t *, + uint16_t *, uint64_t *); +int64_t opal_pci_eeh_freeze_clear(uint64_t, uint64_t, uint64_t); +int64_t opal_pci_phb_mmio_enable(uint64_t, uint16_t, uint16_t, uint16_t); +int64_t opal_pci_set_phb_mem_window(uint64_t, uint16_t, uint16_t, + uint64_t, uint64_t, uint64_t); +int64_t opal_pci_map_pe_mmio_window(uint64_t, uint64_t, uint16_t, + uint16_t, uint16_t); +int64_t opal_pci_set_pe(uint64_t, uint64_t, uint64_t, uint8_t, uint8_t, + uint8_t, uint8_t); +int64_t opal_pci_set_xive_pe(uint64_t, uint64_t, uint32_t); +int64_t opal_get_msi_32(uint64_t, uint32_t, uint32_t, uint8_t, + uint32_t *, uint32_t *); +int64_t opal_get_msi_64(uint64_t, uint32_t, uint32_t, uint8_t, + uint64_t *, uint32_t *); +int64_t opal_start_cpu(uint64_t, uint64_t); +int64_t opal_pci_map_pe_dma_window(uint64_t, uint64_t, uint16_t, uint16_t, + uint64_t, uint64_t, uint64_t); +int64_t opal_pci_map_pe_dma_window_real(uint64_t, uint64_t, uint16_t, + uint64_t, uint64_t); +int64_t opal_pci_reset(uint64_t, uint8_t, uint8_t); +int64_t opal_reinit_cpus(uint64_t); +int64_t opal_check_token(uint64_t); +int64_t opal_sensor_read(uint32_t, int, uint32_t *); +int64_t opal_ipmi_send(uint64_t, struct opal_ipmi_msg *, uint64_t); +int64_t opal_ipmi_recv(uint64_t, struct opal_ipmi_msg *, uint64_t *); +int64_t opal_console_flush(uint64_t); +int64_t opal_xive_reset(uint64_t); +int64_t opal_xive_get_irq_info(uint32_t, uint64_t *, uint64_t *, + uint64_t *, uint32_t *, uint32_t *); +int64_t opal_xive_get_irq_config(uint32_t, uint64_t *, uint8_t *, uint32_t *); +int64_t opal_xive_set_irq_config(uint32_t, uint64_t, uint8_t, uint32_t); +int64_t opal_xive_get_queue_info(uint64_t, uint8_t, uint64_t *, + uint64_t *, uint64_t *, uint32_t *, uint64_t *); +int64_t opal_xive_set_queue_info(uint64_t, uint8_t, uint64_t, + uint64_t, uint64_t); +int64_t opal_xive_get_vp_info(uint64_t, uint64_t *, uint64_t *, + uint64_t *, uint32_t *); +int64_t opal_xive_set_vp_info(uint64_t, uint64_t, uint64_t); +int64_t opal_xive_dump(uint32_t, uint32_t); +int64_t opal_sensor_read_u64(uint32_t, int, uint64_t *); + +void opal_printf(const char *fmt, ...); + +void *opal_intr_establish(uint64_t, int, int (*)(void *), void *); + +#endif + +#endif /* _MACHINE_OPAL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/openpromio.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/openpromio.h new file mode 100644 index 000000000000..e4f9fce47b1b --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/openpromio.h @@ -0,0 +1,57 @@ +/* $OpenBSD: openpromio.h,v 1.1 2020/06/27 21:39:05 kettenis Exp $ */ +/* $NetBSD: openpromio.h,v 1.1.1.1 1998/06/20 04:58:52 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)openpromio.h 8.1 (Berkeley) 6/11/93 + */ + +struct opiocdesc { + int op_nodeid; /* passed or returned node id */ + int op_namelen; /* length of op_name */ + char *op_name; /* pointer to field name */ + int op_buflen; /* length of op_buf (value-result) */ + char *op_buf; /* pointer to field value */ +}; + +#define OPIOCGET _IOWR('O', 1, struct opiocdesc) /* get openprom field */ +#define OPIOCSET _IOW('O', 2, struct opiocdesc) /* set openprom field */ +#define OPIOCNEXTPROP _IOWR('O', 3, struct opiocdesc) /* get next property */ +#define OPIOCGETOPTNODE _IOR('O', 4, int) /* get openprom field */ +#define OPIOCGETNEXT _IOWR('O', 5, int) /* get next node of node */ +#define OPIOCGETCHILD _IOWR('O', 6, int) /* get first child of node */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/param.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/param.h new file mode 100644 index 000000000000..00b5dc20577c --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/param.h @@ -0,0 +1,80 @@ +/* $OpenBSD: param.h,v 1.3 2025/07/07 18:33:37 kettenis Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ + +#ifdef _KERNEL +#ifndef _LOCORE +#include +#endif +#endif + +#define _MACHINE powerpc64 +#define MACHINE "powerpc64" +#define _MACHINE_ARCH powerpc64 +#define MACHINE_ARCH "powerpc64" +#define MID_MACHINE MID_POWERPC64 + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define PAGE_MASK (PAGE_SIZE - 1) + +#define KERNBASE 0xffffff8000000000ULL /* start of kernel virtual space */ + +#ifdef _KERNEL + +#define NBPG PAGE_SIZE /* bytes/page */ +#define PGSHIFT PAGE_SHIFT /* LOG2(PAGE_SIZE) */ +#define PGOFSET PAGE_MASK /* byte offset into page */ + +#define UPAGES 6 /* pages of u-area */ +#define USPACE (UPAGES * PAGE_SIZE) /* total size of u-area */ +#define USPACE_ALIGN 0 /* u-area alignment 0-none */ +#define __HAVE_USPACE_GUARD + +#define NMBCLUSTERS (64 * 1024) /* max cluster allocation */ + +#ifndef MSGBUFSIZE +#define MSGBUFSIZE (16 * PAGE_SIZE) /* default message buffer size */ +#endif + +#define STACKALIGNBYTES (32 - 1) +#define STACKALIGN(p) ((u_long)(p) &~ STACKALIGNBYTES) + +#define __HAVE_FDT + +#endif /* _KERNEL */ + +#endif /* _MACHINE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/pcb.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/pcb.h new file mode 100644 index 000000000000..58948188ec59 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/pcb.h @@ -0,0 +1,37 @@ +/* $OpenBSD: pcb.h,v 1.8 2021/01/09 13:14:02 kettenis Exp $ */ + +/* + * Copyright (c) 2020 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_PCB_H_ +#define _MACHINE_PCB_H_ + +#include +#include + +struct pcb { + register_t pcb_sp; + u_int pcb_flags; +#define PCB_FPU 0x000000001 +#define PCB_VEC 0x000000002 +#define PCB_VSX 0x000000004 + struct slb pcb_slb[32]; + vaddr_t pcb_onfault; + vaddr_t pcb_userva; + struct fpreg pcb_fpstate; +}; + +#endif /* _MACHINE_PCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/pci_machdep.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/pci_machdep.h new file mode 100644 index 000000000000..0f0168282f43 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/pci_machdep.h @@ -0,0 +1,134 @@ +/* $OpenBSD: pci_machdep.h,v 1.6 2024/05/22 05:51:49 jsg Exp $ */ + +/* + * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +typedef struct ppc64_pci_chipset *pci_chipset_tag_t; +typedef uint64_t pcitag_t; + +#define PCITAG_NODE(x) ((x) >> 32) +#define PCITAG_OFFSET(x) ((x) & 0xffffffff) + +/* Supported interrupt types. */ +#define PCI_NONE 0 +#define PCI_INTX 1 +#define PCI_MSI32 2 +#define PCI_MSI64 3 +#define PCI_MSIX 4 + +typedef struct { + pci_chipset_tag_t ih_pc; + pcitag_t ih_tag; + int ih_intrpin; + int ih_type; +} pci_intr_handle_t; + +struct pci_attach_args; + +/* + * powerpc64-specific PCI structure and type definitions. + * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE. + */ +struct ppc64_pci_chipset { + void *pc_conf_v; + void (*pc_attach_hook)(struct device *, + struct device *, struct pcibus_attach_args *); + int (*pc_bus_maxdevs)(void *, int); + pcitag_t (*pc_make_tag)(void *, int, int, int); + void (*pc_decompose_tag)(void *, pcitag_t, int *, + int *, int *); + int (*pc_conf_size)(void *, pcitag_t); + pcireg_t (*pc_conf_read)(void *, pcitag_t, int); + void (*pc_conf_write)(void *, pcitag_t, int, pcireg_t); + + void *pc_intr_v; + int (*pc_intr_map)(struct pci_attach_args *, + pci_intr_handle_t *); + int (*pc_intr_map_msi)(struct pci_attach_args *, + pci_intr_handle_t *); + int (*pc_intr_map_msix)(struct pci_attach_args *, + int, pci_intr_handle_t *); + const char *(*pc_intr_string)(void *, pci_intr_handle_t); + void *(*pc_intr_establish)(void *, pci_intr_handle_t, + int, struct cpu_info *, int (*)(void *), void *, + char *); + void (*pc_intr_disestablish)(void *, void *); +}; + +/* + * Functions provided to machine-independent PCI code. + */ +#define pci_attach_hook(p, s, pba) \ + (*(pba)->pba_pc->pc_attach_hook)((p), (s), (pba)) +#define pci_bus_maxdevs(c, b) \ + (*(c)->pc_bus_maxdevs)((c)->pc_conf_v, (b)) +#define pci_make_tag(c, b, d, f) \ + (*(c)->pc_make_tag)((c)->pc_conf_v, (b), (d), (f)) +#define pci_decompose_tag(c, t, bp, dp, fp) \ + (*(c)->pc_decompose_tag)((c)->pc_conf_v, (t), (bp), (dp), (fp)) +#define pci_conf_size(c, t) \ + (*(c)->pc_conf_size)((c)->pc_conf_v, (t)) +#define pci_conf_read(c, t, r) \ + (*(c)->pc_conf_read)((c)->pc_conf_v, (t), (r)) +#define pci_conf_write(c, t, r, v) \ + (*(c)->pc_conf_write)((c)->pc_conf_v, (t), (r), (v)) +#define pci_intr_map(c, ihp) \ + (*(c)->pa_pc->pc_intr_map)((c), (ihp)) +#define pci_intr_map_msi(c, ihp) \ + (*(c)->pa_pc->pc_intr_map_msi)((c), (ihp)) +#define pci_intr_map_msix(c, vec, ihp) \ + (*(c)->pa_pc->pc_intr_map_msix)((c), (vec), (ihp)) +#define pci_intr_string(c, ih) \ + (*(c)->pc_intr_string)((c)->pc_intr_v, (ih)) +#define pci_intr_establish(c, ih, l, h, a, nm) \ + (*(c)->pc_intr_establish)((c)->pc_intr_v, (ih), (l), NULL, (h), (a),\ + (nm)) +#define pci_intr_establish_cpu(c, ih, l, ci, h, a, nm) \ + (*(c)->pc_intr_establish)((c)->pc_intr_v, (ih), (l), (ci), (h), (a),\ + (nm)) +#define pci_intr_disestablish(c, iv) \ + (*(c)->pc_intr_disestablish)((c)->pc_intr_v, (iv)) +#define pci_probe_device_hook(c, a) (0) + +#define pci_min_powerstate(c, t) (PCI_PMCSR_STATE_D3) +#define pci_set_powerstate_md(c, t, s, p) + +#define pci_dev_postattach(a, b) + +void pci_mcfg_init(bus_space_tag_t, bus_addr_t, int, int, int); + +void pci_msi_enable(pci_chipset_tag_t, pcitag_t, bus_addr_t, uint32_t); +void pci_msix_enable(pci_chipset_tag_t, pcitag_t, bus_space_tag_t, + int, bus_addr_t, uint32_t); +int _pci_intr_map_msi(struct pci_attach_args *, pci_intr_handle_t *); +int _pci_intr_map_msix(struct pci_attach_args *, int, pci_intr_handle_t *); + +#define __HAVE_PCI_MSIX + +int pci_msix_table_map(pci_chipset_tag_t, pcitag_t, + bus_space_tag_t, bus_space_handle_t *); +void pci_msix_table_unmap(pci_chipset_tag_t, pcitag_t, + bus_space_tag_t, bus_space_handle_t); \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/pmap.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/pmap.h new file mode 100644 index 000000000000..661c2cf34dd4 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/pmap.h @@ -0,0 +1,98 @@ +/* $OpenBSD: pmap.h,v 1.19 2023/12/11 22:12:53 kettenis Exp $ */ + +/* + * Copyright (c) 2020 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_PMAP_H_ +#define _MACHINE_PMAP_H_ + +#include +#include + +#ifdef _KERNEL + +#include + +/* V->P mapping data */ +#define VP_IDX1_CNT 256 +#define VP_IDX1_MASK (VP_IDX1_CNT - 1) +#define VP_IDX1_POS 20 +#define VP_IDX2_CNT 256 +#define VP_IDX2_MASK (VP_IDX2_CNT - 1) +#define VP_IDX2_POS 12 + +struct pmap { + LIST_HEAD(,slb_desc) pm_slbd; + int pm_refs; + struct pmap_statistics pm_stats; + struct mutex pm_mtx; +}; + +typedef struct pmap *pmap_t; + +#define PG_PMAP_MOD PG_PMAP0 +#define PG_PMAP_REF PG_PMAP1 +#define PG_PMAP_EXE PG_PMAP2 +#define PG_PMAP_UC PG_PMAP3 + +#define PMAP_CACHE_DEFAULT 0 +#define PMAP_CACHE_CI 1 /* cache inhibit */ +#define PMAP_CACHE_WB 3 /* write-back cached */ + +/* + * MD flags that we use for pmap_enter (in the pa): + */ +#define PMAP_PA_MASK ~((paddr_t)PAGE_MASK) /* to remove the flags */ +#define PMAP_NOCACHE 0x1 /* map uncached */ + +extern struct pmap kernel_pmap_store; + +#define pmap_kernel() (&kernel_pmap_store) +#define pmap_resident_count(pm) ((pm)->pm_stats.resident_count) +#define pmap_wired_count(pm) ((pm)->pm_stats.wired_count) + +#define pmap_init_percpu() do { /* nothing */ } while (0) +#define pmap_unuse_final(p) +#define pmap_remove_holes(vm) +#define pmap_update(pm) + +void pmap_bootstrap(void); +void pmap_bootstrap_cpu(void); + +int pmap_slbd_fault(pmap_t, vaddr_t); +int pmap_slbd_enter(pmap_t, vaddr_t); +int pmap_set_user_slb(pmap_t, vaddr_t, vaddr_t *, vsize_t *); +void pmap_clear_user_slb(void); +void pmap_unset_user_slb(void); + +#ifdef DDB +struct pte; +struct pte *pmap_get_kernel_pte(vaddr_t); +#endif + +#endif /* _KERNEL */ + +struct vm_page_md { + struct mutex pv_mtx; + LIST_HEAD(,pte_desc) pv_list; +}; + +#define VM_MDPAGE_INIT(pg) do { \ + mtx_init(&(pg)->mdpage.pv_mtx, IPL_VM); \ + LIST_INIT(&((pg)->mdpage.pv_list)); \ +} while (0) + +#endif /* _MACHINE_PMAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/proc.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/proc.h new file mode 100644 index 000000000000..da21008f744a --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/proc.h @@ -0,0 +1,46 @@ +/* $OpenBSD: proc.h,v 1.3 2020/06/22 16:58:20 kettenis Exp $ */ + +/* + * Copyright (c) 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)proc.h 7.1 (Berkeley) 5/15/91 + */ + +#ifndef _MACHINE_PROC_H_ +#define _MACHINE_PROC_H_ + +/* + * Machine-dependent part of the proc structure for arm64. + */ +struct mdproc { + struct trapframe *md_regs; + volatile int md_astpending; + paddr_t md_user_slb_pa; +}; + +#endif /* _MACHINE_PROC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/profile.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/profile.h new file mode 100644 index 000000000000..a27eeba08c8a --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/profile.h @@ -0,0 +1,70 @@ +/* $OpenBSD: profile.h,v 1.1 2020/06/25 01:55:14 drahn Exp $ */ + +/* + * Copyright (c) 2020 Dale Rahn drahn@openbsd.org + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * mcount frame size skips over the red zone (288B) (calling function may use) + * and 128 bytes of local storage (32 bytes of reserved and 96 of our storage + * this function assumes it will only every call the local __mcount function + */ +#define MCOUNT \ +__asm__(" \n"\ + " .section \".text\" \n"\ + " .p2align 2 \n"\ + " .globl _mcount \n"\ + " .local __mcount \n"\ + " .type _mcount,@function \n"\ + "_mcount: \n"\ + ".L_mcount_gep0: \n"\ + " addis %r2, %r12, .TOC.-.L_mcount_gep0@ha; \n"\ + " addi %r2, %r2, .TOC.-.L_mcount_gep0@l; \n"\ + ".L_mcount_lep0: \n"\ + ".localentry _mcount, .L_mcount_lep0-.L_mcount_gep0; \n"\ + " ld %r11,16(%r1) \n"\ + " mflr %r0 \n"\ + " std %r0, 16(%r1) \n"\ + " stdu %r1,-(288+128)(%r1) \n"\ + " std %r3, 32(%r1) \n"\ + " std %r4, 40(%r1) \n"\ + " std %r5, 48(%r1) \n"\ + " std %r6, 56(%r1) \n"\ + " std %r7, 64(%r1) \n"\ + " std %r8, 72(%r1) \n"\ + " std %r9, 80(%r1) \n"\ + " std %r10,88(%r1) \n"\ + " std %r11,96(%r1) \n"\ + " mr %r4, %r0 \n"\ + " mr %r3, %r11 \n"\ + " bl __mcount \n"\ + " nop \n"\ + " ld %r3, 32(%r1) \n"\ + " ld %r4, 40(%r1) \n"\ + " ld %r5, 48(%r1) \n"\ + " ld %r6, 56(%r1) \n"\ + " ld %r7, 64(%r1) \n"\ + " ld %r8, 72(%r1) \n"\ + " ld %r9, 80(%r1) \n"\ + " ld %r10,88(%r1) \n"\ + " ld %r11,96(%r1) \n"\ + " addi %r1, %r1, (288+128) \n"\ + " ld %r0, 16(%r1) \n"\ + " std %r11,16(%r1) \n"\ + " mtlr %r0 \n"\ + " blr \n"\ + " .size _mcount, .-_mcount \n"\ + ); +#define _MCOUNT_DECL static void __mcount \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/psl.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/psl.h new file mode 100644 index 000000000000..13f2e488a542 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/psl.h @@ -0,0 +1,88 @@ +/* $OpenBSD: psl.h,v 1.3 2021/01/09 13:14:02 kettenis Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + * + * $NetBSD: psl.h,v 1.5 2000/11/19 19:52:37 matt Exp $ + */ + +#ifndef _MACHINE_PSL_H_ +#define _MACHINE_PSL_H_ + +/* + * Machine State Register (MSR) - All cores + */ +#define PSL_VEC 0x02000000UL /* AltiVec/SPE vector unit available */ +#define PSL_VSX 0x00800000UL /* Vector-Scalar unit available */ +#define PSL_EE 0x00008000UL /* external interrupt enable */ +#define PSL_PR 0x00004000UL /* privilege mode (1 == user) */ +#define PSL_FP 0x00002000UL /* floating point enable */ +#define PSL_ME 0x00001000UL /* machine check enable */ +#define PSL_FE0 0x00000800UL /* floating point interrupt mode 0 */ +#define PSL_FE1 0x00000100UL /* floating point interrupt mode 1 */ +#define PSL_PMM 0x00000004UL /* performance monitor mark */ +#define PSL_RI 0x00000002UL /* recoverable interrupt */ + +#define PSL_GS 0x10000000UL /* Guest state */ +#define PSL_UCLE 0x04000000UL /* User mode cache lock enable */ +#define PSL_WE 0x00040000UL /* Wait state enable */ +#define PSL_CE 0x00020000UL /* Critical interrupt enable */ +#define PSL_UBLE 0x00000400UL /* BTB lock enable - e500 only */ +#define PSL_DWE 0x00000400UL /* Debug Wait Enable - 440 only*/ +#define PSL_DE 0x00000200UL /* Debug interrupt enable */ +#define PSL_IS 0x00000020UL /* Instruction address space */ +#define PSL_DS 0x00000010UL /* Data address space */ + +#define PSL_SF 0x8000000000000000UL /* 64-bit addressing */ +#define PSL_HV 0x1000000000000000UL /* hyper-privileged mode */ + +#define PSL_POW 0x00040000UL /* power management */ +#define PSL_ILE 0x00010000UL /* interrupt endian mode (1 == le) */ +#define PSL_SE 0x00000400UL /* single-step trace enable */ +#define PSL_BE 0x00000200UL /* branch trace enable */ +#define PSL_IP 0x00000040UL /* interrupt prefix - 601 only */ +#define PSL_IR 0x00000020UL /* instruction address relocation */ +#define PSL_DR 0x00000010UL /* data address relocation */ +#define PSL_LE 0x00000001UL /* endian mode (1 == le) */ + +/* + * Floating-point exception modes: + */ +#define PSL_FE_DIS 0 /* none */ +#define PSL_FE_NONREC PSL_FE1 /* imprecise non-recoverable */ +#define PSL_FE_REC PSL_FE0 /* imprecise recoverable */ +#define PSL_FE_PREC (PSL_FE0 | PSL_FE1) /* precise */ +#define PSL_FE_DFLT PSL_FE_DIS /* default == none */ + +#define PSL_FPU (PSL_FP | PSL_FE_PREC) + +#endif /* _MACHINE_PSL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/pte.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/pte.h new file mode 100644 index 000000000000..b3e199c63501 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/pte.h @@ -0,0 +1,80 @@ +/* $OpenBSD: pte.h,v 1.8 2023/01/25 09:53:53 kettenis Exp $ */ + +/* + * Copyright (c) 2020 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_PTE_H_ +#define _MACHINE_PTE_H_ + +/* + * Page Table Entry bits that should work for all 64-bit POWER CPUs as + * well as the PowerPC 970. + */ + +struct pte { + uint64_t pte_hi; + uint64_t pte_lo; +}; + +/* High doubleword: */ +#define PTE_VALID 0x0000000000000001ULL +#define PTE_HID 0x0000000000000002ULL +#define PTE_WIRED 0x0000000000000008ULL /* SW */ +#define PTE_AVPN 0x3fffffffffffff80ULL +#define PTE_VSID_SHIFT 12 + +/* Low doubleword: */ +#define PTE_PP 0x0000000000000003ULL +#define PTE_RO 0x0000000000000003ULL +#define PTE_RW 0x0000000000000002ULL +#define PTE_N 0x0000000000000004ULL +#define PTE_G 0x0000000000000008ULL +#define PTE_M 0x0000000000000010ULL +#define PTE_I 0x0000000000000020ULL +#define PTE_W 0x0000000000000040ULL +#define PTE_CHG 0x0000000000000080ULL +#define PTE_REF 0x0000000000000100ULL +#define PTE_AC 0x0000000000000200ULL +#define PTE_RPGN 0x0ffffffffffff000ULL + +#define ADDR_PIDX 0x000000000ffff000ULL +#define ADDR_PIDX_SHIFT 12 +#define ADDR_ESID_SHIFT 28 +#define ADDR_VSID_SHIFT 28 + +struct pate { + uint64_t pate_htab; + uint64_t pate_prt; +}; + +#define SLBE_ESID_SHIFT 28 +#define SLBE_VALID 0x0000000008000000UL + +#define SLBV_VSID_SHIFT 12 + +struct slb { + uint64_t slb_slbe; + uint64_t slb_slbv; +}; + +#define VSID_VRMA 0x1ffffff + +#define USER_ADDR 0xcfffffff00000000ULL +#define USER_ESID (USER_ADDR >> ADDR_ESID_SHIFT) +#define SEGMENT_SIZE (256 * 1024 * 1024ULL) +#define SEGMENT_MASK (SEGMENT_SIZE - 1) + +#endif /* _MACHINE_PTE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/ptrace.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/ptrace.h new file mode 100644 index 000000000000..b77303a8fa1b --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/ptrace.h @@ -0,0 +1,44 @@ +/* $OpenBSD: ptrace.h,v 1.1 2020/05/16 17:11:14 kettenis Exp $ */ + +/* + * Copyright (c) 1993 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _POWERPC_PTRACE_H_ +#define _POWERPC_PTRACE_H_ + +/* + * powerpc64-dependent ptrace definitions + */ +#define PT_STEP (PT_FIRSTMACH + 0) +#define PT_GETREGS (PT_FIRSTMACH + 1) +#define PT_SETREGS (PT_FIRSTMACH + 2) +#define PT_GETFPREGS (PT_FIRSTMACH + 3) +#define PT_SETFPREGS (PT_FIRSTMACH + 4) + +#endif /* !_POWERPC_PTRACE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/reg.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/reg.h new file mode 100644 index 000000000000..037633d10aef --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/reg.h @@ -0,0 +1,39 @@ +/* $OpenBSD: reg.h,v 1.3 2020/07/14 09:41:30 kettenis Exp $ */ + +/* + * Copyright (c) 2020 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_REG_H_ +#define _MACHINE_REG_H_ + +struct reg { + uint64_t r_reg[32]; + uint64_t r_lr; + uint64_t r_cr; + uint64_t r_xer; + uint64_t r_ctr; + uint64_t r_pc; + uint64_t r_ps; +}; + +struct fpreg { + __uint128_t fp_vsx[64]; + uint64_t fp_fpscr; + uint64_t fp_vscr; + uint64_t fp_vrsave; +}; + +#endif /* !_MACHINE_REG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/reloc.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/reloc.h new file mode 100644 index 000000000000..f233ce24dc3b --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/reloc.h @@ -0,0 +1,148 @@ +/* $OpenBSD: reloc.h,v 1.2 2020/07/18 16:41:43 kettenis Exp $ */ + +/* + * Copyright (c) 2020 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_RELOC_H_ +#define _MACHINE_RELOC_H_ + +#define R_PPC64_NONE 0 +#define R_PPC64_ADDR32 1 +#define R_PPC64_ADDR24 2 +#define R_PPC64_ADDR16 3 +#define R_PPC64_ADDR16_LO 4 +#define R_PPC64_ADDR16_HI 5 +#define R_PPC64_ADDR16_HA 6 +#define R_PPC64_ADDR14 7 + +#define R_PPC64_REL24 10 +#define R_PPC64_REL14 11 + +#define R_PPC64_GOT16 14 +#define R_PPC64_GOT16_LO 15 +#define R_PPC64_GOT16_HI 16 +#define R_PPC64_GOT16_HA 17 + +#define R_PPC64_COPY 19 +#define R_PPC64_GLOB_DAT 20 +#define R_PPC64_JMP_SLOT 21 +#define R_PPC64_RELATIVE 22 + +#define R_PPC64_UADDR32 24 +#define R_PPC64_UADDR16 25 +#define R_PPC64_REL32 26 +#define R_PPC64_PLT32 27 +#define R_PPC64_PLTREL32 28 +#define R_PPC64_PLT16_LO 29 +#define R_PPC64_PLT16_HI 30 +#define R_PPC64_PLT16_HA 31 + +#define R_PPC64_SECTOFF 33 +#define R_PPC64_SECTOFF_LO 34 +#define R_PPC64_SECTOFF_HI 35 +#define R_PPC64_SECTOFF_HA 36 +#define R_PPC64_REL30 37 +#define R_PPC64_ADDR64 38 +#define R_PPC64_ADDR16_HIGHER 39 +#define R_PPC64_ADDR16_HIGHERA 40 +#define R_PPC64_ADDR16_HIGHEST 41 +#define R_PPC64_ADDR16_HIGHESTA 42 +#define R_PPC64_UADDR64 43 +#define R_PPC64_REL64 44 +#define R_PPC64_PLT64 45 +#define R_PPC64_PLTREL64 46 +#define R_PPC64_TOC16 47 +#define R_PPC64_TOC16_LO 48 +#define R_PPC64_TOC16_HI 49 +#define R_PPC64_TOC16_HA 50 +#define R_PPC64_TOC 51 +#define R_PPC64_PLTGOT16 52 +#define R_PPC64_PLTGOT16_LO 53 +#define R_PPC64_PLTGOT16_HI 54 +#define R_PPC64_PLTGOT16_HA 55 +#define R_PPC64_ADDR16_DS 56 +#define R_PPC64_ADDR16_LO_DS 57 +#define R_PPC64_GOT16_DS 58 +#define R_PPC64_GOT16_LO_DS 59 +#define R_PPC64_PLT16_LO_DS 60 +#define R_PPC64_SECTOFF_DS 61 +#define R_PPC64_SECTOFF_LO_DS 62 +#define R_PPC64_TOC16_DS 63 +#define R_PPC64_TOC16_LO_DS 64 +#define R_PPC64_PLTGOT16_DS 65 +#define R_PPC64_PLTGOT16_LO_DS 66 +#define R_PPC64_TLS 67 +#define R_PPC64_DTPMOD64 68 +#define R_PPC64_TPREL16 69 +#define R_PPC64_TPREL16_LO 70 +#define R_PPC64_TPREL16_HI 71 +#define R_PPC64_TPREL16_HA 72 +#define R_PPC64_TPREL64 73 +#define R_PPC64_DTPREL16 74 +#define R_PPC64_DTPREL16_LO 75 +#define R_PPC64_DTPREL16_HI 76 +#define R_PPC64_DTPREL16_HA 77 +#define R_PPC64_DTPREL64 78 +#define R_PPC64_GOT_TLSGD16 79 +#define R_PPC64_GOT_TLSGD16_LO 80 +#define R_PPC64_GOT_TLSGD16_HI 81 +#define R_PPC64_GOT_TLSGD16_HA 82 +#define R_PPC64_GOT_TLSD16 83 +#define R_PPC64_GOT_TLSD16_LO 84 +#define R_PPC64_GOT_TLSD16_HI 85 +#define R_PPC64_GOT_TLSD16_HA 86 +#define R_PPC64_GOT_TPREL16_DS 87 +#define R_PPC64_GOT_TPREL16_LO_DS 88 +#define R_PPC64_GOT_TPREL16_HI 89 +#define R_PPC64_GOT_TPREL16_HA 90 +#define R_PPC64_GOT_DTPREL16_DS 91 +#define R_PPC64_GOT_DTPREL16_LO_DS 92 +#define R_PPC64_GOT_DTPREL16_HI 93 +#define R_PPC64_GOT_DTPREL16_HA 94 +#define R_PPC64_TPREL16_DS 95 +#define R_PPC64_TPREL16_LO_DS 96 +#define R_PPC64_TPREL16_HIGHER 97 +#define R_PPC64_TPREL16_HIGHERA 98 +#define R_PPC64_TPREL16_HIGHEST 99 +#define R_PPC64_TPREL16_HIGHESTA 100 +#define R_PPC64_DTPREL16_DS 101 +#define R_PPC64_DTPREL16_LO_DS 102 +#define R_PPC64_DTPREL16_HIGHER 103 +#define R_PPC64_DTPREL16_HIGHERA 104 +#define R_PPC64_DTPREL16_HIGHEST 105 +#define R_PPC64_DTPREL16_HIGHESTA 106 +#define R_PPC64_TLSGD 107 +#define R_PPC64_TLSLD 108 +#define R_PPC64_TOCSAVE 109 +#define R_PPC64_ADDR16_HIGH 110 +#define R_PPC64_ADDR16_HIGHA 111 +#define R_PPC64_TPREL16_HIGH 112 +#define R_PPC64_TPREL16_HIGHA 113 +#define R_PPC64_DTPREL16_HIGH 114 +#define R_PPC64_DTPREL16_HIGHA 115 +#define R_PPC64_REL24_NOTOC 116 +#define R_PPC64_ADDR64_LOCAL 117 +#define R_PPC64_ENTRY 118 + +#define R_PPC64_IRELATIVE 248 +#define R_PPC64_REL16 249 +#define R_PPC64_REL16_LO 250 +#define R_PPC64_REL16_HI 251 +#define R_PPC64_REL16_HA 252 +#define R_PPC64_GNU_VTINHERIT 253 +#define R_PPC64_GNU_VTENTRY 254 + +#endif /* _MACHINE_RELOC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/setjmp.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/setjmp.h new file mode 100644 index 000000000000..02b53f759f42 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/setjmp.h @@ -0,0 +1,4 @@ +/* $OpenBSD: setjmp.h,v 1.1 2020/06/25 05:01:16 drahn Exp $ */ +/* $NetBSD: setjmp.h,v 1.1 1996/09/30 16:34:34 ws Exp $ */ + +#define _JBLEN 208 \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/signal.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/signal.h new file mode 100644 index 000000000000..68710820a2be --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/signal.h @@ -0,0 +1,65 @@ +/* $OpenBSD: signal.h,v 1.5 2020/07/13 22:37:37 kettenis Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 _MACHDEP_SIGNAL_H_ +#define _MACHDEP_SIGNAL_H_ + +#include + +typedef int sig_atomic_t; + +#if __BSD_VISIBLE || __XPG_VISIBLE >= 420 + +#include + +struct sigcontext { + long sc_cookie; + int sc_mask; /* saved signal mask */ + __register_t sc_reg[32]; /* saved registers */ + __register_t sc_lr; + __register_t sc_cr; + __register_t sc_xer; + __register_t sc_ctr; + __register_t sc_pc; + __register_t sc_ps; + __register_t sc_vrsave; + __uint128_t sc_vsx[64]; + __uint64_t sc_fpscr; + __uint64_t sc_vscr; +}; + +#define sc_sp sc_reg[1] + +#endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ + +#endif /* _MACHDEP_SIGNAL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/smbiosvar.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/smbiosvar.h new file mode 100644 index 000000000000..60200682ad10 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/smbiosvar.h @@ -0,0 +1,278 @@ +/* $OpenBSD: smbiosvar.h,v 1.3 2025/07/15 01:09:32 jsg Exp $ */ +/* + * Copyright (c) 2006 Gordon Willem Klok + * Copyright (c) 2005 Jordan Hargrave + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_SMBIOSVAR_ +#define _MACHINE_SMBIOSVAR_ + +#define SMBIOS_UUID_NPRESENT 0x1 +#define SMBIOS_UUID_NSET 0x2 + +/* + * Section 3.5 of "UUIDs and GUIDs" found at + * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt + * specifies the string representation of a UUID. + */ +#define SMBIOS_UUID_REP "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" +#define SMBIOS_UUID_REPLEN 37 /* 16 zero padded values, 4 hyphens, 1 null */ + +struct smbios_entry { + uint8_t mjr; + uint8_t min; + uint8_t *addr; + uint16_t len; + uint16_t count; +}; + +struct smbhdr { + uint32_t sig; /* "_SM_" */ + uint8_t checksum; /* Entry point checksum */ + uint8_t len; /* Entry point structure length */ + uint8_t majrev; /* Specification major revision */ + uint8_t minrev; /* Specification minor revision */ + uint16_t mss; /* Maximum Structure Size */ + uint8_t epr; /* Entry Point Revision */ + uint8_t fa[5]; /* value determined by EPR */ + uint8_t sasig[5]; /* Secondary Anchor "_DMI_" */ + uint8_t sachecksum; /* Secondary Checksum */ + uint16_t size; /* Length of structure table in bytes */ + uint32_t addr; /* Structure table address */ + uint16_t count; /* Number of SMBIOS structures */ + uint8_t rev; /* BCD revision */ +} __packed; + +struct smb3hdr { + uint8_t sig[5]; /* "_SM3_" */ + uint8_t checksum; /* Entry point structure checksum */ + uint8_t len; /* Entry point length */ + uint8_t majrev; /* SMBIOS major version */ + uint8_t minrev; /* SMBIOS minor version */ + uint8_t docrev; /* SMBIOS docrev */ + uint8_t epr; /* Entry point revision */ + uint8_t reserved; /* Reserved */ + uint32_t size; /* Structure table maximum size */ + uint64_t addr; /* Structure table address */ +} __packed; + +struct smbtblhdr { + uint8_t type; + uint8_t size; + uint16_t handle; +} __packed; + +struct smbtable { + struct smbtblhdr *hdr; + void *tblhdr; + uint32_t cookie; +}; + +#define SMBIOS_TYPE_BIOS 0 +#define SMBIOS_TYPE_SYSTEM 1 +#define SMBIOS_TYPE_BASEBOARD 2 +#define SMBIOS_TYPE_ENCLOSURE 3 +#define SMBIOS_TYPE_PROCESSOR 4 +#define SMBIOS_TYPE_MEMCTRL 5 +#define SMBIOS_TYPE_MEMMOD 6 +#define SMBIOS_TYPE_CACHE 7 +#define SMBIOS_TYPE_PORT 8 +#define SMBIOS_TYPE_SLOTS 9 +#define SMBIOS_TYPE_OBD 10 +#define SMBIOS_TYPE_OEM 11 +#define SMBIOS_TYPE_SYSCONFOPT 12 +#define SMBIOS_TYPE_BIOSLANG 13 +#define SMBIOS_TYPE_GROUPASSOC 14 +#define SMBIOS_TYPE_SYSEVENTLOG 15 +#define SMBIOS_TYPE_PHYMEM 16 +#define SMBIOS_TYPE_MEMDEV 17 +#define SMBIOS_TYPE_ECCINFO32 18 +#define SMBIOS_TYPE_MEMMAPARRAYADDR 19 +#define SMBIOS_TYPE_MEMMAPDEVADDR 20 +#define SMBIOS_TYPE_INBUILTPOINT 21 +#define SMBIOS_TYPE_PORTBATT 22 +#define SMBIOS_TYPE_SYSRESET 23 +#define SMBIOS_TYPE_HWSECUIRTY 24 +#define SMBIOS_TYPE_PWRCTRL 25 +#define SMBIOS_TYPE_VOLTPROBE 26 +#define SMBIOS_TYPE_COOLING 27 +#define SMBIOS_TYPE_TEMPPROBE 28 +#define SMBIOS_TYPE_CURRENTPROBE 29 +#define SMBIOS_TYPE_OOB_REMOTEACCESS 30 +#define SMBIOS_TYPE_BIS 31 +#define SMBIOS_TYPE_SBI 32 +#define SMBIOS_TYPE_ECCINFO64 33 +#define SMBIOS_TYPE_MGMTDEV 34 +#define SMBIOS_TYPE_MGTDEVCOMP 35 +#define SMBIOS_TYPE_MGTDEVTHRESH 36 +#define SMBIOS_TYPE_MEMCHANNEL 37 +#define SMBIOS_TYPE_IPMIDEV 38 +#define SMBIOS_TYPE_SPS 39 +#define SMBIOS_TYPE_INACTIVE 126 +#define SMBIOS_TYPE_EOT 127 + +/* + * SMBIOS Structure Type 0 "BIOS Information" + * DMTF Specification DSP0134 Section: 3.3.1 p.g. 34 + */ +struct smbios_struct_bios { + uint8_t vendor; /* string */ + uint8_t version; /* string */ + uint16_t startaddr; + uint8_t release; /* string */ + uint8_t romsize; + uint64_t characteristics; + uint32_t charext; + uint8_t major_rel; + uint8_t minor_rel; + uint8_t ecf_mjr_rel; /* embedded controller firmware */ + uint8_t ecf_min_rel; /* embedded controller firmware */ +} __packed; + +/* + * SMBIOS Structure Type 1 "System Information" + * DMTF Specification DSP0134 Section 3.3.2 p.g. 35 + */ + +struct smbios_sys { +/* SMBIOS spec 2.0+ */ + uint8_t vendor; /* string */ + uint8_t product; /* string */ + uint8_t version; /* string */ + uint8_t serial; /* string */ +/* SMBIOS spec 2.1+ */ + uint8_t uuid[16]; + uint8_t wakeup; +/* SMBIOS spec 2.4+ */ + uint8_t sku; /* string */ + uint8_t family; /* string */ +} __packed; + +/* + * SMBIOS Structure Type 2 "Base Board (Module) Information" + * DMTF Specification DSP0134 Section 3.3.3 p.g. 37 + */ +struct smbios_board { + uint8_t vendor; /* string */ + uint8_t product; /* string */ + uint8_t version; /* string */ + uint8_t serial; /* string */ + uint8_t asset; /* string */ + uint8_t feature; /* feature flags */ + uint8_t location; /* location in chassis */ + uint16_t handle; /* chassis handle */ + uint8_t type; /* board type */ + uint8_t noc; /* number of contained objects */ +} __packed; + +/* + * SMBIOS Structure Type 3 "System Enclosure or Chassis" + * DMTF Specification DSP0134 + */ +struct smbios_enclosure { + /* SMBIOS spec 2.0+ */ + uint8_t vendor; /* string */ + uint8_t type; + uint8_t version; /* string */ + uint8_t serial; /* string */ + uint8_t asset_tag; /* string */ + /* SMBIOS spec 2.1+ */ + uint8_t boot_state; + uint8_t psu_state; + uint8_t thermal_state; + uint8_t security_status; + /* SMBIOS spec 2.3+ */ + uint16_t oem_defined; + uint8_t height; + uint8_t no_power_cords; + uint8_t no_contained_element; + uint8_t reclen_contained_element; + uint8_t contained_elements; + /* SMBIOS spec 2.7+ */ + uint8_t sku; /* string */ +} __packed; + +/* + * SMBIOS Structure Type 4 "processor Information" + * DMTF Specification DSP0134 v2.5 Section 3.3.5 p.g. 24 + */ +struct smbios_cpu { + uint8_t cpu_socket_designation; /* string */ + uint8_t cpu_type; + uint8_t cpu_family; + uint8_t cpu_mfg; /* string */ + uint32_t cpu_id_eax; + uint32_t cpu_id_edx; + uint8_t cpu_version; /* string */ + uint8_t cpu_voltage; + uint16_t cpu_clock; + uint16_t cpu_max_speed; + uint16_t cpu_current_speed; + uint8_t cpu_status; +#define SMBIOS_CPUST_POPULATED (1<<6) +#define SMBIOS_CPUST_STATUSMASK (0x07) + uint8_t cpu_upgrade; + uint16_t cpu_l1_handle; + uint16_t cpu_l2_handle; + uint16_t cpu_l3_handle; + uint8_t cpu_serial; /* string */ + uint8_t cpu_asset_tag; /* string */ + uint8_t cpu_part_nr; /* string */ + /* following fields were added in smbios 2.5 */ + uint8_t cpu_core_count; + uint8_t cpu_core_enabled; + uint8_t cpu_thread_count; + uint16_t cpu_characteristics; +} __packed; + +/* + * SMBIOS Structure Type 38 "IPMI Information" + * DMTF Specification DSP0134 Section 3.3.39 p.g. 91 + */ +struct smbios_ipmi { + uint8_t smipmi_if_type; /* IPMI Interface Type */ + uint8_t smipmi_if_rev; /* BCD IPMI Revision */ + uint8_t smipmi_i2c_address; /* I2C address of BMC */ + uint8_t smipmi_nvram_address; /* I2C address of NVRAM + * storage */ + uint64_t smipmi_base_address; /* Base address of BMC (BAR + * format */ + uint8_t smipmi_base_flags; /* Flags field: + * bit 7:6 : register spacing + * 00 = byte + * 01 = dword + * 02 = word + * bit 4 : Lower bit BAR + * bit 3 : IRQ valid + * bit 2 : N/A + * bit 1 : Interrupt polarity + * bit 0 : Interrupt trigger */ + uint8_t smipmi_irq; /* IRQ if applicable */ +} __packed; + +int smbios_find_table(uint8_t, struct smbtable *); +char *smbios_get_string(struct smbtable *, uint8_t, char *, size_t); + +#endif \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/spinlock.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/spinlock.h new file mode 100644 index 000000000000..98555de9676f --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/spinlock.h @@ -0,0 +1,26 @@ +/* $OpenBSD: spinlock.h,v 1.1 2020/05/16 17:11:14 kettenis Exp $ */ + +/* + * Copyright (c) 2014 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_SPINLOCK_H_ +#define _MACHINE_SPINLOCK_H_ + +#define _ATOMIC_LOCK_UNLOCKED (0) +#define _ATOMIC_LOCK_LOCKED (1) +typedef int _atomic_lock_t; + +#endif \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/tcb.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/tcb.h new file mode 100644 index 000000000000..879efa9de8ec --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/tcb.h @@ -0,0 +1,42 @@ +/* $OpenBSD: tcb.h,v 1.4 2020/07/14 16:48:13 kettenis Exp $ */ + +/* + * Copyright (c) 2011 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TCB_H_ +#define _MACHINE_TCB_H_ + +#ifdef _KERNEL + +#define TCB_GET(p) \ + ((void *)(p)->p_md.md_regs->fixreg[13]) +#define TCB_SET(p, addr) \ + ((p)->p_md.md_regs->fixreg[13] = (__register_t)(addr)) + +#else /* _KERNEL */ + +/* ELF TLS ABI calls for small TCB, with static TLS data after it */ +#define TLS_VARIANT 1 + +/* powerpc offsets the TCB pointer 0x7000 bytes after the data */ +#define TCB_OFFSET 0x7008 + +register void *__tcb __asm__ ("r13"); +#define TCB_GET() (__tcb) +#define TCB_SET(tcb) ((__tcb) = (tcb)) + +#endif /* _KERNEL */ +#endif /* _MACHINE_TCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/timetc.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/timetc.h new file mode 100644 index 000000000000..9c07a63a5247 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/timetc.h @@ -0,0 +1,23 @@ +/* $OpenBSD: timetc.h,v 1.2 2022/11/05 16:23:02 cheloha Exp $ */ +/* + * Copyright (c) 2020 Paul Irofti + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TIMETC_H_ +#define _MACHINE_TIMETC_H_ + +#define TC_TB 1 + +#endif /* _MACHINE_TIMETC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/trap.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/trap.h new file mode 100644 index 000000000000..7e1ef37d2998 --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/trap.h @@ -0,0 +1,158 @@ +/* $OpenBSD: trap.h,v 1.9 2022/05/19 05:43:48 miod Exp $ */ +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + * + * $NetBSD: trap.h,v 1.7 2002/02/22 13:51:40 kleink Exp $ + */ + +#ifndef _MACHINE_TRAP_H_ +#define _MACHINE_TRAP_H_ + +#define EXC_RSVD 0x0000 /* Reserved */ +#define EXC_RST 0x0100 /* Reset; all but IBM4xx */ +#define EXC_MCHK 0x0200 /* Machine Check */ +#define EXC_DSI 0x0300 /* Data Storage Interrupt */ +#define EXC_DSE 0x0380 /* Data Segment Interrupt */ +#define EXC_ISI 0x0400 /* Instruction Storage Interrupt */ +#define EXC_ISE 0x0480 /* Instruction Segment Interrupt */ +#define EXC_EXI 0x0500 /* External Interrupt */ +#define EXC_ALI 0x0600 /* Alignment Interrupt */ +#define EXC_PGM 0x0700 /* Program Interrupt */ +#define EXC_FPU 0x0800 /* Floating-point Unavailable */ +#define EXC_DECR 0x0900 /* Decrementer Interrupt */ +#define EXC_SC 0x0c00 /* System Call */ +#define EXC_TRC 0x0d00 /* Trace */ +#define EXC_FPA 0x0e00 /* Floating-point Assist */ + +/* The following is only available on the 601: */ +#define EXC_RUNMODETRC 0x2000 /* Run Mode/Trace Exception */ + +/* The following are only available on 970(G5): */ +#define EXC_VECAST_G5 0x1700 /* AltiVec Assist */ + +/* The following are only available on 7400(G4): */ +#define EXC_VEC 0x0f20 /* AltiVec Unavailable */ +#define EXC_VECAST_G4 0x1600 /* AltiVec Assist */ + +/* The following are only available on 604/750/7400: */ +#define EXC_PERF 0x0f00 /* Performance Monitoring */ +#define EXC_BPT 0x1300 /* Instruction Breakpoint */ +#define EXC_SMI 0x1400 /* System Management Interrupt */ + +/* The following are only available on 750/7400: */ +#define EXC_THRM 0x1700 /* Thermal Management Interrupt */ + +/* And these are only on the 603: */ +#define EXC_IMISS 0x1000 /* Instruction translation miss */ +#define EXC_DLMISS 0x1100 /* Data load translation miss */ +#define EXC_DSMISS 0x1200 /* Data store translation miss */ + +/* Power ISA 2.06+: */ +#define EXC_HDSI 0x0e00 /* Hypervisor Data Storage */ +#define EXC_HISI 0x0e20 /* Hypervisor Instruction Storage */ +#define EXC_HEA 0x0e40 /* Hypervisor Emulation Assistance */ +#define EXC_HMI 0x0e60 /* Hypervisor Maintenance */ +#define EXC_VSX 0x0f40 /* VSX Unavailable */ + +/* Power ISA 2.07+: */ +#define EXC_FAC 0x0f60 /* Facility Unavailable */ +#define EXC_HFAC 0x0f80 /* Hypervisor Facility Unavailable */ + +/* Power ISA 3.0+: */ +#define EXC_HVI 0x0ea0 /* Hypervisor Virtualization */ + +/* The following are available on 4xx and 85xx */ +#define EXC_CRIT 0x0100 /* Critical Input Interrupt */ +#define EXC_PIT 0x1000 /* Programmable Interval Timer */ +#define EXC_FIT 0x1010 /* Fixed Interval Timer */ +#define EXC_WDOG 0x1020 /* Watchdog Timer */ +#define EXC_DTMISS 0x1100 /* Data TLB Miss */ +#define EXC_ITMISS 0x1200 /* Instruction TLB Miss */ +#define EXC_APU 0x1300 /* Auxiliary Processing Unit */ +#define EXC_DEBUG 0x2f10 /* Debug trap */ +#define EXC_VECAST_E 0x2f20 /* Altivec Assist (Book-E) */ +#define EXC_SPFPD 0x2f30 /* SPE Floating-point Data */ +#define EXC_SPFPR 0x2f40 /* SPE Floating-point Round */ + +/* POWER8 */ +#define EXC_SOFT_PATCH 0x1500 /* POWER8 Soft Patch Exception */ + +#define EXC_END 0x3000 /* End of exception vectors */ + +#define EXC_AST 0x3000 /* Fake AST vector */ + +/* Trap was in user mode */ +#define EXC_USER 0x10000 + + +/* + * EXC_ALI sets bits in the DSISR and DAR to provide enough + * information to recover from the unaligned access without needing to + * parse the offending instruction. This includes certain bits of the + * opcode, and information about what registers are used. The opcode + * indicator values below come from Appendix F of Book III of "The + * PowerPC Architecture". + */ + +#define EXC_ALI_OPCODE_INDICATOR(dsisr) ((dsisr >> 10) & 0x7f) +#define EXC_ALI_LFD 0x09 +#define EXC_ALI_STFD 0x0b + +/* Macros to extract register information */ +#define EXC_ALI_RST(dsisr) ((dsisr >> 5) & 0x1f) /* source or target */ +#define EXC_ALI_RA(dsisr) (dsisr & 0x1f) +#define EXC_ALI_INST_RST(instr) ((instr >> 21) & 0x1f) + +/* + * SRR1 bits for program exception traps. These identify what caused + * the program exception. See section 6.5.9 of the Power ISA Version + * 2.05. + */ + +#define EXC_PGM_FPENABLED (1UL << 20) +#define EXC_PGM_ILLEGAL (1UL << 19) +#define EXC_PGM_PRIV (1UL << 18) +#define EXC_PGM_TRAP (1UL << 17) + +/* + * DSISR bits. + */ + +#define DSISR_STORE (1UL << 25) + +/* Magic pointers to store trap handler entry points */ +#define TRAP_ENTRY 0x1f8 +#define TRAP_HVENTRY 0x1f0 +#define TRAP_SLBENTRY 0x1e8 +#define TRAP_RSTENTRY 0x1e0 + +#endif /* _MACHINE_TRAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/powerpc64-openbsd-none/powerpc64/vmparam.h b/lib/libc/include/powerpc64-openbsd-none/powerpc64/vmparam.h new file mode 100644 index 000000000000..4cad35a1a2ef --- /dev/null +++ b/lib/libc/include/powerpc64-openbsd-none/powerpc64/vmparam.h @@ -0,0 +1,53 @@ +/* + * Machine dependent constants for powerpc64. + */ + +#define USRSTACK VM_MAXUSER_ADDRESS + +/* + * Virtual memory related constants, all in bytes + */ +#define MAXTSIZ ((paddr_t)256*1024*1024) /* max text size */ +#ifndef DFLDSIZ +#define DFLDSIZ ((paddr_t)512*1024*1024) /* initial data size limit */ +#endif +#ifndef MAXDSIZ +#define MAXDSIZ ((paddr_t)32*1024*1024*1024) /* max data size */ +#endif +#ifndef BRKSIZ +#define BRKSIZ ((paddr_t)16*1024*1024*1024) /* heap gap size */ +#endif +#ifndef DFLSSIZ +#define DFLSSIZ ((paddr_t)2*1024*1024) /* initial stack size limit */ +#endif +#ifndef MAXSSIZ +#define MAXSSIZ ((paddr_t)32*1024*1024) /* max stack size */ +#endif + +#define STACKGAP_RANDOM 256*1024 + +/* + * Size of shared memory map + */ +#ifndef SHMMAXPGS +#define SHMMAXPGS 1024 +#endif + +/* + * Size of User Raw I/O map + */ +#define USRIOSIZE 300 + +#define VM_PHYS_SIZE (USRIOSIZE * PAGE_SIZE) + +#define VM_PHYSSEG_MAX 32 +#define VM_PHYSSEG_STRAT VM_PSTRAT_BSEARCH + +#define VM_MIN_ADDRESS ((vaddr_t)PAGE_SIZE) +#define VM_MAXUSER_ADDRESS 0xbffffffffffff000UL +#define VM_MAX_ADDRESS 0xffffffffffffffffUL +#ifdef _KERNEL +#define VM_MIN_STACK_ADDRESS 0x9000000000000000UL +#endif +#define VM_MIN_KERNEL_ADDRESS 0xc000000000000000UL +#define VM_MAX_KERNEL_ADDRESS 0xc0000007ffffffffUL \ No newline at end of file diff --git a/lib/libc/include/riscv64-freebsd-none/fenv.h b/lib/libc/include/riscv64-freebsd-none/fenv.h index bb4faebfbd3b..7946a71dc875 100644 --- a/lib/libc/include/riscv64-freebsd-none/fenv.h +++ b/lib/libc/include/riscv64-freebsd-none/fenv.h @@ -36,6 +36,7 @@ #ifndef _FENV_H_ #define _FENV_H_ +#include #include #ifndef __fenv_static @@ -71,32 +72,13 @@ __BEGIN_DECLS extern const fenv_t __fe_dfl_env; #define FE_DFL_ENV (&__fe_dfl_env) -#if !defined(__riscv_float_abi_soft) && !defined(__riscv_float_abi_double) -#if defined(__riscv_float_abi_single) -#error single precision floating point ABI not supported -#else -#error compiler did not set soft/hard float macros -#endif +#ifndef __riscv_float_abi_double +#error only double hard float ABI supported #endif -#ifndef __riscv_float_abi_soft #define __rfs(__fcsr) __asm __volatile("csrr %0, fcsr" : "=r" (__fcsr)) #define __wfs(__fcsr) __asm __volatile("csrw fcsr, %0" :: "r" (__fcsr)) -#endif -#ifdef __riscv_float_abi_soft -int feclearexcept(int __excepts); -int fegetexceptflag(fexcept_t *__flagp, int __excepts); -int fesetexceptflag(const fexcept_t *__flagp, int __excepts); -int feraiseexcept(int __excepts); -int fetestexcept(int __excepts); -int fegetround(void); -int fesetround(int __round); -int fegetenv(fenv_t *__envp); -int feholdexcept(fenv_t *__envp); -int fesetenv(const fenv_t *__envp); -int feupdateenv(const fenv_t *__envp); -#else __fenv_static inline int feclearexcept(int __excepts) { @@ -212,15 +194,9 @@ feupdateenv(const fenv_t *__envp) return (0); } -#endif /* !__riscv_float_abi_soft */ #if __BSD_VISIBLE -#ifdef __riscv_float_abi_soft -int feenableexcept(int __mask); -int fedisableexcept(int __mask); -int fegetexcept(void); -#else __fenv_static inline int feenableexcept(int __mask __unused) { @@ -248,7 +224,6 @@ fegetexcept(void) return (0); } -#endif /* !__riscv_float_abi_soft */ #endif /* __BSD_VISIBLE */ diff --git a/lib/libc/include/riscv64-freebsd-none/float.h b/lib/libc/include/riscv64-freebsd-none/float.h index ade407a51cf1..38b5696e5a3e 100644 --- a/lib/libc/include/riscv64-freebsd-none/float.h +++ b/lib/libc/include/riscv64-freebsd-none/float.h @@ -25,8 +25,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)float.h 7.1 (Berkeley) 5/8/90 */ #ifndef _MACHINE_FLOAT_H_ diff --git a/lib/libc/include/riscv64-freebsd-none/machine/_align.h b/lib/libc/include/riscv64-freebsd-none/machine/_align.h index 2e412076b802..92180fbd2064 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/_align.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/_align.h @@ -25,8 +25,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)param.h 5.8 (Berkeley) 6/28/91 */ #ifndef _MACHINE__ALIGN_H_ diff --git a/lib/libc/include/riscv64-freebsd-none/machine/_bus.h b/lib/libc/include/riscv64-freebsd-none/machine/_bus.h deleted file mode 100644 index 8e9a287dc2ee..000000000000 --- a/lib/libc/include/riscv64-freebsd-none/machine/_bus.h +++ /dev/null @@ -1,43 +0,0 @@ -/*- - * Copyright (c) 2005 M. Warner Losh - * - * 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, - * without modification, immediately at the beginning of the file. - * 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 _MACHINE__BUS_H_ -#define _MACHINE__BUS_H_ - -/* - * Addresses (in bus space). - */ -typedef u_long bus_addr_t; -typedef u_long bus_size_t; - -/* - * Access methods for bus space. - */ -typedef u_long bus_space_handle_t; -typedef struct bus_space *bus_space_tag_t; - -#endif /* !_MACHINE__BUS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-freebsd-none/machine/_limits.h b/lib/libc/include/riscv64-freebsd-none/machine/_limits.h index 0f4f32ce8512..d23300e5b029 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/_limits.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/_limits.h @@ -22,8 +22,6 @@ * 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. - * - * @(#)limits.h 8.3 (Berkeley) 1/4/94 */ #ifndef _MACHINE__LIMITS_H_ diff --git a/lib/libc/include/riscv64-freebsd-none/machine/_types.h b/lib/libc/include/riscv64-freebsd-none/machine/_types.h index 1c8957ffd1a5..a47d3b205e8e 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/_types.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/_types.h @@ -26,9 +26,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * From: @(#)ansi.h 8.2 (Berkeley) 1/4/94 - * From: @(#)types.h 8.3 (Berkeley) 1/5/94 */ #ifndef _MACHINE__TYPES_H_ diff --git a/lib/libc/include/riscv64-freebsd-none/machine/asm.h b/lib/libc/include/riscv64-freebsd-none/machine/asm.h index 0486779337db..9805134544d8 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/asm.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/asm.h @@ -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_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-freebsd-none/machine/atomic.h b/lib/libc/include/riscv64-freebsd-none/machine/atomic.h index 7fbe86c2bf92..c0d1320ad44c 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/atomic.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/atomic.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2015 Ruslan Bukin + * Copyright (c) 2015-2024 Ruslan Bukin * All rights reserved. * * Portions of this software were developed by SRI International and the @@ -105,8 +105,6 @@ atomic_fcmpset_rel_##WIDTH(__volatile uint##WIDTH##_t *p, \ ATOMIC_CMPSET_ACQ_REL(8); ATOMIC_FCMPSET_ACQ_REL(8); -ATOMIC_CMPSET_ACQ_REL(16); -ATOMIC_FCMPSET_ACQ_REL(16); #define atomic_cmpset_char atomic_cmpset_8 #define atomic_cmpset_acq_char atomic_cmpset_acq_8 @@ -116,11 +114,40 @@ ATOMIC_FCMPSET_ACQ_REL(16); #define atomic_fcmpset_rel_char atomic_fcmpset_rel_8 #define atomic_cmpset_short atomic_cmpset_16 -#define atomic_cmpset_acq_short atomic_cmpset_acq_16 -#define atomic_cmpset_rel_short atomic_cmpset_rel_16 #define atomic_fcmpset_short atomic_fcmpset_16 + +ATOMIC_CMPSET_ACQ_REL(16); +ATOMIC_FCMPSET_ACQ_REL(16); + +#define atomic_load_acq_16 atomic_load_acq_16 +static __inline uint16_t +atomic_load_acq_16(const volatile uint16_t *p) +{ + uint16_t ret; + + ret = *p; + + fence(); + + return (ret); +} + +static __inline void +atomic_store_rel_16(volatile uint16_t *p, uint16_t val) +{ + + fence(); + + *p = val; +} + +#define atomic_cmpset_acq_short atomic_cmpset_acq_16 #define atomic_fcmpset_acq_short atomic_fcmpset_acq_16 +#define atomic_load_acq_short atomic_load_acq_16 + +#define atomic_cmpset_rel_short atomic_cmpset_rel_16 #define atomic_fcmpset_rel_short atomic_fcmpset_rel_16 +#define atomic_store_rel_short atomic_store_rel_16 static __inline void atomic_add_32(volatile uint32_t *p, uint32_t val) @@ -239,6 +266,34 @@ atomic_readandclear_32(volatile uint32_t *p) return (ret); } +static __inline int +atomic_testandclear_32(volatile uint32_t *p, u_int val) +{ + uint32_t mask, old; + + mask = 1u << (val & 31); + __asm __volatile("amoand.w %0, %2, %1" + : "=&r" (old), "+A" (*p) + : "r" (~mask) + : "memory"); + + return ((old & mask) != 0); +} + +static __inline int +atomic_testandset_32(volatile uint32_t *p, u_int val) +{ + uint32_t mask, old; + + mask = 1u << (val & 31); + __asm __volatile("amoor.w %0, %2, %1" + : "=&r" (old), "+A" (*p) + : "r" (mask) + : "memory"); + + return ((old & mask) != 0); +} + #define atomic_add_int atomic_add_32 #define atomic_clear_int atomic_clear_32 #define atomic_cmpset_int atomic_cmpset_32 @@ -257,7 +312,7 @@ ATOMIC_CMPSET_ACQ_REL(32); ATOMIC_FCMPSET_ACQ_REL(32); static __inline uint32_t -atomic_load_acq_32(volatile uint32_t *p) +atomic_load_acq_32(const volatile uint32_t *p) { uint32_t ret; @@ -410,6 +465,48 @@ atomic_readandclear_64(volatile uint64_t *p) return (ret); } +static __inline int +atomic_testandclear_64(volatile uint64_t *p, u_int val) +{ + uint64_t mask, old; + + mask = 1ul << (val & 63); + __asm __volatile("amoand.d %0, %2, %1" + : "=&r" (old), "+A" (*p) + : "r" (~mask) + : "memory"); + + return ((old & mask) != 0); +} + +static __inline int +atomic_testandset_64(volatile uint64_t *p, u_int val) +{ + uint64_t mask, old; + + mask = 1ul << (val & 63); + __asm __volatile("amoor.d %0, %2, %1" + : "=&r" (old), "+A" (*p) + : "r" (mask) + : "memory"); + + return ((old & mask) != 0); +} + +static __inline int +atomic_testandset_acq_64(volatile uint64_t *p, u_int val) +{ + uint64_t mask, old; + + mask = 1ul << (val & 63); + __asm __volatile("amoor.d.aq %0, %2, %1" + : "=&r" (old), "+A" (*p) + : "r" (mask) + : "memory"); + + return ((old & mask) != 0); +} + static __inline uint32_t atomic_swap_32(volatile uint32_t *p, uint32_t val) { @@ -447,6 +544,9 @@ atomic_swap_64(volatile uint64_t *p, uint64_t val) #define atomic_set_long atomic_set_64 #define atomic_subtract_long atomic_subtract_64 #define atomic_swap_long atomic_swap_64 +#define atomic_testandclear_long atomic_testandclear_64 +#define atomic_testandset_long atomic_testandset_64 +#define atomic_testandset_acq_long atomic_testandset_acq_64 #define atomic_add_ptr atomic_add_64 #define atomic_clear_ptr atomic_clear_64 @@ -457,6 +557,8 @@ atomic_swap_64(volatile uint64_t *p, uint64_t val) #define atomic_set_ptr atomic_set_64 #define atomic_subtract_ptr atomic_subtract_64 #define atomic_swap_ptr atomic_swap_64 +#define atomic_testandclear_ptr atomic_testandclear_64 +#define atomic_testandset_ptr atomic_testandset_64 ATOMIC_ACQ_REL(set, 64) ATOMIC_ACQ_REL(clear, 64) @@ -467,7 +569,7 @@ ATOMIC_CMPSET_ACQ_REL(64); ATOMIC_FCMPSET_ACQ_REL(64); static __inline uint64_t -atomic_load_acq_64(volatile uint64_t *p) +atomic_load_acq_64(const volatile uint64_t *p) { uint64_t ret; @@ -554,4 +656,7 @@ atomic_thread_fence_seq_cst(void) #include +#define atomic_set_short atomic_set_16 +#define atomic_clear_short atomic_clear_16 + #endif /* _MACHINE_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-freebsd-none/machine/bus_dma.h b/lib/libc/include/riscv64-freebsd-none/machine/bus_dma.h index b54730aa0ae8..05460bd4e685 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/bus_dma.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/bus_dma.h @@ -49,7 +49,7 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, /* * Free a piece of memory and it's allociated dmamap, that was allocated - * via bus_dmamem_alloc. Make the same choice for free/contigfree. + * via bus_dmamem_alloc. */ static inline void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) diff --git a/lib/libc/include/riscv64-freebsd-none/machine/bus_dma_impl.h b/lib/libc/include/riscv64-freebsd-none/machine/bus_dma_impl.h index bda4ea6b2c6f..cbded0b9660e 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/bus_dma_impl.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/bus_dma_impl.h @@ -31,27 +31,22 @@ struct bus_dma_tag_common { struct bus_dma_impl *impl; - struct bus_dma_tag_common *parent; bus_size_t alignment; bus_addr_t boundary; bus_addr_t lowaddr; bus_addr_t highaddr; - bus_dma_filter_t *filter; - void *filterarg; bus_size_t maxsize; u_int nsegments; bus_size_t maxsegsz; int flags; bus_dma_lock_t *lockfunc; void *lockfuncarg; - int ref_count; }; struct bus_dma_impl { int (*tag_create)(bus_dma_tag_t parent, bus_size_t alignment, bus_addr_t boundary, bus_addr_t lowaddr, - bus_addr_t highaddr, bus_dma_filter_t *filter, - void *filterarg, bus_size_t maxsize, int nsegments, + bus_addr_t highaddr, bus_size_t maxsize, int nsegments, bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc, void *lockfuncarg, bus_dma_tag_t *dmat); int (*tag_destroy)(bus_dma_tag_t dmat); @@ -79,13 +74,11 @@ struct bus_dma_impl { bus_dmasync_op_t op); }; -int bus_dma_run_filter(struct bus_dma_tag_common *dmat, bus_addr_t paddr); int common_bus_dma_tag_create(struct bus_dma_tag_common *parent, bus_size_t alignment, bus_addr_t boundary, bus_addr_t lowaddr, bus_addr_t highaddr, - bus_dma_filter_t *filter, void *filterarg, bus_size_t maxsize, - int nsegments, bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc, - void *lockfuncarg, size_t sz, void **dmat); + bus_size_t maxsize, int nsegments, bus_size_t maxsegsz, int flags, + bus_dma_lock_t *lockfunc, void *lockfuncarg, size_t sz, void **dmat); extern struct bus_dma_impl bus_dma_bounce_impl; diff --git a/lib/libc/include/riscv64-freebsd-none/machine/cbo.h b/lib/libc/include/riscv64-freebsd-none/machine/cbo.h new file mode 100644 index 000000000000..ce8baf79d9ae --- /dev/null +++ b/lib/libc/include/riscv64-freebsd-none/machine/cbo.h @@ -0,0 +1,33 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Ruslan Bukin + * + * 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_CBO_H_ +#define _RISCV_CBO_H_ + +void cbo_zicbom_setup_cache(int cbom_block_size); + +#endif /* _RISCV_CBO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-freebsd-none/machine/cpu.h b/lib/libc/include/riscv64-freebsd-none/machine/cpu.h index 12f823d7ee3c..1d840b451f87 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/cpu.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/cpu.h @@ -35,9 +35,11 @@ #ifndef _MACHINE_CPU_H_ #define _MACHINE_CPU_H_ +#ifndef LOCORE #include #include #include +#endif #define TRAPF_PC(tfp) ((tfp)->tf_sepc) #define TRAPF_USERMODE(tfp) (((tfp)->tf_sstatus & SSTATUS_SPP) == 0) @@ -47,8 +49,6 @@ #define cpu_spinwait() /* nothing */ #define cpu_lock_delay() DELAY(1) -#ifdef _KERNEL - /* * Core manufacturer IDs, as reported by the mvendorid CSR. */ @@ -80,6 +80,7 @@ /* SiFive marchid values */ #define MARCHID_SIFIVE_U7 MARCHID_COMMERCIAL(7) +#define MARCHID_SIFIVE_P5 MARCHID_COMMERCIAL(8) /* * MMU virtual-addressing modes. Support for each level implies the previous, @@ -89,6 +90,9 @@ #define MMU_SV48 0x2 /* 4-level paging */ #define MMU_SV57 0x4 /* 5-level paging */ +#ifdef _KERNEL +#ifndef LOCORE + extern char btext[]; extern char etext[]; @@ -105,6 +109,7 @@ get_cyclecount(void) return (rdcycle()); } -#endif +#endif /* !LOCORE */ +#endif /* _KERNEL */ #endif /* !_MACHINE_CPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-freebsd-none/machine/cpufunc.h b/lib/libc/include/riscv64-freebsd-none/machine/cpufunc.h index 23af7f81fb9e..df60a9a0f88e 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/cpufunc.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/cpufunc.h @@ -44,6 +44,8 @@ breakpoint(void) #ifdef _KERNEL +#include + #include static __inline register_t @@ -102,21 +104,62 @@ sfence_vma_page(uintptr_t addr) __asm __volatile("sfence.vma %0" :: "r" (addr) : "memory"); } +static __inline void +sfence_vma_asid(uint64_t asid) +{ + + __asm __volatile("sfence.vma x0, %0" :: "r" (asid) : "memory"); +} + +static __inline void +sfence_vma_asid_page(uint64_t asid, uintptr_t addr) +{ + + __asm __volatile("sfence.vma %0, %1" :: "r" (addr), "r" (asid) + : "memory"); +} + #define rdcycle() csr_read64(cycle) #define rdtime() csr_read64(time) #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); + +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); +} -#define cpu_idcache_wbinv_range(a, s) -#define cpu_icache_sync_range(a, s) -#define cpu_icache_sync_range_checked(a, s) +void riscv_cache_install_hooks(struct riscv_cache_ops *, u_int); #define cpufunc_nullop() riscv_nullop() diff --git a/lib/libc/include/riscv64-freebsd-none/machine/elf.h b/lib/libc/include/riscv64-freebsd-none/machine/elf.h index aab0b1713afb..9533750a8eeb 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/elf.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/elf.h @@ -80,7 +80,9 @@ __ElfType(Auxinfo); #define HWCAP_ISA_F HWCAP_ISA_BIT('f') #define HWCAP_ISA_D HWCAP_ISA_BIT('d') #define HWCAP_ISA_C HWCAP_ISA_BIT('c') +#define HWCAP_ISA_H HWCAP_ISA_BIT('h') #define HWCAP_ISA_G \ (HWCAP_ISA_I | HWCAP_ISA_M | HWCAP_ISA_A | HWCAP_ISA_F | HWCAP_ISA_D) +#define HWCAP_ISA_B HWCAP_ISA_BIT('b') #endif /* !_MACHINE_ELF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-freebsd-none/machine/endian.h b/lib/libc/include/riscv64-freebsd-none/machine/endian.h index 69d16e3fc53c..6b21c3cb51ce 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/endian.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/endian.h @@ -24,8 +24,6 @@ * 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. - * - * @(#)endian.h 8.1 (Berkeley) 6/10/93 * $NetBSD: endian.h,v 1.7 1999/08/21 05:53:51 simonb Exp $ */ diff --git a/lib/libc/include/riscv64-freebsd-none/machine/float.h b/lib/libc/include/riscv64-freebsd-none/machine/float.h index ade407a51cf1..38b5696e5a3e 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/float.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/float.h @@ -25,8 +25,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)float.h 7.1 (Berkeley) 5/8/90 */ #ifndef _MACHINE_FLOAT_H_ diff --git a/lib/libc/include/riscv64-freebsd-none/machine/fpe.h b/lib/libc/include/riscv64-freebsd-none/machine/fpe.h index 0b62e481e316..7cdbca94990e 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/fpe.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/fpe.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2016 Ruslan Bukin + * Copyright (c) 2016-2024 Ruslan Bukin * All rights reserved. * * This software was developed by SRI International and the University of @@ -34,4 +34,14 @@ void fpe_state_save(struct thread *td); void fpe_state_clear(void); +struct fpreg *fpu_save_area_alloc(void); +void fpu_save_area_free(struct fpreg *fsa); +void fpu_save_area_reset(struct fpreg *fsa); + +void fpe_enable(void); +void fpe_disable(void); + +void fpe_store(struct fpreg *state); +void fpe_restore(struct fpreg *state); + #endif /* !_MACHINE_FPE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-freebsd-none/machine/frame.h b/lib/libc/include/riscv64-freebsd-none/machine/frame.h index c05590e2dee5..58aec0107c44 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/frame.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/frame.h @@ -57,6 +57,10 @@ struct trapframe { uint64_t tf_scause; }; +#ifdef _KERNEL +#define TF_SIZE (roundup2(sizeof(struct trapframe), STACKALIGNBYTES + 1)) +#endif + /* * Signal frame. Pushed onto user stack before calling sigcode. */ @@ -65,6 +69,16 @@ struct sigframe { ucontext_t sf_uc; /* actual saved ucontext */ }; +#ifdef _KERNEL +/* + * Kernel frame. Reserved near the top of kernel stacks for saving kernel + * state while in userspace. + */ +struct kernframe { + register_t kf_tp; +}; +#endif + #endif /* !LOCORE */ /* Definitions for syscalls */ diff --git a/lib/libc/include/riscv64-freebsd-none/machine/ifunc.h b/lib/libc/include/riscv64-freebsd-none/machine/ifunc.h new file mode 100644 index 000000000000..5ef7dfe31d9b --- /dev/null +++ b/lib/libc/include/riscv64-freebsd-none/machine/ifunc.h @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 2015-2018 The FreeBSD Foundation + * Copyright (c) 2024 Jessica Clarke + * + * Part of this software was developed by Konstantin Belousov + * 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_IFUNC_H +#define __RISCV_IFUNC_H + +#define DEFINE_IFUNC(qual, ret_type, name, args) \ + static ret_type (*name##_resolver(void))args __used; \ + qual ret_type name args __attribute__((ifunc(#name "_resolver"))); \ + static ret_type (*name##_resolver(void))args + +#define DEFINE_UIFUNC(qual, ret_type, name, args) \ + static ret_type (*name##_resolver(unsigned long, unsigned long, \ + unsigned long, unsigned long, unsigned long, unsigned long, \ + unsigned long, unsigned long))args __used; \ + qual ret_type name args __attribute__((ifunc(#name "_resolver"))); \ + static ret_type (*name##_resolver(unsigned long elf_hwcap __unused, \ + unsigned long _arg2 __unused, unsigned long _arg3 __unused, \ + unsigned long _arg4 __unused, unsigned long _arg5 __unused, \ + unsigned long _arg6 __unused, unsigned long _arg7 __unused, \ + unsigned long _arg8 __unused))args + +#endif \ No newline at end of file diff --git a/lib/libc/include/riscv64-freebsd-none/machine/in_cksum.h b/lib/libc/include/riscv64-freebsd-none/machine/in_cksum.h index b6519929ca3c..ad5bd81eae39 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/in_cksum.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/in_cksum.h @@ -27,7 +27,6 @@ * SUCH DAMAGE. * * from tahoe: in_cksum.c 1.2 86/01/05 - * from: @(#)in_cksum.c 1.3 (Berkeley) 1/19/91 * from: Id: in_cksum.c,v 1.8 1995/12/03 18:35:19 bde Exp */ diff --git a/lib/libc/include/riscv64-freebsd-none/machine/intr.h b/lib/libc/include/riscv64-freebsd-none/machine/intr.h index f5e919f401c9..6a3a88998bac 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/intr.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/intr.h @@ -39,8 +39,7 @@ #define NIRQ 1024 #endif -#include - +#ifndef LOCORE enum { IRQ_SOFTWARE_USER, IRQ_SOFTWARE_SUPERVISOR, @@ -55,5 +54,9 @@ enum { IRQ_EXTERNAL_HYPERVISOR, IRQ_EXTERNAL_MACHINE, }; +#endif /* !LOCORE */ + +#define INTR_ROOT_IRQ 0 +#define INTR_ROOT_COUNT 1 #endif /* !_MACHINE_INTR_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-freebsd-none/machine/machdep.h b/lib/libc/include/riscv64-freebsd-none/machine/machdep.h index 9830497cfb4f..d8876c847bed 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/machdep.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/machdep.h @@ -36,10 +36,8 @@ #define _MACHINE_MACHDEP_H_ struct riscv_bootparams { - vm_offset_t kern_l1pt; /* Kernel L1 base */ vm_offset_t kern_phys; /* Kernel base (physical) addr */ vm_offset_t kern_stack; - vm_offset_t dtbp_virt; /* Device tree blob virtual addr */ vm_offset_t dtbp_phys; /* Device tree blob physical addr */ vm_offset_t modulep; /* loader(8) metadata */ }; diff --git a/lib/libc/include/riscv64-freebsd-none/machine/md_var.h b/lib/libc/include/riscv64-freebsd-none/machine/md_var.h index 3022f4e02f7a..53b2cf27f792 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/md_var.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/md_var.h @@ -42,8 +42,10 @@ extern register_t mimpid; extern u_int mmu_caps; /* Supervisor-mode extension support */ +extern bool has_hyp; extern bool has_sstc; extern bool has_sscofpmf; +extern bool has_svpbmt; struct dumperinfo; struct minidumpstate; diff --git a/lib/libc/include/riscv64-freebsd-none/machine/metadata.h b/lib/libc/include/riscv64-freebsd-none/machine/metadata.h index 08bc8720378c..3e583bb2dc87 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/metadata.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/metadata.h @@ -30,11 +30,18 @@ #define MODINFOMD_DTBP 0x1001 #define MODINFOMD_EFI_MAP 0x1002 +#define MODINFOMD_EFI_FB 0x1003 +#define MODINFOMD_BOOT_HARTID 0x1004 +/* + * This is not the same as the UEFI standard EFI_MEMORY_ATTRIBUTES_TABLE, though + * memory_size / descritpr_size entries of EFI_MEMORY_DESCRIPTORS follow this table + * starting at a 16-byte alignment. + */ struct efi_map_header { - size_t memory_size; - size_t descriptor_size; - uint32_t descriptor_version; + size_t memory_size; /* Numnber of bytes that follow */ + size_t descriptor_size; /* Size of each EFI_MEMORY_DESCRIPTOR */ + uint32_t descriptor_version; /* Currently '1' */ }; /* diff --git a/lib/libc/include/riscv64-freebsd-none/machine/param.h b/lib/libc/include/riscv64-freebsd-none/machine/param.h index d8f05877155d..ca250fee4ccb 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/param.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/param.h @@ -25,8 +25,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)param.h 5.8 (Berkeley) 6/28/91 */ #ifndef _MACHINE_PARAM_H_ @@ -41,8 +39,6 @@ #define STACKALIGNBYTES (16 - 1) #define STACKALIGN(p) ((uint64_t)(p) & ~STACKALIGNBYTES) -#define __PCI_REROUTE_INTERRUPT - #ifndef MACHINE #define MACHINE "riscv" #endif @@ -95,15 +91,7 @@ /* * Mach derived conversion macros */ -#define round_page(x) (((unsigned long)(x) + PAGE_MASK) & ~PAGE_MASK) -#define trunc_page(x) ((unsigned long)(x) & ~PAGE_MASK) - -#define atop(x) ((unsigned long)(x) >> PAGE_SHIFT) -#define ptoa(x) ((unsigned long)(x) << PAGE_SHIFT) - #define riscv_btop(x) ((unsigned long)(x) >> PAGE_SHIFT) #define riscv_ptob(x) ((unsigned long)(x) << PAGE_SHIFT) -#define pgtok(x) ((unsigned long)(x) * (PAGE_SIZE / 1024)) - #endif /* !_MACHINE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-freebsd-none/machine/pcpu.h b/lib/libc/include/riscv64-freebsd-none/machine/pcpu.h index adf445fc2be2..03f8fa47f8ce 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/pcpu.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/pcpu.h @@ -46,7 +46,8 @@ struct pmap *pc_curpmap; /* Currently active pmap */ \ uint32_t pc_pending_ipis; /* IPIs pending to this CPU */ \ uint32_t pc_hart; /* Hart ID */ \ - char __pad[56] /* Pad to factor of PAGE_SIZE */ + uint64_t pc_clock; \ + char __pad[48] /* Pad to factor of PAGE_SIZE */ #ifdef _KERNEL diff --git a/lib/libc/include/riscv64-freebsd-none/machine/pmap.h b/lib/libc/include/riscv64-freebsd-none/machine/pmap.h index ee06de490d62..70dc01e96977 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/pmap.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/pmap.h @@ -67,6 +67,12 @@ struct md_page { vm_memattr_t pv_memattr; }; +enum pmap_stage { + PM_INVALID, + PM_STAGE1, + PM_STAGE2, +}; + struct pmap { struct mtx pm_mtx; struct pmap_statistics pm_stats; /* pmap statictics */ @@ -76,6 +82,7 @@ struct pmap { TAILQ_HEAD(,pv_chunk) pm_pvchunk; /* list of mappings in pmap */ LIST_ENTRY(pmap) pm_list; /* List of all pmaps */ struct vm_radix pm_root; + enum pmap_stage pm_stage; }; typedef struct pmap *pmap_t; @@ -126,7 +133,7 @@ struct thread; void pmap_activate_boot(pmap_t); void pmap_activate_sw(struct thread *); -void pmap_bootstrap(vm_offset_t, vm_paddr_t, vm_size_t); +void pmap_bootstrap(vm_paddr_t, vm_size_t); int pmap_change_attr(vm_offset_t va, vm_size_t size, int mode); void pmap_kenter(vm_offset_t sva, vm_size_t size, vm_paddr_t pa, int mode); void pmap_kenter_device(vm_offset_t, vm_size_t, vm_paddr_t); @@ -134,6 +141,7 @@ vm_paddr_t pmap_kextract(vm_offset_t va); void pmap_kremove(vm_offset_t); void pmap_kremove_device(vm_offset_t, vm_size_t); void *pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, vm_memattr_t ma); +int pmap_pinit_stage(pmap_t, enum pmap_stage); bool pmap_page_is_mapped(vm_page_t m); bool pmap_ps_enabled(pmap_t); diff --git a/lib/libc/include/riscv64-freebsd-none/machine/proc.h b/lib/libc/include/riscv64-freebsd-none/machine/proc.h index cb453c4b43a6..b6745a76b332 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/proc.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/proc.h @@ -25,8 +25,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)proc.h 7.1 (Berkeley) 5/15/91 * from: FreeBSD: src/sys/i386/include/proc.h,v 1.11 2001/06/29 */ diff --git a/lib/libc/include/riscv64-freebsd-none/machine/pte.h b/lib/libc/include/riscv64-freebsd-none/machine/pte.h index 5a905bedeee3..de6de5213dcb 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/pte.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/pte.h @@ -83,6 +83,51 @@ typedef uint64_t pn_t; /* page number */ #define PTE_PROMOTE (PTE_V | PTE_RWX | PTE_D | PTE_G | PTE_U | \ PTE_SW_MANAGED | PTE_SW_WIRED) +/* + * Svpbmt Memory Attribute (MA) bits [62:61]. + * + * +------+-------+------------------------------------------------------------+ + * | Mode | Value | Requested Memory Attributes | + * +------+-------+------------------------------------------------------------+ + * | PMA | 00 | None, inherited from Physical Memory Attributes (firmware) | + * | NC | 01 | Non-cacheable, idempotent, weakly-ordered (RVWMO), | + * | | | main memory | + * | IO | 10 | Non-cacheable, non-idempotent, strongly-ordered, I/O | + * | -- | 11 | Reserved | + * +------+-------+------------------------------------------------------------+ + */ +#define PTE_MA_SHIFT 61 +#define PTE_MA_MASK (0x3ul << PTE_MA_SHIFT) +#define PTE_MA_NONE (0ul) +#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 @@ -92,6 +137,4 @@ typedef uint64_t pn_t; /* page number */ #define PTE_PPN3_S 37 #define PTE_SIZE 8 -#endif /* !_MACHINE_PTE_H_ */ - -/* End of pte.h */ \ No newline at end of file +#endif /* !_MACHINE_PTE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-freebsd-none/machine/resource.h b/lib/libc/include/riscv64-freebsd-none/machine/resource.h index 8b40a35d9635..8df4f2f2cd36 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/resource.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/resource.h @@ -40,8 +40,6 @@ #define SYS_RES_MEMORY 3 /* i/o memory */ #define SYS_RES_IOPORT 4 /* i/o ports */ #define SYS_RES_GPIO 5 /* general purpose i/o */ -#ifdef NEW_PCIB #define PCI_RES_BUS 6 /* PCI bus numbers */ -#endif #endif /* !_MACHINE_RESOURCE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-freebsd-none/machine/riscvreg.h b/lib/libc/include/riscv64-freebsd-none/machine/riscvreg.h index e65c349e4ea0..159b8d531f56 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/riscvreg.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/riscvreg.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2015-2017 Ruslan Bukin + * Copyright (c) 2015-2024 Ruslan Bukin * All rights reserved. * * Portions of this software were developed by SRI International and the @@ -47,9 +47,15 @@ #define SCAUSE_STORE_ACCESS_FAULT 7 #define SCAUSE_ECALL_USER 8 #define SCAUSE_ECALL_SUPERVISOR 9 +#define SCAUSE_VIRTUAL_SUPERVISOR_ECALL 10 +#define SCAUSE_MACHINE_ECALL 11 #define SCAUSE_INST_PAGE_FAULT 12 #define SCAUSE_LOAD_PAGE_FAULT 13 #define SCAUSE_STORE_PAGE_FAULT 15 +#define SCAUSE_FETCH_GUEST_PAGE_FAULT 20 +#define SCAUSE_LOAD_GUEST_PAGE_FAULT 21 +#define SCAUSE_VIRTUAL_INSTRUCTION 22 +#define SCAUSE_STORE_GUEST_PAGE_FAULT 23 #define SSTATUS_UIE (1 << 0) #define SSTATUS_SIE (1 << 1) @@ -116,6 +122,17 @@ #define MSTATUS_PRV_H 2 /* hypervisor */ #define MSTATUS_PRV_M 3 /* machine */ +#define HSTATUS_VSBE (1 << 5) +#define HSTATUS_GVA (1 << 6) +#define HSTATUS_SPV (1 << 7) +#define HSTATUS_SPVP (1 << 8) +#define HSTATUS_HU (1 << 9) +#define HSTATUS_VGEIN_S 12 +#define HSTATUS_VGEIN_M (0xf << HSTATUS_VGEIN_S) +#define HSTATUS_VTVM (1 << 20) +#define HSTATUS_VTW (1 << 21) +#define HSTATUS_VTSR (1 << 22) + #define MIE_USIE (1 << 0) #define MIE_SSIE (1 << 1) #define MIE_HSIE (1 << 2) @@ -143,10 +160,31 @@ #define MIP_SEIP (1 << 9) +#define HVIP_VSSIP (1 << 2) +#define HVIP_VSTIP (1 << 6) +#define HVIP_VSEIP (1 << 10) + +#define HIE_VSSIE (1 << 2) +#define HIE_VSTIE (1 << 6) +#define HIE_VSEIE (1 << 10) +#define HIE_SGEIE (1 << 12) + /* Note: sip register has no SIP_STIP bit in Spike simulator */ #define SIP_SSIP (1 << 1) #define SIP_STIP (1 << 5) +#define HENVCFG_STCE (1UL << 63) +#define HENVCFG_PBMTE (1UL << 62) +#define HENVCFG_CBZE (1UL << 7) +#define HENVCFG_CBCFE (1UL << 6) +#define HENVCFG_CBIE_S 4 +#define HENVCFG_CBIE_M (0x3 << HENVCFG_CBIE_S) +#define HENVCFG_FIOM (1UL << 0) + +#define HCOUNTEREN_CY (1UL << 0) /* Cycle */ +#define HCOUNTEREN_TM (1UL << 1) /* Time */ +#define HCOUNTEREN_IR (1UL << 2) /* Instret */ + #define SATP_PPN_S 0 #define SATP_PPN_M (0xfffffffffffUL << SATP_PPN_S) #define SATP_ASID_S 44 @@ -189,13 +227,14 @@ (__builtin_constant_p(val) && ((u_long)(val) < 32)) #define csr_swap(csr, val) \ -({ if (CSR_ZIMM(val)) \ +({ u_long ret; \ + if (CSR_ZIMM(val)) \ __asm __volatile("csrrwi %0, " #csr ", %1" \ - : "=r" (val) : "i" (val)); \ + : "=r" (ret) : "i" (val)); \ else \ __asm __volatile("csrrw %0, " #csr ", %1" \ - : "=r" (val) : "r" (val)); \ - val; \ + : "=r" (ret) : "r" (val)); \ + ret; \ }) #define csr_write(csr, val) \ diff --git a/lib/libc/include/riscv64-freebsd-none/machine/runq.h b/lib/libc/include/riscv64-freebsd-none/machine/runq.h deleted file mode 100644 index 392bf093b433..000000000000 --- a/lib/libc/include/riscv64-freebsd-none/machine/runq.h +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * Copyright (c) 2001 Jake Burkholder - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _MACHINE_RUNQ_H_ -#define _MACHINE_RUNQ_H_ - -#define RQB_LEN (1) /* Number of priority status words. */ -#define RQB_L2BPW (6) /* Log2(sizeof(rqb_word_t) * NBBY)). */ -#define RQB_BPW (1<> RQB_L2BPW) - -#define RQB_FFS(word) (ffsl(word) - 1) - -/* - * Type of run queue status word. - */ -typedef unsigned long rqb_word_t; - -#endif \ No newline at end of file diff --git a/lib/libc/include/riscv64-freebsd-none/machine/sbi.h b/lib/libc/include/riscv64-freebsd-none/machine/sbi.h index 2cf51a83413d..c982de0c0d26 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/sbi.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/sbi.h @@ -49,6 +49,12 @@ #define SBI_IMPL_ID_KVM 3 #define SBI_IMPL_ID_RUSTSBI 4 #define SBI_IMPL_ID_DIOSIX 5 +#define SBI_IMPL_ID_COFFER 6 +#define SBI_IMPL_ID_XEN_PROJECT 7 +#define SBI_IMPL_ID_POLARFIRE_HSS 8 +#define SBI_IMPL_ID_COREBOOT 9 +#define SBI_IMPL_ID_OREBOOT 10 +#define SBI_IMPL_ID_BHYVE 11 /* SBI Error Codes */ #define SBI_SUCCESS 0 @@ -117,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) @@ -236,4 +244,5 @@ sbi_console_getchar(void) void sbi_print_version(void); void sbi_init(void); +#endif /* !LOCORE */ #endif /* !_MACHINE_SBI_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-freebsd-none/machine/sdt_machdep.h b/lib/libc/include/riscv64-freebsd-none/machine/sdt_machdep.h new file mode 100644 index 000000000000..d64ccbd61edf --- /dev/null +++ b/lib/libc/include/riscv64-freebsd-none/machine/sdt_machdep.h @@ -0,0 +1,12 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 Mark Johnston + */ + +#ifndef _SYS_SDT_MACHDEP_H_ +#define _SYS_SDT_MACHDEP_H_ + +#define _SDT_ASM_PATCH_INSTR ".option push; .option norvc; nop; .option pop" + +#endif /* _SYS_SDT_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-freebsd-none/machine/signal.h b/lib/libc/include/riscv64-freebsd-none/machine/signal.h index d1935504bacb..c1d7d8ff82dd 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/signal.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/signal.h @@ -25,8 +25,6 @@ * 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. - * - * @(#)signal.h 8.1 (Berkeley) 6/11/93 * from: FreeBSD: src/sys/i386/include/signal.h,v 1.13 2000/11/09 * from: FreeBSD: src/sys/sparc64/include/signal.h,v 1.6 2001/09/30 18:52:17 */ diff --git a/lib/libc/include/riscv64-freebsd-none/machine/thead.h b/lib/libc/include/riscv64-freebsd-none/machine/thead.h new file mode 100644 index 000000000000..8d3d50bbe2f4 --- /dev/null +++ b/lib/libc/include/riscv64-freebsd-none/machine/thead.h @@ -0,0 +1,37 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 The FreeBSD Foundation + * + * This software was developed by Mitchell Horne 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_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-freebsd-none/machine/vm.h b/lib/libc/include/riscv64-freebsd-none/machine/vm.h index 13ffd9a8fc92..b28fa7d95106 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/vm.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/vm.h @@ -28,10 +28,14 @@ #define _MACHINE_VM_H_ /* Memory attribute configuration. */ -#define VM_MEMATTR_DEVICE 0 +#define VM_MEMATTR_PMA 0 #define VM_MEMATTR_UNCACHEABLE 1 -#define VM_MEMATTR_WRITE_BACK 2 +#define VM_MEMATTR_DEVICE 2 -#define VM_MEMATTR_DEFAULT VM_MEMATTR_WRITE_BACK +#define VM_MEMATTR_WRITE_BACK VM_MEMATTR_PMA +#define VM_MEMATTR_DEFAULT VM_MEMATTR_PMA + +#define VM_MEMATTR_LAST VM_MEMATTR_DEVICE +#define VM_MEMATTR_TOTAL (VM_MEMATTR_LAST + 1) #endif /* !_MACHINE_VM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-freebsd-none/machine/vmm.h b/lib/libc/include/riscv64-freebsd-none/machine/vmm.h new file mode 100644 index 000000000000..d9a27a2f850d --- /dev/null +++ b/lib/libc/include/riscv64-freebsd-none/machine/vmm.h @@ -0,0 +1,299 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2015 Mihai Carabas + * Copyright (c) 2024 Ruslan Bukin + * + * This software was developed by the University of Cambridge Computer + * Laboratory (Department of Computer Science and Technology) under Innovate + * UK project 105694, "Digital Security by Design (DSbD) Technology Platform + * Prototype". + * + * 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 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 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 _VMM_H_ +#define _VMM_H_ + +#include +#include +#include +#include + +#include "pte.h" +#include "pmap.h" + +struct vcpu; + +enum vm_suspend_how { + VM_SUSPEND_NONE, + VM_SUSPEND_RESET, + VM_SUSPEND_POWEROFF, + VM_SUSPEND_HALT, + VM_SUSPEND_DESTROY, + VM_SUSPEND_LAST +}; + +/* + * Identifiers for architecturally defined registers. + */ +enum vm_reg_name { + VM_REG_GUEST_ZERO = 0, + VM_REG_GUEST_RA, + VM_REG_GUEST_SP, + VM_REG_GUEST_GP, + VM_REG_GUEST_TP, + VM_REG_GUEST_T0, + VM_REG_GUEST_T1, + VM_REG_GUEST_T2, + VM_REG_GUEST_S0, + VM_REG_GUEST_S1, + VM_REG_GUEST_A0, + VM_REG_GUEST_A1, + VM_REG_GUEST_A2, + VM_REG_GUEST_A3, + VM_REG_GUEST_A4, + VM_REG_GUEST_A5, + VM_REG_GUEST_A6, + VM_REG_GUEST_A7, + VM_REG_GUEST_S2, + VM_REG_GUEST_S3, + VM_REG_GUEST_S4, + VM_REG_GUEST_S5, + VM_REG_GUEST_S6, + VM_REG_GUEST_S7, + VM_REG_GUEST_S8, + VM_REG_GUEST_S9, + VM_REG_GUEST_S10, + VM_REG_GUEST_S11, + VM_REG_GUEST_T3, + VM_REG_GUEST_T4, + VM_REG_GUEST_T5, + VM_REG_GUEST_T6, + VM_REG_GUEST_SEPC, + VM_REG_LAST +}; + +#define VM_INTINFO_VECTOR(info) ((info) & 0xff) +#define VM_INTINFO_DEL_ERRCODE 0x800 +#define VM_INTINFO_RSVD 0x7ffff000 +#define VM_INTINFO_VALID 0x80000000 +#define VM_INTINFO_TYPE 0x700 +#define VM_INTINFO_HWINTR (0 << 8) +#define VM_INTINFO_NMI (2 << 8) +#define VM_INTINFO_HWEXCEPTION (3 << 8) +#define VM_INTINFO_SWINTR (4 << 8) + +#define VM_MAX_NAMELEN 32 +#define VM_MAX_SUFFIXLEN 15 + +#ifdef _KERNEL + +struct vm; +struct vm_exception; +struct vm_exit; +struct vm_run; +struct vm_object; +struct vm_guest_paging; +struct vm_aplic_descr; +struct pmap; + +struct vm_eventinfo { + void *rptr; /* rendezvous cookie */ + int *sptr; /* suspend cookie */ + int *iptr; /* reqidle cookie */ +}; + +int vm_create(const char *name, struct vm **retvm); +struct vcpu *vm_alloc_vcpu(struct vm *vm, int vcpuid); +void vm_disable_vcpu_creation(struct vm *vm); +void vm_slock_vcpus(struct vm *vm); +void vm_unlock_vcpus(struct vm *vm); +void vm_destroy(struct vm *vm); +int vm_reinit(struct vm *vm); +const char *vm_name(struct vm *vm); + +uint16_t vm_get_maxcpus(struct vm *vm); +void vm_get_topology(struct vm *vm, uint16_t *sockets, uint16_t *cores, + uint16_t *threads, uint16_t *maxcpus); +int vm_set_topology(struct vm *vm, uint16_t sockets, uint16_t cores, + uint16_t threads, uint16_t maxcpus); +int vm_get_register(struct vcpu *vcpu, int reg, uint64_t *retval); +int vm_set_register(struct vcpu *vcpu, int reg, uint64_t val); +int vm_run(struct vcpu *vcpu); +int vm_suspend(struct vm *vm, enum vm_suspend_how how); +void* vm_get_cookie(struct vm *vm); +int vcpu_vcpuid(struct vcpu *vcpu); +void *vcpu_get_cookie(struct vcpu *vcpu); +struct vm *vcpu_vm(struct vcpu *vcpu); +struct vcpu *vm_vcpu(struct vm *vm, int cpu); +int vm_get_capability(struct vcpu *vcpu, int type, int *val); +int vm_set_capability(struct vcpu *vcpu, int type, int val); +int vm_activate_cpu(struct vcpu *vcpu); +int vm_suspend_cpu(struct vm *vm, struct vcpu *vcpu); +int vm_resume_cpu(struct vm *vm, struct vcpu *vcpu); +int vm_inject_exception(struct vcpu *vcpu, uint64_t scause); +int vm_attach_aplic(struct vm *vm, struct vm_aplic_descr *descr); +int vm_assert_irq(struct vm *vm, uint32_t irq); +int vm_deassert_irq(struct vm *vm, uint32_t irq); +int vm_raise_msi(struct vm *vm, uint64_t msg, uint64_t addr, int bus, int slot, + int func); +struct vm_exit *vm_exitinfo(struct vcpu *vcpu); +void vm_exit_suspended(struct vcpu *vcpu, uint64_t pc); +void vm_exit_debug(struct vcpu *vcpu, uint64_t pc); +void vm_exit_rendezvous(struct vcpu *vcpu, uint64_t pc); +void vm_exit_astpending(struct vcpu *vcpu, uint64_t pc); + +cpuset_t vm_active_cpus(struct vm *vm); +cpuset_t vm_debug_cpus(struct vm *vm); +cpuset_t vm_suspended_cpus(struct vm *vm); + +static __inline int +vcpu_rendezvous_pending(struct vm_eventinfo *info) +{ + + return (*((uintptr_t *)(info->rptr)) != 0); +} + +static __inline int +vcpu_suspended(struct vm_eventinfo *info) +{ + + return (*info->sptr); +} + +int vcpu_debugged(struct vcpu *vcpu); + +enum vcpu_state { + VCPU_IDLE, + VCPU_FROZEN, + VCPU_RUNNING, + VCPU_SLEEPING, +}; + +int vcpu_set_state(struct vcpu *vcpu, enum vcpu_state state, bool from_idle); +enum vcpu_state vcpu_get_state(struct vcpu *vcpu, int *hostcpu); + +static int __inline +vcpu_is_running(struct vcpu *vcpu, int *hostcpu) +{ + return (vcpu_get_state(vcpu, hostcpu) == VCPU_RUNNING); +} + +#ifdef _SYS_PROC_H_ +static int __inline +vcpu_should_yield(struct vcpu *vcpu) +{ + struct thread *td; + + td = curthread; + return (td->td_ast != 0 || td->td_owepreempt != 0); +} +#endif + +void *vcpu_stats(struct vcpu *vcpu); +void vcpu_notify_event(struct vcpu *vcpu); +struct vmspace *vm_vmspace(struct vm *vm); +struct vm_mem *vm_mem(struct vm *vm); + +enum vm_reg_name vm_segment_name(int seg_encoding); + +#endif /* _KERNEL */ + +#define VM_DIR_READ 0 +#define VM_DIR_WRITE 1 + +#define VM_GP_M_MASK 0x1f +#define VM_GP_MMU_ENABLED (1 << 5) + +struct vm_guest_paging { + int flags; + int padding; +}; + +struct vie { + uint8_t access_size:4, sign_extend:1, dir:1, unused:2; + enum vm_reg_name reg; +}; + +struct vre { + uint32_t inst_syndrome; + uint8_t dir:1, unused:7; + enum vm_reg_name reg; +}; + +/* + * Identifiers for optional vmm capabilities + */ +enum vm_cap_type { + VM_CAP_UNRESTRICTED_GUEST, + VM_CAP_SSTC, + VM_CAP_MAX +}; + +enum vm_exitcode { + VM_EXITCODE_BOGUS, + VM_EXITCODE_ECALL, + VM_EXITCODE_HYP, + VM_EXITCODE_PAGING, + VM_EXITCODE_SUSPENDED, + VM_EXITCODE_DEBUG, + VM_EXITCODE_INST_EMUL, + VM_EXITCODE_WFI, + VM_EXITCODE_MAX +}; + +struct vm_exit { + uint64_t scause; + uint64_t sepc; + uint64_t stval; + uint64_t htval; + uint64_t htinst; + enum vm_exitcode exitcode; + int inst_length; + uint64_t pc; + union { + struct { + uint64_t gpa; + } paging; + + struct { + uint64_t gpa; + struct vm_guest_paging paging; + struct vie vie; + } inst_emul; + + struct { + uint64_t args[8]; + } ecall; + + struct { + enum vm_suspend_how how; + } suspended; + + struct { + uint64_t scause; + } hyp; + } u; +}; + +#endif /* _VMM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-freebsd-none/machine/vmm_dev.h b/lib/libc/include/riscv64-freebsd-none/machine/vmm_dev.h new file mode 100644 index 000000000000..2e186a113f4c --- /dev/null +++ b/lib/libc/include/riscv64-freebsd-none/machine/vmm_dev.h @@ -0,0 +1,265 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2015 Mihai Carabas + * Copyright (c) 2024 Ruslan Bukin + * + * This software was developed by the University of Cambridge Computer + * Laboratory (Department of Computer Science and Technology) under Innovate + * UK project 105694, "Digital Security by Design (DSbD) Technology Platform + * Prototype". + * + * 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 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 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 _VMM_DEV_H_ +#define _VMM_DEV_H_ + +#include + +#include + +struct vm_memmap { + vm_paddr_t gpa; + int segid; /* memory segment */ + vm_ooffset_t segoff; /* offset into memory segment */ + size_t len; /* mmap length */ + int prot; /* RWX */ + int flags; +}; +#define VM_MEMMAP_F_WIRED 0x01 + +struct vm_munmap { + vm_paddr_t gpa; + size_t len; +}; + +#define VM_MEMSEG_NAME(m) ((m)->name[0] != '\0' ? (m)->name : NULL) +struct vm_memseg { + int segid; + size_t len; + char name[VM_MAX_SUFFIXLEN + 1]; + domainset_t *ds_mask; + size_t ds_mask_size; + int ds_policy; +}; + +struct vm_register { + int cpuid; + int regnum; /* enum vm_reg_name */ + uint64_t regval; +}; + +struct vm_register_set { + int cpuid; + unsigned int count; + const int *regnums; /* enum vm_reg_name */ + uint64_t *regvals; +}; + +struct vm_run { + int cpuid; + cpuset_t *cpuset; /* CPU set storage */ + size_t cpusetsize; + struct vm_exit *vm_exit; +}; + +struct vm_exception { + int cpuid; + uint64_t scause; +}; + +struct vm_msi { + uint64_t msg; + uint64_t addr; + int bus; + int slot; + int func; +}; + +struct vm_capability { + int cpuid; + enum vm_cap_type captype; + int capval; + int allcpus; +}; + +#define MAX_VM_STATS 64 +struct vm_stats { + int cpuid; /* in */ + int index; /* in */ + int num_entries; /* out */ + struct timeval tv; + uint64_t statbuf[MAX_VM_STATS]; +}; +struct vm_stat_desc { + int index; /* in */ + char desc[128]; /* out */ +}; + +struct vm_suspend { + enum vm_suspend_how how; +}; + +struct vm_gla2gpa { + int vcpuid; /* inputs */ + int prot; /* PROT_READ or PROT_WRITE */ + uint64_t gla; + struct vm_guest_paging paging; + int fault; /* outputs */ + uint64_t gpa; +}; + +struct vm_activate_cpu { + int vcpuid; +}; + +struct vm_cpuset { + int which; + int cpusetsize; + cpuset_t *cpus; +}; +#define VM_ACTIVE_CPUS 0 +#define VM_SUSPENDED_CPUS 1 +#define VM_DEBUG_CPUS 2 + +struct vm_aplic_descr { + uint64_t mem_start; + uint64_t mem_size; +}; + +struct vm_irq { + uint32_t irq; +}; + +struct vm_cpu_topology { + uint16_t sockets; + uint16_t cores; + uint16_t threads; + uint16_t maxcpus; +}; + +enum { + /* general routines */ + IOCNUM_ABIVERS = 0, + IOCNUM_RUN = 1, + IOCNUM_SET_CAPABILITY = 2, + IOCNUM_GET_CAPABILITY = 3, + IOCNUM_SUSPEND = 4, + IOCNUM_REINIT = 5, + + /* memory apis */ + IOCNUM_GET_GPA_PMAP = 12, + IOCNUM_GLA2GPA_NOFAULT = 13, + IOCNUM_ALLOC_MEMSEG = 14, + IOCNUM_GET_MEMSEG = 15, + IOCNUM_MMAP_MEMSEG = 16, + IOCNUM_MMAP_GETNEXT = 17, + IOCNUM_MUNMAP_MEMSEG = 18, + + /* register/state accessors */ + IOCNUM_SET_REGISTER = 20, + IOCNUM_GET_REGISTER = 21, + IOCNUM_SET_REGISTER_SET = 24, + IOCNUM_GET_REGISTER_SET = 25, + + /* statistics */ + IOCNUM_VM_STATS = 50, + IOCNUM_VM_STAT_DESC = 51, + + /* CPU Topology */ + IOCNUM_SET_TOPOLOGY = 63, + IOCNUM_GET_TOPOLOGY = 64, + + /* interrupt injection */ + IOCNUM_ASSERT_IRQ = 80, + IOCNUM_DEASSERT_IRQ = 81, + IOCNUM_RAISE_MSI = 82, + IOCNUM_INJECT_EXCEPTION = 83, + + /* vm_cpuset */ + IOCNUM_ACTIVATE_CPU = 90, + IOCNUM_GET_CPUSET = 91, + IOCNUM_SUSPEND_CPU = 92, + IOCNUM_RESUME_CPU = 93, + + /* vm_attach_aplic */ + IOCNUM_ATTACH_APLIC = 110, +}; + +#define VM_RUN \ + _IOWR('v', IOCNUM_RUN, struct vm_run) +#define VM_SUSPEND \ + _IOW('v', IOCNUM_SUSPEND, struct vm_suspend) +#define VM_REINIT \ + _IO('v', IOCNUM_REINIT) +#define VM_ALLOC_MEMSEG \ + _IOW('v', IOCNUM_ALLOC_MEMSEG, struct vm_memseg) +#define VM_GET_MEMSEG \ + _IOWR('v', IOCNUM_GET_MEMSEG, struct vm_memseg) +#define VM_MMAP_MEMSEG \ + _IOW('v', IOCNUM_MMAP_MEMSEG, struct vm_memmap) +#define VM_MMAP_GETNEXT \ + _IOWR('v', IOCNUM_MMAP_GETNEXT, struct vm_memmap) +#define VM_MUNMAP_MEMSEG \ + _IOW('v', IOCNUM_MUNMAP_MEMSEG, struct vm_munmap) +#define VM_SET_REGISTER \ + _IOW('v', IOCNUM_SET_REGISTER, struct vm_register) +#define VM_GET_REGISTER \ + _IOWR('v', IOCNUM_GET_REGISTER, struct vm_register) +#define VM_SET_REGISTER_SET \ + _IOW('v', IOCNUM_SET_REGISTER_SET, struct vm_register_set) +#define VM_GET_REGISTER_SET \ + _IOWR('v', IOCNUM_GET_REGISTER_SET, struct vm_register_set) +#define VM_SET_CAPABILITY \ + _IOW('v', IOCNUM_SET_CAPABILITY, struct vm_capability) +#define VM_GET_CAPABILITY \ + _IOWR('v', IOCNUM_GET_CAPABILITY, struct vm_capability) +#define VM_STATS \ + _IOWR('v', IOCNUM_VM_STATS, struct vm_stats) +#define VM_STAT_DESC \ + _IOWR('v', IOCNUM_VM_STAT_DESC, struct vm_stat_desc) +#define VM_ASSERT_IRQ \ + _IOW('v', IOCNUM_ASSERT_IRQ, struct vm_irq) +#define VM_DEASSERT_IRQ \ + _IOW('v', IOCNUM_DEASSERT_IRQ, struct vm_irq) +#define VM_RAISE_MSI \ + _IOW('v', IOCNUM_RAISE_MSI, struct vm_msi) +#define VM_INJECT_EXCEPTION \ + _IOW('v', IOCNUM_INJECT_EXCEPTION, struct vm_exception) +#define VM_SET_TOPOLOGY \ + _IOW('v', IOCNUM_SET_TOPOLOGY, struct vm_cpu_topology) +#define VM_GET_TOPOLOGY \ + _IOR('v', IOCNUM_GET_TOPOLOGY, struct vm_cpu_topology) +#define VM_GLA2GPA_NOFAULT \ + _IOWR('v', IOCNUM_GLA2GPA_NOFAULT, struct vm_gla2gpa) +#define VM_ACTIVATE_CPU \ + _IOW('v', IOCNUM_ACTIVATE_CPU, struct vm_activate_cpu) +#define VM_GET_CPUS \ + _IOW('v', IOCNUM_GET_CPUSET, struct vm_cpuset) +#define VM_SUSPEND_CPU \ + _IOW('v', IOCNUM_SUSPEND_CPU, struct vm_activate_cpu) +#define VM_RESUME_CPU \ + _IOW('v', IOCNUM_RESUME_CPU, struct vm_activate_cpu) +#define VM_ATTACH_APLIC \ + _IOW('v', IOCNUM_ATTACH_APLIC, struct vm_aplic_descr) +#endif \ No newline at end of file diff --git a/lib/libc/include/riscv64-freebsd-none/machine/vmm_instruction_emul.h b/lib/libc/include/riscv64-freebsd-none/machine/vmm_instruction_emul.h new file mode 100644 index 000000000000..4aef995ba45c --- /dev/null +++ b/lib/libc/include/riscv64-freebsd-none/machine/vmm_instruction_emul.h @@ -0,0 +1,85 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2015 Mihai Carabas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY 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 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 _VMM_INSTRUCTION_EMUL_H_ +#define _VMM_INSTRUCTION_EMUL_H_ + +/* + * Callback functions to read and write memory regions. + */ +typedef int (*mem_region_read_t)(struct vcpu *vcpu, uint64_t gpa, + uint64_t *rval, int rsize, void *arg); +typedef int (*mem_region_write_t)(struct vcpu *vcpu, uint64_t gpa, + uint64_t wval, int wsize, void *arg); + +/* + * Callback functions to read and write registers. + */ +typedef int (*reg_read_t)(struct vcpu *vcpu, uint64_t *rval, void *arg); +typedef int (*reg_write_t)(struct vcpu *vcpu, uint64_t wval, void *arg); + +/* + * Emulate the decoded 'vie' instruction when it contains a memory operation. + * + * The callbacks 'mrr' and 'mrw' emulate reads and writes to the memory region + * containing 'gpa'. 'mrarg' is an opaque argument that is passed into the + * callback functions. + * + * 'void *vm' should be 'struct vm *' when called from kernel context and + * 'struct vmctx *' when called from user context. + * + */ +int vmm_emulate_instruction(struct vcpu *vcpu, uint64_t gpa, struct vie *vie, + struct vm_guest_paging *paging, mem_region_read_t mrr, + mem_region_write_t mrw, void *mrarg); + +/* + * Emulate the decoded 'vre' instruction when it contains a register access. + * + * The callbacks 'regread' and 'regwrite' emulate reads and writes to the + * register from 'vie'. 'regarg' is an opaque argument that is passed into the + * callback functions. + * + * 'void *vm' should be 'struct vm *' when called from kernel context and + * 'struct vmctx *' when called from user context. + * + */ +int vmm_emulate_register(struct vcpu *vcpu, struct vre *vre, reg_read_t regread, + reg_write_t regwrite, void *regarg); + +#ifdef _KERNEL +void vm_register_reg_handler(struct vm *vm, uint64_t iss, uint64_t mask, + reg_read_t reg_read, reg_write_t reg_write, void *arg); +void vm_deregister_reg_handler(struct vm *vm, uint64_t iss, uint64_t mask); + +void vm_register_inst_handler(struct vm *vm, uint64_t start, uint64_t size, + mem_region_read_t mmio_read, mem_region_write_t mmio_write); +void vm_deregister_inst_handler(struct vm *vm, uint64_t start, uint64_t size); +#endif + +#endif /* _VMM_INSTRUCTION_EMUL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-freebsd-none/machine/vmparam.h b/lib/libc/include/riscv64-freebsd-none/machine/vmparam.h index d6f5d5342a57..ead7b93b28f6 100644 --- a/lib/libc/include/riscv64-freebsd-none/machine/vmparam.h +++ b/lib/libc/include/riscv64-freebsd-none/machine/vmparam.h @@ -30,8 +30,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)vmparam.h 5.9 (Berkeley) 5/12/91 * from: FreeBSD: src/sys/i386/include/vmparam.h,v 1.33 2000/03/30 */ @@ -211,8 +209,6 @@ #define PS_STRINGS_SV39 (USRSTACK_SV39 - sizeof(struct ps_strings)) #define PS_STRINGS_SV48 (USRSTACK_SV48 - sizeof(struct ps_strings)) -#define VM_EARLY_DTB_ADDRESS (VM_MAX_KERNEL_ADDRESS - (2 * L2_SIZE)) - /* * How many physical pages per kmem arena virtual page. */ @@ -236,19 +232,22 @@ #define VM_INITIAL_PAGEIN 16 #endif -#define UMA_MD_SMALL_ALLOC +#define UMA_USE_DMAP #ifndef LOCORE extern vm_paddr_t dmap_phys_base; extern vm_paddr_t dmap_phys_max; extern vm_offset_t dmap_max_addr; -extern vm_offset_t init_pt_va; #endif #define ZERO_REGION_SIZE (64 * 1024) /* 64KB */ +/* + * The top of KVA is reserved for early device mappings. + */ #define DEVMAP_MAX_VADDR VM_MAX_KERNEL_ADDRESS -#define PMAP_MAPDEV_EARLY_SIZE L2_SIZE +#define DEVMAP_MIN_VADDR (DEVMAP_MAX_VADDR - PMAP_MAPDEV_EARLY_SIZE) +#define PMAP_MAPDEV_EARLY_SIZE (4 * L2_SIZE) /* * No non-transparent large page support in the pmap. @@ -259,5 +258,6 @@ extern vm_offset_t init_pt_va; * Need a page dump array for minidump. */ #define MINIDUMP_PAGE_TRACKING 1 +#define MINIDUMP_STARTUP_PAGE_TRACKING 1 #endif /* !_MACHINE_VMPARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/frame.h b/lib/libc/include/riscv64-openbsd-none/frame.h new file mode 100644 index 000000000000..e15698128f54 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/frame.h @@ -0,0 +1,99 @@ +/* $OpenBSD: frame.h,v 1.3 2022/02/24 14:19:10 visa Exp $ */ + +/* + * Copyright (c) 2019 Brian Bamsch + * Copyright (c) 2016 Dale Rahn + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 _MACHINE_FRAME_H_ +#define _MACHINE_FRAME_H_ + +#ifndef _LOCORE + +#include + +/* + * Exception/Trap Stack Frame + */ +#define clockframe trapframe +typedef struct trapframe { + /* Standard Registers */ + register_t tf_ra; + register_t tf_sp; + register_t tf_gp; + register_t tf_tp; + register_t tf_t[7]; + register_t tf_s[12]; + register_t tf_a[8]; + /* Supervisor Trap CSRs */ + register_t tf_sepc; + register_t tf_sstatus; + register_t tf_stval; + register_t tf_scause; + register_t tf_pad; +} trapframe_t; + +/* + * pushed on stack for signal delivery + */ +struct sigframe { + int sf_signum; + struct sigcontext sf_sc; + siginfo_t sf_si; +}; + +/* + * System stack frames. + */ + +/* + * Stack frame inside cpu_switch() + */ +struct switchframe { + register_t sf_s[12]; + register_t sf_ra; + register_t sf_pad; +}; + +struct callframe { + struct callframe *f_frame; + register_t f_ra; +}; + +#endif /* !_LOCORE */ + +#endif /* !_MACHINE_FRAME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/_float.h b/lib/libc/include/riscv64-openbsd-none/machine/_float.h new file mode 100644 index 000000000000..d52ce43ca74d --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/_float.h @@ -0,0 +1,96 @@ +/* $OpenBSD: _float.h,v 1.1 2021/04/23 02:42:16 drahn Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE__FLOAT_H_ +#define _MACHINE__FLOAT_H_ + +#define __FLT_RADIX 2 /* b */ +#define __FLT_ROUNDS __flt_rounds() +#define __FLT_EVAL_METHOD 0 /* no promotions */ + +#define __FLT_MANT_DIG 24 /* p */ +#define __FLT_EPSILON 1.19209290E-7F /* b**(1-p) */ +#define __FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ +#define __FLT_MIN_EXP (-125) /* emin */ +#define __FLT_MIN 1.17549435E-38F /* b**(emin-1) */ +#define __FLT_MIN_10_EXP (-37) /* ceil(log10(b**(emin-1))) */ +#define __FLT_MAX_EXP 128 /* emax */ +#define __FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ +#define __FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ + +#define __DBL_MANT_DIG 53 +#define __DBL_EPSILON 2.2204460492503131E-16 +#define __DBL_DIG 15 +#define __DBL_MIN_EXP (-1021) +#define __DBL_MIN 2.2250738585072014E-308 +#define __DBL_MIN_10_EXP (-307) +#define __DBL_MAX_EXP 1024 +#define __DBL_MAX 1.7976931348623157E+308 +#define __DBL_MAX_10_EXP 308 + +#ifdef __LDBL_MANT_DIG__ +#define __LDBL_MANT_DIG __LDBL_MANT_DIG__ +#define __LDBL_EPSILON __LDBL_EPSILON__ +#define __LDBL_DIG __LDBL_DIG__ +#define __LDBL_MIN_EXP __LDBL_MIN_EXP__ +#define __LDBL_MIN __LDBL_MIN__ +#define __LDBL_MIN_10_EXP __LDBL_MIN_10_EXP__ +#define __LDBL_MAX_EXP __LDBL_MAX_EXP__ +#define __LDBL_MAX __LDBL_MAX__ +#define __LDBL_MAX_10_EXP __LDBL_MAX_10_EXP__ +#else +#define __LDBL_MANT_DIG DBL_MANT_DIG +#define __LDBL_EPSILON DBL_EPSILON +#define __LDBL_DIG DBL_DIG +#define __LDBL_MIN_EXP DBL_MIN_EXP +#define __LDBL_MIN DBL_MIN +#define __LDBL_MIN_10_EXP DBL_MIN_10_EXP +#define __LDBL_MAX_EXP DBL_MAX_EXP +#define __LDBL_MAX DBL_MAX +#define __LDBL_MAX_10_EXP DBL_MAX_10_EXP +#endif + +#define __DECIMAL_DIG 17 + +#endif /* _MACHINE__FLOAT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/_types.h b/lib/libc/include/riscv64-openbsd-none/machine/_types.h new file mode 100644 index 000000000000..b5c1227f1e6e --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/_types.h @@ -0,0 +1,146 @@ +/* $OpenBSD: _types.h,v 1.5 2023/07/02 19:02:28 cheloha Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.3 (Berkeley) 1/5/94 + * @(#)ansi.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _MACHINE__TYPES_H_ +#define _MACHINE__TYPES_H_ + +#if defined(_KERNEL) +typedef struct label_t { + long val[14]; +} label_t; +#endif + +/* + * _ALIGN(p) rounds p (pointer or byte index) up to a correctly-aligned + * value for all data types (int, long, ...). The result is an + * unsigned long and must be cast to any desired pointer type. + * + * _ALIGNED_POINTER is a boolean macro that checks whether an address + * is valid to fetch data elements of type t from on this architecture. + * This does not reflect the optimal alignment, just the possibility + * (within reasonable limits). + */ +#define _ALIGNBYTES (sizeof(long) - 1) +#define _STACKALIGNBYTES 15 +#define _ALIGN(p) (((unsigned long)(p) + _ALIGNBYTES) & ~_ALIGNBYTES) +#define _ALIGNED_POINTER(p,t) ((((unsigned long)(p)) & (sizeof(t) - 1)) == 0) +#define _MAX_PAGE_SHIFT 12 /* same as PAGE_SHIFT */ + +/* 7.18.1.1 Exact-width integer types */ +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short __int16_t; +typedef unsigned short __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; +/* LONGLONG */ +typedef long long __int64_t; +/* LONGLONG */ +typedef unsigned long long __uint64_t; + +/* 7.18.1.2 Minimum-width integer types */ +typedef __int8_t __int_least8_t; +typedef __uint8_t __uint_least8_t; +typedef __int16_t __int_least16_t; +typedef __uint16_t __uint_least16_t; +typedef __int32_t __int_least32_t; +typedef __uint32_t __uint_least32_t; +typedef __int64_t __int_least64_t; +typedef __uint64_t __uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types */ +typedef __int32_t __int_fast8_t; +typedef __uint32_t __uint_fast8_t; +typedef __int32_t __int_fast16_t; +typedef __uint32_t __uint_fast16_t; +typedef __int32_t __int_fast32_t; +typedef __uint32_t __uint_fast32_t; +typedef __int64_t __int_fast64_t; +typedef __uint64_t __uint_fast64_t; +#define __INT_FAST8_MIN INT32_MIN +#define __INT_FAST16_MIN INT32_MIN +#define __INT_FAST32_MIN INT32_MIN +#define __INT_FAST64_MIN INT64_MIN +#define __INT_FAST8_MAX INT32_MAX +#define __INT_FAST16_MAX INT32_MAX +#define __INT_FAST32_MAX INT32_MAX +#define __INT_FAST64_MAX INT64_MAX +#define __UINT_FAST8_MAX UINT32_MAX +#define __UINT_FAST16_MAX UINT32_MAX +#define __UINT_FAST32_MAX UINT32_MAX +#define __UINT_FAST64_MAX UINT64_MAX + +/* 7.18.1.4 Integer types capable of holding object pointers */ +typedef long __intptr_t; +typedef unsigned long __uintptr_t; + +/* 7.18.1.5 Greatest-width integer types */ +typedef __int64_t __intmax_t; +typedef __uint64_t __uintmax_t; + +/* Register size */ +typedef long __register_t; + +/* VM system types */ +typedef unsigned long __vaddr_t; +typedef unsigned long __paddr_t; +typedef unsigned long __vsize_t; +typedef unsigned long __psize_t; + +/* Standard system types */ +typedef double __double_t; +typedef float __float_t; +typedef long __ptrdiff_t; +typedef unsigned long __size_t; +typedef long __ssize_t; +#if defined(__GNUC__) && __GNUC__ >= 3 +typedef __builtin_va_list __va_list; +#else +typedef char * __va_list; +#endif + +/* Wide character support types */ +#ifndef __cplusplus +#ifdef __WCHAR_UNSIGNED__ +typedef unsigned int __wchar_t; +#else +typedef int __wchar_t; +#endif +#endif +typedef int __wint_t; +typedef int __rune_t; +typedef void * __wctrans_t; +typedef void * __wctype_t; + +#endif /* _MACHINE__TYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/apmvar.h b/lib/libc/include/riscv64-openbsd-none/machine/apmvar.h new file mode 100644 index 000000000000..18cdbfd9de9e --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/apmvar.h @@ -0,0 +1,122 @@ +/* $OpenBSD: apmvar.h,v 1.1 2023/11/06 20:59:26 jca Exp $ */ + +/* + * Copyright (c) 2001 Alexander Guy + * Copyright (c) 1995 John T. Kohl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _MACHINE_APMVAR_H_ +#define _MACHINE_APMVAR_H_ + +#include + +/* Advanced Power Management (v1.0 and v1.1 specification) + * functions/defines/etc. + */ + +/* These definitions make up the heart of the user-land interface + * to the APM devices. + */ + +#define APM_AC_OFF 0x00 +#define APM_AC_ON 0x01 +#define APM_AC_BACKUP 0x02 +#define APM_AC_UNKNOWN 0xff +#define APM_BATT_HIGH 0x00 +#define APM_BATT_LOW 0x01 +#define APM_BATT_CRITICAL 0x02 +#define APM_BATT_CHARGING 0x03 +#define APM_BATT_UNKNOWN 0xff +#define APM_BATT_LIFE_UNKNOWN 0xff + +#define APM_NOEVENT 0x0000 +#define APM_STANDBY_REQ 0x0001 +#define APM_SUSPEND_REQ 0x0002 +#define APM_NORMAL_RESUME 0x0003 +#define APM_CRIT_RESUME 0x0004 /* suspend/resume happened + without us */ +#define APM_BATTERY_LOW 0x0005 +#define APM_POWER_CHANGE 0x0006 +#define APM_UPDATE_TIME 0x0007 +#define APM_CRIT_SUSPEND_REQ 0x0008 +#define APM_USER_STANDBY_REQ 0x0009 +#define APM_USER_SUSPEND_REQ 0x000A +#define APM_SYS_STANDBY_RESUME 0x000B +#define APM_CAPABILITY_CHANGE 0x000C /* apm v1.2 */ +#define APM_USER_HIBERNATE_REQ 0x000D +#define APM_EVENT_MASK 0xffff + +#define APM_EVENT_COMPOSE(t,i) ((((i) & 0x7fff) << 16)|((t) & APM_EVENT_MASK)) +#define APM_EVENT_TYPE(e) ((e) & APM_EVENT_MASK) +#define APM_EVENT_INDEX(e) ((e) >> 16) + +/* + * LP (Laptop Package) + * + * Copyright (C) 1994 by HOSOKAWA Tatsumi + * + * This software may be used, modified, copied, and distributed, in + * both source and binary form provided that the above copyright and + * these terms are retained. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with its + * use. + * + * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) + */ + +#define APM_BATTERY_ABSENT 4 + +struct apm_power_info { + u_char battery_state; + u_char ac_state; + u_char battery_life; + u_char spare1; + u_int minutes_left; /* estimate */ + u_int spare2[6]; +}; + +struct apm_ctl { + u_int dev; + u_int mode; +}; + +#define APM_IOC_REJECT _IOW('A', 0, struct apm_event_info) /* reject request # */ +#define APM_IOC_STANDBY _IO('A', 1) /* put system into standby */ +#define APM_IOC_SUSPEND _IO('A', 2) /* put system into suspend */ +#define APM_IOC_GETPOWER _IOR('A', 3, struct apm_power_info) /* fetch battery state */ +#define APM_IOC_DEV_CTL _IOW('A', 5, struct apm_ctl) /* put device into mode */ +#define APM_IOC_PRN_CTL _IOW('A', 6, int ) /* driver power status msg */ +#define APM_PRINT_ON 0 /* driver power status displayed */ +#define APM_PRINT_OFF 1 /* driver power status not displayed */ +#define APM_PRINT_PCT 2 /* driver power status only displayed + if the percentage changes */ +#define APM_IOC_STANDBY_REQ _IO('A', 7) /* request standby */ +#define APM_IOC_SUSPEND_REQ _IO('A', 8) /* request suspend */ +#define APM_IOC_HIBERNATE _IO('A', 9) /* put system into hibernate */ + +#endif /* _MACHINE_APMVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/asm.h b/lib/libc/include/riscv64-openbsd-none/machine/asm.h new file mode 100644 index 000000000000..dcb1d9d02b8f --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/asm.h @@ -0,0 +1,129 @@ +/* $OpenBSD: asm.h,v 1.8 2022/12/06 00:08:38 jca Exp $ */ + +/* + * Copyright (c) 2020 Brian Bamsch + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)asm.h 5.5 (Berkeley) 5/7/91 + */ + +#ifndef _MACHINE_ASM_H_ +#define _MACHINE_ASM_H_ + +#define _C_LABEL(x) x +#define _ASM_LABEL(x) x + +#ifdef __STDC__ +# define __CONCAT(x,y) x ## y +# define __STRING(x) #x +#else +# define __CONCAT(x,y) x/**/y +# define __STRING(x) "x" +#endif + +#ifndef _ALIGN_TEXT +# define _ALIGN_TEXT .align 0 +#endif + +/* NB == No Binding: use .globl or .weak as necessary */ +#define _ENTRY_NB(x) \ + .text; .p2align 1; .type x,@function; x: +#define _ENTRY(x) .globl x; _ENTRY_NB(x) + +#if defined(PROF) || defined(GPROF) +// XXX Profiler Support +#define _PROF_PROLOGUE \ + addi sp, sp, -16; \ + sd ra, 8(sp); \ + sd fp, 0(sp); \ + mv fp, sp; \ + call __mcount; \ + ld ra, 8(sp); \ + ld fp, 0(sp); \ + add sp, sp, 16; +#else +#define _PROF_PROLOGUE +#endif + +#if defined(_RET_PROTECTOR) +// XXX Retguard Support +#error RETGUARD not yet supported for riscv64 +#else +#define RETGUARD_CALC_COOKIE(reg) +#define RETGUARD_LOAD_RANDOM(x, reg) +#define RETGUARD_SETUP(x, reg) +#define RETGUARD_CHECK(x, reg) +#define RETGUARD_PUSH(reg) +#define RETGUARD_POP(reg) +#define RETGUARD_SYMBOL(x) +#endif + +#define ENTRY(y) _ENTRY(y); _PROF_PROLOGUE +#define ENTRY_NP(y) _ENTRY(y) +#define ENTRY_NB(y) _ENTRY_NB(y); _PROF_PROLOGUE +#define ASENTRY(y) _ENTRY(y); _PROF_PROLOGUE +#define ASENTRY_NP(y) _ENTRY(y) +#define END(y) .size y, . - y +#define EENTRY(sym) .globl sym; sym: +#define EEND(sym) + +#ifdef __PIC__ +#define PIC_SYM(x,y) x(y) +#else +#define PIC_SYM(x,y) x +#endif + +#define STRONG_ALIAS(alias,sym) \ + .global alias; \ + alias = sym +#define WEAK_ALIAS(alias,sym) \ + .weak alias; \ + alias = sym + +#define SWAP_FAULT_HANDLER(handler, tmp0, tmp1) \ + ld tmp0, CI_CURPCB(tp); /* Load the pcb */ \ + ld tmp1, PCB_ONFAULT(tmp0); /* Save old handler */ \ + sd handler, PCB_ONFAULT(tmp0); /* Set the handler */ \ + mv handler, tmp1 + +#define SET_FAULT_HANDLER(handler, pcb) \ + ld pcb, CI_CURPCB(tp); /* Load the pcb */ \ + sd handler, PCB_ONFAULT(pcb) /* Set the handler */ + +#define ENTER_USER_ACCESS(tmp) \ + li tmp, SSTATUS_SUM; \ + csrs sstatus, tmp + +#define EXIT_USER_ACCESS(tmp) \ + li tmp, SSTATUS_SUM; \ + csrc sstatus, tmp + +#endif /* _MACHINE_ASM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/atomic.h b/lib/libc/include/riscv64-openbsd-none/machine/atomic.h new file mode 100644 index 000000000000..95cfadaae9dc --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/atomic.h @@ -0,0 +1,50 @@ +/* $OpenBSD: atomic.h,v 1.5 2024/01/24 12:25:50 jca Exp $ */ + +/* Public Domain */ + +#ifndef _MACHINE_ATOMIC_H_ +#define _MACHINE_ATOMIC_H_ + +#define __membar(_f) do {__asm volatile(_f ::: "memory"); } while (0) + +#define membar_enter() __membar("fence w,rw") +#define membar_exit() __membar("fence rw,w") +#define membar_producer() __membar("fence w,w") +#define membar_consumer() __membar("fence r,r") +#define membar_sync() __membar("fence rw,rw") + +#if defined(_KERNEL) + +/* virtio needs MP membars even on SP kernels */ +#define virtio_membar_producer() __membar("fence w,w") +#define virtio_membar_consumer() __membar("fence r,r") +#define virtio_membar_sync() __membar("fence rw,rw") + +/* + * Set bits + * *p = *p | v + */ +static inline void +atomic_setbits_int(volatile unsigned int *p, unsigned int v) +{ + __asm volatile("amoor.w zero, %1, %0" + : "+A" (*p) + : "r" (v) + : "memory"); +} + +/* + * Clear bits + * *p = *p & (~v) + */ +static inline void +atomic_clearbits_int(volatile unsigned int *p, unsigned int v) +{ + __asm volatile("amoand.w zero, %1, %0" + : "+A" (*p) + : "r" (~v) + : "memory"); +} + +#endif /* defined(_KERNEL) */ +#endif /* _MACHINE_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/bootconfig.h b/lib/libc/include/riscv64-openbsd-none/machine/bootconfig.h new file mode 100644 index 000000000000..40f8da8ae4f1 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/bootconfig.h @@ -0,0 +1,47 @@ +/* $OpenBSD: bootconfig.h,v 1.5 2024/04/06 18:33:54 kettenis Exp $ */ + +/*- + * Copyright (c) 2015-2017 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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 _MACHINE_BOOTCONFIG_H_ +#define _MACHINE_BOOTCONFIG_H_ + +struct riscv_bootparams { + vaddr_t kern_l1pt; /* L1 page table for the kernel */ + paddr_t kern_phys; + vaddr_t kern_stack; + paddr_t dtbp_phys; /* Device tree blob physical addr */ +}; + +#endif /* _MACHINE_BOOTCONFIG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/bus.h b/lib/libc/include/riscv64-openbsd-none/machine/bus.h new file mode 100644 index 000000000000..85999dfe9d44 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/bus.h @@ -0,0 +1,544 @@ +/* $OpenBSD: bus.h,v 1.8 2025/08/03 14:03:12 jca Exp $ */ + +/* + * Copyright (c) 2003-2004 Opsycon AB Sweden. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BUS_H_ +#define _MACHINE_BUS_H_ + +#ifdef __STDC__ +#define CAT(a,b) a##b +#define CAT3(a,b,c) a##b##c +#else +#define CAT(a,b) a/**/b +#define CAT3(a,b,c) a/**/b/**/c +#endif + +/* + * Bus access types. + */ +struct bus_space; +typedef u_long bus_addr_t; +typedef u_long bus_size_t; +typedef u_long bus_space_handle_t; +typedef struct bus_space *bus_space_tag_t; +typedef struct bus_space bus_space_t; + +struct bus_space { + bus_addr_t bus_base; + void *bus_private; + u_int8_t (*_space_read_1)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_1)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int8_t); + u_int16_t (*_space_read_2)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_2)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int16_t); + u_int32_t (*_space_read_4)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_4)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int32_t); + u_int64_t (*_space_read_8)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_8)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int64_t); + void (*_space_read_raw_2)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_2)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + void (*_space_read_raw_4)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_4)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + void (*_space_read_raw_8)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_8)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + int (*_space_map)(bus_space_tag_t , bus_addr_t, + bus_size_t, int, bus_space_handle_t *); + void (*_space_unmap)(bus_space_tag_t, bus_space_handle_t, + bus_size_t); + int (*_space_subregion)(bus_space_tag_t, bus_space_handle_t, + bus_size_t, bus_size_t, bus_space_handle_t *); + void * (*_space_vaddr)(bus_space_tag_t, bus_space_handle_t); + paddr_t (*_space_mmap)(bus_space_tag_t, bus_addr_t, off_t, + int, int); +}; + +#define bus_space_read_1(t, h, o) (*(t)->_space_read_1)((t), (h), (o)) +#define bus_space_read_2(t, h, o) (*(t)->_space_read_2)((t), (h), (o)) +#define bus_space_read_4(t, h, o) (*(t)->_space_read_4)((t), (h), (o)) +#define bus_space_read_8(t, h, o) (*(t)->_space_read_8)((t), (h), (o)) + +#define bus_space_write_1(t, h, o, v) (*(t)->_space_write_1)((t), (h), (o), (v)) +#define bus_space_write_2(t, h, o, v) (*(t)->_space_write_2)((t), (h), (o), (v)) +#define bus_space_write_4(t, h, o, v) (*(t)->_space_write_4)((t), (h), (o), (v)) +#define bus_space_write_8(t, h, o, v) (*(t)->_space_write_8)((t), (h), (o), (v)) + +#define bus_space_read_raw_2(t, h, o) \ + (*(t)->_space_read_2)((t), (h), (o)) +#define bus_space_read_raw_4(t, h, o) \ + (*(t)->_space_read_4)((t), (h), (o)) +#define bus_space_read_raw_8(t, h, o) \ + (*(t)->_space_read_8)((t), (h), (o)) + +#define bus_space_write_raw_2(t, h, o, v) \ + (*(t)->_space_write_2)((t), (h), (o), (v)) +#define bus_space_write_raw_4(t, h, o, v) \ + (*(t)->_space_write_4)((t), (h), (o), (v)) +#define bus_space_write_raw_8(t, h, o, v) \ + (*(t)->_space_write_8)((t), (h), (o), (v)) + +#define bus_space_read_raw_multi_2(t, h, a, b, l) \ + (*(t)->_space_read_raw_2)((t), (h), (a), (b), (l)) +#define bus_space_read_raw_multi_4(t, h, a, b, l) \ + (*(t)->_space_read_raw_4)((t), (h), (a), (b), (l)) +#define bus_space_read_raw_multi_8(t, h, a, b, l) \ + (*(t)->_space_read_raw_8)((t), (h), (a), (b), (l)) + +#define bus_space_write_raw_multi_2(t, h, a, b, l) \ + (*(t)->_space_write_raw_2)((t), (h), (a), (b), (l)) +#define bus_space_write_raw_multi_4(t, h, a, b, l) \ + (*(t)->_space_write_raw_4)((t), (h), (a), (b), (l)) +#define bus_space_write_raw_multi_8(t, h, a, b, l) \ + (*(t)->_space_write_raw_8)((t), (h), (a), (b), (l)) + +#define bus_space_map(t, o, s, c, p) (*(t)->_space_map)((t), (o), (s), (c), (p)) +#define bus_space_unmap(t, h, s) (*(t)->_space_unmap)((t), (h), (s)) +#define bus_space_subregion(t, h, o, s, p) \ + (*(t)->_space_subregion)((t), (h), (o), (s), (p)) + +#define BUS_SPACE_MAP_CACHEABLE 0x01 +#define BUS_SPACE_MAP_LINEAR 0x02 +#define BUS_SPACE_MAP_PREFETCHABLE 0x04 + +extern bus_space_t riscv64_bs_tag; + +#define bus_space_vaddr(t, h) (*(t)->_space_vaddr)((t), (h)) +#define bus_space_mmap(t, a, o, p, f) \ + (*(t)->_space_mmap)((t), (a), (o), (p), (f)) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_multi(n,m) \ +static __inline void \ +CAT(bus_space_read_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t o, CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) \ + *x++ = CAT(bus_space_read_,n)(bst, bsh, o); \ +} + +bus_space_read_multi(1,8) +bus_space_read_multi(2,16) +bus_space_read_multi(4,32) +bus_space_read_multi(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_region(n,m) \ +static __inline void \ +CAT(bus_space_read_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) { \ + *x++ = CAT(bus_space_read_,n)(bst, bsh, ba); \ + ba += (n); \ + } \ +} + +bus_space_read_region(1,8) +bus_space_read_region(2,16) +bus_space_read_region(4,32) +bus_space_read_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_raw_region(n,m) \ +static __inline void \ +CAT(bus_space_read_raw_region_,n)(bus_space_tag_t bst, \ + bus_space_handle_t bsh, \ + bus_addr_t ba, u_int8_t *x, size_t cnt) \ +{ \ + cnt >>= ((n) >> 1); \ + while (cnt--) { \ + CAT(bus_space_read_raw_multi_,n)(bst, bsh, ba, x, (n)); \ + ba += (n); \ + x += (n); \ + } \ +} + +bus_space_read_raw_region(2,16) +bus_space_read_raw_region(4,32) +bus_space_read_raw_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_multi(n,m) \ +static __inline void \ +CAT(bus_space_write_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t o, const CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) \ + CAT(bus_space_write_,n)(bst, bsh, o, *x++); \ +} + +bus_space_write_multi(1,8) +bus_space_write_multi(2,16) +bus_space_write_multi(4,32) +bus_space_write_multi(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_region(n,m) \ +static __inline void \ +CAT(bus_space_write_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, const CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) { \ + CAT(bus_space_write_,n)(bst, bsh, ba, *x++); \ + ba += (n); \ + } \ +} + +bus_space_write_region(1,8) +bus_space_write_region(2,16) +bus_space_write_region(4,32) +bus_space_write_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_raw_region(n,m) \ +static __inline void \ +CAT(bus_space_write_raw_region_,n)(bus_space_tag_t bst, \ + bus_space_handle_t bsh, \ + bus_addr_t ba, const u_int8_t *x, size_t cnt) \ +{ \ + cnt >>= ((n) >> 1); \ + while (cnt--) { \ + CAT(bus_space_write_raw_multi_,n)(bst, bsh, ba, x, (n)); \ + ba += (n); \ + x += (n); \ + } \ +} + +bus_space_write_raw_region(2,16) +bus_space_write_raw_region(4,32) +bus_space_write_raw_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_set_region(n,m) \ +static __inline void \ +CAT(bus_space_set_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(u_int,m,_t) x, size_t cnt) \ +{ \ + while (cnt--) { \ + CAT(bus_space_write_,n)(bst, bsh, ba, x); \ + ba += (n); \ + } \ +} + +bus_space_set_region(1,8) +bus_space_set_region(2,16) +bus_space_set_region(4,32) +bus_space_set_region(8,64) + +/*----------------------------------------------------------------------------*/ +static __inline void +bus_space_copy_1(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + char *s = (char *)(h1 + o1); + char *d = (char *)(h2 + o2); + + __asm volatile ("fence w,o" ::: "memory"); + while (c--) + *d++ = *s++; + __asm volatile ("fence io,iwr" ::: "memory"); +} + + +static __inline void +bus_space_copy_2(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + short *s = (short *)(h1 + o1); + short *d = (short *)(h2 + o2); + + __asm volatile ("fence w,o" ::: "memory"); + while (c--) + *d++ = *s++; + __asm volatile ("fence io,iwr" ::: "memory"); +} + +static __inline void +bus_space_copy_4(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + int *s = (int *)(h1 + o1); + int *d = (int *)(h2 + o2); + + __asm volatile ("fence w,o" ::: "memory"); + while (c--) + *d++ = *s++; + __asm volatile ("fence io,iwr" ::: "memory"); +} + +static __inline void +bus_space_copy_8(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + int64_t *s = (int64_t *)(h1 + o1); + int64_t *d = (int64_t *)(h2 + o2); + + __asm volatile ("fence w,o" ::: "memory"); + while (c--) + *d++ = *s++; + __asm volatile ("fence io,iwr" ::: "memory"); +} + +/*----------------------------------------------------------------------------*/ +/* + * Bus read/write barrier methods. + * + * void bus_space_barrier(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * bus_size_t len, int flags); + * + */ +static inline void +bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, + bus_size_t length, int flags) +{ + __asm__ volatile ("fence iorw,iorw" ::: "memory"); +} +#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ +#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ + +#define BUS_DMA_WAITOK 0x0000 +#define BUS_DMA_NOWAIT 0x0001 +#define BUS_DMA_ALLOCNOW 0x0002 +#define BUS_DMA_COHERENT 0x0008 +#define BUS_DMA_BUS1 0x0010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x0020 +#define BUS_DMA_BUS3 0x0040 +#define BUS_DMA_BUS4 0x0080 +#define BUS_DMA_READ 0x0100 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x0200 /* mapping is memory -> device only */ +#define BUS_DMA_STREAMING 0x0400 /* hint: sequential, unidirectional */ +#define BUS_DMA_ZERO 0x0800 /* zero memory in dmamem_alloc */ +#define BUS_DMA_NOCACHE 0x1000 +#define BUS_DMA_64BIT 0x2000 /* device handles 64bit dva */ + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct proc; +struct uio; + +#define BUS_DMASYNC_POSTREAD 0x0001 +#define BUS_DMASYNC_POSTWRITE 0x0002 +#define BUS_DMASYNC_PREREAD 0x0004 +#define BUS_DMASYNC_PREWRITE 0x0008 + +typedef struct machine_bus_dma_tag *bus_dma_tag_t; +typedef struct machine_bus_dmamap *bus_dmamap_t; + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +struct machine_bus_dma_segment { + bus_addr_t ds_addr; /* DMA address */ + bus_size_t ds_len; /* length of transfer */ + + paddr_t _ds_paddr; /* CPU address */ + vaddr_t _ds_vaddr; /* CPU address */ + int _ds_coherent; /* Coherently mapped */ +}; +typedef struct machine_bus_dma_segment bus_dma_segment_t; + +/* + * bus_dma_tag_t + * + * A machine-dependent opaque type describing the implementation of + * DMA for a given bus. + */ + +struct machine_bus_dma_tag { + void *_cookie; /* cookie used in the guts */ + int _flags; /* misc. flags */ + + /* + * DMA mapping methods. + */ + int (*_dmamap_create)(bus_dma_tag_t , bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); + void (*_dmamap_destroy)(bus_dma_tag_t , bus_dmamap_t); + int (*_dmamap_load)(bus_dma_tag_t , bus_dmamap_t, void *, + bus_size_t, struct proc *, int); + int (*_dmamap_load_mbuf)(bus_dma_tag_t , bus_dmamap_t, + struct mbuf *, int); + int (*_dmamap_load_uio)(bus_dma_tag_t , bus_dmamap_t, + struct uio *, int); + int (*_dmamap_load_raw)(bus_dma_tag_t , bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); + int (*_dmamap_load_buffer)(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int, paddr_t *, int *, int); + void (*_dmamap_unload)(bus_dma_tag_t , bus_dmamap_t); + void (*_dmamap_sync)(bus_dma_tag_t , bus_dmamap_t, + bus_addr_t, bus_size_t, int); + + /* + * DMA memory utility functions. + */ + int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); + int (*_dmamem_alloc_range)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int, + paddr_t, paddr_t); + void (*_dmamem_free)(bus_dma_tag_t, bus_dma_segment_t *, int); + int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); + void (*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t); + paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, + int, off_t, int, int); + + /* + * internal memory address translation information. + */ + bus_addr_t _dma_mask; +}; + +#define bus_dmamap_create(t, s, n, m, b, f, p) \ + (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) +#define bus_dmamap_destroy(t, p) \ + (*(t)->_dmamap_destroy)((t), (p)) +#define bus_dmamap_load(t, m, b, s, p, f) \ + (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) +#define bus_dmamap_load_mbuf(t, m, b, f) \ + (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) +#define bus_dmamap_load_uio(t, m, u, f) \ + (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) +#define bus_dmamap_load_raw(t, m, sg, n, s, f) \ + (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) +#define bus_dmamap_unload(t, p) \ + (*(t)->_dmamap_unload)((t), (p)) +#define bus_dmamap_sync(t, p, a, l, o) \ + (void)((t)->_dmamap_sync ? \ + (*(t)->_dmamap_sync)((t), (p), (a), (l), (o)) : (void)0) + +#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ + (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f)) +#define bus_dmamem_alloc_range(t, s, a, b, sg, n, r, f, l, h) \ + (*(t)->_dmamem_alloc_range)((t), (s), (a), (b), (sg), \ + (n), (r), (f), (l), (h)) +#define bus_dmamem_free(t, sg, n) \ + (*(t)->_dmamem_free)((t), (sg), (n)) +#define bus_dmamem_map(t, sg, n, s, k, f) \ + (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f)) +#define bus_dmamem_unmap(t, k, s) \ + (*(t)->_dmamem_unmap)((t), (k), (s)) +#define bus_dmamem_mmap(t, sg, n, o, p, f) \ + (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f)) + +int _dmamap_create(bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); +void _dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); +int _dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); +int _dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *, int); +int _dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, struct uio *, int); +int _dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); +int _dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int, paddr_t *, int *, int); +void _dmamap_unload(bus_dma_tag_t, bus_dmamap_t); +void _dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, + bus_size_t, int); + +int _dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); +void _dmamem_free(bus_dma_tag_t, bus_dma_segment_t *, int); +int _dmamem_map(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); +void _dmamem_unmap(bus_dma_tag_t, caddr_t, size_t); +paddr_t _dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, int, int); +int _dmamem_alloc_range(bus_dma_tag_t, bus_size_t, bus_size_t, bus_size_t, + bus_dma_segment_t *, int, int *, int, paddr_t, paddr_t); + +/* + * bus_dmamap_t + * + * Describes a DMA mapping. + */ +struct machine_bus_dmamap { + /* + * PRIVATE MEMBERS: not for use by machine-independent code. + */ + bus_size_t _dm_size; /* largest DMA transfer mappable */ + int _dm_segcnt; /* number of segs this map can map */ + bus_size_t _dm_maxsegsz; /* largest possible segment */ + bus_size_t _dm_boundary; /* don't cross this */ + int _dm_flags; /* misc. flags */ + + void *_dm_cookie; /* cookie for bus-specific functions */ + + /* + * PUBLIC MEMBERS: these are used by machine-independent code. + */ + bus_size_t dm_mapsize; /* size of the mapping */ + int dm_nsegs; /* # valid segments in mapping */ + bus_dma_segment_t dm_segs[1]; /* segments; variable length */ +}; + +int generic_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, + bus_space_handle_t *); +void generic_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t); +int generic_space_region(bus_space_tag_t, bus_space_handle_t, bus_size_t, + bus_size_t, bus_space_handle_t *); +void *generic_space_vaddr(bus_space_tag_t, bus_space_handle_t); +paddr_t generic_space_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int); +uint8_t generic_space_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint16_t generic_space_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint32_t generic_space_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint64_t generic_space_read_8(bus_space_tag_t, bus_space_handle_t, bus_size_t); +void generic_space_read_raw_2(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint8_t); +void generic_space_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint16_t); +void generic_space_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint32_t); +void generic_space_write_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint64_t); +void generic_space_write_raw_2(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); +void generic_space_read_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); +void generic_space_read_raw_8(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_raw_8(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); + +#endif /* _MACHINE_BUS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/cdefs.h b/lib/libc/include/riscv64-openbsd-none/machine/cdefs.h new file mode 100644 index 000000000000..951add32121c --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/cdefs.h @@ -0,0 +1,16 @@ +/* $OpenBSD: cdefs.h,v 1.1 2021/04/23 02:42:16 drahn Exp $ */ + +#ifndef _MACHINE_CDEFS_H_ +#define _MACHINE_CDEFS_H_ + +#define __strong_alias(alias,sym) \ + __asm__(".global " __STRING(alias) " ; " __STRING(alias) \ + " = " __STRING(sym)) +#define __weak_alias(alias,sym) \ + __asm__(".weak " __STRING(alias) " ; " __STRING(alias) \ + " = " __STRING(sym)) +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning." __STRING(sym) \ + " ; .ascii \"" msg "\" ; .text") + +#endif /* !_MACHINE_CDEFS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/conf.h b/lib/libc/include/riscv64-openbsd-none/machine/conf.h new file mode 100644 index 000000000000..9dc1b949f210 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/conf.h @@ -0,0 +1,50 @@ +/* $OpenBSD: conf.h,v 1.4 2022/06/28 14:43:50 visa Exp $ */ + +/* + * Copyright (c) 1996 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_CONF_H_ +#define _MACHINE_CONF_H_ + +#include + +#define mmread mmrw +#define mmwrite mmrw +cdev_decl(mm); + +/* open, close, ioctl */ +#define cdev_openprom_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) nullop, 0, \ + (dev_type_mmap((*))) enodev } + +cdev_decl(openprom); + +#endif /* _MACHINE_CONF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/cpu.h b/lib/libc/include/riscv64-openbsd-none/machine/cpu.h new file mode 100644 index 000000000000..8e6ecc4dca9a --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/cpu.h @@ -0,0 +1,284 @@ +/* $OpenBSD: cpu.h,v 1.24 2024/06/11 16:02:35 jca Exp $ */ + +/* + * Copyright (c) 2019 Mike Larkin + * Copyright (c) 2016 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_CPU_H_ +#define _MACHINE_CPU_H_ + +/* + * User-visible definitions + */ + +/* CTL_MACHDEP definitions. */ +#define CPU_COMPATIBLE 1 /* compatible property */ +#define CPU_MAXID 2 /* number of valid machdep ids */ + +#define CTL_MACHDEP_NAMES { \ + { 0, 0 }, \ + { "compatible", CTLTYPE_STRING }, \ +} + +#ifdef _KERNEL + +/* + * Kernel-only definitions + */ +#include +#include +#include + +/* All the CLKF_* macros take a struct clockframe * as an argument. */ + +#define clockframe trapframe +/* + * CLKF_USERMODE: Return TRUE/FALSE (1/0) depending on whether the + * frame came from USR mode or not. + */ +#define CLKF_USERMODE(frame) ((frame->tf_sstatus & SSTATUS_SPP) == 0) + +/* + * CLKF_INTR: True if we took the interrupt from inside another + * interrupt handler. + */ +#define CLKF_INTR(frame) (curcpu()->ci_idepth > 1) + +/* + * CLKF_PC: Extract the program counter from a clockframe + */ +#define CLKF_PC(frame) (frame->tf_sepc) + +/* + * PROC_PC: Find out the program counter for the given process. + */ +#define PROC_PC(p) ((p)->p_addr->u_pcb.pcb_tf->tf_sepc) +#define PROC_STACK(p) ((p)->p_addr->u_pcb.pcb_tf->tf_sp) + +#include +#include +#include +#include +#include + +struct cpu_info { + struct device *ci_dev; /* Device corresponding to this CPU */ + struct cpu_info *ci_next; + struct schedstate_percpu ci_schedstate; /* scheduler state */ + + u_int32_t ci_cpuid; + uint64_t ci_hartid; + int ci_node; + struct cpu_info *ci_self; + + struct proc *ci_curproc; + struct pmap *ci_curpm; + u_int32_t ci_randseed; + + struct pcb *ci_curpcb; + struct pcb *ci_idle_pcb; + + struct clockqueue ci_queue; + volatile int ci_timer_deferred; + + uint32_t ci_cpl; + uint32_t ci_ipending; + uint32_t ci_idepth; +#ifdef DIAGNOSTIC + int ci_mutex_level; +#endif + int ci_want_resched; + + struct opp_table *ci_opp_table; + volatile int ci_opp_idx; + volatile int ci_opp_max; + uint32_t ci_cpu_supply; + +#ifdef MULTIPROCESSOR + struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM]; +#define __HAVE_UVM_PERCPU + struct uvm_pmr_cache ci_uvm; + volatile int ci_flags; + uint64_t ci_satp; + vaddr_t ci_initstack_end; + int ci_ipi_reason; + + volatile int ci_ddb_paused; +#define CI_DDB_RUNNING 0 +#define CI_DDB_SHOULDSTOP 1 +#define CI_DDB_STOPPED 2 +#define CI_DDB_ENTERDDB 3 +#define CI_DDB_INDDB 4 + +#endif + +#ifdef GPROF + struct gmonparam *ci_gmon; + struct clockintr ci_gmonclock; +#endif + + char ci_panicbuf[512]; +}; + +#define CPUF_PRIMARY (1<<0) +#define CPUF_AP (1<<1) +#define CPUF_IDENTIFY (1<<2) +#define CPUF_IDENTIFIED (1<<3) +#define CPUF_PRESENT (1<<4) +#define CPUF_GO (1<<5) +#define CPUF_RUNNING (1<<6) + +static inline struct cpu_info * +curcpu(void) +{ + struct cpu_info *__ci = NULL; + __asm volatile("mv %0, tp" : "=&r"(__ci)); + return (__ci); +} + +extern uint32_t boot_hart; /* The hart we booted on. */ +extern struct cpu_info cpu_info_primary; +extern struct cpu_info *cpu_info_list; + +#ifndef MULTIPROCESSOR + +#define cpu_number() 0 +#define CPU_IS_PRIMARY(ci) 1 +#define CPU_IS_RUNNING(ci) 1 +#define CPU_INFO_ITERATOR int +#define CPU_INFO_FOREACH(cii, ci) \ + for (cii = 0, ci = curcpu(); ci != NULL; ci = NULL) +#define CPU_INFO_UNIT(ci) 0 +#define MAXCPUS 1 +#define cpu_unidle(ci) + +#else + +#define cpu_number() (curcpu()->ci_cpuid) +#define CPU_IS_PRIMARY(ci) ((ci) == &cpu_info_primary) +#define CPU_IS_RUNNING(ci) ((ci)->ci_flags & CPUF_RUNNING) +#define CPU_INFO_ITERATOR int +#define CPU_INFO_FOREACH(cii, ci) for (cii = 0, ci = cpu_info_list; \ + ci != NULL; ci = ci->ci_next) +#define CPU_INFO_UNIT(ci) ((ci)->ci_dev ? (ci)->ci_dev->dv_unit : 0) +#define MAXCPUS 32 + +extern struct cpu_info *cpu_info[MAXCPUS]; + +void cpu_boot_secondary_processors(void); + +#endif /* !MULTIPROCESSOR */ + +/* Zihintpause ratified extension */ +#define CPU_BUSY_CYCLE() __asm volatile(".long 0x0100000f" ::: "memory") + +#define curpcb curcpu()->ci_curpcb + +static inline unsigned int +cpu_rnd_messybits(void) +{ + // Should do bit reversal ^ with csr_read(time); + return csr_read(time); +} + +/* + * Scheduling glue + */ +#define aston(p) ((p)->p_md.md_astpending = 1) +#define setsoftast() aston(curcpu()->ci_curproc) + +/* + * Notify the current process (p) that it has a signal pending, + * process as soon as possible. + */ + +#ifdef MULTIPROCESSOR +void cpu_unidle(struct cpu_info *ci); +#define signotify(p) (aston(p), cpu_unidle((p)->p_cpu)) +void cpu_kick(struct cpu_info *); +#else +#define cpu_kick(ci) +#define cpu_unidle(ci) +#define signotify(p) setsoftast() +#endif + +/* + * Preempt the current process if in interrupt from user mode, + * or after the current trap/syscall if in system mode. + */ +void need_resched(struct cpu_info *); +#define clear_resched(ci) ((ci)->ci_want_resched = 0) + +/* + * Give a profiling tick to the current process when the user profiling + * buffer pages are invalid. On the i386, request an ast to send us + * through trap(), marking the proc as needing a profiling tick. + */ +#define need_proftick(p) aston(p) + +// asm code to start new kernel contexts. +void proc_trampoline(void); + +/* + * Random cruft + */ +void dumpconf(void); + +static inline void +intr_enable(void) +{ + __asm volatile("csrsi sstatus, %0" :: "i" (SSTATUS_SIE)); +} + +static inline u_long +intr_disable(void) +{ + uint64_t ret; + + __asm volatile( + "csrrci %0, sstatus, %1" + : "=&r" (ret) : "i" (SSTATUS_SIE) + ); + + return (ret & (SSTATUS_SIE)); +} + +static inline void +intr_restore(u_long s) +{ + __asm volatile("csrs sstatus, %0" :: "r" (s)); +} + +void delay (unsigned); +#define DELAY(x) delay(x) + +extern void (*cpu_startclock_fcn)(void); + +void fpu_save(struct proc *, struct trapframe *); +void fpu_load(struct proc *); + +extern int cpu_errata_sifive_cip_1200; + +#define cpu_idle_enter() do { /* nothing */ } while (0) +#define cpu_idle_leave() do { /* nothing */ } while (0) + +#endif /* _KERNEL */ + +#ifdef MULTIPROCESSOR +#include +#endif /* MULTIPROCESSOR */ + +#endif /* !_MACHINE_CPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/cpufunc.h b/lib/libc/include/riscv64-openbsd-none/machine/cpufunc.h new file mode 100644 index 000000000000..f4b61288bb38 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/cpufunc.h @@ -0,0 +1,103 @@ +/* $OpenBSD: cpufunc.h,v 1.6 2023/08/21 20:17:30 miod Exp $ */ + +/*- + * Copyright (c) 2014 Andrew Turner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: head/sys/cpu/include/cpufunc.h 299683 2016-05-13 16:03:50Z andrew $ + */ + +#ifndef _MACHINE_CPUFUNC_H_ +#define _MACHINE_CPUFUNC_H_ + +static __inline void +breakpoint(void) +{ + __asm("ebreak"); +} + +#ifdef _KERNEL + +#include + +#define rdcycle() csr_read(cycle) +#define rdtime() csr_read(time) +#define rdinstret() csr_read(instret) +#define rdhpmcounter(n) csr_read(hpmcounter##n) + +static __inline void +fence_i(void) +{ + __asm volatile("fence.i" ::: "memory"); +} + +static __inline void +sfence_vma(void) +{ + __asm volatile("sfence.vma" ::: "memory"); +} + +static __inline void +sfence_vma_page(uintptr_t addr) +{ + __asm volatile("sfence.vma %0" + : + : "r" (addr) + : "memory"); +} + +// XXX ASIDs in riscv64 are only 16 bits. +static __inline void +sfence_vma_asid(uint64_t asid) +{ + __asm volatile("sfence.vma x0, %0" + : + : "r" (asid) + : "memory"); +} + +static __inline void +sfence_vma_page_asid(uintptr_t addr, uint64_t asid) +{ + __asm volatile("sfence.vma %0, %1" + : + : "r" (addr), "r" (asid) + : "memory"); +} + +extern int64_t dcache_line_size; +extern int64_t icache_line_size; + +extern void (*cpu_dcache_wbinv_range)(paddr_t, psize_t); +extern void (*cpu_dcache_inv_range)(paddr_t, psize_t); +extern void (*cpu_dcache_wb_range)(paddr_t, psize_t); + +static __inline void +load_satp(uint64_t val) +{ + __asm volatile("csrw satp, %0" :: "r"(val)); +} + +#endif /* _KERNEL */ +#endif /* _MACHINE_CPUFUNC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/db_machdep.h b/lib/libc/include/riscv64-openbsd-none/machine/db_machdep.h new file mode 100644 index 000000000000..0d0e4fdfb956 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/db_machdep.h @@ -0,0 +1,93 @@ +/* $OpenBSD: db_machdep.h,v 1.5 2021/08/30 08:11:12 jasper Exp $ */ + +/* + * Copyright (c) 2019 Brian Bamsch + * Copyright (c) 2015-2016 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_DB_MACHDEP_H_ +#define _MACHINE_DB_MACHDEP_H_ + +#include +#include +#include +#include +#include + +#define T_BREAKPOINT (EXCP_BREAKPOINT) +#define T_WATCHPOINT (0) + +typedef long db_expr_t; + +typedef trapframe_t db_regs_t; + +extern db_regs_t ddb_regs; +#define DDB_REGS (&ddb_regs) + +#define PC_REGS(regs) ((vaddr_t)(regs)->tf_ra) +#define SET_PC_REGS(regs, value) (regs)->tf_ra = (register_t)(value) + +#define BKPT_INST (KERNEL_BREAKPOINT) +#define BKPT_SIZE (INSN_SIZE) +#define BKPT_SET(inst) (BKPT_INST) + +#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BREAKPOINT) +#define IS_WATCHPOINT_TRAP(type, code) ((type) == T_WATCHPOINT) + +#define inst_trap_return(ins) (ins == 0x10000073) /* eret */ +#define inst_return(ins) (ins == 0x00008067) /* ret */ +#define inst_call(ins) (((ins) & 0x7f) == 0x6f || \ + ((ins) & 0x7f) == 0x67) /* jal, jalr */ +#define inst_branch(ins) (((ins) & 0x7f) == 0x63) /* branch */ + +#define next_instr_address(pc, bd) ((bd) ? (pc) : ((pc) + INSN_SIZE)) + +#define DB_MACHINE_COMMANDS + +#define SOFTWARE_SSTEP + +int db_trapper(vaddr_t, u_int, trapframe_t *, int); +void db_machine_init (void); +vaddr_t db_branch_taken(u_int inst, vaddr_t pc, db_regs_t *regs); + +#define branch_taken(ins, pc, fun, regs) \ + db_branch_taken((ins), (pc), (regs)) + +/* For ddb_state */ +#define DDB_STATE_NOT_RUNNING 0 +#define DDB_STATE_RUNNING 1 +#define DDB_STATE_EXITING 2 + +#endif /* !_MACHINE_DB_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/disklabel.h b/lib/libc/include/riscv64-openbsd-none/machine/disklabel.h new file mode 100644 index 000000000000..fcb739943e89 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/disklabel.h @@ -0,0 +1,26 @@ +/* $OpenBSD: disklabel.h,v 1.2 2021/05/12 01:20:52 jsg Exp $ */ + +/* + * Copyright (c) 2014 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_DISKLABEL_H_ +#define _MACHINE_DISKLABEL_H_ + +#define LABELSECTOR 1 /* sector containing label */ +#define LABELOFFSET 0 /* offset of label in sector */ +#define MAXPARTITIONS 16 /* number of partitions */ + +#endif /* _MACHINE_DISKLABEL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/elf.h b/lib/libc/include/riscv64-openbsd-none/machine/elf.h new file mode 100644 index 000000000000..651c966fb81c --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/elf.h @@ -0,0 +1,52 @@ +/* $OpenBSD: elf.h,v 1.3 2024/07/14 09:48:49 jca Exp $ */ + +/*- + * Copyright (c) 1996-1997 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_ELF_H_ +#define _MACHINE_ELF_H_ + +/* + * ELF definitions for the RISC-V architecture. + */ + +#ifdef _KERNEL +# define __HAVE_CPU_HWCAP +extern unsigned long hwcap; +#endif /* _KERNEL */ + +/* Flags passed in AT_HWCAP */ +#define HWCAP_ISA_BIT(c) (1 << ((c) - 'a')) +#define HWCAP_ISA_I HWCAP_ISA_BIT('i') +#define HWCAP_ISA_M HWCAP_ISA_BIT('m') +#define HWCAP_ISA_A HWCAP_ISA_BIT('a') +#define HWCAP_ISA_F HWCAP_ISA_BIT('f') +#define HWCAP_ISA_D HWCAP_ISA_BIT('d') +#define HWCAP_ISA_C HWCAP_ISA_BIT('c') +#define HWCAP_ISA_G \ + (HWCAP_ISA_I | HWCAP_ISA_M | HWCAP_ISA_A | HWCAP_ISA_F | HWCAP_ISA_D) + +#endif /* !_MACHINE_ELF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/endian.h b/lib/libc/include/riscv64-openbsd-none/machine/endian.h new file mode 100644 index 000000000000..b63c54e85059 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/endian.h @@ -0,0 +1,29 @@ +/* $OpenBSD: endian.h,v 1.3 2022/03/22 06:46:45 miod Exp $ */ + +/* + * Copyright (c) 2015 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_ENDIAN_H_ +#define _MACHINE_ENDIAN_H_ + +#define _BYTE_ORDER _LITTLE_ENDIAN +#define __STRICT_ALIGNMENT + +#ifndef __FROM_SYS__ENDIAN +#include +#endif + +#endif /* _MACHINE_ENDIAN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/exec.h b/lib/libc/include/riscv64-openbsd-none/machine/exec.h new file mode 100644 index 000000000000..a6073819af0e --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/exec.h @@ -0,0 +1,30 @@ +/* $OpenBSD: exec.h,v 1.2 2021/05/12 01:20:52 jsg Exp $ */ + +/* + * Copyright (c) 2014 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_EXEC_H_ +#define _MACHINE_EXEC_H_ + +#define __LDPGSZ 4096 + +#define ARCH_ELFSIZE 64 + +#define ELF_TARG_CLASS ELFCLASS64 +#define ELF_TARG_DATA ELFDATA2LSB +#define ELF_TARG_MACH EM_RISCV + +#endif \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/fdt.h b/lib/libc/include/riscv64-openbsd-none/machine/fdt.h new file mode 100644 index 000000000000..536ed4d04bcc --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/fdt.h @@ -0,0 +1,59 @@ +/* $OpenBSD: fdt.h,v 1.4 2022/05/30 17:39:09 kettenis Exp $ */ + +/* + * Copyright (c) 2016 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __RISCV_FDT_H__ +#define __RISCV_FDT_H__ + +#define _RISCV64_BUS_DMA_PRIVATE +#include + +struct fdt_attach_args { + const char *fa_name; + int fa_node; + bus_space_tag_t fa_iot; + bus_dma_tag_t fa_dmat; + struct fdt_reg *fa_reg; + int fa_nreg; + uint32_t *fa_intr; + int fa_nintr; + int fa_acells; + int fa_scells; +}; + +extern int stdout_node; +extern int stdout_speed; +extern bus_space_tag_t fdt_cons_bs_tag; + +void *fdt_find_cons(const char *); + +#define fdt_intr_enable riscv_intr_enable +#define fdt_intr_establish riscv_intr_establish_fdt +#define fdt_intr_establish_idx riscv_intr_establish_fdt_idx +#define fdt_intr_establish_idx_cpu riscv_intr_establish_fdt_idx_cpu +#define fdt_intr_establish_imap riscv_intr_establish_fdt_imap +#define fdt_intr_establish_imap_cpu riscv_intr_establish_fdt_imap_cpu +#define fdt_intr_establish_msi riscv_intr_establish_fdt_msi +#define fdt_intr_establish_msi_cpu riscv_intr_establish_fdt_msi_cpu +#define fdt_intr_disable riscv_intr_disable +#define fdt_intr_disestablish riscv_intr_disestablish_fdt +#define fdt_intr_get_parent riscv_intr_get_parent +#define fdt_intr_parent_establish riscv_intr_parent_establish_fdt +#define fdt_intr_parent_disestablish riscv_intr_parent_disestablish_fdt +#define fdt_intr_register riscv_intr_register_fdt + +#endif /* __RISCV_FDT_H__ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/fenv.h b/lib/libc/include/riscv64-openbsd-none/machine/fenv.h new file mode 100644 index 000000000000..e1645e961c93 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/fenv.h @@ -0,0 +1,95 @@ +/* $OpenBSD: fenv.h,v 1.2 2021/05/12 02:28:25 jsg Exp $ */ + +/* + * Copyright (c) 2011 Martynas Venckus + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_FENV_H_ +#define _MACHINE_FENV_H_ + +/* + * Each symbol representing a floating point exception expands to an integer + * constant expression with values, such that bitwise-inclusive ORs of _all + * combinations_ of the constants result in distinct values. + * + * We use such values that allow direct bitwise operations on FPU registers. + */ +#define FE_INVALID 0x10 +#define FE_DIVBYZERO 0x08 +#define FE_OVERFLOW 0x04 +#define FE_UNDERFLOW 0x02 +#define FE_INEXACT 0x01 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * exception constants defined above. + */ +#define FE_ALL_EXCEPT (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | \ + FE_UNDERFLOW | FE_INEXACT ) + +/* + * Each symbol representing the rounding direction, expands to an integer + * constant expression whose value is distinct non-negative value. + * + * We use such values that allow direct bitwise operations on FPU registers. + */ +#define FE_TONEAREST 0x0 +#define FE_TOWARDZERO 0x1 +#define FE_DOWNWARD 0x2 +#define FE_UPWARD 0x3 +#define FE_TONEARESTFROMZERO 0x4 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * rounding direction constants defined above. + */ +#define _ROUND_MASK (FE_TONEAREST | FE_TOWARDZERO | FE_DOWNWARD | \ + FE_UPWARD | FE_TONEARESTFROMZERO) +#define _ROUND_SHIFT 5 + +/* + * fenv_t represents the entire floating-point environment. + */ +typedef unsigned int fenv_t; + +/* + * The following constant represents the default floating-point environment + * (that is, the one installed at program startup) and has type pointer to + * const-qualified fenv_t. + * + * It can be used as an argument to the functions within the header + * that manage the floating-point environment, namely fesetenv() and + * feupdateenv(). + */ +__BEGIN_DECLS +extern fenv_t __fe_dfl_env; +__END_DECLS +#define FE_DFL_ENV ((const fenv_t *)&__fe_dfl_env) + +/* + * fexcept_t represents the floating-point status flags collectively, including + * any status the implementation associates with the flags. + * + * A floating-point status flag is a system variable whose value is set (but + * never cleared) when a floating-point exception is raised, which occurs as a + * side effect of exceptional floating-point arithmetic to provide auxiliary + * information. + * + * A floating-point control mode is a system variable whose value may be set by + * the user to affect the subsequent behavior of floating-point arithmetic. + */ +typedef unsigned int fexcept_t; + +#endif /* !_MACHINE_FENV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/frame.h b/lib/libc/include/riscv64-openbsd-none/machine/frame.h new file mode 100644 index 000000000000..e15698128f54 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/frame.h @@ -0,0 +1,99 @@ +/* $OpenBSD: frame.h,v 1.3 2022/02/24 14:19:10 visa Exp $ */ + +/* + * Copyright (c) 2019 Brian Bamsch + * Copyright (c) 2016 Dale Rahn + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 _MACHINE_FRAME_H_ +#define _MACHINE_FRAME_H_ + +#ifndef _LOCORE + +#include + +/* + * Exception/Trap Stack Frame + */ +#define clockframe trapframe +typedef struct trapframe { + /* Standard Registers */ + register_t tf_ra; + register_t tf_sp; + register_t tf_gp; + register_t tf_tp; + register_t tf_t[7]; + register_t tf_s[12]; + register_t tf_a[8]; + /* Supervisor Trap CSRs */ + register_t tf_sepc; + register_t tf_sstatus; + register_t tf_stval; + register_t tf_scause; + register_t tf_pad; +} trapframe_t; + +/* + * pushed on stack for signal delivery + */ +struct sigframe { + int sf_signum; + struct sigcontext sf_sc; + siginfo_t sf_si; +}; + +/* + * System stack frames. + */ + +/* + * Stack frame inside cpu_switch() + */ +struct switchframe { + register_t sf_s[12]; + register_t sf_ra; + register_t sf_pad; +}; + +struct callframe { + struct callframe *f_frame; + register_t f_ra; +}; + +#endif /* !_LOCORE */ + +#endif /* !_MACHINE_FRAME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/ieee.h b/lib/libc/include/riscv64-openbsd-none/machine/ieee.h new file mode 100644 index 000000000000..74d6e987a900 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/ieee.h @@ -0,0 +1,148 @@ +/* $OpenBSD: ieee.h,v 1.3 2021/05/12 01:20:52 jsg Exp $ */ +/* $NetBSD: ieee.h,v 1.1 1996/09/30 16:34:25 ws Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ieee.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * ieee.h defines the machine-dependent layout of the machine's IEEE + * floating point. It does *not* define (yet?) any of the rounding + * mode bits, exceptions, and so forth. + */ + +/* + * Define the number of bits in each fraction and exponent. + * + * k k+1 + * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented + * + * (-exp_bias+1) + * as fractions that look like 0.fffff x 2 . This means that + * + * -126 + * the number 0.10000 x 2 , for instance, is the same as the normalized + * + * -127 -128 + * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero + * + * -129 + * in the fraction; to represent 2 , we need two, and so on. This + * + * (-exp_bias-fracbits+1) + * implies that the smallest denormalized number is 2 + * + * for whichever format we are talking about: for single precision, for + * + * -126 -149 + * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and + * + * -149 == -127 - 23 + 1. + */ +#define SNG_EXPBITS 8 +#define SNG_FRACBITS 23 + +#define DBL_EXPBITS 11 +#define DBL_FRACHBITS 20 +#define DBL_FRACLBITS 32 +#define DBL_FRACBITS 52 + +#define EXT_EXPBITS 15 +#define EXT_FRACHBITS 16 +#define EXT_FRACHMBITS 32 +#define EXT_FRACLMBITS 32 +#define EXT_FRACLBITS 32 +#define EXT_FRACBITS 112 + +#define EXT_IMPLICIT_NBIT + +#define EXT_TO_ARRAY32(p, a) do { \ + (a)[0] = (uint32_t)(p)->ext_fracl; \ + (a)[1] = (uint32_t)(p)->ext_fraclm; \ + (a)[2] = (uint32_t)(p)->ext_frachm; \ + (a)[3] = (uint32_t)(p)->ext_frach; \ +} while (0) + +struct ieee_single { + u_int sng_frac:23; + u_int sng_exp:8; + u_int sng_sign:1; +}; + +struct ieee_double { + u_int dbl_fracl; + u_int dbl_frach:20; + u_int dbl_exp:11; + u_int dbl_sign:1; +}; + +struct ieee_ext { + u_int ext_fracl; + u_int ext_fraclm; + u_int ext_frachm; + u_int ext_frach:16; + u_int ext_exp:15; + u_int ext_sign:1; +}; + +/* + * Floats whose exponent is in [1..INFNAN) (of whatever type) are + * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. + * Floats whose exponent is zero are either zero (iff all fraction + * bits are zero) or subnormal values. + * + * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its + * high fraction; if the bit is set, it is a `quiet NaN'. + */ +#define SNG_EXP_INFNAN 255 +#define DBL_EXP_INFNAN 2047 +#define EXT_EXP_INFNAN 32767 + +#if 0 +#define SNG_QUIETNAN (1 << 22) +#define DBL_QUIETNAN (1 << 19) +#define EXT_QUIETNAN (1 << 15) +#endif + +/* + * Exponent biases. + */ +#define SNG_EXP_BIAS 127 +#define DBL_EXP_BIAS 1023 +#define EXT_EXP_BIAS 16383 \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/ieeefp.h b/lib/libc/include/riscv64-openbsd-none/machine/ieeefp.h new file mode 100644 index 000000000000..e8f7507588d0 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/ieeefp.h @@ -0,0 +1,25 @@ +/* $OpenBSD: ieeefp.h,v 1.3 2021/04/30 00:25:52 drahn Exp $ */ + +/* + * Based on ieeefp.h written by J.T. Conklin, Apr 28, 1995 + * Public domain. + */ + +#ifndef _MACHINE_IEEEFP_H_ +#define _MACHINE_IEEEFP_H_ + +typedef int fp_except; +#define FP_X_INV 0x10 /* invalid operation exception */ +#define FP_X_DZ 0x08 /* divide-by-zero exception */ +#define FP_X_OFL 0x04 /* overflow exception */ +#define FP_X_UFL 0x02 /* underflow exception */ +#define FP_X_IMP 0x01 /* imprecise (loss of precision) */ + +typedef enum { + FP_RN=0, /* round to nearest representable number */ + FP_RZ=1, /* round to zero (truncate) */ + FP_RM=2, /* round toward negative infinity */ + FP_RP=3 /* round toward positive infinity */ +} fp_rnd; + +#endif /* _MACHINE_IEEEFP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/intr.h b/lib/libc/include/riscv64-openbsd-none/machine/intr.h new file mode 100644 index 000000000000..14ef73c2133d --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/intr.h @@ -0,0 +1,227 @@ +/* $OpenBSD: intr.h,v 1.10 2025/05/19 02:13:15 jsg Exp $ */ + +/* + * Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _MACHINE_INTR_H_ +#define _MACHINE_INTR_H_ + +/* + * The interrupt level ipl is a logical level; per-platform interrupt + * code will turn it into the appropriate hardware interrupt masks + * values. + * + * Interrupt sources on the CPU are kept enabled regardless of the + * current ipl value; individual hardware sources interrupting while + * logically masked are masked on the fly, remembered as pending, and + * unmasked at the first splx() opportunity. + */ +#ifdef _KERNEL + +/* Interrupt priority `levels'; not mutually exclusive. */ +#define IPL_NONE 0 /* nothing */ +#define IPL_SOFTCLOCK 2 /* soft clock interrupts */ +#define IPL_SOFTNET 3 /* soft network interrupts */ +#define IPL_SOFTTTY 4 /* soft terminal interrupts */ +#define IPL_BIO 5 /* block I/O */ +#define IPL_NET 6 /* network */ +#define IPL_TTY 7 /* terminal */ +#define IPL_VM 8 /* memory allocation */ +#define IPL_AUDIO 9 /* audio */ +#define IPL_CLOCK 10 /* clock */ +#define IPL_SCHED IPL_CLOCK +#define IPL_STATCLOCK IPL_CLOCK +#define IPL_HIGH 11 /* everything */ +#define IPL_IPI 12 /* interprocessor interrupt */ +#define NIPL 13 /* number of levels */ + +#define IPL_MPFLOOR IPL_TTY +/* Interrupt priority 'flags'. */ +#define IPL_IRQMASK 0xf /* priority only */ +#define IPL_FLAGMASK 0xf00 /* flags only*/ +#define IPL_MPSAFE 0x100 /* 'mpsafe' interrupt, no kernel lock */ + +/* Interrupt sharing types. */ +#define IST_NONE 0 /* none */ +#define IST_PULSE 1 /* pulsed */ +#define IST_EDGE 2 /* edge-triggered */ +#define IST_LEVEL 3 /* level-triggered */ + +#define IST_LEVEL_LOW IST_LEVEL +#define IST_LEVEL_HIGH 4 +#define IST_EDGE_FALLING IST_EDGE +#define IST_EDGE_RISING 5 +#define IST_EDGE_BOTH 6 + +enum { + IRQ_SOFTWARE_USER, + IRQ_SOFTWARE_SUPERVISOR, + IRQ_SOFTWARE_HYPERVISOR, + IRQ_SOFTWARE_MACHINE, + IRQ_TIMER_USER, + IRQ_TIMER_SUPERVISOR, + IRQ_TIMER_HYPERVISOR, + IRQ_TIMER_MACHINE, + IRQ_EXTERNAL_USER, + IRQ_EXTERNAL_SUPERVISOR, + IRQ_EXTERNAL_HYPERVISOR, + IRQ_EXTERNAL_MACHINE, + INTC_NIRQS +}; + +#define __USE_MI_SOFTINTR + +#include + +#ifndef _LOCORE +#include + +void softintr(int); + +int splraise(int); +int spllower(int); +void splx(int); + +void riscv_cpu_intr(void *); +void riscv_do_pending_intr(int); +void riscv_set_intr_func(int (*raise)(int), int (*lower)(int), + void (*x)(int), void (*setipl)(int)); +void riscv_set_intr_handler(void (*intr_handle)(void *)); + +struct machine_intr_handle { + struct interrupt_controller *ih_ic; + void *ih_ih; +}; + +struct riscv_intr_func { + int (*raise)(int); + int (*lower)(int); + void (*x)(int); + void (*setipl)(int); +}; + +extern struct riscv_intr_func riscv_intr_func; + +#define splraise(cpl) (riscv_intr_func.raise(cpl)) +#define _splraise(cpl) (riscv_intr_func.raise(cpl)) +#define spllower(cpl) (riscv_intr_func.lower(cpl)) +#define splx(cpl) (riscv_intr_func.x(cpl)) + +#define splsoftclock() splraise(IPL_SOFTCLOCK) +#define splsoftnet() splraise(IPL_SOFTNET) +#define splsofttty() splraise(IPL_SOFTTTY) +#define splbio() splraise(IPL_BIO) +#define splnet() splraise(IPL_NET) +#define spltty() splraise(IPL_TTY) +#define splvm() splraise(IPL_VM) +#define splaudio() splraise(IPL_AUDIO) +#define splclock() splraise(IPL_CLOCK) +#define splsched() splraise(IPL_SCHED) +#define splstatclock() splraise(IPL_STATCLOCK) +#define splhigh() splraise(IPL_HIGH) + +#define spl0() spllower(IPL_NONE) + +void intr_barrier(void *); + +void riscv_init_smask(void); /* XXX */ +extern uint32_t riscv_smask[NIPL]; + +void riscv_clock_register(void (*)(void), void (*)(u_int), void (*)(int), + void (*)(void)); + +/* + **** interrupt controller structure and routines **** + */ +struct cpu_info; +struct interrupt_controller { + int ic_node; + void *ic_cookie; + void *(*ic_establish)(void *, int *, int, struct cpu_info *, + int (*)(void *), void *, char *); + void *(*ic_establish_msi)(void *, uint64_t *, uint64_t *, int, + struct cpu_info *, int (*)(void *), void *, char *); + void (*ic_disestablish)(void *); + void (*ic_enable)(void *); + void (*ic_disable)(void *); + void (*ic_route)(void *, int, struct cpu_info *); + void (*ic_cpu_enable)(void); + void (*ic_barrier)(void *); + + LIST_ENTRY(interrupt_controller) ic_list; + uint32_t ic_phandle; + uint32_t ic_cells; +}; + +void riscv_intr_init_fdt(void); +void riscv_intr_register_fdt(struct interrupt_controller *); +void *riscv_intr_establish_fdt(int, int, int (*)(void *), + void *, char *); +void *riscv_intr_establish_fdt_idx(int, int, int, int (*)(void *), + void *, char *); +void *riscv_intr_establish_fdt_idx_cpu(int, int, int, struct cpu_info *, + int (*)(void *), void *, char *); +void *riscv_intr_establish_fdt_imap_cpu(int, int *, int, int, + struct cpu_info *, int (*)(void *), void *, char *); +void *riscv_intr_establish_fdt_msi(int, uint64_t *, uint64_t *, int, + int (*)(void *), void *, char *); +void *riscv_intr_establish_fdt_msi_cpu(int, uint64_t *, uint64_t *, int, + struct cpu_info *, int (*)(void *), void *, char *); +void riscv_intr_disestablish_fdt(void *); +void riscv_intr_enable(void *); +void riscv_intr_disable(void *); +void riscv_intr_route(void *, int, struct cpu_info *); +void riscv_intr_cpu_enable(void); + +#define IPI_NOP 0 +#define IPI_DDB (1 << 0) + +void intr_send_ipi(struct cpu_info *, int); + +#ifdef DIAGNOSTIC +/* + * Although this function is implemented in MI code, it must be in this MD + * header because we don't want this header to include MI includes. + */ +void splassert_fail(int, int, const char *); +extern int splassert_ctl; +void riscv_splassert_check(int, const char *); +#define splassert(__wantipl) do { \ + if (splassert_ctl > 0) { \ + riscv_splassert_check(__wantipl, __func__); \ + } \ +} while (0) +#define splsoftassert(wantipl) splassert(wantipl) +#else +#define splassert(wantipl) do { /* nothing */ } while (0) +#define splsoftassert(wantipl) do { /* nothing */ } while (0) +#endif + +#endif /* ! _LOCORE */ + +#endif /* _KERNEL */ + +#endif /* _MACHINE_INTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/kcore.h b/lib/libc/include/riscv64-openbsd-none/machine/kcore.h new file mode 100644 index 000000000000..484ee5d0ee8c --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/kcore.h @@ -0,0 +1,16 @@ +/* $OpenBSD: kcore.h,v 1.2 2021/05/12 01:20:52 jsg Exp $ */ + +/* public domain */ + +/* Make sure this is larger than DRAM_BLOCKS on all arm-based platforms */ +#define NPHYS_RAM_SEGS 8 + +typedef struct cpu_kcore_hdr { + u_int64_t kernelbase; /* value of KERNEL_BASE */ + u_int64_t kerneloffs; /* offset of kernel in RAM */ + u_int64_t staticsize; /* size of contiguous mapping */ + u_int64_t pmap_kernel_l1; /* pmap_kernel()->pm_l1 */ + u_int64_t pmap_kernel_l2; /* pmap_kernel()->pm_l2 */ + u_int64_t reserved[11]; + phys_ram_seg_t ram_segs[NPHYS_RAM_SEGS]; +} cpu_kcore_hdr_t; \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/limits.h b/lib/libc/include/riscv64-openbsd-none/machine/limits.h new file mode 100644 index 000000000000..e06dde0b2bb9 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/limits.h @@ -0,0 +1,56 @@ +/* $OpenBSD: limits.h,v 1.2 2021/06/25 19:22:51 matthieu Exp $ */ +/* $NetBSD: limits.h,v 1.4 2003/04/28 23:16:18 bjh21 Exp $ */ + +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)limits.h 7.2 (Berkeley) 6/28/90 + */ + +#ifndef _MACHINE_LIMITS_H_ +#define _MACHINE_LIMITS_H_ + +#include + +#if __POSIX_VISIBLE || __XPG_VISIBLE +#ifndef SIZE_MAX +#define SIZE_MAX ULONG_MAX /* max value for a size_t */ +#endif +#define SSIZE_MAX LONG_MAX /* max value for a ssize_t */ +#endif + +#if __BSD_VISIBLE +#define SIZE_T_MAX ULONG_MAX /* max value for a size_t (historic) */ + +#define UQUAD_MAX (ULONG_MAX) /* max unsigned quad */ +#define QUAD_MAX (LONG_MAX) /* max signed quad */ +#define QUAD_MIN (LONG_MIN) /* min signed quad */ + +#endif /* __BSD_VISIBLE */ + +#endif /* _MACHINE_LIMITS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/loadfile_machdep.h b/lib/libc/include/riscv64-openbsd-none/machine/loadfile_machdep.h new file mode 100644 index 000000000000..c6b1f00082b4 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/loadfile_machdep.h @@ -0,0 +1,53 @@ +/* $OpenBSD: loadfile_machdep.h,v 1.2 2021/04/23 15:31:12 drahn Exp $ */ +/* $NetBSD: loadfile_machdep.h,v 1.1 1999/04/29 03:17:12 tsubai Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define BOOT_ELF +#define ELFSIZE 64 + +#define LOAD_KERNEL (LOAD_ALL & ~LOAD_TEXTA) +#define COUNT_KERNEL (COUNT_ALL & ~COUNT_TEXTA) + +extern u_long efi_loadaddr; +#define LOADADDR(a) (((((u_long)(a)) + offset)&0x3fffffffff) + \ + efi_loadaddr) +#define ALIGNENTRY(a) ((u_long)(a)) +#define READ(f, b, c) read((f), (void *)LOADADDR(b), (c)) +#define BCOPY(s, d, c) memcpy((void *)LOADADDR(d), (void *)(s), (c)) +#define BZERO(d, c) memset((void *)LOADADDR(d), 0, (c)) +#define WARN(a) (void)(printf a, \ + printf((errno ? ": %s\n" : "\n"), \ + strerror(errno))) +#define PROGRESS(a) (void) printf a +#define ALLOC(a) alloc(a) +#define FREE(a, b) free(a, b) + +void run_loadfile(uint64_t *, int); \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/mplock.h b/lib/libc/include/riscv64-openbsd-none/machine/mplock.h new file mode 100644 index 000000000000..1a87e05398a4 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/mplock.h @@ -0,0 +1,10 @@ +/* $OpenBSD: mplock.h,v 1.1 2021/06/27 20:36:57 kettenis Exp $ */ + +/* public domain */ + +#ifndef _MACHINE_MPLOCK_H_ +#define _MACHINE_MPLOCK_H_ + +#define __USE_MI_MPLOCK + +#endif /* !_MACHINE_MPLOCK_H */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/mutex.h b/lib/libc/include/riscv64-openbsd-none/machine/mutex.h new file mode 100644 index 000000000000..bc6b8cbb83bd --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/mutex.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mutex.h,v 1.1 2021/04/23 02:42:16 drahn Exp $ */ + +#define __USE_MI_MUTEX \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/openpromio.h b/lib/libc/include/riscv64-openbsd-none/machine/openpromio.h new file mode 100644 index 000000000000..4f49bf5934c9 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/openpromio.h @@ -0,0 +1,57 @@ +/* $OpenBSD: openpromio.h,v 1.1 2021/04/23 12:01:03 jsg Exp $ */ +/* $NetBSD: openpromio.h,v 1.1.1.1 1998/06/20 04:58:52 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)openpromio.h 8.1 (Berkeley) 6/11/93 + */ + +struct opiocdesc { + int op_nodeid; /* passed or returned node id */ + int op_namelen; /* length of op_name */ + char *op_name; /* pointer to field name */ + int op_buflen; /* length of op_buf (value-result) */ + char *op_buf; /* pointer to field value */ +}; + +#define OPIOCGET _IOWR('O', 1, struct opiocdesc) /* get openprom field */ +#define OPIOCSET _IOW('O', 2, struct opiocdesc) /* set openprom field */ +#define OPIOCNEXTPROP _IOWR('O', 3, struct opiocdesc) /* get next property */ +#define OPIOCGETOPTNODE _IOR('O', 4, int) /* get openprom field */ +#define OPIOCGETNEXT _IOWR('O', 5, int) /* get next node of node */ +#define OPIOCGETCHILD _IOWR('O', 6, int) /* get first child of node */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/param.h b/lib/libc/include/riscv64-openbsd-none/machine/param.h new file mode 100644 index 000000000000..1260fa3a3c52 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/param.h @@ -0,0 +1,78 @@ +/* $OpenBSD: param.h,v 1.7 2025/07/07 18:33:37 kettenis Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ + +#ifdef _KERNEL +#ifndef _LOCORE +#include +#endif +#endif + +#define _MACHINE riscv64 +#define MACHINE "riscv64" +#define _MACHINE_ARCH riscv64 +#define MACHINE_ARCH "riscv64" +#define MID_MACHINE MID_RISCV64 + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define PAGE_MASK (PAGE_SIZE - 1) + +#ifdef _KERNEL + +#define NBPG PAGE_SIZE /* bytes/page */ +#define PGSHIFT PAGE_SHIFT /* LOG2(PAGE_SIZE) */ +#define PGOFSET PAGE_MASK /* byte offset into page */ + +#define UPAGES 6 /* pages of u-area */ +#define USPACE (UPAGES * PAGE_SIZE) /* total size of u-area */ +#define USPACE_ALIGN 0 /* u-area alignment 0-none */ +#define __HAVE_USPACE_GUARD + +#define NMBCLUSTERS (64 * 1024) /* max cluster allocation */ + +#ifndef MSGBUFSIZE +#define MSGBUFSIZE (16 * PAGE_SIZE) /* default message buffer size */ +#endif + +#define STACKALIGNBYTES (16 - 1) +#define STACKALIGN(p) ((u_long)(p) &~ STACKALIGNBYTES) + +#define __HAVE_FDT + +#endif /* _KERNEL */ + +#endif /* _MACHINE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/pcb.h b/lib/libc/include/riscv64-openbsd-none/machine/pcb.h new file mode 100644 index 000000000000..a1b6cb9e4740 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/pcb.h @@ -0,0 +1,41 @@ +/* $OpenBSD: pcb.h,v 1.4 2024/10/15 09:16:39 jsg Exp $ */ + +/* + * Copyright (c) 2016 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef _MACHINE_PCB_H_ +#define _MACHINE_PCB_H_ + +#include +#include + +struct trapframe; + +/* + * Warning certain fields must be within 256 bytes of the beginning + * of this structure. + */ +struct pcb { + u_int pcb_flags; +#define PCB_FPU 0x00000001 /* Process had FPU initialized */ +#define PCB_SINGLESTEP 0x00000002 /* Single step process */ + struct trapframe *pcb_tf; + + register_t pcb_sp; // stack pointer of switchframe + + caddr_t pcb_onfault; // On fault handler + struct fpreg pcb_fpstate; // Floating Point state */ +}; +#endif /* _MACHINE_PCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/pci_machdep.h b/lib/libc/include/riscv64-openbsd-none/machine/pci_machdep.h new file mode 100644 index 000000000000..4737ab100a6a --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/pci_machdep.h @@ -0,0 +1,140 @@ +/* $OpenBSD: pci_machdep.h,v 1.5 2024/05/22 05:51:49 jsg Exp $ */ + +/* + * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +typedef struct machine_pci_chipset *pci_chipset_tag_t; +typedef uint64_t pcitag_t; + +#define PCITAG_NODE(x) ((x) >> 32) +#define PCITAG_OFFSET(x) ((x) & 0xffffffff) + +/* Supported interrupt types. */ +#define PCI_NONE 0 +#define PCI_INTX 1 +#define PCI_MSI 2 +#define PCI_MSIX 3 + +typedef struct { + pci_chipset_tag_t ih_pc; + pcitag_t ih_tag; + int ih_intrpin; + int ih_type; + bus_dma_tag_t ih_dmat; +} pci_intr_handle_t; + +struct pci_attach_args; + +/* + * Machine-specific PCI structure and type definitions. + * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE. + */ +struct machine_pci_chipset { + void *pc_conf_v; + void (*pc_attach_hook)(struct device *, + struct device *, struct pcibus_attach_args *); + int (*pc_bus_maxdevs)(void *, int); + pcitag_t (*pc_make_tag)(void *, int, int, int); + void (*pc_decompose_tag)(void *, pcitag_t, int *, + int *, int *); + int (*pc_conf_size)(void *, pcitag_t); + pcireg_t (*pc_conf_read)(void *, pcitag_t, int); + void (*pc_conf_write)(void *, pcitag_t, int, pcireg_t); + int (*pc_probe_device_hook)(void *, struct pci_attach_args *); + + void *pc_intr_v; + int (*pc_intr_map)(struct pci_attach_args *, + pci_intr_handle_t *); + int (*pc_intr_map_msi)(struct pci_attach_args *, + pci_intr_handle_t *); + int (*pc_intr_map_msivec)(struct pci_attach_args *, + int, pci_intr_handle_t *); + int (*pc_intr_map_msix)(struct pci_attach_args *, + int, pci_intr_handle_t *); + const char *(*pc_intr_string)(void *, pci_intr_handle_t); + void *(*pc_intr_establish)(void *, pci_intr_handle_t, + int, struct cpu_info *, int (*)(void *), void *, + char *); + void (*pc_intr_disestablish)(void *, void *); +}; + +/* + * Functions provided to machine-independent PCI code. + */ +#define pci_attach_hook(p, s, pba) \ + (*(pba)->pba_pc->pc_attach_hook)((p), (s), (pba)) +#define pci_bus_maxdevs(c, b) \ + (*(c)->pc_bus_maxdevs)((c)->pc_conf_v, (b)) +#define pci_make_tag(c, b, d, f) \ + (*(c)->pc_make_tag)((c)->pc_conf_v, (b), (d), (f)) +#define pci_decompose_tag(c, t, bp, dp, fp) \ + (*(c)->pc_decompose_tag)((c)->pc_conf_v, (t), (bp), (dp), (fp)) +#define pci_conf_size(c, t) \ + (*(c)->pc_conf_size)((c)->pc_conf_v, (t)) +#define pci_conf_read(c, t, r) \ + (*(c)->pc_conf_read)((c)->pc_conf_v, (t), (r)) +#define pci_conf_write(c, t, r, v) \ + (*(c)->pc_conf_write)((c)->pc_conf_v, (t), (r), (v)) +#define pci_probe_device_hook(c, a) \ + (*(c)->pc_probe_device_hook)((c)->pc_conf_v, (a)) +#define pci_intr_map(c, ihp) \ + (*(c)->pa_pc->pc_intr_map)((c), (ihp)) +#define pci_intr_map_msi(c, ihp) \ + (*(c)->pa_pc->pc_intr_map_msi)((c), (ihp)) +#define pci_intr_map_msix(c, vec, ihp) \ + (*(c)->pa_pc->pc_intr_map_msix)((c), (vec), (ihp)) +#define pci_intr_string(c, ih) \ + (*(c)->pc_intr_string)((c)->pc_intr_v, (ih)) +#define pci_intr_establish(c, ih, l, h, a, nm) \ + (*(c)->pc_intr_establish)((c)->pc_intr_v, (ih), (l), NULL, (h), (a),\ + (nm)) +#define pci_intr_establish_cpu(c, ih, l, ci, h, a, nm) \ + (*(c)->pc_intr_establish)((c)->pc_intr_v, (ih), (l), (ci), (h), (a),\ + (nm)) +#define pci_intr_disestablish(c, iv) \ + (*(c)->pc_intr_disestablish)((c)->pc_intr_v, (iv)) + +#define pci_min_powerstate(c, t) (PCI_PMCSR_STATE_D3) +#define pci_set_powerstate_md(c, t, s, p) + +#define pci_dev_postattach(a, b) + +void pci_mcfg_init(bus_space_tag_t, bus_addr_t, int, int, int); + +void pci_msi_enable(pci_chipset_tag_t, pcitag_t, bus_addr_t, uint32_t); +void pci_msix_enable(pci_chipset_tag_t, pcitag_t, bus_space_tag_t, + int, bus_addr_t, uint32_t); +int _pci_intr_map_msi(struct pci_attach_args *, pci_intr_handle_t *); +int _pci_intr_map_msivec(struct pci_attach_args *, int, + pci_intr_handle_t *); +int _pci_intr_map_msix(struct pci_attach_args *, int, pci_intr_handle_t *); + +#define __HAVE_PCI_MSIX + +int pci_msix_table_map(pci_chipset_tag_t, pcitag_t, + bus_space_tag_t, bus_space_handle_t *); +void pci_msix_table_unmap(pci_chipset_tag_t, pcitag_t, + bus_space_tag_t, bus_space_handle_t); \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/pmap.h b/lib/libc/include/riscv64-openbsd-none/machine/pmap.h new file mode 100644 index 000000000000..d6e867d90f34 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/pmap.h @@ -0,0 +1,132 @@ +/* $OpenBSD: pmap.h,v 1.14 2025/02/03 17:59:40 jca Exp $ */ + +/* + * Copyright (c) 2019-2020 Brian Bamsch + * Copyright (c) 2008,2009,2014 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef _MACHINE_PMAP_H_ +#define _MACHINE_PMAP_H_ + +#ifndef _LOCORE +#include +#include +#include +#endif + + +/* V->P mapping data */ +// XXX Only targeting compatibility with SV39 +#define VP_IDX0_CNT 512 +#define VP_IDX0_MASK (VP_IDX0_CNT-1) +#define VP_IDX0_POS 39 +#define VP_IDX1_CNT 512 +#define VP_IDX1_MASK (VP_IDX1_CNT-1) +#define VP_IDX1_POS 30 +#define VP_IDX2_CNT 512 +#define VP_IDX2_MASK (VP_IDX2_CNT-1) +#define VP_IDX2_POS 21 +#define VP_IDX3_CNT 512 +#define VP_IDX3_MASK (VP_IDX3_CNT-1) +#define VP_IDX3_POS 12 + +/* cache flags */ +// XXX These are duplicated from arm64 and may need some reworking +#define PMAP_CACHE_CI (PMAP_MD0) /* cache inhibit */ +#define PMAP_CACHE_WB (PMAP_MD1) /* writeback */ +#define PMAP_CACHE_DEV (PMAP_MD2) /* device mapping */ +#define PMAP_CACHE_BITS (PMAP_MD0|PMAP_MD1|PMAP_MD2) + +#define PTED_VA_MANAGED_M (PMAP_MD3) +#define PTED_VA_WIRED_M (PMAP_MD3 << 1) + +#if defined(_KERNEL) && !defined(_LOCORE) +/* + * Pmap stuff + */ + +typedef struct pmap *pmap_t; + +struct pmap { + struct mutex pm_mtx; + union { + // XXX Sv48 not yet supported + // XXX Consider inverting Lx + struct pmapvp1 *l1; /* virtual to physical table 3 lvl */ + } pm_vp; + uint64_t pm_satp; + int pm_privileged; + int pm_refs; /* ref count */ + struct pmap_statistics pm_stats; /* pmap statistics */ +}; + +#define PMAP_PA_MASK ~((paddr_t)PAGE_MASK) /* to remove the flags */ +#define PMAP_NOCACHE 0x1 /* non-cacheable memory */ +#define PMAP_DEVICE 0x2 /* device memory */ + +#define PG_PMAP_MOD PG_PMAP0 +#define PG_PMAP_REF PG_PMAP1 +#define PG_PMAP_EXE PG_PMAP2 + +// [NCPUS] +extern paddr_t zero_page; +extern paddr_t copy_src_page; +extern paddr_t copy_dst_page; + +void pagezero(vaddr_t); + +extern struct pmap kernel_pmap_; +#define pmap_kernel() (&kernel_pmap_) +#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) +#define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count) + +vaddr_t pmap_bootstrap(long kvo, paddr_t lpt1, + vaddr_t kernelstart, vaddr_t kernelend, + paddr_t memstart, paddr_t memend); +void pmap_kenter_cache(vaddr_t va, paddr_t pa, vm_prot_t prot, int cacheable); +void pmap_page_ro(pmap_t pm, vaddr_t va, vm_prot_t prot); + +paddr_t pmap_steal_avail(size_t size, int align, void **kva); +void pmap_avail_fixup(void); +void pmap_physload_avail(void); + +#define PMAP_GROWKERNEL + +#define PHYS_TO_DMAP(pa) ((pa) - dmap_phys_base + DMAP_MIN_ADDRESS) + +struct pv_entry; + +/* investigate */ +#define pmap_unuse_final(p) do { /* nothing */ } while (0) +int pmap_fault_fixup(pmap_t, vaddr_t, vm_prot_t); +void pmap_postinit(void); +void pmap_init_percpu(void); + +#define __HAVE_PMAP_POPULATE + +#endif /* _KERNEL && !_LOCORE */ + +#ifndef _LOCORE +struct vm_page_md { + struct mutex pv_mtx; + LIST_HEAD(,pte_desc) pv_list; +}; + +#define VM_MDPAGE_INIT(pg) do { \ + mtx_init(&(pg)->mdpage.pv_mtx, IPL_VM); \ + LIST_INIT(&((pg)->mdpage.pv_list)); \ +} while (0) +#endif /* _LOCORE */ + +#endif /* _MACHINE_PMAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/proc.h b/lib/libc/include/riscv64-openbsd-none/machine/proc.h new file mode 100644 index 000000000000..e1a7bf3652d7 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/proc.h @@ -0,0 +1,45 @@ +/* $OpenBSD: proc.h,v 1.2 2021/05/12 01:20:52 jsg Exp $ */ +/* $NetBSD: proc.h,v 1.1 2003/04/26 18:39:46 fvdl Exp $ */ + +/* + * Copyright (c) 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)proc.h 7.1 (Berkeley) 5/15/91 + */ + +#ifndef _MACHINE_PROC_H_ +#define _MACHINE_PROC_H_ + +/* + * Machine-dependent part of the proc structure for riscv64. + */ +struct mdproc { + volatile int md_astpending; +}; + +#endif /* _MACHINE_PROC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/profile.h b/lib/libc/include/riscv64-openbsd-none/machine/profile.h new file mode 100644 index 000000000000..3074be08fc7b --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/profile.h @@ -0,0 +1,92 @@ +/* $OpenBSD: profile.h,v 1.4 2021/05/21 16:49:57 deraadt Exp $ */ + +/* + * Copyright (c) 2015 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define _MCOUNT_DECL void _mcount + +#define MCOUNT_ASM_NAME "__mcount" + +#ifdef __PIC__ +#define PLTSYM "" /* XXX -aarch64 defaults to PLT? */ +#else +#define PLTSYM "" +#endif + +#define MCOUNT \ +__asm__ (".text \n;" \ + ".align 3 \n;" \ + ".globl " MCOUNT_ASM_NAME " \n;" \ + ".type " MCOUNT_ASM_NAME ",@function \n;" \ + MCOUNT_ASM_NAME ": \n;" \ + " addi sp, sp, -176 \n" \ + " sd fp, 0(sp) \n" \ + " sd ra, 8(sp) \n" \ + " sd s1, 24(sp) \n" \ + " sd a0, 32(sp) \n" \ + " sd a1, 40(sp) \n" \ + " sd a2, 48(sp) \n" \ + " sd a3, 56(sp) \n" \ + " sd a4, 64(sp) \n" \ + " sd a5, 72(sp) \n" \ + " sd a6, 80(sp) \n" \ + " sd a7, 88(sp) \n" \ + " sd s2, 96(sp) \n" \ + " sd s3, 104(sp) \n" \ + " sd s4, 112(sp) \n" \ + " sd s5, 120(sp) \n" \ + " sd s6, 128(sp) \n" \ + " sd s7, 136(sp) \n" \ + " sd s8, 144(sp) \n" \ + " sd s9, 152(sp) \n" \ + " sd s10, 160(sp) \n" \ + " sd s11, 168(sp) \n" \ + " ld a0, 8(fp) \n" \ + " mv a1, x1 \n" \ + " call " __STRING(_mcount) PLTSYM " \n" \ + /* restore argument registers */ \ + " ld fp, 0(sp) \n" \ + " ld ra, 8(sp) \n" \ + " ld s1, 24(sp) \n" \ + " ld a0, 32(sp) \n" \ + " ld a1, 40(sp) \n" \ + " ld a2, 48(sp) \n" \ + " ld a3, 56(sp) \n" \ + " ld a4, 64(sp) \n" \ + " ld a5, 72(sp) \n" \ + " ld a6, 80(sp) \n" \ + " ld a7, 88(sp) \n" \ + " ld s2, 96(sp) \n" \ + " ld s3, 104(sp) \n" \ + " ld s4, 112(sp) \n" \ + " ld s5, 120(sp) \n" \ + " ld s6, 128(sp) \n" \ + " ld s7, 136(sp) \n" \ + " ld s8, 144(sp) \n" \ + " ld s9, 152(sp) \n" \ + " ld s10, 160(sp) \n" \ + " ld s11, 168(sp) \n" \ + " addi sp, sp, 176 \n" \ + " jr ra \n"); + +#ifdef _KERNEL +// Change this to dair read/set, then restore. +#define MCOUNT_ENTER \ +__asm__ ("mrs %x0,daif; msr daifset, #0x2": "=r"(s)); +#define MCOUNT_EXIT \ +__asm__ ("msr daif, %x0":: "r"(s)); + +#endif \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/pte.h b/lib/libc/include/riscv64-openbsd-none/machine/pte.h new file mode 100644 index 000000000000..c050e38cb22b --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/pte.h @@ -0,0 +1,85 @@ +/* $OpenBSD: pte.h,v 1.4 2024/10/14 12:02:16 jsg Exp $ */ + +/* + * Copyright (c) 2019 Brian Bamsch + * Copyright (c) 2014 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef _RISCV64_PTE_H_ +#define _RISCV64_PTE_H_ + +#define Lx_TABLE_ALIGN (4096) + +/* Block and Page attributes */ +/* Bits 9:8 are reserved for software */ +#define PTE_ATTR_MASK (0x3ffUL) +#define PTE_SW_MANAGED (1 << 9) +#define PTE_SW_WIRED (1 << 8) +#define PTE_D (1 << 7) /* Dirty */ +#define PTE_A (1 << 6) /* Accessed */ +#define PTE_G (1 << 5) /* Global */ +#define PTE_U (1 << 4) /* User */ +#define PTE_X (1 << 3) /* Execute */ +#define PTE_W (1 << 2) /* Write */ +#define PTE_R (1 << 1) /* Read */ +#define PTE_V (1 << 0) /* Valid */ +#define PTE_RWX (PTE_R | PTE_W | PTE_X) +#define PTE_RX (PTE_R | PTE_X) +#define PTE_KERN (PTE_V | PTE_R | PTE_W | PTE_A | PTE_D) + +/* T-Head extended page attributes */ +#define PTE_THEAD_SO (1ULL << 63) +#define PTE_THEAD_C (1ULL << 62) +#define PTE_THEAD_B (1ULL << 61) +#define PTE_THEAD_SH (1ULL << 60) + +/* Level 0 table, 512GiB per entry */ +#define L0_SHIFT 39 + +/* Level 1 table, 1GiB per entry */ +#define L1_SHIFT 30 +#define L1_SIZE (1UL << L1_SHIFT) +#define L1_OFFSET (L1_SIZE - 1) + +/* Level 2 table, 2MiB per entry */ +#define L2_SHIFT 21 +#define L2_SIZE (1UL << L2_SHIFT) +#define L2_OFFSET (L2_SIZE - 1) + +/* Level 3 table, 4KiB per entry */ +#define L3_SHIFT 12 +#define L3_SIZE (1UL << L3_SHIFT) +#define L3_OFFSET (L3_SIZE - 1) + +/* page mapping */ +#define Ln_ENTRIES_SHIFT 9 +#define Ln_ENTRIES (1 << Ln_ENTRIES_SHIFT) +#define Ln_ADDR_MASK (Ln_ENTRIES - 1) +#define Ln_TABLE_MASK ((1 << 12) - 1) + +/* physical page number mask */ +#define PTE_RPGN (((1ULL << 56) - 1) & ~PAGE_MASK) + +#define PTE_PPN0_S 10 +#define PTE_PPN1_S 19 +#define PTE_PPN2_S 28 +#define PTE_PPN3_S 37 +#define PTE_SIZE 8 + +#ifndef _LOCORE +typedef uint64_t pt_entry_t; /* page table entry */ +typedef uint64_t pn_t; /* page number */ +#endif /* !_LOCORE */ + +#endif /* _RISCV64_PTE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/ptrace.h b/lib/libc/include/riscv64-openbsd-none/machine/ptrace.h new file mode 100644 index 000000000000..acffe6191946 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/ptrace.h @@ -0,0 +1,25 @@ +/* $OpenBSD: ptrace.h,v 1.4 2021/09/03 14:13:06 jca Exp $ */ + +/* + * Copyright (c) 2014 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#if 0 +#define PT_STEP (PT_FIRSTMACH + 0) +#endif +#define PT_GETREGS (PT_FIRSTMACH + 1) +#define PT_SETREGS (PT_FIRSTMACH + 2) +#define PT_GETFPREGS (PT_FIRSTMACH + 3) +#define PT_SETFPREGS (PT_FIRSTMACH + 4) \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/reg.h b/lib/libc/include/riscv64-openbsd-none/machine/reg.h new file mode 100644 index 000000000000..f80b13d4aa2f --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/reg.h @@ -0,0 +1,60 @@ +/* $OpenBSD: reg.h,v 1.2 2021/05/12 01:20:52 jsg Exp $ */ + +/*- + * Copyright (c) 2019 Brian Bamsch + * Copyright (c) 2015-2016 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_REG_H_ +#define _MACHINE_REG_H_ + +struct reg { + uint64_t r_ra; /* return address */ + uint64_t r_sp; /* stack pointer */ + uint64_t r_gp; /* global pointer */ + uint64_t r_tp; /* thread pointer */ + uint64_t r_t[7]; /* temporary registers */ + uint64_t r_s[12]; /* saved registers */ + uint64_t r_a[8]; /* argument registers */ + uint64_t r_sepc; /* exception program counter */ + uint64_t r_sstatus; /* status register */ +}; + +struct fpreg { + uint64_t fp_f[32]; /* floating-point registers */ + uint64_t fp_fcsr; /* floating-point control register */ +}; + +#endif /* !_MACHINE_REG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/reloc.h b/lib/libc/include/riscv64-openbsd-none/machine/reloc.h new file mode 100644 index 000000000000..09dea83e329d --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/reloc.h @@ -0,0 +1,19 @@ +/* $OpenBSD: reloc.h,v 1.2 2021/05/12 01:20:52 jsg Exp $ */ + +/* + * RISCV64 static relocation types. + */ + +/* Relocation types used by the dynamic linker. */ +#define R_RISCV_NONE 0 +#define R_RISCV_32 1 +#define R_RISCV_64 2 +#define R_RISCV_RELATIVE 3 +#define R_RISCV_COPY 4 +#define R_RISCV_JUMP_SLOT 5 +#define R_RISCV_TLS_DTPMOD32 6 +#define R_RISCV_TLS_DTPMOD64 7 +#define R_RISCV_TLS_DTPREL32 8 +#define R_RISCV_TLS_DTPREL64 9 +#define R_RISCV_TLS_TPREL32 10 +#define R_RISCV_TLS_TPREL64 11 \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/riscvreg.h b/lib/libc/include/riscv64-openbsd-none/machine/riscvreg.h new file mode 100644 index 000000000000..cf19db3ca1d3 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/riscvreg.h @@ -0,0 +1,235 @@ +/* $OpenBSD: riscvreg.h,v 1.5 2022/08/29 02:01:18 jsg Exp $ */ + +/*- + * Copyright (c) 2019 Brian Bamsch + * Copyright (c) 2015-2017 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 _MACHINE_RISCVREG_H_ +#define _MACHINE_RISCVREG_H_ + +#define EXCP_SHIFT 0 +#define EXCP_MASK (0xf << EXCP_SHIFT) +#define EXCP_MISALIGNED_FETCH 0 +#define EXCP_FAULT_FETCH 1 +#define EXCP_ILLEGAL_INSTRUCTION 2 +#define EXCP_BREAKPOINT 3 +#define EXCP_MISALIGNED_LOAD 4 +#define EXCP_FAULT_LOAD 5 +#define EXCP_MISALIGNED_STORE 6 +#define EXCP_FAULT_STORE 7 +#define EXCP_USER_ECALL 8 +#define EXCP_SUPERVISOR_ECALL 9 +#define EXCP_HYPERVISOR_ECALL 10 +#define EXCP_MACHINE_ECALL 11 +#define EXCP_INST_PAGE_FAULT 12 +#define EXCP_LOAD_PAGE_FAULT 13 +#define EXCP_STORE_PAGE_FAULT 15 +#define EXCP_INTR (1ULL << 63) + +#define MSTATUS_UIE (1 << 0) +#define MSTATUS_SIE (1 << 1) +#define MSTATUS_MIE (1 << 3) +#define MSTATUS_UPIE (1 << 4) +#define MSTATUS_SPIE (1 << 5) +#define MSTATUS_MPIE (1 << 7) +#define MSTATUS_SPP (1 << 8) +#define MSTATUS_MPP_SHIFT 11 +#define MSTATUS_MPP_MASK (0x3 << MSTATUS_MPP_SHIFT) +#define MSTATUS_FS_SHIFT 13 +#define MSTATUS_FS_MASK (0x3 << MSTATUS_FS_SHIFT) +#define MSTATUS_XS_SHIFT 15 +#define MSTATUS_XS_MASK (0x3 << MSTATUS_XS_SHIFT) +#define MSTATUS_MPRV (1 << 17) +#define MSTATUS_SUM (1 << 18) +#define MSTATUS_MXR (1 << 19) +#define MSTATUS_TVM (1 << 20) +#define MSTATUS_TW (1 << 21) +#define MSTATUS_TSR (1 << 22) +#define MSTATUS_UXL_SHIFT 32 +#define MSTATUS_UXL_MASK (0x3ULL << MSTATUS_UXL_SHIFT) +#define MSTATUS_SXL_SHIFT 34 +#define MSTATUS_SXL_MASK (0x3ULL << MSTATUS_SXL_SHIFT) +#define MSTATUS_SD (1ULL << (MXLEN - 1)) + +#define SSTATUS_UIE (1 << 0) +#define SSTATUS_SIE (1 << 1) +#define SSTATUS_UPIE (1 << 4) +#define SSTATUS_SPIE (1 << 5) +#define SSTATUS_SPP (1 << 8) +#define SSTATUS_FS_SHIFT 13 +#define SSTATUS_FS_MASK (0x3 << SSTATUS_FS_SHIFT) +#define SSTATUS_FS_OFF (0x0 << SSTATUS_FS_SHIFT) +#define SSTATUS_FS_INITIAL (0x1 << SSTATUS_FS_SHIFT) +#define SSTATUS_FS_CLEAN (0x2 << SSTATUS_FS_SHIFT) +#define SSTATUS_FS_DIRTY (0x3 << SSTATUS_FS_SHIFT) +#define SSTATUS_XS_SHIFT 15 +#define SSTATUS_XS_MASK (0x3 << SSTATUS_XS_SHIFT) +#define SSTATUS_SUM (1 << 18) +#define SSTATUS_MXR (1 << 19) +#define SSTATUS_UXL_SHIFT 32 +#define SSTATUS_UXL_MASK (0x3ULL << SSTATUS_UXL_SHIFT) +#define SSTATUS_SD (1ULL << (SXLEN - 1)) + +#define USTATUS_UIE (1 << 0) +#define USTATUS_UPIE (1 << 4) + +#define MSTATUS_PRV_U 0 /* user */ +#define MSTATUS_PRV_S 1 /* supervisor */ +#define MSTATUS_PRV_H 2 /* hypervisor */ +#define MSTATUS_PRV_M 3 /* machine */ + +#define MIE_USIE (1 << 0) +#define MIE_SSIE (1 << 1) +#define MIE_MSIE (1 << 3) +#define MIE_UTIE (1 << 4) +#define MIE_STIE (1 << 5) +#define MIE_MTIE (1 << 7) +#define MIE_UEIE (1 << 8) +#define MIE_SEIE (1 << 9) +#define MIE_MEIE (1 << 11) + +#define MIP_USIP (1 << 0) +#define MIP_SSIP (1 << 1) +#define MIP_MSIP (1 << 3) +#define MIP_UTIP (1 << 4) +#define MIP_STIP (1 << 5) +#define MIP_MTIP (1 << 7) +#define MIP_UEIP (1 << 8) +#define MIP_SEIP (1 << 9) +#define MIP_MEIP (1 << 11) + +#define SIE_USIE (1 << 0) +#define SIE_SSIE (1 << 1) +#define SIE_UTIE (1 << 4) +#define SIE_STIE (1 << 5) +#define SIE_UEIE (1 << 8) +#define SIE_SEIE (1 << 9) + +#define SIP_USIP (1 << 0) +#define SIP_SSIP (1 << 1) +#define SIP_UTIP (1 << 4) +#define SIP_STIP (1 << 5) +#define SIP_UEIP (1 << 8) +#define SIP_SEIP (1 << 9) + +#define UIE_USIE (1 << 0) +#define UIE_UTIE (1 << 4) +#define UIE_UEIE (1 << 8) + +#define UIP_USIP (1 << 0) +#define UIP_UTIP (1 << 4) +#define UIP_UEIP (1 << 8) + +#define PPN(pa) ((pa) >> PAGE_SHIFT) +#define SATP_PPN_SHIFT 0 +#define SATP_PPN_MASK (0xfffffffffffULL << SATP_PPN_SHIFT) +#define SATP_PPN(satp) (((satp) & SATP_PPN_MASK) >> SATP_PPN_SHIFT) +#define SATP_FORMAT_PPN(ppn) (((uint64_t)(ppn) << SATP_PPN_SHIFT) & SATP_PPN_MASK) +#define SATP_ASID_SHIFT 44 +#define SATP_ASID_MASK (0xffffULL << SATP_ASID_SHIFT) +#define SATP_ASID(satp) (((satp) & SATP_ASID_MASK) >> SATP_ASID_SHIFT) +#define SATP_FORMAT_ASID(asid) (((uint64_t)(asid) << SATP_ASID_SHIFT) & SATP_ASID_MASK) +#define SATP_MODE_SHIFT 60 +#define SATP_MODE_MASK (0xfULL << SATP_MODE_SHIFT) +#define SATP_MODE(mode) (((satp) & SATP_MODE_MASK) >> SATP_MODE_SHIFT) + +#define SATP_MODE_SV39 (8ULL << SATP_MODE_SHIFT) +#define SATP_MODE_SV48 (9ULL << SATP_MODE_SHIFT) +#define SATP_MODE_SV57 (10ULL << SATP_MODE_SHIFT) +#define SATP_MODE_SV64 (11ULL << SATP_MODE_SHIFT) + +/** + * As of RISC-V Machine ISA v1.11, the XLEN can vary between + * Machine, Supervisor, and User modes. The Machine XLEN (MXLEN) + * is resolved from the MXL field of the 'misa' CSR. The + * Supervisor XLEN (SXLEN) and User XLEN (UXLEN) are resolved + * from the SXL and UXL fields of the 'mstatus' CSR, respectively. + * + * The Machine XLEN is reset to the widest supported ISA variant + * at machine reset. For now, assume that all modes will always + * use the same, static XLEN of 64 bits. + */ +#define XLEN 64 +#define XLEN_BYTES (XLEN / 8) +#define MXLEN XLEN +#define SXLEN XLEN +#define UXLEN XLEN +#define INSN_SIZE 4 +#define INSN_C_SIZE 2 + +// Check if val can fit in the CSR immediate form +#define CSR_ZIMM(val) \ + (__builtin_constant_p(val) && ((u_long)(val) < 32)) + +#define csr_swap(csr, val) \ +({ if (CSR_ZIMM(val)) \ + __asm volatile("csrrwi %0, " #csr ", %1" \ + : "=r" (val) : "i" (val)); \ + else \ + __asm volatile("csrrw %0, " #csr ", %1" \ + : "=r" (val) : "r" (val)); \ + val; \ +}) + +#define csr_write(csr, val) \ +({ if (CSR_ZIMM(val)) \ + __asm volatile("csrwi " #csr ", %0" :: "i" (val)); \ + else \ + __asm volatile("csrw " #csr ", %0" :: "r" (val)); \ +}) + +#define csr_set(csr, val) \ +({ if (CSR_ZIMM(val)) \ + __asm volatile("csrsi " #csr ", %0" :: "i" (val)); \ + else \ + __asm volatile("csrs " #csr ", %0" :: "r" (val)); \ +}) + +#define csr_clear(csr, val) \ +({ if (CSR_ZIMM(val)) \ + __asm volatile("csrci " #csr ", %0" :: "i" (val)); \ + else \ + __asm volatile("csrc " #csr ", %0" :: "r" (val)); \ +}) + +#define csr_read(csr) \ +({ u_long val; \ + __asm volatile("csrr %0, " #csr : "=r" (val)); \ + val; \ +}) + +#endif /* !_MACHINE_RISCVREG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/sbi.h b/lib/libc/include/riscv64-openbsd-none/machine/sbi.h new file mode 100644 index 000000000000..51e313311dc7 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/sbi.h @@ -0,0 +1,267 @@ +/* $OpenBSD: sbi.h,v 1.6 2024/03/29 22:11:34 kettenis Exp $ */ + +/*- + * Copyright (c) 2016-2017 Ruslan Bukin + * All rights reserved. + * Copyright (c) 2019 Mitchell Horne + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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 _MACHINE_SBI_H_ +#define _MACHINE_SBI_H_ + +/* SBI Specification Version */ +#define SBI_SPEC_VERS_MAJOR_OFFSET 24 +#define SBI_SPEC_VERS_MAJOR_MASK (0x7F << SBI_SPEC_VERS_MAJOR_OFFSET) +#define SBI_SPEC_VERS_MINOR_OFFSET 0 +#define SBI_SPEC_VERS_MINOR_MASK (0xFFFFFF << SBI_SPEC_VERS_MINOR_OFFSET) + +/* SBI Implementation IDs */ +#define SBI_IMPL_ID_BBL 0 +#define SBI_IMPL_ID_OPENSBI 1 + +/* SBI Error Codes */ +#define SBI_SUCCESS 0 +#define SBI_ERR_FAILURE -1 +#define SBI_ERR_NOT_SUPPORTED -2 +#define SBI_ERR_INVALID_PARAM -3 +#define SBI_ERR_DENIED -4 +#define SBI_ERR_INVALID_ADDRESS -5 + +/* SBI Base Extension */ +#define SBI_EXT_ID_BASE 0x10 +#define SBI_BASE_GET_SPEC_VERSION 0 +#define SBI_BASE_GET_IMPL_ID 1 +#define SBI_BASE_GET_IMPL_VERSION 2 +#define SBI_BASE_PROBE_EXTENSION 3 +#define SBI_BASE_GET_MVENDORID 4 +#define SBI_BASE_GET_MARCHID 5 +#define SBI_BASE_GET_MIMPID 6 + +/* Hart State Management (HSM) Extension */ +#define SBI_EXT_ID_HSM 0x48534D +#define SBI_HSM_HART_START 0 +#define SBI_HSM_HART_STOP 1 +#define SBI_HSM_HART_STATUS 2 +#define SBI_HSM_STATUS_STARTED 0 +#define SBI_HSM_STATUS_STOPPED 1 +#define SBI_HSM_STATUS_START_PENDING 2 +#define SBI_HSM_STATUS_STOP_PENDING 3 + +/* System Reset Extension */ +#define SBI_EXT_ID_SRST 0x53525354 +#define SBI_SRST_RESET 0 +#define SBI_SRST_RESET_SHUTDOWN 0 +#define SBI_SRST_RESET_COLD_REBOOT 1 +#define SBI_SRST_RESET_WARM_REBOOT 2 + +/* Legacy Extensions */ +#define SBI_SET_TIMER 0 +#define SBI_CONSOLE_PUTCHAR 1 +#define SBI_CONSOLE_GETCHAR 2 +#define SBI_CLEAR_IPI 3 +#define SBI_SEND_IPI 4 +#define SBI_REMOTE_FENCE_I 5 +#define SBI_REMOTE_SFENCE_VMA 6 +#define SBI_REMOTE_SFENCE_VMA_ASID 7 +#define SBI_SHUTDOWN 8 + +#define SBI_CALL0(e, f) SBI_CALL4(e, f, 0, 0, 0, 0) +#define SBI_CALL1(e, f, p1) SBI_CALL4(e, f, p1, 0, 0, 0) +#define SBI_CALL2(e, f, p1, p2) SBI_CALL4(e, f, p1, p2, 0, 0) +#define SBI_CALL3(e, f, p1, p2, p3) SBI_CALL4(e, f, p1, p2, p3, 0) +#define SBI_CALL4(e, f, p1, p2, p3, p4) sbi_call(e, f, p1, p2, p3, p4) + +/* + * Documentation available at + * https://github.com/riscv/riscv-sbi-doc/blob/master/riscv-sbi.adoc + */ + +struct sbi_ret { + long error; + long value; +}; + +static __inline struct sbi_ret +sbi_call(uint64_t arg7, uint64_t arg6, uint64_t arg0, uint64_t arg1, + uint64_t arg2, uint64_t arg3) +{ + struct sbi_ret ret; + + register uintptr_t a0 __asm ("a0") = (uintptr_t)(arg0); + register uintptr_t a1 __asm ("a1") = (uintptr_t)(arg1); + register uintptr_t a2 __asm ("a2") = (uintptr_t)(arg2); + register uintptr_t a3 __asm ("a3") = (uintptr_t)(arg3); + register uintptr_t a6 __asm ("a6") = (uintptr_t)(arg6); + register uintptr_t a7 __asm ("a7") = (uintptr_t)(arg7); + + __asm volatile( \ + "ecall" \ + :"+r"(a0), "+r"(a1) \ + :"r"(a2), "r"(a3), "r"(a6), "r"(a7) \ + :"memory"); + + ret.error = a0; + ret.value = a1; + return (ret); +} + +/* Base extension functions and variables. */ +extern u_long sbi_spec_version; +extern u_long sbi_impl_id; +extern u_long sbi_impl_version; + +static __inline u_int +sbi_get_mvendorid(void) +{ + return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_MVENDORID).value); +} + + +static __inline u_long +sbi_get_marchid(void) +{ + return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_MARCHID).value); +} + +static __inline u_long +sbi_get_mimpid(void) +{ + return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_MIMPID).value); +} + +static __inline long +sbi_probe_extension(long id) +{ + return (SBI_CALL1(SBI_EXT_ID_BASE, SBI_BASE_PROBE_EXTENSION, id).value); +} + +/* Hart State Management extension functions. */ + +/* + * Start execution on the specified hart at physical address start_addr. The + * register a0 will contain the hart's ID, and a1 will contain the value of + * priv. + */ +int sbi_hsm_hart_start(u_long hart, u_long start_addr, u_long priv); + +/* + * Stop execution on the current hart. Interrupts should be disabled, or this + * function may return. + */ +void sbi_hsm_hart_stop(void); + +/* + * Get the execution status of the specified hart. The status will be one of: + * - SBI_HSM_STATUS_STARTED + * - SBI_HSM_STATUS_STOPPED + * - SBI_HSM_STATUS_START_PENDING + * - SBI_HSM_STATUS_STOP_PENDING + */ +int sbi_hsm_hart_status(u_long hart); + +/* Legacy extension functions. */ +static __inline void +sbi_console_putchar(int ch) +{ + + (void)SBI_CALL1(SBI_CONSOLE_PUTCHAR, 0, ch); +} + +static __inline int +sbi_console_getchar(void) +{ + + /* + * XXX: The "error" is returned here because legacy SBI functions + * continue to return their value in a0. + */ + return (SBI_CALL0(SBI_CONSOLE_GETCHAR, 0).error); +} + +static __inline void +sbi_set_timer(uint64_t val) +{ + + (void)SBI_CALL1(SBI_SET_TIMER, 0, val); +} + +static __inline void +sbi_shutdown(void) +{ + + (void)SBI_CALL0(SBI_SHUTDOWN, 0); +} + +static __inline void +sbi_clear_ipi(void) +{ + + (void)SBI_CALL0(SBI_CLEAR_IPI, 0); +} + +static __inline void +sbi_send_ipi(const unsigned long *hart_mask) +{ + + (void)SBI_CALL1(SBI_SEND_IPI, 0, (uint64_t)hart_mask); +} + +static __inline void +sbi_remote_fence_i(const unsigned long *hart_mask) +{ + + (void)SBI_CALL1(SBI_REMOTE_FENCE_I, 0, (uint64_t)hart_mask); +} + +static __inline void +sbi_remote_sfence_vma(const unsigned long *hart_mask, + unsigned long start, unsigned long size) +{ + + (void)SBI_CALL3(SBI_REMOTE_SFENCE_VMA, 0, (uint64_t)hart_mask, start, + size); +} + +static __inline void +sbi_remote_sfence_vma_asid(const unsigned long *hart_mask, + unsigned long start, unsigned long size, + unsigned long asid) +{ + + (void)SBI_CALL4(SBI_REMOTE_SFENCE_VMA_ASID, 0, (uint64_t)hart_mask, + start, size, asid); +} + +void sbi_print_version(void); +void sbi_init(void); + +#endif /* !_MACHINE_SBI_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/setjmp.h b/lib/libc/include/riscv64-openbsd-none/machine/setjmp.h new file mode 100644 index 000000000000..5d0d59cc4dcf --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/setjmp.h @@ -0,0 +1,8 @@ +/* $OpenBSD: setjmp.h,v 1.4 2021/06/17 16:09:08 kettenis Exp $ */ + +/* + * machine/setjmp.h: machine dependent setjmp-related information. + */ + +#define _JBLEN 32 /* sp, ra, [f]s0-11, fscr, magic val, sigmask */ +#define _JB_SIGMASK 28 \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/signal.h b/lib/libc/include/riscv64-openbsd-none/machine/signal.h new file mode 100644 index 000000000000..cf9ddecbfc7c --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/signal.h @@ -0,0 +1,70 @@ +/* $OpenBSD: signal.h,v 1.4 2021/05/20 15:14:30 drahn Exp $ */ + +/*- + * Copyright (c) 1986, 1989, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)signal.h 8.1 (Berkeley) 6/11/93 + * from: FreeBSD: src/sys/i386/include/signal.h,v 1.13 2000/11/09 + * from: FreeBSD: src/sys/sparc64/include/signal.h,v 1.6 2001/09/30 18:52:17 + * $FreeBSD: head/sys/riscv/include/signal.h 292407 2015-12-17 18:44:30Z br $ + */ + +#ifndef _MACHINE_SIGNAL_H_ +#define _MACHINE_SIGNAL_H_ + +#include + +typedef int sig_atomic_t; + +#if __BSD_VISIBLE || __XPG_VISIBLE >= 420 + +#include + +struct sigcontext { + int __sc_unused; + int sc_mask; + + __register_t sc_ra; + __register_t sc_sp; + __register_t sc_gp; + __register_t sc_tp; + __register_t sc_t[7]; + __register_t sc_s[12]; + __register_t sc_a[8]; + __register_t sc_sepc; + + /* 64 bit floats as well as integer registers */ + __register_t sc_f[32]; /* floating-point registers */ + __register_t sc_fcsr; /* floating-point control register */ + + long sc_cookie; +}; + +#endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ + +#endif /* !_MACHINE_SIGNAL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/simplebusvar.h b/lib/libc/include/riscv64-openbsd-none/machine/simplebusvar.h new file mode 100644 index 000000000000..5be6208e7492 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/simplebusvar.h @@ -0,0 +1,38 @@ +/* $OpenBSD: simplebusvar.h,v 1.1 2023/09/22 01:10:44 jsg Exp $ */ + +/* + * Copyright (c) 2016 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +struct simplebus_softc { + struct device sc_dev; + int sc_node; + bus_space_tag_t sc_iot; + bus_dma_tag_t sc_dmat; + int sc_acells; + int sc_scells; + int sc_pacells; + int sc_pscells; + struct bus_space sc_bus; + struct machine_bus_dma_tag sc_dma; + int *sc_ranges; + int sc_rangeslen; + int *sc_dmaranges; + int sc_dmarangeslen; + int sc_early; + int sc_early_nodes[64]; +}; + +extern void simplebus_attach(struct device *, struct device *, void *); \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/spinlock.h b/lib/libc/include/riscv64-openbsd-none/machine/spinlock.h new file mode 100644 index 000000000000..aca85f3b7b7c --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/spinlock.h @@ -0,0 +1,10 @@ +/* $OpenBSD: spinlock.h,v 1.2 2021/05/12 01:20:52 jsg Exp $ */ + +#ifndef _MACHINE_SPINLOCK_H_ +#define _MACHINE_SPINLOCK_H_ + +#define _ATOMIC_LOCK_UNLOCKED (0) +#define _ATOMIC_LOCK_LOCKED (1) +typedef int _atomic_lock_t; + +#endif \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/sysarch.h b/lib/libc/include/riscv64-openbsd-none/machine/sysarch.h new file mode 100644 index 000000000000..cef4a2f0be96 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/sysarch.h @@ -0,0 +1,43 @@ +/* $OpenBSD: sysarch.h,v 1.1 2021/09/14 12:03:49 jca Exp $ */ + +/* + * Copyright (c) 2021 Jeremie Courreges-Anglas + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _RISCV64_SYSARCH_H_ +#define _RISCV64_SYSARCH_H_ + +/* + * Architecture specific syscalls (riscv64) + */ + +#define RISCV_SYNC_ICACHE 0 + +struct riscv_sync_icache_args { + u_int64_t addr; /* Virtual start address */ + size_t len; /* Region size */ +}; + +#ifndef _KERNEL + +#include + +__BEGIN_DECLS +int sysarch(int, void *); +__END_DECLS + +#endif /* _KERNEL */ + +#endif /* _RISCV64_SYSARCH_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/syscall.h b/lib/libc/include/riscv64-openbsd-none/machine/syscall.h new file mode 100644 index 000000000000..b3f643ffdde4 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/syscall.h @@ -0,0 +1,28 @@ +/* $OpenBSD: syscall.h,v 1.3 2021/05/21 16:49:35 deraadt Exp $ */ + +/* + * Copyright (c) 2020 Brian Bamsch + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_SYSCALL_H_ +#define _MACHINE_SYSCALL_H_ + +#ifdef _KERNEL + +void svc_handler (trapframe_t *); + +#endif + +#endif /* !_MACHINE_SYSCALL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/tcb.h b/lib/libc/include/riscv64-openbsd-none/machine/tcb.h new file mode 100644 index 000000000000..d1400331983f --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/tcb.h @@ -0,0 +1,52 @@ +/* $OpenBSD: tcb.h,v 1.3 2021/05/12 01:20:52 jsg Exp $ */ + +/* + * Copyright (c) 2019 Brian Bamsch + * Copyright (c) 2011 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TCB_H_ +#define _MACHINE_TCB_H_ + +#ifdef _KERNEL + +#include + +#define TCB_GET(p) \ + ((void *)(((struct pcb *)(p)->p_addr)->pcb_tf->tf_tp)) + +#define TCB_SET(p, addr) \ + do { \ + ((struct pcb *)(p)->p_addr)->pcb_tf->tf_tp = (long)(addr); \ + } while (0) + +#else /* _KERNEL */ + +/* ELF TLS ABI calls for small TCB, with static TLS data after it */ +#define TLS_VARIANT 1 + +static inline void * +__riscv64_read_tcb(void) +{ + void *tcb; + __asm volatile("mv %0, tp": "=r" (tcb)); + return tcb; +} + +#define TCB_GET() __riscv64_read_tcb() + +#endif /* _KERNEL */ + +#endif /* _MACHINE_TCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/timetc.h b/lib/libc/include/riscv64-openbsd-none/machine/timetc.h new file mode 100644 index 000000000000..a19dd6f23f95 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/timetc.h @@ -0,0 +1,24 @@ +/* $OpenBSD: timetc.h,v 1.3 2021/07/24 22:41:09 jca Exp $ */ + +/* + * Copyright (c) 2020 Paul Irofti + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TIMETC_H_ +#define _MACHINE_TIMETC_H_ + +#define TC_TB 1 + +#endif /* _MACHINE_TIMETC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/trap.h b/lib/libc/include/riscv64-openbsd-none/machine/trap.h new file mode 100644 index 000000000000..337eb2f71f20 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/trap.h @@ -0,0 +1,24 @@ +/* $OpenBSD: trap.h,v 1.2 2021/05/12 01:20:52 jsg Exp $ */ + +/* + * Copyright (c) 2019 Brian Bamsch + * Copyright (c) 2016 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define KERNEL_BREAKPOINT 0x00100073 /* EBREAK -- Used by DDB */ + +#define KBPT_ASM "ebreak" + +#define USER_BREAKPOINT 0x00100073 /* EBREAK */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/machine/vmparam.h b/lib/libc/include/riscv64-openbsd-none/machine/vmparam.h new file mode 100644 index 000000000000..a7d864087a73 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/machine/vmparam.h @@ -0,0 +1,150 @@ +/* $OpenBSD: vmparam.h,v 1.9 2023/11/28 09:10:18 jsg Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vmparam.h 5.9 (Berkeley) 5/12/91 + */ + +#ifndef _MACHINE_VMPARAM_H_ +#define _MACHINE_VMPARAM_H_ + +/* + * Machine dependent constants for riscv64. + */ + +#define USRSTACK VM_MAXUSER_ADDRESS + +/* + * Virtual memory related constants, all in bytes + */ +#ifndef MAXTSIZ +#define MAXTSIZ ((paddr_t)1*1024*1024*1024) /* max text size */ +#endif +#ifndef DFLDSIZ +#define DFLDSIZ ((paddr_t)128*1024*1024) /* initial data size limit */ +#endif +#ifndef MAXDSIZ +#define MAXDSIZ ((paddr_t)16*1024*1024*1024) /* max data size */ +#endif +#ifndef BRKSIZ +#define BRKSIZ ((paddr_t)1*1024*1024*1024) /* heap gap size */ +#endif +#ifndef DFLSSIZ +#define DFLSSIZ ((paddr_t)128*1024*1024) /* initial stack size limit */ +#endif +#ifndef MAXSSIZ +#define MAXSSIZ ((paddr_t)1*1024*1024*1024) /* max stack size */ +#endif + +#define STACKGAP_RANDOM 256*1024 + +/* + * Size of shared memory map + */ +#ifndef SHMMAXPGS +#define SHMMAXPGS 1024 +#endif + +/* + * Size of User Raw I/O map + */ +#define USRIOSIZE 300 + +/** + * Address space layout. + * + * RISC-V implements multiple paging modes with different virtual address space + * sizes: SV32, SV39 and SV48. SV39 permits a virtual address space size of + * 512GB and uses a three-level page table. Since this is large enough for most + * purposes, we currently use SV39 for both userland and the kernel, avoiding + * the extra translation step required by SV48. + * + * The address space is split into two regions at each end of the 64-bit address + * space: + * + * 0x0000000000000000 - 0x0000003fffffffff 256GB user map + * 0x0000004000000000 - 0xffffffbfffffffff unmappable + * 0xffffffc000000000 - 0xffffffc7ffffffff 32GB kernel map + * 0xffffffc800000000 - 0xffffffcfffffffff 32GB unused + * 0xffffffd000000000 - 0xffffffefffffffff 128GB direct map + * 0xfffffff000000000 - 0xffffffffffffffff 64GB unused + * + * The kernel is loaded at the beginning of the kernel map. + * + * We define some interesting address constants: + * + * VM_MIN_ADDRESS and VM_MAX_ADDRESS define the start and end of the entire + * 64 bit address space, mostly just for convenience. + * + * VM_MIN_KERNEL_ADDRESS and VM_MAX_KERNEL_ADDRESS define the start and end of + * mappable kernel virtual address space. + * + * VM_MIN_ADDRESS and VM_MAXUSER_ADDRESS define the start and end of the + * user address space. + */ +#define VM_MIN_ADDRESS ((vaddr_t)PAGE_SIZE) +#define VM_MAX_ADDRESS (0xffffffffffffffffUL) + +#define VM_MIN_KERNEL_ADDRESS (0xffffffc000000000UL) +#define VM_MAX_KERNEL_ADDRESS (0xffffffc800000000UL) + +/* Kernel L1 Page Table Range */ +#define L1_KERN_BASE (256) +#define L1_KERN_ENTRIES (288 - L1_KERN_BASE) + +#define DMAP_MIN_ADDRESS (0xffffffd000000000UL) +#define DMAP_MAX_ADDRESS (0xfffffff000000000UL) + +/* DMAP L1 Page Table Range */ +#define L1_DMAP_BASE (320) +#define L1_DMAP_ENTRIES (448 - L1_DMAP_BASE) + +#define VM_MAXUSER_ADDRESS (0x0000004000000000UL) /* 39 bits */ + +#ifdef _KERNEL +#define VM_MIN_STACK_ADDRESS (VM_MAXUSER_ADDRESS * 3 / 4) +#endif + +#define KERNBASE (VM_MIN_KERNEL_ADDRESS) + +#ifndef _LOCORE +extern paddr_t dmap_phys_base; +#endif + +/* virtual sizes (bytes) for various kernel submaps */ +#define VM_PHYS_SIZE (USRIOSIZE*PAGE_SIZE) + +#define VM_PHYSSEG_MAX 32 +#define VM_PHYSSEG_STRAT VM_PSTRAT_BSEARCH +#define VM_PHYSSEG_NOADD /* can't add RAM after vm_mem_init */ + +#endif /* _MACHINE_VMPARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/_float.h b/lib/libc/include/riscv64-openbsd-none/riscv64/_float.h new file mode 100644 index 000000000000..d52ce43ca74d --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/_float.h @@ -0,0 +1,96 @@ +/* $OpenBSD: _float.h,v 1.1 2021/04/23 02:42:16 drahn Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE__FLOAT_H_ +#define _MACHINE__FLOAT_H_ + +#define __FLT_RADIX 2 /* b */ +#define __FLT_ROUNDS __flt_rounds() +#define __FLT_EVAL_METHOD 0 /* no promotions */ + +#define __FLT_MANT_DIG 24 /* p */ +#define __FLT_EPSILON 1.19209290E-7F /* b**(1-p) */ +#define __FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ +#define __FLT_MIN_EXP (-125) /* emin */ +#define __FLT_MIN 1.17549435E-38F /* b**(emin-1) */ +#define __FLT_MIN_10_EXP (-37) /* ceil(log10(b**(emin-1))) */ +#define __FLT_MAX_EXP 128 /* emax */ +#define __FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ +#define __FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ + +#define __DBL_MANT_DIG 53 +#define __DBL_EPSILON 2.2204460492503131E-16 +#define __DBL_DIG 15 +#define __DBL_MIN_EXP (-1021) +#define __DBL_MIN 2.2250738585072014E-308 +#define __DBL_MIN_10_EXP (-307) +#define __DBL_MAX_EXP 1024 +#define __DBL_MAX 1.7976931348623157E+308 +#define __DBL_MAX_10_EXP 308 + +#ifdef __LDBL_MANT_DIG__ +#define __LDBL_MANT_DIG __LDBL_MANT_DIG__ +#define __LDBL_EPSILON __LDBL_EPSILON__ +#define __LDBL_DIG __LDBL_DIG__ +#define __LDBL_MIN_EXP __LDBL_MIN_EXP__ +#define __LDBL_MIN __LDBL_MIN__ +#define __LDBL_MIN_10_EXP __LDBL_MIN_10_EXP__ +#define __LDBL_MAX_EXP __LDBL_MAX_EXP__ +#define __LDBL_MAX __LDBL_MAX__ +#define __LDBL_MAX_10_EXP __LDBL_MAX_10_EXP__ +#else +#define __LDBL_MANT_DIG DBL_MANT_DIG +#define __LDBL_EPSILON DBL_EPSILON +#define __LDBL_DIG DBL_DIG +#define __LDBL_MIN_EXP DBL_MIN_EXP +#define __LDBL_MIN DBL_MIN +#define __LDBL_MIN_10_EXP DBL_MIN_10_EXP +#define __LDBL_MAX_EXP DBL_MAX_EXP +#define __LDBL_MAX DBL_MAX +#define __LDBL_MAX_10_EXP DBL_MAX_10_EXP +#endif + +#define __DECIMAL_DIG 17 + +#endif /* _MACHINE__FLOAT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/_types.h b/lib/libc/include/riscv64-openbsd-none/riscv64/_types.h new file mode 100644 index 000000000000..b5c1227f1e6e --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/_types.h @@ -0,0 +1,146 @@ +/* $OpenBSD: _types.h,v 1.5 2023/07/02 19:02:28 cheloha Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.3 (Berkeley) 1/5/94 + * @(#)ansi.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _MACHINE__TYPES_H_ +#define _MACHINE__TYPES_H_ + +#if defined(_KERNEL) +typedef struct label_t { + long val[14]; +} label_t; +#endif + +/* + * _ALIGN(p) rounds p (pointer or byte index) up to a correctly-aligned + * value for all data types (int, long, ...). The result is an + * unsigned long and must be cast to any desired pointer type. + * + * _ALIGNED_POINTER is a boolean macro that checks whether an address + * is valid to fetch data elements of type t from on this architecture. + * This does not reflect the optimal alignment, just the possibility + * (within reasonable limits). + */ +#define _ALIGNBYTES (sizeof(long) - 1) +#define _STACKALIGNBYTES 15 +#define _ALIGN(p) (((unsigned long)(p) + _ALIGNBYTES) & ~_ALIGNBYTES) +#define _ALIGNED_POINTER(p,t) ((((unsigned long)(p)) & (sizeof(t) - 1)) == 0) +#define _MAX_PAGE_SHIFT 12 /* same as PAGE_SHIFT */ + +/* 7.18.1.1 Exact-width integer types */ +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short __int16_t; +typedef unsigned short __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; +/* LONGLONG */ +typedef long long __int64_t; +/* LONGLONG */ +typedef unsigned long long __uint64_t; + +/* 7.18.1.2 Minimum-width integer types */ +typedef __int8_t __int_least8_t; +typedef __uint8_t __uint_least8_t; +typedef __int16_t __int_least16_t; +typedef __uint16_t __uint_least16_t; +typedef __int32_t __int_least32_t; +typedef __uint32_t __uint_least32_t; +typedef __int64_t __int_least64_t; +typedef __uint64_t __uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types */ +typedef __int32_t __int_fast8_t; +typedef __uint32_t __uint_fast8_t; +typedef __int32_t __int_fast16_t; +typedef __uint32_t __uint_fast16_t; +typedef __int32_t __int_fast32_t; +typedef __uint32_t __uint_fast32_t; +typedef __int64_t __int_fast64_t; +typedef __uint64_t __uint_fast64_t; +#define __INT_FAST8_MIN INT32_MIN +#define __INT_FAST16_MIN INT32_MIN +#define __INT_FAST32_MIN INT32_MIN +#define __INT_FAST64_MIN INT64_MIN +#define __INT_FAST8_MAX INT32_MAX +#define __INT_FAST16_MAX INT32_MAX +#define __INT_FAST32_MAX INT32_MAX +#define __INT_FAST64_MAX INT64_MAX +#define __UINT_FAST8_MAX UINT32_MAX +#define __UINT_FAST16_MAX UINT32_MAX +#define __UINT_FAST32_MAX UINT32_MAX +#define __UINT_FAST64_MAX UINT64_MAX + +/* 7.18.1.4 Integer types capable of holding object pointers */ +typedef long __intptr_t; +typedef unsigned long __uintptr_t; + +/* 7.18.1.5 Greatest-width integer types */ +typedef __int64_t __intmax_t; +typedef __uint64_t __uintmax_t; + +/* Register size */ +typedef long __register_t; + +/* VM system types */ +typedef unsigned long __vaddr_t; +typedef unsigned long __paddr_t; +typedef unsigned long __vsize_t; +typedef unsigned long __psize_t; + +/* Standard system types */ +typedef double __double_t; +typedef float __float_t; +typedef long __ptrdiff_t; +typedef unsigned long __size_t; +typedef long __ssize_t; +#if defined(__GNUC__) && __GNUC__ >= 3 +typedef __builtin_va_list __va_list; +#else +typedef char * __va_list; +#endif + +/* Wide character support types */ +#ifndef __cplusplus +#ifdef __WCHAR_UNSIGNED__ +typedef unsigned int __wchar_t; +#else +typedef int __wchar_t; +#endif +#endif +typedef int __wint_t; +typedef int __rune_t; +typedef void * __wctrans_t; +typedef void * __wctype_t; + +#endif /* _MACHINE__TYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/apmvar.h b/lib/libc/include/riscv64-openbsd-none/riscv64/apmvar.h new file mode 100644 index 000000000000..18cdbfd9de9e --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/apmvar.h @@ -0,0 +1,122 @@ +/* $OpenBSD: apmvar.h,v 1.1 2023/11/06 20:59:26 jca Exp $ */ + +/* + * Copyright (c) 2001 Alexander Guy + * Copyright (c) 1995 John T. Kohl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _MACHINE_APMVAR_H_ +#define _MACHINE_APMVAR_H_ + +#include + +/* Advanced Power Management (v1.0 and v1.1 specification) + * functions/defines/etc. + */ + +/* These definitions make up the heart of the user-land interface + * to the APM devices. + */ + +#define APM_AC_OFF 0x00 +#define APM_AC_ON 0x01 +#define APM_AC_BACKUP 0x02 +#define APM_AC_UNKNOWN 0xff +#define APM_BATT_HIGH 0x00 +#define APM_BATT_LOW 0x01 +#define APM_BATT_CRITICAL 0x02 +#define APM_BATT_CHARGING 0x03 +#define APM_BATT_UNKNOWN 0xff +#define APM_BATT_LIFE_UNKNOWN 0xff + +#define APM_NOEVENT 0x0000 +#define APM_STANDBY_REQ 0x0001 +#define APM_SUSPEND_REQ 0x0002 +#define APM_NORMAL_RESUME 0x0003 +#define APM_CRIT_RESUME 0x0004 /* suspend/resume happened + without us */ +#define APM_BATTERY_LOW 0x0005 +#define APM_POWER_CHANGE 0x0006 +#define APM_UPDATE_TIME 0x0007 +#define APM_CRIT_SUSPEND_REQ 0x0008 +#define APM_USER_STANDBY_REQ 0x0009 +#define APM_USER_SUSPEND_REQ 0x000A +#define APM_SYS_STANDBY_RESUME 0x000B +#define APM_CAPABILITY_CHANGE 0x000C /* apm v1.2 */ +#define APM_USER_HIBERNATE_REQ 0x000D +#define APM_EVENT_MASK 0xffff + +#define APM_EVENT_COMPOSE(t,i) ((((i) & 0x7fff) << 16)|((t) & APM_EVENT_MASK)) +#define APM_EVENT_TYPE(e) ((e) & APM_EVENT_MASK) +#define APM_EVENT_INDEX(e) ((e) >> 16) + +/* + * LP (Laptop Package) + * + * Copyright (C) 1994 by HOSOKAWA Tatsumi + * + * This software may be used, modified, copied, and distributed, in + * both source and binary form provided that the above copyright and + * these terms are retained. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with its + * use. + * + * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) + */ + +#define APM_BATTERY_ABSENT 4 + +struct apm_power_info { + u_char battery_state; + u_char ac_state; + u_char battery_life; + u_char spare1; + u_int minutes_left; /* estimate */ + u_int spare2[6]; +}; + +struct apm_ctl { + u_int dev; + u_int mode; +}; + +#define APM_IOC_REJECT _IOW('A', 0, struct apm_event_info) /* reject request # */ +#define APM_IOC_STANDBY _IO('A', 1) /* put system into standby */ +#define APM_IOC_SUSPEND _IO('A', 2) /* put system into suspend */ +#define APM_IOC_GETPOWER _IOR('A', 3, struct apm_power_info) /* fetch battery state */ +#define APM_IOC_DEV_CTL _IOW('A', 5, struct apm_ctl) /* put device into mode */ +#define APM_IOC_PRN_CTL _IOW('A', 6, int ) /* driver power status msg */ +#define APM_PRINT_ON 0 /* driver power status displayed */ +#define APM_PRINT_OFF 1 /* driver power status not displayed */ +#define APM_PRINT_PCT 2 /* driver power status only displayed + if the percentage changes */ +#define APM_IOC_STANDBY_REQ _IO('A', 7) /* request standby */ +#define APM_IOC_SUSPEND_REQ _IO('A', 8) /* request suspend */ +#define APM_IOC_HIBERNATE _IO('A', 9) /* put system into hibernate */ + +#endif /* _MACHINE_APMVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/asm.h b/lib/libc/include/riscv64-openbsd-none/riscv64/asm.h new file mode 100644 index 000000000000..dcb1d9d02b8f --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/asm.h @@ -0,0 +1,129 @@ +/* $OpenBSD: asm.h,v 1.8 2022/12/06 00:08:38 jca Exp $ */ + +/* + * Copyright (c) 2020 Brian Bamsch + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)asm.h 5.5 (Berkeley) 5/7/91 + */ + +#ifndef _MACHINE_ASM_H_ +#define _MACHINE_ASM_H_ + +#define _C_LABEL(x) x +#define _ASM_LABEL(x) x + +#ifdef __STDC__ +# define __CONCAT(x,y) x ## y +# define __STRING(x) #x +#else +# define __CONCAT(x,y) x/**/y +# define __STRING(x) "x" +#endif + +#ifndef _ALIGN_TEXT +# define _ALIGN_TEXT .align 0 +#endif + +/* NB == No Binding: use .globl or .weak as necessary */ +#define _ENTRY_NB(x) \ + .text; .p2align 1; .type x,@function; x: +#define _ENTRY(x) .globl x; _ENTRY_NB(x) + +#if defined(PROF) || defined(GPROF) +// XXX Profiler Support +#define _PROF_PROLOGUE \ + addi sp, sp, -16; \ + sd ra, 8(sp); \ + sd fp, 0(sp); \ + mv fp, sp; \ + call __mcount; \ + ld ra, 8(sp); \ + ld fp, 0(sp); \ + add sp, sp, 16; +#else +#define _PROF_PROLOGUE +#endif + +#if defined(_RET_PROTECTOR) +// XXX Retguard Support +#error RETGUARD not yet supported for riscv64 +#else +#define RETGUARD_CALC_COOKIE(reg) +#define RETGUARD_LOAD_RANDOM(x, reg) +#define RETGUARD_SETUP(x, reg) +#define RETGUARD_CHECK(x, reg) +#define RETGUARD_PUSH(reg) +#define RETGUARD_POP(reg) +#define RETGUARD_SYMBOL(x) +#endif + +#define ENTRY(y) _ENTRY(y); _PROF_PROLOGUE +#define ENTRY_NP(y) _ENTRY(y) +#define ENTRY_NB(y) _ENTRY_NB(y); _PROF_PROLOGUE +#define ASENTRY(y) _ENTRY(y); _PROF_PROLOGUE +#define ASENTRY_NP(y) _ENTRY(y) +#define END(y) .size y, . - y +#define EENTRY(sym) .globl sym; sym: +#define EEND(sym) + +#ifdef __PIC__ +#define PIC_SYM(x,y) x(y) +#else +#define PIC_SYM(x,y) x +#endif + +#define STRONG_ALIAS(alias,sym) \ + .global alias; \ + alias = sym +#define WEAK_ALIAS(alias,sym) \ + .weak alias; \ + alias = sym + +#define SWAP_FAULT_HANDLER(handler, tmp0, tmp1) \ + ld tmp0, CI_CURPCB(tp); /* Load the pcb */ \ + ld tmp1, PCB_ONFAULT(tmp0); /* Save old handler */ \ + sd handler, PCB_ONFAULT(tmp0); /* Set the handler */ \ + mv handler, tmp1 + +#define SET_FAULT_HANDLER(handler, pcb) \ + ld pcb, CI_CURPCB(tp); /* Load the pcb */ \ + sd handler, PCB_ONFAULT(pcb) /* Set the handler */ + +#define ENTER_USER_ACCESS(tmp) \ + li tmp, SSTATUS_SUM; \ + csrs sstatus, tmp + +#define EXIT_USER_ACCESS(tmp) \ + li tmp, SSTATUS_SUM; \ + csrc sstatus, tmp + +#endif /* _MACHINE_ASM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/atomic.h b/lib/libc/include/riscv64-openbsd-none/riscv64/atomic.h new file mode 100644 index 000000000000..95cfadaae9dc --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/atomic.h @@ -0,0 +1,50 @@ +/* $OpenBSD: atomic.h,v 1.5 2024/01/24 12:25:50 jca Exp $ */ + +/* Public Domain */ + +#ifndef _MACHINE_ATOMIC_H_ +#define _MACHINE_ATOMIC_H_ + +#define __membar(_f) do {__asm volatile(_f ::: "memory"); } while (0) + +#define membar_enter() __membar("fence w,rw") +#define membar_exit() __membar("fence rw,w") +#define membar_producer() __membar("fence w,w") +#define membar_consumer() __membar("fence r,r") +#define membar_sync() __membar("fence rw,rw") + +#if defined(_KERNEL) + +/* virtio needs MP membars even on SP kernels */ +#define virtio_membar_producer() __membar("fence w,w") +#define virtio_membar_consumer() __membar("fence r,r") +#define virtio_membar_sync() __membar("fence rw,rw") + +/* + * Set bits + * *p = *p | v + */ +static inline void +atomic_setbits_int(volatile unsigned int *p, unsigned int v) +{ + __asm volatile("amoor.w zero, %1, %0" + : "+A" (*p) + : "r" (v) + : "memory"); +} + +/* + * Clear bits + * *p = *p & (~v) + */ +static inline void +atomic_clearbits_int(volatile unsigned int *p, unsigned int v) +{ + __asm volatile("amoand.w zero, %1, %0" + : "+A" (*p) + : "r" (~v) + : "memory"); +} + +#endif /* defined(_KERNEL) */ +#endif /* _MACHINE_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/bootconfig.h b/lib/libc/include/riscv64-openbsd-none/riscv64/bootconfig.h new file mode 100644 index 000000000000..40f8da8ae4f1 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/bootconfig.h @@ -0,0 +1,47 @@ +/* $OpenBSD: bootconfig.h,v 1.5 2024/04/06 18:33:54 kettenis Exp $ */ + +/*- + * Copyright (c) 2015-2017 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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 _MACHINE_BOOTCONFIG_H_ +#define _MACHINE_BOOTCONFIG_H_ + +struct riscv_bootparams { + vaddr_t kern_l1pt; /* L1 page table for the kernel */ + paddr_t kern_phys; + vaddr_t kern_stack; + paddr_t dtbp_phys; /* Device tree blob physical addr */ +}; + +#endif /* _MACHINE_BOOTCONFIG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/bus.h b/lib/libc/include/riscv64-openbsd-none/riscv64/bus.h new file mode 100644 index 000000000000..85999dfe9d44 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/bus.h @@ -0,0 +1,544 @@ +/* $OpenBSD: bus.h,v 1.8 2025/08/03 14:03:12 jca Exp $ */ + +/* + * Copyright (c) 2003-2004 Opsycon AB Sweden. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BUS_H_ +#define _MACHINE_BUS_H_ + +#ifdef __STDC__ +#define CAT(a,b) a##b +#define CAT3(a,b,c) a##b##c +#else +#define CAT(a,b) a/**/b +#define CAT3(a,b,c) a/**/b/**/c +#endif + +/* + * Bus access types. + */ +struct bus_space; +typedef u_long bus_addr_t; +typedef u_long bus_size_t; +typedef u_long bus_space_handle_t; +typedef struct bus_space *bus_space_tag_t; +typedef struct bus_space bus_space_t; + +struct bus_space { + bus_addr_t bus_base; + void *bus_private; + u_int8_t (*_space_read_1)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_1)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int8_t); + u_int16_t (*_space_read_2)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_2)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int16_t); + u_int32_t (*_space_read_4)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_4)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int32_t); + u_int64_t (*_space_read_8)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_8)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int64_t); + void (*_space_read_raw_2)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_2)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + void (*_space_read_raw_4)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_4)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + void (*_space_read_raw_8)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_8)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + int (*_space_map)(bus_space_tag_t , bus_addr_t, + bus_size_t, int, bus_space_handle_t *); + void (*_space_unmap)(bus_space_tag_t, bus_space_handle_t, + bus_size_t); + int (*_space_subregion)(bus_space_tag_t, bus_space_handle_t, + bus_size_t, bus_size_t, bus_space_handle_t *); + void * (*_space_vaddr)(bus_space_tag_t, bus_space_handle_t); + paddr_t (*_space_mmap)(bus_space_tag_t, bus_addr_t, off_t, + int, int); +}; + +#define bus_space_read_1(t, h, o) (*(t)->_space_read_1)((t), (h), (o)) +#define bus_space_read_2(t, h, o) (*(t)->_space_read_2)((t), (h), (o)) +#define bus_space_read_4(t, h, o) (*(t)->_space_read_4)((t), (h), (o)) +#define bus_space_read_8(t, h, o) (*(t)->_space_read_8)((t), (h), (o)) + +#define bus_space_write_1(t, h, o, v) (*(t)->_space_write_1)((t), (h), (o), (v)) +#define bus_space_write_2(t, h, o, v) (*(t)->_space_write_2)((t), (h), (o), (v)) +#define bus_space_write_4(t, h, o, v) (*(t)->_space_write_4)((t), (h), (o), (v)) +#define bus_space_write_8(t, h, o, v) (*(t)->_space_write_8)((t), (h), (o), (v)) + +#define bus_space_read_raw_2(t, h, o) \ + (*(t)->_space_read_2)((t), (h), (o)) +#define bus_space_read_raw_4(t, h, o) \ + (*(t)->_space_read_4)((t), (h), (o)) +#define bus_space_read_raw_8(t, h, o) \ + (*(t)->_space_read_8)((t), (h), (o)) + +#define bus_space_write_raw_2(t, h, o, v) \ + (*(t)->_space_write_2)((t), (h), (o), (v)) +#define bus_space_write_raw_4(t, h, o, v) \ + (*(t)->_space_write_4)((t), (h), (o), (v)) +#define bus_space_write_raw_8(t, h, o, v) \ + (*(t)->_space_write_8)((t), (h), (o), (v)) + +#define bus_space_read_raw_multi_2(t, h, a, b, l) \ + (*(t)->_space_read_raw_2)((t), (h), (a), (b), (l)) +#define bus_space_read_raw_multi_4(t, h, a, b, l) \ + (*(t)->_space_read_raw_4)((t), (h), (a), (b), (l)) +#define bus_space_read_raw_multi_8(t, h, a, b, l) \ + (*(t)->_space_read_raw_8)((t), (h), (a), (b), (l)) + +#define bus_space_write_raw_multi_2(t, h, a, b, l) \ + (*(t)->_space_write_raw_2)((t), (h), (a), (b), (l)) +#define bus_space_write_raw_multi_4(t, h, a, b, l) \ + (*(t)->_space_write_raw_4)((t), (h), (a), (b), (l)) +#define bus_space_write_raw_multi_8(t, h, a, b, l) \ + (*(t)->_space_write_raw_8)((t), (h), (a), (b), (l)) + +#define bus_space_map(t, o, s, c, p) (*(t)->_space_map)((t), (o), (s), (c), (p)) +#define bus_space_unmap(t, h, s) (*(t)->_space_unmap)((t), (h), (s)) +#define bus_space_subregion(t, h, o, s, p) \ + (*(t)->_space_subregion)((t), (h), (o), (s), (p)) + +#define BUS_SPACE_MAP_CACHEABLE 0x01 +#define BUS_SPACE_MAP_LINEAR 0x02 +#define BUS_SPACE_MAP_PREFETCHABLE 0x04 + +extern bus_space_t riscv64_bs_tag; + +#define bus_space_vaddr(t, h) (*(t)->_space_vaddr)((t), (h)) +#define bus_space_mmap(t, a, o, p, f) \ + (*(t)->_space_mmap)((t), (a), (o), (p), (f)) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_multi(n,m) \ +static __inline void \ +CAT(bus_space_read_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t o, CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) \ + *x++ = CAT(bus_space_read_,n)(bst, bsh, o); \ +} + +bus_space_read_multi(1,8) +bus_space_read_multi(2,16) +bus_space_read_multi(4,32) +bus_space_read_multi(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_region(n,m) \ +static __inline void \ +CAT(bus_space_read_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) { \ + *x++ = CAT(bus_space_read_,n)(bst, bsh, ba); \ + ba += (n); \ + } \ +} + +bus_space_read_region(1,8) +bus_space_read_region(2,16) +bus_space_read_region(4,32) +bus_space_read_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_raw_region(n,m) \ +static __inline void \ +CAT(bus_space_read_raw_region_,n)(bus_space_tag_t bst, \ + bus_space_handle_t bsh, \ + bus_addr_t ba, u_int8_t *x, size_t cnt) \ +{ \ + cnt >>= ((n) >> 1); \ + while (cnt--) { \ + CAT(bus_space_read_raw_multi_,n)(bst, bsh, ba, x, (n)); \ + ba += (n); \ + x += (n); \ + } \ +} + +bus_space_read_raw_region(2,16) +bus_space_read_raw_region(4,32) +bus_space_read_raw_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_multi(n,m) \ +static __inline void \ +CAT(bus_space_write_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t o, const CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) \ + CAT(bus_space_write_,n)(bst, bsh, o, *x++); \ +} + +bus_space_write_multi(1,8) +bus_space_write_multi(2,16) +bus_space_write_multi(4,32) +bus_space_write_multi(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_region(n,m) \ +static __inline void \ +CAT(bus_space_write_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, const CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) { \ + CAT(bus_space_write_,n)(bst, bsh, ba, *x++); \ + ba += (n); \ + } \ +} + +bus_space_write_region(1,8) +bus_space_write_region(2,16) +bus_space_write_region(4,32) +bus_space_write_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_raw_region(n,m) \ +static __inline void \ +CAT(bus_space_write_raw_region_,n)(bus_space_tag_t bst, \ + bus_space_handle_t bsh, \ + bus_addr_t ba, const u_int8_t *x, size_t cnt) \ +{ \ + cnt >>= ((n) >> 1); \ + while (cnt--) { \ + CAT(bus_space_write_raw_multi_,n)(bst, bsh, ba, x, (n)); \ + ba += (n); \ + x += (n); \ + } \ +} + +bus_space_write_raw_region(2,16) +bus_space_write_raw_region(4,32) +bus_space_write_raw_region(8,64) + +/*----------------------------------------------------------------------------*/ +#define bus_space_set_region(n,m) \ +static __inline void \ +CAT(bus_space_set_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(u_int,m,_t) x, size_t cnt) \ +{ \ + while (cnt--) { \ + CAT(bus_space_write_,n)(bst, bsh, ba, x); \ + ba += (n); \ + } \ +} + +bus_space_set_region(1,8) +bus_space_set_region(2,16) +bus_space_set_region(4,32) +bus_space_set_region(8,64) + +/*----------------------------------------------------------------------------*/ +static __inline void +bus_space_copy_1(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + char *s = (char *)(h1 + o1); + char *d = (char *)(h2 + o2); + + __asm volatile ("fence w,o" ::: "memory"); + while (c--) + *d++ = *s++; + __asm volatile ("fence io,iwr" ::: "memory"); +} + + +static __inline void +bus_space_copy_2(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + short *s = (short *)(h1 + o1); + short *d = (short *)(h2 + o2); + + __asm volatile ("fence w,o" ::: "memory"); + while (c--) + *d++ = *s++; + __asm volatile ("fence io,iwr" ::: "memory"); +} + +static __inline void +bus_space_copy_4(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + int *s = (int *)(h1 + o1); + int *d = (int *)(h2 + o2); + + __asm volatile ("fence w,o" ::: "memory"); + while (c--) + *d++ = *s++; + __asm volatile ("fence io,iwr" ::: "memory"); +} + +static __inline void +bus_space_copy_8(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + int64_t *s = (int64_t *)(h1 + o1); + int64_t *d = (int64_t *)(h2 + o2); + + __asm volatile ("fence w,o" ::: "memory"); + while (c--) + *d++ = *s++; + __asm volatile ("fence io,iwr" ::: "memory"); +} + +/*----------------------------------------------------------------------------*/ +/* + * Bus read/write barrier methods. + * + * void bus_space_barrier(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * bus_size_t len, int flags); + * + */ +static inline void +bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, + bus_size_t length, int flags) +{ + __asm__ volatile ("fence iorw,iorw" ::: "memory"); +} +#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ +#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ + +#define BUS_DMA_WAITOK 0x0000 +#define BUS_DMA_NOWAIT 0x0001 +#define BUS_DMA_ALLOCNOW 0x0002 +#define BUS_DMA_COHERENT 0x0008 +#define BUS_DMA_BUS1 0x0010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x0020 +#define BUS_DMA_BUS3 0x0040 +#define BUS_DMA_BUS4 0x0080 +#define BUS_DMA_READ 0x0100 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x0200 /* mapping is memory -> device only */ +#define BUS_DMA_STREAMING 0x0400 /* hint: sequential, unidirectional */ +#define BUS_DMA_ZERO 0x0800 /* zero memory in dmamem_alloc */ +#define BUS_DMA_NOCACHE 0x1000 +#define BUS_DMA_64BIT 0x2000 /* device handles 64bit dva */ + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct proc; +struct uio; + +#define BUS_DMASYNC_POSTREAD 0x0001 +#define BUS_DMASYNC_POSTWRITE 0x0002 +#define BUS_DMASYNC_PREREAD 0x0004 +#define BUS_DMASYNC_PREWRITE 0x0008 + +typedef struct machine_bus_dma_tag *bus_dma_tag_t; +typedef struct machine_bus_dmamap *bus_dmamap_t; + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +struct machine_bus_dma_segment { + bus_addr_t ds_addr; /* DMA address */ + bus_size_t ds_len; /* length of transfer */ + + paddr_t _ds_paddr; /* CPU address */ + vaddr_t _ds_vaddr; /* CPU address */ + int _ds_coherent; /* Coherently mapped */ +}; +typedef struct machine_bus_dma_segment bus_dma_segment_t; + +/* + * bus_dma_tag_t + * + * A machine-dependent opaque type describing the implementation of + * DMA for a given bus. + */ + +struct machine_bus_dma_tag { + void *_cookie; /* cookie used in the guts */ + int _flags; /* misc. flags */ + + /* + * DMA mapping methods. + */ + int (*_dmamap_create)(bus_dma_tag_t , bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); + void (*_dmamap_destroy)(bus_dma_tag_t , bus_dmamap_t); + int (*_dmamap_load)(bus_dma_tag_t , bus_dmamap_t, void *, + bus_size_t, struct proc *, int); + int (*_dmamap_load_mbuf)(bus_dma_tag_t , bus_dmamap_t, + struct mbuf *, int); + int (*_dmamap_load_uio)(bus_dma_tag_t , bus_dmamap_t, + struct uio *, int); + int (*_dmamap_load_raw)(bus_dma_tag_t , bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); + int (*_dmamap_load_buffer)(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int, paddr_t *, int *, int); + void (*_dmamap_unload)(bus_dma_tag_t , bus_dmamap_t); + void (*_dmamap_sync)(bus_dma_tag_t , bus_dmamap_t, + bus_addr_t, bus_size_t, int); + + /* + * DMA memory utility functions. + */ + int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); + int (*_dmamem_alloc_range)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int, + paddr_t, paddr_t); + void (*_dmamem_free)(bus_dma_tag_t, bus_dma_segment_t *, int); + int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); + void (*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t); + paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, + int, off_t, int, int); + + /* + * internal memory address translation information. + */ + bus_addr_t _dma_mask; +}; + +#define bus_dmamap_create(t, s, n, m, b, f, p) \ + (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) +#define bus_dmamap_destroy(t, p) \ + (*(t)->_dmamap_destroy)((t), (p)) +#define bus_dmamap_load(t, m, b, s, p, f) \ + (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) +#define bus_dmamap_load_mbuf(t, m, b, f) \ + (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) +#define bus_dmamap_load_uio(t, m, u, f) \ + (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) +#define bus_dmamap_load_raw(t, m, sg, n, s, f) \ + (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) +#define bus_dmamap_unload(t, p) \ + (*(t)->_dmamap_unload)((t), (p)) +#define bus_dmamap_sync(t, p, a, l, o) \ + (void)((t)->_dmamap_sync ? \ + (*(t)->_dmamap_sync)((t), (p), (a), (l), (o)) : (void)0) + +#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ + (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f)) +#define bus_dmamem_alloc_range(t, s, a, b, sg, n, r, f, l, h) \ + (*(t)->_dmamem_alloc_range)((t), (s), (a), (b), (sg), \ + (n), (r), (f), (l), (h)) +#define bus_dmamem_free(t, sg, n) \ + (*(t)->_dmamem_free)((t), (sg), (n)) +#define bus_dmamem_map(t, sg, n, s, k, f) \ + (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f)) +#define bus_dmamem_unmap(t, k, s) \ + (*(t)->_dmamem_unmap)((t), (k), (s)) +#define bus_dmamem_mmap(t, sg, n, o, p, f) \ + (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f)) + +int _dmamap_create(bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); +void _dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); +int _dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); +int _dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *, int); +int _dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, struct uio *, int); +int _dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); +int _dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int, paddr_t *, int *, int); +void _dmamap_unload(bus_dma_tag_t, bus_dmamap_t); +void _dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, + bus_size_t, int); + +int _dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); +void _dmamem_free(bus_dma_tag_t, bus_dma_segment_t *, int); +int _dmamem_map(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); +void _dmamem_unmap(bus_dma_tag_t, caddr_t, size_t); +paddr_t _dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, int, int); +int _dmamem_alloc_range(bus_dma_tag_t, bus_size_t, bus_size_t, bus_size_t, + bus_dma_segment_t *, int, int *, int, paddr_t, paddr_t); + +/* + * bus_dmamap_t + * + * Describes a DMA mapping. + */ +struct machine_bus_dmamap { + /* + * PRIVATE MEMBERS: not for use by machine-independent code. + */ + bus_size_t _dm_size; /* largest DMA transfer mappable */ + int _dm_segcnt; /* number of segs this map can map */ + bus_size_t _dm_maxsegsz; /* largest possible segment */ + bus_size_t _dm_boundary; /* don't cross this */ + int _dm_flags; /* misc. flags */ + + void *_dm_cookie; /* cookie for bus-specific functions */ + + /* + * PUBLIC MEMBERS: these are used by machine-independent code. + */ + bus_size_t dm_mapsize; /* size of the mapping */ + int dm_nsegs; /* # valid segments in mapping */ + bus_dma_segment_t dm_segs[1]; /* segments; variable length */ +}; + +int generic_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, + bus_space_handle_t *); +void generic_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t); +int generic_space_region(bus_space_tag_t, bus_space_handle_t, bus_size_t, + bus_size_t, bus_space_handle_t *); +void *generic_space_vaddr(bus_space_tag_t, bus_space_handle_t); +paddr_t generic_space_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int); +uint8_t generic_space_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint16_t generic_space_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint32_t generic_space_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint64_t generic_space_read_8(bus_space_tag_t, bus_space_handle_t, bus_size_t); +void generic_space_read_raw_2(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint8_t); +void generic_space_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint16_t); +void generic_space_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint32_t); +void generic_space_write_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint64_t); +void generic_space_write_raw_2(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); +void generic_space_read_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); +void generic_space_read_raw_8(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_raw_8(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); + +#endif /* _MACHINE_BUS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/cdefs.h b/lib/libc/include/riscv64-openbsd-none/riscv64/cdefs.h new file mode 100644 index 000000000000..951add32121c --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/cdefs.h @@ -0,0 +1,16 @@ +/* $OpenBSD: cdefs.h,v 1.1 2021/04/23 02:42:16 drahn Exp $ */ + +#ifndef _MACHINE_CDEFS_H_ +#define _MACHINE_CDEFS_H_ + +#define __strong_alias(alias,sym) \ + __asm__(".global " __STRING(alias) " ; " __STRING(alias) \ + " = " __STRING(sym)) +#define __weak_alias(alias,sym) \ + __asm__(".weak " __STRING(alias) " ; " __STRING(alias) \ + " = " __STRING(sym)) +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning." __STRING(sym) \ + " ; .ascii \"" msg "\" ; .text") + +#endif /* !_MACHINE_CDEFS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/conf.h b/lib/libc/include/riscv64-openbsd-none/riscv64/conf.h new file mode 100644 index 000000000000..9dc1b949f210 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/conf.h @@ -0,0 +1,50 @@ +/* $OpenBSD: conf.h,v 1.4 2022/06/28 14:43:50 visa Exp $ */ + +/* + * Copyright (c) 1996 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_CONF_H_ +#define _MACHINE_CONF_H_ + +#include + +#define mmread mmrw +#define mmwrite mmrw +cdev_decl(mm); + +/* open, close, ioctl */ +#define cdev_openprom_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) nullop, 0, \ + (dev_type_mmap((*))) enodev } + +cdev_decl(openprom); + +#endif /* _MACHINE_CONF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/cpu.h b/lib/libc/include/riscv64-openbsd-none/riscv64/cpu.h new file mode 100644 index 000000000000..8e6ecc4dca9a --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/cpu.h @@ -0,0 +1,284 @@ +/* $OpenBSD: cpu.h,v 1.24 2024/06/11 16:02:35 jca Exp $ */ + +/* + * Copyright (c) 2019 Mike Larkin + * Copyright (c) 2016 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_CPU_H_ +#define _MACHINE_CPU_H_ + +/* + * User-visible definitions + */ + +/* CTL_MACHDEP definitions. */ +#define CPU_COMPATIBLE 1 /* compatible property */ +#define CPU_MAXID 2 /* number of valid machdep ids */ + +#define CTL_MACHDEP_NAMES { \ + { 0, 0 }, \ + { "compatible", CTLTYPE_STRING }, \ +} + +#ifdef _KERNEL + +/* + * Kernel-only definitions + */ +#include +#include +#include + +/* All the CLKF_* macros take a struct clockframe * as an argument. */ + +#define clockframe trapframe +/* + * CLKF_USERMODE: Return TRUE/FALSE (1/0) depending on whether the + * frame came from USR mode or not. + */ +#define CLKF_USERMODE(frame) ((frame->tf_sstatus & SSTATUS_SPP) == 0) + +/* + * CLKF_INTR: True if we took the interrupt from inside another + * interrupt handler. + */ +#define CLKF_INTR(frame) (curcpu()->ci_idepth > 1) + +/* + * CLKF_PC: Extract the program counter from a clockframe + */ +#define CLKF_PC(frame) (frame->tf_sepc) + +/* + * PROC_PC: Find out the program counter for the given process. + */ +#define PROC_PC(p) ((p)->p_addr->u_pcb.pcb_tf->tf_sepc) +#define PROC_STACK(p) ((p)->p_addr->u_pcb.pcb_tf->tf_sp) + +#include +#include +#include +#include +#include + +struct cpu_info { + struct device *ci_dev; /* Device corresponding to this CPU */ + struct cpu_info *ci_next; + struct schedstate_percpu ci_schedstate; /* scheduler state */ + + u_int32_t ci_cpuid; + uint64_t ci_hartid; + int ci_node; + struct cpu_info *ci_self; + + struct proc *ci_curproc; + struct pmap *ci_curpm; + u_int32_t ci_randseed; + + struct pcb *ci_curpcb; + struct pcb *ci_idle_pcb; + + struct clockqueue ci_queue; + volatile int ci_timer_deferred; + + uint32_t ci_cpl; + uint32_t ci_ipending; + uint32_t ci_idepth; +#ifdef DIAGNOSTIC + int ci_mutex_level; +#endif + int ci_want_resched; + + struct opp_table *ci_opp_table; + volatile int ci_opp_idx; + volatile int ci_opp_max; + uint32_t ci_cpu_supply; + +#ifdef MULTIPROCESSOR + struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM]; +#define __HAVE_UVM_PERCPU + struct uvm_pmr_cache ci_uvm; + volatile int ci_flags; + uint64_t ci_satp; + vaddr_t ci_initstack_end; + int ci_ipi_reason; + + volatile int ci_ddb_paused; +#define CI_DDB_RUNNING 0 +#define CI_DDB_SHOULDSTOP 1 +#define CI_DDB_STOPPED 2 +#define CI_DDB_ENTERDDB 3 +#define CI_DDB_INDDB 4 + +#endif + +#ifdef GPROF + struct gmonparam *ci_gmon; + struct clockintr ci_gmonclock; +#endif + + char ci_panicbuf[512]; +}; + +#define CPUF_PRIMARY (1<<0) +#define CPUF_AP (1<<1) +#define CPUF_IDENTIFY (1<<2) +#define CPUF_IDENTIFIED (1<<3) +#define CPUF_PRESENT (1<<4) +#define CPUF_GO (1<<5) +#define CPUF_RUNNING (1<<6) + +static inline struct cpu_info * +curcpu(void) +{ + struct cpu_info *__ci = NULL; + __asm volatile("mv %0, tp" : "=&r"(__ci)); + return (__ci); +} + +extern uint32_t boot_hart; /* The hart we booted on. */ +extern struct cpu_info cpu_info_primary; +extern struct cpu_info *cpu_info_list; + +#ifndef MULTIPROCESSOR + +#define cpu_number() 0 +#define CPU_IS_PRIMARY(ci) 1 +#define CPU_IS_RUNNING(ci) 1 +#define CPU_INFO_ITERATOR int +#define CPU_INFO_FOREACH(cii, ci) \ + for (cii = 0, ci = curcpu(); ci != NULL; ci = NULL) +#define CPU_INFO_UNIT(ci) 0 +#define MAXCPUS 1 +#define cpu_unidle(ci) + +#else + +#define cpu_number() (curcpu()->ci_cpuid) +#define CPU_IS_PRIMARY(ci) ((ci) == &cpu_info_primary) +#define CPU_IS_RUNNING(ci) ((ci)->ci_flags & CPUF_RUNNING) +#define CPU_INFO_ITERATOR int +#define CPU_INFO_FOREACH(cii, ci) for (cii = 0, ci = cpu_info_list; \ + ci != NULL; ci = ci->ci_next) +#define CPU_INFO_UNIT(ci) ((ci)->ci_dev ? (ci)->ci_dev->dv_unit : 0) +#define MAXCPUS 32 + +extern struct cpu_info *cpu_info[MAXCPUS]; + +void cpu_boot_secondary_processors(void); + +#endif /* !MULTIPROCESSOR */ + +/* Zihintpause ratified extension */ +#define CPU_BUSY_CYCLE() __asm volatile(".long 0x0100000f" ::: "memory") + +#define curpcb curcpu()->ci_curpcb + +static inline unsigned int +cpu_rnd_messybits(void) +{ + // Should do bit reversal ^ with csr_read(time); + return csr_read(time); +} + +/* + * Scheduling glue + */ +#define aston(p) ((p)->p_md.md_astpending = 1) +#define setsoftast() aston(curcpu()->ci_curproc) + +/* + * Notify the current process (p) that it has a signal pending, + * process as soon as possible. + */ + +#ifdef MULTIPROCESSOR +void cpu_unidle(struct cpu_info *ci); +#define signotify(p) (aston(p), cpu_unidle((p)->p_cpu)) +void cpu_kick(struct cpu_info *); +#else +#define cpu_kick(ci) +#define cpu_unidle(ci) +#define signotify(p) setsoftast() +#endif + +/* + * Preempt the current process if in interrupt from user mode, + * or after the current trap/syscall if in system mode. + */ +void need_resched(struct cpu_info *); +#define clear_resched(ci) ((ci)->ci_want_resched = 0) + +/* + * Give a profiling tick to the current process when the user profiling + * buffer pages are invalid. On the i386, request an ast to send us + * through trap(), marking the proc as needing a profiling tick. + */ +#define need_proftick(p) aston(p) + +// asm code to start new kernel contexts. +void proc_trampoline(void); + +/* + * Random cruft + */ +void dumpconf(void); + +static inline void +intr_enable(void) +{ + __asm volatile("csrsi sstatus, %0" :: "i" (SSTATUS_SIE)); +} + +static inline u_long +intr_disable(void) +{ + uint64_t ret; + + __asm volatile( + "csrrci %0, sstatus, %1" + : "=&r" (ret) : "i" (SSTATUS_SIE) + ); + + return (ret & (SSTATUS_SIE)); +} + +static inline void +intr_restore(u_long s) +{ + __asm volatile("csrs sstatus, %0" :: "r" (s)); +} + +void delay (unsigned); +#define DELAY(x) delay(x) + +extern void (*cpu_startclock_fcn)(void); + +void fpu_save(struct proc *, struct trapframe *); +void fpu_load(struct proc *); + +extern int cpu_errata_sifive_cip_1200; + +#define cpu_idle_enter() do { /* nothing */ } while (0) +#define cpu_idle_leave() do { /* nothing */ } while (0) + +#endif /* _KERNEL */ + +#ifdef MULTIPROCESSOR +#include +#endif /* MULTIPROCESSOR */ + +#endif /* !_MACHINE_CPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/cpufunc.h b/lib/libc/include/riscv64-openbsd-none/riscv64/cpufunc.h new file mode 100644 index 000000000000..f4b61288bb38 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/cpufunc.h @@ -0,0 +1,103 @@ +/* $OpenBSD: cpufunc.h,v 1.6 2023/08/21 20:17:30 miod Exp $ */ + +/*- + * Copyright (c) 2014 Andrew Turner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: head/sys/cpu/include/cpufunc.h 299683 2016-05-13 16:03:50Z andrew $ + */ + +#ifndef _MACHINE_CPUFUNC_H_ +#define _MACHINE_CPUFUNC_H_ + +static __inline void +breakpoint(void) +{ + __asm("ebreak"); +} + +#ifdef _KERNEL + +#include + +#define rdcycle() csr_read(cycle) +#define rdtime() csr_read(time) +#define rdinstret() csr_read(instret) +#define rdhpmcounter(n) csr_read(hpmcounter##n) + +static __inline void +fence_i(void) +{ + __asm volatile("fence.i" ::: "memory"); +} + +static __inline void +sfence_vma(void) +{ + __asm volatile("sfence.vma" ::: "memory"); +} + +static __inline void +sfence_vma_page(uintptr_t addr) +{ + __asm volatile("sfence.vma %0" + : + : "r" (addr) + : "memory"); +} + +// XXX ASIDs in riscv64 are only 16 bits. +static __inline void +sfence_vma_asid(uint64_t asid) +{ + __asm volatile("sfence.vma x0, %0" + : + : "r" (asid) + : "memory"); +} + +static __inline void +sfence_vma_page_asid(uintptr_t addr, uint64_t asid) +{ + __asm volatile("sfence.vma %0, %1" + : + : "r" (addr), "r" (asid) + : "memory"); +} + +extern int64_t dcache_line_size; +extern int64_t icache_line_size; + +extern void (*cpu_dcache_wbinv_range)(paddr_t, psize_t); +extern void (*cpu_dcache_inv_range)(paddr_t, psize_t); +extern void (*cpu_dcache_wb_range)(paddr_t, psize_t); + +static __inline void +load_satp(uint64_t val) +{ + __asm volatile("csrw satp, %0" :: "r"(val)); +} + +#endif /* _KERNEL */ +#endif /* _MACHINE_CPUFUNC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/db_machdep.h b/lib/libc/include/riscv64-openbsd-none/riscv64/db_machdep.h new file mode 100644 index 000000000000..0d0e4fdfb956 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/db_machdep.h @@ -0,0 +1,93 @@ +/* $OpenBSD: db_machdep.h,v 1.5 2021/08/30 08:11:12 jasper Exp $ */ + +/* + * Copyright (c) 2019 Brian Bamsch + * Copyright (c) 2015-2016 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_DB_MACHDEP_H_ +#define _MACHINE_DB_MACHDEP_H_ + +#include +#include +#include +#include +#include + +#define T_BREAKPOINT (EXCP_BREAKPOINT) +#define T_WATCHPOINT (0) + +typedef long db_expr_t; + +typedef trapframe_t db_regs_t; + +extern db_regs_t ddb_regs; +#define DDB_REGS (&ddb_regs) + +#define PC_REGS(regs) ((vaddr_t)(regs)->tf_ra) +#define SET_PC_REGS(regs, value) (regs)->tf_ra = (register_t)(value) + +#define BKPT_INST (KERNEL_BREAKPOINT) +#define BKPT_SIZE (INSN_SIZE) +#define BKPT_SET(inst) (BKPT_INST) + +#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BREAKPOINT) +#define IS_WATCHPOINT_TRAP(type, code) ((type) == T_WATCHPOINT) + +#define inst_trap_return(ins) (ins == 0x10000073) /* eret */ +#define inst_return(ins) (ins == 0x00008067) /* ret */ +#define inst_call(ins) (((ins) & 0x7f) == 0x6f || \ + ((ins) & 0x7f) == 0x67) /* jal, jalr */ +#define inst_branch(ins) (((ins) & 0x7f) == 0x63) /* branch */ + +#define next_instr_address(pc, bd) ((bd) ? (pc) : ((pc) + INSN_SIZE)) + +#define DB_MACHINE_COMMANDS + +#define SOFTWARE_SSTEP + +int db_trapper(vaddr_t, u_int, trapframe_t *, int); +void db_machine_init (void); +vaddr_t db_branch_taken(u_int inst, vaddr_t pc, db_regs_t *regs); + +#define branch_taken(ins, pc, fun, regs) \ + db_branch_taken((ins), (pc), (regs)) + +/* For ddb_state */ +#define DDB_STATE_NOT_RUNNING 0 +#define DDB_STATE_RUNNING 1 +#define DDB_STATE_EXITING 2 + +#endif /* !_MACHINE_DB_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/disklabel.h b/lib/libc/include/riscv64-openbsd-none/riscv64/disklabel.h new file mode 100644 index 000000000000..fcb739943e89 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/disklabel.h @@ -0,0 +1,26 @@ +/* $OpenBSD: disklabel.h,v 1.2 2021/05/12 01:20:52 jsg Exp $ */ + +/* + * Copyright (c) 2014 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_DISKLABEL_H_ +#define _MACHINE_DISKLABEL_H_ + +#define LABELSECTOR 1 /* sector containing label */ +#define LABELOFFSET 0 /* offset of label in sector */ +#define MAXPARTITIONS 16 /* number of partitions */ + +#endif /* _MACHINE_DISKLABEL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/elf.h b/lib/libc/include/riscv64-openbsd-none/riscv64/elf.h new file mode 100644 index 000000000000..651c966fb81c --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/elf.h @@ -0,0 +1,52 @@ +/* $OpenBSD: elf.h,v 1.3 2024/07/14 09:48:49 jca Exp $ */ + +/*- + * Copyright (c) 1996-1997 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_ELF_H_ +#define _MACHINE_ELF_H_ + +/* + * ELF definitions for the RISC-V architecture. + */ + +#ifdef _KERNEL +# define __HAVE_CPU_HWCAP +extern unsigned long hwcap; +#endif /* _KERNEL */ + +/* Flags passed in AT_HWCAP */ +#define HWCAP_ISA_BIT(c) (1 << ((c) - 'a')) +#define HWCAP_ISA_I HWCAP_ISA_BIT('i') +#define HWCAP_ISA_M HWCAP_ISA_BIT('m') +#define HWCAP_ISA_A HWCAP_ISA_BIT('a') +#define HWCAP_ISA_F HWCAP_ISA_BIT('f') +#define HWCAP_ISA_D HWCAP_ISA_BIT('d') +#define HWCAP_ISA_C HWCAP_ISA_BIT('c') +#define HWCAP_ISA_G \ + (HWCAP_ISA_I | HWCAP_ISA_M | HWCAP_ISA_A | HWCAP_ISA_F | HWCAP_ISA_D) + +#endif /* !_MACHINE_ELF_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/endian.h b/lib/libc/include/riscv64-openbsd-none/riscv64/endian.h new file mode 100644 index 000000000000..b63c54e85059 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/endian.h @@ -0,0 +1,29 @@ +/* $OpenBSD: endian.h,v 1.3 2022/03/22 06:46:45 miod Exp $ */ + +/* + * Copyright (c) 2015 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_ENDIAN_H_ +#define _MACHINE_ENDIAN_H_ + +#define _BYTE_ORDER _LITTLE_ENDIAN +#define __STRICT_ALIGNMENT + +#ifndef __FROM_SYS__ENDIAN +#include +#endif + +#endif /* _MACHINE_ENDIAN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/exec.h b/lib/libc/include/riscv64-openbsd-none/riscv64/exec.h new file mode 100644 index 000000000000..a6073819af0e --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/exec.h @@ -0,0 +1,30 @@ +/* $OpenBSD: exec.h,v 1.2 2021/05/12 01:20:52 jsg Exp $ */ + +/* + * Copyright (c) 2014 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_EXEC_H_ +#define _MACHINE_EXEC_H_ + +#define __LDPGSZ 4096 + +#define ARCH_ELFSIZE 64 + +#define ELF_TARG_CLASS ELFCLASS64 +#define ELF_TARG_DATA ELFDATA2LSB +#define ELF_TARG_MACH EM_RISCV + +#endif \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/fdt.h b/lib/libc/include/riscv64-openbsd-none/riscv64/fdt.h new file mode 100644 index 000000000000..536ed4d04bcc --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/fdt.h @@ -0,0 +1,59 @@ +/* $OpenBSD: fdt.h,v 1.4 2022/05/30 17:39:09 kettenis Exp $ */ + +/* + * Copyright (c) 2016 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __RISCV_FDT_H__ +#define __RISCV_FDT_H__ + +#define _RISCV64_BUS_DMA_PRIVATE +#include + +struct fdt_attach_args { + const char *fa_name; + int fa_node; + bus_space_tag_t fa_iot; + bus_dma_tag_t fa_dmat; + struct fdt_reg *fa_reg; + int fa_nreg; + uint32_t *fa_intr; + int fa_nintr; + int fa_acells; + int fa_scells; +}; + +extern int stdout_node; +extern int stdout_speed; +extern bus_space_tag_t fdt_cons_bs_tag; + +void *fdt_find_cons(const char *); + +#define fdt_intr_enable riscv_intr_enable +#define fdt_intr_establish riscv_intr_establish_fdt +#define fdt_intr_establish_idx riscv_intr_establish_fdt_idx +#define fdt_intr_establish_idx_cpu riscv_intr_establish_fdt_idx_cpu +#define fdt_intr_establish_imap riscv_intr_establish_fdt_imap +#define fdt_intr_establish_imap_cpu riscv_intr_establish_fdt_imap_cpu +#define fdt_intr_establish_msi riscv_intr_establish_fdt_msi +#define fdt_intr_establish_msi_cpu riscv_intr_establish_fdt_msi_cpu +#define fdt_intr_disable riscv_intr_disable +#define fdt_intr_disestablish riscv_intr_disestablish_fdt +#define fdt_intr_get_parent riscv_intr_get_parent +#define fdt_intr_parent_establish riscv_intr_parent_establish_fdt +#define fdt_intr_parent_disestablish riscv_intr_parent_disestablish_fdt +#define fdt_intr_register riscv_intr_register_fdt + +#endif /* __RISCV_FDT_H__ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/fenv.h b/lib/libc/include/riscv64-openbsd-none/riscv64/fenv.h new file mode 100644 index 000000000000..e1645e961c93 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/fenv.h @@ -0,0 +1,95 @@ +/* $OpenBSD: fenv.h,v 1.2 2021/05/12 02:28:25 jsg Exp $ */ + +/* + * Copyright (c) 2011 Martynas Venckus + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_FENV_H_ +#define _MACHINE_FENV_H_ + +/* + * Each symbol representing a floating point exception expands to an integer + * constant expression with values, such that bitwise-inclusive ORs of _all + * combinations_ of the constants result in distinct values. + * + * We use such values that allow direct bitwise operations on FPU registers. + */ +#define FE_INVALID 0x10 +#define FE_DIVBYZERO 0x08 +#define FE_OVERFLOW 0x04 +#define FE_UNDERFLOW 0x02 +#define FE_INEXACT 0x01 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * exception constants defined above. + */ +#define FE_ALL_EXCEPT (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | \ + FE_UNDERFLOW | FE_INEXACT ) + +/* + * Each symbol representing the rounding direction, expands to an integer + * constant expression whose value is distinct non-negative value. + * + * We use such values that allow direct bitwise operations on FPU registers. + */ +#define FE_TONEAREST 0x0 +#define FE_TOWARDZERO 0x1 +#define FE_DOWNWARD 0x2 +#define FE_UPWARD 0x3 +#define FE_TONEARESTFROMZERO 0x4 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * rounding direction constants defined above. + */ +#define _ROUND_MASK (FE_TONEAREST | FE_TOWARDZERO | FE_DOWNWARD | \ + FE_UPWARD | FE_TONEARESTFROMZERO) +#define _ROUND_SHIFT 5 + +/* + * fenv_t represents the entire floating-point environment. + */ +typedef unsigned int fenv_t; + +/* + * The following constant represents the default floating-point environment + * (that is, the one installed at program startup) and has type pointer to + * const-qualified fenv_t. + * + * It can be used as an argument to the functions within the header + * that manage the floating-point environment, namely fesetenv() and + * feupdateenv(). + */ +__BEGIN_DECLS +extern fenv_t __fe_dfl_env; +__END_DECLS +#define FE_DFL_ENV ((const fenv_t *)&__fe_dfl_env) + +/* + * fexcept_t represents the floating-point status flags collectively, including + * any status the implementation associates with the flags. + * + * A floating-point status flag is a system variable whose value is set (but + * never cleared) when a floating-point exception is raised, which occurs as a + * side effect of exceptional floating-point arithmetic to provide auxiliary + * information. + * + * A floating-point control mode is a system variable whose value may be set by + * the user to affect the subsequent behavior of floating-point arithmetic. + */ +typedef unsigned int fexcept_t; + +#endif /* !_MACHINE_FENV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/frame.h b/lib/libc/include/riscv64-openbsd-none/riscv64/frame.h new file mode 100644 index 000000000000..e15698128f54 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/frame.h @@ -0,0 +1,99 @@ +/* $OpenBSD: frame.h,v 1.3 2022/02/24 14:19:10 visa Exp $ */ + +/* + * Copyright (c) 2019 Brian Bamsch + * Copyright (c) 2016 Dale Rahn + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 _MACHINE_FRAME_H_ +#define _MACHINE_FRAME_H_ + +#ifndef _LOCORE + +#include + +/* + * Exception/Trap Stack Frame + */ +#define clockframe trapframe +typedef struct trapframe { + /* Standard Registers */ + register_t tf_ra; + register_t tf_sp; + register_t tf_gp; + register_t tf_tp; + register_t tf_t[7]; + register_t tf_s[12]; + register_t tf_a[8]; + /* Supervisor Trap CSRs */ + register_t tf_sepc; + register_t tf_sstatus; + register_t tf_stval; + register_t tf_scause; + register_t tf_pad; +} trapframe_t; + +/* + * pushed on stack for signal delivery + */ +struct sigframe { + int sf_signum; + struct sigcontext sf_sc; + siginfo_t sf_si; +}; + +/* + * System stack frames. + */ + +/* + * Stack frame inside cpu_switch() + */ +struct switchframe { + register_t sf_s[12]; + register_t sf_ra; + register_t sf_pad; +}; + +struct callframe { + struct callframe *f_frame; + register_t f_ra; +}; + +#endif /* !_LOCORE */ + +#endif /* !_MACHINE_FRAME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/ieee.h b/lib/libc/include/riscv64-openbsd-none/riscv64/ieee.h new file mode 100644 index 000000000000..74d6e987a900 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/ieee.h @@ -0,0 +1,148 @@ +/* $OpenBSD: ieee.h,v 1.3 2021/05/12 01:20:52 jsg Exp $ */ +/* $NetBSD: ieee.h,v 1.1 1996/09/30 16:34:25 ws Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ieee.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * ieee.h defines the machine-dependent layout of the machine's IEEE + * floating point. It does *not* define (yet?) any of the rounding + * mode bits, exceptions, and so forth. + */ + +/* + * Define the number of bits in each fraction and exponent. + * + * k k+1 + * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented + * + * (-exp_bias+1) + * as fractions that look like 0.fffff x 2 . This means that + * + * -126 + * the number 0.10000 x 2 , for instance, is the same as the normalized + * + * -127 -128 + * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero + * + * -129 + * in the fraction; to represent 2 , we need two, and so on. This + * + * (-exp_bias-fracbits+1) + * implies that the smallest denormalized number is 2 + * + * for whichever format we are talking about: for single precision, for + * + * -126 -149 + * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and + * + * -149 == -127 - 23 + 1. + */ +#define SNG_EXPBITS 8 +#define SNG_FRACBITS 23 + +#define DBL_EXPBITS 11 +#define DBL_FRACHBITS 20 +#define DBL_FRACLBITS 32 +#define DBL_FRACBITS 52 + +#define EXT_EXPBITS 15 +#define EXT_FRACHBITS 16 +#define EXT_FRACHMBITS 32 +#define EXT_FRACLMBITS 32 +#define EXT_FRACLBITS 32 +#define EXT_FRACBITS 112 + +#define EXT_IMPLICIT_NBIT + +#define EXT_TO_ARRAY32(p, a) do { \ + (a)[0] = (uint32_t)(p)->ext_fracl; \ + (a)[1] = (uint32_t)(p)->ext_fraclm; \ + (a)[2] = (uint32_t)(p)->ext_frachm; \ + (a)[3] = (uint32_t)(p)->ext_frach; \ +} while (0) + +struct ieee_single { + u_int sng_frac:23; + u_int sng_exp:8; + u_int sng_sign:1; +}; + +struct ieee_double { + u_int dbl_fracl; + u_int dbl_frach:20; + u_int dbl_exp:11; + u_int dbl_sign:1; +}; + +struct ieee_ext { + u_int ext_fracl; + u_int ext_fraclm; + u_int ext_frachm; + u_int ext_frach:16; + u_int ext_exp:15; + u_int ext_sign:1; +}; + +/* + * Floats whose exponent is in [1..INFNAN) (of whatever type) are + * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. + * Floats whose exponent is zero are either zero (iff all fraction + * bits are zero) or subnormal values. + * + * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its + * high fraction; if the bit is set, it is a `quiet NaN'. + */ +#define SNG_EXP_INFNAN 255 +#define DBL_EXP_INFNAN 2047 +#define EXT_EXP_INFNAN 32767 + +#if 0 +#define SNG_QUIETNAN (1 << 22) +#define DBL_QUIETNAN (1 << 19) +#define EXT_QUIETNAN (1 << 15) +#endif + +/* + * Exponent biases. + */ +#define SNG_EXP_BIAS 127 +#define DBL_EXP_BIAS 1023 +#define EXT_EXP_BIAS 16383 \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/ieeefp.h b/lib/libc/include/riscv64-openbsd-none/riscv64/ieeefp.h new file mode 100644 index 000000000000..e8f7507588d0 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/ieeefp.h @@ -0,0 +1,25 @@ +/* $OpenBSD: ieeefp.h,v 1.3 2021/04/30 00:25:52 drahn Exp $ */ + +/* + * Based on ieeefp.h written by J.T. Conklin, Apr 28, 1995 + * Public domain. + */ + +#ifndef _MACHINE_IEEEFP_H_ +#define _MACHINE_IEEEFP_H_ + +typedef int fp_except; +#define FP_X_INV 0x10 /* invalid operation exception */ +#define FP_X_DZ 0x08 /* divide-by-zero exception */ +#define FP_X_OFL 0x04 /* overflow exception */ +#define FP_X_UFL 0x02 /* underflow exception */ +#define FP_X_IMP 0x01 /* imprecise (loss of precision) */ + +typedef enum { + FP_RN=0, /* round to nearest representable number */ + FP_RZ=1, /* round to zero (truncate) */ + FP_RM=2, /* round toward negative infinity */ + FP_RP=3 /* round toward positive infinity */ +} fp_rnd; + +#endif /* _MACHINE_IEEEFP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/intr.h b/lib/libc/include/riscv64-openbsd-none/riscv64/intr.h new file mode 100644 index 000000000000..14ef73c2133d --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/intr.h @@ -0,0 +1,227 @@ +/* $OpenBSD: intr.h,v 1.10 2025/05/19 02:13:15 jsg Exp $ */ + +/* + * Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _MACHINE_INTR_H_ +#define _MACHINE_INTR_H_ + +/* + * The interrupt level ipl is a logical level; per-platform interrupt + * code will turn it into the appropriate hardware interrupt masks + * values. + * + * Interrupt sources on the CPU are kept enabled regardless of the + * current ipl value; individual hardware sources interrupting while + * logically masked are masked on the fly, remembered as pending, and + * unmasked at the first splx() opportunity. + */ +#ifdef _KERNEL + +/* Interrupt priority `levels'; not mutually exclusive. */ +#define IPL_NONE 0 /* nothing */ +#define IPL_SOFTCLOCK 2 /* soft clock interrupts */ +#define IPL_SOFTNET 3 /* soft network interrupts */ +#define IPL_SOFTTTY 4 /* soft terminal interrupts */ +#define IPL_BIO 5 /* block I/O */ +#define IPL_NET 6 /* network */ +#define IPL_TTY 7 /* terminal */ +#define IPL_VM 8 /* memory allocation */ +#define IPL_AUDIO 9 /* audio */ +#define IPL_CLOCK 10 /* clock */ +#define IPL_SCHED IPL_CLOCK +#define IPL_STATCLOCK IPL_CLOCK +#define IPL_HIGH 11 /* everything */ +#define IPL_IPI 12 /* interprocessor interrupt */ +#define NIPL 13 /* number of levels */ + +#define IPL_MPFLOOR IPL_TTY +/* Interrupt priority 'flags'. */ +#define IPL_IRQMASK 0xf /* priority only */ +#define IPL_FLAGMASK 0xf00 /* flags only*/ +#define IPL_MPSAFE 0x100 /* 'mpsafe' interrupt, no kernel lock */ + +/* Interrupt sharing types. */ +#define IST_NONE 0 /* none */ +#define IST_PULSE 1 /* pulsed */ +#define IST_EDGE 2 /* edge-triggered */ +#define IST_LEVEL 3 /* level-triggered */ + +#define IST_LEVEL_LOW IST_LEVEL +#define IST_LEVEL_HIGH 4 +#define IST_EDGE_FALLING IST_EDGE +#define IST_EDGE_RISING 5 +#define IST_EDGE_BOTH 6 + +enum { + IRQ_SOFTWARE_USER, + IRQ_SOFTWARE_SUPERVISOR, + IRQ_SOFTWARE_HYPERVISOR, + IRQ_SOFTWARE_MACHINE, + IRQ_TIMER_USER, + IRQ_TIMER_SUPERVISOR, + IRQ_TIMER_HYPERVISOR, + IRQ_TIMER_MACHINE, + IRQ_EXTERNAL_USER, + IRQ_EXTERNAL_SUPERVISOR, + IRQ_EXTERNAL_HYPERVISOR, + IRQ_EXTERNAL_MACHINE, + INTC_NIRQS +}; + +#define __USE_MI_SOFTINTR + +#include + +#ifndef _LOCORE +#include + +void softintr(int); + +int splraise(int); +int spllower(int); +void splx(int); + +void riscv_cpu_intr(void *); +void riscv_do_pending_intr(int); +void riscv_set_intr_func(int (*raise)(int), int (*lower)(int), + void (*x)(int), void (*setipl)(int)); +void riscv_set_intr_handler(void (*intr_handle)(void *)); + +struct machine_intr_handle { + struct interrupt_controller *ih_ic; + void *ih_ih; +}; + +struct riscv_intr_func { + int (*raise)(int); + int (*lower)(int); + void (*x)(int); + void (*setipl)(int); +}; + +extern struct riscv_intr_func riscv_intr_func; + +#define splraise(cpl) (riscv_intr_func.raise(cpl)) +#define _splraise(cpl) (riscv_intr_func.raise(cpl)) +#define spllower(cpl) (riscv_intr_func.lower(cpl)) +#define splx(cpl) (riscv_intr_func.x(cpl)) + +#define splsoftclock() splraise(IPL_SOFTCLOCK) +#define splsoftnet() splraise(IPL_SOFTNET) +#define splsofttty() splraise(IPL_SOFTTTY) +#define splbio() splraise(IPL_BIO) +#define splnet() splraise(IPL_NET) +#define spltty() splraise(IPL_TTY) +#define splvm() splraise(IPL_VM) +#define splaudio() splraise(IPL_AUDIO) +#define splclock() splraise(IPL_CLOCK) +#define splsched() splraise(IPL_SCHED) +#define splstatclock() splraise(IPL_STATCLOCK) +#define splhigh() splraise(IPL_HIGH) + +#define spl0() spllower(IPL_NONE) + +void intr_barrier(void *); + +void riscv_init_smask(void); /* XXX */ +extern uint32_t riscv_smask[NIPL]; + +void riscv_clock_register(void (*)(void), void (*)(u_int), void (*)(int), + void (*)(void)); + +/* + **** interrupt controller structure and routines **** + */ +struct cpu_info; +struct interrupt_controller { + int ic_node; + void *ic_cookie; + void *(*ic_establish)(void *, int *, int, struct cpu_info *, + int (*)(void *), void *, char *); + void *(*ic_establish_msi)(void *, uint64_t *, uint64_t *, int, + struct cpu_info *, int (*)(void *), void *, char *); + void (*ic_disestablish)(void *); + void (*ic_enable)(void *); + void (*ic_disable)(void *); + void (*ic_route)(void *, int, struct cpu_info *); + void (*ic_cpu_enable)(void); + void (*ic_barrier)(void *); + + LIST_ENTRY(interrupt_controller) ic_list; + uint32_t ic_phandle; + uint32_t ic_cells; +}; + +void riscv_intr_init_fdt(void); +void riscv_intr_register_fdt(struct interrupt_controller *); +void *riscv_intr_establish_fdt(int, int, int (*)(void *), + void *, char *); +void *riscv_intr_establish_fdt_idx(int, int, int, int (*)(void *), + void *, char *); +void *riscv_intr_establish_fdt_idx_cpu(int, int, int, struct cpu_info *, + int (*)(void *), void *, char *); +void *riscv_intr_establish_fdt_imap_cpu(int, int *, int, int, + struct cpu_info *, int (*)(void *), void *, char *); +void *riscv_intr_establish_fdt_msi(int, uint64_t *, uint64_t *, int, + int (*)(void *), void *, char *); +void *riscv_intr_establish_fdt_msi_cpu(int, uint64_t *, uint64_t *, int, + struct cpu_info *, int (*)(void *), void *, char *); +void riscv_intr_disestablish_fdt(void *); +void riscv_intr_enable(void *); +void riscv_intr_disable(void *); +void riscv_intr_route(void *, int, struct cpu_info *); +void riscv_intr_cpu_enable(void); + +#define IPI_NOP 0 +#define IPI_DDB (1 << 0) + +void intr_send_ipi(struct cpu_info *, int); + +#ifdef DIAGNOSTIC +/* + * Although this function is implemented in MI code, it must be in this MD + * header because we don't want this header to include MI includes. + */ +void splassert_fail(int, int, const char *); +extern int splassert_ctl; +void riscv_splassert_check(int, const char *); +#define splassert(__wantipl) do { \ + if (splassert_ctl > 0) { \ + riscv_splassert_check(__wantipl, __func__); \ + } \ +} while (0) +#define splsoftassert(wantipl) splassert(wantipl) +#else +#define splassert(wantipl) do { /* nothing */ } while (0) +#define splsoftassert(wantipl) do { /* nothing */ } while (0) +#endif + +#endif /* ! _LOCORE */ + +#endif /* _KERNEL */ + +#endif /* _MACHINE_INTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/kcore.h b/lib/libc/include/riscv64-openbsd-none/riscv64/kcore.h new file mode 100644 index 000000000000..484ee5d0ee8c --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/kcore.h @@ -0,0 +1,16 @@ +/* $OpenBSD: kcore.h,v 1.2 2021/05/12 01:20:52 jsg Exp $ */ + +/* public domain */ + +/* Make sure this is larger than DRAM_BLOCKS on all arm-based platforms */ +#define NPHYS_RAM_SEGS 8 + +typedef struct cpu_kcore_hdr { + u_int64_t kernelbase; /* value of KERNEL_BASE */ + u_int64_t kerneloffs; /* offset of kernel in RAM */ + u_int64_t staticsize; /* size of contiguous mapping */ + u_int64_t pmap_kernel_l1; /* pmap_kernel()->pm_l1 */ + u_int64_t pmap_kernel_l2; /* pmap_kernel()->pm_l2 */ + u_int64_t reserved[11]; + phys_ram_seg_t ram_segs[NPHYS_RAM_SEGS]; +} cpu_kcore_hdr_t; \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/limits.h b/lib/libc/include/riscv64-openbsd-none/riscv64/limits.h new file mode 100644 index 000000000000..e06dde0b2bb9 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/limits.h @@ -0,0 +1,56 @@ +/* $OpenBSD: limits.h,v 1.2 2021/06/25 19:22:51 matthieu Exp $ */ +/* $NetBSD: limits.h,v 1.4 2003/04/28 23:16:18 bjh21 Exp $ */ + +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)limits.h 7.2 (Berkeley) 6/28/90 + */ + +#ifndef _MACHINE_LIMITS_H_ +#define _MACHINE_LIMITS_H_ + +#include + +#if __POSIX_VISIBLE || __XPG_VISIBLE +#ifndef SIZE_MAX +#define SIZE_MAX ULONG_MAX /* max value for a size_t */ +#endif +#define SSIZE_MAX LONG_MAX /* max value for a ssize_t */ +#endif + +#if __BSD_VISIBLE +#define SIZE_T_MAX ULONG_MAX /* max value for a size_t (historic) */ + +#define UQUAD_MAX (ULONG_MAX) /* max unsigned quad */ +#define QUAD_MAX (LONG_MAX) /* max signed quad */ +#define QUAD_MIN (LONG_MIN) /* min signed quad */ + +#endif /* __BSD_VISIBLE */ + +#endif /* _MACHINE_LIMITS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/loadfile_machdep.h b/lib/libc/include/riscv64-openbsd-none/riscv64/loadfile_machdep.h new file mode 100644 index 000000000000..c6b1f00082b4 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/loadfile_machdep.h @@ -0,0 +1,53 @@ +/* $OpenBSD: loadfile_machdep.h,v 1.2 2021/04/23 15:31:12 drahn Exp $ */ +/* $NetBSD: loadfile_machdep.h,v 1.1 1999/04/29 03:17:12 tsubai Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define BOOT_ELF +#define ELFSIZE 64 + +#define LOAD_KERNEL (LOAD_ALL & ~LOAD_TEXTA) +#define COUNT_KERNEL (COUNT_ALL & ~COUNT_TEXTA) + +extern u_long efi_loadaddr; +#define LOADADDR(a) (((((u_long)(a)) + offset)&0x3fffffffff) + \ + efi_loadaddr) +#define ALIGNENTRY(a) ((u_long)(a)) +#define READ(f, b, c) read((f), (void *)LOADADDR(b), (c)) +#define BCOPY(s, d, c) memcpy((void *)LOADADDR(d), (void *)(s), (c)) +#define BZERO(d, c) memset((void *)LOADADDR(d), 0, (c)) +#define WARN(a) (void)(printf a, \ + printf((errno ? ": %s\n" : "\n"), \ + strerror(errno))) +#define PROGRESS(a) (void) printf a +#define ALLOC(a) alloc(a) +#define FREE(a, b) free(a, b) + +void run_loadfile(uint64_t *, int); \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/mplock.h b/lib/libc/include/riscv64-openbsd-none/riscv64/mplock.h new file mode 100644 index 000000000000..1a87e05398a4 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/mplock.h @@ -0,0 +1,10 @@ +/* $OpenBSD: mplock.h,v 1.1 2021/06/27 20:36:57 kettenis Exp $ */ + +/* public domain */ + +#ifndef _MACHINE_MPLOCK_H_ +#define _MACHINE_MPLOCK_H_ + +#define __USE_MI_MPLOCK + +#endif /* !_MACHINE_MPLOCK_H */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/mutex.h b/lib/libc/include/riscv64-openbsd-none/riscv64/mutex.h new file mode 100644 index 000000000000..bc6b8cbb83bd --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/mutex.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mutex.h,v 1.1 2021/04/23 02:42:16 drahn Exp $ */ + +#define __USE_MI_MUTEX \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/openpromio.h b/lib/libc/include/riscv64-openbsd-none/riscv64/openpromio.h new file mode 100644 index 000000000000..4f49bf5934c9 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/openpromio.h @@ -0,0 +1,57 @@ +/* $OpenBSD: openpromio.h,v 1.1 2021/04/23 12:01:03 jsg Exp $ */ +/* $NetBSD: openpromio.h,v 1.1.1.1 1998/06/20 04:58:52 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)openpromio.h 8.1 (Berkeley) 6/11/93 + */ + +struct opiocdesc { + int op_nodeid; /* passed or returned node id */ + int op_namelen; /* length of op_name */ + char *op_name; /* pointer to field name */ + int op_buflen; /* length of op_buf (value-result) */ + char *op_buf; /* pointer to field value */ +}; + +#define OPIOCGET _IOWR('O', 1, struct opiocdesc) /* get openprom field */ +#define OPIOCSET _IOW('O', 2, struct opiocdesc) /* set openprom field */ +#define OPIOCNEXTPROP _IOWR('O', 3, struct opiocdesc) /* get next property */ +#define OPIOCGETOPTNODE _IOR('O', 4, int) /* get openprom field */ +#define OPIOCGETNEXT _IOWR('O', 5, int) /* get next node of node */ +#define OPIOCGETCHILD _IOWR('O', 6, int) /* get first child of node */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/param.h b/lib/libc/include/riscv64-openbsd-none/riscv64/param.h new file mode 100644 index 000000000000..1260fa3a3c52 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/param.h @@ -0,0 +1,78 @@ +/* $OpenBSD: param.h,v 1.7 2025/07/07 18:33:37 kettenis Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ + +#ifdef _KERNEL +#ifndef _LOCORE +#include +#endif +#endif + +#define _MACHINE riscv64 +#define MACHINE "riscv64" +#define _MACHINE_ARCH riscv64 +#define MACHINE_ARCH "riscv64" +#define MID_MACHINE MID_RISCV64 + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define PAGE_MASK (PAGE_SIZE - 1) + +#ifdef _KERNEL + +#define NBPG PAGE_SIZE /* bytes/page */ +#define PGSHIFT PAGE_SHIFT /* LOG2(PAGE_SIZE) */ +#define PGOFSET PAGE_MASK /* byte offset into page */ + +#define UPAGES 6 /* pages of u-area */ +#define USPACE (UPAGES * PAGE_SIZE) /* total size of u-area */ +#define USPACE_ALIGN 0 /* u-area alignment 0-none */ +#define __HAVE_USPACE_GUARD + +#define NMBCLUSTERS (64 * 1024) /* max cluster allocation */ + +#ifndef MSGBUFSIZE +#define MSGBUFSIZE (16 * PAGE_SIZE) /* default message buffer size */ +#endif + +#define STACKALIGNBYTES (16 - 1) +#define STACKALIGN(p) ((u_long)(p) &~ STACKALIGNBYTES) + +#define __HAVE_FDT + +#endif /* _KERNEL */ + +#endif /* _MACHINE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/pcb.h b/lib/libc/include/riscv64-openbsd-none/riscv64/pcb.h new file mode 100644 index 000000000000..a1b6cb9e4740 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/pcb.h @@ -0,0 +1,41 @@ +/* $OpenBSD: pcb.h,v 1.4 2024/10/15 09:16:39 jsg Exp $ */ + +/* + * Copyright (c) 2016 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef _MACHINE_PCB_H_ +#define _MACHINE_PCB_H_ + +#include +#include + +struct trapframe; + +/* + * Warning certain fields must be within 256 bytes of the beginning + * of this structure. + */ +struct pcb { + u_int pcb_flags; +#define PCB_FPU 0x00000001 /* Process had FPU initialized */ +#define PCB_SINGLESTEP 0x00000002 /* Single step process */ + struct trapframe *pcb_tf; + + register_t pcb_sp; // stack pointer of switchframe + + caddr_t pcb_onfault; // On fault handler + struct fpreg pcb_fpstate; // Floating Point state */ +}; +#endif /* _MACHINE_PCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/pci_machdep.h b/lib/libc/include/riscv64-openbsd-none/riscv64/pci_machdep.h new file mode 100644 index 000000000000..4737ab100a6a --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/pci_machdep.h @@ -0,0 +1,140 @@ +/* $OpenBSD: pci_machdep.h,v 1.5 2024/05/22 05:51:49 jsg Exp $ */ + +/* + * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +typedef struct machine_pci_chipset *pci_chipset_tag_t; +typedef uint64_t pcitag_t; + +#define PCITAG_NODE(x) ((x) >> 32) +#define PCITAG_OFFSET(x) ((x) & 0xffffffff) + +/* Supported interrupt types. */ +#define PCI_NONE 0 +#define PCI_INTX 1 +#define PCI_MSI 2 +#define PCI_MSIX 3 + +typedef struct { + pci_chipset_tag_t ih_pc; + pcitag_t ih_tag; + int ih_intrpin; + int ih_type; + bus_dma_tag_t ih_dmat; +} pci_intr_handle_t; + +struct pci_attach_args; + +/* + * Machine-specific PCI structure and type definitions. + * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE. + */ +struct machine_pci_chipset { + void *pc_conf_v; + void (*pc_attach_hook)(struct device *, + struct device *, struct pcibus_attach_args *); + int (*pc_bus_maxdevs)(void *, int); + pcitag_t (*pc_make_tag)(void *, int, int, int); + void (*pc_decompose_tag)(void *, pcitag_t, int *, + int *, int *); + int (*pc_conf_size)(void *, pcitag_t); + pcireg_t (*pc_conf_read)(void *, pcitag_t, int); + void (*pc_conf_write)(void *, pcitag_t, int, pcireg_t); + int (*pc_probe_device_hook)(void *, struct pci_attach_args *); + + void *pc_intr_v; + int (*pc_intr_map)(struct pci_attach_args *, + pci_intr_handle_t *); + int (*pc_intr_map_msi)(struct pci_attach_args *, + pci_intr_handle_t *); + int (*pc_intr_map_msivec)(struct pci_attach_args *, + int, pci_intr_handle_t *); + int (*pc_intr_map_msix)(struct pci_attach_args *, + int, pci_intr_handle_t *); + const char *(*pc_intr_string)(void *, pci_intr_handle_t); + void *(*pc_intr_establish)(void *, pci_intr_handle_t, + int, struct cpu_info *, int (*)(void *), void *, + char *); + void (*pc_intr_disestablish)(void *, void *); +}; + +/* + * Functions provided to machine-independent PCI code. + */ +#define pci_attach_hook(p, s, pba) \ + (*(pba)->pba_pc->pc_attach_hook)((p), (s), (pba)) +#define pci_bus_maxdevs(c, b) \ + (*(c)->pc_bus_maxdevs)((c)->pc_conf_v, (b)) +#define pci_make_tag(c, b, d, f) \ + (*(c)->pc_make_tag)((c)->pc_conf_v, (b), (d), (f)) +#define pci_decompose_tag(c, t, bp, dp, fp) \ + (*(c)->pc_decompose_tag)((c)->pc_conf_v, (t), (bp), (dp), (fp)) +#define pci_conf_size(c, t) \ + (*(c)->pc_conf_size)((c)->pc_conf_v, (t)) +#define pci_conf_read(c, t, r) \ + (*(c)->pc_conf_read)((c)->pc_conf_v, (t), (r)) +#define pci_conf_write(c, t, r, v) \ + (*(c)->pc_conf_write)((c)->pc_conf_v, (t), (r), (v)) +#define pci_probe_device_hook(c, a) \ + (*(c)->pc_probe_device_hook)((c)->pc_conf_v, (a)) +#define pci_intr_map(c, ihp) \ + (*(c)->pa_pc->pc_intr_map)((c), (ihp)) +#define pci_intr_map_msi(c, ihp) \ + (*(c)->pa_pc->pc_intr_map_msi)((c), (ihp)) +#define pci_intr_map_msix(c, vec, ihp) \ + (*(c)->pa_pc->pc_intr_map_msix)((c), (vec), (ihp)) +#define pci_intr_string(c, ih) \ + (*(c)->pc_intr_string)((c)->pc_intr_v, (ih)) +#define pci_intr_establish(c, ih, l, h, a, nm) \ + (*(c)->pc_intr_establish)((c)->pc_intr_v, (ih), (l), NULL, (h), (a),\ + (nm)) +#define pci_intr_establish_cpu(c, ih, l, ci, h, a, nm) \ + (*(c)->pc_intr_establish)((c)->pc_intr_v, (ih), (l), (ci), (h), (a),\ + (nm)) +#define pci_intr_disestablish(c, iv) \ + (*(c)->pc_intr_disestablish)((c)->pc_intr_v, (iv)) + +#define pci_min_powerstate(c, t) (PCI_PMCSR_STATE_D3) +#define pci_set_powerstate_md(c, t, s, p) + +#define pci_dev_postattach(a, b) + +void pci_mcfg_init(bus_space_tag_t, bus_addr_t, int, int, int); + +void pci_msi_enable(pci_chipset_tag_t, pcitag_t, bus_addr_t, uint32_t); +void pci_msix_enable(pci_chipset_tag_t, pcitag_t, bus_space_tag_t, + int, bus_addr_t, uint32_t); +int _pci_intr_map_msi(struct pci_attach_args *, pci_intr_handle_t *); +int _pci_intr_map_msivec(struct pci_attach_args *, int, + pci_intr_handle_t *); +int _pci_intr_map_msix(struct pci_attach_args *, int, pci_intr_handle_t *); + +#define __HAVE_PCI_MSIX + +int pci_msix_table_map(pci_chipset_tag_t, pcitag_t, + bus_space_tag_t, bus_space_handle_t *); +void pci_msix_table_unmap(pci_chipset_tag_t, pcitag_t, + bus_space_tag_t, bus_space_handle_t); \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/pmap.h b/lib/libc/include/riscv64-openbsd-none/riscv64/pmap.h new file mode 100644 index 000000000000..d6e867d90f34 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/pmap.h @@ -0,0 +1,132 @@ +/* $OpenBSD: pmap.h,v 1.14 2025/02/03 17:59:40 jca Exp $ */ + +/* + * Copyright (c) 2019-2020 Brian Bamsch + * Copyright (c) 2008,2009,2014 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef _MACHINE_PMAP_H_ +#define _MACHINE_PMAP_H_ + +#ifndef _LOCORE +#include +#include +#include +#endif + + +/* V->P mapping data */ +// XXX Only targeting compatibility with SV39 +#define VP_IDX0_CNT 512 +#define VP_IDX0_MASK (VP_IDX0_CNT-1) +#define VP_IDX0_POS 39 +#define VP_IDX1_CNT 512 +#define VP_IDX1_MASK (VP_IDX1_CNT-1) +#define VP_IDX1_POS 30 +#define VP_IDX2_CNT 512 +#define VP_IDX2_MASK (VP_IDX2_CNT-1) +#define VP_IDX2_POS 21 +#define VP_IDX3_CNT 512 +#define VP_IDX3_MASK (VP_IDX3_CNT-1) +#define VP_IDX3_POS 12 + +/* cache flags */ +// XXX These are duplicated from arm64 and may need some reworking +#define PMAP_CACHE_CI (PMAP_MD0) /* cache inhibit */ +#define PMAP_CACHE_WB (PMAP_MD1) /* writeback */ +#define PMAP_CACHE_DEV (PMAP_MD2) /* device mapping */ +#define PMAP_CACHE_BITS (PMAP_MD0|PMAP_MD1|PMAP_MD2) + +#define PTED_VA_MANAGED_M (PMAP_MD3) +#define PTED_VA_WIRED_M (PMAP_MD3 << 1) + +#if defined(_KERNEL) && !defined(_LOCORE) +/* + * Pmap stuff + */ + +typedef struct pmap *pmap_t; + +struct pmap { + struct mutex pm_mtx; + union { + // XXX Sv48 not yet supported + // XXX Consider inverting Lx + struct pmapvp1 *l1; /* virtual to physical table 3 lvl */ + } pm_vp; + uint64_t pm_satp; + int pm_privileged; + int pm_refs; /* ref count */ + struct pmap_statistics pm_stats; /* pmap statistics */ +}; + +#define PMAP_PA_MASK ~((paddr_t)PAGE_MASK) /* to remove the flags */ +#define PMAP_NOCACHE 0x1 /* non-cacheable memory */ +#define PMAP_DEVICE 0x2 /* device memory */ + +#define PG_PMAP_MOD PG_PMAP0 +#define PG_PMAP_REF PG_PMAP1 +#define PG_PMAP_EXE PG_PMAP2 + +// [NCPUS] +extern paddr_t zero_page; +extern paddr_t copy_src_page; +extern paddr_t copy_dst_page; + +void pagezero(vaddr_t); + +extern struct pmap kernel_pmap_; +#define pmap_kernel() (&kernel_pmap_) +#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) +#define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count) + +vaddr_t pmap_bootstrap(long kvo, paddr_t lpt1, + vaddr_t kernelstart, vaddr_t kernelend, + paddr_t memstart, paddr_t memend); +void pmap_kenter_cache(vaddr_t va, paddr_t pa, vm_prot_t prot, int cacheable); +void pmap_page_ro(pmap_t pm, vaddr_t va, vm_prot_t prot); + +paddr_t pmap_steal_avail(size_t size, int align, void **kva); +void pmap_avail_fixup(void); +void pmap_physload_avail(void); + +#define PMAP_GROWKERNEL + +#define PHYS_TO_DMAP(pa) ((pa) - dmap_phys_base + DMAP_MIN_ADDRESS) + +struct pv_entry; + +/* investigate */ +#define pmap_unuse_final(p) do { /* nothing */ } while (0) +int pmap_fault_fixup(pmap_t, vaddr_t, vm_prot_t); +void pmap_postinit(void); +void pmap_init_percpu(void); + +#define __HAVE_PMAP_POPULATE + +#endif /* _KERNEL && !_LOCORE */ + +#ifndef _LOCORE +struct vm_page_md { + struct mutex pv_mtx; + LIST_HEAD(,pte_desc) pv_list; +}; + +#define VM_MDPAGE_INIT(pg) do { \ + mtx_init(&(pg)->mdpage.pv_mtx, IPL_VM); \ + LIST_INIT(&((pg)->mdpage.pv_list)); \ +} while (0) +#endif /* _LOCORE */ + +#endif /* _MACHINE_PMAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/proc.h b/lib/libc/include/riscv64-openbsd-none/riscv64/proc.h new file mode 100644 index 000000000000..e1a7bf3652d7 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/proc.h @@ -0,0 +1,45 @@ +/* $OpenBSD: proc.h,v 1.2 2021/05/12 01:20:52 jsg Exp $ */ +/* $NetBSD: proc.h,v 1.1 2003/04/26 18:39:46 fvdl Exp $ */ + +/* + * Copyright (c) 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)proc.h 7.1 (Berkeley) 5/15/91 + */ + +#ifndef _MACHINE_PROC_H_ +#define _MACHINE_PROC_H_ + +/* + * Machine-dependent part of the proc structure for riscv64. + */ +struct mdproc { + volatile int md_astpending; +}; + +#endif /* _MACHINE_PROC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/profile.h b/lib/libc/include/riscv64-openbsd-none/riscv64/profile.h new file mode 100644 index 000000000000..3074be08fc7b --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/profile.h @@ -0,0 +1,92 @@ +/* $OpenBSD: profile.h,v 1.4 2021/05/21 16:49:57 deraadt Exp $ */ + +/* + * Copyright (c) 2015 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define _MCOUNT_DECL void _mcount + +#define MCOUNT_ASM_NAME "__mcount" + +#ifdef __PIC__ +#define PLTSYM "" /* XXX -aarch64 defaults to PLT? */ +#else +#define PLTSYM "" +#endif + +#define MCOUNT \ +__asm__ (".text \n;" \ + ".align 3 \n;" \ + ".globl " MCOUNT_ASM_NAME " \n;" \ + ".type " MCOUNT_ASM_NAME ",@function \n;" \ + MCOUNT_ASM_NAME ": \n;" \ + " addi sp, sp, -176 \n" \ + " sd fp, 0(sp) \n" \ + " sd ra, 8(sp) \n" \ + " sd s1, 24(sp) \n" \ + " sd a0, 32(sp) \n" \ + " sd a1, 40(sp) \n" \ + " sd a2, 48(sp) \n" \ + " sd a3, 56(sp) \n" \ + " sd a4, 64(sp) \n" \ + " sd a5, 72(sp) \n" \ + " sd a6, 80(sp) \n" \ + " sd a7, 88(sp) \n" \ + " sd s2, 96(sp) \n" \ + " sd s3, 104(sp) \n" \ + " sd s4, 112(sp) \n" \ + " sd s5, 120(sp) \n" \ + " sd s6, 128(sp) \n" \ + " sd s7, 136(sp) \n" \ + " sd s8, 144(sp) \n" \ + " sd s9, 152(sp) \n" \ + " sd s10, 160(sp) \n" \ + " sd s11, 168(sp) \n" \ + " ld a0, 8(fp) \n" \ + " mv a1, x1 \n" \ + " call " __STRING(_mcount) PLTSYM " \n" \ + /* restore argument registers */ \ + " ld fp, 0(sp) \n" \ + " ld ra, 8(sp) \n" \ + " ld s1, 24(sp) \n" \ + " ld a0, 32(sp) \n" \ + " ld a1, 40(sp) \n" \ + " ld a2, 48(sp) \n" \ + " ld a3, 56(sp) \n" \ + " ld a4, 64(sp) \n" \ + " ld a5, 72(sp) \n" \ + " ld a6, 80(sp) \n" \ + " ld a7, 88(sp) \n" \ + " ld s2, 96(sp) \n" \ + " ld s3, 104(sp) \n" \ + " ld s4, 112(sp) \n" \ + " ld s5, 120(sp) \n" \ + " ld s6, 128(sp) \n" \ + " ld s7, 136(sp) \n" \ + " ld s8, 144(sp) \n" \ + " ld s9, 152(sp) \n" \ + " ld s10, 160(sp) \n" \ + " ld s11, 168(sp) \n" \ + " addi sp, sp, 176 \n" \ + " jr ra \n"); + +#ifdef _KERNEL +// Change this to dair read/set, then restore. +#define MCOUNT_ENTER \ +__asm__ ("mrs %x0,daif; msr daifset, #0x2": "=r"(s)); +#define MCOUNT_EXIT \ +__asm__ ("msr daif, %x0":: "r"(s)); + +#endif \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/pte.h b/lib/libc/include/riscv64-openbsd-none/riscv64/pte.h new file mode 100644 index 000000000000..c050e38cb22b --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/pte.h @@ -0,0 +1,85 @@ +/* $OpenBSD: pte.h,v 1.4 2024/10/14 12:02:16 jsg Exp $ */ + +/* + * Copyright (c) 2019 Brian Bamsch + * Copyright (c) 2014 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef _RISCV64_PTE_H_ +#define _RISCV64_PTE_H_ + +#define Lx_TABLE_ALIGN (4096) + +/* Block and Page attributes */ +/* Bits 9:8 are reserved for software */ +#define PTE_ATTR_MASK (0x3ffUL) +#define PTE_SW_MANAGED (1 << 9) +#define PTE_SW_WIRED (1 << 8) +#define PTE_D (1 << 7) /* Dirty */ +#define PTE_A (1 << 6) /* Accessed */ +#define PTE_G (1 << 5) /* Global */ +#define PTE_U (1 << 4) /* User */ +#define PTE_X (1 << 3) /* Execute */ +#define PTE_W (1 << 2) /* Write */ +#define PTE_R (1 << 1) /* Read */ +#define PTE_V (1 << 0) /* Valid */ +#define PTE_RWX (PTE_R | PTE_W | PTE_X) +#define PTE_RX (PTE_R | PTE_X) +#define PTE_KERN (PTE_V | PTE_R | PTE_W | PTE_A | PTE_D) + +/* T-Head extended page attributes */ +#define PTE_THEAD_SO (1ULL << 63) +#define PTE_THEAD_C (1ULL << 62) +#define PTE_THEAD_B (1ULL << 61) +#define PTE_THEAD_SH (1ULL << 60) + +/* Level 0 table, 512GiB per entry */ +#define L0_SHIFT 39 + +/* Level 1 table, 1GiB per entry */ +#define L1_SHIFT 30 +#define L1_SIZE (1UL << L1_SHIFT) +#define L1_OFFSET (L1_SIZE - 1) + +/* Level 2 table, 2MiB per entry */ +#define L2_SHIFT 21 +#define L2_SIZE (1UL << L2_SHIFT) +#define L2_OFFSET (L2_SIZE - 1) + +/* Level 3 table, 4KiB per entry */ +#define L3_SHIFT 12 +#define L3_SIZE (1UL << L3_SHIFT) +#define L3_OFFSET (L3_SIZE - 1) + +/* page mapping */ +#define Ln_ENTRIES_SHIFT 9 +#define Ln_ENTRIES (1 << Ln_ENTRIES_SHIFT) +#define Ln_ADDR_MASK (Ln_ENTRIES - 1) +#define Ln_TABLE_MASK ((1 << 12) - 1) + +/* physical page number mask */ +#define PTE_RPGN (((1ULL << 56) - 1) & ~PAGE_MASK) + +#define PTE_PPN0_S 10 +#define PTE_PPN1_S 19 +#define PTE_PPN2_S 28 +#define PTE_PPN3_S 37 +#define PTE_SIZE 8 + +#ifndef _LOCORE +typedef uint64_t pt_entry_t; /* page table entry */ +typedef uint64_t pn_t; /* page number */ +#endif /* !_LOCORE */ + +#endif /* _RISCV64_PTE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/ptrace.h b/lib/libc/include/riscv64-openbsd-none/riscv64/ptrace.h new file mode 100644 index 000000000000..acffe6191946 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/ptrace.h @@ -0,0 +1,25 @@ +/* $OpenBSD: ptrace.h,v 1.4 2021/09/03 14:13:06 jca Exp $ */ + +/* + * Copyright (c) 2014 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#if 0 +#define PT_STEP (PT_FIRSTMACH + 0) +#endif +#define PT_GETREGS (PT_FIRSTMACH + 1) +#define PT_SETREGS (PT_FIRSTMACH + 2) +#define PT_GETFPREGS (PT_FIRSTMACH + 3) +#define PT_SETFPREGS (PT_FIRSTMACH + 4) \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/reg.h b/lib/libc/include/riscv64-openbsd-none/riscv64/reg.h new file mode 100644 index 000000000000..f80b13d4aa2f --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/reg.h @@ -0,0 +1,60 @@ +/* $OpenBSD: reg.h,v 1.2 2021/05/12 01:20:52 jsg Exp $ */ + +/*- + * Copyright (c) 2019 Brian Bamsch + * Copyright (c) 2015-2016 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_REG_H_ +#define _MACHINE_REG_H_ + +struct reg { + uint64_t r_ra; /* return address */ + uint64_t r_sp; /* stack pointer */ + uint64_t r_gp; /* global pointer */ + uint64_t r_tp; /* thread pointer */ + uint64_t r_t[7]; /* temporary registers */ + uint64_t r_s[12]; /* saved registers */ + uint64_t r_a[8]; /* argument registers */ + uint64_t r_sepc; /* exception program counter */ + uint64_t r_sstatus; /* status register */ +}; + +struct fpreg { + uint64_t fp_f[32]; /* floating-point registers */ + uint64_t fp_fcsr; /* floating-point control register */ +}; + +#endif /* !_MACHINE_REG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/reloc.h b/lib/libc/include/riscv64-openbsd-none/riscv64/reloc.h new file mode 100644 index 000000000000..09dea83e329d --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/reloc.h @@ -0,0 +1,19 @@ +/* $OpenBSD: reloc.h,v 1.2 2021/05/12 01:20:52 jsg Exp $ */ + +/* + * RISCV64 static relocation types. + */ + +/* Relocation types used by the dynamic linker. */ +#define R_RISCV_NONE 0 +#define R_RISCV_32 1 +#define R_RISCV_64 2 +#define R_RISCV_RELATIVE 3 +#define R_RISCV_COPY 4 +#define R_RISCV_JUMP_SLOT 5 +#define R_RISCV_TLS_DTPMOD32 6 +#define R_RISCV_TLS_DTPMOD64 7 +#define R_RISCV_TLS_DTPREL32 8 +#define R_RISCV_TLS_DTPREL64 9 +#define R_RISCV_TLS_TPREL32 10 +#define R_RISCV_TLS_TPREL64 11 \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/riscvreg.h b/lib/libc/include/riscv64-openbsd-none/riscv64/riscvreg.h new file mode 100644 index 000000000000..cf19db3ca1d3 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/riscvreg.h @@ -0,0 +1,235 @@ +/* $OpenBSD: riscvreg.h,v 1.5 2022/08/29 02:01:18 jsg Exp $ */ + +/*- + * Copyright (c) 2019 Brian Bamsch + * Copyright (c) 2015-2017 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 _MACHINE_RISCVREG_H_ +#define _MACHINE_RISCVREG_H_ + +#define EXCP_SHIFT 0 +#define EXCP_MASK (0xf << EXCP_SHIFT) +#define EXCP_MISALIGNED_FETCH 0 +#define EXCP_FAULT_FETCH 1 +#define EXCP_ILLEGAL_INSTRUCTION 2 +#define EXCP_BREAKPOINT 3 +#define EXCP_MISALIGNED_LOAD 4 +#define EXCP_FAULT_LOAD 5 +#define EXCP_MISALIGNED_STORE 6 +#define EXCP_FAULT_STORE 7 +#define EXCP_USER_ECALL 8 +#define EXCP_SUPERVISOR_ECALL 9 +#define EXCP_HYPERVISOR_ECALL 10 +#define EXCP_MACHINE_ECALL 11 +#define EXCP_INST_PAGE_FAULT 12 +#define EXCP_LOAD_PAGE_FAULT 13 +#define EXCP_STORE_PAGE_FAULT 15 +#define EXCP_INTR (1ULL << 63) + +#define MSTATUS_UIE (1 << 0) +#define MSTATUS_SIE (1 << 1) +#define MSTATUS_MIE (1 << 3) +#define MSTATUS_UPIE (1 << 4) +#define MSTATUS_SPIE (1 << 5) +#define MSTATUS_MPIE (1 << 7) +#define MSTATUS_SPP (1 << 8) +#define MSTATUS_MPP_SHIFT 11 +#define MSTATUS_MPP_MASK (0x3 << MSTATUS_MPP_SHIFT) +#define MSTATUS_FS_SHIFT 13 +#define MSTATUS_FS_MASK (0x3 << MSTATUS_FS_SHIFT) +#define MSTATUS_XS_SHIFT 15 +#define MSTATUS_XS_MASK (0x3 << MSTATUS_XS_SHIFT) +#define MSTATUS_MPRV (1 << 17) +#define MSTATUS_SUM (1 << 18) +#define MSTATUS_MXR (1 << 19) +#define MSTATUS_TVM (1 << 20) +#define MSTATUS_TW (1 << 21) +#define MSTATUS_TSR (1 << 22) +#define MSTATUS_UXL_SHIFT 32 +#define MSTATUS_UXL_MASK (0x3ULL << MSTATUS_UXL_SHIFT) +#define MSTATUS_SXL_SHIFT 34 +#define MSTATUS_SXL_MASK (0x3ULL << MSTATUS_SXL_SHIFT) +#define MSTATUS_SD (1ULL << (MXLEN - 1)) + +#define SSTATUS_UIE (1 << 0) +#define SSTATUS_SIE (1 << 1) +#define SSTATUS_UPIE (1 << 4) +#define SSTATUS_SPIE (1 << 5) +#define SSTATUS_SPP (1 << 8) +#define SSTATUS_FS_SHIFT 13 +#define SSTATUS_FS_MASK (0x3 << SSTATUS_FS_SHIFT) +#define SSTATUS_FS_OFF (0x0 << SSTATUS_FS_SHIFT) +#define SSTATUS_FS_INITIAL (0x1 << SSTATUS_FS_SHIFT) +#define SSTATUS_FS_CLEAN (0x2 << SSTATUS_FS_SHIFT) +#define SSTATUS_FS_DIRTY (0x3 << SSTATUS_FS_SHIFT) +#define SSTATUS_XS_SHIFT 15 +#define SSTATUS_XS_MASK (0x3 << SSTATUS_XS_SHIFT) +#define SSTATUS_SUM (1 << 18) +#define SSTATUS_MXR (1 << 19) +#define SSTATUS_UXL_SHIFT 32 +#define SSTATUS_UXL_MASK (0x3ULL << SSTATUS_UXL_SHIFT) +#define SSTATUS_SD (1ULL << (SXLEN - 1)) + +#define USTATUS_UIE (1 << 0) +#define USTATUS_UPIE (1 << 4) + +#define MSTATUS_PRV_U 0 /* user */ +#define MSTATUS_PRV_S 1 /* supervisor */ +#define MSTATUS_PRV_H 2 /* hypervisor */ +#define MSTATUS_PRV_M 3 /* machine */ + +#define MIE_USIE (1 << 0) +#define MIE_SSIE (1 << 1) +#define MIE_MSIE (1 << 3) +#define MIE_UTIE (1 << 4) +#define MIE_STIE (1 << 5) +#define MIE_MTIE (1 << 7) +#define MIE_UEIE (1 << 8) +#define MIE_SEIE (1 << 9) +#define MIE_MEIE (1 << 11) + +#define MIP_USIP (1 << 0) +#define MIP_SSIP (1 << 1) +#define MIP_MSIP (1 << 3) +#define MIP_UTIP (1 << 4) +#define MIP_STIP (1 << 5) +#define MIP_MTIP (1 << 7) +#define MIP_UEIP (1 << 8) +#define MIP_SEIP (1 << 9) +#define MIP_MEIP (1 << 11) + +#define SIE_USIE (1 << 0) +#define SIE_SSIE (1 << 1) +#define SIE_UTIE (1 << 4) +#define SIE_STIE (1 << 5) +#define SIE_UEIE (1 << 8) +#define SIE_SEIE (1 << 9) + +#define SIP_USIP (1 << 0) +#define SIP_SSIP (1 << 1) +#define SIP_UTIP (1 << 4) +#define SIP_STIP (1 << 5) +#define SIP_UEIP (1 << 8) +#define SIP_SEIP (1 << 9) + +#define UIE_USIE (1 << 0) +#define UIE_UTIE (1 << 4) +#define UIE_UEIE (1 << 8) + +#define UIP_USIP (1 << 0) +#define UIP_UTIP (1 << 4) +#define UIP_UEIP (1 << 8) + +#define PPN(pa) ((pa) >> PAGE_SHIFT) +#define SATP_PPN_SHIFT 0 +#define SATP_PPN_MASK (0xfffffffffffULL << SATP_PPN_SHIFT) +#define SATP_PPN(satp) (((satp) & SATP_PPN_MASK) >> SATP_PPN_SHIFT) +#define SATP_FORMAT_PPN(ppn) (((uint64_t)(ppn) << SATP_PPN_SHIFT) & SATP_PPN_MASK) +#define SATP_ASID_SHIFT 44 +#define SATP_ASID_MASK (0xffffULL << SATP_ASID_SHIFT) +#define SATP_ASID(satp) (((satp) & SATP_ASID_MASK) >> SATP_ASID_SHIFT) +#define SATP_FORMAT_ASID(asid) (((uint64_t)(asid) << SATP_ASID_SHIFT) & SATP_ASID_MASK) +#define SATP_MODE_SHIFT 60 +#define SATP_MODE_MASK (0xfULL << SATP_MODE_SHIFT) +#define SATP_MODE(mode) (((satp) & SATP_MODE_MASK) >> SATP_MODE_SHIFT) + +#define SATP_MODE_SV39 (8ULL << SATP_MODE_SHIFT) +#define SATP_MODE_SV48 (9ULL << SATP_MODE_SHIFT) +#define SATP_MODE_SV57 (10ULL << SATP_MODE_SHIFT) +#define SATP_MODE_SV64 (11ULL << SATP_MODE_SHIFT) + +/** + * As of RISC-V Machine ISA v1.11, the XLEN can vary between + * Machine, Supervisor, and User modes. The Machine XLEN (MXLEN) + * is resolved from the MXL field of the 'misa' CSR. The + * Supervisor XLEN (SXLEN) and User XLEN (UXLEN) are resolved + * from the SXL and UXL fields of the 'mstatus' CSR, respectively. + * + * The Machine XLEN is reset to the widest supported ISA variant + * at machine reset. For now, assume that all modes will always + * use the same, static XLEN of 64 bits. + */ +#define XLEN 64 +#define XLEN_BYTES (XLEN / 8) +#define MXLEN XLEN +#define SXLEN XLEN +#define UXLEN XLEN +#define INSN_SIZE 4 +#define INSN_C_SIZE 2 + +// Check if val can fit in the CSR immediate form +#define CSR_ZIMM(val) \ + (__builtin_constant_p(val) && ((u_long)(val) < 32)) + +#define csr_swap(csr, val) \ +({ if (CSR_ZIMM(val)) \ + __asm volatile("csrrwi %0, " #csr ", %1" \ + : "=r" (val) : "i" (val)); \ + else \ + __asm volatile("csrrw %0, " #csr ", %1" \ + : "=r" (val) : "r" (val)); \ + val; \ +}) + +#define csr_write(csr, val) \ +({ if (CSR_ZIMM(val)) \ + __asm volatile("csrwi " #csr ", %0" :: "i" (val)); \ + else \ + __asm volatile("csrw " #csr ", %0" :: "r" (val)); \ +}) + +#define csr_set(csr, val) \ +({ if (CSR_ZIMM(val)) \ + __asm volatile("csrsi " #csr ", %0" :: "i" (val)); \ + else \ + __asm volatile("csrs " #csr ", %0" :: "r" (val)); \ +}) + +#define csr_clear(csr, val) \ +({ if (CSR_ZIMM(val)) \ + __asm volatile("csrci " #csr ", %0" :: "i" (val)); \ + else \ + __asm volatile("csrc " #csr ", %0" :: "r" (val)); \ +}) + +#define csr_read(csr) \ +({ u_long val; \ + __asm volatile("csrr %0, " #csr : "=r" (val)); \ + val; \ +}) + +#endif /* !_MACHINE_RISCVREG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/sbi.h b/lib/libc/include/riscv64-openbsd-none/riscv64/sbi.h new file mode 100644 index 000000000000..51e313311dc7 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/sbi.h @@ -0,0 +1,267 @@ +/* $OpenBSD: sbi.h,v 1.6 2024/03/29 22:11:34 kettenis Exp $ */ + +/*- + * Copyright (c) 2016-2017 Ruslan Bukin + * All rights reserved. + * Copyright (c) 2019 Mitchell Horne + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * 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 _MACHINE_SBI_H_ +#define _MACHINE_SBI_H_ + +/* SBI Specification Version */ +#define SBI_SPEC_VERS_MAJOR_OFFSET 24 +#define SBI_SPEC_VERS_MAJOR_MASK (0x7F << SBI_SPEC_VERS_MAJOR_OFFSET) +#define SBI_SPEC_VERS_MINOR_OFFSET 0 +#define SBI_SPEC_VERS_MINOR_MASK (0xFFFFFF << SBI_SPEC_VERS_MINOR_OFFSET) + +/* SBI Implementation IDs */ +#define SBI_IMPL_ID_BBL 0 +#define SBI_IMPL_ID_OPENSBI 1 + +/* SBI Error Codes */ +#define SBI_SUCCESS 0 +#define SBI_ERR_FAILURE -1 +#define SBI_ERR_NOT_SUPPORTED -2 +#define SBI_ERR_INVALID_PARAM -3 +#define SBI_ERR_DENIED -4 +#define SBI_ERR_INVALID_ADDRESS -5 + +/* SBI Base Extension */ +#define SBI_EXT_ID_BASE 0x10 +#define SBI_BASE_GET_SPEC_VERSION 0 +#define SBI_BASE_GET_IMPL_ID 1 +#define SBI_BASE_GET_IMPL_VERSION 2 +#define SBI_BASE_PROBE_EXTENSION 3 +#define SBI_BASE_GET_MVENDORID 4 +#define SBI_BASE_GET_MARCHID 5 +#define SBI_BASE_GET_MIMPID 6 + +/* Hart State Management (HSM) Extension */ +#define SBI_EXT_ID_HSM 0x48534D +#define SBI_HSM_HART_START 0 +#define SBI_HSM_HART_STOP 1 +#define SBI_HSM_HART_STATUS 2 +#define SBI_HSM_STATUS_STARTED 0 +#define SBI_HSM_STATUS_STOPPED 1 +#define SBI_HSM_STATUS_START_PENDING 2 +#define SBI_HSM_STATUS_STOP_PENDING 3 + +/* System Reset Extension */ +#define SBI_EXT_ID_SRST 0x53525354 +#define SBI_SRST_RESET 0 +#define SBI_SRST_RESET_SHUTDOWN 0 +#define SBI_SRST_RESET_COLD_REBOOT 1 +#define SBI_SRST_RESET_WARM_REBOOT 2 + +/* Legacy Extensions */ +#define SBI_SET_TIMER 0 +#define SBI_CONSOLE_PUTCHAR 1 +#define SBI_CONSOLE_GETCHAR 2 +#define SBI_CLEAR_IPI 3 +#define SBI_SEND_IPI 4 +#define SBI_REMOTE_FENCE_I 5 +#define SBI_REMOTE_SFENCE_VMA 6 +#define SBI_REMOTE_SFENCE_VMA_ASID 7 +#define SBI_SHUTDOWN 8 + +#define SBI_CALL0(e, f) SBI_CALL4(e, f, 0, 0, 0, 0) +#define SBI_CALL1(e, f, p1) SBI_CALL4(e, f, p1, 0, 0, 0) +#define SBI_CALL2(e, f, p1, p2) SBI_CALL4(e, f, p1, p2, 0, 0) +#define SBI_CALL3(e, f, p1, p2, p3) SBI_CALL4(e, f, p1, p2, p3, 0) +#define SBI_CALL4(e, f, p1, p2, p3, p4) sbi_call(e, f, p1, p2, p3, p4) + +/* + * Documentation available at + * https://github.com/riscv/riscv-sbi-doc/blob/master/riscv-sbi.adoc + */ + +struct sbi_ret { + long error; + long value; +}; + +static __inline struct sbi_ret +sbi_call(uint64_t arg7, uint64_t arg6, uint64_t arg0, uint64_t arg1, + uint64_t arg2, uint64_t arg3) +{ + struct sbi_ret ret; + + register uintptr_t a0 __asm ("a0") = (uintptr_t)(arg0); + register uintptr_t a1 __asm ("a1") = (uintptr_t)(arg1); + register uintptr_t a2 __asm ("a2") = (uintptr_t)(arg2); + register uintptr_t a3 __asm ("a3") = (uintptr_t)(arg3); + register uintptr_t a6 __asm ("a6") = (uintptr_t)(arg6); + register uintptr_t a7 __asm ("a7") = (uintptr_t)(arg7); + + __asm volatile( \ + "ecall" \ + :"+r"(a0), "+r"(a1) \ + :"r"(a2), "r"(a3), "r"(a6), "r"(a7) \ + :"memory"); + + ret.error = a0; + ret.value = a1; + return (ret); +} + +/* Base extension functions and variables. */ +extern u_long sbi_spec_version; +extern u_long sbi_impl_id; +extern u_long sbi_impl_version; + +static __inline u_int +sbi_get_mvendorid(void) +{ + return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_MVENDORID).value); +} + + +static __inline u_long +sbi_get_marchid(void) +{ + return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_MARCHID).value); +} + +static __inline u_long +sbi_get_mimpid(void) +{ + return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_MIMPID).value); +} + +static __inline long +sbi_probe_extension(long id) +{ + return (SBI_CALL1(SBI_EXT_ID_BASE, SBI_BASE_PROBE_EXTENSION, id).value); +} + +/* Hart State Management extension functions. */ + +/* + * Start execution on the specified hart at physical address start_addr. The + * register a0 will contain the hart's ID, and a1 will contain the value of + * priv. + */ +int sbi_hsm_hart_start(u_long hart, u_long start_addr, u_long priv); + +/* + * Stop execution on the current hart. Interrupts should be disabled, or this + * function may return. + */ +void sbi_hsm_hart_stop(void); + +/* + * Get the execution status of the specified hart. The status will be one of: + * - SBI_HSM_STATUS_STARTED + * - SBI_HSM_STATUS_STOPPED + * - SBI_HSM_STATUS_START_PENDING + * - SBI_HSM_STATUS_STOP_PENDING + */ +int sbi_hsm_hart_status(u_long hart); + +/* Legacy extension functions. */ +static __inline void +sbi_console_putchar(int ch) +{ + + (void)SBI_CALL1(SBI_CONSOLE_PUTCHAR, 0, ch); +} + +static __inline int +sbi_console_getchar(void) +{ + + /* + * XXX: The "error" is returned here because legacy SBI functions + * continue to return their value in a0. + */ + return (SBI_CALL0(SBI_CONSOLE_GETCHAR, 0).error); +} + +static __inline void +sbi_set_timer(uint64_t val) +{ + + (void)SBI_CALL1(SBI_SET_TIMER, 0, val); +} + +static __inline void +sbi_shutdown(void) +{ + + (void)SBI_CALL0(SBI_SHUTDOWN, 0); +} + +static __inline void +sbi_clear_ipi(void) +{ + + (void)SBI_CALL0(SBI_CLEAR_IPI, 0); +} + +static __inline void +sbi_send_ipi(const unsigned long *hart_mask) +{ + + (void)SBI_CALL1(SBI_SEND_IPI, 0, (uint64_t)hart_mask); +} + +static __inline void +sbi_remote_fence_i(const unsigned long *hart_mask) +{ + + (void)SBI_CALL1(SBI_REMOTE_FENCE_I, 0, (uint64_t)hart_mask); +} + +static __inline void +sbi_remote_sfence_vma(const unsigned long *hart_mask, + unsigned long start, unsigned long size) +{ + + (void)SBI_CALL3(SBI_REMOTE_SFENCE_VMA, 0, (uint64_t)hart_mask, start, + size); +} + +static __inline void +sbi_remote_sfence_vma_asid(const unsigned long *hart_mask, + unsigned long start, unsigned long size, + unsigned long asid) +{ + + (void)SBI_CALL4(SBI_REMOTE_SFENCE_VMA_ASID, 0, (uint64_t)hart_mask, + start, size, asid); +} + +void sbi_print_version(void); +void sbi_init(void); + +#endif /* !_MACHINE_SBI_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/setjmp.h b/lib/libc/include/riscv64-openbsd-none/riscv64/setjmp.h new file mode 100644 index 000000000000..5d0d59cc4dcf --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/setjmp.h @@ -0,0 +1,8 @@ +/* $OpenBSD: setjmp.h,v 1.4 2021/06/17 16:09:08 kettenis Exp $ */ + +/* + * machine/setjmp.h: machine dependent setjmp-related information. + */ + +#define _JBLEN 32 /* sp, ra, [f]s0-11, fscr, magic val, sigmask */ +#define _JB_SIGMASK 28 \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/signal.h b/lib/libc/include/riscv64-openbsd-none/riscv64/signal.h new file mode 100644 index 000000000000..cf9ddecbfc7c --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/signal.h @@ -0,0 +1,70 @@ +/* $OpenBSD: signal.h,v 1.4 2021/05/20 15:14:30 drahn Exp $ */ + +/*- + * Copyright (c) 1986, 1989, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)signal.h 8.1 (Berkeley) 6/11/93 + * from: FreeBSD: src/sys/i386/include/signal.h,v 1.13 2000/11/09 + * from: FreeBSD: src/sys/sparc64/include/signal.h,v 1.6 2001/09/30 18:52:17 + * $FreeBSD: head/sys/riscv/include/signal.h 292407 2015-12-17 18:44:30Z br $ + */ + +#ifndef _MACHINE_SIGNAL_H_ +#define _MACHINE_SIGNAL_H_ + +#include + +typedef int sig_atomic_t; + +#if __BSD_VISIBLE || __XPG_VISIBLE >= 420 + +#include + +struct sigcontext { + int __sc_unused; + int sc_mask; + + __register_t sc_ra; + __register_t sc_sp; + __register_t sc_gp; + __register_t sc_tp; + __register_t sc_t[7]; + __register_t sc_s[12]; + __register_t sc_a[8]; + __register_t sc_sepc; + + /* 64 bit floats as well as integer registers */ + __register_t sc_f[32]; /* floating-point registers */ + __register_t sc_fcsr; /* floating-point control register */ + + long sc_cookie; +}; + +#endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ + +#endif /* !_MACHINE_SIGNAL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/simplebusvar.h b/lib/libc/include/riscv64-openbsd-none/riscv64/simplebusvar.h new file mode 100644 index 000000000000..5be6208e7492 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/simplebusvar.h @@ -0,0 +1,38 @@ +/* $OpenBSD: simplebusvar.h,v 1.1 2023/09/22 01:10:44 jsg Exp $ */ + +/* + * Copyright (c) 2016 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +struct simplebus_softc { + struct device sc_dev; + int sc_node; + bus_space_tag_t sc_iot; + bus_dma_tag_t sc_dmat; + int sc_acells; + int sc_scells; + int sc_pacells; + int sc_pscells; + struct bus_space sc_bus; + struct machine_bus_dma_tag sc_dma; + int *sc_ranges; + int sc_rangeslen; + int *sc_dmaranges; + int sc_dmarangeslen; + int sc_early; + int sc_early_nodes[64]; +}; + +extern void simplebus_attach(struct device *, struct device *, void *); \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/spinlock.h b/lib/libc/include/riscv64-openbsd-none/riscv64/spinlock.h new file mode 100644 index 000000000000..aca85f3b7b7c --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/spinlock.h @@ -0,0 +1,10 @@ +/* $OpenBSD: spinlock.h,v 1.2 2021/05/12 01:20:52 jsg Exp $ */ + +#ifndef _MACHINE_SPINLOCK_H_ +#define _MACHINE_SPINLOCK_H_ + +#define _ATOMIC_LOCK_UNLOCKED (0) +#define _ATOMIC_LOCK_LOCKED (1) +typedef int _atomic_lock_t; + +#endif \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/sysarch.h b/lib/libc/include/riscv64-openbsd-none/riscv64/sysarch.h new file mode 100644 index 000000000000..cef4a2f0be96 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/sysarch.h @@ -0,0 +1,43 @@ +/* $OpenBSD: sysarch.h,v 1.1 2021/09/14 12:03:49 jca Exp $ */ + +/* + * Copyright (c) 2021 Jeremie Courreges-Anglas + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _RISCV64_SYSARCH_H_ +#define _RISCV64_SYSARCH_H_ + +/* + * Architecture specific syscalls (riscv64) + */ + +#define RISCV_SYNC_ICACHE 0 + +struct riscv_sync_icache_args { + u_int64_t addr; /* Virtual start address */ + size_t len; /* Region size */ +}; + +#ifndef _KERNEL + +#include + +__BEGIN_DECLS +int sysarch(int, void *); +__END_DECLS + +#endif /* _KERNEL */ + +#endif /* _RISCV64_SYSARCH_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/syscall.h b/lib/libc/include/riscv64-openbsd-none/riscv64/syscall.h new file mode 100644 index 000000000000..b3f643ffdde4 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/syscall.h @@ -0,0 +1,28 @@ +/* $OpenBSD: syscall.h,v 1.3 2021/05/21 16:49:35 deraadt Exp $ */ + +/* + * Copyright (c) 2020 Brian Bamsch + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_SYSCALL_H_ +#define _MACHINE_SYSCALL_H_ + +#ifdef _KERNEL + +void svc_handler (trapframe_t *); + +#endif + +#endif /* !_MACHINE_SYSCALL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/tcb.h b/lib/libc/include/riscv64-openbsd-none/riscv64/tcb.h new file mode 100644 index 000000000000..d1400331983f --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/tcb.h @@ -0,0 +1,52 @@ +/* $OpenBSD: tcb.h,v 1.3 2021/05/12 01:20:52 jsg Exp $ */ + +/* + * Copyright (c) 2019 Brian Bamsch + * Copyright (c) 2011 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TCB_H_ +#define _MACHINE_TCB_H_ + +#ifdef _KERNEL + +#include + +#define TCB_GET(p) \ + ((void *)(((struct pcb *)(p)->p_addr)->pcb_tf->tf_tp)) + +#define TCB_SET(p, addr) \ + do { \ + ((struct pcb *)(p)->p_addr)->pcb_tf->tf_tp = (long)(addr); \ + } while (0) + +#else /* _KERNEL */ + +/* ELF TLS ABI calls for small TCB, with static TLS data after it */ +#define TLS_VARIANT 1 + +static inline void * +__riscv64_read_tcb(void) +{ + void *tcb; + __asm volatile("mv %0, tp": "=r" (tcb)); + return tcb; +} + +#define TCB_GET() __riscv64_read_tcb() + +#endif /* _KERNEL */ + +#endif /* _MACHINE_TCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/timetc.h b/lib/libc/include/riscv64-openbsd-none/riscv64/timetc.h new file mode 100644 index 000000000000..a19dd6f23f95 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/timetc.h @@ -0,0 +1,24 @@ +/* $OpenBSD: timetc.h,v 1.3 2021/07/24 22:41:09 jca Exp $ */ + +/* + * Copyright (c) 2020 Paul Irofti + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TIMETC_H_ +#define _MACHINE_TIMETC_H_ + +#define TC_TB 1 + +#endif /* _MACHINE_TIMETC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/trap.h b/lib/libc/include/riscv64-openbsd-none/riscv64/trap.h new file mode 100644 index 000000000000..337eb2f71f20 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/trap.h @@ -0,0 +1,24 @@ +/* $OpenBSD: trap.h,v 1.2 2021/05/12 01:20:52 jsg Exp $ */ + +/* + * Copyright (c) 2019 Brian Bamsch + * Copyright (c) 2016 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define KERNEL_BREAKPOINT 0x00100073 /* EBREAK -- Used by DDB */ + +#define KBPT_ASM "ebreak" + +#define USER_BREAKPOINT 0x00100073 /* EBREAK */ \ No newline at end of file diff --git a/lib/libc/include/riscv64-openbsd-none/riscv64/vmparam.h b/lib/libc/include/riscv64-openbsd-none/riscv64/vmparam.h new file mode 100644 index 000000000000..a7d864087a73 --- /dev/null +++ b/lib/libc/include/riscv64-openbsd-none/riscv64/vmparam.h @@ -0,0 +1,150 @@ +/* $OpenBSD: vmparam.h,v 1.9 2023/11/28 09:10:18 jsg Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vmparam.h 5.9 (Berkeley) 5/12/91 + */ + +#ifndef _MACHINE_VMPARAM_H_ +#define _MACHINE_VMPARAM_H_ + +/* + * Machine dependent constants for riscv64. + */ + +#define USRSTACK VM_MAXUSER_ADDRESS + +/* + * Virtual memory related constants, all in bytes + */ +#ifndef MAXTSIZ +#define MAXTSIZ ((paddr_t)1*1024*1024*1024) /* max text size */ +#endif +#ifndef DFLDSIZ +#define DFLDSIZ ((paddr_t)128*1024*1024) /* initial data size limit */ +#endif +#ifndef MAXDSIZ +#define MAXDSIZ ((paddr_t)16*1024*1024*1024) /* max data size */ +#endif +#ifndef BRKSIZ +#define BRKSIZ ((paddr_t)1*1024*1024*1024) /* heap gap size */ +#endif +#ifndef DFLSSIZ +#define DFLSSIZ ((paddr_t)128*1024*1024) /* initial stack size limit */ +#endif +#ifndef MAXSSIZ +#define MAXSSIZ ((paddr_t)1*1024*1024*1024) /* max stack size */ +#endif + +#define STACKGAP_RANDOM 256*1024 + +/* + * Size of shared memory map + */ +#ifndef SHMMAXPGS +#define SHMMAXPGS 1024 +#endif + +/* + * Size of User Raw I/O map + */ +#define USRIOSIZE 300 + +/** + * Address space layout. + * + * RISC-V implements multiple paging modes with different virtual address space + * sizes: SV32, SV39 and SV48. SV39 permits a virtual address space size of + * 512GB and uses a three-level page table. Since this is large enough for most + * purposes, we currently use SV39 for both userland and the kernel, avoiding + * the extra translation step required by SV48. + * + * The address space is split into two regions at each end of the 64-bit address + * space: + * + * 0x0000000000000000 - 0x0000003fffffffff 256GB user map + * 0x0000004000000000 - 0xffffffbfffffffff unmappable + * 0xffffffc000000000 - 0xffffffc7ffffffff 32GB kernel map + * 0xffffffc800000000 - 0xffffffcfffffffff 32GB unused + * 0xffffffd000000000 - 0xffffffefffffffff 128GB direct map + * 0xfffffff000000000 - 0xffffffffffffffff 64GB unused + * + * The kernel is loaded at the beginning of the kernel map. + * + * We define some interesting address constants: + * + * VM_MIN_ADDRESS and VM_MAX_ADDRESS define the start and end of the entire + * 64 bit address space, mostly just for convenience. + * + * VM_MIN_KERNEL_ADDRESS and VM_MAX_KERNEL_ADDRESS define the start and end of + * mappable kernel virtual address space. + * + * VM_MIN_ADDRESS and VM_MAXUSER_ADDRESS define the start and end of the + * user address space. + */ +#define VM_MIN_ADDRESS ((vaddr_t)PAGE_SIZE) +#define VM_MAX_ADDRESS (0xffffffffffffffffUL) + +#define VM_MIN_KERNEL_ADDRESS (0xffffffc000000000UL) +#define VM_MAX_KERNEL_ADDRESS (0xffffffc800000000UL) + +/* Kernel L1 Page Table Range */ +#define L1_KERN_BASE (256) +#define L1_KERN_ENTRIES (288 - L1_KERN_BASE) + +#define DMAP_MIN_ADDRESS (0xffffffd000000000UL) +#define DMAP_MAX_ADDRESS (0xfffffff000000000UL) + +/* DMAP L1 Page Table Range */ +#define L1_DMAP_BASE (320) +#define L1_DMAP_ENTRIES (448 - L1_DMAP_BASE) + +#define VM_MAXUSER_ADDRESS (0x0000004000000000UL) /* 39 bits */ + +#ifdef _KERNEL +#define VM_MIN_STACK_ADDRESS (VM_MAXUSER_ADDRESS * 3 / 4) +#endif + +#define KERNBASE (VM_MIN_KERNEL_ADDRESS) + +#ifndef _LOCORE +extern paddr_t dmap_phys_base; +#endif + +/* virtual sizes (bytes) for various kernel submaps */ +#define VM_PHYS_SIZE (USRIOSIZE*PAGE_SIZE) + +#define VM_PHYSSEG_MAX 32 +#define VM_PHYSSEG_STRAT VM_PSTRAT_BSEARCH +#define VM_PHYSSEG_NOADD /* can't add RAM after vm_mem_init */ + +#endif /* _MACHINE_VMPARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/frame.h b/lib/libc/include/sparc64-openbsd-none/frame.h new file mode 100644 index 000000000000..4b077a0ce660 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/frame.h @@ -0,0 +1,105 @@ +/* $OpenBSD: frame.h,v 1.11 2024/04/08 20:07:53 miod Exp $ */ +/* $NetBSD: frame.h,v 1.9 2001/03/04 09:28:35 mrg Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)frame.h 8.1 (Berkeley) 6/11/93 + */ + +#ifndef _MACHINE_FRAME_H_ +#define _MACHINE_FRAME_H_ + +/* + * CC64FSZ (C Compiler 64-bit Frame SiZe) is the size of a stack frame used + * by the compiler in 64-bit mode. It is (16)*8; space for 8 ins, 8 outs. + */ +#define CC64FSZ 176 + +/* + * v9 stacks all have a bias of 2047 added to the %sp and %fp, so you can easily + * detect it by testing the register for an odd value. Why 2K-1 I don't know. + */ +#define BIAS (2048-1) + +#if defined(_KERNEL) && !defined(_LOCORE) + +/* + * Sparc v9 stack frame format. + * + * Note that the contents of each stack frame may be held only in + * machine register windows. In order to get an accurate picture + * of the frame, you must first force the kernel to write any such + * windows to the stack. + * + * V9 frames have an odd bias, so you can tell a v9 frame from + * a v8 frame by testing the stack pointer's lsb. + */ +struct frame { + int64_t fr_local[8]; /* space to save locals (%l0..%l7) */ + int64_t fr_arg[6]; /* space to save arguments (%i0..%i5) */ + u_int64_t fr_fp; /* space to save frame pointer (%i6) */ + u_int64_t fr_pc; /* space to save return pc (%i7) */ + /* + * SVR4 reserves a bunch of extra stuff. + */ + int64_t fr_argd[6]; /* `register save area' (lunacy) */ + int64_t fr_argx[0]; /* arg extension (args 7..n; variable size) */ +}; + +#define v9next_frame(f) ((struct frame*)(f->fr_fp+BIAS)) + +/* + * The v9 trapframe. + */ +struct trapframe { + int64_t tf_tstate; /* tstate register */ + int64_t tf_pc; /* return pc */ + int64_t tf_npc; /* return npc */ + int tf_y; /* %y register -- 32-bits */ + short tf_tt; /* What type of trap this was */ + char tf_pil; /* What IRQ we're handling */ + char tf_oldpil; /* What our old SPL was */ + int64_t tf_global[8]; /* global registers in trap's caller */ + int64_t tf_out[8]; /* output registers in trap's caller */ + int64_t tf_local[8]; /* local registers in trap's caller */ + int64_t tf_in[8]; /* in registers in trap's caller (for debug) */ +}; + +#endif /* _KERNEL && !_LOCORE */ + +#endif /* _MACHINE_FRAME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/_float.h b/lib/libc/include/sparc64-openbsd-none/machine/_float.h new file mode 100644 index 000000000000..3ab11abcabb1 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/_float.h @@ -0,0 +1,80 @@ +/* $OpenBSD: _float.h,v 1.1 2012/06/26 16:12:45 deraadt Exp $ */ + +/* + * Copyright (c) 1992, 1993, 2001 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE__FLOAT_H_ +#define _MACHINE__FLOAT_H_ + +#define __FLT_RADIX 2 /* b */ +#define __FLT_ROUNDS __flt_rounds() +#define __FLT_EVAL_METHOD 0 /* no promotions */ + +#define __FLT_MANT_DIG 24 /* p */ +#define __FLT_EPSILON 1.19209290E-07F /* b**(1-p) */ +#define __FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ +#define __FLT_MIN_EXP -125 /* emin */ +#define __FLT_MIN 1.17549435E-38F /* b**(emin-1) */ +#define __FLT_MIN_10_EXP -37 /* ceil(log10(b**(emin-1))) */ +#define __FLT_MAX_EXP 128 /* emax */ +#define __FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ +#define __FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ + +#define __DBL_MANT_DIG 53 +#define __DBL_EPSILON 2.2204460492503131E-16 +#define __DBL_DIG 15 +#define __DBL_MIN_EXP -1021 +#define __DBL_MIN 2.2250738585072014E-308 +#define __DBL_MIN_10_EXP -307 +#define __DBL_MAX_EXP 1024 +#define __DBL_MAX 1.7976931348623157E+308 +#define __DBL_MAX_10_EXP 308 + +#define __LDBL_MANT_DIG 113 +#define __LDBL_EPSILON 1.925929944387235853055977942584927319E-34L +#define __LDBL_DIG 33 +#define __LDBL_MIN_EXP (-16381) +#define __LDBL_MIN 3.362103143112093506262677817321752603E-4932L +#define __LDBL_MIN_10_EXP (-4931) +#define __LDBL_MAX_EXP (+16384) +#define __LDBL_MAX 1.189731495357231765085759326628007016E+4932L +#define __LDBL_MAX_10_EXP (+4932) + +#define __DECIMAL_DIG 36 + +#endif /* _MACHINE__FLOAT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/_types.h b/lib/libc/include/sparc64-openbsd-none/machine/_types.h new file mode 100644 index 000000000000..b0d11eb13a20 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/_types.h @@ -0,0 +1,140 @@ +/* $OpenBSD: _types.h,v 1.25 2023/07/02 19:02:28 cheloha Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.3 (Berkeley) 1/5/94 + * @(#)ansi.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _MACHINE__TYPES_H_ +#define _MACHINE__TYPES_H_ + +#if defined(_KERNEL) +typedef struct label_t { + long val[2]; +} label_t; +#endif + +/* + * _ALIGN(p) rounds p (pointer or byte index) up to a correctly-aligned + * value for all data types (int, long, ...). The result is an + * unsigned long and must be cast to any desired pointer type. + * + * _ALIGNED_POINTER is a boolean macro that checks whether an address + * is valid to fetch data elements of type t from on this architecture. + * This does not reflect the optimal alignment, just the possibility + * (within reasonable limits). + */ +#define _ALIGNBYTES 0xf +#define _STACKALIGNBYTES _ALIGNBYTES +#define _ALIGN(p) (((unsigned long)(p) + _ALIGNBYTES) & ~_ALIGNBYTES) +#define _ALIGNED_POINTER(p,t) ((((unsigned long)(p)) & (sizeof(t) - 1)) == 0) +#define _MAX_PAGE_SHIFT 13 /* same as PAGE_SHIFT */ + +/* 7.18.1.1 Exact-width integer types */ +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short __int16_t; +typedef unsigned short __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; +typedef long long __int64_t; +typedef unsigned long long __uint64_t; + +/* 7.18.1.2 Minimum-width integer types */ +typedef __int8_t __int_least8_t; +typedef __uint8_t __uint_least8_t; +typedef __int16_t __int_least16_t; +typedef __uint16_t __uint_least16_t; +typedef __int32_t __int_least32_t; +typedef __uint32_t __uint_least32_t; +typedef __int64_t __int_least64_t; +typedef __uint64_t __uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types */ +typedef __int32_t __int_fast8_t; +typedef __uint32_t __uint_fast8_t; +typedef __int32_t __int_fast16_t; +typedef __uint32_t __uint_fast16_t; +typedef __int32_t __int_fast32_t; +typedef __uint32_t __uint_fast32_t; +typedef __int64_t __int_fast64_t; +typedef __uint64_t __uint_fast64_t; +#define __INT_FAST8_MIN INT32_MIN +#define __INT_FAST16_MIN INT32_MIN +#define __INT_FAST32_MIN INT32_MIN +#define __INT_FAST64_MIN INT64_MIN +#define __INT_FAST8_MAX INT32_MAX +#define __INT_FAST16_MAX INT32_MAX +#define __INT_FAST32_MAX INT32_MAX +#define __INT_FAST64_MAX INT64_MAX +#define __UINT_FAST8_MAX UINT32_MAX +#define __UINT_FAST16_MAX UINT32_MAX +#define __UINT_FAST32_MAX UINT32_MAX +#define __UINT_FAST64_MAX UINT64_MAX + +/* 7.18.1.4 Integer types capable of holding object pointers */ +typedef long __intptr_t; +typedef unsigned long __uintptr_t; + +/* 7.18.1.5 Greatest-width integer types */ +typedef __int64_t __intmax_t; +typedef __uint64_t __uintmax_t; + +/* Register size */ +typedef long __register_t; + +/* VM system types */ +typedef unsigned long __vaddr_t; +typedef unsigned long __paddr_t; +typedef unsigned long __vsize_t; +typedef unsigned long __psize_t; + +/* Standard system types */ +typedef double __double_t; +typedef float __float_t; +typedef long __ptrdiff_t; +typedef unsigned long __size_t; +typedef long __ssize_t; +#if defined(__GNUC__) && __GNUC__ >= 3 +typedef __builtin_va_list __va_list; +#else +typedef char * __va_list; +#endif + +/* Wide character support types */ +#ifndef __cplusplus +typedef int __wchar_t; +#endif +typedef int __wint_t; +typedef int __rune_t; +typedef void * __wctrans_t; +typedef void * __wctype_t; + +#endif /* _MACHINE__TYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/apmvar.h b/lib/libc/include/sparc64-openbsd-none/machine/apmvar.h new file mode 100644 index 000000000000..62e9480a19b3 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/apmvar.h @@ -0,0 +1,122 @@ +/* $OpenBSD: apmvar.h,v 1.7 2019/01/22 02:36:30 phessler Exp $ */ + +/* + * Copyright (c) 2001 Alexander Guy + * Copyright (c) 1995 John T. Kohl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _MACHINE_APMVAR_H_ +#define _MACHINE_APMVAR_H_ + +#include + +/* Advanced Power Management (v1.0 and v1.1 specification) + * functions/defines/etc. + */ + +/* These definitions make up the heart of the user-land interface + * to the APM devices. + */ + +#define APM_AC_OFF 0x00 +#define APM_AC_ON 0x01 +#define APM_AC_BACKUP 0x02 +#define APM_AC_UNKNOWN 0xff +#define APM_BATT_HIGH 0x00 +#define APM_BATT_LOW 0x01 +#define APM_BATT_CRITICAL 0x02 +#define APM_BATT_CHARGING 0x03 +#define APM_BATT_UNKNOWN 0xff +#define APM_BATT_LIFE_UNKNOWN 0xff + +#define APM_NOEVENT 0x0000 +#define APM_STANDBY_REQ 0x0001 +#define APM_SUSPEND_REQ 0x0002 +#define APM_NORMAL_RESUME 0x0003 +#define APM_CRIT_RESUME 0x0004 /* suspend/resume happened + without us */ +#define APM_BATTERY_LOW 0x0005 +#define APM_POWER_CHANGE 0x0006 +#define APM_UPDATE_TIME 0x0007 +#define APM_CRIT_SUSPEND_REQ 0x0008 +#define APM_USER_STANDBY_REQ 0x0009 +#define APM_USER_SUSPEND_REQ 0x000A +#define APM_SYS_STANDBY_RESUME 0x000B +#define APM_CAPABILITY_CHANGE 0x000C /* apm v1.2 */ +#define APM_USER_HIBERNATE_REQ 0x000D +#define APM_EVENT_MASK 0xffff + +#define APM_EVENT_COMPOSE(t,i) ((((i) & 0x7fff) << 16)|((t) & APM_EVENT_MASK)) +#define APM_EVENT_TYPE(e) ((e) & APM_EVENT_MASK) +#define APM_EVENT_INDEX(e) ((e) >> 16) + +/* + * LP (Laptop Package) + * + * Copyright (C) 1994 by HOSOKAWA Tatsumi + * + * This software may be used, modified, copied, and distributed, in + * both source and binary form provided that the above copyright and + * these terms are retained. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with its + * use. + * + * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) + */ + +#define APM_BATTERY_ABSENT 4 + +struct apm_power_info { + u_char battery_state; + u_char ac_state; + u_char battery_life; + u_char spare1; + u_int minutes_left; /* estimate */ + u_int spare2[6]; +}; + +struct apm_ctl { + u_int dev; + u_int mode; +}; + +#define APM_IOC_REJECT _IOW('A', 0, struct apm_event_info) /* reject request # */ +#define APM_IOC_STANDBY _IO('A', 1) /* put system into standby */ +#define APM_IOC_SUSPEND _IO('A', 2) /* put system into suspend */ +#define APM_IOC_GETPOWER _IOR('A', 3, struct apm_power_info) /* fetch battery state */ +#define APM_IOC_DEV_CTL _IOW('A', 5, struct apm_ctl) /* put device into mode */ +#define APM_IOC_PRN_CTL _IOW('A', 6, int ) /* driver power status msg */ +#define APM_PRINT_ON 0 /* driver power status displayed */ +#define APM_PRINT_OFF 1 /* driver power status not displayed */ +#define APM_PRINT_PCT 2 /* driver power status only displayed + if the percentage changes */ +#define APM_IOC_STANDBY_REQ _IO('A', 7) /* request standby */ +#define APM_IOC_SUSPEND_REQ _IO('A', 8) /* request suspend */ +#define APM_IOC_HIBERNATE _IO('A', 9) /* put system into hibernate */ + +#endif /* _MACHINE_APMVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/asm.h b/lib/libc/include/sparc64-openbsd-none/machine/asm.h new file mode 100644 index 000000000000..2267bb9443d0 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/asm.h @@ -0,0 +1,96 @@ +/* $OpenBSD: asm.h,v 1.19 2024/03/29 21:05:34 miod Exp $ */ +/* $NetBSD: asm.h,v 1.15 2000/08/02 22:24:39 eeh Exp $ */ + +/* + * Copyright (c) 1994 Allen Briggs + * All rights reserved. + * + * Gleaned from locore.s and sun3 asm.h which had the following copyrights: + * locore.s: + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1990 The Regents of the University of California. + * sun3/include/asm.h: + * Copyright (c) 1993 Adam Glass + * Copyright (c) 1990 The Regents of the University of California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_ASM_H_ +#define _MACHINE_ASM_H_ + +/* Pull in CC64FSZ and BIAS from frame.h */ +#include + +#define _C_LABEL(name) name +#define _ASM_LABEL(name) name + +#ifdef __PIC__ +/* + * PIC_PROLOGUE() is akin to the compiler generated function prologue for + * PIC code. It leaves the address of the Global Offset Table in DEST, + * clobbering register TMP in the process. Using the temporary enables us + * to work without a stack frame (doing so requires saving %o7) . + */ +#define PIC_PROLOGUE(dest,tmp) \ + sethi %hi(_GLOBAL_OFFSET_TABLE_-4),dest; \ + rd %pc, tmp; \ + or dest,%lo(_GLOBAL_OFFSET_TABLE_+4),dest; \ + add dest,tmp,dest +#else +#define PIC_PROLOGUE(dest,tmp) +#endif + +#define FTYPE(x) .type x,@function +#define OTYPE(x) .type x,@object + +#define _ENTRY_NB(name) \ + .align 4; .proc 1; FTYPE(name); name: +#define _ENTRY(name) .globl name; _ENTRY_NB(name) + +#if defined(PROF) || defined(GPROF) +#define _PROF_PROLOGUE \ + .data; .align 8; 1: .uaword 0; .uaword 0; \ + .text; save %sp,-CC64FSZ,%sp; sethi %hi(1b),%o0; call _mcount; \ + or %o0,%lo(1b),%o0; restore +#else +#define _PROF_PROLOGUE +#endif + +#define ENTRY(name) _ENTRY(name); _PROF_PROLOGUE +#define NENTRY(name) _ENTRY(name) +#define ENTRY_NB(name) _ENTRY_NB(name); _PROF_PROLOGUE +#define ASENTRY(name) _ENTRY(name); _PROF_PROLOGUE +#define FUNC(name) ASENTRY(name) +#define END(y) .size y, . - y + +#define STRONG_ALIAS(alias,sym) \ + .global alias; \ + alias = sym +#define WEAK_ALIAS(alias,sym) \ + .weak alias; \ + alias = sym + +#endif /* _MACHINE_ASM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/atomic.h b/lib/libc/include/sparc64-openbsd-none/machine/atomic.h new file mode 100644 index 000000000000..bab72dabbee1 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/atomic.h @@ -0,0 +1,154 @@ +/* $OpenBSD: atomic.h,v 1.15 2017/07/04 09:00:12 mpi Exp $ */ +/* + * Copyright (c) 2007 Artur Grabowski + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_ATOMIC_H_ +#define _MACHINE_ATOMIC_H_ + +static inline unsigned int +_atomic_cas_uint(volatile unsigned int *p, unsigned int e, unsigned int n) +{ + __asm volatile("cas [%2], %3, %0" + : "+r" (n), "=m" (*p) + : "r" (p), "r" (e), "m" (*p)); + + return (n); +} +#define atomic_cas_uint(_p, _e, _n) _atomic_cas_uint((_p), (_e), (_n)) + +static inline unsigned long +_atomic_cas_ulong(volatile unsigned long *p, unsigned long e, unsigned long n) +{ + __asm volatile("casx [%2], %3, %0" + : "+r" (n), "=m" (*p) + : "r" (p), "r" (e), "m" (*p)); + + return (n); +} +#define atomic_cas_ulong(_p, _e, _n) _atomic_cas_ulong((_p), (_e), (_n)) + +static inline void * +_atomic_cas_ptr(volatile void *p, void *e, void *n) +{ + __asm volatile("casx [%2], %3, %0" + : "+r" (n), "=m" (*(volatile unsigned long *)p) + : "r" (p), "r" (e), "m" (*(volatile unsigned long *)p)); + + return (n); +} +#define atomic_cas_ptr(_p, _e, _n) _atomic_cas_ptr((_p), (_e), (_n)) + +#define _def_atomic_swap(_f, _t, _c) \ +static inline _t \ +_f(volatile _t *p, _t v) \ +{ \ + _t e; \ + _t r; \ + \ + r = (_t)*p; \ + do { \ + e = r; \ + r = _c(p, e, v); \ + } while (r != e); \ + \ + return (r); \ +} + +_def_atomic_swap(_atomic_swap_uint, unsigned int, atomic_cas_uint) +_def_atomic_swap(_atomic_swap_ulong, unsigned long, atomic_cas_ulong) +#undef _def_atomic_swap + +static inline void * +_atomic_swap_ptr(volatile void *p, void *v) +{ + void *e, *r; + + r = *(void **)p; + do { + e = r; + r = atomic_cas_ptr(p, e, v); + } while (r != e); + + return (r); +} + +#define atomic_swap_uint(_p, _v) _atomic_swap_uint(_p, _v) +#define atomic_swap_ulong(_p, _v) _atomic_swap_ulong(_p, _v) +#define atomic_swap_ptr(_p, _v) _atomic_swap_ptr(_p, _v) + +#define _def_atomic_op_nv(_f, _t, _c, _op) \ +static inline _t \ +_f(volatile _t *p, _t v) \ +{ \ + _t e, r, f; \ + \ + r = *p; \ + do { \ + e = r; \ + f = e _op v; \ + r = _c(p, e, f); \ + } while (r != e); \ + \ + return (f); \ +} + +_def_atomic_op_nv(_atomic_add_int_nv, unsigned int, atomic_cas_uint, +) +_def_atomic_op_nv(_atomic_add_long_nv, unsigned long, atomic_cas_ulong, +) +_def_atomic_op_nv(_atomic_sub_int_nv, unsigned int, atomic_cas_uint, -) +_def_atomic_op_nv(_atomic_sub_long_nv, unsigned long, atomic_cas_ulong, -) +#undef _def_atomic_op_nv + +#define atomic_add_int_nv(_p, _v) _atomic_add_int_nv(_p, _v) +#define atomic_add_long_nv(_p, _v) _atomic_add_long_nv(_p, _v) +#define atomic_sub_int_nv(_p, _v) _atomic_sub_int_nv(_p, _v) +#define atomic_sub_long_nv(_p, _v) _atomic_sub_long_nv(_p, _v) + +#define __membar(_m) __asm volatile("membar " _m ::: "memory") + +#define membar_enter() __membar("#StoreLoad|#StoreStore") +#define membar_exit() __membar("#LoadStore|#StoreStore") +#define membar_producer() __membar("#StoreStore") +#define membar_consumer() __membar("#LoadLoad") +#define membar_sync() __membar("#Sync") + +#if defined(_KERNEL) + +static __inline void +atomic_setbits_int(volatile unsigned int *uip, unsigned int v) +{ + unsigned int e, r; + + r = *uip; + do { + e = r; + r = atomic_cas_uint(uip, e, e | v); + } while (r != e); +} + +static __inline void +atomic_clearbits_int(volatile unsigned int *uip, unsigned int v) +{ + unsigned int e, r; + + r = *uip; + do { + e = r; + r = atomic_cas_uint(uip, e, e & ~v); + } while (r != e); +} + +#endif /* defined(_KERNEL) */ +#endif /* _MACHINE_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/autoconf.h b/lib/libc/include/sparc64-openbsd-none/machine/autoconf.h new file mode 100644 index 000000000000..0a5ed5b2dc36 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/autoconf.h @@ -0,0 +1,159 @@ +/* $OpenBSD: autoconf.h,v 1.20 2024/05/17 20:05:08 miod Exp $ */ +/* $NetBSD: autoconf.h,v 1.10 2001/07/24 19:32:11 eeh Exp $ */ + +/*- + * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)autoconf.h 8.2 (Berkeley) 9/30/93 + */ + +/* + * Autoconfiguration information. + */ + +#include +#include + +/* This is used to map device classes to IPLs */ +struct intrmap { + char *in_class; + int in_lev; +}; +extern struct intrmap intrmap[]; + +/* The "mainbus" on ultra desktops is actually the UPA bus. We need to + * separate this from peripheral buses like SBus and PCI because each bus may + * have different ways of encoding properties, such as "reg" and "interrupts". + */ + +/* Device register space description */ +struct upa_reg { + int64_t ur_paddr; + int64_t ur_len; +}; + +/* + * Attach arguments presented by mainbus_attach() + * + * Large fields first followed by smaller ones to minimize stack space used. + */ +struct mainbus_attach_args { + bus_space_tag_t ma_bustag; /* parent bus tag */ + bus_dma_tag_t ma_dmatag; + char *ma_name; /* PROM node name */ + struct upa_reg *ma_reg; /* "reg" properties */ + u_int *ma_address; /* "address" properties -- 32 bits */ + u_int *ma_interrupts; /* "interrupts" properties */ + int ma_upaid; /* UPA bus ID */ + int ma_node; /* PROM handle */ + int ma_nreg; /* Counts for those properties */ + int ma_naddress; + int ma_ninterrupts; + int ma_pri; /* priority (IPL) */ +}; + +/* + * length; the others convert or make some other guarantee. + */ +long getproplen(int node, char *name); +int getprop(int, char *, size_t, int *, void **); +char *getpropstring(int node, char *name); +int getpropint(int node, char *name, int deflt); +int getpropspeed(int node, char *name); + +/* Frequently used options node */ +extern int optionsnode; + + /* new interfaces: */ +char *getpropstringA(int, char *, char *); + +/* + * `clockfreq' produces a printable representation of a clock frequency + * (this is just a frill). + */ +char *clockfreq(long freq); + +/* Openprom V2 style boot path */ +struct device; +struct bootpath { + int node; + char name[16]; /* name of this node */ + long val[3]; /* up to three optional values */ + struct device *dev; /* device that recognised this component */ +}; +struct bootpath *bootpath_store(int, struct bootpath *); + +void bootstrap(int); +int firstchild(int); +int nextsibling(int); +void callrom(void); +struct device *getdevunit(const char *, int); +int romgetcursoraddr(int **, int **); +int findroot(void); +int findnode(int, const char *); +int checkstatus(int); +int node_has_property(int, const char *); +void device_register(struct device *, void *); \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/boot_flag.h b/lib/libc/include/sparc64-openbsd-none/machine/boot_flag.h new file mode 100644 index 000000000000..e53f7fc9bd41 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/boot_flag.h @@ -0,0 +1,50 @@ +/* $OpenBSD: boot_flag.h,v 1.8 2023/11/09 14:26:34 kn Exp $ */ +/* $NetBSD: boot_flag.h,v 1.3 2001/07/01 02:56:21 gmcgarry Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BOOT_FLAG_H_ +#define _MACHINE_BOOT_FLAG_H_ + +/* softraid boot information */ +#define BOOTSR_UUID_MAX 16 +#define BOOTSR_CRYPTO_MAXKEYBYTES 32 + +/* MD boot data in .openbsd.bootdata ELF segment */ +struct openbsd_bootdata { + u_int64_t version; + u_int64_t len; /* of structure */ + + u_int8_t sr_uuid[BOOTSR_UUID_MAX]; + u_int8_t sr_maskkey[BOOTSR_CRYPTO_MAXKEYBYTES]; + u_int32_t boothowto; +} __packed; + +#define BOOTDATA_VERSION 1 +#define BOOTDATA_LEN_BOOTHOWTO 68 + +#endif /* _MACHINE_BOOT_FLAG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/bppioctl.h b/lib/libc/include/sparc64-openbsd-none/machine/bppioctl.h new file mode 100644 index 000000000000..c424ccb47484 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/bppioctl.h @@ -0,0 +1,59 @@ +/* $OpenBSD: bppioctl.h,v 1.2 2008/11/29 01:55:06 ray Exp $ */ + +/*- + * Copyright (c) 1998 Iain Hibbert + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _IOCTL_ +#include +#endif + +struct bpp_param { + int bp_burst; /* chars to send/recv in one call */ + int bp_timeout; /* timeout: -1 blocking, 0 non blocking >0 ms */ + int bp_delay; /* delay between polls (ms) */ +}; + +#define BPP_BLOCK -1 +#define BPP_NOBLOCK 0 + +/* defaults */ +#define BPP_BURST 1024 +#define BPP_TIMEOUT BPP_BLOCK +#define BPP_DELAY 10 + +/* limits */ +#define BPP_BURST_MIN 1 +#define BPP_BURST_MAX 1024 +#define BPP_DELAY_MIN 0 +#define BPP_DELAY_MAX 30000 + +/* status bits */ +#define BPP_BUSY (1<<0) +#define BPP_PAPER (1<<1) + +/* ioctl commands */ +#define BPPIOCSPARAM _IOW('P', 0x1, struct bpp_param) +#define BPPIOCGPARAM _IOR('P', 0x2, struct bpp_param) +#define BPPIOCGSTAT _IOR('P', 0x4, int) \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/bus.h b/lib/libc/include/sparc64-openbsd-none/machine/bus.h new file mode 100644 index 000000000000..8e6f0472d366 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/bus.h @@ -0,0 +1,649 @@ +/* $OpenBSD: bus.h,v 1.38 2024/10/22 22:01:58 jsg Exp $ */ +/* $NetBSD: bus.h,v 1.31 2001/09/21 15:30:41 wiz Exp $ */ + +/*- + * Copyright (c) 1996, 1997, 1998, 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1997-1999, 2001 Eduardo E. Horvath. All rights reserved. + * Copyright (c) 1996 Charles M. Hannum. All rights reserved. + * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BUS_H_ +#define _MACHINE_BUS_H_ + +#include + +#ifdef _KERNEL + +/* + * Debug hooks + */ + +#define BSDB_ACCESS 0x01 +#define BSDB_MAP 0x02 +#define BSDB_ASSERT 0x04 +#define BSDB_MAPDETAIL 0x08 +#define BSDB_ALL_ACCESS 0x10 +extern int bus_space_debug; + +#define BSHDB_ACCESS 0x01 +#define BSHDB_NO_ACCESS 0x02 + +#if defined(BUS_SPACE_DEBUG) +#include +#define BUS_SPACE_PRINTF(l, s) do { \ + if(bus_space_debug & (l)) printf s; \ +} while(0) +#define BUS_SPACE_TRACE(t, h, s) do { \ + if ( (((bus_space_debug & BSDB_ALL_ACCESS) != 0) && \ + (((h).bh_flags & BSHDB_NO_ACCESS) == 0)) || \ + (((bus_space_debug & BSDB_ACCESS) != 0) && \ + (((h).bh_flags & BSHDB_ACCESS) != 0))) \ + printf s; \ + } while(0) +#define BUS_SPACE_SET_FLAGS(t, h, f) ((h).bh_flags |= (f)) +#define BUS_SPACE_CLEAR_FLAGS(t, h, f) ((h).bh_flags &= ~(f)) +#define BUS_SPACE_FLAG_DECL(s) int s +#define BUS_SPACE_SAVE_FLAGS(t, h, s) (s = (h).bh_flags) +#define BUS_SPACE_RESTORE_FLAGS(t, h, s) (s = (h).bh_flags) +#define BUS_SPACE_ASSERT(t, h, o, n) do { \ + if (bus_space_debug & BSDB_ASSERT) \ + bus_space_assert(t, &(h), o, n); \ + } while(0) +#else /* BUS_SPACE_DEBUG */ +#define BUS_SPACE_PRINTF(l, s) +#define BUS_SPACE_TRACE(t, h, s) +#define BUS_SPACE_SET_FLAGS(t, h, f) +#define BUS_SPACE_CLEAR_FLAGS(t, h, f) +#define BUS_SPACE_FLAG_DECL(s) +#define BUS_SPACE_SAVE_FLAGS(t, h, s) +#define BUS_SPACE_RESTORE_FLAGS(t, h, s) +#define BUS_SPACE_ASSERT(t, h, o, n) +#endif /* BUS_SPACE_DEBUG */ + + +/* + * UPA and SBus spaces are non-cached and big endian + * (except for RAM and PROM) + * + * PCI spaces are non-cached and little endian + */ + +enum sparc_bus_type { + UPA_BUS_SPACE, + SBUS_BUS_SPACE, + PCI_CONFIG_BUS_SPACE, + PCI_IO_BUS_SPACE, + PCI_MEMORY_BUS_SPACE, + LAST_BUS_SPACE +}; +/* For backwards compatibility */ +#define SPARC_BUS_SPACE UPA_BUS_SPACE + +/* + * Bus address and size types + */ +typedef const struct sparc_bus_space_tag *bus_space_tag_t; +typedef u_long bus_addr_t; +typedef u_long bus_size_t; + + +typedef struct _bus_space_handle { + paddr_t bh_ptr; +#ifdef BUS_SPACE_DEBUG + bus_space_tag_t bh_tag; + bus_size_t bh_size; + int bh_flags; +#endif +} bus_space_handle_t; + +/* For buses which have an iospace. */ +#define BUS_ADDR_IOSPACE(x) ((x)>>32) +#define BUS_ADDR_PADDR(x) ((x)&0xffffffff) +#define BUS_ADDR(io, pa) ((((bus_addr_t)io)<<32)|(pa)) + +/* + * Access methods for bus resources and address space. + */ + +struct sparc_bus_space_tag { + void *cookie; + bus_space_tag_t parent; + enum sparc_bus_type default_type; + u_int8_t asi; + u_int8_t sasi; + char name[32]; + + int (*sparc_bus_alloc)(bus_space_tag_t, + bus_space_tag_t, + bus_addr_t, bus_addr_t, + bus_size_t, bus_size_t, bus_size_t, + int, bus_addr_t *, bus_space_handle_t *); + + void (*sparc_bus_free)(bus_space_tag_t, + bus_space_tag_t, + bus_space_handle_t, bus_size_t); + + int (*sparc_bus_map)(bus_space_tag_t, + bus_space_tag_t, + bus_addr_t, bus_size_t, + int, bus_space_handle_t *); + + int (*sparc_bus_protect)(bus_space_tag_t, + bus_space_tag_t, + bus_space_handle_t, bus_size_t, int); + + int (*sparc_bus_unmap)(bus_space_tag_t, + bus_space_tag_t, + bus_space_handle_t, bus_size_t); + + int (*sparc_bus_subregion)(bus_space_tag_t, + bus_space_tag_t, + bus_space_handle_t, bus_size_t, + bus_size_t, bus_space_handle_t *); + + paddr_t (*sparc_bus_mmap)(bus_space_tag_t, + bus_space_tag_t, + bus_addr_t, off_t, int, int); + + void *(*sparc_intr_establish)(bus_space_tag_t, + bus_space_tag_t, + int, int, int, + int (*)(void *), void *, + const char *); + void *(*sparc_intr_establish_cpu)(bus_space_tag_t, + bus_space_tag_t, + int, int, int, + struct cpu_info *, + int (*)(void *), void *, + const char *); + + bus_addr_t (*sparc_bus_addr)(bus_space_tag_t, + bus_space_tag_t, bus_space_handle_t); +}; + +/* + * Bus space function prototypes. + */ +int bus_space_alloc( + bus_space_tag_t, + bus_addr_t, /* reg start */ + bus_addr_t, /* reg end */ + bus_size_t, /* size */ + bus_size_t, /* alignment */ + bus_size_t, /* boundary */ + int, /* flags */ + bus_addr_t *, + bus_space_handle_t *); +void bus_space_free( + bus_space_tag_t, + bus_space_handle_t, + bus_size_t); +int bus_space_map( + bus_space_tag_t, + bus_addr_t, + bus_size_t, + int, /*flags*/ + bus_space_handle_t *); +int bus_space_protect( + bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + int); /*flags*/ +int bus_space_unmap( + bus_space_tag_t, + bus_space_handle_t, + bus_size_t); +int bus_space_subregion( + bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + bus_size_t, + bus_space_handle_t *); +static void bus_space_barrier( + bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + bus_size_t, + int); +paddr_t bus_space_mmap( + bus_space_tag_t, + bus_addr_t, /*addr*/ + off_t, /*offset*/ + int, /*prot*/ + int); /*flags*/ +void *bus_intr_establish( + bus_space_tag_t, + int, /*bus-specific intr*/ + int, /*device class level, + see machine/intr.h*/ + int, /*flags*/ + int (*)(void *), /*handler*/ + void *, /*handler arg*/ + const char *); /*what*/ +void *bus_intr_establish_cpu( + bus_space_tag_t, + int, /*bus-specific intr*/ + int, /*device class level, + see machine/intr.h*/ + int, /*flags*/ + struct cpu_info *, /*cpu*/ + int (*)(void *), /*handler*/ + void *, /*handler arg*/ + const char *); /*what*/ +void *bus_intr_allocate( + bus_space_tag_t, + int (*)(void *), /*handler*/ + void *, /*handler arg*/ + int, /*number*/ + int, /*pil*/ + volatile u_int64_t *, /*map*/ + volatile u_int64_t *, /*clr*/ + const char *); /*what*/ +void bus_intr_free(void *); +void bus_space_render_tag( + bus_space_tag_t, + char *, + size_t); +void *bus_space_vaddr( + bus_space_tag_t, + bus_space_handle_t); + +#ifdef BUS_SPACE_DEBUG +void bus_space_assert(bus_space_tag_t, + const bus_space_handle_t *, + bus_size_t, int); +void bus_space_render_tag(bus_space_tag_t, char*, size_t); +#endif /* BUS_SPACE_DEBUG */ + + +#define _BS_PRECALL(t,f) \ + while (t->f == NULL) \ + t = t->parent; +#define _BS_POSTCALL + +#define _BS_CALL(t,f) \ + (*(t)->f) + +/* flags for bus_space_barrier() */ +#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ +#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ + +static inline void +bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + bus_size_t s, int f) +{ +#ifdef notyet + switch (f) { + case (BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE): + __membar("#LoadLoad|#StoreStore"); + break; + case BUS_SPACE_BARRIER_READ: + membar("#LoadLoad"); + break; + case BUS_SPACE_BARRIER_WRITE: + membar("#StoreStore"); + break; + default: + break; + } +#else + __membar("#Sync"); +#endif +} + +#include + +/* flags for bus space map functions */ +#define BUS_SPACE_MAP_CACHEABLE 0x0001 +#define BUS_SPACE_MAP_LINEAR 0x0002 +#define BUS_SPACE_MAP_READONLY 0x0004 +#define BUS_SPACE_MAP_PREFETCHABLE 0x0008 +#define BUS_SPACE_MAP_PROMADDRESS 0x0010 +#define BUS_SPACE_MAP_BUS1 0x0100 /* placeholders for bus functions... */ +#define BUS_SPACE_MAP_BUS2 0x0200 +#define BUS_SPACE_MAP_BUS3 0x0400 +#define BUS_SPACE_MAP_BUS4 0x0800 + + +/* flags for bus_intr_establish() */ +#define BUS_INTR_ESTABLISH_MPSAFE 0x0001 +#define BUS_INTR_ESTABLISH_SOFTINTR 0x0002 + +/* + * Flags used in various bus DMA methods. + */ +#define BUS_DMA_WAITOK 0x0000 /* safe to sleep (pseudo-flag) */ +#define BUS_DMA_NOWAIT 0x0001 /* not safe to sleep */ +#define BUS_DMA_ALLOCNOW 0x0002 /* perform resource allocation now */ +#define BUS_DMA_COHERENT 0x0004 /* hint: map memory DMA coherent */ +#define BUS_DMA_NOWRITE 0x0008 /* I suppose the following two should default on */ +#define BUS_DMA_BUS1 0x0010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x0020 +#define BUS_DMA_BUS3 0x0040 +#define BUS_DMA_BUS4 0x0080 +#define BUS_DMA_STREAMING 0x0100 /* hint: sequential, unidirectional */ +#define BUS_DMA_READ 0x0200 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x0400 /* mapping is memory -> device only */ +#define BUS_DMA_ZERO 0x0800 /* zero memory in dmamem_alloc */ +#define BUS_DMA_OVERRUN 0x1000 /* tolerate DMA overruns */ +#define BUS_DMA_64BIT 0x2000 /* device handles 64bit dva */ + +#define BUS_DMA_NOCACHE BUS_DMA_BUS1 +#define BUS_DMA_DVMA BUS_DMA_BUS2 /* Don't bother with alignment */ +#define BUS_DMA_24BIT BUS_DMA_BUS3 /* 24bit device */ + +#define BUS_DMA_RAW BUS_DMA_STREAMING + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct uio; + +/* + * Operations performed by bus_dmamap_sync(). + */ +#define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */ +#define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */ +#define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */ +#define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */ + +typedef struct sparc_bus_dma_tag *bus_dma_tag_t; +typedef struct sparc_bus_dmamap *bus_dmamap_t; + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +struct sparc_bus_dma_segment { + bus_addr_t ds_addr; /* DVMA address */ + bus_size_t ds_len; /* length of transfer */ + /* + * The following is to support bus_dmamem_alloc()'s + * odd interface. Only the values in the first + * segment are used. This means that 3/5ths of + * most segments are useless space (and mbufs use 1024 + * segments). + */ + bus_size_t _ds_boundary; /* don't cross this */ + bus_size_t _ds_align; /* align to this */ + void *_ds_mlist; /* XXX - dmamap_alloc'ed pages */ +}; +typedef struct sparc_bus_dma_segment bus_dma_segment_t; + + +/* + * bus_dma_tag_t + * + * A machine-dependent opaque type describing the implementation of + * DMA for a given bus. + */ +struct sparc_bus_dma_tag { + void *_cookie; /* cookie used in the guts */ + struct sparc_bus_dma_tag* _parent; + + /* + * DMA mapping methods. + */ + int (*_dmamap_create)(bus_dma_tag_t, bus_dma_tag_t, bus_size_t, + int, bus_size_t, bus_size_t, int, bus_dmamap_t *); + void (*_dmamap_destroy)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t); + int (*_dmamap_load)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, + void *, bus_size_t, struct proc *, int); + int (*_dmamap_load_mbuf)(bus_dma_tag_t, bus_dma_tag_t, + bus_dmamap_t, struct mbuf *, int); + int (*_dmamap_load_uio)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, + struct uio *, int); + int (*_dmamap_load_raw)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); + void (*_dmamap_unload)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t); + void (*_dmamap_sync)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, + bus_addr_t, bus_size_t, int); + + /* + * DMA memory utility functions. + */ + int (*_dmamem_alloc)(bus_dma_tag_t, bus_dma_tag_t, bus_size_t, + bus_size_t, bus_size_t, bus_dma_segment_t *, int, int *, + int); + void (*_dmamem_free)(bus_dma_tag_t, bus_dma_tag_t, + bus_dma_segment_t *, int); + int (*_dmamem_map)(bus_dma_tag_t, bus_dma_tag_t, + bus_dma_segment_t *, int, size_t, caddr_t *, int); + void (*_dmamem_unmap)(bus_dma_tag_t, bus_dma_tag_t, caddr_t, + size_t); + paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_tag_t, + bus_dma_segment_t *, int, off_t, int, int); +}; + +#define _BD_PRECALL(t,f) \ + while (t->f == NULL) { \ + t = t->_parent; \ + } +#define _BD_CALL(t,f) \ + (*(t)->f) +#define _BD_POSTCALL + +static inline int +bus_dmamap_create(bus_dma_tag_t t, bus_size_t s, int n, bus_size_t m, + bus_size_t b, int f, bus_dmamap_t *p) +{ + int r; + const bus_dma_tag_t t0 = t; + _BD_PRECALL(t, _dmamap_create); + r = _BD_CALL(t, _dmamap_create)(t, t0, s, n, m, b, f, p); + _BD_POSTCALL; + return (r); +} +static inline void +bus_dmamap_destroy(bus_dma_tag_t t, bus_dmamap_t p) +{ + const bus_dma_tag_t t0 = t; + _BD_PRECALL(t, _dmamap_destroy); + _BD_CALL(t, _dmamap_destroy)(t, t0, p); + _BD_POSTCALL; +} +static inline int +bus_dmamap_load(bus_dma_tag_t t, bus_dmamap_t m, void *b, bus_size_t s, + struct proc *p, int f) +{ + const bus_dma_tag_t t0 = t; + int r; + _BD_PRECALL(t, _dmamap_load); + r = _BD_CALL(t, _dmamap_load)(t, t0, m, b, s, p, f); + _BD_POSTCALL; + return (r); +} +static inline int +bus_dmamap_load_mbuf(bus_dma_tag_t t, bus_dmamap_t m, struct mbuf *b, + int f) +{ + const bus_dma_tag_t t0 = t; + int r; + _BD_PRECALL(t, _dmamap_load_mbuf); + r = _BD_CALL(t, _dmamap_load_mbuf)(t, t0, m, b, f); + _BD_POSTCALL; + return (r); +} +static inline int +bus_dmamap_load_uio(bus_dma_tag_t t, bus_dmamap_t m, struct uio * u, int f) +{ + const bus_dma_tag_t t0 = t; + int r; + _BD_PRECALL(t, _dmamap_load_uio); + r = _BD_CALL(t, _dmamap_load_uio)(t, t0, m, u, f); + _BD_POSTCALL; + return (r); +} +static inline int +bus_dmamap_load_raw(bus_dma_tag_t t, bus_dmamap_t m, bus_dma_segment_t *sg, + int n, bus_size_t s, int f) +{ + const bus_dma_tag_t t0 = t; + int r; + _BD_PRECALL(t, _dmamap_load_raw); + r = _BD_CALL(t, _dmamap_load_raw)(t, t0, m, sg, n, s, f); + _BD_POSTCALL; + return (r); +} +static inline void +bus_dmamap_unload(bus_dma_tag_t t, bus_dmamap_t p) +{ + const bus_dma_tag_t t0 = t; + _BD_PRECALL(t, _dmamap_unload); + _BD_CALL(t, _dmamap_unload)(t, t0, p); + _BD_POSTCALL; +} +static inline void +bus_dmamap_sync(bus_dma_tag_t t, bus_dmamap_t p, bus_addr_t o, bus_size_t l, + int ops) +{ + const bus_dma_tag_t t0 = t; + _BD_PRECALL(t, _dmamap_sync); + _BD_CALL(t, _dmamap_sync)(t, t0, p, o, l, ops); + _BD_POSTCALL; +} +static inline int +bus_dmamem_alloc(bus_dma_tag_t t, bus_size_t s, bus_size_t a, bus_size_t b, + bus_dma_segment_t *sg, int n, int *r, int f) +{ + const bus_dma_tag_t t0 = t; + int ret; + _BD_PRECALL(t, _dmamem_alloc); + ret = _BD_CALL(t, _dmamem_alloc)(t, t0, s, a, b, sg, n, r, f); + _BD_POSTCALL; + return (ret); +} +static inline void +bus_dmamem_free(bus_dma_tag_t t, bus_dma_segment_t *sg, int n) +{ + const bus_dma_tag_t t0 = t; + _BD_PRECALL(t, _dmamem_free); + _BD_CALL(t, _dmamem_free)(t, t0, sg, n); + _BD_POSTCALL; +} +static inline int +bus_dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *sg, int n, size_t s, + caddr_t *k, int f) +{ + const bus_dma_tag_t t0 = t; + int r; + _BD_PRECALL(t, _dmamem_map); + r = _BD_CALL(t, _dmamem_map)(t, t0, sg, n, s, k, f); + _BD_POSTCALL; + return (r); +} +static inline void +bus_dmamem_unmap(bus_dma_tag_t t, caddr_t k, size_t s) +{ + const bus_dma_tag_t t0 = t; + _BD_PRECALL(t, _dmamem_unmap); + _BD_CALL(t, _dmamem_unmap)(t, t0, k, s); + _BD_POSTCALL; +} +static inline paddr_t +bus_dmamem_mmap(bus_dma_tag_t t, bus_dma_segment_t *sg, int n, off_t o, int p, + int f) +{ + const bus_dma_tag_t t0 = t; + int r; + _BD_PRECALL(t, _dmamem_mmap); + r = _BD_CALL(t, _dmamem_mmap)(t, t0, sg, n, o, p, f); + _BD_POSTCALL; + return (r); +} + +/* + * bus_dmamap_t + * + * Describes a DMA mapping. + */ +struct sparc_bus_dmamap { + /* + * PRIVATE MEMBERS: not for use by machine-independent code. + */ + bus_addr_t _dm_dvmastart; /* start and size of allocated */ + bus_size_t _dm_dvmasize; /* DVMA segment for this map */ + + bus_size_t _dm_size; /* largest DMA transfer mappable */ + bus_size_t _dm_maxsegsz; /* largest possible segment */ + bus_size_t _dm_boundary; /* don't cross this */ + int _dm_segcnt; /* number of segs this map can map */ + int _dm_flags; /* misc. flags */ +#define _DM_TYPE_LOAD 0 +#define _DM_TYPE_SEGS 1 +#define _DM_TYPE_UIO 2 +#define _DM_TYPE_MBUF 3 + int _dm_type; /* mapping type: raw, uio, mbuf, etc */ + void *_dm_source; /* source mbuf/uio/etc. for unload */ + + void *_dm_cookie; /* cookie for bus-specific functions */ + + /* + * PUBLIC MEMBERS: these are used by machine-independent code. + */ + bus_size_t dm_mapsize; /* size of the mapping */ + int dm_nsegs; /* # valid segments in mapping */ + + bus_dma_segment_t dm_segs[1]; /* segments; variable length */ +}; + +#endif /* _KERNEL */ + +#endif /* _MACHINE_BUS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/cdefs.h b/lib/libc/include/sparc64-openbsd-none/machine/cdefs.h new file mode 100644 index 000000000000..26521d24336d --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/cdefs.h @@ -0,0 +1,16 @@ +/* $OpenBSD: cdefs.h,v 1.4 2013/03/28 17:30:45 martynas Exp $ */ + +#ifndef _MACHINE_CDEFS_H_ +#define _MACHINE_CDEFS_H_ + +#define __strong_alias(alias,sym) \ + __asm__(".global " __STRING(alias) " ; " \ + __STRING(alias) " = " __STRING(sym)) +#define __weak_alias(alias,sym) \ + __asm__(".weak " __STRING(alias) " ; " \ + __STRING(alias) " = " __STRING(sym)) +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning." __STRING(sym) \ + " ; .ascii \"" msg "\" ; .text") + +#endif /* !_MACHINE_CDEFS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/conf.h b/lib/libc/include/sparc64-openbsd-none/machine/conf.h new file mode 100644 index 000000000000..dd9ef3a150ca --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/conf.h @@ -0,0 +1,101 @@ +/* $OpenBSD: conf.h,v 1.28 2024/03/29 21:06:14 miod Exp $ */ +/* $NetBSD: conf.h,v 1.9 2001/03/26 12:33:26 lukem Exp $ */ + +/*- + * Copyright (c) 1996 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define mmread mmrw +#define mmwrite mmrw +cdev_decl(mm); + +cdev_decl(openprom); + +/* open, close, ioctl */ +#define cdev_openprom_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) nullop, 0, \ + (dev_type_mmap((*))) enodev } + +cdev_decl(uperf); + +/* open, close, ioctl */ +#define cdev_uperf_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) nullop, 0, \ + (dev_type_mmap((*))) enodev } + +cdev_decl(vdsp); + +/* open, close, ioctl */ +#define cdev_vdsp_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) nullop, 0, \ + (dev_type_mmap((*))) enodev } + +#define cdev_gen_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) nullop, \ + 0, (dev_type_mmap((*))) enodev, \ + 0, 0, dev_init(c,n,kqfilter) } + +cdev_decl(zs); + +bdev_decl(fd); +cdev_decl(fd); + +cdev_decl(bpp); +cdev_decl(lpt); + +bdev_decl(wd); +cdev_decl(wd); + +cdev_decl(sabtty); + +cdev_decl(pcons); +cdev_decl(vcons); +cdev_decl(vcctty); +cdev_decl(sbbc); + +cdev_decl(vldcp); + +cdev_decl(com); + +cdev_decl(mtty); +cdev_decl(mbpp); +cdev_decl(stty); +cdev_decl(sbpp); + +/* open, close, write, ioctl */ +#define cdev_bpp_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) nullop, \ + 0, (dev_type_mmap((*))) enodev, 0, 0, seltrue_kqfilter } \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/cpu.h b/lib/libc/include/sparc64-openbsd-none/machine/cpu.h new file mode 100644 index 000000000000..e5535fb38275 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/cpu.h @@ -0,0 +1,384 @@ +/* $OpenBSD: cpu.h,v 1.109 2024/11/06 12:06:15 miod Exp $ */ +/* $NetBSD: cpu.h,v 1.28 2001/06/14 22:56:58 thorpej Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)cpu.h 8.4 (Berkeley) 1/5/94 + */ + +#ifndef _MACHINE_CPU_H_ +#define _MACHINE_CPU_H_ + +/* + * CTL_MACHDEP definitions. + */ + /* 1 formerly: booted kernel name */ +#define CPU_LED_BLINK 2 /* int: blink leds? */ +#define CPU_ALLOWAPERTURE 3 /* allow xf86 operations */ +#define CPU_CPUTYPE 4 /* cpu type */ +#define CPU_CECCERRORS 5 /* Correctable ECC errors */ +#define CPU_CECCLAST 6 /* Correctable ECC last fault addr */ + /* 7 formerly: soft reset via keyboard */ +#define CPU_MAXID 8 /* number of valid machdep ids */ + +#define CTL_MACHDEP_NAMES { \ + { 0, 0 }, \ + { 0, 0 }, \ + { "led_blink", CTLTYPE_INT }, \ + { "allowaperture", CTLTYPE_INT }, \ + { "cputype", CTLTYPE_INT }, \ + { "ceccerrs", CTLTYPE_INT }, \ + { "cecclast", CTLTYPE_QUAD }, \ + { 0, 0 }, \ +} + +#ifdef _KERNEL +/* + * Exported definitions unique to SPARC cpu support. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* + * The cpu_info structure is part of a 64KB structure mapped both the kernel + * pmap and a single locked TTE a CPUINFO_VA for that particular processor. + * Each processor's cpu_info is accessible at CPUINFO_VA only for that + * processor. Other processors can access that through an additional mapping + * in the kernel pmap. + * + * The 64KB page contains: + * + * cpu_info + * interrupt stack (all remaining space) + * idle PCB + * idle stack (STACKSPACE - sizeof(PCB)) + * 32KB TSB + */ + +struct cpu_info { + /* + * SPARC cpu_info structures live at two VAs: one global + * VA (so each CPU can access any other CPU's cpu_info) + * and an alias VA CPUINFO_VA which is the same on each + * CPU and maps to that CPU's cpu_info. Since the alias + * CPUINFO_VA is how we locate our cpu_info, we have to + * self-reference the global VA so that we can return it + * in the curcpu() macro. + */ + struct cpu_info * volatile ci_self; + + /* Most important fields first */ + struct proc *ci_curproc; + struct pcb *ci_cpcb; /* also initial stack */ + paddr_t ci_cpcbpaddr; + struct cpu_info *ci_next; + + struct proc *ci_fpproc; + int ci_cpuid; + int ci_flags; + int ci_upaid; +#ifdef MULTIPROCESSOR + int ci_itid; + struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM]; +#define __HAVE_UVM_PERCPU + struct uvm_pmr_cache ci_uvm; /* [o] page cache */ +#endif + int ci_node; + u_int32_t ci_randseed; + struct schedstate_percpu ci_schedstate; /* scheduler state */ + + int ci_want_resched; + int ci_handled_intr_level; + int ci_idepth; + struct intrhand *ci_intrpending[16]; + struct clockqueue ci_queue; + struct intrhand ci_tickintr; + + volatile int ci_ddb_paused; +#define CI_DDB_RUNNING 0 +#define CI_DDB_SHOULDSTOP 1 +#define CI_DDB_STOPPED 2 +#define CI_DDB_ENTERDDB 3 +#define CI_DDB_INDDB 4 + + /* Spinning up the CPU */ + void (*ci_spinup)(void); /* spinup routine */ + void *ci_initstack; + paddr_t ci_paddr; /* Phys addr of this structure. */ + +#ifdef SUN4V + struct rwindow ci_rw; + u_int64_t ci_rwsp; + + paddr_t ci_mmfsa; + paddr_t ci_cpumq; + paddr_t ci_devmq; + + paddr_t ci_cpuset; + paddr_t ci_mondo; +#endif + + int ci_pci_probe; + int ci_pci_fault; + +#ifdef DIAGNOSTIC + int ci_mutex_level; +#endif +#ifdef GPROF + struct gmonparam *ci_gmon; + struct clockintr ci_gmonclock; +#endif + char ci_panicbuf[512]; +}; + +#define CPUF_RUNNING 0x0001 /* CPU is running */ + +extern struct cpu_info *cpus; + +#ifdef MULTIPROCESSOR + +register struct cpu_info *__curcpu asm ("g7"); + +#define curcpu() (__curcpu->ci_self) +#define cpu_number() (__curcpu->ci_cpuid) + +#define CPU_IS_PRIMARY(ci) ((ci)->ci_cpuid == 0) +#define CPU_IS_RUNNING(ci) 1 +#define CPU_INFO_ITERATOR int +#define CPU_INFO_FOREACH(cii, ci) \ + for (cii = 0, ci = cpus; ci != NULL; ci = ci->ci_next) +#define CPU_INFO_UNIT(ci) ((ci)->ci_cpuid) +#define MAXCPUS 256 + +void cpu_boot_secondary_processors(void); + +void sparc64_send_ipi(int, void (*)(void), u_int64_t, u_int64_t); +void sparc64_broadcast_ipi(void (*)(void), u_int64_t, u_int64_t); + +void cpu_unidle(struct cpu_info *); + +#else /* MULTIPROCESSOR */ + +#define __curcpu ((struct cpu_info *)CPUINFO_VA) +#define curcpu() __curcpu +#define cpu_number() 0 + +#define CPU_IS_PRIMARY(ci) 1 +#define CPU_IS_RUNNING(ci) 1 +#define CPU_INFO_ITERATOR int +#define CPU_INFO_FOREACH(cii, ci) \ + for (cii = 0, ci = curcpu(); ci != NULL; ci = NULL) +#define CPU_INFO_UNIT(ci) 0 +#define MAXCPUS 1 + +#define cpu_unidle(ci) + +#endif /* MULTIPROCESSOR */ + +#define curpcb __curcpu->ci_cpcb +#define fpproc __curcpu->ci_fpproc + +static inline unsigned int +cpu_rnd_messybits(void) +{ + u_int64_t tick; + + __asm volatile("rd %%tick, %0" : "=r" (tick) :); + + return ((tick >> 32) ^ tick); +} + +/* + * On processors with multiple threads we force a thread switch. + * + * On UltraSPARC T2 and its successors, the optimal way to do this + * seems to be to do three nop reads of %ccr. This works on + * UltraSPARC T1 as well, even though three nop casx operations seem + * to be slightly more optimal. Since these instructions are + * effectively nops, executing them on earlier non-CMT processors is + * harmless, so we make this the default. + * + * On SPARC T4 and later, we can use the processor-specific pause + * instruction. + * + * On SPARC64 VI and its successors we execute the processor-specific + * sleep instruction. + */ +#define CPU_BUSY_CYCLE() \ +do { \ + __asm volatile( \ + "999: rd %%ccr, %%g0 \n" \ + " rd %%ccr, %%g0 \n" \ + " rd %%ccr, %%g0 \n" \ + " .section .sun4v_pause_patch, \"ax\" \n" \ + " .word 999b \n" \ + " .word 0xb7802080 ! pause 128 \n" \ + " .word 999b + 4 \n" \ + " nop \n" \ + " .word 999b + 8 \n" \ + " nop \n" \ + " .previous \n" \ + " .section .sun4u_mtp_patch, \"ax\" \n" \ + " .word 999b \n" \ + " .word 0x81b01060 ! sleep \n" \ + " .word 999b + 4 \n" \ + " nop \n" \ + " .word 999b + 8 \n" \ + " nop \n" \ + " .previous \n" \ + : : : "memory"); \ +} while (0) + +/* + * Arguments to clockintr_dispatch encapsulate the + * previous machine state in an opaque clockframe. + */ +struct clockframe { + struct trapframe t; + int saved_intr_level; +}; + +#define CLKF_USERMODE(framep) (((framep)->t.tf_tstate & TSTATE_PRIV) == 0) +#define CLKF_PC(framep) ((framep)->t.tf_pc) +#define CLKF_INTR(framep) ((framep)->saved_intr_level != 0) + +extern void (*cpu_start_clock)(void); + +#define aston(p) ((p)->p_md.md_astpending = 1) + +/* + * Preempt the current process if in interrupt from user mode, + * or after the current trap/syscall if in system mode. + */ +extern void need_resched(struct cpu_info *); +#define clear_resched(ci) (ci)->ci_want_resched = 0 + +/* + * This is used during profiling to integrate system time. + */ +#define PROC_PC(p) ((p)->p_md.md_tf->tf_pc) +#define PROC_STACK(p) ((p)->p_md.md_tf->tf_out[6] + (2048-1)) /* BIAS */ + +/* + * Give a profiling tick to the current process when the user profiling + * buffer pages are invalid. On the sparc, request an ast to send us + * through trap(), marking the proc as needing a profiling tick. + */ +#define need_proftick(p) aston(p) + +void signotify(struct proc *); + +/* cpu.c */ +int cpu_myid(void); +/* machdep.c */ +void dumpconf(void); +caddr_t reserve_dumppages(caddr_t); +/* clock.c */ +struct timeval; +int clockintr(void *);/* level 10 (clock) interrupt code */ +/* locore.s */ +struct fpstate; +void savefpstate(struct fpstate *); +void loadfpstate(struct fpstate *); +void clearfpstate(void); +u_int64_t probeget(paddr_t, int, int); +#define write_all_windows() __asm volatile("flushw" : : ) +void write_user_windows(void); +void proc_trampoline(void); +struct pcb; +void snapshot(struct pcb *); +struct frame *getfp(void); +void switchtoctx(int); +/* trap.c */ +void pmap_unuse_final(struct proc *); +int rwindow_save(struct proc *); +/* vm_machdep.c */ +void fpusave_cpu(struct cpu_info *, int); +void fpusave_proc(struct proc *, int); +/* fb.c */ +void fb_unblank(void); +/* ltc.c */ +void ltc_full_blast(void); +/* tda.c */ +void tda_full_blast(void); +/* emul.c */ +int emul_qf(int32_t, struct proc *, union sigval, struct trapframe *); +int emul_popc(int32_t, struct proc *, union sigval, struct trapframe *); + +/* + * + * The SPARC has a Trap Base Register (TBR) which holds the upper 20 bits + * of the trap vector table. The next eight bits are supplied by the + * hardware when the trap occurs, and the bottom four bits are always + * zero (so that we can shove up to 16 bytes of executable code---exactly + * four instructions---into each trap vector). + * + * The hardware allocates half the trap vectors to hardware and half to + * software. + * + * Traps have priorities assigned (lower number => higher priority). + */ + +struct trapvec { + int tv_instr[8]; /* the eight instructions */ +}; +extern struct trapvec trapbase[]; /* the 256 vectors */ + +struct blink_led { + void (*bl_func)(void *, int); + void *bl_arg; + SLIST_ENTRY(blink_led) bl_next; +}; + +extern void blink_led_register(struct blink_led *); + +#ifdef MULTIPROCESSOR +#include +#endif + +#endif /* _KERNEL */ +#endif /* _MACHINE_CPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/ctlreg.h b/lib/libc/include/sparc64-openbsd-none/machine/ctlreg.h new file mode 100644 index 000000000000..6120cae56e03 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/ctlreg.h @@ -0,0 +1,715 @@ +/* $OpenBSD: ctlreg.h,v 1.33 2025/07/16 07:15:42 jsg Exp $ */ +/* $NetBSD: ctlreg.h,v 1.28 2001/08/06 23:55:34 eeh Exp $ */ + +/* + * Copyright (c) 1996-2001 Eduardo Horvath + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/* + * Copyright (c) 2001 Jake Burkholder. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _SPARC64_CTLREG_ +#define _SPARC64_CTLREG_ + +/* + * Sun 4u control registers. (includes address space definitions + * and some registers in control space). + */ + +/* + * The Alternate address spaces. + * + * 0x00-0x7f are privileged + * 0x80-0xff can be used by users + */ + +#define ASI_LITTLE 0x08 /* This bit should make an ASI little endian */ + +#define ASI_NUCLEUS 0x04 /* [4u] kernel address space */ +#define ASI_NUCLEUS_LITTLE 0x0c /* [4u] kernel address space, little endian */ + +#define ASI_AS_IF_USER_PRIMARY 0x10 /* [4u] primary user address space */ +#define ASI_AS_IF_USER_SECONDARY 0x11 /* [4u] secondary user address space */ + +#define ASI_PHYS_CACHED 0x14 /* [4u] MMU bypass to main memory */ +#define ASI_PHYS_NON_CACHED 0x15 /* [4u] MMU bypass to I/O location */ + +#define ASI_AS_IF_USER_PRIMARY_LITTLE 0x18 /* [4u] primary user address space, little endian */ +#define ASI_AS_IF_USER_SECONDARY_LITTIE 0x19 /* [4u] secondary user address space, little endian */ + +#define ASI_PHYS_CACHED_LITTLE 0x1c /* [4u] MMU bypass to main memory, little endian */ +#define ASI_PHYS_NON_CACHED_LITTLE 0x1d /* [4u] MMU bypass to I/O location, little endian */ + +#define ASI_SCRATCHPAD 0x20 /* [4v] scratchpad registers */ +#define ASI_MMU_CONTEXTID 0x21 /* [4v] MMU context */ + +#define ASI_NUCLEUS_QUAD_LDD 0x24 /* [4u] use w/LDDA to load 128-bit item */ +#define ASI_QUEUE 0x25 /* [4v] interrupt queue registers */ +#define ASI_NUCLEUS_QUAD_LDD_LITTLE 0x2c /* [4u] use w/LDDA to load 128-bit item, little endian */ + +#define ASI_FLUSH_D_PAGE_PRIMARY 0x38 /* [4u] flush D-cache page using primary context */ +#define ASI_FLUSH_D_PAGE_SECONDARY 0x39 /* [4u] flush D-cache page using secondary context */ +#define ASI_FLUSH_D_CTX_PRIMARY 0x3a /* [4u] flush D-cache context using primary context */ +#define ASI_FLUSH_D_CTX_SECONDARY 0x3b /* [4u] flush D-cache context using secondary context */ + +#define ASI_DCACHE_INVALIDATE 0x42 /* [III] invalidate D-cache */ +#define ASI_DCACHE_UTAG 0x43 /* [III] diagnostic access to D-cache micro tag */ +#define ASI_DCACHE_SNOOP_TAG 0x44 /* [III] diagnostic access to D-cache snoop tag RAM */ + +#define ASI_LSU_CONTROL_REGISTER 0x45 /* [4u] load/store unit control register */ + +#define ASI_DCACHE_DATA 0x46 /* [4u] diagnostic access to D-cache data RAM */ +#define ASI_DCACHE_TAG 0x47 /* [4u] diagnostic access to D-cache tag RAM */ + +#define ASI_INTR_DISPATCH_STATUS 0x48 /* [4u] interrupt dispatch status register */ +#define ASI_INTR_RECEIVE 0x49 /* [4u] interrupt receive status register */ +#define ASI_MID_REG 0x4a /* [4u] hardware config and MID */ +#define ASI_ERROR_EN_REG 0x4b /* [4u] asynchronous error enables */ +#define ASI_AFSR 0x4c /* [4u] asynchronous fault status register */ +#define ASI_AFAR 0x4d /* [4u] asynchronous fault address register */ + +#define ASI_SCRATCH 0x4f /* [VI] scratch registers */ + +#define ASI_ICACHE_DATA 0x66 /* [4u] diagnostic access to D-cache data RAM */ +#define ASI_ICACHE_TAG 0x67 /* [4u] diagnostic access to D-cache tag RAM */ +#define ASI_FLUSH_I_PAGE_PRIMARY 0x68 /* [4u] flush D-cache page using primary context */ +#define ASI_FLUSH_I_PAGE_SECONDARY 0x69 /* [4u] flush D-cache page using secondary context */ +#define ASI_FLUSH_I_CTX_PRIMARY 0x6a /* [4u] flush D-cache context using primary context */ +#define ASI_FLUSH_I_CTX_SECONDARY 0x6b /* [4u] flush D-cache context using secondary context */ + +#define ASI_BLOCK_AS_IF_USER_PRIMARY 0x70 /* [4u] primary user address space, block loads/stores */ +#define ASI_BLOCK_AS_IF_USER_SECONDARY 0x71 /* [4u] secondary user address space, block loads/stores */ + +#define ASI_ECACHE_DIAG 0x76 /* [4u] diag access to E-cache tag and data */ +#define ASI_DATAPATH_ERR_REG_WRITE 0x77 /* [4u] ASI is reused */ + +#define ASI_BLOCK_AS_IF_USER_PRIMARY_LITTLE 0x78 /* [4u] primary user address space, block loads/stores */ +#define ASI_BLOCK_AS_IF_USER_SECONDARY_LITTLE 0x79 /* [4u] secondary user address space, block loads/stores */ + +#define ASI_INTERRUPT_RECEIVE_DATA 0x7f /* [4u] interrupt receive data registers {0,1,2} */ +#define ASI_DATAPATH_ERR_REG_READ 0x7f /* [4u] read access to datapath error registers (ASI reused) */ + +#define ASI_PRIMARY 0x80 /* [4u] primary address space */ +#define ASI_SECONDARY 0x81 /* [4u] secondary address space */ +#define ASI_PRIMARY_NOFAULT 0x82 /* [4u] primary address space, no fault */ +#define ASI_SECONDARY_NOFAULT 0x83 /* [4u] secondary address space, no fault */ + +#define ASI_PRIMARY_LITTLE 0x88 /* [4u] primary address space, little endian */ +#define ASI_SECONDARY_LITTLE 0x89 /* [4u] secondary address space, little endian */ +#define ASI_PRIMARY_NOFAULT_LITTLE 0x8a /* [4u] primary address space, no fault, little endian */ +#define ASI_SECONDARY_NOFAULT_LITTLE 0x8b /* [4u] secondary address space, no fault, little endian */ + +#define ASI_PST8_PRIMARY 0xc0 /* [VIS] Eight 8-bit partial store, primary */ +#define ASI_PST8_SECONDARY 0xc1 /* [VIS] Eight 8-bit partial store, secondary */ +#define ASI_PST16_PRIMARY 0xc2 /* [VIS] Four 16-bit partial store, primary */ +#define ASI_PST16_SECONDARY 0xc3 /* [VIS] Fout 16-bit partial store, secondary */ +#define ASI_PST32_PRIMARY 0xc4 /* [VIS] Two 32-bit partial store, primary */ +#define ASI_PST32_SECONDARY 0xc5 /* [VIS] Two 32-bit partial store, secondary */ + +#define ASI_PST8_PRIMARY_LITTLE 0xc8 /* [VIS] Eight 8-bit partial store, primary, little endian */ +#define ASI_PST8_SECONDARY_LITTLE 0xc9 /* [VIS] Eight 8-bit partial store, secondary, little endian */ +#define ASI_PST16_PRIMARY_LITTLE 0xca /* [VIS] Four 16-bit partial store, primary, little endian */ +#define ASI_PST16_SECONDARY_LITTLE 0xcb /* [VIS] Fout 16-bit partial store, secondary, little endian */ +#define ASI_PST32_PRIMARY_LITTLE 0xcc /* [VIS] Two 32-bit partial store, primary, little endian */ +#define ASI_PST32_SECONDARY_LITTLE 0xcd /* [VIS] Two 32-bit partial store, secondary, little endian */ + +#define ASI_FL8_PRIMARY 0xd0 /* [VIS] One 8-bit load/store floating, primary */ +#define ASI_FL8_SECONDARY 0xd1 /* [VIS] One 8-bit load/store floating, secondary */ +#define ASI_FL16_PRIMARY 0xd2 /* [VIS] One 16-bit load/store floating, primary */ +#define ASI_FL16_SECONDARY 0xd3 /* [VIS] One 16-bit load/store floating, secondary */ + +#define ASI_FL8_PRIMARY_LITTLE 0xd8 /* [VIS] One 8-bit load/store floating, primary, little endian */ +#define ASI_FL8_SECONDARY_LITTLE 0xd9 /* [VIS] One 8-bit load/store floating, secondary, little endian */ +#define ASI_FL16_PRIMARY_LITTLE 0xda /* [VIS] One 16-bit load/store floating, primary, little endian */ +#define ASI_FL16_SECONDARY_LITTLE 0xdb /* [VIS] One 16-bit load/store floating, secondary, little endian */ + +#define ASI_BLOCK_COMMIT_PRIMARY 0xe0 /* [4u] block store with commit, primary */ +#define ASI_BLOCK_COMMIT_SECONDARY 0xe1 /* [4u] block store with commit, secondary */ +#define ASI_BLOCK_PRIMARY 0xf0 /* [4u] block load/store, primary */ +#define ASI_BLOCK_SECONDARY 0xf1 /* [4u] block load/store, secondary */ +#define ASI_BLOCK_PRIMARY_LITTLE 0xf8 /* [4u] block load/store, primary, little endian */ +#define ASI_BLOCK_SECONDARY_LITTLE 0xf9 /* [4u] block load/store, secondary, little endian */ + + +/* + * These are the shorter names used by Solaris + */ + +#define ASI_N ASI_NUCLEUS +#define ASI_NL ASI_NUCLEUS_LITTLE +#define ASI_AIUP ASI_AS_IF_USER_PRIMARY +#define ASI_AIUS ASI_AS_IF_USER_SECONDARY +#define ASI_AIUPL ASI_AS_IF_USER_PRIMARY_LITTLE +#define ASI_AIUSL ASI_AS_IF_USER_SECONDARY_LITTLE +#define ASI_P ASI_PRIMARY +#define ASI_S ASI_SECONDARY +#define ASI_PNF ASI_PRIMARY_NOFAULT +#define ASI_SNF ASI_SECONDARY_NOFAULT +#define ASI_PL ASI_PRIMARY_LITTLE +#define ASI_SL ASI_SECONDARY_LITTLE +#define ASI_PNFL ASI_PRIMARY_NOFAULT_LITTLE +#define ASI_SNFL ASI_SECONDARY_NOFAULT_LITTLE +#define ASI_FL8_P ASI_FL8_PRIMARY +#define ASI_FL8_S ASI_FL8_SECONDARY +#define ASI_FL16_P ASI_FL16_PRIMARY +#define ASI_FL16_S ASI_FL16_SECONDARY +#define ASI_FL8_PL ASI_FL8_PRIMARY_LITTLE +#define ASI_FL8_SL ASI_FL8_SECONDARY_LITTLE +#define ASI_FL16_PL ASI_FL16_PRIMARY_LITTLE +#define ASI_FL16_SL ASI_FL16_SECONDARY_LITTLE +#define ASI_BLK_AIUP ASI_BLOCK_AS_IF_USER_PRIMARY +#define ASI_BLK_AIUPL ASI_BLOCK_AS_IF_USER_PRIMARY_LITTLE +#define ASI_BLK_AIUS ASI_BLOCK_AS_IF_USER_SECONDARY +#define ASI_BLK_AIUSL ASI_BLOCK_AS_IF_USER_SECONDARY_LITTLE +#define ASI_BLK_COMMIT_P ASI_BLOCK_COMMIT_PRIMARY +#define ASI_BLK_COMMIT_PRIMARY ASI_BLOCK_COMMIT_PRIMARY +#define ASI_BLK_COMMIT_S ASI_BLOCK_COMMIT_SECONDARY +#define ASI_BLK_COMMIT_SECONDARY ASI_BLOCK_COMMIT_SECONDARY +#define ASI_BLK_P ASI_BLOCK_PRIMARY +#define ASI_BLK_PL ASI_BLOCK_PRIMARY_LITTLE +#define ASI_BLK_S ASI_BLOCK_SECONDARY +#define ASI_BLK_SL ASI_BLOCK_SECONDARY_LITTLE + +/* Alternative spellings */ +#define ASI_PRIMARY_NO_FAULT ASI_PRIMARY_NOFAULT +#define ASI_PRIMARY_NO_FAULT_LITTLE ASI_PRIMARY_NOFAULT_LITTLE +#define ASI_SECONDARY_NO_FAULT ASI_SECONDARY_NOFAULT +#define ASI_SECONDARY_NO_FAULT_LITTLE ASI_SECONDARY_NOFAULT_LITTLE + +#define PHYS_ASI(x) (((x) | 0x09) == 0x1d) +#define LITTLE_ASI(x) ((x) & ASI_LITTLE) + +/* + * %tick: cpu cycle counter + */ +#define TICK_NPT 0x8000000000000000 /* trap on non priv access */ +#define TICK_TICKS 0x7fffffffffffffff /* counter bits */ + +/* + * The following are 4u control registers + */ + +/* Get the CPU's UPA port ID */ +#define UPA_CR_MID(x) (((x) >> 17) & 0x1f) +#define CPU_UPAID UPA_CR_MID(ldxa(0, ASI_MID_REG)) + +/* Get the CPU's Fireplane agent ID */ +#define FIREPLANE_CR_AID(x) (((x) >> 17) & 0x3ff) +#define CPU_FIREPLANEID FIREPLANE_CR_AID(ldxa(0, ASI_MID_REG)) + +/* Get the CPU's Jupiter Bus interrupt target ID */ +#define JUPITER_CR_ITID(x) ((x) & 0x3ff) +#define CPU_JUPITERID JUPITER_CR_ITID(ldxa(0, ASI_MID_REG)) + +/* + * [4u] MMU and Cache Control Register (MCCR) + * use ASI = 0x45 + */ +#define ASI_MCCR ASI_LSU_CONTROL_REGISTER +#define MCCR 0x00 + +/* MCCR Bits and their meanings */ +#define MCCR_DMMU_EN 0x08 +#define MCCR_IMMU_EN 0x04 +#define MCCR_DCACHE_EN 0x02 +#define MCCR_ICACHE_EN 0x01 + + +/* + * MMU control registers + */ + +/* Choose an MMU */ +#define ASI_DMMU 0x58 +#define ASI_IMMU 0x50 + +/* Other assorted MMU ASIs */ +#define ASI_IMMU_8KPTR 0x51 +#define ASI_IMMU_64KPTR 0x52 +#define ASI_IMMU_DATA_IN 0x54 +#define ASI_IMMU_TLB_DATA 0x55 +#define ASI_IMMU_TLB_TAG 0x56 +#define ASI_DMMU_8KPTR 0x59 +#define ASI_DMMU_64KPTR 0x5a +#define ASI_DMMU_DATA_IN 0x5c +#define ASI_DMMU_TLB_DATA 0x5d +#define ASI_DMMU_TLB_TAG 0x5e + +/* + * The following are the control registers + * They work on both MMUs unless noted. + * III = cheetah only + * + * Register contents are defined later on individual registers. + */ +#define TSB_TAG_TARGET 0x0 +#define TLB_DATA_IN 0x0 +#define CTX_PRIMARY 0x08 /* primary context -- DMMU only */ +#define CTX_SECONDARY 0x10 /* secondary context -- DMMU only */ +#define SFSR 0x18 +#define SFAR 0x20 /* fault address -- DMMU only */ +#define TSB 0x28 +#define TLB_TAG_ACCESS 0x30 +#define VIRTUAL_WATCHPOINT 0x38 +#define PHYSICAL_WATCHPOINT 0x40 +#define TSB_PEXT 0x48 /* III primary ext */ +#define TSB_SEXT 0x50 /* III 2ndary ext -- DMMU only */ +#define TSB_NEXT 0x58 /* III nucleus ext */ + +/* Tag Target bits */ +#define TAG_TARGET_VA_MASK 0x03ffffffffffffffffLL +#define TAG_TARGET_VA(x) (((x)<<22)&TAG_TARGET_VA_MASK) +#define TAG_TARGET_CONTEXT(x) ((x)>>48) +#define TAG_TARGET(c,v) ((((uint64_t)c)<<48)|(((uint64_t)v)&TAG_TARGET_VA_MASK)) + +/* SFSR bits for both D_SFSR and I_SFSR */ +#define SFSR_NF 0x1000000 /* Non-faulting load */ +#define SFSR_ASI(x) ((x)>>16) +#define SFSR_TM 0x0008000 /* TLB miss */ +#define SFSR_FT_VA_OOR_2 0x0002000 /* IMMU: jumpl or return to unsupported VA */ +#define SFSR_FT_VA_OOR_1 0x0001000 /* fault at unsupported VA */ +#define SFSR_FT_NFO 0x0000800 /* DMMU: Access to page marked NFO */ +#define SFSR_ILL_ASI 0x0000400 /* DMMU: Illegal (unsupported) ASI */ +#define SFSR_FT_IO_ATOMIC 0x0000200 /* DMMU: Atomic access to noncacheable page */ +#define SFSR_FT_ILL_NF 0x0000100 /* DMMU: NF load or flush to page marked E (has side effects) */ +#define SFSR_FT_PRIV 0x0000080 /* Privilege violation */ +#define SFSR_FT_E 0x0000040 /* DMUU: value of E bit associated address */ +#define SFSR_CTXT(x) (((x)>>4)&0x3) +#define SFSR_CTXT_IS_PRIM(x) (SFSR_CTXT(x)==0x00) +#define SFSR_CTXT_IS_SECOND(x) (SFSR_CTXT(x)==0x01) +#define SFSR_CTXT_IS_NUCLEUS(x) (SFSR_CTXT(x)==0x02) +#define SFSR_PRIV 0x0000008 /* value of PSTATE.PRIV for faulting access */ +#define SFSR_W 0x0000004 /* DMMU: attempted write */ +#define SFSR_OW 0x0000002 /* Overwrite; prev fault was still valid */ +#define SFSR_FV 0x0000001 /* Fault is valid */ +#define SFSR_FT (SFSR_FT_VA_OOR_2|SFSR_FT_VA_OOR_1|SFSR_FT_NFO|SFSR_ILL_ASI|SFSR_FT_IO_ATOMIC|SFSR_FT_ILL_NF|SFSR_FT_PRIV) + +#define SFSR_BITS "\20\31NF\20TM\16VAT\15VAD\14NFO\13ASI\12A\11NF\10PRIV\7E\6NUCLEUS\5SECONDCTX\4PRIV\3W\2OW\1FV" + +/* ASFR bits */ +#define ASFR_ME 0x100000000LL +#define ASFR_PRIV 0x080000000LL +#define ASFR_ISAP 0x040000000LL +#define ASFR_ETP 0x020000000LL +#define ASFR_IVUE 0x010000000LL +#define ASFR_TO 0x008000000LL +#define ASFR_BERR 0x004000000LL +#define ASFR_LDP 0x002000000LL +#define ASFR_CP 0x001000000LL +#define ASFR_WP 0x000800000LL +#define ASFR_EDP 0x000400000LL +#define ASFR_UE 0x000200000LL +#define ASFR_CE 0x000100000LL +#define ASFR_ETS 0x0000f0000LL +#define ASFT_P_SYND 0x00000ffffLL + +#define AFSR_BITS "\20" \ + "\20ME\37PRIV\36ISAP\35ETP\34IVUE\33TO\32BERR\31LDP\30CP\27WP\26EDP" \ + "\25UE\24CE" + +/* + * Here's the spitfire TSB control register bits. + * + * Each TSB entry is 16-bytes wide. The TSB must be size aligned + */ +#define TSB_SIZE_512 0x0 /* 8kB, etc. */ +#define TSB_SIZE_1K 0x01 +#define TSB_SIZE_2K 0x02 +#define TSB_SIZE_4K 0x03 +#define TSB_SIZE_8K 0x04 +#define TSB_SIZE_16K 0x05 +#define TSB_SIZE_32K 0x06 +#define TSB_SIZE_64K 0x07 +#define TSB_SPLIT 0x1000 +#define TSB_BASE 0xffffffffffffe000 + +/* TLB Tag Access bits */ +#define TLB_TAG_ACCESS_VA 0xffffffffffffe000 +#define TLB_TAG_ACCESS_CTX 0x0000000000001fff + +/* + * TLB demap registers. TTEs are defined in v9pte.h + * + * Use the address space to select between IMMU and DMMU. + * The address of the register selects which context register + * to read the ASI from. + * + * The data stored in the register is interpreted as the VA to + * use. The DEMAP_CTX_<> registers ignore the address and demap the + * entire ASI. + * + */ +#define ASI_IMMU_DEMAP 0x57 /* [4u] IMMU TLB demap */ +#define ASI_DMMU_DEMAP 0x5f /* [4u] IMMU TLB demap */ + +#define DEMAP_PAGE_NUCLEUS ((0x02)<<4) /* Demap page from kernel AS */ +#define DEMAP_PAGE_PRIMARY ((0x00)<<4) /* Demap a page from primary CTXT */ +#define DEMAP_PAGE_SECONDARY ((0x01)<<4) /* Demap page from secondary CTXT (DMMU only) */ +#define DEMAP_CTX_NUCLEUS ((0x06)<<4) /* Demap all of kernel CTXT */ +#define DEMAP_CTX_PRIMARY ((0x04)<<4) /* Demap all of primary CTXT */ +#define DEMAP_CTX_SECONDARY ((0x05)<<4) /* Demap all of secondary CTXT */ + +/* + * Interrupt registers. This really gets hairy. + */ + +/* IRSR -- Interrupt Receive Status Register */ +#define ASI_IRSR 0x49 +#define IRSR 0x00 +#define IRSR_BUSY 0x020 +#define IRSR_MID(x) (x&0x1f) + +/* IRDR -- Interrupt Receive Data Registers */ +#define ASI_IRDR 0x7f +#define IRDR_0H 0x40 +#define IRDR_0L 0x48 /* unimplemented */ +#define IRDR_1H 0x50 +#define IRDR_1L 0x58 /* unimplemented */ +#define IRDR_2H 0x60 +#define IRDR_2L 0x68 /* unimplemented */ +#define IRDR_3H 0x70 /* unimplemented */ +#define IRDR_3L 0x78 /* unimplemented */ + +/* SOFTINT ASRs */ +#define SET_SOFTINT %asr20 /* Sets these bits */ +#define CLEAR_SOFTINT %asr21 /* Clears these bits */ +#define SOFTINT %asr22 /* Reads the register */ +#define TICK_CMPR %asr23 + +#define TICK_INT 0x01 /* level-14 clock tick */ +#define SOFTINT1 (0x1<<1) +#define SOFTINT2 (0x1<<2) +#define SOFTINT3 (0x1<<3) +#define SOFTINT4 (0x1<<4) +#define SOFTINT5 (0x1<<5) +#define SOFTINT6 (0x1<<6) +#define SOFTINT7 (0x1<<7) +#define SOFTINT8 (0x1<<8) +#define SOFTINT9 (0x1<<9) +#define SOFTINT10 (0x1<<10) +#define SOFTINT11 (0x1<<11) +#define SOFTINT12 (0x1<<12) +#define SOFTINT13 (0x1<<13) +#define SOFTINT14 (0x1<<14) +#define SOFTINT15 (0x1<<15) +#define STICK_INT (0x1<<16) + +/* Interrupt Dispatch -- usually reserved for cross-calls */ +#define ASR_IDSR 0x48 /* Interrupt dispatch status reg */ +#define IDSR 0x00 +#define IDSR_NACK 0x02 +#define IDSR_BUSY 0x01 + +#define ASI_INTERRUPT_DISPATCH 0x77 /* [4u] spitfire interrupt dispatch regs */ + +/* Interrupt delivery initiation */ +#define IDCR(x) ((((u_int64_t)(x)) << 14) | 0x70) + +#define IDDR_0H 0x40 /* Store data to send in these regs */ +#define IDDR_0L 0x48 /* unimplemented */ +#define IDDR_1H 0x50 +#define IDDR_1L 0x58 /* unimplemented */ +#define IDDR_2H 0x60 +#define IDDR_2L 0x68 /* unimplemented */ +#define IDDR_3H 0x80 /* unimplemented */ +#define IDDR_3L 0x88 /* unimplemented */ + +/* + * Error registers + */ + +/* Since we won't try to fix async errs, we don't care about the bits in the regs */ +#define ASI_AFAR 0x4d /* Asynchronous fault address register */ +#define AFAR 0x00 +#define ASI_AFSR 0x4c /* Asynchronous fault status register */ +#define AFSR 0x00 + +#define ASI_P_EER 0x4b /* Error enable register */ +#define P_EER 0x00 +#define P_EER_ISAPEN 0x04 /* Enable fatal on ISAP */ +#define P_EER_NCEEN 0x02 /* Enable trap on uncorrectable errs */ +#define P_EER_CEEN 0x01 /* Enable trap on correctable errs */ + +#define ASI_DATAPATH_READ 0x7f /* Read the regs */ +#define ASI_DATAPATH_WRITE 0x77 /* Write to the regs */ +#define P_DPER_0 0x00 /* Datapath err reg 0 */ +#define P_DPER_1 0x18 /* Datapath err reg 1 */ +#define P_DCR_0 0x20 /* Datapath control reg 0 */ +#define P_DCR_1 0x38 /* Datapath control reg 0 */ + + +/* From sparc64/asm.h which I think I'll deprecate since it makes bus.h a pain. */ + +#ifndef _LOCORE +/* + * GCC __asm constructs for doing assembly stuff. + */ + +/* + * ``Routines'' to load and store from/to alternate address space. + * The location can be a variable, the asi value (address space indicator) + * must be a constant. + * + * N.B.: You can put as many special functions here as you like, since + * they cost no kernel space or time if they are not used. + * + * These were static inline functions, but gcc screws up the constraints + * on the address space identifiers (the "n"umeric value part) because + * it inlines too late, so we have to use the funny valued-macro syntax. + */ + +/* + * Apparently the definition of bypass ASIs is that they all use the + * D$ so we need to flush the D$ to make sure we don't get data pollution. + */ + +#define sparc_wr(name, val, xor) \ +do { \ + if (__builtin_constant_p(xor)) \ + __asm volatile("wr %%g0, %0, %%" #name \ + : : "rI" ((val) ^ (xor)) : "%g0"); \ + else \ + __asm volatile("wr %0, %1, %%" #name \ + : : "r" (val), "rI" (xor) : "%g0"); \ +} while(0) + +#define sparc_wrpr(name, val, xor) \ +do { \ + if (__builtin_constant_p(xor)) \ + __asm volatile("wrpr %%g0, %0, %%" #name \ + : : "rI" ((val) ^ (xor)) : "%g0"); \ + else \ + __asm volatile("wrpr %0, %1, %%" #name \ + : : "r" (val), "rI" (xor) : "%g0"); \ + __asm volatile("" : : : "memory"); \ +} while(0) + + +#define sparc_rd(name) sparc_rd_ ## name() +#define GEN_RD(name) \ +static inline u_int64_t sparc_rd_ ## name(void); \ +static inline u_int64_t \ +sparc_rd_ ## name(void) \ +{ \ + u_int64_t r; \ + __asm volatile("rd %%" #name ", %0" : \ + "=r" (r) : : "%g0"); \ + return (r); \ +} + +#define sparc_rdpr(name) sparc_rdpr_ ## name() +#define GEN_RDPR(name) \ +static inline u_int64_t sparc_rdpr_ ## name(void); \ +static inline u_int64_t \ +sparc_rdpr_ ## name(void) \ +{ \ + u_int64_t r; \ + __asm volatile("rdpr %%" #name ", %0" : \ + "=r" (r) : : "%g0"); \ + return (r); \ +} + +GEN_RD(asi); +GEN_RD(fprs); +GEN_RD(asr22); +GEN_RD(sys_tick); +GEN_RD(sys_tick_cmpr); +GEN_RDPR(tick); +GEN_RDPR(tba); +GEN_RDPR(pstate); +GEN_RDPR(pil); +GEN_RDPR(cwp); +GEN_RDPR(cansave); +GEN_RDPR(canrestore); +GEN_RDPR(cleanwin); +GEN_RDPR(otherwin); +GEN_RDPR(wstate); +GEN_RDPR(ver); +/* + * Before adding GEN_RDPRs for other registers, see Errata 50 (E.g,. in + * the US-IIi manual) regarding tstate, pc and npc reads. + */ + +/* Generate ld*a/st*a functions for non-constant ASI's. */ +#define LDNC_GEN(tp, o) \ + static inline tp o ## _asi(paddr_t); \ + static inline tp \ + o ## _asi(paddr_t va) \ + { \ + tp r; \ + __asm volatile( \ + #o " [%1] %%asi, %0" \ + : "=r" (r) \ + : "r" ((volatile tp *)va) \ + : "%g0"); \ + return (r); \ + } \ + static inline tp o ## _nc(paddr_t, int); \ + static inline tp \ + o ## _nc(paddr_t va, int asi) \ + { \ + sparc_wr(asi, asi, 0); \ + return (o ## _asi(va)); \ + } + +LDNC_GEN(u_char, lduba); +LDNC_GEN(u_short, lduha); +LDNC_GEN(u_int, lduwa); +LDNC_GEN(u_int64_t, ldxa); + +LDNC_GEN(int, lda); + +#define LDC_GEN(va, asi, op, opa, type) ({ \ + type __r ## op ## type; \ + if(asi == ASI_PRIMARY || \ + (sizeof(type) == 1 && asi == ASI_PRIMARY_LITTLE)) \ + __r ## op ## type = *((volatile type *)va); \ + else \ + __asm volatile(#opa " [%1] " #asi ", %0" \ + : "=r" (__r ## op ## type) \ + : "r" ((volatile type *)va) \ + : "%g0"); \ + __r ## op ## type; \ +}) + +#ifdef __OPTIMIZE__ +#define LD_GENERIC(va, asi, op, type) (__builtin_constant_p(asi) ? \ + LDC_GEN((va), asi, op, op ## a, type) : op ## a_nc((va), asi)) +#else /* __OPTIMIZE */ +#define LD_GENERIC(va, asi, op, type) (op ## a_nc((va), asi)) +#endif /* __OPTIMIZE__ */ + +#define lduba(va, asi) LD_GENERIC(va, asi, ldub, u_int8_t) +#define lduha(va, asi) LD_GENERIC(va, asi, lduh, u_int16_t) +#define lduwa(va, asi) LD_GENERIC(va, asi, lduw, u_int32_t) +#define ldxa(va, asi) LD_GENERIC(va, asi, ldx, u_int64_t) + +#define STNC_GEN(tp, o) \ + static inline void o ## _asi(paddr_t, tp); \ + static inline void \ + o ## _asi(paddr_t va, tp val) \ + { \ + __asm volatile( \ + #o " %0, [%1] %%asi" \ + : \ + : "r" (val), "r" ((volatile tp *)va) \ + : "memory"); \ + } \ + static inline void o ## _nc(paddr_t, int, tp); \ + static inline void \ + o ## _nc(paddr_t va, int asi, tp val) \ + { \ + sparc_wr(asi, asi, 0); \ + o ## _asi(va, val); \ + } + +STNC_GEN(u_int8_t, stba); +STNC_GEN(u_int16_t, stha); +STNC_GEN(u_int32_t, stwa); +STNC_GEN(u_int64_t, stxa); + +STNC_GEN(u_int, sta); + +#define STC_GEN(va, asi, val, op, opa, type) ({ \ + if(asi == ASI_PRIMARY || \ + (sizeof(type) == 1 && asi == ASI_PRIMARY_LITTLE)) \ + *((volatile type *)va) = val; \ + else \ + __asm volatile(#opa " %0, [%1] " #asi \ + : : "r" (val), "r" ((volatile type *)va) \ + : "memory"); \ + }) + +#ifdef __OPTIMIZE__ +#define ST_GENERIC(va, asi, val, op, type) (__builtin_constant_p(asi) ? \ + STC_GEN((va), (asi), (val), op, op ## a, type) : \ + op ## a_nc((va), asi, (val))) +#else /* __OPTIMIZE__ */ +#define ST_GENERIC(va, asi, val, op, type) (op ## a_nc((va), asi, (val))) +#endif /* __OPTIMIZE__ */ + +#define stba(va, asi, val) ST_GENERIC(va, asi, val, stb, u_int8_t) +#define stha(va, asi, val) ST_GENERIC(va, asi, val, sth, u_int16_t) +#define stwa(va, asi, val) ST_GENERIC(va, asi, val, stw, u_int32_t) +#define stxa(va, asi, val) ST_GENERIC(va, asi, val, stx, u_int64_t) + + +static inline void asi_set(int); +static inline void +asi_set(int asi) +{ + sparc_wr(asi, asi, 0); +} + +static inline u_int8_t asi_get(void); +static inline u_int8_t +asi_get(void) +{ + return sparc_rd(asi); +} + +/* flush address from instruction cache */ +static inline void flush(void *); +static inline void +flush(void *p) +{ + __asm volatile("flush %0" + : : "r" (p) + : "memory"); +} + +/* Read 64-bit %tick and %sys_tick registers. */ +#define tick() (sparc_rdpr(tick) & TICK_TICKS) +#define sys_tick() (sparc_rd(sys_tick) & TICK_TICKS) +extern u_int64_t stick(void); + +extern void tick_enable(void); +extern void sys_tick_enable(void); + +extern void tickcmpr_set(u_int64_t); +extern void sys_tickcmpr_set(u_int64_t); +extern void stickcmpr_set(u_int64_t); + +#endif /* _LOCORE */ +#endif /* _SPARC64_CTLREG_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/db_machdep.h b/lib/libc/include/sparc64-openbsd-none/machine/db_machdep.h new file mode 100644 index 000000000000..9edef3be5342 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/db_machdep.h @@ -0,0 +1,145 @@ +/* $OpenBSD: db_machdep.h,v 1.23 2022/10/21 18:55:42 miod Exp $ */ +/* $NetBSD: db_machdep.h,v 1.12 2001/07/07 15:16:13 eeh Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#ifndef _MACHINE_DB_MACHDEP_H_ +#define _MACHINE_DB_MACHDEP_H_ + +/* + * Machine-dependent defines for new kernel debugger. + */ + +#include + +#include +#include +#include +#include + +/* end of mangling */ + +typedef long db_expr_t; /* expression - signed */ + +struct trapstate { + int64_t tstate; + int64_t tpc; + int64_t tnpc; + int64_t tt; +}; +#if 1 +typedef struct { + struct trapframe ddb_tf; + struct frame ddb_fr; + struct trapstate ddb_ts[5]; + int ddb_tl; + struct fpstate ddb_fpstate; +} db_regs_t; +#else +typedef struct db_regs { + struct trapregs dbr_traps[4]; + int dbr_y; + char dbr_tl; + char dbr_canrestore; + char dbr_cansave; + char dbr_cleanwin; + char dbr_cwp; + char dbr_wstate; + int64_t dbr_g[8]; + int64_t dbr_ag[8]; + int64_t dbr_ig[8]; + int64_t dbr_mg[8]; + int64_t dbr_out[8]; + int64_t dbr_local[8]; + int64_t dbr_in[8]; +} db_regs_t; +#endif + +extern db_regs_t ddb_regs; /* register state */ +#define DDB_TF (&ddb_regs.ddb_tf) +#define DDB_FR (&ddb_regs.ddb_fr) +#define DDB_FP (&ddb_regs.ddb_fpstate) + +#define PC_REGS(regs) ((vaddr_t)(regs)->ddb_tf.tf_pc) +#define SET_PC_REGS(regs, value) (regs)->ddb_tf.tf_pc = (int32_t)(value) +#define PC_ADVANCE(regs) do { \ + vaddr_t n = (regs)->ddb_tf.tf_npc; \ + (regs)->ddb_tf.tf_pc = n; \ + (regs)->ddb_tf.tf_npc = n + 4; \ +} while(0) + +#define BKPT_INST 0x91d02001 /* breakpoint instruction */ +#define BKPT_SIZE (4) /* size of breakpoint inst */ +#define BKPT_SET(inst) (BKPT_INST) + +#define IS_BREAKPOINT_TRAP(type, code) \ + ((type) == T_BREAKPOINT || (type) == T_KGDB_EXEC) +#define IS_WATCHPOINT_TRAP(type, code) \ + ((type) ==T_PA_WATCHPT || (type) == T_VA_WATCHPT) + +/* + * Sparc cpus have no hardware single-step. + */ +#define SOFTWARE_SSTEP + +int db_inst_trap_return(int inst); +int db_inst_return(int inst); +int db_inst_call(int inst); +int db_inst_branch(int inst); +int db_inst_unconditional_flow_transfer(int inst); +vaddr_t db_branch_taken(int inst, vaddr_t pc, db_regs_t *regs); + +#define inst_trap_return(ins) db_inst_trap_return(ins) +#define inst_return(ins) db_inst_return(ins) +#define inst_call(ins) db_inst_call(ins) +#define inst_branch(ins) db_inst_branch(ins) +#define inst_unconditional_flow_transfer(ins) \ + db_inst_unconditional_flow_transfer(ins) +#define branch_taken(ins, pc, fun, regs) \ + db_branch_taken((ins), (pc), (regs)) + +/* see note in db_interface.c about reversed breakpoint addrs */ +#define next_instr_address(pc, bd) \ + ((bd) ? (pc) : ddb_regs.ddb_tf.tf_npc) + +#define DB_MACHINE_COMMANDS + +void db_machine_init(void); +int db_ktrap(int, struct trapframe *); + +int db_enter_ddb(void); +void db_startcpu(struct cpu_info *); +void db_stopcpu(struct cpu_info *); + +#define DDB_STATE_NOT_RUNNING 0 +#define DDB_STATE_RUNNING 1 +#define DDB_STATE_EXITING 2 + +/* Register device-specific method for triggering XIRs. */ +void db_register_xir(void (*)(void *, int), void *); + +#endif /* _MACHINE_DB_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/disklabel.h b/lib/libc/include/sparc64-openbsd-none/machine/disklabel.h new file mode 100644 index 000000000000..5b9d93732ab6 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/disklabel.h @@ -0,0 +1,40 @@ +/* $OpenBSD: disklabel.h,v 1.5 2015/09/30 14:57:03 krw Exp $ */ + +/* + * Copyright (c) 1994 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_DISKLABEL_H_ +#define _MACHINE_DISKLABEL_H_ + +#define LABELSECTOR 0 /* sector containing label */ +#define LABELOFFSET 128 /* offset of label in sector */ +#define MAXPARTITIONS 16 /* number of partitions */ + +#endif /* _MACHINE_DISKLABEL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/elf.h b/lib/libc/include/sparc64-openbsd-none/machine/elf.h new file mode 100644 index 000000000000..1a69b90df3a0 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/elf.h @@ -0,0 +1,7 @@ +/* $OpenBSD: elf.h,v 1.1 2024/07/14 09:48:49 jca Exp $ */ + +/* + * This file is in the public domain. + */ + +/* Nothing for now */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/endian.h b/lib/libc/include/sparc64-openbsd-none/machine/endian.h new file mode 100644 index 000000000000..ed220930b5fe --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/endian.h @@ -0,0 +1,84 @@ +/* $OpenBSD: endian.h,v 1.7 2014/10/22 23:56:47 dlg Exp $ */ + +#ifndef _MACHINE_ENDIAN_H_ +#define _MACHINE_ENDIAN_H_ + +#define _BYTE_ORDER _BIG_ENDIAN + +#ifdef _KERNEL + +#define __ASI_P_L 0x88 /* == ASI_PRIMARY_LITTLE */ + +static inline __uint16_t +__mswap16(volatile const __uint16_t *m) +{ + __uint16_t v; + + __asm("lduha [%1] %2, %0 ! %3" + : "=r" (v) + : "r" (m), "n" (__ASI_P_L), "m" (*m)); + + return (v); +} + +static inline __uint32_t +__mswap32(volatile const __uint32_t *m) +{ + __uint32_t v; + + __asm("lduwa [%1] %2, %0 ! %3" + : "=r" (v) + : "r" (m), "n" (__ASI_P_L), "m" (*m)); + + return (v); +} + +static inline __uint64_t +__mswap64(volatile const __uint64_t *m) +{ + __uint64_t v; + + __asm("ldxa [%1] %2, %0 ! %3" + : "=r" (v) + : "r" (m), "n" (__ASI_P_L), "m" (*m)); + + return (v); +} + +static inline void +__swapm16(volatile __uint16_t *m, __uint16_t v) +{ + __asm("stha %1, [%2] %3 ! %0" + : "=m" (*m) + : "r" (v), "r" (m), "n" (__ASI_P_L)); +} + +static inline void +__swapm32(volatile __uint32_t *m, __uint32_t v) +{ + __asm("stwa %1, [%2] %3 ! %0" + : "=m" (*m) + : "r" (v), "r" (m), "n" (__ASI_P_L)); +} + +static inline void +__swapm64(volatile __uint64_t *m, __uint64_t v) +{ + __asm("stxa %1, [%2] %3 ! %0" + : "=m" (*m) + : "r" (v), "r" (m), "n" (__ASI_P_L)); +} + +#undef __ASI_P_L + +#define __HAVE_MD_SWAPIO + +#endif /* _KERNEL */ + +#define __STRICT_ALIGNMENT + +#ifndef __FROM_SYS__ENDIAN +#include +#endif + +#endif /* _MACHINE_ENDIAN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/exec.h b/lib/libc/include/sparc64-openbsd-none/machine/exec.h new file mode 100644 index 000000000000..e71ec31b247c --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/exec.h @@ -0,0 +1,99 @@ +/* $OpenBSD: exec.h,v 1.11 2017/02/08 05:09:26 guenther Exp $ */ +/* $NetBSD: elf_machdep.h,v 1.7 2001/02/11 00:18:49 eeh Exp $ */ + +#define ARCH_ELFSIZE 64 /* MD native binary size */ +#define ELF_TARG_CLASS ELFCLASS64 +#define ELF_TARG_MACH EM_SPARCV9 + +#define ELF_TARG_DATA ELFDATA2MSB + +/* The following are what is used for AT_SUN_HWCAP: */ +#define AV_SPARC_HWMUL_32x32 1 /* 32x32-bit smul/umul is efficient */ +#define AV_SPARC_HWDIV_32x32 2 /* 32x32-bit sdiv/udiv is efficient */ +#define AV_SPARC_HWFSMULD 4 /* fsmuld is efficient */ + +/* + * Here are some SPARC specific flags I can't + * find a better home for. They are used for AT_FLAGS + * and in the exec header. + */ +#define EF_SPARCV9_MM 0x3 +#define EF_SPARCV9_TSO 0x0 +#define EF_SPARCV9_PSO 0x1 +#define EF_SPARCV9_RMO 0x2 + +#define EF_SPARC_32PLUS_MASK 0xffff00 /* bits indicating V8+ type */ +#define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */ +#define EF_SPARC_EXT_MASK 0xffff00 /* bits for vendor extensions */ +#define EF_SPARC_SUN_US1 0x000200 /* UltraSPARC 1 extensions */ +#define EF_SPARC_HAL_R1 0x000400 /* HAL R1 extensions */ +#define EF_SPARC_SUN_US3 0x000800 /* UltraSPARC 3 extensions */ + +/* Relocation types */ +#define R_SPARC_NONE 0 +#define R_SPARC_8 1 +#define R_SPARC_16 2 +#define R_SPARC_32 3 +#define R_SPARC_DISP8 4 +#define R_SPARC_DISP16 5 +#define R_SPARC_DISP32 6 +#define R_SPARC_WDISP30 7 +#define R_SPARC_WDISP22 8 +#define R_SPARC_HI22 9 +#define R_SPARC_22 10 +#define R_SPARC_13 11 +#define R_SPARC_LO10 12 +#define R_SPARC_GOT10 13 +#define R_SPARC_GOT13 14 +#define R_SPARC_GOT22 15 +#define R_SPARC_PC10 16 +#define R_SPARC_PC22 17 +#define R_SPARC_WPLT30 18 +#define R_SPARC_COPY 19 +#define R_SPARC_GLOB_DAT 20 +#define R_SPARC_JMP_SLOT 21 +#define R_SPARC_RELATIVE 22 +#define R_SPARC_UA32 23 +#define R_SPARC_PLT32 24 +#define R_SPARC_HIPLT22 25 +#define R_SPARC_LOPLT10 26 +#define R_SPARC_PCPLT32 27 +#define R_SPARC_PCPLT22 28 +#define R_SPARC_PCPLT10 29 +#define R_SPARC_10 30 +#define R_SPARC_11 31 +#define R_SPARC_64 32 +#define R_SPARC_OLO10 33 +#define R_SPARC_HH22 34 +#define R_SPARC_HM10 35 +#define R_SPARC_LM22 36 +#define R_SPARC_PC_HH22 37 +#define R_SPARC_PC_HM10 38 +#define R_SPARC_PC_LM22 39 +#define R_SPARC_WDISP16 40 +#define R_SPARC_WDISP19 41 +#define R_SPARC_GLOB_JMP 42 +#define R_SPARC_7 43 +#define R_SPARC_5 44 +#define R_SPARC_6 45 +#define R_SPARC_DISP64 46 +#define R_SPARC_PLT64 47 +#define R_SPARC_HIX22 48 +#define R_SPARC_LOX10 49 +#define R_SPARC_H44 50 +#define R_SPARC_M44 51 +#define R_SPARC_L44 52 +#define R_SPARC_REGISTER 53 +#define R_SPARC_UA64 54 +#define R_SPARC_UA16 55 +#define R_SPARC_TLS_DTPMOD32 74 +#define R_SPARC_TLS_DTPMOD64 75 +#define R_SPARC_TLS_DTPOFF32 76 +#define R_SPARC_TLS_DTPOFF64 77 +#define R_SPARC_TLS_TPOFF32 78 +#define R_SPARC_TLS_TPOFF64 79 + + +#define R_TYPE(name) __CONCAT(R_SPARC_,name) + +#define __LDPGSZ 8192 /* linker page size */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/fbvar.h b/lib/libc/include/sparc64-openbsd-none/machine/fbvar.h new file mode 100644 index 000000000000..6815f314900a --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/fbvar.h @@ -0,0 +1,80 @@ +/* $OpenBSD: fbvar.h,v 1.8 2008/12/29 22:07:35 miod Exp $ */ +/* $NetBSD: fbvar.h,v 1.9 1997/07/07 23:31:30 pk Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)fbvar.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * Common frame buffer variables. + * All framebuffer softc structures must start with such a structure. + */ +struct sunfb { + struct device sf_dev; /* base device */ + + int sf_width; + int sf_height; + int sf_depth; + int sf_linebytes; + + int sf_fbsize; /* sf_height * sf_linebytes */ + + int *sf_crowp, *sf_ccolp; /* PROM cursor position */ + + struct rasops_info sf_ro; + + struct wsscreen_descr sf_wsd; + struct wsscreen_list sf_wsl; + struct wsscreen_descr *sf_scrlist[1]; + int sf_nscreens; +}; + +/* + * Selected framebuffer node on OBP systems if k/d console. + */ +extern int fbnode; + +void fb_setsize(struct sunfb*, int, int, int, int, int); +void fbwscons_init(struct sunfb *, int, int); +void fbwscons_console_init(struct sunfb *, int); +void fbwscons_setcolormap(struct sunfb *, + void (*)(void *, u_int, u_int8_t, u_int8_t, u_int8_t)); +void fbwscons_attach(struct sunfb *, struct wsdisplay_accessops *, int); + +int ifb_ident(void *); \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/fenv.h b/lib/libc/include/sparc64-openbsd-none/machine/fenv.h new file mode 100644 index 000000000000..9fb328fd32df --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/fenv.h @@ -0,0 +1,108 @@ +/* $OpenBSD: fenv.h,v 1.4 2011/05/25 21:46:49 martynas Exp $ */ +/* $NetBSD: fenv.h,v 1.1.2.2 2011/02/08 16:19:41 bouyer Exp $ */ + +/*- + * Copyright (c) 2004-2005 David Schultz + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SPARC64_FENV_H_ +#define _SPARC64_FENV_H_ + +/* + * Each symbol representing a floating point exception expands to an integer + * constant expression with values, such that bitwise-inclusive ORs of _all + * combinations_ of the constants result in distinct values. + * + * We use such values that allow direct bitwise operations on FPU registers. + */ +#define FE_INEXACT 0x020 +#define FE_DIVBYZERO 0x040 +#define FE_UNDERFLOW 0x080 +#define FE_OVERFLOW 0x100 +#define FE_INVALID 0x200 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * exception constants defined above. + */ +#define FE_ALL_EXCEPT (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | \ + FE_OVERFLOW | FE_INVALID) +#define _MASK_SHIFT 18 + +/* + * Each symbol representing the rounding direction, expands to an integer + * constant expression whose value is distinct non-negative value. + * + * We use such values that allow direct bitwise operations on FPU registers. + */ +#define FE_TONEAREST 0x0 +#define FE_TOWARDZERO 0x1 +#define FE_UPWARD 0x2 +#define FE_DOWNWARD 0x3 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * rounding direction constants defined above. + */ +#define _ROUND_MASK (FE_TONEAREST | FE_TOWARDZERO | FE_UPWARD | \ + FE_DOWNWARD) +#define _ROUND_SHIFT 30 + +/* + * fenv_t represents the entire floating-point environment. + */ +typedef unsigned long fenv_t; + +/* + * The following constant represents the default floating-point environment + * (that is, the one installed at program startup) and has type pointer to + * const-qualified fenv_t. + * + * It can be used as an argument to the functions within the header + * that manage the floating-point environment, namely fesetenv() and + * feupdateenv(). + */ +__BEGIN_DECLS +extern fenv_t __fe_dfl_env; +__END_DECLS +#define FE_DFL_ENV ((const fenv_t *)&__fe_dfl_env) + +/* + * fexcept_t represents the floating-point status flags collectively, including + * any status the implementation associates with the flags. + * + * A floating-point status flag is a system variable whose value is set (but + * never cleared) when a floating-point exception is raised, which occurs as a + * side effect of exceptional floating-point arithmetic to provide auxiliary + * information. + * + * A floating-point control mode is a system variable whose value may be set by + * the user to affect the subsequent behavior of floating-point arithmetic. + */ +typedef unsigned long fexcept_t; + +#endif /* !_SPARC64_FENV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/frame.h b/lib/libc/include/sparc64-openbsd-none/machine/frame.h new file mode 100644 index 000000000000..4b077a0ce660 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/frame.h @@ -0,0 +1,105 @@ +/* $OpenBSD: frame.h,v 1.11 2024/04/08 20:07:53 miod Exp $ */ +/* $NetBSD: frame.h,v 1.9 2001/03/04 09:28:35 mrg Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)frame.h 8.1 (Berkeley) 6/11/93 + */ + +#ifndef _MACHINE_FRAME_H_ +#define _MACHINE_FRAME_H_ + +/* + * CC64FSZ (C Compiler 64-bit Frame SiZe) is the size of a stack frame used + * by the compiler in 64-bit mode. It is (16)*8; space for 8 ins, 8 outs. + */ +#define CC64FSZ 176 + +/* + * v9 stacks all have a bias of 2047 added to the %sp and %fp, so you can easily + * detect it by testing the register for an odd value. Why 2K-1 I don't know. + */ +#define BIAS (2048-1) + +#if defined(_KERNEL) && !defined(_LOCORE) + +/* + * Sparc v9 stack frame format. + * + * Note that the contents of each stack frame may be held only in + * machine register windows. In order to get an accurate picture + * of the frame, you must first force the kernel to write any such + * windows to the stack. + * + * V9 frames have an odd bias, so you can tell a v9 frame from + * a v8 frame by testing the stack pointer's lsb. + */ +struct frame { + int64_t fr_local[8]; /* space to save locals (%l0..%l7) */ + int64_t fr_arg[6]; /* space to save arguments (%i0..%i5) */ + u_int64_t fr_fp; /* space to save frame pointer (%i6) */ + u_int64_t fr_pc; /* space to save return pc (%i7) */ + /* + * SVR4 reserves a bunch of extra stuff. + */ + int64_t fr_argd[6]; /* `register save area' (lunacy) */ + int64_t fr_argx[0]; /* arg extension (args 7..n; variable size) */ +}; + +#define v9next_frame(f) ((struct frame*)(f->fr_fp+BIAS)) + +/* + * The v9 trapframe. + */ +struct trapframe { + int64_t tf_tstate; /* tstate register */ + int64_t tf_pc; /* return pc */ + int64_t tf_npc; /* return npc */ + int tf_y; /* %y register -- 32-bits */ + short tf_tt; /* What type of trap this was */ + char tf_pil; /* What IRQ we're handling */ + char tf_oldpil; /* What our old SPL was */ + int64_t tf_global[8]; /* global registers in trap's caller */ + int64_t tf_out[8]; /* output registers in trap's caller */ + int64_t tf_local[8]; /* local registers in trap's caller */ + int64_t tf_in[8]; /* in registers in trap's caller (for debug) */ +}; + +#endif /* _KERNEL && !_LOCORE */ + +#endif /* _MACHINE_FRAME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/fsr.h b/lib/libc/include/sparc64-openbsd-none/machine/fsr.h new file mode 100644 index 000000000000..d6689e55f9fe --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/fsr.h @@ -0,0 +1,132 @@ +/* $OpenBSD: fsr.h,v 1.2 2003/06/02 23:27:56 millert Exp $ */ +/* $NetBSD: fsr.h,v 1.1.1.1 1998/06/20 04:58:51 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)fsr.h 8.1 (Berkeley) 6/11/93 + */ + +#ifndef _MACHINE_FSR_H_ +#define _MACHINE_FSR_H_ + +/* + * Bits in FPRS + */ +#define FPRS_FEF 0x04 /* Enable FP -- must be set to enable FP regs */ +#define FPRS_DU 0x02 /* Dirty upper -- upper fp regs are dirty */ +#define FPRS_DL 0x01 /* Dirty lower -- lower fp regs are dirty */ + +/* + * Bits in FSR. + */ + +#define FSR_RD 0xc0000000 /* rounding direction */ +#define FSR_RD_RN 0 /* round to nearest */ +#define FSR_RD_RZ 1 /* round towards 0 */ +#define FSR_RD_RP 2 /* round towards +inf */ +#define FSR_RD_RM 3 /* round towards -inf */ +#define FSR_RD_SHIFT 30 +#define FSR_RD_MASK 0x03 + +#define FSR_RP 0x30000000 /* extended rounding precision */ +#define FSR_RP_X 0 /* extended stays extended */ +#define FSR_RP_S 1 /* extended => single */ +#define FSR_RP_D 2 /* extended => double */ +#define FSR_RP_80 3 /* extended => 80-bit */ +#define FSR_RP_SHIFT 28 +#define FSR_RP_MASK 0x03 + +#define FSR_TEM 0x0f800000 /* trap enable mask */ +#define FSR_TEM_SHIFT 23 +#define FSR_TEM_MASK 0x1f + +#define FSR_NS 0x00400000 /* ``nonstandard mode'' */ +#define FSR_AU 0x00400000 /* aka abrupt underflow mode */ +#define FSR_MBZ 0x00300000 /* reserved; must be zero */ + +#define FSR_VER 0x000e0000 /* version bits */ +#define FSR_VER_SHIFT 17 +#define FSR_VER_MASK 0x07 + +#define FSR_FTT 0x0001c000 /* FP trap type */ +#define FSR_TT_NONE 0 /* no trap */ +#define FSR_TT_IEEE 1 /* IEEE exception */ +#define FSR_TT_UNFIN 2 /* unfinished operation */ +#define FSR_TT_UNIMP 3 /* unimplemented operation */ +#define FSR_TT_SEQ 4 /* sequence error */ +#define FSR_TT_HWERR 5 /* hardware error (unrecoverable) */ +#define FSR_FTT_SHIFT 14 +#define FSR_FTT_MASK 0x03 + +#define FSR_QNE 0x00002000 /* queue not empty */ +#define FSR_PR 0x00001000 /* partial result */ + +#define FSR_FCC 0x00000c00 /* FP condition codes */ +#define FSR_CC_EQ 0 /* f1 = f2 */ +#define FSR_CC_LT 1 /* f1 < f2 */ +#define FSR_CC_GT 2 /* f1 > f2 */ +#define FSR_CC_UO 3 /* (f1,f2) unordered */ +#define FSR_FCC_SHIFT 10 +#define FSR_FCC_MASK 0x03 + +#define FSR_AX 0x000003e0 /* accrued exceptions */ +#define FSR_AX_SHIFT 5 +#define FSR_AX_MASK 0x1f +#define FSR_CX 0x0000001f /* current exceptions */ +#define FSR_CX_SHIFT 0 +#define FSR_CX_MASK 0x1f + +/* These are the 3 new v9 fcc's */ +#define FSR_FCC3 0x06000000000 /* FP condition codes */ +#define FSR_FCC3_SHIFT 36 + +#define FSR_FCC2 0x0c00000000 /* FP condition codes */ +#define FSR_FCC2_SHIFT 34 + +#define FSR_FCC1 0x0600000000 /* FP condition codes */ +#define FSR_FCC1_SHIFT 32 + + +/* The following exceptions apply to TEM, AX, and CX. */ +#define FSR_NV 0x10 /* invalid operand */ +#define FSR_OF 0x08 /* overflow */ +#define FSR_UF 0x04 /* underflow */ +#define FSR_DZ 0x02 /* division by zero */ +#define FSR_NX 0x01 /* inexact result */ + +#endif /* _MACHINE_FSR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/hypervisor.h b/lib/libc/include/sparc64-openbsd-none/machine/hypervisor.h new file mode 100644 index 000000000000..c8d8cc48dcdb --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/hypervisor.h @@ -0,0 +1,348 @@ +/* $OpenBSD: hypervisor.h,v 1.21 2024/04/08 20:00:27 miod Exp $ */ + +/* + * Copyright (c) 2008 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * UltraSPARC Hypervisor API. + */ + +/* + * API versioning + */ + +int64_t hv_api_get_version(uint64_t api_group, + uint64_t *major_number, uint64_t *minor_number); + +/* + * Domain services + */ + +int64_t hv_mach_desc(paddr_t buffer, psize_t *length); +int64_t hv_mach_pri(paddr_t buffer, psize_t *length); + +/* + * CPU services + */ + +void hv_cpu_yield(void); +int64_t hv_cpu_qconf(uint64_t queue, uint64_t base, uint64_t nentries); + +#define CPU_MONDO_QUEUE 0x3c +#define DEVICE_MONDO_QUEUE 0x3d +#define RESUMABLE_ERROR_QUEUE 0x3e +#define NONRESUMABLE_ERROR_QUEUE 0x3f + +int64_t hv_cpu_mondo_send(uint64_t ncpus, paddr_t cpulist, paddr_t data); +int64_t hv_cpu_myid(uint64_t *cpuid); + +/* + * MMU services + */ + +int64_t hv_mmu_demap_page(vaddr_t vaddr, uint64_t context, uint64_t flags); +int64_t hv_mmu_demap_ctx(uint64_t context, uint64_t flags); +int64_t hv_mmu_map_perm_addr(vaddr_t vaddr, uint64_t tte, uint64_t flags); +int64_t hv_mmu_unmap_perm_addr(vaddr_t vaddr, uint64_t flags); +int64_t hv_mmu_map_addr(vaddr_t vaddr, uint64_t context, uint64_t tte, + uint64_t flags); +int64_t hv_mmu_unmap_addr(vaddr_t vaddr, uint64_t context, uint64_t flags); + +#define MAP_DTLB 0x1 +#define MAP_ITLB 0x2 + +struct tsb_desc { + uint16_t td_idxpgsz; + uint16_t td_assoc; + uint32_t td_size; + uint32_t td_ctxidx; + uint32_t td_pgsz; + paddr_t td_pa; + uint64_t td_reserved; +}; + +int64_t hv_mmu_tsb_ctx0(uint64_t ntsb, paddr_t tsbptr); +int64_t hv_mmu_tsb_ctxnon0(uint64_t ntsb, paddr_t tsbptr); + +/* + * Cache and memory services + */ + +int64_t hv_mem_scrub(paddr_t raddr, psize_t length); +int64_t hv_mem_sync(paddr_t raddr, psize_t length); + +/* + * Device interrupt services + */ + +int64_t hv_intr_devino_to_sysino(uint64_t devhandle, uint64_t devino, + uint64_t *sysino); +int64_t hv_intr_getenabled(uint64_t sysino, uint64_t *intr_enabled); +int64_t hv_intr_setenabled(uint64_t sysino, uint64_t intr_enabled); +int64_t hv_intr_getstate(uint64_t sysino, uint64_t *intr_state); +int64_t hv_intr_setstate(uint64_t sysino, uint64_t intr_state); +int64_t hv_intr_gettarget(uint64_t sysino, uint64_t *cpuid); +int64_t hv_intr_settarget(uint64_t sysino, uint64_t cpuid); + +#define INTR_DISABLED 0 +#define INTR_ENABLED 1 + +#define INTR_IDLE 0 +#define INTR_RECEIVED 1 +#define INTR_DELIVERED 2 + +int64_t hv_vintr_getcookie(uint64_t devhandle, uint64_t devino, + uint64_t *cookie_value); +int64_t hv_vintr_setcookie(uint64_t devhandle, uint64_t devino, + uint64_t cookie_value); +int64_t hv_vintr_getenabled(uint64_t devhandle, uint64_t devino, + uint64_t *intr_enabled); +int64_t hv_vintr_setenabled(uint64_t devhandle, uint64_t devino, + uint64_t intr_enabled); +int64_t hv_vintr_getstate(uint64_t devhandle, uint64_t devino, + uint64_t *intr_state); +int64_t hv_vintr_setstate(uint64_t devhandle, uint64_t devino, + uint64_t intr_state); +int64_t hv_vintr_gettarget(uint64_t devhandle, uint64_t devino, + uint64_t *cpuid); +int64_t hv_vintr_settarget(uint64_t devhandle, uint64_t devino, + uint64_t cpuid); + +/* + * Time of day services + */ + +int64_t hv_tod_get(uint64_t *tod); +int64_t hv_tod_set(uint64_t tod); + +/* + * Console services + */ + +int64_t hv_cons_getchar(int64_t *ch); +int64_t hv_cons_putchar(int64_t ch); +int64_t hv_api_putchar(int64_t ch); + +#define CONS_BREAK -1 +#define CONS_HUP -2 + +/* + * Domain state services + */ + +int64_t hv_soft_state_set(uint64_t software_state, + paddr_t software_description_ptr); + +#define SIS_NORMAL 0x1 +#define SIS_TRANSITION 0x2 + +/* + * PCI I/O services + */ + +int64_t hv_pci_iommu_map(uint64_t devhandle, uint64_t tsbid, + uint64_t nttes, uint64_t io_attributes, paddr_t io_page_list_p, + uint64_t *nttes_mapped); +int64_t hv_pci_iommu_demap(uint64_t devhandle, uint64_t tsbid, + uint64_t nttes, uint64_t *nttes_demapped); +int64_t hv_pci_iommu_getmap(uint64_t devhandle, uint64_t tsbid, + uint64_t *io_attributes, paddr_t *r_addr); +int64_t hv_pci_iommu_getbypass(uint64_t devhandle, paddr_t r_addr, + uint64_t io_attributes, uint64_t *io_addr); + +int64_t hv_pci_config_get(uint64_t devhandle, uint64_t pci_device, + uint64_t pci_config_offset, uint64_t size, + uint64_t *error_flag, uint64_t *data); +int64_t hv_pci_config_put(uint64_t devhandle, uint64_t pci_device, + uint64_t pci_config_offset, uint64_t size, uint64_t data, + uint64_t *error_flag); + +#define PCI_MAP_ATTR_READ 0x01 /* From memory */ +#define PCI_MAP_ATTR_WRITE 0x02 /* To memory */ + +/* + * PCI MSI services + */ + +int64_t hv_pci_msiq_conf(uint64_t devhandle, uint64_t msiqid, + uint64_t r_addr, uint64_t nentries); +int64_t hv_pci_msiq_info(uint64_t devhandle, uint64_t msiqid, + uint64_t *r_addr, uint64_t *nentries); + +int64_t hv_pci_msiq_getvalid(uint64_t devhandle, uint64_t msiqid, + uint64_t *msiqvalid); +int64_t hv_pci_msiq_setvalid(uint64_t devhandle, uint64_t msiqid, + uint64_t msiqvalid); + +#define PCI_MSIQ_INVALID 0 +#define PCI_MSIQ_VALID 1 + +int64_t hv_pci_msiq_getstate(uint64_t devhandle, uint64_t msiqid, + uint64_t *msiqstate); +int64_t hv_pci_msiq_setstate(uint64_t devhandle, uint64_t msiqid, + uint64_t msiqstate); + +#define PCI_MSIQSTATE_IDLE 0 +#define PCI_MSIQSTATE_ERROR 1 + +int64_t hv_pci_msiq_gethead(uint64_t devhandle, uint64_t msiqid, + uint64_t *msiqhead); +int64_t hv_pci_msiq_sethead(uint64_t devhandle, uint64_t msiqid, + uint64_t msiqhead); +int64_t hv_pci_msiq_gettail(uint64_t devhandle, uint64_t msiqid, + uint64_t *msiqtail); + +int64_t hv_pci_msi_getvalid(uint64_t devhandle, uint64_t msinum, + uint64_t *msivalidstate); +int64_t hv_pci_msi_setvalid(uint64_t devhandle, uint64_t msinum, + uint64_t msivalidstate); + +#define PCI_MSI_INVALID 0 +#define PCI_MSI_VALID 1 + +int64_t hv_pci_msi_getmsiq(uint64_t devhandle, uint64_t msinum, + uint64_t *msiqid); +int64_t hv_pci_msi_setmsiq(uint64_t devhandle, uint64_t msinum, + uint64_t msitype, uint64_t msiqid); + +int64_t hv_pci_msi_getstate(uint64_t devhandle, uint64_t msinum, + uint64_t *msistate); +int64_t hv_pci_msi_setstate(uint64_t devhandle, uint64_t msinum, + uint64_t msistate); + +#define PCI_MSISTATE_IDLE 0 +#define PCI_MSISTATE_DELIVERED 1 + +int64_t hv_pci_msg_getmsiq(uint64_t devhandle, uint64_t msg, + uint64_t *msiqid); +int64_t hv_pci_msg_setmsiq(uint64_t devhandle, uint64_t msg, + uint64_t msiqid); + +int64_t hv_pci_msg_getvalid(uint64_t devhandle, uint64_t msg, + uint64_t *msgvalidstate); +int64_t hv_pci_msg_setvalid(uint64_t devhandle, uint64_t msg, + uint64_t msgvalidstate); + +#define PCIE_MSG_INVALID 0 +#define PCIE_MSG_VALID 1 + +#define PCIE_PME_MSG 0x18 +#define PCIE_PME_ACK_MSG 0x1b +#define PCIE_CORR_MSG 0x30 +#define PCIE_NONFATAL_MSG 0x31 +#define PCIE_FATAL_MSG 0x32 + +/* + * Logical Domain Channel services + */ + +int64_t hv_ldc_tx_qconf(uint64_t ldc_id, paddr_t base_raddr, + uint64_t nentries); +int64_t hv_ldc_tx_qinfo(uint64_t ldc_id, paddr_t *base_raddr, + uint64_t *nentries); +int64_t hv_ldc_tx_get_state(uint64_t ldc_id, uint64_t *head_offset, + uint64_t *tail_offset, uint64_t *channel_state); +int64_t hv_ldc_tx_set_qtail(uint64_t ldc_id, uint64_t tail_offset); +int64_t hv_ldc_rx_qconf(uint64_t ldc_id, paddr_t base_raddr, + uint64_t nentries); +int64_t hv_ldc_rx_qinfo(uint64_t ldc_id, paddr_t *base_raddr, + uint64_t *nentries); +int64_t hv_ldc_rx_get_state(uint64_t ldc_id, uint64_t *head_offset, + uint64_t *tail_offset, uint64_t *channel_state); +int64_t hv_ldc_rx_set_qhead(uint64_t ldc_id, uint64_t head_offset); + +#define LDC_CHANNEL_DOWN 0 +#define LDC_CHANNEL_UP 1 +#define LDC_CHANNEL_RESET 2 + +/* Used by drivers only, not part of the hypervisor API. */ +#define LDC_CHANNEL_INIT ((uint64_t)-1) + +int64_t hv_ldc_set_map_table(uint64_t ldc_id, paddr_t base_raddr, + uint64_t nentries); +int64_t hv_ldc_get_map_table(uint64_t ldc_id, paddr_t *base_raddr, + uint64_t *nentries); +int64_t hv_ldc_copy(uint64_t ldc_id, uint64_t flags, uint64_t cookie, + paddr_t raddr, psize_t length, psize_t *ret_length); + +#define LDC_COPY_IN 0 +#define LDC_COPY_OUT 1 + +int64_t hv_ldc_mapin(uint64_t ldc_id, uint64_t cookie, paddr_t *raddr, + uint64_t *perms); +int64_t hv_ldc_unmap(paddr_t raddr, uint64_t *perms); + +/* + * Static Direct I/O services + */ + +int64_t hv_pci_iov_root_configured(uint64_t devhandle); +int64_t hv_pci_real_config_get(uint64_t devhandle, uint64_t pci_device, + uint64_t pci_config_offset, uint64_t size, + uint64_t *error_flag, uint64_t *data); +int64_t hv_pci_real_config_put(uint64_t devhandle, uint64_t pci_device, + uint64_t pci_config_offset, uint64_t size, uint64_t data, + uint64_t *error_flag); +int64_t hv_pci_error_send(uint64_t devhandle, uint64_t devino, + uint64_t pci_device); + +/* + * Cryptographic services + */ + +int64_t hv_rng_get_diag_control(void); +int64_t hv_rng_ctl_read(paddr_t raddr, uint64_t *state, uint64_t *delta); +int64_t hv_rng_ctl_write(paddr_t raddr, uint64_t state, uint64_t timeout, + uint64_t *delta); + +#define RNG_STATE_UNCONFIGURED 0 +#define RNG_STATE_CONFIGURED 1 +#define RNG_STATE_HEALTHCHECK 2 +#define RNG_STATE_ERROR 3 + +int64_t hv_rng_data_read_diag(paddr_t raddr, uint64_t size, uint64_t *delta); +int64_t hv_rng_data_read(paddr_t raddr, uint64_t *delta); + +/* + * Error codes + */ + +#define H_EOK 0 +#define H_ENOCPU 1 +#define H_ENORADDR 2 +#define H_ENOINTR 3 +#define H_EBADPGSZ 4 +#define H_EBADTSB 5 +#define H_EINVAL 6 +#define H_EBADTRAP 7 +#define H_EBADALIGN 8 +#define H_EWOULDBLOCK 9 +#define H_ENOACCESS 10 +#define H_EIO 11 +#define H_ECPUERROR 12 +#define H_ENOTSUPPORTED 13 +#define H_ENOMAP 14 +#define H_ETOOMANY 15 +#define H_ECHANNEL 16 + +extern uint64_t sun4v_group_interrupt_major; +extern uint64_t sun4v_group_sdio_major; + +int64_t sun4v_intr_devino_to_sysino(uint64_t, uint64_t, uint64_t *); +int64_t sun4v_intr_setcookie(uint64_t, uint64_t, uint64_t); +int64_t sun4v_intr_setenabled(uint64_t, uint64_t, uint64_t); +int64_t sun4v_intr_setstate(uint64_t, uint64_t, uint64_t); +int64_t sun4v_intr_settarget(uint64_t, uint64_t, uint64_t); \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/idprom.h b/lib/libc/include/sparc64-openbsd-none/machine/idprom.h new file mode 100644 index 000000000000..0332fc8f2ef7 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/idprom.h @@ -0,0 +1,52 @@ +/* $OpenBSD: idprom.h,v 1.3 2024/03/29 21:06:14 miod Exp $ */ +/* $NetBSD: idprom.h,v 1.2 1998/09/05 23:57:26 eeh Exp $ */ + +/* + * Copyright (c) 1993 Adam Glass + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Adam Glass. + * 4. The name of the Author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Adam Glass ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * ID prom format. The ``host id'' is set up by taking the machine + * ID as the top byte and the hostid field as the remaining three. + * The id_xxx0 field appears to contain some other number. The id_xxx1 + * contains a bunch of 00's and a5's on my machines, suggesting it is + * not actually used. The checksum seems to include them, however. + */ +struct idprom { + u_char id_format; /* format identifier (= 1) */ + u_char id_machine; /* machine type (see param.h) */ + u_char id_ether[6]; /* ethernet address */ + int id_date; /* date of manufacture */ + u_char id_hostid[3]; /* ``host id'' bytes */ + u_char id_checksum; /* xor of everything else */ + char id_undef[16]; /* undefined */ +}; + +#define IDPROM_VERSION 1 \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/ieee.h b/lib/libc/include/sparc64-openbsd-none/machine/ieee.h new file mode 100644 index 000000000000..9d22c7a0de76 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/ieee.h @@ -0,0 +1,148 @@ +/* $OpenBSD: ieee.h,v 1.4 2017/04/16 14:20:49 kettenis Exp $ */ +/* $NetBSD: ieee.h,v 1.1.1.1 1998/06/20 04:58:51 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ieee.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * ieee.h defines the machine-dependent layout of the machine's IEEE + * floating point. It does *not* define (yet?) any of the rounding + * mode bits, exceptions, and so forth. + */ + +/* + * Define the number of bits in each fraction and exponent. + * + * k k+1 + * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented + * + * (-exp_bias+1) + * as fractions that look like 0.fffff x 2 . This means that + * + * -126 + * the number 0.10000 x 2 , for instance, is the same as the normalized + * + * -127 -128 + * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero + * + * -129 + * in the fraction; to represent 2 , we need two, and so on. This + * + * (-exp_bias-fracbits+1) + * implies that the smallest denormalized number is 2 + * + * for whichever format we are talking about: for single precision, for + * + * -126 -149 + * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and + * + * -149 == -127 - 23 + 1. + */ +#define SNG_EXPBITS 8 +#define SNG_FRACBITS 23 + +#define DBL_EXPBITS 11 +#define DBL_FRACHBITS 20 +#define DBL_FRACLBITS 32 +#define DBL_FRACBITS 52 + +#define EXT_EXPBITS 15 +#define EXT_FRACHBITS 16 +#define EXT_FRACHMBITS 32 +#define EXT_FRACLMBITS 32 +#define EXT_FRACLBITS 32 +#define EXT_FRACBITS 112 + +#define EXT_IMPLICIT_NBIT + +#define EXT_TO_ARRAY32(p, a) do { \ + (a)[0] = (uint32_t)(p)->ext_fracl; \ + (a)[1] = (uint32_t)(p)->ext_fraclm; \ + (a)[2] = (uint32_t)(p)->ext_frachm; \ + (a)[3] = (uint32_t)(p)->ext_frach; \ +} while(0) + +struct ieee_single { + u_int sng_sign:1; + u_int sng_exp:8; + u_int sng_frac:23; +}; + +struct ieee_double { + u_int dbl_sign:1; + u_int dbl_exp:11; + u_int dbl_frach:20; + u_int dbl_fracl; +}; + +struct ieee_ext { + u_int ext_sign:1; + u_int ext_exp:15; + u_int ext_frach:16; + u_int ext_frachm; + u_int ext_fraclm; + u_int ext_fracl; +}; + +/* + * Floats whose exponent is in [1..INFNAN) (of whatever type) are + * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. + * Floats whose exponent is zero are either zero (iff all fraction + * bits are zero) or subnormal values. + * + * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its + * high fraction; if the bit is set, it is a `quiet NaN'. + */ +#define SNG_EXP_INFNAN 255 +#define DBL_EXP_INFNAN 2047 +#define EXT_EXP_INFNAN 32767 + +#if 0 +#define SNG_QUIETNAN (1 << 22) +#define DBL_QUIETNAN (1 << 19) +#define EXT_QUIETNAN (1 << 15) +#endif + +/* + * Exponent biases. + */ +#define SNG_EXP_BIAS 127 +#define DBL_EXP_BIAS 1023 +#define EXT_EXP_BIAS 16383 \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/ieeefp.h b/lib/libc/include/sparc64-openbsd-none/machine/ieeefp.h new file mode 100644 index 000000000000..0997cfae6df4 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/ieeefp.h @@ -0,0 +1,24 @@ +/* $OpenBSD: ieeefp.h,v 1.3 2011/03/23 16:54:37 pirofti Exp $ */ +/* + * Written by J.T. Conklin, Apr 6, 1995 + * Public domain. + */ + +#ifndef _MACHINE_IEEEFP_H_ +#define _MACHINE_IEEEFP_H_ + +typedef int fp_except; +#define FP_X_IMP 0x01 /* imprecise (loss of precision) */ +#define FP_X_DZ 0x02 /* divide-by-zero exception */ +#define FP_X_UFL 0x04 /* underflow exception */ +#define FP_X_OFL 0x08 /* overflow exception */ +#define FP_X_INV 0x10 /* invalid operation exception */ + +typedef enum { + FP_RN=0, /* round to nearest representable number */ + FP_RZ=1, /* round to zero (truncate) */ + FP_RP=2, /* round toward positive infinity */ + FP_RM=3 /* round toward negative infinity */ +} fp_rnd; + +#endif /* _MACHINE_IEEEFP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/instr.h b/lib/libc/include/sparc64-openbsd-none/machine/instr.h new file mode 100644 index 000000000000..9054144e9718 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/instr.h @@ -0,0 +1,502 @@ +/* $OpenBSD: instr.h,v 1.8 2025/07/16 07:15:42 jsg Exp $ */ +/* $NetBSD: instr.h,v 1.3 2000/01/10 03:53:20 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)instr.h 8.1 (Berkeley) 6/11/93 + */ + +/* see also Appendix F of the SPARC version 8 document */ +enum IOP { IOP_OP2, IOP_CALL, IOP_reg, IOP_mem }; +enum IOP2 { IOP2_UNIMP, IOP2_BPcc, IOP2_Bicc, IOP2_BPr, + IOP2_SETHI, IOP2_FBPfcc, IOP2_FBfcc, IOP2_CBccc }; +enum IOP3_reg { + IOP3_ADD, IOP3_AND, IOP3_OR, IOP3_XOR, + IOP3_SUB, IOP3_ANDN, IOP3_ORN, IOP3_XNOR, + IOP3_ADDX, IOP3_MULX, IOP3_UMUL, IOP3_SMUL, + IOP3_SUBX, IOP3_UDIVX, IOP3_UDIV, IOP3_SDIV, + IOP3_ADDcc, IOP3_ANDcc, IOP3_ORcc, IOP3_XORcc, + IOP3_SUBcc, IOP3_ANDNcc, IOP3_ORNcc, IOP3_XNORcc, + IOP3_ADDXcc, IOP3_rerr19, IOP3_UMULcc, IOP3_SMULcc, + IOP3_SUBXcc, IOP3_rerr1d, IOP3_UDIVcc, IOP3_SDIVcc, + IOP3_TADDcc, IOP3_TSUBcc, IOP3_TADDccTV, IOP3_TSUBccTV, + IOP3_MULScc, IOP3_SLL, IOP3_SRL, IOP3_SRA, + IOP3_RDASR_RDY_STBAR, IOP3_RDPSR, IOP3_RDWIM, IOP3_RDTGBR, + IOP3_MOVcc, IOP3_SDIVX, IOP3_POPC, IOP3_MOVr, + IOP3_WRASR_WRY, IOP3_WRPSR, IOP3_WRWIM, IOP3_WRTBR, + IOP3_FPop1, IOP3_FPop2, IOP3_CPop1, IOP3_CPop2, + IOP3_JMPL, IOP3_RETT, IOP3_Ticc, IOP3_FLUSH, + IOP3_SAVE, IOP3_RESTORE, IOP3_DONE_RETRY, IOP3_rerr3f +}; +enum IOP3_mem { + IOP3_LD, IOP3_LDUB, IOP3_LDUH, IOP3_LDD, + IOP3_ST, IOP3_STB, IOP3_STH, IOP3_STD, + IOP3_LDSW, IOP3_LDSB, IOP3_LDSH, IOP3_LDX, + IOP3_merr0c, IOP3_LDSTUB, IOP3_STX, IOP3_SWAP, + IOP3_LDA, IOP3_LDUBA, IOP3_LDUHA, IOP3_LDDA, + IOP3_STA, IOP3_STBA, IOP3_STHA, IOP3_STDA, + IOP3_LDSWA, IOP3_LDSBA, IOP3_LDSHA, IOP3_LDXA, + IOP3_merr1c, IOP3_LDSTUBA, IOP3_STXA, IOP3_SWAPA, + IOP3_LDF, IOP3_LDFSR, IOP3_LDQF, IOP3_LDDF, + IOP3_STF, IOP3_STFSR, IOP3_STQF, IOP3_STDF, + IOP3_merr28, IOP3_merr29, IOP3_merr2a, IOP3_merr2b, + IOP3_merr2c, IOP3_PREFETCH, IOP3_merr2e, IOP3_merr2f, + IOP3_LFC, IOP3_LDCSR, IOP3_LDQFA, IOP3_LDDC, + IOP3_STC, IOP3_STCSR, IOP3_STQFA, IOP3_STDC, + IOP3_merr38, IOP3_merr39, IOP3_merr3a, IOP3_merr3b, + IOP3_CASA, IOP3_PREFETCHA, IOP3_CASXA, IOP3_merr3f +}; + +/* + * Integer condition codes. + */ +#define Icc_N 0x0 /* never */ +#define Icc_E 0x1 /* equal (equiv. zero) */ +#define Icc_LE 0x2 /* less or equal */ +#define Icc_L 0x3 /* less */ +#define Icc_LEU 0x4 /* less or equal unsigned */ +#define Icc_CS 0x5 /* carry set (equiv. less unsigned) */ +#define Icc_NEG 0x6 /* negative */ +#define Icc_VS 0x7 /* overflow set */ +#define Icc_A 0x8 /* always */ +#define Icc_NE 0x9 /* not equal (equiv. not zero) */ +#define Icc_G 0xa /* greater */ +#define Icc_GE 0xb /* greater or equal */ +#define Icc_GU 0xc /* greater unsigned */ +#define Icc_CC 0xd /* carry clear (equiv. gtr or eq unsigned) */ +#define Icc_POS 0xe /* positive */ +#define Icc_VC 0xf /* overflow clear */ + +/* + * Integer registers. + */ +#define I_G0 0 +#define I_G1 1 +#define I_G2 2 +#define I_G3 3 +#define I_G4 4 +#define I_G5 5 +#define I_G6 6 +#define I_G7 7 +#define I_O0 8 +#define I_O1 9 +#define I_O2 10 +#define I_O3 11 +#define I_O4 12 +#define I_O5 13 +#define I_O6 14 +#define I_O7 15 +#define I_L0 16 +#define I_L1 17 +#define I_L2 18 +#define I_L3 19 +#define I_L4 20 +#define I_L5 21 +#define I_L6 22 +#define I_L7 23 +#define I_I0 24 +#define I_I1 25 +#define I_I2 26 +#define I_I3 27 +#define I_I4 28 +#define I_I5 29 +#define I_I6 30 +#define I_I7 31 + +/* + * An instruction. + */ +union instr { + int i_int; /* as a whole */ + + /* + * The first level of decoding is to use the top 2 bits. + * This gives us one of three `formats', which usually give + * a second level of decoding. + */ + struct { + u_int i_op:2; /* first-level decode */ + u_int :30; + } i_any; + + /* + * Format 1 instructions: CALL (undifferentiated). + */ + struct { + u_int :2; /* 01 */ + int i_disp:30; /* displacement */ + } i_call; + + /* + * Format 2 instructions (SETHI, UNIMP, and branches, plus illegal + * unused codes). + */ + struct { + u_int :2; /* 00 */ + u_int :5; + u_int i_op2:3; /* second-level decode */ + u_int :22; + } i_op2; + + /* UNIMP, SETHI */ + struct { + u_int :2; /* 00 */ + u_int i_rd:5; /* destination register */ + u_int i_op2:3; /* opcode: UNIMP or SETHI */ + u_int i_imm:22; /* immediate value */ + } i_imm22; + + /* branches: Bicc, FBfcc, CBccc */ + struct { + u_int :2; /* 00 */ + u_int i_annul:1; /* annul bit */ + u_int i_cond:4; /* condition codes */ + u_int i_op2:3; /* opcode: {Bi,FBf,CBc}cc */ + int i_disp:22; /* branch displacement */ + } i_branch; + + /* more branches: BPcc, FBPfcc */ + struct { + u_int :2; /* 00 */ + u_int i_annul:1; /* annul bit */ + u_int i_cond:4; /* condition codes */ + u_int i_op2:3; /* opcode: {BP,FBPf}cc */ + u_int i_cc:2; /* condition code selector */ + u_int i_pred:1; /* branch prediction bit */ + int i_disp:19; /* branch displacement */ + } i_branch_p; + + /* one last branch: BPr */ + struct { + u_int :2; /* 00 */ + u_int i_annul:1; /* annul bit */ + u_int :1; /* 0 */ + u_int i_rcond:4; /* register condition */ + u_int :3; /* 011 */ + int i_disphi:2; /* branch displacement, hi bits */ + u_int i_pred:1; /* branch prediction bit */ + u_int i_rs1:1; /* source register 1 */ + u_int i_displo:16; /* branch displacement, lo bits */ + } i_branch_pr; + + + /* + * Format 3 instructions (memory reference; arithmetic, logical, + * shift, and other miscellaneous operations). The second-level + * decode almost always makes use of an `rd' and `rs1', however + * (see also IOP3_reg and IOP3_mem). + * + * Beyond that, the low 14 bits may be broken up in one of three + * different ways, if at all: + * 1 bit of imm=0 + 8 bits of asi + 5 bits of rs2 [reg & mem] + * 1 bit of imm=1 + 13 bits of signed immediate [reg & mem] + * 9 bits of coprocessor `opf' opcode + 5 bits of rs2 [reg only] + */ + struct { + u_int :2; /* 10 or 11 */ + u_int i_rd:5; /* destination register */ + u_int i_op3:6; /* second-level decode */ + u_int i_rs1:5; /* source register 1 */ + u_int i_low14:14; /* varies */ + } i_op3; + + /* + * Memory forms. These set i_op=3 and use simm13 or asi layout. + * Memory references without an ASI should use 0, but the actual + * ASI field is simply ignored. + */ + struct { + u_int :2; /* 11 only */ + u_int i_rd:5; /* destination register */ + u_int i_op3:6; /* second-level decode (see IOP3_mem) */ + u_int i_rs1:5; /* source register 1 */ + u_int i_i:1; /* immediate vs asi */ + u_int i_low13:13; /* depend on i bit */ + } i_loadstore; + + /* + * Memory and register forms. + * These come in quite a variety and we do not + * attempt to break them down much. + */ + struct { + u_int :2; /* 10 or 11 */ + u_int i_rd:5; /* destination register */ + u_int i_op3:6; /* second-level decode */ + u_int i_rs1:5; /* source register 1 */ + u_int i_i:1; /* immediate bit (1) */ + int i_simm13:13; /* signed immediate */ + } i_simm13; + struct { + u_int :2; /* 10 or 11 */ + u_int i_rd:5; /* destination register */ + u_int i_op3:6; /* second-level decode */ + u_int i_rs1:5; /* source register 1 */ + u_int i_i:1; /* immediate vs asi */ + u_int i_asi:8; /* asi */ + u_int i_rs2:5; /* source register 2 */ + } i_asi; + struct { + u_int :2; /* 10 only (register, no memory) */ + u_int i_rd:5; /* destination register */ + u_int i_op3:6; /* second-level decode (see IOP3_reg) */ + u_int i_rs1:5; /* source register 1 */ + u_int i_opf:9; /* coprocessor 3rd-level decode */ + u_int i_rs2:5; /* source register 2 */ + } i_opf; + + /* + * Format 4 instructions (movcc, fmovr, fmovcc, and tcc). The + * second-level decode almost always makes use of an `rd' and either + * `rs1' or `cond'. + * + * Beyond that, the low 14 bits may be broken up in one of three + * different ways, if at all: + * 1 bit of imm=0 + 8 bits of asi + 5 bits of rs2 [reg & mem] + * 1 bit of imm=1 + 13 bits of signed immediate [reg & mem] + * 9 bits of coprocessor `opf' opcode + 5 bits of rs2 [reg only] */ + struct { + u_int :2; /* 10 */ + u_int i_rd:5; /* destination register */ + u_int i_op3:6; /* second-level decode */ + u_int i_rs1:5; /* source register 1 */ + u_int i_low14:14; /* varies */ + } i_op4; + + /* + * Move fp register on condition codes. + */ + struct { + u_int :2; /* 10 */ + u_int i_rd:5; /* destination register */ + u_int i_op3:6; /* second-level decode */ + u_int :1; + u_int i_cond:4; /* condition */ + u_int i_opf_cc:3; /* condition code register */ + u_int i_opf_low:6; /* third level decode */ + u_int i_rs2:5; /* source register */ + } i_fmovcc; + + /* + * Move fp register on integer register. + */ + struct { + u_int :2; /* 10 */ + u_int i_rd:5; /* destination register */ + u_int i_op3:6; /* second-level decode */ + u_int i_rs1:5; /* source register 1 */ + u_int :1; + u_int i_rcond:3; /* register condition */ + u_int i_opf_low:6; + u_int i_rs2:5; /* source register 2 */ + } i_fmovr; + +}; + +/* + * Internal macros for building instructions. These correspond 1-to-1 to + * the names above. Note that x << y | z == (x << y) | z. + */ +#define _I_ANY(op, b) ((op) << 30 | (b)) + +#define _I_OP2(high, op2, low) \ + _I_ANY(IOP_OP2, (high) << 25 | (op2) << 22 | (low)) +#define _I_IMM22(rd, op2, imm) \ + _I_ANY(IOP_OP2, (rd) << 25 | (op2) << 22 | (imm)) +#define _I_BRANCH(a, c, op2, disp) \ + _I_ANY(IOP_OP2, (a) << 29 | (c) << 25 | (op2) << 22 | (disp)) +#define _I_FBFCC(a, cond, disp) \ + _I_BRANCH(a, cond, IOP2_FBfcc, disp) +#define _I_CBCCC(a, cond, disp) \ + _I_BRANCH(a, cond, IOP2_CBccc, disp) + +#define _I_SIMM(simm) (1 << 13 | ((simm) & 0x1fff)) + +#define _I_OP3_GEN(form, rd, op3, rs1, low14) \ + _I_ANY(form, (rd) << 25 | (op3) << 19 | (rs1) << 14 | (low14)) +#define _I_OP3_LS_RAR(rd, op3, rs1, asi, rs2) \ + _I_OP3_GEN(IOP_mem, rd, op3, rs1, (asi) << 5 | (rs2)) +#define _I_OP3_LS_RI(rd, op3, rs1, simm13) \ + _I_OP3_GEN(IOP_mem, rd, op3, rs1, _I_SIMM(simm13)) +#define _I_OP3_LS_RR(rd, op3, rs1, rs2) \ + _I_OP3_GEN(IOP_mem, rd, op3, rs1, rs2) +#define _I_OP3_R_RAR(rd, op3, rs1, asi, rs2) \ + _I_OP3_GEN(IOP_reg, rd, op3, rs1, (asi) << 5 | (rs2)) +#define _I_OP3_R_RI(rd, op3, rs1, simm13) \ + _I_OP3_GEN(IOP_reg, rd, op3, rs1, _I_SIMM(simm13)) +#define _I_OP3_R_RR(rd, op3, rs1, rs2) \ + _I_OP3_GEN(IOP_reg, rd, op3, rs1, rs2) + +#define I_CALL(d) _I_ANY(IOP_CALL, d) +#define I_UNIMP(v) _I_IMM22(0, IOP2_UNIMP, v) +#define I_BN(a, d) _I_BRANCH(a, Icc_N, IOP2_Bicc, d) +#define I_BE(a, d) _I_BRANCH(a, Icc_E, IOP2_Bicc, d) +#define I_BZ(a, d) _I_BRANCH(a, Icc_E, IOP2_Bicc, d) +#define I_BLE(a, d) _I_BRANCH(a, Icc_LE, IOP2_Bicc, d) +#define I_BL(a, d) _I_BRANCH(a, Icc_L, IOP2_Bicc, d) +#define I_BLEU(a, d) _I_BRANCH(a, Icc_LEU, IOP2_Bicc, d) +#define I_BCS(a, d) _I_BRANCH(a, Icc_CS, IOP2_Bicc, d) +#define I_BLU(a, d) _I_BRANCH(a, Icc_CS, IOP2_Bicc, d) +#define I_BNEG(a, d) _I_BRANCH(a, Icc_NEG, IOP2_Bicc, d) +#define I_BVS(a, d) _I_BRANCH(a, Icc_VS, IOP2_Bicc, d) +#define I_BA(a, d) _I_BRANCH(a, Icc_A, IOP2_Bicc, d) +#define I_B(a, d) _I_BRANCH(a, Icc_A, IOP2_Bicc, d) +#define I_BNE(a, d) _I_BRANCH(a, Icc_NE, IOP2_Bicc, d) +#define I_BNZ(a, d) _I_BRANCH(a, Icc_NE, IOP2_Bicc, d) +#define I_BG(a, d) _I_BRANCH(a, Icc_G, IOP2_Bicc, d) +#define I_BGE(a, d) _I_BRANCH(a, Icc_GE, IOP2_Bicc, d) +#define I_BGU(a, d) _I_BRANCH(a, Icc_GU, IOP2_Bicc, d) +#define I_BCC(a, d) _I_BRANCH(a, Icc_CC, IOP2_Bicc, d) +#define I_BGEU(a, d) _I_BRANCH(a, Icc_CC, IOP2_Bicc, d) +#define I_BPOS(a, d) _I_BRANCH(a, Icc_POS, IOP2_Bicc, d) +#define I_BVC(a, d) _I_BRANCH(a, Icc_VC, IOP2_Bicc, d) +#define I_SETHI(r, v) _I_IMM22(r, 4, v) + +#define I_ORri(rd, rs1, imm) _I_OP3_R_RI(rd, IOP3_OR, rs1, imm) +#define I_ORrr(rd, rs1, rs2) _I_OP3_R_RR(rd, IOP3_OR, rs1, rs2) + +#define I_MOVi(rd, imm) _I_OP3_R_RI(rd, IOP3_OR, I_G0, imm) +#define I_MOVr(rd, rs) _I_OP3_R_RR(rd, IOP3_OR, I_G0, rs) + +#define I_RDPSR(rd) _I_OP3_R_RR(rd, IOP3_RDPSR, 0, 0) + +#define I_JMPLri(rd, rs1, imm) _I_OP3_R_RI(rd, IOP3_JMPL, rs1, imm) +#define I_JMPLrr(rd, rs1, rs2) _I_OP3_R_RR(rd, IOP3_JMPL, rs1, rs2) + +/* + * FPop values. + */ + +/* These are in FPop1 space */ +#define FMOVS 0x001 +#define FMOVD 0x002 +#define FMOVQ 0x003 +#define FNEGS 0x005 +#define FNEGD 0x006 +#define FNEGQ 0x007 +#define FABSS 0x009 +#define FABSD 0x00a +#define FABSQ 0x00b +#define FSQRTS 0x029 +#define FSQRTD 0x02a +#define FSQRTQ 0x02b +#define FADDS 0x041 +#define FADDD 0x042 +#define FADDQ 0x043 +#define FSUBS 0x045 +#define FSUBD 0x046 +#define FSUBQ 0x047 +#define FMULS 0x049 +#define FMULD 0x04a +#define FMULQ 0x04b +#define FDIVS 0x04d +#define FDIVD 0x04e +#define FDIVQ 0x04f +#define FSMULD 0x069 +#define FDMULQ 0x06e +#define FSTOX 0x081 +#define FDTOX 0x082 +#define FQTOX 0x083 +#define FXTOS 0x084 +#define FXTOD 0x088 +#define FXTOQ 0x08c +#define FITOS 0x0c4 +#define FDTOS 0x0c6 +#define FQTOS 0x0c7 +#define FITOD 0x0c8 +#define FSTOD 0x0c9 +#define FQTOD 0x0cb +#define FITOQ 0x0cc +#define FSTOQ 0x0cd +#define FDTOQ 0x0ce +#define FSTOI 0x0d1 +#define FDTOI 0x0d2 +#define FQTOI 0x0d3 + +/* These are in FPop2 space */ +#define FMVFC0S 0x001 +#define FMVFC0D 0x002 +#define FMVFC0Q 0x003 +#define FMOVZS 0x025 +#define FMOVZD 0x026 +#define FMOVZQ 0x027 +#define FMVFC1S 0x041 +#define FMVFC1D 0x042 +#define FMVFC1Q 0x043 +#define FMOVLEZS 0x045 +#define FMOVLEZD 0x046 +#define FMOVLEZQ 0x047 +#define FCMPS 0x051 +#define FCMPD 0x052 +#define FCMPQ 0x053 +#define FCMPES 0x055 +#define FCMPED 0x056 +#define FCMPEQ 0x057 +#define FMOVLZS 0x065 +#define FMOVLZD 0x066 +#define FMOVLZQ 0x067 +#define FMVFC2S 0x081 +#define FMVFC2D 0x082 +#define FMVFC2Q 0x083 +#define FMOVNZS 0x0a5 +#define FMOVNZD 0x0a6 +#define FMOVNZQ 0x0a7 +#define FMVFC3S 0x0c1 +#define FMVFC3D 0x0c2 +#define FMVFC3Q 0x0c3 +#define FMOVGZS 0x0c5 +#define FMOVGZD 0x0c6 +#define FMOVGZQ 0x0c7 +#define FMOVGEZS 0x0e5 +#define FMOVGEZD 0x0e6 +#define FMOVGEZQ 0x0e7 +#define FMVICS 0x101 +#define FMVICD 0x102 +#define FMVICQ 0x103 +#define FMVXCS 0x181 +#define FMVXCD 0x182 +#define FMVXCQ 0x183 + +/* + * FPU data types. + */ +#define FTYPE_LNG -1 /* data = 64-bit signed long integer */ +#define FTYPE_INT 0 /* data = 32-bit signed integer */ +#define FTYPE_SNG 1 /* data = 32-bit float */ +#define FTYPE_DBL 2 /* data = 64-bit double */ +#define FTYPE_EXT 3 /* data = 128-bit extended (quad-prec) */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/intr.h b/lib/libc/include/sparc64-openbsd-none/machine/intr.h new file mode 100644 index 000000000000..6e353965693a --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/intr.h @@ -0,0 +1,119 @@ +/* $OpenBSD: intr.h,v 1.26 2025/05/11 19:41:05 miod Exp $ */ +/* $NetBSD: intr.h,v 1.8 2001/01/14 23:50:30 thorpej Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_INTR_H_ +#define _MACHINE_INTR_H_ + +#include + +#include + +/* + * Interrupt handler chains. Interrupt handlers should return 0 for + * ``not me'' or 1 (``I took care of it''). intr_establish() inserts a + * handler into the list. The handler is called with its (single) + * argument, or with a pointer to a clockframe if ih_arg is NULL. + */ +struct intrhand { + int (*ih_fun)(void *); + void *ih_arg; + short ih_number; /* interrupt number */ + /* the H/W provides */ + char ih_pil; /* interrupt priority */ + char ih_mpsafe; + struct intrhand *ih_next; /* global list */ + struct intrhand *ih_pending; /* pending list */ + volatile u_int64_t *ih_map; /* interrupt map reg */ + volatile u_int64_t *ih_clr; /* clear interrupt reg */ + void (*ih_ack)(struct intrhand *); + struct evcount ih_count; /* # of interrupts */ + const void *ih_bus; /* parent bus */ + struct cpu_info *ih_cpu; /* target */ + char ih_name[32]; /* device name */ +}; + +extern struct intrhand *intrlev[MAXINTNUM]; + +void intr_establish(struct intrhand *); + +/* XXX - arbitrary numbers; no interpretation is defined yet */ +#define IPL_NONE 0 /* nothing */ +#define IPL_SOFTINT 1 /* softint */ +#define IPL_SOFTCLOCK 1 /* timeouts */ +#define IPL_SOFTNET 2 /* protocol stack */ +#define IPL_BIO PIL_BIO /* block I/O */ +#define IPL_NET PIL_NET /* network */ +#define IPL_SOFTTTY 4 /* delayed terminal handling */ +#define IPL_TTY PIL_TTY /* terminal */ +#define IPL_VM PIL_VM /* memory allocation */ +#define IPL_AUDIO PIL_AUD /* audio */ +#define IPL_CLOCK PIL_CLOCK /* clock */ +#define IPL_SERIAL PIL_SER /* serial */ +#define IPL_SCHED PIL_SCHED /* scheduler */ +#define IPL_STATCLOCK PIL_STATCLOCK /* statclock */ +#define IPL_HIGH PIL_HIGH /* everything */ + +#define spl0() _spl(IPL_NONE) +#define splsoftclock() _splraise(IPL_SOFTCLOCK) +#define splsoftnet() _splraise(IPL_SOFTNET) +#define splbio() _splraise(IPL_BIO) +#define splnet() _splraise(IPL_NET) +#define splsofttty() _splraise(IPL_SOFTTTY) +#define spltty() _splraise(IPL_TTY) +#define splvm() _splraise(IPL_VM) +#define splaudio() _splraise(IPL_AUDIO) +#define splclock() _splraise(IPL_CLOCK) +#define splserial() _splraise(IPL_SERIAL) +#define splsched() _splraise(IPL_SCHED) +#define splstatclock() _splraise(IPL_STATCLOCK) +#define splhigh() _splraise(IPL_HIGH) +#define splx(_oldipl) _splx(_oldipl) + +#define splzs() splserial() + +#define IPL_MPFLOOR IPL_SERIAL +#define IPL_MPSAFE 0x100 + +int splraise(int); +void intr_barrier(void *); + +void *softintr_establish(int, void (*)(void *), void *); +void softintr_disestablish(void *); +void softintr_schedule(void *); + +void *softintr_establish_raw(int, void (*)(void *), void *); +#define softintr_disestablish_raw(ih) softintr_disestablish(ih) +#define softintr_schedule_raw(ih) softintr_schedule(ih) + +void send_softint(int, struct intrhand *); + +#endif /* _MACHINE_INTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/ioctl_fd.h b/lib/libc/include/sparc64-openbsd-none/machine/ioctl_fd.h new file mode 100644 index 000000000000..e7fcb85fe9d2 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/ioctl_fd.h @@ -0,0 +1,130 @@ +/* $OpenBSD: ioctl_fd.h,v 1.2 2011/03/23 16:54:37 pirofti Exp $ */ +/* from: ioctl_fd.h,v 1.4 1995/06/29 03:49:32 jtk Exp */ + +/* + * Copyright (C) 1992-1994 by Joerg Wunsch, Dresden + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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(S) BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * From: Id: ioctl_fd.h,v 1.7 1994/10/30 19:17:39 joerg Exp + */ + +#ifndef _MACHINE_IOCTL_FD_H_ +#define _MACHINE_IOCTL_FD_H_ + +#define FD_FORMAT_VERSION 110 /* used to validate before formatting */ +#define FD_MAX_NSEC 36 /* highest known number of spt - allow for */ + /* 2.88 MB drives */ + +struct fd_formb { + int format_version; /* == FD_FORMAT_VERSION */ + int cyl, head; + int transfer_rate; /* fdreg.h: FDC_???KBPS */ + + union { + struct fd_form_data { + /* + * DO NOT CHANGE THE LAYOUT OF THIS STRUCTS + * it is hardware-dependant since it exactly + * matches the byte sequence to write to FDC + * during its `format track' operation + */ + u_char secshift; /* 0 -> 128, ...; usually 2 -> 512 */ + u_char nsecs; /* must be <= FD_MAX_NSEC */ + u_char gaplen; /* GAP 3 length; usually 84 */ + u_char fillbyte; /* usually 0xf6 */ + struct fd_idfield_data { + /* + * data to write into id fields; + * for obscure formats, they mustn't match + * the real values (but mostly do) + */ + u_char cylno; /* 0 thru 79 (or 39) */ + u_char headno; /* 0, or 1 */ + u_char secno; /* starting at 1! */ + u_char secsize; /* usually 2 */ + } idfields[FD_MAX_NSEC]; /* 0 <= idx < nsecs used */ + } structured; + u_char raw[1]; /* to have continuous indexed access */ + } format_info; +}; + +/* make life easier */ +# define fd_formb_secshift format_info.structured.secshift +# define fd_formb_nsecs format_info.structured.nsecs +# define fd_formb_gaplen format_info.structured.gaplen +# define fd_formb_fillbyte format_info.structured.fillbyte +/* these data must be filled in for(i = 0; i < fd_formb_nsecs; i++) */ +# define fd_formb_cylno(i) format_info.structured.idfields[i].cylno +# define fd_formb_headno(i) format_info.structured.idfields[i].headno +# define fd_formb_secno(i) format_info.structured.idfields[i].secno +# define fd_formb_secsize(i) format_info.structured.idfields[i].secsize + +/* + * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how + * we tell them apart. + */ +struct fd_type { + int sectrac; /* sectors per track */ + int heads; /* number of heads */ + int seccyl; /* sectors per cylinder */ + int secsize; /* size code for sectors */ + int datalen; /* data len when secsize = 0 */ + int steprate; /* step rate and head unload time */ + int gap1; /* gap len between sectors */ + int gap2; /* formatting gap */ + int tracks; /* total num of tracks */ + int size; /* size of disk in sectors */ + int step; /* steps per cylinder */ + int rate; /* transfer speed code */ + char *name; +}; + + +#define FD_FORM _IOW('F', 61, struct fd_formb) /* format a track */ +#define FD_GTYPE _IOR('F', 62, struct fd_type) /* get drive type */ +#define FD_STYPE _IOW('F', 63, struct fd_type) /* set drive type */ + +#define FD_GOPTS _IOR('F', 64, int) /* drive options, see below */ +#define FD_SOPTS _IOW('F', 65, int) + +#define FDOPT_NORETRY 0x0001 /* no retries on failure (cleared on close) */ +#define FDOPT_SILENT 0x0002 + +/* + * The following definitions duplicate those in sys/i386/isa/fdreg.h + * They are here since their values are to be used in the above + * structure when formatting a floppy. For very obvious reasons, both + * definitions must match ;-) + */ +#ifndef FDC_500KBPS +#define FDC_500KBPS 0x00 /* 500KBPS MFM drive transfer rate */ +#define FDC_300KBPS 0x01 /* 300KBPS MFM drive transfer rate */ +#define FDC_250KBPS 0x02 /* 250KBPS MFM drive transfer rate */ +#define FDC_125KBPS 0x03 /* 125KBPS FM drive transfer rate */ + /* for some controllers 1MPBS instead */ +#endif /* FDC_500KBPS */ + + +#endif /* !_MACHINE_IOCTL_FD_H__ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/kcore.h b/lib/libc/include/sparc64-openbsd-none/machine/kcore.h new file mode 100644 index 000000000000..6c89a84b0c80 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/kcore.h @@ -0,0 +1,61 @@ +/* $OpenBSD: kcore.h,v 1.3 2008/06/26 05:42:13 ray Exp $ */ +/* $NetBSD: kcore.h,v 1.4 2000/08/01 00:40:26 eeh Exp $ */ + +/*- + * Copyright (c) 1996 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * The layout of a kernel core on the dump device is as follows: + * a `struct kcore_seg' of type CORE_CPU + * a `struct cpu_kcore_hdr' + */ + +typedef struct cpu_kcore_hdr { + int cputype; /* CPU type associated with this dump */ + + int nmemseg; /* # of physical memory segments */ + uint64_t memsegoffset; /* start of memseg array (relative */ + /* to the start of this header) */ + + int nsegmap; /* # of kernel segs */ + uint64_t segmapoffset; /* start of segmap array (relative */ + /* to the start of this header) */ + + uint64_t kernbase; /* copy of KERNBASE goes here */ + uint64_t cpubase; /* Pointer to cpu_info structure */ + + uint64_t ktextbase; /* Virtual start of text segment */ + uint64_t ktextp; /* Physical address of 4MB locked TLB */ + uint64_t ktextsz; /* Size of locked kernel text segment. */ + + uint64_t kdatabase; /* Virtual start of data segment */ + uint64_t kdatap; /* Physical address of 4MB locked TLB */ + uint64_t kdatasz; /* Size of locked kernel data segment. */ + +} cpu_kcore_hdr_t; \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/limits.h b/lib/libc/include/sparc64-openbsd-none/machine/limits.h new file mode 100644 index 000000000000..9060a2e178d0 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/limits.h @@ -0,0 +1,55 @@ +/* $OpenBSD: limits.h,v 1.11 2015/04/30 13:42:08 millert Exp $ */ +/* $NetBSD: limits.h,v 1.8 2000/08/08 22:31:14 tshiozak Exp $ */ + +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)limits.h 8.3 (Berkeley) 1/4/94 + */ + +#ifndef _MACHINE_LIMITS_H_ +#define _MACHINE_LIMITS_H_ + +#include + +#if __POSIX_VISIBLE || __XPG_VISIBLE +#define SSIZE_MAX LONG_MAX /* max value for a ssize_t */ +#endif + +#if __BSD_VISIBLE +#define SIZE_T_MAX ULONG_MAX /* max value for a size_t (historic) */ + +/* GCC requires that quad constants be written as expressions. */ +#define UQUAD_MAX ((u_quad_t)0-1) /* max value for a uquad_t */ + /* max value for a quad_t */ +#define QUAD_MAX ((quad_t)(UQUAD_MAX >> 1)) +#define QUAD_MIN (-QUAD_MAX-1) /* min value for a quad_t */ + +#endif /* __BSD_VISIBLE */ + +#endif /* _MACHINE_LIMITS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/loadfile_machdep.h b/lib/libc/include/sparc64-openbsd-none/machine/loadfile_machdep.h new file mode 100644 index 000000000000..9902239fb27e --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/loadfile_machdep.h @@ -0,0 +1,65 @@ +/* $OpenBSD: loadfile_machdep.h,v 1.3 2013/10/17 11:54:02 miod Exp $ */ +/* $NetBSD: loadfile_machdep.h,v 1.3 2000/08/16 08:16:58 mrg Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define BOOT_ELF +#ifdef __sparc_v9__ +#define ELFSIZE 64 +#else +#define ELFSIZE 32 +#endif + +#define LOAD_KERNEL LOAD_ALL +#define COUNT_KERNEL COUNT_ALL + +#ifdef _STANDALONE +#define LOADADDR(a) (((u_long)(a) & 0x0fffffff) + offset) +#define ALIGNENTRY(a) ((u_long)(a)) +#define READ(f, b, c) read((f), (void *)LOADADDR(b), (c)) +#define BCOPY(s, d, c) memcpy((void *)LOADADDR(d), (void *)(s), (c)) +#define BZERO(d, c) memset((void *)LOADADDR(d), 0, (c)) +#define WARN(a) (void)(printf a, \ + printf((errno ? ": %s\n" : "\n"), \ + strerror(errno))) +#define PROGRESS(a) (void) printf a +#define ALLOC(a) alloc(a) +#define FREE(a, b) free(a, b) +#else +#define LOADADDR(a) (((u_long)(a)) + offset) +#define ALIGNENTRY(a) ((u_long)(a)) +#define READ(f, b, c) read((f), (void *)LOADADDR(b), (c)) +#define BCOPY(s, d, c) memcpy((void *)LOADADDR(d), (void *)(s), (c)) +#define BZERO(d, c) memset((void *)LOADADDR(d), 0, (c)) +#define WARN(a) warn a +#define PROGRESS(a) /* nothing */ +#define ALLOC(a) malloc(a) +#define FREE(a, b) free(a) +#endif \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/mdesc.h b/lib/libc/include/sparc64-openbsd-none/machine/mdesc.h new file mode 100644 index 000000000000..bffc347b6a15 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/mdesc.h @@ -0,0 +1,55 @@ +/* $OpenBSD: mdesc.h,v 1.4 2019/10/20 16:27:19 kettenis Exp $ */ +/* + * Copyright (c) 2009 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +struct md_header { + uint32_t transport_version; + uint32_t node_blk_sz; + uint32_t name_blk_sz; + uint32_t data_blk_sz; +}; + +struct md_element { + uint8_t tag; + uint8_t name_len; + uint16_t _reserved_field; + uint32_t name_offset; + union { + struct { + uint32_t data_len; + uint32_t data_offset; + } y; + uint64_t val; + } d; +}; + +#ifdef _KERNEL + +extern caddr_t mdesc; +extern size_t mdesc_len; + +extern caddr_t pri; +extern size_t pri_len; + +void mdesc_init(void); +uint64_t mdesc_get_prop_val(int, const char *); +const char *mdesc_get_prop_str(int, const char *); +const char *mdesc_get_prop_data(int, const char *, size_t *); +int mdesc_find(const char *, uint64_t); +int mdesc_find_child(int, const char *, uint64_t); +int mdesc_find_node(const char *); + +#endif \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/mutex.h b/lib/libc/include/sparc64-openbsd-none/machine/mutex.h new file mode 100644 index 000000000000..b9368872daec --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/mutex.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mutex.h,v 1.8 2018/02/19 09:18:50 mpi Exp $ */ + +#define __USE_MI_MUTEX \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/openfirm.h b/lib/libc/include/sparc64-openbsd-none/machine/openfirm.h new file mode 100644 index 000000000000..aadcaf0a9abf --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/openfirm.h @@ -0,0 +1,65 @@ +/* $OpenBSD: openfirm.h,v 1.7 2024/11/08 12:48:00 miod Exp $ */ +/* $NetBSD: openfirm.h,v 1.8 2001/07/20 00:07:14 eeh Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + */ +/* + * Prototypes for additional OpenFirmware Interface Routines + */ + +#include + +/* All cells are 8 byte slots */ +typedef u_int64_t cell_t; +#define HDL2CELL(x) (cell_t)(u_int)(int)(x) +#define ADR2CELL(x) (cell_t)(x) + +#define HDQ2CELL_HI(x) (cell_t)(0) +#define HDQ2CELL_LO(x) (cell_t)(x) + +#define CELL2HDQ(hi, lo) (lo) + +int OF_test(char *service); +int OF_test_method(int handle, char *method); + +int OF_stdin(void); +int OF_stdout(void); +void OF_set_symbol_lookup(void (*s2v)(void *), void (*v2s)(void *)); +void OF_poweroff(void); +void OF_sym2val(void *); +void OF_val2sym(void *); +int OF_milliseconds(void); +int OF_searchprop(int node, char *prop, void *buf, int buflen); +int OF_mapintr(int node, int *interrupt, int validlen, int buflen); +int OF_instance_to_path(int ihandle, char *buf, int buflen); +int OF_package_to_path(int phandle, char *buf, int buflen); + +void (*OF_set_callback(void (*)(void *)))(void *); \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/openpromio.h b/lib/libc/include/sparc64-openbsd-none/machine/openpromio.h new file mode 100644 index 000000000000..c301d356b6d1 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/openpromio.h @@ -0,0 +1,57 @@ +/* $OpenBSD: openpromio.h,v 1.3 2003/06/02 23:27:56 millert Exp $ */ +/* $NetBSD: openpromio.h,v 1.1.1.1 1998/06/20 04:58:52 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)openpromio.h 8.1 (Berkeley) 6/11/93 + */ + +struct opiocdesc { + int op_nodeid; /* passed or returned node id */ + int op_namelen; /* length of op_name */ + char *op_name; /* pointer to field name */ + int op_buflen; /* length of op_buf (value-result) */ + char *op_buf; /* pointer to field value */ +}; + +#define OPIOCGET _IOWR('O', 1, struct opiocdesc) /* get openprom field */ +#define OPIOCSET _IOW('O', 2, struct opiocdesc) /* set openprom field */ +#define OPIOCNEXTPROP _IOWR('O', 3, struct opiocdesc) /* get next property */ +#define OPIOCGETOPTNODE _IOR('O', 4, int) /* get openprom field */ +#define OPIOCGETNEXT _IOWR('O', 5, int) /* get next node of node */ +#define OPIOCGETCHILD _IOWR('O', 6, int) /* get first child of node */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/param.h b/lib/libc/include/sparc64-openbsd-none/machine/param.h new file mode 100644 index 000000000000..c3d5e1fd20d4 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/param.h @@ -0,0 +1,183 @@ +/* $OpenBSD: param.h,v 1.42 2023/12/14 13:26:49 claudio Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1996-1999 Eduardo Horvath + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ + +#define _MACHINE sparc64 +#define MACHINE "sparc64" +#define _MACHINE_ARCH sparc64 +#define MACHINE_ARCH "sparc64" +#define MID_MACHINE MID_SPARC64 + +#define PAGE_SHIFT 13 +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define PAGE_MASK (PAGE_SIZE - 1) + +/* + * Here are all the magic kernel virtual addresses and how they're allocated. + * + * First, the PROM is usually a fixed-sized block from 0x00000000f0000000 to + * 0x00000000f0100000. It also uses some space around 0x00000000fff00000 to + * map in device registers. The rest is pretty much ours to play with. + * + * The kernel starts at KERNBASE. Here's the layout. We use macros to set + * the addresses so we can relocate everything easily. We use 4MB locked TTEs + * to map in the kernel text and data segments. Any extra pages are recycled, + * so they can potentially be double-mapped. This shouldn't really be a + * problem since they're unused, but wild pointers can cause silent data + * corruption if they are in those segments. + * + * 0x0000000000000000: 64K NFO page zero + * 0x0000000000010000: Userland or PROM + * KERNBASE: 4MB kernel text and read only data + * This is mapped in the ITLB and + * Read-Only in the DTLB + * KERNBASE+0x400000: 4MB kernel data and BSS -- not in ITLB + * Contains context table, kernel pmap, + * and other important structures. + * KERNBASE+0x800000: Unmapped page -- redzone + * KERNBASE+0x802000: Process 0 stack and u-area + * KERNBASE+0x806000: 2 pages for pmap_copy_page and /dev/mem + * KERNBASE+0x80a000: Start of kernel VA segment + * KERNEND: End of kernel VA segment + * KERNEND+0x02000: Auxreg_va (unused?) + * KERNEND+0x04000: TMPMAP_VA (unused?) + * KERNEND+0x06000: message buffer. + * KERNEND+0x010000: 64K locked TTE -- different for each CPU + * Contains interrupt stack, cpu_info structure, + * and 32KB kernel TSB. + * + */ +#define KERNBASE 0x001000000 /* start of kernel virtual space */ + +#ifdef _KERNEL + +#define KERNEND 0x0e0000000 /* end of kernel virtual space */ + +#define _MAXNBPG 8192 /* fixed VAs, independent of actual NBPG */ + +#define AUXREG_VA ( KERNEND + _MAXNBPG) /* 1 page REDZONE */ +#define TMPMAP_VA ( AUXREG_VA + _MAXNBPG) +#define MSGBUF_VA ( TMPMAP_VA + _MAXNBPG) +/* + * Here's the location of the interrupt stack and CPU structure. + */ +#define INTSTACK ( KERNEND + 8*_MAXNBPG)/* 64K after kernel end */ +#define EINTSTACK ( INTSTACK + 2*USPACE) /* 32KB */ +#define CPUINFO_VA ( EINTSTACK) + +#define NBPG PAGE_SIZE /* bytes/page */ +#define PGSHIFT PAGE_SHIFT /* LOG2(PAGE_SIZE) */ +#define PGOFSET PAGE_MASK /* byte offset into page */ + +#define UPAGES 2 /* pages of u-area */ +#define USPACE (UPAGES * PAGE_SIZE) /* total size of u-area */ +#define USPACE_ALIGN 0 /* u-area alignment 0-none */ + +#define NMBCLUSTERS (64 * 1024) /* max cluster allocation */ + +#ifndef MSGBUFSIZE +#define MSGBUFSIZE (1 * PAGE_SIZE) +#endif + +#ifndef _LOCORE + +extern void delay(unsigned int); +#define DELAY(n) delay(n) + +extern int cputyp; + +#if defined (SUN4US) || defined (SUN4V) +#define CPU_ISSUN4U (cputyp == CPU_SUN4U) +#define CPU_ISSUN4US (cputyp == CPU_SUN4US) +#define CPU_ISSUN4V (cputyp == CPU_SUN4V) +#else +#define CPU_ISSUN4U (1) +#define CPU_ISSUN4US (0) +#define CPU_ISSUN4V (0) +#endif + +#endif /* _LOCORE */ + +/* + * Values for the cputyp variable. + */ +#define CPU_SUN4 0 +#define CPU_SUN4C 1 +#define CPU_SUN4M 2 +#define CPU_SUN4U 3 +#define CPU_SUN4US 4 +#define CPU_SUN4V 5 + +/* + * On a sun4u machine, the page size is 8192. + */ + +#ifndef _LOCORE +#include +#endif + +#endif /* _KERNEL */ + +#endif /* _MACHINE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/pcb.h b/lib/libc/include/sparc64-openbsd-none/machine/pcb.h new file mode 100644 index 000000000000..c98a66a72e0d --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/pcb.h @@ -0,0 +1,152 @@ +/* $OpenBSD: pcb.h,v 1.11 2022/10/21 18:55:42 miod Exp $ */ +/* $NetBSD: pcb.h,v 1.7 2000/12/29 17:12:05 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pcb.h 8.1 (Berkeley) 6/11/93 + */ + +#ifndef _MACHINE_PCB_H_ +#define _MACHINE_PCB_H_ + +#include + +#ifdef notyet +#define PCB_MAXWIN 32 /* architectural limit */ +#else +#define PCB_MAXWIN 8 /* worried about u area sizes ... */ +#endif + +/* + * SPARC Process Control Block. + * + * pcb_uw is positive if there are any user windows that are + * are currently in the CPU windows rather than on the user + * stack. Whenever we are running in the kernel with traps + * enabled, we decrement pcb_uw for each ``push'' of a CPU + * register window into the stack, and we increment it for + * each ``pull'' from the stack into the CPU. (If traps are + * disabled, or if we are in user mode, pcb_uw is junk.) + * + * To ease computing pcb_uw on traps from user mode, we keep track + * of the log base 2 of the single bit that is set in %wim. + * + * If an overflow occurs while the associated user stack pages + * are invalid (paged out), we have to store the registers + * in a page that is locked in core while the process runs, + * i.e., right here in the pcb. We also need the stack pointer + * for the last such window (but only the last, as the others + * are in each window) and the count of windows saved. We + * cheat by having a whole window structure for that one %sp. + * Thus, to save window pcb_rw[i] to memory, we write it at + * pcb_rw[i + 1].rw_in[6]. + * + * pcb_nsaved has three `kinds' of values. If 0, it means no + * registers are in the PCB (though if pcb_uw is positive, + * there may be the next time you look). If positive, it means + * there are no user registers in the CPU, but there are some + * saved in pcb_rw[]. As a special case, traps that needed + * assistance to pull user registers from the stack also store + * the registers in pcb_rw[], and set pcb_nsaved to -1. This + * special state is normally short-term: it can only last until the + * trap returns, and it can never persist across entry to user code. + */ +/* + * v9 addendum: + * + * Window handling between v8 and v9 has changed somewhat. There + * is no %wim. Instead, we have a %cwp, %cansave, %canrestore, + * %cleanwin, and %otherwin. By definition: + * + * %cansave + %canrestore + %otherwin = NWINDOWS - 2 + * + * In addition, %cleanwin >= %canrestore since restorable windows + * are considered clean. This means that by storing %canrestore + * and %otherwin, we should be able to compute the values of all + * the other registers. + * + * The only other register we need to save is %cwp because it cannot + * be trivially computed from the other registers. The %cwp is + * stored in the %tstate register, but if the machine was in a register + * window spill/fill handler, the value of that %cwp may be off by + * as much as 2 register windows. We will also store %cwp. [We will + * try to steal pcb_uw or pcb_nsaved for this purpose eventually.] + * + * To calculate what registers are in the pcb, start with pcb_cwp + * and proceed to (pcb_cwp - pcb_canrestore) % NWINDOWS. These should + * be saved to their appropriate register windows. The client routine + * (trap handler) is responsible for saving pcb_cwp + 1 [%o1-%o7] in + * the trap frame or on the stack. + * + * + * Even more addendum: + * + * With the new system for keeping track of register windows we don't + * care about anything other than pcb_uw which keeps track of how many + * full windows we have. As soon as a flush traps, we dump all user + * windows to the pcb, handle the fault, then restore all user windows. + * + * XXX we are using pcb_nsaved as the counter. pcb_uw is still a mask. + * change this as soon as the new scheme is debugged. + */ +struct pcb { + u_int64_t pcb_sp; /* sp (%o6) when switch() was called */ + u_int64_t pcb_pc; /* pc (%o7) when switch() was called */ + caddr_t pcb_onfault; /* for copyin/out */ + short pcb_pstate; /* %pstate when switch() was called -- may be useful if we support multiple memory models */ + char pcb_nsaved; /* number of windows saved in pcb */ + + /* The rest is probably not needed except for pcb_rw */ + char pcb_cwp; /* %cwp when switch() was called */ + char pcb_pil; /* %pil when switch() was called -- probably not needed */ + + const char *lastcall; /* DEBUG -- name of last system call */ + u_int64_t pcb_wcookie; + + /* the following MUST be aligned on a 64-bit boundary */ + struct rwindow pcb_rw[PCB_MAXWIN]; /* saved windows */ + u_int64_t pcb_rwsp[PCB_MAXWIN]; +}; + +#ifndef _KERNEL +/* Let gdb compile. We need fancier macros to make these make sense. */ +#define pcb_psr pcb_pstate +#define pcb_wim pcb_cwp +#endif /* _KERNEL */ + +#endif /* _MACHINE_PCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/pci_machdep.h b/lib/libc/include/sparc64-openbsd-none/machine/pci_machdep.h new file mode 100644 index 000000000000..f42a581bd4fc --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/pci_machdep.h @@ -0,0 +1,137 @@ +/* $OpenBSD: pci_machdep.h,v 1.38 2020/06/23 01:21:29 jmatthew Exp $ */ +/* $NetBSD: pci_machdep.h,v 1.7 2001/07/20 00:07:14 eeh Exp $ */ + +/* + * Copyright (c) 1999 Matthew R. Green + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_PCI_MACHDEP_H_ +#define _MACHINE_PCI_MACHDEP_H_ + +/* + * Forward declarations. + */ +struct pci_attach_args; + +/* + * define some bits used to glue into the common PCI code. + */ + +#define __HAVE_PCI_MSIX + +typedef struct sparc_pci_chipset *pci_chipset_tag_t; + +#define PCI_INTR_INTX 0x00000000 +#define PCI_INTR_MSI 0x80000000 +#define PCI_INTR_MSIX 0x40000000 +#define PCI_INTR_TYPE_MASK 0xc0000000 +#define PCI_INTR_TYPE(_ih) ((_ih) & PCI_INTR_TYPE_MASK) + +#define PCI_INTR_TAG_MASK 0x00ffff00 +#define PCI_INTR_TAG(_ih) ((_ih) & PCI_INTR_TAG_MASK) + +#define PCI_INTR_VEC_MASK 0x000000ff +#define PCI_INTR_VEC(_ih) ((_ih) & PCI_INTR_VEC_MASK) +typedef u_int pci_intr_handle_t; + +/* + * The stuuuuuuupid allegedly MI PCI code expects pcitag_t to be a + * scalar type. But we really need to store both the OFW node and + * the bus/device/function info in it. (We'd like to store more, + * like all the ofw properties, but we don't need to.) Luckily, + * both are 32-bit values, so we can squeeze them into a u_int64_t + * with a little help from some macros. + */ + +#define PCITAG_NODE(x) (int)(((x)>>32)&0xffffffff) +#define PCITAG_OFFSET(x) ((x)&0xffffffff) +#define PCITAG_BUS(t) ((PCITAG_OFFSET(t)>>16)&0xff) +#define PCITAG_DEV(t) ((PCITAG_OFFSET(t)>>11)&0x1f) +#define PCITAG_FUN(t) ((PCITAG_OFFSET(t)>>8)&0x7) +#define PCITAG_CREATE(n,b,d,f) (((u_int64_t)(n)<<32)|((b)<<16)|((d)<<11)|((f)<<8)) +#define PCITAG_SETNODE(t,n) ((t)&0xffffffff)|(((n)<<32) +typedef u_int64_t pcitag_t; + +struct sparc_pci_chipset { + void *cookie; + bus_space_tag_t bustag; + bus_space_handle_t bushandle; + int rootnode; /* PCI controller */ + int busnode[256]; + int (*conf_size)(pci_chipset_tag_t, pcitag_t); + pcireg_t (*conf_read)(pci_chipset_tag_t, pcitag_t, int); + void (*conf_write)(pci_chipset_tag_t, pcitag_t, int, pcireg_t); + int (*intr_map)(struct pci_attach_args *, pci_intr_handle_t *); + int (*probe_device_hook)(void *, struct pci_attach_args *); +}; + +void pci_attach_hook(struct device *, struct device *, + struct pcibus_attach_args *); +int pci_probe_device_hook(pci_chipset_tag_t, + struct pci_attach_args *); +int pci_bus_maxdevs(pci_chipset_tag_t, int); +pcitag_t pci_make_tag(pci_chipset_tag_t, int, int, int); +void pci_decompose_tag(pci_chipset_tag_t, pcitag_t, int *, int *, + int *); +int pci_conf_size(pci_chipset_tag_t, pcitag_t); +pcireg_t pci_conf_read(pci_chipset_tag_t, pcitag_t, int); +void pci_conf_write(pci_chipset_tag_t, pcitag_t, int, + pcireg_t); +int pci_intr_map(struct pci_attach_args *, pci_intr_handle_t *); +int pci_intr_map_msi(struct pci_attach_args *, pci_intr_handle_t *); +int pci_intr_map_msix(struct pci_attach_args *, int, + pci_intr_handle_t *); +int pci_intr_line(pci_chipset_tag_t, pci_intr_handle_t); +const char *pci_intr_string(pci_chipset_tag_t, pci_intr_handle_t); +void *pci_intr_establish(pci_chipset_tag_t, pci_intr_handle_t, + int, int (*)(void *), void *, const char *); +void *pci_intr_establish_cpu(pci_chipset_tag_t, pci_intr_handle_t, + int, struct cpu_info *, + int (*)(void *), void *, const char *); +void pci_intr_disestablish(pci_chipset_tag_t, void *); + +void pci_msi_enable(pci_chipset_tag_t, pcitag_t, bus_addr_t, int); +void pci_msix_enable(pci_chipset_tag_t, pcitag_t, bus_space_tag_t, + int, bus_addr_t, uint32_t); +int pci_msix_table_map(pci_chipset_tag_t, pcitag_t, + bus_space_tag_t, bus_space_handle_t *); +void pci_msix_table_unmap(pci_chipset_tag_t, pcitag_t, + bus_space_tag_t, bus_space_handle_t); + +int sparc64_pci_enumerate_bus(struct pci_softc *, + int (*match)(struct pci_attach_args *), + struct pci_attach_args *); + +#define PCI_MACHDEP_ENUMERATE_BUS sparc64_pci_enumerate_bus + +#define pci_min_powerstate(c, t) (PCI_PMCSR_STATE_D3) +#define pci_set_powerstate_md(c, t, s, p) + +#define pciide_machdep_compat_intr_establish(a, b, c, d, e) (NULL) +#define pciide_machdep_compat_intr_disestablish(a, b) do { } while (0) + +#define pci_dev_postattach(a, b) + +#endif /* _MACHINE_PCI_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/pmap.h b/lib/libc/include/sparc64-openbsd-none/machine/pmap.h new file mode 100644 index 000000000000..e5cad9b40fe1 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/pmap.h @@ -0,0 +1,214 @@ +/* $OpenBSD: pmap.h,v 1.41 2025/09/18 14:54:33 kettenis Exp $ */ +/* $NetBSD: pmap.h,v 1.16 2001/04/22 23:19:30 thorpej Exp $ */ + +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_PMAP_H_ +#define _MACHINE_PMAP_H_ + +#ifndef _LOCORE +#ifdef _KERNEL +#include +#endif +#include +#endif + +#define __HAVE_PMAP_PURGE + +/* + * This scheme uses 2-level page tables. + * + * While we're still in 32-bit mode we do the following: + * + * offset: 13 bits + * 1st level: 1024 64-bit TTEs in an 8K page for 10 bits + * 2nd level: 512 32-bit pointers in the pmap for 9 bits + * ------- + * total: 32 bits + * + * In 64-bit mode the Spitfire and Blackbird CPUs support only + * 44-bit virtual addresses. All addresses between + * 0x0000 07ff ffff ffff and 0xffff f800 0000 0000 are in the + * "VA hole" and trap, so we don't have to track them. However, + * we do need to keep them in mind during PT walking. If they + * ever change the size of the address "hole" we need to rework + * all the page table handling. + * + * offset: 13 bits + * 1st level: 1024 64-bit TTEs in an 8K page for 10 bits + * 2nd level: 1024 64-bit pointers in an 8K page for 10 bits + * 3rd level: 1024 64-bit pointers in the segmap for 10 bits + * ------- + * total: 43 bits + * + * Of course, this means for 32-bit spaces we always have a (practically) + * wasted page for the segmap (only one entry used) and half a page wasted + * for the page directory. We still have need of one extra bit 8^(. + */ + +#define HOLESHIFT (43) + +#define PTSZ (PAGE_SIZE/8) +#define PDSZ (PTSZ) +#define STSZ (PTSZ) + +#define PTSHIFT (13) +#define PDSHIFT (10+PTSHIFT) +#define STSHIFT (10+PDSHIFT) + +#define PTMASK (PTSZ-1) +#define PDMASK (PDSZ-1) +#define STMASK (STSZ-1) + +#ifndef _LOCORE + +#define va_to_seg(v) (int)((((paddr_t)(v))>>STSHIFT)&STMASK) +#define va_to_dir(v) (int)((((paddr_t)(v))>>PDSHIFT)&PDMASK) +#define va_to_pte(v) (int)((((paddr_t)(v))>>PTSHIFT)&PTMASK) + +#ifdef _KERNEL + +/* + * Support for big page sizes. This maps the page size to the + * page bits. + */ +struct page_size_map { + u_int64_t mask; + u_int64_t code; +#ifdef DEBUG + u_int64_t use; +#endif +}; +extern const struct page_size_map page_size_map[]; + +struct pmap { + struct mutex pm_mtx; + int pm_ctx; /* Current context */ + int pm_refs; /* ref count */ + /* + * This contains 64-bit pointers to pages that contain + * 1024 64-bit pointers to page tables. All addresses + * are physical. + * + * !!! Only touch this through pseg_get() and pseg_set() !!! + */ + paddr_t pm_physaddr; /* physical address of pm_segs */ + int64_t *pm_segs; + + struct pmap_statistics pm_stats; +}; + +/* + * This comes from the PROM and is used to map prom entries. + */ +struct prom_map { + u_int64_t vstart; + u_int64_t vsize; + u_int64_t tte; +}; + +#define PMAP_NC 0x001 /* Set the E bit in the page */ +#define PMAP_NVC 0x002 /* Don't enable the virtual cache */ +#define PMAP_NOCACHE PMAP_NC +#define PMAP_LITTLE 0x004 /* Map in little endian mode */ +/* Large page size hints -- we really should use another param to pmap_enter() */ +#define PMAP_8K 0x000 +#define PMAP_64K 0x008 /* Use 64K page */ +#define PMAP_512K 0x010 +#define PMAP_4M 0x018 +#define PMAP_SZ_TO_TTE(x) (((x)&0x018)<<58) +/* If these bits are different in va's to the same PA then there is an aliasing in the d$ */ +#define VA_ALIAS_ALIGN (1<<14) +#define VA_ALIAS_MASK (VA_ALIAS_ALIGN - 1) + +typedef struct pmap *pmap_t; + +extern struct pmap kernel_pmap_; +#define pmap_kernel() (&kernel_pmap_) + +/* int pmap_change_wiring(pmap_t pm, vaddr_t va, boolean_t wired); */ +#define pmap_resident_count(pm) ((pm)->pm_stats.resident_count) +#define pmap_update(pm) /* nothing (yet) */ + +#define pmap_proc_iflush(p,va,len) /* nothing */ +#define pmap_init_percpu() do { /* nothing */ } while (0) + +void pmap_bootstrap(u_long, u_long, u_int, u_int); +int pmap_copyinsn(pmap_t, vaddr_t, uint32_t *); + +/* make sure all page mappings are modulo 16K to prevent d$ aliasing */ +#define PMAP_PREFER +/* pmap prefer alignment */ +#define PMAP_PREFER_ALIGN() (VA_ALIAS_ALIGN) +/* pmap prefer offset in alignment */ +#define PMAP_PREFER_OFFSET(of) ((of) & VA_ALIAS_MASK) + +#define PMAP_CHECK_COPYIN CPU_ISSUN4V + +#define PMAP_GROWKERNEL /* turn on pmap_growkernel interface */ + +/* SPARC specific? */ +int pmap_dumpsize(void); +int pmap_dumpmmu(int (*)(dev_t, daddr_t, caddr_t, size_t), daddr_t); +int pmap_pa_exists(paddr_t); + +/* SPARC64 specific */ +int ctx_alloc(struct pmap*); +void ctx_free(struct pmap*); + +#endif /* _KERNEL */ + +/* + * For each struct vm_page, there is a list of all currently valid virtual + * mappings of that page. + */ +typedef struct pv_entry { + struct pv_entry *pv_next; /* next pv_entry */ + struct pmap *pv_pmap; /* pmap where mapping lies */ + vaddr_t pv_va; /* virtual address for mapping */ +} *pv_entry_t; +/* PV flags encoded in the low bits of the VA of the first pv_entry */ + +struct vm_page_md { + struct mutex pvmtx; + struct pv_entry pvent; +}; + +#define VM_MDPAGE_INIT(pg) do { \ + mtx_init(&(pg)->mdpage.pvmtx, IPL_VM); \ + (pg)->mdpage.pvent.pv_next = NULL; \ + (pg)->mdpage.pvent.pv_pmap = NULL; \ + (pg)->mdpage.pvent.pv_va = 0; \ +} while (0) + +#endif /* _LOCORE */ +#endif /* _MACHINE_PMAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/proc.h b/lib/libc/include/sparc64-openbsd-none/machine/proc.h new file mode 100644 index 000000000000..55fd5598d909 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/proc.h @@ -0,0 +1,52 @@ +/* $OpenBSD: proc.h,v 1.10 2024/11/07 05:24:43 jsg Exp $ */ +/* $NetBSD: proc.h,v 1.2 1999/11/06 20:13:50 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)proc.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * Machine-dependent part of the proc structure for SPARC. + */ +struct mdproc { + struct trapframe *md_tf; /* trap/syscall registers */ + struct fpstate *md_fpstate; /* fpu state, if any; always resident */ + volatile int md_astpending; + paddr_t md_pcbpaddr; +}; \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/profile.h b/lib/libc/include/sparc64-openbsd-none/machine/profile.h new file mode 100644 index 000000000000..477b98523688 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/profile.h @@ -0,0 +1,74 @@ +/* $OpenBSD: profile.h,v 1.4 2012/08/22 17:19:35 pascal Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)profile.h 8.1 (Berkeley) 6/11/93 + */ + +#ifdef __PIC__ +/* Inline expansion of PICCY_SET() (see ). */ +#define MCOUNT \ + __asm__(".global _mcount");\ + __asm__("_mcount:");\ + __asm__("add %o7, 8, %o1");\ + __asm__("1: rd %pc, %o2");\ + __asm__("add %o2, __mcount-1b, %o2");\ + __asm__("ld [%o2], %o2");\ + __asm__("jmpl %o2, %g0");\ + __asm__("add %i7, 8, %o0"); +#else +#define MCOUNT \ + __asm__(".global _mcount");\ + __asm__("_mcount:");\ + __asm__("add %i7, 8, %o0");\ + __asm__("sethi %hi(__mcount), %o2");\ + __asm__("jmpl %o2 + %lo(__mcount), %g0");\ + __asm__("add %o7, 8, %o1"); +#endif + +#define _MCOUNT_DECL static void __mcount + +#ifdef _KERNEL +/* + * Block interrupts during mcount so that those interrupts can also be + * counted (as soon as we get done with the current counting). On the + * SPARC, we just splhigh/splx as those do not recursively invoke mcount. + */ +#define MCOUNT_ENTER s = splhigh() +#define MCOUNT_EXIT splx(s) +#endif /* _KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/psl.h b/lib/libc/include/sparc64-openbsd-none/machine/psl.h new file mode 100644 index 000000000000..84f4b94cac45 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/psl.h @@ -0,0 +1,327 @@ +/* $OpenBSD: psl.h,v 1.37 2024/11/06 07:11:14 miod Exp $ */ +/* $NetBSD: psl.h,v 1.20 2001/04/13 23:30:05 thorpej Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)psl.h 8.1 (Berkeley) 6/11/93 + */ + +#ifndef _SPARC64_PSL_ +#define _SPARC64_PSL_ + +/* Interesting spl()s */ +#define PIL_SCSI 3 +#define PIL_BIO 5 +#define PIL_VIDEO 5 +#define PIL_TTY 6 +#define PIL_NET 6 +#define PIL_VM 7 +#define PIL_AUD 8 +#define PIL_CLOCK 10 +#define PIL_FD 11 +#define PIL_SER 12 +#define PIL_STATCLOCK 14 +#define PIL_HIGH 15 +#define PIL_SCHED PIL_STATCLOCK + +/* + * SPARC V9 CCR register + */ + +#define ICC_C 0x01L +#define ICC_V 0x02L +#define ICC_Z 0x04L +#define ICC_N 0x08L +#define XCC_SHIFT 4 +#define XCC_C (ICC_C< 0) { \ + splassert_check(__wantipl, __func__); \ + } \ +} while (0) +#define splsoftassert(wantipl) splassert(wantipl) +#else +#define splassert(wantipl) do { /* nada */ } while (0) +#define splsoftassert(wantipl) do { /* nada */ } while (0) +#endif + +/* + * GCC pseudo-functions for manipulating privileged registers + */ +static inline u_int64_t getpstate(void); +static inline u_int64_t +getpstate(void) +{ + return (sparc_rdpr(pstate)); +} + +static inline void setpstate(u_int64_t); +static inline void +setpstate(u_int64_t newpstate) +{ + sparc_wrpr(pstate, newpstate, 0); +} + +static inline int getcwp(void); +static inline int +getcwp(void) +{ + return (sparc_rdpr(cwp)); +} + +static inline void setcwp(u_int64_t); +static inline void +setcwp(u_int64_t newcwp) +{ + sparc_wrpr(cwp, newcwp, 0); +} + +static inline u_int64_t getver(void); +static inline u_int64_t +getver(void) +{ + return (sparc_rdpr(ver)); +} + +static inline u_int64_t intr_disable(void); +static inline u_int64_t +intr_disable(void) +{ + u_int64_t s; + + s = sparc_rdpr(pstate); + sparc_wrpr(pstate, s & ~PSTATE_IE, 0); + return (s); +} + +static inline void intr_restore(u_int64_t); +static inline void +intr_restore(u_int64_t s) +{ + sparc_wrpr(pstate, s, 0); +} + +static inline void stxa_sync(u_int64_t, u_int64_t, u_int64_t); +static inline void +stxa_sync(u_int64_t va, u_int64_t asi, u_int64_t val) +{ + u_int64_t s = intr_disable(); + stxa_nc(va, asi, val); + __asm volatile("membar #Sync" : : : "memory"); + intr_restore(s); +} + +static inline int +_spl(int newipl) +{ + int oldpil; + + __asm volatile( " rdpr %%pil, %0 \n" + " wrpr %%g0, %1, %%pil \n" + : "=&r" (oldpil) + : "I" (newipl) + : "%g0"); + __asm volatile("" : : : "memory"); + + return (oldpil); +} + +/* A non-priority-decreasing version of SPL */ +static inline int +_splraise(int newpil) +{ + int oldpil; + + oldpil = sparc_rdpr(pil); + if (newpil > oldpil) + sparc_wrpr(pil, newpil, 0); + return (oldpil); +} + +static inline void +_splx(int newpil) +{ + sparc_wrpr(pil, newpil, 0); +} + +#endif /* KERNEL && !_LOCORE */ + +#endif /* _SPARC64_PSL_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/pte.h b/lib/libc/include/sparc64-openbsd-none/machine/pte.h new file mode 100644 index 000000000000..50afa9a98baf --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/pte.h @@ -0,0 +1,204 @@ +/* $OpenBSD: pte.h,v 1.17 2024/04/14 19:08:09 miod Exp $ */ +/* $NetBSD: pte.h,v 1.7 2001/07/31 06:55:46 eeh Exp $ */ + +/* + * Copyright (c) 1996-1999 Eduardo Horvath + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _MACHINE_PTE_H_ +#define _MACHINE_PTE_H_ + +/* virtual address to virtual page number */ +#define VA_SUN4U_VPG(va) (((int)(va) >> 13) & 31) + +/* virtual address to offset within page */ +#define VA_SUN4U_OFF(va) (((int)(va)) & 0x1FFF) + +/* When we go to 64-bit VAs we need to handle the hole */ +#define VA_VPG(va) VA_SUN4U_VPG(va) +#define VA_OFF(va) VA_SUN4U_OFF(va) + +#define PG_SHIFT4U 13 +#define MMU_PAGE_ALIGN 8192 + +/* If you know where a tte is in the tsb, how do you find its va? */ +#define TSBVA(i) ((tsb[(i)].tag.f.tag_va<<22)|(((i)<<13)&0x3ff000)) + +#ifndef _LOCORE +/* + * This is the spitfire TTE. + */ +#if 0 /* We don't use bitfields anyway. */ +struct sun4u_tag_fields { + u_int64_t tag_g:1, /* global flag */ + tag_ctxt:15, /* context for mapping */ + tag_unassigned:6, + tag_va:42; /* virtual address bits<64:22> */ +}; +union sun4u_tag { struct sun4u_tag_fields f; int64_t tag; }; +struct sun4u_data_fields { + u_int64_t data_v:1, /* valid bit */ + data_size:2, /* page size [8K*8**] */ + data_nfo:1, /* no-fault only */ + data_ie:1, /* invert endianness [inefficient] */ + data_soft2:2, /* reserved for S/W */ + data_pa:36, /* physical address */ + data_accessed:1,/* S/W accessed bit */ + data_modified:1,/* S/W modified bit */ + data_realw:1, /* S/W real writable bit (to manage modified) */ + data_tsblock:1, /* S/W TSB locked entry */ + data_exec:1, /* S/W Executable */ + data_onlyexec:1,/* S/W Executable only */ + data_lock:1, /* lock into TLB */ + data_cacheable:2, /* cacheability control */ + data_e:1, /* explicit accesses only */ + data_priv:1, /* privileged page */ + data_w:1, /* writeable */ + data_g:1; /* same as tag_g */ +}; +union sun4u_data { struct sun4u_data_fields f; int64_t data; }; +struct sun4u_tte { + union sun4u_tag tag; + union sun4u_data data; +}; +#else +struct sun4u_tte { + int64_t tag; + int64_t data; +}; +#endif +typedef struct sun4u_tte pte_t; + +/* Assembly routine to flush a mapping */ +extern void (*sp_tlb_flush_pte)(vaddr_t, uint64_t); +extern void (*sp_tlb_flush_ctx)(uint64_t); + +#if defined(MULTIPROCESSOR) +void smp_tlb_flush_pte(vaddr_t, uint64_t); +void smp_tlb_flush_ctx(uint64_t); +#define tlb_flush_pte(va,ctx) smp_tlb_flush_pte(va, ctx) +#define tlb_flush_ctx(ctx) smp_tlb_flush_ctx(ctx) +#else +#define tlb_flush_pte(va,ctx) (*sp_tlb_flush_pte)(va, ctx) +#define tlb_flush_ctx(ctx) (*sp_tlb_flush_ctx)(ctx) +#endif + +#endif /* _LOCORE */ + +/* TSB tag masks */ +#define CTX_MASK ((1<<13)-1) +#define TSB_TAG_CTX_SHIFT 48 +#define TSB_TAG_VA_SHIFT 22 + +#define TSB_TAG_LOCKED 0x0000040000000000LL + +#define TSB_TAG_G 0x8000000000000000LL +#define TSB_TAG_CTX(t) ((((int64_t)(t))>>TSB_TAG_CTX_SHIFT)&CTX_MASK) +#define TSB_TAG_VA(t) ((((int64_t)(t))<>TSB_TAG_VA_SHIFT)) + +/* Page sizes */ +#define PGSZ_8K 0 +#define PGSZ_64K 1 +#define PGSZ_512K 2 +#define PGSZ_4M 3 + +#define SUN4U_PGSZ_SHIFT 61 +#define SUN4U_TLB_SZ(s) (((uint64_t)(s)) << SUN4U_PGSZ_SHIFT) + +/* TLB data masks */ +#define SUN4U_TLB_V 0x8000000000000000LL +#define SUN4U_TLB_8K SUN4U_TLB_SZ(PGSZ_8K) +#define SUN4U_TLB_64K SUN4U_TLB_SZ(PGSZ_64K) +#define SUN4U_TLB_512K SUN4U_TLB_SZ(PGSZ_512K) +#define SUN4U_TLB_4M SUN4U_TLB_SZ(PGSZ_4M) +#define SUN4U_TLB_SZ_MASK 0x6000000000000000LL +#define SUN4U_TLB_NFO 0x1000000000000000LL +#define SUN4U_TLB_IE 0x0800000000000000LL +#define SUN4U_TLB_SOFT2_MASK 0x07fc000000000000LL +#define SUN4U_TLB_RESERVED_MASK 0x0003800000000000LL +#define SUN4U_TLB_PA_MASK 0x00007fffffffe000LL +#define SUN4U_TLB_SOFT_MASK 0x0000000000001f80LL +/* S/W bits */ +#define SUN4U_TLB_ACCESS 0x0000000000000200LL +#define SUN4U_TLB_MODIFY 0x0000000000000800LL +#define SUN4U_TLB_REAL_W 0x0000000000000400LL +#define SUN4U_TLB_TSB_LOCK 0x0000000000001000LL +#define SUN4U_TLB_EXEC 0x0000000000000100LL +#define SUN4U_TLB_EXEC_ONLY 0x0000000000000080LL +/* H/W bits */ +#define SUN4U_TLB_L 0x0000000000000040LL +#define SUN4U_TLB_CACHE_MASK 0x0000000000000030LL +#define SUN4U_TLB_CP 0x0000000000000020LL +#define SUN4U_TLB_CV 0x0000000000000010LL +#define SUN4U_TLB_E 0x0000000000000008LL +#define SUN4U_TLB_P 0x0000000000000004LL +#define SUN4U_TLB_W 0x0000000000000002LL +#define SUN4U_TLB_G 0x0000000000000001LL + +#define SUN4U_TSB_DATA(g,sz,pa,priv,write,cache,aliased,valid,ie) \ +(((valid)?SUN4U_TLB_V:0LL)|SUN4U_TLB_SZ(sz)|\ +(((u_int64_t)(pa))&SUN4U_TLB_PA_MASK)|\ +((cache)?((aliased)?SUN4U_TLB_CP:SUN4U_TLB_CACHE_MASK):SUN4U_TLB_E)|\ +((priv)?SUN4U_TLB_P:0LL)|((write)?SUN4U_TLB_W:0LL)|((g)?SUN4U_TLB_G:0LL)|\ +((ie)?SUN4U_TLB_IE:0LL)) + +#define SUN4V_PGSZ_SHIFT 0 +#define SUN4V_TLB_SZ(s) (((uint64_t)(s))<rb_bt, (addr), (size), (flags), (hp)) +#define md_space_unmap(rbt, h, size, addrp) \ + do { \ + *addrp = (rbt)->rb_bt->sparc_bus_addr((rbt)->rb_bt, \ + (rbt)->rb_bt, (h)); \ + bus_space_unmap((rbt)->rb_bt, (h), (size)); \ + } while (0) + +void pccbb_attach_hook(struct device *, struct device *, + struct pci_attach_args *); + +#endif /* _MACHINE_RBUS_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/reg.h b/lib/libc/include/sparc64-openbsd-none/machine/reg.h new file mode 100644 index 000000000000..cd4dc0304dce --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/reg.h @@ -0,0 +1,92 @@ +/* $OpenBSD: reg.h,v 1.9 2024/03/29 21:14:31 miod Exp $ */ +/* $NetBSD: reg.h,v 1.8 2001/06/19 12:59:16 wiz Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)reg.h 8.1 (Berkeley) 6/11/93 + */ + +#ifndef _MACHINE_REG_H_ +#define _MACHINE_REG_H_ + +/* + * The v9 register window. Each stack pointer (%o6 aka %sp) in each window + * must ALWAYS point to some place at which it is safe to scribble on + * 64 bytes. (If not, your process gets mangled.) Furthermore, each + * stack pointer should be aligned on a 16-byte boundary (plus the BIAS) + * for v9 stacks (the kernel as currently coded allows arbitrary alignment, + * but with a hefty performance penalty). + */ +struct rwindow { + int64_t rw_local[8]; /* %l0..%l7 */ + int64_t rw_in[8]; /* %i0..%i7 */ +}; + +struct reg { + int64_t r_tstate; /* tstate register */ + int64_t r_pc; /* return pc */ + int64_t r_npc; /* return npc */ + int r_y; /* %y register -- 32-bits */ + int64_t r_global[8]; /* %g* registers in trap's caller */ + int64_t r_out[8]; /* %o* registers in trap's caller */ + int64_t r_local[8]; /* %l* registers in trap's caller */ + int64_t r_in[8]; /* %i* registers in trap's caller */ +}; + +/* + * FP coprocessor registers. + */ + +struct fpstate { + u_int fs_regs[64]; /* our view is 64 32-bit registers */ + int64_t fs_fsr; /* %fsr */ + int fs_gsr; /* graphics state reg */ +}; + +/* + * The actual FP registers are made accessible (c.f. ptrace(2)) through + * a `struct fpreg'; relies on the + * fact that `fpreg' is a prefix of `fpstate'. + */ +struct fpreg { + u_int fr_regs[64]; /* our view is 64 32-bit registers */ + int64_t fr_fsr; /* %fsr */ + int fr_gsr; /* graphics state reg */ +}; + +#endif /* _MACHINE_REG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/reloc.h b/lib/libc/include/sparc64-openbsd-none/machine/reloc.h new file mode 100644 index 000000000000..6e23309ed504 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/reloc.h @@ -0,0 +1,36 @@ +/* $OpenBSD: reloc.h,v 1.5 2011/03/23 16:54:37 pirofti Exp $ */ +/* + * Copyright (c) 2001 Artur Grabowski + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_RELOC_H_ +#define _MACHINE_RELOC_H_ + +#define RELOC_NONE 0 + +#define RELOC_COPY 19 +#define RELOC_GLOB_DAT 20 +#define RELOC_JMP_SLOT 21 +#define RELOC_RELATIVE 22 +#define RELOC_64 32 +#define RELOC_UA64 54 +#define RELOC_TLS_DTPMOD32 74 +#define RELOC_TLS_DTPMOD64 75 +#define RELOC_TLS_DTPOFF32 76 +#define RELOC_TLS_DTPOFF64 77 +#define RELOC_TLS_TPOFF32 78 +#define RELOC_TLS_TPOFF64 79 + +#endif /* _MACHINE_RELOC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/setjmp.h b/lib/libc/include/sparc64-openbsd-none/machine/setjmp.h new file mode 100644 index 000000000000..54523bed4344 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/setjmp.h @@ -0,0 +1,7 @@ +/* $OpenBSD: setjmp.h,v 1.1 2001/08/23 15:32:01 art Exp $ */ + +/* + * machine/setjmp.h: machine dependent setjmp-related information. + */ + +#define _JBLEN 14 /* size, in longs, of a jmp_buf */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/signal.h b/lib/libc/include/sparc64-openbsd-none/machine/signal.h new file mode 100644 index 000000000000..e94d2341af48 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/signal.h @@ -0,0 +1,87 @@ +/* $OpenBSD: signal.h,v 1.13 2024/03/29 21:16:38 miod Exp $ */ +/* $NetBSD: signal.h,v 1.10 2001/05/09 19:50:49 kleink Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)signal.h 8.1 (Berkeley) 6/11/93 + */ + +#ifndef _MACHINE_SIGNAL_H_ +#define _MACHINE_SIGNAL_H_ + +#include + +typedef int sig_atomic_t; + +#if __BSD_VISIBLE || __XPG_VISIBLE >= 420 +/* + * Information pushed on stack when a signal is delivered. + * This is used by the kernel to restore state following + * execution of the signal handler. It is also made available + * to the handler to allow it to restore state properly if + * a non-standard exit is performed. + */ +struct sigcontext { + long sc_cookie; + /* begin machine dependent portion */ + long sc_sp; /* %sp to restore */ + long sc_pc; /* pc to restore */ + long sc_npc; /* npc to restore */ + long sc_tstate; /* tstate to restore */ + long sc_g1; /* %g1 to restore */ + long sc_o0; /* %o0 to restore */ + int sc_mask; /* signal mask to restore */ +}; +#endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ + +#if defined(_KERNEL) +/* + * `Code' arguments to signal handlers. The names, and the funny numbering. + * are defined so as to match up with what SunOS uses; I have no idea why + * they did the numbers that way, except maybe to match up with the 68881. + */ +#define FPE_INTOVF_TRAP 0x01 /* integer overflow */ +#define FPE_INTDIV_TRAP 0x14 /* integer divide by zero */ +#define FPE_FLTINEX_TRAP 0xc4 /* inexact */ +#define FPE_FLTDIV_TRAP 0xc8 /* divide by zero */ +#define FPE_FLTUND_TRAP 0xcc /* underflow */ +#define FPE_FLTOPERR_TRAP 0xd0 /* operand error */ +#define FPE_FLTOVF_TRAP 0xd4 /* overflow */ +#endif + +#endif /* !_MACHINE_SIGNAL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/sparc64.h b/lib/libc/include/sparc64-openbsd-none/machine/sparc64.h new file mode 100644 index 000000000000..16b33d5f7759 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/sparc64.h @@ -0,0 +1,65 @@ +/* $OpenBSD: sparc64.h,v 1.14 2018/08/28 00:00:42 dlg Exp $ */ +/* $NetBSD: sparc64.h,v 1.3 2000/10/20 05:47:03 mrg Exp $ */ + +/* + * Copyright (C) 1996 Wolfgang Solfrank. + * Copyright (C) 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _MACHINE_SPARC64_H_ +#define _MACHINE_SPARC64_H_ + +struct mem_region { + u_int64_t start; + u_int64_t size; +}; + +int prom_set_trap_table(vaddr_t tba, paddr_t mmfsa); +paddr_t prom_vtop(vaddr_t vaddr); +vaddr_t prom_claim_virt(vaddr_t vaddr, int len); +vaddr_t prom_alloc_virt(int len, int align); +int prom_free_virt(vaddr_t vaddr, int len); +int prom_unmap_virt(vaddr_t vaddr, int len); +int prom_map_phys(paddr_t paddr, off_t size, vaddr_t vaddr, int mode); +paddr_t prom_alloc_phys(int len, int align); +paddr_t prom_claim_phys(paddr_t phys, int len); +int prom_free_phys(paddr_t paddr, int len); +paddr_t prom_get_msgbuf(int len, int align); +int prom_itlb_load(int index, u_int64_t data, vaddr_t vaddr); +int prom_dtlb_load(int index, u_int64_t data, vaddr_t vaddr); +void prom_start_cpu(int cpu, void *func, long arg); +void prom_start_cpu_by_cpuid(int cpu, void *func, long arg); +const char *prom_serengeti_set_console_input(const char *); +uint64_t prom_set_sun4v_api_version(uint64_t, uint64_t, uint64_t, uint64_t *); +void prom_sun4v_soft_state_supported(void); + +/* + * Debug + */ +void prom_printf(const char *, ...); +#endif /* _MACHINE_SPARC64_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/spinlock.h b/lib/libc/include/sparc64-openbsd-none/machine/spinlock.h new file mode 100644 index 000000000000..4a30761476a9 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/spinlock.h @@ -0,0 +1,10 @@ +/* $OpenBSD: spinlock.h,v 1.3 2017/09/05 02:40:54 guenther Exp $ */ + +#ifndef _MACHINE_SPINLOCK_H_ +#define _MACHINE_SPINLOCK_H_ + +#define _ATOMIC_LOCK_UNLOCKED (0x00) +#define _ATOMIC_LOCK_LOCKED (0xFF) +typedef unsigned char _atomic_lock_t; + +#endif \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/tcb.h b/lib/libc/include/sparc64-openbsd-none/machine/tcb.h new file mode 100644 index 000000000000..a5d8911686af --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/tcb.h @@ -0,0 +1,44 @@ +/* $OpenBSD: tcb.h,v 1.7 2017/04/20 10:03:40 kettenis Exp $ */ + +/* + * Copyright (c) 2011 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TCB_H_ +#define _MACHINE_TCB_H_ + +#ifdef _KERNEL + +#include + +/* + * In userspace, register %g7 contains the address of the thread's TCB + */ +#define TCB_GET(p) \ + ((void *)(p)->p_md.md_tf->tf_global[7]) +#define TCB_SET(p, addr) \ + ((p)->p_md.md_tf->tf_global[7] = (int64_t)(addr)) + +#else /* _KERNEL */ + +/* ELF TLS ABI calls for big TCB, with static TLS data at negative offsets */ +#define TLS_VARIANT 2 + +register void *__tcb __asm__ ("g7"); +#define TCB_GET() (__tcb) +#define TCB_SET(tcb) ((__tcb) = (tcb)) + +#endif /* _KERNEL */ +#endif /* _MACHINE_TCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/timetc.h b/lib/libc/include/sparc64-openbsd-none/machine/timetc.h new file mode 100644 index 000000000000..7ae3900f527d --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/timetc.h @@ -0,0 +1,24 @@ +/* $OpenBSD: timetc.h,v 1.2 2020/07/08 09:20:28 kettenis Exp $ */ +/* + * Copyright (c) 2020 Paul Irofti + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TIMETC_H_ +#define _MACHINE_TIMETC_H_ + +#define TC_TICK 1 +#define TC_SYS_TICK 2 + +#endif /* _MACHINE_TIMETC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/trap.h b/lib/libc/include/sparc64-openbsd-none/machine/trap.h new file mode 100644 index 000000000000..2b7f57bdaf49 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/trap.h @@ -0,0 +1,159 @@ +/* $OpenBSD: trap.h,v 1.5 2013/04/02 13:24:57 kettenis Exp $ */ +/* $NetBSD: trap.h,v 1.4 1999/06/07 05:28:04 eeh Exp $ */ + +/* + * Copyright (c) 1996-1999 Eduardo Horvath + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + + +#ifndef _MACHINE_TRAP_H +#define _MACHINE_TRAP_H + +/* trap vec (pri) description */ +/* 0x000 unused */ +#define T_POR 0x001 /* (0) power on reset */ +#define T_WDR 0x002 /* (1) watchdog reset */ +#define T_XIR 0x003 /* (1) externally initiated reset */ +#define T_SIR 0x004 /* (1) software initiated reset */ +#define T_RED_EXCEPTION 0x005 /* (1) RED state exception */ +/* 0x006 unused */ +/* 0x007 unused */ +#define T_INST_EXCEPT 0x008 /* (5) instruction access exception */ +#define T_TEXTFAULT 0x009 /* (2) ? Text fault */ +#define T_INST_ERROR 0x00a /* (3) instruction access error */ +/* 0x00b unused */ +/* through 0x00f unused */ +#define T_ILLINST 0x010 /* (7) illegal instruction */ +#define T_PRIVINST 0x011 /* (6) privileged opcode */ +#define T_UNIMP_LDD 0x012 /* (6) unimplemented LDD */ +#define T_UNIMP_STD 0x013 /* (6) unimplemented STD */ +/* 0x014 unused */ +/* through 0x01f unused */ +#define T_FPDISABLED 0x020 /* (8) fpu disabled */ +#define T_FP_IEEE_754 0x021 /* (11) ieee 754 exception */ +#define T_FP_OTHER 0x022 /* (11) other fp exception */ +#define T_TAGOF 0x023 /* (14) tag overflow */ +#define T_CLEAN_WINDOW 0x024 /* (10) clean window exception */ +/* 0x025 unused */ +/* through 0x027 unused */ +#define T_DIV0 0x028 /* (15) division routine was handed 0 */ +#define T_PROCERR 0x029 /* (4) internal processor error */ +/* 0x02a unused */ +/* through 0x02f unused */ +#define T_DATAFAULT 0x030 /* (12) address fault during data fetch */ +#define T_DATA_MMU_MISS 0x031 /* (12) data access MMU miss */ +#define T_DATA_ERROR 0x032 /* (12) data access error */ +#define T_DATA_PROT 0x033 /* (12) Data protection ??? */ +#define T_ALIGN 0x034 /* (10) address not properly aligned */ +#define T_LDDF_ALIGN 0x035 /* (10) LDDF address not properly aligned */ +#define T_STDF_ALIGN 0x036 /* (10) STDF address not properly aligned */ +#define T_PRIVACT 0x037 /* (11) privileged action */ +#define T_LDQF_ALIGN 0x038 /* (10) LDQF address not properly aligned */ +#define T_STQF_ALIGN 0x039 /* (10) STQF address not properly aligned */ +/* 0x03a unused */ +/* through 0x03f unused */ +#define T_ASYNC_ERROR 0x040 /* (2) ???? */ +#define T_L1INT 0x041 /* (31) level 1 interrupt */ +#define T_L2INT 0x042 /* (30) level 2 interrupt */ +#define T_L3INT 0x043 /* (29) level 3 interrupt */ +#define T_L4INT 0x044 /* (28) level 4 interrupt */ +#define T_L5INT 0x045 /* (27) level 5 interrupt */ +#define T_L6INT 0x046 /* (26) level 6 interrupt */ +#define T_L7INT 0x047 /* (25) level 7 interrupt */ +#define T_L8INT 0x048 /* (24) level 8 interrupt */ +#define T_L9INT 0x049 /* (23) level 9 interrupt */ +#define T_L10INT 0x04a /* (22) level 10 interrupt */ +#define T_L11INT 0x04b /* (21) level 11 interrupt */ +#define T_L12INT 0x04c /* (20) level 12 interrupt */ +#define T_L13INT 0x04d /* (19) level 13 interrupt */ +#define T_L14INT 0x04e /* (18) level 14 interrupt */ +#define T_L15INT 0x04f /* (17) level 15 interrupt */ +/* 0x050 unused */ +/* through 0x05f unused */ +#define T_INTVEC 0x060 /* (16) interrupt vector [Interrupt Global Regs]*/ +#define T_PA_WATCHPT 0x061 /* (12) Physical addr data watchpoint */ +#define T_VA_WATCHPT 0x062 /* (11) Virtual addr data watchpoint */ +#define T_ECCERR 0x063 /* (33) ECC correction error */ +#define T_FIMMU_MISS 0x064 /* (2) fast instruction access MMU miss */ +/* through 0x067 unused */ +#define T_FDMMU_MISS 0x068 /* (2) fast data access MMU miss */ +/* through 0x06b unused */ +#define T_FDMMU_PROT 0x06c /* (2) fast data access protection */ +/* through 0x06f unused */ +/* 0x070...0x07f implementation dependent exceptions */ +#define T_SPILL_N_NORM 0x080 /* (9) spill (n=0..7) normal */ +/* through 0x09f unused */ +#define T_SPILL_N_OTHER 0x0a0 /* (9) spill (n=0..7) other */ +/* through 0x0bf unused */ +#define T_FILL_N_NORM 0x0c0 /* (9) fill (n=0..7) normal */ +/* through 0x0df unused */ +#define T_FILL_N_OTHER 0x0e0 /* (9) fill (n=0..7) other */ +/* through 0x0ff unused */ + +/* beginning of `user' vectors (from trap instructions) - all priority 16 */ +#define T_SUN_SYSCALL 0x100 /* system call */ +#define T_BREAKPOINT 0x101 /* breakpoint `instruction' */ +#define T_UDIV0 0x102 /* division routine was handed 0 */ +#define T_FLUSHWIN 0x103 /* flush windows */ +#define T_CLEANWIN 0x104 /* provide clean windows */ +#define T_RANGECHECK 0x105 /* ? */ +#define T_FIXALIGN 0x106 /* fix up unaligned accesses */ +#define T_INTOF 0x107 /* integer overflow ? */ +#define T_SVR4_SYSCALL 0x108 /* SVR4 system call */ +#define T_BSD_SYSCALL 0x109 /* BSD system call */ +#define T_KGDB_EXEC 0x10a /* for kernel gdb */ + +/* 0x10b..0x1ff are currently unallocated, except the following */ +#define T_SVR4_GETCC 0x120 +#define T_SVR4_SETCC 0x121 +#define T_SVR4_GETPSR 0x122 +#define T_SVR4_SETPSR 0x123 +#define T_SVR4_GETHRTIME 0x124 +#define T_SVR4_GETHRVTIME 0x125 +#define T_SVR4_GETHRESTIME 0x127 +#define T_GETCC 0x132 +#define T_SETCC 0x133 +#define T_SVID_SYSCALL 0x164 +#define T_SPARC_INTL_SYSCALL 0x165 +#define T_OS_VENDOR_SYSCALL 0x166 +#define T_HW_OEM_SYSCALL 0x167 +#define T_RTF_DEF_TRAP 0x168 +#define T_MON_BREAKPOINT 0x17f + +#ifdef _KERNEL /* pseudo traps for locore.s */ +#define T_RWRET -1 /* need first user window for trap return */ +#define T_AST -2 /* no-op, just needed reschedule or profile */ +#endif + +/* flags to system call (flags in %g1 along with syscall number) */ +#define SYSCALL_G2RFLAG 0x400 /* on success, return to %g2 rather than npc */ + +/* + * `software trap' macros to keep people happy (sparc v8 manual says not + * to set the upper bits). + */ +#define ST_BREAKPOINT (T_BREAKPOINT & 0x7f) +#define ST_DIV0 (T_DIV0 & 0x7f) +#define ST_FLUSHWIN (T_FLUSHWIN & 0x7f) +#define ST_SYSCALL (T_SUN_SYSCALL & 0x7f) + +#endif /* _MACHINE_TRAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/vmparam.h b/lib/libc/include/sparc64-openbsd-none/machine/vmparam.h new file mode 100644 index 000000000000..4a3d2ed36cd1 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/vmparam.h @@ -0,0 +1,124 @@ +/* $OpenBSD: vmparam.h,v 1.35 2024/03/29 21:06:14 miod Exp $ */ +/* $NetBSD: vmparam.h,v 1.18 2001/05/01 02:19:19 thorpej Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vmparam.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * Machine dependent constants for sun4u and sun4v UltraSPARC + */ + +#ifndef VMPARAM_H +#define VMPARAM_H + +#define USRSTACK 0xffffffffffffe000L + +/* + * Virtual memory related constants, all in bytes + */ +/* + * Since the compiler generates `call' instructions we can't + * have more than 4GB in a single text segment. + * + * And since we only have a 40-bit address space, allow half + * of that for data and the other half for stack. + */ +#ifndef MAXTSIZ +#define MAXTSIZ (1L*1024*1024*1024) /* max text size */ +#endif +#ifndef DFLDSIZ +#define DFLDSIZ (128L*1024*1024) /* initial data size limit */ +#endif +#ifndef MAXDSIZ +#define MAXDSIZ (8L*1024*1024*1024) /* max data size */ +#endif +#ifndef BRKSIZ +#define BRKSIZ MAXDSIZ /* heap gap size */ +#endif +#ifndef DFLSSIZ +#define DFLSSIZ (2L*1024*1024) /* initial stack size limit */ +#endif +#ifndef MAXSSIZ +#define MAXSSIZ (32L*1024*1024) /* max stack size */ +#endif + +#define STACKGAP_RANDOM 256*1024 + +/* + * Size of shared memory map + */ +#ifndef SHMMAXPGS +#define SHMMAXPGS 4096 /* 32mb */ +#endif + +/* + * Size of User Raw I/O map + */ +#define USRIOSIZE 300 + +/* + * Mach derived constants + */ + +/* + * User/kernel map constants. + */ +#define VM_MIN_ADDRESS ((vaddr_t)PAGE_SIZE) +#define VM_MAX_ADDRESS ((vaddr_t)-1) +#define VM_MAXUSER_ADDRESS ((vaddr_t)-PAGE_SIZE) +#ifdef _KERNEL +#define VM_MIN_STACK_ADDRESS ((vaddr_t)0xfffffe0000000000L) +#endif + +/* map PIE into the first quarter of the address space before hole */ +#define VM_PIE_MIN_ADDR PAGE_SIZE +#define VM_PIE_MAX_ADDR 0x10000000000 + +#define VM_MIN_KERNEL_ADDRESS ((vaddr_t)KERNBASE) +#define VM_MAX_KERNEL_ADDRESS ((vaddr_t)0x000007ffffffffffL) + +/* virtual sizes (bytes) for various kernel submaps */ +#define VM_PHYS_SIZE (USRIOSIZE*PAGE_SIZE) + +#define VM_PHYSSEG_MAX 32 /* up to 32 segments */ +#define VM_PHYSSEG_STRAT VM_PSTRAT_BSEARCH +#define VM_PHYSSEG_NOADD /* can't add RAM after vm_mem_init */ + +#endif \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/machine/z8530var.h b/lib/libc/include/sparc64-openbsd-none/machine/z8530var.h new file mode 100644 index 000000000000..9439d8e8f52b --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/machine/z8530var.h @@ -0,0 +1,80 @@ +/* $OpenBSD: z8530var.h,v 1.9 2024/03/29 21:17:13 miod Exp $ */ +/* $NetBSD: z8530var.h,v 1.4 2000/11/08 23:41:42 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)zsvar.h 8.1 (Berkeley) 6/11/93 + */ + +#include +#include + +struct zsc_softc { + struct device zsc_dev; /* base device */ + bus_space_tag_t zsc_bustag; /* bus space/dma tags */ + bus_dma_tag_t zsc_dmatag; + struct zs_chanstate *zsc_cs[2]; /* channel A and B soft state */ + + /* Machine-dependent part follows... */ + void *zsc_softintr; + int zsc_promunit; /* PROM's view of zs devices */ + int zsc_node; /* PROM node, if any */ + struct zs_chanstate zsc_cs_store[2]; +}; + +/* + * Functions to read and write individual registers in a channel. + * The ZS chip requires a 1.6 uSec. recovery time between accesses. + * On sparc64, the recovery time is handled in hardware. + */ + +u_char zs_read_reg(struct zs_chanstate *cs, u_char reg); +u_char zs_read_csr(struct zs_chanstate *cs); +u_char zs_read_data(struct zs_chanstate *cs); + +void zs_write_reg(struct zs_chanstate *cs, u_char reg, u_char val); +void zs_write_csr(struct zs_chanstate *cs, u_char val); +void zs_write_data(struct zs_chanstate *cs, u_char val); + +/* The sparc has splzs() in psl.h */ + +/* We want to call it "zs" instead of "zsc" (sigh). */ +#ifndef ZSCCF_CHANNEL +#define ZSCCF_CHANNEL 0 +#define ZSCCF_CHANNEL_DEFAULT -1 +#endif \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/_float.h b/lib/libc/include/sparc64-openbsd-none/sparc64/_float.h new file mode 100644 index 000000000000..3ab11abcabb1 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/_float.h @@ -0,0 +1,80 @@ +/* $OpenBSD: _float.h,v 1.1 2012/06/26 16:12:45 deraadt Exp $ */ + +/* + * Copyright (c) 1992, 1993, 2001 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE__FLOAT_H_ +#define _MACHINE__FLOAT_H_ + +#define __FLT_RADIX 2 /* b */ +#define __FLT_ROUNDS __flt_rounds() +#define __FLT_EVAL_METHOD 0 /* no promotions */ + +#define __FLT_MANT_DIG 24 /* p */ +#define __FLT_EPSILON 1.19209290E-07F /* b**(1-p) */ +#define __FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ +#define __FLT_MIN_EXP -125 /* emin */ +#define __FLT_MIN 1.17549435E-38F /* b**(emin-1) */ +#define __FLT_MIN_10_EXP -37 /* ceil(log10(b**(emin-1))) */ +#define __FLT_MAX_EXP 128 /* emax */ +#define __FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ +#define __FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ + +#define __DBL_MANT_DIG 53 +#define __DBL_EPSILON 2.2204460492503131E-16 +#define __DBL_DIG 15 +#define __DBL_MIN_EXP -1021 +#define __DBL_MIN 2.2250738585072014E-308 +#define __DBL_MIN_10_EXP -307 +#define __DBL_MAX_EXP 1024 +#define __DBL_MAX 1.7976931348623157E+308 +#define __DBL_MAX_10_EXP 308 + +#define __LDBL_MANT_DIG 113 +#define __LDBL_EPSILON 1.925929944387235853055977942584927319E-34L +#define __LDBL_DIG 33 +#define __LDBL_MIN_EXP (-16381) +#define __LDBL_MIN 3.362103143112093506262677817321752603E-4932L +#define __LDBL_MIN_10_EXP (-4931) +#define __LDBL_MAX_EXP (+16384) +#define __LDBL_MAX 1.189731495357231765085759326628007016E+4932L +#define __LDBL_MAX_10_EXP (+4932) + +#define __DECIMAL_DIG 36 + +#endif /* _MACHINE__FLOAT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/_types.h b/lib/libc/include/sparc64-openbsd-none/sparc64/_types.h new file mode 100644 index 000000000000..b0d11eb13a20 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/_types.h @@ -0,0 +1,140 @@ +/* $OpenBSD: _types.h,v 1.25 2023/07/02 19:02:28 cheloha Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.3 (Berkeley) 1/5/94 + * @(#)ansi.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _MACHINE__TYPES_H_ +#define _MACHINE__TYPES_H_ + +#if defined(_KERNEL) +typedef struct label_t { + long val[2]; +} label_t; +#endif + +/* + * _ALIGN(p) rounds p (pointer or byte index) up to a correctly-aligned + * value for all data types (int, long, ...). The result is an + * unsigned long and must be cast to any desired pointer type. + * + * _ALIGNED_POINTER is a boolean macro that checks whether an address + * is valid to fetch data elements of type t from on this architecture. + * This does not reflect the optimal alignment, just the possibility + * (within reasonable limits). + */ +#define _ALIGNBYTES 0xf +#define _STACKALIGNBYTES _ALIGNBYTES +#define _ALIGN(p) (((unsigned long)(p) + _ALIGNBYTES) & ~_ALIGNBYTES) +#define _ALIGNED_POINTER(p,t) ((((unsigned long)(p)) & (sizeof(t) - 1)) == 0) +#define _MAX_PAGE_SHIFT 13 /* same as PAGE_SHIFT */ + +/* 7.18.1.1 Exact-width integer types */ +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short __int16_t; +typedef unsigned short __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; +typedef long long __int64_t; +typedef unsigned long long __uint64_t; + +/* 7.18.1.2 Minimum-width integer types */ +typedef __int8_t __int_least8_t; +typedef __uint8_t __uint_least8_t; +typedef __int16_t __int_least16_t; +typedef __uint16_t __uint_least16_t; +typedef __int32_t __int_least32_t; +typedef __uint32_t __uint_least32_t; +typedef __int64_t __int_least64_t; +typedef __uint64_t __uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types */ +typedef __int32_t __int_fast8_t; +typedef __uint32_t __uint_fast8_t; +typedef __int32_t __int_fast16_t; +typedef __uint32_t __uint_fast16_t; +typedef __int32_t __int_fast32_t; +typedef __uint32_t __uint_fast32_t; +typedef __int64_t __int_fast64_t; +typedef __uint64_t __uint_fast64_t; +#define __INT_FAST8_MIN INT32_MIN +#define __INT_FAST16_MIN INT32_MIN +#define __INT_FAST32_MIN INT32_MIN +#define __INT_FAST64_MIN INT64_MIN +#define __INT_FAST8_MAX INT32_MAX +#define __INT_FAST16_MAX INT32_MAX +#define __INT_FAST32_MAX INT32_MAX +#define __INT_FAST64_MAX INT64_MAX +#define __UINT_FAST8_MAX UINT32_MAX +#define __UINT_FAST16_MAX UINT32_MAX +#define __UINT_FAST32_MAX UINT32_MAX +#define __UINT_FAST64_MAX UINT64_MAX + +/* 7.18.1.4 Integer types capable of holding object pointers */ +typedef long __intptr_t; +typedef unsigned long __uintptr_t; + +/* 7.18.1.5 Greatest-width integer types */ +typedef __int64_t __intmax_t; +typedef __uint64_t __uintmax_t; + +/* Register size */ +typedef long __register_t; + +/* VM system types */ +typedef unsigned long __vaddr_t; +typedef unsigned long __paddr_t; +typedef unsigned long __vsize_t; +typedef unsigned long __psize_t; + +/* Standard system types */ +typedef double __double_t; +typedef float __float_t; +typedef long __ptrdiff_t; +typedef unsigned long __size_t; +typedef long __ssize_t; +#if defined(__GNUC__) && __GNUC__ >= 3 +typedef __builtin_va_list __va_list; +#else +typedef char * __va_list; +#endif + +/* Wide character support types */ +#ifndef __cplusplus +typedef int __wchar_t; +#endif +typedef int __wint_t; +typedef int __rune_t; +typedef void * __wctrans_t; +typedef void * __wctype_t; + +#endif /* _MACHINE__TYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/apmvar.h b/lib/libc/include/sparc64-openbsd-none/sparc64/apmvar.h new file mode 100644 index 000000000000..62e9480a19b3 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/apmvar.h @@ -0,0 +1,122 @@ +/* $OpenBSD: apmvar.h,v 1.7 2019/01/22 02:36:30 phessler Exp $ */ + +/* + * Copyright (c) 2001 Alexander Guy + * Copyright (c) 1995 John T. Kohl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _MACHINE_APMVAR_H_ +#define _MACHINE_APMVAR_H_ + +#include + +/* Advanced Power Management (v1.0 and v1.1 specification) + * functions/defines/etc. + */ + +/* These definitions make up the heart of the user-land interface + * to the APM devices. + */ + +#define APM_AC_OFF 0x00 +#define APM_AC_ON 0x01 +#define APM_AC_BACKUP 0x02 +#define APM_AC_UNKNOWN 0xff +#define APM_BATT_HIGH 0x00 +#define APM_BATT_LOW 0x01 +#define APM_BATT_CRITICAL 0x02 +#define APM_BATT_CHARGING 0x03 +#define APM_BATT_UNKNOWN 0xff +#define APM_BATT_LIFE_UNKNOWN 0xff + +#define APM_NOEVENT 0x0000 +#define APM_STANDBY_REQ 0x0001 +#define APM_SUSPEND_REQ 0x0002 +#define APM_NORMAL_RESUME 0x0003 +#define APM_CRIT_RESUME 0x0004 /* suspend/resume happened + without us */ +#define APM_BATTERY_LOW 0x0005 +#define APM_POWER_CHANGE 0x0006 +#define APM_UPDATE_TIME 0x0007 +#define APM_CRIT_SUSPEND_REQ 0x0008 +#define APM_USER_STANDBY_REQ 0x0009 +#define APM_USER_SUSPEND_REQ 0x000A +#define APM_SYS_STANDBY_RESUME 0x000B +#define APM_CAPABILITY_CHANGE 0x000C /* apm v1.2 */ +#define APM_USER_HIBERNATE_REQ 0x000D +#define APM_EVENT_MASK 0xffff + +#define APM_EVENT_COMPOSE(t,i) ((((i) & 0x7fff) << 16)|((t) & APM_EVENT_MASK)) +#define APM_EVENT_TYPE(e) ((e) & APM_EVENT_MASK) +#define APM_EVENT_INDEX(e) ((e) >> 16) + +/* + * LP (Laptop Package) + * + * Copyright (C) 1994 by HOSOKAWA Tatsumi + * + * This software may be used, modified, copied, and distributed, in + * both source and binary form provided that the above copyright and + * these terms are retained. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with its + * use. + * + * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) + */ + +#define APM_BATTERY_ABSENT 4 + +struct apm_power_info { + u_char battery_state; + u_char ac_state; + u_char battery_life; + u_char spare1; + u_int minutes_left; /* estimate */ + u_int spare2[6]; +}; + +struct apm_ctl { + u_int dev; + u_int mode; +}; + +#define APM_IOC_REJECT _IOW('A', 0, struct apm_event_info) /* reject request # */ +#define APM_IOC_STANDBY _IO('A', 1) /* put system into standby */ +#define APM_IOC_SUSPEND _IO('A', 2) /* put system into suspend */ +#define APM_IOC_GETPOWER _IOR('A', 3, struct apm_power_info) /* fetch battery state */ +#define APM_IOC_DEV_CTL _IOW('A', 5, struct apm_ctl) /* put device into mode */ +#define APM_IOC_PRN_CTL _IOW('A', 6, int ) /* driver power status msg */ +#define APM_PRINT_ON 0 /* driver power status displayed */ +#define APM_PRINT_OFF 1 /* driver power status not displayed */ +#define APM_PRINT_PCT 2 /* driver power status only displayed + if the percentage changes */ +#define APM_IOC_STANDBY_REQ _IO('A', 7) /* request standby */ +#define APM_IOC_SUSPEND_REQ _IO('A', 8) /* request suspend */ +#define APM_IOC_HIBERNATE _IO('A', 9) /* put system into hibernate */ + +#endif /* _MACHINE_APMVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/asm.h b/lib/libc/include/sparc64-openbsd-none/sparc64/asm.h new file mode 100644 index 000000000000..2267bb9443d0 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/asm.h @@ -0,0 +1,96 @@ +/* $OpenBSD: asm.h,v 1.19 2024/03/29 21:05:34 miod Exp $ */ +/* $NetBSD: asm.h,v 1.15 2000/08/02 22:24:39 eeh Exp $ */ + +/* + * Copyright (c) 1994 Allen Briggs + * All rights reserved. + * + * Gleaned from locore.s and sun3 asm.h which had the following copyrights: + * locore.s: + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1990 The Regents of the University of California. + * sun3/include/asm.h: + * Copyright (c) 1993 Adam Glass + * Copyright (c) 1990 The Regents of the University of California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_ASM_H_ +#define _MACHINE_ASM_H_ + +/* Pull in CC64FSZ and BIAS from frame.h */ +#include + +#define _C_LABEL(name) name +#define _ASM_LABEL(name) name + +#ifdef __PIC__ +/* + * PIC_PROLOGUE() is akin to the compiler generated function prologue for + * PIC code. It leaves the address of the Global Offset Table in DEST, + * clobbering register TMP in the process. Using the temporary enables us + * to work without a stack frame (doing so requires saving %o7) . + */ +#define PIC_PROLOGUE(dest,tmp) \ + sethi %hi(_GLOBAL_OFFSET_TABLE_-4),dest; \ + rd %pc, tmp; \ + or dest,%lo(_GLOBAL_OFFSET_TABLE_+4),dest; \ + add dest,tmp,dest +#else +#define PIC_PROLOGUE(dest,tmp) +#endif + +#define FTYPE(x) .type x,@function +#define OTYPE(x) .type x,@object + +#define _ENTRY_NB(name) \ + .align 4; .proc 1; FTYPE(name); name: +#define _ENTRY(name) .globl name; _ENTRY_NB(name) + +#if defined(PROF) || defined(GPROF) +#define _PROF_PROLOGUE \ + .data; .align 8; 1: .uaword 0; .uaword 0; \ + .text; save %sp,-CC64FSZ,%sp; sethi %hi(1b),%o0; call _mcount; \ + or %o0,%lo(1b),%o0; restore +#else +#define _PROF_PROLOGUE +#endif + +#define ENTRY(name) _ENTRY(name); _PROF_PROLOGUE +#define NENTRY(name) _ENTRY(name) +#define ENTRY_NB(name) _ENTRY_NB(name); _PROF_PROLOGUE +#define ASENTRY(name) _ENTRY(name); _PROF_PROLOGUE +#define FUNC(name) ASENTRY(name) +#define END(y) .size y, . - y + +#define STRONG_ALIAS(alias,sym) \ + .global alias; \ + alias = sym +#define WEAK_ALIAS(alias,sym) \ + .weak alias; \ + alias = sym + +#endif /* _MACHINE_ASM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/atomic.h b/lib/libc/include/sparc64-openbsd-none/sparc64/atomic.h new file mode 100644 index 000000000000..bab72dabbee1 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/atomic.h @@ -0,0 +1,154 @@ +/* $OpenBSD: atomic.h,v 1.15 2017/07/04 09:00:12 mpi Exp $ */ +/* + * Copyright (c) 2007 Artur Grabowski + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_ATOMIC_H_ +#define _MACHINE_ATOMIC_H_ + +static inline unsigned int +_atomic_cas_uint(volatile unsigned int *p, unsigned int e, unsigned int n) +{ + __asm volatile("cas [%2], %3, %0" + : "+r" (n), "=m" (*p) + : "r" (p), "r" (e), "m" (*p)); + + return (n); +} +#define atomic_cas_uint(_p, _e, _n) _atomic_cas_uint((_p), (_e), (_n)) + +static inline unsigned long +_atomic_cas_ulong(volatile unsigned long *p, unsigned long e, unsigned long n) +{ + __asm volatile("casx [%2], %3, %0" + : "+r" (n), "=m" (*p) + : "r" (p), "r" (e), "m" (*p)); + + return (n); +} +#define atomic_cas_ulong(_p, _e, _n) _atomic_cas_ulong((_p), (_e), (_n)) + +static inline void * +_atomic_cas_ptr(volatile void *p, void *e, void *n) +{ + __asm volatile("casx [%2], %3, %0" + : "+r" (n), "=m" (*(volatile unsigned long *)p) + : "r" (p), "r" (e), "m" (*(volatile unsigned long *)p)); + + return (n); +} +#define atomic_cas_ptr(_p, _e, _n) _atomic_cas_ptr((_p), (_e), (_n)) + +#define _def_atomic_swap(_f, _t, _c) \ +static inline _t \ +_f(volatile _t *p, _t v) \ +{ \ + _t e; \ + _t r; \ + \ + r = (_t)*p; \ + do { \ + e = r; \ + r = _c(p, e, v); \ + } while (r != e); \ + \ + return (r); \ +} + +_def_atomic_swap(_atomic_swap_uint, unsigned int, atomic_cas_uint) +_def_atomic_swap(_atomic_swap_ulong, unsigned long, atomic_cas_ulong) +#undef _def_atomic_swap + +static inline void * +_atomic_swap_ptr(volatile void *p, void *v) +{ + void *e, *r; + + r = *(void **)p; + do { + e = r; + r = atomic_cas_ptr(p, e, v); + } while (r != e); + + return (r); +} + +#define atomic_swap_uint(_p, _v) _atomic_swap_uint(_p, _v) +#define atomic_swap_ulong(_p, _v) _atomic_swap_ulong(_p, _v) +#define atomic_swap_ptr(_p, _v) _atomic_swap_ptr(_p, _v) + +#define _def_atomic_op_nv(_f, _t, _c, _op) \ +static inline _t \ +_f(volatile _t *p, _t v) \ +{ \ + _t e, r, f; \ + \ + r = *p; \ + do { \ + e = r; \ + f = e _op v; \ + r = _c(p, e, f); \ + } while (r != e); \ + \ + return (f); \ +} + +_def_atomic_op_nv(_atomic_add_int_nv, unsigned int, atomic_cas_uint, +) +_def_atomic_op_nv(_atomic_add_long_nv, unsigned long, atomic_cas_ulong, +) +_def_atomic_op_nv(_atomic_sub_int_nv, unsigned int, atomic_cas_uint, -) +_def_atomic_op_nv(_atomic_sub_long_nv, unsigned long, atomic_cas_ulong, -) +#undef _def_atomic_op_nv + +#define atomic_add_int_nv(_p, _v) _atomic_add_int_nv(_p, _v) +#define atomic_add_long_nv(_p, _v) _atomic_add_long_nv(_p, _v) +#define atomic_sub_int_nv(_p, _v) _atomic_sub_int_nv(_p, _v) +#define atomic_sub_long_nv(_p, _v) _atomic_sub_long_nv(_p, _v) + +#define __membar(_m) __asm volatile("membar " _m ::: "memory") + +#define membar_enter() __membar("#StoreLoad|#StoreStore") +#define membar_exit() __membar("#LoadStore|#StoreStore") +#define membar_producer() __membar("#StoreStore") +#define membar_consumer() __membar("#LoadLoad") +#define membar_sync() __membar("#Sync") + +#if defined(_KERNEL) + +static __inline void +atomic_setbits_int(volatile unsigned int *uip, unsigned int v) +{ + unsigned int e, r; + + r = *uip; + do { + e = r; + r = atomic_cas_uint(uip, e, e | v); + } while (r != e); +} + +static __inline void +atomic_clearbits_int(volatile unsigned int *uip, unsigned int v) +{ + unsigned int e, r; + + r = *uip; + do { + e = r; + r = atomic_cas_uint(uip, e, e & ~v); + } while (r != e); +} + +#endif /* defined(_KERNEL) */ +#endif /* _MACHINE_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/autoconf.h b/lib/libc/include/sparc64-openbsd-none/sparc64/autoconf.h new file mode 100644 index 000000000000..0a5ed5b2dc36 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/autoconf.h @@ -0,0 +1,159 @@ +/* $OpenBSD: autoconf.h,v 1.20 2024/05/17 20:05:08 miod Exp $ */ +/* $NetBSD: autoconf.h,v 1.10 2001/07/24 19:32:11 eeh Exp $ */ + +/*- + * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)autoconf.h 8.2 (Berkeley) 9/30/93 + */ + +/* + * Autoconfiguration information. + */ + +#include +#include + +/* This is used to map device classes to IPLs */ +struct intrmap { + char *in_class; + int in_lev; +}; +extern struct intrmap intrmap[]; + +/* The "mainbus" on ultra desktops is actually the UPA bus. We need to + * separate this from peripheral buses like SBus and PCI because each bus may + * have different ways of encoding properties, such as "reg" and "interrupts". + */ + +/* Device register space description */ +struct upa_reg { + int64_t ur_paddr; + int64_t ur_len; +}; + +/* + * Attach arguments presented by mainbus_attach() + * + * Large fields first followed by smaller ones to minimize stack space used. + */ +struct mainbus_attach_args { + bus_space_tag_t ma_bustag; /* parent bus tag */ + bus_dma_tag_t ma_dmatag; + char *ma_name; /* PROM node name */ + struct upa_reg *ma_reg; /* "reg" properties */ + u_int *ma_address; /* "address" properties -- 32 bits */ + u_int *ma_interrupts; /* "interrupts" properties */ + int ma_upaid; /* UPA bus ID */ + int ma_node; /* PROM handle */ + int ma_nreg; /* Counts for those properties */ + int ma_naddress; + int ma_ninterrupts; + int ma_pri; /* priority (IPL) */ +}; + +/* + * length; the others convert or make some other guarantee. + */ +long getproplen(int node, char *name); +int getprop(int, char *, size_t, int *, void **); +char *getpropstring(int node, char *name); +int getpropint(int node, char *name, int deflt); +int getpropspeed(int node, char *name); + +/* Frequently used options node */ +extern int optionsnode; + + /* new interfaces: */ +char *getpropstringA(int, char *, char *); + +/* + * `clockfreq' produces a printable representation of a clock frequency + * (this is just a frill). + */ +char *clockfreq(long freq); + +/* Openprom V2 style boot path */ +struct device; +struct bootpath { + int node; + char name[16]; /* name of this node */ + long val[3]; /* up to three optional values */ + struct device *dev; /* device that recognised this component */ +}; +struct bootpath *bootpath_store(int, struct bootpath *); + +void bootstrap(int); +int firstchild(int); +int nextsibling(int); +void callrom(void); +struct device *getdevunit(const char *, int); +int romgetcursoraddr(int **, int **); +int findroot(void); +int findnode(int, const char *); +int checkstatus(int); +int node_has_property(int, const char *); +void device_register(struct device *, void *); \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/boot_flag.h b/lib/libc/include/sparc64-openbsd-none/sparc64/boot_flag.h new file mode 100644 index 000000000000..e53f7fc9bd41 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/boot_flag.h @@ -0,0 +1,50 @@ +/* $OpenBSD: boot_flag.h,v 1.8 2023/11/09 14:26:34 kn Exp $ */ +/* $NetBSD: boot_flag.h,v 1.3 2001/07/01 02:56:21 gmcgarry Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BOOT_FLAG_H_ +#define _MACHINE_BOOT_FLAG_H_ + +/* softraid boot information */ +#define BOOTSR_UUID_MAX 16 +#define BOOTSR_CRYPTO_MAXKEYBYTES 32 + +/* MD boot data in .openbsd.bootdata ELF segment */ +struct openbsd_bootdata { + u_int64_t version; + u_int64_t len; /* of structure */ + + u_int8_t sr_uuid[BOOTSR_UUID_MAX]; + u_int8_t sr_maskkey[BOOTSR_CRYPTO_MAXKEYBYTES]; + u_int32_t boothowto; +} __packed; + +#define BOOTDATA_VERSION 1 +#define BOOTDATA_LEN_BOOTHOWTO 68 + +#endif /* _MACHINE_BOOT_FLAG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/bppioctl.h b/lib/libc/include/sparc64-openbsd-none/sparc64/bppioctl.h new file mode 100644 index 000000000000..c424ccb47484 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/bppioctl.h @@ -0,0 +1,59 @@ +/* $OpenBSD: bppioctl.h,v 1.2 2008/11/29 01:55:06 ray Exp $ */ + +/*- + * Copyright (c) 1998 Iain Hibbert + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _IOCTL_ +#include +#endif + +struct bpp_param { + int bp_burst; /* chars to send/recv in one call */ + int bp_timeout; /* timeout: -1 blocking, 0 non blocking >0 ms */ + int bp_delay; /* delay between polls (ms) */ +}; + +#define BPP_BLOCK -1 +#define BPP_NOBLOCK 0 + +/* defaults */ +#define BPP_BURST 1024 +#define BPP_TIMEOUT BPP_BLOCK +#define BPP_DELAY 10 + +/* limits */ +#define BPP_BURST_MIN 1 +#define BPP_BURST_MAX 1024 +#define BPP_DELAY_MIN 0 +#define BPP_DELAY_MAX 30000 + +/* status bits */ +#define BPP_BUSY (1<<0) +#define BPP_PAPER (1<<1) + +/* ioctl commands */ +#define BPPIOCSPARAM _IOW('P', 0x1, struct bpp_param) +#define BPPIOCGPARAM _IOR('P', 0x2, struct bpp_param) +#define BPPIOCGSTAT _IOR('P', 0x4, int) \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/bus.h b/lib/libc/include/sparc64-openbsd-none/sparc64/bus.h new file mode 100644 index 000000000000..8e6f0472d366 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/bus.h @@ -0,0 +1,649 @@ +/* $OpenBSD: bus.h,v 1.38 2024/10/22 22:01:58 jsg Exp $ */ +/* $NetBSD: bus.h,v 1.31 2001/09/21 15:30:41 wiz Exp $ */ + +/*- + * Copyright (c) 1996, 1997, 1998, 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1997-1999, 2001 Eduardo E. Horvath. All rights reserved. + * Copyright (c) 1996 Charles M. Hannum. All rights reserved. + * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BUS_H_ +#define _MACHINE_BUS_H_ + +#include + +#ifdef _KERNEL + +/* + * Debug hooks + */ + +#define BSDB_ACCESS 0x01 +#define BSDB_MAP 0x02 +#define BSDB_ASSERT 0x04 +#define BSDB_MAPDETAIL 0x08 +#define BSDB_ALL_ACCESS 0x10 +extern int bus_space_debug; + +#define BSHDB_ACCESS 0x01 +#define BSHDB_NO_ACCESS 0x02 + +#if defined(BUS_SPACE_DEBUG) +#include +#define BUS_SPACE_PRINTF(l, s) do { \ + if(bus_space_debug & (l)) printf s; \ +} while(0) +#define BUS_SPACE_TRACE(t, h, s) do { \ + if ( (((bus_space_debug & BSDB_ALL_ACCESS) != 0) && \ + (((h).bh_flags & BSHDB_NO_ACCESS) == 0)) || \ + (((bus_space_debug & BSDB_ACCESS) != 0) && \ + (((h).bh_flags & BSHDB_ACCESS) != 0))) \ + printf s; \ + } while(0) +#define BUS_SPACE_SET_FLAGS(t, h, f) ((h).bh_flags |= (f)) +#define BUS_SPACE_CLEAR_FLAGS(t, h, f) ((h).bh_flags &= ~(f)) +#define BUS_SPACE_FLAG_DECL(s) int s +#define BUS_SPACE_SAVE_FLAGS(t, h, s) (s = (h).bh_flags) +#define BUS_SPACE_RESTORE_FLAGS(t, h, s) (s = (h).bh_flags) +#define BUS_SPACE_ASSERT(t, h, o, n) do { \ + if (bus_space_debug & BSDB_ASSERT) \ + bus_space_assert(t, &(h), o, n); \ + } while(0) +#else /* BUS_SPACE_DEBUG */ +#define BUS_SPACE_PRINTF(l, s) +#define BUS_SPACE_TRACE(t, h, s) +#define BUS_SPACE_SET_FLAGS(t, h, f) +#define BUS_SPACE_CLEAR_FLAGS(t, h, f) +#define BUS_SPACE_FLAG_DECL(s) +#define BUS_SPACE_SAVE_FLAGS(t, h, s) +#define BUS_SPACE_RESTORE_FLAGS(t, h, s) +#define BUS_SPACE_ASSERT(t, h, o, n) +#endif /* BUS_SPACE_DEBUG */ + + +/* + * UPA and SBus spaces are non-cached and big endian + * (except for RAM and PROM) + * + * PCI spaces are non-cached and little endian + */ + +enum sparc_bus_type { + UPA_BUS_SPACE, + SBUS_BUS_SPACE, + PCI_CONFIG_BUS_SPACE, + PCI_IO_BUS_SPACE, + PCI_MEMORY_BUS_SPACE, + LAST_BUS_SPACE +}; +/* For backwards compatibility */ +#define SPARC_BUS_SPACE UPA_BUS_SPACE + +/* + * Bus address and size types + */ +typedef const struct sparc_bus_space_tag *bus_space_tag_t; +typedef u_long bus_addr_t; +typedef u_long bus_size_t; + + +typedef struct _bus_space_handle { + paddr_t bh_ptr; +#ifdef BUS_SPACE_DEBUG + bus_space_tag_t bh_tag; + bus_size_t bh_size; + int bh_flags; +#endif +} bus_space_handle_t; + +/* For buses which have an iospace. */ +#define BUS_ADDR_IOSPACE(x) ((x)>>32) +#define BUS_ADDR_PADDR(x) ((x)&0xffffffff) +#define BUS_ADDR(io, pa) ((((bus_addr_t)io)<<32)|(pa)) + +/* + * Access methods for bus resources and address space. + */ + +struct sparc_bus_space_tag { + void *cookie; + bus_space_tag_t parent; + enum sparc_bus_type default_type; + u_int8_t asi; + u_int8_t sasi; + char name[32]; + + int (*sparc_bus_alloc)(bus_space_tag_t, + bus_space_tag_t, + bus_addr_t, bus_addr_t, + bus_size_t, bus_size_t, bus_size_t, + int, bus_addr_t *, bus_space_handle_t *); + + void (*sparc_bus_free)(bus_space_tag_t, + bus_space_tag_t, + bus_space_handle_t, bus_size_t); + + int (*sparc_bus_map)(bus_space_tag_t, + bus_space_tag_t, + bus_addr_t, bus_size_t, + int, bus_space_handle_t *); + + int (*sparc_bus_protect)(bus_space_tag_t, + bus_space_tag_t, + bus_space_handle_t, bus_size_t, int); + + int (*sparc_bus_unmap)(bus_space_tag_t, + bus_space_tag_t, + bus_space_handle_t, bus_size_t); + + int (*sparc_bus_subregion)(bus_space_tag_t, + bus_space_tag_t, + bus_space_handle_t, bus_size_t, + bus_size_t, bus_space_handle_t *); + + paddr_t (*sparc_bus_mmap)(bus_space_tag_t, + bus_space_tag_t, + bus_addr_t, off_t, int, int); + + void *(*sparc_intr_establish)(bus_space_tag_t, + bus_space_tag_t, + int, int, int, + int (*)(void *), void *, + const char *); + void *(*sparc_intr_establish_cpu)(bus_space_tag_t, + bus_space_tag_t, + int, int, int, + struct cpu_info *, + int (*)(void *), void *, + const char *); + + bus_addr_t (*sparc_bus_addr)(bus_space_tag_t, + bus_space_tag_t, bus_space_handle_t); +}; + +/* + * Bus space function prototypes. + */ +int bus_space_alloc( + bus_space_tag_t, + bus_addr_t, /* reg start */ + bus_addr_t, /* reg end */ + bus_size_t, /* size */ + bus_size_t, /* alignment */ + bus_size_t, /* boundary */ + int, /* flags */ + bus_addr_t *, + bus_space_handle_t *); +void bus_space_free( + bus_space_tag_t, + bus_space_handle_t, + bus_size_t); +int bus_space_map( + bus_space_tag_t, + bus_addr_t, + bus_size_t, + int, /*flags*/ + bus_space_handle_t *); +int bus_space_protect( + bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + int); /*flags*/ +int bus_space_unmap( + bus_space_tag_t, + bus_space_handle_t, + bus_size_t); +int bus_space_subregion( + bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + bus_size_t, + bus_space_handle_t *); +static void bus_space_barrier( + bus_space_tag_t, + bus_space_handle_t, + bus_size_t, + bus_size_t, + int); +paddr_t bus_space_mmap( + bus_space_tag_t, + bus_addr_t, /*addr*/ + off_t, /*offset*/ + int, /*prot*/ + int); /*flags*/ +void *bus_intr_establish( + bus_space_tag_t, + int, /*bus-specific intr*/ + int, /*device class level, + see machine/intr.h*/ + int, /*flags*/ + int (*)(void *), /*handler*/ + void *, /*handler arg*/ + const char *); /*what*/ +void *bus_intr_establish_cpu( + bus_space_tag_t, + int, /*bus-specific intr*/ + int, /*device class level, + see machine/intr.h*/ + int, /*flags*/ + struct cpu_info *, /*cpu*/ + int (*)(void *), /*handler*/ + void *, /*handler arg*/ + const char *); /*what*/ +void *bus_intr_allocate( + bus_space_tag_t, + int (*)(void *), /*handler*/ + void *, /*handler arg*/ + int, /*number*/ + int, /*pil*/ + volatile u_int64_t *, /*map*/ + volatile u_int64_t *, /*clr*/ + const char *); /*what*/ +void bus_intr_free(void *); +void bus_space_render_tag( + bus_space_tag_t, + char *, + size_t); +void *bus_space_vaddr( + bus_space_tag_t, + bus_space_handle_t); + +#ifdef BUS_SPACE_DEBUG +void bus_space_assert(bus_space_tag_t, + const bus_space_handle_t *, + bus_size_t, int); +void bus_space_render_tag(bus_space_tag_t, char*, size_t); +#endif /* BUS_SPACE_DEBUG */ + + +#define _BS_PRECALL(t,f) \ + while (t->f == NULL) \ + t = t->parent; +#define _BS_POSTCALL + +#define _BS_CALL(t,f) \ + (*(t)->f) + +/* flags for bus_space_barrier() */ +#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ +#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ + +static inline void +bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + bus_size_t s, int f) +{ +#ifdef notyet + switch (f) { + case (BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE): + __membar("#LoadLoad|#StoreStore"); + break; + case BUS_SPACE_BARRIER_READ: + membar("#LoadLoad"); + break; + case BUS_SPACE_BARRIER_WRITE: + membar("#StoreStore"); + break; + default: + break; + } +#else + __membar("#Sync"); +#endif +} + +#include + +/* flags for bus space map functions */ +#define BUS_SPACE_MAP_CACHEABLE 0x0001 +#define BUS_SPACE_MAP_LINEAR 0x0002 +#define BUS_SPACE_MAP_READONLY 0x0004 +#define BUS_SPACE_MAP_PREFETCHABLE 0x0008 +#define BUS_SPACE_MAP_PROMADDRESS 0x0010 +#define BUS_SPACE_MAP_BUS1 0x0100 /* placeholders for bus functions... */ +#define BUS_SPACE_MAP_BUS2 0x0200 +#define BUS_SPACE_MAP_BUS3 0x0400 +#define BUS_SPACE_MAP_BUS4 0x0800 + + +/* flags for bus_intr_establish() */ +#define BUS_INTR_ESTABLISH_MPSAFE 0x0001 +#define BUS_INTR_ESTABLISH_SOFTINTR 0x0002 + +/* + * Flags used in various bus DMA methods. + */ +#define BUS_DMA_WAITOK 0x0000 /* safe to sleep (pseudo-flag) */ +#define BUS_DMA_NOWAIT 0x0001 /* not safe to sleep */ +#define BUS_DMA_ALLOCNOW 0x0002 /* perform resource allocation now */ +#define BUS_DMA_COHERENT 0x0004 /* hint: map memory DMA coherent */ +#define BUS_DMA_NOWRITE 0x0008 /* I suppose the following two should default on */ +#define BUS_DMA_BUS1 0x0010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x0020 +#define BUS_DMA_BUS3 0x0040 +#define BUS_DMA_BUS4 0x0080 +#define BUS_DMA_STREAMING 0x0100 /* hint: sequential, unidirectional */ +#define BUS_DMA_READ 0x0200 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x0400 /* mapping is memory -> device only */ +#define BUS_DMA_ZERO 0x0800 /* zero memory in dmamem_alloc */ +#define BUS_DMA_OVERRUN 0x1000 /* tolerate DMA overruns */ +#define BUS_DMA_64BIT 0x2000 /* device handles 64bit dva */ + +#define BUS_DMA_NOCACHE BUS_DMA_BUS1 +#define BUS_DMA_DVMA BUS_DMA_BUS2 /* Don't bother with alignment */ +#define BUS_DMA_24BIT BUS_DMA_BUS3 /* 24bit device */ + +#define BUS_DMA_RAW BUS_DMA_STREAMING + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct uio; + +/* + * Operations performed by bus_dmamap_sync(). + */ +#define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */ +#define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */ +#define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */ +#define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */ + +typedef struct sparc_bus_dma_tag *bus_dma_tag_t; +typedef struct sparc_bus_dmamap *bus_dmamap_t; + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +struct sparc_bus_dma_segment { + bus_addr_t ds_addr; /* DVMA address */ + bus_size_t ds_len; /* length of transfer */ + /* + * The following is to support bus_dmamem_alloc()'s + * odd interface. Only the values in the first + * segment are used. This means that 3/5ths of + * most segments are useless space (and mbufs use 1024 + * segments). + */ + bus_size_t _ds_boundary; /* don't cross this */ + bus_size_t _ds_align; /* align to this */ + void *_ds_mlist; /* XXX - dmamap_alloc'ed pages */ +}; +typedef struct sparc_bus_dma_segment bus_dma_segment_t; + + +/* + * bus_dma_tag_t + * + * A machine-dependent opaque type describing the implementation of + * DMA for a given bus. + */ +struct sparc_bus_dma_tag { + void *_cookie; /* cookie used in the guts */ + struct sparc_bus_dma_tag* _parent; + + /* + * DMA mapping methods. + */ + int (*_dmamap_create)(bus_dma_tag_t, bus_dma_tag_t, bus_size_t, + int, bus_size_t, bus_size_t, int, bus_dmamap_t *); + void (*_dmamap_destroy)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t); + int (*_dmamap_load)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, + void *, bus_size_t, struct proc *, int); + int (*_dmamap_load_mbuf)(bus_dma_tag_t, bus_dma_tag_t, + bus_dmamap_t, struct mbuf *, int); + int (*_dmamap_load_uio)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, + struct uio *, int); + int (*_dmamap_load_raw)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); + void (*_dmamap_unload)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t); + void (*_dmamap_sync)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, + bus_addr_t, bus_size_t, int); + + /* + * DMA memory utility functions. + */ + int (*_dmamem_alloc)(bus_dma_tag_t, bus_dma_tag_t, bus_size_t, + bus_size_t, bus_size_t, bus_dma_segment_t *, int, int *, + int); + void (*_dmamem_free)(bus_dma_tag_t, bus_dma_tag_t, + bus_dma_segment_t *, int); + int (*_dmamem_map)(bus_dma_tag_t, bus_dma_tag_t, + bus_dma_segment_t *, int, size_t, caddr_t *, int); + void (*_dmamem_unmap)(bus_dma_tag_t, bus_dma_tag_t, caddr_t, + size_t); + paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_tag_t, + bus_dma_segment_t *, int, off_t, int, int); +}; + +#define _BD_PRECALL(t,f) \ + while (t->f == NULL) { \ + t = t->_parent; \ + } +#define _BD_CALL(t,f) \ + (*(t)->f) +#define _BD_POSTCALL + +static inline int +bus_dmamap_create(bus_dma_tag_t t, bus_size_t s, int n, bus_size_t m, + bus_size_t b, int f, bus_dmamap_t *p) +{ + int r; + const bus_dma_tag_t t0 = t; + _BD_PRECALL(t, _dmamap_create); + r = _BD_CALL(t, _dmamap_create)(t, t0, s, n, m, b, f, p); + _BD_POSTCALL; + return (r); +} +static inline void +bus_dmamap_destroy(bus_dma_tag_t t, bus_dmamap_t p) +{ + const bus_dma_tag_t t0 = t; + _BD_PRECALL(t, _dmamap_destroy); + _BD_CALL(t, _dmamap_destroy)(t, t0, p); + _BD_POSTCALL; +} +static inline int +bus_dmamap_load(bus_dma_tag_t t, bus_dmamap_t m, void *b, bus_size_t s, + struct proc *p, int f) +{ + const bus_dma_tag_t t0 = t; + int r; + _BD_PRECALL(t, _dmamap_load); + r = _BD_CALL(t, _dmamap_load)(t, t0, m, b, s, p, f); + _BD_POSTCALL; + return (r); +} +static inline int +bus_dmamap_load_mbuf(bus_dma_tag_t t, bus_dmamap_t m, struct mbuf *b, + int f) +{ + const bus_dma_tag_t t0 = t; + int r; + _BD_PRECALL(t, _dmamap_load_mbuf); + r = _BD_CALL(t, _dmamap_load_mbuf)(t, t0, m, b, f); + _BD_POSTCALL; + return (r); +} +static inline int +bus_dmamap_load_uio(bus_dma_tag_t t, bus_dmamap_t m, struct uio * u, int f) +{ + const bus_dma_tag_t t0 = t; + int r; + _BD_PRECALL(t, _dmamap_load_uio); + r = _BD_CALL(t, _dmamap_load_uio)(t, t0, m, u, f); + _BD_POSTCALL; + return (r); +} +static inline int +bus_dmamap_load_raw(bus_dma_tag_t t, bus_dmamap_t m, bus_dma_segment_t *sg, + int n, bus_size_t s, int f) +{ + const bus_dma_tag_t t0 = t; + int r; + _BD_PRECALL(t, _dmamap_load_raw); + r = _BD_CALL(t, _dmamap_load_raw)(t, t0, m, sg, n, s, f); + _BD_POSTCALL; + return (r); +} +static inline void +bus_dmamap_unload(bus_dma_tag_t t, bus_dmamap_t p) +{ + const bus_dma_tag_t t0 = t; + _BD_PRECALL(t, _dmamap_unload); + _BD_CALL(t, _dmamap_unload)(t, t0, p); + _BD_POSTCALL; +} +static inline void +bus_dmamap_sync(bus_dma_tag_t t, bus_dmamap_t p, bus_addr_t o, bus_size_t l, + int ops) +{ + const bus_dma_tag_t t0 = t; + _BD_PRECALL(t, _dmamap_sync); + _BD_CALL(t, _dmamap_sync)(t, t0, p, o, l, ops); + _BD_POSTCALL; +} +static inline int +bus_dmamem_alloc(bus_dma_tag_t t, bus_size_t s, bus_size_t a, bus_size_t b, + bus_dma_segment_t *sg, int n, int *r, int f) +{ + const bus_dma_tag_t t0 = t; + int ret; + _BD_PRECALL(t, _dmamem_alloc); + ret = _BD_CALL(t, _dmamem_alloc)(t, t0, s, a, b, sg, n, r, f); + _BD_POSTCALL; + return (ret); +} +static inline void +bus_dmamem_free(bus_dma_tag_t t, bus_dma_segment_t *sg, int n) +{ + const bus_dma_tag_t t0 = t; + _BD_PRECALL(t, _dmamem_free); + _BD_CALL(t, _dmamem_free)(t, t0, sg, n); + _BD_POSTCALL; +} +static inline int +bus_dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *sg, int n, size_t s, + caddr_t *k, int f) +{ + const bus_dma_tag_t t0 = t; + int r; + _BD_PRECALL(t, _dmamem_map); + r = _BD_CALL(t, _dmamem_map)(t, t0, sg, n, s, k, f); + _BD_POSTCALL; + return (r); +} +static inline void +bus_dmamem_unmap(bus_dma_tag_t t, caddr_t k, size_t s) +{ + const bus_dma_tag_t t0 = t; + _BD_PRECALL(t, _dmamem_unmap); + _BD_CALL(t, _dmamem_unmap)(t, t0, k, s); + _BD_POSTCALL; +} +static inline paddr_t +bus_dmamem_mmap(bus_dma_tag_t t, bus_dma_segment_t *sg, int n, off_t o, int p, + int f) +{ + const bus_dma_tag_t t0 = t; + int r; + _BD_PRECALL(t, _dmamem_mmap); + r = _BD_CALL(t, _dmamem_mmap)(t, t0, sg, n, o, p, f); + _BD_POSTCALL; + return (r); +} + +/* + * bus_dmamap_t + * + * Describes a DMA mapping. + */ +struct sparc_bus_dmamap { + /* + * PRIVATE MEMBERS: not for use by machine-independent code. + */ + bus_addr_t _dm_dvmastart; /* start and size of allocated */ + bus_size_t _dm_dvmasize; /* DVMA segment for this map */ + + bus_size_t _dm_size; /* largest DMA transfer mappable */ + bus_size_t _dm_maxsegsz; /* largest possible segment */ + bus_size_t _dm_boundary; /* don't cross this */ + int _dm_segcnt; /* number of segs this map can map */ + int _dm_flags; /* misc. flags */ +#define _DM_TYPE_LOAD 0 +#define _DM_TYPE_SEGS 1 +#define _DM_TYPE_UIO 2 +#define _DM_TYPE_MBUF 3 + int _dm_type; /* mapping type: raw, uio, mbuf, etc */ + void *_dm_source; /* source mbuf/uio/etc. for unload */ + + void *_dm_cookie; /* cookie for bus-specific functions */ + + /* + * PUBLIC MEMBERS: these are used by machine-independent code. + */ + bus_size_t dm_mapsize; /* size of the mapping */ + int dm_nsegs; /* # valid segments in mapping */ + + bus_dma_segment_t dm_segs[1]; /* segments; variable length */ +}; + +#endif /* _KERNEL */ + +#endif /* _MACHINE_BUS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/cdefs.h b/lib/libc/include/sparc64-openbsd-none/sparc64/cdefs.h new file mode 100644 index 000000000000..26521d24336d --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/cdefs.h @@ -0,0 +1,16 @@ +/* $OpenBSD: cdefs.h,v 1.4 2013/03/28 17:30:45 martynas Exp $ */ + +#ifndef _MACHINE_CDEFS_H_ +#define _MACHINE_CDEFS_H_ + +#define __strong_alias(alias,sym) \ + __asm__(".global " __STRING(alias) " ; " \ + __STRING(alias) " = " __STRING(sym)) +#define __weak_alias(alias,sym) \ + __asm__(".weak " __STRING(alias) " ; " \ + __STRING(alias) " = " __STRING(sym)) +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning." __STRING(sym) \ + " ; .ascii \"" msg "\" ; .text") + +#endif /* !_MACHINE_CDEFS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/conf.h b/lib/libc/include/sparc64-openbsd-none/sparc64/conf.h new file mode 100644 index 000000000000..dd9ef3a150ca --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/conf.h @@ -0,0 +1,101 @@ +/* $OpenBSD: conf.h,v 1.28 2024/03/29 21:06:14 miod Exp $ */ +/* $NetBSD: conf.h,v 1.9 2001/03/26 12:33:26 lukem Exp $ */ + +/*- + * Copyright (c) 1996 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define mmread mmrw +#define mmwrite mmrw +cdev_decl(mm); + +cdev_decl(openprom); + +/* open, close, ioctl */ +#define cdev_openprom_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) nullop, 0, \ + (dev_type_mmap((*))) enodev } + +cdev_decl(uperf); + +/* open, close, ioctl */ +#define cdev_uperf_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) nullop, 0, \ + (dev_type_mmap((*))) enodev } + +cdev_decl(vdsp); + +/* open, close, ioctl */ +#define cdev_vdsp_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) nullop, 0, \ + (dev_type_mmap((*))) enodev } + +#define cdev_gen_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) nullop, \ + 0, (dev_type_mmap((*))) enodev, \ + 0, 0, dev_init(c,n,kqfilter) } + +cdev_decl(zs); + +bdev_decl(fd); +cdev_decl(fd); + +cdev_decl(bpp); +cdev_decl(lpt); + +bdev_decl(wd); +cdev_decl(wd); + +cdev_decl(sabtty); + +cdev_decl(pcons); +cdev_decl(vcons); +cdev_decl(vcctty); +cdev_decl(sbbc); + +cdev_decl(vldcp); + +cdev_decl(com); + +cdev_decl(mtty); +cdev_decl(mbpp); +cdev_decl(stty); +cdev_decl(sbpp); + +/* open, close, write, ioctl */ +#define cdev_bpp_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) nullop, \ + 0, (dev_type_mmap((*))) enodev, 0, 0, seltrue_kqfilter } \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/cpu.h b/lib/libc/include/sparc64-openbsd-none/sparc64/cpu.h new file mode 100644 index 000000000000..e5535fb38275 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/cpu.h @@ -0,0 +1,384 @@ +/* $OpenBSD: cpu.h,v 1.109 2024/11/06 12:06:15 miod Exp $ */ +/* $NetBSD: cpu.h,v 1.28 2001/06/14 22:56:58 thorpej Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)cpu.h 8.4 (Berkeley) 1/5/94 + */ + +#ifndef _MACHINE_CPU_H_ +#define _MACHINE_CPU_H_ + +/* + * CTL_MACHDEP definitions. + */ + /* 1 formerly: booted kernel name */ +#define CPU_LED_BLINK 2 /* int: blink leds? */ +#define CPU_ALLOWAPERTURE 3 /* allow xf86 operations */ +#define CPU_CPUTYPE 4 /* cpu type */ +#define CPU_CECCERRORS 5 /* Correctable ECC errors */ +#define CPU_CECCLAST 6 /* Correctable ECC last fault addr */ + /* 7 formerly: soft reset via keyboard */ +#define CPU_MAXID 8 /* number of valid machdep ids */ + +#define CTL_MACHDEP_NAMES { \ + { 0, 0 }, \ + { 0, 0 }, \ + { "led_blink", CTLTYPE_INT }, \ + { "allowaperture", CTLTYPE_INT }, \ + { "cputype", CTLTYPE_INT }, \ + { "ceccerrs", CTLTYPE_INT }, \ + { "cecclast", CTLTYPE_QUAD }, \ + { 0, 0 }, \ +} + +#ifdef _KERNEL +/* + * Exported definitions unique to SPARC cpu support. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* + * The cpu_info structure is part of a 64KB structure mapped both the kernel + * pmap and a single locked TTE a CPUINFO_VA for that particular processor. + * Each processor's cpu_info is accessible at CPUINFO_VA only for that + * processor. Other processors can access that through an additional mapping + * in the kernel pmap. + * + * The 64KB page contains: + * + * cpu_info + * interrupt stack (all remaining space) + * idle PCB + * idle stack (STACKSPACE - sizeof(PCB)) + * 32KB TSB + */ + +struct cpu_info { + /* + * SPARC cpu_info structures live at two VAs: one global + * VA (so each CPU can access any other CPU's cpu_info) + * and an alias VA CPUINFO_VA which is the same on each + * CPU and maps to that CPU's cpu_info. Since the alias + * CPUINFO_VA is how we locate our cpu_info, we have to + * self-reference the global VA so that we can return it + * in the curcpu() macro. + */ + struct cpu_info * volatile ci_self; + + /* Most important fields first */ + struct proc *ci_curproc; + struct pcb *ci_cpcb; /* also initial stack */ + paddr_t ci_cpcbpaddr; + struct cpu_info *ci_next; + + struct proc *ci_fpproc; + int ci_cpuid; + int ci_flags; + int ci_upaid; +#ifdef MULTIPROCESSOR + int ci_itid; + struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM]; +#define __HAVE_UVM_PERCPU + struct uvm_pmr_cache ci_uvm; /* [o] page cache */ +#endif + int ci_node; + u_int32_t ci_randseed; + struct schedstate_percpu ci_schedstate; /* scheduler state */ + + int ci_want_resched; + int ci_handled_intr_level; + int ci_idepth; + struct intrhand *ci_intrpending[16]; + struct clockqueue ci_queue; + struct intrhand ci_tickintr; + + volatile int ci_ddb_paused; +#define CI_DDB_RUNNING 0 +#define CI_DDB_SHOULDSTOP 1 +#define CI_DDB_STOPPED 2 +#define CI_DDB_ENTERDDB 3 +#define CI_DDB_INDDB 4 + + /* Spinning up the CPU */ + void (*ci_spinup)(void); /* spinup routine */ + void *ci_initstack; + paddr_t ci_paddr; /* Phys addr of this structure. */ + +#ifdef SUN4V + struct rwindow ci_rw; + u_int64_t ci_rwsp; + + paddr_t ci_mmfsa; + paddr_t ci_cpumq; + paddr_t ci_devmq; + + paddr_t ci_cpuset; + paddr_t ci_mondo; +#endif + + int ci_pci_probe; + int ci_pci_fault; + +#ifdef DIAGNOSTIC + int ci_mutex_level; +#endif +#ifdef GPROF + struct gmonparam *ci_gmon; + struct clockintr ci_gmonclock; +#endif + char ci_panicbuf[512]; +}; + +#define CPUF_RUNNING 0x0001 /* CPU is running */ + +extern struct cpu_info *cpus; + +#ifdef MULTIPROCESSOR + +register struct cpu_info *__curcpu asm ("g7"); + +#define curcpu() (__curcpu->ci_self) +#define cpu_number() (__curcpu->ci_cpuid) + +#define CPU_IS_PRIMARY(ci) ((ci)->ci_cpuid == 0) +#define CPU_IS_RUNNING(ci) 1 +#define CPU_INFO_ITERATOR int +#define CPU_INFO_FOREACH(cii, ci) \ + for (cii = 0, ci = cpus; ci != NULL; ci = ci->ci_next) +#define CPU_INFO_UNIT(ci) ((ci)->ci_cpuid) +#define MAXCPUS 256 + +void cpu_boot_secondary_processors(void); + +void sparc64_send_ipi(int, void (*)(void), u_int64_t, u_int64_t); +void sparc64_broadcast_ipi(void (*)(void), u_int64_t, u_int64_t); + +void cpu_unidle(struct cpu_info *); + +#else /* MULTIPROCESSOR */ + +#define __curcpu ((struct cpu_info *)CPUINFO_VA) +#define curcpu() __curcpu +#define cpu_number() 0 + +#define CPU_IS_PRIMARY(ci) 1 +#define CPU_IS_RUNNING(ci) 1 +#define CPU_INFO_ITERATOR int +#define CPU_INFO_FOREACH(cii, ci) \ + for (cii = 0, ci = curcpu(); ci != NULL; ci = NULL) +#define CPU_INFO_UNIT(ci) 0 +#define MAXCPUS 1 + +#define cpu_unidle(ci) + +#endif /* MULTIPROCESSOR */ + +#define curpcb __curcpu->ci_cpcb +#define fpproc __curcpu->ci_fpproc + +static inline unsigned int +cpu_rnd_messybits(void) +{ + u_int64_t tick; + + __asm volatile("rd %%tick, %0" : "=r" (tick) :); + + return ((tick >> 32) ^ tick); +} + +/* + * On processors with multiple threads we force a thread switch. + * + * On UltraSPARC T2 and its successors, the optimal way to do this + * seems to be to do three nop reads of %ccr. This works on + * UltraSPARC T1 as well, even though three nop casx operations seem + * to be slightly more optimal. Since these instructions are + * effectively nops, executing them on earlier non-CMT processors is + * harmless, so we make this the default. + * + * On SPARC T4 and later, we can use the processor-specific pause + * instruction. + * + * On SPARC64 VI and its successors we execute the processor-specific + * sleep instruction. + */ +#define CPU_BUSY_CYCLE() \ +do { \ + __asm volatile( \ + "999: rd %%ccr, %%g0 \n" \ + " rd %%ccr, %%g0 \n" \ + " rd %%ccr, %%g0 \n" \ + " .section .sun4v_pause_patch, \"ax\" \n" \ + " .word 999b \n" \ + " .word 0xb7802080 ! pause 128 \n" \ + " .word 999b + 4 \n" \ + " nop \n" \ + " .word 999b + 8 \n" \ + " nop \n" \ + " .previous \n" \ + " .section .sun4u_mtp_patch, \"ax\" \n" \ + " .word 999b \n" \ + " .word 0x81b01060 ! sleep \n" \ + " .word 999b + 4 \n" \ + " nop \n" \ + " .word 999b + 8 \n" \ + " nop \n" \ + " .previous \n" \ + : : : "memory"); \ +} while (0) + +/* + * Arguments to clockintr_dispatch encapsulate the + * previous machine state in an opaque clockframe. + */ +struct clockframe { + struct trapframe t; + int saved_intr_level; +}; + +#define CLKF_USERMODE(framep) (((framep)->t.tf_tstate & TSTATE_PRIV) == 0) +#define CLKF_PC(framep) ((framep)->t.tf_pc) +#define CLKF_INTR(framep) ((framep)->saved_intr_level != 0) + +extern void (*cpu_start_clock)(void); + +#define aston(p) ((p)->p_md.md_astpending = 1) + +/* + * Preempt the current process if in interrupt from user mode, + * or after the current trap/syscall if in system mode. + */ +extern void need_resched(struct cpu_info *); +#define clear_resched(ci) (ci)->ci_want_resched = 0 + +/* + * This is used during profiling to integrate system time. + */ +#define PROC_PC(p) ((p)->p_md.md_tf->tf_pc) +#define PROC_STACK(p) ((p)->p_md.md_tf->tf_out[6] + (2048-1)) /* BIAS */ + +/* + * Give a profiling tick to the current process when the user profiling + * buffer pages are invalid. On the sparc, request an ast to send us + * through trap(), marking the proc as needing a profiling tick. + */ +#define need_proftick(p) aston(p) + +void signotify(struct proc *); + +/* cpu.c */ +int cpu_myid(void); +/* machdep.c */ +void dumpconf(void); +caddr_t reserve_dumppages(caddr_t); +/* clock.c */ +struct timeval; +int clockintr(void *);/* level 10 (clock) interrupt code */ +/* locore.s */ +struct fpstate; +void savefpstate(struct fpstate *); +void loadfpstate(struct fpstate *); +void clearfpstate(void); +u_int64_t probeget(paddr_t, int, int); +#define write_all_windows() __asm volatile("flushw" : : ) +void write_user_windows(void); +void proc_trampoline(void); +struct pcb; +void snapshot(struct pcb *); +struct frame *getfp(void); +void switchtoctx(int); +/* trap.c */ +void pmap_unuse_final(struct proc *); +int rwindow_save(struct proc *); +/* vm_machdep.c */ +void fpusave_cpu(struct cpu_info *, int); +void fpusave_proc(struct proc *, int); +/* fb.c */ +void fb_unblank(void); +/* ltc.c */ +void ltc_full_blast(void); +/* tda.c */ +void tda_full_blast(void); +/* emul.c */ +int emul_qf(int32_t, struct proc *, union sigval, struct trapframe *); +int emul_popc(int32_t, struct proc *, union sigval, struct trapframe *); + +/* + * + * The SPARC has a Trap Base Register (TBR) which holds the upper 20 bits + * of the trap vector table. The next eight bits are supplied by the + * hardware when the trap occurs, and the bottom four bits are always + * zero (so that we can shove up to 16 bytes of executable code---exactly + * four instructions---into each trap vector). + * + * The hardware allocates half the trap vectors to hardware and half to + * software. + * + * Traps have priorities assigned (lower number => higher priority). + */ + +struct trapvec { + int tv_instr[8]; /* the eight instructions */ +}; +extern struct trapvec trapbase[]; /* the 256 vectors */ + +struct blink_led { + void (*bl_func)(void *, int); + void *bl_arg; + SLIST_ENTRY(blink_led) bl_next; +}; + +extern void blink_led_register(struct blink_led *); + +#ifdef MULTIPROCESSOR +#include +#endif + +#endif /* _KERNEL */ +#endif /* _MACHINE_CPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/ctlreg.h b/lib/libc/include/sparc64-openbsd-none/sparc64/ctlreg.h new file mode 100644 index 000000000000..6120cae56e03 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/ctlreg.h @@ -0,0 +1,715 @@ +/* $OpenBSD: ctlreg.h,v 1.33 2025/07/16 07:15:42 jsg Exp $ */ +/* $NetBSD: ctlreg.h,v 1.28 2001/08/06 23:55:34 eeh Exp $ */ + +/* + * Copyright (c) 1996-2001 Eduardo Horvath + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/* + * Copyright (c) 2001 Jake Burkholder. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _SPARC64_CTLREG_ +#define _SPARC64_CTLREG_ + +/* + * Sun 4u control registers. (includes address space definitions + * and some registers in control space). + */ + +/* + * The Alternate address spaces. + * + * 0x00-0x7f are privileged + * 0x80-0xff can be used by users + */ + +#define ASI_LITTLE 0x08 /* This bit should make an ASI little endian */ + +#define ASI_NUCLEUS 0x04 /* [4u] kernel address space */ +#define ASI_NUCLEUS_LITTLE 0x0c /* [4u] kernel address space, little endian */ + +#define ASI_AS_IF_USER_PRIMARY 0x10 /* [4u] primary user address space */ +#define ASI_AS_IF_USER_SECONDARY 0x11 /* [4u] secondary user address space */ + +#define ASI_PHYS_CACHED 0x14 /* [4u] MMU bypass to main memory */ +#define ASI_PHYS_NON_CACHED 0x15 /* [4u] MMU bypass to I/O location */ + +#define ASI_AS_IF_USER_PRIMARY_LITTLE 0x18 /* [4u] primary user address space, little endian */ +#define ASI_AS_IF_USER_SECONDARY_LITTIE 0x19 /* [4u] secondary user address space, little endian */ + +#define ASI_PHYS_CACHED_LITTLE 0x1c /* [4u] MMU bypass to main memory, little endian */ +#define ASI_PHYS_NON_CACHED_LITTLE 0x1d /* [4u] MMU bypass to I/O location, little endian */ + +#define ASI_SCRATCHPAD 0x20 /* [4v] scratchpad registers */ +#define ASI_MMU_CONTEXTID 0x21 /* [4v] MMU context */ + +#define ASI_NUCLEUS_QUAD_LDD 0x24 /* [4u] use w/LDDA to load 128-bit item */ +#define ASI_QUEUE 0x25 /* [4v] interrupt queue registers */ +#define ASI_NUCLEUS_QUAD_LDD_LITTLE 0x2c /* [4u] use w/LDDA to load 128-bit item, little endian */ + +#define ASI_FLUSH_D_PAGE_PRIMARY 0x38 /* [4u] flush D-cache page using primary context */ +#define ASI_FLUSH_D_PAGE_SECONDARY 0x39 /* [4u] flush D-cache page using secondary context */ +#define ASI_FLUSH_D_CTX_PRIMARY 0x3a /* [4u] flush D-cache context using primary context */ +#define ASI_FLUSH_D_CTX_SECONDARY 0x3b /* [4u] flush D-cache context using secondary context */ + +#define ASI_DCACHE_INVALIDATE 0x42 /* [III] invalidate D-cache */ +#define ASI_DCACHE_UTAG 0x43 /* [III] diagnostic access to D-cache micro tag */ +#define ASI_DCACHE_SNOOP_TAG 0x44 /* [III] diagnostic access to D-cache snoop tag RAM */ + +#define ASI_LSU_CONTROL_REGISTER 0x45 /* [4u] load/store unit control register */ + +#define ASI_DCACHE_DATA 0x46 /* [4u] diagnostic access to D-cache data RAM */ +#define ASI_DCACHE_TAG 0x47 /* [4u] diagnostic access to D-cache tag RAM */ + +#define ASI_INTR_DISPATCH_STATUS 0x48 /* [4u] interrupt dispatch status register */ +#define ASI_INTR_RECEIVE 0x49 /* [4u] interrupt receive status register */ +#define ASI_MID_REG 0x4a /* [4u] hardware config and MID */ +#define ASI_ERROR_EN_REG 0x4b /* [4u] asynchronous error enables */ +#define ASI_AFSR 0x4c /* [4u] asynchronous fault status register */ +#define ASI_AFAR 0x4d /* [4u] asynchronous fault address register */ + +#define ASI_SCRATCH 0x4f /* [VI] scratch registers */ + +#define ASI_ICACHE_DATA 0x66 /* [4u] diagnostic access to D-cache data RAM */ +#define ASI_ICACHE_TAG 0x67 /* [4u] diagnostic access to D-cache tag RAM */ +#define ASI_FLUSH_I_PAGE_PRIMARY 0x68 /* [4u] flush D-cache page using primary context */ +#define ASI_FLUSH_I_PAGE_SECONDARY 0x69 /* [4u] flush D-cache page using secondary context */ +#define ASI_FLUSH_I_CTX_PRIMARY 0x6a /* [4u] flush D-cache context using primary context */ +#define ASI_FLUSH_I_CTX_SECONDARY 0x6b /* [4u] flush D-cache context using secondary context */ + +#define ASI_BLOCK_AS_IF_USER_PRIMARY 0x70 /* [4u] primary user address space, block loads/stores */ +#define ASI_BLOCK_AS_IF_USER_SECONDARY 0x71 /* [4u] secondary user address space, block loads/stores */ + +#define ASI_ECACHE_DIAG 0x76 /* [4u] diag access to E-cache tag and data */ +#define ASI_DATAPATH_ERR_REG_WRITE 0x77 /* [4u] ASI is reused */ + +#define ASI_BLOCK_AS_IF_USER_PRIMARY_LITTLE 0x78 /* [4u] primary user address space, block loads/stores */ +#define ASI_BLOCK_AS_IF_USER_SECONDARY_LITTLE 0x79 /* [4u] secondary user address space, block loads/stores */ + +#define ASI_INTERRUPT_RECEIVE_DATA 0x7f /* [4u] interrupt receive data registers {0,1,2} */ +#define ASI_DATAPATH_ERR_REG_READ 0x7f /* [4u] read access to datapath error registers (ASI reused) */ + +#define ASI_PRIMARY 0x80 /* [4u] primary address space */ +#define ASI_SECONDARY 0x81 /* [4u] secondary address space */ +#define ASI_PRIMARY_NOFAULT 0x82 /* [4u] primary address space, no fault */ +#define ASI_SECONDARY_NOFAULT 0x83 /* [4u] secondary address space, no fault */ + +#define ASI_PRIMARY_LITTLE 0x88 /* [4u] primary address space, little endian */ +#define ASI_SECONDARY_LITTLE 0x89 /* [4u] secondary address space, little endian */ +#define ASI_PRIMARY_NOFAULT_LITTLE 0x8a /* [4u] primary address space, no fault, little endian */ +#define ASI_SECONDARY_NOFAULT_LITTLE 0x8b /* [4u] secondary address space, no fault, little endian */ + +#define ASI_PST8_PRIMARY 0xc0 /* [VIS] Eight 8-bit partial store, primary */ +#define ASI_PST8_SECONDARY 0xc1 /* [VIS] Eight 8-bit partial store, secondary */ +#define ASI_PST16_PRIMARY 0xc2 /* [VIS] Four 16-bit partial store, primary */ +#define ASI_PST16_SECONDARY 0xc3 /* [VIS] Fout 16-bit partial store, secondary */ +#define ASI_PST32_PRIMARY 0xc4 /* [VIS] Two 32-bit partial store, primary */ +#define ASI_PST32_SECONDARY 0xc5 /* [VIS] Two 32-bit partial store, secondary */ + +#define ASI_PST8_PRIMARY_LITTLE 0xc8 /* [VIS] Eight 8-bit partial store, primary, little endian */ +#define ASI_PST8_SECONDARY_LITTLE 0xc9 /* [VIS] Eight 8-bit partial store, secondary, little endian */ +#define ASI_PST16_PRIMARY_LITTLE 0xca /* [VIS] Four 16-bit partial store, primary, little endian */ +#define ASI_PST16_SECONDARY_LITTLE 0xcb /* [VIS] Fout 16-bit partial store, secondary, little endian */ +#define ASI_PST32_PRIMARY_LITTLE 0xcc /* [VIS] Two 32-bit partial store, primary, little endian */ +#define ASI_PST32_SECONDARY_LITTLE 0xcd /* [VIS] Two 32-bit partial store, secondary, little endian */ + +#define ASI_FL8_PRIMARY 0xd0 /* [VIS] One 8-bit load/store floating, primary */ +#define ASI_FL8_SECONDARY 0xd1 /* [VIS] One 8-bit load/store floating, secondary */ +#define ASI_FL16_PRIMARY 0xd2 /* [VIS] One 16-bit load/store floating, primary */ +#define ASI_FL16_SECONDARY 0xd3 /* [VIS] One 16-bit load/store floating, secondary */ + +#define ASI_FL8_PRIMARY_LITTLE 0xd8 /* [VIS] One 8-bit load/store floating, primary, little endian */ +#define ASI_FL8_SECONDARY_LITTLE 0xd9 /* [VIS] One 8-bit load/store floating, secondary, little endian */ +#define ASI_FL16_PRIMARY_LITTLE 0xda /* [VIS] One 16-bit load/store floating, primary, little endian */ +#define ASI_FL16_SECONDARY_LITTLE 0xdb /* [VIS] One 16-bit load/store floating, secondary, little endian */ + +#define ASI_BLOCK_COMMIT_PRIMARY 0xe0 /* [4u] block store with commit, primary */ +#define ASI_BLOCK_COMMIT_SECONDARY 0xe1 /* [4u] block store with commit, secondary */ +#define ASI_BLOCK_PRIMARY 0xf0 /* [4u] block load/store, primary */ +#define ASI_BLOCK_SECONDARY 0xf1 /* [4u] block load/store, secondary */ +#define ASI_BLOCK_PRIMARY_LITTLE 0xf8 /* [4u] block load/store, primary, little endian */ +#define ASI_BLOCK_SECONDARY_LITTLE 0xf9 /* [4u] block load/store, secondary, little endian */ + + +/* + * These are the shorter names used by Solaris + */ + +#define ASI_N ASI_NUCLEUS +#define ASI_NL ASI_NUCLEUS_LITTLE +#define ASI_AIUP ASI_AS_IF_USER_PRIMARY +#define ASI_AIUS ASI_AS_IF_USER_SECONDARY +#define ASI_AIUPL ASI_AS_IF_USER_PRIMARY_LITTLE +#define ASI_AIUSL ASI_AS_IF_USER_SECONDARY_LITTLE +#define ASI_P ASI_PRIMARY +#define ASI_S ASI_SECONDARY +#define ASI_PNF ASI_PRIMARY_NOFAULT +#define ASI_SNF ASI_SECONDARY_NOFAULT +#define ASI_PL ASI_PRIMARY_LITTLE +#define ASI_SL ASI_SECONDARY_LITTLE +#define ASI_PNFL ASI_PRIMARY_NOFAULT_LITTLE +#define ASI_SNFL ASI_SECONDARY_NOFAULT_LITTLE +#define ASI_FL8_P ASI_FL8_PRIMARY +#define ASI_FL8_S ASI_FL8_SECONDARY +#define ASI_FL16_P ASI_FL16_PRIMARY +#define ASI_FL16_S ASI_FL16_SECONDARY +#define ASI_FL8_PL ASI_FL8_PRIMARY_LITTLE +#define ASI_FL8_SL ASI_FL8_SECONDARY_LITTLE +#define ASI_FL16_PL ASI_FL16_PRIMARY_LITTLE +#define ASI_FL16_SL ASI_FL16_SECONDARY_LITTLE +#define ASI_BLK_AIUP ASI_BLOCK_AS_IF_USER_PRIMARY +#define ASI_BLK_AIUPL ASI_BLOCK_AS_IF_USER_PRIMARY_LITTLE +#define ASI_BLK_AIUS ASI_BLOCK_AS_IF_USER_SECONDARY +#define ASI_BLK_AIUSL ASI_BLOCK_AS_IF_USER_SECONDARY_LITTLE +#define ASI_BLK_COMMIT_P ASI_BLOCK_COMMIT_PRIMARY +#define ASI_BLK_COMMIT_PRIMARY ASI_BLOCK_COMMIT_PRIMARY +#define ASI_BLK_COMMIT_S ASI_BLOCK_COMMIT_SECONDARY +#define ASI_BLK_COMMIT_SECONDARY ASI_BLOCK_COMMIT_SECONDARY +#define ASI_BLK_P ASI_BLOCK_PRIMARY +#define ASI_BLK_PL ASI_BLOCK_PRIMARY_LITTLE +#define ASI_BLK_S ASI_BLOCK_SECONDARY +#define ASI_BLK_SL ASI_BLOCK_SECONDARY_LITTLE + +/* Alternative spellings */ +#define ASI_PRIMARY_NO_FAULT ASI_PRIMARY_NOFAULT +#define ASI_PRIMARY_NO_FAULT_LITTLE ASI_PRIMARY_NOFAULT_LITTLE +#define ASI_SECONDARY_NO_FAULT ASI_SECONDARY_NOFAULT +#define ASI_SECONDARY_NO_FAULT_LITTLE ASI_SECONDARY_NOFAULT_LITTLE + +#define PHYS_ASI(x) (((x) | 0x09) == 0x1d) +#define LITTLE_ASI(x) ((x) & ASI_LITTLE) + +/* + * %tick: cpu cycle counter + */ +#define TICK_NPT 0x8000000000000000 /* trap on non priv access */ +#define TICK_TICKS 0x7fffffffffffffff /* counter bits */ + +/* + * The following are 4u control registers + */ + +/* Get the CPU's UPA port ID */ +#define UPA_CR_MID(x) (((x) >> 17) & 0x1f) +#define CPU_UPAID UPA_CR_MID(ldxa(0, ASI_MID_REG)) + +/* Get the CPU's Fireplane agent ID */ +#define FIREPLANE_CR_AID(x) (((x) >> 17) & 0x3ff) +#define CPU_FIREPLANEID FIREPLANE_CR_AID(ldxa(0, ASI_MID_REG)) + +/* Get the CPU's Jupiter Bus interrupt target ID */ +#define JUPITER_CR_ITID(x) ((x) & 0x3ff) +#define CPU_JUPITERID JUPITER_CR_ITID(ldxa(0, ASI_MID_REG)) + +/* + * [4u] MMU and Cache Control Register (MCCR) + * use ASI = 0x45 + */ +#define ASI_MCCR ASI_LSU_CONTROL_REGISTER +#define MCCR 0x00 + +/* MCCR Bits and their meanings */ +#define MCCR_DMMU_EN 0x08 +#define MCCR_IMMU_EN 0x04 +#define MCCR_DCACHE_EN 0x02 +#define MCCR_ICACHE_EN 0x01 + + +/* + * MMU control registers + */ + +/* Choose an MMU */ +#define ASI_DMMU 0x58 +#define ASI_IMMU 0x50 + +/* Other assorted MMU ASIs */ +#define ASI_IMMU_8KPTR 0x51 +#define ASI_IMMU_64KPTR 0x52 +#define ASI_IMMU_DATA_IN 0x54 +#define ASI_IMMU_TLB_DATA 0x55 +#define ASI_IMMU_TLB_TAG 0x56 +#define ASI_DMMU_8KPTR 0x59 +#define ASI_DMMU_64KPTR 0x5a +#define ASI_DMMU_DATA_IN 0x5c +#define ASI_DMMU_TLB_DATA 0x5d +#define ASI_DMMU_TLB_TAG 0x5e + +/* + * The following are the control registers + * They work on both MMUs unless noted. + * III = cheetah only + * + * Register contents are defined later on individual registers. + */ +#define TSB_TAG_TARGET 0x0 +#define TLB_DATA_IN 0x0 +#define CTX_PRIMARY 0x08 /* primary context -- DMMU only */ +#define CTX_SECONDARY 0x10 /* secondary context -- DMMU only */ +#define SFSR 0x18 +#define SFAR 0x20 /* fault address -- DMMU only */ +#define TSB 0x28 +#define TLB_TAG_ACCESS 0x30 +#define VIRTUAL_WATCHPOINT 0x38 +#define PHYSICAL_WATCHPOINT 0x40 +#define TSB_PEXT 0x48 /* III primary ext */ +#define TSB_SEXT 0x50 /* III 2ndary ext -- DMMU only */ +#define TSB_NEXT 0x58 /* III nucleus ext */ + +/* Tag Target bits */ +#define TAG_TARGET_VA_MASK 0x03ffffffffffffffffLL +#define TAG_TARGET_VA(x) (((x)<<22)&TAG_TARGET_VA_MASK) +#define TAG_TARGET_CONTEXT(x) ((x)>>48) +#define TAG_TARGET(c,v) ((((uint64_t)c)<<48)|(((uint64_t)v)&TAG_TARGET_VA_MASK)) + +/* SFSR bits for both D_SFSR and I_SFSR */ +#define SFSR_NF 0x1000000 /* Non-faulting load */ +#define SFSR_ASI(x) ((x)>>16) +#define SFSR_TM 0x0008000 /* TLB miss */ +#define SFSR_FT_VA_OOR_2 0x0002000 /* IMMU: jumpl or return to unsupported VA */ +#define SFSR_FT_VA_OOR_1 0x0001000 /* fault at unsupported VA */ +#define SFSR_FT_NFO 0x0000800 /* DMMU: Access to page marked NFO */ +#define SFSR_ILL_ASI 0x0000400 /* DMMU: Illegal (unsupported) ASI */ +#define SFSR_FT_IO_ATOMIC 0x0000200 /* DMMU: Atomic access to noncacheable page */ +#define SFSR_FT_ILL_NF 0x0000100 /* DMMU: NF load or flush to page marked E (has side effects) */ +#define SFSR_FT_PRIV 0x0000080 /* Privilege violation */ +#define SFSR_FT_E 0x0000040 /* DMUU: value of E bit associated address */ +#define SFSR_CTXT(x) (((x)>>4)&0x3) +#define SFSR_CTXT_IS_PRIM(x) (SFSR_CTXT(x)==0x00) +#define SFSR_CTXT_IS_SECOND(x) (SFSR_CTXT(x)==0x01) +#define SFSR_CTXT_IS_NUCLEUS(x) (SFSR_CTXT(x)==0x02) +#define SFSR_PRIV 0x0000008 /* value of PSTATE.PRIV for faulting access */ +#define SFSR_W 0x0000004 /* DMMU: attempted write */ +#define SFSR_OW 0x0000002 /* Overwrite; prev fault was still valid */ +#define SFSR_FV 0x0000001 /* Fault is valid */ +#define SFSR_FT (SFSR_FT_VA_OOR_2|SFSR_FT_VA_OOR_1|SFSR_FT_NFO|SFSR_ILL_ASI|SFSR_FT_IO_ATOMIC|SFSR_FT_ILL_NF|SFSR_FT_PRIV) + +#define SFSR_BITS "\20\31NF\20TM\16VAT\15VAD\14NFO\13ASI\12A\11NF\10PRIV\7E\6NUCLEUS\5SECONDCTX\4PRIV\3W\2OW\1FV" + +/* ASFR bits */ +#define ASFR_ME 0x100000000LL +#define ASFR_PRIV 0x080000000LL +#define ASFR_ISAP 0x040000000LL +#define ASFR_ETP 0x020000000LL +#define ASFR_IVUE 0x010000000LL +#define ASFR_TO 0x008000000LL +#define ASFR_BERR 0x004000000LL +#define ASFR_LDP 0x002000000LL +#define ASFR_CP 0x001000000LL +#define ASFR_WP 0x000800000LL +#define ASFR_EDP 0x000400000LL +#define ASFR_UE 0x000200000LL +#define ASFR_CE 0x000100000LL +#define ASFR_ETS 0x0000f0000LL +#define ASFT_P_SYND 0x00000ffffLL + +#define AFSR_BITS "\20" \ + "\20ME\37PRIV\36ISAP\35ETP\34IVUE\33TO\32BERR\31LDP\30CP\27WP\26EDP" \ + "\25UE\24CE" + +/* + * Here's the spitfire TSB control register bits. + * + * Each TSB entry is 16-bytes wide. The TSB must be size aligned + */ +#define TSB_SIZE_512 0x0 /* 8kB, etc. */ +#define TSB_SIZE_1K 0x01 +#define TSB_SIZE_2K 0x02 +#define TSB_SIZE_4K 0x03 +#define TSB_SIZE_8K 0x04 +#define TSB_SIZE_16K 0x05 +#define TSB_SIZE_32K 0x06 +#define TSB_SIZE_64K 0x07 +#define TSB_SPLIT 0x1000 +#define TSB_BASE 0xffffffffffffe000 + +/* TLB Tag Access bits */ +#define TLB_TAG_ACCESS_VA 0xffffffffffffe000 +#define TLB_TAG_ACCESS_CTX 0x0000000000001fff + +/* + * TLB demap registers. TTEs are defined in v9pte.h + * + * Use the address space to select between IMMU and DMMU. + * The address of the register selects which context register + * to read the ASI from. + * + * The data stored in the register is interpreted as the VA to + * use. The DEMAP_CTX_<> registers ignore the address and demap the + * entire ASI. + * + */ +#define ASI_IMMU_DEMAP 0x57 /* [4u] IMMU TLB demap */ +#define ASI_DMMU_DEMAP 0x5f /* [4u] IMMU TLB demap */ + +#define DEMAP_PAGE_NUCLEUS ((0x02)<<4) /* Demap page from kernel AS */ +#define DEMAP_PAGE_PRIMARY ((0x00)<<4) /* Demap a page from primary CTXT */ +#define DEMAP_PAGE_SECONDARY ((0x01)<<4) /* Demap page from secondary CTXT (DMMU only) */ +#define DEMAP_CTX_NUCLEUS ((0x06)<<4) /* Demap all of kernel CTXT */ +#define DEMAP_CTX_PRIMARY ((0x04)<<4) /* Demap all of primary CTXT */ +#define DEMAP_CTX_SECONDARY ((0x05)<<4) /* Demap all of secondary CTXT */ + +/* + * Interrupt registers. This really gets hairy. + */ + +/* IRSR -- Interrupt Receive Status Register */ +#define ASI_IRSR 0x49 +#define IRSR 0x00 +#define IRSR_BUSY 0x020 +#define IRSR_MID(x) (x&0x1f) + +/* IRDR -- Interrupt Receive Data Registers */ +#define ASI_IRDR 0x7f +#define IRDR_0H 0x40 +#define IRDR_0L 0x48 /* unimplemented */ +#define IRDR_1H 0x50 +#define IRDR_1L 0x58 /* unimplemented */ +#define IRDR_2H 0x60 +#define IRDR_2L 0x68 /* unimplemented */ +#define IRDR_3H 0x70 /* unimplemented */ +#define IRDR_3L 0x78 /* unimplemented */ + +/* SOFTINT ASRs */ +#define SET_SOFTINT %asr20 /* Sets these bits */ +#define CLEAR_SOFTINT %asr21 /* Clears these bits */ +#define SOFTINT %asr22 /* Reads the register */ +#define TICK_CMPR %asr23 + +#define TICK_INT 0x01 /* level-14 clock tick */ +#define SOFTINT1 (0x1<<1) +#define SOFTINT2 (0x1<<2) +#define SOFTINT3 (0x1<<3) +#define SOFTINT4 (0x1<<4) +#define SOFTINT5 (0x1<<5) +#define SOFTINT6 (0x1<<6) +#define SOFTINT7 (0x1<<7) +#define SOFTINT8 (0x1<<8) +#define SOFTINT9 (0x1<<9) +#define SOFTINT10 (0x1<<10) +#define SOFTINT11 (0x1<<11) +#define SOFTINT12 (0x1<<12) +#define SOFTINT13 (0x1<<13) +#define SOFTINT14 (0x1<<14) +#define SOFTINT15 (0x1<<15) +#define STICK_INT (0x1<<16) + +/* Interrupt Dispatch -- usually reserved for cross-calls */ +#define ASR_IDSR 0x48 /* Interrupt dispatch status reg */ +#define IDSR 0x00 +#define IDSR_NACK 0x02 +#define IDSR_BUSY 0x01 + +#define ASI_INTERRUPT_DISPATCH 0x77 /* [4u] spitfire interrupt dispatch regs */ + +/* Interrupt delivery initiation */ +#define IDCR(x) ((((u_int64_t)(x)) << 14) | 0x70) + +#define IDDR_0H 0x40 /* Store data to send in these regs */ +#define IDDR_0L 0x48 /* unimplemented */ +#define IDDR_1H 0x50 +#define IDDR_1L 0x58 /* unimplemented */ +#define IDDR_2H 0x60 +#define IDDR_2L 0x68 /* unimplemented */ +#define IDDR_3H 0x80 /* unimplemented */ +#define IDDR_3L 0x88 /* unimplemented */ + +/* + * Error registers + */ + +/* Since we won't try to fix async errs, we don't care about the bits in the regs */ +#define ASI_AFAR 0x4d /* Asynchronous fault address register */ +#define AFAR 0x00 +#define ASI_AFSR 0x4c /* Asynchronous fault status register */ +#define AFSR 0x00 + +#define ASI_P_EER 0x4b /* Error enable register */ +#define P_EER 0x00 +#define P_EER_ISAPEN 0x04 /* Enable fatal on ISAP */ +#define P_EER_NCEEN 0x02 /* Enable trap on uncorrectable errs */ +#define P_EER_CEEN 0x01 /* Enable trap on correctable errs */ + +#define ASI_DATAPATH_READ 0x7f /* Read the regs */ +#define ASI_DATAPATH_WRITE 0x77 /* Write to the regs */ +#define P_DPER_0 0x00 /* Datapath err reg 0 */ +#define P_DPER_1 0x18 /* Datapath err reg 1 */ +#define P_DCR_0 0x20 /* Datapath control reg 0 */ +#define P_DCR_1 0x38 /* Datapath control reg 0 */ + + +/* From sparc64/asm.h which I think I'll deprecate since it makes bus.h a pain. */ + +#ifndef _LOCORE +/* + * GCC __asm constructs for doing assembly stuff. + */ + +/* + * ``Routines'' to load and store from/to alternate address space. + * The location can be a variable, the asi value (address space indicator) + * must be a constant. + * + * N.B.: You can put as many special functions here as you like, since + * they cost no kernel space or time if they are not used. + * + * These were static inline functions, but gcc screws up the constraints + * on the address space identifiers (the "n"umeric value part) because + * it inlines too late, so we have to use the funny valued-macro syntax. + */ + +/* + * Apparently the definition of bypass ASIs is that they all use the + * D$ so we need to flush the D$ to make sure we don't get data pollution. + */ + +#define sparc_wr(name, val, xor) \ +do { \ + if (__builtin_constant_p(xor)) \ + __asm volatile("wr %%g0, %0, %%" #name \ + : : "rI" ((val) ^ (xor)) : "%g0"); \ + else \ + __asm volatile("wr %0, %1, %%" #name \ + : : "r" (val), "rI" (xor) : "%g0"); \ +} while(0) + +#define sparc_wrpr(name, val, xor) \ +do { \ + if (__builtin_constant_p(xor)) \ + __asm volatile("wrpr %%g0, %0, %%" #name \ + : : "rI" ((val) ^ (xor)) : "%g0"); \ + else \ + __asm volatile("wrpr %0, %1, %%" #name \ + : : "r" (val), "rI" (xor) : "%g0"); \ + __asm volatile("" : : : "memory"); \ +} while(0) + + +#define sparc_rd(name) sparc_rd_ ## name() +#define GEN_RD(name) \ +static inline u_int64_t sparc_rd_ ## name(void); \ +static inline u_int64_t \ +sparc_rd_ ## name(void) \ +{ \ + u_int64_t r; \ + __asm volatile("rd %%" #name ", %0" : \ + "=r" (r) : : "%g0"); \ + return (r); \ +} + +#define sparc_rdpr(name) sparc_rdpr_ ## name() +#define GEN_RDPR(name) \ +static inline u_int64_t sparc_rdpr_ ## name(void); \ +static inline u_int64_t \ +sparc_rdpr_ ## name(void) \ +{ \ + u_int64_t r; \ + __asm volatile("rdpr %%" #name ", %0" : \ + "=r" (r) : : "%g0"); \ + return (r); \ +} + +GEN_RD(asi); +GEN_RD(fprs); +GEN_RD(asr22); +GEN_RD(sys_tick); +GEN_RD(sys_tick_cmpr); +GEN_RDPR(tick); +GEN_RDPR(tba); +GEN_RDPR(pstate); +GEN_RDPR(pil); +GEN_RDPR(cwp); +GEN_RDPR(cansave); +GEN_RDPR(canrestore); +GEN_RDPR(cleanwin); +GEN_RDPR(otherwin); +GEN_RDPR(wstate); +GEN_RDPR(ver); +/* + * Before adding GEN_RDPRs for other registers, see Errata 50 (E.g,. in + * the US-IIi manual) regarding tstate, pc and npc reads. + */ + +/* Generate ld*a/st*a functions for non-constant ASI's. */ +#define LDNC_GEN(tp, o) \ + static inline tp o ## _asi(paddr_t); \ + static inline tp \ + o ## _asi(paddr_t va) \ + { \ + tp r; \ + __asm volatile( \ + #o " [%1] %%asi, %0" \ + : "=r" (r) \ + : "r" ((volatile tp *)va) \ + : "%g0"); \ + return (r); \ + } \ + static inline tp o ## _nc(paddr_t, int); \ + static inline tp \ + o ## _nc(paddr_t va, int asi) \ + { \ + sparc_wr(asi, asi, 0); \ + return (o ## _asi(va)); \ + } + +LDNC_GEN(u_char, lduba); +LDNC_GEN(u_short, lduha); +LDNC_GEN(u_int, lduwa); +LDNC_GEN(u_int64_t, ldxa); + +LDNC_GEN(int, lda); + +#define LDC_GEN(va, asi, op, opa, type) ({ \ + type __r ## op ## type; \ + if(asi == ASI_PRIMARY || \ + (sizeof(type) == 1 && asi == ASI_PRIMARY_LITTLE)) \ + __r ## op ## type = *((volatile type *)va); \ + else \ + __asm volatile(#opa " [%1] " #asi ", %0" \ + : "=r" (__r ## op ## type) \ + : "r" ((volatile type *)va) \ + : "%g0"); \ + __r ## op ## type; \ +}) + +#ifdef __OPTIMIZE__ +#define LD_GENERIC(va, asi, op, type) (__builtin_constant_p(asi) ? \ + LDC_GEN((va), asi, op, op ## a, type) : op ## a_nc((va), asi)) +#else /* __OPTIMIZE */ +#define LD_GENERIC(va, asi, op, type) (op ## a_nc((va), asi)) +#endif /* __OPTIMIZE__ */ + +#define lduba(va, asi) LD_GENERIC(va, asi, ldub, u_int8_t) +#define lduha(va, asi) LD_GENERIC(va, asi, lduh, u_int16_t) +#define lduwa(va, asi) LD_GENERIC(va, asi, lduw, u_int32_t) +#define ldxa(va, asi) LD_GENERIC(va, asi, ldx, u_int64_t) + +#define STNC_GEN(tp, o) \ + static inline void o ## _asi(paddr_t, tp); \ + static inline void \ + o ## _asi(paddr_t va, tp val) \ + { \ + __asm volatile( \ + #o " %0, [%1] %%asi" \ + : \ + : "r" (val), "r" ((volatile tp *)va) \ + : "memory"); \ + } \ + static inline void o ## _nc(paddr_t, int, tp); \ + static inline void \ + o ## _nc(paddr_t va, int asi, tp val) \ + { \ + sparc_wr(asi, asi, 0); \ + o ## _asi(va, val); \ + } + +STNC_GEN(u_int8_t, stba); +STNC_GEN(u_int16_t, stha); +STNC_GEN(u_int32_t, stwa); +STNC_GEN(u_int64_t, stxa); + +STNC_GEN(u_int, sta); + +#define STC_GEN(va, asi, val, op, opa, type) ({ \ + if(asi == ASI_PRIMARY || \ + (sizeof(type) == 1 && asi == ASI_PRIMARY_LITTLE)) \ + *((volatile type *)va) = val; \ + else \ + __asm volatile(#opa " %0, [%1] " #asi \ + : : "r" (val), "r" ((volatile type *)va) \ + : "memory"); \ + }) + +#ifdef __OPTIMIZE__ +#define ST_GENERIC(va, asi, val, op, type) (__builtin_constant_p(asi) ? \ + STC_GEN((va), (asi), (val), op, op ## a, type) : \ + op ## a_nc((va), asi, (val))) +#else /* __OPTIMIZE__ */ +#define ST_GENERIC(va, asi, val, op, type) (op ## a_nc((va), asi, (val))) +#endif /* __OPTIMIZE__ */ + +#define stba(va, asi, val) ST_GENERIC(va, asi, val, stb, u_int8_t) +#define stha(va, asi, val) ST_GENERIC(va, asi, val, sth, u_int16_t) +#define stwa(va, asi, val) ST_GENERIC(va, asi, val, stw, u_int32_t) +#define stxa(va, asi, val) ST_GENERIC(va, asi, val, stx, u_int64_t) + + +static inline void asi_set(int); +static inline void +asi_set(int asi) +{ + sparc_wr(asi, asi, 0); +} + +static inline u_int8_t asi_get(void); +static inline u_int8_t +asi_get(void) +{ + return sparc_rd(asi); +} + +/* flush address from instruction cache */ +static inline void flush(void *); +static inline void +flush(void *p) +{ + __asm volatile("flush %0" + : : "r" (p) + : "memory"); +} + +/* Read 64-bit %tick and %sys_tick registers. */ +#define tick() (sparc_rdpr(tick) & TICK_TICKS) +#define sys_tick() (sparc_rd(sys_tick) & TICK_TICKS) +extern u_int64_t stick(void); + +extern void tick_enable(void); +extern void sys_tick_enable(void); + +extern void tickcmpr_set(u_int64_t); +extern void sys_tickcmpr_set(u_int64_t); +extern void stickcmpr_set(u_int64_t); + +#endif /* _LOCORE */ +#endif /* _SPARC64_CTLREG_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/db_machdep.h b/lib/libc/include/sparc64-openbsd-none/sparc64/db_machdep.h new file mode 100644 index 000000000000..9edef3be5342 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/db_machdep.h @@ -0,0 +1,145 @@ +/* $OpenBSD: db_machdep.h,v 1.23 2022/10/21 18:55:42 miod Exp $ */ +/* $NetBSD: db_machdep.h,v 1.12 2001/07/07 15:16:13 eeh Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#ifndef _MACHINE_DB_MACHDEP_H_ +#define _MACHINE_DB_MACHDEP_H_ + +/* + * Machine-dependent defines for new kernel debugger. + */ + +#include + +#include +#include +#include +#include + +/* end of mangling */ + +typedef long db_expr_t; /* expression - signed */ + +struct trapstate { + int64_t tstate; + int64_t tpc; + int64_t tnpc; + int64_t tt; +}; +#if 1 +typedef struct { + struct trapframe ddb_tf; + struct frame ddb_fr; + struct trapstate ddb_ts[5]; + int ddb_tl; + struct fpstate ddb_fpstate; +} db_regs_t; +#else +typedef struct db_regs { + struct trapregs dbr_traps[4]; + int dbr_y; + char dbr_tl; + char dbr_canrestore; + char dbr_cansave; + char dbr_cleanwin; + char dbr_cwp; + char dbr_wstate; + int64_t dbr_g[8]; + int64_t dbr_ag[8]; + int64_t dbr_ig[8]; + int64_t dbr_mg[8]; + int64_t dbr_out[8]; + int64_t dbr_local[8]; + int64_t dbr_in[8]; +} db_regs_t; +#endif + +extern db_regs_t ddb_regs; /* register state */ +#define DDB_TF (&ddb_regs.ddb_tf) +#define DDB_FR (&ddb_regs.ddb_fr) +#define DDB_FP (&ddb_regs.ddb_fpstate) + +#define PC_REGS(regs) ((vaddr_t)(regs)->ddb_tf.tf_pc) +#define SET_PC_REGS(regs, value) (regs)->ddb_tf.tf_pc = (int32_t)(value) +#define PC_ADVANCE(regs) do { \ + vaddr_t n = (regs)->ddb_tf.tf_npc; \ + (regs)->ddb_tf.tf_pc = n; \ + (regs)->ddb_tf.tf_npc = n + 4; \ +} while(0) + +#define BKPT_INST 0x91d02001 /* breakpoint instruction */ +#define BKPT_SIZE (4) /* size of breakpoint inst */ +#define BKPT_SET(inst) (BKPT_INST) + +#define IS_BREAKPOINT_TRAP(type, code) \ + ((type) == T_BREAKPOINT || (type) == T_KGDB_EXEC) +#define IS_WATCHPOINT_TRAP(type, code) \ + ((type) ==T_PA_WATCHPT || (type) == T_VA_WATCHPT) + +/* + * Sparc cpus have no hardware single-step. + */ +#define SOFTWARE_SSTEP + +int db_inst_trap_return(int inst); +int db_inst_return(int inst); +int db_inst_call(int inst); +int db_inst_branch(int inst); +int db_inst_unconditional_flow_transfer(int inst); +vaddr_t db_branch_taken(int inst, vaddr_t pc, db_regs_t *regs); + +#define inst_trap_return(ins) db_inst_trap_return(ins) +#define inst_return(ins) db_inst_return(ins) +#define inst_call(ins) db_inst_call(ins) +#define inst_branch(ins) db_inst_branch(ins) +#define inst_unconditional_flow_transfer(ins) \ + db_inst_unconditional_flow_transfer(ins) +#define branch_taken(ins, pc, fun, regs) \ + db_branch_taken((ins), (pc), (regs)) + +/* see note in db_interface.c about reversed breakpoint addrs */ +#define next_instr_address(pc, bd) \ + ((bd) ? (pc) : ddb_regs.ddb_tf.tf_npc) + +#define DB_MACHINE_COMMANDS + +void db_machine_init(void); +int db_ktrap(int, struct trapframe *); + +int db_enter_ddb(void); +void db_startcpu(struct cpu_info *); +void db_stopcpu(struct cpu_info *); + +#define DDB_STATE_NOT_RUNNING 0 +#define DDB_STATE_RUNNING 1 +#define DDB_STATE_EXITING 2 + +/* Register device-specific method for triggering XIRs. */ +void db_register_xir(void (*)(void *, int), void *); + +#endif /* _MACHINE_DB_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/disklabel.h b/lib/libc/include/sparc64-openbsd-none/sparc64/disklabel.h new file mode 100644 index 000000000000..5b9d93732ab6 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/disklabel.h @@ -0,0 +1,40 @@ +/* $OpenBSD: disklabel.h,v 1.5 2015/09/30 14:57:03 krw Exp $ */ + +/* + * Copyright (c) 1994 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_DISKLABEL_H_ +#define _MACHINE_DISKLABEL_H_ + +#define LABELSECTOR 0 /* sector containing label */ +#define LABELOFFSET 128 /* offset of label in sector */ +#define MAXPARTITIONS 16 /* number of partitions */ + +#endif /* _MACHINE_DISKLABEL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/elf.h b/lib/libc/include/sparc64-openbsd-none/sparc64/elf.h new file mode 100644 index 000000000000..1a69b90df3a0 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/elf.h @@ -0,0 +1,7 @@ +/* $OpenBSD: elf.h,v 1.1 2024/07/14 09:48:49 jca Exp $ */ + +/* + * This file is in the public domain. + */ + +/* Nothing for now */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/endian.h b/lib/libc/include/sparc64-openbsd-none/sparc64/endian.h new file mode 100644 index 000000000000..ed220930b5fe --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/endian.h @@ -0,0 +1,84 @@ +/* $OpenBSD: endian.h,v 1.7 2014/10/22 23:56:47 dlg Exp $ */ + +#ifndef _MACHINE_ENDIAN_H_ +#define _MACHINE_ENDIAN_H_ + +#define _BYTE_ORDER _BIG_ENDIAN + +#ifdef _KERNEL + +#define __ASI_P_L 0x88 /* == ASI_PRIMARY_LITTLE */ + +static inline __uint16_t +__mswap16(volatile const __uint16_t *m) +{ + __uint16_t v; + + __asm("lduha [%1] %2, %0 ! %3" + : "=r" (v) + : "r" (m), "n" (__ASI_P_L), "m" (*m)); + + return (v); +} + +static inline __uint32_t +__mswap32(volatile const __uint32_t *m) +{ + __uint32_t v; + + __asm("lduwa [%1] %2, %0 ! %3" + : "=r" (v) + : "r" (m), "n" (__ASI_P_L), "m" (*m)); + + return (v); +} + +static inline __uint64_t +__mswap64(volatile const __uint64_t *m) +{ + __uint64_t v; + + __asm("ldxa [%1] %2, %0 ! %3" + : "=r" (v) + : "r" (m), "n" (__ASI_P_L), "m" (*m)); + + return (v); +} + +static inline void +__swapm16(volatile __uint16_t *m, __uint16_t v) +{ + __asm("stha %1, [%2] %3 ! %0" + : "=m" (*m) + : "r" (v), "r" (m), "n" (__ASI_P_L)); +} + +static inline void +__swapm32(volatile __uint32_t *m, __uint32_t v) +{ + __asm("stwa %1, [%2] %3 ! %0" + : "=m" (*m) + : "r" (v), "r" (m), "n" (__ASI_P_L)); +} + +static inline void +__swapm64(volatile __uint64_t *m, __uint64_t v) +{ + __asm("stxa %1, [%2] %3 ! %0" + : "=m" (*m) + : "r" (v), "r" (m), "n" (__ASI_P_L)); +} + +#undef __ASI_P_L + +#define __HAVE_MD_SWAPIO + +#endif /* _KERNEL */ + +#define __STRICT_ALIGNMENT + +#ifndef __FROM_SYS__ENDIAN +#include +#endif + +#endif /* _MACHINE_ENDIAN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/exec.h b/lib/libc/include/sparc64-openbsd-none/sparc64/exec.h new file mode 100644 index 000000000000..e71ec31b247c --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/exec.h @@ -0,0 +1,99 @@ +/* $OpenBSD: exec.h,v 1.11 2017/02/08 05:09:26 guenther Exp $ */ +/* $NetBSD: elf_machdep.h,v 1.7 2001/02/11 00:18:49 eeh Exp $ */ + +#define ARCH_ELFSIZE 64 /* MD native binary size */ +#define ELF_TARG_CLASS ELFCLASS64 +#define ELF_TARG_MACH EM_SPARCV9 + +#define ELF_TARG_DATA ELFDATA2MSB + +/* The following are what is used for AT_SUN_HWCAP: */ +#define AV_SPARC_HWMUL_32x32 1 /* 32x32-bit smul/umul is efficient */ +#define AV_SPARC_HWDIV_32x32 2 /* 32x32-bit sdiv/udiv is efficient */ +#define AV_SPARC_HWFSMULD 4 /* fsmuld is efficient */ + +/* + * Here are some SPARC specific flags I can't + * find a better home for. They are used for AT_FLAGS + * and in the exec header. + */ +#define EF_SPARCV9_MM 0x3 +#define EF_SPARCV9_TSO 0x0 +#define EF_SPARCV9_PSO 0x1 +#define EF_SPARCV9_RMO 0x2 + +#define EF_SPARC_32PLUS_MASK 0xffff00 /* bits indicating V8+ type */ +#define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */ +#define EF_SPARC_EXT_MASK 0xffff00 /* bits for vendor extensions */ +#define EF_SPARC_SUN_US1 0x000200 /* UltraSPARC 1 extensions */ +#define EF_SPARC_HAL_R1 0x000400 /* HAL R1 extensions */ +#define EF_SPARC_SUN_US3 0x000800 /* UltraSPARC 3 extensions */ + +/* Relocation types */ +#define R_SPARC_NONE 0 +#define R_SPARC_8 1 +#define R_SPARC_16 2 +#define R_SPARC_32 3 +#define R_SPARC_DISP8 4 +#define R_SPARC_DISP16 5 +#define R_SPARC_DISP32 6 +#define R_SPARC_WDISP30 7 +#define R_SPARC_WDISP22 8 +#define R_SPARC_HI22 9 +#define R_SPARC_22 10 +#define R_SPARC_13 11 +#define R_SPARC_LO10 12 +#define R_SPARC_GOT10 13 +#define R_SPARC_GOT13 14 +#define R_SPARC_GOT22 15 +#define R_SPARC_PC10 16 +#define R_SPARC_PC22 17 +#define R_SPARC_WPLT30 18 +#define R_SPARC_COPY 19 +#define R_SPARC_GLOB_DAT 20 +#define R_SPARC_JMP_SLOT 21 +#define R_SPARC_RELATIVE 22 +#define R_SPARC_UA32 23 +#define R_SPARC_PLT32 24 +#define R_SPARC_HIPLT22 25 +#define R_SPARC_LOPLT10 26 +#define R_SPARC_PCPLT32 27 +#define R_SPARC_PCPLT22 28 +#define R_SPARC_PCPLT10 29 +#define R_SPARC_10 30 +#define R_SPARC_11 31 +#define R_SPARC_64 32 +#define R_SPARC_OLO10 33 +#define R_SPARC_HH22 34 +#define R_SPARC_HM10 35 +#define R_SPARC_LM22 36 +#define R_SPARC_PC_HH22 37 +#define R_SPARC_PC_HM10 38 +#define R_SPARC_PC_LM22 39 +#define R_SPARC_WDISP16 40 +#define R_SPARC_WDISP19 41 +#define R_SPARC_GLOB_JMP 42 +#define R_SPARC_7 43 +#define R_SPARC_5 44 +#define R_SPARC_6 45 +#define R_SPARC_DISP64 46 +#define R_SPARC_PLT64 47 +#define R_SPARC_HIX22 48 +#define R_SPARC_LOX10 49 +#define R_SPARC_H44 50 +#define R_SPARC_M44 51 +#define R_SPARC_L44 52 +#define R_SPARC_REGISTER 53 +#define R_SPARC_UA64 54 +#define R_SPARC_UA16 55 +#define R_SPARC_TLS_DTPMOD32 74 +#define R_SPARC_TLS_DTPMOD64 75 +#define R_SPARC_TLS_DTPOFF32 76 +#define R_SPARC_TLS_DTPOFF64 77 +#define R_SPARC_TLS_TPOFF32 78 +#define R_SPARC_TLS_TPOFF64 79 + + +#define R_TYPE(name) __CONCAT(R_SPARC_,name) + +#define __LDPGSZ 8192 /* linker page size */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/fbvar.h b/lib/libc/include/sparc64-openbsd-none/sparc64/fbvar.h new file mode 100644 index 000000000000..6815f314900a --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/fbvar.h @@ -0,0 +1,80 @@ +/* $OpenBSD: fbvar.h,v 1.8 2008/12/29 22:07:35 miod Exp $ */ +/* $NetBSD: fbvar.h,v 1.9 1997/07/07 23:31:30 pk Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)fbvar.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * Common frame buffer variables. + * All framebuffer softc structures must start with such a structure. + */ +struct sunfb { + struct device sf_dev; /* base device */ + + int sf_width; + int sf_height; + int sf_depth; + int sf_linebytes; + + int sf_fbsize; /* sf_height * sf_linebytes */ + + int *sf_crowp, *sf_ccolp; /* PROM cursor position */ + + struct rasops_info sf_ro; + + struct wsscreen_descr sf_wsd; + struct wsscreen_list sf_wsl; + struct wsscreen_descr *sf_scrlist[1]; + int sf_nscreens; +}; + +/* + * Selected framebuffer node on OBP systems if k/d console. + */ +extern int fbnode; + +void fb_setsize(struct sunfb*, int, int, int, int, int); +void fbwscons_init(struct sunfb *, int, int); +void fbwscons_console_init(struct sunfb *, int); +void fbwscons_setcolormap(struct sunfb *, + void (*)(void *, u_int, u_int8_t, u_int8_t, u_int8_t)); +void fbwscons_attach(struct sunfb *, struct wsdisplay_accessops *, int); + +int ifb_ident(void *); \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/fenv.h b/lib/libc/include/sparc64-openbsd-none/sparc64/fenv.h new file mode 100644 index 000000000000..9fb328fd32df --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/fenv.h @@ -0,0 +1,108 @@ +/* $OpenBSD: fenv.h,v 1.4 2011/05/25 21:46:49 martynas Exp $ */ +/* $NetBSD: fenv.h,v 1.1.2.2 2011/02/08 16:19:41 bouyer Exp $ */ + +/*- + * Copyright (c) 2004-2005 David Schultz + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SPARC64_FENV_H_ +#define _SPARC64_FENV_H_ + +/* + * Each symbol representing a floating point exception expands to an integer + * constant expression with values, such that bitwise-inclusive ORs of _all + * combinations_ of the constants result in distinct values. + * + * We use such values that allow direct bitwise operations on FPU registers. + */ +#define FE_INEXACT 0x020 +#define FE_DIVBYZERO 0x040 +#define FE_UNDERFLOW 0x080 +#define FE_OVERFLOW 0x100 +#define FE_INVALID 0x200 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * exception constants defined above. + */ +#define FE_ALL_EXCEPT (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | \ + FE_OVERFLOW | FE_INVALID) +#define _MASK_SHIFT 18 + +/* + * Each symbol representing the rounding direction, expands to an integer + * constant expression whose value is distinct non-negative value. + * + * We use such values that allow direct bitwise operations on FPU registers. + */ +#define FE_TONEAREST 0x0 +#define FE_TOWARDZERO 0x1 +#define FE_UPWARD 0x2 +#define FE_DOWNWARD 0x3 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * rounding direction constants defined above. + */ +#define _ROUND_MASK (FE_TONEAREST | FE_TOWARDZERO | FE_UPWARD | \ + FE_DOWNWARD) +#define _ROUND_SHIFT 30 + +/* + * fenv_t represents the entire floating-point environment. + */ +typedef unsigned long fenv_t; + +/* + * The following constant represents the default floating-point environment + * (that is, the one installed at program startup) and has type pointer to + * const-qualified fenv_t. + * + * It can be used as an argument to the functions within the header + * that manage the floating-point environment, namely fesetenv() and + * feupdateenv(). + */ +__BEGIN_DECLS +extern fenv_t __fe_dfl_env; +__END_DECLS +#define FE_DFL_ENV ((const fenv_t *)&__fe_dfl_env) + +/* + * fexcept_t represents the floating-point status flags collectively, including + * any status the implementation associates with the flags. + * + * A floating-point status flag is a system variable whose value is set (but + * never cleared) when a floating-point exception is raised, which occurs as a + * side effect of exceptional floating-point arithmetic to provide auxiliary + * information. + * + * A floating-point control mode is a system variable whose value may be set by + * the user to affect the subsequent behavior of floating-point arithmetic. + */ +typedef unsigned long fexcept_t; + +#endif /* !_SPARC64_FENV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/frame.h b/lib/libc/include/sparc64-openbsd-none/sparc64/frame.h new file mode 100644 index 000000000000..4b077a0ce660 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/frame.h @@ -0,0 +1,105 @@ +/* $OpenBSD: frame.h,v 1.11 2024/04/08 20:07:53 miod Exp $ */ +/* $NetBSD: frame.h,v 1.9 2001/03/04 09:28:35 mrg Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)frame.h 8.1 (Berkeley) 6/11/93 + */ + +#ifndef _MACHINE_FRAME_H_ +#define _MACHINE_FRAME_H_ + +/* + * CC64FSZ (C Compiler 64-bit Frame SiZe) is the size of a stack frame used + * by the compiler in 64-bit mode. It is (16)*8; space for 8 ins, 8 outs. + */ +#define CC64FSZ 176 + +/* + * v9 stacks all have a bias of 2047 added to the %sp and %fp, so you can easily + * detect it by testing the register for an odd value. Why 2K-1 I don't know. + */ +#define BIAS (2048-1) + +#if defined(_KERNEL) && !defined(_LOCORE) + +/* + * Sparc v9 stack frame format. + * + * Note that the contents of each stack frame may be held only in + * machine register windows. In order to get an accurate picture + * of the frame, you must first force the kernel to write any such + * windows to the stack. + * + * V9 frames have an odd bias, so you can tell a v9 frame from + * a v8 frame by testing the stack pointer's lsb. + */ +struct frame { + int64_t fr_local[8]; /* space to save locals (%l0..%l7) */ + int64_t fr_arg[6]; /* space to save arguments (%i0..%i5) */ + u_int64_t fr_fp; /* space to save frame pointer (%i6) */ + u_int64_t fr_pc; /* space to save return pc (%i7) */ + /* + * SVR4 reserves a bunch of extra stuff. + */ + int64_t fr_argd[6]; /* `register save area' (lunacy) */ + int64_t fr_argx[0]; /* arg extension (args 7..n; variable size) */ +}; + +#define v9next_frame(f) ((struct frame*)(f->fr_fp+BIAS)) + +/* + * The v9 trapframe. + */ +struct trapframe { + int64_t tf_tstate; /* tstate register */ + int64_t tf_pc; /* return pc */ + int64_t tf_npc; /* return npc */ + int tf_y; /* %y register -- 32-bits */ + short tf_tt; /* What type of trap this was */ + char tf_pil; /* What IRQ we're handling */ + char tf_oldpil; /* What our old SPL was */ + int64_t tf_global[8]; /* global registers in trap's caller */ + int64_t tf_out[8]; /* output registers in trap's caller */ + int64_t tf_local[8]; /* local registers in trap's caller */ + int64_t tf_in[8]; /* in registers in trap's caller (for debug) */ +}; + +#endif /* _KERNEL && !_LOCORE */ + +#endif /* _MACHINE_FRAME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/fsr.h b/lib/libc/include/sparc64-openbsd-none/sparc64/fsr.h new file mode 100644 index 000000000000..d6689e55f9fe --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/fsr.h @@ -0,0 +1,132 @@ +/* $OpenBSD: fsr.h,v 1.2 2003/06/02 23:27:56 millert Exp $ */ +/* $NetBSD: fsr.h,v 1.1.1.1 1998/06/20 04:58:51 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)fsr.h 8.1 (Berkeley) 6/11/93 + */ + +#ifndef _MACHINE_FSR_H_ +#define _MACHINE_FSR_H_ + +/* + * Bits in FPRS + */ +#define FPRS_FEF 0x04 /* Enable FP -- must be set to enable FP regs */ +#define FPRS_DU 0x02 /* Dirty upper -- upper fp regs are dirty */ +#define FPRS_DL 0x01 /* Dirty lower -- lower fp regs are dirty */ + +/* + * Bits in FSR. + */ + +#define FSR_RD 0xc0000000 /* rounding direction */ +#define FSR_RD_RN 0 /* round to nearest */ +#define FSR_RD_RZ 1 /* round towards 0 */ +#define FSR_RD_RP 2 /* round towards +inf */ +#define FSR_RD_RM 3 /* round towards -inf */ +#define FSR_RD_SHIFT 30 +#define FSR_RD_MASK 0x03 + +#define FSR_RP 0x30000000 /* extended rounding precision */ +#define FSR_RP_X 0 /* extended stays extended */ +#define FSR_RP_S 1 /* extended => single */ +#define FSR_RP_D 2 /* extended => double */ +#define FSR_RP_80 3 /* extended => 80-bit */ +#define FSR_RP_SHIFT 28 +#define FSR_RP_MASK 0x03 + +#define FSR_TEM 0x0f800000 /* trap enable mask */ +#define FSR_TEM_SHIFT 23 +#define FSR_TEM_MASK 0x1f + +#define FSR_NS 0x00400000 /* ``nonstandard mode'' */ +#define FSR_AU 0x00400000 /* aka abrupt underflow mode */ +#define FSR_MBZ 0x00300000 /* reserved; must be zero */ + +#define FSR_VER 0x000e0000 /* version bits */ +#define FSR_VER_SHIFT 17 +#define FSR_VER_MASK 0x07 + +#define FSR_FTT 0x0001c000 /* FP trap type */ +#define FSR_TT_NONE 0 /* no trap */ +#define FSR_TT_IEEE 1 /* IEEE exception */ +#define FSR_TT_UNFIN 2 /* unfinished operation */ +#define FSR_TT_UNIMP 3 /* unimplemented operation */ +#define FSR_TT_SEQ 4 /* sequence error */ +#define FSR_TT_HWERR 5 /* hardware error (unrecoverable) */ +#define FSR_FTT_SHIFT 14 +#define FSR_FTT_MASK 0x03 + +#define FSR_QNE 0x00002000 /* queue not empty */ +#define FSR_PR 0x00001000 /* partial result */ + +#define FSR_FCC 0x00000c00 /* FP condition codes */ +#define FSR_CC_EQ 0 /* f1 = f2 */ +#define FSR_CC_LT 1 /* f1 < f2 */ +#define FSR_CC_GT 2 /* f1 > f2 */ +#define FSR_CC_UO 3 /* (f1,f2) unordered */ +#define FSR_FCC_SHIFT 10 +#define FSR_FCC_MASK 0x03 + +#define FSR_AX 0x000003e0 /* accrued exceptions */ +#define FSR_AX_SHIFT 5 +#define FSR_AX_MASK 0x1f +#define FSR_CX 0x0000001f /* current exceptions */ +#define FSR_CX_SHIFT 0 +#define FSR_CX_MASK 0x1f + +/* These are the 3 new v9 fcc's */ +#define FSR_FCC3 0x06000000000 /* FP condition codes */ +#define FSR_FCC3_SHIFT 36 + +#define FSR_FCC2 0x0c00000000 /* FP condition codes */ +#define FSR_FCC2_SHIFT 34 + +#define FSR_FCC1 0x0600000000 /* FP condition codes */ +#define FSR_FCC1_SHIFT 32 + + +/* The following exceptions apply to TEM, AX, and CX. */ +#define FSR_NV 0x10 /* invalid operand */ +#define FSR_OF 0x08 /* overflow */ +#define FSR_UF 0x04 /* underflow */ +#define FSR_DZ 0x02 /* division by zero */ +#define FSR_NX 0x01 /* inexact result */ + +#endif /* _MACHINE_FSR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/hypervisor.h b/lib/libc/include/sparc64-openbsd-none/sparc64/hypervisor.h new file mode 100644 index 000000000000..c8d8cc48dcdb --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/hypervisor.h @@ -0,0 +1,348 @@ +/* $OpenBSD: hypervisor.h,v 1.21 2024/04/08 20:00:27 miod Exp $ */ + +/* + * Copyright (c) 2008 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * UltraSPARC Hypervisor API. + */ + +/* + * API versioning + */ + +int64_t hv_api_get_version(uint64_t api_group, + uint64_t *major_number, uint64_t *minor_number); + +/* + * Domain services + */ + +int64_t hv_mach_desc(paddr_t buffer, psize_t *length); +int64_t hv_mach_pri(paddr_t buffer, psize_t *length); + +/* + * CPU services + */ + +void hv_cpu_yield(void); +int64_t hv_cpu_qconf(uint64_t queue, uint64_t base, uint64_t nentries); + +#define CPU_MONDO_QUEUE 0x3c +#define DEVICE_MONDO_QUEUE 0x3d +#define RESUMABLE_ERROR_QUEUE 0x3e +#define NONRESUMABLE_ERROR_QUEUE 0x3f + +int64_t hv_cpu_mondo_send(uint64_t ncpus, paddr_t cpulist, paddr_t data); +int64_t hv_cpu_myid(uint64_t *cpuid); + +/* + * MMU services + */ + +int64_t hv_mmu_demap_page(vaddr_t vaddr, uint64_t context, uint64_t flags); +int64_t hv_mmu_demap_ctx(uint64_t context, uint64_t flags); +int64_t hv_mmu_map_perm_addr(vaddr_t vaddr, uint64_t tte, uint64_t flags); +int64_t hv_mmu_unmap_perm_addr(vaddr_t vaddr, uint64_t flags); +int64_t hv_mmu_map_addr(vaddr_t vaddr, uint64_t context, uint64_t tte, + uint64_t flags); +int64_t hv_mmu_unmap_addr(vaddr_t vaddr, uint64_t context, uint64_t flags); + +#define MAP_DTLB 0x1 +#define MAP_ITLB 0x2 + +struct tsb_desc { + uint16_t td_idxpgsz; + uint16_t td_assoc; + uint32_t td_size; + uint32_t td_ctxidx; + uint32_t td_pgsz; + paddr_t td_pa; + uint64_t td_reserved; +}; + +int64_t hv_mmu_tsb_ctx0(uint64_t ntsb, paddr_t tsbptr); +int64_t hv_mmu_tsb_ctxnon0(uint64_t ntsb, paddr_t tsbptr); + +/* + * Cache and memory services + */ + +int64_t hv_mem_scrub(paddr_t raddr, psize_t length); +int64_t hv_mem_sync(paddr_t raddr, psize_t length); + +/* + * Device interrupt services + */ + +int64_t hv_intr_devino_to_sysino(uint64_t devhandle, uint64_t devino, + uint64_t *sysino); +int64_t hv_intr_getenabled(uint64_t sysino, uint64_t *intr_enabled); +int64_t hv_intr_setenabled(uint64_t sysino, uint64_t intr_enabled); +int64_t hv_intr_getstate(uint64_t sysino, uint64_t *intr_state); +int64_t hv_intr_setstate(uint64_t sysino, uint64_t intr_state); +int64_t hv_intr_gettarget(uint64_t sysino, uint64_t *cpuid); +int64_t hv_intr_settarget(uint64_t sysino, uint64_t cpuid); + +#define INTR_DISABLED 0 +#define INTR_ENABLED 1 + +#define INTR_IDLE 0 +#define INTR_RECEIVED 1 +#define INTR_DELIVERED 2 + +int64_t hv_vintr_getcookie(uint64_t devhandle, uint64_t devino, + uint64_t *cookie_value); +int64_t hv_vintr_setcookie(uint64_t devhandle, uint64_t devino, + uint64_t cookie_value); +int64_t hv_vintr_getenabled(uint64_t devhandle, uint64_t devino, + uint64_t *intr_enabled); +int64_t hv_vintr_setenabled(uint64_t devhandle, uint64_t devino, + uint64_t intr_enabled); +int64_t hv_vintr_getstate(uint64_t devhandle, uint64_t devino, + uint64_t *intr_state); +int64_t hv_vintr_setstate(uint64_t devhandle, uint64_t devino, + uint64_t intr_state); +int64_t hv_vintr_gettarget(uint64_t devhandle, uint64_t devino, + uint64_t *cpuid); +int64_t hv_vintr_settarget(uint64_t devhandle, uint64_t devino, + uint64_t cpuid); + +/* + * Time of day services + */ + +int64_t hv_tod_get(uint64_t *tod); +int64_t hv_tod_set(uint64_t tod); + +/* + * Console services + */ + +int64_t hv_cons_getchar(int64_t *ch); +int64_t hv_cons_putchar(int64_t ch); +int64_t hv_api_putchar(int64_t ch); + +#define CONS_BREAK -1 +#define CONS_HUP -2 + +/* + * Domain state services + */ + +int64_t hv_soft_state_set(uint64_t software_state, + paddr_t software_description_ptr); + +#define SIS_NORMAL 0x1 +#define SIS_TRANSITION 0x2 + +/* + * PCI I/O services + */ + +int64_t hv_pci_iommu_map(uint64_t devhandle, uint64_t tsbid, + uint64_t nttes, uint64_t io_attributes, paddr_t io_page_list_p, + uint64_t *nttes_mapped); +int64_t hv_pci_iommu_demap(uint64_t devhandle, uint64_t tsbid, + uint64_t nttes, uint64_t *nttes_demapped); +int64_t hv_pci_iommu_getmap(uint64_t devhandle, uint64_t tsbid, + uint64_t *io_attributes, paddr_t *r_addr); +int64_t hv_pci_iommu_getbypass(uint64_t devhandle, paddr_t r_addr, + uint64_t io_attributes, uint64_t *io_addr); + +int64_t hv_pci_config_get(uint64_t devhandle, uint64_t pci_device, + uint64_t pci_config_offset, uint64_t size, + uint64_t *error_flag, uint64_t *data); +int64_t hv_pci_config_put(uint64_t devhandle, uint64_t pci_device, + uint64_t pci_config_offset, uint64_t size, uint64_t data, + uint64_t *error_flag); + +#define PCI_MAP_ATTR_READ 0x01 /* From memory */ +#define PCI_MAP_ATTR_WRITE 0x02 /* To memory */ + +/* + * PCI MSI services + */ + +int64_t hv_pci_msiq_conf(uint64_t devhandle, uint64_t msiqid, + uint64_t r_addr, uint64_t nentries); +int64_t hv_pci_msiq_info(uint64_t devhandle, uint64_t msiqid, + uint64_t *r_addr, uint64_t *nentries); + +int64_t hv_pci_msiq_getvalid(uint64_t devhandle, uint64_t msiqid, + uint64_t *msiqvalid); +int64_t hv_pci_msiq_setvalid(uint64_t devhandle, uint64_t msiqid, + uint64_t msiqvalid); + +#define PCI_MSIQ_INVALID 0 +#define PCI_MSIQ_VALID 1 + +int64_t hv_pci_msiq_getstate(uint64_t devhandle, uint64_t msiqid, + uint64_t *msiqstate); +int64_t hv_pci_msiq_setstate(uint64_t devhandle, uint64_t msiqid, + uint64_t msiqstate); + +#define PCI_MSIQSTATE_IDLE 0 +#define PCI_MSIQSTATE_ERROR 1 + +int64_t hv_pci_msiq_gethead(uint64_t devhandle, uint64_t msiqid, + uint64_t *msiqhead); +int64_t hv_pci_msiq_sethead(uint64_t devhandle, uint64_t msiqid, + uint64_t msiqhead); +int64_t hv_pci_msiq_gettail(uint64_t devhandle, uint64_t msiqid, + uint64_t *msiqtail); + +int64_t hv_pci_msi_getvalid(uint64_t devhandle, uint64_t msinum, + uint64_t *msivalidstate); +int64_t hv_pci_msi_setvalid(uint64_t devhandle, uint64_t msinum, + uint64_t msivalidstate); + +#define PCI_MSI_INVALID 0 +#define PCI_MSI_VALID 1 + +int64_t hv_pci_msi_getmsiq(uint64_t devhandle, uint64_t msinum, + uint64_t *msiqid); +int64_t hv_pci_msi_setmsiq(uint64_t devhandle, uint64_t msinum, + uint64_t msitype, uint64_t msiqid); + +int64_t hv_pci_msi_getstate(uint64_t devhandle, uint64_t msinum, + uint64_t *msistate); +int64_t hv_pci_msi_setstate(uint64_t devhandle, uint64_t msinum, + uint64_t msistate); + +#define PCI_MSISTATE_IDLE 0 +#define PCI_MSISTATE_DELIVERED 1 + +int64_t hv_pci_msg_getmsiq(uint64_t devhandle, uint64_t msg, + uint64_t *msiqid); +int64_t hv_pci_msg_setmsiq(uint64_t devhandle, uint64_t msg, + uint64_t msiqid); + +int64_t hv_pci_msg_getvalid(uint64_t devhandle, uint64_t msg, + uint64_t *msgvalidstate); +int64_t hv_pci_msg_setvalid(uint64_t devhandle, uint64_t msg, + uint64_t msgvalidstate); + +#define PCIE_MSG_INVALID 0 +#define PCIE_MSG_VALID 1 + +#define PCIE_PME_MSG 0x18 +#define PCIE_PME_ACK_MSG 0x1b +#define PCIE_CORR_MSG 0x30 +#define PCIE_NONFATAL_MSG 0x31 +#define PCIE_FATAL_MSG 0x32 + +/* + * Logical Domain Channel services + */ + +int64_t hv_ldc_tx_qconf(uint64_t ldc_id, paddr_t base_raddr, + uint64_t nentries); +int64_t hv_ldc_tx_qinfo(uint64_t ldc_id, paddr_t *base_raddr, + uint64_t *nentries); +int64_t hv_ldc_tx_get_state(uint64_t ldc_id, uint64_t *head_offset, + uint64_t *tail_offset, uint64_t *channel_state); +int64_t hv_ldc_tx_set_qtail(uint64_t ldc_id, uint64_t tail_offset); +int64_t hv_ldc_rx_qconf(uint64_t ldc_id, paddr_t base_raddr, + uint64_t nentries); +int64_t hv_ldc_rx_qinfo(uint64_t ldc_id, paddr_t *base_raddr, + uint64_t *nentries); +int64_t hv_ldc_rx_get_state(uint64_t ldc_id, uint64_t *head_offset, + uint64_t *tail_offset, uint64_t *channel_state); +int64_t hv_ldc_rx_set_qhead(uint64_t ldc_id, uint64_t head_offset); + +#define LDC_CHANNEL_DOWN 0 +#define LDC_CHANNEL_UP 1 +#define LDC_CHANNEL_RESET 2 + +/* Used by drivers only, not part of the hypervisor API. */ +#define LDC_CHANNEL_INIT ((uint64_t)-1) + +int64_t hv_ldc_set_map_table(uint64_t ldc_id, paddr_t base_raddr, + uint64_t nentries); +int64_t hv_ldc_get_map_table(uint64_t ldc_id, paddr_t *base_raddr, + uint64_t *nentries); +int64_t hv_ldc_copy(uint64_t ldc_id, uint64_t flags, uint64_t cookie, + paddr_t raddr, psize_t length, psize_t *ret_length); + +#define LDC_COPY_IN 0 +#define LDC_COPY_OUT 1 + +int64_t hv_ldc_mapin(uint64_t ldc_id, uint64_t cookie, paddr_t *raddr, + uint64_t *perms); +int64_t hv_ldc_unmap(paddr_t raddr, uint64_t *perms); + +/* + * Static Direct I/O services + */ + +int64_t hv_pci_iov_root_configured(uint64_t devhandle); +int64_t hv_pci_real_config_get(uint64_t devhandle, uint64_t pci_device, + uint64_t pci_config_offset, uint64_t size, + uint64_t *error_flag, uint64_t *data); +int64_t hv_pci_real_config_put(uint64_t devhandle, uint64_t pci_device, + uint64_t pci_config_offset, uint64_t size, uint64_t data, + uint64_t *error_flag); +int64_t hv_pci_error_send(uint64_t devhandle, uint64_t devino, + uint64_t pci_device); + +/* + * Cryptographic services + */ + +int64_t hv_rng_get_diag_control(void); +int64_t hv_rng_ctl_read(paddr_t raddr, uint64_t *state, uint64_t *delta); +int64_t hv_rng_ctl_write(paddr_t raddr, uint64_t state, uint64_t timeout, + uint64_t *delta); + +#define RNG_STATE_UNCONFIGURED 0 +#define RNG_STATE_CONFIGURED 1 +#define RNG_STATE_HEALTHCHECK 2 +#define RNG_STATE_ERROR 3 + +int64_t hv_rng_data_read_diag(paddr_t raddr, uint64_t size, uint64_t *delta); +int64_t hv_rng_data_read(paddr_t raddr, uint64_t *delta); + +/* + * Error codes + */ + +#define H_EOK 0 +#define H_ENOCPU 1 +#define H_ENORADDR 2 +#define H_ENOINTR 3 +#define H_EBADPGSZ 4 +#define H_EBADTSB 5 +#define H_EINVAL 6 +#define H_EBADTRAP 7 +#define H_EBADALIGN 8 +#define H_EWOULDBLOCK 9 +#define H_ENOACCESS 10 +#define H_EIO 11 +#define H_ECPUERROR 12 +#define H_ENOTSUPPORTED 13 +#define H_ENOMAP 14 +#define H_ETOOMANY 15 +#define H_ECHANNEL 16 + +extern uint64_t sun4v_group_interrupt_major; +extern uint64_t sun4v_group_sdio_major; + +int64_t sun4v_intr_devino_to_sysino(uint64_t, uint64_t, uint64_t *); +int64_t sun4v_intr_setcookie(uint64_t, uint64_t, uint64_t); +int64_t sun4v_intr_setenabled(uint64_t, uint64_t, uint64_t); +int64_t sun4v_intr_setstate(uint64_t, uint64_t, uint64_t); +int64_t sun4v_intr_settarget(uint64_t, uint64_t, uint64_t); \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/idprom.h b/lib/libc/include/sparc64-openbsd-none/sparc64/idprom.h new file mode 100644 index 000000000000..0332fc8f2ef7 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/idprom.h @@ -0,0 +1,52 @@ +/* $OpenBSD: idprom.h,v 1.3 2024/03/29 21:06:14 miod Exp $ */ +/* $NetBSD: idprom.h,v 1.2 1998/09/05 23:57:26 eeh Exp $ */ + +/* + * Copyright (c) 1993 Adam Glass + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Adam Glass. + * 4. The name of the Author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Adam Glass ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * ID prom format. The ``host id'' is set up by taking the machine + * ID as the top byte and the hostid field as the remaining three. + * The id_xxx0 field appears to contain some other number. The id_xxx1 + * contains a bunch of 00's and a5's on my machines, suggesting it is + * not actually used. The checksum seems to include them, however. + */ +struct idprom { + u_char id_format; /* format identifier (= 1) */ + u_char id_machine; /* machine type (see param.h) */ + u_char id_ether[6]; /* ethernet address */ + int id_date; /* date of manufacture */ + u_char id_hostid[3]; /* ``host id'' bytes */ + u_char id_checksum; /* xor of everything else */ + char id_undef[16]; /* undefined */ +}; + +#define IDPROM_VERSION 1 \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/ieee.h b/lib/libc/include/sparc64-openbsd-none/sparc64/ieee.h new file mode 100644 index 000000000000..9d22c7a0de76 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/ieee.h @@ -0,0 +1,148 @@ +/* $OpenBSD: ieee.h,v 1.4 2017/04/16 14:20:49 kettenis Exp $ */ +/* $NetBSD: ieee.h,v 1.1.1.1 1998/06/20 04:58:51 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ieee.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * ieee.h defines the machine-dependent layout of the machine's IEEE + * floating point. It does *not* define (yet?) any of the rounding + * mode bits, exceptions, and so forth. + */ + +/* + * Define the number of bits in each fraction and exponent. + * + * k k+1 + * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented + * + * (-exp_bias+1) + * as fractions that look like 0.fffff x 2 . This means that + * + * -126 + * the number 0.10000 x 2 , for instance, is the same as the normalized + * + * -127 -128 + * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero + * + * -129 + * in the fraction; to represent 2 , we need two, and so on. This + * + * (-exp_bias-fracbits+1) + * implies that the smallest denormalized number is 2 + * + * for whichever format we are talking about: for single precision, for + * + * -126 -149 + * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and + * + * -149 == -127 - 23 + 1. + */ +#define SNG_EXPBITS 8 +#define SNG_FRACBITS 23 + +#define DBL_EXPBITS 11 +#define DBL_FRACHBITS 20 +#define DBL_FRACLBITS 32 +#define DBL_FRACBITS 52 + +#define EXT_EXPBITS 15 +#define EXT_FRACHBITS 16 +#define EXT_FRACHMBITS 32 +#define EXT_FRACLMBITS 32 +#define EXT_FRACLBITS 32 +#define EXT_FRACBITS 112 + +#define EXT_IMPLICIT_NBIT + +#define EXT_TO_ARRAY32(p, a) do { \ + (a)[0] = (uint32_t)(p)->ext_fracl; \ + (a)[1] = (uint32_t)(p)->ext_fraclm; \ + (a)[2] = (uint32_t)(p)->ext_frachm; \ + (a)[3] = (uint32_t)(p)->ext_frach; \ +} while(0) + +struct ieee_single { + u_int sng_sign:1; + u_int sng_exp:8; + u_int sng_frac:23; +}; + +struct ieee_double { + u_int dbl_sign:1; + u_int dbl_exp:11; + u_int dbl_frach:20; + u_int dbl_fracl; +}; + +struct ieee_ext { + u_int ext_sign:1; + u_int ext_exp:15; + u_int ext_frach:16; + u_int ext_frachm; + u_int ext_fraclm; + u_int ext_fracl; +}; + +/* + * Floats whose exponent is in [1..INFNAN) (of whatever type) are + * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. + * Floats whose exponent is zero are either zero (iff all fraction + * bits are zero) or subnormal values. + * + * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its + * high fraction; if the bit is set, it is a `quiet NaN'. + */ +#define SNG_EXP_INFNAN 255 +#define DBL_EXP_INFNAN 2047 +#define EXT_EXP_INFNAN 32767 + +#if 0 +#define SNG_QUIETNAN (1 << 22) +#define DBL_QUIETNAN (1 << 19) +#define EXT_QUIETNAN (1 << 15) +#endif + +/* + * Exponent biases. + */ +#define SNG_EXP_BIAS 127 +#define DBL_EXP_BIAS 1023 +#define EXT_EXP_BIAS 16383 \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/ieeefp.h b/lib/libc/include/sparc64-openbsd-none/sparc64/ieeefp.h new file mode 100644 index 000000000000..0997cfae6df4 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/ieeefp.h @@ -0,0 +1,24 @@ +/* $OpenBSD: ieeefp.h,v 1.3 2011/03/23 16:54:37 pirofti Exp $ */ +/* + * Written by J.T. Conklin, Apr 6, 1995 + * Public domain. + */ + +#ifndef _MACHINE_IEEEFP_H_ +#define _MACHINE_IEEEFP_H_ + +typedef int fp_except; +#define FP_X_IMP 0x01 /* imprecise (loss of precision) */ +#define FP_X_DZ 0x02 /* divide-by-zero exception */ +#define FP_X_UFL 0x04 /* underflow exception */ +#define FP_X_OFL 0x08 /* overflow exception */ +#define FP_X_INV 0x10 /* invalid operation exception */ + +typedef enum { + FP_RN=0, /* round to nearest representable number */ + FP_RZ=1, /* round to zero (truncate) */ + FP_RP=2, /* round toward positive infinity */ + FP_RM=3 /* round toward negative infinity */ +} fp_rnd; + +#endif /* _MACHINE_IEEEFP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/instr.h b/lib/libc/include/sparc64-openbsd-none/sparc64/instr.h new file mode 100644 index 000000000000..9054144e9718 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/instr.h @@ -0,0 +1,502 @@ +/* $OpenBSD: instr.h,v 1.8 2025/07/16 07:15:42 jsg Exp $ */ +/* $NetBSD: instr.h,v 1.3 2000/01/10 03:53:20 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)instr.h 8.1 (Berkeley) 6/11/93 + */ + +/* see also Appendix F of the SPARC version 8 document */ +enum IOP { IOP_OP2, IOP_CALL, IOP_reg, IOP_mem }; +enum IOP2 { IOP2_UNIMP, IOP2_BPcc, IOP2_Bicc, IOP2_BPr, + IOP2_SETHI, IOP2_FBPfcc, IOP2_FBfcc, IOP2_CBccc }; +enum IOP3_reg { + IOP3_ADD, IOP3_AND, IOP3_OR, IOP3_XOR, + IOP3_SUB, IOP3_ANDN, IOP3_ORN, IOP3_XNOR, + IOP3_ADDX, IOP3_MULX, IOP3_UMUL, IOP3_SMUL, + IOP3_SUBX, IOP3_UDIVX, IOP3_UDIV, IOP3_SDIV, + IOP3_ADDcc, IOP3_ANDcc, IOP3_ORcc, IOP3_XORcc, + IOP3_SUBcc, IOP3_ANDNcc, IOP3_ORNcc, IOP3_XNORcc, + IOP3_ADDXcc, IOP3_rerr19, IOP3_UMULcc, IOP3_SMULcc, + IOP3_SUBXcc, IOP3_rerr1d, IOP3_UDIVcc, IOP3_SDIVcc, + IOP3_TADDcc, IOP3_TSUBcc, IOP3_TADDccTV, IOP3_TSUBccTV, + IOP3_MULScc, IOP3_SLL, IOP3_SRL, IOP3_SRA, + IOP3_RDASR_RDY_STBAR, IOP3_RDPSR, IOP3_RDWIM, IOP3_RDTGBR, + IOP3_MOVcc, IOP3_SDIVX, IOP3_POPC, IOP3_MOVr, + IOP3_WRASR_WRY, IOP3_WRPSR, IOP3_WRWIM, IOP3_WRTBR, + IOP3_FPop1, IOP3_FPop2, IOP3_CPop1, IOP3_CPop2, + IOP3_JMPL, IOP3_RETT, IOP3_Ticc, IOP3_FLUSH, + IOP3_SAVE, IOP3_RESTORE, IOP3_DONE_RETRY, IOP3_rerr3f +}; +enum IOP3_mem { + IOP3_LD, IOP3_LDUB, IOP3_LDUH, IOP3_LDD, + IOP3_ST, IOP3_STB, IOP3_STH, IOP3_STD, + IOP3_LDSW, IOP3_LDSB, IOP3_LDSH, IOP3_LDX, + IOP3_merr0c, IOP3_LDSTUB, IOP3_STX, IOP3_SWAP, + IOP3_LDA, IOP3_LDUBA, IOP3_LDUHA, IOP3_LDDA, + IOP3_STA, IOP3_STBA, IOP3_STHA, IOP3_STDA, + IOP3_LDSWA, IOP3_LDSBA, IOP3_LDSHA, IOP3_LDXA, + IOP3_merr1c, IOP3_LDSTUBA, IOP3_STXA, IOP3_SWAPA, + IOP3_LDF, IOP3_LDFSR, IOP3_LDQF, IOP3_LDDF, + IOP3_STF, IOP3_STFSR, IOP3_STQF, IOP3_STDF, + IOP3_merr28, IOP3_merr29, IOP3_merr2a, IOP3_merr2b, + IOP3_merr2c, IOP3_PREFETCH, IOP3_merr2e, IOP3_merr2f, + IOP3_LFC, IOP3_LDCSR, IOP3_LDQFA, IOP3_LDDC, + IOP3_STC, IOP3_STCSR, IOP3_STQFA, IOP3_STDC, + IOP3_merr38, IOP3_merr39, IOP3_merr3a, IOP3_merr3b, + IOP3_CASA, IOP3_PREFETCHA, IOP3_CASXA, IOP3_merr3f +}; + +/* + * Integer condition codes. + */ +#define Icc_N 0x0 /* never */ +#define Icc_E 0x1 /* equal (equiv. zero) */ +#define Icc_LE 0x2 /* less or equal */ +#define Icc_L 0x3 /* less */ +#define Icc_LEU 0x4 /* less or equal unsigned */ +#define Icc_CS 0x5 /* carry set (equiv. less unsigned) */ +#define Icc_NEG 0x6 /* negative */ +#define Icc_VS 0x7 /* overflow set */ +#define Icc_A 0x8 /* always */ +#define Icc_NE 0x9 /* not equal (equiv. not zero) */ +#define Icc_G 0xa /* greater */ +#define Icc_GE 0xb /* greater or equal */ +#define Icc_GU 0xc /* greater unsigned */ +#define Icc_CC 0xd /* carry clear (equiv. gtr or eq unsigned) */ +#define Icc_POS 0xe /* positive */ +#define Icc_VC 0xf /* overflow clear */ + +/* + * Integer registers. + */ +#define I_G0 0 +#define I_G1 1 +#define I_G2 2 +#define I_G3 3 +#define I_G4 4 +#define I_G5 5 +#define I_G6 6 +#define I_G7 7 +#define I_O0 8 +#define I_O1 9 +#define I_O2 10 +#define I_O3 11 +#define I_O4 12 +#define I_O5 13 +#define I_O6 14 +#define I_O7 15 +#define I_L0 16 +#define I_L1 17 +#define I_L2 18 +#define I_L3 19 +#define I_L4 20 +#define I_L5 21 +#define I_L6 22 +#define I_L7 23 +#define I_I0 24 +#define I_I1 25 +#define I_I2 26 +#define I_I3 27 +#define I_I4 28 +#define I_I5 29 +#define I_I6 30 +#define I_I7 31 + +/* + * An instruction. + */ +union instr { + int i_int; /* as a whole */ + + /* + * The first level of decoding is to use the top 2 bits. + * This gives us one of three `formats', which usually give + * a second level of decoding. + */ + struct { + u_int i_op:2; /* first-level decode */ + u_int :30; + } i_any; + + /* + * Format 1 instructions: CALL (undifferentiated). + */ + struct { + u_int :2; /* 01 */ + int i_disp:30; /* displacement */ + } i_call; + + /* + * Format 2 instructions (SETHI, UNIMP, and branches, plus illegal + * unused codes). + */ + struct { + u_int :2; /* 00 */ + u_int :5; + u_int i_op2:3; /* second-level decode */ + u_int :22; + } i_op2; + + /* UNIMP, SETHI */ + struct { + u_int :2; /* 00 */ + u_int i_rd:5; /* destination register */ + u_int i_op2:3; /* opcode: UNIMP or SETHI */ + u_int i_imm:22; /* immediate value */ + } i_imm22; + + /* branches: Bicc, FBfcc, CBccc */ + struct { + u_int :2; /* 00 */ + u_int i_annul:1; /* annul bit */ + u_int i_cond:4; /* condition codes */ + u_int i_op2:3; /* opcode: {Bi,FBf,CBc}cc */ + int i_disp:22; /* branch displacement */ + } i_branch; + + /* more branches: BPcc, FBPfcc */ + struct { + u_int :2; /* 00 */ + u_int i_annul:1; /* annul bit */ + u_int i_cond:4; /* condition codes */ + u_int i_op2:3; /* opcode: {BP,FBPf}cc */ + u_int i_cc:2; /* condition code selector */ + u_int i_pred:1; /* branch prediction bit */ + int i_disp:19; /* branch displacement */ + } i_branch_p; + + /* one last branch: BPr */ + struct { + u_int :2; /* 00 */ + u_int i_annul:1; /* annul bit */ + u_int :1; /* 0 */ + u_int i_rcond:4; /* register condition */ + u_int :3; /* 011 */ + int i_disphi:2; /* branch displacement, hi bits */ + u_int i_pred:1; /* branch prediction bit */ + u_int i_rs1:1; /* source register 1 */ + u_int i_displo:16; /* branch displacement, lo bits */ + } i_branch_pr; + + + /* + * Format 3 instructions (memory reference; arithmetic, logical, + * shift, and other miscellaneous operations). The second-level + * decode almost always makes use of an `rd' and `rs1', however + * (see also IOP3_reg and IOP3_mem). + * + * Beyond that, the low 14 bits may be broken up in one of three + * different ways, if at all: + * 1 bit of imm=0 + 8 bits of asi + 5 bits of rs2 [reg & mem] + * 1 bit of imm=1 + 13 bits of signed immediate [reg & mem] + * 9 bits of coprocessor `opf' opcode + 5 bits of rs2 [reg only] + */ + struct { + u_int :2; /* 10 or 11 */ + u_int i_rd:5; /* destination register */ + u_int i_op3:6; /* second-level decode */ + u_int i_rs1:5; /* source register 1 */ + u_int i_low14:14; /* varies */ + } i_op3; + + /* + * Memory forms. These set i_op=3 and use simm13 or asi layout. + * Memory references without an ASI should use 0, but the actual + * ASI field is simply ignored. + */ + struct { + u_int :2; /* 11 only */ + u_int i_rd:5; /* destination register */ + u_int i_op3:6; /* second-level decode (see IOP3_mem) */ + u_int i_rs1:5; /* source register 1 */ + u_int i_i:1; /* immediate vs asi */ + u_int i_low13:13; /* depend on i bit */ + } i_loadstore; + + /* + * Memory and register forms. + * These come in quite a variety and we do not + * attempt to break them down much. + */ + struct { + u_int :2; /* 10 or 11 */ + u_int i_rd:5; /* destination register */ + u_int i_op3:6; /* second-level decode */ + u_int i_rs1:5; /* source register 1 */ + u_int i_i:1; /* immediate bit (1) */ + int i_simm13:13; /* signed immediate */ + } i_simm13; + struct { + u_int :2; /* 10 or 11 */ + u_int i_rd:5; /* destination register */ + u_int i_op3:6; /* second-level decode */ + u_int i_rs1:5; /* source register 1 */ + u_int i_i:1; /* immediate vs asi */ + u_int i_asi:8; /* asi */ + u_int i_rs2:5; /* source register 2 */ + } i_asi; + struct { + u_int :2; /* 10 only (register, no memory) */ + u_int i_rd:5; /* destination register */ + u_int i_op3:6; /* second-level decode (see IOP3_reg) */ + u_int i_rs1:5; /* source register 1 */ + u_int i_opf:9; /* coprocessor 3rd-level decode */ + u_int i_rs2:5; /* source register 2 */ + } i_opf; + + /* + * Format 4 instructions (movcc, fmovr, fmovcc, and tcc). The + * second-level decode almost always makes use of an `rd' and either + * `rs1' or `cond'. + * + * Beyond that, the low 14 bits may be broken up in one of three + * different ways, if at all: + * 1 bit of imm=0 + 8 bits of asi + 5 bits of rs2 [reg & mem] + * 1 bit of imm=1 + 13 bits of signed immediate [reg & mem] + * 9 bits of coprocessor `opf' opcode + 5 bits of rs2 [reg only] */ + struct { + u_int :2; /* 10 */ + u_int i_rd:5; /* destination register */ + u_int i_op3:6; /* second-level decode */ + u_int i_rs1:5; /* source register 1 */ + u_int i_low14:14; /* varies */ + } i_op4; + + /* + * Move fp register on condition codes. + */ + struct { + u_int :2; /* 10 */ + u_int i_rd:5; /* destination register */ + u_int i_op3:6; /* second-level decode */ + u_int :1; + u_int i_cond:4; /* condition */ + u_int i_opf_cc:3; /* condition code register */ + u_int i_opf_low:6; /* third level decode */ + u_int i_rs2:5; /* source register */ + } i_fmovcc; + + /* + * Move fp register on integer register. + */ + struct { + u_int :2; /* 10 */ + u_int i_rd:5; /* destination register */ + u_int i_op3:6; /* second-level decode */ + u_int i_rs1:5; /* source register 1 */ + u_int :1; + u_int i_rcond:3; /* register condition */ + u_int i_opf_low:6; + u_int i_rs2:5; /* source register 2 */ + } i_fmovr; + +}; + +/* + * Internal macros for building instructions. These correspond 1-to-1 to + * the names above. Note that x << y | z == (x << y) | z. + */ +#define _I_ANY(op, b) ((op) << 30 | (b)) + +#define _I_OP2(high, op2, low) \ + _I_ANY(IOP_OP2, (high) << 25 | (op2) << 22 | (low)) +#define _I_IMM22(rd, op2, imm) \ + _I_ANY(IOP_OP2, (rd) << 25 | (op2) << 22 | (imm)) +#define _I_BRANCH(a, c, op2, disp) \ + _I_ANY(IOP_OP2, (a) << 29 | (c) << 25 | (op2) << 22 | (disp)) +#define _I_FBFCC(a, cond, disp) \ + _I_BRANCH(a, cond, IOP2_FBfcc, disp) +#define _I_CBCCC(a, cond, disp) \ + _I_BRANCH(a, cond, IOP2_CBccc, disp) + +#define _I_SIMM(simm) (1 << 13 | ((simm) & 0x1fff)) + +#define _I_OP3_GEN(form, rd, op3, rs1, low14) \ + _I_ANY(form, (rd) << 25 | (op3) << 19 | (rs1) << 14 | (low14)) +#define _I_OP3_LS_RAR(rd, op3, rs1, asi, rs2) \ + _I_OP3_GEN(IOP_mem, rd, op3, rs1, (asi) << 5 | (rs2)) +#define _I_OP3_LS_RI(rd, op3, rs1, simm13) \ + _I_OP3_GEN(IOP_mem, rd, op3, rs1, _I_SIMM(simm13)) +#define _I_OP3_LS_RR(rd, op3, rs1, rs2) \ + _I_OP3_GEN(IOP_mem, rd, op3, rs1, rs2) +#define _I_OP3_R_RAR(rd, op3, rs1, asi, rs2) \ + _I_OP3_GEN(IOP_reg, rd, op3, rs1, (asi) << 5 | (rs2)) +#define _I_OP3_R_RI(rd, op3, rs1, simm13) \ + _I_OP3_GEN(IOP_reg, rd, op3, rs1, _I_SIMM(simm13)) +#define _I_OP3_R_RR(rd, op3, rs1, rs2) \ + _I_OP3_GEN(IOP_reg, rd, op3, rs1, rs2) + +#define I_CALL(d) _I_ANY(IOP_CALL, d) +#define I_UNIMP(v) _I_IMM22(0, IOP2_UNIMP, v) +#define I_BN(a, d) _I_BRANCH(a, Icc_N, IOP2_Bicc, d) +#define I_BE(a, d) _I_BRANCH(a, Icc_E, IOP2_Bicc, d) +#define I_BZ(a, d) _I_BRANCH(a, Icc_E, IOP2_Bicc, d) +#define I_BLE(a, d) _I_BRANCH(a, Icc_LE, IOP2_Bicc, d) +#define I_BL(a, d) _I_BRANCH(a, Icc_L, IOP2_Bicc, d) +#define I_BLEU(a, d) _I_BRANCH(a, Icc_LEU, IOP2_Bicc, d) +#define I_BCS(a, d) _I_BRANCH(a, Icc_CS, IOP2_Bicc, d) +#define I_BLU(a, d) _I_BRANCH(a, Icc_CS, IOP2_Bicc, d) +#define I_BNEG(a, d) _I_BRANCH(a, Icc_NEG, IOP2_Bicc, d) +#define I_BVS(a, d) _I_BRANCH(a, Icc_VS, IOP2_Bicc, d) +#define I_BA(a, d) _I_BRANCH(a, Icc_A, IOP2_Bicc, d) +#define I_B(a, d) _I_BRANCH(a, Icc_A, IOP2_Bicc, d) +#define I_BNE(a, d) _I_BRANCH(a, Icc_NE, IOP2_Bicc, d) +#define I_BNZ(a, d) _I_BRANCH(a, Icc_NE, IOP2_Bicc, d) +#define I_BG(a, d) _I_BRANCH(a, Icc_G, IOP2_Bicc, d) +#define I_BGE(a, d) _I_BRANCH(a, Icc_GE, IOP2_Bicc, d) +#define I_BGU(a, d) _I_BRANCH(a, Icc_GU, IOP2_Bicc, d) +#define I_BCC(a, d) _I_BRANCH(a, Icc_CC, IOP2_Bicc, d) +#define I_BGEU(a, d) _I_BRANCH(a, Icc_CC, IOP2_Bicc, d) +#define I_BPOS(a, d) _I_BRANCH(a, Icc_POS, IOP2_Bicc, d) +#define I_BVC(a, d) _I_BRANCH(a, Icc_VC, IOP2_Bicc, d) +#define I_SETHI(r, v) _I_IMM22(r, 4, v) + +#define I_ORri(rd, rs1, imm) _I_OP3_R_RI(rd, IOP3_OR, rs1, imm) +#define I_ORrr(rd, rs1, rs2) _I_OP3_R_RR(rd, IOP3_OR, rs1, rs2) + +#define I_MOVi(rd, imm) _I_OP3_R_RI(rd, IOP3_OR, I_G0, imm) +#define I_MOVr(rd, rs) _I_OP3_R_RR(rd, IOP3_OR, I_G0, rs) + +#define I_RDPSR(rd) _I_OP3_R_RR(rd, IOP3_RDPSR, 0, 0) + +#define I_JMPLri(rd, rs1, imm) _I_OP3_R_RI(rd, IOP3_JMPL, rs1, imm) +#define I_JMPLrr(rd, rs1, rs2) _I_OP3_R_RR(rd, IOP3_JMPL, rs1, rs2) + +/* + * FPop values. + */ + +/* These are in FPop1 space */ +#define FMOVS 0x001 +#define FMOVD 0x002 +#define FMOVQ 0x003 +#define FNEGS 0x005 +#define FNEGD 0x006 +#define FNEGQ 0x007 +#define FABSS 0x009 +#define FABSD 0x00a +#define FABSQ 0x00b +#define FSQRTS 0x029 +#define FSQRTD 0x02a +#define FSQRTQ 0x02b +#define FADDS 0x041 +#define FADDD 0x042 +#define FADDQ 0x043 +#define FSUBS 0x045 +#define FSUBD 0x046 +#define FSUBQ 0x047 +#define FMULS 0x049 +#define FMULD 0x04a +#define FMULQ 0x04b +#define FDIVS 0x04d +#define FDIVD 0x04e +#define FDIVQ 0x04f +#define FSMULD 0x069 +#define FDMULQ 0x06e +#define FSTOX 0x081 +#define FDTOX 0x082 +#define FQTOX 0x083 +#define FXTOS 0x084 +#define FXTOD 0x088 +#define FXTOQ 0x08c +#define FITOS 0x0c4 +#define FDTOS 0x0c6 +#define FQTOS 0x0c7 +#define FITOD 0x0c8 +#define FSTOD 0x0c9 +#define FQTOD 0x0cb +#define FITOQ 0x0cc +#define FSTOQ 0x0cd +#define FDTOQ 0x0ce +#define FSTOI 0x0d1 +#define FDTOI 0x0d2 +#define FQTOI 0x0d3 + +/* These are in FPop2 space */ +#define FMVFC0S 0x001 +#define FMVFC0D 0x002 +#define FMVFC0Q 0x003 +#define FMOVZS 0x025 +#define FMOVZD 0x026 +#define FMOVZQ 0x027 +#define FMVFC1S 0x041 +#define FMVFC1D 0x042 +#define FMVFC1Q 0x043 +#define FMOVLEZS 0x045 +#define FMOVLEZD 0x046 +#define FMOVLEZQ 0x047 +#define FCMPS 0x051 +#define FCMPD 0x052 +#define FCMPQ 0x053 +#define FCMPES 0x055 +#define FCMPED 0x056 +#define FCMPEQ 0x057 +#define FMOVLZS 0x065 +#define FMOVLZD 0x066 +#define FMOVLZQ 0x067 +#define FMVFC2S 0x081 +#define FMVFC2D 0x082 +#define FMVFC2Q 0x083 +#define FMOVNZS 0x0a5 +#define FMOVNZD 0x0a6 +#define FMOVNZQ 0x0a7 +#define FMVFC3S 0x0c1 +#define FMVFC3D 0x0c2 +#define FMVFC3Q 0x0c3 +#define FMOVGZS 0x0c5 +#define FMOVGZD 0x0c6 +#define FMOVGZQ 0x0c7 +#define FMOVGEZS 0x0e5 +#define FMOVGEZD 0x0e6 +#define FMOVGEZQ 0x0e7 +#define FMVICS 0x101 +#define FMVICD 0x102 +#define FMVICQ 0x103 +#define FMVXCS 0x181 +#define FMVXCD 0x182 +#define FMVXCQ 0x183 + +/* + * FPU data types. + */ +#define FTYPE_LNG -1 /* data = 64-bit signed long integer */ +#define FTYPE_INT 0 /* data = 32-bit signed integer */ +#define FTYPE_SNG 1 /* data = 32-bit float */ +#define FTYPE_DBL 2 /* data = 64-bit double */ +#define FTYPE_EXT 3 /* data = 128-bit extended (quad-prec) */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/intr.h b/lib/libc/include/sparc64-openbsd-none/sparc64/intr.h new file mode 100644 index 000000000000..6e353965693a --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/intr.h @@ -0,0 +1,119 @@ +/* $OpenBSD: intr.h,v 1.26 2025/05/11 19:41:05 miod Exp $ */ +/* $NetBSD: intr.h,v 1.8 2001/01/14 23:50:30 thorpej Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_INTR_H_ +#define _MACHINE_INTR_H_ + +#include + +#include + +/* + * Interrupt handler chains. Interrupt handlers should return 0 for + * ``not me'' or 1 (``I took care of it''). intr_establish() inserts a + * handler into the list. The handler is called with its (single) + * argument, or with a pointer to a clockframe if ih_arg is NULL. + */ +struct intrhand { + int (*ih_fun)(void *); + void *ih_arg; + short ih_number; /* interrupt number */ + /* the H/W provides */ + char ih_pil; /* interrupt priority */ + char ih_mpsafe; + struct intrhand *ih_next; /* global list */ + struct intrhand *ih_pending; /* pending list */ + volatile u_int64_t *ih_map; /* interrupt map reg */ + volatile u_int64_t *ih_clr; /* clear interrupt reg */ + void (*ih_ack)(struct intrhand *); + struct evcount ih_count; /* # of interrupts */ + const void *ih_bus; /* parent bus */ + struct cpu_info *ih_cpu; /* target */ + char ih_name[32]; /* device name */ +}; + +extern struct intrhand *intrlev[MAXINTNUM]; + +void intr_establish(struct intrhand *); + +/* XXX - arbitrary numbers; no interpretation is defined yet */ +#define IPL_NONE 0 /* nothing */ +#define IPL_SOFTINT 1 /* softint */ +#define IPL_SOFTCLOCK 1 /* timeouts */ +#define IPL_SOFTNET 2 /* protocol stack */ +#define IPL_BIO PIL_BIO /* block I/O */ +#define IPL_NET PIL_NET /* network */ +#define IPL_SOFTTTY 4 /* delayed terminal handling */ +#define IPL_TTY PIL_TTY /* terminal */ +#define IPL_VM PIL_VM /* memory allocation */ +#define IPL_AUDIO PIL_AUD /* audio */ +#define IPL_CLOCK PIL_CLOCK /* clock */ +#define IPL_SERIAL PIL_SER /* serial */ +#define IPL_SCHED PIL_SCHED /* scheduler */ +#define IPL_STATCLOCK PIL_STATCLOCK /* statclock */ +#define IPL_HIGH PIL_HIGH /* everything */ + +#define spl0() _spl(IPL_NONE) +#define splsoftclock() _splraise(IPL_SOFTCLOCK) +#define splsoftnet() _splraise(IPL_SOFTNET) +#define splbio() _splraise(IPL_BIO) +#define splnet() _splraise(IPL_NET) +#define splsofttty() _splraise(IPL_SOFTTTY) +#define spltty() _splraise(IPL_TTY) +#define splvm() _splraise(IPL_VM) +#define splaudio() _splraise(IPL_AUDIO) +#define splclock() _splraise(IPL_CLOCK) +#define splserial() _splraise(IPL_SERIAL) +#define splsched() _splraise(IPL_SCHED) +#define splstatclock() _splraise(IPL_STATCLOCK) +#define splhigh() _splraise(IPL_HIGH) +#define splx(_oldipl) _splx(_oldipl) + +#define splzs() splserial() + +#define IPL_MPFLOOR IPL_SERIAL +#define IPL_MPSAFE 0x100 + +int splraise(int); +void intr_barrier(void *); + +void *softintr_establish(int, void (*)(void *), void *); +void softintr_disestablish(void *); +void softintr_schedule(void *); + +void *softintr_establish_raw(int, void (*)(void *), void *); +#define softintr_disestablish_raw(ih) softintr_disestablish(ih) +#define softintr_schedule_raw(ih) softintr_schedule(ih) + +void send_softint(int, struct intrhand *); + +#endif /* _MACHINE_INTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/ioctl_fd.h b/lib/libc/include/sparc64-openbsd-none/sparc64/ioctl_fd.h new file mode 100644 index 000000000000..e7fcb85fe9d2 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/ioctl_fd.h @@ -0,0 +1,130 @@ +/* $OpenBSD: ioctl_fd.h,v 1.2 2011/03/23 16:54:37 pirofti Exp $ */ +/* from: ioctl_fd.h,v 1.4 1995/06/29 03:49:32 jtk Exp */ + +/* + * Copyright (C) 1992-1994 by Joerg Wunsch, Dresden + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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(S) BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * From: Id: ioctl_fd.h,v 1.7 1994/10/30 19:17:39 joerg Exp + */ + +#ifndef _MACHINE_IOCTL_FD_H_ +#define _MACHINE_IOCTL_FD_H_ + +#define FD_FORMAT_VERSION 110 /* used to validate before formatting */ +#define FD_MAX_NSEC 36 /* highest known number of spt - allow for */ + /* 2.88 MB drives */ + +struct fd_formb { + int format_version; /* == FD_FORMAT_VERSION */ + int cyl, head; + int transfer_rate; /* fdreg.h: FDC_???KBPS */ + + union { + struct fd_form_data { + /* + * DO NOT CHANGE THE LAYOUT OF THIS STRUCTS + * it is hardware-dependant since it exactly + * matches the byte sequence to write to FDC + * during its `format track' operation + */ + u_char secshift; /* 0 -> 128, ...; usually 2 -> 512 */ + u_char nsecs; /* must be <= FD_MAX_NSEC */ + u_char gaplen; /* GAP 3 length; usually 84 */ + u_char fillbyte; /* usually 0xf6 */ + struct fd_idfield_data { + /* + * data to write into id fields; + * for obscure formats, they mustn't match + * the real values (but mostly do) + */ + u_char cylno; /* 0 thru 79 (or 39) */ + u_char headno; /* 0, or 1 */ + u_char secno; /* starting at 1! */ + u_char secsize; /* usually 2 */ + } idfields[FD_MAX_NSEC]; /* 0 <= idx < nsecs used */ + } structured; + u_char raw[1]; /* to have continuous indexed access */ + } format_info; +}; + +/* make life easier */ +# define fd_formb_secshift format_info.structured.secshift +# define fd_formb_nsecs format_info.structured.nsecs +# define fd_formb_gaplen format_info.structured.gaplen +# define fd_formb_fillbyte format_info.structured.fillbyte +/* these data must be filled in for(i = 0; i < fd_formb_nsecs; i++) */ +# define fd_formb_cylno(i) format_info.structured.idfields[i].cylno +# define fd_formb_headno(i) format_info.structured.idfields[i].headno +# define fd_formb_secno(i) format_info.structured.idfields[i].secno +# define fd_formb_secsize(i) format_info.structured.idfields[i].secsize + +/* + * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how + * we tell them apart. + */ +struct fd_type { + int sectrac; /* sectors per track */ + int heads; /* number of heads */ + int seccyl; /* sectors per cylinder */ + int secsize; /* size code for sectors */ + int datalen; /* data len when secsize = 0 */ + int steprate; /* step rate and head unload time */ + int gap1; /* gap len between sectors */ + int gap2; /* formatting gap */ + int tracks; /* total num of tracks */ + int size; /* size of disk in sectors */ + int step; /* steps per cylinder */ + int rate; /* transfer speed code */ + char *name; +}; + + +#define FD_FORM _IOW('F', 61, struct fd_formb) /* format a track */ +#define FD_GTYPE _IOR('F', 62, struct fd_type) /* get drive type */ +#define FD_STYPE _IOW('F', 63, struct fd_type) /* set drive type */ + +#define FD_GOPTS _IOR('F', 64, int) /* drive options, see below */ +#define FD_SOPTS _IOW('F', 65, int) + +#define FDOPT_NORETRY 0x0001 /* no retries on failure (cleared on close) */ +#define FDOPT_SILENT 0x0002 + +/* + * The following definitions duplicate those in sys/i386/isa/fdreg.h + * They are here since their values are to be used in the above + * structure when formatting a floppy. For very obvious reasons, both + * definitions must match ;-) + */ +#ifndef FDC_500KBPS +#define FDC_500KBPS 0x00 /* 500KBPS MFM drive transfer rate */ +#define FDC_300KBPS 0x01 /* 300KBPS MFM drive transfer rate */ +#define FDC_250KBPS 0x02 /* 250KBPS MFM drive transfer rate */ +#define FDC_125KBPS 0x03 /* 125KBPS FM drive transfer rate */ + /* for some controllers 1MPBS instead */ +#endif /* FDC_500KBPS */ + + +#endif /* !_MACHINE_IOCTL_FD_H__ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/kcore.h b/lib/libc/include/sparc64-openbsd-none/sparc64/kcore.h new file mode 100644 index 000000000000..6c89a84b0c80 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/kcore.h @@ -0,0 +1,61 @@ +/* $OpenBSD: kcore.h,v 1.3 2008/06/26 05:42:13 ray Exp $ */ +/* $NetBSD: kcore.h,v 1.4 2000/08/01 00:40:26 eeh Exp $ */ + +/*- + * Copyright (c) 1996 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * The layout of a kernel core on the dump device is as follows: + * a `struct kcore_seg' of type CORE_CPU + * a `struct cpu_kcore_hdr' + */ + +typedef struct cpu_kcore_hdr { + int cputype; /* CPU type associated with this dump */ + + int nmemseg; /* # of physical memory segments */ + uint64_t memsegoffset; /* start of memseg array (relative */ + /* to the start of this header) */ + + int nsegmap; /* # of kernel segs */ + uint64_t segmapoffset; /* start of segmap array (relative */ + /* to the start of this header) */ + + uint64_t kernbase; /* copy of KERNBASE goes here */ + uint64_t cpubase; /* Pointer to cpu_info structure */ + + uint64_t ktextbase; /* Virtual start of text segment */ + uint64_t ktextp; /* Physical address of 4MB locked TLB */ + uint64_t ktextsz; /* Size of locked kernel text segment. */ + + uint64_t kdatabase; /* Virtual start of data segment */ + uint64_t kdatap; /* Physical address of 4MB locked TLB */ + uint64_t kdatasz; /* Size of locked kernel data segment. */ + +} cpu_kcore_hdr_t; \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/limits.h b/lib/libc/include/sparc64-openbsd-none/sparc64/limits.h new file mode 100644 index 000000000000..9060a2e178d0 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/limits.h @@ -0,0 +1,55 @@ +/* $OpenBSD: limits.h,v 1.11 2015/04/30 13:42:08 millert Exp $ */ +/* $NetBSD: limits.h,v 1.8 2000/08/08 22:31:14 tshiozak Exp $ */ + +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)limits.h 8.3 (Berkeley) 1/4/94 + */ + +#ifndef _MACHINE_LIMITS_H_ +#define _MACHINE_LIMITS_H_ + +#include + +#if __POSIX_VISIBLE || __XPG_VISIBLE +#define SSIZE_MAX LONG_MAX /* max value for a ssize_t */ +#endif + +#if __BSD_VISIBLE +#define SIZE_T_MAX ULONG_MAX /* max value for a size_t (historic) */ + +/* GCC requires that quad constants be written as expressions. */ +#define UQUAD_MAX ((u_quad_t)0-1) /* max value for a uquad_t */ + /* max value for a quad_t */ +#define QUAD_MAX ((quad_t)(UQUAD_MAX >> 1)) +#define QUAD_MIN (-QUAD_MAX-1) /* min value for a quad_t */ + +#endif /* __BSD_VISIBLE */ + +#endif /* _MACHINE_LIMITS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/loadfile_machdep.h b/lib/libc/include/sparc64-openbsd-none/sparc64/loadfile_machdep.h new file mode 100644 index 000000000000..9902239fb27e --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/loadfile_machdep.h @@ -0,0 +1,65 @@ +/* $OpenBSD: loadfile_machdep.h,v 1.3 2013/10/17 11:54:02 miod Exp $ */ +/* $NetBSD: loadfile_machdep.h,v 1.3 2000/08/16 08:16:58 mrg Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define BOOT_ELF +#ifdef __sparc_v9__ +#define ELFSIZE 64 +#else +#define ELFSIZE 32 +#endif + +#define LOAD_KERNEL LOAD_ALL +#define COUNT_KERNEL COUNT_ALL + +#ifdef _STANDALONE +#define LOADADDR(a) (((u_long)(a) & 0x0fffffff) + offset) +#define ALIGNENTRY(a) ((u_long)(a)) +#define READ(f, b, c) read((f), (void *)LOADADDR(b), (c)) +#define BCOPY(s, d, c) memcpy((void *)LOADADDR(d), (void *)(s), (c)) +#define BZERO(d, c) memset((void *)LOADADDR(d), 0, (c)) +#define WARN(a) (void)(printf a, \ + printf((errno ? ": %s\n" : "\n"), \ + strerror(errno))) +#define PROGRESS(a) (void) printf a +#define ALLOC(a) alloc(a) +#define FREE(a, b) free(a, b) +#else +#define LOADADDR(a) (((u_long)(a)) + offset) +#define ALIGNENTRY(a) ((u_long)(a)) +#define READ(f, b, c) read((f), (void *)LOADADDR(b), (c)) +#define BCOPY(s, d, c) memcpy((void *)LOADADDR(d), (void *)(s), (c)) +#define BZERO(d, c) memset((void *)LOADADDR(d), 0, (c)) +#define WARN(a) warn a +#define PROGRESS(a) /* nothing */ +#define ALLOC(a) malloc(a) +#define FREE(a, b) free(a) +#endif \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/mdesc.h b/lib/libc/include/sparc64-openbsd-none/sparc64/mdesc.h new file mode 100644 index 000000000000..bffc347b6a15 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/mdesc.h @@ -0,0 +1,55 @@ +/* $OpenBSD: mdesc.h,v 1.4 2019/10/20 16:27:19 kettenis Exp $ */ +/* + * Copyright (c) 2009 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +struct md_header { + uint32_t transport_version; + uint32_t node_blk_sz; + uint32_t name_blk_sz; + uint32_t data_blk_sz; +}; + +struct md_element { + uint8_t tag; + uint8_t name_len; + uint16_t _reserved_field; + uint32_t name_offset; + union { + struct { + uint32_t data_len; + uint32_t data_offset; + } y; + uint64_t val; + } d; +}; + +#ifdef _KERNEL + +extern caddr_t mdesc; +extern size_t mdesc_len; + +extern caddr_t pri; +extern size_t pri_len; + +void mdesc_init(void); +uint64_t mdesc_get_prop_val(int, const char *); +const char *mdesc_get_prop_str(int, const char *); +const char *mdesc_get_prop_data(int, const char *, size_t *); +int mdesc_find(const char *, uint64_t); +int mdesc_find_child(int, const char *, uint64_t); +int mdesc_find_node(const char *); + +#endif \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/mplock.h b/lib/libc/include/sparc64-openbsd-none/sparc64/mplock.h new file mode 100644 index 000000000000..0630808c58de --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/mplock.h @@ -0,0 +1,10 @@ +/* $OpenBSD: mplock.h,v 1.4 2017/10/17 14:25:35 visa Exp $ */ + +/* public domain */ + +#ifndef _MACHINE_MPLOCK_H_ +#define _MACHINE_MPLOCK_H_ + +#define __USE_MI_MPLOCK + +#endif /* !_MACHINE_MPLOCK_H */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/mutex.h b/lib/libc/include/sparc64-openbsd-none/sparc64/mutex.h new file mode 100644 index 000000000000..b9368872daec --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/mutex.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mutex.h,v 1.8 2018/02/19 09:18:50 mpi Exp $ */ + +#define __USE_MI_MUTEX \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/openfirm.h b/lib/libc/include/sparc64-openbsd-none/sparc64/openfirm.h new file mode 100644 index 000000000000..aadcaf0a9abf --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/openfirm.h @@ -0,0 +1,65 @@ +/* $OpenBSD: openfirm.h,v 1.7 2024/11/08 12:48:00 miod Exp $ */ +/* $NetBSD: openfirm.h,v 1.8 2001/07/20 00:07:14 eeh Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + */ +/* + * Prototypes for additional OpenFirmware Interface Routines + */ + +#include + +/* All cells are 8 byte slots */ +typedef u_int64_t cell_t; +#define HDL2CELL(x) (cell_t)(u_int)(int)(x) +#define ADR2CELL(x) (cell_t)(x) + +#define HDQ2CELL_HI(x) (cell_t)(0) +#define HDQ2CELL_LO(x) (cell_t)(x) + +#define CELL2HDQ(hi, lo) (lo) + +int OF_test(char *service); +int OF_test_method(int handle, char *method); + +int OF_stdin(void); +int OF_stdout(void); +void OF_set_symbol_lookup(void (*s2v)(void *), void (*v2s)(void *)); +void OF_poweroff(void); +void OF_sym2val(void *); +void OF_val2sym(void *); +int OF_milliseconds(void); +int OF_searchprop(int node, char *prop, void *buf, int buflen); +int OF_mapintr(int node, int *interrupt, int validlen, int buflen); +int OF_instance_to_path(int ihandle, char *buf, int buflen); +int OF_package_to_path(int phandle, char *buf, int buflen); + +void (*OF_set_callback(void (*)(void *)))(void *); \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/openpromio.h b/lib/libc/include/sparc64-openbsd-none/sparc64/openpromio.h new file mode 100644 index 000000000000..c301d356b6d1 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/openpromio.h @@ -0,0 +1,57 @@ +/* $OpenBSD: openpromio.h,v 1.3 2003/06/02 23:27:56 millert Exp $ */ +/* $NetBSD: openpromio.h,v 1.1.1.1 1998/06/20 04:58:52 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)openpromio.h 8.1 (Berkeley) 6/11/93 + */ + +struct opiocdesc { + int op_nodeid; /* passed or returned node id */ + int op_namelen; /* length of op_name */ + char *op_name; /* pointer to field name */ + int op_buflen; /* length of op_buf (value-result) */ + char *op_buf; /* pointer to field value */ +}; + +#define OPIOCGET _IOWR('O', 1, struct opiocdesc) /* get openprom field */ +#define OPIOCSET _IOW('O', 2, struct opiocdesc) /* set openprom field */ +#define OPIOCNEXTPROP _IOWR('O', 3, struct opiocdesc) /* get next property */ +#define OPIOCGETOPTNODE _IOR('O', 4, int) /* get openprom field */ +#define OPIOCGETNEXT _IOWR('O', 5, int) /* get next node of node */ +#define OPIOCGETCHILD _IOWR('O', 6, int) /* get first child of node */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/param.h b/lib/libc/include/sparc64-openbsd-none/sparc64/param.h new file mode 100644 index 000000000000..c3d5e1fd20d4 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/param.h @@ -0,0 +1,183 @@ +/* $OpenBSD: param.h,v 1.42 2023/12/14 13:26:49 claudio Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1996-1999 Eduardo Horvath + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ + +#define _MACHINE sparc64 +#define MACHINE "sparc64" +#define _MACHINE_ARCH sparc64 +#define MACHINE_ARCH "sparc64" +#define MID_MACHINE MID_SPARC64 + +#define PAGE_SHIFT 13 +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define PAGE_MASK (PAGE_SIZE - 1) + +/* + * Here are all the magic kernel virtual addresses and how they're allocated. + * + * First, the PROM is usually a fixed-sized block from 0x00000000f0000000 to + * 0x00000000f0100000. It also uses some space around 0x00000000fff00000 to + * map in device registers. The rest is pretty much ours to play with. + * + * The kernel starts at KERNBASE. Here's the layout. We use macros to set + * the addresses so we can relocate everything easily. We use 4MB locked TTEs + * to map in the kernel text and data segments. Any extra pages are recycled, + * so they can potentially be double-mapped. This shouldn't really be a + * problem since they're unused, but wild pointers can cause silent data + * corruption if they are in those segments. + * + * 0x0000000000000000: 64K NFO page zero + * 0x0000000000010000: Userland or PROM + * KERNBASE: 4MB kernel text and read only data + * This is mapped in the ITLB and + * Read-Only in the DTLB + * KERNBASE+0x400000: 4MB kernel data and BSS -- not in ITLB + * Contains context table, kernel pmap, + * and other important structures. + * KERNBASE+0x800000: Unmapped page -- redzone + * KERNBASE+0x802000: Process 0 stack and u-area + * KERNBASE+0x806000: 2 pages for pmap_copy_page and /dev/mem + * KERNBASE+0x80a000: Start of kernel VA segment + * KERNEND: End of kernel VA segment + * KERNEND+0x02000: Auxreg_va (unused?) + * KERNEND+0x04000: TMPMAP_VA (unused?) + * KERNEND+0x06000: message buffer. + * KERNEND+0x010000: 64K locked TTE -- different for each CPU + * Contains interrupt stack, cpu_info structure, + * and 32KB kernel TSB. + * + */ +#define KERNBASE 0x001000000 /* start of kernel virtual space */ + +#ifdef _KERNEL + +#define KERNEND 0x0e0000000 /* end of kernel virtual space */ + +#define _MAXNBPG 8192 /* fixed VAs, independent of actual NBPG */ + +#define AUXREG_VA ( KERNEND + _MAXNBPG) /* 1 page REDZONE */ +#define TMPMAP_VA ( AUXREG_VA + _MAXNBPG) +#define MSGBUF_VA ( TMPMAP_VA + _MAXNBPG) +/* + * Here's the location of the interrupt stack and CPU structure. + */ +#define INTSTACK ( KERNEND + 8*_MAXNBPG)/* 64K after kernel end */ +#define EINTSTACK ( INTSTACK + 2*USPACE) /* 32KB */ +#define CPUINFO_VA ( EINTSTACK) + +#define NBPG PAGE_SIZE /* bytes/page */ +#define PGSHIFT PAGE_SHIFT /* LOG2(PAGE_SIZE) */ +#define PGOFSET PAGE_MASK /* byte offset into page */ + +#define UPAGES 2 /* pages of u-area */ +#define USPACE (UPAGES * PAGE_SIZE) /* total size of u-area */ +#define USPACE_ALIGN 0 /* u-area alignment 0-none */ + +#define NMBCLUSTERS (64 * 1024) /* max cluster allocation */ + +#ifndef MSGBUFSIZE +#define MSGBUFSIZE (1 * PAGE_SIZE) +#endif + +#ifndef _LOCORE + +extern void delay(unsigned int); +#define DELAY(n) delay(n) + +extern int cputyp; + +#if defined (SUN4US) || defined (SUN4V) +#define CPU_ISSUN4U (cputyp == CPU_SUN4U) +#define CPU_ISSUN4US (cputyp == CPU_SUN4US) +#define CPU_ISSUN4V (cputyp == CPU_SUN4V) +#else +#define CPU_ISSUN4U (1) +#define CPU_ISSUN4US (0) +#define CPU_ISSUN4V (0) +#endif + +#endif /* _LOCORE */ + +/* + * Values for the cputyp variable. + */ +#define CPU_SUN4 0 +#define CPU_SUN4C 1 +#define CPU_SUN4M 2 +#define CPU_SUN4U 3 +#define CPU_SUN4US 4 +#define CPU_SUN4V 5 + +/* + * On a sun4u machine, the page size is 8192. + */ + +#ifndef _LOCORE +#include +#endif + +#endif /* _KERNEL */ + +#endif /* _MACHINE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/pcb.h b/lib/libc/include/sparc64-openbsd-none/sparc64/pcb.h new file mode 100644 index 000000000000..c98a66a72e0d --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/pcb.h @@ -0,0 +1,152 @@ +/* $OpenBSD: pcb.h,v 1.11 2022/10/21 18:55:42 miod Exp $ */ +/* $NetBSD: pcb.h,v 1.7 2000/12/29 17:12:05 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pcb.h 8.1 (Berkeley) 6/11/93 + */ + +#ifndef _MACHINE_PCB_H_ +#define _MACHINE_PCB_H_ + +#include + +#ifdef notyet +#define PCB_MAXWIN 32 /* architectural limit */ +#else +#define PCB_MAXWIN 8 /* worried about u area sizes ... */ +#endif + +/* + * SPARC Process Control Block. + * + * pcb_uw is positive if there are any user windows that are + * are currently in the CPU windows rather than on the user + * stack. Whenever we are running in the kernel with traps + * enabled, we decrement pcb_uw for each ``push'' of a CPU + * register window into the stack, and we increment it for + * each ``pull'' from the stack into the CPU. (If traps are + * disabled, or if we are in user mode, pcb_uw is junk.) + * + * To ease computing pcb_uw on traps from user mode, we keep track + * of the log base 2 of the single bit that is set in %wim. + * + * If an overflow occurs while the associated user stack pages + * are invalid (paged out), we have to store the registers + * in a page that is locked in core while the process runs, + * i.e., right here in the pcb. We also need the stack pointer + * for the last such window (but only the last, as the others + * are in each window) and the count of windows saved. We + * cheat by having a whole window structure for that one %sp. + * Thus, to save window pcb_rw[i] to memory, we write it at + * pcb_rw[i + 1].rw_in[6]. + * + * pcb_nsaved has three `kinds' of values. If 0, it means no + * registers are in the PCB (though if pcb_uw is positive, + * there may be the next time you look). If positive, it means + * there are no user registers in the CPU, but there are some + * saved in pcb_rw[]. As a special case, traps that needed + * assistance to pull user registers from the stack also store + * the registers in pcb_rw[], and set pcb_nsaved to -1. This + * special state is normally short-term: it can only last until the + * trap returns, and it can never persist across entry to user code. + */ +/* + * v9 addendum: + * + * Window handling between v8 and v9 has changed somewhat. There + * is no %wim. Instead, we have a %cwp, %cansave, %canrestore, + * %cleanwin, and %otherwin. By definition: + * + * %cansave + %canrestore + %otherwin = NWINDOWS - 2 + * + * In addition, %cleanwin >= %canrestore since restorable windows + * are considered clean. This means that by storing %canrestore + * and %otherwin, we should be able to compute the values of all + * the other registers. + * + * The only other register we need to save is %cwp because it cannot + * be trivially computed from the other registers. The %cwp is + * stored in the %tstate register, but if the machine was in a register + * window spill/fill handler, the value of that %cwp may be off by + * as much as 2 register windows. We will also store %cwp. [We will + * try to steal pcb_uw or pcb_nsaved for this purpose eventually.] + * + * To calculate what registers are in the pcb, start with pcb_cwp + * and proceed to (pcb_cwp - pcb_canrestore) % NWINDOWS. These should + * be saved to their appropriate register windows. The client routine + * (trap handler) is responsible for saving pcb_cwp + 1 [%o1-%o7] in + * the trap frame or on the stack. + * + * + * Even more addendum: + * + * With the new system for keeping track of register windows we don't + * care about anything other than pcb_uw which keeps track of how many + * full windows we have. As soon as a flush traps, we dump all user + * windows to the pcb, handle the fault, then restore all user windows. + * + * XXX we are using pcb_nsaved as the counter. pcb_uw is still a mask. + * change this as soon as the new scheme is debugged. + */ +struct pcb { + u_int64_t pcb_sp; /* sp (%o6) when switch() was called */ + u_int64_t pcb_pc; /* pc (%o7) when switch() was called */ + caddr_t pcb_onfault; /* for copyin/out */ + short pcb_pstate; /* %pstate when switch() was called -- may be useful if we support multiple memory models */ + char pcb_nsaved; /* number of windows saved in pcb */ + + /* The rest is probably not needed except for pcb_rw */ + char pcb_cwp; /* %cwp when switch() was called */ + char pcb_pil; /* %pil when switch() was called -- probably not needed */ + + const char *lastcall; /* DEBUG -- name of last system call */ + u_int64_t pcb_wcookie; + + /* the following MUST be aligned on a 64-bit boundary */ + struct rwindow pcb_rw[PCB_MAXWIN]; /* saved windows */ + u_int64_t pcb_rwsp[PCB_MAXWIN]; +}; + +#ifndef _KERNEL +/* Let gdb compile. We need fancier macros to make these make sense. */ +#define pcb_psr pcb_pstate +#define pcb_wim pcb_cwp +#endif /* _KERNEL */ + +#endif /* _MACHINE_PCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/pci_machdep.h b/lib/libc/include/sparc64-openbsd-none/sparc64/pci_machdep.h new file mode 100644 index 000000000000..f42a581bd4fc --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/pci_machdep.h @@ -0,0 +1,137 @@ +/* $OpenBSD: pci_machdep.h,v 1.38 2020/06/23 01:21:29 jmatthew Exp $ */ +/* $NetBSD: pci_machdep.h,v 1.7 2001/07/20 00:07:14 eeh Exp $ */ + +/* + * Copyright (c) 1999 Matthew R. Green + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_PCI_MACHDEP_H_ +#define _MACHINE_PCI_MACHDEP_H_ + +/* + * Forward declarations. + */ +struct pci_attach_args; + +/* + * define some bits used to glue into the common PCI code. + */ + +#define __HAVE_PCI_MSIX + +typedef struct sparc_pci_chipset *pci_chipset_tag_t; + +#define PCI_INTR_INTX 0x00000000 +#define PCI_INTR_MSI 0x80000000 +#define PCI_INTR_MSIX 0x40000000 +#define PCI_INTR_TYPE_MASK 0xc0000000 +#define PCI_INTR_TYPE(_ih) ((_ih) & PCI_INTR_TYPE_MASK) + +#define PCI_INTR_TAG_MASK 0x00ffff00 +#define PCI_INTR_TAG(_ih) ((_ih) & PCI_INTR_TAG_MASK) + +#define PCI_INTR_VEC_MASK 0x000000ff +#define PCI_INTR_VEC(_ih) ((_ih) & PCI_INTR_VEC_MASK) +typedef u_int pci_intr_handle_t; + +/* + * The stuuuuuuupid allegedly MI PCI code expects pcitag_t to be a + * scalar type. But we really need to store both the OFW node and + * the bus/device/function info in it. (We'd like to store more, + * like all the ofw properties, but we don't need to.) Luckily, + * both are 32-bit values, so we can squeeze them into a u_int64_t + * with a little help from some macros. + */ + +#define PCITAG_NODE(x) (int)(((x)>>32)&0xffffffff) +#define PCITAG_OFFSET(x) ((x)&0xffffffff) +#define PCITAG_BUS(t) ((PCITAG_OFFSET(t)>>16)&0xff) +#define PCITAG_DEV(t) ((PCITAG_OFFSET(t)>>11)&0x1f) +#define PCITAG_FUN(t) ((PCITAG_OFFSET(t)>>8)&0x7) +#define PCITAG_CREATE(n,b,d,f) (((u_int64_t)(n)<<32)|((b)<<16)|((d)<<11)|((f)<<8)) +#define PCITAG_SETNODE(t,n) ((t)&0xffffffff)|(((n)<<32) +typedef u_int64_t pcitag_t; + +struct sparc_pci_chipset { + void *cookie; + bus_space_tag_t bustag; + bus_space_handle_t bushandle; + int rootnode; /* PCI controller */ + int busnode[256]; + int (*conf_size)(pci_chipset_tag_t, pcitag_t); + pcireg_t (*conf_read)(pci_chipset_tag_t, pcitag_t, int); + void (*conf_write)(pci_chipset_tag_t, pcitag_t, int, pcireg_t); + int (*intr_map)(struct pci_attach_args *, pci_intr_handle_t *); + int (*probe_device_hook)(void *, struct pci_attach_args *); +}; + +void pci_attach_hook(struct device *, struct device *, + struct pcibus_attach_args *); +int pci_probe_device_hook(pci_chipset_tag_t, + struct pci_attach_args *); +int pci_bus_maxdevs(pci_chipset_tag_t, int); +pcitag_t pci_make_tag(pci_chipset_tag_t, int, int, int); +void pci_decompose_tag(pci_chipset_tag_t, pcitag_t, int *, int *, + int *); +int pci_conf_size(pci_chipset_tag_t, pcitag_t); +pcireg_t pci_conf_read(pci_chipset_tag_t, pcitag_t, int); +void pci_conf_write(pci_chipset_tag_t, pcitag_t, int, + pcireg_t); +int pci_intr_map(struct pci_attach_args *, pci_intr_handle_t *); +int pci_intr_map_msi(struct pci_attach_args *, pci_intr_handle_t *); +int pci_intr_map_msix(struct pci_attach_args *, int, + pci_intr_handle_t *); +int pci_intr_line(pci_chipset_tag_t, pci_intr_handle_t); +const char *pci_intr_string(pci_chipset_tag_t, pci_intr_handle_t); +void *pci_intr_establish(pci_chipset_tag_t, pci_intr_handle_t, + int, int (*)(void *), void *, const char *); +void *pci_intr_establish_cpu(pci_chipset_tag_t, pci_intr_handle_t, + int, struct cpu_info *, + int (*)(void *), void *, const char *); +void pci_intr_disestablish(pci_chipset_tag_t, void *); + +void pci_msi_enable(pci_chipset_tag_t, pcitag_t, bus_addr_t, int); +void pci_msix_enable(pci_chipset_tag_t, pcitag_t, bus_space_tag_t, + int, bus_addr_t, uint32_t); +int pci_msix_table_map(pci_chipset_tag_t, pcitag_t, + bus_space_tag_t, bus_space_handle_t *); +void pci_msix_table_unmap(pci_chipset_tag_t, pcitag_t, + bus_space_tag_t, bus_space_handle_t); + +int sparc64_pci_enumerate_bus(struct pci_softc *, + int (*match)(struct pci_attach_args *), + struct pci_attach_args *); + +#define PCI_MACHDEP_ENUMERATE_BUS sparc64_pci_enumerate_bus + +#define pci_min_powerstate(c, t) (PCI_PMCSR_STATE_D3) +#define pci_set_powerstate_md(c, t, s, p) + +#define pciide_machdep_compat_intr_establish(a, b, c, d, e) (NULL) +#define pciide_machdep_compat_intr_disestablish(a, b) do { } while (0) + +#define pci_dev_postattach(a, b) + +#endif /* _MACHINE_PCI_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/pmap.h b/lib/libc/include/sparc64-openbsd-none/sparc64/pmap.h new file mode 100644 index 000000000000..e5cad9b40fe1 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/pmap.h @@ -0,0 +1,214 @@ +/* $OpenBSD: pmap.h,v 1.41 2025/09/18 14:54:33 kettenis Exp $ */ +/* $NetBSD: pmap.h,v 1.16 2001/04/22 23:19:30 thorpej Exp $ */ + +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_PMAP_H_ +#define _MACHINE_PMAP_H_ + +#ifndef _LOCORE +#ifdef _KERNEL +#include +#endif +#include +#endif + +#define __HAVE_PMAP_PURGE + +/* + * This scheme uses 2-level page tables. + * + * While we're still in 32-bit mode we do the following: + * + * offset: 13 bits + * 1st level: 1024 64-bit TTEs in an 8K page for 10 bits + * 2nd level: 512 32-bit pointers in the pmap for 9 bits + * ------- + * total: 32 bits + * + * In 64-bit mode the Spitfire and Blackbird CPUs support only + * 44-bit virtual addresses. All addresses between + * 0x0000 07ff ffff ffff and 0xffff f800 0000 0000 are in the + * "VA hole" and trap, so we don't have to track them. However, + * we do need to keep them in mind during PT walking. If they + * ever change the size of the address "hole" we need to rework + * all the page table handling. + * + * offset: 13 bits + * 1st level: 1024 64-bit TTEs in an 8K page for 10 bits + * 2nd level: 1024 64-bit pointers in an 8K page for 10 bits + * 3rd level: 1024 64-bit pointers in the segmap for 10 bits + * ------- + * total: 43 bits + * + * Of course, this means for 32-bit spaces we always have a (practically) + * wasted page for the segmap (only one entry used) and half a page wasted + * for the page directory. We still have need of one extra bit 8^(. + */ + +#define HOLESHIFT (43) + +#define PTSZ (PAGE_SIZE/8) +#define PDSZ (PTSZ) +#define STSZ (PTSZ) + +#define PTSHIFT (13) +#define PDSHIFT (10+PTSHIFT) +#define STSHIFT (10+PDSHIFT) + +#define PTMASK (PTSZ-1) +#define PDMASK (PDSZ-1) +#define STMASK (STSZ-1) + +#ifndef _LOCORE + +#define va_to_seg(v) (int)((((paddr_t)(v))>>STSHIFT)&STMASK) +#define va_to_dir(v) (int)((((paddr_t)(v))>>PDSHIFT)&PDMASK) +#define va_to_pte(v) (int)((((paddr_t)(v))>>PTSHIFT)&PTMASK) + +#ifdef _KERNEL + +/* + * Support for big page sizes. This maps the page size to the + * page bits. + */ +struct page_size_map { + u_int64_t mask; + u_int64_t code; +#ifdef DEBUG + u_int64_t use; +#endif +}; +extern const struct page_size_map page_size_map[]; + +struct pmap { + struct mutex pm_mtx; + int pm_ctx; /* Current context */ + int pm_refs; /* ref count */ + /* + * This contains 64-bit pointers to pages that contain + * 1024 64-bit pointers to page tables. All addresses + * are physical. + * + * !!! Only touch this through pseg_get() and pseg_set() !!! + */ + paddr_t pm_physaddr; /* physical address of pm_segs */ + int64_t *pm_segs; + + struct pmap_statistics pm_stats; +}; + +/* + * This comes from the PROM and is used to map prom entries. + */ +struct prom_map { + u_int64_t vstart; + u_int64_t vsize; + u_int64_t tte; +}; + +#define PMAP_NC 0x001 /* Set the E bit in the page */ +#define PMAP_NVC 0x002 /* Don't enable the virtual cache */ +#define PMAP_NOCACHE PMAP_NC +#define PMAP_LITTLE 0x004 /* Map in little endian mode */ +/* Large page size hints -- we really should use another param to pmap_enter() */ +#define PMAP_8K 0x000 +#define PMAP_64K 0x008 /* Use 64K page */ +#define PMAP_512K 0x010 +#define PMAP_4M 0x018 +#define PMAP_SZ_TO_TTE(x) (((x)&0x018)<<58) +/* If these bits are different in va's to the same PA then there is an aliasing in the d$ */ +#define VA_ALIAS_ALIGN (1<<14) +#define VA_ALIAS_MASK (VA_ALIAS_ALIGN - 1) + +typedef struct pmap *pmap_t; + +extern struct pmap kernel_pmap_; +#define pmap_kernel() (&kernel_pmap_) + +/* int pmap_change_wiring(pmap_t pm, vaddr_t va, boolean_t wired); */ +#define pmap_resident_count(pm) ((pm)->pm_stats.resident_count) +#define pmap_update(pm) /* nothing (yet) */ + +#define pmap_proc_iflush(p,va,len) /* nothing */ +#define pmap_init_percpu() do { /* nothing */ } while (0) + +void pmap_bootstrap(u_long, u_long, u_int, u_int); +int pmap_copyinsn(pmap_t, vaddr_t, uint32_t *); + +/* make sure all page mappings are modulo 16K to prevent d$ aliasing */ +#define PMAP_PREFER +/* pmap prefer alignment */ +#define PMAP_PREFER_ALIGN() (VA_ALIAS_ALIGN) +/* pmap prefer offset in alignment */ +#define PMAP_PREFER_OFFSET(of) ((of) & VA_ALIAS_MASK) + +#define PMAP_CHECK_COPYIN CPU_ISSUN4V + +#define PMAP_GROWKERNEL /* turn on pmap_growkernel interface */ + +/* SPARC specific? */ +int pmap_dumpsize(void); +int pmap_dumpmmu(int (*)(dev_t, daddr_t, caddr_t, size_t), daddr_t); +int pmap_pa_exists(paddr_t); + +/* SPARC64 specific */ +int ctx_alloc(struct pmap*); +void ctx_free(struct pmap*); + +#endif /* _KERNEL */ + +/* + * For each struct vm_page, there is a list of all currently valid virtual + * mappings of that page. + */ +typedef struct pv_entry { + struct pv_entry *pv_next; /* next pv_entry */ + struct pmap *pv_pmap; /* pmap where mapping lies */ + vaddr_t pv_va; /* virtual address for mapping */ +} *pv_entry_t; +/* PV flags encoded in the low bits of the VA of the first pv_entry */ + +struct vm_page_md { + struct mutex pvmtx; + struct pv_entry pvent; +}; + +#define VM_MDPAGE_INIT(pg) do { \ + mtx_init(&(pg)->mdpage.pvmtx, IPL_VM); \ + (pg)->mdpage.pvent.pv_next = NULL; \ + (pg)->mdpage.pvent.pv_pmap = NULL; \ + (pg)->mdpage.pvent.pv_va = 0; \ +} while (0) + +#endif /* _LOCORE */ +#endif /* _MACHINE_PMAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/proc.h b/lib/libc/include/sparc64-openbsd-none/sparc64/proc.h new file mode 100644 index 000000000000..55fd5598d909 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/proc.h @@ -0,0 +1,52 @@ +/* $OpenBSD: proc.h,v 1.10 2024/11/07 05:24:43 jsg Exp $ */ +/* $NetBSD: proc.h,v 1.2 1999/11/06 20:13:50 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)proc.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * Machine-dependent part of the proc structure for SPARC. + */ +struct mdproc { + struct trapframe *md_tf; /* trap/syscall registers */ + struct fpstate *md_fpstate; /* fpu state, if any; always resident */ + volatile int md_astpending; + paddr_t md_pcbpaddr; +}; \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/profile.h b/lib/libc/include/sparc64-openbsd-none/sparc64/profile.h new file mode 100644 index 000000000000..477b98523688 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/profile.h @@ -0,0 +1,74 @@ +/* $OpenBSD: profile.h,v 1.4 2012/08/22 17:19:35 pascal Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)profile.h 8.1 (Berkeley) 6/11/93 + */ + +#ifdef __PIC__ +/* Inline expansion of PICCY_SET() (see ). */ +#define MCOUNT \ + __asm__(".global _mcount");\ + __asm__("_mcount:");\ + __asm__("add %o7, 8, %o1");\ + __asm__("1: rd %pc, %o2");\ + __asm__("add %o2, __mcount-1b, %o2");\ + __asm__("ld [%o2], %o2");\ + __asm__("jmpl %o2, %g0");\ + __asm__("add %i7, 8, %o0"); +#else +#define MCOUNT \ + __asm__(".global _mcount");\ + __asm__("_mcount:");\ + __asm__("add %i7, 8, %o0");\ + __asm__("sethi %hi(__mcount), %o2");\ + __asm__("jmpl %o2 + %lo(__mcount), %g0");\ + __asm__("add %o7, 8, %o1"); +#endif + +#define _MCOUNT_DECL static void __mcount + +#ifdef _KERNEL +/* + * Block interrupts during mcount so that those interrupts can also be + * counted (as soon as we get done with the current counting). On the + * SPARC, we just splhigh/splx as those do not recursively invoke mcount. + */ +#define MCOUNT_ENTER s = splhigh() +#define MCOUNT_EXIT splx(s) +#endif /* _KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/psl.h b/lib/libc/include/sparc64-openbsd-none/sparc64/psl.h new file mode 100644 index 000000000000..84f4b94cac45 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/psl.h @@ -0,0 +1,327 @@ +/* $OpenBSD: psl.h,v 1.37 2024/11/06 07:11:14 miod Exp $ */ +/* $NetBSD: psl.h,v 1.20 2001/04/13 23:30:05 thorpej Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)psl.h 8.1 (Berkeley) 6/11/93 + */ + +#ifndef _SPARC64_PSL_ +#define _SPARC64_PSL_ + +/* Interesting spl()s */ +#define PIL_SCSI 3 +#define PIL_BIO 5 +#define PIL_VIDEO 5 +#define PIL_TTY 6 +#define PIL_NET 6 +#define PIL_VM 7 +#define PIL_AUD 8 +#define PIL_CLOCK 10 +#define PIL_FD 11 +#define PIL_SER 12 +#define PIL_STATCLOCK 14 +#define PIL_HIGH 15 +#define PIL_SCHED PIL_STATCLOCK + +/* + * SPARC V9 CCR register + */ + +#define ICC_C 0x01L +#define ICC_V 0x02L +#define ICC_Z 0x04L +#define ICC_N 0x08L +#define XCC_SHIFT 4 +#define XCC_C (ICC_C< 0) { \ + splassert_check(__wantipl, __func__); \ + } \ +} while (0) +#define splsoftassert(wantipl) splassert(wantipl) +#else +#define splassert(wantipl) do { /* nada */ } while (0) +#define splsoftassert(wantipl) do { /* nada */ } while (0) +#endif + +/* + * GCC pseudo-functions for manipulating privileged registers + */ +static inline u_int64_t getpstate(void); +static inline u_int64_t +getpstate(void) +{ + return (sparc_rdpr(pstate)); +} + +static inline void setpstate(u_int64_t); +static inline void +setpstate(u_int64_t newpstate) +{ + sparc_wrpr(pstate, newpstate, 0); +} + +static inline int getcwp(void); +static inline int +getcwp(void) +{ + return (sparc_rdpr(cwp)); +} + +static inline void setcwp(u_int64_t); +static inline void +setcwp(u_int64_t newcwp) +{ + sparc_wrpr(cwp, newcwp, 0); +} + +static inline u_int64_t getver(void); +static inline u_int64_t +getver(void) +{ + return (sparc_rdpr(ver)); +} + +static inline u_int64_t intr_disable(void); +static inline u_int64_t +intr_disable(void) +{ + u_int64_t s; + + s = sparc_rdpr(pstate); + sparc_wrpr(pstate, s & ~PSTATE_IE, 0); + return (s); +} + +static inline void intr_restore(u_int64_t); +static inline void +intr_restore(u_int64_t s) +{ + sparc_wrpr(pstate, s, 0); +} + +static inline void stxa_sync(u_int64_t, u_int64_t, u_int64_t); +static inline void +stxa_sync(u_int64_t va, u_int64_t asi, u_int64_t val) +{ + u_int64_t s = intr_disable(); + stxa_nc(va, asi, val); + __asm volatile("membar #Sync" : : : "memory"); + intr_restore(s); +} + +static inline int +_spl(int newipl) +{ + int oldpil; + + __asm volatile( " rdpr %%pil, %0 \n" + " wrpr %%g0, %1, %%pil \n" + : "=&r" (oldpil) + : "I" (newipl) + : "%g0"); + __asm volatile("" : : : "memory"); + + return (oldpil); +} + +/* A non-priority-decreasing version of SPL */ +static inline int +_splraise(int newpil) +{ + int oldpil; + + oldpil = sparc_rdpr(pil); + if (newpil > oldpil) + sparc_wrpr(pil, newpil, 0); + return (oldpil); +} + +static inline void +_splx(int newpil) +{ + sparc_wrpr(pil, newpil, 0); +} + +#endif /* KERNEL && !_LOCORE */ + +#endif /* _SPARC64_PSL_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/pte.h b/lib/libc/include/sparc64-openbsd-none/sparc64/pte.h new file mode 100644 index 000000000000..50afa9a98baf --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/pte.h @@ -0,0 +1,204 @@ +/* $OpenBSD: pte.h,v 1.17 2024/04/14 19:08:09 miod Exp $ */ +/* $NetBSD: pte.h,v 1.7 2001/07/31 06:55:46 eeh Exp $ */ + +/* + * Copyright (c) 1996-1999 Eduardo Horvath + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _MACHINE_PTE_H_ +#define _MACHINE_PTE_H_ + +/* virtual address to virtual page number */ +#define VA_SUN4U_VPG(va) (((int)(va) >> 13) & 31) + +/* virtual address to offset within page */ +#define VA_SUN4U_OFF(va) (((int)(va)) & 0x1FFF) + +/* When we go to 64-bit VAs we need to handle the hole */ +#define VA_VPG(va) VA_SUN4U_VPG(va) +#define VA_OFF(va) VA_SUN4U_OFF(va) + +#define PG_SHIFT4U 13 +#define MMU_PAGE_ALIGN 8192 + +/* If you know where a tte is in the tsb, how do you find its va? */ +#define TSBVA(i) ((tsb[(i)].tag.f.tag_va<<22)|(((i)<<13)&0x3ff000)) + +#ifndef _LOCORE +/* + * This is the spitfire TTE. + */ +#if 0 /* We don't use bitfields anyway. */ +struct sun4u_tag_fields { + u_int64_t tag_g:1, /* global flag */ + tag_ctxt:15, /* context for mapping */ + tag_unassigned:6, + tag_va:42; /* virtual address bits<64:22> */ +}; +union sun4u_tag { struct sun4u_tag_fields f; int64_t tag; }; +struct sun4u_data_fields { + u_int64_t data_v:1, /* valid bit */ + data_size:2, /* page size [8K*8**] */ + data_nfo:1, /* no-fault only */ + data_ie:1, /* invert endianness [inefficient] */ + data_soft2:2, /* reserved for S/W */ + data_pa:36, /* physical address */ + data_accessed:1,/* S/W accessed bit */ + data_modified:1,/* S/W modified bit */ + data_realw:1, /* S/W real writable bit (to manage modified) */ + data_tsblock:1, /* S/W TSB locked entry */ + data_exec:1, /* S/W Executable */ + data_onlyexec:1,/* S/W Executable only */ + data_lock:1, /* lock into TLB */ + data_cacheable:2, /* cacheability control */ + data_e:1, /* explicit accesses only */ + data_priv:1, /* privileged page */ + data_w:1, /* writeable */ + data_g:1; /* same as tag_g */ +}; +union sun4u_data { struct sun4u_data_fields f; int64_t data; }; +struct sun4u_tte { + union sun4u_tag tag; + union sun4u_data data; +}; +#else +struct sun4u_tte { + int64_t tag; + int64_t data; +}; +#endif +typedef struct sun4u_tte pte_t; + +/* Assembly routine to flush a mapping */ +extern void (*sp_tlb_flush_pte)(vaddr_t, uint64_t); +extern void (*sp_tlb_flush_ctx)(uint64_t); + +#if defined(MULTIPROCESSOR) +void smp_tlb_flush_pte(vaddr_t, uint64_t); +void smp_tlb_flush_ctx(uint64_t); +#define tlb_flush_pte(va,ctx) smp_tlb_flush_pte(va, ctx) +#define tlb_flush_ctx(ctx) smp_tlb_flush_ctx(ctx) +#else +#define tlb_flush_pte(va,ctx) (*sp_tlb_flush_pte)(va, ctx) +#define tlb_flush_ctx(ctx) (*sp_tlb_flush_ctx)(ctx) +#endif + +#endif /* _LOCORE */ + +/* TSB tag masks */ +#define CTX_MASK ((1<<13)-1) +#define TSB_TAG_CTX_SHIFT 48 +#define TSB_TAG_VA_SHIFT 22 + +#define TSB_TAG_LOCKED 0x0000040000000000LL + +#define TSB_TAG_G 0x8000000000000000LL +#define TSB_TAG_CTX(t) ((((int64_t)(t))>>TSB_TAG_CTX_SHIFT)&CTX_MASK) +#define TSB_TAG_VA(t) ((((int64_t)(t))<>TSB_TAG_VA_SHIFT)) + +/* Page sizes */ +#define PGSZ_8K 0 +#define PGSZ_64K 1 +#define PGSZ_512K 2 +#define PGSZ_4M 3 + +#define SUN4U_PGSZ_SHIFT 61 +#define SUN4U_TLB_SZ(s) (((uint64_t)(s)) << SUN4U_PGSZ_SHIFT) + +/* TLB data masks */ +#define SUN4U_TLB_V 0x8000000000000000LL +#define SUN4U_TLB_8K SUN4U_TLB_SZ(PGSZ_8K) +#define SUN4U_TLB_64K SUN4U_TLB_SZ(PGSZ_64K) +#define SUN4U_TLB_512K SUN4U_TLB_SZ(PGSZ_512K) +#define SUN4U_TLB_4M SUN4U_TLB_SZ(PGSZ_4M) +#define SUN4U_TLB_SZ_MASK 0x6000000000000000LL +#define SUN4U_TLB_NFO 0x1000000000000000LL +#define SUN4U_TLB_IE 0x0800000000000000LL +#define SUN4U_TLB_SOFT2_MASK 0x07fc000000000000LL +#define SUN4U_TLB_RESERVED_MASK 0x0003800000000000LL +#define SUN4U_TLB_PA_MASK 0x00007fffffffe000LL +#define SUN4U_TLB_SOFT_MASK 0x0000000000001f80LL +/* S/W bits */ +#define SUN4U_TLB_ACCESS 0x0000000000000200LL +#define SUN4U_TLB_MODIFY 0x0000000000000800LL +#define SUN4U_TLB_REAL_W 0x0000000000000400LL +#define SUN4U_TLB_TSB_LOCK 0x0000000000001000LL +#define SUN4U_TLB_EXEC 0x0000000000000100LL +#define SUN4U_TLB_EXEC_ONLY 0x0000000000000080LL +/* H/W bits */ +#define SUN4U_TLB_L 0x0000000000000040LL +#define SUN4U_TLB_CACHE_MASK 0x0000000000000030LL +#define SUN4U_TLB_CP 0x0000000000000020LL +#define SUN4U_TLB_CV 0x0000000000000010LL +#define SUN4U_TLB_E 0x0000000000000008LL +#define SUN4U_TLB_P 0x0000000000000004LL +#define SUN4U_TLB_W 0x0000000000000002LL +#define SUN4U_TLB_G 0x0000000000000001LL + +#define SUN4U_TSB_DATA(g,sz,pa,priv,write,cache,aliased,valid,ie) \ +(((valid)?SUN4U_TLB_V:0LL)|SUN4U_TLB_SZ(sz)|\ +(((u_int64_t)(pa))&SUN4U_TLB_PA_MASK)|\ +((cache)?((aliased)?SUN4U_TLB_CP:SUN4U_TLB_CACHE_MASK):SUN4U_TLB_E)|\ +((priv)?SUN4U_TLB_P:0LL)|((write)?SUN4U_TLB_W:0LL)|((g)?SUN4U_TLB_G:0LL)|\ +((ie)?SUN4U_TLB_IE:0LL)) + +#define SUN4V_PGSZ_SHIFT 0 +#define SUN4V_TLB_SZ(s) (((uint64_t)(s))<rb_bt, (addr), (size), (flags), (hp)) +#define md_space_unmap(rbt, h, size, addrp) \ + do { \ + *addrp = (rbt)->rb_bt->sparc_bus_addr((rbt)->rb_bt, \ + (rbt)->rb_bt, (h)); \ + bus_space_unmap((rbt)->rb_bt, (h), (size)); \ + } while (0) + +void pccbb_attach_hook(struct device *, struct device *, + struct pci_attach_args *); + +#endif /* _MACHINE_RBUS_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/reg.h b/lib/libc/include/sparc64-openbsd-none/sparc64/reg.h new file mode 100644 index 000000000000..cd4dc0304dce --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/reg.h @@ -0,0 +1,92 @@ +/* $OpenBSD: reg.h,v 1.9 2024/03/29 21:14:31 miod Exp $ */ +/* $NetBSD: reg.h,v 1.8 2001/06/19 12:59:16 wiz Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)reg.h 8.1 (Berkeley) 6/11/93 + */ + +#ifndef _MACHINE_REG_H_ +#define _MACHINE_REG_H_ + +/* + * The v9 register window. Each stack pointer (%o6 aka %sp) in each window + * must ALWAYS point to some place at which it is safe to scribble on + * 64 bytes. (If not, your process gets mangled.) Furthermore, each + * stack pointer should be aligned on a 16-byte boundary (plus the BIAS) + * for v9 stacks (the kernel as currently coded allows arbitrary alignment, + * but with a hefty performance penalty). + */ +struct rwindow { + int64_t rw_local[8]; /* %l0..%l7 */ + int64_t rw_in[8]; /* %i0..%i7 */ +}; + +struct reg { + int64_t r_tstate; /* tstate register */ + int64_t r_pc; /* return pc */ + int64_t r_npc; /* return npc */ + int r_y; /* %y register -- 32-bits */ + int64_t r_global[8]; /* %g* registers in trap's caller */ + int64_t r_out[8]; /* %o* registers in trap's caller */ + int64_t r_local[8]; /* %l* registers in trap's caller */ + int64_t r_in[8]; /* %i* registers in trap's caller */ +}; + +/* + * FP coprocessor registers. + */ + +struct fpstate { + u_int fs_regs[64]; /* our view is 64 32-bit registers */ + int64_t fs_fsr; /* %fsr */ + int fs_gsr; /* graphics state reg */ +}; + +/* + * The actual FP registers are made accessible (c.f. ptrace(2)) through + * a `struct fpreg'; relies on the + * fact that `fpreg' is a prefix of `fpstate'. + */ +struct fpreg { + u_int fr_regs[64]; /* our view is 64 32-bit registers */ + int64_t fr_fsr; /* %fsr */ + int fr_gsr; /* graphics state reg */ +}; + +#endif /* _MACHINE_REG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/reloc.h b/lib/libc/include/sparc64-openbsd-none/sparc64/reloc.h new file mode 100644 index 000000000000..6e23309ed504 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/reloc.h @@ -0,0 +1,36 @@ +/* $OpenBSD: reloc.h,v 1.5 2011/03/23 16:54:37 pirofti Exp $ */ +/* + * Copyright (c) 2001 Artur Grabowski + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_RELOC_H_ +#define _MACHINE_RELOC_H_ + +#define RELOC_NONE 0 + +#define RELOC_COPY 19 +#define RELOC_GLOB_DAT 20 +#define RELOC_JMP_SLOT 21 +#define RELOC_RELATIVE 22 +#define RELOC_64 32 +#define RELOC_UA64 54 +#define RELOC_TLS_DTPMOD32 74 +#define RELOC_TLS_DTPMOD64 75 +#define RELOC_TLS_DTPOFF32 76 +#define RELOC_TLS_DTPOFF64 77 +#define RELOC_TLS_TPOFF32 78 +#define RELOC_TLS_TPOFF64 79 + +#endif /* _MACHINE_RELOC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/setjmp.h b/lib/libc/include/sparc64-openbsd-none/sparc64/setjmp.h new file mode 100644 index 000000000000..54523bed4344 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/setjmp.h @@ -0,0 +1,7 @@ +/* $OpenBSD: setjmp.h,v 1.1 2001/08/23 15:32:01 art Exp $ */ + +/* + * machine/setjmp.h: machine dependent setjmp-related information. + */ + +#define _JBLEN 14 /* size, in longs, of a jmp_buf */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/signal.h b/lib/libc/include/sparc64-openbsd-none/sparc64/signal.h new file mode 100644 index 000000000000..e94d2341af48 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/signal.h @@ -0,0 +1,87 @@ +/* $OpenBSD: signal.h,v 1.13 2024/03/29 21:16:38 miod Exp $ */ +/* $NetBSD: signal.h,v 1.10 2001/05/09 19:50:49 kleink Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)signal.h 8.1 (Berkeley) 6/11/93 + */ + +#ifndef _MACHINE_SIGNAL_H_ +#define _MACHINE_SIGNAL_H_ + +#include + +typedef int sig_atomic_t; + +#if __BSD_VISIBLE || __XPG_VISIBLE >= 420 +/* + * Information pushed on stack when a signal is delivered. + * This is used by the kernel to restore state following + * execution of the signal handler. It is also made available + * to the handler to allow it to restore state properly if + * a non-standard exit is performed. + */ +struct sigcontext { + long sc_cookie; + /* begin machine dependent portion */ + long sc_sp; /* %sp to restore */ + long sc_pc; /* pc to restore */ + long sc_npc; /* npc to restore */ + long sc_tstate; /* tstate to restore */ + long sc_g1; /* %g1 to restore */ + long sc_o0; /* %o0 to restore */ + int sc_mask; /* signal mask to restore */ +}; +#endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ + +#if defined(_KERNEL) +/* + * `Code' arguments to signal handlers. The names, and the funny numbering. + * are defined so as to match up with what SunOS uses; I have no idea why + * they did the numbers that way, except maybe to match up with the 68881. + */ +#define FPE_INTOVF_TRAP 0x01 /* integer overflow */ +#define FPE_INTDIV_TRAP 0x14 /* integer divide by zero */ +#define FPE_FLTINEX_TRAP 0xc4 /* inexact */ +#define FPE_FLTDIV_TRAP 0xc8 /* divide by zero */ +#define FPE_FLTUND_TRAP 0xcc /* underflow */ +#define FPE_FLTOPERR_TRAP 0xd0 /* operand error */ +#define FPE_FLTOVF_TRAP 0xd4 /* overflow */ +#endif + +#endif /* !_MACHINE_SIGNAL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/sparc64.h b/lib/libc/include/sparc64-openbsd-none/sparc64/sparc64.h new file mode 100644 index 000000000000..16b33d5f7759 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/sparc64.h @@ -0,0 +1,65 @@ +/* $OpenBSD: sparc64.h,v 1.14 2018/08/28 00:00:42 dlg Exp $ */ +/* $NetBSD: sparc64.h,v 1.3 2000/10/20 05:47:03 mrg Exp $ */ + +/* + * Copyright (C) 1996 Wolfgang Solfrank. + * Copyright (C) 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _MACHINE_SPARC64_H_ +#define _MACHINE_SPARC64_H_ + +struct mem_region { + u_int64_t start; + u_int64_t size; +}; + +int prom_set_trap_table(vaddr_t tba, paddr_t mmfsa); +paddr_t prom_vtop(vaddr_t vaddr); +vaddr_t prom_claim_virt(vaddr_t vaddr, int len); +vaddr_t prom_alloc_virt(int len, int align); +int prom_free_virt(vaddr_t vaddr, int len); +int prom_unmap_virt(vaddr_t vaddr, int len); +int prom_map_phys(paddr_t paddr, off_t size, vaddr_t vaddr, int mode); +paddr_t prom_alloc_phys(int len, int align); +paddr_t prom_claim_phys(paddr_t phys, int len); +int prom_free_phys(paddr_t paddr, int len); +paddr_t prom_get_msgbuf(int len, int align); +int prom_itlb_load(int index, u_int64_t data, vaddr_t vaddr); +int prom_dtlb_load(int index, u_int64_t data, vaddr_t vaddr); +void prom_start_cpu(int cpu, void *func, long arg); +void prom_start_cpu_by_cpuid(int cpu, void *func, long arg); +const char *prom_serengeti_set_console_input(const char *); +uint64_t prom_set_sun4v_api_version(uint64_t, uint64_t, uint64_t, uint64_t *); +void prom_sun4v_soft_state_supported(void); + +/* + * Debug + */ +void prom_printf(const char *, ...); +#endif /* _MACHINE_SPARC64_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/spinlock.h b/lib/libc/include/sparc64-openbsd-none/sparc64/spinlock.h new file mode 100644 index 000000000000..4a30761476a9 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/spinlock.h @@ -0,0 +1,10 @@ +/* $OpenBSD: spinlock.h,v 1.3 2017/09/05 02:40:54 guenther Exp $ */ + +#ifndef _MACHINE_SPINLOCK_H_ +#define _MACHINE_SPINLOCK_H_ + +#define _ATOMIC_LOCK_UNLOCKED (0x00) +#define _ATOMIC_LOCK_LOCKED (0xFF) +typedef unsigned char _atomic_lock_t; + +#endif \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/tcb.h b/lib/libc/include/sparc64-openbsd-none/sparc64/tcb.h new file mode 100644 index 000000000000..a5d8911686af --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/tcb.h @@ -0,0 +1,44 @@ +/* $OpenBSD: tcb.h,v 1.7 2017/04/20 10:03:40 kettenis Exp $ */ + +/* + * Copyright (c) 2011 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TCB_H_ +#define _MACHINE_TCB_H_ + +#ifdef _KERNEL + +#include + +/* + * In userspace, register %g7 contains the address of the thread's TCB + */ +#define TCB_GET(p) \ + ((void *)(p)->p_md.md_tf->tf_global[7]) +#define TCB_SET(p, addr) \ + ((p)->p_md.md_tf->tf_global[7] = (int64_t)(addr)) + +#else /* _KERNEL */ + +/* ELF TLS ABI calls for big TCB, with static TLS data at negative offsets */ +#define TLS_VARIANT 2 + +register void *__tcb __asm__ ("g7"); +#define TCB_GET() (__tcb) +#define TCB_SET(tcb) ((__tcb) = (tcb)) + +#endif /* _KERNEL */ +#endif /* _MACHINE_TCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/timetc.h b/lib/libc/include/sparc64-openbsd-none/sparc64/timetc.h new file mode 100644 index 000000000000..7ae3900f527d --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/timetc.h @@ -0,0 +1,24 @@ +/* $OpenBSD: timetc.h,v 1.2 2020/07/08 09:20:28 kettenis Exp $ */ +/* + * Copyright (c) 2020 Paul Irofti + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TIMETC_H_ +#define _MACHINE_TIMETC_H_ + +#define TC_TICK 1 +#define TC_SYS_TICK 2 + +#endif /* _MACHINE_TIMETC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/trap.h b/lib/libc/include/sparc64-openbsd-none/sparc64/trap.h new file mode 100644 index 000000000000..2b7f57bdaf49 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/trap.h @@ -0,0 +1,159 @@ +/* $OpenBSD: trap.h,v 1.5 2013/04/02 13:24:57 kettenis Exp $ */ +/* $NetBSD: trap.h,v 1.4 1999/06/07 05:28:04 eeh Exp $ */ + +/* + * Copyright (c) 1996-1999 Eduardo Horvath + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + + +#ifndef _MACHINE_TRAP_H +#define _MACHINE_TRAP_H + +/* trap vec (pri) description */ +/* 0x000 unused */ +#define T_POR 0x001 /* (0) power on reset */ +#define T_WDR 0x002 /* (1) watchdog reset */ +#define T_XIR 0x003 /* (1) externally initiated reset */ +#define T_SIR 0x004 /* (1) software initiated reset */ +#define T_RED_EXCEPTION 0x005 /* (1) RED state exception */ +/* 0x006 unused */ +/* 0x007 unused */ +#define T_INST_EXCEPT 0x008 /* (5) instruction access exception */ +#define T_TEXTFAULT 0x009 /* (2) ? Text fault */ +#define T_INST_ERROR 0x00a /* (3) instruction access error */ +/* 0x00b unused */ +/* through 0x00f unused */ +#define T_ILLINST 0x010 /* (7) illegal instruction */ +#define T_PRIVINST 0x011 /* (6) privileged opcode */ +#define T_UNIMP_LDD 0x012 /* (6) unimplemented LDD */ +#define T_UNIMP_STD 0x013 /* (6) unimplemented STD */ +/* 0x014 unused */ +/* through 0x01f unused */ +#define T_FPDISABLED 0x020 /* (8) fpu disabled */ +#define T_FP_IEEE_754 0x021 /* (11) ieee 754 exception */ +#define T_FP_OTHER 0x022 /* (11) other fp exception */ +#define T_TAGOF 0x023 /* (14) tag overflow */ +#define T_CLEAN_WINDOW 0x024 /* (10) clean window exception */ +/* 0x025 unused */ +/* through 0x027 unused */ +#define T_DIV0 0x028 /* (15) division routine was handed 0 */ +#define T_PROCERR 0x029 /* (4) internal processor error */ +/* 0x02a unused */ +/* through 0x02f unused */ +#define T_DATAFAULT 0x030 /* (12) address fault during data fetch */ +#define T_DATA_MMU_MISS 0x031 /* (12) data access MMU miss */ +#define T_DATA_ERROR 0x032 /* (12) data access error */ +#define T_DATA_PROT 0x033 /* (12) Data protection ??? */ +#define T_ALIGN 0x034 /* (10) address not properly aligned */ +#define T_LDDF_ALIGN 0x035 /* (10) LDDF address not properly aligned */ +#define T_STDF_ALIGN 0x036 /* (10) STDF address not properly aligned */ +#define T_PRIVACT 0x037 /* (11) privileged action */ +#define T_LDQF_ALIGN 0x038 /* (10) LDQF address not properly aligned */ +#define T_STQF_ALIGN 0x039 /* (10) STQF address not properly aligned */ +/* 0x03a unused */ +/* through 0x03f unused */ +#define T_ASYNC_ERROR 0x040 /* (2) ???? */ +#define T_L1INT 0x041 /* (31) level 1 interrupt */ +#define T_L2INT 0x042 /* (30) level 2 interrupt */ +#define T_L3INT 0x043 /* (29) level 3 interrupt */ +#define T_L4INT 0x044 /* (28) level 4 interrupt */ +#define T_L5INT 0x045 /* (27) level 5 interrupt */ +#define T_L6INT 0x046 /* (26) level 6 interrupt */ +#define T_L7INT 0x047 /* (25) level 7 interrupt */ +#define T_L8INT 0x048 /* (24) level 8 interrupt */ +#define T_L9INT 0x049 /* (23) level 9 interrupt */ +#define T_L10INT 0x04a /* (22) level 10 interrupt */ +#define T_L11INT 0x04b /* (21) level 11 interrupt */ +#define T_L12INT 0x04c /* (20) level 12 interrupt */ +#define T_L13INT 0x04d /* (19) level 13 interrupt */ +#define T_L14INT 0x04e /* (18) level 14 interrupt */ +#define T_L15INT 0x04f /* (17) level 15 interrupt */ +/* 0x050 unused */ +/* through 0x05f unused */ +#define T_INTVEC 0x060 /* (16) interrupt vector [Interrupt Global Regs]*/ +#define T_PA_WATCHPT 0x061 /* (12) Physical addr data watchpoint */ +#define T_VA_WATCHPT 0x062 /* (11) Virtual addr data watchpoint */ +#define T_ECCERR 0x063 /* (33) ECC correction error */ +#define T_FIMMU_MISS 0x064 /* (2) fast instruction access MMU miss */ +/* through 0x067 unused */ +#define T_FDMMU_MISS 0x068 /* (2) fast data access MMU miss */ +/* through 0x06b unused */ +#define T_FDMMU_PROT 0x06c /* (2) fast data access protection */ +/* through 0x06f unused */ +/* 0x070...0x07f implementation dependent exceptions */ +#define T_SPILL_N_NORM 0x080 /* (9) spill (n=0..7) normal */ +/* through 0x09f unused */ +#define T_SPILL_N_OTHER 0x0a0 /* (9) spill (n=0..7) other */ +/* through 0x0bf unused */ +#define T_FILL_N_NORM 0x0c0 /* (9) fill (n=0..7) normal */ +/* through 0x0df unused */ +#define T_FILL_N_OTHER 0x0e0 /* (9) fill (n=0..7) other */ +/* through 0x0ff unused */ + +/* beginning of `user' vectors (from trap instructions) - all priority 16 */ +#define T_SUN_SYSCALL 0x100 /* system call */ +#define T_BREAKPOINT 0x101 /* breakpoint `instruction' */ +#define T_UDIV0 0x102 /* division routine was handed 0 */ +#define T_FLUSHWIN 0x103 /* flush windows */ +#define T_CLEANWIN 0x104 /* provide clean windows */ +#define T_RANGECHECK 0x105 /* ? */ +#define T_FIXALIGN 0x106 /* fix up unaligned accesses */ +#define T_INTOF 0x107 /* integer overflow ? */ +#define T_SVR4_SYSCALL 0x108 /* SVR4 system call */ +#define T_BSD_SYSCALL 0x109 /* BSD system call */ +#define T_KGDB_EXEC 0x10a /* for kernel gdb */ + +/* 0x10b..0x1ff are currently unallocated, except the following */ +#define T_SVR4_GETCC 0x120 +#define T_SVR4_SETCC 0x121 +#define T_SVR4_GETPSR 0x122 +#define T_SVR4_SETPSR 0x123 +#define T_SVR4_GETHRTIME 0x124 +#define T_SVR4_GETHRVTIME 0x125 +#define T_SVR4_GETHRESTIME 0x127 +#define T_GETCC 0x132 +#define T_SETCC 0x133 +#define T_SVID_SYSCALL 0x164 +#define T_SPARC_INTL_SYSCALL 0x165 +#define T_OS_VENDOR_SYSCALL 0x166 +#define T_HW_OEM_SYSCALL 0x167 +#define T_RTF_DEF_TRAP 0x168 +#define T_MON_BREAKPOINT 0x17f + +#ifdef _KERNEL /* pseudo traps for locore.s */ +#define T_RWRET -1 /* need first user window for trap return */ +#define T_AST -2 /* no-op, just needed reschedule or profile */ +#endif + +/* flags to system call (flags in %g1 along with syscall number) */ +#define SYSCALL_G2RFLAG 0x400 /* on success, return to %g2 rather than npc */ + +/* + * `software trap' macros to keep people happy (sparc v8 manual says not + * to set the upper bits). + */ +#define ST_BREAKPOINT (T_BREAKPOINT & 0x7f) +#define ST_DIV0 (T_DIV0 & 0x7f) +#define ST_FLUSHWIN (T_FLUSHWIN & 0x7f) +#define ST_SYSCALL (T_SUN_SYSCALL & 0x7f) + +#endif /* _MACHINE_TRAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/vmparam.h b/lib/libc/include/sparc64-openbsd-none/sparc64/vmparam.h new file mode 100644 index 000000000000..4a3d2ed36cd1 --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/vmparam.h @@ -0,0 +1,124 @@ +/* $OpenBSD: vmparam.h,v 1.35 2024/03/29 21:06:14 miod Exp $ */ +/* $NetBSD: vmparam.h,v 1.18 2001/05/01 02:19:19 thorpej Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vmparam.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * Machine dependent constants for sun4u and sun4v UltraSPARC + */ + +#ifndef VMPARAM_H +#define VMPARAM_H + +#define USRSTACK 0xffffffffffffe000L + +/* + * Virtual memory related constants, all in bytes + */ +/* + * Since the compiler generates `call' instructions we can't + * have more than 4GB in a single text segment. + * + * And since we only have a 40-bit address space, allow half + * of that for data and the other half for stack. + */ +#ifndef MAXTSIZ +#define MAXTSIZ (1L*1024*1024*1024) /* max text size */ +#endif +#ifndef DFLDSIZ +#define DFLDSIZ (128L*1024*1024) /* initial data size limit */ +#endif +#ifndef MAXDSIZ +#define MAXDSIZ (8L*1024*1024*1024) /* max data size */ +#endif +#ifndef BRKSIZ +#define BRKSIZ MAXDSIZ /* heap gap size */ +#endif +#ifndef DFLSSIZ +#define DFLSSIZ (2L*1024*1024) /* initial stack size limit */ +#endif +#ifndef MAXSSIZ +#define MAXSSIZ (32L*1024*1024) /* max stack size */ +#endif + +#define STACKGAP_RANDOM 256*1024 + +/* + * Size of shared memory map + */ +#ifndef SHMMAXPGS +#define SHMMAXPGS 4096 /* 32mb */ +#endif + +/* + * Size of User Raw I/O map + */ +#define USRIOSIZE 300 + +/* + * Mach derived constants + */ + +/* + * User/kernel map constants. + */ +#define VM_MIN_ADDRESS ((vaddr_t)PAGE_SIZE) +#define VM_MAX_ADDRESS ((vaddr_t)-1) +#define VM_MAXUSER_ADDRESS ((vaddr_t)-PAGE_SIZE) +#ifdef _KERNEL +#define VM_MIN_STACK_ADDRESS ((vaddr_t)0xfffffe0000000000L) +#endif + +/* map PIE into the first quarter of the address space before hole */ +#define VM_PIE_MIN_ADDR PAGE_SIZE +#define VM_PIE_MAX_ADDR 0x10000000000 + +#define VM_MIN_KERNEL_ADDRESS ((vaddr_t)KERNBASE) +#define VM_MAX_KERNEL_ADDRESS ((vaddr_t)0x000007ffffffffffL) + +/* virtual sizes (bytes) for various kernel submaps */ +#define VM_PHYS_SIZE (USRIOSIZE*PAGE_SIZE) + +#define VM_PHYSSEG_MAX 32 /* up to 32 segments */ +#define VM_PHYSSEG_STRAT VM_PSTRAT_BSEARCH +#define VM_PHYSSEG_NOADD /* can't add RAM after vm_mem_init */ + +#endif \ No newline at end of file diff --git a/lib/libc/include/sparc64-openbsd-none/sparc64/z8530var.h b/lib/libc/include/sparc64-openbsd-none/sparc64/z8530var.h new file mode 100644 index 000000000000..9439d8e8f52b --- /dev/null +++ b/lib/libc/include/sparc64-openbsd-none/sparc64/z8530var.h @@ -0,0 +1,80 @@ +/* $OpenBSD: z8530var.h,v 1.9 2024/03/29 21:17:13 miod Exp $ */ +/* $NetBSD: z8530var.h,v 1.4 2000/11/08 23:41:42 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)zsvar.h 8.1 (Berkeley) 6/11/93 + */ + +#include +#include + +struct zsc_softc { + struct device zsc_dev; /* base device */ + bus_space_tag_t zsc_bustag; /* bus space/dma tags */ + bus_dma_tag_t zsc_dmatag; + struct zs_chanstate *zsc_cs[2]; /* channel A and B soft state */ + + /* Machine-dependent part follows... */ + void *zsc_softintr; + int zsc_promunit; /* PROM's view of zs devices */ + int zsc_node; /* PROM node, if any */ + struct zs_chanstate zsc_cs_store[2]; +}; + +/* + * Functions to read and write individual registers in a channel. + * The ZS chip requires a 1.6 uSec. recovery time between accesses. + * On sparc64, the recovery time is handled in hardware. + */ + +u_char zs_read_reg(struct zs_chanstate *cs, u_char reg); +u_char zs_read_csr(struct zs_chanstate *cs); +u_char zs_read_data(struct zs_chanstate *cs); + +void zs_write_reg(struct zs_chanstate *cs, u_char reg, u_char val); +void zs_write_csr(struct zs_chanstate *cs, u_char val); +void zs_write_data(struct zs_chanstate *cs, u_char val); + +/* The sparc has splzs() in psl.h */ + +/* We want to call it "zs" instead of "zsc" (sigh). */ +#ifndef ZSCCF_CHANNEL +#define ZSCCF_CHANNEL 0 +#define ZSCCF_CHANNEL_DEFAULT -1 +#endif \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/fenv.h b/lib/libc/include/x86-freebsd-none/fenv.h deleted file mode 100644 index 3f511b649c27..000000000000 --- a/lib/libc/include/x86-freebsd-none/fenv.h +++ /dev/null @@ -1,348 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2004-2005 David Schultz - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _FENV_H_ -#define _FENV_H_ - -#include -#include -#include - -#ifndef __fenv_static -#define __fenv_static static -#endif - -typedef __uint16_t fexcept_t; - -/* Exception flags */ -#define FE_INVALID 0x01 -#define FE_DENORMAL 0x02 -#define FE_DIVBYZERO 0x04 -#define FE_OVERFLOW 0x08 -#define FE_UNDERFLOW 0x10 -#define FE_INEXACT 0x20 -#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_DENORMAL | FE_INEXACT | \ - FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) - -/* Rounding modes */ -#define FE_TONEAREST 0x0000 -#define FE_DOWNWARD 0x0400 -#define FE_UPWARD 0x0800 -#define FE_TOWARDZERO 0x0c00 -#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ - FE_UPWARD | FE_TOWARDZERO) - -/* - * As compared to the x87 control word, the SSE unit's control word - * has the rounding control bits offset by 3 and the exception mask - * bits offset by 7. - */ -#define _SSE_ROUND_SHIFT 3 -#define _SSE_EMASK_SHIFT 7 - -#ifdef __i386__ -/* - * To preserve binary compatibility with FreeBSD 5.3, we pack the - * mxcsr into some reserved fields, rather than changing sizeof(fenv_t). - */ -typedef struct { - __uint16_t __control; - __uint16_t __mxcsr_hi; - __uint16_t __status; - __uint16_t __mxcsr_lo; - __uint32_t __tag; - char __other[16]; -} fenv_t; -#else /* __amd64__ */ -typedef struct { - struct { - __uint32_t __control; - __uint32_t __status; - __uint32_t __tag; - char __other[16]; - } __x87; - __uint32_t __mxcsr; -} fenv_t; -#endif /* __i386__ */ - -__BEGIN_DECLS - -/* Default floating-point environment */ -extern const fenv_t __fe_dfl_env; -#define FE_DFL_ENV (&__fe_dfl_env) - -#define __fldenvx(__env) __asm __volatile("fldenv %0" : : "m" (__env) \ - : "st", "st(1)", "st(2)", "st(3)", "st(4)", \ - "st(5)", "st(6)", "st(7)") -#define __fwait() __asm __volatile("fwait") - -int fegetenv(fenv_t *__envp); -int feholdexcept(fenv_t *__envp); -int fesetexceptflag(const fexcept_t *__flagp, int __excepts); -int feraiseexcept(int __excepts); -int feupdateenv(const fenv_t *__envp); - -__fenv_static inline int -fegetround(void) -{ - __uint16_t __control; - - /* - * We assume that the x87 and the SSE unit agree on the - * rounding mode. Reading the control word on the x87 turns - * out to be about 5 times faster than reading it on the SSE - * unit on an Opteron 244. - */ - __fnstcw(&__control); - return (__control & _ROUND_MASK); -} - -#if __BSD_VISIBLE - -int feenableexcept(int __mask); -int fedisableexcept(int __mask); - -/* We currently provide no external definition of fegetexcept(). */ -static inline int -fegetexcept(void) -{ - __uint16_t __control; - - /* - * We assume that the masks for the x87 and the SSE unit are - * the same. - */ - __fnstcw(&__control); - return (~__control & FE_ALL_EXCEPT); -} - -#endif /* __BSD_VISIBLE */ - -#ifdef __i386__ - -/* After testing for SSE support once, we cache the result in __has_sse. */ -enum __sse_support { __SSE_YES, __SSE_NO, __SSE_UNK }; -extern enum __sse_support __has_sse; -int __test_sse(void); -#ifdef __SSE__ -#define __HAS_SSE() 1 -#else -#define __HAS_SSE() (__has_sse == __SSE_YES || \ - (__has_sse == __SSE_UNK && __test_sse())) -#endif - -#define __get_mxcsr(env) (((env).__mxcsr_hi << 16) | \ - ((env).__mxcsr_lo)) -#define __set_mxcsr(env, x) do { \ - (env).__mxcsr_hi = (__uint32_t)(x) >> 16; \ - (env).__mxcsr_lo = (__uint16_t)(x); \ -} while (0) - -__fenv_static inline int -feclearexcept(int __excepts) -{ - fenv_t __env; - __uint32_t __mxcsr; - - if (__excepts == FE_ALL_EXCEPT) { - __fnclex(); - } else { - __fnstenv(&__env); - __env.__status &= ~__excepts; - __fldenv(&__env); - } - if (__HAS_SSE()) { - __stmxcsr(&__mxcsr); - __mxcsr &= ~__excepts; - __ldmxcsr(&__mxcsr); - } - return (0); -} - -__fenv_static inline int -fegetexceptflag(fexcept_t *__flagp, int __excepts) -{ - __uint32_t __mxcsr; - __uint16_t __status; - - __fnstsw(&__status); - if (__HAS_SSE()) - __stmxcsr(&__mxcsr); - else - __mxcsr = 0; - *__flagp = (__mxcsr | __status) & __excepts; - return (0); -} - -__fenv_static inline int -fetestexcept(int __excepts) -{ - __uint32_t __mxcsr; - __uint16_t __status; - - __fnstsw(&__status); - if (__HAS_SSE()) - __stmxcsr(&__mxcsr); - else - __mxcsr = 0; - return ((__status | __mxcsr) & __excepts); -} - -__fenv_static inline int -fesetround(int __round) -{ - __uint32_t __mxcsr; - __uint16_t __control; - - if (__round & ~_ROUND_MASK) - return (-1); - - __fnstcw(&__control); - __control &= ~_ROUND_MASK; - __control |= __round; - __fldcw(&__control); - - if (__HAS_SSE()) { - __stmxcsr(&__mxcsr); - __mxcsr &= ~(_ROUND_MASK << _SSE_ROUND_SHIFT); - __mxcsr |= __round << _SSE_ROUND_SHIFT; - __ldmxcsr(&__mxcsr); - } - - return (0); -} - -__fenv_static inline int -fesetenv(const fenv_t *__envp) -{ - fenv_t __env = *__envp; - __uint32_t __mxcsr; - - __mxcsr = __get_mxcsr(__env); - __set_mxcsr(__env, 0xffffffff); - /* - * XXX Using fldenvx() instead of fldenv() tells the compiler that this - * instruction clobbers the i387 register stack. This happens because - * we restore the tag word from the saved environment. Normally, this - * would happen anyway and we wouldn't care, because the ABI allows - * function calls to clobber the i387 regs. However, fesetenv() is - * inlined, so we need to be more careful. - */ - __fldenvx(__env); - if (__HAS_SSE()) - __ldmxcsr(&__mxcsr); - return (0); -} - -#else /* __amd64__ */ - -__fenv_static inline int -feclearexcept(int __excepts) -{ - fenv_t __env; - - if (__excepts == FE_ALL_EXCEPT) { - __fnclex(); - } else { - __fnstenv(&__env.__x87); - __env.__x87.__status &= ~__excepts; - __fldenv(&__env.__x87); - } - __stmxcsr(&__env.__mxcsr); - __env.__mxcsr &= ~__excepts; - __ldmxcsr(&__env.__mxcsr); - return (0); -} - -__fenv_static inline int -fegetexceptflag(fexcept_t *__flagp, int __excepts) -{ - __uint32_t __mxcsr; - __uint16_t __status; - - __stmxcsr(&__mxcsr); - __fnstsw(&__status); - *__flagp = (__mxcsr | __status) & __excepts; - return (0); -} - -__fenv_static inline int -fetestexcept(int __excepts) -{ - __uint32_t __mxcsr; - __uint16_t __status; - - __stmxcsr(&__mxcsr); - __fnstsw(&__status); - return ((__status | __mxcsr) & __excepts); -} - -__fenv_static inline int -fesetround(int __round) -{ - __uint32_t __mxcsr; - __uint16_t __control; - - if (__round & ~_ROUND_MASK) - return (-1); - - __fnstcw(&__control); - __control &= ~_ROUND_MASK; - __control |= __round; - __fldcw(&__control); - - __stmxcsr(&__mxcsr); - __mxcsr &= ~(_ROUND_MASK << _SSE_ROUND_SHIFT); - __mxcsr |= __round << _SSE_ROUND_SHIFT; - __ldmxcsr(&__mxcsr); - - return (0); -} - -__fenv_static inline int -fesetenv(const fenv_t *__envp) -{ - - /* - * XXX Using fldenvx() instead of fldenv() tells the compiler that this - * instruction clobbers the i387 register stack. This happens because - * we restore the tag word from the saved environment. Normally, this - * would happen anyway and we wouldn't care, because the ABI allows - * function calls to clobber the i387 regs. However, fesetenv() is - * inlined, so we need to be more careful. - */ - __fldenvx(__envp->__x87); - __ldmxcsr(&__envp->__mxcsr); - return (0); -} - -#endif /* __i386__ */ - -__END_DECLS - -#endif /* !_FENV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/float.h b/lib/libc/include/x86-freebsd-none/float.h deleted file mode 100644 index 0e6d11c8c393..000000000000 --- a/lib/libc/include/x86-freebsd-none/float.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/floatingpoint.h b/lib/libc/include/x86-freebsd-none/floatingpoint.h deleted file mode 100644 index 134415f2e6e7..000000000000 --- a/lib/libc/include/x86-freebsd-none/floatingpoint.h +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 1993 Andrew Moore, Talke Studio - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#) floatingpoint.h 1.0 (Berkeley) 9/23/93 - */ - -#ifndef _FLOATINGPOINT_H_ -#define _FLOATINGPOINT_H_ - -#include -#include - -#endif /* !_FLOATINGPOINT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/_align.h b/lib/libc/include/x86-freebsd-none/machine/_align.h deleted file mode 100644 index 4af6dd67a7aa..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/_align.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/_bus.h b/lib/libc/include/x86-freebsd-none/machine/_bus.h index d244b86af3b7..5f916269fece 100644 --- a/lib/libc/include/x86-freebsd-none/machine/_bus.h +++ b/lib/libc/include/x86-freebsd-none/machine/_bus.h @@ -1,30 +1,13 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2005 M. Warner Losh + * Copyright (c) 2005 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, - * without modification, immediately at the beginning of the file. - * 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. + * SPDX-License-Identifier: BSD-2-Clause * - * 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. + * Derived in part from NetBSD's bus.h files by (alphabetically): + * Christopher G. Demetriou + * Charles M. Hannum + * Jason Thorpe + * The NetBSD Foundation. */ #ifndef I386_INCLUDE__BUS_H diff --git a/lib/libc/include/x86-freebsd-none/machine/_inttypes.h b/lib/libc/include/x86-freebsd-none/machine/_inttypes.h deleted file mode 100644 index 218f00871b16..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/_inttypes.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/_limits.h b/lib/libc/include/x86-freebsd-none/machine/_limits.h deleted file mode 100644 index 71d8b62434e1..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/_limits.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/_stdint.h b/lib/libc/include/x86-freebsd-none/machine/_stdint.h deleted file mode 100644 index 4fb2b3fb4ada..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/_stdint.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/_types.h b/lib/libc/include/x86-freebsd-none/machine/_types.h deleted file mode 100644 index da8cb16909c4..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/_types.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/asm.h b/lib/libc/include/x86-freebsd-none/machine/asm.h index c51c45ae7212..7a0b90fc1d4c 100644 --- a/lib/libc/include/x86-freebsd-none/machine/asm.h +++ b/lib/libc/include/x86-freebsd-none/machine/asm.h @@ -30,8 +30,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)DEFS.h 5.1 (Berkeley) 4/23/90 */ #ifndef _MACHINE_ASM_H_ diff --git a/lib/libc/include/x86-freebsd-none/machine/atomic.h b/lib/libc/include/x86-freebsd-none/machine/atomic.h index 3211d15efae7..63143fe5a35a 100644 --- a/lib/libc/include/x86-freebsd-none/machine/atomic.h +++ b/lib/libc/include/x86-freebsd-none/machine/atomic.h @@ -49,8 +49,8 @@ static __inline void __mbk(void) { - __asm __volatile("lock; addl $0,%%fs:%0" - : "+m" (*(u_int *)__OFFSETOF_MONITORBUF) : : "memory", "cc"); + __asm __volatile("lock; addl $0,%%fs:%c0" + : : "i" (__OFFSETOF_MONITORBUF) : "memory", "cc"); } static __inline void @@ -249,7 +249,7 @@ atomic_testandclear_int(volatile u_int *p, u_int v) #define ATOMIC_LOAD(TYPE) \ static __inline u_##TYPE \ -atomic_load_acq_##TYPE(volatile u_##TYPE *p) \ +atomic_load_acq_##TYPE(const volatile u_##TYPE *p) \ { \ u_##TYPE res; \ \ @@ -299,17 +299,6 @@ atomic_thread_fence_seq_cst(void) #ifdef _KERNEL -#ifdef WANT_FUNCTIONS -int atomic_cmpset_64_i386(volatile uint64_t *, uint64_t, uint64_t); -int atomic_cmpset_64_i586(volatile uint64_t *, uint64_t, uint64_t); -uint64_t atomic_load_acq_64_i386(volatile uint64_t *); -uint64_t atomic_load_acq_64_i586(volatile uint64_t *); -void atomic_store_rel_64_i386(volatile uint64_t *, uint64_t); -void atomic_store_rel_64_i586(volatile uint64_t *, uint64_t); -uint64_t atomic_swap_64_i386(volatile uint64_t *, uint64_t); -uint64_t atomic_swap_64_i586(volatile uint64_t *, uint64_t); -#endif - /* I486 does not support SMP or CMPXCHG8B. */ static __inline int atomic_cmpset_64_i386(volatile uint64_t *dst, uint64_t expect, uint64_t src) @@ -353,12 +342,12 @@ atomic_fcmpset_64_i386(volatile uint64_t *dst, uint64_t *expect, uint64_t src) } static __inline uint64_t -atomic_load_acq_64_i386(volatile uint64_t *p) +atomic_load_acq_64_i386(const volatile uint64_t *p) { - volatile uint32_t *q; + const volatile uint32_t *q; uint64_t res; - q = (volatile uint32_t *)p; + q = (const volatile uint32_t *)p; __asm __volatile( " pushfl ; " " cli ; " @@ -447,8 +436,12 @@ atomic_fcmpset_64_i586(volatile uint64_t *dst, uint64_t *expect, uint64_t src) return (res); } +/* + * Architecturally always writes back some value to '*p' so will trigger + * a #GP(0) on read-only mappings. + */ static __inline uint64_t -atomic_load_acq_64_i586(volatile uint64_t *p) +atomic_load_acq_64_i586(const volatile uint64_t *p) { uint64_t res; @@ -456,9 +449,9 @@ atomic_load_acq_64_i586(volatile uint64_t *p) " movl %%ebx,%%eax ; " " movl %%ecx,%%edx ; " " lock; cmpxchg8b %1" - : "=&A" (res), /* 0 */ - "+m" (*p) /* 1 */ - : : "memory", "cc"); + : "=&A" (res) /* 0 */ + : "m" (*p) /* 1 */ + : "memory", "cc"); return (res); } @@ -514,7 +507,7 @@ atomic_fcmpset_64(volatile uint64_t *dst, uint64_t *expect, uint64_t src) } static __inline uint64_t -atomic_load_acq_64(volatile uint64_t *p) +atomic_load_acq_64(const volatile uint64_t *p) { if ((cpu_feature & CPUID_CX8) == 0) @@ -614,8 +607,6 @@ ATOMIC_LOADSTORE(long); #undef ATOMIC_STORE #undef ATOMIC_LOADSTORE -#ifndef WANT_FUNCTIONS - static __inline int atomic_cmpset_long(volatile u_long *dst, u_long expect, u_long src) { @@ -842,7 +833,7 @@ atomic_swap_long(volatile u_long *p, u_long v) #define atomic_subtract_rel_ptr(p, v) \ atomic_subtract_rel_int((volatile u_int *)(p), (u_int)(v)) #define atomic_load_acq_ptr(p) \ - atomic_load_acq_int((volatile u_int *)(p)) + atomic_load_acq_int((const volatile u_int *)(p)) #define atomic_store_rel_ptr(p, v) \ atomic_store_rel_int((volatile u_int *)(p), (v)) #define atomic_cmpset_ptr(dst, old, new) \ @@ -865,8 +856,10 @@ atomic_swap_long(volatile u_long *p, u_long v) atomic_swap_int((volatile u_int *)(p), (u_int)(v)) #define atomic_readandclear_ptr(p) \ atomic_readandclear_int((volatile u_int *)(p)) - -#endif /* !WANT_FUNCTIONS */ +#define atomic_testandclear_ptr(p, val) \ + atomic_testandclear_int((volatile u_int *)(p), (val)) +#define atomic_testandset_ptr(p, val) \ + atomic_testandset_int((volatile u_int *)(p), (val)) #if defined(_KERNEL) #define mb() __mbk() diff --git a/lib/libc/include/x86-freebsd-none/machine/bus.h b/lib/libc/include/x86-freebsd-none/machine/bus.h deleted file mode 100644 index 025c59ba2f2f..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/bus.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/clock.h b/lib/libc/include/x86-freebsd-none/machine/clock.h deleted file mode 100644 index 838e4abd5916..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/clock.h +++ /dev/null @@ -1,5 +0,0 @@ -/* - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/cpu.h b/lib/libc/include/x86-freebsd-none/machine/cpu.h index 62ddef75f5e6..21d0051493df 100644 --- a/lib/libc/include/x86-freebsd-none/machine/cpu.h +++ b/lib/libc/include/x86-freebsd-none/machine/cpu.h @@ -30,8 +30,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)cpu.h 5.4 (Berkeley) 5/9/91 */ #ifndef _MACHINE_CPU_H_ diff --git a/lib/libc/include/x86-freebsd-none/machine/cpufunc.h b/lib/libc/include/x86-freebsd-none/machine/cpufunc.h index 0c8667b08dc1..22cd1b7cd1db 100644 --- a/lib/libc/include/x86-freebsd-none/machine/cpufunc.h +++ b/lib/libc/include/x86-freebsd-none/machine/cpufunc.h @@ -63,15 +63,6 @@ bsfl(u_int mask) return (result); } -static __inline __pure2 u_int -bsrl(u_int mask) -{ - u_int result; - - __asm("bsrl %1,%0" : "=r" (result) : "rm" (mask) : "cc"); - return (result); -} - static __inline void clflush(u_long addr) { @@ -83,7 +74,7 @@ static __inline void clflushopt(u_long addr) { - __asm __volatile(".byte 0x66;clflush %0" : : "m" (*(char *)addr)); + __asm __volatile("clflushopt %0" : : "m" (*(char *)addr)); } static __inline void diff --git a/lib/libc/include/x86-freebsd-none/machine/dump.h b/lib/libc/include/x86-freebsd-none/machine/dump.h deleted file mode 100644 index cf91d4b47952..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/dump.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/elf.h b/lib/libc/include/x86-freebsd-none/machine/elf.h deleted file mode 100644 index 36a7ae1abaad..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/elf.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/endian.h b/lib/libc/include/x86-freebsd-none/machine/endian.h deleted file mode 100644 index 02be261a3b80..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/endian.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/exec.h b/lib/libc/include/x86-freebsd-none/machine/exec.h deleted file mode 100644 index 3a992321ba55..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/exec.h +++ /dev/null @@ -1,39 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)exec.h 8.1 (Berkeley) 6/11/93 - */ - -#ifndef _MACHINE_EXEC_H_ -#define _MACHINE_EXEC_H_ - -#define __LDPGSZ 4096 - -#endif /* !_MACHINE_EXEC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/float.h b/lib/libc/include/x86-freebsd-none/machine/float.h deleted file mode 100644 index 0e6d11c8c393..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/float.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/floatingpoint.h b/lib/libc/include/x86-freebsd-none/machine/floatingpoint.h deleted file mode 100644 index 134415f2e6e7..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/floatingpoint.h +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 1993 Andrew Moore, Talke Studio - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#) floatingpoint.h 1.0 (Berkeley) 9/23/93 - */ - -#ifndef _FLOATINGPOINT_H_ -#define _FLOATINGPOINT_H_ - -#include -#include - -#endif /* !_FLOATINGPOINT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/ieeefp.h b/lib/libc/include/x86-freebsd-none/machine/ieeefp.h index 14dc1311d272..2fc5a4785fad 100644 --- a/lib/libc/include/x86-freebsd-none/machine/ieeefp.h +++ b/lib/libc/include/x86-freebsd-none/machine/ieeefp.h @@ -32,8 +32,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#) ieeefp.h 1.0 (Berkeley) 9/23/93 */ #ifndef _MACHINE_IEEEFP_H_ diff --git a/lib/libc/include/x86-freebsd-none/machine/in_cksum.h b/lib/libc/include/x86-freebsd-none/machine/in_cksum.h index a9b78c12f723..8d037a9bef25 100644 --- a/lib/libc/include/x86-freebsd-none/machine/in_cksum.h +++ b/lib/libc/include/x86-freebsd-none/machine/in_cksum.h @@ -29,7 +29,6 @@ * SUCH DAMAGE. * * from tahoe: in_cksum.c 1.2 86/01/05 - * from: @(#)in_cksum.c 1.3 (Berkeley) 1/19/91 * from: Id: in_cksum.c,v 1.8 1995/12/03 18:35:19 bde Exp */ diff --git a/lib/libc/include/x86-freebsd-none/machine/metadata.h b/lib/libc/include/x86-freebsd-none/machine/metadata.h deleted file mode 100644 index 2b194e06d14b..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/metadata.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/npx.h b/lib/libc/include/x86-freebsd-none/machine/npx.h index c5d62ba579b6..3c66e65dff5b 100644 --- a/lib/libc/include/x86-freebsd-none/machine/npx.h +++ b/lib/libc/include/x86-freebsd-none/machine/npx.h @@ -30,8 +30,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)npx.h 5.3 (Berkeley) 1/18/91 */ /* diff --git a/lib/libc/include/x86-freebsd-none/machine/ofw_machdep.h b/lib/libc/include/x86-freebsd-none/machine/ofw_machdep.h deleted file mode 100644 index 21d28906f0dd..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/ofw_machdep.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/param.h b/lib/libc/include/x86-freebsd-none/machine/param.h index 392093d81578..5699c7f0fd23 100644 --- a/lib/libc/include/x86-freebsd-none/machine/param.h +++ b/lib/libc/include/x86-freebsd-none/machine/param.h @@ -30,8 +30,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)param.h 5.8 (Berkeley) 6/28/91 */ #ifndef _I386_INCLUDE_PARAM_H_ @@ -43,9 +41,7 @@ * Machine dependent constants for Intel 386. */ -#define __HAVE_ACPI #define __HAVE_PIR -#define __PCI_REROUTE_INTERRUPT #ifndef MACHINE #define MACHINE "i386" @@ -146,19 +142,12 @@ /* * Mach derived conversion macros */ -#define trunc_page(x) ((x) & ~PAGE_MASK) -#define round_page(x) (((x) + PAGE_MASK) & ~PAGE_MASK) #define trunc_4mpage(x) ((x) & ~PDRMASK) #define round_4mpage(x) ((((x)) + PDRMASK) & ~PDRMASK) -#define atop(x) ((x) >> PAGE_SHIFT) -#define ptoa(x) ((x) << PAGE_SHIFT) - #define i386_btop(x) ((x) >> PAGE_SHIFT) #define i386_ptob(x) ((x) << PAGE_SHIFT) -#define pgtok(x) ((x) * (PAGE_SIZE / 1024)) - #define INKERNEL(va) (TRUE) #endif /* !_I386_INCLUDE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/pcb.h b/lib/libc/include/x86-freebsd-none/machine/pcb.h index 1a973ebe0b35..897227eb4d0a 100644 --- a/lib/libc/include/x86-freebsd-none/machine/pcb.h +++ b/lib/libc/include/x86-freebsd-none/machine/pcb.h @@ -30,8 +30,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)pcb.h 5.10 (Berkeley) 5/12/91 */ #ifndef _I386_PCB_H_ diff --git a/lib/libc/include/x86-freebsd-none/machine/pcpu.h b/lib/libc/include/x86-freebsd-none/machine/pcpu.h index 48704d4b6016..87c6b69f2bfd 100644 --- a/lib/libc/include/x86-freebsd-none/machine/pcpu.h +++ b/lib/libc/include/x86-freebsd-none/machine/pcpu.h @@ -108,16 +108,8 @@ _Static_assert(sizeof(struct monitorbuf) == 128, "2x cache line"); /* * Evaluates to the address of the per-cpu variable name. */ -#define __PCPU_PTR(name) __extension__ ({ \ - __pcpu_type(name) *__p; \ - \ - __asm __volatile("movl %%fs:%1,%0; addl %2,%0" \ - : "=r" (__p) \ - : "m" (*(struct pcpu *)(__pcpu_offset(pc_prvspace))), \ - "i" (__pcpu_offset(name))); \ - \ - __p; \ -}) +#define __PCPU_PTR(name) \ + (&get_pcpu()->name) /* * Evaluates to the value of the per-cpu variable name. @@ -126,14 +118,13 @@ _Static_assert(sizeof(struct monitorbuf) == 128, "2x cache line"); __pcpu_type(name) __res; \ struct __s { \ u_char __b[MIN(sizeof(__res), 4)]; \ - } __s; \ + }; \ \ if (sizeof(__res) == 1 || sizeof(__res) == 2 || \ sizeof(__res) == 4) { \ - __asm __volatile("mov %%fs:%1,%0" \ - : "=r" (__s) \ - : "m" (*(struct __s *)(__pcpu_offset(name)))); \ - *(struct __s *)(void *)&__res = __s; \ + __asm __volatile("mov %%fs:%c1,%0" \ + : "=r" (*(struct __s *)(void *)&__res) \ + : "i" (__pcpu_offset(name))); \ } else { \ __res = *__PCPU_PTR(name); \ } \ @@ -148,15 +139,16 @@ _Static_assert(sizeof(struct monitorbuf) == 128, "2x cache line"); __pcpu_type(name) __val; \ struct __s { \ u_char __b[MIN(sizeof(__val), 4)]; \ - } __s; \ + }; \ \ __val = (val); \ if (sizeof(__val) == 1 || sizeof(__val) == 2 || \ sizeof(__val) == 4) { \ - __s = *(struct __s *)(void *)&__val; \ - __asm __volatile("add %1,%%fs:%0" \ - : "=m" (*(struct __s *)(__pcpu_offset(name))) \ - : "r" (__s)); \ + __asm __volatile("add %1,%%fs:%c0" \ + : \ + : "i" (__pcpu_offset(name)), \ + "r" (*(struct __s *)(void *)&__val) \ + : "cc", "memory"); \ } else \ *__PCPU_PTR(name) += __val; \ } while (0) @@ -168,15 +160,16 @@ _Static_assert(sizeof(struct monitorbuf) == 128, "2x cache line"); __pcpu_type(name) __val; \ struct __s { \ u_char __b[MIN(sizeof(__val), 4)]; \ - } __s; \ + }; \ \ __val = (val); \ if (sizeof(__val) == 1 || sizeof(__val) == 2 || \ sizeof(__val) == 4) { \ - __s = *(struct __s *)(void *)&__val; \ - __asm __volatile("mov %1,%%fs:%0" \ - : "=m" (*(struct __s *)(__pcpu_offset(name))) \ - : "r" (__s)); \ + __asm __volatile("mov %1,%%fs:%c0" \ + : \ + : "i" (__pcpu_offset(name)), \ + "r" (*(struct __s *)(void *)&__val) \ + : "memory"); \ } else { \ *__PCPU_PTR(name) = __val; \ } \ @@ -185,9 +178,9 @@ _Static_assert(sizeof(struct monitorbuf) == 128, "2x cache line"); #define get_pcpu() __extension__ ({ \ struct pcpu *__pc; \ \ - __asm __volatile("movl %%fs:%1,%0" \ + __asm __volatile("movl %%fs:%c1,%0" \ : "=r" (__pc) \ - : "m" (*(struct pcpu *)(__pcpu_offset(pc_prvspace)))); \ + : "i" (__pcpu_offset(pc_prvspace))); \ __pc; \ }) diff --git a/lib/libc/include/x86-freebsd-none/machine/pcpu_aux.h b/lib/libc/include/x86-freebsd-none/machine/pcpu_aux.h index 4fc13cdfd3fa..5807079df3a6 100644 --- a/lib/libc/include/x86-freebsd-none/machine/pcpu_aux.h +++ b/lib/libc/include/x86-freebsd-none/machine/pcpu_aux.h @@ -49,8 +49,8 @@ __curthread(void) { struct thread *td; - __asm("movl %%fs:%1,%0" : "=r" (td) - : "m" (*(char *)offsetof(struct pcpu, pc_curthread))); + __asm("movl %%fs:%c1,%0" : "=r" (td) + : "i" (offsetof(struct pcpu, pc_curthread))); return (td); } #define curthread (__curthread()) @@ -60,8 +60,8 @@ __curpcb(void) { struct pcb *pcb; - __asm("movl %%fs:%1,%0" : "=r" (pcb) - : "m" (*(char *)offsetof(struct pcpu, pc_curpcb))); + __asm("movl %%fs:%c1,%0" : "=r" (pcb) + : "i" (offsetof(struct pcpu, pc_curpcb))); return (pcb); } #define curpcb (__curpcb()) diff --git a/lib/libc/include/x86-freebsd-none/machine/pmap.h b/lib/libc/include/x86-freebsd-none/machine/pmap.h index c4971b12424c..886993cbbdd3 100644 --- a/lib/libc/include/x86-freebsd-none/machine/pmap.h +++ b/lib/libc/include/x86-freebsd-none/machine/pmap.h @@ -37,9 +37,6 @@ * map the page tables using the pagetables themselves. This is done to * reduce the impact on kernel virtual memory for lots of sparse address * space, and to reduce the cost of memory to each process. - * - * from: hp300: @(#)pmap.h 7.2 (Berkeley) 12/16/90 - * from: @(#)pmap.h 7.4 (Berkeley) 5/12/91 */ #ifndef _MACHINE_PMAP_H_ @@ -83,7 +80,7 @@ * 4KB (PTE) page mappings have identical settings for the following fields: */ #define PG_PTE_PROMOTE (PG_MANAGED | PG_W | PG_G | PG_PTE_PAT | \ - PG_M | PG_A | PG_NC_PCD | PG_NC_PWT | PG_U | PG_RW | PG_V) + PG_M | PG_NC_PCD | PG_NC_PWT | PG_U | PG_RW | PG_V) /* * Page Protection Exception bits @@ -221,7 +218,7 @@ void pmap_basemem_setup(u_int basemem); void *pmap_bios16_enter(void); void pmap_bios16_leave(void *handle); void pmap_bootstrap(vm_paddr_t); -int pmap_cache_bits(pmap_t, int mode, boolean_t is_pde); +int pmap_cache_bits(pmap_t, int mode, bool is_pde); int pmap_change_attr(vm_offset_t, vm_size_t, int); caddr_t pmap_cmap3(vm_paddr_t pa, u_int pte_bits); void pmap_cp_slow0_map(vm_offset_t kaddr, int plen, vm_page_t *ma); @@ -239,7 +236,7 @@ void pmap_ksetrw(vm_offset_t va); void *pmap_mapbios(vm_paddr_t, vm_size_t); void *pmap_mapdev(vm_paddr_t, vm_size_t); void *pmap_mapdev_attr(vm_paddr_t, vm_size_t, int); -boolean_t pmap_page_is_mapped(vm_page_t m); +bool pmap_page_is_mapped(vm_page_t m); void pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma); vm_paddr_t pmap_pg_frame(vm_paddr_t pa); bool pmap_ps_enabled(pmap_t pmap); diff --git a/lib/libc/include/x86-freebsd-none/machine/pmap_base.h b/lib/libc/include/x86-freebsd-none/machine/pmap_base.h index 73a6dcbd3b14..e590f96a05da 100644 --- a/lib/libc/include/x86-freebsd-none/machine/pmap_base.h +++ b/lib/libc/include/x86-freebsd-none/machine/pmap_base.h @@ -58,8 +58,8 @@ struct pmap_methods { void *(*pm_bios16_enter)(void); void (*pm_bios16_leave)(void *handle); void (*pm_bootstrap)(vm_paddr_t firstaddr); - boolean_t (*pm_is_valid_memattr)(pmap_t, vm_memattr_t); - int (*pm_cache_bits)(pmap_t, int, boolean_t); + bool (*pm_is_valid_memattr)(pmap_t, vm_memattr_t); + int (*pm_cache_bits)(pmap_t, int, bool); bool (*pm_ps_enabled)(pmap_t); void (*pm_pinit0)(pmap_t); int (*pm_pinit)(pmap_t); @@ -84,13 +84,13 @@ struct pmap_methods { void (*pm_object_init_pt)(pmap_t, vm_offset_t, vm_object_t, vm_pindex_t, vm_size_t); void (*pm_unwire)(pmap_t, vm_offset_t, vm_offset_t); - boolean_t (*pm_page_exists_quick)(pmap_t, vm_page_t); + bool (*pm_page_exists_quick)(pmap_t, vm_page_t); int (*pm_page_wired_mappings)(vm_page_t); - boolean_t (*pm_page_is_mapped)(vm_page_t); + bool (*pm_page_is_mapped)(vm_page_t); void (*pm_remove_pages)(pmap_t); - boolean_t (*pm_is_modified)(vm_page_t); - boolean_t (*pm_is_prefaultable)(pmap_t, vm_offset_t); - boolean_t (*pm_is_referenced)(vm_page_t); + bool (*pm_is_modified)(vm_page_t); + bool (*pm_is_prefaultable)(pmap_t, vm_offset_t); + bool (*pm_is_referenced)(vm_page_t); void (*pm_remove_write)(vm_page_t); int (*pm_ts_referenced)(vm_page_t); void *(*pm_mapdev_attr)(vm_paddr_t, vm_size_t, int, int); @@ -107,7 +107,7 @@ struct pmap_methods { void (*pm_remove_all)(vm_page_t); void (*pm_init)(void); void (*pm_init_pat)(void); - void (*pm_growkernel)(vm_offset_t); + int (*pm_growkernel)(vm_offset_t); void (*pm_invalidate_page)(pmap_t, vm_offset_t); void (*pm_invalidate_range)(pmap_t, vm_offset_t, vm_offset_t); void (*pm_invalidate_all)(pmap_t); diff --git a/lib/libc/include/x86-freebsd-none/machine/pmap_nopae.h b/lib/libc/include/x86-freebsd-none/machine/pmap_nopae.h index c3ce424beb14..3af191062f58 100644 --- a/lib/libc/include/x86-freebsd-none/machine/pmap_nopae.h +++ b/lib/libc/include/x86-freebsd-none/machine/pmap_nopae.h @@ -44,9 +44,6 @@ * map the page tables using the pagetables themselves. This is done to * reduce the impact on kernel virtual memory for lots of sparse address * space, and to reduce the cost of memory to each process. - * - * from: hp300: @(#)pmap.h 7.2 (Berkeley) 12/16/90 - * from: @(#)pmap.h 7.4 (Berkeley) 5/12/91 */ #ifndef _MACHINE_PMAP_NOPAE_H diff --git a/lib/libc/include/x86-freebsd-none/machine/pmap_pae.h b/lib/libc/include/x86-freebsd-none/machine/pmap_pae.h index df87eeaee873..859fdc59a40f 100644 --- a/lib/libc/include/x86-freebsd-none/machine/pmap_pae.h +++ b/lib/libc/include/x86-freebsd-none/machine/pmap_pae.h @@ -44,9 +44,6 @@ * map the page tables using the pagetables themselves. This is done to * reduce the impact on kernel virtual memory for lots of sparse address * space, and to reduce the cost of memory to each process. - * - * from: hp300: @(#)pmap.h 7.2 (Berkeley) 12/16/90 - * from: @(#)pmap.h 7.4 (Berkeley) 5/12/91 */ #ifndef _MACHINE_PMAP_PAE_H diff --git a/lib/libc/include/x86-freebsd-none/machine/proc.h b/lib/libc/include/x86-freebsd-none/machine/proc.h index 8ba00996450b..3377daab2ca4 100644 --- a/lib/libc/include/x86-freebsd-none/machine/proc.h +++ b/lib/libc/include/x86-freebsd-none/machine/proc.h @@ -27,8 +27,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)proc.h 7.1 (Berkeley) 5/15/91 */ #ifndef _MACHINE_PROC_H_ diff --git a/lib/libc/include/x86-freebsd-none/machine/profile.h b/lib/libc/include/x86-freebsd-none/machine/profile.h index c58517f68773..2789d419f554 100644 --- a/lib/libc/include/x86-freebsd-none/machine/profile.h +++ b/lib/libc/include/x86-freebsd-none/machine/profile.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)profile.h 8.1 (Berkeley) 6/11/93 */ #ifndef _MACHINE_PROFILE_H_ diff --git a/lib/libc/include/x86-freebsd-none/machine/psl.h b/lib/libc/include/x86-freebsd-none/machine/psl.h deleted file mode 100644 index 59536384fca5..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/psl.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/ptrace.h b/lib/libc/include/x86-freebsd-none/machine/ptrace.h deleted file mode 100644 index 0a426e24fabd..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/ptrace.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/reg.h b/lib/libc/include/x86-freebsd-none/machine/reg.h deleted file mode 100644 index 419b2756cc0d..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/reg.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/reloc.h b/lib/libc/include/x86-freebsd-none/machine/reloc.h deleted file mode 100644 index 4b31acb73c7b..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/reloc.h +++ /dev/null @@ -1,50 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)reloc.h 8.1 (Berkeley) 6/10/93 - */ - -#ifndef _I386_MACHINE_RELOC_H_ -#define _I386_MACHINE_RELOC_H_ - -/* Relocation format. */ -struct relocation_info { - int r_address; /* offset in text or data segment */ - unsigned int r_symbolnum : 24, /* ordinal number of add symbol */ - r_pcrel : 1, /* 1 if value should be pc-relative */ - r_length : 2, /* log base 2 of value's width */ - r_extern : 1, /* 1 if need to add symbol to value */ - r_baserel : 1, /* linkage table relative */ - r_jmptable : 1, /* relocate to jump table */ - r_relative : 1, /* load address relative */ - r_copy : 1; /* run time copy */ -}; - -#endif \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/resource.h b/lib/libc/include/x86-freebsd-none/machine/resource.h index aaafc404fff3..4c356f38308e 100644 --- a/lib/libc/include/x86-freebsd-none/machine/resource.h +++ b/lib/libc/include/x86-freebsd-none/machine/resource.h @@ -39,8 +39,6 @@ #define SYS_RES_DRQ 2 /* isa dma lines */ #define SYS_RES_MEMORY 3 /* i/o memory */ #define SYS_RES_IOPORT 4 /* i/o ports */ -#ifdef NEW_PCIB #define PCI_RES_BUS 5 /* PCI bus numbers */ -#endif #endif /* !_MACHINE_RESOURCE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/runq.h b/lib/libc/include/x86-freebsd-none/machine/runq.h deleted file mode 100644 index 63b30d582a97..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/runq.h +++ /dev/null @@ -1,46 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2001 Jake Burkholder - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _MACHINE_RUNQ_H_ -#define _MACHINE_RUNQ_H_ - -#define RQB_LEN (2) /* Number of priority status words. */ -#define RQB_L2BPW (5) /* Log2(sizeof(rqb_word_t) * NBBY)). */ -#define RQB_BPW (1<> RQB_L2BPW) - -#define RQB_FFS(word) (ffs(word) - 1) - -/* - * Type of run queue status word. - */ -typedef u_int32_t rqb_word_t; - -#endif \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/sdt_machdep.h b/lib/libc/include/x86-freebsd-none/machine/sdt_machdep.h new file mode 100644 index 000000000000..127c93cbc82a --- /dev/null +++ b/lib/libc/include/x86-freebsd-none/machine/sdt_machdep.h @@ -0,0 +1,19 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 Mark Johnston + */ + +#ifndef _SYS_SDT_MACHDEP_H_ +#define _SYS_SDT_MACHDEP_H_ + +#define _SDT_ASM_PATCH_INSTR "nop; nop; nop; nop; nop" + +/* + * Work around an apparent clang bug or limitation which prevents the use of the + * "i" (immediate) constraint with the probe structure. + */ +#define _SDT_ASM_PROBE_CONSTRAINT "Ws" +#define _SDT_ASM_PROBE_OPERAND "p" + +#endif \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/segments.h b/lib/libc/include/x86-freebsd-none/machine/segments.h index c2d38f970b23..cfb3054fd8bb 100644 --- a/lib/libc/include/x86-freebsd-none/machine/segments.h +++ b/lib/libc/include/x86-freebsd-none/machine/segments.h @@ -31,8 +31,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)segments.h 7.1 (Berkeley) 5/9/91 */ #ifndef _MACHINE_SEGMENTS_H_ diff --git a/lib/libc/include/x86-freebsd-none/machine/setjmp.h b/lib/libc/include/x86-freebsd-none/machine/setjmp.h deleted file mode 100644 index 41ef6217a78d..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/setjmp.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/signal.h b/lib/libc/include/x86-freebsd-none/machine/signal.h index 926a34f56392..c2a08dcb7535 100644 --- a/lib/libc/include/x86-freebsd-none/machine/signal.h +++ b/lib/libc/include/x86-freebsd-none/machine/signal.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)signal.h 8.1 (Berkeley) 6/11/93 */ #ifndef _MACHINE_SIGNAL_H_ diff --git a/lib/libc/include/x86-freebsd-none/machine/sysarch.h b/lib/libc/include/x86-freebsd-none/machine/sysarch.h deleted file mode 100644 index 7a8789707932..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/sysarch.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/tls.h b/lib/libc/include/x86-freebsd-none/machine/tls.h deleted file mode 100644 index 9a386029151e..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/tls.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/trap.h b/lib/libc/include/x86-freebsd-none/machine/trap.h deleted file mode 100644 index d8320b7b3503..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/trap.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/tss.h b/lib/libc/include/x86-freebsd-none/machine/tss.h index 3d315ded6328..0a59c54a60da 100644 --- a/lib/libc/include/x86-freebsd-none/machine/tss.h +++ b/lib/libc/include/x86-freebsd-none/machine/tss.h @@ -30,8 +30,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)tss.h 5.4 (Berkeley) 1/18/91 */ #ifndef _MACHINE_TSS_H_ diff --git a/lib/libc/include/x86-freebsd-none/machine/vdso.h b/lib/libc/include/x86-freebsd-none/machine/vdso.h deleted file mode 100644 index 57db69e06a7c..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/vdso.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/vm.h b/lib/libc/include/x86-freebsd-none/machine/vm.h deleted file mode 100644 index fdd08a2e4de4..000000000000 --- a/lib/libc/include/x86-freebsd-none/machine/vm.h +++ /dev/null @@ -1,46 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2009 Hudson River Trading LLC - * Written by: John H. Baldwin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _MACHINE_VM_H_ -#define _MACHINE_VM_H_ - -#include - -/* Memory attributes. */ -#define VM_MEMATTR_UNCACHEABLE ((vm_memattr_t)PAT_UNCACHEABLE) -#define VM_MEMATTR_WRITE_COMBINING ((vm_memattr_t)PAT_WRITE_COMBINING) -#define VM_MEMATTR_WRITE_THROUGH ((vm_memattr_t)PAT_WRITE_THROUGH) -#define VM_MEMATTR_WRITE_PROTECTED ((vm_memattr_t)PAT_WRITE_PROTECTED) -#define VM_MEMATTR_WRITE_BACK ((vm_memattr_t)PAT_WRITE_BACK) -#define VM_MEMATTR_WEAK_UNCACHEABLE ((vm_memattr_t)PAT_UNCACHED) - -#define VM_MEMATTR_DEFAULT VM_MEMATTR_WRITE_BACK -#define VM_MEMATTR_DEVICE VM_MEMATTR_UNCACHEABLE - -#endif /* !_MACHINE_VM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/machine/vmparam.h b/lib/libc/include/x86-freebsd-none/machine/vmparam.h index 2e4840657613..625944650a1e 100644 --- a/lib/libc/include/x86-freebsd-none/machine/vmparam.h +++ b/lib/libc/include/x86-freebsd-none/machine/vmparam.h @@ -32,8 +32,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)vmparam.h 5.9 (Berkeley) 5/12/91 */ #ifndef _MACHINE_VMPARAM_H_ @@ -248,5 +246,6 @@ * Need a page dump array for minidump. */ #define MINIDUMP_PAGE_TRACKING 1 +#define MINIDUMP_STARTUP_PAGE_TRACKING 0 #endif /* _MACHINE_VMPARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-freebsd-none/stdarg.h b/lib/libc/include/x86-freebsd-none/stdarg.h deleted file mode 100644 index 20289894d6be..000000000000 --- a/lib/libc/include/x86-freebsd-none/stdarg.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/frame.h b/lib/libc/include/x86-openbsd-none/frame.h new file mode 100644 index 000000000000..dbdb06fd21b9 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/frame.h @@ -0,0 +1,173 @@ +/* $OpenBSD: frame.h,v 1.13 2018/06/15 17:58:41 bluhm Exp $ */ +/* $NetBSD: frame.h,v 1.12 1995/10/11 04:20:08 mycroft Exp $ */ + +/*- + * Copyright (c) 1995 Charles M. Hannum. All rights reserved. + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)frame.h 5.2 (Berkeley) 1/18/91 + */ + +#ifndef _MACHINE_FRAME_H +#define _MACHINE_FRAME_H +#include + +/* + * System stack frames. + */ + +/* + * Exception/Trap Stack Frame + */ +struct trapframe { + int tf_fs; + int tf_gs; + int tf_es; + int tf_ds; + int tf_edi; + int tf_esi; + int tf_err; /* not the hardware position */ + int tf_ebx; + int tf_edx; + int tf_ecx; + int tf_eax; + int tf_trapno; + /* below portion defined in 386 hardware */ + int tf_ebp; /* hardware puts err here, INTRENTRY() moves it up */ + int tf_eip; + int tf_cs; + int tf_eflags; + /* below used when transitting rings (e.g. user to kernel) */ + int tf_esp; + int tf_ss; + /* below used when switching out of VM86 mode */ + int tf_vm86_es; + int tf_vm86_ds; + int tf_vm86_fs; + int tf_vm86_gs; +}; + +/* + * Interrupt stack frame + */ +struct intrframe { + int if_ppl; + int if_fs; + int if_gs; + int if_es; + int if_ds; + int if_edi; + int if_esi; + int :32; /* for compat with trap frame - err */ + int if_ebx; + int if_edx; + int if_ecx; + int if_eax; + int :32; /* for compat with trap frame - trapno */ + int if_ebp; + /* below portion defined in 386 hardware */ + int if_eip; + int if_cs; + int if_eflags; + /* below only when transitting rings (e.g. user to kernel) */ + int if_esp; + int if_ss; +}; + +/* + * iret stack frame + */ +struct iretframe { + int irf_trapno; + int irf_err; + int irf_eip; + int irf_cs; + int irf_eflags; + int irf_esp; + int irf_ss; + /* below used when switching back to VM86 mode */ + int irf_vm86_es; + int irf_vm86_ds; + int irf_vm86_fs; + int irf_vm86_gs; +}; + +/* + * Trampoline stack frame + */ +struct trampframe { + int trf__deadbeef; + int trf__kern_esp; + int trf_fs; + int trf_eax; + int trf_ebp; + int trf_trapno; + int trf_err; + int trf_eip; + int trf_cs; + int trf_eflags; + int trf_esp; + int trf_ss; + /* below used when switching out of VM86 mode */ + int trf_vm86_es; + int trf_vm86_ds; + int trf_vm86_fs; + int trf_vm86_gs; +}; + +/* + * Stack frame inside cpu_switch() + */ +struct switchframe { + int sf_edi; + int sf_esi; + int sf_ebx; + int sf_eip; +}; + +struct callframe { + struct callframe *f_frame; + int f_retaddr; + int f_arg0; +}; + +/* + * Signal frame + */ +struct sigframe { + int sf_signum; + siginfo_t *sf_sip; + struct sigcontext *sf_scp; + sig_t sf_handler; + struct sigcontext sf_sc; + siginfo_t sf_si; +}; +#endif \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/_float.h b/lib/libc/include/x86-openbsd-none/i386/_float.h new file mode 100644 index 000000000000..4610c97974a5 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/_float.h @@ -0,0 +1,71 @@ +/* $OpenBSD: _float.h,v 1.1 2012/06/26 16:12:44 deraadt Exp $ */ + +/* + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE__FLOAT_H_ +#define _MACHINE__FLOAT_H_ + +#define __FLT_RADIX 2 /* b */ +#define __FLT_ROUNDS __flt_rounds() +#define __FLT_EVAL_METHOD 2 /* long double */ + +#define __FLT_MANT_DIG 24 /* p */ +#define __FLT_EPSILON 1.19209290E-07F /* b**(1-p) */ +#define __FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ +#define __FLT_MIN_EXP (-125) /* emin */ +#define __FLT_MIN 1.17549435E-38F /* b**(emin-1) */ +#define __FLT_MIN_10_EXP (-37) /* ceil(log10(b**(emin-1))) */ +#define __FLT_MAX_EXP 128 /* emax */ +#define __FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ +#define __FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ + +#define __DBL_MANT_DIG 53 +#define __DBL_EPSILON 2.2204460492503131E-16 +#define __DBL_DIG 15 +#define __DBL_MIN_EXP (-1021) +#define __DBL_MIN 2.2250738585072014E-308 +#define __DBL_MIN_10_EXP (-307) +#define __DBL_MAX_EXP 1024 +#define __DBL_MAX 1.7976931348623157E+308 +#define __DBL_MAX_10_EXP 308 + +#define __LDBL_MANT_DIG 64 +#define __LDBL_EPSILON 1.08420217248550443401e-19L +#define __LDBL_DIG 18 +#define __LDBL_MIN_EXP (-16381) +#define __LDBL_MIN 3.36210314311209350626e-4932L +#define __LDBL_MIN_10_EXP (-4931) +#define __LDBL_MAX_EXP 16384 +#define __LDBL_MAX 1.18973149535723176502e+4932L +#define __LDBL_MAX_10_EXP 4932 + +#define __DECIMAL_DIG 21 + +#endif /* _MACHINE__FLOAT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/_types.h b/lib/libc/include/x86-openbsd-none/i386/_types.h new file mode 100644 index 000000000000..b9c612f1bb4a --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/_types.h @@ -0,0 +1,140 @@ +/* $OpenBSD: _types.h,v 1.25 2023/07/02 19:02:27 cheloha Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.3 (Berkeley) 1/5/94 + * @(#)ansi.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _MACHINE__TYPES_H_ +#define _MACHINE__TYPES_H_ + +/* + * _ALIGN(p) rounds p (pointer or byte index) up to a correctly-aligned + * value for all data types (int, long, ...). The result is an + * unsigned long and must be cast to any desired pointer type. + * + * _ALIGNED_POINTER is a boolean macro that checks whether an address + * is valid to fetch data elements of type t from on this architecture. + * This does not reflect the optimal alignment, just the possibility + * (within reasonable limits). + */ +#define _ALIGNBYTES (sizeof(int) - 1) +#define _STACKALIGNBYTES 15 +#define _ALIGN(p) (((unsigned long)(p) + _ALIGNBYTES) & ~_ALIGNBYTES) +#define _ALIGNED_POINTER(p,t) 1 +#define _MAX_PAGE_SHIFT 12 /* same as PAGE_SHIFT */ + +#if defined(_KERNEL) +typedef struct label_t { + long val[6]; +} label_t; +#endif + +/* 7.18.1.1 Exact-width integer types */ +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short __int16_t; +typedef unsigned short __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; +typedef long long __int64_t; +typedef unsigned long long __uint64_t; + +/* 7.18.1.2 Minimum-width integer types */ +typedef __int8_t __int_least8_t; +typedef __uint8_t __uint_least8_t; +typedef __int16_t __int_least16_t; +typedef __uint16_t __uint_least16_t; +typedef __int32_t __int_least32_t; +typedef __uint32_t __uint_least32_t; +typedef __int64_t __int_least64_t; +typedef __uint64_t __uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types */ +typedef __int32_t __int_fast8_t; +typedef __uint32_t __uint_fast8_t; +typedef __int32_t __int_fast16_t; +typedef __uint32_t __uint_fast16_t; +typedef __int32_t __int_fast32_t; +typedef __uint32_t __uint_fast32_t; +typedef __int64_t __int_fast64_t; +typedef __uint64_t __uint_fast64_t; +#define __INT_FAST8_MIN INT32_MIN +#define __INT_FAST16_MIN INT32_MIN +#define __INT_FAST32_MIN INT32_MIN +#define __INT_FAST64_MIN INT64_MIN +#define __INT_FAST8_MAX INT32_MAX +#define __INT_FAST16_MAX INT32_MAX +#define __INT_FAST32_MAX INT32_MAX +#define __INT_FAST64_MAX INT64_MAX +#define __UINT_FAST8_MAX UINT32_MAX +#define __UINT_FAST16_MAX UINT32_MAX +#define __UINT_FAST32_MAX UINT32_MAX +#define __UINT_FAST64_MAX UINT64_MAX + +/* 7.18.1.4 Integer types capable of holding object pointers */ +typedef long __intptr_t; +typedef unsigned long __uintptr_t; + +/* 7.18.1.5 Greatest-width integer types */ +typedef __int64_t __intmax_t; +typedef __uint64_t __uintmax_t; + +/* Register size */ +typedef long __register_t; + +/* VM system types */ +typedef unsigned long __vaddr_t; +typedef unsigned long __paddr_t; +typedef unsigned long __vsize_t; +typedef unsigned long __psize_t; + +/* Standard system types */ +typedef long double __double_t; +typedef long double __float_t; +typedef long __ptrdiff_t; +typedef unsigned long __size_t; +typedef long __ssize_t; +#if defined(__GNUC__) && __GNUC__ >= 3 +typedef __builtin_va_list __va_list; +#else +typedef char * __va_list; +#endif + +/* Wide character support types */ +#ifndef __cplusplus +typedef int __wchar_t; +#endif +typedef int __wint_t; +typedef int __rune_t; +typedef void * __wctrans_t; +typedef void * __wctype_t; + +#endif /* _MACHINE__TYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/acpiapm.h b/lib/libc/include/x86-openbsd-none/i386/acpiapm.h new file mode 100644 index 000000000000..6921c56fd28f --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/acpiapm.h @@ -0,0 +1,22 @@ +/* $OpenBSD: acpiapm.h,v 1.1 2007/11/25 15:45:17 tedu Exp $ */ +/* + * Copyright (c) 2007 Ted Unangst + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +extern int (*acpiapm_open)(dev_t, int, int, struct proc *); +extern int (*acpiapm_close)(dev_t, int, int, struct proc *); +extern int (*acpiapm_ioctl)(dev_t, u_long, caddr_t, int, struct proc *); +extern int (*acpiapm_kqfilter)(dev_t, struct knote *); \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/amdmsr.h b/lib/libc/include/x86-openbsd-none/i386/amdmsr.h new file mode 100644 index 000000000000..1a6027a5a36c --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/amdmsr.h @@ -0,0 +1,34 @@ +/* $OpenBSD: amdmsr.h,v 1.4 2011/03/23 16:54:35 pirofti Exp $ */ + +/* + * Copyright (c) 2008 Marc Balmer + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_AMDMSR_H_ +#define _MACHINE_AMDMSR_H_ + +struct amdmsr_req { + u_int32_t addr; /* 32-bit MSR address */ + u_int64_t val; /* 64-bit MSR value */ +}; + +#define RDMSR _IOWR('M', 0, struct amdmsr_req) +#define WRMSR _IOW('M', 1, struct amdmsr_req) + +#ifdef _KERNEL +int amdmsr_probe(void); +#endif + +#endif /* !_MACHINE_AMDMSR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/apicvar.h b/lib/libc/include/x86-openbsd-none/i386/apicvar.h new file mode 100644 index 000000000000..754f54465e12 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/apicvar.h @@ -0,0 +1,54 @@ +/* $OpenBSD: apicvar.h,v 1.7 2025/09/05 16:57:48 kettenis Exp $ */ +/* $NetBSD: apicvar.h,v 1.1.2.3 2000/02/27 20:25:00 sommerfeld Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_APICVAR_H_ +#define _MACHINE_APICVAR_H_ + +#include + +struct apic_attach_args { + const char *aaa_name; + int apic_id; + int apic_version; + int flags; +#define IOAPIC_PICMODE 0x01 +#define IOAPIC_VWIRE 0x02 + bus_space_tag_t apic_memt; + bus_addr_t apic_address; + int apic_vecbase; +}; + +void apic_format_redir(char *, char *, int, u_int32_t, u_int32_t); + +#endif /* !_MACHINE_APICVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/apmvar.h b/lib/libc/include/x86-openbsd-none/i386/apmvar.h new file mode 100644 index 000000000000..4d29641e7a1b --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/apmvar.h @@ -0,0 +1,303 @@ +/* $OpenBSD: apmvar.h,v 1.22 2019/01/22 02:36:30 phessler Exp $ */ + +/* + * Copyright (c) 1995 John T. Kohl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _MACHINE_APMVAR_H_ +#define _MACHINE_APMVAR_H_ + +#include + +/* Advanced Power Management (v1.0 and v1.1 specification) + * functions/defines/etc. + */ + +#define APM_VERSION 0x0102 + +/* + * APM info word from boot loader + */ +#define APM_16BIT_SUPPORTED 0x00010000 +#define APM_32BIT_SUPPORTED 0x00020000 +#define APM_IDLE_SLOWS 0x00040000 +#define APM_BIOS_PM_DISABLED 0x00080000 +#define APM_BIOS_PM_DISENGAGED 0x00100000 +#define APM_MAJOR(f) (((f) >> 8) & 0xff) +#define APM_MINOR(f) ((f) & 0xff) +#define APM_VERMASK 0x0000ffff +#define APM_NOCLI 0x00010000 +#define APM_BEBATT 0x00020000 + +/* APM error codes */ +#define APM_ERR_CODE(regs) (((regs)->ax & 0xff00) >> 8) +#define APM_ERR_PM_DISABLED 0x01 +#define APM_ERR_REALALREADY 0x02 +#define APM_ERR_NOTCONN 0x03 +#define APM_ERR_16ALREADY 0x05 +#define APM_ERR_16NOTSUPP 0x06 +#define APM_ERR_32ALREADY 0x07 +#define APM_ERR_32NOTSUPP 0x08 +#define APM_ERR_UNRECOG_DEV 0x09 +#define APM_ERR_ERANGE 0x0A +#define APM_ERR_NOTENGAGED 0x0B +#define APM_ERR_EOPNOSUPP 0x0C +#define APM_ERR_RTIMER_DISABLED 0x0D +#define APM_ERR_UNABLE 0x60 +#define APM_ERR_NOEVENTS 0x80 +#define APM_ERR_NOT_PRESENT 0x86 + +#define APM_DEV_APM_BIOS 0x0000 +#define APM_DEV_ALLDEVS 0x0001 +/* device classes are high byte; device IDs go in low byte */ +#define APM_DEV_DISPLAY(x) (0x0100|((x)&0xff)) +#define APM_DEV_DISK(x) (0x0200|((x)&0xff)) +#define APM_DEV_PARALLEL(x) (0x0300|((x)&0xff)) +#define APM_DEV_SERIAL(x) (0x0400|((x)&0xff)) +#define APM_DEV_NETWORK(x) (0x0500|((x)&0xff)) +#define APM_DEV_PCMCIA(x) (0x0600|((x)&0xff)) +#define APM_DEV_BATTERIES(x) (0x8000|((x)&0xff)) +#define APM_DEV_ALLUNITS 0xff +/* 0x8100-0xDFFF - reserved */ +/* 0xE000-0xEFFF - OEM-defined */ +/* 0xF000-0xFFFF - reserved */ + +#define APM_INSTCHECK 0x5300 /* int15 only */ +#define APM_16BIT_SUPPORT 0x01 +#define APM_32BIT_SUPPORT 0x02 +#define APM_CPUIDLE_SLOW 0x04 +#define APM_DISABLED 0x08 +#define APM_DISENGAGED 0x10 + +#define APM_REAL_CONNECT 0x5301 /* int15 only */ +#define APM_PROT16_CONNECT 0x5302 /* int15 only */ +#define APM_PROT32_CONNECT 0x5303 /* int15 only */ +#define APM_DISCONNECT 0x5304 /* %bx = APM_DEV_APM_BIOS */ + +#define APM_CPU_IDLE 0x5305 +#define APM_CPU_BUSY 0x5306 + +#define APM_SET_PWR_STATE 0x5307 +#define APM_SYS_READY 0x0000 /* %cx */ +#define APM_SYS_STANDBY 0x0001 +#define APM_SYS_SUSPEND 0x0002 +#define APM_SYS_OFF 0x0003 +#define APM_LASTREQ_INPROG 0x0004 +#define APM_LASTREQ_REJECTED 0x0005 +/* 0x0006 - 0x001f Reserved system states */ +/* 0x0020 - 0x003f OEM-defined system states */ +/* 0x0040 - 0x007f OEM-defined device states */ +/* 0x0080 - 0xffff Reserved device states */ + +/* system standby is device ID (%bx) 0x0001, APM_SYS_STANDBY */ +/* system suspend is device ID (%bx) 0x0001, APM_SYS_SUSPEND */ + +#define APM_PWR_MGT_ENABLE 0x5308 +#define APM_MGT_ALL 0xffff /* %bx */ +#define APM_MGT_DISABLE 0x0 /* %cx */ +#define APM_MGT_ENABLE 0x1 + +#define APM_SYSTEM_DEFAULTS 0x5309 +#define APM_DEFAULTS_ALL 0xffff /* %bx */ + +#define APM_POWER_STATUS 0x530a +#define APM_AC_OFF 0x00 +#define APM_AC_ON 0x01 +#define APM_AC_BACKUP 0x02 +#define APM_AC_UNKNOWN 0xff +#define APM_BATT_HIGH 0x00 +#define APM_BATT_LOW 0x01 +#define APM_BATT_CRITICAL 0x02 +#define APM_BATT_CHARGING 0x03 +#define APM_BATT_UNKNOWN 0xff +#define APM_BATT_FLAG_HIGH 0x01 +#define APM_BATT_FLAG_LOW 0x02 +#define APM_BATT_FLAG_CRITICAL 0x04 +#define APM_BATT_FLAG_CHARGING 0x08 +#define APM_BATT_FLAG_NOBATTERY 0x10 +#define APM_BATT_FLAG_NOSYSBATT 0x80 +#define APM_BATT_LIFE_UNKNOWN 0xff +#define BATT_STATE(regp) ((regp)->bx & 0xff) +#define BATT_FLAGS(regp) (((regp)->cx & 0xff00) >> 8) +#define AC_STATE(regp) (((regp)->bx & 0xff00) >> 8) +#define BATT_LIFE(regp) ((regp)->cx & 0xff) /* in % */ +/* Return time in minutes. According to the APM 1.2 spec: + DX = Remaining battery life -- time units + Bit 15 = 0 Time units are seconds + = 1 Time units are minutes + Bits 14-0 = Number of seconds or minutes */ +#define BATT_REMAINING(regp) (((regp)->dx & 0x8000) ? \ + ((regp)->dx & 0x7fff) : \ + ((regp)->dx & 0x7fff)/60) +#define BATT_REM_VALID(regp) (((regp)->dx & 0xffff) != 0xffff) +#define BATT_COUNT(regp) ((regp)->si) + +#define APM_GET_PM_EVENT 0x530b +#define APM_NOEVENT 0x0000 +#define APM_STANDBY_REQ 0x0001 /* %bx on return */ +#define APM_SUSPEND_REQ 0x0002 +#define APM_NORMAL_RESUME 0x0003 +#define APM_CRIT_RESUME 0x0004 /* suspend/resume happened + without us */ +#define APM_BATTERY_LOW 0x0005 +#define APM_POWER_CHANGE 0x0006 +#define APM_UPDATE_TIME 0x0007 +#define APM_CRIT_SUSPEND_REQ 0x0008 +#define APM_USER_STANDBY_REQ 0x0009 +#define APM_USER_SUSPEND_REQ 0x000A +#define APM_SYS_STANDBY_RESUME 0x000B +#define APM_CAPABILITY_CHANGE 0x000C /* apm v1.2 */ +/* 0x000d - 0x00ff Reserved system events */ +#define APM_USER_HIBERNATE_REQ 0x000D +/* 0x0100 - 0x01ff Reserved device events */ +/* 0x0200 - 0x02ff OEM-defined APM events */ +/* 0x0300 - 0xffff Reserved */ +#define APM_EVENT_MASK 0xffff + +#define APM_EVENT_COMPOSE(t,i) ((((i) & 0x7fff) << 16)|((t) & APM_EVENT_MASK)) +#define APM_EVENT_TYPE(e) ((e) & APM_EVENT_MASK) +#define APM_EVENT_INDEX(e) ((e) >> 16) + +#define APM_GET_POWER_STATE 0x530c +#define APM_DEVICE_MGMT_ENABLE 0x530d + +#define APM_DRIVER_VERSION 0x530e +/* %bx should be DEV value (APM_DEV_APM_BIOS) + %ch = driver major vno + %cl = driver minor vno + return: %ah = conn major; %al = conn minor + */ +#define APM_CONN_MINOR(regp) ((regp)->ax & 0xff) +#define APM_CONN_MAJOR(regp) (((regp)->ax & 0xff00) >> 8) + +#define APM_PWR_MGT_ENGAGE 0x530F +#define APM_MGT_DISENGAGE 0x0 /* %cx */ +#define APM_MGT_ENGAGE 0x1 + +/* %bx - APM_DEV_APM_BIOS + * %bl - number of batteries + * %cx - capabilities + */ +#define APM_GET_CAPABILITIES 0x5310 +#define APM_NBATTERIES(regp) ((regp)->bx) +#define APM_GLOBAL_STANDBY 0x0001 +#define APM_GLOBAL_SUSPEND 0x0002 +#define APM_RTIMER_STANDBY 0x0004 /* resume time wakes up */ +#define APM_RTIMER_SUSPEND 0x0008 +#define APM_IRRING_STANDBY 0x0010 /* internal ring wakes up */ +#define APM_IRRING_SUSPEND 0x0020 +#define APM_PCCARD_STANDBY 0x0040 /* pccard wakes up */ +#define APM_PCCARD_SUSPEND 0x0080 + +/* %bx - APM_DEV_APM_BIOS + * %cl - function + * for %cl=2 (set resume timer) + * %ch - seconds in BCD + * %dh - hours in BCD + * %dl - minutes in BCD + * %si - month in BCD (high), day in BCD (low) + * %di - year in BCD + */ +#define APM_RESUME_TIMER 0x5311 +#define APM_RT_DISABLE 0x0 +#define APM_RT_GET 0x1 +#define APM_RT_SET 0x2 + +/* %bx - APM_DEV_APM_BIOS + * %cx - function + */ +#define APM_RESUME_ON_RING 0x5312 +#define APM_ROR_DISABLE 0x0 +#define APM_ROR_ENABLE 0x1 +#define APM_ROR_STATUS 0x2 + +/* %bx - APM_EDV_APM_BIOS + * %cx - function + */ +#define APM_INACTIVITY_TIMER 0x5313 +#define APM_IT_DISABLE 0x0 +#define APM_IT_ENABLE 0x1 +#define APM_IT_STATUS 0x2 + +/* %bh - function */ +#define APM_OEM 0x5380 +#define APM_OEM_INSTCHECK 0x7f /* %bx - OEM ID */ + +/* + * LP (Laptop Package) + * + * Copyright (C) 1994 by HOSOKAWA Tatsumi + * + * This software may be used, modified, copied, and distributed, in + * both source and binary form provided that the above copyright and + * these terms are retained. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with its + * use. + * + * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) + */ + +#define APM_BATTERY_ABSENT 4 + +struct apm_power_info { + u_char battery_state; + u_char ac_state; + u_char battery_life; + u_char spare1; + u_int minutes_left; /* estimate */ + u_int spare2[6]; +}; + +struct apm_ctl { + u_int dev; + u_int mode; +}; + +#define APM_IOC_REJECT _IOW('A', 0, struct apm_event_info) /* reject request # */ +#define APM_IOC_STANDBY _IO('A', 1) /* put system into standby */ +#define APM_IOC_SUSPEND _IO('A', 2) /* put system into suspend */ +#define APM_IOC_GETPOWER _IOR('A', 3, struct apm_power_info) /* fetch battery state */ +#define APM_IOC_DEV_CTL _IOW('A', 5, struct apm_ctl) /* put device into mode */ +#define APM_IOC_PRN_CTL _IOW('A', 6, int ) /* driver power status msg */ +#define APM_PRINT_ON 0 /* driver power status displayed */ +#define APM_PRINT_OFF 1 /* driver power status not displayed */ +#define APM_PRINT_PCT 2 /* driver power status only displayed + if the percentage changes */ +#define APM_IOC_STANDBY_REQ _IO('A', 7) /* request standby */ +#define APM_IOC_SUSPEND_REQ _IO('A', 8) /* request suspend */ +#define APM_IOC_HIBERNATE _IO('A', 9) /* put system into hibernate */ + + +#ifdef _KERNEL +extern void apm_cpu_busy(void); +extern void apm_cpu_idle(void); +extern void apminit(void); +int apm_set_powstate(u_int devid, u_int powstate); +#endif /* _KERNEL */ + +#endif /* _MACHINE_APMVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/asm.h b/lib/libc/include/x86-openbsd-none/i386/asm.h new file mode 100644 index 000000000000..c5b22ef4f4d1 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/asm.h @@ -0,0 +1,131 @@ +/* $OpenBSD: asm.h,v 1.19 2022/12/08 01:25:45 guenther Exp $ */ +/* $NetBSD: asm.h,v 1.7 1994/10/27 04:15:56 cgd Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)asm.h 5.5 (Berkeley) 5/7/91 + */ + +#ifndef _MACHINE_ASM_H_ +#define _MACHINE_ASM_H_ + +#ifdef __PIC__ +#define PIC_PROLOGUE \ + pushl %ebx; \ + call 666f; \ +666: \ + popl %ebx; \ + addl $_GLOBAL_OFFSET_TABLE_+[.-666b], %ebx +#define PIC_EPILOGUE \ + popl %ebx +#define PIC_PLT(x) x@PLT +#define PIC_GOT(x) x@GOT(%ebx) +#define PIC_GOTOFF(x) x@GOTOFF(%ebx) +#else +#define PIC_PROLOGUE +#define PIC_EPILOGUE +#define PIC_PLT(x) x +#define PIC_GOT(x) x +#define PIC_GOTOFF(x) x +#endif + +#define _C_LABEL(name) name +#define _ASM_LABEL(x) x + +#define CVAROFF(x, y) x + y + +#ifdef __STDC__ +# define __CONCAT(x,y) x ## y +# define __STRING(x) #x +#else +# define __CONCAT(x,y) x/**/y +# define __STRING(x) "x" +#endif + +/* + * STRONG_ALIAS, WEAK_ALIAS + * Create a strong or weak alias. + */ +#define STRONG_ALIAS(alias,sym) \ + .global alias; \ + alias = sym +#define WEAK_ALIAS(alias,sym) \ + .weak alias; \ + alias = sym + +/* let kernels and others override entrypoint alignment */ +#ifndef _ALIGN_TEXT +# define _ALIGN_TEXT .align 2, 0x90 +#endif + +/* NB == No Binding: use .globl or .weak as necessary */ +#define _ENTRY_NB(x) \ + .text; _ALIGN_TEXT; .type x,@function; x: +#define _ENTRY(x) .globl x; _ENTRY_NB(x) + +#ifdef _KERNEL +#define KUTEXT .section .kutext, "ax" + +#define IDTVEC(name) \ + KUTEXT; ALIGN_TEXT; \ + .globl X##name; X##name: +#define KIDTVEC(name) \ + .text; ALIGN_TEXT; \ + .globl X##name; X##name: +#define KUENTRY(x) \ + KUTEXT; _ALIGN_TEXT; .globl x; .type x,@function; x: + +#endif /* _KERNEL */ + +#if defined(PROF) || defined(GPROF) +# define _PROF_PROLOGUE \ + pushl %ebp; movl %esp,%ebp; call PIC_PLT(mcount); popl %ebp +#else +# define _PROF_PROLOGUE +#endif + +#define ENTRY(y) _ENTRY(y); _PROF_PROLOGUE +#define ENTRY_NB(y) _ENTRY_NB(y); _PROF_PROLOGUE +#define NENTRY(y) _ENTRY(y) +#define ASENTRY(y) _ENTRY(y); _PROF_PROLOGUE +#define NASENTRY(y) _ENTRY(y) +#define END(y) .size y, . - y + +#define ALTENTRY(name) .globl name; name: + +#ifdef _KERNEL + +#define CPUVAR(var) %fs:__CONCAT(CPU_INFO_,var) + +#endif /* _KERNEL */ + +#endif /* !_MACHINE_ASM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/atomic.h b/lib/libc/include/x86-openbsd-none/i386/atomic.h new file mode 100644 index 000000000000..ef6a8301b468 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/atomic.h @@ -0,0 +1,316 @@ +/* $OpenBSD: atomic.h,v 1.20 2022/08/29 02:01:18 jsg Exp $ */ +/* $NetBSD: atomic.h,v 1.1.2.2 2000/02/21 18:54:07 sommerfeld Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_ATOMIC_H_ +#define _MACHINE_ATOMIC_H_ + +/* + * Perform atomic operations on memory. Should be atomic with respect + * to interrupts and multiple processors. + * + * void atomic_setbits_int(volatile u_int *a, u_int mask) { *a |= mask; } + * void atomic_clearbits_int(volatile u_int *a, u_int mas) { *a &= ~mask; } + */ +#if !defined(_LOCORE) + +#if defined(MULTIPROCESSOR) || !defined(_KERNEL) +#define _LOCK "lock" +#else +#define _LOCK +#endif + +static inline unsigned int +_atomic_cas_uint(volatile unsigned int *p, unsigned int e, unsigned int n) +{ + __asm volatile(_LOCK " cmpxchgl %2, %1" + : "=a" (n), "=m" (*p) + : "r" (n), "a" (e), "m" (*p)); + + return (n); +} +#define atomic_cas_uint(_p, _e, _n) _atomic_cas_uint((_p), (_e), (_n)) + +static inline unsigned long +_atomic_cas_ulong(volatile unsigned long *p, unsigned long e, unsigned long n) +{ + __asm volatile(_LOCK " cmpxchgl %2, %1" + : "=a" (n), "=m" (*p) + : "r" (n), "a" (e), "m" (*p)); + + return (n); +} +#define atomic_cas_ulong(_p, _e, _n) _atomic_cas_ulong((_p), (_e), (_n)) + +static inline void * +_atomic_cas_ptr(volatile void *p, void *e, void *n) +{ + __asm volatile(_LOCK " cmpxchgl %2, %1" + : "=a" (n), "=m" (*(unsigned long *)p) + : "r" (n), "a" (e), "m" (*(unsigned long *)p)); + + return (n); +} +#define atomic_cas_ptr(_p, _e, _n) _atomic_cas_ptr((_p), (_e), (_n)) + +static inline unsigned int +_atomic_swap_uint(volatile unsigned int *p, unsigned int n) +{ + __asm volatile("xchgl %0, %1" + : "=a" (n), "=m" (*p) + : "0" (n), "m" (*p)); + + return (n); +} +#define atomic_swap_uint(_p, _n) _atomic_swap_uint((_p), (_n)) +#define atomic_swap_32(_p, _n) _atomic_swap_uint((_p), (_n)) + +static inline unsigned long +_atomic_swap_ulong(volatile unsigned long *p, unsigned long n) +{ + __asm volatile("xchgl %0, %1" + : "=a" (n), "=m" (*p) + : "0" (n), "m" (*p)); + + return (n); +} +#define atomic_swap_ulong(_p, _n) _atomic_swap_ulong((_p), (_n)) + +static inline void * +_atomic_swap_ptr(volatile void *p, void *n) +{ + __asm volatile("xchgl %0, %1" + : "=a" (n), "=m" (*(unsigned long *)p) + : "0" (n), "m" (*(unsigned long *)p)); + + return (n); +} +#define atomic_swap_ptr(_p, _n) _atomic_swap_ptr((_p), (_n)) + +static inline void +_atomic_inc_int(volatile unsigned int *p) +{ + __asm volatile(_LOCK " incl %0" + : "+m" (*p)); +} +#define atomic_inc_int(_p) _atomic_inc_int(_p) + +static inline void +_atomic_inc_long(volatile unsigned long *p) +{ + __asm volatile(_LOCK " incl %0" + : "+m" (*p)); +} +#define atomic_inc_long(_p) _atomic_inc_long(_p) + +static inline void +_atomic_dec_int(volatile unsigned int *p) +{ + __asm volatile(_LOCK " decl %0" + : "+m" (*p)); +} +#define atomic_dec_int(_p) _atomic_dec_int(_p) + +static inline void +_atomic_dec_long(volatile unsigned long *p) +{ + __asm volatile(_LOCK " decl %0" + : "+m" (*p)); +} +#define atomic_dec_long(_p) _atomic_dec_long(_p) + +static inline void +_atomic_add_int(volatile unsigned int *p, unsigned int v) +{ + __asm volatile(_LOCK " addl %1,%0" + : "+m" (*p) + : "a" (v)); +} +#define atomic_add_int(_p, _v) _atomic_add_int(_p, _v) + +static inline void +_atomic_add_long(volatile unsigned long *p, unsigned long v) +{ + __asm volatile(_LOCK " addl %1,%0" + : "+m" (*p) + : "a" (v)); +} +#define atomic_add_long(_p, _v) _atomic_add_long(_p, _v) + +static inline void +_atomic_sub_int(volatile unsigned int *p, unsigned int v) +{ + __asm volatile(_LOCK " subl %1,%0" + : "+m" (*p) + : "a" (v)); +} +#define atomic_sub_int(_p, _v) _atomic_sub_int(_p, _v) + +static inline void +_atomic_sub_long(volatile unsigned long *p, unsigned long v) +{ + __asm volatile(_LOCK " subl %1,%0" + : "+m" (*p) + : "a" (v)); +} +#define atomic_sub_long(_p, _v) _atomic_sub_long(_p, _v) + + +static inline unsigned long +_atomic_add_int_nv(volatile unsigned int *p, unsigned int v) +{ + unsigned int rv = v; + + __asm volatile(_LOCK " xaddl %0,%1" + : "+a" (rv), "+m" (*p)); + + return (rv + v); +} +#define atomic_add_int_nv(_p, _v) _atomic_add_int_nv(_p, _v) + +static inline unsigned long +_atomic_add_long_nv(volatile unsigned long *p, unsigned long v) +{ + unsigned long rv = v; + + __asm volatile(_LOCK " xaddl %0,%1" + : "+a" (rv), "+m" (*p)); + + return (rv + v); +} +#define atomic_add_long_nv(_p, _v) _atomic_add_long_nv(_p, _v) + +static inline unsigned long +_atomic_sub_int_nv(volatile unsigned int *p, unsigned int v) +{ + unsigned int rv = 0 - v; + + __asm volatile(_LOCK " xaddl %0,%1" + : "+a" (rv), "+m" (*p)); + + return (rv - v); +} +#define atomic_sub_int_nv(_p, _v) _atomic_sub_int_nv(_p, _v) + +static inline unsigned long +_atomic_sub_long_nv(volatile unsigned long *p, unsigned long v) +{ + unsigned long rv = 0 - v; + + __asm volatile(_LOCK " xaddl %0,%1" + : "+a" (rv), "+m" (*p)); + + return (rv - v); +} +#define atomic_sub_long_nv(_p, _v) _atomic_sub_long_nv(_p, _v) + +/* + * The IA-32 architecture is rather strongly ordered. When accessing + * normal write-back cacheable memory, only reads may be reordered with + * older writes to different locations. There are a few instructions + * (clfush, non-temporal move instructions) that obey weaker ordering + * rules, but those instructions will only be used in (inline) + * assembly code where we can add the necessary fence instructions + * ourselves. + */ + +#define __membar(_f) do { __asm volatile(_f ::: "memory"); } while (0) + +#if defined(MULTIPROCESSOR) || !defined(_KERNEL) +#define membar_enter() __membar("lock; addl $0,0(%%esp)") +#define membar_exit() __membar("") +#define membar_producer() __membar("") +#define membar_consumer() __membar("") +#define membar_sync() __membar("lock; addl $0,0(%%esp)") +#else +#define membar_enter() __membar("") +#define membar_exit() __membar("") +#define membar_producer() __membar("") +#define membar_consumer() __membar("") +#define membar_sync() __membar("") +#endif + +#define membar_enter_after_atomic() __membar("") +#define membar_exit_before_atomic() __membar("") + +#ifdef _KERNEL + +/* virtio needs MP membars even on SP kernels */ +#define virtio_membar_producer() __membar("") +#define virtio_membar_consumer() __membar("") +#define virtio_membar_sync() __membar("lock; addl $0,0(%%esp)") + +static __inline u_int64_t +i386_atomic_testset_uq(volatile u_int64_t *ptr, u_int64_t val) +{ + __asm__ volatile ("\n1:\t" _LOCK " cmpxchg8b (%1); jnz 1b" : "+A" (val) : + "r" (ptr), "b" ((u_int32_t)val), "c" ((u_int32_t)(val >> 32))); + return val; +} + +static __inline u_int32_t +i386_atomic_testset_ul(volatile u_int32_t *ptr, unsigned long val) +{ + __asm__ volatile ("xchgl %0,(%2)" :"=r" (val):"0" (val),"r" (ptr)); + return val; +} + +static __inline int +i386_atomic_testset_i(volatile int *ptr, unsigned long val) +{ + __asm__ volatile ("xchgl %0,(%2)" :"=r" (val):"0" (val),"r" (ptr)); + return val; +} + +static __inline void +i386_atomic_setbits_l(volatile u_int32_t *ptr, unsigned long bits) +{ + __asm volatile(_LOCK " orl %1,%0" : "=m" (*ptr) : "ir" (bits)); +} + +static __inline void +i386_atomic_clearbits_l(volatile u_int32_t *ptr, unsigned long bits) +{ + bits = ~bits; + __asm volatile(_LOCK " andl %1,%0" : "=m" (*ptr) : "ir" (bits)); +} + +#define atomic_setbits_int i386_atomic_setbits_l +#define atomic_clearbits_int i386_atomic_clearbits_l + +#endif /* _KERNEL */ + +#undef _LOCK + +#endif /* !defined(_LOCORE) */ +#endif /* _MACHINE_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/biosvar.h b/lib/libc/include/x86-openbsd-none/i386/biosvar.h new file mode 100644 index 000000000000..db9769bb7ce0 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/biosvar.h @@ -0,0 +1,306 @@ +/* $OpenBSD: biosvar.h,v 1.68 2019/08/04 14:28:58 kettenis Exp $ */ + +/* + * Copyright (c) 1997-1999 Michael Shalayeff + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES 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 MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BIOSVAR_H_ +#define _MACHINE_BIOSVAR_H_ + + /* some boxes put apm data seg in the 2nd page */ +#define BOOTARG_OFF (PAGE_SIZE * 2) +#define BOOTARG_LEN (PAGE_SIZE * 1) +#define BOOTBIOS_ADDR (0x7c00) +#define BOOTBIOS_MAXSEC ((1 << 28) - 1) + + /* BIOS configure flags */ +#define BIOSF_BIOS32 0x0001 +#define BIOSF_PCIBIOS 0x0002 +#define BIOSF_PROMSCAN 0x0004 +#define BIOSF_SMBIOS 0x0008 + +/* BIOS media ID */ +#define BIOSM_F320K 0xff /* floppy ds/sd 8 spt */ +#define BIOSM_F160K 0xfe /* floppy ss/sd 8 spt */ +#define BIOSM_F360K 0xfd /* floppy ds/sd 9 spt */ +#define BIOSM_F180K 0xfc /* floppy ss/sd 9 spt */ +#define BIOSM_ROMD 0xfa /* ROM disk */ +#define BIOSM_F120M 0xf9 /* floppy ds/hd 15 spt 5.25" */ +#define BIOSM_F720K 0xf9 /* floppy ds/dd 9 spt 3.50" */ +#define BIOSM_HD 0xf8 /* hard drive */ +#define BIOSM_F144K 0xf0 /* floppy ds/hd 18 spt 3.50" */ +#define BIOSM_OTHER 0xf0 /* any other */ + +/* + * BIOS memory maps + */ +#define BIOS_MAP_END 0x00 /* End of array XXX - special */ +#define BIOS_MAP_FREE 0x01 /* Usable memory */ +#define BIOS_MAP_RES 0x02 /* Reserved memory */ +#define BIOS_MAP_ACPI 0x03 /* ACPI Reclaim memory */ +#define BIOS_MAP_NVS 0x04 /* ACPI NVS memory */ + +/* + * Optional ROM header + */ +typedef +struct bios_romheader { + uint16_t signature; /* 0xaa55 */ + uint8_t len; /* length in pages (512 bytes) */ + uint32_t entry; /* initialization entry point */ + uint8_t reserved[19]; + uint16_t pnpheader; /* offset to PnP expansion header */ +} __packed *bios_romheader_t; + +/* + * BIOS32 + */ +typedef +struct bios32_header { + uint32_t signature; /* 00: signature "_32_" */ + uint32_t entry; /* 04: entry point */ + uint8_t rev; /* 08: revision */ + uint8_t length; /* 09: header length */ + uint8_t cksum; /* 0a: modulo 256 checksum */ + uint8_t reserved[5]; +} __packed *bios32_header_t; + +typedef +struct bios32_entry_info { + uint32_t bei_base; + uint32_t bei_size; + uint32_t bei_entry; +} __packed *bios32_entry_info_t; + +typedef +struct bios32_entry { + uint32_t offset; + uint16_t segment; +} __packed *bios32_entry_t; + +#define BIOS32_START 0xe0000 +#define BIOS32_SIZE 0x20000 +#define BIOS32_END (BIOS32_START + BIOS32_SIZE - 0x10) + +#define BIOS32_MAKESIG(a, b, c, d) \ + ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24)) +#define BIOS32_SIGNATURE BIOS32_MAKESIG('_', '3', '2', '_') +#define PCIBIOS_SIGNATURE BIOS32_MAKESIG('$', 'P', 'C', 'I') +#define SMBIOS_SIGNATURE BIOS32_MAKESIG('_', 'S', 'M', '_') + +/* + * CTL_BIOS definitions. + */ +#define BIOS_DEV 1 /* int: BIOS boot device */ +#define BIOS_DISKINFO 2 /* struct: BIOS boot device info */ +#define BIOS_CKSUMLEN 3 /* int: disk cksum block count */ +#define BIOS_MAXID 4 /* number of valid machdep ids */ + +#define CTL_BIOS_NAMES { \ + { 0, 0 }, \ + { "biosdev", CTLTYPE_INT }, \ + { "diskinfo", CTLTYPE_STRUCT }, \ + { "cksumlen", CTLTYPE_INT }, \ +} + +#define BOOTARG_MEMMAP 0 +typedef struct _bios_memmap { + uint64_t addr; /* Beginning of block */ + uint64_t size; /* Size of block */ + uint32_t type; /* Type of block */ +} __packed bios_memmap_t; + +/* Info about disk from the bios, plus the mapping from + * BIOS numbers to BSD major (driver?) number. + * + * Also, do not bother with BIOSN*() macros, just parcel + * the info out, and use it like this. This makes for less + * of a dependence on BIOSN*() macros having to be the same + * across /boot, /bsd, and userland. + */ +#define BOOTARG_DISKINFO 1 +typedef struct _bios_diskinfo { + /* BIOS section */ + int bios_number; /* BIOS number of drive (or -1) */ + u_int bios_cylinders; /* BIOS cylinders */ + u_int bios_heads; /* BIOS heads */ + u_int bios_sectors; /* BIOS sectors */ + int bios_edd; /* EDD support */ + + /* BSD section */ + dev_t bsd_dev; /* BSD device */ + + /* Checksum section */ + uint32_t checksum; /* Checksum for drive */ + + /* Misc. flags */ + uint32_t flags; +#define BDI_INVALID 0x00000001 /* I/O error during checksumming */ +#define BDI_GOODLABEL 0x00000002 /* Had SCSI or ST506/ESDI disklabel */ +#define BDI_BADLABEL 0x00000004 /* Had another disklabel */ +#define BDI_EL_TORITO 0x00000008 /* 2,048-byte sectors */ +#define BDI_HIBVALID 0x00000010 /* hibernate signature valid */ +#define BDI_PICKED 0x80000000 /* kernel-only: cksum matched */ + +} __packed bios_diskinfo_t; + +#define BOOTARG_APMINFO 2 +typedef struct _bios_apminfo { + /* APM_CONNECT returned values */ + u_int apm_detail; + u_int apm_code32_base; + u_int apm_code16_base; + u_int apm_code_len; + u_int apm_data_base; + u_int apm_data_len; + u_int apm_entry; + u_int apm_code16_len; +} __packed bios_apminfo_t; + +#define BOOTARG_CKSUMLEN 3 /* uint32_t */ + +#define BOOTARG_PCIINFO 4 +typedef struct _bios_pciinfo { + /* PCI BIOS v2.0+ - Installation check values */ + uint32_t pci_chars; /* Characteristics (%eax) */ + uint32_t pci_rev; /* BCD Revision (%ebx) */ + uint32_t pci_entry32; /* PM entry point for PCI BIOS */ + uint32_t pci_lastbus; /* Number of last PCI bus */ +} __packed bios_pciinfo_t; + +#define BOOTARG_CONSDEV 5 +typedef struct _bios_consdev { + dev_t consdev; + int conspeed; + int consaddr; + int consfreq; +} __packed bios_consdev_t; + +#define BOOTARG_SMPINFO 6 /* struct mp_float[] */ + +#define BOOTARG_BOOTMAC 7 +typedef struct _bios_bootmac { + char mac[6]; +} __packed bios_bootmac_t; + +#define BOOTARG_DDB 8 +typedef struct _bios_ddb { + int db_console; +} __packed bios_ddb_t; + +#define BOOTARG_BOOTDUID 9 +typedef struct _bios_bootduid { + u_char duid[8]; +} __packed bios_bootduid_t; + +#define BOOTARG_BOOTSR 10 +#define BOOTSR_UUID_MAX 16 +#define BOOTSR_CRYPTO_MAXKEYBYTES 32 +typedef struct _bios_bootsr { + uint8_t uuid[BOOTSR_UUID_MAX]; + uint8_t maskkey[BOOTSR_CRYPTO_MAXKEYBYTES]; +} __packed bios_bootsr_t; + +#define BOOTARG_EFIINFO 11 +typedef struct _bios_efiinfo { + uint64_t config_acpi; + uint64_t config_smbios; + uint64_t fb_addr; + uint64_t fb_size; + uint32_t fb_height; + uint32_t fb_width; + uint32_t fb_pixpsl; /* pixels per scan line */ + uint32_t fb_red_mask; + uint32_t fb_green_mask; + uint32_t fb_blue_mask; + uint32_t fb_reserved_mask; +} __packed bios_efiinfo_t; + +#define BOOTARG_UCODE 12 +typedef struct _bios_ucode { + uint64_t uc_addr; + uint64_t uc_size; +} __packed bios_ucode_t; + +#if defined(_KERNEL) || defined (_STANDALONE) + +#ifdef _LOCORE +#define DOINT(n) int $0x20+(n) +#else +#define DOINT(n) "int $0x20+(" #n ")" + +extern volatile struct BIOS_regs { + uint32_t biosr_ax; + uint32_t biosr_cx; + uint32_t biosr_dx; + uint32_t biosr_bx; + uint32_t biosr_bp; + uint32_t biosr_si; + uint32_t biosr_di; + uint32_t biosr_ds; + uint32_t biosr_es; +} __packed BIOS_regs; + +#ifdef _KERNEL +#include + +struct bios_attach_args { + char *ba_name; + u_int ba_func; + bus_space_tag_t ba_iot; + bus_space_tag_t ba_memt; + union { + void *_p; + bios_apminfo_t *_ba_apmp; + paddr_t _ba_acpipbase; + } _; +}; + +#define ba_apmp _._ba_apmp +#define ba_acpipbase _._ba_acpipbase + +struct consdev; +struct proc; + +int bios_sysctl(int *, u_int, void *, size_t *, void *, size_t, struct proc *); + +void bios_getopt(void); + +/* bios32.c */ +int bios32_service(uint32_t, bios32_entry_t, bios32_entry_info_t); +void bios32_cleanup(void); + +extern u_int bootapiver; +extern bios_memmap_t *bios_memmap; +extern bios_efiinfo_t *bios_efiinfo; +extern bios_ucode_t *bios_ucode; +extern void *bios_smpinfo; +extern bios_pciinfo_t *bios_pciinfo; + +#endif /* _KERNEL */ +#endif /* _LOCORE */ +#endif /* _KERNEL || _STANDALONE */ + +#endif /* _MACHINE_BIOSVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/bus.h b/lib/libc/include/x86-openbsd-none/i386/bus.h new file mode 100644 index 000000000000..6ed2cb5fb72f --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/bus.h @@ -0,0 +1,701 @@ +/* $OpenBSD: bus.h,v 1.67 2017/05/08 00:27:45 dlg Exp $ */ +/* $NetBSD: bus.h,v 1.6 1996/11/10 03:19:25 thorpej Exp $ */ + +/*- + * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1996 Charles M. Hannum. All rights reserved. + * Copyright (c) 1996 Jason R. Thorpe. All rights reserved. + * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BUS_H_ +#define _MACHINE_BUS_H_ + +#include +#include + +#include + +/* + * Bus address and size types + */ +typedef u_long bus_addr_t; +typedef u_long bus_size_t; + +/* + * Access methods for bus resources and address space. + */ +struct i386_bus_space_ops; +typedef const struct i386_bus_space_ops *bus_space_tag_t; +typedef u_long bus_space_handle_t; + +int bus_space_map(bus_space_tag_t t, bus_addr_t addr, + bus_size_t size, int flags, bus_space_handle_t *bshp); +/* like bus_space_map(), but without extent map checking/allocation */ +int _bus_space_map(bus_space_tag_t t, bus_addr_t addr, + bus_size_t size, int flags, bus_space_handle_t *bshp); +void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t size); +/* like bus_space_unmap(), but without extent map deallocation */ +void _bus_space_unmap(bus_space_tag_t, bus_space_handle_t, + bus_size_t, bus_addr_t *); +int bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp); +paddr_t bus_space_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int); + +int bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart, + bus_addr_t rend, bus_size_t size, bus_size_t align, + bus_size_t boundary, int flags, bus_addr_t *addrp, + bus_space_handle_t *bshp); +void bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t size); + +struct i386_bus_space_ops { + +/* + * u_intN_t bus_space_read_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset); + * + * Read a 1, 2, 4, or 8 byte quantity from bus space + * described by tag/handle/offset. + */ + u_int8_t (*read_1)(bus_space_handle_t, bus_size_t); + u_int16_t (*read_2)(bus_space_handle_t, bus_size_t); + u_int32_t (*read_4)(bus_space_handle_t, bus_size_t); + +#define bus_space_read_1(_t, _h, _o) ((_t)->read_1((_h), (_o))) +#define bus_space_read_2(_t, _h, _o) ((_t)->read_2((_h), (_o))) +#define bus_space_read_4(_t, _h, _o) ((_t)->read_4((_h), (_o))) + +#define bus_space_read_raw_2(t, h, o) \ + bus_space_read_2((t), (h), (o)) +#define bus_space_read_raw_4(t, h, o) \ + bus_space_read_4((t), (h), (o)) + +#if 0 +/* Cause a link error for bus_space_read_8 and bus_space_read_raw_8 */ +#define bus_space_read_8(t, h, o) !!! bus_space_read_8 unimplemented !!! +#define bus_space_read_raw_8(t, h, o) !!! bus_space_read_raw_8 unimplemented !!! +#endif + +/* + * void bus_space_read_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t *addr, size_t count); + * + * Read `count' 1, 2, 4, or 8 byte quantities from bus space + * described by tag/handle/offset and copy into buffer provided. + */ + + void (*read_multi_1)(bus_space_handle_t, bus_size_t, + u_int8_t *, bus_size_t); + void (*read_multi_2)(bus_space_handle_t, bus_size_t, + u_int16_t *, bus_size_t); + void (*read_multi_4)(bus_space_handle_t, bus_size_t, + u_int32_t *, bus_size_t); + +#define bus_space_read_multi_1(_t, _h, _o, _a, _c) \ + ((_t)->read_multi_1((_h), (_o), (_a), (_c))) +#define bus_space_read_multi_2(_t, _h, _o, _a, _c) \ + ((_t)->read_multi_2((_h), (_o), (_a), (_c))) +#define bus_space_read_multi_4(_t, _h, _o, _a, _c) \ + ((_t)->read_multi_4((_h), (_o), (_a), (_c))) + +#if 0 /* Cause a link error for bus_space_read_multi_8 */ +#define bus_space_read_multi_8 !!! bus_space_read_multi_8 unimplemented !!! +#endif + +/* + * void bus_space_read_raw_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_int8_t *addr, size_t count); + * + * Read `count' bytes in 2, 4 or 8 byte wide quantities from bus space + * described by tag/handle/offset and copy into buffer provided. The buffer + * must have proper alignment for the N byte wide entities. Furthermore + * possible byte-swapping should be done by these functions. + */ + +#define bus_space_read_raw_multi_2(t, h, o, a, c) \ + bus_space_read_multi_2((t), (h), (o), (u_int16_t *)(a), (c) >> 1) +#define bus_space_read_raw_multi_4(t, h, o, a, c) \ + bus_space_read_multi_4((t), (h), (o), (u_int32_t *)(a), (c) >> 2) + +#if 0 /* Cause a link error for bus_space_read_raw_multi_8 */ +#define bus_space_read_raw_multi_8 \ + !!! bus_space_read_raw_multi_8 unimplemented !!! +#endif + +/* + * void bus_space_read_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t *addr, size_t count); + * + * Read `count' 1, 2, 4, or 8 byte quantities from bus space + * described by tag/handle and starting at `offset' and copy into + * buffer provided. + */ + + void (*read_region_1)(bus_space_handle_t, + bus_size_t, u_int8_t *, bus_size_t); + void (*read_region_2)(bus_space_handle_t, + bus_size_t, u_int16_t *, bus_size_t); + void (*read_region_4)(bus_space_handle_t, + bus_size_t, u_int32_t *, bus_size_t); + +#define bus_space_read_region_1(_t, _h, _o, _a, _c) \ + ((_t)->read_region_1((_h), (_o), (_a), (_c))) +#define bus_space_read_region_2(_t, _h, _o, _a, _c) \ + ((_t)->read_region_2((_h), (_o), (_a), (_c))) +#define bus_space_read_region_4(_t, _h, _o, _a, _c) \ + ((_t)->read_region_4((_h), (_o), (_a), (_c))) + +#if 0 /* Cause a link error for bus_space_read_region_8 */ +#define bus_space_read_region_8 !!! bus_space_read_region_8 unimplemented !!! +#endif + +/* + * void bus_space_read_raw_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_int8_t *addr, size_t count); + * + * Read `count' bytes in 2, 4 or 8 byte wide quantities from bus space + * described by tag/handle and starting at `offset' and copy into + * buffer provided. The buffer must have proper alignment for the N byte + * wide entities. Furthermore possible byte-swapping should be done by + * these functions. + */ + +#define bus_space_read_raw_region_2(_t, _h, _o, _a, _c) \ + ((_t)->read_region_2((_h), (_o), (u_int16_t *)(_a), (_c) >> 1)) +#define bus_space_read_raw_region_4(_t, _h, _o, _a, _c) \ + ((_t)->read_region_4((_h), (_o), (u_int32_t *)(_a), (_c) >> 2)) + +#if 0 /* Cause a link error for bus_space_read_raw_region_8 */ +#define bus_space_read_raw_region_8 \ + !!! bus_space_read_raw_region_8 unimplemented !!! +#endif + +/* + * void bus_space_write_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t value); + * + * Write the 1, 2, 4, or 8 byte value `value' to bus space + * described by tag/handle/offset. + */ + + void (*write_1)(bus_space_handle_t, bus_size_t, u_int8_t); + void (*write_2)(bus_space_handle_t, bus_size_t, u_int16_t); + void (*write_4)(bus_space_handle_t, bus_size_t, u_int32_t); + +#define bus_space_write_1(_t, _h, _o, _v) \ + ((_t)->write_1((_h), (_o), (_v))) +#define bus_space_write_2(_t, _h, _o, _v) \ + ((_t)->write_2((_h), (_o), (_v))) +#define bus_space_write_4(_t, _h, _o, _v) \ + ((_t)->write_4((_h), (_o), (_v))) + +#define bus_space_write_raw_2(t, h, o, v) \ + bus_space_write_2((t), (h), (o), (v)) +#define bus_space_write_raw_4(t, h, o, v) \ + bus_space_write_4((t), (h), (o), (v)) + +#if 0 +/* Cause a link error for bus_space_write_8 and bus_space_write_raw_8 */ +#define bus_space_write_8 !!! bus_space_write_8 not implemented !!! +#define bus_space_write_raw_8 !!! bus_space_write_raw_8 not implemented !!! +#endif + +/* + * void bus_space_write_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_intN_t *addr, size_t count); + * + * Write `count' 1, 2, 4, or 8 byte quantities from the buffer + * provided to bus space described by tag/handle/offset. + */ + + void (*write_multi_1)(bus_space_handle_t, + bus_size_t, const u_int8_t *, bus_size_t); + void (*write_multi_2)(bus_space_handle_t, + bus_size_t, const u_int16_t *, bus_size_t); + void (*write_multi_4)(bus_space_handle_t, + bus_size_t, const u_int32_t *, bus_size_t); + +#define bus_space_write_multi_1(_t, _h, _o, _a, _c) \ + ((_t)->write_multi_1((_h), (_o), (_a), (_c))) +#define bus_space_write_multi_2(_t, _h, _o, _a, _c) \ + ((_t)->write_multi_2((_h), (_o), (_a), (_c))) +#define bus_space_write_multi_4(_t, _h, _o, _a, _c) \ + ((_t)->write_multi_4((_h), (_o), (_a), (_c))) + +#if 0 /* Cause a link error for bus_space_write_multi_8 */ +#define bus_space_write_multi_8(t, h, o, a, c) \ + !!! bus_space_write_multi_8 unimplemented !!! +#endif + +/* + * void bus_space_write_raw_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_int8_t *addr, size_t count); + * + * Write `count' bytes in 2, 4 or 8 byte wide quantities from the buffer + * provided to bus space described by tag/handle/offset. The buffer + * must have proper alignment for the N byte wide entities. Furthermore + * possible byte-swapping should be done by these functions. + */ + +#define bus_space_write_raw_multi_2(_t, _h, _o, _a, _c) \ + ((_t)->write_multi_2((_h), (_o), (const u_int16_t *)(_a), (_c) >> 1)) +#define bus_space_write_raw_multi_4(_t, _h, _o, _a, _c) \ + ((_t)->write_multi_4((_h), (_o), (const u_int32_t *)(_a), (_c) >> 2)) + +#if 0 /* Cause a link error for bus_space_write_raw_multi_8 */ +#define bus_space_write_raw_multi_8 \ + !!! bus_space_write_raw_multi_8 unimplemented !!! +#endif + +/* + * void bus_space_write_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_intN_t *addr, size_t count); + * + * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided + * to bus space described by tag/handle starting at `offset'. + */ + + void (*write_region_1)(bus_space_handle_t, + bus_size_t, const u_int8_t *, bus_size_t); + void (*write_region_2)(bus_space_handle_t, + bus_size_t, const u_int16_t *, bus_size_t); + void (*write_region_4)(bus_space_handle_t, + bus_size_t, const u_int32_t *, bus_size_t); + +#define bus_space_write_region_1(_t, _h, _o, _a, _c) \ + ((_t)->write_region_1((_h), (_o), (_a), (_c))) +#define bus_space_write_region_2(_t, _h, _o, _a, _c) \ + ((_t)->write_region_2((_h), (_o), (_a), (_c))) +#define bus_space_write_region_4(_t, _h, _o, _a, _c) \ + ((_t)->write_region_4((_h), (_o), (_a), (_c))) + +#if 0 /* Cause a link error for bus_space_write_region_8 */ +#define bus_space_write_region_8 \ + !!! bus_space_write_region_8 unimplemented !!! +#endif + +/* + * void bus_space_write_raw_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_int8_t *addr, size_t count); + * + * Write `count' bytes in 2, 4 or 8 byte wide quantities to bus space + * described by tag/handle and starting at `offset' from the + * buffer provided. The buffer must have proper alignment for the N byte + * wide entities. Furthermore possible byte-swapping should be done by + * these functions. + */ + +#define bus_space_write_raw_region_2(_t, _h, _o, _a, _c) \ + ((_t)->write_region_2((_h), (_o), (const u_int16_t *)(_a), (_c) >> 1)) +#define bus_space_write_raw_region_4(_t, _h, _o, _a, _c) \ + ((_t)->write_region_4((_h), (_o), (const u_int32_t *)(_a), (_c) >> 2)) + +#if 0 /* Cause a link error for bus_space_write_raw_region_8 */ +#define bus_space_write_raw_region_8 \ + !!! bus_space_write_raw_region_8 unimplemented !!! +#endif + +/* + * void bus_space_set_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t val, size_t count); + * + * Write the 1, 2, 4, or 8 byte value `val' to bus space described + * by tag/handle/offset `count' times. + */ + + void (*set_multi_1)(bus_space_handle_t, + bus_size_t, u_int8_t, size_t); + void (*set_multi_2)(bus_space_handle_t, + bus_size_t, u_int16_t, size_t); + void (*set_multi_4)(bus_space_handle_t, + bus_size_t, u_int32_t, size_t); + +#define bus_space_set_multi_1(_t, _h, _o, _a, _c) \ + ((_t)->set_multi_1((_h), (_o), (_a), (_c))) +#define bus_space_set_multi_2(_t, _h, _o, _a, _c) \ + ((_t)->set_multi_2((_h), (_o), (_a), (_c))) +#define bus_space_set_multi_4(_t, _h, _o, _a, _c) \ + ((_t)->set_multi_4((_h), (_o), (_a), (_c))) + +#if 0 /* Cause a link error for bus_space_set_multi_8 */ +#define bus_space_set_multi_8 \ + !!! bus_space_set_multi_8 unimplemented !!! +#endif + +/* + * void bus_space_set_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t val, size_t count); + * + * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described + * by tag/handle starting at `offset'. + */ + + void (*set_region_1)(bus_space_handle_t, + bus_size_t, u_int8_t, size_t); + void (*set_region_2)(bus_space_handle_t, + bus_size_t, u_int16_t, size_t); + void (*set_region_4)(bus_space_handle_t, + bus_size_t, u_int32_t, size_t); + +#define bus_space_set_region_1(_t, _h, _o, _a, _c) \ + ((_t)->set_region_1((_h), (_o), (_a), (_c))) +#define bus_space_set_region_2(_t, _h, _o, _a, _c) \ + ((_t)->set_region_2((_h), (_o), (_a), (_c))) +#define bus_space_set_region_4(_t, _h, _o, _a, _c) \ + ((_t)->set_region_4((_h), (_o), (_a), (_c))) + +#if 0 /* Cause a link error for bus_space_set_region_8 */ +#define bus_space_set_region_8 \ + !!! bus_space_set_region_8 unimplemented !!! +#endif + +/* + * void bus_space_copy_N(bus_space_tag_t tag, + * bus_space_handle_t bsh1, bus_size_t off1, + * bus_space_handle_t bsh2, bus_size_t off2, + * size_t count); + * + * Copy `count' 1, 2, 4, or 8 byte values from bus space starting + * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2. + */ + + void (*copy_1)(bus_space_handle_t, + bus_size_t, bus_space_handle_t, bus_size_t, size_t); + void (*copy_2)(bus_space_handle_t, + bus_size_t, bus_space_handle_t, bus_size_t, size_t); + void (*copy_4)(bus_space_handle_t, + bus_size_t, bus_space_handle_t, bus_size_t, size_t); + +#define bus_space_copy_1(_t, _h1, _o1, _h2, _o2, _c) \ + ((_t)->copy_1((_h1), (_o1), (_h2), (_o2), (_c))) +#define bus_space_copy_2(_t, _h1, _o1, _h2, _o2, _c) \ + ((_t)->copy_2((_h1), (_o1), (_h2), (_o2), (_c))) +#define bus_space_copy_4(_t, _h1, _o1, _h2, _o2, _c) \ + ((_t)->copy_4((_h1), (_o1), (_h2), (_o2), (_c))) + +#if 0 /* Cause a link error for bus_space_copy_8 */ +#define bus_space_copy_8 \ + !!! bus_space_copy_8 unimplemented !!! +#endif + +#define i386_space_copy1(a1, a2, cnt, movs, df) \ + __asm volatile(df "\n\trep\n\t" movs : \ + "+S" (a1), "+D" (a2), "+c" (cnt) :: "memory", "cc"); + +#define i386_space_copy(a1, a2, sz, cnt) do { \ + if ((void *)(a1) < (void *)(a2)) { \ + a1 += ((cnt) - 1) * (sz); a2 += ((cnt) - 1) * (sz); \ + switch (sz) { \ + case 1: i386_space_copy1(a1,a2,cnt,"movsb","std");break;\ + case 2: i386_space_copy1(a1,a2,cnt,"movsw","std");break;\ + case 4: i386_space_copy1(a1,a2,cnt,"movsl","std");break;\ + } \ + __asm volatile("cld"); /* must restore before func ret */ \ + } else \ + switch (sz) { \ + case 1: i386_space_copy1(a1,a2,cnt,"movsb","cld");break;\ + case 2: i386_space_copy1(a1,a2,cnt,"movsw","cld");break;\ + case 4: i386_space_copy1(a1,a2,cnt,"movsl","cld");break;\ + } \ +} while (0) + +/* + * void *bus_space_vaddr(bus_space_tag_t, bus_space_handle_t); + * + * Get the kernel virtual address for the mapped bus space. + * Only allowed for regions mapped with BUS_SPACE_MAP_LINEAR. + */ + void * (*vaddr)(bus_space_handle_t); + +#define bus_space_vaddr(_t, _h) \ + ((_t)->vaddr((_h))) +}; + +/* + * Bus read/write barrier methods. + * + * void bus_space_barrier(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * bus_size_t len, int flags); + * + * Note: the i386 does not currently require barriers, but we must + * provide the flags to MI code. + */ +#define bus_space_barrier(t, h, o, l, f) do { \ + ((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f)));\ + __asm volatile("" : : : "memory"); \ +} while (0) +#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ +#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ + +#define BUS_SPACE_MAP_CACHEABLE 0x0001 +#define BUS_SPACE_MAP_LINEAR 0x0002 +#define BUS_SPACE_MAP_PREFETCHABLE 0x0008 + +/* + * Values for the i386 bus space tag, not to be used directly by MI code. + */ + +/* space is i/o space */ +extern const struct i386_bus_space_ops i386_bus_space_io_ops; +#define I386_BUS_SPACE_IO (&i386_bus_space_io_ops) + +/* space is mem space */ +extern const struct i386_bus_space_ops i386_bus_space_mem_ops; +#define I386_BUS_SPACE_MEM (&i386_bus_space_mem_ops) + +/* + * Flags used in various bus DMA methods. + */ +#define BUS_DMA_WAITOK 0x0000 /* safe to sleep (pseudo-flag) */ +#define BUS_DMA_NOWAIT 0x0001 /* not safe to sleep */ +#define BUS_DMA_ALLOCNOW 0x0002 /* perform resource allocation now */ +#define BUS_DMA_COHERENT 0x0004 /* hint: map memory DMA coherent */ +#define BUS_DMA_BUS1 0x0010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x0020 +#define BUS_DMA_BUS3 0x0040 +#define BUS_DMA_24BIT 0x0080 /* isadma map */ +#define BUS_DMA_STREAMING 0x0100 /* hint: sequential, unidirectional */ +#define BUS_DMA_READ 0x0200 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x0400 /* mapping is memory -> device only */ +#define BUS_DMA_NOCACHE 0x0800 /* map memory uncached */ +#define BUS_DMA_ZERO 0x1000 /* dmamem_alloc return zeroed mem */ +#define BUS_DMA_64BIT 0x2000 /* device handles 64bit dva */ + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct proc; +struct uio; + +/* + * Operations performed by bus_dmamap_sync(). + */ +#define BUS_DMASYNC_PREREAD 0x01 +#define BUS_DMASYNC_POSTREAD 0x02 +#define BUS_DMASYNC_PREWRITE 0x04 +#define BUS_DMASYNC_POSTWRITE 0x08 + +typedef struct bus_dma_tag *bus_dma_tag_t; +typedef struct bus_dmamap *bus_dmamap_t; + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +struct bus_dma_segment { + bus_addr_t ds_addr; /* DMA address */ + bus_size_t ds_len; /* length of transfer */ + /* + * Ugh. need this so can pass alignment down from bus_dmamem_alloc + * to scatter gather maps. only the first one is used so the rest is + * wasted space. bus_dma could do with fixing the api for this. + */ + bus_size_t _ds_boundary; /* don't cross */ + bus_size_t _ds_align; /* align to me */ +}; +typedef struct bus_dma_segment bus_dma_segment_t; + +/* + * bus_dma_tag_t + * + * A machine-dependent opaque type describing the implementation of + * DMA for a given bus. + */ + +struct bus_dma_tag { + void *_cookie; /* cookie used in the guts */ + + /* + * DMA mapping methods. + */ + int (*_dmamap_create)(bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); + void (*_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t); + int (*_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); + int (*_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t, + struct mbuf *, int); + int (*_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t, + struct uio *, int); + int (*_dmamap_load_raw)(bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); + void (*_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t); + void (*_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t, + bus_addr_t, bus_size_t, int); + + /* + * DMA memory utility functions. + */ + int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); + int (*_dmamem_alloc_range)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int, + bus_addr_t, bus_addr_t); + void (*_dmamem_free)(bus_dma_tag_t, + bus_dma_segment_t *, int); + int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); + void (*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t); + paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, + int, off_t, int, int); +}; + +#define bus_dmamap_create(t, s, n, m, b, f, p) \ + (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) +#define bus_dmamap_destroy(t, p) \ + (*(t)->_dmamap_destroy)((t), (p)) +#define bus_dmamap_load(t, m, b, s, p, f) \ + (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) +#define bus_dmamap_load_mbuf(t, m, b, f) \ + (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) +#define bus_dmamap_load_uio(t, m, u, f) \ + (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) +#define bus_dmamap_load_raw(t, m, sg, n, s, f) \ + (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) +#define bus_dmamap_unload(t, p) \ + (*(t)->_dmamap_unload)((t), (p)) +#define bus_dmamap_sync(t, p, o, l, ops) \ + (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops)) + +#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ + (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f)) +#define bus_dmamem_alloc_range(t, s, a, b, sg, n, r, f, l, h) \ + (*(t)->_dmamem_alloc_range)((t), (s), (a), (b), (sg), \ + (n), (r), (f), (l), (h)) +#define bus_dmamem_free(t, sg, n) \ + (*(t)->_dmamem_free)((t), (sg), (n)) +#define bus_dmamem_map(t, sg, n, s, k, f) \ + (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f)) +#define bus_dmamem_unmap(t, k, s) \ + (*(t)->_dmamem_unmap)((t), (k), (s)) +#define bus_dmamem_mmap(t, sg, n, o, p, f) \ + (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f)) + +/* + * bus_dmamap_t + * + * Describes a DMA mapping. + */ +struct bus_dmamap { + /* + * PRIVATE MEMBERS: not for use by machine-independent code. + */ + bus_size_t _dm_size; /* largest DMA transfer mappable */ + int _dm_segcnt; /* number of segs this map can map */ + bus_size_t _dm_maxsegsz; /* largest possible segment */ + bus_size_t _dm_boundary; /* don't cross this */ + int _dm_flags; /* misc. flags */ + + void *_dm_cookie; /* cookie for bus-specific functions */ + + /* + * PUBLIC MEMBERS: these are used by machine-independent code. + */ + bus_size_t dm_mapsize; /* size of the mapping */ + int dm_nsegs; /* # valid segments in mapping */ + bus_dma_segment_t dm_segs[1]; /* segments; variable length */ +}; + +int _bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t, + bus_size_t, int, bus_dmamap_t *); +void _bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); +int _bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); +int _bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, + struct mbuf *, int); +int _bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, + struct uio *, int); +int _bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); +void _bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t); +void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, + bus_size_t, int); + +int _bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size, + bus_size_t alignment, bus_size_t boundary, + bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags); +void _bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs); +int _bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs, size_t size, caddr_t *kvap, int flags); +void _bus_dmamem_unmap(bus_dma_tag_t tag, caddr_t kva, + size_t size); +paddr_t _bus_dmamem_mmap(bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs, off_t off, int prot, int flags); + +int _bus_dmamem_alloc_range(bus_dma_tag_t tag, bus_size_t size, + bus_size_t alignment, bus_size_t boundary, + bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags, + paddr_t low, paddr_t high); + +#endif /* _MACHINE_BUS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/cdefs.h b/lib/libc/include/x86-openbsd-none/i386/cdefs.h new file mode 100644 index 000000000000..af2607c12a2c --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/cdefs.h @@ -0,0 +1,21 @@ +/* $OpenBSD: cdefs.h,v 1.10 2013/03/28 17:30:45 martynas Exp $ */ + +/* + * Written by J.T. Conklin 01/17/95. + * Public domain. + */ + +#ifndef _MACHINE_CDEFS_H_ +#define _MACHINE_CDEFS_H_ + +#define __strong_alias(alias,sym) \ + __asm__(".global " __STRING(alias) " ; " \ + __STRING(alias) " = " __STRING(sym)) +#define __weak_alias(alias,sym) \ + __asm__(".weak " __STRING(alias) " ; " \ + __STRING(alias) " = " __STRING(sym)) +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning." __STRING(sym) \ + " ; .ascii \"" msg "\" ; .text") + +#endif /* !_MACHINE_CDEFS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/codepatch.h b/lib/libc/include/x86-openbsd-none/i386/codepatch.h new file mode 100644 index 000000000000..fa33bf8bf8fc --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/codepatch.h @@ -0,0 +1,52 @@ +/* $OpenBSD: codepatch.h,v 1.3 2023/07/31 17:10:31 bluhm Exp $ */ +/* + * Copyright (c) 2014-2015 Stefan Fritsch + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_CODEPATCH_H_ +#define _MACHINE_CODEPATCH_H_ + +#include + +#ifndef _LOCORE + +void *codepatch_maprw(vaddr_t *nva, vaddr_t dest); +void codepatch_unmaprw(vaddr_t nva); +void codepatch_fill_nop(void *caddr, uint16_t len); +void codepatch_nop(uint16_t tag); +void codepatch_replace(uint16_t tag, const void *code, size_t len); +void codepatch_call(uint16_t tag, void *func); + +#endif /* !_LOCORE */ + +/* + * Mark the start of some code snippet to be patched. + */ +#define CODEPATCH_START 998: +/* + * Mark the end of some code to be patched, and assign the given tag. + */ +#define CODEPATCH_END(tag) \ + 999: \ + .section .codepatch, "a" ;\ + .int 998b ;\ + .short (999b - 998b) ;\ + .short tag ;\ + .previous + +#define CPTAG_STAC 1 +#define CPTAG_CLAC 2 + +#endif /* _MACHINE_CODEPATCH_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/conf.h b/lib/libc/include/x86-openbsd-none/i386/conf.h new file mode 100644 index 000000000000..eaceeec5cd5a --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/conf.h @@ -0,0 +1,60 @@ +/* $OpenBSD: conf.h,v 1.21 2024/06/11 03:28:42 jsg Exp $ */ +/* $NetBSD: conf.h,v 1.2 1996/05/05 19:28:34 christos Exp $ */ + +/* + * Copyright (c) 1996 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#define mmread mmrw +#define mmwrite mmrw +cdev_decl(mm); + +bdev_decl(fd); +cdev_decl(fd); + +#define cdev_acpiapm_init(c,n) {\ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev, 0, 0, dev_init(c,n,kqfilter) } + +cdev_decl(spkr); + +cdev_decl(joy); + +cdev_decl(bios); + +cdev_decl(acpi); + +cdev_decl(apm); + +cdev_decl(acpiapm); + +cdev_decl(pctr); \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/cpu.h b/lib/libc/include/x86-openbsd-none/i386/cpu.h new file mode 100644 index 000000000000..eda232d75f28 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/cpu.h @@ -0,0 +1,533 @@ +/* $OpenBSD: cpu.h,v 1.192 2024/06/18 12:37:29 jsg Exp $ */ +/* $NetBSD: cpu.h,v 1.35 1996/05/05 19:29:26 christos Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)cpu.h 5.4 (Berkeley) 5/9/91 + */ + +#ifndef _MACHINE_CPU_H_ +#define _MACHINE_CPU_H_ + +/* + * Definitions unique to i386 cpu support. + */ +#ifdef _KERNEL +#include +#include +#include +#include +#include + +#ifdef MULTIPROCESSOR +#include +#include +#endif + +#endif /* _KERNEL */ + +/* + * Arguments to hardclock, softclock and statclock + * encapsulate the previous machine state in an opaque + * clockframe; for now, use generic intrframe. + * + * XXX intrframe has a lot of gunk we don't need. + */ +#define clockframe intrframe + +#include +#include +#include +#include +#include +#include + +struct intrsource; + +#ifdef _KERNEL +/* XXX stuff to move to cpuvar.h later */ +struct cpu_info { + u_int32_t ci_kern_cr3; /* U+K page table */ + u_int32_t ci_scratch; /* for U<-->K transition */ + +#define ci_PAGEALIGN ci_dev + struct device *ci_dev; /* our device */ + struct cpu_info *ci_self; /* pointer to this structure */ + struct schedstate_percpu ci_schedstate; /* scheduler state */ + struct cpu_info *ci_next; /* next cpu */ + + /* + * Public members. + */ + struct proc *ci_curproc; /* current owner of the processor */ + cpuid_t ci_cpuid; /* our CPU ID */ + u_int ci_apicid; /* our APIC ID */ + u_int ci_acpi_proc_id; + u_int32_t ci_randseed; + + u_int32_t ci_kern_esp; /* kernel-only stack */ + u_int32_t ci_intr_esp; /* U<-->K trampoline stack */ + u_int32_t ci_user_cr3; /* U-K page table */ + +#if defined(MULTIPROCESSOR) + struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM]; +#define __HAVE_UVM_PERCPU + struct uvm_pmr_cache ci_uvm; +#endif + + /* + * Private members. + */ + struct proc *ci_fpcurproc; /* current owner of the FPU */ + struct proc *ci_fpsaveproc; + int ci_fpsaving; /* save in progress */ + + struct pcb *ci_curpcb; /* VA of current HW PCB */ + struct pcb *ci_idle_pcb; /* VA of current PCB */ + struct pmap *ci_curpmap; + + struct intrsource *ci_isources[MAX_INTR_SOURCES]; + u_int32_t ci_ipending; + int ci_ilevel; + int ci_idepth; + u_int32_t ci_imask[NIPL]; + u_int32_t ci_iunmask[NIPL]; +#ifdef DIAGNOSTIC + int ci_mutex_level; +#endif + + paddr_t ci_idle_pcb_paddr; /* PA of idle PCB */ + volatile u_long ci_flags; /* flags; see below */ + u_int32_t ci_ipis; /* interprocessor interrupts pending */ + + u_int32_t ci_level; + u_int32_t ci_vendor[4]; + u_int32_t ci_signature; /* X86 cpuid type */ + u_int32_t ci_family; /* extended cpuid family */ + u_int32_t ci_model; /* extended cpuid model */ + u_int32_t ci_feature_flags; /* X86 CPUID feature bits */ + u_int32_t ci_feature_sefflags_ebx;/* more CPUID feature bits */ + u_int32_t ci_feature_sefflags_ecx;/* more CPUID feature bits */ + u_int32_t ci_feature_sefflags_edx;/* more CPUID feature bits */ + u_int32_t ci_feature_tpmflags; /* thermal & power bits */ + u_int32_t cpu_class; /* CPU class */ + u_int32_t ci_cflushsz; /* clflush cache-line size */ + + int ci_inatomic; + + struct cpu_functions *ci_func; /* start/stop functions */ + void (*cpu_setup)(struct cpu_info *); /* proc-dependant init */ + + struct device *ci_acpicpudev; + volatile u_int ci_mwait; +#define MWAIT_IN_IDLE 0x1 /* don't need IPI to wake */ +#define MWAIT_KEEP_IDLING 0x2 /* cleared by other cpus to wake me */ +#define MWAIT_ONLY 0x4 /* set if all idle states use mwait */ +#define MWAIT_IDLING (MWAIT_IN_IDLE | MWAIT_KEEP_IDLING) + + int ci_want_resched; + + union descriptor *ci_gdt; + struct i386tss *ci_tss; + struct i386tss *ci_nmi_tss; + + volatile int ci_ddb_paused; /* paused due to other proc in ddb */ +#define CI_DDB_RUNNING 0 +#define CI_DDB_SHOULDSTOP 1 +#define CI_DDB_STOPPED 2 +#define CI_DDB_ENTERDDB 3 +#define CI_DDB_INDDB 4 + + struct ksensordev ci_sensordev; + struct ksensor ci_sensor; +#if defined(GPROF) || defined(DDBPROF) + struct gmonparam *ci_gmon; + struct clockintr ci_gmonclock; +#endif + struct clockqueue ci_queue; + char ci_panicbuf[512]; +}; + +/* + * Processor flag notes: The "primary" CPU has certain MI-defined + * roles (mostly relating to hardclock handling); we distinguish + * between the processor which booted us, and the processor currently + * holding the "primary" role just to give us the flexibility later to + * change primaries should we be sufficiently twisted. + */ + +#define CPUF_BSP 0x0001 /* CPU is the original BSP */ +#define CPUF_AP 0x0002 /* CPU is an AP */ +#define CPUF_SP 0x0004 /* CPU is only processor */ +#define CPUF_PRIMARY 0x0008 /* CPU is active primary processor */ +#define CPUF_APIC_CD 0x0010 /* CPU has apic configured */ +#define CPUF_CONST_TSC 0x0020 /* CPU has constant TSC */ + +#define CPUF_PRESENT 0x1000 /* CPU is present */ +#define CPUF_RUNNING 0x2000 /* CPU is running */ +#define CPUF_VMM 0x4000 /* CPU is executing in VMM mode */ + +/* + * We statically allocate the CPU info for the primary CPU (or, + * the only CPU on uniprocessors), and the primary CPU is the + * first CPU on the CPU info list. + */ +struct cpu_info_full; +extern struct cpu_info_full cpu_info_full_primary; +#define cpu_info_primary (*(struct cpu_info *)((char *)&cpu_info_full_primary + PAGE_SIZE*2 - offsetof(struct cpu_info, ci_PAGEALIGN))) + +extern struct cpu_info *cpu_info_list; + +#define CPU_INFO_ITERATOR int +#define CPU_INFO_FOREACH(cii, ci) for (cii = 0, ci = cpu_info_list; \ + ci != NULL; ci = ci->ci_next) + +#define CPU_INFO_UNIT(ci) ((ci)->ci_dev ? (ci)->ci_dev->dv_unit : 0) + +#ifdef MULTIPROCESSOR + +#define MAXCPUS 32 /* because we use a bitmask */ + +#define CPU_STARTUP(_ci) ((_ci)->ci_func->start(_ci)) +#define CPU_STOP(_ci) ((_ci)->ci_func->stop(_ci)) +#define CPU_START_CLEANUP(_ci) ((_ci)->ci_func->cleanup(_ci)) + +static struct cpu_info *curcpu(void); + +static __inline struct cpu_info * +curcpu(void) +{ + struct cpu_info *ci; + + /* Can't include sys/param.h for offsetof() since it includes us */ + __asm volatile("movl %%fs:%1, %0" : + "=r" (ci) : "m" + (*(struct cpu_info * const *)&((struct cpu_info *)0)->ci_self)); + return ci; +} +#define cpu_number() (curcpu()->ci_cpuid) + +#define CPU_IS_PRIMARY(ci) ((ci)->ci_flags & CPUF_PRIMARY) +#define CPU_IS_RUNNING(ci) ((ci)->ci_flags & CPUF_RUNNING) + +extern struct cpu_info *cpu_info[MAXCPUS]; + +extern void cpu_boot_secondary_processors(void); +extern void cpu_init_idle_pcbs(void); + +void cpu_kick(struct cpu_info *); +void cpu_unidle(struct cpu_info *); + +#define CPU_BUSY_CYCLE() __asm volatile("pause": : : "memory") + +#else /* MULTIPROCESSOR */ + +#define MAXCPUS 1 + +#define cpu_number() 0 +#define curcpu() (&cpu_info_primary) + +#define CPU_IS_PRIMARY(ci) 1 +#define CPU_IS_RUNNING(ci) 1 + +#define cpu_kick(ci) +#define cpu_unidle(ci) + +#define CPU_BUSY_CYCLE() __asm volatile ("" ::: "memory") + +#endif + +#include + +#define aston(p) ((p)->p_md.md_astpending = 1) + +#define curpcb curcpu()->ci_curpcb + +unsigned int cpu_rnd_messybits(void); + +/* + * Preempt the current process if in interrupt from user mode, + * or after the current trap/syscall if in system mode. + */ +extern void need_resched(struct cpu_info *); +#define clear_resched(ci) (ci)->ci_want_resched = 0 + +#define CLKF_USERMODE(frame) USERMODE((frame)->if_cs, (frame)->if_eflags) +#define CLKF_PC(frame) ((frame)->if_eip) +#define CLKF_INTR(frame) (IDXSEL((frame)->if_cs) == GICODE_SEL) + +/* + * This is used during profiling to integrate system time. + */ +#define PROC_PC(p) ((p)->p_md.md_regs->tf_eip) +#define PROC_STACK(p) ((p)->p_md.md_regs->tf_esp) + +/* + * Give a profiling tick to the current process when the user profiling + * buffer pages are invalid. On the i386, request an ast to send us + * through trap(), marking the proc as needing a profiling tick. + */ +#define need_proftick(p) aston(p) + +/* + * Notify the current process (p) that it has a signal pending, + * process as soon as possible. + */ +void signotify(struct proc *); + +/* + * We need a machine-independent name for this. + */ +extern void (*delay_func)(int); +void delay_fini(void(*)(int)); +void delay_init(void(*)(int), int); +struct timeval; + +#define DELAY(x) (*delay_func)(x) +#define delay(x) (*delay_func)(x) + +/* + * High resolution clock support (Pentium only) + */ +void calibrate_cyclecounter(void); + +/* + * pull in #defines for kinds of processors + */ +#include + +struct cpu_cpuid_nameclass { + const char *cpu_id; + int cpu_vendor; + const char *cpu_vendorname; + struct cpu_cpuid_family { + int cpu_class; + const char *cpu_models[CPU_MAXMODEL+2]; + void (*cpu_setup)(struct cpu_info *); + } cpu_family[CPU_MAXFAMILY - CPU_MINFAMILY + 1]; +}; + +struct cpu_cpuid_feature { + int feature_bit; + const char *feature_name; +}; + +/* locore.s */ +extern int cpu_id; +extern char cpu_vendor[]; /* note: NOT nul-terminated */ +extern char cpu_brandstr[]; +extern int cpuid_level; +extern int cpu_miscinfo; +extern int cpu_feature; +extern int ecpu_feature; +extern int cpu_ecxfeature; +extern int ecpu_ecxfeature; +extern int cpu_cache_eax; +extern int cpu_cache_ebx; +extern int cpu_cache_ecx; +extern int cpu_cache_edx; +extern int cpu_perf_eax; +extern int cpu_perf_ebx; +extern int cpu_perf_edx; +extern int cpu_apmi_edx; +extern int cpu_pae; /* cpu has both PAE and NX features */ + +/* cpu.c */ +extern u_int cpu_mwait_size; +extern u_int cpu_mwait_states; +extern void cpu_update_nmi_cr3(vaddr_t); +extern void cpu_tsx_disable(struct cpu_info *); + +/* machdep.c */ +extern int cpu_apmhalt; +extern int cpu_class; +extern char cpu_model[]; +extern const struct cpu_cpuid_nameclass i386_cpuid_cpus[]; +extern void (*cpu_idle_enter_fcn)(void); +extern void (*cpu_idle_cycle_fcn)(void); +extern void (*cpu_idle_leave_fcn)(void); +extern void (*cpu_suspend_cycle_fcn)(void); + +extern int cpuspeed; + +#if !defined(SMALL_KERNEL) +#define BUS66 6667 +#define BUS100 10000 +#define BUS133 13333 +#define BUS166 16667 +#define BUS200 20000 +#define BUS266 26667 +#define BUS333 33333 +extern int bus_clock; +#endif + +/* F00F bug fix stuff for pentium cpu */ +extern int cpu_f00f_bug; +void fix_f00f(void); + +/* dkcsum.c */ +void dkcsumattach(void); + +extern int i386_use_fxsave; +extern int i386_has_sse; +extern int i386_has_sse2; + +extern void (*update_cpuspeed)(void); + +extern void (*initclock_func)(void); +extern void (*startclock_func)(void); + +/* machdep.c */ +void dumpconf(void); +void cpu_reset(void); +void i386_proc0_tss_init(void); +void i386_init_pcb_tss(struct cpu_info *); +void cpuid(u_int32_t, u_int32_t *); + +/* locore.s */ +struct region_descriptor; +void lgdt(struct region_descriptor *); + +struct pcb; +void savectx(struct pcb *); +void proc_trampoline(void); + +/* clock.c */ +void startclocks(void); +void rtcinit(void); +void rtcstart(void); +void rtcstop(void); +void i8254_delay(int); +void i8254_initclocks(void); +void i8254_startclock(void); +void i8254_start_both_clocks(void); +void i8254_inittimecounter(void); +void i8254_inittimecounter_simple(void); + +#if !defined(SMALL_KERNEL) +/* est.c */ +void est_init(struct cpu_info *, int); +void est_setperf(int); +/* longrun.c */ +void longrun_init(void); +void longrun_setperf(int); +/* p4tcc.c */ +void p4tcc_init(int, int); +void p4tcc_setperf(int); +/* powernow.c */ +void k6_powernow_init(void); +void k6_powernow_setperf(int); +/* powernow-k7.c */ +void k7_powernow_init(void); +void k7_powernow_setperf(int); +/* powernow-k8.c */ +void k8_powernow_init(void); +void k8_powernow_setperf(int); +/* k1x-pstate.c */ +void k1x_init(struct cpu_info *); +void k1x_setperf(int); +#endif + +/* npx.c */ +void npxsave_proc(struct proc *, int); +void npxsave_cpu(struct cpu_info *, int); + +/* isa_machdep.c */ +void isa_defaultirq(void); +int isa_nmi(void); + +/* pmap.c */ +void pmap_bootstrap(vaddr_t); + +/* vm_machdep.c */ +int kvtop(caddr_t); + +#ifdef MULTIPROCESSOR +/* mp_setperf.c */ +void mp_setperf_init(void); +#endif + +int cpu_paenable(void *); +#endif /* _KERNEL */ + +/* + * CTL_MACHDEP definitions. + */ +#define CPU_CONSDEV 1 /* dev_t: console terminal device */ +#define CPU_BIOS 2 /* BIOS variables */ +#define CPU_BLK2CHR 3 /* convert blk maj into chr one */ +#define CPU_CHR2BLK 4 /* convert chr maj into blk one */ +#define CPU_ALLOWAPERTURE 5 /* allow mmap of /dev/xf86 */ +#define CPU_CPUVENDOR 6 /* cpuid vendor string */ +#define CPU_CPUID 7 /* cpuid */ +#define CPU_CPUFEATURE 8 /* cpuid features */ +#define CPU_KBDRESET 10 /* keyboard reset under pcvt */ +#define CPU_OSFXSR 13 /* uses FXSAVE/FXRSTOR */ +#define CPU_SSE 14 /* supports SSE */ +#define CPU_SSE2 15 /* supports SSE2 */ +#define CPU_XCRYPT 16 /* supports VIA xcrypt in userland */ +#define CPU_LIDACTION 18 /* action caused by lid close */ +#define CPU_FORCEUKBD 19 /* Force ukbd(4) as console keyboard */ +#define CPU_MAXID 20 /* number of valid machdep ids */ + +#define CTL_MACHDEP_NAMES { \ + { 0, 0 }, \ + { "console_device", CTLTYPE_STRUCT }, \ + { "bios", CTLTYPE_INT }, \ + { "blk2chr", CTLTYPE_STRUCT }, \ + { "chr2blk", CTLTYPE_STRUCT }, \ + { "allowaperture", CTLTYPE_INT }, \ + { "cpuvendor", CTLTYPE_STRING }, \ + { "cpuid", CTLTYPE_INT }, \ + { "cpufeature", CTLTYPE_INT }, \ + { 0, 0 }, \ + { "kbdreset", CTLTYPE_INT }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "osfxsr", CTLTYPE_INT }, \ + { "sse", CTLTYPE_INT }, \ + { "sse2", CTLTYPE_INT }, \ + { "xcrypt", CTLTYPE_INT }, \ + { 0, 0 }, \ + { "lidaction", CTLTYPE_INT }, \ + { "forceukbd", CTLTYPE_INT }, \ +} + +/* + * This needs to be included late since it relies on definitions higher + * up in this file. + */ +#if defined(MULTIPROCESSOR) && defined(_KERNEL) +#include +#endif + +#endif /* !_MACHINE_CPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/cpu_full.h b/lib/libc/include/x86-openbsd-none/i386/cpu_full.h new file mode 100644 index 000000000000..fd87a09aada8 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/cpu_full.h @@ -0,0 +1,67 @@ +/* $OpenBSD: cpu_full.h,v 1.3 2018/06/22 13:21:14 bluhm Exp $ */ +/* + * Copyright (c) 2018 Philip Guenther + * Copyright (c) 2018 Hans-Joerg Hoexer + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_CPU_FULL_H_ +#define _MACHINE_CPU_FULL_H_ + +#include /* offsetof, PAGE_SIZE */ +#include +#include + +struct cpu_info_full { + /* page mapped kRO in u-k */ + union { + struct { + struct i386tss uu_tss; + struct i386tss uu_nmi_tss; + union descriptor uu_gdt[NGDT]; + } u_tssgdt; + char u_align[PAGE_SIZE]; + } cif_TSS_RO; +#define cif_tss cif_TSS_RO.u_tssgdt.uu_tss +#define cif_nmi_tss cif_TSS_RO.u_tssgdt.uu_nmi_tss +#define cif_gdt cif_TSS_RO.u_tssgdt.uu_gdt + + /* start of page mapped kRW in u-k */ + uint32_t cif_tramp_stack[(PAGE_SIZE / 4 + - offsetof(struct cpu_info, ci_PAGEALIGN)) / sizeof(uint32_t)]; + uint32_t cif_nmi_stack[(3 * PAGE_SIZE / 4) / sizeof(uint32_t)]; + + /* + * Beginning of this hangs over into the kRW page; rest is + * unmapped in u-k + */ + struct cpu_info cif_cpu; +} __aligned(PAGE_SIZE); + +/* tss, align shim, and gdt must fit in a page */ +CTASSERT(_ALIGN(2 * sizeof(struct i386tss)) + + sizeof(struct segment_descriptor) * NGDT < PAGE_SIZE); + +/* verify expected alignment */ +CTASSERT(offsetof(struct cpu_info_full, cif_cpu.ci_PAGEALIGN) % PAGE_SIZE == 0); + +/* verify total size is multiple of page size */ +CTASSERT(sizeof(struct cpu_info_full) % PAGE_SIZE == 0); + +extern struct cpu_info_full cpu_info_full_primary; + +/* Now make sure the cpu_info_primary macro is correct */ +CTASSERT(&cpu_info_primary - &cpu_info_full_primary.cif_cpu == 0); + +#endif /* _MACHINE_CPU_FULL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/cpufunc.h b/lib/libc/include/x86-openbsd-none/i386/cpufunc.h new file mode 100644 index 000000000000..a13a9ba4a92a --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/cpufunc.h @@ -0,0 +1,310 @@ +/* $OpenBSD: cpufunc.h,v 1.34 2025/06/20 14:06:34 sf Exp $ */ +/* $NetBSD: cpufunc.h,v 1.8 1994/10/27 04:15:59 cgd Exp $ */ + +/* + * Copyright (c) 1993 Charles Hannum. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Charles Hannum. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_CPUFUNC_H_ +#define _MACHINE_CPUFUNC_H_ + +#ifdef _KERNEL + +/* + * Functions to provide access to i386-specific instructions. + */ + +#include + +#include + +static __inline void invlpg(u_int); +static __inline void lidt(void *); +static __inline void lldt(u_short); +static __inline void ltr(u_short); +static __inline void lcr0(u_int); +static __inline u_int rcr0(void); +static __inline u_int rcr2(void); +static __inline void lcr3(u_int); +static __inline u_int rcr3(void); +static __inline void lcr4(u_int); +static __inline u_int rcr4(void); +static __inline void tlbflush(void); +static __inline u_int read_eflags(void); +static __inline void write_eflags(u_int); +static __inline void wbinvd(void); +static __inline void clflush(u_int32_t addr); +static __inline void mfence(void); +static __inline void wrmsr(u_int, u_int64_t); +static __inline u_int64_t rdmsr(u_int); +static __inline void breakpoint(void); + +static __inline void +invlpg(u_int addr) +{ + __asm volatile("invlpg (%0)" : : "r" (addr) : "memory"); +} + +static __inline void +lidt(void *p) +{ + __asm volatile("lidt (%0)" : : "r" (p) : "memory"); +} + +static __inline void +lldt(u_short sel) +{ + __asm volatile("lldt %0" : : "r" (sel)); +} + +static __inline void +ltr(u_short sel) +{ + __asm volatile("ltr %0" : : "r" (sel)); +} + +static __inline void +lcr0(u_int val) +{ + __asm volatile("movl %0,%%cr0" : : "r" (val)); +} + +static __inline u_int +rcr0(void) +{ + u_int val; + __asm volatile("movl %%cr0,%0" : "=r" (val)); + return val; +} + +static __inline u_int +rcr2(void) +{ + u_int val; + __asm volatile("movl %%cr2,%0" : "=r" (val)); + return val; +} + +static __inline void +lcr3(u_int val) +{ + __asm volatile("movl %0,%%cr3" : : "r" (val)); +} + +static __inline u_int +rcr3(void) +{ + u_int val; + __asm volatile("movl %%cr3,%0" : "=r" (val)); + return val; +} + +static __inline void +lcr4(u_int val) +{ + __asm volatile("movl %0,%%cr4" : : "r" (val)); +} + +static __inline u_int +rcr4(void) +{ + u_int val; + __asm volatile("movl %%cr4,%0" : "=r" (val)); + return val; +} + +static __inline void +tlbflush(void) +{ + u_int val; + __asm volatile("movl %%cr3,%0" : "=r" (val)); + __asm volatile("movl %0,%%cr3" : : "r" (val)); +} + +#ifdef notyet +void setidt(int idx, /*XXX*/caddr_t func, int typ, int dpl); +#endif + + +/* XXXX ought to be in psl.h with spl() functions */ + +static __inline u_int +read_eflags(void) +{ + u_int ef; + + __asm volatile("pushfl; popl %0" : "=r" (ef)); + return (ef); +} + +static __inline void +write_eflags(u_int ef) +{ + __asm volatile("pushl %0; popfl" : : "r" (ef)); +} + +static inline void +intr_enable(void) +{ + __asm volatile("sti"); +} + +static inline u_long +intr_disable(void) +{ + u_long ef; + + ef = read_eflags(); + __asm volatile("cli"); + return (ef); +} + +static inline void +intr_restore(u_long ef) +{ + write_eflags(ef); +} + +static __inline void +wbinvd(void) +{ + __asm volatile("wbinvd" : : : "memory"); +} + +#ifdef MULTIPROCESSOR +int wbinvd_on_all_cpus(void); +#else +static inline int +wbinvd_on_all_cpus(void) +{ + wbinvd(); + return 0; +} +#endif + +static __inline void +clflush(u_int32_t addr) +{ + __asm volatile("clflush %0" : "+m" (*(volatile char *)addr)); +} + +static __inline void +mfence(void) +{ + __asm volatile("mfence" : : : "memory"); +} + +static __inline u_int64_t +rdtsc(void) +{ + uint64_t tsc; + + __asm volatile("rdtsc" : "=A" (tsc)); + return (tsc); +} + +static inline uint64_t +rdtsc_lfence(void) +{ + uint64_t tsc; + + __asm volatile("lfence; rdtsc" : "=A" (tsc)); + return tsc; +} + +static __inline void +wrmsr(u_int msr, u_int64_t newval) +{ + __asm volatile("wrmsr" : : "A" (newval), "c" (msr)); +} + +static __inline u_int64_t +rdmsr(u_int msr) +{ + u_int64_t rv; + + __asm volatile("rdmsr" : "=A" (rv) : "c" (msr)); + return (rv); +} + +static __inline void +monitor(const volatile void *addr, u_long extensions, u_int hints) +{ + __asm volatile("monitor" + : : "a" (addr), "c" (extensions), "d" (hints)); +} + +static __inline void +mwait(u_long extensions, u_int hints) +{ + __asm volatile("mwait" : : "a" (hints), "c" (extensions)); +} + +/* + * Some of the undocumented AMD64 MSRs need a 'passcode' to access. + * + * See LinuxBIOSv2: src/cpu/amd/model_fxx/model_fxx_init.c + */ + +#define OPTERON_MSR_PASSCODE 0x9c5a203a + +static __inline u_int64_t +rdmsr_locked(u_int msr, u_int code) +{ + uint64_t rv; + __asm volatile("rdmsr" + : "=A" (rv) + : "c" (msr), "D" (code)); + return (rv); +} + +static __inline void +wrmsr_locked(u_int msr, u_int code, u_int64_t newval) +{ + __asm volatile("wrmsr" + : + : "A" (newval), "c" (msr), "D" (code)); +} + +/* Break into DDB. */ +static __inline void +breakpoint(void) +{ + __asm volatile("int $3"); +} + +void amd64_errata(struct cpu_info *); +void cpu_ucode_setup(void); +void cpu_ucode_apply(struct cpu_info *); + +struct cpu_info_full; +void cpu_enter_pages(struct cpu_info_full *); + +#endif /* _KERNEL */ +#endif /* !_MACHINE_CPUFUNC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/cputypes.h b/lib/libc/include/x86-openbsd-none/i386/cputypes.h new file mode 100644 index 000000000000..0cd4be7abc39 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/cputypes.h @@ -0,0 +1,60 @@ +/* $OpenBSD: cputypes.h,v 1.15 2022/08/22 08:53:55 jsg Exp $ */ +/* $NetBSD: cputypes.h,v 1.10 1997/10/18 04:51:03 mikel Exp $ */ + +/* + * Copyright (c) 1993 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Classes of Processor + */ + +#define CPUCLASS_486 1 +#define CPUCLASS_586 2 +#define CPUCLASS_686 3 + +/* + * CPU vendors + */ + +#define CPUVENDOR_UNKNOWN -1 +#define CPUVENDOR_INTEL 0 +#define CPUVENDOR_CYRIX 1 +#define CPUVENDOR_AMD 3 +#define CPUVENDOR_IDT 4 +#define CPUVENDOR_TRANSMETA 6 +#define CPUVENDOR_NS 7 +#define CPUVENDOR_VIA 8 +#define CPUVENDOR_SIS 9 + +/* + * Some other defines, dealing with values returned by cpuid. + */ + +#define CPU_MAXMODEL 15 /* Models within family range 0-15 */ +#define CPU_DEFMODEL 16 /* Value for unknown model -> default */ +#define CPU_MINFAMILY 4 /* Lowest that cpuid can return (486) */ +#define CPU_MAXFAMILY 0xf /* Highest we know (686) */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/cpuvar.h b/lib/libc/include/x86-openbsd-none/i386/cpuvar.h new file mode 100644 index 000000000000..e420bbdc642d --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/cpuvar.h @@ -0,0 +1,98 @@ +/* $OpenBSD: cpuvar.h,v 1.8 2024/10/21 03:07:54 jsg Exp $ */ +/* $NetBSD: cpuvar.h,v 1.1.2.3 2000/02/21 18:54:07 sommerfeld Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1999 Stefan Grefen + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +struct cpu_functions { + int (*start)(struct cpu_info *); + int (*stop)(struct cpu_info *); + void (*cleanup)(struct cpu_info *); +}; + +extern struct cpu_functions mp_cpu_funcs; + +#define CPU_ROLE_SP 0 +#define CPU_ROLE_BP 1 +#define CPU_ROLE_AP 2 + +struct cpu_attach_args { + const char *caa_name; + int cpu_apicid; + int cpu_acpi_proc_id; + int cpu_role; + struct cpu_functions *cpu_func; + int cpu_signature; + int feature_flags; +}; + +#ifdef _KERNEL + +void i386_ipi(int,int,int); +void i386_ipi_init(int); + +void identifycpu(struct cpu_info *); +void cpu_init(struct cpu_info *); +void cpu_init_first(void); + +#endif \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/db_machdep.h b/lib/libc/include/x86-openbsd-none/i386/db_machdep.h new file mode 100644 index 000000000000..720fb23437af --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/db_machdep.h @@ -0,0 +1,94 @@ +/* $OpenBSD: db_machdep.h,v 1.30 2021/08/30 08:11:12 jasper Exp $ */ +/* $NetBSD: db_machdep.h,v 1.9 1996/05/03 19:23:59 christos Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#ifndef _MACHINE_DB_MACHDEP_H_ +#define _MACHINE_DB_MACHDEP_H_ + +/* + * Machine-dependent defines for new kernel debugger. + */ + +#include +#include +#include + +typedef long db_expr_t; /* expression - signed */ + +typedef struct trapframe db_regs_t; +extern db_regs_t ddb_regs; /* register state */ + +#define PC_REGS(regs) ((vaddr_t)(regs)->tf_eip) +#define SET_PC_REGS(regs, value) (regs)->tf_eip = (int)(value) + +#define BKPT_INST 0xcc /* breakpoint instruction */ +#define BKPT_SIZE (1) /* size of breakpoint inst */ +#define BKPT_SET(inst) (BKPT_INST) + +#define SSF_INST 0x55 +#define SSF_SIZE (1) + +#define FIXUP_PC_AFTER_BREAK(regs) ((regs)->tf_eip -= BKPT_SIZE) + +#define db_clear_single_step(regs) ((regs)->tf_eflags &= ~PSL_T) +#define db_set_single_step(regs) ((regs)->tf_eflags |= PSL_T) + +#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BPTFLT) +#define IS_WATCHPOINT_TRAP(type, code) ((type) == T_TRCTRAP && (code) & 15) + +#define I_CALL 0xe8 +#define I_CALLI 0xff +#define I_RET 0xc3 +#define I_IRET 0xcf + +#define inst_trap_return(ins) (((ins)&0xff) == I_IRET) +#define inst_return(ins) (((ins)&0xff) == I_RET) +#define inst_call(ins) (((ins)&0xff) == I_CALL || \ + (((ins)&0xff) == I_CALLI && \ + ((ins)&0x3800) == 0x1000)) + +#define DB_MACHINE_COMMANDS + +/* macro for checking if a thread has used floating-point */ + +int db_ktrap(int, int, db_regs_t *); + +void db_machine_init(void); +int db_enter_ddb(void); +void db_startcpu(int); +void db_stopcpu(int); +void i386_ipi_db(struct cpu_info *); + +extern struct db_mutex ddb_mp_mutex; + +/* For ddb_state */ +#define DDB_STATE_NOT_RUNNING 0 +#define DDB_STATE_RUNNING 1 +#define DDB_STATE_EXITING 2 + +#endif /* _MACHINE_DB_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/disklabel.h b/lib/libc/include/x86-openbsd-none/i386/disklabel.h new file mode 100644 index 000000000000..4d97c53ec23c --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/disklabel.h @@ -0,0 +1,40 @@ +/* $OpenBSD: disklabel.h,v 1.35 2015/09/30 14:57:03 krw Exp $ */ + +/* + * Copyright (c) 1994 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_DISKLABEL_H_ +#define _MACHINE_DISKLABEL_H_ + +#define LABELSECTOR 1 /* sector containing label */ +#define LABELOFFSET 0 /* offset of label in sector */ +#define MAXPARTITIONS 16 /* number of partitions */ + +#endif /* _MACHINE_DISKLABEL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/elf.h b/lib/libc/include/x86-openbsd-none/i386/elf.h new file mode 100644 index 000000000000..1cd8fda26a98 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/elf.h @@ -0,0 +1,7 @@ +/* $OpenBSD: elf.h,v 1.1 2024/07/14 09:48:48 jca Exp $ */ + +/* + * This file is in the public domain. + */ + +/* Nothing for now */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/endian.h b/lib/libc/include/x86-openbsd-none/i386/endian.h new file mode 100644 index 000000000000..146c79b32c4b --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/endian.h @@ -0,0 +1,36 @@ +/* $OpenBSD: endian.h,v 1.20 2024/05/07 14:26:48 naddy Exp $ */ + +/*- + * Copyright (c) 1997 Niklas Hallqvist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_ENDIAN_H_ +#define _MACHINE_ENDIAN_H_ + +#define _BYTE_ORDER _LITTLE_ENDIAN + +#ifndef __FROM_SYS__ENDIAN +#include +#endif + +#endif /* _MACHINE_ENDIAN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/exec.h b/lib/libc/include/x86-openbsd-none/i386/exec.h new file mode 100644 index 000000000000..aed3f3c61650 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/exec.h @@ -0,0 +1,43 @@ +/* $OpenBSD: exec.h,v 1.14 2017/02/08 05:09:25 guenther Exp $ */ +/* $NetBSD: exec.h,v 1.6 1994/10/27 04:16:05 cgd Exp $ */ + +/* + * Copyright (c) 1993 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_EXEC_H_ +#define _MACHINE_EXEC_H_ + +#define __LDPGSZ 4096 + +#define ARCH_ELFSIZE 32 + +#define ELF_TARG_CLASS ELFCLASS32 +#define ELF_TARG_DATA ELFDATA2LSB +#define ELF_TARG_MACH EM_386 /* XXX - EM_486 is currently unused + by all OSs/compilers/linkers */ + +#endif /* _MACHINE_EXEC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/fenv.h b/lib/libc/include/x86-openbsd-none/i386/fenv.h new file mode 100644 index 000000000000..febe5dc2968a --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/fenv.h @@ -0,0 +1,115 @@ +/* $OpenBSD: fenv.h,v 1.3 2011/05/25 21:46:49 martynas Exp $ */ +/* $NetBSD: fenv.h,v 1.1.6.2 2010/10/24 22:48:02 jym Exp $ */ + +/*- + * Copyright (c) 2004-2005 David Schultz + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _I386_FENV_H_ +#define _I386_FENV_H_ + +/* + * Each symbol representing a floating point exception expands to an integer + * constant expression with values, such that bitwise-inclusive ORs of _all + * combinations_ of the constants result in distinct values. + * + * We use such values that allow direct bitwise operations on FPU/SSE registers. + */ +#define FE_INVALID 0x01 +#define FE_DENORMAL 0x02 +#define FE_DIVBYZERO 0x04 +#define FE_OVERFLOW 0x08 +#define FE_UNDERFLOW 0x10 +#define FE_INEXACT 0x20 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * exception constants defined above. + */ +#define FE_ALL_EXCEPT (FE_INVALID | FE_DENORMAL | FE_DIVBYZERO | \ + FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) +#define _SSE_MASK_SHIFT 7 + +/* + * Each symbol representing the rounding direction, expands to an integer + * constant expression whose value is distinct non-negative value. + * + * We use such values that allow direct bitwise operations on FPU/SSE registers. + */ +#define FE_TONEAREST 0x000 +#define FE_DOWNWARD 0x400 +#define FE_UPWARD 0x800 +#define FE_TOWARDZERO 0xc00 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * rounding direction constants defined above. + */ +#define _X87_ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | \ + FE_TOWARDZERO) +#define _SSE_ROUND_SHIFT 3 + +/* + * fenv_t represents the entire floating-point environment. + */ +typedef struct { + struct { + unsigned int __control; /* Control word register */ + unsigned int __status; /* Status word register */ + unsigned int __tag; /* Tag word register */ + unsigned int __others[4]; /* EIP, Pointer Selector, etc */ + } __x87; + unsigned int __mxcsr; /* Control, status register */ +} fenv_t; + +/* + * The following constant represents the default floating-point environment + * (that is, the one installed at program startup) and has type pointer to + * const-qualified fenv_t. + * + * It can be used as an argument to the functions within the header + * that manage the floating-point environment, namely fesetenv() and + * feupdateenv(). + */ +__BEGIN_DECLS +extern fenv_t __fe_dfl_env; +__END_DECLS +#define FE_DFL_ENV ((const fenv_t *)&__fe_dfl_env) + +/* + * fexcept_t represents the floating-point status flags collectively, including + * any status the implementation associates with the flags. + * + * A floating-point status flag is a system variable whose value is set (but + * never cleared) when a floating-point exception is raised, which occurs as a + * side effect of exceptional floating-point arithmetic to provide auxiliary + * information. + * + * A floating-point control mode is a system variable whose value may be set by + * the user to affect the subsequent behavior of floating-point arithmetic. + */ +typedef unsigned int fexcept_t; + +#endif /* !_I386_FENV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/frame.h b/lib/libc/include/x86-openbsd-none/i386/frame.h new file mode 100644 index 000000000000..dbdb06fd21b9 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/frame.h @@ -0,0 +1,173 @@ +/* $OpenBSD: frame.h,v 1.13 2018/06/15 17:58:41 bluhm Exp $ */ +/* $NetBSD: frame.h,v 1.12 1995/10/11 04:20:08 mycroft Exp $ */ + +/*- + * Copyright (c) 1995 Charles M. Hannum. All rights reserved. + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)frame.h 5.2 (Berkeley) 1/18/91 + */ + +#ifndef _MACHINE_FRAME_H +#define _MACHINE_FRAME_H +#include + +/* + * System stack frames. + */ + +/* + * Exception/Trap Stack Frame + */ +struct trapframe { + int tf_fs; + int tf_gs; + int tf_es; + int tf_ds; + int tf_edi; + int tf_esi; + int tf_err; /* not the hardware position */ + int tf_ebx; + int tf_edx; + int tf_ecx; + int tf_eax; + int tf_trapno; + /* below portion defined in 386 hardware */ + int tf_ebp; /* hardware puts err here, INTRENTRY() moves it up */ + int tf_eip; + int tf_cs; + int tf_eflags; + /* below used when transitting rings (e.g. user to kernel) */ + int tf_esp; + int tf_ss; + /* below used when switching out of VM86 mode */ + int tf_vm86_es; + int tf_vm86_ds; + int tf_vm86_fs; + int tf_vm86_gs; +}; + +/* + * Interrupt stack frame + */ +struct intrframe { + int if_ppl; + int if_fs; + int if_gs; + int if_es; + int if_ds; + int if_edi; + int if_esi; + int :32; /* for compat with trap frame - err */ + int if_ebx; + int if_edx; + int if_ecx; + int if_eax; + int :32; /* for compat with trap frame - trapno */ + int if_ebp; + /* below portion defined in 386 hardware */ + int if_eip; + int if_cs; + int if_eflags; + /* below only when transitting rings (e.g. user to kernel) */ + int if_esp; + int if_ss; +}; + +/* + * iret stack frame + */ +struct iretframe { + int irf_trapno; + int irf_err; + int irf_eip; + int irf_cs; + int irf_eflags; + int irf_esp; + int irf_ss; + /* below used when switching back to VM86 mode */ + int irf_vm86_es; + int irf_vm86_ds; + int irf_vm86_fs; + int irf_vm86_gs; +}; + +/* + * Trampoline stack frame + */ +struct trampframe { + int trf__deadbeef; + int trf__kern_esp; + int trf_fs; + int trf_eax; + int trf_ebp; + int trf_trapno; + int trf_err; + int trf_eip; + int trf_cs; + int trf_eflags; + int trf_esp; + int trf_ss; + /* below used when switching out of VM86 mode */ + int trf_vm86_es; + int trf_vm86_ds; + int trf_vm86_fs; + int trf_vm86_gs; +}; + +/* + * Stack frame inside cpu_switch() + */ +struct switchframe { + int sf_edi; + int sf_esi; + int sf_ebx; + int sf_eip; +}; + +struct callframe { + struct callframe *f_frame; + int f_retaddr; + int f_arg0; +}; + +/* + * Signal frame + */ +struct sigframe { + int sf_signum; + siginfo_t *sf_sip; + struct sigcontext *sf_scp; + sig_t sf_handler; + struct sigcontext sf_sc; + siginfo_t sf_si; +}; +#endif \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/gdt.h b/lib/libc/include/x86-openbsd-none/i386/gdt.h new file mode 100644 index 000000000000..d88017f3cf5a --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/gdt.h @@ -0,0 +1,43 @@ +/* $OpenBSD: gdt.h,v 1.18 2024/05/22 05:51:49 jsg Exp $ */ +/* $NetBSD: gdt.h,v 1.7.10.6 2002/08/19 01:22:36 sommerfeld Exp $ */ + +/*- + * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by John T. Kohl and Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LOCORE + +struct cpu_info; +struct pcb; +struct pmap; + +void gdt_alloc_cpu(struct cpu_info *); +void gdt_init(void); +void gdt_init_cpu(struct cpu_info *); +void setgdt(int, void *, size_t, int, int, int, int); +#endif \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/hibernate.h b/lib/libc/include/x86-openbsd-none/i386/hibernate.h new file mode 100644 index 000000000000..493fa4d82cc4 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/hibernate.h @@ -0,0 +1,35 @@ +/* $OpenBSD: hibernate.h,v 1.10 2018/06/21 07:33:30 mlarkin Exp $ */ + +/* + * Copyright (c) 2011 Mike Larkin + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +/* i386 hibernate support structures and functions */ + +int get_hibernate_info_md(union hibernate_info *); +void hibernate_flush(void); +void hibernate_enter_resume_mapping(vaddr_t, paddr_t, int); +int hibernate_inflate_skip(union hibernate_info *, paddr_t); +int hibernate_suspend(void); +void hibernate_switch_stack_machdep(void); +void hibernate_resume_machdep(vaddr_t); +void hibernate_activate_resume_pt_machdep(void); +void hibernate_enable_intr_machdep(void); +void hibernate_disable_intr_machdep(void); +#ifdef MULTIPROCESSOR +void hibernate_quiesce_cpus(void); +#endif /* MULTIPROCESSOR */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/hibernate_var.h b/lib/libc/include/x86-openbsd-none/i386/hibernate_var.h new file mode 100644 index 000000000000..e37fa095cec9 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/hibernate_var.h @@ -0,0 +1,53 @@ +/* $OpenBSD: hibernate_var.h,v 1.16 2025/05/21 04:05:22 mlarkin Exp $ */ + +/* + * Copyright (c) 2011 Mike Larkin + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define HIB_PD_MASK 0xffc00000 +#define PIGLET_PAGE_MASK (HIB_PD_MASK) + +#define HIBERNATE_PD_PAGE (PAGE_SIZE * 21) +#define HIBERNATE_PT_PAGE (PAGE_SIZE * 22) +/* 2 pages for stack */ +#define HIBERNATE_STACK_PAGE (PAGE_SIZE * 24) +#define HIBERNATE_INFLATE_PAGE (PAGE_SIZE * 25) +/* HIBERNATE_HIBALLOC_PAGE must be the last stolen page (see machdep.c) */ +#define HIBERNATE_HIBALLOC_PAGE (PAGE_SIZE * 26) + +/* Use 4MB hibernation chunks */ +#define HIBERNATE_CHUNK_SIZE 0x400000 + +#define HIBERNATE_CHUNK_TABLE_SIZE 0x100000 + +#define HIBERNATE_STACK_OFFSET 0x0F00 + +#define atop_4m(x) ((x) >> PDSHIFT) +#define atop_4k(x) ((x) >> PAGE_SHIFT) +#define s4pde_4m(va) ((pt_entry_t *)HIBERNATE_PD_PAGE + atop_4m(va)) +#define s4pde_4k(va) ((pt_entry_t *)HIBERNATE_PD_PAGE + atop_4k(va)) +#define s4pte_4k(va) ((pt_entry_t *)HIBERNATE_PT_PAGE + atop_4k(va)) + +/* + * Minimum amount of memory for hibernate support. This is used in early boot + * when deciding if we can preallocate the piglet. If the machine does not + * have at least HIBERNATE_MIN_MEMORY RAM, we won't support hibernate. This + * avoids late allocation issues due to fragmented memory and failure to + * hibernate. We need to be able to allocate 16MB contiguous memory, aligned + * to 2MB. + * + * The default minimum required memory is 512MB (1ULL << 29). + */ +#define HIBERNATE_MIN_MEMORY (1ULL << 29) \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/i82093reg.h b/lib/libc/include/x86-openbsd-none/i386/i82093reg.h new file mode 100644 index 000000000000..ac97c359552a --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/i82093reg.h @@ -0,0 +1,118 @@ +/* $OpenBSD: i82093reg.h,v 1.6 2022/12/08 01:25:45 guenther Exp $ */ +/* $NetBSD: i82093reg.h,v 1.1.2.2 2000/02/21 18:54:07 sommerfeld Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Typically, the first apic lives here. + */ +#define IOAPIC_BASE_DEFAULT 0xfec00000 + +/* + * Memory-space registers. + */ + +/* + * The externally visible registers are all 32 bits wide; + * store the register number of interest in IOAPIC_REG, and store/fetch + * the real value in IOAPIC_DATA. + */ +#define IOAPIC_REG 0x0000 +#define IOAPIC_DATA 0x0010 + +/* + * Internal I/O APIC registers. + */ + +#define IOAPIC_ID 0x00 + +#define IOAPIC_ID_SHIFT 24 +#define IOAPIC_ID_MASK 0x0f000000 + +/* Version, and maximum interrupt pin number. */ + +#define IOAPIC_VER 0x01 + +#define IOAPIC_VER_SHIFT 0 +#define IOAPIC_VER_MASK 0x000000ff + +#define IOAPIC_MAX_SHIFT 16 +#define IOAPIC_MAX_MASK 0x00ff0000 + +/* + * Arbitration ID. Same format as IOAPIC_ID register. + */ +#define IOAPIC_ARB 0x02 + +/* + * Redirection table registers. + */ + +#define IOAPIC_REDHI(pin) (0x11 + ((pin)<<1)) +#define IOAPIC_REDLO(pin) (0x10 + ((pin)<<1)) + +#define IOAPIC_REDHI_DEST_SHIFT 24 /* destination. */ +#define IOAPIC_REDHI_DEST_MASK 0xff000000 + +#define IOAPIC_REDLO_MASK 0x00010000 /* 0=enabled; 1=masked */ + +#define IOAPIC_REDLO_LEVEL 0x00008000 /* 0=edge, 1=level */ +#define IOAPIC_REDLO_RIRR 0x00004000 /* remote IRR; read only */ +#define IOAPIC_REDLO_ACTLO 0x00002000 /* 0=act. hi; 1=act. lo */ +#define IOAPIC_REDLO_DELSTS 0x00001000 /* 0=idle; 1=send pending */ +#define IOAPIC_REDLO_DSTMOD 0x00000800 /* 0=physical; 1=logical */ + +#define IOAPIC_REDLO_DEL_MASK 0x00000700 /* del. mode mask */ +#define IOAPIC_REDLO_DEL_SHIFT 8 + +#define IOAPIC_REDLO_DEL_FIXED 0 +#define IOAPIC_REDLO_DEL_LOPRI 1 +#define IOAPIC_REDLO_DEL_SMI 2 +#define IOAPIC_REDLO_DEL_NMI 4 +#define IOAPIC_REDLO_DEL_INIT 5 +#define IOAPIC_REDLO_DEL_EXTINT 7 + +#define IOAPIC_REDLO_VECTOR_MASK 0x000000ff /* delivery vector */ + +#define IMCR_ADDR 0x22 +#define IMCR_DATA 0x23 + +#define IMCR_REGISTER 0x70 +#define IMCR_PIC 0x00 +#define IMCR_APIC 0x01 + +#ifdef _KERNEL + +#define ioapic_asm_ack(num) \ + movl $0,local_apic + LAPIC_EOI + +#endif \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/i82093var.h b/lib/libc/include/x86-openbsd-none/i386/i82093var.h new file mode 100644 index 000000000000..a74a367ff814 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/i82093var.h @@ -0,0 +1,99 @@ +/* $OpenBSD: i82093var.h,v 1.13 2024/10/22 21:50:02 jsg Exp $ */ +/* $NetBSD: i82093var.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_I82093VAR_H_ +#define _MACHINE_I82093VAR_H_ + +#include + +struct ioapic_pin { + struct intrhand *ip_handler; + struct ioapic_pin *ip_next; /* next pin on this vector */ + struct mp_intr_map *ip_map; + int ip_vector; /* IDT vector */ + int ip_type; + int ip_minlevel; + int ip_maxlevel; +}; + +struct ioapic_softc { + struct pic sc_pic; + struct ioapic_softc *sc_next; + int sc_apicid; + int sc_apic_vers; + int sc_apic_vecbase; /* global int base if ACPI */ + int sc_apic_sz; /* apic size*/ + int sc_flags; + paddr_t sc_pa; /* PA of ioapic */ + volatile u_int32_t *sc_reg; /* KVA of ioapic addr */ + volatile u_int32_t *sc_data; /* KVA of ioapic data */ + struct ioapic_pin *sc_pins; /* sc_apic_sz entries */ +}; + +/* + * MP: intr_handle_t is bitfielded. + * ih&0xff -> line number. + * ih&0x10000000 -> if 0, old-style isa irq; if 1, routed via ioapic. + * (ih&0xff0000)>>16 -> ioapic id. + * (ih&0x00ff00)>>8 -> ioapic line. + */ + +#define APIC_INT_VIA_APIC 0x10000000 +#define APIC_INT_VIA_MSG 0x20000000 +#define APIC_INT_APIC_MASK 0x00ff0000 +#define APIC_INT_APIC_SHIFT 16 +#define APIC_INT_PIN_MASK 0x0000ff00 +#define APIC_INT_PIN_SHIFT 8 +#define APIC_INT_LINE_MASK 0x000000ff + +#define APIC_IRQ_APIC(x) ((x & APIC_INT_APIC_MASK) >> APIC_INT_APIC_SHIFT) +#define APIC_IRQ_PIN(x) ((x & APIC_INT_PIN_MASK) >> APIC_INT_PIN_SHIFT) + +void *apic_intr_establish(int, int, int, int (*)(void *), void *, + const char *); +void apic_intr_disestablish(void *); + +void ioapic_print_redir(struct ioapic_softc *, char *, int); +struct ioapic_softc *ioapic_find(int); +struct ioapic_softc *ioapic_find_bybase(int); + +void ioapic_enable(void); + +extern int ioapic_bsp_id; +extern int nioapics; +extern struct ioapic_softc *ioapics; +extern u_int16_t ioapic_id_map; +extern u_int8_t ioapic_id_remap[]; + +#endif /* !_MACHINE_I82093VAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/i82489reg.h b/lib/libc/include/x86-openbsd-none/i386/i82489reg.h new file mode 100644 index 000000000000..bb3c256cfb89 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/i82489reg.h @@ -0,0 +1,144 @@ +/* $OpenBSD: i82489reg.h,v 1.5 2019/07/26 04:35:38 kevlo Exp $ */ +/* $NetBSD: i82489reg.h,v 1.1.2.1 2000/02/20 16:30:27 sommerfeld Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Frank van der Linden. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +/* + * Registers and constants for the 82489DX and Pentium (and up) integrated + * "local" APIC. + */ + +#define LAPIC_ID 0x020 /* ID. RW */ +# define LAPIC_ID_MASK 0x0f000000 +# define LAPIC_ID_SHIFT 24 + +#define LAPIC_VERS 0x030 /* Version. R */ +# define LAPIC_VERSION_MASK 0x000000ff +# define LAPIC_VERSION_LVT_MASK 0x00ff0000 +# define LAPIC_VERSION_LVT_SHIFT 16 + +#define LAPIC_TPRI 0x080 /* Task Prio. RW */ +# define LAPIC_TPRI_MASK 0x000000ff +# define LAPIC_TPRI_INT_MASK 0x000000f0 +# define LAPIC_TPRI_SUB_MASK 0x0000000f + +#define LAPIC_APRI 0x090 /* Arbitration prio R */ +# define LAPIC_APRI_MASK 0x000000ff + +#define LAPIC_PPRI 0x0a0 /* Processor prio. R */ +#define LAPIC_EOI 0x0b0 /* End Int. W */ +#define LAPIC_RRR 0x0c0 /* Remote read R */ +#define LAPIC_LDR 0x0d0 /* Logical dest. RW */ +#define LAPIC_DFR 0x0e0 /* Dest. format RW */ + +#define LAPIC_SVR 0x0f0 /* Spurious intvec RW */ +# define LAPIC_SVR_VECTOR_MASK 0x000000ff +# define LAPIC_SVR_VEC_FIX 0x0000000f +# define LAPIC_SVR_VEC_PROG 0x000000f0 +# define LAPIC_SVR_ENABLE 0x00000100 +# define LAPIC_SVR_SWEN 0x00000100 +# define LAPIC_SVR_FOCUS 0x00000200 +# define LAPIC_SVR_FDIS 0x00000200 + +#define LAPIC_ISR 0x100 /* Int. status. R */ +#define LAPIC_TMR 0x180 +#define LAPIC_IRR 0x200 +#define LAPIC_ESR 0x280 /* Err status. R */ + +#define LAPIC_ICRLO 0x300 /* Int. cmd. RW */ +# define LAPIC_DLMODE_MASK 0x00000700 +# define LAPIC_DLMODE_FIXED 0x00000000 +# define LAPIC_DLMODE_LOW 0x00000100 +# define LAPIC_DLMODE_SMI 0x00000200 +# define LAPIC_DLMODE_RR 0x00000300 +# define LAPIC_DLMODE_NMI 0x00000400 +# define LAPIC_DLMODE_INIT 0x00000500 +# define LAPIC_DLMODE_STARTUP 0x00000600 + +# define LAPIC_DSTMODE_LOG 0x00000800 + +# define LAPIC_DLSTAT_BUSY 0x00001000 + +# define LAPIC_LVL_ASSERT 0x00004000 +# define LAPIC_LVL_DEASSERT 0x00000000 + +# define LAPIC_LVL_TRIG 0x00008000 + +# define LAPIC_RRSTAT_MASK 0x00030000 +# define LAPIC_RRSTAT_INPROG 0x00010000 +# define LAPIC_RRSTAT_VALID 0x00020000 + +# define LAPIC_DEST_MASK 0x000c0000 +# define LAPIC_DEST_SELF 0x00040000 +# define LAPIC_DEST_ALLINCL 0x00080000 +# define LAPIC_DEST_ALLEXCL 0x000c0000 + +# define LAPIC_RESV2_MASK 0xfff00000 + + +#define LAPIC_ICRHI 0x310 /* Int. cmd. RW */ + +#define LAPIC_LVTT 0x320 /* Loc.vec.(timer) RW */ +# define LAPIC_LVTT_VEC_MASK 0x000000ff +# define LAPIC_LVTT_DS 0x00001000 +# define LAPIC_LVTT_M 0x00010000 +# define LAPIC_LVTT_TM 0x00020000 +# define LAPIC_LVTT_TM_ONESHOT 0x00000000 +# define LAPIC_LVTT_TM_PERIODIC 0x00020000 +# define LAPIC_LVTT_TM_TSCDL 0x00040000 + +#define LAPIC_PCINT 0x340 +#define LAPIC_LVINT0 0x350 /* Loc.vec (LINT0) RW */ +# define LAPIC_LVT_PERIODIC 0x00020000 +# define LAPIC_LVT_MASKED 0x00010000 +# define LAPIC_LVT_LEVTRIG 0x00008000 +# define LAPIC_LVT_REMOTE_IRR 0x00004000 +# define LAPIC_INP_POL 0x00002000 +# define LAPIC_PEND_SEND 0x00001000 + +#define LAPIC_LVINT1 0x360 /* Loc.vec (LINT1) RW */ +#define LAPIC_LVERR 0x370 /* Loc.vec (ERROR) RW */ +#define LAPIC_ICR_TIMER 0x380 /* Initial count RW */ +#define LAPIC_CCR_TIMER 0x390 /* Current count RO */ + +#define LAPIC_DCR_TIMER 0x3e0 /* Divisor config register */ +# define LAPIC_DCRT_DIV1 0x0b +# define LAPIC_DCRT_DIV2 0x00 +# define LAPIC_DCRT_DIV4 0x01 +# define LAPIC_DCRT_DIV8 0x02 +# define LAPIC_DCRT_DIV16 0x03 +# define LAPIC_DCRT_DIV32 0x08 +# define LAPIC_DCRT_DIV64 0x09 +# define LAPIC_DCRT_DIV128 0x0a + +#define LAPIC_BASE 0xfee00000 + +#define LAPIC_IRQ_MASK(i) (1 << ((i) + 1)) \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/i82489var.h b/lib/libc/include/x86-openbsd-none/i386/i82489var.h new file mode 100644 index 000000000000..bfdf6811710d --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/i82489var.h @@ -0,0 +1,128 @@ +/* $OpenBSD: i82489var.h,v 1.16 2024/07/07 03:03:09 jsg Exp $ */ +/* $NetBSD: i82489var.h,v 1.1.2.2 2000/02/21 18:46:14 sommerfeld Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Frank van der Linden. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_I82489VAR_H_ +#define _MACHINE_I82489VAR_H_ + +static __inline__ u_int32_t i82489_readreg(int); +static __inline__ void i82489_writereg(int, u_int32_t); + +#ifdef _KERNEL +extern volatile u_int32_t local_apic[]; +#endif + +static __inline__ u_int32_t +i82489_readreg(int reg) +{ + return *((volatile u_int32_t *)(((volatile u_int8_t *)local_apic) + + reg)); +} + +static __inline__ void +i82489_writereg(int reg, u_int32_t val) +{ + *((volatile u_int32_t *)(((volatile u_int8_t *)local_apic) + reg)) = + val; + /* + * intel xeon errata p53: + * write to a lapic register sometimes may appear to have not occurred + * workaround: + * follow write with a read [from id register] + */ + val = *((volatile u_int32_t *)(((volatile u_int8_t *)local_apic) + + LAPIC_ID)); +} + +/* + * "spurious interrupt vector"; vector used by interrupt which was + * aborted because the CPU masked it after it happened but before it + * was delivered.. "Oh, sorry, i caught you at a bad time". + * Low-order 4 bits must be all ones. + */ +extern void Xintrspurious(void); +#define LAPIC_SPURIOUS_VECTOR 0xef + +/* + * Vector used for inter-processor interrupts. + */ +extern void Xintripi(void); +#define LAPIC_IPI_VECTOR IPL_IPI + +/* + * Vector used for local apic timer interrupts. + */ + +extern void Xintrltimer(void); +#define LAPIC_TIMER_VECTOR IPL_CLOCK + +/* + * Vectors to be used for self-soft-interrupts. + */ + +#define LAPIC_SOFTCLOCK_VECTOR IPL_SOFTCLOCK +#define LAPIC_SOFTNET_VECTOR IPL_SOFTNET +#define LAPIC_SOFTTTY_VECTOR IPL_SOFTTTY + +/* + * Special IPI vectors. We can use IDT 0xf0 - 0xff for this. + */ +#define LAPIC_IPI_OFFSET 0xf0 +#define LAPIC_IPI_INVLTLB (LAPIC_IPI_OFFSET + 0) +#define LAPIC_IPI_INVLPG (LAPIC_IPI_OFFSET + 1) +#define LAPIC_IPI_INVLRANGE (LAPIC_IPI_OFFSET + 2) +#define LAPIC_IPI_RELOADCR3 (LAPIC_IPI_OFFSET + 3) + +extern void Xintripi_invltlb(void); +extern void Xintripi_invlpg(void); +extern void Xintripi_invlrange(void); +extern void Xintripi_reloadcr3(void); + +extern void Xintrsoftclock(void); +extern void Xintrsoftnet(void); +extern void Xintrsofttty(void); + +extern void (*apichandler[])(void); + +struct cpu_info; + +extern void lapic_boot_init(paddr_t); +extern void lapic_startclock(void); +extern void lapic_initclocks(void); +extern void lapic_set_lvt(void); +extern void lapic_set_softvectors(void); +extern void lapic_enable(void); +extern void lapic_disable(void); +extern void lapic_calibrate_timer(struct cpu_info *); + +#define lapic_cpu_number() (i82489_readreg(LAPIC_ID)>>LAPIC_ID_SHIFT) + +#endif \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/i8259.h b/lib/libc/include/x86-openbsd-none/i386/i8259.h new file mode 100644 index 000000000000..724ae4f4f189 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/i8259.h @@ -0,0 +1,144 @@ +/* $OpenBSD: i8259.h,v 1.7 2015/09/02 13:39:23 mikeb Exp $ */ +/* $NetBSD: i8259.h,v 1.3 2003/05/04 22:01:56 fvdl Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)icu.h 5.6 (Berkeley) 5/9/91 + */ + +#ifndef _MACHINE_I8259_H_ +#define _MACHINE_I8259_H_ + +#include + +#ifndef _LOCORE + +/* + * Interrupt "level" mechanism variables, masks, and macros + */ +extern unsigned imen; /* interrupt mask enable */ + +#define SET_ICUS() (outb(IO_ICU1 + 1, imen), outb(IO_ICU2 + 1, imen >> 8)) + +#endif /* !_LOCORE */ + +/* + * Interrupt enable bits -- in order of priority + */ +#define IRQ_SLAVE 2 + +/* + * Interrupt Control offset into Interrupt descriptor table (IDT) + */ +#define ICU_OFFSET 32 /* 0-31 are processor exceptions */ +#define ICU_LEN 16 /* 32-47 are ISA interrupts */ + + +#define ICU_HARDWARE_MASK + +/* + * These macros are fairly self explanatory. If ICU_SPECIAL_MASK_MODE is + * defined, we try to take advantage of the ICU's `special mask mode' by only + * EOIing the interrupts on return. This avoids the requirement of masking and + * unmasking. We can't do this without special mask mode, because the ICU + * would also hold interrupts that it thinks are of lower priority. + * + * Many machines do not support special mask mode, so by default we don't try + * to use it. + */ + +#define IRQ_BIT(num) (1 << ((num) % 8)) +#define IRQ_BYTE(num) ((num) >> 3) + +#define i8259_late_ack(num) + +#ifdef ICU_SPECIAL_MASK_MODE + +#define i8259_asm_ack1(num) +#define i8259_asm_ack2(num) \ + movb $(0x60|IRQ_SLAVE),%al /* specific EOI for IRQ2 */ ;\ + outb %al,$IO_ICU1 +#define i8259_asm_mask(num) +#define i8259_asm_unmask(num) \ + movb $(0x60|(num%8)),%al /* specific EOI */ ;\ + outb %al,$ICUADDR + +#else /* ICU_SPECIAL_MASK_MODE */ + +#ifndef AUTO_EOI_1 +#define i8259_asm_ack1(num) \ + movb $(0x60|(num%8)),%al /* specific EOI */ ;\ + outb %al,$IO_ICU1 +#else +#define i8259_asm_ack1(num) +#endif + +#ifndef AUTO_EOI_2 +#define i8259_asm_ack2(num) \ + movb $(0x60|(num%8)),%al /* specific EOI */ ;\ + outb %al,$IO_ICU2 /* do the second ICU first */ ;\ + movb $(0x60|IRQ_SLAVE),%al /* specific EOI for IRQ2 */ ;\ + outb %al,$IO_ICU1 +#else +#define i8259_asm_ack2(num) +#endif + +#ifdef ICU_HARDWARE_MASK + +#define i8259_asm_mask(num) \ + movb CVAROFF(imen, IRQ_BYTE(num)),%al ;\ + orb $IRQ_BIT(num),%al ;\ + movb %al,CVAROFF(imen, IRQ_BYTE(num)) ;\ + pushl %eax ;\ + inb $0x84,%al ;\ + popl %eax ;\ + outb %al,$(ICUADDR+1) +#define i8259_asm_unmask(num) \ + cli ;\ + movb CVAROFF(imen, IRQ_BYTE(num)),%al ;\ + andb $~IRQ_BIT(num),%al ;\ + movb %al,CVAROFF(imen, IRQ_BYTE(num)) ;\ + pushl %eax ;\ + inb $0x84,%al ;\ + popl %eax ;\ + outb %al,$(ICUADDR+1) ;\ + sti + +#else /* ICU_HARDWARE_MASK */ + +#define i8259_asm_mask(num) +#define i8259_asm_unmask(num) + +#endif /* ICU_HARDWARE_MASK */ +#endif /* ICU_SPECIAL_MASK_MODE */ + +#endif /* !_MACHINE_I8259_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/ieee.h b/lib/libc/include/x86-openbsd-none/i386/ieee.h new file mode 100644 index 000000000000..cc799d2c2734 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/ieee.h @@ -0,0 +1,141 @@ +/* $OpenBSD: ieee.h,v 1.3 2008/09/07 20:36:06 martynas Exp $ */ +/* $NetBSD: ieee.h,v 1.1 1996/09/30 16:34:25 ws Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ieee.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * ieee.h defines the machine-dependent layout of the machine's IEEE + * floating point. It does *not* define (yet?) any of the rounding + * mode bits, exceptions, and so forth. + */ + +/* + * Define the number of bits in each fraction and exponent. + * + * k k+1 + * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented + * + * (-exp_bias+1) + * as fractions that look like 0.fffff x 2 . This means that + * + * -126 + * the number 0.10000 x 2 , for instance, is the same as the normalized + * + * -127 -128 + * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero + * + * -129 + * in the fraction; to represent 2 , we need two, and so on. This + * + * (-exp_bias-fracbits+1) + * implies that the smallest denormalized number is 2 + * + * for whichever format we are talking about: for single precision, for + * + * -126 -149 + * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and + * + * -149 == -127 - 23 + 1. + */ +#define SNG_EXPBITS 8 +#define SNG_FRACBITS 23 + +#define DBL_EXPBITS 11 +#define DBL_FRACHBITS 20 +#define DBL_FRACLBITS 32 +#define DBL_FRACBITS 52 + +#define EXT_EXPBITS 15 +#define EXT_FRACHBITS 32 +#define EXT_FRACLBITS 32 +#define EXT_FRACBITS 64 + +#define EXT_TO_ARRAY32(p, a) do { \ + (a)[0] = (uint32_t)(p)->ext_fracl; \ + (a)[1] = (uint32_t)(p)->ext_frach; \ +} while(0) + +struct ieee_single { + u_int sng_frac:23; + u_int sng_exp:8; + u_int sng_sign:1; +}; + +struct ieee_double { + u_int dbl_fracl; + u_int dbl_frach:20; + u_int dbl_exp:11; + u_int dbl_sign:1; +}; + +struct ieee_ext { + u_int ext_fracl; + u_int ext_frach; + u_int ext_exp:15; + u_int ext_sign:1; + u_int ext_pad:16; +}; + +/* + * Floats whose exponent is in [1..INFNAN) (of whatever type) are + * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. + * Floats whose exponent is zero are either zero (iff all fraction + * bits are zero) or subnormal values. + * + * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its + * high fraction; if the bit is set, it is a `quiet NaN'. + */ +#define SNG_EXP_INFNAN 255 +#define DBL_EXP_INFNAN 2047 +#define EXT_EXP_INFNAN 32767 + +#if 0 +#define SNG_QUIETNAN (1 << 22) +#define DBL_QUIETNAN (1 << 19) +#define EXT_QUIETNAN (1 << 15) +#endif + +/* + * Exponent biases. + */ +#define SNG_EXP_BIAS 127 +#define DBL_EXP_BIAS 1023 +#define EXT_EXP_BIAS 16383 \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/ieeefp.h b/lib/libc/include/x86-openbsd-none/i386/ieeefp.h new file mode 100644 index 000000000000..9a9a90bad753 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/ieeefp.h @@ -0,0 +1,26 @@ +/* $OpenBSD: ieeefp.h,v 1.3 2011/03/23 16:54:35 pirofti Exp $ */ + +/* + * Written by J.T. Conklin, Apr 6, 1995 + * Public domain. + */ + +#ifndef _MACHINE_IEEEFP_H_ +#define _MACHINE_IEEEFP_H_ + +typedef int fp_except; +#define FP_X_INV 0x01 /* invalid operation exception */ +#define FP_X_DNML 0x02 /* denormalization exception */ +#define FP_X_DZ 0x04 /* divide-by-zero exception */ +#define FP_X_OFL 0x08 /* overflow exception */ +#define FP_X_UFL 0x10 /* underflow exception */ +#define FP_X_IMP 0x20 /* imprecise (loss of precision) */ + +typedef enum { + FP_RN=0, /* round to nearest representable number */ + FP_RM=1, /* round toward negative infinity */ + FP_RP=2, /* round toward positive infinity */ + FP_RZ=3 /* round to zero (truncate) */ +} fp_rnd; + +#endif /* _MACHINE_IEEEFP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/intr.h b/lib/libc/include/x86-openbsd-none/i386/intr.h new file mode 100644 index 000000000000..299370353b2f --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/intr.h @@ -0,0 +1,149 @@ +/* $OpenBSD: intr.h,v 1.51 2025/04/25 12:47:37 mvs Exp $ */ +/* $NetBSD: intr.h,v 1.5 1996/05/13 06:11:28 mycroft Exp $ */ + +/* + * Copyright (c) 1996 Charles M. Hannum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Charles M. Hannum. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_INTR_H_ +#define _MACHINE_INTR_H_ + +#define __USE_MI_SOFTINTR + +#include +#include + +#ifndef _LOCORE +#include +#include + +extern volatile u_int32_t lapic_tpr; /* Current interrupt priority level. */ + +extern int imask[]; /* Bitmasks telling what interrupts are blocked. */ +extern int iunmask[]; /* Bitmasks telling what interrupts are accepted. */ + +#define IMASK(level) imask[IPL(level)] +#define IUNMASK(level) iunmask[IPL(level)] + +extern void Xspllower(void); + +extern int splraise(int); +extern int spllower(int); +extern void splx(int); +extern void softintr(int); + +/* + * compiler barrier: prevent reordering of instructions. + * This prevents the compiler from reordering code around + * this "instruction", acting as a sequence point for code generation. + */ + +#define __splbarrier() __asm volatile("":::"memory") + +/* SPL asserts */ +#ifdef DIAGNOSTIC +/* + * Although this function is implemented in MI code, it must be in this MD + * header because we don't want this header to include MI includes. + */ +void splassert_fail(int, int, const char *); +extern int splassert_ctl; +void splassert_check(int, const char *); +#define splassert(__wantipl) do { \ + if (splassert_ctl > 0) { \ + splassert_check(__wantipl, __func__); \ + } \ +} while (0) +#define splsoftassert(wantipl) splassert(wantipl) +#else +#define splassert(wantipl) do { /* nada */ } while (0) +#define splsoftassert(wantipl) do { /* nada */ } while (0) +#endif + +/* + * Define the splraise and splx code in macros, so that the code can be + * reused in a profiling build in a way that does not cause recursion. + */ +#define _SPLRAISE(ocpl, ncpl) \ + ocpl = lapic_tpr; \ + if (ncpl > ocpl) \ + lapic_tpr = ncpl + + +#define _SPLX(ncpl) \ + lapic_tpr = ncpl; \ + if (curcpu()->ci_ipending & IUNMASK(ncpl)) \ + Xspllower() + +/* + * Hardware interrupt masks + */ +#define splbio() splraise(IPL_BIO) +#define splnet() splraise(IPL_NET) +#define spltty() splraise(IPL_TTY) +#define splaudio() splraise(IPL_AUDIO) +#define splclock() splraise(IPL_CLOCK) +#define splstatclock() splclock() +#define splipi() splraise(IPL_IPI) + +/* + * Software interrupt masks + */ +#define splsoftclock() splraise(IPL_SOFTCLOCK) +#define splsoftnet() splraise(IPL_SOFTNET) +#define splsofttty() splraise(IPL_SOFTTTY) + +/* + * Miscellaneous + */ +#define splvm() splraise(IPL_VM) +#define splhigh() splraise(IPL_HIGH) +#define splsched() splraise(IPL_SCHED) +#define spl0() spllower(IPL_NONE) + +#include + +struct cpu_info; + +void intr_barrier(void *); +void intr_enable_wakeup(void); +void intr_disable_wakeup(void); + +#ifdef MULTIPROCESSOR +void i386_send_ipi(struct cpu_info *, int); +int i386_fast_ipi(struct cpu_info *, int); +void i386_broadcast_ipi(int); +void i386_ipi_handler(void); +void i386_setperf_ipi(struct cpu_info *); + +extern void (*ipifunc[I386_NIPI])(struct cpu_info *); +#endif + +#endif /* !_LOCORE */ + +#endif /* !_MACHINE_INTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/intrdefs.h b/lib/libc/include/x86-openbsd-none/i386/intrdefs.h new file mode 100644 index 000000000000..dedc83ff0368 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/intrdefs.h @@ -0,0 +1,126 @@ +/* $OpenBSD: intrdefs.h,v 1.20 2025/06/11 09:57:01 kettenis Exp $ */ +/* $NetBSD: intrdefs.h,v 1.2 2003/05/04 22:01:56 fvdl Exp $ */ + +#ifndef _I386_INTRDEFS_H +#define _I386_INTRDEFS_H + +/* + * Intel APICs (advanced programmable interrupt controllers) have + * bytesized priority registers where the upper nibble is the actual + * interrupt priority level (a.k.a. IPL). Interrupt vectors are + * closely tied to these levels as interrupts whose vectors' upper + * nibble is lower than or equal to the current level are blocked. + * Not all 256 possible vectors are available for interrupts in + * APIC systems, only + * + * For systems where instead the older ICU (interrupt controlling + * unit, a.k.a. PIC or 82C59) is used, the IPL is not directly useful, + * since the interrupt blocking is handled via interrupt masks instead + * of levels. However the IPL is easily used as an offset into arrays + * of masks. + */ +#define IPLSHIFT 4 /* The upper nibble of vectors is the IPL. */ +#define NIPL 16 /* Four bits of information gives as much. */ +#define IPL(level) ((level) >> IPLSHIFT) /* Extract the IPL. */ +/* XXX Maybe this IDTVECOFF definition should be elsewhere? */ +#define IDTVECOFF 0x20 /* The lower 32 IDT vectors are reserved. */ + +/* + * This macro is only defined for 0 <= x < 14, i.e. there are fourteen + * distinct priority levels available for interrupts. + */ +#define MAKEIPL(priority) (IDTVECOFF + ((priority) << IPLSHIFT)) + +/* + * Interrupt priority levels. + * + * XXX We are somewhat sloppy about what we mean by IPLs, sometimes + * XXX we refer to the eight-bit value suitable for storing into APICs' + * XXX priority registers, other times about the four-bit entity found + * XXX in the former values' upper nibble, which can be used as offsets + * XXX in various arrays of our implementation. We are hoping that + * XXX the context will provide enough information to not make this + * XXX sloppy naming a real problem. + * + * There are tty, network and disk drivers that use free() at interrupt + * time, so imp > (tty | net | bio). + * + * Since run queues may be manipulated by both the statclock and tty, + * network, and disk drivers, clock > imp. + * + * IPL_HIGH must block everything that can manipulate a run queue. + * + * XXX Ultimately we may need serial drivers to run at the absolute highest + * XXX priority to avoid overruns, then we must make serial > high. + * + * The level numbers are picked to fit into APIC vector priorities. + */ +#define IPL_NONE 0 /* nothing */ +#define IPL_SOFTCLOCK MAKEIPL(1) /* timeouts */ +#define IPL_SOFTNET MAKEIPL(2) /* protocol stacks */ +#define IPL_BIO MAKEIPL(3) /* block I/O */ +#define IPL_NET MAKEIPL(4) /* network */ +#define IPL_SOFTTTY MAKEIPL(5) /* delayed terminal handling */ +#define IPL_TTY MAKEIPL(6) /* terminal */ +#define IPL_VM MAKEIPL(7) /* memory allocation */ +#define IPL_AUDIO MAKEIPL(8) /* audio */ +#define IPL_CLOCK MAKEIPL(9) /* clock */ +#define IPL_STATCLOCK IPL_CLOCK /* statclock */ +#define IPL_SCHED IPL_CLOCK +#define IPL_HIGH MAKEIPL(10) /* everything */ +#define IPL_IPI MAKEIPL(11) /* interprocessor interrupt */ + +#define IPL_MPFLOOR IPL_TTY +#define IPL_MPSAFE 0x100 +#define IPL_WAKEUP 0 + +/* Interrupt sharing types. */ +#define IST_NONE 0 /* none */ +#define IST_PULSE 1 /* pulsed */ +#define IST_EDGE 2 /* edge-triggered */ +#define IST_LEVEL 3 /* level-triggered */ + +/* + * Local APIC masks. Must not conflict with SIR_* below, and must + * be >= NUM_LEGACY_IRQs. Note that LIR_IPI must be first. + */ +#define LIR_IPI 31 +#define LIR_TIMER 30 + +/* Soft interrupt masks. */ +#define SIR_CLOCK 29 +#define SIR_NET 28 +#define SIR_TTY 27 + + +/* + * Maximum # of interrupt sources per CPU. 32 to fit in one word. + * ioapics can theoretically produce more, but it's not likely to + * happen. For multiple ioapics, things can be routed to different + * CPUs. + */ +#define MAX_INTR_SOURCES 32 +#define NUM_LEGACY_IRQS 16 + +/* + * Low and high boundaries between which interrupt gates will + * be allocated in the IDT. + */ +#define IDT_INTR_LOW (0x20 + NUM_LEGACY_IRQS) +#define IDT_INTR_HIGH 0xef + +#define I386_IPI_HALT 0x00000001 +#define I386_IPI_NOP 0x00000002 +#define I386_IPI_FLUSH_FPU 0x00000004 +#define I386_IPI_SYNCH_FPU 0x00000008 +#define I386_IPI_MTRR 0x00000010 +#define I386_IPI_GDT 0x00000020 +#define I386_IPI_DDB 0x00000040 /* synchronize while in ddb */ +#define I386_IPI_SETPERF 0x00000080 +#define I386_IPI_WBINVD 0x00000100 + +#define I386_NIPI 9 + +#define IREENT_MAGIC 0x18041969 + +#endif /* _I386_INTRDEFS_H */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/ioctl_fd.h b/lib/libc/include/x86-openbsd-none/i386/ioctl_fd.h new file mode 100644 index 000000000000..a370bf56f6b4 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/ioctl_fd.h @@ -0,0 +1,131 @@ +/* $OpenBSD: ioctl_fd.h,v 1.4 2011/03/23 16:54:35 pirofti Exp $ */ +/* from: ioctl_fd.h,v 1.4 1995/06/29 03:49:32 jtk Exp */ + +/* + * Copyright (C) 1992-1994 by Joerg Wunsch, Dresden + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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(S) BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * From: Id: ioctl_fd.h,v 1.7 1994/10/30 19:17:39 joerg Exp + */ + +#ifndef _MACHINE_IOCTL_FD_H_ +#define _MACHINE_IOCTL_FD_H_ + +#include + +#define FD_FORMAT_VERSION 110 /* used to validate before formatting */ +#define FD_MAX_NSEC 36 /* highest known number of spt - allow for */ + /* 2.88 MB drives */ + +struct fd_formb { + int format_version; /* == FD_FORMAT_VERSION */ + int cyl, head; + int transfer_rate; /* fdreg.h: FDC_???KBPS */ + + union { + struct fd_form_data { + /* + * DO NOT CHANGE THE LAYOUT OF THIS STRUCTS + * it is hardware-dependant since it exactly + * matches the byte sequence to write to FDC + * during its `format track' operation + */ + u_char secshift; /* 0 -> 128, ...; usually 2 -> 512 */ + u_char nsecs; /* must be <= FD_MAX_NSEC */ + u_char gaplen; /* GAP 3 length; usually 84 */ + u_char fillbyte; /* usually 0xf6 */ + struct fd_idfield_data { + /* + * data to write into id fields; + * for obscure formats, they mustn't match + * the real values (but mostly do) + */ + u_char cylno; /* 0 thru 79 (or 39) */ + u_char headno; /* 0, or 1 */ + u_char secno; /* starting at 1! */ + u_char secsize; /* usually 2 */ + } idfields[FD_MAX_NSEC]; /* 0 <= idx < nsecs used */ + } structured; + u_char raw[1]; /* to have continuous indexed access */ + } format_info; +}; + +/* make life easier */ +# define fd_formb_secshift format_info.structured.secshift +# define fd_formb_nsecs format_info.structured.nsecs +# define fd_formb_gaplen format_info.structured.gaplen +# define fd_formb_fillbyte format_info.structured.fillbyte +/* these data must be filled in for(i = 0; i < fd_formb_nsecs; i++) */ +# define fd_formb_cylno(i) format_info.structured.idfields[i].cylno +# define fd_formb_headno(i) format_info.structured.idfields[i].headno +# define fd_formb_secno(i) format_info.structured.idfields[i].secno +# define fd_formb_secsize(i) format_info.structured.idfields[i].secsize + +/* + * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how + * we tell them apart. + */ +struct fd_type { + int sectrac; /* sectors per track */ + int heads; /* number of heads */ + int seccyl; /* sectors per cylinder */ + int secsize; /* size code for sectors */ + int datalen; /* data len when secsize = 0 */ + int steprate; /* step rate and head unload time */ + int gap1; /* gap len between sectors */ + int gap2; /* formatting gap */ + int tracks; /* total num of tracks */ + int size; /* size of disk in sectors */ + int step; /* steps per cylinder */ + int rate; /* transfer speed code */ + char *name; +}; + + +#define FD_FORM _IOW('F', 61, struct fd_formb) /* format a track */ +#define FD_GTYPE _IOR('F', 62, struct fd_type) /* get drive type */ +#define FD_STYPE _IOW('F', 63, struct fd_type) /* set drive type */ + +#define FD_GOPTS _IOR('F', 64, int) /* drive options, see below */ +#define FD_SOPTS _IOW('F', 65, int) + +#define FDOPT_NORETRY 0x0001 /* no retries on failure (cleared on close) */ + +/* + * The following definitions duplicate those in sys/i386/isa/fdreg.h + * They are here since their values are to be used in the above + * structure when formatting a floppy. For very obvious reasons, both + * definitions must match ;-) + */ +#ifndef FDC_500KBPS +#define FDC_500KBPS 0x00 /* 500KBPS MFM drive transfer rate */ +#define FDC_300KBPS 0x01 /* 300KBPS MFM drive transfer rate */ +#define FDC_250KBPS 0x02 /* 250KBPS MFM drive transfer rate */ +#define FDC_125KBPS 0x03 /* 125KBPS FM drive transfer rate */ + /* for some controllers 1MPBS instead */ +#endif /* FDC_500KBPS */ + + +#endif /* !_MACHINE_IOCTL_FD_H__ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/joystick.h b/lib/libc/include/x86-openbsd-none/i386/joystick.h new file mode 100644 index 000000000000..2d55604d07ba --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/joystick.h @@ -0,0 +1,23 @@ +/* $OpenBSD: joystick.h,v 1.6 2011/03/23 16:54:35 pirofti Exp $ */ +/* $NetBSD: joystick.h,v 1.1 1996/03/27 19:18:56 perry Exp $ */ + +#ifndef _MACHINE_JOYSTICK_H_ +#define _MACHINE_JOYSTICK_H_ + +#include + +struct joystick { + int x; + int y; + int b1; + int b2; +}; + +#define JOY_SETTIMEOUT _IOW('J', 1, int) /* set timeout */ +#define JOY_GETTIMEOUT _IOR('J', 2, int) /* get timeout */ +#define JOY_SET_X_OFFSET _IOW('J', 3, int) /* set offset on X-axis */ +#define JOY_SET_Y_OFFSET _IOW('J', 4, int) /* set offset on Y-axis */ +#define JOY_GET_X_OFFSET _IOR('J', 5, int) /* get offset on X-axis */ +#define JOY_GET_Y_OFFSET _IOR('J', 6, int) /* get offset on Y-axis */ + +#endif /* _MACHINE_JOYSTICK_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/kcore.h b/lib/libc/include/x86-openbsd-none/i386/kcore.h new file mode 100644 index 000000000000..24e23270519b --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/kcore.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2011 Mike Larkin + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_KCORE_H_ +#define _MACHINE_KCORE_H_ + +struct dumpmem { + paddr_t start; + paddr_t end; +}; + +#endif /* _MACHINE_KCORE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/limits.h b/lib/libc/include/x86-openbsd-none/i386/limits.h new file mode 100644 index 000000000000..86b69dfadb56 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/limits.h @@ -0,0 +1,53 @@ +/* $OpenBSD: limits.h,v 1.14 2015/04/30 13:42:08 millert Exp $ */ +/* $NetBSD: limits.h,v 1.11 1995/12/21 01:08:59 mycroft Exp $ */ + +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)limits.h 7.2 (Berkeley) 6/28/90 + */ + +#ifndef _MACHINE_LIMITS_H_ +#define _MACHINE_LIMITS_H_ + +#include + +#if __POSIX_VISIBLE || __XPG_VISIBLE +#define SSIZE_MAX LONG_MAX /* max value for a ssize_t */ +#endif + +#if __BSD_VISIBLE +#define SIZE_T_MAX ULONG_MAX /* max value for a size_t (historic) */ + +#define UQUAD_MAX 0xffffffffffffffffULL /* max unsigned quad */ +#define QUAD_MAX 0x7fffffffffffffffLL /* max signed quad */ +#define QUAD_MIN (-0x7fffffffffffffffLL-1) /* min signed quad */ + +#endif /* __BSD_VISIBLE */ + +#endif /* _MACHINE_LIMITS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/loadfile_machdep.h b/lib/libc/include/x86-openbsd-none/i386/loadfile_machdep.h new file mode 100644 index 000000000000..6a9232df7079 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/loadfile_machdep.h @@ -0,0 +1,55 @@ +/* $OpenBSD: loadfile_machdep.h,v 1.8 2019/04/10 04:17:35 deraadt Exp $ */ +/* $NetBSD: loadfile_machdep.h,v 1.1 1999/04/29 03:17:12 tsubai Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define BOOT_ELF +#define BOOT_ELF32 +#define BOOT_ELF64 + +/* Keep a default ELFSIZE */ +#define ELFSIZE 32 + +#define LOAD_KERNEL LOAD_ALL +#define COUNT_KERNEL COUNT_ALL + +#define LOADADDR(a) ((((u_long)(a)) + offset)&0xfffffff) +#define ALIGNENTRY(a) ((u_long)(a)) +#define READ(f, b, c) read((f), (void *)LOADADDR(b), (size_t)(c)) +#define BCOPY(s, d, c) memcpy((void *)LOADADDR(d), (void *)(s), (c)) +#define BZERO(d, c) memset((void *)LOADADDR(d), 0, (c)) +#define WARN(a) (void)(printf a, \ + printf((errno ? ": %s\n" : "\n"), \ + strerror(errno))) +#define PROGRESS(a) (void) printf a +#define ALLOC(a) alloc(a) +#define FREE(a, b) free(a, b) + +void run_loadfile(uint64_t *, int); \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/mpbiosreg.h b/lib/libc/include/x86-openbsd-none/i386/mpbiosreg.h new file mode 100644 index 000000000000..37b3615c41e4 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/mpbiosreg.h @@ -0,0 +1,155 @@ +/* $OpenBSD: mpbiosreg.h,v 1.6 2023/04/10 04:21:20 jsg Exp $ */ +/* $NetBSD: mpbiosreg.h,v 1.1.2.3 2000/02/29 13:17:51 sommerfeld Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_MPBIOSREG_H_ +#define _MACHINE_MPBIOSREG_H_ + +#define BIOS_BASE (0xf0000) +#define BIOS_SIZE (0x10000) +#define BIOS_COUNT (BIOS_SIZE) + +/* + * Multiprocessor config table entry types. + */ + +#define MPS_MCT_CPU 0 +#define MPS_MCT_BUS 1 +#define MPS_MCT_IOAPIC 2 +#define MPS_MCT_IOINT 3 +#define MPS_MCT_LINT 4 + +#define MPS_MCT_NTYPES 5 + +/* + * Interrupt types + */ + +#define MPS_INTTYPE_INT 0 +#define MPS_INTTYPE_NMI 1 +#define MPS_INTTYPE_SMI 2 +#define MPS_INTTYPE_ExtINT 3 + +#define MPS_INTPO_DEF 0 +#define MPS_INTPO_ACTHI 1 +#define MPS_INTPO_ACTLO 3 +#define MPS_INTPO_SHIFT 0 +#define MPS_INTPO_MASK 3 + +#define MPS_INTTR_DEF 0 +#define MPS_INTTR_EDGE 1 +#define MPS_INTTR_LEVEL 3 +#define MPS_INTTR_SHIFT 2 +#define MPS_INTTR_MASK 3 + +#define MPS_INT(p,t) \ + ((((p) & MPS_INTPO_MASK) << MPS_INTPO_SHIFT) | \ + (((t) & MPS_INTTR_MASK) << MPS_INTTR_SHIFT)) + +/* MP Floating Pointer Structure */ +struct mpbios_fps { + u_int32_t signature; +/* string defined by the Intel MP Spec as identifying the MP table */ +#define MP_FP_SIG 0x5f504d5f /* _MP_ */ + + u_int32_t pap; + u_int8_t length; + u_int8_t spec_rev; + u_int8_t checksum; + u_int8_t mpfb1; /* system configuration */ + u_int8_t mpfb2; /* flags */ +#define MPFPS_FLAG_IMCR 0x80 /* IMCR present */ + u_int8_t mpfb3; /* unused */ + u_int8_t mpfb4; /* unused */ + u_int8_t mpfb5; /* unused */ +}; + +/* MP Configuration Table Header */ +struct mpbios_cth { + u_int32_t signature; +#define MP_CT_SIG 0x504d4350 /* PCMP */ + + u_int16_t base_len; + u_int8_t spec_rev; + u_int8_t checksum; + u_int8_t oem_id[8]; + u_int8_t product_id[12]; + u_int32_t oem_table_pointer; + u_int16_t oem_table_size; + u_int16_t entry_count; + u_int32_t apic_address; + u_int16_t ext_len; + u_int8_t ext_cksum; + u_int8_t reserved; +}; + +struct mpbios_proc { + u_int8_t type; + u_int8_t apic_id; + u_int8_t apic_version; + u_int8_t cpu_flags; +#define PROCENTRY_FLAG_EN 0x01 +#define PROCENTRY_FLAG_BP 0x02 + u_long cpu_signature; + u_long feature_flags; + u_long reserved1; + u_long reserved2; +}; + +struct mpbios_bus { + u_int8_t type; + u_int8_t bus_id; + char bus_type[6]; +}; + +struct mpbios_ioapic { + u_int8_t type; + u_int8_t apic_id; + u_int8_t apic_version; + u_int8_t apic_flags; +#define IOAPICENTRY_FLAG_EN 0x01 + void *apic_address; +}; + +struct mpbios_int { + u_int8_t type; + u_int8_t int_type; + u_int16_t int_flags; + u_int8_t src_bus_id; + u_int8_t src_bus_irq; + u_int8_t dst_apic_id; +#define MPS_ALL_APICS 0xff + u_int8_t dst_apic_int; +}; + +#endif /* !_MACHINE_MPBIOSREG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/mpbiosvar.h b/lib/libc/include/x86-openbsd-none/i386/mpbiosvar.h new file mode 100644 index 000000000000..6c0bc7a5253a --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/mpbiosvar.h @@ -0,0 +1,86 @@ +/* $OpenBSD: mpbiosvar.h,v 1.13 2024/10/22 21:50:02 jsg Exp $ */ +/* $NetBSD: mpbiosvar.h,v 1.1.2.3 2000/02/29 13:17:20 sommerfeld Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef _MACHINE_MPBIOSVAR_H_ +#define _MACHINE_MPBIOSVAR_H_ + +#define MP_TRAMPOLINE (16 * PAGE_SIZE) +#define MP_TRAMP_DATA (17 * PAGE_SIZE) + +#if !defined(_LOCORE) + +#include + +struct mp_bus { + char *mb_name; /* XXX bus name */ + int mb_idx; /* XXX bus index */ + void (*mb_intr_print) (int); + void (*mb_intr_cfg)(const struct mpbios_int *, u_int32_t *); + struct mp_intr_map *mb_intrs; + u_int32_t mb_data; /* random bus-specific datum. */ +}; + +struct mp_intr_map { + struct mp_intr_map *next; + struct mp_bus *bus; + int bus_pin; + struct ioapic_softc *ioapic; + int ioapic_pin; + int ioapic_ih; /* int handle, for apic_intr_est */ + int type; /* from mp spec intr record */ + int flags; /* from mp spec intr record */ + u_int32_t redir; + int cpu_id; +}; + +#if defined(_KERNEL) +extern int mp_verbose; +extern struct mp_bus *mp_busses; +extern int mp_nbusses; +extern struct mp_intr_map *mp_intrs; +extern int mp_nintrs; +extern struct mp_bus *mp_isa_bus; +extern struct mp_bus *mp_eisa_bus; + +void mpbios_scan(struct device *); +int mpbios_probe(struct device *); +int mpbios_invent(int, int, int); + +void mpbios_intr_fixup(void); +#endif + +#endif + +#endif /* !_MACHINE_MPBIOSVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/mplock.h b/lib/libc/include/x86-openbsd-none/i386/mplock.h new file mode 100644 index 000000000000..0630808c58de --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/mplock.h @@ -0,0 +1,10 @@ +/* $OpenBSD: mplock.h,v 1.4 2017/10/17 14:25:35 visa Exp $ */ + +/* public domain */ + +#ifndef _MACHINE_MPLOCK_H_ +#define _MACHINE_MPLOCK_H_ + +#define __USE_MI_MPLOCK + +#endif /* !_MACHINE_MPLOCK_H */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/mutex.h b/lib/libc/include/x86-openbsd-none/i386/mutex.h new file mode 100644 index 000000000000..3aa5554e532e --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/mutex.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mutex.h,v 1.13 2018/01/25 15:06:29 mpi Exp $ */ + +#define __USE_MI_MUTEX \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/npx.h b/lib/libc/include/x86-openbsd-none/i386/npx.h new file mode 100644 index 000000000000..004a44af61c7 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/npx.h @@ -0,0 +1,158 @@ +/* $OpenBSD: npx.h,v 1.20 2021/03/11 11:16:57 jsg Exp $ */ +/* $NetBSD: npx.h,v 1.11 1994/10/27 04:16:11 cgd Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)npx.h 5.3 (Berkeley) 1/18/91 + */ + +/* + * 287/387 NPX Coprocessor Data Structures and Constants + * W. Jolitz 1/90 + */ + +#ifndef _MACHINE_NPX_H_ +#define _MACHINE_NPX_H_ + +/* Environment information of floating point unit */ +struct env87 { + long en_cw; /* control word (16bits) */ + long en_sw; /* status word (16bits) */ + long en_tw; /* tag word (16bits) */ + long en_fip; /* floating point instruction pointer */ + u_short en_fcs; /* floating code segment selector */ + u_short en_opcode; /* opcode last executed (11 bits ) */ + long en_foo; /* floating operand offset */ + long en_fos; /* floating operand segment selector */ +}; + +#define EN_SW_IE 0x0001 /* invalid operation */ +#define EN_SW_DE 0x0002 /* denormal */ +#define EN_SW_ZE 0x0004 /* divide by zero */ +#define EN_SW_OE 0x0008 /* overflow */ +#define EN_SW_UE 0x0010 /* underflow */ +#define EN_SW_PE 0x0020 /* loss of precision */ + +/* Contents of each floating point accumulator */ +struct fpacc87 { +#ifdef dontdef /* too unportable */ + u_long fp_mantlo; /* mantissa low (31:0) */ + u_long fp_manthi; /* mantissa high (63:32) */ + int fp_exp:15; /* exponent */ + int fp_sgn:1; /* mantissa sign */ +#else + u_char fp_bytes[10]; +#endif +}; + +/* Floating point and emulator context */ +struct save87 { + struct env87 sv_env; /* floating point control/status */ + struct fpacc87 sv_ac[8]; /* accumulator contents, 0-7 */ + u_long sv_ex_sw; /* status word for last exception */ + u_long sv_ex_tw; /* tag word for last exception */ +}; + +/* Environment of FPU/MMX/SSE/SSE2. */ +struct envxmm { +/*0*/ uint16_t en_cw; /* FPU Control Word */ + uint16_t en_sw; /* FPU Status Word */ + uint8_t en_tw; /* FPU Tag Word (abridged) */ + uint8_t en_rsvd0; + uint16_t en_opcode; /* FPU Opcode */ + uint32_t en_fip; /* FPU Instruction Pointer */ + uint16_t en_fcs; /* FPU IP selector */ + uint16_t en_rsvd1; +/*16*/ uint32_t en_foo; /* FPU Data pointer */ + uint16_t en_fos; /* FPU Data pointer selector */ + uint16_t en_rsvd2; + uint32_t en_mxcsr; /* MXCSR Register State */ + uint32_t en_mxcsr_mask; /* Mask for valid MXCSR bits (may be 0) */ +}; + +/* FPU registers in the extended save format. */ +struct fpaccxmm { + uint8_t fp_bytes[10]; + uint8_t fp_rsvd[6]; +}; + +/* SSE/SSE2 registers. */ +struct xmmreg { + uint8_t sse_bytes[16]; +}; + +/* FPU/MMX/SSE/SSE2 context */ +struct savexmm { + struct envxmm sv_env; /* control/status context */ + struct fpaccxmm sv_ac[8]; /* ST/MM regs */ + struct xmmreg sv_xmmregs[8]; /* XMM regs */ + uint8_t sv_rsvd[16 * 14]; + /* 512-bytes --- end of hardware portion of save area */ + uint32_t sv_ex_sw; /* saved SW from last exception */ + uint32_t sv_ex_tw; /* saved TW from last exception */ +}; + +union savefpu { + struct save87 sv_87; + struct savexmm sv_xmm; +}; + +#define __INITIAL_NPXCW__ 0x037f + +/* + * The default MXCSR value at reset is 0x1f80, IA-32 Instruction + * Set Reference, pg. 3-369. + */ +#define __INITIAL_MXCSR__ 0x1f80 +#define __INITIAL_MXCSR_MASK__ 0xffbf + +/* + * The standard control word from finit is 0x37F, giving: + * round to nearest + * 64-bit precision + * all exceptions masked. + */ + +void process_xmm_to_s87(const struct savexmm *, struct save87 *); +void process_s87_to_xmm(const struct save87 *, struct savexmm *); + +struct cpu_info; +struct trapframe; + +extern uint32_t fpu_mxcsr_mask; + +void npxinit(struct cpu_info *); +void npxtrap(struct trapframe *); +void fpu_kernel_enter(void); +void fpu_kernel_exit(void); + +#endif /* !_MACHINE_NPX_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/param.h b/lib/libc/include/x86-openbsd-none/i386/param.h new file mode 100644 index 000000000000..8fa438464652 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/param.h @@ -0,0 +1,80 @@ +/* $OpenBSD: param.h,v 1.53 2023/12/14 13:26:49 claudio Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ + +#ifdef _KERNEL +#ifdef _LOCORE +#include +#else +#include +#endif +#endif + +#define _MACHINE i386 +#define MACHINE "i386" +#define _MACHINE_ARCH i386 +#define MACHINE_ARCH "i386" +#define MID_MACHINE MID_I386 + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define PAGE_MASK (PAGE_SIZE - 1) + +#define KERNBASE 0xd0000000 + +#ifdef _KERNEL + +#define KERNTEXTOFF (KERNBASE+0x200000) /* start of kernel text */ + +#define NBPG PAGE_SIZE /* bytes/page */ +#define PGSHIFT PAGE_SHIFT /* LOG2(PAGE_SIZE) */ +#define PGOFSET PAGE_MASK /* byte offset into page */ + +#define UPAGES 3 /* pages of u-area */ +#define USPACE (UPAGES * PAGE_SIZE) /* total size of u-area */ +#define USPACE_ALIGN 0 /* u-area alignment 0-none */ + +#define NMBCLUSTERS (32 * 1024) /* max cluster allocation */ + +#ifndef MSGBUFSIZE +#define MSGBUFSIZE (8 * PAGE_SIZE) /* default message buffer size */ +#endif + +#define __HAVE_ACPI + +#endif /* _KERNEL */ + +#endif /* _MACHINE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/pcb.h b/lib/libc/include/x86-openbsd-none/i386/pcb.h new file mode 100644 index 000000000000..ae727d2d47f0 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/pcb.h @@ -0,0 +1,78 @@ +/* $OpenBSD: pcb.h,v 1.25 2022/02/21 14:26:19 jsg Exp $ */ +/* $NetBSD: pcb.h,v 1.21 1996/01/08 13:51:42 mycroft Exp $ */ + +/*- + * Copyright (c) 1995 Charles M. Hannum. All rights reserved. + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pcb.h 5.10 (Berkeley) 5/12/91 + */ + +/* + * Intel 386 process control block + */ + +#ifndef _MACHINE_PCB_H_ +#define _MACHINE_PCB_H_ + +#include + +#include +#include +#include + +/* + * Please note that pcb_savefpu must be aligned to 16 bytes. + */ +struct pcb { + union savefpu pcb_savefpu; /* floating point state for FPU */ + int pcb_cr3; + int pcb_esp; + int pcb_ebp; + int pcb_kstack; /* kernel stack address */ + int pcb_cr0; /* saved image of CR0 */ + caddr_t pcb_onfault; /* copyin/out fault recovery */ + struct segment_descriptor pcb_threadsegs[2]; + /* per-thread descriptors */ + int vm86_eflags; /* virtual eflags for vm86 mode */ + int vm86_flagmask; /* flag mask for vm86 mode */ + void *vm86_userp; /* XXX performance hack */ + struct pmap *pcb_pmap; /* back pointer to our pmap */ + struct cpu_info *pcb_fpcpu; /* cpu holding our fpu state */ + int pcb_flags; +#define PCB_SAVECTX 0x00000001 +}; + +/* the indexes of the %fs/%gs segments in pcb_threadsegs */ +#define TSEG_FS 0 +#define TSEG_GS 1 + +#endif /* _MACHINE_PCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/pctr.h b/lib/libc/include/x86-openbsd-none/i386/pctr.h new file mode 100644 index 000000000000..91c0e3f0b0cf --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/pctr.h @@ -0,0 +1,93 @@ +/* $OpenBSD: pctr.h,v 1.17 2014/03/29 18:09:29 guenther Exp $ */ + +/* + * Pentium performance counter driver for OpenBSD. + * Copyright 1996 David Mazieres . + * + * Modification and redistribution in source and binary forms is + * permitted provided that due credit is given to the author and the + * OpenBSD project by leaving this copyright notice intact. + */ + +#ifndef _MACHINE_PCTR_H_ +#define _MACHINE_PCTR_H_ + +#include + +typedef u_int64_t pctrval; + +#define PCTR_NUM 4 + +struct pctrst { + u_int pctr_fn[PCTR_NUM]; /* Current settings of counters */ + pctrval pctr_tsc; /* Free-running 64-bit cycle counter */ + pctrval pctr_hwc[PCTR_NUM]; /* Values of the hardware counters */ +}; + +/* Bit values in fn fields and PIOCS ioctl's */ +#define P5CTR_K 0x40 /* Monitor kernel-level events */ +#define P5CTR_U 0x80 /* Monitor user-level events */ +#define P5CTR_C 0x100 /* count cycles rather than events */ + +#define PCTR_U 0x010000 /* Monitor user-level events */ +#define PCTR_K 0x020000 /* Monitor kernel-level events */ +#define PCTR_E 0x040000 /* Edge detect */ +#define PCTR_EN 0x400000 /* Enable counters (counter 0 only) */ +#define PCTR_I 0x800000 /* Invert counter mask */ + +/* Unit Mask bits */ +#define PCTR_UM_M 0x0800 /* Modified cache lines */ +#define PCTR_UM_E 0x0400 /* Exclusive cache lines */ +#define PCTR_UM_S 0x0200 /* Shared cache lines */ +#define PCTR_UM_I 0x0100 /* Invalid cache lines */ +#define PCTR_UM_MESI (PCTR_UM_M|PCTR_UM_E|PCTR_UM_S|PCTR_UM_I) +#define PCTR_UM_A 0x2000 /* Any initiator */ + +#define PCTR_UM_SHIFT 8 /* Left shift for unit mask */ +#define PCTR_CM_SHIFT 24 /* Left shift for counter mask */ + +/* ioctl to set which counter a device tracks */ +#define PCIOCRD _IOR('c', 1, struct pctrst) /* Read counter value */ +#define PCIOCS0 _IOW('c', 8, unsigned int) /* Set counter 0 function */ +#define PCIOCS1 _IOW('c', 9, unsigned int) /* Set counter 1 function */ +#define PCIOCS2 _IOW('c', 10, unsigned int) /* Set counter 0 function */ +#define PCIOCS3 _IOW('c', 11, unsigned int) /* Set counter 1 function */ + +#define _PATH_PCTR "/dev/pctr" + +#define rdtsc() \ +({ \ + pctrval v; \ + __asm volatile ("rdtsc" : "=A" (v)); \ + v; \ +}) + +/* Read the performance counters (Pentium Pro only) */ +#define rdpmc(ctr) \ +({ \ + pctrval v; \ + __asm volatile ("rdpmc\n" \ + "\tandl $0xff, %%edx" \ + : "=A" (v) : "c" (ctr)); \ + v; \ +}) + +#ifdef _KERNEL + +#define rdmsr(msr) \ +({ \ + pctrval v; \ + __asm volatile ("rdmsr" : "=A" (v) : "c" (msr)); \ + v; \ +}) + +#define wrmsr(msr, v) \ + __asm volatile ("wrmsr" :: "A" ((u_int64_t) (v)), "c" (msr)); + +void pctrattach(int); +int pctropen(dev_t, int, int, struct proc *); +int pctrclose(dev_t, int, int, struct proc *); +int pctrioctl(dev_t, u_long, caddr_t, int, struct proc *); + +#endif /* _KERNEL */ +#endif /* ! _MACHINE_PCTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/pic.h b/lib/libc/include/x86-openbsd-none/i386/pic.h new file mode 100644 index 000000000000..26b88fde7633 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/pic.h @@ -0,0 +1,42 @@ +/* $OpenBSD: pic.h,v 1.2 2014/12/16 21:40:05 tedu Exp $ */ +/* $NetBSD: pic.h,v 1.1 2003/02/26 21:26:11 fvdl Exp $ */ + +#ifndef _X86_PIC_H +#define _X86_PIC_H + +#include +#include + +struct cpu_info; + +/* + * Structure common to all PIC softcs + */ +struct pic { + struct device pic_dev; + int pic_type; +#ifdef MULTIPROCESSOR + struct mutex pic_mutex; +#endif + void (*pic_hwmask)(struct pic *, int); + void (*pic_hwunmask)(struct pic *, int); + void (*pic_addroute)(struct pic *, struct cpu_info *, int, int, int); + void (*pic_delroute)(struct pic *, struct cpu_info *, int, int, int); + struct intrstub *pic_level_stubs; + struct intrstub *pic_edge_stubs; +}; + +#define pic_name pic_dev.dv_xname + +/* + * PIC types. + */ +#define PIC_I8259 0 +#define PIC_IOAPIC 1 +#define PIC_LAPIC 2 +#define PIC_SOFT 3 + +extern struct pic i8259_pic; +extern struct pic local_pic; +extern struct pic softintr_pic; +#endif \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/pio.h b/lib/libc/include/x86-openbsd-none/i386/pio.h new file mode 100644 index 000000000000..6ca1c2844448 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/pio.h @@ -0,0 +1,201 @@ +/* $OpenBSD: pio.h,v 1.12 2015/04/25 21:31:24 guenther Exp $ */ +/* $NetBSD: pio.h,v 1.13 1996/03/08 20:15:23 cgd Exp $ */ + +/* + * Copyright (c) 1993, 1995 Charles M. Hannum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Charles M. Hannum. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_PIO_H_ +#define _MACHINE_PIO_H_ + +/* + * Functions to provide access to i386 programmed I/O instructions. + * + * The in[bwl]() and out[bwl]() functions are split into two varieties: one to + * use a small, constant, 8-bit port number, and another to use a large or + * variable port number. The former can be compiled as a smaller instruction. + */ + + +#ifdef __OPTIMIZE__ + +#define __use_immediate_port(port) \ + (__builtin_constant_p((port)) && (port) < 0x100) + +#else + +#define __use_immediate_port(port) 0 + +#endif + + +#define inb(port) \ + (__use_immediate_port(port) ? __inbc(port) : __inb(port)) + +static __inline u_int8_t +__inbc(int port) +{ + u_int8_t data; + __asm volatile("inb %w1,%0" : "=a" (data) : "id" (port)); + return data; +} + +static __inline u_int8_t +__inb(int port) +{ + u_int8_t data; + __asm volatile("inb %w1,%0" : "=a" (data) : "d" (port)); + return data; +} + +static __inline void +insb(int port, void *addr, int cnt) +{ + __asm volatile("repne\n\tinsb" + : "+D" (addr), "+c" (cnt) : "d" (port) : "memory", "cc"); +} + +#define inw(port) \ + (__use_immediate_port(port) ? __inwc(port) : __inw(port)) + +static __inline u_int16_t +__inwc(int port) +{ + u_int16_t data; + __asm volatile("inw %w1,%0" : "=a" (data) : "id" (port)); + return data; +} + +static __inline u_int16_t +__inw(int port) +{ + u_int16_t data; + __asm volatile("inw %w1,%0" : "=a" (data) : "d" (port)); + return data; +} + +static __inline void +insw(int port, void *addr, int cnt) +{ + __asm volatile("repne\n\tinsw" + : "+D" (addr), "+c" (cnt) : "d" (port) : "memory", "cc"); +} + +#define inl(port) \ + (__use_immediate_port(port) ? __inlc(port) : __inl(port)) + +static __inline u_int32_t +__inlc(int port) +{ + u_int32_t data; + __asm volatile("inl %w1,%0" : "=a" (data) : "id" (port)); + return data; +} + +static __inline u_int32_t +__inl(int port) +{ + u_int32_t data; + __asm volatile("inl %w1,%0" : "=a" (data) : "d" (port)); + return data; +} + +static __inline void +insl(int port, void *addr, int cnt) +{ + __asm volatile("repne\n\tinsl" + : "+D" (addr), "+c" (cnt) : "d" (port) : "memory", "cc"); +} + +#define outb(port, data) \ + (__use_immediate_port(port) ? __outbc(port, data) : __outb(port, data)) + +static __inline void +__outbc(int port, u_int8_t data) +{ + __asm volatile("outb %0,%w1" : : "a" (data), "id" (port)); +} + +static __inline void +__outb(int port, u_int8_t data) +{ + __asm volatile("outb %0,%w1" : : "a" (data), "d" (port)); +} + +static __inline void +outsb(int port, const void *addr, int cnt) +{ + __asm volatile("repne\n\toutsb" + : "+S" (addr), "+c" (cnt) : "d" (port) : "cc"); +} + +#define outw(port, data) \ + (__use_immediate_port(port) ? __outwc(port, data) : __outw(port, data)) + +static __inline void +__outwc(int port, u_int16_t data) +{ + __asm volatile("outw %0,%w1" : : "a" (data), "id" (port)); +} + +static __inline void +__outw(int port, u_int16_t data) +{ + __asm volatile("outw %0,%w1" : : "a" (data), "d" (port)); +} + +static __inline void +outsw(int port, const void *addr, int cnt) +{ + __asm volatile("repne\n\toutsw" + : "+S" (addr), "+c" (cnt) : "d" (port) : "cc"); +} + +#define outl(port, data) \ + (__use_immediate_port(port) ? __outlc(port, data) : __outl(port, data)) + +static __inline void +__outlc(int port, u_int32_t data) +{ + __asm volatile("outl %0,%w1" : : "a" (data), "id" (port)); +} + +static __inline void +__outl(int port, u_int32_t data) +{ + __asm volatile("outl %0,%w1" : : "a" (data), "d" (port)); +} + +static __inline void +outsl(int port, const void *addr, int cnt) +{ + __asm volatile("repne\n\toutsl" + : "+S" (addr), "+c" (cnt) : "d" (port) : "cc"); +} + +#endif /* _MACHINE_PIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/pmap.h b/lib/libc/include/x86-openbsd-none/i386/pmap.h new file mode 100644 index 000000000000..0c46db395ee2 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/pmap.h @@ -0,0 +1,480 @@ +/* $OpenBSD: pmap.h,v 1.98 2025/07/16 07:15:42 jsg Exp $ */ +/* $NetBSD: pmap.h,v 1.44 2000/04/24 17:18:18 thorpej Exp $ */ + +/* + * Copyright (c) 1997 Charles D. Cranor and Washington University. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * pmap.h: see pmap.c for the history of this pmap module. + */ + +#ifndef _MACHINE_PMAP_H_ +#define _MACHINE_PMAP_H_ + +#ifdef _KERNEL +#include +#include +#endif +#include +#include +#include + +#define PDSLOT_PTE ((KERNBASE/NBPD)-2) /* 830: for recursive PDP map */ +#define PDSLOT_KERN (KERNBASE/NBPD) /* 832: start of kernel space */ +#define PDSLOT_APTE ((unsigned)1022) /* 1022: alternative recursive slot */ + +/* + * The following define determines how many PTPs should be set up for the + * kernel by locore.s at boot time. This should be large enough to + * get the VM system running. Once the VM system is running, the + * pmap module can add more PTPs to the kernel area on demand. + */ + +#ifndef NKPTP +#define NKPTP 8 /* 16/32MB to start */ +#endif +#define NKPTP_MIN 4 /* smallest value we allow */ + +/* + * PG_AVAIL usage: we make use of the ignored bits of the PTE + */ + +#define PG_W PG_AVAIL1 /* "wired" mapping */ +#define PG_PVLIST PG_AVAIL2 /* mapping has entry on pvlist */ +#define PG_X PG_AVAIL3 /* executable mapping */ + +#define PTP0_PA (PAGE_SIZE * 3) + +#ifdef _KERNEL +/* + * pmap data structures: see pmap.c for details of locking. + */ + +struct pmap; +typedef struct pmap *pmap_t; + +/* + * We maintain a list of all non-kernel pmaps. + */ + +LIST_HEAD(pmap_head, pmap); /* struct pmap_head: head of a pmap list */ + +/* + * The pmap structure + * + * Note that the pm_obj contains the reference count, + * page list, and number of PTPs within the pmap. + */ + +struct pmap { + uint64_t pm_pdidx[4]; /* PDIEs for PAE mode */ + uint64_t pm_pdidx_intel[4]; /* PDIEs for PAE mode U-K */ + + struct mutex pm_mtx; + struct mutex pm_apte_mtx; + + /* + * pm_pdir : VA of PD when executing in privileged mode + * (lock by object lock) + * pm_pdirpa : PA of PD when executing in privileged mode, + * (read-only after create) + * pm_pdir_intel : VA of PD when executing on Intel CPU in + * usermode (no kernel mappings) + * pm_pdirpa_intel : PA of PD when executing on Intel CPU in + * usermode (no kernel mappings) + */ + paddr_t pm_pdirpa, pm_pdirpa_intel; + vaddr_t pm_pdir, pm_pdir_intel; + int pm_pdirsize; /* PD size (4k vs 16k on PAE) */ + struct uvm_object pm_obj; /* object (lck by object lock) */ + LIST_ENTRY(pmap) pm_list; /* list (lck by pm_list lock) */ + struct vm_page *pm_ptphint; /* pointer to a PTP in our pmap */ + struct pmap_statistics pm_stats; /* pmap stats (lck by object lock) */ + + vaddr_t pm_hiexec; /* highest executable mapping */ + int pm_flags; /* see below */ + + struct segment_descriptor pm_codeseg; /* cs descriptor for process */ +}; + +/* + * For each managed physical page we maintain a list of s + * which it is mapped at. The list is headed by a pv_head structure. + * there is one pv_head per managed phys page (allocated at boot time). + * The pv_head structure points to a list of pv_entry structures (each + * describes one mapping). + */ + +struct pv_entry { /* locked by its list's pvh_lock */ + struct pv_entry *pv_next; /* next entry */ + struct pmap *pv_pmap; /* the pmap */ + vaddr_t pv_va; /* the virtual address */ + struct vm_page *pv_ptp; /* the vm_page of the PTP */ +}; +/* + * MD flags to pmap_enter: + */ + +/* to get just the pa from params to pmap_enter */ +#define PMAP_PA_MASK ~((paddr_t)PAGE_MASK) +#define PMAP_NOCACHE 0x1 /* map uncached */ +#define PMAP_WC 0x2 /* map write combining. */ + +/* + * We keep mod/ref flags in struct vm_page->pg_flags. + */ +#define PG_PMAP_MOD PG_PMAP0 +#define PG_PMAP_REF PG_PMAP1 +#define PG_PMAP_WC PG_PMAP2 + +/* + * pv_entrys are dynamically allocated in chunks from a single page. + * we keep track of how many pv_entrys are in use for each page and + * we can free pv_entry pages if needed. There is one lock for the + * entire allocation system. + */ + +struct pv_page_info { + TAILQ_ENTRY(pv_page) pvpi_list; + struct pv_entry *pvpi_pvfree; + int pvpi_nfree; +}; + +/* + * number of pv_entries in a pv_page + */ + +#define PVE_PER_PVPAGE ((PAGE_SIZE - sizeof(struct pv_page_info)) / \ + sizeof(struct pv_entry)) + +/* + * a pv_page: where pv_entrys are allocated from + */ + +struct pv_page { + struct pv_page_info pvinfo; + struct pv_entry pvents[PVE_PER_PVPAGE]; +}; + +/* + * pv_entrys are dynamically allocated in chunks from a single page. + * we keep track of how many pv_entrys are in use for each page and + * we can free pv_entry pages if needed. There is one lock for the + * entire allocation system. + */ + +extern char PTD[]; +extern struct pmap kernel_pmap_store; /* kernel pmap */ +extern int nkptp_max; + +#define PMAP_REMOVE_ALL 0 +#define PMAP_REMOVE_SKIPWIRED 1 + +extern struct pool pmap_pv_pool; + +/* + * Macros + */ + +#define pmap_kernel() (&kernel_pmap_store) +#define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count) +#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) +#define pmap_update(pm) /* nada */ + +#define pmap_clear_modify(pg) pmap_clear_attrs(pg, PG_M) +#define pmap_clear_reference(pg) pmap_clear_attrs(pg, PG_U) +#define pmap_is_modified(pg) pmap_test_attrs(pg, PG_M) +#define pmap_is_referenced(pg) pmap_test_attrs(pg, PG_U) +#define pmap_valid_entry(E) ((E) & PG_V) /* is PDE or PTE valid? */ + +#define pmap_proc_iflush(p,va,len) /* nothing */ +#define pmap_init_percpu() do { /* nothing */ } while (0) +#define pmap_unuse_final(p) /* nothing */ +#define pmap_remove_holes(vm) do { /* nothing */ } while (0) + +/* + * Prototypes + */ + +vaddr_t pmap_tmpmap_pa_86(paddr_t); +vaddr_t pmap_tmpmap_pa(paddr_t); +void pmap_tmpunmap_pa_86(void); +void pmap_tmpunmap_pa(void); + +void pmap_bootstrap(vaddr_t); +void pmap_bootstrap_pae(void); +void pmap_virtual_space(vaddr_t *, vaddr_t *); +void pmap_init(void); +struct pmap *pmap_create(void); +void pmap_destroy(struct pmap *); +void pmap_reference(struct pmap *); +void pmap_remove(struct pmap *, vaddr_t, vaddr_t); +void pmap_activate(struct proc *); +void pmap_deactivate(struct proc *); +void pmap_kenter_pa(vaddr_t, paddr_t, vm_prot_t); +void pmap_kremove(vaddr_t, vsize_t); +void pmap_zero_page(struct vm_page *); +void pmap_copy_page(struct vm_page *, struct vm_page *); +void pmap_enter_pv(struct vm_page *, struct pv_entry *, + struct pmap *, vaddr_t, struct vm_page *); +int pmap_clear_attrs(struct vm_page *, int); +static void pmap_page_protect(struct vm_page *, vm_prot_t); +void pmap_page_remove(struct vm_page *); +static void pmap_protect(struct pmap *, vaddr_t, + vaddr_t, vm_prot_t); +void pmap_remove(struct pmap *, vaddr_t, vaddr_t); +int pmap_test_attrs(struct vm_page *, int); +void pmap_write_protect(struct pmap *, vaddr_t, + vaddr_t, vm_prot_t); +int pmap_exec_fixup(struct vm_map *, struct trapframe *, + vaddr_t, struct pcb *); +void pmap_exec_account(struct pmap *, vaddr_t, u_int32_t, + u_int32_t); +struct pv_entry *pmap_remove_pv(struct vm_page *, struct pmap *, vaddr_t); +void pmap_apte_flush(void); +void pmap_switch(struct proc *, struct proc *); +vaddr_t reserve_dumppages(vaddr_t); /* XXX: not a pmap fn */ +paddr_t vtophys(vaddr_t va); +paddr_t vtophys_pae(vaddr_t va); + +extern u_int32_t (*pmap_pte_set_p)(vaddr_t, paddr_t, u_int32_t); +extern u_int32_t (*pmap_pte_setbits_p)(vaddr_t, u_int32_t, u_int32_t); +extern u_int32_t (*pmap_pte_bits_p)(vaddr_t); +extern paddr_t (*pmap_pte_paddr_p)(vaddr_t); +extern int (*pmap_clear_attrs_p)(struct vm_page *, int); +extern int (*pmap_enter_p)(pmap_t, vaddr_t, paddr_t, vm_prot_t, int); +extern void (*pmap_enter_special_p)(vaddr_t, paddr_t, vm_prot_t, u_int32_t); +extern int (*pmap_extract_p)(pmap_t, vaddr_t, paddr_t *); +extern vaddr_t (*pmap_growkernel_p)(vaddr_t); +extern void (*pmap_page_remove_p)(struct vm_page *); +extern void (*pmap_do_remove_p)(struct pmap *, vaddr_t, vaddr_t, int); +extern int (*pmap_test_attrs_p)(struct vm_page *, int); +extern void (*pmap_unwire_p)(struct pmap *, vaddr_t); +extern void (*pmap_write_protect_p)(struct pmap*, vaddr_t, vaddr_t, vm_prot_t); +extern void (*pmap_pinit_pd_p)(pmap_t); +extern void (*pmap_zero_phys_p)(paddr_t); +extern void (*pmap_copy_page_p)(struct vm_page *, struct vm_page *); + +u_int32_t pmap_pte_set_pae(vaddr_t, paddr_t, u_int32_t); +u_int32_t pmap_pte_setbits_pae(vaddr_t, u_int32_t, u_int32_t); +u_int32_t pmap_pte_bits_pae(vaddr_t); +paddr_t pmap_pte_paddr_pae(vaddr_t); +int pmap_clear_attrs_pae(struct vm_page *, int); +int pmap_enter_pae(pmap_t, vaddr_t, paddr_t, vm_prot_t, int); +void pmap_enter_special_pae(vaddr_t, paddr_t, vm_prot_t, u_int32_t); +int pmap_extract_pae(pmap_t, vaddr_t, paddr_t *); +vaddr_t pmap_growkernel_pae(vaddr_t); +void pmap_page_remove_pae(struct vm_page *); +void pmap_do_remove_pae(struct pmap *, vaddr_t, vaddr_t, int); +int pmap_test_attrs_pae(struct vm_page *, int); +void pmap_unwire_pae(struct pmap *, vaddr_t); +void pmap_write_protect_pae(struct pmap *, vaddr_t, vaddr_t, vm_prot_t); +void pmap_pinit_pd_pae(pmap_t); +void pmap_zero_phys_pae(paddr_t); +void pmap_copy_page_pae(struct vm_page *, struct vm_page *); + +#define pmap_pte_set (*pmap_pte_set_p) +#define pmap_pte_setbits (*pmap_pte_setbits_p) +#define pmap_pte_bits (*pmap_pte_bits_p) +#define pmap_pte_paddr (*pmap_pte_paddr_p) +#define pmap_clear_attrs (*pmap_clear_attrs_p) +#define pmap_page_remove (*pmap_page_remove_p) +#define pmap_do_remove (*pmap_do_remove_p) +#define pmap_test_attrs (*pmap_test_attrs_p) +#define pmap_unwire (*pmap_unwire_p) +#define pmap_write_protect (*pmap_write_protect_p) +#define pmap_pinit_pd (*pmap_pinit_pd_p) +#define pmap_zero_phys (*pmap_zero_phys_p) +#define pmap_copy_page (*pmap_copy_page_p) + +u_int32_t pmap_pte_set_86(vaddr_t, paddr_t, u_int32_t); +u_int32_t pmap_pte_setbits_86(vaddr_t, u_int32_t, u_int32_t); +u_int32_t pmap_pte_bits_86(vaddr_t); +paddr_t pmap_pte_paddr_86(vaddr_t); +int pmap_clear_attrs_86(struct vm_page *, int); +int pmap_enter_86(pmap_t, vaddr_t, paddr_t, vm_prot_t, int); +void pmap_enter_special_86(vaddr_t, paddr_t, vm_prot_t, u_int32_t); +int pmap_extract_86(pmap_t, vaddr_t, paddr_t *); +vaddr_t pmap_growkernel_86(vaddr_t); +void pmap_page_remove_86(struct vm_page *); +void pmap_do_remove_86(struct pmap *, vaddr_t, vaddr_t, int); +int pmap_test_attrs_86(struct vm_page *, int); +void pmap_unwire_86(struct pmap *, vaddr_t); +void pmap_write_protect_86(struct pmap *, vaddr_t, vaddr_t, vm_prot_t); +void pmap_pinit_pd_86(pmap_t); +void pmap_zero_phys_86(paddr_t); +void pmap_copy_page_86(struct vm_page *, struct vm_page *); +void pmap_tlb_shootpage(struct pmap *, vaddr_t); +void pmap_tlb_shootrange(struct pmap *, vaddr_t, vaddr_t); +void pmap_tlb_shoottlb(void); +#ifdef MULTIPROCESSOR +void pmap_tlb_droppmap(struct pmap *); +void pmap_tlb_shootwait(void); +#else +#define pmap_tlb_shootwait() +#endif + +void pmap_prealloc_lowmem_ptp(void); +void pmap_prealloc_lowmem_ptp_pae(void); +vaddr_t pmap_tmpmap_pa(paddr_t); +void pmap_tmpunmap_pa(void); +vaddr_t pmap_tmpmap_pa_pae(paddr_t); +void pmap_tmpunmap_pa_pae(void); + + +/* + * functions for flushing the cache for vaddrs and pages. + * these functions are not part of the MI pmap interface and thus + * should not be used as such. + */ +void pmap_flush_cache(vaddr_t, vsize_t); +void pmap_flush_page(paddr_t); +void pmap_flush_page_pae(paddr_t); + +#define PMAP_CHECK_COPYIN 1 + +#define PMAP_GROWKERNEL /* turn on pmap_growkernel interface */ + +/* + * Inline functions + */ + +/* + * pmap_update_pg: flush one page from the TLB (or flush the whole thing + * if hardware doesn't support one-page flushing) + */ + +#define pmap_update_pg(va) invlpg((u_int)(va)) + +/* + * pmap_update_2pg: flush two pages from the TLB + */ + +#define pmap_update_2pg(va, vb) { invlpg((u_int)(va)); invlpg((u_int)(vb)); } + +/* + * pmap_page_protect: change the protection of all recorded mappings + * of a managed page + * + * => This function is a front end for pmap_page_remove/pmap_clear_attrs + * => We only have to worry about making the page more protected. + * Unprotecting a page is done on-demand at fault time. + */ + +static __inline void +pmap_page_protect(struct vm_page *pg, vm_prot_t prot) +{ + if ((prot & PROT_WRITE) == 0) { + if (prot & (PROT_READ | PROT_EXEC)) { + (void) pmap_clear_attrs(pg, PG_RW); + } else { + pmap_page_remove(pg); + } + } +} + +/* + * pmap_protect: change the protection of pages in a pmap + * + * => This function is a front end for pmap_remove/pmap_write_protect. + * => We only have to worry about making the page more protected. + * Unprotecting a page is done on-demand at fault time. + */ + +static __inline void +pmap_protect(struct pmap *pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot) +{ + if ((prot & PROT_WRITE) == 0) { + if (prot & (PROT_READ | PROT_EXEC)) { + pmap_write_protect(pmap, sva, eva, prot); + } else { + pmap_remove(pmap, sva, eva); + } + } +} + +/* + * pmap_growkernel, pmap_enter, and pmap_extract get picked up in various + * modules from both uvm_pmap.h and pmap.h. Since uvm_pmap.h defines these + * as functions, inline them here to suppress linker warnings. + */ +static __inline vaddr_t +pmap_growkernel(vaddr_t maxkvaddr) +{ + return (*pmap_growkernel_p)(maxkvaddr); +} + +static __inline int +pmap_enter(struct pmap *pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags) +{ + return (*pmap_enter_p)(pmap, va, pa, prot, flags); +} + +static __inline void +pmap_enter_special(vaddr_t va, paddr_t pa, vm_prot_t prot, u_int32_t flags) +{ + (*pmap_enter_special_p)(va, pa, prot, flags); +} + +static __inline int +pmap_extract(struct pmap *pmap, vaddr_t va, paddr_t *pa) +{ + return (*pmap_extract_p)(pmap, va, pa); +} + +/* + * p m a p i n l i n e h e l p e r f u n c t i o n s + */ + +/* + * pmap_is_active: is this pmap loaded into the specified processor's %cr3? + */ + +static __inline int +pmap_is_active(struct pmap *pmap, struct cpu_info *ci) +{ + return (pmap == pmap_kernel() || ci->ci_curpmap == pmap); +} + +static __inline int +pmap_is_curpmap(struct pmap *pmap) +{ + return (pmap_is_active(pmap, curcpu())); +} + +#endif /* _KERNEL */ + +struct pv_entry; +struct vm_page_md { + struct mutex pv_mtx; + struct pv_entry *pv_list; +}; + +#define VM_MDPAGE_INIT(pg) do { \ + mtx_init(&(pg)->mdpage.pv_mtx, IPL_VM); \ + (pg)->mdpage.pv_list = NULL; \ +} while (0) + +#endif /* _MACHINE_PMAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/proc.h b/lib/libc/include/x86-openbsd-none/i386/proc.h new file mode 100644 index 000000000000..aa4ac664f980 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/proc.h @@ -0,0 +1,45 @@ +/* $OpenBSD: proc.h,v 1.10 2018/03/31 13:45:03 bluhm Exp $ */ +/* $NetBSD: proc.h,v 1.10 1995/08/06 05:33:23 mycroft Exp $ */ + +/* + * Copyright (c) 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)proc.h 7.1 (Berkeley) 5/15/91 + */ + +/* + * Machine-dependent part of the proc structure for i386. + */ +struct mdproc { + struct trapframe *md_regs; /* registers on current frame */ + int md_flags; /* machine-dependent flags */ + int md_astpending; +}; + +/* md_flags */ +#define MDP_USEDFPU 0x0001 /* has used the FPU */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/profile.h b/lib/libc/include/x86-openbsd-none/i386/profile.h new file mode 100644 index 000000000000..b6762e06dadb --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/profile.h @@ -0,0 +1,76 @@ +/* $OpenBSD: profile.h,v 1.12 2014/03/29 18:09:29 guenther Exp $ */ +/* $NetBSD: profile.h,v 1.6 1995/03/28 18:17:08 jtc Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)profile.h 8.1 (Berkeley) 6/11/93 + */ + +#define _MCOUNT_DECL static __inline void _mcount + +#define MCOUNT \ +extern void mcount(void) __asm("__mcount"); \ +__weak_alias(mcount,__mcount); \ +void \ +mcount(void) \ +{ \ + int selfpc, frompcindex; \ + int eax, ecx, edx; \ + \ + __asm volatile("movl %%eax,%0" : "=g" (eax)); \ + __asm volatile("movl %%ecx,%0" : "=g" (ecx)); \ + __asm volatile("movl %%edx,%0" : "=g" (edx)); \ + /* \ + * find the return address for mcount, \ + * and the return address for mcount's caller. \ + * \ + * selfpc = pc pushed by mcount call \ + */ \ + __asm volatile ("movl 4(%%ebp),%0" : "=r" (selfpc)); \ + /* \ + * frompcindex = pc pushed by call into self. \ + */ \ + __asm volatile ("movl (%%ebp),%0;movl 4(%0),%0" : \ + "+r" (frompcindex)); \ + _mcount(frompcindex, selfpc); \ + \ + __asm volatile("movl %0,%%edx" : : "g" (edx)); \ + __asm volatile("movl %0,%%ecx" : : "g" (ecx)); \ + __asm volatile("movl %0,%%eax" : : "g" (eax)); \ +} + +#ifdef _KERNEL +/* + * We inline the code that splhigh and splx would do here as otherwise we would + * call recursively into mcount() as machdep.c is compiled with -pg on a + * profiling build. + */ +#define MCOUNT_ENTER _SPLRAISE(s, IPL_HIGH); __splbarrier() +#define MCOUNT_EXIT __splbarrier(); _SPLX(s) +#endif /* _KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/psl.h b/lib/libc/include/x86-openbsd-none/i386/psl.h new file mode 100644 index 000000000000..f59e7e0c7772 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/psl.h @@ -0,0 +1,98 @@ +/* $OpenBSD: psl.h,v 1.21 2018/07/09 19:20:30 guenther Exp $ */ +/* $NetBSD: psl.h,v 1.30 1996/05/13 01:28:05 mycroft Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)psl.h 5.2 (Berkeley) 1/18/91 + */ + +#ifndef _MACHINE_PSL_H_ +#define _MACHINE_PSL_H_ + +/* + * 386 processor status longword. + */ +#define PSL_C 0x00000001 /* carry flag */ +#define PSL_PF 0x00000004 /* parity flag */ +#define PSL_AF 0x00000010 /* auxiliary carry flag */ +#define PSL_Z 0x00000040 /* zero flag */ +#define PSL_N 0x00000080 /* sign flag */ +#define PSL_T 0x00000100 /* trap flag */ +#define PSL_I 0x00000200 /* interrupt enable flag */ +#define PSL_D 0x00000400 /* direction flag */ +#define PSL_V 0x00000800 /* overflow flag */ +#define PSL_IOPL 0x00003000 /* i/o privilege level */ +#define PSL_NT 0x00004000 /* nested task */ +#define PSL_RF 0x00010000 /* resume flag */ +#define PSL_VM 0x00020000 /* virtual 8086 mode */ +#define PSL_AC 0x00040000 /* alignment check flag */ +#define PSL_VIF 0x00080000 /* virtual interrupt enable flag */ +#define PSL_VIP 0x00100000 /* virtual interrupt pending flag */ +#define PSL_ID 0x00200000 /* identification flag */ +#define PSL_XCRYPT 0x40000000 /* VIA xcrypt: operation loaded */ + +#define PSL_MBO 0x00000002 /* must be one bits */ +#define PSL_MBZ 0xffc08028 /* must be zero bits */ + +#define PSL_USERSET (PSL_MBO | PSL_I) +#define PSL_USERSTATIC (PSL_MBO | PSL_MBZ | PSL_I | PSL_IOPL | PSL_NT | PSL_VM | PSL_VIF | PSL_VIP) + +#ifdef _KERNEL +#include + +#ifndef _LOCORE + +#include + +/* + * Interrupt handler chains. isa_intr_establish() inserts a handler into + * the list. The handler is called with its (single) argument. + */ + +struct intrhand { + int (*ih_fun)(void *); + void *ih_arg; + int ih_level; + int ih_flags; + struct intrhand *ih_next; + int ih_pin; + int ih_irq; + struct evcount ih_count; + int ih_vec; +}; + +extern int intr_shared_edge; /* This system has shared edge interrupts */ + +#endif /* _LOCORE */ +#endif /* _KERNEL */ + +#endif /* !_MACHINE_PSL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/pte.h b/lib/libc/include/x86-openbsd-none/i386/pte.h new file mode 100644 index 000000000000..14a6902bf329 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/pte.h @@ -0,0 +1,92 @@ +/* $OpenBSD: pte.h,v 1.23 2019/01/18 01:34:50 pd Exp $ */ +/* $NetBSD: pte.h,v 1.11 1998/02/06 21:58:05 thorpej Exp $ */ + +/* + * Copyright (c) 1997 Charles D. Cranor and Washington University. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * pte.h rewritten by chuck based on the jolitz version, plus random + * info on the pentium and other processors found on the net. the + * goal of this rewrite is to provide enough documentation on the MMU + * hardware that the reader will be able to understand it without having + * to refer to a hardware manual. + */ + +#ifndef _MACHINE_PTE_H_ +#define _MACHINE_PTE_H_ + +/* + * now we define various for playing with virtual addresses + */ + +#define PDSHIFT 22 /* offset of PD index in VA */ +#define NBPD (1 << PDSHIFT) /* # bytes mapped by PD (4MB) */ + +/* + * here we define the bits of the PDE/PTE, as described above: + * + * XXXCDC: need to rename these (PG_u == ugly). + */ + +#define PG_V 0x00000001 /* valid entry */ +#define PG_RO 0x00000000 /* read-only page */ +#define PG_RW 0x00000002 /* read-write page */ +#define PG_u 0x00000004 /* user accessible page */ +#define PG_PROT 0x00000806 /* all protection bits */ +#define PG_WT 0x00000008 /* write through */ +#define PG_N 0x00000010 /* non-cacheable */ +#define PG_U 0x00000020 /* has been used */ +#define PG_M 0x00000040 /* has been modified */ +#define PG_PAT 0x00000080 /* PAT bit. (on pte) */ +#define PG_PS 0x00000080 /* 4MB page size (on pde) */ +#define PG_G 0x00000100 /* global, don't TLB flush */ +#define PG_AVAIL1 0x00000200 /* ignored by hardware */ +#define PG_AVAIL2 0x00000400 /* ignored by hardware */ +#define PG_AVAIL3 0x00000800 /* ignored by hardware */ +#define PG_PATLG 0x00001000 /* PAT on large pages */ + +/* Cacheability bits when we are using PAT */ +#define PG_WB (0) /* The default */ +#define PG_WC (PG_WT) /* WT and CD is WC */ +#define PG_UCMINUS (PG_N) /* UC but mtrr can override */ +#define PG_UC (PG_WT | PG_N) /* hard UC */ + +/* + * various shorthand protection codes + */ + +#define PG_KR 0x00000000 /* kernel read-only */ +#define PG_KW 0x00000002 /* kernel read-write */ + +/* + * page protection exception bits + */ + +#define PGEX_P 0x01 /* protection violation (vs. no mapping) */ +#define PGEX_W 0x02 /* exception during a write cycle */ +#define PGEX_U 0x04 /* exception while in user mode (upl) */ +#define PGEX_I 0x10 /* instruction fetch blocked by NX */ + +#endif /* _MACHINE_PTE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/ptrace.h b/lib/libc/include/x86-openbsd-none/i386/ptrace.h new file mode 100644 index 000000000000..d8efdad5a982 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/ptrace.h @@ -0,0 +1,50 @@ +/* $OpenBSD: ptrace.h,v 1.3 2005/04/03 20:21:44 kettenis Exp $ */ +/* $NetBSD: ptrace.h,v 1.6 1995/08/06 05:33:23 mycroft Exp $ */ + +/* + * Copyright (c) 1993 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * i386-dependent ptrace definitions + */ +#define PT_STEP (PT_FIRSTMACH + 0) +#define PT_GETREGS (PT_FIRSTMACH + 1) +#define PT_SETREGS (PT_FIRSTMACH + 2) +#define PT_GETFPREGS (PT_FIRSTMACH + 3) +#define PT_SETFPREGS (PT_FIRSTMACH + 4) +#define PT_GETXMMREGS (PT_FIRSTMACH + 5) +#define PT_SETXMMREGS (PT_FIRSTMACH + 6) + +#ifdef _KERNEL +struct xmmregs; + +int process_read_xmmregs(struct proc *, struct xmmregs *); +int process_write_xmmregs(struct proc *, const struct xmmregs *); +#endif \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/rbus_machdep.h b/lib/libc/include/x86-openbsd-none/i386/rbus_machdep.h new file mode 100644 index 000000000000..0d0d6eda307e --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/rbus_machdep.h @@ -0,0 +1,48 @@ +/* $OpenBSD: rbus_machdep.h,v 1.10 2024/05/22 05:51:49 jsg Exp $ */ +/* $NetBSD: rbus_machdep.h,v 1.2 1999/10/15 06:43:05 haya Exp $ */ + +/* + * Copyright (c) 1999 + * HAYAKAWA Koichi. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_RBUS_MACHDEP_H_ +#define _MACHINE_RBUS_MACHDEP_H_ + +struct pci_attach_args; /* XXX */ + +#define md_space_map(rbt, physaddr, size, flags, bshp) \ + _bus_space_map((rbt)->rb_bt, (physaddr), (size), (flags), (bshp)) + +#define md_space_unmap(rbt, bsh, size, adrp) \ + _bus_space_unmap((rbt)->rb_bt, (bsh), (size), (adrp)) + +rbus_tag_t rbus_pccbb_parent_io(struct device *, + struct pci_attach_args *); +rbus_tag_t rbus_pccbb_parent_mem(struct device *, + struct pci_attach_args *); + +void pccbb_attach_hook(struct device *, struct device *, + struct pci_attach_args *); + +#endif /* _MACHINE_RBUS_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/reg.h b/lib/libc/include/x86-openbsd-none/i386/reg.h new file mode 100644 index 000000000000..b25bcac8853f --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/reg.h @@ -0,0 +1,103 @@ +/* $OpenBSD: reg.h,v 1.7 2011/03/23 16:54:35 pirofti Exp $ */ +/* $NetBSD: reg.h,v 1.14 1995/10/11 04:20:24 mycroft Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)reg.h 5.5 (Berkeley) 1/18/91 + */ + +#ifndef _MACHINE_REG_H_ +#define _MACHINE_REG_H_ + +/* + * Location of the users' stored + * registers within appropriate frame of 'trap' and 'syscall', relative to + * base of stack frame. + * Normal usage is u.u_ar0[XX] in kernel. + */ + +/* When referenced during a trap/exception, registers are at these offsets */ + +#define tES (0) +#define tDS (1) +#define tEDI (2) +#define tESI (3) +#define tEBP (4) +#define tEBX (5) +#define tEDX (6) +#define tECX (7) +#define tEAX (8) + +#define tEIP (11) +#define tCS (12) +#define tEFLAGS (13) +#define tESP (14) +#define tSS (15) + +/* + * Registers accessible to ptrace(2) syscall for debugger + * The machine-dependent code for PT_{SET,GET}REGS needs to + * use whichever order, defined above, is correct, so that it + * is all invisible to the user. + */ +struct reg { + int r_eax; + int r_ecx; + int r_edx; + int r_ebx; + int r_esp; + int r_ebp; + int r_esi; + int r_edi; + int r_eip; + int r_eflags; + int r_cs; + int r_ss; + int r_ds; + int r_es; + int r_fs; + int r_gs; +}; + +struct fpreg { + /* + * XXX + * Fill this in with real info. + */ + char __data[116]; +}; + +struct xmmregs { + char __data[512]; +}; + +#endif /* !_MACHINE_REG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/reloc.h b/lib/libc/include/x86-openbsd-none/i386/reloc.h new file mode 100644 index 000000000000..e2d976bbfd9b --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/reloc.h @@ -0,0 +1,52 @@ +/* $OpenBSD: reloc.h,v 1.3 2011/03/23 16:54:35 pirofti Exp $ */ + +/* + * Copyright (c) 2002,2003 Dale Rahn + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _MACHINE_RELOC_H_ +#define _MACHINE_RELOC_H_ +#define R_TYPE(X) __CONCAT(RELOC_,X) + + +#define RELOC_NONE 0 /* No reloc */ +#define RELOC_32 1 /* Direct 32 bit */ +#define RELOC_PC32 2 /* PC relative 32 bit */ +#define RELOC_GOT32 3 /* 32 bit GOT entry */ +#define RELOC_PLT32 4 /* 32 bit PLT address */ +#define RELOC_COPY 5 /* Copy symbol at runtime */ +#define RELOC_GLOB_DAT 6 /* Create GOT entry */ +#define RELOC_JUMP_SLOT 7 /* Create PLT entry */ +#define RELOC_RELATIVE 8 /* Adjust by program base */ +#define RELOC_GOTOFF 9 /* 32 bit offset to GOT */ +#define RELOC_GOTPC 10 /* 32 bit PC relative offset to GOT */ +#define RELOC_TLS_TPOFF 14 /* negative offset in static TLS block */ +#define RELOC_16 20 +#define RELOC_PC16 21 +#define RELOC_8 22 +#define RELOC_PC8 23 +#define RELOC_TLS_DTPMOD32 35 /* ID of module containing symbol */ +#define RELOC_TLS_DTPOFF32 36 /* Offset in TLS block */ +#define RELOC_TLS_TPOFF32 37 /* Offset in static TLS block */ + +#endif /* _MACHINE_RELOC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/segments.h b/lib/libc/include/x86-openbsd-none/i386/segments.h new file mode 100644 index 000000000000..03a4bc81be9e --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/segments.h @@ -0,0 +1,229 @@ +/* $OpenBSD: segments.h,v 1.28 2020/09/24 11:36:50 deraadt Exp $ */ +/* $NetBSD: segments.h,v 1.23 1996/02/01 22:31:03 mycroft Exp $ */ + +/*- + * Copyright (c) 1995 Charles M. Hannum. All rights reserved. + * Copyright (c) 1989, 1990 William F. Jolitz + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)segments.h 7.1 (Berkeley) 5/9/91 + */ + +/* + * 386 Segmentation Data Structures and definitions + * William F. Jolitz (william@ernie.berkeley.edu) 6/20/1989 + */ + +#ifndef _MACHINE_SEGMENTS_H_ +#define _MACHINE_SEGMENTS_H_ + +/* + * Selectors + */ + +#define ISPL(s) ((s) & SEL_RPL) /* what is the priority level of a selector */ +#define SEL_KPL 0 /* kernel privilege level */ +#define SEL_UPL 3 /* user privilege level */ +#define SEL_RPL 3 /* requester's privilege level mask */ +#define ISLDT(s) ((s) & SEL_LDT) /* is it local or global */ +#define SEL_LDT 4 /* local descriptor table */ +#define IDXSEL(s) (((s) >> 3) & 0x1fff) /* index of selector */ +#define GSEL(s,r) (((s) << 3) | r) /* a global selector */ +#define LSEL(s,r) (((s) << 3) | r | SEL_LDT) /* a local selector */ + +#define USERMODE(c, f) (ISPL(c) == SEL_UPL) +#define KERNELMODE(c, f) (ISPL(c) == SEL_KPL) + +#ifndef _LOCORE + +/* + * Memory and System segment descriptors + */ +struct segment_descriptor { + unsigned sd_lolimit:16; /* segment extent (lsb) */ + unsigned sd_lobase:24; /* segment base address (lsb) */ + unsigned sd_type:5; /* segment type */ + unsigned sd_dpl:2; /* segment descriptor priority level */ + unsigned sd_p:1; /* segment descriptor present */ + unsigned sd_hilimit:4; /* segment extent (msb) */ + unsigned sd_xx:2; /* unused */ + unsigned sd_def32:1; /* default 32 vs 16 bit size */ + unsigned sd_gran:1; /* limit granularity (byte/page) */ + unsigned sd_hibase:8; /* segment base address (msb) */ +} __packed; + +/* + * Gate descriptors (e.g. indirect descriptors) + */ +struct gate_descriptor { + unsigned gd_looffset:16; /* gate offset (lsb) */ + unsigned gd_selector:16; /* gate segment selector */ + unsigned gd_stkcpy:5; /* number of stack wds to cpy */ + unsigned gd_xx:3; /* unused */ + unsigned gd_type:5; /* segment type */ + unsigned gd_dpl:2; /* segment descriptor priority level */ + unsigned gd_p:1; /* segment descriptor present */ + unsigned gd_hioffset:16; /* gate offset (msb) */ +} __packed; + +/* + * Generic descriptor + */ +union descriptor { + struct segment_descriptor sd; + struct gate_descriptor gd; +} __packed; + +/* + * region descriptors, used to load gdt/idt tables before segments yet exist. + */ +struct region_descriptor { + unsigned rd_limit:16; /* segment extent */ + unsigned rd_base:32; /* base address */ +} __packed; + +#ifdef _KERNEL +extern union descriptor *gdt; +extern struct gate_descriptor idt_region[]; +extern struct gate_descriptor *idt; + +#define SEGDESC_LIMIT(sd) (ptoa(((sd).sd_hilimit << 16) | (sd).sd_lolimit)) + +void setgate(struct gate_descriptor *, void *, int, int, int, int); +void setregion(struct region_descriptor *, void *, size_t); +void setsegment(struct segment_descriptor *, void *, size_t, int, int, + int, int); +void initcodesegment(struct segment_descriptor *); +void unsetgate(struct gate_descriptor *); +void cpu_init_idt(void); + +int idt_vec_alloc(int, int); +void idt_vec_set(int, void (*)(void)); +void idt_vec_free(int); + +#endif /* _KERNEL */ + +#endif /* !_LOCORE */ + +/* system segments and gate types */ +#define SDT_SYSNULL 0 /* system null */ +#define SDT_SYS286TSS 1 /* system 286 TSS available */ +#define SDT_SYSLDT 2 /* system local descriptor table */ +#define SDT_SYS286BSY 3 /* system 286 TSS busy */ +#define SDT_SYS286CGT 4 /* system 286 call gate */ +#define SDT_SYSTASKGT 5 /* system task gate */ +#define SDT_SYS286IGT 6 /* system 286 interrupt gate */ +#define SDT_SYS286TGT 7 /* system 286 trap gate */ +#define SDT_SYSNULL2 8 /* system null again */ +#define SDT_SYS386TSS 9 /* system 386 TSS available */ +#define SDT_SYSNULL3 10 /* system null again */ +#define SDT_SYS386BSY 11 /* system 386 TSS busy */ +#define SDT_SYS386CGT 12 /* system 386 call gate */ +#define SDT_SYSNULL4 13 /* system null again */ +#define SDT_SYS386IGT 14 /* system 386 interrupt gate */ +#define SDT_SYS386TGT 15 /* system 386 trap gate */ + +/* memory segment types */ +#define SDT_MEMRO 16 /* memory read only */ +#define SDT_MEMROA 17 /* memory read only accessed */ +#define SDT_MEMRW 18 /* memory read write */ +#define SDT_MEMRWA 19 /* memory read write accessed */ +#define SDT_MEMROD 20 /* memory read only expand dwn limit */ +#define SDT_MEMRODA 21 /* memory read only expand dwn limit accessed */ +#define SDT_MEMRWD 22 /* memory read write expand dwn limit */ +#define SDT_MEMRWDA 23 /* memory read write expand dwn limit acessed */ +#define SDT_MEME 24 /* memory execute only */ +#define SDT_MEMEA 25 /* memory execute only accessed */ +#define SDT_MEMER 26 /* memory execute read */ +#define SDT_MEMERA 27 /* memory execute read accessed */ +#define SDT_MEMEC 28 /* memory execute only conforming */ +#define SDT_MEMEAC 29 /* memory execute only accessed conforming */ +#define SDT_MEMERC 30 /* memory execute read conforming */ +#define SDT_MEMERAC 31 /* memory execute read accessed conforming */ + +/* is memory segment descriptor pointer ? */ +#define ISMEMSDP(s) ((s->d_type) >= SDT_MEMRO && \ + (s->d_type) <= SDT_MEMERAC) + +/* is 286 gate descriptor pointer ? */ +#define IS286GDP(s) ((s->d_type) >= SDT_SYS286CGT && \ + (s->d_type) < SDT_SYS286TGT) + +/* is 386 gate descriptor pointer ? */ +#define IS386GDP(s) ((s->d_type) >= SDT_SYS386CGT && \ + (s->d_type) < SDT_SYS386TGT) + +/* is gate descriptor pointer ? */ +#define ISGDP(s) (IS286GDP(s) || IS386GDP(s)) + +/* is segment descriptor pointer ? */ +#define ISSDP(s) (ISMEMSDP(s) || !ISGDP(s)) + +/* is system segment descriptor pointer ? */ +#define ISSYSSDP(s) (!ISMEMSDP(s) && !ISGDP(s)) + +/* + * Segment Protection Exception code bits + */ +#define SEGEX_EXT 0x01 /* recursive or externally induced */ +#define SEGEX_IDT 0x02 /* interrupt descriptor table */ +#define SEGEX_TI 0x04 /* local descriptor table */ + +/* + * Entries in the Interrupt Descriptor Table (IDT) + */ +#define NIDT 256 +#define NRSVIDT 32 /* reserved entries for cpu exceptions */ + +/* + * Entries in the Global Descriptor Table (GDT) + */ +#define GNULL_SEL 0 /* Null descriptor */ +#define GCODE_SEL 1 /* Kernel code descriptor */ +#define GDATA_SEL 2 /* Kernel data descriptor */ +#define GLDT_SEL 3 /* Default LDT descriptor (UNUSED) */ +#define GCPU_SEL 4 /* per-CPU segment */ +#define GUCODE_SEL 5 /* User code descriptor (a stack short) */ +#define GUDATA_SEL 6 /* User data descriptor */ +#define GAPM32CODE_SEL 7 /* 32 bit APM code descriptor */ +#define GAPM16CODE_SEL 8 /* 16 bit APM code descriptor */ +#define GAPMDATA_SEL 9 /* APM data descriptor */ +#define GICODE_SEL 10 /* Interrupt code descriptor (same as Kernel code) */ +#define GUFS_SEL 11 /* User per-thread (%fs) descriptor */ +#define GUGS_SEL 12 /* User per-thread (%gs) descriptor */ +#define GTSS_SEL 13 /* common TSS */ +#define GNMITSS_SEL 14 /* NMI TSS */ +#define GBIOS32_SEL 15 /* spare slot for 32 bit BIOS calls */ +#define NGDT 16 + +#define GDT_SIZE (NGDT << 3) + +#endif /* _MACHINE_SEGMENTS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/setjmp.h b/lib/libc/include/x86-openbsd-none/i386/setjmp.h new file mode 100644 index 000000000000..f53a7cc52544 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/setjmp.h @@ -0,0 +1,18 @@ +/* $OpenBSD: setjmp.h,v 1.4 2020/12/13 21:21:32 bluhm Exp $ */ +/* $NetBSD: setjmp.h,v 1.1 1994/12/20 10:36:43 cgd Exp $ */ + +/* + * machine/setjmp.h: machine dependent setjmp-related information. + */ + +#define _JB_EIP 0 +#define _JB_EBX 1 +#define _JB_ESP 2 +#define _JB_EBP 3 +#define _JB_ESI 4 +#define _JB_EDI 5 +#define _JB_SIGMASK 6 +#define _JB_SIGFLAG 7 +#define _JB_FCW 8 + +#define _JBLEN 10 /* size, in longs, of a jmp_buf */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/signal.h b/lib/libc/include/x86-openbsd-none/i386/signal.h new file mode 100644 index 000000000000..80c9b368f1c5 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/signal.h @@ -0,0 +1,88 @@ +/* $OpenBSD: signal.h,v 1.11 2016/05/10 18:39:45 deraadt Exp $ */ +/* $NetBSD: signal.h,v 1.6 1996/01/08 13:51:43 mycroft Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)signal.h 7.16 (Berkeley) 3/17/91 + */ + +#ifndef _MACHINE_SIGNAL_H_ +#define _MACHINE_SIGNAL_H_ + +#include + +typedef int sig_atomic_t; + +#ifdef _KERNEL +#include +#endif + +#if __BSD_VISIBLE || __XPG_VISIBLE >= 420 +/* + * Information pushed on stack when a signal is delivered. + * This is used by the kernel to restore state following + * execution of the signal handler. It is also made available + * to the handler to allow it to restore state properly if + * a non-standard exit is performed. + */ +struct sigcontext { + int sc_gs; + int sc_fs; + int sc_es; + int sc_ds; + int sc_edi; + int sc_esi; + int sc_ebp; + int sc_ebx; + int sc_edx; + int sc_ecx; + int sc_eax; + /* XXX */ + int sc_eip; + int sc_cs; + int sc_eflags; + int sc_esp; + int sc_ss; + + long sc_cookie; + int sc_mask; /* signal mask to restore */ + + int sc_trapno; /* XXX should be above */ + int sc_err; + + union savefpu *sc_fpstate; +}; + +#define sc_sp sc_esp +#define sc_fp sc_ebp +#define sc_pc sc_eip +#define sc_ps sc_eflags + +#endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ +#endif /* !_MACHINE_SIGNAL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/smbiosvar.h b/lib/libc/include/x86-openbsd-none/i386/smbiosvar.h new file mode 100644 index 000000000000..34349b6ec955 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/smbiosvar.h @@ -0,0 +1,281 @@ +/* $OpenBSD: smbiosvar.h,v 1.14 2025/07/15 01:09:32 jsg Exp $ */ +/* + * Copyright (c) 2006 Gordon Willem Klok + * Copyright (c) 2005 Jordan Hargrave + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_SMBIOSVAR_ +#define _MACHINE_SMBIOSVAR_ + +#define SMBIOS_START 0xf0000 +#define SMBIOS_END 0xfffff + +#define SMBIOS_UUID_NPRESENT 0x1 +#define SMBIOS_UUID_NSET 0x2 + +/* + * Section 3.5 of "UUIDs and GUIDs" found at + * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt + * specifies the string representation of a UUID. + */ +#define SMBIOS_UUID_REP "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" +#define SMBIOS_UUID_REPLEN 37 /* 16 zero padded values, 4 hyphens, 1 null */ + +struct smbios_entry { + uint8_t mjr; + uint8_t min; + uint8_t *addr; + uint16_t len; + uint16_t count; +}; + +struct smbhdr { + uint32_t sig; /* "_SM_" */ + uint8_t checksum; /* Entry point checksum */ + uint8_t len; /* Entry point structure length */ + uint8_t majrev; /* Specification major revision */ + uint8_t minrev; /* Specification minor revision */ + uint16_t mss; /* Maximum Structure Size */ + uint8_t epr; /* Entry Point Revision */ + uint8_t fa[5]; /* value determined by EPR */ + uint8_t sasig[5]; /* Secondary Anchor "_DMI_" */ + uint8_t sachecksum; /* Secondary Checksum */ + uint16_t size; /* Length of structure table in bytes */ + uint32_t addr; /* Structure table address */ + uint16_t count; /* Number of SMBIOS structures */ + uint8_t rev; /* BCD revision */ +} __packed; + +struct smb3hdr { + uint8_t sig[5]; /* "_SM3_" */ + uint8_t checksum; /* Entry point structure checksum */ + uint8_t len; /* Entry point length */ + uint8_t majrev; /* SMBIOS major version */ + uint8_t minrev; /* SMBIOS minor version */ + uint8_t docrev; /* SMBIOS docrev */ + uint8_t epr; /* Entry point revision */ + uint8_t reserved; /* Reserved */ + uint32_t size; /* Structure table maximum size */ + uint64_t addr; /* Structure table address */ +} __packed; + +struct smbtblhdr { + uint8_t type; + uint8_t size; + uint16_t handle; +} __packed; + +struct smbtable { + struct smbtblhdr *hdr; + void *tblhdr; + uint32_t cookie; +}; + +#define SMBIOS_TYPE_BIOS 0 +#define SMBIOS_TYPE_SYSTEM 1 +#define SMBIOS_TYPE_BASEBOARD 2 +#define SMBIOS_TYPE_ENCLOSURE 3 +#define SMBIOS_TYPE_PROCESSOR 4 +#define SMBIOS_TYPE_MEMCTRL 5 +#define SMBIOS_TYPE_MEMMOD 6 +#define SMBIOS_TYPE_CACHE 7 +#define SMBIOS_TYPE_PORT 8 +#define SMBIOS_TYPE_SLOTS 9 +#define SMBIOS_TYPE_OBD 10 +#define SMBIOS_TYPE_OEM 11 +#define SMBIOS_TYPE_SYSCONFOPT 12 +#define SMBIOS_TYPE_BIOSLANG 13 +#define SMBIOS_TYPE_GROUPASSOC 14 +#define SMBIOS_TYPE_SYSEVENTLOG 15 +#define SMBIOS_TYPE_PHYMEM 16 +#define SMBIOS_TYPE_MEMDEV 17 +#define SMBIOS_TYPE_ECCINFO32 18 +#define SMBIOS_TYPE_MEMMAPARRAYADDR 19 +#define SMBIOS_TYPE_MEMMAPDEVADDR 20 +#define SMBIOS_TYPE_INBUILTPOINT 21 +#define SMBIOS_TYPE_PORTBATT 22 +#define SMBIOS_TYPE_SYSRESET 23 +#define SMBIOS_TYPE_HWSECUIRTY 24 +#define SMBIOS_TYPE_PWRCTRL 25 +#define SMBIOS_TYPE_VOLTPROBE 26 +#define SMBIOS_TYPE_COOLING 27 +#define SMBIOS_TYPE_TEMPPROBE 28 +#define SMBIOS_TYPE_CURRENTPROBE 29 +#define SMBIOS_TYPE_OOB_REMOTEACCESS 30 +#define SMBIOS_TYPE_BIS 31 +#define SMBIOS_TYPE_SBI 32 +#define SMBIOS_TYPE_ECCINFO64 33 +#define SMBIOS_TYPE_MGMTDEV 34 +#define SMBIOS_TYPE_MGTDEVCOMP 35 +#define SMBIOS_TYPE_MGTDEVTHRESH 36 +#define SMBIOS_TYPE_MEMCHANNEL 37 +#define SMBIOS_TYPE_IPMIDEV 38 +#define SMBIOS_TYPE_SPS 39 +#define SMBIOS_TYPE_INACTIVE 126 +#define SMBIOS_TYPE_EOT 127 + +/* + * SMBIOS Structure Type 0 "BIOS Information" + * DMTF Specification DSP0134 Section: 3.3.1 p.g. 34 + */ +struct smbios_struct_bios { + uint8_t vendor; /* string */ + uint8_t version; /* string */ + uint16_t startaddr; + uint8_t release; /* string */ + uint8_t romsize; + uint64_t characteristics; + uint32_t charext; + uint8_t major_rel; + uint8_t minor_rel; + uint8_t ecf_mjr_rel; /* embedded controller firmware */ + uint8_t ecf_min_rel; /* embedded controller firmware */ +} __packed; + +/* + * SMBIOS Structure Type 1 "System Information" + * DMTF Specification DSP0134 Section 3.3.2 p.g. 35 + */ + +struct smbios_sys { +/* SMBIOS spec 2.0+ */ + uint8_t vendor; /* string */ + uint8_t product; /* string */ + uint8_t version; /* string */ + uint8_t serial; /* string */ +/* SMBIOS spec 2.1+ */ + uint8_t uuid[16]; + uint8_t wakeup; +/* SMBIOS spec 2.4+ */ + uint8_t sku; /* string */ + uint8_t family; /* string */ +} __packed; + +/* + * SMBIOS Structure Type 2 "Base Board (Module) Information" + * DMTF Specification DSP0134 Section 3.3.3 p.g. 37 + */ +struct smbios_board { + uint8_t vendor; /* string */ + uint8_t product; /* string */ + uint8_t version; /* string */ + uint8_t serial; /* string */ + uint8_t asset; /* string */ + uint8_t feature; /* feature flags */ + uint8_t location; /* location in chassis */ + uint16_t handle; /* chassis handle */ + uint8_t type; /* board type */ + uint8_t noc; /* number of contained objects */ +} __packed; + +/* + * SMBIOS Structure Type 3 "System Enclosure or Chassis" + * DMTF Specification DSP0134 + */ +struct smbios_enclosure { + /* SMBIOS spec 2.0+ */ + uint8_t vendor; /* string */ + uint8_t type; + uint8_t version; /* string */ + uint8_t serial; /* string */ + uint8_t asset_tag; /* string */ + /* SMBIOS spec 2.1+ */ + uint8_t boot_state; + uint8_t psu_state; + uint8_t thermal_state; + uint8_t security_status; + /* SMBIOS spec 2.3+ */ + uint16_t oem_defined; + uint8_t height; + uint8_t no_power_cords; + uint8_t no_contained_element; + uint8_t reclen_contained_element; + uint8_t contained_elements; + /* SMBIOS spec 2.7+ */ + uint8_t sku; /* string */ +} __packed; + +/* + * SMBIOS Structure Type 4 "processor Information" + * DMTF Specification DSP0134 v2.5 Section 3.3.5 p.g. 24 + */ +struct smbios_cpu { + uint8_t cpu_socket_designation; /* string */ + uint8_t cpu_type; + uint8_t cpu_family; + uint8_t cpu_mfg; /* string */ + uint32_t cpu_id_eax; + uint32_t cpu_id_edx; + uint8_t cpu_version; /* string */ + uint8_t cpu_voltage; + uint16_t cpu_clock; + uint16_t cpu_max_speed; + uint16_t cpu_current_speed; + uint8_t cpu_status; +#define SMBIOS_CPUST_POPULATED (1<<6) +#define SMBIOS_CPUST_STATUSMASK (0x07) + uint8_t cpu_upgrade; + uint16_t cpu_l1_handle; + uint16_t cpu_l2_handle; + uint16_t cpu_l3_handle; + uint8_t cpu_serial; /* string */ + uint8_t cpu_asset_tag; /* string */ + uint8_t cpu_part_nr; /* string */ + /* following fields were added in smbios 2.5 */ + uint8_t cpu_core_count; + uint8_t cpu_core_enabled; + uint8_t cpu_thread_count; + uint16_t cpu_characteristics; +} __packed; + +/* + * SMBIOS Structure Type 38 "IPMI Information" + * DMTF Specification DSP0134 Section 3.3.39 p.g. 91 + */ +struct smbios_ipmi { + uint8_t smipmi_if_type; /* IPMI Interface Type */ + uint8_t smipmi_if_rev; /* BCD IPMI Revision */ + uint8_t smipmi_i2c_address; /* I2C address of BMC */ + uint8_t smipmi_nvram_address; /* I2C address of NVRAM + * storage */ + uint64_t smipmi_base_address; /* Base address of BMC (BAR + * format */ + uint8_t smipmi_base_flags; /* Flags field: + * bit 7:6 : register spacing + * 00 = byte + * 01 = dword + * 02 = word + * bit 4 : Lower bit BAR + * bit 3 : IRQ valid + * bit 2 : N/A + * bit 1 : Interrupt polarity + * bit 0 : Interrupt trigger */ + uint8_t smipmi_irq; /* IRQ if applicable */ +} __packed; + +int smbios_find_table(uint8_t, struct smbtable *); +char *smbios_get_string(struct smbtable *, uint8_t, char *, size_t); + +#endif \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/specialreg.h b/lib/libc/include/x86-openbsd-none/i386/specialreg.h new file mode 100644 index 000000000000..6024995d828a --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/specialreg.h @@ -0,0 +1,812 @@ +/* $OpenBSD: specialreg.h,v 1.85 2023/08/16 04:07:38 jsg Exp $ */ +/* $NetBSD: specialreg.h,v 1.7 1994/10/27 04:16:26 cgd Exp $ */ + +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)specialreg.h 7.1 (Berkeley) 5/9/91 + */ + +/* + * Bits in 386 special registers: + */ +#define CR0_PE 0x00000001 /* Protected mode Enable */ +#define CR0_MP 0x00000002 /* "Math" Present (NPX or NPX emulator) */ +#define CR0_EM 0x00000004 /* EMulate non-NPX coproc. (trap ESC only) */ +#define CR0_TS 0x00000008 /* Task Switched (if MP, trap ESC and WAIT) */ +#define CR0_ET 0x00000010 /* Extension Type (387 (if set) vs 287) */ +#define CR0_PG 0x80000000 /* PaGing enable */ + +/* + * Bits in 486 special registers: + */ +#define CR0_NE 0x00000020 /* Numeric Error enable (EX16 vs IRQ13) */ +#define CR0_WP 0x00010000 /* Write Protect (honor PG_RW in all modes) */ +#define CR0_AM 0x00040000 /* Alignment Mask (set to enable AC flag) */ +#define CR0_NW 0x20000000 /* Not Write-through */ +#define CR0_CD 0x40000000 /* Cache Disable */ + +/* + * bits in CR3 + */ +#define CR3_PWT (1ULL << 3) +#define CR3_PCD (1ULL << 4) + +/* + * bits in the pentiums %cr4 register: + */ + +#define CR4_VME 0x00000001 /* virtual 8086 mode extension enable */ +#define CR4_PVI 0x00000002 /* protected mode virtual interrupt enable */ +#define CR4_TSD 0x00000004 /* restrict RDTSC instruction to cpl 0 only */ +#define CR4_DE 0x00000008 /* debugging extension */ +#define CR4_PSE 0x00000010 /* large (4MB) page size enable */ +#define CR4_PAE 0x00000020 /* physical address extension enable */ +#define CR4_MCE 0x00000040 /* machine check enable */ +#define CR4_PGE 0x00000080 /* page global enable */ +#define CR4_PCE 0x00000100 /* enable RDPMC instruction for all cpls */ +#define CR4_OSFXSR 0x00000200 /* enable fxsave/fxrestor and SSE */ +#define CR4_OSXMMEXCPT 0x00000400 /* enable unmasked SSE exceptions */ +#define CR4_UMIP 0x00000800 /* user mode instruction prevention */ +#define CR4_VMXE 0x00002000 /* enable virtual machine operation */ +#define CR4_SMXE 0x00004000 /* enable safe mode operation */ +#define CR4_FSGSBASE 0x00010000 /* enable {RD,WR}{FS,GS}BASE ops */ +#define CR4_PCIDE 0x00020000 /* enable process-context IDs */ +#define CR4_OSXSAVE 0x00040000 /* enable XSAVE and extended states */ +#define CR4_SMEP 0x00100000 /* supervisor mode exec protection */ +#define CR4_SMAP 0x00200000 /* supervisor mode access prevention */ +#define CR4_PKE 0x00400000 /* protection key enable */ + +/* + * CPUID "features" bits (CPUID function 0x1): + * EDX bits, then ECX bits + */ + +#define CPUID_FPU 0x00000001 /* processor has an FPU? */ +#define CPUID_VME 0x00000002 /* has virtual mode (%cr4's VME/PVI) */ +#define CPUID_DE 0x00000004 /* has debugging extension */ +#define CPUID_PSE 0x00000008 /* has 4MB page size extension */ +#define CPUID_TSC 0x00000010 /* has time stamp counter */ +#define CPUID_MSR 0x00000020 /* has model specific registers */ +#define CPUID_PAE 0x00000040 /* has phys address extension */ +#define CPUID_MCE 0x00000080 /* has machine check exception */ +#define CPUID_CX8 0x00000100 /* has CMPXCHG8B instruction */ +#define CPUID_APIC 0x00000200 /* has enabled APIC */ +#define CPUID_SYS1 0x00000400 /* has SYSCALL/SYSRET inst. (Cyrix) */ +#define CPUID_SEP 0x00000800 /* has SYSCALL/SYSRET inst. (AMD/Intel) */ +#define CPUID_MTRR 0x00001000 /* has memory type range register */ +#define CPUID_PGE 0x00002000 /* has page global extension */ +#define CPUID_MCA 0x00004000 /* has machine check architecture */ +#define CPUID_CMOV 0x00008000 /* has CMOVcc instruction */ +#define CPUID_PAT 0x00010000 /* has page attribute table */ +#define CPUID_PSE36 0x00020000 /* has 36bit page size extension */ +#define CPUID_PSN 0x00040000 /* has processor serial number */ +#define CPUID_CFLUSH 0x00080000 /* CFLUSH insn supported */ +#define CPUID_B20 0x00100000 /* reserved */ +#define CPUID_DS 0x00200000 /* Debug Store */ +#define CPUID_ACPI 0x00400000 /* ACPI performance modulation regs */ +#define CPUID_MMX 0x00800000 /* has MMX instructions */ +#define CPUID_FXSR 0x01000000 /* has FXRSTOR instruction */ +#define CPUID_SSE 0x02000000 /* has streaming SIMD extensions */ +#define CPUID_SSE2 0x04000000 /* has streaming SIMD extensions #2 */ +#define CPUID_SS 0x08000000 /* self-snoop */ +#define CPUID_HTT 0x10000000 /* Hyper-Threading Technology */ +#define CPUID_TM 0x20000000 /* thermal monitor (TCC) */ +#define CPUID_B30 0x40000000 /* reserved */ +#define CPUID_PBE 0x80000000 /* Pending Break Enabled restarts clock */ + +#define CPUIDECX_SSE3 0x00000001 /* streaming SIMD extensions #3 */ +#define CPUIDECX_PCLMUL 0x00000002 /* Carryless Multiplication */ +#define CPUIDECX_DTES64 0x00000004 /* 64bit debug store */ +#define CPUIDECX_MWAIT 0x00000008 /* Monitor/Mwait */ +#define CPUIDECX_DSCPL 0x00000010 /* CPL Qualified Debug Store */ +#define CPUIDECX_VMX 0x00000020 /* Virtual Machine Extensions */ +#define CPUIDECX_SMX 0x00000040 /* Safer Mode Extensions */ +#define CPUIDECX_EST 0x00000080 /* enhanced SpeedStep */ +#define CPUIDECX_TM2 0x00000100 /* thermal monitor 2 */ +#define CPUIDECX_SSSE3 0x00000200 /* Supplemental Streaming SIMD Ext. 3 */ +#define CPUIDECX_CNXTID 0x00000400 /* Context ID */ +#define CPUIDECX_SDBG 0x00000800 /* Silicon debug capability */ +#define CPUIDECX_FMA3 0x00001000 /* Fused Multiply Add */ +#define CPUIDECX_CX16 0x00002000 /* has CMPXCHG16B instruction */ +#define CPUIDECX_XTPR 0x00004000 /* xTPR Update Control */ +#define CPUIDECX_PDCM 0x00008000 /* Perfmon and Debug Capability */ +#define CPUIDECX_PCID 0x00020000 /* Process-context ID Capability */ +#define CPUIDECX_DCA 0x00040000 /* Direct Cache Access */ +#define CPUIDECX_SSE41 0x00080000 /* Streaming SIMD Extensions 4.1 */ +#define CPUIDECX_SSE42 0x00100000 /* Streaming SIMD Extensions 4.2 */ +#define CPUIDECX_X2APIC 0x00200000 /* Extended xAPIC Support */ +#define CPUIDECX_MOVBE 0x00400000 /* MOVBE Instruction */ +#define CPUIDECX_POPCNT 0x00800000 /* POPCNT Instruction */ +#define CPUIDECX_DEADLINE 0x01000000 /* APIC one-shot via deadline */ +#define CPUIDECX_AES 0x02000000 /* AES Instruction */ +#define CPUIDECX_XSAVE 0x04000000 /* XSAVE/XSTOR States */ +#define CPUIDECX_OSXSAVE 0x08000000 /* OSXSAVE */ +#define CPUIDECX_AVX 0x10000000 /* Advanced Vector Extensions */ +#define CPUIDECX_F16C 0x20000000 /* 16bit fp conversion */ +#define CPUIDECX_RDRAND 0x40000000 /* RDRAND instruction */ +#define CPUIDECX_HV 0x80000000 /* Running on hypervisor */ + +/* + * "Structured Extended Feature Flags Parameters" (CPUID function 0x7, leaf 0) + * EBX bits + */ +#define SEFF0EBX_FSGSBASE 0x00000001 /* {RD,WR}[FG]SBASE instructions */ +#define SEFF0EBX_TSC_ADJUST 0x00000002 /* Has IA32_TSC_ADJUST MSR */ +#define SEFF0EBX_SGX 0x00000004 /* Software Guard Extensions */ +#define SEFF0EBX_BMI1 0x00000008 /* advanced bit manipulation */ +#define SEFF0EBX_HLE 0x00000010 /* Hardware Lock Elision */ +#define SEFF0EBX_AVX2 0x00000020 /* Advanced Vector Extensions 2 */ +#define SEFF0EBX_SMEP 0x00000080 /* Supervisor mode exec protection */ +#define SEFF0EBX_BMI2 0x00000100 /* advanced bit manipulation */ +#define SEFF0EBX_ERMS 0x00000200 /* Enhanced REP MOVSB/STOSB */ +#define SEFF0EBX_INVPCID 0x00000400 /* INVPCID instruction */ +#define SEFF0EBX_RTM 0x00000800 /* Restricted Transactional Memory */ +#define SEFF0EBX_PQM 0x00001000 /* Quality of Service Monitoring */ +#define SEFF0EBX_MPX 0x00004000 /* Memory Protection Extensions */ +#define SEFF0EBX_AVX512F 0x00010000 /* AVX-512 foundation inst */ +#define SEFF0EBX_AVX512DQ 0x00020000 /* AVX-512 double/quadword */ +#define SEFF0EBX_RDSEED 0x00040000 /* RDSEED instruction */ +#define SEFF0EBX_ADX 0x00080000 /* ADCX/ADOX instructions */ +#define SEFF0EBX_SMAP 0x00100000 /* Supervisor mode access prevent */ +#define SEFF0EBX_AVX512IFMA 0x00200000 /* AVX-512 integer mult-add */ +#define SEFF0EBX_PCOMMIT 0x00400000 /* Persistent commit inst */ +#define SEFF0EBX_CLFLUSHOPT 0x00800000 /* cache line flush */ +#define SEFF0EBX_CLWB 0x01000000 /* cache line write back */ +#define SEFF0EBX_PT 0x02000000 /* Processor Trace */ +#define SEFF0EBX_AVX512PF 0x04000000 /* AVX-512 prefetch */ +#define SEFF0EBX_AVX512ER 0x08000000 /* AVX-512 exp/reciprocal */ +#define SEFF0EBX_AVX512CD 0x10000000 /* AVX-512 conflict detection */ +#define SEFF0EBX_SHA 0x20000000 /* SHA Extensions */ +#define SEFF0EBX_AVX512BW 0x40000000 /* AVX-512 byte/word inst */ +#define SEFF0EBX_AVX512VL 0x80000000 /* AVX-512 vector len inst */ +/* SEFF ECX bits */ +#define SEFF0ECX_PREFETCHWT1 0x00000001 /* PREFETCHWT1 instruction */ +#define SEFF0ECX_AVX512VBMI 0x00000002 /* AVX-512 vector bit inst */ +#define SEFF0ECX_UMIP 0x00000004 /* UMIP support */ +#define SEFF0ECX_PKU 0x00000008 /* Page prot keys for user mode */ +#define SEFF0ECX_WAITPKG 0x00000020 /* UMONITOR/UMWAIT/TPAUSE insns */ +/* SEFF EDX bits */ +#define SEFF0EDX_AVX512_4FNNIW 0x00000004 /* AVX-512 neural network insns */ +#define SEFF0EDX_AVX512_4FMAPS 0x00000008 /* AVX-512 mult accum single prec */ +#define SEFF0EDX_SRBDS_CTRL 0x00000200 /* MCU_OPT_CTRL MSR */ +#define SEFF0EDX_MD_CLEAR 0x00000400 /* Microarch Data Clear */ +#define SEFF0EDX_TSXFA 0x00002000 /* TSX Forced Abort */ +#define SEFF0EDX_IBRS 0x04000000 /* IBRS / IBPB Speculation Control */ +#define SEFF0EDX_STIBP 0x08000000 /* STIBP Speculation Control */ +#define SEFF0EDX_L1DF 0x10000000 /* L1D_FLUSH */ +#define SEFF0EDX_ARCH_CAP 0x20000000 /* Has IA32_ARCH_CAPABILITIES MSR */ +#define SEFF0EDX_SSBD 0x80000000 /* Spec Store Bypass Disable */ + +/* + * Thermal and Power Management (CPUID function 0x6) EAX bits + */ +#define TPM_SENSOR 0x00000001 /* Digital temp sensor */ +#define TPM_ARAT 0x00000004 /* APIC Timer Always Running */ + +/* + * "Architectural Performance Monitoring" bits (CPUID function 0x0a): + * EAX bits + */ + +#define CPUIDEAX_VERID 0x000000ff +#define CPUIDEAX_NUM_GC(cpuid) (((cpuid) >> 8) & 0x000000ff) +#define CPUIDEAX_BIT_GC(cpuid) (((cpuid) >> 16) & 0x000000ff) +#define CPUIDEAX_LEN_EBX(cpuid) (((cpuid) >> 24) & 0x000000ff) + +#define CPUIDEBX_EVT_CORE (1 << 0) /* Core cycle */ +#define CPUIDEBX_EVT_INST (1 << 1) /* Instruction retired */ +#define CPUIDEBX_EVT_REFR (1 << 2) /* Reference cycles */ +#define CPUIDEBX_EVT_CACHE_REF (1 << 3) /* Last-level cache ref. */ +#define CPUIDEBX_EVT_CACHE_MIS (1 << 4) /* Last-level cache miss. */ +#define CPUIDEBX_EVT_BRANCH_INST (1 << 5) /* Branch instruction ret. */ +#define CPUIDEBX_EVT_BRANCH_MISP (1 << 6) /* Branch mispredict ret. */ + +#define CPUIDEDX_NUM_FC(cpuid) (((cpuid) >> 0) & 0x0000001f) +#define CPUIDEDX_BIT_FC(cpuid) (((cpuid) >> 5) & 0x000000ff) + +/* + * CPUID "extended features" bits (CPUID function 0x80000001): + * EDX bits, then ECX bits + */ + +#define CPUID_MPC 0x00080000 /* Multiprocessing Capable */ +#define CPUID_NXE 0x00100000 /* No-Execute Extension */ +#define CPUID_MMXX 0x00400000 /* AMD MMX Extensions */ +#define CPUID_FFXSR 0x02000000 /* fast FP/MMX save/restore */ +#define CPUID_PAGE1GB 0x04000000 /* 1-GByte pages */ +#define CPUID_RDTSCP 0x08000000 /* RDTSCP / IA32_TSC_AUX available */ +#define CPUID_LONG 0x20000000 /* long mode */ +#define CPUID_3DNOW2 0x40000000 /* 3DNow! Instruction Extension */ +#define CPUID_3DNOW 0x80000000 /* 3DNow! Instructions */ + +#define CPUIDECX_LAHF 0x00000001 /* LAHF and SAHF instructions */ +#define CPUIDECX_CMPLEG 0x00000002 /* Core MP legacy mode */ +#define CPUIDECX_SVM 0x00000004 /* Secure Virtual Machine */ +#define CPUIDECX_EAPICSP 0x00000008 /* Extended APIC space */ +#define CPUIDECX_AMCR8 0x00000010 /* LOCK MOV CR0 means MOV CR8 */ +#define CPUIDECX_ABM 0x00000020 /* LZCNT instruction */ +#define CPUIDECX_SSE4A 0x00000040 /* SSE4-A instruction set */ +#define CPUIDECX_MASSE 0x00000080 /* Misaligned SSE mode */ +#define CPUIDECX_3DNOWP 0x00000100 /* 3DNowPrefetch */ +#define CPUIDECX_OSVW 0x00000200 /* OS visible workaround */ +#define CPUIDECX_IBS 0x00000400 /* Instruction based sampling */ +#define CPUIDECX_XOP 0x00000800 /* Extended operating support */ +#define CPUIDECX_SKINIT 0x00001000 /* SKINIT and STGI are supported */ +#define CPUIDECX_WDT 0x00002000 /* Watchdog timer */ +/* Reserved 0x00004000 */ +#define CPUIDECX_LWP 0x00008000 /* Lightweight profiling support */ +#define CPUIDECX_FMA4 0x00010000 /* 4-operand FMA instructions */ +#define CPUIDECX_TCE 0x00020000 /* Translation Cache Extension */ +/* Reserved 0x00040000 */ +#define CPUIDECX_NODEID 0x00080000 /* Support for MSRC001C */ +/* Reserved 0x00100000 */ +#define CPUIDECX_TBM 0x00200000 /* Trailing bit manipulation instruction */ +#define CPUIDECX_TOPEXT 0x00400000 /* Topology extensions support */ +#define CPUIDECX_CPCTR 0x00800000 /* core performance counter ext */ +#define CPUIDECX_DBKP 0x04000000 /* DataBreakpointExtension */ +#define CPUIDECX_PERFTSC 0x08000000 /* performance time-stamp counter */ +#define CPUIDECX_PCTRL3 0x10000000 /* L3 performance counter ext */ +#define CPUIDECX_MWAITX 0x20000000 /* MWAITX/MONITORX */ + +/* + * "Advanced Power Management Information" bits (CPUID function 0x80000007): + * EDX bits. + */ + +#define CPUIDEDX_ITSC (1 << 8) /* Invariant TSC */ + +/* + * AMD CPUID function 0x80000008 EBX bits + */ +#define CPUIDEBX_IBPB (1ULL << 12) /* Speculation Control IBPB */ +#define CPUIDEBX_IBRS (1ULL << 14) /* Speculation Control IBRS */ +#define CPUIDEBX_STIBP (1ULL << 15) /* Speculation Control STIBP */ +#define CPUIDEBX_IBRS_ALWAYSON (1ULL << 16) /* IBRS always on mode */ +#define CPUIDEBX_STIBP_ALWAYSON (1ULL << 17) /* STIBP always on mode */ +#define CPUIDEBX_IBRS_PREF (1ULL << 18) /* IBRS preferred */ +#define CPUIDEBX_SSBD (1ULL << 24) /* Speculation Control SSBD */ +#define CPUIDEBX_VIRT_SSBD (1ULL << 25) /* Virt Spec Control SSBD */ +#define CPUIDEBX_SSBD_NOTREQ (1ULL << 26) /* SSBD not required */ + +#define CPUID2FAMILY(cpuid) (((cpuid) >> 8) & 15) +#define CPUID2MODEL(cpuid) (((cpuid) >> 4) & 15) +#define CPUID2STEPPING(cpuid) ((cpuid) & 15) + +#define CPUID(code, eax, ebx, ecx, edx) \ + __asm volatile("cpuid" \ + : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \ + : "a" (code)) +#define CPUID_LEAF(code, leaf, eax, ebx, ecx, edx) \ + __asm volatile("cpuid" \ + : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \ + : "a" (code), "c" (leaf)) + + +/* + * Model-specific registers for the i386 family + */ +#define MSR_P5_MC_ADDR 0x000 +#define MSR_P5_MC_TYPE 0x001 +#define MSR_TSC 0x010 +#define P5MSR_CTRSEL 0x011 /* P5 only (trap on P6) */ +#define P5MSR_CTR0 0x012 /* P5 only (trap on P6) */ +#define P5MSR_CTR1 0x013 /* P5 only (trap on P6) */ +#define MSR_PLATFORM_ID 0x017 /* Platform ID for microcode */ +#define MSR_APICBASE 0x01b +#define APICBASE_BSP 0x100 +#define APICBASE_ENABLE_X2APIC 0x400 +#define APICBASE_GLOBAL_ENABLE 0x800 +#define MSR_EBL_CR_POWERON 0x02a +#define MSR_EBC_FREQUENCY_ID 0x02c /* Pentium 4 only */ +#define MSR_TEST_CTL 0x033 +#define MSR_IA32_FEATURE_CONTROL 0x03a +#define MSR_SPEC_CTRL 0x048 /* Speculation Control IBRS / STIBP */ +#define SPEC_CTRL_IBRS (1ULL << 0) +#define SPEC_CTRL_STIBP (1ULL << 1) +#define SPEC_CTRL_SSBD (1ULL << 2) +#define MSR_PRED_CMD 0x049 /* Speculation Control IBPB */ +#define PRED_CMD_IBPB (1ULL << 0) +#define MSR_BIOS_UPDT_TRIG 0x079 +#define MSR_BBL_CR_D0 0x088 /* PII+ only */ +#define MSR_BBL_CR_D1 0x089 /* PII+ only */ +#define MSR_BBL_CR_D2 0x08a /* PII+ only */ +#define MSR_BIOS_SIGN 0x08b +#define MSR_PERFCTR0 0x0c1 +#define MSR_PERFCTR1 0x0c2 +#define P6MSR_CTR0 0x0c1 +#define P6MSR_CTR1 0x0c2 +#define MSR_FSB_FREQ 0x0cd /* Core Duo/Solo only */ +#define MSR_MTRRcap 0x0fe +#define MTRRcap_FIXED 0x100 /* bit 8 - fixed MTRRs supported */ +#define MTRRcap_WC 0x400 /* bit 10 - WC type supported */ +#define MTRRcap_SMRR 0x800 /* bit 11 - SMM range reg supported */ +#define MSR_ARCH_CAPABILITIES 0x10a +#define ARCH_CAP_RDCL_NO (1 << 0) /* Meltdown safe */ +#define ARCH_CAP_IBRS_ALL (1 << 1) /* enhanced IBRS */ +#define ARCH_CAP_RSBA (1 << 2) /* RSB Alternate */ +#define ARCH_CAP_SKIP_L1DFL_VMENTRY (1 << 3) +#define ARCH_CAP_SSB_NO (1 << 4) /* Spec St Byp safe */ +#define ARCH_CAP_MDS_NO (1 << 5) /* microarch data-sampling */ +#define ARCH_CAP_IF_PSCHANGE_MC_NO (1 << 6) /* PS MCE safe */ +#define ARCH_CAP_TSX_CTRL (1 << 7) /* has TSX_CTRL MSR */ +#define ARCH_CAP_TAA_NO (1 << 8) /* TSX AA safe */ +#define ARCH_CAP_MCU_CONTROL (1 << 9) /* has MCU_CTRL MSR */ +#define ARCH_CAP_MISC_PACKAGE_CTLS (1 << 10) /* has MISC_PKG_CTLS MSR */ +#define ARCH_CAP_ENERGY_FILTERING_CTL (1 << 11) /* r/w energy fltring bit */ +#define ARCH_CAP_DOITM (1 << 12) /* Data oprnd indpdnt tmng */ +#define ARCH_CAP_SBDR_SSDP_NO (1 << 13) /* SBDR/SSDP safe */ +#define ARCH_CAP_FBSDP_NO (1 << 14) /* FBSDP safe */ +#define ARCH_CAP_PSDP_NO (1 << 15) /* PSDP safe */ +#define ARCH_CAP_FB_CLEAR (1 << 17) /* MD_CLEAR covers FB */ +#define ARCH_CAP_FB_CLEAR_CTRL (1 << 18) +#define ARCH_CAP_RRSBA (1 << 19) /* has RRSBA if not dis */ +#define ARCH_CAP_BHI_NO (1 << 20) /* BHI safe */ +#define ARCH_CAP_XAPIC_DISABLE_STATUS (1 << 21) /* can disable xAPIC */ +#define ARCH_CAP_OVERCLOCKING_STATUS (1 << 23) /* has OVRCLCKNG_STAT MSR */ +#define ARCH_CAP_PBRSB_NO (1 << 24) /* PBSR safe */ +#define ARCH_CAP_GDS_CTRL (1 << 25) /* has GDS_MITG_DIS/LOCK */ +#define ARCH_CAP_GDS_NO (1 << 26) /* GDS safe */ +#define MSR_FLUSH_CMD 0x10b +#define FLUSH_CMD_L1D_FLUSH (1ULL << 0) +#define MSR_BBL_CR_ADDR 0x116 /* PII+ only */ +#define MSR_BBL_CR_DECC 0x118 /* PII+ only */ +#define MSR_BBL_CR_CTL 0x119 /* PII+ only */ +#define MSR_BBL_CR_TRIG 0x11a /* PII+ only */ +#define MSR_BBL_CR_BUSY 0x11b /* PII+ only */ +#define MSR_BBL_CR_CTR3 0x11e /* PII+ only */ +#define MSR_TSX_CTRL 0x122 +#define TSX_CTRL_RTM_DISABLE (1ULL << 0) +#define TSX_CTRL_TSX_CPUID_CLEAR (1ULL << 1) +#define MSR_MCU_OPT_CTRL 0x123 +#define RNGDS_MITG_DIS (1ULL << 0) +#define MSR_SYSENTER_CS 0x174 +#define MSR_SYSENTER_ESP 0x175 +#define MSR_SYSENTER_EIP 0x176 +#define MSR_MCG_CAP 0x179 +#define MSR_MCG_STATUS 0x17a +#define MSR_MCG_CTL 0x17b +#define P6MSR_CTRSEL0 0x186 +#define P6MSR_CTRSEL1 0x187 +#define MSR_PERF_STATUS 0x198 /* Pentium M */ +#define MSR_PERF_CTL 0x199 /* Pentium M */ +#define PERF_CTL_TURBO 0x100000000ULL /* bit 32 - turbo mode */ +#define MSR_THERM_CONTROL 0x19a +#define MSR_THERM_INTERRUPT 0x19b +#define MSR_THERM_STATUS 0x19c +#define MSR_THERM_STATUS_VALID_BIT 0x80000000 +#define MSR_THERM_STATUS_TEMP(msr) ((msr >> 16) & 0x7f) +#define MSR_THERM2_CTL 0x19d /* Pentium M */ +#define MSR_MISC_ENABLE 0x1a0 +/* + * MSR_MISC_ENABLE (0x1a0) + * + * Enable Fast Strings: enables fast REP MOVS/REP STORS (R/W) + * Enable TCC: Enable automatic thermal control circuit (R/W) + * Performance monitoring available: 1 if enabled (R/O) + * Branch trace storage unavailable: 1 if unsupported (R/O) + * Processor event based sampling unavailable: 1 if unsupported (R/O) + * Enhanced Intel SpeedStep technology enable: 1 to enable (R/W) + * Enable monitor FSM: 1 to enable MONITOR/MWAIT (R/W) + * Limit CPUID maxval: 1 to limit CPUID leaf nodes to 0x2 and lower (R/W) + * Enable xTPR message disable: 1 to disable xTPR messages + * XD bit disable: 1 to disable NX capability (bit 34, or bit 2 of %edx/%rdx) + */ +#define MISC_ENABLE_FAST_STRINGS (1 << 0) +#define MISC_ENABLE_TCC (1 << 3) +#define MISC_ENABLE_PERF_MON_AVAILABLE (1 << 7) +#define MISC_ENABLE_BTS_UNAVAILABLE (1 << 11) +#define MISC_ENABLE_PEBS_UNAVAILABLE (1 << 12) +#define MISC_ENABLE_EIST_ENABLED (1 << 16) +#define MISC_ENABLE_ENABLE_MONITOR_FSM (1 << 18) +#define MISC_ENABLE_LIMIT_CPUID_MAXVAL (1 << 22) +#define MISC_ENABLE_xTPR_MESSAGE_DISABLE (1 << 23) +#define MISC_ENABLE_XD_BIT_DISABLE (1 << 2) +/* + * for Core i Series and newer Xeons, see + * http://www.intel.com/content/dam/www/public/us/en/ + * documents/white-papers/cpu-monitoring-dts-peci-paper.pdf + */ +#define MSR_TEMPERATURE_TARGET 0x1a2 /* Core i Series, Newer Xeons */ +#define MSR_TEMPERATURE_TARGET_TJMAX(r) (((r) >> 16) & 0xff) +/* + * not documented anywhere, see intelcore_update_sensor() + * only available Core Duo and Core Solo Processors + */ +#define MSR_TEMPERATURE_TARGET_UNDOCUMENTED 0x0ee +#define MSR_TEMPERATURE_TARGET_LOW_BIT_UNDOCUMENTED 0x40000000 +#define MSR_DEBUGCTLMSR 0x1d9 +#define MSR_LASTBRANCHFROMIP 0x1db +#define MSR_LASTBRANCHTOIP 0x1dc +#define MSR_LASTINTFROMIP 0x1dd +#define MSR_LASTINTTOIP 0x1de +#define MSR_ROB_CR_BKUPTMPDR6 0x1e0 +#define MSR_MTRRvarBase 0x200 +#define MSR_MTRRfix64K_00000 0x250 +#define MSR_MTRRfix16K_80000 0x258 +#define MSR_MTRRfix4K_C0000 0x268 +#define MSR_CR_PAT 0x277 +#define MSR_MTRRdefType 0x2ff +#define MTRRdefType_FIXED_ENABLE 0x400 /* bit 10 - fixed MTRR enabled */ +#define MTRRdefType_ENABLE 0x800 /* bit 11 - MTRRs enabled */ +#define MSR_PERF_FIXED_CTR1 0x30a /* CPU_CLK_Unhalted.Core */ +#define MSR_PERF_FIXED_CTR2 0x30b /* CPU_CLK.Unhalted.Ref */ +#define MSR_PERF_FIXED_CTR_CTRL 0x38d +#define MSR_PERF_FIXED_CTR_FC_DIS 0x0 /* disable counter */ +#define MSR_PERF_FIXED_CTR_FC_1 0x1 /* count ring 1 */ +#define MSR_PERF_FIXED_CTR_FC_123 0x2 /* count rings 1,2,3 */ +#define MSR_PERF_FIXED_CTR_FC_ANY 0x3 /* count everything */ +#define MSR_PERF_FIXED_CTR_FC_MASK 0x3 +#define MSR_PERF_FIXED_CTR_FC(_i, _v) ((_v) << (4 * (_i))) +#define MSR_PERF_FIXED_CTR_ANYTHR(_i) (0x4 << (4 * (_i))) +#define MSR_PERF_FIXED_CTR_INT(_i) (0x8 << (4 * (_i))) +#define MSR_PERF_GLOBAL_CTRL 0x38f +#define MSR_PERF_GLOBAL_CTR1_EN (1ULL << 33) +#define MSR_PERF_GLOBAL_CTR2_EN (1ULL << 34) +#define MSR_MC0_CTL 0x400 +#define MSR_MC0_STATUS 0x401 +#define MSR_MC0_ADDR 0x402 +#define MSR_MC0_MISC 0x403 +#define MSR_MC1_CTL 0x404 +#define MSR_MC1_STATUS 0x405 +#define MSR_MC1_ADDR 0x406 +#define MSR_MC1_MISC 0x407 +#define MSR_MC2_CTL 0x408 +#define MSR_MC2_STATUS 0x409 +#define MSR_MC2_ADDR 0x40a +#define MSR_MC2_MISC 0x40b +#define MSR_MC4_CTL 0x40c +#define MSR_MC4_STATUS 0x40d +#define MSR_MC4_ADDR 0x40e +#define MSR_MC4_MISC 0x40f +#define MSR_MC3_CTL 0x410 +#define MSR_MC3_STATUS 0x411 +#define MSR_MC3_ADDR 0x412 +#define MSR_MC3_MISC 0x413 + +/* VIA MSRs */ +#define MSR_CENT_TMTEMPERATURE 0x1423 /* Thermal monitor temperature */ +#define MSR_C7M_TMTEMPERATURE 0x1169 + +/* AMD MSRs */ +#define MSR_K6_EPMR 0xc0000086 +#define MSR_K7_EVNTSEL0 0xc0010000 +#define MSR_K7_EVNTSEL1 0xc0010001 +#define MSR_K7_EVNTSEL2 0xc0010002 +#define MSR_K7_EVNTSEL3 0xc0010003 +#define MSR_K7_PERFCTR0 0xc0010004 +#define MSR_K7_PERFCTR1 0xc0010005 +#define MSR_K7_PERFCTR2 0xc0010006 +#define MSR_K7_PERFCTR3 0xc0010007 + +/* + * AMD K8 (Opteron) MSRs. + */ +#define MSR_PATCH_LEVEL 0x0000008b +#define MSR_SYSCFG 0xc0000010 + +#define MSR_EFER 0xc0000080 /* Extended feature enable */ +#define EFER_SCE 0x00000001 /* SYSCALL extension */ +#define EFER_LME 0x00000100 /* Long Mode Active */ +#define EFER_LMA 0x00000400 /* Long Mode Enabled */ +#define EFER_NXE 0x00000800 /* No-Execute Enabled */ +#define EFER_SVME 0x00001000 /* SVM Enabled */ + +#define MSR_STAR 0xc0000081 /* 32 bit syscall gate addr */ +#define MSR_LSTAR 0xc0000082 /* 64 bit syscall gate addr */ +#define MSR_CSTAR 0xc0000083 /* compat syscall gate addr */ +#define MSR_SFMASK 0xc0000084 /* flags to clear on syscall */ + +#define MSR_FSBASE 0xc0000100 /* 64bit offset for fs: */ +#define MSR_GSBASE 0xc0000101 /* 64bit offset for gs: */ +#define MSR_KERNELGSBASE 0xc0000102 /* storage for swapgs ins */ +#define MSR_PATCH_LOADER 0xc0010020 +#define MSR_INT_PEN_MSG 0xc0010055 /* Interrupt pending message */ + +#define MSR_DE_CFG 0xc0011029 /* Decode Configuration */ +#define DE_CFG_721 0x00000001 /* errata 721 */ +#define DE_CFG_SERIALIZE_LFENCE (1 << 1) /* Enable serializing lfence */ +#define DE_CFG_SERIALIZE_9 (1 << 9) /* Zenbleed chickenbit */ + +#define IPM_C1E_CMP_HLT 0x10000000 +#define IPM_SMI_CMP_HLT 0x08000000 + +/* + * These require a 'passcode' for access. See cpufunc.h. + */ +#define MSR_HWCR 0xc0010015 +#define HWCR_FFDIS 0x00000040 + +#define MSR_NB_CFG 0xc001001f +#define NB_CFG_DISIOREQLOCK 0x0000000000000004ULL +#define NB_CFG_DISDATMSK 0x0000001000000000ULL + +#define MSR_LS_CFG 0xc0011020 +#define LS_CFG_DIS_LS2_SQUISH 0x02000000 + +#define MSR_IC_CFG 0xc0011021 +#define IC_CFG_DIS_SEQ_PREFETCH 0x00000800 + +#define MSR_DC_CFG 0xc0011022 +#define DC_CFG_DIS_CNV_WC_SSO 0x00000004 +#define DC_CFG_DIS_SMC_CHK_BUF 0x00000400 + +#define MSR_BU_CFG 0xc0011023 +#define BU_CFG_THRL2IDXCMPDIS 0x0000080000000000ULL +#define BU_CFG_WBPFSMCCHKDIS 0x0000200000000000ULL +#define BU_CFG_WBENHWSBDIS 0x0001000000000000ULL + +/* + * Constants related to MTRRs + */ +#define MTRR_N64K 8 /* numbers of fixed-size entries */ +#define MTRR_N16K 16 +#define MTRR_N4K 64 + +/* + * the following four 3-byte registers control the non-cacheable regions. + * These registers must be written as three separate bytes. + * + * NCRx+0: A31-A24 of starting address + * NCRx+1: A23-A16 of starting address + * NCRx+2: A15-A12 of starting address | NCR_SIZE_xx. + * + * The non-cacheable region's starting address must be aligned to the + * size indicated by the NCR_SIZE_xx field. + */ +#define NCR1 0xc4 +#define NCR2 0xc7 +#define NCR3 0xca +#define NCR4 0xcd + +#define NCR_SIZE_0K 0 +#define NCR_SIZE_4K 1 +#define NCR_SIZE_8K 2 +#define NCR_SIZE_16K 3 +#define NCR_SIZE_32K 4 +#define NCR_SIZE_64K 5 +#define NCR_SIZE_128K 6 +#define NCR_SIZE_256K 7 +#define NCR_SIZE_512K 8 +#define NCR_SIZE_1M 9 +#define NCR_SIZE_2M 10 +#define NCR_SIZE_4M 11 +#define NCR_SIZE_8M 12 +#define NCR_SIZE_16M 13 +#define NCR_SIZE_32M 14 +#define NCR_SIZE_4G 15 + +/* + * Performance monitor events. + * + * Note that 586-class and 686-class CPUs have different performance + * monitors available, and they are accessed differently: + * + * 686-class: `rdpmc' instruction + * 586-class: `rdmsr' instruction, CESR MSR + * + * The descriptions of these events are too lengthy to include here. + * See Appendix A of "Intel Architecture Software Developer's + * Manual, Volume 3: System Programming" for more information. + */ + +/* + * 586-class CESR MSR format. Lower 16 bits is CTR0, upper 16 bits + * is CTR1. + */ + +#define PMC5_CESR_EVENT 0x003f +#define PMC5_CESR_OS 0x0040 +#define PMC5_CESR_USR 0x0080 +#define PMC5_CESR_E 0x0100 +#define PMC5_CESR_P 0x0200 + +/* + * 686-class Event Selector MSR format. + */ + +#define PMC6_EVTSEL_EVENT 0x000000ff +#define PMC6_EVTSEL_UNIT 0x0000ff00 +#define PMC6_EVTSEL_UNIT_SHIFT 8 +#define PMC6_EVTSEL_USR (1 << 16) +#define PMC6_EVTSEL_OS (1 << 17) +#define PMC6_EVTSEL_E (1 << 18) +#define PMC6_EVTSEL_PC (1 << 19) +#define PMC6_EVTSEL_INT (1 << 20) +#define PMC6_EVTSEL_EN (1 << 22) /* PerfEvtSel0 only */ +#define PMC6_EVTSEL_INV (1 << 23) +#define PMC6_EVTSEL_COUNTER_MASK 0xff000000 +#define PMC6_EVTSEL_COUNTER_MASK_SHIFT 24 + +/* Data Cache Unit */ +#define PMC6_DATA_MEM_REFS 0x43 +#define PMC6_DCU_LINES_IN 0x45 +#define PMC6_DCU_M_LINES_IN 0x46 +#define PMC6_DCU_M_LINES_OUT 0x47 +#define PMC6_DCU_MISS_OUTSTANDING 0x48 + +/* Instruction Fetch Unit */ +#define PMC6_IFU_IFETCH 0x80 +#define PMC6_IFU_IFETCH_MISS 0x81 +#define PMC6_ITLB_MISS 0x85 +#define PMC6_IFU_MEM_STALL 0x86 +#define PMC6_ILD_STALL 0x87 + +/* L2 Cache */ +#define PMC6_L2_IFETCH 0x28 +#define PMC6_L2_LD 0x29 +#define PMC6_L2_ST 0x2a +#define PMC6_L2_LINES_IN 0x24 +#define PMC6_L2_LINES_OUT 0x26 +#define PMC6_L2_M_LINES_INM 0x25 +#define PMC6_L2_M_LINES_OUTM 0x27 +#define PMC6_L2_RQSTS 0x2e +#define PMC6_L2_ADS 0x21 +#define PMC6_L2_DBUS_BUSY 0x22 +#define PMC6_L2_DBUS_BUSY_RD 0x23 + +/* External Bus Logic */ +#define PMC6_BUS_DRDY_CLOCKS 0x62 +#define PMC6_BUS_LOCK_CLOCKS 0x63 +#define PMC6_BUS_REQ_OUTSTANDING 0x60 +#define PMC6_BUS_TRAN_BRD 0x65 +#define PMC6_BUS_TRAN_RFO 0x66 +#define PMC6_BUS_TRANS_WB 0x67 +#define PMC6_BUS_TRAN_IFETCH 0x68 +#define PMC6_BUS_TRAN_INVAL 0x69 +#define PMC6_BUS_TRAN_PWR 0x6a +#define PMC6_BUS_TRANS_P 0x6b +#define PMC6_BUS_TRANS_IO 0x6c +#define PMC6_BUS_TRAN_DEF 0x6d +#define PMC6_BUS_TRAN_BURST 0x6e +#define PMC6_BUS_TRAN_ANY 0x70 +#define PMC6_BUS_TRAN_MEM 0x6f +#define PMC6_BUS_DATA_RCV 0x64 +#define PMC6_BUS_BNR_DRV 0x61 +#define PMC6_BUS_HIT_DRV 0x7a +#define PMC6_BUS_HITM_DRDV 0x7b +#define PMC6_BUS_SNOOP_STALL 0x7e + +/* Floating Point Unit */ +#define PMC6_FLOPS 0xc1 +#define PMC6_FP_COMP_OPS_EXE 0x10 +#define PMC6_FP_ASSIST 0x11 +#define PMC6_MUL 0x12 +#define PMC6_DIV 0x12 +#define PMC6_CYCLES_DIV_BUSY 0x14 + +/* Memory Ordering */ +#define PMC6_LD_BLOCKS 0x03 +#define PMC6_SB_DRAINS 0x04 +#define PMC6_MISALIGN_MEM_REF 0x05 +#define PMC6_EMON_KNI_PREF_DISPATCHED 0x07 /* P-III only */ +#define PMC6_EMON_KNI_PREF_MISS 0x4b /* P-III only */ + +/* Instruction Decoding and Retirement */ +#define PMC6_INST_RETIRED 0xc0 +#define PMC6_UOPS_RETIRED 0xc2 +#define PMC6_INST_DECODED 0xd0 +#define PMC6_EMON_KNI_INST_RETIRED 0xd8 +#define PMC6_EMON_KNI_COMP_INST_RET 0xd9 + +/* Interrupts */ +#define PMC6_HW_INT_RX 0xc8 +#define PMC6_CYCLES_INT_MASKED 0xc6 +#define PMC6_CYCLES_INT_PENDING_AND_MASKED 0xc7 + +/* Branches */ +#define PMC6_BR_INST_RETIRED 0xc4 +#define PMC6_BR_MISS_PRED_RETIRED 0xc5 +#define PMC6_BR_TAKEN_RETIRED 0xc9 +#define PMC6_BR_MISS_PRED_TAKEN_RET 0xca +#define PMC6_BR_INST_DECODED 0xe0 +#define PMC6_BTB_MISSES 0xe2 +#define PMC6_BR_BOGUS 0xe4 +#define PMC6_BACLEARS 0xe6 + +/* Stalls */ +#define PMC6_RESOURCE_STALLS 0xa2 +#define PMC6_PARTIAL_RAT_STALLS 0xd2 + +/* Segment Register Loads */ +#define PMC6_SEGMENT_REG_LOADS 0x06 + +/* Clocks */ +#define PMC6_CPU_CLK_UNHALTED 0x79 + +/* MMX Unit */ +#define PMC6_MMX_INSTR_EXEC 0xb0 /* Celeron, P-II, P-IIX only */ +#define PMC6_MMX_SAT_INSTR_EXEC 0xb1 /* P-II and P-III only */ +#define PMC6_MMX_UOPS_EXEC 0xb2 /* P-II and P-III only */ +#define PMC6_MMX_INSTR_TYPE_EXEC 0xb3 /* P-II and P-III only */ +#define PMC6_FP_MMX_TRANS 0xcc /* P-II and P-III only */ +#define PMC6_MMX_ASSIST 0xcd /* P-II and P-III only */ +#define PMC6_MMX_INSTR_RET 0xc3 /* P-II only */ + +/* Segment Register Renaming */ +#define PMC6_SEG_RENAME_STALLS 0xd4 /* P-II and P-III only */ +#define PMC6_SEG_REG_RENAMES 0xd5 /* P-II and P-III only */ +#define PMC6_RET_SEG_RENAMES 0xd6 /* P-II and P-III only */ + +/* VIA C3 crypto featureset: for i386_has_xcrypt */ +#define C3_HAS_AES 1 /* cpu has AES */ +#define C3_HAS_SHA 2 /* cpu has SHA1 & SHA256 */ +#define C3_HAS_MM 4 /* cpu has RSA instructions */ +#define C3_HAS_AESCTR 8 /* cpu has AES-CTR instructions */ + +/* Centaur Extended Feature flags */ +#define C3_CPUID_HAS_RNG 0x000004 +#define C3_CPUID_DO_RNG 0x000008 +#define C3_CPUID_HAS_ACE 0x000040 +#define C3_CPUID_DO_ACE 0x000080 +#define C3_CPUID_HAS_ACE2 0x000100 +#define C3_CPUID_DO_ACE2 0x000200 +#define C3_CPUID_HAS_PHE 0x000400 +#define C3_CPUID_DO_PHE 0x000800 +#define C3_CPUID_HAS_PMM 0x001000 +#define C3_CPUID_DO_PMM 0x002000 + +/* VIA C3 xcrypt-* instruction context control options */ +#define C3_CRYPT_CWLO_ROUND_M 0x0000000f +#define C3_CRYPT_CWLO_ALG_M 0x00000070 +#define C3_CRYPT_CWLO_ALG_AES 0x00000000 +#define C3_CRYPT_CWLO_KEYGEN_M 0x00000080 +#define C3_CRYPT_CWLO_KEYGEN_HW 0x00000000 +#define C3_CRYPT_CWLO_KEYGEN_SW 0x00000080 +#define C3_CRYPT_CWLO_NORMAL 0x00000000 +#define C3_CRYPT_CWLO_INTERMEDIATE 0x00000100 +#define C3_CRYPT_CWLO_ENCRYPT 0x00000000 +#define C3_CRYPT_CWLO_DECRYPT 0x00000200 +#define C3_CRYPT_CWLO_KEY128 0x0000000a /* 128bit, 10 rds */ +#define C3_CRYPT_CWLO_KEY192 0x0000040c /* 192bit, 12 rds */ +#define C3_CRYPT_CWLO_KEY256 0x0000080e /* 256bit, 15 rds */ + +/* Intel Silicon Debug */ +#define IA32_DEBUG_INTERFACE 0xc80 +#define IA32_DEBUG_INTERFACE_ENABLE 0x00000001 +#define IA32_DEBUG_INTERFACE_LOCK 0x40000000 +#define IA32_DEBUG_INTERFACE_MASK 0x80000000 + +/* + * PAT + */ +#define PATENTRY(n, type) ((uint64_t)type << ((n) * 8)) +#define PAT_UC 0x0UL +#define PAT_WC 0x1UL +#define PAT_WT 0x4UL +#define PAT_WP 0x5UL +#define PAT_WB 0x6UL +#define PAT_UCMINUS 0x7UL + +/* + * XSAVE subfeatures (cpuid 0xd, leaf 1) + */ +#define XSAVE_XSAVEOPT 0x1UL +#define XSAVE_XSAVEC 0x2UL +#define XSAVE_XGETBV1 0x4UL +#define XSAVE_XSAVES 0x8UL \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/spinlock.h b/lib/libc/include/x86-openbsd-none/i386/spinlock.h new file mode 100644 index 000000000000..f3fe78c83412 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/spinlock.h @@ -0,0 +1,10 @@ +/* $OpenBSD: spinlock.h,v 1.3 2017/09/05 02:40:54 guenther Exp $ */ + +#ifndef _MACHINE_SPINLOCK_H_ +#define _MACHINE_SPINLOCK_H_ + +#define _ATOMIC_LOCK_UNLOCKED (0) +#define _ATOMIC_LOCK_LOCKED (1) +typedef int _atomic_lock_t; + +#endif \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/sysarch.h b/lib/libc/include/x86-openbsd-none/i386/sysarch.h new file mode 100644 index 000000000000..871c60d946ba --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/sysarch.h @@ -0,0 +1,38 @@ +/* $OpenBSD: sysarch.h,v 1.14 2016/03/24 04:56:08 guenther Exp $ */ +/* $NetBSD: sysarch.h,v 1.8 1996/01/08 13:51:44 mycroft Exp $ */ + +#ifndef _MACHINE_SYSARCH_H_ +#define _MACHINE_SYSARCH_H_ + +/* + * Architecture specific syscalls (i386) + */ +#define I386_IOPL 2 +#define I386_VM86 5 +#define I386_GET_FSBASE 6 +#define I386_SET_FSBASE 7 +#define I386_GET_GSBASE 8 +#define I386_SET_GSBASE 9 + +struct i386_iopl_args { + int iopl; +}; + +#ifdef _KERNEL +uint32_t i386_get_threadbase(struct proc *, int); +int i386_set_threadbase(struct proc *, uint32_t, int); +#else + +#include + +__BEGIN_DECLS +int i386_iopl(int); +int i386_get_fsbase(void **); +int i386_set_fsbase(void *); +int i386_get_gsbase(void **); +int i386_set_gsbase(void *); +int sysarch(int, void *); +__END_DECLS +#endif + +#endif /* !_MACHINE_SYSARCH_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/tcb.h b/lib/libc/include/x86-openbsd-none/i386/tcb.h new file mode 100644 index 000000000000..eb8003e2605b --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/tcb.h @@ -0,0 +1,51 @@ +/* $OpenBSD: tcb.h,v 1.4 2016/09/04 08:49:35 guenther Exp $ */ +/* + * Copyright (c) 2011 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TCB_H_ +#define _MACHINE_TCB_H_ + +#ifdef _KERNEL + +#include +#include + +#define TCB_GET(p) \ + ((void *)i386_get_threadbase(p, TSEG_GS)) +#define TCB_SET(p, addr) \ + i386_set_threadbase(p, (uint32_t)(addr), TSEG_GS) + +#else /* _KERNEL */ + +/* ELF TLS ABI calls for big TCB, with static TLS data at negative offsets */ +#define TLS_VARIANT 2 + +/* Read a slot from the TCB */ +static inline void * +__i386_read_tcb(int offset) +{ + void *val; + __asm__ ("movl %%gs:(%1),%0" : "=r" (val) : "r" (offset)); + return val; +} + +/* Get a pointer to the TCB itself */ +#define TCB_GET() __i386_read_tcb(0) + +/* Setting the TCB pointer can only be done via syscall, so no TCB_SET() */ + +#endif /* _KERNEL */ +#endif /* _MACHINE_TCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/timetc.h b/lib/libc/include/x86-openbsd-none/i386/timetc.h new file mode 100644 index 000000000000..9af8a41ca23f --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/timetc.h @@ -0,0 +1,23 @@ +/* $OpenBSD: timetc.h,v 1.1 2020/07/06 13:33:07 pirofti Exp $ */ +/* + * Copyright (c) 2020 Paul Irofti + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TIMETC_H_ +#define _MACHINE_TIMETC_H_ + +#define TC_LAST 0 + +#endif /* _MACHINE_TIMETC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/trap.h b/lib/libc/include/x86-openbsd-none/i386/trap.h new file mode 100644 index 000000000000..6a91b82f3eff --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/trap.h @@ -0,0 +1,65 @@ +/* $OpenBSD: trap.h,v 1.6 2015/06/28 01:11:27 guenther Exp $ */ +/* $NetBSD: trap.h,v 1.4 1994/10/27 04:16:30 cgd Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)trap.h 5.4 (Berkeley) 5/9/91 + */ + +/* + * Trap type values + * also known in trap.c for name strings + */ + +#define T_PRIVINFLT 0 /* privileged instruction */ +#define T_BPTFLT 1 /* breakpoint trap */ +#define T_ARITHTRAP 2 /* arithmetic trap */ +#define T_RESERVED 3 /* reserved fault base */ +#define T_PROTFLT 4 /* protection fault */ +#define T_TRCTRAP 5 /* trace trap */ +#define T_PAGEFLT 6 /* page fault */ +#define T_ALIGNFLT 7 /* alignment fault */ +#define T_DIVIDE 8 /* integer divide fault */ +#define T_NMI 9 /* non-maskable interrupt */ +#define T_OFLOW 10 /* overflow trap */ +#define T_BOUND 11 /* bounds check fault */ +#define T_DNA 12 /* device not available fault */ +#define T_DOUBLEFLT 13 /* double fault */ +#define T_FPOPFLT 14 /* fp coprocessor operand fetch fault (![P]Pro)*/ +#define T_TSSFLT 15 /* invalid tss fault */ +#define T_SEGNPFLT 16 /* segment not present fault */ +#define T_STKFLT 17 /* stack fault */ +#define T_MACHK 18 /* machine check ([P]Pro) */ +#define T_XFTRAP 19 /* SIMD FP exception */ + +/* Trap's coming from user mode */ +#define T_USER 0x100 \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/tss.h b/lib/libc/include/x86-openbsd-none/i386/tss.h new file mode 100644 index 000000000000..d2e5f750b678 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/tss.h @@ -0,0 +1,74 @@ +/* $OpenBSD: tss.h,v 1.12 2018/06/22 13:21:14 bluhm Exp $ */ +/* $NetBSD: tss.h,v 1.6 1995/10/11 04:20:28 mycroft Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tss.h 5.4 (Berkeley) 1/18/91 + */ + +#ifndef _MACHINE_TSS_H_ +#define _MACHINE_TSS_H_ + +/* + * Intel 386 Context Data Type + */ + +struct i386tss { + int __tss_link; + int tss_esp0; /* kernel stack pointer at privilege level 0 */ + int tss_ss0; /* kernel stack segment at privilege level 0 */ + int __tss_esp1; + int __tss_ss1; + int __tss_esp2; + int __tss_ss2; + int tss_cr3; + int tss_eip; + int tss_eflags; + int tss_eax; + int tss_ecx; + int tss_edx; + int tss_ebx; + int tss_esp; + int tss_ebp; + int tss_esi; + int tss_edi; + int tss_es; + int tss_cs; + int tss_ss; + int tss_ds; + int tss_fs; + int tss_gs; + int tss_ldt; + int tss_ioopt; /* options and I/O permission map offset */ +}; + +#endif /* _MACHINE_TSS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/vga_post.h b/lib/libc/include/x86-openbsd-none/i386/vga_post.h new file mode 100644 index 000000000000..7207b11c31df --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/vga_post.h @@ -0,0 +1,43 @@ +/* $NetBSD: vga_post.h,v 1.2 2008/03/29 17:40:22 jmcneill Exp $ */ +/* $OpenBSD: vga_post.h,v 1.2 2011/03/23 16:54:35 pirofti Exp $ */ + +/*- + * Copyright (c) 2007 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_VGA_POST_H_ +#define _MACHINE_VGA_POST_H_ + +#ifdef _KERNEL +struct vga_post; + +struct vga_post *vga_post_init(int, int, int); +void vga_post_free(struct vga_post *); +void vga_post_call(struct vga_post *); +#endif +#endif \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/vmmvar.h b/lib/libc/include/x86-openbsd-none/i386/vmmvar.h new file mode 100644 index 000000000000..6528cb81029e --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/vmmvar.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2014 Mike Larkin + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define VMM_HV_SIGNATURE "OpenBSDVMM58" \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/i386/vmparam.h b/lib/libc/include/x86-openbsd-none/i386/vmparam.h new file mode 100644 index 000000000000..3e7cc4f4bbc9 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/i386/vmparam.h @@ -0,0 +1,108 @@ +/* $OpenBSD: vmparam.h,v 1.57 2021/03/16 18:04:16 kurt Exp $ */ +/* $NetBSD: vmparam.h,v 1.15 1994/10/27 04:16:34 cgd Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vmparam.h 5.9 (Berkeley) 5/12/91 + */ + +#ifndef _MACHINE_VMPARAM_H_ +#define _MACHINE_VMPARAM_H_ +/* + * Machine dependent constants for 386. + */ + +#define USRSTACK VM_MAXUSER_ADDRESS + +/* + * Virtual memory related constants, all in bytes + */ +#define MAXTSIZ (256*1024*1024) /* max text size */ +#ifndef DFLDSIZ +#define DFLDSIZ (64*1024*1024) /* initial data size limit */ +#endif +#ifndef MAXDSIZ +#define MAXDSIZ (3UL*1024*1024*1024) /* max data size */ +#endif +#ifndef BRKSIZ +#define BRKSIZ (128*1024*1024) /* heap gap size */ +#endif +#ifndef DFLSSIZ +#define DFLSSIZ (4*1024*1024) /* initial stack size limit */ +#endif +#ifndef MAXSSIZ +#define MAXSSIZ (32*1024*1024) /* max stack size */ +#endif + +#define STACKGAP_RANDOM 256*1024 + +/* I386 has a line where all code is executable: 0 - I386_MAX_EXE_ADDR */ +#define I386_MAX_EXE_ADDR 0x20000000 /* exec line */ + +/* map PIE into 320MB - 448MB address range */ +#define VM_PIE_MIN_ADDR 0x14000000 +#define VM_PIE_MAX_ADDR 0x1C000000 + +/* + * Size of shared memory map + */ +#ifndef SHMMAXPGS +#define SHMMAXPGS 8192 +#endif + +/* + * Size of User Raw I/O map + */ +#define USRIOSIZE 300 + +/* + * Specific addresses being unmapped and used as fillers for free memory. + */ +#define DEADBEEF0 0xefffeecc /* malloc's filler */ +#define DEADBEEF1 0xefffaabb /* pool's filler */ + +/* user/kernel map constants */ +#define VM_MIN_ADDRESS ((vaddr_t)PAGE_SIZE) +#define VM_MAXUSER_ADDRESS ((vaddr_t)((PDSLOT_PTE<= 3 +typedef __builtin_va_list __va_list; +#else +typedef char * __va_list; +#endif + +/* Wide character support types */ +#ifndef __cplusplus +typedef int __wchar_t; +#endif +typedef int __wint_t; +typedef int __rune_t; +typedef void * __wctrans_t; +typedef void * __wctype_t; + +#endif /* _MACHINE__TYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/acpiapm.h b/lib/libc/include/x86-openbsd-none/machine/acpiapm.h new file mode 100644 index 000000000000..6921c56fd28f --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/acpiapm.h @@ -0,0 +1,22 @@ +/* $OpenBSD: acpiapm.h,v 1.1 2007/11/25 15:45:17 tedu Exp $ */ +/* + * Copyright (c) 2007 Ted Unangst + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +extern int (*acpiapm_open)(dev_t, int, int, struct proc *); +extern int (*acpiapm_close)(dev_t, int, int, struct proc *); +extern int (*acpiapm_ioctl)(dev_t, u_long, caddr_t, int, struct proc *); +extern int (*acpiapm_kqfilter)(dev_t, struct knote *); \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/amdmsr.h b/lib/libc/include/x86-openbsd-none/machine/amdmsr.h new file mode 100644 index 000000000000..1a6027a5a36c --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/amdmsr.h @@ -0,0 +1,34 @@ +/* $OpenBSD: amdmsr.h,v 1.4 2011/03/23 16:54:35 pirofti Exp $ */ + +/* + * Copyright (c) 2008 Marc Balmer + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_AMDMSR_H_ +#define _MACHINE_AMDMSR_H_ + +struct amdmsr_req { + u_int32_t addr; /* 32-bit MSR address */ + u_int64_t val; /* 64-bit MSR value */ +}; + +#define RDMSR _IOWR('M', 0, struct amdmsr_req) +#define WRMSR _IOW('M', 1, struct amdmsr_req) + +#ifdef _KERNEL +int amdmsr_probe(void); +#endif + +#endif /* !_MACHINE_AMDMSR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/apicvar.h b/lib/libc/include/x86-openbsd-none/machine/apicvar.h new file mode 100644 index 000000000000..754f54465e12 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/apicvar.h @@ -0,0 +1,54 @@ +/* $OpenBSD: apicvar.h,v 1.7 2025/09/05 16:57:48 kettenis Exp $ */ +/* $NetBSD: apicvar.h,v 1.1.2.3 2000/02/27 20:25:00 sommerfeld Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_APICVAR_H_ +#define _MACHINE_APICVAR_H_ + +#include + +struct apic_attach_args { + const char *aaa_name; + int apic_id; + int apic_version; + int flags; +#define IOAPIC_PICMODE 0x01 +#define IOAPIC_VWIRE 0x02 + bus_space_tag_t apic_memt; + bus_addr_t apic_address; + int apic_vecbase; +}; + +void apic_format_redir(char *, char *, int, u_int32_t, u_int32_t); + +#endif /* !_MACHINE_APICVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/apmvar.h b/lib/libc/include/x86-openbsd-none/machine/apmvar.h new file mode 100644 index 000000000000..4d29641e7a1b --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/apmvar.h @@ -0,0 +1,303 @@ +/* $OpenBSD: apmvar.h,v 1.22 2019/01/22 02:36:30 phessler Exp $ */ + +/* + * Copyright (c) 1995 John T. Kohl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _MACHINE_APMVAR_H_ +#define _MACHINE_APMVAR_H_ + +#include + +/* Advanced Power Management (v1.0 and v1.1 specification) + * functions/defines/etc. + */ + +#define APM_VERSION 0x0102 + +/* + * APM info word from boot loader + */ +#define APM_16BIT_SUPPORTED 0x00010000 +#define APM_32BIT_SUPPORTED 0x00020000 +#define APM_IDLE_SLOWS 0x00040000 +#define APM_BIOS_PM_DISABLED 0x00080000 +#define APM_BIOS_PM_DISENGAGED 0x00100000 +#define APM_MAJOR(f) (((f) >> 8) & 0xff) +#define APM_MINOR(f) ((f) & 0xff) +#define APM_VERMASK 0x0000ffff +#define APM_NOCLI 0x00010000 +#define APM_BEBATT 0x00020000 + +/* APM error codes */ +#define APM_ERR_CODE(regs) (((regs)->ax & 0xff00) >> 8) +#define APM_ERR_PM_DISABLED 0x01 +#define APM_ERR_REALALREADY 0x02 +#define APM_ERR_NOTCONN 0x03 +#define APM_ERR_16ALREADY 0x05 +#define APM_ERR_16NOTSUPP 0x06 +#define APM_ERR_32ALREADY 0x07 +#define APM_ERR_32NOTSUPP 0x08 +#define APM_ERR_UNRECOG_DEV 0x09 +#define APM_ERR_ERANGE 0x0A +#define APM_ERR_NOTENGAGED 0x0B +#define APM_ERR_EOPNOSUPP 0x0C +#define APM_ERR_RTIMER_DISABLED 0x0D +#define APM_ERR_UNABLE 0x60 +#define APM_ERR_NOEVENTS 0x80 +#define APM_ERR_NOT_PRESENT 0x86 + +#define APM_DEV_APM_BIOS 0x0000 +#define APM_DEV_ALLDEVS 0x0001 +/* device classes are high byte; device IDs go in low byte */ +#define APM_DEV_DISPLAY(x) (0x0100|((x)&0xff)) +#define APM_DEV_DISK(x) (0x0200|((x)&0xff)) +#define APM_DEV_PARALLEL(x) (0x0300|((x)&0xff)) +#define APM_DEV_SERIAL(x) (0x0400|((x)&0xff)) +#define APM_DEV_NETWORK(x) (0x0500|((x)&0xff)) +#define APM_DEV_PCMCIA(x) (0x0600|((x)&0xff)) +#define APM_DEV_BATTERIES(x) (0x8000|((x)&0xff)) +#define APM_DEV_ALLUNITS 0xff +/* 0x8100-0xDFFF - reserved */ +/* 0xE000-0xEFFF - OEM-defined */ +/* 0xF000-0xFFFF - reserved */ + +#define APM_INSTCHECK 0x5300 /* int15 only */ +#define APM_16BIT_SUPPORT 0x01 +#define APM_32BIT_SUPPORT 0x02 +#define APM_CPUIDLE_SLOW 0x04 +#define APM_DISABLED 0x08 +#define APM_DISENGAGED 0x10 + +#define APM_REAL_CONNECT 0x5301 /* int15 only */ +#define APM_PROT16_CONNECT 0x5302 /* int15 only */ +#define APM_PROT32_CONNECT 0x5303 /* int15 only */ +#define APM_DISCONNECT 0x5304 /* %bx = APM_DEV_APM_BIOS */ + +#define APM_CPU_IDLE 0x5305 +#define APM_CPU_BUSY 0x5306 + +#define APM_SET_PWR_STATE 0x5307 +#define APM_SYS_READY 0x0000 /* %cx */ +#define APM_SYS_STANDBY 0x0001 +#define APM_SYS_SUSPEND 0x0002 +#define APM_SYS_OFF 0x0003 +#define APM_LASTREQ_INPROG 0x0004 +#define APM_LASTREQ_REJECTED 0x0005 +/* 0x0006 - 0x001f Reserved system states */ +/* 0x0020 - 0x003f OEM-defined system states */ +/* 0x0040 - 0x007f OEM-defined device states */ +/* 0x0080 - 0xffff Reserved device states */ + +/* system standby is device ID (%bx) 0x0001, APM_SYS_STANDBY */ +/* system suspend is device ID (%bx) 0x0001, APM_SYS_SUSPEND */ + +#define APM_PWR_MGT_ENABLE 0x5308 +#define APM_MGT_ALL 0xffff /* %bx */ +#define APM_MGT_DISABLE 0x0 /* %cx */ +#define APM_MGT_ENABLE 0x1 + +#define APM_SYSTEM_DEFAULTS 0x5309 +#define APM_DEFAULTS_ALL 0xffff /* %bx */ + +#define APM_POWER_STATUS 0x530a +#define APM_AC_OFF 0x00 +#define APM_AC_ON 0x01 +#define APM_AC_BACKUP 0x02 +#define APM_AC_UNKNOWN 0xff +#define APM_BATT_HIGH 0x00 +#define APM_BATT_LOW 0x01 +#define APM_BATT_CRITICAL 0x02 +#define APM_BATT_CHARGING 0x03 +#define APM_BATT_UNKNOWN 0xff +#define APM_BATT_FLAG_HIGH 0x01 +#define APM_BATT_FLAG_LOW 0x02 +#define APM_BATT_FLAG_CRITICAL 0x04 +#define APM_BATT_FLAG_CHARGING 0x08 +#define APM_BATT_FLAG_NOBATTERY 0x10 +#define APM_BATT_FLAG_NOSYSBATT 0x80 +#define APM_BATT_LIFE_UNKNOWN 0xff +#define BATT_STATE(regp) ((regp)->bx & 0xff) +#define BATT_FLAGS(regp) (((regp)->cx & 0xff00) >> 8) +#define AC_STATE(regp) (((regp)->bx & 0xff00) >> 8) +#define BATT_LIFE(regp) ((regp)->cx & 0xff) /* in % */ +/* Return time in minutes. According to the APM 1.2 spec: + DX = Remaining battery life -- time units + Bit 15 = 0 Time units are seconds + = 1 Time units are minutes + Bits 14-0 = Number of seconds or minutes */ +#define BATT_REMAINING(regp) (((regp)->dx & 0x8000) ? \ + ((regp)->dx & 0x7fff) : \ + ((regp)->dx & 0x7fff)/60) +#define BATT_REM_VALID(regp) (((regp)->dx & 0xffff) != 0xffff) +#define BATT_COUNT(regp) ((regp)->si) + +#define APM_GET_PM_EVENT 0x530b +#define APM_NOEVENT 0x0000 +#define APM_STANDBY_REQ 0x0001 /* %bx on return */ +#define APM_SUSPEND_REQ 0x0002 +#define APM_NORMAL_RESUME 0x0003 +#define APM_CRIT_RESUME 0x0004 /* suspend/resume happened + without us */ +#define APM_BATTERY_LOW 0x0005 +#define APM_POWER_CHANGE 0x0006 +#define APM_UPDATE_TIME 0x0007 +#define APM_CRIT_SUSPEND_REQ 0x0008 +#define APM_USER_STANDBY_REQ 0x0009 +#define APM_USER_SUSPEND_REQ 0x000A +#define APM_SYS_STANDBY_RESUME 0x000B +#define APM_CAPABILITY_CHANGE 0x000C /* apm v1.2 */ +/* 0x000d - 0x00ff Reserved system events */ +#define APM_USER_HIBERNATE_REQ 0x000D +/* 0x0100 - 0x01ff Reserved device events */ +/* 0x0200 - 0x02ff OEM-defined APM events */ +/* 0x0300 - 0xffff Reserved */ +#define APM_EVENT_MASK 0xffff + +#define APM_EVENT_COMPOSE(t,i) ((((i) & 0x7fff) << 16)|((t) & APM_EVENT_MASK)) +#define APM_EVENT_TYPE(e) ((e) & APM_EVENT_MASK) +#define APM_EVENT_INDEX(e) ((e) >> 16) + +#define APM_GET_POWER_STATE 0x530c +#define APM_DEVICE_MGMT_ENABLE 0x530d + +#define APM_DRIVER_VERSION 0x530e +/* %bx should be DEV value (APM_DEV_APM_BIOS) + %ch = driver major vno + %cl = driver minor vno + return: %ah = conn major; %al = conn minor + */ +#define APM_CONN_MINOR(regp) ((regp)->ax & 0xff) +#define APM_CONN_MAJOR(regp) (((regp)->ax & 0xff00) >> 8) + +#define APM_PWR_MGT_ENGAGE 0x530F +#define APM_MGT_DISENGAGE 0x0 /* %cx */ +#define APM_MGT_ENGAGE 0x1 + +/* %bx - APM_DEV_APM_BIOS + * %bl - number of batteries + * %cx - capabilities + */ +#define APM_GET_CAPABILITIES 0x5310 +#define APM_NBATTERIES(regp) ((regp)->bx) +#define APM_GLOBAL_STANDBY 0x0001 +#define APM_GLOBAL_SUSPEND 0x0002 +#define APM_RTIMER_STANDBY 0x0004 /* resume time wakes up */ +#define APM_RTIMER_SUSPEND 0x0008 +#define APM_IRRING_STANDBY 0x0010 /* internal ring wakes up */ +#define APM_IRRING_SUSPEND 0x0020 +#define APM_PCCARD_STANDBY 0x0040 /* pccard wakes up */ +#define APM_PCCARD_SUSPEND 0x0080 + +/* %bx - APM_DEV_APM_BIOS + * %cl - function + * for %cl=2 (set resume timer) + * %ch - seconds in BCD + * %dh - hours in BCD + * %dl - minutes in BCD + * %si - month in BCD (high), day in BCD (low) + * %di - year in BCD + */ +#define APM_RESUME_TIMER 0x5311 +#define APM_RT_DISABLE 0x0 +#define APM_RT_GET 0x1 +#define APM_RT_SET 0x2 + +/* %bx - APM_DEV_APM_BIOS + * %cx - function + */ +#define APM_RESUME_ON_RING 0x5312 +#define APM_ROR_DISABLE 0x0 +#define APM_ROR_ENABLE 0x1 +#define APM_ROR_STATUS 0x2 + +/* %bx - APM_EDV_APM_BIOS + * %cx - function + */ +#define APM_INACTIVITY_TIMER 0x5313 +#define APM_IT_DISABLE 0x0 +#define APM_IT_ENABLE 0x1 +#define APM_IT_STATUS 0x2 + +/* %bh - function */ +#define APM_OEM 0x5380 +#define APM_OEM_INSTCHECK 0x7f /* %bx - OEM ID */ + +/* + * LP (Laptop Package) + * + * Copyright (C) 1994 by HOSOKAWA Tatsumi + * + * This software may be used, modified, copied, and distributed, in + * both source and binary form provided that the above copyright and + * these terms are retained. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with its + * use. + * + * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) + */ + +#define APM_BATTERY_ABSENT 4 + +struct apm_power_info { + u_char battery_state; + u_char ac_state; + u_char battery_life; + u_char spare1; + u_int minutes_left; /* estimate */ + u_int spare2[6]; +}; + +struct apm_ctl { + u_int dev; + u_int mode; +}; + +#define APM_IOC_REJECT _IOW('A', 0, struct apm_event_info) /* reject request # */ +#define APM_IOC_STANDBY _IO('A', 1) /* put system into standby */ +#define APM_IOC_SUSPEND _IO('A', 2) /* put system into suspend */ +#define APM_IOC_GETPOWER _IOR('A', 3, struct apm_power_info) /* fetch battery state */ +#define APM_IOC_DEV_CTL _IOW('A', 5, struct apm_ctl) /* put device into mode */ +#define APM_IOC_PRN_CTL _IOW('A', 6, int ) /* driver power status msg */ +#define APM_PRINT_ON 0 /* driver power status displayed */ +#define APM_PRINT_OFF 1 /* driver power status not displayed */ +#define APM_PRINT_PCT 2 /* driver power status only displayed + if the percentage changes */ +#define APM_IOC_STANDBY_REQ _IO('A', 7) /* request standby */ +#define APM_IOC_SUSPEND_REQ _IO('A', 8) /* request suspend */ +#define APM_IOC_HIBERNATE _IO('A', 9) /* put system into hibernate */ + + +#ifdef _KERNEL +extern void apm_cpu_busy(void); +extern void apm_cpu_idle(void); +extern void apminit(void); +int apm_set_powstate(u_int devid, u_int powstate); +#endif /* _KERNEL */ + +#endif /* _MACHINE_APMVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/asm.h b/lib/libc/include/x86-openbsd-none/machine/asm.h new file mode 100644 index 000000000000..c5b22ef4f4d1 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/asm.h @@ -0,0 +1,131 @@ +/* $OpenBSD: asm.h,v 1.19 2022/12/08 01:25:45 guenther Exp $ */ +/* $NetBSD: asm.h,v 1.7 1994/10/27 04:15:56 cgd Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)asm.h 5.5 (Berkeley) 5/7/91 + */ + +#ifndef _MACHINE_ASM_H_ +#define _MACHINE_ASM_H_ + +#ifdef __PIC__ +#define PIC_PROLOGUE \ + pushl %ebx; \ + call 666f; \ +666: \ + popl %ebx; \ + addl $_GLOBAL_OFFSET_TABLE_+[.-666b], %ebx +#define PIC_EPILOGUE \ + popl %ebx +#define PIC_PLT(x) x@PLT +#define PIC_GOT(x) x@GOT(%ebx) +#define PIC_GOTOFF(x) x@GOTOFF(%ebx) +#else +#define PIC_PROLOGUE +#define PIC_EPILOGUE +#define PIC_PLT(x) x +#define PIC_GOT(x) x +#define PIC_GOTOFF(x) x +#endif + +#define _C_LABEL(name) name +#define _ASM_LABEL(x) x + +#define CVAROFF(x, y) x + y + +#ifdef __STDC__ +# define __CONCAT(x,y) x ## y +# define __STRING(x) #x +#else +# define __CONCAT(x,y) x/**/y +# define __STRING(x) "x" +#endif + +/* + * STRONG_ALIAS, WEAK_ALIAS + * Create a strong or weak alias. + */ +#define STRONG_ALIAS(alias,sym) \ + .global alias; \ + alias = sym +#define WEAK_ALIAS(alias,sym) \ + .weak alias; \ + alias = sym + +/* let kernels and others override entrypoint alignment */ +#ifndef _ALIGN_TEXT +# define _ALIGN_TEXT .align 2, 0x90 +#endif + +/* NB == No Binding: use .globl or .weak as necessary */ +#define _ENTRY_NB(x) \ + .text; _ALIGN_TEXT; .type x,@function; x: +#define _ENTRY(x) .globl x; _ENTRY_NB(x) + +#ifdef _KERNEL +#define KUTEXT .section .kutext, "ax" + +#define IDTVEC(name) \ + KUTEXT; ALIGN_TEXT; \ + .globl X##name; X##name: +#define KIDTVEC(name) \ + .text; ALIGN_TEXT; \ + .globl X##name; X##name: +#define KUENTRY(x) \ + KUTEXT; _ALIGN_TEXT; .globl x; .type x,@function; x: + +#endif /* _KERNEL */ + +#if defined(PROF) || defined(GPROF) +# define _PROF_PROLOGUE \ + pushl %ebp; movl %esp,%ebp; call PIC_PLT(mcount); popl %ebp +#else +# define _PROF_PROLOGUE +#endif + +#define ENTRY(y) _ENTRY(y); _PROF_PROLOGUE +#define ENTRY_NB(y) _ENTRY_NB(y); _PROF_PROLOGUE +#define NENTRY(y) _ENTRY(y) +#define ASENTRY(y) _ENTRY(y); _PROF_PROLOGUE +#define NASENTRY(y) _ENTRY(y) +#define END(y) .size y, . - y + +#define ALTENTRY(name) .globl name; name: + +#ifdef _KERNEL + +#define CPUVAR(var) %fs:__CONCAT(CPU_INFO_,var) + +#endif /* _KERNEL */ + +#endif /* !_MACHINE_ASM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/atomic.h b/lib/libc/include/x86-openbsd-none/machine/atomic.h new file mode 100644 index 000000000000..ef6a8301b468 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/atomic.h @@ -0,0 +1,316 @@ +/* $OpenBSD: atomic.h,v 1.20 2022/08/29 02:01:18 jsg Exp $ */ +/* $NetBSD: atomic.h,v 1.1.2.2 2000/02/21 18:54:07 sommerfeld Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_ATOMIC_H_ +#define _MACHINE_ATOMIC_H_ + +/* + * Perform atomic operations on memory. Should be atomic with respect + * to interrupts and multiple processors. + * + * void atomic_setbits_int(volatile u_int *a, u_int mask) { *a |= mask; } + * void atomic_clearbits_int(volatile u_int *a, u_int mas) { *a &= ~mask; } + */ +#if !defined(_LOCORE) + +#if defined(MULTIPROCESSOR) || !defined(_KERNEL) +#define _LOCK "lock" +#else +#define _LOCK +#endif + +static inline unsigned int +_atomic_cas_uint(volatile unsigned int *p, unsigned int e, unsigned int n) +{ + __asm volatile(_LOCK " cmpxchgl %2, %1" + : "=a" (n), "=m" (*p) + : "r" (n), "a" (e), "m" (*p)); + + return (n); +} +#define atomic_cas_uint(_p, _e, _n) _atomic_cas_uint((_p), (_e), (_n)) + +static inline unsigned long +_atomic_cas_ulong(volatile unsigned long *p, unsigned long e, unsigned long n) +{ + __asm volatile(_LOCK " cmpxchgl %2, %1" + : "=a" (n), "=m" (*p) + : "r" (n), "a" (e), "m" (*p)); + + return (n); +} +#define atomic_cas_ulong(_p, _e, _n) _atomic_cas_ulong((_p), (_e), (_n)) + +static inline void * +_atomic_cas_ptr(volatile void *p, void *e, void *n) +{ + __asm volatile(_LOCK " cmpxchgl %2, %1" + : "=a" (n), "=m" (*(unsigned long *)p) + : "r" (n), "a" (e), "m" (*(unsigned long *)p)); + + return (n); +} +#define atomic_cas_ptr(_p, _e, _n) _atomic_cas_ptr((_p), (_e), (_n)) + +static inline unsigned int +_atomic_swap_uint(volatile unsigned int *p, unsigned int n) +{ + __asm volatile("xchgl %0, %1" + : "=a" (n), "=m" (*p) + : "0" (n), "m" (*p)); + + return (n); +} +#define atomic_swap_uint(_p, _n) _atomic_swap_uint((_p), (_n)) +#define atomic_swap_32(_p, _n) _atomic_swap_uint((_p), (_n)) + +static inline unsigned long +_atomic_swap_ulong(volatile unsigned long *p, unsigned long n) +{ + __asm volatile("xchgl %0, %1" + : "=a" (n), "=m" (*p) + : "0" (n), "m" (*p)); + + return (n); +} +#define atomic_swap_ulong(_p, _n) _atomic_swap_ulong((_p), (_n)) + +static inline void * +_atomic_swap_ptr(volatile void *p, void *n) +{ + __asm volatile("xchgl %0, %1" + : "=a" (n), "=m" (*(unsigned long *)p) + : "0" (n), "m" (*(unsigned long *)p)); + + return (n); +} +#define atomic_swap_ptr(_p, _n) _atomic_swap_ptr((_p), (_n)) + +static inline void +_atomic_inc_int(volatile unsigned int *p) +{ + __asm volatile(_LOCK " incl %0" + : "+m" (*p)); +} +#define atomic_inc_int(_p) _atomic_inc_int(_p) + +static inline void +_atomic_inc_long(volatile unsigned long *p) +{ + __asm volatile(_LOCK " incl %0" + : "+m" (*p)); +} +#define atomic_inc_long(_p) _atomic_inc_long(_p) + +static inline void +_atomic_dec_int(volatile unsigned int *p) +{ + __asm volatile(_LOCK " decl %0" + : "+m" (*p)); +} +#define atomic_dec_int(_p) _atomic_dec_int(_p) + +static inline void +_atomic_dec_long(volatile unsigned long *p) +{ + __asm volatile(_LOCK " decl %0" + : "+m" (*p)); +} +#define atomic_dec_long(_p) _atomic_dec_long(_p) + +static inline void +_atomic_add_int(volatile unsigned int *p, unsigned int v) +{ + __asm volatile(_LOCK " addl %1,%0" + : "+m" (*p) + : "a" (v)); +} +#define atomic_add_int(_p, _v) _atomic_add_int(_p, _v) + +static inline void +_atomic_add_long(volatile unsigned long *p, unsigned long v) +{ + __asm volatile(_LOCK " addl %1,%0" + : "+m" (*p) + : "a" (v)); +} +#define atomic_add_long(_p, _v) _atomic_add_long(_p, _v) + +static inline void +_atomic_sub_int(volatile unsigned int *p, unsigned int v) +{ + __asm volatile(_LOCK " subl %1,%0" + : "+m" (*p) + : "a" (v)); +} +#define atomic_sub_int(_p, _v) _atomic_sub_int(_p, _v) + +static inline void +_atomic_sub_long(volatile unsigned long *p, unsigned long v) +{ + __asm volatile(_LOCK " subl %1,%0" + : "+m" (*p) + : "a" (v)); +} +#define atomic_sub_long(_p, _v) _atomic_sub_long(_p, _v) + + +static inline unsigned long +_atomic_add_int_nv(volatile unsigned int *p, unsigned int v) +{ + unsigned int rv = v; + + __asm volatile(_LOCK " xaddl %0,%1" + : "+a" (rv), "+m" (*p)); + + return (rv + v); +} +#define atomic_add_int_nv(_p, _v) _atomic_add_int_nv(_p, _v) + +static inline unsigned long +_atomic_add_long_nv(volatile unsigned long *p, unsigned long v) +{ + unsigned long rv = v; + + __asm volatile(_LOCK " xaddl %0,%1" + : "+a" (rv), "+m" (*p)); + + return (rv + v); +} +#define atomic_add_long_nv(_p, _v) _atomic_add_long_nv(_p, _v) + +static inline unsigned long +_atomic_sub_int_nv(volatile unsigned int *p, unsigned int v) +{ + unsigned int rv = 0 - v; + + __asm volatile(_LOCK " xaddl %0,%1" + : "+a" (rv), "+m" (*p)); + + return (rv - v); +} +#define atomic_sub_int_nv(_p, _v) _atomic_sub_int_nv(_p, _v) + +static inline unsigned long +_atomic_sub_long_nv(volatile unsigned long *p, unsigned long v) +{ + unsigned long rv = 0 - v; + + __asm volatile(_LOCK " xaddl %0,%1" + : "+a" (rv), "+m" (*p)); + + return (rv - v); +} +#define atomic_sub_long_nv(_p, _v) _atomic_sub_long_nv(_p, _v) + +/* + * The IA-32 architecture is rather strongly ordered. When accessing + * normal write-back cacheable memory, only reads may be reordered with + * older writes to different locations. There are a few instructions + * (clfush, non-temporal move instructions) that obey weaker ordering + * rules, but those instructions will only be used in (inline) + * assembly code where we can add the necessary fence instructions + * ourselves. + */ + +#define __membar(_f) do { __asm volatile(_f ::: "memory"); } while (0) + +#if defined(MULTIPROCESSOR) || !defined(_KERNEL) +#define membar_enter() __membar("lock; addl $0,0(%%esp)") +#define membar_exit() __membar("") +#define membar_producer() __membar("") +#define membar_consumer() __membar("") +#define membar_sync() __membar("lock; addl $0,0(%%esp)") +#else +#define membar_enter() __membar("") +#define membar_exit() __membar("") +#define membar_producer() __membar("") +#define membar_consumer() __membar("") +#define membar_sync() __membar("") +#endif + +#define membar_enter_after_atomic() __membar("") +#define membar_exit_before_atomic() __membar("") + +#ifdef _KERNEL + +/* virtio needs MP membars even on SP kernels */ +#define virtio_membar_producer() __membar("") +#define virtio_membar_consumer() __membar("") +#define virtio_membar_sync() __membar("lock; addl $0,0(%%esp)") + +static __inline u_int64_t +i386_atomic_testset_uq(volatile u_int64_t *ptr, u_int64_t val) +{ + __asm__ volatile ("\n1:\t" _LOCK " cmpxchg8b (%1); jnz 1b" : "+A" (val) : + "r" (ptr), "b" ((u_int32_t)val), "c" ((u_int32_t)(val >> 32))); + return val; +} + +static __inline u_int32_t +i386_atomic_testset_ul(volatile u_int32_t *ptr, unsigned long val) +{ + __asm__ volatile ("xchgl %0,(%2)" :"=r" (val):"0" (val),"r" (ptr)); + return val; +} + +static __inline int +i386_atomic_testset_i(volatile int *ptr, unsigned long val) +{ + __asm__ volatile ("xchgl %0,(%2)" :"=r" (val):"0" (val),"r" (ptr)); + return val; +} + +static __inline void +i386_atomic_setbits_l(volatile u_int32_t *ptr, unsigned long bits) +{ + __asm volatile(_LOCK " orl %1,%0" : "=m" (*ptr) : "ir" (bits)); +} + +static __inline void +i386_atomic_clearbits_l(volatile u_int32_t *ptr, unsigned long bits) +{ + bits = ~bits; + __asm volatile(_LOCK " andl %1,%0" : "=m" (*ptr) : "ir" (bits)); +} + +#define atomic_setbits_int i386_atomic_setbits_l +#define atomic_clearbits_int i386_atomic_clearbits_l + +#endif /* _KERNEL */ + +#undef _LOCK + +#endif /* !defined(_LOCORE) */ +#endif /* _MACHINE_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/biosvar.h b/lib/libc/include/x86-openbsd-none/machine/biosvar.h new file mode 100644 index 000000000000..db9769bb7ce0 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/biosvar.h @@ -0,0 +1,306 @@ +/* $OpenBSD: biosvar.h,v 1.68 2019/08/04 14:28:58 kettenis Exp $ */ + +/* + * Copyright (c) 1997-1999 Michael Shalayeff + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES 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 MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BIOSVAR_H_ +#define _MACHINE_BIOSVAR_H_ + + /* some boxes put apm data seg in the 2nd page */ +#define BOOTARG_OFF (PAGE_SIZE * 2) +#define BOOTARG_LEN (PAGE_SIZE * 1) +#define BOOTBIOS_ADDR (0x7c00) +#define BOOTBIOS_MAXSEC ((1 << 28) - 1) + + /* BIOS configure flags */ +#define BIOSF_BIOS32 0x0001 +#define BIOSF_PCIBIOS 0x0002 +#define BIOSF_PROMSCAN 0x0004 +#define BIOSF_SMBIOS 0x0008 + +/* BIOS media ID */ +#define BIOSM_F320K 0xff /* floppy ds/sd 8 spt */ +#define BIOSM_F160K 0xfe /* floppy ss/sd 8 spt */ +#define BIOSM_F360K 0xfd /* floppy ds/sd 9 spt */ +#define BIOSM_F180K 0xfc /* floppy ss/sd 9 spt */ +#define BIOSM_ROMD 0xfa /* ROM disk */ +#define BIOSM_F120M 0xf9 /* floppy ds/hd 15 spt 5.25" */ +#define BIOSM_F720K 0xf9 /* floppy ds/dd 9 spt 3.50" */ +#define BIOSM_HD 0xf8 /* hard drive */ +#define BIOSM_F144K 0xf0 /* floppy ds/hd 18 spt 3.50" */ +#define BIOSM_OTHER 0xf0 /* any other */ + +/* + * BIOS memory maps + */ +#define BIOS_MAP_END 0x00 /* End of array XXX - special */ +#define BIOS_MAP_FREE 0x01 /* Usable memory */ +#define BIOS_MAP_RES 0x02 /* Reserved memory */ +#define BIOS_MAP_ACPI 0x03 /* ACPI Reclaim memory */ +#define BIOS_MAP_NVS 0x04 /* ACPI NVS memory */ + +/* + * Optional ROM header + */ +typedef +struct bios_romheader { + uint16_t signature; /* 0xaa55 */ + uint8_t len; /* length in pages (512 bytes) */ + uint32_t entry; /* initialization entry point */ + uint8_t reserved[19]; + uint16_t pnpheader; /* offset to PnP expansion header */ +} __packed *bios_romheader_t; + +/* + * BIOS32 + */ +typedef +struct bios32_header { + uint32_t signature; /* 00: signature "_32_" */ + uint32_t entry; /* 04: entry point */ + uint8_t rev; /* 08: revision */ + uint8_t length; /* 09: header length */ + uint8_t cksum; /* 0a: modulo 256 checksum */ + uint8_t reserved[5]; +} __packed *bios32_header_t; + +typedef +struct bios32_entry_info { + uint32_t bei_base; + uint32_t bei_size; + uint32_t bei_entry; +} __packed *bios32_entry_info_t; + +typedef +struct bios32_entry { + uint32_t offset; + uint16_t segment; +} __packed *bios32_entry_t; + +#define BIOS32_START 0xe0000 +#define BIOS32_SIZE 0x20000 +#define BIOS32_END (BIOS32_START + BIOS32_SIZE - 0x10) + +#define BIOS32_MAKESIG(a, b, c, d) \ + ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24)) +#define BIOS32_SIGNATURE BIOS32_MAKESIG('_', '3', '2', '_') +#define PCIBIOS_SIGNATURE BIOS32_MAKESIG('$', 'P', 'C', 'I') +#define SMBIOS_SIGNATURE BIOS32_MAKESIG('_', 'S', 'M', '_') + +/* + * CTL_BIOS definitions. + */ +#define BIOS_DEV 1 /* int: BIOS boot device */ +#define BIOS_DISKINFO 2 /* struct: BIOS boot device info */ +#define BIOS_CKSUMLEN 3 /* int: disk cksum block count */ +#define BIOS_MAXID 4 /* number of valid machdep ids */ + +#define CTL_BIOS_NAMES { \ + { 0, 0 }, \ + { "biosdev", CTLTYPE_INT }, \ + { "diskinfo", CTLTYPE_STRUCT }, \ + { "cksumlen", CTLTYPE_INT }, \ +} + +#define BOOTARG_MEMMAP 0 +typedef struct _bios_memmap { + uint64_t addr; /* Beginning of block */ + uint64_t size; /* Size of block */ + uint32_t type; /* Type of block */ +} __packed bios_memmap_t; + +/* Info about disk from the bios, plus the mapping from + * BIOS numbers to BSD major (driver?) number. + * + * Also, do not bother with BIOSN*() macros, just parcel + * the info out, and use it like this. This makes for less + * of a dependence on BIOSN*() macros having to be the same + * across /boot, /bsd, and userland. + */ +#define BOOTARG_DISKINFO 1 +typedef struct _bios_diskinfo { + /* BIOS section */ + int bios_number; /* BIOS number of drive (or -1) */ + u_int bios_cylinders; /* BIOS cylinders */ + u_int bios_heads; /* BIOS heads */ + u_int bios_sectors; /* BIOS sectors */ + int bios_edd; /* EDD support */ + + /* BSD section */ + dev_t bsd_dev; /* BSD device */ + + /* Checksum section */ + uint32_t checksum; /* Checksum for drive */ + + /* Misc. flags */ + uint32_t flags; +#define BDI_INVALID 0x00000001 /* I/O error during checksumming */ +#define BDI_GOODLABEL 0x00000002 /* Had SCSI or ST506/ESDI disklabel */ +#define BDI_BADLABEL 0x00000004 /* Had another disklabel */ +#define BDI_EL_TORITO 0x00000008 /* 2,048-byte sectors */ +#define BDI_HIBVALID 0x00000010 /* hibernate signature valid */ +#define BDI_PICKED 0x80000000 /* kernel-only: cksum matched */ + +} __packed bios_diskinfo_t; + +#define BOOTARG_APMINFO 2 +typedef struct _bios_apminfo { + /* APM_CONNECT returned values */ + u_int apm_detail; + u_int apm_code32_base; + u_int apm_code16_base; + u_int apm_code_len; + u_int apm_data_base; + u_int apm_data_len; + u_int apm_entry; + u_int apm_code16_len; +} __packed bios_apminfo_t; + +#define BOOTARG_CKSUMLEN 3 /* uint32_t */ + +#define BOOTARG_PCIINFO 4 +typedef struct _bios_pciinfo { + /* PCI BIOS v2.0+ - Installation check values */ + uint32_t pci_chars; /* Characteristics (%eax) */ + uint32_t pci_rev; /* BCD Revision (%ebx) */ + uint32_t pci_entry32; /* PM entry point for PCI BIOS */ + uint32_t pci_lastbus; /* Number of last PCI bus */ +} __packed bios_pciinfo_t; + +#define BOOTARG_CONSDEV 5 +typedef struct _bios_consdev { + dev_t consdev; + int conspeed; + int consaddr; + int consfreq; +} __packed bios_consdev_t; + +#define BOOTARG_SMPINFO 6 /* struct mp_float[] */ + +#define BOOTARG_BOOTMAC 7 +typedef struct _bios_bootmac { + char mac[6]; +} __packed bios_bootmac_t; + +#define BOOTARG_DDB 8 +typedef struct _bios_ddb { + int db_console; +} __packed bios_ddb_t; + +#define BOOTARG_BOOTDUID 9 +typedef struct _bios_bootduid { + u_char duid[8]; +} __packed bios_bootduid_t; + +#define BOOTARG_BOOTSR 10 +#define BOOTSR_UUID_MAX 16 +#define BOOTSR_CRYPTO_MAXKEYBYTES 32 +typedef struct _bios_bootsr { + uint8_t uuid[BOOTSR_UUID_MAX]; + uint8_t maskkey[BOOTSR_CRYPTO_MAXKEYBYTES]; +} __packed bios_bootsr_t; + +#define BOOTARG_EFIINFO 11 +typedef struct _bios_efiinfo { + uint64_t config_acpi; + uint64_t config_smbios; + uint64_t fb_addr; + uint64_t fb_size; + uint32_t fb_height; + uint32_t fb_width; + uint32_t fb_pixpsl; /* pixels per scan line */ + uint32_t fb_red_mask; + uint32_t fb_green_mask; + uint32_t fb_blue_mask; + uint32_t fb_reserved_mask; +} __packed bios_efiinfo_t; + +#define BOOTARG_UCODE 12 +typedef struct _bios_ucode { + uint64_t uc_addr; + uint64_t uc_size; +} __packed bios_ucode_t; + +#if defined(_KERNEL) || defined (_STANDALONE) + +#ifdef _LOCORE +#define DOINT(n) int $0x20+(n) +#else +#define DOINT(n) "int $0x20+(" #n ")" + +extern volatile struct BIOS_regs { + uint32_t biosr_ax; + uint32_t biosr_cx; + uint32_t biosr_dx; + uint32_t biosr_bx; + uint32_t biosr_bp; + uint32_t biosr_si; + uint32_t biosr_di; + uint32_t biosr_ds; + uint32_t biosr_es; +} __packed BIOS_regs; + +#ifdef _KERNEL +#include + +struct bios_attach_args { + char *ba_name; + u_int ba_func; + bus_space_tag_t ba_iot; + bus_space_tag_t ba_memt; + union { + void *_p; + bios_apminfo_t *_ba_apmp; + paddr_t _ba_acpipbase; + } _; +}; + +#define ba_apmp _._ba_apmp +#define ba_acpipbase _._ba_acpipbase + +struct consdev; +struct proc; + +int bios_sysctl(int *, u_int, void *, size_t *, void *, size_t, struct proc *); + +void bios_getopt(void); + +/* bios32.c */ +int bios32_service(uint32_t, bios32_entry_t, bios32_entry_info_t); +void bios32_cleanup(void); + +extern u_int bootapiver; +extern bios_memmap_t *bios_memmap; +extern bios_efiinfo_t *bios_efiinfo; +extern bios_ucode_t *bios_ucode; +extern void *bios_smpinfo; +extern bios_pciinfo_t *bios_pciinfo; + +#endif /* _KERNEL */ +#endif /* _LOCORE */ +#endif /* _KERNEL || _STANDALONE */ + +#endif /* _MACHINE_BIOSVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/bus.h b/lib/libc/include/x86-openbsd-none/machine/bus.h new file mode 100644 index 000000000000..6ed2cb5fb72f --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/bus.h @@ -0,0 +1,701 @@ +/* $OpenBSD: bus.h,v 1.67 2017/05/08 00:27:45 dlg Exp $ */ +/* $NetBSD: bus.h,v 1.6 1996/11/10 03:19:25 thorpej Exp $ */ + +/*- + * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1996 Charles M. Hannum. All rights reserved. + * Copyright (c) 1996 Jason R. Thorpe. All rights reserved. + * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BUS_H_ +#define _MACHINE_BUS_H_ + +#include +#include + +#include + +/* + * Bus address and size types + */ +typedef u_long bus_addr_t; +typedef u_long bus_size_t; + +/* + * Access methods for bus resources and address space. + */ +struct i386_bus_space_ops; +typedef const struct i386_bus_space_ops *bus_space_tag_t; +typedef u_long bus_space_handle_t; + +int bus_space_map(bus_space_tag_t t, bus_addr_t addr, + bus_size_t size, int flags, bus_space_handle_t *bshp); +/* like bus_space_map(), but without extent map checking/allocation */ +int _bus_space_map(bus_space_tag_t t, bus_addr_t addr, + bus_size_t size, int flags, bus_space_handle_t *bshp); +void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t size); +/* like bus_space_unmap(), but without extent map deallocation */ +void _bus_space_unmap(bus_space_tag_t, bus_space_handle_t, + bus_size_t, bus_addr_t *); +int bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp); +paddr_t bus_space_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int); + +int bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart, + bus_addr_t rend, bus_size_t size, bus_size_t align, + bus_size_t boundary, int flags, bus_addr_t *addrp, + bus_space_handle_t *bshp); +void bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t size); + +struct i386_bus_space_ops { + +/* + * u_intN_t bus_space_read_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset); + * + * Read a 1, 2, 4, or 8 byte quantity from bus space + * described by tag/handle/offset. + */ + u_int8_t (*read_1)(bus_space_handle_t, bus_size_t); + u_int16_t (*read_2)(bus_space_handle_t, bus_size_t); + u_int32_t (*read_4)(bus_space_handle_t, bus_size_t); + +#define bus_space_read_1(_t, _h, _o) ((_t)->read_1((_h), (_o))) +#define bus_space_read_2(_t, _h, _o) ((_t)->read_2((_h), (_o))) +#define bus_space_read_4(_t, _h, _o) ((_t)->read_4((_h), (_o))) + +#define bus_space_read_raw_2(t, h, o) \ + bus_space_read_2((t), (h), (o)) +#define bus_space_read_raw_4(t, h, o) \ + bus_space_read_4((t), (h), (o)) + +#if 0 +/* Cause a link error for bus_space_read_8 and bus_space_read_raw_8 */ +#define bus_space_read_8(t, h, o) !!! bus_space_read_8 unimplemented !!! +#define bus_space_read_raw_8(t, h, o) !!! bus_space_read_raw_8 unimplemented !!! +#endif + +/* + * void bus_space_read_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t *addr, size_t count); + * + * Read `count' 1, 2, 4, or 8 byte quantities from bus space + * described by tag/handle/offset and copy into buffer provided. + */ + + void (*read_multi_1)(bus_space_handle_t, bus_size_t, + u_int8_t *, bus_size_t); + void (*read_multi_2)(bus_space_handle_t, bus_size_t, + u_int16_t *, bus_size_t); + void (*read_multi_4)(bus_space_handle_t, bus_size_t, + u_int32_t *, bus_size_t); + +#define bus_space_read_multi_1(_t, _h, _o, _a, _c) \ + ((_t)->read_multi_1((_h), (_o), (_a), (_c))) +#define bus_space_read_multi_2(_t, _h, _o, _a, _c) \ + ((_t)->read_multi_2((_h), (_o), (_a), (_c))) +#define bus_space_read_multi_4(_t, _h, _o, _a, _c) \ + ((_t)->read_multi_4((_h), (_o), (_a), (_c))) + +#if 0 /* Cause a link error for bus_space_read_multi_8 */ +#define bus_space_read_multi_8 !!! bus_space_read_multi_8 unimplemented !!! +#endif + +/* + * void bus_space_read_raw_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_int8_t *addr, size_t count); + * + * Read `count' bytes in 2, 4 or 8 byte wide quantities from bus space + * described by tag/handle/offset and copy into buffer provided. The buffer + * must have proper alignment for the N byte wide entities. Furthermore + * possible byte-swapping should be done by these functions. + */ + +#define bus_space_read_raw_multi_2(t, h, o, a, c) \ + bus_space_read_multi_2((t), (h), (o), (u_int16_t *)(a), (c) >> 1) +#define bus_space_read_raw_multi_4(t, h, o, a, c) \ + bus_space_read_multi_4((t), (h), (o), (u_int32_t *)(a), (c) >> 2) + +#if 0 /* Cause a link error for bus_space_read_raw_multi_8 */ +#define bus_space_read_raw_multi_8 \ + !!! bus_space_read_raw_multi_8 unimplemented !!! +#endif + +/* + * void bus_space_read_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t *addr, size_t count); + * + * Read `count' 1, 2, 4, or 8 byte quantities from bus space + * described by tag/handle and starting at `offset' and copy into + * buffer provided. + */ + + void (*read_region_1)(bus_space_handle_t, + bus_size_t, u_int8_t *, bus_size_t); + void (*read_region_2)(bus_space_handle_t, + bus_size_t, u_int16_t *, bus_size_t); + void (*read_region_4)(bus_space_handle_t, + bus_size_t, u_int32_t *, bus_size_t); + +#define bus_space_read_region_1(_t, _h, _o, _a, _c) \ + ((_t)->read_region_1((_h), (_o), (_a), (_c))) +#define bus_space_read_region_2(_t, _h, _o, _a, _c) \ + ((_t)->read_region_2((_h), (_o), (_a), (_c))) +#define bus_space_read_region_4(_t, _h, _o, _a, _c) \ + ((_t)->read_region_4((_h), (_o), (_a), (_c))) + +#if 0 /* Cause a link error for bus_space_read_region_8 */ +#define bus_space_read_region_8 !!! bus_space_read_region_8 unimplemented !!! +#endif + +/* + * void bus_space_read_raw_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_int8_t *addr, size_t count); + * + * Read `count' bytes in 2, 4 or 8 byte wide quantities from bus space + * described by tag/handle and starting at `offset' and copy into + * buffer provided. The buffer must have proper alignment for the N byte + * wide entities. Furthermore possible byte-swapping should be done by + * these functions. + */ + +#define bus_space_read_raw_region_2(_t, _h, _o, _a, _c) \ + ((_t)->read_region_2((_h), (_o), (u_int16_t *)(_a), (_c) >> 1)) +#define bus_space_read_raw_region_4(_t, _h, _o, _a, _c) \ + ((_t)->read_region_4((_h), (_o), (u_int32_t *)(_a), (_c) >> 2)) + +#if 0 /* Cause a link error for bus_space_read_raw_region_8 */ +#define bus_space_read_raw_region_8 \ + !!! bus_space_read_raw_region_8 unimplemented !!! +#endif + +/* + * void bus_space_write_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t value); + * + * Write the 1, 2, 4, or 8 byte value `value' to bus space + * described by tag/handle/offset. + */ + + void (*write_1)(bus_space_handle_t, bus_size_t, u_int8_t); + void (*write_2)(bus_space_handle_t, bus_size_t, u_int16_t); + void (*write_4)(bus_space_handle_t, bus_size_t, u_int32_t); + +#define bus_space_write_1(_t, _h, _o, _v) \ + ((_t)->write_1((_h), (_o), (_v))) +#define bus_space_write_2(_t, _h, _o, _v) \ + ((_t)->write_2((_h), (_o), (_v))) +#define bus_space_write_4(_t, _h, _o, _v) \ + ((_t)->write_4((_h), (_o), (_v))) + +#define bus_space_write_raw_2(t, h, o, v) \ + bus_space_write_2((t), (h), (o), (v)) +#define bus_space_write_raw_4(t, h, o, v) \ + bus_space_write_4((t), (h), (o), (v)) + +#if 0 +/* Cause a link error for bus_space_write_8 and bus_space_write_raw_8 */ +#define bus_space_write_8 !!! bus_space_write_8 not implemented !!! +#define bus_space_write_raw_8 !!! bus_space_write_raw_8 not implemented !!! +#endif + +/* + * void bus_space_write_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_intN_t *addr, size_t count); + * + * Write `count' 1, 2, 4, or 8 byte quantities from the buffer + * provided to bus space described by tag/handle/offset. + */ + + void (*write_multi_1)(bus_space_handle_t, + bus_size_t, const u_int8_t *, bus_size_t); + void (*write_multi_2)(bus_space_handle_t, + bus_size_t, const u_int16_t *, bus_size_t); + void (*write_multi_4)(bus_space_handle_t, + bus_size_t, const u_int32_t *, bus_size_t); + +#define bus_space_write_multi_1(_t, _h, _o, _a, _c) \ + ((_t)->write_multi_1((_h), (_o), (_a), (_c))) +#define bus_space_write_multi_2(_t, _h, _o, _a, _c) \ + ((_t)->write_multi_2((_h), (_o), (_a), (_c))) +#define bus_space_write_multi_4(_t, _h, _o, _a, _c) \ + ((_t)->write_multi_4((_h), (_o), (_a), (_c))) + +#if 0 /* Cause a link error for bus_space_write_multi_8 */ +#define bus_space_write_multi_8(t, h, o, a, c) \ + !!! bus_space_write_multi_8 unimplemented !!! +#endif + +/* + * void bus_space_write_raw_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_int8_t *addr, size_t count); + * + * Write `count' bytes in 2, 4 or 8 byte wide quantities from the buffer + * provided to bus space described by tag/handle/offset. The buffer + * must have proper alignment for the N byte wide entities. Furthermore + * possible byte-swapping should be done by these functions. + */ + +#define bus_space_write_raw_multi_2(_t, _h, _o, _a, _c) \ + ((_t)->write_multi_2((_h), (_o), (const u_int16_t *)(_a), (_c) >> 1)) +#define bus_space_write_raw_multi_4(_t, _h, _o, _a, _c) \ + ((_t)->write_multi_4((_h), (_o), (const u_int32_t *)(_a), (_c) >> 2)) + +#if 0 /* Cause a link error for bus_space_write_raw_multi_8 */ +#define bus_space_write_raw_multi_8 \ + !!! bus_space_write_raw_multi_8 unimplemented !!! +#endif + +/* + * void bus_space_write_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_intN_t *addr, size_t count); + * + * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided + * to bus space described by tag/handle starting at `offset'. + */ + + void (*write_region_1)(bus_space_handle_t, + bus_size_t, const u_int8_t *, bus_size_t); + void (*write_region_2)(bus_space_handle_t, + bus_size_t, const u_int16_t *, bus_size_t); + void (*write_region_4)(bus_space_handle_t, + bus_size_t, const u_int32_t *, bus_size_t); + +#define bus_space_write_region_1(_t, _h, _o, _a, _c) \ + ((_t)->write_region_1((_h), (_o), (_a), (_c))) +#define bus_space_write_region_2(_t, _h, _o, _a, _c) \ + ((_t)->write_region_2((_h), (_o), (_a), (_c))) +#define bus_space_write_region_4(_t, _h, _o, _a, _c) \ + ((_t)->write_region_4((_h), (_o), (_a), (_c))) + +#if 0 /* Cause a link error for bus_space_write_region_8 */ +#define bus_space_write_region_8 \ + !!! bus_space_write_region_8 unimplemented !!! +#endif + +/* + * void bus_space_write_raw_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_int8_t *addr, size_t count); + * + * Write `count' bytes in 2, 4 or 8 byte wide quantities to bus space + * described by tag/handle and starting at `offset' from the + * buffer provided. The buffer must have proper alignment for the N byte + * wide entities. Furthermore possible byte-swapping should be done by + * these functions. + */ + +#define bus_space_write_raw_region_2(_t, _h, _o, _a, _c) \ + ((_t)->write_region_2((_h), (_o), (const u_int16_t *)(_a), (_c) >> 1)) +#define bus_space_write_raw_region_4(_t, _h, _o, _a, _c) \ + ((_t)->write_region_4((_h), (_o), (const u_int32_t *)(_a), (_c) >> 2)) + +#if 0 /* Cause a link error for bus_space_write_raw_region_8 */ +#define bus_space_write_raw_region_8 \ + !!! bus_space_write_raw_region_8 unimplemented !!! +#endif + +/* + * void bus_space_set_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t val, size_t count); + * + * Write the 1, 2, 4, or 8 byte value `val' to bus space described + * by tag/handle/offset `count' times. + */ + + void (*set_multi_1)(bus_space_handle_t, + bus_size_t, u_int8_t, size_t); + void (*set_multi_2)(bus_space_handle_t, + bus_size_t, u_int16_t, size_t); + void (*set_multi_4)(bus_space_handle_t, + bus_size_t, u_int32_t, size_t); + +#define bus_space_set_multi_1(_t, _h, _o, _a, _c) \ + ((_t)->set_multi_1((_h), (_o), (_a), (_c))) +#define bus_space_set_multi_2(_t, _h, _o, _a, _c) \ + ((_t)->set_multi_2((_h), (_o), (_a), (_c))) +#define bus_space_set_multi_4(_t, _h, _o, _a, _c) \ + ((_t)->set_multi_4((_h), (_o), (_a), (_c))) + +#if 0 /* Cause a link error for bus_space_set_multi_8 */ +#define bus_space_set_multi_8 \ + !!! bus_space_set_multi_8 unimplemented !!! +#endif + +/* + * void bus_space_set_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t val, size_t count); + * + * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described + * by tag/handle starting at `offset'. + */ + + void (*set_region_1)(bus_space_handle_t, + bus_size_t, u_int8_t, size_t); + void (*set_region_2)(bus_space_handle_t, + bus_size_t, u_int16_t, size_t); + void (*set_region_4)(bus_space_handle_t, + bus_size_t, u_int32_t, size_t); + +#define bus_space_set_region_1(_t, _h, _o, _a, _c) \ + ((_t)->set_region_1((_h), (_o), (_a), (_c))) +#define bus_space_set_region_2(_t, _h, _o, _a, _c) \ + ((_t)->set_region_2((_h), (_o), (_a), (_c))) +#define bus_space_set_region_4(_t, _h, _o, _a, _c) \ + ((_t)->set_region_4((_h), (_o), (_a), (_c))) + +#if 0 /* Cause a link error for bus_space_set_region_8 */ +#define bus_space_set_region_8 \ + !!! bus_space_set_region_8 unimplemented !!! +#endif + +/* + * void bus_space_copy_N(bus_space_tag_t tag, + * bus_space_handle_t bsh1, bus_size_t off1, + * bus_space_handle_t bsh2, bus_size_t off2, + * size_t count); + * + * Copy `count' 1, 2, 4, or 8 byte values from bus space starting + * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2. + */ + + void (*copy_1)(bus_space_handle_t, + bus_size_t, bus_space_handle_t, bus_size_t, size_t); + void (*copy_2)(bus_space_handle_t, + bus_size_t, bus_space_handle_t, bus_size_t, size_t); + void (*copy_4)(bus_space_handle_t, + bus_size_t, bus_space_handle_t, bus_size_t, size_t); + +#define bus_space_copy_1(_t, _h1, _o1, _h2, _o2, _c) \ + ((_t)->copy_1((_h1), (_o1), (_h2), (_o2), (_c))) +#define bus_space_copy_2(_t, _h1, _o1, _h2, _o2, _c) \ + ((_t)->copy_2((_h1), (_o1), (_h2), (_o2), (_c))) +#define bus_space_copy_4(_t, _h1, _o1, _h2, _o2, _c) \ + ((_t)->copy_4((_h1), (_o1), (_h2), (_o2), (_c))) + +#if 0 /* Cause a link error for bus_space_copy_8 */ +#define bus_space_copy_8 \ + !!! bus_space_copy_8 unimplemented !!! +#endif + +#define i386_space_copy1(a1, a2, cnt, movs, df) \ + __asm volatile(df "\n\trep\n\t" movs : \ + "+S" (a1), "+D" (a2), "+c" (cnt) :: "memory", "cc"); + +#define i386_space_copy(a1, a2, sz, cnt) do { \ + if ((void *)(a1) < (void *)(a2)) { \ + a1 += ((cnt) - 1) * (sz); a2 += ((cnt) - 1) * (sz); \ + switch (sz) { \ + case 1: i386_space_copy1(a1,a2,cnt,"movsb","std");break;\ + case 2: i386_space_copy1(a1,a2,cnt,"movsw","std");break;\ + case 4: i386_space_copy1(a1,a2,cnt,"movsl","std");break;\ + } \ + __asm volatile("cld"); /* must restore before func ret */ \ + } else \ + switch (sz) { \ + case 1: i386_space_copy1(a1,a2,cnt,"movsb","cld");break;\ + case 2: i386_space_copy1(a1,a2,cnt,"movsw","cld");break;\ + case 4: i386_space_copy1(a1,a2,cnt,"movsl","cld");break;\ + } \ +} while (0) + +/* + * void *bus_space_vaddr(bus_space_tag_t, bus_space_handle_t); + * + * Get the kernel virtual address for the mapped bus space. + * Only allowed for regions mapped with BUS_SPACE_MAP_LINEAR. + */ + void * (*vaddr)(bus_space_handle_t); + +#define bus_space_vaddr(_t, _h) \ + ((_t)->vaddr((_h))) +}; + +/* + * Bus read/write barrier methods. + * + * void bus_space_barrier(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * bus_size_t len, int flags); + * + * Note: the i386 does not currently require barriers, but we must + * provide the flags to MI code. + */ +#define bus_space_barrier(t, h, o, l, f) do { \ + ((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f)));\ + __asm volatile("" : : : "memory"); \ +} while (0) +#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ +#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ + +#define BUS_SPACE_MAP_CACHEABLE 0x0001 +#define BUS_SPACE_MAP_LINEAR 0x0002 +#define BUS_SPACE_MAP_PREFETCHABLE 0x0008 + +/* + * Values for the i386 bus space tag, not to be used directly by MI code. + */ + +/* space is i/o space */ +extern const struct i386_bus_space_ops i386_bus_space_io_ops; +#define I386_BUS_SPACE_IO (&i386_bus_space_io_ops) + +/* space is mem space */ +extern const struct i386_bus_space_ops i386_bus_space_mem_ops; +#define I386_BUS_SPACE_MEM (&i386_bus_space_mem_ops) + +/* + * Flags used in various bus DMA methods. + */ +#define BUS_DMA_WAITOK 0x0000 /* safe to sleep (pseudo-flag) */ +#define BUS_DMA_NOWAIT 0x0001 /* not safe to sleep */ +#define BUS_DMA_ALLOCNOW 0x0002 /* perform resource allocation now */ +#define BUS_DMA_COHERENT 0x0004 /* hint: map memory DMA coherent */ +#define BUS_DMA_BUS1 0x0010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x0020 +#define BUS_DMA_BUS3 0x0040 +#define BUS_DMA_24BIT 0x0080 /* isadma map */ +#define BUS_DMA_STREAMING 0x0100 /* hint: sequential, unidirectional */ +#define BUS_DMA_READ 0x0200 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x0400 /* mapping is memory -> device only */ +#define BUS_DMA_NOCACHE 0x0800 /* map memory uncached */ +#define BUS_DMA_ZERO 0x1000 /* dmamem_alloc return zeroed mem */ +#define BUS_DMA_64BIT 0x2000 /* device handles 64bit dva */ + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct proc; +struct uio; + +/* + * Operations performed by bus_dmamap_sync(). + */ +#define BUS_DMASYNC_PREREAD 0x01 +#define BUS_DMASYNC_POSTREAD 0x02 +#define BUS_DMASYNC_PREWRITE 0x04 +#define BUS_DMASYNC_POSTWRITE 0x08 + +typedef struct bus_dma_tag *bus_dma_tag_t; +typedef struct bus_dmamap *bus_dmamap_t; + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +struct bus_dma_segment { + bus_addr_t ds_addr; /* DMA address */ + bus_size_t ds_len; /* length of transfer */ + /* + * Ugh. need this so can pass alignment down from bus_dmamem_alloc + * to scatter gather maps. only the first one is used so the rest is + * wasted space. bus_dma could do with fixing the api for this. + */ + bus_size_t _ds_boundary; /* don't cross */ + bus_size_t _ds_align; /* align to me */ +}; +typedef struct bus_dma_segment bus_dma_segment_t; + +/* + * bus_dma_tag_t + * + * A machine-dependent opaque type describing the implementation of + * DMA for a given bus. + */ + +struct bus_dma_tag { + void *_cookie; /* cookie used in the guts */ + + /* + * DMA mapping methods. + */ + int (*_dmamap_create)(bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); + void (*_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t); + int (*_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); + int (*_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t, + struct mbuf *, int); + int (*_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t, + struct uio *, int); + int (*_dmamap_load_raw)(bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); + void (*_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t); + void (*_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t, + bus_addr_t, bus_size_t, int); + + /* + * DMA memory utility functions. + */ + int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); + int (*_dmamem_alloc_range)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int, + bus_addr_t, bus_addr_t); + void (*_dmamem_free)(bus_dma_tag_t, + bus_dma_segment_t *, int); + int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); + void (*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t); + paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, + int, off_t, int, int); +}; + +#define bus_dmamap_create(t, s, n, m, b, f, p) \ + (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) +#define bus_dmamap_destroy(t, p) \ + (*(t)->_dmamap_destroy)((t), (p)) +#define bus_dmamap_load(t, m, b, s, p, f) \ + (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) +#define bus_dmamap_load_mbuf(t, m, b, f) \ + (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) +#define bus_dmamap_load_uio(t, m, u, f) \ + (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) +#define bus_dmamap_load_raw(t, m, sg, n, s, f) \ + (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) +#define bus_dmamap_unload(t, p) \ + (*(t)->_dmamap_unload)((t), (p)) +#define bus_dmamap_sync(t, p, o, l, ops) \ + (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops)) + +#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ + (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f)) +#define bus_dmamem_alloc_range(t, s, a, b, sg, n, r, f, l, h) \ + (*(t)->_dmamem_alloc_range)((t), (s), (a), (b), (sg), \ + (n), (r), (f), (l), (h)) +#define bus_dmamem_free(t, sg, n) \ + (*(t)->_dmamem_free)((t), (sg), (n)) +#define bus_dmamem_map(t, sg, n, s, k, f) \ + (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f)) +#define bus_dmamem_unmap(t, k, s) \ + (*(t)->_dmamem_unmap)((t), (k), (s)) +#define bus_dmamem_mmap(t, sg, n, o, p, f) \ + (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f)) + +/* + * bus_dmamap_t + * + * Describes a DMA mapping. + */ +struct bus_dmamap { + /* + * PRIVATE MEMBERS: not for use by machine-independent code. + */ + bus_size_t _dm_size; /* largest DMA transfer mappable */ + int _dm_segcnt; /* number of segs this map can map */ + bus_size_t _dm_maxsegsz; /* largest possible segment */ + bus_size_t _dm_boundary; /* don't cross this */ + int _dm_flags; /* misc. flags */ + + void *_dm_cookie; /* cookie for bus-specific functions */ + + /* + * PUBLIC MEMBERS: these are used by machine-independent code. + */ + bus_size_t dm_mapsize; /* size of the mapping */ + int dm_nsegs; /* # valid segments in mapping */ + bus_dma_segment_t dm_segs[1]; /* segments; variable length */ +}; + +int _bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t, + bus_size_t, int, bus_dmamap_t *); +void _bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); +int _bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); +int _bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, + struct mbuf *, int); +int _bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, + struct uio *, int); +int _bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); +void _bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t); +void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, + bus_size_t, int); + +int _bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size, + bus_size_t alignment, bus_size_t boundary, + bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags); +void _bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs); +int _bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs, size_t size, caddr_t *kvap, int flags); +void _bus_dmamem_unmap(bus_dma_tag_t tag, caddr_t kva, + size_t size); +paddr_t _bus_dmamem_mmap(bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs, off_t off, int prot, int flags); + +int _bus_dmamem_alloc_range(bus_dma_tag_t tag, bus_size_t size, + bus_size_t alignment, bus_size_t boundary, + bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags, + paddr_t low, paddr_t high); + +#endif /* _MACHINE_BUS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/cdefs.h b/lib/libc/include/x86-openbsd-none/machine/cdefs.h new file mode 100644 index 000000000000..af2607c12a2c --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/cdefs.h @@ -0,0 +1,21 @@ +/* $OpenBSD: cdefs.h,v 1.10 2013/03/28 17:30:45 martynas Exp $ */ + +/* + * Written by J.T. Conklin 01/17/95. + * Public domain. + */ + +#ifndef _MACHINE_CDEFS_H_ +#define _MACHINE_CDEFS_H_ + +#define __strong_alias(alias,sym) \ + __asm__(".global " __STRING(alias) " ; " \ + __STRING(alias) " = " __STRING(sym)) +#define __weak_alias(alias,sym) \ + __asm__(".weak " __STRING(alias) " ; " \ + __STRING(alias) " = " __STRING(sym)) +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning." __STRING(sym) \ + " ; .ascii \"" msg "\" ; .text") + +#endif /* !_MACHINE_CDEFS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/codepatch.h b/lib/libc/include/x86-openbsd-none/machine/codepatch.h new file mode 100644 index 000000000000..fa33bf8bf8fc --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/codepatch.h @@ -0,0 +1,52 @@ +/* $OpenBSD: codepatch.h,v 1.3 2023/07/31 17:10:31 bluhm Exp $ */ +/* + * Copyright (c) 2014-2015 Stefan Fritsch + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_CODEPATCH_H_ +#define _MACHINE_CODEPATCH_H_ + +#include + +#ifndef _LOCORE + +void *codepatch_maprw(vaddr_t *nva, vaddr_t dest); +void codepatch_unmaprw(vaddr_t nva); +void codepatch_fill_nop(void *caddr, uint16_t len); +void codepatch_nop(uint16_t tag); +void codepatch_replace(uint16_t tag, const void *code, size_t len); +void codepatch_call(uint16_t tag, void *func); + +#endif /* !_LOCORE */ + +/* + * Mark the start of some code snippet to be patched. + */ +#define CODEPATCH_START 998: +/* + * Mark the end of some code to be patched, and assign the given tag. + */ +#define CODEPATCH_END(tag) \ + 999: \ + .section .codepatch, "a" ;\ + .int 998b ;\ + .short (999b - 998b) ;\ + .short tag ;\ + .previous + +#define CPTAG_STAC 1 +#define CPTAG_CLAC 2 + +#endif /* _MACHINE_CODEPATCH_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/conf.h b/lib/libc/include/x86-openbsd-none/machine/conf.h new file mode 100644 index 000000000000..eaceeec5cd5a --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/conf.h @@ -0,0 +1,60 @@ +/* $OpenBSD: conf.h,v 1.21 2024/06/11 03:28:42 jsg Exp $ */ +/* $NetBSD: conf.h,v 1.2 1996/05/05 19:28:34 christos Exp $ */ + +/* + * Copyright (c) 1996 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#define mmread mmrw +#define mmwrite mmrw +cdev_decl(mm); + +bdev_decl(fd); +cdev_decl(fd); + +#define cdev_acpiapm_init(c,n) {\ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev, 0, 0, dev_init(c,n,kqfilter) } + +cdev_decl(spkr); + +cdev_decl(joy); + +cdev_decl(bios); + +cdev_decl(acpi); + +cdev_decl(apm); + +cdev_decl(acpiapm); + +cdev_decl(pctr); \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/cpu.h b/lib/libc/include/x86-openbsd-none/machine/cpu.h new file mode 100644 index 000000000000..eda232d75f28 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/cpu.h @@ -0,0 +1,533 @@ +/* $OpenBSD: cpu.h,v 1.192 2024/06/18 12:37:29 jsg Exp $ */ +/* $NetBSD: cpu.h,v 1.35 1996/05/05 19:29:26 christos Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)cpu.h 5.4 (Berkeley) 5/9/91 + */ + +#ifndef _MACHINE_CPU_H_ +#define _MACHINE_CPU_H_ + +/* + * Definitions unique to i386 cpu support. + */ +#ifdef _KERNEL +#include +#include +#include +#include +#include + +#ifdef MULTIPROCESSOR +#include +#include +#endif + +#endif /* _KERNEL */ + +/* + * Arguments to hardclock, softclock and statclock + * encapsulate the previous machine state in an opaque + * clockframe; for now, use generic intrframe. + * + * XXX intrframe has a lot of gunk we don't need. + */ +#define clockframe intrframe + +#include +#include +#include +#include +#include +#include + +struct intrsource; + +#ifdef _KERNEL +/* XXX stuff to move to cpuvar.h later */ +struct cpu_info { + u_int32_t ci_kern_cr3; /* U+K page table */ + u_int32_t ci_scratch; /* for U<-->K transition */ + +#define ci_PAGEALIGN ci_dev + struct device *ci_dev; /* our device */ + struct cpu_info *ci_self; /* pointer to this structure */ + struct schedstate_percpu ci_schedstate; /* scheduler state */ + struct cpu_info *ci_next; /* next cpu */ + + /* + * Public members. + */ + struct proc *ci_curproc; /* current owner of the processor */ + cpuid_t ci_cpuid; /* our CPU ID */ + u_int ci_apicid; /* our APIC ID */ + u_int ci_acpi_proc_id; + u_int32_t ci_randseed; + + u_int32_t ci_kern_esp; /* kernel-only stack */ + u_int32_t ci_intr_esp; /* U<-->K trampoline stack */ + u_int32_t ci_user_cr3; /* U-K page table */ + +#if defined(MULTIPROCESSOR) + struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM]; +#define __HAVE_UVM_PERCPU + struct uvm_pmr_cache ci_uvm; +#endif + + /* + * Private members. + */ + struct proc *ci_fpcurproc; /* current owner of the FPU */ + struct proc *ci_fpsaveproc; + int ci_fpsaving; /* save in progress */ + + struct pcb *ci_curpcb; /* VA of current HW PCB */ + struct pcb *ci_idle_pcb; /* VA of current PCB */ + struct pmap *ci_curpmap; + + struct intrsource *ci_isources[MAX_INTR_SOURCES]; + u_int32_t ci_ipending; + int ci_ilevel; + int ci_idepth; + u_int32_t ci_imask[NIPL]; + u_int32_t ci_iunmask[NIPL]; +#ifdef DIAGNOSTIC + int ci_mutex_level; +#endif + + paddr_t ci_idle_pcb_paddr; /* PA of idle PCB */ + volatile u_long ci_flags; /* flags; see below */ + u_int32_t ci_ipis; /* interprocessor interrupts pending */ + + u_int32_t ci_level; + u_int32_t ci_vendor[4]; + u_int32_t ci_signature; /* X86 cpuid type */ + u_int32_t ci_family; /* extended cpuid family */ + u_int32_t ci_model; /* extended cpuid model */ + u_int32_t ci_feature_flags; /* X86 CPUID feature bits */ + u_int32_t ci_feature_sefflags_ebx;/* more CPUID feature bits */ + u_int32_t ci_feature_sefflags_ecx;/* more CPUID feature bits */ + u_int32_t ci_feature_sefflags_edx;/* more CPUID feature bits */ + u_int32_t ci_feature_tpmflags; /* thermal & power bits */ + u_int32_t cpu_class; /* CPU class */ + u_int32_t ci_cflushsz; /* clflush cache-line size */ + + int ci_inatomic; + + struct cpu_functions *ci_func; /* start/stop functions */ + void (*cpu_setup)(struct cpu_info *); /* proc-dependant init */ + + struct device *ci_acpicpudev; + volatile u_int ci_mwait; +#define MWAIT_IN_IDLE 0x1 /* don't need IPI to wake */ +#define MWAIT_KEEP_IDLING 0x2 /* cleared by other cpus to wake me */ +#define MWAIT_ONLY 0x4 /* set if all idle states use mwait */ +#define MWAIT_IDLING (MWAIT_IN_IDLE | MWAIT_KEEP_IDLING) + + int ci_want_resched; + + union descriptor *ci_gdt; + struct i386tss *ci_tss; + struct i386tss *ci_nmi_tss; + + volatile int ci_ddb_paused; /* paused due to other proc in ddb */ +#define CI_DDB_RUNNING 0 +#define CI_DDB_SHOULDSTOP 1 +#define CI_DDB_STOPPED 2 +#define CI_DDB_ENTERDDB 3 +#define CI_DDB_INDDB 4 + + struct ksensordev ci_sensordev; + struct ksensor ci_sensor; +#if defined(GPROF) || defined(DDBPROF) + struct gmonparam *ci_gmon; + struct clockintr ci_gmonclock; +#endif + struct clockqueue ci_queue; + char ci_panicbuf[512]; +}; + +/* + * Processor flag notes: The "primary" CPU has certain MI-defined + * roles (mostly relating to hardclock handling); we distinguish + * between the processor which booted us, and the processor currently + * holding the "primary" role just to give us the flexibility later to + * change primaries should we be sufficiently twisted. + */ + +#define CPUF_BSP 0x0001 /* CPU is the original BSP */ +#define CPUF_AP 0x0002 /* CPU is an AP */ +#define CPUF_SP 0x0004 /* CPU is only processor */ +#define CPUF_PRIMARY 0x0008 /* CPU is active primary processor */ +#define CPUF_APIC_CD 0x0010 /* CPU has apic configured */ +#define CPUF_CONST_TSC 0x0020 /* CPU has constant TSC */ + +#define CPUF_PRESENT 0x1000 /* CPU is present */ +#define CPUF_RUNNING 0x2000 /* CPU is running */ +#define CPUF_VMM 0x4000 /* CPU is executing in VMM mode */ + +/* + * We statically allocate the CPU info for the primary CPU (or, + * the only CPU on uniprocessors), and the primary CPU is the + * first CPU on the CPU info list. + */ +struct cpu_info_full; +extern struct cpu_info_full cpu_info_full_primary; +#define cpu_info_primary (*(struct cpu_info *)((char *)&cpu_info_full_primary + PAGE_SIZE*2 - offsetof(struct cpu_info, ci_PAGEALIGN))) + +extern struct cpu_info *cpu_info_list; + +#define CPU_INFO_ITERATOR int +#define CPU_INFO_FOREACH(cii, ci) for (cii = 0, ci = cpu_info_list; \ + ci != NULL; ci = ci->ci_next) + +#define CPU_INFO_UNIT(ci) ((ci)->ci_dev ? (ci)->ci_dev->dv_unit : 0) + +#ifdef MULTIPROCESSOR + +#define MAXCPUS 32 /* because we use a bitmask */ + +#define CPU_STARTUP(_ci) ((_ci)->ci_func->start(_ci)) +#define CPU_STOP(_ci) ((_ci)->ci_func->stop(_ci)) +#define CPU_START_CLEANUP(_ci) ((_ci)->ci_func->cleanup(_ci)) + +static struct cpu_info *curcpu(void); + +static __inline struct cpu_info * +curcpu(void) +{ + struct cpu_info *ci; + + /* Can't include sys/param.h for offsetof() since it includes us */ + __asm volatile("movl %%fs:%1, %0" : + "=r" (ci) : "m" + (*(struct cpu_info * const *)&((struct cpu_info *)0)->ci_self)); + return ci; +} +#define cpu_number() (curcpu()->ci_cpuid) + +#define CPU_IS_PRIMARY(ci) ((ci)->ci_flags & CPUF_PRIMARY) +#define CPU_IS_RUNNING(ci) ((ci)->ci_flags & CPUF_RUNNING) + +extern struct cpu_info *cpu_info[MAXCPUS]; + +extern void cpu_boot_secondary_processors(void); +extern void cpu_init_idle_pcbs(void); + +void cpu_kick(struct cpu_info *); +void cpu_unidle(struct cpu_info *); + +#define CPU_BUSY_CYCLE() __asm volatile("pause": : : "memory") + +#else /* MULTIPROCESSOR */ + +#define MAXCPUS 1 + +#define cpu_number() 0 +#define curcpu() (&cpu_info_primary) + +#define CPU_IS_PRIMARY(ci) 1 +#define CPU_IS_RUNNING(ci) 1 + +#define cpu_kick(ci) +#define cpu_unidle(ci) + +#define CPU_BUSY_CYCLE() __asm volatile ("" ::: "memory") + +#endif + +#include + +#define aston(p) ((p)->p_md.md_astpending = 1) + +#define curpcb curcpu()->ci_curpcb + +unsigned int cpu_rnd_messybits(void); + +/* + * Preempt the current process if in interrupt from user mode, + * or after the current trap/syscall if in system mode. + */ +extern void need_resched(struct cpu_info *); +#define clear_resched(ci) (ci)->ci_want_resched = 0 + +#define CLKF_USERMODE(frame) USERMODE((frame)->if_cs, (frame)->if_eflags) +#define CLKF_PC(frame) ((frame)->if_eip) +#define CLKF_INTR(frame) (IDXSEL((frame)->if_cs) == GICODE_SEL) + +/* + * This is used during profiling to integrate system time. + */ +#define PROC_PC(p) ((p)->p_md.md_regs->tf_eip) +#define PROC_STACK(p) ((p)->p_md.md_regs->tf_esp) + +/* + * Give a profiling tick to the current process when the user profiling + * buffer pages are invalid. On the i386, request an ast to send us + * through trap(), marking the proc as needing a profiling tick. + */ +#define need_proftick(p) aston(p) + +/* + * Notify the current process (p) that it has a signal pending, + * process as soon as possible. + */ +void signotify(struct proc *); + +/* + * We need a machine-independent name for this. + */ +extern void (*delay_func)(int); +void delay_fini(void(*)(int)); +void delay_init(void(*)(int), int); +struct timeval; + +#define DELAY(x) (*delay_func)(x) +#define delay(x) (*delay_func)(x) + +/* + * High resolution clock support (Pentium only) + */ +void calibrate_cyclecounter(void); + +/* + * pull in #defines for kinds of processors + */ +#include + +struct cpu_cpuid_nameclass { + const char *cpu_id; + int cpu_vendor; + const char *cpu_vendorname; + struct cpu_cpuid_family { + int cpu_class; + const char *cpu_models[CPU_MAXMODEL+2]; + void (*cpu_setup)(struct cpu_info *); + } cpu_family[CPU_MAXFAMILY - CPU_MINFAMILY + 1]; +}; + +struct cpu_cpuid_feature { + int feature_bit; + const char *feature_name; +}; + +/* locore.s */ +extern int cpu_id; +extern char cpu_vendor[]; /* note: NOT nul-terminated */ +extern char cpu_brandstr[]; +extern int cpuid_level; +extern int cpu_miscinfo; +extern int cpu_feature; +extern int ecpu_feature; +extern int cpu_ecxfeature; +extern int ecpu_ecxfeature; +extern int cpu_cache_eax; +extern int cpu_cache_ebx; +extern int cpu_cache_ecx; +extern int cpu_cache_edx; +extern int cpu_perf_eax; +extern int cpu_perf_ebx; +extern int cpu_perf_edx; +extern int cpu_apmi_edx; +extern int cpu_pae; /* cpu has both PAE and NX features */ + +/* cpu.c */ +extern u_int cpu_mwait_size; +extern u_int cpu_mwait_states; +extern void cpu_update_nmi_cr3(vaddr_t); +extern void cpu_tsx_disable(struct cpu_info *); + +/* machdep.c */ +extern int cpu_apmhalt; +extern int cpu_class; +extern char cpu_model[]; +extern const struct cpu_cpuid_nameclass i386_cpuid_cpus[]; +extern void (*cpu_idle_enter_fcn)(void); +extern void (*cpu_idle_cycle_fcn)(void); +extern void (*cpu_idle_leave_fcn)(void); +extern void (*cpu_suspend_cycle_fcn)(void); + +extern int cpuspeed; + +#if !defined(SMALL_KERNEL) +#define BUS66 6667 +#define BUS100 10000 +#define BUS133 13333 +#define BUS166 16667 +#define BUS200 20000 +#define BUS266 26667 +#define BUS333 33333 +extern int bus_clock; +#endif + +/* F00F bug fix stuff for pentium cpu */ +extern int cpu_f00f_bug; +void fix_f00f(void); + +/* dkcsum.c */ +void dkcsumattach(void); + +extern int i386_use_fxsave; +extern int i386_has_sse; +extern int i386_has_sse2; + +extern void (*update_cpuspeed)(void); + +extern void (*initclock_func)(void); +extern void (*startclock_func)(void); + +/* machdep.c */ +void dumpconf(void); +void cpu_reset(void); +void i386_proc0_tss_init(void); +void i386_init_pcb_tss(struct cpu_info *); +void cpuid(u_int32_t, u_int32_t *); + +/* locore.s */ +struct region_descriptor; +void lgdt(struct region_descriptor *); + +struct pcb; +void savectx(struct pcb *); +void proc_trampoline(void); + +/* clock.c */ +void startclocks(void); +void rtcinit(void); +void rtcstart(void); +void rtcstop(void); +void i8254_delay(int); +void i8254_initclocks(void); +void i8254_startclock(void); +void i8254_start_both_clocks(void); +void i8254_inittimecounter(void); +void i8254_inittimecounter_simple(void); + +#if !defined(SMALL_KERNEL) +/* est.c */ +void est_init(struct cpu_info *, int); +void est_setperf(int); +/* longrun.c */ +void longrun_init(void); +void longrun_setperf(int); +/* p4tcc.c */ +void p4tcc_init(int, int); +void p4tcc_setperf(int); +/* powernow.c */ +void k6_powernow_init(void); +void k6_powernow_setperf(int); +/* powernow-k7.c */ +void k7_powernow_init(void); +void k7_powernow_setperf(int); +/* powernow-k8.c */ +void k8_powernow_init(void); +void k8_powernow_setperf(int); +/* k1x-pstate.c */ +void k1x_init(struct cpu_info *); +void k1x_setperf(int); +#endif + +/* npx.c */ +void npxsave_proc(struct proc *, int); +void npxsave_cpu(struct cpu_info *, int); + +/* isa_machdep.c */ +void isa_defaultirq(void); +int isa_nmi(void); + +/* pmap.c */ +void pmap_bootstrap(vaddr_t); + +/* vm_machdep.c */ +int kvtop(caddr_t); + +#ifdef MULTIPROCESSOR +/* mp_setperf.c */ +void mp_setperf_init(void); +#endif + +int cpu_paenable(void *); +#endif /* _KERNEL */ + +/* + * CTL_MACHDEP definitions. + */ +#define CPU_CONSDEV 1 /* dev_t: console terminal device */ +#define CPU_BIOS 2 /* BIOS variables */ +#define CPU_BLK2CHR 3 /* convert blk maj into chr one */ +#define CPU_CHR2BLK 4 /* convert chr maj into blk one */ +#define CPU_ALLOWAPERTURE 5 /* allow mmap of /dev/xf86 */ +#define CPU_CPUVENDOR 6 /* cpuid vendor string */ +#define CPU_CPUID 7 /* cpuid */ +#define CPU_CPUFEATURE 8 /* cpuid features */ +#define CPU_KBDRESET 10 /* keyboard reset under pcvt */ +#define CPU_OSFXSR 13 /* uses FXSAVE/FXRSTOR */ +#define CPU_SSE 14 /* supports SSE */ +#define CPU_SSE2 15 /* supports SSE2 */ +#define CPU_XCRYPT 16 /* supports VIA xcrypt in userland */ +#define CPU_LIDACTION 18 /* action caused by lid close */ +#define CPU_FORCEUKBD 19 /* Force ukbd(4) as console keyboard */ +#define CPU_MAXID 20 /* number of valid machdep ids */ + +#define CTL_MACHDEP_NAMES { \ + { 0, 0 }, \ + { "console_device", CTLTYPE_STRUCT }, \ + { "bios", CTLTYPE_INT }, \ + { "blk2chr", CTLTYPE_STRUCT }, \ + { "chr2blk", CTLTYPE_STRUCT }, \ + { "allowaperture", CTLTYPE_INT }, \ + { "cpuvendor", CTLTYPE_STRING }, \ + { "cpuid", CTLTYPE_INT }, \ + { "cpufeature", CTLTYPE_INT }, \ + { 0, 0 }, \ + { "kbdreset", CTLTYPE_INT }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "osfxsr", CTLTYPE_INT }, \ + { "sse", CTLTYPE_INT }, \ + { "sse2", CTLTYPE_INT }, \ + { "xcrypt", CTLTYPE_INT }, \ + { 0, 0 }, \ + { "lidaction", CTLTYPE_INT }, \ + { "forceukbd", CTLTYPE_INT }, \ +} + +/* + * This needs to be included late since it relies on definitions higher + * up in this file. + */ +#if defined(MULTIPROCESSOR) && defined(_KERNEL) +#include +#endif + +#endif /* !_MACHINE_CPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/cpu_full.h b/lib/libc/include/x86-openbsd-none/machine/cpu_full.h new file mode 100644 index 000000000000..fd87a09aada8 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/cpu_full.h @@ -0,0 +1,67 @@ +/* $OpenBSD: cpu_full.h,v 1.3 2018/06/22 13:21:14 bluhm Exp $ */ +/* + * Copyright (c) 2018 Philip Guenther + * Copyright (c) 2018 Hans-Joerg Hoexer + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_CPU_FULL_H_ +#define _MACHINE_CPU_FULL_H_ + +#include /* offsetof, PAGE_SIZE */ +#include +#include + +struct cpu_info_full { + /* page mapped kRO in u-k */ + union { + struct { + struct i386tss uu_tss; + struct i386tss uu_nmi_tss; + union descriptor uu_gdt[NGDT]; + } u_tssgdt; + char u_align[PAGE_SIZE]; + } cif_TSS_RO; +#define cif_tss cif_TSS_RO.u_tssgdt.uu_tss +#define cif_nmi_tss cif_TSS_RO.u_tssgdt.uu_nmi_tss +#define cif_gdt cif_TSS_RO.u_tssgdt.uu_gdt + + /* start of page mapped kRW in u-k */ + uint32_t cif_tramp_stack[(PAGE_SIZE / 4 + - offsetof(struct cpu_info, ci_PAGEALIGN)) / sizeof(uint32_t)]; + uint32_t cif_nmi_stack[(3 * PAGE_SIZE / 4) / sizeof(uint32_t)]; + + /* + * Beginning of this hangs over into the kRW page; rest is + * unmapped in u-k + */ + struct cpu_info cif_cpu; +} __aligned(PAGE_SIZE); + +/* tss, align shim, and gdt must fit in a page */ +CTASSERT(_ALIGN(2 * sizeof(struct i386tss)) + + sizeof(struct segment_descriptor) * NGDT < PAGE_SIZE); + +/* verify expected alignment */ +CTASSERT(offsetof(struct cpu_info_full, cif_cpu.ci_PAGEALIGN) % PAGE_SIZE == 0); + +/* verify total size is multiple of page size */ +CTASSERT(sizeof(struct cpu_info_full) % PAGE_SIZE == 0); + +extern struct cpu_info_full cpu_info_full_primary; + +/* Now make sure the cpu_info_primary macro is correct */ +CTASSERT(&cpu_info_primary - &cpu_info_full_primary.cif_cpu == 0); + +#endif /* _MACHINE_CPU_FULL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/cpufunc.h b/lib/libc/include/x86-openbsd-none/machine/cpufunc.h new file mode 100644 index 000000000000..a13a9ba4a92a --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/cpufunc.h @@ -0,0 +1,310 @@ +/* $OpenBSD: cpufunc.h,v 1.34 2025/06/20 14:06:34 sf Exp $ */ +/* $NetBSD: cpufunc.h,v 1.8 1994/10/27 04:15:59 cgd Exp $ */ + +/* + * Copyright (c) 1993 Charles Hannum. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Charles Hannum. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_CPUFUNC_H_ +#define _MACHINE_CPUFUNC_H_ + +#ifdef _KERNEL + +/* + * Functions to provide access to i386-specific instructions. + */ + +#include + +#include + +static __inline void invlpg(u_int); +static __inline void lidt(void *); +static __inline void lldt(u_short); +static __inline void ltr(u_short); +static __inline void lcr0(u_int); +static __inline u_int rcr0(void); +static __inline u_int rcr2(void); +static __inline void lcr3(u_int); +static __inline u_int rcr3(void); +static __inline void lcr4(u_int); +static __inline u_int rcr4(void); +static __inline void tlbflush(void); +static __inline u_int read_eflags(void); +static __inline void write_eflags(u_int); +static __inline void wbinvd(void); +static __inline void clflush(u_int32_t addr); +static __inline void mfence(void); +static __inline void wrmsr(u_int, u_int64_t); +static __inline u_int64_t rdmsr(u_int); +static __inline void breakpoint(void); + +static __inline void +invlpg(u_int addr) +{ + __asm volatile("invlpg (%0)" : : "r" (addr) : "memory"); +} + +static __inline void +lidt(void *p) +{ + __asm volatile("lidt (%0)" : : "r" (p) : "memory"); +} + +static __inline void +lldt(u_short sel) +{ + __asm volatile("lldt %0" : : "r" (sel)); +} + +static __inline void +ltr(u_short sel) +{ + __asm volatile("ltr %0" : : "r" (sel)); +} + +static __inline void +lcr0(u_int val) +{ + __asm volatile("movl %0,%%cr0" : : "r" (val)); +} + +static __inline u_int +rcr0(void) +{ + u_int val; + __asm volatile("movl %%cr0,%0" : "=r" (val)); + return val; +} + +static __inline u_int +rcr2(void) +{ + u_int val; + __asm volatile("movl %%cr2,%0" : "=r" (val)); + return val; +} + +static __inline void +lcr3(u_int val) +{ + __asm volatile("movl %0,%%cr3" : : "r" (val)); +} + +static __inline u_int +rcr3(void) +{ + u_int val; + __asm volatile("movl %%cr3,%0" : "=r" (val)); + return val; +} + +static __inline void +lcr4(u_int val) +{ + __asm volatile("movl %0,%%cr4" : : "r" (val)); +} + +static __inline u_int +rcr4(void) +{ + u_int val; + __asm volatile("movl %%cr4,%0" : "=r" (val)); + return val; +} + +static __inline void +tlbflush(void) +{ + u_int val; + __asm volatile("movl %%cr3,%0" : "=r" (val)); + __asm volatile("movl %0,%%cr3" : : "r" (val)); +} + +#ifdef notyet +void setidt(int idx, /*XXX*/caddr_t func, int typ, int dpl); +#endif + + +/* XXXX ought to be in psl.h with spl() functions */ + +static __inline u_int +read_eflags(void) +{ + u_int ef; + + __asm volatile("pushfl; popl %0" : "=r" (ef)); + return (ef); +} + +static __inline void +write_eflags(u_int ef) +{ + __asm volatile("pushl %0; popfl" : : "r" (ef)); +} + +static inline void +intr_enable(void) +{ + __asm volatile("sti"); +} + +static inline u_long +intr_disable(void) +{ + u_long ef; + + ef = read_eflags(); + __asm volatile("cli"); + return (ef); +} + +static inline void +intr_restore(u_long ef) +{ + write_eflags(ef); +} + +static __inline void +wbinvd(void) +{ + __asm volatile("wbinvd" : : : "memory"); +} + +#ifdef MULTIPROCESSOR +int wbinvd_on_all_cpus(void); +#else +static inline int +wbinvd_on_all_cpus(void) +{ + wbinvd(); + return 0; +} +#endif + +static __inline void +clflush(u_int32_t addr) +{ + __asm volatile("clflush %0" : "+m" (*(volatile char *)addr)); +} + +static __inline void +mfence(void) +{ + __asm volatile("mfence" : : : "memory"); +} + +static __inline u_int64_t +rdtsc(void) +{ + uint64_t tsc; + + __asm volatile("rdtsc" : "=A" (tsc)); + return (tsc); +} + +static inline uint64_t +rdtsc_lfence(void) +{ + uint64_t tsc; + + __asm volatile("lfence; rdtsc" : "=A" (tsc)); + return tsc; +} + +static __inline void +wrmsr(u_int msr, u_int64_t newval) +{ + __asm volatile("wrmsr" : : "A" (newval), "c" (msr)); +} + +static __inline u_int64_t +rdmsr(u_int msr) +{ + u_int64_t rv; + + __asm volatile("rdmsr" : "=A" (rv) : "c" (msr)); + return (rv); +} + +static __inline void +monitor(const volatile void *addr, u_long extensions, u_int hints) +{ + __asm volatile("monitor" + : : "a" (addr), "c" (extensions), "d" (hints)); +} + +static __inline void +mwait(u_long extensions, u_int hints) +{ + __asm volatile("mwait" : : "a" (hints), "c" (extensions)); +} + +/* + * Some of the undocumented AMD64 MSRs need a 'passcode' to access. + * + * See LinuxBIOSv2: src/cpu/amd/model_fxx/model_fxx_init.c + */ + +#define OPTERON_MSR_PASSCODE 0x9c5a203a + +static __inline u_int64_t +rdmsr_locked(u_int msr, u_int code) +{ + uint64_t rv; + __asm volatile("rdmsr" + : "=A" (rv) + : "c" (msr), "D" (code)); + return (rv); +} + +static __inline void +wrmsr_locked(u_int msr, u_int code, u_int64_t newval) +{ + __asm volatile("wrmsr" + : + : "A" (newval), "c" (msr), "D" (code)); +} + +/* Break into DDB. */ +static __inline void +breakpoint(void) +{ + __asm volatile("int $3"); +} + +void amd64_errata(struct cpu_info *); +void cpu_ucode_setup(void); +void cpu_ucode_apply(struct cpu_info *); + +struct cpu_info_full; +void cpu_enter_pages(struct cpu_info_full *); + +#endif /* _KERNEL */ +#endif /* !_MACHINE_CPUFUNC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/cputypes.h b/lib/libc/include/x86-openbsd-none/machine/cputypes.h new file mode 100644 index 000000000000..0cd4be7abc39 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/cputypes.h @@ -0,0 +1,60 @@ +/* $OpenBSD: cputypes.h,v 1.15 2022/08/22 08:53:55 jsg Exp $ */ +/* $NetBSD: cputypes.h,v 1.10 1997/10/18 04:51:03 mikel Exp $ */ + +/* + * Copyright (c) 1993 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Classes of Processor + */ + +#define CPUCLASS_486 1 +#define CPUCLASS_586 2 +#define CPUCLASS_686 3 + +/* + * CPU vendors + */ + +#define CPUVENDOR_UNKNOWN -1 +#define CPUVENDOR_INTEL 0 +#define CPUVENDOR_CYRIX 1 +#define CPUVENDOR_AMD 3 +#define CPUVENDOR_IDT 4 +#define CPUVENDOR_TRANSMETA 6 +#define CPUVENDOR_NS 7 +#define CPUVENDOR_VIA 8 +#define CPUVENDOR_SIS 9 + +/* + * Some other defines, dealing with values returned by cpuid. + */ + +#define CPU_MAXMODEL 15 /* Models within family range 0-15 */ +#define CPU_DEFMODEL 16 /* Value for unknown model -> default */ +#define CPU_MINFAMILY 4 /* Lowest that cpuid can return (486) */ +#define CPU_MAXFAMILY 0xf /* Highest we know (686) */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/cpuvar.h b/lib/libc/include/x86-openbsd-none/machine/cpuvar.h new file mode 100644 index 000000000000..e420bbdc642d --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/cpuvar.h @@ -0,0 +1,98 @@ +/* $OpenBSD: cpuvar.h,v 1.8 2024/10/21 03:07:54 jsg Exp $ */ +/* $NetBSD: cpuvar.h,v 1.1.2.3 2000/02/21 18:54:07 sommerfeld Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1999 Stefan Grefen + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +struct cpu_functions { + int (*start)(struct cpu_info *); + int (*stop)(struct cpu_info *); + void (*cleanup)(struct cpu_info *); +}; + +extern struct cpu_functions mp_cpu_funcs; + +#define CPU_ROLE_SP 0 +#define CPU_ROLE_BP 1 +#define CPU_ROLE_AP 2 + +struct cpu_attach_args { + const char *caa_name; + int cpu_apicid; + int cpu_acpi_proc_id; + int cpu_role; + struct cpu_functions *cpu_func; + int cpu_signature; + int feature_flags; +}; + +#ifdef _KERNEL + +void i386_ipi(int,int,int); +void i386_ipi_init(int); + +void identifycpu(struct cpu_info *); +void cpu_init(struct cpu_info *); +void cpu_init_first(void); + +#endif \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/db_machdep.h b/lib/libc/include/x86-openbsd-none/machine/db_machdep.h new file mode 100644 index 000000000000..720fb23437af --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/db_machdep.h @@ -0,0 +1,94 @@ +/* $OpenBSD: db_machdep.h,v 1.30 2021/08/30 08:11:12 jasper Exp $ */ +/* $NetBSD: db_machdep.h,v 1.9 1996/05/03 19:23:59 christos Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#ifndef _MACHINE_DB_MACHDEP_H_ +#define _MACHINE_DB_MACHDEP_H_ + +/* + * Machine-dependent defines for new kernel debugger. + */ + +#include +#include +#include + +typedef long db_expr_t; /* expression - signed */ + +typedef struct trapframe db_regs_t; +extern db_regs_t ddb_regs; /* register state */ + +#define PC_REGS(regs) ((vaddr_t)(regs)->tf_eip) +#define SET_PC_REGS(regs, value) (regs)->tf_eip = (int)(value) + +#define BKPT_INST 0xcc /* breakpoint instruction */ +#define BKPT_SIZE (1) /* size of breakpoint inst */ +#define BKPT_SET(inst) (BKPT_INST) + +#define SSF_INST 0x55 +#define SSF_SIZE (1) + +#define FIXUP_PC_AFTER_BREAK(regs) ((regs)->tf_eip -= BKPT_SIZE) + +#define db_clear_single_step(regs) ((regs)->tf_eflags &= ~PSL_T) +#define db_set_single_step(regs) ((regs)->tf_eflags |= PSL_T) + +#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BPTFLT) +#define IS_WATCHPOINT_TRAP(type, code) ((type) == T_TRCTRAP && (code) & 15) + +#define I_CALL 0xe8 +#define I_CALLI 0xff +#define I_RET 0xc3 +#define I_IRET 0xcf + +#define inst_trap_return(ins) (((ins)&0xff) == I_IRET) +#define inst_return(ins) (((ins)&0xff) == I_RET) +#define inst_call(ins) (((ins)&0xff) == I_CALL || \ + (((ins)&0xff) == I_CALLI && \ + ((ins)&0x3800) == 0x1000)) + +#define DB_MACHINE_COMMANDS + +/* macro for checking if a thread has used floating-point */ + +int db_ktrap(int, int, db_regs_t *); + +void db_machine_init(void); +int db_enter_ddb(void); +void db_startcpu(int); +void db_stopcpu(int); +void i386_ipi_db(struct cpu_info *); + +extern struct db_mutex ddb_mp_mutex; + +/* For ddb_state */ +#define DDB_STATE_NOT_RUNNING 0 +#define DDB_STATE_RUNNING 1 +#define DDB_STATE_EXITING 2 + +#endif /* _MACHINE_DB_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/disklabel.h b/lib/libc/include/x86-openbsd-none/machine/disklabel.h new file mode 100644 index 000000000000..4d97c53ec23c --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/disklabel.h @@ -0,0 +1,40 @@ +/* $OpenBSD: disklabel.h,v 1.35 2015/09/30 14:57:03 krw Exp $ */ + +/* + * Copyright (c) 1994 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_DISKLABEL_H_ +#define _MACHINE_DISKLABEL_H_ + +#define LABELSECTOR 1 /* sector containing label */ +#define LABELOFFSET 0 /* offset of label in sector */ +#define MAXPARTITIONS 16 /* number of partitions */ + +#endif /* _MACHINE_DISKLABEL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/endian.h b/lib/libc/include/x86-openbsd-none/machine/endian.h new file mode 100644 index 000000000000..146c79b32c4b --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/endian.h @@ -0,0 +1,36 @@ +/* $OpenBSD: endian.h,v 1.20 2024/05/07 14:26:48 naddy Exp $ */ + +/*- + * Copyright (c) 1997 Niklas Hallqvist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_ENDIAN_H_ +#define _MACHINE_ENDIAN_H_ + +#define _BYTE_ORDER _LITTLE_ENDIAN + +#ifndef __FROM_SYS__ENDIAN +#include +#endif + +#endif /* _MACHINE_ENDIAN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/exec.h b/lib/libc/include/x86-openbsd-none/machine/exec.h new file mode 100644 index 000000000000..aed3f3c61650 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/exec.h @@ -0,0 +1,43 @@ +/* $OpenBSD: exec.h,v 1.14 2017/02/08 05:09:25 guenther Exp $ */ +/* $NetBSD: exec.h,v 1.6 1994/10/27 04:16:05 cgd Exp $ */ + +/* + * Copyright (c) 1993 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_EXEC_H_ +#define _MACHINE_EXEC_H_ + +#define __LDPGSZ 4096 + +#define ARCH_ELFSIZE 32 + +#define ELF_TARG_CLASS ELFCLASS32 +#define ELF_TARG_DATA ELFDATA2LSB +#define ELF_TARG_MACH EM_386 /* XXX - EM_486 is currently unused + by all OSs/compilers/linkers */ + +#endif /* _MACHINE_EXEC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/fenv.h b/lib/libc/include/x86-openbsd-none/machine/fenv.h new file mode 100644 index 000000000000..febe5dc2968a --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/fenv.h @@ -0,0 +1,115 @@ +/* $OpenBSD: fenv.h,v 1.3 2011/05/25 21:46:49 martynas Exp $ */ +/* $NetBSD: fenv.h,v 1.1.6.2 2010/10/24 22:48:02 jym Exp $ */ + +/*- + * Copyright (c) 2004-2005 David Schultz + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _I386_FENV_H_ +#define _I386_FENV_H_ + +/* + * Each symbol representing a floating point exception expands to an integer + * constant expression with values, such that bitwise-inclusive ORs of _all + * combinations_ of the constants result in distinct values. + * + * We use such values that allow direct bitwise operations on FPU/SSE registers. + */ +#define FE_INVALID 0x01 +#define FE_DENORMAL 0x02 +#define FE_DIVBYZERO 0x04 +#define FE_OVERFLOW 0x08 +#define FE_UNDERFLOW 0x10 +#define FE_INEXACT 0x20 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * exception constants defined above. + */ +#define FE_ALL_EXCEPT (FE_INVALID | FE_DENORMAL | FE_DIVBYZERO | \ + FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) +#define _SSE_MASK_SHIFT 7 + +/* + * Each symbol representing the rounding direction, expands to an integer + * constant expression whose value is distinct non-negative value. + * + * We use such values that allow direct bitwise operations on FPU/SSE registers. + */ +#define FE_TONEAREST 0x000 +#define FE_DOWNWARD 0x400 +#define FE_UPWARD 0x800 +#define FE_TOWARDZERO 0xc00 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * rounding direction constants defined above. + */ +#define _X87_ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | \ + FE_TOWARDZERO) +#define _SSE_ROUND_SHIFT 3 + +/* + * fenv_t represents the entire floating-point environment. + */ +typedef struct { + struct { + unsigned int __control; /* Control word register */ + unsigned int __status; /* Status word register */ + unsigned int __tag; /* Tag word register */ + unsigned int __others[4]; /* EIP, Pointer Selector, etc */ + } __x87; + unsigned int __mxcsr; /* Control, status register */ +} fenv_t; + +/* + * The following constant represents the default floating-point environment + * (that is, the one installed at program startup) and has type pointer to + * const-qualified fenv_t. + * + * It can be used as an argument to the functions within the header + * that manage the floating-point environment, namely fesetenv() and + * feupdateenv(). + */ +__BEGIN_DECLS +extern fenv_t __fe_dfl_env; +__END_DECLS +#define FE_DFL_ENV ((const fenv_t *)&__fe_dfl_env) + +/* + * fexcept_t represents the floating-point status flags collectively, including + * any status the implementation associates with the flags. + * + * A floating-point status flag is a system variable whose value is set (but + * never cleared) when a floating-point exception is raised, which occurs as a + * side effect of exceptional floating-point arithmetic to provide auxiliary + * information. + * + * A floating-point control mode is a system variable whose value may be set by + * the user to affect the subsequent behavior of floating-point arithmetic. + */ +typedef unsigned int fexcept_t; + +#endif /* !_I386_FENV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/frame.h b/lib/libc/include/x86-openbsd-none/machine/frame.h new file mode 100644 index 000000000000..dbdb06fd21b9 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/frame.h @@ -0,0 +1,173 @@ +/* $OpenBSD: frame.h,v 1.13 2018/06/15 17:58:41 bluhm Exp $ */ +/* $NetBSD: frame.h,v 1.12 1995/10/11 04:20:08 mycroft Exp $ */ + +/*- + * Copyright (c) 1995 Charles M. Hannum. All rights reserved. + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)frame.h 5.2 (Berkeley) 1/18/91 + */ + +#ifndef _MACHINE_FRAME_H +#define _MACHINE_FRAME_H +#include + +/* + * System stack frames. + */ + +/* + * Exception/Trap Stack Frame + */ +struct trapframe { + int tf_fs; + int tf_gs; + int tf_es; + int tf_ds; + int tf_edi; + int tf_esi; + int tf_err; /* not the hardware position */ + int tf_ebx; + int tf_edx; + int tf_ecx; + int tf_eax; + int tf_trapno; + /* below portion defined in 386 hardware */ + int tf_ebp; /* hardware puts err here, INTRENTRY() moves it up */ + int tf_eip; + int tf_cs; + int tf_eflags; + /* below used when transitting rings (e.g. user to kernel) */ + int tf_esp; + int tf_ss; + /* below used when switching out of VM86 mode */ + int tf_vm86_es; + int tf_vm86_ds; + int tf_vm86_fs; + int tf_vm86_gs; +}; + +/* + * Interrupt stack frame + */ +struct intrframe { + int if_ppl; + int if_fs; + int if_gs; + int if_es; + int if_ds; + int if_edi; + int if_esi; + int :32; /* for compat with trap frame - err */ + int if_ebx; + int if_edx; + int if_ecx; + int if_eax; + int :32; /* for compat with trap frame - trapno */ + int if_ebp; + /* below portion defined in 386 hardware */ + int if_eip; + int if_cs; + int if_eflags; + /* below only when transitting rings (e.g. user to kernel) */ + int if_esp; + int if_ss; +}; + +/* + * iret stack frame + */ +struct iretframe { + int irf_trapno; + int irf_err; + int irf_eip; + int irf_cs; + int irf_eflags; + int irf_esp; + int irf_ss; + /* below used when switching back to VM86 mode */ + int irf_vm86_es; + int irf_vm86_ds; + int irf_vm86_fs; + int irf_vm86_gs; +}; + +/* + * Trampoline stack frame + */ +struct trampframe { + int trf__deadbeef; + int trf__kern_esp; + int trf_fs; + int trf_eax; + int trf_ebp; + int trf_trapno; + int trf_err; + int trf_eip; + int trf_cs; + int trf_eflags; + int trf_esp; + int trf_ss; + /* below used when switching out of VM86 mode */ + int trf_vm86_es; + int trf_vm86_ds; + int trf_vm86_fs; + int trf_vm86_gs; +}; + +/* + * Stack frame inside cpu_switch() + */ +struct switchframe { + int sf_edi; + int sf_esi; + int sf_ebx; + int sf_eip; +}; + +struct callframe { + struct callframe *f_frame; + int f_retaddr; + int f_arg0; +}; + +/* + * Signal frame + */ +struct sigframe { + int sf_signum; + siginfo_t *sf_sip; + struct sigcontext *sf_scp; + sig_t sf_handler; + struct sigcontext sf_sc; + siginfo_t sf_si; +}; +#endif \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/gdt.h b/lib/libc/include/x86-openbsd-none/machine/gdt.h new file mode 100644 index 000000000000..d88017f3cf5a --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/gdt.h @@ -0,0 +1,43 @@ +/* $OpenBSD: gdt.h,v 1.18 2024/05/22 05:51:49 jsg Exp $ */ +/* $NetBSD: gdt.h,v 1.7.10.6 2002/08/19 01:22:36 sommerfeld Exp $ */ + +/*- + * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by John T. Kohl and Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LOCORE + +struct cpu_info; +struct pcb; +struct pmap; + +void gdt_alloc_cpu(struct cpu_info *); +void gdt_init(void); +void gdt_init_cpu(struct cpu_info *); +void setgdt(int, void *, size_t, int, int, int, int); +#endif \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/hibernate.h b/lib/libc/include/x86-openbsd-none/machine/hibernate.h new file mode 100644 index 000000000000..493fa4d82cc4 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/hibernate.h @@ -0,0 +1,35 @@ +/* $OpenBSD: hibernate.h,v 1.10 2018/06/21 07:33:30 mlarkin Exp $ */ + +/* + * Copyright (c) 2011 Mike Larkin + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +/* i386 hibernate support structures and functions */ + +int get_hibernate_info_md(union hibernate_info *); +void hibernate_flush(void); +void hibernate_enter_resume_mapping(vaddr_t, paddr_t, int); +int hibernate_inflate_skip(union hibernate_info *, paddr_t); +int hibernate_suspend(void); +void hibernate_switch_stack_machdep(void); +void hibernate_resume_machdep(vaddr_t); +void hibernate_activate_resume_pt_machdep(void); +void hibernate_enable_intr_machdep(void); +void hibernate_disable_intr_machdep(void); +#ifdef MULTIPROCESSOR +void hibernate_quiesce_cpus(void); +#endif /* MULTIPROCESSOR */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/hibernate_var.h b/lib/libc/include/x86-openbsd-none/machine/hibernate_var.h new file mode 100644 index 000000000000..e37fa095cec9 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/hibernate_var.h @@ -0,0 +1,53 @@ +/* $OpenBSD: hibernate_var.h,v 1.16 2025/05/21 04:05:22 mlarkin Exp $ */ + +/* + * Copyright (c) 2011 Mike Larkin + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define HIB_PD_MASK 0xffc00000 +#define PIGLET_PAGE_MASK (HIB_PD_MASK) + +#define HIBERNATE_PD_PAGE (PAGE_SIZE * 21) +#define HIBERNATE_PT_PAGE (PAGE_SIZE * 22) +/* 2 pages for stack */ +#define HIBERNATE_STACK_PAGE (PAGE_SIZE * 24) +#define HIBERNATE_INFLATE_PAGE (PAGE_SIZE * 25) +/* HIBERNATE_HIBALLOC_PAGE must be the last stolen page (see machdep.c) */ +#define HIBERNATE_HIBALLOC_PAGE (PAGE_SIZE * 26) + +/* Use 4MB hibernation chunks */ +#define HIBERNATE_CHUNK_SIZE 0x400000 + +#define HIBERNATE_CHUNK_TABLE_SIZE 0x100000 + +#define HIBERNATE_STACK_OFFSET 0x0F00 + +#define atop_4m(x) ((x) >> PDSHIFT) +#define atop_4k(x) ((x) >> PAGE_SHIFT) +#define s4pde_4m(va) ((pt_entry_t *)HIBERNATE_PD_PAGE + atop_4m(va)) +#define s4pde_4k(va) ((pt_entry_t *)HIBERNATE_PD_PAGE + atop_4k(va)) +#define s4pte_4k(va) ((pt_entry_t *)HIBERNATE_PT_PAGE + atop_4k(va)) + +/* + * Minimum amount of memory for hibernate support. This is used in early boot + * when deciding if we can preallocate the piglet. If the machine does not + * have at least HIBERNATE_MIN_MEMORY RAM, we won't support hibernate. This + * avoids late allocation issues due to fragmented memory and failure to + * hibernate. We need to be able to allocate 16MB contiguous memory, aligned + * to 2MB. + * + * The default minimum required memory is 512MB (1ULL << 29). + */ +#define HIBERNATE_MIN_MEMORY (1ULL << 29) \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/i82093reg.h b/lib/libc/include/x86-openbsd-none/machine/i82093reg.h new file mode 100644 index 000000000000..ac97c359552a --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/i82093reg.h @@ -0,0 +1,118 @@ +/* $OpenBSD: i82093reg.h,v 1.6 2022/12/08 01:25:45 guenther Exp $ */ +/* $NetBSD: i82093reg.h,v 1.1.2.2 2000/02/21 18:54:07 sommerfeld Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Typically, the first apic lives here. + */ +#define IOAPIC_BASE_DEFAULT 0xfec00000 + +/* + * Memory-space registers. + */ + +/* + * The externally visible registers are all 32 bits wide; + * store the register number of interest in IOAPIC_REG, and store/fetch + * the real value in IOAPIC_DATA. + */ +#define IOAPIC_REG 0x0000 +#define IOAPIC_DATA 0x0010 + +/* + * Internal I/O APIC registers. + */ + +#define IOAPIC_ID 0x00 + +#define IOAPIC_ID_SHIFT 24 +#define IOAPIC_ID_MASK 0x0f000000 + +/* Version, and maximum interrupt pin number. */ + +#define IOAPIC_VER 0x01 + +#define IOAPIC_VER_SHIFT 0 +#define IOAPIC_VER_MASK 0x000000ff + +#define IOAPIC_MAX_SHIFT 16 +#define IOAPIC_MAX_MASK 0x00ff0000 + +/* + * Arbitration ID. Same format as IOAPIC_ID register. + */ +#define IOAPIC_ARB 0x02 + +/* + * Redirection table registers. + */ + +#define IOAPIC_REDHI(pin) (0x11 + ((pin)<<1)) +#define IOAPIC_REDLO(pin) (0x10 + ((pin)<<1)) + +#define IOAPIC_REDHI_DEST_SHIFT 24 /* destination. */ +#define IOAPIC_REDHI_DEST_MASK 0xff000000 + +#define IOAPIC_REDLO_MASK 0x00010000 /* 0=enabled; 1=masked */ + +#define IOAPIC_REDLO_LEVEL 0x00008000 /* 0=edge, 1=level */ +#define IOAPIC_REDLO_RIRR 0x00004000 /* remote IRR; read only */ +#define IOAPIC_REDLO_ACTLO 0x00002000 /* 0=act. hi; 1=act. lo */ +#define IOAPIC_REDLO_DELSTS 0x00001000 /* 0=idle; 1=send pending */ +#define IOAPIC_REDLO_DSTMOD 0x00000800 /* 0=physical; 1=logical */ + +#define IOAPIC_REDLO_DEL_MASK 0x00000700 /* del. mode mask */ +#define IOAPIC_REDLO_DEL_SHIFT 8 + +#define IOAPIC_REDLO_DEL_FIXED 0 +#define IOAPIC_REDLO_DEL_LOPRI 1 +#define IOAPIC_REDLO_DEL_SMI 2 +#define IOAPIC_REDLO_DEL_NMI 4 +#define IOAPIC_REDLO_DEL_INIT 5 +#define IOAPIC_REDLO_DEL_EXTINT 7 + +#define IOAPIC_REDLO_VECTOR_MASK 0x000000ff /* delivery vector */ + +#define IMCR_ADDR 0x22 +#define IMCR_DATA 0x23 + +#define IMCR_REGISTER 0x70 +#define IMCR_PIC 0x00 +#define IMCR_APIC 0x01 + +#ifdef _KERNEL + +#define ioapic_asm_ack(num) \ + movl $0,local_apic + LAPIC_EOI + +#endif \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/i82093var.h b/lib/libc/include/x86-openbsd-none/machine/i82093var.h new file mode 100644 index 000000000000..a74a367ff814 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/i82093var.h @@ -0,0 +1,99 @@ +/* $OpenBSD: i82093var.h,v 1.13 2024/10/22 21:50:02 jsg Exp $ */ +/* $NetBSD: i82093var.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_I82093VAR_H_ +#define _MACHINE_I82093VAR_H_ + +#include + +struct ioapic_pin { + struct intrhand *ip_handler; + struct ioapic_pin *ip_next; /* next pin on this vector */ + struct mp_intr_map *ip_map; + int ip_vector; /* IDT vector */ + int ip_type; + int ip_minlevel; + int ip_maxlevel; +}; + +struct ioapic_softc { + struct pic sc_pic; + struct ioapic_softc *sc_next; + int sc_apicid; + int sc_apic_vers; + int sc_apic_vecbase; /* global int base if ACPI */ + int sc_apic_sz; /* apic size*/ + int sc_flags; + paddr_t sc_pa; /* PA of ioapic */ + volatile u_int32_t *sc_reg; /* KVA of ioapic addr */ + volatile u_int32_t *sc_data; /* KVA of ioapic data */ + struct ioapic_pin *sc_pins; /* sc_apic_sz entries */ +}; + +/* + * MP: intr_handle_t is bitfielded. + * ih&0xff -> line number. + * ih&0x10000000 -> if 0, old-style isa irq; if 1, routed via ioapic. + * (ih&0xff0000)>>16 -> ioapic id. + * (ih&0x00ff00)>>8 -> ioapic line. + */ + +#define APIC_INT_VIA_APIC 0x10000000 +#define APIC_INT_VIA_MSG 0x20000000 +#define APIC_INT_APIC_MASK 0x00ff0000 +#define APIC_INT_APIC_SHIFT 16 +#define APIC_INT_PIN_MASK 0x0000ff00 +#define APIC_INT_PIN_SHIFT 8 +#define APIC_INT_LINE_MASK 0x000000ff + +#define APIC_IRQ_APIC(x) ((x & APIC_INT_APIC_MASK) >> APIC_INT_APIC_SHIFT) +#define APIC_IRQ_PIN(x) ((x & APIC_INT_PIN_MASK) >> APIC_INT_PIN_SHIFT) + +void *apic_intr_establish(int, int, int, int (*)(void *), void *, + const char *); +void apic_intr_disestablish(void *); + +void ioapic_print_redir(struct ioapic_softc *, char *, int); +struct ioapic_softc *ioapic_find(int); +struct ioapic_softc *ioapic_find_bybase(int); + +void ioapic_enable(void); + +extern int ioapic_bsp_id; +extern int nioapics; +extern struct ioapic_softc *ioapics; +extern u_int16_t ioapic_id_map; +extern u_int8_t ioapic_id_remap[]; + +#endif /* !_MACHINE_I82093VAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/i82489reg.h b/lib/libc/include/x86-openbsd-none/machine/i82489reg.h new file mode 100644 index 000000000000..bb3c256cfb89 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/i82489reg.h @@ -0,0 +1,144 @@ +/* $OpenBSD: i82489reg.h,v 1.5 2019/07/26 04:35:38 kevlo Exp $ */ +/* $NetBSD: i82489reg.h,v 1.1.2.1 2000/02/20 16:30:27 sommerfeld Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Frank van der Linden. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +/* + * Registers and constants for the 82489DX and Pentium (and up) integrated + * "local" APIC. + */ + +#define LAPIC_ID 0x020 /* ID. RW */ +# define LAPIC_ID_MASK 0x0f000000 +# define LAPIC_ID_SHIFT 24 + +#define LAPIC_VERS 0x030 /* Version. R */ +# define LAPIC_VERSION_MASK 0x000000ff +# define LAPIC_VERSION_LVT_MASK 0x00ff0000 +# define LAPIC_VERSION_LVT_SHIFT 16 + +#define LAPIC_TPRI 0x080 /* Task Prio. RW */ +# define LAPIC_TPRI_MASK 0x000000ff +# define LAPIC_TPRI_INT_MASK 0x000000f0 +# define LAPIC_TPRI_SUB_MASK 0x0000000f + +#define LAPIC_APRI 0x090 /* Arbitration prio R */ +# define LAPIC_APRI_MASK 0x000000ff + +#define LAPIC_PPRI 0x0a0 /* Processor prio. R */ +#define LAPIC_EOI 0x0b0 /* End Int. W */ +#define LAPIC_RRR 0x0c0 /* Remote read R */ +#define LAPIC_LDR 0x0d0 /* Logical dest. RW */ +#define LAPIC_DFR 0x0e0 /* Dest. format RW */ + +#define LAPIC_SVR 0x0f0 /* Spurious intvec RW */ +# define LAPIC_SVR_VECTOR_MASK 0x000000ff +# define LAPIC_SVR_VEC_FIX 0x0000000f +# define LAPIC_SVR_VEC_PROG 0x000000f0 +# define LAPIC_SVR_ENABLE 0x00000100 +# define LAPIC_SVR_SWEN 0x00000100 +# define LAPIC_SVR_FOCUS 0x00000200 +# define LAPIC_SVR_FDIS 0x00000200 + +#define LAPIC_ISR 0x100 /* Int. status. R */ +#define LAPIC_TMR 0x180 +#define LAPIC_IRR 0x200 +#define LAPIC_ESR 0x280 /* Err status. R */ + +#define LAPIC_ICRLO 0x300 /* Int. cmd. RW */ +# define LAPIC_DLMODE_MASK 0x00000700 +# define LAPIC_DLMODE_FIXED 0x00000000 +# define LAPIC_DLMODE_LOW 0x00000100 +# define LAPIC_DLMODE_SMI 0x00000200 +# define LAPIC_DLMODE_RR 0x00000300 +# define LAPIC_DLMODE_NMI 0x00000400 +# define LAPIC_DLMODE_INIT 0x00000500 +# define LAPIC_DLMODE_STARTUP 0x00000600 + +# define LAPIC_DSTMODE_LOG 0x00000800 + +# define LAPIC_DLSTAT_BUSY 0x00001000 + +# define LAPIC_LVL_ASSERT 0x00004000 +# define LAPIC_LVL_DEASSERT 0x00000000 + +# define LAPIC_LVL_TRIG 0x00008000 + +# define LAPIC_RRSTAT_MASK 0x00030000 +# define LAPIC_RRSTAT_INPROG 0x00010000 +# define LAPIC_RRSTAT_VALID 0x00020000 + +# define LAPIC_DEST_MASK 0x000c0000 +# define LAPIC_DEST_SELF 0x00040000 +# define LAPIC_DEST_ALLINCL 0x00080000 +# define LAPIC_DEST_ALLEXCL 0x000c0000 + +# define LAPIC_RESV2_MASK 0xfff00000 + + +#define LAPIC_ICRHI 0x310 /* Int. cmd. RW */ + +#define LAPIC_LVTT 0x320 /* Loc.vec.(timer) RW */ +# define LAPIC_LVTT_VEC_MASK 0x000000ff +# define LAPIC_LVTT_DS 0x00001000 +# define LAPIC_LVTT_M 0x00010000 +# define LAPIC_LVTT_TM 0x00020000 +# define LAPIC_LVTT_TM_ONESHOT 0x00000000 +# define LAPIC_LVTT_TM_PERIODIC 0x00020000 +# define LAPIC_LVTT_TM_TSCDL 0x00040000 + +#define LAPIC_PCINT 0x340 +#define LAPIC_LVINT0 0x350 /* Loc.vec (LINT0) RW */ +# define LAPIC_LVT_PERIODIC 0x00020000 +# define LAPIC_LVT_MASKED 0x00010000 +# define LAPIC_LVT_LEVTRIG 0x00008000 +# define LAPIC_LVT_REMOTE_IRR 0x00004000 +# define LAPIC_INP_POL 0x00002000 +# define LAPIC_PEND_SEND 0x00001000 + +#define LAPIC_LVINT1 0x360 /* Loc.vec (LINT1) RW */ +#define LAPIC_LVERR 0x370 /* Loc.vec (ERROR) RW */ +#define LAPIC_ICR_TIMER 0x380 /* Initial count RW */ +#define LAPIC_CCR_TIMER 0x390 /* Current count RO */ + +#define LAPIC_DCR_TIMER 0x3e0 /* Divisor config register */ +# define LAPIC_DCRT_DIV1 0x0b +# define LAPIC_DCRT_DIV2 0x00 +# define LAPIC_DCRT_DIV4 0x01 +# define LAPIC_DCRT_DIV8 0x02 +# define LAPIC_DCRT_DIV16 0x03 +# define LAPIC_DCRT_DIV32 0x08 +# define LAPIC_DCRT_DIV64 0x09 +# define LAPIC_DCRT_DIV128 0x0a + +#define LAPIC_BASE 0xfee00000 + +#define LAPIC_IRQ_MASK(i) (1 << ((i) + 1)) \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/i82489var.h b/lib/libc/include/x86-openbsd-none/machine/i82489var.h new file mode 100644 index 000000000000..bfdf6811710d --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/i82489var.h @@ -0,0 +1,128 @@ +/* $OpenBSD: i82489var.h,v 1.16 2024/07/07 03:03:09 jsg Exp $ */ +/* $NetBSD: i82489var.h,v 1.1.2.2 2000/02/21 18:46:14 sommerfeld Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Frank van der Linden. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_I82489VAR_H_ +#define _MACHINE_I82489VAR_H_ + +static __inline__ u_int32_t i82489_readreg(int); +static __inline__ void i82489_writereg(int, u_int32_t); + +#ifdef _KERNEL +extern volatile u_int32_t local_apic[]; +#endif + +static __inline__ u_int32_t +i82489_readreg(int reg) +{ + return *((volatile u_int32_t *)(((volatile u_int8_t *)local_apic) + + reg)); +} + +static __inline__ void +i82489_writereg(int reg, u_int32_t val) +{ + *((volatile u_int32_t *)(((volatile u_int8_t *)local_apic) + reg)) = + val; + /* + * intel xeon errata p53: + * write to a lapic register sometimes may appear to have not occurred + * workaround: + * follow write with a read [from id register] + */ + val = *((volatile u_int32_t *)(((volatile u_int8_t *)local_apic) + + LAPIC_ID)); +} + +/* + * "spurious interrupt vector"; vector used by interrupt which was + * aborted because the CPU masked it after it happened but before it + * was delivered.. "Oh, sorry, i caught you at a bad time". + * Low-order 4 bits must be all ones. + */ +extern void Xintrspurious(void); +#define LAPIC_SPURIOUS_VECTOR 0xef + +/* + * Vector used for inter-processor interrupts. + */ +extern void Xintripi(void); +#define LAPIC_IPI_VECTOR IPL_IPI + +/* + * Vector used for local apic timer interrupts. + */ + +extern void Xintrltimer(void); +#define LAPIC_TIMER_VECTOR IPL_CLOCK + +/* + * Vectors to be used for self-soft-interrupts. + */ + +#define LAPIC_SOFTCLOCK_VECTOR IPL_SOFTCLOCK +#define LAPIC_SOFTNET_VECTOR IPL_SOFTNET +#define LAPIC_SOFTTTY_VECTOR IPL_SOFTTTY + +/* + * Special IPI vectors. We can use IDT 0xf0 - 0xff for this. + */ +#define LAPIC_IPI_OFFSET 0xf0 +#define LAPIC_IPI_INVLTLB (LAPIC_IPI_OFFSET + 0) +#define LAPIC_IPI_INVLPG (LAPIC_IPI_OFFSET + 1) +#define LAPIC_IPI_INVLRANGE (LAPIC_IPI_OFFSET + 2) +#define LAPIC_IPI_RELOADCR3 (LAPIC_IPI_OFFSET + 3) + +extern void Xintripi_invltlb(void); +extern void Xintripi_invlpg(void); +extern void Xintripi_invlrange(void); +extern void Xintripi_reloadcr3(void); + +extern void Xintrsoftclock(void); +extern void Xintrsoftnet(void); +extern void Xintrsofttty(void); + +extern void (*apichandler[])(void); + +struct cpu_info; + +extern void lapic_boot_init(paddr_t); +extern void lapic_startclock(void); +extern void lapic_initclocks(void); +extern void lapic_set_lvt(void); +extern void lapic_set_softvectors(void); +extern void lapic_enable(void); +extern void lapic_disable(void); +extern void lapic_calibrate_timer(struct cpu_info *); + +#define lapic_cpu_number() (i82489_readreg(LAPIC_ID)>>LAPIC_ID_SHIFT) + +#endif \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/i8259.h b/lib/libc/include/x86-openbsd-none/machine/i8259.h new file mode 100644 index 000000000000..724ae4f4f189 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/i8259.h @@ -0,0 +1,144 @@ +/* $OpenBSD: i8259.h,v 1.7 2015/09/02 13:39:23 mikeb Exp $ */ +/* $NetBSD: i8259.h,v 1.3 2003/05/04 22:01:56 fvdl Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)icu.h 5.6 (Berkeley) 5/9/91 + */ + +#ifndef _MACHINE_I8259_H_ +#define _MACHINE_I8259_H_ + +#include + +#ifndef _LOCORE + +/* + * Interrupt "level" mechanism variables, masks, and macros + */ +extern unsigned imen; /* interrupt mask enable */ + +#define SET_ICUS() (outb(IO_ICU1 + 1, imen), outb(IO_ICU2 + 1, imen >> 8)) + +#endif /* !_LOCORE */ + +/* + * Interrupt enable bits -- in order of priority + */ +#define IRQ_SLAVE 2 + +/* + * Interrupt Control offset into Interrupt descriptor table (IDT) + */ +#define ICU_OFFSET 32 /* 0-31 are processor exceptions */ +#define ICU_LEN 16 /* 32-47 are ISA interrupts */ + + +#define ICU_HARDWARE_MASK + +/* + * These macros are fairly self explanatory. If ICU_SPECIAL_MASK_MODE is + * defined, we try to take advantage of the ICU's `special mask mode' by only + * EOIing the interrupts on return. This avoids the requirement of masking and + * unmasking. We can't do this without special mask mode, because the ICU + * would also hold interrupts that it thinks are of lower priority. + * + * Many machines do not support special mask mode, so by default we don't try + * to use it. + */ + +#define IRQ_BIT(num) (1 << ((num) % 8)) +#define IRQ_BYTE(num) ((num) >> 3) + +#define i8259_late_ack(num) + +#ifdef ICU_SPECIAL_MASK_MODE + +#define i8259_asm_ack1(num) +#define i8259_asm_ack2(num) \ + movb $(0x60|IRQ_SLAVE),%al /* specific EOI for IRQ2 */ ;\ + outb %al,$IO_ICU1 +#define i8259_asm_mask(num) +#define i8259_asm_unmask(num) \ + movb $(0x60|(num%8)),%al /* specific EOI */ ;\ + outb %al,$ICUADDR + +#else /* ICU_SPECIAL_MASK_MODE */ + +#ifndef AUTO_EOI_1 +#define i8259_asm_ack1(num) \ + movb $(0x60|(num%8)),%al /* specific EOI */ ;\ + outb %al,$IO_ICU1 +#else +#define i8259_asm_ack1(num) +#endif + +#ifndef AUTO_EOI_2 +#define i8259_asm_ack2(num) \ + movb $(0x60|(num%8)),%al /* specific EOI */ ;\ + outb %al,$IO_ICU2 /* do the second ICU first */ ;\ + movb $(0x60|IRQ_SLAVE),%al /* specific EOI for IRQ2 */ ;\ + outb %al,$IO_ICU1 +#else +#define i8259_asm_ack2(num) +#endif + +#ifdef ICU_HARDWARE_MASK + +#define i8259_asm_mask(num) \ + movb CVAROFF(imen, IRQ_BYTE(num)),%al ;\ + orb $IRQ_BIT(num),%al ;\ + movb %al,CVAROFF(imen, IRQ_BYTE(num)) ;\ + pushl %eax ;\ + inb $0x84,%al ;\ + popl %eax ;\ + outb %al,$(ICUADDR+1) +#define i8259_asm_unmask(num) \ + cli ;\ + movb CVAROFF(imen, IRQ_BYTE(num)),%al ;\ + andb $~IRQ_BIT(num),%al ;\ + movb %al,CVAROFF(imen, IRQ_BYTE(num)) ;\ + pushl %eax ;\ + inb $0x84,%al ;\ + popl %eax ;\ + outb %al,$(ICUADDR+1) ;\ + sti + +#else /* ICU_HARDWARE_MASK */ + +#define i8259_asm_mask(num) +#define i8259_asm_unmask(num) + +#endif /* ICU_HARDWARE_MASK */ +#endif /* ICU_SPECIAL_MASK_MODE */ + +#endif /* !_MACHINE_I8259_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/ieee.h b/lib/libc/include/x86-openbsd-none/machine/ieee.h new file mode 100644 index 000000000000..cc799d2c2734 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/ieee.h @@ -0,0 +1,141 @@ +/* $OpenBSD: ieee.h,v 1.3 2008/09/07 20:36:06 martynas Exp $ */ +/* $NetBSD: ieee.h,v 1.1 1996/09/30 16:34:25 ws Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ieee.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * ieee.h defines the machine-dependent layout of the machine's IEEE + * floating point. It does *not* define (yet?) any of the rounding + * mode bits, exceptions, and so forth. + */ + +/* + * Define the number of bits in each fraction and exponent. + * + * k k+1 + * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented + * + * (-exp_bias+1) + * as fractions that look like 0.fffff x 2 . This means that + * + * -126 + * the number 0.10000 x 2 , for instance, is the same as the normalized + * + * -127 -128 + * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero + * + * -129 + * in the fraction; to represent 2 , we need two, and so on. This + * + * (-exp_bias-fracbits+1) + * implies that the smallest denormalized number is 2 + * + * for whichever format we are talking about: for single precision, for + * + * -126 -149 + * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and + * + * -149 == -127 - 23 + 1. + */ +#define SNG_EXPBITS 8 +#define SNG_FRACBITS 23 + +#define DBL_EXPBITS 11 +#define DBL_FRACHBITS 20 +#define DBL_FRACLBITS 32 +#define DBL_FRACBITS 52 + +#define EXT_EXPBITS 15 +#define EXT_FRACHBITS 32 +#define EXT_FRACLBITS 32 +#define EXT_FRACBITS 64 + +#define EXT_TO_ARRAY32(p, a) do { \ + (a)[0] = (uint32_t)(p)->ext_fracl; \ + (a)[1] = (uint32_t)(p)->ext_frach; \ +} while(0) + +struct ieee_single { + u_int sng_frac:23; + u_int sng_exp:8; + u_int sng_sign:1; +}; + +struct ieee_double { + u_int dbl_fracl; + u_int dbl_frach:20; + u_int dbl_exp:11; + u_int dbl_sign:1; +}; + +struct ieee_ext { + u_int ext_fracl; + u_int ext_frach; + u_int ext_exp:15; + u_int ext_sign:1; + u_int ext_pad:16; +}; + +/* + * Floats whose exponent is in [1..INFNAN) (of whatever type) are + * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. + * Floats whose exponent is zero are either zero (iff all fraction + * bits are zero) or subnormal values. + * + * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its + * high fraction; if the bit is set, it is a `quiet NaN'. + */ +#define SNG_EXP_INFNAN 255 +#define DBL_EXP_INFNAN 2047 +#define EXT_EXP_INFNAN 32767 + +#if 0 +#define SNG_QUIETNAN (1 << 22) +#define DBL_QUIETNAN (1 << 19) +#define EXT_QUIETNAN (1 << 15) +#endif + +/* + * Exponent biases. + */ +#define SNG_EXP_BIAS 127 +#define DBL_EXP_BIAS 1023 +#define EXT_EXP_BIAS 16383 \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/ieeefp.h b/lib/libc/include/x86-openbsd-none/machine/ieeefp.h new file mode 100644 index 000000000000..9a9a90bad753 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/ieeefp.h @@ -0,0 +1,26 @@ +/* $OpenBSD: ieeefp.h,v 1.3 2011/03/23 16:54:35 pirofti Exp $ */ + +/* + * Written by J.T. Conklin, Apr 6, 1995 + * Public domain. + */ + +#ifndef _MACHINE_IEEEFP_H_ +#define _MACHINE_IEEEFP_H_ + +typedef int fp_except; +#define FP_X_INV 0x01 /* invalid operation exception */ +#define FP_X_DNML 0x02 /* denormalization exception */ +#define FP_X_DZ 0x04 /* divide-by-zero exception */ +#define FP_X_OFL 0x08 /* overflow exception */ +#define FP_X_UFL 0x10 /* underflow exception */ +#define FP_X_IMP 0x20 /* imprecise (loss of precision) */ + +typedef enum { + FP_RN=0, /* round to nearest representable number */ + FP_RM=1, /* round toward negative infinity */ + FP_RP=2, /* round toward positive infinity */ + FP_RZ=3 /* round to zero (truncate) */ +} fp_rnd; + +#endif /* _MACHINE_IEEEFP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/intr.h b/lib/libc/include/x86-openbsd-none/machine/intr.h new file mode 100644 index 000000000000..299370353b2f --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/intr.h @@ -0,0 +1,149 @@ +/* $OpenBSD: intr.h,v 1.51 2025/04/25 12:47:37 mvs Exp $ */ +/* $NetBSD: intr.h,v 1.5 1996/05/13 06:11:28 mycroft Exp $ */ + +/* + * Copyright (c) 1996 Charles M. Hannum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Charles M. Hannum. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_INTR_H_ +#define _MACHINE_INTR_H_ + +#define __USE_MI_SOFTINTR + +#include +#include + +#ifndef _LOCORE +#include +#include + +extern volatile u_int32_t lapic_tpr; /* Current interrupt priority level. */ + +extern int imask[]; /* Bitmasks telling what interrupts are blocked. */ +extern int iunmask[]; /* Bitmasks telling what interrupts are accepted. */ + +#define IMASK(level) imask[IPL(level)] +#define IUNMASK(level) iunmask[IPL(level)] + +extern void Xspllower(void); + +extern int splraise(int); +extern int spllower(int); +extern void splx(int); +extern void softintr(int); + +/* + * compiler barrier: prevent reordering of instructions. + * This prevents the compiler from reordering code around + * this "instruction", acting as a sequence point for code generation. + */ + +#define __splbarrier() __asm volatile("":::"memory") + +/* SPL asserts */ +#ifdef DIAGNOSTIC +/* + * Although this function is implemented in MI code, it must be in this MD + * header because we don't want this header to include MI includes. + */ +void splassert_fail(int, int, const char *); +extern int splassert_ctl; +void splassert_check(int, const char *); +#define splassert(__wantipl) do { \ + if (splassert_ctl > 0) { \ + splassert_check(__wantipl, __func__); \ + } \ +} while (0) +#define splsoftassert(wantipl) splassert(wantipl) +#else +#define splassert(wantipl) do { /* nada */ } while (0) +#define splsoftassert(wantipl) do { /* nada */ } while (0) +#endif + +/* + * Define the splraise and splx code in macros, so that the code can be + * reused in a profiling build in a way that does not cause recursion. + */ +#define _SPLRAISE(ocpl, ncpl) \ + ocpl = lapic_tpr; \ + if (ncpl > ocpl) \ + lapic_tpr = ncpl + + +#define _SPLX(ncpl) \ + lapic_tpr = ncpl; \ + if (curcpu()->ci_ipending & IUNMASK(ncpl)) \ + Xspllower() + +/* + * Hardware interrupt masks + */ +#define splbio() splraise(IPL_BIO) +#define splnet() splraise(IPL_NET) +#define spltty() splraise(IPL_TTY) +#define splaudio() splraise(IPL_AUDIO) +#define splclock() splraise(IPL_CLOCK) +#define splstatclock() splclock() +#define splipi() splraise(IPL_IPI) + +/* + * Software interrupt masks + */ +#define splsoftclock() splraise(IPL_SOFTCLOCK) +#define splsoftnet() splraise(IPL_SOFTNET) +#define splsofttty() splraise(IPL_SOFTTTY) + +/* + * Miscellaneous + */ +#define splvm() splraise(IPL_VM) +#define splhigh() splraise(IPL_HIGH) +#define splsched() splraise(IPL_SCHED) +#define spl0() spllower(IPL_NONE) + +#include + +struct cpu_info; + +void intr_barrier(void *); +void intr_enable_wakeup(void); +void intr_disable_wakeup(void); + +#ifdef MULTIPROCESSOR +void i386_send_ipi(struct cpu_info *, int); +int i386_fast_ipi(struct cpu_info *, int); +void i386_broadcast_ipi(int); +void i386_ipi_handler(void); +void i386_setperf_ipi(struct cpu_info *); + +extern void (*ipifunc[I386_NIPI])(struct cpu_info *); +#endif + +#endif /* !_LOCORE */ + +#endif /* !_MACHINE_INTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/intrdefs.h b/lib/libc/include/x86-openbsd-none/machine/intrdefs.h new file mode 100644 index 000000000000..dedc83ff0368 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/intrdefs.h @@ -0,0 +1,126 @@ +/* $OpenBSD: intrdefs.h,v 1.20 2025/06/11 09:57:01 kettenis Exp $ */ +/* $NetBSD: intrdefs.h,v 1.2 2003/05/04 22:01:56 fvdl Exp $ */ + +#ifndef _I386_INTRDEFS_H +#define _I386_INTRDEFS_H + +/* + * Intel APICs (advanced programmable interrupt controllers) have + * bytesized priority registers where the upper nibble is the actual + * interrupt priority level (a.k.a. IPL). Interrupt vectors are + * closely tied to these levels as interrupts whose vectors' upper + * nibble is lower than or equal to the current level are blocked. + * Not all 256 possible vectors are available for interrupts in + * APIC systems, only + * + * For systems where instead the older ICU (interrupt controlling + * unit, a.k.a. PIC or 82C59) is used, the IPL is not directly useful, + * since the interrupt blocking is handled via interrupt masks instead + * of levels. However the IPL is easily used as an offset into arrays + * of masks. + */ +#define IPLSHIFT 4 /* The upper nibble of vectors is the IPL. */ +#define NIPL 16 /* Four bits of information gives as much. */ +#define IPL(level) ((level) >> IPLSHIFT) /* Extract the IPL. */ +/* XXX Maybe this IDTVECOFF definition should be elsewhere? */ +#define IDTVECOFF 0x20 /* The lower 32 IDT vectors are reserved. */ + +/* + * This macro is only defined for 0 <= x < 14, i.e. there are fourteen + * distinct priority levels available for interrupts. + */ +#define MAKEIPL(priority) (IDTVECOFF + ((priority) << IPLSHIFT)) + +/* + * Interrupt priority levels. + * + * XXX We are somewhat sloppy about what we mean by IPLs, sometimes + * XXX we refer to the eight-bit value suitable for storing into APICs' + * XXX priority registers, other times about the four-bit entity found + * XXX in the former values' upper nibble, which can be used as offsets + * XXX in various arrays of our implementation. We are hoping that + * XXX the context will provide enough information to not make this + * XXX sloppy naming a real problem. + * + * There are tty, network and disk drivers that use free() at interrupt + * time, so imp > (tty | net | bio). + * + * Since run queues may be manipulated by both the statclock and tty, + * network, and disk drivers, clock > imp. + * + * IPL_HIGH must block everything that can manipulate a run queue. + * + * XXX Ultimately we may need serial drivers to run at the absolute highest + * XXX priority to avoid overruns, then we must make serial > high. + * + * The level numbers are picked to fit into APIC vector priorities. + */ +#define IPL_NONE 0 /* nothing */ +#define IPL_SOFTCLOCK MAKEIPL(1) /* timeouts */ +#define IPL_SOFTNET MAKEIPL(2) /* protocol stacks */ +#define IPL_BIO MAKEIPL(3) /* block I/O */ +#define IPL_NET MAKEIPL(4) /* network */ +#define IPL_SOFTTTY MAKEIPL(5) /* delayed terminal handling */ +#define IPL_TTY MAKEIPL(6) /* terminal */ +#define IPL_VM MAKEIPL(7) /* memory allocation */ +#define IPL_AUDIO MAKEIPL(8) /* audio */ +#define IPL_CLOCK MAKEIPL(9) /* clock */ +#define IPL_STATCLOCK IPL_CLOCK /* statclock */ +#define IPL_SCHED IPL_CLOCK +#define IPL_HIGH MAKEIPL(10) /* everything */ +#define IPL_IPI MAKEIPL(11) /* interprocessor interrupt */ + +#define IPL_MPFLOOR IPL_TTY +#define IPL_MPSAFE 0x100 +#define IPL_WAKEUP 0 + +/* Interrupt sharing types. */ +#define IST_NONE 0 /* none */ +#define IST_PULSE 1 /* pulsed */ +#define IST_EDGE 2 /* edge-triggered */ +#define IST_LEVEL 3 /* level-triggered */ + +/* + * Local APIC masks. Must not conflict with SIR_* below, and must + * be >= NUM_LEGACY_IRQs. Note that LIR_IPI must be first. + */ +#define LIR_IPI 31 +#define LIR_TIMER 30 + +/* Soft interrupt masks. */ +#define SIR_CLOCK 29 +#define SIR_NET 28 +#define SIR_TTY 27 + + +/* + * Maximum # of interrupt sources per CPU. 32 to fit in one word. + * ioapics can theoretically produce more, but it's not likely to + * happen. For multiple ioapics, things can be routed to different + * CPUs. + */ +#define MAX_INTR_SOURCES 32 +#define NUM_LEGACY_IRQS 16 + +/* + * Low and high boundaries between which interrupt gates will + * be allocated in the IDT. + */ +#define IDT_INTR_LOW (0x20 + NUM_LEGACY_IRQS) +#define IDT_INTR_HIGH 0xef + +#define I386_IPI_HALT 0x00000001 +#define I386_IPI_NOP 0x00000002 +#define I386_IPI_FLUSH_FPU 0x00000004 +#define I386_IPI_SYNCH_FPU 0x00000008 +#define I386_IPI_MTRR 0x00000010 +#define I386_IPI_GDT 0x00000020 +#define I386_IPI_DDB 0x00000040 /* synchronize while in ddb */ +#define I386_IPI_SETPERF 0x00000080 +#define I386_IPI_WBINVD 0x00000100 + +#define I386_NIPI 9 + +#define IREENT_MAGIC 0x18041969 + +#endif /* _I386_INTRDEFS_H */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/ioctl_fd.h b/lib/libc/include/x86-openbsd-none/machine/ioctl_fd.h new file mode 100644 index 000000000000..a370bf56f6b4 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/ioctl_fd.h @@ -0,0 +1,131 @@ +/* $OpenBSD: ioctl_fd.h,v 1.4 2011/03/23 16:54:35 pirofti Exp $ */ +/* from: ioctl_fd.h,v 1.4 1995/06/29 03:49:32 jtk Exp */ + +/* + * Copyright (C) 1992-1994 by Joerg Wunsch, Dresden + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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(S) BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * From: Id: ioctl_fd.h,v 1.7 1994/10/30 19:17:39 joerg Exp + */ + +#ifndef _MACHINE_IOCTL_FD_H_ +#define _MACHINE_IOCTL_FD_H_ + +#include + +#define FD_FORMAT_VERSION 110 /* used to validate before formatting */ +#define FD_MAX_NSEC 36 /* highest known number of spt - allow for */ + /* 2.88 MB drives */ + +struct fd_formb { + int format_version; /* == FD_FORMAT_VERSION */ + int cyl, head; + int transfer_rate; /* fdreg.h: FDC_???KBPS */ + + union { + struct fd_form_data { + /* + * DO NOT CHANGE THE LAYOUT OF THIS STRUCTS + * it is hardware-dependant since it exactly + * matches the byte sequence to write to FDC + * during its `format track' operation + */ + u_char secshift; /* 0 -> 128, ...; usually 2 -> 512 */ + u_char nsecs; /* must be <= FD_MAX_NSEC */ + u_char gaplen; /* GAP 3 length; usually 84 */ + u_char fillbyte; /* usually 0xf6 */ + struct fd_idfield_data { + /* + * data to write into id fields; + * for obscure formats, they mustn't match + * the real values (but mostly do) + */ + u_char cylno; /* 0 thru 79 (or 39) */ + u_char headno; /* 0, or 1 */ + u_char secno; /* starting at 1! */ + u_char secsize; /* usually 2 */ + } idfields[FD_MAX_NSEC]; /* 0 <= idx < nsecs used */ + } structured; + u_char raw[1]; /* to have continuous indexed access */ + } format_info; +}; + +/* make life easier */ +# define fd_formb_secshift format_info.structured.secshift +# define fd_formb_nsecs format_info.structured.nsecs +# define fd_formb_gaplen format_info.structured.gaplen +# define fd_formb_fillbyte format_info.structured.fillbyte +/* these data must be filled in for(i = 0; i < fd_formb_nsecs; i++) */ +# define fd_formb_cylno(i) format_info.structured.idfields[i].cylno +# define fd_formb_headno(i) format_info.structured.idfields[i].headno +# define fd_formb_secno(i) format_info.structured.idfields[i].secno +# define fd_formb_secsize(i) format_info.structured.idfields[i].secsize + +/* + * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how + * we tell them apart. + */ +struct fd_type { + int sectrac; /* sectors per track */ + int heads; /* number of heads */ + int seccyl; /* sectors per cylinder */ + int secsize; /* size code for sectors */ + int datalen; /* data len when secsize = 0 */ + int steprate; /* step rate and head unload time */ + int gap1; /* gap len between sectors */ + int gap2; /* formatting gap */ + int tracks; /* total num of tracks */ + int size; /* size of disk in sectors */ + int step; /* steps per cylinder */ + int rate; /* transfer speed code */ + char *name; +}; + + +#define FD_FORM _IOW('F', 61, struct fd_formb) /* format a track */ +#define FD_GTYPE _IOR('F', 62, struct fd_type) /* get drive type */ +#define FD_STYPE _IOW('F', 63, struct fd_type) /* set drive type */ + +#define FD_GOPTS _IOR('F', 64, int) /* drive options, see below */ +#define FD_SOPTS _IOW('F', 65, int) + +#define FDOPT_NORETRY 0x0001 /* no retries on failure (cleared on close) */ + +/* + * The following definitions duplicate those in sys/i386/isa/fdreg.h + * They are here since their values are to be used in the above + * structure when formatting a floppy. For very obvious reasons, both + * definitions must match ;-) + */ +#ifndef FDC_500KBPS +#define FDC_500KBPS 0x00 /* 500KBPS MFM drive transfer rate */ +#define FDC_300KBPS 0x01 /* 300KBPS MFM drive transfer rate */ +#define FDC_250KBPS 0x02 /* 250KBPS MFM drive transfer rate */ +#define FDC_125KBPS 0x03 /* 125KBPS FM drive transfer rate */ + /* for some controllers 1MPBS instead */ +#endif /* FDC_500KBPS */ + + +#endif /* !_MACHINE_IOCTL_FD_H__ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/joystick.h b/lib/libc/include/x86-openbsd-none/machine/joystick.h new file mode 100644 index 000000000000..2d55604d07ba --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/joystick.h @@ -0,0 +1,23 @@ +/* $OpenBSD: joystick.h,v 1.6 2011/03/23 16:54:35 pirofti Exp $ */ +/* $NetBSD: joystick.h,v 1.1 1996/03/27 19:18:56 perry Exp $ */ + +#ifndef _MACHINE_JOYSTICK_H_ +#define _MACHINE_JOYSTICK_H_ + +#include + +struct joystick { + int x; + int y; + int b1; + int b2; +}; + +#define JOY_SETTIMEOUT _IOW('J', 1, int) /* set timeout */ +#define JOY_GETTIMEOUT _IOR('J', 2, int) /* get timeout */ +#define JOY_SET_X_OFFSET _IOW('J', 3, int) /* set offset on X-axis */ +#define JOY_SET_Y_OFFSET _IOW('J', 4, int) /* set offset on Y-axis */ +#define JOY_GET_X_OFFSET _IOR('J', 5, int) /* get offset on X-axis */ +#define JOY_GET_Y_OFFSET _IOR('J', 6, int) /* get offset on Y-axis */ + +#endif /* _MACHINE_JOYSTICK_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/kcore.h b/lib/libc/include/x86-openbsd-none/machine/kcore.h new file mode 100644 index 000000000000..24e23270519b --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/kcore.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2011 Mike Larkin + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_KCORE_H_ +#define _MACHINE_KCORE_H_ + +struct dumpmem { + paddr_t start; + paddr_t end; +}; + +#endif /* _MACHINE_KCORE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/limits.h b/lib/libc/include/x86-openbsd-none/machine/limits.h new file mode 100644 index 000000000000..86b69dfadb56 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/limits.h @@ -0,0 +1,53 @@ +/* $OpenBSD: limits.h,v 1.14 2015/04/30 13:42:08 millert Exp $ */ +/* $NetBSD: limits.h,v 1.11 1995/12/21 01:08:59 mycroft Exp $ */ + +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)limits.h 7.2 (Berkeley) 6/28/90 + */ + +#ifndef _MACHINE_LIMITS_H_ +#define _MACHINE_LIMITS_H_ + +#include + +#if __POSIX_VISIBLE || __XPG_VISIBLE +#define SSIZE_MAX LONG_MAX /* max value for a ssize_t */ +#endif + +#if __BSD_VISIBLE +#define SIZE_T_MAX ULONG_MAX /* max value for a size_t (historic) */ + +#define UQUAD_MAX 0xffffffffffffffffULL /* max unsigned quad */ +#define QUAD_MAX 0x7fffffffffffffffLL /* max signed quad */ +#define QUAD_MIN (-0x7fffffffffffffffLL-1) /* min signed quad */ + +#endif /* __BSD_VISIBLE */ + +#endif /* _MACHINE_LIMITS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/loadfile_machdep.h b/lib/libc/include/x86-openbsd-none/machine/loadfile_machdep.h new file mode 100644 index 000000000000..6a9232df7079 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/loadfile_machdep.h @@ -0,0 +1,55 @@ +/* $OpenBSD: loadfile_machdep.h,v 1.8 2019/04/10 04:17:35 deraadt Exp $ */ +/* $NetBSD: loadfile_machdep.h,v 1.1 1999/04/29 03:17:12 tsubai Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define BOOT_ELF +#define BOOT_ELF32 +#define BOOT_ELF64 + +/* Keep a default ELFSIZE */ +#define ELFSIZE 32 + +#define LOAD_KERNEL LOAD_ALL +#define COUNT_KERNEL COUNT_ALL + +#define LOADADDR(a) ((((u_long)(a)) + offset)&0xfffffff) +#define ALIGNENTRY(a) ((u_long)(a)) +#define READ(f, b, c) read((f), (void *)LOADADDR(b), (size_t)(c)) +#define BCOPY(s, d, c) memcpy((void *)LOADADDR(d), (void *)(s), (c)) +#define BZERO(d, c) memset((void *)LOADADDR(d), 0, (c)) +#define WARN(a) (void)(printf a, \ + printf((errno ? ": %s\n" : "\n"), \ + strerror(errno))) +#define PROGRESS(a) (void) printf a +#define ALLOC(a) alloc(a) +#define FREE(a, b) free(a, b) + +void run_loadfile(uint64_t *, int); \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/mpbiosreg.h b/lib/libc/include/x86-openbsd-none/machine/mpbiosreg.h new file mode 100644 index 000000000000..37b3615c41e4 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/mpbiosreg.h @@ -0,0 +1,155 @@ +/* $OpenBSD: mpbiosreg.h,v 1.6 2023/04/10 04:21:20 jsg Exp $ */ +/* $NetBSD: mpbiosreg.h,v 1.1.2.3 2000/02/29 13:17:51 sommerfeld Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_MPBIOSREG_H_ +#define _MACHINE_MPBIOSREG_H_ + +#define BIOS_BASE (0xf0000) +#define BIOS_SIZE (0x10000) +#define BIOS_COUNT (BIOS_SIZE) + +/* + * Multiprocessor config table entry types. + */ + +#define MPS_MCT_CPU 0 +#define MPS_MCT_BUS 1 +#define MPS_MCT_IOAPIC 2 +#define MPS_MCT_IOINT 3 +#define MPS_MCT_LINT 4 + +#define MPS_MCT_NTYPES 5 + +/* + * Interrupt types + */ + +#define MPS_INTTYPE_INT 0 +#define MPS_INTTYPE_NMI 1 +#define MPS_INTTYPE_SMI 2 +#define MPS_INTTYPE_ExtINT 3 + +#define MPS_INTPO_DEF 0 +#define MPS_INTPO_ACTHI 1 +#define MPS_INTPO_ACTLO 3 +#define MPS_INTPO_SHIFT 0 +#define MPS_INTPO_MASK 3 + +#define MPS_INTTR_DEF 0 +#define MPS_INTTR_EDGE 1 +#define MPS_INTTR_LEVEL 3 +#define MPS_INTTR_SHIFT 2 +#define MPS_INTTR_MASK 3 + +#define MPS_INT(p,t) \ + ((((p) & MPS_INTPO_MASK) << MPS_INTPO_SHIFT) | \ + (((t) & MPS_INTTR_MASK) << MPS_INTTR_SHIFT)) + +/* MP Floating Pointer Structure */ +struct mpbios_fps { + u_int32_t signature; +/* string defined by the Intel MP Spec as identifying the MP table */ +#define MP_FP_SIG 0x5f504d5f /* _MP_ */ + + u_int32_t pap; + u_int8_t length; + u_int8_t spec_rev; + u_int8_t checksum; + u_int8_t mpfb1; /* system configuration */ + u_int8_t mpfb2; /* flags */ +#define MPFPS_FLAG_IMCR 0x80 /* IMCR present */ + u_int8_t mpfb3; /* unused */ + u_int8_t mpfb4; /* unused */ + u_int8_t mpfb5; /* unused */ +}; + +/* MP Configuration Table Header */ +struct mpbios_cth { + u_int32_t signature; +#define MP_CT_SIG 0x504d4350 /* PCMP */ + + u_int16_t base_len; + u_int8_t spec_rev; + u_int8_t checksum; + u_int8_t oem_id[8]; + u_int8_t product_id[12]; + u_int32_t oem_table_pointer; + u_int16_t oem_table_size; + u_int16_t entry_count; + u_int32_t apic_address; + u_int16_t ext_len; + u_int8_t ext_cksum; + u_int8_t reserved; +}; + +struct mpbios_proc { + u_int8_t type; + u_int8_t apic_id; + u_int8_t apic_version; + u_int8_t cpu_flags; +#define PROCENTRY_FLAG_EN 0x01 +#define PROCENTRY_FLAG_BP 0x02 + u_long cpu_signature; + u_long feature_flags; + u_long reserved1; + u_long reserved2; +}; + +struct mpbios_bus { + u_int8_t type; + u_int8_t bus_id; + char bus_type[6]; +}; + +struct mpbios_ioapic { + u_int8_t type; + u_int8_t apic_id; + u_int8_t apic_version; + u_int8_t apic_flags; +#define IOAPICENTRY_FLAG_EN 0x01 + void *apic_address; +}; + +struct mpbios_int { + u_int8_t type; + u_int8_t int_type; + u_int16_t int_flags; + u_int8_t src_bus_id; + u_int8_t src_bus_irq; + u_int8_t dst_apic_id; +#define MPS_ALL_APICS 0xff + u_int8_t dst_apic_int; +}; + +#endif /* !_MACHINE_MPBIOSREG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/mpbiosvar.h b/lib/libc/include/x86-openbsd-none/machine/mpbiosvar.h new file mode 100644 index 000000000000..6c0bc7a5253a --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/mpbiosvar.h @@ -0,0 +1,86 @@ +/* $OpenBSD: mpbiosvar.h,v 1.13 2024/10/22 21:50:02 jsg Exp $ */ +/* $NetBSD: mpbiosvar.h,v 1.1.2.3 2000/02/29 13:17:20 sommerfeld Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef _MACHINE_MPBIOSVAR_H_ +#define _MACHINE_MPBIOSVAR_H_ + +#define MP_TRAMPOLINE (16 * PAGE_SIZE) +#define MP_TRAMP_DATA (17 * PAGE_SIZE) + +#if !defined(_LOCORE) + +#include + +struct mp_bus { + char *mb_name; /* XXX bus name */ + int mb_idx; /* XXX bus index */ + void (*mb_intr_print) (int); + void (*mb_intr_cfg)(const struct mpbios_int *, u_int32_t *); + struct mp_intr_map *mb_intrs; + u_int32_t mb_data; /* random bus-specific datum. */ +}; + +struct mp_intr_map { + struct mp_intr_map *next; + struct mp_bus *bus; + int bus_pin; + struct ioapic_softc *ioapic; + int ioapic_pin; + int ioapic_ih; /* int handle, for apic_intr_est */ + int type; /* from mp spec intr record */ + int flags; /* from mp spec intr record */ + u_int32_t redir; + int cpu_id; +}; + +#if defined(_KERNEL) +extern int mp_verbose; +extern struct mp_bus *mp_busses; +extern int mp_nbusses; +extern struct mp_intr_map *mp_intrs; +extern int mp_nintrs; +extern struct mp_bus *mp_isa_bus; +extern struct mp_bus *mp_eisa_bus; + +void mpbios_scan(struct device *); +int mpbios_probe(struct device *); +int mpbios_invent(int, int, int); + +void mpbios_intr_fixup(void); +#endif + +#endif + +#endif /* !_MACHINE_MPBIOSVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/mutex.h b/lib/libc/include/x86-openbsd-none/machine/mutex.h new file mode 100644 index 000000000000..3aa5554e532e --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/mutex.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mutex.h,v 1.13 2018/01/25 15:06:29 mpi Exp $ */ + +#define __USE_MI_MUTEX \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/npx.h b/lib/libc/include/x86-openbsd-none/machine/npx.h new file mode 100644 index 000000000000..004a44af61c7 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/npx.h @@ -0,0 +1,158 @@ +/* $OpenBSD: npx.h,v 1.20 2021/03/11 11:16:57 jsg Exp $ */ +/* $NetBSD: npx.h,v 1.11 1994/10/27 04:16:11 cgd Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)npx.h 5.3 (Berkeley) 1/18/91 + */ + +/* + * 287/387 NPX Coprocessor Data Structures and Constants + * W. Jolitz 1/90 + */ + +#ifndef _MACHINE_NPX_H_ +#define _MACHINE_NPX_H_ + +/* Environment information of floating point unit */ +struct env87 { + long en_cw; /* control word (16bits) */ + long en_sw; /* status word (16bits) */ + long en_tw; /* tag word (16bits) */ + long en_fip; /* floating point instruction pointer */ + u_short en_fcs; /* floating code segment selector */ + u_short en_opcode; /* opcode last executed (11 bits ) */ + long en_foo; /* floating operand offset */ + long en_fos; /* floating operand segment selector */ +}; + +#define EN_SW_IE 0x0001 /* invalid operation */ +#define EN_SW_DE 0x0002 /* denormal */ +#define EN_SW_ZE 0x0004 /* divide by zero */ +#define EN_SW_OE 0x0008 /* overflow */ +#define EN_SW_UE 0x0010 /* underflow */ +#define EN_SW_PE 0x0020 /* loss of precision */ + +/* Contents of each floating point accumulator */ +struct fpacc87 { +#ifdef dontdef /* too unportable */ + u_long fp_mantlo; /* mantissa low (31:0) */ + u_long fp_manthi; /* mantissa high (63:32) */ + int fp_exp:15; /* exponent */ + int fp_sgn:1; /* mantissa sign */ +#else + u_char fp_bytes[10]; +#endif +}; + +/* Floating point and emulator context */ +struct save87 { + struct env87 sv_env; /* floating point control/status */ + struct fpacc87 sv_ac[8]; /* accumulator contents, 0-7 */ + u_long sv_ex_sw; /* status word for last exception */ + u_long sv_ex_tw; /* tag word for last exception */ +}; + +/* Environment of FPU/MMX/SSE/SSE2. */ +struct envxmm { +/*0*/ uint16_t en_cw; /* FPU Control Word */ + uint16_t en_sw; /* FPU Status Word */ + uint8_t en_tw; /* FPU Tag Word (abridged) */ + uint8_t en_rsvd0; + uint16_t en_opcode; /* FPU Opcode */ + uint32_t en_fip; /* FPU Instruction Pointer */ + uint16_t en_fcs; /* FPU IP selector */ + uint16_t en_rsvd1; +/*16*/ uint32_t en_foo; /* FPU Data pointer */ + uint16_t en_fos; /* FPU Data pointer selector */ + uint16_t en_rsvd2; + uint32_t en_mxcsr; /* MXCSR Register State */ + uint32_t en_mxcsr_mask; /* Mask for valid MXCSR bits (may be 0) */ +}; + +/* FPU registers in the extended save format. */ +struct fpaccxmm { + uint8_t fp_bytes[10]; + uint8_t fp_rsvd[6]; +}; + +/* SSE/SSE2 registers. */ +struct xmmreg { + uint8_t sse_bytes[16]; +}; + +/* FPU/MMX/SSE/SSE2 context */ +struct savexmm { + struct envxmm sv_env; /* control/status context */ + struct fpaccxmm sv_ac[8]; /* ST/MM regs */ + struct xmmreg sv_xmmregs[8]; /* XMM regs */ + uint8_t sv_rsvd[16 * 14]; + /* 512-bytes --- end of hardware portion of save area */ + uint32_t sv_ex_sw; /* saved SW from last exception */ + uint32_t sv_ex_tw; /* saved TW from last exception */ +}; + +union savefpu { + struct save87 sv_87; + struct savexmm sv_xmm; +}; + +#define __INITIAL_NPXCW__ 0x037f + +/* + * The default MXCSR value at reset is 0x1f80, IA-32 Instruction + * Set Reference, pg. 3-369. + */ +#define __INITIAL_MXCSR__ 0x1f80 +#define __INITIAL_MXCSR_MASK__ 0xffbf + +/* + * The standard control word from finit is 0x37F, giving: + * round to nearest + * 64-bit precision + * all exceptions masked. + */ + +void process_xmm_to_s87(const struct savexmm *, struct save87 *); +void process_s87_to_xmm(const struct save87 *, struct savexmm *); + +struct cpu_info; +struct trapframe; + +extern uint32_t fpu_mxcsr_mask; + +void npxinit(struct cpu_info *); +void npxtrap(struct trapframe *); +void fpu_kernel_enter(void); +void fpu_kernel_exit(void); + +#endif /* !_MACHINE_NPX_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/param.h b/lib/libc/include/x86-openbsd-none/machine/param.h new file mode 100644 index 000000000000..8fa438464652 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/param.h @@ -0,0 +1,80 @@ +/* $OpenBSD: param.h,v 1.53 2023/12/14 13:26:49 claudio Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ + +#ifdef _KERNEL +#ifdef _LOCORE +#include +#else +#include +#endif +#endif + +#define _MACHINE i386 +#define MACHINE "i386" +#define _MACHINE_ARCH i386 +#define MACHINE_ARCH "i386" +#define MID_MACHINE MID_I386 + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define PAGE_MASK (PAGE_SIZE - 1) + +#define KERNBASE 0xd0000000 + +#ifdef _KERNEL + +#define KERNTEXTOFF (KERNBASE+0x200000) /* start of kernel text */ + +#define NBPG PAGE_SIZE /* bytes/page */ +#define PGSHIFT PAGE_SHIFT /* LOG2(PAGE_SIZE) */ +#define PGOFSET PAGE_MASK /* byte offset into page */ + +#define UPAGES 3 /* pages of u-area */ +#define USPACE (UPAGES * PAGE_SIZE) /* total size of u-area */ +#define USPACE_ALIGN 0 /* u-area alignment 0-none */ + +#define NMBCLUSTERS (32 * 1024) /* max cluster allocation */ + +#ifndef MSGBUFSIZE +#define MSGBUFSIZE (8 * PAGE_SIZE) /* default message buffer size */ +#endif + +#define __HAVE_ACPI + +#endif /* _KERNEL */ + +#endif /* _MACHINE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/pcb.h b/lib/libc/include/x86-openbsd-none/machine/pcb.h new file mode 100644 index 000000000000..ae727d2d47f0 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/pcb.h @@ -0,0 +1,78 @@ +/* $OpenBSD: pcb.h,v 1.25 2022/02/21 14:26:19 jsg Exp $ */ +/* $NetBSD: pcb.h,v 1.21 1996/01/08 13:51:42 mycroft Exp $ */ + +/*- + * Copyright (c) 1995 Charles M. Hannum. All rights reserved. + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pcb.h 5.10 (Berkeley) 5/12/91 + */ + +/* + * Intel 386 process control block + */ + +#ifndef _MACHINE_PCB_H_ +#define _MACHINE_PCB_H_ + +#include + +#include +#include +#include + +/* + * Please note that pcb_savefpu must be aligned to 16 bytes. + */ +struct pcb { + union savefpu pcb_savefpu; /* floating point state for FPU */ + int pcb_cr3; + int pcb_esp; + int pcb_ebp; + int pcb_kstack; /* kernel stack address */ + int pcb_cr0; /* saved image of CR0 */ + caddr_t pcb_onfault; /* copyin/out fault recovery */ + struct segment_descriptor pcb_threadsegs[2]; + /* per-thread descriptors */ + int vm86_eflags; /* virtual eflags for vm86 mode */ + int vm86_flagmask; /* flag mask for vm86 mode */ + void *vm86_userp; /* XXX performance hack */ + struct pmap *pcb_pmap; /* back pointer to our pmap */ + struct cpu_info *pcb_fpcpu; /* cpu holding our fpu state */ + int pcb_flags; +#define PCB_SAVECTX 0x00000001 +}; + +/* the indexes of the %fs/%gs segments in pcb_threadsegs */ +#define TSEG_FS 0 +#define TSEG_GS 1 + +#endif /* _MACHINE_PCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/pctr.h b/lib/libc/include/x86-openbsd-none/machine/pctr.h new file mode 100644 index 000000000000..91c0e3f0b0cf --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/pctr.h @@ -0,0 +1,93 @@ +/* $OpenBSD: pctr.h,v 1.17 2014/03/29 18:09:29 guenther Exp $ */ + +/* + * Pentium performance counter driver for OpenBSD. + * Copyright 1996 David Mazieres . + * + * Modification and redistribution in source and binary forms is + * permitted provided that due credit is given to the author and the + * OpenBSD project by leaving this copyright notice intact. + */ + +#ifndef _MACHINE_PCTR_H_ +#define _MACHINE_PCTR_H_ + +#include + +typedef u_int64_t pctrval; + +#define PCTR_NUM 4 + +struct pctrst { + u_int pctr_fn[PCTR_NUM]; /* Current settings of counters */ + pctrval pctr_tsc; /* Free-running 64-bit cycle counter */ + pctrval pctr_hwc[PCTR_NUM]; /* Values of the hardware counters */ +}; + +/* Bit values in fn fields and PIOCS ioctl's */ +#define P5CTR_K 0x40 /* Monitor kernel-level events */ +#define P5CTR_U 0x80 /* Monitor user-level events */ +#define P5CTR_C 0x100 /* count cycles rather than events */ + +#define PCTR_U 0x010000 /* Monitor user-level events */ +#define PCTR_K 0x020000 /* Monitor kernel-level events */ +#define PCTR_E 0x040000 /* Edge detect */ +#define PCTR_EN 0x400000 /* Enable counters (counter 0 only) */ +#define PCTR_I 0x800000 /* Invert counter mask */ + +/* Unit Mask bits */ +#define PCTR_UM_M 0x0800 /* Modified cache lines */ +#define PCTR_UM_E 0x0400 /* Exclusive cache lines */ +#define PCTR_UM_S 0x0200 /* Shared cache lines */ +#define PCTR_UM_I 0x0100 /* Invalid cache lines */ +#define PCTR_UM_MESI (PCTR_UM_M|PCTR_UM_E|PCTR_UM_S|PCTR_UM_I) +#define PCTR_UM_A 0x2000 /* Any initiator */ + +#define PCTR_UM_SHIFT 8 /* Left shift for unit mask */ +#define PCTR_CM_SHIFT 24 /* Left shift for counter mask */ + +/* ioctl to set which counter a device tracks */ +#define PCIOCRD _IOR('c', 1, struct pctrst) /* Read counter value */ +#define PCIOCS0 _IOW('c', 8, unsigned int) /* Set counter 0 function */ +#define PCIOCS1 _IOW('c', 9, unsigned int) /* Set counter 1 function */ +#define PCIOCS2 _IOW('c', 10, unsigned int) /* Set counter 0 function */ +#define PCIOCS3 _IOW('c', 11, unsigned int) /* Set counter 1 function */ + +#define _PATH_PCTR "/dev/pctr" + +#define rdtsc() \ +({ \ + pctrval v; \ + __asm volatile ("rdtsc" : "=A" (v)); \ + v; \ +}) + +/* Read the performance counters (Pentium Pro only) */ +#define rdpmc(ctr) \ +({ \ + pctrval v; \ + __asm volatile ("rdpmc\n" \ + "\tandl $0xff, %%edx" \ + : "=A" (v) : "c" (ctr)); \ + v; \ +}) + +#ifdef _KERNEL + +#define rdmsr(msr) \ +({ \ + pctrval v; \ + __asm volatile ("rdmsr" : "=A" (v) : "c" (msr)); \ + v; \ +}) + +#define wrmsr(msr, v) \ + __asm volatile ("wrmsr" :: "A" ((u_int64_t) (v)), "c" (msr)); + +void pctrattach(int); +int pctropen(dev_t, int, int, struct proc *); +int pctrclose(dev_t, int, int, struct proc *); +int pctrioctl(dev_t, u_long, caddr_t, int, struct proc *); + +#endif /* _KERNEL */ +#endif /* ! _MACHINE_PCTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/pic.h b/lib/libc/include/x86-openbsd-none/machine/pic.h new file mode 100644 index 000000000000..26b88fde7633 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/pic.h @@ -0,0 +1,42 @@ +/* $OpenBSD: pic.h,v 1.2 2014/12/16 21:40:05 tedu Exp $ */ +/* $NetBSD: pic.h,v 1.1 2003/02/26 21:26:11 fvdl Exp $ */ + +#ifndef _X86_PIC_H +#define _X86_PIC_H + +#include +#include + +struct cpu_info; + +/* + * Structure common to all PIC softcs + */ +struct pic { + struct device pic_dev; + int pic_type; +#ifdef MULTIPROCESSOR + struct mutex pic_mutex; +#endif + void (*pic_hwmask)(struct pic *, int); + void (*pic_hwunmask)(struct pic *, int); + void (*pic_addroute)(struct pic *, struct cpu_info *, int, int, int); + void (*pic_delroute)(struct pic *, struct cpu_info *, int, int, int); + struct intrstub *pic_level_stubs; + struct intrstub *pic_edge_stubs; +}; + +#define pic_name pic_dev.dv_xname + +/* + * PIC types. + */ +#define PIC_I8259 0 +#define PIC_IOAPIC 1 +#define PIC_LAPIC 2 +#define PIC_SOFT 3 + +extern struct pic i8259_pic; +extern struct pic local_pic; +extern struct pic softintr_pic; +#endif \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/pio.h b/lib/libc/include/x86-openbsd-none/machine/pio.h new file mode 100644 index 000000000000..6ca1c2844448 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/pio.h @@ -0,0 +1,201 @@ +/* $OpenBSD: pio.h,v 1.12 2015/04/25 21:31:24 guenther Exp $ */ +/* $NetBSD: pio.h,v 1.13 1996/03/08 20:15:23 cgd Exp $ */ + +/* + * Copyright (c) 1993, 1995 Charles M. Hannum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Charles M. Hannum. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_PIO_H_ +#define _MACHINE_PIO_H_ + +/* + * Functions to provide access to i386 programmed I/O instructions. + * + * The in[bwl]() and out[bwl]() functions are split into two varieties: one to + * use a small, constant, 8-bit port number, and another to use a large or + * variable port number. The former can be compiled as a smaller instruction. + */ + + +#ifdef __OPTIMIZE__ + +#define __use_immediate_port(port) \ + (__builtin_constant_p((port)) && (port) < 0x100) + +#else + +#define __use_immediate_port(port) 0 + +#endif + + +#define inb(port) \ + (__use_immediate_port(port) ? __inbc(port) : __inb(port)) + +static __inline u_int8_t +__inbc(int port) +{ + u_int8_t data; + __asm volatile("inb %w1,%0" : "=a" (data) : "id" (port)); + return data; +} + +static __inline u_int8_t +__inb(int port) +{ + u_int8_t data; + __asm volatile("inb %w1,%0" : "=a" (data) : "d" (port)); + return data; +} + +static __inline void +insb(int port, void *addr, int cnt) +{ + __asm volatile("repne\n\tinsb" + : "+D" (addr), "+c" (cnt) : "d" (port) : "memory", "cc"); +} + +#define inw(port) \ + (__use_immediate_port(port) ? __inwc(port) : __inw(port)) + +static __inline u_int16_t +__inwc(int port) +{ + u_int16_t data; + __asm volatile("inw %w1,%0" : "=a" (data) : "id" (port)); + return data; +} + +static __inline u_int16_t +__inw(int port) +{ + u_int16_t data; + __asm volatile("inw %w1,%0" : "=a" (data) : "d" (port)); + return data; +} + +static __inline void +insw(int port, void *addr, int cnt) +{ + __asm volatile("repne\n\tinsw" + : "+D" (addr), "+c" (cnt) : "d" (port) : "memory", "cc"); +} + +#define inl(port) \ + (__use_immediate_port(port) ? __inlc(port) : __inl(port)) + +static __inline u_int32_t +__inlc(int port) +{ + u_int32_t data; + __asm volatile("inl %w1,%0" : "=a" (data) : "id" (port)); + return data; +} + +static __inline u_int32_t +__inl(int port) +{ + u_int32_t data; + __asm volatile("inl %w1,%0" : "=a" (data) : "d" (port)); + return data; +} + +static __inline void +insl(int port, void *addr, int cnt) +{ + __asm volatile("repne\n\tinsl" + : "+D" (addr), "+c" (cnt) : "d" (port) : "memory", "cc"); +} + +#define outb(port, data) \ + (__use_immediate_port(port) ? __outbc(port, data) : __outb(port, data)) + +static __inline void +__outbc(int port, u_int8_t data) +{ + __asm volatile("outb %0,%w1" : : "a" (data), "id" (port)); +} + +static __inline void +__outb(int port, u_int8_t data) +{ + __asm volatile("outb %0,%w1" : : "a" (data), "d" (port)); +} + +static __inline void +outsb(int port, const void *addr, int cnt) +{ + __asm volatile("repne\n\toutsb" + : "+S" (addr), "+c" (cnt) : "d" (port) : "cc"); +} + +#define outw(port, data) \ + (__use_immediate_port(port) ? __outwc(port, data) : __outw(port, data)) + +static __inline void +__outwc(int port, u_int16_t data) +{ + __asm volatile("outw %0,%w1" : : "a" (data), "id" (port)); +} + +static __inline void +__outw(int port, u_int16_t data) +{ + __asm volatile("outw %0,%w1" : : "a" (data), "d" (port)); +} + +static __inline void +outsw(int port, const void *addr, int cnt) +{ + __asm volatile("repne\n\toutsw" + : "+S" (addr), "+c" (cnt) : "d" (port) : "cc"); +} + +#define outl(port, data) \ + (__use_immediate_port(port) ? __outlc(port, data) : __outl(port, data)) + +static __inline void +__outlc(int port, u_int32_t data) +{ + __asm volatile("outl %0,%w1" : : "a" (data), "id" (port)); +} + +static __inline void +__outl(int port, u_int32_t data) +{ + __asm volatile("outl %0,%w1" : : "a" (data), "d" (port)); +} + +static __inline void +outsl(int port, const void *addr, int cnt) +{ + __asm volatile("repne\n\toutsl" + : "+S" (addr), "+c" (cnt) : "d" (port) : "cc"); +} + +#endif /* _MACHINE_PIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/pmap.h b/lib/libc/include/x86-openbsd-none/machine/pmap.h new file mode 100644 index 000000000000..0c46db395ee2 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/pmap.h @@ -0,0 +1,480 @@ +/* $OpenBSD: pmap.h,v 1.98 2025/07/16 07:15:42 jsg Exp $ */ +/* $NetBSD: pmap.h,v 1.44 2000/04/24 17:18:18 thorpej Exp $ */ + +/* + * Copyright (c) 1997 Charles D. Cranor and Washington University. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * pmap.h: see pmap.c for the history of this pmap module. + */ + +#ifndef _MACHINE_PMAP_H_ +#define _MACHINE_PMAP_H_ + +#ifdef _KERNEL +#include +#include +#endif +#include +#include +#include + +#define PDSLOT_PTE ((KERNBASE/NBPD)-2) /* 830: for recursive PDP map */ +#define PDSLOT_KERN (KERNBASE/NBPD) /* 832: start of kernel space */ +#define PDSLOT_APTE ((unsigned)1022) /* 1022: alternative recursive slot */ + +/* + * The following define determines how many PTPs should be set up for the + * kernel by locore.s at boot time. This should be large enough to + * get the VM system running. Once the VM system is running, the + * pmap module can add more PTPs to the kernel area on demand. + */ + +#ifndef NKPTP +#define NKPTP 8 /* 16/32MB to start */ +#endif +#define NKPTP_MIN 4 /* smallest value we allow */ + +/* + * PG_AVAIL usage: we make use of the ignored bits of the PTE + */ + +#define PG_W PG_AVAIL1 /* "wired" mapping */ +#define PG_PVLIST PG_AVAIL2 /* mapping has entry on pvlist */ +#define PG_X PG_AVAIL3 /* executable mapping */ + +#define PTP0_PA (PAGE_SIZE * 3) + +#ifdef _KERNEL +/* + * pmap data structures: see pmap.c for details of locking. + */ + +struct pmap; +typedef struct pmap *pmap_t; + +/* + * We maintain a list of all non-kernel pmaps. + */ + +LIST_HEAD(pmap_head, pmap); /* struct pmap_head: head of a pmap list */ + +/* + * The pmap structure + * + * Note that the pm_obj contains the reference count, + * page list, and number of PTPs within the pmap. + */ + +struct pmap { + uint64_t pm_pdidx[4]; /* PDIEs for PAE mode */ + uint64_t pm_pdidx_intel[4]; /* PDIEs for PAE mode U-K */ + + struct mutex pm_mtx; + struct mutex pm_apte_mtx; + + /* + * pm_pdir : VA of PD when executing in privileged mode + * (lock by object lock) + * pm_pdirpa : PA of PD when executing in privileged mode, + * (read-only after create) + * pm_pdir_intel : VA of PD when executing on Intel CPU in + * usermode (no kernel mappings) + * pm_pdirpa_intel : PA of PD when executing on Intel CPU in + * usermode (no kernel mappings) + */ + paddr_t pm_pdirpa, pm_pdirpa_intel; + vaddr_t pm_pdir, pm_pdir_intel; + int pm_pdirsize; /* PD size (4k vs 16k on PAE) */ + struct uvm_object pm_obj; /* object (lck by object lock) */ + LIST_ENTRY(pmap) pm_list; /* list (lck by pm_list lock) */ + struct vm_page *pm_ptphint; /* pointer to a PTP in our pmap */ + struct pmap_statistics pm_stats; /* pmap stats (lck by object lock) */ + + vaddr_t pm_hiexec; /* highest executable mapping */ + int pm_flags; /* see below */ + + struct segment_descriptor pm_codeseg; /* cs descriptor for process */ +}; + +/* + * For each managed physical page we maintain a list of s + * which it is mapped at. The list is headed by a pv_head structure. + * there is one pv_head per managed phys page (allocated at boot time). + * The pv_head structure points to a list of pv_entry structures (each + * describes one mapping). + */ + +struct pv_entry { /* locked by its list's pvh_lock */ + struct pv_entry *pv_next; /* next entry */ + struct pmap *pv_pmap; /* the pmap */ + vaddr_t pv_va; /* the virtual address */ + struct vm_page *pv_ptp; /* the vm_page of the PTP */ +}; +/* + * MD flags to pmap_enter: + */ + +/* to get just the pa from params to pmap_enter */ +#define PMAP_PA_MASK ~((paddr_t)PAGE_MASK) +#define PMAP_NOCACHE 0x1 /* map uncached */ +#define PMAP_WC 0x2 /* map write combining. */ + +/* + * We keep mod/ref flags in struct vm_page->pg_flags. + */ +#define PG_PMAP_MOD PG_PMAP0 +#define PG_PMAP_REF PG_PMAP1 +#define PG_PMAP_WC PG_PMAP2 + +/* + * pv_entrys are dynamically allocated in chunks from a single page. + * we keep track of how many pv_entrys are in use for each page and + * we can free pv_entry pages if needed. There is one lock for the + * entire allocation system. + */ + +struct pv_page_info { + TAILQ_ENTRY(pv_page) pvpi_list; + struct pv_entry *pvpi_pvfree; + int pvpi_nfree; +}; + +/* + * number of pv_entries in a pv_page + */ + +#define PVE_PER_PVPAGE ((PAGE_SIZE - sizeof(struct pv_page_info)) / \ + sizeof(struct pv_entry)) + +/* + * a pv_page: where pv_entrys are allocated from + */ + +struct pv_page { + struct pv_page_info pvinfo; + struct pv_entry pvents[PVE_PER_PVPAGE]; +}; + +/* + * pv_entrys are dynamically allocated in chunks from a single page. + * we keep track of how many pv_entrys are in use for each page and + * we can free pv_entry pages if needed. There is one lock for the + * entire allocation system. + */ + +extern char PTD[]; +extern struct pmap kernel_pmap_store; /* kernel pmap */ +extern int nkptp_max; + +#define PMAP_REMOVE_ALL 0 +#define PMAP_REMOVE_SKIPWIRED 1 + +extern struct pool pmap_pv_pool; + +/* + * Macros + */ + +#define pmap_kernel() (&kernel_pmap_store) +#define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count) +#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) +#define pmap_update(pm) /* nada */ + +#define pmap_clear_modify(pg) pmap_clear_attrs(pg, PG_M) +#define pmap_clear_reference(pg) pmap_clear_attrs(pg, PG_U) +#define pmap_is_modified(pg) pmap_test_attrs(pg, PG_M) +#define pmap_is_referenced(pg) pmap_test_attrs(pg, PG_U) +#define pmap_valid_entry(E) ((E) & PG_V) /* is PDE or PTE valid? */ + +#define pmap_proc_iflush(p,va,len) /* nothing */ +#define pmap_init_percpu() do { /* nothing */ } while (0) +#define pmap_unuse_final(p) /* nothing */ +#define pmap_remove_holes(vm) do { /* nothing */ } while (0) + +/* + * Prototypes + */ + +vaddr_t pmap_tmpmap_pa_86(paddr_t); +vaddr_t pmap_tmpmap_pa(paddr_t); +void pmap_tmpunmap_pa_86(void); +void pmap_tmpunmap_pa(void); + +void pmap_bootstrap(vaddr_t); +void pmap_bootstrap_pae(void); +void pmap_virtual_space(vaddr_t *, vaddr_t *); +void pmap_init(void); +struct pmap *pmap_create(void); +void pmap_destroy(struct pmap *); +void pmap_reference(struct pmap *); +void pmap_remove(struct pmap *, vaddr_t, vaddr_t); +void pmap_activate(struct proc *); +void pmap_deactivate(struct proc *); +void pmap_kenter_pa(vaddr_t, paddr_t, vm_prot_t); +void pmap_kremove(vaddr_t, vsize_t); +void pmap_zero_page(struct vm_page *); +void pmap_copy_page(struct vm_page *, struct vm_page *); +void pmap_enter_pv(struct vm_page *, struct pv_entry *, + struct pmap *, vaddr_t, struct vm_page *); +int pmap_clear_attrs(struct vm_page *, int); +static void pmap_page_protect(struct vm_page *, vm_prot_t); +void pmap_page_remove(struct vm_page *); +static void pmap_protect(struct pmap *, vaddr_t, + vaddr_t, vm_prot_t); +void pmap_remove(struct pmap *, vaddr_t, vaddr_t); +int pmap_test_attrs(struct vm_page *, int); +void pmap_write_protect(struct pmap *, vaddr_t, + vaddr_t, vm_prot_t); +int pmap_exec_fixup(struct vm_map *, struct trapframe *, + vaddr_t, struct pcb *); +void pmap_exec_account(struct pmap *, vaddr_t, u_int32_t, + u_int32_t); +struct pv_entry *pmap_remove_pv(struct vm_page *, struct pmap *, vaddr_t); +void pmap_apte_flush(void); +void pmap_switch(struct proc *, struct proc *); +vaddr_t reserve_dumppages(vaddr_t); /* XXX: not a pmap fn */ +paddr_t vtophys(vaddr_t va); +paddr_t vtophys_pae(vaddr_t va); + +extern u_int32_t (*pmap_pte_set_p)(vaddr_t, paddr_t, u_int32_t); +extern u_int32_t (*pmap_pte_setbits_p)(vaddr_t, u_int32_t, u_int32_t); +extern u_int32_t (*pmap_pte_bits_p)(vaddr_t); +extern paddr_t (*pmap_pte_paddr_p)(vaddr_t); +extern int (*pmap_clear_attrs_p)(struct vm_page *, int); +extern int (*pmap_enter_p)(pmap_t, vaddr_t, paddr_t, vm_prot_t, int); +extern void (*pmap_enter_special_p)(vaddr_t, paddr_t, vm_prot_t, u_int32_t); +extern int (*pmap_extract_p)(pmap_t, vaddr_t, paddr_t *); +extern vaddr_t (*pmap_growkernel_p)(vaddr_t); +extern void (*pmap_page_remove_p)(struct vm_page *); +extern void (*pmap_do_remove_p)(struct pmap *, vaddr_t, vaddr_t, int); +extern int (*pmap_test_attrs_p)(struct vm_page *, int); +extern void (*pmap_unwire_p)(struct pmap *, vaddr_t); +extern void (*pmap_write_protect_p)(struct pmap*, vaddr_t, vaddr_t, vm_prot_t); +extern void (*pmap_pinit_pd_p)(pmap_t); +extern void (*pmap_zero_phys_p)(paddr_t); +extern void (*pmap_copy_page_p)(struct vm_page *, struct vm_page *); + +u_int32_t pmap_pte_set_pae(vaddr_t, paddr_t, u_int32_t); +u_int32_t pmap_pte_setbits_pae(vaddr_t, u_int32_t, u_int32_t); +u_int32_t pmap_pte_bits_pae(vaddr_t); +paddr_t pmap_pte_paddr_pae(vaddr_t); +int pmap_clear_attrs_pae(struct vm_page *, int); +int pmap_enter_pae(pmap_t, vaddr_t, paddr_t, vm_prot_t, int); +void pmap_enter_special_pae(vaddr_t, paddr_t, vm_prot_t, u_int32_t); +int pmap_extract_pae(pmap_t, vaddr_t, paddr_t *); +vaddr_t pmap_growkernel_pae(vaddr_t); +void pmap_page_remove_pae(struct vm_page *); +void pmap_do_remove_pae(struct pmap *, vaddr_t, vaddr_t, int); +int pmap_test_attrs_pae(struct vm_page *, int); +void pmap_unwire_pae(struct pmap *, vaddr_t); +void pmap_write_protect_pae(struct pmap *, vaddr_t, vaddr_t, vm_prot_t); +void pmap_pinit_pd_pae(pmap_t); +void pmap_zero_phys_pae(paddr_t); +void pmap_copy_page_pae(struct vm_page *, struct vm_page *); + +#define pmap_pte_set (*pmap_pte_set_p) +#define pmap_pte_setbits (*pmap_pte_setbits_p) +#define pmap_pte_bits (*pmap_pte_bits_p) +#define pmap_pte_paddr (*pmap_pte_paddr_p) +#define pmap_clear_attrs (*pmap_clear_attrs_p) +#define pmap_page_remove (*pmap_page_remove_p) +#define pmap_do_remove (*pmap_do_remove_p) +#define pmap_test_attrs (*pmap_test_attrs_p) +#define pmap_unwire (*pmap_unwire_p) +#define pmap_write_protect (*pmap_write_protect_p) +#define pmap_pinit_pd (*pmap_pinit_pd_p) +#define pmap_zero_phys (*pmap_zero_phys_p) +#define pmap_copy_page (*pmap_copy_page_p) + +u_int32_t pmap_pte_set_86(vaddr_t, paddr_t, u_int32_t); +u_int32_t pmap_pte_setbits_86(vaddr_t, u_int32_t, u_int32_t); +u_int32_t pmap_pte_bits_86(vaddr_t); +paddr_t pmap_pte_paddr_86(vaddr_t); +int pmap_clear_attrs_86(struct vm_page *, int); +int pmap_enter_86(pmap_t, vaddr_t, paddr_t, vm_prot_t, int); +void pmap_enter_special_86(vaddr_t, paddr_t, vm_prot_t, u_int32_t); +int pmap_extract_86(pmap_t, vaddr_t, paddr_t *); +vaddr_t pmap_growkernel_86(vaddr_t); +void pmap_page_remove_86(struct vm_page *); +void pmap_do_remove_86(struct pmap *, vaddr_t, vaddr_t, int); +int pmap_test_attrs_86(struct vm_page *, int); +void pmap_unwire_86(struct pmap *, vaddr_t); +void pmap_write_protect_86(struct pmap *, vaddr_t, vaddr_t, vm_prot_t); +void pmap_pinit_pd_86(pmap_t); +void pmap_zero_phys_86(paddr_t); +void pmap_copy_page_86(struct vm_page *, struct vm_page *); +void pmap_tlb_shootpage(struct pmap *, vaddr_t); +void pmap_tlb_shootrange(struct pmap *, vaddr_t, vaddr_t); +void pmap_tlb_shoottlb(void); +#ifdef MULTIPROCESSOR +void pmap_tlb_droppmap(struct pmap *); +void pmap_tlb_shootwait(void); +#else +#define pmap_tlb_shootwait() +#endif + +void pmap_prealloc_lowmem_ptp(void); +void pmap_prealloc_lowmem_ptp_pae(void); +vaddr_t pmap_tmpmap_pa(paddr_t); +void pmap_tmpunmap_pa(void); +vaddr_t pmap_tmpmap_pa_pae(paddr_t); +void pmap_tmpunmap_pa_pae(void); + + +/* + * functions for flushing the cache for vaddrs and pages. + * these functions are not part of the MI pmap interface and thus + * should not be used as such. + */ +void pmap_flush_cache(vaddr_t, vsize_t); +void pmap_flush_page(paddr_t); +void pmap_flush_page_pae(paddr_t); + +#define PMAP_CHECK_COPYIN 1 + +#define PMAP_GROWKERNEL /* turn on pmap_growkernel interface */ + +/* + * Inline functions + */ + +/* + * pmap_update_pg: flush one page from the TLB (or flush the whole thing + * if hardware doesn't support one-page flushing) + */ + +#define pmap_update_pg(va) invlpg((u_int)(va)) + +/* + * pmap_update_2pg: flush two pages from the TLB + */ + +#define pmap_update_2pg(va, vb) { invlpg((u_int)(va)); invlpg((u_int)(vb)); } + +/* + * pmap_page_protect: change the protection of all recorded mappings + * of a managed page + * + * => This function is a front end for pmap_page_remove/pmap_clear_attrs + * => We only have to worry about making the page more protected. + * Unprotecting a page is done on-demand at fault time. + */ + +static __inline void +pmap_page_protect(struct vm_page *pg, vm_prot_t prot) +{ + if ((prot & PROT_WRITE) == 0) { + if (prot & (PROT_READ | PROT_EXEC)) { + (void) pmap_clear_attrs(pg, PG_RW); + } else { + pmap_page_remove(pg); + } + } +} + +/* + * pmap_protect: change the protection of pages in a pmap + * + * => This function is a front end for pmap_remove/pmap_write_protect. + * => We only have to worry about making the page more protected. + * Unprotecting a page is done on-demand at fault time. + */ + +static __inline void +pmap_protect(struct pmap *pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot) +{ + if ((prot & PROT_WRITE) == 0) { + if (prot & (PROT_READ | PROT_EXEC)) { + pmap_write_protect(pmap, sva, eva, prot); + } else { + pmap_remove(pmap, sva, eva); + } + } +} + +/* + * pmap_growkernel, pmap_enter, and pmap_extract get picked up in various + * modules from both uvm_pmap.h and pmap.h. Since uvm_pmap.h defines these + * as functions, inline them here to suppress linker warnings. + */ +static __inline vaddr_t +pmap_growkernel(vaddr_t maxkvaddr) +{ + return (*pmap_growkernel_p)(maxkvaddr); +} + +static __inline int +pmap_enter(struct pmap *pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags) +{ + return (*pmap_enter_p)(pmap, va, pa, prot, flags); +} + +static __inline void +pmap_enter_special(vaddr_t va, paddr_t pa, vm_prot_t prot, u_int32_t flags) +{ + (*pmap_enter_special_p)(va, pa, prot, flags); +} + +static __inline int +pmap_extract(struct pmap *pmap, vaddr_t va, paddr_t *pa) +{ + return (*pmap_extract_p)(pmap, va, pa); +} + +/* + * p m a p i n l i n e h e l p e r f u n c t i o n s + */ + +/* + * pmap_is_active: is this pmap loaded into the specified processor's %cr3? + */ + +static __inline int +pmap_is_active(struct pmap *pmap, struct cpu_info *ci) +{ + return (pmap == pmap_kernel() || ci->ci_curpmap == pmap); +} + +static __inline int +pmap_is_curpmap(struct pmap *pmap) +{ + return (pmap_is_active(pmap, curcpu())); +} + +#endif /* _KERNEL */ + +struct pv_entry; +struct vm_page_md { + struct mutex pv_mtx; + struct pv_entry *pv_list; +}; + +#define VM_MDPAGE_INIT(pg) do { \ + mtx_init(&(pg)->mdpage.pv_mtx, IPL_VM); \ + (pg)->mdpage.pv_list = NULL; \ +} while (0) + +#endif /* _MACHINE_PMAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/proc.h b/lib/libc/include/x86-openbsd-none/machine/proc.h new file mode 100644 index 000000000000..aa4ac664f980 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/proc.h @@ -0,0 +1,45 @@ +/* $OpenBSD: proc.h,v 1.10 2018/03/31 13:45:03 bluhm Exp $ */ +/* $NetBSD: proc.h,v 1.10 1995/08/06 05:33:23 mycroft Exp $ */ + +/* + * Copyright (c) 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)proc.h 7.1 (Berkeley) 5/15/91 + */ + +/* + * Machine-dependent part of the proc structure for i386. + */ +struct mdproc { + struct trapframe *md_regs; /* registers on current frame */ + int md_flags; /* machine-dependent flags */ + int md_astpending; +}; + +/* md_flags */ +#define MDP_USEDFPU 0x0001 /* has used the FPU */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/profile.h b/lib/libc/include/x86-openbsd-none/machine/profile.h new file mode 100644 index 000000000000..b6762e06dadb --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/profile.h @@ -0,0 +1,76 @@ +/* $OpenBSD: profile.h,v 1.12 2014/03/29 18:09:29 guenther Exp $ */ +/* $NetBSD: profile.h,v 1.6 1995/03/28 18:17:08 jtc Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)profile.h 8.1 (Berkeley) 6/11/93 + */ + +#define _MCOUNT_DECL static __inline void _mcount + +#define MCOUNT \ +extern void mcount(void) __asm("__mcount"); \ +__weak_alias(mcount,__mcount); \ +void \ +mcount(void) \ +{ \ + int selfpc, frompcindex; \ + int eax, ecx, edx; \ + \ + __asm volatile("movl %%eax,%0" : "=g" (eax)); \ + __asm volatile("movl %%ecx,%0" : "=g" (ecx)); \ + __asm volatile("movl %%edx,%0" : "=g" (edx)); \ + /* \ + * find the return address for mcount, \ + * and the return address for mcount's caller. \ + * \ + * selfpc = pc pushed by mcount call \ + */ \ + __asm volatile ("movl 4(%%ebp),%0" : "=r" (selfpc)); \ + /* \ + * frompcindex = pc pushed by call into self. \ + */ \ + __asm volatile ("movl (%%ebp),%0;movl 4(%0),%0" : \ + "+r" (frompcindex)); \ + _mcount(frompcindex, selfpc); \ + \ + __asm volatile("movl %0,%%edx" : : "g" (edx)); \ + __asm volatile("movl %0,%%ecx" : : "g" (ecx)); \ + __asm volatile("movl %0,%%eax" : : "g" (eax)); \ +} + +#ifdef _KERNEL +/* + * We inline the code that splhigh and splx would do here as otherwise we would + * call recursively into mcount() as machdep.c is compiled with -pg on a + * profiling build. + */ +#define MCOUNT_ENTER _SPLRAISE(s, IPL_HIGH); __splbarrier() +#define MCOUNT_EXIT __splbarrier(); _SPLX(s) +#endif /* _KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/psl.h b/lib/libc/include/x86-openbsd-none/machine/psl.h new file mode 100644 index 000000000000..f59e7e0c7772 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/psl.h @@ -0,0 +1,98 @@ +/* $OpenBSD: psl.h,v 1.21 2018/07/09 19:20:30 guenther Exp $ */ +/* $NetBSD: psl.h,v 1.30 1996/05/13 01:28:05 mycroft Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)psl.h 5.2 (Berkeley) 1/18/91 + */ + +#ifndef _MACHINE_PSL_H_ +#define _MACHINE_PSL_H_ + +/* + * 386 processor status longword. + */ +#define PSL_C 0x00000001 /* carry flag */ +#define PSL_PF 0x00000004 /* parity flag */ +#define PSL_AF 0x00000010 /* auxiliary carry flag */ +#define PSL_Z 0x00000040 /* zero flag */ +#define PSL_N 0x00000080 /* sign flag */ +#define PSL_T 0x00000100 /* trap flag */ +#define PSL_I 0x00000200 /* interrupt enable flag */ +#define PSL_D 0x00000400 /* direction flag */ +#define PSL_V 0x00000800 /* overflow flag */ +#define PSL_IOPL 0x00003000 /* i/o privilege level */ +#define PSL_NT 0x00004000 /* nested task */ +#define PSL_RF 0x00010000 /* resume flag */ +#define PSL_VM 0x00020000 /* virtual 8086 mode */ +#define PSL_AC 0x00040000 /* alignment check flag */ +#define PSL_VIF 0x00080000 /* virtual interrupt enable flag */ +#define PSL_VIP 0x00100000 /* virtual interrupt pending flag */ +#define PSL_ID 0x00200000 /* identification flag */ +#define PSL_XCRYPT 0x40000000 /* VIA xcrypt: operation loaded */ + +#define PSL_MBO 0x00000002 /* must be one bits */ +#define PSL_MBZ 0xffc08028 /* must be zero bits */ + +#define PSL_USERSET (PSL_MBO | PSL_I) +#define PSL_USERSTATIC (PSL_MBO | PSL_MBZ | PSL_I | PSL_IOPL | PSL_NT | PSL_VM | PSL_VIF | PSL_VIP) + +#ifdef _KERNEL +#include + +#ifndef _LOCORE + +#include + +/* + * Interrupt handler chains. isa_intr_establish() inserts a handler into + * the list. The handler is called with its (single) argument. + */ + +struct intrhand { + int (*ih_fun)(void *); + void *ih_arg; + int ih_level; + int ih_flags; + struct intrhand *ih_next; + int ih_pin; + int ih_irq; + struct evcount ih_count; + int ih_vec; +}; + +extern int intr_shared_edge; /* This system has shared edge interrupts */ + +#endif /* _LOCORE */ +#endif /* _KERNEL */ + +#endif /* !_MACHINE_PSL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/pte.h b/lib/libc/include/x86-openbsd-none/machine/pte.h new file mode 100644 index 000000000000..14a6902bf329 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/pte.h @@ -0,0 +1,92 @@ +/* $OpenBSD: pte.h,v 1.23 2019/01/18 01:34:50 pd Exp $ */ +/* $NetBSD: pte.h,v 1.11 1998/02/06 21:58:05 thorpej Exp $ */ + +/* + * Copyright (c) 1997 Charles D. Cranor and Washington University. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * pte.h rewritten by chuck based on the jolitz version, plus random + * info on the pentium and other processors found on the net. the + * goal of this rewrite is to provide enough documentation on the MMU + * hardware that the reader will be able to understand it without having + * to refer to a hardware manual. + */ + +#ifndef _MACHINE_PTE_H_ +#define _MACHINE_PTE_H_ + +/* + * now we define various for playing with virtual addresses + */ + +#define PDSHIFT 22 /* offset of PD index in VA */ +#define NBPD (1 << PDSHIFT) /* # bytes mapped by PD (4MB) */ + +/* + * here we define the bits of the PDE/PTE, as described above: + * + * XXXCDC: need to rename these (PG_u == ugly). + */ + +#define PG_V 0x00000001 /* valid entry */ +#define PG_RO 0x00000000 /* read-only page */ +#define PG_RW 0x00000002 /* read-write page */ +#define PG_u 0x00000004 /* user accessible page */ +#define PG_PROT 0x00000806 /* all protection bits */ +#define PG_WT 0x00000008 /* write through */ +#define PG_N 0x00000010 /* non-cacheable */ +#define PG_U 0x00000020 /* has been used */ +#define PG_M 0x00000040 /* has been modified */ +#define PG_PAT 0x00000080 /* PAT bit. (on pte) */ +#define PG_PS 0x00000080 /* 4MB page size (on pde) */ +#define PG_G 0x00000100 /* global, don't TLB flush */ +#define PG_AVAIL1 0x00000200 /* ignored by hardware */ +#define PG_AVAIL2 0x00000400 /* ignored by hardware */ +#define PG_AVAIL3 0x00000800 /* ignored by hardware */ +#define PG_PATLG 0x00001000 /* PAT on large pages */ + +/* Cacheability bits when we are using PAT */ +#define PG_WB (0) /* The default */ +#define PG_WC (PG_WT) /* WT and CD is WC */ +#define PG_UCMINUS (PG_N) /* UC but mtrr can override */ +#define PG_UC (PG_WT | PG_N) /* hard UC */ + +/* + * various shorthand protection codes + */ + +#define PG_KR 0x00000000 /* kernel read-only */ +#define PG_KW 0x00000002 /* kernel read-write */ + +/* + * page protection exception bits + */ + +#define PGEX_P 0x01 /* protection violation (vs. no mapping) */ +#define PGEX_W 0x02 /* exception during a write cycle */ +#define PGEX_U 0x04 /* exception while in user mode (upl) */ +#define PGEX_I 0x10 /* instruction fetch blocked by NX */ + +#endif /* _MACHINE_PTE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/ptrace.h b/lib/libc/include/x86-openbsd-none/machine/ptrace.h new file mode 100644 index 000000000000..d8efdad5a982 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/ptrace.h @@ -0,0 +1,50 @@ +/* $OpenBSD: ptrace.h,v 1.3 2005/04/03 20:21:44 kettenis Exp $ */ +/* $NetBSD: ptrace.h,v 1.6 1995/08/06 05:33:23 mycroft Exp $ */ + +/* + * Copyright (c) 1993 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * i386-dependent ptrace definitions + */ +#define PT_STEP (PT_FIRSTMACH + 0) +#define PT_GETREGS (PT_FIRSTMACH + 1) +#define PT_SETREGS (PT_FIRSTMACH + 2) +#define PT_GETFPREGS (PT_FIRSTMACH + 3) +#define PT_SETFPREGS (PT_FIRSTMACH + 4) +#define PT_GETXMMREGS (PT_FIRSTMACH + 5) +#define PT_SETXMMREGS (PT_FIRSTMACH + 6) + +#ifdef _KERNEL +struct xmmregs; + +int process_read_xmmregs(struct proc *, struct xmmregs *); +int process_write_xmmregs(struct proc *, const struct xmmregs *); +#endif \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/rbus_machdep.h b/lib/libc/include/x86-openbsd-none/machine/rbus_machdep.h new file mode 100644 index 000000000000..0d0d6eda307e --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/rbus_machdep.h @@ -0,0 +1,48 @@ +/* $OpenBSD: rbus_machdep.h,v 1.10 2024/05/22 05:51:49 jsg Exp $ */ +/* $NetBSD: rbus_machdep.h,v 1.2 1999/10/15 06:43:05 haya Exp $ */ + +/* + * Copyright (c) 1999 + * HAYAKAWA Koichi. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_RBUS_MACHDEP_H_ +#define _MACHINE_RBUS_MACHDEP_H_ + +struct pci_attach_args; /* XXX */ + +#define md_space_map(rbt, physaddr, size, flags, bshp) \ + _bus_space_map((rbt)->rb_bt, (physaddr), (size), (flags), (bshp)) + +#define md_space_unmap(rbt, bsh, size, adrp) \ + _bus_space_unmap((rbt)->rb_bt, (bsh), (size), (adrp)) + +rbus_tag_t rbus_pccbb_parent_io(struct device *, + struct pci_attach_args *); +rbus_tag_t rbus_pccbb_parent_mem(struct device *, + struct pci_attach_args *); + +void pccbb_attach_hook(struct device *, struct device *, + struct pci_attach_args *); + +#endif /* _MACHINE_RBUS_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/reg.h b/lib/libc/include/x86-openbsd-none/machine/reg.h new file mode 100644 index 000000000000..b25bcac8853f --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/reg.h @@ -0,0 +1,103 @@ +/* $OpenBSD: reg.h,v 1.7 2011/03/23 16:54:35 pirofti Exp $ */ +/* $NetBSD: reg.h,v 1.14 1995/10/11 04:20:24 mycroft Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)reg.h 5.5 (Berkeley) 1/18/91 + */ + +#ifndef _MACHINE_REG_H_ +#define _MACHINE_REG_H_ + +/* + * Location of the users' stored + * registers within appropriate frame of 'trap' and 'syscall', relative to + * base of stack frame. + * Normal usage is u.u_ar0[XX] in kernel. + */ + +/* When referenced during a trap/exception, registers are at these offsets */ + +#define tES (0) +#define tDS (1) +#define tEDI (2) +#define tESI (3) +#define tEBP (4) +#define tEBX (5) +#define tEDX (6) +#define tECX (7) +#define tEAX (8) + +#define tEIP (11) +#define tCS (12) +#define tEFLAGS (13) +#define tESP (14) +#define tSS (15) + +/* + * Registers accessible to ptrace(2) syscall for debugger + * The machine-dependent code for PT_{SET,GET}REGS needs to + * use whichever order, defined above, is correct, so that it + * is all invisible to the user. + */ +struct reg { + int r_eax; + int r_ecx; + int r_edx; + int r_ebx; + int r_esp; + int r_ebp; + int r_esi; + int r_edi; + int r_eip; + int r_eflags; + int r_cs; + int r_ss; + int r_ds; + int r_es; + int r_fs; + int r_gs; +}; + +struct fpreg { + /* + * XXX + * Fill this in with real info. + */ + char __data[116]; +}; + +struct xmmregs { + char __data[512]; +}; + +#endif /* !_MACHINE_REG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/reloc.h b/lib/libc/include/x86-openbsd-none/machine/reloc.h new file mode 100644 index 000000000000..e2d976bbfd9b --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/reloc.h @@ -0,0 +1,52 @@ +/* $OpenBSD: reloc.h,v 1.3 2011/03/23 16:54:35 pirofti Exp $ */ + +/* + * Copyright (c) 2002,2003 Dale Rahn + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _MACHINE_RELOC_H_ +#define _MACHINE_RELOC_H_ +#define R_TYPE(X) __CONCAT(RELOC_,X) + + +#define RELOC_NONE 0 /* No reloc */ +#define RELOC_32 1 /* Direct 32 bit */ +#define RELOC_PC32 2 /* PC relative 32 bit */ +#define RELOC_GOT32 3 /* 32 bit GOT entry */ +#define RELOC_PLT32 4 /* 32 bit PLT address */ +#define RELOC_COPY 5 /* Copy symbol at runtime */ +#define RELOC_GLOB_DAT 6 /* Create GOT entry */ +#define RELOC_JUMP_SLOT 7 /* Create PLT entry */ +#define RELOC_RELATIVE 8 /* Adjust by program base */ +#define RELOC_GOTOFF 9 /* 32 bit offset to GOT */ +#define RELOC_GOTPC 10 /* 32 bit PC relative offset to GOT */ +#define RELOC_TLS_TPOFF 14 /* negative offset in static TLS block */ +#define RELOC_16 20 +#define RELOC_PC16 21 +#define RELOC_8 22 +#define RELOC_PC8 23 +#define RELOC_TLS_DTPMOD32 35 /* ID of module containing symbol */ +#define RELOC_TLS_DTPOFF32 36 /* Offset in TLS block */ +#define RELOC_TLS_TPOFF32 37 /* Offset in static TLS block */ + +#endif /* _MACHINE_RELOC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/segments.h b/lib/libc/include/x86-openbsd-none/machine/segments.h new file mode 100644 index 000000000000..03a4bc81be9e --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/segments.h @@ -0,0 +1,229 @@ +/* $OpenBSD: segments.h,v 1.28 2020/09/24 11:36:50 deraadt Exp $ */ +/* $NetBSD: segments.h,v 1.23 1996/02/01 22:31:03 mycroft Exp $ */ + +/*- + * Copyright (c) 1995 Charles M. Hannum. All rights reserved. + * Copyright (c) 1989, 1990 William F. Jolitz + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)segments.h 7.1 (Berkeley) 5/9/91 + */ + +/* + * 386 Segmentation Data Structures and definitions + * William F. Jolitz (william@ernie.berkeley.edu) 6/20/1989 + */ + +#ifndef _MACHINE_SEGMENTS_H_ +#define _MACHINE_SEGMENTS_H_ + +/* + * Selectors + */ + +#define ISPL(s) ((s) & SEL_RPL) /* what is the priority level of a selector */ +#define SEL_KPL 0 /* kernel privilege level */ +#define SEL_UPL 3 /* user privilege level */ +#define SEL_RPL 3 /* requester's privilege level mask */ +#define ISLDT(s) ((s) & SEL_LDT) /* is it local or global */ +#define SEL_LDT 4 /* local descriptor table */ +#define IDXSEL(s) (((s) >> 3) & 0x1fff) /* index of selector */ +#define GSEL(s,r) (((s) << 3) | r) /* a global selector */ +#define LSEL(s,r) (((s) << 3) | r | SEL_LDT) /* a local selector */ + +#define USERMODE(c, f) (ISPL(c) == SEL_UPL) +#define KERNELMODE(c, f) (ISPL(c) == SEL_KPL) + +#ifndef _LOCORE + +/* + * Memory and System segment descriptors + */ +struct segment_descriptor { + unsigned sd_lolimit:16; /* segment extent (lsb) */ + unsigned sd_lobase:24; /* segment base address (lsb) */ + unsigned sd_type:5; /* segment type */ + unsigned sd_dpl:2; /* segment descriptor priority level */ + unsigned sd_p:1; /* segment descriptor present */ + unsigned sd_hilimit:4; /* segment extent (msb) */ + unsigned sd_xx:2; /* unused */ + unsigned sd_def32:1; /* default 32 vs 16 bit size */ + unsigned sd_gran:1; /* limit granularity (byte/page) */ + unsigned sd_hibase:8; /* segment base address (msb) */ +} __packed; + +/* + * Gate descriptors (e.g. indirect descriptors) + */ +struct gate_descriptor { + unsigned gd_looffset:16; /* gate offset (lsb) */ + unsigned gd_selector:16; /* gate segment selector */ + unsigned gd_stkcpy:5; /* number of stack wds to cpy */ + unsigned gd_xx:3; /* unused */ + unsigned gd_type:5; /* segment type */ + unsigned gd_dpl:2; /* segment descriptor priority level */ + unsigned gd_p:1; /* segment descriptor present */ + unsigned gd_hioffset:16; /* gate offset (msb) */ +} __packed; + +/* + * Generic descriptor + */ +union descriptor { + struct segment_descriptor sd; + struct gate_descriptor gd; +} __packed; + +/* + * region descriptors, used to load gdt/idt tables before segments yet exist. + */ +struct region_descriptor { + unsigned rd_limit:16; /* segment extent */ + unsigned rd_base:32; /* base address */ +} __packed; + +#ifdef _KERNEL +extern union descriptor *gdt; +extern struct gate_descriptor idt_region[]; +extern struct gate_descriptor *idt; + +#define SEGDESC_LIMIT(sd) (ptoa(((sd).sd_hilimit << 16) | (sd).sd_lolimit)) + +void setgate(struct gate_descriptor *, void *, int, int, int, int); +void setregion(struct region_descriptor *, void *, size_t); +void setsegment(struct segment_descriptor *, void *, size_t, int, int, + int, int); +void initcodesegment(struct segment_descriptor *); +void unsetgate(struct gate_descriptor *); +void cpu_init_idt(void); + +int idt_vec_alloc(int, int); +void idt_vec_set(int, void (*)(void)); +void idt_vec_free(int); + +#endif /* _KERNEL */ + +#endif /* !_LOCORE */ + +/* system segments and gate types */ +#define SDT_SYSNULL 0 /* system null */ +#define SDT_SYS286TSS 1 /* system 286 TSS available */ +#define SDT_SYSLDT 2 /* system local descriptor table */ +#define SDT_SYS286BSY 3 /* system 286 TSS busy */ +#define SDT_SYS286CGT 4 /* system 286 call gate */ +#define SDT_SYSTASKGT 5 /* system task gate */ +#define SDT_SYS286IGT 6 /* system 286 interrupt gate */ +#define SDT_SYS286TGT 7 /* system 286 trap gate */ +#define SDT_SYSNULL2 8 /* system null again */ +#define SDT_SYS386TSS 9 /* system 386 TSS available */ +#define SDT_SYSNULL3 10 /* system null again */ +#define SDT_SYS386BSY 11 /* system 386 TSS busy */ +#define SDT_SYS386CGT 12 /* system 386 call gate */ +#define SDT_SYSNULL4 13 /* system null again */ +#define SDT_SYS386IGT 14 /* system 386 interrupt gate */ +#define SDT_SYS386TGT 15 /* system 386 trap gate */ + +/* memory segment types */ +#define SDT_MEMRO 16 /* memory read only */ +#define SDT_MEMROA 17 /* memory read only accessed */ +#define SDT_MEMRW 18 /* memory read write */ +#define SDT_MEMRWA 19 /* memory read write accessed */ +#define SDT_MEMROD 20 /* memory read only expand dwn limit */ +#define SDT_MEMRODA 21 /* memory read only expand dwn limit accessed */ +#define SDT_MEMRWD 22 /* memory read write expand dwn limit */ +#define SDT_MEMRWDA 23 /* memory read write expand dwn limit acessed */ +#define SDT_MEME 24 /* memory execute only */ +#define SDT_MEMEA 25 /* memory execute only accessed */ +#define SDT_MEMER 26 /* memory execute read */ +#define SDT_MEMERA 27 /* memory execute read accessed */ +#define SDT_MEMEC 28 /* memory execute only conforming */ +#define SDT_MEMEAC 29 /* memory execute only accessed conforming */ +#define SDT_MEMERC 30 /* memory execute read conforming */ +#define SDT_MEMERAC 31 /* memory execute read accessed conforming */ + +/* is memory segment descriptor pointer ? */ +#define ISMEMSDP(s) ((s->d_type) >= SDT_MEMRO && \ + (s->d_type) <= SDT_MEMERAC) + +/* is 286 gate descriptor pointer ? */ +#define IS286GDP(s) ((s->d_type) >= SDT_SYS286CGT && \ + (s->d_type) < SDT_SYS286TGT) + +/* is 386 gate descriptor pointer ? */ +#define IS386GDP(s) ((s->d_type) >= SDT_SYS386CGT && \ + (s->d_type) < SDT_SYS386TGT) + +/* is gate descriptor pointer ? */ +#define ISGDP(s) (IS286GDP(s) || IS386GDP(s)) + +/* is segment descriptor pointer ? */ +#define ISSDP(s) (ISMEMSDP(s) || !ISGDP(s)) + +/* is system segment descriptor pointer ? */ +#define ISSYSSDP(s) (!ISMEMSDP(s) && !ISGDP(s)) + +/* + * Segment Protection Exception code bits + */ +#define SEGEX_EXT 0x01 /* recursive or externally induced */ +#define SEGEX_IDT 0x02 /* interrupt descriptor table */ +#define SEGEX_TI 0x04 /* local descriptor table */ + +/* + * Entries in the Interrupt Descriptor Table (IDT) + */ +#define NIDT 256 +#define NRSVIDT 32 /* reserved entries for cpu exceptions */ + +/* + * Entries in the Global Descriptor Table (GDT) + */ +#define GNULL_SEL 0 /* Null descriptor */ +#define GCODE_SEL 1 /* Kernel code descriptor */ +#define GDATA_SEL 2 /* Kernel data descriptor */ +#define GLDT_SEL 3 /* Default LDT descriptor (UNUSED) */ +#define GCPU_SEL 4 /* per-CPU segment */ +#define GUCODE_SEL 5 /* User code descriptor (a stack short) */ +#define GUDATA_SEL 6 /* User data descriptor */ +#define GAPM32CODE_SEL 7 /* 32 bit APM code descriptor */ +#define GAPM16CODE_SEL 8 /* 16 bit APM code descriptor */ +#define GAPMDATA_SEL 9 /* APM data descriptor */ +#define GICODE_SEL 10 /* Interrupt code descriptor (same as Kernel code) */ +#define GUFS_SEL 11 /* User per-thread (%fs) descriptor */ +#define GUGS_SEL 12 /* User per-thread (%gs) descriptor */ +#define GTSS_SEL 13 /* common TSS */ +#define GNMITSS_SEL 14 /* NMI TSS */ +#define GBIOS32_SEL 15 /* spare slot for 32 bit BIOS calls */ +#define NGDT 16 + +#define GDT_SIZE (NGDT << 3) + +#endif /* _MACHINE_SEGMENTS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/setjmp.h b/lib/libc/include/x86-openbsd-none/machine/setjmp.h new file mode 100644 index 000000000000..f53a7cc52544 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/setjmp.h @@ -0,0 +1,18 @@ +/* $OpenBSD: setjmp.h,v 1.4 2020/12/13 21:21:32 bluhm Exp $ */ +/* $NetBSD: setjmp.h,v 1.1 1994/12/20 10:36:43 cgd Exp $ */ + +/* + * machine/setjmp.h: machine dependent setjmp-related information. + */ + +#define _JB_EIP 0 +#define _JB_EBX 1 +#define _JB_ESP 2 +#define _JB_EBP 3 +#define _JB_ESI 4 +#define _JB_EDI 5 +#define _JB_SIGMASK 6 +#define _JB_SIGFLAG 7 +#define _JB_FCW 8 + +#define _JBLEN 10 /* size, in longs, of a jmp_buf */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/signal.h b/lib/libc/include/x86-openbsd-none/machine/signal.h new file mode 100644 index 000000000000..80c9b368f1c5 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/signal.h @@ -0,0 +1,88 @@ +/* $OpenBSD: signal.h,v 1.11 2016/05/10 18:39:45 deraadt Exp $ */ +/* $NetBSD: signal.h,v 1.6 1996/01/08 13:51:43 mycroft Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)signal.h 7.16 (Berkeley) 3/17/91 + */ + +#ifndef _MACHINE_SIGNAL_H_ +#define _MACHINE_SIGNAL_H_ + +#include + +typedef int sig_atomic_t; + +#ifdef _KERNEL +#include +#endif + +#if __BSD_VISIBLE || __XPG_VISIBLE >= 420 +/* + * Information pushed on stack when a signal is delivered. + * This is used by the kernel to restore state following + * execution of the signal handler. It is also made available + * to the handler to allow it to restore state properly if + * a non-standard exit is performed. + */ +struct sigcontext { + int sc_gs; + int sc_fs; + int sc_es; + int sc_ds; + int sc_edi; + int sc_esi; + int sc_ebp; + int sc_ebx; + int sc_edx; + int sc_ecx; + int sc_eax; + /* XXX */ + int sc_eip; + int sc_cs; + int sc_eflags; + int sc_esp; + int sc_ss; + + long sc_cookie; + int sc_mask; /* signal mask to restore */ + + int sc_trapno; /* XXX should be above */ + int sc_err; + + union savefpu *sc_fpstate; +}; + +#define sc_sp sc_esp +#define sc_fp sc_ebp +#define sc_pc sc_eip +#define sc_ps sc_eflags + +#endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ +#endif /* !_MACHINE_SIGNAL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/specialreg.h b/lib/libc/include/x86-openbsd-none/machine/specialreg.h new file mode 100644 index 000000000000..6024995d828a --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/specialreg.h @@ -0,0 +1,812 @@ +/* $OpenBSD: specialreg.h,v 1.85 2023/08/16 04:07:38 jsg Exp $ */ +/* $NetBSD: specialreg.h,v 1.7 1994/10/27 04:16:26 cgd Exp $ */ + +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)specialreg.h 7.1 (Berkeley) 5/9/91 + */ + +/* + * Bits in 386 special registers: + */ +#define CR0_PE 0x00000001 /* Protected mode Enable */ +#define CR0_MP 0x00000002 /* "Math" Present (NPX or NPX emulator) */ +#define CR0_EM 0x00000004 /* EMulate non-NPX coproc. (trap ESC only) */ +#define CR0_TS 0x00000008 /* Task Switched (if MP, trap ESC and WAIT) */ +#define CR0_ET 0x00000010 /* Extension Type (387 (if set) vs 287) */ +#define CR0_PG 0x80000000 /* PaGing enable */ + +/* + * Bits in 486 special registers: + */ +#define CR0_NE 0x00000020 /* Numeric Error enable (EX16 vs IRQ13) */ +#define CR0_WP 0x00010000 /* Write Protect (honor PG_RW in all modes) */ +#define CR0_AM 0x00040000 /* Alignment Mask (set to enable AC flag) */ +#define CR0_NW 0x20000000 /* Not Write-through */ +#define CR0_CD 0x40000000 /* Cache Disable */ + +/* + * bits in CR3 + */ +#define CR3_PWT (1ULL << 3) +#define CR3_PCD (1ULL << 4) + +/* + * bits in the pentiums %cr4 register: + */ + +#define CR4_VME 0x00000001 /* virtual 8086 mode extension enable */ +#define CR4_PVI 0x00000002 /* protected mode virtual interrupt enable */ +#define CR4_TSD 0x00000004 /* restrict RDTSC instruction to cpl 0 only */ +#define CR4_DE 0x00000008 /* debugging extension */ +#define CR4_PSE 0x00000010 /* large (4MB) page size enable */ +#define CR4_PAE 0x00000020 /* physical address extension enable */ +#define CR4_MCE 0x00000040 /* machine check enable */ +#define CR4_PGE 0x00000080 /* page global enable */ +#define CR4_PCE 0x00000100 /* enable RDPMC instruction for all cpls */ +#define CR4_OSFXSR 0x00000200 /* enable fxsave/fxrestor and SSE */ +#define CR4_OSXMMEXCPT 0x00000400 /* enable unmasked SSE exceptions */ +#define CR4_UMIP 0x00000800 /* user mode instruction prevention */ +#define CR4_VMXE 0x00002000 /* enable virtual machine operation */ +#define CR4_SMXE 0x00004000 /* enable safe mode operation */ +#define CR4_FSGSBASE 0x00010000 /* enable {RD,WR}{FS,GS}BASE ops */ +#define CR4_PCIDE 0x00020000 /* enable process-context IDs */ +#define CR4_OSXSAVE 0x00040000 /* enable XSAVE and extended states */ +#define CR4_SMEP 0x00100000 /* supervisor mode exec protection */ +#define CR4_SMAP 0x00200000 /* supervisor mode access prevention */ +#define CR4_PKE 0x00400000 /* protection key enable */ + +/* + * CPUID "features" bits (CPUID function 0x1): + * EDX bits, then ECX bits + */ + +#define CPUID_FPU 0x00000001 /* processor has an FPU? */ +#define CPUID_VME 0x00000002 /* has virtual mode (%cr4's VME/PVI) */ +#define CPUID_DE 0x00000004 /* has debugging extension */ +#define CPUID_PSE 0x00000008 /* has 4MB page size extension */ +#define CPUID_TSC 0x00000010 /* has time stamp counter */ +#define CPUID_MSR 0x00000020 /* has model specific registers */ +#define CPUID_PAE 0x00000040 /* has phys address extension */ +#define CPUID_MCE 0x00000080 /* has machine check exception */ +#define CPUID_CX8 0x00000100 /* has CMPXCHG8B instruction */ +#define CPUID_APIC 0x00000200 /* has enabled APIC */ +#define CPUID_SYS1 0x00000400 /* has SYSCALL/SYSRET inst. (Cyrix) */ +#define CPUID_SEP 0x00000800 /* has SYSCALL/SYSRET inst. (AMD/Intel) */ +#define CPUID_MTRR 0x00001000 /* has memory type range register */ +#define CPUID_PGE 0x00002000 /* has page global extension */ +#define CPUID_MCA 0x00004000 /* has machine check architecture */ +#define CPUID_CMOV 0x00008000 /* has CMOVcc instruction */ +#define CPUID_PAT 0x00010000 /* has page attribute table */ +#define CPUID_PSE36 0x00020000 /* has 36bit page size extension */ +#define CPUID_PSN 0x00040000 /* has processor serial number */ +#define CPUID_CFLUSH 0x00080000 /* CFLUSH insn supported */ +#define CPUID_B20 0x00100000 /* reserved */ +#define CPUID_DS 0x00200000 /* Debug Store */ +#define CPUID_ACPI 0x00400000 /* ACPI performance modulation regs */ +#define CPUID_MMX 0x00800000 /* has MMX instructions */ +#define CPUID_FXSR 0x01000000 /* has FXRSTOR instruction */ +#define CPUID_SSE 0x02000000 /* has streaming SIMD extensions */ +#define CPUID_SSE2 0x04000000 /* has streaming SIMD extensions #2 */ +#define CPUID_SS 0x08000000 /* self-snoop */ +#define CPUID_HTT 0x10000000 /* Hyper-Threading Technology */ +#define CPUID_TM 0x20000000 /* thermal monitor (TCC) */ +#define CPUID_B30 0x40000000 /* reserved */ +#define CPUID_PBE 0x80000000 /* Pending Break Enabled restarts clock */ + +#define CPUIDECX_SSE3 0x00000001 /* streaming SIMD extensions #3 */ +#define CPUIDECX_PCLMUL 0x00000002 /* Carryless Multiplication */ +#define CPUIDECX_DTES64 0x00000004 /* 64bit debug store */ +#define CPUIDECX_MWAIT 0x00000008 /* Monitor/Mwait */ +#define CPUIDECX_DSCPL 0x00000010 /* CPL Qualified Debug Store */ +#define CPUIDECX_VMX 0x00000020 /* Virtual Machine Extensions */ +#define CPUIDECX_SMX 0x00000040 /* Safer Mode Extensions */ +#define CPUIDECX_EST 0x00000080 /* enhanced SpeedStep */ +#define CPUIDECX_TM2 0x00000100 /* thermal monitor 2 */ +#define CPUIDECX_SSSE3 0x00000200 /* Supplemental Streaming SIMD Ext. 3 */ +#define CPUIDECX_CNXTID 0x00000400 /* Context ID */ +#define CPUIDECX_SDBG 0x00000800 /* Silicon debug capability */ +#define CPUIDECX_FMA3 0x00001000 /* Fused Multiply Add */ +#define CPUIDECX_CX16 0x00002000 /* has CMPXCHG16B instruction */ +#define CPUIDECX_XTPR 0x00004000 /* xTPR Update Control */ +#define CPUIDECX_PDCM 0x00008000 /* Perfmon and Debug Capability */ +#define CPUIDECX_PCID 0x00020000 /* Process-context ID Capability */ +#define CPUIDECX_DCA 0x00040000 /* Direct Cache Access */ +#define CPUIDECX_SSE41 0x00080000 /* Streaming SIMD Extensions 4.1 */ +#define CPUIDECX_SSE42 0x00100000 /* Streaming SIMD Extensions 4.2 */ +#define CPUIDECX_X2APIC 0x00200000 /* Extended xAPIC Support */ +#define CPUIDECX_MOVBE 0x00400000 /* MOVBE Instruction */ +#define CPUIDECX_POPCNT 0x00800000 /* POPCNT Instruction */ +#define CPUIDECX_DEADLINE 0x01000000 /* APIC one-shot via deadline */ +#define CPUIDECX_AES 0x02000000 /* AES Instruction */ +#define CPUIDECX_XSAVE 0x04000000 /* XSAVE/XSTOR States */ +#define CPUIDECX_OSXSAVE 0x08000000 /* OSXSAVE */ +#define CPUIDECX_AVX 0x10000000 /* Advanced Vector Extensions */ +#define CPUIDECX_F16C 0x20000000 /* 16bit fp conversion */ +#define CPUIDECX_RDRAND 0x40000000 /* RDRAND instruction */ +#define CPUIDECX_HV 0x80000000 /* Running on hypervisor */ + +/* + * "Structured Extended Feature Flags Parameters" (CPUID function 0x7, leaf 0) + * EBX bits + */ +#define SEFF0EBX_FSGSBASE 0x00000001 /* {RD,WR}[FG]SBASE instructions */ +#define SEFF0EBX_TSC_ADJUST 0x00000002 /* Has IA32_TSC_ADJUST MSR */ +#define SEFF0EBX_SGX 0x00000004 /* Software Guard Extensions */ +#define SEFF0EBX_BMI1 0x00000008 /* advanced bit manipulation */ +#define SEFF0EBX_HLE 0x00000010 /* Hardware Lock Elision */ +#define SEFF0EBX_AVX2 0x00000020 /* Advanced Vector Extensions 2 */ +#define SEFF0EBX_SMEP 0x00000080 /* Supervisor mode exec protection */ +#define SEFF0EBX_BMI2 0x00000100 /* advanced bit manipulation */ +#define SEFF0EBX_ERMS 0x00000200 /* Enhanced REP MOVSB/STOSB */ +#define SEFF0EBX_INVPCID 0x00000400 /* INVPCID instruction */ +#define SEFF0EBX_RTM 0x00000800 /* Restricted Transactional Memory */ +#define SEFF0EBX_PQM 0x00001000 /* Quality of Service Monitoring */ +#define SEFF0EBX_MPX 0x00004000 /* Memory Protection Extensions */ +#define SEFF0EBX_AVX512F 0x00010000 /* AVX-512 foundation inst */ +#define SEFF0EBX_AVX512DQ 0x00020000 /* AVX-512 double/quadword */ +#define SEFF0EBX_RDSEED 0x00040000 /* RDSEED instruction */ +#define SEFF0EBX_ADX 0x00080000 /* ADCX/ADOX instructions */ +#define SEFF0EBX_SMAP 0x00100000 /* Supervisor mode access prevent */ +#define SEFF0EBX_AVX512IFMA 0x00200000 /* AVX-512 integer mult-add */ +#define SEFF0EBX_PCOMMIT 0x00400000 /* Persistent commit inst */ +#define SEFF0EBX_CLFLUSHOPT 0x00800000 /* cache line flush */ +#define SEFF0EBX_CLWB 0x01000000 /* cache line write back */ +#define SEFF0EBX_PT 0x02000000 /* Processor Trace */ +#define SEFF0EBX_AVX512PF 0x04000000 /* AVX-512 prefetch */ +#define SEFF0EBX_AVX512ER 0x08000000 /* AVX-512 exp/reciprocal */ +#define SEFF0EBX_AVX512CD 0x10000000 /* AVX-512 conflict detection */ +#define SEFF0EBX_SHA 0x20000000 /* SHA Extensions */ +#define SEFF0EBX_AVX512BW 0x40000000 /* AVX-512 byte/word inst */ +#define SEFF0EBX_AVX512VL 0x80000000 /* AVX-512 vector len inst */ +/* SEFF ECX bits */ +#define SEFF0ECX_PREFETCHWT1 0x00000001 /* PREFETCHWT1 instruction */ +#define SEFF0ECX_AVX512VBMI 0x00000002 /* AVX-512 vector bit inst */ +#define SEFF0ECX_UMIP 0x00000004 /* UMIP support */ +#define SEFF0ECX_PKU 0x00000008 /* Page prot keys for user mode */ +#define SEFF0ECX_WAITPKG 0x00000020 /* UMONITOR/UMWAIT/TPAUSE insns */ +/* SEFF EDX bits */ +#define SEFF0EDX_AVX512_4FNNIW 0x00000004 /* AVX-512 neural network insns */ +#define SEFF0EDX_AVX512_4FMAPS 0x00000008 /* AVX-512 mult accum single prec */ +#define SEFF0EDX_SRBDS_CTRL 0x00000200 /* MCU_OPT_CTRL MSR */ +#define SEFF0EDX_MD_CLEAR 0x00000400 /* Microarch Data Clear */ +#define SEFF0EDX_TSXFA 0x00002000 /* TSX Forced Abort */ +#define SEFF0EDX_IBRS 0x04000000 /* IBRS / IBPB Speculation Control */ +#define SEFF0EDX_STIBP 0x08000000 /* STIBP Speculation Control */ +#define SEFF0EDX_L1DF 0x10000000 /* L1D_FLUSH */ +#define SEFF0EDX_ARCH_CAP 0x20000000 /* Has IA32_ARCH_CAPABILITIES MSR */ +#define SEFF0EDX_SSBD 0x80000000 /* Spec Store Bypass Disable */ + +/* + * Thermal and Power Management (CPUID function 0x6) EAX bits + */ +#define TPM_SENSOR 0x00000001 /* Digital temp sensor */ +#define TPM_ARAT 0x00000004 /* APIC Timer Always Running */ + +/* + * "Architectural Performance Monitoring" bits (CPUID function 0x0a): + * EAX bits + */ + +#define CPUIDEAX_VERID 0x000000ff +#define CPUIDEAX_NUM_GC(cpuid) (((cpuid) >> 8) & 0x000000ff) +#define CPUIDEAX_BIT_GC(cpuid) (((cpuid) >> 16) & 0x000000ff) +#define CPUIDEAX_LEN_EBX(cpuid) (((cpuid) >> 24) & 0x000000ff) + +#define CPUIDEBX_EVT_CORE (1 << 0) /* Core cycle */ +#define CPUIDEBX_EVT_INST (1 << 1) /* Instruction retired */ +#define CPUIDEBX_EVT_REFR (1 << 2) /* Reference cycles */ +#define CPUIDEBX_EVT_CACHE_REF (1 << 3) /* Last-level cache ref. */ +#define CPUIDEBX_EVT_CACHE_MIS (1 << 4) /* Last-level cache miss. */ +#define CPUIDEBX_EVT_BRANCH_INST (1 << 5) /* Branch instruction ret. */ +#define CPUIDEBX_EVT_BRANCH_MISP (1 << 6) /* Branch mispredict ret. */ + +#define CPUIDEDX_NUM_FC(cpuid) (((cpuid) >> 0) & 0x0000001f) +#define CPUIDEDX_BIT_FC(cpuid) (((cpuid) >> 5) & 0x000000ff) + +/* + * CPUID "extended features" bits (CPUID function 0x80000001): + * EDX bits, then ECX bits + */ + +#define CPUID_MPC 0x00080000 /* Multiprocessing Capable */ +#define CPUID_NXE 0x00100000 /* No-Execute Extension */ +#define CPUID_MMXX 0x00400000 /* AMD MMX Extensions */ +#define CPUID_FFXSR 0x02000000 /* fast FP/MMX save/restore */ +#define CPUID_PAGE1GB 0x04000000 /* 1-GByte pages */ +#define CPUID_RDTSCP 0x08000000 /* RDTSCP / IA32_TSC_AUX available */ +#define CPUID_LONG 0x20000000 /* long mode */ +#define CPUID_3DNOW2 0x40000000 /* 3DNow! Instruction Extension */ +#define CPUID_3DNOW 0x80000000 /* 3DNow! Instructions */ + +#define CPUIDECX_LAHF 0x00000001 /* LAHF and SAHF instructions */ +#define CPUIDECX_CMPLEG 0x00000002 /* Core MP legacy mode */ +#define CPUIDECX_SVM 0x00000004 /* Secure Virtual Machine */ +#define CPUIDECX_EAPICSP 0x00000008 /* Extended APIC space */ +#define CPUIDECX_AMCR8 0x00000010 /* LOCK MOV CR0 means MOV CR8 */ +#define CPUIDECX_ABM 0x00000020 /* LZCNT instruction */ +#define CPUIDECX_SSE4A 0x00000040 /* SSE4-A instruction set */ +#define CPUIDECX_MASSE 0x00000080 /* Misaligned SSE mode */ +#define CPUIDECX_3DNOWP 0x00000100 /* 3DNowPrefetch */ +#define CPUIDECX_OSVW 0x00000200 /* OS visible workaround */ +#define CPUIDECX_IBS 0x00000400 /* Instruction based sampling */ +#define CPUIDECX_XOP 0x00000800 /* Extended operating support */ +#define CPUIDECX_SKINIT 0x00001000 /* SKINIT and STGI are supported */ +#define CPUIDECX_WDT 0x00002000 /* Watchdog timer */ +/* Reserved 0x00004000 */ +#define CPUIDECX_LWP 0x00008000 /* Lightweight profiling support */ +#define CPUIDECX_FMA4 0x00010000 /* 4-operand FMA instructions */ +#define CPUIDECX_TCE 0x00020000 /* Translation Cache Extension */ +/* Reserved 0x00040000 */ +#define CPUIDECX_NODEID 0x00080000 /* Support for MSRC001C */ +/* Reserved 0x00100000 */ +#define CPUIDECX_TBM 0x00200000 /* Trailing bit manipulation instruction */ +#define CPUIDECX_TOPEXT 0x00400000 /* Topology extensions support */ +#define CPUIDECX_CPCTR 0x00800000 /* core performance counter ext */ +#define CPUIDECX_DBKP 0x04000000 /* DataBreakpointExtension */ +#define CPUIDECX_PERFTSC 0x08000000 /* performance time-stamp counter */ +#define CPUIDECX_PCTRL3 0x10000000 /* L3 performance counter ext */ +#define CPUIDECX_MWAITX 0x20000000 /* MWAITX/MONITORX */ + +/* + * "Advanced Power Management Information" bits (CPUID function 0x80000007): + * EDX bits. + */ + +#define CPUIDEDX_ITSC (1 << 8) /* Invariant TSC */ + +/* + * AMD CPUID function 0x80000008 EBX bits + */ +#define CPUIDEBX_IBPB (1ULL << 12) /* Speculation Control IBPB */ +#define CPUIDEBX_IBRS (1ULL << 14) /* Speculation Control IBRS */ +#define CPUIDEBX_STIBP (1ULL << 15) /* Speculation Control STIBP */ +#define CPUIDEBX_IBRS_ALWAYSON (1ULL << 16) /* IBRS always on mode */ +#define CPUIDEBX_STIBP_ALWAYSON (1ULL << 17) /* STIBP always on mode */ +#define CPUIDEBX_IBRS_PREF (1ULL << 18) /* IBRS preferred */ +#define CPUIDEBX_SSBD (1ULL << 24) /* Speculation Control SSBD */ +#define CPUIDEBX_VIRT_SSBD (1ULL << 25) /* Virt Spec Control SSBD */ +#define CPUIDEBX_SSBD_NOTREQ (1ULL << 26) /* SSBD not required */ + +#define CPUID2FAMILY(cpuid) (((cpuid) >> 8) & 15) +#define CPUID2MODEL(cpuid) (((cpuid) >> 4) & 15) +#define CPUID2STEPPING(cpuid) ((cpuid) & 15) + +#define CPUID(code, eax, ebx, ecx, edx) \ + __asm volatile("cpuid" \ + : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \ + : "a" (code)) +#define CPUID_LEAF(code, leaf, eax, ebx, ecx, edx) \ + __asm volatile("cpuid" \ + : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \ + : "a" (code), "c" (leaf)) + + +/* + * Model-specific registers for the i386 family + */ +#define MSR_P5_MC_ADDR 0x000 +#define MSR_P5_MC_TYPE 0x001 +#define MSR_TSC 0x010 +#define P5MSR_CTRSEL 0x011 /* P5 only (trap on P6) */ +#define P5MSR_CTR0 0x012 /* P5 only (trap on P6) */ +#define P5MSR_CTR1 0x013 /* P5 only (trap on P6) */ +#define MSR_PLATFORM_ID 0x017 /* Platform ID for microcode */ +#define MSR_APICBASE 0x01b +#define APICBASE_BSP 0x100 +#define APICBASE_ENABLE_X2APIC 0x400 +#define APICBASE_GLOBAL_ENABLE 0x800 +#define MSR_EBL_CR_POWERON 0x02a +#define MSR_EBC_FREQUENCY_ID 0x02c /* Pentium 4 only */ +#define MSR_TEST_CTL 0x033 +#define MSR_IA32_FEATURE_CONTROL 0x03a +#define MSR_SPEC_CTRL 0x048 /* Speculation Control IBRS / STIBP */ +#define SPEC_CTRL_IBRS (1ULL << 0) +#define SPEC_CTRL_STIBP (1ULL << 1) +#define SPEC_CTRL_SSBD (1ULL << 2) +#define MSR_PRED_CMD 0x049 /* Speculation Control IBPB */ +#define PRED_CMD_IBPB (1ULL << 0) +#define MSR_BIOS_UPDT_TRIG 0x079 +#define MSR_BBL_CR_D0 0x088 /* PII+ only */ +#define MSR_BBL_CR_D1 0x089 /* PII+ only */ +#define MSR_BBL_CR_D2 0x08a /* PII+ only */ +#define MSR_BIOS_SIGN 0x08b +#define MSR_PERFCTR0 0x0c1 +#define MSR_PERFCTR1 0x0c2 +#define P6MSR_CTR0 0x0c1 +#define P6MSR_CTR1 0x0c2 +#define MSR_FSB_FREQ 0x0cd /* Core Duo/Solo only */ +#define MSR_MTRRcap 0x0fe +#define MTRRcap_FIXED 0x100 /* bit 8 - fixed MTRRs supported */ +#define MTRRcap_WC 0x400 /* bit 10 - WC type supported */ +#define MTRRcap_SMRR 0x800 /* bit 11 - SMM range reg supported */ +#define MSR_ARCH_CAPABILITIES 0x10a +#define ARCH_CAP_RDCL_NO (1 << 0) /* Meltdown safe */ +#define ARCH_CAP_IBRS_ALL (1 << 1) /* enhanced IBRS */ +#define ARCH_CAP_RSBA (1 << 2) /* RSB Alternate */ +#define ARCH_CAP_SKIP_L1DFL_VMENTRY (1 << 3) +#define ARCH_CAP_SSB_NO (1 << 4) /* Spec St Byp safe */ +#define ARCH_CAP_MDS_NO (1 << 5) /* microarch data-sampling */ +#define ARCH_CAP_IF_PSCHANGE_MC_NO (1 << 6) /* PS MCE safe */ +#define ARCH_CAP_TSX_CTRL (1 << 7) /* has TSX_CTRL MSR */ +#define ARCH_CAP_TAA_NO (1 << 8) /* TSX AA safe */ +#define ARCH_CAP_MCU_CONTROL (1 << 9) /* has MCU_CTRL MSR */ +#define ARCH_CAP_MISC_PACKAGE_CTLS (1 << 10) /* has MISC_PKG_CTLS MSR */ +#define ARCH_CAP_ENERGY_FILTERING_CTL (1 << 11) /* r/w energy fltring bit */ +#define ARCH_CAP_DOITM (1 << 12) /* Data oprnd indpdnt tmng */ +#define ARCH_CAP_SBDR_SSDP_NO (1 << 13) /* SBDR/SSDP safe */ +#define ARCH_CAP_FBSDP_NO (1 << 14) /* FBSDP safe */ +#define ARCH_CAP_PSDP_NO (1 << 15) /* PSDP safe */ +#define ARCH_CAP_FB_CLEAR (1 << 17) /* MD_CLEAR covers FB */ +#define ARCH_CAP_FB_CLEAR_CTRL (1 << 18) +#define ARCH_CAP_RRSBA (1 << 19) /* has RRSBA if not dis */ +#define ARCH_CAP_BHI_NO (1 << 20) /* BHI safe */ +#define ARCH_CAP_XAPIC_DISABLE_STATUS (1 << 21) /* can disable xAPIC */ +#define ARCH_CAP_OVERCLOCKING_STATUS (1 << 23) /* has OVRCLCKNG_STAT MSR */ +#define ARCH_CAP_PBRSB_NO (1 << 24) /* PBSR safe */ +#define ARCH_CAP_GDS_CTRL (1 << 25) /* has GDS_MITG_DIS/LOCK */ +#define ARCH_CAP_GDS_NO (1 << 26) /* GDS safe */ +#define MSR_FLUSH_CMD 0x10b +#define FLUSH_CMD_L1D_FLUSH (1ULL << 0) +#define MSR_BBL_CR_ADDR 0x116 /* PII+ only */ +#define MSR_BBL_CR_DECC 0x118 /* PII+ only */ +#define MSR_BBL_CR_CTL 0x119 /* PII+ only */ +#define MSR_BBL_CR_TRIG 0x11a /* PII+ only */ +#define MSR_BBL_CR_BUSY 0x11b /* PII+ only */ +#define MSR_BBL_CR_CTR3 0x11e /* PII+ only */ +#define MSR_TSX_CTRL 0x122 +#define TSX_CTRL_RTM_DISABLE (1ULL << 0) +#define TSX_CTRL_TSX_CPUID_CLEAR (1ULL << 1) +#define MSR_MCU_OPT_CTRL 0x123 +#define RNGDS_MITG_DIS (1ULL << 0) +#define MSR_SYSENTER_CS 0x174 +#define MSR_SYSENTER_ESP 0x175 +#define MSR_SYSENTER_EIP 0x176 +#define MSR_MCG_CAP 0x179 +#define MSR_MCG_STATUS 0x17a +#define MSR_MCG_CTL 0x17b +#define P6MSR_CTRSEL0 0x186 +#define P6MSR_CTRSEL1 0x187 +#define MSR_PERF_STATUS 0x198 /* Pentium M */ +#define MSR_PERF_CTL 0x199 /* Pentium M */ +#define PERF_CTL_TURBO 0x100000000ULL /* bit 32 - turbo mode */ +#define MSR_THERM_CONTROL 0x19a +#define MSR_THERM_INTERRUPT 0x19b +#define MSR_THERM_STATUS 0x19c +#define MSR_THERM_STATUS_VALID_BIT 0x80000000 +#define MSR_THERM_STATUS_TEMP(msr) ((msr >> 16) & 0x7f) +#define MSR_THERM2_CTL 0x19d /* Pentium M */ +#define MSR_MISC_ENABLE 0x1a0 +/* + * MSR_MISC_ENABLE (0x1a0) + * + * Enable Fast Strings: enables fast REP MOVS/REP STORS (R/W) + * Enable TCC: Enable automatic thermal control circuit (R/W) + * Performance monitoring available: 1 if enabled (R/O) + * Branch trace storage unavailable: 1 if unsupported (R/O) + * Processor event based sampling unavailable: 1 if unsupported (R/O) + * Enhanced Intel SpeedStep technology enable: 1 to enable (R/W) + * Enable monitor FSM: 1 to enable MONITOR/MWAIT (R/W) + * Limit CPUID maxval: 1 to limit CPUID leaf nodes to 0x2 and lower (R/W) + * Enable xTPR message disable: 1 to disable xTPR messages + * XD bit disable: 1 to disable NX capability (bit 34, or bit 2 of %edx/%rdx) + */ +#define MISC_ENABLE_FAST_STRINGS (1 << 0) +#define MISC_ENABLE_TCC (1 << 3) +#define MISC_ENABLE_PERF_MON_AVAILABLE (1 << 7) +#define MISC_ENABLE_BTS_UNAVAILABLE (1 << 11) +#define MISC_ENABLE_PEBS_UNAVAILABLE (1 << 12) +#define MISC_ENABLE_EIST_ENABLED (1 << 16) +#define MISC_ENABLE_ENABLE_MONITOR_FSM (1 << 18) +#define MISC_ENABLE_LIMIT_CPUID_MAXVAL (1 << 22) +#define MISC_ENABLE_xTPR_MESSAGE_DISABLE (1 << 23) +#define MISC_ENABLE_XD_BIT_DISABLE (1 << 2) +/* + * for Core i Series and newer Xeons, see + * http://www.intel.com/content/dam/www/public/us/en/ + * documents/white-papers/cpu-monitoring-dts-peci-paper.pdf + */ +#define MSR_TEMPERATURE_TARGET 0x1a2 /* Core i Series, Newer Xeons */ +#define MSR_TEMPERATURE_TARGET_TJMAX(r) (((r) >> 16) & 0xff) +/* + * not documented anywhere, see intelcore_update_sensor() + * only available Core Duo and Core Solo Processors + */ +#define MSR_TEMPERATURE_TARGET_UNDOCUMENTED 0x0ee +#define MSR_TEMPERATURE_TARGET_LOW_BIT_UNDOCUMENTED 0x40000000 +#define MSR_DEBUGCTLMSR 0x1d9 +#define MSR_LASTBRANCHFROMIP 0x1db +#define MSR_LASTBRANCHTOIP 0x1dc +#define MSR_LASTINTFROMIP 0x1dd +#define MSR_LASTINTTOIP 0x1de +#define MSR_ROB_CR_BKUPTMPDR6 0x1e0 +#define MSR_MTRRvarBase 0x200 +#define MSR_MTRRfix64K_00000 0x250 +#define MSR_MTRRfix16K_80000 0x258 +#define MSR_MTRRfix4K_C0000 0x268 +#define MSR_CR_PAT 0x277 +#define MSR_MTRRdefType 0x2ff +#define MTRRdefType_FIXED_ENABLE 0x400 /* bit 10 - fixed MTRR enabled */ +#define MTRRdefType_ENABLE 0x800 /* bit 11 - MTRRs enabled */ +#define MSR_PERF_FIXED_CTR1 0x30a /* CPU_CLK_Unhalted.Core */ +#define MSR_PERF_FIXED_CTR2 0x30b /* CPU_CLK.Unhalted.Ref */ +#define MSR_PERF_FIXED_CTR_CTRL 0x38d +#define MSR_PERF_FIXED_CTR_FC_DIS 0x0 /* disable counter */ +#define MSR_PERF_FIXED_CTR_FC_1 0x1 /* count ring 1 */ +#define MSR_PERF_FIXED_CTR_FC_123 0x2 /* count rings 1,2,3 */ +#define MSR_PERF_FIXED_CTR_FC_ANY 0x3 /* count everything */ +#define MSR_PERF_FIXED_CTR_FC_MASK 0x3 +#define MSR_PERF_FIXED_CTR_FC(_i, _v) ((_v) << (4 * (_i))) +#define MSR_PERF_FIXED_CTR_ANYTHR(_i) (0x4 << (4 * (_i))) +#define MSR_PERF_FIXED_CTR_INT(_i) (0x8 << (4 * (_i))) +#define MSR_PERF_GLOBAL_CTRL 0x38f +#define MSR_PERF_GLOBAL_CTR1_EN (1ULL << 33) +#define MSR_PERF_GLOBAL_CTR2_EN (1ULL << 34) +#define MSR_MC0_CTL 0x400 +#define MSR_MC0_STATUS 0x401 +#define MSR_MC0_ADDR 0x402 +#define MSR_MC0_MISC 0x403 +#define MSR_MC1_CTL 0x404 +#define MSR_MC1_STATUS 0x405 +#define MSR_MC1_ADDR 0x406 +#define MSR_MC1_MISC 0x407 +#define MSR_MC2_CTL 0x408 +#define MSR_MC2_STATUS 0x409 +#define MSR_MC2_ADDR 0x40a +#define MSR_MC2_MISC 0x40b +#define MSR_MC4_CTL 0x40c +#define MSR_MC4_STATUS 0x40d +#define MSR_MC4_ADDR 0x40e +#define MSR_MC4_MISC 0x40f +#define MSR_MC3_CTL 0x410 +#define MSR_MC3_STATUS 0x411 +#define MSR_MC3_ADDR 0x412 +#define MSR_MC3_MISC 0x413 + +/* VIA MSRs */ +#define MSR_CENT_TMTEMPERATURE 0x1423 /* Thermal monitor temperature */ +#define MSR_C7M_TMTEMPERATURE 0x1169 + +/* AMD MSRs */ +#define MSR_K6_EPMR 0xc0000086 +#define MSR_K7_EVNTSEL0 0xc0010000 +#define MSR_K7_EVNTSEL1 0xc0010001 +#define MSR_K7_EVNTSEL2 0xc0010002 +#define MSR_K7_EVNTSEL3 0xc0010003 +#define MSR_K7_PERFCTR0 0xc0010004 +#define MSR_K7_PERFCTR1 0xc0010005 +#define MSR_K7_PERFCTR2 0xc0010006 +#define MSR_K7_PERFCTR3 0xc0010007 + +/* + * AMD K8 (Opteron) MSRs. + */ +#define MSR_PATCH_LEVEL 0x0000008b +#define MSR_SYSCFG 0xc0000010 + +#define MSR_EFER 0xc0000080 /* Extended feature enable */ +#define EFER_SCE 0x00000001 /* SYSCALL extension */ +#define EFER_LME 0x00000100 /* Long Mode Active */ +#define EFER_LMA 0x00000400 /* Long Mode Enabled */ +#define EFER_NXE 0x00000800 /* No-Execute Enabled */ +#define EFER_SVME 0x00001000 /* SVM Enabled */ + +#define MSR_STAR 0xc0000081 /* 32 bit syscall gate addr */ +#define MSR_LSTAR 0xc0000082 /* 64 bit syscall gate addr */ +#define MSR_CSTAR 0xc0000083 /* compat syscall gate addr */ +#define MSR_SFMASK 0xc0000084 /* flags to clear on syscall */ + +#define MSR_FSBASE 0xc0000100 /* 64bit offset for fs: */ +#define MSR_GSBASE 0xc0000101 /* 64bit offset for gs: */ +#define MSR_KERNELGSBASE 0xc0000102 /* storage for swapgs ins */ +#define MSR_PATCH_LOADER 0xc0010020 +#define MSR_INT_PEN_MSG 0xc0010055 /* Interrupt pending message */ + +#define MSR_DE_CFG 0xc0011029 /* Decode Configuration */ +#define DE_CFG_721 0x00000001 /* errata 721 */ +#define DE_CFG_SERIALIZE_LFENCE (1 << 1) /* Enable serializing lfence */ +#define DE_CFG_SERIALIZE_9 (1 << 9) /* Zenbleed chickenbit */ + +#define IPM_C1E_CMP_HLT 0x10000000 +#define IPM_SMI_CMP_HLT 0x08000000 + +/* + * These require a 'passcode' for access. See cpufunc.h. + */ +#define MSR_HWCR 0xc0010015 +#define HWCR_FFDIS 0x00000040 + +#define MSR_NB_CFG 0xc001001f +#define NB_CFG_DISIOREQLOCK 0x0000000000000004ULL +#define NB_CFG_DISDATMSK 0x0000001000000000ULL + +#define MSR_LS_CFG 0xc0011020 +#define LS_CFG_DIS_LS2_SQUISH 0x02000000 + +#define MSR_IC_CFG 0xc0011021 +#define IC_CFG_DIS_SEQ_PREFETCH 0x00000800 + +#define MSR_DC_CFG 0xc0011022 +#define DC_CFG_DIS_CNV_WC_SSO 0x00000004 +#define DC_CFG_DIS_SMC_CHK_BUF 0x00000400 + +#define MSR_BU_CFG 0xc0011023 +#define BU_CFG_THRL2IDXCMPDIS 0x0000080000000000ULL +#define BU_CFG_WBPFSMCCHKDIS 0x0000200000000000ULL +#define BU_CFG_WBENHWSBDIS 0x0001000000000000ULL + +/* + * Constants related to MTRRs + */ +#define MTRR_N64K 8 /* numbers of fixed-size entries */ +#define MTRR_N16K 16 +#define MTRR_N4K 64 + +/* + * the following four 3-byte registers control the non-cacheable regions. + * These registers must be written as three separate bytes. + * + * NCRx+0: A31-A24 of starting address + * NCRx+1: A23-A16 of starting address + * NCRx+2: A15-A12 of starting address | NCR_SIZE_xx. + * + * The non-cacheable region's starting address must be aligned to the + * size indicated by the NCR_SIZE_xx field. + */ +#define NCR1 0xc4 +#define NCR2 0xc7 +#define NCR3 0xca +#define NCR4 0xcd + +#define NCR_SIZE_0K 0 +#define NCR_SIZE_4K 1 +#define NCR_SIZE_8K 2 +#define NCR_SIZE_16K 3 +#define NCR_SIZE_32K 4 +#define NCR_SIZE_64K 5 +#define NCR_SIZE_128K 6 +#define NCR_SIZE_256K 7 +#define NCR_SIZE_512K 8 +#define NCR_SIZE_1M 9 +#define NCR_SIZE_2M 10 +#define NCR_SIZE_4M 11 +#define NCR_SIZE_8M 12 +#define NCR_SIZE_16M 13 +#define NCR_SIZE_32M 14 +#define NCR_SIZE_4G 15 + +/* + * Performance monitor events. + * + * Note that 586-class and 686-class CPUs have different performance + * monitors available, and they are accessed differently: + * + * 686-class: `rdpmc' instruction + * 586-class: `rdmsr' instruction, CESR MSR + * + * The descriptions of these events are too lengthy to include here. + * See Appendix A of "Intel Architecture Software Developer's + * Manual, Volume 3: System Programming" for more information. + */ + +/* + * 586-class CESR MSR format. Lower 16 bits is CTR0, upper 16 bits + * is CTR1. + */ + +#define PMC5_CESR_EVENT 0x003f +#define PMC5_CESR_OS 0x0040 +#define PMC5_CESR_USR 0x0080 +#define PMC5_CESR_E 0x0100 +#define PMC5_CESR_P 0x0200 + +/* + * 686-class Event Selector MSR format. + */ + +#define PMC6_EVTSEL_EVENT 0x000000ff +#define PMC6_EVTSEL_UNIT 0x0000ff00 +#define PMC6_EVTSEL_UNIT_SHIFT 8 +#define PMC6_EVTSEL_USR (1 << 16) +#define PMC6_EVTSEL_OS (1 << 17) +#define PMC6_EVTSEL_E (1 << 18) +#define PMC6_EVTSEL_PC (1 << 19) +#define PMC6_EVTSEL_INT (1 << 20) +#define PMC6_EVTSEL_EN (1 << 22) /* PerfEvtSel0 only */ +#define PMC6_EVTSEL_INV (1 << 23) +#define PMC6_EVTSEL_COUNTER_MASK 0xff000000 +#define PMC6_EVTSEL_COUNTER_MASK_SHIFT 24 + +/* Data Cache Unit */ +#define PMC6_DATA_MEM_REFS 0x43 +#define PMC6_DCU_LINES_IN 0x45 +#define PMC6_DCU_M_LINES_IN 0x46 +#define PMC6_DCU_M_LINES_OUT 0x47 +#define PMC6_DCU_MISS_OUTSTANDING 0x48 + +/* Instruction Fetch Unit */ +#define PMC6_IFU_IFETCH 0x80 +#define PMC6_IFU_IFETCH_MISS 0x81 +#define PMC6_ITLB_MISS 0x85 +#define PMC6_IFU_MEM_STALL 0x86 +#define PMC6_ILD_STALL 0x87 + +/* L2 Cache */ +#define PMC6_L2_IFETCH 0x28 +#define PMC6_L2_LD 0x29 +#define PMC6_L2_ST 0x2a +#define PMC6_L2_LINES_IN 0x24 +#define PMC6_L2_LINES_OUT 0x26 +#define PMC6_L2_M_LINES_INM 0x25 +#define PMC6_L2_M_LINES_OUTM 0x27 +#define PMC6_L2_RQSTS 0x2e +#define PMC6_L2_ADS 0x21 +#define PMC6_L2_DBUS_BUSY 0x22 +#define PMC6_L2_DBUS_BUSY_RD 0x23 + +/* External Bus Logic */ +#define PMC6_BUS_DRDY_CLOCKS 0x62 +#define PMC6_BUS_LOCK_CLOCKS 0x63 +#define PMC6_BUS_REQ_OUTSTANDING 0x60 +#define PMC6_BUS_TRAN_BRD 0x65 +#define PMC6_BUS_TRAN_RFO 0x66 +#define PMC6_BUS_TRANS_WB 0x67 +#define PMC6_BUS_TRAN_IFETCH 0x68 +#define PMC6_BUS_TRAN_INVAL 0x69 +#define PMC6_BUS_TRAN_PWR 0x6a +#define PMC6_BUS_TRANS_P 0x6b +#define PMC6_BUS_TRANS_IO 0x6c +#define PMC6_BUS_TRAN_DEF 0x6d +#define PMC6_BUS_TRAN_BURST 0x6e +#define PMC6_BUS_TRAN_ANY 0x70 +#define PMC6_BUS_TRAN_MEM 0x6f +#define PMC6_BUS_DATA_RCV 0x64 +#define PMC6_BUS_BNR_DRV 0x61 +#define PMC6_BUS_HIT_DRV 0x7a +#define PMC6_BUS_HITM_DRDV 0x7b +#define PMC6_BUS_SNOOP_STALL 0x7e + +/* Floating Point Unit */ +#define PMC6_FLOPS 0xc1 +#define PMC6_FP_COMP_OPS_EXE 0x10 +#define PMC6_FP_ASSIST 0x11 +#define PMC6_MUL 0x12 +#define PMC6_DIV 0x12 +#define PMC6_CYCLES_DIV_BUSY 0x14 + +/* Memory Ordering */ +#define PMC6_LD_BLOCKS 0x03 +#define PMC6_SB_DRAINS 0x04 +#define PMC6_MISALIGN_MEM_REF 0x05 +#define PMC6_EMON_KNI_PREF_DISPATCHED 0x07 /* P-III only */ +#define PMC6_EMON_KNI_PREF_MISS 0x4b /* P-III only */ + +/* Instruction Decoding and Retirement */ +#define PMC6_INST_RETIRED 0xc0 +#define PMC6_UOPS_RETIRED 0xc2 +#define PMC6_INST_DECODED 0xd0 +#define PMC6_EMON_KNI_INST_RETIRED 0xd8 +#define PMC6_EMON_KNI_COMP_INST_RET 0xd9 + +/* Interrupts */ +#define PMC6_HW_INT_RX 0xc8 +#define PMC6_CYCLES_INT_MASKED 0xc6 +#define PMC6_CYCLES_INT_PENDING_AND_MASKED 0xc7 + +/* Branches */ +#define PMC6_BR_INST_RETIRED 0xc4 +#define PMC6_BR_MISS_PRED_RETIRED 0xc5 +#define PMC6_BR_TAKEN_RETIRED 0xc9 +#define PMC6_BR_MISS_PRED_TAKEN_RET 0xca +#define PMC6_BR_INST_DECODED 0xe0 +#define PMC6_BTB_MISSES 0xe2 +#define PMC6_BR_BOGUS 0xe4 +#define PMC6_BACLEARS 0xe6 + +/* Stalls */ +#define PMC6_RESOURCE_STALLS 0xa2 +#define PMC6_PARTIAL_RAT_STALLS 0xd2 + +/* Segment Register Loads */ +#define PMC6_SEGMENT_REG_LOADS 0x06 + +/* Clocks */ +#define PMC6_CPU_CLK_UNHALTED 0x79 + +/* MMX Unit */ +#define PMC6_MMX_INSTR_EXEC 0xb0 /* Celeron, P-II, P-IIX only */ +#define PMC6_MMX_SAT_INSTR_EXEC 0xb1 /* P-II and P-III only */ +#define PMC6_MMX_UOPS_EXEC 0xb2 /* P-II and P-III only */ +#define PMC6_MMX_INSTR_TYPE_EXEC 0xb3 /* P-II and P-III only */ +#define PMC6_FP_MMX_TRANS 0xcc /* P-II and P-III only */ +#define PMC6_MMX_ASSIST 0xcd /* P-II and P-III only */ +#define PMC6_MMX_INSTR_RET 0xc3 /* P-II only */ + +/* Segment Register Renaming */ +#define PMC6_SEG_RENAME_STALLS 0xd4 /* P-II and P-III only */ +#define PMC6_SEG_REG_RENAMES 0xd5 /* P-II and P-III only */ +#define PMC6_RET_SEG_RENAMES 0xd6 /* P-II and P-III only */ + +/* VIA C3 crypto featureset: for i386_has_xcrypt */ +#define C3_HAS_AES 1 /* cpu has AES */ +#define C3_HAS_SHA 2 /* cpu has SHA1 & SHA256 */ +#define C3_HAS_MM 4 /* cpu has RSA instructions */ +#define C3_HAS_AESCTR 8 /* cpu has AES-CTR instructions */ + +/* Centaur Extended Feature flags */ +#define C3_CPUID_HAS_RNG 0x000004 +#define C3_CPUID_DO_RNG 0x000008 +#define C3_CPUID_HAS_ACE 0x000040 +#define C3_CPUID_DO_ACE 0x000080 +#define C3_CPUID_HAS_ACE2 0x000100 +#define C3_CPUID_DO_ACE2 0x000200 +#define C3_CPUID_HAS_PHE 0x000400 +#define C3_CPUID_DO_PHE 0x000800 +#define C3_CPUID_HAS_PMM 0x001000 +#define C3_CPUID_DO_PMM 0x002000 + +/* VIA C3 xcrypt-* instruction context control options */ +#define C3_CRYPT_CWLO_ROUND_M 0x0000000f +#define C3_CRYPT_CWLO_ALG_M 0x00000070 +#define C3_CRYPT_CWLO_ALG_AES 0x00000000 +#define C3_CRYPT_CWLO_KEYGEN_M 0x00000080 +#define C3_CRYPT_CWLO_KEYGEN_HW 0x00000000 +#define C3_CRYPT_CWLO_KEYGEN_SW 0x00000080 +#define C3_CRYPT_CWLO_NORMAL 0x00000000 +#define C3_CRYPT_CWLO_INTERMEDIATE 0x00000100 +#define C3_CRYPT_CWLO_ENCRYPT 0x00000000 +#define C3_CRYPT_CWLO_DECRYPT 0x00000200 +#define C3_CRYPT_CWLO_KEY128 0x0000000a /* 128bit, 10 rds */ +#define C3_CRYPT_CWLO_KEY192 0x0000040c /* 192bit, 12 rds */ +#define C3_CRYPT_CWLO_KEY256 0x0000080e /* 256bit, 15 rds */ + +/* Intel Silicon Debug */ +#define IA32_DEBUG_INTERFACE 0xc80 +#define IA32_DEBUG_INTERFACE_ENABLE 0x00000001 +#define IA32_DEBUG_INTERFACE_LOCK 0x40000000 +#define IA32_DEBUG_INTERFACE_MASK 0x80000000 + +/* + * PAT + */ +#define PATENTRY(n, type) ((uint64_t)type << ((n) * 8)) +#define PAT_UC 0x0UL +#define PAT_WC 0x1UL +#define PAT_WT 0x4UL +#define PAT_WP 0x5UL +#define PAT_WB 0x6UL +#define PAT_UCMINUS 0x7UL + +/* + * XSAVE subfeatures (cpuid 0xd, leaf 1) + */ +#define XSAVE_XSAVEOPT 0x1UL +#define XSAVE_XSAVEC 0x2UL +#define XSAVE_XGETBV1 0x4UL +#define XSAVE_XSAVES 0x8UL \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/sysarch.h b/lib/libc/include/x86-openbsd-none/machine/sysarch.h new file mode 100644 index 000000000000..871c60d946ba --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/sysarch.h @@ -0,0 +1,38 @@ +/* $OpenBSD: sysarch.h,v 1.14 2016/03/24 04:56:08 guenther Exp $ */ +/* $NetBSD: sysarch.h,v 1.8 1996/01/08 13:51:44 mycroft Exp $ */ + +#ifndef _MACHINE_SYSARCH_H_ +#define _MACHINE_SYSARCH_H_ + +/* + * Architecture specific syscalls (i386) + */ +#define I386_IOPL 2 +#define I386_VM86 5 +#define I386_GET_FSBASE 6 +#define I386_SET_FSBASE 7 +#define I386_GET_GSBASE 8 +#define I386_SET_GSBASE 9 + +struct i386_iopl_args { + int iopl; +}; + +#ifdef _KERNEL +uint32_t i386_get_threadbase(struct proc *, int); +int i386_set_threadbase(struct proc *, uint32_t, int); +#else + +#include + +__BEGIN_DECLS +int i386_iopl(int); +int i386_get_fsbase(void **); +int i386_set_fsbase(void *); +int i386_get_gsbase(void **); +int i386_set_gsbase(void *); +int sysarch(int, void *); +__END_DECLS +#endif + +#endif /* !_MACHINE_SYSARCH_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/tcb.h b/lib/libc/include/x86-openbsd-none/machine/tcb.h new file mode 100644 index 000000000000..eb8003e2605b --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/tcb.h @@ -0,0 +1,51 @@ +/* $OpenBSD: tcb.h,v 1.4 2016/09/04 08:49:35 guenther Exp $ */ +/* + * Copyright (c) 2011 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TCB_H_ +#define _MACHINE_TCB_H_ + +#ifdef _KERNEL + +#include +#include + +#define TCB_GET(p) \ + ((void *)i386_get_threadbase(p, TSEG_GS)) +#define TCB_SET(p, addr) \ + i386_set_threadbase(p, (uint32_t)(addr), TSEG_GS) + +#else /* _KERNEL */ + +/* ELF TLS ABI calls for big TCB, with static TLS data at negative offsets */ +#define TLS_VARIANT 2 + +/* Read a slot from the TCB */ +static inline void * +__i386_read_tcb(int offset) +{ + void *val; + __asm__ ("movl %%gs:(%1),%0" : "=r" (val) : "r" (offset)); + return val; +} + +/* Get a pointer to the TCB itself */ +#define TCB_GET() __i386_read_tcb(0) + +/* Setting the TCB pointer can only be done via syscall, so no TCB_SET() */ + +#endif /* _KERNEL */ +#endif /* _MACHINE_TCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/trap.h b/lib/libc/include/x86-openbsd-none/machine/trap.h new file mode 100644 index 000000000000..6a91b82f3eff --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/trap.h @@ -0,0 +1,65 @@ +/* $OpenBSD: trap.h,v 1.6 2015/06/28 01:11:27 guenther Exp $ */ +/* $NetBSD: trap.h,v 1.4 1994/10/27 04:16:30 cgd Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)trap.h 5.4 (Berkeley) 5/9/91 + */ + +/* + * Trap type values + * also known in trap.c for name strings + */ + +#define T_PRIVINFLT 0 /* privileged instruction */ +#define T_BPTFLT 1 /* breakpoint trap */ +#define T_ARITHTRAP 2 /* arithmetic trap */ +#define T_RESERVED 3 /* reserved fault base */ +#define T_PROTFLT 4 /* protection fault */ +#define T_TRCTRAP 5 /* trace trap */ +#define T_PAGEFLT 6 /* page fault */ +#define T_ALIGNFLT 7 /* alignment fault */ +#define T_DIVIDE 8 /* integer divide fault */ +#define T_NMI 9 /* non-maskable interrupt */ +#define T_OFLOW 10 /* overflow trap */ +#define T_BOUND 11 /* bounds check fault */ +#define T_DNA 12 /* device not available fault */ +#define T_DOUBLEFLT 13 /* double fault */ +#define T_FPOPFLT 14 /* fp coprocessor operand fetch fault (![P]Pro)*/ +#define T_TSSFLT 15 /* invalid tss fault */ +#define T_SEGNPFLT 16 /* segment not present fault */ +#define T_STKFLT 17 /* stack fault */ +#define T_MACHK 18 /* machine check ([P]Pro) */ +#define T_XFTRAP 19 /* SIMD FP exception */ + +/* Trap's coming from user mode */ +#define T_USER 0x100 \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/tss.h b/lib/libc/include/x86-openbsd-none/machine/tss.h new file mode 100644 index 000000000000..d2e5f750b678 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/tss.h @@ -0,0 +1,74 @@ +/* $OpenBSD: tss.h,v 1.12 2018/06/22 13:21:14 bluhm Exp $ */ +/* $NetBSD: tss.h,v 1.6 1995/10/11 04:20:28 mycroft Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tss.h 5.4 (Berkeley) 1/18/91 + */ + +#ifndef _MACHINE_TSS_H_ +#define _MACHINE_TSS_H_ + +/* + * Intel 386 Context Data Type + */ + +struct i386tss { + int __tss_link; + int tss_esp0; /* kernel stack pointer at privilege level 0 */ + int tss_ss0; /* kernel stack segment at privilege level 0 */ + int __tss_esp1; + int __tss_ss1; + int __tss_esp2; + int __tss_ss2; + int tss_cr3; + int tss_eip; + int tss_eflags; + int tss_eax; + int tss_ecx; + int tss_edx; + int tss_ebx; + int tss_esp; + int tss_ebp; + int tss_esi; + int tss_edi; + int tss_es; + int tss_cs; + int tss_ss; + int tss_ds; + int tss_fs; + int tss_gs; + int tss_ldt; + int tss_ioopt; /* options and I/O permission map offset */ +}; + +#endif /* _MACHINE_TSS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/vga_post.h b/lib/libc/include/x86-openbsd-none/machine/vga_post.h new file mode 100644 index 000000000000..7207b11c31df --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/vga_post.h @@ -0,0 +1,43 @@ +/* $NetBSD: vga_post.h,v 1.2 2008/03/29 17:40:22 jmcneill Exp $ */ +/* $OpenBSD: vga_post.h,v 1.2 2011/03/23 16:54:35 pirofti Exp $ */ + +/*- + * Copyright (c) 2007 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_VGA_POST_H_ +#define _MACHINE_VGA_POST_H_ + +#ifdef _KERNEL +struct vga_post; + +struct vga_post *vga_post_init(int, int, int); +void vga_post_free(struct vga_post *); +void vga_post_call(struct vga_post *); +#endif +#endif \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/vmmvar.h b/lib/libc/include/x86-openbsd-none/machine/vmmvar.h new file mode 100644 index 000000000000..6528cb81029e --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/vmmvar.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2014 Mike Larkin + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define VMM_HV_SIGNATURE "OpenBSDVMM58" \ No newline at end of file diff --git a/lib/libc/include/x86-openbsd-none/machine/vmparam.h b/lib/libc/include/x86-openbsd-none/machine/vmparam.h new file mode 100644 index 000000000000..3e7cc4f4bbc9 --- /dev/null +++ b/lib/libc/include/x86-openbsd-none/machine/vmparam.h @@ -0,0 +1,108 @@ +/* $OpenBSD: vmparam.h,v 1.57 2021/03/16 18:04:16 kurt Exp $ */ +/* $NetBSD: vmparam.h,v 1.15 1994/10/27 04:16:34 cgd Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vmparam.h 5.9 (Berkeley) 5/12/91 + */ + +#ifndef _MACHINE_VMPARAM_H_ +#define _MACHINE_VMPARAM_H_ +/* + * Machine dependent constants for 386. + */ + +#define USRSTACK VM_MAXUSER_ADDRESS + +/* + * Virtual memory related constants, all in bytes + */ +#define MAXTSIZ (256*1024*1024) /* max text size */ +#ifndef DFLDSIZ +#define DFLDSIZ (64*1024*1024) /* initial data size limit */ +#endif +#ifndef MAXDSIZ +#define MAXDSIZ (3UL*1024*1024*1024) /* max data size */ +#endif +#ifndef BRKSIZ +#define BRKSIZ (128*1024*1024) /* heap gap size */ +#endif +#ifndef DFLSSIZ +#define DFLSSIZ (4*1024*1024) /* initial stack size limit */ +#endif +#ifndef MAXSSIZ +#define MAXSSIZ (32*1024*1024) /* max stack size */ +#endif + +#define STACKGAP_RANDOM 256*1024 + +/* I386 has a line where all code is executable: 0 - I386_MAX_EXE_ADDR */ +#define I386_MAX_EXE_ADDR 0x20000000 /* exec line */ + +/* map PIE into 320MB - 448MB address range */ +#define VM_PIE_MIN_ADDR 0x14000000 +#define VM_PIE_MAX_ADDR 0x1C000000 + +/* + * Size of shared memory map + */ +#ifndef SHMMAXPGS +#define SHMMAXPGS 8192 +#endif + +/* + * Size of User Raw I/O map + */ +#define USRIOSIZE 300 + +/* + * Specific addresses being unmapped and used as fillers for free memory. + */ +#define DEADBEEF0 0xefffeecc /* malloc's filler */ +#define DEADBEEF1 0xefffaabb /* pool's filler */ + +/* user/kernel map constants */ +#define VM_MIN_ADDRESS ((vaddr_t)PAGE_SIZE) +#define VM_MAXUSER_ADDRESS ((vaddr_t)((PDSLOT_PTE< - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _FENV_H_ -#define _FENV_H_ - -#include -#include -#include - -#ifndef __fenv_static -#define __fenv_static static -#endif - -typedef __uint16_t fexcept_t; - -/* Exception flags */ -#define FE_INVALID 0x01 -#define FE_DENORMAL 0x02 -#define FE_DIVBYZERO 0x04 -#define FE_OVERFLOW 0x08 -#define FE_UNDERFLOW 0x10 -#define FE_INEXACT 0x20 -#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_DENORMAL | FE_INEXACT | \ - FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) - -/* Rounding modes */ -#define FE_TONEAREST 0x0000 -#define FE_DOWNWARD 0x0400 -#define FE_UPWARD 0x0800 -#define FE_TOWARDZERO 0x0c00 -#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ - FE_UPWARD | FE_TOWARDZERO) - -/* - * As compared to the x87 control word, the SSE unit's control word - * has the rounding control bits offset by 3 and the exception mask - * bits offset by 7. - */ -#define _SSE_ROUND_SHIFT 3 -#define _SSE_EMASK_SHIFT 7 - -#ifdef __i386__ -/* - * To preserve binary compatibility with FreeBSD 5.3, we pack the - * mxcsr into some reserved fields, rather than changing sizeof(fenv_t). - */ -typedef struct { - __uint16_t __control; - __uint16_t __mxcsr_hi; - __uint16_t __status; - __uint16_t __mxcsr_lo; - __uint32_t __tag; - char __other[16]; -} fenv_t; -#else /* __amd64__ */ -typedef struct { - struct { - __uint32_t __control; - __uint32_t __status; - __uint32_t __tag; - char __other[16]; - } __x87; - __uint32_t __mxcsr; -} fenv_t; -#endif /* __i386__ */ - -__BEGIN_DECLS - -/* Default floating-point environment */ -extern const fenv_t __fe_dfl_env; -#define FE_DFL_ENV (&__fe_dfl_env) - -#define __fldenvx(__env) __asm __volatile("fldenv %0" : : "m" (__env) \ - : "st", "st(1)", "st(2)", "st(3)", "st(4)", \ - "st(5)", "st(6)", "st(7)") -#define __fwait() __asm __volatile("fwait") - -int fegetenv(fenv_t *__envp); -int feholdexcept(fenv_t *__envp); -int fesetexceptflag(const fexcept_t *__flagp, int __excepts); -int feraiseexcept(int __excepts); -int feupdateenv(const fenv_t *__envp); - -__fenv_static inline int -fegetround(void) -{ - __uint16_t __control; - - /* - * We assume that the x87 and the SSE unit agree on the - * rounding mode. Reading the control word on the x87 turns - * out to be about 5 times faster than reading it on the SSE - * unit on an Opteron 244. - */ - __fnstcw(&__control); - return (__control & _ROUND_MASK); -} - -#if __BSD_VISIBLE - -int feenableexcept(int __mask); -int fedisableexcept(int __mask); - -/* We currently provide no external definition of fegetexcept(). */ -static inline int -fegetexcept(void) -{ - __uint16_t __control; - - /* - * We assume that the masks for the x87 and the SSE unit are - * the same. - */ - __fnstcw(&__control); - return (~__control & FE_ALL_EXCEPT); -} - -#endif /* __BSD_VISIBLE */ - -#ifdef __i386__ - -/* After testing for SSE support once, we cache the result in __has_sse. */ -enum __sse_support { __SSE_YES, __SSE_NO, __SSE_UNK }; -extern enum __sse_support __has_sse; -int __test_sse(void); -#ifdef __SSE__ -#define __HAS_SSE() 1 -#else -#define __HAS_SSE() (__has_sse == __SSE_YES || \ - (__has_sse == __SSE_UNK && __test_sse())) -#endif - -#define __get_mxcsr(env) (((env).__mxcsr_hi << 16) | \ - ((env).__mxcsr_lo)) -#define __set_mxcsr(env, x) do { \ - (env).__mxcsr_hi = (__uint32_t)(x) >> 16; \ - (env).__mxcsr_lo = (__uint16_t)(x); \ -} while (0) - -__fenv_static inline int -feclearexcept(int __excepts) -{ - fenv_t __env; - __uint32_t __mxcsr; - - if (__excepts == FE_ALL_EXCEPT) { - __fnclex(); - } else { - __fnstenv(&__env); - __env.__status &= ~__excepts; - __fldenv(&__env); - } - if (__HAS_SSE()) { - __stmxcsr(&__mxcsr); - __mxcsr &= ~__excepts; - __ldmxcsr(&__mxcsr); - } - return (0); -} - -__fenv_static inline int -fegetexceptflag(fexcept_t *__flagp, int __excepts) -{ - __uint32_t __mxcsr; - __uint16_t __status; - - __fnstsw(&__status); - if (__HAS_SSE()) - __stmxcsr(&__mxcsr); - else - __mxcsr = 0; - *__flagp = (__mxcsr | __status) & __excepts; - return (0); -} - -__fenv_static inline int -fetestexcept(int __excepts) -{ - __uint32_t __mxcsr; - __uint16_t __status; - - __fnstsw(&__status); - if (__HAS_SSE()) - __stmxcsr(&__mxcsr); - else - __mxcsr = 0; - return ((__status | __mxcsr) & __excepts); -} - -__fenv_static inline int -fesetround(int __round) -{ - __uint32_t __mxcsr; - __uint16_t __control; - - if (__round & ~_ROUND_MASK) - return (-1); - - __fnstcw(&__control); - __control &= ~_ROUND_MASK; - __control |= __round; - __fldcw(&__control); - - if (__HAS_SSE()) { - __stmxcsr(&__mxcsr); - __mxcsr &= ~(_ROUND_MASK << _SSE_ROUND_SHIFT); - __mxcsr |= __round << _SSE_ROUND_SHIFT; - __ldmxcsr(&__mxcsr); - } - - return (0); -} - -__fenv_static inline int -fesetenv(const fenv_t *__envp) -{ - fenv_t __env = *__envp; - __uint32_t __mxcsr; - - __mxcsr = __get_mxcsr(__env); - __set_mxcsr(__env, 0xffffffff); - /* - * XXX Using fldenvx() instead of fldenv() tells the compiler that this - * instruction clobbers the i387 register stack. This happens because - * we restore the tag word from the saved environment. Normally, this - * would happen anyway and we wouldn't care, because the ABI allows - * function calls to clobber the i387 regs. However, fesetenv() is - * inlined, so we need to be more careful. - */ - __fldenvx(__env); - if (__HAS_SSE()) - __ldmxcsr(&__mxcsr); - return (0); -} - -#else /* __amd64__ */ - -__fenv_static inline int -feclearexcept(int __excepts) -{ - fenv_t __env; - - if (__excepts == FE_ALL_EXCEPT) { - __fnclex(); - } else { - __fnstenv(&__env.__x87); - __env.__x87.__status &= ~__excepts; - __fldenv(&__env.__x87); - } - __stmxcsr(&__env.__mxcsr); - __env.__mxcsr &= ~__excepts; - __ldmxcsr(&__env.__mxcsr); - return (0); -} - -__fenv_static inline int -fegetexceptflag(fexcept_t *__flagp, int __excepts) -{ - __uint32_t __mxcsr; - __uint16_t __status; - - __stmxcsr(&__mxcsr); - __fnstsw(&__status); - *__flagp = (__mxcsr | __status) & __excepts; - return (0); -} - -__fenv_static inline int -fetestexcept(int __excepts) -{ - __uint32_t __mxcsr; - __uint16_t __status; - - __stmxcsr(&__mxcsr); - __fnstsw(&__status); - return ((__status | __mxcsr) & __excepts); -} - -__fenv_static inline int -fesetround(int __round) -{ - __uint32_t __mxcsr; - __uint16_t __control; - - if (__round & ~_ROUND_MASK) - return (-1); - - __fnstcw(&__control); - __control &= ~_ROUND_MASK; - __control |= __round; - __fldcw(&__control); - - __stmxcsr(&__mxcsr); - __mxcsr &= ~(_ROUND_MASK << _SSE_ROUND_SHIFT); - __mxcsr |= __round << _SSE_ROUND_SHIFT; - __ldmxcsr(&__mxcsr); - - return (0); -} - -__fenv_static inline int -fesetenv(const fenv_t *__envp) -{ - - /* - * XXX Using fldenvx() instead of fldenv() tells the compiler that this - * instruction clobbers the i387 register stack. This happens because - * we restore the tag word from the saved environment. Normally, this - * would happen anyway and we wouldn't care, because the ABI allows - * function calls to clobber the i387 regs. However, fesetenv() is - * inlined, so we need to be more careful. - */ - __fldenvx(__envp->__x87); - __ldmxcsr(&__envp->__mxcsr); - return (0); -} - -#endif /* __i386__ */ - -__END_DECLS - -#endif /* !_FENV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/float.h b/lib/libc/include/x86_64-freebsd-none/float.h deleted file mode 100644 index 0e6d11c8c393..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/float.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/floatingpoint.h b/lib/libc/include/x86_64-freebsd-none/floatingpoint.h deleted file mode 100644 index 134415f2e6e7..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/floatingpoint.h +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 1993 Andrew Moore, Talke Studio - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#) floatingpoint.h 1.0 (Berkeley) 9/23/93 - */ - -#ifndef _FLOATINGPOINT_H_ -#define _FLOATINGPOINT_H_ - -#include -#include - -#endif /* !_FLOATINGPOINT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/i386/asm.h b/lib/libc/include/x86_64-freebsd-none/i386/asm.h index c51c45ae7212..7a0b90fc1d4c 100644 --- a/lib/libc/include/x86_64-freebsd-none/i386/asm.h +++ b/lib/libc/include/x86_64-freebsd-none/i386/asm.h @@ -30,8 +30,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)DEFS.h 5.1 (Berkeley) 4/23/90 */ #ifndef _MACHINE_ASM_H_ diff --git a/lib/libc/include/x86_64-freebsd-none/i386/atomic.h b/lib/libc/include/x86_64-freebsd-none/i386/atomic.h index 3211d15efae7..63143fe5a35a 100644 --- a/lib/libc/include/x86_64-freebsd-none/i386/atomic.h +++ b/lib/libc/include/x86_64-freebsd-none/i386/atomic.h @@ -49,8 +49,8 @@ static __inline void __mbk(void) { - __asm __volatile("lock; addl $0,%%fs:%0" - : "+m" (*(u_int *)__OFFSETOF_MONITORBUF) : : "memory", "cc"); + __asm __volatile("lock; addl $0,%%fs:%c0" + : : "i" (__OFFSETOF_MONITORBUF) : "memory", "cc"); } static __inline void @@ -249,7 +249,7 @@ atomic_testandclear_int(volatile u_int *p, u_int v) #define ATOMIC_LOAD(TYPE) \ static __inline u_##TYPE \ -atomic_load_acq_##TYPE(volatile u_##TYPE *p) \ +atomic_load_acq_##TYPE(const volatile u_##TYPE *p) \ { \ u_##TYPE res; \ \ @@ -299,17 +299,6 @@ atomic_thread_fence_seq_cst(void) #ifdef _KERNEL -#ifdef WANT_FUNCTIONS -int atomic_cmpset_64_i386(volatile uint64_t *, uint64_t, uint64_t); -int atomic_cmpset_64_i586(volatile uint64_t *, uint64_t, uint64_t); -uint64_t atomic_load_acq_64_i386(volatile uint64_t *); -uint64_t atomic_load_acq_64_i586(volatile uint64_t *); -void atomic_store_rel_64_i386(volatile uint64_t *, uint64_t); -void atomic_store_rel_64_i586(volatile uint64_t *, uint64_t); -uint64_t atomic_swap_64_i386(volatile uint64_t *, uint64_t); -uint64_t atomic_swap_64_i586(volatile uint64_t *, uint64_t); -#endif - /* I486 does not support SMP or CMPXCHG8B. */ static __inline int atomic_cmpset_64_i386(volatile uint64_t *dst, uint64_t expect, uint64_t src) @@ -353,12 +342,12 @@ atomic_fcmpset_64_i386(volatile uint64_t *dst, uint64_t *expect, uint64_t src) } static __inline uint64_t -atomic_load_acq_64_i386(volatile uint64_t *p) +atomic_load_acq_64_i386(const volatile uint64_t *p) { - volatile uint32_t *q; + const volatile uint32_t *q; uint64_t res; - q = (volatile uint32_t *)p; + q = (const volatile uint32_t *)p; __asm __volatile( " pushfl ; " " cli ; " @@ -447,8 +436,12 @@ atomic_fcmpset_64_i586(volatile uint64_t *dst, uint64_t *expect, uint64_t src) return (res); } +/* + * Architecturally always writes back some value to '*p' so will trigger + * a #GP(0) on read-only mappings. + */ static __inline uint64_t -atomic_load_acq_64_i586(volatile uint64_t *p) +atomic_load_acq_64_i586(const volatile uint64_t *p) { uint64_t res; @@ -456,9 +449,9 @@ atomic_load_acq_64_i586(volatile uint64_t *p) " movl %%ebx,%%eax ; " " movl %%ecx,%%edx ; " " lock; cmpxchg8b %1" - : "=&A" (res), /* 0 */ - "+m" (*p) /* 1 */ - : : "memory", "cc"); + : "=&A" (res) /* 0 */ + : "m" (*p) /* 1 */ + : "memory", "cc"); return (res); } @@ -514,7 +507,7 @@ atomic_fcmpset_64(volatile uint64_t *dst, uint64_t *expect, uint64_t src) } static __inline uint64_t -atomic_load_acq_64(volatile uint64_t *p) +atomic_load_acq_64(const volatile uint64_t *p) { if ((cpu_feature & CPUID_CX8) == 0) @@ -614,8 +607,6 @@ ATOMIC_LOADSTORE(long); #undef ATOMIC_STORE #undef ATOMIC_LOADSTORE -#ifndef WANT_FUNCTIONS - static __inline int atomic_cmpset_long(volatile u_long *dst, u_long expect, u_long src) { @@ -842,7 +833,7 @@ atomic_swap_long(volatile u_long *p, u_long v) #define atomic_subtract_rel_ptr(p, v) \ atomic_subtract_rel_int((volatile u_int *)(p), (u_int)(v)) #define atomic_load_acq_ptr(p) \ - atomic_load_acq_int((volatile u_int *)(p)) + atomic_load_acq_int((const volatile u_int *)(p)) #define atomic_store_rel_ptr(p, v) \ atomic_store_rel_int((volatile u_int *)(p), (v)) #define atomic_cmpset_ptr(dst, old, new) \ @@ -865,8 +856,10 @@ atomic_swap_long(volatile u_long *p, u_long v) atomic_swap_int((volatile u_int *)(p), (u_int)(v)) #define atomic_readandclear_ptr(p) \ atomic_readandclear_int((volatile u_int *)(p)) - -#endif /* !WANT_FUNCTIONS */ +#define atomic_testandclear_ptr(p, val) \ + atomic_testandclear_int((volatile u_int *)(p), (val)) +#define atomic_testandset_ptr(p, val) \ + atomic_testandset_int((volatile u_int *)(p), (val)) #if defined(_KERNEL) #define mb() __mbk() diff --git a/lib/libc/include/x86_64-freebsd-none/i386/cpufunc.h b/lib/libc/include/x86_64-freebsd-none/i386/cpufunc.h index 0c8667b08dc1..22cd1b7cd1db 100644 --- a/lib/libc/include/x86_64-freebsd-none/i386/cpufunc.h +++ b/lib/libc/include/x86_64-freebsd-none/i386/cpufunc.h @@ -63,15 +63,6 @@ bsfl(u_int mask) return (result); } -static __inline __pure2 u_int -bsrl(u_int mask) -{ - u_int result; - - __asm("bsrl %1,%0" : "=r" (result) : "rm" (mask) : "cc"); - return (result); -} - static __inline void clflush(u_long addr) { @@ -83,7 +74,7 @@ static __inline void clflushopt(u_long addr) { - __asm __volatile(".byte 0x66;clflush %0" : : "m" (*(char *)addr)); + __asm __volatile("clflushopt %0" : : "m" (*(char *)addr)); } static __inline void diff --git a/lib/libc/include/x86_64-freebsd-none/i386/pcpu.h b/lib/libc/include/x86_64-freebsd-none/i386/pcpu.h index 48704d4b6016..87c6b69f2bfd 100644 --- a/lib/libc/include/x86_64-freebsd-none/i386/pcpu.h +++ b/lib/libc/include/x86_64-freebsd-none/i386/pcpu.h @@ -108,16 +108,8 @@ _Static_assert(sizeof(struct monitorbuf) == 128, "2x cache line"); /* * Evaluates to the address of the per-cpu variable name. */ -#define __PCPU_PTR(name) __extension__ ({ \ - __pcpu_type(name) *__p; \ - \ - __asm __volatile("movl %%fs:%1,%0; addl %2,%0" \ - : "=r" (__p) \ - : "m" (*(struct pcpu *)(__pcpu_offset(pc_prvspace))), \ - "i" (__pcpu_offset(name))); \ - \ - __p; \ -}) +#define __PCPU_PTR(name) \ + (&get_pcpu()->name) /* * Evaluates to the value of the per-cpu variable name. @@ -126,14 +118,13 @@ _Static_assert(sizeof(struct monitorbuf) == 128, "2x cache line"); __pcpu_type(name) __res; \ struct __s { \ u_char __b[MIN(sizeof(__res), 4)]; \ - } __s; \ + }; \ \ if (sizeof(__res) == 1 || sizeof(__res) == 2 || \ sizeof(__res) == 4) { \ - __asm __volatile("mov %%fs:%1,%0" \ - : "=r" (__s) \ - : "m" (*(struct __s *)(__pcpu_offset(name)))); \ - *(struct __s *)(void *)&__res = __s; \ + __asm __volatile("mov %%fs:%c1,%0" \ + : "=r" (*(struct __s *)(void *)&__res) \ + : "i" (__pcpu_offset(name))); \ } else { \ __res = *__PCPU_PTR(name); \ } \ @@ -148,15 +139,16 @@ _Static_assert(sizeof(struct monitorbuf) == 128, "2x cache line"); __pcpu_type(name) __val; \ struct __s { \ u_char __b[MIN(sizeof(__val), 4)]; \ - } __s; \ + }; \ \ __val = (val); \ if (sizeof(__val) == 1 || sizeof(__val) == 2 || \ sizeof(__val) == 4) { \ - __s = *(struct __s *)(void *)&__val; \ - __asm __volatile("add %1,%%fs:%0" \ - : "=m" (*(struct __s *)(__pcpu_offset(name))) \ - : "r" (__s)); \ + __asm __volatile("add %1,%%fs:%c0" \ + : \ + : "i" (__pcpu_offset(name)), \ + "r" (*(struct __s *)(void *)&__val) \ + : "cc", "memory"); \ } else \ *__PCPU_PTR(name) += __val; \ } while (0) @@ -168,15 +160,16 @@ _Static_assert(sizeof(struct monitorbuf) == 128, "2x cache line"); __pcpu_type(name) __val; \ struct __s { \ u_char __b[MIN(sizeof(__val), 4)]; \ - } __s; \ + }; \ \ __val = (val); \ if (sizeof(__val) == 1 || sizeof(__val) == 2 || \ sizeof(__val) == 4) { \ - __s = *(struct __s *)(void *)&__val; \ - __asm __volatile("mov %1,%%fs:%0" \ - : "=m" (*(struct __s *)(__pcpu_offset(name))) \ - : "r" (__s)); \ + __asm __volatile("mov %1,%%fs:%c0" \ + : \ + : "i" (__pcpu_offset(name)), \ + "r" (*(struct __s *)(void *)&__val) \ + : "memory"); \ } else { \ *__PCPU_PTR(name) = __val; \ } \ @@ -185,9 +178,9 @@ _Static_assert(sizeof(struct monitorbuf) == 128, "2x cache line"); #define get_pcpu() __extension__ ({ \ struct pcpu *__pc; \ \ - __asm __volatile("movl %%fs:%1,%0" \ + __asm __volatile("movl %%fs:%c1,%0" \ : "=r" (__pc) \ - : "m" (*(struct pcpu *)(__pcpu_offset(pc_prvspace)))); \ + : "i" (__pcpu_offset(pc_prvspace))); \ __pc; \ }) diff --git a/lib/libc/include/x86_64-freebsd-none/i386/pcpu_aux.h b/lib/libc/include/x86_64-freebsd-none/i386/pcpu_aux.h index 4fc13cdfd3fa..5807079df3a6 100644 --- a/lib/libc/include/x86_64-freebsd-none/i386/pcpu_aux.h +++ b/lib/libc/include/x86_64-freebsd-none/i386/pcpu_aux.h @@ -49,8 +49,8 @@ __curthread(void) { struct thread *td; - __asm("movl %%fs:%1,%0" : "=r" (td) - : "m" (*(char *)offsetof(struct pcpu, pc_curthread))); + __asm("movl %%fs:%c1,%0" : "=r" (td) + : "i" (offsetof(struct pcpu, pc_curthread))); return (td); } #define curthread (__curthread()) @@ -60,8 +60,8 @@ __curpcb(void) { struct pcb *pcb; - __asm("movl %%fs:%1,%0" : "=r" (pcb) - : "m" (*(char *)offsetof(struct pcpu, pc_curpcb))); + __asm("movl %%fs:%c1,%0" : "=r" (pcb) + : "i" (offsetof(struct pcpu, pc_curpcb))); return (pcb); } #define curpcb (__curpcb()) diff --git a/lib/libc/include/x86_64-freebsd-none/i386/pmap.h b/lib/libc/include/x86_64-freebsd-none/i386/pmap.h index c4971b12424c..886993cbbdd3 100644 --- a/lib/libc/include/x86_64-freebsd-none/i386/pmap.h +++ b/lib/libc/include/x86_64-freebsd-none/i386/pmap.h @@ -37,9 +37,6 @@ * map the page tables using the pagetables themselves. This is done to * reduce the impact on kernel virtual memory for lots of sparse address * space, and to reduce the cost of memory to each process. - * - * from: hp300: @(#)pmap.h 7.2 (Berkeley) 12/16/90 - * from: @(#)pmap.h 7.4 (Berkeley) 5/12/91 */ #ifndef _MACHINE_PMAP_H_ @@ -83,7 +80,7 @@ * 4KB (PTE) page mappings have identical settings for the following fields: */ #define PG_PTE_PROMOTE (PG_MANAGED | PG_W | PG_G | PG_PTE_PAT | \ - PG_M | PG_A | PG_NC_PCD | PG_NC_PWT | PG_U | PG_RW | PG_V) + PG_M | PG_NC_PCD | PG_NC_PWT | PG_U | PG_RW | PG_V) /* * Page Protection Exception bits @@ -221,7 +218,7 @@ void pmap_basemem_setup(u_int basemem); void *pmap_bios16_enter(void); void pmap_bios16_leave(void *handle); void pmap_bootstrap(vm_paddr_t); -int pmap_cache_bits(pmap_t, int mode, boolean_t is_pde); +int pmap_cache_bits(pmap_t, int mode, bool is_pde); int pmap_change_attr(vm_offset_t, vm_size_t, int); caddr_t pmap_cmap3(vm_paddr_t pa, u_int pte_bits); void pmap_cp_slow0_map(vm_offset_t kaddr, int plen, vm_page_t *ma); @@ -239,7 +236,7 @@ void pmap_ksetrw(vm_offset_t va); void *pmap_mapbios(vm_paddr_t, vm_size_t); void *pmap_mapdev(vm_paddr_t, vm_size_t); void *pmap_mapdev_attr(vm_paddr_t, vm_size_t, int); -boolean_t pmap_page_is_mapped(vm_page_t m); +bool pmap_page_is_mapped(vm_page_t m); void pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma); vm_paddr_t pmap_pg_frame(vm_paddr_t pa); bool pmap_ps_enabled(pmap_t pmap); diff --git a/lib/libc/include/x86_64-freebsd-none/i386/proc.h b/lib/libc/include/x86_64-freebsd-none/i386/proc.h index 8ba00996450b..3377daab2ca4 100644 --- a/lib/libc/include/x86_64-freebsd-none/i386/proc.h +++ b/lib/libc/include/x86_64-freebsd-none/i386/proc.h @@ -27,8 +27,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)proc.h 7.1 (Berkeley) 5/15/91 */ #ifndef _MACHINE_PROC_H_ diff --git a/lib/libc/include/x86_64-freebsd-none/i386/profile.h b/lib/libc/include/x86_64-freebsd-none/i386/profile.h index c58517f68773..2789d419f554 100644 --- a/lib/libc/include/x86_64-freebsd-none/i386/profile.h +++ b/lib/libc/include/x86_64-freebsd-none/i386/profile.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)profile.h 8.1 (Berkeley) 6/11/93 */ #ifndef _MACHINE_PROFILE_H_ diff --git a/lib/libc/include/x86_64-freebsd-none/i386/segments.h b/lib/libc/include/x86_64-freebsd-none/i386/segments.h index c2d38f970b23..cfb3054fd8bb 100644 --- a/lib/libc/include/x86_64-freebsd-none/i386/segments.h +++ b/lib/libc/include/x86_64-freebsd-none/i386/segments.h @@ -31,8 +31,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)segments.h 7.1 (Berkeley) 5/9/91 */ #ifndef _MACHINE_SEGMENTS_H_ diff --git a/lib/libc/include/x86_64-freebsd-none/i386/vmparam.h b/lib/libc/include/x86_64-freebsd-none/i386/vmparam.h index 2e4840657613..625944650a1e 100644 --- a/lib/libc/include/x86_64-freebsd-none/i386/vmparam.h +++ b/lib/libc/include/x86_64-freebsd-none/i386/vmparam.h @@ -32,8 +32,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)vmparam.h 5.9 (Berkeley) 5/12/91 */ #ifndef _MACHINE_VMPARAM_H_ @@ -248,5 +246,6 @@ * Need a page dump array for minidump. */ #define MINIDUMP_PAGE_TRACKING 1 +#define MINIDUMP_STARTUP_PAGE_TRACKING 0 #endif /* _MACHINE_VMPARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/_align.h b/lib/libc/include/x86_64-freebsd-none/machine/_align.h deleted file mode 100644 index 4af6dd67a7aa..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/_align.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/_bus.h b/lib/libc/include/x86_64-freebsd-none/machine/_bus.h index 2a13caba31ee..ce1bada4344e 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/_bus.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/_bus.h @@ -1,30 +1,13 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2005 M. Warner Losh + * Copyright (c) 2005 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, - * without modification, immediately at the beginning of the file. - * 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. + * SPDX-License-Identifier: BSD-2-Clause * - * 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. + * Derived in part from NetBSD's bus.h files by (alphabetically): + * Christopher G. Demetriou + * Charles M. Hannum + * Jason Thorpe + * The NetBSD Foundation. */ #ifndef AMD64_INCLUDE__BUS_H diff --git a/lib/libc/include/x86_64-freebsd-none/machine/_inttypes.h b/lib/libc/include/x86_64-freebsd-none/machine/_inttypes.h deleted file mode 100644 index 218f00871b16..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/_inttypes.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/_limits.h b/lib/libc/include/x86_64-freebsd-none/machine/_limits.h deleted file mode 100644 index 71d8b62434e1..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/_limits.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/_stdint.h b/lib/libc/include/x86_64-freebsd-none/machine/_stdint.h deleted file mode 100644 index 4fb2b3fb4ada..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/_stdint.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/_types.h b/lib/libc/include/x86_64-freebsd-none/machine/_types.h deleted file mode 100644 index da8cb16909c4..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/_types.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/asm.h b/lib/libc/include/x86_64-freebsd-none/machine/asm.h index 11184f221317..d3ca1f7208c1 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/asm.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/asm.h @@ -30,8 +30,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)DEFS.h 5.1 (Berkeley) 4/23/90 */ #ifdef __i386__ @@ -94,7 +92,7 @@ #define END(x) .size x, . - x; .cfi_endproc /* - * WEAK_REFERENCE(): create a weak reference alias from sym. + * WEAK_REFERENCE(): create a weak reference alias from sym. * The macro is not a general asm macro that takes arbitrary names, * but one that takes only C names. It does the non-null name * translation inside the macro. diff --git a/lib/libc/include/x86_64-freebsd-none/machine/atomic.h b/lib/libc/include/x86_64-freebsd-none/machine/atomic.h index 8e1b656ce7d0..eeefa748c86e 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/atomic.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/atomic.h @@ -102,7 +102,7 @@ */ /* - * Always use lock prefixes. The result is slighly less optimal for + * Always use lock prefixes. The result is slightly less optimal for * UP systems, but it matters less now, and sometimes UP is emulated * over SMP. * @@ -295,8 +295,8 @@ static __inline void __storeload_barrier(void) { #if defined(_KERNEL) - __asm __volatile("lock; addl $0,%%gs:%0" - : "+m" (*(u_int *)OFFSETOF_MONITORBUF) : : "memory", "cc"); + __asm __volatile("lock; addl $0,%%gs:%c0" + : : "i" (OFFSETOF_MONITORBUF) : "memory", "cc"); #else /* !_KERNEL */ __asm __volatile("lock; addl $0,-8(%%rsp)" : : : "memory", "cc"); #endif /* _KERNEL*/ @@ -304,7 +304,7 @@ __storeload_barrier(void) #define ATOMIC_LOAD(TYPE) \ static __inline u_##TYPE \ -atomic_load_acq_##TYPE(volatile u_##TYPE *p) \ +atomic_load_acq_##TYPE(const volatile u_##TYPE *p) \ { \ u_##TYPE res; \ \ @@ -385,7 +385,6 @@ ATOMIC_LOADSTORE(long); #undef ATOMIC_LOAD #undef ATOMIC_STORE #undef ATOMIC_LOADSTORE -#ifndef WANT_FUNCTIONS /* Read the current value and store a new value in the destination. */ static __inline u_int @@ -589,8 +588,8 @@ atomic_swap_long(volatile u_long *p, u_long v) #define atomic_fcmpset_rel_ptr atomic_fcmpset_rel_long #define atomic_swap_ptr atomic_swap_long #define atomic_readandclear_ptr atomic_readandclear_long - -#endif /* !WANT_FUNCTIONS */ +#define atomic_testandset_ptr atomic_testandset_long +#define atomic_testandclear_ptr atomic_testandclear_long #endif /* !SAN_NEEDS_INTERCEPTORS || SAN_RUNTIME */ diff --git a/lib/libc/include/x86_64-freebsd-none/machine/bus.h b/lib/libc/include/x86_64-freebsd-none/machine/bus.h deleted file mode 100644 index 025c59ba2f2f..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/bus.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/bus_dma.h b/lib/libc/include/x86_64-freebsd-none/machine/bus_dma.h index a7a39a174fa6..6435c896e2fa 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/bus_dma.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/bus_dma.h @@ -29,6 +29,6 @@ #ifndef _AMD64_BUS_DMA_H_ #define _AMD64_BUS_DMA_H_ -#include +#include #endif /* _AMD64_BUS_DMA_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/clock.h b/lib/libc/include/x86_64-freebsd-none/machine/clock.h deleted file mode 100644 index 838e4abd5916..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/clock.h +++ /dev/null @@ -1,5 +0,0 @@ -/* - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/cpu.h b/lib/libc/include/x86_64-freebsd-none/machine/cpu.h index 7d947e6b6e14..bbd38817fb7e 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/cpu.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/cpu.h @@ -30,8 +30,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)cpu.h 5.4 (Berkeley) 5/9/91 */ #ifndef _MACHINE_CPU_H_ @@ -72,7 +70,8 @@ extern char btext[]; extern char _end[]; extern char etext[]; -/* Resume hook for VMM. */ +/* Suspend and resume hook for VMM. */ +extern void (*vmm_suspend_p)(void); extern void (*vmm_resume_p)(void); void cpu_halt(void); diff --git a/lib/libc/include/x86_64-freebsd-none/machine/cpufunc.h b/lib/libc/include/x86_64-freebsd-none/machine/cpufunc.h index 7d2fdf0af924..2d339f84b44d 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/cpufunc.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/cpufunc.h @@ -65,10 +65,6 @@ breakpoint(void) #define bsfq(mask) __builtin_ctzl(mask) -#define bsrl(mask) (__builtin_clz(mask) ^ 0x1f) - -#define bsrq(mask) (__builtin_clzl(mask) ^ 0x3f) - static __inline void clflush(u_long addr) { @@ -80,7 +76,7 @@ static __inline void clflushopt(u_long addr) { - __asm __volatile(".byte 0x66;clflush %0" : : "m" (*(char *)addr)); + __asm __volatile("clflushopt %0" : : "m" (*(char *)addr)); } static __inline void @@ -576,6 +572,15 @@ rss(void) return (sel); } +static __inline u_short +rcs(void) +{ + u_short sel; + + __asm __volatile("movw %%cs,%0" : "=rm" (sel)); + return (sel); +} + static __inline void load_ds(u_short sel) { @@ -946,6 +951,29 @@ sgx_eremove(void *epc) return (sgx_encls(SGX_EREMOVE, 0, (uint64_t)epc, 0)); } +static __inline void +xrstors(uint8_t *save_area, uint64_t state_bitmap) +{ + uint32_t low, hi; + + low = state_bitmap; + hi = state_bitmap >> 32; + __asm __volatile("xrstors %0" : : "m"(*save_area), "a"(low), + "d"(hi)); +} + +static __inline void +xsaves(uint8_t *save_area, uint64_t state_bitmap) +{ + uint32_t low, hi; + + low = state_bitmap; + hi = state_bitmap >> 32; + __asm __volatile("xsaves %0" : "=m"(*save_area) : "a"(low), + "d"(hi) + : "memory"); +} + void reset_dbregs(void); #ifdef _KERNEL diff --git a/lib/libc/include/x86_64-freebsd-none/machine/dump.h b/lib/libc/include/x86_64-freebsd-none/machine/dump.h deleted file mode 100644 index cf91d4b47952..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/dump.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/efi.h b/lib/libc/include/x86_64-freebsd-none/machine/efi.h index d1dc00371a1e..0c6099120883 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/efi.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/efi.h @@ -29,6 +29,8 @@ #ifndef __AMD64_INCLUDE_EFI_H_ #define __AMD64_INCLUDE_EFI_H_ +#include + /* * XXX: from gcc 6.2 manual: * Note, the ms_abi attribute for Microsoft Windows 64-bit targets @@ -51,6 +53,10 @@ #define EFI_TIME_OWNED() mtx_assert(&atrtc_time_lock, MA_OWNED) #define EFI_RT_HANDLE_FAULTS_DEFAULT 1 + +#define EFI_MAP_BOOTTYPE_ALLOWED(type) (((efi_map_regs >> (type)) & 1) != 0) + +extern uint32_t efi_map_regs; #endif struct efirt_callinfo { diff --git a/lib/libc/include/x86_64-freebsd-none/machine/elf.h b/lib/libc/include/x86_64-freebsd-none/machine/elf.h deleted file mode 100644 index 36a7ae1abaad..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/elf.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/endian.h b/lib/libc/include/x86_64-freebsd-none/machine/endian.h deleted file mode 100644 index 02be261a3b80..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/endian.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/exec.h b/lib/libc/include/x86_64-freebsd-none/machine/exec.h deleted file mode 100644 index 3a992321ba55..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/exec.h +++ /dev/null @@ -1,39 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)exec.h 8.1 (Berkeley) 6/11/93 - */ - -#ifndef _MACHINE_EXEC_H_ -#define _MACHINE_EXEC_H_ - -#define __LDPGSZ 4096 - -#endif /* !_MACHINE_EXEC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/float.h b/lib/libc/include/x86_64-freebsd-none/machine/float.h deleted file mode 100644 index 0e6d11c8c393..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/float.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/floatingpoint.h b/lib/libc/include/x86_64-freebsd-none/machine/floatingpoint.h deleted file mode 100644 index 134415f2e6e7..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/floatingpoint.h +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 1993 Andrew Moore, Talke Studio - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#) floatingpoint.h 1.0 (Berkeley) 9/23/93 - */ - -#ifndef _FLOATINGPOINT_H_ -#define _FLOATINGPOINT_H_ - -#include -#include - -#endif /* !_FLOATINGPOINT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/fpu.h b/lib/libc/include/x86_64-freebsd-none/machine/fpu.h index f4ada921ebd2..e5bf23ad9f88 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/fpu.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/fpu.h @@ -30,8 +30,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)npx.h 5.3 (Berkeley) 1/18/91 */ /* diff --git a/lib/libc/include/x86_64-freebsd-none/machine/ieeefp.h b/lib/libc/include/x86_64-freebsd-none/machine/ieeefp.h index 79a55381f197..27f5ef58c314 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/ieeefp.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/ieeefp.h @@ -32,8 +32,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#) ieeefp.h 1.0 (Berkeley) 9/23/93 */ #ifndef _MACHINE_IEEEFP_H_ diff --git a/lib/libc/include/x86_64-freebsd-none/machine/md_var.h b/lib/libc/include/x86_64-freebsd-none/machine/md_var.h index 6a55cd48d5d2..57036e48d494 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/md_var.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/md_var.h @@ -50,6 +50,7 @@ extern vm_paddr_t intel_graphics_stolen_base; extern vm_paddr_t intel_graphics_stolen_size; extern int la57; +extern int prefer_uva_la48; extern vm_paddr_t kernphys; extern vm_paddr_t KERNend; @@ -98,6 +99,10 @@ void get_fpcontext(struct thread *td, struct __mcontext *mcp, int set_fpcontext(struct thread *td, struct __mcontext *mcp, char *xfpustate, size_t xfpustate_len); +void wrmsr_early_safe_start(void); +void wrmsr_early_safe_end(void); +int wrmsr_early_safe(u_int msr, uint64_t data); + #endif /* !_MACHINE_MD_VAR_H_ */ #endif /* __i386__ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/metadata.h b/lib/libc/include/x86_64-freebsd-none/machine/metadata.h deleted file mode 100644 index 2b194e06d14b..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/metadata.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/msan.h b/lib/libc/include/x86_64-freebsd-none/machine/msan.h index 085cba783367..95abd83ea5c9 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/msan.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/msan.h @@ -81,7 +81,7 @@ kmsan_md_unsupported(vm_offset_t addr) * The kernel itself isn't shadowed: for most purposes global variables * are always initialized, and because KMSAN kernels are large * (GENERIC-KMSAN is ~80MB at the time of writing), shadowing would - * incur signficant memory usage. + * incur significant memory usage. */ return (addr < VM_MIN_KERNEL_ADDRESS || addr >= KERNBASE); } diff --git a/lib/libc/include/x86_64-freebsd-none/machine/ofw_machdep.h b/lib/libc/include/x86_64-freebsd-none/machine/ofw_machdep.h deleted file mode 100644 index 21d28906f0dd..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/ofw_machdep.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/param.h b/lib/libc/include/x86_64-freebsd-none/machine/param.h index b98eb83cf393..0403f0d36a02 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/param.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/param.h @@ -36,8 +36,6 @@ * 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. - * - * @(#)param.h 8.1 (Berkeley) 6/10/93 */ #ifndef _AMD64_INCLUDE_PARAM_H_ @@ -49,9 +47,6 @@ * Machine dependent constants for AMD64. */ -#define __HAVE_ACPI -#define __PCI_REROUTE_INTERRUPT - #ifndef MACHINE #define MACHINE "amd64" #endif @@ -80,7 +75,7 @@ * ALIGNED_POINTER is a boolean macro that checks whether an address * is valid to fetch data elements of type t from on this architecture. * This does not reflect the optimal alignment, just the possibility - * (within reasonable limits). + * (within reasonable limits). */ #define ALIGNED_POINTER(p, t) 1 @@ -144,25 +139,17 @@ /* * Mach derived conversion macros */ -#define round_page(x) ((((unsigned long)(x)) + PAGE_MASK) & ~(PAGE_MASK)) -#define trunc_page(x) ((unsigned long)(x) & ~(PAGE_MASK)) #define trunc_2mpage(x) ((unsigned long)(x) & ~PDRMASK) #define round_2mpage(x) ((((unsigned long)(x)) + PDRMASK) & ~PDRMASK) #define trunc_1gpage(x) ((unsigned long)(x) & ~PDPMASK) -#define atop(x) ((unsigned long)(x) >> PAGE_SHIFT) -#define ptoa(x) ((unsigned long)(x) << PAGE_SHIFT) - #define amd64_btop(x) ((unsigned long)(x) >> PAGE_SHIFT) #define amd64_ptob(x) ((unsigned long)(x) << PAGE_SHIFT) -#define pgtok(x) ((unsigned long)(x) * (PAGE_SIZE / 1024)) +#define INKERNEL(va) \ + (((va) >= kva_layout.dmap_low && (va) < kva_layout.dmap_high) || \ + ((va) >= kva_layout.km_low && (va) < kva_layout.km_high)) -#define INKERNEL(va) (((va) >= DMAP_MIN_ADDRESS && (va) < DMAP_MAX_ADDRESS) \ - || ((va) >= VM_MIN_KERNEL_ADDRESS && (va) < VM_MAX_KERNEL_ADDRESS)) - -#ifdef SMP #define SC_TABLESIZE 1024 /* Must be power of 2. */ -#endif #endif /* !_AMD64_INCLUDE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/pcb.h b/lib/libc/include/x86_64-freebsd-none/machine/pcb.h index 7ab791703722..b478c3064e00 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/pcb.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/pcb.h @@ -31,8 +31,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)pcb.h 5.10 (Berkeley) 5/12/91 */ #ifndef _AMD64_PCB_H_ @@ -86,6 +84,7 @@ struct pcb { #define PCB_KERNFPU_THR 0x0020 /* fpu_kern_thread() */ #define PCB_32BIT 0x0040 /* process has 32 bit context (segs etc) */ #define PCB_FPUNOSAVE 0x0080 /* no save area for current FPU ctx */ +#define PCB_TLSBASE 0x0100 /* tlsbase was set */ uint16_t pcb_initial_fpucw; @@ -106,7 +105,8 @@ struct pcb { struct savefpu *pcb_save; - uint64_t pcb_pad[5]; + register_t pcb_tlsbase; /* not same as pcb_fsbase */ + uint64_t pcb_pad[4]; }; /* Per-CPU state saved during suspend and resume. */ diff --git a/lib/libc/include/x86_64-freebsd-none/machine/pcpu.h b/lib/libc/include/x86_64-freebsd-none/machine/pcpu.h index e9ed33c71218..469ae6213dc5 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/pcpu.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/pcpu.h @@ -182,16 +182,8 @@ _Static_assert(sizeof(struct monitorbuf) == 128, "2x cache line"); /* * Evaluates to the address of the per-cpu variable name. */ -#define __PCPU_PTR(name) __extension__ ({ \ - __pcpu_type(name) *__p; \ - \ - __asm __volatile("movq %%gs:%1,%0; addq %2,%0" \ - : "=r" (__p) \ - : "m" (*(struct pcpu *)(__pcpu_offset(pc_prvspace))), \ - "i" (__pcpu_offset(name))); \ - \ - __p; \ -}) +#define __PCPU_PTR(name) \ + (&get_pcpu()->name) /* * Evaluates to the value of the per-cpu variable name. @@ -200,14 +192,13 @@ _Static_assert(sizeof(struct monitorbuf) == 128, "2x cache line"); __pcpu_type(name) __res; \ struct __s { \ u_char __b[MIN(sizeof(__pcpu_type(name)), 8)]; \ - } __s; \ + }; \ \ if (sizeof(__res) == 1 || sizeof(__res) == 2 || \ sizeof(__res) == 4 || sizeof(__res) == 8) { \ - __asm __volatile("mov %%gs:%1,%0" \ - : "=r" (__s) \ - : "m" (*(struct __s *)(__pcpu_offset(name)))); \ - *(struct __s *)(void *)&__res = __s; \ + __asm __volatile("mov %%gs:%c1,%0" \ + : "=r" (*(struct __s *)(void *)&__res) \ + : "i" (__pcpu_offset(name))); \ } else { \ __res = *__PCPU_PTR(name); \ } \ @@ -222,15 +213,16 @@ _Static_assert(sizeof(struct monitorbuf) == 128, "2x cache line"); __pcpu_type(name) __val; \ struct __s { \ u_char __b[MIN(sizeof(__pcpu_type(name)), 8)]; \ - } __s; \ + }; \ \ __val = (val); \ if (sizeof(__val) == 1 || sizeof(__val) == 2 || \ sizeof(__val) == 4 || sizeof(__val) == 8) { \ - __s = *(struct __s *)(void *)&__val; \ - __asm __volatile("add %1,%%gs:%0" \ - : "=m" (*(struct __s *)(__pcpu_offset(name))) \ - : "r" (__s)); \ + __asm __volatile("add %1,%%gs:%c0" \ + : \ + : "i" (__pcpu_offset(name)), \ + "r" (*(struct __s *)(void *)&__val) \ + : "cc", "memory"); \ } else \ *__PCPU_PTR(name) += __val; \ } while (0) @@ -238,30 +230,31 @@ _Static_assert(sizeof(struct monitorbuf) == 128, "2x cache line"); /* * Sets the value of the per-cpu variable name to value val. */ -#define __PCPU_SET(name, val) { \ +#define __PCPU_SET(name, val) do { \ __pcpu_type(name) __val; \ struct __s { \ u_char __b[MIN(sizeof(__pcpu_type(name)), 8)]; \ - } __s; \ + }; \ \ __val = (val); \ if (sizeof(__val) == 1 || sizeof(__val) == 2 || \ sizeof(__val) == 4 || sizeof(__val) == 8) { \ - __s = *(struct __s *)(void *)&__val; \ - __asm __volatile("mov %1,%%gs:%0" \ - : "=m" (*(struct __s *)(__pcpu_offset(name))) \ - : "r" (__s)); \ + __asm __volatile("mov %1,%%gs:%c0" \ + : \ + : "i" (__pcpu_offset(name)), \ + "r" (*(struct __s *)(void *)&__val) \ + : "memory"); \ } else { \ *__PCPU_PTR(name) = __val; \ } \ -} +} while (0) #define get_pcpu() __extension__ ({ \ struct pcpu *__pc; \ \ - __asm __volatile("movq %%gs:%1,%0" \ + __asm __volatile("movq %%gs:%c1,%0" \ : "=r" (__pc) \ - : "m" (*(struct pcpu *)(__pcpu_offset(pc_prvspace)))); \ + : "i" (__pcpu_offset(pc_prvspace))); \ __pc; \ }) #endif /* !__SEG_GS */ diff --git a/lib/libc/include/x86_64-freebsd-none/machine/pcpu_aux.h b/lib/libc/include/x86_64-freebsd-none/machine/pcpu_aux.h index c42a421182c2..b8d87dc04c4b 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/pcpu_aux.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/pcpu_aux.h @@ -54,8 +54,8 @@ __curthread(void) { struct thread *td; - __asm("movq %%gs:%P1,%0" : "=r" (td) : "n" (offsetof(struct pcpu, - pc_curthread))); + __asm("movq %%gs:%c1,%0" : "=r" (td) + : "i" (offsetof(struct pcpu, pc_curthread))); return (td); } #define curthread (__curthread()) diff --git a/lib/libc/include/x86_64-freebsd-none/machine/pmap.h b/lib/libc/include/x86_64-freebsd-none/machine/pmap.h index bfcb1c0cd686..fc01fc724979 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/pmap.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/pmap.h @@ -38,9 +38,6 @@ * map the page tables using the pagetables themselves. This is done to * reduce the impact on kernel virtual memory for lots of sparse address * space, and to reduce the cost of memory to each process. - * - * from: hp300: @(#)pmap.h 7.2 (Berkeley) 12/16/90 - * from: @(#)pmap.h 7.4 (Berkeley) 5/12/91 */ #ifdef __i386__ @@ -50,48 +47,7 @@ #ifndef _MACHINE_PMAP_H_ #define _MACHINE_PMAP_H_ -/* - * Page-directory and page-table entries follow this format, with a few - * of the fields not present here and there, depending on a lot of things. - */ - /* ---- Intel Nomenclature ---- */ -#define X86_PG_V 0x001 /* P Valid */ -#define X86_PG_RW 0x002 /* R/W Read/Write */ -#define X86_PG_U 0x004 /* U/S User/Supervisor */ -#define X86_PG_NC_PWT 0x008 /* PWT Write through */ -#define X86_PG_NC_PCD 0x010 /* PCD Cache disable */ -#define X86_PG_A 0x020 /* A Accessed */ -#define X86_PG_M 0x040 /* D Dirty */ -#define X86_PG_PS 0x080 /* PS Page size (0=4k,1=2M) */ -#define X86_PG_PTE_PAT 0x080 /* PAT PAT index */ -#define X86_PG_G 0x100 /* G Global */ -#define X86_PG_AVAIL1 0x200 /* / Available for system */ -#define X86_PG_AVAIL2 0x400 /* < programmers use */ -#define X86_PG_AVAIL3 0x800 /* \ */ -#define X86_PG_PDE_PAT 0x1000 /* PAT PAT index */ -#define X86_PG_PKU(idx) ((pt_entry_t)idx << 59) -#define X86_PG_NX (1ul<<63) /* No-execute */ -#define X86_PG_AVAIL(x) (1ul << (x)) - -/* Page level cache control fields used to determine the PAT type */ -#define X86_PG_PDE_CACHE (X86_PG_PDE_PAT | X86_PG_NC_PWT | X86_PG_NC_PCD) -#define X86_PG_PTE_CACHE (X86_PG_PTE_PAT | X86_PG_NC_PWT | X86_PG_NC_PCD) - -/* Protection keys indexes */ -#define PMAP_MAX_PKRU_IDX 0xf -#define X86_PG_PKU_MASK X86_PG_PKU(PMAP_MAX_PKRU_IDX) - -/* - * Intel extended page table (EPT) bit definitions. - */ -#define EPT_PG_READ 0x001 /* R Read */ -#define EPT_PG_WRITE 0x002 /* W Write */ -#define EPT_PG_EXECUTE 0x004 /* X Execute */ -#define EPT_PG_IGNORE_PAT 0x040 /* IPAT Ignore PAT */ -#define EPT_PG_PS 0x080 /* PS Page size */ -#define EPT_PG_A 0x100 /* A Accessed */ -#define EPT_PG_M 0x200 /* D Dirty */ -#define EPT_PG_MEMORY_TYPE(x) ((x) << 3) /* MT Memory Type */ +#include /* * Define the PG_xx macros in terms of the bits on x86 PTEs. @@ -120,9 +76,6 @@ #define EPT_PG_EMUL_V X86_PG_AVAIL(52) #define EPT_PG_EMUL_RW X86_PG_AVAIL(53) #define PG_PROMOTED X86_PG_AVAIL(54) /* PDE only */ -#define PG_FRAME (0x000ffffffffff000ul) -#define PG_PS_FRAME (0x000fffffffe00000ul) -#define PG_PS_PDP_FRAME (0x000fffffc0000000ul) /* * Promotion to a 2MB (PDE) page mapping requires that the corresponding 4KB @@ -132,18 +85,6 @@ PG_M | PG_U | PG_RW | PG_V | PG_PKU_MASK) /* - * Page Protection Exception bits - */ - -#define PGEX_P 0x01 /* Protection violation vs. not present */ -#define PGEX_W 0x02 /* during a Write cycle */ -#define PGEX_U 0x04 /* access from User mode (UPL) */ -#define PGEX_RSV 0x08 /* reserved PTE field is non-zero */ -#define PGEX_I 0x10 /* during an instruction fetch */ -#define PGEX_PK 0x20 /* protection key violation */ -#define PGEX_SGX 0x8000 /* SGX-related */ - -/* * undef the PG_xx macros that define bits in the regular x86 PTEs that * have a different position in nested PTEs. This is done when compiling * code that needs to be aware of the differences between regular x86 and @@ -169,12 +110,7 @@ * Pte related macros. This is complicated by having to deal with * the sign extension of the 48th bit. */ -#define KV4ADDR(l4, l3, l2, l1) ( \ - ((unsigned long)-1 << 47) | \ - ((unsigned long)(l4) << PML4SHIFT) | \ - ((unsigned long)(l3) << PDPSHIFT) | \ - ((unsigned long)(l2) << PDRSHIFT) | \ - ((unsigned long)(l1) << PAGE_SHIFT)) +#define KV4ADDR(l4, l3, l2, l1) KV5ADDR(-1, l4, l3, l2, l1) #define KV5ADDR(l5, l4, l3, l2, l1) ( \ ((unsigned long)-1 << 56) | \ ((unsigned long)(l5) << PML5SHIFT) | \ @@ -233,11 +169,12 @@ * the recursive page table map. */ #define NDMPML4E 8 +#define NDMPML5E 32 /* - * These values control the layout of virtual memory. The starting address - * of the direct map, which is controlled by DMPML4I, must be a multiple of - * its size. (See the PHYS_TO_DMAP() and DMAP_TO_PHYS() macros.) + * These values control the layout of virtual memory. The starting + * address of the direct map is controlled by DMPML4I on LA48 and + * DMPML5I on LA57. * * Note: KPML4I is the index of the (single) level 4 page that maps * the KVA that holds KERNBASE, while KPML4BASE is the index of the @@ -255,6 +192,7 @@ #define KPML4BASE (NPML4EPG-NKPML4E) /* KVM at highest addresses */ #define DMPML4I rounddown(KPML4BASE-NDMPML4E, NDMPML4E) /* Below KVM */ +#define DMPML5I (NPML5EPG / 2 + 1) #define KPML4I (NPML4EPG-1) #define KPDPI (NPDPEPG-2) /* kernbase at -2GB */ @@ -264,9 +202,14 @@ #define KMSANSHADPML4I (KPML4BASE - NKMSANSHADPML4E) #define KMSANORIGPML4I (DMPML4I - NKMSANORIGPML4E) -/* Large map: index of the first and max last pml4 entry */ +/* + * Large map: index of the first and max last pml4/la48 and pml5/la57 + * entry. + */ #define LMSPML4I (PML4PML4I + 1) #define LMEPML4I (KASANPML4I - 1) +#define LMSPML5I (DMPML5I + NDMPML5E) +#define LMEPML5I (LMSPML5I + 32 - 1) /* 32 slots for large map */ /* * XXX doesn't really belong here I guess... @@ -448,10 +391,10 @@ void pmap_activate_boot(pmap_t pmap); void pmap_activate_sw(struct thread *); void pmap_allow_2m_x_ept_recalculate(void); void pmap_bootstrap(vm_paddr_t *); -int pmap_cache_bits(pmap_t pmap, int mode, boolean_t is_pde); +int pmap_cache_bits(pmap_t pmap, int mode, bool is_pde); int pmap_change_attr(vm_offset_t, vm_size_t, int); int pmap_change_prot(vm_offset_t, vm_size_t, vm_prot_t); -void pmap_demote_DMAP(vm_paddr_t base, vm_size_t len, boolean_t invalidate); +void pmap_demote_DMAP(vm_paddr_t base, vm_size_t len, bool invalidate); void pmap_flush_cache_range(vm_offset_t, vm_offset_t); void pmap_flush_cache_phys_range(vm_paddr_t, vm_paddr_t, vm_memattr_t); void pmap_init_pat(void); @@ -467,7 +410,7 @@ void *pmap_mapdev(vm_paddr_t, vm_size_t); void *pmap_mapdev_attr(vm_paddr_t, vm_size_t, int); void *pmap_mapdev_pciecfg(vm_paddr_t pa, vm_size_t size); bool pmap_not_in_di(void); -boolean_t pmap_page_is_mapped(vm_page_t m); +bool pmap_page_is_mapped(vm_page_t m); void pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma); void pmap_page_set_memattr_noflush(vm_page_t m, vm_memattr_t ma); void pmap_pinit_pml4(vm_page_t); @@ -612,6 +555,25 @@ pmap_pml5e_index(vm_offset_t va) return ((va >> PML5SHIFT) & ((1ul << NPML5EPGSHIFT) - 1)); } +struct kva_layout_s { + vm_offset_t kva_min; + vm_offset_t kva_max; + vm_offset_t dmap_low; /* DMAP_MIN_ADDRESS */ + vm_offset_t dmap_high; /* DMAP_MAX_ADDRESS */ + vm_offset_t lm_low; /* LARGEMAP_MIN_ADDRESS */ + vm_offset_t lm_high; /* LARGEMAP_MAX_ADDRESS */ + vm_offset_t km_low; /* VM_MIN_KERNEL_ADDRESS */ + vm_offset_t km_high; /* VM_MAX_KERNEL_ADDRESS */ + vm_offset_t rec_pt; + vm_offset_t kasan_shadow_low; /* KASAN_MIN_ADDRESS */ + vm_offset_t kasan_shadow_high; /* KASAN_MAX_ADDRESS */ + vm_offset_t kmsan_shadow_low; /* KMSAN_SHAD_MIN_ADDRESS */ + vm_offset_t kmsan_shadow_high; /* KMSAN_SHAD_MAX_ADDRESS */ + vm_offset_t kmsan_origin_low; /* KMSAN_ORIG_MIN_ADDRESS */ + vm_offset_t kmsan_origin_high; /* KMSAN_ORIG_MAX_ADDRESS */ +}; +extern struct kva_layout_s kva_layout; + #endif /* !LOCORE */ #endif /* !_MACHINE_PMAP_H_ */ diff --git a/lib/libc/include/x86_64-freebsd-none/machine/proc.h b/lib/libc/include/x86_64-freebsd-none/machine/proc.h index 1bfc5a199676..12b06f653c4f 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/proc.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/proc.h @@ -27,8 +27,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)proc.h 7.1 (Berkeley) 5/15/91 */ #ifdef __i386__ diff --git a/lib/libc/include/x86_64-freebsd-none/machine/profile.h b/lib/libc/include/x86_64-freebsd-none/machine/profile.h index 8b0c79da822c..1648bf947925 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/profile.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/profile.h @@ -27,8 +27,6 @@ * 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. - * - * @(#)profile.h 8.1 (Berkeley) 6/11/93 */ #ifdef __i386__ diff --git a/lib/libc/include/x86_64-freebsd-none/machine/psl.h b/lib/libc/include/x86_64-freebsd-none/machine/psl.h deleted file mode 100644 index 59536384fca5..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/psl.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/pte.h b/lib/libc/include/x86_64-freebsd-none/machine/pte.h new file mode 100644 index 000000000000..2a123b737366 --- /dev/null +++ b/lib/libc/include/x86_64-freebsd-none/machine/pte.h @@ -0,0 +1,104 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2003 Peter Wemm. + * Copyright (c) 1991 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department and William Jolitz of UUNET Technologies Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Derived from hp300 version by Mike Hibler, this version by William + * Jolitz uses a recursive map [a pde points to the page directory] to + * map the page tables using the pagetables themselves. This is done to + * reduce the impact on kernel virtual memory for lots of sparse address + * space, and to reduce the cost of memory to each process. + */ + +#ifndef _MACHINE_PTE_H_ +#define _MACHINE_PTE_H_ + +/* + * Page-directory and page-table entries follow this format, with a few + * of the fields not present here and there, depending on a lot of things. + */ + /* ---- Intel Nomenclature ---- */ +#define X86_PG_V 0x001 /* P Valid */ +#define X86_PG_RW 0x002 /* R/W Read/Write */ +#define X86_PG_U 0x004 /* U/S User/Supervisor */ +#define X86_PG_NC_PWT 0x008 /* PWT Write through */ +#define X86_PG_NC_PCD 0x010 /* PCD Cache disable */ +#define X86_PG_A 0x020 /* A Accessed */ +#define X86_PG_M 0x040 /* D Dirty */ +#define X86_PG_PS 0x080 /* PS Page size (0=4k,1=2M) */ +#define X86_PG_PTE_PAT 0x080 /* PAT PAT index */ +#define X86_PG_G 0x100 /* G Global */ +#define X86_PG_AVAIL1 0x200 /* / Available for system */ +#define X86_PG_AVAIL2 0x400 /* < programmers use */ +#define X86_PG_AVAIL3 0x800 /* \ */ +#define X86_PG_PDE_PAT 0x1000 /* PAT PAT index */ +#define X86_PG_PKU(idx) ((pt_entry_t)idx << 59) +#define X86_PG_NX (1ul<<63) /* No-execute */ +#define X86_PG_AVAIL(x) (1ul << (x)) + +/* Page level cache control fields used to determine the PAT type */ +#define X86_PG_PDE_CACHE (X86_PG_PDE_PAT | X86_PG_NC_PWT | X86_PG_NC_PCD) +#define X86_PG_PTE_CACHE (X86_PG_PTE_PAT | X86_PG_NC_PWT | X86_PG_NC_PCD) + +/* Protection keys indexes */ +#define PMAP_MAX_PKRU_IDX 0xf +#define X86_PG_PKU_MASK X86_PG_PKU(PMAP_MAX_PKRU_IDX) + +/* + * Intel extended page table (EPT) bit definitions. + */ +#define EPT_PG_READ 0x001 /* R Read */ +#define EPT_PG_WRITE 0x002 /* W Write */ +#define EPT_PG_EXECUTE 0x004 /* X Execute */ +#define EPT_PG_IGNORE_PAT 0x040 /* IPAT Ignore PAT */ +#define EPT_PG_PS 0x080 /* PS Page size */ +#define EPT_PG_A 0x100 /* A Accessed */ +#define EPT_PG_M 0x200 /* D Dirty */ +#define EPT_PG_MEMORY_TYPE(x) ((x) << 3) /* MT Memory Type */ + +#define PG_FRAME (0x000ffffffffff000ul) +#define PG_PS_FRAME (0x000fffffffe00000ul) +#define PG_PS_PDP_FRAME (0x000fffffc0000000ul) + +/* + * Page Protection Exception bits + */ +#define PGEX_P 0x01 /* Protection violation vs. not present */ +#define PGEX_W 0x02 /* during a Write cycle */ +#define PGEX_U 0x04 /* access from User mode (UPL) */ +#define PGEX_RSV 0x08 /* reserved PTE field is non-zero */ +#define PGEX_I 0x10 /* during an instruction fetch */ +#define PGEX_PK 0x20 /* protection key violation */ +#define PGEX_SGX 0x8000 /* SGX-related */ + +#endif \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/ptrace.h b/lib/libc/include/x86_64-freebsd-none/machine/ptrace.h deleted file mode 100644 index 0a426e24fabd..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/ptrace.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/reg.h b/lib/libc/include/x86_64-freebsd-none/machine/reg.h deleted file mode 100644 index 419b2756cc0d..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/reg.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/reloc.h b/lib/libc/include/x86_64-freebsd-none/machine/reloc.h deleted file mode 100644 index 4b31acb73c7b..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/reloc.h +++ /dev/null @@ -1,50 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)reloc.h 8.1 (Berkeley) 6/10/93 - */ - -#ifndef _I386_MACHINE_RELOC_H_ -#define _I386_MACHINE_RELOC_H_ - -/* Relocation format. */ -struct relocation_info { - int r_address; /* offset in text or data segment */ - unsigned int r_symbolnum : 24, /* ordinal number of add symbol */ - r_pcrel : 1, /* 1 if value should be pc-relative */ - r_length : 2, /* log base 2 of value's width */ - r_extern : 1, /* 1 if need to add symbol to value */ - r_baserel : 1, /* linkage table relative */ - r_jmptable : 1, /* relocate to jump table */ - r_relative : 1, /* load address relative */ - r_copy : 1; /* run time copy */ -}; - -#endif \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/resource.h b/lib/libc/include/x86_64-freebsd-none/machine/resource.h index aaafc404fff3..55cf68e28253 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/resource.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/resource.h @@ -12,7 +12,7 @@ * no representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied * warranty. - * + * * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF @@ -39,8 +39,6 @@ #define SYS_RES_DRQ 2 /* isa dma lines */ #define SYS_RES_MEMORY 3 /* i/o memory */ #define SYS_RES_IOPORT 4 /* i/o ports */ -#ifdef NEW_PCIB #define PCI_RES_BUS 5 /* PCI bus numbers */ -#endif #endif /* !_MACHINE_RESOURCE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/runq.h b/lib/libc/include/x86_64-freebsd-none/machine/runq.h deleted file mode 100644 index ac2270b627b1..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/runq.h +++ /dev/null @@ -1,46 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2001 Jake Burkholder - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _MACHINE_RUNQ_H_ -#define _MACHINE_RUNQ_H_ - -#define RQB_LEN (1) /* Number of priority status words. */ -#define RQB_L2BPW (6) /* Log2(sizeof(rqb_word_t) * NBBY)). */ -#define RQB_BPW (1<> RQB_L2BPW) - -#define RQB_FFS(word) (bsfq(word)) - -/* - * Type of run queue status word. - */ -typedef u_int64_t rqb_word_t; - -#endif \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/sdt_machdep.h b/lib/libc/include/x86_64-freebsd-none/machine/sdt_machdep.h new file mode 100644 index 000000000000..3e07c58fb977 --- /dev/null +++ b/lib/libc/include/x86_64-freebsd-none/machine/sdt_machdep.h @@ -0,0 +1,12 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 Mark Johnston + */ + +#ifndef _SYS_SDT_MACHDEP_H_ +#define _SYS_SDT_MACHDEP_H_ + +#define _SDT_ASM_PATCH_INSTR "nopw 0(%%rax,%%rax,1)" + +#endif \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/segments.h b/lib/libc/include/x86_64-freebsd-none/machine/segments.h index d33cde3649db..ee443e5b122a 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/segments.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/segments.h @@ -31,8 +31,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)segments.h 7.1 (Berkeley) 5/9/91 */ #ifdef __i386__ diff --git a/lib/libc/include/x86_64-freebsd-none/machine/setjmp.h b/lib/libc/include/x86_64-freebsd-none/machine/setjmp.h deleted file mode 100644 index 41ef6217a78d..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/setjmp.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/sf_buf.h b/lib/libc/include/x86_64-freebsd-none/machine/sf_buf.h index 619fa972636b..6d34e9dcf4d4 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/sf_buf.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/sf_buf.h @@ -34,7 +34,7 @@ * On this machine, the only purpose for which sf_buf is used is to implement * an opaque pointer required by the machine-independent parts of the kernel. * That pointer references the vm_page that is "mapped" by the sf_buf. The - * actual mapping is provided by the direct virtual-to-physical mapping. + * actual mapping is provided by the direct virtual-to-physical mapping. */ static inline vm_offset_t sf_buf_kva(struct sf_buf *sf) diff --git a/lib/libc/include/x86_64-freebsd-none/machine/smp.h b/lib/libc/include/x86_64-freebsd-none/machine/smp.h index 5fd858a2a1d1..20f408b5d46b 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/smp.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/smp.h @@ -13,8 +13,6 @@ #ifdef _KERNEL -#ifdef SMP - #ifndef LOCORE #include @@ -39,7 +37,6 @@ void invlop_handler(void); int start_all_aps(void); #endif /* !LOCORE */ -#endif /* SMP */ #endif /* _KERNEL */ #endif /* _MACHINE_SMP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/sysarch.h b/lib/libc/include/x86_64-freebsd-none/machine/sysarch.h deleted file mode 100644 index 7a8789707932..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/sysarch.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/tls.h b/lib/libc/include/x86_64-freebsd-none/machine/tls.h deleted file mode 100644 index 9a386029151e..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/tls.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/trap.h b/lib/libc/include/x86_64-freebsd-none/machine/trap.h deleted file mode 100644 index d8320b7b3503..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/trap.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/tss.h b/lib/libc/include/x86_64-freebsd-none/machine/tss.h index 420abc785125..b92b5c902d6e 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/tss.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/tss.h @@ -30,8 +30,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)tss.h 5.4 (Berkeley) 1/18/91 */ #ifndef _MACHINE_TSS_H_ diff --git a/lib/libc/include/x86_64-freebsd-none/machine/vdso.h b/lib/libc/include/x86_64-freebsd-none/machine/vdso.h deleted file mode 100644 index 57db69e06a7c..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/vdso.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/vm.h b/lib/libc/include/x86_64-freebsd-none/machine/vm.h deleted file mode 100644 index fdd08a2e4de4..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/machine/vm.h +++ /dev/null @@ -1,46 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2009 Hudson River Trading LLC - * Written by: John H. Baldwin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _MACHINE_VM_H_ -#define _MACHINE_VM_H_ - -#include - -/* Memory attributes. */ -#define VM_MEMATTR_UNCACHEABLE ((vm_memattr_t)PAT_UNCACHEABLE) -#define VM_MEMATTR_WRITE_COMBINING ((vm_memattr_t)PAT_WRITE_COMBINING) -#define VM_MEMATTR_WRITE_THROUGH ((vm_memattr_t)PAT_WRITE_THROUGH) -#define VM_MEMATTR_WRITE_PROTECTED ((vm_memattr_t)PAT_WRITE_PROTECTED) -#define VM_MEMATTR_WRITE_BACK ((vm_memattr_t)PAT_WRITE_BACK) -#define VM_MEMATTR_WEAK_UNCACHEABLE ((vm_memattr_t)PAT_UNCACHED) - -#define VM_MEMATTR_DEFAULT VM_MEMATTR_WRITE_BACK -#define VM_MEMATTR_DEVICE VM_MEMATTR_UNCACHEABLE - -#endif /* !_MACHINE_VM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-freebsd-none/machine/vmm.h b/lib/libc/include/x86_64-freebsd-none/machine/vmm.h index d922750dcdcb..53a16e7a26ac 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/vmm.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/vmm.h @@ -46,6 +46,7 @@ enum vm_suspend_how { VM_SUSPEND_POWEROFF, VM_SUSPEND_HALT, VM_SUSPEND_TRIPLEFAULT, + VM_SUSPEND_DESTROY, VM_SUSPEND_LAST }; @@ -124,7 +125,7 @@ enum x2apic_state { /* * The VM name has to fit into the pathname length constraints of devfs, * governed primarily by SPECNAMELEN. The length is the total number of - * characters in the full path, relative to the mount point and not + * characters in the full path, relative to the mount point and not * including any leading '/' characters. * A prefix and a suffix are added to the name specified by the user. * The prefix is usually "vmm/" or "vmm.io/", but can be a few characters @@ -150,6 +151,7 @@ CTASSERT(VM_MAX_NAMELEN >= VM_MIN_NAMELEN); struct vm; struct vm_exception; +struct vm_mem; struct seg_desc; struct vm_exit; struct vm_run; @@ -170,6 +172,7 @@ struct vm_eventinfo { typedef int (*vmm_init_func_t)(int ipinum); typedef int (*vmm_cleanup_func_t)(void); +typedef void (*vmm_suspend_func_t)(void); typedef void (*vmm_resume_func_t)(void); typedef void * (*vmi_init_func_t)(struct vm *vm, struct pmap *pmap); typedef int (*vmi_run_func_t)(void *vcpui, register_t rip, @@ -194,6 +197,7 @@ typedef int (*vmi_restore_tsc_t)(void *vcpui, uint64_t now); struct vmm_ops { vmm_init_func_t modinit; /* module wide initialization */ vmm_cleanup_func_t modcleanup; + vmm_resume_func_t modsuspend; vmm_resume_func_t modresume; vmi_init_func_t init; /* vm-specific initialization */ @@ -236,39 +240,11 @@ void vm_get_topology(struct vm *vm, uint16_t *sockets, uint16_t *cores, int vm_set_topology(struct vm *vm, uint16_t sockets, uint16_t cores, uint16_t threads, uint16_t maxcpus); -/* - * APIs that modify the guest memory map require all vcpus to be frozen. - */ -void vm_slock_memsegs(struct vm *vm); -void vm_xlock_memsegs(struct vm *vm); -void vm_unlock_memsegs(struct vm *vm); -int vm_mmap_memseg(struct vm *vm, vm_paddr_t gpa, int segid, vm_ooffset_t off, - size_t len, int prot, int flags); -int vm_munmap_memseg(struct vm *vm, vm_paddr_t gpa, size_t len); -int vm_alloc_memseg(struct vm *vm, int ident, size_t len, bool sysmem); -void vm_free_memseg(struct vm *vm, int ident); int vm_map_mmio(struct vm *vm, vm_paddr_t gpa, size_t len, vm_paddr_t hpa); int vm_unmap_mmio(struct vm *vm, vm_paddr_t gpa, size_t len); int vm_assign_pptdev(struct vm *vm, int bus, int slot, int func); int vm_unassign_pptdev(struct vm *vm, int bus, int slot, int func); -/* - * APIs that inspect the guest memory map require only a *single* vcpu to - * be frozen. This acts like a read lock on the guest memory map since any - * modification requires *all* vcpus to be frozen. - */ -int vm_mmap_getnext(struct vm *vm, vm_paddr_t *gpa, int *segid, - vm_ooffset_t *segoff, size_t *len, int *prot, int *flags); -int vm_get_memseg(struct vm *vm, int ident, size_t *len, bool *sysmem, - struct vm_object **objptr); -vm_paddr_t vmm_sysmem_maxaddr(struct vm *vm); -void *vm_gpa_hold(struct vcpu *vcpu, vm_paddr_t gpa, size_t len, - int prot, void **cookie); -void *vm_gpa_hold_global(struct vm *vm, vm_paddr_t gpa, size_t len, - int prot, void **cookie); -void vm_gpa_release(void *cookie); -bool vm_mem_allocated(struct vcpu *vcpu, vm_paddr_t gpa); - int vm_get_register(struct vcpu *vcpu, int reg, uint64_t *retval); int vm_set_register(struct vcpu *vcpu, int reg, uint64_t val); int vm_get_seg_desc(struct vcpu *vcpu, int reg, @@ -399,7 +375,8 @@ vcpu_should_yield(struct vcpu *vcpu) void *vcpu_stats(struct vcpu *vcpu); void vcpu_notify_event(struct vcpu *vcpu, bool lapic_intr); -struct vmspace *vm_get_vmspace(struct vm *vm); +struct vmspace *vm_vmspace(struct vm *vm); +struct vm_mem *vm_mem(struct vm *vm); struct vatpic *vm_atpic(struct vm *vm); struct vatpit *vm_atpit(struct vm *vm); struct vpmtmr *vm_pmtmr(struct vm *vm); @@ -448,7 +425,7 @@ int vm_get_intinfo(struct vcpu *vcpu, uint64_t *info1, uint64_t *info2); /* * Function used to keep track of the guest's TSC offset. The - * offset is used by the virutalization extensions to provide a consistent + * offset is used by the virtualization extensions to provide a consistent * value for the Time Stamp Counter to the guest. */ void vm_set_tsc_offset(struct vcpu *vcpu, uint64_t offset); @@ -465,7 +442,7 @@ struct vm_copyinfo { /* * Set up 'copyinfo[]' to copy to/from guest linear address space starting * at 'gla' and 'len' bytes long. The 'prot' should be set to PROT_READ for - * a copyin or PROT_WRITE for a copyout. + * a copyin or PROT_WRITE for a copyout. * * retval is_fault Interpretation * 0 0 Success @@ -673,6 +650,8 @@ struct vm_inout_str { int addrsize; enum vm_reg_name seg_name; struct seg_desc seg_desc; + int cs_d; + uint64_t cs_base; }; enum task_switch_reason { diff --git a/lib/libc/include/x86_64-freebsd-none/machine/vmm_dev.h b/lib/libc/include/x86_64-freebsd-none/machine/vmm_dev.h index 997a34a5518e..23f06ff5c342 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/vmm_dev.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/vmm_dev.h @@ -29,12 +29,10 @@ #ifndef _VMM_DEV_H_ #define _VMM_DEV_H_ -struct vm_snapshot_meta; +#include -#ifdef _KERNEL -void vmmdev_init(void); -int vmmdev_cleanup(void); -#endif +#include +#include struct vm_memmap { vm_paddr_t gpa; @@ -56,16 +54,12 @@ struct vm_munmap { struct vm_memseg { int segid; size_t len; - char name[VM_MAX_SUFFIXLEN + 1]; + char name[VM_MAX_SUFFIXLEN + 1]; + domainset_t *ds_mask; + size_t ds_mask_size; + int ds_policy; }; -struct vm_memseg_fbsd12 { - int segid; - size_t len; - char name[64]; -}; -_Static_assert(sizeof(struct vm_memseg_fbsd12) == 80, "COMPAT_FREEBSD12 ABI"); - struct vm_register { int cpuid; int regnum; /* enum vm_reg_name */ @@ -312,7 +306,7 @@ enum { IOCNUM_UNMAP_PPTDEV_MMIO = 46, /* statistics */ - IOCNUM_VM_STATS = 50, + IOCNUM_VM_STATS = 50, IOCNUM_VM_STAT_DESC = 51, /* kernel device state */ @@ -354,12 +348,8 @@ enum { _IOW('v', IOCNUM_SUSPEND, struct vm_suspend) #define VM_REINIT \ _IO('v', IOCNUM_REINIT) -#define VM_ALLOC_MEMSEG_FBSD12 \ - _IOW('v', IOCNUM_ALLOC_MEMSEG, struct vm_memseg_fbsd12) #define VM_ALLOC_MEMSEG \ _IOW('v', IOCNUM_ALLOC_MEMSEG, struct vm_memseg) -#define VM_GET_MEMSEG_FBSD12 \ - _IOWR('v', IOCNUM_GET_MEMSEG, struct vm_memseg_fbsd12) #define VM_GET_MEMSEG \ _IOWR('v', IOCNUM_GET_MEMSEG, struct vm_memseg) #define VM_MMAP_MEMSEG \ diff --git a/lib/libc/include/x86_64-freebsd-none/machine/vmm_instruction_emul.h b/lib/libc/include/x86_64-freebsd-none/machine/vmm_instruction_emul.h index 52ca34b48f9c..164ed16e9d28 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/vmm_instruction_emul.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/vmm_instruction_emul.h @@ -31,6 +31,31 @@ #include +/* struct vie_op.op_type */ +enum { + VIE_OP_TYPE_NONE = 0, + VIE_OP_TYPE_MOV, + VIE_OP_TYPE_MOVSX, + VIE_OP_TYPE_MOVZX, + VIE_OP_TYPE_AND, + VIE_OP_TYPE_OR, + VIE_OP_TYPE_SUB, + VIE_OP_TYPE_TWO_BYTE, + VIE_OP_TYPE_PUSH, + VIE_OP_TYPE_CMP, + VIE_OP_TYPE_POP, + VIE_OP_TYPE_MOVS, + VIE_OP_TYPE_GROUP1, + VIE_OP_TYPE_STOS, + VIE_OP_TYPE_BITTEST, + VIE_OP_TYPE_TWOB_GRP15, + VIE_OP_TYPE_ADD, + VIE_OP_TYPE_TEST, + VIE_OP_TYPE_BEXTR, + VIE_OP_TYPE_OUTS, + VIE_OP_TYPE_LAST +}; + /* * Callback functions to read and write memory regions. */ @@ -112,7 +137,7 @@ void vie_init(struct vie *vie, const char *inst_bytes, int inst_length); * 'gla' is the guest linear address provided by the hardware assist * that caused the nested page table fault. It is used to verify that * the software instruction decoding is in agreement with the hardware. - * + * * Some hardware assists do not provide the 'gla' to the hypervisor. * To skip the 'gla' verification for this or any other reason pass * in VIE_INVALID_GLA instead. diff --git a/lib/libc/include/x86_64-freebsd-none/machine/vmparam.h b/lib/libc/include/x86_64-freebsd-none/machine/vmparam.h index b4ee0e03e56a..862c29760b15 100644 --- a/lib/libc/include/x86_64-freebsd-none/machine/vmparam.h +++ b/lib/libc/include/x86_64-freebsd-none/machine/vmparam.h @@ -38,8 +38,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * from: @(#)vmparam.h 5.9 (Berkeley) 5/12/91 */ #ifdef __i386__ @@ -74,12 +72,12 @@ #endif /* - * We provide a machine specific single page allocator through the use - * of the direct mapped segment. This uses 2MB pages for reduced + * We provide a single page allocator through the use of the + * direct mapped segment. This uses 2MB pages for reduced * TLB pressure. */ #if !defined(KASAN) && !defined(KMSAN) -#define UMA_MD_SMALL_ALLOC +#define UMA_USE_DMAP #endif /* @@ -91,19 +89,21 @@ * The number of PHYSSEG entries must be one greater than the number * of phys_avail entries because the phys_avail entry that spans the * largest physical address that is accessible by ISA DMA is split - * into two PHYSSEG entries. + * into two PHYSSEG entries. */ #define VM_PHYSSEG_MAX 63 /* - * Create two free page pools: VM_FREEPOOL_DEFAULT is the default pool - * from which physical pages are allocated and VM_FREEPOOL_DIRECT is - * the pool from which physical pages for page tables and small UMA - * objects are allocated. + * Create three free page pools: VM_FREEPOOL_DEFAULT is the default pool from + * which physical pages are allocated and VM_FREEPOOL_DIRECT is the pool from + * which physical pages for page tables and small UMA objects are allocated. + * VM_FREEPOOL_LAZYINIT is a special-purpose pool that is populated only during + * boot and is used to implement deferred initialization of page structures. */ -#define VM_NFREEPOOL 2 -#define VM_FREEPOOL_DEFAULT 0 -#define VM_FREEPOOL_DIRECT 1 +#define VM_NFREEPOOL 3 +#define VM_FREEPOOL_LAZYINIT 0 +#define VM_FREEPOOL_DEFAULT 1 +#define VM_FREEPOOL_DIRECT 2 /* * Create up to three free page lists: VM_FREELIST_DMA32 is for physical pages @@ -149,10 +149,6 @@ #define VM_LEVEL_0_ORDER 9 #endif -#ifdef SMP -#define PA_LOCK_COUNT 256 -#endif - /* * Kernel physical load address for non-UEFI boot and for legacy UEFI loader. * Newer UEFI loader loads kernel anywhere below 4G, with memory allocated @@ -167,6 +163,7 @@ * Virtual addresses of things. Derived from the page directory and * page table indexes from pmap.h for precision. * + * LA48: * 0x0000000000000000 - 0x00007fffffffffff user map * 0x0000800000000000 - 0xffff7fffffffffff does not exist (hole) * 0xffff800000000000 - 0xffff804020100fff recursive page table (512GB slot) @@ -179,32 +176,38 @@ * 0xfffffc0000000000 - 0xfffffdffffffffff 2TB KMSAN shadow map, optional * 0xfffffe0000000000 - 0xffffffffffffffff 2TB kernel map * + * LA57: + * 0x0000000000000000 - 0x00ffffffffffffff user map + * 0x0100000000000000 - 0xf0ffffffffffffff does not exist (hole) + * 0xff00000000000000 - 0xff00ffffffffffff recursive page table (2048TB slot) + * 0xff01000000000000 - 0xff20ffffffffffff direct map (32 x 2048TB slots) + * 0xff21000000000000 - 0xff40ffffffffffff large map + * 0xff41000000000000 - 0xffff7fffffffffff unused + * 0xffff800000000000 - 0xfffff5ffffffffff unused (start of kernel pml4 entry) + * 0xfffff60000000000 - 0xfffff7ffffffffff 2TB KMSAN origin map, optional + * 0xfffff78000000000 - 0xfffff7bfffffffff 512GB KASAN shadow map, optional + * 0xfffff80000000000 - 0xfffffbffffffffff 4TB unused + * 0xfffffc0000000000 - 0xfffffdffffffffff 2TB KMSAN shadow map, optional + * 0xfffffe0000000000 - 0xffffffffffffffff 2TB kernel map + * * Within the kernel map: * * 0xfffffe0000000000 vm_page_array * 0xffffffff80000000 KERNBASE */ -#define VM_MIN_KERNEL_ADDRESS KV4ADDR(KPML4BASE, 0, 0, 0) -#define VM_MAX_KERNEL_ADDRESS KV4ADDR(KPML4BASE + NKPML4E - 1, \ - NPDPEPG-1, NPDEPG-1, NPTEPG-1) - -#define DMAP_MIN_ADDRESS KV4ADDR(DMPML4I, 0, 0, 0) -#define DMAP_MAX_ADDRESS KV4ADDR(DMPML4I + NDMPML4E, 0, 0, 0) - -#define KASAN_MIN_ADDRESS KV4ADDR(KASANPML4I, 0, 0, 0) -#define KASAN_MAX_ADDRESS KV4ADDR(KASANPML4I + NKASANPML4E, 0, 0, 0) +#define VM_MIN_KERNEL_ADDRESS_LA48 KV4ADDR(KPML4BASE, 0, 0, 0) +#define VM_MIN_KERNEL_ADDRESS kva_layout.km_low +#define VM_MAX_KERNEL_ADDRESS kva_layout.km_high -#define KMSAN_SHAD_MIN_ADDRESS KV4ADDR(KMSANSHADPML4I, 0, 0, 0) -#define KMSAN_SHAD_MAX_ADDRESS KV4ADDR(KMSANSHADPML4I + NKMSANSHADPML4E, \ - 0, 0, 0) +#define KASAN_MIN_ADDRESS (kva_layout.kasan_shadow_low) +#define KASAN_MAX_ADDRESS (kva_layout.kasan_shadow_high) -#define KMSAN_ORIG_MIN_ADDRESS KV4ADDR(KMSANORIGPML4I, 0, 0, 0) -#define KMSAN_ORIG_MAX_ADDRESS KV4ADDR(KMSANORIGPML4I + NKMSANORIGPML4E, \ - 0, 0, 0) +#define KMSAN_SHAD_MIN_ADDRESS (kva_layout.kmsan_shadow_low) +#define KMSAN_SHAD_MAX_ADDRESS (kva_layout.kmsan_shadow_high) -#define LARGEMAP_MIN_ADDRESS KV4ADDR(LMSPML4I, 0, 0, 0) -#define LARGEMAP_MAX_ADDRESS KV4ADDR(LMEPML4I + 1, 0, 0, 0) +#define KMSAN_ORIG_MIN_ADDRESS (kva_layout.kmsan_origin_low) +#define KMSAN_ORIG_MAX_ADDRESS (kva_layout.kmsan_origin_high) /* * Formally kernel mapping starts at KERNBASE, but kernel linker @@ -243,21 +246,21 @@ * vt fb startup needs to be reworked. */ #define PHYS_IN_DMAP(pa) (dmaplimit == 0 || (pa) < dmaplimit) -#define VIRT_IN_DMAP(va) ((va) >= DMAP_MIN_ADDRESS && \ - (va) < (DMAP_MIN_ADDRESS + dmaplimit)) +#define VIRT_IN_DMAP(va) \ + ((va) >= kva_layout.dmap_low && (va) < kva_layout.dmap_low + dmaplimit) #define PMAP_HAS_DMAP 1 -#define PHYS_TO_DMAP(x) ({ \ +#define PHYS_TO_DMAP(x) __extension__ ({ \ KASSERT(PHYS_IN_DMAP(x), \ ("physical address %#jx not covered by the DMAP", \ (uintmax_t)x)); \ - (x) | DMAP_MIN_ADDRESS; }) + (x) + kva_layout.dmap_low; }) -#define DMAP_TO_PHYS(x) ({ \ +#define DMAP_TO_PHYS(x) __extension__ ({ \ KASSERT(VIRT_IN_DMAP(x), \ ("virtual address %#jx not covered by the DMAP", \ (uintmax_t)x)); \ - (x) & ~DMAP_MIN_ADDRESS; }) + (x) - kva_layout.dmap_low; }) /* * amd64 maps the page array into KVA so that it can be more easily @@ -278,7 +281,7 @@ */ #ifndef VM_KMEM_SIZE_MAX #define VM_KMEM_SIZE_MAX ((VM_MAX_KERNEL_ADDRESS - \ - VM_MIN_KERNEL_ADDRESS + 1) * 3 / 5) + kva_layout.km_low + 1) * 3 / 5) #endif /* initial pagein size of beginning of executable file */ @@ -296,7 +299,8 @@ /* * Need a page dump array for minidump. */ -#define MINIDUMP_PAGE_TRACKING 1 +#define MINIDUMP_PAGE_TRACKING 1 +#define MINIDUMP_STARTUP_PAGE_TRACKING 1 #endif /* _MACHINE_VMPARAM_H_ */ diff --git a/lib/libc/include/x86_64-freebsd-none/stdarg.h b/lib/libc/include/x86_64-freebsd-none/stdarg.h deleted file mode 100644 index 20289894d6be..000000000000 --- a/lib/libc/include/x86_64-freebsd-none/stdarg.h +++ /dev/null @@ -1,5 +0,0 @@ -/*- - * This file is in the public domain. - */ - -#include \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/_float.h b/lib/libc/include/x86_64-openbsd-none/amd64/_float.h new file mode 100644 index 000000000000..8627bb549920 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/_float.h @@ -0,0 +1,71 @@ +/* $OpenBSD: _float.h,v 1.1 2012/06/26 16:12:43 deraadt Exp $ */ + +/* + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE__FLOAT_H_ +#define _MACHINE__FLOAT_H_ + +#define __FLT_RADIX 2 /* b */ +#define __FLT_ROUNDS __flt_rounds() +#define __FLT_EVAL_METHOD 0 /* no promotions */ + +#define __FLT_MANT_DIG 24 /* p */ +#define __FLT_EPSILON 1.19209290E-07F /* b**(1-p) */ +#define __FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ +#define __FLT_MIN_EXP (-125) /* emin */ +#define __FLT_MIN 1.17549435E-38F /* b**(emin-1) */ +#define __FLT_MIN_10_EXP (-37) /* ceil(log10(b**(emin-1))) */ +#define __FLT_MAX_EXP 128 /* emax */ +#define __FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ +#define __FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ + +#define __DBL_MANT_DIG 53 +#define __DBL_EPSILON 2.2204460492503131E-16 +#define __DBL_DIG 15 +#define __DBL_MIN_EXP (-1021) +#define __DBL_MIN 2.2250738585072014E-308 +#define __DBL_MIN_10_EXP (-307) +#define __DBL_MAX_EXP 1024 +#define __DBL_MAX 1.7976931348623157E+308 +#define __DBL_MAX_10_EXP 308 + +#define __LDBL_MANT_DIG 64 +#define __LDBL_EPSILON 1.08420217248550443401e-19L +#define __LDBL_DIG 18 +#define __LDBL_MIN_EXP (-16381) +#define __LDBL_MIN 3.36210314311209350626e-4932L +#define __LDBL_MIN_10_EXP (-4931) +#define __LDBL_MAX_EXP 16384 +#define __LDBL_MAX 1.18973149535723176502e+4932L +#define __LDBL_MAX_10_EXP 4932 + +#define __DECIMAL_DIG 21 + +#endif /* _MACHINE__FLOAT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/_types.h b/lib/libc/include/x86_64-openbsd-none/amd64/_types.h new file mode 100644 index 000000000000..6d48c5e0337a --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/_types.h @@ -0,0 +1,140 @@ +/* $OpenBSD: _types.h,v 1.19 2023/07/02 19:02:27 cheloha Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.3 (Berkeley) 1/5/94 + * @(#)ansi.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _MACHINE__TYPES_H_ +#define _MACHINE__TYPES_H_ + +/* + * _ALIGN(p) rounds p (pointer or byte index) up to a correctly-aligned + * value for all data types (int, long, ...). The result is an + * unsigned long and must be cast to any desired pointer type. + * + * _ALIGNED_POINTER is a boolean macro that checks whether an address + * is valid to fetch data elements of type t from on this architecture. + * This does not reflect the optimal alignment, just the possibility + * (within reasonable limits). + */ +#define _ALIGNBYTES (sizeof(long) - 1) +#define _STACKALIGNBYTES 15 +#define _ALIGN(p) (((unsigned long)(p) + _ALIGNBYTES) &~_ALIGNBYTES) +#define _ALIGNED_POINTER(p,t) 1 +#define _MAX_PAGE_SHIFT 12 /* same as PAGE_SHIFT */ + +#if defined(_KERNEL) +typedef struct label_t { + long val[8]; +} label_t; +#endif + +/* 7.18.1.1 Exact-width integer types */ +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short __int16_t; +typedef unsigned short __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; +typedef long long __int64_t; +typedef unsigned long long __uint64_t; + +/* 7.18.1.2 Minimum-width integer types */ +typedef __int8_t __int_least8_t; +typedef __uint8_t __uint_least8_t; +typedef __int16_t __int_least16_t; +typedef __uint16_t __uint_least16_t; +typedef __int32_t __int_least32_t; +typedef __uint32_t __uint_least32_t; +typedef __int64_t __int_least64_t; +typedef __uint64_t __uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types */ +typedef __int32_t __int_fast8_t; +typedef __uint32_t __uint_fast8_t; +typedef __int32_t __int_fast16_t; +typedef __uint32_t __uint_fast16_t; +typedef __int32_t __int_fast32_t; +typedef __uint32_t __uint_fast32_t; +typedef __int64_t __int_fast64_t; +typedef __uint64_t __uint_fast64_t; +#define __INT_FAST8_MIN INT32_MIN +#define __INT_FAST16_MIN INT32_MIN +#define __INT_FAST32_MIN INT32_MIN +#define __INT_FAST64_MIN INT64_MIN +#define __INT_FAST8_MAX INT32_MAX +#define __INT_FAST16_MAX INT32_MAX +#define __INT_FAST32_MAX INT32_MAX +#define __INT_FAST64_MAX INT64_MAX +#define __UINT_FAST8_MAX UINT32_MAX +#define __UINT_FAST16_MAX UINT32_MAX +#define __UINT_FAST32_MAX UINT32_MAX +#define __UINT_FAST64_MAX UINT64_MAX + +/* 7.18.1.4 Integer types capable of holding object pointers */ +typedef long __intptr_t; +typedef unsigned long __uintptr_t; + +/* 7.18.1.5 Greatest-width integer types */ +typedef __int64_t __intmax_t; +typedef __uint64_t __uintmax_t; + +/* Register size */ +typedef long __register_t; + +/* VM system types */ +typedef unsigned long __vaddr_t; +typedef unsigned long __paddr_t; +typedef unsigned long __vsize_t; +typedef unsigned long __psize_t; + +/* Standard system types */ +typedef double __double_t; +typedef float __float_t; +typedef long __ptrdiff_t; +typedef unsigned long __size_t; +typedef long __ssize_t; +#if defined(__GNUC__) && __GNUC__ >= 3 +typedef __builtin_va_list __va_list; +#else +typedef char * __va_list; +#endif + +/* Wide character support types */ +#ifndef __cplusplus +typedef int __wchar_t; +#endif +typedef int __wint_t; +typedef int __rune_t; +typedef void * __wctrans_t; +typedef void * __wctype_t; + +#endif /* _MACHINE__TYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/apicvar.h b/lib/libc/include/x86_64-openbsd-none/amd64/apicvar.h new file mode 100644 index 000000000000..90c3cd3bc140 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/apicvar.h @@ -0,0 +1,54 @@ +/* $OpenBSD: apicvar.h,v 1.4 2025/09/05 16:57:48 kettenis Exp $ */ +/* $NetBSD: apicvar.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_APICVAR_H_ +#define _MACHINE_APICVAR_H_ + +#include + +struct apic_attach_args { + const char *aaa_name; + int apic_id; + int apic_version; + int flags; +#define IOAPIC_PICMODE 0x01 +#define IOAPIC_VWIRE 0x02 + bus_space_tag_t apic_memt; + bus_addr_t apic_address; + int apic_vecbase; +}; + +void apic_format_redir(char *, char *, int, u_int32_t, u_int32_t); + +#endif /* !_MACHINE_APICVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/apmvar.h b/lib/libc/include/x86_64-openbsd-none/amd64/apmvar.h new file mode 100644 index 000000000000..7407c1c6cf3b --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/apmvar.h @@ -0,0 +1,303 @@ +/* XXX - DSR */ +/* $OpenBSD: apmvar.h,v 1.8 2019/01/22 02:36:30 phessler Exp $ */ + +/* + * Copyright (c) 1995 John T. Kohl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _MACHINE_APMVAR_H_ +#define _MACHINE_APMVAR_H_ + +#include + +/* Advanced Power Management (v1.0 and v1.1 specification) + * functions/defines/etc. + */ + +#define APM_VERSION 0x0102 + +/* + * APM info word from boot loader + */ +#define APM_16BIT_SUPPORTED 0x00010000 +#define APM_32BIT_SUPPORTED 0x00020000 +#define APM_IDLE_SLOWS 0x00040000 +#define APM_BIOS_PM_DISABLED 0x00080000 +#define APM_BIOS_PM_DISENGAGED 0x00100000 +#define APM_MAJOR(f) (((f) >> 8) & 0xff) +#define APM_MINOR(f) ((f) & 0xff) +#define APM_VERMASK 0x0000ffff +#define APM_NOCLI 0x00010000 +#define APM_BEBATT 0x00020000 + +/* APM error codes */ +#define APM_ERR_CODE(regs) (((regs)->ax & 0xff00) >> 8) +#define APM_ERR_PM_DISABLED 0x01 +#define APM_ERR_REALALREADY 0x02 +#define APM_ERR_NOTCONN 0x03 +#define APM_ERR_16ALREADY 0x05 +#define APM_ERR_16NOTSUPP 0x06 +#define APM_ERR_32ALREADY 0x07 +#define APM_ERR_32NOTSUPP 0x08 +#define APM_ERR_UNRECOG_DEV 0x09 +#define APM_ERR_ERANGE 0x0A +#define APM_ERR_NOTENGAGED 0x0B +#define APM_ERR_EOPNOSUPP 0x0C +#define APM_ERR_RTIMER_DISABLED 0x0D +#define APM_ERR_UNABLE 0x60 +#define APM_ERR_NOEVENTS 0x80 +#define APM_ERR_NOT_PRESENT 0x86 + +#define APM_DEV_APM_BIOS 0x0000 +#define APM_DEV_ALLDEVS 0x0001 +/* device classes are high byte; device IDs go in low byte */ +#define APM_DEV_DISPLAY(x) (0x0100|((x)&0xff)) +#define APM_DEV_DISK(x) (0x0200|((x)&0xff)) +#define APM_DEV_PARALLEL(x) (0x0300|((x)&0xff)) +#define APM_DEV_SERIAL(x) (0x0400|((x)&0xff)) +#define APM_DEV_NETWORK(x) (0x0500|((x)&0xff)) +#define APM_DEV_PCMCIA(x) (0x0600|((x)&0xff)) +#define APM_DEV_BATTERIES(x) (0x8000|((x)&0xff)) +#define APM_DEV_ALLUNITS 0xff +/* 0x8100-0xDFFF - reserved */ +/* 0xE000-0xEFFF - OEM-defined */ +/* 0xF000-0xFFFF - reserved */ + +#define APM_INSTCHECK 0x5300 /* int15 only */ +#define APM_16BIT_SUPPORT 0x01 +#define APM_32BIT_SUPPORT 0x02 +#define APM_CPUIDLE_SLOW 0x04 +#define APM_DISABLED 0x08 +#define APM_DISENGAGED 0x10 + +#define APM_REAL_CONNECT 0x5301 /* int15 only */ +#define APM_PROT16_CONNECT 0x5302 /* int15 only */ +#define APM_PROT32_CONNECT 0x5303 /* int15 only */ +#define APM_DISCONNECT 0x5304 /* %bx = APM_DEV_APM_BIOS */ + +#define APM_CPU_IDLE 0x5305 +#define APM_CPU_BUSY 0x5306 + +#define APM_SET_PWR_STATE 0x5307 +#define APM_SYS_READY 0x0000 /* %cx */ +#define APM_SYS_STANDBY 0x0001 +#define APM_SYS_SUSPEND 0x0002 +#define APM_SYS_OFF 0x0003 +#define APM_LASTREQ_INPROG 0x0004 +#define APM_LASTREQ_REJECTED 0x0005 +/* 0x0006 - 0x001f Reserved system states */ +/* 0x0020 - 0x003f OEM-defined system states */ +/* 0x0040 - 0x007f OEM-defined device states */ +/* 0x0080 - 0xffff Reserved device states */ + +/* system standby is device ID (%bx) 0x0001, APM_SYS_STANDBY */ +/* system suspend is device ID (%bx) 0x0001, APM_SYS_SUSPEND */ + +#define APM_PWR_MGT_ENABLE 0x5308 +#define APM_MGT_ALL 0xffff /* %bx */ +#define APM_MGT_DISABLE 0x0 /* %cx */ +#define APM_MGT_ENABLE 0x1 + +#define APM_SYSTEM_DEFAULTS 0x5309 +#define APM_DEFAULTS_ALL 0xffff /* %bx */ + +#define APM_POWER_STATUS 0x530a +#define APM_AC_OFF 0x00 +#define APM_AC_ON 0x01 +#define APM_AC_BACKUP 0x02 +#define APM_AC_UNKNOWN 0xff +#define APM_BATT_HIGH 0x00 +#define APM_BATT_LOW 0x01 +#define APM_BATT_CRITICAL 0x02 +#define APM_BATT_CHARGING 0x03 +#define APM_BATT_UNKNOWN 0xff +#define APM_BATT_FLAG_HIGH 0x01 +#define APM_BATT_FLAG_LOW 0x02 +#define APM_BATT_FLAG_CRITICAL 0x04 +#define APM_BATT_FLAG_CHARGING 0x08 +#define APM_BATT_FLAG_NOBATTERY 0x10 +#define APM_BATT_FLAG_NOSYSBATT 0x80 +#define APM_BATT_LIFE_UNKNOWN 0xff +#define BATT_STATE(regp) ((regp)->bx & 0xff) +#define BATT_FLAGS(regp) (((regp)->cx & 0xff00) >> 8) +#define AC_STATE(regp) (((regp)->bx & 0xff00) >> 8) +#define BATT_LIFE(regp) ((regp)->cx & 0xff) /* in % */ +/* Return time in minutes. According to the APM 1.2 spec: + DX = Remaining battery life -- time units + Bit 15 = 0 Time units are seconds + = 1 Time units are minutes + Bits 14-0 = Number of seconds or minutes */ +#define BATT_REMAINING(regp) (((regp)->dx & 0x8000) ? \ + ((regp)->dx & 0x7fff) : \ + ((regp)->dx & 0x7fff)/60) +#define BATT_REM_VALID(regp) (((regp)->dx & 0xffff) != 0xffff) +#define BATT_COUNT(regp) ((regp)->si) + +#define APM_GET_PM_EVENT 0x530b +#define APM_NOEVENT 0x0000 +#define APM_STANDBY_REQ 0x0001 /* %bx on return */ +#define APM_SUSPEND_REQ 0x0002 +#define APM_NORMAL_RESUME 0x0003 +#define APM_CRIT_RESUME 0x0004 /* suspend/resume happened + without us */ +#define APM_BATTERY_LOW 0x0005 +#define APM_POWER_CHANGE 0x0006 +#define APM_UPDATE_TIME 0x0007 +#define APM_CRIT_SUSPEND_REQ 0x0008 +#define APM_USER_STANDBY_REQ 0x0009 +#define APM_USER_SUSPEND_REQ 0x000A +#define APM_SYS_STANDBY_RESUME 0x000B +#define APM_CAPABILITY_CHANGE 0x000C /* apm v1.2 */ +/* 0x000d - 0x00ff Reserved system events */ +#define APM_USER_HIBERNATE_REQ 0x000D +/* 0x0100 - 0x01ff Reserved device events */ +/* 0x0200 - 0x02ff OEM-defined APM events */ +/* 0x0300 - 0xffff Reserved */ +#define APM_EVENT_MASK 0xffff + +#define APM_EVENT_COMPOSE(t,i) ((((i) & 0x7fff) << 16)|((t) & APM_EVENT_MASK)) +#define APM_EVENT_TYPE(e) ((e) & APM_EVENT_MASK) +#define APM_EVENT_INDEX(e) ((e) >> 16) + +#define APM_GET_POWER_STATE 0x530c +#define APM_DEVICE_MGMT_ENABLE 0x530d + +#define APM_DRIVER_VERSION 0x530e +/* %bx should be DEV value (APM_DEV_APM_BIOS) + %ch = driver major vno + %cl = driver minor vno + return: %ah = conn major; %al = conn minor + */ +#define APM_CONN_MINOR(regp) ((regp)->ax & 0xff) +#define APM_CONN_MAJOR(regp) (((regp)->ax & 0xff00) >> 8) + +#define APM_PWR_MGT_ENGAGE 0x530F +#define APM_MGT_DISENGAGE 0x0 /* %cx */ +#define APM_MGT_ENGAGE 0x1 + +/* %bx - APM_DEV_APM_BIOS + * %bl - number of batteries + * %cx - capabilities + */ +#define APM_GET_CAPABILITIES 0x5310 +#define APM_NBATTERIES(regp) ((regp)->bx) +#define APM_GLOBAL_STANDBY 0x0001 +#define APM_GLOBAL_SUSPEND 0x0002 +#define APM_RTIMER_STANDBY 0x0004 /* resume time wakes up */ +#define APM_RTIMER_SUSPEND 0x0008 +#define APM_IRRING_STANDBY 0x0010 /* internal ring wakes up */ +#define APM_IRRING_SUSPEND 0x0020 +#define APM_PCCARD_STANDBY 0x0040 /* pccard wakes up */ +#define APM_PCCARD_SUSPEND 0x0080 + +/* %bx - APM_DEV_APM_BIOS + * %cl - function + * for %cl=2 (set resume timer) + * %ch - seconds in BCD + * %dh - hours in BCD + * %dl - minutes in BCD + * %si - month in BCD (high), day in BCD (low) + * %di - year in BCD + */ +#define APM_RESUME_TIMER 0x5311 +#define APM_RT_DISABLE 0x0 +#define APM_RT_GET 0x1 +#define APM_RT_SET 0x2 + +/* %bx - APM_DEV_APM_BIOS + * %cx - function + */ +#define APM_RESUME_ON_RING 0x5312 +#define APM_ROR_DISABLE 0x0 +#define APM_ROR_ENABLE 0x1 +#define APM_ROR_STATUS 0x2 + +/* %bx - APM_EDV_APM_BIOS + * %cx - function + */ +#define APM_INACTIVITY_TIMER 0x5313 +#define APM_IT_DISABLE 0x0 +#define APM_IT_ENABLE 0x1 +#define APM_IT_STATUS 0x2 + +/* %bh - function */ +#define APM_OEM 0x5380 +#define APM_OEM_INSTCHECK 0x7f /* %bx - OEM ID */ + +/* + * LP (Laptop Package) + * + * Copyright (C) 1994 by HOSOKAWA Tatsumi + * + * This software may be used, modified, copied, and distributed, in + * both source and binary form provided that the above copyright and + * these terms are retained. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with its + * use. + * + * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) + */ + +#define APM_BATTERY_ABSENT 4 + +struct apm_power_info { + u_char battery_state; + u_char ac_state; + u_char battery_life; + u_char spare1; + u_int minutes_left; /* estimate */ + u_int spare2[6]; +}; + +struct apm_ctl { + u_int dev; + u_int mode; +}; + +#define APM_IOC_REJECT _IOW('A', 0, struct apm_event_info) /* reject request # */ +#define APM_IOC_STANDBY _IO('A', 1) /* put system into standby */ +#define APM_IOC_SUSPEND _IO('A', 2) /* put system into suspend */ +#define APM_IOC_GETPOWER _IOR('A', 3, struct apm_power_info) /* fetch battery state */ +#define APM_IOC_DEV_CTL _IOW('A', 5, struct apm_ctl) /* put device into mode */ +#define APM_IOC_PRN_CTL _IOW('A', 6, int ) /* driver power status msg */ +#define APM_PRINT_ON 0 /* driver power status displayed */ +#define APM_PRINT_OFF 1 /* driver power status not displayed */ +#define APM_PRINT_PCT 2 /* driver power status only displayed + if the percentage changes */ +#define APM_IOC_STANDBY_REQ _IO('A', 7) /* request standby */ +#define APM_IOC_SUSPEND_REQ _IO('A', 8) /* request suspend */ +#define APM_IOC_HIBERNATE _IO('A', 9) /* put system into hibernate */ + +#ifdef _KERNEL +extern void apm_cpu_busy(void); +extern void apm_cpu_idle(void); +extern void apminit(void); +int apm_set_powstate(u_int devid, u_int powstate); +#endif /* _KERNEL */ + +#endif /* _MACHINE_APMVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/asm.h b/lib/libc/include/x86_64-openbsd-none/amd64/asm.h new file mode 100644 index 000000000000..64acd3a4f0a3 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/asm.h @@ -0,0 +1,196 @@ +/* $OpenBSD: asm.h,v 1.24 2023/04/17 00:02:14 deraadt Exp $ */ +/* $NetBSD: asm.h,v 1.2 2003/05/02 18:05:47 yamt Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)asm.h 5.5 (Berkeley) 5/7/91 + */ + +#ifndef _MACHINE_ASM_H_ +#define _MACHINE_ASM_H_ + +#ifdef __PIC__ +#define PIC_PLT(x) x@PLT +#define PIC_GOT(x) x@GOTPCREL(%rip) +#else +#define PIC_PLT(x) x +#define PIC_GOT(x) x +#endif + +# define _C_LABEL(x) x +#define _ASM_LABEL(x) x + +#define CVAROFF(x,y) (x+y)(%rip) + +#ifdef __STDC__ +# define __CONCAT(x,y) x ## y +# define __STRING(x) #x +#else +# define __CONCAT(x,y) x/**/y +# define __STRING(x) "x" +#endif + +/* let kernels and others override entrypoint alignment */ +#ifndef _ALIGN_TEXT +#define _ALIGN_TEXT .align 16, 0x90 +#endif +#define _ALIGN_TRAPS .align 16, 0xcc + +#define _FENTRY(x) .type x,@function; x: + +/* NB == No Binding: use .globl or .weak as necessary */ +#define NENTRY_NB(x) \ + .text; _ALIGN_TEXT; _FENTRY(x) +#define _ENTRY_NB(x) \ + .text; _ALIGN_TRAPS; _FENTRY(x) +#define _ENTRY(x) .globl x; _ENTRY_NB(x) +#define _NENTRY(x) .globl x; NENTRY_NB(x) + +#ifdef _KERNEL +#define KUTEXT .section .kutext, "ax", @progbits + +#define KUTEXT_PAGE_START .pushsection .kutext.page, "a", @progbits +#define KTEXT_PAGE_START .pushsection .ktext.page, "ax", @progbits +#define KUTEXT_PAGE_END .popsection +#define KTEXT_PAGE_END .popsection + +#define IDTVEC(name) \ + KUTEXT; _ALIGN_TRAPS; IDTVEC_NOALIGN(name); endbr64 +#define GENTRY(x) .globl x; _FENTRY(x) +#define IDTVEC_NOALIGN(name) GENTRY(X ## name) +#define IDTVEC_ALIAS(alias,sym) \ + .global X ## alias; \ + X ## alias = X ## sym; +#define KIDTVEC(name) \ + .text; _ALIGN_TRAPS; IDTVEC_NOALIGN(name); endbr64 +#define KIDTVEC_FALLTHROUGH(name) \ + _ALIGN_TEXT; IDTVEC_NOALIGN(name) +#define KUENTRY(x) \ + KUTEXT; _ALIGN_TRAPS; GENTRY(x) + +/* Return stack refill, to prevent speculation attacks on natural returns */ +#define RET_STACK_REFILL_WITH_RCX \ + mov $8,%rcx ; \ + _ALIGN_TEXT ; \ + 3: call 5f ; \ + 4: pause ; \ + lfence ; \ + call 4b ; \ + _ALIGN_TRAPS ; \ + 5: call 7f ; \ + 6: pause ; \ + lfence ; \ + call 6b ; \ + _ALIGN_TRAPS ; \ + 7: loop 3b ; \ + add $(16*8),%rsp + +#endif /* _KERNEL */ + +#ifdef __STDC__ +#define CPUVAR(off) %gs:CPU_INFO_ ## off +#else +#define CPUVAR(off) %gs:CPU_INFO_/**/off +#endif + + +#if defined(PROF) || defined(GPROF) +# define _PROF_PROLOGUE \ + pushq %rbp; leaq (%rsp),%rbp; call PIC_PLT(__mcount); popq %rbp +#else +# define _PROF_PROLOGUE +#endif + +#if defined(_RET_PROTECTOR) +# define RETGUARD_SETUP_OFF(x, reg, off) \ + RETGUARD_SYMBOL(x); \ + movq (__retguard_ ## x)(%rip), %reg; \ + xorq off(%rsp), %reg +# define RETGUARD_SETUP(x, reg) \ + RETGUARD_SETUP_OFF(x, reg, 0) +# define RETGUARD_CHECK(x, reg) \ + xorq (%rsp), %reg; \ + cmpq (__retguard_ ## x)(%rip), %reg; \ + je 66f; \ + int3; int3; \ + .zero (0xf - ((. + 3 - x) & 0xf)), 0xcc; \ +66: +# define RETGUARD_PUSH(reg) \ + pushq %reg +# define RETGUARD_POP(reg) \ + popq %reg +# define RETGUARD_SYMBOL(x) \ + .ifndef __retguard_ ## x; \ + .hidden __retguard_ ## x; \ + .type __retguard_ ## x,@object; \ + .pushsection .openbsd.randomdata.retguard,"aw",@progbits; \ + .weak __retguard_ ## x; \ + .p2align 3; \ + __retguard_ ## x: ; \ + .quad 0; \ + .size __retguard_ ## x, 8; \ + .popsection; \ + .endif +#else +# define RETGUARD_SETUP_OFF(x, reg, off) +# define RETGUARD_SETUP(x, reg) +# define RETGUARD_CHECK(x, reg) +# define RETGUARD_PUSH(reg) +# define RETGUARD_POP(reg) +# define RETGUARD_SYMBOL(x) +#endif + +#define ENTRY(y) _ENTRY(y); endbr64; _PROF_PROLOGUE +#define NENTRY(y) _NENTRY(y) +#define ASENTRY(y) _NENTRY(y); endbr64; _PROF_PROLOGUE +#define ENTRY_NB(y) _ENTRY_NB(y); endbr64; _PROF_PROLOGUE +#define END(y) .size y, . - y + +#define STRONG_ALIAS(alias,sym) \ + .global alias; \ + alias = sym +#define WEAK_ALIAS(alias,sym) \ + .weak alias; \ + alias = sym + +/* generic retpoline ("return trampoline") generator */ +#define JMP_RETPOLINE(reg) \ + call 69f ; \ + 68: pause ; \ + lfence ; \ + jmp 68b ; \ + _ALIGN_TRAPS ; \ + 69: mov %reg,(%rsp) ; \ + ret ; \ + lfence + +#endif /* !_MACHINE_ASM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/atomic.h b/lib/libc/include/x86_64-openbsd-none/amd64/atomic.h new file mode 100644 index 000000000000..329eccec1c44 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/atomic.h @@ -0,0 +1,325 @@ +/* $OpenBSD: atomic.h,v 1.23 2023/11/11 18:47:02 jca Exp $ */ +/* $NetBSD: atomic.h,v 1.1 2003/04/26 18:39:37 fvdl Exp $ */ + +/* + * Copyright 2002 (c) Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Frank van der Linden for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_ATOMIC_H_ +#define _MACHINE_ATOMIC_H_ + +/* + * Perform atomic operations on memory. Should be atomic with respect + * to interrupts and multiple processors. + * + * void atomic_setbits_int(volatile u_int *a, u_int mask) { *a |= mask; } + * void atomic_clearbits_int(volatile u_int *a, u_int mask) { *a &= ~mask; } + */ + +#if !defined(_LOCORE) + +#if defined(MULTIPROCESSOR) || !defined(_KERNEL) +#define _LOCK "lock" +#else +#define _LOCK +#endif + +static inline unsigned int +_atomic_cas_uint(volatile unsigned int *p, unsigned int e, unsigned int n) +{ + __asm volatile(_LOCK " cmpxchgl %2, %1" + : "=a" (n), "=m" (*p) + : "r" (n), "a" (e), "m" (*p)); + + return (n); +} +#define atomic_cas_uint(_p, _e, _n) _atomic_cas_uint((_p), (_e), (_n)) + +static inline unsigned long +_atomic_cas_ulong(volatile unsigned long *p, unsigned long e, unsigned long n) +{ + __asm volatile(_LOCK " cmpxchgq %2, %1" + : "=a" (n), "=m" (*p) + : "r" (n), "a" (e), "m" (*p)); + + return (n); +} +#define atomic_cas_ulong(_p, _e, _n) _atomic_cas_ulong((_p), (_e), (_n)) + +static inline void * +_atomic_cas_ptr(volatile void *p, void *e, void *n) +{ + __asm volatile(_LOCK " cmpxchgq %2, %1" + : "=a" (n), "=m" (*(unsigned long *)p) + : "r" (n), "a" (e), "m" (*(unsigned long *)p)); + + return (n); +} +#define atomic_cas_ptr(_p, _e, _n) _atomic_cas_ptr((_p), (_e), (_n)) + +static inline unsigned int +_atomic_swap_uint(volatile unsigned int *p, unsigned int n) +{ + __asm volatile("xchgl %0, %1" + : "=a" (n), "=m" (*p) + : "0" (n), "m" (*p)); + + return (n); +} +#define atomic_swap_uint(_p, _n) _atomic_swap_uint((_p), (_n)) +#define atomic_swap_32(_p, _n) _atomic_swap_uint((_p), (_n)) + +static inline unsigned long +_atomic_swap_ulong(volatile unsigned long *p, unsigned long n) +{ + __asm volatile("xchgq %0, %1" + : "=a" (n), "=m" (*p) + : "0" (n), "m" (*p)); + + return (n); +} +#define atomic_swap_ulong(_p, _n) _atomic_swap_ulong((_p), (_n)) + +static inline uint64_t +_atomic_swap_64(volatile uint64_t *p, uint64_t n) +{ + __asm volatile("xchgq %0, %1" + : "=a" (n), "=m" (*p) + : "0" (n), "m" (*p)); + + return (n); +} +#define atomic_swap_64(_p, _n) _atomic_swap_64((_p), (_n)) + +static inline void * +_atomic_swap_ptr(volatile void *p, void *n) +{ + __asm volatile("xchgq %0, %1" + : "=a" (n), "=m" (*(unsigned long *)p) + : "0" (n), "m" (*(unsigned long *)p)); + + return (n); +} +#define atomic_swap_ptr(_p, _n) _atomic_swap_ptr((_p), (_n)) + +static inline void +_atomic_inc_int(volatile unsigned int *p) +{ + __asm volatile(_LOCK " incl %0" + : "+m" (*p)); +} +#define atomic_inc_int(_p) _atomic_inc_int(_p) + +static inline void +_atomic_inc_long(volatile unsigned long *p) +{ + __asm volatile(_LOCK " incq %0" + : "+m" (*p)); +} +#define atomic_inc_long(_p) _atomic_inc_long(_p) + +static inline void +_atomic_dec_int(volatile unsigned int *p) +{ + __asm volatile(_LOCK " decl %0" + : "+m" (*p)); +} +#define atomic_dec_int(_p) _atomic_dec_int(_p) + +static inline void +_atomic_dec_long(volatile unsigned long *p) +{ + __asm volatile(_LOCK " decq %0" + : "+m" (*p)); +} +#define atomic_dec_long(_p) _atomic_dec_long(_p) + +static inline void +_atomic_add_int(volatile unsigned int *p, unsigned int v) +{ + __asm volatile(_LOCK " addl %1,%0" + : "+m" (*p) + : "a" (v)); +} +#define atomic_add_int(_p, _v) _atomic_add_int(_p, _v) + +static inline void +_atomic_add_long(volatile unsigned long *p, unsigned long v) +{ + __asm volatile(_LOCK " addq %1,%0" + : "+m" (*p) + : "a" (v)); +} +#define atomic_add_long(_p, _v) _atomic_add_long(_p, _v) + +static inline void +_atomic_sub_int(volatile unsigned int *p, unsigned int v) +{ + __asm volatile(_LOCK " subl %1,%0" + : "+m" (*p) + : "a" (v)); +} +#define atomic_sub_int(_p, _v) _atomic_sub_int(_p, _v) + +static inline void +_atomic_sub_long(volatile unsigned long *p, unsigned long v) +{ + __asm volatile(_LOCK " subq %1,%0" + : "+m" (*p) + : "a" (v)); +} +#define atomic_sub_long(_p, _v) _atomic_sub_long(_p, _v) + + +static inline unsigned long +_atomic_add_int_nv(volatile unsigned int *p, unsigned int v) +{ + unsigned int rv = v; + + __asm volatile(_LOCK " xaddl %0,%1" + : "+a" (rv), "+m" (*p)); + + return (rv + v); +} +#define atomic_add_int_nv(_p, _v) _atomic_add_int_nv(_p, _v) + +static inline unsigned long +_atomic_add_long_nv(volatile unsigned long *p, unsigned long v) +{ + unsigned long rv = v; + + __asm volatile(_LOCK " xaddq %0,%1" + : "+a" (rv), "+m" (*p)); + + return (rv + v); +} +#define atomic_add_long_nv(_p, _v) _atomic_add_long_nv(_p, _v) + +static inline unsigned long +_atomic_sub_int_nv(volatile unsigned int *p, unsigned int v) +{ + unsigned int rv = 0 - v; + + __asm volatile(_LOCK " xaddl %0,%1" + : "+a" (rv), "+m" (*p)); + + return (rv - v); +} +#define atomic_sub_int_nv(_p, _v) _atomic_sub_int_nv(_p, _v) + +static inline unsigned long +_atomic_sub_long_nv(volatile unsigned long *p, unsigned long v) +{ + unsigned long rv = 0 - v; + + __asm volatile(_LOCK " xaddq %0,%1" + : "+a" (rv), "+m" (*p)); + + return (rv - v); +} +#define atomic_sub_long_nv(_p, _v) _atomic_sub_long_nv(_p, _v) + +/* + * The AMD64 architecture is rather strongly ordered. When accessing + * normal write-back cacheable memory, only reads may be reordered with + * older writes to different locations. There are a few instructions + * (clfush, non-temporal move instructions) that obey weaker ordering + * rules, but those instructions will only be used in (inline) + * assembly code where we can add the necessary fence instructions + * ourselves. + */ + +#define __membar(_f) do { __asm volatile(_f ::: "memory"); } while (0) + +#if defined(MULTIPROCESSOR) || !defined(_KERNEL) +#define membar_enter() __membar("mfence") +#define membar_exit() __membar("") +#define membar_producer() __membar("") +#define membar_consumer() __membar("") +#define membar_sync() __membar("mfence") +#else +#define membar_enter() __membar("") +#define membar_exit() __membar("") +#define membar_producer() __membar("") +#define membar_consumer() __membar("") +#define membar_sync() __membar("") +#endif + +#define membar_enter_after_atomic() __membar("") +#define membar_exit_before_atomic() __membar("") + +#ifdef _KERNEL + +/* virtio needs MP membars even on SP kernels */ +#define virtio_membar_producer() __membar("") +#define virtio_membar_consumer() __membar("") +#define virtio_membar_sync() __membar("mfence") + +static __inline void +x86_atomic_setbits_u32(volatile u_int32_t *ptr, u_int32_t bits) +{ + __asm volatile(_LOCK " orl %1,%0" : "=m" (*ptr) : "ir" (bits)); +} + +static __inline void +x86_atomic_clearbits_u32(volatile u_int32_t *ptr, u_int32_t bits) +{ + __asm volatile(_LOCK " andl %1,%0" : "=m" (*ptr) : "ir" (~bits)); +} + +static __inline void +x86_atomic_setbits_u64(volatile u_int64_t *ptr, u_int64_t bits) +{ + __asm volatile(_LOCK " orq %1,%0" : "=m" (*ptr) : "er" (bits)); +} + +static __inline void +x86_atomic_clearbits_u64(volatile u_int64_t *ptr, u_int64_t bits) +{ + __asm volatile(_LOCK " andq %1,%0" : "=m" (*ptr) : "er" (~bits)); +} + +#define x86_atomic_testset_ul x86_atomic_testset_u64 +#define x86_atomic_setbits_ul x86_atomic_setbits_u64 +#define x86_atomic_clearbits_ul x86_atomic_clearbits_u64 + +#define atomic_setbits_int x86_atomic_setbits_u32 +#define atomic_clearbits_int x86_atomic_clearbits_u32 + +#endif /* _KERNEL */ + +#undef _LOCK + +#endif /* !defined(_LOCORE) */ +#endif /* _MACHINE_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/biosvar.h b/lib/libc/include/x86_64-openbsd-none/amd64/biosvar.h new file mode 100644 index 000000000000..523bb6255b8e --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/biosvar.h @@ -0,0 +1,283 @@ +/* $OpenBSD: biosvar.h,v 1.32 2023/09/08 20:47:22 kn Exp $ */ + +/* + * Copyright (c) 1997-1999 Michael Shalayeff + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES 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 MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BIOSVAR_H_ +#define _MACHINE_BIOSVAR_H_ + + /* some boxes put apm data seg in the 2nd page */ +#define BOOTARG_OFF (PAGE_SIZE * 2) +#define BOOTARG_LEN (PAGE_SIZE * 1) +#define BOOTBIOS_ADDR (0x7c00) +#define BOOTBIOS_MAXSEC ((1 << 28) - 1) + + /* BIOS configure flags */ +#define BIOSF_BIOS32 0x0001 +#define BIOSF_PCIBIOS 0x0002 +#define BIOSF_PROMSCAN 0x0004 +#define BIOSF_SMBIOS 0x0008 + +/* BIOS media ID */ +#define BIOSM_F320K 0xff /* floppy ds/sd 8 spt */ +#define BIOSM_F160K 0xfe /* floppy ss/sd 8 spt */ +#define BIOSM_F360K 0xfd /* floppy ds/sd 9 spt */ +#define BIOSM_F180K 0xfc /* floppy ss/sd 9 spt */ +#define BIOSM_ROMD 0xfa /* ROM disk */ +#define BIOSM_F120M 0xf9 /* floppy ds/hd 15 spt 5.25" */ +#define BIOSM_F720K 0xf9 /* floppy ds/dd 9 spt 3.50" */ +#define BIOSM_HD 0xf8 /* hard drive */ +#define BIOSM_F144K 0xf0 /* floppy ds/hd 18 spt 3.50" */ +#define BIOSM_OTHER 0xf0 /* any other */ + +/* + * BIOS memory maps + */ +#define BIOS_MAP_END 0x00 /* End of array XXX - special */ +#define BIOS_MAP_FREE 0x01 /* Usable memory */ +#define BIOS_MAP_RES 0x02 /* Reserved memory */ +#define BIOS_MAP_ACPI 0x03 /* ACPI Reclaim memory */ +#define BIOS_MAP_NVS 0x04 /* ACPI NVS memory */ + +/* + * Optional ROM header + */ +typedef +struct bios_romheader { + uint16_t signature; /* 0xaa55 */ + uint8_t len; /* length in pages (512 bytes) */ + uint32_t entry; /* initialization entry point */ + uint8_t reserved[19]; + uint16_t pnpheader; /* offset to PnP expansion header */ +} __packed *bios_romheader_t; + +#define BIOS32_MAKESIG(a, b, c, d) \ + ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24)) +#define SMBIOS_SIGNATURE BIOS32_MAKESIG('_', 'S', 'M', '_') + +/* + * CTL_BIOS definitions. + */ +#define BIOS_DEV 1 /* int: BIOS boot device */ +#define BIOS_DISKINFO 2 /* struct: BIOS boot device info */ +#define BIOS_CKSUMLEN 3 /* int: disk cksum block count */ +#define BIOS_MAXID 4 /* number of valid machdep ids */ + +#define CTL_BIOS_NAMES { \ + { 0, 0 }, \ + { "biosdev", CTLTYPE_INT }, \ + { "diskinfo", CTLTYPE_STRUCT }, \ + { "cksumlen", CTLTYPE_INT }, \ +} + +#define BOOTARG_MEMMAP 0 +typedef struct _bios_memmap { + uint64_t addr; /* Beginning of block */ + uint64_t size; /* Size of block */ + uint32_t type; /* Type of block */ +} __packed bios_memmap_t; + +/* Info about disk from the bios, plus the mapping from + * BIOS numbers to BSD major (driver?) number. + * + * Also, do not bother with BIOSN*() macros, just parcel + * the info out, and use it like this. This makes for less + * of a dependence on BIOSN*() macros having to be the same + * across /boot, /bsd, and userland. + */ +#define BOOTARG_DISKINFO 1 +typedef struct _bios_diskinfo { + /* BIOS section */ + int bios_number; /* BIOS number of drive (or -1) */ + u_int bios_cylinders; /* BIOS cylinders */ + u_int bios_heads; /* BIOS heads */ + u_int bios_sectors; /* BIOS sectors */ + int bios_edd; /* EDD support */ + + /* BSD section */ + dev_t bsd_dev; /* BSD device */ + + /* Checksum section */ + uint32_t checksum; /* Checksum for drive */ + + /* Misc. flags */ + uint32_t flags; +#define BDI_INVALID 0x00000001 /* I/O error during checksumming */ +#define BDI_GOODLABEL 0x00000002 /* Had SCSI or ST506/ESDI disklabel */ +#define BDI_BADLABEL 0x00000004 /* Had another disklabel */ +#define BDI_EL_TORITO 0x00000008 /* 2,048-byte sectors */ +#define BDI_HIBVALID 0x00000010 /* hibernate signature valid */ +#define BDI_PICKED 0x80000000 /* kernel-only: cksum matched */ + +} __packed bios_diskinfo_t; + +#define BOOTARG_APMINFO 2 +typedef struct _bios_apminfo { + /* APM_CONNECT returned values */ + u_int apm_detail; + u_int apm_code32_base; + u_int apm_code16_base; + u_int apm_code_len; + u_int apm_data_base; + u_int apm_data_len; + u_int apm_entry; + u_int apm_code16_len; +} __packed bios_apminfo_t; + +#define BOOTARG_CKSUMLEN 3 /* uint32_t */ + +#define BOOTARG_PCIINFO 4 +typedef struct _bios_pciinfo { + /* PCI BIOS v2.0+ - Installation check values */ + uint32_t pci_chars; /* Characteristics (%eax) */ + uint32_t pci_rev; /* BCD Revision (%ebx) */ + uint32_t pci_entry32; /* PM entry point for PCI BIOS */ + uint32_t pci_lastbus; /* Number of last PCI bus */ +} __packed bios_pciinfo_t; + +#define BOOTARG_CONSDEV 5 +typedef struct _bios_consdev { + dev_t consdev; + int conspeed; + uint64_t consaddr; + int consfreq; + uint32_t flags; +#define BCD_MMIO 0x00000001 /* Memory Mapped IO */ + int reg_width; + int reg_shift; +} __packed bios_consdev_t; + +#define BOOTARG_BOOTMAC 7 +typedef struct _bios_bootmac { + char mac[6]; +} __packed bios_bootmac_t; + +#define BOOTARG_DDB 8 +typedef struct _bios_ddb { + int db_console; +} __packed bios_ddb_t; + +#define BOOTARG_BOOTDUID 9 +typedef struct _bios_bootduid { + u_char duid[8]; +} __packed bios_bootduid_t; + +#define BOOTARG_BOOTSR 10 +#define BOOTSR_UUID_MAX 16 +#define BOOTSR_CRYPTO_MAXKEYBYTES 32 +typedef struct _bios_bootsr { + uint8_t uuid[BOOTSR_UUID_MAX]; + uint8_t maskkey[BOOTSR_CRYPTO_MAXKEYBYTES]; +} __packed bios_bootsr_t; + +#define BOOTARG_EFIINFO 11 +typedef struct _bios_efiinfo { + uint64_t config_acpi; + uint64_t config_smbios; + uint64_t fb_addr; + uint64_t fb_size; + uint32_t fb_height; + uint32_t fb_width; + uint32_t fb_pixpsl; /* pixels per scan line */ + uint32_t fb_red_mask; + uint32_t fb_green_mask; + uint32_t fb_blue_mask; + uint32_t fb_reserved_mask; + uint32_t flags; +#define BEI_64BIT 0x00000001 /* 64-bit EFI implementation */ +#define BEI_ESRT 0x00000002 /* ESRT table */ + uint32_t mmap_desc_ver; + uint32_t mmap_desc_size; + uint32_t mmap_size; + uint64_t mmap_start; + uint64_t system_table; + uint64_t config_esrt; +} __packed bios_efiinfo_t; + +#define BOOTARG_UCODE 12 +typedef struct _bios_ucode { + uint64_t uc_addr; + uint64_t uc_size; +} __packed bios_ucode_t; + +#if defined(_KERNEL) || defined (_STANDALONE) + +#ifdef _LOCORE +#define DOINT(n) int $0x20+(n) +#else +#define DOINT(n) "int $0x20+(" #n ")" + +extern volatile struct BIOS_regs { + uint32_t biosr_ax; + uint32_t biosr_cx; + uint32_t biosr_dx; + uint32_t biosr_bx; + uint32_t biosr_bp; + uint32_t biosr_si; + uint32_t biosr_di; + uint32_t biosr_ds; + uint32_t biosr_es; +} __packed BIOS_regs; + +#ifdef _KERNEL +#include + +struct bios_attach_args { + char *ba_name; + u_int ba_func; + bus_space_tag_t ba_iot; + bus_space_tag_t ba_memt; + union { + void *_p; + bios_apminfo_t *_ba_apmp; + paddr_t _ba_acpipbase; + } _; +}; + +#define ba_apmp _._ba_apmp +#define ba_acpipbase _._ba_acpipbase + +struct consdev; +struct proc; + +int bios_sysctl(int *, u_int, void *, size_t *, void *, size_t, struct proc *); + +void bios_getopt(void); +bios_diskinfo_t *bios_getdiskinfo(dev_t); + +extern int biosbasemem; +extern u_int bootapiver; +extern bios_memmap_t *bios_memmap; +extern bios_efiinfo_t *bios_efiinfo; +extern bios_ucode_t *bios_ucode; + +#endif /* _KERNEL */ +#endif /* _LOCORE */ +#endif /* _KERNEL || _STANDALONE */ + +#endif /* _MACHINE_BIOSVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/bus.h b/lib/libc/include/x86_64-openbsd-none/amd64/bus.h new file mode 100644 index 000000000000..140e3a73f3d4 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/bus.h @@ -0,0 +1,706 @@ +/* $OpenBSD: bus.h,v 1.37 2025/08/23 10:15:49 sf Exp $ */ +/* $NetBSD: bus.h,v 1.6 1996/11/10 03:19:25 thorpej Exp $ */ + +/*- + * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1996 Charles M. Hannum. All rights reserved. + * Copyright (c) 1996 Jason R. Thorpe. All rights reserved. + * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BUS_H_ +#define _MACHINE_BUS_H_ + +#include +#include + +#include + +/* + * Bus address and size types + */ +typedef u_long bus_addr_t; +typedef u_long bus_size_t; + +/* + * Access methods for bus resources and address space. + */ +struct x86_bus_space_ops; +typedef const struct x86_bus_space_ops *bus_space_tag_t; +typedef u_long bus_space_handle_t; + +int bus_space_map(bus_space_tag_t t, bus_addr_t addr, + bus_size_t size, int flags, bus_space_handle_t *bshp); +/* like map, but without extent map checking/allocation */ +int _bus_space_map(bus_space_tag_t t, bus_addr_t addr, + bus_size_t size, int flags, bus_space_handle_t *bshp); + +int bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart, + bus_addr_t rend, bus_size_t size, bus_size_t align, + bus_size_t boundary, int flags, bus_addr_t *addrp, + bus_space_handle_t *bshp); +void bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t size); + +/* + * int bus_space_unmap(bus_space_tag_t t, + * bus_space_handle_t bsh, bus_size_t size); + * + * Unmap a region of bus space. + */ + +void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t size); +void _bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t size, bus_addr_t *); + +/* like bus_space_map(), but without extent map checking/allocation */ +int _bus_space_map(bus_space_tag_t t, bus_addr_t addr, + bus_size_t size, int flags, bus_space_handle_t *bshp); + +/* + * int bus_space_subregion(bus_space_tag_t t, + * bus_space_handle_t bsh, bus_size_t offset, bus_size_t size, + * bus_space_handle_t *nbshp); + * + * Get a new handle for a subregion of an already-mapped area of bus space. + */ + +int bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp); + +struct x86_bus_space_ops { + +/* + * u_intN_t bus_space_read_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset); + * + * Read a 1, 2, 4, or 8 byte quantity from bus space + * described by tag/handle/offset. + */ + u_int8_t (*read_1)(bus_space_handle_t, bus_size_t); + u_int16_t (*read_2)(bus_space_handle_t, bus_size_t); + u_int32_t (*read_4)(bus_space_handle_t, bus_size_t); + u_int64_t (*read_8)(bus_space_handle_t, bus_size_t); + +#define bus_space_read_1(_t, _h, _o) ((_t)->read_1((_h), (_o))) +#define bus_space_read_2(_t, _h, _o) ((_t)->read_2((_h), (_o))) +#define bus_space_read_4(_t, _h, _o) ((_t)->read_4((_h), (_o))) +#define bus_space_read_8(_t, _h, _o) ((_t)->read_8((_h), (_o))) + +#define bus_space_read_raw_2(_t, _h, _o) ((_t)->read_2((_h), (_o))) +#define bus_space_read_raw_4(_t, _h, _o) ((_t)->read_4((_h), (_o))) +#define bus_space_read_raw_8(_t, _h, _o) ((_t)->read_8((_h), (_o))) + +/* + * void bus_space_read_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t *addr, size_t count); + * + * Read `count' 1, 2, 4, or 8 byte quantities from bus space + * described by tag/handle/offset and copy into buffer provided. + */ + + void (*read_multi_1)(bus_space_handle_t, bus_size_t, + u_int8_t *, bus_size_t); + void (*read_multi_2)(bus_space_handle_t, bus_size_t, + u_int16_t *, bus_size_t); + void (*read_multi_4)(bus_space_handle_t, bus_size_t, + u_int32_t *, bus_size_t); + void (*read_multi_8)(bus_space_handle_t, bus_size_t, + u_int64_t *, bus_size_t); + +#define bus_space_read_multi_1(_t, _h, _o, _a, _c) \ + ((_t)->read_multi_1((_h), (_o), (_a), (_c))) +#define bus_space_read_multi_2(_t, _h, _o, _a, _c) \ + ((_t)->read_multi_2((_h), (_o), (_a), (_c))) +#define bus_space_read_multi_4(_t, _h, _o, _a, _c) \ + ((_t)->read_multi_4((_h), (_o), (_a), (_c))) +#define bus_space_read_multi_8(_t, _h, _o, _a, _c) \ + ((_t)->read_multi_8((_h), (_o), (_a), (_c))) + +/* + * void bus_space_read_raw_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_int8_t *addr, size_t count); + * + * Read `count' bytes in 2, 4 or 8 byte wide quantities from bus space + * described by tag/handle/offset and copy into buffer provided. The buffer + * must have proper alignment for the N byte wide entities. Furthermore + * possible byte-swapping should be done by these functions. + */ + +#define bus_space_read_raw_multi_2(_t, _h, _o, _a, _c) \ + ((_t)->read_multi_2((_h), (_o), (u_int16_t *)(_a), (_c) >> 1)) +#define bus_space_read_raw_multi_4(_t, _h, _o, _a, _c) \ + ((_t)->read_multi_4((_h), (_o), (u_int32_t *)(_a), (_c) >> 2)) +#define bus_space_read_raw_multi_8(_t, _h, _o, _a, _c) \ + ((_t)->read_multi_8((_h), (_o), (u_int64_t *)(_a), (_c) >> 3)) + +/* + * void bus_space_read_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t *addr, size_t count); + * + * Read `count' 1, 2, 4, or 8 byte quantities from bus space + * described by tag/handle and starting at `offset' and copy into + * buffer provided. + */ + + void (*read_region_1)(bus_space_handle_t, + bus_size_t, u_int8_t *, bus_size_t); + void (*read_region_2)(bus_space_handle_t, + bus_size_t, u_int16_t *, bus_size_t); + void (*read_region_4)(bus_space_handle_t, + bus_size_t, u_int32_t *, bus_size_t); + void (*read_region_8)(bus_space_handle_t, + bus_size_t, u_int64_t *, bus_size_t); + +#define bus_space_read_region_1(_t, _h, _o, _a, _c) \ + ((_t)->read_region_1((_h), (_o), (_a), (_c))) +#define bus_space_read_region_2(_t, _h, _o, _a, _c) \ + ((_t)->read_region_2((_h), (_o), (_a), (_c))) +#define bus_space_read_region_4(_t, _h, _o, _a, _c) \ + ((_t)->read_region_4((_h), (_o), (_a), (_c))) +#define bus_space_read_region_8(_t, _h, _o, _a, _c) \ + ((_t)->read_region_8((_h), (_o), (_a), (_c))) + +/* + * void bus_space_read_raw_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_int8_t *addr, size_t count); + * + * Read `count' bytes in 2, 4 or 8 byte wide quantities from bus space + * described by tag/handle and starting at `offset' and copy into + * buffer provided. The buffer must have proper alignment for the N byte + * wide entities. Furthermore possible byte-swapping should be done by + * these functions. + */ + +#define bus_space_read_raw_region_2(_t, _h, _o, _a, _c) \ + ((_t)->read_region_2((_h), (_o), (u_int16_t *)(_a), (_c) >> 1)) +#define bus_space_read_raw_region_4(_t, _h, _o, _a, _c) \ + ((_t)->read_region_4((_h), (_o), (u_int32_t *)(_a), (_c) >> 2)) +#define bus_space_read_raw_region_8(_t, _h, _o, _a, _c) \ + ((_t)->read_region_8((_h), (_o), (u_int64_t *)(_a), (_c) >> 3)) + +/* + * void bus_space_write_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t value); + * + * Write the 1, 2, 4, or 8 byte value `value' to bus space + * described by tag/handle/offset. + */ + + void (*write_1)(bus_space_handle_t, bus_size_t, u_int8_t); + void (*write_2)(bus_space_handle_t, bus_size_t, u_int16_t); + void (*write_4)(bus_space_handle_t, bus_size_t, u_int32_t); + void (*write_8)(bus_space_handle_t, bus_size_t, u_int64_t); + +#define bus_space_write_1(_t, _h, _o, _v) \ + ((_t)->write_1((_h), (_o), (_v))) +#define bus_space_write_2(_t, _h, _o, _v) \ + ((_t)->write_2((_h), (_o), (_v))) +#define bus_space_write_4(_t, _h, _o, _v) \ + ((_t)->write_4((_h), (_o), (_v))) +#define bus_space_write_8(_t, _h, _o, _v) \ + ((_t)->write_8((_h), (_o), (_v))) + +#define bus_space_write_raw_2(_t, _h, _o, _v) \ + ((_t)->write_2((_h), (_o), (_v))) +#define bus_space_write_raw_4(_t, _h, _o, _v) \ + ((_t)->write_4((_h), (_o), (_v))) +#define bus_space_write_raw_8(_t, _h, _o, _v) \ + ((_t)->write_8((_h), (_o), (_v))) + +/* + * void bus_space_write_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_intN_t *addr, size_t count); + * + * Write `count' 1, 2, 4, or 8 byte quantities from the buffer + * provided to bus space described by tag/handle/offset. + */ + + void (*write_multi_1)(bus_space_handle_t, + bus_size_t, const u_int8_t *, bus_size_t); + void (*write_multi_2)(bus_space_handle_t, + bus_size_t, const u_int16_t *, bus_size_t); + void (*write_multi_4)(bus_space_handle_t, + bus_size_t, const u_int32_t *, bus_size_t); + void (*write_multi_8)(bus_space_handle_t, + bus_size_t, const u_int64_t *, bus_size_t); + +#define bus_space_write_multi_1(_t, _h, _o, _a, _c) \ + ((_t)->write_multi_1((_h), (_o), (_a), (_c))) +#define bus_space_write_multi_2(_t, _h, _o, _a, _c) \ + ((_t)->write_multi_2((_h), (_o), (_a), (_c))) +#define bus_space_write_multi_4(_t, _h, _o, _a, _c) \ + ((_t)->write_multi_4((_h), (_o), (_a), (_c))) +#define bus_space_write_multi_8(_t, _h, _o, _a, _c) \ + ((_t)->write_multi_8((_h), (_o), (_a), (_c))) + +/* + * void bus_space_write_raw_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_int8_t *addr, size_t count); + * + * Write `count' bytes in 2, 4 or 8 byte wide quantities from the buffer + * provided to bus space described by tag/handle/offset. The buffer + * must have proper alignment for the N byte wide entities. Furthermore + * possible byte-swapping should be done by these functions. + */ + +#define bus_space_write_raw_multi_2(_t, _h, _o, _a, _c) \ + ((_t)->write_multi_2((_h), (_o), (const u_int16_t *)(_a), (_c) >> 1)) +#define bus_space_write_raw_multi_4(_t, _h, _o, _a, _c) \ + ((_t)->write_multi_4((_h), (_o), (const u_int32_t *)(_a), (_c) >> 2)) +#define bus_space_write_raw_multi_8(_t, _h, _o, _a, _c) \ + ((_t)->write_multi_8((_h), (_o), (const u_int64_t *)(_a), (_c) >> 3)) + +/* + * void bus_space_write_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_intN_t *addr, size_t count); + * + * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided + * to bus space described by tag/handle starting at `offset'. + */ + + void (*write_region_1)(bus_space_handle_t, + bus_size_t, const u_int8_t *, bus_size_t); + void (*write_region_2)(bus_space_handle_t, + bus_size_t, const u_int16_t *, bus_size_t); + void (*write_region_4)(bus_space_handle_t, + bus_size_t, const u_int32_t *, bus_size_t); + void (*write_region_8)(bus_space_handle_t, + bus_size_t, const u_int64_t *, bus_size_t); + +#define bus_space_write_region_1(_t, _h, _o, _a, _c) \ + ((_t)->write_region_1((_h), (_o), (_a), (_c))) +#define bus_space_write_region_2(_t, _h, _o, _a, _c) \ + ((_t)->write_region_2((_h), (_o), (_a), (_c))) +#define bus_space_write_region_4(_t, _h, _o, _a, _c) \ + ((_t)->write_region_4((_h), (_o), (_a), (_c))) +#define bus_space_write_region_8(_t, _h, _o, _a, _c) \ + ((_t)->write_region_8((_h), (_o), (_a), (_c))) + +/* + * void bus_space_write_raw_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_int8_t *addr, size_t count); + * + * Write `count' bytes in 2, 4 or 8 byte wide quantities to bus space + * described by tag/handle and starting at `offset' from the + * buffer provided. The buffer must have proper alignment for the N byte + * wide entities. Furthermore possible byte-swapping should be done by + * these functions. + */ + +#define bus_space_write_raw_region_2(_t, _h, _o, _a, _c) \ + ((_t)->write_region_2((_h), (_o), (const u_int16_t *)(_a), (_c) >> 1)) +#define bus_space_write_raw_region_4(_t, _h, _o, _a, _c) \ + ((_t)->write_region_4((_h), (_o), (const u_int32_t *)(_a), (_c) >> 2)) +#define bus_space_write_raw_region_8(_t, _h, _o, _a, _c) \ + ((_t)->write_region_8((_h), (_o), (const u_int64_t *)(_a), (_c) >> 3)) + +/* + * void bus_space_set_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t val, size_t count); + * + * Write the 1, 2, 4, or 8 byte value `val' to bus space described + * by tag/handle/offset `count' times. + */ + + void (*set_multi_1)(bus_space_handle_t, + bus_size_t, u_int8_t, size_t); + void (*set_multi_2)(bus_space_handle_t, + bus_size_t, u_int16_t, size_t); + void (*set_multi_4)(bus_space_handle_t, + bus_size_t, u_int32_t, size_t); + void (*set_multi_8)(bus_space_handle_t, + bus_size_t, u_int64_t, size_t); + +#define bus_space_set_multi_1(_t, _h, _o, _a, _c) \ + ((_t)->set_multi_1((_h), (_o), (_a), (_c))) +#define bus_space_set_multi_2(_t, _h, _o, _a, _c) \ + ((_t)->set_multi_2((_h), (_o), (_a), (_c))) +#define bus_space_set_multi_4(_t, _h, _o, _a, _c) \ + ((_t)->set_multi_4((_h), (_o), (_a), (_c))) +#define bus_space_set_multi_8(_t, _h, _o, _a, _c) \ + ((_t)->set_multi_8((_h), (_o), (_a), (_c))) + +/* + * void bus_space_set_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t val, size_t count); + * + * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described + * by tag/handle starting at `offset'. + */ + + void (*set_region_1)(bus_space_handle_t, + bus_size_t, u_int8_t, size_t); + void (*set_region_2)(bus_space_handle_t, + bus_size_t, u_int16_t, size_t); + void (*set_region_4)(bus_space_handle_t, + bus_size_t, u_int32_t, size_t); + void (*set_region_8)(bus_space_handle_t, + bus_size_t, u_int64_t, size_t); + +#define bus_space_set_region_1(_t, _h, _o, _a, _c) \ + ((_t)->set_region_1((_h), (_o), (_a), (_c))) +#define bus_space_set_region_2(_t, _h, _o, _a, _c) \ + ((_t)->set_region_2((_h), (_o), (_a), (_c))) +#define bus_space_set_region_4(_t, _h, _o, _a, _c) \ + ((_t)->set_region_4((_h), (_o), (_a), (_c))) +#define bus_space_set_region_8(_t, _h, _o, _a, _c) \ + ((_t)->set_region_8((_h), (_o), (_a), (_c))) + +/* + * void bus_space_copy_N(bus_space_tag_t tag, + * bus_space_handle_t bsh1, bus_size_t off1, + * bus_space_handle_t bsh2, bus_size_t off2, + * size_t count); + * + * Copy `count' 1, 2, 4, or 8 byte values from bus space starting + * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2. + */ + + void (*copy_1)(bus_space_handle_t, + bus_size_t, bus_space_handle_t, bus_size_t, size_t); + void (*copy_2)(bus_space_handle_t, + bus_size_t, bus_space_handle_t, bus_size_t, size_t); + void (*copy_4)(bus_space_handle_t, + bus_size_t, bus_space_handle_t, bus_size_t, size_t); + void (*copy_8)(bus_space_handle_t, + bus_size_t, bus_space_handle_t, bus_size_t, size_t); + +#define bus_space_copy_1(_t, _h1, _o1, _h2, _o2, _c) \ + ((_t)->copy_1((_h1), (_o1), (_h2), (_o2), (_c))) +#define bus_space_copy_2(_t, _h1, _o1, _h2, _o2, _c) \ + ((_t)->copy_2((_h1), (_o1), (_h2), (_o2), (_c))) +#define bus_space_copy_4(_t, _h1, _o1, _h2, _o2, _c) \ + ((_t)->copy_4((_h1), (_o1), (_h2), (_o2), (_c))) +#define bus_space_copy_8(_t, _h1, _o1, _h2, _o2, _c) \ + ((_t)->copy_8((_h1), (_o1), (_h2), (_o2), (_c))) + +/* + * void *bus_space_vaddr(bus_space_tag_t, bus_space_handle_t); + * + * Get the kernel virtual address for the mapped bus space. + * Only allowed for regions mapped with BUS_SPACE_MAP_LINEAR. + */ + void * (*vaddr)(bus_space_handle_t); + +#define bus_space_vaddr(_t, _h) \ + ((_t)->vaddr((_h))) + +/* + * paddr_t bus_space_mmap(bus_space_tag_t t, bus_addr_t base, + * off_t offset, int prot, int flags); + * + * Mmap an area of bus space. + */ + + paddr_t (*mmap)(bus_addr_t, off_t, int, int); + +#define bus_space_mmap(_t, _a, _o, _p, _f) \ + ((_t)->mmap((_a), (_o), (_p), (_f))) +}; + +/* + * Bus read/write barrier methods. + */ +#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ +#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ + +static inline void +bus_space_barrier(bus_space_tag_t space, bus_space_handle_t + handle, bus_size_t offset, bus_size_t length, int flags) +{ + switch (flags) { + case (BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE): + __asm volatile("mfence" ::: "memory"); + break; + case BUS_SPACE_BARRIER_WRITE: + __asm volatile("sfence" ::: "memory"); + break; + default: + __asm volatile("lfence" ::: "memory"); + break; + } +} + +#define BUS_SPACE_MAP_CACHEABLE 0x0001 +#define BUS_SPACE_MAP_LINEAR 0x0002 +#define BUS_SPACE_MAP_PREFETCHABLE 0x0008 + +/* + * Values for the x86 bus space tag, not to be used directly by MI code. + */ + +/* space is i/o space */ +extern const struct x86_bus_space_ops *x86_bus_space_io_ops; +#define X86_BUS_SPACE_IO (x86_bus_space_io_ops) + +/* space is mem space */ +extern const struct x86_bus_space_ops *x86_bus_space_mem_ops; +#define X86_BUS_SPACE_MEM (x86_bus_space_mem_ops) + +/* + * bus_dma + */ + +/* + * Flags used in various bus DMA methods. + */ +#define BUS_DMA_WAITOK 0x0000 /* safe to sleep (pseudo-flag) */ +#define BUS_DMA_NOWAIT 0x0001 /* not safe to sleep */ +#define BUS_DMA_ALLOCNOW 0x0002 /* perform resource allocation now */ +#define BUS_DMA_COHERENT 0x0004 /* hint: map memory DMA coherent */ +#define BUS_DMA_BUS1 0x0010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x0020 +#define BUS_DMA_32BIT 0x0040 +#define BUS_DMA_24BIT 0x0080 /* isadma map */ +#define BUS_DMA_STREAMING 0x0100 /* hint: sequential, unidirectional */ +#define BUS_DMA_READ 0x0200 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x0400 /* mapping is memory -> device only */ +#define BUS_DMA_NOCACHE 0x0800 /* map memory uncached */ +#define BUS_DMA_ZERO 0x1000 /* zero memory in dmamem_alloc */ +#define BUS_DMA_64BIT 0x2000 /* device handles 64bit dva */ + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct proc; +struct uio; + +/* + * Operations performed by bus_dmamap_sync(). + */ +#define BUS_DMASYNC_PREREAD 0x01 +#define BUS_DMASYNC_POSTREAD 0x02 +#define BUS_DMASYNC_PREWRITE 0x04 +#define BUS_DMASYNC_POSTWRITE 0x08 + +typedef struct bus_dma_tag *bus_dma_tag_t; +typedef struct bus_dmamap *bus_dmamap_t; + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +struct bus_dma_segment { + bus_addr_t ds_addr; /* DMA address */ + bus_size_t ds_len; /* length of transfer */ + vaddr_t _ds_va; /* mapped loaded data */ + vaddr_t _ds_bounce_va; /* mapped bounced data */ + + /* + * Ugh. need this so can pass alignment down from bus_dmamem_alloc + * to scatter gather maps. only the first one is used so the rest is + * wasted space. bus_dma could do with fixing the api for this. + */ + bus_size_t _ds_boundary; /* don't cross */ + bus_size_t _ds_align; /* align to me */ +}; +typedef struct bus_dma_segment bus_dma_segment_t; + +/* + * bus_dma_tag_t + * + * A machine-dependent opaque type describing the implementation of + * DMA for a given bus. + */ + +struct bus_dma_tag { + void *_cookie; /* cookie used in the guts */ + + /* + * DMA mapping methods. + */ + int (*_dmamap_create)(bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); + void (*_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t); + int (*_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); + int (*_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t, + struct mbuf *, int); + int (*_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t, + struct uio *, int); + int (*_dmamap_load_raw)(bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); + void (*_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t); + void (*_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t, + bus_addr_t, bus_size_t, int); + + /* + * DMA memory utility functions. + */ + int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); + int (*_dmamem_alloc_range)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int, + bus_addr_t, bus_addr_t); + void (*_dmamem_free)(bus_dma_tag_t, + bus_dma_segment_t *, int); + int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); + void (*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t); + paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, + int, off_t, int, int); +}; + +#define bus_dmamap_create(t, s, n, m, b, f, p) \ + (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) +#define bus_dmamap_destroy(t, p) \ + (*(t)->_dmamap_destroy)((t), (p)) +#define bus_dmamap_load(t, m, b, s, p, f) \ + (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) +#define bus_dmamap_load_mbuf(t, m, b, f) \ + (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) +#define bus_dmamap_load_uio(t, m, u, f) \ + (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) +#define bus_dmamap_load_raw(t, m, sg, n, s, f) \ + (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) +#define bus_dmamap_unload(t, p) \ + (*(t)->_dmamap_unload)((t), (p)) +#define bus_dmamap_sync(t, p, o, l, ops) \ + (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops)) + +#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ + (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f)) +#define bus_dmamem_alloc_range(t, s, a, b, sg, n, r, f, l, h) \ + (*(t)->_dmamem_alloc_range)((t), (s), (a), (b), (sg), \ + (n), (r), (f), (l), (h)) +#define bus_dmamem_free(t, sg, n) \ + (*(t)->_dmamem_free)((t), (sg), (n)) +#define bus_dmamem_map(t, sg, n, s, k, f) \ + (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f)) +#define bus_dmamem_unmap(t, k, s) \ + (*(t)->_dmamem_unmap)((t), (k), (s)) +#define bus_dmamem_mmap(t, sg, n, o, p, f) \ + (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f)) + +/* + * bus_dmamap_t + * + * Describes a DMA mapping. + */ +struct bus_dmamap { + /* + * PRIVATE MEMBERS: not for use by machine-independent code. + */ + bus_size_t _dm_size; /* largest DMA transfer mappable */ + int _dm_flags; /* misc. flags */ + int _dm_segcnt; /* number of segs this map can map */ + bus_size_t _dm_maxsegsz; /* largest possible segment */ + bus_size_t _dm_boundary; /* don't cross this */ + + void *_dm_cookie; /* cookie for bus-specific functions */ + + struct vm_page **_dm_pages; /* replacement pages */ + vaddr_t _dm_pgva; /* those above -- mapped */ + int _dm_npages; /* number of pages allocated */ + int _dm_nused; /* number of pages replaced */ + + /* + * PUBLIC MEMBERS: these are used by machine-independent code. + */ + bus_size_t dm_mapsize; /* size of the mapping */ + int dm_nsegs; /* # valid segments in mapping */ + bus_dma_segment_t dm_segs[1]; /* segments; variable length */ +}; + +int _bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t, + bus_size_t, int, bus_dmamap_t *); +void _bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); +int _bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); +int _bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, + struct mbuf *, int); +int _bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, + struct uio *, int); +int _bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); +void _bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t); +void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, + bus_size_t, int); + +int _bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size, + bus_size_t alignment, bus_size_t boundary, + bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags); +void _bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs); +int _bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs, size_t size, caddr_t *kvap, int flags); +void _bus_dmamem_unmap(bus_dma_tag_t tag, caddr_t kva, + size_t size); +paddr_t _bus_dmamem_mmap(bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs, off_t off, int prot, int flags); + +int _bus_dmamem_alloc_range(bus_dma_tag_t tag, bus_size_t size, + bus_size_t alignment, bus_size_t boundary, + bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags, + bus_addr_t low, bus_addr_t high); + +#endif /* _MACHINE_BUS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/cdefs.h b/lib/libc/include/x86_64-openbsd-none/amd64/cdefs.h new file mode 100644 index 000000000000..cd6f968643f2 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/cdefs.h @@ -0,0 +1,21 @@ +/* $OpenBSD: cdefs.h,v 1.3 2013/03/28 17:30:45 martynas Exp $ */ + +/* + * Written by J.T. Conklin 01/17/95. + * Public domain. + */ + +#ifndef _MACHINE_CDEFS_H_ +#define _MACHINE_CDEFS_H_ + +#define __strong_alias(alias,sym) \ + __asm__(".global " __STRING(alias) " ; " __STRING(alias) \ + " = " __STRING(sym)) +#define __weak_alias(alias,sym) \ + __asm__(".weak " __STRING(alias) " ; " __STRING(alias) \ + " = " __STRING(sym)) +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning." __STRING(sym) \ + " ; .ascii \"" msg "\" ; .text") + +#endif /* !_MACHINE_CDEFS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/codepatch.h b/lib/libc/include/x86_64-openbsd-none/amd64/codepatch.h new file mode 100644 index 000000000000..04ea726a26f3 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/codepatch.h @@ -0,0 +1,120 @@ +/* $OpenBSD: codepatch.h,v 1.19 2024/02/12 01:18:17 guenther Exp $ */ +/* + * Copyright (c) 2014-2015 Stefan Fritsch + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_CODEPATCH_H_ +#define _MACHINE_CODEPATCH_H_ + +#include + +#ifndef _LOCORE + +/* code in this section will be unmapped after boot */ +#define __cptext __attribute__((section(".cptext"))) + +__cptext void *codepatch_maprw(vaddr_t *nva, vaddr_t dest); +__cptext void codepatch_unmaprw(vaddr_t nva); +__cptext void codepatch_fill_nop(void *caddr, uint16_t len); +__cptext void codepatch_nop(uint16_t tag); +__cptext void codepatch_replace(uint16_t tag, const void *code, size_t len); +__cptext void codepatch_call(uint16_t _tag, void *_func); +__cptext void codepatch_jmp(uint16_t _tag, void *_func); +void codepatch_disable(void); + +#endif /* !_LOCORE */ + +/* + * Mark the start of some code snippet to be patched. + */ +#define CODEPATCH_START 998: +/* + * Mark the end of some code to be patched, and assign the given tag. + */ +#define CODEPATCH_END2(startnum,tag) \ + 999: \ + .section .codepatch, "a" ;\ + .quad startnum##b ;\ + .short (999b - startnum##b) ;\ + .short tag ;\ + .int 0 ;\ + .previous +#define CODEPATCH_END(tag) CODEPATCH_END2(998,tag) + +#define CPTAG_STAC 1 +#define CPTAG_CLAC 2 +#define CPTAG_EOI 3 +#define CPTAG_XRSTOR 4 +#define CPTAG_XSAVE 5 +#define CPTAG_MELTDOWN_NOP 6 +#define CPTAG_MELTDOWN_ALLTRAPS 7 +#define CPTAG_PCID_SET_REUSE 8 +#define CPTAG_MDS 9 +#define CPTAG_MDS_VMM 10 +#define CPTAG_FENCE_SWAPGS_MIS_TAKEN 11 +#define CPTAG_FENCE_NO_SAFE_SMAP 12 +#define CPTAG_XRSTORS 13 +#define CPTAG_RETPOLINE_RAX 14 +#define CPTAG_RETPOLINE_R11 15 +#define CPTAG_RETPOLINE_R13 16 +#define CPTAG_IBPB_NOP 17 + +/* + * stac/clac SMAP instructions have lfence like semantics. Let's + * guarantee those semantics on older cpus. + */ +#define SMAP_NOP lfence +#define SMAP_STAC CODEPATCH_START ;\ + SMAP_NOP ;\ + CODEPATCH_END(CPTAG_STAC) +#define SMAP_CLAC CODEPATCH_START ;\ + SMAP_NOP ;\ + CODEPATCH_END(CPTAG_CLAC) + +/* CVE-2019-1125: block speculation after swapgs */ +#define FENCE_SWAPGS_MIS_TAKEN \ + CODEPATCH_START ; \ + lfence ; \ + CODEPATCH_END(CPTAG_FENCE_SWAPGS_MIS_TAKEN) +/* block speculation when a correct SMAP impl would have been enough */ +#define FENCE_NO_SAFE_SMAP \ + CODEPATCH_START ; \ + lfence ; \ + CODEPATCH_END(CPTAG_FENCE_NO_SAFE_SMAP) + +#define PCID_SET_REUSE_SIZE 12 +#define PCID_SET_REUSE_NOP \ + 997: ;\ + .byte 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 ;\ + .byte 0x0f, 0x1f, 0x40, 0x00 ;\ + CODEPATCH_END2(997, CPTAG_PCID_SET_REUSE) + +/* Would be neat if these could be in something like .cptext */ +#define CODEPATCH_CODE(symbol, instructions...) \ + .section .rodata; \ + .globl symbol; \ +symbol: instructions; \ + .size symbol, . - symbol + +/* provide a (short) variable with the length of the patch */ +#define CODEPATCH_CODE_LEN(symbol, instructions...) \ + CODEPATCH_CODE(symbol, instructions); \ +996: .globl symbol##_len; \ + .align 2; \ +symbol##_len: \ + .short 996b - symbol; \ + .size symbol##_len, 2 + +#endif /* _MACHINE_CODEPATCH_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/conf.h b/lib/libc/include/x86_64-openbsd-none/amd64/conf.h new file mode 100644 index 000000000000..bd23d33ba71b --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/conf.h @@ -0,0 +1,59 @@ +/* $OpenBSD: conf.h,v 1.11 2024/09/04 07:45:08 jsg Exp $ */ +/* $NetBSD: conf.h,v 1.2 1996/05/05 19:28:34 christos Exp $ */ + +/* + * Copyright (c) 1996 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#define mmread mmrw +#define mmwrite mmrw +cdev_decl(mm); + +bdev_decl(fd); +cdev_decl(fd); + +cdev_decl(spkr); + +cdev_decl(bios); + +#define cdev_acpi_init(c,n) {\ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev, 0, 0, dev_init(c,n,kqfilter) } +cdev_decl(acpi); + +cdev_decl(pctr); + +#include "vmm.h" +cdev_decl(vmm); + +#include "psp.h" +cdev_decl(psp); \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/cpu.h b/lib/libc/include/x86_64-openbsd-none/amd64/cpu.h new file mode 100644 index 000000000000..d3cab29e55ae --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/cpu.h @@ -0,0 +1,530 @@ +/* $OpenBSD: cpu.h,v 1.180 2025/04/28 16:18:25 bluhm Exp $ */ +/* $NetBSD: cpu.h,v 1.1 2003/04/26 18:39:39 fvdl Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)cpu.h 5.4 (Berkeley) 5/9/91 + */ + +#ifndef _MACHINE_CPU_H_ +#define _MACHINE_CPU_H_ + +/* + * Definitions unique to x86-64 cpu support. + */ +#ifdef _KERNEL +#include +#include /* USERMODE */ +#include +#endif /* _KERNEL */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef _KERNEL + +/* VMXON region (Intel) */ +struct vmxon_region { + uint32_t vr_revision; +}; + +/* + * VMX for Intel CPUs + */ +struct vmx { + uint64_t vmx_cr0_fixed0; + uint64_t vmx_cr0_fixed1; + uint64_t vmx_cr4_fixed0; + uint64_t vmx_cr4_fixed1; + uint32_t vmx_vmxon_revision; + uint32_t vmx_msr_table_size; + uint32_t vmx_cr3_tgt_count; + uint8_t vmx_has_l1_flush_msr; + uint64_t vmx_invept_mode; +}; + +/* + * SVM for AMD CPUs + */ +struct svm { + uint32_t svm_max_asid; + uint8_t svm_flush_by_asid; + uint8_t svm_vmcb_clean; + uint8_t svm_decode_assist; +}; + +union vmm_cpu_cap { + struct vmx vcc_vmx; + struct svm vcc_svm; +}; + +enum cpu_vendor { + CPUV_UNKNOWN, + CPUV_AMD, + CPUV_INTEL, + CPUV_VIA, +}; + +/* + * Locks used to protect struct members in this file: + * I immutable after creation + * a atomic operations + * o owned (read/modified only) by this CPU + */ +struct x86_64_tss; +struct vcpu; +struct cpu_info { + /* + * The beginning of this structure in mapped in the userspace "u-k" + * page tables, so that these first couple members can be accessed + * from the trampoline code. The ci_PAGEALIGN member defines where + * the part that is *not* visible begins, so don't put anything + * above it that must be kept hidden from userspace! + */ + u_int64_t ci_kern_cr3; /* [o] U+K page table */ + u_int64_t ci_scratch; /* [o] for U<-->K transition */ + +#define ci_PAGEALIGN ci_dev + struct device *ci_dev; /* [I] */ + struct cpu_info *ci_self; /* [I] */ + struct cpu_info *ci_next; /* [I] */ + + u_int ci_cpuid; /* [I] */ + u_int ci_apicid; /* [I] */ + u_int ci_acpi_proc_id; /* [I] */ + u_int32_t ci_randseed; /* [o] */ + + u_int64_t ci_kern_rsp; /* [o] kernel-only stack */ + u_int64_t ci_intr_rsp; /* [o] U<-->K trampoline stack */ + u_int64_t ci_user_cr3; /* [o] U-K page table */ + + /* bits for mitigating Micro-architectural Data Sampling */ + char ci_mds_tmp[64]; /* [o] 64-byte aligned */ + void *ci_mds_buf; /* [I] */ + + struct proc *ci_curproc; /* [o] */ + struct schedstate_percpu ci_schedstate; /* scheduler state */ + + struct pmap *ci_proc_pmap; /* active, non-kernel pmap */ + struct pmap *ci_user_pmap; /* [o] last pmap used in userspace */ + struct pcb *ci_curpcb; /* [o] */ + struct pcb *ci_idle_pcb; /* [o] */ + + u_int ci_pflags; /* [o] */ +#define CPUPF_USERSEGS 0x01 /* CPU has curproc's segs and FS.base */ +#define CPUPF_USERXSTATE 0x02 /* CPU has curproc's xsave state */ + + struct intrsource *ci_isources[MAX_INTR_SOURCES]; + u_int64_t ci_ipending; + int ci_ilevel; + int ci_idepth; + int ci_handled_intr_level; + u_int64_t ci_imask[NIPL]; + u_int64_t ci_iunmask[NIPL]; +#ifdef DIAGNOSTIC + int ci_mutex_level; +#endif + + volatile u_int ci_flags; /* [a] */ + u_int32_t ci_ipis; /* [a] */ + + enum cpu_vendor ci_vendor; /* [I] mapped from cpuid(0) */ + u_int32_t ci_cpuid_level; /* [I] cpuid(0).eax */ + u_int32_t ci_feature_flags; /* [I] */ + u_int32_t ci_feature_eflags; /* [I] */ + u_int32_t ci_feature_sefflags_ebx;/* [I] */ + u_int32_t ci_feature_sefflags_ecx;/* [I] */ + u_int32_t ci_feature_sefflags_edx;/* [I] */ + u_int32_t ci_feature_amdspec_ebx; /* [I] */ + u_int32_t ci_feature_amdsev_eax; /* [I] */ + u_int32_t ci_feature_amdsev_ebx; /* [I] */ + u_int32_t ci_feature_amdsev_ecx; /* [I] */ + u_int32_t ci_feature_amdsev_edx; /* [I] */ + u_int32_t ci_feature_tpmflags; /* [I] */ + u_int32_t ci_pnfeatset; /* [I] */ + u_int32_t ci_efeature_eax; /* [I] */ + u_int32_t ci_efeature_ecx; /* [I] */ + u_int32_t ci_brand[12]; /* [I] */ + u_int32_t ci_signature; /* [I] */ + u_int32_t ci_family; /* [I] */ + u_int32_t ci_model; /* [I] */ + u_int32_t ci_cflushsz; /* [I] */ + + int ci_inatomic; /* [o] */ + +#define __HAVE_CPU_TOPOLOGY + u_int32_t ci_smt_id; /* [I] */ + u_int32_t ci_core_id; /* [I] */ + u_int32_t ci_pkg_id; /* [I] */ + + struct cpu_functions *ci_func; /* [I] */ + void (*cpu_setup)(struct cpu_info *); /* [I] */ + + struct device *ci_acpicpudev; /* [I] */ + volatile u_int ci_mwait; /* [a] */ +#define MWAIT_IN_IDLE 0x1 /* don't need IPI to wake */ +#define MWAIT_KEEP_IDLING 0x2 /* cleared by other cpus to wake me */ +#define MWAIT_ONLY 0x4 /* set if all idle states use mwait */ +#define MWAIT_IDLING (MWAIT_IN_IDLE | MWAIT_KEEP_IDLING) + + int ci_want_resched; + + struct x86_64_tss *ci_tss; /* [o] */ + void *ci_gdt; /* [o] */ + + volatile int ci_ddb_paused; +#define CI_DDB_RUNNING 0 +#define CI_DDB_SHOULDSTOP 1 +#define CI_DDB_STOPPED 2 +#define CI_DDB_ENTERDDB 3 +#define CI_DDB_INDDB 4 + +#ifdef MULTIPROCESSOR + struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM]; +#define __HAVE_UVM_PERCPU + struct uvm_pmr_cache ci_uvm; /* [o] page cache */ +#endif + + struct ksensordev ci_sensordev; + struct ksensor ci_sensor; + struct ksensor ci_hz_sensor; + u_int64_t ci_hz_mperf; + u_int64_t ci_hz_aperf; +#if defined(GPROF) || defined(DDBPROF) + struct gmonparam *ci_gmon; + struct clockintr ci_gmonclock; +#endif + u_int32_t ci_vmm_flags; +#define CI_VMM_VMX (1 << 0) +#define CI_VMM_SVM (1 << 1) +#define CI_VMM_RVI (1 << 2) +#define CI_VMM_EPT (1 << 3) +#define CI_VMM_DIS (1 << 4) + union vmm_cpu_cap ci_vmm_cap; + paddr_t ci_vmxon_region_pa; + struct vmxon_region *ci_vmxon_region; + paddr_t ci_vmcs_pa; + struct rwlock ci_vmcs_lock; + struct pmap *ci_ept_pmap; /* [o] last used EPT pmap */ + struct vcpu *ci_guest_vcpu; /* [o] last vcpu resumed */ + + char ci_panicbuf[512]; + + struct clockqueue ci_queue; +}; + +#define CPUF_BSP 0x0001 /* CPU is the original BSP */ +#define CPUF_AP 0x0002 /* CPU is an AP */ +#define CPUF_SP 0x0004 /* CPU is only processor */ +#define CPUF_PRIMARY 0x0008 /* CPU is active primary processor */ + +#define CPUF_IDENTIFY 0x0010 /* CPU may now identify */ +#define CPUF_IDENTIFIED 0x0020 /* CPU has been identified */ + +#define CPUF_CONST_TSC 0x0040 /* CPU has constant TSC */ +#define CPUF_INVAR_TSC 0x0100 /* CPU has invariant TSC */ + +#define CPUF_PRESENT 0x1000 /* CPU is present */ +#define CPUF_RUNNING 0x2000 /* CPU is running */ +#define CPUF_PAUSE 0x4000 /* CPU is paused in DDB */ +#define CPUF_GO 0x8000 /* CPU should start running */ +#define CPUF_PARK 0x10000 /* CPU should self-park in real mode */ +#define CPUF_VMM 0x20000 /* CPU is executing in VMM mode */ + +#define PROC_PC(p) ((p)->p_md.md_regs->tf_rip) +#define PROC_STACK(p) ((p)->p_md.md_regs->tf_rsp) + +struct cpu_info_full; +extern struct cpu_info_full cpu_info_full_primary; +#define cpu_info_primary (*(struct cpu_info *)((char *)&cpu_info_full_primary + 4096*2 - offsetof(struct cpu_info, ci_PAGEALIGN))) + +extern struct cpu_info *cpu_info_list; + +#define CPU_INFO_ITERATOR int +#define CPU_INFO_FOREACH(cii, ci) for (cii = 0, ci = cpu_info_list; \ + ci != NULL; ci = ci->ci_next) + +#define CPU_INFO_UNIT(ci) ((ci)->ci_dev ? (ci)->ci_dev->dv_unit : 0) + +/* + * Preempt the current process if in interrupt from user mode, + * or after the current trap/syscall if in system mode. + */ +extern void need_resched(struct cpu_info *); +#define clear_resched(ci) (ci)->ci_want_resched = 0 + +#if defined(MULTIPROCESSOR) + +#define MAXCPUS 64 /* bitmask */ + +#define CPU_STARTUP(_ci) ((_ci)->ci_func->start(_ci)) +#define CPU_STOP(_ci) ((_ci)->ci_func->stop(_ci)) +#define CPU_START_CLEANUP(_ci) ((_ci)->ci_func->cleanup(_ci)) + +#define curcpu() ({struct cpu_info *__ci; \ + asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) \ + :"n" (offsetof(struct cpu_info, ci_self))); \ + __ci;}) +#define cpu_number() (curcpu()->ci_cpuid) + +#define CPU_IS_PRIMARY(ci) ((ci)->ci_flags & CPUF_PRIMARY) +#define CPU_IS_RUNNING(ci) ((ci)->ci_flags & CPUF_RUNNING) + +extern struct cpu_info *cpu_info[MAXCPUS]; + +void cpu_boot_secondary_processors(void); + +void cpu_kick(struct cpu_info *); +void cpu_unidle(struct cpu_info *); + +#define CPU_BUSY_CYCLE() __asm volatile("pause": : : "memory") + +#else /* !MULTIPROCESSOR */ + +#define MAXCPUS 1 + +#ifdef _KERNEL +#define curcpu() (&cpu_info_primary) + +#define cpu_kick(ci) +#define cpu_unidle(ci) + +#define CPU_BUSY_CYCLE() __asm volatile ("" ::: "memory") + +#endif + +/* + * definitions of cpu-dependent requirements + * referenced in generic code + */ +#define cpu_number() 0 +#define CPU_IS_PRIMARY(ci) 1 +#define CPU_IS_RUNNING(ci) 1 + +#endif /* MULTIPROCESSOR */ + +#include +#include + +static inline unsigned int +cpu_rnd_messybits(void) +{ + unsigned int hi, lo; + + __asm volatile("rdtsc" : "=d" (hi), "=a" (lo)); + + return (hi ^ lo); +} + +#endif /* _KERNEL */ + +#ifdef MULTIPROCESSOR +#include +#endif + +#define aston(p) ((p)->p_md.md_astpending = 1) + +#define curpcb curcpu()->ci_curpcb + +/* + * Arguments to hardclock, softclock and statclock + * encapsulate the previous machine state in an opaque + * clockframe; for now, use generic intrframe. + */ +#define clockframe intrframe + +#define CLKF_USERMODE(frame) USERMODE((frame)->if_cs, (frame)->if_rflags) +#define CLKF_PC(frame) ((frame)->if_rip) +#define CLKF_INTR(frame) (curcpu()->ci_idepth > 1) + +/* + * Give a profiling tick to the current process when the user profiling + * buffer pages are invalid. On the i386, request an ast to send us + * through usertrap(), marking the proc as needing a profiling tick. + */ +#define need_proftick(p) aston(p) + +void signotify(struct proc *); + +/* + * We need a machine-independent name for this. + */ +extern void (*delay_func)(int); +void delay_fini(void (*)(int)); +void delay_init(void (*)(int), int); +struct timeval; + +#define DELAY(x) (*delay_func)(x) +#define delay(x) (*delay_func)(x) + + +#ifdef _KERNEL +/* cpu.c */ +extern int cpu_feature; +extern int cpu_ebxfeature; +extern int cpu_ecxfeature; +extern int ecpu_ecxfeature; +extern int cpu_sev_guestmode; +extern int cpu_id; +extern char cpu_vendor[]; +extern int cpuid_level; +extern int cpu_meltdown; +extern u_int cpu_mwait_size; +extern u_int cpu_mwait_states; + +int cpu_suspend_primary(void); + +/* cacheinfo.c */ +void x86_print_cacheinfo(struct cpu_info *); + +/* identcpu.c */ +void identifycpu(struct cpu_info *); +int cpu_amd64speed(int *); +extern int cpuspeed; +extern int amd64_pos_cbit; +extern int amd64_min_noes_asid; + +/* machdep.c */ +void dumpconf(void); +void cpu_set_vendor(struct cpu_info *, int _level, const char *_vendor); +void cpu_reset(void); +void x86_64_proc0_tss_ldt_init(void); +int amd64_pa_used(paddr_t); +#define cpu_idle_enter() do { /* nothing */ } while (0) +extern void (*cpu_idle_cycle_fcn)(void); +extern void (*cpu_suspend_cycle_fcn)(void); +#define cpu_idle_cycle() (*cpu_idle_cycle_fcn)() +#define cpu_idle_leave() do { /* nothing */ } while (0) +extern void (*initclock_func)(void); +extern void (*startclock_func)(void); + +struct region_descriptor; +void lgdt(struct region_descriptor *); + +struct pcb; +void savectx(struct pcb *); +void proc_trampoline(void); + +/* clock.c */ +void startclocks(void); +void rtcinit(void); +void rtcstart(void); +void rtcstop(void); +void i8254_delay(int); +void i8254_initclocks(void); +void i8254_startclock(void); +void i8254_start_both_clocks(void); +void i8254_inittimecounter(void); +void i8254_inittimecounter_simple(void); + +/* i8259.c */ +void i8259_default_setup(void); + +void cpu_init_msrs(struct cpu_info *); +void cpu_fix_msrs(struct cpu_info *); +void cpu_tsx_disable(struct cpu_info *); + +/* dkcsum.c */ +void dkcsumattach(void); + +/* bus_machdep.c */ +void x86_bus_space_init(void); +void x86_bus_space_mallocok(void); + +/* powernow-k8.c */ +void k8_powernow_init(struct cpu_info *); +void k8_powernow_setperf(int); + +/* k1x-pstate.c */ +void k1x_init(struct cpu_info *); +void k1x_setperf(int); + +void est_init(struct cpu_info *); +void est_setperf(int); + +#ifdef MULTIPROCESSOR +/* mp_setperf.c */ +void mp_setperf_init(void); +#endif + +#endif /* _KERNEL */ + +/* + * CTL_MACHDEP definitions. + */ +#define CPU_CONSDEV 1 /* dev_t: console terminal device */ +#define CPU_BIOS 2 /* BIOS variables */ +#define CPU_BLK2CHR 3 /* convert blk maj into chr one */ +#define CPU_CHR2BLK 4 /* convert chr maj into blk one */ +#define CPU_ALLOWAPERTURE 5 /* allow mmap of /dev/xf86 */ +#define CPU_CPUVENDOR 6 /* cpuid vendor string */ +#define CPU_CPUID 7 /* cpuid */ +#define CPU_CPUFEATURE 8 /* cpuid features */ +#define CPU_KBDRESET 10 /* keyboard reset under pcvt */ +#define CPU_XCRYPT 12 /* supports VIA xcrypt in userland */ +#define CPU_LIDACTION 14 /* action caused by lid close */ +#define CPU_FORCEUKBD 15 /* Force ukbd(4) as console keyboard */ +#define CPU_TSCFREQ 16 /* TSC frequency */ +#define CPU_INVARIANTTSC 17 /* has invariant TSC */ +#define CPU_PWRACTION 18 /* action caused by power button */ +#define CPU_RETPOLINE 19 /* cpu requires retpoline pattern */ +#define CPU_MAXID 20 /* number of valid machdep ids */ + +#define CTL_MACHDEP_NAMES { \ + { 0, 0 }, \ + { "console_device", CTLTYPE_STRUCT }, \ + { "bios", CTLTYPE_INT }, \ + { "blk2chr", CTLTYPE_STRUCT }, \ + { "chr2blk", CTLTYPE_STRUCT }, \ + { "allowaperture", CTLTYPE_INT }, \ + { "cpuvendor", CTLTYPE_STRING }, \ + { "cpuid", CTLTYPE_INT }, \ + { "cpufeature", CTLTYPE_INT }, \ + { 0, 0 }, \ + { "kbdreset", CTLTYPE_INT }, \ + { 0, 0 }, \ + { "xcrypt", CTLTYPE_INT }, \ + { 0, 0 }, \ + { "lidaction", CTLTYPE_INT }, \ + { "forceukbd", CTLTYPE_INT }, \ + { "tscfreq", CTLTYPE_QUAD }, \ + { "invarianttsc", CTLTYPE_INT }, \ + { "pwraction", CTLTYPE_INT }, \ + { "retpoline", CTLTYPE_INT }, \ +} + +#endif /* !_MACHINE_CPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/cpu_full.h b/lib/libc/include/x86_64-openbsd-none/amd64/cpu_full.h new file mode 100644 index 000000000000..0d6485cd0e2d --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/cpu_full.h @@ -0,0 +1,70 @@ +/* $OpenBSD: cpu_full.h,v 1.5 2019/05/17 19:07:47 guenther Exp $ */ +/* + * Copyright (c) 2018 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_CPU_FULL_H_ +#define _MACHINE_CPU_FULL_H_ + +#include /* offsetof, PAGE_SIZE */ +#include +#include + +/* + * The layout of the full per-CPU information, including TSS, GDT, + * trampoline stacks, and cpu_info described in + */ +struct cpu_info_full { + /* page mapped kRO in u-k */ + union { + struct { + struct x86_64_tss uu_tss; + uint64_t uu_gdt[GDT_SIZE / 8]; + } u_tssgdt; + char u_align[PAGE_SIZE]; + } cif_RO; +#define cif_tss cif_RO.u_tssgdt.uu_tss +#define cif_gdt cif_RO.u_tssgdt.uu_gdt + + /* start of page mapped kRW in u-k */ + uint64_t cif_tramp_stack[(PAGE_SIZE / 4 + - offsetof(struct cpu_info, ci_PAGEALIGN)) / sizeof(uint64_t)]; + uint64_t cif_dblflt_stack[(PAGE_SIZE / 4) / sizeof(uint64_t)]; + uint64_t cif_nmi_stack[(2 * PAGE_SIZE / 4) / sizeof(uint64_t)]; + + /* + * Beginning of this hangs over into the kRW page; rest is + * unmapped in u-k + */ + struct cpu_info cif_cpu; +} __aligned(PAGE_SIZE); + +/* tss, align shim, and gdt must fit in a page */ +CTASSERT(_ALIGN(sizeof(struct x86_64_tss)) + + sizeof(struct mem_segment_descriptor) * (NGDT_MEM + 2*NGDT_SYS) + < PAGE_SIZE); + +/* verify expected alignment */ +CTASSERT(offsetof(struct cpu_info_full, cif_cpu.ci_PAGEALIGN) % PAGE_SIZE == 0); + +/* verify total size is multiple of page size */ +CTASSERT(sizeof(struct cpu_info_full) % PAGE_SIZE == 0); + +extern struct cpu_info_full cpu_info_full_primary; + +/* Now make sure the cpu_info_primary macro is correct */ +CTASSERT(&cpu_info_primary - &cpu_info_full_primary.cif_cpu == 0); + +#endif /* _MACHINE_CPU_FULL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/cpufunc.h b/lib/libc/include/x86_64-openbsd-none/amd64/cpufunc.h new file mode 100644 index 000000000000..6a8420e179f5 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/cpufunc.h @@ -0,0 +1,461 @@ +/* $OpenBSD: cpufunc.h,v 1.45 2025/06/27 17:23:49 bluhm Exp $ */ +/* $NetBSD: cpufunc.h,v 1.3 2003/05/08 10:27:43 fvdl Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_CPUFUNC_H_ +#define _MACHINE_CPUFUNC_H_ + +/* + * Functions to provide access to i386-specific instructions. + */ + +#include + +#include + +#if defined(_KERNEL) && !defined (_STANDALONE) + +static __inline void +invlpg(u_int64_t addr) +{ + __asm volatile("invlpg (%0)" : : "r" (addr) : "memory"); +} + +static __inline void +sidt(void *p) +{ + __asm volatile("sidt (%0)" : : "r" (p) : "memory"); +} + +static __inline void +lidt(void *p) +{ + __asm volatile("lidt (%0)" : : "r" (p) : "memory"); +} + +static __inline void +sgdt(void *p) +{ + __asm volatile("sgdt (%0)" : : "r" (p) : "memory"); +} + +static __inline void +bare_lgdt(struct region_descriptor *p) +{ + __asm volatile("lgdt (%0)" : : "r" (p) : "memory"); +} + +static __inline void +sldt(u_short *sel) +{ + __asm volatile("sldt (%0)" : : "r" (sel) : "memory"); +} + +static __inline void +lldt(u_short sel) +{ + __asm volatile("lldt %0" : : "r" (sel)); +} + +static __inline void +ltr(u_short sel) +{ + __asm volatile("ltr %0" : : "r" (sel)); +} + +static __inline void +lcr8(u_int val) +{ + u_int64_t val64 = val; + __asm volatile("movq %0,%%cr8" : : "r" (val64)); +} + +/* + * Upper 32 bits are reserved anyway, so just keep this 32bits. + */ +static __inline void +lcr0(u_int val) +{ + u_int64_t val64 = val; + __asm volatile("movq %0,%%cr0" : : "r" (val64)); +} + +static __inline u_int +rcr0(void) +{ + u_int64_t val64; + u_int val; + __asm volatile("movq %%cr0,%0" : "=r" (val64)); + val = val64; + return val; +} + +static __inline u_int64_t +rcr2(void) +{ + u_int64_t val; + __asm volatile("movq %%cr2,%0" : "=r" (val)); + return val; +} + +static __inline void +lcr3(u_int64_t val) +{ + __asm volatile("movq %0,%%cr3" : : "r" (val)); +} + +static __inline u_int64_t +rcr3(void) +{ + u_int64_t val; + __asm volatile("movq %%cr3,%0" : "=r" (val)); + return val; +} + +/* + * Same as for cr0. Don't touch upper 32 bits. + */ +static __inline void +lcr4(u_int val) +{ + u_int64_t val64 = val; + + __asm volatile("movq %0,%%cr4" : : "r" (val64)); +} + +static __inline u_int +rcr4(void) +{ + u_int64_t val64; + __asm volatile("movq %%cr4,%0" : "=r" (val64)); + return (u_int) val64; +} + +/* + * DR6 and DR7 debug registers + */ +static inline uint64_t +rdr6(void) +{ + u_int64_t val; + __asm volatile("movq %%dr6,%0" : "=r" (val)); + return val; +} + +static inline uint64_t +rdr7(void) +{ + u_int64_t val; + __asm volatile("movq %%dr7,%0" : "=r" (val)); + return val; +} + +static __inline void +tlbflush(void) +{ + u_int64_t val; + __asm volatile("movq %%cr3,%0" : "=r" (val)); + __asm volatile("movq %0,%%cr3" : : "r" (val)); +} + +static inline void +invpcid(uint64_t type, paddr_t pcid, paddr_t addr) +{ + uint64_t desc[2] = { pcid, addr }; + asm volatile("invpcid %0,%1" : : "m"(desc[0]), "r"(type)); +} +#define INVPCID_ADDR 0 +#define INVPCID_PCID 1 +#define INVPCID_ALL 2 +#define INVPCID_NON_GLOBAL 3 + +#ifdef notyet +void setidt(int idx, /*XXX*/caddr_t func, int typ, int dpl); +#endif + + +/* XXXX ought to be in psl.h with spl() functions */ + +static __inline u_long +read_rflags(void) +{ + u_long ef; + + __asm volatile("pushfq; popq %0" : "=r" (ef)); + return (ef); +} + +static __inline void +write_rflags(u_long ef) +{ + __asm volatile("pushq %0; popfq" : : "r" (ef)); +} + +static __inline void +intr_enable(void) +{ + __asm volatile("sti"); +} + +static __inline u_long +intr_disable(void) +{ + u_long ef; + + ef = read_rflags(); + __asm volatile("cli"); + return (ef); +} + +static __inline void +intr_restore(u_long ef) +{ + write_rflags(ef); +} + +static __inline u_int64_t +rdmsr(u_int msr) +{ + uint32_t hi, lo; + __asm volatile("rdmsr" : "=d" (hi), "=a" (lo) : "c" (msr)); + return (((uint64_t)hi << 32) | (uint64_t) lo); +} + +static __inline int +rdpkru(u_int ecx) +{ + uint32_t edx, pkru; + asm volatile("rdpkru " : "=a" (pkru), "=d" (edx) : "c" (ecx)); + return pkru; +} + +static __inline void +wrpkru(u_int ecx, uint32_t pkru) +{ + uint32_t edx = 0; + asm volatile("wrpkru" : : "a" (pkru), "c" (ecx), "d" (edx)); +} + +static __inline void +wrmsr(u_int msr, u_int64_t newval) +{ + __asm volatile("wrmsr" : + : "a" (newval & 0xffffffff), "d" (newval >> 32), "c" (msr)); +} + +/* + * Some of the undocumented AMD64 MSRs need a 'passcode' to access. + * + * See LinuxBIOSv2: src/cpu/amd/model_fxx/model_fxx_init.c + */ + +#define OPTERON_MSR_PASSCODE 0x9c5a203a + +static __inline u_int64_t +rdmsr_locked(u_int msr, u_int code) +{ + uint32_t hi, lo; + __asm volatile("rdmsr" + : "=d" (hi), "=a" (lo) + : "c" (msr), "D" (code)); + return (((uint64_t)hi << 32) | (uint64_t) lo); +} + +static __inline void +wrmsr_locked(u_int msr, u_int code, u_int64_t newval) +{ + __asm volatile("wrmsr" : + : "a" (newval & 0xffffffff), "d" (newval >> 32), "c" (msr), "D" (code)); +} + +static __inline void +wbinvd(void) +{ + __asm volatile("wbinvd" : : : "memory"); +} + +#ifdef MULTIPROCESSOR +int wbinvd_on_all_cpus(void); +void wbinvd_on_all_cpus_acked(void); +#else +static inline int +wbinvd_on_all_cpus(void) +{ + wbinvd(); + return 0; +} + +static inline int +wbinvd_on_all_cpus_acked(void) +{ + wbinvd(); + return 0; +} +#endif /* MULTIPROCESSOR */ + +static __inline void +clflush(u_int64_t addr) +{ + __asm volatile("clflush %0" : "+m" (*(volatile char *)addr)); +} + +static __inline void +mfence(void) +{ + __asm volatile("mfence" : : : "memory"); +} + +static __inline u_int64_t +rdtsc(void) +{ + uint32_t hi, lo; + + __asm volatile("rdtsc" : "=d" (hi), "=a" (lo)); + return (((uint64_t)hi << 32) | (uint64_t) lo); +} + +static __inline u_int64_t +rdtscp(void) +{ + uint32_t hi, lo; + + __asm volatile("rdtscp" : "=d" (hi), "=a" (lo) : : "ecx"); + return (((uint64_t)hi << 32) | (uint64_t) lo); +} + +static __inline u_int64_t +rdtsc_lfence(void) +{ + uint32_t hi, lo; + + __asm volatile("lfence; rdtsc" : "=d" (hi), "=a" (lo)); + return (((uint64_t)hi << 32) | (uint64_t) lo); +} + +static __inline u_int64_t +rdpmc(u_int pmc) +{ + uint32_t hi, lo; + + __asm volatile("rdpmc" : "=d" (hi), "=a" (lo) : "c" (pmc)); + return (((uint64_t)hi << 32) | (uint64_t) lo); +} + +static __inline void +monitor(const volatile void *addr, u_long extensions, u_int hints) +{ + + __asm volatile("monitor" + : : "a" (addr), "c" (extensions), "d" (hints)); +} + +static __inline void +mwait(u_long extensions, u_int hints) +{ + + __asm volatile( + " mwait ;" + " mov $8,%%rcx ;" + " .align 16,0x90 ;" + "3: call 5f ;" + "4: pause ;" + " lfence ;" + " call 4b ;" + " .align 16,0xcc ;" + "5: call 7f ;" + "6: pause ;" + " lfence ;" + " call 6b ;" + " .align 16,0xcc ;" + "7: loop 3b ;" + " add $(16*8),%%rsp" + : "+c" (extensions) : "a" (hints)); +} + +static __inline void +xsetbv(uint32_t reg, uint64_t mask) +{ + uint32_t lo, hi; + + lo = mask; + hi = mask >> 32; + __asm volatile("xsetbv" :: "c" (reg), "a" (lo), "d" (hi) : "memory"); +} + +static __inline uint64_t +xgetbv(uint32_t reg) +{ + uint32_t lo, hi; + + __asm volatile("xgetbv" : "=a" (lo), "=d" (hi) : "c" (reg)); + + return (((uint64_t)hi << 32) | (uint64_t)lo); +} + +static __inline void +stgi(void) +{ + __asm volatile("stgi"); +} + +static __inline void +clgi(void) +{ + __asm volatile("clgi"); +} + +/* Break into DDB. */ +static __inline void +breakpoint(void) +{ + __asm volatile("int $3"); +} + +/* VMGEXIT */ +static __inline void +vmgexit(void) +{ + /* rep; vmmcall encodes the vmgexit instruction */ + __asm volatile("rep; vmmcall"); +} + +void amd64_errata(struct cpu_info *); +void cpu_ucode_setup(void); +void cpu_ucode_apply(struct cpu_info *); + +struct cpu_info_full; +void cpu_enter_pages(struct cpu_info_full *); + +int rdmsr_safe(u_int msr, uint64_t *); + +#endif /* _KERNEL */ + +#endif /* !_MACHINE_CPUFUNC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/cpuvar.h b/lib/libc/include/x86_64-openbsd-none/amd64/cpuvar.h new file mode 100644 index 000000000000..c82e3adf881c --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/cpuvar.h @@ -0,0 +1,100 @@ +/* $OpenBSD: cpuvar.h,v 1.14 2024/10/22 10:14:49 jsg Exp $ */ +/* $NetBSD: cpuvar.h,v 1.1 2003/03/01 18:29:28 fvdl Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1999 Stefan Grefen + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +struct cpu_functions { + int (*start)(struct cpu_info *); + int (*stop)(struct cpu_info *); + void (*cleanup)(struct cpu_info *); +}; + +extern struct cpu_functions mp_cpu_funcs; + +#define CPU_ROLE_SP 0 +#define CPU_ROLE_BP 1 +#define CPU_ROLE_AP 2 + +struct cpu_attach_args { + const char *caa_name; + int cpu_apicid; + int cpu_acpi_proc_id; + int cpu_role; + struct cpu_functions *cpu_func; +}; + +#ifdef _KERNEL + +#ifdef MULTIPROCESSOR +extern void (*x86_ipi)(int,int,int); +void x86_ipi_init(int); +#endif + +void identifycpu(struct cpu_info *); +void cpu_init(struct cpu_info *); + +void tsc_test_sync_bp(struct cpu_info *); +void tsc_test_sync_ap(struct cpu_info *); + +#endif \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/db_machdep.h b/lib/libc/include/x86_64-openbsd-none/amd64/db_machdep.h new file mode 100644 index 000000000000..4a66d5a76198 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/db_machdep.h @@ -0,0 +1,101 @@ +/* $OpenBSD: db_machdep.h,v 1.19 2021/08/30 08:11:12 jasper Exp $ */ +/* $NetBSD: db_machdep.h,v 1.2 2003/04/29 17:06:04 scw Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#ifndef _MACHINE_DB_MACHDEP_H_ +#define _MACHINE_DB_MACHDEP_H_ + +/* + * Machine-dependent defines for new kernel debugger. + */ + +#include +#include +#include +#include + +typedef long db_expr_t; /* expression - signed */ + +typedef struct trapframe db_regs_t; + +extern db_regs_t ddb_regs; /* register state */ + +#define PC_REGS(regs) ((vaddr_t)(regs)->tf_rip) +#define SET_PC_REGS(regs, value) (regs)->tf_rip = (int64_t)(value) + +#define BKPT_ADDR(addr) (addr) /* breakpoint address */ +#define BKPT_INST 0xcc /* breakpoint instruction */ +#define BKPT_SIZE (1) /* size of breakpoint inst */ +#define BKPT_SET(inst) (BKPT_INST) + +#define SSF_INST 0x55 +#define SSF_SIZE (1) + +#define FIXUP_PC_AFTER_BREAK(regs) ((regs)->tf_rip -= BKPT_SIZE) + +#define db_clear_single_step(regs) ((regs)->tf_rflags &= ~PSL_T) +#define db_set_single_step(regs) ((regs)->tf_rflags |= PSL_T) + +#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BPTFLT) +#define IS_WATCHPOINT_TRAP(type, code) ((type) == T_TRCTRAP && (code) & 15) + +#define I_CALL 0xe8 +#define I_CALLI 0xff +#define I_RET 0xc3 +#define I_IRET 0xcf + +#define inst_trap_return(ins) (((ins)&0xff) == I_IRET) +#define inst_return(ins) (((ins)&0xff) == I_RET) +#define inst_call(ins) (((ins)&0xff) == I_CALL || \ + (((ins)&0xff) == I_CALLI && \ + ((ins)&0x3800) == 0x1000)) + +/* macro for checking if a thread has used floating-point */ + +int db_ktrap(int, int, db_regs_t *); + +void db_machine_init(void); +int db_enter_ddb(void); +void db_startcpu(int); +void db_stopcpu(int); +void x86_ipi_db(struct cpu_info *); + +#define DDB_STATE_NOT_RUNNING 0 +#define DDB_STATE_RUNNING 1 +#define DDB_STATE_EXITING 2 + +/* + * We define some of our own commands + */ +#define DB_MACHINE_COMMANDS + +extern void db_machine_init(void); + +extern void cpu_debug_dump(void); + +#endif /* _MACHINE_DB_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/disklabel.h b/lib/libc/include/x86_64-openbsd-none/amd64/disklabel.h new file mode 100644 index 000000000000..44d225a0a846 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/disklabel.h @@ -0,0 +1,40 @@ +/* $OpenBSD: disklabel.h,v 1.11 2015/09/30 14:57:03 krw Exp $ */ + +/* + * Copyright (c) 1994 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_DISKLABEL_H_ +#define _MACHINE_DISKLABEL_H_ + +#define LABELSECTOR 1 /* sector containing label */ +#define LABELOFFSET 0 /* offset of label in sector */ +#define MAXPARTITIONS 16 /* number of partitions */ + +#endif /* _MACHINE_DISKLABEL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/efifbvar.h b/lib/libc/include/x86_64-openbsd-none/amd64/efifbvar.h new file mode 100644 index 000000000000..1958da38bcad --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/efifbvar.h @@ -0,0 +1,40 @@ +/* $OpenBSD: efifbvar.h,v 1.10 2019/05/04 11:34:47 kettenis Exp $ */ + +/* + * Copyright (c) 2015 YASUOKA Masahiko + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_EFIFB_H_ +#define _MACHINE_EFIFB_H_ + +struct efifb_attach_args { + const char *eaa_name; +}; + +struct pci_attach_args; + +int efifb_cnattach(void); +void efifb_cnremap(void); +int efifb_is_console(struct pci_attach_args *); +int efifb_is_primary(struct pci_attach_args *); +void efifb_detach(void); +void efifb_reattach(void); + +int efifb_cb_found(void); +int efifb_cb_cnattach(void); + +psize_t efifb_stolen(void); + +#endif /* _MACHINE_EFIFB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/efivar.h b/lib/libc/include/x86_64-openbsd-none/amd64/efivar.h new file mode 100644 index 000000000000..72645470e802 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/efivar.h @@ -0,0 +1,42 @@ +/* $OpenBSD: efivar.h,v 1.1 2023/01/14 12:11:10 kettenis Exp $ */ +/* + * Copyright (c) 2022 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_EFIVAR_H_ +#define _MACHINE_EFIVAR_H_ + +#include + +struct efi_softc { + struct device sc_dev; + struct pmap *sc_pm; + EFI_RUNTIME_SERVICES *sc_rs; + EFI_SYSTEM_RESOURCE_TABLE *sc_esrt; + u_long sc_psw; + uint64_t sc_cr3; + + struct todr_chip_handle sc_todr; +}; + +void efi_enter(struct efi_softc *); +void efi_leave(struct efi_softc *); + +extern label_t efi_jmpbuf; + +#define efi_enter_check(sc) (setjmp(&efi_jmpbuf) ? \ + (efi_leave(sc), EFAULT) : (efi_enter(sc), 0)) + +#endif /* _MACHINE_EFIVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/elf.h b/lib/libc/include/x86_64-openbsd-none/amd64/elf.h new file mode 100644 index 000000000000..1cd8fda26a98 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/elf.h @@ -0,0 +1,7 @@ +/* $OpenBSD: elf.h,v 1.1 2024/07/14 09:48:48 jca Exp $ */ + +/* + * This file is in the public domain. + */ + +/* Nothing for now */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/endian.h b/lib/libc/include/x86_64-openbsd-none/amd64/endian.h new file mode 100644 index 000000000000..7ff7b356d9c6 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/endian.h @@ -0,0 +1,36 @@ +/* $OpenBSD: endian.h,v 1.8 2024/05/07 14:26:48 naddy Exp $ */ + +/*- + * Copyright (c) 1997 Niklas Hallqvist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_ENDIAN_H_ +#define _MACHINE_ENDIAN_H_ + +#define _BYTE_ORDER _LITTLE_ENDIAN + +#ifndef __FROM_SYS__ENDIAN +#include +#endif + +#endif /* _MACHINE_ENDIAN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/exec.h b/lib/libc/include/x86_64-openbsd-none/amd64/exec.h new file mode 100644 index 000000000000..8fafeb9b4c03 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/exec.h @@ -0,0 +1,17 @@ +/* $OpenBSD: exec.h,v 1.7 2017/02/08 05:09:25 guenther Exp $ */ +/* + * Written by Artur Grabowski Public Domain + */ + +#ifndef _MACHINE_EXEC_H_ +#define _MACHINE_EXEC_H_ + +#define __LDPGSZ 4096 + +#define ARCH_ELFSIZE 64 + +#define ELF_TARG_CLASS ELFCLASS64 +#define ELF_TARG_DATA ELFDATA2LSB +#define ELF_TARG_MACH EM_AMD64 + +#endif \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/fenv.h b/lib/libc/include/x86_64-openbsd-none/amd64/fenv.h new file mode 100644 index 000000000000..0b16f62459cb --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/fenv.h @@ -0,0 +1,115 @@ +/* $OpenBSD: fenv.h,v 1.4 2011/05/25 21:46:49 martynas Exp $ */ +/* $NetBSD: fenv.h,v 1.1 2010/07/31 21:47:54 joerg Exp $ */ + +/*- + * Copyright (c) 2004-2005 David Schultz + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _AMD64_FENV_H_ +#define _AMD64_FENV_H_ + +/* + * Each symbol representing a floating point exception expands to an integer + * constant expression with values, such that bitwise-inclusive ORs of _all + * combinations_ of the constants result in distinct values. + * + * We use such values that allow direct bitwise operations on FPU/SSE registers. + */ +#define FE_INVALID 0x01 +#define FE_DENORMAL 0x02 +#define FE_DIVBYZERO 0x04 +#define FE_OVERFLOW 0x08 +#define FE_UNDERFLOW 0x10 +#define FE_INEXACT 0x20 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * exception constants defined above. + */ +#define FE_ALL_EXCEPT (FE_INVALID | FE_DENORMAL | FE_DIVBYZERO | \ + FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) +#define _SSE_MASK_SHIFT 7 + +/* + * Each symbol representing the rounding direction, expands to an integer + * constant expression whose value is distinct non-negative value. + * + * We use such values that allow direct bitwise operations on FPU/SSE registers. + */ +#define FE_TONEAREST 0x000 +#define FE_DOWNWARD 0x400 +#define FE_UPWARD 0x800 +#define FE_TOWARDZERO 0xc00 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * rounding direction constants defined above. + */ +#define _X87_ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | \ + FE_TOWARDZERO) +#define _SSE_ROUND_SHIFT 3 + +/* + * fenv_t represents the entire floating-point environment. + */ +typedef struct { + struct { + unsigned int __control; /* Control word register */ + unsigned int __status; /* Status word register */ + unsigned int __tag; /* Tag word register */ + unsigned int __others[4]; /* EIP, Pointer Selector, etc */ + } __x87; + unsigned int __mxcsr; /* Control, status register */ +} fenv_t; + +/* + * The following constant represents the default floating-point environment + * (that is, the one installed at program startup) and has type pointer to + * const-qualified fenv_t. + * + * It can be used as an argument to the functions within the header + * that manage the floating-point environment, namely fesetenv() and + * feupdateenv(). + */ +__BEGIN_DECLS +extern fenv_t __fe_dfl_env; +__END_DECLS +#define FE_DFL_ENV ((const fenv_t *)&__fe_dfl_env) + +/* + * fexcept_t represents the floating-point status flags collectively, including + * any status the implementation associates with the flags. + * + * A floating-point status flag is a system variable whose value is set (but + * never cleared) when a floating-point exception is raised, which occurs as a + * side effect of exceptional floating-point arithmetic to provide auxiliary + * information. + * + * A floating-point control mode is a system variable whose value may be set by + * the user to affect the subsequent behavior of floating-point arithmetic. + */ +typedef unsigned int fexcept_t; + +#endif /* !_AMD64_FENV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/fpu.h b/lib/libc/include/x86_64-openbsd-none/amd64/fpu.h new file mode 100644 index 000000000000..b79b7a27c45c --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/fpu.h @@ -0,0 +1,111 @@ +/* $OpenBSD: fpu.h,v 1.20 2024/04/14 09:59:04 kettenis Exp $ */ +/* $NetBSD: fpu.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $ */ + +#ifndef _MACHINE_FPU_H_ +#define _MACHINE_FPU_H_ + +#include + +/* + * If the CPU supports xsave/xrstor then we use them so that we can provide + * AVX support. Otherwise we require fxsave/fxrstor, as the SSE registers + * are part of the ABI for passing floating point values. + * While fxsave/fxrstor only required 16-byte alignment for the save area, + * xsave/xrstor requires the save area to have 64-byte alignment. + */ + +struct fxsave64 { + u_int16_t fx_fcw; + u_int16_t fx_fsw; + u_int8_t fx_ftw; + u_int8_t fx_unused1; + u_int16_t fx_fop; + u_int64_t fx_rip; + u_int64_t fx_rdp; + u_int32_t fx_mxcsr; + u_int32_t fx_mxcsr_mask; + u_int64_t fx_st[8][2]; /* 8 normal FP regs */ + u_int64_t fx_xmm[16][2]; /* 16 SSE2 registers */ + u_int8_t fx_unused3[96]; +} __packed; + +struct xstate_hdr { + uint64_t xstate_bv; + uint64_t xstate_xcomp_bv; + uint8_t xstate_rsrv0[8]; + uint8_t xstate_rsrv[40]; +} __packed; + +struct savefpu { + struct fxsave64 fp_fxsave; /* see above */ + struct xstate_hdr fp_xstate; + u_int64_t fp_ymm[16][2]; + u_int8_t fp_components[1856]; /* enough for AVX-512 */ +}; + +/* + * The i387 defaults to Intel extended precision mode and round to nearest, + * with all exceptions masked. + */ +#define __INITIAL_NPXCW__ 0x037f +#define __INITIAL_MXCSR__ 0x1f80 +#define __INITIAL_MXCSR_MASK__ 0xffbf + +#ifdef _KERNEL +/* + * XXX + */ +struct trapframe; +struct cpu_info; + +extern size_t fpu_save_len; +extern uint32_t fpu_mxcsr_mask; +extern uint64_t xsave_mask; +extern int cpu_use_xsaves; + +void fpuinit(struct cpu_info *); +int fputrap(int _type); +void fpusave(struct savefpu *); +void fpusavereset(struct savefpu *); +void fpu_kernel_enter(void); +void fpu_kernel_exit(void); + +/* pointer to fxsave/xsave/xsaves data with everything reset */ +#define fpu_cleandata (&proc0.p_addr->u_pcb.pcb_savefpu) + +int xrstor_user(struct savefpu *_addr, uint64_t _mask); +void xrstor_kern(struct savefpu *_addr, uint64_t _mask); +#define fpureset() \ + xrstor_kern(fpu_cleandata, xsave_mask) +int xsetbv_user(uint32_t _reg, uint64_t _mask); + +#define fninit() __asm("fninit") +#define fwait() __asm("fwait") +/* should be fxsave64, but where we use this it doesn't matter */ +#define fxsave(addr) __asm("fxsave %0" : "=m" (*addr)) +#define ldmxcsr(addr) __asm("ldmxcsr %0" : : "m" (*addr)) +#define fldcw(addr) __asm("fldcw %0" : : "m" (*addr)) + +static inline void +xsave(struct savefpu *addr, uint64_t mask) +{ + uint32_t lo, hi; + + lo = mask; + hi = mask >> 32; + __asm volatile("xsave64 %0" : "+m" (*addr) : "a" (lo), "d" (hi)); +} + +static inline void +xrstors(const struct savefpu *addr, uint64_t mask) +{ + uint32_t lo, hi; + + lo = mask; + hi = mask >> 32; + __asm volatile("xrstors64 %0" : : "m" (*addr), "a" (lo), "d" (hi)); +} + +#endif + +#endif /* _MACHINE_FPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/frame.h b/lib/libc/include/x86_64-openbsd-none/amd64/frame.h new file mode 100644 index 000000000000..bd9658dec45d --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/frame.h @@ -0,0 +1,174 @@ +/* $OpenBSD: frame.h,v 1.11 2024/01/31 06:06:28 guenther Exp $ */ +/* $NetBSD: frame.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)frame.h 5.2 (Berkeley) 1/18/91 + */ + +/* + * Adapted for NetBSD/amd64 by fvdl@wasabisystems.com + */ + +#ifndef _MACHINE_FRAME_H_ +#define _MACHINE_FRAME_H_ + +#include +#include + +/* + * System stack frames. + */ + +/* + * Exception/Trap Stack Frame + */ +struct trapframe { + int64_t tf_rdi; /* ordered by syscall args... */ + int64_t tf_rsi; + int64_t tf_rdx; + int64_t tf_r10; + int64_t tf_r8; + int64_t tf_r9; /* ...to here */ + int64_t tf_rcx; + int64_t tf_r11; + int64_t tf_r12; + int64_t tf_r13; + int64_t tf_r14; + int64_t tf_r15; + int64_t tf_err; /* not the hardware position */ + int64_t tf_rbx; + int64_t tf_rax; + int64_t tf_trapno; + int64_t tf_rbp; /* hardware puts err here, INTRENTRY() moves it up */ + /* below portion defined in hardware */ + int64_t tf_rip; + int64_t tf_cs; + int64_t tf_rflags; + /* These are pushed unconditionally on the x86-64 */ + int64_t tf_rsp; + int64_t tf_ss; +}; + +/* + * Interrupt stack frame + */ +struct intrframe { + int64_t if_rdi; + int64_t if_rsi; + int64_t if_rdx; + int64_t if_r10; + int64_t if_r8; + int64_t if_r9; + int64_t if_rcx; + int64_t if_r11; + int64_t if_r12; + int64_t if_r13; + int64_t if_r14; + int64_t if_r15; + int64_t if_err; /* IREENT_MAGIC if resume/recurse */ + int64_t if_rbx; + int64_t if_rax; + int64_t if_ppl; /* previous priority level */ + int64_t if_rbp; + /* below portion defined in hardware */ + int64_t if_rip; + int64_t if_cs; + int64_t if_rflags; + /* These are pushed unconditionally on the x86-64 */ + int64_t if_rsp; + int64_t if_ss; +}; + + +/* + * The trampoline frame used on the kernel stack page which is present + * but kernel-only, in the page tables used when in userspace. This is + * the minimum for iretq operation. + */ +struct iretq_frame { + int64_t iretq_rip; + int64_t iretq_cs; + int64_t iretq_rflags; + int64_t iretq_rsp; + int64_t iretq_ss; +}; + +/* + * Stack frame inside cpu_switch() + */ +struct switchframe { + int64_t sf_r15; + int64_t sf_r14; + int64_t sf_r13; + int64_t sf_r12; + int64_t sf_rbp; + int64_t sf_rbx; + int64_t sf_rip; +}; + +struct callframe { + struct callframe *f_frame; + long f_retaddr; + long f_arg0; +}; + +#endif /* _MACHINE_FRAME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/frameasm.h b/lib/libc/include/x86_64-openbsd-none/amd64/frameasm.h new file mode 100644 index 000000000000..0ef22deefb18 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/frameasm.h @@ -0,0 +1,199 @@ +/* $OpenBSD: frameasm.h,v 1.27 2023/07/27 00:30:07 guenther Exp $ */ +/* $NetBSD: frameasm.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $ */ + +#ifndef _AMD64_MACHINE_FRAMEASM_H +#define _AMD64_MACHINE_FRAMEASM_H + +/* + * Macros to define pushing/popping frames for interrupts, traps + * and system calls. Currently all the same; will diverge later. + */ + +/* + * These are used on interrupt or trap entry or exit. + */ +#define INTR_SAVE_GPRS \ + subq $120,%rsp ; \ + INTR_SAVE_MOST_GPRS_NO_ADJ ; \ + movq %rcx,TF_RCX(%rsp) +#define INTR_SAVE_MOST_GPRS_NO_ADJ \ + movq %r15,TF_R15(%rsp) ; \ + movq %r14,TF_R14(%rsp) ; \ + movq %r13,TF_R13(%rsp) ; \ + movq %r12,TF_R12(%rsp) ; \ + movq %r11,TF_R11(%rsp) ; \ + movq %r10,TF_R10(%rsp) ; \ + movq %r9,TF_R9(%rsp) ; \ + movq %r8,TF_R8(%rsp) ; \ + movq %rdi,TF_RDI(%rsp) ; \ + movq %rsi,TF_RSI(%rsp) ; \ + movq %rbp,TF_RBP(%rsp) ; \ + leaq TF_RBP(%rsp),%rbp ; \ + movq %rbx,TF_RBX(%rsp) ; \ + movq %rdx,TF_RDX(%rsp) ; \ + movq %rax,TF_RAX(%rsp) + +/* + * We clear registers when coming from userspace to prevent + * user-controlled values from being available for use in speculative + * execution in the kernel. %rsp and %rbp are the kernel values when + * this is used, so there are only 14 to clear. 32bit operations clear + * the register upper-halves automatically. + */ +#define INTR_CLEAR_GPRS \ + xorl %eax,%eax ; \ + xorl %ebx,%ebx ; \ + xorl %ecx,%ecx ; \ + xorl %edx,%edx ; \ + xorl %esi,%esi ; \ + xorl %edi,%edi ; \ + xorl %r8d,%r8d ; \ + xorl %r9d,%r9d ; \ + xorl %r10d,%r10d ; \ + xorl %r11d,%r11d ; \ + xorl %r12d,%r12d ; \ + xorl %r13d,%r13d ; \ + xorl %r14d,%r14d ; \ + xorl %r15d,%r15d + + +/* + * For real interrupt code paths, where we can come from userspace. + * We only have an iretq_frame on entry. + */ +#define INTRENTRY_LABEL(label) X##label##_untramp +#define INTRENTRY(label) \ + endbr64 ; \ + testb $SEL_RPL,IRETQ_CS(%rsp) ; \ + je INTRENTRY_LABEL(label) ; \ + swapgs ; \ + FENCE_SWAPGS_MIS_TAKEN ; \ + movq %rax,CPUVAR(SCRATCH) ; \ + CODEPATCH_START ; \ + movq CPUVAR(KERN_CR3),%rax ; \ + movq %rax,%cr3 ; \ + CODEPATCH_END(CPTAG_MELTDOWN_NOP);\ + jmp 98f ; \ +END(X##label) ; \ +_ENTRY(INTRENTRY_LABEL(label)) /* from kernel */ \ + FENCE_NO_SAFE_SMAP ; \ + subq $TF_RIP,%rsp ; \ + movq %rcx,TF_RCX(%rsp) ; \ + jmp 99f ; \ + _ALIGN_TRAPS ; \ +98: /* from userspace */ \ + movq CPUVAR(KERN_RSP),%rax ; \ + xchgq %rax,%rsp ; \ + movq %rcx,TF_RCX(%rsp) ; \ + RET_STACK_REFILL_WITH_RCX ; \ + /* copy iretq frame to the trap frame */ \ + movq IRETQ_RIP(%rax),%rcx ; \ + movq %rcx,TF_RIP(%rsp) ; \ + movq IRETQ_CS(%rax),%rcx ; \ + movq %rcx,TF_CS(%rsp) ; \ + movq IRETQ_RFLAGS(%rax),%rcx ; \ + movq %rcx,TF_RFLAGS(%rsp) ; \ + movq IRETQ_RSP(%rax),%rcx ; \ + movq %rcx,TF_RSP(%rsp) ; \ + movq IRETQ_SS(%rax),%rcx ; \ + movq %rcx,TF_SS(%rsp) ; \ + movq CPUVAR(SCRATCH),%rax ; \ +99: INTR_SAVE_MOST_GPRS_NO_ADJ ; \ + INTR_CLEAR_GPRS ; \ + movq %rax,TF_ERR(%rsp) + +#define INTRFASTEXIT \ + jmp intr_fast_exit + +/* + * Entry for faking up an interrupt frame after spllower() unblocks + * a previously received interrupt. On entry, %r13 has the %rip + * to return to. %r10 and %r11 are scratch. + */ +#define INTR_RECURSE \ + endbr64 ; \ + /* fake the iretq_frame */ ; \ + movq %rsp,%r10 ; \ + movl %ss,%r11d ; \ + pushq %r11 ; \ + pushq %r10 ; \ + pushfq ; \ + movl %cs,%r11d ; \ + pushq %r11 ; \ + pushq %r13 ; \ + /* now do the rest of the intrframe */ \ + subq $16,%rsp ; \ + INTR_SAVE_GPRS + + +/* + * Entry for traps from kernel, where there's a trapno + err already + * on the stack. We have to move the err from its hardware location + * to the location we want it. + */ +#define TRAP_ENTRY_KERN \ + subq $120,%rsp ; \ + movq %rcx,TF_RCX(%rsp) ; \ + movq (TF_RIP - 8)(%rsp),%rcx ; \ + movq %rcx,TF_ERR(%rsp) ; \ + INTR_SAVE_MOST_GPRS_NO_ADJ + +/* + * Entry for traps from userland, where there's a trapno + err on + * the iretq stack. + * Assumes that %rax has been saved in CPUVAR(SCRATCH). + */ +#define TRAP_ENTRY_USER \ + movq CPUVAR(KERN_RSP),%rax ; \ + xchgq %rax,%rsp ; \ + movq %rcx,TF_RCX(%rsp) ; \ + RET_STACK_REFILL_WITH_RCX ; \ + /* copy trapno+err to the trap frame */ \ + movq 0(%rax),%rcx ; \ + movq %rcx,TF_TRAPNO(%rsp) ; \ + movq 8(%rax),%rcx ; \ + movq %rcx,TF_ERR(%rsp) ; \ + /* copy iretq frame to the trap frame */ \ + movq (IRETQ_RIP+16)(%rax),%rcx ; \ + movq %rcx,TF_RIP(%rsp) ; \ + movq (IRETQ_CS+16)(%rax),%rcx ; \ + movq %rcx,TF_CS(%rsp) ; \ + movq (IRETQ_RFLAGS+16)(%rax),%rcx ; \ + movq %rcx,TF_RFLAGS(%rsp) ; \ + movq (IRETQ_RSP+16)(%rax),%rcx ; \ + movq %rcx,TF_RSP(%rsp) ; \ + movq (IRETQ_SS+16)(%rax),%rcx ; \ + movq %rcx,TF_SS(%rsp) ; \ + movq CPUVAR(SCRATCH),%rax ; \ + INTR_SAVE_MOST_GPRS_NO_ADJ ; \ + INTR_CLEAR_GPRS + +/* + * Entry from syscall instruction, where RIP is in %rcx and RFLAGS is in %r11. + * We stash the syscall # in tf_err for SPL check. + * Assumes that %rax has been saved in CPUVAR(SCRATCH). + */ +#define SYSCALL_ENTRY \ + movq CPUVAR(KERN_RSP),%rax ; \ + xchgq %rax,%rsp ; \ + movq %rcx,TF_RCX(%rsp) ; \ + movq %rcx,TF_RIP(%rsp) ; \ + RET_STACK_REFILL_WITH_RCX ; \ + movq $(GSEL(GUDATA_SEL, SEL_UPL)),TF_SS(%rsp) ; \ + movq %rax,TF_RSP(%rsp) ; \ + movq CPUVAR(SCRATCH),%rax ; \ + INTR_SAVE_MOST_GPRS_NO_ADJ ; \ + movq %r11, TF_RFLAGS(%rsp) ; \ + movq $(GSEL(GUCODE_SEL, SEL_UPL)), TF_CS(%rsp) ; \ + movq %rax,TF_ERR(%rsp) ; \ + INTR_CLEAR_GPRS + +#define CHECK_ASTPENDING(reg) movq CPUVAR(CURPROC),reg ; \ + cmpq $0, reg ; \ + je 99f ; \ + cmpl $0, P_MD_ASTPENDING(reg) ; \ + 99: + +#define CLEAR_ASTPENDING(reg) movl $0, P_MD_ASTPENDING(reg) + +#endif /* _AMD64_MACHINE_FRAMEASM_H */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/gdt.h b/lib/libc/include/x86_64-openbsd-none/amd64/gdt.h new file mode 100644 index 000000000000..0e9ba4aa905c --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/gdt.h @@ -0,0 +1,33 @@ +/* $OpenBSD: gdt.h,v 1.6 2018/02/21 19:24:15 guenther Exp $ */ +/* $NetBSD: gdt.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $ */ + +/*- + * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by John T. Kohl and Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +void gdt_init_cpu(struct cpu_info *); \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/ghcb.h b/lib/libc/include/x86_64-openbsd-none/amd64/ghcb.h new file mode 100644 index 000000000000..73f9484212bb --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/ghcb.h @@ -0,0 +1,251 @@ +/* $OpenBSD: ghcb.h,v 1.6 2025/09/17 18:37:44 sf Exp $ */ + +/* + * Copyright (c) 2024, 2025 Hans-Joerg Hoexer + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_GHCB_H_ +#define _MACHINE_GHCB_H_ + +#ifndef _LOCORE + +#include + +#include + +#define GHCB_OFFSET(m) ((m) / 8) +#define GHCB_IDX(m) (GHCB_OFFSET((m)) / 8) +#define GHCB_BIT(m) (GHCB_OFFSET((m)) % 8) + +#define GHCB_XSS 0x140 +#define GHCB_RAX 0x1F8 +#define GHCB_RBX 0x318 +#define GHCB_RCX 0x308 +#define GHCB_RDX 0x310 +#define GHCB_SW_EXITCODE 0x390 +#define GHCB_SW_EXITINFO1 0x398 +#define GHCB_SW_EXITINFO2 0x3A0 +#define GHCB_SW_SCRATCH 0x3A8 +#define GHCB_XCR0 0x3E8 + +#define GHCB_MAX 0xFFF + +struct ghcb_sa { + uint8_t v_pad0[0xcb]; /* 000h-0CAh */ + uint8_t v_cpl; /* 0CBh */ + uint8_t v_pad1[0x74]; /* 0CCh-13Fh */ + uint64_t v_xss; /* 140h */ + uint8_t v_pad2[0x18]; /* 148h-15Fh */ + uint64_t v_dr7; /* 160h */ + uint8_t v_pad3[0x10]; /* 168h-177h */ + uint64_t v_rip; /* 178h */ + uint8_t v_pad4[0x58]; /* 180h-1D7h */ + uint64_t v_rsp; /* 1D8h */ + uint8_t v_pad5[0x18]; /* 1E0h-1F7h */ + uint64_t v_rax; /* 1F8h */ + uint8_t v_pad6[0x108]; /* 200h-307h */ + uint64_t v_rcx; /* 308h */ + uint64_t v_rdx; /* 310h */ + uint64_t v_rbx; /* 318h */ + uint8_t v_pad7[0x8]; /* 320h-327h */ + uint64_t v_rbp; /* 328h */ + uint64_t v_rsi; /* 330h */ + uint64_t v_rdi; /* 338h */ + uint64_t v_r8; /* 340h */ + uint64_t v_r9; /* 348h */ + uint64_t v_r10; /* 350h */ + uint64_t v_r11; /* 358h */ + uint64_t v_r12; /* 360h */ + uint64_t v_r13; /* 368h */ + uint64_t v_r14; /* 370h */ + uint64_t v_r15; /* 378h */ + uint8_t v_pad8[0x10]; /* 380h-38Fh */ + uint64_t v_sw_exitcode; /* 390h */ + uint64_t v_sw_exitinfo1; /* 398h */ + uint64_t v_sw_exitinfo2; /* 3a0h */ + uint64_t v_sw_scratch; /* 3a8h */ + uint8_t v_pad9[0x38]; /* 3B0h-3E7h */ + uint64_t v_xcr0; /* 3E8h */ +#define GHCB_VB_SZ 0x10 + uint8_t valid_bitmap[GHCB_VB_SZ]; + /* 3F0h-3FFh */ + uint64_t v_x87_state_gpa; /* 400h */ + uint8_t v_pad10[0x3f8]; /* 408h-7FFh */ + uint8_t v_sharedbuf[0x7f0]; /* 800h-FEFh */ + uint8_t v_pad11[0xa]; /* FF0h-FF9h */ + uint16_t v_ghcb_proto_version; /* FFAh-FFBh */ + uint32_t v_ghcb_usage; /* FFCh-FFFh */ +}; + +#define GHCB_SZ8 0 +#define GHCB_SZ16 1 +#define GHCB_SZ32 2 +#define GHCB_SZ64 3 + +struct ghcb_sync { + uint8_t valid_bitmap[GHCB_VB_SZ]; + + int sz_a; + int sz_b; + int sz_c; + int sz_d; +}; +#endif /* !_LOCORE */ + +/* Definitions used with the MSR protocol */ +#define MSR_PROTO_CPUID_REQ 0x4 +#define MSR_PROTO_CPUID_RESP 0x5 +#define MSR_PROTO_TERMINATE 0x100 + +#ifndef _LOCORE + +extern vaddr_t ghcb_vaddr; +extern paddr_t ghcb_paddr; + +struct ghcb_extra_regs { + uint64_t exitcode; + uint64_t exitinfo1; + uint64_t exitinfo2; + uint64_t scratch; + void *data; + size_t data_sz; +}; + +void ghcb_clear(struct ghcb_sa *); +int ghcb_valbm_set(uint8_t *, int); +int ghcb_valbm_isset(uint8_t *, int); +int ghcb_verify_bm(uint8_t *, uint8_t *); +int ghcb_valid(struct ghcb_sa *); + +void ghcb_sync_val(int, int, struct ghcb_sync *); +void ghcb_sync_out(struct trapframe *, const struct ghcb_extra_regs *, + struct ghcb_sa *, struct ghcb_sync *); +void ghcb_sync_in(struct trapframe *, struct ghcb_extra_regs *, + struct ghcb_sa *, struct ghcb_sync *); +void _ghcb_mem_rw(vaddr_t, int, void *, bool); +void _ghcb_io_rw(uint16_t, int, uint32_t *, bool); + +static inline uint8_t +ghcb_mem_read_1(vaddr_t addr) +{ + uint8_t val; + + _ghcb_mem_rw(addr, GHCB_SZ8, &val, true); + return val; +} + +static inline uint16_t +ghcb_mem_read_2(vaddr_t addr) +{ + uint16_t val; + + _ghcb_mem_rw(addr, GHCB_SZ16, &val, true); + return val; +} + +static inline uint32_t +ghcb_mem_read_4(vaddr_t addr) +{ + uint32_t val; + + _ghcb_mem_rw(addr, GHCB_SZ32, &val, true); + return val; +} + +static inline uint64_t +ghcb_mem_read_8(vaddr_t addr) +{ + uint64_t val; + + _ghcb_mem_rw(addr, GHCB_SZ64, &val, true); + return val; +} + +static inline void +ghcb_mem_write_1(vaddr_t addr, uint8_t v) +{ + _ghcb_mem_rw(addr, GHCB_SZ8, &v, false); +} + +static inline void +ghcb_mem_write_2(vaddr_t addr, uint16_t v) +{ + _ghcb_mem_rw(addr, GHCB_SZ16, &v, false); +} + +static inline void +ghcb_mem_write_4(vaddr_t addr, uint32_t v) +{ + _ghcb_mem_rw(addr, GHCB_SZ32, &v, false); +} + +static inline void +ghcb_mem_write_8(vaddr_t addr, uint64_t v) +{ + _ghcb_mem_rw(addr, GHCB_SZ64, &v, false); +} + +static inline uint8_t +ghcb_io_read_1(uint16_t port) +{ + uint32_t val; + + _ghcb_io_rw(port, GHCB_SZ8, &val, true); + return val; +} + +static inline uint16_t +ghcb_io_read_2(uint16_t port) +{ + uint32_t val; + + _ghcb_io_rw(port, GHCB_SZ16, &val, true); + return val; +} + +static inline uint32_t +ghcb_io_read_4(uint16_t port) +{ + uint32_t val; + + _ghcb_io_rw(port, GHCB_SZ32, &val, true); + return val; +} + +static inline void +ghcb_io_write_1(uint16_t port, uint8_t v) +{ + uint32_t val = v; + + _ghcb_io_rw(port, GHCB_SZ8, &val, false); +} + +static inline void +ghcb_io_write_2(uint16_t port, uint16_t v) +{ + uint32_t val = v; + + _ghcb_io_rw(port, GHCB_SZ16, &val, false); +} + +static inline void +ghcb_io_write_4(uint16_t port, uint32_t v) +{ + _ghcb_io_rw(port, GHCB_SZ32, &v, false); +} + +#endif /* !_LOCORE */ + +#endif /* !_MACHINE_GHCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/hibernate.h b/lib/libc/include/x86_64-openbsd-none/amd64/hibernate.h new file mode 100644 index 000000000000..09f2c2bbe8c8 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/hibernate.h @@ -0,0 +1,36 @@ +/* $OpenBSD: hibernate.h,v 1.7 2018/06/21 07:33:30 mlarkin Exp $ */ + +/* + * Copyright (c) 2011 Mike Larkin + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +/* amd64 hibernate support structures and functions */ + +int get_hibernate_info_md(union hibernate_info *); +void hibernate_flush(void); +void hibernate_enter_resume_mapping(vaddr_t, paddr_t, int); +int hibernate_inflate_skip(union hibernate_info *, paddr_t); +int hibernate_suspend(void); +void hibernate_switch_stack_machdep(void); +void hibernate_resume_machdep(vaddr_t); +void hibernate_activate_resume_pt_machdep(void); +void hibernate_enable_intr_machdep(void); +void hibernate_disable_intr_machdep(void); +#ifdef MULTIPROCESSOR +void hibernate_quiesce_cpus(void); +void hibernate_drop_to_real_mode(void); +#endif /* MULTIPROCESSOR */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/hibernate_var.h b/lib/libc/include/x86_64-openbsd-none/amd64/hibernate_var.h new file mode 100644 index 000000000000..f65025fe94c8 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/hibernate_var.h @@ -0,0 +1,75 @@ +/* $OpenBSD: hibernate_var.h,v 1.14 2025/09/13 13:43:47 mlarkin Exp $ */ + +/* + * Copyright (c) 2011 Mike Larkin + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define PIGLET_PAGE_MASK (L2_FRAME) + +/* + * PML4 table for resume + */ +#define HIBERNATE_PML4T (PAGE_SIZE * 21) + +/* + * amd64 uses a PDPT to map the first 512GB phys mem plus one more + * to map any ranges of phys mem past 512GB (if needed) + */ +#define HIBERNATE_PDPT_LOW (PAGE_SIZE * 22) +#define HIBERNATE_PDPT_HI (PAGE_SIZE * 23) + +/* + * amd64 uses one PD to map the first 1GB phys mem plus one more to map any + * other 1GB ranges within the first 512GB phys, plus one more to map any + * 1GB range in any subsequent 512GB range + */ +#define HIBERNATE_PD_LOW (PAGE_SIZE * 24) +#define HIBERNATE_PD_LOW2 (PAGE_SIZE * 25) +#define HIBERNATE_PD_HI (PAGE_SIZE * 26) + +/* + * amd64 uses one PT to map the first 2MB phys mem plus one more to map any + * other 2MB range within the first 1GB, plus one more to map any 2MB range + * in any subsequent 512GB range. + */ +#define HIBERNATE_PT_LOW (PAGE_SIZE * 27) +#define HIBERNATE_PT_LOW2 (PAGE_SIZE * 28) +#define HIBERNATE_PT_HI (PAGE_SIZE * 29) + +/* 3 pages for stack */ +#define HIBERNATE_STACK_PAGE (PAGE_SIZE * 32) + +#define HIBERNATE_INFLATE_PAGE (PAGE_SIZE * 33) +/* HIBERNATE_HIBALLOC_PAGE must be the last stolen page (see machdep.c) */ +#define HIBERNATE_HIBALLOC_PAGE (PAGE_SIZE * 34) + +/* Use 4MB hibernation chunks */ +#define HIBERNATE_CHUNK_SIZE 0x400000 + +#define HIBERNATE_CHUNK_TABLE_SIZE 0x200000 + +#define HIBERNATE_STACK_OFFSET 0x0F00 + +/* + * Minimum amount of memory for hibernate support. This is used in early boot + * when deciding if we can preallocate the piglet. If the machine does not + * have at least HIBERNATE_MIN_MEMORY RAM, we won't support hibernate. This + * avoids late allocation issues due to fragmented memory and failure to + * hibernate. We need to be able to allocate 16MB contiguous memory, aligned + * to 2MB. + * + * The default minimum required memory is 512MB (1ULL << 29). + */ +#define HIBERNATE_MIN_MEMORY (1ULL << 29) \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/i82093reg.h b/lib/libc/include/x86_64-openbsd-none/amd64/i82093reg.h new file mode 100644 index 000000000000..c5b341fb947d --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/i82093reg.h @@ -0,0 +1,135 @@ +/* $OpenBSD: i82093reg.h,v 1.9 2025/09/05 16:57:48 kettenis Exp $ */ +/* $NetBSD: i82093reg.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Typically, the first apic lives here. + */ +#define IOAPIC_BASE_DEFAULT 0xfec00000 + +/* + * Memory-space registers. + */ + +/* + * The externally visible registers are all 32 bits wide; + * store the register number of interest in IOAPIC_REG, and store/fetch + * the real value in IOAPIC_DATA. + */ +#define IOAPIC_REG 0x0000 +#define IOAPIC_DATA 0x0010 + +/* + * Internal I/O APIC registers. + */ + +#define IOAPIC_ID 0x00 + +#define IOAPIC_ID_SHIFT 24 +#define IOAPIC_ID_MASK 0x0f000000 + +/* Version, and maximum interrupt pin number. */ + +#define IOAPIC_VER 0x01 + +#define IOAPIC_VER_SHIFT 0 +#define IOAPIC_VER_MASK 0x000000ff + +#define IOAPIC_MAX_SHIFT 16 +#define IOAPIC_MAX_MASK 0x00ff0000 + +/* + * Arbitration ID. Same format as IOAPIC_ID register. + */ +#define IOAPIC_ARB 0x02 + +/* + * Redirection table registers. + */ + +#define IOAPIC_REDHI(pin) (0x11 + ((pin)<<1)) +#define IOAPIC_REDLO(pin) (0x10 + ((pin)<<1)) + +#define IOAPIC_REDHI_DEST_SHIFT 24 /* destination. */ +#define IOAPIC_REDHI_DEST_MASK 0xff000000 + +#define IOAPIC_REDLO_MASK 0x00010000 /* 0=enabled; 1=masked */ + +#define IOAPIC_REDLO_LEVEL 0x00008000 /* 0=edge, 1=level */ +#define IOAPIC_REDLO_RIRR 0x00004000 /* remote IRR; read only */ +#define IOAPIC_REDLO_ACTLO 0x00002000 /* 0=act. hi; 1=act. lo */ +#define IOAPIC_REDLO_DELSTS 0x00001000 /* 0=idle; 1=send pending */ +#define IOAPIC_REDLO_DSTMOD 0x00000800 /* 0=physical; 1=logical */ + +#define IOAPIC_REDLO_DEL_MASK 0x00000700 /* del. mode mask */ +#define IOAPIC_REDLO_DEL_SHIFT 8 + +#define IOAPIC_REDLO_DEL_FIXED 0 +#define IOAPIC_REDLO_DEL_LOPRI 1 +#define IOAPIC_REDLO_DEL_SMI 2 +#define IOAPIC_REDLO_DEL_NMI 4 +#define IOAPIC_REDLO_DEL_INIT 5 +#define IOAPIC_REDLO_DEL_EXTINT 7 + +#define IOAPIC_REDLO_VECTOR_MASK 0x000000ff /* delivery vector */ + +#define IMCR_ADDR 0x22 +#define IMCR_DATA 0x23 + +#define IMCR_REGISTER 0x70 +#define IMCR_PIC 0x00 +#define IMCR_APIC 0x01 + +#ifdef _KERNEL + +#include + +#define ioapic_asm_ack(num) \ + CODEPATCH_START ;\ + movl $0,(local_apic+LAPIC_EOI)(%rip) ;\ + CODEPATCH_END(CPTAG_EOI) + +#define ioapic_mask(num) \ + movq IS_PIC(%r14),%rdi ;\ + movl IS_PIN(%r14),%esi ;\ + call ioapic_hwmask + +#define ioapic_unmask(num) \ + cmpq $IREENT_MAGIC,IF_ERR(%rsp) ;\ + jne 79f ;\ + movq IS_PIC(%r14),%rdi ;\ + movl IS_PIN(%r14),%esi ;\ + call ioapic_hwunmask ;\ +79: + +#endif \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/i82093var.h b/lib/libc/include/x86_64-openbsd-none/amd64/i82093var.h new file mode 100644 index 000000000000..1124b33cc727 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/i82093var.h @@ -0,0 +1,92 @@ +/* $OpenBSD: i82093var.h,v 1.8 2025/09/05 16:57:48 kettenis Exp $ */ +/* $NetBSD: i82093var.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_I82093VAR_H_ +#define _MACHINE_I82093VAR_H_ + +#include + +struct ioapic_pin { + struct ioapic_pin *ip_next; /* next pin on this vector */ + struct mp_intr_map *ip_map; + int ip_vector; /* IDT vector */ + int ip_type; + struct cpu_info *ip_cpu; /* target CPU */ +}; + +struct ioapic_softc { + struct pic sc_pic; + struct ioapic_softc *sc_next; + int sc_apicid; + int sc_apic_vers; + int sc_apic_vecbase; /* global int base if ACPI */ + int sc_apic_sz; /* apic size*/ + int sc_flags; + bus_space_tag_t sc_memt; + bus_space_handle_t sc_memh; + struct ioapic_pin *sc_pins; /* sc_apic_sz entries */ +}; + +/* + * MP: intr_handle_t is bitfielded. + * ih&0xff -> legacy irq number. + * ih&0x10000000 -> if 0, old-style isa irq; if 1, routed via ioapic. + * (ih&0xff0000)>>16 -> ioapic id. + * (ih&0x00ff00)>>8 -> ioapic pin. + */ + +#define APIC_INT_VIA_APIC 0x10000000 +#define APIC_INT_VIA_MSG 0x20000000 +#define APIC_INT_VIA_MSGX 0x40000000 +#define APIC_INT_APIC_MASK 0x00ff0000 +#define APIC_INT_APIC_SHIFT 16 +#define APIC_INT_PIN_MASK 0x0000ff00 +#define APIC_INT_PIN_SHIFT 8 + +#define APIC_IRQ_APIC(x) ((x & APIC_INT_APIC_MASK) >> APIC_INT_APIC_SHIFT) +#define APIC_IRQ_PIN(x) ((x & APIC_INT_PIN_MASK) >> APIC_INT_PIN_SHIFT) +#define APIC_IRQ_ISLEGACY(x) (!((x) & APIC_INT_VIA_APIC)) +#define APIC_IRQ_LEGACY_IRQ(x) ((x) & 0xff) + +void ioapic_print_redir(struct ioapic_softc *, char *, int); +struct ioapic_softc *ioapic_find(int); +struct ioapic_softc *ioapic_find_bybase(int); + +void ioapic_enable(void); + +extern int ioapic_bsp_id; +extern int nioapics; +extern struct ioapic_softc *ioapics; + +#endif /* !_MACHINE_I82093VAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/i82489reg.h b/lib/libc/include/x86_64-openbsd-none/amd64/i82489reg.h new file mode 100644 index 000000000000..788c516ac729 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/i82489reg.h @@ -0,0 +1,149 @@ +/* $OpenBSD: i82489reg.h,v 1.5 2019/07/26 04:35:38 kevlo Exp $ */ +/* $NetBSD: i82489reg.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Frank van der Linden. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +/* + * Registers and constants for the 82489DX and Pentium (and up) integrated + * "local" APIC. + */ + +#define LAPIC_ID 0x020 /* ID. RW */ +# define LAPIC_ID_MASK 0x0f000000 +# define LAPIC_ID_SHIFT 24 + +#define LAPIC_VERS 0x030 /* Version. R */ +# define LAPIC_VERSION_MASK 0x000000ff +# define LAPIC_VERSION_LVT_MASK 0x00ff0000 +# define LAPIC_VERSION_LVT_SHIFT 16 + +#define LAPIC_TPRI 0x080 /* Task Prio. RW */ +# define LAPIC_TPRI_MASK 0x000000ff +# define LAPIC_TPRI_INT_MASK 0x000000f0 +# define LAPIC_TPRI_SUB_MASK 0x0000000f + +#define LAPIC_APRI 0x090 /* Arbitration prio R */ +# define LAPIC_APRI_MASK 0x000000ff + +#define LAPIC_PPRI 0x0a0 /* Processor prio. R */ +#define LAPIC_EOI 0x0b0 /* End Int. W */ +#define LAPIC_RRR 0x0c0 /* Remote read R */ +#define LAPIC_LDR 0x0d0 /* Logical dest. RW */ +#define LAPIC_DFR 0x0e0 /* Dest. format RW */ + +#define LAPIC_SVR 0x0f0 /* Spurious intvec RW */ +# define LAPIC_SVR_VECTOR_MASK 0x000000ff +# define LAPIC_SVR_VEC_FIX 0x0000000f +# define LAPIC_SVR_VEC_PROG 0x000000f0 +# define LAPIC_SVR_ENABLE 0x00000100 +# define LAPIC_SVR_SWEN 0x00000100 +# define LAPIC_SVR_FOCUS 0x00000200 +# define LAPIC_SVR_FDIS 0x00000200 + +#define LAPIC_ISR 0x100 /* Int. status. R */ +#define LAPIC_TMR 0x180 +#define LAPIC_IRR 0x200 +#define LAPIC_ESR 0x280 /* Err status. R */ + +#define LAPIC_ICRLO 0x300 /* Int. cmd. RW */ +# define LAPIC_DLMODE_MASK 0x00000700 +# define LAPIC_DLMODE_FIXED 0x00000000 +# define LAPIC_DLMODE_LOW 0x00000100 +# define LAPIC_DLMODE_SMI 0x00000200 +# define LAPIC_DLMODE_RR 0x00000300 +# define LAPIC_DLMODE_NMI 0x00000400 +# define LAPIC_DLMODE_INIT 0x00000500 +# define LAPIC_DLMODE_STARTUP 0x00000600 + +# define LAPIC_DSTMODE_LOG 0x00000800 + +# define LAPIC_DLSTAT_BUSY 0x00001000 + +# define LAPIC_LVL_ASSERT 0x00004000 +# define LAPIC_LVL_DEASSERT 0x00000000 + +# define LAPIC_LVL_TRIG 0x00008000 + +# define LAPIC_RRSTAT_MASK 0x00030000 +# define LAPIC_RRSTAT_INPROG 0x00010000 +# define LAPIC_RRSTAT_VALID 0x00020000 + +# define LAPIC_DEST_MASK 0x000c0000 +# define LAPIC_DEST_SELF 0x00040000 +# define LAPIC_DEST_ALLINCL 0x00080000 +# define LAPIC_DEST_ALLEXCL 0x000c0000 + +# define LAPIC_RESV2_MASK 0xfff00000 + + +#define LAPIC_ICRHI 0x310 /* Int. cmd. RW */ + +#define LAPIC_LVTT 0x320 /* Loc.vec.(timer) RW */ +# define LAPIC_LVTT_VEC_MASK 0x000000ff +# define LAPIC_LVTT_DS 0x00001000 +# define LAPIC_LVTT_M 0x00010000 +# define LAPIC_LVTT_TM 0x00020000 +# define LAPIC_LVTT_TM_ONESHOT 0x00000000 +# define LAPIC_LVTT_TM_PERIODIC 0x00020000 +# define LAPIC_LVTT_TM_TSCDL 0x00040000 + +#define LAPIC_PCINT 0x340 +#define LAPIC_LVINT0 0x350 /* Loc.vec (LINT0) RW */ +# define LAPIC_LVT_PERIODIC 0x00020000 +# define LAPIC_LVT_MASKED 0x00010000 +# define LAPIC_LVT_LEVTRIG 0x00008000 +# define LAPIC_LVT_REMOTE_IRR 0x00004000 +# define LAPIC_INP_POL 0x00002000 +# define LAPIC_PEND_SEND 0x00001000 + +#define LAPIC_LVINT1 0x360 /* Loc.vec (LINT1) RW */ +#define LAPIC_LVERR 0x370 /* Loc.vec (ERROR) RW */ +#define LAPIC_ICR_TIMER 0x380 /* Initial count RW */ +#define LAPIC_CCR_TIMER 0x390 /* Current count RO */ + +#define LAPIC_DCR_TIMER 0x3e0 /* Divisor config register */ +# define LAPIC_DCRT_DIV1 0x0b +# define LAPIC_DCRT_DIV2 0x00 +# define LAPIC_DCRT_DIV4 0x01 +# define LAPIC_DCRT_DIV8 0x02 +# define LAPIC_DCRT_DIV16 0x03 +# define LAPIC_DCRT_DIV32 0x08 +# define LAPIC_DCRT_DIV64 0x09 +# define LAPIC_DCRT_DIV128 0x0a + +#define LAPIC_BASE 0xfee00000 + +#define LAPIC_IRQ_MASK(i) (1 << ((i) + 1)) + +#define MSR_X2APIC_BASE 0x800 +#define MSR_X2APIC_EOI (MSR_X2APIC_BASE+0x0b) /* End Int. W */ +#define MSR_X2APIC_ID (MSR_X2APIC_BASE+0x02) /* ID. RW */ +#define X2APIC_ID_MASK 0xff \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/i82489var.h b/lib/libc/include/x86_64-openbsd-none/amd64/i82489var.h new file mode 100644 index 000000000000..4477a132663e --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/i82489var.h @@ -0,0 +1,124 @@ +/* $OpenBSD: i82489var.h,v 1.21 2024/11/07 17:24:42 bluhm Exp $ */ +/* $NetBSD: i82489var.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Frank van der Linden. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_I82489VAR_H_ +#define _MACHINE_I82489VAR_H_ + +#include "vmm.h" + +/* + * Software definitions belonging to Local APIC driver. + */ + +#ifdef _KERNEL +extern volatile u_int32_t local_apic[]; +extern volatile u_int32_t lapic_tpr; +#endif + +extern u_int32_t (*lapic_readreg)(int); +extern void (*lapic_writereg)(int, u_int32_t); +u_int32_t lapic_cpu_number(void); + +/* + * "spurious interrupt vector"; vector used by interrupt which was + * aborted because the CPU masked it after it happened but before it + * was delivered.. "Oh, sorry, i caught you at a bad time". + * Low-order 4 bits must be all ones. + */ +extern void Xintrspurious(void); +#define LAPIC_SPURIOUS_VECTOR 0xef + +/* + * Vector used for inter-processor interrupts. + */ +extern void Xintr_lapic_ipi(void); +extern void Xrecurse_lapic_ipi(void); +extern void Xresume_lapic_ipi(void); +#define LAPIC_IPI_VECTOR 0xe0 + +/* + * We take 0xf0-0xfe for fast IPI handlers. + */ +#define LAPIC_IPI_OFFSET 0xf0 +#define LAPIC_IPI_INVLTLB (LAPIC_IPI_OFFSET + 0) +#define LAPIC_IPI_INVLPG (LAPIC_IPI_OFFSET + 1) +#define LAPIC_IPI_INVLRANGE (LAPIC_IPI_OFFSET + 2) +#define LAPIC_IPI_WBINVD (LAPIC_IPI_OFFSET + 3) +#define LAPIC_IPI_INVEPT (LAPIC_IPI_OFFSET + 4) + +extern void Xipi_invltlb(void); +extern void Xipi_invltlb_pcid(void); +extern void Xipi_invlpg(void); +extern void Xipi_invlpg_pcid(void); +extern void Xipi_invlrange(void); +extern void Xipi_invlrange_pcid(void); +extern void Xipi_wbinvd(void); +#if NVMM > 0 +extern void Xipi_invept(void); +#endif /* NVMM > 0 */ + +/* + * Vector used for local apic timer interrupts. + */ + +extern void Xintr_lapic_ltimer(void); +extern void Xresume_lapic_ltimer(void); +extern void Xrecurse_lapic_ltimer(void); +#define LAPIC_TIMER_VECTOR 0xc0 + +/* + * Vector used for Xen HVM Event Channel Interrupts. + */ +extern void Xintr_xen_upcall(void); +extern void Xresume_xen_upcall(void); +extern void Xrecurse_xen_upcall(void); +#define LAPIC_XEN_VECTOR 0x70 + +/* + * Vector used for Hyper-V Interrupts. + */ +extern void Xintr_hyperv_upcall(void); +extern void Xresume_hyperv_upcall(void); +extern void Xrecurse_hyperv_upcall(void); +#define LAPIC_HYPERV_VECTOR 0x71 + +struct cpu_info; + +extern void lapic_boot_init(paddr_t); +extern void lapic_set_lvt(void); +extern void lapic_enable(void); +extern void lapic_disable(void); +extern void lapic_calibrate_timer(struct cpu_info *ci); +extern void lapic_startclock(void); +extern void lapic_initclocks(void); + +#endif \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/i8259.h b/lib/libc/include/x86_64-openbsd-none/amd64/i8259.h new file mode 100644 index 000000000000..28bdcd474324 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/i8259.h @@ -0,0 +1,144 @@ +/* $OpenBSD: i8259.h,v 1.4 2015/09/02 13:39:23 mikeb Exp $ */ +/* $NetBSD: i8259.h,v 1.3 2003/05/04 22:01:56 fvdl Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)icu.h 5.6 (Berkeley) 5/9/91 + */ + +#ifndef _MACHINE_I8259_H_ +#define _MACHINE_I8259_H_ + +#include + +#ifndef _LOCORE + +/* + * Interrupt "level" mechanism variables, masks, and macros + */ +extern unsigned i8259_imen; /* interrupt mask enable */ + +extern void i8259_default_setup(void); + +#endif /* !_LOCORE */ + +/* + * Interrupt enable bits -- in order of priority + */ +#define IRQ_SLAVE 2 + +/* + * Interrupt Control offset into Interrupt descriptor table (IDT) + */ +#define ICU_OFFSET 32 /* 0-31 are processor exceptions */ +#define ICU_LEN 16 /* 32-47 are ISA interrupts */ + + +#define ICU_HARDWARE_MASK + +/* + * These macros are fairly self explanatory. If ICU_SPECIAL_MASK_MODE is + * defined, we try to take advantage of the ICU's `special mask mode' by only + * EOIing the interrupts on return. This avoids the requirement of masking and + * unmasking. We can't do this without special mask mode, because the ICU + * would also hold interrupts that it thinks are of lower priority. + * + * Many machines do not support special mask mode, so by default we don't try + * to use it. + */ + +#define IRQ_BIT(num) (1 << ((num) % 8)) +#define IRQ_BYTE(num) ((num) >> 3) + +#define i8259_late_ack(num) + +#ifdef ICU_SPECIAL_MASK_MODE + +#define i8259_asm_ack1(num) +#define i8259_asm_ack2(num) \ + movb $(0x60|IRQ_SLAVE),%al /* specific EOI for IRQ2 */ ;\ + outb %al,$IO_ICU1 +#define i8259_asm_mask(num) +#define i8259_asm_unmask(num) \ + movb $(0x60|(num%8)),%al /* specific EOI */ ;\ + outb %al,$ICUADDR + +#else /* ICU_SPECIAL_MASK_MODE */ + +#ifndef AUTO_EOI_1 +#define i8259_asm_ack1(num) \ + movb $(0x60|(num%8)),%al /* specific EOI */ ;\ + outb %al,$IO_ICU1 +#else +#define i8259_asm_ack1(num) +#endif + +#ifndef AUTO_EOI_2 +#define i8259_asm_ack2(num) \ + movb $(0x60|(num%8)),%al /* specific EOI */ ;\ + outb %al,$IO_ICU2 /* do the second ICU first */ ;\ + movb $(0x60|IRQ_SLAVE),%al /* specific EOI for IRQ2 */ ;\ + outb %al,$IO_ICU1 +#else +#define i8259_asm_ack2(num) +#endif + +#ifdef PIC_MASKDELAY +#define MASKDELAY pushl %eax ; inb $0x84,%al ; popl %eax +#else +#define MASKDELAY +#endif + +#ifdef ICU_HARDWARE_MASK + +#define i8259_asm_mask(num) \ + movb CVAROFF(i8259_imen, IRQ_BYTE(num)),%al ;\ + orb $IRQ_BIT(num),%al ;\ + movb %al,CVAROFF(i8259_imen, IRQ_BYTE(num)) ;\ + MASKDELAY ;\ + outb %al,$(ICUADDR+1) +#define i8259_asm_unmask(num) \ + movb CVAROFF(i8259_imen, IRQ_BYTE(num)),%al ;\ + andb $~IRQ_BIT(num),%al ;\ + movb %al,CVAROFF(i8259_imen, IRQ_BYTE(num)) ;\ + MASKDELAY ;\ + outb %al,$(ICUADDR+1) + +#else /* ICU_HARDWARE_MASK */ + +#define i8259_asm_mask(num) +#define i8259_asm_unmask(num) + +#endif /* ICU_HARDWARE_MASK */ +#endif /* ICU_SPECIAL_MASK_MODE */ + +#endif /* !_MACHINE_I8259_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/ieee.h b/lib/libc/include/x86_64-openbsd-none/amd64/ieee.h new file mode 100644 index 000000000000..dea4be1a6ba2 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/ieee.h @@ -0,0 +1,142 @@ +/* $OpenBSD: ieee.h,v 1.2 2008/09/07 20:36:06 martynas Exp $ */ +/* $NetBSD: ieee.h,v 1.1 1996/09/30 16:34:25 ws Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ieee.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * ieee.h defines the machine-dependent layout of the machine's IEEE + * floating point. It does *not* define (yet?) any of the rounding + * mode bits, exceptions, and so forth. + */ + +/* + * Define the number of bits in each fraction and exponent. + * + * k k+1 + * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented + * + * (-exp_bias+1) + * as fractions that look like 0.fffff x 2 . This means that + * + * -126 + * the number 0.10000 x 2 , for instance, is the same as the normalized + * + * -127 -128 + * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero + * + * -129 + * in the fraction; to represent 2 , we need two, and so on. This + * + * (-exp_bias-fracbits+1) + * implies that the smallest denormalized number is 2 + * + * for whichever format we are talking about: for single precision, for + * + * -126 -149 + * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and + * + * -149 == -127 - 23 + 1. + */ +#define SNG_EXPBITS 8 +#define SNG_FRACBITS 23 + +#define DBL_EXPBITS 11 +#define DBL_FRACHBITS 20 +#define DBL_FRACLBITS 32 +#define DBL_FRACBITS 52 + +#define EXT_EXPBITS 15 +#define EXT_FRACHBITS 32 +#define EXT_FRACLBITS 32 +#define EXT_FRACBITS 64 + +#define EXT_TO_ARRAY32(p, a) do { \ + (a)[0] = (uint32_t)(p)->ext_fracl; \ + (a)[1] = (uint32_t)(p)->ext_frach; \ +} while(0) + +struct ieee_single { + u_int sng_frac:23; + u_int sng_exp:8; + u_int sng_sign:1; +}; + +struct ieee_double { + u_int dbl_fracl; + u_int dbl_frach:20; + u_int dbl_exp:11; + u_int dbl_sign:1; +}; + +struct ieee_ext { + u_int ext_fracl; + u_int ext_frach; + u_int ext_exp:15; + u_int ext_sign:1; + u_int ext_padl:16; + u_int ext_padh; +}; + +/* + * Floats whose exponent is in [1..INFNAN) (of whatever type) are + * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. + * Floats whose exponent is zero are either zero (iff all fraction + * bits are zero) or subnormal values. + * + * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its + * high fraction; if the bit is set, it is a `quiet NaN'. + */ +#define SNG_EXP_INFNAN 255 +#define DBL_EXP_INFNAN 2047 +#define EXT_EXP_INFNAN 32767 + +#if 0 +#define SNG_QUIETNAN (1 << 22) +#define DBL_QUIETNAN (1 << 19) +#define EXT_QUIETNAN (1 << 15) +#endif + +/* + * Exponent biases. + */ +#define SNG_EXP_BIAS 127 +#define DBL_EXP_BIAS 1023 +#define EXT_EXP_BIAS 16383 \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/ieeefp.h b/lib/libc/include/x86_64-openbsd-none/amd64/ieeefp.h new file mode 100644 index 000000000000..510fd8e15751 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/ieeefp.h @@ -0,0 +1,26 @@ +/* $OpenBSD: ieeefp.h,v 1.2 2011/03/23 16:54:34 pirofti Exp $ */ + +/* + * Written by J.T. Conklin, Apr 6, 1995 + * Public domain. + */ + +#ifndef _MACHINE_IEEEFP_H_ +#define _MACHINE_IEEEFP_H_ + +typedef int fp_except; +#define FP_X_INV 0x01 /* invalid operation exception */ +#define FP_X_DNML 0x02 /* denormalization exception */ +#define FP_X_DZ 0x04 /* divide-by-zero exception */ +#define FP_X_OFL 0x08 /* overflow exception */ +#define FP_X_UFL 0x10 /* underflow exception */ +#define FP_X_IMP 0x20 /* imprecise (loss of precision) */ + +typedef enum { + FP_RN=0, /* round to nearest representable number */ + FP_RM=1, /* round toward negative infinity */ + FP_RP=2, /* round toward positive infinity */ + FP_RZ=3 /* round to zero (truncate) */ +} fp_rnd; + +#endif /* _MACHINE_IEEEFP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/intr.h b/lib/libc/include/x86_64-openbsd-none/amd64/intr.h new file mode 100644 index 000000000000..ca5fda214175 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/intr.h @@ -0,0 +1,229 @@ +/* $OpenBSD: intr.h,v 1.36 2025/06/11 09:57:01 kettenis Exp $ */ +/* $NetBSD: intr.h,v 1.2 2003/05/04 22:01:56 fvdl Exp $ */ + +/*- + * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum, and by Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_INTR_H_ +#define _MACHINE_INTR_H_ + +#define __USE_MI_SOFTINTR + +#include +#include + +#ifndef _LOCORE +#include + +#include + +/* + * Struct describing an interrupt source for a CPU. struct cpu_info + * has an array of MAX_INTR_SOURCES of these. The index in the array + * is equal to the stub number of the stubcode as present in vector.s + * + * The primary CPU's array of interrupt sources has its first 16 + * entries reserved for legacy ISA irq handlers. This means that + * they have a 1:1 mapping for arrayindex:irq_num. This is not + * true for interrupts that come in through IO APICs, to find + * their source, go through ci->ci_isources[index].is_pic + * + * It's possible to always maintain a 1:1 mapping, but that means + * limiting the total number of interrupt sources to MAX_INTR_SOURCES + * (32), instead of 32 per CPU. It also would mean that having multiple + * IO APICs which deliver interrupts from an equal pin number would + * overlap if they were to be sent to the same CPU. + */ + +struct intrstub { + void *ist_entry; + void *ist_recurse; + void *ist_resume; +}; + +struct intrsource { + int is_maxlevel; /* max. IPL for this source */ + int is_pin; /* IRQ for legacy; pin for IO APIC */ + struct intrhand *is_handlers; /* handler chain */ + struct pic *is_pic; /* originating PIC */ + void *is_recurse; /* entry for spllower */ + void *is_resume; /* entry for doreti */ + char is_evname[32]; /* event counter name */ + int is_flags; /* see below */ + int is_type; /* level, edge */ + int is_idtvec; + int is_minlevel; +}; + +#define IS_LEGACY 0x0001 /* legacy ISA irq source */ +#define IS_IPI 0x0002 +#define IS_LOG 0x0004 + + +/* + * Interrupt handler chains. *_intr_establish() insert a handler into + * the list. The handler is called with its (single) argument. + */ + +struct intrhand { + int (*ih_fun)(void *); + void *ih_arg; + int ih_level; + int ih_flags; + struct intrhand *ih_next; + int ih_pin; + int ih_slot; + struct cpu_info *ih_cpu; + int ih_irq; + struct evcount ih_count; +}; + +#define IMASK(ci,level) (ci)->ci_imask[(level)] +#define IUNMASK(ci,level) (ci)->ci_iunmask[(level)] + +extern void Xspllower(int); + +int splraise(int); +int spllower(int); +void softintr(int); +void dosoftint(int); + +/* + * Convert spl level to local APIC level + */ +#define APIC_LEVEL(l) ((l) << 4) + +/* + * compiler barrier: prevent reordering of instructions. + * This prevents the compiler from reordering code around + * this "instruction", acting as a sequence point for code generation. + */ + +#define __splbarrier() __asm volatile("":::"memory") + +/* + * Hardware interrupt masks + */ +#define splbio() splraise(IPL_BIO) +#define splnet() splraise(IPL_NET) +#define spltty() splraise(IPL_TTY) +#define splaudio() splraise(IPL_AUDIO) +#define splclock() splraise(IPL_CLOCK) +#define splstatclock() splclock() +#define splipi() splraise(IPL_IPI) + +/* + * Software interrupt masks + */ +#define splsoftclock() splraise(IPL_SOFTCLOCK) +#define splsoftnet() splraise(IPL_SOFTNET) +#define splsofttty() splraise(IPL_SOFTTTY) + +/* + * Miscellaneous + */ +#define splvm() splraise(IPL_VM) +#define splhigh() splraise(IPL_HIGH) +#define spl0() spllower(IPL_NONE) +#define splsched() splraise(IPL_SCHED) +#define splx(x) spllower(x) + +/* SPL asserts */ +#ifdef DIAGNOSTIC +/* + * Although this function is implemented in MI code, it must be in this MD + * header because we don't want this header to include MI includes. + */ +void splassert_fail(int, int, const char *); +extern int splassert_ctl; +void splassert_check(int, const char *); +#define splassert(__wantipl) do { \ + if (splassert_ctl > 0) { \ + splassert_check(__wantipl, __func__); \ + } \ +} while (0) +#define splsoftassert(wantipl) splassert(wantipl) +#else +#define splassert(wantipl) do { /* nada */ } while (0) +#define splsoftassert(wantipl) do { /* nada */ } while (0) +#endif + +#define IPLSHIFT 4 /* The upper nibble of vectors is the IPL. */ +#define IPL(level) ((level) >> IPLSHIFT) /* Extract the IPL. */ + +#include + +/* + * Stub declarations. + */ + +extern void Xsoftclock(void); +extern void Xsoftnet(void); +extern void Xsofttty(void); + +extern struct intrstub i8259_stubs[]; +extern struct intrstub ioapic_edge_stubs[]; +extern struct intrstub ioapic_level_stubs[]; + +struct cpu_info; + +extern int intr_shared_edge; + +extern char idt_allocmap[]; + +void intr_default_setup(void); +int x86_nmi(void); +void intr_calculatemasks(struct cpu_info *); +int intr_allocate_slot_cpu(struct cpu_info *, struct pic *, int, int *); +int intr_allocate_slot(struct pic *, int, int, int, struct cpu_info **, int *, + int *); +void *intr_establish(int, struct pic *, int, int, int, + struct cpu_info *, int (*)(void *), void *, const char *); +void intr_disestablish(struct intrhand *); +int intr_handler(struct intrframe *, struct intrhand *); +void cpu_intr_init(struct cpu_info *); +void intr_printconfig(void); +void intr_barrier(void *); +void intr_set_wakeup(void *); +void intr_enable_wakeup(void); +void intr_disable_wakeup(void); + +#ifdef MULTIPROCESSOR +void x86_send_ipi(struct cpu_info *, int); +int x86_fast_ipi(struct cpu_info *, int); +void x86_broadcast_ipi(int); +void x86_ipi_handler(void); +void x86_setperf_ipi(struct cpu_info *); + +extern void (*ipifunc[X86_NIPI])(struct cpu_info *); +#endif + +#endif /* !_LOCORE */ + +#endif /* !_MACHINE_INTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/intrdefs.h b/lib/libc/include/x86_64-openbsd-none/amd64/intrdefs.h new file mode 100644 index 000000000000..54fe1358ca83 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/intrdefs.h @@ -0,0 +1,93 @@ +/* $OpenBSD: intrdefs.h,v 1.24 2024/05/26 13:37:31 kettenis Exp $ */ +/* $NetBSD: intrdefs.h,v 1.2 2003/05/04 22:01:56 fvdl Exp $ */ + +#ifndef _AMD64_INTRDEFS_H +#define _AMD64_INTRDEFS_H + +/* + * Interrupt priority levels. + * + * There are tty, network and disk drivers that use free() at interrupt + * time, so imp > (tty | net | bio). + * + * Since run queues may be manipulated by both the statclock and tty, + * network, and disk drivers, clock > imp. + * + * IPL_HIGH must block everything that can manipulate a run queue. + * + * The level numbers are picked to fit into APIC vector priorities. + * + */ +#define IPL_NONE 0x0 /* nothing */ +#define IPL_SOFTCLOCK 0x1 /* timeouts */ +#define IPL_SOFTNET 0x2 /* protocol stacks */ +#define IPL_BIO 0x3 /* block I/O */ +#define IPL_NET 0x4 /* network */ +#define IPL_SOFTTTY 0x8 /* delayed terminal handling */ +#define IPL_TTY 0x9 /* terminal */ +#define IPL_VM 0xa /* memory allocation */ +#define IPL_AUDIO 0xb /* audio */ +#define IPL_CLOCK 0xc /* clock */ +#define IPL_SCHED IPL_CLOCK +#define IPL_STATCLOCK IPL_CLOCK +#define IPL_HIGH 0xd /* everything */ +#define IPL_IPI 0xe /* inter-processor interrupts */ +#define NIPL 16 + +#define IPL_MPFLOOR IPL_TTY +#define IPL_MPSAFE 0x100 +#define IPL_WAKEUP 0x200 + +/* Interrupt sharing types. */ +#define IST_NONE 0 /* none */ +#define IST_PULSE 1 /* pulsed */ +#define IST_EDGE 2 /* edge-triggered */ +#define IST_LEVEL 3 /* level-triggered */ + +/* + * Local APIC masks. Must not conflict with SIR_* above, and must + * be >= NUM_LEGACY_IRQs. Note that LIR_IPI must be first. + */ +#define LIR_IPI 63 +#define LIR_TIMER 62 + +/* Soft interrupt masks. */ +#define SIR_CLOCK 61 +#define SIR_NET 60 +#define SIR_TTY 59 + +#define LIR_XEN 58 +#define LIR_HYPERV 57 + +/* + * Maximum # of interrupt sources per CPU. 64 to fit in one word. + * ioapics can theoretically produce more, but it's not likely to + * happen. For multiple ioapics, things can be routed to different + * CPUs. + */ +#define MAX_INTR_SOURCES 64 +#define NUM_LEGACY_IRQS 16 + +/* + * Low and high boundaries between which interrupt gates will + * be allocated in the IDT. + */ +#define IDT_INTR_LOW (0x20 + NUM_LEGACY_IRQS) +#define IDT_INTR_HIGH 0xef + +#define X86_IPI_HALT 0x00000001 +#define X86_IPI_NOP 0x00000002 +#define X86_IPI_VMCLEAR_VMM 0x00000004 +#define X86_IPI_PCTR 0x00000010 +#define X86_IPI_MTRR 0x00000020 +#define X86_IPI_SETPERF 0x00000040 +#define X86_IPI_DDB 0x00000080 +#define X86_IPI_START_VMM 0x00000100 +#define X86_IPI_STOP_VMM 0x00000200 +#define X86_IPI_WBINVD 0x00000400 + +#define X86_NIPI 12 + +#define IREENT_MAGIC 0x18041969 + +#endif /* _AMD64_INTRDEFS_H */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/ioctl_fd.h b/lib/libc/include/x86_64-openbsd-none/amd64/ioctl_fd.h new file mode 100644 index 000000000000..659711f9d7bd --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/ioctl_fd.h @@ -0,0 +1,130 @@ +/* $OpenBSD: ioctl_fd.h,v 1.2 2011/03/23 16:54:34 pirofti Exp $ */ + +/* + * Copyright (C) 1992-1994 by Joerg Wunsch, Dresden + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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(S) BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * From: Id: ioctl_fd.h,v 1.7 1994/10/30 19:17:39 joerg Exp + */ + +#ifndef _MACHINE_IOCTL_FD_H_ +#define _MACHINE_IOCTL_FD_H_ + +#include + +#define FD_FORMAT_VERSION 110 /* used to validate before formatting */ +#define FD_MAX_NSEC 36 /* highest known number of spt - allow for */ + /* 2.88 MB drives */ + +struct fd_formb { + int format_version; /* == FD_FORMAT_VERSION */ + int cyl, head; + int transfer_rate; /* fdreg.h: FDC_???KBPS */ + + union { + struct fd_form_data { + /* + * DO NOT CHANGE THE LAYOUT OF THIS STRUCTS + * it is hardware-dependant since it exactly + * matches the byte sequence to write to FDC + * during its `format track' operation + */ + u_char secshift; /* 0 -> 128, ...; usually 2 -> 512 */ + u_char nsecs; /* must be <= FD_MAX_NSEC */ + u_char gaplen; /* GAP 3 length; usually 84 */ + u_char fillbyte; /* usually 0xf6 */ + struct fd_idfield_data { + /* + * data to write into id fields; + * for obscure formats, they mustn't match + * the real values (but mostly do) + */ + u_char cylno; /* 0 thru 79 (or 39) */ + u_char headno; /* 0, or 1 */ + u_char secno; /* starting at 1! */ + u_char secsize; /* usually 2 */ + } idfields[FD_MAX_NSEC]; /* 0 <= idx < nsecs used */ + } structured; + u_char raw[1]; /* to have continuous indexed access */ + } format_info; +}; + +/* make life easier */ +# define fd_formb_secshift format_info.structured.secshift +# define fd_formb_nsecs format_info.structured.nsecs +# define fd_formb_gaplen format_info.structured.gaplen +# define fd_formb_fillbyte format_info.structured.fillbyte +/* these data must be filled in for(i = 0; i < fd_formb_nsecs; i++) */ +# define fd_formb_cylno(i) format_info.structured.idfields[i].cylno +# define fd_formb_headno(i) format_info.structured.idfields[i].headno +# define fd_formb_secno(i) format_info.structured.idfields[i].secno +# define fd_formb_secsize(i) format_info.structured.idfields[i].secsize + +/* + * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how + * we tell them apart. + */ +struct fd_type { + int sectrac; /* sectors per track */ + int heads; /* number of heads */ + int seccyl; /* sectors per cylinder */ + int secsize; /* size code for sectors */ + int datalen; /* data len when secsize = 0 */ + int steprate; /* step rate and head unload time */ + int gap1; /* gap len between sectors */ + int gap2; /* formatting gap */ + int tracks; /* total num of tracks */ + int size; /* size of disk in sectors */ + int step; /* steps per cylinder */ + int rate; /* transfer speed code */ + char *name; +}; + + +#define FD_FORM _IOW('F', 61, struct fd_formb) /* format a track */ +#define FD_GTYPE _IOR('F', 62, struct fd_type) /* get drive type */ +#define FD_STYPE _IOW('F', 63, struct fd_type) /* set drive type */ + +#define FD_GOPTS _IOR('F', 64, int) /* drive options, see below */ +#define FD_SOPTS _IOW('F', 65, int) + +#define FDOPT_NORETRY 0x0001 /* no retries on failure (cleared on close) */ + +/* + * The following definitions duplicate those in sys/i386/isa/fdreg.h + * They are here since their values are to be used in the above + * structure when formatting a floppy. For very obvious reasons, both + * definitions must match ;-) + */ +#ifndef FDC_500KBPS +#define FDC_500KBPS 0x00 /* 500KBPS MFM drive transfer rate */ +#define FDC_300KBPS 0x01 /* 300KBPS MFM drive transfer rate */ +#define FDC_250KBPS 0x02 /* 250KBPS MFM drive transfer rate */ +#define FDC_125KBPS 0x03 /* 125KBPS FM drive transfer rate */ + /* for some controllers 1MPBS instead */ +#endif /* FDC_500KBPS */ + + +#endif /* !_MACHINE_IOCTL_FD_H__ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/isa_machdep.h b/lib/libc/include/x86_64-openbsd-none/amd64/isa_machdep.h new file mode 100644 index 000000000000..3efae87c134d --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/isa_machdep.h @@ -0,0 +1,163 @@ +/* $OpenBSD: isa_machdep.h,v 1.11 2024/05/22 05:51:49 jsg Exp $ */ +/* $NetBSD: isa_machdep.h,v 1.2 2003/05/09 23:51:28 fvdl Exp $ */ + +/*- + * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)isa.h 5.7 (Berkeley) 5/9/91 + */ + +/* + * Various pieces of the i386 port want to include this file without + * or in spite of using isavar.h, and should be fixed. + */ + +#ifndef _I386_ISA_MACHDEP_H_ /* XXX */ +#define _I386_ISA_MACHDEP_H_ /* XXX */ + +#include +#include + +/* + * ISA can only DMA to 0-16M. + */ +#define ISA_DMA_BOUNCE_THRESHOLD 0x00ffffff + +/* + * XXX THIS FILE IS A MESS. copyright: berkeley's probably. + * contents from isavar.h and isareg.h, mostly the latter. + * perhaps charles's? + * + * copyright from berkeley's isa.h which is now dev/isa/isareg.h. + */ + +/* + * Types provided to machine-independent ISA code. + */ + +typedef void *isa_chipset_tag_t; + +struct device; /* XXX */ +struct isabus_attach_args; /* XXX */ + +/* + * Functions provided to machine-independent ISA code. + */ +void isa_attach_hook(struct device *, struct device *, + struct isabus_attach_args *); +int isa_intr_alloc(isa_chipset_tag_t, int, int, int *); +void *isa_intr_establish(isa_chipset_tag_t ic, int irq, int type, + int level, int (*ih_fun)(void *), void *ih_arg, char *); +void isa_intr_disestablish(isa_chipset_tag_t ic, void *handler); + +int isa_intr_check(isa_chipset_tag_t, int, int); + +/* + * ALL OF THE FOLLOWING ARE MACHINE-DEPENDENT, AND SHOULD NOT BE USED + * BY PORTABLE CODE. + */ + +extern struct bus_dma_tag isa_bus_dma_tag; + +/* + * Cookie used by ISA dma. A pointer to one of these it stashed in + * the DMA map. + */ +struct isa_dma_cookie { + int id_flags; /* flags; see below */ + + void *id_origbuf; /* pointer to orig buffer if + bouncing */ + bus_size_t id_origbuflen; /* ...and size */ + + void *id_bouncebuf; /* pointer to the bounce buffer */ + bus_size_t id_bouncebuflen; /* ...and size */ + int id_nbouncesegs; /* number of valid bounce segs */ + bus_dma_segment_t id_bouncesegs[0]; /* array of bounce buffer + physical memory segments */ +}; + +/* id_flags */ +#define ID_MIGHT_NEED_BOUNCE 0x01 /* map could need bounce buffers */ +#define ID_HAS_BOUNCE 0x02 /* map currently has bounce buffers */ +#define ID_IS_BOUNCING 0x04 /* map is bouncing current xfer */ + +/* + * Variables and macros to deal with the ISA I/O hole. + * XXX These should be converted to machine- and bus-mapping-independent + * function definitions, invoked through the softc. + */ + +extern u_long atdevbase; /* kernel virtual address of "hole" */ + +/* + * Given a kernel virtual address for some location + * in the "hole" I/O space, return a physical address. + */ +#define ISA_PHYSADDR(v) ((void *) ((u_long)(v) - atdevbase + IOM_BEGIN)) + +/* + * Given a physical address in the "hole", + * return a kernel virtual address. + */ +#define ISA_HOLE_VADDR(p) ((void *) ((u_long)(p) - IOM_BEGIN + atdevbase)) + +#endif /* _I386_ISA_MACHDEP_H_ XXX */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/kcore.h b/lib/libc/include/x86_64-openbsd-none/amd64/kcore.h new file mode 100644 index 000000000000..b02ab2866472 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/kcore.h @@ -0,0 +1,47 @@ +/* $OpenBSD: kcore.h,v 1.5 2018/04/03 07:13:37 mlarkin Exp $ */ +/* $NetBSD: kcore.h,v 1.1 2003/04/26 18:39:43 fvdl Exp $ */ + +/* + * Copyright (c) 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +/* + * Modified for NetBSD/i386 by Jason R. Thorpe, Numerical Aerospace + * Simulation Facility, NASA Ames Research Center. + * + * And once again modified for x86-64 by Frank van der Linden of + * Wasabi Systems, Inc. + */ + +#ifndef _MACHINE_KCORE_H_ +#define _MACHINE_KCORE_H_ + +typedef struct cpu_kcore_hdr { + u_int64_t ptdpaddr; /* PA of PML4 */ + u_int64_t nmemsegs; /* Number of RAM segments */ +} cpu_kcore_hdr_t; + +#endif /* _MACHINE_KCORE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/limits.h b/lib/libc/include/x86_64-openbsd-none/amd64/limits.h new file mode 100644 index 000000000000..f288e0542996 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/limits.h @@ -0,0 +1,52 @@ +/* $OpenBSD: limits.h,v 1.6 2015/04/30 13:42:08 millert Exp $ */ + +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)limits.h 7.2 (Berkeley) 6/28/90 + */ + +#ifndef _MACHINE_LIMITS_H_ +#define _MACHINE_LIMITS_H_ + +#include + +#if __POSIX_VISIBLE || __XPG_VISIBLE +#define SSIZE_MAX LONG_MAX /* max value for a ssize_t */ +#endif + +#if __BSD_VISIBLE +#define SIZE_T_MAX ULONG_MAX /* max value for a size_t (historic) */ + +#define UQUAD_MAX 0xffffffffffffffffULL /* max unsigned quad */ +#define QUAD_MAX 0x7fffffffffffffffLL /* max signed quad */ +#define QUAD_MIN (-0x7fffffffffffffffLL-1) /* min signed quad */ + +#endif /* __BSD_VISIBLE */ + +#endif /* _MACHINE_LIMITS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/loadfile_machdep.h b/lib/libc/include/x86_64-openbsd-none/amd64/loadfile_machdep.h new file mode 100644 index 000000000000..c856e9b9f60b --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/loadfile_machdep.h @@ -0,0 +1,61 @@ +/* $OpenBSD: loadfile_machdep.h,v 1.9 2019/05/28 04:51:26 mlarkin Exp $ */ +/* $NetBSD: loadfile_machdep.h,v 1.1 1999/04/29 03:17:12 tsubai Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define BOOT_ELF +#define BOOT_ELF32 +#define BOOT_ELF64 + +/* Keep a default ELFSIZE */ +#define ELFSIZE 64 + +#define LOAD_KERNEL LOAD_ALL +#define COUNT_KERNEL COUNT_ALL + +#ifdef EFIBOOT +extern u_long efi_loadaddr; +#define LOADADDR(a) (((((u_long)(a)) + offset)&0xfffffff) + \ + efi_loadaddr) +#else +#define LOADADDR(a) ((a) + offset) +#endif +#define ALIGNENTRY(a) ((u_long)(a)) +#define READ(f, b, c) read((f), (void *)LOADADDR(b), (c)) +#define BCOPY(s, d, c) memcpy((void *)LOADADDR(d), (void *)(s), (c)) +#define BZERO(d, c) memset((void *)LOADADDR(d), 0, (c)) +#define WARN(a) (void)(printf a, \ + printf((errno ? ": %s\n" : "\n"), \ + strerror(errno))) +#define PROGRESS(a) (void) printf a +#define ALLOC(a) alloc(a) +#define FREE(a, b) free(a, b) + +void run_loadfile(uint64_t *, int); \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/mpbiosreg.h b/lib/libc/include/x86_64-openbsd-none/amd64/mpbiosreg.h new file mode 100644 index 000000000000..8a35f5f11d18 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/mpbiosreg.h @@ -0,0 +1,156 @@ +/* $OpenBSD: mpbiosreg.h,v 1.5 2023/04/10 04:21:20 jsg Exp $ */ +/* $NetBSD: mpbiosreg.h,v 1.3 2003/03/04 23:27:32 fvdl Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_MPBIOSREG_H_ +#define _MACHINE_MPBIOSREG_H_ + +#define BIOS_BASE (0xf0000) +#define BIOS_SIZE (0x10000) +#define BIOS_COUNT (BIOS_SIZE) + +/* + * Multiprocessor config table entry types. + */ + +#define MPS_MCT_CPU 0 +#define MPS_MCT_BUS 1 +#define MPS_MCT_IOAPIC 2 +#define MPS_MCT_IOINT 3 +#define MPS_MCT_LINT 4 + +#define MPS_MCT_NTYPES 5 + +/* + * Interrupt types + */ + +#define MPS_INTTYPE_INT 0 +#define MPS_INTTYPE_NMI 1 +#define MPS_INTTYPE_SMI 2 +#define MPS_INTTYPE_ExtINT 3 + +#define MPS_INTPO_DEF 0 +#define MPS_INTPO_ACTHI 1 +#define MPS_INTPO_ACTLO 3 +#define MPS_INTPO_SHIFT 0 +#define MPS_INTPO_MASK 3 + +#define MPS_INTTR_DEF 0 +#define MPS_INTTR_EDGE 1 +#define MPS_INTTR_LEVEL 3 +#define MPS_INTTR_SHIFT 2 +#define MPS_INTTR_MASK 3 + +#define MPS_INT(p,t) \ + ((((p) & MPS_INTPO_MASK) << MPS_INTPO_SHIFT) | \ + (((t) & MPS_INTTR_MASK) << MPS_INTTR_SHIFT)) + +/* MP Floating Pointer Structure */ +struct mpbios_fps { + u_int32_t signature; +/* string defined by the Intel MP Spec as identifying the MP table */ +#define MP_FP_SIG 0x5f504d5f /* _MP_ */ + + u_int32_t pap; + u_int8_t length; + u_int8_t spec_rev; + u_int8_t checksum; + u_int8_t mpfb1; /* system configuration */ + u_int8_t mpfb2; /* flags */ +#define MPFPS_FLAG_IMCR 0x80 /* IMCR present */ + u_int8_t mpfb3; /* unused */ + u_int8_t mpfb4; /* unused */ + u_int8_t mpfb5; /* unused */ +}; + +/* MP Configuration Table Header */ +struct mpbios_cth { + u_int32_t signature; +#define MP_CT_SIG 0x504d4350 /* PCMP */ + + u_int16_t base_len; + u_int8_t spec_rev; + u_int8_t checksum; + u_int8_t oem_id[8]; + u_int8_t product_id[12]; + u_int32_t oem_table_pointer; + u_int16_t oem_table_size; + u_int16_t entry_count; + u_int32_t apic_address; + u_int16_t ext_len; + u_int8_t ext_cksum; + u_int8_t reserved; +}; + +struct mpbios_proc { + u_int8_t type; + u_int8_t apic_id; + u_int8_t apic_version; + u_int8_t cpu_flags; +#define PROCENTRY_FLAG_EN 0x01 +#define PROCENTRY_FLAG_BP 0x02 + u_int32_t cpu_signature; + u_int32_t feature_flags; + u_int32_t reserved1; + u_int32_t reserved2; +}; + +struct mpbios_bus { + u_int8_t type; + u_int8_t bus_id; + char bus_type[6]; +}; + +struct mpbios_ioapic { + u_int8_t type; + u_int8_t apic_id; + u_int8_t apic_version; + u_int8_t apic_flags; +#define IOAPICENTRY_FLAG_EN 0x01 + u_int32_t apic_address; +}; + +struct mpbios_int { + u_int8_t type; + u_int8_t int_type; + u_int16_t int_flags; + u_int8_t src_bus_id; + u_int8_t src_bus_irq; + u_int8_t dst_apic_id; +#define MPS_ALL_APICS 0xff + u_int8_t dst_apic_int; +}; + + +#endif /* !_MACHINE_MPBIOSREG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/mpbiosvar.h b/lib/libc/include/x86_64-openbsd-none/amd64/mpbiosvar.h new file mode 100644 index 000000000000..2247427b231e --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/mpbiosvar.h @@ -0,0 +1,57 @@ +/* $OpenBSD: mpbiosvar.h,v 1.7 2025/09/05 16:57:48 kettenis Exp $ */ +/* $NetBSD: mpbiosvar.h,v 1.2 2003/04/02 07:53:57 thorpej Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef _MACHINE_MPBIOSVAR_H_ +#define _MACHINE_MPBIOSVAR_H_ + +#define MP_TRAMPOLINE (16 * PAGE_SIZE) +#define MP_TRAMP_DATA (17 * PAGE_SIZE) + +#if !defined(_LOCORE) + +#include +#include + +#if defined(_KERNEL) +int mpbios_probe(struct device *); + +void mpbios_intr_fixup(void); + +extern int mpbios_scanned; +#endif + +#endif + +#endif /* !_MACHINE_MPBIOSVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/mpconfig.h b/lib/libc/include/x86_64-openbsd-none/amd64/mpconfig.h new file mode 100644 index 000000000000..7fc051d696d3 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/mpconfig.h @@ -0,0 +1,49 @@ +/* $OpenBSD: mpconfig.h,v 1.8 2011/10/21 20:48:11 kettenis Exp $ */ +/* $NetBSD: mpconfig.h,v 1.2 2003/05/11 00:05:52 fvdl Exp $ */ + +/* + * Definitions originally from the mpbios code, but now used for ACPI + * MP config as well. + */ + +#ifndef _AMD64_MPCONFIG_H +#define _AMD64_MPCONFIG_H + +#ifndef _LOCORE + +struct mpbios_int; + +struct mp_bus { + char *mb_name; /* XXX bus name */ + int mb_idx; /* XXX bus index */ + void (*mb_intr_print)(int); + void (*mb_intr_cfg)(const struct mpbios_int *, u_int32_t *); + struct mp_intr_map *mb_intrs; + u_int32_t mb_data; /* random bus-specific datum. */ +}; + +struct mp_intr_map { + struct mp_intr_map *next; + struct mp_bus *bus; + int bus_pin; + struct ioapic_softc *ioapic; + int ioapic_pin; + int ioapic_ih; /* int handle, for apic_intr_est */ + int type; /* from mp spec intr record */ + int flags; /* from mp spec intr record */ + u_int32_t redir; + int cpu_id; +}; + +#if defined(_KERNEL) +extern int mp_verbose; +extern struct mp_bus *mp_busses; +extern int mp_nbusses; +extern struct mp_intr_map *mp_intrs; +extern int mp_nintrs; +extern struct mp_bus *mp_isa_bus; +extern struct mp_bus *mp_eisa_bus; +#endif +#endif + +#endif /* _AMD64_MPCONFIG_H */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/mplock.h b/lib/libc/include/x86_64-openbsd-none/amd64/mplock.h new file mode 100644 index 000000000000..d91a96332ee7 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/mplock.h @@ -0,0 +1,10 @@ +/* $OpenBSD: mplock.h,v 1.5 2017/10/17 14:25:35 visa Exp $ */ + +/* public domain */ + +#ifndef _MACHINE_MPLOCK_H_ +#define _MACHINE_MPLOCK_H_ + +#define __USE_MI_MPLOCK + +#endif /* !_MACHINE_MPLOCK_H */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/mutex.h b/lib/libc/include/x86_64-openbsd-none/amd64/mutex.h new file mode 100644 index 000000000000..69b3361f02f3 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/mutex.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mutex.h,v 1.11 2018/01/25 15:06:29 mpi Exp $ */ + +#define __USE_MI_MUTEX \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/param.h b/lib/libc/include/x86_64-openbsd-none/amd64/param.h new file mode 100644 index 000000000000..69522312f0fe --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/param.h @@ -0,0 +1,81 @@ +/* $OpenBSD: param.h,v 1.30 2025/07/07 18:33:36 kettenis Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ + +#ifdef _KERNEL +#ifdef _LOCORE +#include +#else +#include +#endif +#endif + +#define _MACHINE amd64 +#define MACHINE "amd64" +#define _MACHINE_ARCH amd64 +#define MACHINE_ARCH "amd64" +#define MID_MACHINE MID_AMD64 + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define PAGE_MASK (PAGE_SIZE - 1) + +#define KERNBASE 0xffffffff80000000 /* start of kernel virtual space */ + +#ifdef _KERNEL + +#define KERNTEXTOFF (KERNBASE+0x1000000) /* start of kernel text */ + +#define NBPG PAGE_SIZE /* bytes/page */ +#define PGSHIFT PAGE_SHIFT /* LOG2(PAGE_SIZE) */ +#define PGOFSET PAGE_MASK /* byte offset into page */ + +#define UPAGES 6 /* pages of u-area */ +#define USPACE (UPAGES * PAGE_SIZE) /* total size of u-area */ +#define USPACE_ALIGN 0 /* u-area alignment 0-none */ +#define __HAVE_USPACE_GUARD + +#define NMBCLUSTERS (256 * 1024) /* max cluster allocation */ + +#ifndef MSGBUFSIZE +#define MSGBUFSIZE (32 * PAGE_SIZE) /* default message buffer size */ +#endif + +#define __HAVE_ACPI + +#endif /* _KERNEL */ + +#endif /* _MACHINE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/pcb.h b/lib/libc/include/x86_64-openbsd-none/amd64/pcb.h new file mode 100644 index 000000000000..3cc195e20507 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/pcb.h @@ -0,0 +1,93 @@ +/* $OpenBSD: pcb.h,v 1.17 2018/06/05 06:39:11 guenther Exp $ */ +/* $NetBSD: pcb.h,v 1.1 2003/04/26 18:39:45 fvdl Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pcb.h 5.10 (Berkeley) 5/12/91 + */ + +#ifndef _MACHINE_PCB_H_ +#define _MACHINE_PCB_H_ + +#include + +#include + +/* + * Please note that the pcb_savefpu field in struct below must be + * on a 64-byte boundary. + */ +struct pcb { + struct savefpu pcb_savefpu; /* floating point state */ + u_int64_t pcb_cr3; + u_int64_t pcb_rsp; + u_int64_t pcb_rbp; + u_int64_t pcb_kstack; /* kernel stack address */ + u_int64_t pcb_fsbase; /* per-thread offset: %fs */ + caddr_t pcb_onfault; /* copyin/out fault recovery */ + struct pmap *pcb_pmap; /* back pointer to our pmap */ +}; + +#ifdef _KERNEL +void reset_segs(void); +#endif + +#endif /* _MACHINE_PCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/pci_machdep.h b/lib/libc/include/x86_64-openbsd-none/amd64/pci_machdep.h new file mode 100644 index 000000000000..6804596ff5a3 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/pci_machdep.h @@ -0,0 +1,137 @@ +/* $OpenBSD: pci_machdep.h,v 1.32 2025/01/23 11:24:34 kettenis Exp $ */ +/* $NetBSD: pci_machdep.h,v 1.1 2003/02/26 21:26:11 fvdl Exp $ */ + +/* + * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. + * Copyright (c) 1994 Charles M. Hannum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Charles M. Hannum. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Machine-specific definitions for PCI autoconfiguration. + */ + +/* + * amd64-specific PCI structure and type definitions. + * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE. + */ + +extern struct bus_dma_tag pci_bus_dma_tag; + +/* + * Types provided to machine-independent PCI code + */ +typedef void *pci_chipset_tag_t; +typedef u_int32_t pcitag_t; + +typedef struct { + pcitag_t tag; + int line, pin; +} pci_intr_handle_t; + +#define pci_intr_line(pc,ih) ((ih.line) & 0xff) + +/* + * amd64-specific PCI variables and functions. + * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE. + */ +struct pci_attach_args; + +extern struct extent *pciio_ex; +extern struct extent *pcimem_ex; +extern struct extent *pcibus_ex; +void pci_init_extents(void); + +/* + * Functions provided to machine-independent PCI code. + */ +void pci_attach_hook(struct device *, struct device *, + struct pcibus_attach_args *); +int pci_bus_maxdevs(pci_chipset_tag_t, int); +pcitag_t pci_make_tag(pci_chipset_tag_t, int, int, int); +void pci_decompose_tag(pci_chipset_tag_t, pcitag_t, + int *, int *, int *); +int pci_conf_size(pci_chipset_tag_t, pcitag_t); +pcireg_t pci_conf_read(pci_chipset_tag_t, pcitag_t, int); +void pci_conf_write(pci_chipset_tag_t, pcitag_t, int, + pcireg_t); +int pci_intr_enable_msivec(struct pci_attach_args *, int); +int pci_intr_map_msi(struct pci_attach_args *, + pci_intr_handle_t *); +int pci_intr_map_msivec(struct pci_attach_args *, + int, pci_intr_handle_t *); +int pci_intr_map_msix(struct pci_attach_args *, + int, pci_intr_handle_t *); +int pci_intr_map(struct pci_attach_args *, pci_intr_handle_t *); +const char *pci_intr_string(pci_chipset_tag_t, pci_intr_handle_t); +void *pci_intr_establish(pci_chipset_tag_t, pci_intr_handle_t, + int, int (*)(void *), void *, const char *); +void *pci_intr_establish_cpu(pci_chipset_tag_t, pci_intr_handle_t, + int, struct cpu_info *, + int (*)(void *), void *, const char *); +void pci_intr_disestablish(pci_chipset_tag_t, void *); +int pci_probe_device_hook(pci_chipset_tag_t, + struct pci_attach_args *); + +void pci_dev_postattach(struct device *, struct pci_attach_args *); + +pcireg_t pci_min_powerstate(pci_chipset_tag_t, pcitag_t); +void pci_set_powerstate_md(pci_chipset_tag_t, pcitag_t, int, int); + +void pci_mcfg_init(bus_space_tag_t, bus_addr_t, int, int, int); +pci_chipset_tag_t pci_lookup_segment(int, int); + +#define __HAVE_PCI_MSIX + +int pci_msix_table_map(pci_chipset_tag_t, pcitag_t, + bus_space_tag_t, bus_space_handle_t *); +void pci_msix_table_unmap(pci_chipset_tag_t, pcitag_t, + bus_space_tag_t, bus_space_handle_t); + +/* + * ALL OF THE FOLLOWING ARE MACHINE-DEPENDENT, AND SHOULD NOT BE USED + * BY PORTABLE CODE. + */ + +/* + * Section 6.2.4, `Miscellaneous Functions' of the PCI Specification, + * says that 255 means `unknown' or `no connection' to the interrupt + * controller on a PC. + */ +#define X86_PCI_INTERRUPT_LINE_NO_CONNECTION 0xff + +/* + * PCI address space is shared with ISA, so avoid legacy ISA I/O + * registers. + */ +#define PCI_IO_START 0x400 +#define PCI_IO_END 0xffff + +/* + * Avoid the DOS Compatibility Memory area. + */ +#define PCI_MEM_START 0x100000 \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/pctr.h b/lib/libc/include/x86_64-openbsd-none/amd64/pctr.h new file mode 100644 index 000000000000..53f01bdf681f --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/pctr.h @@ -0,0 +1,73 @@ +/* $OpenBSD: pctr.h,v 1.7 2019/08/26 12:41:47 pirofti Exp $ */ + +/* + * Pentium performance counter driver for OpenBSD. + * Copyright 1996 David Mazieres . + * + * Modification and redistribution in source and binary forms is + * permitted provided that due credit is given to the author and the + * OpenBSD project by leaving this copyright notice intact. + */ + +#ifndef _MACHINE_PCTR_H_ +#define _MACHINE_PCTR_H_ + +#include + +typedef u_int64_t pctrval; + +#define PCTR_NUM 4 + +struct pctrst { + u_int pctr_fn[PCTR_NUM]; /* Current settings of counters */ + pctrval pctr_tsc; /* Free-running 64-bit cycle counter */ + pctrval pctr_hwc[PCTR_NUM]; /* Values of the hardware counters */ +}; + +/* Bit values in fn fields and PIOCS ioctl's */ +#define PCTR_U 0x010000 /* Monitor user-level events */ +#define PCTR_K 0x020000 /* Monitor kernel-level events */ +#define PCTR_E 0x040000 /* Edge detect */ +#define PCTR_EN 0x400000 /* Enable counters (counter 0 only) */ +#define PCTR_I 0x800000 /* Invert counter mask */ + +/* Unit Mask values to distinguish cache coherent states */ +#define PCTR_UM_M 0x0800 /* Modified cache lines */ +#define PCTR_UM_E 0x0400 /* Exclusive cache lines */ +#define PCTR_UM_S 0x0200 /* Shared cache lines */ +#define PCTR_UM_I 0x0100 /* Invalid cache lines */ +#define PCTR_UM_MESI (PCTR_UM_M|PCTR_UM_E|PCTR_UM_S|PCTR_UM_I) +#define PCTR_UM_A 0x2000 /* Any initiator */ + +#define PCTR_UM_SHIFT 8 /* Left shift for unit mask */ +#define PCTR_CM_SHIFT 24 /* Left shift for counter mask */ + +/* ioctl to set which counter a device tracks */ +#define PCIOCRD _IOR('c', 1, struct pctrst) /* Read counter value */ +#define PCIOCS0 _IOW('c', 8, unsigned int) /* Set counter 0 function */ +#define PCIOCS1 _IOW('c', 9, unsigned int) /* Set counter 1 function */ +#define PCIOCS2 _IOW('c', 10, unsigned int) /* Set counter 2 function */ +#define PCIOCS3 _IOW('c', 11, unsigned int) /* Set counter 3 function */ + +#define _PATH_PCTR "/dev/pctr" + +#define rdpmc(pmc) \ +({ \ + u_int32_t hi, lo; \ + __asm volatile("rdpmc" \ + : "=d" (hi), "=a" (lo) : "c" (pmc)); \ + hi &= 0xffffff; \ + (((u_int64_t)hi << 32) | (u_int64_t)lo); \ +}) + +#ifdef _KERNEL + +void pctrattach(int); +int pctropen(dev_t, int, int, struct proc *); +int pctrclose(dev_t, int, int, struct proc *); +int pctrioctl(dev_t, u_long, caddr_t, int, struct proc *); +void pctr_reload(struct cpu_info *); +void pctr_resume(struct cpu_info *); + +#endif /* _KERNEL */ +#endif /* ! _MACHINE_PCTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/pic.h b/lib/libc/include/x86_64-openbsd-none/amd64/pic.h new file mode 100644 index 000000000000..21acee849893 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/pic.h @@ -0,0 +1,45 @@ +/* $OpenBSD: pic.h,v 1.8 2024/01/19 18:38:16 kettenis Exp $ */ +/* $NetBSD: pic.h,v 1.1 2003/02/26 21:26:11 fvdl Exp $ */ + +#ifndef _X86_PIC_H +#define _X86_PIC_H + +#include +#include + +struct cpu_info; + +/* + * Structure common to all PIC softcs + */ +struct pic { + struct device pic_dev; + int pic_type; +#ifdef MULTIPROCESSOR + struct mutex pic_mutex; +#endif + void (*pic_hwmask)(struct pic *, int); + void (*pic_hwunmask)(struct pic *, int); + void (*pic_addroute)(struct pic *, struct cpu_info *, int, int, int); + void (*pic_delroute)(struct pic *, struct cpu_info *, int, int, int); + int (*pic_allocidtvec)(struct pic *, int, int, int); + struct intrstub *pic_level_stubs; + struct intrstub *pic_edge_stubs; +}; + +#define pic_name pic_dev.dv_xname + +/* + * PIC types. + */ +#define PIC_I8259 0 +#define PIC_IOAPIC 1 +#define PIC_LAPIC 2 +#define PIC_MSI 3 +#define PIC_SOFT 4 + +extern struct pic i8259_pic; +extern struct pic local_pic; +extern struct pic msi_pic; +extern struct pic softintr_pic; +#endif \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/pio.h b/lib/libc/include/x86_64-openbsd-none/amd64/pio.h new file mode 100644 index 000000000000..f1236a357000 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/pio.h @@ -0,0 +1,225 @@ +/* $OpenBSD: pio.h,v 1.5 2015/04/25 21:31:24 guenther Exp $ */ +/* $NetBSD: pio.h,v 1.2 2003/02/27 11:22:46 fvdl Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_PIO_H_ +#define _MACHINE_PIO_H_ + +/* + * Functions to provide access to x86 programmed I/O instructions. + * + * The in[bwl]() and out[bwl]() functions are split into two varieties: one to + * use a small, constant, 8-bit port number, and another to use a large or + * variable port number. The former can be compiled as a smaller instruction. + */ + + +#ifdef __OPTIMIZE__ + +#define __use_immediate_port(port) \ + (__builtin_constant_p((port)) && (port) < 0x100) + +#else + +#define __use_immediate_port(port) 0 + +#endif + + +#define inb(port) \ + (/* CONSTCOND */ __use_immediate_port(port) ? __inbc(port) : __inb(port)) + +static __inline u_int8_t +__inbc(unsigned port) +{ + u_int8_t data; + __asm volatile("inb %w1,%0" : "=a" (data) : "id" (port)); + return data; +} + +static __inline u_int8_t +__inb(unsigned port) +{ + u_int8_t data; + __asm volatile("inb %w1,%0" : "=a" (data) : "d" (port)); + return data; +} + +static __inline void +insb(unsigned port, void *addr, int cnt) +{ + void *dummy1; + int dummy2; + __asm volatile("repne\n\tinsb" : + "=D" (dummy1), "=c" (dummy2) : + "d" (port), "0" (addr), "1" (cnt) : + "memory"); +} + +#define inw(port) \ + (/* CONSTCOND */ __use_immediate_port(port) ? __inwc(port) : __inw(port)) + +static __inline u_int16_t +__inwc(unsigned port) +{ + u_int16_t data; + __asm volatile("inw %w1,%0" : "=a" (data) : "id" (port)); + return data; +} + +static __inline u_int16_t +__inw(unsigned port) +{ + u_int16_t data; + __asm volatile("inw %w1,%0" : "=a" (data) : "d" (port)); + return data; +} + +static __inline void +insw(unsigned port, void *addr, int cnt) +{ + void *dummy1; + int dummy2; + __asm volatile("repne\n\tinsw" : + "=D" (dummy1), "=c" (dummy2) : + "d" (port), "0" (addr), "1" (cnt) : + "memory"); +} + +#define inl(port) \ + (/* CONSTCOND */ __use_immediate_port(port) ? __inlc(port) : __inl(port)) + +static __inline u_int32_t +__inlc(unsigned port) +{ + u_int32_t data; + __asm volatile("inl %w1,%0" : "=a" (data) : "id" (port)); + return data; +} + +static __inline u_int32_t +__inl(unsigned port) +{ + u_int32_t data; + __asm volatile("inl %w1,%0" : "=a" (data) : "d" (port)); + return data; +} + +static __inline void +insl(unsigned port, void *addr, int cnt) +{ + void *dummy1; + int dummy2; + __asm volatile("repne\n\tinsl" : + "=D" (dummy1), "=c" (dummy2) : + "d" (port), "0" (addr), "1" (cnt) : + "memory"); +} + +#define outb(port, data) \ + (/* CONSTCOND */__use_immediate_port(port) ? __outbc(port, data) : \ + __outb(port, data)) + +static __inline void +__outbc(unsigned port, u_int8_t data) +{ + __asm volatile("outb %0,%w1" : : "a" (data), "id" (port)); +} + +static __inline void +__outb(unsigned port, u_int8_t data) +{ + __asm volatile("outb %0,%w1" : : "a" (data), "d" (port)); +} + +static __inline void +outsb(unsigned port, const void *addr, int cnt) +{ + void *dummy1; + int dummy2; + __asm volatile("repne\n\toutsb" : + "=S" (dummy1), "=c" (dummy2) : + "d" (port), "0" (addr), "1" (cnt)); +} + +#define outw(port, data) \ + (/* CONSTCOND */ __use_immediate_port(port) ? __outwc(port, data) : \ + __outw(port, data)) + +static __inline void +__outwc(unsigned port, u_int16_t data) +{ + __asm volatile("outw %0,%w1" : : "a" (data), "id" (port)); +} + +static __inline void +__outw(unsigned port, u_int16_t data) +{ + __asm volatile("outw %0,%w1" : : "a" (data), "d" (port)); +} + +static __inline void +outsw(unsigned port, const void *addr, int cnt) +{ + void *dummy1; + int dummy2; + __asm volatile("repne\n\toutsw" : + "=S" (dummy1), "=c" (dummy2) : + "d" (port), "0" (addr), "1" (cnt)); +} + +#define outl(port, data) \ + (/* CONSTCOND */ __use_immediate_port(port) ? __outlc(port, data) : \ + __outl(port, data)) + +static __inline void +__outlc(unsigned port, u_int32_t data) +{ + __asm volatile("outl %0,%w1" : : "a" (data), "id" (port)); +} + +static __inline void +__outl(unsigned port, u_int32_t data) +{ + __asm volatile("outl %0,%w1" : : "a" (data), "d" (port)); +} + +static __inline void +outsl(unsigned port, const void *addr, int cnt) +{ + void *dummy1; + int dummy2; + __asm volatile("repne\n\toutsl" : + "=S" (dummy1), "=c" (dummy2) : + "d" (port), "0" (addr), "1" (cnt)); +} + +#endif /* _MACHINE_PIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/pmap.h b/lib/libc/include/x86_64-openbsd-none/amd64/pmap.h new file mode 100644 index 000000000000..1b1c88897834 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/pmap.h @@ -0,0 +1,524 @@ +/* $OpenBSD: pmap.h,v 1.94 2025/07/07 00:55:15 jsg Exp $ */ +/* $NetBSD: pmap.h,v 1.1 2003/04/26 18:39:46 fvdl Exp $ */ + +/* + * Copyright (c) 1997 Charles D. Cranor and Washington University. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2001 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Frank van der Linden for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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. + */ + +/* + * pmap.h: see pmap.c for the history of this pmap module. + */ + +#ifndef _MACHINE_PMAP_H_ +#define _MACHINE_PMAP_H_ + +#ifndef _LOCORE +#ifdef _KERNEL +#include /* for KASSERT() */ +#include +#endif /* _KERNEL */ +#include +#include +#include +#endif + +/* + * The x86_64 pmap module closely resembles the i386 one. It uses + * the same recursive entry scheme. See the i386 pmap.h for a + * description. The alternate area trick for accessing non-current + * pmaps has been removed, though, because it performs badly on SMP + * systems. + * The most obvious difference to i386 is that 2 extra levels of page + * table need to be dealt with. The level 1 page table pages are at: + * + * l1: 0x00007f8000000000 - 0x00007fffffffffff (39 bits, needs PML4 entry) + * + * The other levels are kept as physical pages in 3 UVM objects and are + * temporarily mapped for virtual access when needed. + * + * The other obvious difference from i386 is that it has a direct map of all + * physical memory in the VA range: + * + * 0xfffffd8000000000 - 0xffffff7fffffffff + * + * The direct map is used in some cases to access PTEs of non-current pmaps. + * + * Note that address space is signed, so the layout for 48 bits is: + * + * +---------------------------------+ 0xffffffffffffffff + * | Kernel Image | + * +---------------------------------+ 0xffffff8000000000 + * | Direct Map | + * +---------------------------------+ 0xfffffd8000000000 + * ~ ~ + * | | + * | Kernel Space | + * | | + * | | + * +---------------------------------+ 0xffff800000000000 = 0x0000800000000000 + * | L1 table (PTE pages) | + * +---------------------------------+ 0x00007f8000000000 + * ~ ~ + * | | + * | User Space | + * | | + * | | + * +---------------------------------+ 0x0000000000000000 + * + * In other words, there is a 'VA hole' at 0x0000800000000000 - + * 0xffff800000000000 which will trap, just as on, for example, + * sparcv9. + * + * The unused space can be used if needed, but it adds a little more + * complexity to the calculations. + */ + +/* + * Mask to get rid of the sign-extended part of addresses. + */ +#define VA_SIGN_MASK 0xffff000000000000 +#define VA_SIGN_NEG(va) ((va) | VA_SIGN_MASK) +/* + * XXXfvdl this one's not right. + */ +#define VA_SIGN_POS(va) ((va) & ~VA_SIGN_MASK) + +#define L4_SLOT_PTE 255 +#define L4_SLOT_KERN 256 +#define L4_SLOT_KERNBASE 511 +#define NUM_L4_SLOT_DIRECT 4 +#define L4_SLOT_DIRECT (L4_SLOT_KERNBASE - NUM_L4_SLOT_DIRECT) +#define L4_SLOT_EARLY (L4_SLOT_DIRECT - 1) + +#define PDIR_SLOT_KERN L4_SLOT_KERN +#define PDIR_SLOT_PTE L4_SLOT_PTE +#define PDIR_SLOT_DIRECT L4_SLOT_DIRECT +#define PDIR_SLOT_EARLY L4_SLOT_EARLY + +/* + * the following defines give the virtual addresses of various MMU + * data structures: + * PTE_BASE: the base VA of the linear PTE mappings + * PDP_PDE: the VA of the PDE that points back to the PDP + * + */ + +#define PTE_BASE ((pt_entry_t *) (L4_SLOT_PTE * NBPD_L4)) +#define PMAP_DIRECT_BASE (VA_SIGN_NEG((L4_SLOT_DIRECT * NBPD_L4))) +#define PMAP_DIRECT_END (VA_SIGN_NEG(((L4_SLOT_DIRECT + \ + NUM_L4_SLOT_DIRECT) * NBPD_L4))) + +#define L1_BASE PTE_BASE + +#define L2_BASE ((pd_entry_t *)((char *)L1_BASE + L4_SLOT_PTE * NBPD_L3)) +#define L3_BASE ((pd_entry_t *)((char *)L2_BASE + L4_SLOT_PTE * NBPD_L2)) +#define L4_BASE ((pd_entry_t *)((char *)L3_BASE + L4_SLOT_PTE * NBPD_L1)) + +#define PDP_PDE (L4_BASE + PDIR_SLOT_PTE) + +#define PDP_BASE L4_BASE + +#define NKL4_MAX_ENTRIES (unsigned long)1 +#define NKL3_MAX_ENTRIES (unsigned long)(NKL4_MAX_ENTRIES * 512) +#define NKL2_MAX_ENTRIES (unsigned long)(NKL3_MAX_ENTRIES * 512) +#define NKL1_MAX_ENTRIES (unsigned long)(NKL2_MAX_ENTRIES * 512) + +#define NKL4_KIMG_ENTRIES 1 +#define NKL3_KIMG_ENTRIES 1 +#define NKL2_KIMG_ENTRIES 64 + +/* number of pages of direct map entries set up by locore0.S */ +#define NDML4_ENTRIES 1 +#define NDML3_ENTRIES 1 +#define NDML2_ENTRIES 4 /* 4GB */ + +/* + * Since kva space is below the kernel in its entirety, we start off + * with zero entries on each level. + */ +#define NKL4_START_ENTRIES 0 +#define NKL3_START_ENTRIES 0 +#define NKL2_START_ENTRIES 0 +#define NKL1_START_ENTRIES 0 /* XXX */ + +#define NTOPLEVEL_PDES (PAGE_SIZE / (sizeof (pd_entry_t))) + +#define NPDPG (PAGE_SIZE / sizeof (pd_entry_t)) + +/* + * pl*_pi: index in the ptp page for a pde mapping a VA. + * (pl*_i below is the index in the virtual array of all pdes per level) + */ +#define pl1_pi(VA) (((VA_SIGN_POS(VA)) & L1_MASK) >> L1_SHIFT) +#define pl2_pi(VA) (((VA_SIGN_POS(VA)) & L2_MASK) >> L2_SHIFT) +#define pl3_pi(VA) (((VA_SIGN_POS(VA)) & L3_MASK) >> L3_SHIFT) +#define pl4_pi(VA) (((VA_SIGN_POS(VA)) & L4_MASK) >> L4_SHIFT) + +/* + * pl*_i: generate index into pde/pte arrays in virtual space + */ +#define pl1_i(VA) (((VA_SIGN_POS(VA)) & L1_FRAME) >> L1_SHIFT) +#define pl2_i(VA) (((VA_SIGN_POS(VA)) & L2_FRAME) >> L2_SHIFT) +#define pl3_i(VA) (((VA_SIGN_POS(VA)) & L3_FRAME) >> L3_SHIFT) +#define pl4_i(VA) (((VA_SIGN_POS(VA)) & L4_FRAME) >> L4_SHIFT) +#define pl_i(va, lvl) \ + (((VA_SIGN_POS(va)) & ptp_masks[(lvl)-1]) >> ptp_shifts[(lvl)-1]) + +#define PTP_MASK_INITIALIZER { L1_FRAME, L2_FRAME, L3_FRAME, L4_FRAME } +#define PTP_SHIFT_INITIALIZER { L1_SHIFT, L2_SHIFT, L3_SHIFT, L4_SHIFT } +#define NKPTP_INITIALIZER { NKL1_START_ENTRIES, NKL2_START_ENTRIES, \ + NKL3_START_ENTRIES, NKL4_START_ENTRIES } +#define NKPTPMAX_INITIALIZER { NKL1_MAX_ENTRIES, NKL2_MAX_ENTRIES, \ + NKL3_MAX_ENTRIES, NKL4_MAX_ENTRIES } +#define NBPD_INITIALIZER { NBPD_L1, NBPD_L2, NBPD_L3, NBPD_L4 } +#define PDES_INITIALIZER { L2_BASE, L3_BASE, L4_BASE } + +/* + * PTP macros: + * a PTP's index is the PD index of the PDE that points to it + * a PTP's offset is the byte-offset in the PTE space that this PTP is at + * a PTP's VA is the first VA mapped by that PTP + */ + +#define ptp_va2o(va, lvl) (pl_i(va, (lvl)+1) * PAGE_SIZE) + +#define PTP_LEVELS 4 + +/* + * PG_AVAIL usage: we make use of the ignored bits of the PTE + */ + +#define PG_W PG_AVAIL1 /* "wired" mapping */ +#define PG_PVLIST PG_AVAIL2 /* mapping has entry on pvlist */ +/* PG_AVAIL3 not used */ + +/* + * PCID assignments. + * The shootdown code assumes KERN, PROC, and PROC_INTEL are both + * consecutive and in that order. + */ +#define PCID_KERN 0 /* for pmap_kernel() */ +#define PCID_PROC 1 /* non-pmap_kernel(), U+K */ +#define PCID_PROC_INTEL 2 /* non-pmap_kernel(), U-K (meltdown) */ +#define PCID_TEMP 3 /* temp mapping of another non-pmap_kernel() */ +#define PCID_EFI 4 /* EFI runtime services */ + +extern int pmap_use_pcid; /* non-zero if PCID support is enabled */ + +/* + * Number of PTEs per cache line. 8 byte pte, 64-byte cache line + * Used to avoid false sharing of cache lines. + */ +#define NPTECL 8 + + +#if defined(_KERNEL) && !defined(_LOCORE) +/* + * pmap data structures: see pmap.c for details of locking. + */ + +struct pmap; +typedef struct pmap *pmap_t; + +/* + * we maintain a list of all non-kernel pmaps + */ + +LIST_HEAD(pmap_head, pmap); /* struct pmap_head: head of a pmap list */ + +/* + * the pmap structure + * + * note that the pm_obj contains the reference count, + * page list, and number of PTPs within the pmap. + */ + +#define PMAP_TYPE_NORMAL 1 +#define PMAP_TYPE_EPT 2 +#define PMAP_TYPE_RVI 3 +#define pmap_nested(pm) ((pm)->pm_type != PMAP_TYPE_NORMAL) +#define pmap_is_ept(pm) ((pm)->pm_type == PMAP_TYPE_EPT) + +struct pmap { + struct mutex pm_mtx; + struct uvm_object pm_obj[PTP_LEVELS-1]; /* objects for lvl >= 1) */ + LIST_ENTRY(pmap) pm_list; /* list (lck by pm_list lock) */ + /* + * pm_pdir : VA of page table to be used when executing in + * privileged mode + * pm_pdirpa : PA of page table to be used when executing in + * privileged mode + * pm_pdir_intel : VA of special page table to be used when executing + * on an Intel CPU in usermode (no kernel mappings) + * pm_pdirpa_intel : PA of special page table to be used when executing + * on an Intel CPU in usermode (no kernel mappings) + */ + pd_entry_t *pm_pdir, *pm_pdir_intel; + paddr_t pm_pdirpa, pm_pdirpa_intel; + + struct vm_page *pm_ptphint[PTP_LEVELS-1]; + /* pointer to a PTP in our pmap */ + struct pmap_statistics pm_stats; /* pmap stats (lck by object lock) */ + + int pm_type; /* Type of pmap this is (PMAP_TYPE_x) */ + uint64_t eptp; /* cached EPTP (used by vmm) */ +}; + +#define PMAP_EFI PMAP_MD0 +#define PMAP_NOCRYPT PMAP_MD1 + +/* + * MD flags that we use for pmap_enter (in the pa): + */ +#define PMAP_PA_MASK ~((paddr_t)PAGE_MASK) /* to remove the flags */ +#define PMAP_NOCACHE 0x1 /* set the non-cacheable bit. */ +#define PMAP_WC 0x2 /* set page write combining. */ + +/* + * We keep mod/ref flags in struct vm_page->pg_flags. + */ +#define PG_PMAP_MOD PG_PMAP0 +#define PG_PMAP_REF PG_PMAP1 +#define PG_PMAP_WC PG_PMAP2 + +/* + * for each managed physical page we maintain a list of 's + * which it is mapped at. + */ +struct pv_entry { /* locked by its list's pvh_lock */ + struct pv_entry *pv_next; /* next entry */ + struct pmap *pv_pmap; /* the pmap */ + vaddr_t pv_va; /* the virtual address */ + struct vm_page *pv_ptp; /* the vm_page of the PTP */ +}; + +/* + * global kernel variables + */ + +extern struct pmap kernel_pmap_store; /* kernel pmap */ + +extern long nkptp[]; + +extern const paddr_t ptp_masks[]; +extern const int ptp_shifts[]; +extern const long nbpd[], nkptpmax[]; + +/* + * macros + */ + +#define pmap_kernel() (&kernel_pmap_store) +#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) +#define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count) +#define pmap_update(pmap) /* nothing (yet) */ + +#define pmap_clear_modify(pg) pmap_clear_attrs(pg, PG_M) +#define pmap_clear_reference(pg) pmap_clear_attrs(pg, PG_U) +#define pmap_is_modified(pg) pmap_test_attrs(pg, PG_M) +#define pmap_is_referenced(pg) pmap_test_attrs(pg, PG_U) +#define pmap_valid_entry(E) ((E) & PG_V) /* is PDE or PTE valid? */ + +#define pmap_proc_iflush(p,va,len) /* nothing */ +#define pmap_unuse_final(p) /* nothing */ +#define pmap_remove_holes(vm) do { /* nothing */ } while (0) + + +/* + * prototypes + */ + +void map_tramps(void); /* machdep.c */ +paddr_t pmap_bootstrap(paddr_t, paddr_t); +void pmap_init_percpu(void); +void pmap_randomize(void); +void pmap_randomize_level(pd_entry_t *, int); +int pmap_clear_attrs(struct vm_page *, unsigned long); +static void pmap_page_protect(struct vm_page *, vm_prot_t); +void pmap_page_remove (struct vm_page *); +static void pmap_protect(struct pmap *, vaddr_t, + vaddr_t, vm_prot_t); +void pmap_remove(struct pmap *, vaddr_t, vaddr_t); +int pmap_test_attrs(struct vm_page *, unsigned); +static void pmap_update_pg(vaddr_t); +void pmap_write_protect(struct pmap *, vaddr_t, + vaddr_t, vm_prot_t); + +paddr_t pmap_prealloc_lowmem_ptps(paddr_t); + +void pagezero(vaddr_t); + +void pmap_convert(struct pmap *, int); +void pmap_enter_special(vaddr_t, paddr_t, vm_prot_t); +vaddr_t pmap_set_pml4_early(paddr_t pa); +void pmap_clear_pml4_early(void); + +/* + * functions for flushing the cache for vaddrs and pages. + * these functions are not part of the MI pmap interface and thus + * should not be used as such. + */ +void pmap_flush_cache(vaddr_t, vsize_t); +#define pmap_flush_page(paddr) do { \ + KDASSERT(PHYS_TO_VM_PAGE(paddr) != NULL); \ + pmap_flush_cache(PMAP_DIRECT_MAP(paddr), PAGE_SIZE); \ +} while (/* CONSTCOND */ 0) + +#define PMAP_CHECK_COPYIN (pg_xo == 0) + +#define PMAP_STEAL_MEMORY /* enable pmap_steal_memory() */ +#define PMAP_GROWKERNEL /* turn on pmap_growkernel interface */ + +/* + * inline functions + */ + +/* + * pmap_update_pg: flush one page from the TLB (or flush the whole thing + * if hardware doesn't support one-page flushing) + */ + +static inline void +pmap_update_pg(vaddr_t va) +{ + invlpg(va); +} + +/* + * pmap_page_protect: change the protection of all recorded mappings + * of a managed page + * + * => this function is a frontend for pmap_page_remove/pmap_clear_attrs + * => we only have to worry about making the page more protected. + * unprotecting a page is done on-demand at fault time. + */ + +static inline void +pmap_page_protect(struct vm_page *pg, vm_prot_t prot) +{ + if (prot == PROT_READ) { + (void) pmap_clear_attrs(pg, PG_RW); + } else { + KASSERT(prot == PROT_NONE); + pmap_page_remove(pg); + } +} + +/* + * pmap_protect: change the protection of pages in a pmap + * + * => this function is a frontend for pmap_remove/pmap_write_protect + * => we only have to worry about making the page more protected. + * unprotecting a page is done on-demand at fault time. + */ + +static inline void +pmap_protect(struct pmap *pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot) +{ + if (prot != PROT_NONE) { + pmap_write_protect(pmap, sva, eva, prot); + } else { + pmap_remove(pmap, sva, eva); + } +} + +/* + * kvtopte: return a pointer to the PTE mapping a kernel VA + */ + +static inline pt_entry_t * +kvtopte(vaddr_t va) +{ +#ifdef LARGEPAGES + { + pd_entry_t *pde; + + pde = L1_BASE + pl2_i(va); + if (*pde & PG_PS) + return ((pt_entry_t *)pde); + } +#endif + + return (PTE_BASE + pl1_i(va)); +} + +#define PMAP_DIRECT_MAP(pa) ((vaddr_t)PMAP_DIRECT_BASE + (pa)) +#define PMAP_DIRECT_UNMAP(va) ((paddr_t)(va) - PMAP_DIRECT_BASE) +#define pmap_map_direct(pg) PMAP_DIRECT_MAP(VM_PAGE_TO_PHYS(pg)) +#define pmap_unmap_direct(va) PHYS_TO_VM_PAGE(PMAP_DIRECT_UNMAP(va)) + +#define __HAVE_PMAP_DIRECT +#define __HAVE_PMAP_MPSAFE_ENTER_COW + +#endif /* _KERNEL && !_LOCORE */ + +#ifndef _LOCORE +struct pv_entry; +struct vm_page_md { + struct mutex pv_mtx; + struct pv_entry *pv_list; +}; + +#define VM_MDPAGE_INIT(pg) do { \ + mtx_init(&(pg)->mdpage.pv_mtx, IPL_VM); \ + (pg)->mdpage.pv_list = NULL; \ +} while (0) +#endif /* !_LOCORE */ + +#endif /* _MACHINE_PMAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/proc.h b/lib/libc/include/x86_64-openbsd-none/amd64/proc.h new file mode 100644 index 000000000000..f365bebe6b5b --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/proc.h @@ -0,0 +1,52 @@ +/* $OpenBSD: proc.h,v 1.10 2018/06/05 06:39:11 guenther Exp $ */ +/* $NetBSD: proc.h,v 1.1 2003/04/26 18:39:46 fvdl Exp $ */ + +/* + * Copyright (c) 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)proc.h 7.1 (Berkeley) 5/15/91 + */ + +#ifndef _MACHINE_PROC_H_ +#define _MACHINE_PROC_H_ + +/* + * Machine-dependent part of the proc structure for amd64. + */ +struct trapframe; +struct mdproc { + struct trapframe *md_regs; /* registers on current frame */ + int md_flags; + volatile int md_astpending; +}; + +/* md_flags */ +#define MDP_IRET 0x0002 /* return via iret, not sysret */ + /* (iret can restore r11 and rcx) */ + +#endif /* _MACHINE_PROC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/profile.h b/lib/libc/include/x86_64-openbsd-none/amd64/profile.h new file mode 100644 index 000000000000..04fc7ace4875 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/profile.h @@ -0,0 +1,77 @@ +/* $OpenBSD: profile.h,v 1.6 2023/06/27 10:11:15 cheloha Exp $ */ +/* $NetBSD: profile.h,v 1.3 2003/11/28 23:22:45 fvdl Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)profile.h 8.1 (Berkeley) 6/11/93 + */ + +#define _MCOUNT_DECL void _mcount + +#ifdef __PIC__ +#define __MCPLT "@PLT" +#else +#define __MCPLT +#endif + +#define MCOUNT \ +__asm(" .globl __mcount \n" \ +" .type __mcount,@function\n" \ +"__mcount: \n" \ +" pushq %rbp \n" \ +" movq %rsp,%rbp \n" \ +" subq $56,%rsp \n" \ +" movq %rdi,0(%rsp) \n" \ +" movq %rsi,8(%rsp) \n" \ +" movq %rdx,16(%rsp) \n" \ +" movq %rcx,24(%rsp) \n" \ +" movq %r8,32(%rsp) \n" \ +" movq %r9,40(%rsp) \n" \ +" movq %rax,48(%rsp) \n" \ +" movq 0(%rbp),%r11 \n" \ +" movq 8(%r11),%rdi \n" \ +" movq 8(%rbp),%rsi \n" \ +" call _mcount"__MCPLT"\n" \ +" movq 0(%rsp),%rdi \n" \ +" movq 8(%rsp),%rsi \n" \ +" movq 16(%rsp),%rdx \n" \ +" movq 24(%rsp),%rcx \n" \ +" movq 32(%rsp),%r8 \n" \ +" movq 40(%rsp),%r9 \n" \ +" movq 48(%rsp),%rax \n" \ +" leave \n" \ +" ret \n" \ +" lfence \n" \ +" .size __mcount,.-__mcount"); + + +#ifdef _KERNEL +#define MCOUNT_ENTER s = intr_disable() +#define MCOUNT_EXIT intr_restore(s) +#endif /* _KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/psl.h b/lib/libc/include/x86_64-openbsd-none/amd64/psl.h new file mode 100644 index 000000000000..2fa183244ff5 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/psl.h @@ -0,0 +1,76 @@ +/* $OpenBSD: psl.h,v 1.5 2018/07/09 19:20:29 guenther Exp $ */ +/* $NetBSD: psl.h,v 1.1 2003/02/26 21:26:11 fvdl Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)psl.h 5.2 (Berkeley) 1/18/91 + */ + +#ifndef _MACHINE_PSL_H_ +#define _MACHINE_PSL_H_ + +/* + * 386 processor status longword. + */ +#define PSL_C 0x00000001 /* carry flag */ +#define PSL_PF 0x00000004 /* parity flag */ +#define PSL_AF 0x00000010 /* auxiliary carry flag */ +#define PSL_Z 0x00000040 /* zero flag */ +#define PSL_N 0x00000080 /* sign flag */ +#define PSL_T 0x00000100 /* trap flag */ +#define PSL_I 0x00000200 /* interrupt enable flag */ +#define PSL_D 0x00000400 /* direction flag */ +#define PSL_V 0x00000800 /* overflow flag */ +#define PSL_IOPL 0x00003000 /* i/o privilege level */ +#define PSL_NT 0x00004000 /* nested task */ +#define PSL_RF 0x00010000 /* resume flag */ +#define PSL_VM 0x00020000 /* virtual 8086 mode */ +#define PSL_AC 0x00040000 /* alignment check flag */ +#define PSL_VIF 0x00080000 /* virtual interrupt enable flag */ +#define PSL_VIP 0x00100000 /* virtual interrupt pending flag */ +#define PSL_ID 0x00200000 /* identification flag */ + +#define PSL_MBO 0x00000002 /* must be one bits */ +#define PSL_MBZ 0xffc08028 /* must be zero bits */ + +#define PSL_USERSET (PSL_MBO | PSL_I) +#define PSL_USERSTATIC (PSL_MBO | PSL_MBZ | PSL_I | PSL_IOPL | PSL_NT | PSL_VM | PSL_VIF | PSL_VIP) +#define PSL_USER (PSL_C | PSL_MBO | PSL_PF | PSL_AF | PSL_Z | PSL_N | PSL_V) + +/* + * ??? + */ +#ifdef _KERNEL +#include +#endif + +#endif /* !_MACHINE_PSL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/pte.h b/lib/libc/include/x86_64-openbsd-none/amd64/pte.h new file mode 100644 index 000000000000..c91bf8cea9cf --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/pte.h @@ -0,0 +1,171 @@ +/* $OpenBSD: pte.h,v 1.18 2024/07/09 19:11:06 bluhm Exp $ */ +/* $NetBSD: pte.h,v 1.1 2003/04/26 18:39:47 fvdl Exp $ */ + +/* + * Copyright (c) 2001 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Frank van der Linden for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_PTE_H_ +#define _MACHINE_PTE_H_ + +/* + * amd64 MMU hardware structure: + * + * the (first generation) amd64 MMU is a 4-level MMU which maps 2^48 bytes + * of virtual memory. The pagesize we use is 4K (4096 [0x1000] bytes), + * although 2M and 4M can be used as well. The indexes in the levels + * are 9 bits wide (512 64bit entries per level), dividing the bits + * 9-9-9-9-12. + * + * The top level table, called PML4, contains 512 64bit entries pointing + * to 3rd level table. The 3rd level table is called the 'page directory + * pointers directory' and has 512 entries pointing to page directories. + * The 2nd level is the page directory, containing 512 pointers to + * page table pages. Lastly, level 1 consists of pages containing 512 + * PTEs. + * + * Simply put, levels 4-1 all consist of pages containing 512 + * entries pointing to the next level. Level 0 is the actual PTEs + * themselves. + * + * For a description on the other bits, which are i386 compatible, + * see the i386 pte.h + */ + +#if !defined(_LOCORE) + +/* + * here we define the data types for PDEs and PTEs + */ + +typedef u_int64_t pd_entry_t; /* PDE */ +typedef u_int64_t pt_entry_t; /* PTE */ + +#endif + +/* + * now we define various for playing with virtual addresses + */ + +#define L1_SHIFT 12 +#define L2_SHIFT 21 +#define L3_SHIFT 30 +#define L4_SHIFT 39 +#define NBPD_L1 (1ULL << L1_SHIFT) /* # bytes mapped by L1 ent (4K) */ +#define NBPD_L2 (1ULL << L2_SHIFT) /* # bytes mapped by L2 ent (2MB) */ +#define NBPD_L3 (1ULL << L3_SHIFT) /* # bytes mapped by L3 ent (1G) */ +#define NBPD_L4 (1ULL << L4_SHIFT) /* # bytes mapped by L4 ent (512G) */ + +#define L4_MASK 0x0000ff8000000000UL +#define L3_MASK 0x0000007fc0000000UL +#define L2_MASK 0x000000003fe00000UL +#define L1_MASK 0x00000000001ff000UL + +#define L4_FRAME L4_MASK +#define L3_FRAME (L4_FRAME|L3_MASK) +#define L2_FRAME (L3_FRAME|L2_MASK) +#define L1_FRAME (L2_FRAME|L1_MASK) + +#define PAGE_MASK_L2 (NBPD_L2 - 1) + +#define x86_round_pdr(x) \ + ((((unsigned long)(x)) + (NBPD_L2 - 1)) & ~(NBPD_L2 - 1)) + +/* + * PDE/PTE bits. These are no different from their i386 counterparts. + */ + +#define PG_V 0x0000000000000001UL /* valid */ +#define PG_RO 0x0000000000000000UL /* read-only */ +#define PG_RW 0x0000000000000002UL /* read-write */ +#define PG_u 0x0000000000000004UL /* user accessible */ +#define PG_PROT 0x0000000000000006UL +#define PG_WT 0x0000000000000008UL /* write through */ +#define PG_N 0x0000000000000010UL /* non-cacheable */ +#define PG_U 0x0000000000000020UL /* used */ +#define PG_M 0x0000000000000040UL /* modified */ +#define PG_PAT 0x0000000000000080UL /* PAT bit. (on pte) */ +#define PG_PS 0x0000000000000080UL /* 2MB page size (on pde) */ +#define PG_G 0x0000000000000100UL /* not flushed */ +#define PG_AVAIL1 0x0000000000000200UL +#define PG_AVAIL2 0x0000000000000400UL +#define PG_AVAIL3 0x0000000000000800UL +#define PG_PATLG 0x0000000000001000UL /* PAT on large pages */ +#define PG_PKMASK 0x7800000000000000UL /* Protection Key Mask */ +#define PG_XO 0x0800000000000000UL /* key1 used for execute-only */ +#define PG_NX 0x8000000000000000UL /* non-executable */ +#define PG_FRAME 0x000ffffffffff000UL + +#define PG_LGFRAME 0x000fffffffe00000UL /* large (2M) page frame mask */ + +#define PGK_VALUE 0xfffffffc /* key0 is normal */ + +/* EPT PTE bits */ +#define EPT_R (1ULL << 0) +#define EPT_W (1ULL << 1) +#define EPT_X (1ULL << 2) +#define EPT_WB (6ULL << 3) +#define EPT_PS (1ULL << 7) + +/* Cacheability bits when we are using PAT */ +#define PG_WB (0) /* The default */ +#define PG_WC (PG_WT) /* WT and CD is WC */ +#define PG_UCMINUS (PG_N) /* UC but mtrr can override */ +#define PG_UC (PG_WT | PG_N) /* hard UC */ + +/* + * short forms of protection codes + */ + +#define PG_KR 0x0000000000000000UL /* kernel read-only */ +#define PG_KW 0x0000000000000002UL /* kernel read-write */ + +/* + * page protection exception bits + */ + +#define PGEX_P 0x01 /* protection violation (vs. no mapping) */ +#define PGEX_W 0x02 /* exception during a write cycle */ +#define PGEX_U 0x04 /* exception while in user mode (upl) */ +#define PGEX_I 0x10 /* instruction fetch blocked by NX */ +#define PGEX_PK 0x20 /* protection-key violation */ + +#ifdef _KERNEL +extern pt_entry_t pg_xo; /* XO pte bits using PKU key1 */ +extern pt_entry_t pg_nx; /* NX pte bit */ +extern pt_entry_t pg_crypt; /* C pte bit */ +extern pt_entry_t pg_g_kern; /* PG_G if glbl mappings can be used in kern */ +#endif /* _KERNEL */ + +#endif /* _MACHINE_PTE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/ptrace.h b/lib/libc/include/x86_64-openbsd-none/amd64/ptrace.h new file mode 100644 index 000000000000..7a0450c88f69 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/ptrace.h @@ -0,0 +1,56 @@ +/* $OpenBSD: ptrace.h,v 1.2 2024/11/27 05:25:57 anton Exp $ */ +/* $NetBSD: ptrace.h,v 1.1 2003/04/26 18:39:47 fvdl Exp $ */ + +/* + * Copyright (c) 1993 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * i386-dependent ptrace definitions + */ +#define PT_STEP (PT_FIRSTMACH + 0) +#define PT_GETREGS (PT_FIRSTMACH + 1) +#define PT_SETREGS (PT_FIRSTMACH + 2) +#define PT_GETFPREGS (PT_FIRSTMACH + 3) +#define PT_SETFPREGS (PT_FIRSTMACH + 4) + +#define PT_GETXSTATE_INFO (PT_FIRSTMACH + 5) +#define PT_GETXSTATE (PT_FIRSTMACH + 6) +#define PT_SETXSTATE (PT_FIRSTMACH + 7) + +struct ptrace_xstate_info { + uint64_t xsave_mask; + uint32_t xsave_len; +}; + +#ifdef _KERNEL +int process_read_xstate_info(struct proc *, void *); +int process_read_xstate(struct proc *, void *); +int process_write_xstate(struct proc *, void *); +#endif \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/rbus_machdep.h b/lib/libc/include/x86_64-openbsd-none/amd64/rbus_machdep.h new file mode 100644 index 000000000000..6c293739bc80 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/rbus_machdep.h @@ -0,0 +1,48 @@ +/* $OpenBSD: rbus_machdep.h,v 1.8 2024/05/22 05:51:49 jsg Exp $ */ +/* $NetBSD: rbus_machdep.h,v 1.2 1999/10/15 06:43:05 haya Exp $ */ + +/* + * Copyright (c) 1999 + * HAYAKAWA Koichi. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_RBUS_MACHDEP_H_ +#define _MACHINE_RBUS_MACHDEP_H_ + +struct pci_attach_args; /* XXX */ + +#define md_space_map(rbt, physaddr, size, flags, bshp) \ + _bus_space_map((rbt)->rb_bt, (physaddr), (size), (flags), (bshp)) + +#define md_space_unmap(rbt, bsh, size, adrp) \ + _bus_space_unmap((rbt)->rb_bt, (bsh), (size), (adrp)) + +rbus_tag_t rbus_pccbb_parent_io(struct device *, + struct pci_attach_args *); +rbus_tag_t rbus_pccbb_parent_mem(struct device *, + struct pci_attach_args *); + +void pccbb_attach_hook(struct device *, struct device *, + struct pci_attach_args *); + +#endif /* _MACHINE_RBUS_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/reg.h b/lib/libc/include/x86_64-openbsd-none/amd64/reg.h new file mode 100644 index 000000000000..de1804e1945d --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/reg.h @@ -0,0 +1,125 @@ +/* $OpenBSD: reg.h,v 1.7 2019/07/14 05:08:26 guenther Exp $ */ +/* $NetBSD: reg.h,v 1.1 2003/04/26 18:39:47 fvdl Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)reg.h 5.5 (Berkeley) 1/18/91 + */ + +#ifndef _MACHINE_REG_H_ +#define _MACHINE_REG_H_ + +#include + +/* + * XXX + * The #defines aren't used in the kernel, but some user-level code still + * expects them. + */ + +/* When referenced during a trap/exception, registers are at these offsets */ + +#define tRDI 0 +#define tRSI 1 +#define tRDX 2 +#define tRCX 3 +#define tR8 4 +#define tR9 5 +#define tR10 6 +#define tR11 7 +#define tR12 8 +#define tR13 9 +#define tR14 10 +#define tR15 11 +#define tRBP 12 +#define tRBX 13 +#define tRAX 14 +#define tRSP 15 +#define tRIP 16 +#define tRFLAGS 17 +#define tCS 18 +#define tSS 19 +#define tDS 20 +#define tES 21 +#define tFS 22 +#define tGS 23 + +/* + * Registers accessible to ptrace(2) syscall for debugger use. + */ +struct reg { + int64_t r_rdi; + int64_t r_rsi; + int64_t r_rdx; + int64_t r_rcx; + int64_t r_r8; + int64_t r_r9; + int64_t r_r10; + int64_t r_r11; + int64_t r_r12; + int64_t r_r13; + int64_t r_r14; + int64_t r_r15; + int64_t r_rbp; + int64_t r_rbx; + int64_t r_rax; + int64_t r_rsp; + int64_t r_rip; + int64_t r_rflags; + int64_t r_cs; + int64_t r_ss; + int64_t r_ds; + int64_t r_es; + int64_t r_fs; + int64_t r_gs; +}; + +struct fpreg { + struct fxsave64 fxstate; +}; + +#define fp_fcw fxstate.fx_fcw +#define fp_fsw fxstate.fx_fsw +#define fp_ftw fxstate.fx_ftw +#define fp_fop fxstate.fx_fop +#define fp_rip fxstate.fx_rip +#define fp_rdp fxstate.fx_rdp +#define fp_mxcsr fxstate.fx_mxcsr +#define fp_mxcsr_mask fxstate.fx_mxcsr_mask +#define fp_st fxstate.fx_st +#define fp_xmm fxstate.fx_xmm + +#ifdef _KERNEL +int check_context(const struct reg *, struct trapframe *); +#endif + +#endif /* !_MACHINE_REG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/reloc.h b/lib/libc/include/x86_64-openbsd-none/amd64/reloc.h new file mode 100644 index 000000000000..b83e6d05711c --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/reloc.h @@ -0,0 +1,69 @@ +/* $OpenBSD: reloc.h,v 1.4 2018/10/20 11:56:31 kettenis Exp $ */ + +/* + * Copyright (c) 2002,2003 Dale Rahn + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _MACHINE_RELOC_H_ +#define _MACHINE_RELOC_H_ + +#define R_TYPE(X) __CONCAT(R_X86_64_,X) + +#define R_X86_64_NONE 0 +#define R_X86_64_64 1 +#define R_X86_64_PC32 2 +#define R_X86_64_GOT32 3 +#define R_X86_64_PLT32 4 +#define R_X86_64_COPY 5 +#define R_X86_64_GLOB_DAT 6 +#define R_X86_64_JUMP_SLOT 7 +#define R_X86_64_RELATIVE 8 +#define R_X86_64_GOTPCREL 9 +#define R_X86_64_32 10 +#define R_X86_64_32S 11 +#define R_X86_64_16 12 +#define R_X86_64_PC16 13 +#define R_X86_64_8 14 +#define R_X86_64_PC8 15 +#define R_X86_64_DTPMOD64 16 +#define R_X86_64_DTPOFF64 17 +#define R_X86_64_TPOFF64 18 +#define R_X86_64_TLSGD 19 +#define R_X86_64_TLSLD 20 +#define R_X86_64_DTPOFF32 21 +#define R_X86_64_GOTTPOFF 22 +#define R_X86_64_TPOFF32 23 + +#define R_386_NONE 0 +#define R_386_32 1 +#define R_386_PC32 2 +#define R_386_GOT32 3 +#define R_386_PLT32 4 +#define R_386_COPY 5 +#define R_386_GLOB_DAT 6 +#define R_386_JMP_SLOT 7 +#define R_386_RELATIVE 8 +#define R_386_GOTOFF 9 +#define R_386_GOTPC 10 + +#endif /* _MACHINE_RELOC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/segments.h b/lib/libc/include/x86_64-openbsd-none/amd64/segments.h new file mode 100644 index 000000000000..8bf2140313d4 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/segments.h @@ -0,0 +1,279 @@ +/* $OpenBSD: segments.h,v 1.18 2025/06/27 17:23:49 bluhm Exp $ */ +/* $NetBSD: segments.h,v 1.1 2003/04/26 18:39:47 fvdl Exp $ */ + +/*- + * Copyright (c) 1995, 1997 + * Charles M. Hannum. All rights reserved. + * Copyright (c) 1989, 1990 William F. Jolitz + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)segments.h 7.1 (Berkeley) 5/9/91 + */ + +/* + * Adapted for NetBSD/amd64 by fvdl@wasabisystems.com. + */ + +/* + * 386 Segmentation Data Structures and definitions + * William F. Jolitz (william@ernie.berkeley.edu) 6/20/1989 + */ + +#ifndef _MACHINE_SEGMENTS_H_ +#define _MACHINE_SEGMENTS_H_ + +/* + * Selectors + */ + +#define ISPL(s) ((s) & SEL_RPL) /* what is the priority level of a selector */ +#define SEL_KPL 0 /* kernel privilege level */ +#define SEL_UPL 3 /* user privilege level */ +#define SEL_RPL 3 /* requester's privilege level mask */ +#define ISLDT(s) ((s) & SEL_LDT) /* is it local or global */ +#define SEL_LDT 4 /* local descriptor table */ + +#define SYSSEL_START (NGDT_MEM << 3) +#define GDT_SIZE (SYSSEL_START + (NGDT_SYS << 4)) + +/* + * These define the index not from the start of the GDT, but from + * the part of the GDT that they're allocated from. + * First NGDT_MEM entries are 8-byte descriptors for CS and DS. + * Next NGDT_SYS entries are 16-byte descriptors defining TSSs. + */ + +#define IDXSEL(s) (((s) >> 3) & 0x1fff) +#define IDXDYNSEL(s) ((((s) & ~SEL_RPL) - DYNSEL_START) >> 4) + +#define GSEL(s,r) (((s) << 3) | r) +#define GSYSSEL(s,r) ((((s) << 4) + SYSSEL_START) | r) +#define GDYNSEL(s,r) ((((s) << 4) + DYNSEL_START) | r | SEL_KPL) + +#define LSEL(s,r) ((s) | r | SEL_LDT) + +#define USERMODE(c, f) (ISPL(c) == SEL_UPL) +#define KERNELMODE(c, f) (ISPL(c) == SEL_KPL) + +#ifndef _LOCORE + +/* + * Memory and System segment descriptors + */ + +/* + * Below is used for TSS and LDT. + */ +struct sys_segment_descriptor { + u_int64_t sd_lolimit:16; /* segment extent (lsb) */ + u_int64_t sd_lobase:24; /* segment base address (lsb) */ + u_int64_t sd_type:5; /* segment type */ + u_int64_t sd_dpl:2; /* segment descriptor priority level */ + u_int64_t sd_p:1; /* segment descriptor present */ + u_int64_t sd_hilimit:4; /* segment extent (msb) */ + u_int64_t sd_xx1:3; /* avl, long and def32 (not used) */ + u_int64_t sd_gran:1; /* limit granularity (byte/page) */ + u_int64_t sd_hibase:40; /* segment base address (msb) */ + u_int64_t sd_xx2:8; /* reserved */ + u_int64_t sd_zero:5; /* must be zero */ + u_int64_t sd_xx3:19; /* reserved */ +} __packed; + +/* + * Below is used for cs, ds, etc. + */ +struct mem_segment_descriptor { + unsigned int sd_lolimit:16; /* segment extent (lsb) */ + unsigned int sd_lobase:24; /* segment base address (lsb) */ + unsigned int sd_type:5; /* segment type */ + unsigned int sd_dpl:2; /* segment descriptor priority level */ + unsigned int sd_p:1; /* segment descriptor present */ + unsigned int sd_hilimit:4; /* segment extent (msb) */ + unsigned int sd_avl:1; /* available */ + unsigned int sd_long:1; /* long mode */ + unsigned int sd_def32:1; /* default 32 vs 16 bit size */ + unsigned int sd_gran:1; /* limit granularity (byte/page) */ + unsigned int sd_hibase:8; /* segment base address (msb) */ +} __packed; + +/* + * Gate descriptors (e.g. indirect descriptors) + */ +struct gate_descriptor { + u_int64_t gd_looffset:16; /* gate offset (lsb) */ + u_int64_t gd_selector:16; /* gate segment selector */ + u_int64_t gd_ist:3; /* IST select */ + u_int64_t gd_xx1:5; /* reserved */ + u_int64_t gd_type:5; /* segment type */ + u_int64_t gd_dpl:2; /* segment descriptor priority level */ + u_int64_t gd_p:1; /* segment descriptor present */ + u_int64_t gd_hioffset:48; /* gate offset (msb) */ + u_int64_t gd_xx2:8; /* reserved */ + u_int64_t gd_zero:5; /* must be zero */ + u_int64_t gd_xx3:19; /* reserved */ +} __packed; + +/* + * region descriptors, used to load gdt/idt tables before segments yet exist. + */ +struct region_descriptor { + u_int16_t rd_limit; /* segment extent */ + u_int64_t rd_base; /* base address */ +} __packed; + +#ifdef _KERNEL +extern struct gate_descriptor *idt; +extern struct gate_descriptor early_idt[]; + +void setgate(struct gate_descriptor *, void *, int, int, int, int); +void unsetgate(struct gate_descriptor *); +void setregion(struct region_descriptor *, void *, u_int16_t); +void set_sys_segment(struct sys_segment_descriptor *, void *, size_t, + int, int, int); +void set_mem_segment(struct mem_segment_descriptor *, void *, size_t, + int, int, int, int, int); +int idt_vec_alloc(int, int); +int idt_vec_alloc_range(int, int, int); +void idt_vec_set(int, void (*)(void)); +void idt_vec_free(int); +void cpu_init_idt(void); + +#endif /* _KERNEL */ + +#endif /* !_LOCORE */ + +/* system segments and gate types */ +#define SDT_SYSNULL 0 /* system null */ +#define SDT_SYS286TSS 1 /* system 286 TSS available */ +#define SDT_SYSLDT 2 /* system local descriptor table */ +#define SDT_SYS286BSY 3 /* system 286 TSS busy */ +#define SDT_SYS286CGT 4 /* system 286 call gate */ +#define SDT_SYSTASKGT 5 /* system task gate */ +#define SDT_SYS286IGT 6 /* system 286 interrupt gate */ +#define SDT_SYS286TGT 7 /* system 286 trap gate */ +#define SDT_SYSNULL2 8 /* system null again */ +#define SDT_SYS386TSS 9 /* system 386 TSS available */ +#define SDT_SYSNULL3 10 /* system null again */ +#define SDT_SYS386BSY 11 /* system 386 TSS busy */ +#define SDT_SYS386CGT 12 /* system 386 call gate */ +#define SDT_SYSNULL4 13 /* system null again */ +#define SDT_SYS386IGT 14 /* system 386 interrupt gate */ +#define SDT_SYS386TGT 15 /* system 386 trap gate */ + +/* memory segment types */ +#define SDT_MEMRO 16 /* memory read only */ +#define SDT_MEMROA 17 /* memory read only accessed */ +#define SDT_MEMRW 18 /* memory read write */ +#define SDT_MEMRWA 19 /* memory read write accessed */ +#define SDT_MEMROD 20 /* memory read only expand dwn limit */ +#define SDT_MEMRODA 21 /* memory read only expand dwn limit accessed */ +#define SDT_MEMRWD 22 /* memory read write expand dwn limit */ +#define SDT_MEMRWDA 23 /* memory read write expand dwn limit acessed */ +#define SDT_MEME 24 /* memory execute only */ +#define SDT_MEMEA 25 /* memory execute only accessed */ +#define SDT_MEMER 26 /* memory execute read */ +#define SDT_MEMERA 27 /* memory execute read accessed */ +#define SDT_MEMEC 28 /* memory execute only conforming */ +#define SDT_MEMEAC 29 /* memory execute only accessed conforming */ +#define SDT_MEMERC 30 /* memory execute read conforming */ +#define SDT_MEMERAC 31 /* memory execute read accessed conforming */ + +/* is memory segment descriptor pointer ? */ +#define ISMEMSDP(s) ((s->d_type) >= SDT_MEMRO && \ + (s->d_type) <= SDT_MEMERAC) + +/* is 286 gate descriptor pointer ? */ +#define IS286GDP(s) ((s->d_type) >= SDT_SYS286CGT && \ + (s->d_type) < SDT_SYS286TGT) + +/* is 386 gate descriptor pointer ? */ +#define IS386GDP(s) ((s->d_type) >= SDT_SYS386CGT && \ + (s->d_type) < SDT_SYS386TGT) + +/* is gate descriptor pointer ? */ +#define ISGDP(s) (IS286GDP(s) || IS386GDP(s)) + +/* is segment descriptor pointer ? */ +#define ISSDP(s) (ISMEMSDP(s) || !ISGDP(s)) + +/* is system segment descriptor pointer ? */ +#define ISSYSSDP(s) (!ISMEMSDP(s) && !ISGDP(s)) + +/* + * Segment Protection Exception code bits + */ +#define SEGEX_EXT 0x01 /* recursive or externally induced */ +#define SEGEX_IDT 0x02 /* interrupt descriptor table */ +#define SEGEX_TI 0x04 /* local descriptor table */ + +/* + * Entries in the Interrupt Descriptor Table (IDT) + */ +#define NIDT 256 +#define NRSVIDT 32 /* reserved entries for cpu exceptions */ + +/* + * Entries in the Global Descriptor Table (GDT) + * The code and data descriptors must come first. There + * are NGDT_MEM of them. + * + * Then comes the predefined TSS descriptor. + * There are NGDT_SYS of them. + * + * The particular order of the UDATA and UCODE descriptors is + * required by the sysretq instruction. + */ +#define GNULL_SEL 0 /* Null descriptor */ +#define GCODE_SEL 1 /* Kernel code descriptor */ +#define GDATA_SEL 2 /* Kernel data descriptor */ +#define GUDATA_SEL 3 /* User data descriptor */ +#define GUCODE_SEL 4 /* User code descriptor */ +#define NGDT_MEM 5 + +#define GPROC0_SEL 0 /* common TSS */ +#define NGDT_SYS 1 + +#define GDT_SYS_OFFSET (NGDT_MEM << 3) + +#define GDT_ADDR_MEM(s,i) \ + ((struct mem_segment_descriptor *)((char *)(s) + ((i) << 3))) +#define GDT_ADDR_SYS(s,i) \ + ((struct sys_segment_descriptor *)((char *)(s) + ((i) << 4) + SYSSEL_START)) + +/* + * Checks for valid user selectors. + */ +#define VALID_USER_CSEL(s) \ + ((s) == GSEL(GUCODE_SEL, SEL_UPL)) +#define VALID_USER_DSEL(s) \ + ((s) == GSEL(GUDATA_SEL, SEL_UPL)) + +#endif /* _MACHINE_SEGMENTS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/setjmp.h b/lib/libc/include/x86_64-openbsd-none/amd64/setjmp.h new file mode 100644 index 000000000000..88f0465d1526 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/setjmp.h @@ -0,0 +1,22 @@ +/* $OpenBSD: setjmp.h,v 1.2 2020/10/21 19:00:14 kettenis Exp $ */ +/* $NetBSD: setjmp.h,v 1.1 2003/04/26 18:39:47 fvdl Exp $ */ + +/* + * machine/setjmp.h: machine dependent setjmp-related information. + * These are only the callee-saved registers, code calling setjmp + * will expect the rest to be clobbered anyway. + */ + +#define _JB_RBX 0 +#define _JB_RBP 1 +#define _JB_R12 2 +#define _JB_R13 3 +#define _JB_R14 4 +#define _JB_R15 5 +#define _JB_RSP 6 +#define _JB_PC 7 +#define _JB_SIGFLAG 8 +#define _JB_SIGMASK 9 +#define _JB_MXCSR 10 + +#define _JBLEN 11 /* size, in longs, of a jmp_buf */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/signal.h b/lib/libc/include/x86_64-openbsd-none/amd64/signal.h new file mode 100644 index 000000000000..5b19f70f3b4a --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/signal.h @@ -0,0 +1,89 @@ +/* $OpenBSD: signal.h,v 1.9 2016/05/10 18:39:42 deraadt Exp $ */ +/* $NetBSD: signal.h,v 1.2 2003/04/28 23:16:17 bjh21 Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)signal.h 7.16 (Berkeley) 3/17/91 + */ + +#ifndef _MACHINE_SIGNAL_H_ +#define _MACHINE_SIGNAL_H_ + +#include + +typedef int sig_atomic_t; + +#ifdef _KERNEL +#include +#endif + +#if __BSD_VISIBLE || __XPG_VISIBLE >= 420 +/* + * Information pushed on stack when a signal is delivered. + * This is used by the kernel to restore state following + * execution of the signal handler. It is also made available + * to the handler to allow it to restore state properly if + * a non-standard exit is performed. + */ +struct sigcontext { + /* plain match trapframe */ + long sc_rdi; + long sc_rsi; + long sc_rdx; + long sc_rcx; + long sc_r8; + long sc_r9; + long sc_r10; + long sc_r11; + long sc_r12; + long sc_r13; + long sc_r14; + long sc_r15; + long sc_rbp; + long sc_rbx; + long sc_rax; + long sc_gs; + long sc_fs; + long sc_es; + long sc_ds; + long sc_trapno; + long sc_err; + long sc_rip; + long sc_cs; + long sc_rflags; + long sc_rsp; + long sc_ss; + + struct fxsave64 *sc_fpstate; + int __sc_unused; + int sc_mask; + long sc_cookie; +}; +#endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ +#endif /* !_MACHINE_SIGNAL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/smbiosvar.h b/lib/libc/include/x86_64-openbsd-none/amd64/smbiosvar.h new file mode 100644 index 000000000000..34349b6ec955 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/smbiosvar.h @@ -0,0 +1,281 @@ +/* $OpenBSD: smbiosvar.h,v 1.14 2025/07/15 01:09:32 jsg Exp $ */ +/* + * Copyright (c) 2006 Gordon Willem Klok + * Copyright (c) 2005 Jordan Hargrave + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_SMBIOSVAR_ +#define _MACHINE_SMBIOSVAR_ + +#define SMBIOS_START 0xf0000 +#define SMBIOS_END 0xfffff + +#define SMBIOS_UUID_NPRESENT 0x1 +#define SMBIOS_UUID_NSET 0x2 + +/* + * Section 3.5 of "UUIDs and GUIDs" found at + * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt + * specifies the string representation of a UUID. + */ +#define SMBIOS_UUID_REP "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" +#define SMBIOS_UUID_REPLEN 37 /* 16 zero padded values, 4 hyphens, 1 null */ + +struct smbios_entry { + uint8_t mjr; + uint8_t min; + uint8_t *addr; + uint16_t len; + uint16_t count; +}; + +struct smbhdr { + uint32_t sig; /* "_SM_" */ + uint8_t checksum; /* Entry point checksum */ + uint8_t len; /* Entry point structure length */ + uint8_t majrev; /* Specification major revision */ + uint8_t minrev; /* Specification minor revision */ + uint16_t mss; /* Maximum Structure Size */ + uint8_t epr; /* Entry Point Revision */ + uint8_t fa[5]; /* value determined by EPR */ + uint8_t sasig[5]; /* Secondary Anchor "_DMI_" */ + uint8_t sachecksum; /* Secondary Checksum */ + uint16_t size; /* Length of structure table in bytes */ + uint32_t addr; /* Structure table address */ + uint16_t count; /* Number of SMBIOS structures */ + uint8_t rev; /* BCD revision */ +} __packed; + +struct smb3hdr { + uint8_t sig[5]; /* "_SM3_" */ + uint8_t checksum; /* Entry point structure checksum */ + uint8_t len; /* Entry point length */ + uint8_t majrev; /* SMBIOS major version */ + uint8_t minrev; /* SMBIOS minor version */ + uint8_t docrev; /* SMBIOS docrev */ + uint8_t epr; /* Entry point revision */ + uint8_t reserved; /* Reserved */ + uint32_t size; /* Structure table maximum size */ + uint64_t addr; /* Structure table address */ +} __packed; + +struct smbtblhdr { + uint8_t type; + uint8_t size; + uint16_t handle; +} __packed; + +struct smbtable { + struct smbtblhdr *hdr; + void *tblhdr; + uint32_t cookie; +}; + +#define SMBIOS_TYPE_BIOS 0 +#define SMBIOS_TYPE_SYSTEM 1 +#define SMBIOS_TYPE_BASEBOARD 2 +#define SMBIOS_TYPE_ENCLOSURE 3 +#define SMBIOS_TYPE_PROCESSOR 4 +#define SMBIOS_TYPE_MEMCTRL 5 +#define SMBIOS_TYPE_MEMMOD 6 +#define SMBIOS_TYPE_CACHE 7 +#define SMBIOS_TYPE_PORT 8 +#define SMBIOS_TYPE_SLOTS 9 +#define SMBIOS_TYPE_OBD 10 +#define SMBIOS_TYPE_OEM 11 +#define SMBIOS_TYPE_SYSCONFOPT 12 +#define SMBIOS_TYPE_BIOSLANG 13 +#define SMBIOS_TYPE_GROUPASSOC 14 +#define SMBIOS_TYPE_SYSEVENTLOG 15 +#define SMBIOS_TYPE_PHYMEM 16 +#define SMBIOS_TYPE_MEMDEV 17 +#define SMBIOS_TYPE_ECCINFO32 18 +#define SMBIOS_TYPE_MEMMAPARRAYADDR 19 +#define SMBIOS_TYPE_MEMMAPDEVADDR 20 +#define SMBIOS_TYPE_INBUILTPOINT 21 +#define SMBIOS_TYPE_PORTBATT 22 +#define SMBIOS_TYPE_SYSRESET 23 +#define SMBIOS_TYPE_HWSECUIRTY 24 +#define SMBIOS_TYPE_PWRCTRL 25 +#define SMBIOS_TYPE_VOLTPROBE 26 +#define SMBIOS_TYPE_COOLING 27 +#define SMBIOS_TYPE_TEMPPROBE 28 +#define SMBIOS_TYPE_CURRENTPROBE 29 +#define SMBIOS_TYPE_OOB_REMOTEACCESS 30 +#define SMBIOS_TYPE_BIS 31 +#define SMBIOS_TYPE_SBI 32 +#define SMBIOS_TYPE_ECCINFO64 33 +#define SMBIOS_TYPE_MGMTDEV 34 +#define SMBIOS_TYPE_MGTDEVCOMP 35 +#define SMBIOS_TYPE_MGTDEVTHRESH 36 +#define SMBIOS_TYPE_MEMCHANNEL 37 +#define SMBIOS_TYPE_IPMIDEV 38 +#define SMBIOS_TYPE_SPS 39 +#define SMBIOS_TYPE_INACTIVE 126 +#define SMBIOS_TYPE_EOT 127 + +/* + * SMBIOS Structure Type 0 "BIOS Information" + * DMTF Specification DSP0134 Section: 3.3.1 p.g. 34 + */ +struct smbios_struct_bios { + uint8_t vendor; /* string */ + uint8_t version; /* string */ + uint16_t startaddr; + uint8_t release; /* string */ + uint8_t romsize; + uint64_t characteristics; + uint32_t charext; + uint8_t major_rel; + uint8_t minor_rel; + uint8_t ecf_mjr_rel; /* embedded controller firmware */ + uint8_t ecf_min_rel; /* embedded controller firmware */ +} __packed; + +/* + * SMBIOS Structure Type 1 "System Information" + * DMTF Specification DSP0134 Section 3.3.2 p.g. 35 + */ + +struct smbios_sys { +/* SMBIOS spec 2.0+ */ + uint8_t vendor; /* string */ + uint8_t product; /* string */ + uint8_t version; /* string */ + uint8_t serial; /* string */ +/* SMBIOS spec 2.1+ */ + uint8_t uuid[16]; + uint8_t wakeup; +/* SMBIOS spec 2.4+ */ + uint8_t sku; /* string */ + uint8_t family; /* string */ +} __packed; + +/* + * SMBIOS Structure Type 2 "Base Board (Module) Information" + * DMTF Specification DSP0134 Section 3.3.3 p.g. 37 + */ +struct smbios_board { + uint8_t vendor; /* string */ + uint8_t product; /* string */ + uint8_t version; /* string */ + uint8_t serial; /* string */ + uint8_t asset; /* string */ + uint8_t feature; /* feature flags */ + uint8_t location; /* location in chassis */ + uint16_t handle; /* chassis handle */ + uint8_t type; /* board type */ + uint8_t noc; /* number of contained objects */ +} __packed; + +/* + * SMBIOS Structure Type 3 "System Enclosure or Chassis" + * DMTF Specification DSP0134 + */ +struct smbios_enclosure { + /* SMBIOS spec 2.0+ */ + uint8_t vendor; /* string */ + uint8_t type; + uint8_t version; /* string */ + uint8_t serial; /* string */ + uint8_t asset_tag; /* string */ + /* SMBIOS spec 2.1+ */ + uint8_t boot_state; + uint8_t psu_state; + uint8_t thermal_state; + uint8_t security_status; + /* SMBIOS spec 2.3+ */ + uint16_t oem_defined; + uint8_t height; + uint8_t no_power_cords; + uint8_t no_contained_element; + uint8_t reclen_contained_element; + uint8_t contained_elements; + /* SMBIOS spec 2.7+ */ + uint8_t sku; /* string */ +} __packed; + +/* + * SMBIOS Structure Type 4 "processor Information" + * DMTF Specification DSP0134 v2.5 Section 3.3.5 p.g. 24 + */ +struct smbios_cpu { + uint8_t cpu_socket_designation; /* string */ + uint8_t cpu_type; + uint8_t cpu_family; + uint8_t cpu_mfg; /* string */ + uint32_t cpu_id_eax; + uint32_t cpu_id_edx; + uint8_t cpu_version; /* string */ + uint8_t cpu_voltage; + uint16_t cpu_clock; + uint16_t cpu_max_speed; + uint16_t cpu_current_speed; + uint8_t cpu_status; +#define SMBIOS_CPUST_POPULATED (1<<6) +#define SMBIOS_CPUST_STATUSMASK (0x07) + uint8_t cpu_upgrade; + uint16_t cpu_l1_handle; + uint16_t cpu_l2_handle; + uint16_t cpu_l3_handle; + uint8_t cpu_serial; /* string */ + uint8_t cpu_asset_tag; /* string */ + uint8_t cpu_part_nr; /* string */ + /* following fields were added in smbios 2.5 */ + uint8_t cpu_core_count; + uint8_t cpu_core_enabled; + uint8_t cpu_thread_count; + uint16_t cpu_characteristics; +} __packed; + +/* + * SMBIOS Structure Type 38 "IPMI Information" + * DMTF Specification DSP0134 Section 3.3.39 p.g. 91 + */ +struct smbios_ipmi { + uint8_t smipmi_if_type; /* IPMI Interface Type */ + uint8_t smipmi_if_rev; /* BCD IPMI Revision */ + uint8_t smipmi_i2c_address; /* I2C address of BMC */ + uint8_t smipmi_nvram_address; /* I2C address of NVRAM + * storage */ + uint64_t smipmi_base_address; /* Base address of BMC (BAR + * format */ + uint8_t smipmi_base_flags; /* Flags field: + * bit 7:6 : register spacing + * 00 = byte + * 01 = dword + * 02 = word + * bit 4 : Lower bit BAR + * bit 3 : IRQ valid + * bit 2 : N/A + * bit 1 : Interrupt polarity + * bit 0 : Interrupt trigger */ + uint8_t smipmi_irq; /* IRQ if applicable */ +} __packed; + +int smbios_find_table(uint8_t, struct smbtable *); +char *smbios_get_string(struct smbtable *, uint8_t, char *, size_t); + +#endif \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/specialreg.h b/lib/libc/include/x86_64-openbsd-none/amd64/specialreg.h new file mode 100644 index 000000000000..fc0770c81d11 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/specialreg.h @@ -0,0 +1,1645 @@ +/* $OpenBSD: specialreg.h,v 1.120 2025/07/16 07:15:41 jsg Exp $ */ +/* $NetBSD: specialreg.h,v 1.1 2003/04/26 18:39:48 fvdl Exp $ */ +/* $NetBSD: x86/specialreg.h,v 1.2 2003/04/25 21:54:30 fvdl Exp $ */ + +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)specialreg.h 7.1 (Berkeley) 5/9/91 + */ + +/* + * Bits in 386 special registers: + */ +#define CR0_PE 0x00000001 /* Protected mode Enable */ +#define CR0_MP 0x00000002 /* "Math" Present (NPX or NPX emulator) */ +#define CR0_EM 0x00000004 /* EMulate non-NPX coproc. (trap ESC only) */ +#define CR0_TS 0x00000008 /* Task Switched (if MP, trap ESC and WAIT) */ +#define CR0_ET 0x00000010 /* Extension Type (387 (if set) vs 287) */ +#define CR0_PG 0x80000000 /* PaGing enable */ + +/* + * Bits in 486 special registers: + */ +#define CR0_NE 0x00000020 /* Numeric Error enable (EX16 vs IRQ13) */ +#define CR0_WP 0x00010000 /* Write Protect (honor PG_RW in all modes) */ +#define CR0_AM 0x00040000 /* Alignment Mask (set to enable AC flag) */ +#define CR0_NW 0x20000000 /* Not Write-through */ +#define CR0_CD 0x40000000 /* Cache Disable */ + +/* + * bits in CR3 + */ +#define CR3_PCID 0xfffULL +#define CR3_PWT (1ULL << 3) +#define CR3_PCD (1ULL << 4) +#define CR3_REUSE_PCID (1ULL << 63) +#define CR3_PADDR 0x7ffffffffffff000ULL + +/* + * bits in the pentiums %cr4 register: + */ + +#define CR4_VME 0x00000001 /* virtual 8086 mode extension enable */ +#define CR4_PVI 0x00000002 /* protected mode virtual interrupt enable */ +#define CR4_TSD 0x00000004 /* restrict RDTSC instruction to cpl 0 only */ +#define CR4_DE 0x00000008 /* debugging extension */ +#define CR4_PSE 0x00000010 /* large (4MB) page size enable */ +#define CR4_PAE 0x00000020 /* physical address extension enable */ +#define CR4_MCE 0x00000040 /* machine check enable */ +#define CR4_PGE 0x00000080 /* page global enable */ +#define CR4_PCE 0x00000100 /* enable RDPMC instruction for all cpls */ +#define CR4_OSFXSR 0x00000200 /* enable fxsave/fxrestor and SSE */ +#define CR4_OSXMMEXCPT 0x00000400 /* enable unmasked SSE exceptions */ +#define CR4_UMIP 0x00000800 /* user mode instruction prevention */ +#define CR4_VMXE 0x00002000 /* enable virtual machine operation */ +#define CR4_SMXE 0x00004000 /* enable safe mode operation */ +#define CR4_FSGSBASE 0x00010000 /* enable {RD,WR}{FS,GS}BASE ops */ +#define CR4_PCIDE 0x00020000 /* enable process-context IDs */ +#define CR4_OSXSAVE 0x00040000 /* enable XSAVE and extended states */ +#define CR4_KL 0x00080000 /* enable AES Key Locker */ +#define CR4_SMEP 0x00100000 /* supervisor mode exec protection */ +#define CR4_SMAP 0x00200000 /* supervisor mode access prevention */ +#define CR4_PKE 0x00400000 /* user-mode protection keys */ +#define CR4_CET 0x00800000 /* control-flow enforcement tech */ +#define CR4_PKS 0x01000000 /* supervisor-mode protection keys */ +#define CR4_UINTR 0x02000000 /* user interrupts enable bit */ + +/* + * Extended state components, for xsave/xrstor family of instructions. + */ +#define XFEATURE_X87 0x00000001 /* x87 FPU/MMX state */ +#define XFEATURE_SSE 0x00000002 /* SSE state */ +#define XFEATURE_AVX 0x00000004 /* AVX state */ +#define XFEATURE_BNDREG 0x00000008 /* MPX state */ +#define XFEATURE_BNDCSR 0x00000010 /* MPX state */ +#define XFEATURE_MPX (XFEATURE_BNDREG | XFEATURE_BNDCSR) +#define XFEATURE_OPMASK 0x00000020 /* AVX-512 opmask */ +#define XFEATURE_ZMM_HI256 0x00000040 /* AVX-512 ZMM0-7 */ +#define XFEATURE_HI16_ZMM 0x00000080 /* AVX-512 ZMM16-31 */ +#define XFEATURE_AVX512 (XFEATURE_OPMASK | XFEATURE_ZMM_HI256 | \ + XFEATURE_HI16_ZMM) +#define XFEATURE_PT 0x00000100 /* processor trace */ +#define XFEATURE_PKRU 0x00000200 /* user page key */ +#define XFEATURE_PASID 0x00000400 /* Process ASIDs */ +#define XFEATURE_CET_U 0x00000800 /* ctrl-flow enforce user */ +#define XFEATURE_CET_S 0x00001000 /* ctrl-flow enforce system */ +#define XFEATURE_CET (XFEATURE_CET_U | XFEATURE_CET_S) +#define XFEATURE_HDC 0x00002000 /* HW duty cycling */ +#define XFEATURE_UINTR 0x00004000 /* user interrupts */ +#define XFEATURE_LBR 0x00008000 /* last-branch record */ +#define XFEATURE_HWP 0x00010000 /* HW P-states */ +#define XFEATURE_TILECFG 0x00020000 /* AMX state */ +#define XFEATURE_TILEDATA 0x00040000 /* AMX state */ +#define XFEATURE_AMX (XFEATURE_TILECFG | XFEATURE_TILEDATA) + +/* valid only in xcomp_bv field: */ +#define XFEATURE_COMPRESSED (1ULL << 63) /* compressed format */ + +/* which bits are for XCR0 and which for the XSS MSR? */ +#define XFEATURE_XCR0_MASK \ + (XFEATURE_X87 | XFEATURE_SSE | XFEATURE_AVX | XFEATURE_MPX | \ + XFEATURE_AVX512 | XFEATURE_PKRU | XFEATURE_AMX) +#define XFEATURE_XSS_MASK \ + (XFEATURE_PT | XFEATURE_PASID | XFEATURE_CET | XFEATURE_HDC | \ + XFEATURE_UINTR | XFEATURE_LBR | XFEATURE_HWP) + +/* + * CPUID "features" bits (CPUID function 0x1): + * EDX bits, then ECX bits + */ + +#define CPUID_FPU 0x00000001 /* processor has an FPU? */ +#define CPUID_VME 0x00000002 /* has virtual mode (%cr4's VME/PVI) */ +#define CPUID_DE 0x00000004 /* has debugging extension */ +#define CPUID_PSE 0x00000008 /* has 4MB page size extension */ +#define CPUID_TSC 0x00000010 /* has time stamp counter */ +#define CPUID_MSR 0x00000020 /* has model specific registers */ +#define CPUID_PAE 0x00000040 /* has phys address extension */ +#define CPUID_MCE 0x00000080 /* has machine check exception */ +#define CPUID_CX8 0x00000100 /* has CMPXCHG8B instruction */ +#define CPUID_APIC 0x00000200 /* has enabled APIC */ +#define CPUID_SYS1 0x00000400 /* has SYSCALL/SYSRET inst. (Cyrix) */ +#define CPUID_SEP 0x00000800 /* has SYSCALL/SYSRET inst. (AMD/Intel) */ +#define CPUID_MTRR 0x00001000 /* has memory type range register */ +#define CPUID_PGE 0x00002000 /* has page global extension */ +#define CPUID_MCA 0x00004000 /* has machine check architecture */ +#define CPUID_CMOV 0x00008000 /* has CMOVcc instruction */ +#define CPUID_PAT 0x00010000 /* has page attribute table */ +#define CPUID_PSE36 0x00020000 /* has 36bit page size extension */ +#define CPUID_PSN 0x00040000 /* has processor serial number */ +#define CPUID_CFLUSH 0x00080000 /* CFLUSH insn supported */ +#define CPUID_B20 0x00100000 /* reserved */ +#define CPUID_DS 0x00200000 /* Debug Store */ +#define CPUID_ACPI 0x00400000 /* ACPI performance modulation regs */ +#define CPUID_MMX 0x00800000 /* has MMX instructions */ +#define CPUID_FXSR 0x01000000 /* has FXRSTOR instruction */ +#define CPUID_SSE 0x02000000 /* has streaming SIMD extensions */ +#define CPUID_SSE2 0x04000000 /* has streaming SIMD extensions #2 */ +#define CPUID_SS 0x08000000 /* self-snoop */ +#define CPUID_HTT 0x10000000 /* Hyper-Threading Technology */ +#define CPUID_TM 0x20000000 /* thermal monitor (TCC) */ +#define CPUID_B30 0x40000000 /* reserved */ +#define CPUID_PBE 0x80000000 /* Pending Break Enabled restarts clock */ +#define CPUID_EDX_BITS \ + ("\20" "\01FPU" "\02VME" "\03DE" "\04PSE" "\05TSC" "\06MSR" "\07PAE" \ + "\010MCE" "\011CX8" "\012APIC" "\014SEP" "\015MTRR" "\016PGE" "\017MCA" \ + "\020CMOV" "\021PAT" "\022PSE36" "\023PSN" "\024CFLUSH" "\026DS" \ + "\027ACPI" "\030MMX" "\031FXSR" "\032SSE" "\033SSE2" "\034SS" "\035HTT" \ + "\036TM" "\040PBE" ) + +#define CPUIDECX_SSE3 0x00000001 /* streaming SIMD extensions #3 */ +#define CPUIDECX_PCLMUL 0x00000002 /* Carryless Multiplication */ +#define CPUIDECX_DTES64 0x00000004 /* 64bit debug store */ +#define CPUIDECX_MWAIT 0x00000008 /* Monitor/Mwait */ +#define CPUIDECX_DSCPL 0x00000010 /* CPL Qualified Debug Store */ +#define CPUIDECX_VMX 0x00000020 /* Virtual Machine Extensions */ +#define CPUIDECX_SMX 0x00000040 /* Safer Mode Extensions */ +#define CPUIDECX_EST 0x00000080 /* enhanced SpeedStep */ +#define CPUIDECX_TM2 0x00000100 /* thermal monitor 2 */ +#define CPUIDECX_SSSE3 0x00000200 /* Supplemental Streaming SIMD Ext. 3 */ +#define CPUIDECX_CNXTID 0x00000400 /* Context ID */ +#define CPUIDECX_SDBG 0x00000800 /* Silicon debug capability */ +#define CPUIDECX_FMA3 0x00001000 /* Fused Multiply Add */ +#define CPUIDECX_CX16 0x00002000 /* has CMPXCHG16B instruction */ +#define CPUIDECX_XTPR 0x00004000 /* xTPR Update Control */ +#define CPUIDECX_PDCM 0x00008000 /* Perfmon and Debug Capability */ +#define CPUIDECX_PCID 0x00020000 /* Process-context ID Capability */ +#define CPUIDECX_DCA 0x00040000 /* Direct Cache Access */ +#define CPUIDECX_SSE41 0x00080000 /* Streaming SIMD Extensions 4.1 */ +#define CPUIDECX_SSE42 0x00100000 /* Streaming SIMD Extensions 4.2 */ +#define CPUIDECX_X2APIC 0x00200000 /* Extended xAPIC Support */ +#define CPUIDECX_MOVBE 0x00400000 /* MOVBE Instruction */ +#define CPUIDECX_POPCNT 0x00800000 /* POPCNT Instruction */ +#define CPUIDECX_DEADLINE 0x01000000 /* APIC one-shot via deadline */ +#define CPUIDECX_AES 0x02000000 /* AES Instruction */ +#define CPUIDECX_XSAVE 0x04000000 /* XSAVE/XSTOR States */ +#define CPUIDECX_OSXSAVE 0x08000000 /* OSXSAVE */ +#define CPUIDECX_AVX 0x10000000 /* Advanced Vector Extensions */ +#define CPUIDECX_F16C 0x20000000 /* 16bit fp conversion */ +#define CPUIDECX_RDRAND 0x40000000 /* RDRAND instruction */ +#define CPUIDECX_HV 0x80000000 /* Running on hypervisor */ +#define CPUID_ECX_BITS \ + ("\20" "\01SSE3" "\02PCLMUL" "\03DTES64" "\04MWAIT" "\05DS-CPL" "\06VMX" \ + "\07SMX" "\010EST" "\011TM2" "\012SSSE3" "\013CNXT-ID" "\014SDBG" \ + "\015FMA3" "\016CX16" "\017xTPR" "\020PDCM" "\022PCID" "\023DCA" \ + "\024SSE4.1" "\025SSE4.2" "\026x2APIC" "\027MOVBE" "\030POPCNT" \ + "\031DEADLINE" "\032AES" "\033XSAVE" "\034OSXSAVE" "\035AVX" "\036F16C" \ + "\037RDRAND" "\040HV" ) + +/* + * "Structured Extended Feature Flags Parameters" (CPUID function 0x7, leaf 0) + * EBX bits + */ +#define SEFF0EBX_FSGSBASE 0x00000001 /* {RD,WR}[FG]SBASE instructions */ +#define SEFF0EBX_TSC_ADJUST 0x00000002 /* Has IA32_TSC_ADJUST MSR */ +#define SEFF0EBX_SGX 0x00000004 /* Software Guard Extensions */ +#define SEFF0EBX_BMI1 0x00000008 /* advanced bit manipulation */ +#define SEFF0EBX_HLE 0x00000010 /* Hardware Lock Elision */ +#define SEFF0EBX_AVX2 0x00000020 /* Advanced Vector Extensions 2 */ +#define SEFF0EBX_SMEP 0x00000080 /* Supervisor mode exec protection */ +#define SEFF0EBX_BMI2 0x00000100 /* advanced bit manipulation */ +#define SEFF0EBX_ERMS 0x00000200 /* Enhanced REP MOVSB/STOSB */ +#define SEFF0EBX_INVPCID 0x00000400 /* INVPCID instruction */ +#define SEFF0EBX_RTM 0x00000800 /* Restricted Transactional Memory */ +#define SEFF0EBX_PQM 0x00001000 /* Quality of Service Monitoring */ +#define SEFF0EBX_MPX 0x00004000 /* Memory Protection Extensions */ +#define SEFF0EBX_AVX512F 0x00010000 /* AVX-512 foundation inst */ +#define SEFF0EBX_AVX512DQ 0x00020000 /* AVX-512 double/quadword */ +#define SEFF0EBX_RDSEED 0x00040000 /* RDSEED instruction */ +#define SEFF0EBX_ADX 0x00080000 /* ADCX/ADOX instructions */ +#define SEFF0EBX_SMAP 0x00100000 /* Supervisor mode access prevent */ +#define SEFF0EBX_AVX512IFMA 0x00200000 /* AVX-512 integer mult-add */ +#define SEFF0EBX_PCOMMIT 0x00400000 /* Persistent commit inst */ +#define SEFF0EBX_CLFLUSHOPT 0x00800000 /* cache line flush */ +#define SEFF0EBX_CLWB 0x01000000 /* cache line write back */ +#define SEFF0EBX_PT 0x02000000 /* Processor Trace */ +#define SEFF0EBX_AVX512PF 0x04000000 /* AVX-512 prefetch */ +#define SEFF0EBX_AVX512ER 0x08000000 /* AVX-512 exp/reciprocal */ +#define SEFF0EBX_AVX512CD 0x10000000 /* AVX-512 conflict detection */ +#define SEFF0EBX_SHA 0x20000000 /* SHA Extensions */ +#define SEFF0EBX_AVX512BW 0x40000000 /* AVX-512 byte/word inst */ +#define SEFF0EBX_AVX512VL 0x80000000 /* AVX-512 vector len inst */ +#define SEFF0_EBX_BITS \ + ("\20" "\01FSGSBASE" "\02TSC_ADJUST" "\03SGX" "\04BMI1" "\05HLE" \ + "\06AVX2" "\010SMEP" "\011BMI2" "\012ERMS" "\013INVPCID" "\014RTM" \ + "\015PQM" "\017MPX" "\021AVX512F" "\022AVX512DQ" "\023RDSEED" "\024ADX" \ + "\025SMAP" "\026AVX512IFMA" "\027PCOMMIT" "\030CLFLUSHOPT" "\031CLWB" \ + "\032PT" "\033AVX512PF" "\034AVX512ER" "\035AVX512CD" "\036SHA" \ + "\037AVX512BW" "\040AVX512VL" ) + +/* SEFF ECX bits */ +#define SEFF0ECX_PREFETCHWT1 0x00000001 /* PREFETCHWT1 instruction */ +#define SEFF0ECX_AVX512VBMI 0x00000002 /* AVX-512 vector bit inst */ +#define SEFF0ECX_UMIP 0x00000004 /* UMIP support */ +#define SEFF0ECX_PKU 0x00000008 /* Page prot keys for user mode */ +#define SEFF0ECX_OSPKE 0x00000010 /* OS enabled RD/WRPKRU */ +#define SEFF0ECX_WAITPKG 0x00000020 /* UMONITOR/UMWAIT/TPAUSE insns */ +#define SEFF0ECX_PKS 0x80000000 /* Page prot keys for sup mode */ +#define SEFF0_ECX_BITS \ + ("\20" "\01PREFETCHWT1" "\02AVX512VBMI" "\03UMIP" "\04PKU" "\06WAITPKG" \ + "\040PKS" ) + +/* SEFF EDX bits */ +#define SEFF0EDX_AVX512_4FNNIW 0x00000004 /* AVX-512 neural network insns */ +#define SEFF0EDX_AVX512_4FMAPS 0x00000008 /* AVX-512 mult accum single prec */ +#define SEFF0EDX_SRBDS_CTRL 0x00000200 /* MCU_OPT_CTRL MSR */ +#define SEFF0EDX_MD_CLEAR 0x00000400 /* Microarch Data Clear */ +#define SEFF0EDX_TSXFA 0x00002000 /* TSX Forced Abort */ +#define SEFF0EDX_IBT 0x00100000 /* Indirect Branch Tracking */ +#define SEFF0EDX_IBRS 0x04000000 /* IBRS / IBPB Speculation Control */ +#define SEFF0EDX_STIBP 0x08000000 /* STIBP Speculation Control */ +#define SEFF0EDX_L1DF 0x10000000 /* L1D_FLUSH */ +#define SEFF0EDX_ARCH_CAP 0x20000000 /* Has IA32_ARCH_CAPABILITIES MSR */ +#define SEFF0EDX_SSBD 0x80000000 /* Spec Store Bypass Disable */ +#define SEFF0_EDX_BITS \ + ("\20" "\03AVX512FNNIW" "\04AVX512FMAPS" "\012SRBDS_CTRL" "\013MD_CLEAR" \ + "\016TSXFA" "\025IBT" "\033IBRS,IBPB" "\034STIBP" "\035L1DF" "\040SSBD" ) + +/* + * Thermal and Power Management (CPUID function 0x6) EAX bits + */ +#define TPM_SENSOR 0x00000001 /* Digital temp sensor */ +#define TPM_ARAT 0x00000004 /* APIC Timer Always Running */ +#define TPM_PTS 0x00000040 /* Intel Package Thermal Status */ +#define TPM_EAX_BITS \ + ("\20" "\01SENSOR" "\03ARAT" "\07PTS") +/* Thermal and Power Management (CPUID function 0x6) ECX bits */ +#define TPM_EFFFREQ 0x00000001 /* APERF & MPERF MSR present */ +#define TPM_ECX_BITS \ + ("\20" "\01EFFFREQ" ) + + /* + * "Architectural Performance Monitoring" bits (CPUID function 0x0a): + * EAX bits, EBX bits, EDX bits. + */ + +#define CPUIDEAX_VERID 0x000000ff /* Version ID */ +#define CPUIDEAX_NUM_GC(cpuid) (((cpuid) >> 8) & 0x000000ff) +#define CPUIDEAX_BIT_GC(cpuid) (((cpuid) >> 16) & 0x000000ff) +#define CPUIDEAX_LEN_EBX(cpuid) (((cpuid) >> 24) & 0x000000ff) + +#define CPUIDEBX_EVT_CORE (1 << 0) /* Core cycle */ +#define CPUIDEBX_EVT_INST (1 << 1) /* Instruction retired */ +#define CPUIDEBX_EVT_REFR (1 << 2) /* Reference cycles */ +#define CPUIDEBX_EVT_CACHE_REF (1 << 3) /* Last-level cache ref. */ +#define CPUIDEBX_EVT_CACHE_MIS (1 << 4) /* Last-level cache miss. */ +#define CPUIDEBX_EVT_BRANCH_INST (1 << 5) /* Branch instruction ret. */ +#define CPUIDEBX_EVT_BRANCH_MISP (1 << 6) /* Branch mispredict ret. */ + +#define CPUIDEDX_NUM_FC(cpuid) (((cpuid) >> 0) & 0x0000001f) +#define CPUIDEDX_BIT_FC(cpuid) (((cpuid) >> 5) & 0x000000ff) + +/* + * CPUID "extended features" bits (CPUID function 0x80000001): + * EDX bits, then ECX bits + */ + +#define CPUID_MPC 0x00080000 /* Multiprocessing Capable */ +#define CPUID_NXE 0x00100000 /* No-Execute Extension */ +#define CPUID_MMXX 0x00400000 /* AMD MMX Extensions */ +#define CPUID_FFXSR 0x02000000 /* fast FP/MMX save/restore */ +#define CPUID_PAGE1GB 0x04000000 /* 1-GByte pages */ +#define CPUID_RDTSCP 0x08000000 /* RDTSCP / IA32_TSC_AUX available */ +#define CPUID_LONG 0x20000000 /* long mode */ +#define CPUID_3DNOW2 0x40000000 /* 3DNow! Instruction Extension */ +#define CPUID_3DNOW 0x80000000 /* 3DNow! Instructions */ +#define CPUIDE_EDX_BITS \ + ("\20" "\024MPC" "\025NXE" "\027MMXX" "\032FFXSR" "\033PAGE1GB" \ + "\034RDTSCP" "\036LONG" "\0373DNOW2" "\0403DNOW" ) + +#define CPUIDECX_LAHF 0x00000001 /* LAHF and SAHF instructions */ +#define CPUIDECX_CMPLEG 0x00000002 /* Core MP legacy mode */ +#define CPUIDECX_SVM 0x00000004 /* Secure Virtual Machine */ +#define CPUIDECX_EAPICSP 0x00000008 /* Extended APIC space */ +#define CPUIDECX_AMCR8 0x00000010 /* LOCK MOV CR0 means MOV CR8 */ +#define CPUIDECX_ABM 0x00000020 /* LZCNT instruction */ +#define CPUIDECX_SSE4A 0x00000040 /* SSE4-A instruction set */ +#define CPUIDECX_MASSE 0x00000080 /* Misaligned SSE mode */ +#define CPUIDECX_3DNOWP 0x00000100 /* 3DNowPrefetch */ +#define CPUIDECX_OSVW 0x00000200 /* OS visible workaround */ +#define CPUIDECX_IBS 0x00000400 /* Instruction based sampling */ +#define CPUIDECX_XOP 0x00000800 /* Extended operating support */ +#define CPUIDECX_SKINIT 0x00001000 /* SKINIT and STGI are supported */ +#define CPUIDECX_WDT 0x00002000 /* Watchdog timer */ +/* Reserved 0x00004000 */ +#define CPUIDECX_LWP 0x00008000 /* Lightweight profiling support */ +#define CPUIDECX_FMA4 0x00010000 /* 4-operand FMA instructions */ +#define CPUIDECX_TCE 0x00020000 /* Translation Cache Extension */ +/* Reserved 0x00040000 */ +#define CPUIDECX_NODEID 0x00080000 /* Support for MSRC001C */ +/* Reserved 0x00100000 */ +#define CPUIDECX_TBM 0x00200000 /* Trailing bit manipulation instruction */ +#define CPUIDECX_TOPEXT 0x00400000 /* Topology extensions support */ +#define CPUIDECX_CPCTR 0x00800000 /* core performance counter ext */ +#define CPUIDECX_DBKP 0x04000000 /* DataBreakpointExtension */ +#define CPUIDECX_PERFTSC 0x08000000 /* performance time-stamp counter */ +#define CPUIDECX_PCTRL3 0x10000000 /* L3 performance counter ext */ +#define CPUIDECX_MWAITX 0x20000000 /* MWAITX/MONITORX */ +#define CPUIDE_ECX_BITS \ + ("\20" "\01LAHF" "\02CMPLEG" "\03SVM" "\04EAPICSP" "\05AMCR8" "\06ABM" \ + "\07SSE4A" "\010MASSE" "\0113DNOWP" "\012OSVW" "\013IBS" "\014XOP" \ + "\015SKINIT" "\020WDT" "\021FMA4" "\022TCE" "\024NODEID" "\026TBM" \ + "\027TOPEXT" "\030CPCTR" "\033DBKP" "\034PERFTSC" "\035PCTRL3" \ + "\036MWAITX" ) + +/* + * "Advanced Power Management Information" bits (CPUID function 0x80000007): + * EDX bits. + */ +#define CPUIDEDX_HWPSTATE (1 << 7) /* Hardware P State Control */ +#define CPUIDEDX_ITSC (1 << 8) /* Invariant TSC */ +#define CPUID_APMI_EDX_BITS \ + ("\20" "\010HWPSTATE" "\011ITSC" ) + +/* + * AMD CPUID function 0x80000008 EBX bits + */ +#define CPUIDEBX_INVLPGB (1ULL << 3) /* INVLPG w/broadcast */ +#define CPUIDEBX_IBPB (1ULL << 12) /* Speculation Control IBPB */ +#define CPUIDEBX_IBRS (1ULL << 14) /* Speculation Control IBRS */ +#define CPUIDEBX_STIBP (1ULL << 15) /* Speculation Control STIBP */ +#define CPUIDEBX_IBRS_ALWAYSON (1ULL << 16) /* IBRS always on mode */ +#define CPUIDEBX_STIBP_ALWAYSON (1ULL << 17) /* STIBP always on mode */ +#define CPUIDEBX_IBRS_PREF (1ULL << 18) /* IBRS preferred */ +#define CPUIDEBX_IBRS_SAME_MODE (1ULL << 19) /* IBRS not mode-specific */ +#define CPUIDEBX_SSBD (1ULL << 24) /* Speculation Control SSBD */ +#define CPUIDEBX_VIRT_SSBD (1ULL << 25) /* Virt Spec Control SSBD */ +#define CPUIDEBX_SSBD_NOTREQ (1ULL << 26) /* SSBD not required */ +#define CPUID_AMDSPEC_EBX_BITS \ + ("\20" "\04INVLPGB" "\015IBPB" "\017IBRS" "\020STIBP" "\021IBRS_ALL" \ + "\022STIBP_ALL" "\023IBRS_PREF" "\024IBRS_SM" "\031SSBD" "\032VIRTSSBD" \ + "\033SSBDNR" ) + +/* + * AMD CPUID function 0x8000001F EAX bits + */ +#define CPUIDEAX_SME (1ULL << 0) /* SME */ +#define CPUIDEAX_SEV (1ULL << 1) /* SEV */ +#define CPUIDEAX_PFLUSH_MSR (1ULL << 2) /* Page Flush MSR */ +#define CPUIDEAX_SEVES (1ULL << 3) /* SEV-ES */ +#define CPUIDEAX_SEVSNP (1ULL << 4) /* SEV-SNP */ +#define CPUIDEAX_VMPL (1ULL << 5) /* VM Permission Levels */ +#define CPUIDEAX_RMPQUERY (1ULL << 6) /* RMPQUERY */ +#define CPUIDEAX_VMPLSSS (1ULL << 7) /* VMPL Supervisor Shadow Stack */ +#define CPUIDEAX_SECTSC (1ULL << 8) /* Secure TSC */ +#define CPUIDEAX_TSCAUXVIRT (1ULL << 9) /* TSC Aux Virtualization */ +#define CPUIDEAX_HWECACHECOH (1ULL << 10) /* Coherency Across Enc. Domains */ +#define CPUIDEAX_64BITHOST (1ULL << 11) /* SEV guest requires 64bit host */ +#define CPUIDEAX_RESTINJ (1ULL << 12) /* Restricted Injection */ +#define CPUIDEAX_ALTINJ (1ULL << 13) /* Alternate Injection */ +#define CPUIDEAX_DBGSTSW (1ULL << 14) /* Full debug state swap */ +#define CPUIDEAX_IBSDISALLOW (1ULL << 15) /* Disallowing IBS use by host */ +#define CPUIDEAX_VTE (1ULL << 16) /* Virt. Transparent Encryption */ +#define CPUIDEAX_VMGEXITPARAM (1ULL << 17) /* VMGEXIT Parameter */ +#define CPUIDEAX_VTOMMSR (1ULL << 18) /* Virtual TOM MSR */ +#define CPUIDEAX_IBSVIRT (1ULL << 19) /* IBS Virtualization for SEV-ES */ +#define CPUIDEAX_VMSARPROT (1ULL << 24) /* VMSA Register Protection */ +#define CPUIDEAX_SMTPROT (1ULL << 25) /* SMT Protection */ +#define CPUIDEAX_SVSMPAGEMSR (1ULL << 28) /* SVSM Communication Page MSR */ +#define CPUIDEAX_NVSMSR (1ULL << 29) /* NestedVirtSnpMsr */ +#define CPUID_AMDSEV_EAX_BITS \ + ("\20" "\01SME" "\02SEV" "\03PFLUSH_MSR" "\04SEVES" "\05SEVSNP" "\06VMPL" \ + "\07RMPQUERY" "\010VMPLSSS" "\011SECTSC" "\012TSCAUXVIRT" \ + "\013HWECACHECOH" "\014REQ64BITHOST" "\015RESTINJ" "\016ALTINJ" \ + "\017DBGSTSW" "\020IBSDISALLOW" "\021VTE" "\022VMGEXITPARAM" \ + "\023VTOMMSR" "\024IBSVIRT" "\031VMSARPROT" "\032SMTPROT" \ + "\035SVSMPAGEMSR" "\036NVSMSR" ) + +/* Number of encrypted guests */ +#define CPUID_AMDSEV_ECX_BITS ("\20") + +/* Minimum ASID for SEV enabled, SEV-ES disabled guest. */ +#define CPUID_AMDSEV_EDX_BITS ("\20") + +#define CPUID2FAMILY(cpuid) (((cpuid) >> 8) & 15) +#define CPUID2MODEL(cpuid) (((cpuid) >> 4) & 15) +#define CPUID2STEPPING(cpuid) ((cpuid) & 15) + +#define CPUID(code, eax, ebx, ecx, edx) \ + __asm volatile("cpuid" \ + : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \ + : "a" (code)) +#define CPUID_LEAF(code, leaf, eax, ebx, ecx, edx) \ + __asm volatile("cpuid" \ + : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \ + : "a" (code), "c" (leaf)) + + +/* + * Model-specific registers for the i386 family + */ +#define MSR_P5_MC_ADDR 0x000 /* P5 only */ +#define MSR_P5_MC_TYPE 0x001 /* P5 only */ +#define MSR_TSC 0x010 +#define MSR_CESR 0x011 /* P5 only (trap on P6) */ +#define MSR_CTR0 0x012 /* P5 only (trap on P6) */ +#define MSR_CTR1 0x013 /* P5 only (trap on P6) */ +#define MSR_PLATFORM_ID 0x017 /* Platform ID for microcode */ +#define MSR_APICBASE 0x01b +#define APICBASE_BSP 0x100 +#define APICBASE_ENABLE_X2APIC 0x400 +#define APICBASE_GLOBAL_ENABLE 0x800 +#define MSR_EBL_CR_POWERON 0x02a +#define MSR_EBC_FREQUENCY_ID 0x02c /* Pentium 4 only */ +#define MSR_TEST_CTL 0x033 +#define MSR_IA32_FEATURE_CONTROL 0x03a +#define MSR_TSC_ADJUST 0x03b +#define MSR_SPEC_CTRL 0x048 /* Speculation Control IBRS / STIBP */ +#define SPEC_CTRL_IBRS (1ULL << 0) +#define SPEC_CTRL_STIBP (1ULL << 1) +#define SPEC_CTRL_SSBD (1ULL << 2) +#define MSR_PRED_CMD 0x049 /* Speculation Control IBPB */ +#define PRED_CMD_IBPB (1ULL << 0) +#define MSR_BIOS_UPDT_TRIG 0x079 +#define MSR_BBL_CR_D0 0x088 /* PII+ only */ +#define MSR_BBL_CR_D1 0x089 /* PII+ only */ +#define MSR_BBL_CR_D2 0x08a /* PII+ only */ +#define MSR_BIOS_SIGN 0x08b +#define MSR_SMM_MONITOR_CTL 0x09b +#define MSR_SMBASE 0x09e +#define MSR_PERFCTR0 0x0c1 +#define MSR_PERFCTR1 0x0c2 +#define MSR_FSB_FREQ 0x0cd /* Core Duo/Solo only */ +#define MSR_MPERF 0x0e7 +#define MSR_APERF 0x0e8 +#define MSR_MTRRcap 0x0fe +#define MTRRcap_FIXED 0x100 /* bit 8 - fixed MTRRs supported */ +#define MTRRcap_WC 0x400 /* bit 10 - WC type supported */ +#define MTRRcap_SMRR 0x800 /* bit 11 - SMM range reg supported */ +#define MSR_ARCH_CAPABILITIES 0x10a +#define ARCH_CAP_RDCL_NO (1 << 0) /* Meltdown safe */ +#define ARCH_CAP_IBRS_ALL (1 << 1) /* enhanced IBRS */ +#define ARCH_CAP_RSBA (1 << 2) /* RSB Alternate */ +#define ARCH_CAP_SKIP_L1DFL_VMENTRY (1 << 3) +#define ARCH_CAP_SSB_NO (1 << 4) /* Spec St Byp safe */ +#define ARCH_CAP_MDS_NO (1 << 5) /* microarch data-sampling */ +#define ARCH_CAP_IF_PSCHANGE_MC_NO (1 << 6) /* PS MCE safe */ +#define ARCH_CAP_TSX_CTRL (1 << 7) /* has TSX_CTRL MSR */ +#define ARCH_CAP_TAA_NO (1 << 8) /* TSX AA safe */ +#define ARCH_CAP_MCU_CONTROL (1 << 9) /* has MCU_CTRL MSR */ +#define ARCH_CAP_MISC_PACKAGE_CTLS (1 << 10) /* has MISC_PKG_CTLS MSR */ +#define ARCH_CAP_ENERGY_FILTERING_CTL (1 << 11) /* r/w energy fltring bit */ +#define ARCH_CAP_DOITM (1 << 12) /* Data oprnd indpdnt tmng */ +#define ARCH_CAP_SBDR_SSDP_NO (1 << 13) /* SBDR/SSDP safe */ +#define ARCH_CAP_FBSDP_NO (1 << 14) /* FBSDP safe */ +#define ARCH_CAP_PSDP_NO (1 << 15) /* PSDP safe */ +#define ARCH_CAP_FB_CLEAR (1 << 17) /* MD_CLEAR covers FB */ +#define ARCH_CAP_FB_CLEAR_CTRL (1 << 18) +#define ARCH_CAP_RRSBA (1 << 19) /* has RRSBA if not dis */ +#define ARCH_CAP_BHI_NO (1 << 20) /* BHI safe */ +#define ARCH_CAP_XAPIC_DISABLE_STATUS (1 << 21) /* can disable xAPIC */ +#define ARCH_CAP_OVERCLOCKING_STATUS (1 << 23) /* has OVRCLCKNG_STAT MSR */ +#define ARCH_CAP_PBRSB_NO (1 << 24) /* PBSR safe */ +#define ARCH_CAP_GDS_CTRL (1 << 25) /* has GDS_MITG_DIS/LOCK */ +#define ARCH_CAP_GDS_NO (1 << 26) /* GDS safe */ +#define ARCH_CAP_RFDS_NO (1 << 27) /* RFDS safe */ +#define ARCH_CAP_RFDS_CLEAR (1 << 28) /* use VERW for RFDS */ +#define ARCH_CAP_MSR_BITS \ + ("\20" "\02IBRS_ALL" "\03RSBA" "\04SKIP_L1DFL" "\05SSB_NO" "\06MDS_NO" \ + "\07IF_PSCHANGE" "\010TSX_CTRL" "\011TAA_NO" "\012MCU_CONTROL" \ + "\013MISC_PKG_CT" "\014ENERGY_FILT" "\015DOITM" "\016SBDR_SSDP_N" \ + "\017FBSDP_NO" "\020PSDP_NO" "\022FB_CLEAR" "\023FB_CLEAR_CT" \ + "\024RRSBA" "\025BHI_NO" "\026XAPIC_DIS" "\030OVERCLOCK" "\031PBRSB_NO" \ + "\032GDS_CTRL" "\033GDS_NO" "\034RFDS_NO" "\035RFDS_CLEAR" ) + +#define MSR_FLUSH_CMD 0x10b +#define FLUSH_CMD_L1D_FLUSH 0x1 /* (1ULL << 0) */ +#define MSR_BBL_CR_ADDR 0x116 /* PII+ only */ +#define MSR_BBL_CR_DECC 0x118 /* PII+ only */ +#define MSR_BBL_CR_CTL 0x119 /* PII+ only */ +#define MSR_BBL_CR_TRIG 0x11a /* PII+ only */ +#define MSR_BBL_CR_BUSY 0x11b /* PII+ only */ +#define MSR_BBL_CR_CTR3 0x11e /* PII+ only */ +#define MSR_TSX_CTRL 0x122 +#define TSX_CTRL_RTM_DISABLE (1ULL << 0) +#define TSX_CTRL_TSX_CPUID_CLEAR (1ULL << 1) +#define MSR_MCU_OPT_CTRL 0x123 +#define RNGDS_MITG_DIS (1ULL << 0) +#define MSR_SYSENTER_CS 0x174 /* PII+ only */ +#define MSR_SYSENTER_ESP 0x175 /* PII+ only */ +#define MSR_SYSENTER_EIP 0x176 /* PII+ only */ +#define MSR_MCG_CAP 0x179 +#define MSR_MCG_STATUS 0x17a +#define MSR_MCG_CTL 0x17b +#define MSR_EVNTSEL0 0x186 +#define MSR_EVNTSEL1 0x187 +#define MSR_PERF_STATUS 0x198 /* Pentium M */ +#define MSR_PERF_CTL 0x199 /* Pentium M */ +#define PERF_CTL_TURBO 0x100000000ULL /* bit 32 - turbo mode */ +#define MSR_THERM_CONTROL 0x19a +#define MSR_THERM_INTERRUPT 0x19b +#define MSR_THERM_STATUS 0x19c +#define MSR_THERM_STATUS_VALID_BIT 0x80000000 +#define MSR_THERM_STATUS_TEMP(msr) ((msr >> 16) & 0x7f) +#define MSR_THERM2_CTL 0x19d /* Pentium M */ +#define MSR_MISC_ENABLE 0x1a0 +/* + * MSR_MISC_ENABLE (0x1a0) + * + * Enable Fast Strings: enables fast REP MOVS/REP STORS (R/W) + * Enable TCC: Enable automatic thermal control circuit (R/W) + * Performance monitoring available: 1 if enabled (R/O) + * Branch trace storage unavailable: 1 if unsupported (R/O) + * Processor event based sampling unavailable: 1 if unsupported (R/O) + * Enhanced Intel SpeedStep technology enable: 1 to enable (R/W) + * Enable monitor FSM: 1 to enable MONITOR/MWAIT (R/W) + * Limit CPUID maxval: 1 to limit CPUID leaf nodes to 0x2 and lower (R/W) + * Enable xTPR message disable: 1 to disable xTPR messages + * XD bit disable: 1 to disable NX capability (bit 34, or bit 2 of %edx/%rdx) + */ +#define MISC_ENABLE_FAST_STRINGS (1 << 0) +#define MISC_ENABLE_TCC (1 << 3) +#define MISC_ENABLE_PERF_MON_AVAILABLE (1 << 7) +#define MISC_ENABLE_BTS_UNAVAILABLE (1 << 11) +#define MISC_ENABLE_PEBS_UNAVAILABLE (1 << 12) +#define MISC_ENABLE_EIST_ENABLED (1 << 16) +#define MISC_ENABLE_ENABLE_MONITOR_FSM (1 << 18) +#define MISC_ENABLE_LIMIT_CPUID_MAXVAL (1 << 22) +#define MISC_ENABLE_xTPR_MESSAGE_DISABLE (1 << 23) +#define MISC_ENABLE_XD_BIT_DISABLE (1 << 2) + +/* + * for Core i Series and newer Xeons, see + * http://www.intel.com/content/dam/www/public/us/en/ + * documents/white-papers/cpu-monitoring-dts-peci-paper.pdf + */ +#define MSR_TEMPERATURE_TARGET 0x1a2 /* Core i Series, Newer Xeons */ +#define MSR_TEMPERATURE_TARGET_TJMAX(msr) (((msr) >> 16) & 0xff) +/* + * not documented anywhere, see intelcore_update_sensor() + * only available Core Duo and Core Solo Processors + */ +#define MSR_TEMPERATURE_TARGET_UNDOCUMENTED 0x0ee +#define MSR_TEMPERATURE_TARGET_LOW_BIT_UNDOCUMENTED 0x40000000 +#define MSR_DEBUGCTLMSR 0x1d9 +#define MSR_LASTBRANCHFROMIP 0x1db +#define MSR_LASTBRANCHTOIP 0x1dc +#define MSR_LASTINTFROMIP 0x1dd +#define MSR_LASTINTTOIP 0x1de +#define MSR_ROB_CR_BKUPTMPDR6 0x1e0 +#define MSR_MTRRvarBase 0x200 +#define MSR_MTRRfix64K_00000 0x250 +#define MSR_MTRRfix16K_80000 0x258 +#define MSR_MTRRfix4K_C0000 0x268 +#define MSR_CR_PAT 0x277 +#define MSR_MTRRdefType 0x2ff +#define MTRRdefType_FIXED_ENABLE 0x400 /* bit 10 - fixed MTRR enabled */ +#define MTRRdefType_ENABLE 0x800 /* bit 11 - MTRRs enabled */ +#define MSR_PERF_FIXED_CTR1 0x30a /* CPU_CLK_Unhalted.Core */ +#define MSR_PERF_FIXED_CTR2 0x30b /* CPU_CLK.Unhalted.Ref */ +#define MSR_PERF_FIXED_CTR_CTRL 0x38d +#define MSR_PERF_FIXED_CTR_FC_DIS 0x0 /* disable counter */ +#define MSR_PERF_FIXED_CTR_FC_1 0x1 /* count ring 1 */ +#define MSR_PERF_FIXED_CTR_FC_123 0x2 /* count rings 1,2,3 */ +#define MSR_PERF_FIXED_CTR_FC_ANY 0x3 /* count everything */ +#define MSR_PERF_FIXED_CTR_FC_MASK 0x3 +#define MSR_PERF_FIXED_CTR_FC(_i, _v) ((_v) << (4 * (_i))) +#define MSR_PERF_FIXED_CTR_ANYTHR(_i) (0x4 << (4 * (_i))) +#define MSR_PERF_FIXED_CTR_INT(_i) (0x8 << (4 * (_i))) +#define MSR_PERF_GLOBAL_CTRL 0x38f +#define MSR_PERF_GLOBAL_CTR1_EN (1ULL << 33) +#define MSR_PERF_GLOBAL_CTR2_EN (1ULL << 34) +#define MSR_PKG_C3_RESIDENCY 0x3f8 +#define MSR_PKG_C6_RESIDENCY 0x3f9 +#define MSR_PKG_C7_RESIDENCY 0x3fa +#define MSR_CORE_C3_RESIDENCY 0x3fc +#define MSR_CORE_C6_RESIDENCY 0x3fd +#define MSR_CORE_C7_RESIDENCY 0x3fe +#define MSR_MC0_CTL 0x400 +#define MSR_MC0_STATUS 0x401 +#define MSR_MC0_ADDR 0x402 +#define MSR_MC0_MISC 0x403 +#define MSR_MC1_CTL 0x404 +#define MSR_MC1_STATUS 0x405 +#define MSR_MC1_ADDR 0x406 +#define MSR_MC1_MISC 0x407 +#define MSR_MC2_CTL 0x408 +#define MSR_MC2_STATUS 0x409 +#define MSR_MC2_ADDR 0x40a +#define MSR_MC2_MISC 0x40b +#define MSR_MC4_CTL 0x40c +#define MSR_MC4_STATUS 0x40d +#define MSR_MC4_ADDR 0x40e +#define MSR_MC4_MISC 0x40f +#define MSR_MC3_CTL 0x410 +#define MSR_MC3_STATUS 0x411 +#define MSR_MC3_ADDR 0x412 +#define MSR_MC3_MISC 0x413 +#define MSR_PKG_C2_RESIDENCY 0x60d +#define MSR_PKG_C8_RESIDENCY 0x630 +#define MSR_PKG_C9_RESIDENCY 0x631 +#define MSR_PKG_C10_RESIDENCY 0x632 +#define MSR_U_CET 0x6a0 +#define MSR_CET_ENDBR_EN (1 << 2) +#define MSR_CET_NO_TRACK_EN (1 << 4) +#define MSR_S_CET 0x6a2 +#define MSR_PKRS 0x6e1 +#define MSR_XSS 0xda0 + +/* VIA MSR */ +#define MSR_CENT_TMTEMPERATURE 0x1423 /* Thermal monitor temperature */ + +/* + * AMD K6/K7 MSRs. + */ +#define MSR_K6_UWCCR 0xc0000085 +#define MSR_K7_EVNTSEL0 0xc0010000 +#define MSR_K7_EVNTSEL1 0xc0010001 +#define MSR_K7_EVNTSEL2 0xc0010002 +#define MSR_K7_EVNTSEL3 0xc0010003 +#define MSR_K7_PERFCTR0 0xc0010004 +#define MSR_K7_PERFCTR1 0xc0010005 +#define MSR_K7_PERFCTR2 0xc0010006 +#define MSR_K7_PERFCTR3 0xc0010007 + +/* + * AMD K8 (Opteron) MSRs. + */ +#define MSR_PATCH_LEVEL 0x0000008b +#define MSR_SYSCFG 0xc0000010 + +#define MSR_EFER 0xc0000080 /* Extended feature enable */ +#define EFER_SCE 0x00000001 /* SYSCALL extension */ +#define EFER_LME 0x00000100 /* Long Mode Enabled */ +#define EFER_LMA 0x00000400 /* Long Mode Active */ +#define EFER_NXE 0x00000800 /* No-Execute Enabled */ +#define EFER_SVME 0x00001000 /* SVM Enabled */ + +#define MSR_STAR 0xc0000081 /* 32 bit syscall gate addr */ +#define MSR_LSTAR 0xc0000082 /* 64 bit syscall gate addr */ +#define MSR_CSTAR 0xc0000083 /* compat syscall gate addr */ +#define MSR_SFMASK 0xc0000084 /* flags to clear on syscall */ + +#define MSR_FSBASE 0xc0000100 /* 64bit offset for fs: */ +#define MSR_GSBASE 0xc0000101 /* 64bit offset for gs: */ +#define MSR_KERNELGSBASE 0xc0000102 /* storage for swapgs ins */ +#define MSR_PATCH_LOADER 0xc0010020 +#define MSR_INT_PEN_MSG 0xc0010055 /* Interrupt pending message */ + +#define MSR_DE_CFG 0xc0011029 /* Decode Configuration */ +#define DE_CFG_721 0x00000001 /* errata 721 */ +#define DE_CFG_SERIALIZE_LFENCE (1 << 1) /* Enable serializing lfence */ +#define DE_CFG_SERIALIZE_9 (1 << 9) /* Zenbleed chickenbit */ + +#define IPM_C1E_CMP_HLT 0x10000000 +#define IPM_SMI_CMP_HLT 0x08000000 + +/* + * These require a 'passcode' for access. See cpufunc.h. + */ +#define MSR_HWCR 0xc0010015 +#define HWCR_FFDIS 0x00000040 +#define HWCR_TSCFREQSEL 0x01000000 + +#define MSR_PSTATEDEF(_n) (0xc0010064 + (_n)) +#define PSTATEDEF_EN 0x8000000000000000ULL + +#define MSR_NB_CFG 0xc001001f +#define NB_CFG_DISIOREQLOCK 0x0000000000000004ULL +#define NB_CFG_DISDATMSK 0x0000001000000000ULL + +#define MSR_SEV_GHCB 0xc0010130 +#define SEV_CPUID_REQ 0x00000004 +#define SEV_CPUID_RESP 0x00000005 + +#define MSR_SEV_STATUS 0xc0010131 +#define SEV_STAT_ENABLED 0x00000001 +#define SEV_STAT_ES_ENABLED 0x00000002 + +#define MSR_LS_CFG 0xc0011020 +#define LS_CFG_DIS_LS2_SQUISH 0x02000000 + +#define MSR_IC_CFG 0xc0011021 +#define IC_CFG_DIS_SEQ_PREFETCH 0x00000800 + +#define MSR_DC_CFG 0xc0011022 +#define DC_CFG_DIS_CNV_WC_SSO 0x00000004 +#define DC_CFG_DIS_SMC_CHK_BUF 0x00000400 + +#define MSR_BU_CFG 0xc0011023 +#define BU_CFG_THRL2IDXCMPDIS 0x0000080000000000ULL +#define BU_CFG_WBPFSMCCHKDIS 0x0000200000000000ULL +#define BU_CFG_WBENHWSBDIS 0x0001000000000000ULL + +/* + * Constants related to MTRRs + */ +#define MTRR_N64K 8 /* numbers of fixed-size entries */ +#define MTRR_N16K 16 +#define MTRR_N4K 64 + +/* + * the following four 3-byte registers control the non-cacheable regions. + * These registers must be written as three separate bytes. + * + * NCRx+0: A31-A24 of starting address + * NCRx+1: A23-A16 of starting address + * NCRx+2: A15-A12 of starting address | NCR_SIZE_xx. + * + * The non-cacheable region's starting address must be aligned to the + * size indicated by the NCR_SIZE_xx field. + */ +#define NCR1 0xc4 +#define NCR2 0xc7 +#define NCR3 0xca +#define NCR4 0xcd + +#define NCR_SIZE_0K 0 +#define NCR_SIZE_4K 1 +#define NCR_SIZE_8K 2 +#define NCR_SIZE_16K 3 +#define NCR_SIZE_32K 4 +#define NCR_SIZE_64K 5 +#define NCR_SIZE_128K 6 +#define NCR_SIZE_256K 7 +#define NCR_SIZE_512K 8 +#define NCR_SIZE_1M 9 +#define NCR_SIZE_2M 10 +#define NCR_SIZE_4M 11 +#define NCR_SIZE_8M 12 +#define NCR_SIZE_16M 13 +#define NCR_SIZE_32M 14 +#define NCR_SIZE_4G 15 + +/* + * Performance monitor events. + * + * Note that 586-class and 686-class CPUs have different performance + * monitors available, and they are accessed differently: + * + * 686-class: `rdpmc' instruction + * 586-class: `rdmsr' instruction, CESR MSR + * + * The descriptions of these events are too lengthy to include here. + * See Appendix A of "Intel Architecture Software Developer's + * Manual, Volume 3: System Programming" for more information. + */ + +/* + * 586-class CESR MSR format. Lower 16 bits is CTR0, upper 16 bits + * is CTR1. + */ + +#define PMC5_CESR_EVENT 0x003f +#define PMC5_CESR_OS 0x0040 +#define PMC5_CESR_USR 0x0080 +#define PMC5_CESR_E 0x0100 +#define PMC5_CESR_P 0x0200 + +#define PMC5_DATA_READ 0x00 +#define PMC5_DATA_WRITE 0x01 +#define PMC5_DATA_TLB_MISS 0x02 +#define PMC5_DATA_READ_MISS 0x03 +#define PMC5_DATA_WRITE_MISS 0x04 +#define PMC5_WRITE_M_E 0x05 +#define PMC5_DATA_LINES_WBACK 0x06 +#define PMC5_DATA_CACHE_SNOOP 0x07 +#define PMC5_DATA_CACHE_SNOOP_HIT 0x08 +#define PMC5_MEM_ACCESS_BOTH_PIPES 0x09 +#define PMC5_BANK_CONFLICTS 0x0a +#define PMC5_MISALIGNED_DATA 0x0b +#define PMC5_INST_READ 0x0c +#define PMC5_INST_TLB_MISS 0x0d +#define PMC5_INST_CACHE_MISS 0x0e +#define PMC5_SEGMENT_REG_LOAD 0x0f +#define PMC5_BRANCHES 0x12 +#define PMC5_BTB_HITS 0x13 +#define PMC5_BRANCH_TAKEN 0x14 +#define PMC5_PIPELINE_FLUSH 0x15 +#define PMC5_INST_EXECUTED 0x16 +#define PMC5_INST_EXECUTED_V_PIPE 0x17 +#define PMC5_BUS_UTILIZATION 0x18 +#define PMC5_WRITE_BACKUP_STALL 0x19 +#define PMC5_DATA_READ_STALL 0x1a +#define PMC5_WRITE_E_M_STALL 0x1b +#define PMC5_LOCKED_BUS 0x1c +#define PMC5_IO_CYCLE 0x1d +#define PMC5_NONCACHE_MEM_READ 0x1e +#define PMC5_AGI_STALL 0x1f +#define PMC5_FLOPS 0x22 +#define PMC5_BP0_MATCH 0x23 +#define PMC5_BP1_MATCH 0x24 +#define PMC5_BP2_MATCH 0x25 +#define PMC5_BP3_MATCH 0x26 +#define PMC5_HARDWARE_INTR 0x27 +#define PMC5_DATA_RW 0x28 +#define PMC5_DATA_RW_MISS 0x29 + +/* + * 686-class Event Selector MSR format. + */ + +#define PMC6_EVTSEL_EVENT 0x000000ff +#define PMC6_EVTSEL_UNIT 0x0000ff00 +#define PMC6_EVTSEL_UNIT_SHIFT 8 +#define PMC6_EVTSEL_USR (1 << 16) +#define PMC6_EVTSEL_OS (1 << 17) +#define PMC6_EVTSEL_E (1 << 18) +#define PMC6_EVTSEL_PC (1 << 19) +#define PMC6_EVTSEL_INT (1 << 20) +#define PMC6_EVTSEL_EN (1 << 22) /* PerfEvtSel0 only */ +#define PMC6_EVTSEL_INV (1 << 23) +#define PMC6_EVTSEL_COUNTER_MASK 0xff000000 +#define PMC6_EVTSEL_COUNTER_MASK_SHIFT 24 + +/* Data Cache Unit */ +#define PMC6_DATA_MEM_REFS 0x43 +#define PMC6_DCU_LINES_IN 0x45 +#define PMC6_DCU_M_LINES_IN 0x46 +#define PMC6_DCU_M_LINES_OUT 0x47 +#define PMC6_DCU_MISS_OUTSTANDING 0x48 + +/* Instruction Fetch Unit */ +#define PMC6_IFU_IFETCH 0x80 +#define PMC6_IFU_IFETCH_MISS 0x81 +#define PMC6_ITLB_MISS 0x85 +#define PMC6_IFU_MEM_STALL 0x86 +#define PMC6_ILD_STALL 0x87 + +/* L2 Cache */ +#define PMC6_L2_IFETCH 0x28 +#define PMC6_L2_LD 0x29 +#define PMC6_L2_ST 0x2a +#define PMC6_L2_LINES_IN 0x24 +#define PMC6_L2_LINES_OUT 0x26 +#define PMC6_L2_M_LINES_INM 0x25 +#define PMC6_L2_M_LINES_OUTM 0x27 +#define PMC6_L2_RQSTS 0x2e +#define PMC6_L2_ADS 0x21 +#define PMC6_L2_DBUS_BUSY 0x22 +#define PMC6_L2_DBUS_BUSY_RD 0x23 + +/* External Bus Logic */ +#define PMC6_BUS_DRDY_CLOCKS 0x62 +#define PMC6_BUS_LOCK_CLOCKS 0x63 +#define PMC6_BUS_REQ_OUTSTANDING 0x60 +#define PMC6_BUS_TRAN_BRD 0x65 +#define PMC6_BUS_TRAN_RFO 0x66 +#define PMC6_BUS_TRANS_WB 0x67 +#define PMC6_BUS_TRAN_IFETCH 0x68 +#define PMC6_BUS_TRAN_INVAL 0x69 +#define PMC6_BUS_TRAN_PWR 0x6a +#define PMC6_BUS_TRANS_P 0x6b +#define PMC6_BUS_TRANS_IO 0x6c +#define PMC6_BUS_TRAN_DEF 0x6d +#define PMC6_BUS_TRAN_BURST 0x6e +#define PMC6_BUS_TRAN_ANY 0x70 +#define PMC6_BUS_TRAN_MEM 0x6f +#define PMC6_BUS_DATA_RCV 0x64 +#define PMC6_BUS_BNR_DRV 0x61 +#define PMC6_BUS_HIT_DRV 0x7a +#define PMC6_BUS_HITM_DRDV 0x7b +#define PMC6_BUS_SNOOP_STALL 0x7e + +/* Floating Point Unit */ +#define PMC6_FLOPS 0xc1 +#define PMC6_FP_COMP_OPS_EXE 0x10 +#define PMC6_FP_ASSIST 0x11 +#define PMC6_MUL 0x12 +#define PMC6_DIV 0x12 +#define PMC6_CYCLES_DIV_BUSY 0x14 + +/* Memory Ordering */ +#define PMC6_LD_BLOCKS 0x03 +#define PMC6_SB_DRAINS 0x04 +#define PMC6_MISALIGN_MEM_REF 0x05 +#define PMC6_EMON_KNI_PREF_DISPATCHED 0x07 /* P-III only */ +#define PMC6_EMON_KNI_PREF_MISS 0x4b /* P-III only */ + +/* Instruction Decoding and Retirement */ +#define PMC6_INST_RETIRED 0xc0 +#define PMC6_UOPS_RETIRED 0xc2 +#define PMC6_INST_DECODED 0xd0 +#define PMC6_EMON_KNI_INST_RETIRED 0xd8 +#define PMC6_EMON_KNI_COMP_INST_RET 0xd9 + +/* Interrupts */ +#define PMC6_HW_INT_RX 0xc8 +#define PMC6_CYCLES_INT_MASKED 0xc6 +#define PMC6_CYCLES_INT_PENDING_AND_MASKED 0xc7 + +/* Branches */ +#define PMC6_BR_INST_RETIRED 0xc4 +#define PMC6_BR_MISS_PRED_RETIRED 0xc5 +#define PMC6_BR_TAKEN_RETIRED 0xc9 +#define PMC6_BR_MISS_PRED_TAKEN_RET 0xca +#define PMC6_BR_INST_DECODED 0xe0 +#define PMC6_BTB_MISSES 0xe2 +#define PMC6_BR_BOGUS 0xe4 +#define PMC6_BACLEARS 0xe6 + +/* Stalls */ +#define PMC6_RESOURCE_STALLS 0xa2 +#define PMC6_PARTIAL_RAT_STALLS 0xd2 + +/* Segment Register Loads */ +#define PMC6_SEGMENT_REG_LOADS 0x06 + +/* Clocks */ +#define PMC6_CPU_CLK_UNHALTED 0x79 + +/* MMX Unit */ +#define PMC6_MMX_INSTR_EXEC 0xb0 /* Celeron, P-II, P-IIX only */ +#define PMC6_MMX_SAT_INSTR_EXEC 0xb1 /* P-II and P-III only */ +#define PMC6_MMX_UOPS_EXEC 0xb2 /* P-II and P-III only */ +#define PMC6_MMX_INSTR_TYPE_EXEC 0xb3 /* P-II and P-III only */ +#define PMC6_FP_MMX_TRANS 0xcc /* P-II and P-III only */ +#define PMC6_MMX_ASSIST 0xcd /* P-II and P-III only */ +#define PMC6_MMX_INSTR_RET 0xc3 /* P-II only */ + +/* Segment Register Renaming */ +#define PMC6_SEG_RENAME_STALLS 0xd4 /* P-II and P-III only */ +#define PMC6_SEG_REG_RENAMES 0xd5 /* P-II and P-III only */ +#define PMC6_RET_SEG_RENAMES 0xd6 /* P-II and P-III only */ + +/* + * AMD K7 Event Selector MSR format. + */ + +#define K7_EVTSEL_EVENT 0x000000ff +#define K7_EVTSEL_UNIT 0x0000ff00 +#define K7_EVTSEL_UNIT_SHIFT 8 +#define K7_EVTSEL_USR (1 << 16) +#define K7_EVTSEL_OS (1 << 17) +#define K7_EVTSEL_E (1 << 18) +#define K7_EVTSEL_PC (1 << 19) +#define K7_EVTSEL_INT (1 << 20) +#define K7_EVTSEL_EN (1 << 22) +#define K7_EVTSEL_INV (1 << 23) +#define K7_EVTSEL_COUNTER_MASK 0xff000000 +#define K7_EVTSEL_COUNTER_MASK_SHIFT 24 + +/* Segment Register Loads */ +#define K7_SEGMENT_REG_LOADS 0x20 + +#define K7_STORES_TO_ACTIVE_INST_STREAM 0x21 + +/* Data Cache Unit */ +#define K7_DATA_CACHE_ACCESS 0x40 +#define K7_DATA_CACHE_MISS 0x41 +#define K7_DATA_CACHE_REFILL 0x42 +#define K7_DATA_CACHE_REFILL_SYSTEM 0x43 +#define K7_DATA_CACHE_WBACK 0x44 +#define K7_L2_DTLB_HIT 0x45 +#define K7_L2_DTLB_MISS 0x46 +#define K7_MISALIGNED_DATA_REF 0x47 +#define K7_SYSTEM_REQUEST 0x64 +#define K7_SYSTEM_REQUEST_TYPE 0x65 + +#define K7_SNOOP_HIT 0x73 +#define K7_SINGLE_BIT_ECC_ERROR 0x74 +#define K7_CACHE_LINE_INVAL 0x75 +#define K7_CYCLES_PROCESSOR_IS_RUNNING 0x76 +#define K7_L2_REQUEST 0x79 +#define K7_L2_REQUEST_BUSY 0x7a + +/* Instruction Fetch Unit */ +#define K7_IFU_IFETCH 0x80 +#define K7_IFU_IFETCH_MISS 0x81 +#define K7_IFU_REFILL_FROM_L2 0x82 +#define K7_IFU_REFILL_FROM_SYSTEM 0x83 +#define K7_ITLB_L1_MISS 0x84 +#define K7_ITLB_L2_MISS 0x85 +#define K7_SNOOP_RESYNC 0x86 +#define K7_IFU_STALL 0x87 + +#define K7_RETURN_STACK_HITS 0x88 +#define K7_RETURN_STACK_OVERFLOW 0x89 + +/* Retired */ +#define K7_RETIRED_INST 0xc0 +#define K7_RETIRED_OPS 0xc1 +#define K7_RETIRED_BRANCHES 0xc2 +#define K7_RETIRED_BRANCH_MISPREDICTED 0xc3 +#define K7_RETIRED_TAKEN_BRANCH 0xc4 +#define K7_RETIRED_TAKEN_BRANCH_MISPREDICTED 0xc5 +#define K7_RETIRED_FAR_CONTROL_TRANSFER 0xc6 +#define K7_RETIRED_RESYNC_BRANCH 0xc7 +#define K7_RETIRED_NEAR_RETURNS 0xc8 +#define K7_RETIRED_NEAR_RETURNS_MISPREDICTED 0xc9 +#define K7_RETIRED_INDIRECT_MISPREDICTED 0xca + +/* Interrupts */ +#define K7_CYCLES_INT_MASKED 0xcd +#define K7_CYCLES_INT_PENDING_AND_MASKED 0xce +#define K7_HW_INTR_RECV 0xcf + +#define K7_INSTRUCTION_DECODER_EMPTY 0xd0 +#define K7_DISPATCH_STALLS 0xd1 +#define K7_BRANCH_ABORTS_TO_RETIRE 0xd2 +#define K7_SERIALIZE 0xd3 +#define K7_SEGMENT_LOAD_STALL 0xd4 +#define K7_ICU_FULL 0xd5 +#define K7_RESERVATION_STATIONS_FULL 0xd6 +#define K7_FPU_FULL 0xd7 +#define K7_LS_FULL 0xd8 +#define K7_ALL_QUIET_STALL 0xd9 +#define K7_FAR_TRANSFER_OR_RESYNC_BRANCH_PENDING 0xda + +#define K7_BP0_MATCH 0xdc +#define K7_BP1_MATCH 0xdd +#define K7_BP2_MATCH 0xde +#define K7_BP3_MATCH 0xdf + +/* VIA C3 crypto featureset: for amd64_has_xcrypt */ +#define C3_HAS_AES 1 /* cpu has AES */ +#define C3_HAS_SHA 2 /* cpu has SHA1 & SHA256 */ +#define C3_HAS_MM 4 /* cpu has RSA instructions */ +#define C3_HAS_AESCTR 8 /* cpu has AES-CTR instructions */ + +/* Centaur Extended Feature flags */ +#define C3_CPUID_HAS_RNG 0x000004 +#define C3_CPUID_DO_RNG 0x000008 +#define C3_CPUID_HAS_ACE 0x000040 +#define C3_CPUID_DO_ACE 0x000080 +#define C3_CPUID_HAS_ACE2 0x000100 +#define C3_CPUID_DO_ACE2 0x000200 +#define C3_CPUID_HAS_PHE 0x000400 +#define C3_CPUID_DO_PHE 0x000800 +#define C3_CPUID_HAS_PMM 0x001000 +#define C3_CPUID_DO_PMM 0x002000 + +/* VIA C3 xcrypt-* instruction context control options */ +#define C3_CRYPT_CWLO_ROUND_M 0x0000000f +#define C3_CRYPT_CWLO_ALG_M 0x00000070 +#define C3_CRYPT_CWLO_ALG_AES 0x00000000 +#define C3_CRYPT_CWLO_KEYGEN_M 0x00000080 +#define C3_CRYPT_CWLO_KEYGEN_HW 0x00000000 +#define C3_CRYPT_CWLO_KEYGEN_SW 0x00000080 +#define C3_CRYPT_CWLO_NORMAL 0x00000000 +#define C3_CRYPT_CWLO_INTERMEDIATE 0x00000100 +#define C3_CRYPT_CWLO_ENCRYPT 0x00000000 +#define C3_CRYPT_CWLO_DECRYPT 0x00000200 +#define C3_CRYPT_CWLO_KEY128 0x0000000a /* 128bit, 10 rds */ +#define C3_CRYPT_CWLO_KEY192 0x0000040c /* 192bit, 12 rds */ +#define C3_CRYPT_CWLO_KEY256 0x0000080e /* 256bit, 15 rds */ + +/* Intel Silicon Debug */ +#define IA32_DEBUG_INTERFACE 0xc80 +#define IA32_DEBUG_INTERFACE_ENABLE 0x00000001 +#define IA32_DEBUG_INTERFACE_LOCK 0x40000000 +#define IA32_DEBUG_INTERFACE_MASK 0x80000000 + +/* + * VMX + */ +#define IA32_FEATURE_CONTROL_LOCK 0x01 +#define IA32_FEATURE_CONTROL_SMX_EN 0x02 +#define IA32_FEATURE_CONTROL_VMX_EN 0x04 +#define IA32_FEATURE_CONTROL_SENTER_EN (1ULL << 15) +#define IA32_FEATURE_CONTROL_SENTER_PARAM_MASK 0x7f00 +#define IA32_VMX_BASIC 0x480 +#define IA32_VMX_PINBASED_CTLS 0x481 +#define IA32_VMX_PROCBASED_CTLS 0x482 +#define IA32_VMX_EXIT_CTLS 0x483 +#define IA32_VMX_ENTRY_CTLS 0x484 +#define IA32_VMX_MISC 0x485 +#define IA32_VMX_CR0_FIXED0 0x486 +#define IA32_VMX_CR0_FIXED1 0x487 +#define IA32_VMX_CR4_FIXED0 0x488 +#define IA32_VMX_CR4_FIXED1 0x489 +#define IA32_VMX_PROCBASED2_CTLS 0x48B +#define IA32_VMX_EPT_VPID_CAP 0x48C +#define IA32_VMX_TRUE_PINBASED_CTLS 0x48D +#define IA32_VMX_TRUE_PROCBASED_CTLS 0x48E +#define IA32_VMX_TRUE_EXIT_CTLS 0x48F +#define IA32_VMX_TRUE_ENTRY_CTLS 0x490 +#define IA32_VMX_VMFUNC 0x491 + +#define IA32_EPT_VPID_CAP_XO_TRANSLATIONS (1ULL << 0) +#define IA32_EPT_VPID_CAP_PAGE_WALK_4 (1ULL << 6) +#define IA32_EPT_VPID_CAP_WB (1ULL << 14) +#define IA32_EPT_VPID_CAP_AD_BITS (1ULL << 21) +#define IA32_EPT_VPID_CAP_INVEPT_CONTEXT (1ULL << 25) +#define IA32_EPT_VPID_CAP_INVEPT_ALL (1ULL << 26) + +#define IA32_EPT_PAGING_CACHE_TYPE_UC 0x0 +#define IA32_EPT_PAGING_CACHE_TYPE_WB 0x6 +#define IA32_EPT_AD_BITS_ENABLE (1ULL << 6) +#define IA32_EPT_PAGE_WALK_LENGTH 0x4 + +/* VMX : IA32_VMX_BASIC bits */ +#define IA32_VMX_TRUE_CTLS_AVAIL (1ULL << 55) + +/* VMX : IA32_VMX_PINBASED_CTLS bits */ +#define IA32_VMX_EXTERNAL_INT_EXITING (1ULL << 0) +#define IA32_VMX_NMI_EXITING (1ULL << 3) +#define IA32_VMX_VIRTUAL_NMIS (1ULL << 5) +#define IA32_VMX_ACTIVATE_VMX_PREEMPTION_TIMER (1ULL << 6) +#define IA32_VMX_PROCESS_POSTED_INTERRUPTS (1ULL << 7) + +/* VMX : IA32_VMX_PROCBASED_CTLS bits */ +#define IA32_VMX_INTERRUPT_WINDOW_EXITING (1ULL << 2) +#define IA32_VMX_USE_TSC_OFFSETTING (1ULL << 3) +#define IA32_VMX_HLT_EXITING (1ULL << 7) +#define IA32_VMX_INVLPG_EXITING (1ULL << 9) +#define IA32_VMX_MWAIT_EXITING (1ULL << 10) +#define IA32_VMX_RDPMC_EXITING (1ULL << 11) +#define IA32_VMX_RDTSC_EXITING (1ULL << 12) +#define IA32_VMX_CR3_LOAD_EXITING (1ULL << 15) +#define IA32_VMX_CR3_STORE_EXITING (1ULL << 16) +#define IA32_VMX_CR8_LOAD_EXITING (1ULL << 19) +#define IA32_VMX_CR8_STORE_EXITING (1ULL << 20) +#define IA32_VMX_USE_TPR_SHADOW (1ULL << 21) +#define IA32_VMX_NMI_WINDOW_EXITING (1ULL << 22) +#define IA32_VMX_MOV_DR_EXITING (1ULL << 23) +#define IA32_VMX_UNCONDITIONAL_IO_EXITING (1ULL << 24) +#define IA32_VMX_USE_IO_BITMAPS (1ULL << 25) +#define IA32_VMX_MONITOR_TRAP_FLAG (1ULL << 27) +#define IA32_VMX_USE_MSR_BITMAPS (1ULL << 28) +#define IA32_VMX_MONITOR_EXITING (1ULL << 29) +#define IA32_VMX_PAUSE_EXITING (1ULL << 30) +#define IA32_VMX_ACTIVATE_SECONDARY_CONTROLS (1ULL << 31) + +/* VMX : IA32_VMX_PROCBASED2_CTLS bits */ +#define IA32_VMX_VIRTUALIZE_APIC (1ULL << 0) +#define IA32_VMX_ENABLE_EPT (1ULL << 1) +#define IA32_VMX_DESCRIPTOR_TABLE_EXITING (1ULL << 2) +#define IA32_VMX_ENABLE_RDTSCP (1ULL << 3) +#define IA32_VMX_VIRTUALIZE_X2APIC_MODE (1ULL << 4) +#define IA32_VMX_ENABLE_VPID (1ULL << 5) +#define IA32_VMX_WBINVD_EXITING (1ULL << 6) +#define IA32_VMX_UNRESTRICTED_GUEST (1ULL << 7) +#define IA32_VMX_APIC_REGISTER_VIRTUALIZATION (1ULL << 8) +#define IA32_VMX_VIRTUAL_INTERRUPT_DELIVERY (1ULL << 9) +#define IA32_VMX_PAUSE_LOOP_EXITING (1ULL << 10) +#define IA32_VMX_RDRAND_EXITING (1ULL << 11) +#define IA32_VMX_ENABLE_INVPCID (1ULL << 12) +#define IA32_VMX_ENABLE_VM_FUNCTIONS (1ULL << 13) +#define IA32_VMX_VMCS_SHADOWING (1ULL << 14) +#define IA32_VMX_ENABLE_ENCLS_EXITING (1ULL << 15) +#define IA32_VMX_RDSEED_EXITING (1ULL << 16) +#define IA32_VMX_ENABLE_PML (1ULL << 17) +#define IA32_VMX_EPT_VIOLATION_VE (1ULL << 18) +#define IA32_VMX_CONCEAL_VMX_FROM_PT (1ULL << 19) +#define IA32_VMX_ENABLE_XSAVES_XRSTORS (1ULL << 20) +#define IA32_VMX_ENABLE_TSC_SCALING (1ULL << 25) + +/* VMX : IA32_VMX_EXIT_CTLS bits */ +#define IA32_VMX_SAVE_DEBUG_CONTROLS (1ULL << 2) +#define IA32_VMX_HOST_SPACE_ADDRESS_SIZE (1ULL << 9) +#define IA32_VMX_LOAD_IA32_PERF_GLOBAL_CTRL_ON_EXIT (1ULL << 12) +#define IA32_VMX_ACKNOWLEDGE_INTERRUPT_ON_EXIT (1ULL << 15) +#define IA32_VMX_SAVE_IA32_PAT_ON_EXIT (1ULL << 18) +#define IA32_VMX_LOAD_IA32_PAT_ON_EXIT (1ULL << 19) +#define IA32_VMX_SAVE_IA32_EFER_ON_EXIT (1ULL << 20) +#define IA32_VMX_LOAD_IA32_EFER_ON_EXIT (1ULL << 21) +#define IA32_VMX_SAVE_VMX_PREEMPTION_TIMER (1ULL << 22) +#define IA32_VMX_CLEAR_IA32_BNDCFGS_ON_EXIT (1ULL << 23) +#define IA32_VMX_CONCEAL_VM_EXITS_FROM_PT (1ULL << 24) +#define IA32_VMX_LOAD_HOST_CET_STATE (1ULL << 28) + +/* VMX: IA32_VMX_ENTRY_CTLS bits */ +#define IA32_VMX_LOAD_DEBUG_CONTROLS (1ULL << 2) +#define IA32_VMX_IA32E_MODE_GUEST (1ULL << 9) +#define IA32_VMX_ENTRY_TO_SMM (1ULL << 10) +#define IA32_VMX_DEACTIVATE_DUAL_MONITOR_TREATMENT (1ULL << 11) +#define IA32_VMX_LOAD_IA32_PERF_GLOBAL_CTRL_ON_ENTRY (1ULL << 13) +#define IA32_VMX_LOAD_IA32_PAT_ON_ENTRY (1ULL << 14) +#define IA32_VMX_LOAD_IA32_EFER_ON_ENTRY (1ULL << 15) +#define IA32_VMX_LOAD_IA32_BNDCFGS_ON_ENTRY (1ULL << 16) +#define IA32_VMX_CONCEAL_VM_ENTRIES_FROM_PT (1ULL << 17) +#define IA32_VMX_LOAD_GUEST_CET_STATE (1ULL << 20) + +/* + * VMX : VMCS Fields + */ + +/* 16-bit control fields */ +#define VMCS_GUEST_VPID 0x0000 +#define VMCS_POSTED_INT_NOTIF_VECTOR 0x0002 +#define VMCS_EPTP_INDEX 0x0004 + +/* 16-bit guest state fields */ +#define VMCS_GUEST_IA32_ES_SEL 0x0800 +#define VMCS_GUEST_IA32_CS_SEL 0x0802 +#define VMCS_GUEST_IA32_SS_SEL 0x0804 +#define VMCS_GUEST_IA32_DS_SEL 0x0806 +#define VMCS_GUEST_IA32_FS_SEL 0x0808 +#define VMCS_GUEST_IA32_GS_SEL 0x080A +#define VMCS_GUEST_IA32_LDTR_SEL 0x080C +#define VMCS_GUEST_IA32_TR_SEL 0x080E +#define VMCS_GUEST_INTERRUPT_STATUS 0x0810 +#define VMCS_GUEST_PML_INDEX 0x0812 + +/* 16-bit host state fields */ +#define VMCS_HOST_IA32_ES_SEL 0x0C00 +#define VMCS_HOST_IA32_CS_SEL 0x0C02 +#define VMCS_HOST_IA32_SS_SEL 0x0C04 +#define VMCS_HOST_IA32_DS_SEL 0x0C06 +#define VMCS_HOST_IA32_FS_SEL 0x0C08 +#define VMCS_HOST_IA32_GS_SEL 0x0C0A +#define VMCS_HOST_IA32_TR_SEL 0x0C0C + +/* 64-bit control fields */ +#define VMCS_IO_BITMAP_A 0x2000 +#define VMCS_IO_BITMAP_B 0x2002 +#define VMCS_MSR_BITMAP_ADDRESS 0x2004 +#define VMCS_EXIT_STORE_MSR_ADDRESS 0x2006 +#define VMCS_EXIT_LOAD_MSR_ADDRESS 0x2008 +#define VMCS_ENTRY_LOAD_MSR_ADDRESS 0x200A +#define VMCS_EXECUTIVE_VMCS_POINTER 0x200C +#define VMCS_PML_ADDRESS 0x200E +#define VMCS_TSC_OFFSET 0x2010 +#define VMCS_VIRTUAL_APIC_ADDRESS 0x2012 +#define VMCS_APIC_ACCESS_ADDRESS 0x2014 +#define VMCS_POSTED_INTERRUPT_DESC 0x2016 +#define VMCS_VM_FUNCTION_CONTROLS 0x2018 +#define VMCS_GUEST_IA32_EPTP 0x201A +#define VMCS_EOI_EXIT_BITMAP_0 0x201C +#define VMCS_EOI_EXIT_BITMAP_1 0x201E +#define VMCS_EOI_EXIT_BITMAP_2 0x2020 +#define VMCS_EOI_EXIT_BITMAP_3 0x2022 +#define VMCS_EPTP_LIST_ADDRESS 0x2024 +#define VMCS_VMREAD_BITMAP_ADDRESS 0x2026 +#define VMCS_VMWRITE_BITMAP_ADDRESS 0x2028 +#define VMCS_VIRTUALIZATION_EXC_ADDRESS 0x202A +#define VMCS_XSS_EXITING_BITMAP 0x202C +#define VMCS_ENCLS_EXITING_BITMAP 0x202E +#define VMCS_TSC_MULTIPLIER 0x2032 + +/* 64-bit RO data field */ +#define VMCS_GUEST_PHYSICAL_ADDRESS 0x2400 + +/* 64-bit guest state fields */ +#define VMCS_LINK_POINTER 0x2800 +#define VMCS_GUEST_IA32_DEBUGCTL 0x2802 +#define VMCS_GUEST_IA32_PAT 0x2804 +#define VMCS_GUEST_IA32_EFER 0x2806 +#define VMCS_GUEST_IA32_PERF_GBL_CTRL 0x2808 +#define VMCS_GUEST_PDPTE0 0x280A +#define VMCS_GUEST_PDPTE1 0x280C +#define VMCS_GUEST_PDPTE2 0x280E +#define VMCS_GUEST_PDPTE3 0x2810 +#define VMCS_GUEST_IA32_BNDCFGS 0x2812 + +/* 64-bit host state fields */ +#define VMCS_HOST_IA32_PAT 0x2C00 +#define VMCS_HOST_IA32_EFER 0x2C02 +#define VMCS_HOST_IA32_PERF_GBL_CTRL 0x2C04 + +/* 32-bit control fields */ +#define VMCS_PINBASED_CTLS 0x4000 +#define VMCS_PROCBASED_CTLS 0x4002 +#define VMCS_EXCEPTION_BITMAP 0x4004 +#define VMCS_PF_ERROR_CODE_MASK 0x4006 +#define VMCS_PF_ERROR_CODE_MATCH 0x4008 +#define VMCS_CR3_TARGET_COUNT 0x400A +#define VMCS_EXIT_CTLS 0x400C +#define VMCS_EXIT_MSR_STORE_COUNT 0x400E +#define VMCS_EXIT_MSR_LOAD_COUNT 0x4010 +#define VMCS_ENTRY_CTLS 0x4012 +#define VMCS_ENTRY_MSR_LOAD_COUNT 0x4014 +#define VMCS_ENTRY_INTERRUPTION_INFO 0x4016 +#define VMCS_ENTRY_EXCEPTION_ERROR_CODE 0x4018 +#define VMCS_ENTRY_INSTRUCTION_LENGTH 0x401A +#define VMCS_TPR_THRESHOLD 0x401C +#define VMCS_PROCBASED2_CTLS 0x401E +#define VMCS_PLE_GAP 0x4020 +#define VMCS_PLE_WINDOW 0x4022 + +/* 32-bit RO data fields */ +#define VMCS_INSTRUCTION_ERROR 0x4400 +#define VMCS_EXIT_REASON 0x4402 +#define VMCS_EXIT_INTERRUPTION_INFO 0x4404 +#define VMCS_EXIT_INTERRUPTION_ERR_CODE 0x4406 +#define VMCS_IDT_VECTORING_INFO 0x4408 +#define VMCS_IDT_VECTORING_ERROR_CODE 0x440A +#define VMCS_INSTRUCTION_LENGTH 0x440C +#define VMCS_EXIT_INSTRUCTION_INFO 0x440E + +/* 32-bit guest state fields */ +#define VMCS_GUEST_IA32_ES_LIMIT 0x4800 +#define VMCS_GUEST_IA32_CS_LIMIT 0x4802 +#define VMCS_GUEST_IA32_SS_LIMIT 0x4804 +#define VMCS_GUEST_IA32_DS_LIMIT 0x4806 +#define VMCS_GUEST_IA32_FS_LIMIT 0x4808 +#define VMCS_GUEST_IA32_GS_LIMIT 0x480A +#define VMCS_GUEST_IA32_LDTR_LIMIT 0x480C +#define VMCS_GUEST_IA32_TR_LIMIT 0x480E +#define VMCS_GUEST_IA32_GDTR_LIMIT 0x4810 +#define VMCS_GUEST_IA32_IDTR_LIMIT 0x4812 +#define VMCS_GUEST_IA32_ES_AR 0x4814 +#define VMCS_GUEST_IA32_CS_AR 0x4816 +#define VMCS_GUEST_IA32_SS_AR 0x4818 +#define VMCS_GUEST_IA32_DS_AR 0x481A +#define VMCS_GUEST_IA32_FS_AR 0x481C +#define VMCS_GUEST_IA32_GS_AR 0x481E +#define VMCS_GUEST_IA32_LDTR_AR 0x4820 +#define VMCS_GUEST_IA32_TR_AR 0x4822 +#define VMCS_GUEST_INTERRUPTIBILITY_ST 0x4824 +#define VMCS_GUEST_ACTIVITY_STATE 0x4826 +#define VMCS_GUEST_SMBASE 0x4828 +#define VMCS_GUEST_IA32_SYSENTER_CS 0x482A +#define VMCS_VMX_PREEMPTION_TIMER_VAL 0x482E + +/* 32-bit host state field */ +#define VMCS_HOST_IA32_SYSENTER_CS 0x4C00 + +/* Natural-width control fields */ +#define VMCS_CR0_MASK 0x6000 +#define VMCS_CR4_MASK 0x6002 +#define VMCS_CR0_READ_SHADOW 0x6004 +#define VMCS_CR4_READ_SHADOW 0x6006 +#define VMCS_CR3_TARGET_0 0x6008 +#define VMCS_CR3_TARGET_1 0x600A +#define VMCS_CR3_TARGET_2 0x600C +#define VMCS_CR3_TARGET_3 0x600E + +/* Natural-width RO fields */ +#define VMCS_GUEST_EXIT_QUALIFICATION 0x6400 +#define VMCS_IO_RCX 0x6402 +#define VMCS_IO_RSI 0x6404 +#define VMCS_IO_RDI 0x6406 +#define VMCS_IO_RIP 0x6408 +#define VMCS_GUEST_LINEAR_ADDRESS 0x640A + +/* Natural-width guest state fields */ +#define VMCS_GUEST_IA32_CR0 0x6800 +#define VMCS_GUEST_IA32_CR3 0x6802 +#define VMCS_GUEST_IA32_CR4 0x6804 +#define VMCS_GUEST_IA32_ES_BASE 0x6806 +#define VMCS_GUEST_IA32_CS_BASE 0x6808 +#define VMCS_GUEST_IA32_SS_BASE 0x680A +#define VMCS_GUEST_IA32_DS_BASE 0x680C +#define VMCS_GUEST_IA32_FS_BASE 0x680E +#define VMCS_GUEST_IA32_GS_BASE 0x6810 +#define VMCS_GUEST_IA32_LDTR_BASE 0x6812 +#define VMCS_GUEST_IA32_TR_BASE 0x6814 +#define VMCS_GUEST_IA32_GDTR_BASE 0x6816 +#define VMCS_GUEST_IA32_IDTR_BASE 0x6818 +#define VMCS_GUEST_IA32_DR7 0x681A +#define VMCS_GUEST_IA32_RSP 0x681C +#define VMCS_GUEST_IA32_RIP 0x681E +#define VMCS_GUEST_IA32_RFLAGS 0x6820 +#define VMCS_GUEST_PENDING_DBG_EXC 0x6822 +#define VMCS_GUEST_IA32_SYSENTER_ESP 0x6824 +#define VMCS_GUEST_IA32_SYSENTER_EIP 0x6826 +#define VMCS_GUEST_IA32_S_CET 0x6828 + +/* Natural-width host state fields */ +#define VMCS_HOST_IA32_CR0 0x6C00 +#define VMCS_HOST_IA32_CR3 0x6C02 +#define VMCS_HOST_IA32_CR4 0x6C04 +#define VMCS_HOST_IA32_FS_BASE 0x6C06 +#define VMCS_HOST_IA32_GS_BASE 0x6C08 +#define VMCS_HOST_IA32_TR_BASE 0x6C0A +#define VMCS_HOST_IA32_GDTR_BASE 0x6C0C +#define VMCS_HOST_IA32_IDTR_BASE 0x6C0E +#define VMCS_HOST_IA32_SYSENTER_ESP 0x6C10 +#define VMCS_HOST_IA32_SYSENTER_EIP 0x6C12 +#define VMCS_HOST_IA32_RSP 0x6C14 +#define VMCS_HOST_IA32_RIP 0x6C16 +#define VMCS_HOST_IA32_S_CET 0x6C18 + +#define IA32_VMX_INVVPID_INDIV_ADDR_CTX 0x0 +#define IA32_VMX_INVVPID_SINGLE_CTX 0x1 +#define IA32_VMX_INVVPID_ALL_CTX 0x2 +#define IA32_VMX_INVVPID_SINGLE_CTX_GLB 0x3 + +#define IA32_VMX_INVEPT_SINGLE_CTX 0x1 +#define IA32_VMX_INVEPT_GLOBAL_CTX 0x2 + +#define IA32_VMX_EPT_FAULT_READ (1ULL << 0) +#define IA32_VMX_EPT_FAULT_WRITE (1ULL << 1) +#define IA32_VMX_EPT_FAULT_EXEC (1ULL << 2) + +#define IA32_VMX_EPT_FAULT_WAS_READABLE (1ULL << 3) +#define IA32_VMX_EPT_FAULT_WAS_WRITABLE (1ULL << 4) +#define IA32_VMX_EPT_FAULT_WAS_EXECABLE (1ULL << 5) + +#define IA32_VMX_MSR_LIST_SIZE_MASK (7ULL << 25) +#define IA32_VMX_CR3_TGT_SIZE_MASK (0x1FFULL << 16) + +#define VMX_SKIP_L1D_FLUSH 2 +#define VMX_L1D_FLUSH_SIZE (64 * 1024) + +/* + * SVM + */ +#define MSR_AMD_VM_CR 0xc0010114 +#define MSR_AMD_VM_HSAVE_PA 0xc0010117 +#define CPUID_AMD_SVM_CAP 0x8000000A +#define AMD_SVM_NESTED_PAGING_CAP (1 << 0) +#define AMD_SVM_VMCB_CLEAN_CAP (1 << 5) +#define AMD_SVM_FLUSH_BY_ASID_CAP (1 << 6) +#define AMD_SVM_DECODE_ASSIST_CAP (1 << 7) +#define AMD_SVMDIS 0x10 + +#define SVM_TLB_CONTROL_FLUSH_NONE 0 +#define SVM_TLB_CONTROL_FLUSH_ALL 1 +#define SVM_TLB_CONTROL_FLUSH_ASID 3 +#define SVM_TLB_CONTROL_FLUSH_ASID_GLB 7 + +#define SVM_CLEANBITS_I (1 << 0) +#define SVM_CLEANBITS_IOPM (1 << 1) +#define SVM_CLEANBITS_ASID (1 << 2) +#define SVM_CLEANBITS_TPR (1 << 3) +#define SVM_CLEANBITS_NP (1 << 4) +#define SVM_CLEANBITS_CR (1 << 5) +#define SVM_CLEANBITS_DR (1 << 6) +#define SVM_CLEANBITS_DT (1 << 7) +#define SVM_CLEANBITS_SEG (1 << 8) +#define SVM_CLEANBITS_CR2 (1 << 9) +#define SVM_CLEANBITS_LBR (1 << 10) +#define SVM_CLEANBITS_AVIC (1 << 11) + +#define SVM_CLEANBITS_ALL \ + (SVM_CLEANBITS_I | SVM_CLEANBITS_IOPM | SVM_CLEANBITS_ASID | \ + SVM_CLEANBITS_TPR | SVM_CLEANBITS_NP | SVM_CLEANBITS_CR | \ + SVM_CLEANBITS_DR | SVM_CLEANBITS_DT | SVM_CLEANBITS_SEG | \ + SVM_CLEANBITS_CR2 | SVM_CLEANBITS_LBR | SVM_CLEANBITS_AVIC ) + +#define SVM_INTR_MISC_V_IGN_TPR 0x10 + +/* + * SVM : VMCB intercepts + */ +#define SVM_INTERCEPT_CR0_READ (1UL << 0) +#define SVM_INTERCEPT_CR1_READ (1UL << 1) +#define SVM_INTERCEPT_CR2_READ (1UL << 2) +#define SVM_INTERCEPT_CR3_READ (1UL << 2) +#define SVM_INTERCEPT_CR4_READ (1UL << 4) +#define SVM_INTERCEPT_CR5_READ (1UL << 5) +#define SVM_INTERCEPT_CR6_READ (1UL << 6) +#define SVM_INTERCEPT_CR7_READ (1UL << 7) +#define SVM_INTERCEPT_CR8_READ (1UL << 8) +#define SVM_INTERCEPT_CR9_READ (1UL << 9) +#define SVM_INTERCEPT_CR10_READ (1UL << 10) +#define SVM_INTERCEPT_CR11_READ (1UL << 11) +#define SVM_INTERCEPT_CR12_READ (1UL << 12) +#define SVM_INTERCEPT_CR13_READ (1UL << 13) +#define SVM_INTERCEPT_CR14_READ (1UL << 14) +#define SVM_INTERCEPT_CR15_READ (1UL << 15) +#define SVM_INTERCEPT_CR0_WRITE (1UL << 16) +#define SVM_INTERCEPT_CR1_WRITE (1UL << 17) +#define SVM_INTERCEPT_CR2_WRITE (1UL << 18) +#define SVM_INTERCEPT_CR3_WRITE (1UL << 19) +#define SVM_INTERCEPT_CR4_WRITE (1UL << 20) +#define SVM_INTERCEPT_CR5_WRITE (1UL << 21) +#define SVM_INTERCEPT_CR6_WRITE (1UL << 22) +#define SVM_INTERCEPT_CR7_WRITE (1UL << 23) +#define SVM_INTERCEPT_CR8_WRITE (1UL << 24) +#define SVM_INTERCEPT_CR9_WRITE (1UL << 25) +#define SVM_INTERCEPT_CR10_WRITE (1UL << 26) +#define SVM_INTERCEPT_CR11_WRITE (1UL << 27) +#define SVM_INTERCEPT_CR12_WRITE (1UL << 28) +#define SVM_INTERCEPT_CR13_WRITE (1UL << 29) +#define SVM_INTERCEPT_CR14_WRITE (1UL << 30) +#define SVM_INTERCEPT_CR15_WRITE (1UL << 31) +#define SVM_INTERCEPT_DR0_READ (1UL << 0) +#define SVM_INTERCEPT_DR1_READ (1UL << 1) +#define SVM_INTERCEPT_DR2_READ (1UL << 2) +#define SVM_INTERCEPT_DR3_READ (1UL << 2) +#define SVM_INTERCEPT_DR4_READ (1UL << 4) +#define SVM_INTERCEPT_DR5_READ (1UL << 5) +#define SVM_INTERCEPT_DR6_READ (1UL << 6) +#define SVM_INTERCEPT_DR7_READ (1UL << 7) +#define SVM_INTERCEPT_DR8_READ (1UL << 8) +#define SVM_INTERCEPT_DR9_READ (1UL << 9) +#define SVM_INTERCEPT_DR10_READ (1UL << 10) +#define SVM_INTERCEPT_DR11_READ (1UL << 11) +#define SVM_INTERCEPT_DR12_READ (1UL << 12) +#define SVM_INTERCEPT_DR13_READ (1UL << 13) +#define SVM_INTERCEPT_DR14_READ (1UL << 14) +#define SVM_INTERCEPT_DR15_READ (1UL << 15) +#define SVM_INTERCEPT_DR0_WRITE (1UL << 16) +#define SVM_INTERCEPT_DR1_WRITE (1UL << 17) +#define SVM_INTERCEPT_DR2_WRITE (1UL << 18) +#define SVM_INTERCEPT_DR3_WRITE (1UL << 19) +#define SVM_INTERCEPT_DR4_WRITE (1UL << 20) +#define SVM_INTERCEPT_DR5_WRITE (1UL << 21) +#define SVM_INTERCEPT_DR6_WRITE (1UL << 22) +#define SVM_INTERCEPT_DR7_WRITE (1UL << 23) +#define SVM_INTERCEPT_DR8_WRITE (1UL << 24) +#define SVM_INTERCEPT_DR9_WRITE (1UL << 25) +#define SVM_INTERCEPT_DR10_WRITE (1UL << 26) +#define SVM_INTERCEPT_DR11_WRITE (1UL << 27) +#define SVM_INTERCEPT_DR12_WRITE (1UL << 28) +#define SVM_INTERCEPT_DR13_WRITE (1UL << 29) +#define SVM_INTERCEPT_DR14_WRITE (1UL << 30) +#define SVM_INTERCEPT_DR15_WRITE (1UL << 31) +#define SVM_INTERCEPT_INTR (1UL << 0) +#define SVM_INTERCEPT_NMI (1UL << 1) +#define SVM_INTERCEPT_SMI (1UL << 2) +#define SVM_INTERCEPT_INIT (1UL << 3) +#define SVM_INTERCEPT_VINTR (1UL << 4) +#define SVM_INTERCEPT_CR0_SEL_WRITE (1UL << 5) +#define SVM_INTERCEPT_IDTR_READ (1UL << 6) +#define SVM_INTERCEPT_GDTR_READ (1UL << 7) +#define SVM_INTERCEPT_LDTR_READ (1UL << 8) +#define SVM_INTERCEPT_TR_READ (1UL << 9) +#define SVM_INTERCEPT_IDTR_WRITE (1UL << 10) +#define SVM_INTERCEPT_GDTR_WRITE (1UL << 11) +#define SVM_INTERCEPT_LDTR_WRITE (1UL << 12) +#define SVM_INTERCEPT_TR_WRITE (1UL << 13) +#define SVM_INTERCEPT_RDTSC (1UL << 14) +#define SVM_INTERCEPT_RDPMC (1UL << 15) +#define SVM_INTERCEPT_PUSHF (1UL << 16) +#define SVM_INTERCEPT_POPF (1UL << 17) +#define SVM_INTERCEPT_CPUID (1UL << 18) +#define SVM_INTERCEPT_RSM (1UL << 19) +#define SVM_INTERCEPT_IRET (1UL << 20) +#define SVM_INTERCEPT_INTN (1UL << 21) +#define SVM_INTERCEPT_INVD (1UL << 22) +#define SVM_INTERCEPT_PAUSE (1UL << 23) +#define SVM_INTERCEPT_HLT (1UL << 24) +#define SVM_INTERCEPT_INVLPG (1UL << 25) +#define SVM_INTERCEPT_INVLPGA (1UL << 26) +#define SVM_INTERCEPT_INOUT (1UL << 27) +#define SVM_INTERCEPT_MSR (1UL << 28) +#define SVM_INTERCEPT_TASK_SWITCH (1UL << 29) +#define SVM_INTERCEPT_FERR_FREEZE (1UL << 30) +#define SVM_INTERCEPT_SHUTDOWN (1UL << 31) +#define SVM_INTERCEPT_VMRUN (1UL << 0) +#define SVM_INTERCEPT_VMMCALL (1UL << 1) +#define SVM_INTERCEPT_VMLOAD (1UL << 2) +#define SVM_INTERCEPT_VMSAVE (1UL << 3) +#define SVM_INTERCEPT_STGI (1UL << 4) +#define SVM_INTERCEPT_CLGI (1UL << 5) +#define SVM_INTERCEPT_SKINIT (1UL << 6) +#define SVM_INTERCEPT_RDTSCP (1UL << 7) +#define SVM_INTERCEPT_ICEBP (1UL << 8) +#define SVM_INTERCEPT_WBINVD (1UL << 9) +#define SVM_INTERCEPT_MONITOR (1UL << 10) +#define SVM_INTERCEPT_MWAIT_UNCOND (1UL << 11) +#define SVM_INTERCEPT_MWAIT_COND (1UL << 12) +#define SVM_INTERCEPT_XSETBV (1UL << 13) +#define SVM_INTERCEPT_EFER_WRITE (1UL << 15) +#define SVM_INTERCEPT_CR0_WRITE_POST (1UL << 16) +#define SVM_INTERCEPT_CR1_WRITE_POST (1UL << 17) +#define SVM_INTERCEPT_CR2_WRITE_POST (1UL << 18) +#define SVM_INTERCEPT_CR3_WRITE_POST (1UL << 19) +#define SVM_INTERCEPT_CR4_WRITE_POST (1UL << 20) +#define SVM_INTERCEPT_CR5_WRITE_POST (1UL << 21) +#define SVM_INTERCEPT_CR6_WRITE_POST (1UL << 22) +#define SVM_INTERCEPT_CR7_WRITE_POST (1UL << 23) +#define SVM_INTERCEPT_CR8_WRITE_POST (1UL << 24) +#define SVM_INTERCEPT_CR9_WRITE_POST (1UL << 25) +#define SVM_INTERCEPT_CR10_WRITE_POST (1UL << 26) +#define SVM_INTERCEPT_CR11_WRITE_POST (1UL << 27) +#define SVM_INTERCEPT_CR12_WRITE_POST (1UL << 28) +#define SVM_INTERCEPT_CR13_WRITE_POST (1UL << 29) +#define SVM_INTERCEPT_CR14_WRITE_POST (1UL << 30) +#define SVM_INTERCEPT_CR15_WRITE_POST (1UL << 31) + +/* + * SME and SEV + */ +#define CPUID_AMD_SEV_CAP 0x8000001F +#define AMD_SME_CAP (1UL << 0) +#define AMD_SEV_CAP (1UL << 1) + +/* + * PAT + */ +#define PATENTRY(n, type) (type << ((n) * 8)) +#define PAT_UC 0x0UL +#define PAT_WC 0x1UL +#define PAT_WT 0x4UL +#define PAT_WP 0x5UL +#define PAT_WB 0x6UL +#define PAT_UCMINUS 0x7UL + +/* + * XSAVE subfeatures (cpuid 0xd, leaf 1) + */ +#define XSAVE_XSAVEOPT 0x01UL +#define XSAVE_XSAVEC 0x02UL +#define XSAVE_XGETBV1 0x04UL +#define XSAVE_XSAVES 0x08UL +#define XSAVE_XFD 0x10UL +#define XSAVE_BITS \ + ("\20" "\01XSAVEOPT" "\02XSAVEC" "\03XGETBV1" "\04XSAVES" "\05XFD" ) + +/* + * Default cr0 and cr4 flags. + */ +#define CR0_DEFAULT (CR0_PE|CR0_PG|CR0_NE|CR0_WP) +#define CR4_DEFAULT (CR4_PAE|CR4_PGE|CR4_PSE|CR4_OSFXSR|CR4_OSXMMEXCPT) \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/spinlock.h b/lib/libc/include/x86_64-openbsd-none/amd64/spinlock.h new file mode 100644 index 000000000000..f3fe78c83412 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/spinlock.h @@ -0,0 +1,10 @@ +/* $OpenBSD: spinlock.h,v 1.3 2017/09/05 02:40:54 guenther Exp $ */ + +#ifndef _MACHINE_SPINLOCK_H_ +#define _MACHINE_SPINLOCK_H_ + +#define _ATOMIC_LOCK_UNLOCKED (0) +#define _ATOMIC_LOCK_LOCKED (1) +typedef int _atomic_lock_t; + +#endif \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/sysarch.h b/lib/libc/include/x86_64-openbsd-none/amd64/sysarch.h new file mode 100644 index 000000000000..aea941c71176 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/sysarch.h @@ -0,0 +1,28 @@ +/* $OpenBSD: sysarch.h,v 1.14 2018/01/07 18:54:44 guenther Exp $ */ +/* $NetBSD: sysarch.h,v 1.1 2003/04/26 18:39:48 fvdl Exp $ */ + +#ifndef _MACHINE_SYSARCH_H_ +#define _MACHINE_SYSARCH_H_ + +/* + * Architecture specific syscalls (amd64) + */ +#define AMD64_IOPL 2 + +struct amd64_iopl_args { + int iopl; +}; + +#ifdef _KERNEL +int amd64_iopl(struct proc *, void *, register_t *); +#else + +#include + +__BEGIN_DECLS +int amd64_iopl(int); +int sysarch(int, void *); +__END_DECLS +#endif + +#endif /* !_MACHINE_SYSARCH_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/tcb.h b/lib/libc/include/x86_64-openbsd-none/amd64/tcb.h new file mode 100644 index 000000000000..1d7d3135dece --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/tcb.h @@ -0,0 +1,53 @@ +/* $OpenBSD: tcb.h,v 1.6 2017/10/13 05:14:02 guenther Exp $ */ + +/* + * Copyright (c) 2011 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TCB_H_ +#define _MACHINE_TCB_H_ + +#ifdef _KERNEL + +void *tcb_get(struct proc *_p); +void tcb_set(struct proc *_p, void *_newtcb); + +#define TCB_GET(p) tcb_get(p) +#define TCB_SET(p, addr) tcb_set(p, addr) + +/* address must be in canonical form; requiring lower-half is okay */ +#define TCB_INVALID(addr) ((u_long)(addr) > 0x00007fffffffffff) + +#else /* _KERNEL */ + +/* ELF TLS ABI calls for big TCB, with static TLS data at negative offsets */ +#define TLS_VARIANT 2 + +/* Read a slot from the TCB */ +static inline void * +__amd64_read_tcb(long offset) +{ + void *val; + __asm__ ("movq %%fs:(%1),%0" : "=r" (val) : "r" (offset)); + return val; +} + +/* Get a pointer to the TCB itself */ +#define TCB_GET() __amd64_read_tcb(0) + +/* Setting the TCB pointer can only be done via syscall, so no TCB_SET() */ + +#endif /* _KERNEL */ +#endif /* _MACHINE_TCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/timetc.h b/lib/libc/include/x86_64-openbsd-none/amd64/timetc.h new file mode 100644 index 000000000000..668058407847 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/timetc.h @@ -0,0 +1,24 @@ +/* $OpenBSD: timetc.h,v 1.3 2022/09/22 04:57:08 robert Exp $ */ +/* + * Copyright (c) 2020 Paul Irofti + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TIMETC_H_ +#define _MACHINE_TIMETC_H_ + +#define TC_TSC_LFENCE 1 +#define TC_TSC_RDTSCP 2 + +#endif /* _MACHINE_TIMETC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/trap.h b/lib/libc/include/x86_64-openbsd-none/amd64/trap.h new file mode 100644 index 000000000000..f8b9fe76338d --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/trap.h @@ -0,0 +1,65 @@ +/* $OpenBSD: trap.h,v 1.6 2025/06/23 11:33:39 bluhm Exp $ */ +/* $NetBSD: trap.h,v 1.4 1994/10/27 04:16:30 cgd Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)trap.h 5.4 (Berkeley) 5/9/91 + */ + +/* + * Trap type values + * also known in trap.c for name strings + */ + +#define T_PRIVINFLT 0 /* privileged instruction */ +#define T_BPTFLT 1 /* breakpoint trap */ +#define T_ARITHTRAP 2 /* arithmetic trap */ +#define T_RESERVED 3 /* reserved fault base */ +#define T_PROTFLT 4 /* protection fault */ +#define T_TRCTRAP 5 /* trace trap */ +#define T_PAGEFLT 6 /* page fault */ +#define T_ALIGNFLT 7 /* alignment fault */ +#define T_DIVIDE 8 /* integer divide fault */ +#define T_NMI 9 /* non-maskable interrupt */ +#define T_OFLOW 10 /* overflow trap */ +#define T_BOUND 11 /* bounds check fault */ +#define T_DNA 12 /* device not available fault */ +#define T_DOUBLEFLT 13 /* double fault */ +#define T_FPOPFLT 14 /* fp coprocessor operand fetch fault (![P]Pro)*/ +#define T_TSSFLT 15 /* invalid tss fault */ +#define T_SEGNPFLT 16 /* segment not present fault */ +#define T_STKFLT 17 /* stack fault */ +#define T_MCA 18 /* machine check ([P]Pro) */ +#define T_XMM 19 /* SSE FP exception */ +#define T_VE 20 /* virtualization exception */ +#define T_CP 21 /* control protection exception */ +#define T_VC 29 /* VMM communication exception */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/tss.h b/lib/libc/include/x86_64-openbsd-none/amd64/tss.h new file mode 100644 index 000000000000..e6679df97802 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/tss.h @@ -0,0 +1,62 @@ +/* $OpenBSD: tss.h,v 1.4 2011/03/23 16:54:34 pirofti Exp $ */ +/* $NetBSD: tss.h,v 1.1 2003/04/26 18:39:49 fvdl Exp $ */ + +/* + * Copyright (c) 2001 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Frank van der Linden for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_TSS_H_ +#define _MACHINE_TSS_H_ + +/* + * TSS structure. Since TSS hw switching is not supported in long + * mode, this is mainly there for the I/O permission map in + * normal processes. + */ + +struct x86_64_tss { + u_int32_t tss_reserved1; + u_int64_t tss_rsp0; + u_int64_t tss_rsp1; + u_int64_t tss_rsp2; + u_int32_t tss_reserved2; + u_int32_t tss_reserved3; + u_int64_t tss_ist[7]; + u_int32_t tss_reserved4; + u_int32_t tss_reserved5; + u_int16_t tss_reserved6; + u_int16_t tss_iobase; +} __packed; + +#endif /* _MACHINE_TSS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/vga_post.h b/lib/libc/include/x86_64-openbsd-none/amd64/vga_post.h new file mode 100644 index 000000000000..bbf947e99103 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/vga_post.h @@ -0,0 +1,43 @@ +/* $NetBSD: vga_post.h,v 1.2 2008/03/29 17:40:22 jmcneill Exp $ */ +/* $OpenBSD: vga_post.h,v 1.2 2011/03/23 16:54:34 pirofti Exp $ */ + +/*- + * Copyright (c) 2007 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_VGA_POST_H_ +#define _MACHINE_VGA_POST_H_ + +#ifdef _KERNEL +struct vga_post; + +struct vga_post *vga_post_init(int, int, int); +void vga_post_free(struct vga_post *); +void vga_post_call(struct vga_post *); +#endif +#endif \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/vmmvar.h b/lib/libc/include/x86_64-openbsd-none/amd64/vmmvar.h new file mode 100644 index 000000000000..03006e307225 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/vmmvar.h @@ -0,0 +1,1075 @@ +/* $OpenBSD: vmmvar.h,v 1.117 2025/09/17 18:37:44 sf Exp $ */ +/* + * Copyright (c) 2014 Mike Larkin + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * CPU capabilities for VMM operation + */ +#ifndef _MACHINE_VMMVAR_H_ +#define _MACHINE_VMMVAR_H_ + +#ifndef _LOCORE + +#define VMM_HV_SIGNATURE "OpenBSDVMM58" + +/* VMX: Basic Exit Reasons */ +#define VMX_EXIT_NMI 0 +#define VMX_EXIT_EXTINT 1 +#define VMX_EXIT_TRIPLE_FAULT 2 +#define VMX_EXIT_INIT 3 +#define VMX_EXIT_SIPI 4 +#define VMX_EXIT_IO_SMI 5 +#define VMX_EXIT_OTHER_SMI 6 +#define VMX_EXIT_INT_WINDOW 7 +#define VMX_EXIT_NMI_WINDOW 8 +#define VMX_EXIT_TASK_SWITCH 9 +#define VMX_EXIT_CPUID 10 +#define VMX_EXIT_GETSEC 11 +#define VMX_EXIT_HLT 12 +#define VMX_EXIT_INVD 13 +#define VMX_EXIT_INVLPG 14 +#define VMX_EXIT_RDPMC 15 +#define VMX_EXIT_RDTSC 16 +#define VMX_EXIT_RSM 17 +#define VMX_EXIT_VMCALL 18 +#define VMX_EXIT_VMCLEAR 19 +#define VMX_EXIT_VMLAUNCH 20 +#define VMX_EXIT_VMPTRLD 21 +#define VMX_EXIT_VMPTRST 22 +#define VMX_EXIT_VMREAD 23 +#define VMX_EXIT_VMRESUME 24 +#define VMX_EXIT_VMWRITE 25 +#define VMX_EXIT_VMXOFF 26 +#define VMX_EXIT_VMXON 27 +#define VMX_EXIT_CR_ACCESS 28 +#define VMX_EXIT_MOV_DR 29 +#define VMX_EXIT_IO 30 +#define VMX_EXIT_RDMSR 31 +#define VMX_EXIT_WRMSR 32 +#define VMX_EXIT_ENTRY_FAILED_GUEST_STATE 33 +#define VMX_EXIT_ENTRY_FAILED_MSR_LOAD 34 +#define VMX_EXIT_MWAIT 36 +#define VMX_EXIT_MTF 37 +#define VMX_EXIT_MONITOR 39 +#define VMX_EXIT_PAUSE 40 +#define VMX_EXIT_ENTRY_FAILED_MCE 41 +#define VMX_EXIT_TPR_BELOW_THRESHOLD 43 +#define VMX_EXIT_APIC_ACCESS 44 +#define VMX_EXIT_VIRTUALIZED_EOI 45 +#define VMX_EXIT_GDTR_IDTR 46 +#define VMX_EXIT_LDTR_TR 47 +#define VMX_EXIT_EPT_VIOLATION 48 +#define VMX_EXIT_EPT_MISCONFIGURATION 49 +#define VMX_EXIT_INVEPT 50 +#define VMX_EXIT_RDTSCP 51 +#define VMX_EXIT_VMX_PREEMPTION_TIMER_EXPIRED 52 +#define VMX_EXIT_INVVPID 53 +#define VMX_EXIT_WBINVD 54 +#define VMX_EXIT_XSETBV 55 +#define VMX_EXIT_APIC_WRITE 56 +#define VMX_EXIT_RDRAND 57 +#define VMX_EXIT_INVPCID 58 +#define VMX_EXIT_VMFUNC 59 +#define VMX_EXIT_RDSEED 61 +#define VMX_EXIT_XSAVES 63 +#define VMX_EXIT_XRSTORS 64 + +#define VM_EXIT_TERMINATED 0xFFFE +#define VM_EXIT_NONE 0xFFFF + +/* + * VMX: Misc defines + */ +#define VMX_MAX_CR3_TARGETS 256 +#define VMX_VMCS_PA_CLEAR 0xFFFFFFFFFFFFFFFFUL + +#endif /* ! _LOCORE */ + +/* + * SVM: Intercept codes (exit reasons) + */ +#define SVM_VMEXIT_CR0_READ 0x00 +#define SVM_VMEXIT_CR1_READ 0x01 +#define SVM_VMEXIT_CR2_READ 0x02 +#define SVM_VMEXIT_CR3_READ 0x03 +#define SVM_VMEXIT_CR4_READ 0x04 +#define SVM_VMEXIT_CR5_READ 0x05 +#define SVM_VMEXIT_CR6_READ 0x06 +#define SVM_VMEXIT_CR7_READ 0x07 +#define SVM_VMEXIT_CR8_READ 0x08 +#define SVM_VMEXIT_CR9_READ 0x09 +#define SVM_VMEXIT_CR10_READ 0x0A +#define SVM_VMEXIT_CR11_READ 0x0B +#define SVM_VMEXIT_CR12_READ 0x0C +#define SVM_VMEXIT_CR13_READ 0x0D +#define SVM_VMEXIT_CR14_READ 0x0E +#define SVM_VMEXIT_CR15_READ 0x0F +#define SVM_VMEXIT_CR0_WRITE 0x10 +#define SVM_VMEXIT_CR1_WRITE 0x11 +#define SVM_VMEXIT_CR2_WRITE 0x12 +#define SVM_VMEXIT_CR3_WRITE 0x13 +#define SVM_VMEXIT_CR4_WRITE 0x14 +#define SVM_VMEXIT_CR5_WRITE 0x15 +#define SVM_VMEXIT_CR6_WRITE 0x16 +#define SVM_VMEXIT_CR7_WRITE 0x17 +#define SVM_VMEXIT_CR8_WRITE 0x18 +#define SVM_VMEXIT_CR9_WRITE 0x19 +#define SVM_VMEXIT_CR10_WRITE 0x1A +#define SVM_VMEXIT_CR11_WRITE 0x1B +#define SVM_VMEXIT_CR12_WRITE 0x1C +#define SVM_VMEXIT_CR13_WRITE 0x1D +#define SVM_VMEXIT_CR14_WRITE 0x1E +#define SVM_VMEXIT_CR15_WRITE 0x1F +#define SVM_VMEXIT_DR0_READ 0x20 +#define SVM_VMEXIT_DR1_READ 0x21 +#define SVM_VMEXIT_DR2_READ 0x22 +#define SVM_VMEXIT_DR3_READ 0x23 +#define SVM_VMEXIT_DR4_READ 0x24 +#define SVM_VMEXIT_DR5_READ 0x25 +#define SVM_VMEXIT_DR6_READ 0x26 +#define SVM_VMEXIT_DR7_READ 0x27 +#define SVM_VMEXIT_DR8_READ 0x28 +#define SVM_VMEXIT_DR9_READ 0x29 +#define SVM_VMEXIT_DR10_READ 0x2A +#define SVM_VMEXIT_DR11_READ 0x2B +#define SVM_VMEXIT_DR12_READ 0x2C +#define SVM_VMEXIT_DR13_READ 0x2D +#define SVM_VMEXIT_DR14_READ 0x2E +#define SVM_VMEXIT_DR15_READ 0x2F +#define SVM_VMEXIT_DR0_WRITE 0x30 +#define SVM_VMEXIT_DR1_WRITE 0x31 +#define SVM_VMEXIT_DR2_WRITE 0x32 +#define SVM_VMEXIT_DR3_WRITE 0x33 +#define SVM_VMEXIT_DR4_WRITE 0x34 +#define SVM_VMEXIT_DR5_WRITE 0x35 +#define SVM_VMEXIT_DR6_WRITE 0x36 +#define SVM_VMEXIT_DR7_WRITE 0x37 +#define SVM_VMEXIT_DR8_WRITE 0x38 +#define SVM_VMEXIT_DR9_WRITE 0x39 +#define SVM_VMEXIT_DR10_WRITE 0x3A +#define SVM_VMEXIT_DR11_WRITE 0x3B +#define SVM_VMEXIT_DR12_WRITE 0x3C +#define SVM_VMEXIT_DR13_WRITE 0x3D +#define SVM_VMEXIT_DR14_WRITE 0x3E +#define SVM_VMEXIT_DR15_WRITE 0x3F +#define SVM_VMEXIT_EXCP0 0x40 +#define SVM_VMEXIT_EXCP1 0x41 +#define SVM_VMEXIT_EXCP2 0x42 +#define SVM_VMEXIT_EXCP3 0x43 +#define SVM_VMEXIT_EXCP4 0x44 +#define SVM_VMEXIT_EXCP5 0x45 +#define SVM_VMEXIT_EXCP6 0x46 +#define SVM_VMEXIT_EXCP7 0x47 +#define SVM_VMEXIT_EXCP8 0x48 +#define SVM_VMEXIT_EXCP9 0x49 +#define SVM_VMEXIT_EXCP10 0x4A +#define SVM_VMEXIT_EXCP11 0x4B +#define SVM_VMEXIT_EXCP12 0x4C +#define SVM_VMEXIT_EXCP13 0x4D +#define SVM_VMEXIT_EXCP14 0x4E +#define SVM_VMEXIT_EXCP15 0x4F +#define SVM_VMEXIT_EXCP16 0x50 +#define SVM_VMEXIT_EXCP17 0x51 +#define SVM_VMEXIT_EXCP18 0x52 +#define SVM_VMEXIT_EXCP19 0x53 +#define SVM_VMEXIT_EXCP20 0x54 +#define SVM_VMEXIT_EXCP21 0x55 +#define SVM_VMEXIT_EXCP22 0x56 +#define SVM_VMEXIT_EXCP23 0x57 +#define SVM_VMEXIT_EXCP24 0x58 +#define SVM_VMEXIT_EXCP25 0x59 +#define SVM_VMEXIT_EXCP26 0x5A +#define SVM_VMEXIT_EXCP27 0x5B +#define SVM_VMEXIT_EXCP28 0x5C +#define SVM_VMEXIT_EXCP29 0x5D +#define SVM_VMEXIT_EXCP30 0x5E +#define SVM_VMEXIT_EXCP31 0x5F +#define SVM_VMEXIT_INTR 0x60 +#define SVM_VMEXIT_NMI 0x61 +#define SVM_VMEXIT_SMI 0x62 +#define SVM_VMEXIT_INIT 0x63 +#define SVM_VMEXIT_VINTR 0x64 +#define SVM_VMEXIT_CR0_SEL_WRITE 0x65 +#define SVM_VMEXIT_IDTR_READ 0x66 +#define SVM_VMEXIT_GDTR_READ 0x67 +#define SVM_VMEXIT_LDTR_READ 0x68 +#define SVM_VMEXIT_TR_READ 0x69 +#define SVM_VMEXIT_IDTR_WRITE 0x6A +#define SVM_VMEXIT_GDTR_WRITE 0x6B +#define SVM_VMEXIT_LDTR_WRITE 0x6C +#define SVM_VMEXIT_TR_WRITE 0x6D +#define SVM_VMEXIT_RDTSC 0x6E +#define SVM_VMEXIT_RDPMC 0x6F +#define SVM_VMEXIT_PUSHF 0x70 +#define SVM_VMEXIT_POPF 0x71 +#define SVM_VMEXIT_CPUID 0x72 +#define SVM_VMEXIT_RSM 0x73 +#define SVM_VMEXIT_IRET 0x74 +#define SVM_VMEXIT_SWINT 0x75 +#define SVM_VMEXIT_INVD 0x76 +#define SVM_VMEXIT_PAUSE 0x77 +#define SVM_VMEXIT_HLT 0x78 +#define SVM_VMEXIT_INVLPG 0x79 +#define SVM_VMEXIT_INVLPGA 0x7A +#define SVM_VMEXIT_IOIO 0x7B +#define SVM_VMEXIT_MSR 0x7C +#define SVM_VMEXIT_TASK_SWITCH 0x7D +#define SVM_VMEXIT_FERR_FREEZE 0x7E +#define SVM_VMEXIT_SHUTDOWN 0x7F +#define SVM_VMEXIT_VMRUN 0x80 +#define SVM_VMEXIT_VMMCALL 0x81 +#define SVM_VMEXIT_VMLOAD 0x82 +#define SVM_VMEXIT_VMSAVE 0x83 +#define SVM_VMEXIT_STGI 0x84 +#define SVM_VMEXIT_CLGI 0x85 +#define SVM_VMEXIT_SKINIT 0x86 +#define SVM_VMEXIT_RDTSCP 0x87 +#define SVM_VMEXIT_ICEBP 0x88 +#define SVM_VMEXIT_WBINVD 0x89 +#define SVM_VMEXIT_MONITOR 0x8A +#define SVM_VMEXIT_MWAIT 0x8B +#define SVM_VMEXIT_MWAIT_CONDITIONAL 0x8C +#define SVM_VMEXIT_XSETBV 0x8D +#define SVM_VMEXIT_EFER_WRITE_TRAP 0x8F +#define SVM_VMEXIT_CR0_WRITE_TRAP 0x90 +#define SVM_VMEXIT_CR1_WRITE_TRAP 0x91 +#define SVM_VMEXIT_CR2_WRITE_TRAP 0x92 +#define SVM_VMEXIT_CR3_WRITE_TRAP 0x93 +#define SVM_VMEXIT_CR4_WRITE_TRAP 0x94 +#define SVM_VMEXIT_CR5_WRITE_TRAP 0x95 +#define SVM_VMEXIT_CR6_WRITE_TRAP 0x96 +#define SVM_VMEXIT_CR7_WRITE_TRAP 0x97 +#define SVM_VMEXIT_CR8_WRITE_TRAP 0x98 +#define SVM_VMEXIT_CR9_WRITE_TRAP 0x99 +#define SVM_VMEXIT_CR10_WRITE_TRAP 0x9A +#define SVM_VMEXIT_CR11_WRITE_TRAP 0x9B +#define SVM_VMEXIT_CR12_WRITE_TRAP 0x9C +#define SVM_VMEXIT_CR13_WRITE_TRAP 0x9D +#define SVM_VMEXIT_CR14_WRITE_TRAP 0x9E +#define SVM_VMEXIT_CR15_WRITE_TRAP 0x9F +#define SVM_VMEXIT_NPF 0x400 +#define SVM_AVIC_INCOMPLETE_IPI 0x401 +#define SVM_AVIC_NOACCEL 0x402 +#define SVM_VMEXIT_VMGEXIT 0x403 +#define SVM_VMEXIT_INVALID -1 + +/* + * Additional VMEXIT codes used in SEV-ES/SNP in the GHCB + */ +#define SEV_VMGEXIT_MMIO_READ 0x80000001 +#define SEV_VMGEXIT_MMIO_WRITE 0x80000002 + +#ifndef _LOCORE + +/* + * Exception injection vectors (these correspond to the CPU exception types + * defined in the SDM.) + */ +#define VMM_EX_DE 0 /* Divide Error #DE */ +#define VMM_EX_DB 1 /* Debug Exception #DB */ +#define VMM_EX_NMI 2 /* NMI */ +#define VMM_EX_BP 3 /* Breakpoint #BP */ +#define VMM_EX_OF 4 /* Overflow #OF */ +#define VMM_EX_BR 5 /* Bound range exceeded #BR */ +#define VMM_EX_UD 6 /* Undefined opcode #UD */ +#define VMM_EX_NM 7 /* Device not available #NM */ +#define VMM_EX_DF 8 /* Double fault #DF */ +#define VMM_EX_CP 9 /* Coprocessor segment overrun (unused) */ +#define VMM_EX_TS 10 /* Invalid TSS #TS */ +#define VMM_EX_NP 11 /* Segment not present #NP */ +#define VMM_EX_SS 12 /* Stack segment fault #SS */ +#define VMM_EX_GP 13 /* General protection #GP */ +#define VMM_EX_PF 14 /* Page fault #PF */ +#define VMM_EX_MF 16 /* x87 FPU floating point error #MF */ +#define VMM_EX_AC 17 /* Alignment check #AC */ +#define VMM_EX_MC 18 /* Machine check #MC */ +#define VMM_EX_XM 19 /* SIMD floating point exception #XM */ +#define VMM_EX_VE 20 /* Virtualization exception #VE */ + +enum { + VEI_DIR_OUT, + VEI_DIR_IN +}; + +enum { + VEE_FAULT_INVALID = 0, + VEE_FAULT_HANDLED, + VEE_FAULT_MMIO_ASSIST, + VEE_FAULT_PROTECT, +}; + +enum { + VMM_CPU_MODE_REAL, + VMM_CPU_MODE_PROT, + VMM_CPU_MODE_PROT32, + VMM_CPU_MODE_COMPAT, + VMM_CPU_MODE_LONG, + VMM_CPU_MODE_UNKNOWN, +}; + +struct vmm_softc_md { + /* Capabilities */ + uint32_t nr_rvi_cpus; /* [I] */ + uint32_t nr_ept_cpus; /* [I] */ + uint8_t pkru_enabled; /* [I] */ +}; + +/* + * vm exit data + * vm_exit_inout : describes an IN/OUT exit + */ +struct vm_exit_inout { + uint8_t vei_size; /* Size of access */ + uint8_t vei_dir; /* Direction */ + uint8_t vei_rep; /* REP prefix? */ + uint8_t vei_string; /* string variety? */ + uint8_t vei_encoding; /* operand encoding */ + uint16_t vei_port; /* port */ + uint32_t vei_data; /* data */ + uint8_t vei_insn_len; /* Count of instruction bytes */ +}; + +/* + * vm_exit_eptviolation : describes an EPT VIOLATION exit + */ +struct vm_exit_eptviolation { + uint8_t vee_fault_type; /* type of vm exit */ + uint8_t vee_insn_info; /* bitfield */ +#define VEE_LEN_VALID 0x1 /* vee_insn_len is valid */ +#define VEE_BYTES_VALID 0x2 /* vee_insn_bytes is valid */ + uint8_t vee_insn_len; /* [VMX] instruction length */ + uint8_t vee_insn_bytes[15]; /* [SVM] bytes at {R,E,}IP */ +}; + +/* + * struct vcpu_inject_event : describes an exception or interrupt to inject. + */ +struct vcpu_inject_event { + uint8_t vie_vector; /* Exception or interrupt vector. */ + uint32_t vie_errorcode; /* Optional error code. */ + uint8_t vie_type; +#define VCPU_INJECT_NONE 0 +#define VCPU_INJECT_INTR 1 /* External hardware interrupt. */ +#define VCPU_INJECT_EX 2 /* HW or SW Exception */ +#define VCPU_INJECT_NMI 3 /* Non-maskable Interrupt */ +}; + +/* + * struct vcpu_segment_info + * + * Describes a segment + selector set, used in constructing the initial vcpu + * register content + */ +struct vcpu_segment_info { + uint16_t vsi_sel; + uint32_t vsi_limit; + uint32_t vsi_ar; + uint64_t vsi_base; +}; + +/* The GPRS are ordered to assist instruction decode. */ +#define VCPU_REGS_RAX 0 +#define VCPU_REGS_RCX 1 +#define VCPU_REGS_RDX 2 +#define VCPU_REGS_RBX 3 +#define VCPU_REGS_RSP 4 +#define VCPU_REGS_RBP 5 +#define VCPU_REGS_RSI 6 +#define VCPU_REGS_RDI 7 +#define VCPU_REGS_R8 8 +#define VCPU_REGS_R9 9 +#define VCPU_REGS_R10 10 +#define VCPU_REGS_R11 11 +#define VCPU_REGS_R12 12 +#define VCPU_REGS_R13 13 +#define VCPU_REGS_R14 14 +#define VCPU_REGS_R15 15 +#define VCPU_REGS_RIP 16 +#define VCPU_REGS_RFLAGS 17 +#define VCPU_REGS_NGPRS (VCPU_REGS_RFLAGS + 1) + +#define VCPU_REGS_CR0 0 +#define VCPU_REGS_CR2 1 +#define VCPU_REGS_CR3 2 +#define VCPU_REGS_CR4 3 +#define VCPU_REGS_CR8 4 +#define VCPU_REGS_XCR0 5 +#define VCPU_REGS_PDPTE0 6 +#define VCPU_REGS_PDPTE1 7 +#define VCPU_REGS_PDPTE2 8 +#define VCPU_REGS_PDPTE3 9 +#define VCPU_REGS_NCRS (VCPU_REGS_PDPTE3 + 1) + +#define VCPU_REGS_ES 0 +#define VCPU_REGS_CS 1 +#define VCPU_REGS_SS 2 +#define VCPU_REGS_DS 3 +#define VCPU_REGS_FS 4 +#define VCPU_REGS_GS 5 +#define VCPU_REGS_LDTR 6 +#define VCPU_REGS_TR 7 +#define VCPU_REGS_NSREGS (VCPU_REGS_TR + 1) + +#define VCPU_REGS_EFER 0 +#define VCPU_REGS_STAR 1 +#define VCPU_REGS_LSTAR 2 +#define VCPU_REGS_CSTAR 3 +#define VCPU_REGS_SFMASK 4 +#define VCPU_REGS_KGSBASE 5 +#define VCPU_REGS_MISC_ENABLE 6 +#define VCPU_REGS_NMSRS (VCPU_REGS_MISC_ENABLE + 1) + +#define VCPU_REGS_DR0 0 +#define VCPU_REGS_DR1 1 +#define VCPU_REGS_DR2 2 +#define VCPU_REGS_DR3 3 +#define VCPU_REGS_DR6 4 +#define VCPU_REGS_DR7 5 +#define VCPU_REGS_NDRS (VCPU_REGS_DR7 + 1) + +struct vcpu_reg_state { + uint64_t vrs_gprs[VCPU_REGS_NGPRS]; + uint64_t vrs_crs[VCPU_REGS_NCRS]; + uint64_t vrs_msrs[VCPU_REGS_NMSRS]; + uint64_t vrs_drs[VCPU_REGS_NDRS]; + struct vcpu_segment_info vrs_sregs[VCPU_REGS_NSREGS]; + struct vcpu_segment_info vrs_gdtr; + struct vcpu_segment_info vrs_idtr; +}; + +#define VCPU_HOST_REGS_EFER 0 +#define VCPU_HOST_REGS_STAR 1 +#define VCPU_HOST_REGS_LSTAR 2 +#define VCPU_HOST_REGS_CSTAR 3 +#define VCPU_HOST_REGS_SFMASK 4 +#define VCPU_HOST_REGS_KGSBASE 5 +#define VCPU_HOST_REGS_MISC_ENABLE 6 +#define VCPU_HOST_REGS_NMSRS (VCPU_HOST_REGS_MISC_ENABLE + 1) + +/* + * struct vm_exit + * + * Contains VM exit information communicated to vmd(8). This information is + * gathered by vmm(4) from the CPU on each exit that requires help from vmd. + */ +struct vm_exit { + union { + struct vm_exit_inout vei; /* IN/OUT exit */ + struct vm_exit_eptviolation vee; /* EPT VIOLATION exit*/ + }; + + struct vcpu_reg_state vrs; + int cpl; +}; + +struct vm_intr_params { + /* Input parameters to VMM_IOC_INTR */ + uint32_t vip_vm_id; + uint32_t vip_vcpu_id; + uint16_t vip_intr; +}; + +#define VM_RWREGS_GPRS 0x1 /* read/write GPRs */ +#define VM_RWREGS_SREGS 0x2 /* read/write segment registers */ +#define VM_RWREGS_CRS 0x4 /* read/write CRs */ +#define VM_RWREGS_MSRS 0x8 /* read/write MSRs */ +#define VM_RWREGS_DRS 0x10 /* read/write DRs */ +#define VM_RWREGS_ALL (VM_RWREGS_GPRS | VM_RWREGS_SREGS | VM_RWREGS_CRS | \ + VM_RWREGS_MSRS | VM_RWREGS_DRS) + +struct vm_rwregs_params { + /* + * Input/output parameters to VMM_IOC_READREGS / + * VMM_IOC_WRITEREGS + */ + uint32_t vrwp_vm_id; + uint32_t vrwp_vcpu_id; + uint64_t vrwp_mask; + struct vcpu_reg_state vrwp_regs; +}; + +/* IOCTL definitions */ +#define VMM_IOC_INTR _IOW('V', 6, struct vm_intr_params) /* Intr pending */ + +/* CPUID masks */ +/* + * clone host capabilities minus: + * debug store (CPUIDECX_DTES64, CPUIDECX_DSCPL, CPUID_DS) + * monitor/mwait (CPUIDECX_MWAIT, CPUIDECX_MWAITX) + * vmx/svm (CPUIDECX_VMX, CPUIDECX_SVM) + * smx (CPUIDECX_SMX) + * speedstep (CPUIDECX_EST) + * thermal (CPUIDECX_TM2, CPUID_ACPI, CPUID_TM) + * context id (CPUIDECX_CNXTID) + * machine check (CPUID_MCE, CPUID_MCA) + * silicon debug (CPUIDECX_SDBG) + * xTPR (CPUIDECX_XTPR) + * perf/debug (CPUIDECX_PDCM) + * pcid (CPUIDECX_PCID) + * direct cache access (CPUIDECX_DCA) + * x2APIC (CPUIDECX_X2APIC) + * apic deadline (CPUIDECX_DEADLINE) + * apic (CPUID_APIC) + * psn (CPUID_PSN) + * self snoop (CPUID_SS) + * hyperthreading (CPUID_HTT) + * pending break enabled (CPUID_PBE) + * MTRR (CPUID_MTRR) + * Speculative execution control features (AMD) + */ +#define VMM_CPUIDECX_MASK ~(CPUIDECX_EST | CPUIDECX_TM2 | CPUIDECX_MWAIT | \ + CPUIDECX_PDCM | CPUIDECX_VMX | CPUIDECX_DTES64 | \ + CPUIDECX_DSCPL | CPUIDECX_SMX | CPUIDECX_CNXTID | \ + CPUIDECX_SDBG | CPUIDECX_XTPR | CPUIDECX_PCID | \ + CPUIDECX_DCA | CPUIDECX_X2APIC | CPUIDECX_DEADLINE) +#define VMM_ECPUIDECX_MASK ~(CPUIDECX_SVM | CPUIDECX_MWAITX) +#define VMM_CPUIDEDX_MASK ~(CPUID_ACPI | CPUID_TM | \ + CPUID_HTT | CPUID_DS | CPUID_APIC | \ + CPUID_PSN | CPUID_SS | CPUID_PBE | \ + CPUID_MTRR | CPUID_MCE | CPUID_MCA) +#define VMM_AMDSPEC_EBX_MASK ~(CPUIDEBX_IBPB | CPUIDEBX_IBRS | \ + CPUIDEBX_STIBP | CPUIDEBX_IBRS_ALWAYSON | CPUIDEBX_STIBP_ALWAYSON | \ + CPUIDEBX_IBRS_PREF | CPUIDEBX_SSBD | CPUIDEBX_VIRT_SSBD | \ + CPUIDEBX_SSBD_NOTREQ) + +/* This mask is an include list for bits we want to expose */ +#define VMM_APMI_EDX_INCLUDE_MASK (CPUIDEDX_ITSC) + +/* + * SEFF flags - copy from host minus: + * TSC_ADJUST (SEFF0EBX_TSC_ADJUST) + * SGX (SEFF0EBX_SGX) + * HLE (SEFF0EBX_HLE) + * INVPCID (SEFF0EBX_INVPCID) + * RTM (SEFF0EBX_RTM) + * PQM (SEFF0EBX_PQM) + * AVX512F (SEFF0EBX_AVX512F) + * AVX512DQ (SEFF0EBX_AVX512DQ) + * AVX512IFMA (SEFF0EBX_AVX512IFMA) + * AVX512PF (SEFF0EBX_AVX512PF) + * AVX512ER (SEFF0EBX_AVX512ER) + * AVX512CD (SEFF0EBX_AVX512CD) + * AVX512BW (SEFF0EBX_AVX512BW) + * AVX512VL (SEFF0EBX_AVX512VL) + * MPX (SEFF0EBX_MPX) + * PCOMMIT (SEFF0EBX_PCOMMIT) + * PT (SEFF0EBX_PT) + */ +#define VMM_SEFF0EBX_MASK ~(SEFF0EBX_TSC_ADJUST | SEFF0EBX_SGX | \ + SEFF0EBX_HLE | SEFF0EBX_INVPCID | \ + SEFF0EBX_RTM | SEFF0EBX_PQM | SEFF0EBX_MPX | \ + SEFF0EBX_PCOMMIT | SEFF0EBX_PT | \ + SEFF0EBX_AVX512F | SEFF0EBX_AVX512DQ | \ + SEFF0EBX_AVX512IFMA | SEFF0EBX_AVX512PF | \ + SEFF0EBX_AVX512ER | SEFF0EBX_AVX512CD | \ + SEFF0EBX_AVX512BW | SEFF0EBX_AVX512VL) + +/* ECX mask contains the bits to include */ +#define VMM_SEFF0ECX_MASK (SEFF0ECX_UMIP) + +/* EDX mask contains the bits to include */ +#define VMM_SEFF0EDX_MASK (SEFF0EDX_MD_CLEAR) + +/* + * Extended function flags - copy from host minus: + * 0x80000001 EDX:RDTSCP Support + */ +#define VMM_FEAT_EFLAGS_MASK ~(CPUID_RDTSCP) + +/* + * CPUID[0x4] deterministic cache info + */ +#define VMM_CPUID4_CACHE_TOPOLOGY_MASK 0x3FF + +#ifdef _KERNEL + +#define VMX_FAIL_LAUNCH_UNKNOWN 1 +#define VMX_FAIL_LAUNCH_INVALID_VMCS 2 +#define VMX_FAIL_LAUNCH_VALID_VMCS 3 + +/* MSR bitmap manipulation macros */ +#define VMX_MSRIDX(m) ((m) / 8) +#define VMX_MSRBIT(m) (1 << (m) % 8) + +#define SVM_MSRIDX(m) ((m) / 4) +#define SVM_MSRBIT_R(m) (1 << (((m) % 4) * 2)) +#define SVM_MSRBIT_W(m) (1 << (((m) % 4) * 2 + 1)) + +enum { + VMM_MODE_UNKNOWN, + VMM_MODE_EPT, + VMM_MODE_RVI +}; + +enum { + VMM_MEM_TYPE_REGULAR, + VMM_MEM_TYPE_MMIO, + VMM_MEM_TYPE_UNKNOWN +}; + +/* Forward declarations */ +struct vm; +struct vm_create_params; + +/* + * Implementation-specific cpu state + */ + +struct vmcb_segment { + uint16_t vs_sel; /* 000h */ + uint16_t vs_attr; /* 002h */ + uint32_t vs_lim; /* 004h */ + uint64_t vs_base; /* 008h */ +}; + +#define SVM_ENABLE_NP (1ULL << 0) +#define SVM_ENABLE_SEV (1ULL << 1) +#define SVM_SEVES_ENABLE (1ULL << 2) + +#define SMV_GUEST_INTR_MASK (1ULL << 1) + +#define SVM_LBRVIRT_ENABLE (1ULL << 0) + +struct vmcb { + union { + struct { + uint32_t v_cr_rw; /* 000h */ + uint32_t v_dr_rw; /* 004h */ + uint32_t v_excp; /* 008h */ + uint32_t v_intercept1; /* 00Ch */ + uint32_t v_intercept2; /* 010h */ + uint8_t v_pad1[0x28]; /* 014h-03Bh */ + uint16_t v_pause_thr; /* 03Ch */ + uint16_t v_pause_ct; /* 03Eh */ + uint64_t v_iopm_pa; /* 040h */ + uint64_t v_msrpm_pa; /* 048h */ + uint64_t v_tsc_offset; /* 050h */ + uint32_t v_asid; /* 058h */ + uint8_t v_tlb_control; /* 05Ch */ + uint8_t v_pad2[0x3]; /* 05Dh-05Fh */ + uint8_t v_tpr; /* 060h */ + uint8_t v_irq; /* 061h */ + uint8_t v_intr_misc; /* 062h */ + uint8_t v_intr_masking; /* 063h */ + uint8_t v_intr_vector; /* 064h */ + uint8_t v_pad3[0x3]; /* 065h-067h */ + uint64_t v_intr_shadow; /* 068h */ + uint64_t v_exitcode; /* 070h */ + uint64_t v_exitinfo1; /* 078h */ + uint64_t v_exitinfo2; /* 080h */ + uint64_t v_exitintinfo; /* 088h */ + uint64_t v_np_enable; /* 090h */ + uint64_t v_avic_apic_bar; /* 098h */ + uint64_t v_ghcb_gpa; /* 0A0h */ + uint64_t v_eventinj; /* 0A8h */ + uint64_t v_n_cr3; /* 0B0h */ + uint64_t v_lbr_virt_enable; /* 0B8h */ + uint64_t v_vmcb_clean_bits; /* 0C0h */ + uint64_t v_nrip; /* 0C8h */ + uint8_t v_n_bytes_fetched; /* 0D0h */ + uint8_t v_guest_ins_bytes[0xf]; /* 0D1h-0DFh */ + uint64_t v_avic_apic_back_page; /* 0E0h */ + uint64_t v_pad5; /* 0E8h-0EFh */ + uint64_t v_avic_logical_table; /* 0F0h */ + uint64_t v_avic_phys; /* 0F8h */ + uint64_t v_pad12; /* 100h */ + uint64_t v_vmsa_pa; /* 108h */ + + }; + uint8_t vmcb_control[0x400]; + }; + + union { + struct { + /* Offsets here are relative to start of VMCB SSA */ + struct vmcb_segment v_es; /* 000h */ + struct vmcb_segment v_cs; /* 010h */ + struct vmcb_segment v_ss; /* 020h */ + struct vmcb_segment v_ds; /* 030h */ + struct vmcb_segment v_fs; /* 040h */ + struct vmcb_segment v_gs; /* 050h */ + struct vmcb_segment v_gdtr; /* 060h */ + struct vmcb_segment v_ldtr; /* 070h */ + struct vmcb_segment v_idtr; /* 080h */ + struct vmcb_segment v_tr; /* 090h */ + uint8_t v_pad6[0x2B]; /* 0A0h-0CAh */ + uint8_t v_cpl; /* 0CBh */ + uint32_t v_pad7; /* 0CCh-0CFh */ + uint64_t v_efer; /* 0D0h */ + uint8_t v_pad8[0x70]; /* 0D8h-147h */ + uint64_t v_cr4; /* 148h */ + uint64_t v_cr3; /* 150h */ + uint64_t v_cr0; /* 158h */ + uint64_t v_dr7; /* 160h */ + uint64_t v_dr6; /* 168h */ + uint64_t v_rflags; /* 170h */ + uint64_t v_rip; /* 178h */ + uint64_t v_pad9[0xB]; /* 180h-1D7h */ + uint64_t v_rsp; /* 1D8h */ + uint64_t v_pad10[0x3]; /* 1E0h-1F7h */ + uint64_t v_rax; /* 1F8h */ + uint64_t v_star; /* 200h */ + uint64_t v_lstar; /* 208h */ + uint64_t v_cstar; /* 210h */ + uint64_t v_sfmask; /* 218h */ + uint64_t v_kgsbase; /* 220h */ + uint64_t v_sysenter_cs; /* 228h */ + uint64_t v_sysenter_esp; /* 230h */ + uint64_t v_sysenter_eip; /* 238h */ + uint64_t v_cr2; /* 240h */ + uint64_t v_pad11[0x4]; /* 248h-267h */ + uint64_t v_g_pat; /* 268h */ + uint64_t v_dbgctl; /* 270h */ + uint64_t v_br_from; /* 278h */ + uint64_t v_br_to; /* 280h */ + uint64_t v_lastexcpfrom; /* 288h */ + uint64_t v_lastexcpto; /* 290h */ + }; + uint8_t vmcb_layout[PAGE_SIZE - 0x400]; + }; +}; + +struct vmsa { + struct vmcb_segment v_es; /* 000h */ + struct vmcb_segment v_cs; /* 010h */ + struct vmcb_segment v_ss; /* 020h */ + struct vmcb_segment v_ds; /* 030h */ + struct vmcb_segment v_fs; /* 040h */ + struct vmcb_segment v_gs; /* 050h */ + struct vmcb_segment v_gdtr; /* 060h */ + struct vmcb_segment v_ldtr; /* 070h */ + struct vmcb_segment v_idtr; /* 080h */ + struct vmcb_segment v_tr; /* 090h */ + uint64_t v_pl0_ssp; /* 0A0h */ + uint64_t v_pl1_ssp; /* 0A8h */ + uint64_t v_pl2_ssp; /* 0B0h */ + uint64_t v_pl3_ssp; /* 0B8h */ + uint64_t v_u_cet; /* 0C0h */ + uint8_t v_pad1[0x2]; /* 0C8h-0C9h */ + uint8_t v_vmpl; /* 0CAh */ + uint8_t v_cpl; /* 0CBh */ + uint8_t v_pad2[0x4]; /* 0CCh-0CFh */ + uint64_t v_efer; /* 0D0h */ + uint8_t v_pad3[0x68]; /* 0D8h-13Fh */ + uint64_t v_xss; /* 140h */ + uint64_t v_cr4; /* 148h */ + uint64_t v_cr3; /* 150h */ + uint64_t v_cr0; /* 158h */ + uint64_t v_dr7; /* 160h */ + uint64_t v_dr6; /* 168h */ + uint64_t v_rflags; /* 170h */ + uint64_t v_rip; /* 178h */ + uint64_t v_dr0; /* 180h */ + uint64_t v_dr1; /* 188h */ + uint64_t v_dr2; /* 190h */ + uint64_t v_dr3; /* 198h */ + uint64_t v_dr0_addr_msk; /* 1A0h */ + uint64_t v_dr1_addr_msk; /* 1A8h */ + uint64_t v_dr2_addr_msk; /* 1B0h */ + uint64_t v_dr3_addr_msk; /* 1B8h */ + uint8_t v_pad4[0x18]; /* 1C0h-1D7h */ + uint64_t v_rsp; /* 1D8h */ + uint64_t v_s_cet; /* 1E0h */ + uint64_t v_ssp; /* 1E8h */ + uint64_t v_isst_addr; /* 1F0h */ + uint64_t v_rax; /* 1F8h */ + uint64_t v_star; /* 200h */ + uint64_t v_lstar; /* 208h */ + uint64_t v_cstar; /* 210h */ + uint64_t v_sfmask; /* 218h */ + uint64_t v_kgsbase; /* 220h */ + uint64_t v_sysenter_cs; /* 228h */ + uint64_t v_sysenter_esp; /* 230h */ + uint64_t v_sysenter_eip; /* 238h */ + uint64_t v_cr2; /* 240h */ + uint8_t v_pad5[0x20]; /* 248h-267h */ + uint64_t v_g_pat; /* 268h */ + uint64_t v_dbgctl; /* 270h */ + uint64_t v_br_from; /* 278h */ + uint64_t v_br_to; /* 280h */ + uint64_t v_lastexcpfrom; /* 288h */ + uint64_t v_lastexcpto; /* 290h */ + uint8_t v_pad6[0x48]; /* 298h-2DFh */ + uint8_t v_pad7[0x8]; /* 2E0h-2E7h */ + uint32_t v_pkru; /* 2E8h */ + uint32_t v_tsc_aux; /* 2ECh */ + uint64_t v_gst_tsc_scale;/* 2F0h */ + uint64_t v_gst_tsc_off; /* 2F8h */ + uint64_t v_reg_prot_nce; /* 300h */ + uint64_t v_rcx; /* 308h */ + uint64_t v_rdx; /* 310h */ + uint64_t v_rbx; /* 318h */ + uint64_t v_pad8; /* 320h */ + uint64_t v_rbp; /* 328h */ + uint64_t v_rsi; /* 330h */ + uint64_t v_rdi; /* 338h */ + uint64_t v_r8; /* 340h */ + uint64_t v_r9; /* 348h */ + uint64_t v_r10; /* 350h */ + uint64_t v_r11; /* 358h */ + uint64_t v_r12; /* 360h */ + uint64_t v_r13; /* 368h */ + uint64_t v_r14; /* 370h */ + uint64_t v_r15; /* 378h */ + uint8_t v_pad9[0x10]; /* 380h-38Fh */ + uint64_t v_gst_exitinfo1;/* 390h */ + uint64_t v_gst_exitinfo2;/* 398h */ + uint64_t v_gst_exitiinfo;/* 3A0h */ + uint64_t v_gst_nrip; /* 3A8h */ + uint64_t v_sev_features; /* 3B0h */ + uint64_t v_intr_ctrl; /* 3B8h */ + uint64_t v_gst_exitcode; /* 3C0h */ + uint64_t v_virtual_tom; /* 3C8h */ + uint64_t v_tlb_id; /* 3D0h */ + uint64_t v_pcup_id; /* 3D8h */ + uint64_t v_eventinj; /* 3E0h */ + uint64_t v_xcr0; /* 3E8h */ + uint8_t v_pad10[0x10]; /* 3F0h-3FFh */ + uint64_t v_x87_dp; /* 400h */ + uint32_t v_mxcsr; /* 408h */ + uint16_t v_x87_ftw; /* 40Ch */ + uint16_t v_x87_fsw; /* 40Eh */ + uint16_t v_x87_fcw; /* 410h */ + uint16_t v_x87_fop; /* 412h */ + uint16_t v_x87_ds; /* 414h */ + uint16_t v_x87_cs; /* 416h */ + uint64_t v_x87_rip; /* 418h */ + uint8_t v_fp_x87[0x50]; /* 420h-46Fh */ + uint8_t v_fp_xmm[0x100];/* 470h-56Fh */ + uint8_t v_fp_ymm[0x100];/* 570h-66fh */ + uint8_t v_lbr_st[0x100];/* 670h-76Fh */ + uint64_t v_lbr_select; /* 770h */ + uint64_t v_ibs_fetch_ctl;/* 778h */ + uint64_t v_ibs_fetch_la; /* 780h */ + uint64_t v_ibs_op_ctl; /* 788h */ + uint64_t v_ibs_op_rip; /* 790h */ + uint64_t v_ibs_op_data; /* 798h */ + uint64_t v_ibs_op_data2; /* 7A0h */ + uint64_t v_ibs_op_data3; /* 7A8h */ + uint64_t v_ibs_dc_la; /* 7B0h */ + uint64_t v_ibstgt_rip; /* 7B8h */ + uint64_t v_ic_ibs_xtd_ct;/* 7C0h */ +}; + +/* + * With SEV-ES the host save area (HSA) has the same layout as the + * VMSA. However, it has the offset 0x400 into the HSA page. + * See AMD APM Vol 2, Appendix B. + */ +#define SVM_HSA_OFFSET 0x400 + +struct vmcs { + uint32_t vmcs_revision; +}; + +struct vmx_invvpid_descriptor { + uint64_t vid_vpid; + uint64_t vid_addr; +}; + +struct vmx_invept_descriptor { + uint64_t vid_eptp; + uint64_t vid_reserved; +}; + +struct vmx_msr_store { + uint64_t vms_index; + uint64_t vms_data; +}; + +/* + * Storage for guest registers not preserved in VMCS and various exit + * information. + * + * Note that vmx/svm_enter_guest depend on the layout of this struct for + * field access. + */ +struct vcpu_gueststate { + /* %rsi should be first */ + uint64_t vg_rsi; /* 0x00 */ + uint64_t vg_rax; /* 0x08 */ + uint64_t vg_rbx; /* 0x10 */ + uint64_t vg_rcx; /* 0x18 */ + uint64_t vg_rdx; /* 0x20 */ + uint64_t vg_rdi; /* 0x28 */ + uint64_t vg_rbp; /* 0x30 */ + uint64_t vg_r8; /* 0x38 */ + uint64_t vg_r9; /* 0x40 */ + uint64_t vg_r10; /* 0x48 */ + uint64_t vg_r11; /* 0x50 */ + uint64_t vg_r12; /* 0x58 */ + uint64_t vg_r13; /* 0x60 */ + uint64_t vg_r14; /* 0x68 */ + uint64_t vg_r15; /* 0x70 */ + uint64_t vg_cr2; /* 0x78 */ + uint64_t vg_rip; /* 0x80 */ + uint32_t vg_exit_reason; /* 0x88 */ + uint64_t vg_rflags; /* 0x90 */ + uint64_t vg_xcr0; /* 0x98 */ + /* + * Debug registers + * - %dr4/%dr5 are aliased to %dr6/%dr7 (or cause #DE) + * - %dr7 is saved automatically in the VMCS + */ + uint64_t vg_dr0; /* 0xa0 */ + uint64_t vg_dr1; /* 0xa8 */ + uint64_t vg_dr2; /* 0xb0 */ + uint64_t vg_dr3; /* 0xb8 */ + uint64_t vg_dr6; /* 0xc0 */ +}; + +/* + * Virtual CPU + * + * Methods used to vcpu struct members: + * a atomic operations + * I immutable operations + * K kernel lock + * r reference count + * v vcpu rwlock + * V vm struct's vcpu list lock (vm_vcpu_lock) + */ +struct vcpu { + /* + * Guest FPU state - this must remain as the first member of the struct + * to ensure 64-byte alignment (set up during vcpu_pool init) + */ + struct savefpu vc_g_fpu; /* [v] */ + + /* VMCS / VMCB pointer */ + vaddr_t vc_control_va; /* [I] */ + paddr_t vc_control_pa; /* [I] */ + + /* VLAPIC pointer */ + vaddr_t vc_vlapic_va; /* [I] */ + uint64_t vc_vlapic_pa; /* [I] */ + + /* MSR bitmap address */ + vaddr_t vc_msr_bitmap_va; /* [I] */ + uint64_t vc_msr_bitmap_pa; /* [I] */ + + struct vm *vc_parent; /* [I] */ + uint32_t vc_id; /* [I] */ + uint16_t vc_vpid; /* [I] */ + u_int vc_state; /* [a] */ + SLIST_ENTRY(vcpu) vc_vcpu_link; /* [V] */ + + uint8_t vc_virt_mode; /* [I] */ + + struct rwlock vc_lock; + + struct cpu_info *vc_curcpu; /* [a] */ + struct cpu_info *vc_last_pcpu; /* [v] */ + struct vm_exit vc_exit; /* [v] */ + + uint16_t vc_intr; /* [v] */ + uint8_t vc_irqready; /* [v] */ + + uint8_t vc_fpuinited; /* [v] */ + + uint64_t vc_h_xcr0; /* [v] */ + + struct vcpu_gueststate vc_gueststate; /* [v] */ + struct vcpu_inject_event vc_inject; /* [v] */ + + uint32_t vc_pvclock_version; /* [v] */ + paddr_t vc_pvclock_system_gpa; /* [v] */ + uint32_t vc_pvclock_system_tsc_mul; /* [v] */ + + /* Shadowed MSRs */ + uint64_t vc_shadow_pat; /* [v] */ + + /* Userland Protection Keys */ + uint32_t vc_pkru; /* [v] */ + + /* VMX only (all requiring [v]) */ + uint64_t vc_vmx_basic; + uint64_t vc_vmx_entry_ctls; + uint64_t vc_vmx_true_entry_ctls; + uint64_t vc_vmx_exit_ctls; + uint64_t vc_vmx_true_exit_ctls; + uint64_t vc_vmx_pinbased_ctls; + uint64_t vc_vmx_true_pinbased_ctls; + uint64_t vc_vmx_procbased_ctls; + uint64_t vc_vmx_true_procbased_ctls; + uint64_t vc_vmx_procbased2_ctls; + vaddr_t vc_vmx_msr_exit_save_va; + paddr_t vc_vmx_msr_exit_save_pa; + vaddr_t vc_vmx_msr_exit_load_va; + paddr_t vc_vmx_msr_exit_load_pa; +#if 0 /* XXX currently use msr_exit_save for msr_entry_load too */ + vaddr_t vc_vmx_msr_entry_load_va; + paddr_t vc_vmx_msr_entry_load_pa; +#endif + uint8_t vc_vmx_vpid_enabled; + uint64_t vc_vmx_cr0_fixed1; + uint64_t vc_vmx_cr0_fixed0; + uint32_t vc_vmx_vmcs_state; /* [a] */ +#define VMCS_CLEARED 0 +#define VMCS_LAUNCHED 1 + + /* SVM only (all requiring [v]) */ + vaddr_t vc_svm_hsa_va; + paddr_t vc_svm_hsa_pa; + vaddr_t vc_svm_vmsa_va; + paddr_t vc_svm_vmsa_pa; + vaddr_t vc_svm_ghcb_va; + paddr_t vc_svm_ghcb_pa; + vaddr_t vc_svm_ioio_va; + paddr_t vc_svm_ioio_pa; + int vc_sev; /* [I] */ + int vc_seves; /* [I] */ +}; + +SLIST_HEAD(vcpu_head, vcpu); + +void vmm_dispatch_intr(vaddr_t); +int vmxon(uint64_t *); +int vmxoff(void); +int vmclear(paddr_t *); +int vmptrld(paddr_t *); +int vmptrst(paddr_t *); +int vmwrite(uint64_t, uint64_t); +int vmread(uint64_t, uint64_t *); +int invvpid(uint64_t, struct vmx_invvpid_descriptor *); +int invept(uint64_t, struct vmx_invept_descriptor *); +int vmx_enter_guest(paddr_t *, struct vcpu_gueststate *, int, uint8_t); +int svm_enter_guest(uint64_t, struct vcpu_gueststate *, + struct region_descriptor *); +int svm_seves_enter_guest(uint64_t, vaddr_t, struct region_descriptor *); +void start_vmm_on_cpu(struct cpu_info *); +void stop_vmm_on_cpu(struct cpu_info *); +void vmclear_on_cpu(struct cpu_info *); +int vmm_probe_machdep(struct device *, void *, void *); +void vmm_attach_machdep(struct device *, struct device *, void *); +void vmm_activate_machdep(struct device *, int); +int vmmioctl_machdep(dev_t, u_long, caddr_t, int, struct proc *); +int pledge_ioctl_vmm_machdep(struct proc *, long); +int vmm_start(void); +int vmm_stop(void); +int vm_impl_init(struct vm *, struct proc *); +void vm_impl_deinit(struct vm *); +int vcpu_init(struct vcpu *, struct vm_create_params *); +void vcpu_deinit(struct vcpu *); +int vm_rwregs(struct vm_rwregs_params *, int); +int vcpu_reset_regs(struct vcpu *, struct vcpu_reg_state *); +int svm_get_vmsa_pa(uint32_t, uint32_t, uint64_t *); + +#endif /* _KERNEL */ + +#endif /* ! _LOCORE */ + +#endif /* ! _MACHINE_VMMVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/amd64/vmparam.h b/lib/libc/include/x86_64-openbsd-none/amd64/vmparam.h new file mode 100644 index 000000000000..dc577330a247 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/amd64/vmparam.h @@ -0,0 +1,114 @@ +/* $OpenBSD: vmparam.h,v 1.25 2024/11/08 01:44:52 jsg Exp $ */ +/* $NetBSD: vmparam.h,v 1.1 2003/04/26 18:39:49 fvdl Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vmparam.h 5.9 (Berkeley) 5/12/91 + */ + +#ifndef _MACHINE_VMPARAM_H_ +#define _MACHINE_VMPARAM_H_ + +/* + * Machine dependent constants for amd64. + */ + +/* + * USRSTACK is the top (end) of the user stack. Immediately above the + * user stack resides the user structure, which is UPAGES long and contains + * the kernel stack. + * + * Immediately after the user structure is the page table map, and then + * kernel address space. + */ +#define USRSTACK VM_MAXUSER_ADDRESS + +/* + * Virtual memory related constants, all in bytes + */ +#define MAXTSIZ ((paddr_t)256*1024*1024) /* max text size */ +#ifndef DFLDSIZ +#define DFLDSIZ ((paddr_t)128*1024*1024) /* initial data size limit */ +#endif +#ifndef MAXDSIZ +#define MAXDSIZ ((paddr_t)128*1024*1024*1024) /* max data size */ +#endif +#ifndef BRKSIZ +#define BRKSIZ ((paddr_t)8*1024*1024*1024) /* heap gap size */ +#endif +#ifndef DFLSSIZ +#define DFLSSIZ ((paddr_t)2*1024*1024) /* initial stack size limit */ +#endif +#ifndef MAXSSIZ +#define MAXSSIZ ((paddr_t)32*1024*1024) /* max stack size */ +#endif + +#define STACKGAP_RANDOM 256*1024 + +/* + * Size of shared memory map + */ +#ifndef SHMMAXPGS +#define SHMMAXPGS 8192 +#endif + +/* + * Size of User Raw I/O map + */ +#define USRIOSIZE 300 + +/* + * Mach derived constants + */ + +/* user/kernel map constants */ +#define VM_MIN_ADDRESS PAGE_SIZE +#define VM_MAXUSER_ADDRESS 0x00007f7fffffc000 +#define VM_MAX_ADDRESS 0x00007fbfdfeff000 +#ifdef _KERNEL +#define VM_MIN_STACK_ADDRESS 0x0000600000000000 +#endif +#define VM_MIN_KERNEL_ADDRESS 0xffff800000000000 +#define VM_MAX_KERNEL_ADDRESS 0xffff800100000000 + +/* map PIE into approximately the first quarter of user va space */ +#define VM_PIE_MIN_ADDR VM_MIN_ADDRESS +#define VM_PIE_MAX_ADDR 0x200000000000 + +/* virtual sizes (bytes) for various kernel submaps */ +#define VM_PHYS_SIZE (USRIOSIZE*PAGE_SIZE) + +#define VM_PHYSSEG_MAX 16 /* actually we could have this many segments */ +#define VM_PHYSSEG_STRAT VM_PSTRAT_BIGFIRST +#define VM_PHYSSEG_NOADD /* can't add RAM after vm_mem_init */ + +#endif /* _MACHINE_VMPARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/frame.h b/lib/libc/include/x86_64-openbsd-none/frame.h new file mode 100644 index 000000000000..bd9658dec45d --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/frame.h @@ -0,0 +1,174 @@ +/* $OpenBSD: frame.h,v 1.11 2024/01/31 06:06:28 guenther Exp $ */ +/* $NetBSD: frame.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)frame.h 5.2 (Berkeley) 1/18/91 + */ + +/* + * Adapted for NetBSD/amd64 by fvdl@wasabisystems.com + */ + +#ifndef _MACHINE_FRAME_H_ +#define _MACHINE_FRAME_H_ + +#include +#include + +/* + * System stack frames. + */ + +/* + * Exception/Trap Stack Frame + */ +struct trapframe { + int64_t tf_rdi; /* ordered by syscall args... */ + int64_t tf_rsi; + int64_t tf_rdx; + int64_t tf_r10; + int64_t tf_r8; + int64_t tf_r9; /* ...to here */ + int64_t tf_rcx; + int64_t tf_r11; + int64_t tf_r12; + int64_t tf_r13; + int64_t tf_r14; + int64_t tf_r15; + int64_t tf_err; /* not the hardware position */ + int64_t tf_rbx; + int64_t tf_rax; + int64_t tf_trapno; + int64_t tf_rbp; /* hardware puts err here, INTRENTRY() moves it up */ + /* below portion defined in hardware */ + int64_t tf_rip; + int64_t tf_cs; + int64_t tf_rflags; + /* These are pushed unconditionally on the x86-64 */ + int64_t tf_rsp; + int64_t tf_ss; +}; + +/* + * Interrupt stack frame + */ +struct intrframe { + int64_t if_rdi; + int64_t if_rsi; + int64_t if_rdx; + int64_t if_r10; + int64_t if_r8; + int64_t if_r9; + int64_t if_rcx; + int64_t if_r11; + int64_t if_r12; + int64_t if_r13; + int64_t if_r14; + int64_t if_r15; + int64_t if_err; /* IREENT_MAGIC if resume/recurse */ + int64_t if_rbx; + int64_t if_rax; + int64_t if_ppl; /* previous priority level */ + int64_t if_rbp; + /* below portion defined in hardware */ + int64_t if_rip; + int64_t if_cs; + int64_t if_rflags; + /* These are pushed unconditionally on the x86-64 */ + int64_t if_rsp; + int64_t if_ss; +}; + + +/* + * The trampoline frame used on the kernel stack page which is present + * but kernel-only, in the page tables used when in userspace. This is + * the minimum for iretq operation. + */ +struct iretq_frame { + int64_t iretq_rip; + int64_t iretq_cs; + int64_t iretq_rflags; + int64_t iretq_rsp; + int64_t iretq_ss; +}; + +/* + * Stack frame inside cpu_switch() + */ +struct switchframe { + int64_t sf_r15; + int64_t sf_r14; + int64_t sf_r13; + int64_t sf_r12; + int64_t sf_rbp; + int64_t sf_rbx; + int64_t sf_rip; +}; + +struct callframe { + struct callframe *f_frame; + long f_retaddr; + long f_arg0; +}; + +#endif /* _MACHINE_FRAME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/_float.h b/lib/libc/include/x86_64-openbsd-none/machine/_float.h new file mode 100644 index 000000000000..8627bb549920 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/_float.h @@ -0,0 +1,71 @@ +/* $OpenBSD: _float.h,v 1.1 2012/06/26 16:12:43 deraadt Exp $ */ + +/* + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE__FLOAT_H_ +#define _MACHINE__FLOAT_H_ + +#define __FLT_RADIX 2 /* b */ +#define __FLT_ROUNDS __flt_rounds() +#define __FLT_EVAL_METHOD 0 /* no promotions */ + +#define __FLT_MANT_DIG 24 /* p */ +#define __FLT_EPSILON 1.19209290E-07F /* b**(1-p) */ +#define __FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ +#define __FLT_MIN_EXP (-125) /* emin */ +#define __FLT_MIN 1.17549435E-38F /* b**(emin-1) */ +#define __FLT_MIN_10_EXP (-37) /* ceil(log10(b**(emin-1))) */ +#define __FLT_MAX_EXP 128 /* emax */ +#define __FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ +#define __FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ + +#define __DBL_MANT_DIG 53 +#define __DBL_EPSILON 2.2204460492503131E-16 +#define __DBL_DIG 15 +#define __DBL_MIN_EXP (-1021) +#define __DBL_MIN 2.2250738585072014E-308 +#define __DBL_MIN_10_EXP (-307) +#define __DBL_MAX_EXP 1024 +#define __DBL_MAX 1.7976931348623157E+308 +#define __DBL_MAX_10_EXP 308 + +#define __LDBL_MANT_DIG 64 +#define __LDBL_EPSILON 1.08420217248550443401e-19L +#define __LDBL_DIG 18 +#define __LDBL_MIN_EXP (-16381) +#define __LDBL_MIN 3.36210314311209350626e-4932L +#define __LDBL_MIN_10_EXP (-4931) +#define __LDBL_MAX_EXP 16384 +#define __LDBL_MAX 1.18973149535723176502e+4932L +#define __LDBL_MAX_10_EXP 4932 + +#define __DECIMAL_DIG 21 + +#endif /* _MACHINE__FLOAT_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/_types.h b/lib/libc/include/x86_64-openbsd-none/machine/_types.h new file mode 100644 index 000000000000..6d48c5e0337a --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/_types.h @@ -0,0 +1,140 @@ +/* $OpenBSD: _types.h,v 1.19 2023/07/02 19:02:27 cheloha Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.3 (Berkeley) 1/5/94 + * @(#)ansi.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _MACHINE__TYPES_H_ +#define _MACHINE__TYPES_H_ + +/* + * _ALIGN(p) rounds p (pointer or byte index) up to a correctly-aligned + * value for all data types (int, long, ...). The result is an + * unsigned long and must be cast to any desired pointer type. + * + * _ALIGNED_POINTER is a boolean macro that checks whether an address + * is valid to fetch data elements of type t from on this architecture. + * This does not reflect the optimal alignment, just the possibility + * (within reasonable limits). + */ +#define _ALIGNBYTES (sizeof(long) - 1) +#define _STACKALIGNBYTES 15 +#define _ALIGN(p) (((unsigned long)(p) + _ALIGNBYTES) &~_ALIGNBYTES) +#define _ALIGNED_POINTER(p,t) 1 +#define _MAX_PAGE_SHIFT 12 /* same as PAGE_SHIFT */ + +#if defined(_KERNEL) +typedef struct label_t { + long val[8]; +} label_t; +#endif + +/* 7.18.1.1 Exact-width integer types */ +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short __int16_t; +typedef unsigned short __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; +typedef long long __int64_t; +typedef unsigned long long __uint64_t; + +/* 7.18.1.2 Minimum-width integer types */ +typedef __int8_t __int_least8_t; +typedef __uint8_t __uint_least8_t; +typedef __int16_t __int_least16_t; +typedef __uint16_t __uint_least16_t; +typedef __int32_t __int_least32_t; +typedef __uint32_t __uint_least32_t; +typedef __int64_t __int_least64_t; +typedef __uint64_t __uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types */ +typedef __int32_t __int_fast8_t; +typedef __uint32_t __uint_fast8_t; +typedef __int32_t __int_fast16_t; +typedef __uint32_t __uint_fast16_t; +typedef __int32_t __int_fast32_t; +typedef __uint32_t __uint_fast32_t; +typedef __int64_t __int_fast64_t; +typedef __uint64_t __uint_fast64_t; +#define __INT_FAST8_MIN INT32_MIN +#define __INT_FAST16_MIN INT32_MIN +#define __INT_FAST32_MIN INT32_MIN +#define __INT_FAST64_MIN INT64_MIN +#define __INT_FAST8_MAX INT32_MAX +#define __INT_FAST16_MAX INT32_MAX +#define __INT_FAST32_MAX INT32_MAX +#define __INT_FAST64_MAX INT64_MAX +#define __UINT_FAST8_MAX UINT32_MAX +#define __UINT_FAST16_MAX UINT32_MAX +#define __UINT_FAST32_MAX UINT32_MAX +#define __UINT_FAST64_MAX UINT64_MAX + +/* 7.18.1.4 Integer types capable of holding object pointers */ +typedef long __intptr_t; +typedef unsigned long __uintptr_t; + +/* 7.18.1.5 Greatest-width integer types */ +typedef __int64_t __intmax_t; +typedef __uint64_t __uintmax_t; + +/* Register size */ +typedef long __register_t; + +/* VM system types */ +typedef unsigned long __vaddr_t; +typedef unsigned long __paddr_t; +typedef unsigned long __vsize_t; +typedef unsigned long __psize_t; + +/* Standard system types */ +typedef double __double_t; +typedef float __float_t; +typedef long __ptrdiff_t; +typedef unsigned long __size_t; +typedef long __ssize_t; +#if defined(__GNUC__) && __GNUC__ >= 3 +typedef __builtin_va_list __va_list; +#else +typedef char * __va_list; +#endif + +/* Wide character support types */ +#ifndef __cplusplus +typedef int __wchar_t; +#endif +typedef int __wint_t; +typedef int __rune_t; +typedef void * __wctrans_t; +typedef void * __wctype_t; + +#endif /* _MACHINE__TYPES_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/apicvar.h b/lib/libc/include/x86_64-openbsd-none/machine/apicvar.h new file mode 100644 index 000000000000..90c3cd3bc140 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/apicvar.h @@ -0,0 +1,54 @@ +/* $OpenBSD: apicvar.h,v 1.4 2025/09/05 16:57:48 kettenis Exp $ */ +/* $NetBSD: apicvar.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_APICVAR_H_ +#define _MACHINE_APICVAR_H_ + +#include + +struct apic_attach_args { + const char *aaa_name; + int apic_id; + int apic_version; + int flags; +#define IOAPIC_PICMODE 0x01 +#define IOAPIC_VWIRE 0x02 + bus_space_tag_t apic_memt; + bus_addr_t apic_address; + int apic_vecbase; +}; + +void apic_format_redir(char *, char *, int, u_int32_t, u_int32_t); + +#endif /* !_MACHINE_APICVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/apmvar.h b/lib/libc/include/x86_64-openbsd-none/machine/apmvar.h new file mode 100644 index 000000000000..7407c1c6cf3b --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/apmvar.h @@ -0,0 +1,303 @@ +/* XXX - DSR */ +/* $OpenBSD: apmvar.h,v 1.8 2019/01/22 02:36:30 phessler Exp $ */ + +/* + * Copyright (c) 1995 John T. Kohl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _MACHINE_APMVAR_H_ +#define _MACHINE_APMVAR_H_ + +#include + +/* Advanced Power Management (v1.0 and v1.1 specification) + * functions/defines/etc. + */ + +#define APM_VERSION 0x0102 + +/* + * APM info word from boot loader + */ +#define APM_16BIT_SUPPORTED 0x00010000 +#define APM_32BIT_SUPPORTED 0x00020000 +#define APM_IDLE_SLOWS 0x00040000 +#define APM_BIOS_PM_DISABLED 0x00080000 +#define APM_BIOS_PM_DISENGAGED 0x00100000 +#define APM_MAJOR(f) (((f) >> 8) & 0xff) +#define APM_MINOR(f) ((f) & 0xff) +#define APM_VERMASK 0x0000ffff +#define APM_NOCLI 0x00010000 +#define APM_BEBATT 0x00020000 + +/* APM error codes */ +#define APM_ERR_CODE(regs) (((regs)->ax & 0xff00) >> 8) +#define APM_ERR_PM_DISABLED 0x01 +#define APM_ERR_REALALREADY 0x02 +#define APM_ERR_NOTCONN 0x03 +#define APM_ERR_16ALREADY 0x05 +#define APM_ERR_16NOTSUPP 0x06 +#define APM_ERR_32ALREADY 0x07 +#define APM_ERR_32NOTSUPP 0x08 +#define APM_ERR_UNRECOG_DEV 0x09 +#define APM_ERR_ERANGE 0x0A +#define APM_ERR_NOTENGAGED 0x0B +#define APM_ERR_EOPNOSUPP 0x0C +#define APM_ERR_RTIMER_DISABLED 0x0D +#define APM_ERR_UNABLE 0x60 +#define APM_ERR_NOEVENTS 0x80 +#define APM_ERR_NOT_PRESENT 0x86 + +#define APM_DEV_APM_BIOS 0x0000 +#define APM_DEV_ALLDEVS 0x0001 +/* device classes are high byte; device IDs go in low byte */ +#define APM_DEV_DISPLAY(x) (0x0100|((x)&0xff)) +#define APM_DEV_DISK(x) (0x0200|((x)&0xff)) +#define APM_DEV_PARALLEL(x) (0x0300|((x)&0xff)) +#define APM_DEV_SERIAL(x) (0x0400|((x)&0xff)) +#define APM_DEV_NETWORK(x) (0x0500|((x)&0xff)) +#define APM_DEV_PCMCIA(x) (0x0600|((x)&0xff)) +#define APM_DEV_BATTERIES(x) (0x8000|((x)&0xff)) +#define APM_DEV_ALLUNITS 0xff +/* 0x8100-0xDFFF - reserved */ +/* 0xE000-0xEFFF - OEM-defined */ +/* 0xF000-0xFFFF - reserved */ + +#define APM_INSTCHECK 0x5300 /* int15 only */ +#define APM_16BIT_SUPPORT 0x01 +#define APM_32BIT_SUPPORT 0x02 +#define APM_CPUIDLE_SLOW 0x04 +#define APM_DISABLED 0x08 +#define APM_DISENGAGED 0x10 + +#define APM_REAL_CONNECT 0x5301 /* int15 only */ +#define APM_PROT16_CONNECT 0x5302 /* int15 only */ +#define APM_PROT32_CONNECT 0x5303 /* int15 only */ +#define APM_DISCONNECT 0x5304 /* %bx = APM_DEV_APM_BIOS */ + +#define APM_CPU_IDLE 0x5305 +#define APM_CPU_BUSY 0x5306 + +#define APM_SET_PWR_STATE 0x5307 +#define APM_SYS_READY 0x0000 /* %cx */ +#define APM_SYS_STANDBY 0x0001 +#define APM_SYS_SUSPEND 0x0002 +#define APM_SYS_OFF 0x0003 +#define APM_LASTREQ_INPROG 0x0004 +#define APM_LASTREQ_REJECTED 0x0005 +/* 0x0006 - 0x001f Reserved system states */ +/* 0x0020 - 0x003f OEM-defined system states */ +/* 0x0040 - 0x007f OEM-defined device states */ +/* 0x0080 - 0xffff Reserved device states */ + +/* system standby is device ID (%bx) 0x0001, APM_SYS_STANDBY */ +/* system suspend is device ID (%bx) 0x0001, APM_SYS_SUSPEND */ + +#define APM_PWR_MGT_ENABLE 0x5308 +#define APM_MGT_ALL 0xffff /* %bx */ +#define APM_MGT_DISABLE 0x0 /* %cx */ +#define APM_MGT_ENABLE 0x1 + +#define APM_SYSTEM_DEFAULTS 0x5309 +#define APM_DEFAULTS_ALL 0xffff /* %bx */ + +#define APM_POWER_STATUS 0x530a +#define APM_AC_OFF 0x00 +#define APM_AC_ON 0x01 +#define APM_AC_BACKUP 0x02 +#define APM_AC_UNKNOWN 0xff +#define APM_BATT_HIGH 0x00 +#define APM_BATT_LOW 0x01 +#define APM_BATT_CRITICAL 0x02 +#define APM_BATT_CHARGING 0x03 +#define APM_BATT_UNKNOWN 0xff +#define APM_BATT_FLAG_HIGH 0x01 +#define APM_BATT_FLAG_LOW 0x02 +#define APM_BATT_FLAG_CRITICAL 0x04 +#define APM_BATT_FLAG_CHARGING 0x08 +#define APM_BATT_FLAG_NOBATTERY 0x10 +#define APM_BATT_FLAG_NOSYSBATT 0x80 +#define APM_BATT_LIFE_UNKNOWN 0xff +#define BATT_STATE(regp) ((regp)->bx & 0xff) +#define BATT_FLAGS(regp) (((regp)->cx & 0xff00) >> 8) +#define AC_STATE(regp) (((regp)->bx & 0xff00) >> 8) +#define BATT_LIFE(regp) ((regp)->cx & 0xff) /* in % */ +/* Return time in minutes. According to the APM 1.2 spec: + DX = Remaining battery life -- time units + Bit 15 = 0 Time units are seconds + = 1 Time units are minutes + Bits 14-0 = Number of seconds or minutes */ +#define BATT_REMAINING(regp) (((regp)->dx & 0x8000) ? \ + ((regp)->dx & 0x7fff) : \ + ((regp)->dx & 0x7fff)/60) +#define BATT_REM_VALID(regp) (((regp)->dx & 0xffff) != 0xffff) +#define BATT_COUNT(regp) ((regp)->si) + +#define APM_GET_PM_EVENT 0x530b +#define APM_NOEVENT 0x0000 +#define APM_STANDBY_REQ 0x0001 /* %bx on return */ +#define APM_SUSPEND_REQ 0x0002 +#define APM_NORMAL_RESUME 0x0003 +#define APM_CRIT_RESUME 0x0004 /* suspend/resume happened + without us */ +#define APM_BATTERY_LOW 0x0005 +#define APM_POWER_CHANGE 0x0006 +#define APM_UPDATE_TIME 0x0007 +#define APM_CRIT_SUSPEND_REQ 0x0008 +#define APM_USER_STANDBY_REQ 0x0009 +#define APM_USER_SUSPEND_REQ 0x000A +#define APM_SYS_STANDBY_RESUME 0x000B +#define APM_CAPABILITY_CHANGE 0x000C /* apm v1.2 */ +/* 0x000d - 0x00ff Reserved system events */ +#define APM_USER_HIBERNATE_REQ 0x000D +/* 0x0100 - 0x01ff Reserved device events */ +/* 0x0200 - 0x02ff OEM-defined APM events */ +/* 0x0300 - 0xffff Reserved */ +#define APM_EVENT_MASK 0xffff + +#define APM_EVENT_COMPOSE(t,i) ((((i) & 0x7fff) << 16)|((t) & APM_EVENT_MASK)) +#define APM_EVENT_TYPE(e) ((e) & APM_EVENT_MASK) +#define APM_EVENT_INDEX(e) ((e) >> 16) + +#define APM_GET_POWER_STATE 0x530c +#define APM_DEVICE_MGMT_ENABLE 0x530d + +#define APM_DRIVER_VERSION 0x530e +/* %bx should be DEV value (APM_DEV_APM_BIOS) + %ch = driver major vno + %cl = driver minor vno + return: %ah = conn major; %al = conn minor + */ +#define APM_CONN_MINOR(regp) ((regp)->ax & 0xff) +#define APM_CONN_MAJOR(regp) (((regp)->ax & 0xff00) >> 8) + +#define APM_PWR_MGT_ENGAGE 0x530F +#define APM_MGT_DISENGAGE 0x0 /* %cx */ +#define APM_MGT_ENGAGE 0x1 + +/* %bx - APM_DEV_APM_BIOS + * %bl - number of batteries + * %cx - capabilities + */ +#define APM_GET_CAPABILITIES 0x5310 +#define APM_NBATTERIES(regp) ((regp)->bx) +#define APM_GLOBAL_STANDBY 0x0001 +#define APM_GLOBAL_SUSPEND 0x0002 +#define APM_RTIMER_STANDBY 0x0004 /* resume time wakes up */ +#define APM_RTIMER_SUSPEND 0x0008 +#define APM_IRRING_STANDBY 0x0010 /* internal ring wakes up */ +#define APM_IRRING_SUSPEND 0x0020 +#define APM_PCCARD_STANDBY 0x0040 /* pccard wakes up */ +#define APM_PCCARD_SUSPEND 0x0080 + +/* %bx - APM_DEV_APM_BIOS + * %cl - function + * for %cl=2 (set resume timer) + * %ch - seconds in BCD + * %dh - hours in BCD + * %dl - minutes in BCD + * %si - month in BCD (high), day in BCD (low) + * %di - year in BCD + */ +#define APM_RESUME_TIMER 0x5311 +#define APM_RT_DISABLE 0x0 +#define APM_RT_GET 0x1 +#define APM_RT_SET 0x2 + +/* %bx - APM_DEV_APM_BIOS + * %cx - function + */ +#define APM_RESUME_ON_RING 0x5312 +#define APM_ROR_DISABLE 0x0 +#define APM_ROR_ENABLE 0x1 +#define APM_ROR_STATUS 0x2 + +/* %bx - APM_EDV_APM_BIOS + * %cx - function + */ +#define APM_INACTIVITY_TIMER 0x5313 +#define APM_IT_DISABLE 0x0 +#define APM_IT_ENABLE 0x1 +#define APM_IT_STATUS 0x2 + +/* %bh - function */ +#define APM_OEM 0x5380 +#define APM_OEM_INSTCHECK 0x7f /* %bx - OEM ID */ + +/* + * LP (Laptop Package) + * + * Copyright (C) 1994 by HOSOKAWA Tatsumi + * + * This software may be used, modified, copied, and distributed, in + * both source and binary form provided that the above copyright and + * these terms are retained. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with its + * use. + * + * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) + */ + +#define APM_BATTERY_ABSENT 4 + +struct apm_power_info { + u_char battery_state; + u_char ac_state; + u_char battery_life; + u_char spare1; + u_int minutes_left; /* estimate */ + u_int spare2[6]; +}; + +struct apm_ctl { + u_int dev; + u_int mode; +}; + +#define APM_IOC_REJECT _IOW('A', 0, struct apm_event_info) /* reject request # */ +#define APM_IOC_STANDBY _IO('A', 1) /* put system into standby */ +#define APM_IOC_SUSPEND _IO('A', 2) /* put system into suspend */ +#define APM_IOC_GETPOWER _IOR('A', 3, struct apm_power_info) /* fetch battery state */ +#define APM_IOC_DEV_CTL _IOW('A', 5, struct apm_ctl) /* put device into mode */ +#define APM_IOC_PRN_CTL _IOW('A', 6, int ) /* driver power status msg */ +#define APM_PRINT_ON 0 /* driver power status displayed */ +#define APM_PRINT_OFF 1 /* driver power status not displayed */ +#define APM_PRINT_PCT 2 /* driver power status only displayed + if the percentage changes */ +#define APM_IOC_STANDBY_REQ _IO('A', 7) /* request standby */ +#define APM_IOC_SUSPEND_REQ _IO('A', 8) /* request suspend */ +#define APM_IOC_HIBERNATE _IO('A', 9) /* put system into hibernate */ + +#ifdef _KERNEL +extern void apm_cpu_busy(void); +extern void apm_cpu_idle(void); +extern void apminit(void); +int apm_set_powstate(u_int devid, u_int powstate); +#endif /* _KERNEL */ + +#endif /* _MACHINE_APMVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/asm.h b/lib/libc/include/x86_64-openbsd-none/machine/asm.h new file mode 100644 index 000000000000..64acd3a4f0a3 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/asm.h @@ -0,0 +1,196 @@ +/* $OpenBSD: asm.h,v 1.24 2023/04/17 00:02:14 deraadt Exp $ */ +/* $NetBSD: asm.h,v 1.2 2003/05/02 18:05:47 yamt Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)asm.h 5.5 (Berkeley) 5/7/91 + */ + +#ifndef _MACHINE_ASM_H_ +#define _MACHINE_ASM_H_ + +#ifdef __PIC__ +#define PIC_PLT(x) x@PLT +#define PIC_GOT(x) x@GOTPCREL(%rip) +#else +#define PIC_PLT(x) x +#define PIC_GOT(x) x +#endif + +# define _C_LABEL(x) x +#define _ASM_LABEL(x) x + +#define CVAROFF(x,y) (x+y)(%rip) + +#ifdef __STDC__ +# define __CONCAT(x,y) x ## y +# define __STRING(x) #x +#else +# define __CONCAT(x,y) x/**/y +# define __STRING(x) "x" +#endif + +/* let kernels and others override entrypoint alignment */ +#ifndef _ALIGN_TEXT +#define _ALIGN_TEXT .align 16, 0x90 +#endif +#define _ALIGN_TRAPS .align 16, 0xcc + +#define _FENTRY(x) .type x,@function; x: + +/* NB == No Binding: use .globl or .weak as necessary */ +#define NENTRY_NB(x) \ + .text; _ALIGN_TEXT; _FENTRY(x) +#define _ENTRY_NB(x) \ + .text; _ALIGN_TRAPS; _FENTRY(x) +#define _ENTRY(x) .globl x; _ENTRY_NB(x) +#define _NENTRY(x) .globl x; NENTRY_NB(x) + +#ifdef _KERNEL +#define KUTEXT .section .kutext, "ax", @progbits + +#define KUTEXT_PAGE_START .pushsection .kutext.page, "a", @progbits +#define KTEXT_PAGE_START .pushsection .ktext.page, "ax", @progbits +#define KUTEXT_PAGE_END .popsection +#define KTEXT_PAGE_END .popsection + +#define IDTVEC(name) \ + KUTEXT; _ALIGN_TRAPS; IDTVEC_NOALIGN(name); endbr64 +#define GENTRY(x) .globl x; _FENTRY(x) +#define IDTVEC_NOALIGN(name) GENTRY(X ## name) +#define IDTVEC_ALIAS(alias,sym) \ + .global X ## alias; \ + X ## alias = X ## sym; +#define KIDTVEC(name) \ + .text; _ALIGN_TRAPS; IDTVEC_NOALIGN(name); endbr64 +#define KIDTVEC_FALLTHROUGH(name) \ + _ALIGN_TEXT; IDTVEC_NOALIGN(name) +#define KUENTRY(x) \ + KUTEXT; _ALIGN_TRAPS; GENTRY(x) + +/* Return stack refill, to prevent speculation attacks on natural returns */ +#define RET_STACK_REFILL_WITH_RCX \ + mov $8,%rcx ; \ + _ALIGN_TEXT ; \ + 3: call 5f ; \ + 4: pause ; \ + lfence ; \ + call 4b ; \ + _ALIGN_TRAPS ; \ + 5: call 7f ; \ + 6: pause ; \ + lfence ; \ + call 6b ; \ + _ALIGN_TRAPS ; \ + 7: loop 3b ; \ + add $(16*8),%rsp + +#endif /* _KERNEL */ + +#ifdef __STDC__ +#define CPUVAR(off) %gs:CPU_INFO_ ## off +#else +#define CPUVAR(off) %gs:CPU_INFO_/**/off +#endif + + +#if defined(PROF) || defined(GPROF) +# define _PROF_PROLOGUE \ + pushq %rbp; leaq (%rsp),%rbp; call PIC_PLT(__mcount); popq %rbp +#else +# define _PROF_PROLOGUE +#endif + +#if defined(_RET_PROTECTOR) +# define RETGUARD_SETUP_OFF(x, reg, off) \ + RETGUARD_SYMBOL(x); \ + movq (__retguard_ ## x)(%rip), %reg; \ + xorq off(%rsp), %reg +# define RETGUARD_SETUP(x, reg) \ + RETGUARD_SETUP_OFF(x, reg, 0) +# define RETGUARD_CHECK(x, reg) \ + xorq (%rsp), %reg; \ + cmpq (__retguard_ ## x)(%rip), %reg; \ + je 66f; \ + int3; int3; \ + .zero (0xf - ((. + 3 - x) & 0xf)), 0xcc; \ +66: +# define RETGUARD_PUSH(reg) \ + pushq %reg +# define RETGUARD_POP(reg) \ + popq %reg +# define RETGUARD_SYMBOL(x) \ + .ifndef __retguard_ ## x; \ + .hidden __retguard_ ## x; \ + .type __retguard_ ## x,@object; \ + .pushsection .openbsd.randomdata.retguard,"aw",@progbits; \ + .weak __retguard_ ## x; \ + .p2align 3; \ + __retguard_ ## x: ; \ + .quad 0; \ + .size __retguard_ ## x, 8; \ + .popsection; \ + .endif +#else +# define RETGUARD_SETUP_OFF(x, reg, off) +# define RETGUARD_SETUP(x, reg) +# define RETGUARD_CHECK(x, reg) +# define RETGUARD_PUSH(reg) +# define RETGUARD_POP(reg) +# define RETGUARD_SYMBOL(x) +#endif + +#define ENTRY(y) _ENTRY(y); endbr64; _PROF_PROLOGUE +#define NENTRY(y) _NENTRY(y) +#define ASENTRY(y) _NENTRY(y); endbr64; _PROF_PROLOGUE +#define ENTRY_NB(y) _ENTRY_NB(y); endbr64; _PROF_PROLOGUE +#define END(y) .size y, . - y + +#define STRONG_ALIAS(alias,sym) \ + .global alias; \ + alias = sym +#define WEAK_ALIAS(alias,sym) \ + .weak alias; \ + alias = sym + +/* generic retpoline ("return trampoline") generator */ +#define JMP_RETPOLINE(reg) \ + call 69f ; \ + 68: pause ; \ + lfence ; \ + jmp 68b ; \ + _ALIGN_TRAPS ; \ + 69: mov %reg,(%rsp) ; \ + ret ; \ + lfence + +#endif /* !_MACHINE_ASM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/atomic.h b/lib/libc/include/x86_64-openbsd-none/machine/atomic.h new file mode 100644 index 000000000000..329eccec1c44 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/atomic.h @@ -0,0 +1,325 @@ +/* $OpenBSD: atomic.h,v 1.23 2023/11/11 18:47:02 jca Exp $ */ +/* $NetBSD: atomic.h,v 1.1 2003/04/26 18:39:37 fvdl Exp $ */ + +/* + * Copyright 2002 (c) Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Frank van der Linden for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_ATOMIC_H_ +#define _MACHINE_ATOMIC_H_ + +/* + * Perform atomic operations on memory. Should be atomic with respect + * to interrupts and multiple processors. + * + * void atomic_setbits_int(volatile u_int *a, u_int mask) { *a |= mask; } + * void atomic_clearbits_int(volatile u_int *a, u_int mask) { *a &= ~mask; } + */ + +#if !defined(_LOCORE) + +#if defined(MULTIPROCESSOR) || !defined(_KERNEL) +#define _LOCK "lock" +#else +#define _LOCK +#endif + +static inline unsigned int +_atomic_cas_uint(volatile unsigned int *p, unsigned int e, unsigned int n) +{ + __asm volatile(_LOCK " cmpxchgl %2, %1" + : "=a" (n), "=m" (*p) + : "r" (n), "a" (e), "m" (*p)); + + return (n); +} +#define atomic_cas_uint(_p, _e, _n) _atomic_cas_uint((_p), (_e), (_n)) + +static inline unsigned long +_atomic_cas_ulong(volatile unsigned long *p, unsigned long e, unsigned long n) +{ + __asm volatile(_LOCK " cmpxchgq %2, %1" + : "=a" (n), "=m" (*p) + : "r" (n), "a" (e), "m" (*p)); + + return (n); +} +#define atomic_cas_ulong(_p, _e, _n) _atomic_cas_ulong((_p), (_e), (_n)) + +static inline void * +_atomic_cas_ptr(volatile void *p, void *e, void *n) +{ + __asm volatile(_LOCK " cmpxchgq %2, %1" + : "=a" (n), "=m" (*(unsigned long *)p) + : "r" (n), "a" (e), "m" (*(unsigned long *)p)); + + return (n); +} +#define atomic_cas_ptr(_p, _e, _n) _atomic_cas_ptr((_p), (_e), (_n)) + +static inline unsigned int +_atomic_swap_uint(volatile unsigned int *p, unsigned int n) +{ + __asm volatile("xchgl %0, %1" + : "=a" (n), "=m" (*p) + : "0" (n), "m" (*p)); + + return (n); +} +#define atomic_swap_uint(_p, _n) _atomic_swap_uint((_p), (_n)) +#define atomic_swap_32(_p, _n) _atomic_swap_uint((_p), (_n)) + +static inline unsigned long +_atomic_swap_ulong(volatile unsigned long *p, unsigned long n) +{ + __asm volatile("xchgq %0, %1" + : "=a" (n), "=m" (*p) + : "0" (n), "m" (*p)); + + return (n); +} +#define atomic_swap_ulong(_p, _n) _atomic_swap_ulong((_p), (_n)) + +static inline uint64_t +_atomic_swap_64(volatile uint64_t *p, uint64_t n) +{ + __asm volatile("xchgq %0, %1" + : "=a" (n), "=m" (*p) + : "0" (n), "m" (*p)); + + return (n); +} +#define atomic_swap_64(_p, _n) _atomic_swap_64((_p), (_n)) + +static inline void * +_atomic_swap_ptr(volatile void *p, void *n) +{ + __asm volatile("xchgq %0, %1" + : "=a" (n), "=m" (*(unsigned long *)p) + : "0" (n), "m" (*(unsigned long *)p)); + + return (n); +} +#define atomic_swap_ptr(_p, _n) _atomic_swap_ptr((_p), (_n)) + +static inline void +_atomic_inc_int(volatile unsigned int *p) +{ + __asm volatile(_LOCK " incl %0" + : "+m" (*p)); +} +#define atomic_inc_int(_p) _atomic_inc_int(_p) + +static inline void +_atomic_inc_long(volatile unsigned long *p) +{ + __asm volatile(_LOCK " incq %0" + : "+m" (*p)); +} +#define atomic_inc_long(_p) _atomic_inc_long(_p) + +static inline void +_atomic_dec_int(volatile unsigned int *p) +{ + __asm volatile(_LOCK " decl %0" + : "+m" (*p)); +} +#define atomic_dec_int(_p) _atomic_dec_int(_p) + +static inline void +_atomic_dec_long(volatile unsigned long *p) +{ + __asm volatile(_LOCK " decq %0" + : "+m" (*p)); +} +#define atomic_dec_long(_p) _atomic_dec_long(_p) + +static inline void +_atomic_add_int(volatile unsigned int *p, unsigned int v) +{ + __asm volatile(_LOCK " addl %1,%0" + : "+m" (*p) + : "a" (v)); +} +#define atomic_add_int(_p, _v) _atomic_add_int(_p, _v) + +static inline void +_atomic_add_long(volatile unsigned long *p, unsigned long v) +{ + __asm volatile(_LOCK " addq %1,%0" + : "+m" (*p) + : "a" (v)); +} +#define atomic_add_long(_p, _v) _atomic_add_long(_p, _v) + +static inline void +_atomic_sub_int(volatile unsigned int *p, unsigned int v) +{ + __asm volatile(_LOCK " subl %1,%0" + : "+m" (*p) + : "a" (v)); +} +#define atomic_sub_int(_p, _v) _atomic_sub_int(_p, _v) + +static inline void +_atomic_sub_long(volatile unsigned long *p, unsigned long v) +{ + __asm volatile(_LOCK " subq %1,%0" + : "+m" (*p) + : "a" (v)); +} +#define atomic_sub_long(_p, _v) _atomic_sub_long(_p, _v) + + +static inline unsigned long +_atomic_add_int_nv(volatile unsigned int *p, unsigned int v) +{ + unsigned int rv = v; + + __asm volatile(_LOCK " xaddl %0,%1" + : "+a" (rv), "+m" (*p)); + + return (rv + v); +} +#define atomic_add_int_nv(_p, _v) _atomic_add_int_nv(_p, _v) + +static inline unsigned long +_atomic_add_long_nv(volatile unsigned long *p, unsigned long v) +{ + unsigned long rv = v; + + __asm volatile(_LOCK " xaddq %0,%1" + : "+a" (rv), "+m" (*p)); + + return (rv + v); +} +#define atomic_add_long_nv(_p, _v) _atomic_add_long_nv(_p, _v) + +static inline unsigned long +_atomic_sub_int_nv(volatile unsigned int *p, unsigned int v) +{ + unsigned int rv = 0 - v; + + __asm volatile(_LOCK " xaddl %0,%1" + : "+a" (rv), "+m" (*p)); + + return (rv - v); +} +#define atomic_sub_int_nv(_p, _v) _atomic_sub_int_nv(_p, _v) + +static inline unsigned long +_atomic_sub_long_nv(volatile unsigned long *p, unsigned long v) +{ + unsigned long rv = 0 - v; + + __asm volatile(_LOCK " xaddq %0,%1" + : "+a" (rv), "+m" (*p)); + + return (rv - v); +} +#define atomic_sub_long_nv(_p, _v) _atomic_sub_long_nv(_p, _v) + +/* + * The AMD64 architecture is rather strongly ordered. When accessing + * normal write-back cacheable memory, only reads may be reordered with + * older writes to different locations. There are a few instructions + * (clfush, non-temporal move instructions) that obey weaker ordering + * rules, but those instructions will only be used in (inline) + * assembly code where we can add the necessary fence instructions + * ourselves. + */ + +#define __membar(_f) do { __asm volatile(_f ::: "memory"); } while (0) + +#if defined(MULTIPROCESSOR) || !defined(_KERNEL) +#define membar_enter() __membar("mfence") +#define membar_exit() __membar("") +#define membar_producer() __membar("") +#define membar_consumer() __membar("") +#define membar_sync() __membar("mfence") +#else +#define membar_enter() __membar("") +#define membar_exit() __membar("") +#define membar_producer() __membar("") +#define membar_consumer() __membar("") +#define membar_sync() __membar("") +#endif + +#define membar_enter_after_atomic() __membar("") +#define membar_exit_before_atomic() __membar("") + +#ifdef _KERNEL + +/* virtio needs MP membars even on SP kernels */ +#define virtio_membar_producer() __membar("") +#define virtio_membar_consumer() __membar("") +#define virtio_membar_sync() __membar("mfence") + +static __inline void +x86_atomic_setbits_u32(volatile u_int32_t *ptr, u_int32_t bits) +{ + __asm volatile(_LOCK " orl %1,%0" : "=m" (*ptr) : "ir" (bits)); +} + +static __inline void +x86_atomic_clearbits_u32(volatile u_int32_t *ptr, u_int32_t bits) +{ + __asm volatile(_LOCK " andl %1,%0" : "=m" (*ptr) : "ir" (~bits)); +} + +static __inline void +x86_atomic_setbits_u64(volatile u_int64_t *ptr, u_int64_t bits) +{ + __asm volatile(_LOCK " orq %1,%0" : "=m" (*ptr) : "er" (bits)); +} + +static __inline void +x86_atomic_clearbits_u64(volatile u_int64_t *ptr, u_int64_t bits) +{ + __asm volatile(_LOCK " andq %1,%0" : "=m" (*ptr) : "er" (~bits)); +} + +#define x86_atomic_testset_ul x86_atomic_testset_u64 +#define x86_atomic_setbits_ul x86_atomic_setbits_u64 +#define x86_atomic_clearbits_ul x86_atomic_clearbits_u64 + +#define atomic_setbits_int x86_atomic_setbits_u32 +#define atomic_clearbits_int x86_atomic_clearbits_u32 + +#endif /* _KERNEL */ + +#undef _LOCK + +#endif /* !defined(_LOCORE) */ +#endif /* _MACHINE_ATOMIC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/biosvar.h b/lib/libc/include/x86_64-openbsd-none/machine/biosvar.h new file mode 100644 index 000000000000..523bb6255b8e --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/biosvar.h @@ -0,0 +1,283 @@ +/* $OpenBSD: biosvar.h,v 1.32 2023/09/08 20:47:22 kn Exp $ */ + +/* + * Copyright (c) 1997-1999 Michael Shalayeff + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES 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 MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BIOSVAR_H_ +#define _MACHINE_BIOSVAR_H_ + + /* some boxes put apm data seg in the 2nd page */ +#define BOOTARG_OFF (PAGE_SIZE * 2) +#define BOOTARG_LEN (PAGE_SIZE * 1) +#define BOOTBIOS_ADDR (0x7c00) +#define BOOTBIOS_MAXSEC ((1 << 28) - 1) + + /* BIOS configure flags */ +#define BIOSF_BIOS32 0x0001 +#define BIOSF_PCIBIOS 0x0002 +#define BIOSF_PROMSCAN 0x0004 +#define BIOSF_SMBIOS 0x0008 + +/* BIOS media ID */ +#define BIOSM_F320K 0xff /* floppy ds/sd 8 spt */ +#define BIOSM_F160K 0xfe /* floppy ss/sd 8 spt */ +#define BIOSM_F360K 0xfd /* floppy ds/sd 9 spt */ +#define BIOSM_F180K 0xfc /* floppy ss/sd 9 spt */ +#define BIOSM_ROMD 0xfa /* ROM disk */ +#define BIOSM_F120M 0xf9 /* floppy ds/hd 15 spt 5.25" */ +#define BIOSM_F720K 0xf9 /* floppy ds/dd 9 spt 3.50" */ +#define BIOSM_HD 0xf8 /* hard drive */ +#define BIOSM_F144K 0xf0 /* floppy ds/hd 18 spt 3.50" */ +#define BIOSM_OTHER 0xf0 /* any other */ + +/* + * BIOS memory maps + */ +#define BIOS_MAP_END 0x00 /* End of array XXX - special */ +#define BIOS_MAP_FREE 0x01 /* Usable memory */ +#define BIOS_MAP_RES 0x02 /* Reserved memory */ +#define BIOS_MAP_ACPI 0x03 /* ACPI Reclaim memory */ +#define BIOS_MAP_NVS 0x04 /* ACPI NVS memory */ + +/* + * Optional ROM header + */ +typedef +struct bios_romheader { + uint16_t signature; /* 0xaa55 */ + uint8_t len; /* length in pages (512 bytes) */ + uint32_t entry; /* initialization entry point */ + uint8_t reserved[19]; + uint16_t pnpheader; /* offset to PnP expansion header */ +} __packed *bios_romheader_t; + +#define BIOS32_MAKESIG(a, b, c, d) \ + ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24)) +#define SMBIOS_SIGNATURE BIOS32_MAKESIG('_', 'S', 'M', '_') + +/* + * CTL_BIOS definitions. + */ +#define BIOS_DEV 1 /* int: BIOS boot device */ +#define BIOS_DISKINFO 2 /* struct: BIOS boot device info */ +#define BIOS_CKSUMLEN 3 /* int: disk cksum block count */ +#define BIOS_MAXID 4 /* number of valid machdep ids */ + +#define CTL_BIOS_NAMES { \ + { 0, 0 }, \ + { "biosdev", CTLTYPE_INT }, \ + { "diskinfo", CTLTYPE_STRUCT }, \ + { "cksumlen", CTLTYPE_INT }, \ +} + +#define BOOTARG_MEMMAP 0 +typedef struct _bios_memmap { + uint64_t addr; /* Beginning of block */ + uint64_t size; /* Size of block */ + uint32_t type; /* Type of block */ +} __packed bios_memmap_t; + +/* Info about disk from the bios, plus the mapping from + * BIOS numbers to BSD major (driver?) number. + * + * Also, do not bother with BIOSN*() macros, just parcel + * the info out, and use it like this. This makes for less + * of a dependence on BIOSN*() macros having to be the same + * across /boot, /bsd, and userland. + */ +#define BOOTARG_DISKINFO 1 +typedef struct _bios_diskinfo { + /* BIOS section */ + int bios_number; /* BIOS number of drive (or -1) */ + u_int bios_cylinders; /* BIOS cylinders */ + u_int bios_heads; /* BIOS heads */ + u_int bios_sectors; /* BIOS sectors */ + int bios_edd; /* EDD support */ + + /* BSD section */ + dev_t bsd_dev; /* BSD device */ + + /* Checksum section */ + uint32_t checksum; /* Checksum for drive */ + + /* Misc. flags */ + uint32_t flags; +#define BDI_INVALID 0x00000001 /* I/O error during checksumming */ +#define BDI_GOODLABEL 0x00000002 /* Had SCSI or ST506/ESDI disklabel */ +#define BDI_BADLABEL 0x00000004 /* Had another disklabel */ +#define BDI_EL_TORITO 0x00000008 /* 2,048-byte sectors */ +#define BDI_HIBVALID 0x00000010 /* hibernate signature valid */ +#define BDI_PICKED 0x80000000 /* kernel-only: cksum matched */ + +} __packed bios_diskinfo_t; + +#define BOOTARG_APMINFO 2 +typedef struct _bios_apminfo { + /* APM_CONNECT returned values */ + u_int apm_detail; + u_int apm_code32_base; + u_int apm_code16_base; + u_int apm_code_len; + u_int apm_data_base; + u_int apm_data_len; + u_int apm_entry; + u_int apm_code16_len; +} __packed bios_apminfo_t; + +#define BOOTARG_CKSUMLEN 3 /* uint32_t */ + +#define BOOTARG_PCIINFO 4 +typedef struct _bios_pciinfo { + /* PCI BIOS v2.0+ - Installation check values */ + uint32_t pci_chars; /* Characteristics (%eax) */ + uint32_t pci_rev; /* BCD Revision (%ebx) */ + uint32_t pci_entry32; /* PM entry point for PCI BIOS */ + uint32_t pci_lastbus; /* Number of last PCI bus */ +} __packed bios_pciinfo_t; + +#define BOOTARG_CONSDEV 5 +typedef struct _bios_consdev { + dev_t consdev; + int conspeed; + uint64_t consaddr; + int consfreq; + uint32_t flags; +#define BCD_MMIO 0x00000001 /* Memory Mapped IO */ + int reg_width; + int reg_shift; +} __packed bios_consdev_t; + +#define BOOTARG_BOOTMAC 7 +typedef struct _bios_bootmac { + char mac[6]; +} __packed bios_bootmac_t; + +#define BOOTARG_DDB 8 +typedef struct _bios_ddb { + int db_console; +} __packed bios_ddb_t; + +#define BOOTARG_BOOTDUID 9 +typedef struct _bios_bootduid { + u_char duid[8]; +} __packed bios_bootduid_t; + +#define BOOTARG_BOOTSR 10 +#define BOOTSR_UUID_MAX 16 +#define BOOTSR_CRYPTO_MAXKEYBYTES 32 +typedef struct _bios_bootsr { + uint8_t uuid[BOOTSR_UUID_MAX]; + uint8_t maskkey[BOOTSR_CRYPTO_MAXKEYBYTES]; +} __packed bios_bootsr_t; + +#define BOOTARG_EFIINFO 11 +typedef struct _bios_efiinfo { + uint64_t config_acpi; + uint64_t config_smbios; + uint64_t fb_addr; + uint64_t fb_size; + uint32_t fb_height; + uint32_t fb_width; + uint32_t fb_pixpsl; /* pixels per scan line */ + uint32_t fb_red_mask; + uint32_t fb_green_mask; + uint32_t fb_blue_mask; + uint32_t fb_reserved_mask; + uint32_t flags; +#define BEI_64BIT 0x00000001 /* 64-bit EFI implementation */ +#define BEI_ESRT 0x00000002 /* ESRT table */ + uint32_t mmap_desc_ver; + uint32_t mmap_desc_size; + uint32_t mmap_size; + uint64_t mmap_start; + uint64_t system_table; + uint64_t config_esrt; +} __packed bios_efiinfo_t; + +#define BOOTARG_UCODE 12 +typedef struct _bios_ucode { + uint64_t uc_addr; + uint64_t uc_size; +} __packed bios_ucode_t; + +#if defined(_KERNEL) || defined (_STANDALONE) + +#ifdef _LOCORE +#define DOINT(n) int $0x20+(n) +#else +#define DOINT(n) "int $0x20+(" #n ")" + +extern volatile struct BIOS_regs { + uint32_t biosr_ax; + uint32_t biosr_cx; + uint32_t biosr_dx; + uint32_t biosr_bx; + uint32_t biosr_bp; + uint32_t biosr_si; + uint32_t biosr_di; + uint32_t biosr_ds; + uint32_t biosr_es; +} __packed BIOS_regs; + +#ifdef _KERNEL +#include + +struct bios_attach_args { + char *ba_name; + u_int ba_func; + bus_space_tag_t ba_iot; + bus_space_tag_t ba_memt; + union { + void *_p; + bios_apminfo_t *_ba_apmp; + paddr_t _ba_acpipbase; + } _; +}; + +#define ba_apmp _._ba_apmp +#define ba_acpipbase _._ba_acpipbase + +struct consdev; +struct proc; + +int bios_sysctl(int *, u_int, void *, size_t *, void *, size_t, struct proc *); + +void bios_getopt(void); +bios_diskinfo_t *bios_getdiskinfo(dev_t); + +extern int biosbasemem; +extern u_int bootapiver; +extern bios_memmap_t *bios_memmap; +extern bios_efiinfo_t *bios_efiinfo; +extern bios_ucode_t *bios_ucode; + +#endif /* _KERNEL */ +#endif /* _LOCORE */ +#endif /* _KERNEL || _STANDALONE */ + +#endif /* _MACHINE_BIOSVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/bus.h b/lib/libc/include/x86_64-openbsd-none/machine/bus.h new file mode 100644 index 000000000000..140e3a73f3d4 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/bus.h @@ -0,0 +1,706 @@ +/* $OpenBSD: bus.h,v 1.37 2025/08/23 10:15:49 sf Exp $ */ +/* $NetBSD: bus.h,v 1.6 1996/11/10 03:19:25 thorpej Exp $ */ + +/*- + * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1996 Charles M. Hannum. All rights reserved. + * Copyright (c) 1996 Jason R. Thorpe. All rights reserved. + * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BUS_H_ +#define _MACHINE_BUS_H_ + +#include +#include + +#include + +/* + * Bus address and size types + */ +typedef u_long bus_addr_t; +typedef u_long bus_size_t; + +/* + * Access methods for bus resources and address space. + */ +struct x86_bus_space_ops; +typedef const struct x86_bus_space_ops *bus_space_tag_t; +typedef u_long bus_space_handle_t; + +int bus_space_map(bus_space_tag_t t, bus_addr_t addr, + bus_size_t size, int flags, bus_space_handle_t *bshp); +/* like map, but without extent map checking/allocation */ +int _bus_space_map(bus_space_tag_t t, bus_addr_t addr, + bus_size_t size, int flags, bus_space_handle_t *bshp); + +int bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart, + bus_addr_t rend, bus_size_t size, bus_size_t align, + bus_size_t boundary, int flags, bus_addr_t *addrp, + bus_space_handle_t *bshp); +void bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t size); + +/* + * int bus_space_unmap(bus_space_tag_t t, + * bus_space_handle_t bsh, bus_size_t size); + * + * Unmap a region of bus space. + */ + +void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t size); +void _bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t size, bus_addr_t *); + +/* like bus_space_map(), but without extent map checking/allocation */ +int _bus_space_map(bus_space_tag_t t, bus_addr_t addr, + bus_size_t size, int flags, bus_space_handle_t *bshp); + +/* + * int bus_space_subregion(bus_space_tag_t t, + * bus_space_handle_t bsh, bus_size_t offset, bus_size_t size, + * bus_space_handle_t *nbshp); + * + * Get a new handle for a subregion of an already-mapped area of bus space. + */ + +int bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp); + +struct x86_bus_space_ops { + +/* + * u_intN_t bus_space_read_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset); + * + * Read a 1, 2, 4, or 8 byte quantity from bus space + * described by tag/handle/offset. + */ + u_int8_t (*read_1)(bus_space_handle_t, bus_size_t); + u_int16_t (*read_2)(bus_space_handle_t, bus_size_t); + u_int32_t (*read_4)(bus_space_handle_t, bus_size_t); + u_int64_t (*read_8)(bus_space_handle_t, bus_size_t); + +#define bus_space_read_1(_t, _h, _o) ((_t)->read_1((_h), (_o))) +#define bus_space_read_2(_t, _h, _o) ((_t)->read_2((_h), (_o))) +#define bus_space_read_4(_t, _h, _o) ((_t)->read_4((_h), (_o))) +#define bus_space_read_8(_t, _h, _o) ((_t)->read_8((_h), (_o))) + +#define bus_space_read_raw_2(_t, _h, _o) ((_t)->read_2((_h), (_o))) +#define bus_space_read_raw_4(_t, _h, _o) ((_t)->read_4((_h), (_o))) +#define bus_space_read_raw_8(_t, _h, _o) ((_t)->read_8((_h), (_o))) + +/* + * void bus_space_read_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t *addr, size_t count); + * + * Read `count' 1, 2, 4, or 8 byte quantities from bus space + * described by tag/handle/offset and copy into buffer provided. + */ + + void (*read_multi_1)(bus_space_handle_t, bus_size_t, + u_int8_t *, bus_size_t); + void (*read_multi_2)(bus_space_handle_t, bus_size_t, + u_int16_t *, bus_size_t); + void (*read_multi_4)(bus_space_handle_t, bus_size_t, + u_int32_t *, bus_size_t); + void (*read_multi_8)(bus_space_handle_t, bus_size_t, + u_int64_t *, bus_size_t); + +#define bus_space_read_multi_1(_t, _h, _o, _a, _c) \ + ((_t)->read_multi_1((_h), (_o), (_a), (_c))) +#define bus_space_read_multi_2(_t, _h, _o, _a, _c) \ + ((_t)->read_multi_2((_h), (_o), (_a), (_c))) +#define bus_space_read_multi_4(_t, _h, _o, _a, _c) \ + ((_t)->read_multi_4((_h), (_o), (_a), (_c))) +#define bus_space_read_multi_8(_t, _h, _o, _a, _c) \ + ((_t)->read_multi_8((_h), (_o), (_a), (_c))) + +/* + * void bus_space_read_raw_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_int8_t *addr, size_t count); + * + * Read `count' bytes in 2, 4 or 8 byte wide quantities from bus space + * described by tag/handle/offset and copy into buffer provided. The buffer + * must have proper alignment for the N byte wide entities. Furthermore + * possible byte-swapping should be done by these functions. + */ + +#define bus_space_read_raw_multi_2(_t, _h, _o, _a, _c) \ + ((_t)->read_multi_2((_h), (_o), (u_int16_t *)(_a), (_c) >> 1)) +#define bus_space_read_raw_multi_4(_t, _h, _o, _a, _c) \ + ((_t)->read_multi_4((_h), (_o), (u_int32_t *)(_a), (_c) >> 2)) +#define bus_space_read_raw_multi_8(_t, _h, _o, _a, _c) \ + ((_t)->read_multi_8((_h), (_o), (u_int64_t *)(_a), (_c) >> 3)) + +/* + * void bus_space_read_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t *addr, size_t count); + * + * Read `count' 1, 2, 4, or 8 byte quantities from bus space + * described by tag/handle and starting at `offset' and copy into + * buffer provided. + */ + + void (*read_region_1)(bus_space_handle_t, + bus_size_t, u_int8_t *, bus_size_t); + void (*read_region_2)(bus_space_handle_t, + bus_size_t, u_int16_t *, bus_size_t); + void (*read_region_4)(bus_space_handle_t, + bus_size_t, u_int32_t *, bus_size_t); + void (*read_region_8)(bus_space_handle_t, + bus_size_t, u_int64_t *, bus_size_t); + +#define bus_space_read_region_1(_t, _h, _o, _a, _c) \ + ((_t)->read_region_1((_h), (_o), (_a), (_c))) +#define bus_space_read_region_2(_t, _h, _o, _a, _c) \ + ((_t)->read_region_2((_h), (_o), (_a), (_c))) +#define bus_space_read_region_4(_t, _h, _o, _a, _c) \ + ((_t)->read_region_4((_h), (_o), (_a), (_c))) +#define bus_space_read_region_8(_t, _h, _o, _a, _c) \ + ((_t)->read_region_8((_h), (_o), (_a), (_c))) + +/* + * void bus_space_read_raw_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_int8_t *addr, size_t count); + * + * Read `count' bytes in 2, 4 or 8 byte wide quantities from bus space + * described by tag/handle and starting at `offset' and copy into + * buffer provided. The buffer must have proper alignment for the N byte + * wide entities. Furthermore possible byte-swapping should be done by + * these functions. + */ + +#define bus_space_read_raw_region_2(_t, _h, _o, _a, _c) \ + ((_t)->read_region_2((_h), (_o), (u_int16_t *)(_a), (_c) >> 1)) +#define bus_space_read_raw_region_4(_t, _h, _o, _a, _c) \ + ((_t)->read_region_4((_h), (_o), (u_int32_t *)(_a), (_c) >> 2)) +#define bus_space_read_raw_region_8(_t, _h, _o, _a, _c) \ + ((_t)->read_region_8((_h), (_o), (u_int64_t *)(_a), (_c) >> 3)) + +/* + * void bus_space_write_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t value); + * + * Write the 1, 2, 4, or 8 byte value `value' to bus space + * described by tag/handle/offset. + */ + + void (*write_1)(bus_space_handle_t, bus_size_t, u_int8_t); + void (*write_2)(bus_space_handle_t, bus_size_t, u_int16_t); + void (*write_4)(bus_space_handle_t, bus_size_t, u_int32_t); + void (*write_8)(bus_space_handle_t, bus_size_t, u_int64_t); + +#define bus_space_write_1(_t, _h, _o, _v) \ + ((_t)->write_1((_h), (_o), (_v))) +#define bus_space_write_2(_t, _h, _o, _v) \ + ((_t)->write_2((_h), (_o), (_v))) +#define bus_space_write_4(_t, _h, _o, _v) \ + ((_t)->write_4((_h), (_o), (_v))) +#define bus_space_write_8(_t, _h, _o, _v) \ + ((_t)->write_8((_h), (_o), (_v))) + +#define bus_space_write_raw_2(_t, _h, _o, _v) \ + ((_t)->write_2((_h), (_o), (_v))) +#define bus_space_write_raw_4(_t, _h, _o, _v) \ + ((_t)->write_4((_h), (_o), (_v))) +#define bus_space_write_raw_8(_t, _h, _o, _v) \ + ((_t)->write_8((_h), (_o), (_v))) + +/* + * void bus_space_write_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_intN_t *addr, size_t count); + * + * Write `count' 1, 2, 4, or 8 byte quantities from the buffer + * provided to bus space described by tag/handle/offset. + */ + + void (*write_multi_1)(bus_space_handle_t, + bus_size_t, const u_int8_t *, bus_size_t); + void (*write_multi_2)(bus_space_handle_t, + bus_size_t, const u_int16_t *, bus_size_t); + void (*write_multi_4)(bus_space_handle_t, + bus_size_t, const u_int32_t *, bus_size_t); + void (*write_multi_8)(bus_space_handle_t, + bus_size_t, const u_int64_t *, bus_size_t); + +#define bus_space_write_multi_1(_t, _h, _o, _a, _c) \ + ((_t)->write_multi_1((_h), (_o), (_a), (_c))) +#define bus_space_write_multi_2(_t, _h, _o, _a, _c) \ + ((_t)->write_multi_2((_h), (_o), (_a), (_c))) +#define bus_space_write_multi_4(_t, _h, _o, _a, _c) \ + ((_t)->write_multi_4((_h), (_o), (_a), (_c))) +#define bus_space_write_multi_8(_t, _h, _o, _a, _c) \ + ((_t)->write_multi_8((_h), (_o), (_a), (_c))) + +/* + * void bus_space_write_raw_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_int8_t *addr, size_t count); + * + * Write `count' bytes in 2, 4 or 8 byte wide quantities from the buffer + * provided to bus space described by tag/handle/offset. The buffer + * must have proper alignment for the N byte wide entities. Furthermore + * possible byte-swapping should be done by these functions. + */ + +#define bus_space_write_raw_multi_2(_t, _h, _o, _a, _c) \ + ((_t)->write_multi_2((_h), (_o), (const u_int16_t *)(_a), (_c) >> 1)) +#define bus_space_write_raw_multi_4(_t, _h, _o, _a, _c) \ + ((_t)->write_multi_4((_h), (_o), (const u_int32_t *)(_a), (_c) >> 2)) +#define bus_space_write_raw_multi_8(_t, _h, _o, _a, _c) \ + ((_t)->write_multi_8((_h), (_o), (const u_int64_t *)(_a), (_c) >> 3)) + +/* + * void bus_space_write_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_intN_t *addr, size_t count); + * + * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided + * to bus space described by tag/handle starting at `offset'. + */ + + void (*write_region_1)(bus_space_handle_t, + bus_size_t, const u_int8_t *, bus_size_t); + void (*write_region_2)(bus_space_handle_t, + bus_size_t, const u_int16_t *, bus_size_t); + void (*write_region_4)(bus_space_handle_t, + bus_size_t, const u_int32_t *, bus_size_t); + void (*write_region_8)(bus_space_handle_t, + bus_size_t, const u_int64_t *, bus_size_t); + +#define bus_space_write_region_1(_t, _h, _o, _a, _c) \ + ((_t)->write_region_1((_h), (_o), (_a), (_c))) +#define bus_space_write_region_2(_t, _h, _o, _a, _c) \ + ((_t)->write_region_2((_h), (_o), (_a), (_c))) +#define bus_space_write_region_4(_t, _h, _o, _a, _c) \ + ((_t)->write_region_4((_h), (_o), (_a), (_c))) +#define bus_space_write_region_8(_t, _h, _o, _a, _c) \ + ((_t)->write_region_8((_h), (_o), (_a), (_c))) + +/* + * void bus_space_write_raw_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_int8_t *addr, size_t count); + * + * Write `count' bytes in 2, 4 or 8 byte wide quantities to bus space + * described by tag/handle and starting at `offset' from the + * buffer provided. The buffer must have proper alignment for the N byte + * wide entities. Furthermore possible byte-swapping should be done by + * these functions. + */ + +#define bus_space_write_raw_region_2(_t, _h, _o, _a, _c) \ + ((_t)->write_region_2((_h), (_o), (const u_int16_t *)(_a), (_c) >> 1)) +#define bus_space_write_raw_region_4(_t, _h, _o, _a, _c) \ + ((_t)->write_region_4((_h), (_o), (const u_int32_t *)(_a), (_c) >> 2)) +#define bus_space_write_raw_region_8(_t, _h, _o, _a, _c) \ + ((_t)->write_region_8((_h), (_o), (const u_int64_t *)(_a), (_c) >> 3)) + +/* + * void bus_space_set_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t val, size_t count); + * + * Write the 1, 2, 4, or 8 byte value `val' to bus space described + * by tag/handle/offset `count' times. + */ + + void (*set_multi_1)(bus_space_handle_t, + bus_size_t, u_int8_t, size_t); + void (*set_multi_2)(bus_space_handle_t, + bus_size_t, u_int16_t, size_t); + void (*set_multi_4)(bus_space_handle_t, + bus_size_t, u_int32_t, size_t); + void (*set_multi_8)(bus_space_handle_t, + bus_size_t, u_int64_t, size_t); + +#define bus_space_set_multi_1(_t, _h, _o, _a, _c) \ + ((_t)->set_multi_1((_h), (_o), (_a), (_c))) +#define bus_space_set_multi_2(_t, _h, _o, _a, _c) \ + ((_t)->set_multi_2((_h), (_o), (_a), (_c))) +#define bus_space_set_multi_4(_t, _h, _o, _a, _c) \ + ((_t)->set_multi_4((_h), (_o), (_a), (_c))) +#define bus_space_set_multi_8(_t, _h, _o, _a, _c) \ + ((_t)->set_multi_8((_h), (_o), (_a), (_c))) + +/* + * void bus_space_set_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t val, size_t count); + * + * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described + * by tag/handle starting at `offset'. + */ + + void (*set_region_1)(bus_space_handle_t, + bus_size_t, u_int8_t, size_t); + void (*set_region_2)(bus_space_handle_t, + bus_size_t, u_int16_t, size_t); + void (*set_region_4)(bus_space_handle_t, + bus_size_t, u_int32_t, size_t); + void (*set_region_8)(bus_space_handle_t, + bus_size_t, u_int64_t, size_t); + +#define bus_space_set_region_1(_t, _h, _o, _a, _c) \ + ((_t)->set_region_1((_h), (_o), (_a), (_c))) +#define bus_space_set_region_2(_t, _h, _o, _a, _c) \ + ((_t)->set_region_2((_h), (_o), (_a), (_c))) +#define bus_space_set_region_4(_t, _h, _o, _a, _c) \ + ((_t)->set_region_4((_h), (_o), (_a), (_c))) +#define bus_space_set_region_8(_t, _h, _o, _a, _c) \ + ((_t)->set_region_8((_h), (_o), (_a), (_c))) + +/* + * void bus_space_copy_N(bus_space_tag_t tag, + * bus_space_handle_t bsh1, bus_size_t off1, + * bus_space_handle_t bsh2, bus_size_t off2, + * size_t count); + * + * Copy `count' 1, 2, 4, or 8 byte values from bus space starting + * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2. + */ + + void (*copy_1)(bus_space_handle_t, + bus_size_t, bus_space_handle_t, bus_size_t, size_t); + void (*copy_2)(bus_space_handle_t, + bus_size_t, bus_space_handle_t, bus_size_t, size_t); + void (*copy_4)(bus_space_handle_t, + bus_size_t, bus_space_handle_t, bus_size_t, size_t); + void (*copy_8)(bus_space_handle_t, + bus_size_t, bus_space_handle_t, bus_size_t, size_t); + +#define bus_space_copy_1(_t, _h1, _o1, _h2, _o2, _c) \ + ((_t)->copy_1((_h1), (_o1), (_h2), (_o2), (_c))) +#define bus_space_copy_2(_t, _h1, _o1, _h2, _o2, _c) \ + ((_t)->copy_2((_h1), (_o1), (_h2), (_o2), (_c))) +#define bus_space_copy_4(_t, _h1, _o1, _h2, _o2, _c) \ + ((_t)->copy_4((_h1), (_o1), (_h2), (_o2), (_c))) +#define bus_space_copy_8(_t, _h1, _o1, _h2, _o2, _c) \ + ((_t)->copy_8((_h1), (_o1), (_h2), (_o2), (_c))) + +/* + * void *bus_space_vaddr(bus_space_tag_t, bus_space_handle_t); + * + * Get the kernel virtual address for the mapped bus space. + * Only allowed for regions mapped with BUS_SPACE_MAP_LINEAR. + */ + void * (*vaddr)(bus_space_handle_t); + +#define bus_space_vaddr(_t, _h) \ + ((_t)->vaddr((_h))) + +/* + * paddr_t bus_space_mmap(bus_space_tag_t t, bus_addr_t base, + * off_t offset, int prot, int flags); + * + * Mmap an area of bus space. + */ + + paddr_t (*mmap)(bus_addr_t, off_t, int, int); + +#define bus_space_mmap(_t, _a, _o, _p, _f) \ + ((_t)->mmap((_a), (_o), (_p), (_f))) +}; + +/* + * Bus read/write barrier methods. + */ +#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ +#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ + +static inline void +bus_space_barrier(bus_space_tag_t space, bus_space_handle_t + handle, bus_size_t offset, bus_size_t length, int flags) +{ + switch (flags) { + case (BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE): + __asm volatile("mfence" ::: "memory"); + break; + case BUS_SPACE_BARRIER_WRITE: + __asm volatile("sfence" ::: "memory"); + break; + default: + __asm volatile("lfence" ::: "memory"); + break; + } +} + +#define BUS_SPACE_MAP_CACHEABLE 0x0001 +#define BUS_SPACE_MAP_LINEAR 0x0002 +#define BUS_SPACE_MAP_PREFETCHABLE 0x0008 + +/* + * Values for the x86 bus space tag, not to be used directly by MI code. + */ + +/* space is i/o space */ +extern const struct x86_bus_space_ops *x86_bus_space_io_ops; +#define X86_BUS_SPACE_IO (x86_bus_space_io_ops) + +/* space is mem space */ +extern const struct x86_bus_space_ops *x86_bus_space_mem_ops; +#define X86_BUS_SPACE_MEM (x86_bus_space_mem_ops) + +/* + * bus_dma + */ + +/* + * Flags used in various bus DMA methods. + */ +#define BUS_DMA_WAITOK 0x0000 /* safe to sleep (pseudo-flag) */ +#define BUS_DMA_NOWAIT 0x0001 /* not safe to sleep */ +#define BUS_DMA_ALLOCNOW 0x0002 /* perform resource allocation now */ +#define BUS_DMA_COHERENT 0x0004 /* hint: map memory DMA coherent */ +#define BUS_DMA_BUS1 0x0010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x0020 +#define BUS_DMA_32BIT 0x0040 +#define BUS_DMA_24BIT 0x0080 /* isadma map */ +#define BUS_DMA_STREAMING 0x0100 /* hint: sequential, unidirectional */ +#define BUS_DMA_READ 0x0200 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x0400 /* mapping is memory -> device only */ +#define BUS_DMA_NOCACHE 0x0800 /* map memory uncached */ +#define BUS_DMA_ZERO 0x1000 /* zero memory in dmamem_alloc */ +#define BUS_DMA_64BIT 0x2000 /* device handles 64bit dva */ + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct proc; +struct uio; + +/* + * Operations performed by bus_dmamap_sync(). + */ +#define BUS_DMASYNC_PREREAD 0x01 +#define BUS_DMASYNC_POSTREAD 0x02 +#define BUS_DMASYNC_PREWRITE 0x04 +#define BUS_DMASYNC_POSTWRITE 0x08 + +typedef struct bus_dma_tag *bus_dma_tag_t; +typedef struct bus_dmamap *bus_dmamap_t; + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +struct bus_dma_segment { + bus_addr_t ds_addr; /* DMA address */ + bus_size_t ds_len; /* length of transfer */ + vaddr_t _ds_va; /* mapped loaded data */ + vaddr_t _ds_bounce_va; /* mapped bounced data */ + + /* + * Ugh. need this so can pass alignment down from bus_dmamem_alloc + * to scatter gather maps. only the first one is used so the rest is + * wasted space. bus_dma could do with fixing the api for this. + */ + bus_size_t _ds_boundary; /* don't cross */ + bus_size_t _ds_align; /* align to me */ +}; +typedef struct bus_dma_segment bus_dma_segment_t; + +/* + * bus_dma_tag_t + * + * A machine-dependent opaque type describing the implementation of + * DMA for a given bus. + */ + +struct bus_dma_tag { + void *_cookie; /* cookie used in the guts */ + + /* + * DMA mapping methods. + */ + int (*_dmamap_create)(bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); + void (*_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t); + int (*_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); + int (*_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t, + struct mbuf *, int); + int (*_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t, + struct uio *, int); + int (*_dmamap_load_raw)(bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); + void (*_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t); + void (*_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t, + bus_addr_t, bus_size_t, int); + + /* + * DMA memory utility functions. + */ + int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); + int (*_dmamem_alloc_range)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int, + bus_addr_t, bus_addr_t); + void (*_dmamem_free)(bus_dma_tag_t, + bus_dma_segment_t *, int); + int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); + void (*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t); + paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, + int, off_t, int, int); +}; + +#define bus_dmamap_create(t, s, n, m, b, f, p) \ + (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) +#define bus_dmamap_destroy(t, p) \ + (*(t)->_dmamap_destroy)((t), (p)) +#define bus_dmamap_load(t, m, b, s, p, f) \ + (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) +#define bus_dmamap_load_mbuf(t, m, b, f) \ + (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) +#define bus_dmamap_load_uio(t, m, u, f) \ + (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) +#define bus_dmamap_load_raw(t, m, sg, n, s, f) \ + (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) +#define bus_dmamap_unload(t, p) \ + (*(t)->_dmamap_unload)((t), (p)) +#define bus_dmamap_sync(t, p, o, l, ops) \ + (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops)) + +#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ + (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f)) +#define bus_dmamem_alloc_range(t, s, a, b, sg, n, r, f, l, h) \ + (*(t)->_dmamem_alloc_range)((t), (s), (a), (b), (sg), \ + (n), (r), (f), (l), (h)) +#define bus_dmamem_free(t, sg, n) \ + (*(t)->_dmamem_free)((t), (sg), (n)) +#define bus_dmamem_map(t, sg, n, s, k, f) \ + (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f)) +#define bus_dmamem_unmap(t, k, s) \ + (*(t)->_dmamem_unmap)((t), (k), (s)) +#define bus_dmamem_mmap(t, sg, n, o, p, f) \ + (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f)) + +/* + * bus_dmamap_t + * + * Describes a DMA mapping. + */ +struct bus_dmamap { + /* + * PRIVATE MEMBERS: not for use by machine-independent code. + */ + bus_size_t _dm_size; /* largest DMA transfer mappable */ + int _dm_flags; /* misc. flags */ + int _dm_segcnt; /* number of segs this map can map */ + bus_size_t _dm_maxsegsz; /* largest possible segment */ + bus_size_t _dm_boundary; /* don't cross this */ + + void *_dm_cookie; /* cookie for bus-specific functions */ + + struct vm_page **_dm_pages; /* replacement pages */ + vaddr_t _dm_pgva; /* those above -- mapped */ + int _dm_npages; /* number of pages allocated */ + int _dm_nused; /* number of pages replaced */ + + /* + * PUBLIC MEMBERS: these are used by machine-independent code. + */ + bus_size_t dm_mapsize; /* size of the mapping */ + int dm_nsegs; /* # valid segments in mapping */ + bus_dma_segment_t dm_segs[1]; /* segments; variable length */ +}; + +int _bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t, + bus_size_t, int, bus_dmamap_t *); +void _bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); +int _bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); +int _bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, + struct mbuf *, int); +int _bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, + struct uio *, int); +int _bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); +void _bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t); +void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, + bus_size_t, int); + +int _bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size, + bus_size_t alignment, bus_size_t boundary, + bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags); +void _bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs); +int _bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs, size_t size, caddr_t *kvap, int flags); +void _bus_dmamem_unmap(bus_dma_tag_t tag, caddr_t kva, + size_t size); +paddr_t _bus_dmamem_mmap(bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs, off_t off, int prot, int flags); + +int _bus_dmamem_alloc_range(bus_dma_tag_t tag, bus_size_t size, + bus_size_t alignment, bus_size_t boundary, + bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags, + bus_addr_t low, bus_addr_t high); + +#endif /* _MACHINE_BUS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/cdefs.h b/lib/libc/include/x86_64-openbsd-none/machine/cdefs.h new file mode 100644 index 000000000000..cd6f968643f2 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/cdefs.h @@ -0,0 +1,21 @@ +/* $OpenBSD: cdefs.h,v 1.3 2013/03/28 17:30:45 martynas Exp $ */ + +/* + * Written by J.T. Conklin 01/17/95. + * Public domain. + */ + +#ifndef _MACHINE_CDEFS_H_ +#define _MACHINE_CDEFS_H_ + +#define __strong_alias(alias,sym) \ + __asm__(".global " __STRING(alias) " ; " __STRING(alias) \ + " = " __STRING(sym)) +#define __weak_alias(alias,sym) \ + __asm__(".weak " __STRING(alias) " ; " __STRING(alias) \ + " = " __STRING(sym)) +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning." __STRING(sym) \ + " ; .ascii \"" msg "\" ; .text") + +#endif /* !_MACHINE_CDEFS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/codepatch.h b/lib/libc/include/x86_64-openbsd-none/machine/codepatch.h new file mode 100644 index 000000000000..04ea726a26f3 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/codepatch.h @@ -0,0 +1,120 @@ +/* $OpenBSD: codepatch.h,v 1.19 2024/02/12 01:18:17 guenther Exp $ */ +/* + * Copyright (c) 2014-2015 Stefan Fritsch + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_CODEPATCH_H_ +#define _MACHINE_CODEPATCH_H_ + +#include + +#ifndef _LOCORE + +/* code in this section will be unmapped after boot */ +#define __cptext __attribute__((section(".cptext"))) + +__cptext void *codepatch_maprw(vaddr_t *nva, vaddr_t dest); +__cptext void codepatch_unmaprw(vaddr_t nva); +__cptext void codepatch_fill_nop(void *caddr, uint16_t len); +__cptext void codepatch_nop(uint16_t tag); +__cptext void codepatch_replace(uint16_t tag, const void *code, size_t len); +__cptext void codepatch_call(uint16_t _tag, void *_func); +__cptext void codepatch_jmp(uint16_t _tag, void *_func); +void codepatch_disable(void); + +#endif /* !_LOCORE */ + +/* + * Mark the start of some code snippet to be patched. + */ +#define CODEPATCH_START 998: +/* + * Mark the end of some code to be patched, and assign the given tag. + */ +#define CODEPATCH_END2(startnum,tag) \ + 999: \ + .section .codepatch, "a" ;\ + .quad startnum##b ;\ + .short (999b - startnum##b) ;\ + .short tag ;\ + .int 0 ;\ + .previous +#define CODEPATCH_END(tag) CODEPATCH_END2(998,tag) + +#define CPTAG_STAC 1 +#define CPTAG_CLAC 2 +#define CPTAG_EOI 3 +#define CPTAG_XRSTOR 4 +#define CPTAG_XSAVE 5 +#define CPTAG_MELTDOWN_NOP 6 +#define CPTAG_MELTDOWN_ALLTRAPS 7 +#define CPTAG_PCID_SET_REUSE 8 +#define CPTAG_MDS 9 +#define CPTAG_MDS_VMM 10 +#define CPTAG_FENCE_SWAPGS_MIS_TAKEN 11 +#define CPTAG_FENCE_NO_SAFE_SMAP 12 +#define CPTAG_XRSTORS 13 +#define CPTAG_RETPOLINE_RAX 14 +#define CPTAG_RETPOLINE_R11 15 +#define CPTAG_RETPOLINE_R13 16 +#define CPTAG_IBPB_NOP 17 + +/* + * stac/clac SMAP instructions have lfence like semantics. Let's + * guarantee those semantics on older cpus. + */ +#define SMAP_NOP lfence +#define SMAP_STAC CODEPATCH_START ;\ + SMAP_NOP ;\ + CODEPATCH_END(CPTAG_STAC) +#define SMAP_CLAC CODEPATCH_START ;\ + SMAP_NOP ;\ + CODEPATCH_END(CPTAG_CLAC) + +/* CVE-2019-1125: block speculation after swapgs */ +#define FENCE_SWAPGS_MIS_TAKEN \ + CODEPATCH_START ; \ + lfence ; \ + CODEPATCH_END(CPTAG_FENCE_SWAPGS_MIS_TAKEN) +/* block speculation when a correct SMAP impl would have been enough */ +#define FENCE_NO_SAFE_SMAP \ + CODEPATCH_START ; \ + lfence ; \ + CODEPATCH_END(CPTAG_FENCE_NO_SAFE_SMAP) + +#define PCID_SET_REUSE_SIZE 12 +#define PCID_SET_REUSE_NOP \ + 997: ;\ + .byte 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 ;\ + .byte 0x0f, 0x1f, 0x40, 0x00 ;\ + CODEPATCH_END2(997, CPTAG_PCID_SET_REUSE) + +/* Would be neat if these could be in something like .cptext */ +#define CODEPATCH_CODE(symbol, instructions...) \ + .section .rodata; \ + .globl symbol; \ +symbol: instructions; \ + .size symbol, . - symbol + +/* provide a (short) variable with the length of the patch */ +#define CODEPATCH_CODE_LEN(symbol, instructions...) \ + CODEPATCH_CODE(symbol, instructions); \ +996: .globl symbol##_len; \ + .align 2; \ +symbol##_len: \ + .short 996b - symbol; \ + .size symbol##_len, 2 + +#endif /* _MACHINE_CODEPATCH_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/conf.h b/lib/libc/include/x86_64-openbsd-none/machine/conf.h new file mode 100644 index 000000000000..bd23d33ba71b --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/conf.h @@ -0,0 +1,59 @@ +/* $OpenBSD: conf.h,v 1.11 2024/09/04 07:45:08 jsg Exp $ */ +/* $NetBSD: conf.h,v 1.2 1996/05/05 19:28:34 christos Exp $ */ + +/* + * Copyright (c) 1996 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#define mmread mmrw +#define mmwrite mmrw +cdev_decl(mm); + +bdev_decl(fd); +cdev_decl(fd); + +cdev_decl(spkr); + +cdev_decl(bios); + +#define cdev_acpi_init(c,n) {\ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev, 0, 0, dev_init(c,n,kqfilter) } +cdev_decl(acpi); + +cdev_decl(pctr); + +#include "vmm.h" +cdev_decl(vmm); + +#include "psp.h" +cdev_decl(psp); \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/cpu.h b/lib/libc/include/x86_64-openbsd-none/machine/cpu.h new file mode 100644 index 000000000000..d3cab29e55ae --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/cpu.h @@ -0,0 +1,530 @@ +/* $OpenBSD: cpu.h,v 1.180 2025/04/28 16:18:25 bluhm Exp $ */ +/* $NetBSD: cpu.h,v 1.1 2003/04/26 18:39:39 fvdl Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)cpu.h 5.4 (Berkeley) 5/9/91 + */ + +#ifndef _MACHINE_CPU_H_ +#define _MACHINE_CPU_H_ + +/* + * Definitions unique to x86-64 cpu support. + */ +#ifdef _KERNEL +#include +#include /* USERMODE */ +#include +#endif /* _KERNEL */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef _KERNEL + +/* VMXON region (Intel) */ +struct vmxon_region { + uint32_t vr_revision; +}; + +/* + * VMX for Intel CPUs + */ +struct vmx { + uint64_t vmx_cr0_fixed0; + uint64_t vmx_cr0_fixed1; + uint64_t vmx_cr4_fixed0; + uint64_t vmx_cr4_fixed1; + uint32_t vmx_vmxon_revision; + uint32_t vmx_msr_table_size; + uint32_t vmx_cr3_tgt_count; + uint8_t vmx_has_l1_flush_msr; + uint64_t vmx_invept_mode; +}; + +/* + * SVM for AMD CPUs + */ +struct svm { + uint32_t svm_max_asid; + uint8_t svm_flush_by_asid; + uint8_t svm_vmcb_clean; + uint8_t svm_decode_assist; +}; + +union vmm_cpu_cap { + struct vmx vcc_vmx; + struct svm vcc_svm; +}; + +enum cpu_vendor { + CPUV_UNKNOWN, + CPUV_AMD, + CPUV_INTEL, + CPUV_VIA, +}; + +/* + * Locks used to protect struct members in this file: + * I immutable after creation + * a atomic operations + * o owned (read/modified only) by this CPU + */ +struct x86_64_tss; +struct vcpu; +struct cpu_info { + /* + * The beginning of this structure in mapped in the userspace "u-k" + * page tables, so that these first couple members can be accessed + * from the trampoline code. The ci_PAGEALIGN member defines where + * the part that is *not* visible begins, so don't put anything + * above it that must be kept hidden from userspace! + */ + u_int64_t ci_kern_cr3; /* [o] U+K page table */ + u_int64_t ci_scratch; /* [o] for U<-->K transition */ + +#define ci_PAGEALIGN ci_dev + struct device *ci_dev; /* [I] */ + struct cpu_info *ci_self; /* [I] */ + struct cpu_info *ci_next; /* [I] */ + + u_int ci_cpuid; /* [I] */ + u_int ci_apicid; /* [I] */ + u_int ci_acpi_proc_id; /* [I] */ + u_int32_t ci_randseed; /* [o] */ + + u_int64_t ci_kern_rsp; /* [o] kernel-only stack */ + u_int64_t ci_intr_rsp; /* [o] U<-->K trampoline stack */ + u_int64_t ci_user_cr3; /* [o] U-K page table */ + + /* bits for mitigating Micro-architectural Data Sampling */ + char ci_mds_tmp[64]; /* [o] 64-byte aligned */ + void *ci_mds_buf; /* [I] */ + + struct proc *ci_curproc; /* [o] */ + struct schedstate_percpu ci_schedstate; /* scheduler state */ + + struct pmap *ci_proc_pmap; /* active, non-kernel pmap */ + struct pmap *ci_user_pmap; /* [o] last pmap used in userspace */ + struct pcb *ci_curpcb; /* [o] */ + struct pcb *ci_idle_pcb; /* [o] */ + + u_int ci_pflags; /* [o] */ +#define CPUPF_USERSEGS 0x01 /* CPU has curproc's segs and FS.base */ +#define CPUPF_USERXSTATE 0x02 /* CPU has curproc's xsave state */ + + struct intrsource *ci_isources[MAX_INTR_SOURCES]; + u_int64_t ci_ipending; + int ci_ilevel; + int ci_idepth; + int ci_handled_intr_level; + u_int64_t ci_imask[NIPL]; + u_int64_t ci_iunmask[NIPL]; +#ifdef DIAGNOSTIC + int ci_mutex_level; +#endif + + volatile u_int ci_flags; /* [a] */ + u_int32_t ci_ipis; /* [a] */ + + enum cpu_vendor ci_vendor; /* [I] mapped from cpuid(0) */ + u_int32_t ci_cpuid_level; /* [I] cpuid(0).eax */ + u_int32_t ci_feature_flags; /* [I] */ + u_int32_t ci_feature_eflags; /* [I] */ + u_int32_t ci_feature_sefflags_ebx;/* [I] */ + u_int32_t ci_feature_sefflags_ecx;/* [I] */ + u_int32_t ci_feature_sefflags_edx;/* [I] */ + u_int32_t ci_feature_amdspec_ebx; /* [I] */ + u_int32_t ci_feature_amdsev_eax; /* [I] */ + u_int32_t ci_feature_amdsev_ebx; /* [I] */ + u_int32_t ci_feature_amdsev_ecx; /* [I] */ + u_int32_t ci_feature_amdsev_edx; /* [I] */ + u_int32_t ci_feature_tpmflags; /* [I] */ + u_int32_t ci_pnfeatset; /* [I] */ + u_int32_t ci_efeature_eax; /* [I] */ + u_int32_t ci_efeature_ecx; /* [I] */ + u_int32_t ci_brand[12]; /* [I] */ + u_int32_t ci_signature; /* [I] */ + u_int32_t ci_family; /* [I] */ + u_int32_t ci_model; /* [I] */ + u_int32_t ci_cflushsz; /* [I] */ + + int ci_inatomic; /* [o] */ + +#define __HAVE_CPU_TOPOLOGY + u_int32_t ci_smt_id; /* [I] */ + u_int32_t ci_core_id; /* [I] */ + u_int32_t ci_pkg_id; /* [I] */ + + struct cpu_functions *ci_func; /* [I] */ + void (*cpu_setup)(struct cpu_info *); /* [I] */ + + struct device *ci_acpicpudev; /* [I] */ + volatile u_int ci_mwait; /* [a] */ +#define MWAIT_IN_IDLE 0x1 /* don't need IPI to wake */ +#define MWAIT_KEEP_IDLING 0x2 /* cleared by other cpus to wake me */ +#define MWAIT_ONLY 0x4 /* set if all idle states use mwait */ +#define MWAIT_IDLING (MWAIT_IN_IDLE | MWAIT_KEEP_IDLING) + + int ci_want_resched; + + struct x86_64_tss *ci_tss; /* [o] */ + void *ci_gdt; /* [o] */ + + volatile int ci_ddb_paused; +#define CI_DDB_RUNNING 0 +#define CI_DDB_SHOULDSTOP 1 +#define CI_DDB_STOPPED 2 +#define CI_DDB_ENTERDDB 3 +#define CI_DDB_INDDB 4 + +#ifdef MULTIPROCESSOR + struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM]; +#define __HAVE_UVM_PERCPU + struct uvm_pmr_cache ci_uvm; /* [o] page cache */ +#endif + + struct ksensordev ci_sensordev; + struct ksensor ci_sensor; + struct ksensor ci_hz_sensor; + u_int64_t ci_hz_mperf; + u_int64_t ci_hz_aperf; +#if defined(GPROF) || defined(DDBPROF) + struct gmonparam *ci_gmon; + struct clockintr ci_gmonclock; +#endif + u_int32_t ci_vmm_flags; +#define CI_VMM_VMX (1 << 0) +#define CI_VMM_SVM (1 << 1) +#define CI_VMM_RVI (1 << 2) +#define CI_VMM_EPT (1 << 3) +#define CI_VMM_DIS (1 << 4) + union vmm_cpu_cap ci_vmm_cap; + paddr_t ci_vmxon_region_pa; + struct vmxon_region *ci_vmxon_region; + paddr_t ci_vmcs_pa; + struct rwlock ci_vmcs_lock; + struct pmap *ci_ept_pmap; /* [o] last used EPT pmap */ + struct vcpu *ci_guest_vcpu; /* [o] last vcpu resumed */ + + char ci_panicbuf[512]; + + struct clockqueue ci_queue; +}; + +#define CPUF_BSP 0x0001 /* CPU is the original BSP */ +#define CPUF_AP 0x0002 /* CPU is an AP */ +#define CPUF_SP 0x0004 /* CPU is only processor */ +#define CPUF_PRIMARY 0x0008 /* CPU is active primary processor */ + +#define CPUF_IDENTIFY 0x0010 /* CPU may now identify */ +#define CPUF_IDENTIFIED 0x0020 /* CPU has been identified */ + +#define CPUF_CONST_TSC 0x0040 /* CPU has constant TSC */ +#define CPUF_INVAR_TSC 0x0100 /* CPU has invariant TSC */ + +#define CPUF_PRESENT 0x1000 /* CPU is present */ +#define CPUF_RUNNING 0x2000 /* CPU is running */ +#define CPUF_PAUSE 0x4000 /* CPU is paused in DDB */ +#define CPUF_GO 0x8000 /* CPU should start running */ +#define CPUF_PARK 0x10000 /* CPU should self-park in real mode */ +#define CPUF_VMM 0x20000 /* CPU is executing in VMM mode */ + +#define PROC_PC(p) ((p)->p_md.md_regs->tf_rip) +#define PROC_STACK(p) ((p)->p_md.md_regs->tf_rsp) + +struct cpu_info_full; +extern struct cpu_info_full cpu_info_full_primary; +#define cpu_info_primary (*(struct cpu_info *)((char *)&cpu_info_full_primary + 4096*2 - offsetof(struct cpu_info, ci_PAGEALIGN))) + +extern struct cpu_info *cpu_info_list; + +#define CPU_INFO_ITERATOR int +#define CPU_INFO_FOREACH(cii, ci) for (cii = 0, ci = cpu_info_list; \ + ci != NULL; ci = ci->ci_next) + +#define CPU_INFO_UNIT(ci) ((ci)->ci_dev ? (ci)->ci_dev->dv_unit : 0) + +/* + * Preempt the current process if in interrupt from user mode, + * or after the current trap/syscall if in system mode. + */ +extern void need_resched(struct cpu_info *); +#define clear_resched(ci) (ci)->ci_want_resched = 0 + +#if defined(MULTIPROCESSOR) + +#define MAXCPUS 64 /* bitmask */ + +#define CPU_STARTUP(_ci) ((_ci)->ci_func->start(_ci)) +#define CPU_STOP(_ci) ((_ci)->ci_func->stop(_ci)) +#define CPU_START_CLEANUP(_ci) ((_ci)->ci_func->cleanup(_ci)) + +#define curcpu() ({struct cpu_info *__ci; \ + asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) \ + :"n" (offsetof(struct cpu_info, ci_self))); \ + __ci;}) +#define cpu_number() (curcpu()->ci_cpuid) + +#define CPU_IS_PRIMARY(ci) ((ci)->ci_flags & CPUF_PRIMARY) +#define CPU_IS_RUNNING(ci) ((ci)->ci_flags & CPUF_RUNNING) + +extern struct cpu_info *cpu_info[MAXCPUS]; + +void cpu_boot_secondary_processors(void); + +void cpu_kick(struct cpu_info *); +void cpu_unidle(struct cpu_info *); + +#define CPU_BUSY_CYCLE() __asm volatile("pause": : : "memory") + +#else /* !MULTIPROCESSOR */ + +#define MAXCPUS 1 + +#ifdef _KERNEL +#define curcpu() (&cpu_info_primary) + +#define cpu_kick(ci) +#define cpu_unidle(ci) + +#define CPU_BUSY_CYCLE() __asm volatile ("" ::: "memory") + +#endif + +/* + * definitions of cpu-dependent requirements + * referenced in generic code + */ +#define cpu_number() 0 +#define CPU_IS_PRIMARY(ci) 1 +#define CPU_IS_RUNNING(ci) 1 + +#endif /* MULTIPROCESSOR */ + +#include +#include + +static inline unsigned int +cpu_rnd_messybits(void) +{ + unsigned int hi, lo; + + __asm volatile("rdtsc" : "=d" (hi), "=a" (lo)); + + return (hi ^ lo); +} + +#endif /* _KERNEL */ + +#ifdef MULTIPROCESSOR +#include +#endif + +#define aston(p) ((p)->p_md.md_astpending = 1) + +#define curpcb curcpu()->ci_curpcb + +/* + * Arguments to hardclock, softclock and statclock + * encapsulate the previous machine state in an opaque + * clockframe; for now, use generic intrframe. + */ +#define clockframe intrframe + +#define CLKF_USERMODE(frame) USERMODE((frame)->if_cs, (frame)->if_rflags) +#define CLKF_PC(frame) ((frame)->if_rip) +#define CLKF_INTR(frame) (curcpu()->ci_idepth > 1) + +/* + * Give a profiling tick to the current process when the user profiling + * buffer pages are invalid. On the i386, request an ast to send us + * through usertrap(), marking the proc as needing a profiling tick. + */ +#define need_proftick(p) aston(p) + +void signotify(struct proc *); + +/* + * We need a machine-independent name for this. + */ +extern void (*delay_func)(int); +void delay_fini(void (*)(int)); +void delay_init(void (*)(int), int); +struct timeval; + +#define DELAY(x) (*delay_func)(x) +#define delay(x) (*delay_func)(x) + + +#ifdef _KERNEL +/* cpu.c */ +extern int cpu_feature; +extern int cpu_ebxfeature; +extern int cpu_ecxfeature; +extern int ecpu_ecxfeature; +extern int cpu_sev_guestmode; +extern int cpu_id; +extern char cpu_vendor[]; +extern int cpuid_level; +extern int cpu_meltdown; +extern u_int cpu_mwait_size; +extern u_int cpu_mwait_states; + +int cpu_suspend_primary(void); + +/* cacheinfo.c */ +void x86_print_cacheinfo(struct cpu_info *); + +/* identcpu.c */ +void identifycpu(struct cpu_info *); +int cpu_amd64speed(int *); +extern int cpuspeed; +extern int amd64_pos_cbit; +extern int amd64_min_noes_asid; + +/* machdep.c */ +void dumpconf(void); +void cpu_set_vendor(struct cpu_info *, int _level, const char *_vendor); +void cpu_reset(void); +void x86_64_proc0_tss_ldt_init(void); +int amd64_pa_used(paddr_t); +#define cpu_idle_enter() do { /* nothing */ } while (0) +extern void (*cpu_idle_cycle_fcn)(void); +extern void (*cpu_suspend_cycle_fcn)(void); +#define cpu_idle_cycle() (*cpu_idle_cycle_fcn)() +#define cpu_idle_leave() do { /* nothing */ } while (0) +extern void (*initclock_func)(void); +extern void (*startclock_func)(void); + +struct region_descriptor; +void lgdt(struct region_descriptor *); + +struct pcb; +void savectx(struct pcb *); +void proc_trampoline(void); + +/* clock.c */ +void startclocks(void); +void rtcinit(void); +void rtcstart(void); +void rtcstop(void); +void i8254_delay(int); +void i8254_initclocks(void); +void i8254_startclock(void); +void i8254_start_both_clocks(void); +void i8254_inittimecounter(void); +void i8254_inittimecounter_simple(void); + +/* i8259.c */ +void i8259_default_setup(void); + +void cpu_init_msrs(struct cpu_info *); +void cpu_fix_msrs(struct cpu_info *); +void cpu_tsx_disable(struct cpu_info *); + +/* dkcsum.c */ +void dkcsumattach(void); + +/* bus_machdep.c */ +void x86_bus_space_init(void); +void x86_bus_space_mallocok(void); + +/* powernow-k8.c */ +void k8_powernow_init(struct cpu_info *); +void k8_powernow_setperf(int); + +/* k1x-pstate.c */ +void k1x_init(struct cpu_info *); +void k1x_setperf(int); + +void est_init(struct cpu_info *); +void est_setperf(int); + +#ifdef MULTIPROCESSOR +/* mp_setperf.c */ +void mp_setperf_init(void); +#endif + +#endif /* _KERNEL */ + +/* + * CTL_MACHDEP definitions. + */ +#define CPU_CONSDEV 1 /* dev_t: console terminal device */ +#define CPU_BIOS 2 /* BIOS variables */ +#define CPU_BLK2CHR 3 /* convert blk maj into chr one */ +#define CPU_CHR2BLK 4 /* convert chr maj into blk one */ +#define CPU_ALLOWAPERTURE 5 /* allow mmap of /dev/xf86 */ +#define CPU_CPUVENDOR 6 /* cpuid vendor string */ +#define CPU_CPUID 7 /* cpuid */ +#define CPU_CPUFEATURE 8 /* cpuid features */ +#define CPU_KBDRESET 10 /* keyboard reset under pcvt */ +#define CPU_XCRYPT 12 /* supports VIA xcrypt in userland */ +#define CPU_LIDACTION 14 /* action caused by lid close */ +#define CPU_FORCEUKBD 15 /* Force ukbd(4) as console keyboard */ +#define CPU_TSCFREQ 16 /* TSC frequency */ +#define CPU_INVARIANTTSC 17 /* has invariant TSC */ +#define CPU_PWRACTION 18 /* action caused by power button */ +#define CPU_RETPOLINE 19 /* cpu requires retpoline pattern */ +#define CPU_MAXID 20 /* number of valid machdep ids */ + +#define CTL_MACHDEP_NAMES { \ + { 0, 0 }, \ + { "console_device", CTLTYPE_STRUCT }, \ + { "bios", CTLTYPE_INT }, \ + { "blk2chr", CTLTYPE_STRUCT }, \ + { "chr2blk", CTLTYPE_STRUCT }, \ + { "allowaperture", CTLTYPE_INT }, \ + { "cpuvendor", CTLTYPE_STRING }, \ + { "cpuid", CTLTYPE_INT }, \ + { "cpufeature", CTLTYPE_INT }, \ + { 0, 0 }, \ + { "kbdreset", CTLTYPE_INT }, \ + { 0, 0 }, \ + { "xcrypt", CTLTYPE_INT }, \ + { 0, 0 }, \ + { "lidaction", CTLTYPE_INT }, \ + { "forceukbd", CTLTYPE_INT }, \ + { "tscfreq", CTLTYPE_QUAD }, \ + { "invarianttsc", CTLTYPE_INT }, \ + { "pwraction", CTLTYPE_INT }, \ + { "retpoline", CTLTYPE_INT }, \ +} + +#endif /* !_MACHINE_CPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/cpu_full.h b/lib/libc/include/x86_64-openbsd-none/machine/cpu_full.h new file mode 100644 index 000000000000..0d6485cd0e2d --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/cpu_full.h @@ -0,0 +1,70 @@ +/* $OpenBSD: cpu_full.h,v 1.5 2019/05/17 19:07:47 guenther Exp $ */ +/* + * Copyright (c) 2018 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_CPU_FULL_H_ +#define _MACHINE_CPU_FULL_H_ + +#include /* offsetof, PAGE_SIZE */ +#include +#include + +/* + * The layout of the full per-CPU information, including TSS, GDT, + * trampoline stacks, and cpu_info described in + */ +struct cpu_info_full { + /* page mapped kRO in u-k */ + union { + struct { + struct x86_64_tss uu_tss; + uint64_t uu_gdt[GDT_SIZE / 8]; + } u_tssgdt; + char u_align[PAGE_SIZE]; + } cif_RO; +#define cif_tss cif_RO.u_tssgdt.uu_tss +#define cif_gdt cif_RO.u_tssgdt.uu_gdt + + /* start of page mapped kRW in u-k */ + uint64_t cif_tramp_stack[(PAGE_SIZE / 4 + - offsetof(struct cpu_info, ci_PAGEALIGN)) / sizeof(uint64_t)]; + uint64_t cif_dblflt_stack[(PAGE_SIZE / 4) / sizeof(uint64_t)]; + uint64_t cif_nmi_stack[(2 * PAGE_SIZE / 4) / sizeof(uint64_t)]; + + /* + * Beginning of this hangs over into the kRW page; rest is + * unmapped in u-k + */ + struct cpu_info cif_cpu; +} __aligned(PAGE_SIZE); + +/* tss, align shim, and gdt must fit in a page */ +CTASSERT(_ALIGN(sizeof(struct x86_64_tss)) + + sizeof(struct mem_segment_descriptor) * (NGDT_MEM + 2*NGDT_SYS) + < PAGE_SIZE); + +/* verify expected alignment */ +CTASSERT(offsetof(struct cpu_info_full, cif_cpu.ci_PAGEALIGN) % PAGE_SIZE == 0); + +/* verify total size is multiple of page size */ +CTASSERT(sizeof(struct cpu_info_full) % PAGE_SIZE == 0); + +extern struct cpu_info_full cpu_info_full_primary; + +/* Now make sure the cpu_info_primary macro is correct */ +CTASSERT(&cpu_info_primary - &cpu_info_full_primary.cif_cpu == 0); + +#endif /* _MACHINE_CPU_FULL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/cpufunc.h b/lib/libc/include/x86_64-openbsd-none/machine/cpufunc.h new file mode 100644 index 000000000000..6a8420e179f5 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/cpufunc.h @@ -0,0 +1,461 @@ +/* $OpenBSD: cpufunc.h,v 1.45 2025/06/27 17:23:49 bluhm Exp $ */ +/* $NetBSD: cpufunc.h,v 1.3 2003/05/08 10:27:43 fvdl Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_CPUFUNC_H_ +#define _MACHINE_CPUFUNC_H_ + +/* + * Functions to provide access to i386-specific instructions. + */ + +#include + +#include + +#if defined(_KERNEL) && !defined (_STANDALONE) + +static __inline void +invlpg(u_int64_t addr) +{ + __asm volatile("invlpg (%0)" : : "r" (addr) : "memory"); +} + +static __inline void +sidt(void *p) +{ + __asm volatile("sidt (%0)" : : "r" (p) : "memory"); +} + +static __inline void +lidt(void *p) +{ + __asm volatile("lidt (%0)" : : "r" (p) : "memory"); +} + +static __inline void +sgdt(void *p) +{ + __asm volatile("sgdt (%0)" : : "r" (p) : "memory"); +} + +static __inline void +bare_lgdt(struct region_descriptor *p) +{ + __asm volatile("lgdt (%0)" : : "r" (p) : "memory"); +} + +static __inline void +sldt(u_short *sel) +{ + __asm volatile("sldt (%0)" : : "r" (sel) : "memory"); +} + +static __inline void +lldt(u_short sel) +{ + __asm volatile("lldt %0" : : "r" (sel)); +} + +static __inline void +ltr(u_short sel) +{ + __asm volatile("ltr %0" : : "r" (sel)); +} + +static __inline void +lcr8(u_int val) +{ + u_int64_t val64 = val; + __asm volatile("movq %0,%%cr8" : : "r" (val64)); +} + +/* + * Upper 32 bits are reserved anyway, so just keep this 32bits. + */ +static __inline void +lcr0(u_int val) +{ + u_int64_t val64 = val; + __asm volatile("movq %0,%%cr0" : : "r" (val64)); +} + +static __inline u_int +rcr0(void) +{ + u_int64_t val64; + u_int val; + __asm volatile("movq %%cr0,%0" : "=r" (val64)); + val = val64; + return val; +} + +static __inline u_int64_t +rcr2(void) +{ + u_int64_t val; + __asm volatile("movq %%cr2,%0" : "=r" (val)); + return val; +} + +static __inline void +lcr3(u_int64_t val) +{ + __asm volatile("movq %0,%%cr3" : : "r" (val)); +} + +static __inline u_int64_t +rcr3(void) +{ + u_int64_t val; + __asm volatile("movq %%cr3,%0" : "=r" (val)); + return val; +} + +/* + * Same as for cr0. Don't touch upper 32 bits. + */ +static __inline void +lcr4(u_int val) +{ + u_int64_t val64 = val; + + __asm volatile("movq %0,%%cr4" : : "r" (val64)); +} + +static __inline u_int +rcr4(void) +{ + u_int64_t val64; + __asm volatile("movq %%cr4,%0" : "=r" (val64)); + return (u_int) val64; +} + +/* + * DR6 and DR7 debug registers + */ +static inline uint64_t +rdr6(void) +{ + u_int64_t val; + __asm volatile("movq %%dr6,%0" : "=r" (val)); + return val; +} + +static inline uint64_t +rdr7(void) +{ + u_int64_t val; + __asm volatile("movq %%dr7,%0" : "=r" (val)); + return val; +} + +static __inline void +tlbflush(void) +{ + u_int64_t val; + __asm volatile("movq %%cr3,%0" : "=r" (val)); + __asm volatile("movq %0,%%cr3" : : "r" (val)); +} + +static inline void +invpcid(uint64_t type, paddr_t pcid, paddr_t addr) +{ + uint64_t desc[2] = { pcid, addr }; + asm volatile("invpcid %0,%1" : : "m"(desc[0]), "r"(type)); +} +#define INVPCID_ADDR 0 +#define INVPCID_PCID 1 +#define INVPCID_ALL 2 +#define INVPCID_NON_GLOBAL 3 + +#ifdef notyet +void setidt(int idx, /*XXX*/caddr_t func, int typ, int dpl); +#endif + + +/* XXXX ought to be in psl.h with spl() functions */ + +static __inline u_long +read_rflags(void) +{ + u_long ef; + + __asm volatile("pushfq; popq %0" : "=r" (ef)); + return (ef); +} + +static __inline void +write_rflags(u_long ef) +{ + __asm volatile("pushq %0; popfq" : : "r" (ef)); +} + +static __inline void +intr_enable(void) +{ + __asm volatile("sti"); +} + +static __inline u_long +intr_disable(void) +{ + u_long ef; + + ef = read_rflags(); + __asm volatile("cli"); + return (ef); +} + +static __inline void +intr_restore(u_long ef) +{ + write_rflags(ef); +} + +static __inline u_int64_t +rdmsr(u_int msr) +{ + uint32_t hi, lo; + __asm volatile("rdmsr" : "=d" (hi), "=a" (lo) : "c" (msr)); + return (((uint64_t)hi << 32) | (uint64_t) lo); +} + +static __inline int +rdpkru(u_int ecx) +{ + uint32_t edx, pkru; + asm volatile("rdpkru " : "=a" (pkru), "=d" (edx) : "c" (ecx)); + return pkru; +} + +static __inline void +wrpkru(u_int ecx, uint32_t pkru) +{ + uint32_t edx = 0; + asm volatile("wrpkru" : : "a" (pkru), "c" (ecx), "d" (edx)); +} + +static __inline void +wrmsr(u_int msr, u_int64_t newval) +{ + __asm volatile("wrmsr" : + : "a" (newval & 0xffffffff), "d" (newval >> 32), "c" (msr)); +} + +/* + * Some of the undocumented AMD64 MSRs need a 'passcode' to access. + * + * See LinuxBIOSv2: src/cpu/amd/model_fxx/model_fxx_init.c + */ + +#define OPTERON_MSR_PASSCODE 0x9c5a203a + +static __inline u_int64_t +rdmsr_locked(u_int msr, u_int code) +{ + uint32_t hi, lo; + __asm volatile("rdmsr" + : "=d" (hi), "=a" (lo) + : "c" (msr), "D" (code)); + return (((uint64_t)hi << 32) | (uint64_t) lo); +} + +static __inline void +wrmsr_locked(u_int msr, u_int code, u_int64_t newval) +{ + __asm volatile("wrmsr" : + : "a" (newval & 0xffffffff), "d" (newval >> 32), "c" (msr), "D" (code)); +} + +static __inline void +wbinvd(void) +{ + __asm volatile("wbinvd" : : : "memory"); +} + +#ifdef MULTIPROCESSOR +int wbinvd_on_all_cpus(void); +void wbinvd_on_all_cpus_acked(void); +#else +static inline int +wbinvd_on_all_cpus(void) +{ + wbinvd(); + return 0; +} + +static inline int +wbinvd_on_all_cpus_acked(void) +{ + wbinvd(); + return 0; +} +#endif /* MULTIPROCESSOR */ + +static __inline void +clflush(u_int64_t addr) +{ + __asm volatile("clflush %0" : "+m" (*(volatile char *)addr)); +} + +static __inline void +mfence(void) +{ + __asm volatile("mfence" : : : "memory"); +} + +static __inline u_int64_t +rdtsc(void) +{ + uint32_t hi, lo; + + __asm volatile("rdtsc" : "=d" (hi), "=a" (lo)); + return (((uint64_t)hi << 32) | (uint64_t) lo); +} + +static __inline u_int64_t +rdtscp(void) +{ + uint32_t hi, lo; + + __asm volatile("rdtscp" : "=d" (hi), "=a" (lo) : : "ecx"); + return (((uint64_t)hi << 32) | (uint64_t) lo); +} + +static __inline u_int64_t +rdtsc_lfence(void) +{ + uint32_t hi, lo; + + __asm volatile("lfence; rdtsc" : "=d" (hi), "=a" (lo)); + return (((uint64_t)hi << 32) | (uint64_t) lo); +} + +static __inline u_int64_t +rdpmc(u_int pmc) +{ + uint32_t hi, lo; + + __asm volatile("rdpmc" : "=d" (hi), "=a" (lo) : "c" (pmc)); + return (((uint64_t)hi << 32) | (uint64_t) lo); +} + +static __inline void +monitor(const volatile void *addr, u_long extensions, u_int hints) +{ + + __asm volatile("monitor" + : : "a" (addr), "c" (extensions), "d" (hints)); +} + +static __inline void +mwait(u_long extensions, u_int hints) +{ + + __asm volatile( + " mwait ;" + " mov $8,%%rcx ;" + " .align 16,0x90 ;" + "3: call 5f ;" + "4: pause ;" + " lfence ;" + " call 4b ;" + " .align 16,0xcc ;" + "5: call 7f ;" + "6: pause ;" + " lfence ;" + " call 6b ;" + " .align 16,0xcc ;" + "7: loop 3b ;" + " add $(16*8),%%rsp" + : "+c" (extensions) : "a" (hints)); +} + +static __inline void +xsetbv(uint32_t reg, uint64_t mask) +{ + uint32_t lo, hi; + + lo = mask; + hi = mask >> 32; + __asm volatile("xsetbv" :: "c" (reg), "a" (lo), "d" (hi) : "memory"); +} + +static __inline uint64_t +xgetbv(uint32_t reg) +{ + uint32_t lo, hi; + + __asm volatile("xgetbv" : "=a" (lo), "=d" (hi) : "c" (reg)); + + return (((uint64_t)hi << 32) | (uint64_t)lo); +} + +static __inline void +stgi(void) +{ + __asm volatile("stgi"); +} + +static __inline void +clgi(void) +{ + __asm volatile("clgi"); +} + +/* Break into DDB. */ +static __inline void +breakpoint(void) +{ + __asm volatile("int $3"); +} + +/* VMGEXIT */ +static __inline void +vmgexit(void) +{ + /* rep; vmmcall encodes the vmgexit instruction */ + __asm volatile("rep; vmmcall"); +} + +void amd64_errata(struct cpu_info *); +void cpu_ucode_setup(void); +void cpu_ucode_apply(struct cpu_info *); + +struct cpu_info_full; +void cpu_enter_pages(struct cpu_info_full *); + +int rdmsr_safe(u_int msr, uint64_t *); + +#endif /* _KERNEL */ + +#endif /* !_MACHINE_CPUFUNC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/cpuvar.h b/lib/libc/include/x86_64-openbsd-none/machine/cpuvar.h new file mode 100644 index 000000000000..c82e3adf881c --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/cpuvar.h @@ -0,0 +1,100 @@ +/* $OpenBSD: cpuvar.h,v 1.14 2024/10/22 10:14:49 jsg Exp $ */ +/* $NetBSD: cpuvar.h,v 1.1 2003/03/01 18:29:28 fvdl Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1999 Stefan Grefen + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +struct cpu_functions { + int (*start)(struct cpu_info *); + int (*stop)(struct cpu_info *); + void (*cleanup)(struct cpu_info *); +}; + +extern struct cpu_functions mp_cpu_funcs; + +#define CPU_ROLE_SP 0 +#define CPU_ROLE_BP 1 +#define CPU_ROLE_AP 2 + +struct cpu_attach_args { + const char *caa_name; + int cpu_apicid; + int cpu_acpi_proc_id; + int cpu_role; + struct cpu_functions *cpu_func; +}; + +#ifdef _KERNEL + +#ifdef MULTIPROCESSOR +extern void (*x86_ipi)(int,int,int); +void x86_ipi_init(int); +#endif + +void identifycpu(struct cpu_info *); +void cpu_init(struct cpu_info *); + +void tsc_test_sync_bp(struct cpu_info *); +void tsc_test_sync_ap(struct cpu_info *); + +#endif \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/db_machdep.h b/lib/libc/include/x86_64-openbsd-none/machine/db_machdep.h new file mode 100644 index 000000000000..4a66d5a76198 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/db_machdep.h @@ -0,0 +1,101 @@ +/* $OpenBSD: db_machdep.h,v 1.19 2021/08/30 08:11:12 jasper Exp $ */ +/* $NetBSD: db_machdep.h,v 1.2 2003/04/29 17:06:04 scw Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#ifndef _MACHINE_DB_MACHDEP_H_ +#define _MACHINE_DB_MACHDEP_H_ + +/* + * Machine-dependent defines for new kernel debugger. + */ + +#include +#include +#include +#include + +typedef long db_expr_t; /* expression - signed */ + +typedef struct trapframe db_regs_t; + +extern db_regs_t ddb_regs; /* register state */ + +#define PC_REGS(regs) ((vaddr_t)(regs)->tf_rip) +#define SET_PC_REGS(regs, value) (regs)->tf_rip = (int64_t)(value) + +#define BKPT_ADDR(addr) (addr) /* breakpoint address */ +#define BKPT_INST 0xcc /* breakpoint instruction */ +#define BKPT_SIZE (1) /* size of breakpoint inst */ +#define BKPT_SET(inst) (BKPT_INST) + +#define SSF_INST 0x55 +#define SSF_SIZE (1) + +#define FIXUP_PC_AFTER_BREAK(regs) ((regs)->tf_rip -= BKPT_SIZE) + +#define db_clear_single_step(regs) ((regs)->tf_rflags &= ~PSL_T) +#define db_set_single_step(regs) ((regs)->tf_rflags |= PSL_T) + +#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BPTFLT) +#define IS_WATCHPOINT_TRAP(type, code) ((type) == T_TRCTRAP && (code) & 15) + +#define I_CALL 0xe8 +#define I_CALLI 0xff +#define I_RET 0xc3 +#define I_IRET 0xcf + +#define inst_trap_return(ins) (((ins)&0xff) == I_IRET) +#define inst_return(ins) (((ins)&0xff) == I_RET) +#define inst_call(ins) (((ins)&0xff) == I_CALL || \ + (((ins)&0xff) == I_CALLI && \ + ((ins)&0x3800) == 0x1000)) + +/* macro for checking if a thread has used floating-point */ + +int db_ktrap(int, int, db_regs_t *); + +void db_machine_init(void); +int db_enter_ddb(void); +void db_startcpu(int); +void db_stopcpu(int); +void x86_ipi_db(struct cpu_info *); + +#define DDB_STATE_NOT_RUNNING 0 +#define DDB_STATE_RUNNING 1 +#define DDB_STATE_EXITING 2 + +/* + * We define some of our own commands + */ +#define DB_MACHINE_COMMANDS + +extern void db_machine_init(void); + +extern void cpu_debug_dump(void); + +#endif /* _MACHINE_DB_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/disklabel.h b/lib/libc/include/x86_64-openbsd-none/machine/disklabel.h new file mode 100644 index 000000000000..44d225a0a846 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/disklabel.h @@ -0,0 +1,40 @@ +/* $OpenBSD: disklabel.h,v 1.11 2015/09/30 14:57:03 krw Exp $ */ + +/* + * Copyright (c) 1994 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_DISKLABEL_H_ +#define _MACHINE_DISKLABEL_H_ + +#define LABELSECTOR 1 /* sector containing label */ +#define LABELOFFSET 0 /* offset of label in sector */ +#define MAXPARTITIONS 16 /* number of partitions */ + +#endif /* _MACHINE_DISKLABEL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/efifbvar.h b/lib/libc/include/x86_64-openbsd-none/machine/efifbvar.h new file mode 100644 index 000000000000..1958da38bcad --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/efifbvar.h @@ -0,0 +1,40 @@ +/* $OpenBSD: efifbvar.h,v 1.10 2019/05/04 11:34:47 kettenis Exp $ */ + +/* + * Copyright (c) 2015 YASUOKA Masahiko + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_EFIFB_H_ +#define _MACHINE_EFIFB_H_ + +struct efifb_attach_args { + const char *eaa_name; +}; + +struct pci_attach_args; + +int efifb_cnattach(void); +void efifb_cnremap(void); +int efifb_is_console(struct pci_attach_args *); +int efifb_is_primary(struct pci_attach_args *); +void efifb_detach(void); +void efifb_reattach(void); + +int efifb_cb_found(void); +int efifb_cb_cnattach(void); + +psize_t efifb_stolen(void); + +#endif /* _MACHINE_EFIFB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/efivar.h b/lib/libc/include/x86_64-openbsd-none/machine/efivar.h new file mode 100644 index 000000000000..72645470e802 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/efivar.h @@ -0,0 +1,42 @@ +/* $OpenBSD: efivar.h,v 1.1 2023/01/14 12:11:10 kettenis Exp $ */ +/* + * Copyright (c) 2022 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_EFIVAR_H_ +#define _MACHINE_EFIVAR_H_ + +#include + +struct efi_softc { + struct device sc_dev; + struct pmap *sc_pm; + EFI_RUNTIME_SERVICES *sc_rs; + EFI_SYSTEM_RESOURCE_TABLE *sc_esrt; + u_long sc_psw; + uint64_t sc_cr3; + + struct todr_chip_handle sc_todr; +}; + +void efi_enter(struct efi_softc *); +void efi_leave(struct efi_softc *); + +extern label_t efi_jmpbuf; + +#define efi_enter_check(sc) (setjmp(&efi_jmpbuf) ? \ + (efi_leave(sc), EFAULT) : (efi_enter(sc), 0)) + +#endif /* _MACHINE_EFIVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/endian.h b/lib/libc/include/x86_64-openbsd-none/machine/endian.h new file mode 100644 index 000000000000..7ff7b356d9c6 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/endian.h @@ -0,0 +1,36 @@ +/* $OpenBSD: endian.h,v 1.8 2024/05/07 14:26:48 naddy Exp $ */ + +/*- + * Copyright (c) 1997 Niklas Hallqvist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_ENDIAN_H_ +#define _MACHINE_ENDIAN_H_ + +#define _BYTE_ORDER _LITTLE_ENDIAN + +#ifndef __FROM_SYS__ENDIAN +#include +#endif + +#endif /* _MACHINE_ENDIAN_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/exec.h b/lib/libc/include/x86_64-openbsd-none/machine/exec.h new file mode 100644 index 000000000000..8fafeb9b4c03 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/exec.h @@ -0,0 +1,17 @@ +/* $OpenBSD: exec.h,v 1.7 2017/02/08 05:09:25 guenther Exp $ */ +/* + * Written by Artur Grabowski Public Domain + */ + +#ifndef _MACHINE_EXEC_H_ +#define _MACHINE_EXEC_H_ + +#define __LDPGSZ 4096 + +#define ARCH_ELFSIZE 64 + +#define ELF_TARG_CLASS ELFCLASS64 +#define ELF_TARG_DATA ELFDATA2LSB +#define ELF_TARG_MACH EM_AMD64 + +#endif \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/fenv.h b/lib/libc/include/x86_64-openbsd-none/machine/fenv.h new file mode 100644 index 000000000000..0b16f62459cb --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/fenv.h @@ -0,0 +1,115 @@ +/* $OpenBSD: fenv.h,v 1.4 2011/05/25 21:46:49 martynas Exp $ */ +/* $NetBSD: fenv.h,v 1.1 2010/07/31 21:47:54 joerg Exp $ */ + +/*- + * Copyright (c) 2004-2005 David Schultz + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _AMD64_FENV_H_ +#define _AMD64_FENV_H_ + +/* + * Each symbol representing a floating point exception expands to an integer + * constant expression with values, such that bitwise-inclusive ORs of _all + * combinations_ of the constants result in distinct values. + * + * We use such values that allow direct bitwise operations on FPU/SSE registers. + */ +#define FE_INVALID 0x01 +#define FE_DENORMAL 0x02 +#define FE_DIVBYZERO 0x04 +#define FE_OVERFLOW 0x08 +#define FE_UNDERFLOW 0x10 +#define FE_INEXACT 0x20 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * exception constants defined above. + */ +#define FE_ALL_EXCEPT (FE_INVALID | FE_DENORMAL | FE_DIVBYZERO | \ + FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) +#define _SSE_MASK_SHIFT 7 + +/* + * Each symbol representing the rounding direction, expands to an integer + * constant expression whose value is distinct non-negative value. + * + * We use such values that allow direct bitwise operations on FPU/SSE registers. + */ +#define FE_TONEAREST 0x000 +#define FE_DOWNWARD 0x400 +#define FE_UPWARD 0x800 +#define FE_TOWARDZERO 0xc00 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * rounding direction constants defined above. + */ +#define _X87_ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | \ + FE_TOWARDZERO) +#define _SSE_ROUND_SHIFT 3 + +/* + * fenv_t represents the entire floating-point environment. + */ +typedef struct { + struct { + unsigned int __control; /* Control word register */ + unsigned int __status; /* Status word register */ + unsigned int __tag; /* Tag word register */ + unsigned int __others[4]; /* EIP, Pointer Selector, etc */ + } __x87; + unsigned int __mxcsr; /* Control, status register */ +} fenv_t; + +/* + * The following constant represents the default floating-point environment + * (that is, the one installed at program startup) and has type pointer to + * const-qualified fenv_t. + * + * It can be used as an argument to the functions within the header + * that manage the floating-point environment, namely fesetenv() and + * feupdateenv(). + */ +__BEGIN_DECLS +extern fenv_t __fe_dfl_env; +__END_DECLS +#define FE_DFL_ENV ((const fenv_t *)&__fe_dfl_env) + +/* + * fexcept_t represents the floating-point status flags collectively, including + * any status the implementation associates with the flags. + * + * A floating-point status flag is a system variable whose value is set (but + * never cleared) when a floating-point exception is raised, which occurs as a + * side effect of exceptional floating-point arithmetic to provide auxiliary + * information. + * + * A floating-point control mode is a system variable whose value may be set by + * the user to affect the subsequent behavior of floating-point arithmetic. + */ +typedef unsigned int fexcept_t; + +#endif /* !_AMD64_FENV_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/fpu.h b/lib/libc/include/x86_64-openbsd-none/machine/fpu.h new file mode 100644 index 000000000000..b79b7a27c45c --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/fpu.h @@ -0,0 +1,111 @@ +/* $OpenBSD: fpu.h,v 1.20 2024/04/14 09:59:04 kettenis Exp $ */ +/* $NetBSD: fpu.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $ */ + +#ifndef _MACHINE_FPU_H_ +#define _MACHINE_FPU_H_ + +#include + +/* + * If the CPU supports xsave/xrstor then we use them so that we can provide + * AVX support. Otherwise we require fxsave/fxrstor, as the SSE registers + * are part of the ABI for passing floating point values. + * While fxsave/fxrstor only required 16-byte alignment for the save area, + * xsave/xrstor requires the save area to have 64-byte alignment. + */ + +struct fxsave64 { + u_int16_t fx_fcw; + u_int16_t fx_fsw; + u_int8_t fx_ftw; + u_int8_t fx_unused1; + u_int16_t fx_fop; + u_int64_t fx_rip; + u_int64_t fx_rdp; + u_int32_t fx_mxcsr; + u_int32_t fx_mxcsr_mask; + u_int64_t fx_st[8][2]; /* 8 normal FP regs */ + u_int64_t fx_xmm[16][2]; /* 16 SSE2 registers */ + u_int8_t fx_unused3[96]; +} __packed; + +struct xstate_hdr { + uint64_t xstate_bv; + uint64_t xstate_xcomp_bv; + uint8_t xstate_rsrv0[8]; + uint8_t xstate_rsrv[40]; +} __packed; + +struct savefpu { + struct fxsave64 fp_fxsave; /* see above */ + struct xstate_hdr fp_xstate; + u_int64_t fp_ymm[16][2]; + u_int8_t fp_components[1856]; /* enough for AVX-512 */ +}; + +/* + * The i387 defaults to Intel extended precision mode and round to nearest, + * with all exceptions masked. + */ +#define __INITIAL_NPXCW__ 0x037f +#define __INITIAL_MXCSR__ 0x1f80 +#define __INITIAL_MXCSR_MASK__ 0xffbf + +#ifdef _KERNEL +/* + * XXX + */ +struct trapframe; +struct cpu_info; + +extern size_t fpu_save_len; +extern uint32_t fpu_mxcsr_mask; +extern uint64_t xsave_mask; +extern int cpu_use_xsaves; + +void fpuinit(struct cpu_info *); +int fputrap(int _type); +void fpusave(struct savefpu *); +void fpusavereset(struct savefpu *); +void fpu_kernel_enter(void); +void fpu_kernel_exit(void); + +/* pointer to fxsave/xsave/xsaves data with everything reset */ +#define fpu_cleandata (&proc0.p_addr->u_pcb.pcb_savefpu) + +int xrstor_user(struct savefpu *_addr, uint64_t _mask); +void xrstor_kern(struct savefpu *_addr, uint64_t _mask); +#define fpureset() \ + xrstor_kern(fpu_cleandata, xsave_mask) +int xsetbv_user(uint32_t _reg, uint64_t _mask); + +#define fninit() __asm("fninit") +#define fwait() __asm("fwait") +/* should be fxsave64, but where we use this it doesn't matter */ +#define fxsave(addr) __asm("fxsave %0" : "=m" (*addr)) +#define ldmxcsr(addr) __asm("ldmxcsr %0" : : "m" (*addr)) +#define fldcw(addr) __asm("fldcw %0" : : "m" (*addr)) + +static inline void +xsave(struct savefpu *addr, uint64_t mask) +{ + uint32_t lo, hi; + + lo = mask; + hi = mask >> 32; + __asm volatile("xsave64 %0" : "+m" (*addr) : "a" (lo), "d" (hi)); +} + +static inline void +xrstors(const struct savefpu *addr, uint64_t mask) +{ + uint32_t lo, hi; + + lo = mask; + hi = mask >> 32; + __asm volatile("xrstors64 %0" : : "m" (*addr), "a" (lo), "d" (hi)); +} + +#endif + +#endif /* _MACHINE_FPU_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/frame.h b/lib/libc/include/x86_64-openbsd-none/machine/frame.h new file mode 100644 index 000000000000..bd9658dec45d --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/frame.h @@ -0,0 +1,174 @@ +/* $OpenBSD: frame.h,v 1.11 2024/01/31 06:06:28 guenther Exp $ */ +/* $NetBSD: frame.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)frame.h 5.2 (Berkeley) 1/18/91 + */ + +/* + * Adapted for NetBSD/amd64 by fvdl@wasabisystems.com + */ + +#ifndef _MACHINE_FRAME_H_ +#define _MACHINE_FRAME_H_ + +#include +#include + +/* + * System stack frames. + */ + +/* + * Exception/Trap Stack Frame + */ +struct trapframe { + int64_t tf_rdi; /* ordered by syscall args... */ + int64_t tf_rsi; + int64_t tf_rdx; + int64_t tf_r10; + int64_t tf_r8; + int64_t tf_r9; /* ...to here */ + int64_t tf_rcx; + int64_t tf_r11; + int64_t tf_r12; + int64_t tf_r13; + int64_t tf_r14; + int64_t tf_r15; + int64_t tf_err; /* not the hardware position */ + int64_t tf_rbx; + int64_t tf_rax; + int64_t tf_trapno; + int64_t tf_rbp; /* hardware puts err here, INTRENTRY() moves it up */ + /* below portion defined in hardware */ + int64_t tf_rip; + int64_t tf_cs; + int64_t tf_rflags; + /* These are pushed unconditionally on the x86-64 */ + int64_t tf_rsp; + int64_t tf_ss; +}; + +/* + * Interrupt stack frame + */ +struct intrframe { + int64_t if_rdi; + int64_t if_rsi; + int64_t if_rdx; + int64_t if_r10; + int64_t if_r8; + int64_t if_r9; + int64_t if_rcx; + int64_t if_r11; + int64_t if_r12; + int64_t if_r13; + int64_t if_r14; + int64_t if_r15; + int64_t if_err; /* IREENT_MAGIC if resume/recurse */ + int64_t if_rbx; + int64_t if_rax; + int64_t if_ppl; /* previous priority level */ + int64_t if_rbp; + /* below portion defined in hardware */ + int64_t if_rip; + int64_t if_cs; + int64_t if_rflags; + /* These are pushed unconditionally on the x86-64 */ + int64_t if_rsp; + int64_t if_ss; +}; + + +/* + * The trampoline frame used on the kernel stack page which is present + * but kernel-only, in the page tables used when in userspace. This is + * the minimum for iretq operation. + */ +struct iretq_frame { + int64_t iretq_rip; + int64_t iretq_cs; + int64_t iretq_rflags; + int64_t iretq_rsp; + int64_t iretq_ss; +}; + +/* + * Stack frame inside cpu_switch() + */ +struct switchframe { + int64_t sf_r15; + int64_t sf_r14; + int64_t sf_r13; + int64_t sf_r12; + int64_t sf_rbp; + int64_t sf_rbx; + int64_t sf_rip; +}; + +struct callframe { + struct callframe *f_frame; + long f_retaddr; + long f_arg0; +}; + +#endif /* _MACHINE_FRAME_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/frameasm.h b/lib/libc/include/x86_64-openbsd-none/machine/frameasm.h new file mode 100644 index 000000000000..0ef22deefb18 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/frameasm.h @@ -0,0 +1,199 @@ +/* $OpenBSD: frameasm.h,v 1.27 2023/07/27 00:30:07 guenther Exp $ */ +/* $NetBSD: frameasm.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $ */ + +#ifndef _AMD64_MACHINE_FRAMEASM_H +#define _AMD64_MACHINE_FRAMEASM_H + +/* + * Macros to define pushing/popping frames for interrupts, traps + * and system calls. Currently all the same; will diverge later. + */ + +/* + * These are used on interrupt or trap entry or exit. + */ +#define INTR_SAVE_GPRS \ + subq $120,%rsp ; \ + INTR_SAVE_MOST_GPRS_NO_ADJ ; \ + movq %rcx,TF_RCX(%rsp) +#define INTR_SAVE_MOST_GPRS_NO_ADJ \ + movq %r15,TF_R15(%rsp) ; \ + movq %r14,TF_R14(%rsp) ; \ + movq %r13,TF_R13(%rsp) ; \ + movq %r12,TF_R12(%rsp) ; \ + movq %r11,TF_R11(%rsp) ; \ + movq %r10,TF_R10(%rsp) ; \ + movq %r9,TF_R9(%rsp) ; \ + movq %r8,TF_R8(%rsp) ; \ + movq %rdi,TF_RDI(%rsp) ; \ + movq %rsi,TF_RSI(%rsp) ; \ + movq %rbp,TF_RBP(%rsp) ; \ + leaq TF_RBP(%rsp),%rbp ; \ + movq %rbx,TF_RBX(%rsp) ; \ + movq %rdx,TF_RDX(%rsp) ; \ + movq %rax,TF_RAX(%rsp) + +/* + * We clear registers when coming from userspace to prevent + * user-controlled values from being available for use in speculative + * execution in the kernel. %rsp and %rbp are the kernel values when + * this is used, so there are only 14 to clear. 32bit operations clear + * the register upper-halves automatically. + */ +#define INTR_CLEAR_GPRS \ + xorl %eax,%eax ; \ + xorl %ebx,%ebx ; \ + xorl %ecx,%ecx ; \ + xorl %edx,%edx ; \ + xorl %esi,%esi ; \ + xorl %edi,%edi ; \ + xorl %r8d,%r8d ; \ + xorl %r9d,%r9d ; \ + xorl %r10d,%r10d ; \ + xorl %r11d,%r11d ; \ + xorl %r12d,%r12d ; \ + xorl %r13d,%r13d ; \ + xorl %r14d,%r14d ; \ + xorl %r15d,%r15d + + +/* + * For real interrupt code paths, where we can come from userspace. + * We only have an iretq_frame on entry. + */ +#define INTRENTRY_LABEL(label) X##label##_untramp +#define INTRENTRY(label) \ + endbr64 ; \ + testb $SEL_RPL,IRETQ_CS(%rsp) ; \ + je INTRENTRY_LABEL(label) ; \ + swapgs ; \ + FENCE_SWAPGS_MIS_TAKEN ; \ + movq %rax,CPUVAR(SCRATCH) ; \ + CODEPATCH_START ; \ + movq CPUVAR(KERN_CR3),%rax ; \ + movq %rax,%cr3 ; \ + CODEPATCH_END(CPTAG_MELTDOWN_NOP);\ + jmp 98f ; \ +END(X##label) ; \ +_ENTRY(INTRENTRY_LABEL(label)) /* from kernel */ \ + FENCE_NO_SAFE_SMAP ; \ + subq $TF_RIP,%rsp ; \ + movq %rcx,TF_RCX(%rsp) ; \ + jmp 99f ; \ + _ALIGN_TRAPS ; \ +98: /* from userspace */ \ + movq CPUVAR(KERN_RSP),%rax ; \ + xchgq %rax,%rsp ; \ + movq %rcx,TF_RCX(%rsp) ; \ + RET_STACK_REFILL_WITH_RCX ; \ + /* copy iretq frame to the trap frame */ \ + movq IRETQ_RIP(%rax),%rcx ; \ + movq %rcx,TF_RIP(%rsp) ; \ + movq IRETQ_CS(%rax),%rcx ; \ + movq %rcx,TF_CS(%rsp) ; \ + movq IRETQ_RFLAGS(%rax),%rcx ; \ + movq %rcx,TF_RFLAGS(%rsp) ; \ + movq IRETQ_RSP(%rax),%rcx ; \ + movq %rcx,TF_RSP(%rsp) ; \ + movq IRETQ_SS(%rax),%rcx ; \ + movq %rcx,TF_SS(%rsp) ; \ + movq CPUVAR(SCRATCH),%rax ; \ +99: INTR_SAVE_MOST_GPRS_NO_ADJ ; \ + INTR_CLEAR_GPRS ; \ + movq %rax,TF_ERR(%rsp) + +#define INTRFASTEXIT \ + jmp intr_fast_exit + +/* + * Entry for faking up an interrupt frame after spllower() unblocks + * a previously received interrupt. On entry, %r13 has the %rip + * to return to. %r10 and %r11 are scratch. + */ +#define INTR_RECURSE \ + endbr64 ; \ + /* fake the iretq_frame */ ; \ + movq %rsp,%r10 ; \ + movl %ss,%r11d ; \ + pushq %r11 ; \ + pushq %r10 ; \ + pushfq ; \ + movl %cs,%r11d ; \ + pushq %r11 ; \ + pushq %r13 ; \ + /* now do the rest of the intrframe */ \ + subq $16,%rsp ; \ + INTR_SAVE_GPRS + + +/* + * Entry for traps from kernel, where there's a trapno + err already + * on the stack. We have to move the err from its hardware location + * to the location we want it. + */ +#define TRAP_ENTRY_KERN \ + subq $120,%rsp ; \ + movq %rcx,TF_RCX(%rsp) ; \ + movq (TF_RIP - 8)(%rsp),%rcx ; \ + movq %rcx,TF_ERR(%rsp) ; \ + INTR_SAVE_MOST_GPRS_NO_ADJ + +/* + * Entry for traps from userland, where there's a trapno + err on + * the iretq stack. + * Assumes that %rax has been saved in CPUVAR(SCRATCH). + */ +#define TRAP_ENTRY_USER \ + movq CPUVAR(KERN_RSP),%rax ; \ + xchgq %rax,%rsp ; \ + movq %rcx,TF_RCX(%rsp) ; \ + RET_STACK_REFILL_WITH_RCX ; \ + /* copy trapno+err to the trap frame */ \ + movq 0(%rax),%rcx ; \ + movq %rcx,TF_TRAPNO(%rsp) ; \ + movq 8(%rax),%rcx ; \ + movq %rcx,TF_ERR(%rsp) ; \ + /* copy iretq frame to the trap frame */ \ + movq (IRETQ_RIP+16)(%rax),%rcx ; \ + movq %rcx,TF_RIP(%rsp) ; \ + movq (IRETQ_CS+16)(%rax),%rcx ; \ + movq %rcx,TF_CS(%rsp) ; \ + movq (IRETQ_RFLAGS+16)(%rax),%rcx ; \ + movq %rcx,TF_RFLAGS(%rsp) ; \ + movq (IRETQ_RSP+16)(%rax),%rcx ; \ + movq %rcx,TF_RSP(%rsp) ; \ + movq (IRETQ_SS+16)(%rax),%rcx ; \ + movq %rcx,TF_SS(%rsp) ; \ + movq CPUVAR(SCRATCH),%rax ; \ + INTR_SAVE_MOST_GPRS_NO_ADJ ; \ + INTR_CLEAR_GPRS + +/* + * Entry from syscall instruction, where RIP is in %rcx and RFLAGS is in %r11. + * We stash the syscall # in tf_err for SPL check. + * Assumes that %rax has been saved in CPUVAR(SCRATCH). + */ +#define SYSCALL_ENTRY \ + movq CPUVAR(KERN_RSP),%rax ; \ + xchgq %rax,%rsp ; \ + movq %rcx,TF_RCX(%rsp) ; \ + movq %rcx,TF_RIP(%rsp) ; \ + RET_STACK_REFILL_WITH_RCX ; \ + movq $(GSEL(GUDATA_SEL, SEL_UPL)),TF_SS(%rsp) ; \ + movq %rax,TF_RSP(%rsp) ; \ + movq CPUVAR(SCRATCH),%rax ; \ + INTR_SAVE_MOST_GPRS_NO_ADJ ; \ + movq %r11, TF_RFLAGS(%rsp) ; \ + movq $(GSEL(GUCODE_SEL, SEL_UPL)), TF_CS(%rsp) ; \ + movq %rax,TF_ERR(%rsp) ; \ + INTR_CLEAR_GPRS + +#define CHECK_ASTPENDING(reg) movq CPUVAR(CURPROC),reg ; \ + cmpq $0, reg ; \ + je 99f ; \ + cmpl $0, P_MD_ASTPENDING(reg) ; \ + 99: + +#define CLEAR_ASTPENDING(reg) movl $0, P_MD_ASTPENDING(reg) + +#endif /* _AMD64_MACHINE_FRAMEASM_H */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/gdt.h b/lib/libc/include/x86_64-openbsd-none/machine/gdt.h new file mode 100644 index 000000000000..0e9ba4aa905c --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/gdt.h @@ -0,0 +1,33 @@ +/* $OpenBSD: gdt.h,v 1.6 2018/02/21 19:24:15 guenther Exp $ */ +/* $NetBSD: gdt.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $ */ + +/*- + * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by John T. Kohl and Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +void gdt_init_cpu(struct cpu_info *); \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/ghcb.h b/lib/libc/include/x86_64-openbsd-none/machine/ghcb.h new file mode 100644 index 000000000000..73f9484212bb --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/ghcb.h @@ -0,0 +1,251 @@ +/* $OpenBSD: ghcb.h,v 1.6 2025/09/17 18:37:44 sf Exp $ */ + +/* + * Copyright (c) 2024, 2025 Hans-Joerg Hoexer + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_GHCB_H_ +#define _MACHINE_GHCB_H_ + +#ifndef _LOCORE + +#include + +#include + +#define GHCB_OFFSET(m) ((m) / 8) +#define GHCB_IDX(m) (GHCB_OFFSET((m)) / 8) +#define GHCB_BIT(m) (GHCB_OFFSET((m)) % 8) + +#define GHCB_XSS 0x140 +#define GHCB_RAX 0x1F8 +#define GHCB_RBX 0x318 +#define GHCB_RCX 0x308 +#define GHCB_RDX 0x310 +#define GHCB_SW_EXITCODE 0x390 +#define GHCB_SW_EXITINFO1 0x398 +#define GHCB_SW_EXITINFO2 0x3A0 +#define GHCB_SW_SCRATCH 0x3A8 +#define GHCB_XCR0 0x3E8 + +#define GHCB_MAX 0xFFF + +struct ghcb_sa { + uint8_t v_pad0[0xcb]; /* 000h-0CAh */ + uint8_t v_cpl; /* 0CBh */ + uint8_t v_pad1[0x74]; /* 0CCh-13Fh */ + uint64_t v_xss; /* 140h */ + uint8_t v_pad2[0x18]; /* 148h-15Fh */ + uint64_t v_dr7; /* 160h */ + uint8_t v_pad3[0x10]; /* 168h-177h */ + uint64_t v_rip; /* 178h */ + uint8_t v_pad4[0x58]; /* 180h-1D7h */ + uint64_t v_rsp; /* 1D8h */ + uint8_t v_pad5[0x18]; /* 1E0h-1F7h */ + uint64_t v_rax; /* 1F8h */ + uint8_t v_pad6[0x108]; /* 200h-307h */ + uint64_t v_rcx; /* 308h */ + uint64_t v_rdx; /* 310h */ + uint64_t v_rbx; /* 318h */ + uint8_t v_pad7[0x8]; /* 320h-327h */ + uint64_t v_rbp; /* 328h */ + uint64_t v_rsi; /* 330h */ + uint64_t v_rdi; /* 338h */ + uint64_t v_r8; /* 340h */ + uint64_t v_r9; /* 348h */ + uint64_t v_r10; /* 350h */ + uint64_t v_r11; /* 358h */ + uint64_t v_r12; /* 360h */ + uint64_t v_r13; /* 368h */ + uint64_t v_r14; /* 370h */ + uint64_t v_r15; /* 378h */ + uint8_t v_pad8[0x10]; /* 380h-38Fh */ + uint64_t v_sw_exitcode; /* 390h */ + uint64_t v_sw_exitinfo1; /* 398h */ + uint64_t v_sw_exitinfo2; /* 3a0h */ + uint64_t v_sw_scratch; /* 3a8h */ + uint8_t v_pad9[0x38]; /* 3B0h-3E7h */ + uint64_t v_xcr0; /* 3E8h */ +#define GHCB_VB_SZ 0x10 + uint8_t valid_bitmap[GHCB_VB_SZ]; + /* 3F0h-3FFh */ + uint64_t v_x87_state_gpa; /* 400h */ + uint8_t v_pad10[0x3f8]; /* 408h-7FFh */ + uint8_t v_sharedbuf[0x7f0]; /* 800h-FEFh */ + uint8_t v_pad11[0xa]; /* FF0h-FF9h */ + uint16_t v_ghcb_proto_version; /* FFAh-FFBh */ + uint32_t v_ghcb_usage; /* FFCh-FFFh */ +}; + +#define GHCB_SZ8 0 +#define GHCB_SZ16 1 +#define GHCB_SZ32 2 +#define GHCB_SZ64 3 + +struct ghcb_sync { + uint8_t valid_bitmap[GHCB_VB_SZ]; + + int sz_a; + int sz_b; + int sz_c; + int sz_d; +}; +#endif /* !_LOCORE */ + +/* Definitions used with the MSR protocol */ +#define MSR_PROTO_CPUID_REQ 0x4 +#define MSR_PROTO_CPUID_RESP 0x5 +#define MSR_PROTO_TERMINATE 0x100 + +#ifndef _LOCORE + +extern vaddr_t ghcb_vaddr; +extern paddr_t ghcb_paddr; + +struct ghcb_extra_regs { + uint64_t exitcode; + uint64_t exitinfo1; + uint64_t exitinfo2; + uint64_t scratch; + void *data; + size_t data_sz; +}; + +void ghcb_clear(struct ghcb_sa *); +int ghcb_valbm_set(uint8_t *, int); +int ghcb_valbm_isset(uint8_t *, int); +int ghcb_verify_bm(uint8_t *, uint8_t *); +int ghcb_valid(struct ghcb_sa *); + +void ghcb_sync_val(int, int, struct ghcb_sync *); +void ghcb_sync_out(struct trapframe *, const struct ghcb_extra_regs *, + struct ghcb_sa *, struct ghcb_sync *); +void ghcb_sync_in(struct trapframe *, struct ghcb_extra_regs *, + struct ghcb_sa *, struct ghcb_sync *); +void _ghcb_mem_rw(vaddr_t, int, void *, bool); +void _ghcb_io_rw(uint16_t, int, uint32_t *, bool); + +static inline uint8_t +ghcb_mem_read_1(vaddr_t addr) +{ + uint8_t val; + + _ghcb_mem_rw(addr, GHCB_SZ8, &val, true); + return val; +} + +static inline uint16_t +ghcb_mem_read_2(vaddr_t addr) +{ + uint16_t val; + + _ghcb_mem_rw(addr, GHCB_SZ16, &val, true); + return val; +} + +static inline uint32_t +ghcb_mem_read_4(vaddr_t addr) +{ + uint32_t val; + + _ghcb_mem_rw(addr, GHCB_SZ32, &val, true); + return val; +} + +static inline uint64_t +ghcb_mem_read_8(vaddr_t addr) +{ + uint64_t val; + + _ghcb_mem_rw(addr, GHCB_SZ64, &val, true); + return val; +} + +static inline void +ghcb_mem_write_1(vaddr_t addr, uint8_t v) +{ + _ghcb_mem_rw(addr, GHCB_SZ8, &v, false); +} + +static inline void +ghcb_mem_write_2(vaddr_t addr, uint16_t v) +{ + _ghcb_mem_rw(addr, GHCB_SZ16, &v, false); +} + +static inline void +ghcb_mem_write_4(vaddr_t addr, uint32_t v) +{ + _ghcb_mem_rw(addr, GHCB_SZ32, &v, false); +} + +static inline void +ghcb_mem_write_8(vaddr_t addr, uint64_t v) +{ + _ghcb_mem_rw(addr, GHCB_SZ64, &v, false); +} + +static inline uint8_t +ghcb_io_read_1(uint16_t port) +{ + uint32_t val; + + _ghcb_io_rw(port, GHCB_SZ8, &val, true); + return val; +} + +static inline uint16_t +ghcb_io_read_2(uint16_t port) +{ + uint32_t val; + + _ghcb_io_rw(port, GHCB_SZ16, &val, true); + return val; +} + +static inline uint32_t +ghcb_io_read_4(uint16_t port) +{ + uint32_t val; + + _ghcb_io_rw(port, GHCB_SZ32, &val, true); + return val; +} + +static inline void +ghcb_io_write_1(uint16_t port, uint8_t v) +{ + uint32_t val = v; + + _ghcb_io_rw(port, GHCB_SZ8, &val, false); +} + +static inline void +ghcb_io_write_2(uint16_t port, uint16_t v) +{ + uint32_t val = v; + + _ghcb_io_rw(port, GHCB_SZ16, &val, false); +} + +static inline void +ghcb_io_write_4(uint16_t port, uint32_t v) +{ + _ghcb_io_rw(port, GHCB_SZ32, &v, false); +} + +#endif /* !_LOCORE */ + +#endif /* !_MACHINE_GHCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/hibernate.h b/lib/libc/include/x86_64-openbsd-none/machine/hibernate.h new file mode 100644 index 000000000000..09f2c2bbe8c8 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/hibernate.h @@ -0,0 +1,36 @@ +/* $OpenBSD: hibernate.h,v 1.7 2018/06/21 07:33:30 mlarkin Exp $ */ + +/* + * Copyright (c) 2011 Mike Larkin + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +/* amd64 hibernate support structures and functions */ + +int get_hibernate_info_md(union hibernate_info *); +void hibernate_flush(void); +void hibernate_enter_resume_mapping(vaddr_t, paddr_t, int); +int hibernate_inflate_skip(union hibernate_info *, paddr_t); +int hibernate_suspend(void); +void hibernate_switch_stack_machdep(void); +void hibernate_resume_machdep(vaddr_t); +void hibernate_activate_resume_pt_machdep(void); +void hibernate_enable_intr_machdep(void); +void hibernate_disable_intr_machdep(void); +#ifdef MULTIPROCESSOR +void hibernate_quiesce_cpus(void); +void hibernate_drop_to_real_mode(void); +#endif /* MULTIPROCESSOR */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/hibernate_var.h b/lib/libc/include/x86_64-openbsd-none/machine/hibernate_var.h new file mode 100644 index 000000000000..f65025fe94c8 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/hibernate_var.h @@ -0,0 +1,75 @@ +/* $OpenBSD: hibernate_var.h,v 1.14 2025/09/13 13:43:47 mlarkin Exp $ */ + +/* + * Copyright (c) 2011 Mike Larkin + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define PIGLET_PAGE_MASK (L2_FRAME) + +/* + * PML4 table for resume + */ +#define HIBERNATE_PML4T (PAGE_SIZE * 21) + +/* + * amd64 uses a PDPT to map the first 512GB phys mem plus one more + * to map any ranges of phys mem past 512GB (if needed) + */ +#define HIBERNATE_PDPT_LOW (PAGE_SIZE * 22) +#define HIBERNATE_PDPT_HI (PAGE_SIZE * 23) + +/* + * amd64 uses one PD to map the first 1GB phys mem plus one more to map any + * other 1GB ranges within the first 512GB phys, plus one more to map any + * 1GB range in any subsequent 512GB range + */ +#define HIBERNATE_PD_LOW (PAGE_SIZE * 24) +#define HIBERNATE_PD_LOW2 (PAGE_SIZE * 25) +#define HIBERNATE_PD_HI (PAGE_SIZE * 26) + +/* + * amd64 uses one PT to map the first 2MB phys mem plus one more to map any + * other 2MB range within the first 1GB, plus one more to map any 2MB range + * in any subsequent 512GB range. + */ +#define HIBERNATE_PT_LOW (PAGE_SIZE * 27) +#define HIBERNATE_PT_LOW2 (PAGE_SIZE * 28) +#define HIBERNATE_PT_HI (PAGE_SIZE * 29) + +/* 3 pages for stack */ +#define HIBERNATE_STACK_PAGE (PAGE_SIZE * 32) + +#define HIBERNATE_INFLATE_PAGE (PAGE_SIZE * 33) +/* HIBERNATE_HIBALLOC_PAGE must be the last stolen page (see machdep.c) */ +#define HIBERNATE_HIBALLOC_PAGE (PAGE_SIZE * 34) + +/* Use 4MB hibernation chunks */ +#define HIBERNATE_CHUNK_SIZE 0x400000 + +#define HIBERNATE_CHUNK_TABLE_SIZE 0x200000 + +#define HIBERNATE_STACK_OFFSET 0x0F00 + +/* + * Minimum amount of memory for hibernate support. This is used in early boot + * when deciding if we can preallocate the piglet. If the machine does not + * have at least HIBERNATE_MIN_MEMORY RAM, we won't support hibernate. This + * avoids late allocation issues due to fragmented memory and failure to + * hibernate. We need to be able to allocate 16MB contiguous memory, aligned + * to 2MB. + * + * The default minimum required memory is 512MB (1ULL << 29). + */ +#define HIBERNATE_MIN_MEMORY (1ULL << 29) \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/i82093reg.h b/lib/libc/include/x86_64-openbsd-none/machine/i82093reg.h new file mode 100644 index 000000000000..c5b341fb947d --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/i82093reg.h @@ -0,0 +1,135 @@ +/* $OpenBSD: i82093reg.h,v 1.9 2025/09/05 16:57:48 kettenis Exp $ */ +/* $NetBSD: i82093reg.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Typically, the first apic lives here. + */ +#define IOAPIC_BASE_DEFAULT 0xfec00000 + +/* + * Memory-space registers. + */ + +/* + * The externally visible registers are all 32 bits wide; + * store the register number of interest in IOAPIC_REG, and store/fetch + * the real value in IOAPIC_DATA. + */ +#define IOAPIC_REG 0x0000 +#define IOAPIC_DATA 0x0010 + +/* + * Internal I/O APIC registers. + */ + +#define IOAPIC_ID 0x00 + +#define IOAPIC_ID_SHIFT 24 +#define IOAPIC_ID_MASK 0x0f000000 + +/* Version, and maximum interrupt pin number. */ + +#define IOAPIC_VER 0x01 + +#define IOAPIC_VER_SHIFT 0 +#define IOAPIC_VER_MASK 0x000000ff + +#define IOAPIC_MAX_SHIFT 16 +#define IOAPIC_MAX_MASK 0x00ff0000 + +/* + * Arbitration ID. Same format as IOAPIC_ID register. + */ +#define IOAPIC_ARB 0x02 + +/* + * Redirection table registers. + */ + +#define IOAPIC_REDHI(pin) (0x11 + ((pin)<<1)) +#define IOAPIC_REDLO(pin) (0x10 + ((pin)<<1)) + +#define IOAPIC_REDHI_DEST_SHIFT 24 /* destination. */ +#define IOAPIC_REDHI_DEST_MASK 0xff000000 + +#define IOAPIC_REDLO_MASK 0x00010000 /* 0=enabled; 1=masked */ + +#define IOAPIC_REDLO_LEVEL 0x00008000 /* 0=edge, 1=level */ +#define IOAPIC_REDLO_RIRR 0x00004000 /* remote IRR; read only */ +#define IOAPIC_REDLO_ACTLO 0x00002000 /* 0=act. hi; 1=act. lo */ +#define IOAPIC_REDLO_DELSTS 0x00001000 /* 0=idle; 1=send pending */ +#define IOAPIC_REDLO_DSTMOD 0x00000800 /* 0=physical; 1=logical */ + +#define IOAPIC_REDLO_DEL_MASK 0x00000700 /* del. mode mask */ +#define IOAPIC_REDLO_DEL_SHIFT 8 + +#define IOAPIC_REDLO_DEL_FIXED 0 +#define IOAPIC_REDLO_DEL_LOPRI 1 +#define IOAPIC_REDLO_DEL_SMI 2 +#define IOAPIC_REDLO_DEL_NMI 4 +#define IOAPIC_REDLO_DEL_INIT 5 +#define IOAPIC_REDLO_DEL_EXTINT 7 + +#define IOAPIC_REDLO_VECTOR_MASK 0x000000ff /* delivery vector */ + +#define IMCR_ADDR 0x22 +#define IMCR_DATA 0x23 + +#define IMCR_REGISTER 0x70 +#define IMCR_PIC 0x00 +#define IMCR_APIC 0x01 + +#ifdef _KERNEL + +#include + +#define ioapic_asm_ack(num) \ + CODEPATCH_START ;\ + movl $0,(local_apic+LAPIC_EOI)(%rip) ;\ + CODEPATCH_END(CPTAG_EOI) + +#define ioapic_mask(num) \ + movq IS_PIC(%r14),%rdi ;\ + movl IS_PIN(%r14),%esi ;\ + call ioapic_hwmask + +#define ioapic_unmask(num) \ + cmpq $IREENT_MAGIC,IF_ERR(%rsp) ;\ + jne 79f ;\ + movq IS_PIC(%r14),%rdi ;\ + movl IS_PIN(%r14),%esi ;\ + call ioapic_hwunmask ;\ +79: + +#endif \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/i82093var.h b/lib/libc/include/x86_64-openbsd-none/machine/i82093var.h new file mode 100644 index 000000000000..1124b33cc727 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/i82093var.h @@ -0,0 +1,92 @@ +/* $OpenBSD: i82093var.h,v 1.8 2025/09/05 16:57:48 kettenis Exp $ */ +/* $NetBSD: i82093var.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_I82093VAR_H_ +#define _MACHINE_I82093VAR_H_ + +#include + +struct ioapic_pin { + struct ioapic_pin *ip_next; /* next pin on this vector */ + struct mp_intr_map *ip_map; + int ip_vector; /* IDT vector */ + int ip_type; + struct cpu_info *ip_cpu; /* target CPU */ +}; + +struct ioapic_softc { + struct pic sc_pic; + struct ioapic_softc *sc_next; + int sc_apicid; + int sc_apic_vers; + int sc_apic_vecbase; /* global int base if ACPI */ + int sc_apic_sz; /* apic size*/ + int sc_flags; + bus_space_tag_t sc_memt; + bus_space_handle_t sc_memh; + struct ioapic_pin *sc_pins; /* sc_apic_sz entries */ +}; + +/* + * MP: intr_handle_t is bitfielded. + * ih&0xff -> legacy irq number. + * ih&0x10000000 -> if 0, old-style isa irq; if 1, routed via ioapic. + * (ih&0xff0000)>>16 -> ioapic id. + * (ih&0x00ff00)>>8 -> ioapic pin. + */ + +#define APIC_INT_VIA_APIC 0x10000000 +#define APIC_INT_VIA_MSG 0x20000000 +#define APIC_INT_VIA_MSGX 0x40000000 +#define APIC_INT_APIC_MASK 0x00ff0000 +#define APIC_INT_APIC_SHIFT 16 +#define APIC_INT_PIN_MASK 0x0000ff00 +#define APIC_INT_PIN_SHIFT 8 + +#define APIC_IRQ_APIC(x) ((x & APIC_INT_APIC_MASK) >> APIC_INT_APIC_SHIFT) +#define APIC_IRQ_PIN(x) ((x & APIC_INT_PIN_MASK) >> APIC_INT_PIN_SHIFT) +#define APIC_IRQ_ISLEGACY(x) (!((x) & APIC_INT_VIA_APIC)) +#define APIC_IRQ_LEGACY_IRQ(x) ((x) & 0xff) + +void ioapic_print_redir(struct ioapic_softc *, char *, int); +struct ioapic_softc *ioapic_find(int); +struct ioapic_softc *ioapic_find_bybase(int); + +void ioapic_enable(void); + +extern int ioapic_bsp_id; +extern int nioapics; +extern struct ioapic_softc *ioapics; + +#endif /* !_MACHINE_I82093VAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/i82489reg.h b/lib/libc/include/x86_64-openbsd-none/machine/i82489reg.h new file mode 100644 index 000000000000..788c516ac729 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/i82489reg.h @@ -0,0 +1,149 @@ +/* $OpenBSD: i82489reg.h,v 1.5 2019/07/26 04:35:38 kevlo Exp $ */ +/* $NetBSD: i82489reg.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Frank van der Linden. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +/* + * Registers and constants for the 82489DX and Pentium (and up) integrated + * "local" APIC. + */ + +#define LAPIC_ID 0x020 /* ID. RW */ +# define LAPIC_ID_MASK 0x0f000000 +# define LAPIC_ID_SHIFT 24 + +#define LAPIC_VERS 0x030 /* Version. R */ +# define LAPIC_VERSION_MASK 0x000000ff +# define LAPIC_VERSION_LVT_MASK 0x00ff0000 +# define LAPIC_VERSION_LVT_SHIFT 16 + +#define LAPIC_TPRI 0x080 /* Task Prio. RW */ +# define LAPIC_TPRI_MASK 0x000000ff +# define LAPIC_TPRI_INT_MASK 0x000000f0 +# define LAPIC_TPRI_SUB_MASK 0x0000000f + +#define LAPIC_APRI 0x090 /* Arbitration prio R */ +# define LAPIC_APRI_MASK 0x000000ff + +#define LAPIC_PPRI 0x0a0 /* Processor prio. R */ +#define LAPIC_EOI 0x0b0 /* End Int. W */ +#define LAPIC_RRR 0x0c0 /* Remote read R */ +#define LAPIC_LDR 0x0d0 /* Logical dest. RW */ +#define LAPIC_DFR 0x0e0 /* Dest. format RW */ + +#define LAPIC_SVR 0x0f0 /* Spurious intvec RW */ +# define LAPIC_SVR_VECTOR_MASK 0x000000ff +# define LAPIC_SVR_VEC_FIX 0x0000000f +# define LAPIC_SVR_VEC_PROG 0x000000f0 +# define LAPIC_SVR_ENABLE 0x00000100 +# define LAPIC_SVR_SWEN 0x00000100 +# define LAPIC_SVR_FOCUS 0x00000200 +# define LAPIC_SVR_FDIS 0x00000200 + +#define LAPIC_ISR 0x100 /* Int. status. R */ +#define LAPIC_TMR 0x180 +#define LAPIC_IRR 0x200 +#define LAPIC_ESR 0x280 /* Err status. R */ + +#define LAPIC_ICRLO 0x300 /* Int. cmd. RW */ +# define LAPIC_DLMODE_MASK 0x00000700 +# define LAPIC_DLMODE_FIXED 0x00000000 +# define LAPIC_DLMODE_LOW 0x00000100 +# define LAPIC_DLMODE_SMI 0x00000200 +# define LAPIC_DLMODE_RR 0x00000300 +# define LAPIC_DLMODE_NMI 0x00000400 +# define LAPIC_DLMODE_INIT 0x00000500 +# define LAPIC_DLMODE_STARTUP 0x00000600 + +# define LAPIC_DSTMODE_LOG 0x00000800 + +# define LAPIC_DLSTAT_BUSY 0x00001000 + +# define LAPIC_LVL_ASSERT 0x00004000 +# define LAPIC_LVL_DEASSERT 0x00000000 + +# define LAPIC_LVL_TRIG 0x00008000 + +# define LAPIC_RRSTAT_MASK 0x00030000 +# define LAPIC_RRSTAT_INPROG 0x00010000 +# define LAPIC_RRSTAT_VALID 0x00020000 + +# define LAPIC_DEST_MASK 0x000c0000 +# define LAPIC_DEST_SELF 0x00040000 +# define LAPIC_DEST_ALLINCL 0x00080000 +# define LAPIC_DEST_ALLEXCL 0x000c0000 + +# define LAPIC_RESV2_MASK 0xfff00000 + + +#define LAPIC_ICRHI 0x310 /* Int. cmd. RW */ + +#define LAPIC_LVTT 0x320 /* Loc.vec.(timer) RW */ +# define LAPIC_LVTT_VEC_MASK 0x000000ff +# define LAPIC_LVTT_DS 0x00001000 +# define LAPIC_LVTT_M 0x00010000 +# define LAPIC_LVTT_TM 0x00020000 +# define LAPIC_LVTT_TM_ONESHOT 0x00000000 +# define LAPIC_LVTT_TM_PERIODIC 0x00020000 +# define LAPIC_LVTT_TM_TSCDL 0x00040000 + +#define LAPIC_PCINT 0x340 +#define LAPIC_LVINT0 0x350 /* Loc.vec (LINT0) RW */ +# define LAPIC_LVT_PERIODIC 0x00020000 +# define LAPIC_LVT_MASKED 0x00010000 +# define LAPIC_LVT_LEVTRIG 0x00008000 +# define LAPIC_LVT_REMOTE_IRR 0x00004000 +# define LAPIC_INP_POL 0x00002000 +# define LAPIC_PEND_SEND 0x00001000 + +#define LAPIC_LVINT1 0x360 /* Loc.vec (LINT1) RW */ +#define LAPIC_LVERR 0x370 /* Loc.vec (ERROR) RW */ +#define LAPIC_ICR_TIMER 0x380 /* Initial count RW */ +#define LAPIC_CCR_TIMER 0x390 /* Current count RO */ + +#define LAPIC_DCR_TIMER 0x3e0 /* Divisor config register */ +# define LAPIC_DCRT_DIV1 0x0b +# define LAPIC_DCRT_DIV2 0x00 +# define LAPIC_DCRT_DIV4 0x01 +# define LAPIC_DCRT_DIV8 0x02 +# define LAPIC_DCRT_DIV16 0x03 +# define LAPIC_DCRT_DIV32 0x08 +# define LAPIC_DCRT_DIV64 0x09 +# define LAPIC_DCRT_DIV128 0x0a + +#define LAPIC_BASE 0xfee00000 + +#define LAPIC_IRQ_MASK(i) (1 << ((i) + 1)) + +#define MSR_X2APIC_BASE 0x800 +#define MSR_X2APIC_EOI (MSR_X2APIC_BASE+0x0b) /* End Int. W */ +#define MSR_X2APIC_ID (MSR_X2APIC_BASE+0x02) /* ID. RW */ +#define X2APIC_ID_MASK 0xff \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/i82489var.h b/lib/libc/include/x86_64-openbsd-none/machine/i82489var.h new file mode 100644 index 000000000000..4477a132663e --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/i82489var.h @@ -0,0 +1,124 @@ +/* $OpenBSD: i82489var.h,v 1.21 2024/11/07 17:24:42 bluhm Exp $ */ +/* $NetBSD: i82489var.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Frank van der Linden. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_I82489VAR_H_ +#define _MACHINE_I82489VAR_H_ + +#include "vmm.h" + +/* + * Software definitions belonging to Local APIC driver. + */ + +#ifdef _KERNEL +extern volatile u_int32_t local_apic[]; +extern volatile u_int32_t lapic_tpr; +#endif + +extern u_int32_t (*lapic_readreg)(int); +extern void (*lapic_writereg)(int, u_int32_t); +u_int32_t lapic_cpu_number(void); + +/* + * "spurious interrupt vector"; vector used by interrupt which was + * aborted because the CPU masked it after it happened but before it + * was delivered.. "Oh, sorry, i caught you at a bad time". + * Low-order 4 bits must be all ones. + */ +extern void Xintrspurious(void); +#define LAPIC_SPURIOUS_VECTOR 0xef + +/* + * Vector used for inter-processor interrupts. + */ +extern void Xintr_lapic_ipi(void); +extern void Xrecurse_lapic_ipi(void); +extern void Xresume_lapic_ipi(void); +#define LAPIC_IPI_VECTOR 0xe0 + +/* + * We take 0xf0-0xfe for fast IPI handlers. + */ +#define LAPIC_IPI_OFFSET 0xf0 +#define LAPIC_IPI_INVLTLB (LAPIC_IPI_OFFSET + 0) +#define LAPIC_IPI_INVLPG (LAPIC_IPI_OFFSET + 1) +#define LAPIC_IPI_INVLRANGE (LAPIC_IPI_OFFSET + 2) +#define LAPIC_IPI_WBINVD (LAPIC_IPI_OFFSET + 3) +#define LAPIC_IPI_INVEPT (LAPIC_IPI_OFFSET + 4) + +extern void Xipi_invltlb(void); +extern void Xipi_invltlb_pcid(void); +extern void Xipi_invlpg(void); +extern void Xipi_invlpg_pcid(void); +extern void Xipi_invlrange(void); +extern void Xipi_invlrange_pcid(void); +extern void Xipi_wbinvd(void); +#if NVMM > 0 +extern void Xipi_invept(void); +#endif /* NVMM > 0 */ + +/* + * Vector used for local apic timer interrupts. + */ + +extern void Xintr_lapic_ltimer(void); +extern void Xresume_lapic_ltimer(void); +extern void Xrecurse_lapic_ltimer(void); +#define LAPIC_TIMER_VECTOR 0xc0 + +/* + * Vector used for Xen HVM Event Channel Interrupts. + */ +extern void Xintr_xen_upcall(void); +extern void Xresume_xen_upcall(void); +extern void Xrecurse_xen_upcall(void); +#define LAPIC_XEN_VECTOR 0x70 + +/* + * Vector used for Hyper-V Interrupts. + */ +extern void Xintr_hyperv_upcall(void); +extern void Xresume_hyperv_upcall(void); +extern void Xrecurse_hyperv_upcall(void); +#define LAPIC_HYPERV_VECTOR 0x71 + +struct cpu_info; + +extern void lapic_boot_init(paddr_t); +extern void lapic_set_lvt(void); +extern void lapic_enable(void); +extern void lapic_disable(void); +extern void lapic_calibrate_timer(struct cpu_info *ci); +extern void lapic_startclock(void); +extern void lapic_initclocks(void); + +#endif \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/i8259.h b/lib/libc/include/x86_64-openbsd-none/machine/i8259.h new file mode 100644 index 000000000000..28bdcd474324 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/i8259.h @@ -0,0 +1,144 @@ +/* $OpenBSD: i8259.h,v 1.4 2015/09/02 13:39:23 mikeb Exp $ */ +/* $NetBSD: i8259.h,v 1.3 2003/05/04 22:01:56 fvdl Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)icu.h 5.6 (Berkeley) 5/9/91 + */ + +#ifndef _MACHINE_I8259_H_ +#define _MACHINE_I8259_H_ + +#include + +#ifndef _LOCORE + +/* + * Interrupt "level" mechanism variables, masks, and macros + */ +extern unsigned i8259_imen; /* interrupt mask enable */ + +extern void i8259_default_setup(void); + +#endif /* !_LOCORE */ + +/* + * Interrupt enable bits -- in order of priority + */ +#define IRQ_SLAVE 2 + +/* + * Interrupt Control offset into Interrupt descriptor table (IDT) + */ +#define ICU_OFFSET 32 /* 0-31 are processor exceptions */ +#define ICU_LEN 16 /* 32-47 are ISA interrupts */ + + +#define ICU_HARDWARE_MASK + +/* + * These macros are fairly self explanatory. If ICU_SPECIAL_MASK_MODE is + * defined, we try to take advantage of the ICU's `special mask mode' by only + * EOIing the interrupts on return. This avoids the requirement of masking and + * unmasking. We can't do this without special mask mode, because the ICU + * would also hold interrupts that it thinks are of lower priority. + * + * Many machines do not support special mask mode, so by default we don't try + * to use it. + */ + +#define IRQ_BIT(num) (1 << ((num) % 8)) +#define IRQ_BYTE(num) ((num) >> 3) + +#define i8259_late_ack(num) + +#ifdef ICU_SPECIAL_MASK_MODE + +#define i8259_asm_ack1(num) +#define i8259_asm_ack2(num) \ + movb $(0x60|IRQ_SLAVE),%al /* specific EOI for IRQ2 */ ;\ + outb %al,$IO_ICU1 +#define i8259_asm_mask(num) +#define i8259_asm_unmask(num) \ + movb $(0x60|(num%8)),%al /* specific EOI */ ;\ + outb %al,$ICUADDR + +#else /* ICU_SPECIAL_MASK_MODE */ + +#ifndef AUTO_EOI_1 +#define i8259_asm_ack1(num) \ + movb $(0x60|(num%8)),%al /* specific EOI */ ;\ + outb %al,$IO_ICU1 +#else +#define i8259_asm_ack1(num) +#endif + +#ifndef AUTO_EOI_2 +#define i8259_asm_ack2(num) \ + movb $(0x60|(num%8)),%al /* specific EOI */ ;\ + outb %al,$IO_ICU2 /* do the second ICU first */ ;\ + movb $(0x60|IRQ_SLAVE),%al /* specific EOI for IRQ2 */ ;\ + outb %al,$IO_ICU1 +#else +#define i8259_asm_ack2(num) +#endif + +#ifdef PIC_MASKDELAY +#define MASKDELAY pushl %eax ; inb $0x84,%al ; popl %eax +#else +#define MASKDELAY +#endif + +#ifdef ICU_HARDWARE_MASK + +#define i8259_asm_mask(num) \ + movb CVAROFF(i8259_imen, IRQ_BYTE(num)),%al ;\ + orb $IRQ_BIT(num),%al ;\ + movb %al,CVAROFF(i8259_imen, IRQ_BYTE(num)) ;\ + MASKDELAY ;\ + outb %al,$(ICUADDR+1) +#define i8259_asm_unmask(num) \ + movb CVAROFF(i8259_imen, IRQ_BYTE(num)),%al ;\ + andb $~IRQ_BIT(num),%al ;\ + movb %al,CVAROFF(i8259_imen, IRQ_BYTE(num)) ;\ + MASKDELAY ;\ + outb %al,$(ICUADDR+1) + +#else /* ICU_HARDWARE_MASK */ + +#define i8259_asm_mask(num) +#define i8259_asm_unmask(num) + +#endif /* ICU_HARDWARE_MASK */ +#endif /* ICU_SPECIAL_MASK_MODE */ + +#endif /* !_MACHINE_I8259_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/ieee.h b/lib/libc/include/x86_64-openbsd-none/machine/ieee.h new file mode 100644 index 000000000000..dea4be1a6ba2 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/ieee.h @@ -0,0 +1,142 @@ +/* $OpenBSD: ieee.h,v 1.2 2008/09/07 20:36:06 martynas Exp $ */ +/* $NetBSD: ieee.h,v 1.1 1996/09/30 16:34:25 ws Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ieee.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * ieee.h defines the machine-dependent layout of the machine's IEEE + * floating point. It does *not* define (yet?) any of the rounding + * mode bits, exceptions, and so forth. + */ + +/* + * Define the number of bits in each fraction and exponent. + * + * k k+1 + * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented + * + * (-exp_bias+1) + * as fractions that look like 0.fffff x 2 . This means that + * + * -126 + * the number 0.10000 x 2 , for instance, is the same as the normalized + * + * -127 -128 + * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero + * + * -129 + * in the fraction; to represent 2 , we need two, and so on. This + * + * (-exp_bias-fracbits+1) + * implies that the smallest denormalized number is 2 + * + * for whichever format we are talking about: for single precision, for + * + * -126 -149 + * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and + * + * -149 == -127 - 23 + 1. + */ +#define SNG_EXPBITS 8 +#define SNG_FRACBITS 23 + +#define DBL_EXPBITS 11 +#define DBL_FRACHBITS 20 +#define DBL_FRACLBITS 32 +#define DBL_FRACBITS 52 + +#define EXT_EXPBITS 15 +#define EXT_FRACHBITS 32 +#define EXT_FRACLBITS 32 +#define EXT_FRACBITS 64 + +#define EXT_TO_ARRAY32(p, a) do { \ + (a)[0] = (uint32_t)(p)->ext_fracl; \ + (a)[1] = (uint32_t)(p)->ext_frach; \ +} while(0) + +struct ieee_single { + u_int sng_frac:23; + u_int sng_exp:8; + u_int sng_sign:1; +}; + +struct ieee_double { + u_int dbl_fracl; + u_int dbl_frach:20; + u_int dbl_exp:11; + u_int dbl_sign:1; +}; + +struct ieee_ext { + u_int ext_fracl; + u_int ext_frach; + u_int ext_exp:15; + u_int ext_sign:1; + u_int ext_padl:16; + u_int ext_padh; +}; + +/* + * Floats whose exponent is in [1..INFNAN) (of whatever type) are + * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. + * Floats whose exponent is zero are either zero (iff all fraction + * bits are zero) or subnormal values. + * + * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its + * high fraction; if the bit is set, it is a `quiet NaN'. + */ +#define SNG_EXP_INFNAN 255 +#define DBL_EXP_INFNAN 2047 +#define EXT_EXP_INFNAN 32767 + +#if 0 +#define SNG_QUIETNAN (1 << 22) +#define DBL_QUIETNAN (1 << 19) +#define EXT_QUIETNAN (1 << 15) +#endif + +/* + * Exponent biases. + */ +#define SNG_EXP_BIAS 127 +#define DBL_EXP_BIAS 1023 +#define EXT_EXP_BIAS 16383 \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/ieeefp.h b/lib/libc/include/x86_64-openbsd-none/machine/ieeefp.h new file mode 100644 index 000000000000..510fd8e15751 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/ieeefp.h @@ -0,0 +1,26 @@ +/* $OpenBSD: ieeefp.h,v 1.2 2011/03/23 16:54:34 pirofti Exp $ */ + +/* + * Written by J.T. Conklin, Apr 6, 1995 + * Public domain. + */ + +#ifndef _MACHINE_IEEEFP_H_ +#define _MACHINE_IEEEFP_H_ + +typedef int fp_except; +#define FP_X_INV 0x01 /* invalid operation exception */ +#define FP_X_DNML 0x02 /* denormalization exception */ +#define FP_X_DZ 0x04 /* divide-by-zero exception */ +#define FP_X_OFL 0x08 /* overflow exception */ +#define FP_X_UFL 0x10 /* underflow exception */ +#define FP_X_IMP 0x20 /* imprecise (loss of precision) */ + +typedef enum { + FP_RN=0, /* round to nearest representable number */ + FP_RM=1, /* round toward negative infinity */ + FP_RP=2, /* round toward positive infinity */ + FP_RZ=3 /* round to zero (truncate) */ +} fp_rnd; + +#endif /* _MACHINE_IEEEFP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/intr.h b/lib/libc/include/x86_64-openbsd-none/machine/intr.h new file mode 100644 index 000000000000..ca5fda214175 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/intr.h @@ -0,0 +1,229 @@ +/* $OpenBSD: intr.h,v 1.36 2025/06/11 09:57:01 kettenis Exp $ */ +/* $NetBSD: intr.h,v 1.2 2003/05/04 22:01:56 fvdl Exp $ */ + +/*- + * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum, and by Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_INTR_H_ +#define _MACHINE_INTR_H_ + +#define __USE_MI_SOFTINTR + +#include +#include + +#ifndef _LOCORE +#include + +#include + +/* + * Struct describing an interrupt source for a CPU. struct cpu_info + * has an array of MAX_INTR_SOURCES of these. The index in the array + * is equal to the stub number of the stubcode as present in vector.s + * + * The primary CPU's array of interrupt sources has its first 16 + * entries reserved for legacy ISA irq handlers. This means that + * they have a 1:1 mapping for arrayindex:irq_num. This is not + * true for interrupts that come in through IO APICs, to find + * their source, go through ci->ci_isources[index].is_pic + * + * It's possible to always maintain a 1:1 mapping, but that means + * limiting the total number of interrupt sources to MAX_INTR_SOURCES + * (32), instead of 32 per CPU. It also would mean that having multiple + * IO APICs which deliver interrupts from an equal pin number would + * overlap if they were to be sent to the same CPU. + */ + +struct intrstub { + void *ist_entry; + void *ist_recurse; + void *ist_resume; +}; + +struct intrsource { + int is_maxlevel; /* max. IPL for this source */ + int is_pin; /* IRQ for legacy; pin for IO APIC */ + struct intrhand *is_handlers; /* handler chain */ + struct pic *is_pic; /* originating PIC */ + void *is_recurse; /* entry for spllower */ + void *is_resume; /* entry for doreti */ + char is_evname[32]; /* event counter name */ + int is_flags; /* see below */ + int is_type; /* level, edge */ + int is_idtvec; + int is_minlevel; +}; + +#define IS_LEGACY 0x0001 /* legacy ISA irq source */ +#define IS_IPI 0x0002 +#define IS_LOG 0x0004 + + +/* + * Interrupt handler chains. *_intr_establish() insert a handler into + * the list. The handler is called with its (single) argument. + */ + +struct intrhand { + int (*ih_fun)(void *); + void *ih_arg; + int ih_level; + int ih_flags; + struct intrhand *ih_next; + int ih_pin; + int ih_slot; + struct cpu_info *ih_cpu; + int ih_irq; + struct evcount ih_count; +}; + +#define IMASK(ci,level) (ci)->ci_imask[(level)] +#define IUNMASK(ci,level) (ci)->ci_iunmask[(level)] + +extern void Xspllower(int); + +int splraise(int); +int spllower(int); +void softintr(int); +void dosoftint(int); + +/* + * Convert spl level to local APIC level + */ +#define APIC_LEVEL(l) ((l) << 4) + +/* + * compiler barrier: prevent reordering of instructions. + * This prevents the compiler from reordering code around + * this "instruction", acting as a sequence point for code generation. + */ + +#define __splbarrier() __asm volatile("":::"memory") + +/* + * Hardware interrupt masks + */ +#define splbio() splraise(IPL_BIO) +#define splnet() splraise(IPL_NET) +#define spltty() splraise(IPL_TTY) +#define splaudio() splraise(IPL_AUDIO) +#define splclock() splraise(IPL_CLOCK) +#define splstatclock() splclock() +#define splipi() splraise(IPL_IPI) + +/* + * Software interrupt masks + */ +#define splsoftclock() splraise(IPL_SOFTCLOCK) +#define splsoftnet() splraise(IPL_SOFTNET) +#define splsofttty() splraise(IPL_SOFTTTY) + +/* + * Miscellaneous + */ +#define splvm() splraise(IPL_VM) +#define splhigh() splraise(IPL_HIGH) +#define spl0() spllower(IPL_NONE) +#define splsched() splraise(IPL_SCHED) +#define splx(x) spllower(x) + +/* SPL asserts */ +#ifdef DIAGNOSTIC +/* + * Although this function is implemented in MI code, it must be in this MD + * header because we don't want this header to include MI includes. + */ +void splassert_fail(int, int, const char *); +extern int splassert_ctl; +void splassert_check(int, const char *); +#define splassert(__wantipl) do { \ + if (splassert_ctl > 0) { \ + splassert_check(__wantipl, __func__); \ + } \ +} while (0) +#define splsoftassert(wantipl) splassert(wantipl) +#else +#define splassert(wantipl) do { /* nada */ } while (0) +#define splsoftassert(wantipl) do { /* nada */ } while (0) +#endif + +#define IPLSHIFT 4 /* The upper nibble of vectors is the IPL. */ +#define IPL(level) ((level) >> IPLSHIFT) /* Extract the IPL. */ + +#include + +/* + * Stub declarations. + */ + +extern void Xsoftclock(void); +extern void Xsoftnet(void); +extern void Xsofttty(void); + +extern struct intrstub i8259_stubs[]; +extern struct intrstub ioapic_edge_stubs[]; +extern struct intrstub ioapic_level_stubs[]; + +struct cpu_info; + +extern int intr_shared_edge; + +extern char idt_allocmap[]; + +void intr_default_setup(void); +int x86_nmi(void); +void intr_calculatemasks(struct cpu_info *); +int intr_allocate_slot_cpu(struct cpu_info *, struct pic *, int, int *); +int intr_allocate_slot(struct pic *, int, int, int, struct cpu_info **, int *, + int *); +void *intr_establish(int, struct pic *, int, int, int, + struct cpu_info *, int (*)(void *), void *, const char *); +void intr_disestablish(struct intrhand *); +int intr_handler(struct intrframe *, struct intrhand *); +void cpu_intr_init(struct cpu_info *); +void intr_printconfig(void); +void intr_barrier(void *); +void intr_set_wakeup(void *); +void intr_enable_wakeup(void); +void intr_disable_wakeup(void); + +#ifdef MULTIPROCESSOR +void x86_send_ipi(struct cpu_info *, int); +int x86_fast_ipi(struct cpu_info *, int); +void x86_broadcast_ipi(int); +void x86_ipi_handler(void); +void x86_setperf_ipi(struct cpu_info *); + +extern void (*ipifunc[X86_NIPI])(struct cpu_info *); +#endif + +#endif /* !_LOCORE */ + +#endif /* !_MACHINE_INTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/intrdefs.h b/lib/libc/include/x86_64-openbsd-none/machine/intrdefs.h new file mode 100644 index 000000000000..54fe1358ca83 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/intrdefs.h @@ -0,0 +1,93 @@ +/* $OpenBSD: intrdefs.h,v 1.24 2024/05/26 13:37:31 kettenis Exp $ */ +/* $NetBSD: intrdefs.h,v 1.2 2003/05/04 22:01:56 fvdl Exp $ */ + +#ifndef _AMD64_INTRDEFS_H +#define _AMD64_INTRDEFS_H + +/* + * Interrupt priority levels. + * + * There are tty, network and disk drivers that use free() at interrupt + * time, so imp > (tty | net | bio). + * + * Since run queues may be manipulated by both the statclock and tty, + * network, and disk drivers, clock > imp. + * + * IPL_HIGH must block everything that can manipulate a run queue. + * + * The level numbers are picked to fit into APIC vector priorities. + * + */ +#define IPL_NONE 0x0 /* nothing */ +#define IPL_SOFTCLOCK 0x1 /* timeouts */ +#define IPL_SOFTNET 0x2 /* protocol stacks */ +#define IPL_BIO 0x3 /* block I/O */ +#define IPL_NET 0x4 /* network */ +#define IPL_SOFTTTY 0x8 /* delayed terminal handling */ +#define IPL_TTY 0x9 /* terminal */ +#define IPL_VM 0xa /* memory allocation */ +#define IPL_AUDIO 0xb /* audio */ +#define IPL_CLOCK 0xc /* clock */ +#define IPL_SCHED IPL_CLOCK +#define IPL_STATCLOCK IPL_CLOCK +#define IPL_HIGH 0xd /* everything */ +#define IPL_IPI 0xe /* inter-processor interrupts */ +#define NIPL 16 + +#define IPL_MPFLOOR IPL_TTY +#define IPL_MPSAFE 0x100 +#define IPL_WAKEUP 0x200 + +/* Interrupt sharing types. */ +#define IST_NONE 0 /* none */ +#define IST_PULSE 1 /* pulsed */ +#define IST_EDGE 2 /* edge-triggered */ +#define IST_LEVEL 3 /* level-triggered */ + +/* + * Local APIC masks. Must not conflict with SIR_* above, and must + * be >= NUM_LEGACY_IRQs. Note that LIR_IPI must be first. + */ +#define LIR_IPI 63 +#define LIR_TIMER 62 + +/* Soft interrupt masks. */ +#define SIR_CLOCK 61 +#define SIR_NET 60 +#define SIR_TTY 59 + +#define LIR_XEN 58 +#define LIR_HYPERV 57 + +/* + * Maximum # of interrupt sources per CPU. 64 to fit in one word. + * ioapics can theoretically produce more, but it's not likely to + * happen. For multiple ioapics, things can be routed to different + * CPUs. + */ +#define MAX_INTR_SOURCES 64 +#define NUM_LEGACY_IRQS 16 + +/* + * Low and high boundaries between which interrupt gates will + * be allocated in the IDT. + */ +#define IDT_INTR_LOW (0x20 + NUM_LEGACY_IRQS) +#define IDT_INTR_HIGH 0xef + +#define X86_IPI_HALT 0x00000001 +#define X86_IPI_NOP 0x00000002 +#define X86_IPI_VMCLEAR_VMM 0x00000004 +#define X86_IPI_PCTR 0x00000010 +#define X86_IPI_MTRR 0x00000020 +#define X86_IPI_SETPERF 0x00000040 +#define X86_IPI_DDB 0x00000080 +#define X86_IPI_START_VMM 0x00000100 +#define X86_IPI_STOP_VMM 0x00000200 +#define X86_IPI_WBINVD 0x00000400 + +#define X86_NIPI 12 + +#define IREENT_MAGIC 0x18041969 + +#endif /* _AMD64_INTRDEFS_H */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/ioctl_fd.h b/lib/libc/include/x86_64-openbsd-none/machine/ioctl_fd.h new file mode 100644 index 000000000000..659711f9d7bd --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/ioctl_fd.h @@ -0,0 +1,130 @@ +/* $OpenBSD: ioctl_fd.h,v 1.2 2011/03/23 16:54:34 pirofti Exp $ */ + +/* + * Copyright (C) 1992-1994 by Joerg Wunsch, Dresden + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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(S) BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * From: Id: ioctl_fd.h,v 1.7 1994/10/30 19:17:39 joerg Exp + */ + +#ifndef _MACHINE_IOCTL_FD_H_ +#define _MACHINE_IOCTL_FD_H_ + +#include + +#define FD_FORMAT_VERSION 110 /* used to validate before formatting */ +#define FD_MAX_NSEC 36 /* highest known number of spt - allow for */ + /* 2.88 MB drives */ + +struct fd_formb { + int format_version; /* == FD_FORMAT_VERSION */ + int cyl, head; + int transfer_rate; /* fdreg.h: FDC_???KBPS */ + + union { + struct fd_form_data { + /* + * DO NOT CHANGE THE LAYOUT OF THIS STRUCTS + * it is hardware-dependant since it exactly + * matches the byte sequence to write to FDC + * during its `format track' operation + */ + u_char secshift; /* 0 -> 128, ...; usually 2 -> 512 */ + u_char nsecs; /* must be <= FD_MAX_NSEC */ + u_char gaplen; /* GAP 3 length; usually 84 */ + u_char fillbyte; /* usually 0xf6 */ + struct fd_idfield_data { + /* + * data to write into id fields; + * for obscure formats, they mustn't match + * the real values (but mostly do) + */ + u_char cylno; /* 0 thru 79 (or 39) */ + u_char headno; /* 0, or 1 */ + u_char secno; /* starting at 1! */ + u_char secsize; /* usually 2 */ + } idfields[FD_MAX_NSEC]; /* 0 <= idx < nsecs used */ + } structured; + u_char raw[1]; /* to have continuous indexed access */ + } format_info; +}; + +/* make life easier */ +# define fd_formb_secshift format_info.structured.secshift +# define fd_formb_nsecs format_info.structured.nsecs +# define fd_formb_gaplen format_info.structured.gaplen +# define fd_formb_fillbyte format_info.structured.fillbyte +/* these data must be filled in for(i = 0; i < fd_formb_nsecs; i++) */ +# define fd_formb_cylno(i) format_info.structured.idfields[i].cylno +# define fd_formb_headno(i) format_info.structured.idfields[i].headno +# define fd_formb_secno(i) format_info.structured.idfields[i].secno +# define fd_formb_secsize(i) format_info.structured.idfields[i].secsize + +/* + * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how + * we tell them apart. + */ +struct fd_type { + int sectrac; /* sectors per track */ + int heads; /* number of heads */ + int seccyl; /* sectors per cylinder */ + int secsize; /* size code for sectors */ + int datalen; /* data len when secsize = 0 */ + int steprate; /* step rate and head unload time */ + int gap1; /* gap len between sectors */ + int gap2; /* formatting gap */ + int tracks; /* total num of tracks */ + int size; /* size of disk in sectors */ + int step; /* steps per cylinder */ + int rate; /* transfer speed code */ + char *name; +}; + + +#define FD_FORM _IOW('F', 61, struct fd_formb) /* format a track */ +#define FD_GTYPE _IOR('F', 62, struct fd_type) /* get drive type */ +#define FD_STYPE _IOW('F', 63, struct fd_type) /* set drive type */ + +#define FD_GOPTS _IOR('F', 64, int) /* drive options, see below */ +#define FD_SOPTS _IOW('F', 65, int) + +#define FDOPT_NORETRY 0x0001 /* no retries on failure (cleared on close) */ + +/* + * The following definitions duplicate those in sys/i386/isa/fdreg.h + * They are here since their values are to be used in the above + * structure when formatting a floppy. For very obvious reasons, both + * definitions must match ;-) + */ +#ifndef FDC_500KBPS +#define FDC_500KBPS 0x00 /* 500KBPS MFM drive transfer rate */ +#define FDC_300KBPS 0x01 /* 300KBPS MFM drive transfer rate */ +#define FDC_250KBPS 0x02 /* 250KBPS MFM drive transfer rate */ +#define FDC_125KBPS 0x03 /* 125KBPS FM drive transfer rate */ + /* for some controllers 1MPBS instead */ +#endif /* FDC_500KBPS */ + + +#endif /* !_MACHINE_IOCTL_FD_H__ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/isa_machdep.h b/lib/libc/include/x86_64-openbsd-none/machine/isa_machdep.h new file mode 100644 index 000000000000..3efae87c134d --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/isa_machdep.h @@ -0,0 +1,163 @@ +/* $OpenBSD: isa_machdep.h,v 1.11 2024/05/22 05:51:49 jsg Exp $ */ +/* $NetBSD: isa_machdep.h,v 1.2 2003/05/09 23:51:28 fvdl Exp $ */ + +/*- + * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)isa.h 5.7 (Berkeley) 5/9/91 + */ + +/* + * Various pieces of the i386 port want to include this file without + * or in spite of using isavar.h, and should be fixed. + */ + +#ifndef _I386_ISA_MACHDEP_H_ /* XXX */ +#define _I386_ISA_MACHDEP_H_ /* XXX */ + +#include +#include + +/* + * ISA can only DMA to 0-16M. + */ +#define ISA_DMA_BOUNCE_THRESHOLD 0x00ffffff + +/* + * XXX THIS FILE IS A MESS. copyright: berkeley's probably. + * contents from isavar.h and isareg.h, mostly the latter. + * perhaps charles's? + * + * copyright from berkeley's isa.h which is now dev/isa/isareg.h. + */ + +/* + * Types provided to machine-independent ISA code. + */ + +typedef void *isa_chipset_tag_t; + +struct device; /* XXX */ +struct isabus_attach_args; /* XXX */ + +/* + * Functions provided to machine-independent ISA code. + */ +void isa_attach_hook(struct device *, struct device *, + struct isabus_attach_args *); +int isa_intr_alloc(isa_chipset_tag_t, int, int, int *); +void *isa_intr_establish(isa_chipset_tag_t ic, int irq, int type, + int level, int (*ih_fun)(void *), void *ih_arg, char *); +void isa_intr_disestablish(isa_chipset_tag_t ic, void *handler); + +int isa_intr_check(isa_chipset_tag_t, int, int); + +/* + * ALL OF THE FOLLOWING ARE MACHINE-DEPENDENT, AND SHOULD NOT BE USED + * BY PORTABLE CODE. + */ + +extern struct bus_dma_tag isa_bus_dma_tag; + +/* + * Cookie used by ISA dma. A pointer to one of these it stashed in + * the DMA map. + */ +struct isa_dma_cookie { + int id_flags; /* flags; see below */ + + void *id_origbuf; /* pointer to orig buffer if + bouncing */ + bus_size_t id_origbuflen; /* ...and size */ + + void *id_bouncebuf; /* pointer to the bounce buffer */ + bus_size_t id_bouncebuflen; /* ...and size */ + int id_nbouncesegs; /* number of valid bounce segs */ + bus_dma_segment_t id_bouncesegs[0]; /* array of bounce buffer + physical memory segments */ +}; + +/* id_flags */ +#define ID_MIGHT_NEED_BOUNCE 0x01 /* map could need bounce buffers */ +#define ID_HAS_BOUNCE 0x02 /* map currently has bounce buffers */ +#define ID_IS_BOUNCING 0x04 /* map is bouncing current xfer */ + +/* + * Variables and macros to deal with the ISA I/O hole. + * XXX These should be converted to machine- and bus-mapping-independent + * function definitions, invoked through the softc. + */ + +extern u_long atdevbase; /* kernel virtual address of "hole" */ + +/* + * Given a kernel virtual address for some location + * in the "hole" I/O space, return a physical address. + */ +#define ISA_PHYSADDR(v) ((void *) ((u_long)(v) - atdevbase + IOM_BEGIN)) + +/* + * Given a physical address in the "hole", + * return a kernel virtual address. + */ +#define ISA_HOLE_VADDR(p) ((void *) ((u_long)(p) - IOM_BEGIN + atdevbase)) + +#endif /* _I386_ISA_MACHDEP_H_ XXX */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/kcore.h b/lib/libc/include/x86_64-openbsd-none/machine/kcore.h new file mode 100644 index 000000000000..b02ab2866472 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/kcore.h @@ -0,0 +1,47 @@ +/* $OpenBSD: kcore.h,v 1.5 2018/04/03 07:13:37 mlarkin Exp $ */ +/* $NetBSD: kcore.h,v 1.1 2003/04/26 18:39:43 fvdl Exp $ */ + +/* + * Copyright (c) 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +/* + * Modified for NetBSD/i386 by Jason R. Thorpe, Numerical Aerospace + * Simulation Facility, NASA Ames Research Center. + * + * And once again modified for x86-64 by Frank van der Linden of + * Wasabi Systems, Inc. + */ + +#ifndef _MACHINE_KCORE_H_ +#define _MACHINE_KCORE_H_ + +typedef struct cpu_kcore_hdr { + u_int64_t ptdpaddr; /* PA of PML4 */ + u_int64_t nmemsegs; /* Number of RAM segments */ +} cpu_kcore_hdr_t; + +#endif /* _MACHINE_KCORE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/limits.h b/lib/libc/include/x86_64-openbsd-none/machine/limits.h new file mode 100644 index 000000000000..f288e0542996 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/limits.h @@ -0,0 +1,52 @@ +/* $OpenBSD: limits.h,v 1.6 2015/04/30 13:42:08 millert Exp $ */ + +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)limits.h 7.2 (Berkeley) 6/28/90 + */ + +#ifndef _MACHINE_LIMITS_H_ +#define _MACHINE_LIMITS_H_ + +#include + +#if __POSIX_VISIBLE || __XPG_VISIBLE +#define SSIZE_MAX LONG_MAX /* max value for a ssize_t */ +#endif + +#if __BSD_VISIBLE +#define SIZE_T_MAX ULONG_MAX /* max value for a size_t (historic) */ + +#define UQUAD_MAX 0xffffffffffffffffULL /* max unsigned quad */ +#define QUAD_MAX 0x7fffffffffffffffLL /* max signed quad */ +#define QUAD_MIN (-0x7fffffffffffffffLL-1) /* min signed quad */ + +#endif /* __BSD_VISIBLE */ + +#endif /* _MACHINE_LIMITS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/loadfile_machdep.h b/lib/libc/include/x86_64-openbsd-none/machine/loadfile_machdep.h new file mode 100644 index 000000000000..c856e9b9f60b --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/loadfile_machdep.h @@ -0,0 +1,61 @@ +/* $OpenBSD: loadfile_machdep.h,v 1.9 2019/05/28 04:51:26 mlarkin Exp $ */ +/* $NetBSD: loadfile_machdep.h,v 1.1 1999/04/29 03:17:12 tsubai Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define BOOT_ELF +#define BOOT_ELF32 +#define BOOT_ELF64 + +/* Keep a default ELFSIZE */ +#define ELFSIZE 64 + +#define LOAD_KERNEL LOAD_ALL +#define COUNT_KERNEL COUNT_ALL + +#ifdef EFIBOOT +extern u_long efi_loadaddr; +#define LOADADDR(a) (((((u_long)(a)) + offset)&0xfffffff) + \ + efi_loadaddr) +#else +#define LOADADDR(a) ((a) + offset) +#endif +#define ALIGNENTRY(a) ((u_long)(a)) +#define READ(f, b, c) read((f), (void *)LOADADDR(b), (c)) +#define BCOPY(s, d, c) memcpy((void *)LOADADDR(d), (void *)(s), (c)) +#define BZERO(d, c) memset((void *)LOADADDR(d), 0, (c)) +#define WARN(a) (void)(printf a, \ + printf((errno ? ": %s\n" : "\n"), \ + strerror(errno))) +#define PROGRESS(a) (void) printf a +#define ALLOC(a) alloc(a) +#define FREE(a, b) free(a, b) + +void run_loadfile(uint64_t *, int); \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/mpbiosreg.h b/lib/libc/include/x86_64-openbsd-none/machine/mpbiosreg.h new file mode 100644 index 000000000000..8a35f5f11d18 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/mpbiosreg.h @@ -0,0 +1,156 @@ +/* $OpenBSD: mpbiosreg.h,v 1.5 2023/04/10 04:21:20 jsg Exp $ */ +/* $NetBSD: mpbiosreg.h,v 1.3 2003/03/04 23:27:32 fvdl Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_MPBIOSREG_H_ +#define _MACHINE_MPBIOSREG_H_ + +#define BIOS_BASE (0xf0000) +#define BIOS_SIZE (0x10000) +#define BIOS_COUNT (BIOS_SIZE) + +/* + * Multiprocessor config table entry types. + */ + +#define MPS_MCT_CPU 0 +#define MPS_MCT_BUS 1 +#define MPS_MCT_IOAPIC 2 +#define MPS_MCT_IOINT 3 +#define MPS_MCT_LINT 4 + +#define MPS_MCT_NTYPES 5 + +/* + * Interrupt types + */ + +#define MPS_INTTYPE_INT 0 +#define MPS_INTTYPE_NMI 1 +#define MPS_INTTYPE_SMI 2 +#define MPS_INTTYPE_ExtINT 3 + +#define MPS_INTPO_DEF 0 +#define MPS_INTPO_ACTHI 1 +#define MPS_INTPO_ACTLO 3 +#define MPS_INTPO_SHIFT 0 +#define MPS_INTPO_MASK 3 + +#define MPS_INTTR_DEF 0 +#define MPS_INTTR_EDGE 1 +#define MPS_INTTR_LEVEL 3 +#define MPS_INTTR_SHIFT 2 +#define MPS_INTTR_MASK 3 + +#define MPS_INT(p,t) \ + ((((p) & MPS_INTPO_MASK) << MPS_INTPO_SHIFT) | \ + (((t) & MPS_INTTR_MASK) << MPS_INTTR_SHIFT)) + +/* MP Floating Pointer Structure */ +struct mpbios_fps { + u_int32_t signature; +/* string defined by the Intel MP Spec as identifying the MP table */ +#define MP_FP_SIG 0x5f504d5f /* _MP_ */ + + u_int32_t pap; + u_int8_t length; + u_int8_t spec_rev; + u_int8_t checksum; + u_int8_t mpfb1; /* system configuration */ + u_int8_t mpfb2; /* flags */ +#define MPFPS_FLAG_IMCR 0x80 /* IMCR present */ + u_int8_t mpfb3; /* unused */ + u_int8_t mpfb4; /* unused */ + u_int8_t mpfb5; /* unused */ +}; + +/* MP Configuration Table Header */ +struct mpbios_cth { + u_int32_t signature; +#define MP_CT_SIG 0x504d4350 /* PCMP */ + + u_int16_t base_len; + u_int8_t spec_rev; + u_int8_t checksum; + u_int8_t oem_id[8]; + u_int8_t product_id[12]; + u_int32_t oem_table_pointer; + u_int16_t oem_table_size; + u_int16_t entry_count; + u_int32_t apic_address; + u_int16_t ext_len; + u_int8_t ext_cksum; + u_int8_t reserved; +}; + +struct mpbios_proc { + u_int8_t type; + u_int8_t apic_id; + u_int8_t apic_version; + u_int8_t cpu_flags; +#define PROCENTRY_FLAG_EN 0x01 +#define PROCENTRY_FLAG_BP 0x02 + u_int32_t cpu_signature; + u_int32_t feature_flags; + u_int32_t reserved1; + u_int32_t reserved2; +}; + +struct mpbios_bus { + u_int8_t type; + u_int8_t bus_id; + char bus_type[6]; +}; + +struct mpbios_ioapic { + u_int8_t type; + u_int8_t apic_id; + u_int8_t apic_version; + u_int8_t apic_flags; +#define IOAPICENTRY_FLAG_EN 0x01 + u_int32_t apic_address; +}; + +struct mpbios_int { + u_int8_t type; + u_int8_t int_type; + u_int16_t int_flags; + u_int8_t src_bus_id; + u_int8_t src_bus_irq; + u_int8_t dst_apic_id; +#define MPS_ALL_APICS 0xff + u_int8_t dst_apic_int; +}; + + +#endif /* !_MACHINE_MPBIOSREG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/mpbiosvar.h b/lib/libc/include/x86_64-openbsd-none/machine/mpbiosvar.h new file mode 100644 index 000000000000..2247427b231e --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/mpbiosvar.h @@ -0,0 +1,57 @@ +/* $OpenBSD: mpbiosvar.h,v 1.7 2025/09/05 16:57:48 kettenis Exp $ */ +/* $NetBSD: mpbiosvar.h,v 1.2 2003/04/02 07:53:57 thorpej Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by RedBack Networks Inc. + * + * Author: Bill Sommerfeld + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef _MACHINE_MPBIOSVAR_H_ +#define _MACHINE_MPBIOSVAR_H_ + +#define MP_TRAMPOLINE (16 * PAGE_SIZE) +#define MP_TRAMP_DATA (17 * PAGE_SIZE) + +#if !defined(_LOCORE) + +#include +#include + +#if defined(_KERNEL) +int mpbios_probe(struct device *); + +void mpbios_intr_fixup(void); + +extern int mpbios_scanned; +#endif + +#endif + +#endif /* !_MACHINE_MPBIOSVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/mpconfig.h b/lib/libc/include/x86_64-openbsd-none/machine/mpconfig.h new file mode 100644 index 000000000000..7fc051d696d3 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/mpconfig.h @@ -0,0 +1,49 @@ +/* $OpenBSD: mpconfig.h,v 1.8 2011/10/21 20:48:11 kettenis Exp $ */ +/* $NetBSD: mpconfig.h,v 1.2 2003/05/11 00:05:52 fvdl Exp $ */ + +/* + * Definitions originally from the mpbios code, but now used for ACPI + * MP config as well. + */ + +#ifndef _AMD64_MPCONFIG_H +#define _AMD64_MPCONFIG_H + +#ifndef _LOCORE + +struct mpbios_int; + +struct mp_bus { + char *mb_name; /* XXX bus name */ + int mb_idx; /* XXX bus index */ + void (*mb_intr_print)(int); + void (*mb_intr_cfg)(const struct mpbios_int *, u_int32_t *); + struct mp_intr_map *mb_intrs; + u_int32_t mb_data; /* random bus-specific datum. */ +}; + +struct mp_intr_map { + struct mp_intr_map *next; + struct mp_bus *bus; + int bus_pin; + struct ioapic_softc *ioapic; + int ioapic_pin; + int ioapic_ih; /* int handle, for apic_intr_est */ + int type; /* from mp spec intr record */ + int flags; /* from mp spec intr record */ + u_int32_t redir; + int cpu_id; +}; + +#if defined(_KERNEL) +extern int mp_verbose; +extern struct mp_bus *mp_busses; +extern int mp_nbusses; +extern struct mp_intr_map *mp_intrs; +extern int mp_nintrs; +extern struct mp_bus *mp_isa_bus; +extern struct mp_bus *mp_eisa_bus; +#endif +#endif + +#endif /* _AMD64_MPCONFIG_H */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/mplock.h b/lib/libc/include/x86_64-openbsd-none/machine/mplock.h new file mode 100644 index 000000000000..d91a96332ee7 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/mplock.h @@ -0,0 +1,10 @@ +/* $OpenBSD: mplock.h,v 1.5 2017/10/17 14:25:35 visa Exp $ */ + +/* public domain */ + +#ifndef _MACHINE_MPLOCK_H_ +#define _MACHINE_MPLOCK_H_ + +#define __USE_MI_MPLOCK + +#endif /* !_MACHINE_MPLOCK_H */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/mutex.h b/lib/libc/include/x86_64-openbsd-none/machine/mutex.h new file mode 100644 index 000000000000..69b3361f02f3 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/mutex.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mutex.h,v 1.11 2018/01/25 15:06:29 mpi Exp $ */ + +#define __USE_MI_MUTEX \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/param.h b/lib/libc/include/x86_64-openbsd-none/machine/param.h new file mode 100644 index 000000000000..69522312f0fe --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/param.h @@ -0,0 +1,81 @@ +/* $OpenBSD: param.h,v 1.30 2025/07/07 18:33:36 kettenis Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ + +#ifdef _KERNEL +#ifdef _LOCORE +#include +#else +#include +#endif +#endif + +#define _MACHINE amd64 +#define MACHINE "amd64" +#define _MACHINE_ARCH amd64 +#define MACHINE_ARCH "amd64" +#define MID_MACHINE MID_AMD64 + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define PAGE_MASK (PAGE_SIZE - 1) + +#define KERNBASE 0xffffffff80000000 /* start of kernel virtual space */ + +#ifdef _KERNEL + +#define KERNTEXTOFF (KERNBASE+0x1000000) /* start of kernel text */ + +#define NBPG PAGE_SIZE /* bytes/page */ +#define PGSHIFT PAGE_SHIFT /* LOG2(PAGE_SIZE) */ +#define PGOFSET PAGE_MASK /* byte offset into page */ + +#define UPAGES 6 /* pages of u-area */ +#define USPACE (UPAGES * PAGE_SIZE) /* total size of u-area */ +#define USPACE_ALIGN 0 /* u-area alignment 0-none */ +#define __HAVE_USPACE_GUARD + +#define NMBCLUSTERS (256 * 1024) /* max cluster allocation */ + +#ifndef MSGBUFSIZE +#define MSGBUFSIZE (32 * PAGE_SIZE) /* default message buffer size */ +#endif + +#define __HAVE_ACPI + +#endif /* _KERNEL */ + +#endif /* _MACHINE_PARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/pcb.h b/lib/libc/include/x86_64-openbsd-none/machine/pcb.h new file mode 100644 index 000000000000..3cc195e20507 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/pcb.h @@ -0,0 +1,93 @@ +/* $OpenBSD: pcb.h,v 1.17 2018/06/05 06:39:11 guenther Exp $ */ +/* $NetBSD: pcb.h,v 1.1 2003/04/26 18:39:45 fvdl Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pcb.h 5.10 (Berkeley) 5/12/91 + */ + +#ifndef _MACHINE_PCB_H_ +#define _MACHINE_PCB_H_ + +#include + +#include + +/* + * Please note that the pcb_savefpu field in struct below must be + * on a 64-byte boundary. + */ +struct pcb { + struct savefpu pcb_savefpu; /* floating point state */ + u_int64_t pcb_cr3; + u_int64_t pcb_rsp; + u_int64_t pcb_rbp; + u_int64_t pcb_kstack; /* kernel stack address */ + u_int64_t pcb_fsbase; /* per-thread offset: %fs */ + caddr_t pcb_onfault; /* copyin/out fault recovery */ + struct pmap *pcb_pmap; /* back pointer to our pmap */ +}; + +#ifdef _KERNEL +void reset_segs(void); +#endif + +#endif /* _MACHINE_PCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/pci_machdep.h b/lib/libc/include/x86_64-openbsd-none/machine/pci_machdep.h new file mode 100644 index 000000000000..6804596ff5a3 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/pci_machdep.h @@ -0,0 +1,137 @@ +/* $OpenBSD: pci_machdep.h,v 1.32 2025/01/23 11:24:34 kettenis Exp $ */ +/* $NetBSD: pci_machdep.h,v 1.1 2003/02/26 21:26:11 fvdl Exp $ */ + +/* + * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. + * Copyright (c) 1994 Charles M. Hannum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Charles M. Hannum. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Machine-specific definitions for PCI autoconfiguration. + */ + +/* + * amd64-specific PCI structure and type definitions. + * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE. + */ + +extern struct bus_dma_tag pci_bus_dma_tag; + +/* + * Types provided to machine-independent PCI code + */ +typedef void *pci_chipset_tag_t; +typedef u_int32_t pcitag_t; + +typedef struct { + pcitag_t tag; + int line, pin; +} pci_intr_handle_t; + +#define pci_intr_line(pc,ih) ((ih.line) & 0xff) + +/* + * amd64-specific PCI variables and functions. + * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE. + */ +struct pci_attach_args; + +extern struct extent *pciio_ex; +extern struct extent *pcimem_ex; +extern struct extent *pcibus_ex; +void pci_init_extents(void); + +/* + * Functions provided to machine-independent PCI code. + */ +void pci_attach_hook(struct device *, struct device *, + struct pcibus_attach_args *); +int pci_bus_maxdevs(pci_chipset_tag_t, int); +pcitag_t pci_make_tag(pci_chipset_tag_t, int, int, int); +void pci_decompose_tag(pci_chipset_tag_t, pcitag_t, + int *, int *, int *); +int pci_conf_size(pci_chipset_tag_t, pcitag_t); +pcireg_t pci_conf_read(pci_chipset_tag_t, pcitag_t, int); +void pci_conf_write(pci_chipset_tag_t, pcitag_t, int, + pcireg_t); +int pci_intr_enable_msivec(struct pci_attach_args *, int); +int pci_intr_map_msi(struct pci_attach_args *, + pci_intr_handle_t *); +int pci_intr_map_msivec(struct pci_attach_args *, + int, pci_intr_handle_t *); +int pci_intr_map_msix(struct pci_attach_args *, + int, pci_intr_handle_t *); +int pci_intr_map(struct pci_attach_args *, pci_intr_handle_t *); +const char *pci_intr_string(pci_chipset_tag_t, pci_intr_handle_t); +void *pci_intr_establish(pci_chipset_tag_t, pci_intr_handle_t, + int, int (*)(void *), void *, const char *); +void *pci_intr_establish_cpu(pci_chipset_tag_t, pci_intr_handle_t, + int, struct cpu_info *, + int (*)(void *), void *, const char *); +void pci_intr_disestablish(pci_chipset_tag_t, void *); +int pci_probe_device_hook(pci_chipset_tag_t, + struct pci_attach_args *); + +void pci_dev_postattach(struct device *, struct pci_attach_args *); + +pcireg_t pci_min_powerstate(pci_chipset_tag_t, pcitag_t); +void pci_set_powerstate_md(pci_chipset_tag_t, pcitag_t, int, int); + +void pci_mcfg_init(bus_space_tag_t, bus_addr_t, int, int, int); +pci_chipset_tag_t pci_lookup_segment(int, int); + +#define __HAVE_PCI_MSIX + +int pci_msix_table_map(pci_chipset_tag_t, pcitag_t, + bus_space_tag_t, bus_space_handle_t *); +void pci_msix_table_unmap(pci_chipset_tag_t, pcitag_t, + bus_space_tag_t, bus_space_handle_t); + +/* + * ALL OF THE FOLLOWING ARE MACHINE-DEPENDENT, AND SHOULD NOT BE USED + * BY PORTABLE CODE. + */ + +/* + * Section 6.2.4, `Miscellaneous Functions' of the PCI Specification, + * says that 255 means `unknown' or `no connection' to the interrupt + * controller on a PC. + */ +#define X86_PCI_INTERRUPT_LINE_NO_CONNECTION 0xff + +/* + * PCI address space is shared with ISA, so avoid legacy ISA I/O + * registers. + */ +#define PCI_IO_START 0x400 +#define PCI_IO_END 0xffff + +/* + * Avoid the DOS Compatibility Memory area. + */ +#define PCI_MEM_START 0x100000 \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/pctr.h b/lib/libc/include/x86_64-openbsd-none/machine/pctr.h new file mode 100644 index 000000000000..53f01bdf681f --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/pctr.h @@ -0,0 +1,73 @@ +/* $OpenBSD: pctr.h,v 1.7 2019/08/26 12:41:47 pirofti Exp $ */ + +/* + * Pentium performance counter driver for OpenBSD. + * Copyright 1996 David Mazieres . + * + * Modification and redistribution in source and binary forms is + * permitted provided that due credit is given to the author and the + * OpenBSD project by leaving this copyright notice intact. + */ + +#ifndef _MACHINE_PCTR_H_ +#define _MACHINE_PCTR_H_ + +#include + +typedef u_int64_t pctrval; + +#define PCTR_NUM 4 + +struct pctrst { + u_int pctr_fn[PCTR_NUM]; /* Current settings of counters */ + pctrval pctr_tsc; /* Free-running 64-bit cycle counter */ + pctrval pctr_hwc[PCTR_NUM]; /* Values of the hardware counters */ +}; + +/* Bit values in fn fields and PIOCS ioctl's */ +#define PCTR_U 0x010000 /* Monitor user-level events */ +#define PCTR_K 0x020000 /* Monitor kernel-level events */ +#define PCTR_E 0x040000 /* Edge detect */ +#define PCTR_EN 0x400000 /* Enable counters (counter 0 only) */ +#define PCTR_I 0x800000 /* Invert counter mask */ + +/* Unit Mask values to distinguish cache coherent states */ +#define PCTR_UM_M 0x0800 /* Modified cache lines */ +#define PCTR_UM_E 0x0400 /* Exclusive cache lines */ +#define PCTR_UM_S 0x0200 /* Shared cache lines */ +#define PCTR_UM_I 0x0100 /* Invalid cache lines */ +#define PCTR_UM_MESI (PCTR_UM_M|PCTR_UM_E|PCTR_UM_S|PCTR_UM_I) +#define PCTR_UM_A 0x2000 /* Any initiator */ + +#define PCTR_UM_SHIFT 8 /* Left shift for unit mask */ +#define PCTR_CM_SHIFT 24 /* Left shift for counter mask */ + +/* ioctl to set which counter a device tracks */ +#define PCIOCRD _IOR('c', 1, struct pctrst) /* Read counter value */ +#define PCIOCS0 _IOW('c', 8, unsigned int) /* Set counter 0 function */ +#define PCIOCS1 _IOW('c', 9, unsigned int) /* Set counter 1 function */ +#define PCIOCS2 _IOW('c', 10, unsigned int) /* Set counter 2 function */ +#define PCIOCS3 _IOW('c', 11, unsigned int) /* Set counter 3 function */ + +#define _PATH_PCTR "/dev/pctr" + +#define rdpmc(pmc) \ +({ \ + u_int32_t hi, lo; \ + __asm volatile("rdpmc" \ + : "=d" (hi), "=a" (lo) : "c" (pmc)); \ + hi &= 0xffffff; \ + (((u_int64_t)hi << 32) | (u_int64_t)lo); \ +}) + +#ifdef _KERNEL + +void pctrattach(int); +int pctropen(dev_t, int, int, struct proc *); +int pctrclose(dev_t, int, int, struct proc *); +int pctrioctl(dev_t, u_long, caddr_t, int, struct proc *); +void pctr_reload(struct cpu_info *); +void pctr_resume(struct cpu_info *); + +#endif /* _KERNEL */ +#endif /* ! _MACHINE_PCTR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/pic.h b/lib/libc/include/x86_64-openbsd-none/machine/pic.h new file mode 100644 index 000000000000..21acee849893 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/pic.h @@ -0,0 +1,45 @@ +/* $OpenBSD: pic.h,v 1.8 2024/01/19 18:38:16 kettenis Exp $ */ +/* $NetBSD: pic.h,v 1.1 2003/02/26 21:26:11 fvdl Exp $ */ + +#ifndef _X86_PIC_H +#define _X86_PIC_H + +#include +#include + +struct cpu_info; + +/* + * Structure common to all PIC softcs + */ +struct pic { + struct device pic_dev; + int pic_type; +#ifdef MULTIPROCESSOR + struct mutex pic_mutex; +#endif + void (*pic_hwmask)(struct pic *, int); + void (*pic_hwunmask)(struct pic *, int); + void (*pic_addroute)(struct pic *, struct cpu_info *, int, int, int); + void (*pic_delroute)(struct pic *, struct cpu_info *, int, int, int); + int (*pic_allocidtvec)(struct pic *, int, int, int); + struct intrstub *pic_level_stubs; + struct intrstub *pic_edge_stubs; +}; + +#define pic_name pic_dev.dv_xname + +/* + * PIC types. + */ +#define PIC_I8259 0 +#define PIC_IOAPIC 1 +#define PIC_LAPIC 2 +#define PIC_MSI 3 +#define PIC_SOFT 4 + +extern struct pic i8259_pic; +extern struct pic local_pic; +extern struct pic msi_pic; +extern struct pic softintr_pic; +#endif \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/pio.h b/lib/libc/include/x86_64-openbsd-none/machine/pio.h new file mode 100644 index 000000000000..f1236a357000 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/pio.h @@ -0,0 +1,225 @@ +/* $OpenBSD: pio.h,v 1.5 2015/04/25 21:31:24 guenther Exp $ */ +/* $NetBSD: pio.h,v 1.2 2003/02/27 11:22:46 fvdl Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_PIO_H_ +#define _MACHINE_PIO_H_ + +/* + * Functions to provide access to x86 programmed I/O instructions. + * + * The in[bwl]() and out[bwl]() functions are split into two varieties: one to + * use a small, constant, 8-bit port number, and another to use a large or + * variable port number. The former can be compiled as a smaller instruction. + */ + + +#ifdef __OPTIMIZE__ + +#define __use_immediate_port(port) \ + (__builtin_constant_p((port)) && (port) < 0x100) + +#else + +#define __use_immediate_port(port) 0 + +#endif + + +#define inb(port) \ + (/* CONSTCOND */ __use_immediate_port(port) ? __inbc(port) : __inb(port)) + +static __inline u_int8_t +__inbc(unsigned port) +{ + u_int8_t data; + __asm volatile("inb %w1,%0" : "=a" (data) : "id" (port)); + return data; +} + +static __inline u_int8_t +__inb(unsigned port) +{ + u_int8_t data; + __asm volatile("inb %w1,%0" : "=a" (data) : "d" (port)); + return data; +} + +static __inline void +insb(unsigned port, void *addr, int cnt) +{ + void *dummy1; + int dummy2; + __asm volatile("repne\n\tinsb" : + "=D" (dummy1), "=c" (dummy2) : + "d" (port), "0" (addr), "1" (cnt) : + "memory"); +} + +#define inw(port) \ + (/* CONSTCOND */ __use_immediate_port(port) ? __inwc(port) : __inw(port)) + +static __inline u_int16_t +__inwc(unsigned port) +{ + u_int16_t data; + __asm volatile("inw %w1,%0" : "=a" (data) : "id" (port)); + return data; +} + +static __inline u_int16_t +__inw(unsigned port) +{ + u_int16_t data; + __asm volatile("inw %w1,%0" : "=a" (data) : "d" (port)); + return data; +} + +static __inline void +insw(unsigned port, void *addr, int cnt) +{ + void *dummy1; + int dummy2; + __asm volatile("repne\n\tinsw" : + "=D" (dummy1), "=c" (dummy2) : + "d" (port), "0" (addr), "1" (cnt) : + "memory"); +} + +#define inl(port) \ + (/* CONSTCOND */ __use_immediate_port(port) ? __inlc(port) : __inl(port)) + +static __inline u_int32_t +__inlc(unsigned port) +{ + u_int32_t data; + __asm volatile("inl %w1,%0" : "=a" (data) : "id" (port)); + return data; +} + +static __inline u_int32_t +__inl(unsigned port) +{ + u_int32_t data; + __asm volatile("inl %w1,%0" : "=a" (data) : "d" (port)); + return data; +} + +static __inline void +insl(unsigned port, void *addr, int cnt) +{ + void *dummy1; + int dummy2; + __asm volatile("repne\n\tinsl" : + "=D" (dummy1), "=c" (dummy2) : + "d" (port), "0" (addr), "1" (cnt) : + "memory"); +} + +#define outb(port, data) \ + (/* CONSTCOND */__use_immediate_port(port) ? __outbc(port, data) : \ + __outb(port, data)) + +static __inline void +__outbc(unsigned port, u_int8_t data) +{ + __asm volatile("outb %0,%w1" : : "a" (data), "id" (port)); +} + +static __inline void +__outb(unsigned port, u_int8_t data) +{ + __asm volatile("outb %0,%w1" : : "a" (data), "d" (port)); +} + +static __inline void +outsb(unsigned port, const void *addr, int cnt) +{ + void *dummy1; + int dummy2; + __asm volatile("repne\n\toutsb" : + "=S" (dummy1), "=c" (dummy2) : + "d" (port), "0" (addr), "1" (cnt)); +} + +#define outw(port, data) \ + (/* CONSTCOND */ __use_immediate_port(port) ? __outwc(port, data) : \ + __outw(port, data)) + +static __inline void +__outwc(unsigned port, u_int16_t data) +{ + __asm volatile("outw %0,%w1" : : "a" (data), "id" (port)); +} + +static __inline void +__outw(unsigned port, u_int16_t data) +{ + __asm volatile("outw %0,%w1" : : "a" (data), "d" (port)); +} + +static __inline void +outsw(unsigned port, const void *addr, int cnt) +{ + void *dummy1; + int dummy2; + __asm volatile("repne\n\toutsw" : + "=S" (dummy1), "=c" (dummy2) : + "d" (port), "0" (addr), "1" (cnt)); +} + +#define outl(port, data) \ + (/* CONSTCOND */ __use_immediate_port(port) ? __outlc(port, data) : \ + __outl(port, data)) + +static __inline void +__outlc(unsigned port, u_int32_t data) +{ + __asm volatile("outl %0,%w1" : : "a" (data), "id" (port)); +} + +static __inline void +__outl(unsigned port, u_int32_t data) +{ + __asm volatile("outl %0,%w1" : : "a" (data), "d" (port)); +} + +static __inline void +outsl(unsigned port, const void *addr, int cnt) +{ + void *dummy1; + int dummy2; + __asm volatile("repne\n\toutsl" : + "=S" (dummy1), "=c" (dummy2) : + "d" (port), "0" (addr), "1" (cnt)); +} + +#endif /* _MACHINE_PIO_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/pmap.h b/lib/libc/include/x86_64-openbsd-none/machine/pmap.h new file mode 100644 index 000000000000..1b1c88897834 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/pmap.h @@ -0,0 +1,524 @@ +/* $OpenBSD: pmap.h,v 1.94 2025/07/07 00:55:15 jsg Exp $ */ +/* $NetBSD: pmap.h,v 1.1 2003/04/26 18:39:46 fvdl Exp $ */ + +/* + * Copyright (c) 1997 Charles D. Cranor and Washington University. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2001 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Frank van der Linden for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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. + */ + +/* + * pmap.h: see pmap.c for the history of this pmap module. + */ + +#ifndef _MACHINE_PMAP_H_ +#define _MACHINE_PMAP_H_ + +#ifndef _LOCORE +#ifdef _KERNEL +#include /* for KASSERT() */ +#include +#endif /* _KERNEL */ +#include +#include +#include +#endif + +/* + * The x86_64 pmap module closely resembles the i386 one. It uses + * the same recursive entry scheme. See the i386 pmap.h for a + * description. The alternate area trick for accessing non-current + * pmaps has been removed, though, because it performs badly on SMP + * systems. + * The most obvious difference to i386 is that 2 extra levels of page + * table need to be dealt with. The level 1 page table pages are at: + * + * l1: 0x00007f8000000000 - 0x00007fffffffffff (39 bits, needs PML4 entry) + * + * The other levels are kept as physical pages in 3 UVM objects and are + * temporarily mapped for virtual access when needed. + * + * The other obvious difference from i386 is that it has a direct map of all + * physical memory in the VA range: + * + * 0xfffffd8000000000 - 0xffffff7fffffffff + * + * The direct map is used in some cases to access PTEs of non-current pmaps. + * + * Note that address space is signed, so the layout for 48 bits is: + * + * +---------------------------------+ 0xffffffffffffffff + * | Kernel Image | + * +---------------------------------+ 0xffffff8000000000 + * | Direct Map | + * +---------------------------------+ 0xfffffd8000000000 + * ~ ~ + * | | + * | Kernel Space | + * | | + * | | + * +---------------------------------+ 0xffff800000000000 = 0x0000800000000000 + * | L1 table (PTE pages) | + * +---------------------------------+ 0x00007f8000000000 + * ~ ~ + * | | + * | User Space | + * | | + * | | + * +---------------------------------+ 0x0000000000000000 + * + * In other words, there is a 'VA hole' at 0x0000800000000000 - + * 0xffff800000000000 which will trap, just as on, for example, + * sparcv9. + * + * The unused space can be used if needed, but it adds a little more + * complexity to the calculations. + */ + +/* + * Mask to get rid of the sign-extended part of addresses. + */ +#define VA_SIGN_MASK 0xffff000000000000 +#define VA_SIGN_NEG(va) ((va) | VA_SIGN_MASK) +/* + * XXXfvdl this one's not right. + */ +#define VA_SIGN_POS(va) ((va) & ~VA_SIGN_MASK) + +#define L4_SLOT_PTE 255 +#define L4_SLOT_KERN 256 +#define L4_SLOT_KERNBASE 511 +#define NUM_L4_SLOT_DIRECT 4 +#define L4_SLOT_DIRECT (L4_SLOT_KERNBASE - NUM_L4_SLOT_DIRECT) +#define L4_SLOT_EARLY (L4_SLOT_DIRECT - 1) + +#define PDIR_SLOT_KERN L4_SLOT_KERN +#define PDIR_SLOT_PTE L4_SLOT_PTE +#define PDIR_SLOT_DIRECT L4_SLOT_DIRECT +#define PDIR_SLOT_EARLY L4_SLOT_EARLY + +/* + * the following defines give the virtual addresses of various MMU + * data structures: + * PTE_BASE: the base VA of the linear PTE mappings + * PDP_PDE: the VA of the PDE that points back to the PDP + * + */ + +#define PTE_BASE ((pt_entry_t *) (L4_SLOT_PTE * NBPD_L4)) +#define PMAP_DIRECT_BASE (VA_SIGN_NEG((L4_SLOT_DIRECT * NBPD_L4))) +#define PMAP_DIRECT_END (VA_SIGN_NEG(((L4_SLOT_DIRECT + \ + NUM_L4_SLOT_DIRECT) * NBPD_L4))) + +#define L1_BASE PTE_BASE + +#define L2_BASE ((pd_entry_t *)((char *)L1_BASE + L4_SLOT_PTE * NBPD_L3)) +#define L3_BASE ((pd_entry_t *)((char *)L2_BASE + L4_SLOT_PTE * NBPD_L2)) +#define L4_BASE ((pd_entry_t *)((char *)L3_BASE + L4_SLOT_PTE * NBPD_L1)) + +#define PDP_PDE (L4_BASE + PDIR_SLOT_PTE) + +#define PDP_BASE L4_BASE + +#define NKL4_MAX_ENTRIES (unsigned long)1 +#define NKL3_MAX_ENTRIES (unsigned long)(NKL4_MAX_ENTRIES * 512) +#define NKL2_MAX_ENTRIES (unsigned long)(NKL3_MAX_ENTRIES * 512) +#define NKL1_MAX_ENTRIES (unsigned long)(NKL2_MAX_ENTRIES * 512) + +#define NKL4_KIMG_ENTRIES 1 +#define NKL3_KIMG_ENTRIES 1 +#define NKL2_KIMG_ENTRIES 64 + +/* number of pages of direct map entries set up by locore0.S */ +#define NDML4_ENTRIES 1 +#define NDML3_ENTRIES 1 +#define NDML2_ENTRIES 4 /* 4GB */ + +/* + * Since kva space is below the kernel in its entirety, we start off + * with zero entries on each level. + */ +#define NKL4_START_ENTRIES 0 +#define NKL3_START_ENTRIES 0 +#define NKL2_START_ENTRIES 0 +#define NKL1_START_ENTRIES 0 /* XXX */ + +#define NTOPLEVEL_PDES (PAGE_SIZE / (sizeof (pd_entry_t))) + +#define NPDPG (PAGE_SIZE / sizeof (pd_entry_t)) + +/* + * pl*_pi: index in the ptp page for a pde mapping a VA. + * (pl*_i below is the index in the virtual array of all pdes per level) + */ +#define pl1_pi(VA) (((VA_SIGN_POS(VA)) & L1_MASK) >> L1_SHIFT) +#define pl2_pi(VA) (((VA_SIGN_POS(VA)) & L2_MASK) >> L2_SHIFT) +#define pl3_pi(VA) (((VA_SIGN_POS(VA)) & L3_MASK) >> L3_SHIFT) +#define pl4_pi(VA) (((VA_SIGN_POS(VA)) & L4_MASK) >> L4_SHIFT) + +/* + * pl*_i: generate index into pde/pte arrays in virtual space + */ +#define pl1_i(VA) (((VA_SIGN_POS(VA)) & L1_FRAME) >> L1_SHIFT) +#define pl2_i(VA) (((VA_SIGN_POS(VA)) & L2_FRAME) >> L2_SHIFT) +#define pl3_i(VA) (((VA_SIGN_POS(VA)) & L3_FRAME) >> L3_SHIFT) +#define pl4_i(VA) (((VA_SIGN_POS(VA)) & L4_FRAME) >> L4_SHIFT) +#define pl_i(va, lvl) \ + (((VA_SIGN_POS(va)) & ptp_masks[(lvl)-1]) >> ptp_shifts[(lvl)-1]) + +#define PTP_MASK_INITIALIZER { L1_FRAME, L2_FRAME, L3_FRAME, L4_FRAME } +#define PTP_SHIFT_INITIALIZER { L1_SHIFT, L2_SHIFT, L3_SHIFT, L4_SHIFT } +#define NKPTP_INITIALIZER { NKL1_START_ENTRIES, NKL2_START_ENTRIES, \ + NKL3_START_ENTRIES, NKL4_START_ENTRIES } +#define NKPTPMAX_INITIALIZER { NKL1_MAX_ENTRIES, NKL2_MAX_ENTRIES, \ + NKL3_MAX_ENTRIES, NKL4_MAX_ENTRIES } +#define NBPD_INITIALIZER { NBPD_L1, NBPD_L2, NBPD_L3, NBPD_L4 } +#define PDES_INITIALIZER { L2_BASE, L3_BASE, L4_BASE } + +/* + * PTP macros: + * a PTP's index is the PD index of the PDE that points to it + * a PTP's offset is the byte-offset in the PTE space that this PTP is at + * a PTP's VA is the first VA mapped by that PTP + */ + +#define ptp_va2o(va, lvl) (pl_i(va, (lvl)+1) * PAGE_SIZE) + +#define PTP_LEVELS 4 + +/* + * PG_AVAIL usage: we make use of the ignored bits of the PTE + */ + +#define PG_W PG_AVAIL1 /* "wired" mapping */ +#define PG_PVLIST PG_AVAIL2 /* mapping has entry on pvlist */ +/* PG_AVAIL3 not used */ + +/* + * PCID assignments. + * The shootdown code assumes KERN, PROC, and PROC_INTEL are both + * consecutive and in that order. + */ +#define PCID_KERN 0 /* for pmap_kernel() */ +#define PCID_PROC 1 /* non-pmap_kernel(), U+K */ +#define PCID_PROC_INTEL 2 /* non-pmap_kernel(), U-K (meltdown) */ +#define PCID_TEMP 3 /* temp mapping of another non-pmap_kernel() */ +#define PCID_EFI 4 /* EFI runtime services */ + +extern int pmap_use_pcid; /* non-zero if PCID support is enabled */ + +/* + * Number of PTEs per cache line. 8 byte pte, 64-byte cache line + * Used to avoid false sharing of cache lines. + */ +#define NPTECL 8 + + +#if defined(_KERNEL) && !defined(_LOCORE) +/* + * pmap data structures: see pmap.c for details of locking. + */ + +struct pmap; +typedef struct pmap *pmap_t; + +/* + * we maintain a list of all non-kernel pmaps + */ + +LIST_HEAD(pmap_head, pmap); /* struct pmap_head: head of a pmap list */ + +/* + * the pmap structure + * + * note that the pm_obj contains the reference count, + * page list, and number of PTPs within the pmap. + */ + +#define PMAP_TYPE_NORMAL 1 +#define PMAP_TYPE_EPT 2 +#define PMAP_TYPE_RVI 3 +#define pmap_nested(pm) ((pm)->pm_type != PMAP_TYPE_NORMAL) +#define pmap_is_ept(pm) ((pm)->pm_type == PMAP_TYPE_EPT) + +struct pmap { + struct mutex pm_mtx; + struct uvm_object pm_obj[PTP_LEVELS-1]; /* objects for lvl >= 1) */ + LIST_ENTRY(pmap) pm_list; /* list (lck by pm_list lock) */ + /* + * pm_pdir : VA of page table to be used when executing in + * privileged mode + * pm_pdirpa : PA of page table to be used when executing in + * privileged mode + * pm_pdir_intel : VA of special page table to be used when executing + * on an Intel CPU in usermode (no kernel mappings) + * pm_pdirpa_intel : PA of special page table to be used when executing + * on an Intel CPU in usermode (no kernel mappings) + */ + pd_entry_t *pm_pdir, *pm_pdir_intel; + paddr_t pm_pdirpa, pm_pdirpa_intel; + + struct vm_page *pm_ptphint[PTP_LEVELS-1]; + /* pointer to a PTP in our pmap */ + struct pmap_statistics pm_stats; /* pmap stats (lck by object lock) */ + + int pm_type; /* Type of pmap this is (PMAP_TYPE_x) */ + uint64_t eptp; /* cached EPTP (used by vmm) */ +}; + +#define PMAP_EFI PMAP_MD0 +#define PMAP_NOCRYPT PMAP_MD1 + +/* + * MD flags that we use for pmap_enter (in the pa): + */ +#define PMAP_PA_MASK ~((paddr_t)PAGE_MASK) /* to remove the flags */ +#define PMAP_NOCACHE 0x1 /* set the non-cacheable bit. */ +#define PMAP_WC 0x2 /* set page write combining. */ + +/* + * We keep mod/ref flags in struct vm_page->pg_flags. + */ +#define PG_PMAP_MOD PG_PMAP0 +#define PG_PMAP_REF PG_PMAP1 +#define PG_PMAP_WC PG_PMAP2 + +/* + * for each managed physical page we maintain a list of 's + * which it is mapped at. + */ +struct pv_entry { /* locked by its list's pvh_lock */ + struct pv_entry *pv_next; /* next entry */ + struct pmap *pv_pmap; /* the pmap */ + vaddr_t pv_va; /* the virtual address */ + struct vm_page *pv_ptp; /* the vm_page of the PTP */ +}; + +/* + * global kernel variables + */ + +extern struct pmap kernel_pmap_store; /* kernel pmap */ + +extern long nkptp[]; + +extern const paddr_t ptp_masks[]; +extern const int ptp_shifts[]; +extern const long nbpd[], nkptpmax[]; + +/* + * macros + */ + +#define pmap_kernel() (&kernel_pmap_store) +#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) +#define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count) +#define pmap_update(pmap) /* nothing (yet) */ + +#define pmap_clear_modify(pg) pmap_clear_attrs(pg, PG_M) +#define pmap_clear_reference(pg) pmap_clear_attrs(pg, PG_U) +#define pmap_is_modified(pg) pmap_test_attrs(pg, PG_M) +#define pmap_is_referenced(pg) pmap_test_attrs(pg, PG_U) +#define pmap_valid_entry(E) ((E) & PG_V) /* is PDE or PTE valid? */ + +#define pmap_proc_iflush(p,va,len) /* nothing */ +#define pmap_unuse_final(p) /* nothing */ +#define pmap_remove_holes(vm) do { /* nothing */ } while (0) + + +/* + * prototypes + */ + +void map_tramps(void); /* machdep.c */ +paddr_t pmap_bootstrap(paddr_t, paddr_t); +void pmap_init_percpu(void); +void pmap_randomize(void); +void pmap_randomize_level(pd_entry_t *, int); +int pmap_clear_attrs(struct vm_page *, unsigned long); +static void pmap_page_protect(struct vm_page *, vm_prot_t); +void pmap_page_remove (struct vm_page *); +static void pmap_protect(struct pmap *, vaddr_t, + vaddr_t, vm_prot_t); +void pmap_remove(struct pmap *, vaddr_t, vaddr_t); +int pmap_test_attrs(struct vm_page *, unsigned); +static void pmap_update_pg(vaddr_t); +void pmap_write_protect(struct pmap *, vaddr_t, + vaddr_t, vm_prot_t); + +paddr_t pmap_prealloc_lowmem_ptps(paddr_t); + +void pagezero(vaddr_t); + +void pmap_convert(struct pmap *, int); +void pmap_enter_special(vaddr_t, paddr_t, vm_prot_t); +vaddr_t pmap_set_pml4_early(paddr_t pa); +void pmap_clear_pml4_early(void); + +/* + * functions for flushing the cache for vaddrs and pages. + * these functions are not part of the MI pmap interface and thus + * should not be used as such. + */ +void pmap_flush_cache(vaddr_t, vsize_t); +#define pmap_flush_page(paddr) do { \ + KDASSERT(PHYS_TO_VM_PAGE(paddr) != NULL); \ + pmap_flush_cache(PMAP_DIRECT_MAP(paddr), PAGE_SIZE); \ +} while (/* CONSTCOND */ 0) + +#define PMAP_CHECK_COPYIN (pg_xo == 0) + +#define PMAP_STEAL_MEMORY /* enable pmap_steal_memory() */ +#define PMAP_GROWKERNEL /* turn on pmap_growkernel interface */ + +/* + * inline functions + */ + +/* + * pmap_update_pg: flush one page from the TLB (or flush the whole thing + * if hardware doesn't support one-page flushing) + */ + +static inline void +pmap_update_pg(vaddr_t va) +{ + invlpg(va); +} + +/* + * pmap_page_protect: change the protection of all recorded mappings + * of a managed page + * + * => this function is a frontend for pmap_page_remove/pmap_clear_attrs + * => we only have to worry about making the page more protected. + * unprotecting a page is done on-demand at fault time. + */ + +static inline void +pmap_page_protect(struct vm_page *pg, vm_prot_t prot) +{ + if (prot == PROT_READ) { + (void) pmap_clear_attrs(pg, PG_RW); + } else { + KASSERT(prot == PROT_NONE); + pmap_page_remove(pg); + } +} + +/* + * pmap_protect: change the protection of pages in a pmap + * + * => this function is a frontend for pmap_remove/pmap_write_protect + * => we only have to worry about making the page more protected. + * unprotecting a page is done on-demand at fault time. + */ + +static inline void +pmap_protect(struct pmap *pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot) +{ + if (prot != PROT_NONE) { + pmap_write_protect(pmap, sva, eva, prot); + } else { + pmap_remove(pmap, sva, eva); + } +} + +/* + * kvtopte: return a pointer to the PTE mapping a kernel VA + */ + +static inline pt_entry_t * +kvtopte(vaddr_t va) +{ +#ifdef LARGEPAGES + { + pd_entry_t *pde; + + pde = L1_BASE + pl2_i(va); + if (*pde & PG_PS) + return ((pt_entry_t *)pde); + } +#endif + + return (PTE_BASE + pl1_i(va)); +} + +#define PMAP_DIRECT_MAP(pa) ((vaddr_t)PMAP_DIRECT_BASE + (pa)) +#define PMAP_DIRECT_UNMAP(va) ((paddr_t)(va) - PMAP_DIRECT_BASE) +#define pmap_map_direct(pg) PMAP_DIRECT_MAP(VM_PAGE_TO_PHYS(pg)) +#define pmap_unmap_direct(va) PHYS_TO_VM_PAGE(PMAP_DIRECT_UNMAP(va)) + +#define __HAVE_PMAP_DIRECT +#define __HAVE_PMAP_MPSAFE_ENTER_COW + +#endif /* _KERNEL && !_LOCORE */ + +#ifndef _LOCORE +struct pv_entry; +struct vm_page_md { + struct mutex pv_mtx; + struct pv_entry *pv_list; +}; + +#define VM_MDPAGE_INIT(pg) do { \ + mtx_init(&(pg)->mdpage.pv_mtx, IPL_VM); \ + (pg)->mdpage.pv_list = NULL; \ +} while (0) +#endif /* !_LOCORE */ + +#endif /* _MACHINE_PMAP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/proc.h b/lib/libc/include/x86_64-openbsd-none/machine/proc.h new file mode 100644 index 000000000000..f365bebe6b5b --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/proc.h @@ -0,0 +1,52 @@ +/* $OpenBSD: proc.h,v 1.10 2018/06/05 06:39:11 guenther Exp $ */ +/* $NetBSD: proc.h,v 1.1 2003/04/26 18:39:46 fvdl Exp $ */ + +/* + * Copyright (c) 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)proc.h 7.1 (Berkeley) 5/15/91 + */ + +#ifndef _MACHINE_PROC_H_ +#define _MACHINE_PROC_H_ + +/* + * Machine-dependent part of the proc structure for amd64. + */ +struct trapframe; +struct mdproc { + struct trapframe *md_regs; /* registers on current frame */ + int md_flags; + volatile int md_astpending; +}; + +/* md_flags */ +#define MDP_IRET 0x0002 /* return via iret, not sysret */ + /* (iret can restore r11 and rcx) */ + +#endif /* _MACHINE_PROC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/profile.h b/lib/libc/include/x86_64-openbsd-none/machine/profile.h new file mode 100644 index 000000000000..04fc7ace4875 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/profile.h @@ -0,0 +1,77 @@ +/* $OpenBSD: profile.h,v 1.6 2023/06/27 10:11:15 cheloha Exp $ */ +/* $NetBSD: profile.h,v 1.3 2003/11/28 23:22:45 fvdl Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)profile.h 8.1 (Berkeley) 6/11/93 + */ + +#define _MCOUNT_DECL void _mcount + +#ifdef __PIC__ +#define __MCPLT "@PLT" +#else +#define __MCPLT +#endif + +#define MCOUNT \ +__asm(" .globl __mcount \n" \ +" .type __mcount,@function\n" \ +"__mcount: \n" \ +" pushq %rbp \n" \ +" movq %rsp,%rbp \n" \ +" subq $56,%rsp \n" \ +" movq %rdi,0(%rsp) \n" \ +" movq %rsi,8(%rsp) \n" \ +" movq %rdx,16(%rsp) \n" \ +" movq %rcx,24(%rsp) \n" \ +" movq %r8,32(%rsp) \n" \ +" movq %r9,40(%rsp) \n" \ +" movq %rax,48(%rsp) \n" \ +" movq 0(%rbp),%r11 \n" \ +" movq 8(%r11),%rdi \n" \ +" movq 8(%rbp),%rsi \n" \ +" call _mcount"__MCPLT"\n" \ +" movq 0(%rsp),%rdi \n" \ +" movq 8(%rsp),%rsi \n" \ +" movq 16(%rsp),%rdx \n" \ +" movq 24(%rsp),%rcx \n" \ +" movq 32(%rsp),%r8 \n" \ +" movq 40(%rsp),%r9 \n" \ +" movq 48(%rsp),%rax \n" \ +" leave \n" \ +" ret \n" \ +" lfence \n" \ +" .size __mcount,.-__mcount"); + + +#ifdef _KERNEL +#define MCOUNT_ENTER s = intr_disable() +#define MCOUNT_EXIT intr_restore(s) +#endif /* _KERNEL */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/psl.h b/lib/libc/include/x86_64-openbsd-none/machine/psl.h new file mode 100644 index 000000000000..2fa183244ff5 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/psl.h @@ -0,0 +1,76 @@ +/* $OpenBSD: psl.h,v 1.5 2018/07/09 19:20:29 guenther Exp $ */ +/* $NetBSD: psl.h,v 1.1 2003/02/26 21:26:11 fvdl Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)psl.h 5.2 (Berkeley) 1/18/91 + */ + +#ifndef _MACHINE_PSL_H_ +#define _MACHINE_PSL_H_ + +/* + * 386 processor status longword. + */ +#define PSL_C 0x00000001 /* carry flag */ +#define PSL_PF 0x00000004 /* parity flag */ +#define PSL_AF 0x00000010 /* auxiliary carry flag */ +#define PSL_Z 0x00000040 /* zero flag */ +#define PSL_N 0x00000080 /* sign flag */ +#define PSL_T 0x00000100 /* trap flag */ +#define PSL_I 0x00000200 /* interrupt enable flag */ +#define PSL_D 0x00000400 /* direction flag */ +#define PSL_V 0x00000800 /* overflow flag */ +#define PSL_IOPL 0x00003000 /* i/o privilege level */ +#define PSL_NT 0x00004000 /* nested task */ +#define PSL_RF 0x00010000 /* resume flag */ +#define PSL_VM 0x00020000 /* virtual 8086 mode */ +#define PSL_AC 0x00040000 /* alignment check flag */ +#define PSL_VIF 0x00080000 /* virtual interrupt enable flag */ +#define PSL_VIP 0x00100000 /* virtual interrupt pending flag */ +#define PSL_ID 0x00200000 /* identification flag */ + +#define PSL_MBO 0x00000002 /* must be one bits */ +#define PSL_MBZ 0xffc08028 /* must be zero bits */ + +#define PSL_USERSET (PSL_MBO | PSL_I) +#define PSL_USERSTATIC (PSL_MBO | PSL_MBZ | PSL_I | PSL_IOPL | PSL_NT | PSL_VM | PSL_VIF | PSL_VIP) +#define PSL_USER (PSL_C | PSL_MBO | PSL_PF | PSL_AF | PSL_Z | PSL_N | PSL_V) + +/* + * ??? + */ +#ifdef _KERNEL +#include +#endif + +#endif /* !_MACHINE_PSL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/pte.h b/lib/libc/include/x86_64-openbsd-none/machine/pte.h new file mode 100644 index 000000000000..c91bf8cea9cf --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/pte.h @@ -0,0 +1,171 @@ +/* $OpenBSD: pte.h,v 1.18 2024/07/09 19:11:06 bluhm Exp $ */ +/* $NetBSD: pte.h,v 1.1 2003/04/26 18:39:47 fvdl Exp $ */ + +/* + * Copyright (c) 2001 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Frank van der Linden for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_PTE_H_ +#define _MACHINE_PTE_H_ + +/* + * amd64 MMU hardware structure: + * + * the (first generation) amd64 MMU is a 4-level MMU which maps 2^48 bytes + * of virtual memory. The pagesize we use is 4K (4096 [0x1000] bytes), + * although 2M and 4M can be used as well. The indexes in the levels + * are 9 bits wide (512 64bit entries per level), dividing the bits + * 9-9-9-9-12. + * + * The top level table, called PML4, contains 512 64bit entries pointing + * to 3rd level table. The 3rd level table is called the 'page directory + * pointers directory' and has 512 entries pointing to page directories. + * The 2nd level is the page directory, containing 512 pointers to + * page table pages. Lastly, level 1 consists of pages containing 512 + * PTEs. + * + * Simply put, levels 4-1 all consist of pages containing 512 + * entries pointing to the next level. Level 0 is the actual PTEs + * themselves. + * + * For a description on the other bits, which are i386 compatible, + * see the i386 pte.h + */ + +#if !defined(_LOCORE) + +/* + * here we define the data types for PDEs and PTEs + */ + +typedef u_int64_t pd_entry_t; /* PDE */ +typedef u_int64_t pt_entry_t; /* PTE */ + +#endif + +/* + * now we define various for playing with virtual addresses + */ + +#define L1_SHIFT 12 +#define L2_SHIFT 21 +#define L3_SHIFT 30 +#define L4_SHIFT 39 +#define NBPD_L1 (1ULL << L1_SHIFT) /* # bytes mapped by L1 ent (4K) */ +#define NBPD_L2 (1ULL << L2_SHIFT) /* # bytes mapped by L2 ent (2MB) */ +#define NBPD_L3 (1ULL << L3_SHIFT) /* # bytes mapped by L3 ent (1G) */ +#define NBPD_L4 (1ULL << L4_SHIFT) /* # bytes mapped by L4 ent (512G) */ + +#define L4_MASK 0x0000ff8000000000UL +#define L3_MASK 0x0000007fc0000000UL +#define L2_MASK 0x000000003fe00000UL +#define L1_MASK 0x00000000001ff000UL + +#define L4_FRAME L4_MASK +#define L3_FRAME (L4_FRAME|L3_MASK) +#define L2_FRAME (L3_FRAME|L2_MASK) +#define L1_FRAME (L2_FRAME|L1_MASK) + +#define PAGE_MASK_L2 (NBPD_L2 - 1) + +#define x86_round_pdr(x) \ + ((((unsigned long)(x)) + (NBPD_L2 - 1)) & ~(NBPD_L2 - 1)) + +/* + * PDE/PTE bits. These are no different from their i386 counterparts. + */ + +#define PG_V 0x0000000000000001UL /* valid */ +#define PG_RO 0x0000000000000000UL /* read-only */ +#define PG_RW 0x0000000000000002UL /* read-write */ +#define PG_u 0x0000000000000004UL /* user accessible */ +#define PG_PROT 0x0000000000000006UL +#define PG_WT 0x0000000000000008UL /* write through */ +#define PG_N 0x0000000000000010UL /* non-cacheable */ +#define PG_U 0x0000000000000020UL /* used */ +#define PG_M 0x0000000000000040UL /* modified */ +#define PG_PAT 0x0000000000000080UL /* PAT bit. (on pte) */ +#define PG_PS 0x0000000000000080UL /* 2MB page size (on pde) */ +#define PG_G 0x0000000000000100UL /* not flushed */ +#define PG_AVAIL1 0x0000000000000200UL +#define PG_AVAIL2 0x0000000000000400UL +#define PG_AVAIL3 0x0000000000000800UL +#define PG_PATLG 0x0000000000001000UL /* PAT on large pages */ +#define PG_PKMASK 0x7800000000000000UL /* Protection Key Mask */ +#define PG_XO 0x0800000000000000UL /* key1 used for execute-only */ +#define PG_NX 0x8000000000000000UL /* non-executable */ +#define PG_FRAME 0x000ffffffffff000UL + +#define PG_LGFRAME 0x000fffffffe00000UL /* large (2M) page frame mask */ + +#define PGK_VALUE 0xfffffffc /* key0 is normal */ + +/* EPT PTE bits */ +#define EPT_R (1ULL << 0) +#define EPT_W (1ULL << 1) +#define EPT_X (1ULL << 2) +#define EPT_WB (6ULL << 3) +#define EPT_PS (1ULL << 7) + +/* Cacheability bits when we are using PAT */ +#define PG_WB (0) /* The default */ +#define PG_WC (PG_WT) /* WT and CD is WC */ +#define PG_UCMINUS (PG_N) /* UC but mtrr can override */ +#define PG_UC (PG_WT | PG_N) /* hard UC */ + +/* + * short forms of protection codes + */ + +#define PG_KR 0x0000000000000000UL /* kernel read-only */ +#define PG_KW 0x0000000000000002UL /* kernel read-write */ + +/* + * page protection exception bits + */ + +#define PGEX_P 0x01 /* protection violation (vs. no mapping) */ +#define PGEX_W 0x02 /* exception during a write cycle */ +#define PGEX_U 0x04 /* exception while in user mode (upl) */ +#define PGEX_I 0x10 /* instruction fetch blocked by NX */ +#define PGEX_PK 0x20 /* protection-key violation */ + +#ifdef _KERNEL +extern pt_entry_t pg_xo; /* XO pte bits using PKU key1 */ +extern pt_entry_t pg_nx; /* NX pte bit */ +extern pt_entry_t pg_crypt; /* C pte bit */ +extern pt_entry_t pg_g_kern; /* PG_G if glbl mappings can be used in kern */ +#endif /* _KERNEL */ + +#endif /* _MACHINE_PTE_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/ptrace.h b/lib/libc/include/x86_64-openbsd-none/machine/ptrace.h new file mode 100644 index 000000000000..7a0450c88f69 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/ptrace.h @@ -0,0 +1,56 @@ +/* $OpenBSD: ptrace.h,v 1.2 2024/11/27 05:25:57 anton Exp $ */ +/* $NetBSD: ptrace.h,v 1.1 2003/04/26 18:39:47 fvdl Exp $ */ + +/* + * Copyright (c) 1993 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * i386-dependent ptrace definitions + */ +#define PT_STEP (PT_FIRSTMACH + 0) +#define PT_GETREGS (PT_FIRSTMACH + 1) +#define PT_SETREGS (PT_FIRSTMACH + 2) +#define PT_GETFPREGS (PT_FIRSTMACH + 3) +#define PT_SETFPREGS (PT_FIRSTMACH + 4) + +#define PT_GETXSTATE_INFO (PT_FIRSTMACH + 5) +#define PT_GETXSTATE (PT_FIRSTMACH + 6) +#define PT_SETXSTATE (PT_FIRSTMACH + 7) + +struct ptrace_xstate_info { + uint64_t xsave_mask; + uint32_t xsave_len; +}; + +#ifdef _KERNEL +int process_read_xstate_info(struct proc *, void *); +int process_read_xstate(struct proc *, void *); +int process_write_xstate(struct proc *, void *); +#endif \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/rbus_machdep.h b/lib/libc/include/x86_64-openbsd-none/machine/rbus_machdep.h new file mode 100644 index 000000000000..6c293739bc80 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/rbus_machdep.h @@ -0,0 +1,48 @@ +/* $OpenBSD: rbus_machdep.h,v 1.8 2024/05/22 05:51:49 jsg Exp $ */ +/* $NetBSD: rbus_machdep.h,v 1.2 1999/10/15 06:43:05 haya Exp $ */ + +/* + * Copyright (c) 1999 + * HAYAKAWA Koichi. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_RBUS_MACHDEP_H_ +#define _MACHINE_RBUS_MACHDEP_H_ + +struct pci_attach_args; /* XXX */ + +#define md_space_map(rbt, physaddr, size, flags, bshp) \ + _bus_space_map((rbt)->rb_bt, (physaddr), (size), (flags), (bshp)) + +#define md_space_unmap(rbt, bsh, size, adrp) \ + _bus_space_unmap((rbt)->rb_bt, (bsh), (size), (adrp)) + +rbus_tag_t rbus_pccbb_parent_io(struct device *, + struct pci_attach_args *); +rbus_tag_t rbus_pccbb_parent_mem(struct device *, + struct pci_attach_args *); + +void pccbb_attach_hook(struct device *, struct device *, + struct pci_attach_args *); + +#endif /* _MACHINE_RBUS_MACHDEP_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/reg.h b/lib/libc/include/x86_64-openbsd-none/machine/reg.h new file mode 100644 index 000000000000..de1804e1945d --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/reg.h @@ -0,0 +1,125 @@ +/* $OpenBSD: reg.h,v 1.7 2019/07/14 05:08:26 guenther Exp $ */ +/* $NetBSD: reg.h,v 1.1 2003/04/26 18:39:47 fvdl Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)reg.h 5.5 (Berkeley) 1/18/91 + */ + +#ifndef _MACHINE_REG_H_ +#define _MACHINE_REG_H_ + +#include + +/* + * XXX + * The #defines aren't used in the kernel, but some user-level code still + * expects them. + */ + +/* When referenced during a trap/exception, registers are at these offsets */ + +#define tRDI 0 +#define tRSI 1 +#define tRDX 2 +#define tRCX 3 +#define tR8 4 +#define tR9 5 +#define tR10 6 +#define tR11 7 +#define tR12 8 +#define tR13 9 +#define tR14 10 +#define tR15 11 +#define tRBP 12 +#define tRBX 13 +#define tRAX 14 +#define tRSP 15 +#define tRIP 16 +#define tRFLAGS 17 +#define tCS 18 +#define tSS 19 +#define tDS 20 +#define tES 21 +#define tFS 22 +#define tGS 23 + +/* + * Registers accessible to ptrace(2) syscall for debugger use. + */ +struct reg { + int64_t r_rdi; + int64_t r_rsi; + int64_t r_rdx; + int64_t r_rcx; + int64_t r_r8; + int64_t r_r9; + int64_t r_r10; + int64_t r_r11; + int64_t r_r12; + int64_t r_r13; + int64_t r_r14; + int64_t r_r15; + int64_t r_rbp; + int64_t r_rbx; + int64_t r_rax; + int64_t r_rsp; + int64_t r_rip; + int64_t r_rflags; + int64_t r_cs; + int64_t r_ss; + int64_t r_ds; + int64_t r_es; + int64_t r_fs; + int64_t r_gs; +}; + +struct fpreg { + struct fxsave64 fxstate; +}; + +#define fp_fcw fxstate.fx_fcw +#define fp_fsw fxstate.fx_fsw +#define fp_ftw fxstate.fx_ftw +#define fp_fop fxstate.fx_fop +#define fp_rip fxstate.fx_rip +#define fp_rdp fxstate.fx_rdp +#define fp_mxcsr fxstate.fx_mxcsr +#define fp_mxcsr_mask fxstate.fx_mxcsr_mask +#define fp_st fxstate.fx_st +#define fp_xmm fxstate.fx_xmm + +#ifdef _KERNEL +int check_context(const struct reg *, struct trapframe *); +#endif + +#endif /* !_MACHINE_REG_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/reloc.h b/lib/libc/include/x86_64-openbsd-none/machine/reloc.h new file mode 100644 index 000000000000..b83e6d05711c --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/reloc.h @@ -0,0 +1,69 @@ +/* $OpenBSD: reloc.h,v 1.4 2018/10/20 11:56:31 kettenis Exp $ */ + +/* + * Copyright (c) 2002,2003 Dale Rahn + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _MACHINE_RELOC_H_ +#define _MACHINE_RELOC_H_ + +#define R_TYPE(X) __CONCAT(R_X86_64_,X) + +#define R_X86_64_NONE 0 +#define R_X86_64_64 1 +#define R_X86_64_PC32 2 +#define R_X86_64_GOT32 3 +#define R_X86_64_PLT32 4 +#define R_X86_64_COPY 5 +#define R_X86_64_GLOB_DAT 6 +#define R_X86_64_JUMP_SLOT 7 +#define R_X86_64_RELATIVE 8 +#define R_X86_64_GOTPCREL 9 +#define R_X86_64_32 10 +#define R_X86_64_32S 11 +#define R_X86_64_16 12 +#define R_X86_64_PC16 13 +#define R_X86_64_8 14 +#define R_X86_64_PC8 15 +#define R_X86_64_DTPMOD64 16 +#define R_X86_64_DTPOFF64 17 +#define R_X86_64_TPOFF64 18 +#define R_X86_64_TLSGD 19 +#define R_X86_64_TLSLD 20 +#define R_X86_64_DTPOFF32 21 +#define R_X86_64_GOTTPOFF 22 +#define R_X86_64_TPOFF32 23 + +#define R_386_NONE 0 +#define R_386_32 1 +#define R_386_PC32 2 +#define R_386_GOT32 3 +#define R_386_PLT32 4 +#define R_386_COPY 5 +#define R_386_GLOB_DAT 6 +#define R_386_JMP_SLOT 7 +#define R_386_RELATIVE 8 +#define R_386_GOTOFF 9 +#define R_386_GOTPC 10 + +#endif /* _MACHINE_RELOC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/segments.h b/lib/libc/include/x86_64-openbsd-none/machine/segments.h new file mode 100644 index 000000000000..8bf2140313d4 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/segments.h @@ -0,0 +1,279 @@ +/* $OpenBSD: segments.h,v 1.18 2025/06/27 17:23:49 bluhm Exp $ */ +/* $NetBSD: segments.h,v 1.1 2003/04/26 18:39:47 fvdl Exp $ */ + +/*- + * Copyright (c) 1995, 1997 + * Charles M. Hannum. All rights reserved. + * Copyright (c) 1989, 1990 William F. Jolitz + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)segments.h 7.1 (Berkeley) 5/9/91 + */ + +/* + * Adapted for NetBSD/amd64 by fvdl@wasabisystems.com. + */ + +/* + * 386 Segmentation Data Structures and definitions + * William F. Jolitz (william@ernie.berkeley.edu) 6/20/1989 + */ + +#ifndef _MACHINE_SEGMENTS_H_ +#define _MACHINE_SEGMENTS_H_ + +/* + * Selectors + */ + +#define ISPL(s) ((s) & SEL_RPL) /* what is the priority level of a selector */ +#define SEL_KPL 0 /* kernel privilege level */ +#define SEL_UPL 3 /* user privilege level */ +#define SEL_RPL 3 /* requester's privilege level mask */ +#define ISLDT(s) ((s) & SEL_LDT) /* is it local or global */ +#define SEL_LDT 4 /* local descriptor table */ + +#define SYSSEL_START (NGDT_MEM << 3) +#define GDT_SIZE (SYSSEL_START + (NGDT_SYS << 4)) + +/* + * These define the index not from the start of the GDT, but from + * the part of the GDT that they're allocated from. + * First NGDT_MEM entries are 8-byte descriptors for CS and DS. + * Next NGDT_SYS entries are 16-byte descriptors defining TSSs. + */ + +#define IDXSEL(s) (((s) >> 3) & 0x1fff) +#define IDXDYNSEL(s) ((((s) & ~SEL_RPL) - DYNSEL_START) >> 4) + +#define GSEL(s,r) (((s) << 3) | r) +#define GSYSSEL(s,r) ((((s) << 4) + SYSSEL_START) | r) +#define GDYNSEL(s,r) ((((s) << 4) + DYNSEL_START) | r | SEL_KPL) + +#define LSEL(s,r) ((s) | r | SEL_LDT) + +#define USERMODE(c, f) (ISPL(c) == SEL_UPL) +#define KERNELMODE(c, f) (ISPL(c) == SEL_KPL) + +#ifndef _LOCORE + +/* + * Memory and System segment descriptors + */ + +/* + * Below is used for TSS and LDT. + */ +struct sys_segment_descriptor { + u_int64_t sd_lolimit:16; /* segment extent (lsb) */ + u_int64_t sd_lobase:24; /* segment base address (lsb) */ + u_int64_t sd_type:5; /* segment type */ + u_int64_t sd_dpl:2; /* segment descriptor priority level */ + u_int64_t sd_p:1; /* segment descriptor present */ + u_int64_t sd_hilimit:4; /* segment extent (msb) */ + u_int64_t sd_xx1:3; /* avl, long and def32 (not used) */ + u_int64_t sd_gran:1; /* limit granularity (byte/page) */ + u_int64_t sd_hibase:40; /* segment base address (msb) */ + u_int64_t sd_xx2:8; /* reserved */ + u_int64_t sd_zero:5; /* must be zero */ + u_int64_t sd_xx3:19; /* reserved */ +} __packed; + +/* + * Below is used for cs, ds, etc. + */ +struct mem_segment_descriptor { + unsigned int sd_lolimit:16; /* segment extent (lsb) */ + unsigned int sd_lobase:24; /* segment base address (lsb) */ + unsigned int sd_type:5; /* segment type */ + unsigned int sd_dpl:2; /* segment descriptor priority level */ + unsigned int sd_p:1; /* segment descriptor present */ + unsigned int sd_hilimit:4; /* segment extent (msb) */ + unsigned int sd_avl:1; /* available */ + unsigned int sd_long:1; /* long mode */ + unsigned int sd_def32:1; /* default 32 vs 16 bit size */ + unsigned int sd_gran:1; /* limit granularity (byte/page) */ + unsigned int sd_hibase:8; /* segment base address (msb) */ +} __packed; + +/* + * Gate descriptors (e.g. indirect descriptors) + */ +struct gate_descriptor { + u_int64_t gd_looffset:16; /* gate offset (lsb) */ + u_int64_t gd_selector:16; /* gate segment selector */ + u_int64_t gd_ist:3; /* IST select */ + u_int64_t gd_xx1:5; /* reserved */ + u_int64_t gd_type:5; /* segment type */ + u_int64_t gd_dpl:2; /* segment descriptor priority level */ + u_int64_t gd_p:1; /* segment descriptor present */ + u_int64_t gd_hioffset:48; /* gate offset (msb) */ + u_int64_t gd_xx2:8; /* reserved */ + u_int64_t gd_zero:5; /* must be zero */ + u_int64_t gd_xx3:19; /* reserved */ +} __packed; + +/* + * region descriptors, used to load gdt/idt tables before segments yet exist. + */ +struct region_descriptor { + u_int16_t rd_limit; /* segment extent */ + u_int64_t rd_base; /* base address */ +} __packed; + +#ifdef _KERNEL +extern struct gate_descriptor *idt; +extern struct gate_descriptor early_idt[]; + +void setgate(struct gate_descriptor *, void *, int, int, int, int); +void unsetgate(struct gate_descriptor *); +void setregion(struct region_descriptor *, void *, u_int16_t); +void set_sys_segment(struct sys_segment_descriptor *, void *, size_t, + int, int, int); +void set_mem_segment(struct mem_segment_descriptor *, void *, size_t, + int, int, int, int, int); +int idt_vec_alloc(int, int); +int idt_vec_alloc_range(int, int, int); +void idt_vec_set(int, void (*)(void)); +void idt_vec_free(int); +void cpu_init_idt(void); + +#endif /* _KERNEL */ + +#endif /* !_LOCORE */ + +/* system segments and gate types */ +#define SDT_SYSNULL 0 /* system null */ +#define SDT_SYS286TSS 1 /* system 286 TSS available */ +#define SDT_SYSLDT 2 /* system local descriptor table */ +#define SDT_SYS286BSY 3 /* system 286 TSS busy */ +#define SDT_SYS286CGT 4 /* system 286 call gate */ +#define SDT_SYSTASKGT 5 /* system task gate */ +#define SDT_SYS286IGT 6 /* system 286 interrupt gate */ +#define SDT_SYS286TGT 7 /* system 286 trap gate */ +#define SDT_SYSNULL2 8 /* system null again */ +#define SDT_SYS386TSS 9 /* system 386 TSS available */ +#define SDT_SYSNULL3 10 /* system null again */ +#define SDT_SYS386BSY 11 /* system 386 TSS busy */ +#define SDT_SYS386CGT 12 /* system 386 call gate */ +#define SDT_SYSNULL4 13 /* system null again */ +#define SDT_SYS386IGT 14 /* system 386 interrupt gate */ +#define SDT_SYS386TGT 15 /* system 386 trap gate */ + +/* memory segment types */ +#define SDT_MEMRO 16 /* memory read only */ +#define SDT_MEMROA 17 /* memory read only accessed */ +#define SDT_MEMRW 18 /* memory read write */ +#define SDT_MEMRWA 19 /* memory read write accessed */ +#define SDT_MEMROD 20 /* memory read only expand dwn limit */ +#define SDT_MEMRODA 21 /* memory read only expand dwn limit accessed */ +#define SDT_MEMRWD 22 /* memory read write expand dwn limit */ +#define SDT_MEMRWDA 23 /* memory read write expand dwn limit acessed */ +#define SDT_MEME 24 /* memory execute only */ +#define SDT_MEMEA 25 /* memory execute only accessed */ +#define SDT_MEMER 26 /* memory execute read */ +#define SDT_MEMERA 27 /* memory execute read accessed */ +#define SDT_MEMEC 28 /* memory execute only conforming */ +#define SDT_MEMEAC 29 /* memory execute only accessed conforming */ +#define SDT_MEMERC 30 /* memory execute read conforming */ +#define SDT_MEMERAC 31 /* memory execute read accessed conforming */ + +/* is memory segment descriptor pointer ? */ +#define ISMEMSDP(s) ((s->d_type) >= SDT_MEMRO && \ + (s->d_type) <= SDT_MEMERAC) + +/* is 286 gate descriptor pointer ? */ +#define IS286GDP(s) ((s->d_type) >= SDT_SYS286CGT && \ + (s->d_type) < SDT_SYS286TGT) + +/* is 386 gate descriptor pointer ? */ +#define IS386GDP(s) ((s->d_type) >= SDT_SYS386CGT && \ + (s->d_type) < SDT_SYS386TGT) + +/* is gate descriptor pointer ? */ +#define ISGDP(s) (IS286GDP(s) || IS386GDP(s)) + +/* is segment descriptor pointer ? */ +#define ISSDP(s) (ISMEMSDP(s) || !ISGDP(s)) + +/* is system segment descriptor pointer ? */ +#define ISSYSSDP(s) (!ISMEMSDP(s) && !ISGDP(s)) + +/* + * Segment Protection Exception code bits + */ +#define SEGEX_EXT 0x01 /* recursive or externally induced */ +#define SEGEX_IDT 0x02 /* interrupt descriptor table */ +#define SEGEX_TI 0x04 /* local descriptor table */ + +/* + * Entries in the Interrupt Descriptor Table (IDT) + */ +#define NIDT 256 +#define NRSVIDT 32 /* reserved entries for cpu exceptions */ + +/* + * Entries in the Global Descriptor Table (GDT) + * The code and data descriptors must come first. There + * are NGDT_MEM of them. + * + * Then comes the predefined TSS descriptor. + * There are NGDT_SYS of them. + * + * The particular order of the UDATA and UCODE descriptors is + * required by the sysretq instruction. + */ +#define GNULL_SEL 0 /* Null descriptor */ +#define GCODE_SEL 1 /* Kernel code descriptor */ +#define GDATA_SEL 2 /* Kernel data descriptor */ +#define GUDATA_SEL 3 /* User data descriptor */ +#define GUCODE_SEL 4 /* User code descriptor */ +#define NGDT_MEM 5 + +#define GPROC0_SEL 0 /* common TSS */ +#define NGDT_SYS 1 + +#define GDT_SYS_OFFSET (NGDT_MEM << 3) + +#define GDT_ADDR_MEM(s,i) \ + ((struct mem_segment_descriptor *)((char *)(s) + ((i) << 3))) +#define GDT_ADDR_SYS(s,i) \ + ((struct sys_segment_descriptor *)((char *)(s) + ((i) << 4) + SYSSEL_START)) + +/* + * Checks for valid user selectors. + */ +#define VALID_USER_CSEL(s) \ + ((s) == GSEL(GUCODE_SEL, SEL_UPL)) +#define VALID_USER_DSEL(s) \ + ((s) == GSEL(GUDATA_SEL, SEL_UPL)) + +#endif /* _MACHINE_SEGMENTS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/setjmp.h b/lib/libc/include/x86_64-openbsd-none/machine/setjmp.h new file mode 100644 index 000000000000..88f0465d1526 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/setjmp.h @@ -0,0 +1,22 @@ +/* $OpenBSD: setjmp.h,v 1.2 2020/10/21 19:00:14 kettenis Exp $ */ +/* $NetBSD: setjmp.h,v 1.1 2003/04/26 18:39:47 fvdl Exp $ */ + +/* + * machine/setjmp.h: machine dependent setjmp-related information. + * These are only the callee-saved registers, code calling setjmp + * will expect the rest to be clobbered anyway. + */ + +#define _JB_RBX 0 +#define _JB_RBP 1 +#define _JB_R12 2 +#define _JB_R13 3 +#define _JB_R14 4 +#define _JB_R15 5 +#define _JB_RSP 6 +#define _JB_PC 7 +#define _JB_SIGFLAG 8 +#define _JB_SIGMASK 9 +#define _JB_MXCSR 10 + +#define _JBLEN 11 /* size, in longs, of a jmp_buf */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/signal.h b/lib/libc/include/x86_64-openbsd-none/machine/signal.h new file mode 100644 index 000000000000..5b19f70f3b4a --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/signal.h @@ -0,0 +1,89 @@ +/* $OpenBSD: signal.h,v 1.9 2016/05/10 18:39:42 deraadt Exp $ */ +/* $NetBSD: signal.h,v 1.2 2003/04/28 23:16:17 bjh21 Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)signal.h 7.16 (Berkeley) 3/17/91 + */ + +#ifndef _MACHINE_SIGNAL_H_ +#define _MACHINE_SIGNAL_H_ + +#include + +typedef int sig_atomic_t; + +#ifdef _KERNEL +#include +#endif + +#if __BSD_VISIBLE || __XPG_VISIBLE >= 420 +/* + * Information pushed on stack when a signal is delivered. + * This is used by the kernel to restore state following + * execution of the signal handler. It is also made available + * to the handler to allow it to restore state properly if + * a non-standard exit is performed. + */ +struct sigcontext { + /* plain match trapframe */ + long sc_rdi; + long sc_rsi; + long sc_rdx; + long sc_rcx; + long sc_r8; + long sc_r9; + long sc_r10; + long sc_r11; + long sc_r12; + long sc_r13; + long sc_r14; + long sc_r15; + long sc_rbp; + long sc_rbx; + long sc_rax; + long sc_gs; + long sc_fs; + long sc_es; + long sc_ds; + long sc_trapno; + long sc_err; + long sc_rip; + long sc_cs; + long sc_rflags; + long sc_rsp; + long sc_ss; + + struct fxsave64 *sc_fpstate; + int __sc_unused; + int sc_mask; + long sc_cookie; +}; +#endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ +#endif /* !_MACHINE_SIGNAL_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/specialreg.h b/lib/libc/include/x86_64-openbsd-none/machine/specialreg.h new file mode 100644 index 000000000000..fc0770c81d11 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/specialreg.h @@ -0,0 +1,1645 @@ +/* $OpenBSD: specialreg.h,v 1.120 2025/07/16 07:15:41 jsg Exp $ */ +/* $NetBSD: specialreg.h,v 1.1 2003/04/26 18:39:48 fvdl Exp $ */ +/* $NetBSD: x86/specialreg.h,v 1.2 2003/04/25 21:54:30 fvdl Exp $ */ + +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)specialreg.h 7.1 (Berkeley) 5/9/91 + */ + +/* + * Bits in 386 special registers: + */ +#define CR0_PE 0x00000001 /* Protected mode Enable */ +#define CR0_MP 0x00000002 /* "Math" Present (NPX or NPX emulator) */ +#define CR0_EM 0x00000004 /* EMulate non-NPX coproc. (trap ESC only) */ +#define CR0_TS 0x00000008 /* Task Switched (if MP, trap ESC and WAIT) */ +#define CR0_ET 0x00000010 /* Extension Type (387 (if set) vs 287) */ +#define CR0_PG 0x80000000 /* PaGing enable */ + +/* + * Bits in 486 special registers: + */ +#define CR0_NE 0x00000020 /* Numeric Error enable (EX16 vs IRQ13) */ +#define CR0_WP 0x00010000 /* Write Protect (honor PG_RW in all modes) */ +#define CR0_AM 0x00040000 /* Alignment Mask (set to enable AC flag) */ +#define CR0_NW 0x20000000 /* Not Write-through */ +#define CR0_CD 0x40000000 /* Cache Disable */ + +/* + * bits in CR3 + */ +#define CR3_PCID 0xfffULL +#define CR3_PWT (1ULL << 3) +#define CR3_PCD (1ULL << 4) +#define CR3_REUSE_PCID (1ULL << 63) +#define CR3_PADDR 0x7ffffffffffff000ULL + +/* + * bits in the pentiums %cr4 register: + */ + +#define CR4_VME 0x00000001 /* virtual 8086 mode extension enable */ +#define CR4_PVI 0x00000002 /* protected mode virtual interrupt enable */ +#define CR4_TSD 0x00000004 /* restrict RDTSC instruction to cpl 0 only */ +#define CR4_DE 0x00000008 /* debugging extension */ +#define CR4_PSE 0x00000010 /* large (4MB) page size enable */ +#define CR4_PAE 0x00000020 /* physical address extension enable */ +#define CR4_MCE 0x00000040 /* machine check enable */ +#define CR4_PGE 0x00000080 /* page global enable */ +#define CR4_PCE 0x00000100 /* enable RDPMC instruction for all cpls */ +#define CR4_OSFXSR 0x00000200 /* enable fxsave/fxrestor and SSE */ +#define CR4_OSXMMEXCPT 0x00000400 /* enable unmasked SSE exceptions */ +#define CR4_UMIP 0x00000800 /* user mode instruction prevention */ +#define CR4_VMXE 0x00002000 /* enable virtual machine operation */ +#define CR4_SMXE 0x00004000 /* enable safe mode operation */ +#define CR4_FSGSBASE 0x00010000 /* enable {RD,WR}{FS,GS}BASE ops */ +#define CR4_PCIDE 0x00020000 /* enable process-context IDs */ +#define CR4_OSXSAVE 0x00040000 /* enable XSAVE and extended states */ +#define CR4_KL 0x00080000 /* enable AES Key Locker */ +#define CR4_SMEP 0x00100000 /* supervisor mode exec protection */ +#define CR4_SMAP 0x00200000 /* supervisor mode access prevention */ +#define CR4_PKE 0x00400000 /* user-mode protection keys */ +#define CR4_CET 0x00800000 /* control-flow enforcement tech */ +#define CR4_PKS 0x01000000 /* supervisor-mode protection keys */ +#define CR4_UINTR 0x02000000 /* user interrupts enable bit */ + +/* + * Extended state components, for xsave/xrstor family of instructions. + */ +#define XFEATURE_X87 0x00000001 /* x87 FPU/MMX state */ +#define XFEATURE_SSE 0x00000002 /* SSE state */ +#define XFEATURE_AVX 0x00000004 /* AVX state */ +#define XFEATURE_BNDREG 0x00000008 /* MPX state */ +#define XFEATURE_BNDCSR 0x00000010 /* MPX state */ +#define XFEATURE_MPX (XFEATURE_BNDREG | XFEATURE_BNDCSR) +#define XFEATURE_OPMASK 0x00000020 /* AVX-512 opmask */ +#define XFEATURE_ZMM_HI256 0x00000040 /* AVX-512 ZMM0-7 */ +#define XFEATURE_HI16_ZMM 0x00000080 /* AVX-512 ZMM16-31 */ +#define XFEATURE_AVX512 (XFEATURE_OPMASK | XFEATURE_ZMM_HI256 | \ + XFEATURE_HI16_ZMM) +#define XFEATURE_PT 0x00000100 /* processor trace */ +#define XFEATURE_PKRU 0x00000200 /* user page key */ +#define XFEATURE_PASID 0x00000400 /* Process ASIDs */ +#define XFEATURE_CET_U 0x00000800 /* ctrl-flow enforce user */ +#define XFEATURE_CET_S 0x00001000 /* ctrl-flow enforce system */ +#define XFEATURE_CET (XFEATURE_CET_U | XFEATURE_CET_S) +#define XFEATURE_HDC 0x00002000 /* HW duty cycling */ +#define XFEATURE_UINTR 0x00004000 /* user interrupts */ +#define XFEATURE_LBR 0x00008000 /* last-branch record */ +#define XFEATURE_HWP 0x00010000 /* HW P-states */ +#define XFEATURE_TILECFG 0x00020000 /* AMX state */ +#define XFEATURE_TILEDATA 0x00040000 /* AMX state */ +#define XFEATURE_AMX (XFEATURE_TILECFG | XFEATURE_TILEDATA) + +/* valid only in xcomp_bv field: */ +#define XFEATURE_COMPRESSED (1ULL << 63) /* compressed format */ + +/* which bits are for XCR0 and which for the XSS MSR? */ +#define XFEATURE_XCR0_MASK \ + (XFEATURE_X87 | XFEATURE_SSE | XFEATURE_AVX | XFEATURE_MPX | \ + XFEATURE_AVX512 | XFEATURE_PKRU | XFEATURE_AMX) +#define XFEATURE_XSS_MASK \ + (XFEATURE_PT | XFEATURE_PASID | XFEATURE_CET | XFEATURE_HDC | \ + XFEATURE_UINTR | XFEATURE_LBR | XFEATURE_HWP) + +/* + * CPUID "features" bits (CPUID function 0x1): + * EDX bits, then ECX bits + */ + +#define CPUID_FPU 0x00000001 /* processor has an FPU? */ +#define CPUID_VME 0x00000002 /* has virtual mode (%cr4's VME/PVI) */ +#define CPUID_DE 0x00000004 /* has debugging extension */ +#define CPUID_PSE 0x00000008 /* has 4MB page size extension */ +#define CPUID_TSC 0x00000010 /* has time stamp counter */ +#define CPUID_MSR 0x00000020 /* has model specific registers */ +#define CPUID_PAE 0x00000040 /* has phys address extension */ +#define CPUID_MCE 0x00000080 /* has machine check exception */ +#define CPUID_CX8 0x00000100 /* has CMPXCHG8B instruction */ +#define CPUID_APIC 0x00000200 /* has enabled APIC */ +#define CPUID_SYS1 0x00000400 /* has SYSCALL/SYSRET inst. (Cyrix) */ +#define CPUID_SEP 0x00000800 /* has SYSCALL/SYSRET inst. (AMD/Intel) */ +#define CPUID_MTRR 0x00001000 /* has memory type range register */ +#define CPUID_PGE 0x00002000 /* has page global extension */ +#define CPUID_MCA 0x00004000 /* has machine check architecture */ +#define CPUID_CMOV 0x00008000 /* has CMOVcc instruction */ +#define CPUID_PAT 0x00010000 /* has page attribute table */ +#define CPUID_PSE36 0x00020000 /* has 36bit page size extension */ +#define CPUID_PSN 0x00040000 /* has processor serial number */ +#define CPUID_CFLUSH 0x00080000 /* CFLUSH insn supported */ +#define CPUID_B20 0x00100000 /* reserved */ +#define CPUID_DS 0x00200000 /* Debug Store */ +#define CPUID_ACPI 0x00400000 /* ACPI performance modulation regs */ +#define CPUID_MMX 0x00800000 /* has MMX instructions */ +#define CPUID_FXSR 0x01000000 /* has FXRSTOR instruction */ +#define CPUID_SSE 0x02000000 /* has streaming SIMD extensions */ +#define CPUID_SSE2 0x04000000 /* has streaming SIMD extensions #2 */ +#define CPUID_SS 0x08000000 /* self-snoop */ +#define CPUID_HTT 0x10000000 /* Hyper-Threading Technology */ +#define CPUID_TM 0x20000000 /* thermal monitor (TCC) */ +#define CPUID_B30 0x40000000 /* reserved */ +#define CPUID_PBE 0x80000000 /* Pending Break Enabled restarts clock */ +#define CPUID_EDX_BITS \ + ("\20" "\01FPU" "\02VME" "\03DE" "\04PSE" "\05TSC" "\06MSR" "\07PAE" \ + "\010MCE" "\011CX8" "\012APIC" "\014SEP" "\015MTRR" "\016PGE" "\017MCA" \ + "\020CMOV" "\021PAT" "\022PSE36" "\023PSN" "\024CFLUSH" "\026DS" \ + "\027ACPI" "\030MMX" "\031FXSR" "\032SSE" "\033SSE2" "\034SS" "\035HTT" \ + "\036TM" "\040PBE" ) + +#define CPUIDECX_SSE3 0x00000001 /* streaming SIMD extensions #3 */ +#define CPUIDECX_PCLMUL 0x00000002 /* Carryless Multiplication */ +#define CPUIDECX_DTES64 0x00000004 /* 64bit debug store */ +#define CPUIDECX_MWAIT 0x00000008 /* Monitor/Mwait */ +#define CPUIDECX_DSCPL 0x00000010 /* CPL Qualified Debug Store */ +#define CPUIDECX_VMX 0x00000020 /* Virtual Machine Extensions */ +#define CPUIDECX_SMX 0x00000040 /* Safer Mode Extensions */ +#define CPUIDECX_EST 0x00000080 /* enhanced SpeedStep */ +#define CPUIDECX_TM2 0x00000100 /* thermal monitor 2 */ +#define CPUIDECX_SSSE3 0x00000200 /* Supplemental Streaming SIMD Ext. 3 */ +#define CPUIDECX_CNXTID 0x00000400 /* Context ID */ +#define CPUIDECX_SDBG 0x00000800 /* Silicon debug capability */ +#define CPUIDECX_FMA3 0x00001000 /* Fused Multiply Add */ +#define CPUIDECX_CX16 0x00002000 /* has CMPXCHG16B instruction */ +#define CPUIDECX_XTPR 0x00004000 /* xTPR Update Control */ +#define CPUIDECX_PDCM 0x00008000 /* Perfmon and Debug Capability */ +#define CPUIDECX_PCID 0x00020000 /* Process-context ID Capability */ +#define CPUIDECX_DCA 0x00040000 /* Direct Cache Access */ +#define CPUIDECX_SSE41 0x00080000 /* Streaming SIMD Extensions 4.1 */ +#define CPUIDECX_SSE42 0x00100000 /* Streaming SIMD Extensions 4.2 */ +#define CPUIDECX_X2APIC 0x00200000 /* Extended xAPIC Support */ +#define CPUIDECX_MOVBE 0x00400000 /* MOVBE Instruction */ +#define CPUIDECX_POPCNT 0x00800000 /* POPCNT Instruction */ +#define CPUIDECX_DEADLINE 0x01000000 /* APIC one-shot via deadline */ +#define CPUIDECX_AES 0x02000000 /* AES Instruction */ +#define CPUIDECX_XSAVE 0x04000000 /* XSAVE/XSTOR States */ +#define CPUIDECX_OSXSAVE 0x08000000 /* OSXSAVE */ +#define CPUIDECX_AVX 0x10000000 /* Advanced Vector Extensions */ +#define CPUIDECX_F16C 0x20000000 /* 16bit fp conversion */ +#define CPUIDECX_RDRAND 0x40000000 /* RDRAND instruction */ +#define CPUIDECX_HV 0x80000000 /* Running on hypervisor */ +#define CPUID_ECX_BITS \ + ("\20" "\01SSE3" "\02PCLMUL" "\03DTES64" "\04MWAIT" "\05DS-CPL" "\06VMX" \ + "\07SMX" "\010EST" "\011TM2" "\012SSSE3" "\013CNXT-ID" "\014SDBG" \ + "\015FMA3" "\016CX16" "\017xTPR" "\020PDCM" "\022PCID" "\023DCA" \ + "\024SSE4.1" "\025SSE4.2" "\026x2APIC" "\027MOVBE" "\030POPCNT" \ + "\031DEADLINE" "\032AES" "\033XSAVE" "\034OSXSAVE" "\035AVX" "\036F16C" \ + "\037RDRAND" "\040HV" ) + +/* + * "Structured Extended Feature Flags Parameters" (CPUID function 0x7, leaf 0) + * EBX bits + */ +#define SEFF0EBX_FSGSBASE 0x00000001 /* {RD,WR}[FG]SBASE instructions */ +#define SEFF0EBX_TSC_ADJUST 0x00000002 /* Has IA32_TSC_ADJUST MSR */ +#define SEFF0EBX_SGX 0x00000004 /* Software Guard Extensions */ +#define SEFF0EBX_BMI1 0x00000008 /* advanced bit manipulation */ +#define SEFF0EBX_HLE 0x00000010 /* Hardware Lock Elision */ +#define SEFF0EBX_AVX2 0x00000020 /* Advanced Vector Extensions 2 */ +#define SEFF0EBX_SMEP 0x00000080 /* Supervisor mode exec protection */ +#define SEFF0EBX_BMI2 0x00000100 /* advanced bit manipulation */ +#define SEFF0EBX_ERMS 0x00000200 /* Enhanced REP MOVSB/STOSB */ +#define SEFF0EBX_INVPCID 0x00000400 /* INVPCID instruction */ +#define SEFF0EBX_RTM 0x00000800 /* Restricted Transactional Memory */ +#define SEFF0EBX_PQM 0x00001000 /* Quality of Service Monitoring */ +#define SEFF0EBX_MPX 0x00004000 /* Memory Protection Extensions */ +#define SEFF0EBX_AVX512F 0x00010000 /* AVX-512 foundation inst */ +#define SEFF0EBX_AVX512DQ 0x00020000 /* AVX-512 double/quadword */ +#define SEFF0EBX_RDSEED 0x00040000 /* RDSEED instruction */ +#define SEFF0EBX_ADX 0x00080000 /* ADCX/ADOX instructions */ +#define SEFF0EBX_SMAP 0x00100000 /* Supervisor mode access prevent */ +#define SEFF0EBX_AVX512IFMA 0x00200000 /* AVX-512 integer mult-add */ +#define SEFF0EBX_PCOMMIT 0x00400000 /* Persistent commit inst */ +#define SEFF0EBX_CLFLUSHOPT 0x00800000 /* cache line flush */ +#define SEFF0EBX_CLWB 0x01000000 /* cache line write back */ +#define SEFF0EBX_PT 0x02000000 /* Processor Trace */ +#define SEFF0EBX_AVX512PF 0x04000000 /* AVX-512 prefetch */ +#define SEFF0EBX_AVX512ER 0x08000000 /* AVX-512 exp/reciprocal */ +#define SEFF0EBX_AVX512CD 0x10000000 /* AVX-512 conflict detection */ +#define SEFF0EBX_SHA 0x20000000 /* SHA Extensions */ +#define SEFF0EBX_AVX512BW 0x40000000 /* AVX-512 byte/word inst */ +#define SEFF0EBX_AVX512VL 0x80000000 /* AVX-512 vector len inst */ +#define SEFF0_EBX_BITS \ + ("\20" "\01FSGSBASE" "\02TSC_ADJUST" "\03SGX" "\04BMI1" "\05HLE" \ + "\06AVX2" "\010SMEP" "\011BMI2" "\012ERMS" "\013INVPCID" "\014RTM" \ + "\015PQM" "\017MPX" "\021AVX512F" "\022AVX512DQ" "\023RDSEED" "\024ADX" \ + "\025SMAP" "\026AVX512IFMA" "\027PCOMMIT" "\030CLFLUSHOPT" "\031CLWB" \ + "\032PT" "\033AVX512PF" "\034AVX512ER" "\035AVX512CD" "\036SHA" \ + "\037AVX512BW" "\040AVX512VL" ) + +/* SEFF ECX bits */ +#define SEFF0ECX_PREFETCHWT1 0x00000001 /* PREFETCHWT1 instruction */ +#define SEFF0ECX_AVX512VBMI 0x00000002 /* AVX-512 vector bit inst */ +#define SEFF0ECX_UMIP 0x00000004 /* UMIP support */ +#define SEFF0ECX_PKU 0x00000008 /* Page prot keys for user mode */ +#define SEFF0ECX_OSPKE 0x00000010 /* OS enabled RD/WRPKRU */ +#define SEFF0ECX_WAITPKG 0x00000020 /* UMONITOR/UMWAIT/TPAUSE insns */ +#define SEFF0ECX_PKS 0x80000000 /* Page prot keys for sup mode */ +#define SEFF0_ECX_BITS \ + ("\20" "\01PREFETCHWT1" "\02AVX512VBMI" "\03UMIP" "\04PKU" "\06WAITPKG" \ + "\040PKS" ) + +/* SEFF EDX bits */ +#define SEFF0EDX_AVX512_4FNNIW 0x00000004 /* AVX-512 neural network insns */ +#define SEFF0EDX_AVX512_4FMAPS 0x00000008 /* AVX-512 mult accum single prec */ +#define SEFF0EDX_SRBDS_CTRL 0x00000200 /* MCU_OPT_CTRL MSR */ +#define SEFF0EDX_MD_CLEAR 0x00000400 /* Microarch Data Clear */ +#define SEFF0EDX_TSXFA 0x00002000 /* TSX Forced Abort */ +#define SEFF0EDX_IBT 0x00100000 /* Indirect Branch Tracking */ +#define SEFF0EDX_IBRS 0x04000000 /* IBRS / IBPB Speculation Control */ +#define SEFF0EDX_STIBP 0x08000000 /* STIBP Speculation Control */ +#define SEFF0EDX_L1DF 0x10000000 /* L1D_FLUSH */ +#define SEFF0EDX_ARCH_CAP 0x20000000 /* Has IA32_ARCH_CAPABILITIES MSR */ +#define SEFF0EDX_SSBD 0x80000000 /* Spec Store Bypass Disable */ +#define SEFF0_EDX_BITS \ + ("\20" "\03AVX512FNNIW" "\04AVX512FMAPS" "\012SRBDS_CTRL" "\013MD_CLEAR" \ + "\016TSXFA" "\025IBT" "\033IBRS,IBPB" "\034STIBP" "\035L1DF" "\040SSBD" ) + +/* + * Thermal and Power Management (CPUID function 0x6) EAX bits + */ +#define TPM_SENSOR 0x00000001 /* Digital temp sensor */ +#define TPM_ARAT 0x00000004 /* APIC Timer Always Running */ +#define TPM_PTS 0x00000040 /* Intel Package Thermal Status */ +#define TPM_EAX_BITS \ + ("\20" "\01SENSOR" "\03ARAT" "\07PTS") +/* Thermal and Power Management (CPUID function 0x6) ECX bits */ +#define TPM_EFFFREQ 0x00000001 /* APERF & MPERF MSR present */ +#define TPM_ECX_BITS \ + ("\20" "\01EFFFREQ" ) + + /* + * "Architectural Performance Monitoring" bits (CPUID function 0x0a): + * EAX bits, EBX bits, EDX bits. + */ + +#define CPUIDEAX_VERID 0x000000ff /* Version ID */ +#define CPUIDEAX_NUM_GC(cpuid) (((cpuid) >> 8) & 0x000000ff) +#define CPUIDEAX_BIT_GC(cpuid) (((cpuid) >> 16) & 0x000000ff) +#define CPUIDEAX_LEN_EBX(cpuid) (((cpuid) >> 24) & 0x000000ff) + +#define CPUIDEBX_EVT_CORE (1 << 0) /* Core cycle */ +#define CPUIDEBX_EVT_INST (1 << 1) /* Instruction retired */ +#define CPUIDEBX_EVT_REFR (1 << 2) /* Reference cycles */ +#define CPUIDEBX_EVT_CACHE_REF (1 << 3) /* Last-level cache ref. */ +#define CPUIDEBX_EVT_CACHE_MIS (1 << 4) /* Last-level cache miss. */ +#define CPUIDEBX_EVT_BRANCH_INST (1 << 5) /* Branch instruction ret. */ +#define CPUIDEBX_EVT_BRANCH_MISP (1 << 6) /* Branch mispredict ret. */ + +#define CPUIDEDX_NUM_FC(cpuid) (((cpuid) >> 0) & 0x0000001f) +#define CPUIDEDX_BIT_FC(cpuid) (((cpuid) >> 5) & 0x000000ff) + +/* + * CPUID "extended features" bits (CPUID function 0x80000001): + * EDX bits, then ECX bits + */ + +#define CPUID_MPC 0x00080000 /* Multiprocessing Capable */ +#define CPUID_NXE 0x00100000 /* No-Execute Extension */ +#define CPUID_MMXX 0x00400000 /* AMD MMX Extensions */ +#define CPUID_FFXSR 0x02000000 /* fast FP/MMX save/restore */ +#define CPUID_PAGE1GB 0x04000000 /* 1-GByte pages */ +#define CPUID_RDTSCP 0x08000000 /* RDTSCP / IA32_TSC_AUX available */ +#define CPUID_LONG 0x20000000 /* long mode */ +#define CPUID_3DNOW2 0x40000000 /* 3DNow! Instruction Extension */ +#define CPUID_3DNOW 0x80000000 /* 3DNow! Instructions */ +#define CPUIDE_EDX_BITS \ + ("\20" "\024MPC" "\025NXE" "\027MMXX" "\032FFXSR" "\033PAGE1GB" \ + "\034RDTSCP" "\036LONG" "\0373DNOW2" "\0403DNOW" ) + +#define CPUIDECX_LAHF 0x00000001 /* LAHF and SAHF instructions */ +#define CPUIDECX_CMPLEG 0x00000002 /* Core MP legacy mode */ +#define CPUIDECX_SVM 0x00000004 /* Secure Virtual Machine */ +#define CPUIDECX_EAPICSP 0x00000008 /* Extended APIC space */ +#define CPUIDECX_AMCR8 0x00000010 /* LOCK MOV CR0 means MOV CR8 */ +#define CPUIDECX_ABM 0x00000020 /* LZCNT instruction */ +#define CPUIDECX_SSE4A 0x00000040 /* SSE4-A instruction set */ +#define CPUIDECX_MASSE 0x00000080 /* Misaligned SSE mode */ +#define CPUIDECX_3DNOWP 0x00000100 /* 3DNowPrefetch */ +#define CPUIDECX_OSVW 0x00000200 /* OS visible workaround */ +#define CPUIDECX_IBS 0x00000400 /* Instruction based sampling */ +#define CPUIDECX_XOP 0x00000800 /* Extended operating support */ +#define CPUIDECX_SKINIT 0x00001000 /* SKINIT and STGI are supported */ +#define CPUIDECX_WDT 0x00002000 /* Watchdog timer */ +/* Reserved 0x00004000 */ +#define CPUIDECX_LWP 0x00008000 /* Lightweight profiling support */ +#define CPUIDECX_FMA4 0x00010000 /* 4-operand FMA instructions */ +#define CPUIDECX_TCE 0x00020000 /* Translation Cache Extension */ +/* Reserved 0x00040000 */ +#define CPUIDECX_NODEID 0x00080000 /* Support for MSRC001C */ +/* Reserved 0x00100000 */ +#define CPUIDECX_TBM 0x00200000 /* Trailing bit manipulation instruction */ +#define CPUIDECX_TOPEXT 0x00400000 /* Topology extensions support */ +#define CPUIDECX_CPCTR 0x00800000 /* core performance counter ext */ +#define CPUIDECX_DBKP 0x04000000 /* DataBreakpointExtension */ +#define CPUIDECX_PERFTSC 0x08000000 /* performance time-stamp counter */ +#define CPUIDECX_PCTRL3 0x10000000 /* L3 performance counter ext */ +#define CPUIDECX_MWAITX 0x20000000 /* MWAITX/MONITORX */ +#define CPUIDE_ECX_BITS \ + ("\20" "\01LAHF" "\02CMPLEG" "\03SVM" "\04EAPICSP" "\05AMCR8" "\06ABM" \ + "\07SSE4A" "\010MASSE" "\0113DNOWP" "\012OSVW" "\013IBS" "\014XOP" \ + "\015SKINIT" "\020WDT" "\021FMA4" "\022TCE" "\024NODEID" "\026TBM" \ + "\027TOPEXT" "\030CPCTR" "\033DBKP" "\034PERFTSC" "\035PCTRL3" \ + "\036MWAITX" ) + +/* + * "Advanced Power Management Information" bits (CPUID function 0x80000007): + * EDX bits. + */ +#define CPUIDEDX_HWPSTATE (1 << 7) /* Hardware P State Control */ +#define CPUIDEDX_ITSC (1 << 8) /* Invariant TSC */ +#define CPUID_APMI_EDX_BITS \ + ("\20" "\010HWPSTATE" "\011ITSC" ) + +/* + * AMD CPUID function 0x80000008 EBX bits + */ +#define CPUIDEBX_INVLPGB (1ULL << 3) /* INVLPG w/broadcast */ +#define CPUIDEBX_IBPB (1ULL << 12) /* Speculation Control IBPB */ +#define CPUIDEBX_IBRS (1ULL << 14) /* Speculation Control IBRS */ +#define CPUIDEBX_STIBP (1ULL << 15) /* Speculation Control STIBP */ +#define CPUIDEBX_IBRS_ALWAYSON (1ULL << 16) /* IBRS always on mode */ +#define CPUIDEBX_STIBP_ALWAYSON (1ULL << 17) /* STIBP always on mode */ +#define CPUIDEBX_IBRS_PREF (1ULL << 18) /* IBRS preferred */ +#define CPUIDEBX_IBRS_SAME_MODE (1ULL << 19) /* IBRS not mode-specific */ +#define CPUIDEBX_SSBD (1ULL << 24) /* Speculation Control SSBD */ +#define CPUIDEBX_VIRT_SSBD (1ULL << 25) /* Virt Spec Control SSBD */ +#define CPUIDEBX_SSBD_NOTREQ (1ULL << 26) /* SSBD not required */ +#define CPUID_AMDSPEC_EBX_BITS \ + ("\20" "\04INVLPGB" "\015IBPB" "\017IBRS" "\020STIBP" "\021IBRS_ALL" \ + "\022STIBP_ALL" "\023IBRS_PREF" "\024IBRS_SM" "\031SSBD" "\032VIRTSSBD" \ + "\033SSBDNR" ) + +/* + * AMD CPUID function 0x8000001F EAX bits + */ +#define CPUIDEAX_SME (1ULL << 0) /* SME */ +#define CPUIDEAX_SEV (1ULL << 1) /* SEV */ +#define CPUIDEAX_PFLUSH_MSR (1ULL << 2) /* Page Flush MSR */ +#define CPUIDEAX_SEVES (1ULL << 3) /* SEV-ES */ +#define CPUIDEAX_SEVSNP (1ULL << 4) /* SEV-SNP */ +#define CPUIDEAX_VMPL (1ULL << 5) /* VM Permission Levels */ +#define CPUIDEAX_RMPQUERY (1ULL << 6) /* RMPQUERY */ +#define CPUIDEAX_VMPLSSS (1ULL << 7) /* VMPL Supervisor Shadow Stack */ +#define CPUIDEAX_SECTSC (1ULL << 8) /* Secure TSC */ +#define CPUIDEAX_TSCAUXVIRT (1ULL << 9) /* TSC Aux Virtualization */ +#define CPUIDEAX_HWECACHECOH (1ULL << 10) /* Coherency Across Enc. Domains */ +#define CPUIDEAX_64BITHOST (1ULL << 11) /* SEV guest requires 64bit host */ +#define CPUIDEAX_RESTINJ (1ULL << 12) /* Restricted Injection */ +#define CPUIDEAX_ALTINJ (1ULL << 13) /* Alternate Injection */ +#define CPUIDEAX_DBGSTSW (1ULL << 14) /* Full debug state swap */ +#define CPUIDEAX_IBSDISALLOW (1ULL << 15) /* Disallowing IBS use by host */ +#define CPUIDEAX_VTE (1ULL << 16) /* Virt. Transparent Encryption */ +#define CPUIDEAX_VMGEXITPARAM (1ULL << 17) /* VMGEXIT Parameter */ +#define CPUIDEAX_VTOMMSR (1ULL << 18) /* Virtual TOM MSR */ +#define CPUIDEAX_IBSVIRT (1ULL << 19) /* IBS Virtualization for SEV-ES */ +#define CPUIDEAX_VMSARPROT (1ULL << 24) /* VMSA Register Protection */ +#define CPUIDEAX_SMTPROT (1ULL << 25) /* SMT Protection */ +#define CPUIDEAX_SVSMPAGEMSR (1ULL << 28) /* SVSM Communication Page MSR */ +#define CPUIDEAX_NVSMSR (1ULL << 29) /* NestedVirtSnpMsr */ +#define CPUID_AMDSEV_EAX_BITS \ + ("\20" "\01SME" "\02SEV" "\03PFLUSH_MSR" "\04SEVES" "\05SEVSNP" "\06VMPL" \ + "\07RMPQUERY" "\010VMPLSSS" "\011SECTSC" "\012TSCAUXVIRT" \ + "\013HWECACHECOH" "\014REQ64BITHOST" "\015RESTINJ" "\016ALTINJ" \ + "\017DBGSTSW" "\020IBSDISALLOW" "\021VTE" "\022VMGEXITPARAM" \ + "\023VTOMMSR" "\024IBSVIRT" "\031VMSARPROT" "\032SMTPROT" \ + "\035SVSMPAGEMSR" "\036NVSMSR" ) + +/* Number of encrypted guests */ +#define CPUID_AMDSEV_ECX_BITS ("\20") + +/* Minimum ASID for SEV enabled, SEV-ES disabled guest. */ +#define CPUID_AMDSEV_EDX_BITS ("\20") + +#define CPUID2FAMILY(cpuid) (((cpuid) >> 8) & 15) +#define CPUID2MODEL(cpuid) (((cpuid) >> 4) & 15) +#define CPUID2STEPPING(cpuid) ((cpuid) & 15) + +#define CPUID(code, eax, ebx, ecx, edx) \ + __asm volatile("cpuid" \ + : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \ + : "a" (code)) +#define CPUID_LEAF(code, leaf, eax, ebx, ecx, edx) \ + __asm volatile("cpuid" \ + : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \ + : "a" (code), "c" (leaf)) + + +/* + * Model-specific registers for the i386 family + */ +#define MSR_P5_MC_ADDR 0x000 /* P5 only */ +#define MSR_P5_MC_TYPE 0x001 /* P5 only */ +#define MSR_TSC 0x010 +#define MSR_CESR 0x011 /* P5 only (trap on P6) */ +#define MSR_CTR0 0x012 /* P5 only (trap on P6) */ +#define MSR_CTR1 0x013 /* P5 only (trap on P6) */ +#define MSR_PLATFORM_ID 0x017 /* Platform ID for microcode */ +#define MSR_APICBASE 0x01b +#define APICBASE_BSP 0x100 +#define APICBASE_ENABLE_X2APIC 0x400 +#define APICBASE_GLOBAL_ENABLE 0x800 +#define MSR_EBL_CR_POWERON 0x02a +#define MSR_EBC_FREQUENCY_ID 0x02c /* Pentium 4 only */ +#define MSR_TEST_CTL 0x033 +#define MSR_IA32_FEATURE_CONTROL 0x03a +#define MSR_TSC_ADJUST 0x03b +#define MSR_SPEC_CTRL 0x048 /* Speculation Control IBRS / STIBP */ +#define SPEC_CTRL_IBRS (1ULL << 0) +#define SPEC_CTRL_STIBP (1ULL << 1) +#define SPEC_CTRL_SSBD (1ULL << 2) +#define MSR_PRED_CMD 0x049 /* Speculation Control IBPB */ +#define PRED_CMD_IBPB (1ULL << 0) +#define MSR_BIOS_UPDT_TRIG 0x079 +#define MSR_BBL_CR_D0 0x088 /* PII+ only */ +#define MSR_BBL_CR_D1 0x089 /* PII+ only */ +#define MSR_BBL_CR_D2 0x08a /* PII+ only */ +#define MSR_BIOS_SIGN 0x08b +#define MSR_SMM_MONITOR_CTL 0x09b +#define MSR_SMBASE 0x09e +#define MSR_PERFCTR0 0x0c1 +#define MSR_PERFCTR1 0x0c2 +#define MSR_FSB_FREQ 0x0cd /* Core Duo/Solo only */ +#define MSR_MPERF 0x0e7 +#define MSR_APERF 0x0e8 +#define MSR_MTRRcap 0x0fe +#define MTRRcap_FIXED 0x100 /* bit 8 - fixed MTRRs supported */ +#define MTRRcap_WC 0x400 /* bit 10 - WC type supported */ +#define MTRRcap_SMRR 0x800 /* bit 11 - SMM range reg supported */ +#define MSR_ARCH_CAPABILITIES 0x10a +#define ARCH_CAP_RDCL_NO (1 << 0) /* Meltdown safe */ +#define ARCH_CAP_IBRS_ALL (1 << 1) /* enhanced IBRS */ +#define ARCH_CAP_RSBA (1 << 2) /* RSB Alternate */ +#define ARCH_CAP_SKIP_L1DFL_VMENTRY (1 << 3) +#define ARCH_CAP_SSB_NO (1 << 4) /* Spec St Byp safe */ +#define ARCH_CAP_MDS_NO (1 << 5) /* microarch data-sampling */ +#define ARCH_CAP_IF_PSCHANGE_MC_NO (1 << 6) /* PS MCE safe */ +#define ARCH_CAP_TSX_CTRL (1 << 7) /* has TSX_CTRL MSR */ +#define ARCH_CAP_TAA_NO (1 << 8) /* TSX AA safe */ +#define ARCH_CAP_MCU_CONTROL (1 << 9) /* has MCU_CTRL MSR */ +#define ARCH_CAP_MISC_PACKAGE_CTLS (1 << 10) /* has MISC_PKG_CTLS MSR */ +#define ARCH_CAP_ENERGY_FILTERING_CTL (1 << 11) /* r/w energy fltring bit */ +#define ARCH_CAP_DOITM (1 << 12) /* Data oprnd indpdnt tmng */ +#define ARCH_CAP_SBDR_SSDP_NO (1 << 13) /* SBDR/SSDP safe */ +#define ARCH_CAP_FBSDP_NO (1 << 14) /* FBSDP safe */ +#define ARCH_CAP_PSDP_NO (1 << 15) /* PSDP safe */ +#define ARCH_CAP_FB_CLEAR (1 << 17) /* MD_CLEAR covers FB */ +#define ARCH_CAP_FB_CLEAR_CTRL (1 << 18) +#define ARCH_CAP_RRSBA (1 << 19) /* has RRSBA if not dis */ +#define ARCH_CAP_BHI_NO (1 << 20) /* BHI safe */ +#define ARCH_CAP_XAPIC_DISABLE_STATUS (1 << 21) /* can disable xAPIC */ +#define ARCH_CAP_OVERCLOCKING_STATUS (1 << 23) /* has OVRCLCKNG_STAT MSR */ +#define ARCH_CAP_PBRSB_NO (1 << 24) /* PBSR safe */ +#define ARCH_CAP_GDS_CTRL (1 << 25) /* has GDS_MITG_DIS/LOCK */ +#define ARCH_CAP_GDS_NO (1 << 26) /* GDS safe */ +#define ARCH_CAP_RFDS_NO (1 << 27) /* RFDS safe */ +#define ARCH_CAP_RFDS_CLEAR (1 << 28) /* use VERW for RFDS */ +#define ARCH_CAP_MSR_BITS \ + ("\20" "\02IBRS_ALL" "\03RSBA" "\04SKIP_L1DFL" "\05SSB_NO" "\06MDS_NO" \ + "\07IF_PSCHANGE" "\010TSX_CTRL" "\011TAA_NO" "\012MCU_CONTROL" \ + "\013MISC_PKG_CT" "\014ENERGY_FILT" "\015DOITM" "\016SBDR_SSDP_N" \ + "\017FBSDP_NO" "\020PSDP_NO" "\022FB_CLEAR" "\023FB_CLEAR_CT" \ + "\024RRSBA" "\025BHI_NO" "\026XAPIC_DIS" "\030OVERCLOCK" "\031PBRSB_NO" \ + "\032GDS_CTRL" "\033GDS_NO" "\034RFDS_NO" "\035RFDS_CLEAR" ) + +#define MSR_FLUSH_CMD 0x10b +#define FLUSH_CMD_L1D_FLUSH 0x1 /* (1ULL << 0) */ +#define MSR_BBL_CR_ADDR 0x116 /* PII+ only */ +#define MSR_BBL_CR_DECC 0x118 /* PII+ only */ +#define MSR_BBL_CR_CTL 0x119 /* PII+ only */ +#define MSR_BBL_CR_TRIG 0x11a /* PII+ only */ +#define MSR_BBL_CR_BUSY 0x11b /* PII+ only */ +#define MSR_BBL_CR_CTR3 0x11e /* PII+ only */ +#define MSR_TSX_CTRL 0x122 +#define TSX_CTRL_RTM_DISABLE (1ULL << 0) +#define TSX_CTRL_TSX_CPUID_CLEAR (1ULL << 1) +#define MSR_MCU_OPT_CTRL 0x123 +#define RNGDS_MITG_DIS (1ULL << 0) +#define MSR_SYSENTER_CS 0x174 /* PII+ only */ +#define MSR_SYSENTER_ESP 0x175 /* PII+ only */ +#define MSR_SYSENTER_EIP 0x176 /* PII+ only */ +#define MSR_MCG_CAP 0x179 +#define MSR_MCG_STATUS 0x17a +#define MSR_MCG_CTL 0x17b +#define MSR_EVNTSEL0 0x186 +#define MSR_EVNTSEL1 0x187 +#define MSR_PERF_STATUS 0x198 /* Pentium M */ +#define MSR_PERF_CTL 0x199 /* Pentium M */ +#define PERF_CTL_TURBO 0x100000000ULL /* bit 32 - turbo mode */ +#define MSR_THERM_CONTROL 0x19a +#define MSR_THERM_INTERRUPT 0x19b +#define MSR_THERM_STATUS 0x19c +#define MSR_THERM_STATUS_VALID_BIT 0x80000000 +#define MSR_THERM_STATUS_TEMP(msr) ((msr >> 16) & 0x7f) +#define MSR_THERM2_CTL 0x19d /* Pentium M */ +#define MSR_MISC_ENABLE 0x1a0 +/* + * MSR_MISC_ENABLE (0x1a0) + * + * Enable Fast Strings: enables fast REP MOVS/REP STORS (R/W) + * Enable TCC: Enable automatic thermal control circuit (R/W) + * Performance monitoring available: 1 if enabled (R/O) + * Branch trace storage unavailable: 1 if unsupported (R/O) + * Processor event based sampling unavailable: 1 if unsupported (R/O) + * Enhanced Intel SpeedStep technology enable: 1 to enable (R/W) + * Enable monitor FSM: 1 to enable MONITOR/MWAIT (R/W) + * Limit CPUID maxval: 1 to limit CPUID leaf nodes to 0x2 and lower (R/W) + * Enable xTPR message disable: 1 to disable xTPR messages + * XD bit disable: 1 to disable NX capability (bit 34, or bit 2 of %edx/%rdx) + */ +#define MISC_ENABLE_FAST_STRINGS (1 << 0) +#define MISC_ENABLE_TCC (1 << 3) +#define MISC_ENABLE_PERF_MON_AVAILABLE (1 << 7) +#define MISC_ENABLE_BTS_UNAVAILABLE (1 << 11) +#define MISC_ENABLE_PEBS_UNAVAILABLE (1 << 12) +#define MISC_ENABLE_EIST_ENABLED (1 << 16) +#define MISC_ENABLE_ENABLE_MONITOR_FSM (1 << 18) +#define MISC_ENABLE_LIMIT_CPUID_MAXVAL (1 << 22) +#define MISC_ENABLE_xTPR_MESSAGE_DISABLE (1 << 23) +#define MISC_ENABLE_XD_BIT_DISABLE (1 << 2) + +/* + * for Core i Series and newer Xeons, see + * http://www.intel.com/content/dam/www/public/us/en/ + * documents/white-papers/cpu-monitoring-dts-peci-paper.pdf + */ +#define MSR_TEMPERATURE_TARGET 0x1a2 /* Core i Series, Newer Xeons */ +#define MSR_TEMPERATURE_TARGET_TJMAX(msr) (((msr) >> 16) & 0xff) +/* + * not documented anywhere, see intelcore_update_sensor() + * only available Core Duo and Core Solo Processors + */ +#define MSR_TEMPERATURE_TARGET_UNDOCUMENTED 0x0ee +#define MSR_TEMPERATURE_TARGET_LOW_BIT_UNDOCUMENTED 0x40000000 +#define MSR_DEBUGCTLMSR 0x1d9 +#define MSR_LASTBRANCHFROMIP 0x1db +#define MSR_LASTBRANCHTOIP 0x1dc +#define MSR_LASTINTFROMIP 0x1dd +#define MSR_LASTINTTOIP 0x1de +#define MSR_ROB_CR_BKUPTMPDR6 0x1e0 +#define MSR_MTRRvarBase 0x200 +#define MSR_MTRRfix64K_00000 0x250 +#define MSR_MTRRfix16K_80000 0x258 +#define MSR_MTRRfix4K_C0000 0x268 +#define MSR_CR_PAT 0x277 +#define MSR_MTRRdefType 0x2ff +#define MTRRdefType_FIXED_ENABLE 0x400 /* bit 10 - fixed MTRR enabled */ +#define MTRRdefType_ENABLE 0x800 /* bit 11 - MTRRs enabled */ +#define MSR_PERF_FIXED_CTR1 0x30a /* CPU_CLK_Unhalted.Core */ +#define MSR_PERF_FIXED_CTR2 0x30b /* CPU_CLK.Unhalted.Ref */ +#define MSR_PERF_FIXED_CTR_CTRL 0x38d +#define MSR_PERF_FIXED_CTR_FC_DIS 0x0 /* disable counter */ +#define MSR_PERF_FIXED_CTR_FC_1 0x1 /* count ring 1 */ +#define MSR_PERF_FIXED_CTR_FC_123 0x2 /* count rings 1,2,3 */ +#define MSR_PERF_FIXED_CTR_FC_ANY 0x3 /* count everything */ +#define MSR_PERF_FIXED_CTR_FC_MASK 0x3 +#define MSR_PERF_FIXED_CTR_FC(_i, _v) ((_v) << (4 * (_i))) +#define MSR_PERF_FIXED_CTR_ANYTHR(_i) (0x4 << (4 * (_i))) +#define MSR_PERF_FIXED_CTR_INT(_i) (0x8 << (4 * (_i))) +#define MSR_PERF_GLOBAL_CTRL 0x38f +#define MSR_PERF_GLOBAL_CTR1_EN (1ULL << 33) +#define MSR_PERF_GLOBAL_CTR2_EN (1ULL << 34) +#define MSR_PKG_C3_RESIDENCY 0x3f8 +#define MSR_PKG_C6_RESIDENCY 0x3f9 +#define MSR_PKG_C7_RESIDENCY 0x3fa +#define MSR_CORE_C3_RESIDENCY 0x3fc +#define MSR_CORE_C6_RESIDENCY 0x3fd +#define MSR_CORE_C7_RESIDENCY 0x3fe +#define MSR_MC0_CTL 0x400 +#define MSR_MC0_STATUS 0x401 +#define MSR_MC0_ADDR 0x402 +#define MSR_MC0_MISC 0x403 +#define MSR_MC1_CTL 0x404 +#define MSR_MC1_STATUS 0x405 +#define MSR_MC1_ADDR 0x406 +#define MSR_MC1_MISC 0x407 +#define MSR_MC2_CTL 0x408 +#define MSR_MC2_STATUS 0x409 +#define MSR_MC2_ADDR 0x40a +#define MSR_MC2_MISC 0x40b +#define MSR_MC4_CTL 0x40c +#define MSR_MC4_STATUS 0x40d +#define MSR_MC4_ADDR 0x40e +#define MSR_MC4_MISC 0x40f +#define MSR_MC3_CTL 0x410 +#define MSR_MC3_STATUS 0x411 +#define MSR_MC3_ADDR 0x412 +#define MSR_MC3_MISC 0x413 +#define MSR_PKG_C2_RESIDENCY 0x60d +#define MSR_PKG_C8_RESIDENCY 0x630 +#define MSR_PKG_C9_RESIDENCY 0x631 +#define MSR_PKG_C10_RESIDENCY 0x632 +#define MSR_U_CET 0x6a0 +#define MSR_CET_ENDBR_EN (1 << 2) +#define MSR_CET_NO_TRACK_EN (1 << 4) +#define MSR_S_CET 0x6a2 +#define MSR_PKRS 0x6e1 +#define MSR_XSS 0xda0 + +/* VIA MSR */ +#define MSR_CENT_TMTEMPERATURE 0x1423 /* Thermal monitor temperature */ + +/* + * AMD K6/K7 MSRs. + */ +#define MSR_K6_UWCCR 0xc0000085 +#define MSR_K7_EVNTSEL0 0xc0010000 +#define MSR_K7_EVNTSEL1 0xc0010001 +#define MSR_K7_EVNTSEL2 0xc0010002 +#define MSR_K7_EVNTSEL3 0xc0010003 +#define MSR_K7_PERFCTR0 0xc0010004 +#define MSR_K7_PERFCTR1 0xc0010005 +#define MSR_K7_PERFCTR2 0xc0010006 +#define MSR_K7_PERFCTR3 0xc0010007 + +/* + * AMD K8 (Opteron) MSRs. + */ +#define MSR_PATCH_LEVEL 0x0000008b +#define MSR_SYSCFG 0xc0000010 + +#define MSR_EFER 0xc0000080 /* Extended feature enable */ +#define EFER_SCE 0x00000001 /* SYSCALL extension */ +#define EFER_LME 0x00000100 /* Long Mode Enabled */ +#define EFER_LMA 0x00000400 /* Long Mode Active */ +#define EFER_NXE 0x00000800 /* No-Execute Enabled */ +#define EFER_SVME 0x00001000 /* SVM Enabled */ + +#define MSR_STAR 0xc0000081 /* 32 bit syscall gate addr */ +#define MSR_LSTAR 0xc0000082 /* 64 bit syscall gate addr */ +#define MSR_CSTAR 0xc0000083 /* compat syscall gate addr */ +#define MSR_SFMASK 0xc0000084 /* flags to clear on syscall */ + +#define MSR_FSBASE 0xc0000100 /* 64bit offset for fs: */ +#define MSR_GSBASE 0xc0000101 /* 64bit offset for gs: */ +#define MSR_KERNELGSBASE 0xc0000102 /* storage for swapgs ins */ +#define MSR_PATCH_LOADER 0xc0010020 +#define MSR_INT_PEN_MSG 0xc0010055 /* Interrupt pending message */ + +#define MSR_DE_CFG 0xc0011029 /* Decode Configuration */ +#define DE_CFG_721 0x00000001 /* errata 721 */ +#define DE_CFG_SERIALIZE_LFENCE (1 << 1) /* Enable serializing lfence */ +#define DE_CFG_SERIALIZE_9 (1 << 9) /* Zenbleed chickenbit */ + +#define IPM_C1E_CMP_HLT 0x10000000 +#define IPM_SMI_CMP_HLT 0x08000000 + +/* + * These require a 'passcode' for access. See cpufunc.h. + */ +#define MSR_HWCR 0xc0010015 +#define HWCR_FFDIS 0x00000040 +#define HWCR_TSCFREQSEL 0x01000000 + +#define MSR_PSTATEDEF(_n) (0xc0010064 + (_n)) +#define PSTATEDEF_EN 0x8000000000000000ULL + +#define MSR_NB_CFG 0xc001001f +#define NB_CFG_DISIOREQLOCK 0x0000000000000004ULL +#define NB_CFG_DISDATMSK 0x0000001000000000ULL + +#define MSR_SEV_GHCB 0xc0010130 +#define SEV_CPUID_REQ 0x00000004 +#define SEV_CPUID_RESP 0x00000005 + +#define MSR_SEV_STATUS 0xc0010131 +#define SEV_STAT_ENABLED 0x00000001 +#define SEV_STAT_ES_ENABLED 0x00000002 + +#define MSR_LS_CFG 0xc0011020 +#define LS_CFG_DIS_LS2_SQUISH 0x02000000 + +#define MSR_IC_CFG 0xc0011021 +#define IC_CFG_DIS_SEQ_PREFETCH 0x00000800 + +#define MSR_DC_CFG 0xc0011022 +#define DC_CFG_DIS_CNV_WC_SSO 0x00000004 +#define DC_CFG_DIS_SMC_CHK_BUF 0x00000400 + +#define MSR_BU_CFG 0xc0011023 +#define BU_CFG_THRL2IDXCMPDIS 0x0000080000000000ULL +#define BU_CFG_WBPFSMCCHKDIS 0x0000200000000000ULL +#define BU_CFG_WBENHWSBDIS 0x0001000000000000ULL + +/* + * Constants related to MTRRs + */ +#define MTRR_N64K 8 /* numbers of fixed-size entries */ +#define MTRR_N16K 16 +#define MTRR_N4K 64 + +/* + * the following four 3-byte registers control the non-cacheable regions. + * These registers must be written as three separate bytes. + * + * NCRx+0: A31-A24 of starting address + * NCRx+1: A23-A16 of starting address + * NCRx+2: A15-A12 of starting address | NCR_SIZE_xx. + * + * The non-cacheable region's starting address must be aligned to the + * size indicated by the NCR_SIZE_xx field. + */ +#define NCR1 0xc4 +#define NCR2 0xc7 +#define NCR3 0xca +#define NCR4 0xcd + +#define NCR_SIZE_0K 0 +#define NCR_SIZE_4K 1 +#define NCR_SIZE_8K 2 +#define NCR_SIZE_16K 3 +#define NCR_SIZE_32K 4 +#define NCR_SIZE_64K 5 +#define NCR_SIZE_128K 6 +#define NCR_SIZE_256K 7 +#define NCR_SIZE_512K 8 +#define NCR_SIZE_1M 9 +#define NCR_SIZE_2M 10 +#define NCR_SIZE_4M 11 +#define NCR_SIZE_8M 12 +#define NCR_SIZE_16M 13 +#define NCR_SIZE_32M 14 +#define NCR_SIZE_4G 15 + +/* + * Performance monitor events. + * + * Note that 586-class and 686-class CPUs have different performance + * monitors available, and they are accessed differently: + * + * 686-class: `rdpmc' instruction + * 586-class: `rdmsr' instruction, CESR MSR + * + * The descriptions of these events are too lengthy to include here. + * See Appendix A of "Intel Architecture Software Developer's + * Manual, Volume 3: System Programming" for more information. + */ + +/* + * 586-class CESR MSR format. Lower 16 bits is CTR0, upper 16 bits + * is CTR1. + */ + +#define PMC5_CESR_EVENT 0x003f +#define PMC5_CESR_OS 0x0040 +#define PMC5_CESR_USR 0x0080 +#define PMC5_CESR_E 0x0100 +#define PMC5_CESR_P 0x0200 + +#define PMC5_DATA_READ 0x00 +#define PMC5_DATA_WRITE 0x01 +#define PMC5_DATA_TLB_MISS 0x02 +#define PMC5_DATA_READ_MISS 0x03 +#define PMC5_DATA_WRITE_MISS 0x04 +#define PMC5_WRITE_M_E 0x05 +#define PMC5_DATA_LINES_WBACK 0x06 +#define PMC5_DATA_CACHE_SNOOP 0x07 +#define PMC5_DATA_CACHE_SNOOP_HIT 0x08 +#define PMC5_MEM_ACCESS_BOTH_PIPES 0x09 +#define PMC5_BANK_CONFLICTS 0x0a +#define PMC5_MISALIGNED_DATA 0x0b +#define PMC5_INST_READ 0x0c +#define PMC5_INST_TLB_MISS 0x0d +#define PMC5_INST_CACHE_MISS 0x0e +#define PMC5_SEGMENT_REG_LOAD 0x0f +#define PMC5_BRANCHES 0x12 +#define PMC5_BTB_HITS 0x13 +#define PMC5_BRANCH_TAKEN 0x14 +#define PMC5_PIPELINE_FLUSH 0x15 +#define PMC5_INST_EXECUTED 0x16 +#define PMC5_INST_EXECUTED_V_PIPE 0x17 +#define PMC5_BUS_UTILIZATION 0x18 +#define PMC5_WRITE_BACKUP_STALL 0x19 +#define PMC5_DATA_READ_STALL 0x1a +#define PMC5_WRITE_E_M_STALL 0x1b +#define PMC5_LOCKED_BUS 0x1c +#define PMC5_IO_CYCLE 0x1d +#define PMC5_NONCACHE_MEM_READ 0x1e +#define PMC5_AGI_STALL 0x1f +#define PMC5_FLOPS 0x22 +#define PMC5_BP0_MATCH 0x23 +#define PMC5_BP1_MATCH 0x24 +#define PMC5_BP2_MATCH 0x25 +#define PMC5_BP3_MATCH 0x26 +#define PMC5_HARDWARE_INTR 0x27 +#define PMC5_DATA_RW 0x28 +#define PMC5_DATA_RW_MISS 0x29 + +/* + * 686-class Event Selector MSR format. + */ + +#define PMC6_EVTSEL_EVENT 0x000000ff +#define PMC6_EVTSEL_UNIT 0x0000ff00 +#define PMC6_EVTSEL_UNIT_SHIFT 8 +#define PMC6_EVTSEL_USR (1 << 16) +#define PMC6_EVTSEL_OS (1 << 17) +#define PMC6_EVTSEL_E (1 << 18) +#define PMC6_EVTSEL_PC (1 << 19) +#define PMC6_EVTSEL_INT (1 << 20) +#define PMC6_EVTSEL_EN (1 << 22) /* PerfEvtSel0 only */ +#define PMC6_EVTSEL_INV (1 << 23) +#define PMC6_EVTSEL_COUNTER_MASK 0xff000000 +#define PMC6_EVTSEL_COUNTER_MASK_SHIFT 24 + +/* Data Cache Unit */ +#define PMC6_DATA_MEM_REFS 0x43 +#define PMC6_DCU_LINES_IN 0x45 +#define PMC6_DCU_M_LINES_IN 0x46 +#define PMC6_DCU_M_LINES_OUT 0x47 +#define PMC6_DCU_MISS_OUTSTANDING 0x48 + +/* Instruction Fetch Unit */ +#define PMC6_IFU_IFETCH 0x80 +#define PMC6_IFU_IFETCH_MISS 0x81 +#define PMC6_ITLB_MISS 0x85 +#define PMC6_IFU_MEM_STALL 0x86 +#define PMC6_ILD_STALL 0x87 + +/* L2 Cache */ +#define PMC6_L2_IFETCH 0x28 +#define PMC6_L2_LD 0x29 +#define PMC6_L2_ST 0x2a +#define PMC6_L2_LINES_IN 0x24 +#define PMC6_L2_LINES_OUT 0x26 +#define PMC6_L2_M_LINES_INM 0x25 +#define PMC6_L2_M_LINES_OUTM 0x27 +#define PMC6_L2_RQSTS 0x2e +#define PMC6_L2_ADS 0x21 +#define PMC6_L2_DBUS_BUSY 0x22 +#define PMC6_L2_DBUS_BUSY_RD 0x23 + +/* External Bus Logic */ +#define PMC6_BUS_DRDY_CLOCKS 0x62 +#define PMC6_BUS_LOCK_CLOCKS 0x63 +#define PMC6_BUS_REQ_OUTSTANDING 0x60 +#define PMC6_BUS_TRAN_BRD 0x65 +#define PMC6_BUS_TRAN_RFO 0x66 +#define PMC6_BUS_TRANS_WB 0x67 +#define PMC6_BUS_TRAN_IFETCH 0x68 +#define PMC6_BUS_TRAN_INVAL 0x69 +#define PMC6_BUS_TRAN_PWR 0x6a +#define PMC6_BUS_TRANS_P 0x6b +#define PMC6_BUS_TRANS_IO 0x6c +#define PMC6_BUS_TRAN_DEF 0x6d +#define PMC6_BUS_TRAN_BURST 0x6e +#define PMC6_BUS_TRAN_ANY 0x70 +#define PMC6_BUS_TRAN_MEM 0x6f +#define PMC6_BUS_DATA_RCV 0x64 +#define PMC6_BUS_BNR_DRV 0x61 +#define PMC6_BUS_HIT_DRV 0x7a +#define PMC6_BUS_HITM_DRDV 0x7b +#define PMC6_BUS_SNOOP_STALL 0x7e + +/* Floating Point Unit */ +#define PMC6_FLOPS 0xc1 +#define PMC6_FP_COMP_OPS_EXE 0x10 +#define PMC6_FP_ASSIST 0x11 +#define PMC6_MUL 0x12 +#define PMC6_DIV 0x12 +#define PMC6_CYCLES_DIV_BUSY 0x14 + +/* Memory Ordering */ +#define PMC6_LD_BLOCKS 0x03 +#define PMC6_SB_DRAINS 0x04 +#define PMC6_MISALIGN_MEM_REF 0x05 +#define PMC6_EMON_KNI_PREF_DISPATCHED 0x07 /* P-III only */ +#define PMC6_EMON_KNI_PREF_MISS 0x4b /* P-III only */ + +/* Instruction Decoding and Retirement */ +#define PMC6_INST_RETIRED 0xc0 +#define PMC6_UOPS_RETIRED 0xc2 +#define PMC6_INST_DECODED 0xd0 +#define PMC6_EMON_KNI_INST_RETIRED 0xd8 +#define PMC6_EMON_KNI_COMP_INST_RET 0xd9 + +/* Interrupts */ +#define PMC6_HW_INT_RX 0xc8 +#define PMC6_CYCLES_INT_MASKED 0xc6 +#define PMC6_CYCLES_INT_PENDING_AND_MASKED 0xc7 + +/* Branches */ +#define PMC6_BR_INST_RETIRED 0xc4 +#define PMC6_BR_MISS_PRED_RETIRED 0xc5 +#define PMC6_BR_TAKEN_RETIRED 0xc9 +#define PMC6_BR_MISS_PRED_TAKEN_RET 0xca +#define PMC6_BR_INST_DECODED 0xe0 +#define PMC6_BTB_MISSES 0xe2 +#define PMC6_BR_BOGUS 0xe4 +#define PMC6_BACLEARS 0xe6 + +/* Stalls */ +#define PMC6_RESOURCE_STALLS 0xa2 +#define PMC6_PARTIAL_RAT_STALLS 0xd2 + +/* Segment Register Loads */ +#define PMC6_SEGMENT_REG_LOADS 0x06 + +/* Clocks */ +#define PMC6_CPU_CLK_UNHALTED 0x79 + +/* MMX Unit */ +#define PMC6_MMX_INSTR_EXEC 0xb0 /* Celeron, P-II, P-IIX only */ +#define PMC6_MMX_SAT_INSTR_EXEC 0xb1 /* P-II and P-III only */ +#define PMC6_MMX_UOPS_EXEC 0xb2 /* P-II and P-III only */ +#define PMC6_MMX_INSTR_TYPE_EXEC 0xb3 /* P-II and P-III only */ +#define PMC6_FP_MMX_TRANS 0xcc /* P-II and P-III only */ +#define PMC6_MMX_ASSIST 0xcd /* P-II and P-III only */ +#define PMC6_MMX_INSTR_RET 0xc3 /* P-II only */ + +/* Segment Register Renaming */ +#define PMC6_SEG_RENAME_STALLS 0xd4 /* P-II and P-III only */ +#define PMC6_SEG_REG_RENAMES 0xd5 /* P-II and P-III only */ +#define PMC6_RET_SEG_RENAMES 0xd6 /* P-II and P-III only */ + +/* + * AMD K7 Event Selector MSR format. + */ + +#define K7_EVTSEL_EVENT 0x000000ff +#define K7_EVTSEL_UNIT 0x0000ff00 +#define K7_EVTSEL_UNIT_SHIFT 8 +#define K7_EVTSEL_USR (1 << 16) +#define K7_EVTSEL_OS (1 << 17) +#define K7_EVTSEL_E (1 << 18) +#define K7_EVTSEL_PC (1 << 19) +#define K7_EVTSEL_INT (1 << 20) +#define K7_EVTSEL_EN (1 << 22) +#define K7_EVTSEL_INV (1 << 23) +#define K7_EVTSEL_COUNTER_MASK 0xff000000 +#define K7_EVTSEL_COUNTER_MASK_SHIFT 24 + +/* Segment Register Loads */ +#define K7_SEGMENT_REG_LOADS 0x20 + +#define K7_STORES_TO_ACTIVE_INST_STREAM 0x21 + +/* Data Cache Unit */ +#define K7_DATA_CACHE_ACCESS 0x40 +#define K7_DATA_CACHE_MISS 0x41 +#define K7_DATA_CACHE_REFILL 0x42 +#define K7_DATA_CACHE_REFILL_SYSTEM 0x43 +#define K7_DATA_CACHE_WBACK 0x44 +#define K7_L2_DTLB_HIT 0x45 +#define K7_L2_DTLB_MISS 0x46 +#define K7_MISALIGNED_DATA_REF 0x47 +#define K7_SYSTEM_REQUEST 0x64 +#define K7_SYSTEM_REQUEST_TYPE 0x65 + +#define K7_SNOOP_HIT 0x73 +#define K7_SINGLE_BIT_ECC_ERROR 0x74 +#define K7_CACHE_LINE_INVAL 0x75 +#define K7_CYCLES_PROCESSOR_IS_RUNNING 0x76 +#define K7_L2_REQUEST 0x79 +#define K7_L2_REQUEST_BUSY 0x7a + +/* Instruction Fetch Unit */ +#define K7_IFU_IFETCH 0x80 +#define K7_IFU_IFETCH_MISS 0x81 +#define K7_IFU_REFILL_FROM_L2 0x82 +#define K7_IFU_REFILL_FROM_SYSTEM 0x83 +#define K7_ITLB_L1_MISS 0x84 +#define K7_ITLB_L2_MISS 0x85 +#define K7_SNOOP_RESYNC 0x86 +#define K7_IFU_STALL 0x87 + +#define K7_RETURN_STACK_HITS 0x88 +#define K7_RETURN_STACK_OVERFLOW 0x89 + +/* Retired */ +#define K7_RETIRED_INST 0xc0 +#define K7_RETIRED_OPS 0xc1 +#define K7_RETIRED_BRANCHES 0xc2 +#define K7_RETIRED_BRANCH_MISPREDICTED 0xc3 +#define K7_RETIRED_TAKEN_BRANCH 0xc4 +#define K7_RETIRED_TAKEN_BRANCH_MISPREDICTED 0xc5 +#define K7_RETIRED_FAR_CONTROL_TRANSFER 0xc6 +#define K7_RETIRED_RESYNC_BRANCH 0xc7 +#define K7_RETIRED_NEAR_RETURNS 0xc8 +#define K7_RETIRED_NEAR_RETURNS_MISPREDICTED 0xc9 +#define K7_RETIRED_INDIRECT_MISPREDICTED 0xca + +/* Interrupts */ +#define K7_CYCLES_INT_MASKED 0xcd +#define K7_CYCLES_INT_PENDING_AND_MASKED 0xce +#define K7_HW_INTR_RECV 0xcf + +#define K7_INSTRUCTION_DECODER_EMPTY 0xd0 +#define K7_DISPATCH_STALLS 0xd1 +#define K7_BRANCH_ABORTS_TO_RETIRE 0xd2 +#define K7_SERIALIZE 0xd3 +#define K7_SEGMENT_LOAD_STALL 0xd4 +#define K7_ICU_FULL 0xd5 +#define K7_RESERVATION_STATIONS_FULL 0xd6 +#define K7_FPU_FULL 0xd7 +#define K7_LS_FULL 0xd8 +#define K7_ALL_QUIET_STALL 0xd9 +#define K7_FAR_TRANSFER_OR_RESYNC_BRANCH_PENDING 0xda + +#define K7_BP0_MATCH 0xdc +#define K7_BP1_MATCH 0xdd +#define K7_BP2_MATCH 0xde +#define K7_BP3_MATCH 0xdf + +/* VIA C3 crypto featureset: for amd64_has_xcrypt */ +#define C3_HAS_AES 1 /* cpu has AES */ +#define C3_HAS_SHA 2 /* cpu has SHA1 & SHA256 */ +#define C3_HAS_MM 4 /* cpu has RSA instructions */ +#define C3_HAS_AESCTR 8 /* cpu has AES-CTR instructions */ + +/* Centaur Extended Feature flags */ +#define C3_CPUID_HAS_RNG 0x000004 +#define C3_CPUID_DO_RNG 0x000008 +#define C3_CPUID_HAS_ACE 0x000040 +#define C3_CPUID_DO_ACE 0x000080 +#define C3_CPUID_HAS_ACE2 0x000100 +#define C3_CPUID_DO_ACE2 0x000200 +#define C3_CPUID_HAS_PHE 0x000400 +#define C3_CPUID_DO_PHE 0x000800 +#define C3_CPUID_HAS_PMM 0x001000 +#define C3_CPUID_DO_PMM 0x002000 + +/* VIA C3 xcrypt-* instruction context control options */ +#define C3_CRYPT_CWLO_ROUND_M 0x0000000f +#define C3_CRYPT_CWLO_ALG_M 0x00000070 +#define C3_CRYPT_CWLO_ALG_AES 0x00000000 +#define C3_CRYPT_CWLO_KEYGEN_M 0x00000080 +#define C3_CRYPT_CWLO_KEYGEN_HW 0x00000000 +#define C3_CRYPT_CWLO_KEYGEN_SW 0x00000080 +#define C3_CRYPT_CWLO_NORMAL 0x00000000 +#define C3_CRYPT_CWLO_INTERMEDIATE 0x00000100 +#define C3_CRYPT_CWLO_ENCRYPT 0x00000000 +#define C3_CRYPT_CWLO_DECRYPT 0x00000200 +#define C3_CRYPT_CWLO_KEY128 0x0000000a /* 128bit, 10 rds */ +#define C3_CRYPT_CWLO_KEY192 0x0000040c /* 192bit, 12 rds */ +#define C3_CRYPT_CWLO_KEY256 0x0000080e /* 256bit, 15 rds */ + +/* Intel Silicon Debug */ +#define IA32_DEBUG_INTERFACE 0xc80 +#define IA32_DEBUG_INTERFACE_ENABLE 0x00000001 +#define IA32_DEBUG_INTERFACE_LOCK 0x40000000 +#define IA32_DEBUG_INTERFACE_MASK 0x80000000 + +/* + * VMX + */ +#define IA32_FEATURE_CONTROL_LOCK 0x01 +#define IA32_FEATURE_CONTROL_SMX_EN 0x02 +#define IA32_FEATURE_CONTROL_VMX_EN 0x04 +#define IA32_FEATURE_CONTROL_SENTER_EN (1ULL << 15) +#define IA32_FEATURE_CONTROL_SENTER_PARAM_MASK 0x7f00 +#define IA32_VMX_BASIC 0x480 +#define IA32_VMX_PINBASED_CTLS 0x481 +#define IA32_VMX_PROCBASED_CTLS 0x482 +#define IA32_VMX_EXIT_CTLS 0x483 +#define IA32_VMX_ENTRY_CTLS 0x484 +#define IA32_VMX_MISC 0x485 +#define IA32_VMX_CR0_FIXED0 0x486 +#define IA32_VMX_CR0_FIXED1 0x487 +#define IA32_VMX_CR4_FIXED0 0x488 +#define IA32_VMX_CR4_FIXED1 0x489 +#define IA32_VMX_PROCBASED2_CTLS 0x48B +#define IA32_VMX_EPT_VPID_CAP 0x48C +#define IA32_VMX_TRUE_PINBASED_CTLS 0x48D +#define IA32_VMX_TRUE_PROCBASED_CTLS 0x48E +#define IA32_VMX_TRUE_EXIT_CTLS 0x48F +#define IA32_VMX_TRUE_ENTRY_CTLS 0x490 +#define IA32_VMX_VMFUNC 0x491 + +#define IA32_EPT_VPID_CAP_XO_TRANSLATIONS (1ULL << 0) +#define IA32_EPT_VPID_CAP_PAGE_WALK_4 (1ULL << 6) +#define IA32_EPT_VPID_CAP_WB (1ULL << 14) +#define IA32_EPT_VPID_CAP_AD_BITS (1ULL << 21) +#define IA32_EPT_VPID_CAP_INVEPT_CONTEXT (1ULL << 25) +#define IA32_EPT_VPID_CAP_INVEPT_ALL (1ULL << 26) + +#define IA32_EPT_PAGING_CACHE_TYPE_UC 0x0 +#define IA32_EPT_PAGING_CACHE_TYPE_WB 0x6 +#define IA32_EPT_AD_BITS_ENABLE (1ULL << 6) +#define IA32_EPT_PAGE_WALK_LENGTH 0x4 + +/* VMX : IA32_VMX_BASIC bits */ +#define IA32_VMX_TRUE_CTLS_AVAIL (1ULL << 55) + +/* VMX : IA32_VMX_PINBASED_CTLS bits */ +#define IA32_VMX_EXTERNAL_INT_EXITING (1ULL << 0) +#define IA32_VMX_NMI_EXITING (1ULL << 3) +#define IA32_VMX_VIRTUAL_NMIS (1ULL << 5) +#define IA32_VMX_ACTIVATE_VMX_PREEMPTION_TIMER (1ULL << 6) +#define IA32_VMX_PROCESS_POSTED_INTERRUPTS (1ULL << 7) + +/* VMX : IA32_VMX_PROCBASED_CTLS bits */ +#define IA32_VMX_INTERRUPT_WINDOW_EXITING (1ULL << 2) +#define IA32_VMX_USE_TSC_OFFSETTING (1ULL << 3) +#define IA32_VMX_HLT_EXITING (1ULL << 7) +#define IA32_VMX_INVLPG_EXITING (1ULL << 9) +#define IA32_VMX_MWAIT_EXITING (1ULL << 10) +#define IA32_VMX_RDPMC_EXITING (1ULL << 11) +#define IA32_VMX_RDTSC_EXITING (1ULL << 12) +#define IA32_VMX_CR3_LOAD_EXITING (1ULL << 15) +#define IA32_VMX_CR3_STORE_EXITING (1ULL << 16) +#define IA32_VMX_CR8_LOAD_EXITING (1ULL << 19) +#define IA32_VMX_CR8_STORE_EXITING (1ULL << 20) +#define IA32_VMX_USE_TPR_SHADOW (1ULL << 21) +#define IA32_VMX_NMI_WINDOW_EXITING (1ULL << 22) +#define IA32_VMX_MOV_DR_EXITING (1ULL << 23) +#define IA32_VMX_UNCONDITIONAL_IO_EXITING (1ULL << 24) +#define IA32_VMX_USE_IO_BITMAPS (1ULL << 25) +#define IA32_VMX_MONITOR_TRAP_FLAG (1ULL << 27) +#define IA32_VMX_USE_MSR_BITMAPS (1ULL << 28) +#define IA32_VMX_MONITOR_EXITING (1ULL << 29) +#define IA32_VMX_PAUSE_EXITING (1ULL << 30) +#define IA32_VMX_ACTIVATE_SECONDARY_CONTROLS (1ULL << 31) + +/* VMX : IA32_VMX_PROCBASED2_CTLS bits */ +#define IA32_VMX_VIRTUALIZE_APIC (1ULL << 0) +#define IA32_VMX_ENABLE_EPT (1ULL << 1) +#define IA32_VMX_DESCRIPTOR_TABLE_EXITING (1ULL << 2) +#define IA32_VMX_ENABLE_RDTSCP (1ULL << 3) +#define IA32_VMX_VIRTUALIZE_X2APIC_MODE (1ULL << 4) +#define IA32_VMX_ENABLE_VPID (1ULL << 5) +#define IA32_VMX_WBINVD_EXITING (1ULL << 6) +#define IA32_VMX_UNRESTRICTED_GUEST (1ULL << 7) +#define IA32_VMX_APIC_REGISTER_VIRTUALIZATION (1ULL << 8) +#define IA32_VMX_VIRTUAL_INTERRUPT_DELIVERY (1ULL << 9) +#define IA32_VMX_PAUSE_LOOP_EXITING (1ULL << 10) +#define IA32_VMX_RDRAND_EXITING (1ULL << 11) +#define IA32_VMX_ENABLE_INVPCID (1ULL << 12) +#define IA32_VMX_ENABLE_VM_FUNCTIONS (1ULL << 13) +#define IA32_VMX_VMCS_SHADOWING (1ULL << 14) +#define IA32_VMX_ENABLE_ENCLS_EXITING (1ULL << 15) +#define IA32_VMX_RDSEED_EXITING (1ULL << 16) +#define IA32_VMX_ENABLE_PML (1ULL << 17) +#define IA32_VMX_EPT_VIOLATION_VE (1ULL << 18) +#define IA32_VMX_CONCEAL_VMX_FROM_PT (1ULL << 19) +#define IA32_VMX_ENABLE_XSAVES_XRSTORS (1ULL << 20) +#define IA32_VMX_ENABLE_TSC_SCALING (1ULL << 25) + +/* VMX : IA32_VMX_EXIT_CTLS bits */ +#define IA32_VMX_SAVE_DEBUG_CONTROLS (1ULL << 2) +#define IA32_VMX_HOST_SPACE_ADDRESS_SIZE (1ULL << 9) +#define IA32_VMX_LOAD_IA32_PERF_GLOBAL_CTRL_ON_EXIT (1ULL << 12) +#define IA32_VMX_ACKNOWLEDGE_INTERRUPT_ON_EXIT (1ULL << 15) +#define IA32_VMX_SAVE_IA32_PAT_ON_EXIT (1ULL << 18) +#define IA32_VMX_LOAD_IA32_PAT_ON_EXIT (1ULL << 19) +#define IA32_VMX_SAVE_IA32_EFER_ON_EXIT (1ULL << 20) +#define IA32_VMX_LOAD_IA32_EFER_ON_EXIT (1ULL << 21) +#define IA32_VMX_SAVE_VMX_PREEMPTION_TIMER (1ULL << 22) +#define IA32_VMX_CLEAR_IA32_BNDCFGS_ON_EXIT (1ULL << 23) +#define IA32_VMX_CONCEAL_VM_EXITS_FROM_PT (1ULL << 24) +#define IA32_VMX_LOAD_HOST_CET_STATE (1ULL << 28) + +/* VMX: IA32_VMX_ENTRY_CTLS bits */ +#define IA32_VMX_LOAD_DEBUG_CONTROLS (1ULL << 2) +#define IA32_VMX_IA32E_MODE_GUEST (1ULL << 9) +#define IA32_VMX_ENTRY_TO_SMM (1ULL << 10) +#define IA32_VMX_DEACTIVATE_DUAL_MONITOR_TREATMENT (1ULL << 11) +#define IA32_VMX_LOAD_IA32_PERF_GLOBAL_CTRL_ON_ENTRY (1ULL << 13) +#define IA32_VMX_LOAD_IA32_PAT_ON_ENTRY (1ULL << 14) +#define IA32_VMX_LOAD_IA32_EFER_ON_ENTRY (1ULL << 15) +#define IA32_VMX_LOAD_IA32_BNDCFGS_ON_ENTRY (1ULL << 16) +#define IA32_VMX_CONCEAL_VM_ENTRIES_FROM_PT (1ULL << 17) +#define IA32_VMX_LOAD_GUEST_CET_STATE (1ULL << 20) + +/* + * VMX : VMCS Fields + */ + +/* 16-bit control fields */ +#define VMCS_GUEST_VPID 0x0000 +#define VMCS_POSTED_INT_NOTIF_VECTOR 0x0002 +#define VMCS_EPTP_INDEX 0x0004 + +/* 16-bit guest state fields */ +#define VMCS_GUEST_IA32_ES_SEL 0x0800 +#define VMCS_GUEST_IA32_CS_SEL 0x0802 +#define VMCS_GUEST_IA32_SS_SEL 0x0804 +#define VMCS_GUEST_IA32_DS_SEL 0x0806 +#define VMCS_GUEST_IA32_FS_SEL 0x0808 +#define VMCS_GUEST_IA32_GS_SEL 0x080A +#define VMCS_GUEST_IA32_LDTR_SEL 0x080C +#define VMCS_GUEST_IA32_TR_SEL 0x080E +#define VMCS_GUEST_INTERRUPT_STATUS 0x0810 +#define VMCS_GUEST_PML_INDEX 0x0812 + +/* 16-bit host state fields */ +#define VMCS_HOST_IA32_ES_SEL 0x0C00 +#define VMCS_HOST_IA32_CS_SEL 0x0C02 +#define VMCS_HOST_IA32_SS_SEL 0x0C04 +#define VMCS_HOST_IA32_DS_SEL 0x0C06 +#define VMCS_HOST_IA32_FS_SEL 0x0C08 +#define VMCS_HOST_IA32_GS_SEL 0x0C0A +#define VMCS_HOST_IA32_TR_SEL 0x0C0C + +/* 64-bit control fields */ +#define VMCS_IO_BITMAP_A 0x2000 +#define VMCS_IO_BITMAP_B 0x2002 +#define VMCS_MSR_BITMAP_ADDRESS 0x2004 +#define VMCS_EXIT_STORE_MSR_ADDRESS 0x2006 +#define VMCS_EXIT_LOAD_MSR_ADDRESS 0x2008 +#define VMCS_ENTRY_LOAD_MSR_ADDRESS 0x200A +#define VMCS_EXECUTIVE_VMCS_POINTER 0x200C +#define VMCS_PML_ADDRESS 0x200E +#define VMCS_TSC_OFFSET 0x2010 +#define VMCS_VIRTUAL_APIC_ADDRESS 0x2012 +#define VMCS_APIC_ACCESS_ADDRESS 0x2014 +#define VMCS_POSTED_INTERRUPT_DESC 0x2016 +#define VMCS_VM_FUNCTION_CONTROLS 0x2018 +#define VMCS_GUEST_IA32_EPTP 0x201A +#define VMCS_EOI_EXIT_BITMAP_0 0x201C +#define VMCS_EOI_EXIT_BITMAP_1 0x201E +#define VMCS_EOI_EXIT_BITMAP_2 0x2020 +#define VMCS_EOI_EXIT_BITMAP_3 0x2022 +#define VMCS_EPTP_LIST_ADDRESS 0x2024 +#define VMCS_VMREAD_BITMAP_ADDRESS 0x2026 +#define VMCS_VMWRITE_BITMAP_ADDRESS 0x2028 +#define VMCS_VIRTUALIZATION_EXC_ADDRESS 0x202A +#define VMCS_XSS_EXITING_BITMAP 0x202C +#define VMCS_ENCLS_EXITING_BITMAP 0x202E +#define VMCS_TSC_MULTIPLIER 0x2032 + +/* 64-bit RO data field */ +#define VMCS_GUEST_PHYSICAL_ADDRESS 0x2400 + +/* 64-bit guest state fields */ +#define VMCS_LINK_POINTER 0x2800 +#define VMCS_GUEST_IA32_DEBUGCTL 0x2802 +#define VMCS_GUEST_IA32_PAT 0x2804 +#define VMCS_GUEST_IA32_EFER 0x2806 +#define VMCS_GUEST_IA32_PERF_GBL_CTRL 0x2808 +#define VMCS_GUEST_PDPTE0 0x280A +#define VMCS_GUEST_PDPTE1 0x280C +#define VMCS_GUEST_PDPTE2 0x280E +#define VMCS_GUEST_PDPTE3 0x2810 +#define VMCS_GUEST_IA32_BNDCFGS 0x2812 + +/* 64-bit host state fields */ +#define VMCS_HOST_IA32_PAT 0x2C00 +#define VMCS_HOST_IA32_EFER 0x2C02 +#define VMCS_HOST_IA32_PERF_GBL_CTRL 0x2C04 + +/* 32-bit control fields */ +#define VMCS_PINBASED_CTLS 0x4000 +#define VMCS_PROCBASED_CTLS 0x4002 +#define VMCS_EXCEPTION_BITMAP 0x4004 +#define VMCS_PF_ERROR_CODE_MASK 0x4006 +#define VMCS_PF_ERROR_CODE_MATCH 0x4008 +#define VMCS_CR3_TARGET_COUNT 0x400A +#define VMCS_EXIT_CTLS 0x400C +#define VMCS_EXIT_MSR_STORE_COUNT 0x400E +#define VMCS_EXIT_MSR_LOAD_COUNT 0x4010 +#define VMCS_ENTRY_CTLS 0x4012 +#define VMCS_ENTRY_MSR_LOAD_COUNT 0x4014 +#define VMCS_ENTRY_INTERRUPTION_INFO 0x4016 +#define VMCS_ENTRY_EXCEPTION_ERROR_CODE 0x4018 +#define VMCS_ENTRY_INSTRUCTION_LENGTH 0x401A +#define VMCS_TPR_THRESHOLD 0x401C +#define VMCS_PROCBASED2_CTLS 0x401E +#define VMCS_PLE_GAP 0x4020 +#define VMCS_PLE_WINDOW 0x4022 + +/* 32-bit RO data fields */ +#define VMCS_INSTRUCTION_ERROR 0x4400 +#define VMCS_EXIT_REASON 0x4402 +#define VMCS_EXIT_INTERRUPTION_INFO 0x4404 +#define VMCS_EXIT_INTERRUPTION_ERR_CODE 0x4406 +#define VMCS_IDT_VECTORING_INFO 0x4408 +#define VMCS_IDT_VECTORING_ERROR_CODE 0x440A +#define VMCS_INSTRUCTION_LENGTH 0x440C +#define VMCS_EXIT_INSTRUCTION_INFO 0x440E + +/* 32-bit guest state fields */ +#define VMCS_GUEST_IA32_ES_LIMIT 0x4800 +#define VMCS_GUEST_IA32_CS_LIMIT 0x4802 +#define VMCS_GUEST_IA32_SS_LIMIT 0x4804 +#define VMCS_GUEST_IA32_DS_LIMIT 0x4806 +#define VMCS_GUEST_IA32_FS_LIMIT 0x4808 +#define VMCS_GUEST_IA32_GS_LIMIT 0x480A +#define VMCS_GUEST_IA32_LDTR_LIMIT 0x480C +#define VMCS_GUEST_IA32_TR_LIMIT 0x480E +#define VMCS_GUEST_IA32_GDTR_LIMIT 0x4810 +#define VMCS_GUEST_IA32_IDTR_LIMIT 0x4812 +#define VMCS_GUEST_IA32_ES_AR 0x4814 +#define VMCS_GUEST_IA32_CS_AR 0x4816 +#define VMCS_GUEST_IA32_SS_AR 0x4818 +#define VMCS_GUEST_IA32_DS_AR 0x481A +#define VMCS_GUEST_IA32_FS_AR 0x481C +#define VMCS_GUEST_IA32_GS_AR 0x481E +#define VMCS_GUEST_IA32_LDTR_AR 0x4820 +#define VMCS_GUEST_IA32_TR_AR 0x4822 +#define VMCS_GUEST_INTERRUPTIBILITY_ST 0x4824 +#define VMCS_GUEST_ACTIVITY_STATE 0x4826 +#define VMCS_GUEST_SMBASE 0x4828 +#define VMCS_GUEST_IA32_SYSENTER_CS 0x482A +#define VMCS_VMX_PREEMPTION_TIMER_VAL 0x482E + +/* 32-bit host state field */ +#define VMCS_HOST_IA32_SYSENTER_CS 0x4C00 + +/* Natural-width control fields */ +#define VMCS_CR0_MASK 0x6000 +#define VMCS_CR4_MASK 0x6002 +#define VMCS_CR0_READ_SHADOW 0x6004 +#define VMCS_CR4_READ_SHADOW 0x6006 +#define VMCS_CR3_TARGET_0 0x6008 +#define VMCS_CR3_TARGET_1 0x600A +#define VMCS_CR3_TARGET_2 0x600C +#define VMCS_CR3_TARGET_3 0x600E + +/* Natural-width RO fields */ +#define VMCS_GUEST_EXIT_QUALIFICATION 0x6400 +#define VMCS_IO_RCX 0x6402 +#define VMCS_IO_RSI 0x6404 +#define VMCS_IO_RDI 0x6406 +#define VMCS_IO_RIP 0x6408 +#define VMCS_GUEST_LINEAR_ADDRESS 0x640A + +/* Natural-width guest state fields */ +#define VMCS_GUEST_IA32_CR0 0x6800 +#define VMCS_GUEST_IA32_CR3 0x6802 +#define VMCS_GUEST_IA32_CR4 0x6804 +#define VMCS_GUEST_IA32_ES_BASE 0x6806 +#define VMCS_GUEST_IA32_CS_BASE 0x6808 +#define VMCS_GUEST_IA32_SS_BASE 0x680A +#define VMCS_GUEST_IA32_DS_BASE 0x680C +#define VMCS_GUEST_IA32_FS_BASE 0x680E +#define VMCS_GUEST_IA32_GS_BASE 0x6810 +#define VMCS_GUEST_IA32_LDTR_BASE 0x6812 +#define VMCS_GUEST_IA32_TR_BASE 0x6814 +#define VMCS_GUEST_IA32_GDTR_BASE 0x6816 +#define VMCS_GUEST_IA32_IDTR_BASE 0x6818 +#define VMCS_GUEST_IA32_DR7 0x681A +#define VMCS_GUEST_IA32_RSP 0x681C +#define VMCS_GUEST_IA32_RIP 0x681E +#define VMCS_GUEST_IA32_RFLAGS 0x6820 +#define VMCS_GUEST_PENDING_DBG_EXC 0x6822 +#define VMCS_GUEST_IA32_SYSENTER_ESP 0x6824 +#define VMCS_GUEST_IA32_SYSENTER_EIP 0x6826 +#define VMCS_GUEST_IA32_S_CET 0x6828 + +/* Natural-width host state fields */ +#define VMCS_HOST_IA32_CR0 0x6C00 +#define VMCS_HOST_IA32_CR3 0x6C02 +#define VMCS_HOST_IA32_CR4 0x6C04 +#define VMCS_HOST_IA32_FS_BASE 0x6C06 +#define VMCS_HOST_IA32_GS_BASE 0x6C08 +#define VMCS_HOST_IA32_TR_BASE 0x6C0A +#define VMCS_HOST_IA32_GDTR_BASE 0x6C0C +#define VMCS_HOST_IA32_IDTR_BASE 0x6C0E +#define VMCS_HOST_IA32_SYSENTER_ESP 0x6C10 +#define VMCS_HOST_IA32_SYSENTER_EIP 0x6C12 +#define VMCS_HOST_IA32_RSP 0x6C14 +#define VMCS_HOST_IA32_RIP 0x6C16 +#define VMCS_HOST_IA32_S_CET 0x6C18 + +#define IA32_VMX_INVVPID_INDIV_ADDR_CTX 0x0 +#define IA32_VMX_INVVPID_SINGLE_CTX 0x1 +#define IA32_VMX_INVVPID_ALL_CTX 0x2 +#define IA32_VMX_INVVPID_SINGLE_CTX_GLB 0x3 + +#define IA32_VMX_INVEPT_SINGLE_CTX 0x1 +#define IA32_VMX_INVEPT_GLOBAL_CTX 0x2 + +#define IA32_VMX_EPT_FAULT_READ (1ULL << 0) +#define IA32_VMX_EPT_FAULT_WRITE (1ULL << 1) +#define IA32_VMX_EPT_FAULT_EXEC (1ULL << 2) + +#define IA32_VMX_EPT_FAULT_WAS_READABLE (1ULL << 3) +#define IA32_VMX_EPT_FAULT_WAS_WRITABLE (1ULL << 4) +#define IA32_VMX_EPT_FAULT_WAS_EXECABLE (1ULL << 5) + +#define IA32_VMX_MSR_LIST_SIZE_MASK (7ULL << 25) +#define IA32_VMX_CR3_TGT_SIZE_MASK (0x1FFULL << 16) + +#define VMX_SKIP_L1D_FLUSH 2 +#define VMX_L1D_FLUSH_SIZE (64 * 1024) + +/* + * SVM + */ +#define MSR_AMD_VM_CR 0xc0010114 +#define MSR_AMD_VM_HSAVE_PA 0xc0010117 +#define CPUID_AMD_SVM_CAP 0x8000000A +#define AMD_SVM_NESTED_PAGING_CAP (1 << 0) +#define AMD_SVM_VMCB_CLEAN_CAP (1 << 5) +#define AMD_SVM_FLUSH_BY_ASID_CAP (1 << 6) +#define AMD_SVM_DECODE_ASSIST_CAP (1 << 7) +#define AMD_SVMDIS 0x10 + +#define SVM_TLB_CONTROL_FLUSH_NONE 0 +#define SVM_TLB_CONTROL_FLUSH_ALL 1 +#define SVM_TLB_CONTROL_FLUSH_ASID 3 +#define SVM_TLB_CONTROL_FLUSH_ASID_GLB 7 + +#define SVM_CLEANBITS_I (1 << 0) +#define SVM_CLEANBITS_IOPM (1 << 1) +#define SVM_CLEANBITS_ASID (1 << 2) +#define SVM_CLEANBITS_TPR (1 << 3) +#define SVM_CLEANBITS_NP (1 << 4) +#define SVM_CLEANBITS_CR (1 << 5) +#define SVM_CLEANBITS_DR (1 << 6) +#define SVM_CLEANBITS_DT (1 << 7) +#define SVM_CLEANBITS_SEG (1 << 8) +#define SVM_CLEANBITS_CR2 (1 << 9) +#define SVM_CLEANBITS_LBR (1 << 10) +#define SVM_CLEANBITS_AVIC (1 << 11) + +#define SVM_CLEANBITS_ALL \ + (SVM_CLEANBITS_I | SVM_CLEANBITS_IOPM | SVM_CLEANBITS_ASID | \ + SVM_CLEANBITS_TPR | SVM_CLEANBITS_NP | SVM_CLEANBITS_CR | \ + SVM_CLEANBITS_DR | SVM_CLEANBITS_DT | SVM_CLEANBITS_SEG | \ + SVM_CLEANBITS_CR2 | SVM_CLEANBITS_LBR | SVM_CLEANBITS_AVIC ) + +#define SVM_INTR_MISC_V_IGN_TPR 0x10 + +/* + * SVM : VMCB intercepts + */ +#define SVM_INTERCEPT_CR0_READ (1UL << 0) +#define SVM_INTERCEPT_CR1_READ (1UL << 1) +#define SVM_INTERCEPT_CR2_READ (1UL << 2) +#define SVM_INTERCEPT_CR3_READ (1UL << 2) +#define SVM_INTERCEPT_CR4_READ (1UL << 4) +#define SVM_INTERCEPT_CR5_READ (1UL << 5) +#define SVM_INTERCEPT_CR6_READ (1UL << 6) +#define SVM_INTERCEPT_CR7_READ (1UL << 7) +#define SVM_INTERCEPT_CR8_READ (1UL << 8) +#define SVM_INTERCEPT_CR9_READ (1UL << 9) +#define SVM_INTERCEPT_CR10_READ (1UL << 10) +#define SVM_INTERCEPT_CR11_READ (1UL << 11) +#define SVM_INTERCEPT_CR12_READ (1UL << 12) +#define SVM_INTERCEPT_CR13_READ (1UL << 13) +#define SVM_INTERCEPT_CR14_READ (1UL << 14) +#define SVM_INTERCEPT_CR15_READ (1UL << 15) +#define SVM_INTERCEPT_CR0_WRITE (1UL << 16) +#define SVM_INTERCEPT_CR1_WRITE (1UL << 17) +#define SVM_INTERCEPT_CR2_WRITE (1UL << 18) +#define SVM_INTERCEPT_CR3_WRITE (1UL << 19) +#define SVM_INTERCEPT_CR4_WRITE (1UL << 20) +#define SVM_INTERCEPT_CR5_WRITE (1UL << 21) +#define SVM_INTERCEPT_CR6_WRITE (1UL << 22) +#define SVM_INTERCEPT_CR7_WRITE (1UL << 23) +#define SVM_INTERCEPT_CR8_WRITE (1UL << 24) +#define SVM_INTERCEPT_CR9_WRITE (1UL << 25) +#define SVM_INTERCEPT_CR10_WRITE (1UL << 26) +#define SVM_INTERCEPT_CR11_WRITE (1UL << 27) +#define SVM_INTERCEPT_CR12_WRITE (1UL << 28) +#define SVM_INTERCEPT_CR13_WRITE (1UL << 29) +#define SVM_INTERCEPT_CR14_WRITE (1UL << 30) +#define SVM_INTERCEPT_CR15_WRITE (1UL << 31) +#define SVM_INTERCEPT_DR0_READ (1UL << 0) +#define SVM_INTERCEPT_DR1_READ (1UL << 1) +#define SVM_INTERCEPT_DR2_READ (1UL << 2) +#define SVM_INTERCEPT_DR3_READ (1UL << 2) +#define SVM_INTERCEPT_DR4_READ (1UL << 4) +#define SVM_INTERCEPT_DR5_READ (1UL << 5) +#define SVM_INTERCEPT_DR6_READ (1UL << 6) +#define SVM_INTERCEPT_DR7_READ (1UL << 7) +#define SVM_INTERCEPT_DR8_READ (1UL << 8) +#define SVM_INTERCEPT_DR9_READ (1UL << 9) +#define SVM_INTERCEPT_DR10_READ (1UL << 10) +#define SVM_INTERCEPT_DR11_READ (1UL << 11) +#define SVM_INTERCEPT_DR12_READ (1UL << 12) +#define SVM_INTERCEPT_DR13_READ (1UL << 13) +#define SVM_INTERCEPT_DR14_READ (1UL << 14) +#define SVM_INTERCEPT_DR15_READ (1UL << 15) +#define SVM_INTERCEPT_DR0_WRITE (1UL << 16) +#define SVM_INTERCEPT_DR1_WRITE (1UL << 17) +#define SVM_INTERCEPT_DR2_WRITE (1UL << 18) +#define SVM_INTERCEPT_DR3_WRITE (1UL << 19) +#define SVM_INTERCEPT_DR4_WRITE (1UL << 20) +#define SVM_INTERCEPT_DR5_WRITE (1UL << 21) +#define SVM_INTERCEPT_DR6_WRITE (1UL << 22) +#define SVM_INTERCEPT_DR7_WRITE (1UL << 23) +#define SVM_INTERCEPT_DR8_WRITE (1UL << 24) +#define SVM_INTERCEPT_DR9_WRITE (1UL << 25) +#define SVM_INTERCEPT_DR10_WRITE (1UL << 26) +#define SVM_INTERCEPT_DR11_WRITE (1UL << 27) +#define SVM_INTERCEPT_DR12_WRITE (1UL << 28) +#define SVM_INTERCEPT_DR13_WRITE (1UL << 29) +#define SVM_INTERCEPT_DR14_WRITE (1UL << 30) +#define SVM_INTERCEPT_DR15_WRITE (1UL << 31) +#define SVM_INTERCEPT_INTR (1UL << 0) +#define SVM_INTERCEPT_NMI (1UL << 1) +#define SVM_INTERCEPT_SMI (1UL << 2) +#define SVM_INTERCEPT_INIT (1UL << 3) +#define SVM_INTERCEPT_VINTR (1UL << 4) +#define SVM_INTERCEPT_CR0_SEL_WRITE (1UL << 5) +#define SVM_INTERCEPT_IDTR_READ (1UL << 6) +#define SVM_INTERCEPT_GDTR_READ (1UL << 7) +#define SVM_INTERCEPT_LDTR_READ (1UL << 8) +#define SVM_INTERCEPT_TR_READ (1UL << 9) +#define SVM_INTERCEPT_IDTR_WRITE (1UL << 10) +#define SVM_INTERCEPT_GDTR_WRITE (1UL << 11) +#define SVM_INTERCEPT_LDTR_WRITE (1UL << 12) +#define SVM_INTERCEPT_TR_WRITE (1UL << 13) +#define SVM_INTERCEPT_RDTSC (1UL << 14) +#define SVM_INTERCEPT_RDPMC (1UL << 15) +#define SVM_INTERCEPT_PUSHF (1UL << 16) +#define SVM_INTERCEPT_POPF (1UL << 17) +#define SVM_INTERCEPT_CPUID (1UL << 18) +#define SVM_INTERCEPT_RSM (1UL << 19) +#define SVM_INTERCEPT_IRET (1UL << 20) +#define SVM_INTERCEPT_INTN (1UL << 21) +#define SVM_INTERCEPT_INVD (1UL << 22) +#define SVM_INTERCEPT_PAUSE (1UL << 23) +#define SVM_INTERCEPT_HLT (1UL << 24) +#define SVM_INTERCEPT_INVLPG (1UL << 25) +#define SVM_INTERCEPT_INVLPGA (1UL << 26) +#define SVM_INTERCEPT_INOUT (1UL << 27) +#define SVM_INTERCEPT_MSR (1UL << 28) +#define SVM_INTERCEPT_TASK_SWITCH (1UL << 29) +#define SVM_INTERCEPT_FERR_FREEZE (1UL << 30) +#define SVM_INTERCEPT_SHUTDOWN (1UL << 31) +#define SVM_INTERCEPT_VMRUN (1UL << 0) +#define SVM_INTERCEPT_VMMCALL (1UL << 1) +#define SVM_INTERCEPT_VMLOAD (1UL << 2) +#define SVM_INTERCEPT_VMSAVE (1UL << 3) +#define SVM_INTERCEPT_STGI (1UL << 4) +#define SVM_INTERCEPT_CLGI (1UL << 5) +#define SVM_INTERCEPT_SKINIT (1UL << 6) +#define SVM_INTERCEPT_RDTSCP (1UL << 7) +#define SVM_INTERCEPT_ICEBP (1UL << 8) +#define SVM_INTERCEPT_WBINVD (1UL << 9) +#define SVM_INTERCEPT_MONITOR (1UL << 10) +#define SVM_INTERCEPT_MWAIT_UNCOND (1UL << 11) +#define SVM_INTERCEPT_MWAIT_COND (1UL << 12) +#define SVM_INTERCEPT_XSETBV (1UL << 13) +#define SVM_INTERCEPT_EFER_WRITE (1UL << 15) +#define SVM_INTERCEPT_CR0_WRITE_POST (1UL << 16) +#define SVM_INTERCEPT_CR1_WRITE_POST (1UL << 17) +#define SVM_INTERCEPT_CR2_WRITE_POST (1UL << 18) +#define SVM_INTERCEPT_CR3_WRITE_POST (1UL << 19) +#define SVM_INTERCEPT_CR4_WRITE_POST (1UL << 20) +#define SVM_INTERCEPT_CR5_WRITE_POST (1UL << 21) +#define SVM_INTERCEPT_CR6_WRITE_POST (1UL << 22) +#define SVM_INTERCEPT_CR7_WRITE_POST (1UL << 23) +#define SVM_INTERCEPT_CR8_WRITE_POST (1UL << 24) +#define SVM_INTERCEPT_CR9_WRITE_POST (1UL << 25) +#define SVM_INTERCEPT_CR10_WRITE_POST (1UL << 26) +#define SVM_INTERCEPT_CR11_WRITE_POST (1UL << 27) +#define SVM_INTERCEPT_CR12_WRITE_POST (1UL << 28) +#define SVM_INTERCEPT_CR13_WRITE_POST (1UL << 29) +#define SVM_INTERCEPT_CR14_WRITE_POST (1UL << 30) +#define SVM_INTERCEPT_CR15_WRITE_POST (1UL << 31) + +/* + * SME and SEV + */ +#define CPUID_AMD_SEV_CAP 0x8000001F +#define AMD_SME_CAP (1UL << 0) +#define AMD_SEV_CAP (1UL << 1) + +/* + * PAT + */ +#define PATENTRY(n, type) (type << ((n) * 8)) +#define PAT_UC 0x0UL +#define PAT_WC 0x1UL +#define PAT_WT 0x4UL +#define PAT_WP 0x5UL +#define PAT_WB 0x6UL +#define PAT_UCMINUS 0x7UL + +/* + * XSAVE subfeatures (cpuid 0xd, leaf 1) + */ +#define XSAVE_XSAVEOPT 0x01UL +#define XSAVE_XSAVEC 0x02UL +#define XSAVE_XGETBV1 0x04UL +#define XSAVE_XSAVES 0x08UL +#define XSAVE_XFD 0x10UL +#define XSAVE_BITS \ + ("\20" "\01XSAVEOPT" "\02XSAVEC" "\03XGETBV1" "\04XSAVES" "\05XFD" ) + +/* + * Default cr0 and cr4 flags. + */ +#define CR0_DEFAULT (CR0_PE|CR0_PG|CR0_NE|CR0_WP) +#define CR4_DEFAULT (CR4_PAE|CR4_PGE|CR4_PSE|CR4_OSFXSR|CR4_OSXMMEXCPT) \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/sysarch.h b/lib/libc/include/x86_64-openbsd-none/machine/sysarch.h new file mode 100644 index 000000000000..aea941c71176 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/sysarch.h @@ -0,0 +1,28 @@ +/* $OpenBSD: sysarch.h,v 1.14 2018/01/07 18:54:44 guenther Exp $ */ +/* $NetBSD: sysarch.h,v 1.1 2003/04/26 18:39:48 fvdl Exp $ */ + +#ifndef _MACHINE_SYSARCH_H_ +#define _MACHINE_SYSARCH_H_ + +/* + * Architecture specific syscalls (amd64) + */ +#define AMD64_IOPL 2 + +struct amd64_iopl_args { + int iopl; +}; + +#ifdef _KERNEL +int amd64_iopl(struct proc *, void *, register_t *); +#else + +#include + +__BEGIN_DECLS +int amd64_iopl(int); +int sysarch(int, void *); +__END_DECLS +#endif + +#endif /* !_MACHINE_SYSARCH_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/tcb.h b/lib/libc/include/x86_64-openbsd-none/machine/tcb.h new file mode 100644 index 000000000000..1d7d3135dece --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/tcb.h @@ -0,0 +1,53 @@ +/* $OpenBSD: tcb.h,v 1.6 2017/10/13 05:14:02 guenther Exp $ */ + +/* + * Copyright (c) 2011 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TCB_H_ +#define _MACHINE_TCB_H_ + +#ifdef _KERNEL + +void *tcb_get(struct proc *_p); +void tcb_set(struct proc *_p, void *_newtcb); + +#define TCB_GET(p) tcb_get(p) +#define TCB_SET(p, addr) tcb_set(p, addr) + +/* address must be in canonical form; requiring lower-half is okay */ +#define TCB_INVALID(addr) ((u_long)(addr) > 0x00007fffffffffff) + +#else /* _KERNEL */ + +/* ELF TLS ABI calls for big TCB, with static TLS data at negative offsets */ +#define TLS_VARIANT 2 + +/* Read a slot from the TCB */ +static inline void * +__amd64_read_tcb(long offset) +{ + void *val; + __asm__ ("movq %%fs:(%1),%0" : "=r" (val) : "r" (offset)); + return val; +} + +/* Get a pointer to the TCB itself */ +#define TCB_GET() __amd64_read_tcb(0) + +/* Setting the TCB pointer can only be done via syscall, so no TCB_SET() */ + +#endif /* _KERNEL */ +#endif /* _MACHINE_TCB_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/timetc.h b/lib/libc/include/x86_64-openbsd-none/machine/timetc.h new file mode 100644 index 000000000000..668058407847 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/timetc.h @@ -0,0 +1,24 @@ +/* $OpenBSD: timetc.h,v 1.3 2022/09/22 04:57:08 robert Exp $ */ +/* + * Copyright (c) 2020 Paul Irofti + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TIMETC_H_ +#define _MACHINE_TIMETC_H_ + +#define TC_TSC_LFENCE 1 +#define TC_TSC_RDTSCP 2 + +#endif /* _MACHINE_TIMETC_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/trap.h b/lib/libc/include/x86_64-openbsd-none/machine/trap.h new file mode 100644 index 000000000000..f8b9fe76338d --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/trap.h @@ -0,0 +1,65 @@ +/* $OpenBSD: trap.h,v 1.6 2025/06/23 11:33:39 bluhm Exp $ */ +/* $NetBSD: trap.h,v 1.4 1994/10/27 04:16:30 cgd Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)trap.h 5.4 (Berkeley) 5/9/91 + */ + +/* + * Trap type values + * also known in trap.c for name strings + */ + +#define T_PRIVINFLT 0 /* privileged instruction */ +#define T_BPTFLT 1 /* breakpoint trap */ +#define T_ARITHTRAP 2 /* arithmetic trap */ +#define T_RESERVED 3 /* reserved fault base */ +#define T_PROTFLT 4 /* protection fault */ +#define T_TRCTRAP 5 /* trace trap */ +#define T_PAGEFLT 6 /* page fault */ +#define T_ALIGNFLT 7 /* alignment fault */ +#define T_DIVIDE 8 /* integer divide fault */ +#define T_NMI 9 /* non-maskable interrupt */ +#define T_OFLOW 10 /* overflow trap */ +#define T_BOUND 11 /* bounds check fault */ +#define T_DNA 12 /* device not available fault */ +#define T_DOUBLEFLT 13 /* double fault */ +#define T_FPOPFLT 14 /* fp coprocessor operand fetch fault (![P]Pro)*/ +#define T_TSSFLT 15 /* invalid tss fault */ +#define T_SEGNPFLT 16 /* segment not present fault */ +#define T_STKFLT 17 /* stack fault */ +#define T_MCA 18 /* machine check ([P]Pro) */ +#define T_XMM 19 /* SSE FP exception */ +#define T_VE 20 /* virtualization exception */ +#define T_CP 21 /* control protection exception */ +#define T_VC 29 /* VMM communication exception */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/tss.h b/lib/libc/include/x86_64-openbsd-none/machine/tss.h new file mode 100644 index 000000000000..e6679df97802 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/tss.h @@ -0,0 +1,62 @@ +/* $OpenBSD: tss.h,v 1.4 2011/03/23 16:54:34 pirofti Exp $ */ +/* $NetBSD: tss.h,v 1.1 2003/04/26 18:39:49 fvdl Exp $ */ + +/* + * Copyright (c) 2001 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Frank van der Linden for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_TSS_H_ +#define _MACHINE_TSS_H_ + +/* + * TSS structure. Since TSS hw switching is not supported in long + * mode, this is mainly there for the I/O permission map in + * normal processes. + */ + +struct x86_64_tss { + u_int32_t tss_reserved1; + u_int64_t tss_rsp0; + u_int64_t tss_rsp1; + u_int64_t tss_rsp2; + u_int32_t tss_reserved2; + u_int32_t tss_reserved3; + u_int64_t tss_ist[7]; + u_int32_t tss_reserved4; + u_int32_t tss_reserved5; + u_int16_t tss_reserved6; + u_int16_t tss_iobase; +} __packed; + +#endif /* _MACHINE_TSS_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/vga_post.h b/lib/libc/include/x86_64-openbsd-none/machine/vga_post.h new file mode 100644 index 000000000000..bbf947e99103 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/vga_post.h @@ -0,0 +1,43 @@ +/* $NetBSD: vga_post.h,v 1.2 2008/03/29 17:40:22 jmcneill Exp $ */ +/* $OpenBSD: vga_post.h,v 1.2 2011/03/23 16:54:34 pirofti Exp $ */ + +/*- + * Copyright (c) 2007 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_VGA_POST_H_ +#define _MACHINE_VGA_POST_H_ + +#ifdef _KERNEL +struct vga_post; + +struct vga_post *vga_post_init(int, int, int); +void vga_post_free(struct vga_post *); +void vga_post_call(struct vga_post *); +#endif +#endif \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/vmmvar.h b/lib/libc/include/x86_64-openbsd-none/machine/vmmvar.h new file mode 100644 index 000000000000..03006e307225 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/vmmvar.h @@ -0,0 +1,1075 @@ +/* $OpenBSD: vmmvar.h,v 1.117 2025/09/17 18:37:44 sf Exp $ */ +/* + * Copyright (c) 2014 Mike Larkin + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * CPU capabilities for VMM operation + */ +#ifndef _MACHINE_VMMVAR_H_ +#define _MACHINE_VMMVAR_H_ + +#ifndef _LOCORE + +#define VMM_HV_SIGNATURE "OpenBSDVMM58" + +/* VMX: Basic Exit Reasons */ +#define VMX_EXIT_NMI 0 +#define VMX_EXIT_EXTINT 1 +#define VMX_EXIT_TRIPLE_FAULT 2 +#define VMX_EXIT_INIT 3 +#define VMX_EXIT_SIPI 4 +#define VMX_EXIT_IO_SMI 5 +#define VMX_EXIT_OTHER_SMI 6 +#define VMX_EXIT_INT_WINDOW 7 +#define VMX_EXIT_NMI_WINDOW 8 +#define VMX_EXIT_TASK_SWITCH 9 +#define VMX_EXIT_CPUID 10 +#define VMX_EXIT_GETSEC 11 +#define VMX_EXIT_HLT 12 +#define VMX_EXIT_INVD 13 +#define VMX_EXIT_INVLPG 14 +#define VMX_EXIT_RDPMC 15 +#define VMX_EXIT_RDTSC 16 +#define VMX_EXIT_RSM 17 +#define VMX_EXIT_VMCALL 18 +#define VMX_EXIT_VMCLEAR 19 +#define VMX_EXIT_VMLAUNCH 20 +#define VMX_EXIT_VMPTRLD 21 +#define VMX_EXIT_VMPTRST 22 +#define VMX_EXIT_VMREAD 23 +#define VMX_EXIT_VMRESUME 24 +#define VMX_EXIT_VMWRITE 25 +#define VMX_EXIT_VMXOFF 26 +#define VMX_EXIT_VMXON 27 +#define VMX_EXIT_CR_ACCESS 28 +#define VMX_EXIT_MOV_DR 29 +#define VMX_EXIT_IO 30 +#define VMX_EXIT_RDMSR 31 +#define VMX_EXIT_WRMSR 32 +#define VMX_EXIT_ENTRY_FAILED_GUEST_STATE 33 +#define VMX_EXIT_ENTRY_FAILED_MSR_LOAD 34 +#define VMX_EXIT_MWAIT 36 +#define VMX_EXIT_MTF 37 +#define VMX_EXIT_MONITOR 39 +#define VMX_EXIT_PAUSE 40 +#define VMX_EXIT_ENTRY_FAILED_MCE 41 +#define VMX_EXIT_TPR_BELOW_THRESHOLD 43 +#define VMX_EXIT_APIC_ACCESS 44 +#define VMX_EXIT_VIRTUALIZED_EOI 45 +#define VMX_EXIT_GDTR_IDTR 46 +#define VMX_EXIT_LDTR_TR 47 +#define VMX_EXIT_EPT_VIOLATION 48 +#define VMX_EXIT_EPT_MISCONFIGURATION 49 +#define VMX_EXIT_INVEPT 50 +#define VMX_EXIT_RDTSCP 51 +#define VMX_EXIT_VMX_PREEMPTION_TIMER_EXPIRED 52 +#define VMX_EXIT_INVVPID 53 +#define VMX_EXIT_WBINVD 54 +#define VMX_EXIT_XSETBV 55 +#define VMX_EXIT_APIC_WRITE 56 +#define VMX_EXIT_RDRAND 57 +#define VMX_EXIT_INVPCID 58 +#define VMX_EXIT_VMFUNC 59 +#define VMX_EXIT_RDSEED 61 +#define VMX_EXIT_XSAVES 63 +#define VMX_EXIT_XRSTORS 64 + +#define VM_EXIT_TERMINATED 0xFFFE +#define VM_EXIT_NONE 0xFFFF + +/* + * VMX: Misc defines + */ +#define VMX_MAX_CR3_TARGETS 256 +#define VMX_VMCS_PA_CLEAR 0xFFFFFFFFFFFFFFFFUL + +#endif /* ! _LOCORE */ + +/* + * SVM: Intercept codes (exit reasons) + */ +#define SVM_VMEXIT_CR0_READ 0x00 +#define SVM_VMEXIT_CR1_READ 0x01 +#define SVM_VMEXIT_CR2_READ 0x02 +#define SVM_VMEXIT_CR3_READ 0x03 +#define SVM_VMEXIT_CR4_READ 0x04 +#define SVM_VMEXIT_CR5_READ 0x05 +#define SVM_VMEXIT_CR6_READ 0x06 +#define SVM_VMEXIT_CR7_READ 0x07 +#define SVM_VMEXIT_CR8_READ 0x08 +#define SVM_VMEXIT_CR9_READ 0x09 +#define SVM_VMEXIT_CR10_READ 0x0A +#define SVM_VMEXIT_CR11_READ 0x0B +#define SVM_VMEXIT_CR12_READ 0x0C +#define SVM_VMEXIT_CR13_READ 0x0D +#define SVM_VMEXIT_CR14_READ 0x0E +#define SVM_VMEXIT_CR15_READ 0x0F +#define SVM_VMEXIT_CR0_WRITE 0x10 +#define SVM_VMEXIT_CR1_WRITE 0x11 +#define SVM_VMEXIT_CR2_WRITE 0x12 +#define SVM_VMEXIT_CR3_WRITE 0x13 +#define SVM_VMEXIT_CR4_WRITE 0x14 +#define SVM_VMEXIT_CR5_WRITE 0x15 +#define SVM_VMEXIT_CR6_WRITE 0x16 +#define SVM_VMEXIT_CR7_WRITE 0x17 +#define SVM_VMEXIT_CR8_WRITE 0x18 +#define SVM_VMEXIT_CR9_WRITE 0x19 +#define SVM_VMEXIT_CR10_WRITE 0x1A +#define SVM_VMEXIT_CR11_WRITE 0x1B +#define SVM_VMEXIT_CR12_WRITE 0x1C +#define SVM_VMEXIT_CR13_WRITE 0x1D +#define SVM_VMEXIT_CR14_WRITE 0x1E +#define SVM_VMEXIT_CR15_WRITE 0x1F +#define SVM_VMEXIT_DR0_READ 0x20 +#define SVM_VMEXIT_DR1_READ 0x21 +#define SVM_VMEXIT_DR2_READ 0x22 +#define SVM_VMEXIT_DR3_READ 0x23 +#define SVM_VMEXIT_DR4_READ 0x24 +#define SVM_VMEXIT_DR5_READ 0x25 +#define SVM_VMEXIT_DR6_READ 0x26 +#define SVM_VMEXIT_DR7_READ 0x27 +#define SVM_VMEXIT_DR8_READ 0x28 +#define SVM_VMEXIT_DR9_READ 0x29 +#define SVM_VMEXIT_DR10_READ 0x2A +#define SVM_VMEXIT_DR11_READ 0x2B +#define SVM_VMEXIT_DR12_READ 0x2C +#define SVM_VMEXIT_DR13_READ 0x2D +#define SVM_VMEXIT_DR14_READ 0x2E +#define SVM_VMEXIT_DR15_READ 0x2F +#define SVM_VMEXIT_DR0_WRITE 0x30 +#define SVM_VMEXIT_DR1_WRITE 0x31 +#define SVM_VMEXIT_DR2_WRITE 0x32 +#define SVM_VMEXIT_DR3_WRITE 0x33 +#define SVM_VMEXIT_DR4_WRITE 0x34 +#define SVM_VMEXIT_DR5_WRITE 0x35 +#define SVM_VMEXIT_DR6_WRITE 0x36 +#define SVM_VMEXIT_DR7_WRITE 0x37 +#define SVM_VMEXIT_DR8_WRITE 0x38 +#define SVM_VMEXIT_DR9_WRITE 0x39 +#define SVM_VMEXIT_DR10_WRITE 0x3A +#define SVM_VMEXIT_DR11_WRITE 0x3B +#define SVM_VMEXIT_DR12_WRITE 0x3C +#define SVM_VMEXIT_DR13_WRITE 0x3D +#define SVM_VMEXIT_DR14_WRITE 0x3E +#define SVM_VMEXIT_DR15_WRITE 0x3F +#define SVM_VMEXIT_EXCP0 0x40 +#define SVM_VMEXIT_EXCP1 0x41 +#define SVM_VMEXIT_EXCP2 0x42 +#define SVM_VMEXIT_EXCP3 0x43 +#define SVM_VMEXIT_EXCP4 0x44 +#define SVM_VMEXIT_EXCP5 0x45 +#define SVM_VMEXIT_EXCP6 0x46 +#define SVM_VMEXIT_EXCP7 0x47 +#define SVM_VMEXIT_EXCP8 0x48 +#define SVM_VMEXIT_EXCP9 0x49 +#define SVM_VMEXIT_EXCP10 0x4A +#define SVM_VMEXIT_EXCP11 0x4B +#define SVM_VMEXIT_EXCP12 0x4C +#define SVM_VMEXIT_EXCP13 0x4D +#define SVM_VMEXIT_EXCP14 0x4E +#define SVM_VMEXIT_EXCP15 0x4F +#define SVM_VMEXIT_EXCP16 0x50 +#define SVM_VMEXIT_EXCP17 0x51 +#define SVM_VMEXIT_EXCP18 0x52 +#define SVM_VMEXIT_EXCP19 0x53 +#define SVM_VMEXIT_EXCP20 0x54 +#define SVM_VMEXIT_EXCP21 0x55 +#define SVM_VMEXIT_EXCP22 0x56 +#define SVM_VMEXIT_EXCP23 0x57 +#define SVM_VMEXIT_EXCP24 0x58 +#define SVM_VMEXIT_EXCP25 0x59 +#define SVM_VMEXIT_EXCP26 0x5A +#define SVM_VMEXIT_EXCP27 0x5B +#define SVM_VMEXIT_EXCP28 0x5C +#define SVM_VMEXIT_EXCP29 0x5D +#define SVM_VMEXIT_EXCP30 0x5E +#define SVM_VMEXIT_EXCP31 0x5F +#define SVM_VMEXIT_INTR 0x60 +#define SVM_VMEXIT_NMI 0x61 +#define SVM_VMEXIT_SMI 0x62 +#define SVM_VMEXIT_INIT 0x63 +#define SVM_VMEXIT_VINTR 0x64 +#define SVM_VMEXIT_CR0_SEL_WRITE 0x65 +#define SVM_VMEXIT_IDTR_READ 0x66 +#define SVM_VMEXIT_GDTR_READ 0x67 +#define SVM_VMEXIT_LDTR_READ 0x68 +#define SVM_VMEXIT_TR_READ 0x69 +#define SVM_VMEXIT_IDTR_WRITE 0x6A +#define SVM_VMEXIT_GDTR_WRITE 0x6B +#define SVM_VMEXIT_LDTR_WRITE 0x6C +#define SVM_VMEXIT_TR_WRITE 0x6D +#define SVM_VMEXIT_RDTSC 0x6E +#define SVM_VMEXIT_RDPMC 0x6F +#define SVM_VMEXIT_PUSHF 0x70 +#define SVM_VMEXIT_POPF 0x71 +#define SVM_VMEXIT_CPUID 0x72 +#define SVM_VMEXIT_RSM 0x73 +#define SVM_VMEXIT_IRET 0x74 +#define SVM_VMEXIT_SWINT 0x75 +#define SVM_VMEXIT_INVD 0x76 +#define SVM_VMEXIT_PAUSE 0x77 +#define SVM_VMEXIT_HLT 0x78 +#define SVM_VMEXIT_INVLPG 0x79 +#define SVM_VMEXIT_INVLPGA 0x7A +#define SVM_VMEXIT_IOIO 0x7B +#define SVM_VMEXIT_MSR 0x7C +#define SVM_VMEXIT_TASK_SWITCH 0x7D +#define SVM_VMEXIT_FERR_FREEZE 0x7E +#define SVM_VMEXIT_SHUTDOWN 0x7F +#define SVM_VMEXIT_VMRUN 0x80 +#define SVM_VMEXIT_VMMCALL 0x81 +#define SVM_VMEXIT_VMLOAD 0x82 +#define SVM_VMEXIT_VMSAVE 0x83 +#define SVM_VMEXIT_STGI 0x84 +#define SVM_VMEXIT_CLGI 0x85 +#define SVM_VMEXIT_SKINIT 0x86 +#define SVM_VMEXIT_RDTSCP 0x87 +#define SVM_VMEXIT_ICEBP 0x88 +#define SVM_VMEXIT_WBINVD 0x89 +#define SVM_VMEXIT_MONITOR 0x8A +#define SVM_VMEXIT_MWAIT 0x8B +#define SVM_VMEXIT_MWAIT_CONDITIONAL 0x8C +#define SVM_VMEXIT_XSETBV 0x8D +#define SVM_VMEXIT_EFER_WRITE_TRAP 0x8F +#define SVM_VMEXIT_CR0_WRITE_TRAP 0x90 +#define SVM_VMEXIT_CR1_WRITE_TRAP 0x91 +#define SVM_VMEXIT_CR2_WRITE_TRAP 0x92 +#define SVM_VMEXIT_CR3_WRITE_TRAP 0x93 +#define SVM_VMEXIT_CR4_WRITE_TRAP 0x94 +#define SVM_VMEXIT_CR5_WRITE_TRAP 0x95 +#define SVM_VMEXIT_CR6_WRITE_TRAP 0x96 +#define SVM_VMEXIT_CR7_WRITE_TRAP 0x97 +#define SVM_VMEXIT_CR8_WRITE_TRAP 0x98 +#define SVM_VMEXIT_CR9_WRITE_TRAP 0x99 +#define SVM_VMEXIT_CR10_WRITE_TRAP 0x9A +#define SVM_VMEXIT_CR11_WRITE_TRAP 0x9B +#define SVM_VMEXIT_CR12_WRITE_TRAP 0x9C +#define SVM_VMEXIT_CR13_WRITE_TRAP 0x9D +#define SVM_VMEXIT_CR14_WRITE_TRAP 0x9E +#define SVM_VMEXIT_CR15_WRITE_TRAP 0x9F +#define SVM_VMEXIT_NPF 0x400 +#define SVM_AVIC_INCOMPLETE_IPI 0x401 +#define SVM_AVIC_NOACCEL 0x402 +#define SVM_VMEXIT_VMGEXIT 0x403 +#define SVM_VMEXIT_INVALID -1 + +/* + * Additional VMEXIT codes used in SEV-ES/SNP in the GHCB + */ +#define SEV_VMGEXIT_MMIO_READ 0x80000001 +#define SEV_VMGEXIT_MMIO_WRITE 0x80000002 + +#ifndef _LOCORE + +/* + * Exception injection vectors (these correspond to the CPU exception types + * defined in the SDM.) + */ +#define VMM_EX_DE 0 /* Divide Error #DE */ +#define VMM_EX_DB 1 /* Debug Exception #DB */ +#define VMM_EX_NMI 2 /* NMI */ +#define VMM_EX_BP 3 /* Breakpoint #BP */ +#define VMM_EX_OF 4 /* Overflow #OF */ +#define VMM_EX_BR 5 /* Bound range exceeded #BR */ +#define VMM_EX_UD 6 /* Undefined opcode #UD */ +#define VMM_EX_NM 7 /* Device not available #NM */ +#define VMM_EX_DF 8 /* Double fault #DF */ +#define VMM_EX_CP 9 /* Coprocessor segment overrun (unused) */ +#define VMM_EX_TS 10 /* Invalid TSS #TS */ +#define VMM_EX_NP 11 /* Segment not present #NP */ +#define VMM_EX_SS 12 /* Stack segment fault #SS */ +#define VMM_EX_GP 13 /* General protection #GP */ +#define VMM_EX_PF 14 /* Page fault #PF */ +#define VMM_EX_MF 16 /* x87 FPU floating point error #MF */ +#define VMM_EX_AC 17 /* Alignment check #AC */ +#define VMM_EX_MC 18 /* Machine check #MC */ +#define VMM_EX_XM 19 /* SIMD floating point exception #XM */ +#define VMM_EX_VE 20 /* Virtualization exception #VE */ + +enum { + VEI_DIR_OUT, + VEI_DIR_IN +}; + +enum { + VEE_FAULT_INVALID = 0, + VEE_FAULT_HANDLED, + VEE_FAULT_MMIO_ASSIST, + VEE_FAULT_PROTECT, +}; + +enum { + VMM_CPU_MODE_REAL, + VMM_CPU_MODE_PROT, + VMM_CPU_MODE_PROT32, + VMM_CPU_MODE_COMPAT, + VMM_CPU_MODE_LONG, + VMM_CPU_MODE_UNKNOWN, +}; + +struct vmm_softc_md { + /* Capabilities */ + uint32_t nr_rvi_cpus; /* [I] */ + uint32_t nr_ept_cpus; /* [I] */ + uint8_t pkru_enabled; /* [I] */ +}; + +/* + * vm exit data + * vm_exit_inout : describes an IN/OUT exit + */ +struct vm_exit_inout { + uint8_t vei_size; /* Size of access */ + uint8_t vei_dir; /* Direction */ + uint8_t vei_rep; /* REP prefix? */ + uint8_t vei_string; /* string variety? */ + uint8_t vei_encoding; /* operand encoding */ + uint16_t vei_port; /* port */ + uint32_t vei_data; /* data */ + uint8_t vei_insn_len; /* Count of instruction bytes */ +}; + +/* + * vm_exit_eptviolation : describes an EPT VIOLATION exit + */ +struct vm_exit_eptviolation { + uint8_t vee_fault_type; /* type of vm exit */ + uint8_t vee_insn_info; /* bitfield */ +#define VEE_LEN_VALID 0x1 /* vee_insn_len is valid */ +#define VEE_BYTES_VALID 0x2 /* vee_insn_bytes is valid */ + uint8_t vee_insn_len; /* [VMX] instruction length */ + uint8_t vee_insn_bytes[15]; /* [SVM] bytes at {R,E,}IP */ +}; + +/* + * struct vcpu_inject_event : describes an exception or interrupt to inject. + */ +struct vcpu_inject_event { + uint8_t vie_vector; /* Exception or interrupt vector. */ + uint32_t vie_errorcode; /* Optional error code. */ + uint8_t vie_type; +#define VCPU_INJECT_NONE 0 +#define VCPU_INJECT_INTR 1 /* External hardware interrupt. */ +#define VCPU_INJECT_EX 2 /* HW or SW Exception */ +#define VCPU_INJECT_NMI 3 /* Non-maskable Interrupt */ +}; + +/* + * struct vcpu_segment_info + * + * Describes a segment + selector set, used in constructing the initial vcpu + * register content + */ +struct vcpu_segment_info { + uint16_t vsi_sel; + uint32_t vsi_limit; + uint32_t vsi_ar; + uint64_t vsi_base; +}; + +/* The GPRS are ordered to assist instruction decode. */ +#define VCPU_REGS_RAX 0 +#define VCPU_REGS_RCX 1 +#define VCPU_REGS_RDX 2 +#define VCPU_REGS_RBX 3 +#define VCPU_REGS_RSP 4 +#define VCPU_REGS_RBP 5 +#define VCPU_REGS_RSI 6 +#define VCPU_REGS_RDI 7 +#define VCPU_REGS_R8 8 +#define VCPU_REGS_R9 9 +#define VCPU_REGS_R10 10 +#define VCPU_REGS_R11 11 +#define VCPU_REGS_R12 12 +#define VCPU_REGS_R13 13 +#define VCPU_REGS_R14 14 +#define VCPU_REGS_R15 15 +#define VCPU_REGS_RIP 16 +#define VCPU_REGS_RFLAGS 17 +#define VCPU_REGS_NGPRS (VCPU_REGS_RFLAGS + 1) + +#define VCPU_REGS_CR0 0 +#define VCPU_REGS_CR2 1 +#define VCPU_REGS_CR3 2 +#define VCPU_REGS_CR4 3 +#define VCPU_REGS_CR8 4 +#define VCPU_REGS_XCR0 5 +#define VCPU_REGS_PDPTE0 6 +#define VCPU_REGS_PDPTE1 7 +#define VCPU_REGS_PDPTE2 8 +#define VCPU_REGS_PDPTE3 9 +#define VCPU_REGS_NCRS (VCPU_REGS_PDPTE3 + 1) + +#define VCPU_REGS_ES 0 +#define VCPU_REGS_CS 1 +#define VCPU_REGS_SS 2 +#define VCPU_REGS_DS 3 +#define VCPU_REGS_FS 4 +#define VCPU_REGS_GS 5 +#define VCPU_REGS_LDTR 6 +#define VCPU_REGS_TR 7 +#define VCPU_REGS_NSREGS (VCPU_REGS_TR + 1) + +#define VCPU_REGS_EFER 0 +#define VCPU_REGS_STAR 1 +#define VCPU_REGS_LSTAR 2 +#define VCPU_REGS_CSTAR 3 +#define VCPU_REGS_SFMASK 4 +#define VCPU_REGS_KGSBASE 5 +#define VCPU_REGS_MISC_ENABLE 6 +#define VCPU_REGS_NMSRS (VCPU_REGS_MISC_ENABLE + 1) + +#define VCPU_REGS_DR0 0 +#define VCPU_REGS_DR1 1 +#define VCPU_REGS_DR2 2 +#define VCPU_REGS_DR3 3 +#define VCPU_REGS_DR6 4 +#define VCPU_REGS_DR7 5 +#define VCPU_REGS_NDRS (VCPU_REGS_DR7 + 1) + +struct vcpu_reg_state { + uint64_t vrs_gprs[VCPU_REGS_NGPRS]; + uint64_t vrs_crs[VCPU_REGS_NCRS]; + uint64_t vrs_msrs[VCPU_REGS_NMSRS]; + uint64_t vrs_drs[VCPU_REGS_NDRS]; + struct vcpu_segment_info vrs_sregs[VCPU_REGS_NSREGS]; + struct vcpu_segment_info vrs_gdtr; + struct vcpu_segment_info vrs_idtr; +}; + +#define VCPU_HOST_REGS_EFER 0 +#define VCPU_HOST_REGS_STAR 1 +#define VCPU_HOST_REGS_LSTAR 2 +#define VCPU_HOST_REGS_CSTAR 3 +#define VCPU_HOST_REGS_SFMASK 4 +#define VCPU_HOST_REGS_KGSBASE 5 +#define VCPU_HOST_REGS_MISC_ENABLE 6 +#define VCPU_HOST_REGS_NMSRS (VCPU_HOST_REGS_MISC_ENABLE + 1) + +/* + * struct vm_exit + * + * Contains VM exit information communicated to vmd(8). This information is + * gathered by vmm(4) from the CPU on each exit that requires help from vmd. + */ +struct vm_exit { + union { + struct vm_exit_inout vei; /* IN/OUT exit */ + struct vm_exit_eptviolation vee; /* EPT VIOLATION exit*/ + }; + + struct vcpu_reg_state vrs; + int cpl; +}; + +struct vm_intr_params { + /* Input parameters to VMM_IOC_INTR */ + uint32_t vip_vm_id; + uint32_t vip_vcpu_id; + uint16_t vip_intr; +}; + +#define VM_RWREGS_GPRS 0x1 /* read/write GPRs */ +#define VM_RWREGS_SREGS 0x2 /* read/write segment registers */ +#define VM_RWREGS_CRS 0x4 /* read/write CRs */ +#define VM_RWREGS_MSRS 0x8 /* read/write MSRs */ +#define VM_RWREGS_DRS 0x10 /* read/write DRs */ +#define VM_RWREGS_ALL (VM_RWREGS_GPRS | VM_RWREGS_SREGS | VM_RWREGS_CRS | \ + VM_RWREGS_MSRS | VM_RWREGS_DRS) + +struct vm_rwregs_params { + /* + * Input/output parameters to VMM_IOC_READREGS / + * VMM_IOC_WRITEREGS + */ + uint32_t vrwp_vm_id; + uint32_t vrwp_vcpu_id; + uint64_t vrwp_mask; + struct vcpu_reg_state vrwp_regs; +}; + +/* IOCTL definitions */ +#define VMM_IOC_INTR _IOW('V', 6, struct vm_intr_params) /* Intr pending */ + +/* CPUID masks */ +/* + * clone host capabilities minus: + * debug store (CPUIDECX_DTES64, CPUIDECX_DSCPL, CPUID_DS) + * monitor/mwait (CPUIDECX_MWAIT, CPUIDECX_MWAITX) + * vmx/svm (CPUIDECX_VMX, CPUIDECX_SVM) + * smx (CPUIDECX_SMX) + * speedstep (CPUIDECX_EST) + * thermal (CPUIDECX_TM2, CPUID_ACPI, CPUID_TM) + * context id (CPUIDECX_CNXTID) + * machine check (CPUID_MCE, CPUID_MCA) + * silicon debug (CPUIDECX_SDBG) + * xTPR (CPUIDECX_XTPR) + * perf/debug (CPUIDECX_PDCM) + * pcid (CPUIDECX_PCID) + * direct cache access (CPUIDECX_DCA) + * x2APIC (CPUIDECX_X2APIC) + * apic deadline (CPUIDECX_DEADLINE) + * apic (CPUID_APIC) + * psn (CPUID_PSN) + * self snoop (CPUID_SS) + * hyperthreading (CPUID_HTT) + * pending break enabled (CPUID_PBE) + * MTRR (CPUID_MTRR) + * Speculative execution control features (AMD) + */ +#define VMM_CPUIDECX_MASK ~(CPUIDECX_EST | CPUIDECX_TM2 | CPUIDECX_MWAIT | \ + CPUIDECX_PDCM | CPUIDECX_VMX | CPUIDECX_DTES64 | \ + CPUIDECX_DSCPL | CPUIDECX_SMX | CPUIDECX_CNXTID | \ + CPUIDECX_SDBG | CPUIDECX_XTPR | CPUIDECX_PCID | \ + CPUIDECX_DCA | CPUIDECX_X2APIC | CPUIDECX_DEADLINE) +#define VMM_ECPUIDECX_MASK ~(CPUIDECX_SVM | CPUIDECX_MWAITX) +#define VMM_CPUIDEDX_MASK ~(CPUID_ACPI | CPUID_TM | \ + CPUID_HTT | CPUID_DS | CPUID_APIC | \ + CPUID_PSN | CPUID_SS | CPUID_PBE | \ + CPUID_MTRR | CPUID_MCE | CPUID_MCA) +#define VMM_AMDSPEC_EBX_MASK ~(CPUIDEBX_IBPB | CPUIDEBX_IBRS | \ + CPUIDEBX_STIBP | CPUIDEBX_IBRS_ALWAYSON | CPUIDEBX_STIBP_ALWAYSON | \ + CPUIDEBX_IBRS_PREF | CPUIDEBX_SSBD | CPUIDEBX_VIRT_SSBD | \ + CPUIDEBX_SSBD_NOTREQ) + +/* This mask is an include list for bits we want to expose */ +#define VMM_APMI_EDX_INCLUDE_MASK (CPUIDEDX_ITSC) + +/* + * SEFF flags - copy from host minus: + * TSC_ADJUST (SEFF0EBX_TSC_ADJUST) + * SGX (SEFF0EBX_SGX) + * HLE (SEFF0EBX_HLE) + * INVPCID (SEFF0EBX_INVPCID) + * RTM (SEFF0EBX_RTM) + * PQM (SEFF0EBX_PQM) + * AVX512F (SEFF0EBX_AVX512F) + * AVX512DQ (SEFF0EBX_AVX512DQ) + * AVX512IFMA (SEFF0EBX_AVX512IFMA) + * AVX512PF (SEFF0EBX_AVX512PF) + * AVX512ER (SEFF0EBX_AVX512ER) + * AVX512CD (SEFF0EBX_AVX512CD) + * AVX512BW (SEFF0EBX_AVX512BW) + * AVX512VL (SEFF0EBX_AVX512VL) + * MPX (SEFF0EBX_MPX) + * PCOMMIT (SEFF0EBX_PCOMMIT) + * PT (SEFF0EBX_PT) + */ +#define VMM_SEFF0EBX_MASK ~(SEFF0EBX_TSC_ADJUST | SEFF0EBX_SGX | \ + SEFF0EBX_HLE | SEFF0EBX_INVPCID | \ + SEFF0EBX_RTM | SEFF0EBX_PQM | SEFF0EBX_MPX | \ + SEFF0EBX_PCOMMIT | SEFF0EBX_PT | \ + SEFF0EBX_AVX512F | SEFF0EBX_AVX512DQ | \ + SEFF0EBX_AVX512IFMA | SEFF0EBX_AVX512PF | \ + SEFF0EBX_AVX512ER | SEFF0EBX_AVX512CD | \ + SEFF0EBX_AVX512BW | SEFF0EBX_AVX512VL) + +/* ECX mask contains the bits to include */ +#define VMM_SEFF0ECX_MASK (SEFF0ECX_UMIP) + +/* EDX mask contains the bits to include */ +#define VMM_SEFF0EDX_MASK (SEFF0EDX_MD_CLEAR) + +/* + * Extended function flags - copy from host minus: + * 0x80000001 EDX:RDTSCP Support + */ +#define VMM_FEAT_EFLAGS_MASK ~(CPUID_RDTSCP) + +/* + * CPUID[0x4] deterministic cache info + */ +#define VMM_CPUID4_CACHE_TOPOLOGY_MASK 0x3FF + +#ifdef _KERNEL + +#define VMX_FAIL_LAUNCH_UNKNOWN 1 +#define VMX_FAIL_LAUNCH_INVALID_VMCS 2 +#define VMX_FAIL_LAUNCH_VALID_VMCS 3 + +/* MSR bitmap manipulation macros */ +#define VMX_MSRIDX(m) ((m) / 8) +#define VMX_MSRBIT(m) (1 << (m) % 8) + +#define SVM_MSRIDX(m) ((m) / 4) +#define SVM_MSRBIT_R(m) (1 << (((m) % 4) * 2)) +#define SVM_MSRBIT_W(m) (1 << (((m) % 4) * 2 + 1)) + +enum { + VMM_MODE_UNKNOWN, + VMM_MODE_EPT, + VMM_MODE_RVI +}; + +enum { + VMM_MEM_TYPE_REGULAR, + VMM_MEM_TYPE_MMIO, + VMM_MEM_TYPE_UNKNOWN +}; + +/* Forward declarations */ +struct vm; +struct vm_create_params; + +/* + * Implementation-specific cpu state + */ + +struct vmcb_segment { + uint16_t vs_sel; /* 000h */ + uint16_t vs_attr; /* 002h */ + uint32_t vs_lim; /* 004h */ + uint64_t vs_base; /* 008h */ +}; + +#define SVM_ENABLE_NP (1ULL << 0) +#define SVM_ENABLE_SEV (1ULL << 1) +#define SVM_SEVES_ENABLE (1ULL << 2) + +#define SMV_GUEST_INTR_MASK (1ULL << 1) + +#define SVM_LBRVIRT_ENABLE (1ULL << 0) + +struct vmcb { + union { + struct { + uint32_t v_cr_rw; /* 000h */ + uint32_t v_dr_rw; /* 004h */ + uint32_t v_excp; /* 008h */ + uint32_t v_intercept1; /* 00Ch */ + uint32_t v_intercept2; /* 010h */ + uint8_t v_pad1[0x28]; /* 014h-03Bh */ + uint16_t v_pause_thr; /* 03Ch */ + uint16_t v_pause_ct; /* 03Eh */ + uint64_t v_iopm_pa; /* 040h */ + uint64_t v_msrpm_pa; /* 048h */ + uint64_t v_tsc_offset; /* 050h */ + uint32_t v_asid; /* 058h */ + uint8_t v_tlb_control; /* 05Ch */ + uint8_t v_pad2[0x3]; /* 05Dh-05Fh */ + uint8_t v_tpr; /* 060h */ + uint8_t v_irq; /* 061h */ + uint8_t v_intr_misc; /* 062h */ + uint8_t v_intr_masking; /* 063h */ + uint8_t v_intr_vector; /* 064h */ + uint8_t v_pad3[0x3]; /* 065h-067h */ + uint64_t v_intr_shadow; /* 068h */ + uint64_t v_exitcode; /* 070h */ + uint64_t v_exitinfo1; /* 078h */ + uint64_t v_exitinfo2; /* 080h */ + uint64_t v_exitintinfo; /* 088h */ + uint64_t v_np_enable; /* 090h */ + uint64_t v_avic_apic_bar; /* 098h */ + uint64_t v_ghcb_gpa; /* 0A0h */ + uint64_t v_eventinj; /* 0A8h */ + uint64_t v_n_cr3; /* 0B0h */ + uint64_t v_lbr_virt_enable; /* 0B8h */ + uint64_t v_vmcb_clean_bits; /* 0C0h */ + uint64_t v_nrip; /* 0C8h */ + uint8_t v_n_bytes_fetched; /* 0D0h */ + uint8_t v_guest_ins_bytes[0xf]; /* 0D1h-0DFh */ + uint64_t v_avic_apic_back_page; /* 0E0h */ + uint64_t v_pad5; /* 0E8h-0EFh */ + uint64_t v_avic_logical_table; /* 0F0h */ + uint64_t v_avic_phys; /* 0F8h */ + uint64_t v_pad12; /* 100h */ + uint64_t v_vmsa_pa; /* 108h */ + + }; + uint8_t vmcb_control[0x400]; + }; + + union { + struct { + /* Offsets here are relative to start of VMCB SSA */ + struct vmcb_segment v_es; /* 000h */ + struct vmcb_segment v_cs; /* 010h */ + struct vmcb_segment v_ss; /* 020h */ + struct vmcb_segment v_ds; /* 030h */ + struct vmcb_segment v_fs; /* 040h */ + struct vmcb_segment v_gs; /* 050h */ + struct vmcb_segment v_gdtr; /* 060h */ + struct vmcb_segment v_ldtr; /* 070h */ + struct vmcb_segment v_idtr; /* 080h */ + struct vmcb_segment v_tr; /* 090h */ + uint8_t v_pad6[0x2B]; /* 0A0h-0CAh */ + uint8_t v_cpl; /* 0CBh */ + uint32_t v_pad7; /* 0CCh-0CFh */ + uint64_t v_efer; /* 0D0h */ + uint8_t v_pad8[0x70]; /* 0D8h-147h */ + uint64_t v_cr4; /* 148h */ + uint64_t v_cr3; /* 150h */ + uint64_t v_cr0; /* 158h */ + uint64_t v_dr7; /* 160h */ + uint64_t v_dr6; /* 168h */ + uint64_t v_rflags; /* 170h */ + uint64_t v_rip; /* 178h */ + uint64_t v_pad9[0xB]; /* 180h-1D7h */ + uint64_t v_rsp; /* 1D8h */ + uint64_t v_pad10[0x3]; /* 1E0h-1F7h */ + uint64_t v_rax; /* 1F8h */ + uint64_t v_star; /* 200h */ + uint64_t v_lstar; /* 208h */ + uint64_t v_cstar; /* 210h */ + uint64_t v_sfmask; /* 218h */ + uint64_t v_kgsbase; /* 220h */ + uint64_t v_sysenter_cs; /* 228h */ + uint64_t v_sysenter_esp; /* 230h */ + uint64_t v_sysenter_eip; /* 238h */ + uint64_t v_cr2; /* 240h */ + uint64_t v_pad11[0x4]; /* 248h-267h */ + uint64_t v_g_pat; /* 268h */ + uint64_t v_dbgctl; /* 270h */ + uint64_t v_br_from; /* 278h */ + uint64_t v_br_to; /* 280h */ + uint64_t v_lastexcpfrom; /* 288h */ + uint64_t v_lastexcpto; /* 290h */ + }; + uint8_t vmcb_layout[PAGE_SIZE - 0x400]; + }; +}; + +struct vmsa { + struct vmcb_segment v_es; /* 000h */ + struct vmcb_segment v_cs; /* 010h */ + struct vmcb_segment v_ss; /* 020h */ + struct vmcb_segment v_ds; /* 030h */ + struct vmcb_segment v_fs; /* 040h */ + struct vmcb_segment v_gs; /* 050h */ + struct vmcb_segment v_gdtr; /* 060h */ + struct vmcb_segment v_ldtr; /* 070h */ + struct vmcb_segment v_idtr; /* 080h */ + struct vmcb_segment v_tr; /* 090h */ + uint64_t v_pl0_ssp; /* 0A0h */ + uint64_t v_pl1_ssp; /* 0A8h */ + uint64_t v_pl2_ssp; /* 0B0h */ + uint64_t v_pl3_ssp; /* 0B8h */ + uint64_t v_u_cet; /* 0C0h */ + uint8_t v_pad1[0x2]; /* 0C8h-0C9h */ + uint8_t v_vmpl; /* 0CAh */ + uint8_t v_cpl; /* 0CBh */ + uint8_t v_pad2[0x4]; /* 0CCh-0CFh */ + uint64_t v_efer; /* 0D0h */ + uint8_t v_pad3[0x68]; /* 0D8h-13Fh */ + uint64_t v_xss; /* 140h */ + uint64_t v_cr4; /* 148h */ + uint64_t v_cr3; /* 150h */ + uint64_t v_cr0; /* 158h */ + uint64_t v_dr7; /* 160h */ + uint64_t v_dr6; /* 168h */ + uint64_t v_rflags; /* 170h */ + uint64_t v_rip; /* 178h */ + uint64_t v_dr0; /* 180h */ + uint64_t v_dr1; /* 188h */ + uint64_t v_dr2; /* 190h */ + uint64_t v_dr3; /* 198h */ + uint64_t v_dr0_addr_msk; /* 1A0h */ + uint64_t v_dr1_addr_msk; /* 1A8h */ + uint64_t v_dr2_addr_msk; /* 1B0h */ + uint64_t v_dr3_addr_msk; /* 1B8h */ + uint8_t v_pad4[0x18]; /* 1C0h-1D7h */ + uint64_t v_rsp; /* 1D8h */ + uint64_t v_s_cet; /* 1E0h */ + uint64_t v_ssp; /* 1E8h */ + uint64_t v_isst_addr; /* 1F0h */ + uint64_t v_rax; /* 1F8h */ + uint64_t v_star; /* 200h */ + uint64_t v_lstar; /* 208h */ + uint64_t v_cstar; /* 210h */ + uint64_t v_sfmask; /* 218h */ + uint64_t v_kgsbase; /* 220h */ + uint64_t v_sysenter_cs; /* 228h */ + uint64_t v_sysenter_esp; /* 230h */ + uint64_t v_sysenter_eip; /* 238h */ + uint64_t v_cr2; /* 240h */ + uint8_t v_pad5[0x20]; /* 248h-267h */ + uint64_t v_g_pat; /* 268h */ + uint64_t v_dbgctl; /* 270h */ + uint64_t v_br_from; /* 278h */ + uint64_t v_br_to; /* 280h */ + uint64_t v_lastexcpfrom; /* 288h */ + uint64_t v_lastexcpto; /* 290h */ + uint8_t v_pad6[0x48]; /* 298h-2DFh */ + uint8_t v_pad7[0x8]; /* 2E0h-2E7h */ + uint32_t v_pkru; /* 2E8h */ + uint32_t v_tsc_aux; /* 2ECh */ + uint64_t v_gst_tsc_scale;/* 2F0h */ + uint64_t v_gst_tsc_off; /* 2F8h */ + uint64_t v_reg_prot_nce; /* 300h */ + uint64_t v_rcx; /* 308h */ + uint64_t v_rdx; /* 310h */ + uint64_t v_rbx; /* 318h */ + uint64_t v_pad8; /* 320h */ + uint64_t v_rbp; /* 328h */ + uint64_t v_rsi; /* 330h */ + uint64_t v_rdi; /* 338h */ + uint64_t v_r8; /* 340h */ + uint64_t v_r9; /* 348h */ + uint64_t v_r10; /* 350h */ + uint64_t v_r11; /* 358h */ + uint64_t v_r12; /* 360h */ + uint64_t v_r13; /* 368h */ + uint64_t v_r14; /* 370h */ + uint64_t v_r15; /* 378h */ + uint8_t v_pad9[0x10]; /* 380h-38Fh */ + uint64_t v_gst_exitinfo1;/* 390h */ + uint64_t v_gst_exitinfo2;/* 398h */ + uint64_t v_gst_exitiinfo;/* 3A0h */ + uint64_t v_gst_nrip; /* 3A8h */ + uint64_t v_sev_features; /* 3B0h */ + uint64_t v_intr_ctrl; /* 3B8h */ + uint64_t v_gst_exitcode; /* 3C0h */ + uint64_t v_virtual_tom; /* 3C8h */ + uint64_t v_tlb_id; /* 3D0h */ + uint64_t v_pcup_id; /* 3D8h */ + uint64_t v_eventinj; /* 3E0h */ + uint64_t v_xcr0; /* 3E8h */ + uint8_t v_pad10[0x10]; /* 3F0h-3FFh */ + uint64_t v_x87_dp; /* 400h */ + uint32_t v_mxcsr; /* 408h */ + uint16_t v_x87_ftw; /* 40Ch */ + uint16_t v_x87_fsw; /* 40Eh */ + uint16_t v_x87_fcw; /* 410h */ + uint16_t v_x87_fop; /* 412h */ + uint16_t v_x87_ds; /* 414h */ + uint16_t v_x87_cs; /* 416h */ + uint64_t v_x87_rip; /* 418h */ + uint8_t v_fp_x87[0x50]; /* 420h-46Fh */ + uint8_t v_fp_xmm[0x100];/* 470h-56Fh */ + uint8_t v_fp_ymm[0x100];/* 570h-66fh */ + uint8_t v_lbr_st[0x100];/* 670h-76Fh */ + uint64_t v_lbr_select; /* 770h */ + uint64_t v_ibs_fetch_ctl;/* 778h */ + uint64_t v_ibs_fetch_la; /* 780h */ + uint64_t v_ibs_op_ctl; /* 788h */ + uint64_t v_ibs_op_rip; /* 790h */ + uint64_t v_ibs_op_data; /* 798h */ + uint64_t v_ibs_op_data2; /* 7A0h */ + uint64_t v_ibs_op_data3; /* 7A8h */ + uint64_t v_ibs_dc_la; /* 7B0h */ + uint64_t v_ibstgt_rip; /* 7B8h */ + uint64_t v_ic_ibs_xtd_ct;/* 7C0h */ +}; + +/* + * With SEV-ES the host save area (HSA) has the same layout as the + * VMSA. However, it has the offset 0x400 into the HSA page. + * See AMD APM Vol 2, Appendix B. + */ +#define SVM_HSA_OFFSET 0x400 + +struct vmcs { + uint32_t vmcs_revision; +}; + +struct vmx_invvpid_descriptor { + uint64_t vid_vpid; + uint64_t vid_addr; +}; + +struct vmx_invept_descriptor { + uint64_t vid_eptp; + uint64_t vid_reserved; +}; + +struct vmx_msr_store { + uint64_t vms_index; + uint64_t vms_data; +}; + +/* + * Storage for guest registers not preserved in VMCS and various exit + * information. + * + * Note that vmx/svm_enter_guest depend on the layout of this struct for + * field access. + */ +struct vcpu_gueststate { + /* %rsi should be first */ + uint64_t vg_rsi; /* 0x00 */ + uint64_t vg_rax; /* 0x08 */ + uint64_t vg_rbx; /* 0x10 */ + uint64_t vg_rcx; /* 0x18 */ + uint64_t vg_rdx; /* 0x20 */ + uint64_t vg_rdi; /* 0x28 */ + uint64_t vg_rbp; /* 0x30 */ + uint64_t vg_r8; /* 0x38 */ + uint64_t vg_r9; /* 0x40 */ + uint64_t vg_r10; /* 0x48 */ + uint64_t vg_r11; /* 0x50 */ + uint64_t vg_r12; /* 0x58 */ + uint64_t vg_r13; /* 0x60 */ + uint64_t vg_r14; /* 0x68 */ + uint64_t vg_r15; /* 0x70 */ + uint64_t vg_cr2; /* 0x78 */ + uint64_t vg_rip; /* 0x80 */ + uint32_t vg_exit_reason; /* 0x88 */ + uint64_t vg_rflags; /* 0x90 */ + uint64_t vg_xcr0; /* 0x98 */ + /* + * Debug registers + * - %dr4/%dr5 are aliased to %dr6/%dr7 (or cause #DE) + * - %dr7 is saved automatically in the VMCS + */ + uint64_t vg_dr0; /* 0xa0 */ + uint64_t vg_dr1; /* 0xa8 */ + uint64_t vg_dr2; /* 0xb0 */ + uint64_t vg_dr3; /* 0xb8 */ + uint64_t vg_dr6; /* 0xc0 */ +}; + +/* + * Virtual CPU + * + * Methods used to vcpu struct members: + * a atomic operations + * I immutable operations + * K kernel lock + * r reference count + * v vcpu rwlock + * V vm struct's vcpu list lock (vm_vcpu_lock) + */ +struct vcpu { + /* + * Guest FPU state - this must remain as the first member of the struct + * to ensure 64-byte alignment (set up during vcpu_pool init) + */ + struct savefpu vc_g_fpu; /* [v] */ + + /* VMCS / VMCB pointer */ + vaddr_t vc_control_va; /* [I] */ + paddr_t vc_control_pa; /* [I] */ + + /* VLAPIC pointer */ + vaddr_t vc_vlapic_va; /* [I] */ + uint64_t vc_vlapic_pa; /* [I] */ + + /* MSR bitmap address */ + vaddr_t vc_msr_bitmap_va; /* [I] */ + uint64_t vc_msr_bitmap_pa; /* [I] */ + + struct vm *vc_parent; /* [I] */ + uint32_t vc_id; /* [I] */ + uint16_t vc_vpid; /* [I] */ + u_int vc_state; /* [a] */ + SLIST_ENTRY(vcpu) vc_vcpu_link; /* [V] */ + + uint8_t vc_virt_mode; /* [I] */ + + struct rwlock vc_lock; + + struct cpu_info *vc_curcpu; /* [a] */ + struct cpu_info *vc_last_pcpu; /* [v] */ + struct vm_exit vc_exit; /* [v] */ + + uint16_t vc_intr; /* [v] */ + uint8_t vc_irqready; /* [v] */ + + uint8_t vc_fpuinited; /* [v] */ + + uint64_t vc_h_xcr0; /* [v] */ + + struct vcpu_gueststate vc_gueststate; /* [v] */ + struct vcpu_inject_event vc_inject; /* [v] */ + + uint32_t vc_pvclock_version; /* [v] */ + paddr_t vc_pvclock_system_gpa; /* [v] */ + uint32_t vc_pvclock_system_tsc_mul; /* [v] */ + + /* Shadowed MSRs */ + uint64_t vc_shadow_pat; /* [v] */ + + /* Userland Protection Keys */ + uint32_t vc_pkru; /* [v] */ + + /* VMX only (all requiring [v]) */ + uint64_t vc_vmx_basic; + uint64_t vc_vmx_entry_ctls; + uint64_t vc_vmx_true_entry_ctls; + uint64_t vc_vmx_exit_ctls; + uint64_t vc_vmx_true_exit_ctls; + uint64_t vc_vmx_pinbased_ctls; + uint64_t vc_vmx_true_pinbased_ctls; + uint64_t vc_vmx_procbased_ctls; + uint64_t vc_vmx_true_procbased_ctls; + uint64_t vc_vmx_procbased2_ctls; + vaddr_t vc_vmx_msr_exit_save_va; + paddr_t vc_vmx_msr_exit_save_pa; + vaddr_t vc_vmx_msr_exit_load_va; + paddr_t vc_vmx_msr_exit_load_pa; +#if 0 /* XXX currently use msr_exit_save for msr_entry_load too */ + vaddr_t vc_vmx_msr_entry_load_va; + paddr_t vc_vmx_msr_entry_load_pa; +#endif + uint8_t vc_vmx_vpid_enabled; + uint64_t vc_vmx_cr0_fixed1; + uint64_t vc_vmx_cr0_fixed0; + uint32_t vc_vmx_vmcs_state; /* [a] */ +#define VMCS_CLEARED 0 +#define VMCS_LAUNCHED 1 + + /* SVM only (all requiring [v]) */ + vaddr_t vc_svm_hsa_va; + paddr_t vc_svm_hsa_pa; + vaddr_t vc_svm_vmsa_va; + paddr_t vc_svm_vmsa_pa; + vaddr_t vc_svm_ghcb_va; + paddr_t vc_svm_ghcb_pa; + vaddr_t vc_svm_ioio_va; + paddr_t vc_svm_ioio_pa; + int vc_sev; /* [I] */ + int vc_seves; /* [I] */ +}; + +SLIST_HEAD(vcpu_head, vcpu); + +void vmm_dispatch_intr(vaddr_t); +int vmxon(uint64_t *); +int vmxoff(void); +int vmclear(paddr_t *); +int vmptrld(paddr_t *); +int vmptrst(paddr_t *); +int vmwrite(uint64_t, uint64_t); +int vmread(uint64_t, uint64_t *); +int invvpid(uint64_t, struct vmx_invvpid_descriptor *); +int invept(uint64_t, struct vmx_invept_descriptor *); +int vmx_enter_guest(paddr_t *, struct vcpu_gueststate *, int, uint8_t); +int svm_enter_guest(uint64_t, struct vcpu_gueststate *, + struct region_descriptor *); +int svm_seves_enter_guest(uint64_t, vaddr_t, struct region_descriptor *); +void start_vmm_on_cpu(struct cpu_info *); +void stop_vmm_on_cpu(struct cpu_info *); +void vmclear_on_cpu(struct cpu_info *); +int vmm_probe_machdep(struct device *, void *, void *); +void vmm_attach_machdep(struct device *, struct device *, void *); +void vmm_activate_machdep(struct device *, int); +int vmmioctl_machdep(dev_t, u_long, caddr_t, int, struct proc *); +int pledge_ioctl_vmm_machdep(struct proc *, long); +int vmm_start(void); +int vmm_stop(void); +int vm_impl_init(struct vm *, struct proc *); +void vm_impl_deinit(struct vm *); +int vcpu_init(struct vcpu *, struct vm_create_params *); +void vcpu_deinit(struct vcpu *); +int vm_rwregs(struct vm_rwregs_params *, int); +int vcpu_reset_regs(struct vcpu *, struct vcpu_reg_state *); +int svm_get_vmsa_pa(uint32_t, uint32_t, uint64_t *); + +#endif /* _KERNEL */ + +#endif /* ! _LOCORE */ + +#endif /* ! _MACHINE_VMMVAR_H_ */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-openbsd-none/machine/vmparam.h b/lib/libc/include/x86_64-openbsd-none/machine/vmparam.h new file mode 100644 index 000000000000..dc577330a247 --- /dev/null +++ b/lib/libc/include/x86_64-openbsd-none/machine/vmparam.h @@ -0,0 +1,114 @@ +/* $OpenBSD: vmparam.h,v 1.25 2024/11/08 01:44:52 jsg Exp $ */ +/* $NetBSD: vmparam.h,v 1.1 2003/04/26 18:39:49 fvdl Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vmparam.h 5.9 (Berkeley) 5/12/91 + */ + +#ifndef _MACHINE_VMPARAM_H_ +#define _MACHINE_VMPARAM_H_ + +/* + * Machine dependent constants for amd64. + */ + +/* + * USRSTACK is the top (end) of the user stack. Immediately above the + * user stack resides the user structure, which is UPAGES long and contains + * the kernel stack. + * + * Immediately after the user structure is the page table map, and then + * kernel address space. + */ +#define USRSTACK VM_MAXUSER_ADDRESS + +/* + * Virtual memory related constants, all in bytes + */ +#define MAXTSIZ ((paddr_t)256*1024*1024) /* max text size */ +#ifndef DFLDSIZ +#define DFLDSIZ ((paddr_t)128*1024*1024) /* initial data size limit */ +#endif +#ifndef MAXDSIZ +#define MAXDSIZ ((paddr_t)128*1024*1024*1024) /* max data size */ +#endif +#ifndef BRKSIZ +#define BRKSIZ ((paddr_t)8*1024*1024*1024) /* heap gap size */ +#endif +#ifndef DFLSSIZ +#define DFLSSIZ ((paddr_t)2*1024*1024) /* initial stack size limit */ +#endif +#ifndef MAXSSIZ +#define MAXSSIZ ((paddr_t)32*1024*1024) /* max stack size */ +#endif + +#define STACKGAP_RANDOM 256*1024 + +/* + * Size of shared memory map + */ +#ifndef SHMMAXPGS +#define SHMMAXPGS 8192 +#endif + +/* + * Size of User Raw I/O map + */ +#define USRIOSIZE 300 + +/* + * Mach derived constants + */ + +/* user/kernel map constants */ +#define VM_MIN_ADDRESS PAGE_SIZE +#define VM_MAXUSER_ADDRESS 0x00007f7fffffc000 +#define VM_MAX_ADDRESS 0x00007fbfdfeff000 +#ifdef _KERNEL +#define VM_MIN_STACK_ADDRESS 0x0000600000000000 +#endif +#define VM_MIN_KERNEL_ADDRESS 0xffff800000000000 +#define VM_MAX_KERNEL_ADDRESS 0xffff800100000000 + +/* map PIE into approximately the first quarter of user va space */ +#define VM_PIE_MIN_ADDR VM_MIN_ADDRESS +#define VM_PIE_MAX_ADDR 0x200000000000 + +/* virtual sizes (bytes) for various kernel submaps */ +#define VM_PHYS_SIZE (USRIOSIZE*PAGE_SIZE) + +#define VM_PHYSSEG_MAX 16 /* actually we could have this many segments */ +#define VM_PHYSSEG_STRAT VM_PSTRAT_BIGFIRST +#define VM_PHYSSEG_NOADD /* can't add RAM after vm_mem_init */ + +#endif /* _MACHINE_VMPARAM_H_ */ \ No newline at end of file diff --git a/lib/libc/mingw/math/expf.c b/lib/libc/mingw/math/expf.c deleted file mode 100644 index 69d7edc2bc2e..000000000000 --- a/lib/libc/mingw/math/expf.c +++ /dev/null @@ -1,11 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the mingw-w64 runtime package. - * No warranty is given; refer to the file DISCLAIMER.PD within this package. - */ -#include - -float expf (float x) -{ - return (float) exp (x); -} diff --git a/lib/libc/mingw/math/fp_consts.c b/lib/libc/mingw/math/fp_consts.c deleted file mode 100644 index 12330392a048..000000000000 --- a/lib/libc/mingw/math/fp_consts.c +++ /dev/null @@ -1,20 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the mingw-w64 runtime package. - * No warranty is given; refer to the file DISCLAIMER.PD within this package. - */ -#include "fp_consts.h" -const union _ieee_rep __QNAN = { __DOUBLE_QNAN_REP }; -const union _ieee_rep __SNAN = { __DOUBLE_SNAN_REP }; -const union _ieee_rep __INF = { __DOUBLE_INF_REP }; -const union _ieee_rep __DENORM = { __DOUBLE_DENORM_REP }; - -/* ISO C99 */ -#undef nan -/* FIXME */ -double nan (const char *); -double nan (const char * tagp __attribute__((unused)) ) -{ - return __QNAN.double_val; -} - diff --git a/lib/libc/mingw/math/fp_consts.h b/lib/libc/mingw/math/fp_consts.h deleted file mode 100644 index dc042409f143..000000000000 --- a/lib/libc/mingw/math/fp_consts.h +++ /dev/null @@ -1,50 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the mingw-w64 runtime package. - * No warranty is given; refer to the file DISCLAIMER.PD within this package. - */ -#ifndef _FP_CONSTS_H -#define _FP_CONSTS_H - -/* -According to IEEE 754 a QNaN has exponent bits of all 1 values and -initial significand bit of 1. A SNaN has has an exponent of all 1 -values and initial significand bit of 0 (with one or more other -significand bits of 1). An Inf has significand of 0 and -exponent of all 1 values. A denormal value has all exponent bits of 0. -*/ - - -#define __DOUBLE_INF_REP { 0, 0, 0, 0x7ff0 } -#define __DOUBLE_QNAN_REP { 0, 0, 0, 0x7ff8 } -#define __DOUBLE_SNAN_REP { 0, 0, 0, 0x7ff0 } -#define __DOUBLE_DENORM_REP {1, 0, 0, 0} - -#define D_NAN_MASK 0x7ff0000000000000LL /* this will mask NaN's and Inf's */ - -#define __FLOAT_INF_REP { 0, 0x7f80 } -#define __FLOAT_QNAN_REP { 0, 0x7fc0 } -#define __FLOAT_SNAN_REP { 0, 0x7f80 } -#define __FLOAT_DENORM_REP {1,0} - -#define F_NAN_MASK 0x7f800000 - -/* - This assumes no implicit (hidden) bit in extended mode. - Padded to 96 bits - */ -#define __LONG_DOUBLE_INF_REP { 0, 0, 0, 0x8000, 0x7fff, 0 } -#define __LONG_DOUBLE_QNAN_REP { 0, 0, 0, 0xc000, 0x7fff, 0 } -#define __LONG_DOUBLE_SNAN_REP { 0, 0, 0, 0x8000, 0x7fff, 0 } -#define __LONG_DOUBLE_DENORM_REP {1, 0, 0, 0, 0, 0} - -union _ieee_rep -{ - unsigned short rep[6]; - float float_val; - double double_val; - long double ldouble_val; -}; - -#endif /* _FP_CONSTS_H */ - diff --git a/lib/libc/mingw/math/fp_constsf.c b/lib/libc/mingw/math/fp_constsf.c deleted file mode 100644 index 97306dcb1b43..000000000000 --- a/lib/libc/mingw/math/fp_constsf.c +++ /dev/null @@ -1,22 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the mingw-w64 runtime package. - * No warranty is given; refer to the file DISCLAIMER.PD within this package. - */ -#include "fp_consts.h" - -const union _ieee_rep __QNANF = { __FLOAT_QNAN_REP }; -const union _ieee_rep __SNANF = { __FLOAT_SNAN_REP }; -const union _ieee_rep __INFF = { __FLOAT_INF_REP }; -const union _ieee_rep __DENORMF = { __FLOAT_DENORM_REP }; - -/* ISO C99 */ -#undef nanf -/* FIXME */ -float nanf(const char *); - -float nanf(const char * tagp __attribute__((unused)) ) -{ - return __QNANF.float_val; -} - diff --git a/lib/libc/mingw/math/fp_constsl.c b/lib/libc/mingw/math/fp_constsl.c deleted file mode 100644 index 2bb00f7463ff..000000000000 --- a/lib/libc/mingw/math/fp_constsl.c +++ /dev/null @@ -1,25 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the mingw-w64 runtime package. - * No warranty is given; refer to the file DISCLAIMER.PD within this package. - */ -#include "fp_consts.h" -#include - -const union _ieee_rep __QNANL = { __LONG_DOUBLE_QNAN_REP }; -const union _ieee_rep __SNANL = { __LONG_DOUBLE_SNAN_REP }; -const union _ieee_rep __INFL = { __LONG_DOUBLE_INF_REP }; -const union _ieee_rep __DENORML = { __LONG_DOUBLE_DENORM_REP }; - -#undef nanl -/* FIXME */ -long double nanl (const char *); -long double nanl (const char * tagp __attribute__((unused)) ) -{ -#if __SIZEOF_LONG_DOUBLE__ == __SIZEOF_DOUBLE__ - return nan(""); -#else - return __QNANL.ldouble_val; -#endif -} - diff --git a/lib/libc/mingw/math/log10f.c b/lib/libc/mingw/math/log10f.c deleted file mode 100644 index f793e05403d8..000000000000 --- a/lib/libc/mingw/math/log10f.c +++ /dev/null @@ -1,11 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the mingw-w64 runtime package. - * No warranty is given; refer to the file DISCLAIMER.PD within this package. - */ -#include - -float log10f(float _X) -{ - return ((float)log10((double)_X)); -} diff --git a/lib/libc/mingw/math/logf.c b/lib/libc/mingw/math/logf.c deleted file mode 100644 index b85b59256806..000000000000 --- a/lib/libc/mingw/math/logf.c +++ /dev/null @@ -1,11 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the mingw-w64 runtime package. - * No warranty is given; refer to the file DISCLAIMER.PD within this package. - */ -#include - -float logf(float _X) -{ - return ((float)log((double)_X)); -} diff --git a/lib/libc/musl/arch/powerpc64/crt_arch.h b/lib/libc/musl/arch/powerpc64/crt_arch.h index 168669a9336b..c3817deffd11 100644 --- a/lib/libc/musl/arch/powerpc64/crt_arch.h +++ b/lib/libc/musl/arch/powerpc64/crt_arch.h @@ -13,6 +13,7 @@ START ": \n" " stdu 0, -32(1) \n" " mtlr 0 \n" " bl " START "_c \n" +" nop \n" ".weak _DYNAMIC \n" ".hidden _DYNAMIC \n" "1: .long _DYNAMIC-" START "\n" diff --git a/lib/libc/musl/src/ldso/powerpc64/dlsym.s b/lib/libc/musl/src/ldso/powerpc64/dlsym.s index a14715fd4dc7..73e70db9c362 100644 --- a/lib/libc/musl/src/ldso/powerpc64/dlsym.s +++ b/lib/libc/musl/src/ldso/powerpc64/dlsym.s @@ -8,4 +8,5 @@ dlsym: .localentry dlsym,.-dlsym mflr 5 # The return address is arg3. b __dlsym + nop .size dlsym, .-dlsym diff --git a/lib/libc/musl/src/math/exp.c b/lib/libc/musl/src/math/exp.c deleted file mode 100644 index b764d73cfe33..000000000000 --- a/lib/libc/musl/src/math/exp.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Double-precision e^x function. - * - * Copyright (c) 2018, Arm Limited. - * SPDX-License-Identifier: MIT - */ - -#include -#include -#include "libm.h" -#include "exp_data.h" - -#define N (1 << EXP_TABLE_BITS) -#define InvLn2N __exp_data.invln2N -#define NegLn2hiN __exp_data.negln2hiN -#define NegLn2loN __exp_data.negln2loN -#define Shift __exp_data.shift -#define T __exp_data.tab -#define C2 __exp_data.poly[5 - EXP_POLY_ORDER] -#define C3 __exp_data.poly[6 - EXP_POLY_ORDER] -#define C4 __exp_data.poly[7 - EXP_POLY_ORDER] -#define C5 __exp_data.poly[8 - EXP_POLY_ORDER] - -/* Handle cases that may overflow or underflow when computing the result that - is scale*(1+TMP) without intermediate rounding. The bit representation of - scale is in SBITS, however it has a computed exponent that may have - overflown into the sign bit so that needs to be adjusted before using it as - a double. (int32_t)KI is the k used in the argument reduction and exponent - adjustment of scale, positive k here means the result may overflow and - negative k means the result may underflow. */ -static inline double specialcase(double_t tmp, uint64_t sbits, uint64_t ki) -{ - double_t scale, y; - - if ((ki & 0x80000000) == 0) { - /* k > 0, the exponent of scale might have overflowed by <= 460. */ - sbits -= 1009ull << 52; - scale = asdouble(sbits); - y = 0x1p1009 * (scale + scale * tmp); - return eval_as_double(y); - } - /* k < 0, need special care in the subnormal range. */ - sbits += 1022ull << 52; - scale = asdouble(sbits); - y = scale + scale * tmp; - if (y < 1.0) { - /* Round y to the right precision before scaling it into the subnormal - range to avoid double rounding that can cause 0.5+E/2 ulp error where - E is the worst-case ulp error outside the subnormal range. So this - is only useful if the goal is better than 1 ulp worst-case error. */ - double_t hi, lo; - lo = scale - y + scale * tmp; - hi = 1.0 + y; - lo = 1.0 - hi + y + lo; - y = eval_as_double(hi + lo) - 1.0; - /* Avoid -0.0 with downward rounding. */ - if (WANT_ROUNDING && y == 0.0) - y = 0.0; - /* The underflow exception needs to be signaled explicitly. */ - fp_force_eval(fp_barrier(0x1p-1022) * 0x1p-1022); - } - y = 0x1p-1022 * y; - return eval_as_double(y); -} - -/* Top 12 bits of a double (sign and exponent bits). */ -static inline uint32_t top12(double x) -{ - return asuint64(x) >> 52; -} - -double exp(double x) -{ - uint32_t abstop; - uint64_t ki, idx, top, sbits; - double_t kd, z, r, r2, scale, tail, tmp; - - abstop = top12(x) & 0x7ff; - if (predict_false(abstop - top12(0x1p-54) >= top12(512.0) - top12(0x1p-54))) { - if (abstop - top12(0x1p-54) >= 0x80000000) - /* Avoid spurious underflow for tiny x. */ - /* Note: 0 is common input. */ - return WANT_ROUNDING ? 1.0 + x : 1.0; - if (abstop >= top12(1024.0)) { - if (asuint64(x) == asuint64(-INFINITY)) - return 0.0; - if (abstop >= top12(INFINITY)) - return 1.0 + x; - if (asuint64(x) >> 63) - return __math_uflow(0); - else - return __math_oflow(0); - } - /* Large x is special cased below. */ - abstop = 0; - } - - /* exp(x) = 2^(k/N) * exp(r), with exp(r) in [2^(-1/2N),2^(1/2N)]. */ - /* x = ln2/N*k + r, with int k and r in [-ln2/2N, ln2/2N]. */ - z = InvLn2N * x; -#if TOINT_INTRINSICS - kd = roundtoint(z); - ki = converttoint(z); -#elif EXP_USE_TOINT_NARROW - /* z - kd is in [-0.5-2^-16, 0.5] in all rounding modes. */ - kd = eval_as_double(z + Shift); - ki = asuint64(kd) >> 16; - kd = (double_t)(int32_t)ki; -#else - /* z - kd is in [-1, 1] in non-nearest rounding modes. */ - kd = eval_as_double(z + Shift); - ki = asuint64(kd); - kd -= Shift; -#endif - r = x + kd * NegLn2hiN + kd * NegLn2loN; - /* 2^(k/N) ~= scale * (1 + tail). */ - idx = 2 * (ki % N); - top = ki << (52 - EXP_TABLE_BITS); - tail = asdouble(T[idx]); - /* This is only a valid scale when -1023*N < k < 1024*N. */ - sbits = T[idx + 1] + top; - /* exp(x) = 2^(k/N) * exp(r) ~= scale + scale * (tail + exp(r) - 1). */ - /* Evaluation is optimized assuming superscalar pipelined execution. */ - r2 = r * r; - /* Without fma the worst case error is 0.25/N ulp larger. */ - /* Worst case error is less than 0.5+1.11/N+(abs poly error * 2^53) ulp. */ - tmp = tail + r + r2 * (C2 + r * C3) + r2 * r2 * (C4 + r * C5); - if (predict_false(abstop == 0)) - return specialcase(tmp, sbits, ki); - scale = asdouble(sbits); - /* Note: tmp == 0 or |tmp| > 2^-200 and scale > 2^-739, so there - is no spurious underflow here even without fma. */ - return eval_as_double(scale + scale * tmp); -} diff --git a/lib/libc/musl/src/math/exp2.c b/lib/libc/musl/src/math/exp2.c deleted file mode 100644 index e0ff54bd85bb..000000000000 --- a/lib/libc/musl/src/math/exp2.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Double-precision 2^x function. - * - * Copyright (c) 2018, Arm Limited. - * SPDX-License-Identifier: MIT - */ - -#include -#include -#include "libm.h" -#include "exp_data.h" - -#define N (1 << EXP_TABLE_BITS) -#define Shift __exp_data.exp2_shift -#define T __exp_data.tab -#define C1 __exp_data.exp2_poly[0] -#define C2 __exp_data.exp2_poly[1] -#define C3 __exp_data.exp2_poly[2] -#define C4 __exp_data.exp2_poly[3] -#define C5 __exp_data.exp2_poly[4] - -/* Handle cases that may overflow or underflow when computing the result that - is scale*(1+TMP) without intermediate rounding. The bit representation of - scale is in SBITS, however it has a computed exponent that may have - overflown into the sign bit so that needs to be adjusted before using it as - a double. (int32_t)KI is the k used in the argument reduction and exponent - adjustment of scale, positive k here means the result may overflow and - negative k means the result may underflow. */ -static inline double specialcase(double_t tmp, uint64_t sbits, uint64_t ki) -{ - double_t scale, y; - - if ((ki & 0x80000000) == 0) { - /* k > 0, the exponent of scale might have overflowed by 1. */ - sbits -= 1ull << 52; - scale = asdouble(sbits); - y = 2 * (scale + scale * tmp); - return eval_as_double(y); - } - /* k < 0, need special care in the subnormal range. */ - sbits += 1022ull << 52; - scale = asdouble(sbits); - y = scale + scale * tmp; - if (y < 1.0) { - /* Round y to the right precision before scaling it into the subnormal - range to avoid double rounding that can cause 0.5+E/2 ulp error where - E is the worst-case ulp error outside the subnormal range. So this - is only useful if the goal is better than 1 ulp worst-case error. */ - double_t hi, lo; - lo = scale - y + scale * tmp; - hi = 1.0 + y; - lo = 1.0 - hi + y + lo; - y = eval_as_double(hi + lo) - 1.0; - /* Avoid -0.0 with downward rounding. */ - if (WANT_ROUNDING && y == 0.0) - y = 0.0; - /* The underflow exception needs to be signaled explicitly. */ - fp_force_eval(fp_barrier(0x1p-1022) * 0x1p-1022); - } - y = 0x1p-1022 * y; - return eval_as_double(y); -} - -/* Top 12 bits of a double (sign and exponent bits). */ -static inline uint32_t top12(double x) -{ - return asuint64(x) >> 52; -} - -double exp2(double x) -{ - uint32_t abstop; - uint64_t ki, idx, top, sbits; - double_t kd, r, r2, scale, tail, tmp; - - abstop = top12(x) & 0x7ff; - if (predict_false(abstop - top12(0x1p-54) >= top12(512.0) - top12(0x1p-54))) { - if (abstop - top12(0x1p-54) >= 0x80000000) - /* Avoid spurious underflow for tiny x. */ - /* Note: 0 is common input. */ - return WANT_ROUNDING ? 1.0 + x : 1.0; - if (abstop >= top12(1024.0)) { - if (asuint64(x) == asuint64(-INFINITY)) - return 0.0; - if (abstop >= top12(INFINITY)) - return 1.0 + x; - if (!(asuint64(x) >> 63)) - return __math_oflow(0); - else if (asuint64(x) >= asuint64(-1075.0)) - return __math_uflow(0); - } - if (2 * asuint64(x) > 2 * asuint64(928.0)) - /* Large x is special cased below. */ - abstop = 0; - } - - /* exp2(x) = 2^(k/N) * 2^r, with 2^r in [2^(-1/2N),2^(1/2N)]. */ - /* x = k/N + r, with int k and r in [-1/2N, 1/2N]. */ - kd = eval_as_double(x + Shift); - ki = asuint64(kd); /* k. */ - kd -= Shift; /* k/N for int k. */ - r = x - kd; - /* 2^(k/N) ~= scale * (1 + tail). */ - idx = 2 * (ki % N); - top = ki << (52 - EXP_TABLE_BITS); - tail = asdouble(T[idx]); - /* This is only a valid scale when -1023*N < k < 1024*N. */ - sbits = T[idx + 1] + top; - /* exp2(x) = 2^(k/N) * 2^r ~= scale + scale * (tail + 2^r - 1). */ - /* Evaluation is optimized assuming superscalar pipelined execution. */ - r2 = r * r; - /* Without fma the worst case error is 0.5/N ulp larger. */ - /* Worst case error is less than 0.5+0.86/N+(abs poly error * 2^53) ulp. */ - tmp = tail + r * C1 + r2 * (C2 + r * C3) + r2 * r2 * (C4 + r * C5); - if (predict_false(abstop == 0)) - return specialcase(tmp, sbits, ki); - scale = asdouble(sbits); - /* Note: tmp == 0 or |tmp| > 2^-65 and scale > 2^-928, so there - is no spurious underflow here even without fma. */ - return eval_as_double(scale + scale * tmp); -} diff --git a/lib/libc/musl/src/math/exp2f.c b/lib/libc/musl/src/math/exp2f.c deleted file mode 100644 index 0360482cae0a..000000000000 --- a/lib/libc/musl/src/math/exp2f.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Single-precision 2^x function. - * - * Copyright (c) 2017-2018, Arm Limited. - * SPDX-License-Identifier: MIT - */ - -#include -#include -#include "libm.h" -#include "exp2f_data.h" - -/* -EXP2F_TABLE_BITS = 5 -EXP2F_POLY_ORDER = 3 - -ULP error: 0.502 (nearest rounding.) -Relative error: 1.69 * 2^-34 in [-1/64, 1/64] (before rounding.) -Wrong count: 168353 (all nearest rounding wrong results with fma.) -Non-nearest ULP error: 1 (rounded ULP error) -*/ - -#define N (1 << EXP2F_TABLE_BITS) -#define T __exp2f_data.tab -#define C __exp2f_data.poly -#define SHIFT __exp2f_data.shift_scaled - -static inline uint32_t top12(float x) -{ - return asuint(x) >> 20; -} - -float exp2f(float x) -{ - uint32_t abstop; - uint64_t ki, t; - double_t kd, xd, z, r, r2, y, s; - - xd = (double_t)x; - abstop = top12(x) & 0x7ff; - if (predict_false(abstop >= top12(128.0f))) { - /* |x| >= 128 or x is nan. */ - if (asuint(x) == asuint(-INFINITY)) - return 0.0f; - if (abstop >= top12(INFINITY)) - return x + x; - if (x > 0.0f) - return __math_oflowf(0); - if (x <= -150.0f) - return __math_uflowf(0); - } - - /* x = k/N + r with r in [-1/(2N), 1/(2N)] and int k. */ - kd = eval_as_double(xd + SHIFT); - ki = asuint64(kd); - kd -= SHIFT; /* k/N for int k. */ - r = xd - kd; - - /* exp2(x) = 2^(k/N) * 2^r ~= s * (C0*r^3 + C1*r^2 + C2*r + 1) */ - t = T[ki % N]; - t += ki << (52 - EXP2F_TABLE_BITS); - s = asdouble(t); - z = C[0] * r + C[1]; - r2 = r * r; - y = C[2] * r + 1; - y = z * r2 + y; - y = y * s; - return eval_as_float(y); -} diff --git a/lib/libc/musl/src/math/expf.c b/lib/libc/musl/src/math/expf.c deleted file mode 100644 index f9fbf8e727db..000000000000 --- a/lib/libc/musl/src/math/expf.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Single-precision e^x function. - * - * Copyright (c) 2017-2018, Arm Limited. - * SPDX-License-Identifier: MIT - */ - -#include -#include -#include "libm.h" -#include "exp2f_data.h" - -/* -EXP2F_TABLE_BITS = 5 -EXP2F_POLY_ORDER = 3 - -ULP error: 0.502 (nearest rounding.) -Relative error: 1.69 * 2^-34 in [-ln2/64, ln2/64] (before rounding.) -Wrong count: 170635 (all nearest rounding wrong results with fma.) -Non-nearest ULP error: 1 (rounded ULP error) -*/ - -#define N (1 << EXP2F_TABLE_BITS) -#define InvLn2N __exp2f_data.invln2_scaled -#define T __exp2f_data.tab -#define C __exp2f_data.poly_scaled - -static inline uint32_t top12(float x) -{ - return asuint(x) >> 20; -} - -float expf(float x) -{ - uint32_t abstop; - uint64_t ki, t; - double_t kd, xd, z, r, r2, y, s; - - xd = (double_t)x; - abstop = top12(x) & 0x7ff; - if (predict_false(abstop >= top12(88.0f))) { - /* |x| >= 88 or x is nan. */ - if (asuint(x) == asuint(-INFINITY)) - return 0.0f; - if (abstop >= top12(INFINITY)) - return x + x; - if (x > 0x1.62e42ep6f) /* x > log(0x1p128) ~= 88.72 */ - return __math_oflowf(0); - if (x < -0x1.9fe368p6f) /* x < log(0x1p-150) ~= -103.97 */ - return __math_uflowf(0); - } - - /* x*N/Ln2 = k + r with r in [-1/2, 1/2] and int k. */ - z = InvLn2N * xd; - - /* Round and convert z to int, the result is in [-150*N, 128*N] and - ideally ties-to-even rule is used, otherwise the magnitude of r - can be bigger which gives larger approximation error. */ -#if TOINT_INTRINSICS - kd = roundtoint(z); - ki = converttoint(z); -#else -# define SHIFT __exp2f_data.shift - kd = eval_as_double(z + SHIFT); - ki = asuint64(kd); - kd -= SHIFT; -#endif - r = z - kd; - - /* exp(x) = 2^(k/N) * 2^(r/N) ~= s * (C0*r^3 + C1*r^2 + C2*r + 1) */ - t = T[ki % N]; - t += ki << (52 - EXP2F_TABLE_BITS); - s = asdouble(t); - z = C[0] * r + C[1]; - r2 = r * r; - y = C[2] * r + 1; - y = z * r2 + y; - y = y * s; - return eval_as_float(y); -} diff --git a/lib/libc/musl/src/math/fmod.c b/lib/libc/musl/src/math/fmod.c deleted file mode 100644 index 6849722bac50..000000000000 --- a/lib/libc/musl/src/math/fmod.c +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include - -double fmod(double x, double y) -{ - union {double f; uint64_t i;} ux = {x}, uy = {y}; - int ex = ux.i>>52 & 0x7ff; - int ey = uy.i>>52 & 0x7ff; - int sx = ux.i>>63; - uint64_t i; - - /* in the followings uxi should be ux.i, but then gcc wrongly adds */ - /* float load/store to inner loops ruining performance and code size */ - uint64_t uxi = ux.i; - - if (uy.i<<1 == 0 || isnan(y) || ex == 0x7ff) - return (x*y)/(x*y); - if (uxi<<1 <= uy.i<<1) { - if (uxi<<1 == uy.i<<1) - return 0*x; - return x; - } - - /* normalize x and y */ - if (!ex) { - for (i = uxi<<12; i>>63 == 0; ex--, i <<= 1); - uxi <<= -ex + 1; - } else { - uxi &= -1ULL >> 12; - uxi |= 1ULL << 52; - } - if (!ey) { - for (i = uy.i<<12; i>>63 == 0; ey--, i <<= 1); - uy.i <<= -ey + 1; - } else { - uy.i &= -1ULL >> 12; - uy.i |= 1ULL << 52; - } - - /* x mod y */ - for (; ex > ey; ex--) { - i = uxi - uy.i; - if (i >> 63 == 0) { - if (i == 0) - return 0*x; - uxi = i; - } - uxi <<= 1; - } - i = uxi - uy.i; - if (i >> 63 == 0) { - if (i == 0) - return 0*x; - uxi = i; - } - for (; uxi>>52 == 0; uxi <<= 1, ex--); - - /* scale result */ - if (ex > 0) { - uxi -= 1ULL << 52; - uxi |= (uint64_t)ex << 52; - } else { - uxi >>= -ex + 1; - } - uxi |= (uint64_t)sx << 63; - ux.i = uxi; - return ux.f; -} diff --git a/lib/libc/musl/src/math/fmodf.c b/lib/libc/musl/src/math/fmodf.c deleted file mode 100644 index ff58f93365b4..000000000000 --- a/lib/libc/musl/src/math/fmodf.c +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include - -float fmodf(float x, float y) -{ - union {float f; uint32_t i;} ux = {x}, uy = {y}; - int ex = ux.i>>23 & 0xff; - int ey = uy.i>>23 & 0xff; - uint32_t sx = ux.i & 0x80000000; - uint32_t i; - uint32_t uxi = ux.i; - - if (uy.i<<1 == 0 || isnan(y) || ex == 0xff) - return (x*y)/(x*y); - if (uxi<<1 <= uy.i<<1) { - if (uxi<<1 == uy.i<<1) - return 0*x; - return x; - } - - /* normalize x and y */ - if (!ex) { - for (i = uxi<<9; i>>31 == 0; ex--, i <<= 1); - uxi <<= -ex + 1; - } else { - uxi &= -1U >> 9; - uxi |= 1U << 23; - } - if (!ey) { - for (i = uy.i<<9; i>>31 == 0; ey--, i <<= 1); - uy.i <<= -ey + 1; - } else { - uy.i &= -1U >> 9; - uy.i |= 1U << 23; - } - - /* x mod y */ - for (; ex > ey; ex--) { - i = uxi - uy.i; - if (i >> 31 == 0) { - if (i == 0) - return 0*x; - uxi = i; - } - uxi <<= 1; - } - i = uxi - uy.i; - if (i >> 31 == 0) { - if (i == 0) - return 0*x; - uxi = i; - } - for (; uxi>>23 == 0; uxi <<= 1, ex--); - - /* scale result up */ - if (ex > 0) { - uxi -= 1U << 23; - uxi |= (uint32_t)ex << 23; - } else { - uxi >>= -ex + 1; - } - uxi |= sx; - ux.i = uxi; - return ux.f; -} diff --git a/lib/libc/musl/src/math/fmodl.c b/lib/libc/musl/src/math/fmodl.c deleted file mode 100644 index 9f5b87393dca..000000000000 --- a/lib/libc/musl/src/math/fmodl.c +++ /dev/null @@ -1,105 +0,0 @@ -#include "libm.h" - -#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 -long double fmodl(long double x, long double y) -{ - return fmod(x, y); -} -#elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 -long double fmodl(long double x, long double y) -{ - union ldshape ux = {x}, uy = {y}; - int ex = ux.i.se & 0x7fff; - int ey = uy.i.se & 0x7fff; - int sx = ux.i.se & 0x8000; - - if (y == 0 || isnan(y) || ex == 0x7fff) - return (x*y)/(x*y); - ux.i.se = ex; - uy.i.se = ey; - if (ux.f <= uy.f) { - if (ux.f == uy.f) - return 0*x; - return x; - } - - /* normalize x and y */ - if (!ex) { - ux.f *= 0x1p120f; - ex = ux.i.se - 120; - } - if (!ey) { - uy.f *= 0x1p120f; - ey = uy.i.se - 120; - } - - /* x mod y */ -#if LDBL_MANT_DIG == 64 - uint64_t i, mx, my; - mx = ux.i.m; - my = uy.i.m; - for (; ex > ey; ex--) { - i = mx - my; - if (mx >= my) { - if (i == 0) - return 0*x; - mx = 2*i; - } else if (2*mx < mx) { - mx = 2*mx - my; - } else { - mx = 2*mx; - } - } - i = mx - my; - if (mx >= my) { - if (i == 0) - return 0*x; - mx = i; - } - for (; mx >> 63 == 0; mx *= 2, ex--); - ux.i.m = mx; -#elif LDBL_MANT_DIG == 113 - uint64_t hi, lo, xhi, xlo, yhi, ylo; - xhi = (ux.i2.hi & -1ULL>>16) | 1ULL<<48; - yhi = (uy.i2.hi & -1ULL>>16) | 1ULL<<48; - xlo = ux.i2.lo; - ylo = uy.i2.lo; - for (; ex > ey; ex--) { - hi = xhi - yhi; - lo = xlo - ylo; - if (xlo < ylo) - hi -= 1; - if (hi >> 63 == 0) { - if ((hi|lo) == 0) - return 0*x; - xhi = 2*hi + (lo>>63); - xlo = 2*lo; - } else { - xhi = 2*xhi + (xlo>>63); - xlo = 2*xlo; - } - } - hi = xhi - yhi; - lo = xlo - ylo; - if (xlo < ylo) - hi -= 1; - if (hi >> 63 == 0) { - if ((hi|lo) == 0) - return 0*x; - xhi = hi; - xlo = lo; - } - for (; xhi >> 48 == 0; xhi = 2*xhi + (xlo>>63), xlo = 2*xlo, ex--); - ux.i2.hi = xhi; - ux.i2.lo = xlo; -#endif - - /* scale result */ - if (ex <= 0) { - ux.i.se = (ex+120)|sx; - ux.f *= 0x1p-120f; - } else - ux.i.se = ex|sx; - return ux.f; -} -#endif diff --git a/lib/libc/musl/src/math/log.c b/lib/libc/musl/src/math/log.c deleted file mode 100644 index cc52585a9498..000000000000 --- a/lib/libc/musl/src/math/log.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Double-precision log(x) function. - * - * Copyright (c) 2018, Arm Limited. - * SPDX-License-Identifier: MIT - */ - -#include -#include -#include "libm.h" -#include "log_data.h" - -#define T __log_data.tab -#define T2 __log_data.tab2 -#define B __log_data.poly1 -#define A __log_data.poly -#define Ln2hi __log_data.ln2hi -#define Ln2lo __log_data.ln2lo -#define N (1 << LOG_TABLE_BITS) -#define OFF 0x3fe6000000000000 - -/* Top 16 bits of a double. */ -static inline uint32_t top16(double x) -{ - return asuint64(x) >> 48; -} - -double log(double x) -{ - double_t w, z, r, r2, r3, y, invc, logc, kd, hi, lo; - uint64_t ix, iz, tmp; - uint32_t top; - int k, i; - - ix = asuint64(x); - top = top16(x); -#define LO asuint64(1.0 - 0x1p-4) -#define HI asuint64(1.0 + 0x1.09p-4) - if (predict_false(ix - LO < HI - LO)) { - /* Handle close to 1.0 inputs separately. */ - /* Fix sign of zero with downward rounding when x==1. */ - if (WANT_ROUNDING && predict_false(ix == asuint64(1.0))) - return 0; - r = x - 1.0; - r2 = r * r; - r3 = r * r2; - y = r3 * - (B[1] + r * B[2] + r2 * B[3] + - r3 * (B[4] + r * B[5] + r2 * B[6] + - r3 * (B[7] + r * B[8] + r2 * B[9] + r3 * B[10]))); - /* Worst-case error is around 0.507 ULP. */ - w = r * 0x1p27; - double_t rhi = r + w - w; - double_t rlo = r - rhi; - w = rhi * rhi * B[0]; /* B[0] == -0.5. */ - hi = r + w; - lo = r - hi + w; - lo += B[0] * rlo * (rhi + r); - y += lo; - y += hi; - return eval_as_double(y); - } - if (predict_false(top - 0x0010 >= 0x7ff0 - 0x0010)) { - /* x < 0x1p-1022 or inf or nan. */ - if (ix * 2 == 0) - return __math_divzero(1); - if (ix == asuint64(INFINITY)) /* log(inf) == inf. */ - return x; - if ((top & 0x8000) || (top & 0x7ff0) == 0x7ff0) - return __math_invalid(x); - /* x is subnormal, normalize it. */ - ix = asuint64(x * 0x1p52); - ix -= 52ULL << 52; - } - - /* x = 2^k z; where z is in range [OFF,2*OFF) and exact. - The range is split into N subintervals. - The ith subinterval contains z and c is near its center. */ - tmp = ix - OFF; - i = (tmp >> (52 - LOG_TABLE_BITS)) % N; - k = (int64_t)tmp >> 52; /* arithmetic shift */ - iz = ix - (tmp & 0xfffULL << 52); - invc = T[i].invc; - logc = T[i].logc; - z = asdouble(iz); - - /* log(x) = log1p(z/c-1) + log(c) + k*Ln2. */ - /* r ~= z/c - 1, |r| < 1/(2*N). */ -#if __FP_FAST_FMA - /* rounding error: 0x1p-55/N. */ - r = __builtin_fma(z, invc, -1.0); -#else - /* rounding error: 0x1p-55/N + 0x1p-66. */ - r = (z - T2[i].chi - T2[i].clo) * invc; -#endif - kd = (double_t)k; - - /* hi + lo = r + log(c) + k*Ln2. */ - w = kd * Ln2hi + logc; - hi = w + r; - lo = w - hi + r + kd * Ln2lo; - - /* log(x) = lo + (log1p(r) - r) + hi. */ - r2 = r * r; /* rounding error: 0x1p-54/N^2. */ - /* Worst case error if |y| > 0x1p-5: - 0.5 + 4.13/N + abs-poly-error*2^57 ULP (+ 0.002 ULP without fma) - Worst case error if |y| > 0x1p-4: - 0.5 + 2.06/N + abs-poly-error*2^56 ULP (+ 0.001 ULP without fma). */ - y = lo + r2 * A[0] + - r * r2 * (A[1] + r * A[2] + r2 * (A[3] + r * A[4])) + hi; - return eval_as_double(y); -} diff --git a/lib/libc/musl/src/math/log10.c b/lib/libc/musl/src/math/log10.c deleted file mode 100644 index 81026876b223..000000000000 --- a/lib/libc/musl/src/math/log10.c +++ /dev/null @@ -1,101 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/e_log10.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* - * Return the base 10 logarithm of x. See log.c for most comments. - * - * Reduce x to 2^k (1+f) and calculate r = log(1+f) - f + f*f/2 - * as in log.c, then combine and scale in extra precision: - * log10(x) = (f - f*f/2 + r)/log(10) + k*log10(2) - */ - -#include -#include - -static const double -ivln10hi = 4.34294481878168880939e-01, /* 0x3fdbcb7b, 0x15200000 */ -ivln10lo = 2.50829467116452752298e-11, /* 0x3dbb9438, 0xca9aadd5 */ -log10_2hi = 3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */ -log10_2lo = 3.69423907715893078616e-13, /* 0x3D59FEF3, 0x11F12B36 */ -Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ -Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ -Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ -Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ -Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ -Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ -Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ - -double log10(double x) -{ - union {double f; uint64_t i;} u = {x}; - double_t hfsq,f,s,z,R,w,t1,t2,dk,y,hi,lo,val_hi,val_lo; - uint32_t hx; - int k; - - hx = u.i>>32; - k = 0; - if (hx < 0x00100000 || hx>>31) { - if (u.i<<1 == 0) - return -1/(x*x); /* log(+-0)=-inf */ - if (hx>>31) - return (x-x)/0.0; /* log(-#) = NaN */ - /* subnormal number, scale x up */ - k -= 54; - x *= 0x1p54; - u.f = x; - hx = u.i>>32; - } else if (hx >= 0x7ff00000) { - return x; - } else if (hx == 0x3ff00000 && u.i<<32 == 0) - return 0; - - /* reduce x into [sqrt(2)/2, sqrt(2)] */ - hx += 0x3ff00000 - 0x3fe6a09e; - k += (int)(hx>>20) - 0x3ff; - hx = (hx&0x000fffff) + 0x3fe6a09e; - u.i = (uint64_t)hx<<32 | (u.i&0xffffffff); - x = u.f; - - f = x - 1.0; - hfsq = 0.5*f*f; - s = f/(2.0+f); - z = s*s; - w = z*z; - t1 = w*(Lg2+w*(Lg4+w*Lg6)); - t2 = z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); - R = t2 + t1; - - /* See log2.c for details. */ - /* hi+lo = f - hfsq + s*(hfsq+R) ~ log(1+f) */ - hi = f - hfsq; - u.f = hi; - u.i &= (uint64_t)-1<<32; - hi = u.f; - lo = f - hi - hfsq + s*(hfsq+R); - - /* val_hi+val_lo ~ log10(1+f) + k*log10(2) */ - val_hi = hi*ivln10hi; - dk = k; - y = dk*log10_2hi; - val_lo = dk*log10_2lo + (lo+hi)*ivln10lo + lo*ivln10hi; - - /* - * Extra precision in for adding y is not strictly needed - * since there is no very large cancellation near x = sqrt(2) or - * x = 1/sqrt(2), but we do it anyway since it costs little on CPUs - * with some parallelism and it reduces the error for many args. - */ - w = y + val_hi; - val_lo += (y - w) + val_hi; - val_hi = w; - - return val_lo + val_hi; -} diff --git a/lib/libc/musl/src/math/log10f.c b/lib/libc/musl/src/math/log10f.c deleted file mode 100644 index 9ca2f017da66..000000000000 --- a/lib/libc/musl/src/math/log10f.c +++ /dev/null @@ -1,77 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/e_log10f.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* - * See comments in log10.c. - */ - -#include -#include - -static const float -ivln10hi = 4.3432617188e-01, /* 0x3ede6000 */ -ivln10lo = -3.1689971365e-05, /* 0xb804ead9 */ -log10_2hi = 3.0102920532e-01, /* 0x3e9a2080 */ -log10_2lo = 7.9034151668e-07, /* 0x355427db */ -/* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */ -Lg1 = 0xaaaaaa.0p-24, /* 0.66666662693 */ -Lg2 = 0xccce13.0p-25, /* 0.40000972152 */ -Lg3 = 0x91e9ee.0p-25, /* 0.28498786688 */ -Lg4 = 0xf89e26.0p-26; /* 0.24279078841 */ - -float log10f(float x) -{ - union {float f; uint32_t i;} u = {x}; - float_t hfsq,f,s,z,R,w,t1,t2,dk,hi,lo; - uint32_t ix; - int k; - - ix = u.i; - k = 0; - if (ix < 0x00800000 || ix>>31) { /* x < 2**-126 */ - if (ix<<1 == 0) - return -1/(x*x); /* log(+-0)=-inf */ - if (ix>>31) - return (x-x)/0.0f; /* log(-#) = NaN */ - /* subnormal number, scale up x */ - k -= 25; - x *= 0x1p25f; - u.f = x; - ix = u.i; - } else if (ix >= 0x7f800000) { - return x; - } else if (ix == 0x3f800000) - return 0; - - /* reduce x into [sqrt(2)/2, sqrt(2)] */ - ix += 0x3f800000 - 0x3f3504f3; - k += (int)(ix>>23) - 0x7f; - ix = (ix&0x007fffff) + 0x3f3504f3; - u.i = ix; - x = u.f; - - f = x - 1.0f; - s = f/(2.0f + f); - z = s*s; - w = z*z; - t1= w*(Lg2+w*Lg4); - t2= z*(Lg1+w*Lg3); - R = t2 + t1; - hfsq = 0.5f*f*f; - - hi = f - hfsq; - u.f = hi; - u.i &= 0xfffff000; - hi = u.f; - lo = f - hi - hfsq + s*(hfsq+R); - dk = k; - return dk*log10_2lo + (lo+hi)*ivln10lo + lo*ivln10hi + hi*ivln10hi + dk*log10_2hi; -} diff --git a/lib/libc/musl/src/math/log2.c b/lib/libc/musl/src/math/log2.c deleted file mode 100644 index 1276ed4e3100..000000000000 --- a/lib/libc/musl/src/math/log2.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Double-precision log2(x) function. - * - * Copyright (c) 2018, Arm Limited. - * SPDX-License-Identifier: MIT - */ - -#include -#include -#include "libm.h" -#include "log2_data.h" - -#define T __log2_data.tab -#define T2 __log2_data.tab2 -#define B __log2_data.poly1 -#define A __log2_data.poly -#define InvLn2hi __log2_data.invln2hi -#define InvLn2lo __log2_data.invln2lo -#define N (1 << LOG2_TABLE_BITS) -#define OFF 0x3fe6000000000000 - -/* Top 16 bits of a double. */ -static inline uint32_t top16(double x) -{ - return asuint64(x) >> 48; -} - -double log2(double x) -{ - double_t z, r, r2, r4, y, invc, logc, kd, hi, lo, t1, t2, t3, p; - uint64_t ix, iz, tmp; - uint32_t top; - int k, i; - - ix = asuint64(x); - top = top16(x); -#define LO asuint64(1.0 - 0x1.5b51p-5) -#define HI asuint64(1.0 + 0x1.6ab2p-5) - if (predict_false(ix - LO < HI - LO)) { - /* Handle close to 1.0 inputs separately. */ - /* Fix sign of zero with downward rounding when x==1. */ - if (WANT_ROUNDING && predict_false(ix == asuint64(1.0))) - return 0; - r = x - 1.0; -#if __FP_FAST_FMA - hi = r * InvLn2hi; - lo = r * InvLn2lo + __builtin_fma(r, InvLn2hi, -hi); -#else - double_t rhi, rlo; - rhi = asdouble(asuint64(r) & -1ULL << 32); - rlo = r - rhi; - hi = rhi * InvLn2hi; - lo = rlo * InvLn2hi + r * InvLn2lo; -#endif - r2 = r * r; /* rounding error: 0x1p-62. */ - r4 = r2 * r2; - /* Worst-case error is less than 0.54 ULP (0.55 ULP without fma). */ - p = r2 * (B[0] + r * B[1]); - y = hi + p; - lo += hi - y + p; - lo += r4 * (B[2] + r * B[3] + r2 * (B[4] + r * B[5]) + - r4 * (B[6] + r * B[7] + r2 * (B[8] + r * B[9]))); - y += lo; - return eval_as_double(y); - } - if (predict_false(top - 0x0010 >= 0x7ff0 - 0x0010)) { - /* x < 0x1p-1022 or inf or nan. */ - if (ix * 2 == 0) - return __math_divzero(1); - if (ix == asuint64(INFINITY)) /* log(inf) == inf. */ - return x; - if ((top & 0x8000) || (top & 0x7ff0) == 0x7ff0) - return __math_invalid(x); - /* x is subnormal, normalize it. */ - ix = asuint64(x * 0x1p52); - ix -= 52ULL << 52; - } - - /* x = 2^k z; where z is in range [OFF,2*OFF) and exact. - The range is split into N subintervals. - The ith subinterval contains z and c is near its center. */ - tmp = ix - OFF; - i = (tmp >> (52 - LOG2_TABLE_BITS)) % N; - k = (int64_t)tmp >> 52; /* arithmetic shift */ - iz = ix - (tmp & 0xfffULL << 52); - invc = T[i].invc; - logc = T[i].logc; - z = asdouble(iz); - kd = (double_t)k; - - /* log2(x) = log2(z/c) + log2(c) + k. */ - /* r ~= z/c - 1, |r| < 1/(2*N). */ -#if __FP_FAST_FMA - /* rounding error: 0x1p-55/N. */ - r = __builtin_fma(z, invc, -1.0); - t1 = r * InvLn2hi; - t2 = r * InvLn2lo + __builtin_fma(r, InvLn2hi, -t1); -#else - double_t rhi, rlo; - /* rounding error: 0x1p-55/N + 0x1p-65. */ - r = (z - T2[i].chi - T2[i].clo) * invc; - rhi = asdouble(asuint64(r) & -1ULL << 32); - rlo = r - rhi; - t1 = rhi * InvLn2hi; - t2 = rlo * InvLn2hi + r * InvLn2lo; -#endif - - /* hi + lo = r/ln2 + log2(c) + k. */ - t3 = kd + logc; - hi = t3 + t1; - lo = t3 - hi + t1 + t2; - - /* log2(r+1) = r/ln2 + r^2*poly(r). */ - /* Evaluation is optimized assuming superscalar pipelined execution. */ - r2 = r * r; /* rounding error: 0x1p-54/N^2. */ - r4 = r2 * r2; - /* Worst-case error if |y| > 0x1p-4: 0.547 ULP (0.550 ULP without fma). - ~ 0.5 + 2/N/ln2 + abs-poly-error*0x1p56 ULP (+ 0.003 ULP without fma). */ - p = A[0] + r * A[1] + r2 * (A[2] + r * A[3]) + r4 * (A[4] + r * A[5]); - y = lo + r2 * p + hi; - return eval_as_double(y); -} diff --git a/lib/libc/musl/src/math/log2f.c b/lib/libc/musl/src/math/log2f.c deleted file mode 100644 index c368f88f33f5..000000000000 --- a/lib/libc/musl/src/math/log2f.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Single-precision log2 function. - * - * Copyright (c) 2017-2018, Arm Limited. - * SPDX-License-Identifier: MIT - */ - -#include -#include -#include "libm.h" -#include "log2f_data.h" - -/* -LOG2F_TABLE_BITS = 4 -LOG2F_POLY_ORDER = 4 - -ULP error: 0.752 (nearest rounding.) -Relative error: 1.9 * 2^-26 (before rounding.) -*/ - -#define N (1 << LOG2F_TABLE_BITS) -#define T __log2f_data.tab -#define A __log2f_data.poly -#define OFF 0x3f330000 - -float log2f(float x) -{ - double_t z, r, r2, p, y, y0, invc, logc; - uint32_t ix, iz, top, tmp; - int k, i; - - ix = asuint(x); - /* Fix sign of zero with downward rounding when x==1. */ - if (WANT_ROUNDING && predict_false(ix == 0x3f800000)) - return 0; - if (predict_false(ix - 0x00800000 >= 0x7f800000 - 0x00800000)) { - /* x < 0x1p-126 or inf or nan. */ - if (ix * 2 == 0) - return __math_divzerof(1); - if (ix == 0x7f800000) /* log2(inf) == inf. */ - return x; - if ((ix & 0x80000000) || ix * 2 >= 0xff000000) - return __math_invalidf(x); - /* x is subnormal, normalize it. */ - ix = asuint(x * 0x1p23f); - ix -= 23 << 23; - } - - /* x = 2^k z; where z is in range [OFF,2*OFF] and exact. - The range is split into N subintervals. - The ith subinterval contains z and c is near its center. */ - tmp = ix - OFF; - i = (tmp >> (23 - LOG2F_TABLE_BITS)) % N; - top = tmp & 0xff800000; - iz = ix - top; - k = (int32_t)tmp >> 23; /* arithmetic shift */ - invc = T[i].invc; - logc = T[i].logc; - z = (double_t)asfloat(iz); - - /* log2(x) = log1p(z/c-1)/ln2 + log2(c) + k */ - r = z * invc - 1; - y0 = logc + (double_t)k; - - /* Pipelined polynomial evaluation to approximate log1p(r)/ln2. */ - r2 = r * r; - y = A[1] * r + A[2]; - y = A[0] * r2 + y; - p = A[3] * r + y0; - y = y * r2 + p; - return eval_as_float(y); -} diff --git a/lib/libc/musl/src/math/logf.c b/lib/libc/musl/src/math/logf.c deleted file mode 100644 index e4c2237caa2e..000000000000 --- a/lib/libc/musl/src/math/logf.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Single-precision log function. - * - * Copyright (c) 2017-2018, Arm Limited. - * SPDX-License-Identifier: MIT - */ - -#include -#include -#include "libm.h" -#include "logf_data.h" - -/* -LOGF_TABLE_BITS = 4 -LOGF_POLY_ORDER = 4 - -ULP error: 0.818 (nearest rounding.) -Relative error: 1.957 * 2^-26 (before rounding.) -*/ - -#define T __logf_data.tab -#define A __logf_data.poly -#define Ln2 __logf_data.ln2 -#define N (1 << LOGF_TABLE_BITS) -#define OFF 0x3f330000 - -float logf(float x) -{ - double_t z, r, r2, y, y0, invc, logc; - uint32_t ix, iz, tmp; - int k, i; - - ix = asuint(x); - /* Fix sign of zero with downward rounding when x==1. */ - if (WANT_ROUNDING && predict_false(ix == 0x3f800000)) - return 0; - if (predict_false(ix - 0x00800000 >= 0x7f800000 - 0x00800000)) { - /* x < 0x1p-126 or inf or nan. */ - if (ix * 2 == 0) - return __math_divzerof(1); - if (ix == 0x7f800000) /* log(inf) == inf. */ - return x; - if ((ix & 0x80000000) || ix * 2 >= 0xff000000) - return __math_invalidf(x); - /* x is subnormal, normalize it. */ - ix = asuint(x * 0x1p23f); - ix -= 23 << 23; - } - - /* x = 2^k z; where z is in range [OFF,2*OFF] and exact. - The range is split into N subintervals. - The ith subinterval contains z and c is near its center. */ - tmp = ix - OFF; - i = (tmp >> (23 - LOGF_TABLE_BITS)) % N; - k = (int32_t)tmp >> 23; /* arithmetic shift */ - iz = ix - (tmp & 0xff800000); - invc = T[i].invc; - logc = T[i].logc; - z = (double_t)asfloat(iz); - - /* log(x) = log1p(z/c-1) + log(c) + k*Ln2 */ - r = z * invc - 1; - y0 = logc + (double_t)k * Ln2; - - /* Pipelined polynomial evaluation to approximate log1p(r). */ - r2 = r * r; - y = A[1] * r + A[2]; - y = A[0] * r2 + y; - y = y * r2 + (y0 + r); - return eval_as_float(y); -} diff --git a/lib/libc/musl/src/math/nan.c b/lib/libc/musl/src/math/nan.c deleted file mode 100644 index 9e0826c77831..000000000000 --- a/lib/libc/musl/src/math/nan.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -double nan(const char *s) -{ - return NAN; -} diff --git a/lib/libc/musl/src/math/nanf.c b/lib/libc/musl/src/math/nanf.c deleted file mode 100644 index 752ce5463488..000000000000 --- a/lib/libc/musl/src/math/nanf.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -float nanf(const char *s) -{ - return NAN; -} diff --git a/lib/libc/musl/src/math/nanl.c b/lib/libc/musl/src/math/nanl.c deleted file mode 100644 index 969af5641f35..000000000000 --- a/lib/libc/musl/src/math/nanl.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -long double nanl(const char *s) -{ - return NAN; -} diff --git a/lib/libc/musl/src/stdlib/bsearch.c b/lib/libc/musl/src/stdlib/bsearch.c deleted file mode 100644 index fe050ea30a22..000000000000 --- a/lib/libc/musl/src/stdlib/bsearch.c +++ /dev/null @@ -1,20 +0,0 @@ -#include - -void *bsearch(const void *key, const void *base, size_t nel, size_t width, int (*cmp)(const void *, const void *)) -{ - void *try; - int sign; - while (nel > 0) { - try = (char *)base + width*(nel/2); - sign = cmp(key, try); - if (sign < 0) { - nel /= 2; - } else if (sign > 0) { - base = (char *)try + width; - nel -= nel/2+1; - } else { - return try; - } - } - return NULL; -} diff --git a/lib/libc/musl/src/stdlib/div.c b/lib/libc/musl/src/stdlib/div.c deleted file mode 100644 index e42c1f14fa49..000000000000 --- a/lib/libc/musl/src/stdlib/div.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -div_t div(int num, int den) -{ - return (div_t){ num/den, num%den }; -} diff --git a/lib/libc/musl/src/stdlib/imaxdiv.c b/lib/libc/musl/src/stdlib/imaxdiv.c deleted file mode 100644 index b2ce821f51e3..000000000000 --- a/lib/libc/musl/src/stdlib/imaxdiv.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -imaxdiv_t imaxdiv(intmax_t num, intmax_t den) -{ - return (imaxdiv_t){ num/den, num%den }; -} diff --git a/lib/libc/musl/src/stdlib/ldiv.c b/lib/libc/musl/src/stdlib/ldiv.c deleted file mode 100644 index 36eb960b0978..000000000000 --- a/lib/libc/musl/src/stdlib/ldiv.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -ldiv_t ldiv(long num, long den) -{ - return (ldiv_t){ num/den, num%den }; -} diff --git a/lib/libc/musl/src/stdlib/lldiv.c b/lib/libc/musl/src/stdlib/lldiv.c deleted file mode 100644 index 7aaf7a0e6f24..000000000000 --- a/lib/libc/musl/src/stdlib/lldiv.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -lldiv_t lldiv(long long num, long long den) -{ - return (lldiv_t){ num/den, num%den }; -} diff --git a/lib/libc/musl/src/stdlib/qsort.c b/lib/libc/musl/src/stdlib/qsort.c deleted file mode 100644 index 314ddc29da1d..000000000000 --- a/lib/libc/musl/src/stdlib/qsort.c +++ /dev/null @@ -1,221 +0,0 @@ -/* Copyright (C) 2011 by Valentin Ochs - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* Minor changes by Rich Felker for integration in musl, 2011-04-27. */ - -/* Smoothsort, an adaptive variant of Heapsort. Memory usage: O(1). - Run time: Worst case O(n log n), close to O(n) in the mostly-sorted case. */ - -#define _BSD_SOURCE -#include -#include -#include - -#include "atomic.h" -#define ntz(x) a_ctz_l((x)) - -typedef int (*cmpfun)(const void *, const void *, void *); - -static inline int pntz(size_t p[2]) { - int r = ntz(p[0] - 1); - if(r != 0 || (r = 8*sizeof(size_t) + ntz(p[1])) != 8*sizeof(size_t)) { - return r; - } - return 0; -} - -static void cycle(size_t width, unsigned char* ar[], int n) -{ - unsigned char tmp[256]; - size_t l; - int i; - - if(n < 2) { - return; - } - - ar[n] = tmp; - while(width) { - l = sizeof(tmp) < width ? sizeof(tmp) : width; - memcpy(ar[n], ar[0], l); - for(i = 0; i < n; i++) { - memcpy(ar[i], ar[i + 1], l); - ar[i] += l; - } - width -= l; - } -} - -/* shl() and shr() need n > 0 */ -static inline void shl(size_t p[2], int n) -{ - if(n >= 8 * sizeof(size_t)) { - n -= 8 * sizeof(size_t); - p[1] = p[0]; - p[0] = 0; - } - p[1] <<= n; - p[1] |= p[0] >> (sizeof(size_t) * 8 - n); - p[0] <<= n; -} - -static inline void shr(size_t p[2], int n) -{ - if(n >= 8 * sizeof(size_t)) { - n -= 8 * sizeof(size_t); - p[0] = p[1]; - p[1] = 0; - } - p[0] >>= n; - p[0] |= p[1] << (sizeof(size_t) * 8 - n); - p[1] >>= n; -} - -static void sift(unsigned char *head, size_t width, cmpfun cmp, void *arg, int pshift, size_t lp[]) -{ - unsigned char *rt, *lf; - unsigned char *ar[14 * sizeof(size_t) + 1]; - int i = 1; - - ar[0] = head; - while(pshift > 1) { - rt = head - width; - lf = head - width - lp[pshift - 2]; - - if(cmp(ar[0], lf, arg) >= 0 && cmp(ar[0], rt, arg) >= 0) { - break; - } - if(cmp(lf, rt, arg) >= 0) { - ar[i++] = lf; - head = lf; - pshift -= 1; - } else { - ar[i++] = rt; - head = rt; - pshift -= 2; - } - } - cycle(width, ar, i); -} - -static void trinkle(unsigned char *head, size_t width, cmpfun cmp, void *arg, size_t pp[2], int pshift, int trusty, size_t lp[]) -{ - unsigned char *stepson, - *rt, *lf; - size_t p[2]; - unsigned char *ar[14 * sizeof(size_t) + 1]; - int i = 1; - int trail; - - p[0] = pp[0]; - p[1] = pp[1]; - - ar[0] = head; - while(p[0] != 1 || p[1] != 0) { - stepson = head - lp[pshift]; - if(cmp(stepson, ar[0], arg) <= 0) { - break; - } - if(!trusty && pshift > 1) { - rt = head - width; - lf = head - width - lp[pshift - 2]; - if(cmp(rt, stepson, arg) >= 0 || cmp(lf, stepson, arg) >= 0) { - break; - } - } - - ar[i++] = stepson; - head = stepson; - trail = pntz(p); - shr(p, trail); - pshift += trail; - trusty = 0; - } - if(!trusty) { - cycle(width, ar, i); - sift(head, width, cmp, arg, pshift, lp); - } -} - -void __qsort_r(void *base, size_t nel, size_t width, cmpfun cmp, void *arg) -{ - size_t lp[12*sizeof(size_t)]; - size_t i, size = width * nel; - unsigned char *head, *high; - size_t p[2] = {1, 0}; - int pshift = 1; - int trail; - - if (!size) return; - - head = base; - high = head + size - width; - - /* Precompute Leonardo numbers, scaled by element width */ - for(lp[0]=lp[1]=width, i=2; (lp[i]=lp[i-2]+lp[i-1]+width) < size; i++); - - while(head < high) { - if((p[0] & 3) == 3) { - sift(head, width, cmp, arg, pshift, lp); - shr(p, 2); - pshift += 2; - } else { - if(lp[pshift - 1] >= high - head) { - trinkle(head, width, cmp, arg, p, pshift, 0, lp); - } else { - sift(head, width, cmp, arg, pshift, lp); - } - - if(pshift == 1) { - shl(p, 1); - pshift = 0; - } else { - shl(p, pshift - 1); - pshift = 1; - } - } - - p[0] |= 1; - head += width; - } - - trinkle(head, width, cmp, arg, p, pshift, 0, lp); - - while(pshift != 1 || p[0] != 1 || p[1] != 0) { - if(pshift <= 1) { - trail = pntz(p); - shr(p, trail); - pshift += trail; - } else { - shl(p, 2); - pshift -= 2; - p[0] ^= 7; - shr(p, 1); - trinkle(head - lp[pshift] - width, width, cmp, arg, p, pshift + 1, 1, lp); - shl(p, 1); - p[0] |= 1; - trinkle(head - width, width, cmp, arg, p, pshift, 1, lp); - } - head -= width; - } -} - -weak_alias(__qsort_r, qsort_r); diff --git a/lib/libc/musl/src/stdlib/qsort_nr.c b/lib/libc/musl/src/stdlib/qsort_nr.c deleted file mode 100644 index 8ffe71d03819..000000000000 --- a/lib/libc/musl/src/stdlib/qsort_nr.c +++ /dev/null @@ -1,14 +0,0 @@ -#define _BSD_SOURCE -#include - -typedef int (*cmpfun)(const void *, const void *); - -static int wrapper_cmp(const void *v1, const void *v2, void *cmp) -{ - return ((cmpfun)cmp)(v1, v2); -} - -void qsort(void *base, size_t nel, size_t width, cmpfun cmp) -{ - __qsort_r(base, nel, width, wrapper_cmp, (void *)cmp); -} diff --git a/lib/libc/musl/src/string/bcmp.c b/lib/libc/musl/src/string/bcmp.c deleted file mode 100644 index 87c6007ee3cc..000000000000 --- a/lib/libc/musl/src/string/bcmp.c +++ /dev/null @@ -1,8 +0,0 @@ -#define _BSD_SOURCE -#include -#include - -int bcmp(const void *s1, const void *s2, size_t n) -{ - return memcmp(s1, s2, n); -} diff --git a/lib/libc/openbsd/abilists b/lib/libc/openbsd/abilists new file mode 100644 index 000000000000..59cd5c93c3cc Binary files /dev/null and b/lib/libc/openbsd/abilists differ diff --git a/lib/libc/openbsd/lib/csu/aarch64/md_init.h b/lib/libc/openbsd/lib/csu/aarch64/md_init.h new file mode 100644 index 000000000000..70a4d9103d46 --- /dev/null +++ b/lib/libc/openbsd/lib/csu/aarch64/md_init.h @@ -0,0 +1,83 @@ +/* $OpenBSD: md_init.h,v 1.12 2023/11/18 16:26:16 deraadt Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define MD_SECT_CALL_FUNC(section, func) \ + __asm (".section "#section", \"ax\" \n" \ + " bl " #func " \n" \ + " .previous") + +#define MD_SECTION_PROLOGUE(sect, entry_pt) \ + __asm ( \ + ".section "#sect",\"ax\",%progbits \n" \ + " .globl " #entry_pt " \n" \ + " .type " #entry_pt ",%function \n" \ + " .align 4 \n" \ + #entry_pt": \n" \ + " bti c \n" \ + " sub sp, sp, #16 \n" \ + " str lr, [sp] \n" \ + " /* fall thru */ \n" \ + " .previous") + + +#define MD_SECTION_EPILOGUE(sect) \ + __asm ( \ + ".section "#sect",\"ax\",%progbits \n" \ + " ldr lr, [sp] \n" \ + " add sp, sp, #16 \n" \ + " ret \n" \ + " .previous") + + +#define MD_CRT0_START \ + __asm( \ + ".text \n" \ + " .align 0 \n" \ + " .globl _start \n" \ + " .globl __start \n" \ + "_start: \n" \ + "__start: \n" \ + " bti c \n" \ + " mov x3, x2 /* cleanup */ \n" \ + "/* Get argc/argv/envp from stack */ \n" \ + " ldr x0, [sp] \n" \ + " add x1, sp, #0x0008 \n" \ + " add x2, x1, x0, lsl #3 \n" \ + " add x2, x2, #0x0008 \n" \ + " \n" \ + " b ___start \n" \ + ".previous"); + +/* zig patch: no static crt support */ diff --git a/lib/libc/openbsd/lib/csu/amd64/md_init.h b/lib/libc/openbsd/lib/csu/amd64/md_init.h new file mode 100644 index 000000000000..3b41a93b54c1 --- /dev/null +++ b/lib/libc/openbsd/lib/csu/amd64/md_init.h @@ -0,0 +1,80 @@ +/* $OpenBSD: md_init.h,v 1.11 2023/11/18 16:26:16 deraadt Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define MD_SECT_CALL_FUNC(section, func) \ + __asm (".section "#section", \"ax\"\n" \ + " call " #func "\n" \ + " .previous") + +#define MD_SECTION_PROLOGUE(sect, entry_pt) \ + __asm ( \ + ".section "#sect",\"ax\",@progbits \n" \ + " .globl " #entry_pt " \n" \ + " .type " #entry_pt ",@function \n" \ + " .align 16 \n" \ + #entry_pt": \n" \ + " endbr64 \n" \ + " subq $8,%rsp \n" \ + " .previous") + + +#define MD_SECTION_EPILOGUE(sect) \ + __asm ( \ + ".section "#sect",\"ax\",@progbits \n" \ + " addq $8,%rsp \n" \ + " ret \n" \ + " .previous") + + +#define MD_CRT0_START \ + __asm( \ + ".text \n" \ + " .align 8 \n" \ + " .globl __start \n" \ + " .globl _start \n" \ + "_start: \n" \ + "__start: \n" \ + " endbr64 \n" \ + " movq %rdx,%rcx \n" \ + " movq (%rsp),%rdi \n" \ + " leaq 16(%rsp,%rdi,8),%rdx \n" \ + " leaq 8(%rsp),%rsi \n" \ + " subq $8,%rsp \n" \ + " andq $~15,%rsp \n" \ + " addq $8,%rsp \n" \ + " jmp ___start \n" \ + " .previous") + +/* zig patch: no static crt support */ diff --git a/lib/libc/openbsd/lib/csu/arm/md_init.h b/lib/libc/openbsd/lib/csu/arm/md_init.h new file mode 100644 index 000000000000..6865105512b8 --- /dev/null +++ b/lib/libc/openbsd/lib/csu/arm/md_init.h @@ -0,0 +1,112 @@ +/* $OpenBSD: md_init.h,v 1.19 2024/08/17 09:48:31 phessler Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * arm overrides these because it uses %progbits instead of @progbits + */ +#define MD_DATA_SECTION_FLAGS_SYMBOL(section, flags, type, symbol) \ + extern __dso_hidden type symbol[]; \ + __asm(" .section "section",\""flags"\",%progbits \n" \ + " .balign 4 \n" \ + #symbol": \n" \ + " .previous") +#define MD_DATA_SECTION_SYMBOL_VALUE(section, type, symbol, value) \ + extern __dso_hidden type symbol[]; \ + __asm(" .section "section",\"aw\",%progbits \n" \ + " .balign 4 \n" \ + #symbol": \n" \ + " .int "#value" \n" \ + " .previous") +#define MD_DATA_SECTION_FLAGS_VALUE(section, flags, value) \ + __asm(" .section "section",\""flags"\",%progbits \n" \ + " .balign 4 \n" \ + " .int "#value" \n" \ + " .previous") + +#define MD_SECT_CALL_FUNC(section, func) \ + __asm (".section "#section", \"ax\" \n" \ + " movw r0, #:lower16:" #func "- 1f - 8 \n" \ + " movt r0, #:upper16:" #func "- 1f - 8 \n" \ + "1: add r0, r0, pc \n" \ + " blx r0 \n" \ + " .previous") + +#define MD_SECTION_PROLOGUE(sect, entry_pt) \ + __asm ( \ + ".section "#sect",\"ax\",%progbits \n" \ + " .globl " #entry_pt " \n" \ + " .type " #entry_pt ",%function \n" \ + " .align 4 \n" \ + #entry_pt": \n" \ + " push {r4, lr} \n" \ + " /* fall thru */ \n" \ + " .previous") + + +#define MD_SECTION_EPILOGUE(sect) \ + __asm ( \ + ".section "#sect",\"ax\",%progbits \n" \ + " pop {r4, pc} \n" \ + " .previous") + + +/* + * The definitions of environ and __progname prevent the creation + * of COPY relocations for WEAK symbols. + */ +#define MD_CRT0_START \ + __asm( \ + ".text \n" \ + " .align 0 \n" \ + " .globl _start \n" \ + " .globl __start \n" \ + "_start: \n" \ + "__start: \n" \ + " mov r3, r0 /* cleanup */ \n" \ + "/* Get argc/argv/envp from stack */ \n" \ + " ldr r0, [sp, #0] \n" \ + " add r1, sp, #4 \n" \ + " add r2, r1, r0, lsl #2 \n" \ + " add r2, r2, #4 \n" \ + " \n" \ + "/* \n" \ + " * Ensure the stack is properly \n" \ + " * aligned before calling C code. \n" \ + " */ \n" \ + " bic sp, sp, #7" /*__STRING(STACKALIGNBYTES)*/ " \n" \ + " b ___start \n" \ + ".previous"); + +/* zig patch: no static crt support */ diff --git a/lib/libc/openbsd/lib/csu/crt0.c b/lib/libc/openbsd/lib/csu/crt0.c new file mode 100644 index 000000000000..938a707bce6a --- /dev/null +++ b/lib/libc/openbsd/lib/csu/crt0.c @@ -0,0 +1,76 @@ +/* $OpenBSD: crt0.c,v 1.19 2025/05/24 06:32:12 deraadt Exp $ */ + +/* + * Copyright (c) 1995 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include "md_init.h" +/* zig patch: no static crt support */ +#include "extern.h" + +#define STR(x) __STRING(x) /* shorter macro name for MD_RCRT0_START */ + +/* some defaults */ +#ifndef MD_START_ARGS +#define MD_START_ARGS \ + int argc, char **argv, char **envp, void (*cleanup)(void) +#endif +static void ___start(MD_START_ARGS) __used; +#ifndef MD_EPROL_LABEL +#define MD_EPROL_LABEL __asm(" .text\n_eprol:") +#endif + +char ***_csu_finish(char **_argv, char **_envp, void (*_cleanup)(void)); + +/* zig patch: no profiling support */ + +#ifdef MD_CRT0_START +MD_CRT0_START; +#endif + +/* zig patch: no legacy leanup abi support */ + +static void +___start(MD_START_ARGS) +{ + size_t size, i; + char ***environp; +#ifdef MD_START_SETUP + MD_START_SETUP +#endif + + environp = _csu_finish(argv, envp, cleanup); + + exit(main(argc, argv, *environp)); +} diff --git a/lib/libc/openbsd/lib/csu/crtbegin.c b/lib/libc/openbsd/lib/csu/crtbegin.c new file mode 100644 index 000000000000..4ef3062a612f --- /dev/null +++ b/lib/libc/openbsd/lib/csu/crtbegin.c @@ -0,0 +1,61 @@ +/* $OpenBSD: crtbegin.c,v 1.26 2019/01/09 16:42:38 visa Exp $ */ +/* $NetBSD: crtbegin.c,v 1.1 1996/09/12 16:59:03 cgd Exp $ */ + +/* + * Copyright (c) 1993 Paul Kranenburg + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Paul Kranenburg. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Run-time module for GNU C++ compiled shared libraries. + * + * The linker constructs the following arrays of pointers to global + * constructors and destructors. The first element contains the + * number of pointers in each. + * The tables are also null-terminated. + */ +#include + +#include "md_init.h" +#include "os-note-elf.h" +#include "extern.h" + +/* zig patch: no ctors/dtors and init/fini */ + +/* + * Include support for the __cxa_atexit/__cxa_finalize C++ abi for + * gcc > 2.x. __dso_handle is NULL in the main program and a unique + * value for each C++ shared library. For more info on this API, see: + * + * http://www.codesourcery.com/cxx-abi/abi.html#dso-dtor + */ + +void *__dso_handle = NULL; +__asm(".hidden __dso_handle"); + +long __guard_local __dso_hidden __attribute__((section(".openbsd.randomdata"))); diff --git a/lib/libc/openbsd/lib/csu/extern.h b/lib/libc/openbsd/lib/csu/extern.h new file mode 100644 index 000000000000..92dc12a04374 --- /dev/null +++ b/lib/libc/openbsd/lib/csu/extern.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2004 Marc Espie + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +void __init(void) __dso_hidden; +int main(int argc, char *argv[], char *envp[]); + +typedef const void *dl_cb_cb(int); +typedef void (*initarray_f)(int, char **, char **, dl_cb_cb *); +typedef void (*init_f)(void); + +/* + * Provide default implementations of these. Only archs with weird + * ASM stuff (hppa, arm) need to override them + */ +#ifndef MD_DATA_SECTION_FLAGS_SYMBOL +# ifdef __LP64__ +# define VALUE_ALIGN ".balign 8" +# define VALUE_DIRECTIVE ".quad" +# else +# define VALUE_ALIGN ".balign 4" +# define VALUE_DIRECTIVE ".int" +# endif +# define MD_DATA_SECTION_FLAGS_SYMBOL(section, flags, type, symbol) \ + extern __dso_hidden type symbol[]; \ + __asm(" .section "section",\""flags"\",@progbits \n" \ + " "VALUE_ALIGN" \n" \ + #symbol": \n" \ + " .previous") +# define MD_DATA_SECTION_SYMBOL_VALUE(section, type, symbol, value) \ + extern __dso_hidden type symbol[]; \ + __asm(" .section "section",\"aw\",@progbits \n" \ + " "VALUE_ALIGN" \n" \ + #symbol": \n" \ + " "VALUE_DIRECTIVE" "#value" \n" \ + " .previous") +# define MD_DATA_SECTION_FLAGS_VALUE(section, flags, value) \ + __asm(" .section "section",\""flags"\",@progbits \n" \ + " "VALUE_ALIGN" \n" \ + " "VALUE_DIRECTIVE" "#value" \n" \ + " .previous") +#endif diff --git a/lib/libc/openbsd/lib/csu/i386/md_init.h b/lib/libc/openbsd/lib/csu/i386/md_init.h new file mode 100644 index 000000000000..fd6fa64e4d21 --- /dev/null +++ b/lib/libc/openbsd/lib/csu/i386/md_init.h @@ -0,0 +1,83 @@ +/* $OpenBSD: md_init.h,v 1.13 2023/11/18 16:26:16 deraadt Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define MD_SECT_CALL_FUNC(section, func) \ + __asm (".section "#section", \"ax\"\n" \ + " call " #func "\n" \ + " .previous") + +#define MD_SECTION_PROLOGUE(sect, entry_pt) \ + __asm ( \ + ".section "#sect",\"ax\",@progbits \n" \ + " .globl " #entry_pt " \n" \ + " .type " #entry_pt ",@function \n" \ + " .align 16 \n" \ + #entry_pt": \n" \ + " pushl %ebp \n" \ + " movl %esp,%ebp \n" \ + " andl $~15,%esp \n" \ + " .previous") + + +#define MD_SECTION_EPILOGUE(sect) \ + __asm ( \ + ".section "#sect",\"ax\",@progbits \n" \ + " leave \n" \ + " ret \n" \ + " .previous") + + +#define MD_CRT0_START \ + __asm( \ + ".text \n" \ + " .align 4 \n" \ + " .globl __start \n" \ + " .globl _start \n" \ + "_start: \n" \ + "__start: \n" \ + " movl %esp,%ebp \n" \ + " andl $~15,%esp # align stack\n" \ + " pushl %edx # cleanup\n" \ + " movl 0(%ebp),%eax \n" \ + " leal 8(%ebp,%eax,4),%ecx \n" \ + " leal 4(%ebp),%edx \n" \ + " pushl %ecx \n" \ + " pushl %edx \n" \ + " pushl %eax \n" \ + " xorl %ebp,%ebp # mark deepest stack frame\n" \ + " call ___start \n" \ + " .previous") + +/* zig patch: no static crt support */ diff --git a/lib/libc/openbsd/lib/csu/mips64/md_init.h b/lib/libc/openbsd/lib/csu/mips64/md_init.h new file mode 100644 index 000000000000..a20c1ad37c22 --- /dev/null +++ b/lib/libc/openbsd/lib/csu/mips64/md_init.h @@ -0,0 +1,127 @@ +/* $OpenBSD: md_init.h,v 1.22 2023/11/19 00:46:54 deraadt Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * Copyright (c) 2001 Simon Burge + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Allocate 32 bytes for the stack frame. Store GP at SP+16 (since + * this is where code generated by the compiler for fallthru processing + * expects it to be), and the RA at SP+24. + */ + +/* this is gross... */ + +#ifdef __ABICALLS__ +#define MD_FUNCTION_PROLOGUE(entry_pt) \ + " .frame $sp,32,$31 \n" \ + " .set reorder \n" \ + " dsubu $sp,$sp,32 \n" \ + " .cpsetup $25, 16, "#entry_pt" \n" \ + " sd $ra ,24($sp) \n" +#else +#define MD_FUNCTION_PROLOGUE(entry_pt) \ + " dsubu $sp,$sp,32 \n" \ + " sd $ra ,24($sp) \n" +#endif + + +#define MD_SECTION_PROLOGUE(sect, entry_pt) \ + __asm ( \ + ".section "#sect",\"ax\",@progbits \n" \ + ".align 2 \n" \ + ".globl "#entry_pt" \n" \ + ".type "#entry_pt",@function \n" \ + ".ent "#entry_pt" \n" \ + #entry_pt": \n" \ + MD_FUNCTION_PROLOGUE(entry_pt) \ + " /* fall thru */ \n" \ + ".end "#entry_pt" \n" \ + ".previous") + +#define MD_SECTION_EPILOGUE(sect) \ + __asm ( \ + ".section "#sect",\"ax\",@progbits \n" \ + " ld $ra ,24($sp) \n" \ + " # next should have been a .cpreturn \n" \ + " ld $gp,16($sp) \n" \ + " .set noreorder \n" \ + " j $ra \n" \ + " daddu $sp,$sp,32 \n" \ + " .set reorder \n" \ + ".previous") + +#define MD_SECT_CALL_FUNC(section, func) \ + __asm (".section "#section", \"ax\" \n" \ + " .local " #func " \n" \ + " jal " #func " \n" \ + ".previous") + +#define MD_CRT0_START \ + __asm( \ + ".text \n" \ + " .align 3 \n" \ + " .globl __start \n" \ + " .ent __start \n" \ + " .type __start, @function \n" \ + "__start: \n" \ + " lui $gp, %hi(%neg(%gp_rel(__start))) \n" \ + " addiu $gp, $gp, %lo(%neg(%gp_rel(__start))) \n" \ + " daddu $gp, $gp, $t9 \n" \ + " move $a0, $sp \n" \ + " dsrl $a1, $sp, 4 \n" /* align stack on a */ \ + " dsll $sp, $a1, 4 \n" /* 16 byte boundary */ \ + " move $a1, $v0 \n" \ + " .local ___start \n" \ + " dla $t9, ___start \n" \ + " jr $t9 \n" \ + " .end __start \n" \ + " .previous") + +/* zig patch: no static crt support */ + +struct kframe { + long kargc; + char *kargv[1]; /* size depends on kargc */ + char kargstr[1]; /* size varies */ + char kenvstr[1]; /* size varies */ +}; + +#define MD_START_ARGS struct kframe *kfp, void (*cleanup)(void) +#define MD_START_SETUP \ + char **argv, **envp; \ + long argc; \ + \ + argc = kfp->kargc; \ + argv = &kfp->kargv[0]; \ + envp = argv + argc + 1; diff --git a/lib/libc/openbsd/lib/csu/os-note-elf.h b/lib/libc/openbsd/lib/csu/os-note-elf.h new file mode 100644 index 000000000000..48e33f22eb9e --- /dev/null +++ b/lib/libc/openbsd/lib/csu/os-note-elf.h @@ -0,0 +1,19 @@ +/* $OpenBSD: os-note-elf.h,v 1.5 2009/03/06 23:13:40 kurt Exp $ */ +/* + * Contents: + * + * long Name length + * long Description length + * long ELF_NOTE_TYPE_OSVERSION (1) XXX - need a define. + * "OpenBSD\0" + * version? 0 XXX + */ + +__asm(" .section \".note.openbsd.ident\", \"a\"\n" +" .p2align 2\n" +" .long 8\n" +" .long 4\n" +" .long 1\n" +" .ascii \"OpenBSD\\0\"\n" +" .long 0\n" +" .previous\n"); diff --git a/lib/libc/openbsd/lib/csu/powerpc/md_init.h b/lib/libc/openbsd/lib/csu/powerpc/md_init.h new file mode 100644 index 000000000000..933e2ee115f0 --- /dev/null +++ b/lib/libc/openbsd/lib/csu/powerpc/md_init.h @@ -0,0 +1,80 @@ +/* $OpenBSD: md_init.h,v 1.12 2023/11/18 16:26:16 deraadt Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define MD_SECT_CALL_FUNC(section, func) \ + __asm (".section "#section", \"ax\"\n" \ + " bl " #func "\n" \ + " .previous") + +#define MD_SECTION_PROLOGUE(sect, entry_pt) \ + __asm ( \ + ".section "#sect",\"ax\",@progbits \n" \ + " .globl " #entry_pt " \n" \ + " .type " #entry_pt ",@function \n" \ + " .align 4 \n" \ + #entry_pt": \n" \ + " stwu %r1,-16(%r1) \n" \ + " mflr %r0 \n" \ + " stw %r0,12(%r1) \n" \ + " /* fall thru */ \n" \ + " .previous") + + +#define MD_SECTION_EPILOGUE(sect) \ + __asm ( \ + ".section "#sect",\"ax\",@progbits \n" \ + " lwz %r0,12(%r1) \n" \ + " mtlr %r0 \n" \ + " addi %r1,%r1,16 \n" \ + " blr \n" \ + " .previous") + +#define MD_CRT0_START \ +__asm( \ +" .text \n" \ +" .section \".text\" \n" \ +" .align 2 \n" \ +" .globl _start \n" \ +" .type _start, @function \n" \ +" .globl __start \n" \ +" .type __start, @function \n" \ +"_start: \n" \ +"__start: \n" \ +" # put cleanup in r6 instead of r7 \n" \ +" mr %r6, %r7 \n" \ +" b ___start \n" \ +) + +/* zig patch: no static crt support */ diff --git a/lib/libc/openbsd/lib/csu/powerpc64/md_init.h b/lib/libc/openbsd/lib/csu/powerpc64/md_init.h new file mode 100644 index 000000000000..1ede168fc139 --- /dev/null +++ b/lib/libc/openbsd/lib/csu/powerpc64/md_init.h @@ -0,0 +1,75 @@ +/* $OpenBSD: md_init.h,v 1.5 2023/11/18 16:26:16 deraadt Exp $ */ + +/* + * Copyright (c) 2020 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define MD_SECT_CALL_FUNC(section, func) \ + __asm (".section "#section", \"ax\" \n" \ + " bl " #func " \n" \ + " .previous") + +#define MD_SECTION_PROLOGUE(sect, entry_pt) \ + __asm ( \ + ".section "#sect",\"ax\",@progbits \n" \ + " .globl " #entry_pt " \n" \ + " .type " #entry_pt ",@function \n" \ + " .align 4 \n" \ + #entry_pt": \n" \ + ".L_"sect"_gep: \n" \ + " addis %r2, %r12, .TOC.-.L_"sect"_gep@ha \n" \ + " addi %r2, %r2, .TOC.-.L_"sect"_gep@l \n" \ + ".L_"sect"_lep: \n" \ + " .localentry " #entry_pt", .L_"sect"_lep-.L_"sect"_gep; \n" \ + " mflr %r0 \n" \ + " std %r0,16(%r1) \n" \ + " stdu %r1,-64(%r1) \n" \ + " /* fall thru */ \n" \ + " .previous") + + +#define MD_SECTION_EPILOGUE(sect) \ + __asm ( \ + ".section "#sect",\"ax\",@progbits \n" \ + " addi %r1,%r1,64 \n" \ + " ld %r0,16(%r1) \n" \ + " mtlr %r0 \n" \ + " blr \n" \ + " .previous") + +#define MD_CRT0_START \ +__asm( \ +" .text \n" \ +" .section \".text\" \n" \ +" .align 2 \n" \ +" .globl _start \n" \ +" .type _start, @function \n" \ +" .globl __start \n" \ +" .type __start, @function \n" \ +"_start: \n" \ +"__start: \n" \ +" bl 1f \n" \ +"1: \n" \ +" mflr %r30 \n" \ +" addis %r2, %r30, .TOC.-1b@ha \n" \ +" addi %r2, %r2, .TOC.-1b@l \n" \ +" # put cleanup in r6 instead of r7 \n" \ +" mr %r6, %r7 \n" \ +" li %r7, 0 \n" \ +" stdu %r7, -64(%r1) \n" \ +" b ___start \n" \ +) + +/* zig patch: no static crt support */ diff --git a/lib/libc/openbsd/lib/csu/riscv64/md_init.h b/lib/libc/openbsd/lib/csu/riscv64/md_init.h new file mode 100644 index 000000000000..99fd09139917 --- /dev/null +++ b/lib/libc/openbsd/lib/csu/riscv64/md_init.h @@ -0,0 +1,74 @@ +/* $OpenBSD: md_init.h,v 1.4 2023/11/18 16:26:16 deraadt Exp $ */ +/* + * Copyright (c) 2020 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define MD_SECT_CALL_FUNC(section, func) \ + __asm (".section "#section", \"ax\" \n" \ + "call " # func "@plt \n" \ + " .previous") + +#define MD_SECTION_PROLOGUE(sect, entry_pt) \ + __asm ( \ + ".section "#sect",\"ax\",%progbits \n" \ + " .globl " #entry_pt " \n" \ + " .type " #entry_pt ",@function \n" \ + " .align 4 \n" \ + #entry_pt": \n" \ + " addi sp, sp, -16 \n" \ + " sd ra,8(sp) \n" \ + " sd s0,0(sp) \n" \ + " addi s0, sp, 16 \n" \ + " /* fall thru */ \n" \ + " .previous") + + +#define MD_SECTION_EPILOGUE(sect) \ + __asm ( \ + ".section "#sect",\"ax\",%progbits \n" \ + " ld ra, 8(sp) \n" \ + " ld s0, 0(sp) \n" \ + " addi sp, sp, 16 \n" \ + " jr ra \n" \ + " .previous") + + +#define MD_CRT0_START \ + __asm( \ + ".text \n" \ + " .align 0 \n" \ + " .globl _start \n" \ + " .globl __start \n" \ + " .type _start, @function \n" \ + " .type __start, @function \n" \ + "_start: \n" \ + "__start: \n" \ + "/* Get argc/argv/envp from stack */ \n" \ + " ld a0, (sp) \n" \ + " addi a1, sp, 0x8 \n" \ + " slli t0, a0, 0x3 \n" \ + " add a2, a1, t0 \n" \ + " addi a2, a2, 0x8 \n" \ + " \n" \ + " addi sp, sp, -16 \n" \ + " li t0, 0 \n" \ + " sd t0,(sp) \n" \ + " \n" \ + " j ___start \n" \ + " .size _start, .-_start \n" \ + " .size __start, .-__start \n" \ + ".previous"); + +/* zig patch: no static crt support */ diff --git a/lib/libc/openbsd/lib/csu/sparc64/md_init.h b/lib/libc/openbsd/lib/csu/sparc64/md_init.h new file mode 100644 index 000000000000..e46806831f76 --- /dev/null +++ b/lib/libc/openbsd/lib/csu/sparc64/md_init.h @@ -0,0 +1,85 @@ +/* $OpenBSD: md_init.h,v 1.11 2025/01/30 21:41:37 kurt Exp $ */ + +/*- + * Copyright (c) 2001 Ross Harvey + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define MD_SECT_CALL_FUNC(section, func) \ + __asm (".section "#section", \"ax\" \n" \ + " call " #func " \n" \ + " nop \n" \ + " .previous") + +#define MD_SECTION_PROLOGUE(sect, entry_pt) \ + __asm ( \ + ".section "#sect",\"ax\",@progbits \n" \ + " .globl " #entry_pt " \n" \ + " .type " #entry_pt ",@function \n" \ + #entry_pt": \n" \ + " save %sp, -192, %sp \n" \ + " .align 4 \n" \ + " /* fall thru */ \n" \ + " .previous") + + +#define MD_SECTION_EPILOGUE(sect) \ + __asm ( \ + ".section "#sect",\"ax\",@progbits \n" \ + " ret \n" \ + " restore \n" \ + " .previous") + + +#define MD_CRT0_START \ + __asm__( \ + ".text \n" \ + " .align 4 \n" \ + " .global _start \n" \ + " .global __start \n" \ + "_start: \n" \ + "__start: \n" \ + " clr %fp \n" \ + " add %sp, 2175, %o0 /* stack */\n" \ + " ba,pt %icc, ___start \n" \ + " mov %g1, %o1 \n" \ + " .previous") + +/* zig patch: no static crt support */ + +#define MD_START_ARGS char **sp, void (*cleanup)(void) +#define MD_START_SETUP \ + char **argv, **envp; \ + long argc; \ + \ + argc = *(long *)sp; \ + argv = sp + 1; \ + envp = sp + 2 + argc; /* 2: argc + NULL ending argv */ diff --git a/lib/std/Build.zig b/lib/std/Build.zig index 25d1ff6d95b8..a9d42a98d23e 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -1,21 +1,19 @@ +const Build = @This(); const builtin = @import("builtin"); const std = @import("std.zig"); const Io = std.Io; const fs = std.fs; const mem = std.mem; -const debug = std.debug; const panic = std.debug.panic; -const assert = debug.assert; +const assert = std.debug.assert; const log = std.log; const StringHashMap = std.StringHashMap; -const Allocator = mem.Allocator; +const Allocator = std.mem.Allocator; const Target = std.Target; const process = std.process; -const EnvMap = std.process.EnvMap; -const File = fs.File; +const File = std.Io.File; const Sha256 = std.crypto.hash.sha2.Sha256; -const Build = @This(); const ArrayList = std.ArrayList; pub const Cache = @import("Build/Cache.zig"); @@ -79,7 +77,7 @@ enable_rosetta: bool = false, enable_wasmtime: bool = false, /// Use system Wine installation to run cross compiled Windows build artifacts. enable_wine: bool = false, -/// After following the steps in https://github.com/ziglang/zig/wiki/Updating-libc#glibc, +/// After following the steps in https://codeberg.org/ziglang/infra/src/branch/master/libc-update/glibc.md, /// this will be the directory $glibc-build-dir/install/glibcs /// Given the example of the aarch64 target, this is the directory /// that contains the path `aarch64-linux-gnu/lib/ld-linux-aarch64.so.1`. @@ -113,13 +111,14 @@ pub const ReleaseMode = enum { /// Settings that are here rather than in Build are not configurable per-package. pub const Graph = struct { io: Io, + /// Process lifetime. arena: Allocator, system_library_options: std.StringArrayHashMapUnmanaged(SystemLibraryMode) = .empty, system_package_mode: bool = false, debug_compiler_runtime_libs: bool = false, cache: Cache, zig_exe: [:0]const u8, - env_map: EnvMap, + environ_map: process.Environ.Map, global_cache_root: Cache.Directory, zig_lib_directory: Cache.Directory, needed_lazy_dependencies: std.StringArrayHashMapUnmanaged(void) = .empty, @@ -130,6 +129,9 @@ pub const Graph = struct { dependency_cache: InitializedDepMap = .empty, allow_so_scripts: ?bool = null, time_report: bool, + /// Similar to the `Io.Terminal.Mode` returned by `Io.lockStderr`, but also + /// respects the '--color' flag. + stderr_mode: ?Io.Terminal.Mode = null, }; const AvailableDeps = []const struct { []const u8, []const u8 }; @@ -188,7 +190,7 @@ pub const RunError = error{ ExitCodeFailure, ProcessTerminated, ExecNotSupported, -} || std.process.Child.SpawnError; +} || std.process.SpawnError; pub const PkgConfigError = error{ PkgConfigCrashed, @@ -287,7 +289,7 @@ pub fn create( .lib_dir = undefined, .exe_dir = undefined, .h_dir = undefined, - .dest_dir = graph.env_map.get("DESTDIR"), + .dest_dir = graph.environ_map.get("DESTDIR"), .install_tls = .{ .step = .init(.{ .id = TopLevelStep.base_id, @@ -1056,6 +1058,38 @@ pub fn addNamedLazyPath(b: *Build, name: []const u8, lp: LazyPath) void { b.named_lazy_paths.put(b.dupe(name), lp.dupe(b)) catch @panic("OOM"); } +/// Creates a step for mutating files inside a temporary directory created lazily +/// and automatically cleaned up upon successful build. +/// +/// The directory will be placed inside "tmp" rather than "o", and caching will +/// be skipped. During the `make` phase, the step will always do all the file +/// system operations, and on successful build completion, the dir will be +/// deleted along with all other tmp directories. The directory is therefore +/// eligible to be used for mutations by other steps. +/// +/// See also: +/// * `addWriteFiles` +/// * `addMutateFiles` +pub fn addTempFiles(b: *Build) *Step.WriteFile { + const wf = addWriteFiles(b); + wf.mode = .tmp; + return wf; +} + +/// Creates a step for mutating temporary directories created with `addTempFiles`. +/// +/// Consider instead `addWriteFiles` which is for creating a cached directory +/// of files to operate on. +/// +/// This should only be used with a `tmp_path` obtained via `addTempFiles` or +/// `tmpPath`. +pub fn addMutateFiles(b: *Build, tmp_path: LazyPath) *Step.WriteFile { + const wf = addWriteFiles(b); + wf.mode = .{ .mutate = tmp_path }; + tmp_path.addStepDependencies(&wf.step); + return wf; +} + pub fn addWriteFiles(b: *Build) *Step.WriteFile { return Step.WriteFile.create(b); } @@ -1064,10 +1098,6 @@ pub fn addUpdateSourceFiles(b: *Build) *Step.UpdateSourceFiles { return Step.UpdateSourceFiles.create(b); } -pub fn addRemoveDirTree(b: *Build, dir_path: LazyPath) *Step.RemoveDir { - return Step.RemoveDir.create(b, dir_path); -} - pub fn addFail(b: *Build, error_msg: []const u8) *Step.Fail { return Step.Fail.create(b, error_msg); } @@ -1699,21 +1729,20 @@ pub fn addCheckFile( return Step.CheckFile.create(b, file_source, options); } -pub fn truncateFile(b: *Build, dest_path: []const u8) (fs.Dir.MakeError || fs.Dir.StatFileError)!void { - if (b.verbose) { - log.info("truncate {s}", .{dest_path}); - } - const cwd = fs.cwd(); - var src_file = cwd.createFile(dest_path, .{}) catch |err| switch (err) { +pub fn truncateFile(b: *Build, dest_path: []const u8) (Io.Dir.CreateDirError || Io.Dir.StatFileError)!void { + const io = b.graph.io; + if (b.verbose) log.info("truncate {s}", .{dest_path}); + const cwd = Io.Dir.cwd(); + var src_file = cwd.createFile(io, dest_path, .{}) catch |err| switch (err) { error.FileNotFound => blk: { if (fs.path.dirname(dest_path)) |dirname| { - try cwd.makePath(dirname); + try cwd.createDirPath(io, dirname); } - break :blk try cwd.createFile(dest_path, .{}); + break :blk try cwd.createFile(io, dest_path, .{}); }, else => |e| return e, }; - src_file.close(); + src_file.close(io); } /// References a file or directory relative to the source root. @@ -1737,8 +1766,7 @@ pub fn pathFromRoot(b: *Build, sub_path: []const u8) []u8 { } fn pathFromCwd(b: *Build, sub_path: []const u8) []u8 { - const cwd = process.getCwdAlloc(b.allocator) catch @panic("OOM"); - return b.pathResolve(&.{ cwd, sub_path }); + return b.pathResolve(&.{ b.graph.cache.cwd, sub_path }); } pub fn pathJoin(b: *Build, paths: []const []const u8) []u8 { @@ -1754,14 +1782,17 @@ pub fn fmt(b: *Build, comptime format: []const u8, args: anytype) []u8 { } fn supportedWindowsProgramExtension(ext: []const u8) bool { - inline for (@typeInfo(std.process.Child.WindowsExtension).@"enum".fields) |field| { + inline for (@typeInfo(std.process.WindowsExtension).@"enum".fields) |field| { if (std.ascii.eqlIgnoreCase(ext, "." ++ field.name)) return true; } return false; } fn tryFindProgram(b: *Build, full_path: []const u8) ?[]const u8 { - if (fs.realpathAlloc(b.allocator, full_path)) |p| { + const io = b.graph.io; + const arena = b.allocator; + + if (b.build_root.handle.realPathFileAlloc(io, full_path, arena)) |p| { return p; } else |err| switch (err) { error.OutOfMemory => @panic("OOM"), @@ -1769,13 +1800,17 @@ fn tryFindProgram(b: *Build, full_path: []const u8) ?[]const u8 { } if (builtin.os.tag == .windows) { - if (b.graph.env_map.get("PATHEXT")) |PATHEXT| { + if (b.graph.environ_map.get("PATHEXT")) |PATHEXT| { var it = mem.tokenizeScalar(u8, PATHEXT, fs.path.delimiter); while (it.next()) |ext| { if (!supportedWindowsProgramExtension(ext)) continue; - return fs.realpathAlloc(b.allocator, b.fmt("{s}{s}", .{ full_path, ext })) catch |err| switch (err) { + return b.build_root.handle.realPathFileAlloc( + io, + b.fmt("{s}{s}", .{ full_path, ext }), + arena, + ) catch |err| switch (err) { error.OutOfMemory => @panic("OOM"), else => continue, }; @@ -1796,7 +1831,7 @@ pub fn findProgram(b: *Build, names: []const []const u8, paths: []const []const return tryFindProgram(b, b.pathJoin(&.{ search_prefix, "bin", name })) orelse continue; } } - if (b.graph.env_map.get("PATH")) |PATH| { + if (b.graph.environ_map.get("PATH")) |PATH| { for (names) |name| { if (fs.path.isAbsolute(name)) { return name; @@ -1822,24 +1857,26 @@ pub fn runAllowFail( b: *Build, argv: []const []const u8, out_code: *u8, - stderr_behavior: std.process.Child.StdIo, + stderr_behavior: std.process.SpawnOptions.StdIo, ) RunError![]u8 { assert(argv.len != 0); if (!process.can_spawn) return error.ExecNotSupported; - const io = b.graph.io; + const graph = b.graph; + const io = graph.io; const max_output_size = 400 * 1024; - var child = std.process.Child.init(argv, b.allocator); - child.stdin_behavior = .Ignore; - child.stdout_behavior = .Pipe; - child.stderr_behavior = stderr_behavior; - child.env_map = &b.graph.env_map; - - try Step.handleVerbose2(b, null, child.env_map, argv); - try child.spawn(); + try Step.handleVerbose2(b, null, &graph.environ_map, argv); + + var child = try std.process.spawn(io, .{ + .argv = argv, + .environ_map = &graph.environ_map, + .stdin = .ignore, + .stdout = .pipe, + .stderr = stderr_behavior, + }); var stdout_reader = child.stdout.?.readerStreaming(io, &.{}); const stdout = stdout_reader.interface.allocRemaining(b.allocator, .limited(max_output_size)) catch { @@ -1847,16 +1884,20 @@ pub fn runAllowFail( }; errdefer b.allocator.free(stdout); - const term = try child.wait(); + const term = try child.wait(io); switch (term) { - .Exited => |code| { + .exited => |code| { if (code != 0) { out_code.* = @as(u8, @truncate(code)); return error.ExitCodeFailure; } return stdout; }, - .Signal, .Stopped, .Unknown => |code| { + .signal => |sig| { + out_code.* = @as(u8, @truncate(@intFromEnum(sig))); + return error.ProcessTerminated; + }, + .stopped, .unknown => |code| { out_code.* = @as(u8, @truncate(code)); return error.ProcessTerminated; }, @@ -1867,21 +1908,11 @@ pub fn runAllowFail( /// inside step make() functions. If any errors occur, it fails the build with /// a helpful message. pub fn run(b: *Build, argv: []const []const u8) []u8 { - if (!process.can_spawn) { - std.debug.print("unable to spawn the following command: cannot spawn child process\n{s}\n", .{ - try Step.allocPrintCmd(b.allocator, null, argv), - }); - process.exit(1); - } - var code: u8 = undefined; - return b.runAllowFail(argv, &code, .Inherit) catch |err| { - const printed_cmd = Step.allocPrintCmd(b.allocator, null, argv) catch @panic("OOM"); - std.debug.print("unable to spawn the following command: {s}\n{s}\n", .{ - @errorName(err), printed_cmd, - }); - process.exit(1); - }; + return b.runAllowFail(argv, &code, .inherit) catch |err| process.fatal( + "the following command failed with {t}:\n{s}", + .{ err, Step.allocPrintCmd(b.allocator, null, null, argv) catch @panic("OOM") }, + ); } pub fn addSearchPrefix(b: *Build, search_prefix: []const u8) void { @@ -2091,7 +2122,7 @@ pub fn dependencyFromBuildZig( } const full_path = b.pathFromRoot("build.zig.zon"); - debug.panic("'{}' is not a build.zig struct of a dependency in '{s}'", .{ build_zig, full_path }); + std.debug.panic("'{}' is not a build.zig struct of a dependency in '{s}'", .{ build_zig, full_path }); } fn userValuesAreSame(lhs: UserValue, rhs: UserValue) bool { @@ -2185,6 +2216,7 @@ fn dependencyInner( pkg_deps: AvailableDeps, args: anytype, ) *Dependency { + const io = b.graph.io; const user_input_options = userInputOptionsFromArgs(b.allocator, args); if (b.graph.dependency_cache.getContext(.{ .build_root_string = build_root_string, @@ -2194,7 +2226,7 @@ fn dependencyInner( const build_root: std.Build.Cache.Directory = .{ .path = build_root_string, - .handle = fs.cwd().openDir(build_root_string, .{}) catch |err| { + .handle = Io.Dir.cwd().openDir(io, build_root_string, .{}) catch |err| { std.debug.print("unable to open '{s}': {s}\n", .{ build_root_string, @errorName(err), }); @@ -2232,14 +2264,13 @@ pub fn runBuild(b: *Build, build_zig: anytype) anyerror!void { /// A file that is generated by a build step. /// This struct is an interface that is meant to be used with `@fieldParentPtr` to implement the actual path logic. pub const GeneratedFile = struct { - /// The step that generates the file + /// The step that generates the file. step: *Step, - /// The path to the generated file. Must be either absolute or relative to the build runner cwd. /// This value must be set in the `fn make()` of the `step` and must not be `null` afterwards. path: ?[]const u8 = null, - /// Deprecated, see `getPath2`. + /// Deprecated, see `getPath3`. pub fn getPath(gen: GeneratedFile) []const u8 { return gen.step.owner.pathFromCwd(gen.path orelse std.debug.panic( "getPath() was called on a GeneratedFile that wasn't built yet. Is there a missing Step dependency on step '{s}'?", @@ -2247,11 +2278,19 @@ pub const GeneratedFile = struct { )); } + /// Deprecated, see `getPath3`. pub fn getPath2(gen: GeneratedFile, src_builder: *Build, asking_step: ?*Step) []const u8 { + return getPath3(gen, src_builder, asking_step) catch |err| switch (err) { + error.Canceled => std.process.exit(1), + }; + } + + pub fn getPath3(gen: GeneratedFile, src_builder: *Build, asking_step: ?*Step) Io.Cancelable![]const u8 { return gen.path orelse { - const w, const ttyconf = debug.lockStderrWriter(&.{}); - dumpBadGetPathHelp(gen.step, w, ttyconf, src_builder, asking_step) catch {}; - debug.unlockStderrWriter(); + const graph = gen.step.owner.graph; + const io = graph.io; + const stderr = try io.lockStderr(&.{}, graph.stderr_mode); + dumpBadGetPathHelp(gen.step, stderr.terminal(), src_builder, asking_step) catch {}; @panic("misconfigured build script"); }; } @@ -2306,13 +2345,18 @@ pub const LazyPath = union(enum) { /// Applied after `up`. sub_path: []const u8 = "", + + /// If set, the file is hashed only on this suffix, not the full absolute path + content_hash_name: ?[]const u8 = null, }, /// An absolute path or a path relative to the current working directory of /// the build runner process. + /// /// This is uncommon but used for system environment paths such as `--zig-lib-dir` which /// ignore the file system path of build.zig and instead are relative to the directory from /// which `zig build` was invoked. + /// /// Use of this tag indicates a dependency on the host system. cwd_relative: []const u8, @@ -2426,22 +2470,29 @@ pub const LazyPath = union(enum) { } } - /// Deprecated, see `getPath3`. + /// Deprecated, see `getPath4`. pub fn getPath(lazy_path: LazyPath, src_builder: *Build) []const u8 { return getPath2(lazy_path, src_builder, null); } - /// Deprecated, see `getPath3`. + /// Deprecated, see `getPath4`. pub fn getPath2(lazy_path: LazyPath, src_builder: *Build, asking_step: ?*Step) []const u8 { const p = getPath3(lazy_path, src_builder, asking_step); return src_builder.pathResolve(&.{ p.root_dir.path orelse ".", p.sub_path }); } + /// Deprecated, see `getPath4`. + pub fn getPath3(lazy_path: LazyPath, src_builder: *Build, asking_step: ?*Step) Cache.Path { + return getPath4(lazy_path, src_builder, asking_step) catch |err| switch (err) { + error.Canceled => std.process.exit(1), + }; + } + /// Intended to be used during the make phase only. /// /// `asking_step` is only used for debugging purposes; it's the step being /// run that is asking for the path. - pub fn getPath3(lazy_path: LazyPath, src_builder: *Build, asking_step: ?*Step) Cache.Path { + pub fn getPath4(lazy_path: LazyPath, src_builder: *Build, asking_step: ?*Step) Io.Cancelable!Cache.Path { switch (lazy_path) { .src_path => |sp| return .{ .root_dir = sp.owner.build_root, @@ -2455,12 +2506,15 @@ pub const LazyPath = union(enum) { // TODO make gen.file.path not be absolute and use that as the // basis for not traversing up too many directories. + const graph = src_builder.graph; + var file_path: Cache.Path = .{ .root_dir = Cache.Directory.cwd(), .sub_path = gen.file.path orelse { - const w, const ttyconf = debug.lockStderrWriter(&.{}); - dumpBadGetPathHelp(gen.file.step, w, ttyconf, src_builder, asking_step) catch {}; - debug.unlockStderrWriter(); + const io = graph.io; + const stderr = try io.lockStderr(&.{}, graph.stderr_mode); + dumpBadGetPathHelp(gen.file.step, stderr.terminal(), src_builder, asking_step) catch {}; + io.unlockStderr(); @panic("misconfigured build script"); }, }; @@ -2495,7 +2549,9 @@ pub const LazyPath = union(enum) { } } - return file_path.join(src_builder.allocator, gen.sub_path) catch @panic("OOM"); + var item = file_path.join(src_builder.allocator, gen.sub_path) catch @panic("OOM"); + item.content_hash_name = gen.content_hash_name; + return item; }, .dependency => |dep| return .{ .root_dir = dep.dependency.builder.build_root, @@ -2535,6 +2591,7 @@ pub const LazyPath = union(enum) { .file = gen.file, .up = gen.up, .sub_path = dupePathInner(allocator, gen.sub_path), + .content_hash_name = if (gen.content_hash_name) |name| Build.dupeInner(allocator, name) else null, } }, .dependency => |dep| .{ .dependency = .{ .dependency = dep.dependency, @@ -2550,40 +2607,36 @@ fn dumpBadDirnameHelp( comptime msg: []const u8, args: anytype, ) anyerror!void { - const w, const tty_config = debug.lockStderrWriter(&.{}); - defer debug.unlockStderrWriter(); + const stderr = std.debug.lockStderr(&.{}).terminal(); + defer std.debug.unlockStderr(); + const w = stderr.writer; try w.print(msg, args); if (fail_step) |s| { - tty_config.setColor(w, .red) catch {}; + stderr.setColor(.red) catch {}; try w.writeAll(" The step was created by this stack trace:\n"); - tty_config.setColor(w, .reset) catch {}; + stderr.setColor(.reset) catch {}; - s.dump(w, tty_config); + s.dump(stderr); } if (asking_step) |as| { - tty_config.setColor(w, .red) catch {}; + stderr.setColor(.red) catch {}; try w.print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name}); - tty_config.setColor(w, .reset) catch {}; + stderr.setColor(.reset) catch {}; - as.dump(w, tty_config); + as.dump(stderr); } - tty_config.setColor(w, .red) catch {}; - try w.writeAll(" Hope that helps. Proceeding to panic.\n"); - tty_config.setColor(w, .reset) catch {}; + stderr.setColor(.red) catch {}; + try w.writeAll(" Proceeding to panic.\n"); + stderr.setColor(.reset) catch {}; } /// In this function the stderr mutex has already been locked. -pub fn dumpBadGetPathHelp( - s: *Step, - w: *std.Io.Writer, - tty_config: std.Io.tty.Config, - src_builder: *Build, - asking_step: ?*Step, -) anyerror!void { +pub fn dumpBadGetPathHelp(s: *Step, t: Io.Terminal, src_builder: *Build, asking_step: ?*Step) anyerror!void { + const w = t.writer; try w.print( \\getPath() was called on a GeneratedFile that wasn't built yet. \\ source package path: {s} @@ -2594,21 +2647,21 @@ pub fn dumpBadGetPathHelp( s.name, }); - tty_config.setColor(w, .red) catch {}; + t.setColor(.red) catch {}; try w.writeAll(" The step was created by this stack trace:\n"); - tty_config.setColor(w, .reset) catch {}; + t.setColor(.reset) catch {}; - s.dump(w, tty_config); + s.dump(t); if (asking_step) |as| { - tty_config.setColor(w, .red) catch {}; + t.setColor(.red) catch {}; try w.print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name}); - tty_config.setColor(w, .reset) catch {}; + t.setColor(.reset) catch {}; - as.dump(w, tty_config); + as.dump(t); } - tty_config.setColor(w, .red) catch {}; - try w.writeAll(" Hope that helps. Proceeding to panic.\n"); - tty_config.setColor(w, .reset) catch {}; + t.setColor(.red) catch {}; + try w.writeAll(" Proceeding to panic.\n"); + t.setColor(.reset) catch {}; } pub const InstallDir = union(enum) { @@ -2629,20 +2682,12 @@ pub const InstallDir = union(enum) { } }; -/// This function is intended to be called in the `configure` phase only. -/// It returns an absolute directory path, which is potentially going to be a -/// source of API breakage in the future, so keep that in mind when using this -/// function. -pub fn makeTempPath(b: *Build) []const u8 { - const rand_int = std.crypto.random.int(u64); - const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(rand_int); - const result_path = b.cache_root.join(b.allocator, &.{tmp_dir_sub_path}) catch @panic("OOM"); - b.cache_root.handle.makePath(tmp_dir_sub_path) catch |err| { - std.debug.print("unable to make tmp path '{s}': {s}\n", .{ - result_path, @errorName(err), - }); - }; - return result_path; +/// Creates a path leading to a directory inside "tmp" subdirectory of +/// `cache_root` which is created on demand and cleaned up by the build runner +/// upon success. +pub fn tmpPath(b: *Build) LazyPath { + const wf = b.addTempFiles(); + return wf.getDirectory(); } /// A pair of target query and fully resolved target. diff --git a/lib/std/Build/Cache.zig b/lib/std/Build/Cache.zig index e68c3e789220..638143f45b4c 100644 --- a/lib/std/Build/Cache.zig +++ b/lib/std/Build/Cache.zig @@ -8,7 +8,6 @@ const builtin = @import("builtin"); const std = @import("std"); const Io = std.Io; const crypto = std.crypto; -const fs = std.fs; const assert = std.debug.assert; const testing = std.testing; const mem = std.mem; @@ -18,7 +17,7 @@ const log = std.log.scoped(.cache); gpa: Allocator, io: Io, -manifest_dir: fs.Dir, +manifest_dir: Io.Dir, hash: HashHelper = .{}, /// This value is accessed from multiple threads, protected by mutex. recent_problematic_timestamp: Io.Timestamp = .zero, @@ -31,6 +30,8 @@ mutex: Io.Mutex = .init, /// and usefulness of the cache for advanced use cases. prefixes_buffer: [4]Directory = undefined, prefixes_len: usize = 0, +/// Used to identify prefixes. References external memory. +cwd: []const u8, pub const Path = @import("Cache/Path.zig"); pub const Directory = @import("Cache/Directory.zig"); @@ -71,7 +72,7 @@ const PrefixedPath = struct { fn findPrefix(cache: *const Cache, file_path: []const u8) !PrefixedPath { const gpa = cache.gpa; - const resolved_path = try fs.path.resolve(gpa, &.{file_path}); + const resolved_path = try std.fs.path.resolve(gpa, &.{file_path}); errdefer gpa.free(resolved_path); return findPrefixResolved(cache, resolved_path); } @@ -79,11 +80,12 @@ fn findPrefix(cache: *const Cache, file_path: []const u8) !PrefixedPath { /// Takes ownership of `resolved_path` on success. fn findPrefixResolved(cache: *const Cache, resolved_path: []u8) !PrefixedPath { const gpa = cache.gpa; + const cwd = cache.cwd; const prefixes_slice = cache.prefixes(); var i: u8 = 1; // Start at 1 to skip over checking the null prefix. while (i < prefixes_slice.len) : (i += 1) { const p = prefixes_slice[i].path.?; - const sub_path = getPrefixSubpath(gpa, p, resolved_path) catch |err| switch (err) { + const sub_path = getPrefixSubpath(gpa, cwd, p, resolved_path) catch |err| switch (err) { error.NotASubPath => continue, else => |e| return e, }; @@ -101,10 +103,10 @@ fn findPrefixResolved(cache: *const Cache, resolved_path: []u8) !PrefixedPath { }; } -fn getPrefixSubpath(allocator: Allocator, prefix: []const u8, path: []u8) ![]u8 { - const relative = try fs.path.relative(allocator, prefix, path); - errdefer allocator.free(relative); - var component_iterator = fs.path.NativeComponentIterator.init(relative); +fn getPrefixSubpath(gpa: Allocator, cwd: []const u8, prefix: []const u8, path: []u8) ![]u8 { + const relative = try std.fs.path.relative(gpa, cwd, null, prefix, path); + errdefer gpa.free(relative); + var component_iterator: std.fs.path.NativeComponentIterator = .init(relative); if (component_iterator.root() != null) { return error.NotASubPath; } @@ -123,7 +125,7 @@ pub const HexDigest = [hex_digest_len]u8; /// This is currently just an arbitrary non-empty string that can't match another manifest line. const manifest_header = "0"; -const manifest_file_size_max = 100 * 1024 * 1024; +pub const manifest_file_size_max = 100 * 1024 * 1024; /// The type used for hashing file contents. Currently, this is SipHash128(1, 3), because it /// provides enough collision resistance for the Manifest use cases, while being one of our @@ -145,17 +147,17 @@ pub const File = struct { max_file_size: ?usize, /// Populated if the user calls `addOpenedFile`. /// The handle is not owned here. - handle: ?fs.File, + handle: ?Io.File, stat: Stat, bin_digest: BinDigest, contents: ?[]const u8, pub const Stat = struct { - inode: fs.File.INode, + inode: Io.File.INode, size: u64, mtime: Io.Timestamp, - pub fn fromFs(fs_stat: fs.File.Stat) Stat { + pub fn fromFs(fs_stat: Io.File.Stat) Stat { return .{ .inode = fs_stat.inode, .size = fs_stat.size, @@ -178,7 +180,7 @@ pub const File = struct { file.max_file_size = if (file.max_file_size) |old| @max(old, new) else new; } - pub fn updateHandle(file: *File, new_handle: ?fs.File) void { + pub fn updateHandle(file: *File, new_handle: ?Io.File) void { const handle = new_handle orelse return; file.handle = handle; } @@ -293,16 +295,16 @@ pub fn binToHex(bin_digest: BinDigest) HexDigest { } pub const Lock = struct { - manifest_file: fs.File, + manifest_file: Io.File, - pub fn release(lock: *Lock) void { + pub fn release(lock: *Lock, io: Io) void { if (builtin.os.tag == .windows) { // Windows does not guarantee that locks are immediately unlocked when // the file handle is closed. See LockFileEx documentation. - lock.manifest_file.unlock(); + lock.manifest_file.unlock(io); } - lock.manifest_file.close(); + lock.manifest_file.close(io); lock.* = undefined; } }; @@ -311,7 +313,7 @@ pub const Manifest = struct { cache: *Cache, /// Current state for incremental hashing. hash: HashHelper, - manifest_file: ?fs.File, + manifest_file: ?Io.File, manifest_dirty: bool, /// Set this flag to true before calling hit() in order to indicate that /// upon a cache hit, the code using the cache will not modify the files @@ -332,9 +334,9 @@ pub const Manifest = struct { pub const Diagnostic = union(enum) { none, - manifest_create: fs.File.OpenError, - manifest_read: fs.File.ReadError, - manifest_lock: fs.File.LockError, + manifest_create: Io.File.OpenError, + manifest_read: Io.File.Reader.Error, + manifest_lock: Io.File.LockError, file_open: FileOp, file_stat: FileOp, file_read: FileOp, @@ -393,16 +395,16 @@ pub const Manifest = struct { } /// Same as `addFilePath` except the file has already been opened. - pub fn addOpenedFile(m: *Manifest, path: Path, handle: ?fs.File, max_file_size: ?usize) !usize { + pub fn addOpenedFile(m: *Manifest, path: Path, handle: ?Io.File, max_file_size: ?usize) !usize { const gpa = m.cache.gpa; try m.files.ensureUnusedCapacity(gpa, 1); - const resolved_path = try fs.path.resolve(gpa, &.{ + const resolved_path = try std.fs.path.resolve(gpa, &.{ path.root_dir.path orelse ".", path.subPathOrDot(), }); errdefer gpa.free(resolved_path); const prefixed_path = try m.cache.findPrefixResolved(resolved_path); - return addFileInner(m, prefixed_path, handle, max_file_size); + return addFileInner(m, prefixed_path, handle, max_file_size, path.content_hash_name); } /// Deprecated; use `addFilePath`. @@ -414,10 +416,10 @@ pub const Manifest = struct { const prefixed_path = try self.cache.findPrefix(file_path); errdefer gpa.free(prefixed_path.sub_path); - return addFileInner(self, prefixed_path, null, max_file_size); + return addFileInner(self, prefixed_path, null, max_file_size, null); } - fn addFileInner(self: *Manifest, prefixed_path: PrefixedPath, handle: ?fs.File, max_file_size: ?usize) usize { + fn addFileInner(self: *Manifest, prefixed_path: PrefixedPath, handle: ?Io.File, max_file_size: ?usize, content_hash_name: ?[]const u8) usize { const gop = self.files.getOrPutAssumeCapacityAdapted(prefixed_path, FilesAdapter{}); if (gop.found_existing) { self.cache.gpa.free(prefixed_path.sub_path); @@ -434,8 +436,13 @@ pub const Manifest = struct { .handle = handle, }; - self.hash.add(prefixed_path.prefix); - self.hash.addBytes(prefixed_path.sub_path); + if (content_hash_name) |name| { + self.hash.add(@as(u8, '?')); + self.hash.addBytes(name); + } else { + self.hash.add(prefixed_path.prefix); + self.hash.addBytes(prefixed_path.sub_path); + } return gop.index; } @@ -460,7 +467,7 @@ pub const Manifest = struct { } } - pub fn addDepFile(self: *Manifest, dir: fs.Dir, dep_file_sub_path: []const u8) !void { + pub fn addDepFile(self: *Manifest, dir: Io.Dir, dep_file_sub_path: []const u8) !void { assert(self.manifest_file == null); return self.addDepFileMaybePost(dir, dep_file_sub_path); } @@ -503,11 +510,13 @@ pub const Manifest = struct { @memcpy(manifest_file_path[0..self.hex_digest.len], &self.hex_digest); manifest_file_path[hex_digest_len..][0..ext.len].* = ext.*; + const io = self.cache.io; + // We'll try to open the cache with an exclusive lock, but if that would block // and `want_shared_lock` is set, a shared lock might be sufficient, so we'll // open with a shared lock instead. while (true) { - if (self.cache.manifest_dir.createFile(&manifest_file_path, .{ + if (self.cache.manifest_dir.createFile(io, &manifest_file_path, .{ .read = true, .truncate = false, .lock = .exclusive, @@ -518,7 +527,7 @@ pub const Manifest = struct { break; } else |err| switch (err) { error.WouldBlock => { - self.manifest_file = self.cache.manifest_dir.openFile(&manifest_file_path, .{ + self.manifest_file = self.cache.manifest_dir.openFile(io, &manifest_file_path, .{ .mode = .read_write, .lock = .shared, }) catch |e| { @@ -542,7 +551,7 @@ pub const Manifest = struct { return error.CacheCheckFailed; } - if (self.cache.manifest_dir.createFile(&manifest_file_path, .{ + if (self.cache.manifest_dir.createFile(io, &manifest_file_path, .{ .read = true, .truncate = false, .lock = .exclusive, @@ -702,7 +711,7 @@ pub const Manifest = struct { const file_path = iter.rest(); const stat_size = fmt.parseInt(u64, size, 10) catch return error.InvalidFormat; - const stat_inode = fmt.parseInt(fs.File.INode, inode, 10) catch return error.InvalidFormat; + const stat_inode = fmt.parseInt(Io.File.INode, inode, 10) catch return error.InvalidFormat; const stat_mtime = fmt.parseInt(i64, mtime_nsec_str, 10) catch return error.InvalidFormat; const file_bin_digest = b: { if (digest_str.len != hex_digest_len) return error.InvalidFormat; @@ -716,15 +725,13 @@ pub const Manifest = struct { if (file_path.len == 0) return error.InvalidFormat; + const prefixed_path: PrefixedPath = .{ + .prefix = prefix, + .sub_path = file_path, // expires with file_contents + }; const cache_hash_file = f: { - const prefixed_path: PrefixedPath = .{ - .prefix = prefix, - .sub_path = file_path, // expires with file_contents - }; if (idx < input_file_count) { const file = &self.files.keys()[idx]; - if (!file.prefixed_path.eql(prefixed_path)) - return error.InvalidFormat; file.stat = .{ .size = stat_size, @@ -758,7 +765,7 @@ pub const Manifest = struct { const pp = cache_hash_file.prefixed_path; const dir = self.cache.prefixes()[pp.prefix].handle; - const this_file = dir.openFile(pp.sub_path, .{ .mode = .read_only }) catch |err| switch (err) { + const this_file = dir.openFile(io, pp.sub_path, .{ .mode = .read_only }) catch |err| switch (err) { error.FileNotFound => { // Every digest before this one has been populated successfully. return .{ .miss = .{ .file_digests_populated = idx } }; @@ -772,20 +779,22 @@ pub const Manifest = struct { return error.CacheCheckFailed; }, }; - defer this_file.close(); + defer this_file.close(io); - const actual_stat = this_file.stat() catch |err| { + const actual_stat = this_file.stat(io) catch |err| { self.diagnostic = .{ .file_stat = .{ .file_index = idx, .err = err, } }; return error.CacheCheckFailed; }; + + const name_match = pp.eql(prefixed_path); const size_match = actual_stat.size == cache_hash_file.stat.size; const mtime_match = actual_stat.mtime.nanoseconds == cache_hash_file.stat.mtime.nanoseconds; const inode_match = actual_stat.inode == cache_hash_file.stat.inode; - if (!size_match or !mtime_match or !inode_match) { + if (!name_match or !size_match or !mtime_match or !inode_match) { cache_hash_file.stat = .{ .size = actual_stat.size, .mtime = actual_stat.mtime, @@ -799,7 +808,7 @@ pub const Manifest = struct { } var actual_digest: BinDigest = undefined; - hashFile(this_file, &actual_digest) catch |err| { + hashFile(io, this_file, &actual_digest) catch |err| { self.diagnostic = .{ .file_read = .{ .file_index = idx, .err = err, @@ -872,17 +881,17 @@ pub const Manifest = struct { if (man.want_refresh_timestamp) { man.want_refresh_timestamp = false; - var file = man.cache.manifest_dir.createFile("timestamp", .{ + var file = man.cache.manifest_dir.createFile(io, "timestamp", .{ .read = true, .truncate = true, }) catch |err| switch (err) { error.Canceled => return error.Canceled, else => return true, }; - defer file.close(); + defer file.close(io); // Save locally and also save globally (we still hold the global lock). - const stat = file.stat() catch |err| switch (err) { + const stat = file.stat(io) catch |err| switch (err) { error.Canceled => return error.Canceled, else => return true, }; @@ -894,19 +903,24 @@ pub const Manifest = struct { } fn populateFileHash(self: *Manifest, ch_file: *File) !void { + const io = self.cache.io; + if (ch_file.handle) |handle| { return populateFileHashHandle(self, ch_file, handle); } else { const pp = ch_file.prefixed_path; const dir = self.cache.prefixes()[pp.prefix].handle; - const handle = try dir.openFile(pp.sub_path, .{}); - defer handle.close(); + const handle = try dir.openFile(io, pp.sub_path, .{}); + defer handle.close(io); return populateFileHashHandle(self, ch_file, handle); } } - fn populateFileHashHandle(self: *Manifest, ch_file: *File, handle: fs.File) !void { - const actual_stat = try handle.stat(); + fn populateFileHashHandle(self: *Manifest, ch_file: *File, io_file: Io.File) !void { + const io = self.cache.io; + const gpa = self.cache.gpa; + + const actual_stat = try io_file.stat(io); ch_file.stat = .{ .size = actual_stat.size, .mtime = actual_stat.mtime, @@ -920,19 +934,17 @@ pub const Manifest = struct { } if (ch_file.max_file_size) |max_file_size| { - if (ch_file.stat.size > max_file_size) { - return error.FileTooBig; - } + if (ch_file.stat.size > max_file_size) return error.FileTooBig; - const contents = try self.cache.gpa.alloc(u8, @as(usize, @intCast(ch_file.stat.size))); - errdefer self.cache.gpa.free(contents); + // Hash while reading from disk, to keep the contents in the cpu + // cache while doing hashing. + const contents = try gpa.alloc(u8, @intCast(ch_file.stat.size)); + errdefer gpa.free(contents); - // Hash while reading from disk, to keep the contents in the cpu cache while - // doing hashing. var hasher = hasher_init; var off: usize = 0; while (true) { - const bytes_read = try handle.pread(contents[off..], off); + const bytes_read = try io_file.readPositional(io, &.{contents[off..]}, off); if (bytes_read == 0) break; hasher.update(contents[off..][0..bytes_read]); off += bytes_read; @@ -941,7 +953,7 @@ pub const Manifest = struct { ch_file.contents = contents; } else { - try hashFile(handle, &ch_file.bin_digest); + try hashFile(io, io_file, &ch_file.bin_digest); } self.hash.hasher.update(&ch_file.bin_digest); @@ -1064,14 +1076,15 @@ pub const Manifest = struct { self.hash.hasher.update(&new_file.bin_digest); } - pub fn addDepFilePost(self: *Manifest, dir: fs.Dir, dep_file_sub_path: []const u8) !void { + pub fn addDepFilePost(self: *Manifest, dir: Io.Dir, dep_file_sub_path: []const u8) !void { assert(self.manifest_file != null); return self.addDepFileMaybePost(dir, dep_file_sub_path); } - fn addDepFileMaybePost(self: *Manifest, dir: fs.Dir, dep_file_sub_path: []const u8) !void { + fn addDepFileMaybePost(self: *Manifest, dir: Io.Dir, dep_file_sub_path: []const u8) !void { const gpa = self.cache.gpa; - const dep_file_contents = try dir.readFileAlloc(dep_file_sub_path, gpa, .limited(manifest_file_size_max)); + const io = self.cache.io; + const dep_file_contents = try dir.readFileAlloc(io, dep_file_sub_path, gpa, .limited(manifest_file_size_max)); defer gpa.free(dep_file_contents); var error_buf: std.ArrayList(u8) = .empty; @@ -1130,13 +1143,13 @@ pub const Manifest = struct { /// lock from exclusive to shared. pub fn writeManifest(self: *Manifest) !void { assert(self.have_exclusive_lock); - + const io = self.cache.io; const manifest_file = self.manifest_file.?; if (self.manifest_dirty) { self.manifest_dirty = false; var buffer: [4000]u8 = undefined; - var fw = manifest_file.writer(&buffer); + var fw = manifest_file.writer(io, &buffer); writeDirtyManifestToStream(self, &fw) catch |err| switch (err) { error.WriteFailed => return fw.err.?, else => |e| return e, @@ -1148,7 +1161,7 @@ pub const Manifest = struct { } } - fn writeDirtyManifestToStream(self: *Manifest, fw: *fs.File.Writer) !void { + fn writeDirtyManifestToStream(self: *Manifest, fw: *Io.File.Writer) !void { try fw.interface.writeAll(manifest_header ++ "\n"); for (self.files.keys()) |file| { try fw.interface.print("{d} {d} {d} {x} {d} {s}\n", .{ @@ -1165,13 +1178,11 @@ pub const Manifest = struct { fn downgradeToSharedLock(self: *Manifest) !void { if (!self.have_exclusive_lock) return; + const io = self.cache.io; - // WASI does not currently support flock, so we bypass it here. - // TODO: If/when flock is supported on WASI, this check should be removed. - // See https://github.com/WebAssembly/wasi-filesystem/issues/2 - if (builtin.os.tag != .wasi or std.process.can_spawn or !builtin.single_threaded) { + if (std.process.can_spawn or !builtin.single_threaded) { const manifest_file = self.manifest_file.?; - try manifest_file.downgradeLock(); + try manifest_file.downgradeLock(io); } self.have_exclusive_lock = false; @@ -1180,16 +1191,14 @@ pub const Manifest = struct { fn upgradeToExclusiveLock(self: *Manifest) error{CacheCheckFailed}!bool { if (self.have_exclusive_lock) return false; assert(self.manifest_file != null); + const io = self.cache.io; - // WASI does not currently support flock, so we bypass it here. - // TODO: If/when flock is supported on WASI, this check should be removed. - // See https://github.com/WebAssembly/wasi-filesystem/issues/2 - if (builtin.os.tag != .wasi or std.process.can_spawn or !builtin.single_threaded) { + if (std.process.can_spawn or !builtin.single_threaded) { const manifest_file = self.manifest_file.?; // Here we intentionally have a period where the lock is released, in case there are // other processes holding a shared lock. - manifest_file.unlock(); - manifest_file.lock(.exclusive) catch |err| { + manifest_file.unlock(io); + manifest_file.lock(io, .exclusive) catch |err| { self.diagnostic = .{ .manifest_lock = err }; return error.CacheCheckFailed; }; @@ -1202,25 +1211,23 @@ pub const Manifest = struct { /// The `Manifest` remains safe to deinit. /// Don't forget to call `writeManifest` before this! pub fn toOwnedLock(self: *Manifest) Lock { - const lock: Lock = .{ - .manifest_file = self.manifest_file.?, - }; - - self.manifest_file = null; - return lock; + defer self.manifest_file = null; + return .{ .manifest_file = self.manifest_file.? }; } /// Releases the manifest file and frees any memory the Manifest was using. /// `Manifest.hit` must be called first. /// Don't forget to call `writeManifest` before this! pub fn deinit(self: *Manifest) void { + const io = self.cache.io; + if (self.manifest_file) |file| { if (builtin.os.tag == .windows) { // See Lock.release for why this is required on Windows - file.unlock(); + file.unlock(io); } - file.close(); + file.close(io); } for (self.files.keys()) |*file| { file.deinit(self.cache.gpa); @@ -1278,73 +1285,52 @@ pub const Manifest = struct { } }; -/// On operating systems that support symlinks, does a readlink. On other operating systems, -/// uses the file contents. Windows supports symlinks but only with elevated privileges, so -/// it is treated as not supporting symlinks. -pub fn readSmallFile(dir: fs.Dir, sub_path: []const u8, buffer: []u8) ![]u8 { - if (builtin.os.tag == .windows) { - return dir.readFile(sub_path, buffer); - } else { - return dir.readLink(sub_path, buffer); - } -} - -/// On operating systems that support symlinks, does a symlink. On other operating systems, -/// uses the file contents. Windows supports symlinks but only with elevated privileges, so -/// it is treated as not supporting symlinks. -/// `data` must be a valid UTF-8 encoded file path and 255 bytes or fewer. -pub fn writeSmallFile(dir: fs.Dir, sub_path: []const u8, data: []const u8) !void { - assert(data.len <= 255); - if (builtin.os.tag == .windows) { - return dir.writeFile(.{ .sub_path = sub_path, .data = data }); - } else { - return dir.symLink(data, sub_path, .{}); - } -} - -fn hashFile(file: fs.File, bin_digest: *[Hasher.mac_length]u8) fs.File.PReadError!void { - var buf: [1024]u8 = undefined; +fn hashFile(io: Io, file: Io.File, bin_digest: *[Hasher.mac_length]u8) Io.File.ReadPositionalError!void { + var buffer: [2048]u8 = undefined; var hasher = hasher_init; - var off: u64 = 0; + var offset: u64 = 0; while (true) { - const bytes_read = try file.pread(&buf, off); - if (bytes_read == 0) break; - hasher.update(buf[0..bytes_read]); - off += bytes_read; + const n = try file.readPositional(io, &.{&buffer}, offset); + if (n == 0) break; + hasher.update(buffer[0..n]); + offset += n; } hasher.final(bin_digest); } // Create/Write a file, close it, then grab its stat.mtime timestamp. -fn testGetCurrentFileTimestamp(dir: fs.Dir) !Io.Timestamp { +fn testGetCurrentFileTimestamp(io: Io, dir: Io.Dir) !Io.Timestamp { const test_out_file = "test-filetimestamp.tmp"; - var file = try dir.createFile(test_out_file, .{ + var file = try dir.createFile(io, test_out_file, .{ .read = true, .truncate = true, }); defer { - file.close(); - dir.deleteFile(test_out_file) catch {}; + file.close(io); + dir.deleteFile(io, test_out_file) catch {}; } - return (try file.stat()).mtime; + return (try file.stat(io)).mtime; } test "cache file and then recall it" { - const io = std.testing.io; + const io = testing.io; var tmp = testing.tmpDir(.{}); defer tmp.cleanup(); + const cwd = try std.process.getCwdAlloc(testing.allocator); + defer testing.allocator.free(cwd); + const temp_file = "test.txt"; const temp_manifest_dir = "temp_manifest_dir"; - try tmp.dir.writeFile(.{ .sub_path = temp_file, .data = "Hello, world!\n" }); + try tmp.dir.writeFile(io, .{ .sub_path = temp_file, .data = "Hello, world!\n" }); // Wait for file timestamps to tick - const initial_time = try testGetCurrentFileTimestamp(tmp.dir); - while ((try testGetCurrentFileTimestamp(tmp.dir)).nanoseconds == initial_time.nanoseconds) { + const initial_time = try testGetCurrentFileTimestamp(io, tmp.dir); + while ((try testGetCurrentFileTimestamp(io, tmp.dir)).nanoseconds == initial_time.nanoseconds) { try std.Io.Clock.Duration.sleep(.{ .clock = .boot, .raw = .fromNanoseconds(1) }, io); } @@ -1355,10 +1341,11 @@ test "cache file and then recall it" { var cache: Cache = .{ .io = io, .gpa = testing.allocator, - .manifest_dir = try tmp.dir.makeOpenPath(temp_manifest_dir, .{}), + .manifest_dir = try tmp.dir.createDirPathOpen(io, temp_manifest_dir, .{}), + .cwd = cwd, }; cache.addPrefix(.{ .path = null, .handle = tmp.dir }); - defer cache.manifest_dir.close(); + defer cache.manifest_dir.close(io); { var ch = cache.obtain(); @@ -1396,21 +1383,24 @@ test "cache file and then recall it" { } test "check that changing a file makes cache fail" { - const io = std.testing.io; + const io = testing.io; var tmp = testing.tmpDir(.{}); defer tmp.cleanup(); + const cwd = try std.process.getCwdAlloc(testing.allocator); + defer testing.allocator.free(cwd); + const temp_file = "cache_hash_change_file_test.txt"; const temp_manifest_dir = "cache_hash_change_file_manifest_dir"; const original_temp_file_contents = "Hello, world!\n"; const updated_temp_file_contents = "Hello, world; but updated!\n"; - try tmp.dir.writeFile(.{ .sub_path = temp_file, .data = original_temp_file_contents }); + try tmp.dir.writeFile(io, .{ .sub_path = temp_file, .data = original_temp_file_contents }); // Wait for file timestamps to tick - const initial_time = try testGetCurrentFileTimestamp(tmp.dir); - while ((try testGetCurrentFileTimestamp(tmp.dir)).nanoseconds == initial_time.nanoseconds) { + const initial_time = try testGetCurrentFileTimestamp(io, tmp.dir); + while ((try testGetCurrentFileTimestamp(io, tmp.dir)).nanoseconds == initial_time.nanoseconds) { try std.Io.Clock.Duration.sleep(.{ .clock = .boot, .raw = .fromNanoseconds(1) }, io); } @@ -1421,10 +1411,11 @@ test "check that changing a file makes cache fail" { var cache: Cache = .{ .io = io, .gpa = testing.allocator, - .manifest_dir = try tmp.dir.makeOpenPath(temp_manifest_dir, .{}), + .manifest_dir = try tmp.dir.createDirPathOpen(io, temp_manifest_dir, .{}), + .cwd = cwd, }; cache.addPrefix(.{ .path = null, .handle = tmp.dir }); - defer cache.manifest_dir.close(); + defer cache.manifest_dir.close(io); { var ch = cache.obtain(); @@ -1443,7 +1434,7 @@ test "check that changing a file makes cache fail" { try ch.writeManifest(); } - try tmp.dir.writeFile(.{ .sub_path = temp_file, .data = updated_temp_file_contents }); + try tmp.dir.writeFile(io, .{ .sub_path = temp_file, .data = updated_temp_file_contents }); { var ch = cache.obtain(); @@ -1473,6 +1464,9 @@ test "no file inputs" { var tmp = testing.tmpDir(.{}); defer tmp.cleanup(); + const cwd = try std.process.getCwdAlloc(testing.allocator); + defer testing.allocator.free(cwd); + const temp_manifest_dir = "no_file_inputs_manifest_dir"; var digest1: HexDigest = undefined; @@ -1481,10 +1475,11 @@ test "no file inputs" { var cache: Cache = .{ .io = io, .gpa = testing.allocator, - .manifest_dir = try tmp.dir.makeOpenPath(temp_manifest_dir, .{}), + .manifest_dir = try tmp.dir.createDirPathOpen(io, temp_manifest_dir, .{}), + .cwd = cwd, }; cache.addPrefix(.{ .path = null, .handle = tmp.dir }); - defer cache.manifest_dir.close(); + defer cache.manifest_dir.close(io); { var man = cache.obtain(); @@ -1514,21 +1509,24 @@ test "no file inputs" { } test "Manifest with files added after initial hash work" { - const io = std.testing.io; + const io = testing.io; var tmp = testing.tmpDir(.{}); defer tmp.cleanup(); + const cwd = try std.process.getCwdAlloc(testing.allocator); + defer testing.allocator.free(cwd); + const temp_file1 = "cache_hash_post_file_test1.txt"; const temp_file2 = "cache_hash_post_file_test2.txt"; const temp_manifest_dir = "cache_hash_post_file_manifest_dir"; - try tmp.dir.writeFile(.{ .sub_path = temp_file1, .data = "Hello, world!\n" }); - try tmp.dir.writeFile(.{ .sub_path = temp_file2, .data = "Hello world the second!\n" }); + try tmp.dir.writeFile(io, .{ .sub_path = temp_file1, .data = "Hello, world!\n" }); + try tmp.dir.writeFile(io, .{ .sub_path = temp_file2, .data = "Hello world the second!\n" }); // Wait for file timestamps to tick - const initial_time = try testGetCurrentFileTimestamp(tmp.dir); - while ((try testGetCurrentFileTimestamp(tmp.dir)).nanoseconds == initial_time.nanoseconds) { + const initial_time = try testGetCurrentFileTimestamp(io, tmp.dir); + while ((try testGetCurrentFileTimestamp(io, tmp.dir)).nanoseconds == initial_time.nanoseconds) { try std.Io.Clock.Duration.sleep(.{ .clock = .boot, .raw = .fromNanoseconds(1) }, io); } @@ -1540,10 +1538,11 @@ test "Manifest with files added after initial hash work" { var cache: Cache = .{ .io = io, .gpa = testing.allocator, - .manifest_dir = try tmp.dir.makeOpenPath(temp_manifest_dir, .{}), + .manifest_dir = try tmp.dir.createDirPathOpen(io, temp_manifest_dir, .{}), + .cwd = cwd, }; cache.addPrefix(.{ .path = null, .handle = tmp.dir }); - defer cache.manifest_dir.close(); + defer cache.manifest_dir.close(io); { var ch = cache.obtain(); @@ -1575,11 +1574,11 @@ test "Manifest with files added after initial hash work" { try testing.expect(mem.eql(u8, &digest1, &digest2)); // Modify the file added after initial hash - try tmp.dir.writeFile(.{ .sub_path = temp_file2, .data = "Hello world the second, updated\n" }); + try tmp.dir.writeFile(io, .{ .sub_path = temp_file2, .data = "Hello world the second, updated\n" }); // Wait for file timestamps to tick - const initial_time2 = try testGetCurrentFileTimestamp(tmp.dir); - while ((try testGetCurrentFileTimestamp(tmp.dir)).nanoseconds == initial_time2.nanoseconds) { + const initial_time2 = try testGetCurrentFileTimestamp(io, tmp.dir); + while ((try testGetCurrentFileTimestamp(io, tmp.dir)).nanoseconds == initial_time2.nanoseconds) { try std.Io.Clock.Duration.sleep(.{ .clock = .boot, .raw = .fromNanoseconds(1) }, io); } diff --git a/lib/std/Build/Cache/Directory.zig b/lib/std/Build/Cache/Directory.zig index a105a91ed6ec..ce5f5b02bbc5 100644 --- a/lib/std/Build/Cache/Directory.zig +++ b/lib/std/Build/Cache/Directory.zig @@ -1,7 +1,9 @@ const Directory = @This(); + const std = @import("../../std.zig"); -const assert = std.debug.assert; +const Io = std.Io; const fs = std.fs; +const assert = std.debug.assert; const fmt = std.fmt; const Allocator = std.mem.Allocator; @@ -9,7 +11,7 @@ const Allocator = std.mem.Allocator; /// directly, but it is needed when passing the directory to a child process. /// `null` means cwd. path: ?[]const u8, -handle: fs.Dir, +handle: Io.Dir, pub fn clone(d: Directory, arena: Allocator) Allocator.Error!Directory { return .{ @@ -21,7 +23,7 @@ pub fn clone(d: Directory, arena: Allocator) Allocator.Error!Directory { pub fn cwd() Directory { return .{ .path = null, - .handle = fs.cwd(), + .handle = .cwd(), }; } @@ -50,8 +52,8 @@ pub fn joinZ(self: Directory, allocator: Allocator, paths: []const []const u8) ! /// Whether or not the handle should be closed, or the path should be freed /// is determined by usage, however this function is provided for convenience /// if it happens to be what the caller needs. -pub fn closeAndFree(self: *Directory, gpa: Allocator) void { - self.handle.close(); +pub fn closeAndFree(self: *Directory, gpa: Allocator, io: Io) void { + self.handle.close(io); if (self.path) |p| gpa.free(p); self.* = undefined; } @@ -64,5 +66,5 @@ pub fn format(self: Directory, writer: *std.Io.Writer) std.Io.Writer.Error!void } pub fn eql(self: Directory, other: Directory) bool { - return self.handle.fd == other.handle.fd; + return self.handle.handle == other.handle.handle; } diff --git a/lib/std/Build/Cache/Path.zig b/lib/std/Build/Cache/Path.zig index 92290cfdf4d3..2794653b62d2 100644 --- a/lib/std/Build/Cache/Path.zig +++ b/lib/std/Build/Cache/Path.zig @@ -2,8 +2,8 @@ const Path = @This(); const std = @import("../../std.zig"); const Io = std.Io; -const assert = std.debug.assert; const fs = std.fs; +const assert = std.debug.assert; const Allocator = std.mem.Allocator; const Cache = std.Build.Cache; @@ -11,11 +11,13 @@ root_dir: Cache.Directory, /// The path, relative to the root dir, that this `Path` represents. /// Empty string means the root_dir is the path. sub_path: []const u8 = "", +content_hash_name: ?[]const u8 = null, pub fn clone(p: Path, arena: Allocator) Allocator.Error!Path { return .{ .root_dir = try p.root_dir.clone(arena), .sub_path = try arena.dupe(u8, p.sub_path), + .content_hash_name = if (p.content_hash_name) |name| try arena.dupe(u8, name) else null, }; } @@ -59,58 +61,56 @@ pub fn joinStringZ(p: Path, gpa: Allocator, sub_path: []const u8) Allocator.Erro return p.root_dir.joinZ(gpa, parts); } -pub fn openFile( - p: Path, - sub_path: []const u8, - flags: fs.File.OpenFlags, -) !fs.File { +pub fn openFile(p: Path, io: Io, sub_path: []const u8, flags: Io.File.OpenFlags) !Io.File { var buf: [fs.max_path_bytes]u8 = undefined; const joined_path = if (p.sub_path.len == 0) sub_path else p: { break :p std.fmt.bufPrint(&buf, "{s}" ++ fs.path.sep_str ++ "{s}", .{ p.sub_path, sub_path, }) catch return error.NameTooLong; }; - return p.root_dir.handle.openFile(joined_path, flags); + return p.root_dir.handle.openFile(io, joined_path, flags); } pub fn openDir( p: Path, + io: Io, sub_path: []const u8, - args: fs.Dir.OpenOptions, -) fs.Dir.OpenError!fs.Dir { + args: Io.Dir.OpenOptions, +) Io.Dir.OpenError!Io.Dir { var buf: [fs.max_path_bytes]u8 = undefined; const joined_path = if (p.sub_path.len == 0) sub_path else p: { break :p std.fmt.bufPrint(&buf, "{s}" ++ fs.path.sep_str ++ "{s}", .{ p.sub_path, sub_path, }) catch return error.NameTooLong; }; - return p.root_dir.handle.openDir(joined_path, args); + return p.root_dir.handle.openDir(io, joined_path, args); } -pub fn makeOpenPath(p: Path, sub_path: []const u8, opts: fs.Dir.OpenOptions) !fs.Dir { +pub fn createDirPathOpen(p: Path, io: Io, sub_path: []const u8, opts: Io.Dir.OpenOptions) !Io.Dir { var buf: [fs.max_path_bytes]u8 = undefined; const joined_path = if (p.sub_path.len == 0) sub_path else p: { break :p std.fmt.bufPrint(&buf, "{s}" ++ fs.path.sep_str ++ "{s}", .{ p.sub_path, sub_path, }) catch return error.NameTooLong; }; - return p.root_dir.handle.makeOpenPath(joined_path, opts); + return p.root_dir.handle.createDirPathOpen(io, joined_path, opts); } -pub fn statFile(p: Path, sub_path: []const u8) !fs.Dir.Stat { +pub fn statFile(p: Path, io: Io, sub_path: []const u8) !Io.Dir.Stat { var buf: [fs.max_path_bytes]u8 = undefined; const joined_path = if (p.sub_path.len == 0) sub_path else p: { break :p std.fmt.bufPrint(&buf, "{s}" ++ fs.path.sep_str ++ "{s}", .{ p.sub_path, sub_path, }) catch return error.NameTooLong; }; - return p.root_dir.handle.statFile(joined_path); + return p.root_dir.handle.statFile(io, joined_path, .{}); } pub fn atomicFile( p: Path, + io: Io, sub_path: []const u8, - options: fs.Dir.AtomicFileOptions, + options: Io.Dir.AtomicFileOptions, buf: *[fs.max_path_bytes]u8, ) !fs.AtomicFile { const joined_path = if (p.sub_path.len == 0) sub_path else p: { @@ -118,27 +118,27 @@ pub fn atomicFile( p.sub_path, sub_path, }) catch return error.NameTooLong; }; - return p.root_dir.handle.atomicFile(joined_path, options); + return p.root_dir.handle.atomicFile(io, joined_path, options); } -pub fn access(p: Path, sub_path: []const u8, flags: Io.Dir.AccessOptions) !void { +pub fn access(p: Path, io: Io, sub_path: []const u8, flags: Io.Dir.AccessOptions) !void { var buf: [fs.max_path_bytes]u8 = undefined; const joined_path = if (p.sub_path.len == 0) sub_path else p: { break :p std.fmt.bufPrint(&buf, "{s}" ++ fs.path.sep_str ++ "{s}", .{ p.sub_path, sub_path, }) catch return error.NameTooLong; }; - return p.root_dir.handle.access(joined_path, flags); + return p.root_dir.handle.access(io, joined_path, flags); } -pub fn makePath(p: Path, sub_path: []const u8) !void { +pub fn createDirPath(p: Path, io: Io, sub_path: []const u8) !void { var buf: [fs.max_path_bytes]u8 = undefined; const joined_path = if (p.sub_path.len == 0) sub_path else p: { break :p std.fmt.bufPrint(&buf, "{s}" ++ fs.path.sep_str ++ "{s}", .{ p.sub_path, sub_path, }) catch return error.NameTooLong; }; - return p.root_dir.handle.makePath(joined_path); + return p.root_dir.handle.createDirPath(io, joined_path); } pub fn toString(p: Path, allocator: Allocator) Allocator.Error![]u8 { @@ -180,7 +180,7 @@ pub fn formatEscapeChar(path: Path, writer: *Io.Writer) Io.Writer.Error!void { } pub fn format(self: Path, writer: *Io.Writer) Io.Writer.Error!void { - if (std.fs.path.isAbsolute(self.sub_path)) { + if (fs.path.isAbsolute(self.sub_path)) { try writer.writeAll(self.sub_path); return; } @@ -225,9 +225,9 @@ pub const TableAdapter = struct { pub fn hash(self: TableAdapter, a: Cache.Path) u32 { _ = self; - const seed = switch (@typeInfo(@TypeOf(a.root_dir.handle.fd))) { - .pointer => @intFromPtr(a.root_dir.handle.fd), - .int => @as(u32, @bitCast(a.root_dir.handle.fd)), + const seed = switch (@typeInfo(@TypeOf(a.root_dir.handle.handle))) { + .pointer => @intFromPtr(a.root_dir.handle.handle), + .int => @as(u32, @bitCast(a.root_dir.handle.handle)), else => @compileError("unimplemented hash function"), }; return @truncate(Hash.hash(seed, a.sub_path)); diff --git a/lib/std/Build/Fuzz.zig b/lib/std/Build/Fuzz.zig index bb4a960a7307..30e6e81241f0 100644 --- a/lib/std/Build/Fuzz.zig +++ b/lib/std/Build/Fuzz.zig @@ -9,14 +9,12 @@ const Allocator = std.mem.Allocator; const log = std.log; const Coverage = std.debug.Coverage; const abi = Build.abi.fuzz; -const tty = std.Io.tty; const Fuzz = @This(); const build_runner = @import("root"); gpa: Allocator, io: Io, -ttyconf: tty.Config, mode: Mode, /// Allocated into `gpa`. @@ -77,11 +75,10 @@ const CoverageMap = struct { pub fn init( gpa: Allocator, io: Io, - ttyconf: tty.Config, all_steps: []const *Build.Step, root_prog_node: std.Progress.Node, mode: Mode, -) Allocator.Error!Fuzz { +) error{ OutOfMemory, Canceled }!Fuzz { const run_steps: []const *Step.Run = steps: { var steps: std.ArrayList(*Step.Run) = .empty; defer steps.deinit(gpa); @@ -95,13 +92,13 @@ pub fn init( if (run.producer == null) continue; if (run.fuzz_tests.items.len == 0) continue; try steps.append(gpa, run); - rebuild_group.async(io, rebuildTestsWorkerRun, .{ run, gpa, ttyconf, rebuild_node }); + rebuild_group.async(io, rebuildTestsWorkerRun, .{ run, gpa, rebuild_node }); } if (steps.items.len == 0) fatal("no fuzz tests found", .{}); rebuild_node.setEstimatedTotalItems(steps.items.len); const run_steps = try gpa.dupe(*Step.Run, steps.items); - rebuild_group.wait(io); + try rebuild_group.await(io); break :steps run_steps; }; errdefer gpa.free(run_steps); @@ -115,7 +112,6 @@ pub fn init( return .{ .gpa = gpa, .io = io, - .ttyconf = ttyconf, .mode = mode, .run_steps = run_steps, .group = .init, @@ -124,7 +120,7 @@ pub fn init( .coverage_files = .empty, .coverage_mutex = .init, .queue_mutex = .init, - .queue_cond = .{}, + .queue_cond = .init, .msg_queue = .empty, }; } @@ -154,14 +150,16 @@ pub fn deinit(fuzz: *Fuzz) void { fuzz.gpa.free(fuzz.run_steps); } -fn rebuildTestsWorkerRun(run: *Step.Run, gpa: Allocator, ttyconf: tty.Config, parent_prog_node: std.Progress.Node) void { - rebuildTestsWorkerRunFallible(run, gpa, ttyconf, parent_prog_node) catch |err| { +fn rebuildTestsWorkerRun(run: *Step.Run, gpa: Allocator, parent_prog_node: std.Progress.Node) void { + rebuildTestsWorkerRunFallible(run, gpa, parent_prog_node) catch |err| { const compile = run.producer.?; log.err("step '{s}': failed to rebuild in fuzz mode: {t}", .{ compile.step.name, err }); }; } -fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, ttyconf: tty.Config, parent_prog_node: std.Progress.Node) !void { +fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, parent_prog_node: std.Progress.Node) !void { + const graph = run.step.owner.graph; + const io = graph.io; const compile = run.producer.?; const prog_node = parent_prog_node.start(compile.step.name, 0); defer prog_node.end(); @@ -174,9 +172,9 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, ttyconf: tty.Co if (show_error_msgs or show_compile_errors or show_stderr) { var buf: [256]u8 = undefined; - const w, _ = std.debug.lockStderrWriter(&buf); - defer std.debug.unlockStderrWriter(); - build_runner.printErrorMessages(gpa, &compile.step, .{}, w, ttyconf, .verbose, .indent) catch {}; + const stderr = try io.lockStderr(&buf, graph.stderr_mode); + defer io.unlockStderr(); + build_runner.printErrorMessages(gpa, &compile.step, .{}, stderr.terminal(), .verbose, .indent) catch {}; } const rebuilt_bin_path = result catch |err| switch (err) { @@ -186,12 +184,11 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, ttyconf: tty.Co run.rebuilt_executable = try rebuilt_bin_path.join(gpa, compile.out_filename); } -fn fuzzWorkerRun( - fuzz: *Fuzz, - run: *Step.Run, - unit_test_index: u32, -) void { - const gpa = run.step.owner.allocator; +fn fuzzWorkerRun(fuzz: *Fuzz, run: *Step.Run, unit_test_index: u32) void { + const owner = run.step.owner; + const gpa = owner.allocator; + const graph = owner.graph; + const io = graph.io; const test_name = run.cached_test_metadata.?.testName(unit_test_index); const prog_node = fuzz.prog_node.start(test_name, 0); @@ -200,9 +197,11 @@ fn fuzzWorkerRun( run.rerunInFuzzMode(fuzz, unit_test_index, prog_node) catch |err| switch (err) { error.MakeFailed => { var buf: [256]u8 = undefined; - const w, _ = std.debug.lockStderrWriter(&buf); - defer std.debug.unlockStderrWriter(); - build_runner.printErrorMessages(gpa, &run.step, .{}, w, fuzz.ttyconf, .verbose, .indent) catch {}; + const stderr = io.lockStderr(&buf, graph.stderr_mode) catch |e| switch (e) { + error.Canceled => return, + }; + defer io.unlockStderr(); + build_runner.printErrorMessages(gpa, &run.step, .{}, stderr.terminal(), .verbose, .indent) catch {}; return; }, else => { @@ -360,12 +359,13 @@ fn coverageRunCancelable(fuzz: *Fuzz) Io.Cancelable!void { fn prepareTables(fuzz: *Fuzz, run_step: *Step.Run, coverage_id: u64) error{ OutOfMemory, AlreadyReported, Canceled }!void { assert(fuzz.mode == .forever); const ws = fuzz.mode.forever.ws; + const gpa = fuzz.gpa; const io = fuzz.io; try fuzz.coverage_mutex.lock(io); defer fuzz.coverage_mutex.unlock(io); - const gop = try fuzz.coverage_files.getOrPut(fuzz.gpa, coverage_id); + const gop = try fuzz.coverage_files.getOrPut(gpa, coverage_id); if (gop.found_existing) { // We are fuzzing the same executable with multiple threads. // Perhaps the same unit test; perhaps a different one. In any @@ -383,12 +383,13 @@ fn prepareTables(fuzz: *Fuzz, run_step: *Step.Run, coverage_id: u64) error{ OutO .entry_points = .{}, .start_timestamp = ws.now(), }; - errdefer gop.value_ptr.coverage.deinit(fuzz.gpa); + errdefer gop.value_ptr.coverage.deinit(gpa); const rebuilt_exe_path = run_step.rebuilt_executable.?; const target = run_step.producer.?.rootModuleTarget(); var debug_info = std.debug.Info.load( - fuzz.gpa, + gpa, + io, rebuilt_exe_path, &gop.value_ptr.coverage, target.ofmt, @@ -399,21 +400,21 @@ fn prepareTables(fuzz: *Fuzz, run_step: *Step.Run, coverage_id: u64) error{ OutO }); return error.AlreadyReported; }; - defer debug_info.deinit(fuzz.gpa); + defer debug_info.deinit(gpa); const coverage_file_path: Build.Cache.Path = .{ .root_dir = run_step.step.owner.cache_root, .sub_path = "v/" ++ std.fmt.hex(coverage_id), }; - var coverage_file = coverage_file_path.root_dir.handle.openFile(coverage_file_path.sub_path, .{}) catch |err| { + var coverage_file = coverage_file_path.root_dir.handle.openFile(io, coverage_file_path.sub_path, .{}) catch |err| { log.err("step '{s}': failed to load coverage file '{f}': {t}", .{ run_step.step.name, coverage_file_path, err, }); return error.AlreadyReported; }; - defer coverage_file.close(); + defer coverage_file.close(io); - const file_size = coverage_file.getEndPos() catch |err| { + const file_size = coverage_file.length(io) catch |err| { log.err("unable to check len of coverage file '{f}': {t}", .{ coverage_file_path, err }); return error.AlreadyReported; }; @@ -433,14 +434,14 @@ fn prepareTables(fuzz: *Fuzz, run_step: *Step.Run, coverage_id: u64) error{ OutO const header: *const abi.SeenPcsHeader = @ptrCast(mapped_memory[0..@sizeOf(abi.SeenPcsHeader)]); const pcs = header.pcAddrs(); - const source_locations = try fuzz.gpa.alloc(Coverage.SourceLocation, pcs.len); - errdefer fuzz.gpa.free(source_locations); + const source_locations = try gpa.alloc(Coverage.SourceLocation, pcs.len); + errdefer gpa.free(source_locations); // Unfortunately the PCs array that LLVM gives us from the 8-bit PC // counters feature is not sorted. var sorted_pcs: std.MultiArrayList(struct { pc: u64, index: u32, sl: Coverage.SourceLocation }) = .{}; - defer sorted_pcs.deinit(fuzz.gpa); - try sorted_pcs.resize(fuzz.gpa, pcs.len); + defer sorted_pcs.deinit(gpa); + try sorted_pcs.resize(gpa, pcs.len); @memcpy(sorted_pcs.items(.pc), pcs); for (sorted_pcs.items(.index), 0..) |*v, i| v.* = @intCast(i); sorted_pcs.sortUnstable(struct { @@ -451,7 +452,7 @@ fn prepareTables(fuzz: *Fuzz, run_step: *Step.Run, coverage_id: u64) error{ OutO } }{ .addrs = sorted_pcs.items(.pc) }); - debug_info.resolveAddresses(fuzz.gpa, sorted_pcs.items(.pc), sorted_pcs.items(.sl)) catch |err| { + debug_info.resolveAddresses(gpa, io, sorted_pcs.items(.pc), sorted_pcs.items(.sl)) catch |err| { log.err("failed to resolve addresses to source locations: {t}", .{err}); return error.AlreadyReported; }; @@ -512,11 +513,11 @@ fn addEntryPoint(fuzz: *Fuzz, coverage_id: u64, addr: u64) error{ AlreadyReporte try coverage_map.entry_points.append(fuzz.gpa, @intCast(index)); } -pub fn waitAndPrintReport(fuzz: *Fuzz) void { +pub fn waitAndPrintReport(fuzz: *Fuzz) Io.Cancelable!void { assert(fuzz.mode == .limit); const io = fuzz.io; - fuzz.group.wait(io); + try fuzz.group.await(io); fuzz.group = .init; std.debug.print("======= FUZZING REPORT =======\n", .{}); @@ -528,12 +529,12 @@ pub fn waitAndPrintReport(fuzz: *Fuzz) void { .root_dir = cov.run.step.owner.cache_root, .sub_path = "v/" ++ std.fmt.hex(cov.id), }; - var coverage_file = coverage_file_path.root_dir.handle.openFile(coverage_file_path.sub_path, .{}) catch |err| { + var coverage_file = coverage_file_path.root_dir.handle.openFile(io, coverage_file_path.sub_path, .{}) catch |err| { fatal("step '{s}': failed to load coverage file '{f}': {t}", .{ cov.run.step.name, coverage_file_path, err, }); }; - defer coverage_file.close(); + defer coverage_file.close(io); const fuzz_abi = std.Build.abi.fuzz; var rbuf: [0x1000]u8 = undefined; diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig index c247e6946176..24e00bea5ed8 100644 --- a/lib/std/Build/Step.zig +++ b/lib/std/Build/Step.zig @@ -29,7 +29,6 @@ dependants: ArrayList(*Step), /// retain previous value, or update. inputs: Inputs, -state: State, /// Set this field to declare an upper bound on the amount of bytes of memory it will /// take to run the step. Zero means no limit. /// @@ -51,6 +50,9 @@ state: State, /// total system memory available. max_rss: usize, +state: State, +pending_deps: u32, + result_error_msgs: ArrayList([]const u8), result_error_bundle: std.zig.ErrorBundle, result_stderr: []const u8, @@ -111,13 +113,7 @@ pub const TestResults = struct { pub const MakeOptions = struct { progress_node: std.Progress.Node, watch: bool, - web_server: switch (builtin.target.cpu.arch) { - else => ?*Build.WebServer, - // WASM code references `Build.abi` which happens to incidentally reference this type, but - // it currently breaks because `std.net.Address` doesn't work there. Work around for now. - .wasm32 => void, - }, - ttyconf: std.Io.tty.Config, + web_server: ?*Build.WebServer, /// If set, this is a timeout to enforce on all individual unit tests, in nanoseconds. unit_test_timeout_ns: ?u64, /// Not to be confused with `Build.allocator`, which is an alias of `Build.graph.arena`. @@ -135,7 +131,6 @@ pub const State = enum { /// file system inputs have been modified, meaning that the step needs to /// be re-evaluated. precheck_done, - running, dependency_failure, success, failure, @@ -174,7 +169,6 @@ pub const Id = enum { .install_artifact => InstallArtifact, .install_file => InstallFile, .install_dir => InstallDir, - .remove_dir => RemoveDir, .fail => Fail, .fmt => Fmt, .translate_c => TranslateC, @@ -202,7 +196,6 @@ pub const InstallFile = @import("Step/InstallFile.zig"); pub const ObjCopy = @import("Step/ObjCopy.zig"); pub const Compile = @import("Step/Compile.zig"); pub const Options = @import("Step/Options.zig"); -pub const RemoveDir = @import("Step/RemoveDir.zig"); pub const Run = @import("Step/Run.zig"); pub const TranslateC = @import("Step/TranslateC.zig"); pub const WriteFile = @import("Step/WriteFile.zig"); @@ -250,6 +243,7 @@ pub fn init(options: StepOptions) Step { .dependants = .empty, .inputs = Inputs.init, .state = .precheck_unstarted, + .pending_deps = undefined, // initialized by build runner .max_rss = options.max_rss, .debug_stack_trace = blk: { const addr_buf = arena.alloc(usize, options.owner.debug_stack_frames_count) catch @panic("OOM"); @@ -329,16 +323,17 @@ pub fn cast(step: *Step, comptime T: type) ?*T { } /// For debugging purposes, prints identifying information about this Step. -pub fn dump(step: *Step, w: *Io.Writer, tty_config: Io.tty.Config) void { +pub fn dump(step: *Step, t: Io.Terminal) void { + const w = t.writer; if (step.debug_stack_trace.instruction_addresses.len > 0) { w.print("name: '{s}'. creation stack trace:\n", .{step.name}) catch {}; - std.debug.writeStackTrace(&step.debug_stack_trace, w, tty_config) catch {}; + std.debug.writeStackTrace(&step.debug_stack_trace, t) catch {}; } else { const field = "debug_stack_frames_count"; comptime assert(@hasField(Build, field)); - tty_config.setColor(w, .yellow) catch {}; + t.setColor(.yellow) catch {}; w.print("name: '{s}'. no stack trace collected for this step, see std.Build." ++ field ++ "\n", .{step.name}) catch {}; - tty_config.setColor(w, .reset) catch {}; + t.setColor(.reset) catch {}; } } @@ -348,19 +343,21 @@ pub fn captureChildProcess( gpa: Allocator, progress_node: std.Progress.Node, argv: []const []const u8, -) !std.process.Child.RunResult { - const arena = s.owner.allocator; +) !std.process.RunResult { + const graph = s.owner.graph; + const arena = graph.arena; + const io = graph.io; // If an error occurs, it's happened in this command: assert(s.result_failed_command == null); - s.result_failed_command = try allocPrintCmd(gpa, null, argv); + s.result_failed_command = try allocPrintCmd(gpa, null, null, argv); try handleChildProcUnsupported(s); try handleVerbose(s.owner, null, argv); - const result = std.process.Child.run(.{ - .allocator = arena, + const result = std.process.run(arena, io, .{ .argv = argv, + .environ_map = &graph.environ_map, .progress_node = progress_node, }) catch |err| return s.fail("failed to run {s}: {t}", .{ argv[0], err }); @@ -401,9 +398,12 @@ pub fn evalZigProcess( web_server: ?*Build.WebServer, gpa: Allocator, ) !?Path { + const b = s.owner; + const io = b.graph.io; + // If an error occurs, it's happened in this command: assert(s.result_failed_command == null); - s.result_failed_command = try allocPrintCmd(gpa, null, argv); + s.result_failed_command = try allocPrintCmd(gpa, null, null, argv); if (s.getZigProcess()) |zp| update: { assert(watch); @@ -411,7 +411,7 @@ pub fn evalZigProcess( const result = zigProcessUpdate(s, zp, watch, web_server, gpa) catch |err| switch (err) { error.BrokenPipe => { // Process restart required. - const term = zp.child.wait() catch |e| { + const term = zp.child.wait(io) catch |e| { return s.fail("unable to wait for {s}: {t}", .{ argv[0], e }); }; _ = term; @@ -427,7 +427,7 @@ pub fn evalZigProcess( if (s.result_error_msgs.items.len > 0 and result == null) { // Crash detected. - const term = zp.child.wait() catch |e| { + const term = zp.child.wait(io) catch |e| { return s.fail("unable to wait for {s}: {t}", .{ argv[0], e }); }; s.result_peak_rss = zp.child.resource_usage_statistics.getMaxRss() orelse 0; @@ -439,52 +439,50 @@ pub fn evalZigProcess( return result; } assert(argv.len != 0); - const b = s.owner; - const arena = b.allocator; try handleChildProcUnsupported(s); try handleVerbose(s.owner, null, argv); - var child = std.process.Child.init(argv, arena); - child.env_map = &b.graph.env_map; - child.stdin_behavior = .Pipe; - child.stdout_behavior = .Pipe; - child.stderr_behavior = .Pipe; - child.request_resource_usage_statistics = true; - child.progress_node = prog_node; + const zp = try gpa.create(ZigProcess); + defer if (!watch) gpa.destroy(zp); - child.spawn() catch |err| return s.fail("failed to spawn zig compiler {s}: {t}", .{ argv[0], err }); + zp.child = std.process.spawn(io, .{ + .argv = argv, + .environ_map = &b.graph.environ_map, + .stdin = .pipe, + .stdout = .pipe, + .stderr = .pipe, + .request_resource_usage_statistics = true, + .progress_node = prog_node, + }) catch |err| return s.fail("failed to spawn zig compiler {s}: {t}", .{ argv[0], err }); + defer if (!watch) zp.child.kill(io); - const zp = try gpa.create(ZigProcess); zp.* = .{ - .child = child, + .child = zp.child, .poller = Io.poll(gpa, ZigProcess.StreamEnum, .{ - .stdout = child.stdout.?, - .stderr = child.stderr.?, + .stdout = zp.child.stdout.?, + .stderr = zp.child.stderr.?, }), - .progress_ipc_fd = if (std.Progress.have_ipc) child.progress_node.getIpcFd() else {}, + .progress_ipc_fd = if (std.Progress.have_ipc) prog_node.getIpcFd() else {}, }; if (watch) s.setZigProcess(zp); - defer if (!watch) { - zp.poller.deinit(); - gpa.destroy(zp); - }; + defer if (!watch) zp.poller.deinit(); const result = try zigProcessUpdate(s, zp, watch, web_server, gpa); if (!watch) { // Send EOF to stdin. - zp.child.stdin.?.close(); + zp.child.stdin.?.close(io); zp.child.stdin = null; - const term = zp.child.wait() catch |err| { + const term = zp.child.wait(io) catch |err| { return s.fail("unable to wait for {s}: {t}", .{ argv[0], err }); }; s.result_peak_rss = zp.child.resource_usage_statistics.getMaxRss() orelse 0; // Special handling for Compile step that is expecting compile errors. if (s.cast(Compile)) |compile| switch (term) { - .Exited => { + .exited => { // Note that the exit code may be 0 in this case due to the // compiler server protocol. if (compile.expect_errors != null) { @@ -504,36 +502,34 @@ pub fn evalZigProcess( return result; } -/// Wrapper around `std.fs.Dir.updateFile` that handles verbose and error output. +/// Wrapper around `Io.Dir.updateFile` that handles verbose and error output. pub fn installFile(s: *Step, src_lazy_path: Build.LazyPath, dest_path: []const u8) !Io.Dir.PrevStatus { const b = s.owner; const io = b.graph.io; const src_path = src_lazy_path.getPath3(b, s); try handleVerbose(b, null, &.{ "install", "-C", b.fmt("{f}", .{src_path}), dest_path }); - return Io.Dir.updateFile(src_path.root_dir.handle.adaptToNewApi(), io, src_path.sub_path, .cwd(), dest_path, .{}) catch |err| { - return s.fail("unable to update file from '{f}' to '{s}': {t}", .{ - src_path, dest_path, err, - }); - }; + return Io.Dir.updateFile(src_path.root_dir.handle, io, src_path.sub_path, .cwd(), dest_path, .{}) catch |err| + return s.fail("unable to update file from '{f}' to '{s}': {t}", .{ src_path, dest_path, err }); } -/// Wrapper around `std.fs.Dir.makePathStatus` that handles verbose and error output. -pub fn installDir(s: *Step, dest_path: []const u8) !std.fs.Dir.MakePathStatus { +/// Wrapper around `Io.Dir.createDirPathStatus` that handles verbose and error output. +pub fn installDir(s: *Step, dest_path: []const u8) !Io.Dir.CreatePathStatus { const b = s.owner; + const io = b.graph.io; try handleVerbose(b, null, &.{ "install", "-d", dest_path }); - return std.fs.cwd().makePathStatus(dest_path) catch |err| { + return Io.Dir.cwd().createDirPathStatus(io, dest_path, .default_dir) catch |err| return s.fail("unable to create dir '{s}': {t}", .{ dest_path, err }); - }; } fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool, web_server: ?*Build.WebServer, gpa: Allocator) !?Path { const b = s.owner; const arena = b.allocator; + const io = b.graph.io; var timer = try std.time.Timer.start(); - try sendMessage(zp.child.stdin.?, .update); - if (!watch) try sendMessage(zp.child.stdin.?, .exit); + try sendMessage(io, zp.child.stdin.?, .update); + if (!watch) try sendMessage(io, zp.child.stdin.?, .exit); var result: ?Path = null; @@ -670,12 +666,12 @@ fn clearZigProcess(s: *Step, gpa: Allocator) void { } } -fn sendMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag) !void { +fn sendMessage(io: Io, file: Io.File, tag: std.zig.Client.Message.Tag) !void { const header: std.zig.Client.Message.Header = .{ .tag = tag, .bytes_len = 0, }; - var w = file.writer(&.{}); + var w = file.writer(io, &.{}); w.interface.writeStruct(header, .little) catch |err| switch (err) { error.WriteFailed => return w.err.?, }; @@ -692,13 +688,17 @@ pub fn handleVerbose( pub fn handleVerbose2( b: *Build, opt_cwd: ?[]const u8, - opt_env: ?*const std.process.EnvMap, + opt_env: ?*const std.process.Environ.Map, argv: []const []const u8, ) error{OutOfMemory}!void { if (b.verbose) { + const graph = b.graph; // Intention of verbose is to print all sub-process command lines to // stderr before spawning them. - const text = try allocPrintCmd2(b.allocator, opt_cwd, opt_env, argv); + const text = try allocPrintCmd(b.allocator, opt_cwd, if (opt_env) |env| .{ + .child = env, + .parent = &graph.environ_map, + } else null, argv); std.debug.print("{s}\n", .{text}); } } @@ -714,12 +714,15 @@ pub inline fn handleChildProcUnsupported(s: *Step) error{ OutOfMemory, MakeFaile pub fn handleChildProcessTerm(s: *Step, term: std.process.Child.Term) error{ MakeFailed, OutOfMemory }!void { assert(s.result_failed_command != null); switch (term) { - .Exited => |code| { + .exited => |code| { if (code != 0) { return s.fail("process exited with error code {d}", .{code}); } }, - .Signal, .Stopped, .Unknown => { + .signal => |sig| { + return s.fail("process terminated with signal {t}", .{sig}); + }, + .stopped, .unknown => { return s.fail("process terminated unexpectedly", .{}); }, } @@ -728,15 +731,10 @@ pub fn handleChildProcessTerm(s: *Step, term: std.process.Child.Term) error{ Mak pub fn allocPrintCmd( gpa: Allocator, opt_cwd: ?[]const u8, - argv: []const []const u8, -) Allocator.Error![]u8 { - return allocPrintCmd2(gpa, opt_cwd, null, argv); -} - -pub fn allocPrintCmd2( - gpa: Allocator, - opt_cwd: ?[]const u8, - opt_env: ?*const std.process.EnvMap, + opt_env: ?struct { + child: *const std.process.Environ.Map, + parent: *const std.process.Environ.Map, + }, argv: []const []const u8, ) Allocator.Error![]u8 { const shell = struct { @@ -779,13 +777,11 @@ pub fn allocPrintCmd2( const writer = &aw.writer; if (opt_cwd) |cwd| writer.print("cd {s} && ", .{cwd}) catch return error.OutOfMemory; if (opt_env) |env| { - var process_env_map = std.process.getEnvMap(gpa) catch std.process.EnvMap.init(gpa); - defer process_env_map.deinit(); - var it = env.iterator(); + var it = env.child.iterator(); while (it.next()) |entry| { const key = entry.key_ptr.*; const value = entry.value_ptr.*; - if (process_env_map.get(key)) |process_value| { + if (env.parent.get(key)) |process_value| { if (std.mem.eql(u8, value, process_value)) continue; } writer.print("{s}=", .{key}) catch return error.OutOfMemory; @@ -898,7 +894,7 @@ pub fn addWatchInput(step: *Step, lazy_file: Build.LazyPath) Allocator.Error!voi try addWatchInputFromPath(step, .{ .root_dir = .{ .path = null, - .handle = std.fs.cwd(), + .handle = Io.Dir.cwd(), }, .sub_path = std.fs.path.dirname(path_string) orelse "", }, std.fs.path.basename(path_string)); @@ -923,7 +919,7 @@ pub fn addDirectoryWatchInput(step: *Step, lazy_directory: Build.LazyPath) Alloc try addDirectoryWatchInputFromPath(step, .{ .root_dir = .{ .path = null, - .handle = std.fs.cwd(), + .handle = Io.Dir.cwd(), }, .sub_path = path_string, }); @@ -986,14 +982,17 @@ pub fn reset(step: *Step, gpa: Allocator) void { } /// Implementation detail of file watching. Prepares the step for being re-evaluated. -pub fn recursiveReset(step: *Step, gpa: Allocator) void { - assert(step.state != .precheck_done); +/// Returns `true` if the step was newly invalidated, `false` if it was already invalidated. +pub fn invalidateResult(step: *Step, gpa: Allocator) bool { + if (step.state == .precheck_done) return false; + assert(step.pending_deps == 0); step.state = .precheck_done; step.reset(gpa); - for (step.dependants.items) |dep| { - if (dep.state == .precheck_done) continue; - dep.recursiveReset(gpa); + for (step.dependants.items) |dependant| { + _ = dependant.invalidateResult(gpa); + dependant.pending_deps += 1; } + return true; } test { @@ -1007,7 +1006,6 @@ test { _ = ObjCopy; _ = Compile; _ = Options; - _ = RemoveDir; _ = Run; _ = TranslateC; _ = WriteFile; diff --git a/lib/std/Build/Step/CheckFile.zig b/lib/std/Build/Step/CheckFile.zig index 5e664b3bc377..1c3813ca824b 100644 --- a/lib/std/Build/Step/CheckFile.zig +++ b/lib/std/Build/Step/CheckFile.zig @@ -3,7 +3,9 @@ //! TODO: generalize the code in std.testing.expectEqualStrings and make this //! CheckFile step produce those helpful diagnostics when there is not a match. const CheckFile = @This(); + const std = @import("std"); +const Io = std.Io; const Step = std.Build.Step; const fs = std.fs; const mem = std.mem; @@ -49,18 +51,19 @@ pub fn setName(check_file: *CheckFile, name: []const u8) void { fn make(step: *Step, options: Step.MakeOptions) !void { _ = options; const b = step.owner; + const io = b.graph.io; const check_file: *CheckFile = @fieldParentPtr("step", step); try step.singleUnchangingWatchInput(check_file.source); const src_path = check_file.source.getPath2(b, step); - const contents = fs.cwd().readFileAlloc(src_path, b.allocator, .limited(check_file.max_bytes)) catch |err| { + const contents = Io.Dir.cwd().readFileAlloc(io, src_path, b.allocator, .limited(check_file.max_bytes)) catch |err| { return step.fail("unable to read '{s}': {s}", .{ src_path, @errorName(err), }); }; for (check_file.expected_matches) |expected_match| { - if (mem.indexOf(u8, contents, expected_match) == null) { + if (mem.find(u8, contents, expected_match) == null) { return step.fail( \\ \\========= expected to find: =================== diff --git a/lib/std/Build/Step/CheckObject.zig b/lib/std/Build/Step/CheckObject.zig index 4d5071d2c73f..ac8fafaa3fc9 100644 --- a/lib/std/Build/Step/CheckObject.zig +++ b/lib/std/Build/Step/CheckObject.zig @@ -88,7 +88,7 @@ const Action = struct { while (needle_it.next()) |needle_tok| { const hay_tok = hay_it.next() orelse break; if (mem.startsWith(u8, needle_tok, "{")) { - const closing_brace = mem.indexOf(u8, needle_tok, "}") orelse return error.MissingClosingBrace; + const closing_brace = mem.find(u8, needle_tok, "}") orelse return error.MissingClosingBrace; if (closing_brace != needle_tok.len - 1) return error.ClosingBraceNotLast; const name = needle_tok[1..closing_brace]; @@ -133,7 +133,7 @@ const Action = struct { assert(act.tag == .contains); const hay = mem.trim(u8, haystack, " "); const phrase = mem.trim(u8, act.phrase.resolve(b, step), " "); - return mem.indexOf(u8, hay, phrase) != null; + return mem.find(u8, hay, phrase) != null; } /// Returns true if the `phrase` does not exist within the haystack. @@ -547,12 +547,14 @@ pub fn checkComputeCompare( fn make(step: *Step, make_options: Step.MakeOptions) !void { _ = make_options; const b = step.owner; + const io = b.graph.io; const gpa = b.allocator; const check_object: *CheckObject = @fieldParentPtr("step", step); try step.singleUnchangingWatchInput(check_object.source); const src_path = check_object.source.getPath3(b, step); const contents = src_path.root_dir.handle.readFileAllocOptions( + io, src_path.sub_path, gpa, .limited(check_object.max_bytes), @@ -1662,7 +1664,7 @@ const MachODumper = struct { .dump_section => { const name = mem.sliceTo(@as([*:0]const u8, @ptrCast(check.data.items.ptr + check.payload.dump_section)), 0); - const sep_index = mem.indexOfScalar(u8, name, ',') orelse + const sep_index = mem.findScalar(u8, name, ',') orelse return step.fail("invalid section name: {s}", .{name}); const segname = name[0..sep_index]; const sectname = name[sep_index + 1 ..]; diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index 4f9900ab595f..92db0ca0a018 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -1,12 +1,15 @@ +const Compile = @This(); const builtin = @import("builtin"); + const std = @import("std"); +const Io = std.Io; const mem = std.mem; const fs = std.fs; const assert = std.debug.assert; const panic = std.debug.panic; const StringHashMap = std.StringHashMap; const Sha256 = std.crypto.hash.sha2.Sha256; -const Allocator = mem.Allocator; +const Allocator = std.mem.Allocator; const Step = std.Build.Step; const LazyPath = std.Build.LazyPath; const PkgConfigPkg = std.Build.PkgConfigPkg; @@ -15,7 +18,6 @@ const RunError = std.Build.RunError; const Module = std.Build.Module; const InstallDir = std.Build.InstallDir; const GeneratedFile = std.Build.GeneratedFile; -const Compile = @This(); const Path = std.Build.Cache.Path; pub const base_id: Step.Id = .compile; @@ -188,9 +190,6 @@ force_undefined_symbols: std.StringHashMap(void), /// Overrides the default stack size stack_size: ?u64 = null, -/// Deprecated; prefer using `lto`. -want_lto: ?bool = null, - use_llvm: ?bool, use_lld: ?bool, use_new_linker: ?bool, @@ -372,7 +371,7 @@ pub const TestRunner = struct { pub fn create(owner: *std.Build, options: Options) *Compile { const name = owner.dupe(options.name); - if (mem.indexOf(u8, name, "/") != null or mem.indexOf(u8, name, "\\") != null) { + if (mem.find(u8, name, "/") != null or mem.find(u8, name, "\\") != null) { panic("invalid name: '{s}'. It looks like a file path, but it is supposed to be the library or application name.", .{name}); } @@ -540,7 +539,7 @@ pub fn installHeadersDirectory( /// When a module links with this artifact, all headers marked for installation are added to that /// module's include search path. pub fn installConfigHeader(cs: *Compile, config_header: *Step.ConfigHeader) void { - cs.installHeader(config_header.getOutput(), config_header.include_path); + cs.installHeader(config_header.getOutputFile(), config_header.include_path); } /// Forwards all headers marked for installation from `lib` to this artifact. @@ -683,18 +682,6 @@ pub fn producesImplib(compile: *Compile) bool { return compile.isDll(); } -/// Deprecated; use `compile.root_module.link_libc = true` instead. -/// To be removed after 0.15.0 is tagged. -pub fn linkLibC(compile: *Compile) void { - compile.root_module.link_libc = true; -} - -/// Deprecated; use `compile.root_module.link_libcpp = true` instead. -/// To be removed after 0.15.0 is tagged. -pub fn linkLibCpp(compile: *Compile) void { - compile.root_module.link_libcpp = true; -} - const PkgConfigResult = struct { cflags: []const []const u8, libs: []const []const u8, @@ -731,7 +718,7 @@ fn runPkgConfig(compile: *Compile, lib_name: []const u8) !PkgConfigResult { // Prefixed "lib" or suffixed ".0". for (pkgs) |pkg| { - if (std.ascii.indexOfIgnoreCase(pkg.name, lib_name)) |pos| { + if (std.ascii.findIgnoreCase(pkg.name, lib_name)) |pos| { const prefix = pkg.name[0..pos]; const suffix = pkg.name[pos + lib_name.len ..]; if (prefix.len > 0 and !mem.eql(u8, prefix, "lib")) continue; @@ -754,13 +741,13 @@ fn runPkgConfig(compile: *Compile, lib_name: []const u8) !PkgConfigResult { }; var code: u8 = undefined; - const pkg_config_exe = b.graph.env_map.get("PKG_CONFIG") orelse "pkg-config"; + const pkg_config_exe = b.graph.environ_map.get("PKG_CONFIG") orelse "pkg-config"; const stdout = if (b.runAllowFail(&[_][]const u8{ pkg_config_exe, pkg_name, "--cflags", "--libs", - }, &code, .Ignore)) |stdout| stdout else |err| switch (err) { + }, &code, .ignore)) |stdout| stdout else |err| switch (err) { error.ProcessTerminated => return error.PkgConfigCrashed, error.ExecNotSupported => return error.PkgConfigFailed, error.ExitCodeFailure => return error.PkgConfigFailed, @@ -808,46 +795,6 @@ fn runPkgConfig(compile: *Compile, lib_name: []const u8) !PkgConfigResult { }; } -/// Deprecated; use `compile.root_module.linkSystemLibrary(name, .{})` instead. -/// To be removed after 0.15.0 is tagged. -pub fn linkSystemLibrary(compile: *Compile, name: []const u8) void { - return compile.root_module.linkSystemLibrary(name, .{}); -} - -/// Deprecated; use `compile.root_module.linkSystemLibrary(name, options)` instead. -/// To be removed after 0.15.0 is tagged. -pub fn linkSystemLibrary2( - compile: *Compile, - name: []const u8, - options: Module.LinkSystemLibraryOptions, -) void { - return compile.root_module.linkSystemLibrary(name, options); -} - -/// Deprecated; use `c.root_module.linkFramework(name, .{})` instead. -/// To be removed after 0.15.0 is tagged. -pub fn linkFramework(c: *Compile, name: []const u8) void { - c.root_module.linkFramework(name, .{}); -} - -/// Deprecated; use `compile.root_module.addCSourceFiles(options)` instead. -/// To be removed after 0.15.0 is tagged. -pub fn addCSourceFiles(compile: *Compile, options: Module.AddCSourceFilesOptions) void { - compile.root_module.addCSourceFiles(options); -} - -/// Deprecated; use `compile.root_module.addCSourceFile(source)` instead. -/// To be removed after 0.15.0 is tagged. -pub fn addCSourceFile(compile: *Compile, source: Module.CSourceFile) void { - compile.root_module.addCSourceFile(source); -} - -/// Deprecated; use `compile.root_module.addWin32ResourceFile(source)` instead. -/// To be removed after 0.15.0 is tagged. -pub fn addWin32ResourceFile(compile: *Compile, source: Module.RcSourceFile) void { - compile.root_module.addWin32ResourceFile(source); -} - pub fn setVerboseLink(compile: *Compile, value: bool) void { compile.verbose_link = value; } @@ -929,84 +876,6 @@ pub fn getEmittedLlvmBc(compile: *Compile) LazyPath { return compile.getEmittedFileGeneric(&compile.generated_llvm_bc); } -/// Deprecated; use `compile.root_module.addAssemblyFile(source)` instead. -/// To be removed after 0.15.0 is tagged. -pub fn addAssemblyFile(compile: *Compile, source: LazyPath) void { - compile.root_module.addAssemblyFile(source); -} - -/// Deprecated; use `compile.root_module.addObjectFile(source)` instead. -/// To be removed after 0.15.0 is tagged. -pub fn addObjectFile(compile: *Compile, source: LazyPath) void { - compile.root_module.addObjectFile(source); -} - -/// Deprecated; use `compile.root_module.addObject(object)` instead. -/// To be removed after 0.15.0 is tagged. -pub fn addObject(compile: *Compile, object: *Compile) void { - compile.root_module.addObject(object); -} - -/// Deprecated; use `compile.root_module.linkLibrary(library)` instead. -/// To be removed after 0.15.0 is tagged. -pub fn linkLibrary(compile: *Compile, library: *Compile) void { - compile.root_module.linkLibrary(library); -} - -/// Deprecated; use `compile.root_module.addAfterIncludePath(lazy_path)` instead. -/// To be removed after 0.15.0 is tagged. -pub fn addAfterIncludePath(compile: *Compile, lazy_path: LazyPath) void { - compile.root_module.addAfterIncludePath(lazy_path); -} - -/// Deprecated; use `compile.root_module.addSystemIncludePath(lazy_path)` instead. -/// To be removed after 0.15.0 is tagged. -pub fn addSystemIncludePath(compile: *Compile, lazy_path: LazyPath) void { - compile.root_module.addSystemIncludePath(lazy_path); -} - -/// Deprecated; use `compile.root_module.addIncludePath(lazy_path)` instead. -/// To be removed after 0.15.0 is tagged. -pub fn addIncludePath(compile: *Compile, lazy_path: LazyPath) void { - compile.root_module.addIncludePath(lazy_path); -} - -/// Deprecated; use `compile.root_module.addConfigHeader(config_header)` instead. -/// To be removed after 0.15.0 is tagged. -pub fn addConfigHeader(compile: *Compile, config_header: *Step.ConfigHeader) void { - compile.root_module.addConfigHeader(config_header); -} - -/// Deprecated; use `compile.root_module.addEmbedPath(lazy_path)` instead. -/// To be removed after 0.15.0 is tagged. -pub fn addEmbedPath(compile: *Compile, lazy_path: LazyPath) void { - compile.root_module.addEmbedPath(lazy_path); -} - -/// Deprecated; use `compile.root_module.addLibraryPath(directory_path)` instead. -/// To be removed after 0.15.0 is tagged. -pub fn addLibraryPath(compile: *Compile, directory_path: LazyPath) void { - compile.root_module.addLibraryPath(directory_path); -} - -/// Deprecated; use `compile.root_module.addRPath(directory_path)` instead. -/// To be removed after 0.15.0 is tagged. -pub fn addRPath(compile: *Compile, directory_path: LazyPath) void { - compile.root_module.addRPath(directory_path); -} - -/// Deprecated; use `compile.root_module.addSystemFrameworkPath(directory_path)` instead. -/// To be removed after 0.15.0 is tagged. -pub fn addSystemFrameworkPath(compile: *Compile, directory_path: LazyPath) void { - compile.root_module.addSystemFrameworkPath(directory_path); -} - -/// Deprecated; use `compile.root_module.addFrameworkPath(directory_path)` instead. -/// To be removed after 0.15.0 is tagged. -pub fn addFrameworkPath(compile: *Compile, directory_path: LazyPath) void { - compile.root_module.addFrameworkPath(directory_path); -} - pub fn setExecCmd(compile: *Compile, args: []const ?[]const u8) void { const b = compile.step.owner; assert(compile.kind == .@"test"); @@ -1053,20 +922,24 @@ const CliNamedModules = struct { } }; -fn getGeneratedFilePath(compile: *Compile, comptime tag_name: []const u8, asking_step: ?*Step) []const u8 { +fn getGeneratedFilePath(compile: *Compile, comptime tag_name: []const u8, asking_step: ?*Step) ![]const u8 { + const step = &compile.step; + const b = step.owner; + const graph = b.graph; + const io = graph.io; const maybe_path: ?*GeneratedFile = @field(compile, tag_name); const generated_file = maybe_path orelse { - const w, const ttyconf = std.debug.lockStderrWriter(&.{}); - std.Build.dumpBadGetPathHelp(&compile.step, w, ttyconf, compile.step.owner, asking_step) catch {}; - std.debug.unlockStderrWriter(); + const stderr = try io.lockStderr(&.{}, graph.stderr_mode); + std.Build.dumpBadGetPathHelp(&compile.step, stderr.terminal(), compile.step.owner, asking_step) catch {}; + io.unlockStderr(); @panic("missing emit option for " ++ tag_name); }; const path = generated_file.path orelse { - const w, const ttyconf = std.debug.lockStderrWriter(&.{}); - std.Build.dumpBadGetPathHelp(&compile.step, w, ttyconf, compile.step.owner, asking_step) catch {}; - std.debug.unlockStderrWriter(); + const stderr = try io.lockStderr(&.{}, graph.stderr_mode); + std.Build.dumpBadGetPathHelp(&compile.step, stderr.terminal(), compile.step.owner, asking_step) catch {}; + io.unlockStderr(); @panic(tag_name ++ " is null. Is there a missing step dependency?"); }; @@ -1280,9 +1153,9 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { // For everything else, we directly link // against the library file. const full_path_lib = if (other_produces_implib) - other.getGeneratedFilePath("generated_implib", &compile.step) + try other.getGeneratedFilePath("generated_implib", &compile.step) else - other.getGeneratedFilePath("generated_bin", &compile.step); + try other.getGeneratedFilePath("generated_bin", &compile.step); try zig_args.append(full_path_lib); total_linker_objects += 1; @@ -1694,19 +1567,22 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { } // -I and -L arguments that appear after the last --mod argument apply to all modules. + const cwd: Io.Dir = .cwd(); + const io = b.graph.io; + for (b.search_prefixes.items) |search_prefix| { - var prefix_dir = fs.cwd().openDir(search_prefix, .{}) catch |err| { + var prefix_dir = cwd.openDir(io, search_prefix, .{}) catch |err| { return step.fail("unable to open prefix directory '{s}': {s}", .{ search_prefix, @errorName(err), }); }; - defer prefix_dir.close(); + defer prefix_dir.close(io); // Avoid passing -L and -I flags for nonexistent directories. // This prevents a warning, that should probably be upgraded to an error in Zig's // CLI parsing code, when the linker sees an -L directory that does not exist. - if (prefix_dir.access("lib", .{})) |_| { + if (prefix_dir.access(io, "lib", .{})) |_| { try zig_args.appendSlice(&.{ "-L", b.pathJoin(&.{ search_prefix, "lib" }), }); @@ -1717,7 +1593,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { }), } - if (prefix_dir.access("include", .{})) |_| { + if (prefix_dir.access(io, "include", .{})) |_| { try zig_args.appendSlice(&.{ "-I", b.pathJoin(&.{ search_prefix, "include" }), }); @@ -1763,7 +1639,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { .thin => "-flto=thin", .none => "-fno-lto", }); - } else try addFlag(&zig_args, "lto", compile.want_lto); + } try addFlag(&zig_args, "sanitize-coverage-trace-pc-guard", compile.sanitize_coverage_trace_pc_guard); @@ -1793,7 +1669,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { args_length += arg.len + 1; // +1 to account for null terminator } if (args_length >= 30 * 1024) { - try b.cache_root.handle.makePath("args"); + try b.cache_root.handle.createDirPath(io, "args"); const args_to_escape = zig_args.items[2..]; var escaped_args = try std.array_list.Managed([]const u8).initCapacity(arena, args_to_escape.len); @@ -1826,22 +1702,33 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { _ = try std.fmt.bufPrint(&args_hex_hash, "{x}", .{&args_hash}); const args_file = "args" ++ fs.path.sep_str ++ args_hex_hash; - if (b.cache_root.handle.access(args_file, .{})) |_| { + if (b.cache_root.handle.access(io, args_file, .{})) |_| { // The args file is already present from a previous run. } else |err| switch (err) { error.FileNotFound => { - try b.cache_root.handle.makePath("tmp"); - const rand_int = std.crypto.random.int(u64); - const tmp_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(rand_int); - try b.cache_root.handle.writeFile(.{ .sub_path = tmp_path, .data = args }); - defer b.cache_root.handle.deleteFile(tmp_path) catch { - // It's fine if the temporary file can't be cleaned up. + var af = b.cache_root.handle.createFileAtomic(io, args_file, .{ + .replace = false, + .make_path = true, + }) catch |e| return step.fail("failed creating tmp args file {f}{s}: {t}", .{ + b.cache_root, args_file, e, + }); + defer af.deinit(io); + + af.file.writeStreamingAll(io, args) catch |e| { + return step.fail("failed writing args data to tmp file {f}{s}: {t}", .{ + b.cache_root, args_file, e, + }); }; - b.cache_root.handle.rename(tmp_path, args_file) catch |rename_err| switch (rename_err) { + // Note we can't clean up this file, not even after build + // success, because that might interfere with another build + // process that needs the same file. + af.link(io) catch |e| switch (e) { error.PathAlreadyExists => { // The args file was created by another concurrent build process. }, - else => |other_err| return other_err, + else => |other_err| return step.fail("failed linking tmp file {f}{s}: {t}", .{ + b.cache_root, args_file, other_err, + }), }; }, else => |other_err| return other_err, @@ -1949,18 +1836,20 @@ pub fn doAtomicSymLinks( filename_name_only: []const u8, ) !void { const b = step.owner; + const io = b.graph.io; const out_dir = fs.path.dirname(output_path) orelse "."; const out_basename = fs.path.basename(output_path); // sym link for libfoo.so.1 to libfoo.so.1.2.3 const major_only_path = b.pathJoin(&.{ out_dir, filename_major_only }); - fs.cwd().atomicSymLink(out_basename, major_only_path, .{}) catch |err| { + const cwd: Io.Dir = .cwd(); + cwd.symLinkAtomic(io, out_basename, major_only_path, .{}) catch |err| { return step.fail("unable to symlink {s} -> {s}: {s}", .{ major_only_path, out_basename, @errorName(err), }); }; // sym link for libfoo.so to libfoo.so.1 const name_only_path = b.pathJoin(&.{ out_dir, filename_name_only }); - fs.cwd().atomicSymLink(filename_major_only, name_only_path, .{}) catch |err| { + cwd.symLinkAtomic(io, filename_major_only, name_only_path, .{}) catch |err| { return step.fail("Unable to symlink {s} -> {s}: {s}", .{ name_only_path, filename_major_only, @errorName(err), }); @@ -1968,8 +1857,8 @@ pub fn doAtomicSymLinks( } fn execPkgConfigList(b: *std.Build, out_code: *u8) (PkgConfigError || RunError)![]const PkgConfigPkg { - const pkg_config_exe = b.graph.env_map.get("PKG_CONFIG") orelse "pkg-config"; - const stdout = try b.runAllowFail(&[_][]const u8{ pkg_config_exe, "--list-all" }, out_code, .Ignore); + const pkg_config_exe = b.graph.environ_map.get("PKG_CONFIG") orelse "pkg-config"; + const stdout = try b.runAllowFail(&[_][]const u8{ pkg_config_exe, "--list-all" }, out_code, .ignore); var list = std.array_list.Managed(PkgConfigPkg).init(b.allocator); errdefer list.deinit(); var line_it = mem.tokenizeAny(u8, stdout, "\r\n"); @@ -2030,7 +1919,7 @@ fn checkCompileErrors(compile: *Compile) !void { try actual_eb.renderToWriter(.{ .include_reference_trace = false, .include_source_line = false, - }, &aw.writer, .no_color); + }, &aw.writer); break :ae try aw.toOwnedSlice(); }; @@ -2129,7 +2018,7 @@ fn matchCompileError(actual: []const u8, expected: []const u8) bool { // We scan for /?/ in expected line and if there is a match, we match everything // up to and after /?/. const expected_trim = mem.trim(u8, expected, " "); - if (mem.indexOf(u8, expected_trim, "/?/")) |index| { + if (mem.find(u8, expected_trim, "/?/")) |index| { const actual_trim = mem.trim(u8, actual, " "); const lhs = expected_trim[0..index]; const rhs = expected_trim[index + "/?/".len ..]; diff --git a/lib/std/Build/Step/ConfigHeader.zig b/lib/std/Build/Step/ConfigHeader.zig index 3f89bf8ec99b..b55efc0da4f2 100644 --- a/lib/std/Build/Step/ConfigHeader.zig +++ b/lib/std/Build/Step/ConfigHeader.zig @@ -1,5 +1,7 @@ -const std = @import("std"); const ConfigHeader = @This(); + +const std = @import("std"); +const Io = std.Io; const Step = std.Build.Step; const Allocator = std.mem.Allocator; const Writer = std.Io.Writer; @@ -124,9 +126,6 @@ pub fn getOutputFile(ch: *ConfigHeader) std.Build.LazyPath { return ch.getOutputDir().path(ch.step.owner, ch.include_path); } -/// Deprecated; use `getOutputFile`. -pub const getOutput = getOutputFile; - fn addValueInner(config_header: *ConfigHeader, name: []const u8, comptime T: type, value: T) !void { switch (@typeInfo(T)) { .null => { @@ -185,6 +184,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { const gpa = b.allocator; const arena = b.allocator; + const io = b.graph.io; var man = b.graph.cache.obtain(); defer man.deinit(); @@ -208,7 +208,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { .autoconf_undef, .autoconf_at => |file_source| { try bw.writeAll(c_generated_line); const src_path = file_source.getPath2(b, step); - const contents = std.fs.cwd().readFileAlloc(src_path, arena, .limited(config_header.max_bytes)) catch |err| { + const contents = Io.Dir.cwd().readFileAlloc(io, src_path, arena, .limited(config_header.max_bytes)) catch |err| { return step.fail("unable to read autoconf input file '{s}': {s}", .{ src_path, @errorName(err), }); @@ -222,7 +222,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { .cmake => |file_source| { try bw.writeAll(c_generated_line); const src_path = file_source.getPath2(b, step); - const contents = std.fs.cwd().readFileAlloc(src_path, arena, .limited(config_header.max_bytes)) catch |err| { + const contents = Io.Dir.cwd().readFileAlloc(io, src_path, arena, .limited(config_header.max_bytes)) catch |err| { return step.fail("unable to read cmake input file '{s}': {s}", .{ src_path, @errorName(err), }); @@ -258,13 +258,13 @@ fn make(step: *Step, options: Step.MakeOptions) !void { const sub_path = b.pathJoin(&.{ "o", &digest, config_header.include_path }); const sub_path_dirname = std.fs.path.dirname(sub_path).?; - b.cache_root.handle.makePath(sub_path_dirname) catch |err| { + b.cache_root.handle.createDirPath(io, sub_path_dirname) catch |err| { return step.fail("unable to make path '{f}{s}': {s}", .{ b.cache_root, sub_path_dirname, @errorName(err), }); }; - b.cache_root.handle.writeFile(.{ .sub_path = sub_path, .data = output }) catch |err| { + b.cache_root.handle.writeFile(io, .{ .sub_path = sub_path, .data = output }) catch |err| { return step.fail("unable to write file '{f}{s}': {s}", .{ b.cache_root, sub_path, @errorName(err), }); @@ -581,12 +581,12 @@ fn expand_variables_autoconf_at( var source_offset: usize = 0; while (curr < contents.len) : (curr += 1) { if (contents[curr] != '@') continue; - if (std.mem.indexOfScalarPos(u8, contents, curr + 1, '@')) |close_pos| { + if (std.mem.findScalarPos(u8, contents, curr + 1, '@')) |close_pos| { if (close_pos == curr + 1) { // closed immediately, preserve as a literal continue; } - const valid_varname_end = std.mem.indexOfNonePos(u8, contents, curr + 1, valid_varname_chars) orelse 0; + const valid_varname_end = std.mem.findNonePos(u8, contents, curr + 1, valid_varname_chars) orelse 0; if (valid_varname_end != close_pos) { // contains invalid characters, preserve as a literal continue; @@ -638,12 +638,12 @@ fn expand_variables_cmake( loop: while (curr < contents.len) : (curr += 1) { switch (contents[curr]) { '@' => blk: { - if (std.mem.indexOfScalarPos(u8, contents, curr + 1, '@')) |close_pos| { + if (std.mem.findScalarPos(u8, contents, curr + 1, '@')) |close_pos| { if (close_pos == curr + 1) { // closed immediately, preserve as a literal break :blk; } - const valid_varname_end = std.mem.indexOfNonePos(u8, contents, curr + 1, valid_varname_chars) orelse 0; + const valid_varname_end = std.mem.findNonePos(u8, contents, curr + 1, valid_varname_chars) orelse 0; if (valid_varname_end != close_pos) { // contains invalid characters, preserve as a literal break :blk; @@ -734,7 +734,7 @@ fn expand_variables_cmake( else => {}, } - if (var_stack.items.len > 0 and std.mem.indexOfScalar(u8, valid_varname_chars, contents[curr]) == null) { + if (var_stack.items.len > 0 and std.mem.findScalar(u8, valid_varname_chars, contents[curr]) == null) { return error.InvalidCharacter; } } diff --git a/lib/std/Build/Step/Fmt.zig b/lib/std/Build/Step/Fmt.zig index ff748af97973..2da07b63bb42 100644 --- a/lib/std/Build/Step/Fmt.zig +++ b/lib/std/Build/Step/Fmt.zig @@ -69,7 +69,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { const run_result = try step.captureChildProcess(options.gpa, prog_node, argv.items); if (fmt.check) switch (run_result.term) { - .Exited => |code| if (code != 0 and run_result.stdout.len != 0) { + .exited => |code| if (code != 0 and run_result.stdout.len != 0) { var it = std.mem.tokenizeScalar(u8, run_result.stdout, '\n'); while (it.next()) |bad_file_name| { try step.addError("{s}: non-conforming formatting", .{bad_file_name}); diff --git a/lib/std/Build/Step/InstallArtifact.zig b/lib/std/Build/Step/InstallArtifact.zig index c203ae924b96..019d465f01d6 100644 --- a/lib/std/Build/Step/InstallArtifact.zig +++ b/lib/std/Build/Step/InstallArtifact.zig @@ -119,6 +119,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { _ = options; const install_artifact: *InstallArtifact = @fieldParentPtr("step", step); const b = step.owner; + const io = b.graph.io; var all_cached = true; @@ -163,15 +164,15 @@ fn make(step: *Step, options: Step.MakeOptions) !void { const src_dir_path = dir.source.getPath3(b, step); const full_h_prefix = b.getInstallPath(h_dir, dir.dest_rel_path); - var src_dir = src_dir_path.root_dir.handle.openDir(src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| { + var src_dir = src_dir_path.root_dir.handle.openDir(io, src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| { return step.fail("unable to open source directory '{f}': {s}", .{ src_dir_path, @errorName(err), }); }; - defer src_dir.close(); + defer src_dir.close(io); var it = try src_dir.walk(b.allocator); - next_entry: while (try it.next()) |entry| { + next_entry: while (try it.next(io)) |entry| { for (dir.options.exclude_extensions) |ext| { if (std.mem.endsWith(u8, entry.path, ext)) continue :next_entry; } diff --git a/lib/std/Build/Step/InstallDir.zig b/lib/std/Build/Step/InstallDir.zig index fd8a7d113f57..d03e72ca75f4 100644 --- a/lib/std/Build/Step/InstallDir.zig +++ b/lib/std/Build/Step/InstallDir.zig @@ -58,21 +58,20 @@ pub fn create(owner: *std.Build, options: Options) *InstallDir { fn make(step: *Step, options: Step.MakeOptions) !void { _ = options; const b = step.owner; + const io = b.graph.io; const install_dir: *InstallDir = @fieldParentPtr("step", step); step.clearWatchInputs(); const arena = b.allocator; const dest_prefix = b.getInstallPath(install_dir.options.install_dir, install_dir.options.install_subdir); const src_dir_path = install_dir.options.source_dir.getPath3(b, step); const need_derived_inputs = try step.addDirectoryWatchInput(install_dir.options.source_dir); - var src_dir = src_dir_path.root_dir.handle.openDir(src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| { - return step.fail("unable to open source directory '{f}': {s}", .{ - src_dir_path, @errorName(err), - }); + var src_dir = src_dir_path.root_dir.handle.openDir(io, src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| { + return step.fail("unable to open source directory '{f}': {t}", .{ src_dir_path, err }); }; - defer src_dir.close(); + defer src_dir.close(io); var it = try src_dir.walk(arena); var all_cached = true; - next_entry: while (try it.next()) |entry| { + next_entry: while (try it.next(io)) |entry| { for (install_dir.options.exclude_extensions) |ext| { if (mem.endsWith(u8, entry.path, ext)) continue :next_entry; } diff --git a/lib/std/Build/Step/ObjCopy.zig b/lib/std/Build/Step/ObjCopy.zig index b5f058ddfc00..ea0714adf9b5 100644 --- a/lib/std/Build/Step/ObjCopy.zig +++ b/lib/std/Build/Step/ObjCopy.zig @@ -3,7 +3,7 @@ const ObjCopy = @This(); const Allocator = std.mem.Allocator; const ArenaAllocator = std.heap.ArenaAllocator; -const File = std.fs.File; +const File = std.Io.File; const InstallDir = std.Build.InstallDir; const Step = std.Build.Step; const elf = std.elf; @@ -143,6 +143,7 @@ pub fn getOutputSeparatedDebug(objcopy: *const ObjCopy) ?std.Build.LazyPath { fn make(step: *Step, options: Step.MakeOptions) !void { const prog_node = options.progress_node; const b = step.owner; + const io = b.graph.io; const objcopy: *ObjCopy = @fieldParentPtr("step", step); try step.singleUnchangingWatchInput(objcopy.input_file); @@ -176,7 +177,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { const cache_path = "o" ++ fs.path.sep_str ++ digest; const full_dest_path = try b.cache_root.join(b.allocator, &.{ cache_path, objcopy.basename }); const full_dest_path_debug = try b.cache_root.join(b.allocator, &.{ cache_path, b.fmt("{s}.debug", .{objcopy.basename}) }); - b.cache_root.handle.makePath(cache_path) catch |err| { + b.cache_root.handle.createDirPath(io, cache_path) catch |err| { return step.fail("unable to make path {s}: {s}", .{ cache_path, @errorName(err) }); }; diff --git a/lib/std/Build/Step/Options.zig b/lib/std/Build/Step/Options.zig index 441928d5b8ec..6c316b35fccd 100644 --- a/lib/std/Build/Step/Options.zig +++ b/lib/std/Build/Step/Options.zig @@ -1,12 +1,13 @@ -const std = @import("std"); +const Options = @This(); const builtin = @import("builtin"); + +const std = @import("std"); +const Io = std.Io; const fs = std.fs; const Step = std.Build.Step; const GeneratedFile = std.Build.GeneratedFile; const LazyPath = std.Build.LazyPath; -const Options = @This(); - pub const base_id: Step.Id = .options; step: Step, @@ -441,6 +442,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { _ = make_options; const b = step.owner; + const io = b.graph.io; const options: *Options = @fieldParentPtr("step", step); for (options.args.items) |item| { @@ -468,59 +470,38 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { // Optimize for the hot path. Stat the file, and if it already exists, // cache hit. - if (b.cache_root.handle.access(sub_path, .{})) |_| { + if (b.cache_root.handle.access(io, sub_path, .{})) |_| { // This is the hot path, success. step.result_cached = true; return; } else |outer_err| switch (outer_err) { error.FileNotFound => { - const sub_dirname = fs.path.dirname(sub_path).?; - b.cache_root.handle.makePath(sub_dirname) catch |e| { - return step.fail("unable to make path '{f}{s}': {s}", .{ - b.cache_root, sub_dirname, @errorName(e), - }); - }; - - const rand_int = std.crypto.random.int(u64); - const tmp_sub_path = "tmp" ++ fs.path.sep_str ++ - std.fmt.hex(rand_int) ++ fs.path.sep_str ++ - basename; - const tmp_sub_path_dirname = fs.path.dirname(tmp_sub_path).?; - - b.cache_root.handle.makePath(tmp_sub_path_dirname) catch |err| { - return step.fail("unable to make temporary directory '{f}{s}': {s}", .{ - b.cache_root, tmp_sub_path_dirname, @errorName(err), - }); - }; + var atomic_file = b.cache_root.handle.createFileAtomic(io, sub_path, .{ + .replace = false, + .make_path = true, + }) catch |err| return step.fail("failed to create temporary path for '{f}{s}': {t}", .{ + b.cache_root, sub_path, err, + }); + defer atomic_file.deinit(io); - b.cache_root.handle.writeFile(.{ .sub_path = tmp_sub_path, .data = options.contents.items }) catch |err| { - return step.fail("unable to write options to '{f}{s}': {s}", .{ - b.cache_root, tmp_sub_path, @errorName(err), + atomic_file.file.writeStreamingAll(io, options.contents.items) catch |err| { + return step.fail("failed to write options to temporary path for '{f}{s}': {t}", .{ + b.cache_root, sub_path, err, }); }; - b.cache_root.handle.rename(tmp_sub_path, sub_path) catch |err| switch (err) { + atomic_file.link(io) catch |err| switch (err) { error.PathAlreadyExists => { - // Other process beat us to it. Clean up the temp file. - b.cache_root.handle.deleteFile(tmp_sub_path) catch |e| { - try step.addError("warning: unable to delete temp file '{f}{s}': {s}", .{ - b.cache_root, tmp_sub_path, @errorName(e), - }); - }; step.result_cached = true; return; }, - else => { - return step.fail("unable to rename options from '{f}{s}' to '{f}{s}': {s}", .{ - b.cache_root, tmp_sub_path, - b.cache_root, sub_path, - @errorName(err), - }); - }, + else => return step.fail("failed to link temporary file into '{f}{s}': {t}", .{ + b.cache_root, sub_path, err, + }), }; }, - else => |e| return step.fail("unable to access options file '{f}{s}': {s}", .{ - b.cache_root, sub_path, @errorName(e), + else => |e| return step.fail("unable to access options file '{f}{s}': {t}", .{ + b.cache_root, sub_path, e, }), } } @@ -538,17 +519,21 @@ test Options { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); + const cwd = try std.process.getCwdAlloc(std.testing.allocator); + defer std.testing.allocator.free(cwd); + var graph: std.Build.Graph = .{ .io = io, .arena = arena.allocator(), .cache = .{ .io = io, .gpa = arena.allocator(), - .manifest_dir = std.fs.cwd(), + .manifest_dir = Io.Dir.cwd(), + .cwd = cwd, }, .zig_exe = "test", - .env_map = std.process.EnvMap.init(arena.allocator()), - .global_cache_root = .{ .path = "test", .handle = std.fs.cwd() }, + .environ_map = std.process.Environ.Map.init(arena.allocator()), + .global_cache_root = .{ .path = "test", .handle = Io.Dir.cwd() }, .host = .{ .query = .{}, .result = try std.zig.system.resolveTargetQuery(io, .{}), @@ -559,8 +544,8 @@ test Options { var builder = try std.Build.create( &graph, - .{ .path = "test", .handle = std.fs.cwd() }, - .{ .path = "test", .handle = std.fs.cwd() }, + .{ .path = "test", .handle = Io.Dir.cwd() }, + .{ .path = "test", .handle = Io.Dir.cwd() }, &.{}, ); diff --git a/lib/std/Build/Step/RemoveDir.zig b/lib/std/Build/Step/RemoveDir.zig deleted file mode 100644 index e2d4c02abca8..000000000000 --- a/lib/std/Build/Step/RemoveDir.zig +++ /dev/null @@ -1,48 +0,0 @@ -const std = @import("std"); -const fs = std.fs; -const Step = std.Build.Step; -const RemoveDir = @This(); -const LazyPath = std.Build.LazyPath; - -pub const base_id: Step.Id = .remove_dir; - -step: Step, -doomed_path: LazyPath, - -pub fn create(owner: *std.Build, doomed_path: LazyPath) *RemoveDir { - const remove_dir = owner.allocator.create(RemoveDir) catch @panic("OOM"); - remove_dir.* = .{ - .step = Step.init(.{ - .id = base_id, - .name = owner.fmt("RemoveDir {s}", .{doomed_path.getDisplayName()}), - .owner = owner, - .makeFn = make, - }), - .doomed_path = doomed_path.dupe(owner), - }; - return remove_dir; -} - -fn make(step: *Step, options: Step.MakeOptions) !void { - _ = options; - - const b = step.owner; - const remove_dir: *RemoveDir = @fieldParentPtr("step", step); - - step.clearWatchInputs(); - try step.addWatchInput(remove_dir.doomed_path); - - const full_doomed_path = remove_dir.doomed_path.getPath2(b, step); - - b.build_root.handle.deleteTree(full_doomed_path) catch |err| { - if (b.build_root.path) |base| { - return step.fail("unable to recursively delete path '{s}/{s}': {s}", .{ - base, full_doomed_path, @errorName(err), - }); - } else { - return step.fail("unable to recursively delete path '{s}': {s}", .{ - full_doomed_path, @errorName(err), - }); - } - }; -} diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index 764d2830ff1a..6b03d166fc79 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -1,15 +1,16 @@ -const std = @import("std"); +const Run = @This(); const builtin = @import("builtin"); + +const std = @import("std"); +const Io = std.Io; const Build = std.Build; -const Step = Build.Step; -const fs = std.fs; +const Step = std.Build.Step; +const Dir = std.Io.Dir; const mem = std.mem; const process = std.process; -const EnvMap = process.EnvMap; +const EnvMap = std.process.Environ.Map; const assert = std.debug.assert; -const Path = Build.Cache.Path; - -const Run = @This(); +const Path = std.Build.Cache.Path; pub const base_id: Step.Id = .run; @@ -22,22 +23,10 @@ argv: std.ArrayList(Arg), cwd: ?Build.LazyPath, /// Override this field to modify the environment, or use setEnvironmentVariable -env_map: ?*EnvMap, +environ_map: ?*EnvMap, /// Controls the `NO_COLOR` and `CLICOLOR_FORCE` environment variables. -color: enum { - /// `CLICOLOR_FORCE` is set, and `NO_COLOR` is unset. - enable, - /// `NO_COLOR` is set, and `CLICOLOR_FORCE` is unset. - disable, - /// If the build runner is using color, equivalent to `.enable`. Otherwise, equivalent to `.disable`. - inherit, - /// If stderr is captured or checked, equivalent to `.disable`. Otherwise, equivalent to `.inherit`. - auto, - /// The build runner does not modify the `CLICOLOR_FORCE` or `NO_COLOR` environment variables. - /// They are treated like normal variables, so can be controlled through `setEnvironmentVariable`. - manual, -} = .auto, +color: Color = .auto, /// When `true` prevents `ZIG_PROGRESS` environment variable from being passed /// to the child process, which otherwise would be used for the child to send @@ -88,9 +77,6 @@ skip_foreign_checks: bool, /// external executor (such as qemu) but not fail if the executor is unavailable. failing_to_execute_foreign_is_an_error: bool, -/// Deprecated in favor of `stdio_limit`. -max_stdio_size: usize, - /// If stderr or stdout exceeds this amount, the child process is killed and /// the step fails. stdio_limit: std.Io.Limit, @@ -114,6 +100,20 @@ rebuilt_executable: ?Path, /// If this Run step was produced by a Compile step, it is tracked here. producer: ?*Step.Compile, +pub const Color = enum { + /// `CLICOLOR_FORCE` is set, and `NO_COLOR` is unset. + enable, + /// `NO_COLOR` is set, and `CLICOLOR_FORCE` is unset. + disable, + /// If the build runner is using color, equivalent to `.enable`. Otherwise, equivalent to `.disable`. + inherit, + /// If stderr is captured or checked, equivalent to `.disable`. Otherwise, equivalent to `.inherit`. + auto, + /// The build runner does not modify the `CLICOLOR_FORCE` or `NO_COLOR` environment variables. + /// They are treated like normal variables, so can be controlled through `setEnvironmentVariable`. + manual, +}; + pub const StdIn = union(enum) { none, bytes: []const u8, @@ -149,7 +149,7 @@ pub const StdIo = union(enum) { expect_stderr_match: []const u8, expect_stdout_exact: []const u8, expect_stdout_match: []const u8, - expect_term: std.process.Child.Term, + expect_term: process.Child.Term, }; }; @@ -215,7 +215,7 @@ pub fn create(owner: *std.Build, name: []const u8) *Run { }), .argv = .{}, .cwd = null, - .env_map = null, + .environ_map = null, .disable_zig_progress = false, .stdio = .infer_from_args, .stdin = .none, @@ -223,7 +223,6 @@ pub fn create(owner: *std.Build, name: []const u8) *Run { .rename_step_with_output_arg = true, .skip_foreign_checks = false, .failing_to_execute_foreign_is_an_error = true, - .max_stdio_size = 10 * 1024 * 1024, .stdio_limit = .unlimited, .captured_stdout = null, .captured_stderr = null, @@ -315,7 +314,7 @@ pub fn addPrefixedOutputFileArg( run.setName(b.fmt("{s} ({s})", .{ run.step.name, basename })); } - return .{ .generated = .{ .file = &output.generated_file } }; + return .{ .generated = .{ .file = &output.generated_file, .content_hash_name = output.basename } }; } /// Appends an input file to the command line arguments. @@ -541,12 +540,12 @@ pub fn clearEnvironment(run: *Run) void { const b = run.step.owner; const new_env_map = b.allocator.create(EnvMap) catch @panic("OOM"); new_env_map.* = .init(b.allocator); - run.env_map = new_env_map; + run.environ_map = new_env_map; } pub fn addPathDir(run: *Run, search_path: []const u8) void { const b = run.step.owner; - const env_map = getEnvMapInternal(run); + const environ_map = getEnvMapInternal(run); const use_wine = b.enable_wine and b.graph.host.result.os.tag != .windows and use_wine: switch (run.argv.items[0]) { .artifact => |p| p.artifact.rootModuleTarget().os.tag == .windows, @@ -563,17 +562,17 @@ pub fn addPathDir(run: *Run, search_path: []const u8) void { .output_file, .output_directory => false, }; const key = if (use_wine) "WINEPATH" else "PATH"; - const prev_path = env_map.get(key); + const prev_path = environ_map.get(key); if (prev_path) |pp| { const new_path = b.fmt("{s}{c}{s}", .{ pp, - if (use_wine) fs.path.delimiter_windows else fs.path.delimiter, + if (use_wine) Dir.path.delimiter_windows else Dir.path.delimiter, search_path, }); - env_map.put(key, new_path) catch @panic("OOM"); + environ_map.put(key, new_path) catch @panic("OOM"); } else { - env_map.put(key, b.dupePath(search_path)) catch @panic("OOM"); + environ_map.put(key, b.dupePath(search_path)) catch @panic("OOM"); } } @@ -582,43 +581,51 @@ pub fn getEnvMap(run: *Run) *EnvMap { } fn getEnvMapInternal(run: *Run) *EnvMap { - const arena = run.step.owner.allocator; - return run.env_map orelse { - const env_map = arena.create(EnvMap) catch @panic("OOM"); - env_map.* = process.getEnvMap(arena) catch @panic("unhandled error"); - run.env_map = env_map; - return env_map; + const graph = run.step.owner.graph; + const arena = graph.arena; + return run.environ_map orelse { + const cloned_map = arena.create(EnvMap) catch @panic("OOM"); + cloned_map.* = graph.environ_map.clone(arena) catch @panic("OOM"); + run.environ_map = cloned_map; + return cloned_map; }; } pub fn setEnvironmentVariable(run: *Run, key: []const u8, value: []const u8) void { - const b = run.step.owner; - const env_map = run.getEnvMap(); - env_map.put(b.dupe(key), b.dupe(value)) catch @panic("unhandled error"); + const environ_map = run.getEnvMap(); + // This data structure already dupes keys and values. + environ_map.put(key, value) catch @panic("OOM"); } pub fn removeEnvironmentVariable(run: *Run, key: []const u8) void { - run.getEnvMap().remove(key); + _ = run.getEnvMap().swapRemove(key); } /// Adds a check for exact stderr match. Does not add any other checks. pub fn expectStdErrEqual(run: *Run, bytes: []const u8) void { - const new_check: StdIo.Check = .{ .expect_stderr_exact = run.step.owner.dupe(bytes) }; - run.addCheck(new_check); + run.addCheck(.{ .expect_stderr_exact = run.step.owner.dupe(bytes) }); +} + +pub fn expectStdErrMatch(run: *Run, bytes: []const u8) void { + run.addCheck(.{ .expect_stderr_match = run.step.owner.dupe(bytes) }); } /// Adds a check for exact stdout match as well as a check for exit code 0, if /// there is not already an expected termination check. pub fn expectStdOutEqual(run: *Run, bytes: []const u8) void { - const new_check: StdIo.Check = .{ .expect_stdout_exact = run.step.owner.dupe(bytes) }; - run.addCheck(new_check); - if (!run.hasTermCheck()) { - run.expectExitCode(0); - } + run.addCheck(.{ .expect_stdout_exact = run.step.owner.dupe(bytes) }); + if (!run.hasTermCheck()) run.expectExitCode(0); +} + +/// Adds a check for stdout match as well as a check for exit code 0, if there +/// is not already an expected termination check. +pub fn expectStdOutMatch(run: *Run, bytes: []const u8) void { + run.addCheck(.{ .expect_stdout_match = run.step.owner.dupe(bytes) }); + if (!run.hasTermCheck()) run.expectExitCode(0); } pub fn expectExitCode(run: *Run, code: u8) void { - const new_check: StdIo.Check = .{ .expect_term = .{ .Exited = code } }; + const new_check: StdIo.Check = .{ .expect_term = .{ .exited = code } }; run.addCheck(new_check); } @@ -750,28 +757,30 @@ fn checksContainStderr(checks: []const StdIo.Check) bool { /// to make sure the child doesn't see paths relative to a cwd other than its own. fn convertPathArg(run: *Run, path: Build.Cache.Path) []const u8 { const b = run.step.owner; - const path_str = path.toString(b.graph.arena) catch @panic("OOM"); - if (std.fs.path.isAbsolute(path_str)) { + const graph = b.graph; + const arena = graph.arena; + + const path_str = path.toString(arena) catch @panic("OOM"); + if (Dir.path.isAbsolute(path_str)) { // Absolute paths don't need changing. return path_str; } const child_cwd_rel: []const u8 = rel: { const child_lazy_cwd = run.cwd orelse break :rel path_str; - const child_cwd = child_lazy_cwd.getPath3(b, &run.step).toString(b.graph.arena) catch @panic("OOM"); + const child_cwd = child_lazy_cwd.getPath3(b, &run.step).toString(arena) catch @panic("OOM"); // Convert it from relative to *our* cwd, to relative to the *child's* cwd. - break :rel std.fs.path.relative(b.graph.arena, child_cwd, path_str) catch @panic("OOM"); + break :rel Dir.path.relative(arena, graph.cache.cwd, &graph.environ_map, child_cwd, path_str) catch @panic("OOM"); }; // Not every path can be made relative, e.g. if the path and the child cwd are on different // disk designators on Windows. In that case, `relative` will return an absolute path which we can // just return. - if (std.fs.path.isAbsolute(child_cwd_rel)) { - return child_cwd_rel; - } + if (Dir.path.isAbsolute(child_cwd_rel)) return child_cwd_rel; + // We're not done yet. In some cases this path must be prefixed with './': // * On POSIX, the executable name cannot be a single component like 'foo' // * Some executables might treat a leading '-' like a flag, which we must avoid // There's no harm in it, so just *always* apply this prefix. - return std.fs.path.join(b.graph.arena, &.{ ".", child_cwd_rel }) catch @panic("OOM"); + return Dir.path.join(arena, &.{ ".", child_cwd_rel }) catch @panic("OOM"); } const IndexedOutput = struct { @@ -792,32 +801,10 @@ fn make(step: *Step, options: Step.MakeOptions) !void { var man = b.graph.cache.obtain(); defer man.deinit(); - if (run.env_map) |env_map| { - const KV = struct { []const u8, []const u8 }; - var kv_pairs = try std.array_list.Managed(KV).initCapacity(arena, env_map.count()); - var iter = env_map.iterator(); - while (iter.next()) |entry| { - kv_pairs.appendAssumeCapacity(.{ entry.key_ptr.*, entry.value_ptr.* }); - } - - std.mem.sortUnstable(KV, kv_pairs.items, {}, struct { - fn lessThan(_: void, kv1: KV, kv2: KV) bool { - const k1 = kv1[0]; - const k2 = kv2[0]; - - if (k1.len != k2.len) return k1.len < k2.len; - - for (k1, k2) |c1, c2| { - if (c1 == c2) continue; - return c1 < c2; - } - unreachable; // two keys cannot be equal - } - }.lessThan); - - for (kv_pairs.items) |kv| { - man.hash.addBytes(kv[0]); - man.hash.addBytes(kv[1]); + if (run.environ_map) |environ_map| { + for (environ_map.keys(), environ_map.values()) |key, value| { + man.hash.addBytes(key); + man.hash.addBytes(value); } } @@ -849,13 +836,13 @@ fn make(step: *Step, options: Step.MakeOptions) !void { errdefer result.deinit(); result.writer.writeAll(file_plp.prefix) catch return error.OutOfMemory; - const file = file_path.root_dir.handle.openFile(file_path.subPathOrDot(), .{}) catch |err| { + const file = file_path.root_dir.handle.openFile(io, file_path.subPathOrDot(), .{}) catch |err| { return step.fail( "unable to open input file '{f}': {t}", .{ file_path, err }, ); }; - defer file.close(); + defer file.close(io); var buf: [1024]u8 = undefined; var file_reader = file.reader(io, &buf); @@ -908,8 +895,8 @@ fn make(step: *Step, options: Step.MakeOptions) !void { man.hash.addBytes(bytes); }, .lazy_path => |lazy_path| { - const file_path = lazy_path.getPath2(b, step); - _ = try man.addFile(file_path, null); + const file_path = lazy_path.getPath3(b, step); + _ = try man.addFilePath(file_path, null); }, .none => {}, } @@ -968,15 +955,15 @@ fn make(step: *Step, options: Step.MakeOptions) !void { &digest, ); - const output_dir_path = "o" ++ fs.path.sep_str ++ &digest; + const output_dir_path = "o" ++ Dir.path.sep_str ++ &digest; for (output_placeholders.items) |placeholder| { const output_sub_path = b.pathJoin(&.{ output_dir_path, placeholder.output.basename }); const output_sub_dir_path = switch (placeholder.tag) { - .output_file => fs.path.dirname(output_sub_path).?, + .output_file => Dir.path.dirname(output_sub_path).?, .output_directory => output_sub_path, else => unreachable, }; - b.cache_root.handle.makePath(output_sub_dir_path) catch |err| { + b.cache_root.handle.createDirPath(io, output_sub_dir_path) catch |err| { return step.fail("unable to make path '{f}{s}': {s}", .{ b.cache_root, output_sub_dir_path, @errorName(err), }); @@ -997,18 +984,19 @@ fn make(step: *Step, options: Step.MakeOptions) !void { }; // We do not know the final output paths yet, use temp paths to run the command. - const rand_int = std.crypto.random.int(u64); - const tmp_dir_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(rand_int); + var rand_int: u64 = undefined; + io.random(@ptrCast(&rand_int)); + const tmp_dir_path = "tmp" ++ Dir.path.sep_str ++ std.fmt.hex(rand_int); for (output_placeholders.items) |placeholder| { const output_components = .{ tmp_dir_path, placeholder.output.basename }; const output_sub_path = b.pathJoin(&output_components); const output_sub_dir_path = switch (placeholder.tag) { - .output_file => fs.path.dirname(output_sub_path).?, + .output_file => Dir.path.dirname(output_sub_path).?, .output_directory => output_sub_path, else => unreachable, }; - b.cache_root.handle.makePath(output_sub_dir_path) catch |err| { + b.cache_root.handle.createDirPath(io, output_sub_dir_path) catch |err| { return step.fail("unable to make path '{f}{s}': {s}", .{ b.cache_root, output_sub_dir_path, @errorName(err), }); @@ -1026,7 +1014,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { try runCommand(run, argv_list.items, has_side_effects, tmp_dir_path, options, null); - const dep_file_dir = std.fs.cwd(); + const dep_file_dir = Dir.cwd(); const dep_file_basename = dep_output_file.generated_file.getPath2(b, step); if (has_side_effects) try man.addDepFile(dep_file_dir, dep_file_basename) @@ -1043,29 +1031,23 @@ fn make(step: *Step, options: Step.MakeOptions) !void { // Rename into place if (any_output) { - const o_sub_path = "o" ++ fs.path.sep_str ++ &digest; + const o_sub_path = "o" ++ Dir.path.sep_str ++ &digest; - b.cache_root.handle.rename(tmp_dir_path, o_sub_path) catch |err| { + b.cache_root.handle.rename(tmp_dir_path, b.cache_root.handle, o_sub_path, io) catch |err| { if (err == error.PathAlreadyExists) { - b.cache_root.handle.deleteTree(o_sub_path) catch |del_err| { - return step.fail("unable to remove dir '{f}'{s}: {s}", .{ - b.cache_root, - tmp_dir_path, - @errorName(del_err), + b.cache_root.handle.deleteTree(io, o_sub_path) catch |del_err| { + return step.fail("unable to remove dir '{f}'{s}: {t}", .{ + b.cache_root, tmp_dir_path, del_err, }); }; - b.cache_root.handle.rename(tmp_dir_path, o_sub_path) catch |retry_err| { - return step.fail("unable to rename dir '{f}{s}' to '{f}{s}': {s}", .{ - b.cache_root, tmp_dir_path, - b.cache_root, o_sub_path, - @errorName(retry_err), + b.cache_root.handle.rename(tmp_dir_path, b.cache_root.handle, o_sub_path, io) catch |retry_err| { + return step.fail("unable to rename dir '{f}{s}' to '{f}{s}': {t}", .{ + b.cache_root, tmp_dir_path, b.cache_root, o_sub_path, retry_err, }); }; } else { - return step.fail("unable to rename dir '{f}{s}' to '{f}{s}': {s}", .{ - b.cache_root, tmp_dir_path, - b.cache_root, o_sub_path, - @errorName(err), + return step.fail("unable to rename dir '{f}{s}' to '{f}{s}': {t}", .{ + b.cache_root, tmp_dir_path, b.cache_root, o_sub_path, err, }); } }; @@ -1114,8 +1096,8 @@ pub fn rerunInFuzzMode( errdefer result.deinit(); result.writer.writeAll(file_plp.prefix) catch return error.OutOfMemory; - const file = try file_path.root_dir.handle.openFile(file_path.subPathOrDot(), .{}); - defer file.close(); + const file = try file_path.root_dir.handle.openFile(io, file_path.subPathOrDot(), .{}); + defer file.close(io); var buf: [1024]u8 = undefined; var file_reader = file.reader(io, &buf); @@ -1147,13 +1129,13 @@ pub fn rerunInFuzzMode( } const has_side_effects = false; - const rand_int = std.crypto.random.int(u64); - const tmp_dir_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(rand_int); + var rand_int: u64 = undefined; + io.random(@ptrCast(&rand_int)); + const tmp_dir_path = "tmp" ++ Dir.path.sep_str ++ std.fmt.hex(rand_int); try runCommand(run, argv_list.items, has_side_effects, tmp_dir_path, .{ .progress_node = prog_node, .watch = undefined, // not used by `runCommand` .web_server = null, // only needed for time reports - .ttyconf = fuzz.ttyconf, .unit_test_timeout_ns = null, // don't time out fuzz tests for now .gpa = fuzz.gpa, }, .{ @@ -1189,40 +1171,40 @@ fn populateGeneratedPaths( } } -fn formatTerm(term: ?std.process.Child.Term, w: *std.Io.Writer) std.Io.Writer.Error!void { +fn formatTerm(term: ?process.Child.Term, w: *std.Io.Writer) std.Io.Writer.Error!void { if (term) |t| switch (t) { - .Exited => |code| try w.print("exited with code {d}", .{code}), - .Signal => |sig| try w.print("terminated with signal {d}", .{sig}), - .Stopped => |sig| try w.print("stopped with signal {d}", .{sig}), - .Unknown => |code| try w.print("terminated for unknown reason with code {d}", .{code}), + .exited => |code| try w.print("exited with code {d}", .{code}), + .signal => |sig| try w.print("terminated with signal {t}", .{sig}), + .stopped => |sig| try w.print("stopped with signal {d}", .{sig}), + .unknown => |code| try w.print("terminated for unknown reason with code {d}", .{code}), } else { try w.writeAll("exited with any code"); } } -fn fmtTerm(term: ?std.process.Child.Term) std.fmt.Alt(?std.process.Child.Term, formatTerm) { +fn fmtTerm(term: ?process.Child.Term) std.fmt.Alt(?process.Child.Term, formatTerm) { return .{ .data = term }; } -fn termMatches(expected: ?std.process.Child.Term, actual: std.process.Child.Term) bool { +fn termMatches(expected: ?process.Child.Term, actual: process.Child.Term) bool { return if (expected) |e| switch (e) { - .Exited => |expected_code| switch (actual) { - .Exited => |actual_code| expected_code == actual_code, + .exited => |expected_code| switch (actual) { + .exited => |actual_code| expected_code == actual_code, else => false, }, - .Signal => |expected_sig| switch (actual) { - .Signal => |actual_sig| expected_sig == actual_sig, + .signal => |expected_sig| switch (actual) { + .signal => |actual_sig| expected_sig == actual_sig, else => false, }, - .Stopped => |expected_sig| switch (actual) { - .Stopped => |actual_sig| expected_sig == actual_sig, + .stopped => |expected_sig| switch (actual) { + .stopped => |actual_sig| expected_sig == actual_sig, else => false, }, - .Unknown => |expected_code| switch (actual) { - .Unknown => |actual_code| expected_code == actual_code, + .unknown => |expected_code| switch (actual) { + .unknown => |actual_code| expected_code == actual_code, else => false, }, } else switch (actual) { - .Exited => true, + .exited => true, else => false, }; } @@ -1244,11 +1226,12 @@ fn runCommand( const b = step.owner; const arena = b.allocator; const gpa = options.gpa; + const io = b.graph.io; const cwd: ?[]const u8 = if (run.cwd) |lazy_cwd| lazy_cwd.getPath2(b, step) else null; try step.handleChildProcUnsupported(); - try Step.handleVerbose2(step.owner, cwd, run.env_map, argv); + try Step.handleVerbose2(step.owner, cwd, run.environ_map, argv); const allow_skip = switch (run.stdio) { .check, .zig_test => run.skip_foreign_checks, @@ -1258,40 +1241,13 @@ fn runCommand( var interp_argv = std.array_list.Managed([]const u8).init(b.allocator); defer interp_argv.deinit(); - var env_map: EnvMap = env: { - const orig = run.env_map orelse &b.graph.env_map; + var environ_map: EnvMap = env: { + const orig = run.environ_map orelse &b.graph.environ_map; break :env try orig.clone(gpa); }; - defer env_map.deinit(); + defer environ_map.deinit(); - color: switch (run.color) { - .manual => {}, - .enable => { - try env_map.put("CLICOLOR_FORCE", "1"); - env_map.remove("NO_COLOR"); - }, - .disable => { - try env_map.put("NO_COLOR", "1"); - env_map.remove("CLICOLOR_FORCE"); - }, - .inherit => switch (options.ttyconf) { - .no_color, .windows_api => continue :color .disable, - .escape_codes => continue :color .enable, - }, - .auto => { - const capture_stderr = run.captured_stderr != null or switch (run.stdio) { - .check => |checks| checksContainStderr(checks.items), - .infer_from_args, .inherit, .zig_test => false, - }; - if (capture_stderr) { - continue :color .disable; - } else { - continue :color .inherit; - } - }, - } - - const opt_generic_result = spawnChildAndCollect(run, argv, &env_map, has_side_effects, options, fuzz_context) catch |err| term: { + const opt_generic_result = spawnChildAndCollect(run, argv, &environ_map, has_side_effects, options, fuzz_context) catch |err| term: { // InvalidExe: cpu arch mismatch // FileNotFound: can happen with a wrong dynamic linker path if (err == error.InvalidExe or err == error.FileNotFound) interpret: { @@ -1312,7 +1268,7 @@ fn runCommand( const need_cross_libc = exe.is_linking_libc and (root_target.isGnuLibC() or (root_target.isMuslLibC() and exe.linkage == .dynamic)); const other_target = exe.root_module.resolved_target.?.result; - switch (std.zig.system.getExternalExecutor(&b.graph.host.result, &other_target, .{ + switch (std.zig.system.getExternalExecutor(io, &b.graph.host.result, &other_target, .{ .qemu_fixes_dl = need_cross_libc and b.libc_runtimes_dir != null, .link_libc = exe.is_linking_libc, })) { @@ -1327,8 +1283,8 @@ fn runCommand( // Wine's excessive stderr logging is only situationally helpful. Disable it by default, but // allow the user to override it (e.g. with `WINEDEBUG=err+all`) if desired. - if (env_map.get("WINEDEBUG") == null) { - try env_map.put("WINEDEBUG", "-all"); + if (environ_map.get("WINEDEBUG") == null) { + try environ_map.put("WINEDEBUG", "-all"); } } else { return failForeign(run, "-fwine", argv[0], exe); @@ -1425,9 +1381,9 @@ fn runCommand( gpa.free(step.result_failed_command.?); step.result_failed_command = null; - try Step.handleVerbose2(step.owner, cwd, run.env_map, interp_argv.items); + try Step.handleVerbose2(step.owner, cwd, run.environ_map, interp_argv.items); - break :term spawnChildAndCollect(run, interp_argv.items, &env_map, has_side_effects, options, fuzz_context) catch |e| { + break :term spawnChildAndCollect(run, interp_argv.items, &environ_map, has_side_effects, options, fuzz_context) catch |e| { if (!run.failing_to_execute_foreign_is_an_error) return error.MakeSkipped; if (e == error.MakeFailed) return error.MakeFailed; // error already reported return step.fail("unable to spawn interpreter {s}: {s}", .{ @@ -1472,8 +1428,8 @@ fn runCommand( captured.output.generated_file.path = output_path; const sub_path = b.pathJoin(&output_components); - const sub_path_dirname = fs.path.dirname(sub_path).?; - b.cache_root.handle.makePath(sub_path_dirname) catch |err| { + const sub_path_dirname = Dir.path.dirname(sub_path).?; + b.cache_root.handle.createDirPath(io, sub_path_dirname) catch |err| { return step.fail("unable to make path '{f}{s}': {s}", .{ b.cache_root, sub_path_dirname, @errorName(err), }); @@ -1484,7 +1440,7 @@ fn runCommand( .leading => mem.trimStart(u8, stream.bytes.?, &std.ascii.whitespace), .trailing => mem.trimEnd(u8, stream.bytes.?, &std.ascii.whitespace), }; - b.cache_root.handle.writeFile(.{ .sub_path = sub_path, .data = data }) catch |err| { + b.cache_root.handle.writeFile(io, .{ .sub_path = sub_path, .data = data }) catch |err| { return step.fail("unable to write file '{f}{s}': {s}", .{ b.cache_root, sub_path, @errorName(err), }); @@ -1509,7 +1465,7 @@ fn runCommand( } }, .expect_stderr_match => |match| { - if (mem.indexOf(u8, generic_result.stderr.?, match) == null) { + if (mem.find(u8, generic_result.stderr.?, match) == null) { return step.fail( \\========= expected to find in stderr: ========= \\{s} @@ -1535,7 +1491,7 @@ fn runCommand( } }, .expect_stdout_match => |match| { - if (mem.indexOf(u8, generic_result.stdout.?, match) == null) { + if (mem.find(u8, generic_result.stdout.?, match) == null) { return step.fail( \\========= expected to find in stdout: ========= \\{s} @@ -1559,8 +1515,8 @@ fn runCommand( else => { // On failure, report captured stderr like normal standard error output. const bad_exit = switch (generic_result.term) { - .Exited => |code| code != 0, - .Signal, .Stopped, .Unknown => true, + .exited => |code| code != 0, + .signal, .stopped, .unknown => true, }; if (bad_exit) { if (generic_result.stderr) |bytes| { @@ -1573,12 +1529,8 @@ fn runCommand( } } -const EvalZigTestResult = struct { - test_results: Step.TestResults, - test_metadata: ?TestMetadata, -}; const EvalGenericResult = struct { - term: std.process.Child.Term, + term: process.Child.Term, stdout: ?[]const u8, stderr: ?[]const u8, }; @@ -1586,123 +1538,145 @@ const EvalGenericResult = struct { fn spawnChildAndCollect( run: *Run, argv: []const []const u8, - env_map: *EnvMap, + environ_map: *EnvMap, has_side_effects: bool, options: Step.MakeOptions, fuzz_context: ?FuzzContext, ) !?EvalGenericResult { const b = run.step.owner; - const arena = b.allocator; + const graph = b.graph; + const io = graph.io; if (fuzz_context != null) { assert(!has_side_effects); assert(run.stdio == .zig_test); } - var child = std.process.Child.init(argv, arena); - if (run.cwd) |lazy_cwd| { - child.cwd = lazy_cwd.getPath2(b, &run.step); - } - child.env_map = env_map; - child.request_resource_usage_statistics = true; - - child.stdin_behavior = switch (run.stdio) { - .infer_from_args => if (has_side_effects) .Inherit else .Ignore, - .inherit => .Inherit, - .check => .Ignore, - .zig_test => .Pipe, - }; - child.stdout_behavior = switch (run.stdio) { - .infer_from_args => if (has_side_effects) .Inherit else .Ignore, - .inherit => .Inherit, - .check => |checks| if (checksContainStdout(checks.items)) .Pipe else .Ignore, - .zig_test => .Pipe, - }; - child.stderr_behavior = switch (run.stdio) { - .infer_from_args => if (has_side_effects) .Inherit else .Pipe, - .inherit => .Inherit, - .check => .Pipe, - .zig_test => .Pipe, - }; - if (run.captured_stdout != null) child.stdout_behavior = .Pipe; - if (run.captured_stderr != null) child.stderr_behavior = .Pipe; - if (run.stdin != .none) { - assert(run.stdio != .inherit); - child.stdin_behavior = .Pipe; - } + const child_cwd = if (run.cwd) |lazy_cwd| lazy_cwd.getPath2(b, &run.step) else null; // If an error occurs, it's caused by this command: assert(run.step.result_failed_command == null); - run.step.result_failed_command = try Step.allocPrintCmd(options.gpa, child.cwd, argv); + run.step.result_failed_command = try Step.allocPrintCmd(options.gpa, child_cwd, .{ + .child = environ_map, + .parent = &graph.environ_map, + }, argv); + + var spawn_options: process.SpawnOptions = .{ + .argv = argv, + .cwd = child_cwd, + .environ_map = environ_map, + .request_resource_usage_statistics = true, + .stdin = if (run.stdin != .none) s: { + assert(run.stdio != .inherit); + break :s .pipe; + } else switch (run.stdio) { + .infer_from_args => if (has_side_effects) .inherit else .ignore, + .inherit => .inherit, + .check => .ignore, + .zig_test => .pipe, + }, + .stdout = if (run.captured_stdout != null) .pipe else switch (run.stdio) { + .infer_from_args => if (has_side_effects) .inherit else .ignore, + .inherit => .inherit, + .check => |checks| if (checksContainStdout(checks.items)) .pipe else .ignore, + .zig_test => .pipe, + }, + .stderr = if (run.captured_stderr != null) .pipe else switch (run.stdio) { + .infer_from_args => if (has_side_effects) .inherit else .pipe, + .inherit => .inherit, + .check => .pipe, + .zig_test => .pipe, + }, + }; if (run.stdio == .zig_test) { var timer = try std.time.Timer.start(); - const res = try evalZigTest(run, &child, options, fuzz_context); - run.step.result_duration_ns = timer.read(); - run.step.test_results = res.test_results; - if (res.test_metadata) |tm| { - run.cached_test_metadata = tm.toCachedTestMetadata(); - if (options.web_server) |ws| { - if (b.graph.time_report) { - ws.updateTimeReportRunTest( - run, - &run.cached_test_metadata.?, - tm.ns_per_test, - ); - } - } - } + defer run.step.result_duration_ns = timer.read(); + try evalZigTest(run, spawn_options, options, fuzz_context); return null; } else { - const inherit = child.stdout_behavior == .Inherit or child.stderr_behavior == .Inherit; + const inherit = spawn_options.stdout == .inherit or spawn_options.stderr == .inherit; if (!run.disable_zig_progress and !inherit) { - child.progress_node = options.progress_node; + spawn_options.progress_node = options.progress_node; } - if (inherit) std.debug.lockStdErr(); - defer if (inherit) std.debug.unlockStdErr(); + const terminal_mode: Io.Terminal.Mode = if (inherit) m: { + const stderr = try io.lockStderr(&.{}, graph.stderr_mode); + break :m stderr.terminal_mode; + } else .no_color; + defer if (inherit) io.unlockStderr(); + try setColorEnvironmentVariables(run, environ_map, terminal_mode); var timer = try std.time.Timer.start(); - const res = try evalGeneric(run, &child); + const res = try evalGeneric(run, spawn_options); run.step.result_duration_ns = timer.read(); return .{ .term = res.term, .stdout = res.stdout, .stderr = res.stderr }; } } +fn setColorEnvironmentVariables(run: *Run, environ_map: *EnvMap, terminal_mode: Io.Terminal.Mode) !void { + color: switch (run.color) { + .manual => {}, + .enable => { + try environ_map.put("CLICOLOR_FORCE", "1"); + _ = environ_map.swapRemove("NO_COLOR"); + }, + .disable => { + try environ_map.put("NO_COLOR", "1"); + _ = environ_map.swapRemove("CLICOLOR_FORCE"); + }, + .inherit => switch (terminal_mode) { + .no_color, .windows_api => continue :color .disable, + .escape_codes => continue :color .enable, + }, + .auto => { + const capture_stderr = run.captured_stderr != null or switch (run.stdio) { + .check => |checks| checksContainStderr(checks.items), + .infer_from_args, .inherit, .zig_test => false, + }; + if (capture_stderr) { + continue :color .disable; + } else { + continue :color .inherit; + } + }, + } +} + const StdioPollEnum = enum { stdout, stderr }; fn evalZigTest( run: *Run, - child: *std.process.Child, + spawn_options: process.SpawnOptions, options: Step.MakeOptions, fuzz_context: ?FuzzContext, -) !EvalZigTestResult { - const gpa = run.step.owner.allocator; - const arena = run.step.owner.allocator; +) !void { + const step_owner = run.step.owner; + const gpa = step_owner.allocator; + const arena = step_owner.allocator; + const io = step_owner.graph.io; // We will update this every time a child runs. run.step.result_peak_rss = 0; - var result: EvalZigTestResult = .{ - .test_results = .{ - .test_count = 0, - .skip_count = 0, - .fail_count = 0, - .crash_count = 0, - .timeout_count = 0, - .leak_count = 0, - .log_err_count = 0, - }, - .test_metadata = null, + var test_results: Step.TestResults = .{ + .test_count = 0, + .skip_count = 0, + .fail_count = 0, + .crash_count = 0, + .timeout_count = 0, + .leak_count = 0, + .log_err_count = 0, }; + var test_metadata: ?TestMetadata = null; while (true) { - try child.spawn(); + var child = try process.spawn(io, spawn_options); var poller = std.Io.poll(gpa, StdioPollEnum, .{ .stdout = child.stdout.?, .stderr = child.stderr.?, }); var child_killed = false; defer if (!child_killed) { - _ = child.kill() catch {}; + child.kill(io); poller.deinit(); run.step.result_peak_rss = @max( run.step.result_peak_rss, @@ -1710,16 +1684,14 @@ fn evalZigTest( ); }; - try child.waitForSpawn(); - switch (try pollZigTest( run, - child, + &child, options, fuzz_context, &poller, - &result.test_metadata, - &result.test_results, + &test_metadata, + &test_results, )) { .write_failed => |err| { // The runner unexpectedly closed a stdio pipe, which means a crash. Make sure we've captured @@ -1728,18 +1700,19 @@ fn evalZigTest( run.step.result_stderr = try arena.dupe(u8, poller.reader(.stderr).buffered()); // Clean up everything and wait for the child to exit. - child.stdin.?.close(); + child.stdin.?.close(io); child.stdin = null; poller.deinit(); child_killed = true; - const term = try child.wait(); + const term = try child.wait(io); run.step.result_peak_rss = @max( run.step.result_peak_rss, child.resource_usage_statistics.getMaxRss() orelse 0, ); - try run.step.addError("unable to write stdin ({t}); test process unexpectedly {f}", .{ err, fmtTerm(term) }); - return result; + // The individual unit test results are irrelevant: the test runner itself broke! + // Fail immediately without populating `s.test_results`. + return run.step.fail("unable to write stdin ({t}); test process unexpectedly {f}", .{ err, fmtTerm(term) }); }, .no_poll => |no_poll| { // This might be a success (we requested exit and the child dutifully closed stdout) or @@ -1748,11 +1721,11 @@ fn evalZigTest( poller.reader(.stderr).tossBuffered(); // Clean up everything and wait for the child to exit. - child.stdin.?.close(); + child.stdin.?.close(io); child.stdin = null; poller.deinit(); child_killed = true; - const term = try child.wait(); + const term = try child.wait(io); run.step.result_peak_rss = @max( run.step.result_peak_rss, child.resource_usage_statistics.getMaxRss() orelse 0, @@ -1761,10 +1734,10 @@ fn evalZigTest( if (no_poll.active_test_index) |test_index| { // A test was running, so this is definitely a crash. Report it against that // test, and continue to the next test. - result.test_metadata.?.ns_per_test[test_index] = no_poll.ns_elapsed; - result.test_results.crash_count += 1; + test_metadata.?.ns_per_test[test_index] = no_poll.ns_elapsed; + test_results.crash_count += 1; try run.step.addError("'{s}' {f}{s}{s}", .{ - result.test_metadata.?.testName(test_index), + test_metadata.?.testName(test_index), fmtTerm(term), if (stderr_owned.len != 0) " with stderr:\n" else "", std.mem.trim(u8, stderr_owned, "\n"), @@ -1774,11 +1747,28 @@ fn evalZigTest( // Report an error if the child terminated uncleanly or if we were still trying to run more tests. run.step.result_stderr = stderr_owned; - const tests_done = result.test_metadata != null and result.test_metadata.?.next_index == std.math.maxInt(u32); - if (!tests_done or !termMatches(.{ .Exited = 0 }, term)) { - try run.step.addError("test process unexpectedly {f}", .{fmtTerm(term)}); + const tests_done = test_metadata != null and test_metadata.?.next_index == std.math.maxInt(u32); + if (!tests_done or !termMatches(.{ .exited = 0 }, term)) { + // The individual unit test results are irrelevant: the test runner itself broke! + // Fail immediately without populating `s.test_results`. + return run.step.fail("test process unexpectedly {f}", .{fmtTerm(term)}); } - return result; + + // We're done with all of the tests! Commit the test results and return. + run.step.test_results = test_results; + if (test_metadata) |tm| { + run.cached_test_metadata = tm.toCachedTestMetadata(); + if (options.web_server) |ws| { + if (run.step.owner.graph.time_report) { + ws.updateTimeReportRunTest( + run, + &run.cached_test_metadata.?, + tm.ns_per_test, + ); + } + } + } + return; }, .timeout => |timeout| { const stderr = poller.reader(.stderr).buffered(); @@ -1786,10 +1776,10 @@ fn evalZigTest( if (timeout.active_test_index) |test_index| { // A test was running. Report the timeout against that test, and continue on to // the next test. - result.test_metadata.?.ns_per_test[test_index] = timeout.ns_elapsed; - result.test_results.timeout_count += 1; + test_metadata.?.ns_per_test[test_index] = timeout.ns_elapsed; + test_results.timeout_count += 1; try run.step.addError("'{s}' timed out after {D}{s}{s}", .{ - result.test_metadata.?.testName(test_index), + test_metadata.?.testName(test_index), timeout.ns_elapsed, if (stderr.len != 0) " with stderr:\n" else "", std.mem.trim(u8, stderr, "\n"), @@ -1798,6 +1788,8 @@ fn evalZigTest( } // Just log an error and let the child be killed. run.step.result_stderr = try arena.dupe(u8, stderr); + // The individual unit test results in `results` are irrelevant: the test runner + // is broken! Fail immediately without populating `s.test_results`. return run.step.fail("test runner failed to respond for {D}", .{timeout.ns_elapsed}); }, } @@ -1811,7 +1803,7 @@ fn evalZigTest( /// * `poll` fails, indicating the child closed stdout and stderr fn pollZigTest( run: *Run, - child: *std.process.Child, + child: *process.Child, options: Step.MakeOptions, fuzz_context: ?FuzzContext, poller: *std.Io.Poller(StdioPollEnum), @@ -1840,6 +1832,7 @@ fn pollZigTest( switch (ctx.fuzz.mode) { .forever => { sendRunFuzzTestMessage( + io, child.stdin.?, ctx.unit_test_index, .forever, @@ -1848,6 +1841,7 @@ fn pollZigTest( }, .limit => |limit| { sendRunFuzzTestMessage( + io, child.stdin.?, ctx.unit_test_index, .iterations, @@ -1857,11 +1851,11 @@ fn pollZigTest( } } else if (opt_metadata.*) |*md| { // Previous unit test process died or was killed; we're continuing where it left off - requestNextTest(child.stdin.?, md, &sub_prog_node) catch |err| return .{ .write_failed = err }; + requestNextTest(io, child.stdin.?, md, &sub_prog_node) catch |err| return .{ .write_failed = err }; } else { // Running unit tests normally run.fuzz_tests.clearRetainingCapacity(); - sendMessage(child.stdin.?, .query_test_metadata) catch |err| return .{ .write_failed = err }; + sendMessage(io, child.stdin.?, .query_test_metadata) catch |err| return .{ .write_failed = err }; } var active_test_index: ?u32 = null; @@ -1977,7 +1971,7 @@ fn pollZigTest( active_test_index = null; if (timer) |*t| t.reset(); - requestNextTest(child.stdin.?, &opt_metadata.*.?, &sub_prog_node) catch |err| return .{ .write_failed = err }; + requestNextTest(io, child.stdin.?, &opt_metadata.*.?, &sub_prog_node) catch |err| return .{ .write_failed = err }; }, .test_started => { active_test_index = opt_metadata.*.?.next_index - 1; @@ -2026,7 +2020,7 @@ fn pollZigTest( active_test_index = null; if (timer) |*t| md.ns_per_test[tr_hdr.index] = t.lap(); - requestNextTest(child.stdin.?, md, &sub_prog_node) catch |err| return .{ .write_failed = err }; + requestNextTest(io, child.stdin.?, md, &sub_prog_node) catch |err| return .{ .write_failed = err }; }, .coverage_id => { coverage_id = body_r.takeInt(u64, .little) catch unreachable; @@ -2097,7 +2091,7 @@ pub const CachedTestMetadata = struct { } }; -fn requestNextTest(in: fs.File, metadata: *TestMetadata, sub_prog_node: *?std.Progress.Node) !void { +fn requestNextTest(io: Io, in: Io.File, metadata: *TestMetadata, sub_prog_node: *?std.Progress.Node) !void { while (metadata.next_index < metadata.names.len) { const i = metadata.next_index; metadata.next_index += 1; @@ -2108,31 +2102,31 @@ fn requestNextTest(in: fs.File, metadata: *TestMetadata, sub_prog_node: *?std.Pr if (sub_prog_node.*) |n| n.end(); sub_prog_node.* = metadata.prog_node.start(name, 0); - try sendRunTestMessage(in, .run_test, i); + try sendRunTestMessage(io, in, .run_test, i); return; } else { metadata.next_index = std.math.maxInt(u32); // indicate that all tests are done - try sendMessage(in, .exit); + try sendMessage(io, in, .exit); } } -fn sendMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag) !void { +fn sendMessage(io: Io, file: Io.File, tag: std.zig.Client.Message.Tag) !void { const header: std.zig.Client.Message.Header = .{ .tag = tag, .bytes_len = 0, }; - var w = file.writer(&.{}); + var w = file.writer(io, &.{}); w.interface.writeStruct(header, .little) catch |err| switch (err) { error.WriteFailed => return w.err.?, }; } -fn sendRunTestMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag, index: u32) !void { +fn sendRunTestMessage(io: Io, file: Io.File, tag: std.zig.Client.Message.Tag, index: u32) !void { const header: std.zig.Client.Message.Header = .{ .tag = tag, .bytes_len = 4, }; - var w = file.writer(&.{}); + var w = file.writer(io, &.{}); w.interface.writeStruct(header, .little) catch |err| switch (err) { error.WriteFailed => return w.err.?, }; @@ -2142,7 +2136,8 @@ fn sendRunTestMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag, index: } fn sendRunFuzzTestMessage( - file: std.fs.File, + io: Io, + file: Io.File, index: u32, kind: std.Build.abi.fuzz.LimitKind, amount_or_instance: u64, @@ -2151,7 +2146,7 @@ fn sendRunFuzzTestMessage( .tag = .start_fuzzing, .bytes_len = 4 + 1 + 8, }; - var w = file.writer(&.{}); + var w = file.writer(io, &.{}); w.interface.writeStruct(header, .little) catch |err| switch (err) { error.WriteFailed => return w.err.?, }; @@ -2166,35 +2161,33 @@ fn sendRunFuzzTestMessage( }; } -fn evalGeneric(run: *Run, child: *std.process.Child) !EvalGenericResult { +fn evalGeneric(run: *Run, spawn_options: process.SpawnOptions) !EvalGenericResult { const b = run.step.owner; const io = b.graph.io; const arena = b.allocator; - try child.spawn(); - errdefer _ = child.kill() catch {}; - - try child.waitForSpawn(); + var child = try process.spawn(io, spawn_options); + defer child.kill(io); switch (run.stdin) { .bytes => |bytes| { - child.stdin.?.writeAll(bytes) catch |err| { - return run.step.fail("unable to write stdin: {s}", .{@errorName(err)}); + child.stdin.?.writeStreamingAll(io, bytes) catch |err| { + return run.step.fail("unable to write stdin: {t}", .{err}); }; - child.stdin.?.close(); + child.stdin.?.close(io); child.stdin = null; }, .lazy_path => |lazy_path| { const path = lazy_path.getPath3(b, &run.step); - const file = path.root_dir.handle.openFile(path.subPathOrDot(), .{}) catch |err| { - return run.step.fail("unable to open stdin file: {s}", .{@errorName(err)}); + const file = path.root_dir.handle.openFile(io, path.subPathOrDot(), .{}) catch |err| { + return run.step.fail("unable to open stdin file: {t}", .{err}); }; - defer file.close(); + defer file.close(io); // TODO https://github.com/ziglang/zig/issues/23955 var read_buffer: [1024]u8 = undefined; var file_reader = file.reader(io, &read_buffer); var write_buffer: [1024]u8 = undefined; - var stdin_writer = child.stdin.?.writer(&write_buffer); + var stdin_writer = child.stdin.?.writer(io, &write_buffer); _ = stdin_writer.interface.sendFileAll(&file_reader, .unlimited) catch |err| switch (err) { error.ReadFailed => return run.step.fail("failed to read from {f}: {t}", .{ path, file_reader.err.?, @@ -2208,7 +2201,7 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !EvalGenericResult { stdin_writer.err.?, }), }; - child.stdin.?.close(); + child.stdin.?.close(io); child.stdin = null; }, .none => {}, @@ -2217,7 +2210,6 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !EvalGenericResult { var stdout_bytes: ?[]const u8 = null; var stderr_bytes: ?[]const u8 = null; - run.stdio_limit = run.stdio_limit.min(.limited(run.max_stdio_size)); if (child.stdout) |stdout| { if (child.stderr) |stderr| { var poller = std.Io.poll(arena, enum { stdout, stderr }, .{ @@ -2268,7 +2260,7 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !EvalGenericResult { run.step.result_peak_rss = child.resource_usage_statistics.getMaxRss() orelse 0; return .{ - .term = try child.wait(), + .term = try child.wait(io), .stdout = stdout_bytes, .stderr = stderr_bytes, }; @@ -2281,7 +2273,7 @@ fn addPathForDynLibs(run: *Run, artifact: *Step.Compile) void { if (compile.root_module.resolved_target.?.result.os.tag == .windows and compile.isDynamicLibrary()) { - addPathDir(run, fs.path.dirname(compile.getEmittedBin().getPath2(b, &run.step)).?); + addPathDir(run, Dir.path.dirname(compile.getEmittedBin().getPath2(b, &run.step)).?); } } } @@ -2325,10 +2317,10 @@ fn hashStdIo(hh: *std.Build.Cache.HashHelper, stdio: StdIo) void { => |s| hh.addBytes(s), .expect_term => |term| { - hh.add(@as(std.meta.Tag(std.process.Child.Term), term)); + hh.add(@as(std.meta.Tag(process.Child.Term), term)); switch (term) { - .Exited => |x| hh.add(x), - .Signal, .Stopped, .Unknown => |x| hh.add(x), + inline .exited, .signal => |x| hh.add(x), + .stopped, .unknown => |x| hh.add(x), } }, } diff --git a/lib/std/Build/Step/UpdateSourceFiles.zig b/lib/std/Build/Step/UpdateSourceFiles.zig index 7cdb521d21a2..1c4c94f9cf65 100644 --- a/lib/std/Build/Step/UpdateSourceFiles.zig +++ b/lib/std/Build/Step/UpdateSourceFiles.zig @@ -78,13 +78,13 @@ fn make(step: *Step, options: Step.MakeOptions) !void { var any_miss = false; for (usf.output_source_files.items) |output_source_file| { if (fs.path.dirname(output_source_file.sub_path)) |dirname| { - b.build_root.handle.makePath(dirname) catch |err| { + b.build_root.handle.createDirPath(io, dirname) catch |err| { return step.fail("unable to make path '{f}{s}': {t}", .{ b.build_root, dirname, err }); }; } switch (output_source_file.contents) { .bytes => |bytes| { - b.build_root.handle.writeFile(.{ .sub_path = output_source_file.sub_path, .data = bytes }) catch |err| { + b.build_root.handle.writeFile(io, .{ .sub_path = output_source_file.sub_path, .data = bytes }) catch |err| { return step.fail("unable to write file '{f}{s}': {t}", .{ b.build_root, output_source_file.sub_path, err, }); @@ -99,7 +99,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { .cwd(), io, source_path, - b.build_root.handle.adaptToNewApi(), + b.build_root.handle, output_source_file.sub_path, .{}, ) catch |err| { diff --git a/lib/std/Build/Step/WriteFile.zig b/lib/std/Build/Step/WriteFile.zig index 030c7c6811be..0c0e2b5d8637 100644 --- a/lib/std/Build/Step/WriteFile.zig +++ b/lib/std/Build/Step/WriteFile.zig @@ -1,22 +1,42 @@ //! WriteFile is used to create a directory in an appropriate location inside //! the local cache which has a set of files that have either been generated //! during the build, or are copied from the source package. +const WriteFile = @This(); + const std = @import("std"); const Io = std.Io; +const Dir = std.Io.Dir; const Step = std.Build.Step; -const fs = std.fs; const ArrayList = std.ArrayList; -const WriteFile = @This(); +const assert = std.debug.assert; step: Step, -// The elements here are pointers because we need stable pointers for the GeneratedFile field. +/// The elements here are pointers because we need stable pointers for the GeneratedFile field. files: std.ArrayList(File), directories: std.ArrayList(Directory), generated_directory: std.Build.GeneratedFile, +mode: Mode = .whole_cached, pub const base_id: Step.Id = .write_file; +pub const Mode = union(enum) { + /// Default mode. Integrates with the cache system. The directory should be + /// read-only during the make phase. Any different inputs result in + /// different "o" subdirectory. + whole_cached, + /// In this mode, the directory will be placed inside "tmp" rather than + /// "o", and caching will be skipped. During the `make` phase, the step + /// will always do all the file system operations, and on successful build + /// completion, the dir will be deleted along with all other tmp + /// directories. The directory is therefore eligible to be used for + /// mutations by other steps. + tmp, + /// The operations will not be performed against a freshly created + /// directory, but instead act against a temporary directory. + mutate: std.Build.LazyPath, +}; + pub const File = struct { sub_path: []const u8, contents: Contents, @@ -175,118 +195,156 @@ fn maybeUpdateName(write_file: *WriteFile) void { fn make(step: *Step, options: Step.MakeOptions) !void { _ = options; const b = step.owner; - const io = b.graph.io; + const graph = b.graph; + const io = graph.io; const arena = b.allocator; - const gpa = arena; + const gpa = graph.cache.gpa; const write_file: *WriteFile = @fieldParentPtr("step", step); - step.clearWatchInputs(); - - // The cache is used here not really as a way to speed things up - because writing - // the data to a file would probably be very fast - but as a way to find a canonical - // location to put build artifacts. - // If, for example, a hard-coded path was used as the location to put WriteFile - // files, then two WriteFiles executing in parallel might clobber each other. + const open_dir_cache = try arena.alloc(Io.Dir, write_file.directories.items.len); + var open_dirs_count: usize = 0; + defer Io.Dir.closeMany(io, open_dir_cache[0..open_dirs_count]); + + switch (write_file.mode) { + .whole_cached => { + step.clearWatchInputs(); + + // The cache is used here not really as a way to speed things up - because writing + // the data to a file would probably be very fast - but as a way to find a canonical + // location to put build artifacts. + + // If, for example, a hard-coded path was used as the location to put WriteFile + // files, then two WriteFiles executing in parallel might clobber each other. + + var man = b.graph.cache.obtain(); + defer man.deinit(); + + for (write_file.files.items) |file| { + man.hash.addBytes(file.sub_path); + + switch (file.contents) { + .bytes => |bytes| { + man.hash.addBytes(bytes); + }, + .copy => |lazy_path| { + const path = lazy_path.getPath3(b, step); + _ = try man.addFilePath(path, null); + try step.addWatchInput(lazy_path); + }, + } + } - var man = b.graph.cache.obtain(); - defer man.deinit(); + for (write_file.directories.items, open_dir_cache) |dir, *open_dir_cache_elem| { + man.hash.addBytes(dir.sub_path); + for (dir.options.exclude_extensions) |ext| man.hash.addBytes(ext); + if (dir.options.include_extensions) |incs| for (incs) |inc| man.hash.addBytes(inc); - for (write_file.files.items) |file| { - man.hash.addBytes(file.sub_path); + const need_derived_inputs = try step.addDirectoryWatchInput(dir.source); + const src_dir_path = dir.source.getPath3(b, step); - switch (file.contents) { - .bytes => |bytes| { - man.hash.addBytes(bytes); - }, - .copy => |lazy_path| { - const path = lazy_path.getPath3(b, step); - _ = try man.addFilePath(path, null); - try step.addWatchInput(lazy_path); - }, - } - } + var src_dir = src_dir_path.root_dir.handle.openDir(io, src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| { + return step.fail("unable to open source directory '{f}': {s}", .{ + src_dir_path, @errorName(err), + }); + }; + open_dir_cache_elem.* = src_dir; + open_dirs_count += 1; + + var it = try src_dir.walk(gpa); + defer it.deinit(); + while (try it.next(io)) |entry| { + if (!dir.options.pathIncluded(entry.path)) continue; + + switch (entry.kind) { + .directory => { + if (need_derived_inputs) { + const entry_path = try src_dir_path.join(arena, entry.path); + try step.addDirectoryWatchInputFromPath(entry_path); + } + }, + .file => { + const entry_path = try src_dir_path.join(arena, entry.path); + _ = try man.addFilePath(entry_path, null); + }, + else => continue, + } + } + } - const open_dir_cache = try arena.alloc(fs.Dir, write_file.directories.items.len); - var open_dirs_count: usize = 0; - defer closeDirs(open_dir_cache[0..open_dirs_count]); + if (try step.cacheHit(&man)) { + const digest = man.final(); + write_file.generated_directory.path = try b.cache_root.join(arena, &.{ "o", &digest }); + assert(step.result_cached); + return; + } - for (write_file.directories.items, open_dir_cache) |dir, *open_dir_cache_elem| { - man.hash.addBytes(dir.sub_path); - for (dir.options.exclude_extensions) |ext| man.hash.addBytes(ext); - if (dir.options.include_extensions) |incs| for (incs) |inc| man.hash.addBytes(inc); + const digest = man.final(); + const cache_path = "o" ++ Dir.path.sep_str ++ digest; - const need_derived_inputs = try step.addDirectoryWatchInput(dir.source); - const src_dir_path = dir.source.getPath3(b, step); + write_file.generated_directory.path = try b.cache_root.join(arena, &.{cache_path}); - var src_dir = src_dir_path.root_dir.handle.openDir(src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| { - return step.fail("unable to open source directory '{f}': {s}", .{ - src_dir_path, @errorName(err), + try operate(write_file, open_dir_cache, .{ + .root_dir = b.cache_root, + .sub_path = cache_path, }); - }; - open_dir_cache_elem.* = src_dir; - open_dirs_count += 1; - var it = try src_dir.walk(gpa); - defer it.deinit(); - while (try it.next()) |entry| { - if (!dir.options.pathIncluded(entry.path)) continue; + try step.writeManifest(&man); + }, + .tmp => { + step.result_cached = false; - switch (entry.kind) { - .directory => { - if (need_derived_inputs) { - const entry_path = try src_dir_path.join(arena, entry.path); - try step.addDirectoryWatchInputFromPath(entry_path); - } - }, - .file => { - const entry_path = try src_dir_path.join(arena, entry.path); - _ = try man.addFilePath(entry_path, null); - }, - else => continue, - } - } - } + var rand_int: u64 = undefined; + io.random(@ptrCast(&rand_int)); + const tmp_dir_sub_path = "tmp" ++ Dir.path.sep_str ++ std.fmt.hex(rand_int); - if (try step.cacheHit(&man)) { - const digest = man.final(); - write_file.generated_directory.path = try b.cache_root.join(arena, &.{ "o", &digest }); - step.result_cached = true; - return; - } + write_file.generated_directory.path = try b.cache_root.join(arena, &.{tmp_dir_sub_path}); - const digest = man.final(); - const cache_path = "o" ++ fs.path.sep_str ++ digest; + try operate(write_file, open_dir_cache, .{ + .root_dir = b.cache_root, + .sub_path = tmp_dir_sub_path, + }); + }, + .mutate => |lp| { + step.result_cached = false; + const root_path = try lp.getPath4(b, step); + write_file.generated_directory.path = try root_path.toString(arena); + try operate(write_file, open_dir_cache, root_path); + }, + } +} - write_file.generated_directory.path = try b.cache_root.join(arena, &.{ "o", &digest }); +fn operate(write_file: *WriteFile, open_dir_cache: []const Io.Dir, root_path: std.Build.Cache.Path) !void { + const step = &write_file.step; + const b = step.owner; + const io = b.graph.io; + const gpa = b.graph.cache.gpa; + const arena = b.allocator; - var cache_dir = b.cache_root.handle.makeOpenPath(cache_path, .{}) catch |err| { - return step.fail("unable to make path '{f}{s}': {s}", .{ - b.cache_root, cache_path, @errorName(err), - }); - }; - defer cache_dir.close(); + var cache_dir = root_path.root_dir.handle.createDirPathOpen(io, root_path.sub_path, .{}) catch |err| + return step.fail("unable to make path {f}: {t}", .{ root_path, err }); + defer cache_dir.close(io); for (write_file.files.items) |file| { - if (fs.path.dirname(file.sub_path)) |dirname| { - cache_dir.makePath(dirname) catch |err| { - return step.fail("unable to make path '{f}{s}{c}{s}': {t}", .{ - b.cache_root, cache_path, fs.path.sep, dirname, err, + if (Dir.path.dirname(file.sub_path)) |dirname| { + cache_dir.createDirPath(io, dirname) catch |err| { + return step.fail("unable to make path '{f}{c}{s}': {t}", .{ + root_path, Dir.path.sep, dirname, err, }); }; } switch (file.contents) { .bytes => |bytes| { - cache_dir.writeFile(.{ .sub_path = file.sub_path, .data = bytes }) catch |err| { - return step.fail("unable to write file '{f}{s}{c}{s}': {t}", .{ - b.cache_root, cache_path, fs.path.sep, file.sub_path, err, + cache_dir.writeFile(io, .{ .sub_path = file.sub_path, .data = bytes }) catch |err| { + return step.fail("unable to write file '{f}{c}{s}': {t}", .{ + root_path, Dir.path.sep, file.sub_path, err, }); }; }, .copy => |file_source| { const source_path = file_source.getPath2(b, step); - const prev_status = Io.Dir.updateFile(.cwd(), io, source_path, cache_dir.adaptToNewApi(), file.sub_path, .{}) catch |err| { - return step.fail("unable to update file from '{s}' to '{f}{s}{c}{s}': {t}", .{ - source_path, b.cache_root, cache_path, fs.path.sep, file.sub_path, err, + const prev_status = Io.Dir.updateFile(.cwd(), io, source_path, cache_dir, file.sub_path, .{}) catch |err| { + return step.fail("unable to update file from '{s}' to '{f}{c}{s}': {t}", .{ + source_path, root_path, Dir.path.sep, file.sub_path, err, }); }; // At this point we already will mark the step as a cache miss. @@ -303,33 +361,33 @@ fn make(step: *Step, options: Step.MakeOptions) !void { const dest_dirname = dir.sub_path; if (dest_dirname.len != 0) { - cache_dir.makePath(dest_dirname) catch |err| { - return step.fail("unable to make path '{f}{s}{c}{s}': {s}", .{ - b.cache_root, cache_path, fs.path.sep, dest_dirname, @errorName(err), + cache_dir.createDirPath(io, dest_dirname) catch |err| { + return step.fail("unable to make path '{f}{c}{s}': {t}", .{ + root_path, Dir.path.sep, dest_dirname, err, }); }; } var it = try already_open_dir.walk(gpa); defer it.deinit(); - while (try it.next()) |entry| { + while (try it.next(io)) |entry| { if (!dir.options.pathIncluded(entry.path)) continue; const src_entry_path = try src_dir_path.join(arena, entry.path); const dest_path = b.pathJoin(&.{ dest_dirname, entry.path }); switch (entry.kind) { - .directory => try cache_dir.makePath(dest_path), + .directory => try cache_dir.createDirPath(io, dest_path), .file => { const prev_status = Io.Dir.updateFile( - src_entry_path.root_dir.handle.adaptToNewApi(), + src_entry_path.root_dir.handle, io, src_entry_path.sub_path, - cache_dir.adaptToNewApi(), + cache_dir, dest_path, .{}, ) catch |err| { - return step.fail("unable to update file from '{f}' to '{f}{s}{c}{s}': {s}", .{ - src_entry_path, b.cache_root, cache_path, fs.path.sep, dest_path, @errorName(err), + return step.fail("unable to update file from '{f}' to '{f}{c}{s}': {t}", .{ + src_entry_path, root_path, Dir.path.sep, dest_path, err, }); }; _ = prev_status; @@ -338,10 +396,4 @@ fn make(step: *Step, options: Step.MakeOptions) !void { } } } - - try step.writeManifest(&man); -} - -fn closeDirs(dirs: []fs.Dir) void { - for (dirs) |*d| d.close(); } diff --git a/lib/std/Build/Watch.zig b/lib/std/Build/Watch.zig index 3213a9a24dd8..c4ac62b21660 100644 --- a/lib/std/Build/Watch.zig +++ b/lib/std/Build/Watch.zig @@ -1,5 +1,7 @@ const builtin = @import("builtin"); + const std = @import("../std.zig"); +const Io = std.Io; const Step = std.Build.Step; const Allocator = std.mem.Allocator; const assert = std.debug.assert; @@ -99,7 +101,8 @@ const Os = switch (builtin.os.tag) { }; }; - fn init() !Watch { + fn init(cwd_path: []const u8) !Watch { + _ = cwd_path; return .{ .dir_table = .{}, .dir_count = 0, @@ -122,7 +125,7 @@ const Os = switch (builtin.os.tag) { }) catch return error.NameTooLong; const stack_ptr: *std.os.linux.file_handle = @ptrCast(&file_handle_buffer); stack_ptr.handle_bytes = file_handle_buffer.len - @sizeOf(std.os.linux.file_handle); - try posix.name_to_handle_at(path.root_dir.handle.fd, adjusted_path, stack_ptr, mount_id, std.os.linux.AT.HANDLE_FID); + try posix.name_to_handle_at(path.root_dir.handle.handle, adjusted_path, stack_ptr, mount_id, std.os.linux.AT.HANDLE_FID); const stack_lfh: FileHandle = .{ .handle = stack_ptr }; return stack_lfh.clone(gpa); } @@ -222,7 +225,7 @@ const Os = switch (builtin.os.tag) { posix.fanotify_mark(fan_fd, .{ .ADD = true, .ONLYDIR = true, - }, fan_mask, path.root_dir.handle.fd, path.subPathOrDot()) catch |err| { + }, fan_mask, path.root_dir.handle.handle, path.subPathOrDot()) catch |err| { fatal("unable to watch {f}: {s}", .{ path, @errorName(err) }); }; } @@ -275,7 +278,7 @@ const Os = switch (builtin.os.tag) { posix.fanotify_mark(fan_fd, .{ .REMOVE = true, .ONLYDIR = true, - }, fan_mask, path.root_dir.handle.fd, path.subPathOrDot()) catch |err| switch (err) { + }, fan_mask, path.root_dir.handle.handle, path.subPathOrDot()) catch |err| switch (err) { error.FileNotFound => {}, // Expected, harmless. else => |e| std.log.warn("unable to unwatch '{f}': {s}", .{ path, @errorName(e) }), }; @@ -350,10 +353,10 @@ const Os = switch (builtin.os.tag) { } fn init(gpa: Allocator, path: Cache.Path) !*@This() { - // The following code is a drawn out NtCreateFile call. (mostly adapted from std.fs.Dir.makeOpenDirAccessMaskW) + // The following code is a drawn out NtCreateFile call. (mostly adapted from Io.Dir.makeOpenDirAccessMaskW) // It's necessary in order to get the specific flags that are required when calling ReadDirectoryChangesW. var dir_handle: windows.HANDLE = undefined; - const root_fd = path.root_dir.handle.fd; + const root_fd = path.root_dir.handle.handle; const sub_path = path.subPathOrDot(); const sub_path_w = try windows.sliceToPrefixedFileW(root_fd, sub_path); const path_len_bytes = std.math.cast(u16, sub_path_w.len * 2) orelse return error.NameTooLong; @@ -366,7 +369,7 @@ const Os = switch (builtin.os.tag) { var attr = windows.OBJECT_ATTRIBUTES{ .Length = @sizeOf(windows.OBJECT_ATTRIBUTES), .RootDirectory = if (std.fs.path.isAbsoluteWindowsW(sub_path_w.span())) null else root_fd, - .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. + .Attributes = .{}, .ObjectName = &nt_name, .SecurityDescriptor = null, .SecurityQualityOfService = null, @@ -375,14 +378,23 @@ const Os = switch (builtin.os.tag) { switch (windows.ntdll.NtCreateFile( &dir_handle, - windows.SYNCHRONIZE | windows.GENERIC_READ | windows.FILE_LIST_DIRECTORY, + .{ + .SPECIFIC = .{ .FILE_DIRECTORY = .{ + .LIST = true, + } }, + .STANDARD = .{ .SYNCHRONIZE = true }, + .GENERIC = .{ .READ = true }, + }, &attr, &io, null, - 0, - windows.FILE_SHARE_READ | windows.FILE_SHARE_WRITE | windows.FILE_SHARE_DELETE, - windows.FILE_OPEN, - windows.FILE_DIRECTORY_FILE | windows.FILE_OPEN_FOR_BACKUP_INTENT, + .{}, + .VALID_FLAGS, + .OPEN, + .{ + .DIRECTORY_FILE = true, + .OPEN_FOR_BACKUP_INTENT = true, + }, null, 0, )) { @@ -418,7 +430,8 @@ const Os = switch (builtin.os.tag) { } }; - fn init() !Watch { + fn init(cwd_path: []const u8) !Watch { + _ = cwd_path; return .{ .dir_table = .{}, .dir_count = 0, @@ -437,13 +450,13 @@ const Os = switch (builtin.os.tag) { fn getFileId(handle: windows.HANDLE) !FileId { var file_id: FileId = undefined; var io_status: windows.IO_STATUS_BLOCK = undefined; - var volume_info: windows.FILE_FS_VOLUME_INFORMATION = undefined; + var volume_info: windows.FILE.FS_VOLUME_INFORMATION = undefined; switch (windows.ntdll.NtQueryVolumeInformationFile( handle, &io_status, &volume_info, - @sizeOf(windows.FILE_FS_VOLUME_INFORMATION), - .FileFsVolumeInformation, + @sizeOf(windows.FILE.FS_VOLUME_INFORMATION), + .Volume, )) { .SUCCESS => {}, // Buffer overflow here indicates that there is more information available than was able to be stored in the buffer @@ -453,13 +466,13 @@ const Os = switch (builtin.os.tag) { else => |rc| return windows.unexpectedStatus(rc), } file_id.volumeSerialNumber = volume_info.VolumeSerialNumber; - var internal_info: windows.FILE_INTERNAL_INFORMATION = undefined; + var internal_info: windows.FILE.INTERNAL_INFORMATION = undefined; switch (windows.ntdll.NtQueryInformationFile( handle, &io_status, &internal_info, - @sizeOf(windows.FILE_INTERNAL_INFORMATION), - .FileInternalInformation, + @sizeOf(windows.FILE.INTERNAL_INFORMATION), + .Internal, )) { .SUCCESS => {}, else => |rc| return windows.unexpectedStatus(rc), @@ -649,14 +662,13 @@ const Os = switch (builtin.os.tag) { const EV = std.c.EV; const NOTE = std.c.NOTE; - fn init() !Watch { - const kq_fd = try posix.kqueue(); - errdefer posix.close(kq_fd); + fn init(cwd_path: []const u8) !Watch { + _ = cwd_path; return .{ .dir_table = .{}, .dir_count = 0, .os = .{ - .kq_fd = kq_fd, + .kq_fd = try Io.Kqueue.createFileDescriptor(), .handles = .empty, }, .generation = 0, @@ -672,10 +684,10 @@ const Os = switch (builtin.os.tag) { if (!gop.found_existing) { const skip_open_dir = path.sub_path.len == 0; const dir_fd = if (skip_open_dir) - path.root_dir.handle.fd + path.root_dir.handle.handle else - posix.openat(path.root_dir.handle.fd, path.sub_path, dir_open_flags, 0) catch |err| { - fatal("failed to open directory {f}: {s}", .{ path, @errorName(err) }); + posix.openat(path.root_dir.handle.handle, path.sub_path, dir_open_flags, 0) catch |err| { + fatal("failed to open directory {f}: {t}", .{ path, err }); }; // Empirically the dir has to stay open or else no events are triggered. errdefer if (!skip_open_dir) posix.close(dir_fd); @@ -687,7 +699,7 @@ const Os = switch (builtin.os.tag) { .data = 0, .udata = gop.index, }}; - _ = try posix.kevent(w.os.kq_fd, &changes, &.{}, null); + _ = try Io.Kqueue.kevent(w.os.kq_fd, &changes, &.{}, null); assert(handles.len == gop.index); try handles.append(gpa, .{ .rs = .{}, @@ -741,7 +753,7 @@ const Os = switch (builtin.os.tag) { // to access that data via the dir_fd field. const path = w.dir_table.keys()[i]; const dir_fd = if (path.sub_path.len == 0) - path.root_dir.handle.fd + path.root_dir.handle.handle else handles.items(.dir_fd)[i]; assert(dir_fd != -1); @@ -752,7 +764,7 @@ const Os = switch (builtin.os.tag) { const last_dir_fd = fd: { const last_path = w.dir_table.keys()[handles.len - 1]; const last_dir_fd = if (last_path.sub_path.len == 0) - last_path.root_dir.handle.fd + last_path.root_dir.handle.handle else handles.items(.dir_fd)[handles.len - 1]; assert(last_dir_fd != -1); @@ -777,7 +789,7 @@ const Os = switch (builtin.os.tag) { }, }; const filtered_changes = if (i == handles.len - 1) changes[0..1] else &changes; - _ = try posix.kevent(w.os.kq_fd, filtered_changes, &.{}, null); + _ = try Io.Kqueue.kevent(w.os.kq_fd, filtered_changes, &.{}, null); if (path.sub_path.len != 0) posix.close(dir_fd); w.dir_table.swapRemoveAt(i); @@ -791,13 +803,13 @@ const Os = switch (builtin.os.tag) { fn wait(w: *Watch, gpa: Allocator, timeout: Timeout) !WaitResult { var timespec_buffer: posix.timespec = undefined; var event_buffer: [100]posix.Kevent = undefined; - var n = try posix.kevent(w.os.kq_fd, &.{}, &event_buffer, timeout.toTimespec(×pec_buffer)); + var n = try Io.Kqueue.kevent(w.os.kq_fd, &.{}, &event_buffer, timeout.toTimespec(×pec_buffer)); if (n == 0) return .timeout; const reaction_sets = w.os.handles.items(.rs); var any_dirty = markDirtySteps(gpa, reaction_sets, event_buffer[0..n], false); timespec_buffer = .{ .sec = 0, .nsec = 0 }; while (n == event_buffer.len) { - n = try posix.kevent(w.os.kq_fd, &.{}, &event_buffer, ×pec_buffer); + n = try Io.Kqueue.kevent(w.os.kq_fd, &.{}, &event_buffer, ×pec_buffer); if (n == 0) break; any_dirty = markDirtySteps(gpa, reaction_sets, event_buffer[0..n], any_dirty); } @@ -832,9 +844,9 @@ const Os = switch (builtin.os.tag) { .macos => struct { fse: FsEvents, - fn init() !Watch { + fn init(cwd_path: []const u8) !Watch { return .{ - .os = .{ .fse = try .init() }, + .os = .{ .fse = try .init(cwd_path) }, .dir_count = 0, .dir_table = undefined, .generation = undefined, @@ -854,8 +866,8 @@ const Os = switch (builtin.os.tag) { else => void, }; -pub fn init() !Watch { - return Os.init(); +pub fn init(cwd_path: []const u8) !Watch { + return Os.init(cwd_path); } pub const Match = struct { @@ -889,7 +901,7 @@ fn markAllFilesDirty(w: *Watch, gpa: Allocator) void { }; for (reaction_set.values()) |step_set| { for (step_set.keys()) |step| { - step.recursiveReset(gpa); + _ = step.invalidateResult(gpa); } } } @@ -898,10 +910,7 @@ fn markAllFilesDirty(w: *Watch, gpa: Allocator) void { fn markStepSetDirty(gpa: Allocator, step_set: *StepSet, any_dirty: bool) bool { var this_any_dirty = false; for (step_set.keys()) |step| { - if (step.state != .precheck_done) { - step.recursiveReset(gpa); - this_any_dirty = true; - } + if (step.invalidateResult(gpa)) this_any_dirty = true; } return any_dirty or this_any_dirty; } diff --git a/lib/std/Build/Watch/FsEvents.zig b/lib/std/Build/Watch/FsEvents.zig index 6131663993b0..c9d2ed219c7e 100644 --- a/lib/std/Build/Watch/FsEvents.zig +++ b/lib/std/Build/Watch/FsEvents.zig @@ -43,6 +43,8 @@ dispatch_queue: dispatch_queue_t, /// of writing. See the comment at the start of `wait` for details. since_event: FSEventStreamEventId, +cwd_path: []const u8, + /// All of the symbols we pull from the `dlopen`ed CoreServices framework. If any of these symbols /// is not present, `init` will close the framework and return an error. const ResolvedSymbols = struct { @@ -78,7 +80,7 @@ const ResolvedSymbols = struct { kCFAllocatorUseContext: *const CFAllocatorRef, }; -pub fn init() error{ OpenFrameworkFailed, MissingCoreServicesSymbol }!FsEvents { +pub fn init(cwd_path: []const u8) error{ OpenFrameworkFailed, MissingCoreServicesSymbol }!FsEvents { var core_services = std.DynLib.open("/System/Library/Frameworks/CoreServices.framework/CoreServices") catch return error.OpenFrameworkFailed; errdefer core_services.close(); @@ -99,13 +101,14 @@ pub fn init() error{ OpenFrameworkFailed, MissingCoreServicesSymbol }!FsEvents { // Not `.since_now`, because this means we can init `FsEvents` *before* we do work in order // to notice any changes which happened during said work. .since_event = resolved_symbols.FSEventsGetCurrentEventId(), + .cwd_path = cwd_path, }; } -pub fn deinit(fse: *FsEvents, gpa: Allocator) void { +pub fn deinit(fse: *FsEvents, gpa: Allocator, io: Io) void { dispatch_release(fse.waiting_semaphore); dispatch_release(fse.dispatch_queue); - fse.core_services.close(); + fse.core_services.close(io); gpa.free(fse.watch_roots); fse.watch_paths.deinit(gpa); @@ -120,9 +123,6 @@ pub fn setPaths(fse: *FsEvents, gpa: Allocator, steps: []const *std.Build.Step) defer fse.paths_arena = paths_arena_instance.state; const paths_arena = paths_arena_instance.allocator(); - const cwd_path = try std.process.getCwdAlloc(gpa); - defer gpa.free(cwd_path); - var need_dirs: std.StringArrayHashMapUnmanaged(void) = .empty; defer need_dirs.deinit(gpa); @@ -131,7 +131,9 @@ pub fn setPaths(fse: *FsEvents, gpa: Allocator, steps: []const *std.Build.Step) // We take `step` by pointer for a slight memory optimization in a moment. for (steps) |*step| { for (step.*.inputs.table.keys(), step.*.inputs.table.values()) |path, *files| { - const resolved_dir = try std.fs.path.resolvePosix(paths_arena, &.{ cwd_path, path.root_dir.path orelse ".", path.sub_path }); + const resolved_dir = try std.fs.path.resolvePosix(paths_arena, &.{ + fse.cwd_path, path.root_dir.path orelse ".", path.sub_path, + }); try need_dirs.put(gpa, resolved_dir, {}); for (files.items) |file_name| { const watch_path = if (std.mem.eql(u8, file_name, ".")) @@ -347,13 +349,17 @@ fn eventCallback( false => { if (fse.watch_paths.get(event_path)) |steps| { assert(steps.len > 0); - for (steps) |s| dirtyStep(s, gpa, &any_dirty); + for (steps) |s| { + if (s.invalidateResult(gpa)) any_dirty = true; + } } if (std.fs.path.dirname(event_path)) |event_dirname| { // Modifying '/foo/bar' triggers the watch on '/foo'. if (fse.watch_paths.get(event_dirname)) |steps| { assert(steps.len > 0); - for (steps) |s| dirtyStep(s, gpa, &any_dirty); + for (steps) |s| { + if (s.invalidateResult(gpa)) any_dirty = true; + } } } }, @@ -366,7 +372,9 @@ fn eventCallback( const changed_path = std.fs.path.dirname(event_path) orelse event_path; for (fse.watch_paths.keys(), fse.watch_paths.values()) |watching_path, steps| { if (dirStartsWith(watching_path, changed_path)) { - for (steps) |s| dirtyStep(s, gpa, &any_dirty); + for (steps) |s| { + if (s.invalidateResult(gpa)) any_dirty = true; + } } } }, @@ -377,11 +385,6 @@ fn eventCallback( _ = dispatch_semaphore_signal(fse.waiting_semaphore); } } -fn dirtyStep(s: *std.Build.Step, gpa: Allocator, any_dirty: *bool) void { - if (s.state == .precheck_done) return; - s.recursiveReset(gpa); - any_dirty.* = true; -} fn dirStartsWith(path: []const u8, prefix: []const u8) bool { if (std.mem.eql(u8, path, prefix)) return true; if (!std.mem.startsWith(u8, path, prefix)) return false; @@ -487,6 +490,7 @@ const FSEventStreamEventFlags = packed struct(u32) { }; const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; const Allocator = std.mem.Allocator; const watch_log = std.log.scoped(.watch); diff --git a/lib/std/Build/WebServer.zig b/lib/std/Build/WebServer.zig index 4d649e6f9ba9..cb201e991d78 100644 --- a/lib/std/Build/WebServer.zig +++ b/lib/std/Build/WebServer.zig @@ -2,7 +2,6 @@ gpa: Allocator, graph: *const Build.Graph, all_steps: []const *Build.Step, listen_address: net.IpAddress, -ttyconf: Io.tty.Config, root_prog_node: std.Progress.Node, watch: bool, @@ -52,7 +51,6 @@ pub fn notifyUpdate(ws: *WebServer) void { pub const Options = struct { gpa: Allocator, - ttyconf: Io.tty.Config, graph: *const std.Build.Graph, all_steps: []const *Build.Step, root_prog_node: std.Progress.Node, @@ -98,7 +96,6 @@ pub fn init(opts: Options) WebServer { return .{ .gpa = opts.gpa, - .ttyconf = opts.ttyconf, .graph = opts.graph, .all_steps = all_steps, .listen_address = opts.listen_address, @@ -122,13 +119,14 @@ pub fn init(opts: Options) WebServer { .update_id = .init(0), .runner_request_mutex = .init, - .runner_request_ready_cond = .{}, - .runner_request_empty_cond = .{}, + .runner_request_ready_cond = .init, + .runner_request_empty_cond = .init, .runner_request = null, }; } pub fn deinit(ws: *WebServer) void { const gpa = ws.gpa; + const io = ws.graph.io; gpa.free(ws.step_names_trailing); gpa.free(ws.step_status_bits); @@ -139,7 +137,7 @@ pub fn deinit(ws: *WebServer) void { gpa.free(ws.time_report_update_times); if (ws.serve_thread) |t| { - if (ws.tcp_server) |*s| s.stream.close(); + if (ws.tcp_server) |*s| s.stream.close(io); t.join(); } if (ws.tcp_server) |*s| s.deinit(); @@ -217,9 +215,9 @@ pub fn finishBuild(ws: *WebServer, opts: struct { else => {}, } if (@bitSizeOf(usize) != 64) { - // Current implementation depends on posix.mmap()'s second parameter, `length: usize`, - // being compatible with `std.fs.getEndPos() u64`'s return value. This is not the case - // on 32-bit platforms. + // Current implementation depends on posix.mmap()'s second + // parameter, `length: usize`, being compatible with file system's + // u64 return value. This is not the case on 32-bit platforms. // Affects or affected by issues #5185, #22523, and #22464. std.process.fatal("--fuzz not yet implemented on {d}-bit platforms", .{@bitSizeOf(usize)}); } @@ -232,7 +230,6 @@ pub fn finishBuild(ws: *WebServer, opts: struct { ws.fuzz = Fuzz.init( ws.gpa, ws.graph.io, - ws.ttyconf, ws.all_steps, ws.root_prog_node, .{ .forever = .{ .ws = ws } }, @@ -468,11 +465,12 @@ pub fn serveFile( content_type: []const u8, ) !void { const gpa = ws.gpa; + const io = ws.graph.io; // The desired API is actually sendfile, which will require enhancing http.Server. // We load the file with every request so that the user can make changes to the file // and refresh the HTML page without restarting this server. - const file_contents = path.root_dir.handle.readFileAlloc(path.sub_path, gpa, .limited(10 * 1024 * 1024)) catch |err| { - log.err("failed to read '{f}': {s}", .{ path, @errorName(err) }); + const file_contents = path.root_dir.handle.readFileAlloc(io, path.sub_path, gpa, .limited(10 * 1024 * 1024)) catch |err| { + log.err("failed to read '{f}': {t}", .{ path, err }); return error.AlreadyReported; }; defer gpa.free(file_contents); @@ -484,8 +482,8 @@ pub fn serveFile( }); } pub fn serveTarFile(ws: *WebServer, request: *http.Server.Request, paths: []const Cache.Path) !void { - const gpa = ws.gpa; - const io = ws.graph.io; + const graph = ws.graph; + const io = graph.io; var send_buffer: [0x4000]u8 = undefined; var response = try request.respondStreaming(&send_buffer, .{ @@ -497,20 +495,17 @@ pub fn serveTarFile(ws: *WebServer, request: *http.Server.Request, paths: []cons }, }); - var cached_cwd_path: ?[]const u8 = null; - defer if (cached_cwd_path) |p| gpa.free(p); - var archiver: std.tar.Writer = .{ .underlying_writer = &response.writer }; for (paths) |path| { - var file = path.root_dir.handle.openFile(path.sub_path, .{}) catch |err| { + var file = path.root_dir.handle.openFile(io, path.sub_path, .{}) catch |err| { log.err("failed to open '{f}': {s}", .{ path, @errorName(err) }); continue; }; - defer file.close(); - const stat = try file.stat(); + defer file.close(io); + const stat = try file.stat(io); var read_buffer: [1024]u8 = undefined; - var file_reader: Io.File.Reader = .initSize(file.adaptToNewApi(), io, &read_buffer, stat.size); + var file_reader: Io.File.Reader = .initSize(file, io, &read_buffer, stat.size); // TODO: this logic is completely bogus -- obviously so, because `path.root_dir.path` can // be cwd-relative. This is also related to why linkification doesn't work in the fuzzer UI: @@ -518,10 +513,7 @@ pub fn serveTarFile(ws: *WebServer, request: *http.Server.Request, paths: []cons // resulting in modules named "" and "src". The compiler needs to tell the build system // about the module graph so that the build system can correctly encode this information in // the tar file. - archiver.prefix = path.root_dir.path orelse cwd: { - if (cached_cwd_path == null) cached_cwd_path = try std.process.getCwdAlloc(gpa); - break :cwd cached_cwd_path.?; - }; + archiver.prefix = path.root_dir.path orelse graph.cache.cwd; try archiver.writeFile(path.sub_path, &file_reader, @intCast(stat.mtime.toSeconds())); } @@ -530,13 +522,13 @@ pub fn serveTarFile(ws: *WebServer, request: *http.Server.Request, paths: []cons } fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.OptimizeMode) !Cache.Path { - const io = ws.graph.io; const root_name = "build-web"; const arch_os_abi = "wasm32-freestanding"; const cpu_features = "baseline+atomics+bulk_memory+multivalue+mutable_globals+nontrapping_fptoint+reference_types+sign_ext"; const gpa = ws.gpa; const graph = ws.graph; + const io = graph.io; const main_src_path: Cache.Path = .{ .root_dir = graph.zig_lib_directory, @@ -574,11 +566,14 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim "--listen=-", }); - var child: std.process.Child = .init(argv.items, gpa); - child.stdin_behavior = .Pipe; - child.stdout_behavior = .Pipe; - child.stderr_behavior = .Pipe; - try child.spawn(); + var child = try std.process.spawn(io, .{ + .argv = argv.items, + .environ_map = &graph.environ_map, + .stdin = .pipe, + .stdout = .pipe, + .stderr = .pipe, + }); + defer child.kill(io); var poller = Io.poll(gpa, enum { stdout, stderr }, .{ .stdout = child.stdout.?, @@ -586,7 +581,7 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim }); defer poller.deinit(); - try child.stdin.?.writeAll(@ptrCast(@as([]const std.zig.Client.Message.Header, &.{ + try child.stdin.?.writeStreamingAll(io, @ptrCast(@as([]const std.zig.Client.Message.Header, &.{ .{ .tag = .update, .bytes_len = 0 }, .{ .tag = .exit, .bytes_len = 0 }, }))); @@ -634,40 +629,47 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim } // Send EOF to stdin. - child.stdin.?.close(); + child.stdin.?.close(io); child.stdin = null; - switch (try child.wait()) { - .Exited => |code| { + switch (try child.wait(io)) { + .exited => |code| { if (code != 0) { log.err( "the following command exited with error code {d}:\n{s}", - .{ code, try Build.Step.allocPrintCmd(arena, null, argv.items) }, + .{ code, try Build.Step.allocPrintCmd(arena, null, null, argv.items) }, ); return error.WasmCompilationFailed; } }, - .Signal, .Stopped, .Unknown => { + .signal => |sig| { + log.err( + "the following command terminated with signal {t}:\n{s}", + .{ sig, try Build.Step.allocPrintCmd(arena, null, null, argv.items) }, + ); + return error.WasmCompilationFailed; + }, + .stopped, .unknown => { log.err( "the following command terminated unexpectedly:\n{s}", - .{try Build.Step.allocPrintCmd(arena, null, argv.items)}, + .{try Build.Step.allocPrintCmd(arena, null, null, argv.items)}, ); return error.WasmCompilationFailed; }, } if (result_error_bundle.errorMessageCount() > 0) { - result_error_bundle.renderToStdErr(.{}, .auto); + try result_error_bundle.renderToStderr(io, .{}, .auto); log.err("the following command failed with {d} compilation errors:\n{s}", .{ result_error_bundle.errorMessageCount(), - try Build.Step.allocPrintCmd(arena, null, argv.items), + try Build.Step.allocPrintCmd(arena, null, null, argv.items), }); return error.WasmCompilationFailed; } const base_path = result orelse { log.err("child process failed to report result\n{s}", .{ - try Build.Step.allocPrintCmd(arena, null, argv.items), + try Build.Step.allocPrintCmd(arena, null, null, argv.items), }); return error.WasmCompilationFailed; }; diff --git a/lib/std/Io.zig b/lib/std/Io.zig index aa860abb364e..b4d6efc715f1 100644 --- a/lib/std/Io.zig +++ b/lib/std/Io.zig @@ -1,3 +1,18 @@ +//! A cross-platform interface that abstracts all I/O operations and +//! concurrency. It includes: +//! * file system +//! * networking +//! * processes +//! * time and sleeping +//! * randomness +//! * async, await, concurrent, and cancel +//! * concurrent queues +//! * wait groups and select +//! * mutexes, futexes, events, and conditions +//! This interface allows programmers to write optimal, reusable code while +//! participating in these operations. +const Io = @This(); + const builtin = @import("builtin"); const is_windows = builtin.os.tag == .windows; @@ -9,81 +24,6 @@ const assert = std.debug.assert; const Allocator = std.mem.Allocator; const Alignment = std.mem.Alignment; -pub const Limit = enum(usize) { - nothing = 0, - unlimited = std.math.maxInt(usize), - _, - - /// `std.math.maxInt(usize)` is interpreted to mean `.unlimited`. - pub fn limited(n: usize) Limit { - return @enumFromInt(n); - } - - /// Any value grater than `std.math.maxInt(usize)` is interpreted to mean - /// `.unlimited`. - pub fn limited64(n: u64) Limit { - return @enumFromInt(@min(n, std.math.maxInt(usize))); - } - - pub fn countVec(data: []const []const u8) Limit { - var total: usize = 0; - for (data) |d| total += d.len; - return .limited(total); - } - - pub fn min(a: Limit, b: Limit) Limit { - return @enumFromInt(@min(@intFromEnum(a), @intFromEnum(b))); - } - - pub fn minInt(l: Limit, n: usize) usize { - return @min(n, @intFromEnum(l)); - } - - pub fn minInt64(l: Limit, n: u64) usize { - return @min(n, @intFromEnum(l)); - } - - pub fn slice(l: Limit, s: []u8) []u8 { - return s[0..l.minInt(s.len)]; - } - - pub fn sliceConst(l: Limit, s: []const u8) []const u8 { - return s[0..l.minInt(s.len)]; - } - - pub fn toInt(l: Limit) ?usize { - return switch (l) { - else => @intFromEnum(l), - .unlimited => null, - }; - } - - /// Reduces a slice to account for the limit, leaving room for one extra - /// byte above the limit, allowing for the use case of differentiating - /// between end-of-stream and reaching the limit. - pub fn slice1(l: Limit, non_empty_buffer: []u8) []u8 { - assert(non_empty_buffer.len >= 1); - return non_empty_buffer[0..@min(@intFromEnum(l) +| 1, non_empty_buffer.len)]; - } - - pub fn nonzero(l: Limit) bool { - return @intFromEnum(l) > 0; - } - - /// Return a new limit reduced by `amount` or return `null` indicating - /// limit would be exceeded. - pub fn subtract(l: Limit, amount: usize) ?Limit { - if (l == .unlimited) return .unlimited; - if (amount > @intFromEnum(l)) return null; - return @enumFromInt(@intFromEnum(l) - amount); - } -}; - -pub const Reader = @import("Io/Reader.zig"); -pub const Writer = @import("Io/Writer.zig"); - -pub const tty = @import("Io/tty.zig"); - pub fn poll( gpa: Allocator, comptime StreamEnum: type, @@ -438,7 +378,7 @@ pub fn Poller(comptime StreamEnum: type) type { // Cancel the pending read into the FIFO. _ = windows.kernel32.CancelIo(handle); - // We have to wait for the handle to be signalled, i.e. for the cancellation to complete. + // We have to wait for the handle to be signalled, i.e. for the cancelation to complete. switch (windows.kernel32.WaitForSingleObject(handle, windows.INFINITE)) { windows.WAIT_OBJECT_0 => {}, windows.WAIT_FAILED => return windows.unexpectedError(windows.GetLastError()), @@ -528,37 +468,33 @@ pub fn Poller(comptime StreamEnum: type) type { /// Given an enum, returns a struct with fields of that enum, each field /// representing an I/O stream for polling. pub fn PollFiles(comptime StreamEnum: type) type { - return @Struct(.auto, null, std.meta.fieldNames(StreamEnum), &@splat(std.fs.File), &@splat(.{})); -} - -test { - _ = net; - _ = Reader; - _ = Writer; - _ = tty; - _ = Evented; - _ = Threaded; - _ = @import("Io/test.zig"); + return @Struct(.auto, null, std.meta.fieldNames(StreamEnum), &@splat(Io.File), &@splat(.{})); } -const Io = @This(); +userdata: ?*anyopaque, +vtable: *const VTable, +pub const Threaded = @import("Io/Threaded.zig"); pub const Evented = switch (builtin.os.tag) { .linux => switch (builtin.cpu.arch) { - .x86_64, .aarch64 => @import("Io/IoUring.zig"), + .x86_64, .aarch64 => IoUring, else => void, // context-switching code not implemented yet }, .dragonfly, .freebsd, .netbsd, .openbsd, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => switch (builtin.cpu.arch) { - .x86_64, .aarch64 => @import("Io/Kqueue.zig"), + .x86_64, .aarch64 => Kqueue, else => void, // context-switching code not implemented yet }, else => void, }; -pub const Threaded = @import("Io/Threaded.zig"); -pub const net = @import("Io/net.zig"); +pub const Kqueue = @import("Io/Kqueue.zig"); +pub const IoUring = @import("Io/IoUring.zig"); -userdata: ?*anyopaque, -vtable: *const VTable, +pub const Reader = @import("Io/Reader.zig"); +pub const Writer = @import("Io/Writer.zig"); +pub const net = @import("Io/net.zig"); +pub const Dir = @import("Io/Dir.zig"); +pub const File = @import("Io/File.zig"); +pub const Terminal = @import("Io/Terminal.zig"); pub const VTable = struct { /// If it returns `null` it means `result` has been already populated and @@ -620,11 +556,6 @@ pub const VTable = struct { result: []u8, result_alignment: std.mem.Alignment, ) void, - /// Returns whether the current thread of execution is known to have - /// been requested to cancel. - /// - /// Thread-safe. - cancelRequested: *const fn (?*anyopaque) bool, /// When this function returns, implementation guarantees that `start` has /// either already been called, or a unit of concurrency has been assigned @@ -639,7 +570,7 @@ pub const VTable = struct { /// Copied and then passed to `start`. context: []const u8, context_alignment: std.mem.Alignment, - start: *const fn (*Group, context: *const anyopaque) void, + start: *const fn (context: *const anyopaque) Cancelable!void, ) void, /// Thread-safe. groupConcurrent: *const fn ( @@ -650,48 +581,99 @@ pub const VTable = struct { /// Copied and then passed to `start`. context: []const u8, context_alignment: std.mem.Alignment, - start: *const fn (*Group, context: *const anyopaque) void, + start: *const fn (context: *const anyopaque) Cancelable!void, ) ConcurrentError!void, - groupWait: *const fn (?*anyopaque, *Group, token: *anyopaque) void, + groupAwait: *const fn (?*anyopaque, *Group, token: *anyopaque) Cancelable!void, groupCancel: *const fn (?*anyopaque, *Group, token: *anyopaque) void, + recancel: *const fn (?*anyopaque) void, + swapCancelProtection: *const fn (?*anyopaque, new: CancelProtection) CancelProtection, + checkCancel: *const fn (?*anyopaque) Cancelable!void, + /// Blocks until one of the futures from the list has a result ready, such /// that awaiting it will not block. Returns that index. select: *const fn (?*anyopaque, futures: []const *AnyFuture) Cancelable!usize, - mutexLock: *const fn (?*anyopaque, prev_state: Mutex.State, mutex: *Mutex) Cancelable!void, - mutexLockUncancelable: *const fn (?*anyopaque, prev_state: Mutex.State, mutex: *Mutex) void, - mutexUnlock: *const fn (?*anyopaque, prev_state: Mutex.State, mutex: *Mutex) void, + futexWait: *const fn (?*anyopaque, ptr: *const u32, expected: u32, Timeout) Cancelable!void, + futexWaitUncancelable: *const fn (?*anyopaque, ptr: *const u32, expected: u32) void, + futexWake: *const fn (?*anyopaque, ptr: *const u32, max_waiters: u32) void, - conditionWait: *const fn (?*anyopaque, cond: *Condition, mutex: *Mutex) Cancelable!void, - conditionWaitUncancelable: *const fn (?*anyopaque, cond: *Condition, mutex: *Mutex) void, - conditionWake: *const fn (?*anyopaque, cond: *Condition, wake: Condition.Wake) void, - - dirMake: *const fn (?*anyopaque, Dir, sub_path: []const u8, Dir.Mode) Dir.MakeError!void, - dirMakePath: *const fn (?*anyopaque, Dir, sub_path: []const u8, Dir.Mode) Dir.MakeError!void, - dirMakeOpenPath: *const fn (?*anyopaque, Dir, sub_path: []const u8, Dir.OpenOptions) Dir.MakeOpenPathError!Dir, + dirCreateDir: *const fn (?*anyopaque, Dir, []const u8, Dir.Permissions) Dir.CreateDirError!void, + dirCreateDirPath: *const fn (?*anyopaque, Dir, []const u8, Dir.Permissions) Dir.CreateDirPathError!Dir.CreatePathStatus, + dirCreateDirPathOpen: *const fn (?*anyopaque, Dir, []const u8, Dir.Permissions, Dir.OpenOptions) Dir.CreateDirPathOpenError!Dir, + dirOpenDir: *const fn (?*anyopaque, Dir, []const u8, Dir.OpenOptions) Dir.OpenError!Dir, dirStat: *const fn (?*anyopaque, Dir) Dir.StatError!Dir.Stat, - dirStatPath: *const fn (?*anyopaque, Dir, sub_path: []const u8, Dir.StatPathOptions) Dir.StatPathError!File.Stat, - dirAccess: *const fn (?*anyopaque, Dir, sub_path: []const u8, Dir.AccessOptions) Dir.AccessError!void, - dirCreateFile: *const fn (?*anyopaque, Dir, sub_path: []const u8, File.CreateFlags) File.OpenError!File, - dirOpenFile: *const fn (?*anyopaque, Dir, sub_path: []const u8, File.OpenFlags) File.OpenError!File, - dirOpenDir: *const fn (?*anyopaque, Dir, sub_path: []const u8, Dir.OpenOptions) Dir.OpenError!Dir, - dirClose: *const fn (?*anyopaque, Dir) void, + dirStatFile: *const fn (?*anyopaque, Dir, []const u8, Dir.StatFileOptions) Dir.StatFileError!File.Stat, + dirAccess: *const fn (?*anyopaque, Dir, []const u8, Dir.AccessOptions) Dir.AccessError!void, + dirCreateFile: *const fn (?*anyopaque, Dir, []const u8, File.CreateFlags) File.OpenError!File, + dirCreateFileAtomic: *const fn (?*anyopaque, Dir, []const u8, Dir.CreateFileAtomicOptions) Dir.CreateFileAtomicError!File.Atomic, + dirOpenFile: *const fn (?*anyopaque, Dir, []const u8, File.OpenFlags) File.OpenError!File, + dirClose: *const fn (?*anyopaque, []const Dir) void, + dirRead: *const fn (?*anyopaque, *Dir.Reader, []Dir.Entry) Dir.Reader.Error!usize, + dirRealPath: *const fn (?*anyopaque, Dir, out_buffer: []u8) Dir.RealPathError!usize, + dirRealPathFile: *const fn (?*anyopaque, Dir, path_name: []const u8, out_buffer: []u8) Dir.RealPathFileError!usize, + dirDeleteFile: *const fn (?*anyopaque, Dir, []const u8) Dir.DeleteFileError!void, + dirDeleteDir: *const fn (?*anyopaque, Dir, []const u8) Dir.DeleteDirError!void, + dirRename: *const fn (?*anyopaque, old_dir: Dir, old_sub_path: []const u8, new_dir: Dir, new_sub_path: []const u8) Dir.RenameError!void, + dirRenamePreserve: *const fn (?*anyopaque, old_dir: Dir, old_sub_path: []const u8, new_dir: Dir, new_sub_path: []const u8) Dir.RenamePreserveError!void, + dirSymLink: *const fn (?*anyopaque, Dir, target_path: []const u8, sym_link_path: []const u8, Dir.SymLinkFlags) Dir.SymLinkError!void, + dirReadLink: *const fn (?*anyopaque, Dir, sub_path: []const u8, buffer: []u8) Dir.ReadLinkError!usize, + dirSetOwner: *const fn (?*anyopaque, Dir, ?File.Uid, ?File.Gid) Dir.SetOwnerError!void, + dirSetFileOwner: *const fn (?*anyopaque, Dir, []const u8, ?File.Uid, ?File.Gid, Dir.SetFileOwnerOptions) Dir.SetFileOwnerError!void, + dirSetPermissions: *const fn (?*anyopaque, Dir, Dir.Permissions) Dir.SetPermissionsError!void, + dirSetFilePermissions: *const fn (?*anyopaque, Dir, []const u8, File.Permissions, Dir.SetFilePermissionsOptions) Dir.SetFilePermissionsError!void, + dirSetTimestamps: *const fn (?*anyopaque, Dir, []const u8, Dir.SetTimestampsOptions) Dir.SetTimestampsError!void, + dirHardLink: *const fn (?*anyopaque, old_dir: Dir, old_sub_path: []const u8, new_dir: Dir, new_sub_path: []const u8, Dir.HardLinkOptions) Dir.HardLinkError!void, + fileStat: *const fn (?*anyopaque, File) File.StatError!File.Stat, - fileClose: *const fn (?*anyopaque, File) void, - fileWriteStreaming: *const fn (?*anyopaque, File, buffer: [][]const u8) File.WriteStreamingError!usize, - fileWritePositional: *const fn (?*anyopaque, File, buffer: [][]const u8, offset: u64) File.WritePositionalError!usize, + fileLength: *const fn (?*anyopaque, File) File.LengthError!u64, + fileClose: *const fn (?*anyopaque, []const File) void, + fileWriteStreaming: *const fn (?*anyopaque, File, header: []const u8, data: []const []const u8, splat: usize) File.Writer.Error!usize, + fileWritePositional: *const fn (?*anyopaque, File, header: []const u8, data: []const []const u8, splat: usize, offset: u64) File.WritePositionalError!usize, + fileWriteFileStreaming: *const fn (?*anyopaque, File, header: []const u8, *Io.File.Reader, Io.Limit) File.Writer.WriteFileError!usize, + fileWriteFilePositional: *const fn (?*anyopaque, File, header: []const u8, *Io.File.Reader, Io.Limit, offset: u64) File.WriteFilePositionalError!usize, /// Returns 0 on end of stream. - fileReadStreaming: *const fn (?*anyopaque, File, data: [][]u8) File.Reader.Error!usize, + fileReadStreaming: *const fn (?*anyopaque, File, data: []const []u8) File.Reader.Error!usize, /// Returns 0 on end of stream. - fileReadPositional: *const fn (?*anyopaque, File, data: [][]u8, offset: u64) File.ReadPositionalError!usize, + fileReadPositional: *const fn (?*anyopaque, File, data: []const []u8, offset: u64) File.ReadPositionalError!usize, fileSeekBy: *const fn (?*anyopaque, File, relative_offset: i64) File.SeekError!void, fileSeekTo: *const fn (?*anyopaque, File, absolute_offset: u64) File.SeekError!void, - openSelfExe: *const fn (?*anyopaque, File.OpenFlags) File.OpenSelfExeError!File, + fileSync: *const fn (?*anyopaque, File) File.SyncError!void, + fileIsTty: *const fn (?*anyopaque, File) Cancelable!bool, + fileEnableAnsiEscapeCodes: *const fn (?*anyopaque, File) File.EnableAnsiEscapeCodesError!void, + fileSupportsAnsiEscapeCodes: *const fn (?*anyopaque, File) Cancelable!bool, + fileSetLength: *const fn (?*anyopaque, File, u64) File.SetLengthError!void, + fileSetOwner: *const fn (?*anyopaque, File, ?File.Uid, ?File.Gid) File.SetOwnerError!void, + fileSetPermissions: *const fn (?*anyopaque, File, File.Permissions) File.SetPermissionsError!void, + fileSetTimestamps: *const fn (?*anyopaque, File, File.SetTimestampsOptions) File.SetTimestampsError!void, + fileLock: *const fn (?*anyopaque, File, File.Lock) File.LockError!void, + fileTryLock: *const fn (?*anyopaque, File, File.Lock) File.LockError!bool, + fileUnlock: *const fn (?*anyopaque, File) void, + fileDowngradeLock: *const fn (?*anyopaque, File) File.DowngradeLockError!void, + fileRealPath: *const fn (?*anyopaque, File, out_buffer: []u8) File.RealPathError!usize, + fileHardLink: *const fn (?*anyopaque, File, Dir, []const u8, File.HardLinkOptions) File.HardLinkError!void, + + processExecutableOpen: *const fn (?*anyopaque, File.OpenFlags) std.process.OpenExecutableError!File, + processExecutablePath: *const fn (?*anyopaque, buffer: []u8) std.process.ExecutablePathError!usize, + lockStderr: *const fn (?*anyopaque, ?Terminal.Mode) Cancelable!LockedStderr, + tryLockStderr: *const fn (?*anyopaque, ?Terminal.Mode) Cancelable!?LockedStderr, + unlockStderr: *const fn (?*anyopaque) void, + processSetCurrentDir: *const fn (?*anyopaque, Dir) std.process.SetCurrentDirError!void, + processReplace: *const fn (?*anyopaque, std.process.ReplaceOptions) std.process.ReplaceError, + processReplacePath: *const fn (?*anyopaque, Dir, std.process.ReplaceOptions) std.process.ReplaceError, + processSpawn: *const fn (?*anyopaque, std.process.SpawnOptions) std.process.SpawnError!std.process.Child, + processSpawnPath: *const fn (?*anyopaque, Dir, std.process.SpawnOptions) std.process.SpawnError!std.process.Child, + childWait: *const fn (?*anyopaque, *std.process.Child) std.process.Child.WaitError!std.process.Child.Term, + childKill: *const fn (?*anyopaque, *std.process.Child) void, + + progressParentFile: *const fn (?*anyopaque) std.Progress.ParentFileError!File, now: *const fn (?*anyopaque, Clock) Clock.Error!Timestamp, sleep: *const fn (?*anyopaque, Timeout) SleepError!void, + random: *const fn (?*anyopaque, buffer: []u8) void, + randomSecure: *const fn (?*anyopaque, buffer: []u8) RandomSecureError!void, + netListenIp: *const fn (?*anyopaque, address: net.IpAddress, net.IpAddress.ListenOptions) net.IpAddress.ListenError!net.Server, netAccept: *const fn (?*anyopaque, server: net.Socket.Handle) net.Server.AcceptError!net.Stream, netBindIp: *const fn (?*anyopaque, address: *const net.IpAddress, options: net.IpAddress.BindOptions) net.IpAddress.BindError!net.Socket, @@ -703,10 +685,82 @@ pub const VTable = struct { /// Returns 0 on end of stream. netRead: *const fn (?*anyopaque, src: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize, netWrite: *const fn (?*anyopaque, dest: net.Socket.Handle, header: []const u8, data: []const []const u8, splat: usize) net.Stream.Writer.Error!usize, - netClose: *const fn (?*anyopaque, handle: net.Socket.Handle) void, + netWriteFile: *const fn (?*anyopaque, net.Socket.Handle, header: []const u8, *Io.File.Reader, Io.Limit) net.Stream.Writer.WriteFileError!usize, + netClose: *const fn (?*anyopaque, handle: []const net.Socket.Handle) void, + netShutdown: *const fn (?*anyopaque, handle: net.Socket.Handle, how: net.ShutdownHow) net.ShutdownError!void, netInterfaceNameResolve: *const fn (?*anyopaque, *const net.Interface.Name) net.Interface.Name.ResolveError!net.Interface, netInterfaceName: *const fn (?*anyopaque, net.Interface) net.Interface.NameError!net.Interface.Name, - netLookup: *const fn (?*anyopaque, net.HostName, *Queue(net.HostName.LookupResult), net.HostName.LookupOptions) void, + netLookup: *const fn (?*anyopaque, net.HostName, *Queue(net.HostName.LookupResult), net.HostName.LookupOptions) net.HostName.LookupError!void, +}; + +pub const Limit = enum(usize) { + nothing = 0, + unlimited = std.math.maxInt(usize), + _, + + /// `std.math.maxInt(usize)` is interpreted to mean `.unlimited`. + pub fn limited(n: usize) Limit { + return @enumFromInt(n); + } + + /// Any value grater than `std.math.maxInt(usize)` is interpreted to mean + /// `.unlimited`. + pub fn limited64(n: u64) Limit { + return @enumFromInt(@min(n, std.math.maxInt(usize))); + } + + pub fn countVec(data: []const []const u8) Limit { + var total: usize = 0; + for (data) |d| total += d.len; + return .limited(total); + } + + pub fn min(a: Limit, b: Limit) Limit { + return @enumFromInt(@min(@intFromEnum(a), @intFromEnum(b))); + } + + pub fn minInt(l: Limit, n: usize) usize { + return @min(n, @intFromEnum(l)); + } + + pub fn minInt64(l: Limit, n: u64) usize { + return @min(n, @intFromEnum(l)); + } + + pub fn slice(l: Limit, s: []u8) []u8 { + return s[0..l.minInt(s.len)]; + } + + pub fn sliceConst(l: Limit, s: []const u8) []const u8 { + return s[0..l.minInt(s.len)]; + } + + pub fn toInt(l: Limit) ?usize { + return switch (l) { + else => @intFromEnum(l), + .unlimited => null, + }; + } + + /// Reduces a slice to account for the limit, leaving room for one extra + /// byte above the limit, allowing for the use case of differentiating + /// between end-of-stream and reaching the limit. + pub fn slice1(l: Limit, non_empty_buffer: []u8) []u8 { + assert(non_empty_buffer.len >= 1); + return non_empty_buffer[0..@min(@intFromEnum(l) +| 1, non_empty_buffer.len)]; + } + + pub fn nonzero(l: Limit) bool { + return @intFromEnum(l) > 0; + } + + /// Return a new limit reduced by `amount` or return `null` indicating + /// limit would be exceeded. + pub fn subtract(l: Limit, amount: usize) ?Limit { + if (l == .unlimited) return .unlimited; + if (amount > @intFromEnum(l)) return null; + return @enumFromInt(@intFromEnum(l) - amount); + } }; pub const Cancelable = error{ @@ -726,9 +780,6 @@ pub const UnexpectedError = error{ Unexpected, }; -pub const Dir = @import("Io/Dir.zig"); -pub const File = @import("Io/File.zig"); - pub const Clock = enum { /// A settable system-wide clock that measures real (i.e. wall-clock) /// time. This clock is affected by discontinuous jumps in the system @@ -895,7 +946,7 @@ pub const Timestamp = struct { } pub fn withClock(t: Timestamp, clock: Clock) Clock.Timestamp { - return .{ .nanoseconds = t.nanoseconds, .clock = clock }; + return .{ .raw = t, .clock = clock }; } pub fn fromNanoseconds(x: i96) Timestamp { @@ -991,7 +1042,14 @@ pub fn Future(Result: type) type { any_future: ?*AnyFuture, result: Result, - /// Equivalent to `await` but places a cancellation request. + /// Equivalent to `await` but places a cancelation request. This causes the task to receive + /// `error.Canceled` from its next "cancelation point" (if any). A cancelation point is a + /// call to a function in `Io` which can return `error.Canceled`. + /// + /// After cancelation of a task is requested, only the next cancelation point in that task + /// will return `error.Canceled`: future points will not re-signal the cancelation. As such, + /// it is usually a bug to ignore `error.Canceled`. However, to defer handling cancelation + /// requests, see also `recancel` and `CancelProtection`. /// /// Idempotent. Not threadsafe. pub fn cancel(f: *@This(), io: Io) Result { @@ -1011,91 +1069,154 @@ pub fn Future(Result: type) type { }; } +/// An unordered set of tasks which can only be awaited or canceled as a whole. +/// Tasks are spawned in the group with `Group.async` and `Group.concurrent`. +/// +/// The resources associated with each task are *guaranteed* to be released when +/// the individual task returns, as opposed to when the whole group completes or +/// is awaited. For this reason, it is not a resource leak to have a long-lived +/// group which concurrent tasks are repeatedly added to. However, asynchronous +/// tasks are not guaranteed to run until `Group.await` or `Group.cancel` is +/// called, so adding async tasks to a group without ever awaiting it may leak +/// resources. pub const Group = struct { + /// This value indicates whether or not a group has pending tasks. `null` + /// means there are no pending tasks, and no resources associated with the + /// group, so `await` and `cancel` return immediately without calling the + /// implementation. This means that `token` must be accessed atomically to + /// avoid racing with the check in `await` and `cancel`. + token: std.atomic.Value(?*anyopaque), + /// This value is available for the implementation to use as it wishes. state: usize, - context: ?*anyopaque, - token: ?*anyopaque, - pub const init: Group = .{ .state = 0, .context = null, .token = null }; + pub const init: Group = .{ .token = .init(null), .state = 0 }; - /// Calls `function` with `args` asynchronously. The resource spawned is - /// owned by the group. - /// - /// `function` *may* be called immediately, before `async` returns. - /// - /// When this function returns, it is guaranteed that `function` has - /// already been called and completed, or it has successfully been assigned - /// a unit of concurrency. - /// - /// After this is called, `wait` or `cancel` must be called before the - /// group is deinitialized. + /// Equivalent to `Io.async`, except the task is spawned in this `Group` + /// instead of becoming associated with a `Future`. /// - /// Threadsafe. + /// The return type of `function` must be coercible to `Cancelable!void`. /// - /// See also: - /// * `concurrent` - /// * `Io.async` + /// Once this function is called, there are resources associated with the + /// group. To release those resources, `Group.await` or `Group.cancel` must + /// eventually be called. pub fn async(g: *Group, io: Io, function: anytype, args: std.meta.ArgsTuple(@TypeOf(function))) void { const Args = @TypeOf(args); const TypeErased = struct { - fn start(group: *Group, context: *const anyopaque) void { - _ = group; + fn start(context: *const anyopaque) Cancelable!void { const args_casted: *const Args = @ptrCast(@alignCast(context)); - @call(.auto, function, args_casted.*); + return @call(.auto, function, args_casted.*); } }; io.vtable.groupAsync(io.userdata, g, @ptrCast(&args), .of(Args), TypeErased.start); } - /// Calls `function` with `args`, such that the function is not guaranteed - /// to have returned until `wait` is called, allowing the caller to - /// progress while waiting for any `Io` operations. + /// Equivalent to `Io.concurrent`, except the task is spawned in this + /// `Group` instead of becoming associated with a `Future`. /// - /// The resource spawned is owned by the group; after this is called, - /// `wait` or `cancel` must be called before the group is deinitialized. + /// The return type of `function` must be coercible to `Cancelable!void`. /// - /// This has stronger guarantee than `async`, placing restrictions on what kind - /// of `Io` implementations are supported. By calling `async` instead, one - /// allows, for example, stackful single-threaded blocking I/O. - /// - /// Threadsafe. - /// - /// See also: - /// * `async` - /// * `Io.concurrent` + /// Once this function is called, there are resources associated with the + /// group. To release those resources, `Group.await` or `Group.cancel` must + /// eventually be called. pub fn concurrent(g: *Group, io: Io, function: anytype, args: std.meta.ArgsTuple(@TypeOf(function))) ConcurrentError!void { const Args = @TypeOf(args); const TypeErased = struct { - fn start(group: *Group, context: *const anyopaque) void { - _ = group; + fn start(context: *const anyopaque) Cancelable!void { const args_casted: *const Args = @ptrCast(@alignCast(context)); - @call(.auto, function, args_casted.*); + return @call(.auto, function, args_casted.*); } }; return io.vtable.groupConcurrent(io.userdata, g, @ptrCast(&args), .of(Args), TypeErased.start); } /// Blocks until all tasks of the group finish. During this time, - /// cancellation requests propagate to all members of the group. + /// cancelation requests propagate to all members of the group, and + /// will also cause `error.Canceled` to be returned when the group + /// does ultimately finish. /// /// Idempotent. Not threadsafe. - pub fn wait(g: *Group, io: Io) void { - const token = g.token orelse return; - g.token = null; - io.vtable.groupWait(io.userdata, g, token); + /// + /// It is safe to call this function concurrently with `Group.async` or + /// `Group.concurrent`, provided that the group does not complete until + /// the call to `Group.async` or `Group.concurrent` returns. + pub fn await(g: *Group, io: Io) Cancelable!void { + const token = g.token.load(.acquire) orelse return; + try io.vtable.groupAwait(io.userdata, g, token); + assert(g.token.raw == null); } - /// Equivalent to `wait` but immediately requests cancellation on all + /// Equivalent to `await` but immediately requests cancelation on all /// members of the group. /// + /// For a description of cancelation and cancelation points, see `Future.cancel`. + /// /// Idempotent. Not threadsafe. + /// + /// It is safe to call this function concurrently with `Group.async` or + /// `Group.concurrent`, provided that the group does not complete until + /// the call to `Group.async` or `Group.concurrent` returns. pub fn cancel(g: *Group, io: Io) void { - const token = g.token orelse return; - g.token = null; + const token = g.token.load(.acquire) orelse return; io.vtable.groupCancel(io.userdata, g, token); + assert(g.token.raw == null); } }; +/// Asserts that `error.Canceled` was returned from a prior cancelation point, and "re-arms" the +/// cancelation request, so that `error.Canceled` will be returned again from the next cancelation +/// point. +/// +/// For a description of cancelation and cancelation points, see `Future.cancel`. +pub fn recancel(io: Io) void { + io.vtable.recancel(io.userdata); +} + +/// In rare cases, it is desirable to completely block cancelation notification, so that a region +/// of code can run uninterrupted before `error.Canceled` is potentially observed. Therefore, every +/// task has a "cancel protection" state which indicates whether or not `Io` functions can introduce +/// cancelation points. +/// +/// To modify a task's cancel protection state, see `swapCancelProtection`. +/// +/// For a description of cancelation and cancelation points, see `Future.cancel`. +pub const CancelProtection = enum { + /// Any call to an `Io` function with `error.Canceled` in its error set is a cancelation point. + /// + /// This is the default state, which all tasks are created in. + unblocked, + /// No `Io` function introduces a cancelation point (`error.Canceled` will never be returned). + blocked, +}; +/// Updates the current task's cancel protection state (see `CancelProtection`). +/// +/// The typical usage for this function is to protect a block of code from cancelation: +/// ``` +/// const old_cancel_protect = io.swapCancelProtection(.blocked); +/// defer _ = io.swapCancelProtection(old_cancel_protect); +/// doSomeWork() catch |err| switch (err) { +/// error.Canceled => unreachable, +/// }; +/// ``` +/// +/// For a description of cancelation and cancelation points, see `Future.cancel`. +pub fn swapCancelProtection(io: Io, new: CancelProtection) CancelProtection { + return io.vtable.swapCancelProtection(io.userdata, new); +} + +/// This function acts as a pure cancelation point (subject to protection; see `CancelProtection`) +/// and does nothing else. In other words, it returns `error.Canceled` if there is an outstanding +/// non-blocked cancelation request, but otherwise is a no-op. +/// +/// It is rarely necessary to call this function. The primary use case is in long-running CPU-bound +/// tasks which may need to respond to cancelation before completing. Short tasks, or those which +/// perform other `Io` operations (and hence have other cancelation points), will typically already +/// respond quickly to cancelation requests. +/// +/// For a description of cancelation and cancelation points, see `Future.cancel`. +pub fn checkCancel(io: Io) Cancelable!void { + return io.vtable.checkCancel(io.userdata); +} + pub fn Select(comptime U: type) type { return struct { io: Io, @@ -1143,17 +1264,20 @@ pub fn Select(comptime U: type) type { function: anytype, args: std.meta.ArgsTuple(@TypeOf(function)), ) void { - const Args = @TypeOf(args); - const TypeErased = struct { - fn start(group: *Group, context: *const anyopaque) void { - const args_casted: *const Args = @ptrCast(@alignCast(context)); - const unerased_select: *S = @fieldParentPtr("group", group); - const elem = @unionInit(U, @tagName(field), @call(.auto, function, args_casted.*)); - unerased_select.queue.putOneUncancelable(unerased_select.io, elem); + const Context = struct { + select: *S, + args: @TypeOf(args), + fn start(type_erased_context: *const anyopaque) Cancelable!void { + const context: *const @This() = @ptrCast(@alignCast(type_erased_context)); + const elem = @unionInit(U, @tagName(field), @call(.auto, function, context.args)); + context.select.queue.putOneUncancelable(context.select.io, elem) catch |err| switch (err) { + error.Closed => unreachable, + }; } }; + const context: Context = .{ .select = s, .args = args }; _ = @atomicRmw(usize, &s.outstanding, .Add, 1, .monotonic); - s.io.vtable.groupAsync(s.io.userdata, &s.group, @ptrCast(&args), .of(Args), TypeErased.start); + s.io.vtable.groupAsync(s.io.userdata, &s.group, @ptrCast(&context), .of(Context), Context.start); } /// Blocks until another task of the select finishes. @@ -1161,14 +1285,19 @@ pub fn Select(comptime U: type) type { /// Asserts there is at least one more `outstanding` task. /// /// Not threadsafe. - pub fn wait(s: *S) Cancelable!U { + pub fn await(s: *S) Cancelable!U { s.outstanding -= 1; - return s.queue.getOne(s.io); + return s.queue.getOne(s.io) catch |err| switch (err) { + error.Canceled => |e| return e, + error.Closed => unreachable, + }; } - /// Equivalent to `wait` but requests cancellation on all remaining + /// Equivalent to `wait` but requests cancelation on all remaining /// tasks owned by the select. /// + /// For a description of cancelation and cancelation points, see `Future.cancel`. + /// /// It is illegal to call `wait` after this. /// /// Idempotent. Not threadsafe. @@ -1179,104 +1308,352 @@ pub fn Select(comptime U: type) type { }; } -pub const Mutex = struct { - state: State, - - pub const State = enum(usize) { - locked_once = 0b00, - unlocked = 0b01, - contended = 0b10, - /// contended - _, - - pub fn isUnlocked(state: State) bool { - return @intFromEnum(state) & @intFromEnum(State.unlocked) == @intFromEnum(State.unlocked); - } +/// Atomically checks if the value at `ptr` equals `expected`, and if so, blocks until either: +/// +/// * a matching (same `ptr` argument) `futexWake` call occurs, or +/// * a spurious ("random") wakeup occurs. +/// +/// Typically, `futexWake` should be called immediately after updating the value at `ptr.*`, to +/// unblock tasks using `futexWait` to wait for the value to change from what it previously was. +/// +/// The caller is responsible for identifying spurious wakeups if necessary, typically by checking +/// the value at `ptr.*`. +/// +/// Asserts that `T` is 4 bytes in length and has a well-defined layout with no padding bits. +pub fn futexWait(io: Io, comptime T: type, ptr: *align(@alignOf(u32)) const T, expected: T) Cancelable!void { + return futexWaitTimeout(io, T, ptr, expected, .none); +} +/// Same as `futexWait`, except also unblocks if `timeout` expires. As with `futexWait`, spurious +/// wakeups are possible. It remains the caller's responsibility to differentiate between these +/// three possible wake-up reasons if necessary. +pub fn futexWaitTimeout(io: Io, comptime T: type, ptr: *align(@alignOf(u32)) const T, expected: T, timeout: Timeout) Cancelable!void { + const expected_int: u32 = switch (@typeInfo(T)) { + .@"enum" => @bitCast(@intFromEnum(expected)), + else => @bitCast(expected), }; + return io.vtable.futexWait(io.userdata, @ptrCast(ptr), expected_int, timeout); +} +/// Same as `futexWait`, except does not introduce a cancelation point. +/// +/// For a description of cancelation and cancelation points, see `Future.cancel`. +pub fn futexWaitUncancelable(io: Io, comptime T: type, ptr: *align(@alignOf(u32)) const T, expected: T) void { + const expected_int: u32 = switch (@typeInfo(T)) { + .@"enum" => @bitCast(@intFromEnum(expected)), + else => @bitCast(expected), + }; + io.vtable.futexWaitUncancelable(io.userdata, @ptrCast(ptr), expected_int); +} +/// Unblocks pending futex waits on `ptr`, up to a limit of `max_waiters` calls. +pub fn futexWake(io: Io, comptime T: type, ptr: *align(@alignOf(u32)) const T, max_waiters: u32) void { + comptime assert(@sizeOf(T) == @sizeOf(u32)); + if (max_waiters == 0) return; + return io.vtable.futexWake(io.userdata, @ptrCast(ptr), max_waiters); +} - pub const init: Mutex = .{ .state = .unlocked }; +/// Mutex is a synchronization primitive which enforces atomic access to a +/// shared region of code known as the "critical section". +/// +/// Mutex is an extern struct so that it may be used as a field inside another +/// extern struct. Having a guaranteed memory layout including mutexes is +/// important for IPC over shared memory (mmap). +pub const Mutex = extern struct { + state: std.atomic.Value(State), + + pub const init: Mutex = .{ .state = .init(.unlocked) }; + + pub const State = enum(u32) { + unlocked, + locked_once, + contended, + }; - pub fn tryLock(mutex: *Mutex) bool { - const prev_state: State = @enumFromInt(@atomicRmw( - usize, - @as(*usize, @ptrCast(&mutex.state)), - .And, - ~@intFromEnum(State.unlocked), + pub fn tryLock(m: *Mutex) bool { + switch (m.state.cmpxchgWeak( + .unlocked, + .locked_once, .acquire, - )); - return prev_state.isUnlocked(); + .monotonic, + ) orelse return true) { + .unlocked => unreachable, + .locked_once, .contended => return false, + } } - pub fn lock(mutex: *Mutex, io: std.Io) Cancelable!void { - const prev_state: State = @enumFromInt(@atomicRmw( - usize, - @as(*usize, @ptrCast(&mutex.state)), - .And, - ~@intFromEnum(State.unlocked), + pub fn lock(m: *Mutex, io: Io) Cancelable!void { + const initial_state = m.state.cmpxchgWeak( + .unlocked, + .locked_once, .acquire, - )); - if (prev_state.isUnlocked()) { + .monotonic, + ) orelse { @branchHint(.likely); return; + }; + if (initial_state == .contended) { + try io.futexWait(State, &m.state.raw, .contended); + } + while (m.state.swap(.contended, .acquire) != .unlocked) { + try io.futexWait(State, &m.state.raw, .contended); } - return io.vtable.mutexLock(io.userdata, prev_state, mutex); } - /// Same as `lock` but cannot be canceled. - pub fn lockUncancelable(mutex: *Mutex, io: std.Io) void { - const prev_state: State = @enumFromInt(@atomicRmw( - usize, - @as(*usize, @ptrCast(&mutex.state)), - .And, - ~@intFromEnum(State.unlocked), + /// Same as `lock`, except does not introduce a cancelation point. + /// + /// For a description of cancelation and cancelation points, see `Future.cancel`. + pub fn lockUncancelable(m: *Mutex, io: Io) void { + const initial_state = m.state.cmpxchgWeak( + .unlocked, + .locked_once, .acquire, - )); - if (prev_state.isUnlocked()) { + .monotonic, + ) orelse { @branchHint(.likely); return; + }; + if (initial_state == .contended) { + io.futexWaitUncancelable(State, &m.state.raw, .contended); + } + while (m.state.swap(.contended, .acquire) != .unlocked) { + io.futexWaitUncancelable(State, &m.state.raw, .contended); } - return io.vtable.mutexLockUncancelable(io.userdata, prev_state, mutex); } - pub fn unlock(mutex: *Mutex, io: std.Io) void { - const prev_state = @cmpxchgWeak(State, &mutex.state, .locked_once, .unlocked, .release, .acquire) orelse { - @branchHint(.likely); - return; - }; - assert(prev_state != .unlocked); // mutex not locked - return io.vtable.mutexUnlock(io.userdata, prev_state, mutex); + pub fn unlock(m: *Mutex, io: Io) void { + switch (m.state.swap(.unlocked, .release)) { + .unlocked => unreachable, + .locked_once => {}, + .contended => { + @branchHint(.unlikely); + io.futexWake(State, &m.state.raw, 1); + }, + } } }; pub const Condition = struct { - state: u64 = 0, + state: std.atomic.Value(State), + /// Incremented whenever the condition is signaled + epoch: std.atomic.Value(u32), + + const State = packed struct(u32) { + waiters: u16, + signals: u16, + }; + + pub const init: Condition = .{ + .state = .init(.{ .waiters = 0, .signals = 0 }), + .epoch = .init(0), + }; pub fn wait(cond: *Condition, io: Io, mutex: *Mutex) Cancelable!void { - return io.vtable.conditionWait(io.userdata, cond, mutex); + try waitInner(cond, io, mutex, false); } + /// Same as `wait`, except does not introduce a cancelation point. + /// + /// For a description of cancelation and cancelation points, see `Future.cancel`. pub fn waitUncancelable(cond: *Condition, io: Io, mutex: *Mutex) void { - return io.vtable.conditionWaitUncancelable(io.userdata, cond, mutex); + waitInner(cond, io, mutex, true) catch |err| switch (err) { + error.Canceled => unreachable, + }; + } + + fn waitInner(cond: *Condition, io: Io, mutex: *Mutex, uncancelable: bool) Cancelable!void { + var epoch = cond.epoch.load(.acquire); // `.acquire` to ensure ordered before state load + + { + const prev_state = cond.state.fetchAdd(.{ .waiters = 1, .signals = 0 }, .monotonic); + assert(prev_state.waiters < math.maxInt(u16)); // overflow caused by too many waiters + } + + mutex.unlock(io); + defer mutex.lockUncancelable(io); + + while (true) { + const result = if (uncancelable) + io.futexWaitUncancelable(u32, &cond.epoch.raw, epoch) + else + io.futexWait(u32, &cond.epoch.raw, epoch); + + epoch = cond.epoch.load(.acquire); // `.acquire` to ensure ordered before `state` laod + + // Even on error, try to consume a pending signal first. Otherwise a race might + // cause a signal to get stuck in the state with no corresponding waiter. + { + var prev_state = cond.state.load(.monotonic); + while (prev_state.signals > 0) { + prev_state = cond.state.cmpxchgWeak(prev_state, .{ + .waiters = prev_state.waiters - 1, + .signals = prev_state.signals - 1, + }, .acquire, .monotonic) orelse { + // We successfully consumed a signal. + return; + }; + } + } + + // There are no more signals available; this was a spurious wakeup or an error. If it + // was an error, we will remove ourselves as a waiter and return that error. Otherwise, + // we'll loop back to the futex wait. + result catch |err| { + const prev_state = cond.state.fetchSub(.{ .waiters = 1, .signals = 0 }, .monotonic); + assert(prev_state.waiters > 0); // underflow caused by illegal state + return err; + }; + } } pub fn signal(cond: *Condition, io: Io) void { - io.vtable.conditionWake(io.userdata, cond, .one); + var prev_state = cond.state.load(.monotonic); + while (prev_state.waiters > prev_state.signals) { + @branchHint(.unlikely); + prev_state = cond.state.cmpxchgWeak(prev_state, .{ + .waiters = prev_state.waiters, + .signals = prev_state.signals + 1, + }, .release, .monotonic) orelse { + // Update the epoch to tell the waiting threads that there are new signals for them. + // Note that a waiting thread could miss a take if *exactly* (1<<32)-1 wakes happen + // between it observing the epoch and sleeping on it, but this is extraordinarily + // unlikely due to the precise number of calls required. + _ = cond.epoch.fetchAdd(1, .release); // `.release` to ensure ordered after `state` update + io.futexWake(u32, &cond.epoch.raw, 1); + return; + }; + } } pub fn broadcast(cond: *Condition, io: Io) void { - io.vtable.conditionWake(io.userdata, cond, .all); + var prev_state = cond.state.load(.monotonic); + while (prev_state.waiters > prev_state.signals) { + @branchHint(.unlikely); + prev_state = cond.state.cmpxchgWeak(prev_state, .{ + .waiters = prev_state.waiters, + .signals = prev_state.waiters, + }, .release, .monotonic) orelse { + // Update the epoch to tell the waiting threads that there are new signals for them. + // Note that a waiting thread could miss a take if *exactly* (1<<32)-1 wakes happen + // between it observing the epoch and sleeping on it, but this is extraordinarily + // unlikely due to the precise number of calls required. + _ = cond.epoch.fetchAdd(1, .release); // `.release` to ensure ordered after `state` update + io.futexWake(u32, &cond.epoch.raw, prev_state.waiters - prev_state.signals); + return; + }; + } } +}; - pub const Wake = enum { - /// Wake up only one thread. - one, - /// Wake up all threads. - all, - }; +/// Logical boolean flag which can be set and unset and supports a "wait until set" operation. +pub const Event = enum(u32) { + unset, + waiting, + is_set, + + /// Returns whether the logical boolean is `true`. + pub fn isSet(event: *const Event) bool { + return switch (@atomicLoad(Event, event, .acquire)) { + .unset, .waiting => false, + .is_set => true, + }; + } + + /// Blocks until the logical boolean is `true`. + pub fn wait(event: *Event, io: Io) Io.Cancelable!void { + if (@cmpxchgStrong(Event, event, .unset, .waiting, .acquire, .acquire)) |prev| switch (prev) { + .unset => unreachable, + .waiting => {}, + .is_set => return, + }; + errdefer { + // Ideally we would restore the event back to `.unset` instead of `.waiting`, but there + // might be other threads waiting on the event. In theory we could track the *number* of + // waiting threads in the unused bits of the `Event`, but that has its own problem: the + // waiters would wake up when a *new waiter* was added. So it's easiest to just leave + // the state at `.waiting`---at worst it causes one redundant call to `futexWake`. + } + while (true) { + try io.futexWait(Event, event, .waiting); + switch (@atomicLoad(Event, event, .acquire)) { + .unset => unreachable, // `reset` called before pending `wait` returned + .waiting => continue, + .is_set => return, + } + } + } + + /// Same as `wait`, except does not introduce a cancelation point. + /// + /// For a description of cancelation and cancelation points, see `Future.cancel`. + pub fn waitUncancelable(event: *Event, io: Io) void { + if (@cmpxchgStrong(Event, event, .unset, .waiting, .acquire, .acquire)) |prev| switch (prev) { + .unset => unreachable, + .waiting => {}, + .is_set => return, + }; + while (true) { + io.futexWaitUncancelable(Event, event, .waiting); + switch (@atomicLoad(Event, event, .acquire)) { + .unset => unreachable, // `reset` called before pending `wait` returned + .waiting => continue, + .is_set => return, + } + } + } + + pub const WaitTimeoutError = error{Timeout} || Cancelable; + + /// Blocks the calling thread until either the logical boolean is set, the timeout expires, or a + /// spurious wakeup occurs. If the timeout expires or a spurious wakeup occurs, `error.Timeout` + /// is returned. + pub fn waitTimeout(event: *Event, io: Io, timeout: Timeout) WaitTimeoutError!void { + if (@cmpxchgStrong(Event, event, .unset, .waiting, .acquire, .acquire)) |prev| switch (prev) { + .unset => unreachable, + .waiting => assert(!builtin.single_threaded), // invalid state + .is_set => return, + }; + errdefer { + // Ideally we would restore the event back to `.unset` instead of `.waiting`, but there + // might be other threads waiting on the event. In theory we could track the *number* of + // waiting threads in the unused bits of the `Event`, but that has its own problem: the + // waiters would wake up when a *new waiter* was added. So it's easiest to just leave + // the state at `.waiting`---at worst it causes one redundant call to `futexWake`. + } + try io.futexWaitTimeout(Event, event, .waiting, timeout); + switch (@atomicLoad(Event, event, .acquire)) { + .unset => unreachable, // `reset` called before pending `wait` returned + .waiting => return error.Timeout, + .is_set => return, + } + } + + /// Sets the logical boolean to true, and hence unblocks any pending calls to `wait`. The + /// logical boolean remains true until `reset` is called, so future calls to `set` have no + /// semantic effect. + /// + /// Any memory accesses prior to a `set` call are "released", so that if this `set` call causes + /// `isSet` to return `true` or a wait to finish, those tasks will be able to observe those + /// memory accesses. + pub fn set(e: *Event, io: Io) void { + switch (@atomicRmw(Event, e, .Xchg, .is_set, .release)) { + .unset, .is_set => {}, + .waiting => io.futexWake(Event, e, std.math.maxInt(u32)), + } + } + + /// Sets the logical boolean to false. + /// + /// Assumes that there is no pending call to `wait` or `waitUncancelable`. + /// + /// However, concurrent calls to `isSet`, `set`, and `reset` are allowed. + pub fn reset(e: *Event) void { + @atomicStore(Event, e, .unset, .monotonic); + } }; +pub const QueueClosedError = error{Closed}; + pub const TypeErasedQueue = struct { mutex: Mutex, + closed: bool, /// Ring buffer. This data is logically *after* queued getters. buffer: []u8, @@ -1288,12 +1665,14 @@ pub const TypeErasedQueue = struct { const Put = struct { remaining: []const u8, + needed: usize, condition: Condition, node: std.DoublyLinkedList.Node, }; const Get = struct { remaining: []u8, + needed: usize, condition: Condition, node: std.DoublyLinkedList.Node, }; @@ -1301,6 +1680,7 @@ pub const TypeErasedQueue = struct { pub fn init(buffer: []u8) TypeErasedQueue { return .{ .mutex = .init, + .closed = false, .buffer = buffer, .start = 0, .len = 0, @@ -1309,7 +1689,27 @@ pub const TypeErasedQueue = struct { }; } - pub fn put(q: *TypeErasedQueue, io: Io, elements: []const u8, min: usize) Cancelable!usize { + pub fn close(q: *TypeErasedQueue, io: Io) void { + q.mutex.lockUncancelable(io); + defer q.mutex.unlock(io); + q.closed = true; + { + var it = q.getters.first; + while (it) |node| : (it = node.next) { + const getter: *Get = @alignCast(@fieldParentPtr("node", node)); + getter.condition.signal(io); + } + } + { + var it = q.putters.first; + while (it) |node| : (it = node.next) { + const putter: *Put = @alignCast(@fieldParentPtr("node", node)); + putter.condition.signal(io); + } + } + } + + pub fn put(q: *TypeErasedQueue, io: Io, elements: []const u8, min: usize) (QueueClosedError || Cancelable)!usize { assert(elements.len >= min); if (elements.len == 0) return 0; try q.mutex.lock(io); @@ -1317,14 +1717,17 @@ pub const TypeErasedQueue = struct { return q.putLocked(io, elements, min, false); } - /// Same as `put` but cannot be canceled. - pub fn putUncancelable(q: *TypeErasedQueue, io: Io, elements: []const u8, min: usize) usize { + /// Same as `put`, except does not introduce a cancelation point. + /// + /// For a description of cancelation and cancelation points, see `Future.cancel`. + pub fn putUncancelable(q: *TypeErasedQueue, io: Io, elements: []const u8, min: usize) QueueClosedError!usize { assert(elements.len >= min); if (elements.len == 0) return 0; q.mutex.lockUncancelable(io); defer q.mutex.unlock(io); return q.putLocked(io, elements, min, true) catch |err| switch (err) { error.Canceled => unreachable, + error.Closed => |e| return e, }; } @@ -1338,49 +1741,79 @@ pub const TypeErasedQueue = struct { return if (slice.len > 0) slice else null; } - fn putLocked(q: *TypeErasedQueue, io: Io, elements: []const u8, min: usize, uncancelable: bool) Cancelable!usize { + fn putLocked(q: *TypeErasedQueue, io: Io, elements: []const u8, target: usize, uncancelable: bool) (QueueClosedError || Cancelable)!usize { + // A closed queue cannot be added to, even if there is space in the buffer. + if (q.closed) return error.Closed; + // Getters have first priority on the data, and only when the getters // queue is empty do we start populating the buffer. - var remaining = elements; + // The number of elements we add immediately, before possibly blocking. + var n: usize = 0; + while (q.getters.popFirst()) |getter_node| { const getter: *Get = @alignCast(@fieldParentPtr("node", getter_node)); - const copy_len = @min(getter.remaining.len, remaining.len); + const copy_len = @min(getter.remaining.len, elements.len - n); assert(copy_len > 0); - @memcpy(getter.remaining[0..copy_len], remaining[0..copy_len]); - remaining = remaining[copy_len..]; + @memcpy(getter.remaining[0..copy_len], elements[n..][0..copy_len]); getter.remaining = getter.remaining[copy_len..]; - if (getter.remaining.len == 0) { + getter.needed -|= copy_len; + n += copy_len; + if (getter.needed == 0) { getter.condition.signal(io); - if (remaining.len > 0) continue; - } else q.getters.prepend(getter_node); - assert(remaining.len == 0); - return elements.len; + } else { + assert(n == elements.len); // we didn't have enough elements for the getter + q.getters.prepend(getter_node); + } + if (n == elements.len) return elements.len; } while (q.puttableSlice()) |slice| { - const copy_len = @min(slice.len, remaining.len); + const copy_len = @min(slice.len, elements.len - n); assert(copy_len > 0); - @memcpy(slice[0..copy_len], remaining[0..copy_len]); + @memcpy(slice[0..copy_len], elements[n..][0..copy_len]); q.len += copy_len; - remaining = remaining[copy_len..]; - if (remaining.len == 0) return elements.len; + n += copy_len; + if (n == elements.len) return elements.len; } - const total_filled = elements.len - remaining.len; - if (total_filled >= min) return total_filled; + // Don't block if we hit the target. + if (n >= target) return n; - var pending: Put = .{ .remaining = remaining, .condition = .{}, .node = .{} }; + var pending: Put = .{ + .remaining = elements[n..], + .needed = target - n, + .condition = .init, + .node = .{}, + }; q.putters.append(&pending.node); - defer if (pending.remaining.len > 0) q.putters.remove(&pending.node); - while (pending.remaining.len > 0) if (uncancelable) - pending.condition.waitUncancelable(io, &q.mutex) - else - try pending.condition.wait(io, &q.mutex); - return elements.len; + defer if (pending.needed > 0) q.putters.remove(&pending.node); + + while (pending.needed > 0 and !q.closed) { + if (uncancelable) { + pending.condition.waitUncancelable(io, &q.mutex); + continue; + } + pending.condition.wait(io, &q.mutex) catch |err| switch (err) { + error.Canceled => if (pending.remaining.len == elements.len) { + // Canceled while waiting, and appended no elements. + return error.Canceled; + } else { + // Canceled while waiting, but appended some elements, so report those first. + io.recancel(); + return elements.len - pending.remaining.len; + }, + }; + } + if (pending.remaining.len == elements.len) { + // The queue was closed while we were waiting. We appended no elements. + assert(q.closed); + return error.Closed; + } + return elements.len - pending.remaining.len; } - pub fn get(q: *@This(), io: Io, buffer: []u8, min: usize) Cancelable!usize { + pub fn get(q: *TypeErasedQueue, io: Io, buffer: []u8, min: usize) (QueueClosedError || Cancelable)!usize { assert(buffer.len >= min); if (buffer.len == 0) return 0; try q.mutex.lock(io); @@ -1388,13 +1821,17 @@ pub const TypeErasedQueue = struct { return q.getLocked(io, buffer, min, false); } - pub fn getUncancelable(q: *@This(), io: Io, buffer: []u8, min: usize) usize { + /// Same as `get`, except does not introduce a cancelation point. + /// + /// For a description of cancelation and cancelation points, see `Future.cancel`. + pub fn getUncancelable(q: *TypeErasedQueue, io: Io, buffer: []u8, min: usize) QueueClosedError!usize { assert(buffer.len >= min); if (buffer.len == 0) return 0; q.mutex.lockUncancelable(io); defer q.mutex.unlock(io); return q.getLocked(io, buffer, min, true) catch |err| switch (err) { error.Canceled => unreachable, + error.Closed => |e| return e, }; } @@ -1404,21 +1841,23 @@ pub const TypeErasedQueue = struct { return if (slice.len > 0) slice else null; } - fn getLocked(q: *@This(), io: Io, buffer: []u8, min: usize, uncancelable: bool) Cancelable!usize { + fn getLocked(q: *TypeErasedQueue, io: Io, buffer: []u8, target: usize, uncancelable: bool) (QueueClosedError || Cancelable)!usize { // The ring buffer gets first priority, then data should come from any // queued putters, then finally the ring buffer should be filled with // data from putters so they can be resumed. - var remaining = buffer; + // The number of elements we received immediately, before possibly blocking. + var n: usize = 0; + while (q.gettableSlice()) |slice| { - const copy_len = @min(slice.len, remaining.len); + const copy_len = @min(slice.len, buffer.len - n); assert(copy_len > 0); - @memcpy(remaining[0..copy_len], slice[0..copy_len]); + @memcpy(buffer[n..][0..copy_len], slice[0..copy_len]); q.start += copy_len; if (q.buffer.len - q.start == 0) q.start = 0; q.len -= copy_len; - remaining = remaining[copy_len..]; - if (remaining.len == 0) { + n += copy_len; + if (n == buffer.len) { q.fillRingBufferFromPutters(io); return buffer.len; } @@ -1427,33 +1866,64 @@ pub const TypeErasedQueue = struct { // Copy directly from putters into buffer. while (q.putters.popFirst()) |putter_node| { const putter: *Put = @alignCast(@fieldParentPtr("node", putter_node)); - const copy_len = @min(putter.remaining.len, remaining.len); + const copy_len = @min(putter.remaining.len, buffer.len - n); assert(copy_len > 0); - @memcpy(remaining[0..copy_len], putter.remaining[0..copy_len]); + @memcpy(buffer[n..][0..copy_len], putter.remaining[0..copy_len]); putter.remaining = putter.remaining[copy_len..]; - remaining = remaining[copy_len..]; - if (putter.remaining.len == 0) { + putter.needed -|= copy_len; + n += copy_len; + if (putter.needed == 0) { putter.condition.signal(io); - if (remaining.len > 0) continue; - } else q.putters.prepend(putter_node); - assert(remaining.len == 0); - q.fillRingBufferFromPutters(io); - return buffer.len; + } else { + assert(n == buffer.len); // we didn't have enough space for the putter + q.putters.prepend(putter_node); + } + if (n == buffer.len) { + q.fillRingBufferFromPutters(io); + return buffer.len; + } } - // Both ring buffer and putters queue is empty. - const total_filled = buffer.len - remaining.len; - if (total_filled >= min) return total_filled; + // No need to call `fillRingBufferFromPutters` from this point onwards, + // because we emptied the ring buffer *and* the putter queue! + + // Don't block if we hit the target or if the queue is closed. Return how + // many elements we could get immediately, unless the queue was closed and + // empty, in which case report `error.Closed`. + if (n == 0 and q.closed) return error.Closed; + if (n >= target or q.closed) return n; - var pending: Get = .{ .remaining = remaining, .condition = .{}, .node = .{} }; + var pending: Get = .{ + .remaining = buffer[n..], + .needed = target - n, + .condition = .init, + .node = .{}, + }; q.getters.append(&pending.node); - defer if (pending.remaining.len > 0) q.getters.remove(&pending.node); - while (pending.remaining.len > 0) if (uncancelable) - pending.condition.waitUncancelable(io, &q.mutex) - else - try pending.condition.wait(io, &q.mutex); - q.fillRingBufferFromPutters(io); - return buffer.len; + defer if (pending.needed > 0) q.getters.remove(&pending.node); + + while (pending.needed > 0 and !q.closed) { + if (uncancelable) { + pending.condition.waitUncancelable(io, &q.mutex); + continue; + } + pending.condition.wait(io, &q.mutex) catch |err| switch (err) { + error.Canceled => if (pending.remaining.len == buffer.len) { + // Canceled while waiting, and received no elements. + return error.Canceled; + } else { + // Canceled while waiting, but received some elements, so report those first. + io.recancel(); + return buffer.len - pending.remaining.len; + }, + }; + } + if (pending.remaining.len == buffer.len) { + // The queue was closed while we were waiting. We received no elements. + assert(q.closed); + return error.Closed; + } + return buffer.len - pending.remaining.len; } /// Called when there is nonzero space available in the ring buffer and @@ -1469,7 +1939,8 @@ pub const TypeErasedQueue = struct { @memcpy(slice[0..copy_len], putter.remaining[0..copy_len]); q.len += copy_len; putter.remaining = putter.remaining[copy_len..]; - if (putter.remaining.len == 0) { + putter.needed -|= copy_len; + if (putter.needed == 0) { putter.condition.signal(io); break; } @@ -1492,59 +1963,112 @@ pub fn Queue(Elem: type) type { return .{ .type_erased = .init(@ptrCast(buffer)) }; } - /// Appends elements to the end of the queue. The function returns when - /// at least `min` elements have been added to the buffer or sent - /// directly to a consumer. + pub fn close(q: *@This(), io: Io) void { + q.type_erased.close(io); + } + + /// Appends elements to the end of the queue, potentially blocking if + /// there is insufficient capacity. Returns when any one of the + /// following conditions is satisfied: + /// + /// * At least `target` elements have been added to the queue + /// * The queue is closed + /// * The current task is canceled + /// + /// Returns how many of `elements` have been added to the queue, if any. + /// If an error is returned, no elements have been added. /// - /// Returns how many elements have been added to the queue. + /// If the queue is closed or the task is canceled, but some items were + /// already added before the closure or cancelation, then `put` may + /// return a number lower than `target`, in which case future calls are + /// guaranteed to return `error.Canceled` or `error.Closed`. /// - /// Asserts that `elements.len >= min`. - pub fn put(q: *@This(), io: Io, elements: []const Elem, min: usize) Cancelable!usize { - return @divExact(try q.type_erased.put(io, @ptrCast(elements), min * @sizeOf(Elem)), @sizeOf(Elem)); + /// A return value of 0 is only possible if `target` is 0, in which case + /// the call is guaranteed to queue as many of `elements` as is possible + /// *without* blocking. + /// + /// Asserts that `elements.len >= target`. + pub fn put(q: *@This(), io: Io, elements: []const Elem, target: usize) (QueueClosedError || Cancelable)!usize { + return @divExact(try q.type_erased.put(io, @ptrCast(elements), target * @sizeOf(Elem)), @sizeOf(Elem)); } /// Same as `put` but blocks until all elements have been added to the queue. - pub fn putAll(q: *@This(), io: Io, elements: []const Elem) Cancelable!void { - assert(try q.put(io, elements, elements.len) == elements.len); + /// + /// If the queue is closed or canceled, `error.Closed` or `error.Canceled` + /// is returned, and it is unspecified how many, if any, of `elements` were + /// added to the queue prior to cancelation or closure. + pub fn putAll(q: *@This(), io: Io, elements: []const Elem) (QueueClosedError || Cancelable)!void { + const n = try q.put(io, elements, elements.len); + if (n != elements.len) { + _ = try q.put(io, elements[n..], elements.len - n); + unreachable; // partial `put` implies queue was closed or we were canceled + } } - /// Same as `put` but cannot be interrupted. - pub fn putUncancelable(q: *@This(), io: Io, elements: []const Elem, min: usize) usize { - return @divExact(q.type_erased.putUncancelable(io, @ptrCast(elements), min * @sizeOf(Elem)), @sizeOf(Elem)); + /// Same as `put`, except does not introduce a cancelation point. + /// + /// For a description of cancelation and cancelation points, see `Future.cancel`. + pub fn putUncancelable(q: *@This(), io: Io, elements: []const Elem, min: usize) QueueClosedError!usize { + return @divExact(try q.type_erased.putUncancelable(io, @ptrCast(elements), min * @sizeOf(Elem)), @sizeOf(Elem)); } - pub fn putOne(q: *@This(), io: Io, item: Elem) Cancelable!void { + /// Appends `item` to the end of the queue, blocking if the queue is full. + pub fn putOne(q: *@This(), io: Io, item: Elem) (QueueClosedError || Cancelable)!void { assert(try q.put(io, &.{item}, 1) == 1); } - pub fn putOneUncancelable(q: *@This(), io: Io, item: Elem) void { - assert(q.putUncancelable(io, &.{item}, 1) == 1); + /// Same as `putOne`, except does not introduce a cancelation point. + /// + /// For a description of cancelation and cancelation points, see `Future.cancel`. + pub fn putOneUncancelable(q: *@This(), io: Io, item: Elem) QueueClosedError!void { + assert(try q.putUncancelable(io, &.{item}, 1) == 1); } - /// Receives elements from the beginning of the queue. The function - /// returns when at least `min` elements have been populated inside - /// `buffer`. + /// Receives elements from the beginning of the queue, potentially blocking + /// if there are insufficient elements currently in the queue. Returns when + /// any one of the following conditions is satisfied: + /// + /// * At least `target` elements have been received from the queue + /// * The queue is closed and contains no buffered elements + /// * The current task is canceled /// - /// Returns how many elements of `buffer` have been populated. + /// Returns how many elements of `buffer` have been populated, if any. + /// If an error is returned, no elements have been populated. /// - /// Asserts that `buffer.len >= min`. - pub fn get(q: *@This(), io: Io, buffer: []Elem, min: usize) Cancelable!usize { - return @divExact(try q.type_erased.get(io, @ptrCast(buffer), min * @sizeOf(Elem)), @sizeOf(Elem)); + /// If the queue is closed or the task is canceled, but some items were + /// already received before the closure or cancelation, then `get` may + /// return a number lower than `target`, in which case future calls are + /// guaranteed to return `error.Canceled` or `error.Closed`. + /// + /// A return value of 0 is only possible if `target` is 0, in which case + /// the call is guaranteed to fill as much of `buffer` as is possible + /// *without* blocking. + /// + /// Asserts that `buffer.len >= target`. + pub fn get(q: *@This(), io: Io, buffer: []Elem, target: usize) (QueueClosedError || Cancelable)!usize { + return @divExact(try q.type_erased.get(io, @ptrCast(buffer), target * @sizeOf(Elem)), @sizeOf(Elem)); } - pub fn getUncancelable(q: *@This(), io: Io, buffer: []Elem, min: usize) usize { - return @divExact(q.type_erased.getUncancelable(io, @ptrCast(buffer), min * @sizeOf(Elem)), @sizeOf(Elem)); + /// Same as `get`, except does not introduce a cancelation point. + /// + /// For a description of cancelation and cancelation points, see `Future.cancel`. + pub fn getUncancelable(q: *@This(), io: Io, buffer: []Elem, min: usize) QueueClosedError!usize { + return @divExact(try q.type_erased.getUncancelable(io, @ptrCast(buffer), min * @sizeOf(Elem)), @sizeOf(Elem)); } - pub fn getOne(q: *@This(), io: Io) Cancelable!Elem { + /// Receives one element from the beginning of the queue, blocking if the queue is empty. + pub fn getOne(q: *@This(), io: Io) (QueueClosedError || Cancelable)!Elem { var buf: [1]Elem = undefined; assert(try q.get(io, &buf, 1) == 1); return buf[0]; } - pub fn getOneUncancelable(q: *@This(), io: Io) Elem { + /// Same as `getOne`, except does not introduce a cancelation point. + /// + /// For a description of cancelation and cancelation points, see `Future.cancel`. + pub fn getOneUncancelable(q: *@This(), io: Io) QueueClosedError!Elem { var buf: [1]Elem = undefined; - assert(q.getUncancelable(io, &buf, 1) == 1); + assert(try q.getUncancelable(io, &buf, 1) == 1); return buf[0]; } @@ -1632,10 +2156,6 @@ pub fn concurrent( return future; } -pub fn cancelRequested(io: Io) bool { - return io.vtable.cancelRequested(io.userdata); -} - pub const SleepError = error{UnsupportedClock} || UnexpectedError || Cancelable; pub fn sleep(io: Io, duration: Duration, clock: Clock) SleepError!void { @@ -1678,3 +2198,100 @@ pub fn select(io: Io, s: anytype) Cancelable!SelectUnion(@TypeOf(s)) { else => unreachable, } } + +pub const LockedStderr = struct { + file_writer: *File.Writer, + terminal_mode: Terminal.Mode, + + pub fn terminal(ls: LockedStderr) Terminal { + return .{ + .writer = &ls.file_writer.interface, + .mode = ls.terminal_mode, + }; + } + + pub fn clear(ls: LockedStderr, buffer: []u8) Cancelable!void { + const fw = ls.file_writer; + std.Progress.clearWrittenWithEscapeCodes(fw) catch |err| switch (err) { + error.WriteFailed => switch (fw.err.?) { + error.Canceled => |e| return e, + else => {}, + }, + }; + fw.interface.flush() catch |err| switch (err) { + error.WriteFailed => switch (fw.err.?) { + error.Canceled => |e| return e, + else => {}, + }, + }; + fw.interface.buffer = buffer; + } +}; + +/// For doing application-level writes to the standard error stream. +/// Coordinates also with debug-level writes that are ignorant of Io interface +/// and implementations. When this returns, `std.process.stderr_thread_mutex` +/// will be locked. +/// +/// See also: +/// * `tryLockStderr` +pub fn lockStderr(io: Io, buffer: []u8, terminal_mode: ?Terminal.Mode) Cancelable!LockedStderr { + const ls = try io.vtable.lockStderr(io.userdata, terminal_mode); + try ls.clear(buffer); + return ls; +} + +/// Same as `lockStderr` but non-blocking. +pub fn tryLockStderr(io: Io, buffer: []u8, terminal_mode: ?Terminal.Mode) Cancelable!?LockedStderr { + const ls = (try io.vtable.tryLockStderr(io.userdata, buffer, terminal_mode)) orelse return null; + try ls.clear(buffer); + return ls; +} + +pub fn unlockStderr(io: Io) void { + return io.vtable.unlockStderr(io.userdata); +} + +/// Obtains entropy from a cryptographically secure pseudo-random number +/// generator. +/// +/// The implementation *may* store RNG state in process memory and use it to +/// fill `buffer`. +/// +/// The randomness is seeded by `randomSecure`, or a less secure mechanism upon +/// failure. +/// +/// Threadsafe. +/// +/// See also `randomSecure`. +pub fn random(io: Io, buffer: []u8) void { + return io.vtable.random(io.userdata, buffer); +} + +pub const RandomSecureError = error{EntropyUnavailable} || Cancelable; + +/// Obtains cryptographically secure entropy from outside the process. +/// +/// Always makes a syscall, or otherwise avoids dependency on process memory, +/// in order to obtain fresh randomness. Does not rely on stored RNG state. +/// +/// Does not have any fallback mechanisms; returns `error.EntropyUnavailable` +/// if any problems occur. +/// +/// Threadsafe. +/// +/// See also `random`. +pub fn randomSecure(io: Io, buffer: []u8) RandomSecureError!void { + return io.vtable.randomSecure(io.userdata, buffer); +} + +test { + _ = net; + _ = File; + _ = Dir; + _ = Reader; + _ = Writer; + _ = Evented; + _ = Threaded; + _ = @import("Io/test.zig"); +} diff --git a/lib/std/Io/Dir.zig b/lib/std/Io/Dir.zig index 5f66ec70947c..67d1ec849c6c 100644 --- a/lib/std/Io/Dir.zig +++ b/lib/std/Io/Dir.zig @@ -1,4 +1,5 @@ const Dir = @This(); +const root = @import("root"); const builtin = @import("builtin"); const native_os = builtin.os.tag; @@ -6,11 +7,71 @@ const native_os = builtin.os.tag; const std = @import("../std.zig"); const Io = std.Io; const File = Io.File; +const assert = std.debug.assert; +const Allocator = std.mem.Allocator; handle: Handle, -pub const Mode = Io.File.Mode; -pub const default_mode: Mode = 0o755; +pub const path = std.fs.path; + +/// The maximum length of a file path that the operating system will accept. +/// +/// Paths, including those returned from file system operations, may be longer +/// than this length, but such paths cannot be successfully passed back in +/// other file system operations. However, all path components returned by file +/// system operations are assumed to fit into a `u8` array of this length. +/// +/// The byte count includes room for a null sentinel byte. +/// +/// * On Windows, `[]u8` file paths are encoded as +/// [WTF-8](https://wtf-8.codeberg.page/). +/// * On WASI, `[]u8` file paths are encoded as valid UTF-8. +/// * On other platforms, `[]u8` file paths are opaque sequences of bytes with +/// no particular encoding. +pub const max_path_bytes = switch (native_os) { + .linux, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos, .freebsd, .openbsd, .netbsd, .dragonfly, .haiku, .illumos, .plan9, .emscripten, .wasi, .serenity => std.posix.PATH_MAX, + // Each WTF-16LE code unit may be expanded to 3 WTF-8 bytes. + // If it would require 4 WTF-8 bytes, then there would be a surrogate + // pair in the WTF-16LE, and we (over)account 3 bytes for it that way. + // +1 for the null byte at the end, which can be encoded in 1 byte. + .windows => std.os.windows.PATH_MAX_WIDE * 3 + 1, + else => if (@hasDecl(root, "os") and @hasDecl(root.os, "PATH_MAX")) + root.os.PATH_MAX + else + @compileError("PATH_MAX not implemented for " ++ @tagName(native_os)), +}; + +/// This represents the maximum size of a `[]u8` file name component that +/// the platform's common file systems support. File name components returned by file system +/// operations are likely to fit into a `u8` array of this length, but +/// (depending on the platform) this assumption may not hold for every configuration. +/// The byte count does not include a null sentinel byte. +/// On Windows, `[]u8` file name components are encoded as [WTF-8](https://wtf-8.codeberg.page/). +/// On WASI, file name components are encoded as valid UTF-8. +/// On other platforms, `[]u8` components are an opaque sequence of bytes with no particular encoding. +pub const max_name_bytes = switch (native_os) { + .linux, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos, .freebsd, .openbsd, .netbsd, .dragonfly, .illumos, .serenity => std.posix.NAME_MAX, + // Haiku's NAME_MAX includes the null terminator, so subtract one. + .haiku => std.posix.NAME_MAX - 1, + // Each WTF-16LE character may be expanded to 3 WTF-8 bytes. + // If it would require 4 WTF-8 bytes, then there would be a surrogate + // pair in the WTF-16LE, and we (over)account 3 bytes for it that way. + .windows => std.os.windows.NAME_MAX * 3, + // For WASI, the MAX_NAME will depend on the host OS, so it needs to be + // as large as the largest max_name_bytes (Windows) in order to work on any host OS. + // TODO determine if this is a reasonable approach + .wasi => std.os.windows.NAME_MAX * 3, + else => if (@hasDecl(root, "os") and @hasDecl(root.os, "NAME_MAX")) + root.os.NAME_MAX + else + @compileError("NAME_MAX not implemented for " ++ @tagName(native_os)), +}; + +pub const Entry = struct { + name: []const u8, + kind: File.Kind, + inode: File.INode, +}; /// Returns a handle to the current working directory. /// @@ -20,17 +81,326 @@ pub const default_mode: Mode = 0o755; /// Closing the returned `Dir` is checked illegal behavior. /// /// On POSIX targets, this function is comptime-callable. +/// +/// This function is overridable via `std.Options.cwd`. pub fn cwd() Dir { - return switch (native_os) { + const cwdFn = std.Options.cwd orelse return switch (native_os) { .windows => .{ .handle = std.os.windows.peb().ProcessParameters.CurrentDirectory.Handle }, - .wasi => .{ .handle = std.options.wasiCwd() }, + .wasi => .{ .handle = 3 }, // Expect the first preopen to be current working directory. else => .{ .handle = std.posix.AT.FDCWD }, }; + return cwdFn(); +} + +pub const Reader = struct { + dir: Dir, + state: State, + /// Stores I/O implementation specific data. + buffer: []align(@alignOf(usize)) u8, + /// Index of next entry in `buffer`. + index: usize, + /// Fill position of `buffer`. + end: usize, + + /// A length for `buffer` that allows all implementations to function. + pub const min_buffer_len = switch (native_os) { + .linux => std.mem.alignForward(usize, @sizeOf(std.os.linux.dirent64), 8) + + std.mem.alignForward(usize, max_name_bytes, 8), + .windows => len: { + const max_info_len = @sizeOf(std.os.windows.FILE_BOTH_DIR_INFORMATION) + std.os.windows.NAME_MAX * 2; + const info_align = @alignOf(std.os.windows.FILE_BOTH_DIR_INFORMATION); + const reserved_len = std.mem.alignForward(usize, max_name_bytes, info_align) - max_info_len; + break :len std.mem.alignForward(usize, reserved_len, info_align) + max_info_len; + }, + .wasi => @sizeOf(std.os.wasi.dirent_t) + + std.mem.alignForward(usize, max_name_bytes, @alignOf(std.os.wasi.dirent_t)), + .openbsd => std.c.S.BLKSIZE, + else => if (builtin.link_libc) @sizeOf(std.c.dirent) else std.mem.alignForward(usize, max_name_bytes, @alignOf(usize)), + }; + + pub const State = enum { + /// Indicates the next call to `read` should rewind and start over the + /// directory listing. + reset, + reading, + finished, + }; + + pub const Error = error{ + AccessDenied, + PermissionDenied, + SystemResources, + } || Io.UnexpectedError || Io.Cancelable; + + /// Asserts that `buffer` has length at least `min_buffer_len`. + pub fn init(dir: Dir, buffer: []align(@alignOf(usize)) u8) Reader { + assert(buffer.len >= min_buffer_len); + return .{ + .dir = dir, + .state = .reset, + .index = 0, + .end = 0, + .buffer = buffer, + }; + } + + /// All `Entry.name` are invalidated with the next call to `read` or + /// `next`. + pub fn read(r: *Reader, io: Io, buffer: []Entry) Error!usize { + return io.vtable.dirRead(io.userdata, r, buffer); + } + + /// `Entry.name` is invalidated with the next call to `read` or `next`. + pub fn next(r: *Reader, io: Io) Error!?Entry { + var buffer: [1]Entry = undefined; + while (true) { + const n = try read(r, io, &buffer); + if (n == 1) return buffer[0]; + if (r.state == .finished) return null; + } + } + + pub fn reset(r: *Reader) void { + r.state = .reset; + r.index = 0; + r.end = 0; + } +}; + +/// This API is designed for convenience rather than performance: +/// * It chooses a buffer size rather than allowing the user to provide one. +/// * It is movable by only requesting one `Entry` at a time from the `Io` +/// implementation rather than doing batch operations. +/// +/// Still, it will do a decent job of minimizing syscall overhead. For a +/// lower level abstraction, see `Reader`. For a higher level abstraction, +/// see `Walker`. +pub const Iterator = struct { + reader: Reader, + reader_buffer: [reader_buffer_len]u8 align(@alignOf(usize)), + + pub const reader_buffer_len = 2048; + + comptime { + assert(reader_buffer_len >= Reader.min_buffer_len); + } + + pub const Error = Reader.Error; + + pub fn init(dir: Dir, reader_state: Reader.State) Iterator { + return .{ + .reader = .{ + .dir = dir, + .state = reader_state, + .index = 0, + .end = 0, + .buffer = undefined, + }, + .reader_buffer = undefined, + }; + } + + pub fn next(it: *Iterator, io: Io) Error!?Entry { + it.reader.buffer = &it.reader_buffer; + return it.reader.next(io); + } +}; + +pub fn iterate(dir: Dir) Iterator { + return .init(dir, .reset); +} + +/// Like `iterate`, but will not reset the directory cursor before the first +/// iteration. This should only be used in cases where it is known that the +/// `Dir` has not had its cursor modified yet (e.g. it was just opened). +pub fn iterateAssumeFirstIteration(dir: Dir) Iterator { + return .init(dir, .reading); +} + +pub const SelectiveWalker = struct { + stack: std.ArrayList(StackItem), + name_buffer: std.ArrayList(u8), + allocator: Allocator, + + pub const Error = Iterator.Error || Allocator.Error; + + const StackItem = struct { + iter: Iterator, + dirname_len: usize, + }; + + /// After each call to this function, and on deinit(), the memory returned + /// from this function becomes invalid. A copy must be made in order to keep + /// a reference to the path. + pub fn next(self: *SelectiveWalker, io: Io) Error!?Walker.Entry { + while (self.stack.items.len > 0) { + const top = &self.stack.items[self.stack.items.len - 1]; + var dirname_len = top.dirname_len; + if (top.iter.next(io) catch |err| { + // If we get an error, then we want the user to be able to continue + // walking if they want, which means that we need to pop the directory + // that errored from the stack. Otherwise, all future `next` calls would + // likely just fail with the same error. + var item = self.stack.pop().?; + if (self.stack.items.len != 0) { + item.iter.reader.dir.close(io); + } + return err; + }) |entry| { + self.name_buffer.shrinkRetainingCapacity(dirname_len); + if (self.name_buffer.items.len != 0) { + try self.name_buffer.append(self.allocator, path.sep); + dirname_len += 1; + } + try self.name_buffer.ensureUnusedCapacity(self.allocator, entry.name.len + 1); + self.name_buffer.appendSliceAssumeCapacity(entry.name); + self.name_buffer.appendAssumeCapacity(0); + const walker_entry: Walker.Entry = .{ + .dir = top.iter.reader.dir, + .basename = self.name_buffer.items[dirname_len .. self.name_buffer.items.len - 1 :0], + .path = self.name_buffer.items[0 .. self.name_buffer.items.len - 1 :0], + .kind = entry.kind, + }; + return walker_entry; + } else { + var item = self.stack.pop().?; + if (self.stack.items.len != 0) { + item.iter.reader.dir.close(io); + } + } + } + return null; + } + + /// Traverses into the directory, continuing walking one level down. + pub fn enter(self: *SelectiveWalker, io: Io, entry: Walker.Entry) !void { + if (entry.kind != .directory) { + @branchHint(.cold); + return; + } + + var new_dir = entry.dir.openDir(io, entry.basename, .{ .iterate = true }) catch |err| { + switch (err) { + error.NameTooLong => unreachable, + else => |e| return e, + } + }; + errdefer new_dir.close(io); + + try self.stack.append(self.allocator, .{ + .iter = new_dir.iterateAssumeFirstIteration(), + .dirname_len = self.name_buffer.items.len - 1, + }); + } + + pub fn deinit(self: *SelectiveWalker) void { + self.name_buffer.deinit(self.allocator); + self.stack.deinit(self.allocator); + } + + /// Leaves the current directory, continuing walking one level up. + /// If the current entry is a directory entry, then the "current directory" + /// will pertain to that entry if `enter` is called before `leave`. + pub fn leave(self: *SelectiveWalker, io: Io) void { + var item = self.stack.pop().?; + if (self.stack.items.len != 0) { + @branchHint(.likely); + item.iter.reader.dir.close(io); + } + } +}; + +/// Recursively iterates over a directory, but requires the user to +/// opt-in to recursing into each directory entry. +/// +/// `dir` must have been opened with `OpenOptions.iterate` set to `true`. +/// +/// `Walker.deinit` releases allocated memory and directory handles. +/// +/// The order of returned file system entries is undefined. +/// +/// `dir` will not be closed after walking it. +/// +/// See also `walk`. +pub fn walkSelectively(dir: Dir, allocator: Allocator) !SelectiveWalker { + var stack: std.ArrayList(SelectiveWalker.StackItem) = .empty; + + try stack.append(allocator, .{ + .iter = dir.iterate(), + .dirname_len = 0, + }); + + return .{ + .stack = stack, + .name_buffer = .{}, + .allocator = allocator, + }; +} + +pub const Walker = struct { + inner: SelectiveWalker, + + pub const Entry = struct { + /// The containing directory. This can be used to operate directly on `basename` + /// rather than `path`, avoiding `error.NameTooLong` for deeply nested paths. + /// The directory remains open until `next` or `deinit` is called. + dir: Dir, + basename: [:0]const u8, + path: [:0]const u8, + kind: File.Kind, + + /// Returns the depth of the entry relative to the initial directory. + /// Returns 1 for a direct child of the initial directory, 2 for an entry + /// within a direct child of the initial directory, etc. + pub fn depth(self: Walker.Entry) usize { + return std.mem.countScalar(u8, self.path, path.sep) + 1; + } + }; + + /// After each call to this function, and on deinit(), the memory returned + /// from this function becomes invalid. A copy must be made in order to keep + /// a reference to the path. + pub fn next(self: *Walker, io: Io) !?Walker.Entry { + const entry = try self.inner.next(io); + if (entry != null and entry.?.kind == .directory) { + try self.inner.enter(io, entry.?); + } + return entry; + } + + pub fn deinit(self: *Walker) void { + self.inner.deinit(); + } + + /// Leaves the current directory, continuing walking one level up. + /// If the current entry is a directory entry, then the "current directory" + /// is the directory pertaining to the current entry. + pub fn leave(self: *Walker, io: Io) void { + self.inner.leave(io); + } +}; + +/// Recursively iterates over a directory. +/// +/// `dir` must have been opened with `OpenOptions.iterate` set to `true`. +/// +/// `Walker.deinit` releases allocated memory and directory handles. +/// +/// The order of returned file system entries is undefined. +/// +/// `dir` will not be closed after walking it. +/// +/// See also: +/// * `walkSelectively` +pub fn walk(dir: Dir, allocator: Allocator) Allocator.Error!Walker { + return .{ .inner = try walkSelectively(dir, allocator) }; } pub const Handle = std.posix.fd_t; pub const PathNameError = error{ + /// Returned when an insufficient buffer is provided that cannot fit the + /// path name. NameTooLong, /// File system cannot encode the requested file name bytes. /// Could be due to invalid WTF-8 on Windows, invalid UTF-8 on WASI, @@ -69,6 +439,11 @@ pub fn access(dir: Dir, io: Io, sub_path: []const u8, options: AccessOptions) Ac return io.vtable.dirAccess(io.userdata, dir, sub_path, options); } +pub fn accessAbsolute(io: Io, absolute_path: []const u8, options: AccessOptions) AccessError!void { + assert(path.isAbsolute(absolute_path)); + return access(.cwd(), io, absolute_path, options); +} + pub const OpenError = error{ FileNotFound, NotDir, @@ -79,7 +454,6 @@ pub const OpenError = error{ SystemFdQuotaExceeded, NoDevice, SystemResources, - DeviceBusy, /// On Windows, `\\server` or `\\server\share` was not found. NetworkNotFound, } || PathNameError || Io.Cancelable || Io.UnexpectedError; @@ -108,8 +482,17 @@ pub fn openDir(dir: Dir, io: Io, sub_path: []const u8, options: OpenOptions) Ope return io.vtable.dirOpenDir(io.userdata, dir, sub_path, options); } +pub fn openDirAbsolute(io: Io, absolute_path: []const u8, options: OpenOptions) OpenError!Dir { + assert(path.isAbsolute(absolute_path)); + return openDir(.cwd(), io, absolute_path, options); +} + pub fn close(dir: Dir, io: Io) void { - return io.vtable.dirClose(io.userdata, dir); + return io.vtable.dirClose(io.userdata, (&dir)[0..1]); +} + +pub fn closeMany(io: Io, dirs: []const Dir) void { + return io.vtable.dirClose(io.userdata, dirs); } /// Opens a file for reading or writing, without attempting to create a new file. @@ -125,6 +508,11 @@ pub fn openFile(dir: Dir, io: Io, sub_path: []const u8, flags: File.OpenFlags) F return io.vtable.dirOpenFile(io.userdata, dir, sub_path, flags); } +pub fn openFileAbsolute(io: Io, absolute_path: []const u8, flags: File.OpenFlags) File.OpenError!File { + assert(path.isAbsolute(absolute_path)); + return openFile(.cwd(), io, absolute_path, flags); +} + /// Creates, opens, or overwrites a file with write access. /// /// Allocates a resource to be dellocated with `File.close`. @@ -136,6 +524,10 @@ pub fn createFile(dir: Dir, io: Io, sub_path: []const u8, flags: File.CreateFlag return io.vtable.dirCreateFile(io.userdata, dir, sub_path, flags); } +pub fn createFileAbsolute(io: Io, absolute_path: []const u8, flags: File.CreateFlags) File.OpenError!File { + return createFile(.cwd(), io, absolute_path, flags); +} + pub const WriteFileOptions = struct { /// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). /// On WASI, `sub_path` should be encoded as valid UTF-8. @@ -145,13 +537,13 @@ pub const WriteFileOptions = struct { flags: File.CreateFlags = .{}, }; -pub const WriteFileError = File.WriteError || File.OpenError || Io.Cancelable; +pub const WriteFileError = File.Writer.Error || File.OpenError; /// Writes content to the file system, using the file creation flags provided. pub fn writeFile(dir: Dir, io: Io, options: WriteFileOptions) WriteFileError!void { var file = try dir.createFile(io, options.sub_path, options.flags); defer file.close(io); - try file.writeAll(io, options.data); + try file.writeStreamingAll(io, options.data); } pub const PrevStatus = enum { @@ -161,10 +553,10 @@ pub const PrevStatus = enum { pub const UpdateFileError = File.OpenError; -/// Check the file size, mtime, and mode of `source_path` and `dest_path`. If +/// Check the file size, mtime, and permissions of `source_path` and `dest_path`. If /// they are equal, does nothing. Otherwise, atomically copies `source_path` to /// `dest_path`, creating the parent directory hierarchy as needed. The -/// destination file gains the mtime, atime, and mode of the source file so +/// destination file gains the mtime, atime, and permissions of the source file so /// that the next call to `updateFile` will not need a copy. /// /// Returns the previous status of the file before updating. @@ -179,13 +571,13 @@ pub fn updateFile( dest_dir: Dir, /// If directories in this path do not exist, they are created. dest_path: []const u8, - options: std.fs.Dir.CopyFileOptions, + options: CopyFileOptions, ) !PrevStatus { var src_file = try source_dir.openFile(io, source_path, .{}); defer src_file.close(io); const src_stat = try src_file.stat(io); - const actual_mode = options.override_mode orelse src_stat.mode; + const actual_permissions = options.permissions orelse src_stat.permissions; check_dest_stat: { const dest_stat = blk: { var dest_file = dest_dir.openFile(io, dest_path, .{}) catch |err| switch (err) { @@ -199,33 +591,35 @@ pub fn updateFile( if (src_stat.size == dest_stat.size and src_stat.mtime.nanoseconds == dest_stat.mtime.nanoseconds and - actual_mode == dest_stat.mode) + actual_permissions == dest_stat.permissions) { return .fresh; } } - if (std.fs.path.dirname(dest_path)) |dirname| { - try dest_dir.makePath(io, dirname); - } - - var buffer: [1000]u8 = undefined; // Used only when direct fd-to-fd is not available. - var atomic_file = try std.fs.Dir.atomicFile(.adaptFromNewApi(dest_dir), dest_path, .{ - .mode = actual_mode, - .write_buffer = &buffer, + var atomic_file = try dest_dir.createFileAtomic(io, dest_path, .{ + .permissions = actual_permissions, + .make_path = true, + .replace = true, }); - defer atomic_file.deinit(); + defer atomic_file.deinit(io); + + var buffer: [1024]u8 = undefined; // Used only when direct fd-to-fd is not available. + var file_writer = atomic_file.file.writer(io, &buffer); var src_reader: File.Reader = .initSize(src_file, io, &.{}, src_stat.size); - const dest_writer = &atomic_file.file_writer.interface; + const dest_writer = &file_writer.interface; _ = dest_writer.sendFileAll(&src_reader, .unlimited) catch |err| switch (err) { error.ReadFailed => return src_reader.err.?, - error.WriteFailed => return atomic_file.file_writer.err.?, + error.WriteFailed => return file_writer.err.?, }; - try atomic_file.flush(); - try atomic_file.file_writer.file.updateTimes(src_stat.atime, src_stat.mtime); - try atomic_file.renameIntoPlace(); + try file_writer.flush(); + try file_writer.file.setTimestamps(io, .{ + .access_timestamp = .init(src_stat.atime), + .modify_timestamp = .init(src_stat.mtime), + }); + try atomic_file.replace(io); return .stale; } @@ -242,7 +636,11 @@ pub const ReadFileError = File.OpenError || File.Reader.Error; /// * On WASI, `file_path` should be encoded as valid UTF-8. /// * On other platforms, `file_path` is an opaque sequence of bytes with no particular encoding. pub fn readFile(dir: Dir, io: Io, file_path: []const u8, buffer: []u8) ReadFileError![]u8 { - var file = try dir.openFile(io, file_path, .{}); + var file = try dir.openFile(io, file_path, .{ + // We can take advantage of this on Windows since it doesn't involve any extra syscalls, + // so we can get error.IsDir during open rather than during the read. + .allow_directory = if (native_os == .windows) false else true, + }); defer file.close(io); var reader = file.reader(io, &.{}); @@ -253,7 +651,7 @@ pub fn readFile(dir: Dir, io: Io, file_path: []const u8, buffer: []u8) ReadFileE return buffer[0..n]; } -pub const MakeError = error{ +pub const CreateDirError = error{ /// In WASI, this error may occur when the file descriptor does /// not hold the required rights to create a new directory relative to it. AccessDenied, @@ -279,21 +677,36 @@ pub const MakeError = error{ /// * On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. /// /// Related: -/// * `makePath` -/// * `makeDirAbsolute` -pub fn makeDir(dir: Dir, io: Io, sub_path: []const u8) MakeError!void { - return io.vtable.dirMake(io.userdata, dir, sub_path, default_mode); +/// * `createDirPath` +/// * `createDirAbsolute` +pub fn createDir(dir: Dir, io: Io, sub_path: []const u8, permissions: Permissions) CreateDirError!void { + return io.vtable.dirCreateDir(io.userdata, dir, sub_path, permissions); +} + +/// Create a new directory, based on an absolute path. +/// +/// Asserts that the path is absolute. See `createDir` for a function that +/// operates on both absolute and relative paths. +/// +/// On Windows, `absolute_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). +/// On WASI, `absolute_path` should be encoded as valid UTF-8. +/// On other platforms, `absolute_path` is an opaque sequence of bytes with no particular encoding. +pub fn createDirAbsolute(io: Io, absolute_path: []const u8, permissions: Permissions) CreateDirError!void { + assert(path.isAbsolute(absolute_path)); + return createDir(.cwd(), io, absolute_path, permissions); } -pub const MakePathError = MakeError || StatPathError; +test createDirAbsolute {} -/// Calls makeDir iteratively to make an entire path, creating any parent -/// directories that do not exist. +pub const CreateDirPathError = CreateDirError || StatFileError; + +/// Creates parent directories with default permissions as necessary to ensure +/// `sub_path` exists as a directory. /// /// Returns success if the path already exists and is a directory. /// -/// This function is not atomic, and if it returns an error, the file system -/// may have been modified regardless. +/// This function may not be atomic. If it returns an error, the file system +/// may have been modified. /// /// Fails on an empty path with `error.BadPathName` as that is not a path that /// can be created. @@ -309,48 +722,29 @@ pub const MakePathError = MakeError || StatPathError; /// - On other platforms, `..` are not resolved before the path is passed to `mkdirat`, /// meaning a `sub_path` like "first/../second" will create both a `./first` /// and a `./second` directory. -pub fn makePath(dir: Dir, io: Io, sub_path: []const u8) MakePathError!void { - _ = try makePathStatus(dir, io, sub_path); +/// +/// See also: +/// * `createDirPathStatus` +pub fn createDirPath(dir: Dir, io: Io, sub_path: []const u8) CreateDirPathError!void { + _ = try io.vtable.dirCreateDirPath(io.userdata, dir, sub_path, .default_dir); } -pub const MakePathStatus = enum { existed, created }; +pub const CreatePathStatus = enum { existed, created }; -/// Same as `makePath` except returns whether the path already existed or was +/// Same as `createDirPath` except returns whether the path already existed or was /// successfully created. -pub fn makePathStatus(dir: Dir, io: Io, sub_path: []const u8) MakePathError!MakePathStatus { - var it = std.fs.path.componentIterator(sub_path); - var status: MakePathStatus = .existed; - var component = it.last() orelse return error.BadPathName; - while (true) { - if (makeDir(dir, io, component.path)) |_| { - status = .created; - } else |err| switch (err) { - error.PathAlreadyExists => { - // stat the file and return an error if it's not a directory - // this is important because otherwise a dangling symlink - // could cause an infinite loop - check_dir: { - // workaround for windows, see https://github.com/ziglang/zig/issues/16738 - const fstat = statPath(dir, io, component.path, .{}) catch |stat_err| switch (stat_err) { - error.IsDir => break :check_dir, - else => |e| return e, - }; - if (fstat.kind != .directory) return error.NotDir; - } - }, - error.FileNotFound => |e| { - component = it.previous() orelse return e; - continue; - }, - else => |e| return e, - } - component = it.next() orelse return status; - } +pub fn createDirPathStatus(dir: Dir, io: Io, sub_path: []const u8, permissions: Permissions) CreateDirPathError!CreatePathStatus { + return io.vtable.dirCreateDirPath(io.userdata, dir, sub_path, permissions); } -pub const MakeOpenPathError = MakeError || OpenError || StatPathError; +pub const CreateDirPathOpenError = CreateDirError || OpenError || StatFileError; + +pub const CreateDirPathOpenOptions = struct { + open_options: OpenOptions = .{}, + permissions: Permissions = .default_dir, +}; -/// Performs the equivalent of `makePath` followed by `openDir`, atomically if possible. +/// Performs the equivalent of `createDirPath` followed by `openDir`, atomically if possible. /// /// When this operation is canceled, it may leave the file system in a /// partially modified state. @@ -358,8 +752,8 @@ pub const MakeOpenPathError = MakeError || OpenError || StatPathError; /// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). /// On WASI, `sub_path` should be encoded as valid UTF-8. /// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. -pub fn makeOpenPath(dir: Dir, io: Io, sub_path: []const u8, options: OpenOptions) MakeOpenPathError!Dir { - return io.vtable.dirMakeOpenPath(io.userdata, dir, sub_path, options); +pub fn createDirPathOpen(dir: Dir, io: Io, sub_path: []const u8, options: CreateDirPathOpenOptions) CreateDirPathOpenError!Dir { + return io.vtable.dirCreateDirPathOpen(io.userdata, dir, sub_path, options.permissions, options.open_options); } pub const Stat = File.Stat; @@ -369,9 +763,9 @@ pub fn stat(dir: Dir, io: Io) StatError!Stat { return io.vtable.dirStat(io.userdata, dir); } -pub const StatPathError = File.OpenError || File.StatError; +pub const StatFileError = File.OpenError || File.StatError; -pub const StatPathOptions = struct { +pub const StatFileOptions = struct { follow_symlinks: bool = true, }; @@ -387,6 +781,1141 @@ pub const StatPathOptions = struct { /// * On Windows, `sub_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/). /// * On WASI, `sub_path` should be encoded as valid UTF-8. /// * On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. -pub fn statPath(dir: Dir, io: Io, sub_path: []const u8, options: StatPathOptions) StatPathError!Stat { - return io.vtable.dirStatPath(io.userdata, dir, sub_path, options); +pub fn statFile(dir: Dir, io: Io, sub_path: []const u8, options: StatFileOptions) StatFileError!Stat { + return io.vtable.dirStatFile(io.userdata, dir, sub_path, options); +} + +pub const RealPathError = File.RealPathError; + +/// Obtains the canonicalized absolute path name of `sub_path` relative to this +/// `Dir`. If `sub_path` is absolute, ignores this `Dir` handle and obtains the +/// canonicalized absolute pathname of `sub_path` argument. +/// +/// This function has limited platform support, and using it can lead to +/// unnecessary failures and race conditions. It is generally advisable to +/// avoid this function entirely. +pub fn realPath(dir: Dir, io: Io, out_buffer: []u8) RealPathError!usize { + return io.vtable.dirRealPath(io.userdata, dir, out_buffer); +} + +pub const RealPathFileError = RealPathError || PathNameError; + +/// Obtains the canonicalized absolute path name of `sub_path` relative to this +/// `Dir`. If `sub_path` is absolute, ignores this `Dir` handle and obtains the +/// canonicalized absolute pathname of `sub_path` argument. +/// +/// This function has limited platform support, and using it can lead to +/// unnecessary failures and race conditions. It is generally advisable to +/// avoid this function entirely. +/// +/// See also: +/// * `realPathFileAlloc`. +/// * `realPathFileAbsolute`. +pub fn realPathFile(dir: Dir, io: Io, sub_path: []const u8, out_buffer: []u8) RealPathFileError!usize { + return io.vtable.dirRealPathFile(io.userdata, dir, sub_path, out_buffer); +} + +pub const RealPathFileAllocError = RealPathFileError || Allocator.Error; + +/// Same as `realPathFile` except allocates result. +/// +/// This function has limited platform support, and using it can lead to +/// unnecessary failures and race conditions. It is generally advisable to +/// avoid this function entirely. +/// +/// See also: +/// * `realPathFile`. +/// * `realPathFileAbsolute`. +pub fn realPathFileAlloc(dir: Dir, io: Io, sub_path: []const u8, allocator: Allocator) RealPathFileAllocError![:0]u8 { + var buffer: [max_path_bytes]u8 = undefined; + const n = try realPathFile(dir, io, sub_path, &buffer); + return allocator.dupeZ(u8, buffer[0..n]); +} + +/// Same as `realPathFile` except `absolute_path` is asserted to be an absolute +/// path. +/// +/// This function has limited platform support, and using it can lead to +/// unnecessary failures and race conditions. It is generally advisable to +/// avoid this function entirely. +/// +/// See also: +/// * `realPathFile`. +/// * `realPathFileAlloc`. +pub fn realPathFileAbsolute(io: Io, absolute_path: []const u8, out_buffer: []u8) RealPathFileError!usize { + assert(path.isAbsolute(absolute_path)); + return io.vtable.dirRealPathFile(io.userdata, .cwd(), absolute_path, out_buffer); +} + +/// Same as `realPathFileAbsolute` except allocates result. +/// +/// This function has limited platform support, and using it can lead to +/// unnecessary failures and race conditions. It is generally advisable to +/// avoid this function entirely. +/// +/// See also: +/// * `realPathFileAbsolute`. +/// * `realPathFile`. +pub fn realPathFileAbsoluteAlloc(io: Io, absolute_path: []const u8, allocator: Allocator) RealPathFileAllocError![:0]u8 { + var buffer: [max_path_bytes]u8 = undefined; + const n = try realPathFileAbsolute(io, absolute_path, &buffer); + return allocator.dupeZ(u8, buffer[0..n]); +} + +pub const DeleteFileError = error{ + FileNotFound, + /// In WASI, this error may occur when the file descriptor does + /// not hold the required rights to unlink a resource by path relative to it. + AccessDenied, + PermissionDenied, + FileBusy, + FileSystem, + IsDir, + SymLinkLoop, + NotDir, + SystemResources, + ReadOnlyFileSystem, + /// On Windows, `\\server` or `\\server\share` was not found. + NetworkNotFound, +} || PathNameError || Io.Cancelable || Io.UnexpectedError; + +/// Delete a file name and possibly the file it refers to, based on an open directory handle. +/// +/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). +/// On WASI, `sub_path` should be encoded as valid UTF-8. +/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. +/// +/// Asserts that the path parameter has no null bytes. +pub fn deleteFile(dir: Dir, io: Io, sub_path: []const u8) DeleteFileError!void { + return io.vtable.dirDeleteFile(io.userdata, dir, sub_path); +} + +pub fn deleteFileAbsolute(io: Io, absolute_path: []const u8) DeleteFileError!void { + assert(path.isAbsolute(absolute_path)); + return deleteFile(.cwd(), io, absolute_path); +} + +test deleteFileAbsolute {} + +pub const DeleteDirError = error{ + DirNotEmpty, + FileNotFound, + AccessDenied, + PermissionDenied, + FileBusy, + FileSystem, + SymLinkLoop, + NotDir, + SystemResources, + ReadOnlyFileSystem, + /// On Windows, `\\server` or `\\server\share` was not found. + NetworkNotFound, +} || PathNameError || Io.Cancelable || Io.UnexpectedError; + +/// Returns `error.DirNotEmpty` if the directory is not empty. +/// +/// To delete a directory recursively, see `deleteTree`. +/// +/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). +/// On WASI, `sub_path` should be encoded as valid UTF-8. +/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. +pub fn deleteDir(dir: Dir, io: Io, sub_path: []const u8) DeleteDirError!void { + return io.vtable.dirDeleteDir(io.userdata, dir, sub_path); +} + +/// Same as `deleteDir` except the path is absolute. +/// +/// On Windows, `dir_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). +/// On WASI, `dir_path` should be encoded as valid UTF-8. +/// On other platforms, `dir_path` is an opaque sequence of bytes with no particular encoding. +pub fn deleteDirAbsolute(io: Io, absolute_path: []const u8) DeleteDirError!void { + assert(path.isAbsolute(absolute_path)); + return deleteDir(.cwd(), io, absolute_path); +} + +pub const RenameError = error{ + /// In WASI, this error may occur when the file descriptor does + /// not hold the required rights to rename a resource by path relative to it. + AccessDenied, + /// Attempted to replace a nonempty directory. + DirNotEmpty, + PermissionDenied, + FileBusy, + DiskQuota, + IsDir, + SymLinkLoop, + LinkQuotaExceeded, + FileNotFound, + NotDir, + SystemResources, + NoSpaceLeft, + ReadOnlyFileSystem, + CrossDevice, + NoDevice, + SharingViolation, + PipeBusy, + /// On Windows, `\\server` or `\\server\share` was not found. + NetworkNotFound, + /// On Windows, antivirus software is enabled by default. It can be + /// disabled, but Windows Update sometimes ignores the user's preference + /// and re-enables it. When enabled, antivirus software on Windows + /// intercepts file system operations and makes them significantly slower + /// in addition to possibly failing with this error code. + AntivirusInterference, + HardwareFailure, +} || PathNameError || Io.Cancelable || Io.UnexpectedError; + +/// Change the name or location of a file or directory. +/// +/// If `new_sub_path` already exists, it will be replaced. +/// +/// Renaming a file over an existing directory or a directory over an existing +/// file will fail with `error.IsDir` or `error.NotDir` +/// +/// * On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/). +/// * On WASI, both paths should be encoded as valid UTF-8. +/// * On other platforms, both paths are an opaque sequence of bytes with no particular encoding. +pub fn rename( + old_dir: Dir, + old_sub_path: []const u8, + new_dir: Dir, + new_sub_path: []const u8, + io: Io, +) RenameError!void { + return io.vtable.dirRename(io.userdata, old_dir, old_sub_path, new_dir, new_sub_path); +} + +pub fn renameAbsolute(old_path: []const u8, new_path: []const u8, io: Io) RenameError!void { + assert(path.isAbsolute(old_path)); + assert(path.isAbsolute(new_path)); + const my_cwd = cwd(); + return io.vtable.dirRename(io.userdata, my_cwd, old_path, my_cwd, new_path); +} + +pub const RenamePreserveError = error{ + /// In WASI, this error may occur when the file descriptor does + /// not hold the required rights to rename a resource by path relative to it. + /// + /// On Windows, this error may be returned instead of PathAlreadyExists when + /// renaming a directory over an existing directory. + AccessDenied, + PathAlreadyExists, + /// Operating system or file system does not support atomic nonreplacing + /// rename. + OperationUnsupported, +} || RenameError; + +/// Change the name or location of a file or directory. +/// +/// If `new_sub_path` already exists, `error.PathAlreadyExists` will be returned. +/// +/// Renaming a file over an existing directory or a directory over an existing +/// file will fail with `error.IsDir` or `error.NotDir` +/// +/// * On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/). +/// * On WASI, both paths should be encoded as valid UTF-8. +/// * On other platforms, both paths are an opaque sequence of bytes with no particular encoding. +pub fn renamePreserve( + old_dir: Dir, + old_sub_path: []const u8, + new_dir: Dir, + new_sub_path: []const u8, + io: Io, +) RenamePreserveError!void { + return io.vtable.dirRenamePreserve(io.userdata, old_dir, old_sub_path, new_dir, new_sub_path); +} + +pub const HardLinkOptions = File.HardLinkOptions; + +pub const HardLinkError = File.HardLinkError; + +pub fn hardLink( + old_dir: Dir, + old_sub_path: []const u8, + new_dir: Dir, + new_sub_path: []const u8, + io: Io, + options: HardLinkOptions, +) HardLinkError!void { + return io.vtable.dirHardLink(io.userdata, old_dir, old_sub_path, new_dir, new_sub_path, options); +} + +/// Use with `symLink`, `symLinkAtomic`, and `symLinkAbsolute` to +/// specify whether the symlink will point to a file or a directory. This value +/// is ignored on all hosts except Windows where creating symlinks to different +/// resource types, requires different flags. By default, `symLinkAbsolute` is +/// assumed to point to a file. +pub const SymLinkFlags = struct { + is_directory: bool = false, +}; + +pub const SymLinkError = error{ + /// In WASI, this error may occur when the file descriptor does + /// not hold the required rights to create a new symbolic link relative to it. + AccessDenied, + PermissionDenied, + DiskQuota, + PathAlreadyExists, + FileSystem, + SymLinkLoop, + FileNotFound, + SystemResources, + NoSpaceLeft, + /// On Windows, `\\server` or `\\server\share` was not found. + NetworkNotFound, + ReadOnlyFileSystem, + NotDir, +} || PathNameError || Io.Cancelable || Io.UnexpectedError; + +/// Creates a symbolic link named `sym_link_path` which contains the string `target_path`. +/// +/// A symbolic link (also known as a soft link) may point to an existing file or to a nonexistent +/// one; the latter case is known as a dangling link. +/// +/// If `sym_link_path` exists, it will not be overwritten. +/// +/// On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/). +/// On WASI, both paths should be encoded as valid UTF-8. +/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding. +pub fn symLink( + dir: Dir, + io: Io, + target_path: []const u8, + sym_link_path: []const u8, + flags: SymLinkFlags, +) SymLinkError!void { + return io.vtable.dirSymLink(io.userdata, dir, target_path, sym_link_path, flags); +} + +pub fn symLinkAbsolute( + io: Io, + target_path: []const u8, + sym_link_path: []const u8, + flags: SymLinkFlags, +) SymLinkError!void { + assert(path.isAbsolute(target_path)); + assert(path.isAbsolute(sym_link_path)); + return symLink(.cwd(), io, target_path, sym_link_path, flags); +} + +/// Same as `symLink`, except tries to create the symbolic link until it +/// succeeds or encounters an error other than `error.PathAlreadyExists`. +/// +/// * On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/). +/// * On WASI, both paths should be encoded as valid UTF-8. +/// * On other platforms, both paths are an opaque sequence of bytes with no particular encoding. +pub fn symLinkAtomic( + dir: Dir, + io: Io, + target_path: []const u8, + sym_link_path: []const u8, + flags: SymLinkFlags, +) !void { + if (dir.symLink(io, target_path, sym_link_path, flags)) { + return; + } else |err| switch (err) { + error.PathAlreadyExists => {}, + else => |e| return e, + } + + const dirname = path.dirname(sym_link_path) orelse "."; + + const rand_len = @sizeOf(u64) * 2; + const temp_path_len = dirname.len + 1 + rand_len; + var temp_path_buf: [max_path_bytes]u8 = undefined; + + if (temp_path_len > temp_path_buf.len) return error.NameTooLong; + @memcpy(temp_path_buf[0..dirname.len], dirname); + temp_path_buf[dirname.len] = path.sep; + + const temp_path = temp_path_buf[0..temp_path_len]; + + var random_integer: u64 = undefined; + + while (true) { + io.random(@ptrCast(&random_integer)); + temp_path[dirname.len + 1 ..][0..rand_len].* = std.fmt.hex(random_integer); + + if (dir.symLink(io, target_path, temp_path, flags)) { + return dir.rename(temp_path, dir, sym_link_path, io); + } else |err| switch (err) { + error.PathAlreadyExists => continue, + else => |e| return e, + } + } +} + +pub const ReadLinkError = error{ + /// In WASI, this error may occur when the file descriptor does + /// not hold the required rights to read value of a symbolic link relative to it. + AccessDenied, + PermissionDenied, + FileSystem, + SymLinkLoop, + FileNotFound, + SystemResources, + NotLink, + NotDir, + /// Windows-only. This error may occur if the opened reparse point is + /// of unsupported type. + UnsupportedReparsePointType, + /// On Windows, `\\server` or `\\server\share` was not found. + NetworkNotFound, + /// On Windows, antivirus software is enabled by default. It can be + /// disabled, but Windows Update sometimes ignores the user's preference + /// and re-enables it. When enabled, antivirus software on Windows + /// intercepts file system operations and makes them significantly slower + /// in addition to possibly failing with this error code. + AntivirusInterference, +} || PathNameError || Io.Cancelable || Io.UnexpectedError; + +/// Obtain target of a symbolic link. +/// +/// Returns how many bytes of `buffer` are populated. +/// +/// Asserts that the path parameter has no null bytes. +/// +/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). +/// On WASI, `sub_path` should be encoded as valid UTF-8. +/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. +pub fn readLink(dir: Dir, io: Io, sub_path: []const u8, buffer: []u8) ReadLinkError!usize { + return io.vtable.dirReadLink(io.userdata, dir, sub_path, buffer); +} + +/// Same as `readLink`, except it asserts the path is absolute. +/// +/// On Windows, `path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). +/// On WASI, `path` should be encoded as valid UTF-8. +/// On other platforms, `path` is an opaque sequence of bytes with no particular encoding. +pub fn readLinkAbsolute(io: Io, absolute_path: []const u8, buffer: []u8) ReadLinkError!usize { + assert(path.isAbsolute(absolute_path)); + return io.vtable.dirReadLink(io.userdata, .cwd(), absolute_path, buffer); +} + +pub const ReadFileAllocError = File.OpenError || File.Reader.Error || Allocator.Error || error{ + /// File size reached or exceeded the provided limit. + StreamTooLong, +}; + +/// Reads all the bytes from the named file. On success, caller owns returned +/// buffer. +/// +/// If the file size is already known, a better alternative is to initialize a +/// `File.Reader`. +/// +/// If the file size cannot be obtained, an error is returned. If +/// this is a realistic possibility, a better alternative is to initialize a +/// `File.Reader` which handles this seamlessly. +pub fn readFileAlloc( + dir: Dir, + io: Io, + /// On Windows, should be encoded as [WTF-8](https://wtf-8.codeberg.page/). + /// On WASI, should be encoded as valid UTF-8. + /// On other platforms, an opaque sequence of bytes with no particular encoding. + sub_path: []const u8, + /// Used to allocate the result. + gpa: Allocator, + /// If reached or exceeded, `error.StreamTooLong` is returned instead. + limit: Io.Limit, +) ReadFileAllocError![]u8 { + return readFileAllocOptions(dir, io, sub_path, gpa, limit, .of(u8), null); +} + +/// Reads all the bytes from the named file. On success, caller owns returned +/// buffer. +/// +/// If the file size is already known, a better alternative is to initialize a +/// `File.Reader`. +pub fn readFileAllocOptions( + dir: Dir, + io: Io, + /// On Windows, should be encoded as [WTF-8](https://wtf-8.codeberg.page/). + /// On WASI, should be encoded as valid UTF-8. + /// On other platforms, an opaque sequence of bytes with no particular encoding. + sub_path: []const u8, + /// Used to allocate the result. + gpa: Allocator, + /// If reached or exceeded, `error.StreamTooLong` is returned instead. + limit: Io.Limit, + comptime alignment: std.mem.Alignment, + comptime sentinel: ?u8, +) ReadFileAllocError!(if (sentinel) |s| [:s]align(alignment.toByteUnits()) u8 else []align(alignment.toByteUnits()) u8) { + var file = try dir.openFile(io, sub_path, .{ + // We can take advantage of this on Windows since it doesn't involve any extra syscalls, + // so we can get error.IsDir during open rather than during the read. + .allow_directory = if (native_os == .windows) false else true, + }); + defer file.close(io); + var file_reader = file.reader(io, &.{}); + return file_reader.interface.allocRemainingAlignedSentinel(gpa, limit, alignment, sentinel) catch |err| switch (err) { + error.ReadFailed => return file_reader.err.?, + error.OutOfMemory, error.StreamTooLong => |e| return e, + }; +} + +pub const DeleteTreeError = error{ + AccessDenied, + PermissionDenied, + FileTooBig, + SymLinkLoop, + ProcessFdQuotaExceeded, + SystemFdQuotaExceeded, + NoDevice, + SystemResources, + ReadOnlyFileSystem, + FileSystem, + FileBusy, + /// One of the path components was not a directory. + /// This error is unreachable if `sub_path` does not contain a path separator. + NotDir, + /// On Windows, `\\server` or `\\server\share` was not found. + NetworkNotFound, +} || PathNameError || Io.Cancelable || Io.UnexpectedError; + +/// Whether `sub_path` describes a symlink, file, or directory, this function +/// removes it. If it cannot be removed because it is a non-empty directory, +/// this function recursively removes its entries and then tries again. +/// +/// This operation is not atomic on most file systems. +/// +/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). +/// On WASI, `sub_path` should be encoded as valid UTF-8. +/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. +pub fn deleteTree(dir: Dir, io: Io, sub_path: []const u8) DeleteTreeError!void { + var initial_iterable_dir = (try dir.deleteTreeOpenInitialSubpath(io, sub_path, .file)) orelse return; + + const StackItem = struct { + name: []const u8, + parent_dir: Dir, + iter: Iterator, + + fn closeAll(inner_io: Io, items: []@This()) void { + for (items) |*item| item.iter.reader.dir.close(inner_io); + } + }; + + var stack_buffer: [16]StackItem = undefined; + var stack = std.ArrayList(StackItem).initBuffer(&stack_buffer); + defer StackItem.closeAll(io, stack.items); + + stack.appendAssumeCapacity(.{ + .name = sub_path, + .parent_dir = dir, + .iter = initial_iterable_dir.iterateAssumeFirstIteration(), + }); + + process_stack: while (stack.items.len != 0) { + var top = &stack.items[stack.items.len - 1]; + while (try top.iter.next(io)) |entry| { + var treat_as_dir = entry.kind == .directory; + handle_entry: while (true) { + if (treat_as_dir) { + if (stack.unusedCapacitySlice().len >= 1) { + var iterable_dir = top.iter.reader.dir.openDir(io, entry.name, .{ + .follow_symlinks = false, + .iterate = true, + }) catch |err| switch (err) { + error.NotDir => { + treat_as_dir = false; + continue :handle_entry; + }, + error.FileNotFound => { + // That's fine, we were trying to remove this directory anyway. + break :handle_entry; + }, + + error.AccessDenied, + error.PermissionDenied, + error.SymLinkLoop, + error.ProcessFdQuotaExceeded, + error.NameTooLong, + error.SystemFdQuotaExceeded, + error.NoDevice, + error.SystemResources, + error.Unexpected, + error.BadPathName, + error.NetworkNotFound, + error.Canceled, + => |e| return e, + }; + stack.appendAssumeCapacity(.{ + .name = entry.name, + .parent_dir = top.iter.reader.dir, + .iter = iterable_dir.iterateAssumeFirstIteration(), + }); + continue :process_stack; + } else { + try top.iter.reader.dir.deleteTreeMinStackSizeWithKindHint(io, entry.name, entry.kind); + break :handle_entry; + } + } else { + if (top.iter.reader.dir.deleteFile(io, entry.name)) { + break :handle_entry; + } else |err| switch (err) { + error.FileNotFound => break :handle_entry, + + // Impossible because we do not pass any path separators. + error.NotDir => unreachable, + + error.IsDir => { + treat_as_dir = true; + continue :handle_entry; + }, + + error.AccessDenied, + error.PermissionDenied, + error.SymLinkLoop, + error.NameTooLong, + error.SystemResources, + error.ReadOnlyFileSystem, + error.FileSystem, + error.FileBusy, + error.BadPathName, + error.NetworkNotFound, + error.Canceled, + error.Unexpected, + => |e| return e, + } + } + } + } + + // On Windows, we can't delete until the dir's handle has been closed, so + // close it before we try to delete. + top.iter.reader.dir.close(io); + + // In order to avoid double-closing the directory when cleaning up + // the stack in the case of an error, we save the relevant portions and + // pop the value from the stack. + const parent_dir = top.parent_dir; + const name = top.name; + stack.items.len -= 1; + + var need_to_retry: bool = false; + parent_dir.deleteDir(io, name) catch |err| switch (err) { + error.FileNotFound => {}, + error.DirNotEmpty => need_to_retry = true, + else => |e| return e, + }; + + if (need_to_retry) { + // Since we closed the handle that the previous iterator used, we + // need to re-open the dir and re-create the iterator. + var iterable_dir = iterable_dir: { + var treat_as_dir = true; + handle_entry: while (true) { + if (treat_as_dir) { + break :iterable_dir parent_dir.openDir(io, name, .{ + .follow_symlinks = false, + .iterate = true, + }) catch |err| switch (err) { + error.NotDir => { + treat_as_dir = false; + continue :handle_entry; + }, + error.FileNotFound => { + // That's fine, we were trying to remove this directory anyway. + continue :process_stack; + }, + + error.AccessDenied, + error.PermissionDenied, + error.SymLinkLoop, + error.ProcessFdQuotaExceeded, + error.NameTooLong, + error.SystemFdQuotaExceeded, + error.NoDevice, + error.SystemResources, + error.Unexpected, + error.BadPathName, + error.NetworkNotFound, + error.Canceled, + => |e| return e, + }; + } else { + if (parent_dir.deleteFile(io, name)) { + continue :process_stack; + } else |err| switch (err) { + error.FileNotFound => continue :process_stack, + + // Impossible because we do not pass any path separators. + error.NotDir => unreachable, + + error.IsDir => { + treat_as_dir = true; + continue :handle_entry; + }, + + error.AccessDenied, + error.PermissionDenied, + error.SymLinkLoop, + error.NameTooLong, + error.SystemResources, + error.ReadOnlyFileSystem, + error.FileSystem, + error.FileBusy, + error.BadPathName, + error.NetworkNotFound, + error.Canceled, + error.Unexpected, + => |e| return e, + } + } + } + }; + // We know there is room on the stack since we are just re-adding + // the StackItem that we previously popped. + stack.appendAssumeCapacity(.{ + .name = name, + .parent_dir = parent_dir, + .iter = iterable_dir.iterateAssumeFirstIteration(), + }); + continue :process_stack; + } + } +} + +/// Like `deleteTree`, but only keeps one `Iterator` active at a time to minimize the function's stack size. +/// This is slower than `deleteTree` but uses less stack space. +/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). +/// On WASI, `sub_path` should be encoded as valid UTF-8. +/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. +pub fn deleteTreeMinStackSize(dir: Dir, io: Io, sub_path: []const u8) DeleteTreeError!void { + return dir.deleteTreeMinStackSizeWithKindHint(io, sub_path, .file); +} + +fn deleteTreeMinStackSizeWithKindHint(parent: Dir, io: Io, sub_path: []const u8, kind_hint: File.Kind) DeleteTreeError!void { + start_over: while (true) { + var dir = (try parent.deleteTreeOpenInitialSubpath(io, sub_path, kind_hint)) orelse return; + var cleanup_dir_parent: ?Dir = null; + defer if (cleanup_dir_parent) |*d| d.close(io); + + var cleanup_dir = true; + defer if (cleanup_dir) dir.close(io); + + // Valid use of max_path_bytes because dir_name_buf will only + // ever store a single path component that was returned from the + // filesystem. + var dir_name_buf: [max_path_bytes]u8 = undefined; + var dir_name: []const u8 = sub_path; + + // Here we must avoid recursion, in order to provide O(1) memory guarantee of this function. + // Go through each entry and if it is not a directory, delete it. If it is a directory, + // open it, and close the original directory. Repeat. Then start the entire operation over. + + scan_dir: while (true) { + var dir_it = dir.iterateAssumeFirstIteration(); + dir_it: while (try dir_it.next(io)) |entry| { + var treat_as_dir = entry.kind == .directory; + handle_entry: while (true) { + if (treat_as_dir) { + const new_dir = dir.openDir(io, entry.name, .{ + .follow_symlinks = false, + .iterate = true, + }) catch |err| switch (err) { + error.NotDir => { + treat_as_dir = false; + continue :handle_entry; + }, + error.FileNotFound => { + // That's fine, we were trying to remove this directory anyway. + continue :dir_it; + }, + + error.AccessDenied, + error.PermissionDenied, + error.SymLinkLoop, + error.ProcessFdQuotaExceeded, + error.NameTooLong, + error.SystemFdQuotaExceeded, + error.NoDevice, + error.SystemResources, + error.Unexpected, + error.BadPathName, + error.NetworkNotFound, + error.Canceled, + => |e| return e, + }; + if (cleanup_dir_parent) |*d| d.close(io); + cleanup_dir_parent = dir; + dir = new_dir; + const result = dir_name_buf[0..entry.name.len]; + @memcpy(result, entry.name); + dir_name = result; + continue :scan_dir; + } else { + if (dir.deleteFile(io, entry.name)) { + continue :dir_it; + } else |err| switch (err) { + error.FileNotFound => continue :dir_it, + + // Impossible because we do not pass any path separators. + error.NotDir => unreachable, + + error.IsDir => { + treat_as_dir = true; + continue :handle_entry; + }, + + error.AccessDenied, + error.PermissionDenied, + error.SymLinkLoop, + error.NameTooLong, + error.SystemResources, + error.ReadOnlyFileSystem, + error.FileSystem, + error.FileBusy, + error.BadPathName, + error.NetworkNotFound, + error.Canceled, + error.Unexpected, + => |e| return e, + } + } + } + } + // Reached the end of the directory entries, which means we successfully deleted all of them. + // Now to remove the directory itself. + dir.close(io); + cleanup_dir = false; + + if (cleanup_dir_parent) |d| { + d.deleteDir(io, dir_name) catch |err| switch (err) { + // These two things can happen due to file system race conditions. + error.FileNotFound, error.DirNotEmpty => continue :start_over, + else => |e| return e, + }; + continue :start_over; + } else { + parent.deleteDir(io, sub_path) catch |err| switch (err) { + error.FileNotFound => return, + error.DirNotEmpty => continue :start_over, + else => |e| return e, + }; + return; + } + } + } +} + +/// On successful delete, returns null. +fn deleteTreeOpenInitialSubpath(dir: Dir, io: Io, sub_path: []const u8, kind_hint: File.Kind) !?Dir { + return iterable_dir: { + // Treat as a file by default + var treat_as_dir = kind_hint == .directory; + + handle_entry: while (true) { + if (treat_as_dir) { + break :iterable_dir dir.openDir(io, sub_path, .{ + .follow_symlinks = false, + .iterate = true, + }) catch |err| switch (err) { + error.NotDir => { + treat_as_dir = false; + continue :handle_entry; + }, + error.FileNotFound => { + // That's fine, we were trying to remove this directory anyway. + return null; + }, + + error.AccessDenied, + error.PermissionDenied, + error.SymLinkLoop, + error.ProcessFdQuotaExceeded, + error.NameTooLong, + error.SystemFdQuotaExceeded, + error.NoDevice, + error.SystemResources, + error.Unexpected, + error.BadPathName, + error.NetworkNotFound, + error.Canceled, + => |e| return e, + }; + } else { + if (dir.deleteFile(io, sub_path)) { + return null; + } else |err| switch (err) { + error.FileNotFound => return null, + + error.IsDir => { + treat_as_dir = true; + continue :handle_entry; + }, + + error.AccessDenied, + error.PermissionDenied, + error.SymLinkLoop, + error.NameTooLong, + error.SystemResources, + error.ReadOnlyFileSystem, + error.NotDir, + error.FileSystem, + error.FileBusy, + error.BadPathName, + error.NetworkNotFound, + error.Canceled, + error.Unexpected, + => |e| return e, + } + } + } + }; +} + +pub const CopyFileOptions = struct { + /// When this is `null` the permissions are copied from the source file. + permissions: ?File.Permissions = null, + make_path: bool = false, + replace: bool = true, +}; + +pub const CopyFileError = File.OpenError || File.StatError || + CreateFileAtomicError || File.Atomic.ReplaceError || File.Atomic.LinkError || + File.Reader.Error || File.Writer.Error || error{InvalidFileName}; + +/// Atomically creates a new file at `dest_path` within `dest_dir` with the +/// same contents as `source_path` within `source_dir`. +/// +/// Whether to overwrite the existing file is determined by `options`. +/// +/// On Linux, until https://patchwork.kernel.org/patch/9636735/ is merged and +/// readily available, there is a possibility of power loss or application +/// termination leaving temporary files present in the same directory as +/// dest_path. +/// +/// On Windows, both paths should be encoded as +/// [WTF-8](https://wtf-8.codeberg.page/). On WASI, both paths should be +/// encoded as valid UTF-8. On other platforms, both paths are an opaque +/// sequence of bytes with no particular encoding. +pub fn copyFile( + source_dir: Dir, + source_path: []const u8, + dest_dir: Dir, + dest_path: []const u8, + io: Io, + options: CopyFileOptions, +) CopyFileError!void { + const file = try source_dir.openFile(io, source_path, .{}); + var file_reader: File.Reader = .init(.{ .handle = file.handle }, io, &.{}); + defer file_reader.file.close(io); + + const permissions = options.permissions orelse blk: { + const st = try file_reader.file.stat(io); + file_reader.size = st.size; + break :blk st.permissions; + }; + + var atomic_file = try dest_dir.createFileAtomic(io, dest_path, .{ + .permissions = permissions, + .make_path = options.make_path, + .replace = options.replace, + }); + defer atomic_file.deinit(io); + + var buffer: [1024]u8 = undefined; // Used only when direct fd-to-fd is not available. + var file_writer = atomic_file.file.writer(io, &buffer); + + _ = file_writer.interface.sendFileAll(&file_reader, .unlimited) catch |err| switch (err) { + error.ReadFailed => return file_reader.err.?, + error.WriteFailed => return file_writer.err.?, + }; + + try file_writer.flush(); + + switch (options.replace) { + true => try atomic_file.replace(io), + false => try atomic_file.link(io), + } +} + +/// Same as `copyFile`, except asserts that both `source_path` and `dest_path` +/// are absolute. +/// +/// On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/). +/// On WASI, both paths should be encoded as valid UTF-8. +/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding. +pub fn copyFileAbsolute( + source_path: []const u8, + dest_path: []const u8, + io: Io, + options: CopyFileOptions, +) !void { + assert(path.isAbsolute(source_path)); + assert(path.isAbsolute(dest_path)); + const my_cwd = cwd(); + return copyFile(my_cwd, source_path, my_cwd, dest_path, io, options); +} + +test copyFileAbsolute {} + +pub const CreateFileAtomicOptions = struct { + permissions: File.Permissions = .default_file, + make_path: bool = false, + /// Tells whether the unnamed file will be ultimately created with + /// `File.Atomic.link` or `File.Atomic.replace`. + /// + /// If this value is incorrect it will cause an assertion failure in + /// `File.Atomic.replace`. + replace: bool = false, +}; + +pub const CreateFileAtomicError = error{ + NoDevice, + /// On Windows, `\\server` or `\\server\share` was not found. + NetworkNotFound, + /// On Windows, antivirus software is enabled by default. It can be + /// disabled, but Windows Update sometimes ignores the user's preference + /// and re-enables it. When enabled, antivirus software on Windows + /// intercepts file system operations and makes them significantly slower + /// in addition to possibly failing with this error code. + AntivirusInterference, + /// In WASI, this error may occur when the file descriptor does + /// not hold the required rights to open a new resource relative to it. + AccessDenied, + PermissionDenied, + SymLinkLoop, + ProcessFdQuotaExceeded, + SystemFdQuotaExceeded, + /// Either: + /// * One of the path components does not exist. + /// * Cwd was used, but cwd has been deleted. + /// * The path associated with the open directory handle has been deleted. + FileNotFound, + /// Insufficient kernel memory was available. + SystemResources, + /// A new path cannot be created because the device has no room for the new file. + NoSpaceLeft, + /// A component used as a directory in the path was not, in fact, a directory. + NotDir, + WouldBlock, + ReadOnlyFileSystem, +} || Io.Dir.PathNameError || Io.Cancelable || Io.UnexpectedError; + +/// Create an unnamed ephemeral file that can eventually be atomically +/// materialized into `sub_path`. +/// +/// The returned `File.Atomic` provides API to emulate the behavior in case it +/// is not directly supported by the underlying operating system. +/// +/// * On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). +/// * On WASI, `sub_path` should be encoded as valid UTF-8. +/// * On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. +pub fn createFileAtomic( + dir: Dir, + io: Io, + sub_path: []const u8, + options: CreateFileAtomicOptions, +) CreateFileAtomicError!File.Atomic { + return io.vtable.dirCreateFileAtomic(io.userdata, dir, sub_path, options); +} + +pub const SetPermissionsError = File.SetPermissionsError; +pub const Permissions = File.Permissions; + +/// Also known as "chmod". +/// +/// The process must have the correct privileges in order to do this +/// successfully, or must have the effective user ID matching the owner +/// of the directory. Additionally, the directory must have been opened +/// with `OpenOptions.iterate` set to `true`. +pub fn setPermissions(dir: Dir, io: Io, new_permissions: File.Permissions) SetPermissionsError!void { + return io.vtable.dirSetPermissions(io.userdata, dir, new_permissions); +} + +pub const SetFilePermissionsError = PathNameError || SetPermissionsError || error{ + ProcessFdQuotaExceeded, + SystemFdQuotaExceeded, + /// `SetFilePermissionsOptions.follow_symlinks` was set to false, which is + /// not allowed by the file system or operating system. + OperationUnsupported, +}; + +pub const SetFilePermissionsOptions = struct { + follow_symlinks: bool = true, +}; + +/// Also known as "fchmodat". +pub fn setFilePermissions( + dir: Dir, + io: Io, + sub_path: []const u8, + new_permissions: File.Permissions, + options: SetFilePermissionsOptions, +) SetFilePermissionsError!void { + return io.vtable.dirSetFilePermissions(io.userdata, dir, sub_path, new_permissions, options); +} + +pub const SetOwnerError = File.SetOwnerError; + +/// Also known as "chown". +/// +/// The process must have the correct privileges in order to do this +/// successfully. The group may be changed by the owner of the directory to +/// any group of which the owner is a member. Additionally, the directory +/// must have been opened with `OpenOptions.iterate` set to `true`. If the +/// owner or group is specified as `null`, the ID is not changed. +pub fn setOwner(dir: Dir, io: Io, owner: ?File.Uid, group: ?File.Gid) SetOwnerError!void { + return io.vtable.dirSetOwner(io.userdata, dir, owner, group); +} + +pub const SetFileOwnerError = PathNameError || SetOwnerError; + +pub const SetFileOwnerOptions = struct { + follow_symlinks: bool = true, +}; + +/// Also known as "fchownat". +pub fn setFileOwner( + dir: Dir, + io: Io, + sub_path: []const u8, + owner: ?File.Uid, + group: ?File.Gid, + options: SetFileOwnerOptions, +) SetOwnerError!void { + return io.vtable.dirSetFileOwner(io.userdata, dir, sub_path, owner, group, options); +} + +pub const SetTimestampsError = File.SetTimestampsError || PathNameError; + +pub const SetTimestampsOptions = struct { + follow_symlinks: bool = true, + access_timestamp: File.SetTimestamp = .unchanged, + modify_timestamp: File.SetTimestamp = .unchanged, +}; + +/// The granularity that ultimately is stored depends on the combination of +/// operating system and file system. When a value as provided that exceeds +/// this range, the value is clamped to the maximum. +pub fn setTimestamps( + dir: Dir, + io: Io, + sub_path: []const u8, + options: SetTimestampsOptions, +) SetTimestampsError!void { + return io.vtable.dirSetTimestamps(io.userdata, dir, sub_path, options); +} + +pub const SetTimestampsNowOptions = struct { + follow_symlinks: bool = true, +}; + +/// Sets the accessed and modification timestamps of the provided path to the +/// current wall clock time. +/// +/// The granularity that ultimately is stored depends on the combination of +/// operating system and file system. +pub fn setTimestampsNow( + dir: Dir, + io: Io, + sub_path: []const u8, + options: SetTimestampsNowOptions, +) SetTimestampsError!void { + return io.vtable.fileSetTimestamps(io.userdata, dir, sub_path, .{ + .follow_symlinks = options.follow_symlinks, + .access_timestamp = .now, + .modify_timestamp = .now, + }); } diff --git a/lib/std/Io/File.zig b/lib/std/Io/File.zig index 3f7316908577..27833d4d8a5b 100644 --- a/lib/std/Io/File.zig +++ b/lib/std/Io/File.zig @@ -7,12 +7,19 @@ const is_windows = native_os == .windows; const std = @import("../std.zig"); const Io = std.Io; const assert = std.debug.assert; +const Dir = std.Io.Dir; handle: Handle, +pub const Reader = @import("File/Reader.zig"); +pub const Writer = @import("File/Writer.zig"); +pub const Atomic = @import("File/Atomic.zig"); + pub const Handle = std.posix.fd_t; -pub const Mode = std.posix.mode_t; pub const INode = std.posix.ino_t; +pub const NLink = std.posix.nlink_t; +pub const Uid = std.posix.uid_t; +pub const Gid = std.posix.gid_t; pub const Kind = enum { block_device, @@ -41,12 +48,17 @@ pub const Stat = struct { /// The FileIndex on Windows is similar. It is a number for a file that /// is unique to each filesystem. inode: INode, + nlink: NLink, size: u64, - /// This is available on POSIX systems and is always 0 otherwise. - mode: Mode, + permissions: Permissions, kind: Kind, /// Last access time in nanoseconds, relative to UTC 1970-01-01. - atime: Io.Timestamp, + /// + /// Filesystems generally find this value problematic to keep updated since + /// it turns read-only file system accesses into file system mutations. + /// Some systems report stale values, and some systems explicitly refuse to + /// report this value. The latter case is handled by `null`. + atime: ?Io.Timestamp, /// Last modification time in nanoseconds, relative to UTC 1970-01-01. mtime: Io.Timestamp, /// Last status/metadata change time in nanoseconds, relative to UTC 1970-01-01. @@ -95,6 +107,26 @@ pub const Lock = enum { pub const OpenFlags = struct { mode: OpenMode = .read_only, + /// Determines the behavior when opening a path that refers to a directory. + /// + /// If set to true, directories may be opened, but `error.IsDir` is still + /// possible in certain scenarios, e.g. attempting to open a directory with + /// write permissions. + /// + /// If set to false, `error.IsDir` will always be returned when opening a directory. + /// + /// When set to false: + /// * On Windows, the behavior is implemented without any extra syscalls. + /// * On other operating systems, the behavior is implemented with an additional + /// `fstat` syscall. + allow_directory: bool = true, + /// Indicates intent for only some operations to be performed on this + /// opened file: + /// * `close` + /// * `stat` + /// On Linux and FreeBSD, this corresponds to `std.posix.O.PATH`. + path_only: bool = false, + /// Open the file with an advisory lock to coordinate with other processes /// accessing it at the same time. An exclusive lock will prevent other /// processes from acquiring a lock. A shared lock will prevent other @@ -141,7 +173,51 @@ pub const OpenFlags = struct { } }; -pub const CreateFlags = std.fs.File.CreateFlags; +pub const CreateFlags = struct { + /// Whether the file will be created with read access. + read: bool = false, + + /// If the file already exists, and is a regular file, and the access + /// mode allows writing, it will be truncated to length 0. + truncate: bool = true, + + /// Ensures that this open call creates the file, otherwise causes + /// `error.PathAlreadyExists` to be returned. + exclusive: bool = false, + + /// Open the file with an advisory lock to coordinate with other processes + /// accessing it at the same time. An exclusive lock will prevent other + /// processes from acquiring a lock. A shared lock will prevent other + /// processes from acquiring a exclusive lock, but does not prevent + /// other process from getting their own shared locks. + /// + /// The lock is advisory, except on Linux in very specific circumstances[1]. + /// This means that a process that does not respect the locking API can still get access + /// to the file, despite the lock. + /// + /// On these operating systems, the lock is acquired atomically with + /// opening the file: + /// * Darwin + /// * DragonFlyBSD + /// * FreeBSD + /// * Haiku + /// * NetBSD + /// * OpenBSD + /// On these operating systems, the lock is acquired via a separate syscall + /// after opening the file: + /// * Linux + /// * Windows + /// + /// [1]: https://www.kernel.org/doc/Documentation/filesystems/mandatory-locking.txt + lock: Lock = .none, + + /// Sets whether or not to wait until the file is locked to return. If set to true, + /// `error.WouldBlock` will be returned. Otherwise, the file will wait until the file + /// is available to proceed. + lock_nonblocking: bool = false, + + permissions: Permissions = .default_file, +}; pub const OpenError = error{ SharingViolation, @@ -149,7 +225,6 @@ pub const OpenError = error{ NoDevice, /// On Windows, `\\server` or `\\server\share` was not found. NetworkNotFound, - ProcessNotFound, /// On Windows, antivirus software is enabled by default. It can be /// disabled, but Windows Update sometimes ignores the user's preference /// and re-enables it. When enabled, antivirus software on Windows @@ -178,7 +253,9 @@ pub const OpenError = error{ /// The file is too large to be opened. This error is unreachable /// for 64-bit targets, as well as when opening directories. FileTooBig, - /// The path refers to directory but the `DIRECTORY` flag was not provided. + /// Either: + /// * The path refers to a directory and write permissions were requested. + /// * The path refers to a directory and `allow_directory` was set to false. IsDir, /// A new path cannot be created because the device has no room for the new file. /// This error is only reachable when the `CREAT` flag is provided. @@ -189,7 +266,7 @@ pub const OpenError = error{ /// The path already exists and the `CREAT` and `EXCL` flags were provided. PathAlreadyExists, DeviceBusy, - FileLocksNotSupported, + FileLocksUnsupported, /// One of these three things: /// * pathname refers to an executable image which is currently being /// executed and write access was requested. @@ -201,454 +278,470 @@ pub const OpenError = error{ FileBusy, /// Non-blocking was requested and the operation cannot return immediately. WouldBlock, -} || Io.Dir.PathNameError || Io.Cancelable || Io.UnexpectedError; +} || Dir.PathNameError || Io.Cancelable || Io.UnexpectedError; pub fn close(file: File, io: Io) void { - return io.vtable.fileClose(io.userdata, file); + return io.vtable.fileClose(io.userdata, (&file)[0..1]); } -pub const OpenSelfExeError = OpenError || std.fs.SelfExePathError || std.posix.FlockError; - -pub fn openSelfExe(io: Io, flags: OpenFlags) OpenSelfExeError!File { - return io.vtable.openSelfExe(io.userdata, flags); +pub fn closeMany(io: Io, files: []const File) void { + return io.vtable.fileClose(io.userdata, files); } -pub const ReadPositionalError = Reader.Error || error{Unseekable}; +pub const SyncError = error{ + InputOutput, + NoSpaceLeft, + DiskQuota, + AccessDenied, +} || Io.Cancelable || Io.UnexpectedError; -pub fn readPositional(file: File, io: Io, buffer: [][]u8, offset: u64) ReadPositionalError!usize { - return io.vtable.fileReadPositional(io.userdata, file, buffer, offset); +/// Blocks until all pending file contents and metadata modifications for the +/// file have been synchronized with the underlying filesystem. +/// +/// This does not ensure that metadata for the directory containing the file +/// has also reached disk. +pub fn sync(file: File, io: Io) SyncError!void { + return io.vtable.fileSync(io.userdata, file); } -pub const WriteStreamingError = error{} || Io.UnexpectedError || Io.Cancelable; - -pub fn writeStreaming(file: File, io: Io, buffer: [][]const u8) WriteStreamingError!usize { - return file.fileWriteStreaming(io, buffer); +/// Test whether the file refers to a terminal (similar to libc "isatty"). +/// +/// See also: +/// * `enableAnsiEscapeCodes` +/// * `supportsAnsiEscapeCodes`. +pub fn isTty(file: File, io: Io) Io.Cancelable!bool { + return io.vtable.fileIsTty(io.userdata, file); } -pub const WritePositionalError = WriteStreamingError || error{Unseekable}; +pub const EnableAnsiEscapeCodesError = error{ + NotTerminalDevice, +} || Io.Cancelable || Io.UnexpectedError; -pub fn writePositional(file: File, io: Io, buffer: [][]const u8, offset: u64) WritePositionalError!usize { - return io.vtable.fileWritePositional(io.userdata, file, buffer, offset); +pub fn enableAnsiEscapeCodes(file: File, io: Io) EnableAnsiEscapeCodesError!void { + return io.vtable.fileEnableAnsiEscapeCodes(io.userdata, file); } -pub fn openAbsolute(io: Io, absolute_path: []const u8, flags: OpenFlags) OpenError!File { - assert(std.fs.path.isAbsolute(absolute_path)); - return Io.Dir.cwd().openFile(io, absolute_path, flags); +/// Test whether ANSI escape codes will be treated as such without +/// attempting to enable support for ANSI escape codes. +pub fn supportsAnsiEscapeCodes(file: File, io: Io) Io.Cancelable!bool { + return io.vtable.fileSupportsAnsiEscapeCodes(io.userdata, file); } -/// Defaults to positional reading; falls back to streaming. +pub const SetLengthError = error{ + FileTooBig, + InputOutput, + FileBusy, + AccessDenied, + PermissionDenied, + NonResizable, +} || Io.Cancelable || Io.UnexpectedError; + +/// Truncates or expands the file, populating any new data with zeroes. /// -/// Positional is more threadsafe, since the global seek position is not -/// affected. -pub fn reader(file: File, io: Io, buffer: []u8) Reader { - return .init(file, io, buffer); +/// The file offset after this call is left unchanged. +pub fn setLength(file: File, io: Io, new_length: u64) SetLengthError!void { + return io.vtable.fileSetLength(io.userdata, file, new_length); } -/// Positional is more threadsafe, since the global seek position is not -/// affected, but when such syscalls are not available, preemptively -/// initializing in streaming mode skips a failed syscall. -pub fn readerStreaming(file: File, io: Io, buffer: []u8) Reader { - return .initStreaming(file, io, buffer); +pub const LengthError = StatError; + +/// Retrieve the ending byte index of the file. +/// +/// Sometimes cheaper than `stat` if only the length is needed. +pub fn length(file: File, io: Io) LengthError!u64 { + return io.vtable.fileLength(io.userdata, file); } -pub const SeekError = error{ - Unseekable, - /// The file descriptor does not hold the required rights to seek on it. +pub const SetPermissionsError = error{ AccessDenied, + PermissionDenied, + InputOutput, + SymLinkLoop, + FileNotFound, + SystemResources, + ReadOnlyFileSystem, } || Io.Cancelable || Io.UnexpectedError; -/// Memoizes key information about a file handle such as: -/// * The size from calling stat, or the error that occurred therein. -/// * The current seek position. -/// * The error that occurred when trying to seek. -/// * Whether reading should be done positionally or streaming. -/// * Whether reading should be done via fd-to-fd syscalls (e.g. `sendfile`) -/// versus plain variants (e.g. `read`). +/// Also known as "chmod". /// -/// Fulfills the `Io.Reader` interface. -pub const Reader = struct { - io: Io, - file: File, - err: ?Error = null, - mode: Reader.Mode = .positional, - /// Tracks the true seek position in the file. To obtain the logical - /// position, use `logicalPos`. - pos: u64 = 0, - size: ?u64 = null, - size_err: ?SizeError = null, - seek_err: ?Reader.SeekError = null, - interface: Io.Reader, - - pub const Error = error{ - InputOutput, - SystemResources, - IsDir, - BrokenPipe, - ConnectionResetByPeer, - Timeout, - /// In WASI, EBADF is mapped to this error because it is returned when - /// trying to read a directory file descriptor as if it were a file. - NotOpenForReading, - SocketUnconnected, - /// This error occurs when no global event loop is configured, - /// and reading from the file descriptor would block. - WouldBlock, - /// In WASI, this error occurs when the file descriptor does - /// not hold the required rights to read from it. - AccessDenied, - /// This error occurs in Linux if the process to be read from - /// no longer exists. - ProcessNotFound, - /// Unable to read file due to lock. - LockViolation, - } || Io.Cancelable || Io.UnexpectedError; - - pub const SizeError = std.os.windows.GetFileSizeError || StatError || error{ - /// Occurs if, for example, the file handle is a network socket and therefore does not have a size. - Streaming, - }; - - pub const SeekError = File.SeekError || error{ - /// Seeking fell back to reading, and reached the end before the requested seek position. - /// `pos` remains at the end of the file. - EndOfStream, - /// Seeking fell back to reading, which failed. - ReadFailed, - }; - - pub const Mode = enum { - streaming, - positional, - /// Avoid syscalls other than `read` and `readv`. - streaming_reading, - /// Avoid syscalls other than `pread` and `preadv`. - positional_reading, - /// Indicates reading cannot continue because of a seek failure. - failure, - - pub fn toStreaming(m: @This()) @This() { - return switch (m) { - .positional, .streaming => .streaming, - .positional_reading, .streaming_reading => .streaming_reading, - .failure => .failure, - }; - } - - pub fn toReading(m: @This()) @This() { - return switch (m) { - .positional, .positional_reading => .positional_reading, - .streaming, .streaming_reading => .streaming_reading, - .failure => .failure, - }; - } - }; - - pub fn initInterface(buffer: []u8) Io.Reader { - return .{ - .vtable = &.{ - .stream = Reader.stream, - .discard = Reader.discard, - .readVec = Reader.readVec, - }, - .buffer = buffer, - .seek = 0, - .end = 0, - }; - } +/// The process must have the correct privileges in order to do this +/// successfully, or must have the effective user ID matching the owner of the +/// file. +pub fn setPermissions(file: File, io: Io, new_permissions: Permissions) SetPermissionsError!void { + return io.vtable.fileSetPermissions(io.userdata, file, new_permissions); +} - pub fn init(file: File, io: Io, buffer: []u8) Reader { - return .{ - .io = io, - .file = file, - .interface = initInterface(buffer), - }; - } +pub const SetOwnerError = error{ + AccessDenied, + PermissionDenied, + InputOutput, + SymLinkLoop, + FileNotFound, + SystemResources, + ReadOnlyFileSystem, +} || Io.Cancelable || Io.UnexpectedError; - /// Takes a legacy `std.fs.File` to help with upgrading. - pub fn initAdapted(file: std.fs.File, io: Io, buffer: []u8) Reader { - return .init(.{ .handle = file.handle }, io, buffer); - } +/// Also known as "chown". +/// +/// The process must have the correct privileges in order to do this +/// successfully. The group may be changed by the owner of the file to any +/// group of which the owner is a member. If the owner or group is specified as +/// `null`, the ID is not changed. +pub fn setOwner(file: File, io: Io, owner: ?Uid, group: ?Gid) SetOwnerError!void { + return io.vtable.fileSetOwner(io.userdata, file, owner, group); +} - pub fn initSize(file: File, io: Io, buffer: []u8, size: ?u64) Reader { - return .{ - .io = io, - .file = file, - .interface = initInterface(buffer), - .size = size, - }; - } +/// Cross-platform representation of permissions on a file. +/// +/// On POSIX systems this corresponds to "mode" and on Windows this corresponds to "attributes". +pub const Permissions = std.Options.FilePermissions orelse if (is_windows) enum(std.os.windows.DWORD) { + default_file = 0, + _, + + pub const default_dir: @This() = .default_file; + pub const executable_file: @This() = .default_file; + pub const has_executable_bit = false; + + const windows = std.os.windows; - /// Positional is more threadsafe, since the global seek position is not - /// affected, but when such syscalls are not available, preemptively - /// initializing in streaming mode skips a failed syscall. - pub fn initStreaming(file: File, io: Io, buffer: []u8) Reader { - return .{ - .io = io, - .file = file, - .interface = Reader.initInterface(buffer), - .mode = .streaming, - .seek_err = error.Unseekable, - .size_err = error.Streaming, - }; + pub fn toAttributes(self: @This()) windows.FILE.ATTRIBUTE { + return @bitCast(@intFromEnum(self)); } - pub fn getSize(r: *Reader) SizeError!u64 { - return r.size orelse { - if (r.size_err) |err| return err; - if (stat(r.file, r.io)) |st| { - if (st.kind == .file) { - r.size = st.size; - return st.size; - } else { - r.mode = r.mode.toStreaming(); - r.size_err = error.Streaming; - return error.Streaming; - } - } else |err| { - r.size_err = err; - return err; - } - }; + pub fn readOnly(self: @This()) bool { + const attributes = toAttributes(self); + return attributes & windows.FILE_ATTRIBUTE_READONLY != 0; } - pub fn seekBy(r: *Reader, offset: i64) Reader.SeekError!void { - const io = r.io; - switch (r.mode) { - .positional, .positional_reading => { - setLogicalPos(r, @intCast(@as(i64, @intCast(logicalPos(r))) + offset)); - }, - .streaming, .streaming_reading => { - const seek_err = r.seek_err orelse e: { - if (io.vtable.fileSeekBy(io.userdata, r.file, offset)) |_| { - setLogicalPos(r, @intCast(@as(i64, @intCast(logicalPos(r))) + offset)); - return; - } else |err| { - r.seek_err = err; - break :e err; - } - }; - var remaining = std.math.cast(u64, offset) orelse return seek_err; - while (remaining > 0) { - remaining -= discard(&r.interface, .limited64(remaining)) catch |err| { - r.seek_err = err; - return err; - }; - } - r.interface.tossBuffered(); - }, - .failure => return r.seek_err.?, - } + pub fn setReadOnly(self: @This(), read_only: bool) @This() { + const attributes = toAttributes(self); + return @enumFromInt(if (read_only) + attributes | windows.FILE_ATTRIBUTE_READONLY + else + attributes & ~@as(windows.DWORD, windows.FILE_ATTRIBUTE_READONLY)); + } +} else if (std.posix.mode_t != u0) enum(std.posix.mode_t) { + /// This is the default mode given to POSIX operating systems for creating + /// files. `0o666` is "-rw-rw-rw-" which is counter-intuitive at first, + /// since most people would expect "-rw-r--r--", for example, when using + /// the `touch` command, which would correspond to `0o644`. However, POSIX + /// libc implementations use `0o666` inside `fopen` and then rely on the + /// process-scoped "umask" setting to adjust this number for file creation. + default_file = 0o666, + default_dir = 0o755, + executable_file = 0o777, + _, + + pub const has_executable_bit = native_os != .wasi; + + pub fn toMode(self: @This()) std.posix.mode_t { + return @intFromEnum(self); } - /// Repositions logical read offset relative to the beginning of the file. - pub fn seekTo(r: *Reader, offset: u64) Reader.SeekError!void { - const io = r.io; - switch (r.mode) { - .positional, .positional_reading => { - setLogicalPos(r, offset); - }, - .streaming, .streaming_reading => { - const logical_pos = logicalPos(r); - if (offset >= logical_pos) return Reader.seekBy(r, @intCast(offset - logical_pos)); - if (r.seek_err) |err| return err; - io.vtable.fileSeekTo(io.userdata, r.file, offset) catch |err| { - r.seek_err = err; - return err; - }; - setLogicalPos(r, offset); - }, - .failure => return r.seek_err.?, - } + pub fn fromMode(mode: std.posix.mode_t) @This() { + return @enumFromInt(mode); } - pub fn logicalPos(r: *const Reader) u64 { - return r.pos - r.interface.bufferedLen(); + /// Returns `true` if and only if no class has write permissions. + pub fn readOnly(self: @This()) bool { + const mode = toMode(self); + return mode & 0o222 == 0; } - fn setLogicalPos(r: *Reader, offset: u64) void { - const logical_pos = r.logicalPos(); - if (offset < logical_pos or offset >= r.pos) { - r.interface.tossBuffered(); - r.pos = offset; - } else r.interface.toss(@intCast(offset - logical_pos)); + /// Enables write permission for all classes. + pub fn setReadOnly(self: @This(), read_only: bool) @This() { + const mode = toMode(self); + const o222 = @as(std.posix.mode_t, 0o222); + return @enumFromInt(if (read_only) mode & ~o222 else mode | o222); } +} else enum(u0) { + default_file = 0, + pub const default_dir: @This() = .default_file; + pub const executable_file: @This() = .default_file; + pub const has_executable_bit = false; +}; - /// Number of slices to store on the stack, when trying to send as many byte - /// vectors through the underlying read calls as possible. - const max_buffers_len = 16; +pub const SetTimestampsError = error{ + /// times is NULL, or both nsec values are UTIME_NOW, and either: + /// * the effective user ID of the caller does not match the owner + /// of the file, the caller does not have write access to the + /// file, and the caller is not privileged (Linux: does not have + /// either the CAP_FOWNER or the CAP_DAC_OVERRIDE capability); + /// or, + /// * the file is marked immutable (see chattr(1)). + AccessDenied, + /// The caller attempted to change one or both timestamps to a value + /// other than the current time, or to change one of the timestamps + /// to the current time while leaving the other timestamp unchanged, + /// (i.e., times is not NULL, neither nsec field is UTIME_NOW, + /// and neither nsec field is UTIME_OMIT) and either: + /// * the caller's effective user ID does not match the owner of + /// file, and the caller is not privileged (Linux: does not have + /// the CAP_FOWNER capability); or, + /// * the file is marked append-only or immutable (see chattr(1)). + PermissionDenied, + ReadOnlyFileSystem, +} || Io.Cancelable || Io.UnexpectedError; - fn stream(io_reader: *Io.Reader, w: *Io.Writer, limit: Io.Limit) Io.Reader.StreamError!usize { - const r: *Reader = @alignCast(@fieldParentPtr("interface", io_reader)); - return streamMode(r, w, limit, r.mode); - } +pub const SetTimestampsOptions = struct { + access_timestamp: SetTimestamp = .unchanged, + modify_timestamp: SetTimestamp = .unchanged, +}; - pub fn streamMode(r: *Reader, w: *Io.Writer, limit: Io.Limit, mode: Reader.Mode) Io.Reader.StreamError!usize { - switch (mode) { - .positional, .streaming => return w.sendFile(r, limit) catch |write_err| switch (write_err) { - error.Unimplemented => { - r.mode = r.mode.toReading(); - return 0; - }, - else => |e| return e, - }, - .positional_reading => { - const dest = limit.slice(try w.writableSliceGreedy(1)); - var data: [1][]u8 = .{dest}; - const n = try readVecPositional(r, &data); - w.advance(n); - return n; - }, - .streaming_reading => { - const dest = limit.slice(try w.writableSliceGreedy(1)); - var data: [1][]u8 = .{dest}; - const n = try readVecStreaming(r, &data); - w.advance(n); - return n; - }, - .failure => return error.ReadFailed, - } +pub const SetTimestamp = union(enum) { + /// Leave the existing timestamp unmodified. + unchanged, + /// Set to current time using `Io.Clock.real`. + now, + /// Set to provided timestamp using `Io.Clock.real`. + new: Io.Timestamp, + + /// Convenience for interacting with `Stat`, in which `null` indicates `unchanged`. + pub fn init(optional: ?Io.Timestamp) SetTimestamp { + return if (optional) |t| .{ .new = t } else .unchanged; } +}; - fn readVec(io_reader: *Io.Reader, data: [][]u8) Io.Reader.Error!usize { - const r: *Reader = @alignCast(@fieldParentPtr("interface", io_reader)); - switch (r.mode) { - .positional, .positional_reading => return readVecPositional(r, data), - .streaming, .streaming_reading => return readVecStreaming(r, data), - .failure => return error.ReadFailed, - } - } +/// The granularity that ultimately is stored depends on the combination of +/// operating system and file system. When a value as provided that exceeds +/// this range, the value is clamped to the maximum. +pub fn setTimestamps(file: File, io: Io, options: SetTimestampsOptions) SetTimestampsError!void { + return io.vtable.fileSetTimestamps(io.userdata, file, options); +} - fn readVecPositional(r: *Reader, data: [][]u8) Io.Reader.Error!usize { - const io = r.io; - var iovecs_buffer: [max_buffers_len][]u8 = undefined; - const dest_n, const data_size = try r.interface.writableVector(&iovecs_buffer, data); - const dest = iovecs_buffer[0..dest_n]; - assert(dest[0].len > 0); - const n = io.vtable.fileReadPositional(io.userdata, r.file, dest, r.pos) catch |err| switch (err) { - error.Unseekable => { - r.mode = r.mode.toStreaming(); - const pos = r.pos; - if (pos != 0) { - r.pos = 0; - r.seekBy(@intCast(pos)) catch { - r.mode = .failure; - return error.ReadFailed; - }; - } - return 0; - }, - else => |e| { - r.err = e; - return error.ReadFailed; - }, - }; - if (n == 0) { - r.size = r.pos; - return error.EndOfStream; - } - r.pos += n; - if (n > data_size) { - r.interface.end += n - data_size; - return data_size; - } - return n; - } +/// Sets the accessed and modification timestamps of `file` to the current wall +/// clock time. +/// +/// The granularity that ultimately is stored depends on the combination of +/// operating system and file system. +pub fn setTimestampsNow(file: File, io: Io) SetTimestampsError!void { + return io.vtable.fileSetTimestamps(io.userdata, file, .{ + .access_timestamp = .now, + .modify_timestamp = .now, + }); +} - fn readVecStreaming(r: *Reader, data: [][]u8) Io.Reader.Error!usize { - const io = r.io; - var iovecs_buffer: [max_buffers_len][]u8 = undefined; - const dest_n, const data_size = try r.interface.writableVector(&iovecs_buffer, data); - const dest = iovecs_buffer[0..dest_n]; - assert(dest[0].len > 0); - const n = io.vtable.fileReadStreaming(io.userdata, r.file, dest) catch |err| { - r.err = err; - return error.ReadFailed; - }; - if (n == 0) { - r.size = r.pos; - return error.EndOfStream; - } - r.pos += n; - if (n > data_size) { - r.interface.end += n - data_size; - return data_size; - } - return n; - } +/// Returns 0 on stream end or if `buffer` has no space available for data. +/// +/// See also: +/// * `reader` +pub fn readStreaming(file: File, io: Io, buffer: []const []u8) Reader.Error!usize { + return io.vtable.fileReadStreaming(io.userdata, file, buffer); +} - fn discard(io_reader: *Io.Reader, limit: Io.Limit) Io.Reader.Error!usize { - const r: *Reader = @alignCast(@fieldParentPtr("interface", io_reader)); - const io = r.io; - const file = r.file; - switch (r.mode) { - .positional, .positional_reading => { - const size = r.getSize() catch { - r.mode = r.mode.toStreaming(); - return 0; - }; - const logical_pos = logicalPos(r); - const delta = @min(@intFromEnum(limit), size - logical_pos); - setLogicalPos(r, logical_pos + delta); - return delta; - }, - .streaming, .streaming_reading => { - // Unfortunately we can't seek forward without knowing the - // size because the seek syscalls provided to us will not - // return the true end position if a seek would exceed the - // end. - fallback: { - if (r.size_err == null and r.seek_err == null) break :fallback; - - const buffered_len = r.interface.bufferedLen(); - var remaining = @intFromEnum(limit); - if (remaining <= buffered_len) { - r.interface.seek += remaining; - return remaining; - } - remaining -= buffered_len; - r.interface.seek = 0; - r.interface.end = 0; - - var trash_buffer: [128]u8 = undefined; - var data: [1][]u8 = .{trash_buffer[0..@min(trash_buffer.len, remaining)]}; - var iovecs_buffer: [max_buffers_len][]u8 = undefined; - const dest_n, const data_size = try r.interface.writableVector(&iovecs_buffer, &data); - const dest = iovecs_buffer[0..dest_n]; - assert(dest[0].len > 0); - const n = io.vtable.fileReadStreaming(io.userdata, file, dest) catch |err| { - r.err = err; - return error.ReadFailed; - }; - if (n == 0) { - r.size = r.pos; - return error.EndOfStream; - } - r.pos += n; - if (n > data_size) { - r.interface.end += n - data_size; - remaining -= data_size; - } else { - remaining -= n; - } - return @intFromEnum(limit) - remaining; - } - const size = r.getSize() catch return 0; - const n = @min(size - r.pos, std.math.maxInt(i64), @intFromEnum(limit)); - io.vtable.fileSeekBy(io.userdata, file, n) catch |err| { - r.seek_err = err; - return 0; - }; - r.pos += n; - return n; - }, - .failure => return error.ReadFailed, - } +pub const ReadPositionalError = Reader.Error || error{Unseekable}; + +/// Returns 0 on stream end or if `buffer` has no space available for data. +/// +/// See also: +/// * `reader` +pub fn readPositional(file: File, io: Io, buffer: []const []u8, offset: u64) ReadPositionalError!usize { + return io.vtable.fileReadPositional(io.userdata, file, buffer, offset); +} + +pub const WritePositionalError = Writer.Error || error{Unseekable}; + +/// See also: +/// * `writer` +pub fn writePositional(file: File, io: Io, buffer: []const []const u8, offset: u64) WritePositionalError!usize { + return io.vtable.fileWritePositional(io.userdata, file, &.{}, buffer, 1, offset); +} + +/// Equivalent to creating a positional writer, writing `bytes`, and then flushing. +pub fn writePositionalAll(file: File, io: Io, bytes: []const u8, offset: u64) WritePositionalError!void { + var index: usize = 0; + while (index < bytes.len) + index += try io.vtable.fileWritePositional(io.userdata, file, &.{}, &.{bytes[index..]}, 1, offset + index); +} + +pub const SeekError = error{ + Unseekable, + /// The file descriptor does not hold the required rights to seek on it. + AccessDenied, +} || Io.Cancelable || Io.UnexpectedError; + +pub const WriteFilePositionalError = Writer.WriteFileError || error{Unseekable}; + +/// Defaults to positional reading; falls back to streaming. +/// +/// Positional is more threadsafe, since the global seek position is not +/// affected. +/// +/// See also: +/// * `readerStreaming` +pub fn reader(file: File, io: Io, buffer: []u8) Reader { + return .init(file, io, buffer); +} + +/// Equivalent to creating a positional reader and reading multiple times to fill `buffer`. +/// +/// Returns number of bytes read into `buffer`. If less than `buffer.len`, end of file occurred. +/// +/// See also: +/// * `reader` +pub fn readPositionalAll(file: File, io: Io, buffer: []u8, offset: u64) ReadPositionalError!usize { + var index: usize = 0; + while (index != buffer.len) { + const amt = try file.readPositional(io, &.{buffer[index..]}, offset + index); + if (amt == 0) break; + index += amt; } + return index; +} + +/// Positional is more threadsafe, since the global seek position is not +/// affected, but when such syscalls are not available, preemptively +/// initializing in streaming mode skips a failed syscall. +/// +/// See also: +/// * `reader` +pub fn readerStreaming(file: File, io: Io, buffer: []u8) Reader { + return .initStreaming(file, io, buffer); +} - /// Returns whether the stream is at the logical end. - pub fn atEnd(r: *Reader) bool { - // Even if stat fails, size is set when end is encountered. - const size = r.size orelse return false; - return size - logicalPos(r) == 0; +/// Defaults to positional reading; falls back to streaming. +/// +/// Positional is more threadsafe, since the global seek position is not +/// affected. +pub fn writer(file: File, io: Io, buffer: []u8) Writer { + return .init(file, io, buffer); +} + +/// Positional is more threadsafe, since the global seek position is not +/// affected, but when such syscalls are not available, preemptively +/// initializing in streaming mode will skip a failed syscall. +pub fn writerStreaming(file: File, io: Io, buffer: []u8) Writer { + return .initStreaming(file, io, buffer); +} + +/// Equivalent to creating a streaming writer, writing `bytes`, and then flushing. +pub fn writeStreamingAll(file: File, io: Io, bytes: []const u8) Writer.Error!void { + var index: usize = 0; + while (index < bytes.len) { + index += try io.vtable.fileWriteStreaming(io.userdata, file, &.{}, &.{bytes[index..]}, 1); } +} + +pub const LockError = error{ + SystemResources, + FileLocksUnsupported, +} || Io.Cancelable || Io.UnexpectedError; + +/// Blocks when an incompatible lock is held by another process. A process may +/// hold only one type of lock (shared or exclusive) on a file. When a process +/// terminates in any way, the lock is released. +/// +/// Assumes the file is unlocked. +pub fn lock(file: File, io: Io, l: Lock) LockError!void { + return io.vtable.fileLock(io.userdata, file, l); +} + +/// Assumes the file is locked. +pub fn unlock(file: File, io: Io) void { + return io.vtable.fileUnlock(io.userdata, file); +} + +/// Attempts to obtain a lock, returning `true` if the lock is obtained, and +/// `false` if there was an existing incompatible lock held. A process may hold +/// only one type of lock (shared or exclusive) on a file. When a process +/// terminates in any way, the lock is released. +/// +/// Assumes the file is unlocked. +pub fn tryLock(file: File, io: Io, l: Lock) LockError!bool { + return io.vtable.fileTryLock(io.userdata, file, l); +} + +pub const DowngradeLockError = Io.Cancelable || Io.UnexpectedError; + +/// Assumes the file is already locked in exclusive mode. +/// Atomically modifies the lock to be in shared mode, without releasing it. +pub fn downgradeLock(file: File, io: Io) LockError!void { + return io.vtable.fileDowngradeLock(io.userdata, file); +} + +pub const RealPathError = error{ + /// This operating system, file system, or `Io` implementation does not + /// support realpath operations. + OperationUnsupported, + /// The full file system path could not fit into the provided buffer, or + /// due to its length could not be obtained via realpath functions no + /// matter the buffer size provided. + NameTooLong, + FileNotFound, + AccessDenied, + PermissionDenied, + NotDir, + SymLinkLoop, + InputOutput, + FileTooBig, + IsDir, + ProcessFdQuotaExceeded, + SystemFdQuotaExceeded, + NoDevice, + SystemResources, + NoSpaceLeft, + FileSystem, + DeviceBusy, + SharingViolation, + PipeBusy, + /// On Windows, `\\server` or `\\server\share` was not found. + NetworkNotFound, + PathAlreadyExists, + /// On Windows, antivirus software is enabled by default. It can be + /// disabled, but Windows Update sometimes ignores the user's preference + /// and re-enables it. When enabled, antivirus software on Windows + /// intercepts file system operations and makes them significantly slower + /// in addition to possibly failing with this error code. + AntivirusInterference, + /// On Windows, the volume does not contain a recognized file system. File + /// system drivers might not be loaded, or the volume may be corrupt. + UnrecognizedVolume, +} || Io.Cancelable || Io.UnexpectedError; + +/// Obtains the canonicalized absolute path name corresponding to an open file +/// handle. +/// +/// This function has limited platform support, and using it can lead to +/// unnecessary failures and race conditions. It is generally advisable to +/// avoid this function entirely. +pub fn realPath(file: File, io: Io, out_buffer: []u8) RealPathError!usize { + return io.vtable.fileRealPath(io.userdata, file, out_buffer); +} + +pub const HardLinkOptions = struct { + follow_symlinks: bool = false, }; + +pub const HardLinkError = error{ + AccessDenied, + PermissionDenied, + DiskQuota, + PathAlreadyExists, + HardwareFailure, + /// Either the OS or the filesystem does not support hard links. + OperationUnsupported, + SymLinkLoop, + LinkQuotaExceeded, + FileNotFound, + SystemResources, + NoSpaceLeft, + ReadOnlyFileSystem, + CrossDevice, + NotDir, +} || Io.Cancelable || Dir.PathNameError || Io.UnexpectedError; + +pub fn hardLink( + file: File, + io: Io, + new_dir: Dir, + new_sub_path: []const u8, + options: HardLinkOptions, +) HardLinkError!void { + return io.vtable.fileHardLink(io.userdata, file, new_dir, new_sub_path, options); +} + +test { + _ = Reader; + _ = Writer; + _ = Atomic; +} diff --git a/lib/std/Io/File/Atomic.zig b/lib/std/Io/File/Atomic.zig new file mode 100644 index 000000000000..1efacf94061f --- /dev/null +++ b/lib/std/Io/File/Atomic.zig @@ -0,0 +1,86 @@ +const Atomic = @This(); + +const std = @import("../../std.zig"); +const Io = std.Io; +const File = std.Io.File; +const Dir = std.Io.Dir; +const assert = std.debug.assert; + +file: File, +file_basename_hex: u64, +file_open: bool, +file_exists: bool, + +dir: Dir, +close_dir_on_deinit: bool, + +dest_sub_path: []const u8, + +pub const InitError = File.OpenError; + +/// To release all resources, always call `deinit`, even after a successful +/// `finish`. +pub fn deinit(af: *Atomic, io: Io) void { + if (af.file_open) { + af.file.close(io); + af.file_open = false; + } + if (af.file_exists) { + const tmp_sub_path = std.fmt.hex(af.file_basename_hex); + af.dir.deleteFile(io, &tmp_sub_path) catch {}; + af.file_exists = false; + } + if (af.close_dir_on_deinit) { + af.dir.close(io); + af.close_dir_on_deinit = false; + } + af.* = undefined; +} + +pub const LinkError = File.HardLinkError || Dir.RenamePreserveError; + +/// Atomically materializes the file into place, failing with +/// `error.PathAlreadyExists` if something already exists there. +/// +/// If this operation could not be done with an unnamed temporary file, the +/// named temporary file will be deleted in a following operation, which may +/// independently fail. The result of that operation is stored in `delete_err`. +pub fn link(af: *Atomic, io: Io) LinkError!void { + if (af.file_exists) { + if (af.file_open) { + af.file.close(io); + af.file_open = false; + } + const tmp_sub_path = std.fmt.hex(af.file_basename_hex); + try af.dir.renamePreserve(&tmp_sub_path, af.dir, af.dest_sub_path, io); + af.file_exists = false; + } else { + assert(af.file_open); + try af.file.hardLink(io, af.dir, af.dest_sub_path, .{}); + af.file.close(io); + af.file_open = false; + } +} + +pub const ReplaceError = Dir.RenameError; + +/// Atomically materializes the file into place, replacing any file that +/// already exists there. +/// +/// Calling this function requires setting `CreateFileAtomicOptions.replace` to +/// `true`. +/// +/// On Windows, this function introduces a period of time where some file +/// system operations on the destination file will result in +/// `error.AccessDenied`, including rename operations (such as the one used in +/// this function). +pub fn replace(af: *Atomic, io: Io) ReplaceError!void { + assert(af.file_exists); // Wrong value for `CreateFileAtomicOptions.replace`. + if (af.file_open) { + af.file.close(io); + af.file_open = false; + } + const tmp_sub_path = std.fmt.hex(af.file_basename_hex); + try af.dir.rename(&tmp_sub_path, af.dir, af.dest_sub_path, io); + af.file_exists = false; +} diff --git a/lib/std/Io/File/Reader.zig b/lib/std/Io/File/Reader.zig new file mode 100644 index 000000000000..0c573c9ae142 --- /dev/null +++ b/lib/std/Io/File/Reader.zig @@ -0,0 +1,394 @@ +//! Memoizes key information about a file handle such as: +//! * The size from calling stat, or the error that occurred therein. +//! * The current seek position. +//! * The error that occurred when trying to seek. +//! * Whether reading should be done positionally or streaming. +//! * Whether reading should be done via fd-to-fd syscalls (e.g. `sendfile`) +//! versus plain variants (e.g. `read`). +//! +//! Fulfills the `Io.Reader` interface. +const Reader = @This(); + +const std = @import("../../std.zig"); +const Io = std.Io; +const File = std.Io.File; +const assert = std.debug.assert; + +io: Io, +file: File, +err: ?Error = null, +mode: Mode = .positional, +/// Tracks the true seek position in the file. To obtain the logical position, +/// use `logicalPos`. +pos: u64 = 0, +size: ?u64 = null, +size_err: ?SizeError = null, +seek_err: ?SeekError = null, +interface: Io.Reader, + +pub const Error = error{ + InputOutput, + SystemResources, + IsDir, + BrokenPipe, + ConnectionResetByPeer, + Timeout, + /// In WASI, EBADF is mapped to this error because it is returned when + /// trying to read a directory file descriptor as if it were a file. + NotOpenForReading, + SocketUnconnected, + /// Non-blocking has been enabled, and reading from the file descriptor + /// would block. + WouldBlock, + /// In WASI, this error occurs when the file descriptor does + /// not hold the required rights to read from it. + AccessDenied, + /// Unable to read file due to lock. Depending on the `Io` implementation, + /// reading from a locked file may return this error, or may ignore the + /// lock. + LockViolation, +} || Io.Cancelable || Io.UnexpectedError; + +pub const SizeError = std.os.windows.GetFileSizeError || File.StatError || error{ + /// Occurs if, for example, the file handle is a network socket and therefore does not have a size. + Streaming, +}; + +pub const SeekError = File.SeekError || error{ + /// Seeking fell back to reading, and reached the end before the requested seek position. + /// `pos` remains at the end of the file. + EndOfStream, + /// Seeking fell back to reading, which failed. + ReadFailed, +}; + +pub const Mode = enum { + streaming, + positional, + /// Avoid syscalls other than `read` and `readv`. + streaming_simple, + /// Avoid syscalls other than `pread` and `preadv`. + positional_simple, + /// Indicates reading cannot continue because of a seek failure. + failure, + + pub fn toStreaming(m: @This()) @This() { + return switch (m) { + .positional, .streaming => .streaming, + .positional_simple, .streaming_simple => .streaming_simple, + .failure => .failure, + }; + } + + pub fn toSimple(m: @This()) @This() { + return switch (m) { + .positional, .positional_simple => .positional_simple, + .streaming, .streaming_simple => .streaming_simple, + .failure => .failure, + }; + } +}; + +pub fn initInterface(buffer: []u8) Io.Reader { + return .{ + .vtable = &.{ + .stream = stream, + .discard = discard, + .readVec = readVec, + }, + .buffer = buffer, + .seek = 0, + .end = 0, + }; +} + +pub fn init(file: File, io: Io, buffer: []u8) Reader { + return .{ + .io = io, + .file = file, + .interface = initInterface(buffer), + }; +} + +pub fn initSize(file: File, io: Io, buffer: []u8, size: ?u64) Reader { + return .{ + .io = io, + .file = file, + .interface = initInterface(buffer), + .size = size, + }; +} + +/// Positional is more threadsafe, since the global seek position is not +/// affected, but when such syscalls are not available, preemptively +/// initializing in streaming mode skips a failed syscall. +pub fn initStreaming(file: File, io: Io, buffer: []u8) Reader { + return .{ + .io = io, + .file = file, + .interface = Reader.initInterface(buffer), + .mode = .streaming, + .seek_err = error.Unseekable, + .size_err = error.Streaming, + }; +} + +pub fn getSize(r: *Reader) SizeError!u64 { + return r.size orelse { + if (r.size_err) |err| return err; + if (r.file.stat(r.io)) |st| { + if (st.kind == .file) { + r.size = st.size; + return st.size; + } else { + r.mode = r.mode.toStreaming(); + r.size_err = error.Streaming; + return error.Streaming; + } + } else |err| { + r.size_err = err; + return err; + } + }; +} + +pub fn seekBy(r: *Reader, offset: i64) SeekError!void { + const io = r.io; + switch (r.mode) { + .positional, .positional_simple => { + setLogicalPos(r, @intCast(@as(i64, @intCast(logicalPos(r))) + offset)); + }, + .streaming, .streaming_simple => { + const seek_err = r.seek_err orelse e: { + if (io.vtable.fileSeekBy(io.userdata, r.file, offset)) |_| { + setLogicalPos(r, @intCast(@as(i64, @intCast(logicalPos(r))) + offset)); + return; + } else |err| { + r.seek_err = err; + break :e err; + } + }; + var remaining = std.math.cast(u64, offset) orelse return seek_err; + while (remaining > 0) { + remaining -= discard(&r.interface, .limited64(remaining)) catch |err| { + r.seek_err = err; + return err; + }; + } + r.interface.tossBuffered(); + }, + .failure => return r.seek_err.?, + } +} + +/// Repositions logical read offset relative to the beginning of the file. +pub fn seekTo(r: *Reader, offset: u64) SeekError!void { + const io = r.io; + switch (r.mode) { + .positional, .positional_simple => { + setLogicalPos(r, offset); + }, + .streaming, .streaming_simple => { + const logical_pos = logicalPos(r); + if (offset >= logical_pos) return seekBy(r, @intCast(offset - logical_pos)); + if (r.seek_err) |err| return err; + io.vtable.fileSeekTo(io.userdata, r.file, offset) catch |err| { + r.seek_err = err; + return err; + }; + setLogicalPos(r, offset); + }, + .failure => return r.seek_err.?, + } +} + +pub fn logicalPos(r: *const Reader) u64 { + return r.pos - r.interface.bufferedLen(); +} + +fn setLogicalPos(r: *Reader, offset: u64) void { + const logical_pos = r.logicalPos(); + if (offset < logical_pos or offset >= r.pos) { + r.interface.tossBuffered(); + r.pos = offset; + } else r.interface.toss(@intCast(offset - logical_pos)); +} + +/// Number of slices to store on the stack, when trying to send as many byte +/// vectors through the underlying read calls as possible. +const max_buffers_len = 16; + +fn stream(io_reader: *Io.Reader, w: *Io.Writer, limit: Io.Limit) Io.Reader.StreamError!usize { + const r: *Reader = @alignCast(@fieldParentPtr("interface", io_reader)); + return streamMode(r, w, limit, r.mode); +} + +pub fn streamMode(r: *Reader, w: *Io.Writer, limit: Io.Limit, mode: Mode) Io.Reader.StreamError!usize { + switch (mode) { + .positional, .streaming => return w.sendFile(r, limit) catch |write_err| switch (write_err) { + error.Unimplemented => { + r.mode = r.mode.toSimple(); + return 0; + }, + else => |e| return e, + }, + .positional_simple => { + const dest = limit.slice(try w.writableSliceGreedy(1)); + var data: [1][]u8 = .{dest}; + const n = try readVecPositional(r, &data); + w.advance(n); + return n; + }, + .streaming_simple => { + const dest = limit.slice(try w.writableSliceGreedy(1)); + var data: [1][]u8 = .{dest}; + const n = try readVecStreaming(r, &data); + w.advance(n); + return n; + }, + .failure => return error.ReadFailed, + } +} + +fn readVec(io_reader: *Io.Reader, data: [][]u8) Io.Reader.Error!usize { + const r: *Reader = @alignCast(@fieldParentPtr("interface", io_reader)); + switch (r.mode) { + .positional, .positional_simple => return readVecPositional(r, data), + .streaming, .streaming_simple => return readVecStreaming(r, data), + .failure => return error.ReadFailed, + } +} + +fn readVecPositional(r: *Reader, data: [][]u8) Io.Reader.Error!usize { + const io = r.io; + var iovecs_buffer: [max_buffers_len][]u8 = undefined; + const dest_n, const data_size = try r.interface.writableVector(&iovecs_buffer, data); + const dest = iovecs_buffer[0..dest_n]; + assert(dest[0].len > 0); + const n = io.vtable.fileReadPositional(io.userdata, r.file, dest, r.pos) catch |err| switch (err) { + error.Unseekable => { + r.mode = r.mode.toStreaming(); + const pos = r.pos; + if (pos != 0) { + r.pos = 0; + r.seekBy(@intCast(pos)) catch { + r.mode = .failure; + return error.ReadFailed; + }; + } + return 0; + }, + else => |e| { + r.err = e; + return error.ReadFailed; + }, + }; + if (n == 0) { + r.size = r.pos; + return error.EndOfStream; + } + r.pos += n; + if (n > data_size) { + r.interface.end += n - data_size; + return data_size; + } + return n; +} + +fn readVecStreaming(r: *Reader, data: [][]u8) Io.Reader.Error!usize { + const io = r.io; + var iovecs_buffer: [max_buffers_len][]u8 = undefined; + const dest_n, const data_size = try r.interface.writableVector(&iovecs_buffer, data); + const dest = iovecs_buffer[0..dest_n]; + assert(dest[0].len > 0); + const n = io.vtable.fileReadStreaming(io.userdata, r.file, dest) catch |err| { + r.err = err; + return error.ReadFailed; + }; + if (n == 0) { + r.size = r.pos; + return error.EndOfStream; + } + r.pos += n; + if (n > data_size) { + r.interface.end += n - data_size; + return data_size; + } + return n; +} + +fn discard(io_reader: *Io.Reader, limit: Io.Limit) Io.Reader.Error!usize { + const r: *Reader = @alignCast(@fieldParentPtr("interface", io_reader)); + const io = r.io; + const file = r.file; + switch (r.mode) { + .positional, .positional_simple => { + const size = r.getSize() catch { + r.mode = r.mode.toStreaming(); + return 0; + }; + const logical_pos = logicalPos(r); + const delta = @min(@intFromEnum(limit), size - logical_pos); + setLogicalPos(r, logical_pos + delta); + return delta; + }, + .streaming, .streaming_simple => { + // Unfortunately we can't seek forward without knowing the + // size because the seek syscalls provided to us will not + // return the true end position if a seek would exceed the + // end. + fallback: { + if (r.size_err == null and r.seek_err == null) break :fallback; + + const buffered_len = r.interface.bufferedLen(); + var remaining = @intFromEnum(limit); + if (remaining <= buffered_len) { + r.interface.seek += remaining; + return remaining; + } + remaining -= buffered_len; + r.interface.seek = 0; + r.interface.end = 0; + + var trash_buffer: [128]u8 = undefined; + var data: [1][]u8 = .{trash_buffer[0..@min(trash_buffer.len, remaining)]}; + var iovecs_buffer: [max_buffers_len][]u8 = undefined; + const dest_n, const data_size = try r.interface.writableVector(&iovecs_buffer, &data); + const dest = iovecs_buffer[0..dest_n]; + assert(dest[0].len > 0); + const n = io.vtable.fileReadStreaming(io.userdata, file, dest) catch |err| { + r.err = err; + return error.ReadFailed; + }; + if (n == 0) { + r.size = r.pos; + return error.EndOfStream; + } + r.pos += n; + if (n > data_size) { + r.interface.end += n - data_size; + remaining -= data_size; + } else { + remaining -= n; + } + return @intFromEnum(limit) - remaining; + } + const size = r.getSize() catch return 0; + const n = @min(size - r.pos, std.math.maxInt(i64), @intFromEnum(limit)); + io.vtable.fileSeekBy(io.userdata, file, n) catch |err| { + r.seek_err = err; + return 0; + }; + r.pos += n; + return n; + }, + .failure => return error.ReadFailed, + } +} + +/// Returns whether the stream is at the logical end. +pub fn atEnd(r: *Reader) bool { + // Even if stat fails, size is set when end is encountered. + const size = r.size orelse return false; + return size - logicalPos(r) == 0; +} diff --git a/lib/std/Io/File/Writer.zig b/lib/std/Io/File/Writer.zig new file mode 100644 index 000000000000..52bbe83513f2 --- /dev/null +++ b/lib/std/Io/File/Writer.zig @@ -0,0 +1,282 @@ +const Writer = @This(); +const builtin = @import("builtin"); +const is_windows = builtin.os.tag == .windows; + +const std = @import("../../std.zig"); +const Io = std.Io; +const File = std.Io.File; +const assert = std.debug.assert; + +io: Io, +file: File, +err: ?Error = null, +mode: Mode = .positional, +/// Tracks the true seek position in the file. To obtain the logical position, +/// use `logicalPos`. +pos: u64 = 0, +write_file_err: ?WriteFileError = null, +seek_err: ?SeekError = null, +interface: Io.Writer, + +pub const Mode = File.Reader.Mode; + +pub const Error = error{ + DiskQuota, + FileTooBig, + InputOutput, + NoSpaceLeft, + DeviceBusy, + /// File descriptor does not hold the required rights to write to it. + AccessDenied, + PermissionDenied, + /// File is an unconnected socket, or closed its read end. + BrokenPipe, + /// Insufficient kernel memory to read from in_fd. + SystemResources, + NotOpenForWriting, + /// The process cannot access the file because another process has locked + /// a portion of the file. Windows-only. + LockViolation, + /// Non-blocking has been enabled and this operation would block. + WouldBlock, + /// This error occurs when a device gets disconnected before or mid-flush + /// while it's being written to - errno(6): No such device or address. + NoDevice, + FileBusy, +} || Io.Cancelable || Io.UnexpectedError; + +pub const WriteFileError = Error || error{ + /// Descriptor is not valid or locked, or an mmap(2)-like operation is not available for in_fd. + Unimplemented, + /// Can happen on FreeBSD when using copy_file_range. + CorruptedData, + EndOfStream, + ReadFailed, +}; + +pub const SeekError = Io.File.SeekError; + +pub fn init(file: File, io: Io, buffer: []u8) Writer { + return .{ + .io = io, + .file = file, + .interface = initInterface(buffer), + .mode = .positional, + }; +} + +/// Positional is more threadsafe, since the global seek position is not +/// affected, but when such syscalls are not available, preemptively +/// initializing in streaming mode will skip a failed syscall. +pub fn initStreaming(file: File, io: Io, buffer: []u8) Writer { + return .{ + .io = io, + .file = file, + .interface = initInterface(buffer), + .mode = .streaming, + }; +} + +/// Detects if `file` is terminal and sets the mode accordingly. +pub fn initDetect(file: File, io: Io, buffer: []u8) Io.Cancelable!Writer { + return .{ + .io = io, + .file = file, + .interface = initInterface(buffer), + .mode = try .detect(io, file, true, .positional), + }; +} + +pub fn initInterface(buffer: []u8) Io.Writer { + return .{ + .vtable = &.{ + .drain = drain, + .sendFile = sendFile, + }, + .buffer = buffer, + }; +} + +pub fn moveToReader(w: *Writer) File.Reader { + defer w.* = undefined; + return .{ + .io = w.io, + .file = .{ .handle = w.file.handle }, + .mode = w.mode, + .pos = w.pos, + .interface = File.Reader.initInterface(w.interface.buffer), + .seek_err = w.seek_err, + }; +} + +pub fn drain(io_w: *Io.Writer, data: []const []const u8, splat: usize) Io.Writer.Error!usize { + const w: *Writer = @alignCast(@fieldParentPtr("interface", io_w)); + switch (w.mode) { + .positional, .positional_simple => return drainPositional(w, data, splat), + .streaming, .streaming_simple => return drainStreaming(w, data, splat), + .failure => return error.WriteFailed, + } +} + +fn drainPositional(w: *Writer, data: []const []const u8, splat: usize) Io.Writer.Error!usize { + const io = w.io; + const header = w.interface.buffered(); + const n = io.vtable.fileWritePositional(io.userdata, w.file, header, data, splat, w.pos) catch |err| switch (err) { + error.Unseekable => { + w.mode = w.mode.toStreaming(); + const pos = w.pos; + if (pos != 0) { + w.pos = 0; + w.seekTo(@intCast(pos)) catch { + w.mode = .failure; + return error.WriteFailed; + }; + } + return 0; + }, + else => |e| { + w.err = e; + return error.WriteFailed; + }, + }; + w.pos += n; + return w.interface.consume(n); +} + +fn drainStreaming(w: *Writer, data: []const []const u8, splat: usize) Io.Writer.Error!usize { + const io = w.io; + const header = w.interface.buffered(); + const n = io.vtable.fileWriteStreaming(io.userdata, w.file, header, data, splat) catch |err| { + w.err = err; + return error.WriteFailed; + }; + w.pos += n; + return w.interface.consume(n); +} + +pub fn sendFile(io_w: *Io.Writer, file_reader: *Io.File.Reader, limit: Io.Limit) Io.Writer.FileError!usize { + const w: *Writer = @alignCast(@fieldParentPtr("interface", io_w)); + switch (w.mode) { + .positional => return sendFilePositional(w, file_reader, limit), + .positional_simple => return error.Unimplemented, + .streaming => return sendFileStreaming(w, file_reader, limit), + .streaming_simple => return error.Unimplemented, + .failure => return error.WriteFailed, + } +} + +fn sendFilePositional(w: *Writer, file_reader: *Io.File.Reader, limit: Io.Limit) Io.Writer.FileError!usize { + const io = w.io; + const header = w.interface.buffered(); + const n = io.vtable.fileWriteFilePositional(io.userdata, w.file, header, file_reader, limit, w.pos) catch |err| switch (err) { + error.Unseekable => { + w.mode = w.mode.toStreaming(); + const pos = w.pos; + if (pos != 0) { + w.pos = 0; + w.seekTo(@intCast(pos)) catch { + w.mode = .failure; + return error.WriteFailed; + }; + } + return 0; + }, + error.Canceled => { + w.err = error.Canceled; + return error.WriteFailed; + }, + error.EndOfStream => return error.EndOfStream, + error.Unimplemented => return error.Unimplemented, + error.ReadFailed => return error.ReadFailed, + else => |e| { + w.write_file_err = e; + return error.WriteFailed; + }, + }; + w.pos += n; + return w.interface.consume(n); +} + +fn sendFileStreaming(w: *Writer, file_reader: *Io.File.Reader, limit: Io.Limit) Io.Writer.FileError!usize { + const io = w.io; + const header = w.interface.buffered(); + const n = io.vtable.fileWriteFileStreaming(io.userdata, w.file, header, file_reader, limit) catch |err| switch (err) { + error.Canceled => { + w.err = error.Canceled; + return error.WriteFailed; + }, + error.EndOfStream => return error.EndOfStream, + error.Unimplemented => return error.Unimplemented, + error.ReadFailed => return error.ReadFailed, + else => |e| { + w.write_file_err = e; + return error.WriteFailed; + }, + }; + w.pos += n; + return w.interface.consume(n); +} + +pub fn seekTo(w: *Writer, offset: u64) (SeekError || Io.Writer.Error)!void { + try w.interface.flush(); + try seekToUnbuffered(w, offset); +} + +pub fn logicalPos(w: *const Writer) u64 { + return w.pos + w.interface.end; +} + +/// Asserts that no data is currently buffered. +pub fn seekToUnbuffered(w: *Writer, offset: u64) SeekError!void { + assert(w.interface.buffered().len == 0); + const io = w.io; + switch (w.mode) { + .positional, .positional_simple => { + w.pos = offset; + }, + .streaming, .streaming_simple => { + if (w.seek_err) |err| return err; + io.vtable.fileSeekTo(io.userdata, w.file, offset) catch |err| { + w.seek_err = err; + return err; + }; + w.pos = offset; + }, + .failure => return w.seek_err.?, + } +} + +pub const EndError = File.SetLengthError || Io.Writer.Error; + +/// Flushes any buffered data and sets the end position of the file. +/// +/// If not overwriting existing contents, then calling `interface.flush` +/// directly is sufficient. +/// +/// Flush failure is handled by setting `err` so that it can be handled +/// along with other write failures. +pub fn end(w: *Writer) EndError!void { + const io = w.io; + try w.interface.flush(); + switch (w.mode) { + .positional, + .positional_simple, + => w.file.setLength(io, w.pos) catch |err| switch (err) { + error.NonResizable => return, + else => |e| return e, + }, + + .streaming, + .streaming_simple, + .failure, + => {}, + } +} + +/// Convenience method for calling `Io.Writer.flush` and returning the +/// underlying error. +pub fn flush(w: *Writer) Error!void { + w.interface.flush() catch |err| switch (err) { + error.WriteFailed => return w.err.?, + }; +} diff --git a/lib/std/Io/IoUring.zig b/lib/std/Io/IoUring.zig index 5561cdebd262..81cdc242018d 100644 --- a/lib/std/Io/IoUring.zig +++ b/lib/std/Io/IoUring.zig @@ -1093,7 +1093,7 @@ fn createFile( .PERM => return error.PermissionDenied, .EXIST => return error.PathAlreadyExists, .BUSY => return error.DeviceBusy, - .OPNOTSUPP => return error.FileLocksNotSupported, + .OPNOTSUPP => return error.FileLocksUnsupported, .AGAIN => return error.WouldBlock, .TXTBSY => return error.FileBusy, .NXIO => return error.NoDevice, @@ -1201,7 +1201,7 @@ fn fileOpen( .PERM => return error.PermissionDenied, .EXIST => return error.PathAlreadyExists, .BUSY => return error.DeviceBusy, - .OPNOTSUPP => return error.FileLocksNotSupported, + .OPNOTSUPP => return error.FileLocksUnsupported, .AGAIN => return error.WouldBlock, .TXTBSY => return error.FileBusy, .NXIO => return error.NoDevice, diff --git a/lib/std/Io/Kqueue.zig b/lib/std/Io/Kqueue.zig index 5b4f71da08cb..f998d5cef8b4 100644 --- a/lib/std/Io/Kqueue.zig +++ b/lib/std/Io/Kqueue.zig @@ -157,8 +157,11 @@ pub const InitOptions = struct { n_threads: ?usize = null, }; +pub const InitError = Allocator.Error || CreateFileDescriptorError; + pub fn init(k: *Kqueue, gpa: Allocator, options: InitOptions) !void { assert(options.n_threads != 0); + const n_threads = @max(1, options.n_threads orelse std.Thread.getCpuCount() catch 1); const threads_size = n_threads * @sizeOf(Thread); const idle_stack_end_offset = std.mem.alignForward(usize, threads_size + idle_stack_size, std.heap.page_size_max); @@ -204,7 +207,7 @@ pub fn init(k: *Kqueue, gpa: Allocator, options: InitOptions) !void { }, .current_context = &main_fiber.context, .ready_queue = null, - .kq_fd = try posix.kqueue(), + .kq_fd = try createFileDescriptor(), .idle_search_index = 1, .steal_ready_search_index = 1, .wait_queues = .empty, @@ -231,6 +234,23 @@ pub fn deinit(k: *Kqueue) void { k.* = undefined; } +pub const CreateFileDescriptorError = error{ + /// The per-process limit on the number of open file descriptors has been reached. + ProcessFdQuotaExceeded, + /// The system-wide limit on the total number of open files has been reached. + SystemFdQuotaExceeded, +} || Io.UnexpectedError; + +pub fn createFileDescriptor() CreateFileDescriptorError!posix.fd_t { + const rc = posix.system.kqueue(); + switch (posix.errno(rc)) { + .SUCCESS => return @intCast(rc), + .MFILE => return error.ProcessFdQuotaExceeded, + .NFILE => return error.SystemFdQuotaExceeded, + else => |err| return posix.unexpectedErrno(err), + } +} + fn findReadyFiber(k: *Kqueue, thread: *Thread) ?*Fiber { if (@atomicRmw(?*Fiber, &thread.ready_queue, .Xchg, Fiber.finished, .acquire)) |ready_fiber| { @atomicStore(?*Fiber, &thread.ready_queue, ready_fiber.queue_next, .release); @@ -314,7 +334,10 @@ fn schedule(k: *Kqueue, thread: *Thread, ready_queue: Fiber.Queue) void { }, }; // If an error occurs it only pessimises scheduling. - _ = posix.kevent(idle_search_thread.kq_fd, &changes, &.{}, null) catch {}; + _ = kevent(idle_search_thread.kq_fd, &changes, &.{}, null) catch |err| { + // TODO handle EINTR for cancellation purposes + @panic(@errorName(err)); // TODO + }; return; } spawn_thread: { @@ -334,7 +357,7 @@ fn schedule(k: *Kqueue, thread: *Thread, ready_queue: Fiber.Queue) void { .idle_context = undefined, .current_context = &new_thread.idle_context, .ready_queue = ready_queue.head, - .kq_fd = posix.kqueue() catch |err| { + .kq_fd = createFileDescriptor() catch |err| { @atomicStore(u32, &k.threads.reserved, new_thread_index, .release); // no more access to `thread` after giving up reservation std.log.warn("unable to create worker thread due to kqueue init failure: {t}", .{err}); @@ -409,9 +432,9 @@ fn idle(k: *Kqueue, thread: *Thread) void { k.yield(ready_fiber, .nothing); maybe_ready_fiber = null; } - const n = posix.kevent(thread.kq_fd, &.{}, &events_buffer, null) catch |err| { + const n = kevent(thread.kq_fd, &.{}, &events_buffer, null) catch |err| { // TODO handle EINTR for cancellation purposes - @panic(@errorName(err)); + @panic(@errorName(err)); // TODO }; var maybe_ready_queue: ?Fiber.Queue = null; for (events_buffer[0..n]) |event| switch (@as(Completion.UserData, @enumFromInt(event.udata))) { @@ -471,14 +494,6 @@ const SwitchMessage = struct { recycle: *Fiber, register_awaiter: *?*Fiber, register_select: []const *Io.AnyFuture, - mutex_lock: struct { - prev_state: Io.Mutex.State, - mutex: *Io.Mutex, - }, - condition_wait: struct { - cond: *Io.Condition, - mutex: *Io.Mutex, - }, exit, }; @@ -514,59 +529,6 @@ const SwitchMessage = struct { } } }, - .mutex_lock => |mutex_lock| { - const prev_fiber: *Fiber = @alignCast(@fieldParentPtr("context", message.contexts.prev)); - assert(prev_fiber.queue_next == null); - var prev_state = mutex_lock.prev_state; - while (switch (prev_state) { - else => next_state: { - prev_fiber.queue_next = @ptrFromInt(@intFromEnum(prev_state)); - break :next_state @cmpxchgWeak( - Io.Mutex.State, - &mutex_lock.mutex.state, - prev_state, - @enumFromInt(@intFromPtr(prev_fiber)), - .release, - .acquire, - ); - }, - .unlocked => @cmpxchgWeak( - Io.Mutex.State, - &mutex_lock.mutex.state, - .unlocked, - .locked_once, - .acquire, - .acquire, - ) orelse { - prev_fiber.queue_next = null; - k.schedule(thread, .{ .head = prev_fiber, .tail = prev_fiber }); - return; - }, - }) |next_state| prev_state = next_state; - }, - .condition_wait => |condition_wait| { - const prev_fiber: *Fiber = @alignCast(@fieldParentPtr("context", message.contexts.prev)); - assert(prev_fiber.queue_next == null); - const cond_impl = prev_fiber.resultPointer(Condition); - cond_impl.* = .{ - .tail = prev_fiber, - .event = .queued, - }; - if (@cmpxchgStrong( - ?*Fiber, - @as(*?*Fiber, @ptrCast(&condition_wait.cond.state)), - null, - prev_fiber, - .release, - .acquire, - )) |waiting_fiber| { - const waiting_cond_impl = waiting_fiber.?.resultPointer(Condition); - assert(waiting_cond_impl.tail.queue_next == null); - waiting_cond_impl.tail.queue_next = prev_fiber; - waiting_cond_impl.tail = prev_fiber; - } - condition_wait.mutex.unlock(k.io()); - }, .exit => for (k.threads.allocated[0..@atomicLoad(u32, &k.threads.active, .acquire)]) |*each_thread| { const changes = [_]posix.Kevent{ .{ @@ -578,8 +540,9 @@ const SwitchMessage = struct { .udata = @intFromEnum(Completion.UserData.exit), }, }; - _ = posix.kevent(each_thread.kq_fd, &changes, &.{}, null) catch |err| { - @panic(@errorName(err)); + _ = kevent(each_thread.kq_fd, &changes, &.{}, null) catch |err| { + // TODO handle EINTR for cancellation purposes + @panic(@errorName(err)); // TODO }; }, } @@ -854,26 +817,18 @@ pub fn io(k: *Kqueue) Io { .concurrent = concurrent, .await = await, .cancel = cancel, - .cancelRequested = cancelRequested, .select = select, .groupAsync = groupAsync, - .groupWait = groupWait, + .groupConcurrent = groupConcurrent, + .groupAwait = groupAwait, .groupCancel = groupCancel, - .mutexLock = mutexLock, - .mutexLockUncancelable = mutexLockUncancelable, - .mutexUnlock = mutexUnlock, - - .conditionWait = conditionWait, - .conditionWaitUncancelable = conditionWaitUncancelable, - .conditionWake = conditionWake, - - .dirMake = dirMake, - .dirMakePath = dirMakePath, - .dirMakeOpenPath = dirMakeOpenPath, + .dirCreateDir = dirCreateDir, + .dirCreateDirPath = dirCreateDirPath, + .dirCreateDirPathOpen = dirCreateDirPathOpen, .dirStat = dirStat, - .dirStatPath = dirStatPath, + .dirStatFile = dirStatFile, .fileStat = fileStat, .dirAccess = dirAccess, @@ -888,7 +843,6 @@ pub fn io(k: *Kqueue) Io { .fileReadPositional = fileReadPositional, .fileSeekBy = fileSeekBy, .fileSeekTo = fileSeekTo, - .openSelfExe = openSelfExe, .now = now, .sleep = sleep, @@ -900,6 +854,7 @@ pub fn io(k: *Kqueue) Io { .netConnectIp = netConnectIp, .netConnectUnix = netConnectUnix, .netClose = netClose, + .netShutdown = netShutdown, .netRead = netRead, .netWrite = netWrite, .netSend = netSend, @@ -1012,139 +967,111 @@ fn cancelRequested(userdata: ?*anyopaque) bool { fn groupAsync( userdata: ?*anyopaque, - group: *Io.Group, + type_erased: *Io.Group, context: []const u8, - context_alignment: std.mem.Alignment, - start: *const fn (*Io.Group, context: *const anyopaque) void, + context_alignment: Alignment, + start: *const fn (context: *const anyopaque) Io.Cancelable!void, ) void { const k: *Kqueue = @ptrCast(@alignCast(userdata)); _ = k; - _ = group; + _ = type_erased; _ = context; _ = context_alignment; _ = start; @panic("TODO"); } -fn groupWait(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) void { - const k: *Kqueue = @ptrCast(@alignCast(userdata)); - _ = k; - _ = group; - _ = token; - @panic("TODO"); -} - -fn groupCancel(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) void { +fn groupConcurrent( + userdata: ?*anyopaque, + type_erased: *Io.Group, + context: []const u8, + context_alignment: Alignment, + start: *const fn (context: *const anyopaque) Io.Cancelable!void, +) Io.ConcurrentError!void { const k: *Kqueue = @ptrCast(@alignCast(userdata)); _ = k; - _ = group; - _ = token; + _ = type_erased; + _ = context; + _ = context_alignment; + _ = start; @panic("TODO"); } -fn select(userdata: ?*anyopaque, futures: []const *Io.AnyFuture) Io.Cancelable!usize { +fn groupAwait(userdata: ?*anyopaque, type_erased: *Io.Group, initial_token: *anyopaque) Io.Cancelable!void { const k: *Kqueue = @ptrCast(@alignCast(userdata)); _ = k; - _ = futures; + _ = type_erased; + _ = initial_token; @panic("TODO"); } -fn mutexLock(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mutex) Io.Cancelable!void { - const k: *Kqueue = @ptrCast(@alignCast(userdata)); - _ = k; - _ = prev_state; - _ = mutex; - @panic("TODO"); -} -fn mutexLockUncancelable(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mutex) void { - const k: *Kqueue = @ptrCast(@alignCast(userdata)); - _ = k; - _ = prev_state; - _ = mutex; - @panic("TODO"); -} -fn mutexUnlock(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mutex) void { +fn groupCancel(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) void { const k: *Kqueue = @ptrCast(@alignCast(userdata)); _ = k; - _ = prev_state; - _ = mutex; + _ = group; + _ = token; @panic("TODO"); } -fn conditionWait(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) Io.Cancelable!void { - const k: *Kqueue = @ptrCast(@alignCast(userdata)); - k.yield(null, .{ .condition_wait = .{ .cond = cond, .mutex = mutex } }); - const thread = Thread.current(); - const fiber = thread.currentFiber(); - const cond_impl = fiber.resultPointer(Condition); - try mutex.lock(k.io()); - switch (cond_impl.event) { - .queued => {}, - .wake => |wake| if (fiber.queue_next) |next_fiber| switch (wake) { - .one => if (@cmpxchgStrong( - ?*Fiber, - @as(*?*Fiber, @ptrCast(&cond.state)), - null, - next_fiber, - .release, - .acquire, - )) |old_fiber| { - const old_cond_impl = old_fiber.?.resultPointer(Condition); - assert(old_cond_impl.tail.queue_next == null); - old_cond_impl.tail.queue_next = next_fiber; - old_cond_impl.tail = cond_impl.tail; - }, - .all => k.schedule(thread, .{ .head = next_fiber, .tail = cond_impl.tail }), - }, - } - fiber.queue_next = null; -} - -fn conditionWaitUncancelable(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) void { +fn select(userdata: ?*anyopaque, futures: []const *Io.AnyFuture) Io.Cancelable!usize { const k: *Kqueue = @ptrCast(@alignCast(userdata)); _ = k; - _ = cond; - _ = mutex; + _ = futures; @panic("TODO"); } -fn conditionWake(userdata: ?*anyopaque, cond: *Io.Condition, wake: Io.Condition.Wake) void { - const k: *Kqueue = @ptrCast(@alignCast(userdata)); - const waiting_fiber = @atomicRmw(?*Fiber, @as(*?*Fiber, @ptrCast(&cond.state)), .Xchg, null, .acquire) orelse return; - waiting_fiber.resultPointer(Condition).event = .{ .wake = wake }; - k.yield(waiting_fiber, .reschedule); -} -fn dirMake(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, mode: Dir.Mode) Dir.MakeError!void { +fn dirCreateDir(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, permissions: Dir.Permissions) Dir.CreateDirError!void { const k: *Kqueue = @ptrCast(@alignCast(userdata)); _ = k; _ = dir; _ = sub_path; - _ = mode; + _ = permissions; @panic("TODO"); } -fn dirMakePath(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, mode: Dir.Mode) Dir.MakeError!void { + +fn dirCreateDirPath( + userdata: ?*anyopaque, + dir: Dir, + sub_path: []const u8, + permissions: Dir.Permissions, +) Dir.CreateDirPathError!Dir.CreatePathStatus { const k: *Kqueue = @ptrCast(@alignCast(userdata)); _ = k; _ = dir; _ = sub_path; - _ = mode; + _ = permissions; @panic("TODO"); } -fn dirMakeOpenPath(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, options: Dir.OpenOptions) Dir.MakeOpenPathError!Dir { + +fn dirCreateDirPathOpen( + userdata: ?*anyopaque, + dir: Dir, + sub_path: []const u8, + permissions: Dir.Permissions, + options: Dir.OpenOptions, +) Dir.CreateDirPathOpenError!Dir { const k: *Kqueue = @ptrCast(@alignCast(userdata)); _ = k; _ = dir; _ = sub_path; + _ = permissions; _ = options; @panic("TODO"); } + fn dirStat(userdata: ?*anyopaque, dir: Dir) Dir.StatError!Dir.Stat { const k: *Kqueue = @ptrCast(@alignCast(userdata)); _ = k; _ = dir; @panic("TODO"); } -fn dirStatPath(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, options: Dir.StatPathOptions) Dir.StatPathError!File.Stat { + +fn dirStatFile( + userdata: ?*anyopaque, + dir: Dir, + sub_path: []const u8, + options: Dir.StatFileOptions, +) Dir.StatFileError!File.Stat { const k: *Kqueue = @ptrCast(@alignCast(userdata)); _ = k; _ = dir; @@ -1184,10 +1111,10 @@ fn dirOpenDir(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, options: Di _ = options; @panic("TODO"); } -fn dirClose(userdata: ?*anyopaque, dir: Dir) void { +fn dirClose(userdata: ?*anyopaque, dirs: []const Dir) void { const k: *Kqueue = @ptrCast(@alignCast(userdata)); _ = k; - _ = dir; + _ = dirs; @panic("TODO"); } fn fileStat(userdata: ?*anyopaque, file: File) File.StatError!File.Stat { @@ -1196,35 +1123,57 @@ fn fileStat(userdata: ?*anyopaque, file: File) File.StatError!File.Stat { _ = file; @panic("TODO"); } -fn fileClose(userdata: ?*anyopaque, file: File) void { + +fn fileClose(userdata: ?*anyopaque, files: []const File) void { const k: *Kqueue = @ptrCast(@alignCast(userdata)); _ = k; - _ = file; + _ = files; @panic("TODO"); } -fn fileWriteStreaming(userdata: ?*anyopaque, file: File, buffer: [][]const u8) File.WriteStreamingError!usize { + +fn fileWriteStreaming( + userdata: ?*anyopaque, + file: File, + header: []const u8, + data: []const []const u8, + splat: usize, +) File.Writer.Error!usize { const k: *Kqueue = @ptrCast(@alignCast(userdata)); _ = k; _ = file; - _ = buffer; + _ = header; + _ = data; + _ = splat; @panic("TODO"); } -fn fileWritePositional(userdata: ?*anyopaque, file: File, buffer: [][]const u8, offset: u64) File.WritePositionalError!usize { + +fn fileWritePositional( + userdata: ?*anyopaque, + file: File, + header: []const u8, + data: []const []const u8, + splat: usize, + offset: u64, +) File.WritePositionalError!usize { const k: *Kqueue = @ptrCast(@alignCast(userdata)); _ = k; _ = file; - _ = buffer; + _ = header; + _ = data; + _ = splat; _ = offset; @panic("TODO"); } -fn fileReadStreaming(userdata: ?*anyopaque, file: File, data: [][]u8) File.Reader.Error!usize { + +fn fileReadStreaming(userdata: ?*anyopaque, file: File, data: []const []u8) File.Reader.Error!usize { const k: *Kqueue = @ptrCast(@alignCast(userdata)); _ = k; _ = file; _ = data; @panic("TODO"); } -fn fileReadPositional(userdata: ?*anyopaque, file: File, data: [][]u8, offset: u64) File.ReadPositionalError!usize { + +fn fileReadPositional(userdata: ?*anyopaque, file: File, data: []const []u8, offset: u64) File.ReadPositionalError!usize { const k: *Kqueue = @ptrCast(@alignCast(userdata)); _ = k; _ = file; @@ -1246,12 +1195,6 @@ fn fileSeekTo(userdata: ?*anyopaque, file: File, absolute_offset: u64) File.Seek _ = absolute_offset; @panic("TODO"); } -fn openSelfExe(userdata: ?*anyopaque, file: File.OpenFlags) File.OpenSelfExeError!File { - const k: *Kqueue = @ptrCast(@alignCast(userdata)); - _ = k; - _ = file; - @panic("TODO"); -} fn now(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp { const k: *Kqueue = @ptrCast(@alignCast(userdata)); @@ -1517,7 +1460,8 @@ fn netRead(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.Strea .udata = @intFromPtr(fiber), }, }; - assert(0 == (posix.kevent(thread.kq_fd, &changes, &.{}, null) catch |err| { + assert(0 == (kevent(thread.kq_fd, &changes, &.{}, null) catch |err| { + // TODO handle EINTR for cancellation purposes @panic(@errorName(err)); // TODO })); } @@ -1549,12 +1493,22 @@ fn netWrite(userdata: ?*anyopaque, dest: net.Socket.Handle, header: []const u8, _ = splat; @panic("TODO"); } -fn netClose(userdata: ?*anyopaque, handle: net.Socket.Handle) void { + +fn netClose(userdata: ?*anyopaque, handles: []const net.Socket.Handle) void { + const k: *Kqueue = @ptrCast(@alignCast(userdata)); + _ = k; + _ = handles; + @panic("TODO"); +} + +fn netShutdown(userdata: ?*anyopaque, handle: net.Socket.Handle, how: net.ShutdownHow) net.ShutdownError!void { const k: *Kqueue = @ptrCast(@alignCast(userdata)); _ = k; _ = handle; + _ = how; @panic("TODO"); } + fn netInterfaceNameResolve( userdata: ?*anyopaque, name: *const net.Interface.Name, @@ -1564,22 +1518,24 @@ fn netInterfaceNameResolve( _ = name; @panic("TODO"); } + fn netInterfaceName(userdata: ?*anyopaque, interface: net.Interface) net.Interface.NameError!net.Interface.Name { const k: *Kqueue = @ptrCast(@alignCast(userdata)); _ = k; _ = interface; @panic("TODO"); } + fn netLookup( userdata: ?*anyopaque, host_name: net.HostName, - result: *Io.Queue(net.HostName.LookupResult), + resolved: *Io.Queue(net.HostName.LookupResult), options: net.HostName.LookupOptions, -) void { +) net.HostName.LookupError!void { const k: *Kqueue = @ptrCast(@alignCast(userdata)); _ = k; _ = host_name; - _ = result; + _ = resolved; _ = options; @panic("TODO"); } @@ -1734,10 +1690,46 @@ fn checkCancel(k: *Kqueue) error{Canceled}!void { if (cancelRequested(k)) return error.Canceled; } -const Condition = struct { - tail: *Fiber, - event: union(enum) { - queued, - wake: Io.Condition.Wake, - }, +pub const KEventError = error{ + /// The process does not have permission to register a filter. + AccessDenied, + /// The event could not be found to be modified or deleted. + EventNotFound, + /// No memory was available to register the event. + SystemResources, + /// The specified process to attach to does not exist. + ProcessNotFound, + /// changelist or eventlist had too many items on it. + /// TODO remove this possibility + Overflow, }; + +pub fn kevent( + kq: i32, + changelist: []const posix.Kevent, + eventlist: []posix.Kevent, + timeout: ?*const posix.timespec, +) KEventError!usize { + while (true) { + const rc = posix.system.kevent( + kq, + changelist.ptr, + std.math.cast(c_int, changelist.len) orelse return error.Overflow, + eventlist.ptr, + std.math.cast(c_int, eventlist.len) orelse return error.Overflow, + timeout, + ); + switch (posix.errno(rc)) { + .SUCCESS => return @intCast(rc), + .ACCES => return error.AccessDenied, + .FAULT => unreachable, // TODO use error.Unexpected for these + .BADF => unreachable, // Always a race condition. + .INTR => continue, // TODO handle cancelation + .INVAL => unreachable, + .NOENT => return error.EventNotFound, + .NOMEM => return error.SystemResources, + .SRCH => return error.ProcessNotFound, + else => unreachable, + } + } +} diff --git a/lib/std/Io/Reader.zig b/lib/std/Io/Reader.zig index 78963dcdab08..08df1e99bc9d 100644 --- a/lib/std/Io/Reader.zig +++ b/lib/std/Io/Reader.zig @@ -993,7 +993,7 @@ pub fn streamDelimiterLimit( error.ReadFailed => return error.ReadFailed, error.EndOfStream => return @intFromEnum(limit) - remaining, }); - if (std.mem.indexOfScalar(u8, available, delimiter)) |delimiter_index| { + if (std.mem.findScalar(u8, available, delimiter)) |delimiter_index| { try w.writeAll(available[0..delimiter_index]); r.toss(delimiter_index); remaining -= delimiter_index; @@ -1064,7 +1064,7 @@ pub fn discardDelimiterLimit(r: *Reader, delimiter: u8, limit: Limit) DiscardDel error.ReadFailed => return error.ReadFailed, error.EndOfStream => return @intFromEnum(limit) - remaining, }); - if (std.mem.indexOfScalar(u8, available, delimiter)) |delimiter_index| { + if (std.mem.findScalar(u8, available, delimiter)) |delimiter_index| { r.toss(delimiter_index); remaining -= delimiter_index; return @intFromEnum(limit) - remaining; @@ -1252,7 +1252,7 @@ pub const TakeEnumError = Error || error{InvalidEnumTag}; pub fn takeEnum(r: *Reader, comptime Enum: type, endian: std.builtin.Endian) TakeEnumError!Enum { const Tag = @typeInfo(Enum).@"enum".tag_type; const int = try r.takeInt(Tag, endian); - return std.meta.intToEnum(Enum, int); + return std.enums.fromInt(Enum, int) orelse return error.InvalidEnumTag; } /// Reads an integer with the same size as the given nonexhaustive enum's tag type. @@ -1271,38 +1271,113 @@ pub fn takeEnumNonexhaustive(r: *Reader, comptime Enum: type, endian: std.builti pub const TakeLeb128Error = Error || error{Overflow}; /// Read a single LEB128 value as type T, or `error.Overflow` if the value cannot fit. -pub fn takeLeb128(r: *Reader, comptime Result: type) TakeLeb128Error!Result { - const result_info = @typeInfo(Result).int; - return std.math.cast(Result, try r.takeMultipleOf7Leb128(@Int( - result_info.signedness, - std.mem.alignForwardAnyAlign(u16, result_info.bits, 7), - ))) orelse error.Overflow; -} - -fn takeMultipleOf7Leb128(r: *Reader, comptime Result: type) TakeLeb128Error!Result { - const result_info = @typeInfo(Result).int; - comptime assert(result_info.bits % 7 == 0); - var remaining_bits: std.math.Log2IntCeil(Result) = result_info.bits; - const UnsignedResult = @Int(.unsigned, result_info.bits); - var result: UnsignedResult = 0; - var fits = true; - while (true) { - const buffer: []const packed struct(u8) { bits: u7, more: bool } = @ptrCast(try r.peekGreedy(1)); - for (buffer, 1..) |byte, len| { - if (remaining_bits > 0) { - result = @shlExact(@as(UnsignedResult, byte.bits), result_info.bits - 7) | - if (result_info.bits > 7) @shrExact(result, 7) else 0; - remaining_bits -= 7; - } else if (fits) fits = switch (result_info.signedness) { - .signed => @as(i7, @bitCast(byte.bits)) == - @as(i7, @truncate(@as(Result, @bitCast(result)) >> (result_info.bits - 1))), - .unsigned => byte.bits == 0, +pub fn takeLeb128(r: *Reader, comptime T: type) TakeLeb128Error!T { + const info = switch (@typeInfo(T)) { + .int => |info| info, + else => @compileError(@typeName(T) ++ " not supported"), + }; + const Byte = packed struct { bits: u7, more: bool }; + + if (info.bits <= 7) { + var byte: Byte = undefined; + const Bits = @Int(info.signedness, 7); + + byte = @bitCast(try r.takeByte()); + const val = std.math.cast(T, @as(Bits, @bitCast(byte.bits))) orelse error.Overflow; + + const allowed_bits: u7 = switch (info.signedness) { + .unsigned => 0, + .signed => @bitCast(@as(i7, @bitCast(byte.bits)) >> 6), + }; + + var fits = true; + while (byte.more) { + byte = @bitCast(try r.takeByte()); + + if (byte.bits != allowed_bits) fits = false; + } + + return if (fits) blk: { + @branchHint(.likely); + break :blk val; + } else error.Overflow; + } + + const Unsigned = @Int(.unsigned, info.bits); + const UInt = std.math.ByteAlignedInt(Unsigned); + const Int = std.math.ByteAlignedInt(T); + + const uint_bits = @typeInfo(UInt).int.bits; + + var byte: Byte = undefined; + var val: UInt = 0; + const max_bytes = @divFloor(info.bits - 1, 7) + 1; + inline for (0..max_bytes) |iteration| { + const shift = iteration * 7; + + byte = @bitCast(try r.takeByte()); + + const extended: UInt = byte.bits; + val |= extended << shift; + + const bits_written = shift + 7; + + if (bits_written >= info.bits) { + const bits_overflowed = bits_written - info.bits; + const bits_remaining = @mod(info.bits, 7); + + const allowed_bits: u7, var fits: bool = switch (info.signedness) { + .unsigned => blk: { + const fits = bits_remaining == 0 or byte.bits >> bits_remaining == 0; + + break :blk .{ 0, fits }; + }, + .signed => blk: { + const bits: i7 = @bitCast(byte.bits); + + // Move the sign bit into the MSB + const shifted_bits: i7 = bits << bits_overflowed; + + const value_sign: i7 = shifted_bits >> 6; // sign extends + const bits_sign: i7 = bits >> bits_remaining; // sign extends + + const fits = bits_remaining == 0 or bits_sign == value_sign; + + if (uint_bits != info.bits and value_sign != 0) { + const sign_extend_mask = @as(UInt, std.math.maxInt(UInt)) << info.bits; + val |= sign_extend_mask; + } + + break :blk .{ @bitCast(value_sign), fits }; + }, }; - if (byte.more) continue; - r.toss(len); - return if (fits) @as(Result, @bitCast(result)) >> remaining_bits else error.Overflow; + + switch (info.signedness) { + .signed => assert(allowed_bits == 0 or allowed_bits == 0x7F), + .unsigned => comptime assert(allowed_bits == 0), + } + + while (byte.more) { + byte = @bitCast(try r.takeByte()); + if (byte.bits != allowed_bits) fits = false; + } + + return if (fits) blk: { + @branchHint(.likely); + break :blk std.math.cast(T, @as(Int, @bitCast(val))) orelse error.Overflow; + } else error.Overflow; + } + + comptime assert(bits_written < info.bits); + if (!byte.more) { + if (info.signedness == .signed and // can be negative + byte.bits & 0x40 != 0) // is negative + { + const sign_extend_mask = @as(UInt, std.math.maxInt(UInt)) << bits_written; + val |= sign_extend_mask; + } + return std.math.cast(T, @as(Int, @bitCast(val))) orelse error.Overflow; } - r.toss(buffer.len); } } @@ -1610,13 +1685,6 @@ test takeEnum { try testing.expectEqual(@as(E2, @enumFromInt(0x0001)), try r.takeEnum(E2, .big)); } -test takeLeb128 { - var r: Reader = .fixed("\xc7\x9f\x7f\x80"); - try testing.expectEqual(-12345, try r.takeLeb128(i64)); - try testing.expectEqual(0x80, try r.peekByte()); - try testing.expectError(error.EndOfStream, r.takeLeb128(i64)); -} - test readSliceShort { var r: Reader = .fixed("HelloFren"); var buf: [5]u8 = undefined; @@ -1978,90 +2046,245 @@ pub fn writableVector(r: *Reader, buffer: [][]u8, data: []const []u8) Error!stru } test "deserialize signed LEB128" { + // Small values + try testing.expectEqual(5, testLeb128(i7, "\x05")); + try testing.expectEqual(53, testLeb128(i64, "\x35")); + + try testing.expectEqual(-6, testLeb128(i7, "\x7A")); + try testing.expectEqual(-23, testLeb128(i64, "\x69")); + + // Random values + try testing.expectEqual(90, testLeb128(i8, "\xDA\x00")); + try testing.expectEqual(3434, testLeb128(i16, "\xEA\x1A")); + try testing.expectEqual(1505683543, testLeb128(i32, "\xD7\xD0\xFB\xCD\x05")); + try testing.expectEqual(105721575804011595, testLeb128(i64, "\xCB\x88\x92\xD7\xE8\xA6\xE6\xBB\x01")); + try testing.expectEqual(51316697993548595875823294343650416388, testLeb128(i128, "\x84\xAE\xAC\xFC\xE4\xA0\xCD\xE2\x87\xED\x83\xB2\x87\xAA\xA3\x9E\x9B\xCD\x00")); + + try testing.expectEqual(-68, testLeb128(i8, "\xBC\x7F")); + try testing.expectEqual(-20174, testLeb128(i16, "\xB2\xE2\x7E")); + try testing.expectEqual(-166511141, testLeb128(i32, "\xDB\xFB\xCC\xB0\x7F")); + try testing.expectEqual(-4368809844285451825, testLeb128(i64, "\xCF\xA3\x8B\xA1\xFF\xD2\xB7\xAF\x43")); + try testing.expectEqual(-43250117698642799010758201165100952046, testLeb128(i128, "\x92\xAC\xDB\xA4\xEC\xDE\xB9\x95\xD1\xBA\xEC\xB0\xD7\x80\xA4\xAA\xF6\xBE\x7F")); + + // {min,max} values + try testing.expectEqual(std.math.maxInt(i8), testLeb128(i8, "\xFF\x00")); + try testing.expectEqual(std.math.maxInt(i16), testLeb128(i16, "\xFF\xFF\x01")); + try testing.expectEqual(std.math.maxInt(i32), testLeb128(i32, "\xFF\xFF\xFF\xFF\x07")); + try testing.expectEqual(std.math.maxInt(i64), testLeb128(i64, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00")); + try testing.expectEqual(std.math.maxInt(i128), testLeb128(i128, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01")); + + try testing.expectEqual(std.math.minInt(i8), testLeb128(i8, "\x80\x7F")); + try testing.expectEqual(std.math.minInt(i16), testLeb128(i16, "\x80\x80\x7E")); + try testing.expectEqual(std.math.minInt(i32), testLeb128(i32, "\x80\x80\x80\x80\x78")); + try testing.expectEqual(std.math.minInt(i64), testLeb128(i64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x7F")); + try testing.expectEqual(std.math.minInt(i128), testLeb128(i128, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x7E")); + + // Specific cases + try testing.expectEqual(0, testLeb128(i0, "\x00")); + try testing.expectEqual(0, testLeb128(i2, "\x00")); + try testing.expectEqual(0, testLeb128(i8, "\x00")); + + try testing.expectEqual(1, testLeb128(i2, "\x01")); + try testing.expectEqual(1, testLeb128(i8, "\x01")); + + try testing.expectEqual(-1, testLeb128(i2, "\x7F")); + try testing.expectEqual(-1, testLeb128(i8, "\x7F")); + + const end_of_stream: [20]u8 = @splat(0x80); + const overflow: [21]u8 = end_of_stream ++ .{0x01}; + const long_zero: [21]u8 = end_of_stream ++ .{0x00}; + const long_one: [22]u8 = .{0x81} ++ end_of_stream ++ .{0x00}; + const long_minus_one: [20]u8 = @as([19]u8, @splat(0xFF)) ++ .{0x7F}; + // Truncated - try testing.expectError(error.EndOfStream, testLeb128(i64, "\x80")); + try testing.expectError(error.EndOfStream, testLeb128(i16, "\x80\x80\x84\x80")); + try testing.expectError(error.EndOfStream, testLeb128(i16, "\x80\x80\x80\x84\x80")); + try testing.expectError(error.EndOfStream, testLeb128(i32, "\x80\x80\x80\x80\x90")); + + try testing.expectError(error.EndOfStream, testLeb128(i7, "")); + try testing.expectError(error.EndOfStream, testLeb128(i8, "")); + try testing.expectError(error.EndOfStream, testLeb128(i14, "")); + try testing.expectError(error.EndOfStream, testLeb128(i128, "")); + + try testing.expectError(error.EndOfStream, testLeb128(i7, "\x80")); + try testing.expectError(error.EndOfStream, testLeb128(i8, "\x80")); + try testing.expectError(error.EndOfStream, testLeb128(i14, "\x80")); + try testing.expectError(error.EndOfStream, testLeb128(i128, "\x80")); + + try testing.expectError(error.EndOfStream, testLeb128(i7, &end_of_stream)); + try testing.expectError(error.EndOfStream, testLeb128(i8, &end_of_stream)); + try testing.expectError(error.EndOfStream, testLeb128(i14, &end_of_stream)); + try testing.expectError(error.EndOfStream, testLeb128(i128, &end_of_stream)); // Overflow + try testing.expectError(error.Overflow, testLeb128(i0, "\x01")); + try testing.expectError(error.Overflow, testLeb128(i0, "\x7F")); + try testing.expectError(error.Overflow, testLeb128(i8, "\x80\x01")); + try testing.expectError(error.Overflow, testLeb128(i8, "\xFF\x7E")); try testing.expectError(error.Overflow, testLeb128(i8, "\x80\x80\x40")); try testing.expectError(error.Overflow, testLeb128(i16, "\x80\x80\x80\x40")); - try testing.expectError(error.Overflow, testLeb128(i32, "\x80\x80\x80\x80\x40")); - try testing.expectError(error.Overflow, testLeb128(i64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x40")); - try testing.expectError(error.Overflow, testLeb128(i8, "\xff\x7e")); try testing.expectError(error.Overflow, testLeb128(i32, "\x80\x80\x80\x80\x08")); + try testing.expectError(error.Overflow, testLeb128(i32, "\x80\x80\x80\x80\x40")); try testing.expectError(error.Overflow, testLeb128(i64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01")); + try testing.expectError(error.Overflow, testLeb128(i64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x40")); - // Decode SLEB128 - try testing.expect((try testLeb128(i64, "\x00")) == 0); - try testing.expect((try testLeb128(i64, "\x01")) == 1); - try testing.expect((try testLeb128(i64, "\x3f")) == 63); - try testing.expect((try testLeb128(i64, "\x40")) == -64); - try testing.expect((try testLeb128(i64, "\x41")) == -63); - try testing.expect((try testLeb128(i64, "\x7f")) == -1); - try testing.expect((try testLeb128(i64, "\x80\x01")) == 128); - try testing.expect((try testLeb128(i64, "\x81\x01")) == 129); - try testing.expect((try testLeb128(i64, "\xff\x7e")) == -129); - try testing.expect((try testLeb128(i64, "\x80\x7f")) == -128); - try testing.expect((try testLeb128(i64, "\x81\x7f")) == -127); - try testing.expect((try testLeb128(i64, "\xc0\x00")) == 64); - try testing.expect((try testLeb128(i64, "\xc7\x9f\x7f")) == -12345); - try testing.expect((try testLeb128(i8, "\xff\x7f")) == -1); - try testing.expect((try testLeb128(i16, "\xff\xff\x7f")) == -1); - try testing.expect((try testLeb128(i32, "\xff\xff\xff\xff\x7f")) == -1); - try testing.expect((try testLeb128(i32, "\x80\x80\x80\x80\x78")) == -0x80000000); - try testing.expect((try testLeb128(i64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x7f")) == @as(i64, @bitCast(@as(u64, @intCast(0x8000000000000000))))); - try testing.expect((try testLeb128(i64, "\x80\x80\x80\x80\x80\x80\x80\x80\x40")) == -0x4000000000000000); - try testing.expect((try testLeb128(i64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x7f")) == -0x8000000000000000); - - // Decode unnormalized SLEB128 with extra padding bytes. - try testing.expect((try testLeb128(i64, "\x80\x00")) == 0); - try testing.expect((try testLeb128(i64, "\x80\x80\x00")) == 0); - try testing.expect((try testLeb128(i64, "\xff\x00")) == 0x7f); - try testing.expect((try testLeb128(i64, "\xff\x80\x00")) == 0x7f); - try testing.expect((try testLeb128(i64, "\x80\x81\x00")) == 0x80); - try testing.expect((try testLeb128(i64, "\x80\x81\x80\x00")) == 0x80); + try testing.expectError(error.Overflow, testLeb128(i0, &overflow)); + try testing.expectError(error.Overflow, testLeb128(i7, &overflow)); + try testing.expectError(error.Overflow, testLeb128(i8, &overflow)); + try testing.expectError(error.Overflow, testLeb128(i14, &overflow)); + try testing.expectError(error.Overflow, testLeb128(i128, &overflow)); + + // Extra padding + try testing.expectEqual(-1, testLeb128(i32, "\xFF\xFF\xFF\xFF\x7F")); + try testing.expectEqual(-1, testLeb128(i64, "\xFF\x7F")); + try testing.expectEqual(0x7F, testLeb128(i64, "\xFF\x00")); + try testing.expectEqual(0x7F, testLeb128(i64, "\xFF\x80\x00")); + try testing.expectEqual(0x80, testLeb128(i64, "\x80\x81\x00")); + try testing.expectEqual(0x80, testLeb128(i64, "\x80\x81\x80\x00")); + + try testing.expectEqual(0, testLeb128(i0, &long_zero)); + try testing.expectEqual(0, testLeb128(i7, &long_zero)); + try testing.expectEqual(0, testLeb128(i8, &long_zero)); + try testing.expectEqual(0, testLeb128(i14, &long_zero)); + try testing.expectEqual(0, testLeb128(i128, &long_zero)); + + try testing.expectEqual(1, testLeb128(i2, &long_one)); + try testing.expectEqual(1, testLeb128(i7, &long_one)); + try testing.expectEqual(1, testLeb128(i8, &long_one)); + try testing.expectEqual(1, testLeb128(i14, &long_one)); + try testing.expectEqual(1, testLeb128(i128, &long_one)); + + try testing.expectEqual(-1, testLeb128(i2, &long_minus_one)); + try testing.expectEqual(-1, testLeb128(i7, &long_minus_one)); + try testing.expectEqual(-1, testLeb128(i8, &long_minus_one)); + try testing.expectEqual(-1, testLeb128(i14, &long_minus_one)); + try testing.expectEqual(-1, testLeb128(i128, &long_minus_one)); + + // Decode byte boundaries + try testing.expectEqual(std.math.maxInt(i7), testLeb128(i7, "\x3F")); + try testing.expectEqual(std.math.maxInt(i7) + 1, testLeb128(i8, "\xC0\x00")); + try testing.expectEqual(std.math.maxInt(i14), testLeb128(i14, "\xFF\x3F")); + try testing.expectEqual(std.math.maxInt(i14) + 1, testLeb128(i15, "\x80\xC0\x00")); + try testing.expectEqual(std.math.maxInt(i49), testLeb128(i49, "\xFF\xFF\xFF\xFF\xFF\xFF\x3F")); + try testing.expectEqual(std.math.maxInt(i49) + 1, testLeb128(i50, "\x80\x80\x80\x80\x80\x80\xC0\x00")); + try testing.expectEqual(std.math.maxInt(i56), testLeb128(i56, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x3F")); + try testing.expectEqual(std.math.maxInt(i56) + 1, testLeb128(i57, "\x80\x80\x80\x80\x80\x80\x80\xC0\x00")); + try testing.expectEqual(std.math.maxInt(i63), testLeb128(i63, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x3F")); + try testing.expectEqual(std.math.maxInt(i63) + 1, testLeb128(i64, "\x80\x80\x80\x80\x80\x80\x80\x80\xC0\x00")); + + try testing.expectEqual(std.math.minInt(i7), testLeb128(i7, "\x40")); + try testing.expectEqual(std.math.minInt(i7) - 1, testLeb128(i8, "\xBF\x7F")); + try testing.expectEqual(std.math.minInt(i14), testLeb128(i14, "\x80\x40")); + try testing.expectEqual(std.math.minInt(i14) - 1, testLeb128(i15, "\xFF\xBF\x7F")); + try testing.expectEqual(std.math.minInt(i49), testLeb128(i49, "\x80\x80\x80\x80\x80\x80\x40")); + try testing.expectEqual(std.math.minInt(i49) - 1, testLeb128(i50, "\xFF\xFF\xFF\xFF\xFF\xFF\xBF\x7F")); + try testing.expectEqual(std.math.minInt(i56), testLeb128(i56, "\x80\x80\x80\x80\x80\x80\x80\x40")); + try testing.expectEqual(std.math.minInt(i56) - 1, testLeb128(i57, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xBF\x7F")); + try testing.expectEqual(std.math.minInt(i63), testLeb128(i63, "\x80\x80\x80\x80\x80\x80\x80\x80\x40")); + try testing.expectEqual(std.math.minInt(i63) - 1, testLeb128(i64, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xBF\x7F")); } test "deserialize unsigned LEB128" { + // Small values + try testing.expectEqual(46, testLeb128(u7, "\x2E")); + try testing.expectEqual(117, testLeb128(u64, "\x75")); + + // Random values + try testing.expectEqual(224, testLeb128(u8, "\xE0\x01")); + try testing.expectEqual(53023, testLeb128(u16, "\x9F\x9E\x03")); + try testing.expectEqual(2609971022, testLeb128(u32, "\xCE\xFE\xC3\xDC\x09")); + try testing.expectEqual(10223253173206528843, testLeb128(u64, "\xCB\xE6\xF0\xEE\x88\xD3\x92\xF0\x8D\x01")); + try testing.expectEqual(67831258924174241363439488509570048548, testLeb128(u128, "\xA4\xC4\xD7\xE9\x8C\xD2\x86\x80\xBC\xAC\xE5\xAB\xB4\xA2\xD1\xE9\x87\x66")); + + // max values + try testing.expectEqual(std.math.maxInt(u8), testLeb128(u8, "\xFF\x01")); + try testing.expectEqual(std.math.maxInt(u16), testLeb128(u16, "\xFF\xFF\x03")); + try testing.expectEqual(std.math.maxInt(u32), testLeb128(u32, "\xFF\xFF\xFF\xFF\x0F")); + try testing.expectEqual(std.math.maxInt(u64), testLeb128(u64, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01")); + try testing.expectEqual(std.math.maxInt(u128), testLeb128(u128, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x03")); + + // Specific cases + try testing.expectEqual(0, testLeb128(u0, "\x00")); + try testing.expectEqual(0, testLeb128(u1, "\x00")); + try testing.expectEqual(0, testLeb128(u8, "\x00")); + + try testing.expectEqual(1, testLeb128(u1, "\x01")); + try testing.expectEqual(1, testLeb128(u8, "\x01")); + + const end_of_stream: [20]u8 = @splat(0x80); + const overflow: [21]u8 = end_of_stream ++ .{0x01}; + const long_zero: [21]u8 = end_of_stream ++ .{0x00}; + const long_one: [22]u8 = .{0x81} ++ end_of_stream ++ .{0x00}; + // Truncated - try testing.expectError(error.EndOfStream, testLeb128(u64, "\x80")); - try testing.expectError(error.EndOfStream, testLeb128(u16, "\x80\x80\x84")); + try testing.expectError(error.EndOfStream, testLeb128(u16, "\x80\x80\x84\x80")); + try testing.expectError(error.EndOfStream, testLeb128(u16, "\x80\x80\x80\x84\x80")); try testing.expectError(error.EndOfStream, testLeb128(u32, "\x80\x80\x80\x80\x90")); + try testing.expectError(error.EndOfStream, testLeb128(u7, "")); + try testing.expectError(error.EndOfStream, testLeb128(u8, "")); + try testing.expectError(error.EndOfStream, testLeb128(u14, "")); + try testing.expectError(error.EndOfStream, testLeb128(u128, "")); + + try testing.expectError(error.EndOfStream, testLeb128(u7, "\x80")); + try testing.expectError(error.EndOfStream, testLeb128(u8, "\x80")); + try testing.expectError(error.EndOfStream, testLeb128(u14, "\x80")); + try testing.expectError(error.EndOfStream, testLeb128(u128, "\x80")); + + try testing.expectError(error.EndOfStream, testLeb128(u7, &end_of_stream)); + try testing.expectError(error.EndOfStream, testLeb128(u8, &end_of_stream)); + try testing.expectError(error.EndOfStream, testLeb128(u14, &end_of_stream)); + try testing.expectError(error.EndOfStream, testLeb128(u128, &end_of_stream)); + // Overflow + try testing.expectError(error.Overflow, testLeb128(u0, "\x01")); + try testing.expectError(error.Overflow, testLeb128(u1, "\x02")); try testing.expectError(error.Overflow, testLeb128(u8, "\x80\x02")); try testing.expectError(error.Overflow, testLeb128(u8, "\x80\x80\x40")); try testing.expectError(error.Overflow, testLeb128(u16, "\x80\x80\x80\x40")); try testing.expectError(error.Overflow, testLeb128(u32, "\x80\x80\x80\x80\x40")); try testing.expectError(error.Overflow, testLeb128(u64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x40")); - // Decode ULEB128 - try testing.expect((try testLeb128(u64, "\x00")) == 0); - try testing.expect((try testLeb128(u64, "\x01")) == 1); - try testing.expect((try testLeb128(u64, "\x3f")) == 63); - try testing.expect((try testLeb128(u64, "\x40")) == 64); - try testing.expect((try testLeb128(u64, "\x7f")) == 0x7f); - try testing.expect((try testLeb128(u64, "\x80\x01")) == 0x80); - try testing.expect((try testLeb128(u64, "\x81\x01")) == 0x81); - try testing.expect((try testLeb128(u64, "\x90\x01")) == 0x90); - try testing.expect((try testLeb128(u64, "\xff\x01")) == 0xff); - try testing.expect((try testLeb128(u64, "\x80\x02")) == 0x100); - try testing.expect((try testLeb128(u64, "\x81\x02")) == 0x101); - try testing.expect((try testLeb128(u64, "\x80\xc1\x80\x80\x10")) == 4294975616); - try testing.expect((try testLeb128(u64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01")) == 0x8000000000000000); - - // Decode ULEB128 with extra padding bytes - try testing.expect((try testLeb128(u64, "\x80\x00")) == 0); - try testing.expect((try testLeb128(u64, "\x80\x80\x00")) == 0); - try testing.expect((try testLeb128(u64, "\xff\x00")) == 0x7f); - try testing.expect((try testLeb128(u64, "\xff\x80\x00")) == 0x7f); - try testing.expect((try testLeb128(u64, "\x80\x81\x00")) == 0x80); - try testing.expect((try testLeb128(u64, "\x80\x81\x80\x00")) == 0x80); + try testing.expectError(error.Overflow, testLeb128(u7, &overflow)); + try testing.expectError(error.Overflow, testLeb128(u8, &overflow)); + try testing.expectError(error.Overflow, testLeb128(u14, &overflow)); + try testing.expectError(error.Overflow, testLeb128(u128, &overflow)); + + // Extra padding + try testing.expectEqual(0x7F, testLeb128(u64, "\xFF\x00")); + try testing.expectEqual(0x7F, testLeb128(u64, "\xFF\x80\x00")); + try testing.expectEqual(0x80, testLeb128(u64, "\x80\x81\x00")); + try testing.expectEqual(0x80, testLeb128(u64, "\x80\x81\x80\x80\x00")); + + try testing.expectEqual(0, testLeb128(u0, &long_zero)); + try testing.expectEqual(0, testLeb128(u7, &long_zero)); + try testing.expectEqual(0, testLeb128(u8, &long_zero)); + try testing.expectEqual(0, testLeb128(u14, &long_zero)); + try testing.expectEqual(0, testLeb128(u128, &long_zero)); + + try testing.expectEqual(1, testLeb128(u1, &long_one)); + try testing.expectEqual(1, testLeb128(u7, &long_one)); + try testing.expectEqual(1, testLeb128(u8, &long_one)); + try testing.expectEqual(1, testLeb128(u14, &long_one)); + try testing.expectEqual(1, testLeb128(u128, &long_one)); + + // Decode byte boundaries + try testing.expectEqual(std.math.maxInt(u7), testLeb128(u7, "\x7F")); + try testing.expectEqual(std.math.maxInt(u7) + 1, testLeb128(u8, "\x80\x01")); + try testing.expectEqual(std.math.maxInt(u14), testLeb128(u14, "\xFF\x7F")); + try testing.expectEqual(std.math.maxInt(u14) + 1, testLeb128(u15, "\x80\x80\x01")); + try testing.expectEqual(std.math.maxInt(u49), testLeb128(u49, "\xFF\xFF\xFF\xFF\xFF\xFF\x7F")); + try testing.expectEqual(std.math.maxInt(u49) + 1, testLeb128(u50, "\x80\x80\x80\x80\x80\x80\x80\x01")); + try testing.expectEqual(std.math.maxInt(u56), testLeb128(u56, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F")); + try testing.expectEqual(std.math.maxInt(u56) + 1, testLeb128(u57, "\x80\x80\x80\x80\x80\x80\x80\x80\x01")); + try testing.expectEqual(std.math.maxInt(u63), testLeb128(u63, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F")); + try testing.expectEqual(std.math.maxInt(u63) + 1, testLeb128(u64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01")); } fn testLeb128(comptime T: type, encoded: []const u8) !T { var reader: std.Io.Reader = .fixed(encoded); - const result = try reader.takeLeb128(T); - try testing.expect(reader.seek == reader.end); + const result = reader.takeLeb128(T); + try testing.expectEqual(reader.seek, reader.end); return result; } diff --git a/lib/std/Io/Terminal.zig b/lib/std/Io/Terminal.zig new file mode 100644 index 000000000000..beacc4d301c7 --- /dev/null +++ b/lib/std/Io/Terminal.zig @@ -0,0 +1,138 @@ +/// Abstraction for writing to a stream that might support terminal escape +/// codes. +const Terminal = @This(); + +const builtin = @import("builtin"); +const is_windows = builtin.os.tag == .windows; + +const std = @import("std"); +const Io = std.Io; +const File = std.Io.File; + +writer: *Io.Writer, +mode: Mode, + +pub const Color = enum { + black, + red, + green, + yellow, + blue, + magenta, + cyan, + white, + bright_black, + bright_red, + bright_green, + bright_yellow, + bright_blue, + bright_magenta, + bright_cyan, + bright_white, + dim, + bold, + reset, +}; + +pub const Mode = union(enum) { + no_color, + escape_codes, + windows_api: WindowsApi, + + pub const WindowsApi = if (!is_windows) noreturn else struct { + handle: File.Handle, + reset_attributes: u16, + }; + + /// Detect suitable TTY configuration options for the given file (commonly + /// stdout/stderr). + /// + /// Will attempt to enable ANSI escape code support if necessary/possible. + /// + /// * `NO_COLOR` indicates whether "NO_COLOR" environment variable is + /// present and non-empty. + /// * `CLICOLOR_FORCE` indicates whether "CLICOLOR_FORCE" environment + /// variable is present and non-empty. + pub fn detect(io: Io, file: File, NO_COLOR: bool, CLICOLOR_FORCE: bool) Io.Cancelable!Mode { + const force_color: ?bool = if (NO_COLOR) false else if (CLICOLOR_FORCE) true else null; + if (force_color == false) return .no_color; + + if (file.enableAnsiEscapeCodes(io)) |_| { + return .escape_codes; + } else |err| switch (err) { + error.Canceled => return error.Canceled, + error.NotTerminalDevice, error.Unexpected => {}, + } + + if (is_windows and try file.isTty(io)) { + const windows = std.os.windows; + var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined; + if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) != 0) { + return .{ .windows_api = .{ + .handle = file.handle, + .reset_attributes = info.wAttributes, + } }; + } + } + return if (force_color == true) .escape_codes else .no_color; + } +}; + +pub const SetColorError = std.os.windows.SetConsoleTextAttributeError || Io.Writer.Error; + +pub fn setColor(t: Terminal, color: Color) SetColorError!void { + switch (t.mode) { + .no_color => return, + .escape_codes => { + const color_string = switch (color) { + .black => "\x1b[30m", + .red => "\x1b[31m", + .green => "\x1b[32m", + .yellow => "\x1b[33m", + .blue => "\x1b[34m", + .magenta => "\x1b[35m", + .cyan => "\x1b[36m", + .white => "\x1b[37m", + .bright_black => "\x1b[90m", + .bright_red => "\x1b[91m", + .bright_green => "\x1b[92m", + .bright_yellow => "\x1b[93m", + .bright_blue => "\x1b[94m", + .bright_magenta => "\x1b[95m", + .bright_cyan => "\x1b[96m", + .bright_white => "\x1b[97m", + .bold => "\x1b[1m", + .dim => "\x1b[2m", + .reset => "\x1b[0m", + }; + try t.writer.writeAll(color_string); + }, + .windows_api => |wa| { + const windows = std.os.windows; + const attributes: windows.WORD = switch (color) { + .black => 0, + .red => windows.FOREGROUND_RED, + .green => windows.FOREGROUND_GREEN, + .yellow => windows.FOREGROUND_RED | windows.FOREGROUND_GREEN, + .blue => windows.FOREGROUND_BLUE, + .magenta => windows.FOREGROUND_RED | windows.FOREGROUND_BLUE, + .cyan => windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE, + .white => windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE, + .bright_black => windows.FOREGROUND_INTENSITY, + .bright_red => windows.FOREGROUND_RED | windows.FOREGROUND_INTENSITY, + .bright_green => windows.FOREGROUND_GREEN | windows.FOREGROUND_INTENSITY, + .bright_yellow => windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_INTENSITY, + .bright_blue => windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY, + .bright_magenta => windows.FOREGROUND_RED | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY, + .bright_cyan => windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY, + .bright_white, .bold => windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY, + // "dim" is not supported using basic character attributes, but let's still make it do *something*. + // This matches the old behavior of TTY.Color before the bright variants were added. + .dim => windows.FOREGROUND_INTENSITY, + .reset => wa.reset_attributes, + }; + try t.writer.flush(); + try windows.SetConsoleTextAttribute(wa.handle, attributes); + }, + } +} diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 0e5c12504b15..94a0a696646b 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -3,19 +3,23 @@ const Threaded = @This(); const builtin = @import("builtin"); const native_os = builtin.os.tag; const is_windows = native_os == .windows; -const windows = std.os.windows; -const ws2_32 = std.os.windows.ws2_32; +const is_darwin = native_os.isDarwin(); const is_debug = builtin.mode == .Debug; const std = @import("../std.zig"); const Io = std.Io; const net = std.Io.net; +const File = std.Io.File; +const Dir = std.Io.Dir; const HostName = std.Io.net.HostName; const IpAddress = std.Io.net.IpAddress; +const process = std.process; const Allocator = std.mem.Allocator; const Alignment = std.mem.Alignment; const assert = std.debug.assert; const posix = std.posix; +const windows = std.os.windows; +const ws2_32 = std.os.windows.ws2_32; /// Thread-safe. allocator: Allocator, @@ -26,23 +30,7 @@ join_requested: bool = false, stack_size: usize, /// All threads are spawned detached; this is how we wait until they all exit. wait_group: std.Thread.WaitGroup = .{}, -/// Maximum thread pool size (excluding main thread) when dispatching async -/// tasks. Until this limit, calls to `Io.async` when all threads are busy will -/// cause a new thread to be spawned and permanently added to the pool. After -/// this limit, calls to `Io.async` when all threads are busy run the task -/// immediately. -/// -/// Defaults to a number equal to logical CPU cores. -/// -/// Protected by `mutex` once the I/O instance is already in use. See -/// `setAsyncLimit`. async_limit: Io.Limit, -/// Maximum thread pool size (excluding main thread) for dispatching concurrent -/// tasks. Until this limit, calls to `Io.concurrent` will increase the thread -/// pool size. -/// -/// concurrent tasks. After this number, calls to `Io.concurrent` return -/// `error.ConcurrencyUnavailable`. concurrent_limit: Io.Limit = .unlimited, /// Error from calling `std.Thread.getCpuCount` in `init`. cpu_count_error: ?std.Thread.CpuCountError, @@ -50,6 +38,8 @@ cpu_count_error: ?std.Thread.CpuCountError, /// available count, subtract this from either `async_limit` or /// `concurrent_limit`. busy_count: usize = 0, +worker_threads: std.atomic.Value(?*Thread), +pid: Pid = .unknown, wsa: if (is_windows) Wsa else struct {} = .{}, @@ -57,6203 +47,16050 @@ have_signal_handler: bool, old_sig_io: if (have_sig_io) posix.Sigaction else void, old_sig_pipe: if (have_sig_pipe) posix.Sigaction else void, -threadlocal var current_closure: ?*Closure = null; +use_sendfile: UseSendfile = .default, +use_copy_file_range: UseCopyFileRange = .default, +use_fcopyfile: UseFcopyfile = .default, +use_fchmodat2: UseFchmodat2 = .default, -const max_iovecs_len = 8; -const splat_buffer_size = 64; +stderr_writer: File.Writer = .{ + .io = undefined, + .interface = Io.File.Writer.initInterface(&.{}), + .file = if (is_windows) undefined else .stderr(), + .mode = .streaming, +}, +stderr_mode: Io.Terminal.Mode = .no_color, +stderr_writer_initialized: bool = false, -comptime { - if (@TypeOf(posix.IOV_MAX) != void) assert(max_iovecs_len <= posix.IOV_MAX); -} +argv0: Argv0, +environ: Environ, -const CancelId = enum(usize) { - none = 0, - canceling = std.math.maxInt(usize), - _, +null_file: NullFile = .{}, +random_file: RandomFile = .{}, - const ThreadId = if (std.Thread.use_pthreads) std.c.pthread_t else std.Thread.Id; +csprng: Csprng = .{}, - fn currentThread() CancelId { - if (std.Thread.use_pthreads) { - return @enumFromInt(@intFromPtr(std.c.pthread_self())); - } else { - return @enumFromInt(std.Thread.getCurrentId()); - } +pub const Csprng = struct { + rng: std.Random.DefaultCsprng = .{ + .state = undefined, + .offset = std.math.maxInt(usize), + }, + + pub const seed_len = std.Random.DefaultCsprng.secret_seed_length; + + pub fn isInitialized(c: *const Csprng) bool { + return c.rng.offset != std.math.maxInt(usize); } +}; - fn toThreadId(cancel_id: CancelId) ThreadId { - if (std.Thread.use_pthreads) { - return @ptrFromInt(@intFromEnum(cancel_id)); - } else { - return @intCast(@intFromEnum(cancel_id)); +pub const Argv0 = switch (native_os) { + .openbsd, .haiku => struct { + value: ?[*:0]const u8, + + pub const empty: Argv0 = .{ .value = null }; + + pub fn init(args: process.Args) Argv0 { + return .{ .value = args.vector[0] }; } - } + }, + else => struct { + pub const empty: Argv0 = .{}; + + pub fn init(args: process.Args) Argv0 { + _ = args; + return .{}; + } + }, }; -const Closure = struct { - start: Start, - node: std.SinglyLinkedList.Node = .{}, - cancel_tid: CancelId, - - const Start = *const fn (*Closure) void; - - fn requestCancel(closure: *Closure) void { - switch (@atomicRmw(CancelId, &closure.cancel_tid, .Xchg, .canceling, .acq_rel)) { - .none, .canceling => {}, - else => |tid| { - if (std.Thread.use_pthreads) { - const rc = std.c.pthread_kill(tid.toThreadId(), .IO); - if (is_debug) assert(rc == 0); - } else if (native_os == .linux) { - _ = std.os.linux.tgkill(std.os.linux.getpid(), @bitCast(tid.toThreadId()), .IO); - } - }, +const Environ = struct { + /// Unmodified data directly from the OS. + process_environ: process.Environ = .empty, + /// Protected by `mutex`. Determines whether the other fields have been + /// memoized based on `process_environ`. + initialized: bool = false, + /// Protected by `mutex`. Memoized based on `process_environ`. Tracks whether the + /// environment variables are present, ignoring their value. + exist: Exist = .{}, + /// Protected by `mutex`. Memoized based on `process_environ`. + string: String = .{}, + /// ZIG_PROGRESS + zig_progress_handle: std.Progress.ParentFileError!u31 = error.EnvironmentVariableMissing, + /// Protected by `mutex`. Tracks the problem, if any, that occurred when + /// trying to scan environment variables. + /// + /// Errors are only possible on WASI. + err: ?Error = null, + + pub const Error = Allocator.Error || Io.UnexpectedError; + + pub const Exist = struct { + NO_COLOR: bool = false, + CLICOLOR_FORCE: bool = false, + }; + + pub const String = switch (native_os) { + .windows, .wasi => struct {}, + else => struct { + PATH: ?[:0]const u8 = null, + DEBUGINFOD_CACHE_PATH: ?[:0]const u8 = null, + XDG_CACHE_HOME: ?[:0]const u8 = null, + HOME: ?[:0]const u8 = null, + }, + }; +}; + +pub const NullFile = switch (native_os) { + .windows => struct { + handle: ?windows.HANDLE = null, + + fn deinit(this: *@This()) void { + if (this.handle) |handle| { + windows.CloseHandle(handle); + this.handle = null; + } } - } + }, + .wasi, .ios, .tvos, .visionos, .watchos => struct { + fn deinit(this: @This()) void { + _ = this; + } + }, + else => struct { + fd: posix.fd_t = -1, + + fn deinit(this: *@This()) void { + if (this.fd >= 0) { + posix.close(this.fd); + this.fd = -1; + } + } + }, }; -/// Related: -/// * `init_single_threaded` -pub fn init( - /// Must be threadsafe. Only used for the following functions: - /// * `Io.VTable.async` - /// * `Io.VTable.concurrent` - /// * `Io.VTable.groupAsync` - /// * `Io.VTable.groupConcurrent` - /// If these functions are avoided, then `Allocator.failing` may be passed - /// here. - gpa: Allocator, -) Threaded { - if (builtin.single_threaded) return .init_single_threaded; +pub const RandomFile = switch (native_os) { + .windows => NullFile, + else => if (use_dev_urandom) NullFile else struct { + fn deinit(this: @This()) void { + _ = this; + } + }, +}; - const cpu_count = std.Thread.getCpuCount(); +pub const Pid = if (native_os == .linux) enum(posix.pid_t) { + unknown = 0, + _, +} else enum(u0) { unknown = 0 }; + +pub const UseSendfile = if (have_sendfile) enum { + enabled, + disabled, + pub const default: UseSendfile = .enabled; +} else enum { + disabled, + pub const default: UseSendfile = .disabled; +}; - var t: Threaded = .{ - .allocator = gpa, - .stack_size = std.Thread.SpawnConfig.default_stack_size, - .async_limit = if (cpu_count) |n| .limited(n - 1) else |_| .nothing, - .cpu_count_error = if (cpu_count) |_| null else |e| e, - .old_sig_io = undefined, - .old_sig_pipe = undefined, - .have_signal_handler = false, +pub const UseCopyFileRange = if (have_copy_file_range) enum { + enabled, + disabled, + pub const default: UseCopyFileRange = .enabled; +} else enum { + disabled, + pub const default: UseCopyFileRange = .disabled; +}; + +pub const UseFcopyfile = if (have_fcopyfile) enum { + enabled, + disabled, + pub const default: UseFcopyfile = .enabled; +} else enum { + disabled, + pub const default: UseFcopyfile = .disabled; +}; + +pub const UseFchmodat2 = if (have_fchmodat2 and !have_fchmodat_flags) enum { + enabled, + disabled, + pub const default: UseFchmodat2 = .enabled; +} else enum { + disabled, + pub const default: UseFchmodat2 = .disabled; +}; + +const Runnable = struct { + node: std.SinglyLinkedList.Node, + startFn: *const fn (*Runnable, *Thread, *Threaded) void, +}; + +const Group = struct { + ptr: *Io.Group, + + /// Returns a correctly-typed pointer to the `Io.Group.token` field. + /// + /// The status indicates how many pending tasks are in the group, whether the group has been + /// canceled, and whether the group has been awaited. + /// + /// Note that the zero value of `Status` intentionally represents the initial group state (empty + /// with no awaiters). This is a requirement of `Io.Group`. + fn status(g: Group) *std.atomic.Value(Status) { + return @ptrCast(&g.ptr.token); + } + /// Returns a correctly-typed pointer to the `Io.Group.state` field. The double-pointer here is + /// intentional, because the `state` field itself stores a pointer, and this function returns a + /// pointer to that field. + /// + /// On completion of the whole group, if `status` indicates that there is an awaiter, the last + /// task must increment this `u32` and do a futex wake on it to signal that awaiter. + fn awaiter(g: Group) **std.atomic.Value(u32) { + return @ptrCast(&g.ptr.state); + } + + const Status = packed struct(usize) { + num_running: @Int(.unsigned, @bitSizeOf(usize) - 2), + have_awaiter: bool, + canceled: bool, }; - if (posix.Sigaction != void) { - // This causes sending `posix.SIG.IO` to thread to interrupt blocking - // syscalls, returning `posix.E.INTR`. - const act: posix.Sigaction = .{ - .handler = .{ .handler = doNothingSignalHandler }, - .mask = posix.sigemptyset(), - .flags = 0, - }; - if (have_sig_io) posix.sigaction(.IO, &act, &t.old_sig_io); - if (have_sig_pipe) posix.sigaction(.PIPE, &act, &t.old_sig_pipe); - t.have_signal_handler = true; + const Task = struct { + runnable: Runnable, + group: *Io.Group, + func: *const fn (context: *const anyopaque) Io.Cancelable!void, + context_alignment: Alignment, + alloc_len: usize, + + /// `Task.runnable.node` is `undefined` in the created `Task`. + fn create( + gpa: Allocator, + group: Group, + context: []const u8, + context_alignment: Alignment, + func: *const fn (context: *const anyopaque) Io.Cancelable!void, + ) Allocator.Error!*Task { + const max_context_misalignment = context_alignment.toByteUnits() -| @alignOf(Task); + const worst_case_context_offset = context_alignment.forward(@sizeOf(Task) + max_context_misalignment); + const alloc_len = worst_case_context_offset + context.len; + + const task: *Task = @ptrCast(@alignCast(try gpa.alignedAlloc(u8, .of(Task), alloc_len))); + errdefer comptime unreachable; + + task.* = .{ + .runnable = .{ + .node = undefined, + .startFn = &start, + }, + .group = group.ptr, + .func = func, + .context_alignment = context_alignment, + .alloc_len = alloc_len, + }; + @memcpy(task.contextPointer()[0..context.len], context); + return task; + } + + fn destroy(task: *Task, gpa: Allocator) void { + const base: [*]align(@alignOf(Task)) u8 = @ptrCast(task); + gpa.free(base[0..task.alloc_len]); + } + + fn contextPointer(task: *Task) [*]u8 { + const base: [*]u8 = @ptrCast(task); + const offset = task.context_alignment.forward(@intFromPtr(base) + @sizeOf(Task)) - @intFromPtr(base); + return base + offset; + } + + fn start(r: *Runnable, thread: *Thread, t: *Threaded) void { + const task: *Task = @fieldParentPtr("runnable", r); + const group: Group = .{ .ptr = task.group }; + + // This would be a simple store, but it's upgraded to an RMW so we can use `.acquire` to + // enforce the ordering between this and the `group.status().load` below. Paired with + // the `.release` rmw on `Thread.status` in `cancelThreads`, this creates a StoreLoad + // barrier which guarantees that when a group is canceled, either we see the cancelation + // in the group status, or the canceler sees our thread status so can directly notify us + // of the cancelation. + _ = thread.status.swap(.{ + .cancelation = .none, + .awaitable = .fromGroup(group.ptr), + }, .acquire); + if (group.status().load(.monotonic).canceled) { + thread.status.store(.{ + .cancelation = .canceling, + .awaitable = .fromGroup(group.ptr), + }, .monotonic); + } + + const result = task.func(task.contextPointer()); + const cancel_acknowledged = switch (thread.status.load(.monotonic).cancelation) { + .none, .canceling => false, + .canceled => true, + .parked => unreachable, + .blocked => unreachable, + .blocked_windows_dns => unreachable, + .blocked_canceling => unreachable, + }; + if (result) { + assert(!cancel_acknowledged); // group task acknowledged cancelation but did not return `error.Canceled` + } else |err| switch (err) { + error.Canceled => assert(cancel_acknowledged), // group task returned `error.Canceled` but was never canceled + } + + thread.status.store(.{ .cancelation = .none, .awaitable = .null }, .monotonic); + const old_status = group.status().fetchSub(.{ + .num_running = 1, + .have_awaiter = false, + .canceled = false, + }, .acq_rel); // acquire `group.awaiter()`, release task results + assert(old_status.num_running > 0); + if (old_status.have_awaiter and old_status.num_running == 1) { + const to_signal = group.awaiter().*; + // `awaiter` should only be modified by us. For another thread to see `num_running` + // drop to 0 after this point would indicate that another task started up, meaning + // `async`/`cancel` was racing with awaited group completion. + group.awaiter().* = undefined; + _ = to_signal.fetchAdd(1, .release); // release results + Thread.futexWake(&to_signal.raw, 1); + } + + // Task completed. Self-destruct sequence initiated. + task.destroy(t.allocator); + } + }; + + /// Assumes the caller has already atomically updated the group status to indicate cancelation, + /// and notifies any already-running threads of this cancelation. + fn cancelThreads(g: Group, t: *Threaded) bool { + var any_blocked = false; + var it = t.worker_threads.load(.acquire); // acquire `Thread` values + while (it) |thread| : (it = thread.next) { + // This non-mutating RMW exists for ordering reasons: see comment in `Group.Task.start` for reasons. + _ = thread.status.fetchOr(.{ .cancelation = @enumFromInt(0), .awaitable = .null }, .release); + if (thread.cancelAwaitable(.fromGroup(g.ptr))) any_blocked = true; + } + return any_blocked; } - return t; -} + /// Uses `Thread.signalCanceledSyscall` to signal any threads which are still blocked in a + /// syscall for this group and have not observed a cancelation request yet. Returns `true` if + /// more signals may be necessary, in which case the caller must call this again after a delay. + fn signalAllCanceledSyscalls(g: Group, t: *Threaded) bool { + var any_signaled = false; + var it = t.worker_threads.load(.acquire); // acquire `Thread` values + while (it) |thread| : (it = thread.next) { + if (thread.signalCanceledSyscall(t, .fromGroup(g.ptr))) any_signaled = true; + } + return any_signaled; + } -/// Statically initialize such that calls to `Io.VTable.concurrent` will fail -/// with `error.ConcurrencyUnavailable`. -/// -/// When initialized this way: -/// * cancel requests have no effect. -/// * `deinit` is safe, but unnecessary to call. -pub const init_single_threaded: Threaded = .{ - .allocator = .failing, - .stack_size = std.Thread.SpawnConfig.default_stack_size, - .async_limit = .nothing, - .cpu_count_error = null, - .concurrent_limit = .nothing, - .old_sig_io = undefined, - .old_sig_pipe = undefined, - .have_signal_handler = false, + /// The caller has canceled `g`. Inform any threads working on that group of the cancelation if + /// necessary, and wait for `g` to finish (indicated by `num_completed` being incremented from 0 + /// to 1), while sending regular signals to threads if necessary for them to unblock from any + /// cancelable syscalls. + /// + /// `skip_signals` means it is already known that no threads are currently working on the group + /// so no notifications or signals are necessary. + fn waitForCancelWithSignaling( + g: Group, + t: *Threaded, + num_completed: *std.atomic.Value(u32), + skip_signals: bool, + ) void { + var need_signal: bool = !skip_signals and g.cancelThreads(t); + var timeout_ns: u64 = 1 << 10; + while (true) { + need_signal = need_signal and g.signalAllCanceledSyscalls(t); + Thread.futexWaitUncancelable(&num_completed.raw, 0, if (need_signal) timeout_ns else null); + switch (num_completed.load(.acquire)) { // acquire task results + 0 => {}, + 1 => break, + else => unreachable, + } + timeout_ns <<|= 1; + } + } }; -pub fn setAsyncLimit(t: *Threaded, new_limit: Io.Limit) void { - t.mutex.lock(); - defer t.mutex.unlock(); - t.async_limit = new_limit; -} +/// Trailing data: +/// 1. context +/// 2. result +const Future = struct { + runnable: Runnable, + func: *const fn (context: *const anyopaque, result: *anyopaque) void, + status: std.atomic.Value(Status), + /// On completion, increment this `u32` and do a futex wake on it. + awaiter: *std.atomic.Value(u32), + context_alignment: Alignment, + result_offset: usize, + alloc_len: usize, -pub fn deinit(t: *Threaded) void { - t.join(); - if (is_windows and t.wsa.status == .initialized) { - if (ws2_32.WSACleanup() != 0) recoverableOsBugDetected(); + const Status = packed struct(usize) { + /// The values of this enum are chosen so that await/cancel can just OR with 0b01 and 0b11 + /// respectively. That *does* clobber `.done`, but that's actually fine, because if the tag + /// is `.done` then only the awaiter is referencing this `Future` anyway. + tag: enum(u2) { + /// The future is queued or running (depending on whether `thread` is set). + pending = 0b00, + /// Like `pending`, but the future is being awaited. `Future.awaiter` is populated. + pending_awaited = 0b01, + /// Like `pending`, but the future is being canceled. `Future.awaiter` is populated. + pending_canceled = 0b11, + /// The future has already completed. `thread` is `.null`, unless the future terminated + /// with an acknowledged cancel request, in which case `thread` is `.all_ones`. + done = 0b10, + }, + /// When the future begins execution, this is atomically updated from `null` to the thread running the + /// `Future`, so that cancelation knows which thread to cancel. + thread: Thread.PackedPtr, + }; + + /// `Future.runnable.node` is `undefined` in the created `Future`. + fn create( + gpa: Allocator, + result_len: usize, + result_alignment: Alignment, + context: []const u8, + context_alignment: Alignment, + func: *const fn (context: *const anyopaque, result: *anyopaque) void, + ) Allocator.Error!*Future { + const max_context_misalignment = context_alignment.toByteUnits() -| @alignOf(Future); + const worst_case_context_offset = context_alignment.forward(@sizeOf(Future) + max_context_misalignment); + const worst_case_result_offset = result_alignment.forward(worst_case_context_offset + context.len); + const alloc_len = worst_case_result_offset + result_len; + + const future: *Future = @ptrCast(@alignCast(try gpa.alignedAlloc(u8, .of(Future), alloc_len))); + errdefer comptime unreachable; + + const actual_context_addr = context_alignment.forward(@intFromPtr(future) + @sizeOf(Future)); + const actual_result_addr = result_alignment.forward(actual_context_addr + context.len); + const actual_result_offset = actual_result_addr - @intFromPtr(future); + future.* = .{ + .runnable = .{ + .node = undefined, + .startFn = &start, + }, + .func = func, + .status = .init(.{ + .tag = .pending, + .thread = .null, + }), + .awaiter = undefined, + .context_alignment = context_alignment, + .result_offset = actual_result_offset, + .alloc_len = alloc_len, + }; + @memcpy(future.contextPointer()[0..context.len], context); + return future; } - if (posix.Sigaction != void and t.have_signal_handler) { - if (have_sig_io) posix.sigaction(.IO, &t.old_sig_io, null); - if (have_sig_pipe) posix.sigaction(.PIPE, &t.old_sig_pipe, null); + + fn destroy(future: *Future, gpa: Allocator) void { + const base: [*]align(@alignOf(Future)) u8 = @ptrCast(future); + gpa.free(base[0..future.alloc_len]); } - t.* = undefined; -} -fn join(t: *Threaded) void { - if (builtin.single_threaded) return; - { - t.mutex.lock(); - defer t.mutex.unlock(); - t.join_requested = true; + fn resultPointer(future: *Future) [*]u8 { + const base: [*]u8 = @ptrCast(future); + return base + future.result_offset; } - t.cond.broadcast(); - t.wait_group.wait(); -} -fn worker(t: *Threaded) void { - defer t.wait_group.finish(); + fn contextPointer(future: *Future) [*]u8 { + const base: [*]u8 = @ptrCast(future); + const context_offset = future.context_alignment.forward(@intFromPtr(future) + @sizeOf(Future)) - @intFromPtr(future); + return base + context_offset; + } - t.mutex.lock(); - defer t.mutex.unlock(); + fn start(r: *Runnable, thread: *Thread, t: *Threaded) void { + _ = t; + const future: *Future = @fieldParentPtr("runnable", r); - while (true) { - while (t.run_queue.popFirst()) |closure_node| { - t.mutex.unlock(); - const closure: *Closure = @fieldParentPtr("node", closure_node); - closure.start(closure); - t.mutex.lock(); - t.busy_count -= 1; + thread.status.store(.{ + .cancelation = .none, + .awaitable = .fromFuture(future), + }, .monotonic); + { + const old_status = future.status.fetchOr(.{ + .tag = .pending, + .thread = .pack(thread), + }, .release); + assert(old_status.thread == .null); + switch (old_status.tag) { + .pending, .pending_awaited => {}, + .pending_canceled => thread.status.store(.{ + .cancelation = .canceling, + .awaitable = .fromFuture(future), + }, .monotonic), + .done => unreachable, + } + } + + future.func(future.contextPointer(), future.resultPointer()); + + const had_acknowledged_cancel = switch (thread.status.load(.monotonic).cancelation) { + .none, .canceling => false, + .canceled => true, + .parked => unreachable, + .blocked => unreachable, + .blocked_windows_dns => unreachable, + .blocked_canceling => unreachable, + }; + thread.status.store(.{ .cancelation = .none, .awaitable = .null }, .monotonic); + const old_status = future.status.swap(.{ + .tag = .done, + .thread = if (had_acknowledged_cancel) .all_ones else .null, + }, .acq_rel); // acquire `future.awaiter`, release results + switch (old_status.tag) { + .pending => {}, + .pending_awaited, .pending_canceled => { + const to_signal = future.awaiter; + _ = to_signal.fetchAdd(1, .release); // release results + Thread.futexWake(&to_signal.raw, 1); + }, + .done => unreachable, } - if (t.join_requested) break; - t.cond.wait(&t.mutex); } -} -pub fn io(t: *Threaded) Io { - return .{ - .userdata = t, - .vtable = &.{ - .async = async, - .concurrent = concurrent, - .await = await, - .cancel = cancel, - .cancelRequested = cancelRequested, - .select = select, + /// The caller has canceled `future`. `thread` is the thread currently running that future. + /// Inform `thread` of the cancelation if necessary, and wait for `future` to finish (indicated + /// by `num_completed` being incremented from 0 to 1), while sending regular signals to `thread` + /// if necessary for it to unblock from a cancelable syscall. + fn waitForCancelWithSignaling( + future: *Future, + t: *Threaded, + num_completed: *std.atomic.Value(u32), + thread: ?*Thread, + ) void { + var need_signal: bool = thread != null and thread.?.cancelAwaitable(.fromFuture(future)); + var timeout_ns: u64 = 1 << 10; + while (true) { + need_signal = need_signal and thread.?.signalCanceledSyscall(t, .fromFuture(future)); + Thread.futexWaitUncancelable(&num_completed.raw, 0, if (need_signal) timeout_ns else null); + switch (num_completed.load(.acquire)) { // acquire task results + 0 => {}, + 1 => break, + else => unreachable, + } + timeout_ns <<|= 1; + } + } +}; - .groupAsync = groupAsync, - .groupConcurrent = groupConcurrent, - .groupWait = groupWait, - .groupCancel = groupCancel, +/// A sequence of (ptr_bit_width - 3) bits which uniquely identifies a group or future. The bits are +/// the MSBs of the `*Io.Group` or `*Future`. These things do not necessarily have 3 zero bits at +/// the end (they are pointer-aligned, so on 32-bit targets only have 2), but because they both have +/// a *size* of at least 8 bytes, no two groups/futures in memory at the same time will have the +/// same value for all of these bits. In other words, given a group/future pointer, the next group +/// or future must be at least 8 bytes later, so its address will have a different value for one of +/// the top (ptr_bit_width - 3) bits. +const AwaitableId = enum(@Int(.unsigned, @bitSizeOf(usize) - 3)) { + comptime { + assert(@sizeOf(Future) >= 8); + assert(@sizeOf(Io.Group) >= 8); + } + null = 0, + all_ones = std.math.maxInt(@Int(.unsigned, @bitSizeOf(usize) - 3)), + _, + const Split = packed struct(usize) { low: u3, high: AwaitableId }; + fn fromGroup(g: *Io.Group) AwaitableId { + const split: Split = @bitCast(@intFromPtr(g)); + return split.high; + } + fn fromFuture(f: *Future) AwaitableId { + const split: Split = @bitCast(@intFromPtr(f)); + return split.high; + } +}; - .mutexLock = mutexLock, - .mutexLockUncancelable = mutexLockUncancelable, - .mutexUnlock = mutexUnlock, +const Thread = struct { + next: ?*Thread, - .conditionWait = conditionWait, - .conditionWaitUncancelable = conditionWaitUncancelable, - .conditionWake = conditionWake, + id: std.Thread.Id, + handle: Handle, - .dirMake = dirMake, - .dirMakePath = dirMakePath, - .dirMakeOpenPath = dirMakeOpenPath, - .dirStat = dirStat, - .dirStatPath = dirStatPath, - .fileStat = fileStat, - .dirAccess = dirAccess, - .dirCreateFile = dirCreateFile, - .dirOpenFile = dirOpenFile, - .dirOpenDir = dirOpenDir, - .dirClose = dirClose, - .fileClose = fileClose, - .fileWriteStreaming = fileWriteStreaming, - .fileWritePositional = fileWritePositional, - .fileReadStreaming = fileReadStreaming, - .fileReadPositional = fileReadPositional, - .fileSeekBy = fileSeekBy, - .fileSeekTo = fileSeekTo, - .openSelfExe = openSelfExe, + status: std.atomic.Value(Status), - .now = now, - .sleep = sleep, + cancel_protection: Io.CancelProtection, + /// Always released when `Status.cancelation` is set to `.parked`. + futex_waiter: if (use_parking_futex) ?*parking_futex.Waiter else ?noreturn, - .netListenIp = switch (native_os) { - .windows => netListenIpWindows, - else => netListenIpPosix, - }, - .netListenUnix = switch (native_os) { - .windows => netListenUnixWindows, - else => netListenUnixPosix, - }, - .netAccept = switch (native_os) { - .windows => netAcceptWindows, - else => netAcceptPosix, - }, - .netBindIp = switch (native_os) { - .windows => netBindIpWindows, - else => netBindIpPosix, - }, - .netConnectIp = switch (native_os) { - .windows => netConnectIpWindows, - else => netConnectIpPosix, - }, - .netConnectUnix = switch (native_os) { - .windows => netConnectUnixWindows, - else => netConnectUnixPosix, - }, - .netClose = netClose, - .netRead = switch (native_os) { - .windows => netReadWindows, - else => netReadPosix, - }, - .netWrite = switch (native_os) { - .windows => netWriteWindows, - else => netWritePosix, - }, - .netSend = switch (native_os) { - .windows => netSendWindows, - else => netSendPosix, - }, - .netReceive = switch (native_os) { - .windows => netReceiveWindows, - else => netReceivePosix, - }, - .netInterfaceNameResolve = netInterfaceNameResolve, - .netInterfaceName = netInterfaceName, - .netLookup = netLookup, - }, - }; -} - -/// Same as `io` but disables all networking functionality, which has -/// an additional dependency on Windows (ws2_32). -pub fn ioBasic(t: *Threaded) Io { - return .{ - .userdata = t, - .vtable = &.{ - .async = async, - .concurrent = concurrent, - .await = await, - .cancel = cancel, - .cancelRequested = cancelRequested, - .select = select, - - .groupAsync = groupAsync, - .groupConcurrent = groupConcurrent, - .groupWait = groupWait, - .groupCancel = groupCancel, - - .mutexLock = mutexLock, - .mutexLockUncancelable = mutexLockUncancelable, - .mutexUnlock = mutexUnlock, - - .conditionWait = conditionWait, - .conditionWaitUncancelable = conditionWaitUncancelable, - .conditionWake = conditionWake, - - .dirMake = dirMake, - .dirMakePath = dirMakePath, - .dirMakeOpenPath = dirMakeOpenPath, - .dirStat = dirStat, - .dirStatPath = dirStatPath, - .fileStat = fileStat, - .dirAccess = dirAccess, - .dirCreateFile = dirCreateFile, - .dirOpenFile = dirOpenFile, - .dirOpenDir = dirOpenDir, - .dirClose = dirClose, - .fileClose = fileClose, - .fileWriteStreaming = fileWriteStreaming, - .fileWritePositional = fileWritePositional, - .fileReadStreaming = fileReadStreaming, - .fileReadPositional = fileReadPositional, - .fileSeekBy = fileSeekBy, - .fileSeekTo = fileSeekTo, - .openSelfExe = openSelfExe, - - .now = now, - .sleep = sleep, + csprng: Csprng, - .netListenIp = netListenIpUnavailable, - .netListenUnix = netListenUnixUnavailable, - .netAccept = netAcceptUnavailable, - .netBindIp = netBindIpUnavailable, - .netConnectIp = netConnectIpUnavailable, - .netConnectUnix = netConnectUnixUnavailable, - .netClose = netCloseUnavailable, - .netRead = netReadUnavailable, - .netWrite = netWriteUnavailable, - .netSend = netSendUnavailable, - .netReceive = netReceiveUnavailable, - .netInterfaceNameResolve = netInterfaceNameResolveUnavailable, - .netInterfaceName = netInterfaceNameUnavailable, - .netLookup = netLookupUnavailable, - }, + const Handle = Handle: { + if (std.Thread.use_pthreads) break :Handle std.c.pthread_t; + if (builtin.target.os.tag == .windows) break :Handle windows.HANDLE; + break :Handle void; }; -} - -pub const socket_flags_unsupported = native_os.isDarwin() or native_os == .haiku; -const have_accept4 = !socket_flags_unsupported; -const have_flock_open_flags = @hasField(posix.O, "EXLOCK"); -const have_networking = native_os != .wasi; -const have_flock = @TypeOf(posix.system.flock) != void; -const have_sendmmsg = native_os == .linux; -const have_futex = switch (builtin.cpu.arch) { - .wasm32, .wasm64 => builtin.cpu.has(.wasm, .atomics), - else => true, -}; -const have_preadv = switch (native_os) { - .windows, .haiku => false, - else => true, -}; -const have_sig_io = posix.SIG != void and @hasField(posix.SIG, "IO"); -const have_sig_pipe = posix.SIG != void and @hasField(posix.SIG, "PIPE"); -const openat_sym = if (posix.lfs64_abi) posix.system.openat64 else posix.system.openat; -const fstat_sym = if (posix.lfs64_abi) posix.system.fstat64 else posix.system.fstat; -const fstatat_sym = if (posix.lfs64_abi) posix.system.fstatat64 else posix.system.fstatat; -const lseek_sym = if (posix.lfs64_abi) posix.system.lseek64 else posix.system.lseek; -const preadv_sym = if (posix.lfs64_abi) posix.system.preadv64 else posix.system.preadv; + const Status = packed struct(usize) { + /// The specific values of these enum fields are chosen to simplify the implementation of + /// the transformations we need to apply to this state. + cancelation: enum(u3) { + /// The thread has not yet been canceled, and is not in a cancelable operation. + /// To request cancelation, just set the status to `.canceling`. + none = 0b000, + + /// The thread is parked in a cancelable futex wait or sleep. + /// Only applicable if `use_parking_futex` or `use_parking_sleep`. + /// To request cancelation, set the status to `.canceling` and unpark the thread. + /// To unpark for another reason (futex wake), set the status to `.none` and unpark the thread. + parked = 0b001, + + /// The thread is blocked in a cancelable system call. + /// To request cancelation, set the status to `.blocked_canceling` and repeatedly interrupt the system call until the status changes. + blocked = 0b011, + + /// Windows-only: the thread is blocked in a call to `GetAddrInfoExW`. + /// To request cancelation, set the status to `.canceling` and call `GetAddrInfoExCancel`. + blocked_windows_dns = 0b010, + + /// The thread has an outstanding cancelation request but is not in a cancelable operation. + /// When it acknowledges the cancelation, it will set the status to `.canceled`. + canceling = 0b110, + + /// The thread has received and acknowledged a cancelation request. + /// If `recancel` is called, the status will revert to `.canceling`, but otherwise, the status + /// will not change for the remainder of this task's execution. + canceled = 0b111, + + /// The thread is blocked in a cancelable system call, and is being canceled. The thread which triggered the cancelation will send signals to this thread + /// until its status changes. + blocked_canceling = 0b101, + }, -/// Trailing data: -/// 1. context -/// 2. result -const AsyncClosure = struct { - closure: Closure, - func: *const fn (context: *anyopaque, result: *anyopaque) void, - reset_event: ResetEvent, - select_condition: ?*ResetEvent, - context_alignment: Alignment, - result_offset: usize, - alloc_len: usize, + /// We cannot turn this value back into a pointer. Instead, it exists so that a task can be + /// canceled by a cmpxchg on thread status: if it is running the task we want to cancel, + /// then update the `cancelation` field. + awaitable: AwaitableId, + }; - const done_reset_event: *ResetEvent = @ptrFromInt(@alignOf(ResetEvent)); + const SignaleeId = if (std.Thread.use_pthreads) std.c.pthread_t else std.Thread.Id; - fn start(closure: *Closure) void { - const ac: *AsyncClosure = @alignCast(@fieldParentPtr("closure", closure)); - const tid: CancelId = .currentThread(); - if (@cmpxchgStrong(CancelId, &closure.cancel_tid, .none, tid, .acq_rel, .acquire)) |cancel_tid| { - assert(cancel_tid == .canceling); - // Even though we already know the task is canceled, we must still - // run the closure in order to make the return value valid and in - // case there are side effects. - } - current_closure = closure; - ac.func(ac.contextPointer(), ac.resultPointer()); - current_closure = null; + threadlocal var current: ?*Thread = null; - // In case a cancel happens after successful task completion, prevents - // signal from being delivered to the thread in `requestCancel`. - if (@cmpxchgStrong(CancelId, &closure.cancel_tid, tid, .none, .acq_rel, .acquire)) |cancel_tid| { - assert(cancel_tid == .canceling); + /// The thread is neither in a syscall nor entering one, but we want to check for cancelation + /// anyway. If there is a pending cancel request, acknowledge it and return `error.Canceled`. + fn checkCancel() Io.Cancelable!void { + const thread = Thread.current orelse return; + switch (thread.cancel_protection) { + .blocked => return, + .unblocked => {}, } - - if (@atomicRmw(?*ResetEvent, &ac.select_condition, .Xchg, done_reset_event, .release)) |select_reset| { - assert(select_reset != done_reset_event); - select_reset.set(); + // Here, unlike `Syscall.checkCancel`, it's not particularly likely that we're canceled, so + // it seems preferable to do a cheap atomic load and, in the unlikely case, a separate store + // to acknowledge. Besides, the state transitions we need here can't be done with one atomic + // OR/AND/XOR on `Status.cancelation`, so we don't actually have any other option. + const status = thread.status.load(.monotonic); + switch (status.cancelation) { + .parked => unreachable, + .blocked => unreachable, + .blocked_windows_dns => unreachable, + .blocked_canceling => unreachable, + .none, .canceled => {}, + .canceling => { + thread.status.store(.{ + .cancelation = .canceled, + .awaitable = status.awaitable, + }, .monotonic); + return error.Canceled; + }, } - ac.reset_event.set(); } - fn resultPointer(ac: *AsyncClosure) [*]u8 { - const base: [*]u8 = @ptrCast(ac); - return base + ac.result_offset; + fn futexWaitUncancelable(ptr: *const u32, expect: u32, timeout_ns: ?u64) void { + return Thread.futexWaitInner(ptr, expect, true, timeout_ns) catch unreachable; } - fn contextPointer(ac: *AsyncClosure) [*]u8 { - const base: [*]u8 = @ptrCast(ac); - const context_offset = ac.context_alignment.forward(@intFromPtr(ac) + @sizeOf(AsyncClosure)) - @intFromPtr(ac); - return base + context_offset; + fn futexWait(ptr: *const u32, expect: u32, timeout_ns: ?u64) Io.Cancelable!void { + return Thread.futexWaitInner(ptr, expect, false, timeout_ns); } - fn init( - gpa: Allocator, - result_len: usize, - result_alignment: Alignment, - context: []const u8, - context_alignment: Alignment, - func: *const fn (context: *const anyopaque, result: *anyopaque) void, - ) Allocator.Error!*AsyncClosure { - const max_context_misalignment = context_alignment.toByteUnits() -| @alignOf(AsyncClosure); - const worst_case_context_offset = context_alignment.forward(@sizeOf(AsyncClosure) + max_context_misalignment); - const worst_case_result_offset = result_alignment.forward(worst_case_context_offset + context.len); - const alloc_len = worst_case_result_offset + result_len; + fn futexWaitInner(ptr: *const u32, expect: u32, uncancelable: bool, timeout_ns: ?u64) Io.Cancelable!void { + @branchHint(.cold); - const ac: *AsyncClosure = @ptrCast(@alignCast(try gpa.alignedAlloc(u8, .of(AsyncClosure), alloc_len))); - errdefer comptime unreachable; + if (builtin.single_threaded) unreachable; // nobody would ever wake us - const actual_context_addr = context_alignment.forward(@intFromPtr(ac) + @sizeOf(AsyncClosure)); - const actual_result_addr = result_alignment.forward(actual_context_addr + context.len); - const actual_result_offset = actual_result_addr - @intFromPtr(ac); - ac.* = .{ - .closure = .{ - .cancel_tid = .none, - .start = start, + if (use_parking_futex) { + return parking_futex.wait( + ptr, + expect, + uncancelable, + if (timeout_ns) |ns| .{ .duration = .{ + .raw = .fromNanoseconds(ns), + .clock = .boot, + } } else .none, + ); + } else if (builtin.cpu.arch.isWasm()) { + comptime assert(builtin.cpu.has(.wasm, .atomics)); + // TODO implement cancelation for WASM futex waits by signaling the futex + if (!uncancelable) try Thread.checkCancel(); + const to: i64 = if (timeout_ns) |ns| ns else -1; + const signed_expect: i32 = @bitCast(expect); + const result = asm volatile ( + \\local.get %[ptr] + \\local.get %[expected] + \\local.get %[timeout] + \\memory.atomic.wait32 0 + \\local.set %[ret] + : [ret] "=r" (-> u32), + : [ptr] "r" (ptr), + [expected] "r" (signed_expect), + [timeout] "r" (to), + ); + switch (result) { + 0 => {}, // ok + 1 => {}, // expected != loaded + 2 => {}, // timeout + else => assert(!is_debug), + } + } else switch (native_os) { + .linux => { + const linux = std.os.linux; + var ts_buffer: linux.timespec = undefined; + const ts: ?*linux.timespec = if (timeout_ns) |ns| ts: { + ts_buffer = timestampToPosix(ns); + break :ts &ts_buffer; + } else null; + const syscall: Syscall = if (uncancelable) .{ .thread = null } else try .start(); + const rc = linux.futex_4arg(ptr, .{ .cmd = .WAIT, .private = true }, expect, ts); + syscall.finish(); + switch (linux.errno(rc)) { + .SUCCESS => {}, // notified by `wake()` + .INTR => {}, // caller's responsibility to retry + .AGAIN => {}, // ptr.* != expect + .INVAL => {}, // possibly timeout overflow + .TIMEDOUT => {}, + .FAULT => recoverableOsBugDetected(), // ptr was invalid + else => recoverableOsBugDetected(), + } }, - .func = func, - .context_alignment = context_alignment, - .result_offset = actual_result_offset, - .alloc_len = alloc_len, - .reset_event = .unset, - .select_condition = null, - }; - @memcpy(ac.contextPointer()[0..context.len], context); - return ac; - } - - fn waitAndDeinit(ac: *AsyncClosure, t: *Threaded, result: []u8) void { - ac.reset_event.wait(t) catch |err| switch (err) { - error.Canceled => { - ac.closure.requestCancel(); - ac.reset_event.waitUncancelable(); + .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => { + const c = std.c; + const flags: c.UL = .{ + .op = .COMPARE_AND_WAIT, + .NO_ERRNO = true, + }; + const syscall: Syscall = if (uncancelable) .{ .thread = null } else try .start(); + const status = switch (darwin_supports_ulock_wait2) { + true => c.__ulock_wait2(flags, ptr, expect, ns: { + const ns = timeout_ns orelse break :ns 0; + if (ns == 0) break :ns 1; + break :ns ns; + }, 0), + false => c.__ulock_wait(flags, ptr, expect, us: { + const ns = timeout_ns orelse break :us 0; + const us = std.math.lossyCast(u32, ns / std.time.ns_per_us); + if (us == 0) break :us 1; + break :us us; + }), + }; + syscall.finish(); + if (status >= 0) return; + switch (@as(c.E, @enumFromInt(-status))) { + .INTR => {}, // spurious wake + // Address of the futex was paged out. This is unlikely, but possible in theory, and + // pthread/libdispatch on darwin bother to handle it. In this case we'll return + // without waiting, but the caller should retry anyway. + .FAULT => {}, + .TIMEDOUT => {}, // timeout + else => recoverableOsBugDetected(), + } }, - }; - @memcpy(result, ac.resultPointer()[0..result.len]); - ac.deinit(t.allocator); + .freebsd => { + const flags = @intFromEnum(std.c.UMTX_OP.WAIT_UINT_PRIVATE); + var tm_size: usize = 0; + var tm: std.c._umtx_time = undefined; + var tm_ptr: ?*const std.c._umtx_time = null; + if (timeout_ns) |ns| { + tm_ptr = &tm; + tm_size = @sizeOf(@TypeOf(tm)); + tm.flags = 0; // use relative time not UMTX_ABSTIME + tm.clockid = .MONOTONIC; + tm.timeout = timestampToPosix(ns); + } + const syscall: Syscall = if (uncancelable) .{ .thread = null } else try .start(); + const rc = std.c._umtx_op(@intFromPtr(ptr), flags, @as(c_ulong, expect), tm_size, @intFromPtr(tm_ptr)); + syscall.finish(); + if (is_debug) switch (posix.errno(rc)) { + .SUCCESS => {}, + .FAULT => unreachable, // one of the args points to invalid memory + .INVAL => unreachable, // arguments should be correct + .TIMEDOUT => {}, // timeout + .INTR => {}, // spurious wake + else => unreachable, + }; + }, + .openbsd => { + var tm: std.c.timespec = undefined; + var tm_ptr: ?*const std.c.timespec = null; + if (timeout_ns) |ns| { + tm_ptr = &tm; + tm = timestampToPosix(ns); + } + const syscall: Syscall = if (uncancelable) .{ .thread = null } else try .start(); + const rc = std.c.futex( + ptr, + std.c.FUTEX.WAIT | std.c.FUTEX.PRIVATE_FLAG, + @as(c_int, @bitCast(expect)), + tm_ptr, + null, // uaddr2 is ignored + ); + syscall.finish(); + if (is_debug) switch (posix.errno(rc)) { + .SUCCESS => {}, + .NOSYS => unreachable, // constant op known good value + .AGAIN => {}, // contents of uaddr != val + .INVAL => unreachable, // invalid timeout + .TIMEDOUT => {}, // timeout + .INTR => {}, // a signal arrived + .CANCELED => {}, // a signal arrived and SA_RESTART was set + else => unreachable, + }; + }, + .dragonfly => { + var timeout_us: c_int = undefined; + if (timeout_ns) |ns| { + timeout_us = std.math.cast(c_int, ns / std.time.ns_per_us) orelse std.math.maxInt(c_int); + } else { + timeout_us = 0; + } + const syscall: Syscall = if (uncancelable) .{ .thread = null } else try .start(); + const rc = std.c.umtx_sleep(@ptrCast(ptr), @bitCast(expect), timeout_us); + syscall.finish(); + if (is_debug) switch (std.posix.errno(rc)) { + .SUCCESS => {}, + .BUSY => {}, // ptr != expect + .AGAIN => {}, // maybe timed out, or paged out, or hit 2s kernel refresh + .INTR => {}, // spurious wake + .INVAL => unreachable, // invalid timeout + else => unreachable, + }; + }, + else => @compileError("unimplemented: futexWait"), + } } - fn deinit(ac: *AsyncClosure, gpa: Allocator) void { - const base: [*]align(@alignOf(AsyncClosure)) u8 = @ptrCast(ac); - gpa.free(base[0..ac.alloc_len]); - } -}; + fn futexWake(ptr: *const u32, max_waiters: u32) void { + @branchHint(.cold); + assert(max_waiters != 0); -fn async( - userdata: ?*anyopaque, - result: []u8, - result_alignment: Alignment, - context: []const u8, - context_alignment: Alignment, - start: *const fn (context: *const anyopaque, result: *anyopaque) void, -) ?*Io.AnyFuture { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - if (builtin.single_threaded) { - start(context.ptr, result.ptr); - return null; + if (builtin.single_threaded) return; // nothing to wake up + + if (use_parking_futex) { + return parking_futex.wake(ptr, max_waiters); + } else if (builtin.cpu.arch.isWasm()) { + comptime assert(builtin.cpu.has(.wasm, .atomics)); + const woken_count = asm volatile ( + \\local.get %[ptr] + \\local.get %[waiters] + \\memory.atomic.notify 0 + \\local.set %[ret] + : [ret] "=r" (-> u32), + : [ptr] "r" (ptr), + [waiters] "r" (max_waiters), + ); + _ = woken_count; // can be 0 when linker flag 'shared-memory' is not enabled + } else switch (native_os) { + .linux => { + const linux = std.os.linux; + switch (linux.errno(linux.futex_3arg( + ptr, + .{ .cmd = .WAKE, .private = true }, + @min(max_waiters, std.math.maxInt(i32)), + ))) { + .SUCCESS => return, // successful wake up + .INVAL => return, // invalid futex_wait() on ptr done elsewhere + .FAULT => return, // pointer became invalid while doing the wake + else => return recoverableOsBugDetected(), // deadlock due to operating system bug + } + }, + .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => { + const c = std.c; + const flags: c.UL = .{ + .op = .COMPARE_AND_WAIT, + .NO_ERRNO = true, + .WAKE_ALL = max_waiters > 1, + }; + while (true) { + const status = c.__ulock_wake(flags, ptr, 0); + if (status >= 0) return; + switch (@as(c.E, @enumFromInt(-status))) { + .INTR, .CANCELED => continue, // spurious wake() + .FAULT => unreachable, // __ulock_wake doesn't generate EFAULT according to darwin pthread_cond_t + .NOENT => return, // nothing was woken up + .ALREADY => unreachable, // only for UL.Op.WAKE_THREAD + else => unreachable, // deadlock due to operating system bug + } + } + }, + .freebsd => { + const rc = std.c._umtx_op( + @intFromPtr(ptr), + @intFromEnum(std.c.UMTX_OP.WAKE_PRIVATE), + @as(c_ulong, max_waiters), + 0, // there is no timeout struct + 0, // there is no timeout struct pointer + ); + switch (posix.errno(rc)) { + .SUCCESS => {}, + .FAULT => {}, // it's ok if the ptr doesn't point to valid memory + .INVAL => unreachable, // arguments should be correct + else => unreachable, // deadlock due to operating system bug + } + }, + .openbsd => { + const rc = std.c.futex( + ptr, + std.c.FUTEX.WAKE | std.c.FUTEX.PRIVATE_FLAG, + @min(max_waiters, std.math.maxInt(c_int)), + null, // timeout is ignored + null, // uaddr2 is ignored + ); + assert(rc >= 0); + }, + .dragonfly => { + // will generally return 0 unless the address is bad + _ = std.c.umtx_wakeup( + @ptrCast(ptr), + @min(max_waiters, std.math.maxInt(c_int)), + ); + }, + else => @compileError("unimplemented: futexWake"), + } } - const gpa = t.allocator; - const ac = AsyncClosure.init(gpa, result.len, result_alignment, context, context_alignment, start) catch { - start(context.ptr, result.ptr); - return null; - }; - t.mutex.lock(); + /// Cancels `thread` if it is working on `awaitable`. + /// + /// It is possible that `thread` gets canceled by this function, but is blocked in a syscall. In + /// that case, the thread may need to be sent a signal to interrupt the call. This function will + /// return `true` to indicate this, in which case the caller must call `signalCanceledSyscall`. + fn cancelAwaitable(thread: *Thread, awaitable: AwaitableId) bool { + var status = thread.status.load(.monotonic); + while (true) { + if (status.awaitable != awaitable) return false; // thread is working on something else + status = switch (status.cancelation) { + .none => thread.status.cmpxchgWeak( + .{ .cancelation = .none, .awaitable = awaitable }, + .{ .cancelation = .canceling, .awaitable = awaitable }, + .monotonic, + .monotonic, + ) orelse return false, + + .parked => thread.status.cmpxchgWeak( + .{ .cancelation = .parked, .awaitable = awaitable }, + .{ .cancelation = .canceling, .awaitable = awaitable }, + .acquire, // acquire `thread.futex_waiter` + .monotonic, + ) orelse { + if (!use_parking_futex and !use_parking_sleep) unreachable; + if (thread.futex_waiter) |futex_waiter| { + parking_futex.removeCanceledWaiter(futex_waiter); + } + unpark(&.{thread.id}, null); + return false; + }, - const busy_count = t.busy_count; + .blocked => thread.status.cmpxchgWeak( + .{ .cancelation = .blocked, .awaitable = awaitable }, + .{ .cancelation = .blocked_canceling, .awaitable = awaitable }, + .monotonic, + .monotonic, + ) orelse return true, + + .blocked_windows_dns => thread.status.cmpxchgWeak( + .{ .cancelation = .blocked_windows_dns, .awaitable = awaitable }, + .{ .cancelation = .canceling, .awaitable = awaitable }, + .monotonic, + .monotonic, + ) orelse { + if (builtin.target.os.tag != .windows) unreachable; + if (true) { + // TODO: cancel Windows DNS queries. This code path is currently impossible + // as `netLookupFallible` doesn't actually use `.blocked_windows_dns` yet. + unreachable; + } + return false; + }, - if (busy_count >= @intFromEnum(t.async_limit)) { - t.mutex.unlock(); - ac.deinit(gpa); - start(context.ptr, result.ptr); - return null; + .canceling, .canceled => { + // This can happen when the task start raced with the cancelation, so the thread + // saw the cancelation on the future/group *and* we are trying to signal the + // thread here. + return false; + }, + + .blocked_canceling => unreachable, + }; + } } - t.busy_count = busy_count + 1; + /// Sends a signal to `thread` if it is still blocked in a syscall (i.e. has not yet observed + /// the cancelation request from `cancelAwaitable`). + /// + /// Unfortunately, the signal could arrive before the syscall actually starts, so the interrupt + /// is missed. To handle this, we may need to send multiple signals. As such, if this function + /// returns `true`, then it should be called again after a short delay to send another signal if + /// the thread is still blocked. For the implementation, `Future.waitForCancelWithSignaling` and + /// `Group.waitForCancelWithSignaling`: they use exponential backoff starting at a 1us delay and + /// doubling each call. In practice, it is rare to send more than one signal. + fn signalCanceledSyscall(thread: *Thread, t: *Threaded, awaitable: AwaitableId) bool { + const bad_status: Status = .{ .cancelation = .blocked_canceling, .awaitable = awaitable }; + if (thread.status.load(.monotonic) != bad_status) return false; + + // The thread ID and/or handle can be read non-atomically because they never change and were + // released by the store that made `thread` available to us. - const pool_size = t.wait_group.value(); - if (pool_size - busy_count == 0) { - t.wait_group.start(); - const thread = std.Thread.spawn(.{ .stack_size = t.stack_size }, worker, .{t}) catch { - t.wait_group.finish(); - t.busy_count = busy_count; - t.mutex.unlock(); - ac.deinit(gpa); - start(context.ptr, result.ptr); - return null; - }; - thread.detach(); + if (std.Thread.use_pthreads) { + return switch (std.c.pthread_kill(thread.handle, .IO)) { + 0 => true, + else => false, + }; + } else switch (builtin.target.os.tag) { + .linux => { + const pid: posix.pid_t = pid: { + const cached_pid = @atomicLoad(Pid, &t.pid, .monotonic); + if (cached_pid != .unknown) break :pid @intFromEnum(cached_pid); + const pid = std.os.linux.getpid(); + @atomicStore(Pid, &t.pid, @enumFromInt(pid), .monotonic); + break :pid pid; + }; + return switch (std.os.linux.tgkill(pid, @bitCast(thread.id), .IO)) { + 0 => true, + else => false, + }; + }, + .windows => { + var iosb: windows.IO_STATUS_BLOCK = undefined; + return switch (windows.ntdll.NtCancelSynchronousIoFile(thread.handle, null, &iosb)) { + .NOT_FOUND => true, // this might mean the operation hasn't started yet + .SUCCESS => false, // the OS confirmed that our cancelation worked + else => false, + }; + }, + else => return false, + } } - t.run_queue.prepend(&ac.closure.node); - t.mutex.unlock(); - t.cond.signal(); - return @ptrCast(ac); -} - -fn concurrent( - userdata: ?*anyopaque, - result_len: usize, - result_alignment: Alignment, - context: []const u8, - context_alignment: Alignment, - start: *const fn (context: *const anyopaque, result: *anyopaque) void, -) Io.ConcurrentError!*Io.AnyFuture { - if (builtin.single_threaded) return error.ConcurrencyUnavailable; + /// Like a `*Thread`, but 2 bits smaller than a pointer (because the LSBs are always 0 due to + /// alignment) so that those two bits can be used in a `packed struct`. + const PackedPtr = enum(@Int(.unsigned, @bitSizeOf(usize) - 2)) { + null = 0, + all_ones = std.math.maxInt(@Int(.unsigned, @bitSizeOf(usize) - 2)), + _, - const t: *Threaded = @ptrCast(@alignCast(userdata)); + const Split = packed struct(usize) { low: u2, high: PackedPtr }; + fn pack(ptr: *Thread) PackedPtr { + const split: Split = @bitCast(@intFromPtr(ptr)); + assert(split.low == 0); + return split.high; + } + fn unpack(ptr: PackedPtr) ?*Thread { + const split: Split = .{ .low = 0, .high = ptr }; + return @ptrFromInt(@as(usize, @bitCast(split))); + } + }; +}; - const gpa = t.allocator; - const ac = AsyncClosure.init(gpa, result_len, result_alignment, context, context_alignment, start) catch - return error.ConcurrencyUnavailable; - errdefer ac.deinit(gpa); - - t.mutex.lock(); - defer t.mutex.unlock(); - - const busy_count = t.busy_count; - - if (busy_count >= @intFromEnum(t.concurrent_limit)) - return error.ConcurrencyUnavailable; - - t.busy_count = busy_count + 1; - errdefer t.busy_count = busy_count; - - const pool_size = t.wait_group.value(); - if (pool_size - busy_count == 0) { - t.wait_group.start(); - errdefer t.wait_group.finish(); - - const thread = std.Thread.spawn(.{ .stack_size = t.stack_size }, worker, .{t}) catch - return error.ConcurrencyUnavailable; - thread.detach(); - } - - t.run_queue.prepend(&ac.closure.node); - t.cond.signal(); - return @ptrCast(ac); -} - -const GroupClosure = struct { - closure: Closure, - t: *Threaded, - group: *Io.Group, - /// Points to sibling `GroupClosure`. Used for walking the group to cancel all. - node: std.SinglyLinkedList.Node, - func: *const fn (*Io.Group, context: *anyopaque) void, - context_alignment: Alignment, - alloc_len: usize, - - fn start(closure: *Closure) void { - const gc: *GroupClosure = @alignCast(@fieldParentPtr("closure", closure)); - const tid: CancelId = .currentThread(); - const group = gc.group; - const group_state: *std.atomic.Value(usize) = @ptrCast(&group.state); - const reset_event: *ResetEvent = @ptrCast(&group.context); - if (@cmpxchgStrong(CancelId, &closure.cancel_tid, .none, tid, .acq_rel, .acquire)) |cancel_tid| { - assert(cancel_tid == .canceling); - // Even though we already know the task is canceled, we must still - // run the closure in case there are side effects. +const Syscall = struct { + thread: ?*Thread, + /// Marks entry to a syscall region. This should be tightly scoped around the actual syscall + /// to minimize races. The syscall must be marked as "finished" by `checkCancel`, `finish`, + /// or one of the wrappers of `finish`. + fn start() Io.Cancelable!Syscall { + const thread = Thread.current orelse return .{ .thread = null }; + switch (thread.cancel_protection) { + .blocked => return .{ .thread = null }, + .unblocked => {}, } - current_closure = closure; - gc.func(group, gc.contextPointer()); - current_closure = null; - - // In case a cancel happens after successful task completion, prevents - // signal from being delivered to the thread in `requestCancel`. - if (@cmpxchgStrong(CancelId, &closure.cancel_tid, tid, .none, .acq_rel, .acquire)) |cancel_tid| { - assert(cancel_tid == .canceling); + switch (thread.status.fetchOr(.{ + .cancelation = @enumFromInt(0b011), + .awaitable = .null, + }, .monotonic).cancelation) { + .parked => unreachable, + .blocked => unreachable, + .blocked_windows_dns => unreachable, + .blocked_canceling => unreachable, + .none => return .{ .thread = thread }, // new status is `.blocked` + .canceling => return error.Canceled, // new status is `.canceled` + .canceled => return .{ .thread = null }, // new status is `.canceled` (unchanged) } - - const prev_state = group_state.fetchSub(sync_one_pending, .acq_rel); - assert((prev_state / sync_one_pending) > 0); - if (prev_state == (sync_one_pending | sync_is_waiting)) reset_event.set(); } - - fn contextPointer(gc: *GroupClosure) [*]u8 { - const base: [*]u8 = @ptrCast(gc); - const context_offset = gc.context_alignment.forward(@intFromPtr(gc) + @sizeOf(GroupClosure)) - @intFromPtr(gc); - return base + context_offset; + /// Checks whether this syscall has been canceled. This should be called when a syscall is + /// interrupted through a mechanism which may indicate cancelation, or may be spurious. If + /// the syscall was canceled, it is finished and `error.Canceled` is returned. Otherwise, + /// the syscall is not marked finished, and the caller should retry. + fn checkCancel(s: Syscall) Io.Cancelable!void { + const thread = s.thread orelse return; + switch (thread.status.fetchOr(.{ + .cancelation = @enumFromInt(0b010), + .awaitable = .null, + }, .monotonic).cancelation) { + .none => unreachable, + .parked => unreachable, + .blocked_windows_dns => unreachable, + .canceling => unreachable, + .canceled => unreachable, + .blocked => {}, // new status is `.blocked` (unchanged) + .blocked_canceling => return error.Canceled, // new status is `.canceled` + } } - - /// Does not initialize the `node` field. - fn init( - gpa: Allocator, - t: *Threaded, - group: *Io.Group, - context: []const u8, - context_alignment: Alignment, - func: *const fn (*Io.Group, context: *const anyopaque) void, - ) Allocator.Error!*GroupClosure { - const max_context_misalignment = context_alignment.toByteUnits() -| @alignOf(GroupClosure); - const worst_case_context_offset = context_alignment.forward(@sizeOf(GroupClosure) + max_context_misalignment); - const alloc_len = worst_case_context_offset + context.len; - - const gc: *GroupClosure = @ptrCast(@alignCast(try gpa.alignedAlloc(u8, .of(GroupClosure), alloc_len))); - errdefer comptime unreachable; - - gc.* = .{ - .closure = .{ - .cancel_tid = .none, - .start = start, - }, - .t = t, - .group = group, - .node = undefined, - .func = func, - .context_alignment = context_alignment, - .alloc_len = alloc_len, - }; - @memcpy(gc.contextPointer()[0..context.len], context); - return gc; + /// Marks this syscall as finished. + fn finish(s: Syscall) void { + const thread = s.thread orelse return; + switch (thread.status.fetchXor(.{ + .cancelation = @enumFromInt(0b011), + .awaitable = .null, + }, .monotonic).cancelation) { + .none => unreachable, + .parked => unreachable, + .blocked_windows_dns => unreachable, + .canceling => unreachable, + .canceled => unreachable, + .blocked => {}, // new status is `.none` + .blocked_canceling => {}, // new status is `.canceling` + } } - - fn deinit(gc: *GroupClosure, gpa: Allocator) void { - const base: [*]align(@alignOf(GroupClosure)) u8 = @ptrCast(gc); - gpa.free(base[0..gc.alloc_len]); + /// Convenience wrapper which calls `finish`, then returns `err`. + fn fail(s: Syscall, err: anytype) @TypeOf(err) { + s.finish(); + return err; + } + /// Convenience wrapper which calls `finish`, then calls `Threaded.errnoBug`. + fn errnoBug(s: Syscall, err: posix.E) Io.UnexpectedError { + @branchHint(.cold); + s.finish(); + return Threaded.errnoBug(err); + } + /// Convenience wrapper which calls `finish`, then calls `posix.unexpectedErrno`. + fn unexpectedErrno(s: Syscall, err: posix.E) Io.UnexpectedError { + @branchHint(.cold); + s.finish(); + return posix.unexpectedErrno(err); + } + /// Convenience wrapper which calls `finish`, then calls `windows.statusBug`. + fn ntstatusBug(s: Syscall, status: windows.NTSTATUS) Io.UnexpectedError { + @branchHint(.cold); + s.finish(); + return windows.statusBug(status); + } + /// Convenience wrapper which calls `finish`, then calls `windows.unexpectedStatus`. + fn unexpectedNtstatus(s: Syscall, status: windows.NTSTATUS) Io.UnexpectedError { + @branchHint(.cold); + s.finish(); + return windows.unexpectedStatus(status); } - - const sync_is_waiting: usize = 1 << 0; - const sync_one_pending: usize = 1 << 1; }; -fn groupAsync( - userdata: ?*anyopaque, - group: *Io.Group, - context: []const u8, - context_alignment: Alignment, - start: *const fn (*Io.Group, context: *const anyopaque) void, -) void { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - if (builtin.single_threaded) return start(group, context.ptr); +const max_iovecs_len = 8; +const splat_buffer_size = 64; +const default_PATH = "/usr/local/bin:/bin/:/usr/bin"; - const gpa = t.allocator; - const gc = GroupClosure.init(gpa, t, group, context, context_alignment, start) catch - return start(group, context.ptr); +comptime { + if (@TypeOf(posix.IOV_MAX) != void) assert(max_iovecs_len <= posix.IOV_MAX); +} - t.mutex.lock(); +pub const InitOptions = struct { + /// Affects how many bytes are memory-mapped for threads. + stack_size: usize = std.Thread.SpawnConfig.default_stack_size, + /// Maximum thread pool size (excluding main thread) when dispatching async + /// tasks. Until this limit, calls to `Io.async` when all threads are busy will + /// cause a new thread to be spawned and permanently added to the pool. After + /// this limit, calls to `Io.async` when all threads are busy run the task + /// immediately. + /// + /// Defaults to a number equal to logical CPU cores. + /// + /// Protected by `Threaded.mutex` once the I/O instance is already in use. See + /// `setAsyncLimit`. + async_limit: ?Io.Limit = null, + /// Maximum thread pool size (excluding main thread) for dispatching concurrent + /// tasks. Until this limit, calls to `Io.concurrent` will increase the thread + /// pool size. + /// + /// concurrent tasks. After this number, calls to `Io.concurrent` return + /// `error.ConcurrencyUnavailable`. + concurrent_limit: Io.Limit = .unlimited, + /// Affects the following operations: + /// * `processExecutablePath` on OpenBSD and Haiku. + argv0: Argv0 = .empty, + /// Affects the following operations: + /// * `fileIsTty` + /// * `processExecutablePath` on OpenBSD and Haiku (observes "PATH"). + /// * `processSpawn`, `processSpawnPath`, `processReplace`, `processReplacePath` + environ: process.Environ, +}; - const busy_count = t.busy_count; +/// Related: +/// * `init_single_threaded` +pub fn init( + /// Must be threadsafe. Only used for the following functions: + /// * `Io.VTable.async` + /// * `Io.VTable.concurrent` + /// * `Io.VTable.groupAsync` + /// * `Io.VTable.groupConcurrent` + /// If these functions are avoided, then `Allocator.failing` may be passed + /// here. + gpa: Allocator, + options: InitOptions, +) Threaded { + if (builtin.single_threaded) return .{ + .allocator = gpa, + .stack_size = options.stack_size, + .async_limit = options.async_limit orelse init_single_threaded.async_limit, + .cpu_count_error = init_single_threaded.cpu_count_error, + .concurrent_limit = options.concurrent_limit, + .old_sig_io = undefined, + .old_sig_pipe = undefined, + .have_signal_handler = init_single_threaded.have_signal_handler, + .argv0 = options.argv0, + .environ = .{ .process_environ = options.environ }, + .worker_threads = init_single_threaded.worker_threads, + }; - if (busy_count >= @intFromEnum(t.async_limit)) { - t.mutex.unlock(); - gc.deinit(gpa); - return start(group, context.ptr); - } + const cpu_count = std.Thread.getCpuCount(); - t.busy_count = busy_count + 1; + var t: Threaded = .{ + .allocator = gpa, + .stack_size = options.stack_size, + .async_limit = options.async_limit orelse if (cpu_count) |n| .limited(n - 1) else |_| .nothing, + .concurrent_limit = options.concurrent_limit, + .cpu_count_error = if (cpu_count) |_| null else |e| e, + .old_sig_io = undefined, + .old_sig_pipe = undefined, + .have_signal_handler = false, + .argv0 = options.argv0, + .environ = .{ .process_environ = options.environ }, + .worker_threads = .init(null), + }; - const pool_size = t.wait_group.value(); - if (pool_size - busy_count == 0) { - t.wait_group.start(); - const thread = std.Thread.spawn(.{ .stack_size = t.stack_size }, worker, .{t}) catch { - t.wait_group.finish(); - t.busy_count = busy_count; - t.mutex.unlock(); - gc.deinit(gpa); - return start(group, context.ptr); + if (posix.Sigaction != void) { + // This causes sending `posix.SIG.IO` to thread to interrupt blocking + // syscalls, returning `posix.E.INTR`. + const act: posix.Sigaction = .{ + .handler = .{ .handler = doNothingSignalHandler }, + .mask = posix.sigemptyset(), + .flags = 0, }; - thread.detach(); + if (have_sig_io) posix.sigaction(.IO, &act, &t.old_sig_io); + if (have_sig_pipe) posix.sigaction(.PIPE, &act, &t.old_sig_pipe); + t.have_signal_handler = true; } - // Append to the group linked list inside the mutex to make `Io.Group.async` thread-safe. - gc.node = .{ .next = @ptrCast(@alignCast(group.token)) }; - group.token = &gc.node; - - t.run_queue.prepend(&gc.closure.node); - - // This needs to be done before unlocking the mutex to avoid a race with - // the associated task finishing. - const group_state: *std.atomic.Value(usize) = @ptrCast(&group.state); - const prev_state = group_state.fetchAdd(GroupClosure.sync_one_pending, .monotonic); - assert((prev_state / GroupClosure.sync_one_pending) < (std.math.maxInt(usize) / GroupClosure.sync_one_pending)); - - t.mutex.unlock(); - t.cond.signal(); + return t; } -fn groupConcurrent( - userdata: ?*anyopaque, - group: *Io.Group, - context: []const u8, - context_alignment: Alignment, - start: *const fn (*Io.Group, context: *const anyopaque) void, -) Io.ConcurrentError!void { - if (builtin.single_threaded) return error.ConcurrencyUnavailable; +/// Statically initialize such that calls to `Io.VTable.concurrent` will fail +/// with `error.ConcurrencyUnavailable`. +/// +/// When initialized this way: +/// * cancel requests have no effect. +/// * `deinit` is safe, but unnecessary to call. +pub const init_single_threaded: Threaded = .{ + .allocator = .failing, + .stack_size = std.Thread.SpawnConfig.default_stack_size, + .async_limit = .nothing, + .cpu_count_error = null, + .concurrent_limit = .nothing, + .old_sig_io = undefined, + .old_sig_pipe = undefined, + .have_signal_handler = false, + .argv0 = .empty, + .environ = .{}, + .worker_threads = .init(null), +}; - const t: *Threaded = @ptrCast(@alignCast(userdata)); +var global_single_threaded_instance: Threaded = .init_single_threaded; - const gpa = t.allocator; - const gc = GroupClosure.init(gpa, t, group, context, context_alignment, start) catch - return error.ConcurrencyUnavailable; +/// In general, the application is responsible for choosing the `Io` +/// implementation and library code should accept an `Io` parameter rather than +/// accessing this declaration. Most code should avoid referencing this +/// declaration entirely. +/// +/// However, in some cases such as debugging, it is desirable to hardcode a +/// reference to this `Io` implementation. +/// +/// This instance does not support concurrency or cancelation. +pub const global_single_threaded: *Threaded = &global_single_threaded_instance; +pub fn setAsyncLimit(t: *Threaded, new_limit: Io.Limit) void { t.mutex.lock(); defer t.mutex.unlock(); + t.async_limit = new_limit; +} - const busy_count = t.busy_count; - - if (busy_count >= @intFromEnum(t.concurrent_limit)) - return error.ConcurrencyUnavailable; - - t.busy_count = busy_count + 1; - errdefer t.busy_count = busy_count; - - const pool_size = t.wait_group.value(); - if (pool_size - busy_count == 0) { - t.wait_group.start(); - errdefer t.wait_group.finish(); - - const thread = std.Thread.spawn(.{ .stack_size = t.stack_size }, worker, .{t}) catch - return error.ConcurrencyUnavailable; - thread.detach(); +pub fn deinit(t: *Threaded) void { + t.join(); + if (is_windows and t.wsa.status == .initialized) { + if (ws2_32.WSACleanup() != 0) recoverableOsBugDetected(); } - - // Append to the group linked list inside the mutex to make `Io.Group.concurrent` thread-safe. - gc.node = .{ .next = @ptrCast(@alignCast(group.token)) }; - group.token = &gc.node; - - t.run_queue.prepend(&gc.closure.node); - - // This needs to be done before unlocking the mutex to avoid a race with - // the associated task finishing. - const group_state: *std.atomic.Value(usize) = @ptrCast(&group.state); - const prev_state = group_state.fetchAdd(GroupClosure.sync_one_pending, .monotonic); - assert((prev_state / GroupClosure.sync_one_pending) < (std.math.maxInt(usize) / GroupClosure.sync_one_pending)); - - t.cond.signal(); + if (posix.Sigaction != void and t.have_signal_handler) { + if (have_sig_io) posix.sigaction(.IO, &t.old_sig_io, null); + if (have_sig_pipe) posix.sigaction(.PIPE, &t.old_sig_pipe, null); + } + t.null_file.deinit(); + t.random_file.deinit(); + t.* = undefined; } -fn groupWait(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) void { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - const gpa = t.allocator; - +fn join(t: *Threaded) void { if (builtin.single_threaded) return; + { + t.mutex.lock(); + defer t.mutex.unlock(); + t.join_requested = true; + } + t.cond.broadcast(); + t.wait_group.wait(); +} - const group_state: *std.atomic.Value(usize) = @ptrCast(&group.state); - const reset_event: *ResetEvent = @ptrCast(&group.context); - const prev_state = group_state.fetchAdd(GroupClosure.sync_is_waiting, .acquire); - assert(prev_state & GroupClosure.sync_is_waiting == 0); - if ((prev_state / GroupClosure.sync_one_pending) > 0) reset_event.wait(t) catch |err| switch (err) { - error.Canceled => { - var node: *std.SinglyLinkedList.Node = @ptrCast(@alignCast(token)); - while (true) { - const gc: *GroupClosure = @fieldParentPtr("node", node); - gc.closure.requestCancel(); - node = node.next orelse break; - } - reset_event.waitUncancelable(); +fn worker(t: *Threaded) void { + var thread: Thread = .{ + .next = undefined, + .id = std.Thread.getCurrentId(), + .handle = handle: { + if (std.Thread.use_pthreads) break :handle std.c.pthread_self(); + if (builtin.target.os.tag == .windows) break :handle undefined; // populated below }, + .status = .init(.{ + .cancelation = .none, + .awaitable = .null, + }), + .cancel_protection = .unblocked, + .futex_waiter = undefined, + .csprng = .{}, }; - - var node: *std.SinglyLinkedList.Node = @ptrCast(@alignCast(token)); - while (true) { - const gc: *GroupClosure = @fieldParentPtr("node", node); - const node_next = node.next; - gc.deinit(gpa); - node = node_next orelse break; + Thread.current = &thread; + + if (builtin.target.os.tag == .windows) { + assert(windows.ntdll.NtOpenThread( + &thread.handle, + .{ + .SPECIFIC = .{ + .THREAD = .{ + .TERMINATE = true, // for `NtCancelSynchronousIoFile` + }, + }, + }, + &.{ + .Length = @sizeOf(windows.OBJECT_ATTRIBUTES), + .RootDirectory = null, + .ObjectName = null, + .Attributes = .{}, + .SecurityDescriptor = null, + .SecurityQualityOfService = null, + }, + &windows.teb().ClientId, + ) == .SUCCESS); } -} - -fn groupCancel(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) void { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - const gpa = t.allocator; - - if (builtin.single_threaded) return; + defer if (builtin.target.os.tag == .windows) { + windows.CloseHandle(thread.handle); + }; { - var node: *std.SinglyLinkedList.Node = @ptrCast(@alignCast(token)); + var head = t.worker_threads.load(.monotonic); while (true) { - const gc: *GroupClosure = @fieldParentPtr("node", node); - gc.closure.requestCancel(); - node = node.next orelse break; + thread.next = head; + head = t.worker_threads.cmpxchgWeak( + head, + &thread, + .release, + .monotonic, + ) orelse break; } } - const group_state: *std.atomic.Value(usize) = @ptrCast(&group.state); - const reset_event: *ResetEvent = @ptrCast(&group.context); - const prev_state = group_state.fetchAdd(GroupClosure.sync_is_waiting, .acquire); - assert(prev_state & GroupClosure.sync_is_waiting == 0); - if ((prev_state / GroupClosure.sync_one_pending) > 0) reset_event.waitUncancelable(); + defer t.wait_group.finish(); - { - var node: *std.SinglyLinkedList.Node = @ptrCast(@alignCast(token)); - while (true) { - const gc: *GroupClosure = @fieldParentPtr("node", node); - const node_next = node.next; - gc.deinit(gpa); - node = node_next orelse break; + t.mutex.lock(); + defer t.mutex.unlock(); + + while (true) { + while (t.run_queue.popFirst()) |runnable_node| { + t.mutex.unlock(); + thread.cancel_protection = .unblocked; + const runnable: *Runnable = @fieldParentPtr("node", runnable_node); + runnable.startFn(runnable, &thread, t); + t.mutex.lock(); + t.busy_count -= 1; } + if (t.join_requested) break; + t.cond.wait(&t.mutex); } } -fn await( - userdata: ?*anyopaque, - any_future: *Io.AnyFuture, - result: []u8, - result_alignment: Alignment, -) void { - _ = result_alignment; - const t: *Threaded = @ptrCast(@alignCast(userdata)); - const closure: *AsyncClosure = @ptrCast(@alignCast(any_future)); - closure.waitAndDeinit(t, result); -} +pub fn io(t: *Threaded) Io { + return .{ + .userdata = t, + .vtable = &.{ + .async = async, + .concurrent = concurrent, + .await = await, + .cancel = cancel, + .select = select, -fn cancel( - userdata: ?*anyopaque, - any_future: *Io.AnyFuture, - result: []u8, - result_alignment: Alignment, -) void { - _ = result_alignment; - const t: *Threaded = @ptrCast(@alignCast(userdata)); - const ac: *AsyncClosure = @ptrCast(@alignCast(any_future)); - ac.closure.requestCancel(); - ac.waitAndDeinit(t, result); -} + .groupAsync = groupAsync, + .groupConcurrent = groupConcurrent, + .groupAwait = groupAwait, + .groupCancel = groupCancel, -fn cancelRequested(userdata: ?*anyopaque) bool { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - _ = t; - const closure = current_closure orelse return false; - return @atomicLoad(CancelId, &closure.cancel_tid, .acquire) == .canceling; -} - -fn checkCancel(t: *Threaded) error{Canceled}!void { - if (cancelRequested(t)) return error.Canceled; -} - -fn mutexLock(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mutex) Io.Cancelable!void { - if (builtin.single_threaded) unreachable; // Interface should have prevented this. - if (native_os == .netbsd) @panic("TODO"); - const t: *Threaded = @ptrCast(@alignCast(userdata)); - if (prev_state == .contended) { - try futexWait(t, @ptrCast(&mutex.state), @intFromEnum(Io.Mutex.State.contended)); - } - while (@atomicRmw(Io.Mutex.State, &mutex.state, .Xchg, .contended, .acquire) != .unlocked) { - try futexWait(t, @ptrCast(&mutex.state), @intFromEnum(Io.Mutex.State.contended)); - } -} - -fn mutexLockUncancelable(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mutex) void { - if (builtin.single_threaded) unreachable; // Interface should have prevented this. - if (native_os == .netbsd) @panic("TODO"); - _ = userdata; - if (prev_state == .contended) { - futexWaitUncancelable(@ptrCast(&mutex.state), @intFromEnum(Io.Mutex.State.contended)); - } - while (@atomicRmw(Io.Mutex.State, &mutex.state, .Xchg, .contended, .acquire) != .unlocked) { - futexWaitUncancelable(@ptrCast(&mutex.state), @intFromEnum(Io.Mutex.State.contended)); - } -} - -fn mutexUnlock(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mutex) void { - if (builtin.single_threaded) unreachable; // Interface should have prevented this. - if (native_os == .netbsd) @panic("TODO"); - _ = userdata; - _ = prev_state; - if (@atomicRmw(Io.Mutex.State, &mutex.state, .Xchg, .unlocked, .release) == .contended) { - futexWake(@ptrCast(&mutex.state), 1); - } -} - -fn conditionWaitUncancelable(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) void { - if (builtin.single_threaded) unreachable; // Deadlock. - if (native_os == .netbsd) @panic("TODO"); - const t: *Threaded = @ptrCast(@alignCast(userdata)); - const t_io = ioBasic(t); - comptime assert(@TypeOf(cond.state) == u64); - const ints: *[2]std.atomic.Value(u32) = @ptrCast(&cond.state); - const cond_state = &ints[0]; - const cond_epoch = &ints[1]; - const one_waiter = 1; - const waiter_mask = 0xffff; - const one_signal = 1 << 16; - const signal_mask = 0xffff << 16; - var epoch = cond_epoch.load(.acquire); - var state = cond_state.fetchAdd(one_waiter, .monotonic); - assert(state & waiter_mask != waiter_mask); - state += one_waiter; - - mutex.unlock(t_io); - defer mutex.lockUncancelable(t_io); + .recancel = recancel, + .swapCancelProtection = swapCancelProtection, + .checkCancel = checkCancel, - while (true) { - futexWaitUncancelable(cond_epoch, epoch); - epoch = cond_epoch.load(.acquire); - state = cond_state.load(.monotonic); - while (state & signal_mask != 0) { - const new_state = state - one_waiter - one_signal; - state = cond_state.cmpxchgWeak(state, new_state, .acquire, .monotonic) orelse return; - } - } -} + .futexWait = futexWait, + .futexWaitUncancelable = futexWaitUncancelable, + .futexWake = futexWake, -fn conditionWait(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) Io.Cancelable!void { - if (builtin.single_threaded) unreachable; // Deadlock. - if (native_os == .netbsd) @panic("TODO"); - const t: *Threaded = @ptrCast(@alignCast(userdata)); - const t_io = ioBasic(t); - comptime assert(@TypeOf(cond.state) == u64); - const ints: *[2]std.atomic.Value(u32) = @ptrCast(&cond.state); - const cond_state = &ints[0]; - const cond_epoch = &ints[1]; - const one_waiter = 1; - const waiter_mask = 0xffff; - const one_signal = 1 << 16; - const signal_mask = 0xffff << 16; - // Observe the epoch, then check the state again to see if we should wake up. - // The epoch must be observed before we check the state or we could potentially miss a wake() and deadlock: - // - // - T1: s = LOAD(&state) - // - T2: UPDATE(&s, signal) - // - T2: UPDATE(&epoch, 1) + FUTEX_WAKE(&epoch) - // - T1: e = LOAD(&epoch) (was reordered after the state load) - // - T1: s & signals == 0 -> FUTEX_WAIT(&epoch, e) (missed the state update + the epoch change) - // - // Acquire barrier to ensure the epoch load happens before the state load. - var epoch = cond_epoch.load(.acquire); - var state = cond_state.fetchAdd(one_waiter, .monotonic); - assert(state & waiter_mask != waiter_mask); - state += one_waiter; + .dirCreateDir = dirCreateDir, + .dirCreateDirPath = dirCreateDirPath, + .dirCreateDirPathOpen = dirCreateDirPathOpen, + .dirStat = dirStat, + .dirStatFile = dirStatFile, + .dirAccess = dirAccess, + .dirCreateFile = dirCreateFile, + .dirCreateFileAtomic = dirCreateFileAtomic, + .dirOpenFile = dirOpenFile, + .dirOpenDir = dirOpenDir, + .dirClose = dirClose, + .dirRead = dirRead, + .dirRealPath = dirRealPath, + .dirRealPathFile = dirRealPathFile, + .dirDeleteFile = dirDeleteFile, + .dirDeleteDir = dirDeleteDir, + .dirRename = dirRename, + .dirRenamePreserve = dirRenamePreserve, + .dirSymLink = dirSymLink, + .dirReadLink = dirReadLink, + .dirSetOwner = dirSetOwner, + .dirSetFileOwner = dirSetFileOwner, + .dirSetPermissions = dirSetPermissions, + .dirSetFilePermissions = dirSetFilePermissions, + .dirSetTimestamps = dirSetTimestamps, + .dirHardLink = dirHardLink, - mutex.unlock(t_io); - defer mutex.lockUncancelable(t_io); + .fileStat = fileStat, + .fileLength = fileLength, + .fileClose = fileClose, + .fileWriteStreaming = fileWriteStreaming, + .fileWritePositional = fileWritePositional, + .fileWriteFileStreaming = fileWriteFileStreaming, + .fileWriteFilePositional = fileWriteFilePositional, + .fileReadStreaming = fileReadStreaming, + .fileReadPositional = fileReadPositional, + .fileSeekBy = fileSeekBy, + .fileSeekTo = fileSeekTo, + .fileSync = fileSync, + .fileIsTty = fileIsTty, + .fileEnableAnsiEscapeCodes = fileEnableAnsiEscapeCodes, + .fileSupportsAnsiEscapeCodes = fileSupportsAnsiEscapeCodes, + .fileSetLength = fileSetLength, + .fileSetOwner = fileSetOwner, + .fileSetPermissions = fileSetPermissions, + .fileSetTimestamps = fileSetTimestamps, + .fileLock = fileLock, + .fileTryLock = fileTryLock, + .fileUnlock = fileUnlock, + .fileDowngradeLock = fileDowngradeLock, + .fileRealPath = fileRealPath, + .fileHardLink = fileHardLink, + + .processExecutableOpen = processExecutableOpen, + .processExecutablePath = processExecutablePath, + .lockStderr = lockStderr, + .tryLockStderr = tryLockStderr, + .unlockStderr = unlockStderr, + .processSetCurrentDir = processSetCurrentDir, + .processReplace = processReplace, + .processReplacePath = processReplacePath, + .processSpawn = processSpawn, + .processSpawnPath = processSpawnPath, + .childWait = childWait, + .childKill = childKill, + + .progressParentFile = progressParentFile, - while (true) { - try futexWait(t, cond_epoch, epoch); + .now = now, + .sleep = sleep, - epoch = cond_epoch.load(.acquire); - state = cond_state.load(.monotonic); + .random = random, + .randomSecure = randomSecure, - // Try to wake up by consuming a signal and decremented the waiter we - // added previously. Acquire barrier ensures code before the wake() - // which added the signal happens before we decrement it and return. - while (state & signal_mask != 0) { - const new_state = state - one_waiter - one_signal; - state = cond_state.cmpxchgWeak(state, new_state, .acquire, .monotonic) orelse return; - } - } + .netListenIp = switch (native_os) { + .windows => netListenIpWindows, + else => netListenIpPosix, + }, + .netListenUnix = switch (native_os) { + .windows => netListenUnixWindows, + else => netListenUnixPosix, + }, + .netAccept = switch (native_os) { + .windows => netAcceptWindows, + else => netAcceptPosix, + }, + .netBindIp = switch (native_os) { + .windows => netBindIpWindows, + else => netBindIpPosix, + }, + .netConnectIp = switch (native_os) { + .windows => netConnectIpWindows, + else => netConnectIpPosix, + }, + .netConnectUnix = switch (native_os) { + .windows => netConnectUnixWindows, + else => netConnectUnixPosix, + }, + .netClose = netClose, + .netShutdown = switch (native_os) { + .windows => netShutdownWindows, + else => netShutdownPosix, + }, + .netRead = switch (native_os) { + .windows => netReadWindows, + else => netReadPosix, + }, + .netWrite = switch (native_os) { + .windows => netWriteWindows, + else => netWritePosix, + }, + .netWriteFile = netWriteFile, + .netSend = switch (native_os) { + .windows => netSendWindows, + else => netSendPosix, + }, + .netReceive = switch (native_os) { + .windows => netReceiveWindows, + else => netReceivePosix, + }, + .netInterfaceNameResolve = netInterfaceNameResolve, + .netInterfaceName = netInterfaceName, + .netLookup = netLookup, + }, + }; } -fn conditionWake(userdata: ?*anyopaque, cond: *Io.Condition, wake: Io.Condition.Wake) void { - if (builtin.single_threaded) unreachable; // Nothing to wake up. - const t: *Threaded = @ptrCast(@alignCast(userdata)); - _ = t; - comptime assert(@TypeOf(cond.state) == u64); - const ints: *[2]std.atomic.Value(u32) = @ptrCast(&cond.state); - const cond_state = &ints[0]; - const cond_epoch = &ints[1]; - const one_waiter = 1; - const waiter_mask = 0xffff; - const one_signal = 1 << 16; - const signal_mask = 0xffff << 16; - var state = cond_state.load(.monotonic); - while (true) { - const waiters = (state & waiter_mask) / one_waiter; - const signals = (state & signal_mask) / one_signal; - - // Reserves which waiters to wake up by incrementing the signals count. - // Therefore, the signals count is always less than or equal to the - // waiters count. We don't need to Futex.wake if there's nothing to - // wake up or if other wake() threads have reserved to wake up the - // current waiters. - const wakeable = waiters - signals; - if (wakeable == 0) { - return; - } - - const to_wake = switch (wake) { - .one => 1, - .all => wakeable, - }; +/// Same as `io` but disables all networking functionality, which has +/// an additional dependency on Windows (ws2_32). +pub fn ioBasic(t: *Threaded) Io { + return .{ + .userdata = t, + .vtable = &.{ + .async = async, + .concurrent = concurrent, + .await = await, + .cancel = cancel, + .select = select, - // Reserve the amount of waiters to wake by incrementing the signals - // count. Release barrier ensures code before the wake() happens before - // the signal it posted and consumed by the wait() threads. - const new_state = state + (one_signal * to_wake); - state = cond_state.cmpxchgWeak(state, new_state, .release, .monotonic) orelse { - // Wake up the waiting threads we reserved above by changing the epoch value. - // - // A waiting thread could miss a wake up if *exactly* ((1<<32)-1) - // wake()s happen between it observing the epoch and sleeping on - // it. This is very unlikely due to how many precise amount of - // Futex.wake() calls that would be between the waiting thread's - // potential preemption. - // - // Release barrier ensures the signal being added to the state - // happens before the epoch is changed. If not, the waiting thread - // could potentially deadlock from missing both the state and epoch - // change: - // - // - T2: UPDATE(&epoch, 1) (reordered before the state change) - // - T1: e = LOAD(&epoch) - // - T1: s = LOAD(&state) - // - T2: UPDATE(&state, signal) + FUTEX_WAKE(&epoch) - // - T1: s & signals == 0 -> FUTEX_WAIT(&epoch, e) (missed both epoch change and state change) - _ = cond_epoch.fetchAdd(1, .release); - if (native_os == .netbsd) @panic("TODO"); - futexWake(cond_epoch, to_wake); - return; - }; - } -} + .groupAsync = groupAsync, + .groupConcurrent = groupConcurrent, + .groupAwait = groupAwait, + .groupCancel = groupCancel, -const dirMake = switch (native_os) { - .windows => dirMakeWindows, - .wasi => dirMakeWasi, - else => dirMakePosix, -}; + .recancel = recancel, + .swapCancelProtection = swapCancelProtection, + .checkCancel = checkCancel, -fn dirMakePosix(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode: Io.Dir.Mode) Io.Dir.MakeError!void { - const t: *Threaded = @ptrCast(@alignCast(userdata)); + .futexWait = futexWait, + .futexWaitUncancelable = futexWaitUncancelable, + .futexWake = futexWake, - var path_buffer: [posix.PATH_MAX]u8 = undefined; - const sub_path_posix = try pathToPosix(sub_path, &path_buffer); + .dirCreateDir = dirCreateDir, + .dirCreateDirPath = dirCreateDirPath, + .dirCreateDirPathOpen = dirCreateDirPathOpen, + .dirStat = dirStat, + .dirStatFile = dirStatFile, + .dirAccess = dirAccess, + .dirCreateFile = dirCreateFile, + .dirCreateFileAtomic = dirCreateFileAtomic, + .dirOpenFile = dirOpenFile, + .dirOpenDir = dirOpenDir, + .dirClose = dirClose, + .dirRead = dirRead, + .dirRealPath = dirRealPath, + .dirRealPathFile = dirRealPathFile, + .dirDeleteFile = dirDeleteFile, + .dirDeleteDir = dirDeleteDir, + .dirRename = dirRename, + .dirRenamePreserve = dirRenamePreserve, + .dirSymLink = dirSymLink, + .dirReadLink = dirReadLink, + .dirSetOwner = dirSetOwner, + .dirSetFileOwner = dirSetFileOwner, + .dirSetPermissions = dirSetPermissions, + .dirSetFilePermissions = dirSetFilePermissions, + .dirSetTimestamps = dirSetTimestamps, + .dirHardLink = dirHardLink, - while (true) { - try t.checkCancel(); - switch (posix.errno(posix.system.mkdirat(dir.handle, sub_path_posix, mode))) { - .SUCCESS => return, - .INTR => continue, - .CANCELED => return error.Canceled, - - .ACCES => return error.AccessDenied, - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .PERM => return error.PermissionDenied, - .DQUOT => return error.DiskQuota, - .EXIST => return error.PathAlreadyExists, - .FAULT => |err| return errnoBug(err), - .LOOP => return error.SymLinkLoop, - .MLINK => return error.LinkQuotaExceeded, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOMEM => return error.SystemResources, - .NOSPC => return error.NoSpaceLeft, - .NOTDIR => return error.NotDir, - .ROFS => return error.ReadOnlyFileSystem, - // dragonfly: when dir_fd is unlinked from filesystem - .NOTCONN => return error.FileNotFound, - .ILSEQ => return error.BadPathName, - else => |err| return posix.unexpectedErrno(err), - } - } -} + .fileStat = fileStat, + .fileLength = fileLength, + .fileClose = fileClose, + .fileWriteStreaming = fileWriteStreaming, + .fileWritePositional = fileWritePositional, + .fileWriteFileStreaming = fileWriteFileStreaming, + .fileWriteFilePositional = fileWriteFilePositional, + .fileReadStreaming = fileReadStreaming, + .fileReadPositional = fileReadPositional, + .fileSeekBy = fileSeekBy, + .fileSeekTo = fileSeekTo, + .fileSync = fileSync, + .fileIsTty = fileIsTty, + .fileEnableAnsiEscapeCodes = fileEnableAnsiEscapeCodes, + .fileSupportsAnsiEscapeCodes = fileSupportsAnsiEscapeCodes, + .fileSetLength = fileSetLength, + .fileSetOwner = fileSetOwner, + .fileSetPermissions = fileSetPermissions, + .fileSetTimestamps = fileSetTimestamps, + .fileLock = fileLock, + .fileTryLock = fileTryLock, + .fileUnlock = fileUnlock, + .fileDowngradeLock = fileDowngradeLock, + .fileRealPath = fileRealPath, + .fileHardLink = fileHardLink, + + .processExecutableOpen = processExecutableOpen, + .processExecutablePath = processExecutablePath, + .lockStderr = lockStderr, + .tryLockStderr = tryLockStderr, + .unlockStderr = unlockStderr, + .processSetCurrentDir = processSetCurrentDir, + .processReplace = processReplace, + .processReplacePath = processReplacePath, + .processSpawn = processSpawn, + .processSpawnPath = processSpawnPath, + .childWait = childWait, + .childKill = childKill, + + .progressParentFile = progressParentFile, -fn dirMakeWasi(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode: Io.Dir.Mode) Io.Dir.MakeError!void { - if (builtin.link_libc) return dirMakePosix(userdata, dir, sub_path, mode); - const t: *Threaded = @ptrCast(@alignCast(userdata)); - while (true) { - try t.checkCancel(); - switch (std.os.wasi.path_create_directory(dir.handle, sub_path.ptr, sub_path.len)) { - .SUCCESS => return, - .INTR => continue, - .CANCELED => return error.Canceled, - - .ACCES => return error.AccessDenied, - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .PERM => return error.PermissionDenied, - .DQUOT => return error.DiskQuota, - .EXIST => return error.PathAlreadyExists, - .FAULT => |err| return errnoBug(err), - .LOOP => return error.SymLinkLoop, - .MLINK => return error.LinkQuotaExceeded, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOMEM => return error.SystemResources, - .NOSPC => return error.NoSpaceLeft, - .NOTDIR => return error.NotDir, - .ROFS => return error.ReadOnlyFileSystem, - .NOTCAPABLE => return error.AccessDenied, - .ILSEQ => return error.BadPathName, - else => |err| return posix.unexpectedErrno(err), - } - } -} + .now = now, + .sleep = sleep, -fn dirMakeWindows(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode: Io.Dir.Mode) Io.Dir.MakeError!void { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - try t.checkCancel(); + .random = random, + .randomSecure = randomSecure, - const sub_path_w = try windows.sliceToPrefixedFileW(dir.handle, sub_path); - _ = mode; - const sub_dir_handle = windows.OpenFile(sub_path_w.span(), .{ - .dir = dir.handle, - .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE, - .creation = windows.FILE_CREATE, - .filter = .dir_only, - }) catch |err| switch (err) { - error.IsDir => return error.Unexpected, - error.PipeBusy => return error.Unexpected, - error.NoDevice => return error.Unexpected, - error.WouldBlock => return error.Unexpected, - error.AntivirusInterference => return error.Unexpected, - else => |e| return e, + .netListenIp = netListenIpUnavailable, + .netListenUnix = netListenUnixUnavailable, + .netAccept = netAcceptUnavailable, + .netBindIp = netBindIpUnavailable, + .netConnectIp = netConnectIpUnavailable, + .netConnectUnix = netConnectUnixUnavailable, + .netClose = netCloseUnavailable, + .netShutdown = netShutdownUnavailable, + .netRead = netReadUnavailable, + .netWrite = netWriteUnavailable, + .netWriteFile = netWriteFileUnavailable, + .netSend = netSendUnavailable, + .netReceive = netReceiveUnavailable, + .netInterfaceNameResolve = netInterfaceNameResolveUnavailable, + .netInterfaceName = netInterfaceNameUnavailable, + .netLookup = netLookupUnavailable, + }, }; - windows.CloseHandle(sub_dir_handle); } -const dirMakePath = switch (native_os) { - .windows => dirMakePathWindows, - else => dirMakePathPosix, +pub const socket_flags_unsupported = is_darwin or native_os == .haiku; +const have_accept4 = !socket_flags_unsupported; +const have_flock_open_flags = @hasField(posix.O, "EXLOCK"); +const have_networking = native_os != .wasi; +const have_flock = @TypeOf(posix.system.flock) != void; +const have_sendmmsg = native_os == .linux; +const have_futex = switch (builtin.cpu.arch) { + .wasm32, .wasm64 => builtin.cpu.has(.wasm, .atomics), + else => true, +}; +const have_preadv = switch (native_os) { + .windows, .haiku => false, + else => true, +}; +const have_sig_io = posix.SIG != void and @hasField(posix.SIG, "IO"); +const have_sig_pipe = posix.SIG != void and @hasField(posix.SIG, "PIPE"); +const have_sendfile = if (builtin.link_libc) @TypeOf(std.c.sendfile) != void else native_os == .linux; +const have_copy_file_range = switch (native_os) { + .linux, .freebsd => true, + else => false, +}; +const have_fcopyfile = is_darwin; +const have_fchmodat2 = native_os == .linux and + (builtin.os.isAtLeast(.linux, .{ .major = 6, .minor = 6, .patch = 0 }) orelse true) and + (builtin.abi.isAndroid() or !std.c.versionCheck(.{ .major = 2, .minor = 32, .patch = 0 })); +const have_fchmodat_flags = native_os != .linux or + (!builtin.abi.isAndroid() and std.c.versionCheck(.{ .major = 2, .minor = 32, .patch = 0 })); + +const have_fchown = switch (native_os) { + .wasi, .windows => false, + else => true, }; -fn dirMakePathPosix(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode: Io.Dir.Mode) Io.Dir.MakeError!void { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - _ = t; - _ = dir; - _ = sub_path; - _ = mode; - @panic("TODO implement dirMakePathPosix"); -} +const have_fchmod = switch (native_os) { + .windows => false, + .wasi => builtin.link_libc, + else => true, +}; -fn dirMakePathWindows(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode: Io.Dir.Mode) Io.Dir.MakeError!void { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - _ = t; - _ = dir; - _ = sub_path; - _ = mode; - @panic("TODO implement dirMakePathWindows"); -} +const have_waitid = switch (native_os) { + .linux => @hasField(std.os.linux.SYS, "waitid"), + else => false, +}; -const dirMakeOpenPath = switch (native_os) { - .windows => dirMakeOpenPathWindows, - .wasi => dirMakeOpenPathWasi, - else => dirMakeOpenPathPosix, +const have_wait4 = switch (native_os) { + .linux => @hasField(std.os.linux.SYS, "wait4"), + .dragonfly, .freebsd, .netbsd, .openbsd, .illumos, .serenity, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => true, + else => false, }; -fn dirMakeOpenPathPosix( - userdata: ?*anyopaque, - dir: Io.Dir, - sub_path: []const u8, - options: Io.Dir.OpenOptions, -) Io.Dir.MakeOpenPathError!Io.Dir { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - const t_io = ioBasic(t); - return dirOpenDirPosix(t, dir, sub_path, options) catch |err| switch (err) { - error.FileNotFound => { - try dir.makePath(t_io, sub_path); - return dirOpenDirPosix(t, dir, sub_path, options); - }, - else => |e| return e, - }; -} +const open_sym = if (posix.lfs64_abi) posix.system.open64 else posix.system.open; +const openat_sym = if (posix.lfs64_abi) posix.system.openat64 else posix.system.openat; +const fstat_sym = if (posix.lfs64_abi) posix.system.fstat64 else posix.system.fstat; +const fstatat_sym = if (posix.lfs64_abi) posix.system.fstatat64 else posix.system.fstatat; +const lseek_sym = if (posix.lfs64_abi) posix.system.lseek64 else posix.system.lseek; +const preadv_sym = if (posix.lfs64_abi) posix.system.preadv64 else posix.system.preadv; +const ftruncate_sym = if (posix.lfs64_abi) posix.system.ftruncate64 else posix.system.ftruncate; +const pwritev_sym = if (posix.lfs64_abi) posix.system.pwritev64 else posix.system.pwritev; +const sendfile_sym = if (posix.lfs64_abi) posix.system.sendfile64 else posix.system.sendfile; +const linux_copy_file_range_use_c = std.c.versionCheck(if (builtin.abi.isAndroid()) .{ + .major = 34, + .minor = 0, + .patch = 0, +} else .{ + .major = 2, + .minor = 27, + .patch = 0, +}); +const linux_copy_file_range_sys = if (linux_copy_file_range_use_c) std.c else std.os.linux; + +const statx_use_c = std.c.versionCheck(if (builtin.abi.isAndroid()) + .{ .major = 30, .minor = 0, .patch = 0 } +else + .{ .major = 2, .minor = 28, .patch = 0 }); + +const use_libc_getrandom = std.c.versionCheck(if (builtin.abi.isAndroid()) .{ + .major = 28, + .minor = 0, + .patch = 0, +} else .{ + .major = 2, + .minor = 25, + .patch = 0, +}); + +const use_dev_urandom = @TypeOf(posix.system.getrandom) == void and native_os == .linux; -fn dirMakeOpenPathWindows( +fn async( userdata: ?*anyopaque, - dir: Io.Dir, - sub_path: []const u8, - options: Io.Dir.OpenOptions, -) Io.Dir.MakeOpenPathError!Io.Dir { + result: []u8, + result_alignment: Alignment, + context: []const u8, + context_alignment: Alignment, + start: *const fn (context: *const anyopaque, result: *anyopaque) void, +) ?*Io.AnyFuture { const t: *Threaded = @ptrCast(@alignCast(userdata)); - const w = windows; - const access_mask = w.STANDARD_RIGHTS_READ | w.FILE_READ_ATTRIBUTES | w.FILE_READ_EA | - w.SYNCHRONIZE | w.FILE_TRAVERSE | - (if (options.iterate) w.FILE_LIST_DIRECTORY else @as(u32, 0)); + if (builtin.single_threaded) { + start(context.ptr, result.ptr); + return null; + } - var it = std.fs.path.componentIterator(sub_path); - // If there are no components in the path, then create a dummy component with the full path. - var component: std.fs.path.NativeComponentIterator.Component = it.last() orelse .{ - .name = "", - .path = sub_path, + const gpa = t.allocator; + const future = Future.create(gpa, result.len, result_alignment, context, context_alignment, start) catch |err| switch (err) { + error.OutOfMemory => { + start(context.ptr, result.ptr); + return null; + }, }; - while (true) { - try t.checkCancel(); - - const sub_path_w_array = try w.sliceToPrefixedFileW(dir.handle, component.path); - const sub_path_w = sub_path_w_array.span(); - const is_last = it.peekNext() == null; - const create_disposition: u32 = if (is_last) w.FILE_OPEN_IF else w.FILE_CREATE; + t.mutex.lock(); - var result: Io.Dir = .{ .handle = undefined }; + const busy_count = t.busy_count; - const path_len_bytes: u16 = @intCast(sub_path_w.len * 2); - var nt_name: w.UNICODE_STRING = .{ - .Length = path_len_bytes, - .MaximumLength = path_len_bytes, - .Buffer = @constCast(sub_path_w.ptr), - }; - var attr: w.OBJECT_ATTRIBUTES = .{ - .Length = @sizeOf(w.OBJECT_ATTRIBUTES), - .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir.handle, - .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. - .ObjectName = &nt_name, - .SecurityDescriptor = null, - .SecurityQualityOfService = null, - }; - const open_reparse_point: w.DWORD = if (!options.follow_symlinks) w.FILE_OPEN_REPARSE_POINT else 0x0; - var io_status_block: w.IO_STATUS_BLOCK = undefined; - const rc = w.ntdll.NtCreateFile( - &result.handle, - access_mask, - &attr, - &io_status_block, - null, - w.FILE_ATTRIBUTE_NORMAL, - w.FILE_SHARE_READ | w.FILE_SHARE_WRITE | w.FILE_SHARE_DELETE, - create_disposition, - w.FILE_DIRECTORY_FILE | w.FILE_SYNCHRONOUS_IO_NONALERT | w.FILE_OPEN_FOR_BACKUP_INTENT | open_reparse_point, - null, - 0, - ); + if (busy_count >= @intFromEnum(t.async_limit)) { + t.mutex.unlock(); + future.destroy(gpa); + start(context.ptr, result.ptr); + return null; + } - switch (rc) { - .SUCCESS => { - component = it.next() orelse return result; - w.CloseHandle(result.handle); - continue; - }, - .OBJECT_NAME_INVALID => return error.BadPathName, - .OBJECT_NAME_COLLISION => { - assert(!is_last); - // stat the file and return an error if it's not a directory - // this is important because otherwise a dangling symlink - // could cause an infinite loop - check_dir: { - // workaround for windows, see https://github.com/ziglang/zig/issues/16738 - const fstat = dirStatPathWindows(t, dir, component.path, .{ - .follow_symlinks = options.follow_symlinks, - }) catch |stat_err| switch (stat_err) { - error.IsDir => break :check_dir, - else => |e| return e, - }; - if (fstat.kind != .directory) return error.NotDir; - } + t.busy_count = busy_count + 1; - component = it.next().?; - continue; - }, + const pool_size = t.wait_group.value(); + if (pool_size - busy_count == 0) { + t.wait_group.start(); + const thread = std.Thread.spawn(.{ .stack_size = t.stack_size }, worker, .{t}) catch { + t.wait_group.finish(); + t.busy_count = busy_count; + t.mutex.unlock(); + future.destroy(gpa); + start(context.ptr, result.ptr); + return null; + }; + thread.detach(); + } - .OBJECT_NAME_NOT_FOUND, - .OBJECT_PATH_NOT_FOUND, - => { - component = it.previous() orelse return error.FileNotFound; - continue; - }, + t.run_queue.prepend(&future.runnable.node); - .NOT_A_DIRECTORY => return error.NotDir, - // This can happen if the directory has 'List folder contents' permission set to 'Deny' - // and the directory is trying to be opened for iteration. - .ACCESS_DENIED => return error.AccessDenied, - .INVALID_PARAMETER => |err| return w.statusBug(err), - else => return w.unexpectedStatus(rc), - } - } + t.mutex.unlock(); + t.cond.signal(); + return @ptrCast(future); } -fn dirMakeOpenPathWasi( +fn concurrent( userdata: ?*anyopaque, - dir: Io.Dir, - sub_path: []const u8, - options: Io.Dir.OpenOptions, -) Io.Dir.MakeOpenPathError!Io.Dir { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - const t_io = ioBasic(t); - return dirOpenDirWasi(t, dir, sub_path, options) catch |err| switch (err) { - error.FileNotFound => { - try dir.makePath(t_io, sub_path); - return dirOpenDirWasi(t, dir, sub_path, options); - }, - else => |e| return e, - }; -} + result_len: usize, + result_alignment: Alignment, + context: []const u8, + context_alignment: Alignment, + start: *const fn (context: *const anyopaque, result: *anyopaque) void, +) Io.ConcurrentError!*Io.AnyFuture { + if (builtin.single_threaded) return error.ConcurrencyUnavailable; -fn dirStat(userdata: ?*anyopaque, dir: Io.Dir) Io.Dir.StatError!Io.Dir.Stat { const t: *Threaded = @ptrCast(@alignCast(userdata)); - try t.checkCancel(); - _ = dir; - @panic("TODO implement dirStat"); -} + const gpa = t.allocator; + const future = Future.create(gpa, result_len, result_alignment, context, context_alignment, start) catch |err| switch (err) { + error.OutOfMemory => return error.ConcurrencyUnavailable, + }; + errdefer future.destroy(gpa); -const dirStatPath = switch (native_os) { - .linux => dirStatPathLinux, - .windows => dirStatPathWindows, - .wasi => dirStatPathWasi, - else => dirStatPathPosix, -}; + t.mutex.lock(); + defer t.mutex.unlock(); -fn dirStatPathLinux( - userdata: ?*anyopaque, - dir: Io.Dir, - sub_path: []const u8, - options: Io.Dir.StatPathOptions, -) Io.Dir.StatPathError!Io.File.Stat { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - const linux = std.os.linux; + const busy_count = t.busy_count; - var path_buffer: [posix.PATH_MAX]u8 = undefined; - const sub_path_posix = try pathToPosix(sub_path, &path_buffer); + if (busy_count >= @intFromEnum(t.concurrent_limit)) + return error.ConcurrencyUnavailable; - const flags: u32 = linux.AT.NO_AUTOMOUNT | - @as(u32, if (!options.follow_symlinks) linux.AT.SYMLINK_NOFOLLOW else 0); + t.busy_count = busy_count + 1; + errdefer t.busy_count = busy_count; - while (true) { - try t.checkCancel(); - var statx = std.mem.zeroes(linux.Statx); - const rc = linux.statx( - dir.handle, - sub_path_posix, - flags, - linux.STATX_INO | linux.STATX_SIZE | linux.STATX_TYPE | linux.STATX_MODE | linux.STATX_ATIME | linux.STATX_MTIME | linux.STATX_CTIME, - &statx, - ); - switch (linux.errno(rc)) { - .SUCCESS => return statFromLinux(&statx), - .INTR => continue, - .CANCELED => return error.Canceled, + const pool_size = t.wait_group.value(); + if (pool_size - busy_count == 0) { + t.wait_group.start(); + errdefer t.wait_group.finish(); - .ACCES => return error.AccessDenied, - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .FAULT => |err| return errnoBug(err), - .INVAL => |err| return errnoBug(err), - .LOOP => return error.SymLinkLoop, - .NAMETOOLONG => |err| return errnoBug(err), // Handled by pathToPosix() above. - .NOENT => return error.FileNotFound, - .NOTDIR => return error.NotDir, - .NOMEM => return error.SystemResources, - else => |err| return posix.unexpectedErrno(err), - } + const thread = std.Thread.spawn(.{ .stack_size = t.stack_size }, worker, .{t}) catch + return error.ConcurrencyUnavailable; + + thread.detach(); } + + t.run_queue.prepend(&future.runnable.node); + + t.cond.signal(); + return @ptrCast(future); } -fn dirStatPathPosix( +fn groupAsync( userdata: ?*anyopaque, - dir: Io.Dir, - sub_path: []const u8, - options: Io.Dir.StatPathOptions, -) Io.Dir.StatPathError!Io.File.Stat { + type_erased: *Io.Group, + context: []const u8, + context_alignment: Alignment, + start: *const fn (context: *const anyopaque) Io.Cancelable!void, +) void { const t: *Threaded = @ptrCast(@alignCast(userdata)); + const g: Group = .{ .ptr = type_erased }; - var path_buffer: [posix.PATH_MAX]u8 = undefined; - const sub_path_posix = try pathToPosix(sub_path, &path_buffer); + if (builtin.single_threaded) return groupAsyncEager(start, context.ptr); - const flags: u32 = if (!options.follow_symlinks) posix.AT.SYMLINK_NOFOLLOW else 0; + const gpa = t.allocator; + const task = Group.Task.create(gpa, g, context, context_alignment, start) catch |err| switch (err) { + error.OutOfMemory => return groupAsyncEager(start, context.ptr), + }; - while (true) { - try t.checkCancel(); - var stat = std.mem.zeroes(posix.Stat); - switch (posix.errno(fstatat_sym(dir.handle, sub_path_posix, &stat, flags))) { - .SUCCESS => return statFromPosix(&stat), - .INTR => continue, - .CANCELED => return error.Canceled, + t.mutex.lock(); - .INVAL => |err| return errnoBug(err), - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .NOMEM => return error.SystemResources, - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - .FAULT => |err| return errnoBug(err), - .NAMETOOLONG => return error.NameTooLong, - .LOOP => return error.SymLinkLoop, - .NOENT => return error.FileNotFound, - .NOTDIR => return error.FileNotFound, - .ILSEQ => return error.BadPathName, - else => |err| return posix.unexpectedErrno(err), - } + const busy_count = t.busy_count; + + if (busy_count >= @intFromEnum(t.async_limit)) { + t.mutex.unlock(); + task.destroy(gpa); + return groupAsyncEager(start, context.ptr); + } + + t.busy_count = busy_count + 1; + + const pool_size = t.wait_group.value(); + if (pool_size - busy_count == 0) { + t.wait_group.start(); + const thread = std.Thread.spawn(.{ .stack_size = t.stack_size }, worker, .{t}) catch { + t.wait_group.finish(); + t.busy_count = busy_count; + t.mutex.unlock(); + task.destroy(gpa); + return groupAsyncEager(start, context.ptr); + }; + thread.detach(); } + + // TODO: if this logic is changed to be lock-free, this `fetchAdd` must be released by the queue + // prepend so that the task doesn't finish without observing this and try to decrement the count + // below zero. + _ = g.status().fetchAdd(.{ + .num_running = 1, + .have_awaiter = false, + .canceled = false, + }, .monotonic); + t.run_queue.prepend(&task.runnable.node); + + t.mutex.unlock(); + t.cond.signal(); } +fn groupAsyncEager( + start: *const fn (context: *const anyopaque) Io.Cancelable!void, + context: *const anyopaque, +) void { + const pre_acknowledged = if (Thread.current) |thread| ack: { + break :ack switch (thread.status.load(.monotonic).cancelation) { + .none, .canceling => false, + .canceled => true, + .parked => unreachable, + .blocked => unreachable, + .blocked_windows_dns => unreachable, + .blocked_canceling => unreachable, + }; + } else false; + const result = start(context); + const post_acknowledged = if (Thread.current) |thread| ack: { + break :ack switch (thread.status.load(.monotonic).cancelation) { + .none, .canceling => false, + .canceled => true, + .parked => unreachable, + .blocked => unreachable, + .blocked_windows_dns => unreachable, + .blocked_canceling => unreachable, + }; + } else false; -fn dirStatPathWindows( - userdata: ?*anyopaque, - dir: Io.Dir, - sub_path: []const u8, - options: Io.Dir.StatPathOptions, -) Io.Dir.StatPathError!Io.File.Stat { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - const file = try dirOpenFileWindows(t, dir, sub_path, .{ - .follow_symlinks = options.follow_symlinks, - }); - defer windows.CloseHandle(file.handle); - return fileStatWindows(t, file); + if (result) { + if (pre_acknowledged) { + assert(post_acknowledged); // group task called `recancel` but was not canceled + } else { + assert(!post_acknowledged); // group task acknowledged cancelation but did not return `error.Canceled` + } + } else |err| switch (err) { + // Don't swallow the cancelation: make it visible to the `Group.async` caller. + error.Canceled => { + assert(!pre_acknowledged); // group task called `recancel` but was not canceled + assert(post_acknowledged); // group task returned `error.Canceled` but was never canceled + recancelInner(); + }, + } } -fn dirStatPathWasi( +fn groupConcurrent( userdata: ?*anyopaque, - dir: Io.Dir, - sub_path: []const u8, - options: Io.Dir.StatPathOptions, -) Io.Dir.StatPathError!Io.File.Stat { - if (builtin.link_libc) return dirStatPathPosix(userdata, dir, sub_path, options); + type_erased: *Io.Group, + context: []const u8, + context_alignment: Alignment, + start: *const fn (context: *const anyopaque) Io.Cancelable!void, +) Io.ConcurrentError!void { + if (builtin.single_threaded) return error.ConcurrencyUnavailable; + const t: *Threaded = @ptrCast(@alignCast(userdata)); - const wasi = std.os.wasi; - const flags: wasi.lookupflags_t = .{ - .SYMLINK_FOLLOW = options.follow_symlinks, + const g: Group = .{ .ptr = type_erased }; + + const gpa = t.allocator; + const task = Group.Task.create(gpa, g, context, context_alignment, start) catch |err| switch (err) { + error.OutOfMemory => return error.ConcurrencyUnavailable, }; - var stat: wasi.filestat_t = undefined; - while (true) { - try t.checkCancel(); - switch (wasi.path_filestat_get(dir.handle, flags, sub_path.ptr, sub_path.len, &stat)) { - .SUCCESS => return statFromWasi(&stat), - .INTR => continue, - .CANCELED => return error.Canceled, + errdefer task.destroy(gpa); - .INVAL => |err| return errnoBug(err), - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .NOMEM => return error.SystemResources, - .ACCES => return error.AccessDenied, - .FAULT => |err| return errnoBug(err), - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOTDIR => return error.FileNotFound, - .NOTCAPABLE => return error.AccessDenied, - .ILSEQ => return error.BadPathName, - else => |err| return posix.unexpectedErrno(err), - } - } -} + t.mutex.lock(); + defer t.mutex.unlock(); -const fileStat = switch (native_os) { - .linux => fileStatLinux, - .windows => fileStatWindows, - .wasi => fileStatWasi, - else => fileStatPosix, -}; + const busy_count = t.busy_count; -fn fileStatPosix(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File.Stat { - const t: *Threaded = @ptrCast(@alignCast(userdata)); + if (busy_count >= @intFromEnum(t.concurrent_limit)) + return error.ConcurrencyUnavailable; - if (posix.Stat == void) return error.Streaming; + t.busy_count = busy_count + 1; + errdefer t.busy_count = busy_count; - while (true) { - try t.checkCancel(); - var stat = std.mem.zeroes(posix.Stat); - switch (posix.errno(fstat_sym(file.handle, &stat))) { - .SUCCESS => return statFromPosix(&stat), - .INTR => continue, - .CANCELED => return error.Canceled, + const pool_size = t.wait_group.value(); + if (pool_size - busy_count == 0) { + t.wait_group.start(); + errdefer t.wait_group.finish(); - .INVAL => |err| return errnoBug(err), - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .NOMEM => return error.SystemResources, - .ACCES => return error.AccessDenied, - else => |err| return posix.unexpectedErrno(err), - } + const thread = std.Thread.spawn(.{ .stack_size = t.stack_size }, worker, .{t}) catch + return error.ConcurrencyUnavailable; + + thread.detach(); } + + // TODO: if this logic is changed to be lock-free, this `fetchAdd` must be released by the queue + // prepend so that the task doesn't finish without observing this and try to decrement the count + // below zero. + _ = g.status().fetchAdd(.{ + .num_running = 1, + .have_awaiter = false, + .canceled = false, + }, .monotonic); + t.run_queue.prepend(&task.runnable.node); + + t.cond.signal(); } -fn fileStatLinux(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File.Stat { +fn groupAwait(userdata: ?*anyopaque, type_erased: *Io.Group, initial_token: *anyopaque) Io.Cancelable!void { + _ = initial_token; // we need to load `token` *after* the group finishes const t: *Threaded = @ptrCast(@alignCast(userdata)); - const linux = std.os.linux; - while (true) { - try t.checkCancel(); - var statx = std.mem.zeroes(linux.Statx); - const rc = linux.statx( - file.handle, - "", - linux.AT.EMPTY_PATH, - linux.STATX_INO | linux.STATX_SIZE | linux.STATX_TYPE | linux.STATX_MODE | linux.STATX_ATIME | linux.STATX_MTIME | linux.STATX_CTIME, - &statx, - ); - switch (linux.errno(rc)) { - .SUCCESS => return statFromLinux(&statx), - .INTR => continue, - .CANCELED => return error.Canceled, + const g: Group = .{ .ptr = type_erased }; + + var num_completed: std.atomic.Value(u32) = .init(0); + g.awaiter().* = &num_completed; + + const pre_await_status = g.status().fetchOr(.{ + .num_running = 0, + .have_awaiter = true, + .canceled = false, + }, .acq_rel); // acquire results if complete; release `g.awaiter()` + + assert(!pre_await_status.have_awaiter); + assert(!pre_await_status.canceled); + if (pre_await_status.num_running == 0) { + // Already done. Since the group is finished, it's illegal to spawn more tasks in it + // until we return, so we can access `g.status()` non-atomically. + g.status().raw.have_awaiter = false; + return; + } - .ACCES => |err| return errnoBug(err), - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .FAULT => |err| return errnoBug(err), - .INVAL => |err| return errnoBug(err), - .LOOP => |err| return errnoBug(err), - .NAMETOOLONG => |err| return errnoBug(err), - .NOENT => |err| return errnoBug(err), - .NOMEM => return error.SystemResources, - .NOTDIR => |err| return errnoBug(err), - else => |err| return posix.unexpectedErrno(err), + while (Thread.futexWait(&num_completed.raw, 0, null)) { + switch (num_completed.load(.acquire)) { // acquire task results + 0 => continue, + 1 => break, + else => unreachable, // group was reused before `await` returned } + } else |err| switch (err) { + error.Canceled => { + const pre_cancel_status = g.status().fetchOr(.{ + .num_running = 0, + .have_awaiter = false, + .canceled = true, + }, .acq_rel); // acquire results if complete; release `g.awaiter()` + assert(pre_cancel_status.have_awaiter); + assert(!pre_cancel_status.canceled); + + // Even if `pre_cancel_status.num_running == 0`, we still need to wait for the signal, + // because in that case the last member of the group is already trying to modify it. + // However, if we know everything is done, we *can* skip signaling blocked threads. + const skip_signals = pre_cancel_status.num_running == 0; + g.waitForCancelWithSignaling(t, &num_completed, skip_signals); + + // The group is finished, so it's illegal to spawn more tasks in it until we return, so + // we can access `g.status()` non-atomically. + g.status().raw.canceled = false; + g.status().raw.have_awaiter = false; + return error.Canceled; + }, } + + // The group is finished, so it's illegal to spawn more tasks in it until we return, so + // we can access `g.status()` non-atomically. + g.status().raw.have_awaiter = false; } -fn fileStatWindows(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File.Stat { +fn groupCancel(userdata: ?*anyopaque, type_erased: *Io.Group, initial_token: *anyopaque) void { + _ = initial_token; const t: *Threaded = @ptrCast(@alignCast(userdata)); - try t.checkCancel(); + const g: Group = .{ .ptr = type_erased }; + + var num_completed: std.atomic.Value(u32) = .init(0); + g.awaiter().* = &num_completed; + + const pre_cancel_status = g.status().fetchOr(.{ + .num_running = 0, + .have_awaiter = true, + .canceled = true, + }, .acq_rel); // acquire results if complete; release `g.awaiter()` + + assert(!pre_cancel_status.have_awaiter); + assert(!pre_cancel_status.canceled); + if (pre_cancel_status.num_running == 0) { + // Already done. Since the group is finished, it's illegal to spawn more tasks in it + // until we return, so we can access `g.status()` non-atomically. + g.status().raw.have_awaiter = false; + g.status().raw.canceled = false; + return; + } - var io_status_block: windows.IO_STATUS_BLOCK = undefined; - var info: windows.FILE_ALL_INFORMATION = undefined; - const rc = windows.ntdll.NtQueryInformationFile(file.handle, &io_status_block, &info, @sizeOf(windows.FILE_ALL_INFORMATION), .FileAllInformation); - switch (rc) { - .SUCCESS => {}, - // Buffer overflow here indicates that there is more information available than was able to be stored in the buffer - // size provided. This is treated as success because the type of variable-length information that this would be relevant for - // (name, volume name, etc) we don't care about. - .BUFFER_OVERFLOW => {}, - .INVALID_PARAMETER => unreachable, - .ACCESS_DENIED => return error.AccessDenied, - else => return windows.unexpectedStatus(rc), + g.waitForCancelWithSignaling(t, &num_completed, false); + + g.status().raw = .{ .num_running = 0, .have_awaiter = false, .canceled = false }; +} + +fn recancel(userdata: ?*anyopaque) void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + recancelInner(); +} +fn recancelInner() void { + const thread = Thread.current.?; // called `recancel` but was not canceled + switch (thread.status.fetchXor(.{ + .cancelation = @enumFromInt(0b001), + .awaitable = .null, + }, .monotonic).cancelation) { + .canceled => {}, + .none => unreachable, // called `recancel` but was not canceled + .canceling => unreachable, // called `recancel` but cancelation was already pending + .parked => unreachable, + .blocked => unreachable, + .blocked_windows_dns => unreachable, + .blocked_canceling => unreachable, } - return .{ - .inode = info.InternalInformation.IndexNumber, - .size = @as(u64, @bitCast(info.StandardInformation.EndOfFile)), - .mode = 0, - .kind = if (info.BasicInformation.FileAttributes & windows.FILE_ATTRIBUTE_REPARSE_POINT != 0) reparse_point: { - var tag_info: windows.FILE_ATTRIBUTE_TAG_INFO = undefined; - const tag_rc = windows.ntdll.NtQueryInformationFile(file.handle, &io_status_block, &tag_info, @sizeOf(windows.FILE_ATTRIBUTE_TAG_INFO), .FileAttributeTagInformation); - switch (tag_rc) { - .SUCCESS => {}, - // INFO_LENGTH_MISMATCH and ACCESS_DENIED are the only documented possible errors - // https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/d295752f-ce89-4b98-8553-266d37c84f0e - .INFO_LENGTH_MISMATCH => unreachable, - .ACCESS_DENIED => return error.AccessDenied, - else => return windows.unexpectedStatus(rc), - } - if (tag_info.ReparseTag & windows.reparse_tag_name_surrogate_bit != 0) { - break :reparse_point .sym_link; +} + +fn swapCancelProtection(userdata: ?*anyopaque, new: Io.CancelProtection) Io.CancelProtection { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + const thread = Thread.current orelse return .unblocked; + const old = thread.cancel_protection; + thread.cancel_protection = new; + return old; +} + +fn checkCancel(userdata: ?*anyopaque) Io.Cancelable!void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + return Thread.checkCancel(); +} + +fn await( + userdata: ?*anyopaque, + any_future: *Io.AnyFuture, + result: []u8, + result_alignment: Alignment, +) void { + _ = result_alignment; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + const future: *Future = @ptrCast(@alignCast(any_future)); + + var num_completed: std.atomic.Value(u32) = .init(0); + future.awaiter = &num_completed; + + const pre_await_status = future.status.fetchOr(.{ + .tag = .pending_awaited, + .thread = .null, + }, .acq_rel); // acquire results if complete; release `future.awaiter` + switch (pre_await_status.tag) { + .pending => while (Thread.futexWait(&num_completed.raw, 0, null)) { + switch (num_completed.load(.acquire)) { // acquire task results + 0 => continue, + 1 => break, + else => unreachable, // group was reused before `await` returned } - // Unknown reparse point - break :reparse_point .unknown; - } else if (info.BasicInformation.FileAttributes & windows.FILE_ATTRIBUTE_DIRECTORY != 0) - .directory - else - .file, - .atime = windows.fromSysTime(info.BasicInformation.LastAccessTime), - .mtime = windows.fromSysTime(info.BasicInformation.LastWriteTime), - .ctime = windows.fromSysTime(info.BasicInformation.ChangeTime), + } else |err| switch (err) { + error.Canceled => { + const pre_cancel_status = future.status.fetchOr(.{ + .tag = .pending_canceled, + .thread = .null, + }, .acq_rel); // acquire results if complete; release `future.awaiter` + const done_status = switch (pre_cancel_status.tag) { + .pending => unreachable, // invalid state: we already awaited + .pending_awaited => done_status: { + const working_thread = pre_cancel_status.thread.unpack(); + future.waitForCancelWithSignaling(t, &num_completed, @alignCast(working_thread)); + break :done_status future.status.load(.monotonic); + }, + .pending_canceled => unreachable, // `await` raced with `cancel` + .done => done_status: { + // The task just finished, but we still need to wait for the signal, because the + // task thread already figured out that they need to update `future.awaiter`. + future.waitForCancelWithSignaling(t, &num_completed, null); + // Also, we have clobbered `future.status.tag` to `.pending_canceled`, but that's + // not actually a problem for the logic below. + break :done_status pre_cancel_status; + }, + }; + // If the future did not acknowledge the cancelation, we need to mark it outstanding + // for us. Because `done_status.tag == .done`, the information about whether there + // was an acknowledged cancelation is encoded in `done_status.thread`. + assert(done_status.tag == .done); + switch (done_status.thread) { + .null => recancelInner(), // cancelation was not acknowledged, so it's ours + .all_ones => {}, // cancelation was acknowledged, so it was this task's job to propagate it + _ => unreachable, + } + }, + }, + .pending_awaited => unreachable, // `await` raced with `await` + .pending_canceled => unreachable, // `await` raced with `cancel` + .done => {}, + } + @memcpy(result, future.resultPointer()); + future.destroy(t.allocator); +} + +fn cancel( + userdata: ?*anyopaque, + any_future: *Io.AnyFuture, + result: []u8, + result_alignment: Alignment, +) void { + _ = result_alignment; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + const future: *Future = @ptrCast(@alignCast(any_future)); + + var num_completed: std.atomic.Value(u32) = .init(0); + future.awaiter = &num_completed; + + const pre_cancel_status = future.status.fetchOr(.{ + .tag = .pending_canceled, + .thread = .null, + }, .acq_rel); // acquire results if complete; release `future.awaiter` + switch (pre_cancel_status.tag) { + .pending => { + const working_thread = pre_cancel_status.thread.unpack(); + future.waitForCancelWithSignaling(t, &num_completed, @alignCast(working_thread)); + }, + .pending_awaited => unreachable, // `await` raced with `await` + .pending_canceled => unreachable, // `await` raced with `cancel` + .done => {}, + } + @memcpy(result, future.resultPointer()); + future.destroy(t.allocator); +} + +fn futexWait(userdata: ?*anyopaque, ptr: *const u32, expected: u32, timeout: Io.Timeout) Io.Cancelable!void { + if (builtin.single_threaded) unreachable; // Deadlock. + const t: *Threaded = @ptrCast(@alignCast(userdata)); + const t_io = ioBasic(t); + const timeout_ns: ?u64 = ns: { + const d = (timeout.toDurationFromNow(t_io) catch break :ns 10) orelse break :ns null; + break :ns std.math.lossyCast(u64, d.raw.toNanoseconds()); }; + return Thread.futexWait(ptr, expected, timeout_ns); } -fn fileStatWasi(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File.Stat { - if (builtin.link_libc) return fileStatPosix(userdata, file); +fn futexWaitUncancelable(userdata: ?*anyopaque, ptr: *const u32, expected: u32) void { + if (builtin.single_threaded) unreachable; // Deadlock. const t: *Threaded = @ptrCast(@alignCast(userdata)); - while (true) { - try t.checkCancel(); - var stat: std.os.wasi.filestat_t = undefined; - switch (std.os.wasi.fd_filestat_get(file.handle, &stat)) { - .SUCCESS => return statFromWasi(&stat), - .INTR => continue, - .CANCELED => return error.Canceled, + _ = t; + Thread.futexWaitUncancelable(ptr, expected, null); +} - .INVAL => |err| return errnoBug(err), - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .NOMEM => return error.SystemResources, - .ACCES => return error.AccessDenied, - .NOTCAPABLE => return error.AccessDenied, - else => |err| return posix.unexpectedErrno(err), - } - } +fn futexWake(userdata: ?*anyopaque, ptr: *const u32, max_waiters: u32) void { + if (builtin.single_threaded) unreachable; // Nothing to wake up. + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + Thread.futexWake(ptr, max_waiters); } -const dirAccess = switch (native_os) { - .windows => dirAccessWindows, - .wasi => dirAccessWasi, - else => dirAccessPosix, +const dirCreateDir = switch (native_os) { + .windows => dirCreateDirWindows, + .wasi => dirCreateDirWasi, + else => dirCreateDirPosix, }; -fn dirAccessPosix( - userdata: ?*anyopaque, - dir: Io.Dir, - sub_path: []const u8, - options: Io.Dir.AccessOptions, -) Io.Dir.AccessError!void { +fn dirCreateDirPosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, permissions: Dir.Permissions) Dir.CreateDirError!void { const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; var path_buffer: [posix.PATH_MAX]u8 = undefined; const sub_path_posix = try pathToPosix(sub_path, &path_buffer); - const flags: u32 = @as(u32, if (!options.follow_symlinks) posix.AT.SYMLINK_NOFOLLOW else 0); - - const mode: u32 = - @as(u32, if (options.read) posix.R_OK else 0) | - @as(u32, if (options.write) posix.W_OK else 0) | - @as(u32, if (options.execute) posix.X_OK else 0); - + const syscall: Syscall = try .start(); while (true) { - try t.checkCancel(); - switch (posix.errno(posix.system.faccessat(dir.handle, sub_path_posix, mode, flags))) { - .SUCCESS => return, - .INTR => continue, - .CANCELED => return error.Canceled, - - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - .ROFS => return error.ReadOnlyFileSystem, - .LOOP => return error.SymLinkLoop, - .TXTBSY => return error.FileBusy, - .NOTDIR => return error.FileNotFound, - .NOENT => return error.FileNotFound, - .NAMETOOLONG => return error.NameTooLong, - .INVAL => |err| return errnoBug(err), - .FAULT => |err| return errnoBug(err), - .IO => return error.InputOutput, - .NOMEM => return error.SystemResources, - .ILSEQ => return error.BadPathName, - else => |err| return posix.unexpectedErrno(err), + switch (posix.errno(posix.system.mkdirat(dir.handle, sub_path_posix, permissions.toMode()))) { + .SUCCESS => { + syscall.finish(); + return; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ACCES => return error.AccessDenied, + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .PERM => return error.PermissionDenied, + .DQUOT => return error.DiskQuota, + .EXIST => return error.PathAlreadyExists, + .FAULT => |err| return errnoBug(err), + .LOOP => return error.SymLinkLoop, + .MLINK => return error.LinkQuotaExceeded, + .NAMETOOLONG => return error.NameTooLong, + .NOENT => return error.FileNotFound, + .NOMEM => return error.SystemResources, + .NOSPC => return error.NoSpaceLeft, + .NOTDIR => return error.NotDir, + .ROFS => return error.ReadOnlyFileSystem, + // dragonfly: when dir_fd is unlinked from filesystem + .NOTCONN => return error.FileNotFound, + .ILSEQ => return error.BadPathName, + else => |err| return posix.unexpectedErrno(err), + } + }, } } } -fn dirAccessWasi( - userdata: ?*anyopaque, - dir: Io.Dir, - sub_path: []const u8, - options: Io.Dir.AccessOptions, -) Io.Dir.AccessError!void { - if (builtin.link_libc) return dirAccessPosix(userdata, dir, sub_path, options); +fn dirCreateDirWasi(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, permissions: Dir.Permissions) Dir.CreateDirError!void { + if (builtin.link_libc) return dirCreateDirPosix(userdata, dir, sub_path, permissions); const t: *Threaded = @ptrCast(@alignCast(userdata)); - const wasi = std.os.wasi; - const flags: wasi.lookupflags_t = .{ - .SYMLINK_FOLLOW = options.follow_symlinks, - }; - var stat: wasi.filestat_t = undefined; + _ = t; + const syscall: Syscall = try .start(); while (true) { - try t.checkCancel(); - switch (wasi.path_filestat_get(dir.handle, flags, sub_path.ptr, sub_path.len, &stat)) { - .SUCCESS => break, - .INTR => continue, - .CANCELED => return error.Canceled, - - .INVAL => |err| return errnoBug(err), - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .NOMEM => return error.SystemResources, - .ACCES => return error.AccessDenied, - .FAULT => |err| return errnoBug(err), - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOTDIR => return error.FileNotFound, - .NOTCAPABLE => return error.AccessDenied, - .ILSEQ => return error.BadPathName, - else => |err| return posix.unexpectedErrno(err), - } - } - - if (!options.read and !options.write and !options.execute) - return; - - var directory: wasi.fdstat_t = undefined; - if (wasi.fd_fdstat_get(dir.handle, &directory) != .SUCCESS) - return error.AccessDenied; - - var rights: wasi.rights_t = .{}; - if (options.read) { - if (stat.filetype == .DIRECTORY) { - rights.FD_READDIR = true; - } else { - rights.FD_READ = true; + switch (std.os.wasi.path_create_directory(dir.handle, sub_path.ptr, sub_path.len)) { + .SUCCESS => { + syscall.finish(); + return; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ACCES => return error.AccessDenied, + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .PERM => return error.PermissionDenied, + .DQUOT => return error.DiskQuota, + .EXIST => return error.PathAlreadyExists, + .FAULT => |err| return errnoBug(err), + .LOOP => return error.SymLinkLoop, + .MLINK => return error.LinkQuotaExceeded, + .NAMETOOLONG => return error.NameTooLong, + .NOENT => return error.FileNotFound, + .NOMEM => return error.SystemResources, + .NOSPC => return error.NoSpaceLeft, + .NOTDIR => return error.NotDir, + .ROFS => return error.ReadOnlyFileSystem, + .NOTCAPABLE => return error.AccessDenied, + .ILSEQ => return error.BadPathName, + else => |err| return posix.unexpectedErrno(err), + } + }, } } - if (options.write) - rights.FD_WRITE = true; +} - // No validation for execution. +fn dirCreateDirWindows(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, permissions: Dir.Permissions) Dir.CreateDirError!void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; - // https://github.com/ziglang/zig/issues/18882 - const rights_int: u64 = @bitCast(rights); - const inheriting_int: u64 = @bitCast(directory.fs_rights_inheriting); - if ((rights_int & inheriting_int) != rights_int) - return error.AccessDenied; + const sub_path_w = try windows.sliceToPrefixedFileW(dir.handle, sub_path); + _ = permissions; // TODO use this value + + const syscall: Syscall = try .start(); + const sub_dir_handle = while (true) { + break windows.OpenFile(sub_path_w.span(), .{ + .dir = dir.handle, + .access_mask = .{ + .GENERIC = .{ .READ = true }, + .STANDARD = .{ .SYNCHRONIZE = true }, + }, + .creation = .CREATE, + .filter = .dir_only, + }) catch |err| switch (err) { + error.IsDir => return syscall.fail(error.Unexpected), + error.PipeBusy => return syscall.fail(error.Unexpected), + error.NoDevice => return syscall.fail(error.Unexpected), + error.WouldBlock => return syscall.fail(error.Unexpected), + error.AntivirusInterference => return syscall.fail(error.Unexpected), + error.OperationCanceled => { + try syscall.checkCancel(); + continue; + }, + else => |e| return syscall.fail(e), + }; + }; + syscall.finish(); + windows.CloseHandle(sub_dir_handle); } -fn dirAccessWindows( +fn dirCreateDirPath( userdata: ?*anyopaque, - dir: Io.Dir, + dir: Dir, sub_path: []const u8, - options: Io.Dir.AccessOptions, -) Io.Dir.AccessError!void { + permissions: Dir.Permissions, +) Dir.CreateDirPathError!Dir.CreatePathStatus { const t: *Threaded = @ptrCast(@alignCast(userdata)); - try t.checkCancel(); - - _ = options; // TODO - - const sub_path_w_array = try windows.sliceToPrefixedFileW(dir.handle, sub_path); - const sub_path_w = sub_path_w_array.span(); - if (sub_path_w[0] == '.' and sub_path_w[1] == 0) return; - if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) return; - - const path_len_bytes = std.math.cast(u16, std.mem.sliceTo(sub_path_w, 0).len * 2) orelse - return error.NameTooLong; - var nt_name: windows.UNICODE_STRING = .{ - .Length = path_len_bytes, - .MaximumLength = path_len_bytes, - .Buffer = @constCast(sub_path_w.ptr), - }; - var attr = windows.OBJECT_ATTRIBUTES{ - .Length = @sizeOf(windows.OBJECT_ATTRIBUTES), - .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir.handle, - .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. - .ObjectName = &nt_name, - .SecurityDescriptor = null, - .SecurityQualityOfService = null, - }; - var basic_info: windows.FILE_BASIC_INFORMATION = undefined; - switch (windows.ntdll.NtQueryAttributesFile(&attr, &basic_info)) { - .SUCCESS => return, - .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, - .OBJECT_PATH_NOT_FOUND => return error.FileNotFound, - .OBJECT_NAME_INVALID => |err| return windows.statusBug(err), - .INVALID_PARAMETER => |err| return windows.statusBug(err), - .ACCESS_DENIED => return error.AccessDenied, - .OBJECT_PATH_SYNTAX_BAD => |err| return windows.statusBug(err), - else => |rc| return windows.unexpectedStatus(rc), + var it = Dir.path.componentIterator(sub_path); + var status: Dir.CreatePathStatus = .existed; + var component = it.last() orelse return error.BadPathName; + while (true) { + if (dirCreateDir(t, dir, component.path, permissions)) |_| { + status = .created; + } else |err| switch (err) { + error.PathAlreadyExists => { + // It is important to return an error if it's not a directory + // because otherwise a dangling symlink could cause an infinite + // loop. + const kind = try filePathKind(t, dir, component.path); + if (kind != .directory) return error.NotDir; + }, + error.FileNotFound => |e| { + component = it.previous() orelse return e; + continue; + }, + else => |e| return e, + } + component = it.next() orelse return status; } } -const dirCreateFile = switch (native_os) { - .windows => dirCreateFileWindows, - .wasi => dirCreateFileWasi, - else => dirCreateFilePosix, +const dirCreateDirPathOpen = switch (native_os) { + .windows => dirCreateDirPathOpenWindows, + .wasi => dirCreateDirPathOpenWasi, + else => dirCreateDirPathOpenPosix, }; -fn dirCreateFilePosix( +fn dirCreateDirPathOpenPosix( userdata: ?*anyopaque, - dir: Io.Dir, + dir: Dir, sub_path: []const u8, - flags: Io.File.CreateFlags, -) Io.File.OpenError!Io.File { + permissions: Dir.Permissions, + options: Dir.OpenOptions, +) Dir.CreateDirPathOpenError!Dir { const t: *Threaded = @ptrCast(@alignCast(userdata)); - - var path_buffer: [posix.PATH_MAX]u8 = undefined; - const sub_path_posix = try pathToPosix(sub_path, &path_buffer); - - var os_flags: posix.O = .{ - .ACCMODE = if (flags.read) .RDWR else .WRONLY, - .CREAT = true, - .TRUNC = flags.truncate, - .EXCL = flags.exclusive, - }; - if (@hasField(posix.O, "LARGEFILE")) os_flags.LARGEFILE = true; - if (@hasField(posix.O, "CLOEXEC")) os_flags.CLOEXEC = true; - - // Use the O locking flags if the os supports them to acquire the lock - // atomically. Note that the NONBLOCK flag is removed after the openat() - // call is successful. - if (have_flock_open_flags) switch (flags.lock) { - .none => {}, - .shared => { - os_flags.SHLOCK = true; - os_flags.NONBLOCK = flags.lock_nonblocking; - }, - .exclusive => { - os_flags.EXLOCK = true; - os_flags.NONBLOCK = flags.lock_nonblocking; + const t_io = ioBasic(t); + return dirOpenDirPosix(t, dir, sub_path, options) catch |err| switch (err) { + error.FileNotFound => { + _ = try dir.createDirPathStatus(t_io, sub_path, permissions); + return dirOpenDirPosix(t, dir, sub_path, options); }, + else => |e| return e, }; +} - const fd: posix.fd_t = while (true) { - try t.checkCancel(); - const rc = openat_sym(dir.handle, sub_path_posix, os_flags, flags.mode); - switch (posix.errno(rc)) { - .SUCCESS => break @intCast(rc), - .INTR => continue, - .CANCELED => return error.Canceled, - - .FAULT => |err| return errnoBug(err), - .INVAL => return error.BadPathName, - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .ACCES => return error.AccessDenied, - .FBIG => return error.FileTooBig, - .OVERFLOW => return error.FileTooBig, - .ISDIR => return error.IsDir, - .LOOP => return error.SymLinkLoop, - .MFILE => return error.ProcessFdQuotaExceeded, - .NAMETOOLONG => return error.NameTooLong, - .NFILE => return error.SystemFdQuotaExceeded, - .NODEV => return error.NoDevice, - .NOENT => return error.FileNotFound, - .SRCH => return error.ProcessNotFound, - .NOMEM => return error.SystemResources, - .NOSPC => return error.NoSpaceLeft, - .NOTDIR => return error.NotDir, - .PERM => return error.PermissionDenied, - .EXIST => return error.PathAlreadyExists, - .BUSY => return error.DeviceBusy, - .OPNOTSUPP => return error.FileLocksNotSupported, - .AGAIN => return error.WouldBlock, - .TXTBSY => return error.FileBusy, - .NXIO => return error.NoDevice, - .ILSEQ => return error.BadPathName, - else => |err| return posix.unexpectedErrno(err), - } +fn dirCreateDirPathOpenWindows( + userdata: ?*anyopaque, + dir: Dir, + sub_path: []const u8, + permissions: Dir.Permissions, + options: Dir.OpenOptions, +) Dir.CreateDirPathOpenError!Dir { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + const w = windows; + + _ = permissions; // TODO apply these permissions + + var it = Dir.path.componentIterator(sub_path); + // If there are no components in the path, then create a dummy component with the full path. + var component: Dir.path.NativeComponentIterator.Component = it.last() orelse .{ + .name = "", + .path = sub_path, }; - errdefer posix.close(fd); - if (have_flock and !have_flock_open_flags and flags.lock != .none) { - const lock_nonblocking: i32 = if (flags.lock_nonblocking) posix.LOCK.NB else 0; - const lock_flags = switch (flags.lock) { - .none => unreachable, - .shared => posix.LOCK.SH | lock_nonblocking, - .exclusive => posix.LOCK.EX | lock_nonblocking, + components: while (true) { + const sub_path_w_array = try w.sliceToPrefixedFileW(dir.handle, component.path); + const sub_path_w = sub_path_w_array.span(); + const is_last = it.peekNext() == null; + const create_disposition: w.FILE.CREATE_DISPOSITION = if (is_last) .OPEN_IF else .CREATE; + + var result: Dir = .{ .handle = undefined }; + + const path_len_bytes: u16 = @intCast(sub_path_w.len * 2); + var nt_name: w.UNICODE_STRING = .{ + .Length = path_len_bytes, + .MaximumLength = path_len_bytes, + .Buffer = @constCast(sub_path_w.ptr), }; - while (true) { - try t.checkCancel(); - switch (posix.errno(posix.system.flock(fd, lock_flags))) { - .SUCCESS => break, - .INTR => continue, - .CANCELED => return error.Canceled, + var io_status_block: w.IO_STATUS_BLOCK = undefined; - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .INVAL => |err| return errnoBug(err), // invalid parameters - .NOLCK => return error.SystemResources, - .AGAIN => return error.WouldBlock, - .OPNOTSUPP => return error.FileLocksNotSupported, - else => |err| return posix.unexpectedErrno(err), - } - } - } + const syscall: Syscall = try .start(); + while (true) switch (w.ntdll.NtCreateFile( + &result.handle, + .{ + .SPECIFIC = .{ .FILE_DIRECTORY = .{ + .LIST = options.iterate, + .READ_EA = true, + .READ_ATTRIBUTES = true, + .TRAVERSE = true, + } }, + .STANDARD = .{ + .RIGHTS = .READ, + .SYNCHRONIZE = true, + }, + }, + &.{ + .Length = @sizeOf(w.OBJECT_ATTRIBUTES), + .RootDirectory = if (Dir.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir.handle, + .Attributes = .{}, + .ObjectName = &nt_name, + .SecurityDescriptor = null, + .SecurityQualityOfService = null, + }, + &io_status_block, + null, + .{ .NORMAL = true }, + .VALID_FLAGS, + create_disposition, + .{ + .DIRECTORY_FILE = true, + .IO = .SYNCHRONOUS_NONALERT, + .OPEN_FOR_BACKUP_INTENT = true, + .OPEN_REPARSE_POINT = !options.follow_symlinks, + }, + null, + 0, + )) { + .SUCCESS => { + syscall.finish(); + component = it.next() orelse return result; + w.CloseHandle(result.handle); + continue :components; + }, + .CANCELLED => { + try syscall.checkCancel(); + continue; + }, + .OBJECT_NAME_INVALID => return syscall.fail(error.BadPathName), + .OBJECT_NAME_COLLISION => { + syscall.finish(); + assert(!is_last); + // stat the file and return an error if it's not a directory + // this is important because otherwise a dangling symlink + // could cause an infinite loop + const fstat = try dirStatFileWindows(t, dir, component.path, .{ + .follow_symlinks = options.follow_symlinks, + }); + if (fstat.kind != .directory) return error.NotDir; - if (have_flock_open_flags and flags.lock_nonblocking) { - var fl_flags: usize = while (true) { - try t.checkCancel(); - const rc = posix.system.fcntl(fd, posix.F.GETFL, @as(usize, 0)); - switch (posix.errno(rc)) { - .SUCCESS => break @intCast(rc), - .INTR => continue, - .CANCELED => return error.Canceled, - else => |err| return posix.unexpectedErrno(err), - } + component = it.next().?; + continue :components; + }, + + .OBJECT_NAME_NOT_FOUND, + .OBJECT_PATH_NOT_FOUND, + => { + syscall.finish(); + component = it.previous() orelse return error.FileNotFound; + continue :components; + }, + + .NOT_A_DIRECTORY => return syscall.fail(error.NotDir), + // This can happen if the directory has 'List folder contents' permission set to 'Deny' + // and the directory is trying to be opened for iteration. + .ACCESS_DENIED => return syscall.fail(error.AccessDenied), + .INVALID_PARAMETER => |s| return syscall.ntstatusBug(s), + else => |s| return syscall.unexpectedNtstatus(s), }; - fl_flags |= @as(usize, 1 << @bitOffsetOf(posix.O, "NONBLOCK")); - while (true) { - try t.checkCancel(); - switch (posix.errno(posix.system.fcntl(fd, posix.F.SETFL, fl_flags))) { - .SUCCESS => break, - .INTR => continue, - .CANCELED => return error.Canceled, - else => |err| return posix.unexpectedErrno(err), - } - } } - - return .{ .handle = fd }; } -fn dirCreateFileWindows( +fn dirCreateDirPathOpenWasi( userdata: ?*anyopaque, - dir: Io.Dir, + dir: Dir, sub_path: []const u8, - flags: Io.File.CreateFlags, -) Io.File.OpenError!Io.File { - const w = windows; + permissions: Dir.Permissions, + options: Dir.OpenOptions, +) Dir.CreateDirPathOpenError!Dir { const t: *Threaded = @ptrCast(@alignCast(userdata)); - try t.checkCancel(); - - const sub_path_w_array = try w.sliceToPrefixedFileW(dir.handle, sub_path); - const sub_path_w = sub_path_w_array.span(); - - const read_flag = if (flags.read) @as(u32, w.GENERIC_READ) else 0; - const handle = try w.OpenFile(sub_path_w, .{ - .dir = dir.handle, - .access_mask = w.SYNCHRONIZE | w.GENERIC_WRITE | read_flag, - .creation = if (flags.exclusive) - @as(u32, w.FILE_CREATE) - else if (flags.truncate) - @as(u32, w.FILE_OVERWRITE_IF) - else - @as(u32, w.FILE_OPEN_IF), - }); - errdefer w.CloseHandle(handle); - var io_status_block: w.IO_STATUS_BLOCK = undefined; - const range_off: w.LARGE_INTEGER = 0; - const range_len: w.LARGE_INTEGER = 1; - const exclusive = switch (flags.lock) { - .none => return .{ .handle = handle }, - .shared => false, - .exclusive => true, + const t_io = ioBasic(t); + return dirOpenDirWasi(t, dir, sub_path, options) catch |err| switch (err) { + error.FileNotFound => { + _ = try dir.createDirPathStatus(t_io, sub_path, permissions); + return dirOpenDirWasi(t, dir, sub_path, options); + }, + else => |e| return e, }; - try w.LockFile( - handle, - null, - null, - null, - &io_status_block, - &range_off, - &range_len, - null, - @intFromBool(flags.lock_nonblocking), - @intFromBool(exclusive), - ); - return .{ .handle = handle }; } -fn dirCreateFileWasi( - userdata: ?*anyopaque, - dir: Io.Dir, - sub_path: []const u8, - flags: Io.File.CreateFlags, -) Io.File.OpenError!Io.File { +fn dirStat(userdata: ?*anyopaque, dir: Dir) Dir.StatError!Dir.Stat { const t: *Threaded = @ptrCast(@alignCast(userdata)); - const wasi = std.os.wasi; - const lookup_flags: wasi.lookupflags_t = .{}; - const oflags: wasi.oflags_t = .{ - .CREAT = true, - .TRUNC = flags.truncate, - .EXCL = flags.exclusive, - }; - const fdflags: wasi.fdflags_t = .{}; - const base: wasi.rights_t = .{ - .FD_READ = flags.read, - .FD_WRITE = true, - .FD_DATASYNC = true, - .FD_SEEK = true, - .FD_TELL = true, - .FD_FDSTAT_SET_FLAGS = true, - .FD_SYNC = true, - .FD_ALLOCATE = true, - .FD_ADVISE = true, - .FD_FILESTAT_SET_TIMES = true, - .FD_FILESTAT_SET_SIZE = true, - .FD_FILESTAT_GET = true, - // POLL_FD_READWRITE only grants extra rights if the corresponding FD_READ and/or - // FD_WRITE is also set. - .POLL_FD_READWRITE = true, - }; - const inheriting: wasi.rights_t = .{}; - var fd: posix.fd_t = undefined; - while (true) { - try t.checkCancel(); - switch (wasi.path_open(dir.handle, lookup_flags, sub_path.ptr, sub_path.len, oflags, base, inheriting, fdflags, &fd)) { - .SUCCESS => return .{ .handle = fd }, - .INTR => continue, - .CANCELED => return error.Canceled, - - .FAULT => |err| return errnoBug(err), - .INVAL => return error.BadPathName, - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .ACCES => return error.AccessDenied, - .FBIG => return error.FileTooBig, - .OVERFLOW => return error.FileTooBig, - .ISDIR => return error.IsDir, - .LOOP => return error.SymLinkLoop, - .MFILE => return error.ProcessFdQuotaExceeded, - .NAMETOOLONG => return error.NameTooLong, - .NFILE => return error.SystemFdQuotaExceeded, - .NODEV => return error.NoDevice, - .NOENT => return error.FileNotFound, - .NOMEM => return error.SystemResources, - .NOSPC => return error.NoSpaceLeft, - .NOTDIR => return error.NotDir, - .PERM => return error.PermissionDenied, - .EXIST => return error.PathAlreadyExists, - .BUSY => return error.DeviceBusy, - .NOTCAPABLE => return error.AccessDenied, - .ILSEQ => return error.BadPathName, - else => |err| return posix.unexpectedErrno(err), - } - } + const file: File = .{ .handle = dir.handle }; + return fileStat(t, file); } -const dirOpenFile = switch (native_os) { - .windows => dirOpenFileWindows, - .wasi => dirOpenFileWasi, - else => dirOpenFilePosix, +const dirStatFile = switch (native_os) { + .linux => dirStatFileLinux, + .windows => dirStatFileWindows, + .wasi => dirStatFileWasi, + else => dirStatFilePosix, }; -fn dirOpenFilePosix( +fn dirStatFileLinux( userdata: ?*anyopaque, - dir: Io.Dir, + dir: Dir, sub_path: []const u8, - flags: Io.File.OpenFlags, -) Io.File.OpenError!Io.File { + options: Dir.StatFileOptions, +) Dir.StatFileError!File.Stat { const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + const linux = std.os.linux; + const sys = if (statx_use_c) std.c else std.os.linux; var path_buffer: [posix.PATH_MAX]u8 = undefined; const sub_path_posix = try pathToPosix(sub_path, &path_buffer); - var os_flags: posix.O = switch (native_os) { - .wasi => .{ - .read = flags.mode != .write_only, - .write = flags.mode != .read_only, - }, - else => .{ - .ACCMODE = switch (flags.mode) { - .read_only => .RDONLY, - .write_only => .WRONLY, - .read_write => .RDWR, + const flags: u32 = linux.AT.NO_AUTOMOUNT | + @as(u32, if (!options.follow_symlinks) linux.AT.SYMLINK_NOFOLLOW else 0); + + const syscall: Syscall = try .start(); + while (true) { + var statx = std.mem.zeroes(linux.Statx); + switch (sys.errno(sys.statx(dir.handle, sub_path_posix, flags, linux_statx_request, &statx))) { + .SUCCESS => { + syscall.finish(); + return statFromLinux(&statx); }, - }, - }; - if (@hasField(posix.O, "CLOEXEC")) os_flags.CLOEXEC = true; - if (@hasField(posix.O, "LARGEFILE")) os_flags.LARGEFILE = true; - if (@hasField(posix.O, "NOCTTY")) os_flags.NOCTTY = !flags.allow_ctty; + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ACCES => return error.AccessDenied, + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .FAULT => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), + .LOOP => return error.SymLinkLoop, + .NAMETOOLONG => |err| return errnoBug(err), // Handled by pathToPosix() above. + .NOENT => return error.FileNotFound, + .NOTDIR => return error.NotDir, + .NOMEM => return error.SystemResources, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} - // Use the O locking flags if the os supports them to acquire the lock - // atomically. Note that the NONBLOCK flag is removed after the openat() - // call is successful. - if (have_flock_open_flags) switch (flags.lock) { - .none => {}, - .shared => { - os_flags.SHLOCK = true; - os_flags.NONBLOCK = flags.lock_nonblocking; - }, - .exclusive => { - os_flags.EXLOCK = true; - os_flags.NONBLOCK = flags.lock_nonblocking; - }, - }; +fn dirStatFilePosix( + userdata: ?*anyopaque, + dir: Dir, + sub_path: []const u8, + options: Dir.StatFileOptions, +) Dir.StatFileError!File.Stat { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; - const fd: posix.fd_t = while (true) { - try t.checkCancel(); - const rc = openat_sym(dir.handle, sub_path_posix, os_flags, @as(posix.mode_t, 0)); - switch (posix.errno(rc)) { - .SUCCESS => break @intCast(rc), - .INTR => continue, - .CANCELED => return error.Canceled, - - .FAULT => |err| return errnoBug(err), - .INVAL => return error.BadPathName, - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .ACCES => return error.AccessDenied, - .FBIG => return error.FileTooBig, - .OVERFLOW => return error.FileTooBig, - .ISDIR => return error.IsDir, - .LOOP => return error.SymLinkLoop, - .MFILE => return error.ProcessFdQuotaExceeded, - .NAMETOOLONG => return error.NameTooLong, - .NFILE => return error.SystemFdQuotaExceeded, - .NODEV => return error.NoDevice, - .NOENT => return error.FileNotFound, - .SRCH => return error.ProcessNotFound, - .NOMEM => return error.SystemResources, - .NOSPC => return error.NoSpaceLeft, - .NOTDIR => return error.NotDir, - .PERM => return error.PermissionDenied, - .EXIST => return error.PathAlreadyExists, - .BUSY => return error.DeviceBusy, - .OPNOTSUPP => return error.FileLocksNotSupported, - .AGAIN => return error.WouldBlock, - .TXTBSY => return error.FileBusy, - .NXIO => return error.NoDevice, - .ILSEQ => return error.BadPathName, - else => |err| return posix.unexpectedErrno(err), - } - }; - errdefer posix.close(fd); + var path_buffer: [posix.PATH_MAX]u8 = undefined; + const sub_path_posix = try pathToPosix(sub_path, &path_buffer); - if (have_flock and !have_flock_open_flags and flags.lock != .none) { - const lock_nonblocking: i32 = if (flags.lock_nonblocking) posix.LOCK.NB else 0; - const lock_flags = switch (flags.lock) { - .none => unreachable, - .shared => posix.LOCK.SH | lock_nonblocking, - .exclusive => posix.LOCK.EX | lock_nonblocking, - }; - while (true) { - try t.checkCancel(); - switch (posix.errno(posix.system.flock(fd, lock_flags))) { - .SUCCESS => break, - .INTR => continue, - .CANCELED => return error.Canceled, + const flags: u32 = if (!options.follow_symlinks) posix.AT.SYMLINK_NOFOLLOW else 0; - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .INVAL => |err| return errnoBug(err), // invalid parameters - .NOLCK => return error.SystemResources, - .AGAIN => return error.WouldBlock, - .OPNOTSUPP => return error.FileLocksNotSupported, - else => |err| return posix.unexpectedErrno(err), - } - } - } + return posixStatFile(dir.handle, sub_path_posix, flags); +} - if (have_flock_open_flags and flags.lock_nonblocking) { - var fl_flags: usize = while (true) { - try t.checkCancel(); - const rc = posix.system.fcntl(fd, posix.F.GETFL, @as(usize, 0)); - switch (posix.errno(rc)) { - .SUCCESS => break @intCast(rc), - .INTR => continue, - .CANCELED => return error.Canceled, - else => |err| return posix.unexpectedErrno(err), - } - }; - fl_flags |= @as(usize, 1 << @bitOffsetOf(posix.O, "NONBLOCK")); - while (true) { - try t.checkCancel(); - switch (posix.errno(posix.system.fcntl(fd, posix.F.SETFL, fl_flags))) { - .SUCCESS => break, - .INTR => continue, - .CANCELED => return error.Canceled, - else => |err| return posix.unexpectedErrno(err), - } +fn posixStatFile(dir_fd: posix.fd_t, sub_path: [:0]const u8, flags: u32) Dir.StatFileError!File.Stat { + const syscall: Syscall = try .start(); + while (true) { + var stat = std.mem.zeroes(posix.Stat); + switch (posix.errno(fstatat_sym(dir_fd, sub_path, &stat, flags))) { + .SUCCESS => { + syscall.finish(); + return statFromPosix(&stat); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .INVAL => |err| return errnoBug(err), + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .NOMEM => return error.SystemResources, + .ACCES => return error.AccessDenied, + .PERM => return error.PermissionDenied, + .FAULT => |err| return errnoBug(err), + .NAMETOOLONG => return error.NameTooLong, + .LOOP => return error.SymLinkLoop, + .NOENT => return error.FileNotFound, + .NOTDIR => return error.FileNotFound, + .ILSEQ => return error.BadPathName, + else => |err| return posix.unexpectedErrno(err), + } + }, } } - - return .{ .handle = fd }; } -fn dirOpenFileWindows( +fn dirStatFileWindows( userdata: ?*anyopaque, - dir: Io.Dir, + dir: Dir, sub_path: []const u8, - flags: Io.File.OpenFlags, -) Io.File.OpenError!Io.File { + options: Dir.StatFileOptions, +) Dir.StatFileError!File.Stat { const t: *Threaded = @ptrCast(@alignCast(userdata)); - const sub_path_w_array = try windows.sliceToPrefixedFileW(dir.handle, sub_path); - const sub_path_w = sub_path_w_array.span(); - const dir_handle = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir.handle; - return dirOpenFileWtf16(t, dir_handle, sub_path_w, flags); + const file = try dirOpenFileWindows(t, dir, sub_path, .{ + .follow_symlinks = options.follow_symlinks, + }); + defer windows.CloseHandle(file.handle); + return fileStatWindows(t, file); } -pub fn dirOpenFileWtf16( - t: *Threaded, - dir_handle: ?windows.HANDLE, - sub_path_w: [:0]const u16, - flags: Io.File.OpenFlags, -) Io.File.OpenError!Io.File { - if (std.mem.eql(u16, sub_path_w, &.{'.'})) return error.IsDir; - if (std.mem.eql(u16, sub_path_w, &.{ '.', '.' })) return error.IsDir; - const path_len_bytes = std.math.cast(u16, sub_path_w.len * 2) orelse return error.NameTooLong; - - const w = windows; - - var nt_name: w.UNICODE_STRING = .{ - .Length = path_len_bytes, - .MaximumLength = path_len_bytes, - .Buffer = @constCast(sub_path_w.ptr), - }; - var attr: w.OBJECT_ATTRIBUTES = .{ - .Length = @sizeOf(w.OBJECT_ATTRIBUTES), - .RootDirectory = dir_handle, - .Attributes = 0, - .ObjectName = &nt_name, - .SecurityDescriptor = null, - .SecurityQualityOfService = null, +fn dirStatFileWasi( + userdata: ?*anyopaque, + dir: Dir, + sub_path: []const u8, + options: Dir.StatFileOptions, +) Dir.StatFileError!File.Stat { + if (builtin.link_libc) return dirStatFilePosix(userdata, dir, sub_path, options); + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + const wasi = std.os.wasi; + const flags: wasi.lookupflags_t = .{ + .SYMLINK_FOLLOW = options.follow_symlinks, }; - var io_status_block: w.IO_STATUS_BLOCK = undefined; - const blocking_flag: w.ULONG = w.FILE_SYNCHRONOUS_IO_NONALERT; - const file_or_dir_flag: w.ULONG = w.FILE_NON_DIRECTORY_FILE; - // If we're not following symlinks, we need to ensure we don't pass in any - // synchronization flags such as FILE_SYNCHRONOUS_IO_NONALERT. - const create_file_flags: w.ULONG = file_or_dir_flag | - if (flags.follow_symlinks) blocking_flag else w.FILE_OPEN_REPARSE_POINT; - - // There are multiple kernel bugs being worked around with retries. - const max_attempts = 13; - var attempt: u5 = 0; - - const handle = while (true) { - try t.checkCancel(); - - var result: w.HANDLE = undefined; - const rc = w.ntdll.NtCreateFile( - &result, - w.SYNCHRONIZE | - (if (flags.isRead()) @as(u32, w.GENERIC_READ) else 0) | - (if (flags.isWrite()) @as(u32, w.GENERIC_WRITE) else 0), - &attr, - &io_status_block, - null, - w.FILE_ATTRIBUTE_NORMAL, - w.FILE_SHARE_WRITE | w.FILE_SHARE_READ | w.FILE_SHARE_DELETE, - w.FILE_OPEN, - create_file_flags, - null, - 0, - ); - switch (rc) { - .SUCCESS => break result, - .OBJECT_NAME_INVALID => return error.BadPathName, - .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, - .OBJECT_PATH_NOT_FOUND => return error.FileNotFound, - .BAD_NETWORK_PATH => return error.NetworkNotFound, // \\server was not found - .BAD_NETWORK_NAME => return error.NetworkNotFound, // \\server was found but \\server\share wasn't - .NO_MEDIA_IN_DEVICE => return error.NoDevice, - .INVALID_PARAMETER => |err| return w.statusBug(err), - .SHARING_VIOLATION => { - // This occurs if the file attempting to be opened is a running - // executable. However, there's a kernel bug: the error may be - // incorrectly returned for an indeterminate amount of time - // after an executable file is closed. Here we work around the - // kernel bug with retry attempts. - if (max_attempts - attempt == 0) return error.SharingViolation; - _ = w.kernel32.SleepEx((@as(u32, 1) << attempt) >> 1, w.TRUE); - attempt += 1; - continue; + var stat: wasi.filestat_t = undefined; + const syscall: Syscall = try .start(); + while (true) { + switch (wasi.path_filestat_get(dir.handle, flags, sub_path.ptr, sub_path.len, &stat)) { + .SUCCESS => { + syscall.finish(); + return statFromWasi(&stat); }, - .ACCESS_DENIED => return error.AccessDenied, - .PIPE_BUSY => return error.PipeBusy, - .PIPE_NOT_AVAILABLE => return error.NoDevice, - .OBJECT_PATH_SYNTAX_BAD => |err| return w.statusBug(err), - .OBJECT_NAME_COLLISION => return error.PathAlreadyExists, - .FILE_IS_A_DIRECTORY => return error.IsDir, - .NOT_A_DIRECTORY => return error.NotDir, - .USER_MAPPED_FILE => return error.AccessDenied, - .INVALID_HANDLE => |err| return w.statusBug(err), - .DELETE_PENDING => { - // This error means that there *was* a file in this location on - // the file system, but it was deleted. However, the OS is not - // finished with the deletion operation, and so this CreateFile - // call has failed. Here, we simulate the kernel bug being - // fixed by sleeping and retrying until the error goes away. - if (max_attempts - attempt == 0) return error.SharingViolation; - _ = w.kernel32.SleepEx((@as(u32, 1) << attempt) >> 1, w.TRUE); - attempt += 1; + .INTR => { + try syscall.checkCancel(); continue; }, - .VIRUS_INFECTED, .VIRUS_DELETED => return error.AntivirusInterference, - else => return w.unexpectedStatus(rc), + else => |e| { + syscall.finish(); + switch (e) { + .INVAL => |err| return errnoBug(err), + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .NOMEM => return error.SystemResources, + .ACCES => return error.AccessDenied, + .FAULT => |err| return errnoBug(err), + .NAMETOOLONG => return error.NameTooLong, + .NOENT => return error.FileNotFound, + .NOTDIR => return error.FileNotFound, + .NOTCAPABLE => return error.AccessDenied, + .ILSEQ => return error.BadPathName, + else => |err| return posix.unexpectedErrno(err), + } + }, } - }; - errdefer w.CloseHandle(handle); + } +} - const range_off: w.LARGE_INTEGER = 0; - const range_len: w.LARGE_INTEGER = 1; - const exclusive = switch (flags.lock) { - .none => return .{ .handle = handle }, - .shared => false, - .exclusive => true, - }; - try w.LockFile( - handle, - null, - null, - null, - &io_status_block, - &range_off, - &range_len, - null, - @intFromBool(flags.lock_nonblocking), - @intFromBool(exclusive), - ); - return .{ .handle = handle }; +fn filePathKind(t: *Threaded, dir: Dir, sub_path: []const u8) !File.Kind { + if (native_os == .linux) { + var path_buffer: [posix.PATH_MAX]u8 = undefined; + const sub_path_posix = try pathToPosix(sub_path, &path_buffer); + + const linux = std.os.linux; + const syscall: Syscall = try .start(); + while (true) { + var statx = std.mem.zeroes(linux.Statx); + switch (linux.errno(linux.statx(dir.handle, sub_path_posix, 0, .{ .TYPE = true }, &statx))) { + .SUCCESS => { + syscall.finish(); + if (!statx.mask.TYPE) return error.Unexpected; + return statxKind(statx.mode); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + .NOMEM => return syscall.fail(error.SystemResources), + else => |err| return syscall.unexpectedErrno(err), + } + } + } + + const stat = try dirStatFile(t, dir, sub_path, .{}); + return stat.kind; } -fn dirOpenFileWasi( - userdata: ?*anyopaque, - dir: Io.Dir, - sub_path: []const u8, - flags: Io.File.OpenFlags, -) Io.File.OpenError!Io.File { - if (builtin.link_libc) return dirOpenFilePosix(userdata, dir, sub_path, flags); +fn fileLength(userdata: ?*anyopaque, file: File) File.LengthError!u64 { const t: *Threaded = @ptrCast(@alignCast(userdata)); - const wasi = std.os.wasi; - var base: std.os.wasi.rights_t = .{}; - // POLL_FD_READWRITE only grants extra rights if the corresponding FD_READ and/or FD_WRITE - // is also set. - if (flags.isRead()) { - base.FD_READ = true; - base.FD_TELL = true; - base.FD_SEEK = true; - base.FD_FILESTAT_GET = true; - base.POLL_FD_READWRITE = true; - } - if (flags.isWrite()) { - base.FD_WRITE = true; - base.FD_TELL = true; - base.FD_SEEK = true; - base.FD_DATASYNC = true; - base.FD_FDSTAT_SET_FLAGS = true; - base.FD_SYNC = true; - base.FD_ALLOCATE = true; - base.FD_ADVISE = true; - base.FD_FILESTAT_SET_TIMES = true; - base.FD_FILESTAT_SET_SIZE = true; - base.POLL_FD_READWRITE = true; - } - const lookup_flags: wasi.lookupflags_t = .{}; - const oflags: wasi.oflags_t = .{}; - const inheriting: wasi.rights_t = .{}; - const fdflags: wasi.fdflags_t = .{}; - var fd: posix.fd_t = undefined; - while (true) { - try t.checkCancel(); - switch (wasi.path_open(dir.handle, lookup_flags, sub_path.ptr, sub_path.len, oflags, base, inheriting, fdflags, &fd)) { - .SUCCESS => return .{ .handle = fd }, - .INTR => continue, - .CANCELED => return error.Canceled, - - .FAULT => |err| return errnoBug(err), - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .ACCES => return error.AccessDenied, - .FBIG => return error.FileTooBig, - .OVERFLOW => return error.FileTooBig, - .ISDIR => return error.IsDir, - .LOOP => return error.SymLinkLoop, - .MFILE => return error.ProcessFdQuotaExceeded, - .NFILE => return error.SystemFdQuotaExceeded, - .NODEV => return error.NoDevice, - .NOENT => return error.FileNotFound, - .NOMEM => return error.SystemResources, - .NOTDIR => return error.NotDir, - .PERM => return error.PermissionDenied, - .BUSY => return error.DeviceBusy, - .NOTCAPABLE => return error.AccessDenied, - .NAMETOOLONG => return error.NameTooLong, - .INVAL => return error.BadPathName, - .ILSEQ => return error.BadPathName, - else => |err| return posix.unexpectedErrno(err), + + if (native_os == .linux) { + const linux = std.os.linux; + + const syscall: Syscall = try .start(); + while (true) { + var statx = std.mem.zeroes(linux.Statx); + switch (linux.errno(linux.statx(file.handle, "", linux.AT.EMPTY_PATH, .{ .SIZE = true }, &statx))) { + .SUCCESS => { + syscall.finish(); + if (!statx.mask.SIZE) return error.Unexpected; + return statx.size; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ACCES => |err| return errnoBug(err), + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .FAULT => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), + .LOOP => |err| return errnoBug(err), + .NAMETOOLONG => |err| return errnoBug(err), + .NOENT => |err| return errnoBug(err), + .NOMEM => return error.SystemResources, + .NOTDIR => |err| return errnoBug(err), + else => |err| return posix.unexpectedErrno(err), + } + }, + } } + } else if (is_windows) { + // TODO call NtQueryInformationFile and ask for only the size instead of "all" } + + const stat = try fileStat(t, file); + return stat.size; } -const dirOpenDir = switch (native_os) { - .wasi => dirOpenDirWasi, - .haiku => dirOpenDirHaiku, - else => dirOpenDirPosix, +const fileStat = switch (native_os) { + .linux => fileStatLinux, + .windows => fileStatWindows, + .wasi => fileStatWasi, + else => fileStatPosix, }; -/// This function is also used for WASI when libc is linked. -fn dirOpenDirPosix( - userdata: ?*anyopaque, - dir: Io.Dir, - sub_path: []const u8, - options: Io.Dir.OpenOptions, -) Io.Dir.OpenError!Io.Dir { +fn fileStatPosix(userdata: ?*anyopaque, file: File) File.StatError!File.Stat { const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; - if (is_windows) { - const sub_path_w = try windows.sliceToPrefixedFileW(dir.handle, sub_path); - return dirOpenDirWindows(t, dir, sub_path_w.span(), options); + if (posix.Stat == void) return error.Streaming; + + const syscall: Syscall = try .start(); + while (true) { + var stat = std.mem.zeroes(posix.Stat); + switch (posix.errno(fstat_sym(file.handle, &stat))) { + .SUCCESS => { + syscall.finish(); + return statFromPosix(&stat); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .INVAL => |err| return errnoBug(err), + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .NOMEM => return error.SystemResources, + .ACCES => return error.AccessDenied, + else => |err| return posix.unexpectedErrno(err), + } + }, + } } +} - var path_buffer: [posix.PATH_MAX]u8 = undefined; - const sub_path_posix = try pathToPosix(sub_path, &path_buffer); +fn fileStatLinux(userdata: ?*anyopaque, file: File) File.StatError!File.Stat { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + const linux = std.os.linux; + const sys = if (statx_use_c) std.c else std.os.linux; - var flags: posix.O = switch (native_os) { - .wasi => .{ - .read = true, - .NOFOLLOW = !options.follow_symlinks, - .DIRECTORY = true, - }, - else => .{ - .ACCMODE = .RDONLY, - .NOFOLLOW = !options.follow_symlinks, - .DIRECTORY = true, - .CLOEXEC = true, - }, + const syscall: Syscall = try .start(); + while (true) { + var statx = std.mem.zeroes(linux.Statx); + switch (sys.errno(sys.statx(file.handle, "", linux.AT.EMPTY_PATH, linux_statx_request, &statx))) { + .SUCCESS => { + syscall.finish(); + return statFromLinux(&statx); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ACCES => |err| return errnoBug(err), + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .FAULT => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), + .LOOP => |err| return errnoBug(err), + .NAMETOOLONG => |err| return errnoBug(err), + .NOENT => |err| return errnoBug(err), + .NOMEM => return error.SystemResources, + .NOTDIR => |err| return errnoBug(err), + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn fileStatWindows(userdata: ?*anyopaque, file: File) File.StatError!File.Stat { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + var io_status_block: windows.IO_STATUS_BLOCK = undefined; + var info: windows.FILE.ALL_INFORMATION = undefined; + { + const syscall: Syscall = try .start(); + while (true) switch (windows.ntdll.NtQueryInformationFile( + file.handle, + &io_status_block, + &info, + @sizeOf(windows.FILE.ALL_INFORMATION), + .All, + )) { + .SUCCESS => break syscall.finish(), + // Buffer overflow here indicates that there is more information available than was able to be stored in the buffer + // size provided. This is treated as success because the type of variable-length information that this would be relevant for + // (name, volume name, etc) we don't care about. + .BUFFER_OVERFLOW => break syscall.finish(), + .INVALID_PARAMETER => |err| return syscall.ntstatusBug(err), + .ACCESS_DENIED => return syscall.fail(error.AccessDenied), + .CANCELLED => { + try syscall.checkCancel(); + continue; + }, + else => |s| return syscall.unexpectedNtstatus(s), + }; + } + return .{ + .inode = info.InternalInformation.IndexNumber, + .size = @as(u64, @bitCast(info.StandardInformation.EndOfFile)), + .permissions = .default_file, + .kind = if (info.BasicInformation.FileAttributes.REPARSE_POINT) reparse_point: { + var tag_info: windows.FILE.ATTRIBUTE_TAG_INFO = undefined; + const syscall: Syscall = try .start(); + while (true) switch (windows.ntdll.NtQueryInformationFile( + file.handle, + &io_status_block, + &tag_info, + @sizeOf(windows.FILE.ATTRIBUTE_TAG_INFO), + .AttributeTag, + )) { + .SUCCESS => break syscall.finish(), + // INFO_LENGTH_MISMATCH and ACCESS_DENIED are the only documented possible errors + // https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/d295752f-ce89-4b98-8553-266d37c84f0e + .INFO_LENGTH_MISMATCH => |err| return syscall.ntstatusBug(err), + .ACCESS_DENIED => return syscall.fail(error.AccessDenied), + .CANCELLED => { + try syscall.checkCancel(); + continue; + }, + else => |s| return syscall.unexpectedNtstatus(s), + }; + if (tag_info.ReparseTag.IsSurrogate) break :reparse_point .sym_link; + // Unknown reparse point + break :reparse_point .unknown; + } else if (info.BasicInformation.FileAttributes.DIRECTORY) + .directory + else + .file, + .atime = windows.fromSysTime(info.BasicInformation.LastAccessTime), + .mtime = windows.fromSysTime(info.BasicInformation.LastWriteTime), + .ctime = windows.fromSysTime(info.BasicInformation.ChangeTime), + .nlink = 0, }; +} - if (@hasField(posix.O, "PATH") and !options.iterate) - flags.PATH = true; +fn fileStatWasi(userdata: ?*anyopaque, file: File) File.StatError!File.Stat { + if (builtin.link_libc) return fileStatPosix(userdata, file); - while (true) { - try t.checkCancel(); - const rc = openat_sym(dir.handle, sub_path_posix, flags, @as(usize, 0)); - switch (posix.errno(rc)) { - .SUCCESS => return .{ .handle = @intCast(rc) }, - .INTR => continue, - .CANCELED => return error.Canceled, + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; - .FAULT => |err| return errnoBug(err), - .INVAL => return error.BadPathName, - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .ACCES => return error.AccessDenied, - .LOOP => return error.SymLinkLoop, - .MFILE => return error.ProcessFdQuotaExceeded, - .NAMETOOLONG => return error.NameTooLong, - .NFILE => return error.SystemFdQuotaExceeded, - .NODEV => return error.NoDevice, - .NOENT => return error.FileNotFound, - .NOMEM => return error.SystemResources, - .NOTDIR => return error.NotDir, - .PERM => return error.PermissionDenied, - .BUSY => return error.DeviceBusy, - .NXIO => return error.NoDevice, - .ILSEQ => return error.BadPathName, - else => |err| return posix.unexpectedErrno(err), + const syscall: Syscall = try .start(); + while (true) { + var stat: std.os.wasi.filestat_t = undefined; + switch (std.os.wasi.fd_filestat_get(file.handle, &stat)) { + .SUCCESS => { + syscall.finish(); + return statFromWasi(&stat); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .INVAL => |err| return errnoBug(err), + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .NOMEM => return error.SystemResources, + .ACCES => return error.AccessDenied, + .NOTCAPABLE => return error.AccessDenied, + else => |err| return posix.unexpectedErrno(err), + } + }, } } } -fn dirOpenDirHaiku( +const dirAccess = switch (native_os) { + .windows => dirAccessWindows, + .wasi => dirAccessWasi, + else => dirAccessPosix, +}; + +fn dirAccessPosix( userdata: ?*anyopaque, - dir: Io.Dir, + dir: Dir, sub_path: []const u8, - options: Io.Dir.OpenOptions, -) Io.Dir.OpenError!Io.Dir { + options: Dir.AccessOptions, +) Dir.AccessError!void { const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; var path_buffer: [posix.PATH_MAX]u8 = undefined; const sub_path_posix = try pathToPosix(sub_path, &path_buffer); - _ = options; + const flags: u32 = @as(u32, if (!options.follow_symlinks) posix.AT.SYMLINK_NOFOLLOW else 0); + + const mode: u32 = + @as(u32, if (options.read) posix.R_OK else 0) | + @as(u32, if (options.write) posix.W_OK else 0) | + @as(u32, if (options.execute) posix.X_OK else 0); + const syscall: Syscall = try .start(); while (true) { - try t.checkCancel(); - const rc = posix.system._kern_open_dir(dir.handle, sub_path_posix); - if (rc >= 0) return .{ .handle = rc }; - switch (@as(posix.E, @enumFromInt(rc))) { - .INTR => continue, - .CANCELED => return error.Canceled, - .FAULT => |err| return errnoBug(err), - .INVAL => |err| return errnoBug(err), - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .ACCES => return error.AccessDenied, - .LOOP => return error.SymLinkLoop, - .MFILE => return error.ProcessFdQuotaExceeded, - .NAMETOOLONG => return error.NameTooLong, - .NFILE => return error.SystemFdQuotaExceeded, - .NODEV => return error.NoDevice, - .NOENT => return error.FileNotFound, - .NOMEM => return error.SystemResources, - .NOTDIR => return error.NotDir, - .PERM => return error.PermissionDenied, - .BUSY => return error.DeviceBusy, - else => |err| return posix.unexpectedErrno(err), + switch (posix.errno(posix.system.faccessat(dir.handle, sub_path_posix, mode, flags))) { + .SUCCESS => { + syscall.finish(); + return; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ACCES => return error.AccessDenied, + .PERM => return error.PermissionDenied, + .ROFS => return error.ReadOnlyFileSystem, + .LOOP => return error.SymLinkLoop, + .TXTBSY => return error.FileBusy, + .NOTDIR => return error.FileNotFound, + .NOENT => return error.FileNotFound, + .NAMETOOLONG => return error.NameTooLong, + .INVAL => |err| return errnoBug(err), + .FAULT => |err| return errnoBug(err), + .IO => return error.InputOutput, + .NOMEM => return error.SystemResources, + .ILSEQ => return error.BadPathName, + else => |err| return posix.unexpectedErrno(err), + } + }, } } } -pub fn dirOpenDirWindows( - t: *Io.Threaded, - dir: Io.Dir, - sub_path_w: [:0]const u16, - options: Io.Dir.OpenOptions, -) Io.Dir.OpenError!Io.Dir { - const w = windows; - // TODO remove some of these flags if options.access_sub_paths is false - const base_flags = w.STANDARD_RIGHTS_READ | w.FILE_READ_ATTRIBUTES | w.FILE_READ_EA | - w.SYNCHRONIZE | w.FILE_TRAVERSE; - const access_mask: u32 = if (options.iterate) base_flags | w.FILE_LIST_DIRECTORY else base_flags; - - const path_len_bytes: u16 = @intCast(sub_path_w.len * 2); - var nt_name: w.UNICODE_STRING = .{ - .Length = path_len_bytes, - .MaximumLength = path_len_bytes, - .Buffer = @constCast(sub_path_w.ptr), - }; - var attr: w.OBJECT_ATTRIBUTES = .{ - .Length = @sizeOf(w.OBJECT_ATTRIBUTES), - .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir.handle, - .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. - .ObjectName = &nt_name, - .SecurityDescriptor = null, - .SecurityQualityOfService = null, - }; - const open_reparse_point: w.DWORD = if (!options.follow_symlinks) w.FILE_OPEN_REPARSE_POINT else 0x0; - var io_status_block: w.IO_STATUS_BLOCK = undefined; - var result: Io.Dir = .{ .handle = undefined }; - try t.checkCancel(); - const rc = w.ntdll.NtCreateFile( - &result.handle, - access_mask, - &attr, - &io_status_block, - null, - w.FILE_ATTRIBUTE_NORMAL, - w.FILE_SHARE_READ | w.FILE_SHARE_WRITE | w.FILE_SHARE_DELETE, - w.FILE_OPEN, - w.FILE_DIRECTORY_FILE | w.FILE_SYNCHRONOUS_IO_NONALERT | w.FILE_OPEN_FOR_BACKUP_INTENT | open_reparse_point, - null, - 0, - ); - - switch (rc) { - .SUCCESS => return result, - .OBJECT_NAME_INVALID => return error.BadPathName, - .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, - .OBJECT_NAME_COLLISION => |err| return w.statusBug(err), - .OBJECT_PATH_NOT_FOUND => return error.FileNotFound, - .NOT_A_DIRECTORY => return error.NotDir, - // This can happen if the directory has 'List folder contents' permission set to 'Deny' - // and the directory is trying to be opened for iteration. - .ACCESS_DENIED => return error.AccessDenied, - .INVALID_PARAMETER => |err| return w.statusBug(err), - else => return w.unexpectedStatus(rc), - } -} - -const MakeOpenDirAccessMaskWOptions = struct { - no_follow: bool, - create_disposition: u32, -}; - -fn dirClose(userdata: ?*anyopaque, dir: Io.Dir) void { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - _ = t; - posix.close(dir.handle); -} - -fn dirOpenDirWasi( +fn dirAccessWasi( userdata: ?*anyopaque, - dir: Io.Dir, + dir: Dir, sub_path: []const u8, - options: Io.Dir.OpenOptions, -) Io.Dir.OpenError!Io.Dir { - if (builtin.link_libc) return dirOpenDirPosix(userdata, dir, sub_path, options); + options: Dir.AccessOptions, +) Dir.AccessError!void { + if (builtin.link_libc) return dirAccessPosix(userdata, dir, sub_path, options); const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; const wasi = std.os.wasi; - - var base: std.os.wasi.rights_t = .{ - .FD_FILESTAT_GET = true, - .FD_FDSTAT_SET_FLAGS = true, - .FD_FILESTAT_SET_TIMES = true, + const flags: wasi.lookupflags_t = .{ + .SYMLINK_FOLLOW = options.follow_symlinks, }; - if (options.access_sub_paths) { - base.FD_READDIR = true; - base.PATH_CREATE_DIRECTORY = true; - base.PATH_CREATE_FILE = true; - base.PATH_LINK_SOURCE = true; - base.PATH_LINK_TARGET = true; - base.PATH_OPEN = true; - base.PATH_READLINK = true; - base.PATH_RENAME_SOURCE = true; - base.PATH_RENAME_TARGET = true; - base.PATH_FILESTAT_GET = true; - base.PATH_FILESTAT_SET_SIZE = true; - base.PATH_FILESTAT_SET_TIMES = true; - base.PATH_SYMLINK = true; - base.PATH_REMOVE_DIRECTORY = true; - base.PATH_UNLINK_FILE = true; - } - - const lookup_flags: wasi.lookupflags_t = .{ .SYMLINK_FOLLOW = options.follow_symlinks }; - const oflags: wasi.oflags_t = .{ .DIRECTORY = true }; - const fdflags: wasi.fdflags_t = .{}; - var fd: posix.fd_t = undefined; + var stat: wasi.filestat_t = undefined; + const syscall: Syscall = try .start(); while (true) { - try t.checkCancel(); - switch (wasi.path_open(dir.handle, lookup_flags, sub_path.ptr, sub_path.len, oflags, base, base, fdflags, &fd)) { - .SUCCESS => return .{ .handle = fd }, - .INTR => continue, - .CANCELED => return error.Canceled, - - .FAULT => |err| return errnoBug(err), - .INVAL => return error.BadPathName, - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .ACCES => return error.AccessDenied, - .LOOP => return error.SymLinkLoop, - .MFILE => return error.ProcessFdQuotaExceeded, - .NAMETOOLONG => return error.NameTooLong, - .NFILE => return error.SystemFdQuotaExceeded, - .NODEV => return error.NoDevice, - .NOENT => return error.FileNotFound, - .NOMEM => return error.SystemResources, - .NOTDIR => return error.NotDir, - .PERM => return error.PermissionDenied, - .BUSY => return error.DeviceBusy, - .NOTCAPABLE => return error.AccessDenied, - .ILSEQ => return error.BadPathName, - else => |err| return posix.unexpectedErrno(err), - } - } -} - -fn fileClose(userdata: ?*anyopaque, file: Io.File) void { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - _ = t; - posix.close(file.handle); -} - -const fileReadStreaming = switch (native_os) { - .windows => fileReadStreamingWindows, - else => fileReadStreamingPosix, -}; - -fn fileReadStreamingPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io.File.Reader.Error!usize { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - - var iovecs_buffer: [max_iovecs_len]posix.iovec = undefined; - var i: usize = 0; - for (data) |buf| { - if (iovecs_buffer.len - i == 0) break; - if (buf.len != 0) { - iovecs_buffer[i] = .{ .base = buf.ptr, .len = buf.len }; - i += 1; + switch (wasi.path_filestat_get(dir.handle, flags, sub_path.ptr, sub_path.len, &stat)) { + .SUCCESS => { + syscall.finish(); + break; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .INVAL => |err| return errnoBug(err), + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .NOMEM => return error.SystemResources, + .ACCES => return error.AccessDenied, + .FAULT => |err| return errnoBug(err), + .NAMETOOLONG => return error.NameTooLong, + .NOENT => return error.FileNotFound, + .NOTDIR => return error.FileNotFound, + .NOTCAPABLE => return error.AccessDenied, + .ILSEQ => return error.BadPathName, + else => |err| return posix.unexpectedErrno(err), + } + }, } } - const dest = iovecs_buffer[0..i]; - assert(dest[0].len > 0); - - if (native_os == .wasi and !builtin.link_libc) while (true) { - try t.checkCancel(); - var nread: usize = undefined; - switch (std.os.wasi.fd_read(file.handle, dest.ptr, dest.len, &nread)) { - .SUCCESS => return nread, - .INTR => continue, - .CANCELED => return error.Canceled, - .INVAL => |err| return errnoBug(err), - .FAULT => |err| return errnoBug(err), - .BADF => return error.NotOpenForReading, // File operation on directory. - .IO => return error.InputOutput, - .ISDIR => return error.IsDir, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTCONN => return error.SocketUnconnected, - .CONNRESET => return error.ConnectionResetByPeer, - .TIMEDOUT => return error.Timeout, - .NOTCAPABLE => return error.AccessDenied, - else => |err| return posix.unexpectedErrno(err), - } - }; + if (!options.read and !options.write and !options.execute) + return; - while (true) { - try t.checkCancel(); - const rc = posix.system.readv(file.handle, dest.ptr, @intCast(dest.len)); - switch (posix.errno(rc)) { - .SUCCESS => return @intCast(rc), - .INTR => continue, - .CANCELED => return error.Canceled, + var directory: wasi.fdstat_t = undefined; + if (wasi.fd_fdstat_get(dir.handle, &directory) != .SUCCESS) + return error.AccessDenied; - .INVAL => |err| return errnoBug(err), - .FAULT => |err| return errnoBug(err), - .SRCH => return error.ProcessNotFound, - .AGAIN => return error.WouldBlock, - .BADF => |err| { - if (native_os == .wasi) return error.NotOpenForReading; // File operation on directory. - return errnoBug(err); // File descriptor used after closed. - }, - .IO => return error.InputOutput, - .ISDIR => return error.IsDir, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTCONN => return error.SocketUnconnected, - .CONNRESET => return error.ConnectionResetByPeer, - .TIMEDOUT => return error.Timeout, - else => |err| return posix.unexpectedErrno(err), + var rights: wasi.rights_t = .{}; + if (options.read) { + if (stat.filetype == .DIRECTORY) { + rights.FD_READDIR = true; + } else { + rights.FD_READ = true; } } -} - -fn fileReadStreamingWindows(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io.File.Reader.Error!usize { - const t: *Threaded = @ptrCast(@alignCast(userdata)); + if (options.write) + rights.FD_WRITE = true; - const DWORD = windows.DWORD; - var index: usize = 0; - while (data[index].len == 0) index += 1; - const buffer = data[index]; - const want_read_count: DWORD = @min(std.math.maxInt(DWORD), buffer.len); + // No validation for execution. - while (true) { - try t.checkCancel(); - var n: DWORD = undefined; - if (windows.kernel32.ReadFile(file.handle, buffer.ptr, want_read_count, &n, null) != 0) - return n; - switch (windows.GetLastError()) { - .IO_PENDING => |err| return windows.errorBug(err), - .OPERATION_ABORTED => continue, - .BROKEN_PIPE => return 0, - .HANDLE_EOF => return 0, - .NETNAME_DELETED => return error.ConnectionResetByPeer, - .LOCK_VIOLATION => return error.LockViolation, - .ACCESS_DENIED => return error.AccessDenied, - .INVALID_HANDLE => return error.NotOpenForReading, - else => |err| return windows.unexpectedError(err), - } - } + // https://github.com/ziglang/zig/issues/18882 + const rights_int: u64 = @bitCast(rights); + const inheriting_int: u64 = @bitCast(directory.fs_rights_inheriting); + if ((rights_int & inheriting_int) != rights_int) + return error.AccessDenied; } -fn fileReadPositionalPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8, offset: u64) Io.File.ReadPositionalError!usize { +fn dirAccessWindows( + userdata: ?*anyopaque, + dir: Dir, + sub_path: []const u8, + options: Dir.AccessOptions, +) Dir.AccessError!void { const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; - if (!have_preadv) @compileError("TODO"); + _ = options; // TODO - var iovecs_buffer: [max_iovecs_len]posix.iovec = undefined; - var i: usize = 0; - for (data) |buf| { - if (iovecs_buffer.len - i == 0) break; - if (buf.len != 0) { - iovecs_buffer[i] = .{ .base = buf.ptr, .len = buf.len }; - i += 1; - } - } - const dest = iovecs_buffer[0..i]; - assert(dest[0].len > 0); + const sub_path_w_array = try windows.sliceToPrefixedFileW(dir.handle, sub_path); + const sub_path_w = sub_path_w_array.span(); - if (native_os == .wasi and !builtin.link_libc) while (true) { - try t.checkCancel(); - var nread: usize = undefined; - switch (std.os.wasi.fd_pread(file.handle, dest.ptr, dest.len, offset, &nread)) { - .SUCCESS => return nread, - .INTR => continue, - .CANCELED => return error.Canceled, + if (sub_path_w[0] == '.' and sub_path_w[1] == 0) return; + if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) return; - .INVAL => |err| return errnoBug(err), - .FAULT => |err| return errnoBug(err), - .AGAIN => |err| return errnoBug(err), - .BADF => return error.NotOpenForReading, // File operation on directory. - .IO => return error.InputOutput, - .ISDIR => return error.IsDir, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTCONN => return error.SocketUnconnected, - .CONNRESET => return error.ConnectionResetByPeer, - .TIMEDOUT => return error.Timeout, - .NXIO => return error.Unseekable, - .SPIPE => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .NOTCAPABLE => return error.AccessDenied, - else => |err| return posix.unexpectedErrno(err), - } + const path_len_bytes = std.math.cast(u16, std.mem.sliceTo(sub_path_w, 0).len * 2) orelse + return error.NameTooLong; + var nt_name: windows.UNICODE_STRING = .{ + .Length = path_len_bytes, + .MaximumLength = path_len_bytes, + .Buffer = @constCast(sub_path_w.ptr), + }; + var attr: windows.OBJECT_ATTRIBUTES = .{ + .Length = @sizeOf(windows.OBJECT_ATTRIBUTES), + .RootDirectory = if (Dir.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir.handle, + .Attributes = .{}, + .ObjectName = &nt_name, + .SecurityDescriptor = null, + .SecurityQualityOfService = null, + }; + var basic_info: windows.FILE.BASIC_INFORMATION = undefined; + const syscall: Syscall = try .start(); + while (true) switch (windows.ntdll.NtQueryAttributesFile(&attr, &basic_info)) { + .SUCCESS => return syscall.finish(), + .CANCELLED => { + try syscall.checkCancel(); + continue; + }, + .OBJECT_NAME_NOT_FOUND => return syscall.fail(error.FileNotFound), + .OBJECT_PATH_NOT_FOUND => return syscall.fail(error.FileNotFound), + .OBJECT_NAME_INVALID => |err| return syscall.ntstatusBug(err), + .INVALID_PARAMETER => |err| return syscall.ntstatusBug(err), + .ACCESS_DENIED => return syscall.fail(error.AccessDenied), + .OBJECT_PATH_SYNTAX_BAD => |err| return syscall.ntstatusBug(err), + else => |rc| return syscall.unexpectedNtstatus(rc), }; - - while (true) { - try t.checkCancel(); - const rc = preadv_sym(file.handle, dest.ptr, @intCast(dest.len), @bitCast(offset)); - switch (posix.errno(rc)) { - .SUCCESS => return @bitCast(rc), - .INTR => continue, - .CANCELED => return error.Canceled, - - .INVAL => |err| return errnoBug(err), - .FAULT => |err| return errnoBug(err), - .SRCH => return error.ProcessNotFound, - .AGAIN => return error.WouldBlock, - .BADF => |err| { - if (native_os == .wasi) return error.NotOpenForReading; // File operation on directory. - return errnoBug(err); // File descriptor used after closed. - }, - .IO => return error.InputOutput, - .ISDIR => return error.IsDir, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTCONN => return error.SocketUnconnected, - .CONNRESET => return error.ConnectionResetByPeer, - .TIMEDOUT => return error.Timeout, - .NXIO => return error.Unseekable, - .SPIPE => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - else => |err| return posix.unexpectedErrno(err), - } - } } -const fileReadPositional = switch (native_os) { - .windows => fileReadPositionalWindows, - else => fileReadPositionalPosix, +const dirCreateFile = switch (native_os) { + .windows => dirCreateFileWindows, + .wasi => dirCreateFileWasi, + else => dirCreateFilePosix, }; -fn fileReadPositionalWindows(userdata: ?*anyopaque, file: Io.File, data: [][]u8, offset: u64) Io.File.ReadPositionalError!usize { +fn dirCreateFilePosix( + userdata: ?*anyopaque, + dir: Dir, + sub_path: []const u8, + flags: File.CreateFlags, +) File.OpenError!File { const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; - const DWORD = windows.DWORD; - - var index: usize = 0; - while (data[index].len == 0) index += 1; - const buffer = data[index]; - const want_read_count: DWORD = @min(std.math.maxInt(DWORD), buffer.len); + var path_buffer: [posix.PATH_MAX]u8 = undefined; + const sub_path_posix = try pathToPosix(sub_path, &path_buffer); - var overlapped: windows.OVERLAPPED = .{ - .Internal = 0, - .InternalHigh = 0, - .DUMMYUNIONNAME = .{ - .DUMMYSTRUCTNAME = .{ - .Offset = @truncate(offset), - .OffsetHigh = @truncate(offset >> 32), - }, + var os_flags: posix.O = .{ + .ACCMODE = if (flags.read) .RDWR else .WRONLY, + .CREAT = true, + .TRUNC = flags.truncate, + .EXCL = flags.exclusive, + }; + if (@hasField(posix.O, "LARGEFILE")) os_flags.LARGEFILE = true; + if (@hasField(posix.O, "CLOEXEC")) os_flags.CLOEXEC = true; + + // Use the O locking flags if the os supports them to acquire the lock + // atomically. Note that the NONBLOCK flag is removed after the openat() + // call is successful. + if (have_flock_open_flags) switch (flags.lock) { + .none => {}, + .shared => { + os_flags.SHLOCK = true; + os_flags.NONBLOCK = flags.lock_nonblocking; + }, + .exclusive => { + os_flags.EXLOCK = true; + os_flags.NONBLOCK = flags.lock_nonblocking; }, - .hEvent = null, }; - while (true) { - try t.checkCancel(); - var n: DWORD = undefined; - if (windows.kernel32.ReadFile(file.handle, buffer.ptr, want_read_count, &n, &overlapped) != 0) - return n; - switch (windows.GetLastError()) { - .IO_PENDING => |err| return windows.errorBug(err), - .OPERATION_ABORTED => continue, - .BROKEN_PIPE => return 0, - .HANDLE_EOF => return 0, - .NETNAME_DELETED => return error.ConnectionResetByPeer, - .LOCK_VIOLATION => return error.LockViolation, - .ACCESS_DENIED => return error.AccessDenied, - .INVALID_HANDLE => return error.NotOpenForReading, - else => |err| return windows.unexpectedError(err), + const fd: posix.fd_t = fd: { + const syscall: Syscall = try .start(); + while (true) { + const rc = openat_sym(dir.handle, sub_path_posix, os_flags, flags.permissions.toMode()); + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + break :fd @intCast(rc); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .FAULT => |err| return errnoBug(err), + .INVAL => return error.BadPathName, + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .ACCES => return error.AccessDenied, + .FBIG => return error.FileTooBig, + .OVERFLOW => return error.FileTooBig, + .ISDIR => return error.IsDir, + .LOOP => return error.SymLinkLoop, + .MFILE => return error.ProcessFdQuotaExceeded, + .NAMETOOLONG => return error.NameTooLong, + .NFILE => return error.SystemFdQuotaExceeded, + .NODEV => return error.NoDevice, + .NOENT => return error.FileNotFound, + .SRCH => return error.FileNotFound, // Linux when accessing procfs. + .NOMEM => return error.SystemResources, + .NOSPC => return error.NoSpaceLeft, + .NOTDIR => return error.NotDir, + .PERM => return error.PermissionDenied, + .EXIST => return error.PathAlreadyExists, + .BUSY => return error.DeviceBusy, + .OPNOTSUPP => return error.FileLocksUnsupported, + .AGAIN => return error.WouldBlock, + .TXTBSY => return error.FileBusy, + .NXIO => return error.NoDevice, + .ILSEQ => return error.BadPathName, + else => |err| return posix.unexpectedErrno(err), + } + }, + } } - } -} + }; + errdefer posix.close(fd); -fn fileSeekBy(userdata: ?*anyopaque, file: Io.File, offset: i64) Io.File.SeekError!void { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - try t.checkCancel(); + if (have_flock and !have_flock_open_flags and flags.lock != .none) { + const lock_nonblocking: i32 = if (flags.lock_nonblocking) posix.LOCK.NB else 0; + const lock_flags = switch (flags.lock) { + .none => unreachable, + .shared => posix.LOCK.SH | lock_nonblocking, + .exclusive => posix.LOCK.EX | lock_nonblocking, + }; - _ = file; - _ = offset; - @panic("TODO implement fileSeekBy"); -} + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.flock(fd, lock_flags))) { + .SUCCESS => { + syscall.finish(); + break; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .INVAL => |err| return errnoBug(err), // invalid parameters + .NOLCK => return error.SystemResources, + .AGAIN => return error.WouldBlock, + .OPNOTSUPP => return error.FileLocksUnsupported, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } + } -fn fileSeekTo(userdata: ?*anyopaque, file: Io.File, offset: u64) Io.File.SeekError!void { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - const fd = file.handle; + if (have_flock_open_flags and flags.lock_nonblocking) { + var fl_flags: usize = fl: { + const syscall: Syscall = try .start(); + while (true) { + const rc = posix.system.fcntl(fd, posix.F.GETFL, @as(usize, 0)); + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + break :fl @intCast(rc); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |err| { + syscall.finish(); + return posix.unexpectedErrno(err); + }, + } + } + }; - if (native_os == .linux and !builtin.link_libc and @sizeOf(usize) == 4) while (true) { - try t.checkCancel(); - var result: u64 = undefined; - switch (posix.errno(posix.system.llseek(fd, offset, &result, posix.SEEK.SET))) { - .SUCCESS => return, - .INTR => continue, - .CANCELED => return error.Canceled, + fl_flags |= @as(usize, 1 << @bitOffsetOf(posix.O, "NONBLOCK")); - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .INVAL => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .SPIPE => return error.Unseekable, - .NXIO => return error.Unseekable, - else => |err| return posix.unexpectedErrno(err), + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.fcntl(fd, posix.F.SETFL, fl_flags))) { + .SUCCESS => { + syscall.finish(); + break; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |err| { + syscall.finish(); + return posix.unexpectedErrno(err); + }, + } } - }; - - if (native_os == .windows) { - try t.checkCancel(); - return windows.SetFilePointerEx_BEGIN(fd, offset); } - if (native_os == .wasi and !builtin.link_libc) while (true) { - try t.checkCancel(); - var new_offset: std.os.wasi.filesize_t = undefined; - switch (std.os.wasi.fd_seek(fd, @bitCast(offset), .SET, &new_offset)) { - .SUCCESS => return, - .INTR => continue, - .CANCELED => return error.Canceled, - - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .INVAL => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .SPIPE => return error.Unseekable, - .NXIO => return error.Unseekable, - .NOTCAPABLE => return error.AccessDenied, - else => |err| return posix.unexpectedErrno(err), - } - }; + return .{ .handle = fd }; +} - if (posix.SEEK == void) return error.Unseekable; +fn dirCreateFileWindows( + userdata: ?*anyopaque, + dir: Dir, + sub_path: []const u8, + flags: File.CreateFlags, +) File.OpenError!File { + const w = windows; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; - while (true) { - try t.checkCancel(); - switch (posix.errno(lseek_sym(fd, @bitCast(offset), posix.SEEK.SET))) { - .SUCCESS => return, - .INTR => continue, - .CANCELED => return error.Canceled, + const sub_path_w_array = try w.sliceToPrefixedFileW(dir.handle, sub_path); + const sub_path_w = sub_path_w_array.span(); - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .INVAL => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .SPIPE => return error.Unseekable, - .NXIO => return error.Unseekable, - else => |err| return posix.unexpectedErrno(err), + const handle = handle: { + const syscall: Syscall = try .start(); + while (true) { + if (w.OpenFile(sub_path_w, .{ + .dir = dir.handle, + .access_mask = .{ + .STANDARD = .{ .SYNCHRONIZE = true }, + .GENERIC = .{ + .WRITE = true, + .READ = flags.read, + }, + }, + .creation = if (flags.exclusive) + .CREATE + else if (flags.truncate) + .OVERWRITE_IF + else + .OPEN_IF, + })) |handle| { + syscall.finish(); + break :handle handle; + } else |err| switch (err) { + error.OperationCanceled => { + try syscall.checkCancel(); + continue; + }, + else => |e| return syscall.fail(e), + } } - } -} + }; + errdefer w.CloseHandle(handle); -fn openSelfExe(userdata: ?*anyopaque, flags: Io.File.OpenFlags) Io.File.OpenSelfExeError!Io.File { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - switch (native_os) { - .linux, .serenity => return dirOpenFilePosix(t, .{ .handle = posix.AT.FDCWD }, "/proc/self/exe", flags), - .windows => { - // If ImagePathName is a symlink, then it will contain the path of the symlink, - // not the path that the symlink points to. However, because we are opening - // the file, we can let the openFileW call follow the symlink for us. - const image_path_unicode_string = &windows.peb().ProcessParameters.ImagePathName; - const image_path_name = image_path_unicode_string.Buffer.?[0 .. image_path_unicode_string.Length / 2 :0]; - const prefixed_path_w = try windows.wToPrefixedFileW(null, image_path_name); - return dirOpenFileWtf16(t, null, prefixed_path_w.span(), flags); + var io_status_block: w.IO_STATUS_BLOCK = undefined; + const exclusive = switch (flags.lock) { + .none => return .{ .handle = handle }, + .shared => false, + .exclusive => true, + }; + const syscall: Syscall = try .start(); + while (true) switch (w.ntdll.NtLockFile( + handle, + null, + null, + null, + &io_status_block, + &windows_lock_range_off, + &windows_lock_range_len, + null, + @intFromBool(flags.lock_nonblocking), + @intFromBool(exclusive), + )) { + .SUCCESS => { + syscall.finish(); + return .{ .handle = handle }; }, - else => @panic("TODO implement openSelfExe"), - } + .INSUFFICIENT_RESOURCES => return syscall.fail(error.SystemResources), + .LOCK_NOT_GRANTED => return syscall.fail(error.WouldBlock), + .ACCESS_VIOLATION => |err| return syscall.ntstatusBug(err), // bad io_status_block pointer + else => |status| return syscall.unexpectedNtstatus(status), + }; } -fn fileWritePositional( +fn dirCreateFileWasi( userdata: ?*anyopaque, - file: Io.File, - buffer: [][]const u8, - offset: u64, -) Io.File.WritePositionalError!usize { + dir: Dir, + sub_path: []const u8, + flags: File.CreateFlags, +) File.OpenError!File { const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + const wasi = std.os.wasi; + const lookup_flags: wasi.lookupflags_t = .{}; + const oflags: wasi.oflags_t = .{ + .CREAT = true, + .TRUNC = flags.truncate, + .EXCL = flags.exclusive, + }; + const fdflags: wasi.fdflags_t = .{}; + const base: wasi.rights_t = .{ + .FD_READ = flags.read, + .FD_WRITE = true, + .FD_DATASYNC = true, + .FD_SEEK = true, + .FD_TELL = true, + .FD_FDSTAT_SET_FLAGS = true, + .FD_SYNC = true, + .FD_ALLOCATE = true, + .FD_ADVISE = true, + .FD_FILESTAT_SET_TIMES = true, + .FD_FILESTAT_SET_SIZE = true, + .FD_FILESTAT_GET = true, + // POLL_FD_READWRITE only grants extra rights if the corresponding FD_READ and/or + // FD_WRITE is also set. + .POLL_FD_READWRITE = true, + }; + const inheriting: wasi.rights_t = .{}; + var fd: posix.fd_t = undefined; + const syscall: Syscall = try .start(); while (true) { - try t.checkCancel(); - _ = file; - _ = buffer; - _ = offset; - @panic("TODO implement fileWritePositional"); + switch (wasi.path_open(dir.handle, lookup_flags, sub_path.ptr, sub_path.len, oflags, base, inheriting, fdflags, &fd)) { + .SUCCESS => { + syscall.finish(); + return .{ .handle = fd }; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .FAULT => |err| return errnoBug(err), + .INVAL => return error.BadPathName, + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .ACCES => return error.AccessDenied, + .FBIG => return error.FileTooBig, + .OVERFLOW => return error.FileTooBig, + .ISDIR => return error.IsDir, + .LOOP => return error.SymLinkLoop, + .MFILE => return error.ProcessFdQuotaExceeded, + .NAMETOOLONG => return error.NameTooLong, + .NFILE => return error.SystemFdQuotaExceeded, + .NODEV => return error.NoDevice, + .NOENT => return error.FileNotFound, + .NOMEM => return error.SystemResources, + .NOSPC => return error.NoSpaceLeft, + .NOTDIR => return error.NotDir, + .PERM => return error.PermissionDenied, + .EXIST => return error.PathAlreadyExists, + .BUSY => return error.DeviceBusy, + .NOTCAPABLE => return error.AccessDenied, + .ILSEQ => return error.BadPathName, + else => |err| return posix.unexpectedErrno(err), + } + }, + } } } -fn fileWriteStreaming(userdata: ?*anyopaque, file: Io.File, buffer: [][]const u8) Io.File.WriteStreamingError!usize { +fn dirCreateFileAtomic( + userdata: ?*anyopaque, + dir: Dir, + dest_path: []const u8, + options: Dir.CreateFileAtomicOptions, +) Dir.CreateFileAtomicError!File.Atomic { const t: *Threaded = @ptrCast(@alignCast(userdata)); - while (true) { - try t.checkCancel(); - _ = file; - _ = buffer; - @panic("TODO implement fileWriteStreaming"); + const t_io = ioBasic(t); + + // Linux has O_TMPFILE, but linkat() does not support AT_REPLACE, so it's + // useless when we have to make up a bogus path name to do the rename() + // anyway. + if (native_os == .linux and !options.replace) tmpfile: { + const flags: posix.O = if (@hasField(posix.O, "TMPFILE")) .{ + .ACCMODE = .RDWR, + .TMPFILE = true, + .DIRECTORY = true, + .CLOEXEC = true, + } else if (@hasField(posix.O, "TMPFILE0") and !@hasField(posix.O, "TMPFILE2")) .{ + .ACCMODE = .RDWR, + .TMPFILE0 = true, + .TMPFILE1 = true, + .DIRECTORY = true, + .CLOEXEC = true, + } else break :tmpfile; + + const dest_dirname = Dir.path.dirname(dest_path); + if (dest_dirname) |dirname| { + // This has a nice side effect of preemptively triggering EISDIR or + // ENOENT, avoiding the ambiguity below. + if (options.make_path) dir.createDirPath(t_io, dirname) catch |err| switch (err) { + // None of these make sense in this context. + error.IsDir, + error.Streaming, + error.DiskQuota, + error.PathAlreadyExists, + error.LinkQuotaExceeded, + error.SharingViolation, + error.PipeBusy, + error.FileTooBig, + error.DeviceBusy, + error.FileLocksUnsupported, + error.FileBusy, + => return error.Unexpected, + + else => |e| return e, + }; + } + + var path_buffer: [posix.PATH_MAX]u8 = undefined; + const sub_path_posix = try pathToPosix(dest_dirname orelse ".", &path_buffer); + + const syscall: Syscall = try .start(); + while (true) { + const rc = openat_sym(dir.handle, sub_path_posix, flags, options.permissions.toMode()); + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + return .{ + .file = .{ .handle = @intCast(rc) }, + .file_basename_hex = 0, + .dest_sub_path = dest_path, + .file_open = true, + .file_exists = false, + .close_dir_on_deinit = false, + .dir = dir, + }; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + .ISDIR, .NOENT => { + // Ambiguous error code. It might mean the file system + // does not support O_TMPFILE. Therefore, we must fall + // back to not using O_TMPFILE. + syscall.finish(); + break :tmpfile; + }, + .INVAL => return syscall.fail(error.BadPathName), + .ACCES => return syscall.fail(error.AccessDenied), + .LOOP => return syscall.fail(error.SymLinkLoop), + .MFILE => return syscall.fail(error.ProcessFdQuotaExceeded), + .NAMETOOLONG => return syscall.fail(error.NameTooLong), + .NFILE => return syscall.fail(error.SystemFdQuotaExceeded), + .NODEV => return syscall.fail(error.NoDevice), + .NOMEM => return syscall.fail(error.SystemResources), + .NOSPC => return syscall.fail(error.NoSpaceLeft), + .NOTDIR => return syscall.fail(error.NotDir), + .PERM => return syscall.fail(error.PermissionDenied), + .AGAIN => return syscall.fail(error.WouldBlock), + .NXIO => return syscall.fail(error.NoDevice), + .ILSEQ => return syscall.fail(error.BadPathName), + else => |err| return syscall.unexpectedErrno(err), + } + } + } + + if (Dir.path.dirname(dest_path)) |dirname| { + const new_dir = if (options.make_path) + dir.createDirPathOpen(t_io, dirname, .{}) catch |err| switch (err) { + // None of these make sense in this context. + error.IsDir, + error.Streaming, + error.DiskQuota, + error.PathAlreadyExists, + error.LinkQuotaExceeded, + error.SharingViolation, + error.PipeBusy, + error.FileTooBig, + error.FileLocksUnsupported, + error.FileBusy, + error.DeviceBusy, + => return error.Unexpected, + + else => |e| return e, + } + else + try dir.openDir(t_io, dirname, .{}); + + return atomicFileInit(t_io, Dir.path.basename(dest_path), options.permissions, new_dir, true); } + + return atomicFileInit(t_io, dest_path, options.permissions, dir, false); } -fn nowPosix(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - _ = t; - const clock_id: posix.clockid_t = clockToPosix(clock); - var tp: posix.timespec = undefined; - switch (posix.errno(posix.system.clock_gettime(clock_id, &tp))) { - .SUCCESS => return timestampFromPosix(&tp), - .INVAL => return error.UnsupportedClock, - else => |err| return posix.unexpectedErrno(err), +fn atomicFileInit( + t_io: Io, + dest_basename: []const u8, + permissions: File.Permissions, + dir: Dir, + close_dir_on_deinit: bool, +) Dir.CreateFileAtomicError!File.Atomic { + var random_integer: u64 = undefined; + while (true) { + t_io.random(@ptrCast(&random_integer)); + const tmp_sub_path = std.fmt.hex(random_integer); + const file = dir.createFile(t_io, &tmp_sub_path, .{ + .permissions = permissions, + .exclusive = true, + }) catch |err| switch (err) { + error.PathAlreadyExists => continue, + error.DeviceBusy => continue, + error.FileBusy => continue, + error.SharingViolation => continue, + + error.IsDir => return error.Unexpected, // No path components. + error.FileTooBig => return error.Unexpected, // Creating, not opening. + error.FileLocksUnsupported => return error.Unexpected, // Not asking for locks. + error.PipeBusy => return error.Unexpected, // Not opening a pipe. + + else => |e| return e, + }; + return .{ + .file = file, + .file_basename_hex = random_integer, + .dest_sub_path = dest_basename, + .file_open = true, + .file_exists = true, + .close_dir_on_deinit = close_dir_on_deinit, + .dir = dir, + }; } } -const now = switch (native_os) { - .windows => nowWindows, - .wasi => nowWasi, - else => nowPosix, +const dirOpenFile = switch (native_os) { + .windows => dirOpenFileWindows, + .wasi => dirOpenFileWasi, + else => dirOpenFilePosix, }; -fn nowWindows(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp { +fn dirOpenFilePosix( + userdata: ?*anyopaque, + dir: Dir, + sub_path: []const u8, + flags: File.OpenFlags, +) File.OpenError!File { const t: *Threaded = @ptrCast(@alignCast(userdata)); - _ = t; - switch (clock) { - .real => { - // RtlGetSystemTimePrecise() has a granularity of 100 nanoseconds - // and uses the NTFS/Windows epoch, which is 1601-01-01. - const epoch_ns = std.time.epoch.windows * std.time.ns_per_s; - return .{ .nanoseconds = @as(i96, windows.ntdll.RtlGetSystemTimePrecise()) * 100 + epoch_ns }; - }, - .awake, .boot => { - // QPC on windows doesn't fail on >= XP/2000 and includes time suspended. - const qpc = windows.QueryPerformanceCounter(); - // We don't need to cache QPF as it's internally just a memory read to KUSER_SHARED_DATA - // (a read-only page of info updated and mapped by the kernel to all processes): - // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/ns-ntddk-kuser_shared_data - // https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/ntexapi_x/kuser_shared_data/index.htm - const qpf = windows.QueryPerformanceFrequency(); - // 10Mhz (1 qpc tick every 100ns) is a common enough QPF value that we can optimize on it. - // https://github.com/microsoft/STL/blob/785143a0c73f030238ef618890fd4d6ae2b3a3a0/stl/inc/chrono#L694-L701 - const common_qpf = 10_000_000; - if (qpf == common_qpf) return .{ .nanoseconds = qpc * (std.time.ns_per_s / common_qpf) }; + var path_buffer: [posix.PATH_MAX]u8 = undefined; + const sub_path_posix = try pathToPosix(sub_path, &path_buffer); - // Convert to ns using fixed point. - const scale = @as(u64, std.time.ns_per_s << 32) / @as(u32, @intCast(qpf)); - const result = (@as(u96, qpc) * scale) >> 32; - return .{ .nanoseconds = @intCast(result) }; + var os_flags: posix.O = switch (native_os) { + .wasi => .{ + .read = flags.mode != .write_only, + .write = flags.mode != .read_only, + .NOFOLLOW = !flags.follow_symlinks, + }, + else => .{ + .ACCMODE = switch (flags.mode) { + .read_only => .RDONLY, + .write_only => .WRONLY, + .read_write => .RDWR, + }, + .NOFOLLOW = !flags.follow_symlinks, }, - .cpu_process, - .cpu_thread, - => return error.UnsupportedClock, - } -} - -fn nowWasi(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - _ = t; - var ns: std.os.wasi.timestamp_t = undefined; - const err = std.os.wasi.clock_time_get(clockToWasi(clock), 1, &ns); - if (err != .SUCCESS) return error.Unexpected; - return .fromNanoseconds(ns); -} - -const sleep = switch (native_os) { - .windows => sleepWindows, - .wasi => sleepWasi, - .linux => sleepLinux, - else => sleepPosix, -}; - -fn sleepLinux(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - const clock_id: posix.clockid_t = clockToPosix(switch (timeout) { - .none => .awake, - .duration => |d| d.clock, - .deadline => |d| d.clock, - }); - const deadline_nanoseconds: i96 = switch (timeout) { - .none => std.math.maxInt(i96), - .duration => |duration| duration.raw.nanoseconds, - .deadline => |deadline| deadline.raw.nanoseconds, }; - var timespec: posix.timespec = timestampToPosix(deadline_nanoseconds); - while (true) { - try t.checkCancel(); - switch (std.os.linux.errno(std.os.linux.clock_nanosleep(clock_id, .{ .ABSTIME = switch (timeout) { - .none, .duration => false, - .deadline => true, - } }, ×pec, ×pec))) { - .SUCCESS => return, - .INTR => continue, - .CANCELED => return error.Canceled, - .INVAL => return error.UnsupportedClock, - else => |err| return posix.unexpectedErrno(err), - } - } -} + if (@hasField(posix.O, "CLOEXEC")) os_flags.CLOEXEC = true; + if (@hasField(posix.O, "LARGEFILE")) os_flags.LARGEFILE = true; + if (@hasField(posix.O, "NOCTTY")) os_flags.NOCTTY = !flags.allow_ctty; + if (@hasField(posix.O, "PATH") and flags.path_only) os_flags.PATH = true; -fn sleepWindows(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - const t_io = ioBasic(t); - try t.checkCancel(); - const ms = ms: { - const d = (try timeout.toDurationFromNow(t_io)) orelse - break :ms std.math.maxInt(windows.DWORD); - break :ms std.math.lossyCast(windows.DWORD, d.raw.toMilliseconds()); + // Use the O locking flags if the os supports them to acquire the lock + // atomically. Note that the NONBLOCK flag is removed after the openat() + // call is successful. + if (have_flock_open_flags) switch (flags.lock) { + .none => {}, + .shared => { + os_flags.SHLOCK = true; + os_flags.NONBLOCK = flags.lock_nonblocking; + }, + .exclusive => { + os_flags.EXLOCK = true; + os_flags.NONBLOCK = flags.lock_nonblocking; + }, }; - // TODO: alertable true with checkCancel in a loop plus deadline - _ = windows.kernel32.SleepEx(ms, windows.FALSE); -} -fn sleepWasi(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - const t_io = ioBasic(t); - try t.checkCancel(); - - const w = std.os.wasi; + const mode: posix.mode_t = 0; - const clock: w.subscription_clock_t = if (try timeout.toDurationFromNow(t_io)) |d| .{ - .id = clockToWasi(d.clock), - .timeout = std.math.lossyCast(u64, d.raw.nanoseconds), - .precision = 0, - .flags = 0, - } else .{ - .id = .MONOTONIC, - .timeout = std.math.maxInt(u64), - .precision = 0, - .flags = 0, - }; - const in: w.subscription_t = .{ - .userdata = 0, - .u = .{ - .tag = .CLOCK, - .u = .{ .clock = clock }, - }, + const fd: posix.fd_t = fd: { + const syscall: Syscall = try .start(); + while (true) { + const rc = openat_sym(dir.handle, sub_path_posix, os_flags, mode); + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + break :fd @intCast(rc); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .FAULT => |err| return errnoBug(err), + .INVAL => return error.BadPathName, + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .ACCES => return error.AccessDenied, + .FBIG => return error.FileTooBig, + .OVERFLOW => return error.FileTooBig, + .ISDIR => return error.IsDir, + .LOOP => return error.SymLinkLoop, + .MFILE => return error.ProcessFdQuotaExceeded, + .NAMETOOLONG => return error.NameTooLong, + .NFILE => return error.SystemFdQuotaExceeded, + .NODEV => return error.NoDevice, + .NOENT => return error.FileNotFound, + .SRCH => return error.FileNotFound, // Linux when opening procfs files. + .NOMEM => return error.SystemResources, + .NOSPC => return error.NoSpaceLeft, + .NOTDIR => return error.NotDir, + .PERM => return error.PermissionDenied, + .EXIST => return error.PathAlreadyExists, + .BUSY => return error.DeviceBusy, + .OPNOTSUPP => return error.FileLocksUnsupported, + .AGAIN => return error.WouldBlock, + .TXTBSY => return error.FileBusy, + .NXIO => return error.NoDevice, + .ILSEQ => return error.BadPathName, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } }; - var event: w.event_t = undefined; - var nevents: usize = undefined; - _ = w.poll_oneoff(&in, &event, 1, &nevents); -} + errdefer posix.close(fd); -fn sleepPosix(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - const t_io = ioBasic(t); - const sec_type = @typeInfo(posix.timespec).@"struct".fields[0].type; - const nsec_type = @typeInfo(posix.timespec).@"struct".fields[1].type; + if (!flags.allow_directory) { + const is_dir = is_dir: { + const stat = fileStat(t, .{ .handle = fd }) catch |err| switch (err) { + // The directory-ness is either unknown or unknowable + error.Streaming => break :is_dir false, + else => |e| return e, + }; + break :is_dir stat.kind == .directory; + }; + if (is_dir) return error.IsDir; + } - var timespec: posix.timespec = t: { - const d = (try timeout.toDurationFromNow(t_io)) orelse break :t .{ - .sec = std.math.maxInt(sec_type), - .nsec = std.math.maxInt(nsec_type), + if (have_flock and !have_flock_open_flags and flags.lock != .none) { + const lock_nonblocking: i32 = if (flags.lock_nonblocking) posix.LOCK.NB else 0; + const lock_flags = switch (flags.lock) { + .none => unreachable, + .shared => posix.LOCK.SH | lock_nonblocking, + .exclusive => posix.LOCK.EX | lock_nonblocking, }; - break :t timestampToPosix(d.raw.toNanoseconds()); - }; - while (true) { - try t.checkCancel(); - switch (posix.errno(posix.system.nanosleep(×pec, ×pec))) { - .INTR => continue, - .CANCELED => return error.Canceled, - else => return, // This prong handles success as well as unexpected errors. + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.flock(fd, lock_flags))) { + .SUCCESS => { + syscall.finish(); + break; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .INVAL => |err| return errnoBug(err), // invalid parameters + .NOLCK => return error.SystemResources, + .AGAIN => return error.WouldBlock, + .OPNOTSUPP => return error.FileLocksUnsupported, + else => |err| return posix.unexpectedErrno(err), + } + }, + } } } -} - -fn select(userdata: ?*anyopaque, futures: []const *Io.AnyFuture) Io.Cancelable!usize { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - var reset_event: ResetEvent = .unset; - - for (futures, 0..) |future, i| { - const closure: *AsyncClosure = @ptrCast(@alignCast(future)); - if (@atomicRmw(?*ResetEvent, &closure.select_condition, .Xchg, &reset_event, .seq_cst) == AsyncClosure.done_reset_event) { - for (futures[0..i]) |cleanup_future| { - const cleanup_closure: *AsyncClosure = @ptrCast(@alignCast(cleanup_future)); - if (@atomicRmw(?*ResetEvent, &cleanup_closure.select_condition, .Xchg, null, .seq_cst) == AsyncClosure.done_reset_event) { - cleanup_closure.reset_event.waitUncancelable(); // Ensure no reference to our stack-allocated reset_event. + if (have_flock_open_flags and flags.lock_nonblocking) { + var fl_flags: usize = fl: { + const syscall: Syscall = try .start(); + while (true) { + const rc = posix.system.fcntl(fd, posix.F.GETFL, @as(usize, 0)); + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + break :fl @intCast(rc); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |err| { + syscall.finish(); + return posix.unexpectedErrno(err); + }, } } - return i; - } - } + }; - try reset_event.wait(t); + fl_flags |= @as(usize, 1 << @bitOffsetOf(posix.O, "NONBLOCK")); - var result: ?usize = null; - for (futures, 0..) |future, i| { - const closure: *AsyncClosure = @ptrCast(@alignCast(future)); - if (@atomicRmw(?*ResetEvent, &closure.select_condition, .Xchg, null, .seq_cst) == AsyncClosure.done_reset_event) { - closure.reset_event.waitUncancelable(); // Ensure no reference to our stack-allocated reset_event. - if (result == null) result = i; // In case multiple are ready, return first. + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.fcntl(fd, posix.F.SETFL, fl_flags))) { + .SUCCESS => { + syscall.finish(); + break; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |err| { + syscall.finish(); + return posix.unexpectedErrno(err); + }, + } } } - return result.?; + + return .{ .handle = fd }; } -fn netListenIpPosix( +fn dirOpenFileWindows( userdata: ?*anyopaque, - address: IpAddress, - options: IpAddress.ListenOptions, -) IpAddress.ListenError!net.Server { - if (!have_networking) return error.NetworkDown; + dir: Dir, + sub_path: []const u8, + flags: File.OpenFlags, +) File.OpenError!File { const t: *Threaded = @ptrCast(@alignCast(userdata)); - const family = posixAddressFamily(&address); - const socket_fd = try openSocketPosix(t, family, .{ - .mode = options.mode, - .protocol = options.protocol, - }); - errdefer posix.close(socket_fd); - - if (options.reuse_address) { - try setSocketOption(t, socket_fd, posix.SOL.SOCKET, posix.SO.REUSEADDR, 1); - if (@hasDecl(posix.SO, "REUSEPORT")) - try setSocketOption(t, socket_fd, posix.SOL.SOCKET, posix.SO.REUSEPORT, 1); - } - - var storage: PosixAddress = undefined; - var addr_len = addressToPosix(&address, &storage); - try posixBind(t, socket_fd, &storage.any, addr_len); - - while (true) { - try t.checkCancel(); - switch (posix.errno(posix.system.listen(socket_fd, options.kernel_backlog))) { - .SUCCESS => break, - .ADDRINUSE => return error.AddressInUse, - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - else => |err| return posix.unexpectedErrno(err), - } - } - - try posixGetSockName(t, socket_fd, &storage.any, &addr_len); - return .{ - .socket = .{ - .handle = socket_fd, - .address = addressFromPosix(&storage), - }, - }; + _ = t; + const sub_path_w_array = try windows.sliceToPrefixedFileW(dir.handle, sub_path); + const sub_path_w = sub_path_w_array.span(); + const dir_handle = if (Dir.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir.handle; + return dirOpenFileWtf16(dir_handle, sub_path_w, flags); } -fn netListenIpWindows( - userdata: ?*anyopaque, - address: IpAddress, - options: IpAddress.ListenOptions, -) IpAddress.ListenError!net.Server { - if (!have_networking) return error.NetworkDown; - const t: *Threaded = @ptrCast(@alignCast(userdata)); - const family = posixAddressFamily(&address); - const socket_handle = try openSocketWsa(t, family, .{ - .mode = options.mode, - .protocol = options.protocol, - }); - errdefer closeSocketWindows(socket_handle); +pub fn dirOpenFileWtf16( + dir_handle: ?windows.HANDLE, + sub_path_w: [:0]const u16, + flags: File.OpenFlags, +) File.OpenError!File { + const allow_directory = flags.allow_directory and !flags.isWrite(); + if (!allow_directory and std.mem.eql(u16, sub_path_w, &.{'.'})) return error.IsDir; + if (!allow_directory and std.mem.eql(u16, sub_path_w, &.{ '.', '.' })) return error.IsDir; + const path_len_bytes = std.math.cast(u16, sub_path_w.len * 2) orelse return error.NameTooLong; + const w = windows; - if (options.reuse_address) - try setSocketOptionWsa(t, socket_handle, posix.SOL.SOCKET, posix.SO.REUSEADDR, 1); + var nt_name: w.UNICODE_STRING = .{ + .Length = path_len_bytes, + .MaximumLength = path_len_bytes, + .Buffer = @constCast(sub_path_w.ptr), + }; + var attr: w.OBJECT_ATTRIBUTES = .{ + .Length = @sizeOf(w.OBJECT_ATTRIBUTES), + .RootDirectory = dir_handle, + .Attributes = .{}, + .ObjectName = &nt_name, + .SecurityDescriptor = null, + .SecurityQualityOfService = null, + }; + var io_status_block: w.IO_STATUS_BLOCK = undefined; - var storage: WsaAddress = undefined; - var addr_len = addressToWsa(&address, &storage); + // There are multiple kernel bugs being worked around with retries. + const max_attempts = 13; + var attempt: u5 = 0; - while (true) { - try t.checkCancel(); - const rc = ws2_32.bind(socket_handle, &storage.any, addr_len); - if (rc != ws2_32.SOCKET_ERROR) break; - switch (ws2_32.WSAGetLastError()) { - .EINTR => continue, - .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => return error.Canceled, - .NOTINITIALISED => { - try initializeWsa(t); - continue; + var syscall: Syscall = try .start(); + const handle = while (true) { + var result: w.HANDLE = undefined; + switch (w.ntdll.NtCreateFile( + &result, + .{ + .STANDARD = .{ .SYNCHRONIZE = true }, + .GENERIC = .{ + .READ = flags.isRead(), + .WRITE = flags.isWrite(), + }, }, - .EADDRINUSE => return error.AddressInUse, - .EADDRNOTAVAIL => return error.AddressUnavailable, - .ENOTSOCK => |err| return wsaErrorBug(err), - .EFAULT => |err| return wsaErrorBug(err), - .EINVAL => |err| return wsaErrorBug(err), - .ENOBUFS => return error.SystemResources, - .ENETDOWN => return error.NetworkDown, - else => |err| return windows.unexpectedWSAError(err), - } - } - - while (true) { - try t.checkCancel(); - const rc = ws2_32.listen(socket_handle, options.kernel_backlog); - if (rc != ws2_32.SOCKET_ERROR) break; - switch (ws2_32.WSAGetLastError()) { - .EINTR => continue, - .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => return error.Canceled, - .NOTINITIALISED => { - try initializeWsa(t); + &attr, + &io_status_block, + null, + .{ .NORMAL = true }, + .VALID_FLAGS, + .OPEN, + .{ + .IO = if (flags.follow_symlinks) .SYNCHRONOUS_NONALERT else .ASYNCHRONOUS, + .NON_DIRECTORY_FILE = !allow_directory, + .OPEN_REPARSE_POINT = !flags.follow_symlinks, + }, + null, + 0, + )) { + .SUCCESS => { + syscall.finish(); + break result; + }, + .OBJECT_NAME_INVALID => return syscall.fail(error.BadPathName), + .OBJECT_NAME_NOT_FOUND => return syscall.fail(error.FileNotFound), + .OBJECT_PATH_NOT_FOUND => return syscall.fail(error.FileNotFound), + .BAD_NETWORK_PATH => return syscall.fail(error.NetworkNotFound), // \\server was not found + .BAD_NETWORK_NAME => return syscall.fail(error.NetworkNotFound), // \\server was found but \\server\share wasn't + .NO_MEDIA_IN_DEVICE => return syscall.fail(error.NoDevice), + .INVALID_PARAMETER => |err| return syscall.ntstatusBug(err), + .CANCELLED => { + try syscall.checkCancel(); + continue; + }, + .SHARING_VIOLATION => { + // This occurs if the file attempting to be opened is a running + // executable. However, there's a kernel bug: the error may be + // incorrectly returned for an indeterminate amount of time + // after an executable file is closed. Here we work around the + // kernel bug with retry attempts. + syscall.finish(); + if (max_attempts - attempt == 0) return error.SharingViolation; + try parking_sleep.sleep(.{ .duration = .{ + .raw = .fromMilliseconds((@as(u32, 1) << attempt) >> 1), + .clock = .awake, + } }); + attempt += 1; + syscall = try .start(); + continue; + }, + .ACCESS_DENIED => return syscall.fail(error.AccessDenied), + .PIPE_BUSY => return syscall.fail(error.PipeBusy), + .PIPE_NOT_AVAILABLE => return syscall.fail(error.NoDevice), + .OBJECT_PATH_SYNTAX_BAD => |err| return syscall.ntstatusBug(err), + .OBJECT_NAME_COLLISION => return syscall.fail(error.PathAlreadyExists), + .FILE_IS_A_DIRECTORY => return syscall.fail(error.IsDir), + .NOT_A_DIRECTORY => return syscall.fail(error.NotDir), + .USER_MAPPED_FILE => return syscall.fail(error.AccessDenied), + .INVALID_HANDLE => |err| return syscall.ntstatusBug(err), + .DELETE_PENDING => { + // This error means that there *was* a file in this location on + // the file system, but it was deleted. However, the OS is not + // finished with the deletion operation, and so this CreateFile + // call has failed. Here, we simulate the kernel bug being + // fixed by sleeping and retrying until the error goes away. + syscall.finish(); + if (max_attempts - attempt == 0) return error.SharingViolation; + try parking_sleep.sleep(.{ .duration = .{ + .raw = .fromMilliseconds((@as(u32, 1) << attempt) >> 1), + .clock = .awake, + } }); + attempt += 1; + syscall = try .start(); continue; }, - .ENETDOWN => return error.NetworkDown, - .EADDRINUSE => return error.AddressInUse, - .EISCONN => |err| return wsaErrorBug(err), - .EINVAL => |err| return wsaErrorBug(err), - .EMFILE, .ENOBUFS => return error.SystemResources, - .ENOTSOCK => |err| return wsaErrorBug(err), - .EOPNOTSUPP => |err| return wsaErrorBug(err), - .EINPROGRESS => |err| return wsaErrorBug(err), - else => |err| return windows.unexpectedWSAError(err), + .VIRUS_INFECTED, .VIRUS_DELETED => return syscall.fail(error.AntivirusInterference), + else => |rc| return syscall.unexpectedNtstatus(rc), } - } - - try wsaGetSockName(t, socket_handle, &storage.any, &addr_len); - - return .{ - .socket = .{ - .handle = socket_handle, - .address = addressFromWsa(&storage), - }, }; -} + errdefer w.CloseHandle(handle); -fn netListenIpUnavailable( - userdata: ?*anyopaque, - address: IpAddress, - options: IpAddress.ListenOptions, -) IpAddress.ListenError!net.Server { - _ = userdata; - _ = address; - _ = options; - return error.NetworkDown; + const exclusive = switch (flags.lock) { + .none => return .{ .handle = handle }, + .shared => false, + .exclusive => true, + }; + syscall = try .start(); + while (true) switch (w.ntdll.NtLockFile( + handle, + null, + null, + null, + &io_status_block, + &windows_lock_range_off, + &windows_lock_range_len, + null, + @intFromBool(flags.lock_nonblocking), + @intFromBool(exclusive), + )) { + .SUCCESS => break syscall.finish(), + .INSUFFICIENT_RESOURCES => return syscall.fail(error.SystemResources), + .LOCK_NOT_GRANTED => return syscall.fail(error.WouldBlock), + .ACCESS_VIOLATION => |err| return syscall.ntstatusBug(err), // bad io_status_block pointer + else => |status| return syscall.unexpectedNtstatus(status), + }; + return .{ .handle = handle }; } -fn netListenUnixPosix( +fn dirOpenFileWasi( userdata: ?*anyopaque, - address: *const net.UnixAddress, - options: net.UnixAddress.ListenOptions, -) net.UnixAddress.ListenError!net.Socket.Handle { - if (!net.has_unix_sockets) return error.AddressFamilyUnsupported; + dir: Dir, + sub_path: []const u8, + flags: File.OpenFlags, +) File.OpenError!File { + if (builtin.link_libc) return dirOpenFilePosix(userdata, dir, sub_path, flags); const t: *Threaded = @ptrCast(@alignCast(userdata)); - const socket_fd = openSocketPosix(t, posix.AF.UNIX, .{ .mode = .stream }) catch |err| switch (err) { - error.ProtocolUnsupportedBySystem => return error.AddressFamilyUnsupported, - error.ProtocolUnsupportedByAddressFamily => return error.AddressFamilyUnsupported, - error.SocketModeUnsupported => return error.AddressFamilyUnsupported, - error.OptionUnsupported => return error.Unexpected, - else => |e| return e, - }; - errdefer posix.close(socket_fd); - - var storage: UnixAddress = undefined; - const addr_len = addressUnixToPosix(address, &storage); - try posixBindUnix(t, socket_fd, &storage.any, addr_len); - + const wasi = std.os.wasi; + var base: std.os.wasi.rights_t = .{}; + // POLL_FD_READWRITE only grants extra rights if the corresponding FD_READ and/or FD_WRITE + // is also set. + if (flags.isRead()) { + base.FD_READ = true; + base.FD_TELL = true; + base.FD_SEEK = true; + base.FD_FILESTAT_GET = true; + base.POLL_FD_READWRITE = true; + } + if (flags.isWrite()) { + base.FD_WRITE = true; + base.FD_TELL = true; + base.FD_SEEK = true; + base.FD_DATASYNC = true; + base.FD_FDSTAT_SET_FLAGS = true; + base.FD_SYNC = true; + base.FD_ALLOCATE = true; + base.FD_ADVISE = true; + base.FD_FILESTAT_SET_TIMES = true; + base.FD_FILESTAT_SET_SIZE = true; + base.POLL_FD_READWRITE = true; + } + const lookup_flags: wasi.lookupflags_t = .{}; + const oflags: wasi.oflags_t = .{}; + const inheriting: wasi.rights_t = .{}; + const fdflags: wasi.fdflags_t = .{}; + var fd: posix.fd_t = undefined; + const syscall: Syscall = try .start(); while (true) { - try t.checkCancel(); - switch (posix.errno(posix.system.listen(socket_fd, options.kernel_backlog))) { - .SUCCESS => break, - .ADDRINUSE => return error.AddressInUse, - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - else => |err| return posix.unexpectedErrno(err), + switch (wasi.path_open(dir.handle, lookup_flags, sub_path.ptr, sub_path.len, oflags, base, inheriting, fdflags, &fd)) { + .SUCCESS => { + syscall.finish(); + break; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .FAULT => |err| return errnoBug(err), + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .ACCES => return error.AccessDenied, + .FBIG => return error.FileTooBig, + .OVERFLOW => return error.FileTooBig, + .ISDIR => return error.IsDir, + .LOOP => return error.SymLinkLoop, + .MFILE => return error.ProcessFdQuotaExceeded, + .NFILE => return error.SystemFdQuotaExceeded, + .NODEV => return error.NoDevice, + .NOENT => return error.FileNotFound, + .NOMEM => return error.SystemResources, + .NOTDIR => return error.NotDir, + .PERM => return error.PermissionDenied, + .BUSY => return error.DeviceBusy, + .NOTCAPABLE => return error.AccessDenied, + .NAMETOOLONG => return error.NameTooLong, + .INVAL => return error.BadPathName, + .ILSEQ => return error.BadPathName, + else => |err| return posix.unexpectedErrno(err), + } + }, } } + errdefer posix.close(fd); + + if (!flags.allow_directory) { + const is_dir = is_dir: { + const stat = fileStat(t, .{ .handle = fd }) catch |err| switch (err) { + // The directory-ness is either unknown or unknowable + error.Streaming => break :is_dir false, + else => |e| return e, + }; + break :is_dir stat.kind == .directory; + }; + if (is_dir) return error.IsDir; + } - return socket_fd; + return .{ .handle = fd }; } -fn netListenUnixWindows( +const dirOpenDir = switch (native_os) { + .wasi => dirOpenDirWasi, + .haiku => dirOpenDirHaiku, + else => dirOpenDirPosix, +}; + +/// This function is also used for WASI when libc is linked. +fn dirOpenDirPosix( userdata: ?*anyopaque, - address: *const net.UnixAddress, - options: net.UnixAddress.ListenOptions, -) net.UnixAddress.ListenError!net.Socket.Handle { - if (!net.has_unix_sockets) return error.AddressFamilyUnsupported; + dir: Dir, + sub_path: []const u8, + options: Dir.OpenOptions, +) Dir.OpenError!Dir { const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; - const socket_handle = openSocketWsa(t, posix.AF.UNIX, .{ .mode = .stream }) catch |err| switch (err) { - error.ProtocolUnsupportedByAddressFamily => return error.AddressFamilyUnsupported, - else => |e| return e, + if (is_windows) { + const sub_path_w = try windows.sliceToPrefixedFileW(dir.handle, sub_path); + return dirOpenDirWindows(dir, sub_path_w.span(), options); + } + + var path_buffer: [posix.PATH_MAX]u8 = undefined; + const sub_path_posix = try pathToPosix(sub_path, &path_buffer); + + var flags: posix.O = switch (native_os) { + .wasi => .{ + .read = true, + .NOFOLLOW = !options.follow_symlinks, + .DIRECTORY = true, + }, + else => .{ + .ACCMODE = .RDONLY, + .NOFOLLOW = !options.follow_symlinks, + .DIRECTORY = true, + .CLOEXEC = true, + }, }; - errdefer closeSocketWindows(socket_handle); - var storage: WsaAddress = undefined; - const addr_len = addressUnixToWsa(address, &storage); + if (@hasField(posix.O, "PATH") and !options.iterate) + flags.PATH = true; - while (true) { - try t.checkCancel(); - const rc = ws2_32.bind(socket_handle, &storage.any, addr_len); - if (rc != ws2_32.SOCKET_ERROR) break; - switch (ws2_32.WSAGetLastError()) { - .EINTR => continue, - .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => return error.Canceled, - .NOTINITIALISED => { - try initializeWsa(t); - continue; - }, - .EADDRINUSE => return error.AddressInUse, - .EADDRNOTAVAIL => return error.AddressUnavailable, - .ENOTSOCK => |err| return wsaErrorBug(err), - .EFAULT => |err| return wsaErrorBug(err), - .EINVAL => |err| return wsaErrorBug(err), - .ENOBUFS => return error.SystemResources, - .ENETDOWN => return error.NetworkDown, - else => |err| return windows.unexpectedWSAError(err), - } - } + const mode: posix.mode_t = 0; + const syscall: Syscall = try .start(); while (true) { - try t.checkCancel(); - const rc = ws2_32.listen(socket_handle, options.kernel_backlog); - if (rc != ws2_32.SOCKET_ERROR) break; - switch (ws2_32.WSAGetLastError()) { - .EINTR => continue, - .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => return error.Canceled, - .NOTINITIALISED => { - try initializeWsa(t); + const rc = openat_sym(dir.handle, sub_path_posix, flags, mode); + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + return .{ .handle = @intCast(rc) }; + }, + .INTR => { + try syscall.checkCancel(); continue; }, - .ENETDOWN => return error.NetworkDown, - .EADDRINUSE => return error.AddressInUse, - .EISCONN => |err| return wsaErrorBug(err), - .EINVAL => |err| return wsaErrorBug(err), - .EMFILE, .ENOBUFS => return error.SystemResources, - .ENOTSOCK => |err| return wsaErrorBug(err), - .EOPNOTSUPP => |err| return wsaErrorBug(err), - .EINPROGRESS => |err| return wsaErrorBug(err), - else => |err| return windows.unexpectedWSAError(err), + else => |e| { + syscall.finish(); + switch (e) { + .FAULT => |err| return errnoBug(err), + .INVAL => return error.BadPathName, + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .ACCES => return error.AccessDenied, + .LOOP => return error.SymLinkLoop, + .MFILE => return error.ProcessFdQuotaExceeded, + .NAMETOOLONG => return error.NameTooLong, + .NFILE => return error.SystemFdQuotaExceeded, + .NODEV => return error.NoDevice, + .NOENT => return error.FileNotFound, + .NOMEM => return error.SystemResources, + .NOTDIR => return error.NotDir, + .PERM => return error.PermissionDenied, + .BUSY => |err| return errnoBug(err), // O_EXCL not passed + .NXIO => return error.NoDevice, + .ILSEQ => return error.BadPathName, + else => |err| return posix.unexpectedErrno(err), + } + }, } } - - return socket_handle; } -fn netListenUnixUnavailable( +fn dirOpenDirHaiku( userdata: ?*anyopaque, - address: *const net.UnixAddress, - options: net.UnixAddress.ListenOptions, -) net.UnixAddress.ListenError!net.Socket.Handle { - _ = userdata; - _ = address; - _ = options; - return error.AddressFamilyUnsupported; -} - -fn posixBindUnix(t: *Threaded, fd: posix.socket_t, addr: *const posix.sockaddr, addr_len: posix.socklen_t) !void { - while (true) { - try t.checkCancel(); - switch (posix.errno(posix.system.bind(fd, addr, addr_len))) { - .SUCCESS => break, - .INTR => continue, - .CANCELED => return error.Canceled, + dir: Dir, + sub_path: []const u8, + options: Dir.OpenOptions, +) Dir.OpenError!Dir { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; - .ACCES => return error.AccessDenied, - .ADDRINUSE => return error.AddressInUse, - .AFNOSUPPORT => return error.AddressFamilyUnsupported, - .ADDRNOTAVAIL => return error.AddressUnavailable, - .NOMEM => return error.SystemResources, + var path_buffer: [posix.PATH_MAX]u8 = undefined; + const sub_path_posix = try pathToPosix(sub_path, &path_buffer); - .LOOP => return error.SymLinkLoop, - .NOENT => return error.FileNotFound, - .NOTDIR => return error.NotDir, - .ROFS => return error.ReadOnlyFileSystem, - .PERM => return error.PermissionDenied, - - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .INVAL => |err| return errnoBug(err), // invalid parameters - .NOTSOCK => |err| return errnoBug(err), // invalid `sockfd` - .FAULT => |err| return errnoBug(err), // invalid `addr` pointer - .NAMETOOLONG => |err| return errnoBug(err), - else => |err| return posix.unexpectedErrno(err), - } - } -} + _ = options; -fn posixBind(t: *Threaded, socket_fd: posix.socket_t, addr: *const posix.sockaddr, addr_len: posix.socklen_t) !void { + const syscall: Syscall = try .start(); while (true) { - try t.checkCancel(); - switch (posix.errno(posix.system.bind(socket_fd, addr, addr_len))) { - .SUCCESS => break, - .INTR => continue, - .CANCELED => return error.Canceled, - - .ADDRINUSE => return error.AddressInUse, - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .INVAL => |err| return errnoBug(err), // invalid parameters - .NOTSOCK => |err| return errnoBug(err), // invalid `sockfd` - .AFNOSUPPORT => return error.AddressFamilyUnsupported, - .ADDRNOTAVAIL => return error.AddressUnavailable, - .FAULT => |err| return errnoBug(err), // invalid `addr` pointer - .NOMEM => return error.SystemResources, - else => |err| return posix.unexpectedErrno(err), + const rc = posix.system._kern_open_dir(dir.handle, sub_path_posix); + if (rc >= 0) { + syscall.finish(); + return .{ .handle = rc }; } - } -} - -fn posixConnect(t: *Threaded, socket_fd: posix.socket_t, addr: *const posix.sockaddr, addr_len: posix.socklen_t) !void { - while (true) { - try t.checkCancel(); - switch (posix.errno(posix.system.connect(socket_fd, addr, addr_len))) { - .SUCCESS => return, - .INTR => continue, - .CANCELED => return error.Canceled, - - .ADDRNOTAVAIL => return error.AddressUnavailable, - .AFNOSUPPORT => return error.AddressFamilyUnsupported, - .AGAIN, .INPROGRESS => return error.WouldBlock, - .ALREADY => return error.ConnectionPending, - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .CONNREFUSED => return error.ConnectionRefused, - .CONNRESET => return error.ConnectionResetByPeer, - .FAULT => |err| return errnoBug(err), - .ISCONN => |err| return errnoBug(err), - .HOSTUNREACH => return error.HostUnreachable, - .NETUNREACH => return error.NetworkUnreachable, - .NOTSOCK => |err| return errnoBug(err), - .PROTOTYPE => |err| return errnoBug(err), - .TIMEDOUT => return error.Timeout, - .CONNABORTED => |err| return errnoBug(err), - .ACCES => return error.AccessDenied, - .PERM => |err| return errnoBug(err), - .NOENT => |err| return errnoBug(err), - .NETDOWN => return error.NetworkDown, - else => |err| return posix.unexpectedErrno(err), + switch (@as(posix.E, @enumFromInt(rc))) { + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .FAULT => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .ACCES => return error.AccessDenied, + .LOOP => return error.SymLinkLoop, + .MFILE => return error.ProcessFdQuotaExceeded, + .NAMETOOLONG => return error.NameTooLong, + .NFILE => return error.SystemFdQuotaExceeded, + .NODEV => return error.NoDevice, + .NOENT => return error.FileNotFound, + .NOMEM => return error.SystemResources, + .NOTDIR => return error.NotDir, + .PERM => return error.PermissionDenied, + .BUSY => return error.DeviceBusy, + else => |err| return posix.unexpectedErrno(err), + } + }, } } } -fn posixConnectUnix(t: *Threaded, fd: posix.socket_t, addr: *const posix.sockaddr, addr_len: posix.socklen_t) !void { - while (true) { - try t.checkCancel(); - switch (posix.errno(posix.system.connect(fd, addr, addr_len))) { - .SUCCESS => return, - .INTR => continue, - .CANCELED => return error.Canceled, - - .AFNOSUPPORT => return error.AddressFamilyUnsupported, - .AGAIN => return error.WouldBlock, - .INPROGRESS => return error.WouldBlock, - .ACCES => return error.AccessDenied, - - .LOOP => return error.SymLinkLoop, - .NOENT => return error.FileNotFound, - .NOTDIR => return error.NotDir, - .ROFS => return error.ReadOnlyFileSystem, - .PERM => return error.PermissionDenied, - - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .CONNABORTED => |err| return errnoBug(err), - .FAULT => |err| return errnoBug(err), - .ISCONN => |err| return errnoBug(err), - .NOTSOCK => |err| return errnoBug(err), - .PROTOTYPE => |err| return errnoBug(err), - else => |err| return posix.unexpectedErrno(err), - } - } -} +pub fn dirOpenDirWindows( + dir: Dir, + sub_path_w: [:0]const u16, + options: Dir.OpenOptions, +) Dir.OpenError!Dir { + const w = windows; -fn posixGetSockName(t: *Threaded, socket_fd: posix.fd_t, addr: *posix.sockaddr, addr_len: *posix.socklen_t) !void { - while (true) { - try t.checkCancel(); - switch (posix.errno(posix.system.getsockname(socket_fd, addr, addr_len))) { - .SUCCESS => break, - .INTR => continue, - .CANCELED => return error.Canceled, - - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .FAULT => |err| return errnoBug(err), - .INVAL => |err| return errnoBug(err), // invalid parameters - .NOTSOCK => |err| return errnoBug(err), // always a race condition - .NOBUFS => return error.SystemResources, - else => |err| return posix.unexpectedErrno(err), - } - } -} + const path_len_bytes: u16 = @intCast(sub_path_w.len * 2); + var nt_name: w.UNICODE_STRING = .{ + .Length = path_len_bytes, + .MaximumLength = path_len_bytes, + .Buffer = @constCast(sub_path_w.ptr), + }; + var io_status_block: w.IO_STATUS_BLOCK = undefined; + var result: Dir = .{ .handle = undefined }; -fn wsaGetSockName(t: *Threaded, handle: ws2_32.SOCKET, addr: *ws2_32.sockaddr, addr_len: *i32) !void { - while (true) { - try t.checkCancel(); - const rc = ws2_32.getsockname(handle, addr, addr_len); - if (rc != ws2_32.SOCKET_ERROR) break; - switch (ws2_32.WSAGetLastError()) { - .EINTR => continue, - .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => return error.Canceled, - .NOTINITIALISED => { - try initializeWsa(t); - continue; + const syscall: Syscall = try .start(); + while (true) switch (w.ntdll.NtCreateFile( + &result.handle, + // TODO remove some of these flags if options.access_sub_paths is false + .{ + .SPECIFIC = .{ .FILE_DIRECTORY = .{ + .LIST = options.iterate, + .READ_EA = true, + .TRAVERSE = true, + .READ_ATTRIBUTES = true, + } }, + .STANDARD = .{ + .RIGHTS = .READ, + .SYNCHRONIZE = true, }, - .ENETDOWN => return error.NetworkDown, - .EFAULT => |err| return wsaErrorBug(err), - .ENOTSOCK => |err| return wsaErrorBug(err), - .EINVAL => |err| return wsaErrorBug(err), - else => |err| return windows.unexpectedWSAError(err), - } - } + }, + &.{ + .Length = @sizeOf(w.OBJECT_ATTRIBUTES), + .RootDirectory = if (Dir.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir.handle, + .Attributes = .{}, + .ObjectName = &nt_name, + .SecurityDescriptor = null, + .SecurityQualityOfService = null, + }, + &io_status_block, + null, + .{ .NORMAL = true }, + .VALID_FLAGS, + .OPEN, + .{ + .DIRECTORY_FILE = true, + .IO = .SYNCHRONOUS_NONALERT, + .OPEN_FOR_BACKUP_INTENT = true, + .OPEN_REPARSE_POINT = !options.follow_symlinks, + }, + null, + 0, + )) { + .SUCCESS => { + syscall.finish(); + return result; + }, + .CANCELLED => { + try syscall.checkCancel(); + continue; + }, + .OBJECT_NAME_INVALID => return syscall.fail(error.BadPathName), + .OBJECT_NAME_NOT_FOUND => return syscall.fail(error.FileNotFound), + .OBJECT_NAME_COLLISION => |err| return w.statusBug(err), + .OBJECT_PATH_NOT_FOUND => return syscall.fail(error.FileNotFound), + .NOT_A_DIRECTORY => return syscall.fail(error.NotDir), + // This can happen if the directory has 'List folder contents' permission set to 'Deny' + // and the directory is trying to be opened for iteration. + .ACCESS_DENIED => return syscall.fail(error.AccessDenied), + .INVALID_PARAMETER => |err| return syscall.ntstatusBug(err), + else => |rc| return syscall.unexpectedNtstatus(rc), + }; } -fn setSocketOption(t: *Threaded, fd: posix.fd_t, level: i32, opt_name: u32, option: u32) !void { - const o: []const u8 = @ptrCast(&option); - while (true) { - try t.checkCancel(); - switch (posix.errno(posix.system.setsockopt(fd, level, opt_name, o.ptr, @intCast(o.len)))) { - .SUCCESS => return, - .INTR => continue, - .CANCELED => return error.Canceled, +fn dirClose(userdata: ?*anyopaque, dirs: []const Dir) void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + for (dirs) |dir| posix.close(dir.handle); +} + +const dirRead = switch (native_os) { + .linux => dirReadLinux, + .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => dirReadDarwin, + .freebsd, .netbsd, .dragonfly, .openbsd => dirReadBsd, + .illumos => dirReadIllumos, + .haiku => dirReadHaiku, + .windows => dirReadWindows, + .wasi => dirReadWasi, + else => dirReadUnimplemented, +}; - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .NOTSOCK => |err| return errnoBug(err), - .INVAL => |err| return errnoBug(err), - .FAULT => |err| return errnoBug(err), - else => |err| return posix.unexpectedErrno(err), +fn dirReadLinux(userdata: ?*anyopaque, dr: *Dir.Reader, buffer: []Dir.Entry) Dir.Reader.Error!usize { + const linux = std.os.linux; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + var buffer_index: usize = 0; + while (buffer.len - buffer_index != 0) { + if (dr.end - dr.index == 0) { + // Refill the buffer, unless we've already created references to + // buffered data. + if (buffer_index != 0) break; + if (dr.state == .reset) { + posixSeekTo(dr.dir.handle, 0) catch |err| switch (err) { + error.Unseekable => return error.Unexpected, + else => |e| return e, + }; + dr.state = .reading; + } + const syscall: Syscall = try .start(); + const n = while (true) { + const rc = linux.getdents64(dr.dir.handle, dr.buffer.ptr, dr.buffer.len); + switch (linux.errno(rc)) { + .SUCCESS => { + syscall.finish(); + break rc; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .BADF => |err| return errnoBug(err), // Dir is invalid or was opened without iteration ability. + .FAULT => |err| return errnoBug(err), + .NOTDIR => |err| return errnoBug(err), + // To be consistent across platforms, iteration + // ends if the directory being iterated is deleted + // during iteration. This matches the behavior of + // non-Linux, non-WASI UNIX platforms. + .NOENT => { + dr.state = .finished; + return 0; + }, + // This can occur when reading /proc/$PID/net, or + // if the provided buffer is too small. Neither + // scenario is intended to be handled by this API. + .INVAL => return error.Unexpected, + .ACCES => return error.AccessDenied, // Lacking permission to iterate this directory. + else => |err| return posix.unexpectedErrno(err), + } + }, + } + }; + if (n == 0) { + dr.state = .finished; + return 0; + } + dr.index = 0; + dr.end = n; } + // Linux aligns the header by padding after the null byte of the name + // to align the next entry. This means we can find the end of the name + // by looking at only the 8 bytes before the next record. However since + // file names are usually short it's better to keep the machine code + // simpler. + // + // Furthermore, I observed qemu user mode to not align this struct, so + // this code makes the conservative choice to not assume alignment. + const linux_entry: *align(1) linux.dirent64 = @ptrCast(&dr.buffer[dr.index]); + const next_index = dr.index + linux_entry.reclen; + dr.index = next_index; + const name_ptr: [*]u8 = &linux_entry.name; + const padded_name = name_ptr[0 .. linux_entry.reclen - @offsetOf(linux.dirent64, "name")]; + const name_len = std.mem.findScalar(u8, padded_name, 0).?; + const name = name_ptr[0..name_len :0]; + + if (std.mem.eql(u8, name, ".") or std.mem.eql(u8, name, "..")) continue; + + const entry_kind: File.Kind = switch (linux_entry.type) { + linux.DT.BLK => .block_device, + linux.DT.CHR => .character_device, + linux.DT.DIR => .directory, + linux.DT.FIFO => .named_pipe, + linux.DT.LNK => .sym_link, + linux.DT.REG => .file, + linux.DT.SOCK => .unix_domain_socket, + else => .unknown, + }; + buffer[buffer_index] = .{ + .name = name, + .kind = entry_kind, + .inode = linux_entry.ino, + }; + buffer_index += 1; } + return buffer_index; } -fn setSocketOptionWsa(t: *Threaded, socket: Io.net.Socket.Handle, level: i32, opt_name: u32, option: u32) !void { - const o: []const u8 = @ptrCast(&option); - const rc = ws2_32.setsockopt(socket, level, @bitCast(opt_name), o.ptr, @intCast(o.len)); - while (true) { - if (rc != ws2_32.SOCKET_ERROR) return; - switch (ws2_32.WSAGetLastError()) { - .EINTR => continue, - .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => return error.Canceled, - .NOTINITIALISED => { - try initializeWsa(t); - continue; - }, - .ENETDOWN => return error.NetworkDown, - .EFAULT => |err| return wsaErrorBug(err), - .ENOTSOCK => |err| return wsaErrorBug(err), - .EINVAL => |err| return wsaErrorBug(err), - else => |err| return windows.unexpectedWSAError(err), +fn dirReadDarwin(userdata: ?*anyopaque, dr: *Dir.Reader, buffer: []Dir.Entry) Dir.Reader.Error!usize { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + const Header = extern struct { + seek: i64, + }; + const header: *Header = @ptrCast(dr.buffer.ptr); + const header_end: usize = @sizeOf(Header); + if (dr.index < header_end) { + // Initialize header. + dr.index = header_end; + dr.end = header_end; + header.* = .{ .seek = 0 }; + } + var buffer_index: usize = 0; + while (buffer.len - buffer_index != 0) { + if (dr.end - dr.index == 0) { + // Refill the buffer, unless we've already created references to + // buffered data. + if (buffer_index != 0) break; + if (dr.state == .reset) { + posixSeekTo(dr.dir.handle, 0) catch |err| switch (err) { + error.Unseekable => return error.Unexpected, + else => |e| return e, + }; + dr.state = .reading; + } + const dents_buffer = dr.buffer[header_end..]; + const syscall: Syscall = try .start(); + const n: usize = while (true) { + const rc = posix.system.getdirentries(dr.dir.handle, dents_buffer.ptr, dents_buffer.len, &header.seek); + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + break @intCast(rc); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .BADF => |err| return errnoBug(err), // Dir is invalid or was opened without iteration ability. + .FAULT => |err| return errnoBug(err), + .NOTDIR => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), + else => |err| return posix.unexpectedErrno(err), + } + }, + } + }; + if (n == 0) { + dr.state = .finished; + return 0; + } + dr.index = header_end; + dr.end = header_end + n; } + const darwin_entry = @as(*align(1) posix.system.dirent, @ptrCast(&dr.buffer[dr.index])); + const next_index = dr.index + darwin_entry.reclen; + dr.index = next_index; + + const name = @as([*]u8, @ptrCast(&darwin_entry.name))[0..darwin_entry.namlen]; + if (std.mem.eql(u8, name, ".") or std.mem.eql(u8, name, "..") or (darwin_entry.ino == 0)) + continue; + + const entry_kind: File.Kind = switch (darwin_entry.type) { + posix.DT.BLK => .block_device, + posix.DT.CHR => .character_device, + posix.DT.DIR => .directory, + posix.DT.FIFO => .named_pipe, + posix.DT.LNK => .sym_link, + posix.DT.REG => .file, + posix.DT.SOCK => .unix_domain_socket, + posix.DT.WHT => .whiteout, + else => .unknown, + }; + buffer[buffer_index] = .{ + .name = name, + .kind = entry_kind, + .inode = darwin_entry.ino, + }; + buffer_index += 1; } + return buffer_index; } -fn netConnectIpPosix( - userdata: ?*anyopaque, - address: *const IpAddress, - options: IpAddress.ConnectOptions, -) IpAddress.ConnectError!net.Stream { - if (!have_networking) return error.NetworkDown; - if (options.timeout != .none) @panic("TODO implement netConnectIpPosix with timeout"); +fn dirReadBsd(userdata: ?*anyopaque, dr: *Dir.Reader, buffer: []Dir.Entry) Dir.Reader.Error!usize { const t: *Threaded = @ptrCast(@alignCast(userdata)); - const family = posixAddressFamily(address); - const socket_fd = try openSocketPosix(t, family, .{ - .mode = options.mode, - .protocol = options.protocol, - }); - errdefer posix.close(socket_fd); - var storage: PosixAddress = undefined; - var addr_len = addressToPosix(address, &storage); - try posixConnect(t, socket_fd, &storage.any, addr_len); - try posixGetSockName(t, socket_fd, &storage.any, &addr_len); - return .{ .socket = .{ - .handle = socket_fd, - .address = addressFromPosix(&storage), - } }; -} + _ = t; + var buffer_index: usize = 0; + while (buffer.len - buffer_index != 0) { + if (dr.end - dr.index == 0) { + // Refill the buffer, unless we've already created references to + // buffered data. + if (buffer_index != 0) break; + if (dr.state == .reset) { + posixSeekTo(dr.dir.handle, 0) catch |err| switch (err) { + error.Unseekable => return error.Unexpected, + else => |e| return e, + }; + dr.state = .reading; + } + const syscall: Syscall = try .start(); + const n: usize = while (true) { + const rc = posix.system.getdents(dr.dir.handle, dr.buffer.ptr, dr.buffer.len); + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + break @intCast(rc); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .BADF => |err| return errnoBug(err), // Dir is invalid or was opened without iteration ability + .FAULT => |err| return errnoBug(err), + .NOTDIR => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), + // Introduced in freebsd 13.2: directory unlinked + // but still open. To be consistent, iteration ends + // if the directory being iterated is deleted + // during iteration. + .NOENT => { + dr.state = .finished; + return 0; + }, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + }; + if (n == 0) { + dr.state = .finished; + return 0; + } + dr.index = 0; + dr.end = n; + } + const bsd_entry = @as(*align(1) posix.system.dirent, @ptrCast(&dr.buffer[dr.index])); + const next_index = dr.index + + if (@hasField(posix.system.dirent, "reclen")) bsd_entry.reclen else bsd_entry.reclen(); + dr.index = next_index; -fn netConnectIpWindows( - userdata: ?*anyopaque, - address: *const IpAddress, - options: IpAddress.ConnectOptions, -) IpAddress.ConnectError!net.Stream { - if (!have_networking) return error.NetworkDown; - if (options.timeout != .none) @panic("TODO implement netConnectIpWindows with timeout"); - const t: *Threaded = @ptrCast(@alignCast(userdata)); - const family = posixAddressFamily(address); - const socket_handle = try openSocketWsa(t, family, .{ - .mode = options.mode, - .protocol = options.protocol, - }); - errdefer closeSocketWindows(socket_handle); + const name = @as([*]u8, @ptrCast(&bsd_entry.name))[0..bsd_entry.namlen]; - var storage: WsaAddress = undefined; - var addr_len = addressToWsa(address, &storage); + const skip_zero_fileno = switch (native_os) { + // fileno=0 is used to mark invalid entries or deleted files. + .openbsd, .netbsd => true, + else => false, + }; + if (std.mem.eql(u8, name, ".") or std.mem.eql(u8, name, "..") or + (skip_zero_fileno and bsd_entry.fileno == 0)) + { + continue; + } - while (true) { - const rc = ws2_32.connect(socket_handle, &storage.any, addr_len); - if (rc != ws2_32.SOCKET_ERROR) break; - switch (ws2_32.WSAGetLastError()) { - .EINTR => continue, - .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => return error.Canceled, - .NOTINITIALISED => { - try initializeWsa(t); - continue; - }, + const entry_kind: File.Kind = switch (bsd_entry.type) { + posix.DT.BLK => .block_device, + posix.DT.CHR => .character_device, + posix.DT.DIR => .directory, + posix.DT.FIFO => .named_pipe, + posix.DT.LNK => .sym_link, + posix.DT.REG => .file, + posix.DT.SOCK => .unix_domain_socket, + posix.DT.WHT => .whiteout, + else => .unknown, + }; + buffer[buffer_index] = .{ + .name = name, + .kind = entry_kind, + .inode = bsd_entry.fileno, + }; + buffer_index += 1; + } + return buffer_index; +} - .EADDRNOTAVAIL => return error.AddressUnavailable, - .ECONNREFUSED => return error.ConnectionRefused, - .ECONNRESET => return error.ConnectionResetByPeer, - .ETIMEDOUT => return error.Timeout, - .EHOSTUNREACH => return error.HostUnreachable, - .ENETUNREACH => return error.NetworkUnreachable, - .EFAULT => |err| return wsaErrorBug(err), - .EINVAL => |err| return wsaErrorBug(err), - .EISCONN => |err| return wsaErrorBug(err), - .ENOTSOCK => |err| return wsaErrorBug(err), - .EWOULDBLOCK => return error.WouldBlock, - .EACCES => return error.AccessDenied, - .ENOBUFS => return error.SystemResources, - .EAFNOSUPPORT => return error.AddressFamilyUnsupported, - else => |err| return windows.unexpectedWSAError(err), +fn dirReadIllumos(userdata: ?*anyopaque, dr: *Dir.Reader, buffer: []Dir.Entry) Dir.Reader.Error!usize { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + var buffer_index: usize = 0; + while (buffer.len - buffer_index != 0) { + if (dr.end - dr.index == 0) { + // Refill the buffer, unless we've already created references to + // buffered data. + if (buffer_index != 0) break; + if (dr.state == .reset) { + posixSeekTo(dr.dir.handle, 0) catch |err| switch (err) { + error.Unseekable => return error.Unexpected, + else => |e| return e, + }; + dr.state = .reading; + } + const syscall: Syscall = try .start(); + const n: usize = while (true) { + const rc = posix.system.getdents(dr.dir.handle, dr.buffer.ptr, dr.buffer.len); + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + break rc; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .BADF => |err| return errnoBug(err), // Dir is invalid or was opened without iteration ability + .FAULT => |err| return errnoBug(err), + .NOTDIR => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), + else => |err| return posix.unexpectedErrno(err), + } + }, + } + }; + if (n == 0) { + dr.state = .finished; + return 0; + } + dr.index = 0; + dr.end = n; } - } + const entry = @as(*align(1) posix.system.dirent, @ptrCast(&dr.buffer[dr.index])); + const next_index = dr.index + entry.reclen; + dr.index = next_index; - try wsaGetSockName(t, socket_handle, &storage.any, &addr_len); + const name = std.mem.sliceTo(@as([*:0]u8, @ptrCast(&entry.name)), 0); + if (std.mem.eql(u8, name, ".") or std.mem.eql(u8, name, "..")) continue; - return .{ .socket = .{ - .handle = socket_handle, - .address = addressFromWsa(&storage), - } }; + // illumos dirent doesn't expose type, so we have to call stat to get it. + const stat = try posixStatFile(dr.dir.handle, name, posix.AT.SYMLINK_NOFOLLOW); + + buffer[buffer_index] = .{ + .name = name, + .kind = stat.kind, + .inode = entry.ino, + }; + buffer_index += 1; + } + return buffer_index; } -fn netConnectIpUnavailable( - userdata: ?*anyopaque, - address: *const IpAddress, - options: IpAddress.ConnectOptions, -) IpAddress.ConnectError!net.Stream { +fn dirReadHaiku(userdata: ?*anyopaque, dr: *Dir.Reader, buffer: []Dir.Entry) Dir.Reader.Error!usize { _ = userdata; - _ = address; - _ = options; - return error.NetworkDown; + _ = dr; + _ = buffer; + @panic("TODO implement dirReadHaiku"); } -fn netConnectUnixPosix( - userdata: ?*anyopaque, - address: *const net.UnixAddress, -) net.UnixAddress.ConnectError!net.Socket.Handle { - if (!net.has_unix_sockets) return error.AddressFamilyUnsupported; +fn dirReadWindows(userdata: ?*anyopaque, dr: *Dir.Reader, buffer: []Dir.Entry) Dir.Reader.Error!usize { const t: *Threaded = @ptrCast(@alignCast(userdata)); - const socket_fd = openSocketPosix(t, posix.AF.UNIX, .{ .mode = .stream }) catch |err| switch (err) { - error.OptionUnsupported => return error.Unexpected, - else => |e| return e, - }; - errdefer posix.close(socket_fd); - var storage: UnixAddress = undefined; - const addr_len = addressUnixToPosix(address, &storage); - try posixConnectUnix(t, socket_fd, &storage.any, addr_len); - return socket_fd; -} + _ = t; + const w = windows; -fn netConnectUnixWindows( - userdata: ?*anyopaque, - address: *const net.UnixAddress, -) net.UnixAddress.ConnectError!net.Socket.Handle { - if (!net.has_unix_sockets) return error.AddressFamilyUnsupported; - const t: *Threaded = @ptrCast(@alignCast(userdata)); + // We want to be able to use the `dr.buffer` for both the NtQueryDirectoryFile call (which + // returns WTF-16 names) *and* as a buffer for storing those WTF-16 names as WTF-8 to be able + // to return them in `Dir.Entry.name`. However, the problem that needs to be overcome in order to do + // that is that each WTF-16 code unit can be encoded as a maximum of 3 WTF-8 bytes, which means + // that it's not guaranteed that the memory used for the WTF-16 name will be sufficient + // for the WTF-8 encoding of the same name (for example, € is encoded as one WTF-16 code unit, + // [2 bytes] but encoded in WTF-8 as 3 bytes). + // + // The approach taken here is to "reserve" enough space in the `dr.buffer` to ensure that + // at least one entry with the maximum possible WTF-8 name length can be stored without clobbering + // any entries that follow it. That is, we determine how much space is needed to allow that, + // and then only provide the remaining portion of `dr.buffer` to the NtQueryDirectoryFile + // call. The WTF-16 names can then be safely converted using the full `dr.buffer` slice, making + // sure that each name can only potentially overwrite the data of its own entry. + // + // The worst case, where an entry's name is both the maximum length of a component and + // made up entirely of code points that are encoded as one WTF-16 code unit/three WTF-8 bytes, + // would therefore look like the diagram below, and only one entry would be able to be returned: + // + // | reserved | remaining unreserved buffer | + // | entry 1 | entry 2 | ... | + // | wtf-8 name of entry 1 | + // + // However, in the average case we will be able to store more than one WTF-8 name at a time in the + // available buffer and therefore we will be able to populate more than one `Dir.Entry` at a time. + // That might look something like this (where name 1, name 2, etc are the converted WTF-8 names): + // + // | reserved | remaining unreserved buffer | + // | entry 1 | entry 2 | ... | + // | name 1 | name 2 | name 3 | name 4 | ... | + // + // Note: More than the minimum amount of space could be reserved to make the "worst case" + // less likely, but since the worst-case also requires a maximum length component to matter, + // it's unlikely for it to become a problem in normal scenarios even if all names on the filesystem + // are made up of non-ASCII characters that have the "one WTF-16 code unit <-> three WTF-8 bytes" + // property (e.g. code points >= U+0800 and <= U+FFFF), as it's unlikely for a significant + // number of components to be maximum length. + + // We need `3 * NAME_MAX` bytes to store a max-length component as WTF-8 safely. + // Because needing to store a max-length component depends on a `FileName` *with* the maximum + // component length, we know that the corresponding populated `FILE_BOTH_DIR_INFORMATION` will + // be of size `@sizeOf(w.FILE_BOTH_DIR_INFORMATION) + 2 * NAME_MAX` bytes, so we only need to + // reserve enough to get us to up to having `3 * NAME_MAX` bytes available when taking into account + // that we have the ability to write over top of the reserved memory + the full footprint of that + // particular `FILE_BOTH_DIR_INFORMATION`. + const max_info_len = @sizeOf(w.FILE_BOTH_DIR_INFORMATION) + w.NAME_MAX * 2; + const info_align = @alignOf(w.FILE_BOTH_DIR_INFORMATION); + const reserve_needed = std.mem.alignForward(usize, Dir.max_name_bytes, info_align) - max_info_len; + const unreserved_start = std.mem.alignForward(usize, reserve_needed, info_align); + const unreserved_buffer = dr.buffer[unreserved_start..]; + // This is enforced by `Dir.Reader` + assert(unreserved_buffer.len >= max_info_len); + + var name_index: usize = 0; + var buffer_index: usize = 0; + while (buffer.len - buffer_index != 0) { + if (dr.end - dr.index == 0) { + // Refill the buffer, unless we've already created references to + // buffered data. + if (buffer_index != 0) break; + + var io_status_block: w.IO_STATUS_BLOCK = undefined; + const syscall: Syscall = try .start(); + const rc = while (true) switch (w.ntdll.NtQueryDirectoryFile( + dr.dir.handle, + null, + null, + null, + &io_status_block, + unreserved_buffer.ptr, + std.math.lossyCast(w.ULONG, unreserved_buffer.len), + .BothDirectory, + w.FALSE, + null, + @intFromBool(dr.state == .reset), + )) { + .CANCELLED => { + try syscall.checkCancel(); + continue; + }, + else => |rc| { + syscall.finish(); + break rc; + }, + }; + dr.state = .reading; + if (io_status_block.Information == 0) { + dr.state = .finished; + return 0; + } + dr.index = 0; + dr.end = io_status_block.Information; + switch (rc) { + .SUCCESS => {}, + .ACCESS_DENIED => return error.AccessDenied, // Double-check that the Dir was opened with iteration ability + else => return w.unexpectedStatus(rc), + } + } - const socket_handle = try openSocketWsa(t, posix.AF.UNIX, .{ .mode = .stream }); - errdefer closeSocketWindows(socket_handle); - var storage: WsaAddress = undefined; - const addr_len = addressUnixToWsa(address, &storage); + // While the official API docs guarantee FILE_BOTH_DIR_INFORMATION to be aligned properly + // this may not always be the case (e.g. due to faulty VM/sandboxing tools) + const dir_info: *align(2) w.FILE_BOTH_DIR_INFORMATION = @ptrCast(@alignCast(&unreserved_buffer[dr.index])); + const backtrack_index = dr.index; + if (dir_info.NextEntryOffset != 0) { + dr.index += dir_info.NextEntryOffset; + } else { + dr.index = dr.end; + } - while (true) { - const rc = ws2_32.connect(socket_handle, &storage.any, addr_len); - if (rc != ws2_32.SOCKET_ERROR) break; - switch (ws2_32.WSAGetLastError()) { - .EINTR => continue, - .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => return error.Canceled, - .NOTINITIALISED => { - try initializeWsa(t); - continue; - }, + const name_wtf16le = @as([*]u16, @ptrCast(&dir_info.FileName))[0 .. dir_info.FileNameLength / 2]; - .ECONNREFUSED => return error.FileNotFound, - .EFAULT => |err| return wsaErrorBug(err), - .EINVAL => |err| return wsaErrorBug(err), - .EISCONN => |err| return wsaErrorBug(err), - .ENOTSOCK => |err| return wsaErrorBug(err), - .EWOULDBLOCK => return error.WouldBlock, - .EACCES => return error.AccessDenied, - .ENOBUFS => return error.SystemResources, - .EAFNOSUPPORT => return error.AddressFamilyUnsupported, - else => |err| return windows.unexpectedWSAError(err), + if (std.mem.eql(u16, name_wtf16le, &[_]u16{'.'}) or std.mem.eql(u16, name_wtf16le, &[_]u16{ '.', '.' })) { + continue; + } + + // Read any relevant information from the `dir_info` now since it's possible the WTF-8 + // name will overwrite it. + const kind: File.Kind = blk: { + const attrs = dir_info.FileAttributes; + if (attrs.REPARSE_POINT) break :blk .sym_link; + if (attrs.DIRECTORY) break :blk .directory; + break :blk .file; + }; + const inode: File.INode = dir_info.FileIndex; + + // If there's no more space for WTF-8 names without bleeding over into + // the remaining unprocessed entries, then backtrack and return what we have so far. + if (name_index + std.unicode.calcWtf8Len(name_wtf16le) > unreserved_start + dr.index) { + // We should always be able to fit at least one entry into the buffer no matter what + assert(buffer_index != 0); + dr.index = backtrack_index; + break; } + + const name_buf = dr.buffer[name_index..]; + const name_wtf8_len = std.unicode.wtf16LeToWtf8(name_buf, name_wtf16le); + const name_wtf8 = name_buf[0..name_wtf8_len]; + name_index += name_wtf8_len; + + buffer[buffer_index] = .{ + .name = name_wtf8, + .kind = kind, + .inode = inode, + }; + buffer_index += 1; } - return socket_handle; + return buffer_index; } -fn netConnectUnixUnavailable( - userdata: ?*anyopaque, - address: *const net.UnixAddress, -) net.UnixAddress.ConnectError!net.Socket.Handle { - _ = userdata; - _ = address; - return error.AddressFamilyUnsupported; -} - -fn netBindIpPosix( - userdata: ?*anyopaque, - address: *const IpAddress, - options: IpAddress.BindOptions, -) IpAddress.BindError!net.Socket { - if (!have_networking) return error.NetworkDown; +fn dirReadWasi(userdata: ?*anyopaque, dr: *Dir.Reader, buffer: []Dir.Entry) Dir.Reader.Error!usize { + // We intentinally use fd_readdir even when linked with libc, since its + // implementation is exactly the same as below, and we avoid the code + // complexity here. + const wasi = std.os.wasi; const t: *Threaded = @ptrCast(@alignCast(userdata)); - const family = posixAddressFamily(address); - const socket_fd = try openSocketPosix(t, family, options); - errdefer posix.close(socket_fd); - var storage: PosixAddress = undefined; - var addr_len = addressToPosix(address, &storage); - try posixBind(t, socket_fd, &storage.any, addr_len); - try posixGetSockName(t, socket_fd, &storage.any, &addr_len); - return .{ - .handle = socket_fd, - .address = addressFromPosix(&storage), + _ = t; + const Header = extern struct { + cookie: u64, }; -} - -fn netBindIpWindows( - userdata: ?*anyopaque, - address: *const IpAddress, - options: IpAddress.BindOptions, -) IpAddress.BindError!net.Socket { - if (!have_networking) return error.NetworkDown; - const t: *Threaded = @ptrCast(@alignCast(userdata)); - const family = posixAddressFamily(address); - const socket_handle = try openSocketWsa(t, family, .{ - .mode = options.mode, - .protocol = options.protocol, - }); - errdefer closeSocketWindows(socket_handle); - - var storage: WsaAddress = undefined; - var addr_len = addressToWsa(address, &storage); - - while (true) { - try t.checkCancel(); - const rc = ws2_32.bind(socket_handle, &storage.any, addr_len); - if (rc != ws2_32.SOCKET_ERROR) break; - switch (ws2_32.WSAGetLastError()) { - .EINTR => continue, - .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => return error.Canceled, - .NOTINITIALISED => { - try initializeWsa(t); - continue; - }, - .EADDRINUSE => return error.AddressInUse, - .EADDRNOTAVAIL => return error.AddressUnavailable, - .ENOTSOCK => |err| return wsaErrorBug(err), - .EFAULT => |err| return wsaErrorBug(err), - .EINVAL => |err| return wsaErrorBug(err), - .ENOBUFS => return error.SystemResources, - .ENETDOWN => return error.NetworkDown, - else => |err| return windows.unexpectedWSAError(err), + const header: *align(@alignOf(usize)) Header = @ptrCast(dr.buffer.ptr); + const header_end: usize = @sizeOf(Header); + if (dr.index < header_end) { + // Initialize header. + dr.index = header_end; + dr.end = header_end; + header.* = .{ .cookie = wasi.DIRCOOKIE_START }; + } + var buffer_index: usize = 0; + while (buffer.len - buffer_index != 0) { + // According to the WASI spec, the last entry might be truncated, so we + // need to check if the remaining buffer contains the whole dirent. + if (dr.end - dr.index < @sizeOf(wasi.dirent_t)) { + // Refill the buffer, unless we've already created references to + // buffered data. + if (buffer_index != 0) break; + if (dr.state == .reset) { + header.* = .{ .cookie = wasi.DIRCOOKIE_START }; + dr.state = .reading; + } + const dents_buffer = dr.buffer[header_end..]; + var n: usize = undefined; + const syscall: Syscall = try .start(); + while (true) { + switch (wasi.fd_readdir(dr.dir.handle, dents_buffer.ptr, dents_buffer.len, header.cookie, &n)) { + .SUCCESS => { + syscall.finish(); + break; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .BADF => |err| return errnoBug(err), // Dir is invalid or was opened without iteration ability. + .FAULT => |err| return errnoBug(err), + .NOTDIR => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), + // To be consistent across platforms, iteration + // ends if the directory being iterated is deleted + // during iteration. This matches the behavior of + // non-Linux, non-WASI UNIX platforms. + .NOENT => { + dr.state = .finished; + return 0; + }, + .NOTCAPABLE => return error.AccessDenied, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } + if (n == 0) { + dr.state = .finished; + return 0; + } + dr.index = header_end; + dr.end = header_end + n; } - } + const entry: *align(1) wasi.dirent_t = @ptrCast(&dr.buffer[dr.index]); + const entry_size = @sizeOf(wasi.dirent_t); + const name_index = dr.index + entry_size; + if (name_index + entry.namlen > dr.end) { + // This case, the name is truncated, so we need to call readdir to store the entire name. + dr.end = dr.index; // Force fd_readdir in the next loop. + continue; + } + const name = dr.buffer[name_index..][0..entry.namlen]; + const next_index = name_index + entry.namlen; + dr.index = next_index; + header.cookie = entry.next; - try wsaGetSockName(t, socket_handle, &storage.any, &addr_len); + if (std.mem.eql(u8, name, ".") or std.mem.eql(u8, name, "..")) + continue; - return .{ - .handle = socket_handle, - .address = addressFromWsa(&storage), - }; + const entry_kind: File.Kind = switch (entry.type) { + .BLOCK_DEVICE => .block_device, + .CHARACTER_DEVICE => .character_device, + .DIRECTORY => .directory, + .SYMBOLIC_LINK => .sym_link, + .REGULAR_FILE => .file, + .SOCKET_STREAM, .SOCKET_DGRAM => .unix_domain_socket, + else => .unknown, + }; + buffer[buffer_index] = .{ + .name = name, + .kind = entry_kind, + .inode = entry.ino, + }; + buffer_index += 1; + } + return buffer_index; } -fn netBindIpUnavailable( - userdata: ?*anyopaque, - address: *const IpAddress, - options: IpAddress.BindOptions, -) IpAddress.BindError!net.Socket { +fn dirReadUnimplemented(userdata: ?*anyopaque, dir_reader: *Dir.Reader, buffer: []Dir.Entry) Dir.Reader.Error!usize { _ = userdata; - _ = address; - _ = options; - return error.NetworkDown; + _ = dir_reader; + _ = buffer; + return error.Unimplemented; } -fn openSocketPosix( - t: *Threaded, - family: posix.sa_family_t, - options: IpAddress.BindOptions, -) error{ - AddressFamilyUnsupported, - ProtocolUnsupportedBySystem, - ProcessFdQuotaExceeded, - SystemFdQuotaExceeded, - SystemResources, - ProtocolUnsupportedByAddressFamily, - SocketModeUnsupported, - OptionUnsupported, - Unexpected, - Canceled, -}!posix.socket_t { - const mode = posixSocketMode(options.mode); - const protocol = posixProtocol(options.protocol); - const socket_fd = while (true) { - try t.checkCancel(); - const flags: u32 = mode | if (socket_flags_unsupported) 0 else posix.SOCK.CLOEXEC; - const socket_rc = posix.system.socket(family, flags, protocol); - switch (posix.errno(socket_rc)) { - .SUCCESS => { - const fd: posix.fd_t = @intCast(socket_rc); - errdefer posix.close(fd); - if (socket_flags_unsupported) while (true) { - try t.checkCancel(); - switch (posix.errno(posix.system.fcntl(fd, posix.F.SETFD, @as(usize, posix.FD_CLOEXEC)))) { - .SUCCESS => break, - .INTR => continue, - .CANCELED => return error.Canceled, - else => |err| return posix.unexpectedErrno(err), - } - }; - break fd; - }, - .INTR => continue, - .CANCELED => return error.Canceled, +const dirRealPathFile = switch (native_os) { + .windows => dirRealPathFileWindows, + else => dirRealPathFilePosix, +}; - .AFNOSUPPORT => return error.AddressFamilyUnsupported, - .INVAL => return error.ProtocolUnsupportedBySystem, - .MFILE => return error.ProcessFdQuotaExceeded, - .NFILE => return error.SystemFdQuotaExceeded, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .PROTONOSUPPORT => return error.ProtocolUnsupportedByAddressFamily, - .PROTOTYPE => return error.SocketModeUnsupported, - else => |err| return posix.unexpectedErrno(err), +fn dirRealPathFileWindows(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, out_buffer: []u8) Dir.RealPathFileError!usize { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + var path_name_w = try windows.sliceToPrefixedFileW(dir.handle, sub_path); + + const h_file = handle: { + const syscall: Syscall = try .start(); + while (true) { + if (windows.OpenFile(path_name_w.span(), .{ + .dir = dir.handle, + .access_mask = .{ + .GENERIC = .{ .READ = true }, + .STANDARD = .{ .SYNCHRONIZE = true }, + }, + .creation = .OPEN, + .filter = .any, + })) |handle| { + syscall.finish(); + break :handle handle; + } else |err| switch (err) { + error.WouldBlock => unreachable, + error.OperationCanceled => { + try syscall.checkCancel(); + continue; + }, + else => |e| return syscall.fail(e), + } } }; - errdefer posix.close(socket_fd); + defer windows.CloseHandle(h_file); + return realPathWindows(h_file, out_buffer); +} - if (options.ip6_only) { - if (posix.IPV6 == void) return error.OptionUnsupported; - try setSocketOption(t, socket_fd, posix.IPPROTO.IPV6, posix.IPV6.V6ONLY, 0); - } +fn realPathWindows(h_file: windows.HANDLE, out_buffer: []u8) File.RealPathError!usize { + var wide_buf: [windows.PATH_MAX_WIDE]u16 = undefined; + // TODO move GetFinalPathNameByHandle logic into std.Io.Threaded and add cancel checks + try Thread.checkCancel(); + const wide_slice = try windows.GetFinalPathNameByHandle(h_file, .{}, &wide_buf); - return socket_fd; + const len = std.unicode.calcWtf8Len(wide_slice); + if (len > out_buffer.len) + return error.NameTooLong; + + return std.unicode.wtf16LeToWtf8(out_buffer, wide_slice); } -fn openSocketWsa(t: *Threaded, family: posix.sa_family_t, options: IpAddress.BindOptions) !ws2_32.SOCKET { - const mode = posixSocketMode(options.mode); - const protocol = posixProtocol(options.protocol); - const flags: u32 = ws2_32.WSA_FLAG_OVERLAPPED | ws2_32.WSA_FLAG_NO_HANDLE_INHERIT; - while (true) { - try t.checkCancel(); - const rc = ws2_32.WSASocketW(family, @bitCast(mode), @bitCast(protocol), null, 0, flags); - if (rc != ws2_32.INVALID_SOCKET) return rc; - switch (ws2_32.WSAGetLastError()) { - .EINTR => continue, - .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => return error.Canceled, - .NOTINITIALISED => { - try initializeWsa(t); +fn dirRealPathFilePosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, out_buffer: []u8) Dir.RealPathFileError!usize { + if (native_os == .wasi) return error.OperationUnsupported; + + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + var path_buffer: [posix.PATH_MAX]u8 = undefined; + const sub_path_posix = try pathToPosix(sub_path, &path_buffer); + + if (builtin.link_libc and dir.handle == posix.AT.FDCWD) { + if (out_buffer.len < posix.PATH_MAX) return error.NameTooLong; + const syscall: Syscall = try .start(); + while (true) { + if (std.c.realpath(sub_path_posix, out_buffer.ptr)) |redundant_pointer| { + syscall.finish(); + assert(redundant_pointer == out_buffer.ptr); + return std.mem.indexOfScalar(u8, out_buffer, 0) orelse out_buffer.len; + } + const err: posix.E = @enumFromInt(std.c._errno().*); + if (err == .INTR) { + try syscall.checkCancel(); continue; - }, - .EAFNOSUPPORT => return error.AddressFamilyUnsupported, - .EMFILE => return error.ProcessFdQuotaExceeded, - .ENOBUFS => return error.SystemResources, - .EPROTONOSUPPORT => return error.ProtocolUnsupportedByAddressFamily, - else => |err| return windows.unexpectedWSAError(err), + } + syscall.finish(); + switch (err) { + .INVAL => return errnoBug(err), + .BADF => return errnoBug(err), + .FAULT => return errnoBug(err), + .ACCES => return error.AccessDenied, + .NOENT => return error.FileNotFound, + .OPNOTSUPP => return error.OperationUnsupported, + .NOTDIR => return error.NotDir, + .NAMETOOLONG => return error.NameTooLong, + .LOOP => return error.SymLinkLoop, + .IO => return error.InputOutput, + else => return posix.unexpectedErrno(err), + } } } -} -fn netAcceptPosix(userdata: ?*anyopaque, listen_fd: net.Socket.Handle) net.Server.AcceptError!net.Stream { - if (!have_networking) return error.NetworkDown; - const t: *Threaded = @ptrCast(@alignCast(userdata)); - var storage: PosixAddress = undefined; - var addr_len: posix.socklen_t = @sizeOf(PosixAddress); - const fd = while (true) { - try t.checkCancel(); - const rc = if (have_accept4) - posix.system.accept4(listen_fd, &storage.any, &addr_len, posix.SOCK.CLOEXEC) - else - posix.system.accept(listen_fd, &storage.any, &addr_len); + var flags: posix.O = .{}; + if (@hasField(posix.O, "NONBLOCK")) flags.NONBLOCK = true; + if (@hasField(posix.O, "CLOEXEC")) flags.CLOEXEC = true; + if (@hasField(posix.O, "PATH")) flags.PATH = true; + + const mode: posix.mode_t = 0; + + const syscall: Syscall = try .start(); + const fd: posix.fd_t = while (true) { + const rc = openat_sym(dir.handle, sub_path_posix, flags, mode); switch (posix.errno(rc)) { .SUCCESS => { - const fd: posix.fd_t = @intCast(rc); - errdefer posix.close(fd); - if (!have_accept4) while (true) { - try t.checkCancel(); - switch (posix.errno(posix.system.fcntl(fd, posix.F.SETFD, @as(usize, posix.FD_CLOEXEC)))) { - .SUCCESS => break, - .INTR => continue, - .CANCELED => return error.Canceled, - else => |err| return posix.unexpectedErrno(err), - } - }; - break fd; + syscall.finish(); + break @intCast(rc); }, - .INTR => continue, - .CANCELED => return error.Canceled, - - .AGAIN => |err| return errnoBug(err), - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .CONNABORTED => return error.ConnectionAborted, - .FAULT => |err| return errnoBug(err), - .INVAL => |err| return errnoBug(err), - .NOTSOCK => |err| return errnoBug(err), - .MFILE => return error.ProcessFdQuotaExceeded, - .NFILE => return error.SystemFdQuotaExceeded, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .OPNOTSUPP => |err| return errnoBug(err), - .PROTO => return error.ProtocolFailure, - .PERM => return error.BlockedByFirewall, - else => |err| return posix.unexpectedErrno(err), - } - }; - return .{ .socket = .{ - .handle = fd, - .address = addressFromPosix(&storage), - } }; -} - -fn netAcceptWindows(userdata: ?*anyopaque, listen_handle: net.Socket.Handle) net.Server.AcceptError!net.Stream { - if (!have_networking) return error.NetworkDown; - const t: *Threaded = @ptrCast(@alignCast(userdata)); - var storage: WsaAddress = undefined; - var addr_len: i32 = @sizeOf(WsaAddress); - while (true) { - try t.checkCancel(); - const rc = ws2_32.accept(listen_handle, &storage.any, &addr_len); - if (rc != ws2_32.INVALID_SOCKET) return .{ .socket = .{ - .handle = rc, - .address = addressFromWsa(&storage), - } }; - switch (ws2_32.WSAGetLastError()) { - .EINTR => continue, - .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => return error.Canceled, - .NOTINITIALISED => { - try initializeWsa(t); + .INTR => { + try syscall.checkCancel(); continue; }, - .ECONNRESET => return error.ConnectionAborted, - .EFAULT => |err| return wsaErrorBug(err), - .ENOTSOCK => |err| return wsaErrorBug(err), - .EINVAL => |err| return wsaErrorBug(err), - .EMFILE => return error.ProcessFdQuotaExceeded, - .ENETDOWN => return error.NetworkDown, - .ENOBUFS => return error.SystemResources, - .EOPNOTSUPP => |err| return wsaErrorBug(err), - else => |err| return windows.unexpectedWSAError(err), + else => |e| { + syscall.finish(); + switch (e) { + .FAULT => |err| return errnoBug(err), + .INVAL => return error.BadPathName, + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .ACCES => return error.AccessDenied, + .FBIG => return error.FileTooBig, + .OVERFLOW => return error.FileTooBig, + .ISDIR => return error.IsDir, + .LOOP => return error.SymLinkLoop, + .MFILE => return error.ProcessFdQuotaExceeded, + .NAMETOOLONG => return error.NameTooLong, + .NFILE => return error.SystemFdQuotaExceeded, + .NODEV => return error.NoDevice, + .NOENT => return error.FileNotFound, + .SRCH => return error.FileNotFound, // Linux when accessing procfs. + .NOMEM => return error.SystemResources, + .NOSPC => return error.NoSpaceLeft, + .NOTDIR => return error.NotDir, + .PERM => return error.PermissionDenied, + .EXIST => return error.PathAlreadyExists, + .BUSY => return error.DeviceBusy, + .NXIO => return error.NoDevice, + .ILSEQ => return error.BadPathName, + else => |err| return posix.unexpectedErrno(err), + } + }, } - } + }; + defer posix.close(fd); + return realPathPosix(fd, out_buffer); } -fn netAcceptUnavailable(userdata: ?*anyopaque, listen_handle: net.Socket.Handle) net.Server.AcceptError!net.Stream { - _ = userdata; - _ = listen_handle; - return error.NetworkDown; +const dirRealPath = switch (native_os) { + .windows => dirRealPathWindows, + else => dirRealPathPosix, +}; + +fn dirRealPathPosix(userdata: ?*anyopaque, dir: Dir, out_buffer: []u8) Dir.RealPathError!usize { + if (native_os == .wasi) return error.OperationUnsupported; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + return realPathPosix(dir.handle, out_buffer); } -fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize { - if (!have_networking) return error.NetworkDown; +fn dirRealPathWindows(userdata: ?*anyopaque, dir: Dir, out_buffer: []u8) Dir.RealPathError!usize { const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + return realPathWindows(dir.handle, out_buffer); +} - var iovecs_buffer: [max_iovecs_len]posix.iovec = undefined; - var i: usize = 0; - for (data) |buf| { - if (iovecs_buffer.len - i == 0) break; - if (buf.len != 0) { - iovecs_buffer[i] = .{ .base = buf.ptr, .len = buf.len }; - i += 1; - } - } - const dest = iovecs_buffer[0..i]; - assert(dest[0].len > 0); +const fileRealPath = switch (native_os) { + .windows => fileRealPathWindows, + else => fileRealPathPosix, +}; - if (native_os == .wasi and !builtin.link_libc) while (true) { - try t.checkCancel(); - var n: usize = undefined; - switch (std.os.wasi.fd_read(fd, dest.ptr, dest.len, &n)) { - .SUCCESS => return n, - .INTR => continue, - .CANCELED => return error.Canceled, +fn fileRealPathWindows(userdata: ?*anyopaque, file: File, out_buffer: []u8) File.RealPathError!usize { + if (native_os == .wasi) return error.OperationUnsupported; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + return realPathWindows(file.handle, out_buffer); +} - .INVAL => |err| return errnoBug(err), - .FAULT => |err| return errnoBug(err), - .AGAIN => |err| return errnoBug(err), - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTCONN => return error.SocketUnconnected, - .CONNRESET => return error.ConnectionResetByPeer, - .TIMEDOUT => return error.Timeout, - .NOTCAPABLE => return error.AccessDenied, - else => |err| return posix.unexpectedErrno(err), - } - }; +fn fileRealPathPosix(userdata: ?*anyopaque, file: File, out_buffer: []u8) File.RealPathError!usize { + if (native_os == .wasi) return error.OperationUnsupported; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + return realPathPosix(file.handle, out_buffer); +} - while (true) { - try t.checkCancel(); - const rc = posix.system.readv(fd, dest.ptr, @intCast(dest.len)); - switch (posix.errno(rc)) { - .SUCCESS => return @intCast(rc), - .INTR => continue, - .CANCELED => return error.Canceled, - - .INVAL => |err| return errnoBug(err), - .FAULT => |err| return errnoBug(err), - .AGAIN => |err| return errnoBug(err), - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTCONN => return error.SocketUnconnected, - .CONNRESET => return error.ConnectionResetByPeer, - .TIMEDOUT => return error.Timeout, - .PIPE => return error.SocketUnconnected, - .NETDOWN => return error.NetworkDown, - else => |err| return posix.unexpectedErrno(err), - } +fn realPathPosix(fd: posix.fd_t, out_buffer: []u8) File.RealPathError!usize { + switch (native_os) { + .netbsd, .dragonfly, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => { + var sufficient_buffer: [posix.PATH_MAX]u8 = undefined; + @memset(&sufficient_buffer, 0); + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.fcntl(fd, posix.F.GETPATH, &sufficient_buffer))) { + .SUCCESS => { + syscall.finish(); + break; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ACCES => return error.AccessDenied, + .BADF => return error.FileNotFound, + .NOENT => return error.FileNotFound, + .NOMEM => return error.SystemResources, + .NOSPC => return error.NameTooLong, + .RANGE => return error.NameTooLong, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } + const n = std.mem.indexOfScalar(u8, &sufficient_buffer, 0) orelse sufficient_buffer.len; + if (n > out_buffer.len) return error.NameTooLong; + @memcpy(out_buffer[0..n], sufficient_buffer[0..n]); + return n; + }, + .linux, .serenity, .illumos => { + var procfs_buf: ["/proc/self/path/-2147483648\x00".len]u8 = undefined; + const template = if (native_os == .illumos) "/proc/self/path/{d}" else "/proc/self/fd/{d}"; + const proc_path = std.fmt.bufPrintSentinel(&procfs_buf, template, .{fd}, 0) catch unreachable; + const syscall: Syscall = try .start(); + while (true) { + const rc = posix.system.readlink(proc_path, out_buffer.ptr, out_buffer.len); + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + const len: usize = @bitCast(rc); + return len; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ACCES => return error.AccessDenied, + .FAULT => |err| return errnoBug(err), + .IO => return error.FileSystem, + .LOOP => return error.SymLinkLoop, + .NAMETOOLONG => return error.NameTooLong, + .NOENT => return error.FileNotFound, + .NOMEM => return error.SystemResources, + .NOTDIR => return error.NotDir, + .ILSEQ => |err| return errnoBug(err), + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } + }, + .freebsd => { + var k_file: std.c.kinfo_file = undefined; + k_file.structsize = std.c.KINFO_FILE_SIZE; + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(std.c.fcntl(fd, std.c.F.KINFO, @intFromPtr(&k_file)))) { + .SUCCESS => { + syscall.finish(); + break; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + .BADF => { + syscall.finish(); + return error.FileNotFound; + }, + else => |err| { + syscall.finish(); + return posix.unexpectedErrno(err); + }, + } + } + const len = std.mem.findScalar(u8, &k_file.path, 0) orelse k_file.path.len; + if (len == 0) return error.NameTooLong; + @memcpy(out_buffer[0..len], k_file.path[0..len]); + return len; + }, + else => return error.OperationUnsupported, } + comptime unreachable; } -fn netReadWindows(userdata: ?*anyopaque, handle: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize { - if (!have_networking) return error.NetworkDown; - const t: *Threaded = @ptrCast(@alignCast(userdata)); +fn fileHardLink( + userdata: ?*anyopaque, + file: File, + new_dir: Dir, + new_sub_path: []const u8, + options: File.HardLinkOptions, +) File.HardLinkError!void { + _ = userdata; + if (native_os != .linux) return error.OperationUnsupported; - const bufs = b: { - var iovec_buffer: [max_iovecs_len]ws2_32.WSABUF = undefined; - var i: usize = 0; - var n: usize = 0; - for (data) |buf| { - if (iovec_buffer.len - i == 0) break; - if (buf.len == 0) continue; - if (std.math.cast(u32, buf.len)) |len| { - iovec_buffer[i] = .{ .buf = buf.ptr, .len = len }; - i += 1; - n += len; - continue; - } - iovec_buffer[i] = .{ .buf = buf.ptr, .len = std.math.maxInt(u32) }; - i += 1; - n += std.math.maxInt(u32); - break; - } + var new_path_buffer: [posix.PATH_MAX]u8 = undefined; + const new_sub_path_posix = try pathToPosix(new_sub_path, &new_path_buffer); - const bufs = iovec_buffer[0..i]; - assert(bufs[0].len != 0); + const flags: u32 = if (options.follow_symlinks) + posix.AT.SYMLINK_FOLLOW | posix.AT.EMPTY_PATH + else + posix.AT.EMPTY_PATH; - break :b bufs; + return linkat(file.handle, "", new_dir.handle, new_sub_path_posix, flags) catch |err| switch (err) { + error.FileNotFound => { + if (options.follow_symlinks) return error.FileNotFound; + var proc_buf: ["/proc/self/fd/-2147483648\x00".len]u8 = undefined; + const proc_path = std.fmt.bufPrintSentinel(&proc_buf, "/proc/self/fd/{d}", .{file.handle}, 0) catch + unreachable; + return linkat(posix.AT.FDCWD, proc_path, new_dir.handle, new_sub_path_posix, posix.AT.SYMLINK_FOLLOW); + }, + else => |e| return e, }; +} +fn linkat( + old_dir: posix.fd_t, + old_path: [*:0]const u8, + new_dir: posix.fd_t, + new_path: [*:0]const u8, + flags: u32, +) File.HardLinkError!void { + const syscall: Syscall = try .start(); while (true) { - try t.checkCancel(); - - var flags: u32 = 0; - var overlapped: windows.OVERLAPPED = std.mem.zeroes(windows.OVERLAPPED); - var n: u32 = undefined; - const rc = ws2_32.WSARecv(handle, bufs.ptr, @intCast(bufs.len), &n, &flags, &overlapped, null); - if (rc != ws2_32.SOCKET_ERROR) return n; - const wsa_error: ws2_32.WinsockError = switch (ws2_32.WSAGetLastError()) { - .IO_PENDING => e: { - var result_flags: u32 = undefined; - const overlapped_rc = ws2_32.WSAGetOverlappedResult( - handle, - &overlapped, - &n, - windows.TRUE, - &result_flags, - ); - if (overlapped_rc == windows.FALSE) { - break :e ws2_32.WSAGetLastError(); - } else { - return n; - } - }, - else => |err| err, - }; - switch (wsa_error) { - .EINTR => continue, - .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => return error.Canceled, - .NOTINITIALISED => { - try initializeWsa(t); + switch (posix.errno(posix.system.linkat(old_dir, old_path, new_dir, new_path, flags))) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); continue; }, - - .ECONNRESET => return error.ConnectionResetByPeer, - .EFAULT => unreachable, // a pointer is not completely contained in user address space. - .EINVAL => |err| return wsaErrorBug(err), - .EMSGSIZE => |err| return wsaErrorBug(err), - .ENETDOWN => return error.NetworkDown, - .ENETRESET => return error.ConnectionResetByPeer, - .ENOTCONN => return error.SocketUnconnected, - else => |err| return windows.unexpectedWSAError(err), + .ACCES => return syscall.fail(error.AccessDenied), + .DQUOT => return syscall.fail(error.DiskQuota), + .EXIST => return syscall.fail(error.PathAlreadyExists), + .IO => return syscall.fail(error.HardwareFailure), + .LOOP => return syscall.fail(error.SymLinkLoop), + .MLINK => return syscall.fail(error.LinkQuotaExceeded), + .NAMETOOLONG => return syscall.fail(error.NameTooLong), + .NOENT => return syscall.fail(error.FileNotFound), + .NOMEM => return syscall.fail(error.SystemResources), + .NOSPC => return syscall.fail(error.NoSpaceLeft), + .NOTDIR => return syscall.fail(error.NotDir), + .PERM => return syscall.fail(error.PermissionDenied), + .ROFS => return syscall.fail(error.ReadOnlyFileSystem), + .XDEV => return syscall.fail(error.CrossDevice), + .ILSEQ => return syscall.fail(error.BadPathName), + .FAULT => |err| return syscall.errnoBug(err), + .INVAL => |err| return syscall.errnoBug(err), + else => |err| return syscall.unexpectedErrno(err), } } } -fn netReadUnavailable(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize { - _ = userdata; - _ = fd; - _ = data; - return error.NetworkDown; -} - -fn netSendPosix( - userdata: ?*anyopaque, - handle: net.Socket.Handle, - messages: []net.OutgoingMessage, - flags: net.SendFlags, -) struct { ?net.Socket.SendError, usize } { - if (!have_networking) return .{ error.NetworkDown, 0 }; - const t: *Threaded = @ptrCast(@alignCast(userdata)); - - const posix_flags: u32 = - @as(u32, if (@hasDecl(posix.MSG, "CONFIRM") and flags.confirm) posix.MSG.CONFIRM else 0) | - @as(u32, if (@hasDecl(posix.MSG, "DONTROUTE") and flags.dont_route) posix.MSG.DONTROUTE else 0) | - @as(u32, if (@hasDecl(posix.MSG, "EOR") and flags.eor) posix.MSG.EOR else 0) | - @as(u32, if (@hasDecl(posix.MSG, "OOB") and flags.oob) posix.MSG.OOB else 0) | - @as(u32, if (@hasDecl(posix.MSG, "FASTOPEN") and flags.fastopen) posix.MSG.FASTOPEN else 0) | - posix.MSG.NOSIGNAL; +const dirDeleteFile = switch (native_os) { + .windows => dirDeleteFileWindows, + .wasi => dirDeleteFileWasi, + else => dirDeleteFilePosix, +}; - var i: usize = 0; - while (messages.len - i != 0) { - if (have_sendmmsg) { - i += netSendMany(t, handle, messages[i..], posix_flags) catch |err| return .{ err, i }; - continue; - } - netSendOne(t, handle, &messages[i], posix_flags) catch |err| return .{ err, i }; - i += 1; - } - return .{ null, i }; +fn dirDeleteFileWindows(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8) Dir.DeleteFileError!void { + return dirDeleteWindows(userdata, dir, sub_path, false) catch |err| switch (err) { + error.DirNotEmpty => unreachable, + else => |e| return e, + }; } -fn netSendWindows( - userdata: ?*anyopaque, - handle: net.Socket.Handle, - messages: []net.OutgoingMessage, - flags: net.SendFlags, -) struct { ?net.Socket.SendError, usize } { - if (!have_networking) return .{ error.NetworkDown, 0 }; +fn dirDeleteFileWasi(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8) Dir.DeleteFileError!void { + if (builtin.link_libc) return dirDeleteFilePosix(userdata, dir, sub_path); const t: *Threaded = @ptrCast(@alignCast(userdata)); _ = t; - _ = handle; - _ = messages; - _ = flags; - @panic("TODO netSendWindows"); -} - -fn netSendUnavailable( - userdata: ?*anyopaque, - handle: net.Socket.Handle, - messages: []net.OutgoingMessage, - flags: net.SendFlags, -) struct { ?net.Socket.SendError, usize } { - _ = userdata; - _ = handle; - _ = messages; - _ = flags; - return .{ error.NetworkDown, 0 }; -} - -fn netSendOne( - t: *Threaded, - handle: net.Socket.Handle, - message: *net.OutgoingMessage, - flags: u32, -) net.Socket.SendError!void { - var addr: PosixAddress = undefined; - var iovec: posix.iovec_const = .{ .base = @constCast(message.data_ptr), .len = message.data_len }; - const msg: posix.msghdr_const = .{ - .name = &addr.any, - .namelen = addressToPosix(message.address, &addr), - .iov = (&iovec)[0..1], - .iovlen = 1, - // OS returns EINVAL if this pointer is invalid even if controllen is zero. - .control = if (message.control.len == 0) null else @constCast(message.control.ptr), - .controllen = @intCast(message.control.len), - .flags = 0, - }; + const syscall: Syscall = try .start(); while (true) { - try t.checkCancel(); - const rc = posix.system.sendmsg(handle, &msg, flags); - if (is_windows) { - if (rc == ws2_32.SOCKET_ERROR) { - switch (ws2_32.WSAGetLastError()) { - .EINTR => continue, - .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => return error.Canceled, - .NOTINITIALISED => { - try initializeWsa(t); - continue; - }, - .EACCES => return error.AccessDenied, - .EADDRNOTAVAIL => return error.AddressUnavailable, - .ECONNRESET => return error.ConnectionResetByPeer, - .EMSGSIZE => return error.MessageOversize, - .ENOBUFS => return error.SystemResources, - .ENOTSOCK => return error.FileDescriptorNotASocket, - .EAFNOSUPPORT => return error.AddressFamilyUnsupported, - .EDESTADDRREQ => unreachable, // A destination address is required. - .EFAULT => unreachable, // The lpBuffers, lpTo, lpOverlapped, lpNumberOfBytesSent, or lpCompletionRoutine parameters are not part of the user address space, or the lpTo parameter is too small. - .EHOSTUNREACH => return error.NetworkUnreachable, - .EINVAL => unreachable, - .ENETDOWN => return error.NetworkDown, - .ENETRESET => return error.ConnectionResetByPeer, - .ENETUNREACH => return error.NetworkUnreachable, - .ENOTCONN => return error.SocketUnconnected, - .ESHUTDOWN => |err| return wsaErrorBug(err), - else => |err| return windows.unexpectedWSAError(err), - } - } else { - message.data_len = @intCast(rc); - return; - } - } - switch (posix.errno(rc)) { + const res = std.os.wasi.path_unlink_file(dir.handle, sub_path.ptr, sub_path.len); + switch (res) { .SUCCESS => { - message.data_len = @intCast(rc); + syscall.finish(); return; }, - .INTR => continue, - .CANCELED => return error.Canceled, - - .ACCES => return error.AccessDenied, - .ALREADY => return error.FastOpenAlreadyInProgress, - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .CONNRESET => return error.ConnectionResetByPeer, - .DESTADDRREQ => |err| return errnoBug(err), - .FAULT => |err| return errnoBug(err), - .INVAL => |err| return errnoBug(err), - .ISCONN => |err| return errnoBug(err), - .MSGSIZE => return error.MessageOversize, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTSOCK => |err| return errnoBug(err), - .OPNOTSUPP => |err| return errnoBug(err), - .PIPE => return error.SocketUnconnected, - .AFNOSUPPORT => return error.AddressFamilyUnsupported, - .HOSTUNREACH => return error.HostUnreachable, - .NETUNREACH => return error.NetworkUnreachable, - .NOTCONN => return error.SocketUnconnected, - .NETDOWN => return error.NetworkDown, - else => |err| return posix.unexpectedErrno(err), + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ACCES => return error.AccessDenied, + .PERM => return error.PermissionDenied, + .BUSY => return error.FileBusy, + .FAULT => |err| return errnoBug(err), + .IO => return error.FileSystem, + .ISDIR => return error.IsDir, + .LOOP => return error.SymLinkLoop, + .NAMETOOLONG => return error.NameTooLong, + .NOENT => return error.FileNotFound, + .NOTDIR => return error.NotDir, + .NOMEM => return error.SystemResources, + .ROFS => return error.ReadOnlyFileSystem, + .NOTCAPABLE => return error.AccessDenied, + .ILSEQ => return error.BadPathName, + .INVAL => |err| return errnoBug(err), // invalid flags, or pathname has . as last component + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + else => |err| return posix.unexpectedErrno(err), + } + }, } } } -fn netSendMany( - t: *Threaded, - handle: net.Socket.Handle, - messages: []net.OutgoingMessage, - flags: u32, -) net.Socket.SendError!usize { - var msg_buffer: [64]std.os.linux.mmsghdr = undefined; - var addr_buffer: [msg_buffer.len]PosixAddress = undefined; - var iovecs_buffer: [msg_buffer.len]posix.iovec = undefined; - const min_len: usize = @min(messages.len, msg_buffer.len); - const clamped_messages = messages[0..min_len]; - const clamped_msgs = (&msg_buffer)[0..min_len]; - const clamped_addrs = (&addr_buffer)[0..min_len]; - const clamped_iovecs = (&iovecs_buffer)[0..min_len]; +fn dirDeleteFilePosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8) Dir.DeleteFileError!void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; - for (clamped_messages, clamped_msgs, clamped_addrs, clamped_iovecs) |*message, *msg, *addr, *iovec| { - iovec.* = .{ .base = @constCast(message.data_ptr), .len = message.data_len }; - msg.* = .{ - .hdr = .{ - .name = &addr.any, - .namelen = addressToPosix(message.address, addr), - .iov = iovec[0..1], - .iovlen = 1, - .control = @constCast(message.control.ptr), - .controllen = message.control.len, - .flags = 0, - }, - .len = undefined, // Populated by calling sendmmsg below. - }; - } + var path_buffer: [posix.PATH_MAX]u8 = undefined; + const sub_path_posix = try pathToPosix(sub_path, &path_buffer); + const syscall: Syscall = try .start(); while (true) { - try t.checkCancel(); - const rc = posix.system.sendmmsg(handle, clamped_msgs.ptr, @intCast(clamped_msgs.len), flags); - switch (posix.errno(rc)) { + switch (posix.errno(posix.system.unlinkat(dir.handle, sub_path_posix, 0))) { .SUCCESS => { - const n: usize = @intCast(rc); - for (clamped_messages[0..n], clamped_msgs[0..n]) |*message, *msg| { - message.data_len = msg.len; + syscall.finish(); + return; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + // Some systems return permission errors when trying to delete a + // directory, so we need to handle that case specifically and + // translate the error. + .PERM => switch (native_os) { + .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos, .freebsd, .netbsd, .dragonfly, .openbsd, .illumos => { + + // Don't follow symlinks to match unlinkat (which acts on symlinks rather than follows them). + var st = std.mem.zeroes(posix.Stat); + while (true) { + try syscall.checkCancel(); + switch (posix.errno(fstatat_sym(dir.handle, sub_path_posix, &st, posix.AT.SYMLINK_NOFOLLOW))) { + .SUCCESS => { + syscall.finish(); + break; + }, + .INTR => continue, + else => { + syscall.finish(); + return error.PermissionDenied; + }, + } + } + const is_dir = st.mode & posix.S.IFMT == posix.S.IFDIR; + if (is_dir) + return error.IsDir + else + return error.PermissionDenied; + }, + else => { + syscall.finish(); + return error.PermissionDenied; + }, + }, + else => |e| { + syscall.finish(); + switch (e) { + .ACCES => return error.AccessDenied, + .BUSY => return error.FileBusy, + .FAULT => |err| return errnoBug(err), + .IO => return error.FileSystem, + .ISDIR => return error.IsDir, + .LOOP => return error.SymLinkLoop, + .NAMETOOLONG => return error.NameTooLong, + .NOENT => return error.FileNotFound, + .NOTDIR => return error.NotDir, + .NOMEM => return error.SystemResources, + .ROFS => return error.ReadOnlyFileSystem, + .EXIST => |err| return errnoBug(err), + .NOTEMPTY => |err| return errnoBug(err), // Not passing AT.REMOVEDIR + .ILSEQ => return error.BadPathName, + .INVAL => |err| return errnoBug(err), // invalid flags, or pathname has . as last component + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + else => |err| return posix.unexpectedErrno(err), } - return n; }, - .INTR => continue, - .CANCELED => return error.Canceled, - - .AGAIN => |err| return errnoBug(err), - .ALREADY => return error.FastOpenAlreadyInProgress, - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .CONNRESET => return error.ConnectionResetByPeer, - .DESTADDRREQ => |err| return errnoBug(err), // The socket is not connection-mode, and no peer address is set. - .FAULT => |err| return errnoBug(err), // An invalid user space address was specified for an argument. - .INVAL => |err| return errnoBug(err), // Invalid argument passed. - .ISCONN => |err| return errnoBug(err), // connection-mode socket was connected already but a recipient was specified - .MSGSIZE => return error.MessageOversize, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTSOCK => |err| return errnoBug(err), // The file descriptor sockfd does not refer to a socket. - .OPNOTSUPP => |err| return errnoBug(err), // Some bit in the flags argument is inappropriate for the socket type. - .PIPE => return error.SocketUnconnected, - .AFNOSUPPORT => return error.AddressFamilyUnsupported, - .HOSTUNREACH => return error.HostUnreachable, - .NETUNREACH => return error.NetworkUnreachable, - .NOTCONN => return error.SocketUnconnected, - .NETDOWN => return error.NetworkDown, - else => |err| return posix.unexpectedErrno(err), } } } -fn netReceivePosix( - userdata: ?*anyopaque, - handle: net.Socket.Handle, - message_buffer: []net.IncomingMessage, - data_buffer: []u8, - flags: net.ReceiveFlags, - timeout: Io.Timeout, -) struct { ?net.Socket.ReceiveTimeoutError, usize } { - if (!have_networking) return .{ error.NetworkDown, 0 }; - const t: *Threaded = @ptrCast(@alignCast(userdata)); - const t_io = io(t); +const dirDeleteDir = switch (native_os) { + .windows => dirDeleteDirWindows, + .wasi => dirDeleteDirWasi, + else => dirDeleteDirPosix, +}; - // recvmmsg is useless, here's why: - // * [timeout bug](https://bugzilla.kernel.org/show_bug.cgi?id=75371) - // * it wants iovecs for each message but we have a better API: one data - // buffer to handle all the messages. The better API cannot be lowered to - // the split vectors though because reducing the buffer size might make - // some messages unreceivable. +fn dirDeleteDirWindows(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8) Dir.DeleteDirError!void { + return dirDeleteWindows(userdata, dir, sub_path, true) catch |err| switch (err) { + error.IsDir => unreachable, + else => |e| return e, + }; +} - // So the strategy instead is to use non-blocking recvmsg calls, calling - // poll() with timeout if the first one returns EAGAIN. - const posix_flags: u32 = - @as(u32, if (flags.oob) posix.MSG.OOB else 0) | - @as(u32, if (flags.peek) posix.MSG.PEEK else 0) | - @as(u32, if (flags.trunc) posix.MSG.TRUNC else 0) | - posix.MSG.DONTWAIT | posix.MSG.NOSIGNAL; +fn dirDeleteWindows(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, remove_dir: bool) (Dir.DeleteDirError || Dir.DeleteFileError)!void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + const w = windows; - var poll_fds: [1]posix.pollfd = .{ - .{ - .fd = handle, - .events = posix.POLL.IN, - .revents = undefined, - }, + const sub_path_w_buf = try w.sliceToPrefixedFileW(dir.handle, sub_path); + const sub_path_w = sub_path_w_buf.span(); + + const path_len_bytes = @as(u16, @intCast(sub_path_w.len * 2)); + var nt_name: w.UNICODE_STRING = .{ + .Length = path_len_bytes, + .MaximumLength = path_len_bytes, + // The Windows API makes this mutable, but it will not mutate here. + .Buffer = @constCast(sub_path_w.ptr), }; - var message_i: usize = 0; - var data_i: usize = 0; - const deadline = timeout.toDeadline(t_io) catch |err| return .{ err, message_i }; + if (sub_path_w[0] == '.' and sub_path_w[1] == 0) { + // Windows does not recognize this, but it does work with empty string. + nt_name.Length = 0; + } + if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) { + // Can't remove the parent directory with an open handle. + return error.FileBusy; + } - recv: while (true) { - t.checkCancel() catch |err| return .{ err, message_i }; + var io_status_block: w.IO_STATUS_BLOCK = undefined; + var tmp_handle: w.HANDLE = undefined; + { + const syscall: Syscall = try .start(); + while (true) switch (w.ntdll.NtCreateFile( + &tmp_handle, + .{ .STANDARD = .{ + .RIGHTS = .{ .DELETE = true }, + .SYNCHRONIZE = true, + } }, + &.{ + .Length = @sizeOf(w.OBJECT_ATTRIBUTES), + .RootDirectory = if (Dir.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir.handle, + .Attributes = .{}, + .ObjectName = &nt_name, + .SecurityDescriptor = null, + .SecurityQualityOfService = null, + }, + &io_status_block, + null, + .{}, + .VALID_FLAGS, + .OPEN, + .{ + .DIRECTORY_FILE = remove_dir, + .NON_DIRECTORY_FILE = !remove_dir, + .OPEN_REPARSE_POINT = true, // would we ever want to delete the target instead? + }, + null, + 0, + )) { + .SUCCESS => break syscall.finish(), + .OBJECT_NAME_INVALID => |err| return syscall.ntstatusBug(err), + .OBJECT_NAME_NOT_FOUND => return syscall.fail(error.FileNotFound), + .OBJECT_PATH_NOT_FOUND => return syscall.fail(error.FileNotFound), + .BAD_NETWORK_PATH => return syscall.fail(error.NetworkNotFound), // \\server was not found + .BAD_NETWORK_NAME => return syscall.fail(error.NetworkNotFound), // \\server was found but \\server\share wasn't + .INVALID_PARAMETER => |err| return syscall.ntstatusBug(err), + .FILE_IS_A_DIRECTORY => return syscall.fail(error.IsDir), + .NOT_A_DIRECTORY => return syscall.fail(error.NotDir), + .SHARING_VIOLATION => return syscall.fail(error.FileBusy), + .ACCESS_DENIED => return syscall.fail(error.AccessDenied), + .DELETE_PENDING => return syscall.finish(), + else => |rc| return syscall.unexpectedNtstatus(rc), + }; + } + defer w.CloseHandle(tmp_handle); - if (message_buffer.len - message_i == 0) return .{ null, message_i }; - const message = &message_buffer[message_i]; - const remaining_data_buffer = data_buffer[data_i..]; - var storage: PosixAddress = undefined; - var iov: posix.iovec = .{ .base = remaining_data_buffer.ptr, .len = remaining_data_buffer.len }; - var msg: posix.msghdr = .{ - .name = &storage.any, - .namelen = @sizeOf(PosixAddress), - .iov = (&iov)[0..1], - .iovlen = 1, - .control = message.control.ptr, - .controllen = @intCast(message.control.len), - .flags = undefined, + // FileDispositionInformationEx has varying levels of support: + // - FILE_DISPOSITION_INFORMATION_EX requires >= win10_rs1 + // (INVALID_INFO_CLASS is returned if not supported) + // - Requires the NTFS filesystem + // (on filesystems like FAT32, INVALID_PARAMETER is returned) + // - FILE_DISPOSITION_POSIX_SEMANTICS requires >= win10_rs1 + // - FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE requires >= win10_rs5 + // (NOT_SUPPORTED is returned if a flag is unsupported) + // + // The strategy here is just to try using FileDispositionInformationEx and fall back to + // FileDispositionInformation if the return value lets us know that some aspect of it is not supported. + const rc = rc: { + // Deletion with posix semantics if the filesystem supports it. + const info: w.FILE.DISPOSITION.INFORMATION.EX = .{ .Flags = .{ + .DELETE = true, + .POSIX_SEMANTICS = true, + .IGNORE_READONLY_ATTRIBUTE = true, + } }; + + const syscall: Syscall = try .start(); + while (true) switch (w.ntdll.NtSetInformationFile( + tmp_handle, + &io_status_block, + &info, + @sizeOf(w.FILE.DISPOSITION.INFORMATION.EX), + .DispositionEx, + )) { + .CANCELLED => { + try syscall.checkCancel(); + continue; + }, + // The filesystem does not support FileDispositionInformationEx + .INVALID_PARAMETER, + // The operating system does not support FileDispositionInformationEx + .INVALID_INFO_CLASS, + // The operating system does not support one of the flags + .NOT_SUPPORTED, + => break, // use fallback path below; `syscall` still active + + // For all other statuses, fall down to the switch below to handle them. + else => |rc| { + syscall.finish(); + break :rc rc; + }, }; - const recv_rc = posix.system.recvmsg(handle, &msg, posix_flags); - switch (posix.errno(recv_rc)) { - .SUCCESS => { - const data = remaining_data_buffer[0..@intCast(recv_rc)]; - data_i += data.len; - message.* = .{ - .from = addressFromPosix(&storage), - .data = data, - .control = if (msg.control) |ptr| @as([*]u8, @ptrCast(ptr))[0..msg.controllen] else message.control, - .flags = .{ - .eor = (msg.flags & posix.MSG.EOR) != 0, - .trunc = (msg.flags & posix.MSG.TRUNC) != 0, - .ctrunc = (msg.flags & posix.MSG.CTRUNC) != 0, - .oob = (msg.flags & posix.MSG.OOB) != 0, - .errqueue = if (@hasDecl(posix.MSG, "ERRQUEUE")) (msg.flags & posix.MSG.ERRQUEUE) != 0 else false, - }, - }; - message_i += 1; + // Deletion with file pending semantics, which requires waiting or moving + // files to get them removed (from here). + const file_dispo: w.FILE.DISPOSITION.INFORMATION = .{ + .DeleteFile = w.TRUE, + }; + + while (true) switch (w.ntdll.NtSetInformationFile( + tmp_handle, + &io_status_block, + &file_dispo, + @sizeOf(w.FILE.DISPOSITION.INFORMATION), + .Disposition, + )) { + .CANCELLED => { + try syscall.checkCancel(); continue; }, - .AGAIN => while (true) { - t.checkCancel() catch |err| return .{ err, message_i }; - if (message_i != 0) return .{ null, message_i }; + else => |rc| { + syscall.finish(); + break :rc rc; + }, + }; + }; + switch (rc) { + .SUCCESS => {}, + .DIRECTORY_NOT_EMPTY => return error.DirNotEmpty, + .INVALID_PARAMETER => |err| return w.statusBug(err), + .CANNOT_DELETE => return error.AccessDenied, + .MEDIA_WRITE_PROTECTED => return error.AccessDenied, + .ACCESS_DENIED => return error.AccessDenied, + else => return w.unexpectedStatus(rc), + } +} - const max_poll_ms = std.math.maxInt(u31); - const timeout_ms: u31 = if (deadline) |d| t: { - const duration = d.durationFromNow(t_io) catch |err| return .{ err, message_i }; - if (duration.raw.nanoseconds <= 0) return .{ error.Timeout, message_i }; - break :t @intCast(@min(max_poll_ms, duration.raw.toMilliseconds())); - } else max_poll_ms; +fn dirDeleteDirWasi(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8) Dir.DeleteDirError!void { + if (builtin.link_libc) return dirDeleteDirPosix(userdata, dir, sub_path); - const poll_rc = posix.system.poll(&poll_fds, poll_fds.len, timeout_ms); - switch (posix.errno(poll_rc)) { - .SUCCESS => { - if (poll_rc == 0) { - // Although spurious timeouts are OK, when no deadline - // is passed we must not return `error.Timeout`. - if (deadline == null) continue; - return .{ error.Timeout, message_i }; - } - continue :recv; - }, - .INTR => continue, - .CANCELED => return .{ error.Canceled, message_i }, + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; - .FAULT => |err| return .{ errnoBug(err), message_i }, - .INVAL => |err| return .{ errnoBug(err), message_i }, - .NOMEM => return .{ error.SystemResources, message_i }, - else => |err| return .{ posix.unexpectedErrno(err), message_i }, + const syscall: Syscall = try .start(); + while (true) { + const res = std.os.wasi.path_remove_directory(dir.handle, sub_path.ptr, sub_path.len); + switch (res) { + .SUCCESS => { + syscall.finish(); + return; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ACCES => return error.AccessDenied, + .PERM => return error.PermissionDenied, + .BUSY => return error.FileBusy, + .FAULT => |err| return errnoBug(err), + .IO => return error.FileSystem, + .LOOP => return error.SymLinkLoop, + .NAMETOOLONG => return error.NameTooLong, + .NOENT => return error.FileNotFound, + .NOTDIR => return error.NotDir, + .NOMEM => return error.SystemResources, + .ROFS => return error.ReadOnlyFileSystem, + .NOTEMPTY => return error.DirNotEmpty, + .NOTCAPABLE => return error.AccessDenied, + .ILSEQ => return error.BadPathName, + .INVAL => |err| return errnoBug(err), // invalid flags, or pathname has . as last component + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + else => |err| return posix.unexpectedErrno(err), } }, - .INTR => continue, - .CANCELED => return .{ error.Canceled, message_i }, - - .BADF => |err| return .{ errnoBug(err), message_i }, - .NFILE => return .{ error.SystemFdQuotaExceeded, message_i }, - .MFILE => return .{ error.ProcessFdQuotaExceeded, message_i }, - .FAULT => |err| return .{ errnoBug(err), message_i }, - .INVAL => |err| return .{ errnoBug(err), message_i }, - .NOBUFS => return .{ error.SystemResources, message_i }, - .NOMEM => return .{ error.SystemResources, message_i }, - .NOTCONN => return .{ error.SocketUnconnected, message_i }, - .NOTSOCK => |err| return .{ errnoBug(err), message_i }, - .MSGSIZE => return .{ error.MessageOversize, message_i }, - .PIPE => return .{ error.SocketUnconnected, message_i }, - .OPNOTSUPP => |err| return .{ errnoBug(err), message_i }, - .CONNRESET => return .{ error.ConnectionResetByPeer, message_i }, - .NETDOWN => return .{ error.NetworkDown, message_i }, - else => |err| return .{ posix.unexpectedErrno(err), message_i }, } } } -fn netReceiveWindows( - userdata: ?*anyopaque, - handle: net.Socket.Handle, - message_buffer: []net.IncomingMessage, - data_buffer: []u8, - flags: net.ReceiveFlags, - timeout: Io.Timeout, -) struct { ?net.Socket.ReceiveTimeoutError, usize } { - if (!have_networking) return .{ error.NetworkDown, 0 }; +fn dirDeleteDirPosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8) Dir.DeleteDirError!void { const t: *Threaded = @ptrCast(@alignCast(userdata)); _ = t; - _ = handle; - _ = message_buffer; - _ = data_buffer; - _ = flags; - _ = timeout; - @panic("TODO implement netReceiveWindows"); -} - -fn netReceiveUnavailable( - userdata: ?*anyopaque, - handle: net.Socket.Handle, - message_buffer: []net.IncomingMessage, - data_buffer: []u8, - flags: net.ReceiveFlags, - timeout: Io.Timeout, -) struct { ?net.Socket.ReceiveTimeoutError, usize } { - _ = userdata; - _ = handle; - _ = message_buffer; - _ = data_buffer; - _ = flags; - _ = timeout; - return .{ error.NetworkDown, 0 }; -} -fn netWritePosix( - userdata: ?*anyopaque, - fd: net.Socket.Handle, - header: []const u8, - data: []const []const u8, - splat: usize, -) net.Stream.Writer.Error!usize { - if (!have_networking) return error.NetworkDown; - const t: *Threaded = @ptrCast(@alignCast(userdata)); + var path_buffer: [posix.PATH_MAX]u8 = undefined; + const sub_path_posix = try pathToPosix(sub_path, &path_buffer); - var iovecs: [max_iovecs_len]posix.iovec_const = undefined; - var msg: posix.msghdr_const = .{ - .name = null, - .namelen = 0, - .iov = &iovecs, - .iovlen = 0, - .control = null, - .controllen = 0, - .flags = 0, - }; - addBuf(&iovecs, &msg.iovlen, header); - for (data[0 .. data.len - 1]) |bytes| addBuf(&iovecs, &msg.iovlen, bytes); - const pattern = data[data.len - 1]; - if (iovecs.len - msg.iovlen != 0) switch (splat) { - 0 => {}, - 1 => addBuf(&iovecs, &msg.iovlen, pattern), - else => switch (pattern.len) { - 0 => {}, - 1 => { - var backup_buffer: [splat_buffer_size]u8 = undefined; - const splat_buffer = &backup_buffer; - const memset_len = @min(splat_buffer.len, splat); - const buf = splat_buffer[0..memset_len]; - @memset(buf, pattern[0]); - addBuf(&iovecs, &msg.iovlen, buf); - var remaining_splat = splat - buf.len; - while (remaining_splat > splat_buffer.len and iovecs.len - msg.iovlen != 0) { - assert(buf.len == splat_buffer.len); - addBuf(&iovecs, &msg.iovlen, splat_buffer); - remaining_splat -= splat_buffer.len; - } - addBuf(&iovecs, &msg.iovlen, splat_buffer[0..remaining_splat]); + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.unlinkat(dir.handle, sub_path_posix, posix.AT.REMOVEDIR))) { + .SUCCESS => { + syscall.finish(); + return; }, - else => for (0..@min(splat, iovecs.len - msg.iovlen)) |_| { - addBuf(&iovecs, &msg.iovlen, pattern); + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ACCES => return error.AccessDenied, + .PERM => return error.PermissionDenied, + .BUSY => return error.FileBusy, + .FAULT => |err| return errnoBug(err), + .IO => return error.FileSystem, + .ISDIR => |err| return errnoBug(err), + .LOOP => return error.SymLinkLoop, + .NAMETOOLONG => return error.NameTooLong, + .NOENT => return error.FileNotFound, + .NOTDIR => return error.NotDir, + .NOMEM => return error.SystemResources, + .ROFS => return error.ReadOnlyFileSystem, + .EXIST => |err| return errnoBug(err), + .NOTEMPTY => return error.DirNotEmpty, + .ILSEQ => return error.BadPathName, + .INVAL => |err| return errnoBug(err), // invalid flags, or pathname has . as last component + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + else => |err| return posix.unexpectedErrno(err), + } }, - }, - }; - const flags = posix.MSG.NOSIGNAL; - while (true) { - try t.checkCancel(); - const rc = posix.system.sendmsg(fd, &msg, flags); - switch (posix.errno(rc)) { - .SUCCESS => return @intCast(rc), - .INTR => continue, - .CANCELED => return error.Canceled, - - .ACCES => |err| return errnoBug(err), - .AGAIN => |err| return errnoBug(err), - .ALREADY => return error.FastOpenAlreadyInProgress, - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .CONNRESET => return error.ConnectionResetByPeer, - .DESTADDRREQ => |err| return errnoBug(err), // The socket is not connection-mode, and no peer address is set. - .FAULT => |err| return errnoBug(err), // An invalid user space address was specified for an argument. - .INVAL => |err| return errnoBug(err), // Invalid argument passed. - .ISCONN => |err| return errnoBug(err), // connection-mode socket was connected already but a recipient was specified - .MSGSIZE => |err| return errnoBug(err), - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTSOCK => |err| return errnoBug(err), // The file descriptor sockfd does not refer to a socket. - .OPNOTSUPP => |err| return errnoBug(err), // Some bit in the flags argument is inappropriate for the socket type. - .PIPE => return error.SocketUnconnected, - .AFNOSUPPORT => return error.AddressFamilyUnsupported, - .HOSTUNREACH => return error.HostUnreachable, - .NETUNREACH => return error.NetworkUnreachable, - .NOTCONN => return error.SocketUnconnected, - .NETDOWN => return error.NetworkDown, - else => |err| return posix.unexpectedErrno(err), } } } -fn netWriteWindows( +const dirRename = switch (native_os) { + .windows => dirRenameWindows, + .wasi => dirRenameWasi, + else => dirRenamePosix, +}; + +fn dirRenameWindows( userdata: ?*anyopaque, - handle: net.Socket.Handle, - header: []const u8, - data: []const []const u8, - splat: usize, -) net.Stream.Writer.Error!usize { + old_dir: Dir, + old_sub_path: []const u8, + new_dir: Dir, + new_sub_path: []const u8, +) Dir.RenameError!void { const t: *Threaded = @ptrCast(@alignCast(userdata)); - comptime assert(native_os == .windows); + _ = t; + return dirRenameWindowsInner(old_dir, old_sub_path, new_dir, new_sub_path, true) catch |err| switch (err) { + error.PathAlreadyExists => return error.Unexpected, + error.OperationUnsupported => return error.Unexpected, + else => |e| return e, + }; +} - var iovecs: [max_iovecs_len]ws2_32.WSABUF = undefined; - var len: u32 = 0; - addWsaBuf(&iovecs, &len, header); - for (data[0 .. data.len - 1]) |bytes| addWsaBuf(&iovecs, &len, bytes); - const pattern = data[data.len - 1]; - if (iovecs.len - len != 0) switch (splat) { - 0 => {}, - 1 => addWsaBuf(&iovecs, &len, pattern), - else => switch (pattern.len) { - 0 => {}, - 1 => { - var backup_buffer: [64]u8 = undefined; - const splat_buffer = &backup_buffer; - const memset_len = @min(splat_buffer.len, splat); - const buf = splat_buffer[0..memset_len]; - @memset(buf, pattern[0]); - addWsaBuf(&iovecs, &len, buf); - var remaining_splat = splat - buf.len; - while (remaining_splat > splat_buffer.len and len < iovecs.len) { - addWsaBuf(&iovecs, &len, splat_buffer); - remaining_splat -= splat_buffer.len; - } - addWsaBuf(&iovecs, &len, splat_buffer[0..remaining_splat]); - }, - else => for (0..@min(splat, iovecs.len - len)) |_| { - addWsaBuf(&iovecs, &len, pattern); +fn dirRenamePreserve( + userdata: ?*anyopaque, + old_dir: Dir, + old_sub_path: []const u8, + new_dir: Dir, + new_sub_path: []const u8, +) Dir.RenamePreserveError!void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + if (is_windows) return dirRenameWindowsInner(old_dir, old_sub_path, new_dir, new_sub_path, false); + if (native_os == .linux) return dirRenamePreserveLinux(old_dir, old_sub_path, new_dir, new_sub_path); + // Make a hard link then delete the original. + try dirHardLink(t, old_dir, old_sub_path, new_dir, new_sub_path, .{ .follow_symlinks = false }); + const prev = swapCancelProtection(t, .blocked); + defer _ = swapCancelProtection(t, prev); + dirDeleteFile(t, old_dir, old_sub_path) catch {}; +} + +fn dirRenameWindowsInner( + old_dir: Dir, + old_sub_path: []const u8, + new_dir: Dir, + new_sub_path: []const u8, + replace_if_exists: bool, +) Dir.RenamePreserveError!void { + const w = windows; + const old_path_w_buf = try windows.sliceToPrefixedFileW(old_dir.handle, old_sub_path); + const old_path_w = old_path_w_buf.span(); + const new_path_w_buf = try windows.sliceToPrefixedFileW(new_dir.handle, new_sub_path); + const new_path_w = new_path_w_buf.span(); + + const src_fd = src_fd: { + const syscall: Syscall = try .start(); + while (true) { + if (w.OpenFile(old_path_w, .{ + .dir = old_dir.handle, + .access_mask = .{ + .GENERIC = .{ .WRITE = true }, + .STANDARD = .{ + .RIGHTS = .{ .DELETE = true }, + .SYNCHRONIZE = true, + }, + }, + .creation = .OPEN, + .filter = .any, // This function is supposed to rename both files and directories. + .follow_symlinks = false, + })) |handle| { + syscall.finish(); + break :src_fd handle; + } else |err| switch (err) { + error.WouldBlock => unreachable, // Not possible without `.share_access_nonblocking = true`. + error.OperationCanceled => { + try syscall.checkCancel(); + continue; + }, + else => |e| return e, + } + } + }; + defer w.CloseHandle(src_fd); + + var rc: w.NTSTATUS = undefined; + // FileRenameInformationEx has varying levels of support: + // - FILE_RENAME_INFORMATION_EX requires >= win10_rs1 + // (INVALID_INFO_CLASS is returned if not supported) + // - Requires the NTFS filesystem + // (on filesystems like FAT32, INVALID_PARAMETER is returned) + // - FILE_RENAME_POSIX_SEMANTICS requires >= win10_rs1 + // - FILE_RENAME_IGNORE_READONLY_ATTRIBUTE requires >= win10_rs5 + // (NOT_SUPPORTED is returned if a flag is unsupported) + // + // The strategy here is just to try using FileRenameInformationEx and fall back to + // FileRenameInformation if the return value lets us know that some aspect of it is not supported. + const need_fallback = need_fallback: { + const rename_info: w.FILE.RENAME_INFORMATION = .init(.{ + .Flags = .{ + .REPLACE_IF_EXISTS = replace_if_exists, + .POSIX_SEMANTICS = true, + .IGNORE_READONLY_ATTRIBUTE = true, }, - }, + .RootDirectory = if (Dir.path.isAbsoluteWindowsWtf16(new_path_w)) null else new_dir.handle, + .FileName = new_path_w, + }); + var io_status_block: w.IO_STATUS_BLOCK = undefined; + const rename_info_buf = rename_info.toBuffer(); + rc = w.ntdll.NtSetInformationFile( + src_fd, + &io_status_block, + rename_info_buf.ptr, + @intCast(rename_info_buf.len), + .RenameEx, + ); + switch (rc) { + .SUCCESS => return, + // The filesystem does not support FileDispositionInformationEx + .INVALID_PARAMETER, + // The operating system does not support FileDispositionInformationEx + .INVALID_INFO_CLASS, + // The operating system does not support one of the flags + .NOT_SUPPORTED, + => break :need_fallback true, + // For all other statuses, fall down to the switch below to handle them. + else => break :need_fallback false, + } }; - while (true) { - try t.checkCancel(); + if (need_fallback) { + const rename_info: w.FILE.RENAME_INFORMATION = .init(.{ + .Flags = .{ .REPLACE_IF_EXISTS = replace_if_exists }, + .RootDirectory = if (Dir.path.isAbsoluteWindowsWtf16(new_path_w)) null else new_dir.handle, + .FileName = new_path_w, + }); + var io_status_block: w.IO_STATUS_BLOCK = undefined; + const rename_info_buf = rename_info.toBuffer(); + rc = w.ntdll.NtSetInformationFile( + src_fd, + &io_status_block, + rename_info_buf.ptr, + @intCast(rename_info_buf.len), + .Rename, + ); + } - var n: u32 = undefined; - var overlapped: windows.OVERLAPPED = std.mem.zeroes(windows.OVERLAPPED); - const rc = ws2_32.WSASend(handle, &iovecs, len, &n, 0, &overlapped, null); - if (rc != ws2_32.SOCKET_ERROR) return n; - const wsa_error: ws2_32.WinsockError = switch (ws2_32.WSAGetLastError()) { - .IO_PENDING => e: { - var result_flags: u32 = undefined; - const overlapped_rc = ws2_32.WSAGetOverlappedResult( - handle, - &overlapped, - &n, - windows.TRUE, - &result_flags, - ); - if (overlapped_rc == windows.FALSE) { - break :e ws2_32.WSAGetLastError(); - } else { - return n; + switch (rc) { + .SUCCESS => {}, + .INVALID_HANDLE => |err| return w.statusBug(err), + .INVALID_PARAMETER => |err| return w.statusBug(err), + .OBJECT_PATH_SYNTAX_BAD => |err| return w.statusBug(err), + .ACCESS_DENIED => return error.AccessDenied, + .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, + .OBJECT_PATH_NOT_FOUND => return error.FileNotFound, + .NOT_SAME_DEVICE => return error.CrossDevice, + .OBJECT_NAME_COLLISION => return error.PathAlreadyExists, + .DIRECTORY_NOT_EMPTY => return error.DirNotEmpty, + .FILE_IS_A_DIRECTORY => return error.IsDir, + .NOT_A_DIRECTORY => return error.NotDir, + else => return w.unexpectedStatus(rc), + } +} + +fn dirRenameWasi( + userdata: ?*anyopaque, + old_dir: Dir, + old_sub_path: []const u8, + new_dir: Dir, + new_sub_path: []const u8, +) Dir.RenameError!void { + if (builtin.link_libc) return dirRenamePosix(userdata, old_dir, old_sub_path, new_dir, new_sub_path); + + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + const syscall: Syscall = try .start(); + while (true) { + switch (std.os.wasi.path_rename(old_dir.handle, old_sub_path.ptr, old_sub_path.len, new_dir.handle, new_sub_path.ptr, new_sub_path.len)) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ACCES => return error.AccessDenied, + .PERM => return error.PermissionDenied, + .BUSY => return error.FileBusy, + .DQUOT => return error.DiskQuota, + .FAULT => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), + .ISDIR => return error.IsDir, + .LOOP => return error.SymLinkLoop, + .MLINK => return error.LinkQuotaExceeded, + .NAMETOOLONG => return error.NameTooLong, + .NOENT => return error.FileNotFound, + .NOTDIR => return error.NotDir, + .NOMEM => return error.SystemResources, + .NOSPC => return error.NoSpaceLeft, + .EXIST => return error.DirNotEmpty, + .NOTEMPTY => return error.DirNotEmpty, + .ROFS => return error.ReadOnlyFileSystem, + .XDEV => return error.CrossDevice, + .NOTCAPABLE => return error.AccessDenied, + .ILSEQ => return error.BadPathName, + else => |err| return posix.unexpectedErrno(err), } }, - else => |err| err, - }; - switch (wsa_error) { - .EINTR => continue, - .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => return error.Canceled, - .NOTINITIALISED => { - try initializeWsa(t); + } + } +} + +fn dirRenamePosix( + userdata: ?*anyopaque, + old_dir: Dir, + old_sub_path: []const u8, + new_dir: Dir, + new_sub_path: []const u8, +) Dir.RenameError!void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + var old_path_buffer: [posix.PATH_MAX]u8 = undefined; + var new_path_buffer: [posix.PATH_MAX]u8 = undefined; + + const old_sub_path_posix = try pathToPosix(old_sub_path, &old_path_buffer); + const new_sub_path_posix = try pathToPosix(new_sub_path, &new_path_buffer); + + return renameat(old_dir.handle, old_sub_path_posix, new_dir.handle, new_sub_path_posix); +} + +fn dirRenamePreserveLinux( + old_dir: Dir, + old_sub_path: []const u8, + new_dir: Dir, + new_sub_path: []const u8, +) Dir.RenamePreserveError!void { + const linux = std.os.linux; + + var old_path_buffer: [linux.PATH_MAX]u8 = undefined; + var new_path_buffer: [linux.PATH_MAX]u8 = undefined; + + const old_sub_path_posix = try pathToPosix(old_sub_path, &old_path_buffer); + const new_sub_path_posix = try pathToPosix(new_sub_path, &new_path_buffer); + + const syscall: Syscall = try .start(); + while (true) switch (linux.errno(linux.renameat2( + old_dir.handle, + old_sub_path_posix, + new_dir.handle, + new_sub_path_posix, + .{ .NOREPLACE = true }, + ))) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); + continue; + }, + .ACCES => return syscall.fail(error.AccessDenied), + .PERM => return syscall.fail(error.PermissionDenied), + .BUSY => return syscall.fail(error.FileBusy), + .DQUOT => return syscall.fail(error.DiskQuota), + .ISDIR => return syscall.fail(error.IsDir), + .LOOP => return syscall.fail(error.SymLinkLoop), + .MLINK => return syscall.fail(error.LinkQuotaExceeded), + .NAMETOOLONG => return syscall.fail(error.NameTooLong), + .NOENT => return syscall.fail(error.FileNotFound), + .NOTDIR => return syscall.fail(error.NotDir), + .NOMEM => return syscall.fail(error.SystemResources), + .NOSPC => return syscall.fail(error.NoSpaceLeft), + .EXIST => return syscall.fail(error.PathAlreadyExists), + .NOTEMPTY => return syscall.fail(error.DirNotEmpty), + .ROFS => return syscall.fail(error.ReadOnlyFileSystem), + .XDEV => return syscall.fail(error.CrossDevice), + .ILSEQ => return syscall.fail(error.BadPathName), + .FAULT => |err| return syscall.errnoBug(err), + .INVAL => |err| return syscall.errnoBug(err), + else => |err| return syscall.unexpectedErrno(err), + }; +} + +fn renameat( + old_dir: posix.fd_t, + old_sub_path: [*:0]const u8, + new_dir: posix.fd_t, + new_sub_path: [*:0]const u8, +) Dir.RenameError!void { + const syscall: Syscall = try .start(); + while (true) switch (posix.errno(posix.system.renameat(old_dir, old_sub_path, new_dir, new_sub_path))) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); + continue; + }, + .ACCES => return syscall.fail(error.AccessDenied), + .PERM => return syscall.fail(error.PermissionDenied), + .BUSY => return syscall.fail(error.FileBusy), + .DQUOT => return syscall.fail(error.DiskQuota), + .ISDIR => return syscall.fail(error.IsDir), + .IO => return syscall.fail(error.HardwareFailure), + .LOOP => return syscall.fail(error.SymLinkLoop), + .MLINK => return syscall.fail(error.LinkQuotaExceeded), + .NAMETOOLONG => return syscall.fail(error.NameTooLong), + .NOENT => return syscall.fail(error.FileNotFound), + .NOTDIR => return syscall.fail(error.NotDir), + .NOMEM => return syscall.fail(error.SystemResources), + .NOSPC => return syscall.fail(error.NoSpaceLeft), + .EXIST => return syscall.fail(error.DirNotEmpty), + .NOTEMPTY => return syscall.fail(error.DirNotEmpty), + .ROFS => return syscall.fail(error.ReadOnlyFileSystem), + .XDEV => return syscall.fail(error.CrossDevice), + .ILSEQ => return syscall.fail(error.BadPathName), + .FAULT => |err| return syscall.errnoBug(err), + .INVAL => |err| return syscall.errnoBug(err), + else => |err| return syscall.unexpectedErrno(err), + }; +} + +fn renameatPreserve( + old_dir: posix.fd_t, + old_sub_path: [*:0]const u8, + new_dir: posix.fd_t, + new_sub_path: [*:0]const u8, +) Dir.RenameError!void { + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.renameat(old_dir, old_sub_path, new_dir, new_sub_path))) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); continue; }, + else => |e| { + syscall.finish(); + switch (e) { + .ACCES => return error.AccessDenied, + .PERM => return error.PermissionDenied, + .BUSY => return error.FileBusy, + .DQUOT => return error.DiskQuota, + .FAULT => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), + .ISDIR => return error.IsDir, + .LOOP => return error.SymLinkLoop, + .MLINK => return error.LinkQuotaExceeded, + .NAMETOOLONG => return error.NameTooLong, + .NOENT => return error.FileNotFound, + .NOTDIR => return error.NotDir, + .NOMEM => return error.SystemResources, + .NOSPC => return error.NoSpaceLeft, + .EXIST => return error.PathAlreadyExists, + .NOTEMPTY => return error.PathAlreadyExists, + .ROFS => return error.ReadOnlyFileSystem, + .XDEV => return error.CrossDevice, + .ILSEQ => return error.BadPathName, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +const dirSymLink = switch (native_os) { + .windows => dirSymLinkWindows, + .wasi => dirSymLinkWasi, + else => dirSymLinkPosix, +}; + +fn dirSymLinkWindows( + userdata: ?*anyopaque, + dir: Dir, + target_path: []const u8, + sym_link_path: []const u8, + flags: Dir.SymLinkFlags, +) Dir.SymLinkError!void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + const w = windows; + + // Target path does not use sliceToPrefixedFileW because certain paths + // are handled differently when creating a symlink than they would be + // when converting to an NT namespaced path. CreateSymbolicLink in + // symLinkW will handle the necessary conversion. + var target_path_w: w.PathSpace = undefined; + target_path_w.len = try w.wtf8ToWtf16Le(&target_path_w.data, target_path); + target_path_w.data[target_path_w.len] = 0; + // However, we need to canonicalize any path separators to `\`, since if + // the target path is relative, then it must use `\` as the path separator. + std.mem.replaceScalar( + u16, + target_path_w.data[0..target_path_w.len], + std.mem.nativeToLittle(u16, '/'), + std.mem.nativeToLittle(u16, '\\'), + ); - .ECONNABORTED => return error.ConnectionResetByPeer, - .ECONNRESET => return error.ConnectionResetByPeer, - .EINVAL => return error.SocketUnconnected, - .ENETDOWN => return error.NetworkDown, - .ENETRESET => return error.ConnectionResetByPeer, - .ENOBUFS => return error.SystemResources, - .ENOTCONN => return error.SocketUnconnected, - .ENOTSOCK => |err| return wsaErrorBug(err), - .EOPNOTSUPP => |err| return wsaErrorBug(err), - .ESHUTDOWN => |err| return wsaErrorBug(err), - else => |err| return windows.unexpectedWSAError(err), + const sym_link_path_w = try w.sliceToPrefixedFileW(dir.handle, sym_link_path); + + const SYMLINK_DATA = extern struct { + ReparseTag: w.IO_REPARSE_TAG, + ReparseDataLength: w.USHORT, + Reserved: w.USHORT, + SubstituteNameOffset: w.USHORT, + SubstituteNameLength: w.USHORT, + PrintNameOffset: w.USHORT, + PrintNameLength: w.USHORT, + Flags: w.ULONG, + }; + + const symlink_handle = handle: { + const syscall: Syscall = try .start(); + while (true) { + if (w.OpenFile(sym_link_path_w.span(), .{ + .access_mask = .{ + .GENERIC = .{ .READ = true, .WRITE = true }, + .STANDARD = .{ .SYNCHRONIZE = true }, + }, + .dir = dir.handle, + .creation = .CREATE, + .filter = if (flags.is_directory) .dir_only else .non_directory_only, + })) |handle| { + syscall.finish(); + break :handle handle; + } else |err| switch (err) { + error.IsDir => return syscall.fail(error.PathAlreadyExists), + error.NotDir => return syscall.fail(error.Unexpected), + error.WouldBlock => return syscall.fail(error.Unexpected), + error.PipeBusy => return syscall.fail(error.Unexpected), + error.NoDevice => return syscall.fail(error.Unexpected), + error.AntivirusInterference => return syscall.fail(error.Unexpected), + error.OperationCanceled => { + try syscall.checkCancel(); + continue; + }, + else => |e| return e, + } + } + }; + defer w.CloseHandle(symlink_handle); + + // Relevant portions of the documentation: + // > Relative links are specified using the following conventions: + // > - Root relative—for example, "\Windows\System32" resolves to "current drive:\Windows\System32". + // > - Current working directory–relative—for example, if the current working directory is + // > C:\Windows\System32, "C:File.txt" resolves to "C:\Windows\System32\File.txt". + // > Note: If you specify a current working directory–relative link, it is created as an absolute + // > link, due to the way the current working directory is processed based on the user and the thread. + // https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsymboliclinkw + var is_target_absolute = false; + const final_target_path = target_path: { + if (w.hasCommonNtPrefix(u16, target_path_w.span())) { + // Already an NT path, no need to do anything to it + break :target_path target_path_w.span(); + } else { + switch (Dir.path.getWin32PathType(u16, target_path_w.span())) { + // Rooted paths need to avoid getting put through wToPrefixedFileW + // (and they are treated as relative in this context) + // Note: It seems that rooted paths in symbolic links are relative to + // the drive that the symbolic exists on, not to the CWD's drive. + // So, if the symlink is on C:\ and the CWD is on D:\, + // it will still resolve the path relative to the root of + // the C:\ drive. + .rooted => break :target_path target_path_w.span(), + // Keep relative paths relative, but anything else needs to get NT-prefixed. + else => if (!Dir.path.isAbsoluteWindowsWtf16(target_path_w.span())) + break :target_path target_path_w.span(), + } } + var prefixed_target_path = try w.wToPrefixedFileW(dir.handle, target_path_w.span()); + // We do this after prefixing to ensure that drive-relative paths are treated as absolute + is_target_absolute = Dir.path.isAbsoluteWindowsWtf16(prefixed_target_path.span()); + break :target_path prefixed_target_path.span(); + }; + + // prepare reparse data buffer + var buffer: [w.MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined; + const buf_len = @sizeOf(SYMLINK_DATA) + final_target_path.len * 4; + const header_len = @sizeOf(w.ULONG) + @sizeOf(w.USHORT) * 2; + const target_is_absolute = Dir.path.isAbsoluteWindowsWtf16(final_target_path); + const symlink_data: SYMLINK_DATA = .{ + .ReparseTag = .SYMLINK, + .ReparseDataLength = @intCast(buf_len - header_len), + .Reserved = 0, + .SubstituteNameOffset = @intCast(final_target_path.len * 2), + .SubstituteNameLength = @intCast(final_target_path.len * 2), + .PrintNameOffset = 0, + .PrintNameLength = @intCast(final_target_path.len * 2), + .Flags = if (!target_is_absolute) w.SYMLINK_FLAG_RELATIVE else 0, + }; + + @memcpy(buffer[0..@sizeOf(SYMLINK_DATA)], std.mem.asBytes(&symlink_data)); + @memcpy(buffer[@sizeOf(SYMLINK_DATA)..][0 .. final_target_path.len * 2], @as([*]const u8, @ptrCast(final_target_path))); + const paths_start = @sizeOf(SYMLINK_DATA) + final_target_path.len * 2; + @memcpy(buffer[paths_start..][0 .. final_target_path.len * 2], @as([*]const u8, @ptrCast(final_target_path))); + const rc = w.DeviceIoControl(symlink_handle, w.FSCTL.SET_REPARSE_POINT, .{ .in = buffer[0..buf_len] }); + switch (rc) { + .SUCCESS => {}, + .PRIVILEGE_NOT_HELD => return error.PermissionDenied, + .ACCESS_DENIED => return error.AccessDenied, + .INVALID_DEVICE_REQUEST => return error.FileSystem, + else => return windows.unexpectedStatus(rc), } } -fn addWsaBuf(v: []ws2_32.WSABUF, i: *u32, bytes: []const u8) void { - const cap = std.math.maxInt(u32); - var remaining = bytes; - while (remaining.len > cap) { - if (v.len - i.* == 0) return; - v[i.*] = .{ .buf = @constCast(remaining.ptr), .len = cap }; - i.* += 1; - remaining = remaining[cap..]; - } else { - @branchHint(.likely); - if (v.len - i.* == 0) return; - v[i.*] = .{ .buf = @constCast(remaining.ptr), .len = @intCast(remaining.len) }; - i.* += 1; +fn dirSymLinkWasi( + userdata: ?*anyopaque, + dir: Dir, + target_path: []const u8, + sym_link_path: []const u8, + flags: Dir.SymLinkFlags, +) Dir.SymLinkError!void { + if (builtin.link_libc) return dirSymLinkPosix(userdata, dir, target_path, sym_link_path, flags); + + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + const syscall: Syscall = try .start(); + while (true) { + switch (std.os.wasi.path_symlink(target_path.ptr, target_path.len, dir.handle, sym_link_path.ptr, sym_link_path.len)) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .FAULT => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), + .BADF => |err| return errnoBug(err), + .ACCES => return error.AccessDenied, + .PERM => return error.PermissionDenied, + .DQUOT => return error.DiskQuota, + .EXIST => return error.PathAlreadyExists, + .IO => return error.FileSystem, + .LOOP => return error.SymLinkLoop, + .NAMETOOLONG => return error.NameTooLong, + .NOENT => return error.FileNotFound, + .NOTDIR => return error.NotDir, + .NOMEM => return error.SystemResources, + .NOSPC => return error.NoSpaceLeft, + .ROFS => return error.ReadOnlyFileSystem, + .NOTCAPABLE => return error.AccessDenied, + .ILSEQ => return error.BadPathName, + else => |err| return posix.unexpectedErrno(err), + } + }, + } } } -fn netWriteUnavailable( +fn dirSymLinkPosix( userdata: ?*anyopaque, - handle: net.Socket.Handle, - header: []const u8, - data: []const []const u8, - splat: usize, -) net.Stream.Writer.Error!usize { - _ = userdata; - _ = handle; - _ = header; - _ = data; - _ = splat; - return error.NetworkDown; + dir: Dir, + target_path: []const u8, + sym_link_path: []const u8, + flags: Dir.SymLinkFlags, +) Dir.SymLinkError!void { + _ = flags; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + var target_path_buffer: [posix.PATH_MAX]u8 = undefined; + var sym_link_path_buffer: [posix.PATH_MAX]u8 = undefined; + + const target_path_posix = try pathToPosix(target_path, &target_path_buffer); + const sym_link_path_posix = try pathToPosix(sym_link_path, &sym_link_path_buffer); + + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.symlinkat(target_path_posix, dir.handle, sym_link_path_posix))) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .FAULT => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), + .ACCES => return error.AccessDenied, + .PERM => return error.PermissionDenied, + .DQUOT => return error.DiskQuota, + .EXIST => return error.PathAlreadyExists, + .IO => return error.FileSystem, + .LOOP => return error.SymLinkLoop, + .NAMETOOLONG => return error.NameTooLong, + .NOENT => return error.FileNotFound, + .NOTDIR => return error.NotDir, + .NOMEM => return error.SystemResources, + .NOSPC => return error.NoSpaceLeft, + .ROFS => return error.ReadOnlyFileSystem, + .ILSEQ => return error.BadPathName, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } } -fn addBuf(v: []posix.iovec_const, i: *@FieldType(posix.msghdr_const, "iovlen"), bytes: []const u8) void { - // OS checks ptr addr before length so zero length vectors must be omitted. - if (bytes.len == 0) return; - if (v.len - i.* == 0) return; - v[i.*] = .{ .base = bytes.ptr, .len = bytes.len }; - i.* += 1; +const dirReadLink = switch (native_os) { + .windows => dirReadLinkWindows, + .wasi => dirReadLinkWasi, + else => dirReadLinkPosix, +}; + +fn dirReadLinkWindows(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, buffer: []u8) Dir.ReadLinkError!usize { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + const w = windows; + + var sub_path_w_buf = try windows.sliceToPrefixedFileW(dir.handle, sub_path); + + const syscall: Syscall = try .start(); + const result_w = while (true) { + if (w.ReadLink(dir.handle, sub_path_w_buf.span(), &sub_path_w_buf.data)) |res| { + syscall.finish(); + break res; + } else |err| switch (err) { + error.OperationCanceled => { + try syscall.checkCancel(); + continue; + }, + else => |e| return syscall.fail(e), + } + }; + + const len = std.unicode.calcWtf8Len(result_w); + if (len > buffer.len) return error.NameTooLong; + + return std.unicode.wtf16LeToWtf8(buffer, result_w); } -fn netClose(userdata: ?*anyopaque, handle: net.Socket.Handle) void { +fn dirReadLinkWasi(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, buffer: []u8) Dir.ReadLinkError!usize { + if (builtin.link_libc) return dirReadLinkPosix(userdata, dir, sub_path, buffer); + const t: *Threaded = @ptrCast(@alignCast(userdata)); _ = t; - switch (native_os) { - .windows => closeSocketWindows(handle), - else => posix.close(handle), + + var n: usize = undefined; + const syscall: Syscall = try .start(); + while (true) { + switch (std.os.wasi.path_readlink(dir.handle, sub_path.ptr, sub_path.len, buffer.ptr, buffer.len, &n)) { + .SUCCESS => { + syscall.finish(); + return n; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ACCES => return error.AccessDenied, + .FAULT => |err| return errnoBug(err), + .INVAL => return error.NotLink, + .IO => return error.FileSystem, + .LOOP => return error.SymLinkLoop, + .NAMETOOLONG => return error.NameTooLong, + .NOENT => return error.FileNotFound, + .NOMEM => return error.SystemResources, + .NOTDIR => return error.NotDir, + .NOTCAPABLE => return error.AccessDenied, + .ILSEQ => return error.BadPathName, + else => |err| return posix.unexpectedErrno(err), + } + }, + } } } -fn netCloseUnavailable(userdata: ?*anyopaque, handle: net.Socket.Handle) void { - _ = userdata; - _ = handle; - unreachable; // How you gonna close something that was impossible to open? +fn dirReadLinkPosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, buffer: []u8) Dir.ReadLinkError!usize { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + var sub_path_buffer: [posix.PATH_MAX]u8 = undefined; + const sub_path_posix = try pathToPosix(sub_path, &sub_path_buffer); + + const syscall: Syscall = try .start(); + while (true) { + const rc = posix.system.readlinkat(dir.handle, sub_path_posix, buffer.ptr, buffer.len); + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + const len: usize = @bitCast(rc); + return len; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ACCES => return error.AccessDenied, + .FAULT => |err| return errnoBug(err), + .INVAL => return error.NotLink, + .IO => return error.FileSystem, + .LOOP => return error.SymLinkLoop, + .NAMETOOLONG => return error.NameTooLong, + .NOENT => return error.FileNotFound, + .NOMEM => return error.SystemResources, + .NOTDIR => return error.NotDir, + .ILSEQ => return error.BadPathName, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } } -fn netInterfaceNameResolve( +const dirSetPermissions = switch (native_os) { + .windows => dirSetPermissionsWindows, + else => dirSetPermissionsPosix, +}; + +fn dirSetPermissionsWindows(userdata: ?*anyopaque, dir: Dir, permissions: Dir.Permissions) Dir.SetPermissionsError!void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + _ = dir; + _ = permissions; + @panic("TODO implement dirSetPermissionsWindows"); +} + +fn dirSetPermissionsPosix(userdata: ?*anyopaque, dir: Dir, permissions: Dir.Permissions) Dir.SetPermissionsError!void { + if (@sizeOf(Dir.Permissions) == 0) return; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + return setPermissionsPosix(dir.handle, permissions.toMode()); +} + +fn dirSetFilePermissions( userdata: ?*anyopaque, - name: *const net.Interface.Name, -) net.Interface.Name.ResolveError!net.Interface { - if (!have_networking) return error.InterfaceNotFound; + dir: Dir, + sub_path: []const u8, + permissions: Dir.Permissions, + options: Dir.SetFilePermissionsOptions, +) Dir.SetFilePermissionsError!void { + if (@sizeOf(Dir.Permissions) == 0) return; + if (is_windows) @panic("TODO implement dirSetFilePermissions windows"); const t: *Threaded = @ptrCast(@alignCast(userdata)); - if (native_os == .linux) { - const sock_fd = openSocketPosix(t, posix.AF.UNIX, .{ .mode = .dgram }) catch |err| switch (err) { - error.ProcessFdQuotaExceeded => return error.SystemResources, - error.SystemFdQuotaExceeded => return error.SystemResources, - error.AddressFamilyUnsupported => return error.Unexpected, - error.ProtocolUnsupportedBySystem => return error.Unexpected, - error.ProtocolUnsupportedByAddressFamily => return error.Unexpected, - error.SocketModeUnsupported => return error.Unexpected, - error.OptionUnsupported => return error.Unexpected, - else => |e| return e, - }; - defer posix.close(sock_fd); + var path_buffer: [posix.PATH_MAX]u8 = undefined; + const sub_path_posix = try pathToPosix(sub_path, &path_buffer); - var ifr: posix.ifreq = .{ - .ifrn = .{ .name = @bitCast(name.bytes) }, + const mode = permissions.toMode(); + const flags: u32 = if (!options.follow_symlinks) posix.AT.SYMLINK_NOFOLLOW else 0; + + return posixFchmodat(t, dir.handle, sub_path_posix, mode, flags); +} + +fn posixFchmodat( + t: *Threaded, + dir_fd: posix.fd_t, + path: [*:0]const u8, + mode: posix.mode_t, + flags: u32, +) Dir.SetFilePermissionsError!void { + // No special handling for linux is needed if we can use the libc fallback + // or `flags` is empty. Glibc only added the fallback in 2.32. + if (have_fchmodat_flags or flags == 0) { + const syscall: Syscall = try .start(); + while (true) { + const rc = if (have_fchmodat_flags or builtin.link_libc) + posix.system.fchmodat(dir_fd, path, mode, flags) + else + posix.system.fchmodat(dir_fd, path, mode); + switch (posix.errno(rc)) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .BADF => |err| return errnoBug(err), + .FAULT => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), + .ACCES => return error.AccessDenied, + .IO => return error.InputOutput, + .LOOP => return error.SymLinkLoop, + .MFILE => return error.ProcessFdQuotaExceeded, + .NAMETOOLONG => return error.NameTooLong, + .NFILE => return error.SystemFdQuotaExceeded, + .NOENT => return error.FileNotFound, + .NOTDIR => return error.FileNotFound, + .NOMEM => return error.SystemResources, + .OPNOTSUPP => return error.OperationUnsupported, + .PERM => return error.PermissionDenied, + .ROFS => return error.ReadOnlyFileSystem, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } + } + + if (@atomicLoad(UseFchmodat2, &t.use_fchmodat2, .monotonic) == .disabled) + return fchmodatFallback(dir_fd, path, mode); + + comptime assert(native_os == .linux); + + const syscall: Syscall = try .start(); + while (true) { + switch (std.os.linux.errno(std.os.linux.fchmodat2(dir_fd, path, mode, flags))) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .BADF => |err| return errnoBug(err), + .FAULT => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), + .ACCES => return error.AccessDenied, + .IO => return error.InputOutput, + .LOOP => return error.SymLinkLoop, + .NOENT => return error.FileNotFound, + .NOMEM => return error.SystemResources, + .NOTDIR => return error.FileNotFound, + .OPNOTSUPP => return error.OperationUnsupported, + .PERM => return error.PermissionDenied, + .ROFS => return error.ReadOnlyFileSystem, + .NOSYS => { + @atomicStore(UseFchmodat2, &t.use_fchmodat2, .disabled, .monotonic); + return fchmodatFallback(dir_fd, path, mode); + }, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn fchmodatFallback( + dir_fd: posix.fd_t, + path: [*:0]const u8, + mode: posix.mode_t, +) Dir.SetFilePermissionsError!void { + comptime assert(native_os == .linux); + + // Fallback to changing permissions using procfs: + // + // 1. Open `path` as a `PATH` descriptor. + // 2. Stat the fd and check if it isn't a symbolic link. + // 3. Generate the procfs reference to the fd via `/proc/self/fd/{fd}`. + // 4. Pass the procfs path to `chmod` with the `mode`. + const path_fd: posix.fd_t = fd: { + const syscall: Syscall = try .start(); + while (true) { + const rc = posix.system.openat(dir_fd, path, .{ + .PATH = true, + .NOFOLLOW = true, + .CLOEXEC = true, + }, @as(posix.mode_t, 0)); + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + break :fd @intCast(rc); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .FAULT => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), + .ACCES => return error.AccessDenied, + .PERM => return error.PermissionDenied, + .LOOP => return error.SymLinkLoop, + .MFILE => return error.ProcessFdQuotaExceeded, + .NAMETOOLONG => return error.NameTooLong, + .NFILE => return error.SystemFdQuotaExceeded, + .NOENT => return error.FileNotFound, + .NOMEM => return error.SystemResources, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } + }; + defer posix.close(path_fd); + + const path_mode = mode: { + const sys = if (statx_use_c) std.c else std.os.linux; + const syscall: Syscall = try .start(); + while (true) { + var statx = std.mem.zeroes(std.os.linux.Statx); + switch (sys.errno(sys.statx(path_fd, "", posix.AT.EMPTY_PATH, .{ .TYPE = true }, &statx))) { + .SUCCESS => { + syscall.finish(); + if (!statx.mask.TYPE) return error.Unexpected; + break :mode statx.mode; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ACCES => return error.AccessDenied, + .LOOP => return error.SymLinkLoop, + .NOMEM => return error.SystemResources, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } + }; + + // Even though we only wanted TYPE, the kernel can still fill in the additional bits. + if ((path_mode & posix.S.IFMT) == posix.S.IFLNK) + return error.OperationUnsupported; + + var procfs_buf: ["/proc/self/fd/-2147483648\x00".len]u8 = undefined; + const proc_path = std.fmt.bufPrintSentinel(&procfs_buf, "/proc/self/fd/{d}", .{path_fd}, 0) catch unreachable; + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.chmod(proc_path, mode))) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .NOENT => return error.OperationUnsupported, // procfs not mounted. + .BADF => |err| return errnoBug(err), + .FAULT => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), + .ACCES => return error.AccessDenied, + .IO => return error.InputOutput, + .LOOP => return error.SymLinkLoop, + .NOMEM => return error.SystemResources, + .NOTDIR => return error.FileNotFound, + .PERM => return error.PermissionDenied, + .ROFS => return error.ReadOnlyFileSystem, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +const dirSetOwner = switch (native_os) { + .windows => dirSetOwnerUnsupported, + else => dirSetOwnerPosix, +}; + +fn dirSetOwnerUnsupported(userdata: ?*anyopaque, dir: Dir, owner: ?File.Uid, group: ?File.Gid) Dir.SetOwnerError!void { + _ = userdata; + _ = dir; + _ = owner; + _ = group; + return error.Unexpected; +} + +fn dirSetOwnerPosix(userdata: ?*anyopaque, dir: Dir, owner: ?File.Uid, group: ?File.Gid) Dir.SetOwnerError!void { + if (!have_fchown) return error.Unexpected; // Unsupported OS, don't call this function. + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + const uid = owner orelse ~@as(posix.uid_t, 0); + const gid = group orelse ~@as(posix.gid_t, 0); + return posixFchown(dir.handle, uid, gid); +} + +fn posixFchown(fd: posix.fd_t, uid: posix.uid_t, gid: posix.gid_t) File.SetOwnerError!void { + comptime assert(have_fchown); + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.fchown(fd, uid, gid))) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .BADF => |err| return errnoBug(err), // likely fd refers to directory opened without `Dir.OpenOptions.iterate` + .FAULT => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), + .ACCES => return error.AccessDenied, + .IO => return error.InputOutput, + .LOOP => return error.SymLinkLoop, + .NOENT => return error.FileNotFound, + .NOMEM => return error.SystemResources, + .NOTDIR => return error.FileNotFound, + .PERM => return error.PermissionDenied, + .ROFS => return error.ReadOnlyFileSystem, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn dirSetFileOwner( + userdata: ?*anyopaque, + dir: Dir, + sub_path: []const u8, + owner: ?File.Uid, + group: ?File.Gid, + options: Dir.SetFileOwnerOptions, +) Dir.SetFileOwnerError!void { + if (!have_fchown) return error.Unexpected; // Unsupported OS, don't call this function. + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + var path_buffer: [posix.PATH_MAX]u8 = undefined; + const sub_path_posix = try pathToPosix(sub_path, &path_buffer); + + _ = dir; + _ = sub_path_posix; + _ = owner; + _ = group; + _ = options; + @panic("TODO implement dirSetFileOwner"); +} + +const fileSync = switch (native_os) { + .windows => fileSyncWindows, + .wasi => fileSyncWasi, + else => fileSyncPosix, +}; + +fn fileSyncWindows(userdata: ?*anyopaque, file: File) File.SyncError!void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + const syscall: Syscall = try .start(); + while (true) { + if (windows.kernel32.FlushFileBuffers(file.handle) != 0) { + return syscall.finish(); + } + switch (windows.GetLastError()) { + .SUCCESS => unreachable, // `FlushFileBuffers` returned nonzero + .INVALID_HANDLE => unreachable, + .ACCESS_DENIED => return syscall.fail(error.AccessDenied), // a sync was performed but the system couldn't update the access time + .UNEXP_NET_ERR => return syscall.fail(error.InputOutput), + .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + else => |err| { + syscall.finish(); + return windows.unexpectedError(err); + }, + } + } +} + +fn fileSyncPosix(userdata: ?*anyopaque, file: File) File.SyncError!void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.fsync(file.handle))) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .BADF => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), + .ROFS => |err| return errnoBug(err), + .IO => return error.InputOutput, + .NOSPC => return error.NoSpaceLeft, + .DQUOT => return error.DiskQuota, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn fileSyncWasi(userdata: ?*anyopaque, file: File) File.SyncError!void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + const syscall: Syscall = try .start(); + while (true) { + switch (std.os.wasi.fd_sync(file.handle)) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .BADF => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), + .ROFS => |err| return errnoBug(err), + .IO => return error.InputOutput, + .NOSPC => return error.NoSpaceLeft, + .DQUOT => return error.DiskQuota, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn fileIsTty(userdata: ?*anyopaque, file: File) Io.Cancelable!bool { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + return isTty(file); +} + +fn isTty(file: File) Io.Cancelable!bool { + if (is_windows) { + if (try isCygwinPty(file)) return true; + var out: windows.DWORD = undefined; + const syscall: Syscall = try .start(); + while (windows.kernel32.GetConsoleMode(file.handle, &out) == 0) { + switch (windows.GetLastError()) { + .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + else => { + syscall.finish(); + return false; + }, + } + } + syscall.finish(); + return true; + } + + if (builtin.link_libc) { + const syscall: Syscall = try .start(); + while (true) { + const rc = posix.system.isatty(file.handle); + switch (posix.errno(rc - 1)) { + .SUCCESS => { + syscall.finish(); + return true; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => { + syscall.finish(); + return false; + }, + } + } + } + + if (native_os == .wasi) { + var statbuf: std.os.wasi.fdstat_t = undefined; + const err = std.os.wasi.fd_fdstat_get(file.handle, &statbuf); + if (err != .SUCCESS) + return false; + + // A tty is a character device that we can't seek or tell on. + if (statbuf.fs_filetype != .CHARACTER_DEVICE) + return false; + if (statbuf.fs_rights_base.FD_SEEK or statbuf.fs_rights_base.FD_TELL) + return false; + + return true; + } + + if (native_os == .linux) { + const linux = std.os.linux; + const syscall: Syscall = try .start(); + while (true) { + var wsz: posix.winsize = undefined; + const fd: usize = @bitCast(@as(isize, file.handle)); + const rc = linux.syscall3(.ioctl, fd, linux.T.IOCGWINSZ, @intFromPtr(&wsz)); + switch (linux.errno(rc)) { + .SUCCESS => { + syscall.finish(); + return true; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => { + syscall.finish(); + return false; + }, + } + } + } + + @compileError("unimplemented"); +} + +fn fileEnableAnsiEscapeCodes(userdata: ?*anyopaque, file: File) File.EnableAnsiEscapeCodesError!void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + if (!is_windows) { + if (try supportsAnsiEscapeCodes(file)) return; + return error.NotTerminalDevice; + } + + // For Windows Terminal, VT Sequences processing is enabled by default. + var original_console_mode: windows.DWORD = 0; + + { + const syscall: Syscall = try .start(); + while (windows.kernel32.GetConsoleMode(file.handle, &original_console_mode) == 0) { + switch (windows.GetLastError()) { + .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + else => { + syscall.finish(); + if (try isCygwinPty(file)) return; + return error.NotTerminalDevice; + }, + } + } + syscall.finish(); + } + + if (original_console_mode & windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING != 0) return; + + // For Windows Console, VT Sequences processing support was added in Windows 10 build 14361, but disabled by default. + // https://devblogs.microsoft.com/commandline/tmux-support-arrives-for-bash-on-ubuntu-on-windows/ + // + // Note: In Microsoft's example for enabling virtual terminal processing, it + // shows attempting to enable `DISABLE_NEWLINE_AUTO_RETURN` as well: + // https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#example-of-enabling-virtual-terminal-processing + // This is avoided because in the old Windows Console, that flag causes \n (as opposed to \r\n) + // to behave unexpectedly (the cursor moves down 1 row but remains on the same column). + // Additionally, the default console mode in Windows Terminal does not have + // `DISABLE_NEWLINE_AUTO_RETURN` set, so by only enabling `ENABLE_VIRTUAL_TERMINAL_PROCESSING` + // we end up matching the mode of Windows Terminal. + const requested_console_modes = windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING; + const console_mode = original_console_mode | requested_console_modes; + + { + const syscall: Syscall = try .start(); + while (windows.kernel32.SetConsoleMode(file.handle, console_mode) == 0) { + switch (windows.GetLastError()) { + .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + else => { + syscall.finish(); + if (try isCygwinPty(file)) return; + return error.NotTerminalDevice; + }, + } + } + syscall.finish(); + } +} + +fn fileSupportsAnsiEscapeCodes(userdata: ?*anyopaque, file: File) Io.Cancelable!bool { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + return supportsAnsiEscapeCodes(file); +} + +fn supportsAnsiEscapeCodes(file: File) Io.Cancelable!bool { + if (is_windows) { + var console_mode: windows.DWORD = 0; + + const syscall: Syscall = try .start(); + while (windows.kernel32.GetConsoleMode(file.handle, &console_mode) == 0) { + switch (windows.GetLastError()) { + .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + else => { + syscall.finish(); + break; + }, + } + } else { + syscall.finish(); + if (console_mode & windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING != 0) { + return true; + } + } + + return isCygwinPty(file); + } + + if (native_os == .wasi) { + // WASI sanitizes stdout when fd is a tty so ANSI escape codes will not + // be interpreted as actual cursor commands, and stderr is always + // sanitized. + return false; + } + + if (try isTty(file)) return true; + + return false; +} + +fn isCygwinPty(file: File) Io.Cancelable!bool { + if (!is_windows) return false; + + const handle = file.handle; + + // If this is a MSYS2/cygwin pty, then it will be a named pipe with a name in one of these formats: + // msys-[...]-ptyN-[...] + // cygwin-[...]-ptyN-[...] + // + // Example: msys-1888ae32e00d56aa-pty0-to-master + + // First, just check that the handle is a named pipe. + // This allows us to avoid the more costly NtQueryInformationFile call + // for handles that aren't named pipes. + { + var io_status: windows.IO_STATUS_BLOCK = undefined; + var device_info: windows.FILE.FS_DEVICE_INFORMATION = undefined; + const syscall: Syscall = try .start(); + while (true) switch (windows.ntdll.NtQueryVolumeInformationFile( + handle, + &io_status, + &device_info, + @sizeOf(windows.FILE.FS_DEVICE_INFORMATION), + .Device, + )) { + .SUCCESS => break syscall.finish(), + .CANCELLED => { + try syscall.checkCancel(); + continue; + }, + else => { + syscall.finish(); + return false; + }, + }; + if (device_info.DeviceType.FileDevice != .NAMED_PIPE) return false; + } + + const name_bytes_offset = @offsetOf(windows.FILE.NAME_INFORMATION, "FileName"); + // `NAME_MAX` UTF-16 code units (2 bytes each) + // This buffer may not be long enough to handle *all* possible paths + // (PATH_MAX_WIDE would be necessary for that), but because we only care + // about certain paths and we know they must be within a reasonable length, + // we can use this smaller buffer and just return false on any error from + // NtQueryInformationFile. + const num_name_bytes = windows.MAX_PATH * 2; + var name_info_bytes align(@alignOf(windows.FILE.NAME_INFORMATION)) = [_]u8{0} ** (name_bytes_offset + num_name_bytes); + + var io_status_block: windows.IO_STATUS_BLOCK = undefined; + const syscall: Syscall = try .start(); + while (true) switch (windows.ntdll.NtQueryInformationFile( + handle, + &io_status_block, + &name_info_bytes, + @intCast(name_info_bytes.len), + .Name, + )) { + .SUCCESS => break syscall.finish(), + .CANCELLED => { + try syscall.checkCancel(); + continue; + }, + .INVALID_PARAMETER => unreachable, + else => { + syscall.finish(); + return false; + }, + }; + + const name_info: *const windows.FILE_NAME_INFO = @ptrCast(&name_info_bytes); + const name_bytes = name_info_bytes[name_bytes_offset .. name_bytes_offset + name_info.FileNameLength]; + const name_wide = std.mem.bytesAsSlice(u16, name_bytes); + // The name we get from NtQueryInformationFile will be prefixed with a '\', e.g. \msys-1888ae32e00d56aa-pty0-to-master + return (std.mem.startsWith(u16, name_wide, &[_]u16{ '\\', 'm', 's', 'y', 's', '-' }) or + std.mem.startsWith(u16, name_wide, &[_]u16{ '\\', 'c', 'y', 'g', 'w', 'i', 'n', '-' })) and + std.mem.indexOf(u16, name_wide, &[_]u16{ '-', 'p', 't', 'y' }) != null; +} + +fn fileSetLength(userdata: ?*anyopaque, file: File, length: u64) File.SetLengthError!void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + const signed_len: i64 = @bitCast(length); + if (signed_len < 0) return error.FileTooBig; // Avoid ambiguous EINVAL errors. + + if (is_windows) { + var io_status_block: windows.IO_STATUS_BLOCK = undefined; + const eof_info: windows.FILE.END_OF_FILE_INFORMATION = .{ + .EndOfFile = signed_len, + }; + + const syscall: Syscall = try .start(); + while (true) switch (windows.ntdll.NtSetInformationFile( + file.handle, + &io_status_block, + &eof_info, + @sizeOf(windows.FILE.END_OF_FILE_INFORMATION), + .EndOfFile, + )) { + .SUCCESS => return syscall.finish(), + .CANCELLED => { + try syscall.checkCancel(); + continue; + }, + .INVALID_HANDLE => |err| return syscall.ntstatusBug(err), // Handle not open for writing. + .ACCESS_DENIED => return syscall.fail(error.AccessDenied), + .USER_MAPPED_FILE => return syscall.fail(error.AccessDenied), + .INVALID_PARAMETER => return syscall.fail(error.FileTooBig), + else => |status| return syscall.unexpectedNtstatus(status), + }; + } + + if (native_os == .wasi and !builtin.link_libc) { + const syscall: Syscall = try .start(); + while (true) { + switch (std.os.wasi.fd_filestat_set_size(file.handle, length)) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .FBIG => return error.FileTooBig, + .IO => return error.InputOutput, + .PERM => return error.PermissionDenied, + .TXTBSY => return error.FileBusy, + .BADF => |err| return errnoBug(err), // Handle not open for writing + .INVAL => return error.NonResizable, + .NOTCAPABLE => return error.AccessDenied, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } + } + + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(ftruncate_sym(file.handle, signed_len))) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .FBIG => return error.FileTooBig, + .IO => return error.InputOutput, + .PERM => return error.PermissionDenied, + .TXTBSY => return error.FileBusy, + .BADF => |err| return errnoBug(err), // Handle not open for writing. + .INVAL => return error.NonResizable, // This is returned for /dev/null for example. + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn fileSetOwner(userdata: ?*anyopaque, file: File, owner: ?File.Uid, group: ?File.Gid) File.SetOwnerError!void { + if (!have_fchown) return error.Unexpected; // Unsupported OS, don't call this function. + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + const uid = owner orelse ~@as(posix.uid_t, 0); + const gid = group orelse ~@as(posix.gid_t, 0); + return posixFchown(file.handle, uid, gid); +} + +fn fileSetPermissions(userdata: ?*anyopaque, file: File, permissions: File.Permissions) File.SetPermissionsError!void { + if (@sizeOf(File.Permissions) == 0) return; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + switch (native_os) { + .windows => { + var io_status_block: windows.IO_STATUS_BLOCK = undefined; + const info: windows.FILE.BASIC_INFORMATION = .{ + .CreationTime = 0, + .LastAccessTime = 0, + .LastWriteTime = 0, + .ChangeTime = 0, + .FileAttributes = permissions.toAttributes(), + }; + const syscall: Syscall = try .start(); + while (true) switch (windows.ntdll.NtSetInformationFile( + file.handle, + &io_status_block, + &info, + @sizeOf(windows.FILE.BASIC_INFORMATION), + .Basic, + )) { + .SUCCESS => return syscall.finish(), + .CANCELLED => { + try syscall.checkCancel(); + continue; + }, + .INVALID_HANDLE => |err| return syscall.ntstatusBug(err), + .ACCESS_DENIED => return syscall.fail(error.AccessDenied), + else => |status| return syscall.unexpectedNtstatus(status), + }; + }, + .wasi => return error.Unexpected, // Unsupported OS. + else => return setPermissionsPosix(file.handle, permissions.toMode()), + } +} + +fn setPermissionsPosix(fd: posix.fd_t, mode: posix.mode_t) File.SetPermissionsError!void { + comptime assert(have_fchmod); + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.fchmod(fd, mode))) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .BADF => |err| return errnoBug(err), + .FAULT => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), + .ACCES => return error.AccessDenied, + .IO => return error.InputOutput, + .LOOP => return error.SymLinkLoop, + .NOENT => return error.FileNotFound, + .NOMEM => return error.SystemResources, + .NOTDIR => return error.FileNotFound, + .PERM => return error.PermissionDenied, + .ROFS => return error.ReadOnlyFileSystem, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn dirSetTimestamps( + userdata: ?*anyopaque, + dir: Dir, + sub_path: []const u8, + options: Dir.SetTimestampsOptions, +) Dir.SetTimestampsError!void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + if (is_windows) { + @panic("TODO implement dirSetTimestamps windows"); + } + + if (native_os == .wasi and !builtin.link_libc) { + @panic("TODO implement dirSetTimestamps wasi"); + } + + var times_buffer: [2]posix.timespec = undefined; + const times = if (options.modify_timestamp == .now and options.access_timestamp == .now) null else p: { + times_buffer = .{ + setTimestampToPosix(options.access_timestamp), + setTimestampToPosix(options.modify_timestamp), + }; + break :p ×_buffer; + }; + + const flags: u32 = if (!options.follow_symlinks) posix.AT.SYMLINK_NOFOLLOW else 0; + + var path_buffer: [posix.PATH_MAX]u8 = undefined; + const sub_path_posix = try pathToPosix(sub_path, &path_buffer); + + const syscall: Syscall = try .start(); + while (true) switch (posix.errno(posix.system.utimensat(dir.handle, sub_path_posix, times, flags))) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); + continue; + }, + .BADF => |err| return syscall.errnoBug(err), // always a race condition + .FAULT => |err| return syscall.errnoBug(err), + .INVAL => |err| return syscall.errnoBug(err), + .ACCES => return syscall.fail(error.AccessDenied), + .PERM => return syscall.fail(error.PermissionDenied), + .ROFS => return syscall.fail(error.ReadOnlyFileSystem), + else => |err| return syscall.unexpectedErrno(err), + }; +} + +fn fileSetTimestamps( + userdata: ?*anyopaque, + file: File, + options: File.SetTimestampsOptions, +) File.SetTimestampsError!void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + if (is_windows) { + var access_time_buffer: windows.FILETIME = undefined; + var modify_time_buffer: windows.FILETIME = undefined; + var system_time_buffer: windows.LARGE_INTEGER = undefined; + + if (options.access_timestamp == .now or options.modify_timestamp == .now) { + system_time_buffer = windows.ntdll.RtlGetSystemTimePrecise(); + } + + const access_ptr = switch (options.access_timestamp) { + .unchanged => null, + .now => @panic("TODO do SystemTimeToFileTime logic here"), + .new => |ts| p: { + access_time_buffer = windows.nanoSecondsToFileTime(ts); + break :p &access_time_buffer; + }, + }; + + const modify_ptr = switch (options.modify_timestamp) { + .unchanged => null, + .now => @panic("TODO do SystemTimeToFileTime logic here"), + .new => |ts| p: { + modify_time_buffer = windows.nanoSecondsToFileTime(ts); + break :p &modify_time_buffer; + }, + }; + + // https://github.com/ziglang/zig/issues/1840 + const syscall: Syscall = try .start(); + while (true) { + switch (windows.kernel32.SetFileTime(file.handle, null, access_ptr, modify_ptr)) { + 0 => switch (windows.GetLastError()) { + .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + else => |err| { + syscall.finish(); + return windows.unexpectedError(err); + }, + }, + else => return syscall.finish(), + } + } + } + + if (native_os == .wasi and !builtin.link_libc) { + var atime: std.os.wasi.timestamp_t = 0; + var mtime: std.os.wasi.timestamp_t = 0; + var flags: std.os.wasi.fstflags_t = .{}; + + switch (options.access_timestamp) { + .unchanged => {}, + .now => flags.ATIM_NOW = true, + .new => |ts| { + atime = timestampToPosix(ts.nanoseconds).toTimestamp(); + flags.ATIM = true; + }, + } + + switch (options.modify_timestamp) { + .unchanged => {}, + .now => flags.MTIM_NOW = true, + .new => |ts| { + mtime = timestampToPosix(ts.nanoseconds).toTimestamp(); + flags.MTIM = true; + }, + } + + const syscall: Syscall = try .start(); + while (true) switch (std.os.wasi.fd_filestat_set_times(file.handle, atime, mtime, flags)) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); + continue; + }, + .BADF => |err| return syscall.errnoBug(err), // File descriptor use-after-free. + .FAULT => |err| return syscall.errnoBug(err), + .INVAL => |err| return syscall.errnoBug(err), + .ACCES => return syscall.fail(error.AccessDenied), + .PERM => return syscall.fail(error.PermissionDenied), + .ROFS => return syscall.fail(error.ReadOnlyFileSystem), + else => |err| return syscall.unexpectedErrno(err), + }; + } + + var times_buffer: [2]posix.timespec = undefined; + const times = if (options.modify_timestamp == .now and options.access_timestamp == .now) null else p: { + times_buffer = .{ + setTimestampToPosix(options.access_timestamp), + setTimestampToPosix(options.modify_timestamp), + }; + break :p ×_buffer; + }; + + const syscall: Syscall = try .start(); + while (true) switch (posix.errno(posix.system.futimens(file.handle, times))) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); + continue; + }, + .BADF => |err| return syscall.errnoBug(err), // always a race condition + .FAULT => |err| return syscall.errnoBug(err), + .INVAL => |err| return syscall.errnoBug(err), + .ACCES => return syscall.fail(error.AccessDenied), + .PERM => return syscall.fail(error.PermissionDenied), + .ROFS => return syscall.fail(error.ReadOnlyFileSystem), + else => |err| return syscall.unexpectedErrno(err), + }; +} + +const windows_lock_range_off: windows.LARGE_INTEGER = 0; +const windows_lock_range_len: windows.LARGE_INTEGER = 1; + +fn fileLock(userdata: ?*anyopaque, file: File, lock: File.Lock) File.LockError!void { + if (native_os == .wasi) return error.FileLocksUnsupported; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + if (is_windows) { + const exclusive = switch (lock) { + .none => { + // To match the non-Windows behavior, unlock + var io_status_block: windows.IO_STATUS_BLOCK = undefined; + while (true) switch (windows.ntdll.NtUnlockFile( + file.handle, + &io_status_block, + &windows_lock_range_off, + &windows_lock_range_len, + 0, + )) { + .SUCCESS => return, + .CANCELLED => continue, + .RANGE_NOT_LOCKED => return, + .ACCESS_VIOLATION => |err| return windows.statusBug(err), // bad io_status_block pointer + else => |status| return windows.unexpectedStatus(status), + }; + }, + .shared => false, + .exclusive => true, + }; + var io_status_block: windows.IO_STATUS_BLOCK = undefined; + const syscall: Syscall = try .start(); + while (true) switch (windows.ntdll.NtLockFile( + file.handle, + null, + null, + null, + &io_status_block, + &windows_lock_range_off, + &windows_lock_range_len, + null, + windows.FALSE, + @intFromBool(exclusive), + )) { + .SUCCESS => return syscall.finish(), + .CANCELLED => { + try syscall.checkCancel(); + continue; + }, + .INSUFFICIENT_RESOURCES => return syscall.fail(error.SystemResources), + .LOCK_NOT_GRANTED => |err| return syscall.ntstatusBug(err), // passed FailImmediately=false + .ACCESS_VIOLATION => |err| return syscall.ntstatusBug(err), // bad io_status_block pointer + else => |status| return syscall.unexpectedNtstatus(status), + }; + } + + const operation: i32 = switch (lock) { + .none => posix.LOCK.UN, + .shared => posix.LOCK.SH, + .exclusive => posix.LOCK.EX, + }; + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.flock(file.handle, operation))) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .BADF => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), // invalid parameters + .NOLCK => return error.SystemResources, + .AGAIN => |err| return errnoBug(err), + .OPNOTSUPP => return error.FileLocksUnsupported, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn fileTryLock(userdata: ?*anyopaque, file: File, lock: File.Lock) File.LockError!bool { + if (native_os == .wasi) return error.FileLocksUnsupported; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + if (is_windows) { + const exclusive = switch (lock) { + .none => { + // To match the non-Windows behavior, unlock + var io_status_block: windows.IO_STATUS_BLOCK = undefined; + while (true) switch (windows.ntdll.NtUnlockFile( + file.handle, + &io_status_block, + &windows_lock_range_off, + &windows_lock_range_len, + 0, + )) { + .SUCCESS => return true, + .CANCELLED => continue, + .RANGE_NOT_LOCKED => return false, + .ACCESS_VIOLATION => |err| return windows.statusBug(err), // bad io_status_block pointer + else => |status| return windows.unexpectedStatus(status), + }; + }, + .shared => false, + .exclusive => true, + }; + var io_status_block: windows.IO_STATUS_BLOCK = undefined; + const syscall: Syscall = try .start(); + while (true) switch (windows.ntdll.NtLockFile( + file.handle, + null, + null, + null, + &io_status_block, + &windows_lock_range_off, + &windows_lock_range_len, + null, + windows.TRUE, + @intFromBool(exclusive), + )) { + .SUCCESS => { + syscall.finish(); + return true; + }, + .LOCK_NOT_GRANTED => { + syscall.finish(); + return false; + }, + .CANCELLED => { + try syscall.checkCancel(); + continue; + }, + .INSUFFICIENT_RESOURCES => return syscall.fail(error.SystemResources), + .ACCESS_VIOLATION => |err| return syscall.ntstatusBug(err), // bad io_status_block pointer + else => |status| return syscall.unexpectedNtstatus(status), + }; + } + + const operation: i32 = switch (lock) { + .none => posix.LOCK.UN, + .shared => posix.LOCK.SH | posix.LOCK.NB, + .exclusive => posix.LOCK.EX | posix.LOCK.NB, + }; + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.flock(file.handle, operation))) { + .SUCCESS => { + syscall.finish(); + return true; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + .AGAIN => { + syscall.finish(); + return false; + }, + else => |e| { + syscall.finish(); + switch (e) { + .BADF => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), // invalid parameters + .NOLCK => return error.SystemResources, + .OPNOTSUPP => return error.FileLocksUnsupported, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn fileUnlock(userdata: ?*anyopaque, file: File) void { + if (native_os == .wasi) return; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + if (is_windows) { + var io_status_block: windows.IO_STATUS_BLOCK = undefined; + while (true) switch (windows.ntdll.NtUnlockFile( + file.handle, + &io_status_block, + &windows_lock_range_off, + &windows_lock_range_len, + 0, + )) { + .SUCCESS => return, + .CANCELLED => continue, + .RANGE_NOT_LOCKED => if (is_debug) unreachable else return, // Function asserts unlocked. + .ACCESS_VIOLATION => if (is_debug) unreachable else return, // bad io_status_block pointer + else => if (is_debug) unreachable else return, // Resource deallocation must succeed. + }; + } + + while (true) { + switch (posix.errno(posix.system.flock(file.handle, posix.LOCK.UN))) { + .SUCCESS => return, + .CANCELED, .INTR => continue, + .AGAIN => return assert(!is_debug), // unlocking can't block + .BADF => return assert(!is_debug), // File descriptor used after closed. + .INVAL => return assert(!is_debug), // invalid parameters + .NOLCK => return assert(!is_debug), // Resource deallocation. + .OPNOTSUPP => return assert(!is_debug), // We already got the lock. + else => return assert(!is_debug), // Resource deallocation must succeed. + } + } +} + +fn fileDowngradeLock(userdata: ?*anyopaque, file: File) File.DowngradeLockError!void { + if (native_os == .wasi) return; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + if (is_windows) { + // On Windows it works like a semaphore + exclusivity flag. To + // implement this function, we first obtain another lock in shared + // mode. This changes the exclusivity flag, but increments the + // semaphore to 2. So we follow up with an NtUnlockFile which + // decrements the semaphore but does not modify the exclusivity flag. + var io_status_block: windows.IO_STATUS_BLOCK = undefined; + const syscall: Syscall = try .start(); + while (true) switch (windows.ntdll.NtLockFile( + file.handle, + null, + null, + null, + &io_status_block, + &windows_lock_range_off, + &windows_lock_range_len, + null, + windows.TRUE, + windows.FALSE, + )) { + .SUCCESS => break syscall.finish(), + .CANCELLED => { + try syscall.checkCancel(); + continue; + }, + .INSUFFICIENT_RESOURCES => |err| return syscall.ntstatusBug(err), + .LOCK_NOT_GRANTED => |err| return syscall.ntstatusBug(err), // File was not locked in exclusive mode. + .ACCESS_VIOLATION => |err| return syscall.ntstatusBug(err), // bad io_status_block pointer + else => |status| return syscall.unexpectedNtstatus(status), + }; + while (true) switch (windows.ntdll.NtUnlockFile( + file.handle, + &io_status_block, + &windows_lock_range_off, + &windows_lock_range_len, + 0, + )) { + .SUCCESS => return, + .CANCELLED => continue, + .RANGE_NOT_LOCKED => if (is_debug) unreachable else return, // File was not locked. + .ACCESS_VIOLATION => if (is_debug) unreachable else return, // bad io_status_block pointer + else => if (is_debug) unreachable else return, // Resource deallocation must succeed. + }; + } + + const operation = posix.LOCK.SH | posix.LOCK.NB; + + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.flock(file.handle, operation))) { + .SUCCESS => { + syscall.finish(); + return; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .AGAIN => |err| return errnoBug(err), // File was not locked in exclusive mode. + .BADF => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), // invalid parameters + .NOLCK => |err| return errnoBug(err), // Lock already obtained. + .OPNOTSUPP => |err| return errnoBug(err), // Lock already obtained. + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn dirOpenDirWasi( + userdata: ?*anyopaque, + dir: Dir, + sub_path: []const u8, + options: Dir.OpenOptions, +) Dir.OpenError!Dir { + if (builtin.link_libc) return dirOpenDirPosix(userdata, dir, sub_path, options); + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + const wasi = std.os.wasi; + + var base: std.os.wasi.rights_t = .{ + .FD_FILESTAT_GET = true, + .FD_FDSTAT_SET_FLAGS = true, + .FD_FILESTAT_SET_TIMES = true, + }; + if (options.access_sub_paths) { + base.FD_READDIR = true; + base.PATH_CREATE_DIRECTORY = true; + base.PATH_CREATE_FILE = true; + base.PATH_LINK_SOURCE = true; + base.PATH_LINK_TARGET = true; + base.PATH_OPEN = true; + base.PATH_READLINK = true; + base.PATH_RENAME_SOURCE = true; + base.PATH_RENAME_TARGET = true; + base.PATH_FILESTAT_GET = true; + base.PATH_FILESTAT_SET_SIZE = true; + base.PATH_FILESTAT_SET_TIMES = true; + base.PATH_SYMLINK = true; + base.PATH_REMOVE_DIRECTORY = true; + base.PATH_UNLINK_FILE = true; + } + + const lookup_flags: wasi.lookupflags_t = .{ .SYMLINK_FOLLOW = options.follow_symlinks }; + const oflags: wasi.oflags_t = .{ .DIRECTORY = true }; + const fdflags: wasi.fdflags_t = .{}; + var fd: posix.fd_t = undefined; + const syscall: Syscall = try .start(); + while (true) { + switch (wasi.path_open(dir.handle, lookup_flags, sub_path.ptr, sub_path.len, oflags, base, base, fdflags, &fd)) { + .SUCCESS => { + syscall.finish(); + return .{ .handle = fd }; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .FAULT => |err| return errnoBug(err), + .INVAL => return error.BadPathName, + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .ACCES => return error.AccessDenied, + .LOOP => return error.SymLinkLoop, + .MFILE => return error.ProcessFdQuotaExceeded, + .NAMETOOLONG => return error.NameTooLong, + .NFILE => return error.SystemFdQuotaExceeded, + .NODEV => return error.NoDevice, + .NOENT => return error.FileNotFound, + .NOMEM => return error.SystemResources, + .NOTDIR => return error.NotDir, + .PERM => return error.PermissionDenied, + .NOTCAPABLE => return error.AccessDenied, + .ILSEQ => return error.BadPathName, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn dirHardLink( + userdata: ?*anyopaque, + old_dir: Dir, + old_sub_path: []const u8, + new_dir: Dir, + new_sub_path: []const u8, + options: Dir.HardLinkOptions, +) Dir.HardLinkError!void { + if (is_windows) return error.OperationUnsupported; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + if (native_os == .wasi and !builtin.link_libc) { + const flags: std.os.wasi.lookupflags_t = .{ + .SYMLINK_FOLLOW = options.follow_symlinks, + }; + const syscall: Syscall = try .start(); + while (true) { + switch (std.os.wasi.path_link( + old_dir.handle, + flags, + old_sub_path.ptr, + old_sub_path.len, + new_dir.handle, + new_sub_path.ptr, + new_sub_path.len, + )) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ACCES => return error.AccessDenied, + .DQUOT => return error.DiskQuota, + .EXIST => return error.PathAlreadyExists, + .FAULT => |err| return errnoBug(err), + .IO => return error.HardwareFailure, + .LOOP => return error.SymLinkLoop, + .MLINK => return error.LinkQuotaExceeded, + .NAMETOOLONG => return error.NameTooLong, + .NOENT => return error.FileNotFound, + .NOMEM => return error.SystemResources, + .NOSPC => return error.NoSpaceLeft, + .NOTDIR => return error.NotDir, + .PERM => return error.PermissionDenied, + .ROFS => return error.ReadOnlyFileSystem, + .XDEV => return error.CrossDevice, + .INVAL => |err| return errnoBug(err), + .ILSEQ => return error.BadPathName, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } + } + + var old_path_buffer: [posix.PATH_MAX]u8 = undefined; + var new_path_buffer: [posix.PATH_MAX]u8 = undefined; + + const old_sub_path_posix = try pathToPosix(old_sub_path, &old_path_buffer); + const new_sub_path_posix = try pathToPosix(new_sub_path, &new_path_buffer); + + const flags: u32 = if (options.follow_symlinks) posix.AT.SYMLINK_FOLLOW else 0; + return linkat(old_dir.handle, old_sub_path_posix, new_dir.handle, new_sub_path_posix, flags); +} + +fn fileClose(userdata: ?*anyopaque, files: []const File) void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + for (files) |file| posix.close(file.handle); +} + +const fileReadStreaming = switch (native_os) { + .windows => fileReadStreamingWindows, + else => fileReadStreamingPosix, +}; + +fn fileReadStreamingPosix(userdata: ?*anyopaque, file: File, data: []const []u8) File.Reader.Error!usize { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + var iovecs_buffer: [max_iovecs_len]posix.iovec = undefined; + var i: usize = 0; + for (data) |buf| { + if (iovecs_buffer.len - i == 0) break; + if (buf.len != 0) { + iovecs_buffer[i] = .{ .base = buf.ptr, .len = buf.len }; + i += 1; + } + } + if (i == 0) return 0; + const dest = iovecs_buffer[0..i]; + assert(dest[0].len > 0); + + if (native_os == .wasi and !builtin.link_libc) { + const syscall: Syscall = try .start(); + while (true) { + var nread: usize = undefined; + switch (std.os.wasi.fd_read(file.handle, dest.ptr, dest.len, &nread)) { + .SUCCESS => { + syscall.finish(); + return nread; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .INVAL => |err| return errnoBug(err), + .FAULT => |err| return errnoBug(err), + .BADF => return error.NotOpenForReading, // File operation on directory. + .IO => return error.InputOutput, + .ISDIR => return error.IsDir, + .NOBUFS => return error.SystemResources, + .NOMEM => return error.SystemResources, + .NOTCONN => return error.SocketUnconnected, + .CONNRESET => return error.ConnectionResetByPeer, + .TIMEDOUT => return error.Timeout, + .NOTCAPABLE => return error.AccessDenied, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } + } + + const syscall: Syscall = try .start(); + while (true) { + const rc = posix.system.readv(file.handle, dest.ptr, @intCast(dest.len)); + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + return @intCast(rc); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .INVAL => |err| return errnoBug(err), + .FAULT => |err| return errnoBug(err), + .AGAIN => return error.WouldBlock, + .BADF => |err| { + if (native_os == .wasi) return error.NotOpenForReading; // File operation on directory. + return errnoBug(err); // File descriptor used after closed. + }, + .IO => return error.InputOutput, + .ISDIR => return error.IsDir, + .NOBUFS => return error.SystemResources, + .NOMEM => return error.SystemResources, + .NOTCONN => return error.SocketUnconnected, + .CONNRESET => return error.ConnectionResetByPeer, + .TIMEDOUT => return error.Timeout, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn fileReadStreamingWindows(userdata: ?*anyopaque, file: File, data: []const []u8) File.Reader.Error!usize { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + const DWORD = windows.DWORD; + var index: usize = 0; + while (index < data.len and data[index].len == 0) index += 1; + if (index == data.len) return 0; + const buffer = data[index]; + const want_read_count: DWORD = @min(std.math.maxInt(DWORD), buffer.len); + + const syscall: Syscall = try .start(); + while (true) { + var n: DWORD = undefined; + if (windows.kernel32.ReadFile(file.handle, buffer.ptr, want_read_count, &n, null) != 0) { + syscall.finish(); + return n; + } + switch (windows.GetLastError()) { + .IO_PENDING => |err| { + syscall.finish(); + return windows.errorBug(err); + }, + .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + .BROKEN_PIPE, .HANDLE_EOF => { + syscall.finish(); + return 0; + }, + .NETNAME_DELETED => return syscall.fail(error.ConnectionResetByPeer), + .LOCK_VIOLATION => return syscall.fail(error.LockViolation), + .ACCESS_DENIED => return syscall.fail(error.AccessDenied), + .INVALID_HANDLE => return syscall.fail(error.NotOpenForReading), + else => |err| { + syscall.finish(); + return windows.unexpectedError(err); + }, + } + } +} + +fn fileReadPositionalPosix(userdata: ?*anyopaque, file: File, data: []const []u8, offset: u64) File.ReadPositionalError!usize { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + if (!have_preadv) @compileError("TODO implement fileReadPositionalPosix for cursed operating systems that don't support preadv (it's only Haiku)"); + + var iovecs_buffer: [max_iovecs_len]posix.iovec = undefined; + var i: usize = 0; + for (data) |buf| { + if (iovecs_buffer.len - i == 0) break; + if (buf.len != 0) { + iovecs_buffer[i] = .{ .base = buf.ptr, .len = buf.len }; + i += 1; + } + } + if (i == 0) return 0; + const dest = iovecs_buffer[0..i]; + assert(dest[0].len > 0); + + if (native_os == .wasi and !builtin.link_libc) { + const syscall: Syscall = try .start(); + while (true) { + var nread: usize = undefined; + switch (std.os.wasi.fd_pread(file.handle, dest.ptr, dest.len, offset, &nread)) { + .SUCCESS => { + syscall.finish(); + return nread; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .INVAL => |err| return errnoBug(err), + .FAULT => |err| return errnoBug(err), + .AGAIN => |err| return errnoBug(err), + .BADF => return error.NotOpenForReading, // File operation on directory. + .IO => return error.InputOutput, + .ISDIR => return error.IsDir, + .NOBUFS => return error.SystemResources, + .NOMEM => return error.SystemResources, + .NOTCONN => return error.SocketUnconnected, + .CONNRESET => return error.ConnectionResetByPeer, + .TIMEDOUT => return error.Timeout, + .NXIO => return error.Unseekable, + .SPIPE => return error.Unseekable, + .OVERFLOW => return error.Unseekable, + .NOTCAPABLE => return error.AccessDenied, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } + } + + const syscall: Syscall = try .start(); + while (true) { + const rc = preadv_sym(file.handle, dest.ptr, @intCast(dest.len), @bitCast(offset)); + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + return @bitCast(rc); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .INVAL => |err| return errnoBug(err), + .FAULT => |err| return errnoBug(err), + .AGAIN => return error.WouldBlock, + .BADF => |err| { + if (native_os == .wasi) return error.NotOpenForReading; // File operation on directory. + return errnoBug(err); // File descriptor used after closed. + }, + .IO => return error.InputOutput, + .ISDIR => return error.IsDir, + .NOBUFS => return error.SystemResources, + .NOMEM => return error.SystemResources, + .NOTCONN => return error.SocketUnconnected, + .CONNRESET => return error.ConnectionResetByPeer, + .TIMEDOUT => return error.Timeout, + .NXIO => return error.Unseekable, + .SPIPE => return error.Unseekable, + .OVERFLOW => return error.Unseekable, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +const fileReadPositional = switch (native_os) { + .windows => fileReadPositionalWindows, + else => fileReadPositionalPosix, +}; + +fn fileReadPositionalWindows(userdata: ?*anyopaque, file: File, data: []const []u8, offset: u64) File.ReadPositionalError!usize { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + const DWORD = windows.DWORD; + + var index: usize = 0; + while (index < data.len and data[index].len == 0) index += 1; + if (index == data.len) return 0; + const buffer = data[index]; + const want_read_count: DWORD = @min(std.math.maxInt(DWORD), buffer.len); + + var overlapped: windows.OVERLAPPED = .{ + .Internal = 0, + .InternalHigh = 0, + .DUMMYUNIONNAME = .{ + .DUMMYSTRUCTNAME = .{ + .Offset = @truncate(offset), + .OffsetHigh = @truncate(offset >> 32), + }, + }, + .hEvent = null, + }; + + const syscall: Syscall = try .start(); + while (true) { + var n: DWORD = undefined; + if (windows.kernel32.ReadFile(file.handle, buffer.ptr, want_read_count, &n, &overlapped) != 0) { + syscall.finish(); + return n; + } + switch (windows.GetLastError()) { + .IO_PENDING => |err| { + syscall.finish(); + return windows.errorBug(err); + }, + .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + .BROKEN_PIPE, .HANDLE_EOF => { + syscall.finish(); + return 0; + }, + .NETNAME_DELETED => return syscall.fail(error.ConnectionResetByPeer), + .LOCK_VIOLATION => return syscall.fail(error.LockViolation), + .ACCESS_DENIED => return syscall.fail(error.AccessDenied), + .INVALID_HANDLE => return syscall.fail(error.NotOpenForReading), + else => |err| { + syscall.finish(); + return windows.unexpectedError(err); + }, + } + } +} + +fn fileSeekBy(userdata: ?*anyopaque, file: File, offset: i64) File.SeekError!void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + const fd = file.handle; + + if (native_os == .linux and !builtin.link_libc and @sizeOf(usize) == 4) { + var result: u64 = undefined; + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.llseek(fd, @bitCast(offset), &result, posix.SEEK.CUR))) { + .SUCCESS => { + syscall.finish(); + return; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .INVAL => return error.Unseekable, + .OVERFLOW => return error.Unseekable, + .SPIPE => return error.Unseekable, + .NXIO => return error.Unseekable, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } + } + + if (native_os == .windows) { + const syscall: Syscall = try .start(); + while (true) { + if (windows.kernel32.SetFilePointerEx(fd, offset, null, windows.FILE_CURRENT) != 0) { + return syscall.finish(); + } + switch (windows.GetLastError()) { + .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + .INVALID_FUNCTION => return syscall.fail(error.Unseekable), + .NEGATIVE_SEEK => return syscall.fail(error.Unseekable), + .INVALID_PARAMETER => unreachable, + .INVALID_HANDLE => unreachable, + else => |err| { + syscall.finish(); + return windows.unexpectedError(err); + }, + } + } + } + + if (native_os == .wasi and !builtin.link_libc) { + var new_offset: std.os.wasi.filesize_t = undefined; + const syscall: Syscall = try .start(); + while (true) { + switch (std.os.wasi.fd_seek(fd, offset, .CUR, &new_offset)) { + .SUCCESS => { + syscall.finish(); + return; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .INVAL => return error.Unseekable, + .OVERFLOW => return error.Unseekable, + .SPIPE => return error.Unseekable, + .NXIO => return error.Unseekable, + .NOTCAPABLE => return error.AccessDenied, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } + } + + if (posix.SEEK == void) return error.Unseekable; + + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(lseek_sym(fd, offset, posix.SEEK.CUR))) { + .SUCCESS => { + syscall.finish(); + return; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .INVAL => return error.Unseekable, + .OVERFLOW => return error.Unseekable, + .SPIPE => return error.Unseekable, + .NXIO => return error.Unseekable, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn fileSeekTo(userdata: ?*anyopaque, file: File, offset: u64) File.SeekError!void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + const fd = file.handle; + + if (native_os == .windows) { + // "The starting point is zero or the beginning of the file. If [FILE_BEGIN] + // is specified, then the liDistanceToMove parameter is interpreted as an unsigned value." + // https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-setfilepointerex + const ipos: windows.LARGE_INTEGER = @bitCast(offset); + + const syscall: Syscall = try .start(); + while (true) { + if (windows.kernel32.SetFilePointerEx(fd, ipos, null, windows.FILE_BEGIN) != 0) { + return syscall.finish(); + } + switch (windows.GetLastError()) { + .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + .INVALID_FUNCTION => return syscall.fail(error.Unseekable), + .NEGATIVE_SEEK => return syscall.fail(error.Unseekable), + .INVALID_PARAMETER => unreachable, + .INVALID_HANDLE => unreachable, + else => |err| { + syscall.finish(); + return windows.unexpectedError(err); + }, + } + } + } + + if (native_os == .wasi and !builtin.link_libc) { + const syscall: Syscall = try .start(); + while (true) { + var new_offset: std.os.wasi.filesize_t = undefined; + switch (std.os.wasi.fd_seek(fd, @bitCast(offset), .SET, &new_offset)) { + .SUCCESS => { + syscall.finish(); + return; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .INVAL => return error.Unseekable, + .OVERFLOW => return error.Unseekable, + .SPIPE => return error.Unseekable, + .NXIO => return error.Unseekable, + .NOTCAPABLE => return error.AccessDenied, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } + } + + if (posix.SEEK == void) return error.Unseekable; + + return posixSeekTo(fd, offset); +} + +fn posixSeekTo(fd: posix.fd_t, offset: u64) File.SeekError!void { + if (native_os == .linux and !builtin.link_libc and @sizeOf(usize) == 4) { + const syscall: Syscall = try .start(); + while (true) { + var result: u64 = undefined; + switch (posix.errno(posix.system.llseek(fd, offset, &result, posix.SEEK.SET))) { + .SUCCESS => { + syscall.finish(); + return; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .INVAL => return error.Unseekable, + .OVERFLOW => return error.Unseekable, + .SPIPE => return error.Unseekable, + .NXIO => return error.Unseekable, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } + } + + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(lseek_sym(fd, @bitCast(offset), posix.SEEK.SET))) { + .SUCCESS => { + syscall.finish(); + return; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .INVAL => return error.Unseekable, + .OVERFLOW => return error.Unseekable, + .SPIPE => return error.Unseekable, + .NXIO => return error.Unseekable, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn processExecutableOpen(userdata: ?*anyopaque, flags: File.OpenFlags) process.OpenExecutableError!File { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + switch (native_os) { + .wasi => return error.OperationUnsupported, + .linux, .serenity => return dirOpenFilePosix(t, .{ .handle = posix.AT.FDCWD }, "/proc/self/exe", flags), + .windows => { + // If ImagePathName is a symlink, then it will contain the path of the symlink, + // not the path that the symlink points to. However, because we are opening + // the file, we can let the openFileW call follow the symlink for us. + const image_path_unicode_string = &windows.peb().ProcessParameters.ImagePathName; + const image_path_name = image_path_unicode_string.Buffer.?[0 .. image_path_unicode_string.Length / 2 :0]; + const prefixed_path_w = try windows.wToPrefixedFileW(null, image_path_name); + return dirOpenFileWtf16(null, prefixed_path_w.span(), flags); + }, + .driverkit, + .ios, + .maccatalyst, + .macos, + .tvos, + .visionos, + .watchos, + => { + // _NSGetExecutablePath() returns a path that might be a symlink to + // the executable. Here it does not matter since we open it. + var symlink_path_buf: [posix.PATH_MAX + 1]u8 = undefined; + var n: u32 = symlink_path_buf.len; + const rc = std.c._NSGetExecutablePath(&symlink_path_buf, &n); + if (rc != 0) return error.NameTooLong; + const symlink_path = std.mem.sliceTo(&symlink_path_buf, 0); + return dirOpenFilePosix(t, .cwd(), symlink_path, flags); + }, + else => { + var buffer: [Dir.max_path_bytes]u8 = undefined; + const n = try processExecutablePath(t, &buffer); + buffer[n] = 0; + const executable_path = buffer[0..n :0]; + return dirOpenFilePosix(t, .cwd(), executable_path, flags); + }, + } +} + +fn processExecutablePath(userdata: ?*anyopaque, out_buffer: []u8) process.ExecutablePathError!usize { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + + switch (native_os) { + .driverkit, + .ios, + .maccatalyst, + .macos, + .tvos, + .visionos, + .watchos, + => { + // _NSGetExecutablePath() returns a path that might be a symlink to + // the executable. + var symlink_path_buf: [posix.PATH_MAX + 1]u8 = undefined; + var n: u32 = symlink_path_buf.len; + const rc = std.c._NSGetExecutablePath(&symlink_path_buf, &n); + if (rc != 0) return error.NameTooLong; + const symlink_path = std.mem.sliceTo(&symlink_path_buf, 0); + return Io.Dir.realPathFileAbsolute(ioBasic(t), symlink_path, out_buffer) catch |err| switch (err) { + error.NetworkNotFound => unreachable, // Windows-only + else => |e| return e, + }; + }, + .linux, .serenity => return Io.Dir.readLinkAbsolute(ioBasic(t), "/proc/self/exe", out_buffer) catch |err| switch (err) { + error.UnsupportedReparsePointType => unreachable, // Windows-only + error.NetworkNotFound => unreachable, // Windows-only + else => |e| return e, + }, + .illumos => return Io.Dir.readLinkAbsolute(ioBasic(t), "/proc/self/path/a.out", out_buffer) catch |err| switch (err) { + error.UnsupportedReparsePointType => unreachable, // Windows-only + error.NetworkNotFound => unreachable, // Windows-only + else => |e| return e, + }, + .freebsd, .dragonfly => { + var mib: [4]c_int = .{ posix.CTL.KERN, posix.KERN.PROC, posix.KERN.PROC_PATHNAME, -1 }; + var out_len: usize = out_buffer.len; + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.sysctl(&mib, mib.len, out_buffer.ptr, &out_len, null, 0))) { + .SUCCESS => { + syscall.finish(); + return out_len - 1; // discard terminating NUL + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .FAULT => |err| return errnoBug(err), + .PERM => return error.PermissionDenied, + .NOMEM => return error.SystemResources, + .NOENT => |err| return errnoBug(err), + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } + }, + .netbsd => { + var mib = [4]c_int{ posix.CTL.KERN, posix.KERN.PROC_ARGS, -1, posix.KERN.PROC_PATHNAME }; + var out_len: usize = out_buffer.len; + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.sysctl(&mib, mib.len, out_buffer.ptr, &out_len, null, 0))) { + .SUCCESS => { + syscall.finish(); + return out_len - 1; // discard terminating NUL + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .FAULT => |err| return errnoBug(err), + .PERM => return error.PermissionDenied, + .NOMEM => return error.SystemResources, + .NOENT => |err| return errnoBug(err), + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } + }, + .openbsd, .haiku => { + // The best we can do on these operating systems is check based on + // the first process argument. + const argv0 = std.mem.span(t.argv0.value orelse return error.OperationUnsupported); + if (std.mem.findScalar(u8, argv0, '/') != null) { + // argv[0] is a path (relative or absolute): use realpath(3) directly + var resolved_buf: [std.c.PATH_MAX]u8 = undefined; + const syscall: Syscall = try .start(); + while (true) { + if (std.c.realpath(argv0, &resolved_buf)) |p| { + assert(p == &resolved_buf); + break syscall.finish(); + } else switch (@as(std.c.E, @enumFromInt(std.c._errno().*))) { + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ACCES => return error.AccessDenied, + .INVAL => |err| return errnoBug(err), // the pathname argument is a null pointer + .IO => return error.InputOutput, + .LOOP => return error.SymLinkLoop, + .NAMETOOLONG => return error.NameTooLong, + .NOENT => return error.FileNotFound, + .NOTDIR => return error.NotDir, + .NOMEM => |err| return errnoBug(err), // sufficient storage space is unavailable for allocation + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } + const resolved = std.mem.sliceTo(&resolved_buf, 0); + if (resolved.len > out_buffer.len) + return error.NameTooLong; + @memcpy(out_buffer[0..resolved.len], resolved); + return resolved.len; + } else if (argv0.len != 0) { + // argv[0] is not empty (and not a path): search PATH + t.scanEnviron(); + const PATH = t.environ.string.PATH orelse return error.FileNotFound; + var it = std.mem.tokenizeScalar(u8, PATH, ':'); + it: while (it.next()) |dir| { + var resolved_path_buf: [std.c.PATH_MAX]u8 = undefined; + const resolved_path = std.fmt.bufPrintSentinel(&resolved_path_buf, "{s}/{s}", .{ + dir, argv0, + }, 0) catch continue; + + var resolved_buf: [std.c.PATH_MAX]u8 = undefined; + const syscall: Syscall = try .start(); + while (true) { + if (std.c.realpath(resolved_path, &resolved_buf)) |p| { + assert(p == &resolved_buf); + break syscall.finish(); + } else switch (@as(std.c.E, @enumFromInt(std.c._errno().*))) { + .INTR => { + try syscall.checkCancel(); + continue; + }, + .NAMETOOLONG => { + syscall.finish(); + return error.NameTooLong; + }, + .NOMEM => { + syscall.finish(); + return error.SystemResources; + }, + .IO => { + syscall.finish(); + return error.InputOutput; + }, + .ACCES, .LOOP, .NOENT, .NOTDIR => { + syscall.finish(); + continue :it; + }, + else => |err| { + syscall.finish(); + return posix.unexpectedErrno(err); + }, + } + } + const resolved = std.mem.sliceTo(&resolved_buf, 0); + if (resolved.len > out_buffer.len) + return error.NameTooLong; + @memcpy(out_buffer[0..resolved.len], resolved); + return resolved.len; + } + } + return error.FileNotFound; + }, + .windows => { + const w = windows; + const image_path_unicode_string = &w.peb().ProcessParameters.ImagePathName; + const image_path_name = image_path_unicode_string.Buffer.?[0 .. image_path_unicode_string.Length / 2 :0]; + + // If ImagePathName is a symlink, then it will contain the path of the + // symlink, not the path that the symlink points to. We want the path + // that the symlink points to, though, so we need to get the realpath. + var path_name_w_buf = try w.wToPrefixedFileW(null, image_path_name); + + const h_file = handle: { + const syscall: Syscall = try .start(); + while (true) { + if (w.OpenFile(path_name_w_buf.span(), .{ + .dir = null, + .access_mask = .{ + .GENERIC = .{ .READ = true }, + .STANDARD = .{ .SYNCHRONIZE = true }, + }, + .creation = .OPEN, + .filter = .any, + })) |handle| { + syscall.finish(); + break :handle handle; + } else |err| switch (err) { + error.WouldBlock => unreachable, + error.OperationCanceled => { + try syscall.checkCancel(); + continue; + }, + else => |e| return e, + } + } + }; + defer w.CloseHandle(h_file); + + // TODO move GetFinalPathNameByHandle logic into std.Io.Threaded and add cancel checks + try Thread.checkCancel(); + const wide_slice = try w.GetFinalPathNameByHandle(h_file, .{}, &path_name_w_buf.data); + + const len = std.unicode.calcWtf8Len(wide_slice); + if (len > out_buffer.len) + return error.NameTooLong; + + const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice); + return end_index; + }, + else => return error.OperationUnsupported, + } +} + +fn fileWritePositional( + userdata: ?*anyopaque, + file: File, + header: []const u8, + data: []const []const u8, + splat: usize, + offset: u64, +) File.WritePositionalError!usize { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + if (is_windows) { + if (header.len != 0) { + return writeFilePositionalWindows(file.handle, header, offset); + } + for (data[0 .. data.len - 1]) |buf| { + if (buf.len == 0) continue; + return writeFilePositionalWindows(file.handle, buf, offset); + } + const pattern = data[data.len - 1]; + if (pattern.len == 0 or splat == 0) return 0; + return writeFilePositionalWindows(file.handle, pattern, offset); + } + + var iovecs: [max_iovecs_len]posix.iovec_const = undefined; + var iovlen: iovlen_t = 0; + addBuf(&iovecs, &iovlen, header); + for (data[0 .. data.len - 1]) |bytes| addBuf(&iovecs, &iovlen, bytes); + const pattern = data[data.len - 1]; + if (iovecs.len - iovlen != 0) switch (splat) { + 0 => {}, + 1 => addBuf(&iovecs, &iovlen, pattern), + else => switch (pattern.len) { + 0 => {}, + 1 => { + var backup_buffer: [splat_buffer_size]u8 = undefined; + const splat_buffer = &backup_buffer; + const memset_len = @min(splat_buffer.len, splat); + const buf = splat_buffer[0..memset_len]; + @memset(buf, pattern[0]); + addBuf(&iovecs, &iovlen, buf); + var remaining_splat = splat - buf.len; + while (remaining_splat > splat_buffer.len and iovecs.len - iovlen != 0) { + assert(buf.len == splat_buffer.len); + addBuf(&iovecs, &iovlen, splat_buffer); + remaining_splat -= splat_buffer.len; + } + addBuf(&iovecs, &iovlen, splat_buffer[0..@min(remaining_splat, splat_buffer.len)]); + }, + else => for (0..@min(splat, iovecs.len - iovlen)) |_| { + addBuf(&iovecs, &iovlen, pattern); + }, + }, + }; + + if (iovlen == 0) return 0; + + if (native_os == .wasi and !builtin.link_libc) { + var n_written: usize = undefined; + const syscall: Syscall = try .start(); + while (true) { + switch (std.os.wasi.fd_pwrite(file.handle, &iovecs, iovlen, offset, &n_written)) { + .SUCCESS => { + syscall.finish(); + return n_written; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .INVAL => |err| return errnoBug(err), + .FAULT => |err| return errnoBug(err), + .AGAIN => |err| return errnoBug(err), + .BADF => return error.NotOpenForWriting, // can be a race condition. + .DESTADDRREQ => |err| return errnoBug(err), // `connect` was never called. + .DQUOT => return error.DiskQuota, + .FBIG => return error.FileTooBig, + .IO => return error.InputOutput, + .NOSPC => return error.NoSpaceLeft, + .PERM => return error.PermissionDenied, + .PIPE => return error.BrokenPipe, + .NOTCAPABLE => return error.AccessDenied, + .NXIO => return error.Unseekable, + .SPIPE => return error.Unseekable, + .OVERFLOW => return error.Unseekable, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } + } + + const syscall: Syscall = try .start(); + while (true) { + const rc = pwritev_sym(file.handle, &iovecs, @intCast(iovlen), @bitCast(offset)); + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + return @intCast(rc); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .INVAL => |err| return errnoBug(err), + .FAULT => |err| return errnoBug(err), + .AGAIN => return error.WouldBlock, + .BADF => return error.NotOpenForWriting, // Usually a race condition. + .DESTADDRREQ => |err| return errnoBug(err), // `connect` was never called. + .DQUOT => return error.DiskQuota, + .FBIG => return error.FileTooBig, + .IO => return error.InputOutput, + .NOSPC => return error.NoSpaceLeft, + .PERM => return error.PermissionDenied, + .PIPE => return error.BrokenPipe, + .CONNRESET => |err| return errnoBug(err), // Not a socket handle. + .BUSY => return error.DeviceBusy, + .TXTBSY => return error.FileBusy, + .NXIO => return error.Unseekable, + .SPIPE => return error.Unseekable, + .OVERFLOW => return error.Unseekable, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn writeFilePositionalWindows( + handle: windows.HANDLE, + bytes: []const u8, + offset: u64, +) File.WritePositionalError!usize { + var bytes_written: windows.DWORD = undefined; + var overlapped: windows.OVERLAPPED = .{ + .Internal = 0, + .InternalHigh = 0, + .DUMMYUNIONNAME = .{ + .DUMMYSTRUCTNAME = .{ + .Offset = @truncate(offset), + .OffsetHigh = @truncate(offset >> 32), + }, + }, + .hEvent = null, + }; + const adjusted_len = std.math.lossyCast(u32, bytes.len); + const syscall: Syscall = try .start(); + while (true) { + if (windows.kernel32.WriteFile(handle, bytes.ptr, adjusted_len, &bytes_written, &overlapped) != 0) { + syscall.finish(); + return bytes_written; + } + switch (windows.GetLastError()) { + .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + .INVALID_USER_BUFFER => return syscall.fail(error.SystemResources), + .NOT_ENOUGH_MEMORY => return syscall.fail(error.SystemResources), + .NOT_ENOUGH_QUOTA => return syscall.fail(error.SystemResources), + .NO_DATA => return syscall.fail(error.BrokenPipe), + .INVALID_HANDLE => return syscall.fail(error.NotOpenForWriting), + .LOCK_VIOLATION => return syscall.fail(error.LockViolation), + .ACCESS_DENIED => return syscall.fail(error.AccessDenied), + .WORKING_SET_QUOTA => return syscall.fail(error.SystemResources), + else => |err| { + syscall.finish(); + return windows.unexpectedError(err); + }, + } + } +} + +fn fileWriteStreaming( + userdata: ?*anyopaque, + file: File, + header: []const u8, + data: []const []const u8, + splat: usize, +) File.Writer.Error!usize { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + if (is_windows) { + if (header.len != 0) { + return writeFileStreamingWindows(file.handle, header); + } + for (data[0 .. data.len - 1]) |buf| { + if (buf.len == 0) continue; + return writeFileStreamingWindows(file.handle, buf); + } + const pattern = data[data.len - 1]; + if (pattern.len == 0 or splat == 0) return 0; + return writeFileStreamingWindows(file.handle, pattern); + } + + var iovecs: [max_iovecs_len]posix.iovec_const = undefined; + var iovlen: iovlen_t = 0; + addBuf(&iovecs, &iovlen, header); + for (data[0 .. data.len - 1]) |bytes| addBuf(&iovecs, &iovlen, bytes); + const pattern = data[data.len - 1]; + if (iovecs.len - iovlen != 0) switch (splat) { + 0 => {}, + 1 => addBuf(&iovecs, &iovlen, pattern), + else => switch (pattern.len) { + 0 => {}, + 1 => { + var backup_buffer: [splat_buffer_size]u8 = undefined; + const splat_buffer = &backup_buffer; + const memset_len = @min(splat_buffer.len, splat); + const buf = splat_buffer[0..memset_len]; + @memset(buf, pattern[0]); + addBuf(&iovecs, &iovlen, buf); + var remaining_splat = splat - buf.len; + while (remaining_splat > splat_buffer.len and iovecs.len - iovlen != 0) { + assert(buf.len == splat_buffer.len); + addBuf(&iovecs, &iovlen, splat_buffer); + remaining_splat -= splat_buffer.len; + } + addBuf(&iovecs, &iovlen, splat_buffer[0..@min(remaining_splat, splat_buffer.len)]); + }, + else => for (0..@min(splat, iovecs.len - iovlen)) |_| { + addBuf(&iovecs, &iovlen, pattern); + }, + }, + }; + + if (iovlen == 0) return 0; + + if (native_os == .wasi and !builtin.link_libc) { + var n_written: usize = undefined; + const syscall: Syscall = try .start(); + while (true) { + switch (std.os.wasi.fd_write(file.handle, &iovecs, iovlen, &n_written)) { + .SUCCESS => { + syscall.finish(); + return n_written; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .INVAL => |err| return errnoBug(err), + .FAULT => |err| return errnoBug(err), + .AGAIN => |err| return errnoBug(err), + .BADF => return error.NotOpenForWriting, // can be a race condition. + .DESTADDRREQ => |err| return errnoBug(err), // `connect` was never called. + .DQUOT => return error.DiskQuota, + .FBIG => return error.FileTooBig, + .IO => return error.InputOutput, + .NOSPC => return error.NoSpaceLeft, + .PERM => return error.PermissionDenied, + .PIPE => return error.BrokenPipe, + .NOTCAPABLE => return error.AccessDenied, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } + } + + const syscall: Syscall = try .start(); + while (true) { + const rc = posix.system.writev(file.handle, &iovecs, @intCast(iovlen)); + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + return @intCast(rc); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .INVAL => |err| return errnoBug(err), + .FAULT => |err| return errnoBug(err), + .AGAIN => return error.WouldBlock, + .BADF => return error.NotOpenForWriting, // Can be a race condition. + .DESTADDRREQ => |err| return errnoBug(err), // `connect` was never called. + .DQUOT => return error.DiskQuota, + .FBIG => return error.FileTooBig, + .IO => return error.InputOutput, + .NOSPC => return error.NoSpaceLeft, + .PERM => return error.PermissionDenied, + .PIPE => return error.BrokenPipe, + .CONNRESET => |err| return errnoBug(err), // Not a socket handle. + .BUSY => return error.DeviceBusy, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn writeFileStreamingWindows( + handle: windows.HANDLE, + bytes: []const u8, +) File.Writer.Error!usize { + var bytes_written: windows.DWORD = undefined; + const adjusted_len = std.math.lossyCast(u32, bytes.len); + const syscall: Syscall = try .start(); + while (true) { + if (windows.kernel32.WriteFile(handle, bytes.ptr, adjusted_len, &bytes_written, null) != 0) { + syscall.finish(); + return bytes_written; + } + switch (windows.GetLastError()) { + .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + .INVALID_USER_BUFFER => return syscall.fail(error.SystemResources), + .NOT_ENOUGH_MEMORY => return syscall.fail(error.SystemResources), + .NOT_ENOUGH_QUOTA => return syscall.fail(error.SystemResources), + .NO_DATA => return syscall.fail(error.BrokenPipe), + .INVALID_HANDLE => return syscall.fail(error.NotOpenForWriting), + .LOCK_VIOLATION => return syscall.fail(error.LockViolation), + .ACCESS_DENIED => return syscall.fail(error.AccessDenied), + .WORKING_SET_QUOTA => return syscall.fail(error.SystemResources), + else => |err| { + syscall.finish(); + return windows.unexpectedError(err); + }, + } + } +} + +fn fileWriteFileStreaming( + userdata: ?*anyopaque, + file: File, + header: []const u8, + file_reader: *File.Reader, + limit: Io.Limit, +) File.Writer.WriteFileError!usize { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + const reader_buffered = file_reader.interface.buffered(); + if (reader_buffered.len >= @intFromEnum(limit)) { + const n = try fileWriteStreaming(t, file, header, &.{limit.slice(reader_buffered)}, 1); + file_reader.interface.toss(n -| header.len); + return n; + } + const file_limit = @intFromEnum(limit) - reader_buffered.len; + const out_fd = file.handle; + const in_fd = file_reader.file.handle; + + if (file_reader.size) |size| { + if (size - file_reader.pos == 0) { + if (reader_buffered.len != 0) { + const n = try fileWriteStreaming(t, file, header, &.{limit.slice(reader_buffered)}, 1); + file_reader.interface.toss(n -| header.len); + return n; + } else { + return error.EndOfStream; + } + } + } + + if (native_os == .freebsd) sf: { + // Try using sendfile on FreeBSD. + if (@atomicLoad(UseSendfile, &t.use_sendfile, .monotonic) == .disabled) break :sf; + const offset = std.math.cast(std.c.off_t, file_reader.pos) orelse break :sf; + var hdtr_data: std.c.sf_hdtr = undefined; + var headers: [2]posix.iovec_const = undefined; + var headers_i: u8 = 0; + if (header.len != 0) { + headers[headers_i] = .{ .base = header.ptr, .len = header.len }; + headers_i += 1; + } + if (reader_buffered.len != 0) { + headers[headers_i] = .{ .base = reader_buffered.ptr, .len = reader_buffered.len }; + headers_i += 1; + } + const hdtr: ?*std.c.sf_hdtr = if (headers_i == 0) null else b: { + hdtr_data = .{ + .headers = &headers, + .hdr_cnt = headers_i, + .trailers = null, + .trl_cnt = 0, + }; + break :b &hdtr_data; + }; + var sbytes: std.c.off_t = 0; + const nbytes: usize = @min(file_limit, std.math.maxInt(usize)); + const flags = 0; + + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(std.c.sendfile(in_fd, out_fd, offset, nbytes, hdtr, &sbytes, flags))) { + .SUCCESS => { + syscall.finish(); + break; + }, + .INVAL, .OPNOTSUPP, .NOTSOCK, .NOSYS => { + // Give calling code chance to observe before trying + // something else. + syscall.finish(); + @atomicStore(UseSendfile, &t.use_sendfile, .disabled, .monotonic); + return 0; + }, + .INTR, .BUSY => { + if (sbytes == 0) { + try syscall.checkCancel(); + continue; + } else { + // Even if we are being canceled, there have been side + // effects, so it is better to report those side + // effects to the caller. + syscall.finish(); + break; + } + }, + .AGAIN => { + syscall.finish(); + if (sbytes == 0) return error.WouldBlock; + break; + }, + else => |e| { + syscall.finish(); + assert(error.Unexpected == switch (e) { + .NOTCONN => return error.BrokenPipe, + .IO => return error.InputOutput, + .PIPE => return error.BrokenPipe, + .NOBUFS => return error.SystemResources, + .BADF => |err| errnoBug(err), + .FAULT => |err| errnoBug(err), + else => |err| posix.unexpectedErrno(err), + }); + // Give calling code chance to observe the error before trying + // something else. + @atomicStore(UseSendfile, &t.use_sendfile, .disabled, .monotonic); + return 0; + }, + } + } + if (sbytes == 0) { + file_reader.size = file_reader.pos; + return error.EndOfStream; + } + const ubytes: usize = @intCast(sbytes); + file_reader.interface.toss(ubytes -| header.len); + return ubytes; + } + + if (is_darwin) sf: { + // Try using sendfile on macOS. + if (@atomicLoad(UseSendfile, &t.use_sendfile, .monotonic) == .disabled) break :sf; + const offset = std.math.cast(std.c.off_t, file_reader.pos) orelse break :sf; + var hdtr_data: std.c.sf_hdtr = undefined; + var headers: [2]posix.iovec_const = undefined; + var headers_i: u8 = 0; + if (header.len != 0) { + headers[headers_i] = .{ .base = header.ptr, .len = header.len }; + headers_i += 1; + } + if (reader_buffered.len != 0) { + headers[headers_i] = .{ .base = reader_buffered.ptr, .len = reader_buffered.len }; + headers_i += 1; + } + const hdtr: ?*std.c.sf_hdtr = if (headers_i == 0) null else b: { + hdtr_data = .{ + .headers = &headers, + .hdr_cnt = headers_i, + .trailers = null, + .trl_cnt = 0, + }; + break :b &hdtr_data; + }; + const max_count = std.math.maxInt(i32); // Avoid EINVAL. + var len: std.c.off_t = @min(file_limit, max_count); + const flags = 0; + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(std.c.sendfile(in_fd, out_fd, offset, &len, hdtr, flags))) { + .SUCCESS => { + syscall.finish(); + break; + }, + .OPNOTSUPP, .NOTSOCK, .NOSYS => { + // Give calling code chance to observe before trying + // something else. + syscall.finish(); + @atomicStore(UseSendfile, &t.use_sendfile, .disabled, .monotonic); + return 0; + }, + .INTR => { + if (len == 0) { + try syscall.checkCancel(); + continue; + } else { + // Even if we are being canceled, there have been side + // effects, so it is better to report those side + // effects to the caller. + syscall.finish(); + break; + } + }, + .AGAIN => { + syscall.finish(); + if (len == 0) return error.WouldBlock; + break; + }, + else => |e| { + syscall.finish(); + assert(error.Unexpected == switch (e) { + .NOTCONN => return error.BrokenPipe, + .IO => return error.InputOutput, + .PIPE => return error.BrokenPipe, + .BADF => |err| errnoBug(err), + .FAULT => |err| errnoBug(err), + .INVAL => |err| errnoBug(err), + else => |err| posix.unexpectedErrno(err), + }); + // Give calling code chance to observe the error before trying + // something else. + @atomicStore(UseSendfile, &t.use_sendfile, .disabled, .monotonic); + return 0; + }, + } + } + if (len == 0) { + file_reader.size = file_reader.pos; + return error.EndOfStream; + } + const u_len: usize = @bitCast(len); + file_reader.interface.toss(u_len -| header.len); + return u_len; + } + + if (native_os == .linux) sf: { + // Try using sendfile on Linux. + if (@atomicLoad(UseSendfile, &t.use_sendfile, .monotonic) == .disabled) break :sf; + // Linux sendfile does not support headers. + if (header.len != 0 or reader_buffered.len != 0) { + const n = try fileWriteStreaming(t, file, header, &.{limit.slice(reader_buffered)}, 1); + file_reader.interface.toss(n -| header.len); + return n; + } + const max_count = 0x7ffff000; // Avoid EINVAL. + var off: std.os.linux.off_t = undefined; + const off_ptr: ?*std.os.linux.off_t, const count: usize = switch (file_reader.mode) { + .positional => o: { + const size = file_reader.getSize() catch return 0; + off = std.math.cast(std.os.linux.off_t, file_reader.pos) orelse return error.ReadFailed; + break :o .{ &off, @min(@intFromEnum(limit), size - file_reader.pos, max_count) }; + }, + .streaming => .{ null, limit.minInt(max_count) }, + .streaming_simple, .positional_simple => break :sf, + .failure => return error.ReadFailed, + }; + const syscall: Syscall = try .start(); + const n: usize = while (true) { + const rc = sendfile_sym(out_fd, in_fd, off_ptr, count); + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + break @intCast(rc); + }, + .NOSYS, .INVAL => { + // Give calling code chance to observe before trying + // something else. + syscall.finish(); + @atomicStore(UseSendfile, &t.use_sendfile, .disabled, .monotonic); + return 0; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + assert(error.Unexpected == switch (e) { + .NOTCONN => return error.BrokenPipe, // `out_fd` is an unconnected socket + .AGAIN => return error.WouldBlock, + .IO => return error.InputOutput, + .PIPE => return error.BrokenPipe, + .NOMEM => return error.SystemResources, + .NXIO, .SPIPE => { + file_reader.mode = file_reader.mode.toStreaming(); + const pos = file_reader.pos; + if (pos != 0) { + file_reader.pos = 0; + file_reader.seekBy(@intCast(pos)) catch { + file_reader.mode = .failure; + return error.ReadFailed; + }; + } + return 0; + }, + .BADF => |err| errnoBug(err), // Always a race condition. + .FAULT => |err| errnoBug(err), // Segmentation fault. + .OVERFLOW => |err| errnoBug(err), // We avoid passing too large of a `count`. + else => |err| posix.unexpectedErrno(err), + }); + // Give calling code chance to observe the error before trying + // something else. + @atomicStore(UseSendfile, &t.use_sendfile, .disabled, .monotonic); + return 0; + }, + } + }; + if (n == 0) { + file_reader.size = file_reader.pos; + return error.EndOfStream; + } + file_reader.pos += n; + return n; + } + + if (have_copy_file_range) cfr: { + if (@atomicLoad(UseCopyFileRange, &t.use_copy_file_range, .monotonic) == .disabled) break :cfr; + if (header.len != 0 or reader_buffered.len != 0) { + const n = try fileWriteStreaming(t, file, header, &.{limit.slice(reader_buffered)}, 1); + file_reader.interface.toss(n -| header.len); + return n; + } + var off_in: i64 = undefined; + const off_in_ptr: ?*i64 = switch (file_reader.mode) { + .positional_simple, .streaming_simple => return error.Unimplemented, + .positional => p: { + off_in = @intCast(file_reader.pos); + break :p &off_in; + }, + .streaming => null, + .failure => return error.ReadFailed, + }; + const n: usize = switch (native_os) { + .linux => n: { + const syscall: Syscall = try .start(); + while (true) { + const rc = linux_copy_file_range_sys.copy_file_range(in_fd, off_in_ptr, out_fd, null, @intFromEnum(limit), 0); + switch (linux_copy_file_range_sys.errno(rc)) { + .SUCCESS => { + syscall.finish(); + break :n @intCast(rc); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + .OPNOTSUPP, .INVAL, .NOSYS => { + // Give calling code chance to observe before trying + // something else. + syscall.finish(); + @atomicStore(UseCopyFileRange, &t.use_copy_file_range, .disabled, .monotonic); + return 0; + }, + else => |e| { + syscall.finish(); + assert(error.Unexpected == switch (e) { + .FBIG => return error.FileTooBig, + .IO => return error.InputOutput, + .NOMEM => return error.SystemResources, + .NOSPC => return error.NoSpaceLeft, + .OVERFLOW => |err| errnoBug(err), // We avoid passing too large a count. + .PERM => return error.PermissionDenied, + .BUSY => return error.DeviceBusy, + .TXTBSY => return error.FileBusy, + // copy_file_range can still work but not on + // this pair of file descriptors. + .XDEV => return error.Unimplemented, + .ISDIR => |err| errnoBug(err), + .BADF => |err| errnoBug(err), + else => |err| posix.unexpectedErrno(err), + }); + @atomicStore(UseCopyFileRange, &t.use_copy_file_range, .disabled, .monotonic); + return 0; + }, + } + } + }, + .freebsd => n: { + const syscall: Syscall = try .start(); + while (true) { + const rc = std.c.copy_file_range(in_fd, off_in_ptr, out_fd, null, @intFromEnum(limit), 0); + switch (std.c.errno(rc)) { + .SUCCESS => { + syscall.finish(); + break :n @intCast(rc); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + .OPNOTSUPP, .INVAL, .NOSYS => { + // Give calling code chance to observe before trying + // something else. + syscall.finish(); + @atomicStore(UseCopyFileRange, &t.use_copy_file_range, .disabled, .monotonic); + return 0; + }, + else => |e| { + syscall.finish(); + assert(error.Unexpected == switch (e) { + .FBIG => return error.FileTooBig, + .IO => return error.InputOutput, + .INTEGRITY => return error.CorruptedData, + .NOSPC => return error.NoSpaceLeft, + .ISDIR => |err| errnoBug(err), + .BADF => |err| errnoBug(err), + else => |err| posix.unexpectedErrno(err), + }); + @atomicStore(UseCopyFileRange, &t.use_copy_file_range, .disabled, .monotonic); + return 0; + }, + } + } + }, + else => comptime unreachable, + }; + if (n == 0) { + file_reader.size = file_reader.pos; + return error.EndOfStream; + } + file_reader.pos += n; + return n; + } + + return error.Unimplemented; +} + +fn netWriteFile( + userdata: ?*anyopaque, + socket_handle: net.Socket.Handle, + header: []const u8, + file_reader: *File.Reader, + limit: Io.Limit, +) net.Stream.Writer.WriteFileError!usize { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + _ = socket_handle; + _ = header; + _ = file_reader; + _ = limit; + @panic("TODO implement netWriteFile"); +} + +fn netWriteFileUnavailable( + userdata: ?*anyopaque, + socket_handle: net.Socket.Handle, + header: []const u8, + file_reader: *File.Reader, + limit: Io.Limit, +) net.Stream.Writer.WriteFileError!usize { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + _ = socket_handle; + _ = header; + _ = file_reader; + _ = limit; + return error.NetworkDown; +} + +fn fileWriteFilePositional( + userdata: ?*anyopaque, + file: File, + header: []const u8, + file_reader: *File.Reader, + limit: Io.Limit, + offset: u64, +) File.WriteFilePositionalError!usize { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + const reader_buffered = file_reader.interface.buffered(); + if (reader_buffered.len >= @intFromEnum(limit)) { + const n = try fileWritePositional(t, file, header, &.{limit.slice(reader_buffered)}, 1, offset); + file_reader.interface.toss(n -| header.len); + return n; + } + const out_fd = file.handle; + const in_fd = file_reader.file.handle; + + if (file_reader.size) |size| { + if (size - file_reader.pos == 0) { + if (reader_buffered.len != 0) { + const n = try fileWritePositional(t, file, header, &.{limit.slice(reader_buffered)}, 1, offset); + file_reader.interface.toss(n -| header.len); + return n; + } else { + return error.EndOfStream; + } + } + } + + if (have_copy_file_range) cfr: { + if (@atomicLoad(UseCopyFileRange, &t.use_copy_file_range, .monotonic) == .disabled) break :cfr; + if (header.len != 0 or reader_buffered.len != 0) { + const n = try fileWritePositional(t, file, header, &.{limit.slice(reader_buffered)}, 1, offset); + file_reader.interface.toss(n -| header.len); + return n; + } + var off_in: i64 = undefined; + const off_in_ptr: ?*i64 = switch (file_reader.mode) { + .positional_simple, .streaming_simple => return error.Unimplemented, + .positional => p: { + off_in = @intCast(file_reader.pos); + break :p &off_in; + }, + .streaming => null, + .failure => return error.ReadFailed, + }; + var off_out: i64 = @intCast(offset); + const n: usize = switch (native_os) { + .linux => n: { + const syscall: Syscall = try .start(); + while (true) { + const rc = linux_copy_file_range_sys.copy_file_range(in_fd, off_in_ptr, out_fd, &off_out, @intFromEnum(limit), 0); + switch (linux_copy_file_range_sys.errno(rc)) { + .SUCCESS => { + syscall.finish(); + break :n @intCast(rc); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + .OPNOTSUPP, .INVAL, .NOSYS => { + // Give calling code chance to observe before trying + // something else. + syscall.finish(); + @atomicStore(UseCopyFileRange, &t.use_copy_file_range, .disabled, .monotonic); + return 0; + }, + else => |e| { + syscall.finish(); + assert(error.Unexpected == switch (e) { + .FBIG => return error.FileTooBig, + .IO => return error.InputOutput, + .NOMEM => return error.SystemResources, + .NOSPC => return error.NoSpaceLeft, + .OVERFLOW => return error.Unseekable, + .NXIO => return error.Unseekable, + .SPIPE => return error.Unseekable, + .PERM => return error.PermissionDenied, + .TXTBSY => return error.FileBusy, + // copy_file_range can still work but not on + // this pair of file descriptors. + .XDEV => return error.Unimplemented, + .ISDIR => |err| errnoBug(err), + .BADF => |err| errnoBug(err), + else => |err| posix.unexpectedErrno(err), + }); + @atomicStore(UseCopyFileRange, &t.use_copy_file_range, .disabled, .monotonic); + return 0; + }, + } + } + }, + .freebsd => n: { + const syscall: Syscall = try .start(); + while (true) { + const rc = std.c.copy_file_range(in_fd, off_in_ptr, out_fd, &off_out, @intFromEnum(limit), 0); + switch (std.c.errno(rc)) { + .SUCCESS => { + syscall.finish(); + break :n @intCast(rc); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + .OPNOTSUPP, .INVAL, .NOSYS => { + // Give calling code chance to observe before trying + // something else. + syscall.finish(); + @atomicStore(UseCopyFileRange, &t.use_copy_file_range, .disabled, .monotonic); + return 0; + }, + else => |e| { + syscall.finish(); + assert(error.Unexpected == switch (e) { + .FBIG => return error.FileTooBig, + .IO => return error.InputOutput, + .INTEGRITY => return error.CorruptedData, + .NOSPC => return error.NoSpaceLeft, + .OVERFLOW => return error.Unseekable, + .NXIO => return error.Unseekable, + .SPIPE => return error.Unseekable, + .ISDIR => |err| errnoBug(err), + .BADF => |err| errnoBug(err), + else => |err| posix.unexpectedErrno(err), + }); + @atomicStore(UseCopyFileRange, &t.use_copy_file_range, .disabled, .monotonic); + return 0; + }, + } + } + }, + else => comptime unreachable, + }; + if (n == 0) { + file_reader.size = file_reader.pos; + return error.EndOfStream; + } + file_reader.pos += n; + return n; + } + + if (is_darwin) fcf: { + if (@atomicLoad(UseFcopyfile, &t.use_fcopyfile, .monotonic) == .disabled) break :fcf; + if (file_reader.pos != 0) break :fcf; + if (offset != 0) break :fcf; + if (limit != .unlimited) break :fcf; + const size = file_reader.getSize() catch break :fcf; + if (header.len != 0 or reader_buffered.len != 0) { + const n = try fileWritePositional(t, file, header, &.{limit.slice(reader_buffered)}, 1, offset); + file_reader.interface.toss(n -| header.len); + return n; + } + const syscall: Syscall = try .start(); + while (true) { + const rc = std.c.fcopyfile(in_fd, out_fd, null, .{ .DATA = true }); + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + break; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + .OPNOTSUPP => { + // Give calling code chance to observe before trying + // something else. + syscall.finish(); + @atomicStore(UseFcopyfile, &t.use_fcopyfile, .disabled, .monotonic); + return 0; + }, + else => |e| { + syscall.finish(); + assert(error.Unexpected == switch (e) { + .NOMEM => return error.SystemResources, + .INVAL => |err| errnoBug(err), + else => |err| posix.unexpectedErrno(err), + }); + return 0; + }, + } + } + file_reader.pos = size; + return size; + } + + return error.Unimplemented; +} + +fn nowPosix(clock: Io.Clock) Io.Clock.Error!Io.Timestamp { + const clock_id: posix.clockid_t = clockToPosix(clock); + var tp: posix.timespec = undefined; + switch (posix.errno(posix.system.clock_gettime(clock_id, &tp))) { + .SUCCESS => return timestampFromPosix(&tp), + .INVAL => return error.UnsupportedClock, + else => |err| return posix.unexpectedErrno(err), + } +} + +fn now(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + return switch (native_os) { + .windows => nowWindows(clock), + .wasi => nowWasi(clock), + else => nowPosix(clock), + }; +} + +fn nowWindows(clock: Io.Clock) Io.Clock.Error!Io.Timestamp { + switch (clock) { + .real => { + // RtlGetSystemTimePrecise() has a granularity of 100 nanoseconds + // and uses the NTFS/Windows epoch, which is 1601-01-01. + const epoch_ns = std.time.epoch.windows * std.time.ns_per_s; + return .{ .nanoseconds = @as(i96, windows.ntdll.RtlGetSystemTimePrecise()) * 100 + epoch_ns }; + }, + .awake, .boot => { + // QPC on windows doesn't fail on >= XP/2000 and includes time suspended. + const qpc = windows.QueryPerformanceCounter(); + // We don't need to cache QPF as it's internally just a memory read to KUSER_SHARED_DATA + // (a read-only page of info updated and mapped by the kernel to all processes): + // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/ns-ntddk-kuser_shared_data + // https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/ntexapi_x/kuser_shared_data/index.htm + const qpf = windows.QueryPerformanceFrequency(); + + // 10Mhz (1 qpc tick every 100ns) is a common enough QPF value that we can optimize on it. + // https://github.com/microsoft/STL/blob/785143a0c73f030238ef618890fd4d6ae2b3a3a0/stl/inc/chrono#L694-L701 + const common_qpf = 10_000_000; + if (qpf == common_qpf) return .{ .nanoseconds = qpc * (std.time.ns_per_s / common_qpf) }; + + // Convert to ns using fixed point. + const scale = @as(u64, std.time.ns_per_s << 32) / @as(u32, @intCast(qpf)); + const result = (@as(u96, qpc) * scale) >> 32; + return .{ .nanoseconds = @intCast(result) }; + }, + .cpu_process, + .cpu_thread, + => return error.UnsupportedClock, + } +} + +fn nowWasi(clock: Io.Clock) Io.Clock.Error!Io.Timestamp { + var ns: std.os.wasi.timestamp_t = undefined; + const err = std.os.wasi.clock_time_get(clockToWasi(clock), 1, &ns); + if (err != .SUCCESS) return error.Unexpected; + return .fromNanoseconds(ns); +} + +fn sleep(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + if (use_parking_sleep) return parking_sleep.sleep(timeout); + if (native_os == .wasi) return sleepWasi(t, timeout); + if (@TypeOf(posix.system.clock_nanosleep) != void) return sleepPosix(timeout); + return sleepNanosleep(t, timeout); +} + +fn sleepPosix(timeout: Io.Timeout) Io.SleepError!void { + const clock_id: posix.clockid_t = clockToPosix(switch (timeout) { + .none => .awake, + .duration => |d| d.clock, + .deadline => |d| d.clock, + }); + const deadline_nanoseconds: i96 = switch (timeout) { + .none => std.math.maxInt(i96), + .duration => |duration| duration.raw.nanoseconds, + .deadline => |deadline| deadline.raw.nanoseconds, + }; + var timespec: posix.timespec = timestampToPosix(deadline_nanoseconds); + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.clock_nanosleep(clock_id, .{ .ABSTIME = switch (timeout) { + .none, .duration => false, + .deadline => true, + } }, ×pec, ×pec))) { + .SUCCESS => { + syscall.finish(); + return; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + .INVAL => return syscall.fail(error.UnsupportedClock), + else => |err| return syscall.unexpectedErrno(err), + } + } +} + +fn sleepWasi(t: *Threaded, timeout: Io.Timeout) Io.SleepError!void { + const t_io = ioBasic(t); + const w = std.os.wasi; + + const clock: w.subscription_clock_t = if (try timeout.toDurationFromNow(t_io)) |d| .{ + .id = clockToWasi(d.clock), + .timeout = std.math.lossyCast(u64, d.raw.nanoseconds), + .precision = 0, + .flags = 0, + } else .{ + .id = .MONOTONIC, + .timeout = std.math.maxInt(u64), + .precision = 0, + .flags = 0, + }; + const in: w.subscription_t = .{ + .userdata = 0, + .u = .{ + .tag = .CLOCK, + .u = .{ .clock = clock }, + }, + }; + var event: w.event_t = undefined; + var nevents: usize = undefined; + const syscall: Syscall = try .start(); + _ = w.poll_oneoff(&in, &event, 1, &nevents); + syscall.finish(); +} + +fn sleepNanosleep(t: *Threaded, timeout: Io.Timeout) Io.SleepError!void { + const t_io = ioBasic(t); + const sec_type = @typeInfo(posix.timespec).@"struct".fields[0].type; + const nsec_type = @typeInfo(posix.timespec).@"struct".fields[1].type; + + var timespec: posix.timespec = t: { + const d = (try timeout.toDurationFromNow(t_io)) orelse break :t .{ + .sec = std.math.maxInt(sec_type), + .nsec = std.math.maxInt(nsec_type), + }; + break :t timestampToPosix(d.raw.toNanoseconds()); + }; + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.nanosleep(×pec, ×pec))) { + .INTR => { + try syscall.checkCancel(); + continue; + }, + // This prong handles success as well as unexpected errors. + else => return syscall.finish(), + } + } +} + +fn select(userdata: ?*anyopaque, futures: []const *Io.AnyFuture) Io.Cancelable!usize { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + var num_completed: std.atomic.Value(u32) = .init(0); + + for (futures, 0..) |any_future, i| { + const future: *Future = @ptrCast(@alignCast(any_future)); + future.awaiter = &num_completed; + const old_status = future.status.fetchOr( + .{ .tag = .pending_awaited, .thread = .null }, + .release, // release `future.awaiter` + ); + switch (old_status.tag) { + .pending => {}, + .pending_awaited => unreachable, // `await` raced with `select` + .pending_canceled => unreachable, // `cancel` raced with `select` + .done => { + future.status.store(old_status, .monotonic); + _ = finishSelect(&num_completed, futures[0..i]); + return i; + }, + } + } + + errdefer _ = finishSelect(&num_completed, futures); + + while (true) { + const n = num_completed.load(.acquire); + if (n > 0) break; + assert(n < futures.len); + try Thread.futexWait(&num_completed.raw, n, null); + } + return finishSelect(&num_completed, futures).?; +} +fn finishSelect( + num_completed: *std.atomic.Value(u32), + futures: []const *Io.AnyFuture, +) ?usize { + var completed_index: ?usize = null; + var expect_completed: u32 = 0; + for (futures, 0..) |any_future, i| { + const future: *Future = @ptrCast(@alignCast(any_future)); + // This operation will convert `.pending_awaited` to `.pending`, or leave `.done` untouched. + switch (future.status.fetchAnd( + .{ .tag = @enumFromInt(0b10), .thread = .all_ones }, + .monotonic, + ).tag) { + .pending_awaited => {}, + .pending => unreachable, + .pending_canceled => unreachable, + .done => { + expect_completed += 1; + completed_index = i; + }, + } + } + // If any future has just finished, wait for it to signal `num_completed` to avoid dangling + // references to stack memory. + while (true) { + const n = num_completed.load(.acquire); + if (n == expect_completed) break; + assert(n < expect_completed); + Thread.futexWaitUncancelable(&num_completed.raw, n, null); + } + return completed_index; +} + +fn netListenIpPosix( + userdata: ?*anyopaque, + address: IpAddress, + options: IpAddress.ListenOptions, +) IpAddress.ListenError!net.Server { + if (!have_networking) return error.NetworkDown; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + const family = posixAddressFamily(&address); + const socket_fd = try openSocketPosix(family, .{ + .mode = options.mode, + .protocol = options.protocol, + }); + errdefer posix.close(socket_fd); + + if (options.reuse_address) { + try setSocketOption(socket_fd, posix.SOL.SOCKET, posix.SO.REUSEADDR, 1); + if (@hasDecl(posix.SO, "REUSEPORT")) + try setSocketOption(socket_fd, posix.SOL.SOCKET, posix.SO.REUSEPORT, 1); + } + + var storage: PosixAddress = undefined; + var addr_len = addressToPosix(&address, &storage); + try posixBind(socket_fd, &storage.any, addr_len); + + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.listen(socket_fd, options.kernel_backlog))) { + .SUCCESS => { + syscall.finish(); + break; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + .ADDRINUSE => return syscall.fail(error.AddressInUse), + .BADF => |err| return syscall.errnoBug(err), // File descriptor used after closed. + else => |err| return syscall.unexpectedErrno(err), + } + } + + try posixGetSockName(socket_fd, &storage.any, &addr_len); + return .{ + .socket = .{ + .handle = socket_fd, + .address = addressFromPosix(&storage), + }, + }; +} + +fn netListenIpWindows( + userdata: ?*anyopaque, + address: IpAddress, + options: IpAddress.ListenOptions, +) IpAddress.ListenError!net.Server { + if (!have_networking) return error.NetworkDown; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + const family = posixAddressFamily(&address); + const socket_handle = try openSocketWsa(t, family, .{ + .mode = options.mode, + .protocol = options.protocol, + }); + errdefer closeSocketWindows(socket_handle); + + if (options.reuse_address) + try setSocketOptionWsa(t, socket_handle, posix.SOL.SOCKET, posix.SO.REUSEADDR, 1); + + var storage: WsaAddress = undefined; + var addr_len = addressToWsa(&address, &storage); + + var syscall: Syscall = try .start(); + while (true) { + const rc = ws2_32.bind(socket_handle, &storage.any, addr_len); + if (rc != ws2_32.SOCKET_ERROR) { + syscall.finish(); + break; + } + switch (ws2_32.WSAGetLastError()) { + .NOTINITIALISED => { + syscall.finish(); + try initializeWsa(t); + syscall = try .start(); + continue; + }, + .EINTR, .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .EADDRINUSE => return error.AddressInUse, + .EADDRNOTAVAIL => return error.AddressUnavailable, + .ENOTSOCK => |err| return wsaErrorBug(err), + .EFAULT => |err| return wsaErrorBug(err), + .EINVAL => |err| return wsaErrorBug(err), + .ENOBUFS => return error.SystemResources, + .ENETDOWN => return error.NetworkDown, + else => |err| return windows.unexpectedWSAError(err), + } + }, + } + } + + syscall = try .start(); + while (true) { + const rc = ws2_32.listen(socket_handle, options.kernel_backlog); + if (rc != ws2_32.SOCKET_ERROR) { + syscall.finish(); + break; + } + switch (ws2_32.WSAGetLastError()) { + .NOTINITIALISED => { + syscall.finish(); + try initializeWsa(t); + syscall = try .start(); + continue; + }, + .EINTR, .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ENETDOWN => return error.NetworkDown, + .EADDRINUSE => return error.AddressInUse, + .EISCONN => |err| return wsaErrorBug(err), + .EINVAL => |err| return wsaErrorBug(err), + .EMFILE, .ENOBUFS => return error.SystemResources, + .ENOTSOCK => |err| return wsaErrorBug(err), + .EOPNOTSUPP => |err| return wsaErrorBug(err), + .EINPROGRESS => |err| return wsaErrorBug(err), + else => |err| return windows.unexpectedWSAError(err), + } + }, + } + } + + try wsaGetSockName(t, socket_handle, &storage.any, &addr_len); + + return .{ + .socket = .{ + .handle = socket_handle, + .address = addressFromWsa(&storage), + }, + }; +} + +fn netListenIpUnavailable( + userdata: ?*anyopaque, + address: IpAddress, + options: IpAddress.ListenOptions, +) IpAddress.ListenError!net.Server { + _ = userdata; + _ = address; + _ = options; + return error.NetworkDown; +} + +fn netListenUnixPosix( + userdata: ?*anyopaque, + address: *const net.UnixAddress, + options: net.UnixAddress.ListenOptions, +) net.UnixAddress.ListenError!net.Socket.Handle { + if (!net.has_unix_sockets) return error.AddressFamilyUnsupported; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + const socket_fd = openSocketPosix(posix.AF.UNIX, .{ .mode = .stream }) catch |err| switch (err) { + error.ProtocolUnsupportedBySystem => return error.AddressFamilyUnsupported, + error.ProtocolUnsupportedByAddressFamily => return error.AddressFamilyUnsupported, + error.SocketModeUnsupported => return error.AddressFamilyUnsupported, + error.OptionUnsupported => return error.Unexpected, + else => |e| return e, + }; + errdefer posix.close(socket_fd); + + var storage: UnixAddress = undefined; + const addr_len = addressUnixToPosix(address, &storage); + try posixBindUnix(socket_fd, &storage.any, addr_len); + + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.listen(socket_fd, options.kernel_backlog))) { + .SUCCESS => { + syscall.finish(); + break; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + .ADDRINUSE => return syscall.fail(error.AddressInUse), + .BADF => |err| return syscall.errnoBug(err), // File descriptor used after closed. + else => |err| return syscall.unexpectedErrno(err), + } + } + + return socket_fd; +} + +fn netListenUnixWindows( + userdata: ?*anyopaque, + address: *const net.UnixAddress, + options: net.UnixAddress.ListenOptions, +) net.UnixAddress.ListenError!net.Socket.Handle { + if (!net.has_unix_sockets) return error.AddressFamilyUnsupported; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + + const socket_handle = openSocketWsa(t, posix.AF.UNIX, .{ .mode = .stream }) catch |err| switch (err) { + error.ProtocolUnsupportedByAddressFamily => return error.AddressFamilyUnsupported, + else => |e| return e, + }; + errdefer closeSocketWindows(socket_handle); + + var storage: WsaAddress = undefined; + const addr_len = addressUnixToWsa(address, &storage); + + var syscall: Syscall = try .start(); + while (true) { + const rc = ws2_32.bind(socket_handle, &storage.any, addr_len); + if (rc != ws2_32.SOCKET_ERROR) break; + switch (ws2_32.WSAGetLastError()) { + .NOTINITIALISED => { + syscall.finish(); + try initializeWsa(t); + syscall = try .start(); + continue; + }, + .EINTR, .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .EADDRINUSE => return error.AddressInUse, + .EADDRNOTAVAIL => return error.AddressUnavailable, + .ENOTSOCK => |err| return wsaErrorBug(err), + .EFAULT => |err| return wsaErrorBug(err), + .EINVAL => |err| return wsaErrorBug(err), + .ENOBUFS => return error.SystemResources, + .ENETDOWN => return error.NetworkDown, + else => |err| return windows.unexpectedWSAError(err), + } + }, + } + } + + while (true) { + try syscall.checkCancel(); + const rc = ws2_32.listen(socket_handle, options.kernel_backlog); + if (rc != ws2_32.SOCKET_ERROR) { + syscall.finish(); + return socket_handle; + } + switch (ws2_32.WSAGetLastError()) { + .EINTR, .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => continue, + .NOTINITIALISED => { + syscall.finish(); + try initializeWsa(t); + syscall = try .start(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ENETDOWN => return error.NetworkDown, + .EADDRINUSE => return error.AddressInUse, + .EISCONN => |err| return wsaErrorBug(err), + .EINVAL => |err| return wsaErrorBug(err), + .EMFILE, .ENOBUFS => return error.SystemResources, + .ENOTSOCK => |err| return wsaErrorBug(err), + .EOPNOTSUPP => |err| return wsaErrorBug(err), + .EINPROGRESS => |err| return wsaErrorBug(err), + else => |err| return windows.unexpectedWSAError(err), + } + }, + } + } +} + +fn netListenUnixUnavailable( + userdata: ?*anyopaque, + address: *const net.UnixAddress, + options: net.UnixAddress.ListenOptions, +) net.UnixAddress.ListenError!net.Socket.Handle { + _ = userdata; + _ = address; + _ = options; + return error.AddressFamilyUnsupported; +} + +fn posixBindUnix( + fd: posix.socket_t, + addr: *const posix.sockaddr, + addr_len: posix.socklen_t, +) !void { + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.bind(fd, addr, addr_len))) { + .SUCCESS => { + syscall.finish(); + break; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ACCES => return error.AccessDenied, + .ADDRINUSE => return error.AddressInUse, + .AFNOSUPPORT => return error.AddressFamilyUnsupported, + .ADDRNOTAVAIL => return error.AddressUnavailable, + .NOMEM => return error.SystemResources, + + .LOOP => return error.SymLinkLoop, + .NOENT => return error.FileNotFound, + .NOTDIR => return error.NotDir, + .ROFS => return error.ReadOnlyFileSystem, + .PERM => return error.PermissionDenied, + + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .INVAL => |err| return errnoBug(err), // invalid parameters + .NOTSOCK => |err| return errnoBug(err), // invalid `sockfd` + .FAULT => |err| return errnoBug(err), // invalid `addr` pointer + .NAMETOOLONG => |err| return errnoBug(err), + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn posixBind( + socket_fd: posix.socket_t, + addr: *const posix.sockaddr, + addr_len: posix.socklen_t, +) !void { + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.bind(socket_fd, addr, addr_len))) { + .SUCCESS => { + syscall.finish(); + break; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ADDRINUSE => return error.AddressInUse, + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .INVAL => |err| return errnoBug(err), // invalid parameters + .NOTSOCK => |err| return errnoBug(err), // invalid `sockfd` + .AFNOSUPPORT => return error.AddressFamilyUnsupported, + .ADDRNOTAVAIL => return error.AddressUnavailable, + .FAULT => |err| return errnoBug(err), // invalid `addr` pointer + .NOMEM => return error.SystemResources, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn posixConnect( + socket_fd: posix.socket_t, + addr: *const posix.sockaddr, + addr_len: posix.socklen_t, +) !void { + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.connect(socket_fd, addr, addr_len))) { + .SUCCESS => { + syscall.finish(); + return; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ADDRNOTAVAIL => return error.AddressUnavailable, + .AFNOSUPPORT => return error.AddressFamilyUnsupported, + .AGAIN, .INPROGRESS => return error.WouldBlock, + .ALREADY => return error.ConnectionPending, + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .CONNREFUSED => return error.ConnectionRefused, + .CONNRESET => return error.ConnectionResetByPeer, + .FAULT => |err| return errnoBug(err), + .ISCONN => |err| return errnoBug(err), + .HOSTUNREACH => return error.HostUnreachable, + .NETUNREACH => return error.NetworkUnreachable, + .NOTSOCK => |err| return errnoBug(err), + .PROTOTYPE => |err| return errnoBug(err), + .TIMEDOUT => return error.Timeout, + .CONNABORTED => |err| return errnoBug(err), + .ACCES => return error.AccessDenied, + .PERM => |err| return errnoBug(err), + .NOENT => |err| return errnoBug(err), + .NETDOWN => return error.NetworkDown, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn posixConnectUnix( + fd: posix.socket_t, + addr: *const posix.sockaddr, + addr_len: posix.socklen_t, +) !void { + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.connect(fd, addr, addr_len))) { + .SUCCESS => { + syscall.finish(); + return; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .AFNOSUPPORT => return error.AddressFamilyUnsupported, + .AGAIN => return error.WouldBlock, + .INPROGRESS => return error.WouldBlock, + .ACCES => return error.AccessDenied, + + .LOOP => return error.SymLinkLoop, + .NOENT => return error.FileNotFound, + .NOTDIR => return error.NotDir, + .ROFS => return error.ReadOnlyFileSystem, + .PERM => return error.PermissionDenied, + + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .CONNABORTED => |err| return errnoBug(err), + .FAULT => |err| return errnoBug(err), + .ISCONN => |err| return errnoBug(err), + .NOTSOCK => |err| return errnoBug(err), + .PROTOTYPE => |err| return errnoBug(err), + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn posixGetSockName( + socket_fd: posix.fd_t, + addr: *posix.sockaddr, + addr_len: *posix.socklen_t, +) !void { + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.getsockname(socket_fd, addr, addr_len))) { + .SUCCESS => { + syscall.finish(); + break; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .FAULT => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), // invalid parameters + .NOTSOCK => |err| return errnoBug(err), // always a race condition + .NOBUFS => return error.SystemResources, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn wsaGetSockName( + t: *Threaded, + handle: ws2_32.SOCKET, + addr: *ws2_32.sockaddr, + addr_len: *i32, +) !void { + var syscall: Syscall = try .start(); + while (true) { + const rc = ws2_32.getsockname(handle, addr, addr_len); + if (rc != ws2_32.SOCKET_ERROR) { + syscall.finish(); + return; + } + switch (ws2_32.WSAGetLastError()) { + .EINTR, .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + .NOTINITIALISED => { + syscall.finish(); + try initializeWsa(t); + syscall = try .start(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ENETDOWN => return error.NetworkDown, + .EFAULT => |err| return wsaErrorBug(err), + .ENOTSOCK => |err| return wsaErrorBug(err), + .EINVAL => |err| return wsaErrorBug(err), + else => |err| return windows.unexpectedWSAError(err), + } + }, + } + } +} + +fn setSocketOption(fd: posix.fd_t, level: i32, opt_name: u32, option: u32) !void { + const o: []const u8 = @ptrCast(&option); + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.setsockopt(fd, level, opt_name, o.ptr, @intCast(o.len)))) { + .SUCCESS => { + syscall.finish(); + return; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .NOTSOCK => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), + .FAULT => |err| return errnoBug(err), + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn setSocketOptionWsa(t: *Threaded, socket: Io.net.Socket.Handle, level: i32, opt_name: u32, option: u32) !void { + const o: []const u8 = @ptrCast(&option); + var syscall: Syscall = try .start(); + const rc = ws2_32.setsockopt(socket, level, @bitCast(opt_name), o.ptr, @intCast(o.len)); + while (true) { + if (rc != ws2_32.SOCKET_ERROR) return syscall.finish(); + switch (ws2_32.WSAGetLastError()) { + .EINTR, .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + .NOTINITIALISED => { + syscall.finish(); + try initializeWsa(t); + syscall = try .start(); + continue; + }, + .ENETDOWN => return syscall.fail(error.NetworkDown), + .EFAULT, .ENOTSOCK, .EINVAL => |err| { + syscall.finish(); + return wsaErrorBug(err); + }, + else => |err| { + syscall.finish(); + return windows.unexpectedWSAError(err); + }, + } + } +} + +fn netConnectIpPosix( + userdata: ?*anyopaque, + address: *const IpAddress, + options: IpAddress.ConnectOptions, +) IpAddress.ConnectError!net.Stream { + if (!have_networking) return error.NetworkDown; + if (options.timeout != .none) @panic("TODO implement netConnectIpPosix with timeout"); + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + const family = posixAddressFamily(address); + const socket_fd = try openSocketPosix(family, .{ + .mode = options.mode, + .protocol = options.protocol, + }); + errdefer posix.close(socket_fd); + var storage: PosixAddress = undefined; + var addr_len = addressToPosix(address, &storage); + try posixConnect(socket_fd, &storage.any, addr_len); + try posixGetSockName(socket_fd, &storage.any, &addr_len); + return .{ .socket = .{ + .handle = socket_fd, + .address = addressFromPosix(&storage), + } }; +} + +fn netConnectIpWindows( + userdata: ?*anyopaque, + address: *const IpAddress, + options: IpAddress.ConnectOptions, +) IpAddress.ConnectError!net.Stream { + if (!have_networking) return error.NetworkDown; + if (options.timeout != .none) @panic("TODO implement netConnectIpWindows with timeout"); + const t: *Threaded = @ptrCast(@alignCast(userdata)); + const family = posixAddressFamily(address); + const socket_handle = try openSocketWsa(t, family, .{ + .mode = options.mode, + .protocol = options.protocol, + }); + errdefer closeSocketWindows(socket_handle); + + var storage: WsaAddress = undefined; + var addr_len = addressToWsa(address, &storage); + + var syscall: Syscall = try .start(); + while (true) { + const rc = ws2_32.connect(socket_handle, &storage.any, addr_len); + if (rc != ws2_32.SOCKET_ERROR) { + syscall.finish(); + break; + } + switch (ws2_32.WSAGetLastError()) { + .EINTR, .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + .NOTINITIALISED => { + syscall.finish(); + try initializeWsa(t); + syscall = try .start(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .EADDRNOTAVAIL => return error.AddressUnavailable, + .ECONNREFUSED => return error.ConnectionRefused, + .ECONNRESET => return error.ConnectionResetByPeer, + .ETIMEDOUT => return error.Timeout, + .EHOSTUNREACH => return error.HostUnreachable, + .ENETUNREACH => return error.NetworkUnreachable, + .EFAULT => |err| return wsaErrorBug(err), + .EINVAL => |err| return wsaErrorBug(err), + .EISCONN => |err| return wsaErrorBug(err), + .ENOTSOCK => |err| return wsaErrorBug(err), + .EWOULDBLOCK => return error.WouldBlock, + .EACCES => return error.AccessDenied, + .ENOBUFS => return error.SystemResources, + .EAFNOSUPPORT => return error.AddressFamilyUnsupported, + else => |err| return windows.unexpectedWSAError(err), + } + }, + } + } + + try wsaGetSockName(t, socket_handle, &storage.any, &addr_len); + + return .{ .socket = .{ + .handle = socket_handle, + .address = addressFromWsa(&storage), + } }; +} + +fn netConnectIpUnavailable( + userdata: ?*anyopaque, + address: *const IpAddress, + options: IpAddress.ConnectOptions, +) IpAddress.ConnectError!net.Stream { + _ = userdata; + _ = address; + _ = options; + return error.NetworkDown; +} + +fn netConnectUnixPosix( + userdata: ?*anyopaque, + address: *const net.UnixAddress, +) net.UnixAddress.ConnectError!net.Socket.Handle { + if (!net.has_unix_sockets) return error.AddressFamilyUnsupported; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + const socket_fd = openSocketPosix(posix.AF.UNIX, .{ .mode = .stream }) catch |err| switch (err) { + error.OptionUnsupported => return error.Unexpected, + else => |e| return e, + }; + errdefer posix.close(socket_fd); + var storage: UnixAddress = undefined; + const addr_len = addressUnixToPosix(address, &storage); + try posixConnectUnix(socket_fd, &storage.any, addr_len); + return socket_fd; +} + +fn netConnectUnixWindows( + userdata: ?*anyopaque, + address: *const net.UnixAddress, +) net.UnixAddress.ConnectError!net.Socket.Handle { + if (!net.has_unix_sockets) return error.AddressFamilyUnsupported; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + + const socket_handle = try openSocketWsa(t, posix.AF.UNIX, .{ .mode = .stream }); + errdefer closeSocketWindows(socket_handle); + var storage: WsaAddress = undefined; + const addr_len = addressUnixToWsa(address, &storage); + + var syscall: Syscall = try .start(); + while (true) { + const rc = ws2_32.connect(socket_handle, &storage.any, addr_len); + if (rc != ws2_32.SOCKET_ERROR) break; + switch (ws2_32.WSAGetLastError()) { + .EINTR, .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + .NOTINITIALISED => { + syscall.finish(); + try initializeWsa(t); + syscall = try .start(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ECONNREFUSED => return error.FileNotFound, + .EFAULT => |err| return wsaErrorBug(err), + .EINVAL => |err| return wsaErrorBug(err), + .EISCONN => |err| return wsaErrorBug(err), + .ENOTSOCK => |err| return wsaErrorBug(err), + .EWOULDBLOCK => return error.WouldBlock, + .EACCES => return error.AccessDenied, + .ENOBUFS => return error.SystemResources, + .EAFNOSUPPORT => return error.AddressFamilyUnsupported, + else => |err| return windows.unexpectedWSAError(err), + } + }, + } + } + + return socket_handle; +} + +fn netConnectUnixUnavailable( + userdata: ?*anyopaque, + address: *const net.UnixAddress, +) net.UnixAddress.ConnectError!net.Socket.Handle { + _ = userdata; + _ = address; + return error.AddressFamilyUnsupported; +} + +fn netBindIpPosix( + userdata: ?*anyopaque, + address: *const IpAddress, + options: IpAddress.BindOptions, +) IpAddress.BindError!net.Socket { + if (!have_networking) return error.NetworkDown; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + const family = posixAddressFamily(address); + const socket_fd = try openSocketPosix(family, options); + errdefer posix.close(socket_fd); + var storage: PosixAddress = undefined; + var addr_len = addressToPosix(address, &storage); + try posixBind(socket_fd, &storage.any, addr_len); + try posixGetSockName(socket_fd, &storage.any, &addr_len); + return .{ + .handle = socket_fd, + .address = addressFromPosix(&storage), + }; +} + +fn netBindIpWindows( + userdata: ?*anyopaque, + address: *const IpAddress, + options: IpAddress.BindOptions, +) IpAddress.BindError!net.Socket { + if (!have_networking) return error.NetworkDown; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + const family = posixAddressFamily(address); + const socket_handle = try openSocketWsa(t, family, .{ + .mode = options.mode, + .protocol = options.protocol, + }); + errdefer closeSocketWindows(socket_handle); + + var storage: WsaAddress = undefined; + var addr_len = addressToWsa(address, &storage); + + var syscall: Syscall = try .start(); + while (true) { + const rc = ws2_32.bind(socket_handle, &storage.any, addr_len); + if (rc != ws2_32.SOCKET_ERROR) { + syscall.finish(); + break; + } + switch (ws2_32.WSAGetLastError()) { + .EINTR, .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + .NOTINITIALISED => { + syscall.finish(); + try initializeWsa(t); + syscall = try .start(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .EADDRINUSE => return error.AddressInUse, + .EADDRNOTAVAIL => return error.AddressUnavailable, + .ENOTSOCK => |err| return wsaErrorBug(err), + .EFAULT => |err| return wsaErrorBug(err), + .EINVAL => |err| return wsaErrorBug(err), + .ENOBUFS => return error.SystemResources, + .ENETDOWN => return error.NetworkDown, + else => |err| return windows.unexpectedWSAError(err), + } + }, + } + } + + try wsaGetSockName(t, socket_handle, &storage.any, &addr_len); + + return .{ + .handle = socket_handle, + .address = addressFromWsa(&storage), + }; +} + +fn netBindIpUnavailable( + userdata: ?*anyopaque, + address: *const IpAddress, + options: IpAddress.BindOptions, +) IpAddress.BindError!net.Socket { + _ = userdata; + _ = address; + _ = options; + return error.NetworkDown; +} + +fn openSocketPosix( + family: posix.sa_family_t, + options: IpAddress.BindOptions, +) error{ + AddressFamilyUnsupported, + ProtocolUnsupportedBySystem, + ProcessFdQuotaExceeded, + SystemFdQuotaExceeded, + SystemResources, + ProtocolUnsupportedByAddressFamily, + SocketModeUnsupported, + OptionUnsupported, + Unexpected, + Canceled, +}!posix.socket_t { + const mode = posixSocketMode(options.mode); + const protocol = posixProtocol(options.protocol); + const syscall: Syscall = try .start(); + const socket_fd = while (true) { + const flags: u32 = mode | if (socket_flags_unsupported) 0 else posix.SOCK.CLOEXEC; + const socket_rc = posix.system.socket(family, flags, protocol); + switch (posix.errno(socket_rc)) { + .SUCCESS => { + const fd: posix.fd_t = @intCast(socket_rc); + errdefer posix.close(fd); + if (socket_flags_unsupported) while (true) { + try syscall.checkCancel(); + switch (posix.errno(posix.system.fcntl(fd, posix.F.SETFD, @as(usize, posix.FD_CLOEXEC)))) { + .SUCCESS => break, + .INTR => continue, + else => |err| { + syscall.finish(); + return posix.unexpectedErrno(err); + }, + } + }; + syscall.finish(); + break fd; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .AFNOSUPPORT => return error.AddressFamilyUnsupported, + .INVAL => return error.ProtocolUnsupportedBySystem, + .MFILE => return error.ProcessFdQuotaExceeded, + .NFILE => return error.SystemFdQuotaExceeded, + .NOBUFS => return error.SystemResources, + .NOMEM => return error.SystemResources, + .PROTONOSUPPORT => return error.ProtocolUnsupportedByAddressFamily, + .PROTOTYPE => return error.SocketModeUnsupported, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + }; + errdefer posix.close(socket_fd); + + if (options.ip6_only) { + if (posix.IPV6 == void) return error.OptionUnsupported; + try setSocketOption(socket_fd, posix.IPPROTO.IPV6, posix.IPV6.V6ONLY, 0); + } + + return socket_fd; +} + +fn openSocketWsa( + t: *Threaded, + family: posix.sa_family_t, + options: IpAddress.BindOptions, +) !ws2_32.SOCKET { + const mode = posixSocketMode(options.mode); + const protocol = posixProtocol(options.protocol); + const flags: u32 = ws2_32.WSA_FLAG_OVERLAPPED | ws2_32.WSA_FLAG_NO_HANDLE_INHERIT; + var syscall: Syscall = try .start(); + while (true) { + const rc = ws2_32.WSASocketW(family, @bitCast(mode), @bitCast(protocol), null, 0, flags); + if (rc != ws2_32.INVALID_SOCKET) { + syscall.finish(); + return rc; + } + switch (ws2_32.WSAGetLastError()) { + .EINTR, .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + .NOTINITIALISED => { + syscall.finish(); + try initializeWsa(t); + syscall = try .start(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .EAFNOSUPPORT => return error.AddressFamilyUnsupported, + .EMFILE => return error.ProcessFdQuotaExceeded, + .ENOBUFS => return error.SystemResources, + .EPROTONOSUPPORT => return error.ProtocolUnsupportedByAddressFamily, + else => |err| return windows.unexpectedWSAError(err), + } + }, + } + } +} + +fn netAcceptPosix(userdata: ?*anyopaque, listen_fd: net.Socket.Handle) net.Server.AcceptError!net.Stream { + if (!have_networking) return error.NetworkDown; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + var storage: PosixAddress = undefined; + var addr_len: posix.socklen_t = @sizeOf(PosixAddress); + const syscall: Syscall = try .start(); + const fd = while (true) { + const rc = if (have_accept4) + posix.system.accept4(listen_fd, &storage.any, &addr_len, posix.SOCK.CLOEXEC) + else + posix.system.accept(listen_fd, &storage.any, &addr_len); + switch (posix.errno(rc)) { + .SUCCESS => { + const fd: posix.fd_t = @intCast(rc); + errdefer posix.close(fd); + if (!have_accept4) while (true) { + try syscall.checkCancel(); + switch (posix.errno(posix.system.fcntl(fd, posix.F.SETFD, @as(usize, posix.FD_CLOEXEC)))) { + .SUCCESS => break, + .INTR => continue, + else => |err| { + syscall.finish(); + return posix.unexpectedErrno(err); + }, + } + }; + syscall.finish(); + break fd; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .AGAIN => |err| return errnoBug(err), + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .CONNABORTED => return error.ConnectionAborted, + .FAULT => |err| return errnoBug(err), + .INVAL => return error.SocketNotListening, + .NOTSOCK => |err| return errnoBug(err), + .MFILE => return error.ProcessFdQuotaExceeded, + .NFILE => return error.SystemFdQuotaExceeded, + .NOBUFS => return error.SystemResources, + .NOMEM => return error.SystemResources, + .OPNOTSUPP => |err| return errnoBug(err), + .PROTO => return error.ProtocolFailure, + .PERM => return error.BlockedByFirewall, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + }; + return .{ .socket = .{ + .handle = fd, + .address = addressFromPosix(&storage), + } }; +} + +fn netAcceptWindows(userdata: ?*anyopaque, listen_handle: net.Socket.Handle) net.Server.AcceptError!net.Stream { + if (!have_networking) return error.NetworkDown; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + var storage: WsaAddress = undefined; + var addr_len: i32 = @sizeOf(WsaAddress); + var syscall: Syscall = try .start(); + while (true) { + const rc = ws2_32.accept(listen_handle, &storage.any, &addr_len); + if (rc != ws2_32.INVALID_SOCKET) { + syscall.finish(); + return .{ .socket = .{ + .handle = rc, + .address = addressFromWsa(&storage), + } }; + } + switch (ws2_32.WSAGetLastError()) { + .EINTR, .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + .NOTINITIALISED => { + syscall.finish(); + try initializeWsa(t); + syscall = try .start(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ECONNRESET => return error.ConnectionAborted, + .EFAULT => |err| return wsaErrorBug(err), + .ENOTSOCK => |err| return wsaErrorBug(err), + .EINVAL => |err| return wsaErrorBug(err), + .EMFILE => return error.ProcessFdQuotaExceeded, + .ENETDOWN => return error.NetworkDown, + .ENOBUFS => return error.SystemResources, + .EOPNOTSUPP => |err| return wsaErrorBug(err), + else => |err| return windows.unexpectedWSAError(err), + } + }, + } + } +} + +fn netAcceptUnavailable(userdata: ?*anyopaque, listen_handle: net.Socket.Handle) net.Server.AcceptError!net.Stream { + _ = userdata; + _ = listen_handle; + return error.NetworkDown; +} + +fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize { + if (!have_networking) return error.NetworkDown; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + var iovecs_buffer: [max_iovecs_len]posix.iovec = undefined; + var i: usize = 0; + for (data) |buf| { + if (iovecs_buffer.len - i == 0) break; + if (buf.len != 0) { + iovecs_buffer[i] = .{ .base = buf.ptr, .len = buf.len }; + i += 1; + } + } + const dest = iovecs_buffer[0..i]; + assert(dest[0].len > 0); + + if (native_os == .wasi and !builtin.link_libc) { + const syscall: Syscall = try .start(); + while (true) { + var n: usize = undefined; + switch (std.os.wasi.fd_read(fd, dest.ptr, dest.len, &n)) { + .SUCCESS => { + syscall.finish(); + return n; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .INVAL => |err| return errnoBug(err), + .FAULT => |err| return errnoBug(err), + .AGAIN => |err| return errnoBug(err), + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .NOBUFS => return error.SystemResources, + .NOMEM => return error.SystemResources, + .NOTCONN => return error.SocketUnconnected, + .CONNRESET => return error.ConnectionResetByPeer, + .TIMEDOUT => return error.Timeout, + .NOTCAPABLE => return error.AccessDenied, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } + } + + const syscall: Syscall = try .start(); + while (true) { + const rc = posix.system.readv(fd, dest.ptr, @intCast(dest.len)); + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + return @intCast(rc); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .INVAL => |err| return errnoBug(err), + .FAULT => |err| return errnoBug(err), + .AGAIN => |err| return errnoBug(err), + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .NOBUFS => return error.SystemResources, + .NOMEM => return error.SystemResources, + .NOTCONN => return error.SocketUnconnected, + .CONNRESET => return error.ConnectionResetByPeer, + .TIMEDOUT => return error.Timeout, + .PIPE => return error.SocketUnconnected, + .NETDOWN => return error.NetworkDown, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn netReadWindows(userdata: ?*anyopaque, handle: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize { + if (!have_networking) return error.NetworkDown; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + + const bufs = b: { + var iovec_buffer: [max_iovecs_len]ws2_32.WSABUF = undefined; + var i: usize = 0; + var n: usize = 0; + for (data) |buf| { + if (iovec_buffer.len - i == 0) break; + if (buf.len == 0) continue; + if (std.math.cast(u32, buf.len)) |len| { + iovec_buffer[i] = .{ .buf = buf.ptr, .len = len }; + i += 1; + n += len; + continue; + } + iovec_buffer[i] = .{ .buf = buf.ptr, .len = std.math.maxInt(u32) }; + i += 1; + n += std.math.maxInt(u32); + break; + } + + const bufs = iovec_buffer[0..i]; + assert(bufs[0].len != 0); + + break :b bufs; + }; + + var syscall: Syscall = try .start(); + while (true) { + var flags: u32 = 0; + var n: u32 = undefined; + const rc = ws2_32.WSARecv(handle, bufs.ptr, @intCast(bufs.len), &n, &flags, null, null); + if (rc != ws2_32.SOCKET_ERROR) { + syscall.finish(); + return n; + } + switch (ws2_32.WSAGetLastError()) { + .EINTR, .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + .NOTINITIALISED => { + syscall.finish(); + try initializeWsa(t); + syscall = try .start(); + continue; + }, + + .ECONNRESET => return syscall.fail(error.ConnectionResetByPeer), + .ENETDOWN => return syscall.fail(error.NetworkDown), + .ENETRESET => return syscall.fail(error.ConnectionResetByPeer), + .ENOTCONN => return syscall.fail(error.SocketUnconnected), + .EFAULT => unreachable, // a pointer is not completely contained in user address space. + + else => |err| { + syscall.finish(); + switch (err) { + .EINVAL => return wsaErrorBug(err), + .EMSGSIZE => return wsaErrorBug(err), + else => return windows.unexpectedWSAError(err), + } + }, + } + } +} + +fn netReadUnavailable(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize { + _ = userdata; + _ = fd; + _ = data; + return error.NetworkDown; +} + +fn netSendPosix( + userdata: ?*anyopaque, + handle: net.Socket.Handle, + messages: []net.OutgoingMessage, + flags: net.SendFlags, +) struct { ?net.Socket.SendError, usize } { + if (!have_networking) return .{ error.NetworkDown, 0 }; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + + const posix_flags: u32 = + @as(u32, if (@hasDecl(posix.MSG, "CONFIRM") and flags.confirm) posix.MSG.CONFIRM else 0) | + @as(u32, if (@hasDecl(posix.MSG, "DONTROUTE") and flags.dont_route) posix.MSG.DONTROUTE else 0) | + @as(u32, if (@hasDecl(posix.MSG, "EOR") and flags.eor) posix.MSG.EOR else 0) | + @as(u32, if (@hasDecl(posix.MSG, "OOB") and flags.oob) posix.MSG.OOB else 0) | + @as(u32, if (@hasDecl(posix.MSG, "FASTOPEN") and flags.fastopen) posix.MSG.FASTOPEN else 0) | + posix.MSG.NOSIGNAL; + + var i: usize = 0; + while (messages.len - i != 0) { + if (have_sendmmsg) { + i += netSendMany(handle, messages[i..], posix_flags) catch |err| return .{ err, i }; + continue; + } + netSendOne(t, handle, &messages[i], posix_flags) catch |err| return .{ err, i }; + i += 1; + } + return .{ null, i }; +} + +fn netSendWindows( + userdata: ?*anyopaque, + handle: net.Socket.Handle, + messages: []net.OutgoingMessage, + flags: net.SendFlags, +) struct { ?net.Socket.SendError, usize } { + if (!have_networking) return .{ error.NetworkDown, 0 }; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + _ = handle; + _ = messages; + _ = flags; + @panic("TODO netSendWindows"); +} + +fn netSendUnavailable( + userdata: ?*anyopaque, + handle: net.Socket.Handle, + messages: []net.OutgoingMessage, + flags: net.SendFlags, +) struct { ?net.Socket.SendError, usize } { + _ = userdata; + _ = handle; + _ = messages; + _ = flags; + return .{ error.NetworkDown, 0 }; +} + +fn netSendOne( + t: *Threaded, + handle: net.Socket.Handle, + message: *net.OutgoingMessage, + flags: u32, +) net.Socket.SendError!void { + var addr: PosixAddress = undefined; + var iovec: posix.iovec_const = .{ .base = @constCast(message.data_ptr), .len = message.data_len }; + const msg: posix.msghdr_const = .{ + .name = &addr.any, + .namelen = addressToPosix(message.address, &addr), + .iov = (&iovec)[0..1], + .iovlen = 1, + // OS returns EINVAL if this pointer is invalid even if controllen is zero. + .control = if (message.control.len == 0) null else @constCast(message.control.ptr), + .controllen = @intCast(message.control.len), + .flags = 0, + }; + var syscall: Syscall = try .start(); + while (true) { + const rc = posix.system.sendmsg(handle, &msg, flags); + if (is_windows) { + if (rc != ws2_32.SOCKET_ERROR) { + syscall.finish(); + message.data_len = @intCast(rc); + return; + } + switch (ws2_32.WSAGetLastError()) { + .EINTR, .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + .NOTINITIALISED => { + syscall.finish(); + try initializeWsa(t); + syscall = try .start(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .EACCES => return error.AccessDenied, + .EADDRNOTAVAIL => return error.AddressUnavailable, + .ECONNRESET => return error.ConnectionResetByPeer, + .EMSGSIZE => return error.MessageOversize, + .ENOBUFS => return error.SystemResources, + .ENOTSOCK => return error.FileDescriptorNotASocket, + .EAFNOSUPPORT => return error.AddressFamilyUnsupported, + .EDESTADDRREQ => unreachable, // A destination address is required. + .EFAULT => unreachable, // The lpBuffers, lpTo, lpOverlapped, lpNumberOfBytesSent, or lpCompletionRoutine parameters are not part of the user address space, or the lpTo parameter is too small. + .EHOSTUNREACH => return error.NetworkUnreachable, + .EINVAL => unreachable, + .ENETDOWN => return error.NetworkDown, + .ENETRESET => return error.ConnectionResetByPeer, + .ENETUNREACH => return error.NetworkUnreachable, + .ENOTCONN => return error.SocketUnconnected, + .ESHUTDOWN => |err| return wsaErrorBug(err), + else => |err| return windows.unexpectedWSAError(err), + } + }, + } + } + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + message.data_len = @intCast(rc); + return; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ACCES => return error.AccessDenied, + .ALREADY => return error.FastOpenAlreadyInProgress, + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .CONNRESET => return error.ConnectionResetByPeer, + .DESTADDRREQ => |err| return errnoBug(err), + .FAULT => |err| return errnoBug(err), + .INVAL => |err| return errnoBug(err), + .ISCONN => |err| return errnoBug(err), + .MSGSIZE => return error.MessageOversize, + .NOBUFS => return error.SystemResources, + .NOMEM => return error.SystemResources, + .NOTSOCK => |err| return errnoBug(err), + .OPNOTSUPP => |err| return errnoBug(err), + .PIPE => return error.SocketUnconnected, + .AFNOSUPPORT => return error.AddressFamilyUnsupported, + .HOSTUNREACH => return error.HostUnreachable, + .NETUNREACH => return error.NetworkUnreachable, + .NOTCONN => return error.SocketUnconnected, + .NETDOWN => return error.NetworkDown, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn netSendMany( + handle: net.Socket.Handle, + messages: []net.OutgoingMessage, + flags: u32, +) net.Socket.SendError!usize { + var msg_buffer: [64]posix.system.mmsghdr = undefined; + var addr_buffer: [msg_buffer.len]PosixAddress = undefined; + var iovecs_buffer: [msg_buffer.len]posix.iovec = undefined; + const min_len: usize = @min(messages.len, msg_buffer.len); + const clamped_messages = messages[0..min_len]; + const clamped_msgs = (&msg_buffer)[0..min_len]; + const clamped_addrs = (&addr_buffer)[0..min_len]; + const clamped_iovecs = (&iovecs_buffer)[0..min_len]; + + for (clamped_messages, clamped_msgs, clamped_addrs, clamped_iovecs) |*message, *msg, *addr, *iovec| { + iovec.* = .{ .base = @constCast(message.data_ptr), .len = message.data_len }; + msg.* = .{ + .hdr = .{ + .name = &addr.any, + .namelen = addressToPosix(message.address, addr), + .iov = iovec[0..1], + .iovlen = 1, + .control = @constCast(message.control.ptr), + .controllen = message.control.len, + .flags = 0, + }, + .len = undefined, // Populated by calling sendmmsg below. + }; + } + + const syscall: Syscall = try .start(); + while (true) { + const rc = posix.system.sendmmsg(handle, clamped_msgs.ptr, @intCast(clamped_msgs.len), flags); + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + const n: usize = @intCast(rc); + for (clamped_messages[0..n], clamped_msgs[0..n]) |*message, *msg| { + message.data_len = msg.len; + } + return n; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .AGAIN => |err| return errnoBug(err), + .ALREADY => return error.FastOpenAlreadyInProgress, + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .CONNRESET => return error.ConnectionResetByPeer, + .DESTADDRREQ => |err| return errnoBug(err), // The socket is not connection-mode, and no peer address is set. + .FAULT => |err| return errnoBug(err), // An invalid user space address was specified for an argument. + .INVAL => |err| return errnoBug(err), // Invalid argument passed. + .ISCONN => |err| return errnoBug(err), // connection-mode socket was connected already but a recipient was specified + .MSGSIZE => return error.MessageOversize, + .NOBUFS => return error.SystemResources, + .NOMEM => return error.SystemResources, + .NOTSOCK => |err| return errnoBug(err), // The file descriptor sockfd does not refer to a socket. + .OPNOTSUPP => |err| return errnoBug(err), // Some bit in the flags argument is inappropriate for the socket type. + .PIPE => return error.SocketUnconnected, + .AFNOSUPPORT => return error.AddressFamilyUnsupported, + .HOSTUNREACH => return error.HostUnreachable, + .NETUNREACH => return error.NetworkUnreachable, + .NOTCONN => return error.SocketUnconnected, + .NETDOWN => return error.NetworkDown, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn netReceivePosix( + userdata: ?*anyopaque, + handle: net.Socket.Handle, + message_buffer: []net.IncomingMessage, + data_buffer: []u8, + flags: net.ReceiveFlags, + timeout: Io.Timeout, +) struct { ?net.Socket.ReceiveTimeoutError, usize } { + if (!have_networking) return .{ error.NetworkDown, 0 }; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + const t_io = io(t); + + // recvmmsg is useless, here's why: + // * [timeout bug](https://bugzilla.kernel.org/show_bug.cgi?id=75371) + // * it wants iovecs for each message but we have a better API: one data + // buffer to handle all the messages. The better API cannot be lowered to + // the split vectors though because reducing the buffer size might make + // some messages unreceivable. + + // So the strategy instead is to use non-blocking recvmsg calls, calling + // poll() with timeout if the first one returns EAGAIN. + const posix_flags: u32 = + @as(u32, if (flags.oob) posix.MSG.OOB else 0) | + @as(u32, if (flags.peek) posix.MSG.PEEK else 0) | + @as(u32, if (flags.trunc) posix.MSG.TRUNC else 0) | + posix.MSG.DONTWAIT | posix.MSG.NOSIGNAL; + + var poll_fds: [1]posix.pollfd = .{ + .{ + .fd = handle, + .events = posix.POLL.IN, + .revents = undefined, + }, + }; + var message_i: usize = 0; + var data_i: usize = 0; + + const deadline = timeout.toDeadline(t_io) catch |err| return .{ err, message_i }; + + recv: while (true) { + if (message_buffer.len - message_i == 0) return .{ null, message_i }; + const message = &message_buffer[message_i]; + const remaining_data_buffer = data_buffer[data_i..]; + var storage: PosixAddress = undefined; + var iov: posix.iovec = .{ .base = remaining_data_buffer.ptr, .len = remaining_data_buffer.len }; + var msg: posix.msghdr = .{ + .name = &storage.any, + .namelen = @sizeOf(PosixAddress), + .iov = (&iov)[0..1], + .iovlen = 1, + .control = message.control.ptr, + .controllen = @intCast(message.control.len), + .flags = undefined, + }; + + const recv_rc = rc: { + const syscall = Syscall.start() catch |err| return .{ err, message_i }; + const rc = posix.system.recvmsg(handle, &msg, posix_flags); + syscall.finish(); + break :rc rc; + }; + switch (posix.errno(recv_rc)) { + .SUCCESS => { + const data = remaining_data_buffer[0..@intCast(recv_rc)]; + data_i += data.len; + message.* = .{ + .from = addressFromPosix(&storage), + .data = data, + .control = if (msg.control) |ptr| @as([*]u8, @ptrCast(ptr))[0..msg.controllen] else message.control, + .flags = .{ + .eor = (msg.flags & posix.MSG.EOR) != 0, + .trunc = (msg.flags & posix.MSG.TRUNC) != 0, + .ctrunc = (msg.flags & posix.MSG.CTRUNC) != 0, + .oob = (msg.flags & posix.MSG.OOB) != 0, + .errqueue = if (@hasDecl(posix.MSG, "ERRQUEUE")) (msg.flags & posix.MSG.ERRQUEUE) != 0 else false, + }, + }; + message_i += 1; + continue; + }, + .AGAIN => while (true) { + if (message_i != 0) return .{ null, message_i }; + + const max_poll_ms = std.math.maxInt(u31); + const timeout_ms: u31 = if (deadline) |d| t: { + const duration = d.durationFromNow(t_io) catch |err| return .{ err, message_i }; + if (duration.raw.nanoseconds <= 0) return .{ error.Timeout, message_i }; + break :t @intCast(@min(max_poll_ms, duration.raw.toMilliseconds())); + } else max_poll_ms; + + const syscall = Syscall.start() catch |err| return .{ err, message_i }; + const poll_rc = posix.system.poll(&poll_fds, poll_fds.len, timeout_ms); + syscall.finish(); + + switch (posix.errno(poll_rc)) { + .SUCCESS => { + if (poll_rc == 0) { + // Although spurious timeouts are OK, when no deadline + // is passed we must not return `error.Timeout`. + if (deadline == null) continue; + return .{ error.Timeout, message_i }; + } + continue :recv; + }, + .INTR => continue, + + .FAULT => |err| return .{ errnoBug(err), message_i }, + .INVAL => |err| return .{ errnoBug(err), message_i }, + .NOMEM => return .{ error.SystemResources, message_i }, + else => |err| return .{ posix.unexpectedErrno(err), message_i }, + } + }, + .INTR => continue, + + .BADF => |err| return .{ errnoBug(err), message_i }, + .NFILE => return .{ error.SystemFdQuotaExceeded, message_i }, + .MFILE => return .{ error.ProcessFdQuotaExceeded, message_i }, + .FAULT => |err| return .{ errnoBug(err), message_i }, + .INVAL => |err| return .{ errnoBug(err), message_i }, + .NOBUFS => return .{ error.SystemResources, message_i }, + .NOMEM => return .{ error.SystemResources, message_i }, + .NOTCONN => return .{ error.SocketUnconnected, message_i }, + .NOTSOCK => |err| return .{ errnoBug(err), message_i }, + .MSGSIZE => return .{ error.MessageOversize, message_i }, + .PIPE => return .{ error.SocketUnconnected, message_i }, + .OPNOTSUPP => |err| return .{ errnoBug(err), message_i }, + .CONNRESET => return .{ error.ConnectionResetByPeer, message_i }, + .NETDOWN => return .{ error.NetworkDown, message_i }, + else => |err| return .{ posix.unexpectedErrno(err), message_i }, + } + } +} + +fn netReceiveWindows( + userdata: ?*anyopaque, + handle: net.Socket.Handle, + message_buffer: []net.IncomingMessage, + data_buffer: []u8, + flags: net.ReceiveFlags, + timeout: Io.Timeout, +) struct { ?net.Socket.ReceiveTimeoutError, usize } { + if (!have_networking) return .{ error.NetworkDown, 0 }; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + _ = handle; + _ = message_buffer; + _ = data_buffer; + _ = flags; + _ = timeout; + @panic("TODO implement netReceiveWindows"); +} + +fn netReceiveUnavailable( + userdata: ?*anyopaque, + handle: net.Socket.Handle, + message_buffer: []net.IncomingMessage, + data_buffer: []u8, + flags: net.ReceiveFlags, + timeout: Io.Timeout, +) struct { ?net.Socket.ReceiveTimeoutError, usize } { + _ = userdata; + _ = handle; + _ = message_buffer; + _ = data_buffer; + _ = flags; + _ = timeout; + return .{ error.NetworkDown, 0 }; +} + +fn netWritePosix( + userdata: ?*anyopaque, + fd: net.Socket.Handle, + header: []const u8, + data: []const []const u8, + splat: usize, +) net.Stream.Writer.Error!usize { + if (!have_networking) return error.NetworkDown; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + var iovecs: [max_iovecs_len]posix.iovec_const = undefined; + var msg: posix.msghdr_const = .{ + .name = null, + .namelen = 0, + .iov = &iovecs, + .iovlen = 0, + .control = null, + .controllen = 0, + .flags = 0, + }; + addBuf(&iovecs, &msg.iovlen, header); + for (data[0 .. data.len - 1]) |bytes| addBuf(&iovecs, &msg.iovlen, bytes); + const pattern = data[data.len - 1]; + if (iovecs.len - msg.iovlen != 0) switch (splat) { + 0 => {}, + 1 => addBuf(&iovecs, &msg.iovlen, pattern), + else => switch (pattern.len) { + 0 => {}, + 1 => { + var backup_buffer: [splat_buffer_size]u8 = undefined; + const splat_buffer = &backup_buffer; + const memset_len = @min(splat_buffer.len, splat); + const buf = splat_buffer[0..memset_len]; + @memset(buf, pattern[0]); + addBuf(&iovecs, &msg.iovlen, buf); + var remaining_splat = splat - buf.len; + while (remaining_splat > splat_buffer.len and iovecs.len - msg.iovlen != 0) { + assert(buf.len == splat_buffer.len); + addBuf(&iovecs, &msg.iovlen, splat_buffer); + remaining_splat -= splat_buffer.len; + } + addBuf(&iovecs, &msg.iovlen, splat_buffer[0..@min(remaining_splat, splat_buffer.len)]); + }, + else => for (0..@min(splat, iovecs.len - msg.iovlen)) |_| { + addBuf(&iovecs, &msg.iovlen, pattern); + }, + }, + }; + const flags = posix.MSG.NOSIGNAL; + + const syscall: Syscall = try .start(); + while (true) { + const rc = posix.system.sendmsg(fd, &msg, flags); + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + return @intCast(rc); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ACCES => |err| return errnoBug(err), + .AGAIN => |err| return errnoBug(err), + .ALREADY => return error.FastOpenAlreadyInProgress, + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .CONNRESET => return error.ConnectionResetByPeer, + .DESTADDRREQ => |err| return errnoBug(err), // The socket is not connection-mode, and no peer address is set. + .FAULT => |err| return errnoBug(err), // An invalid user space address was specified for an argument. + .INVAL => |err| return errnoBug(err), // Invalid argument passed. + .ISCONN => |err| return errnoBug(err), // connection-mode socket was connected already but a recipient was specified + .MSGSIZE => |err| return errnoBug(err), + .NOBUFS => return error.SystemResources, + .NOMEM => return error.SystemResources, + .NOTSOCK => |err| return errnoBug(err), // The file descriptor sockfd does not refer to a socket. + .OPNOTSUPP => |err| return errnoBug(err), // Some bit in the flags argument is inappropriate for the socket type. + .PIPE => return error.SocketUnconnected, + .AFNOSUPPORT => return error.AddressFamilyUnsupported, + .HOSTUNREACH => return error.HostUnreachable, + .NETUNREACH => return error.NetworkUnreachable, + .NOTCONN => return error.SocketUnconnected, + .NETDOWN => return error.NetworkDown, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn netWriteWindows( + userdata: ?*anyopaque, + handle: net.Socket.Handle, + header: []const u8, + data: []const []const u8, + splat: usize, +) net.Stream.Writer.Error!usize { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + comptime assert(native_os == .windows); + + var iovecs: [max_iovecs_len]ws2_32.WSABUF = undefined; + var len: u32 = 0; + addWsaBuf(&iovecs, &len, header); + for (data[0 .. data.len - 1]) |bytes| addWsaBuf(&iovecs, &len, bytes); + const pattern = data[data.len - 1]; + if (iovecs.len - len != 0) switch (splat) { + 0 => {}, + 1 => addWsaBuf(&iovecs, &len, pattern), + else => switch (pattern.len) { + 0 => {}, + 1 => { + var backup_buffer: [64]u8 = undefined; + const splat_buffer = &backup_buffer; + const memset_len = @min(splat_buffer.len, splat); + const buf = splat_buffer[0..memset_len]; + @memset(buf, pattern[0]); + addWsaBuf(&iovecs, &len, buf); + var remaining_splat = splat - buf.len; + while (remaining_splat > splat_buffer.len and len < iovecs.len) { + addWsaBuf(&iovecs, &len, splat_buffer); + remaining_splat -= splat_buffer.len; + } + addWsaBuf(&iovecs, &len, splat_buffer[0..@min(remaining_splat, splat_buffer.len)]); + }, + else => for (0..@min(splat, iovecs.len - len)) |_| { + addWsaBuf(&iovecs, &len, pattern); + }, + }, + }; + + var syscall: Syscall = try .start(); + while (true) { + var n: u32 = undefined; + const rc = ws2_32.WSASend(handle, &iovecs, len, &n, 0, null, null); + if (rc != ws2_32.SOCKET_ERROR) { + syscall.finish(); + return n; + } + switch (ws2_32.WSAGetLastError()) { + .IO_PENDING => unreachable, // not overlapped + .EINTR, .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + .NOTINITIALISED => { + syscall.finish(); + try initializeWsa(t); + syscall = try .start(); + continue; + }, + + .ECONNABORTED => return syscall.fail(error.ConnectionResetByPeer), + .ECONNRESET => return syscall.fail(error.ConnectionResetByPeer), + .EINVAL => return syscall.fail(error.SocketUnconnected), + .ENETDOWN => return syscall.fail(error.NetworkDown), + .ENETRESET => return syscall.fail(error.ConnectionResetByPeer), + .ENOBUFS => return syscall.fail(error.SystemResources), + .ENOTCONN => return syscall.fail(error.SocketUnconnected), + + else => |err| { + syscall.finish(); + switch (err) { + .ENOTSOCK => return wsaErrorBug(err), + .EOPNOTSUPP => return wsaErrorBug(err), + .ESHUTDOWN => return wsaErrorBug(err), + else => return windows.unexpectedWSAError(err), + } + }, + } + } +} + +fn addWsaBuf(v: []ws2_32.WSABUF, i: *u32, bytes: []const u8) void { + const cap = std.math.maxInt(u32); + var remaining = bytes; + while (remaining.len > cap) { + if (v.len - i.* == 0) return; + v[i.*] = .{ .buf = @constCast(remaining.ptr), .len = cap }; + i.* += 1; + remaining = remaining[cap..]; + } else { + @branchHint(.likely); + if (v.len - i.* == 0) return; + v[i.*] = .{ .buf = @constCast(remaining.ptr), .len = @intCast(remaining.len) }; + i.* += 1; + } +} + +fn netWriteUnavailable( + userdata: ?*anyopaque, + handle: net.Socket.Handle, + header: []const u8, + data: []const []const u8, + splat: usize, +) net.Stream.Writer.Error!usize { + _ = userdata; + _ = handle; + _ = header; + _ = data; + _ = splat; + return error.NetworkDown; +} + +/// This is either usize or u32. Since, either is fine, let's use the same +/// `addBuf` function for both writing to a file and sending network messages. +const iovlen_t = switch (native_os) { + .wasi => u32, + else => @FieldType(posix.msghdr_const, "iovlen"), +}; + +fn addBuf(v: []posix.iovec_const, i: *iovlen_t, bytes: []const u8) void { + // OS checks ptr addr before length so zero length vectors must be omitted. + if (bytes.len == 0) return; + if (v.len - i.* == 0) return; + v[i.*] = .{ .base = bytes.ptr, .len = bytes.len }; + i.* += 1; +} + +fn netClose(userdata: ?*anyopaque, handles: []const net.Socket.Handle) void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + switch (native_os) { + .windows => for (handles) |handle| closeSocketWindows(handle), + else => for (handles) |handle| posix.close(handle), + } +} + +fn netCloseUnavailable(userdata: ?*anyopaque, handles: []const net.Socket.Handle) void { + _ = userdata; + _ = handles; + unreachable; // How you gonna close something that was impossible to open? +} + +fn netShutdownPosix(userdata: ?*anyopaque, handle: net.Socket.Handle, how: net.ShutdownHow) net.ShutdownError!void { + if (!have_networking) return error.NetworkDown; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + const posix_how: i32 = switch (how) { + .recv => posix.SHUT.RD, + .send => posix.SHUT.WR, + .both => posix.SHUT.RDWR, + }; + + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.shutdown(handle, posix_how))) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .BADF, .NOTSOCK, .INVAL => |err| return errnoBug(err), + .NOTCONN => return error.SocketUnconnected, + .NOBUFS => return error.SystemResources, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } +} + +fn netShutdownWindows(userdata: ?*anyopaque, handle: net.Socket.Handle, how: net.ShutdownHow) net.ShutdownError!void { + if (!have_networking) return error.NetworkDown; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + + const wsa_how: i32 = switch (how) { + .recv => ws2_32.SD_RECEIVE, + .send => ws2_32.SD_SEND, + .both => ws2_32.SD_BOTH, + }; + + var syscall: Syscall = try .start(); + while (true) { + const rc = ws2_32.shutdown(handle, wsa_how); + if (rc != ws2_32.SOCKET_ERROR) { + syscall.finish(); + return; + } + switch (ws2_32.WSAGetLastError()) { + .EINTR, .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + .NOTINITIALISED => { + syscall.finish(); + try initializeWsa(t); + syscall = try .start(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .ECONNABORTED => return error.ConnectionAborted, + .ECONNRESET => return error.ConnectionResetByPeer, + .ENETDOWN => return error.NetworkDown, + .ENOTCONN => return error.SocketUnconnected, + .EINVAL, .ENOTSOCK => |err| return wsaErrorBug(err), + else => |err| return windows.unexpectedWSAError(err), + } + }, + } + } +} + +fn netShutdownUnavailable(_: ?*anyopaque, _: net.Socket.Handle, _: net.ShutdownHow) net.ShutdownError!void { + unreachable; // How you gonna shutdown something that was impossible to open? +} + +fn netInterfaceNameResolve( + userdata: ?*anyopaque, + name: *const net.Interface.Name, +) net.Interface.Name.ResolveError!net.Interface { + if (!have_networking) return error.InterfaceNotFound; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + if (native_os == .linux) { + const sock_fd = openSocketPosix(posix.AF.UNIX, .{ .mode = .dgram }) catch |err| switch (err) { + error.ProcessFdQuotaExceeded => return error.SystemResources, + error.SystemFdQuotaExceeded => return error.SystemResources, + error.AddressFamilyUnsupported => return error.Unexpected, + error.ProtocolUnsupportedBySystem => return error.Unexpected, + error.ProtocolUnsupportedByAddressFamily => return error.Unexpected, + error.SocketModeUnsupported => return error.Unexpected, + error.OptionUnsupported => return error.Unexpected, + else => |e| return e, + }; + defer posix.close(sock_fd); + + var ifr: posix.ifreq = .{ + .ifrn = .{ .name = @bitCast(name.bytes) }, .ifru = undefined, }; - while (true) { - try t.checkCancel(); - switch (posix.errno(posix.system.ioctl(sock_fd, posix.SIOCGIFINDEX, @intFromPtr(&ifr)))) { - .SUCCESS => return .{ .index = @bitCast(ifr.ifru.ivalue) }, - .INTR => continue, - .CANCELED => return error.Canceled, + const syscall: Syscall = try .start(); + while (true) { + switch (posix.errno(posix.system.ioctl(sock_fd, posix.SIOCGIFINDEX, @intFromPtr(&ifr)))) { + .SUCCESS => { + syscall.finish(); + return .{ .index = @bitCast(ifr.ifru.ivalue) }; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + switch (e) { + .INVAL => |err| return errnoBug(err), // Bad parameters. + .NOTTY => |err| return errnoBug(err), + .NXIO => |err| return errnoBug(err), + .BADF => |err| return errnoBug(err), // File descriptor used after closed. + .FAULT => |err| return errnoBug(err), // Bad pointer parameter. + .IO => |err| return errnoBug(err), // sock_fd is not a file descriptor + .NODEV => return error.InterfaceNotFound, + else => |err| return posix.unexpectedErrno(err), + } + }, + } + } + } + + if (native_os == .windows) { + try Thread.checkCancel(); + @panic("TODO implement netInterfaceNameResolve for Windows"); + } + + if (builtin.link_libc) { + try Thread.checkCancel(); + const index = std.c.if_nametoindex(&name.bytes); + if (index == 0) return error.InterfaceNotFound; + return .{ .index = @bitCast(index) }; + } + + @panic("unimplemented"); +} + +fn netInterfaceNameResolveUnavailable( + userdata: ?*anyopaque, + name: *const net.Interface.Name, +) net.Interface.Name.ResolveError!net.Interface { + _ = userdata; + _ = name; + return error.InterfaceNotFound; +} + +fn netInterfaceName(userdata: ?*anyopaque, interface: net.Interface) net.Interface.NameError!net.Interface.Name { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + try Thread.checkCancel(); + + if (native_os == .linux) { + _ = interface; + @panic("TODO implement netInterfaceName for linux"); + } + + if (native_os == .windows) { + @panic("TODO implement netInterfaceName for windows"); + } + + if (builtin.link_libc) { + @panic("TODO implement netInterfaceName for libc"); + } + + @panic("unimplemented"); +} + +fn netInterfaceNameUnavailable(userdata: ?*anyopaque, interface: net.Interface) net.Interface.NameError!net.Interface.Name { + _ = userdata; + _ = interface; + return error.Unexpected; +} + +fn netLookup( + userdata: ?*anyopaque, + host_name: HostName, + resolved: *Io.Queue(HostName.LookupResult), + options: HostName.LookupOptions, +) net.HostName.LookupError!void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + defer resolved.close(io(t)); + netLookupFallible(t, host_name, resolved, options) catch |err| switch (err) { + error.Closed => unreachable, // `resolved` must not be closed until `netLookup` returns + else => |e| return e, + }; +} + +fn netLookupUnavailable( + userdata: ?*anyopaque, + host_name: HostName, + resolved: *Io.Queue(HostName.LookupResult), + options: HostName.LookupOptions, +) net.HostName.LookupError!void { + _ = host_name; + _ = options; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + resolved.close(ioBasic(t)); + return error.NetworkDown; +} + +fn netLookupFallible( + t: *Threaded, + host_name: HostName, + resolved: *Io.Queue(HostName.LookupResult), + options: HostName.LookupOptions, +) (net.HostName.LookupError || Io.QueueClosedError)!void { + if (!have_networking) return error.NetworkDown; + + const t_io = io(t); + const name = host_name.bytes; + assert(name.len <= HostName.max_len); + + if (is_windows) { + var name_buffer: [HostName.max_len + 1]u16 = undefined; + const name_len = std.unicode.wtf8ToWtf16Le(&name_buffer, host_name.bytes) catch + unreachable; // HostName is prevalidated. + name_buffer[name_len] = 0; + const name_w = name_buffer[0..name_len :0]; + + var port_buffer: [8]u8 = undefined; + var port_buffer_wide: [8]u16 = undefined; + const port = std.fmt.bufPrint(&port_buffer, "{d}", .{options.port}) catch + unreachable; // `port_buffer` is big enough for decimal u16. + for (port, port_buffer_wide[0..port.len]) |byte, *wide| + wide.* = std.mem.nativeToLittle(u16, byte); + port_buffer_wide[port.len] = 0; + const port_w = port_buffer_wide[0..port.len :0]; + + const hints: ws2_32.ADDRINFOEXW = .{ + .flags = .{ .NUMERICSERV = true }, + .family = if (options.family) |f| switch (f) { + .ip4 => posix.AF.INET, + .ip6 => posix.AF.INET6, + } else posix.AF.UNSPEC, + .socktype = posix.SOCK.STREAM, + .protocol = posix.IPPROTO.TCP, + .canonname = null, + .addr = null, + .addrlen = 0, + .blob = null, + .bloblen = 0, + .provider = null, + .next = null, + }; + var res: *ws2_32.ADDRINFOEXW = undefined; + const timeout: ?*ws2_32.timeval = null; + while (true) { + // TODO: hook this up to cancelation with `Thread.Status.cancelation.blocked_windows_dns`. + // See matching TODO in `Thread.cancelAwaitable`. + try Thread.checkCancel(); + // TODO make this append to the queue eagerly rather than blocking until the whole thing finishes + const rc: ws2_32.WinsockError = @enumFromInt(ws2_32.GetAddrInfoExW(name_w, port_w, .DNS, null, &hints, &res, timeout, null, null, null)); + switch (rc) { + @as(ws2_32.WinsockError, @enumFromInt(0)) => break, + .EINTR, .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => continue, + .NOTINITIALISED => { + try initializeWsa(t); + continue; + }, + .TRY_AGAIN => return error.NameServerFailure, + .EINVAL => |err| return wsaErrorBug(err), + .NO_RECOVERY => return error.NameServerFailure, + .EAFNOSUPPORT => return error.AddressFamilyUnsupported, + .NOT_ENOUGH_MEMORY => return error.SystemResources, + .HOST_NOT_FOUND => return error.UnknownHostName, + .TYPE_NOT_FOUND => return error.ProtocolUnsupportedByAddressFamily, + .ESOCKTNOSUPPORT => return error.ProtocolUnsupportedBySystem, + else => |err| return windows.unexpectedWSAError(err), + } + } + defer ws2_32.FreeAddrInfoExW(res); + + var it: ?*ws2_32.ADDRINFOEXW = res; + var canon_name: ?[*:0]const u16 = null; + while (it) |info| : (it = info.next) { + const addr = info.addr orelse continue; + try resolved.putOne(t_io, .{ .address = addressFromWsa(@alignCast(@fieldParentPtr("any", addr))) }); + + if (info.canonname) |n| { + if (canon_name == null) { + canon_name = n; + } + } + } + if (canon_name) |n| { + const len = std.unicode.wtf16LeToWtf8(options.canonical_name_buffer, std.mem.sliceTo(n, 0)); + try resolved.putOne(t_io, .{ .canonical_name = .{ + .bytes = options.canonical_name_buffer[0..len], + } }); + } + return; + } + + // On Linux, glibc provides getaddrinfo_a which is capable of supporting our semantics. + // However, musl's POSIX-compliant getaddrinfo is not, so we bypass it. + + if (builtin.target.isGnuLibC()) { + // TODO use getaddrinfo_a / gai_cancel + } + + if (native_os == .linux) { + if (options.family != .ip4) { + if (IpAddress.parseIp6(name, options.port)) |addr| { + try resolved.putAll(t_io, &.{ + .{ .address = addr }, + .{ .canonical_name = copyCanon(options.canonical_name_buffer, name) }, + }); + return; + } else |_| {} + } + + if (options.family != .ip6) { + if (IpAddress.parseIp4(name, options.port)) |addr| { + try resolved.putAll(t_io, &.{ + .{ .address = addr }, + .{ .canonical_name = copyCanon(options.canonical_name_buffer, name) }, + }); + return; + } else |_| {} + } + + lookupHosts(t, host_name, resolved, options) catch |err| switch (err) { + error.UnknownHostName => {}, + else => |e| return e, + }; + + // RFC 6761 Section 6.3.3 + // Name resolution APIs and libraries SHOULD recognize + // localhost names as special and SHOULD always return the IP + // loopback address for address queries and negative responses + // for all other query types. + + // Check for equal to "localhost(.)" or ends in ".localhost(.)" + const localhost = if (name[name.len - 1] == '.') "localhost." else "localhost"; + if (std.mem.endsWith(u8, name, localhost) and + (name.len == localhost.len or name[name.len - localhost.len] == '.')) + { + var results_buffer: [3]HostName.LookupResult = undefined; + var results_index: usize = 0; + if (options.family != .ip4) { + results_buffer[results_index] = .{ .address = .{ .ip6 = .loopback(options.port) } }; + results_index += 1; + } + if (options.family != .ip6) { + results_buffer[results_index] = .{ .address = .{ .ip4 = .loopback(options.port) } }; + results_index += 1; + } + const canon_name = "localhost"; + const canon_name_dest = options.canonical_name_buffer[0..canon_name.len]; + canon_name_dest.* = canon_name.*; + results_buffer[results_index] = .{ .canonical_name = .{ .bytes = canon_name_dest } }; + results_index += 1; + try resolved.putAll(t_io, results_buffer[0..results_index]); + return; + } + + return lookupDnsSearch(t, host_name, resolved, options); + } + + if (native_os == .openbsd) { + // TODO use getaddrinfo_async / asr_abort + } + + if (native_os == .freebsd) { + // TODO use dnsres_getaddrinfo + } + + if (is_darwin) { + // TODO use CFHostStartInfoResolution / CFHostCancelInfoResolution + } + + if (builtin.link_libc) { + // This operating system lacks a way to resolve asynchronously. We are + // stuck with getaddrinfo. + var name_buffer: [HostName.max_len + 1]u8 = undefined; + @memcpy(name_buffer[0..host_name.bytes.len], host_name.bytes); + name_buffer[host_name.bytes.len] = 0; + const name_c = name_buffer[0..host_name.bytes.len :0]; + + var port_buffer: [8]u8 = undefined; + const port_c = std.fmt.bufPrintZ(&port_buffer, "{d}", .{options.port}) catch unreachable; + + const hints: posix.addrinfo = .{ + .flags = .{ .NUMERICSERV = true }, + .family = posix.AF.UNSPEC, + .socktype = posix.SOCK.STREAM, + .protocol = posix.IPPROTO.TCP, + .canonname = null, + .addr = null, + .addrlen = 0, + .next = null, + }; + var res: ?*posix.addrinfo = null; + const syscall: Syscall = try .start(); + while (true) { + switch (posix.system.getaddrinfo(name_c.ptr, port_c.ptr, &hints, &res)) { + @as(posix.system.EAI, @enumFromInt(0)) => { + syscall.finish(); + break; + }, + .SYSTEM => switch (posix.errno(-1)) { + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => |e| { + syscall.finish(); + return posix.unexpectedErrno(e); + }, + }, + else => |e| { + syscall.finish(); + switch (e) { + .ADDRFAMILY => return error.AddressFamilyUnsupported, + .AGAIN => return error.NameServerFailure, + .FAIL => return error.NameServerFailure, + .FAMILY => return error.AddressFamilyUnsupported, + .MEMORY => return error.SystemResources, + .NODATA => return error.UnknownHostName, + .NONAME => return error.UnknownHostName, + else => return error.Unexpected, + } + }, + } + } + defer if (res) |some| posix.system.freeaddrinfo(some); + + var it = res; + var canon_name: ?[*:0]const u8 = null; + while (it) |info| : (it = info.next) { + const addr = info.addr orelse continue; + try resolved.putOne(t_io, .{ .address = addressFromPosix(@alignCast(@fieldParentPtr("any", addr))) }); + + if (info.canonname) |n| { + if (canon_name == null) { + canon_name = n; + } + } + } + if (canon_name) |n| { + try resolved.putOne(t_io, .{ + .canonical_name = copyCanon(options.canonical_name_buffer, std.mem.sliceTo(n, 0)), + }); + } + return; + } + + return error.OptionUnsupported; +} + +fn lockStderr(userdata: ?*anyopaque, terminal_mode: ?Io.Terminal.Mode) Io.Cancelable!Io.LockedStderr { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + // Only global mutex since this is Threaded. + process.stderr_thread_mutex.lock(); + return initLockedStderr(t, terminal_mode); +} + +fn tryLockStderr(userdata: ?*anyopaque, terminal_mode: ?Io.Terminal.Mode) Io.Cancelable!?Io.LockedStderr { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + // Only global mutex since this is Threaded. + if (!process.stderr_thread_mutex.tryLock()) return null; + return try initLockedStderr(t, terminal_mode); +} + +fn initLockedStderr(t: *Threaded, terminal_mode: ?Io.Terminal.Mode) Io.Cancelable!Io.LockedStderr { + if (!t.stderr_writer_initialized) { + const io_t = ioBasic(t); + if (is_windows) t.stderr_writer.file = .stderr(); + t.stderr_writer.io = io_t; + t.stderr_writer_initialized = true; + t.scanEnviron(); + const NO_COLOR = t.environ.exist.NO_COLOR; + const CLICOLOR_FORCE = t.environ.exist.CLICOLOR_FORCE; + t.stderr_mode = terminal_mode orelse try .detect(io_t, t.stderr_writer.file, NO_COLOR, CLICOLOR_FORCE); + } + return .{ + .file_writer = &t.stderr_writer, + .terminal_mode = terminal_mode orelse t.stderr_mode, + }; +} + +fn unlockStderr(userdata: ?*anyopaque) void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + t.stderr_writer.interface.flush() catch |err| switch (err) { + error.WriteFailed => switch (t.stderr_writer.err.?) { + error.Canceled => recancelInner(), + else => {}, + }, + }; + t.stderr_writer.interface.end = 0; + t.stderr_writer.interface.buffer = &.{}; + process.stderr_thread_mutex.unlock(); +} + +fn processSetCurrentDir(userdata: ?*anyopaque, dir: Dir) process.SetCurrentDirError!void { + if (native_os == .wasi) return error.OperationUnsupported; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + + if (is_windows) { + var dir_path_buffer: [windows.PATH_MAX_WIDE]u16 = undefined; + // TODO move GetFinalPathNameByHandle logic into std.Io.Threaded and add cancel checks + try Thread.checkCancel(); + const dir_path = try windows.GetFinalPathNameByHandle(dir.handle, .{}, &dir_path_buffer); + const path_len_bytes = std.math.cast(u16, dir_path.len * 2) orelse return error.NameTooLong; + var nt_name: windows.UNICODE_STRING = .{ + .Length = path_len_bytes, + .MaximumLength = path_len_bytes, + .Buffer = @constCast(dir_path.ptr), + }; + const syscall: Syscall = try .start(); + while (true) switch (windows.ntdll.RtlSetCurrentDirectory_U(&nt_name)) { + .SUCCESS => return syscall.finish(), + .OBJECT_NAME_INVALID => return syscall.fail(error.BadPathName), + .OBJECT_NAME_NOT_FOUND => return syscall.fail(error.FileNotFound), + .OBJECT_PATH_NOT_FOUND => return syscall.fail(error.FileNotFound), + .NO_MEDIA_IN_DEVICE => return syscall.fail(error.NoDevice), + .INVALID_PARAMETER => |err| return syscall.ntstatusBug(err), + .ACCESS_DENIED => return syscall.fail(error.AccessDenied), + .OBJECT_PATH_SYNTAX_BAD => |err| return syscall.ntstatusBug(err), + .NOT_A_DIRECTORY => return syscall.fail(error.NotDir), + .CANCELLED => { + try syscall.checkCancel(); + continue; + }, + else => |status| return syscall.unexpectedNtstatus(status), + }; + } + + return fchdir(dir.handle); +} + +pub const PosixAddress = extern union { + any: posix.sockaddr, + in: posix.sockaddr.in, + in6: posix.sockaddr.in6, +}; + +const UnixAddress = extern union { + any: posix.sockaddr, + un: posix.sockaddr.un, +}; + +const WsaAddress = extern union { + any: ws2_32.sockaddr, + in: ws2_32.sockaddr.in, + in6: ws2_32.sockaddr.in6, + un: ws2_32.sockaddr.un, +}; + +pub fn posixAddressFamily(a: *const IpAddress) posix.sa_family_t { + return switch (a.*) { + .ip4 => posix.AF.INET, + .ip6 => posix.AF.INET6, + }; +} + +pub fn addressFromPosix(posix_address: *const PosixAddress) IpAddress { + return switch (posix_address.any.family) { + posix.AF.INET => .{ .ip4 = address4FromPosix(&posix_address.in) }, + posix.AF.INET6 => .{ .ip6 = address6FromPosix(&posix_address.in6) }, + else => .{ .ip4 = .loopback(0) }, + }; +} + +fn addressFromWsa(wsa_address: *const WsaAddress) IpAddress { + return switch (wsa_address.any.family) { + posix.AF.INET => .{ .ip4 = address4FromWsa(&wsa_address.in) }, + posix.AF.INET6 => .{ .ip6 = address6FromWsa(&wsa_address.in6) }, + else => .{ .ip4 = .loopback(0) }, + }; +} + +pub fn addressToPosix(a: *const IpAddress, storage: *PosixAddress) posix.socklen_t { + return switch (a.*) { + .ip4 => |ip4| { + storage.in = address4ToPosix(ip4); + return @sizeOf(posix.sockaddr.in); + }, + .ip6 => |*ip6| { + storage.in6 = address6ToPosix(ip6); + return @sizeOf(posix.sockaddr.in6); + }, + }; +} + +fn addressToWsa(a: *const IpAddress, storage: *WsaAddress) i32 { + return switch (a.*) { + .ip4 => |ip4| { + storage.in = address4ToPosix(ip4); + return @sizeOf(posix.sockaddr.in); + }, + .ip6 => |*ip6| { + storage.in6 = address6ToPosix(ip6); + return @sizeOf(posix.sockaddr.in6); + }, + }; +} + +fn addressUnixToPosix(a: *const net.UnixAddress, storage: *UnixAddress) posix.socklen_t { + @memcpy(storage.un.path[0..a.path.len], a.path); + storage.un.family = posix.AF.UNIX; + storage.un.path[a.path.len] = 0; + return @sizeOf(posix.sockaddr.un); +} + +fn addressUnixToWsa(a: *const net.UnixAddress, storage: *WsaAddress) i32 { + @memcpy(storage.un.path[0..a.path.len], a.path); + storage.un.family = posix.AF.UNIX; + storage.un.path[a.path.len] = 0; + return @sizeOf(posix.sockaddr.un); +} + +fn address4FromPosix(in: *const posix.sockaddr.in) net.Ip4Address { + return .{ + .port = std.mem.bigToNative(u16, in.port), + .bytes = @bitCast(in.addr), + }; +} + +fn address6FromPosix(in6: *const posix.sockaddr.in6) net.Ip6Address { + return .{ + .port = std.mem.bigToNative(u16, in6.port), + .bytes = in6.addr, + .flow = in6.flowinfo, + .interface = .{ .index = in6.scope_id }, + }; +} + +fn address4FromWsa(in: *const ws2_32.sockaddr.in) net.Ip4Address { + return .{ + .port = std.mem.bigToNative(u16, in.port), + .bytes = @bitCast(in.addr), + }; +} + +fn address6FromWsa(in6: *const ws2_32.sockaddr.in6) net.Ip6Address { + return .{ + .port = std.mem.bigToNative(u16, in6.port), + .bytes = in6.addr, + .flow = in6.flowinfo, + .interface = .{ .index = in6.scope_id }, + }; +} + +fn address4ToPosix(a: net.Ip4Address) posix.sockaddr.in { + return .{ + .port = std.mem.nativeToBig(u16, a.port), + .addr = @bitCast(a.bytes), + }; +} + +fn address6ToPosix(a: *const net.Ip6Address) posix.sockaddr.in6 { + return .{ + .port = std.mem.nativeToBig(u16, a.port), + .flowinfo = a.flow, + .addr = a.bytes, + .scope_id = a.interface.index, + }; +} + +pub fn errnoBug(err: posix.E) Io.UnexpectedError { + if (is_debug) std.debug.panic("programmer bug caused syscall error: {t}", .{err}); + return error.Unexpected; +} + +fn wsaErrorBug(err: ws2_32.WinsockError) Io.UnexpectedError { + if (is_debug) std.debug.panic("programmer bug caused syscall error: {t}", .{err}); + return error.Unexpected; +} + +pub fn posixSocketMode(mode: net.Socket.Mode) u32 { + return switch (mode) { + .stream => posix.SOCK.STREAM, + .dgram => posix.SOCK.DGRAM, + .seqpacket => posix.SOCK.SEQPACKET, + .raw => posix.SOCK.RAW, + .rdm => posix.SOCK.RDM, + }; +} + +pub fn posixProtocol(protocol: ?net.Protocol) u32 { + return @intFromEnum(protocol orelse return 0); +} + +fn recoverableOsBugDetected() void { + if (is_debug) unreachable; +} + +fn clockToPosix(clock: Io.Clock) posix.clockid_t { + return switch (clock) { + .real => posix.CLOCK.REALTIME, + .awake => switch (native_os) { + .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => posix.CLOCK.UPTIME_RAW, + else => posix.CLOCK.MONOTONIC, + }, + .boot => switch (native_os) { + .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => posix.CLOCK.MONOTONIC_RAW, + // On freebsd derivatives, use MONOTONIC_FAST as currently there's + // no precision tradeoff. + .freebsd, .dragonfly => posix.CLOCK.MONOTONIC_FAST, + // On linux, use BOOTTIME instead of MONOTONIC as it ticks while + // suspended. + .linux => posix.CLOCK.BOOTTIME, + // On other posix systems, MONOTONIC is generally the fastest and + // ticks while suspended. + else => posix.CLOCK.MONOTONIC, + }, + .cpu_process => posix.CLOCK.PROCESS_CPUTIME_ID, + .cpu_thread => posix.CLOCK.THREAD_CPUTIME_ID, + }; +} + +fn clockToWasi(clock: Io.Clock) std.os.wasi.clockid_t { + return switch (clock) { + .real => .REALTIME, + .awake => .MONOTONIC, + .boot => .MONOTONIC, + .cpu_process => .PROCESS_CPUTIME_ID, + .cpu_thread => .THREAD_CPUTIME_ID, + }; +} + +const linux_statx_request: std.os.linux.STATX = .{ + .TYPE = true, + .MODE = true, + .ATIME = true, + .MTIME = true, + .CTIME = true, + .INO = true, + .SIZE = true, + .NLINK = true, +}; + +const linux_statx_check: std.os.linux.STATX = .{ + .TYPE = true, + .MODE = true, + .ATIME = false, + .MTIME = true, + .CTIME = true, + .INO = true, + .SIZE = true, + .NLINK = true, +}; + +fn statFromLinux(stx: *const std.os.linux.Statx) Io.UnexpectedError!File.Stat { + const actual_mask_int: u32 = @bitCast(stx.mask); + const wanted_mask_int: u32 = @bitCast(linux_statx_check); + if ((actual_mask_int | wanted_mask_int) != actual_mask_int) return error.Unexpected; + + return .{ + .inode = stx.ino, + .nlink = stx.nlink, + .size = stx.size, + .permissions = .fromMode(stx.mode), + .kind = statxKind(stx.mode), + .atime = if (!stx.mask.ATIME) null else .{ + .nanoseconds = @intCast(@as(i128, stx.atime.sec) * std.time.ns_per_s + stx.atime.nsec), + }, + .mtime = .{ .nanoseconds = @intCast(@as(i128, stx.mtime.sec) * std.time.ns_per_s + stx.mtime.nsec) }, + .ctime = .{ .nanoseconds = @intCast(@as(i128, stx.ctime.sec) * std.time.ns_per_s + stx.ctime.nsec) }, + }; +} + +fn statxKind(stx_mode: u16) File.Kind { + return switch (stx_mode & std.os.linux.S.IFMT) { + std.os.linux.S.IFDIR => .directory, + std.os.linux.S.IFCHR => .character_device, + std.os.linux.S.IFBLK => .block_device, + std.os.linux.S.IFREG => .file, + std.os.linux.S.IFIFO => .named_pipe, + std.os.linux.S.IFLNK => .sym_link, + std.os.linux.S.IFSOCK => .unix_domain_socket, + else => .unknown, + }; +} + +fn statFromPosix(st: *const posix.Stat) File.Stat { + const atime = st.atime(); + const mtime = st.mtime(); + const ctime = st.ctime(); + return .{ + .inode = st.ino, + .nlink = st.nlink, + .size = @bitCast(st.size), + .permissions = .fromMode(st.mode), + .kind = k: { + const m = st.mode & posix.S.IFMT; + switch (m) { + posix.S.IFBLK => break :k .block_device, + posix.S.IFCHR => break :k .character_device, + posix.S.IFDIR => break :k .directory, + posix.S.IFIFO => break :k .named_pipe, + posix.S.IFLNK => break :k .sym_link, + posix.S.IFREG => break :k .file, + posix.S.IFSOCK => break :k .unix_domain_socket, + else => {}, + } + if (native_os == .illumos) switch (m) { + posix.S.IFDOOR => break :k .door, + posix.S.IFPORT => break :k .event_port, + else => {}, + }; + + break :k .unknown; + }, + .atime = timestampFromPosix(&atime), + .mtime = timestampFromPosix(&mtime), + .ctime = timestampFromPosix(&ctime), + }; +} + +fn statFromWasi(st: *const std.os.wasi.filestat_t) File.Stat { + return .{ + .inode = st.ino, + .nlink = st.nlink, + .size = @bitCast(st.size), + .permissions = .default_file, + .kind = switch (st.filetype) { + .BLOCK_DEVICE => .block_device, + .CHARACTER_DEVICE => .character_device, + .DIRECTORY => .directory, + .SYMBOLIC_LINK => .sym_link, + .REGULAR_FILE => .file, + .SOCKET_STREAM, .SOCKET_DGRAM => .unix_domain_socket, + else => .unknown, + }, + .atime = .fromNanoseconds(st.atim), + .mtime = .fromNanoseconds(st.mtim), + .ctime = .fromNanoseconds(st.ctim), + }; +} + +fn timestampFromPosix(timespec: *const posix.timespec) Io.Timestamp { + return .{ .nanoseconds = @intCast(@as(i128, timespec.sec) * std.time.ns_per_s + timespec.nsec) }; +} + +fn timestampToPosix(nanoseconds: i96) posix.timespec { + if (builtin.zig_backend == .stage2_wasm) { + // Workaround for https://codeberg.org/ziglang/zig/issues/30575 + return .{ + .sec = @intCast(@divTrunc(nanoseconds, std.time.ns_per_s)), + .nsec = @intCast(@rem(nanoseconds, std.time.ns_per_s)), + }; + } + return .{ + .sec = @intCast(@divFloor(nanoseconds, std.time.ns_per_s)), + .nsec = @intCast(@mod(nanoseconds, std.time.ns_per_s)), + }; +} + +fn setTimestampToPosix(set_ts: File.SetTimestamp) posix.timespec { + return switch (set_ts) { + .unchanged => .OMIT, + .now => .NOW, + .new => |t| timestampToPosix(t.nanoseconds), + }; +} + +fn pathToPosix(file_path: []const u8, buffer: *[posix.PATH_MAX]u8) Dir.PathNameError![:0]u8 { + if (std.mem.containsAtLeastScalar2(u8, file_path, 0, 1)) return error.BadPathName; + // >= rather than > to make room for the null byte + if (file_path.len >= buffer.len) return error.NameTooLong; + @memcpy(buffer[0..file_path.len], file_path); + buffer[file_path.len] = 0; + return buffer[0..file_path.len :0]; +} + +fn lookupDnsSearch( + t: *Threaded, + host_name: HostName, + resolved: *Io.Queue(HostName.LookupResult), + options: HostName.LookupOptions, +) (HostName.LookupError || Io.QueueClosedError)!void { + const t_io = io(t); + const rc = HostName.ResolvConf.init(t_io) catch return error.ResolvConfParseFailed; + + // Count dots, suppress search when >=ndots or name ends in + // a dot, which is an explicit request for global scope. + const dots = std.mem.countScalar(u8, host_name.bytes, '.'); + const search_len = if (dots >= rc.ndots or std.mem.endsWith(u8, host_name.bytes, ".")) 0 else rc.search_len; + const search = rc.search_buffer[0..search_len]; + + var canon_name = host_name.bytes; + + // Strip final dot for canon, fail if multiple trailing dots. + if (std.mem.endsWith(u8, canon_name, ".")) canon_name.len -= 1; + if (std.mem.endsWith(u8, canon_name, ".")) return error.UnknownHostName; + + // Name with search domain appended is set up in `canon_name`. This + // both provides the desired default canonical name (if the requested + // name is not a CNAME record) and serves as a buffer for passing the + // full requested name to `lookupDns`. + @memcpy(options.canonical_name_buffer[0..canon_name.len], canon_name); + options.canonical_name_buffer[canon_name.len] = '.'; + var it = std.mem.tokenizeAny(u8, search, " \t"); + while (it.next()) |token| { + @memcpy(options.canonical_name_buffer[canon_name.len + 1 ..][0..token.len], token); + const lookup_canon_name = options.canonical_name_buffer[0 .. canon_name.len + 1 + token.len]; + if (lookupDns(t, lookup_canon_name, &rc, resolved, options)) |result| { + return result; + } else |err| switch (err) { + error.UnknownHostName, error.NoAddressReturned => continue, + else => |e| return e, + } + } + + const lookup_canon_name = options.canonical_name_buffer[0..canon_name.len]; + return lookupDns(t, lookup_canon_name, &rc, resolved, options); +} + +fn lookupDns( + t: *Threaded, + lookup_canon_name: []const u8, + rc: *const HostName.ResolvConf, + resolved: *Io.Queue(HostName.LookupResult), + options: HostName.LookupOptions, +) (HostName.LookupError || Io.QueueClosedError)!void { + const t_io = io(t); + const family_records: [2]struct { af: IpAddress.Family, rr: HostName.DnsRecord } = .{ + .{ .af = .ip6, .rr = .A }, + .{ .af = .ip4, .rr = .AAAA }, + }; + var query_buffers: [2][280]u8 = undefined; + var answer_buffer: [2 * 512]u8 = undefined; + var queries_buffer: [2][]const u8 = undefined; + var answers_buffer: [2][]const u8 = undefined; + var nq: usize = 0; + var answer_buffer_i: usize = 0; + + for (family_records) |fr| { + if (options.family != fr.af) { + var entropy: [2]u8 = undefined; + random(t, &entropy); + const len = writeResolutionQuery(&query_buffers[nq], 0, lookup_canon_name, 1, fr.rr, entropy); + queries_buffer[nq] = query_buffers[nq][0..len]; + nq += 1; + } + } + + var ip4_mapped_buffer: [HostName.ResolvConf.max_nameservers]IpAddress = undefined; + const ip4_mapped = ip4_mapped_buffer[0..rc.nameservers_len]; + var any_ip6 = false; + for (rc.nameservers(), ip4_mapped) |*ns, *m| { + m.* = .{ .ip6 = .fromAny(ns.*) }; + any_ip6 = any_ip6 or ns.* == .ip6; + } + var socket = s: { + if (any_ip6) ip6: { + const ip6_addr: IpAddress = .{ .ip6 = .unspecified(0) }; + const socket = ip6_addr.bind(t_io, .{ .ip6_only = true, .mode = .dgram }) catch |err| switch (err) { + error.AddressFamilyUnsupported => break :ip6, + else => |e| return e, + }; + break :s socket; + } + any_ip6 = false; + const ip4_addr: IpAddress = .{ .ip4 = .unspecified(0) }; + const socket = try ip4_addr.bind(t_io, .{ .mode = .dgram }); + break :s socket; + }; + defer socket.close(t_io); + + const mapped_nameservers = if (any_ip6) ip4_mapped else rc.nameservers(); + const queries = queries_buffer[0..nq]; + const answers = answers_buffer[0..queries.len]; + var answers_remaining = answers.len; + for (answers) |*answer| answer.len = 0; + + // boot clock is chosen because time the computer is suspended should count + // against time spent waiting for external messages to arrive. + const clock: Io.Clock = .boot; + var now_ts = try clock.now(t_io); + const final_ts = now_ts.addDuration(.fromSeconds(rc.timeout_seconds)); + const attempt_duration: Io.Duration = .{ + .nanoseconds = (std.time.ns_per_s / rc.attempts) * @as(i96, rc.timeout_seconds), + }; + + send: while (now_ts.nanoseconds < final_ts.nanoseconds) : (now_ts = try clock.now(t_io)) { + const max_messages = queries_buffer.len * HostName.ResolvConf.max_nameservers; + { + var message_buffer: [max_messages]Io.net.OutgoingMessage = undefined; + var message_i: usize = 0; + for (queries, answers) |query, *answer| { + if (answer.len != 0) continue; + for (mapped_nameservers) |*ns| { + message_buffer[message_i] = .{ + .address = ns, + .data_ptr = query.ptr, + .data_len = query.len, + }; + message_i += 1; + } + } + _ = netSendPosix(t, socket.handle, message_buffer[0..message_i], .{}); + } + + const timeout: Io.Timeout = .{ .deadline = .{ + .raw = now_ts.addDuration(attempt_duration), + .clock = clock, + } }; + + while (true) { + var message_buffer: [max_messages]Io.net.IncomingMessage = @splat(.init); + const buf = answer_buffer[answer_buffer_i..]; + const recv_err, const recv_n = socket.receiveManyTimeout(t_io, &message_buffer, buf, .{}, timeout); + for (message_buffer[0..recv_n]) |*received_message| { + const reply = received_message.data; + // Ignore non-identifiable packets. + if (reply.len < 4) continue; + + // Ignore replies from addresses we didn't send to. + const ns = for (mapped_nameservers) |*ns| { + if (received_message.from.eql(ns)) break ns; + } else { + continue; + }; + + // Find which query this answer goes with, if any. + const query, const answer = for (queries, answers) |query, *answer| { + if (reply[0] == query[0] and reply[1] == query[1]) break .{ query, answer }; + } else { + continue; + }; + if (answer.len != 0) continue; + + // Only accept positive or negative responses; retry immediately on + // server failure, and ignore all other codes such as refusal. + switch (reply[3] & 15) { + 0, 3 => { + answer.* = reply; + answer_buffer_i += reply.len; + answers_remaining -= 1; + if (answer_buffer.len - answer_buffer_i == 0) break :send; + if (answers_remaining == 0) break :send; + }, + 2 => { + var retry_message: Io.net.OutgoingMessage = .{ + .address = ns, + .data_ptr = query.ptr, + .data_len = query.len, + }; + _ = netSendPosix(t, socket.handle, (&retry_message)[0..1], .{}); + continue; + }, + else => continue, + } + } + if (recv_err) |err| switch (err) { + error.Canceled => return error.Canceled, + error.Timeout => continue :send, + else => continue, + }; + } + } else { + return error.NameServerFailure; + } + + var addresses_len: usize = 0; + var canonical_name: ?HostName = null; + + for (answers) |answer| { + var it = HostName.DnsResponse.init(answer) catch { + // Here we could potentially add diagnostics to the results queue. + continue; + }; + while (it.next() catch { + // Here we could potentially add diagnostics to the results queue. + continue; + }) |record| switch (record.rr) { + .A => { + const data = record.packet[record.data_off..][0..record.data_len]; + if (data.len != 4) return error.InvalidDnsARecord; + try resolved.putOne(t_io, .{ .address = .{ .ip4 = .{ + .bytes = data[0..4].*, + .port = options.port, + } } }); + addresses_len += 1; + }, + .AAAA => { + const data = record.packet[record.data_off..][0..record.data_len]; + if (data.len != 16) return error.InvalidDnsAAAARecord; + try resolved.putOne(t_io, .{ .address = .{ .ip6 = .{ + .bytes = data[0..16].*, + .port = options.port, + } } }); + addresses_len += 1; + }, + .CNAME => { + _, canonical_name = HostName.expand(record.packet, record.data_off, options.canonical_name_buffer) catch + return error.InvalidDnsCnameRecord; + }, + _ => continue, + }; + } + + try resolved.putOne(t_io, .{ .canonical_name = canonical_name orelse .{ .bytes = lookup_canon_name } }); + if (addresses_len == 0) return error.NoAddressReturned; +} + +fn lookupHosts( + t: *Threaded, + host_name: HostName, + resolved: *Io.Queue(HostName.LookupResult), + options: HostName.LookupOptions, +) !void { + const t_io = io(t); + const file = Dir.openFileAbsolute(t_io, "/etc/hosts", .{}) catch |err| switch (err) { + error.FileNotFound, + error.NotDir, + error.AccessDenied, + => return error.UnknownHostName, + + error.Canceled => |e| return e, + + else => { + // Here we could add more detailed diagnostics to the results queue. + return error.DetectingNetworkConfigurationFailed; + }, + }; + defer file.close(t_io); + + var line_buf: [512]u8 = undefined; + var file_reader = file.reader(t_io, &line_buf); + return lookupHostsReader(t, host_name, resolved, options, &file_reader.interface) catch |err| switch (err) { + error.ReadFailed => switch (file_reader.err.?) { + error.Canceled => |e| return e, + else => { + // Here we could add more detailed diagnostics to the results queue. + return error.DetectingNetworkConfigurationFailed; + }, + }, + error.Canceled, + error.Closed, + error.UnknownHostName, + => |e| return e, + }; +} + +fn lookupHostsReader( + t: *Threaded, + host_name: HostName, + resolved: *Io.Queue(HostName.LookupResult), + options: HostName.LookupOptions, + reader: *Io.Reader, +) error{ ReadFailed, Canceled, UnknownHostName, Closed }!void { + const t_io = io(t); + var addresses_len: usize = 0; + var canonical_name: ?HostName = null; + while (true) { + const line = reader.takeDelimiterExclusive('\n') catch |err| switch (err) { + error.StreamTooLong => { + // Skip lines that are too long. + _ = reader.discardDelimiterInclusive('\n') catch |e| switch (e) { + error.EndOfStream => break, + error.ReadFailed => return error.ReadFailed, + }; + continue; + }, + error.ReadFailed => return error.ReadFailed, + error.EndOfStream => break, + }; + reader.toss(1); + var split_it = std.mem.splitScalar(u8, line, '#'); + const no_comment_line = split_it.first(); + + var line_it = std.mem.tokenizeAny(u8, no_comment_line, " \t"); + const ip_text = line_it.next() orelse continue; + var first_name_text: ?[]const u8 = null; + while (line_it.next()) |name_text| { + if (std.mem.eql(u8, name_text, host_name.bytes)) { + if (first_name_text == null) first_name_text = name_text; + break; + } + } else continue; + + if (canonical_name == null) { + if (HostName.init(first_name_text.?)) |name_text| { + if (name_text.bytes.len <= options.canonical_name_buffer.len) { + const canonical_name_dest = options.canonical_name_buffer[0..name_text.bytes.len]; + @memcpy(canonical_name_dest, name_text.bytes); + canonical_name = .{ .bytes = canonical_name_dest }; + } + } else |_| {} + } + + if (options.family != .ip6) { + if (IpAddress.parseIp4(ip_text, options.port)) |addr| { + try resolved.putOne(t_io, .{ .address = addr }); + addresses_len += 1; + } else |_| {} + } + if (options.family != .ip4) { + if (IpAddress.parseIp6(ip_text, options.port)) |addr| { + try resolved.putOne(t_io, .{ .address = addr }); + addresses_len += 1; + } else |_| {} + } + } + + if (canonical_name) |canon_name| try resolved.putOne(t_io, .{ .canonical_name = canon_name }); + if (addresses_len == 0) return error.UnknownHostName; +} + +/// Writes DNS resolution query packet data to `w`; at most 280 bytes. +fn writeResolutionQuery(q: *[280]u8, op: u4, dname: []const u8, class: u8, ty: HostName.DnsRecord, entropy: [2]u8) usize { + // This implementation is ported from musl libc. + // A more idiomatic "ziggy" implementation would be welcome. + var name = dname; + if (std.mem.endsWith(u8, name, ".")) name.len -= 1; + assert(name.len <= 253); + const n = 17 + name.len + @intFromBool(name.len != 0); + + // Construct query template - ID will be filled later + q[0..2].* = entropy; + @memset(q[2..n], 0); + q[2] = @as(u8, op) * 8 + 1; + q[5] = 1; + @memcpy(q[13..][0..name.len], name); + var i: usize = 13; + var j: usize = undefined; + while (q[i] != 0) : (i = j + 1) { + j = i; + while (q[j] != 0 and q[j] != '.') : (j += 1) {} + // TODO determine the circumstances for this and whether or + // not this should be an error. + if (j - i - 1 > 62) unreachable; + q[i - 1] = @intCast(j - i); + } + q[i + 1] = @intFromEnum(ty); + q[i + 3] = class; + return n; +} + +fn copyCanon(canonical_name_buffer: *[HostName.max_len]u8, name: []const u8) HostName { + const dest = canonical_name_buffer[0..name.len]; + @memcpy(dest, name); + return .{ .bytes = dest }; +} + +/// Darwin XNU 7195.50.7.100.1 introduced __ulock_wait2 and migrated code paths (notably pthread_cond_t) towards it: +/// https://github.com/apple/darwin-xnu/commit/d4061fb0260b3ed486147341b72468f836ed6c8f#diff-08f993cc40af475663274687b7c326cc6c3031e0db3ac8de7b24624610616be6 +/// +/// This XNU version appears to correspond to 11.0.1: +/// https://kernelshaman.blogspot.com/2021/01/building-xnu-for-macos-big-sur-1101.html +/// +/// ulock_wait() uses 32-bit micro-second timeouts where 0 = INFINITE or no-timeout +/// ulock_wait2() uses 64-bit nano-second timeouts (with the same convention) +const darwin_supports_ulock_wait2 = builtin.os.version_range.semver.min.major >= 11; + +fn closeSocketWindows(s: ws2_32.SOCKET) void { + const rc = ws2_32.closesocket(s); + if (is_debug) switch (rc) { + 0 => {}, + ws2_32.SOCKET_ERROR => switch (ws2_32.WSAGetLastError()) { + else => recoverableOsBugDetected(), + }, + else => recoverableOsBugDetected(), + }; +} + +const Wsa = struct { + status: Status = .uninitialized, + mutex: Io.Mutex = .init, + init_error: ?Wsa.InitError = null, + + const Status = enum { uninitialized, initialized, failure }; + + const InitError = error{ + ProcessFdQuotaExceeded, + NetworkDown, + VersionUnsupported, + BlockingOperationInProgress, + } || Io.UnexpectedError; +}; + +fn initializeWsa(t: *Threaded) error{ NetworkDown, Canceled }!void { + const t_io = io(t); + const wsa = &t.wsa; + try wsa.mutex.lock(t_io); + defer wsa.mutex.unlock(t_io); + switch (wsa.status) { + .uninitialized => { + var wsa_data: ws2_32.WSADATA = undefined; + const minor_version = 2; + const major_version = 2; + switch (ws2_32.WSAStartup((@as(windows.WORD, minor_version) << 8) | major_version, &wsa_data)) { + 0 => { + wsa.status = .initialized; + return; + }, + else => |err_int| { + wsa.status = .failure; + wsa.init_error = switch (@as(ws2_32.WinsockError, @enumFromInt(@as(u16, @intCast(err_int))))) { + .SYSNOTREADY => error.NetworkDown, + .VERNOTSUPPORTED => error.VersionUnsupported, + .EINPROGRESS => error.BlockingOperationInProgress, + .EPROCLIM => error.ProcessFdQuotaExceeded, + else => |err| windows.unexpectedWSAError(err), + }; + }, + } + }, + .initialized => return, + .failure => {}, + } + return error.NetworkDown; +} + +fn doNothingSignalHandler(_: posix.SIG) callconv(.c) void {} + +const WindowsEnvironStrings = struct { + PATH: ?[:0]const u16 = null, + PATHEXT: ?[:0]const u16 = null, + + fn scan() WindowsEnvironStrings { + const ptr = windows.peb().ProcessParameters.Environment; + + var result: WindowsEnvironStrings = .{}; + var i: usize = 0; + while (ptr[i] != 0) { + const key_start = i; + + // There are some special environment variables that start with =, + // so we need a special case to not treat = as a key/value separator + // if it's the first character. + // https://devblogs.microsoft.com/oldnewthing/20100506-00/?p=14133 + if (ptr[key_start] == '=') i += 1; + + while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {} + const key_w = ptr[key_start..i]; + + if (ptr[i] == '=') i += 1; + + const value_start = i; + while (ptr[i] != 0) : (i += 1) {} + const value_w = ptr[value_start..i :0]; + + i += 1; // skip over null byte - .INVAL => |err| return errnoBug(err), // Bad parameters. - .NOTTY => |err| return errnoBug(err), - .NXIO => |err| return errnoBug(err), - .BADF => |err| return errnoBug(err), // File descriptor used after closed. - .FAULT => |err| return errnoBug(err), // Bad pointer parameter. - .IO => |err| return errnoBug(err), // sock_fd is not a file descriptor - .NODEV => return error.InterfaceNotFound, - else => |err| return posix.unexpectedErrno(err), + inline for (@typeInfo(WindowsEnvironStrings).@"struct".fields) |field| { + const field_name_w = comptime std.unicode.wtf8ToWtf16LeStringLiteral(field.name); + if (std.os.windows.eqlIgnoreCaseWtf16(key_w, field_name_w)) @field(result, field.name) = value_w; } } - } - if (native_os == .windows) { - try t.checkCancel(); - @panic("TODO implement netInterfaceNameResolve for Windows"); + return result; } +}; - if (builtin.link_libc) { - try t.checkCancel(); - const index = std.c.if_nametoindex(&name.bytes); - if (index == 0) return error.InterfaceNotFound; - return .{ .index = @bitCast(index) }; - } +fn scanEnviron(t: *Threaded) void { + t.mutex.lock(); + defer t.mutex.unlock(); - @panic("unimplemented"); -} + if (t.environ.initialized) return; + t.environ.initialized = true; -fn netInterfaceNameResolveUnavailable( - userdata: ?*anyopaque, - name: *const net.Interface.Name, -) net.Interface.Name.ResolveError!net.Interface { - _ = userdata; - _ = name; - return error.InterfaceNotFound; + if (is_windows) { + // This value expires with any call that modifies the environment, + // which is outside of this Io implementation's control, so references + // must be short-lived. + const ptr = windows.peb().ProcessParameters.Environment; + + var i: usize = 0; + while (ptr[i] != 0) { + const key_start = i; + + // There are some special environment variables that start with =, + // so we need a special case to not treat = as a key/value separator + // if it's the first character. + // https://devblogs.microsoft.com/oldnewthing/20100506-00/?p=14133 + if (ptr[key_start] == '=') i += 1; + + while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {} + const key_w = ptr[key_start..i]; + if (std.mem.eql(u16, key_w, &.{ 'N', 'O', '_', 'C', 'O', 'L', 'O', 'R' })) { + t.environ.exist.NO_COLOR = true; + } else if (std.mem.eql(u16, key_w, &.{ 'C', 'L', 'I', 'C', 'O', 'L', 'O', 'R', '_', 'F', 'O', 'R', 'C', 'E' })) { + t.environ.exist.CLICOLOR_FORCE = true; + } + comptime assert(@sizeOf(Environ.String) == 0); + + while (ptr[i] != 0) : (i += 1) {} // skip over '=' and value + i += 1; // skip over null byte + } + } else if (native_os == .wasi and !builtin.link_libc) { + var environ_count: usize = undefined; + var environ_buf_size: usize = undefined; + + switch (std.os.wasi.environ_sizes_get(&environ_count, &environ_buf_size)) { + .SUCCESS => {}, + else => |err| { + t.environ.err = posix.unexpectedErrno(err); + return; + }, + } + if (environ_count == 0) return; + + const environ = t.allocator.alloc([*:0]u8, environ_count) catch |err| { + t.environ.err = err; + return; + }; + defer t.allocator.free(environ); + const environ_buf = t.allocator.alloc(u8, environ_buf_size) catch |err| { + t.environ.err = err; + return; + }; + defer t.allocator.free(environ_buf); + + switch (std.os.wasi.environ_get(environ.ptr, environ_buf.ptr)) { + .SUCCESS => {}, + else => |err| { + t.environ.err = posix.unexpectedErrno(err); + return; + }, + } + + for (environ) |env| { + const pair = std.mem.sliceTo(env, 0); + var parts = std.mem.splitScalar(u8, pair, '='); + const key = parts.first(); + if (std.mem.eql(u8, key, "NO_COLOR")) { + t.environ.exist.NO_COLOR = true; + } else if (std.mem.eql(u8, key, "CLICOLOR_FORCE")) { + t.environ.exist.CLICOLOR_FORCE = true; + } + comptime assert(@sizeOf(Environ.String) == 0); + } + } else { + for (t.environ.process_environ.block) |opt_line| { + const line = opt_line.?; + var line_i: usize = 0; + while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {} + const key = line[0..line_i]; + + var end_i: usize = line_i; + while (line[end_i] != 0) : (end_i += 1) {} + const value = line[line_i + 1 .. end_i :0]; + + if (std.mem.eql(u8, key, "NO_COLOR")) { + t.environ.exist.NO_COLOR = true; + } else if (std.mem.eql(u8, key, "CLICOLOR_FORCE")) { + t.environ.exist.CLICOLOR_FORCE = true; + } else if (std.mem.eql(u8, key, "ZIG_PROGRESS")) { + t.environ.zig_progress_handle = std.fmt.parseInt(u31, value, 10) catch error.UnrecognizedFormat; + } else inline for (@typeInfo(Environ.String).@"struct".fields) |field| { + if (std.mem.eql(u8, key, field.name)) @field(t.environ.string, field.name) = value; + } + } + } } -fn netInterfaceName(userdata: ?*anyopaque, interface: net.Interface) net.Interface.NameError!net.Interface.Name { +fn processReplace(userdata: ?*anyopaque, options: process.ReplaceOptions) process.ReplaceError { const t: *Threaded = @ptrCast(@alignCast(userdata)); - try t.checkCancel(); - if (native_os == .linux) { - _ = interface; - @panic("TODO implement netInterfaceName for linux"); - } + if (!process.can_replace) return error.OperationUnsupported; - if (native_os == .windows) { - @panic("TODO implement netInterfaceName for windows"); - } + t.scanEnviron(); // for PATH + const PATH = t.environ.string.PATH orelse default_PATH; - if (builtin.link_libc) { - @panic("TODO implement netInterfaceName for libc"); - } + var arena_allocator = std.heap.ArenaAllocator.init(t.allocator); + defer arena_allocator.deinit(); + const arena = arena_allocator.allocator(); - @panic("unimplemented"); + const argv_buf = try arena.allocSentinel(?[*:0]const u8, options.argv.len, null); + for (options.argv, 0..) |arg, i| argv_buf[i] = (try arena.dupeZ(u8, arg)).ptr; + + const envp: [*:null]const ?[*:0]const u8 = m: { + const prog_fd: i32 = -1; + if (options.environ_map) |environ_map| { + break :m (try environ_map.createBlockPosix(arena, .{ + .zig_progress_fd = prog_fd, + })).ptr; + } + break :m (try process.Environ.createBlockPosix(t.environ.process_environ, arena, .{ + .zig_progress_fd = prog_fd, + })).ptr; + }; + + return posixExecv(options.expand_arg0, argv_buf.ptr[0].?, argv_buf.ptr, envp, PATH); } -fn netInterfaceNameUnavailable(userdata: ?*anyopaque, interface: net.Interface) net.Interface.NameError!net.Interface.Name { +fn processReplacePath(userdata: ?*anyopaque, dir: Dir, options: process.ReplaceOptions) process.ReplaceError { + if (!process.can_replace) return error.OperationUnsupported; _ = userdata; - _ = interface; - return error.Unexpected; + _ = dir; + _ = options; + @panic("TODO processReplacePath"); } -fn netLookup( - userdata: ?*anyopaque, - host_name: HostName, - resolved: *Io.Queue(HostName.LookupResult), - options: HostName.LookupOptions, -) void { - const t: *Threaded = @ptrCast(@alignCast(userdata)); - const t_io = io(t); - resolved.putOneUncancelable(t_io, .{ .end = netLookupFallible(t, host_name, resolved, options) }); +fn processSpawnPath(userdata: ?*anyopaque, dir: Dir, options: process.SpawnOptions) process.SpawnError!process.Child { + if (!process.can_spawn) return error.OperationUnsupported; + _ = userdata; + _ = dir; + _ = options; + @panic("TODO processSpawnPath"); } -fn netLookupUnavailable( - userdata: ?*anyopaque, - host_name: HostName, - resolved: *Io.Queue(HostName.LookupResult), - options: HostName.LookupOptions, -) void { - _ = host_name; +const processSpawn = switch (native_os) { + .wasi, .ios, .tvos, .visionos, .watchos => processSpawnUnsupported, + .windows => processSpawnWindows, + else => processSpawnPosix, +}; + +fn processSpawnUnsupported(userdata: ?*anyopaque, options: process.SpawnOptions) process.SpawnError!process.Child { + _ = userdata; _ = options; - const t: *Threaded = @ptrCast(@alignCast(userdata)); - const t_io = ioBasic(t); - resolved.putOneUncancelable(t_io, .{ .end = error.NetworkDown }); + return error.OperationUnsupported; } -fn netLookupFallible( - t: *Threaded, - host_name: HostName, - resolved: *Io.Queue(HostName.LookupResult), - options: HostName.LookupOptions, -) !void { - if (!have_networking) return error.NetworkDown; - const t_io = io(t); - const name = host_name.bytes; - assert(name.len <= HostName.max_len); +const Spawned = struct { + pid: posix.pid_t, + err_fd: posix.fd_t, + stdin: ?File, + stdout: ?File, + stderr: ?File, +}; - if (is_windows) { - var name_buffer: [HostName.max_len + 1]u16 = undefined; - const name_len = std.unicode.wtf8ToWtf16Le(&name_buffer, host_name.bytes) catch - unreachable; // HostName is prevalidated. - name_buffer[name_len] = 0; - const name_w = name_buffer[0..name_len :0]; +fn spawnPosix(t: *Threaded, options: process.SpawnOptions) process.SpawnError!Spawned { + // The child process does need to access (one end of) these pipes. However, + // we must initially set CLOEXEC to avoid a race condition. If another thread + // is racing to spawn a different child process, we don't want it to inherit + // these FDs in any scenario; that would mean that, for instance, calls to + // `poll` from the parent would not report the child's stdout as closing when + // expected, since the other child may retain a reference to the write end of + // the pipe. So, we create the pipes with CLOEXEC initially. After fork, we + // need to do something in the new child to make sure we preserve the reference + // we want. We could use `fcntl` to remove CLOEXEC from the FD, but as it + // turns out, we `dup2` everything anyway, so there's no need! + const pipe_flags: posix.O = .{ .CLOEXEC = true }; + + const stdin_pipe = if (options.stdin == .pipe) try pipe2(pipe_flags) else undefined; + errdefer if (options.stdin == .pipe) { + destroyPipe(stdin_pipe); + }; - var port_buffer: [8]u8 = undefined; - var port_buffer_wide: [8]u16 = undefined; - const port = std.fmt.bufPrint(&port_buffer, "{d}", .{options.port}) catch - unreachable; // `port_buffer` is big enough for decimal u16. - for (port, port_buffer_wide[0..port.len]) |byte, *wide| - wide.* = std.mem.nativeToLittle(u16, byte); - port_buffer_wide[port.len] = 0; - const port_w = port_buffer_wide[0..port.len :0]; + const stdout_pipe = if (options.stdout == .pipe) try pipe2(pipe_flags) else undefined; + errdefer if (options.stdout == .pipe) { + destroyPipe(stdout_pipe); + }; - const hints: ws2_32.ADDRINFOEXW = .{ - .flags = .{ .NUMERICSERV = true }, - .family = if (options.family) |f| switch (f) { - .ip4 => posix.AF.INET, - .ip6 => posix.AF.INET6, - } else posix.AF.UNSPEC, - .socktype = posix.SOCK.STREAM, - .protocol = posix.IPPROTO.TCP, - .canonname = null, - .addr = null, - .addrlen = 0, - .blob = null, - .bloblen = 0, - .provider = null, - .next = null, - }; - const cancel_handle: ?*windows.HANDLE = null; - var res: *ws2_32.ADDRINFOEXW = undefined; - const timeout: ?*ws2_32.timeval = null; - while (true) { - try t.checkCancel(); // TODO make requestCancel call GetAddrInfoExCancel - // TODO make this append to the queue eagerly rather than blocking until - // the whole thing finishes - const rc: ws2_32.WinsockError = @enumFromInt(ws2_32.GetAddrInfoExW(name_w, port_w, .DNS, null, &hints, &res, timeout, null, null, cancel_handle)); - switch (rc) { - @as(ws2_32.WinsockError, @enumFromInt(0)) => break, - .EINTR => continue, - .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => return error.Canceled, - .NOTINITIALISED => { - try initializeWsa(t); - continue; - }, - .TRY_AGAIN => return error.NameServerFailure, - .EINVAL => |err| return wsaErrorBug(err), - .NO_RECOVERY => return error.NameServerFailure, - .EAFNOSUPPORT => return error.AddressFamilyUnsupported, - .NOT_ENOUGH_MEMORY => return error.SystemResources, - .HOST_NOT_FOUND => return error.UnknownHostName, - .TYPE_NOT_FOUND => return error.ProtocolUnsupportedByAddressFamily, - .ESOCKTNOSUPPORT => return error.ProtocolUnsupportedBySystem, - else => |err| return windows.unexpectedWSAError(err), - } - } - defer ws2_32.FreeAddrInfoExW(res); + const stderr_pipe = if (options.stderr == .pipe) try pipe2(pipe_flags) else undefined; + errdefer if (options.stderr == .pipe) { + destroyPipe(stderr_pipe); + }; - var it: ?*ws2_32.ADDRINFOEXW = res; - var canon_name: ?[*:0]const u16 = null; - while (it) |info| : (it = info.next) { - const addr = info.addr orelse continue; - const storage: WsaAddress = .{ .any = addr.* }; - try resolved.putOne(t_io, .{ .address = addressFromWsa(&storage) }); + const any_ignore = (options.stdin == .ignore or options.stdout == .ignore or options.stderr == .ignore); + const dev_null_fd = if (any_ignore) try getDevNullFd(t) else undefined; - if (info.canonname) |n| { - if (canon_name == null) { - canon_name = n; - } - } + const prog_pipe: [2]posix.fd_t = p: { + if (options.progress_node.index == .none) { + break :p .{ -1, -1 }; + } else { + // We use CLOEXEC for the same reason as in `pipe_flags`. + break :p try pipe2(.{ .NONBLOCK = true, .CLOEXEC = true }); } - if (canon_name) |n| { - const len = std.unicode.wtf16LeToWtf8(options.canonical_name_buffer, std.mem.sliceTo(n, 0)); - try resolved.putOne(t_io, .{ .canonical_name = .{ - .bytes = options.canonical_name_buffer[0..len], - } }); + }; + errdefer destroyPipe(prog_pipe); + + var arena_allocator = std.heap.ArenaAllocator.init(t.allocator); + defer arena_allocator.deinit(); + const arena = arena_allocator.allocator(); + + // The POSIX standard does not allow malloc() between fork() and execve(), + // and this allocator may be a libc allocator. + // I have personally observed the child process deadlocking when it tries + // to call malloc() due to a heap allocation between fork() and execve(), + // in musl v1.1.24. + // Additionally, we want to reduce the number of possible ways things + // can fail between fork() and execve(). + // Therefore, we do all the allocation for the execve() before the fork(). + // This means we must do the null-termination of argv and env vars here. + const argv_buf = try arena.allocSentinel(?[*:0]const u8, options.argv.len, null); + for (options.argv, 0..) |arg, i| argv_buf[i] = (try arena.dupeZ(u8, arg)).ptr; + + const prog_fileno = 3; + comptime assert(@max(posix.STDIN_FILENO, posix.STDOUT_FILENO, posix.STDERR_FILENO) + 1 == prog_fileno); + + const envp: [*:null]const ?[*:0]const u8 = m: { + const prog_fd: i32 = if (prog_pipe[1] == -1) -1 else prog_fileno; + if (options.environ_map) |environ_map| { + break :m (try environ_map.createBlockPosix(arena, .{ + .zig_progress_fd = prog_fd, + })).ptr; } - return; - } + break :m (try process.Environ.createBlockPosix(t.environ.process_environ, arena, .{ + .zig_progress_fd = prog_fd, + })).ptr; + }; - // On Linux, glibc provides getaddrinfo_a which is capable of supporting our semantics. - // However, musl's POSIX-compliant getaddrinfo is not, so we bypass it. + // This pipe communicates to the parent errors in the child between `fork` and `execvpe`. + // It is closed by the child (via CLOEXEC) without writing if `execvpe` succeeds. + const err_pipe: [2]posix.fd_t = try pipe2(.{ .CLOEXEC = true }); + errdefer destroyPipe(err_pipe); - if (builtin.target.isGnuLibC()) { - // TODO use getaddrinfo_a / gai_cancel - } + t.scanEnviron(); // for PATH + const PATH = t.environ.string.PATH orelse default_PATH; - if (native_os == .linux) { - if (options.family != .ip4) { - if (IpAddress.parseIp6(name, options.port)) |addr| { - try resolved.putAll(t_io, &.{ - .{ .address = addr }, - .{ .canonical_name = copyCanon(options.canonical_name_buffer, name) }, - }); - return; - } else |_| {} + const pid_result: posix.pid_t = fork: { + const rc = posix.system.fork(); + switch (posix.errno(rc)) { + .SUCCESS => break :fork @intCast(rc), + .AGAIN => return error.SystemResources, + .NOMEM => return error.SystemResources, + .NOSYS => return error.OperationUnsupported, + else => |err| return posix.unexpectedErrno(err), } + }; - if (options.family != .ip6) { - if (IpAddress.parseIp4(name, options.port)) |addr| { - try resolved.putAll(t_io, &.{ - .{ .address = addr }, - .{ .canonical_name = copyCanon(options.canonical_name_buffer, name) }, - }); - return; - } else |_| {} + if (pid_result == 0) { + defer comptime unreachable; // We are the child. + if (Thread.current) |current_thread| current_thread.cancel_protection = .blocked; + const ep1 = err_pipe[1]; + + setUpChildIo(options.stdin, stdin_pipe[0], posix.STDIN_FILENO, dev_null_fd) catch |err| forkBail(ep1, err); + setUpChildIo(options.stdout, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch |err| forkBail(ep1, err); + setUpChildIo(options.stderr, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch |err| forkBail(ep1, err); + + if (options.cwd_dir) |cwd| { + fchdir(cwd.handle) catch |err| forkBail(ep1, err); + } else if (options.cwd) |cwd| { + chdir(cwd) catch |err| forkBail(ep1, err); } - lookupHosts(t, host_name, resolved, options) catch |err| switch (err) { - error.UnknownHostName => {}, - else => |e| return e, - }; + // Must happen after fchdir above, the cwd file descriptor might be + // equal to prog_fileno and be clobbered by this dup2 call. + if (prog_pipe[1] != -1) dup2(prog_pipe[1], prog_fileno) catch |err| forkBail(ep1, err); - // RFC 6761 Section 6.3.3 - // Name resolution APIs and libraries SHOULD recognize - // localhost names as special and SHOULD always return the IP - // loopback address for address queries and negative responses - // for all other query types. + if (options.gid) |gid| { + switch (posix.errno(posix.system.setregid(gid, gid))) { + .SUCCESS => {}, + .AGAIN => forkBail(ep1, error.ResourceLimitReached), + .INVAL => forkBail(ep1, error.InvalidUserId), + .PERM => forkBail(ep1, error.PermissionDenied), + else => forkBail(ep1, error.Unexpected), + } + } - // Check for equal to "localhost(.)" or ends in ".localhost(.)" - const localhost = if (name[name.len - 1] == '.') "localhost." else "localhost"; - if (std.mem.endsWith(u8, name, localhost) and - (name.len == localhost.len or name[name.len - localhost.len] == '.')) - { - var results_buffer: [3]HostName.LookupResult = undefined; - var results_index: usize = 0; - if (options.family != .ip4) { - results_buffer[results_index] = .{ .address = .{ .ip6 = .loopback(options.port) } }; - results_index += 1; + if (options.uid) |uid| { + switch (posix.errno(posix.system.setreuid(uid, uid))) { + .SUCCESS => {}, + .AGAIN => forkBail(ep1, error.ResourceLimitReached), + .INVAL => forkBail(ep1, error.InvalidUserId), + .PERM => forkBail(ep1, error.PermissionDenied), + else => forkBail(ep1, error.Unexpected), } - if (options.family != .ip6) { - results_buffer[results_index] = .{ .address = .{ .ip4 = .loopback(options.port) } }; - results_index += 1; + } + + if (options.pgid) |pid| { + switch (posix.errno(posix.system.setpgid(0, pid))) { + .SUCCESS => {}, + .ACCES => forkBail(ep1, error.ProcessAlreadyExec), + .INVAL => forkBail(ep1, error.InvalidProcessGroupId), + .PERM => forkBail(ep1, error.PermissionDenied), + else => forkBail(ep1, error.Unexpected), + } + } + + if (options.start_suspended) { + switch (posix.errno(posix.system.kill(posix.system.getpid(), .STOP))) { + .SUCCESS => {}, + .PERM => forkBail(ep1, error.PermissionDenied), + else => forkBail(ep1, error.Unexpected), } - const canon_name = "localhost"; - const canon_name_dest = options.canonical_name_buffer[0..canon_name.len]; - canon_name_dest.* = canon_name.*; - results_buffer[results_index] = .{ .canonical_name = .{ .bytes = canon_name_dest } }; - results_index += 1; - try resolved.putAll(t_io, results_buffer[0..results_index]); - return; } - return lookupDnsSearch(t, host_name, resolved, options); + const err = posixExecv(options.expand_arg0, argv_buf.ptr[0].?, argv_buf.ptr, envp, PATH); + forkBail(ep1, err); + } + + const pid: posix.pid_t = @intCast(pid_result); // We are the parent. + errdefer comptime unreachable; // The child is forked; we must not error from now on + + posix.close(err_pipe[1]); // make sure only the child holds the write end open + + if (options.stdin == .pipe) posix.close(stdin_pipe[0]); + if (options.stdout == .pipe) posix.close(stdout_pipe[1]); + if (options.stderr == .pipe) posix.close(stderr_pipe[1]); + + if (prog_pipe[1] != -1) posix.close(prog_pipe[1]); + + options.progress_node.setIpcFd(prog_pipe[0]); + + return .{ + .pid = pid, + .err_fd = err_pipe[0], + .stdin = switch (options.stdin) { + .pipe => .{ .handle = stdin_pipe[1] }, + else => null, + }, + .stdout = switch (options.stdout) { + .pipe => .{ .handle = stdout_pipe[0] }, + else => null, + }, + .stderr = switch (options.stderr) { + .pipe => .{ .handle = stderr_pipe[0] }, + else => null, + }, + }; +} + +fn getDevNullFd(t: *Threaded) !posix.fd_t { + { + t.mutex.lock(); + defer t.mutex.unlock(); + if (t.null_file.fd != -1) return t.null_file.fd; + } + const mode: u32 = 0; + const syscall: Syscall = try .start(); + while (true) { + const rc = open_sym("/dev/null", .{ .ACCMODE = .RDWR }, mode); + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + const fresh_fd: posix.fd_t = @intCast(rc); + t.mutex.lock(); // Another thread might have won the race. + defer t.mutex.unlock(); + if (t.null_file.fd != -1) { + posix.close(fresh_fd); + return t.null_file.fd; + } else { + t.null_file.fd = fresh_fd; + return fresh_fd; + } + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + .ACCES => return syscall.fail(error.AccessDenied), + .MFILE => return syscall.fail(error.ProcessFdQuotaExceeded), + .NFILE => return syscall.fail(error.SystemFdQuotaExceeded), + .NODEV => return syscall.fail(error.NoDevice), + .NOENT => return syscall.fail(error.FileNotFound), + .NOMEM => return syscall.fail(error.SystemResources), + .PERM => return syscall.fail(error.PermissionDenied), + else => |err| return syscall.unexpectedErrno(err), + } } +} - if (native_os == .openbsd) { - // TODO use getaddrinfo_async / asr_abort +fn processSpawnPosix(userdata: ?*anyopaque, options: process.SpawnOptions) process.SpawnError!process.Child { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + const spawned = try spawnPosix(t, options); + defer posix.close(spawned.err_fd); + + // Wait for the child to report any errors in or before `execvpe`. + if (readIntFd(spawned.err_fd)) |child_err_int| { + const child_err: process.SpawnError = @errorCast(@errorFromInt(child_err_int)); + return child_err; + } else |read_err| switch (read_err) { + error.EndOfStream => { + // Write end closed by CLOEXEC at the time of the `execvpe` call, + // indicating success. + }, + else => { + // Problem reading the error from the error reporting pipe. We + // don't know if the child is alive or dead. Better to assume it is + // alive so the resource does not risk being leaked. + }, } - if (native_os == .freebsd) { - // TODO use dnsres_getaddrinfo + return .{ + .id = spawned.pid, + .thread_handle = {}, + .stdin = spawned.stdin, + .stdout = spawned.stdout, + .stderr = spawned.stderr, + .request_resource_usage_statistics = options.request_resource_usage_statistics, + }; +} + +fn childWait(userdata: ?*anyopaque, child: *process.Child) process.Child.WaitError!process.Child.Term { + if (native_os == .wasi) unreachable; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + switch (native_os) { + .windows => return childWaitWindows(child), + else => return childWaitPosix(child), } +} - if (native_os.isDarwin()) { - // TODO use CFHostStartInfoResolution / CFHostCancelInfoResolution +fn childKill(userdata: ?*anyopaque, child: *process.Child) void { + if (native_os == .wasi) unreachable; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + if (is_windows) { + childKillWindows(t, child, 1) catch childCleanupWindows(child); + } else { + childKillPosix(child) catch {}; + childCleanupPosix(child); } +} - if (builtin.link_libc) { - // This operating system lacks a way to resolve asynchronously. We are - // stuck with getaddrinfo. - var name_buffer: [HostName.max_len + 1]u8 = undefined; - @memcpy(name_buffer[0..host_name.bytes.len], host_name.bytes); - name_buffer[host_name.bytes.len] = 0; - const name_c = name_buffer[0..host_name.bytes.len :0]; +fn childKillWindows(t: *Threaded, child: *process.Child, exit_code: windows.UINT) !void { + _ = t; // TODO cancelation + const handle = child.id.?; + if (windows.kernel32.TerminateProcess(handle, exit_code) == 0) { + switch (windows.GetLastError()) { + .ACCESS_DENIED => { + // Usually when TerminateProcess triggers a ACCESS_DENIED error, it + // indicates that the process has already exited, but there may be + // some rare edge cases where our process handle no longer has the + // PROCESS_TERMINATE access right, so let's do another check to make + // sure the process is really no longer running: + windows.WaitForSingleObjectEx(handle, 0, false) catch return error.AccessDenied; + return error.AlreadyTerminated; + }, + else => |err| return windows.unexpectedError(err), + } + } + _ = windows.kernel32.WaitForSingleObjectEx(handle, windows.INFINITE, windows.FALSE); + childCleanupWindows(child); +} - var port_buffer: [8]u8 = undefined; - const port_c = std.fmt.bufPrintZ(&port_buffer, "{d}", .{options.port}) catch unreachable; +fn childWaitWindows(child: *process.Child) process.Child.WaitError!process.Child.Term { + const handle = child.id.?; - const hints: posix.addrinfo = .{ - .flags = .{ .NUMERICSERV = true }, - .family = posix.AF.UNSPEC, - .socktype = posix.SOCK.STREAM, - .protocol = posix.IPPROTO.TCP, - .canonname = null, - .addr = null, - .addrlen = 0, - .next = null, - }; - var res: ?*posix.addrinfo = null; - while (true) { - try t.checkCancel(); - switch (posix.system.getaddrinfo(name_c.ptr, port_c.ptr, &hints, &res)) { - @as(posix.system.EAI, @enumFromInt(0)) => break, - .ADDRFAMILY => return error.AddressFamilyUnsupported, - .AGAIN => return error.NameServerFailure, - .FAIL => return error.NameServerFailure, - .FAMILY => return error.AddressFamilyUnsupported, - .MEMORY => return error.SystemResources, - .NODATA => return error.UnknownHostName, - .NONAME => return error.UnknownHostName, - .SYSTEM => switch (posix.errno(-1)) { - .INTR => continue, - .CANCELED => return error.Canceled, - else => |e| return posix.unexpectedErrno(e), - }, - else => return error.Unexpected, + const syscall: Syscall = try .start(); + while (true) switch (windows.kernel32.WaitForSingleObjectEx(handle, windows.INFINITE, windows.FALSE)) { + windows.WAIT_OBJECT_0 => break syscall.finish(), + windows.WAIT_ABANDONED, windows.WAIT_TIMEOUT => { + try syscall.checkCancel(); + continue; + }, + windows.WAIT_FAILED => { + syscall.finish(); + switch (windows.GetLastError()) { + else => |err| return windows.unexpectedError(err), } + }, + else => return syscall.fail(error.Unexpected), + }; + + const term: process.Child.Term = x: { + var exit_code: windows.DWORD = undefined; + if (windows.kernel32.GetExitCodeProcess(handle, &exit_code) == 0) { + break :x .{ .unknown = 0 }; + } else { + break :x .{ .exited = @as(u8, @truncate(exit_code)) }; } - defer if (res) |some| posix.system.freeaddrinfo(some); + }; - var it = res; - var canon_name: ?[*:0]const u8 = null; - while (it) |info| : (it = info.next) { - const addr = info.addr orelse continue; - const storage: PosixAddress = .{ .any = addr.* }; - try resolved.putOne(t_io, .{ .address = addressFromPosix(&storage) }); + childCleanupWindows(child); + return term; +} - if (info.canonname) |n| { - if (canon_name == null) { - canon_name = n; - } - } - } - if (canon_name) |n| { - try resolved.putOne(t_io, .{ - .canonical_name = copyCanon(options.canonical_name_buffer, std.mem.sliceTo(n, 0)), - }); - } - return; - } +fn childCleanupWindows(child: *process.Child) void { + const handle = child.id orelse return; - return error.OptionUnsupported; + if (child.request_resource_usage_statistics) + child.resource_usage_statistics.rusage = windows.GetProcessMemoryInfo(handle) catch null; + + windows.CloseHandle(handle); + child.id = null; + + windows.CloseHandle(child.thread_handle); + child.thread_handle = undefined; + + if (child.stdin) |*stdin| { + windows.CloseHandle(stdin.handle); + child.stdin = null; + } + if (child.stdout) |*stdout| { + windows.CloseHandle(stdout.handle); + child.stdout = null; + } + if (child.stderr) |*stderr| { + windows.CloseHandle(stderr.handle); + child.stderr = null; + } } -pub const PosixAddress = extern union { - any: posix.sockaddr, - in: posix.sockaddr.in, - in6: posix.sockaddr.in6, -}; +fn childWaitPosix(child: *process.Child) process.Child.WaitError!process.Child.Term { + defer childCleanupPosix(child); -const UnixAddress = extern union { - any: posix.sockaddr, - un: posix.sockaddr.un, -}; + const pid = child.id.?; -const WsaAddress = extern union { - any: ws2_32.sockaddr, - in: ws2_32.sockaddr.in, - in6: ws2_32.sockaddr.in6, - un: ws2_32.sockaddr.un, -}; + var ru: posix.rusage = undefined; + const ru_ptr = if (child.request_resource_usage_statistics) &ru else null; -pub fn posixAddressFamily(a: *const IpAddress) posix.sa_family_t { - return switch (a.*) { - .ip4 => posix.AF.INET, - .ip6 => posix.AF.INET6, + if (have_wait4) { + var status: if (builtin.link_libc) c_int else u32 = undefined; + const syscall: Syscall = try .start(); + while (true) switch (posix.errno(posix.system.wait4(pid, &status, 0, ru_ptr))) { + .SUCCESS => { + syscall.finish(); + if (ru_ptr) |p| child.resource_usage_statistics.rusage = p.*; + return statusToTerm(@bitCast(status)); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + .CHILD => |err| return syscall.errnoBug(err), // Double-free. + else => |err| return syscall.unexpectedErrno(err), + }; + } + + if (have_waitid) { + const linux = std.os.linux; // Bypass libc which has the wrong signature. + var info: linux.siginfo_t = undefined; + const syscall: Syscall = try .start(); + while (true) switch (linux.errno(linux.waitid(.PID, pid, &info, linux.W.EXITED, ru_ptr))) { + .SUCCESS => { + syscall.finish(); + if (ru_ptr) |p| child.resource_usage_statistics.rusage = p.*; + const status: u32 = @bitCast(info.fields.common.second.sigchld.status); + const code: linux.CLD = @enumFromInt(info.code); + return switch (code) { + .EXITED => .{ .exited = @truncate(status) }, + .KILLED, .DUMPED => .{ .signal = @enumFromInt(status) }, + .TRAPPED, .STOPPED => .{ .stopped = status }, + _, .CONTINUED => .{ .unknown = status }, + }; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + .CHILD => |err| return syscall.errnoBug(err), // Double-free. + else => |err| return syscall.unexpectedErrno(err), + }; + } + + var status: if (builtin.link_libc) c_int else u32 = undefined; + const syscall: Syscall = try .start(); + while (true) switch (posix.errno(posix.system.waitpid(pid, &status, 0))) { + .SUCCESS => { + syscall.finish(); + return statusToTerm(@bitCast(status)); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + .CHILD => |err| return syscall.errnoBug(err), // Double-free. + else => |err| return syscall.unexpectedErrno(err), }; } -pub fn addressFromPosix(posix_address: *const PosixAddress) IpAddress { - return switch (posix_address.any.family) { - posix.AF.INET => .{ .ip4 = address4FromPosix(&posix_address.in) }, - posix.AF.INET6 => .{ .ip6 = address6FromPosix(&posix_address.in6) }, - else => .{ .ip4 = .loopback(0) }, - }; +fn statusToTerm(status: u32) process.Child.Term { + return if (posix.W.IFEXITED(status)) + .{ .exited = posix.W.EXITSTATUS(status) } + else if (posix.W.IFSIGNALED(status)) + .{ .signal = posix.W.TERMSIG(status) } + else if (posix.W.IFSTOPPED(status)) + .{ .stopped = posix.W.STOPSIG(status) } + else + .{ .unknown = status }; } -fn addressFromWsa(wsa_address: *const WsaAddress) IpAddress { - return switch (wsa_address.any.family) { - posix.AF.INET => .{ .ip4 = address4FromWsa(&wsa_address.in) }, - posix.AF.INET6 => .{ .ip6 = address6FromWsa(&wsa_address.in6) }, - else => .{ .ip4 = .loopback(0) }, +fn childKillPosix(child: *process.Child) !void { + // Entire function body is intentionally uncancelable. + + const pid = child.id.?; + + while (true) switch (posix.errno(posix.system.kill(pid, .TERM))) { + .SUCCESS => break, + .INTR => continue, + .PERM => return error.PermissionDenied, + .INVAL => |err| return errnoBug(err), + .SRCH => |err| return errnoBug(err), + else => |err| return posix.unexpectedErrno(err), }; -} -pub fn addressToPosix(a: *const IpAddress, storage: *PosixAddress) posix.socklen_t { - return switch (a.*) { - .ip4 => |ip4| { - storage.in = address4ToPosix(ip4); - return @sizeOf(posix.sockaddr.in); - }, - .ip6 => |*ip6| { - storage.in6 = address6ToPosix(ip6); - return @sizeOf(posix.sockaddr.in6); - }, + if (have_wait4) { + var status: if (builtin.link_libc) c_int else u32 = undefined; + while (true) switch (posix.errno(posix.system.wait4(pid, &status, 0, null))) { + .SUCCESS => return, + .INTR => continue, + .CHILD => |err| return errnoBug(err), // Double-free. + else => |err| return posix.unexpectedErrno(err), + }; + } + + if (have_waitid) { + const linux = std.os.linux; // Bypass libc which has the wrong signature. + var info: linux.siginfo_t = undefined; + while (true) switch (linux.errno(linux.waitid(.PID, pid, &info, linux.W.EXITED, null))) { + .SUCCESS => return, + .INTR => continue, + .CHILD => |err| return errnoBug(err), // Double-free. + else => |err| return posix.unexpectedErrno(err), + }; + } + + var status: if (builtin.link_libc) c_int else u32 = undefined; + while (true) switch (posix.errno(posix.system.waitpid(pid, &status, 0))) { + .SUCCESS => return, + .INTR => continue, + .CHILD => |err| return errnoBug(err), // Double-free. + else => |err| return posix.unexpectedErrno(err), }; } -fn addressToWsa(a: *const IpAddress, storage: *WsaAddress) i32 { - return switch (a.*) { - .ip4 => |ip4| { - storage.in = address4ToPosix(ip4); - return @sizeOf(posix.sockaddr.in); - }, - .ip6 => |*ip6| { - storage.in6 = address6ToPosix(ip6); - return @sizeOf(posix.sockaddr.in6); - }, - }; +fn childCleanupPosix(child: *process.Child) void { + if (child.stdin) |*stdin| { + posix.close(stdin.handle); + child.stdin = null; + } + if (child.stdout) |*stdout| { + posix.close(stdout.handle); + child.stdout = null; + } + if (child.stderr) |*stderr| { + posix.close(stderr.handle); + child.stderr = null; + } + child.id = null; } -fn addressUnixToPosix(a: *const net.UnixAddress, storage: *UnixAddress) posix.socklen_t { - @memcpy(storage.un.path[0..a.path.len], a.path); - storage.un.family = posix.AF.UNIX; - storage.un.path[a.path.len] = 0; - return @sizeOf(posix.sockaddr.un); +/// Errors that can occur between fork() and execv() +const ForkBailError = process.SpawnError || process.ReplaceError; + +/// Child of fork calls this to report an error to the fork parent. Then the +/// child exits. +fn forkBail(fd: posix.fd_t, err: ForkBailError) noreturn { + writeIntFd(fd, @as(ErrInt, @intFromError(err))) catch {}; + // If we're linking libc, some naughty applications may have registered atexit handlers + // which we really do not want to run in the fork child. I caught LLVM doing this and + // it caused a deadlock instead of doing an exit syscall. In the words of Avril Lavigne, + // "Why'd you have to go and make things so complicated?" + if (builtin.link_libc) { + // The `_exit` function does nothing but make the exit syscall, unlike `exit`. + std.c._exit(1); + } else if (native_os == .linux and !builtin.single_threaded) { + std.os.linux.exit_group(1); + } else { + posix.system.exit(1); + } } -fn addressUnixToWsa(a: *const net.UnixAddress, storage: *WsaAddress) i32 { - @memcpy(storage.un.path[0..a.path.len], a.path); - storage.un.family = posix.AF.UNIX; - storage.un.path[a.path.len] = 0; - return @sizeOf(posix.sockaddr.un); +fn writeIntFd(fd: posix.fd_t, value: ErrInt) !void { + var buffer: [8]u8 = undefined; + std.mem.writeInt(u64, &buffer, value, .little); + // Skip the cancel mechanism. + var i: usize = 0; + while (true) { + const rc = posix.system.write(fd, buffer[i..].ptr, buffer.len - i); + switch (posix.errno(rc)) { + .SUCCESS => { + const n: usize = @intCast(rc); + i += n; + if (buffer.len - i == 0) return; + }, + .INTR => continue, + else => return error.SystemResources, + } + } } -fn address4FromPosix(in: *const posix.sockaddr.in) net.Ip4Address { - return .{ - .port = std.mem.bigToNative(u16, in.port), - .bytes = @bitCast(in.addr), - }; +fn readIntFd(fd: posix.fd_t) !ErrInt { + var buffer: [8]u8 = undefined; + var i: usize = 0; + while (true) { + const rc = posix.system.read(fd, buffer[i..].ptr, buffer.len - i); + switch (posix.errno(rc)) { + .SUCCESS => { + const n: usize = @intCast(rc); + if (n == 0) break; + i += n; + continue; + }, + .INTR => continue, + else => |err| return posix.unexpectedErrno(err), + } + } + if (buffer.len - i != 0) return error.EndOfStream; + return @intCast(std.mem.readInt(u64, &buffer, .little)); } -fn address6FromPosix(in6: *const posix.sockaddr.in6) net.Ip6Address { - return .{ - .port = std.mem.bigToNative(u16, in6.port), - .bytes = in6.addr, - .flow = in6.flowinfo, - .interface = .{ .index = in6.scope_id }, +const ErrInt = std.meta.Int(.unsigned, @sizeOf(anyerror) * 8); + +fn destroyPipe(pipe: [2]posix.fd_t) void { + if (pipe[0] != -1) posix.close(pipe[0]); + if (pipe[0] != pipe[1]) posix.close(pipe[1]); +} + +fn setUpChildIo(stdio: process.SpawnOptions.StdIo, pipe_fd: i32, std_fileno: i32, dev_null_fd: i32) !void { + switch (stdio) { + .pipe => try dup2(pipe_fd, std_fileno), + .close => posix.close(std_fileno), + .inherit => {}, + .ignore => try dup2(dev_null_fd, std_fileno), + .file => @panic("TODO implement setUpChildIo when file is used"), + } +} + +fn processSpawnWindows(userdata: ?*anyopaque, options: process.SpawnOptions) process.SpawnError!process.Child { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + + var saAttr: windows.SECURITY_ATTRIBUTES = .{ + .nLength = @sizeOf(windows.SECURITY_ATTRIBUTES), + .bInheritHandle = windows.TRUE, + .lpSecurityDescriptor = null, + }; + + const any_ignore = + options.stdin == .ignore or + options.stdout == .ignore or + options.stderr == .ignore; + + const nul_handle = if (any_ignore) try getNulHandle(t) else undefined; + + var g_hChildStd_IN_Rd: ?windows.HANDLE = null; + var g_hChildStd_IN_Wr: ?windows.HANDLE = null; + switch (options.stdin) { + .pipe => { + try windowsMakePipeIn(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr); + }, + .ignore => { + g_hChildStd_IN_Rd = nul_handle; + }, + .inherit => { + g_hChildStd_IN_Rd = windows.GetStdHandle(windows.STD_INPUT_HANDLE) catch null; + }, + .close => { + g_hChildStd_IN_Rd = null; + }, + .file => @panic("TODO implement passing file stdio in processSpawnWindows"), + } + errdefer if (options.stdin == .pipe) { + windowsDestroyPipe(g_hChildStd_IN_Rd, g_hChildStd_IN_Wr); + }; + + var g_hChildStd_OUT_Rd: ?windows.HANDLE = null; + var g_hChildStd_OUT_Wr: ?windows.HANDLE = null; + switch (options.stdout) { + .pipe => { + try windowsMakeAsyncPipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr); + }, + .ignore => { + g_hChildStd_OUT_Wr = nul_handle; + }, + .inherit => { + g_hChildStd_OUT_Wr = windows.GetStdHandle(windows.STD_OUTPUT_HANDLE) catch null; + }, + .close => { + g_hChildStd_OUT_Wr = null; + }, + .file => @panic("TODO implement passing file stdio in processSpawnWindows"), + } + errdefer if (options.stdout == .pipe) { + windowsDestroyPipe(g_hChildStd_OUT_Rd, g_hChildStd_OUT_Wr); }; -} -fn address4FromWsa(in: *const ws2_32.sockaddr.in) net.Ip4Address { - return .{ - .port = std.mem.bigToNative(u16, in.port), - .bytes = @bitCast(in.addr), + var g_hChildStd_ERR_Rd: ?windows.HANDLE = null; + var g_hChildStd_ERR_Wr: ?windows.HANDLE = null; + switch (options.stderr) { + .pipe => { + try windowsMakeAsyncPipe(&g_hChildStd_ERR_Rd, &g_hChildStd_ERR_Wr, &saAttr); + }, + .ignore => { + g_hChildStd_ERR_Wr = nul_handle; + }, + .inherit => { + g_hChildStd_ERR_Wr = windows.GetStdHandle(windows.STD_ERROR_HANDLE) catch null; + }, + .close => { + g_hChildStd_ERR_Wr = null; + }, + .file => @panic("TODO implement passing file stdio in processSpawnWindows"), + } + errdefer if (options.stderr == .pipe) { + windowsDestroyPipe(g_hChildStd_ERR_Rd, g_hChildStd_ERR_Wr); }; -} -fn address6FromWsa(in6: *const ws2_32.sockaddr.in6) net.Ip6Address { - return .{ - .port = std.mem.bigToNative(u16, in6.port), - .bytes = in6.addr, - .flow = in6.flowinfo, - .interface = .{ .index = in6.scope_id }, + var siStartInfo: windows.STARTUPINFOW = .{ + .cb = @sizeOf(windows.STARTUPINFOW), + .hStdError = g_hChildStd_ERR_Wr, + .hStdOutput = g_hChildStd_OUT_Wr, + .hStdInput = g_hChildStd_IN_Rd, + .dwFlags = windows.STARTF_USESTDHANDLES, + + .lpReserved = null, + .lpDesktop = null, + .lpTitle = null, + .dwX = 0, + .dwY = 0, + .dwXSize = 0, + .dwYSize = 0, + .dwXCountChars = 0, + .dwYCountChars = 0, + .dwFillAttribute = 0, + .wShowWindow = 0, + .cbReserved2 = 0, + .lpReserved2 = null, + }; + var piProcInfo: windows.PROCESS_INFORMATION = undefined; + + var arena_allocator = std.heap.ArenaAllocator.init(t.allocator); + defer arena_allocator.deinit(); + const arena = arena_allocator.allocator(); + + const cwd_w = if (options.cwd) |cwd| try std.unicode.wtf8ToWtf16LeAllocZ(arena, cwd) else null; + const cwd_w_ptr = if (cwd_w) |cwd| cwd.ptr else null; + + const maybe_envp_buf = if (options.environ_map) |environ_map| try environ_map.createBlockWindows(arena) else null; + const envp_ptr = if (maybe_envp_buf) |envp_buf| envp_buf.ptr else null; + + const app_name_wtf8 = options.argv[0]; + const app_name_is_absolute = Dir.path.isAbsolute(app_name_wtf8); + + // The cwd provided by options is in effect when choosing the executable + // path to match POSIX semantics. + var cwd_path_w_needs_free = false; + const cwd_path_w = x: { + // If the app name is absolute, then we need to use its dirname as the cwd + if (app_name_is_absolute) { + cwd_path_w_needs_free = true; + const dir = Dir.path.dirname(app_name_wtf8).?; + break :x try std.unicode.wtf8ToWtf16LeAllocZ(arena, dir); + } else if (options.cwd) |cwd| { + cwd_path_w_needs_free = true; + break :x try std.unicode.wtf8ToWtf16LeAllocZ(arena, cwd); + } else { + break :x &[_:0]u16{}; // empty for cwd + } }; -} -fn address4ToPosix(a: net.Ip4Address) posix.sockaddr.in { - return .{ - .port = std.mem.nativeToBig(u16, a.port), - .addr = @bitCast(a.bytes), + // If the app name has more than just a filename, then we need to separate + // that into the basename and dirname and use the dirname as an addition to + // the cwd path. This is because NtQueryDirectoryFile cannot accept + // FileName params with path separators. + const app_basename_wtf8 = Dir.path.basename(app_name_wtf8); + // If the app name is absolute, then the cwd will already have the app's dirname in it, + // so only populate app_dirname if app name is a relative path with > 0 path separators. + const maybe_app_dirname_wtf8 = if (!app_name_is_absolute) Dir.path.dirname(app_name_wtf8) else null; + const app_dirname_w: ?[:0]u16 = x: { + if (maybe_app_dirname_wtf8) |app_dirname_wtf8| { + break :x try std.unicode.wtf8ToWtf16LeAllocZ(arena, app_dirname_wtf8); + } + break :x null; }; -} + const app_name_w = try std.unicode.wtf8ToWtf16LeAllocZ(arena, app_basename_wtf8); -fn address6ToPosix(a: *const net.Ip6Address) posix.sockaddr.in6 { - return .{ - .port = std.mem.nativeToBig(u16, a.port), - .flowinfo = a.flow, - .addr = a.bytes, - .scope_id = a.interface.index, + const flags: windows.CreateProcessFlags = .{ + .create_suspended = options.start_suspended, + .create_unicode_environment = true, + .create_no_window = options.create_no_window, }; -} -pub fn errnoBug(err: posix.E) Io.UnexpectedError { - if (is_debug) std.debug.panic("programmer bug caused syscall error: {t}", .{err}); - return error.Unexpected; -} + run: { + // We have to scan each time because the PEB environment pointer is not stable. + const env_strings: WindowsEnvironStrings = .scan(); + const PATH = env_strings.PATH orelse &[_:0]u16{}; + const PATHEXT = env_strings.PATHEXT orelse &[_:0]u16{}; -fn wsaErrorBug(err: ws2_32.WinsockError) Io.UnexpectedError { - if (is_debug) std.debug.panic("programmer bug caused syscall error: {t}", .{err}); - return error.Unexpected; -} + // In case the command ends up being a .bat/.cmd script, we need to escape things using the cmd.exe rules + // and invoke cmd.exe ourselves in order to mitigate arbitrary command execution from maliciously + // constructed arguments. + // + // We'll need to wait until we're actually trying to run the command to know for sure + // if the resolved command has the `.bat` or `.cmd` extension, so we defer actually + // serializing the command line until we determine how it should be serialized. + var cmd_line_cache = WindowsCommandLineCache.init(arena, options.argv); -pub fn posixSocketMode(mode: net.Socket.Mode) u32 { - return switch (mode) { - .stream => posix.SOCK.STREAM, - .dgram => posix.SOCK.DGRAM, - .seqpacket => posix.SOCK.SEQPACKET, - .raw => posix.SOCK.RAW, - .rdm => posix.SOCK.RDM, + var app_buf: std.ArrayList(u16) = .empty; + try app_buf.appendSlice(arena, app_name_w); + + var dir_buf: std.ArrayList(u16) = .empty; + + if (cwd_path_w.len > 0) { + try dir_buf.appendSlice(arena, cwd_path_w); + } + if (app_dirname_w) |app_dir| { + if (dir_buf.items.len > 0) try dir_buf.append(arena, Dir.path.sep); + try dir_buf.appendSlice(arena, app_dir); + } + + windowsCreateProcessPathExt( + arena, + &dir_buf, + &app_buf, + PATHEXT, + &cmd_line_cache, + envp_ptr, + cwd_w_ptr, + flags, + &siStartInfo, + &piProcInfo, + ) catch |no_path_err| { + const original_err = switch (no_path_err) { + // argv[0] contains unsupported characters that will never resolve to a valid exe. + error.InvalidArg0 => return error.FileNotFound, + error.FileNotFound, error.InvalidExe, error.AccessDenied => |e| e, + error.UnrecoverableInvalidExe => return error.InvalidExe, + else => |e| return e, + }; + + // If the app name had path separators, that disallows PATH searching, + // and there's no need to search the PATH if the app name is absolute. + // We still search the path if the cwd is absolute because of the + // "cwd provided by options is in effect when choosing the executable path + // to match posix semantics" behavior--we don't want to skip searching + // the PATH just because we were trying to set the cwd of the child process. + if (app_dirname_w != null or app_name_is_absolute) { + return original_err; + } + + var it = std.mem.tokenizeScalar(u16, PATH, ';'); + while (it.next()) |search_path| { + dir_buf.clearRetainingCapacity(); + try dir_buf.appendSlice(arena, search_path); + + if (windowsCreateProcessPathExt( + arena, + &dir_buf, + &app_buf, + PATHEXT, + &cmd_line_cache, + envp_ptr, + cwd_w_ptr, + flags, + &siStartInfo, + &piProcInfo, + )) { + break :run; + } else |err| switch (err) { + // argv[0] contains unsupported characters that will never resolve to a valid exe. + error.InvalidArg0 => return error.FileNotFound, + error.FileNotFound, error.AccessDenied, error.InvalidExe => continue, + error.UnrecoverableInvalidExe => return error.InvalidExe, + else => |e| return e, + } + } else { + return original_err; + } + }; + } + + if (options.stdin == .pipe) windows.CloseHandle(g_hChildStd_IN_Rd.?); + if (options.stderr == .pipe) windows.CloseHandle(g_hChildStd_ERR_Wr.?); + if (options.stdout == .pipe) windows.CloseHandle(g_hChildStd_OUT_Wr.?); + + return .{ + .id = piProcInfo.hProcess, + .thread_handle = piProcInfo.hThread, + .stdin = if (g_hChildStd_IN_Wr) |h| .{ .handle = h } else null, + .stdout = if (g_hChildStd_OUT_Rd) |h| .{ .handle = h } else null, + .stderr = if (g_hChildStd_ERR_Rd) |h| .{ .handle = h } else null, + .request_resource_usage_statistics = options.request_resource_usage_statistics, }; } -pub fn posixProtocol(protocol: ?net.Protocol) u32 { - return @intFromEnum(protocol orelse return 0); -} +fn getCngHandle(t: *Threaded) Io.RandomSecureError!windows.HANDLE { + { + t.mutex.lock(); + defer t.mutex.unlock(); + if (t.random_file.handle) |handle| return handle; + } -fn recoverableOsBugDetected() void { - if (is_debug) unreachable; -} + const device_path = [_]u16{ '\\', 'D', 'e', 'v', 'i', 'c', 'e', '\\', 'C', 'N', 'G' }; -fn clockToPosix(clock: Io.Clock) posix.clockid_t { - return switch (clock) { - .real => posix.CLOCK.REALTIME, - .awake => switch (native_os) { - .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => posix.CLOCK.UPTIME_RAW, - else => posix.CLOCK.MONOTONIC, + var nt_name: windows.UNICODE_STRING = .{ + .Length = device_path.len * 2, + .MaximumLength = 0, + .Buffer = @constCast(&device_path), + }; + var fresh_handle: windows.HANDLE = undefined; + var io_status_block: windows.IO_STATUS_BLOCK = undefined; + var syscall: Syscall = try .start(); + while (true) switch (windows.ntdll.NtOpenFile( + &fresh_handle, + .{ + .STANDARD = .{ .SYNCHRONIZE = true }, + .SPECIFIC = .{ .FILE = .{ .READ_DATA = true } }, }, - .boot => switch (native_os) { - .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => posix.CLOCK.MONOTONIC_RAW, - // On freebsd derivatives, use MONOTONIC_FAST as currently there's - // no precision tradeoff. - .freebsd, .dragonfly => posix.CLOCK.MONOTONIC_FAST, - // On linux, use BOOTTIME instead of MONOTONIC as it ticks while - // suspended. - .linux => posix.CLOCK.BOOTTIME, - // On other posix systems, MONOTONIC is generally the fastest and - // ticks while suspended. - else => posix.CLOCK.MONOTONIC, + &.{ + .Length = @sizeOf(windows.OBJECT_ATTRIBUTES), + .RootDirectory = null, + .ObjectName = &nt_name, + .Attributes = .{}, + .SecurityDescriptor = null, + .SecurityQualityOfService = null, }, - .cpu_process => posix.CLOCK.PROCESS_CPUTIME_ID, - .cpu_thread => posix.CLOCK.THREAD_CPUTIME_ID, + &io_status_block, + .VALID_FLAGS, + .{ .IO = .SYNCHRONOUS_NONALERT }, + )) { + .SUCCESS => { + syscall.finish(); + t.mutex.lock(); // Another thread might have won the race. + defer t.mutex.unlock(); + if (t.random_file.handle) |prev_handle| { + _ = windows.ntdll.NtClose(fresh_handle); + return prev_handle; + } else { + t.random_file.handle = fresh_handle; + return fresh_handle; + } + }, + .CANCELLED => { + try syscall.checkCancel(); + continue; + }, + .OBJECT_NAME_NOT_FOUND => return syscall.fail(error.EntropyUnavailable), // Observed on wine 10.0 + else => return syscall.fail(error.EntropyUnavailable), }; } -fn clockToWasi(clock: Io.Clock) std.os.wasi.clockid_t { - return switch (clock) { - .real => .REALTIME, - .awake => .MONOTONIC, - .boot => .MONOTONIC, - .cpu_process => .PROCESS_CPUTIME_ID, - .cpu_thread => .THREAD_CPUTIME_ID, - }; -} +fn getNulHandle(t: *Threaded) !windows.HANDLE { + { + t.mutex.lock(); + defer t.mutex.unlock(); + if (t.null_file.handle) |handle| return handle; + } -fn statFromLinux(stx: *const std.os.linux.Statx) Io.File.Stat { - const atime = stx.atime; - const mtime = stx.mtime; - const ctime = stx.ctime; - return .{ - .inode = stx.ino, - .size = stx.size, - .mode = stx.mode, - .kind = switch (stx.mode & std.os.linux.S.IFMT) { - std.os.linux.S.IFDIR => .directory, - std.os.linux.S.IFCHR => .character_device, - std.os.linux.S.IFBLK => .block_device, - std.os.linux.S.IFREG => .file, - std.os.linux.S.IFIFO => .named_pipe, - std.os.linux.S.IFLNK => .sym_link, - std.os.linux.S.IFSOCK => .unix_domain_socket, - else => .unknown, + const device_path = [_]u16{ '\\', 'D', 'e', 'v', 'i', 'c', 'e', '\\', 'N', 'u', 'l', 'l' }; + var nt_name: windows.UNICODE_STRING = .{ + .Length = device_path.len * 2, + .MaximumLength = 0, + .Buffer = @constCast(&device_path), + }; + const attr: windows.OBJECT_ATTRIBUTES = .{ + .Length = @sizeOf(windows.OBJECT_ATTRIBUTES), + .RootDirectory = null, + .Attributes = .{ + .INHERIT = true, }, - .atime = .{ .nanoseconds = @intCast(@as(i128, atime.sec) * std.time.ns_per_s + atime.nsec) }, - .mtime = .{ .nanoseconds = @intCast(@as(i128, mtime.sec) * std.time.ns_per_s + mtime.nsec) }, - .ctime = .{ .nanoseconds = @intCast(@as(i128, ctime.sec) * std.time.ns_per_s + ctime.nsec) }, + .ObjectName = &nt_name, + .SecurityDescriptor = null, + .SecurityQualityOfService = null, }; -} - -fn statFromPosix(st: *const posix.Stat) Io.File.Stat { - const atime = st.atime(); - const mtime = st.mtime(); - const ctime = st.ctime(); - return .{ - .inode = st.ino, - .size = @bitCast(st.size), - .mode = st.mode, - .kind = k: { - const m = st.mode & posix.S.IFMT; - switch (m) { - posix.S.IFBLK => break :k .block_device, - posix.S.IFCHR => break :k .character_device, - posix.S.IFDIR => break :k .directory, - posix.S.IFIFO => break :k .named_pipe, - posix.S.IFLNK => break :k .sym_link, - posix.S.IFREG => break :k .file, - posix.S.IFSOCK => break :k .unix_domain_socket, - else => {}, + var io_status_block: windows.IO_STATUS_BLOCK = undefined; + var fresh_handle: windows.HANDLE = undefined; + var syscall: Syscall = try .start(); + while (true) switch (windows.ntdll.NtCreateFile( + &fresh_handle, + .{ + .STANDARD = .{ .SYNCHRONIZE = true }, + .GENERIC = .{ .WRITE = true, .READ = true }, + }, + &attr, + &io_status_block, + null, + .{ .NORMAL = true }, + .VALID_FLAGS, + .OPEN, + .{ + .DIRECTORY_FILE = false, + .NON_DIRECTORY_FILE = true, + .IO = .SYNCHRONOUS_NONALERT, + .OPEN_REPARSE_POINT = false, + }, + null, + 0, + )) { + .SUCCESS => { + syscall.finish(); + t.mutex.lock(); // Another thread might have won the race. + defer t.mutex.unlock(); + if (t.null_file.handle) |prev_handle| { + windows.CloseHandle(fresh_handle); + return prev_handle; + } else { + t.null_file.handle = fresh_handle; + return fresh_handle; } - if (native_os == .illumos) switch (m) { - posix.S.IFDOOR => break :k .door, - posix.S.IFPORT => break :k .event_port, - else => {}, - }; - - break :k .unknown; }, - .atime = timestampFromPosix(&atime), - .mtime = timestampFromPosix(&mtime), - .ctime = timestampFromPosix(&ctime), - }; -} - -fn statFromWasi(st: *const std.os.wasi.filestat_t) Io.File.Stat { - return .{ - .inode = st.ino, - .size = @bitCast(st.size), - .mode = 0, - .kind = switch (st.filetype) { - .BLOCK_DEVICE => .block_device, - .CHARACTER_DEVICE => .character_device, - .DIRECTORY => .directory, - .SYMBOLIC_LINK => .sym_link, - .REGULAR_FILE => .file, - .SOCKET_STREAM, .SOCKET_DGRAM => .unix_domain_socket, - else => .unknown, + .DELETE_PENDING => { + // This error means that there *was* a file in this location on + // the file system, but it was deleted. However, the OS is not + // finished with the deletion operation, and so this CreateFile + // call has failed. There is not really a sane way to handle + // this other than retrying the creation after the OS finishes + // the deletion. + syscall.finish(); + try parking_sleep.sleep(.{ .duration = .{ + .raw = .fromMilliseconds(1), + .clock = .awake, + } }); + syscall = try .start(); + continue; }, - .atime = .fromNanoseconds(st.atim), - .mtime = .fromNanoseconds(st.mtim), - .ctime = .fromNanoseconds(st.ctim), + .CANCELLED => { + try syscall.checkCancel(); + continue; + }, + .INVALID_PARAMETER => |status| return syscall.ntstatusBug(status), + .OBJECT_PATH_SYNTAX_BAD => |status| return syscall.ntstatusBug(status), + .INVALID_HANDLE => |status| return syscall.ntstatusBug(status), + .OBJECT_NAME_INVALID => return syscall.fail(error.BadPathName), + .OBJECT_NAME_NOT_FOUND => return syscall.fail(error.FileNotFound), + .OBJECT_PATH_NOT_FOUND => return syscall.fail(error.FileNotFound), + .NO_MEDIA_IN_DEVICE => return syscall.fail(error.NoDevice), + .SHARING_VIOLATION => return syscall.fail(error.AccessDenied), + .ACCESS_DENIED => return syscall.fail(error.AccessDenied), + .PIPE_NOT_AVAILABLE => return syscall.fail(error.NoDevice), + .FILE_IS_A_DIRECTORY => return syscall.fail(error.IsDir), + .NOT_A_DIRECTORY => return syscall.fail(error.NotDir), + .USER_MAPPED_FILE => return syscall.fail(error.AccessDenied), + else => |status| return syscall.unexpectedNtstatus(status), }; } -fn timestampFromPosix(timespec: *const posix.timespec) Io.Timestamp { - return .{ .nanoseconds = @intCast(@as(i128, timespec.sec) * std.time.ns_per_s + timespec.nsec) }; -} +/// Expects `app_buf` to contain exactly the app name, and `dir_buf` to contain exactly the dir path. +/// After return, `app_buf` will always contain exactly the app name and `dir_buf` will always contain exactly the dir path. +/// Note: `app_buf` should not contain any leading path separators. +/// Note: If the dir is the cwd, dir_buf should be empty (len = 0). +fn windowsCreateProcessPathExt( + arena: Allocator, + dir_buf: *std.ArrayList(u16), + app_buf: *std.ArrayList(u16), + pathext: [:0]const u16, + cmd_line_cache: *WindowsCommandLineCache, + envp_ptr: ?[*:0]const u16, + cwd_ptr: ?[*:0]u16, + flags: windows.CreateProcessFlags, + lpStartupInfo: *windows.STARTUPINFOW, + lpProcessInformation: *windows.PROCESS_INFORMATION, +) !void { + const app_name_len = app_buf.items.len; + const dir_path_len = dir_buf.items.len; -fn timestampToPosix(nanoseconds: i96) posix.timespec { - return .{ - .sec = @intCast(@divFloor(nanoseconds, std.time.ns_per_s)), - .nsec = @intCast(@mod(nanoseconds, std.time.ns_per_s)), + if (app_name_len == 0) return error.FileNotFound; + + defer app_buf.shrinkRetainingCapacity(app_name_len); + defer dir_buf.shrinkRetainingCapacity(dir_path_len); + + // The name of the game here is to avoid CreateProcessW calls at all costs, + // and only ever try calling it when we have a real candidate for execution. + // Secondarily, we want to minimize the number of syscalls used when checking + // for each PATHEXT-appended version of the app name. + // + // An overview of the technique used: + // - Open the search directory for iteration (either cwd or a path from PATH) + // - Use NtQueryDirectoryFile with a wildcard filename of `*` to + // check if anything that could possibly match either the unappended version + // of the app name or any of the versions with a PATHEXT value appended exists. + // - If the wildcard NtQueryDirectoryFile call found nothing, we can exit early + // without needing to use PATHEXT at all. + // + // This allows us to use a sequence + // for any directory that doesn't contain any possible matches, instead of having + // to use a separate look up for each individual filename combination (unappended + + // each PATHEXT appended). For directories where the wildcard *does* match something, + // we iterate the matches and take note of any that are either the unappended version, + // or a version with a supported PATHEXT appended. We then try calling CreateProcessW + // with the found versions in the appropriate order. + var dir = dir: { + // needs to be null-terminated + try dir_buf.append(arena, 0); + defer dir_buf.shrinkRetainingCapacity(dir_path_len); + const dir_path_z = dir_buf.items[0 .. dir_buf.items.len - 1 :0]; + const prefixed_path = try windows.wToPrefixedFileW(null, dir_path_z); + break :dir dirOpenDirWindows(.cwd(), prefixed_path.span(), .{ + .iterate = true, + }) catch |err| switch (err) { + // These errors must not be ignored because they should not be able + // to affect which file is chosen to execute. Also `error.Canceled` + // must never be swallowed. + error.Canceled, + error.SystemResources, + error.Unexpected, + error.ProcessFdQuotaExceeded, + error.SystemFdQuotaExceeded, + => |e| return e, + + error.AccessDenied, + error.PermissionDenied, + error.SymLinkLoop, + error.FileNotFound, + error.NotDir, + error.NoDevice, + error.NetworkNotFound, + error.NameTooLong, + error.BadPathName, + => return error.FileNotFound, + }; }; -} + defer windows.CloseHandle(dir.handle); + + // Add wildcard and null-terminator + try app_buf.append(arena, '*'); + try app_buf.append(arena, 0); + const app_name_wildcard = app_buf.items[0 .. app_buf.items.len - 1 :0]; + + // This 2048 is arbitrary, we just want it to be large enough to get multiple FILE_DIRECTORY_INFORMATION entries + // returned per NtQueryDirectoryFile call. + var file_information_buf: [2048]u8 align(@alignOf(windows.FILE_DIRECTORY_INFORMATION)) = undefined; + const file_info_maximum_single_entry_size = @sizeOf(windows.FILE_DIRECTORY_INFORMATION) + (windows.NAME_MAX * 2); + if (file_information_buf.len < file_info_maximum_single_entry_size) { + @compileError("file_information_buf must be large enough to contain at least one maximum size FILE_DIRECTORY_INFORMATION entry"); + } + var io_status: windows.IO_STATUS_BLOCK = undefined; + + const num_supported_pathext = @typeInfo(process.WindowsExtension).@"enum".fields.len; + var pathext_seen = [_]bool{false} ** num_supported_pathext; + var any_pathext_seen = false; + var unappended_exists = false; + + // Fully iterate the wildcard matches via NtQueryDirectoryFile and take note of all versions + // of the app_name we should try to spawn. + // Note: This is necessary because the order of the files returned is filesystem-dependent: + // On NTFS, `blah.exe*` will always return `blah.exe` first if it exists. + // On FAT32, it's possible for something like `blah.exe.obj` to be returned first. + while (true) { + const app_name_len_bytes = std.math.cast(u16, app_name_wildcard.len * 2) orelse return error.NameTooLong; + var app_name_unicode_string = windows.UNICODE_STRING{ + .Length = app_name_len_bytes, + .MaximumLength = app_name_len_bytes, + .Buffer = @constCast(app_name_wildcard.ptr), + }; + const rc = windows.ntdll.NtQueryDirectoryFile( + dir.handle, + null, + null, + null, + &io_status, + &file_information_buf, + file_information_buf.len, + .Directory, + windows.FALSE, // single result + &app_name_unicode_string, + windows.FALSE, // restart iteration + ); -fn pathToPosix(file_path: []const u8, buffer: *[posix.PATH_MAX]u8) Io.Dir.PathNameError![:0]u8 { - if (std.mem.containsAtLeastScalar2(u8, file_path, 0, 1)) return error.BadPathName; - // >= rather than > to make room for the null byte - if (file_path.len >= buffer.len) return error.NameTooLong; - @memcpy(buffer[0..file_path.len], file_path); - buffer[file_path.len] = 0; - return buffer[0..file_path.len :0]; -} + // If we get nothing with the wildcard, then we can just bail out + // as we know appending PATHEXT will not yield anything. + switch (rc) { + .SUCCESS => {}, + .NO_SUCH_FILE => return error.FileNotFound, + .NO_MORE_FILES => break, + .ACCESS_DENIED => return error.AccessDenied, + else => return windows.unexpectedStatus(rc), + } -fn lookupDnsSearch( - t: *Threaded, - host_name: HostName, - resolved: *Io.Queue(HostName.LookupResult), - options: HostName.LookupOptions, -) HostName.LookupError!void { - const t_io = io(t); - const rc = HostName.ResolvConf.init(t_io) catch return error.ResolvConfParseFailed; + // According to the docs, this can only happen if there is not enough room in the + // buffer to write at least one complete FILE_DIRECTORY_INFORMATION entry. + // Therefore, this condition should not be possible to hit with the buffer size we use. + std.debug.assert(io_status.Information != 0); + + var it = windows.FileInformationIterator(windows.FILE_DIRECTORY_INFORMATION){ .buf = &file_information_buf }; + while (it.next()) |info| { + // Skip directories + if (info.FileAttributes.DIRECTORY) continue; + const filename = @as([*]u16, @ptrCast(&info.FileName))[0 .. info.FileNameLength / 2]; + // Because all results start with the app_name since we're using the wildcard `app_name*`, + // if the length is equal to app_name then this is an exact match + if (filename.len == app_name_len) { + // Note: We can't break early here because it's possible that the unappended version + // fails to spawn, in which case we still want to try the PATHEXT appended versions. + unappended_exists = true; + } else if (windowsCreateProcessSupportsExtension(filename[app_name_len..])) |pathext_ext| { + pathext_seen[@intFromEnum(pathext_ext)] = true; + any_pathext_seen = true; + } + } + } - // Count dots, suppress search when >=ndots or name ends in - // a dot, which is an explicit request for global scope. - const dots = std.mem.countScalar(u8, host_name.bytes, '.'); - const search_len = if (dots >= rc.ndots or std.mem.endsWith(u8, host_name.bytes, ".")) 0 else rc.search_len; - const search = rc.search_buffer[0..search_len]; + const unappended_err = unappended: { + if (unappended_exists) { + if (dir_path_len != 0) switch (dir_buf.items[dir_buf.items.len - 1]) { + '/', '\\' => {}, + else => try dir_buf.append(arena, Dir.path.sep), + }; + try dir_buf.appendSlice(arena, app_buf.items[0..app_name_len]); + try dir_buf.append(arena, 0); + const full_app_name = dir_buf.items[0 .. dir_buf.items.len - 1 :0]; + + const is_bat_or_cmd = bat_or_cmd: { + const app_name = app_buf.items[0..app_name_len]; + const ext_start = std.mem.lastIndexOfScalar(u16, app_name, '.') orelse break :bat_or_cmd false; + const ext = app_name[ext_start..]; + const ext_enum = windowsCreateProcessSupportsExtension(ext) orelse break :bat_or_cmd false; + switch (ext_enum) { + .cmd, .bat => break :bat_or_cmd true, + else => break :bat_or_cmd false, + } + }; + const cmd_line_w = if (is_bat_or_cmd) + try cmd_line_cache.scriptCommandLine(full_app_name) + else + try cmd_line_cache.commandLine(); + const app_name_w = if (is_bat_or_cmd) + try cmd_line_cache.cmdExePath() + else + full_app_name; + + if (windowsCreateProcess( + app_name_w.ptr, + cmd_line_w.ptr, + envp_ptr, + cwd_ptr, + flags, + lpStartupInfo, + lpProcessInformation, + )) |_| { + return; + } else |err| switch (err) { + error.FileNotFound, + error.AccessDenied, + => break :unappended err, + error.InvalidExe => { + // On InvalidExe, if the extension of the app name is .exe then + // it's treated as an unrecoverable error. Otherwise, it'll be + // skipped as normal. + const app_name = app_buf.items[0..app_name_len]; + const ext_start = std.mem.lastIndexOfScalar(u16, app_name, '.') orelse break :unappended err; + const ext = app_name[ext_start..]; + if (windows.eqlIgnoreCaseWtf16(ext, std.unicode.utf8ToUtf16LeStringLiteral(".EXE"))) { + return error.UnrecoverableInvalidExe; + } + break :unappended err; + }, + else => return err, + } + } + break :unappended error.FileNotFound; + }; + + if (!any_pathext_seen) return unappended_err; - var canon_name = host_name.bytes; + // Now try any PATHEXT appended versions that we've seen + var ext_it = std.mem.tokenizeScalar(u16, pathext, ';'); + while (ext_it.next()) |ext| { + const ext_enum = windowsCreateProcessSupportsExtension(ext) orelse continue; + if (!pathext_seen[@intFromEnum(ext_enum)]) continue; - // Strip final dot for canon, fail if multiple trailing dots. - if (std.mem.endsWith(u8, canon_name, ".")) canon_name.len -= 1; - if (std.mem.endsWith(u8, canon_name, ".")) return error.UnknownHostName; + dir_buf.shrinkRetainingCapacity(dir_path_len); + if (dir_path_len != 0) switch (dir_buf.items[dir_buf.items.len - 1]) { + '/', '\\' => {}, + else => try dir_buf.append(arena, Dir.path.sep), + }; + try dir_buf.appendSlice(arena, app_buf.items[0..app_name_len]); + try dir_buf.appendSlice(arena, ext); + try dir_buf.append(arena, 0); + const full_app_name = dir_buf.items[0 .. dir_buf.items.len - 1 :0]; + + const is_bat_or_cmd = switch (ext_enum) { + .cmd, .bat => true, + else => false, + }; + const cmd_line_w = if (is_bat_or_cmd) + try cmd_line_cache.scriptCommandLine(full_app_name) + else + try cmd_line_cache.commandLine(); + const app_name_w = if (is_bat_or_cmd) + try cmd_line_cache.cmdExePath() + else + full_app_name; - // Name with search domain appended is set up in `canon_name`. This - // both provides the desired default canonical name (if the requested - // name is not a CNAME record) and serves as a buffer for passing the - // full requested name to `lookupDns`. - @memcpy(options.canonical_name_buffer[0..canon_name.len], canon_name); - options.canonical_name_buffer[canon_name.len] = '.'; - var it = std.mem.tokenizeAny(u8, search, " \t"); - while (it.next()) |token| { - @memcpy(options.canonical_name_buffer[canon_name.len + 1 ..][0..token.len], token); - const lookup_canon_name = options.canonical_name_buffer[0 .. canon_name.len + 1 + token.len]; - if (lookupDns(t, lookup_canon_name, &rc, resolved, options)) |result| { - return result; + if (windowsCreateProcess(app_name_w.ptr, cmd_line_w.ptr, envp_ptr, cwd_ptr, flags, lpStartupInfo, lpProcessInformation)) |_| { + return; } else |err| switch (err) { - error.UnknownHostName => continue, - else => |e| return e, + error.FileNotFound => continue, + error.AccessDenied => continue, + error.InvalidExe => { + // On InvalidExe, if the extension of the app name is .exe then + // it's treated as an unrecoverable error. Otherwise, it'll be + // skipped as normal. + if (windows.eqlIgnoreCaseWtf16(ext, std.unicode.utf8ToUtf16LeStringLiteral(".EXE"))) { + return error.UnrecoverableInvalidExe; + } + continue; + }, + else => return err, } } - const lookup_canon_name = options.canonical_name_buffer[0..canon_name.len]; - return lookupDns(t, lookup_canon_name, &rc, resolved, options); + return unappended_err; } -fn lookupDns( - t: *Threaded, - lookup_canon_name: []const u8, - rc: *const HostName.ResolvConf, - resolved: *Io.Queue(HostName.LookupResult), - options: HostName.LookupOptions, -) HostName.LookupError!void { - const t_io = io(t); - const family_records: [2]struct { af: IpAddress.Family, rr: HostName.DnsRecord } = .{ - .{ .af = .ip6, .rr = .A }, - .{ .af = .ip4, .rr = .AAAA }, +fn windowsCreateProcess( + app_name: [*:0]u16, + cmd_line: [*:0]u16, + env_ptr: ?[*:0]const u16, + cwd_ptr: ?[*:0]u16, + flags: windows.CreateProcessFlags, + lpStartupInfo: *windows.STARTUPINFOW, + lpProcessInformation: *windows.PROCESS_INFORMATION, +) !void { + const syscall: Syscall = try .start(); + while (true) { + if (windows.kernel32.CreateProcessW( + app_name, + cmd_line, + null, + null, + windows.TRUE, + flags, + env_ptr, + cwd_ptr, + lpStartupInfo, + lpProcessInformation, + ) != 0) { + return syscall.finish(); + } else switch (windows.GetLastError()) { + .INVALID_PARAMETER => unreachable, + .OPERATION_ABORTED => { + try syscall.checkCancel(); + continue; + }, + .FILE_NOT_FOUND => return syscall.fail(error.FileNotFound), + .PATH_NOT_FOUND => return syscall.fail(error.FileNotFound), + .DIRECTORY => return syscall.fail(error.FileNotFound), + .ACCESS_DENIED => return syscall.fail(error.AccessDenied), + .INVALID_NAME => return syscall.fail(error.InvalidName), + .FILENAME_EXCED_RANGE => return syscall.fail(error.NameTooLong), + .SHARING_VIOLATION => return syscall.fail(error.FileBusy), + .COMMITMENT_LIMIT => return syscall.fail(error.SystemResources), + + // These are all the system errors that are mapped to ENOEXEC by + // the undocumented _dosmaperr (old CRT) or __acrt_errno_map_os_error + // (newer CRT) functions. Their code can be found in crt/src/dosmap.c (old SDK) + // or urt/misc/errno.cpp (newer SDK) in the Windows SDK. + .BAD_FORMAT, + .INVALID_STARTING_CODESEG, // MIN_EXEC_ERROR in errno.cpp + .INVALID_STACKSEG, + .INVALID_MODULETYPE, + .INVALID_EXE_SIGNATURE, + .EXE_MARKED_INVALID, + .BAD_EXE_FORMAT, + .ITERATED_DATA_EXCEEDS_64k, + .INVALID_MINALLOCSIZE, + .DYNLINK_FROM_INVALID_RING, + .IOPL_NOT_ENABLED, + .INVALID_SEGDPL, + .AUTODATASEG_EXCEEDS_64k, + .RING2SEG_MUST_BE_MOVABLE, + .RELOC_CHAIN_XEEDS_SEGLIM, + .INFLOOP_IN_RELOC_CHAIN, // MAX_EXEC_ERROR in errno.cpp + // This one is not mapped to ENOEXEC but it is possible, for example + // when calling CreateProcessW on a plain text file with a .exe extension + .EXE_MACHINE_TYPE_MISMATCH, + => return syscall.fail(error.InvalidExe), + + else => |err| { + syscall.finish(); + return windows.unexpectedError(err); + }, + } + } +} + +/// Case-insensitive WTF-16 lookup +fn windowsCreateProcessSupportsExtension(ext: []const u16) ?process.WindowsExtension { + comptime { + // Ensures keeping this function in sync with the enum. + const fields = @typeInfo(process.WindowsExtension).@"enum".fields; + assert(fields.len == 4); + assert(@intFromEnum(process.WindowsExtension.bat) == 0); + assert(@intFromEnum(process.WindowsExtension.cmd) == 1); + assert(@intFromEnum(process.WindowsExtension.com) == 2); + assert(@intFromEnum(process.WindowsExtension.exe) == 3); + } + + if (ext.len != 4) return null; + const State = enum { + start, + dot, + b, + ba, + c, + cm, + co, + e, + ex, }; - var query_buffers: [2][280]u8 = undefined; - var answer_buffer: [2 * 512]u8 = undefined; - var queries_buffer: [2][]const u8 = undefined; - var answers_buffer: [2][]const u8 = undefined; - var nq: usize = 0; - var answer_buffer_i: usize = 0; + var state: State = .start; + for (ext) |c| switch (state) { + .start => switch (c) { + '.' => state = .dot, + else => return null, + }, + .dot => switch (c) { + 'b', 'B' => state = .b, + 'c', 'C' => state = .c, + 'e', 'E' => state = .e, + else => return null, + }, + .b => switch (c) { + 'a', 'A' => state = .ba, + else => return null, + }, + .c => switch (c) { + 'm', 'M' => state = .cm, + 'o', 'O' => state = .co, + else => return null, + }, + .e => switch (c) { + 'x', 'X' => state = .ex, + else => return null, + }, + .ba => switch (c) { + 't', 'T' => return .bat, + else => return null, + }, + .cm => switch (c) { + 'd', 'D' => return .cmd, + else => return null, + }, + .co => switch (c) { + 'm', 'M' => return .com, + else => return null, + }, + .ex => switch (c) { + 'e', 'E' => return .exe, + else => return null, + }, + }; + return null; +} - for (family_records) |fr| { - if (options.family != fr.af) { - const entropy = std.crypto.random.array(u8, 2); - const len = writeResolutionQuery(&query_buffers[nq], 0, lookup_canon_name, 1, fr.rr, entropy); - queries_buffer[nq] = query_buffers[nq][0..len]; - nq += 1; +test windowsCreateProcessSupportsExtension { + try std.testing.expectEqual(process.WindowsExtension.exe, windowsCreateProcessSupportsExtension(&[_]u16{ '.', 'e', 'X', 'e' }).?); + try std.testing.expect(windowsCreateProcessSupportsExtension(&[_]u16{ '.', 'e', 'X', 'e', 'c' }) == null); +} + +/// Serializes argv into a WTF-16 encoded command-line string for use with CreateProcessW. +/// +/// Serialization is done on-demand and the result is cached in order to allow for: +/// - Only serializing the particular type of command line needed (`.bat`/`.cmd` +/// command line serialization is different from `.exe`/etc) +/// - Reusing the serialized command lines if necessary (i.e. if the execution +/// of a command fails and the PATH is going to be continued to be searched +/// for more candidates) +const WindowsCommandLineCache = struct { + cmd_line: ?[:0]u16 = null, + script_cmd_line: ?[:0]u16 = null, + cmd_exe_path: ?[:0]u16 = null, + argv: []const []const u8, + allocator: Allocator, + + fn init(allocator: Allocator, argv: []const []const u8) WindowsCommandLineCache { + return .{ + .allocator = allocator, + .argv = argv, + }; + } + + fn deinit(self: *WindowsCommandLineCache) void { + if (self.cmd_line) |cmd_line| self.allocator.free(cmd_line); + if (self.script_cmd_line) |script_cmd_line| self.allocator.free(script_cmd_line); + if (self.cmd_exe_path) |cmd_exe_path| self.allocator.free(cmd_exe_path); + } + + fn commandLine(self: *WindowsCommandLineCache) ![:0]u16 { + if (self.cmd_line == null) { + self.cmd_line = try argvToCommandLineWindows(self.allocator, self.argv); } + return self.cmd_line.?; + } + + /// Not cached, since the path to the batch script will change during PATH searching. + /// `script_path` should be as qualified as possible, e.g. if the PATH is being searched, + /// then script_path should include both the search path and the script filename + /// (this allows avoiding cmd.exe having to search the PATH again). + fn scriptCommandLine(self: *WindowsCommandLineCache, script_path: []const u16) ![:0]u16 { + if (self.script_cmd_line) |v| self.allocator.free(v); + self.script_cmd_line = try argvToScriptCommandLineWindows( + self.allocator, + script_path, + self.argv[1..], + ); + return self.script_cmd_line.?; } - var ip4_mapped_buffer: [HostName.ResolvConf.max_nameservers]IpAddress = undefined; - const ip4_mapped = ip4_mapped_buffer[0..rc.nameservers_len]; - var any_ip6 = false; - for (rc.nameservers(), ip4_mapped) |*ns, *m| { - m.* = .{ .ip6 = .fromAny(ns.*) }; - any_ip6 = any_ip6 or ns.* == .ip6; + fn cmdExePath(self: *WindowsCommandLineCache) ![:0]u16 { + if (self.cmd_exe_path == null) { + self.cmd_exe_path = try windowsCmdExePath(self.allocator); + } + return self.cmd_exe_path.?; } - var socket = s: { - if (any_ip6) ip6: { - const ip6_addr: IpAddress = .{ .ip6 = .unspecified(0) }; - const socket = ip6_addr.bind(t_io, .{ .ip6_only = true, .mode = .dgram }) catch |err| switch (err) { - error.AddressFamilyUnsupported => break :ip6, - else => |e| return e, - }; - break :s socket; +}; + +/// Returns the absolute path of `cmd.exe` within the Windows system directory. +/// The caller owns the returned slice. +fn windowsCmdExePath(allocator: Allocator) error{ OutOfMemory, Unexpected }![:0]u16 { + var buf = try std.ArrayList(u16).initCapacity(allocator, 128); + errdefer buf.deinit(allocator); + while (true) { + const unused_slice = buf.unusedCapacitySlice(); + // TODO: Get the system directory from PEB.ReadOnlyStaticServerData + const len = windows.kernel32.GetSystemDirectoryW(@ptrCast(unused_slice), @intCast(unused_slice.len)); + if (len == 0) { + switch (windows.GetLastError()) { + else => |err| return windows.unexpectedError(err), + } } - any_ip6 = false; - const ip4_addr: IpAddress = .{ .ip4 = .unspecified(0) }; - const socket = try ip4_addr.bind(t_io, .{ .mode = .dgram }); - break :s socket; - }; - defer socket.close(t_io); + if (len > unused_slice.len) { + try buf.ensureUnusedCapacity(allocator, len); + } else { + buf.items.len = len; + break; + } + } + switch (buf.items[buf.items.len - 1]) { + '/', '\\' => {}, + else => try buf.append(allocator, Dir.path.sep), + } + try buf.appendSlice(allocator, std.unicode.utf8ToUtf16LeStringLiteral("cmd.exe")); + return try buf.toOwnedSliceSentinel(allocator, 0); +} - const mapped_nameservers = if (any_ip6) ip4_mapped else rc.nameservers(); - const queries = queries_buffer[0..nq]; - const answers = answers_buffer[0..queries.len]; - var answers_remaining = answers.len; - for (answers) |*answer| answer.len = 0; +const ArgvToScriptCommandLineError = error{ + OutOfMemory, + InvalidWtf8, + /// NUL (U+0000), LF (U+000A), CR (U+000D) are not allowed + /// within arguments when executing a `.bat`/`.cmd` script. + /// - NUL/LF signifiies end of arguments, so anything afterwards + /// would be lost after execution. + /// - CR is stripped by `cmd.exe`, so any CR codepoints + /// would be lost after execution. + InvalidBatchScriptArg, +}; - // boot clock is chosen because time the computer is suspended should count - // against time spent waiting for external messages to arrive. - const clock: Io.Clock = .boot; - var now_ts = try clock.now(t_io); - const final_ts = now_ts.addDuration(.fromSeconds(rc.timeout_seconds)); - const attempt_duration: Io.Duration = .{ - .nanoseconds = (std.time.ns_per_s / rc.attempts) * @as(i96, rc.timeout_seconds), - }; +/// Serializes `argv` to a Windows command-line string that uses `cmd.exe /c` and `cmd.exe`-specific +/// escaping rules. The caller owns the returned slice. +/// +/// Escapes `argv` using the suggested mitigation against arbitrary command execution from: +/// https://flatt.tech/research/posts/batbadbut-you-cant-securely-execute-commands-on-windows/ +/// +/// The return of this function will look like +/// `cmd.exe /d /e:ON /v:OFF /c ""` +/// and should be used as the `lpCommandLine` of `CreateProcessW`, while the +/// return of `windowsCmdExePath` should be used as `lpApplicationName`. +/// +/// Should only be used when spawning `.bat`/`.cmd` scripts, see `argvToCommandLineWindows` otherwise. +/// The `.bat`/`.cmd` file must be known to both have the `.bat`/`.cmd` extension and exist on the filesystem. +fn argvToScriptCommandLineWindows( + allocator: Allocator, + /// Path to the `.bat`/`.cmd` script. If this path is relative, it is assumed to be relative to the CWD. + /// The script must have been verified to exist at this path before calling this function. + script_path: []const u16, + /// Arguments, not including the script name itself. Expected to be encoded as WTF-8. + script_args: []const []const u8, +) ArgvToScriptCommandLineError![:0]u16 { + var buf = try std.array_list.Managed(u8).initCapacity(allocator, 64); + defer buf.deinit(); + + // `/d` disables execution of AutoRun commands. + // `/e:ON` and `/v:OFF` are needed for BatBadBut mitigation: + // > If delayed expansion is enabled via the registry value DelayedExpansion, + // > it must be disabled by explicitly calling cmd.exe with the /V:OFF option. + // > Escaping for % requires the command extension to be enabled. + // > If it’s disabled via the registry value EnableExtensions, it must be enabled with the /E:ON option. + // https://flatt.tech/research/posts/batbadbut-you-cant-securely-execute-commands-on-windows/ + buf.appendSliceAssumeCapacity("cmd.exe /d /e:ON /v:OFF /c \""); + + // Always quote the path to the script arg + buf.appendAssumeCapacity('"'); + // We always want the path to the batch script to include a path separator in order to + // avoid cmd.exe searching the PATH for the script. This is not part of the arbitrary + // command execution mitigation, we just know exactly what script we want to execute + // at this point, and potentially making cmd.exe re-find it is unnecessary. + // + // If the script path does not have a path separator, then we know its relative to CWD and + // we can just put `.\` in the front. + if (std.mem.findAny(u16, script_path, &[_]u16{ + std.mem.nativeToLittle(u16, '\\'), std.mem.nativeToLittle(u16, '/'), + }) == null) { + try buf.appendSlice(".\\"); + } + // Note that we don't do any escaping/mitigations for this argument, since the relevant + // characters (", %, etc) are illegal in file paths and this function should only be called + // with script paths that have been verified to exist. + try std.unicode.wtf16LeToWtf8ArrayList(&buf, script_path); + buf.appendAssumeCapacity('"'); + + for (script_args) |arg| { + // Literal carriage returns get stripped when run through cmd.exe + // and NUL/newlines act as 'end of command.' Because of this, it's basically + // always a mistake to include these characters in argv, so it's + // an error condition in order to ensure that the return of this + // function can always roundtrip through cmd.exe. + if (std.mem.findAny(u8, arg, "\x00\r\n") != null) { + return error.InvalidBatchScriptArg; + } - send: while (now_ts.nanoseconds < final_ts.nanoseconds) : (now_ts = try clock.now(t_io)) { - const max_messages = queries_buffer.len * HostName.ResolvConf.max_nameservers; - { - var message_buffer: [max_messages]Io.net.OutgoingMessage = undefined; - var message_i: usize = 0; - for (queries, answers) |query, *answer| { - if (answer.len != 0) continue; - for (mapped_nameservers) |*ns| { - message_buffer[message_i] = .{ - .address = ns, - .data_ptr = query.ptr, - .data_len = query.len, - }; - message_i += 1; + // Separate args with a space. + try buf.append(' '); + + // Need to quote if the argument is empty (otherwise the arg would just be lost) + // or if the last character is a `\`, since then something like "%~2" in a .bat + // script would cause the closing " to be escaped which we don't want. + var needs_quotes = arg.len == 0 or arg[arg.len - 1] == '\\'; + if (!needs_quotes) { + for (arg) |c| { + switch (c) { + // Known good characters that don't need to be quoted + 'A'...'Z', 'a'...'z', '0'...'9', '#', '$', '*', '+', '-', '.', '/', ':', '?', '@', '\\', '_' => {}, + // When in doubt, quote + else => { + needs_quotes = true; + break; + }, } } - _ = netSendPosix(t, socket.handle, message_buffer[0..message_i], .{}); } + if (needs_quotes) { + try buf.append('"'); + } + var backslashes: usize = 0; + for (arg) |c| { + switch (c) { + '\\' => { + backslashes += 1; + }, + '"' => { + try buf.appendNTimes('\\', backslashes); + try buf.append('"'); + backslashes = 0; + }, + // Replace `%` with `%%cd:~,%`. + // + // cmd.exe allows extracting a substring from an environment + // variable with the syntax: `%foo:~,%`. + // Therefore, `%cd:~,%` will always expand to an empty string + // since both the start and end index are blank, and it is assumed + // that `%cd%` is always available since it is a built-in variable + // that corresponds to the current directory. + // + // This means that replacing `%foo%` with `%%cd:~,%foo%%cd:~,%` + // will stop `%foo%` from being expanded and *after* expansion + // we'll still be left with `%foo%` (the literal string). + '%' => { + // the trailing `%` is appended outside the switch + try buf.appendSlice("%%cd:~,"); + backslashes = 0; + }, + else => { + backslashes = 0; + }, + } + try buf.append(c); + } + if (needs_quotes) { + try buf.appendNTimes('\\', backslashes); + try buf.append('"'); + } + } - const timeout: Io.Timeout = .{ .deadline = .{ - .raw = now_ts.addDuration(attempt_duration), - .clock = clock, - } }; + try buf.append('"'); - while (true) { - var message_buffer: [max_messages]Io.net.IncomingMessage = @splat(.init); - const buf = answer_buffer[answer_buffer_i..]; - const recv_err, const recv_n = socket.receiveManyTimeout(t_io, &message_buffer, buf, .{}, timeout); - for (message_buffer[0..recv_n]) |*received_message| { - const reply = received_message.data; - // Ignore non-identifiable packets. - if (reply.len < 4) continue; + return try std.unicode.wtf8ToWtf16LeAllocZ(allocator, buf.items); +} - // Ignore replies from addresses we didn't send to. - const ns = for (mapped_nameservers) |*ns| { - if (received_message.from.eql(ns)) break ns; - } else { - continue; - }; +const ArgvToCommandLineError = error{ OutOfMemory, InvalidWtf8, InvalidArg0 }; - // Find which query this answer goes with, if any. - const query, const answer = for (queries, answers) |query, *answer| { - if (reply[0] == query[0] and reply[1] == query[1]) break .{ query, answer }; - } else { - continue; - }; - if (answer.len != 0) continue; +/// Serializes `argv` to a Windows command-line string suitable for passing to a child process and +/// parsing by the `CommandLineToArgvW` algorithm. The caller owns the returned slice. +/// +/// To avoid arbitrary command execution, this function should not be used when spawning `.bat`/`.cmd` scripts. +/// https://flatt.tech/research/posts/batbadbut-you-cant-securely-execute-commands-on-windows/ +/// +/// When executing `.bat`/`.cmd` scripts, use `argvToScriptCommandLineWindows` instead. +fn argvToCommandLineWindows( + allocator: Allocator, + argv: []const []const u8, +) ArgvToCommandLineError![:0]u16 { + var buf = std.array_list.Managed(u8).init(allocator); + defer buf.deinit(); + + if (argv.len != 0) { + const arg0 = argv[0]; + + // The first argument must be quoted if it contains spaces or ASCII control characters + // (excluding DEL). It also follows special quoting rules where backslashes have no special + // interpretation, which makes it impossible to pass certain first arguments containing + // double quotes to a child process without characters from the first argument leaking into + // subsequent ones (which could have security implications). + // + // Empty arguments technically don't need quotes, but we quote them anyway for maximum + // compatibility with different implementations of the 'CommandLineToArgvW' algorithm. + // + // Double quotes are illegal in paths on Windows, so for the sake of simplicity we reject + // all first arguments containing double quotes, even ones that we could theoretically + // serialize in unquoted form. + var needs_quotes = arg0.len == 0; + for (arg0) |c| { + if (c <= ' ') { + needs_quotes = true; + } else if (c == '"') { + return error.InvalidArg0; + } + } + if (needs_quotes) { + try buf.append('"'); + try buf.appendSlice(arg0); + try buf.append('"'); + } else { + try buf.appendSlice(arg0); + } - // Only accept positive or negative responses; retry immediately on - // server failure, and ignore all other codes such as refusal. - switch (reply[3] & 15) { - 0, 3 => { - answer.* = reply; - answer_buffer_i += reply.len; - answers_remaining -= 1; - if (answer_buffer.len - answer_buffer_i == 0) break :send; - if (answers_remaining == 0) break :send; + for (argv[1..]) |arg| { + try buf.append(' '); + + // Subsequent arguments must be quoted if they contain spaces, tabs or double quotes, + // or if they are empty. For simplicity and for maximum compatibility with different + // implementations of the 'CommandLineToArgvW' algorithm, we also quote all ASCII + // control characters (again, excluding DEL). + needs_quotes = for (arg) |c| { + if (c <= ' ' or c == '"') { + break true; + } + } else arg.len == 0; + if (!needs_quotes) { + try buf.appendSlice(arg); + continue; + } + + try buf.append('"'); + var backslash_count: usize = 0; + for (arg) |byte| { + switch (byte) { + '\\' => { + backslash_count += 1; }, - 2 => { - var retry_message: Io.net.OutgoingMessage = .{ - .address = ns, - .data_ptr = query.ptr, - .data_len = query.len, - }; - _ = netSendPosix(t, socket.handle, (&retry_message)[0..1], .{}); - continue; + '"' => { + try buf.appendNTimes('\\', backslash_count * 2 + 1); + try buf.append('"'); + backslash_count = 0; + }, + else => { + try buf.appendNTimes('\\', backslash_count); + try buf.append(byte); + backslash_count = 0; }, - else => continue, } } - if (recv_err) |err| switch (err) { - error.Canceled => return error.Canceled, - error.Timeout => continue :send, - else => continue, - }; + try buf.appendNTimes('\\', backslash_count * 2); + try buf.append('"'); } - } else { - return error.NameServerFailure; - } - - var addresses_len: usize = 0; - var canonical_name: ?HostName = null; - - for (answers) |answer| { - var it = HostName.DnsResponse.init(answer) catch { - // Here we could potentially add diagnostics to the results queue. - continue; - }; - while (it.next() catch { - // Here we could potentially add diagnostics to the results queue. - continue; - }) |record| switch (record.rr) { - .A => { - const data = record.packet[record.data_off..][0..record.data_len]; - if (data.len != 4) return error.InvalidDnsARecord; - try resolved.putOne(t_io, .{ .address = .{ .ip4 = .{ - .bytes = data[0..4].*, - .port = options.port, - } } }); - addresses_len += 1; - }, - .AAAA => { - const data = record.packet[record.data_off..][0..record.data_len]; - if (data.len != 16) return error.InvalidDnsAAAARecord; - try resolved.putOne(t_io, .{ .address = .{ .ip6 = .{ - .bytes = data[0..16].*, - .port = options.port, - } } }); - addresses_len += 1; - }, - .CNAME => { - _, canonical_name = HostName.expand(record.packet, record.data_off, options.canonical_name_buffer) catch - return error.InvalidDnsCnameRecord; - }, - _ => continue, - }; } - try resolved.putOne(t_io, .{ .canonical_name = canonical_name orelse .{ .bytes = lookup_canon_name } }); - if (addresses_len == 0) return error.NameServerFailure; + return try std.unicode.wtf8ToWtf16LeAllocZ(allocator, buf.items); +} + +test argvToCommandLineWindows { + const t = testArgvToCommandLineWindows; + + try t(&.{ + \\C:\Program Files\zig\zig.exe + , + \\run + , + \\.\src\main.zig + , + \\-target + , + \\x86_64-windows-gnu + , + \\-O + , + \\ReleaseSafe + , + \\-- + , + \\--emoji=🗿 + , + \\--eval=new Regex("Dwayne \"The Rock\" Johnson") + , + }, + \\"C:\Program Files\zig\zig.exe" run .\src\main.zig -target x86_64-windows-gnu -O ReleaseSafe -- --emoji=🗿 "--eval=new Regex(\"Dwayne \\\"The Rock\\\" Johnson\")" + ); + + try t(&.{}, ""); + try t(&.{""}, "\"\""); + try t(&.{" "}, "\" \""); + try t(&.{"\t"}, "\"\t\""); + try t(&.{"\x07"}, "\"\x07\""); + try t(&.{"🦎"}, "🦎"); + + try t( + &.{ "zig", "aa aa", "bb\tbb", "cc\ncc", "dd\r\ndd", "ee\x7Fee" }, + "zig \"aa aa\" \"bb\tbb\" \"cc\ncc\" \"dd\r\ndd\" ee\x7Fee", + ); + + try t( + &.{ "\\\\foo bar\\foo bar\\", "\\\\zig zag\\zig zag\\" }, + "\"\\\\foo bar\\foo bar\\\" \"\\\\zig zag\\zig zag\\\\\"", + ); + + try std.testing.expectError( + error.InvalidArg0, + argvToCommandLineWindows(std.testing.allocator, &.{"\"quotes\"quotes\""}), + ); + try std.testing.expectError( + error.InvalidArg0, + argvToCommandLineWindows(std.testing.allocator, &.{"quotes\"quotes"}), + ); + try std.testing.expectError( + error.InvalidArg0, + argvToCommandLineWindows(std.testing.allocator, &.{"q u o t e s \" q u o t e s"}), + ); } -fn lookupHosts( - t: *Threaded, - host_name: HostName, - resolved: *Io.Queue(HostName.LookupResult), - options: HostName.LookupOptions, -) !void { - const t_io = io(t); - const file = Io.File.openAbsolute(t_io, "/etc/hosts", .{}) catch |err| switch (err) { - error.FileNotFound, - error.NotDir, - error.AccessDenied, - => return error.UnknownHostName, +fn testArgvToCommandLineWindows(argv: []const []const u8, expected_cmd_line: []const u8) !void { + const cmd_line_w = try argvToCommandLineWindows(std.testing.allocator, argv); + defer std.testing.allocator.free(cmd_line_w); - error.Canceled => |e| return e, + const cmd_line = try std.unicode.wtf16LeToWtf8Alloc(std.testing.allocator, cmd_line_w); + defer std.testing.allocator.free(cmd_line); - else => { - // Here we could add more detailed diagnostics to the results queue. - return error.DetectingNetworkConfigurationFailed; - }, + try std.testing.expectEqualStrings(expected_cmd_line, cmd_line); +} + +fn posixExecv( + arg0_expand: process.ArgExpansion, + file: [*:0]const u8, + child_argv: [*:null]?[*:0]const u8, + envp: [*:null]const ?[*:0]const u8, + PATH: []const u8, +) process.ReplaceError { + const file_slice = std.mem.sliceTo(file, 0); + if (std.mem.findScalar(u8, file_slice, '/') != null) return posixExecvPath(file, child_argv, envp); + + // Use of PATH_MAX here is valid as the path_buf will be passed + // directly to the operating system in posixExecvPath. + var path_buf: [posix.PATH_MAX]u8 = undefined; + var it = std.mem.tokenizeScalar(u8, PATH, ':'); + var seen_eacces = false; + var err: process.ReplaceError = error.FileNotFound; + + // In case of expanding arg0 we must put it back if we return with an error. + const prev_arg0 = child_argv[0]; + defer switch (arg0_expand) { + .expand => child_argv[0] = prev_arg0, + .no_expand => {}, }; - defer file.close(t_io); - var line_buf: [512]u8 = undefined; - var file_reader = file.reader(t_io, &line_buf); - return lookupHostsReader(t, host_name, resolved, options, &file_reader.interface) catch |err| switch (err) { - error.ReadFailed => switch (file_reader.err.?) { - error.Canceled => |e| return e, - else => { - // Here we could add more detailed diagnostics to the results queue. - return error.DetectingNetworkConfigurationFailed; + while (it.next()) |search_path| { + const path_len = search_path.len + file_slice.len + 1; + if (path_buf.len < path_len + 1) return error.NameTooLong; + @memcpy(path_buf[0..search_path.len], search_path); + path_buf[search_path.len] = '/'; + @memcpy(path_buf[search_path.len + 1 ..][0..file_slice.len], file_slice); + path_buf[path_len] = 0; + const full_path = path_buf[0..path_len :0].ptr; + switch (arg0_expand) { + .expand => child_argv[0] = full_path, + .no_expand => {}, + } + err = posixExecvPath(full_path, child_argv, envp); + switch (err) { + error.AccessDenied => seen_eacces = true, + error.FileNotFound, error.NotDir => {}, + else => |e| return e, + } + } + if (seen_eacces) return error.AccessDenied; + return err; +} + +/// This function ignores PATH environment variable. +pub fn posixExecvPath( + path: [*:0]const u8, + child_argv: [*:null]const ?[*:0]const u8, + envp: [*:null]const ?[*:0]const u8, +) process.ReplaceError { + try Thread.checkCancel(); + switch (posix.errno(posix.system.execve(path, child_argv, envp))) { + .FAULT => |err| return errnoBug(err), // Bad pointer parameter. + .@"2BIG" => return error.SystemResources, + .MFILE => return error.ProcessFdQuotaExceeded, + .NAMETOOLONG => return error.NameTooLong, + .NFILE => return error.SystemFdQuotaExceeded, + .NOMEM => return error.SystemResources, + .ACCES => return error.AccessDenied, + .PERM => return error.PermissionDenied, + .INVAL => return error.InvalidExe, + .NOEXEC => return error.InvalidExe, + .IO => return error.FileSystem, + .LOOP => return error.FileSystem, + .ISDIR => return error.IsDir, + .NOENT => return error.FileNotFound, + .NOTDIR => return error.NotDir, + .TXTBSY => return error.FileBusy, + else => |err| switch (native_os) { + .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => switch (err) { + .BADEXEC => return error.InvalidExe, + .BADARCH => return error.InvalidExe, + else => return posix.unexpectedErrno(err), }, + .linux => switch (err) { + .LIBBAD => return error.InvalidExe, + else => return posix.unexpectedErrno(err), + }, + else => return posix.unexpectedErrno(err), }, - error.Canceled => |e| return e, - error.UnknownHostName => |e| return e, - }; + } } -fn lookupHostsReader( - t: *Threaded, - host_name: HostName, - resolved: *Io.Queue(HostName.LookupResult), - options: HostName.LookupOptions, - reader: *Io.Reader, -) error{ ReadFailed, Canceled, UnknownHostName }!void { - const t_io = io(t); - var addresses_len: usize = 0; - var canonical_name: ?HostName = null; - while (true) { - const line = reader.takeDelimiterExclusive('\n') catch |err| switch (err) { - error.StreamTooLong => { - // Skip lines that are too long. - _ = reader.discardDelimiterInclusive('\n') catch |e| switch (e) { - error.EndOfStream => break, - error.ReadFailed => return error.ReadFailed, - }; - continue; - }, - error.ReadFailed => return error.ReadFailed, - error.EndOfStream => break, - }; - reader.toss(1); - var split_it = std.mem.splitScalar(u8, line, '#'); - const no_comment_line = split_it.first(); +fn windowsMakePipeIn(rd: *?windows.HANDLE, wr: *?windows.HANDLE, sattr: *const windows.SECURITY_ATTRIBUTES) !void { + var rd_h: windows.HANDLE = undefined; + var wr_h: windows.HANDLE = undefined; + try windows.CreatePipe(&rd_h, &wr_h, sattr); + errdefer windowsDestroyPipe(rd_h, wr_h); + try windows.SetHandleInformation(wr_h, windows.HANDLE_FLAG_INHERIT, 0); + rd.* = rd_h; + wr.* = wr_h; +} - var line_it = std.mem.tokenizeAny(u8, no_comment_line, " \t"); - const ip_text = line_it.next() orelse continue; - var first_name_text: ?[]const u8 = null; - while (line_it.next()) |name_text| { - if (std.mem.eql(u8, name_text, host_name.bytes)) { - if (first_name_text == null) first_name_text = name_text; - break; - } - } else continue; +fn windowsDestroyPipe(rd: ?windows.HANDLE, wr: ?windows.HANDLE) void { + if (rd) |h| posix.close(h); + if (wr) |h| posix.close(h); +} - if (canonical_name == null) { - if (HostName.init(first_name_text.?)) |name_text| { - if (name_text.bytes.len <= options.canonical_name_buffer.len) { - const canonical_name_dest = options.canonical_name_buffer[0..name_text.bytes.len]; - @memcpy(canonical_name_dest, name_text.bytes); - canonical_name = .{ .bytes = canonical_name_dest }; - } - } else |_| {} - } +fn windowsMakeAsyncPipe(rd: *?windows.HANDLE, wr: *?windows.HANDLE, sattr: *const windows.SECURITY_ATTRIBUTES) !void { + var tmp_bufw: [128]u16 = undefined; - if (options.family != .ip6) { - if (IpAddress.parseIp4(ip_text, options.port)) |addr| { - try resolved.putOne(t_io, .{ .address = addr }); - addresses_len += 1; - } else |_| {} + // Anonymous pipes are built upon Named pipes. + // https://docs.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-createpipe + // Asynchronous (overlapped) read and write operations are not supported by anonymous pipes. + // https://docs.microsoft.com/en-us/windows/win32/ipc/anonymous-pipe-operations + const pipe_path = blk: { + var tmp_buf: [128]u8 = undefined; + // Forge a random path for the pipe. + const pipe_path = std.fmt.bufPrintSentinel( + &tmp_buf, + "\\\\.\\pipe\\zig-childprocess-{d}-{d}", + .{ windows.GetCurrentProcessId(), pipe_name_counter.fetchAdd(1, .monotonic) }, + 0, + ) catch unreachable; + const len = std.unicode.wtf8ToWtf16Le(&tmp_bufw, pipe_path) catch unreachable; + tmp_bufw[len] = 0; + break :blk tmp_bufw[0..len :0]; + }; + + // Create the read handle that can be used with overlapped IO ops. + const read_handle = windows.kernel32.CreateNamedPipeW( + pipe_path.ptr, + windows.PIPE_ACCESS_INBOUND | windows.FILE_FLAG_OVERLAPPED, + windows.PIPE_TYPE_BYTE, + 1, + 4096, + 4096, + 0, + sattr, + ); + if (read_handle == windows.INVALID_HANDLE_VALUE) { + switch (windows.GetLastError()) { + else => |err| return windows.unexpectedError(err), } - if (options.family != .ip4) { - if (IpAddress.parseIp6(ip_text, options.port)) |addr| { - try resolved.putOne(t_io, .{ .address = addr }); - addresses_len += 1; - } else |_| {} + } + errdefer posix.close(read_handle); + + var sattr_copy = sattr.*; + const write_handle = windows.kernel32.CreateFileW( + pipe_path.ptr, + .{ .GENERIC = .{ .WRITE = true } }, + 0, + &sattr_copy, + windows.OPEN_EXISTING, + @bitCast(windows.FILE.ATTRIBUTE{ .NORMAL = true }), + null, + ); + if (write_handle == windows.INVALID_HANDLE_VALUE) { + switch (windows.GetLastError()) { + else => |err| return windows.unexpectedError(err), } } + errdefer posix.close(write_handle); - if (canonical_name) |canon_name| try resolved.putOne(t_io, .{ .canonical_name = canon_name }); - if (addresses_len == 0) return error.UnknownHostName; + try windows.SetHandleInformation(read_handle, windows.HANDLE_FLAG_INHERIT, 0); + + rd.* = read_handle; + wr.* = write_handle; } -/// Writes DNS resolution query packet data to `w`; at most 280 bytes. -fn writeResolutionQuery(q: *[280]u8, op: u4, dname: []const u8, class: u8, ty: HostName.DnsRecord, entropy: [2]u8) usize { - // This implementation is ported from musl libc. - // A more idiomatic "ziggy" implementation would be welcome. - var name = dname; - if (std.mem.endsWith(u8, name, ".")) name.len -= 1; - assert(name.len <= 253); - const n = 17 + name.len + @intFromBool(name.len != 0); +var pipe_name_counter = std.atomic.Value(u32).init(1); - // Construct query template - ID will be filled later - q[0..2].* = entropy; - @memset(q[2..n], 0); - q[2] = @as(u8, op) * 8 + 1; - q[5] = 1; - @memcpy(q[13..][0..name.len], name); - var i: usize = 13; - var j: usize = undefined; - while (q[i] != 0) : (i = j + 1) { - j = i; - while (q[j] != 0 and q[j] != '.') : (j += 1) {} - // TODO determine the circumstances for this and whether or - // not this should be an error. - if (j - i - 1 > 62) unreachable; - q[i - 1] = @intCast(j - i); - } - q[i + 1] = @intFromEnum(ty); - q[i + 3] = class; - return n; +fn progressParentFile(userdata: ?*anyopaque) std.Progress.ParentFileError!File { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + + t.scanEnviron(); + + const int = try t.environ.zig_progress_handle; + + return .{ .handle = switch (@typeInfo(Io.File.Handle)) { + .int => int, + .pointer => @ptrFromInt(int), + else => return error.UnsupportedOperation, + } }; } -fn copyCanon(canonical_name_buffer: *[HostName.max_len]u8, name: []const u8) HostName { - const dest = canonical_name_buffer[0..name.len]; - @memcpy(dest, name); - return .{ .bytes = dest }; +pub fn environString(t: *Threaded, comptime name: []const u8) ?[:0]const u8 { + t.scanEnviron(); + return @field(t.environ.string, name); } -/// Darwin XNU 7195.50.7.100.1 introduced __ulock_wait2 and migrated code paths (notably pthread_cond_t) towards it: -/// https://github.com/apple/darwin-xnu/commit/d4061fb0260b3ed486147341b72468f836ed6c8f#diff-08f993cc40af475663274687b7c326cc6c3031e0db3ac8de7b24624610616be6 -/// -/// This XNU version appears to correspond to 11.0.1: -/// https://kernelshaman.blogspot.com/2021/01/building-xnu-for-macos-big-sur-1101.html -/// -/// ulock_wait() uses 32-bit micro-second timeouts where 0 = INFINITE or no-timeout -/// ulock_wait2() uses 64-bit nano-second timeouts (with the same convention) -const darwin_supports_ulock_wait2 = builtin.os.version_range.semver.min.major >= 11; +fn random(userdata: ?*anyopaque, buffer: []u8) void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + const thread = Thread.current orelse return randomMainThread(t, buffer); + if (!thread.csprng.isInitialized()) { + @branchHint(.unlikely); + var seed: [Csprng.seed_len]u8 = undefined; + randomMainThread(t, &seed); + thread.csprng.rng = .init(seed); + } + thread.csprng.rng.fill(buffer); +} -fn futexWait(t: *Threaded, ptr: *const std.atomic.Value(u32), expect: u32) Io.Cancelable!void { - @branchHint(.cold); - - if (builtin.cpu.arch.isWasm()) { - comptime assert(builtin.cpu.has(.wasm, .atomics)); - try t.checkCancel(); - const timeout: i64 = -1; - const signed_expect: i32 = @bitCast(expect); - const result = asm volatile ( - \\local.get %[ptr] - \\local.get %[expected] - \\local.get %[timeout] - \\memory.atomic.wait32 0 - \\local.set %[ret] - : [ret] "=r" (-> u32), - : [ptr] "r" (&ptr.raw), - [expected] "r" (signed_expect), - [timeout] "r" (timeout), - ); - switch (result) { - 0 => {}, // ok - 1 => {}, // expected != loaded - 2 => assert(!is_debug), // timeout - else => assert(!is_debug), - } - } else switch (native_os) { - .linux => { - const linux = std.os.linux; - try t.checkCancel(); - const rc = linux.futex_4arg(ptr, .{ .cmd = .WAIT, .private = true }, expect, null); - if (is_debug) switch (linux.errno(rc)) { - .SUCCESS => {}, // notified by `wake()` - .INTR => {}, // gives caller a chance to check cancellation - .AGAIN => {}, // ptr.* != expect - .INVAL => {}, // possibly timeout overflow - .TIMEDOUT => unreachable, - .FAULT => unreachable, // ptr was invalid - else => unreachable, - }; - }, - .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => { - const c = std.c; - const flags: c.UL = .{ - .op = .COMPARE_AND_WAIT, - .NO_ERRNO = true, +fn randomMainThread(t: *Threaded, buffer: []u8) void { + t.mutex.lock(); + defer t.mutex.unlock(); + + if (!t.csprng.isInitialized()) { + @branchHint(.unlikely); + var seed: [Csprng.seed_len]u8 = undefined; + { + t.mutex.unlock(); + defer t.mutex.lock(); + + const prev = swapCancelProtection(t, .blocked); + defer _ = swapCancelProtection(t, prev); + + randomSecure(t, &seed) catch |err| switch (err) { + error.Canceled => unreachable, + error.EntropyUnavailable => { + @memset(&seed, 0); + const aslr_addr = @intFromPtr(t); + std.mem.writeInt(usize, seed[seed.len - @sizeOf(usize) ..][0..@sizeOf(usize)], aslr_addr, .native); + switch (native_os) { + .windows => fallbackSeedWindows(&seed), + .wasi => if (builtin.link_libc) fallbackSeedPosix(&seed) else fallbackSeedWasi(&seed), + else => fallbackSeedPosix(&seed), + } + }, }; - try t.checkCancel(); - const status = if (darwin_supports_ulock_wait2) - c.__ulock_wait2(flags, ptr, expect, 0, 0) - else - c.__ulock_wait(flags, ptr, expect, 0); + } + t.csprng.rng = .init(seed); + } - if (status >= 0) return; + t.csprng.rng.fill(buffer); +} - if (is_debug) switch (@as(c.E, @enumFromInt(-status))) { - .INTR => {}, // spurious wake - // Address of the futex was paged out. This is unlikely, but possible in theory, and - // pthread/libdispatch on darwin bother to handle it. In this case we'll return - // without waiting, but the caller should retry anyway. - .FAULT => {}, - .TIMEDOUT => unreachable, - else => unreachable, - }; +fn fallbackSeedPosix(seed: *[Csprng.seed_len]u8) void { + std.mem.writeInt(posix.pid_t, seed[0..@sizeOf(posix.pid_t)], posix.system.getpid(), .native); + const i_1 = @sizeOf(posix.pid_t); + + var ts: posix.timespec = undefined; + const Sec = @TypeOf(ts.sec); + const Nsec = @TypeOf(ts.nsec); + const i_2 = i_1 + @sizeOf(Sec); + switch (posix.errno(posix.system.clock_gettime(.REALTIME, &ts))) { + .SUCCESS => { + std.mem.writeInt(Sec, seed[i_1..][0..@sizeOf(Sec)], ts.sec, .native); + std.mem.writeInt(Nsec, seed[i_2..][0..@sizeOf(Nsec)], ts.nsec, .native); }, - .windows => { - try t.checkCancel(); - switch (windows.ntdll.RtlWaitOnAddress(ptr, &expect, @sizeOf(@TypeOf(expect)), null)) { - .SUCCESS => {}, - .CANCELLED => return error.Canceled, - else => recoverableOsBugDetected(), + else => {}, + } +} + +fn fallbackSeedWindows(seed: *[Csprng.seed_len]u8) void { + var pc: windows.LARGE_INTEGER = undefined; + _ = windows.ntdll.RtlQueryPerformanceCounter(&pc); + std.mem.writeInt(windows.LARGE_INTEGER, seed[0..@sizeOf(windows.LARGE_INTEGER)], pc, .native); +} + +fn fallbackSeedWasi(seed: *[Csprng.seed_len]u8) void { + var ts: std.os.wasi.timestamp_t = undefined; + if (std.os.wasi.clock_time_get(.REALTIME, 1, &ts) == .SUCCESS) { + std.mem.writeInt(std.os.wasi.timestamp_t, seed[0..@sizeOf(std.os.wasi.timestamp_t)], ts, .native); + } +} + +fn randomSecure(userdata: ?*anyopaque, buffer: []u8) Io.RandomSecureError!void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + + if (is_windows) { + if (buffer.len == 0) return; + // ProcessPrng from bcryptprimitives.dll has the following properties: + // * introduces a dependency on bcryptprimitives.dll, which apparently + // runs a test suite every time it is loaded + // * heap allocates a 48-byte buffer, handling failure by returning NO_MEMORY in a BOOL + // despite the function being documented to always return TRUE + // * reads from "\\Device\\CNG" which then seeds a per-CPU AES CSPRNG + // Therefore, that function is avoided in favor of using the device directly. + const cng_device = try getCngHandle(t); + var io_status_block: windows.IO_STATUS_BLOCK = undefined; + var i: usize = 0; + const syscall: Syscall = try .start(); + while (true) { + const remaining_len = std.math.lossyCast(u32, buffer.len - i); + switch (windows.ntdll.NtDeviceIoControlFile( + cng_device, + null, + null, + null, + &io_status_block, + windows.IOCTL.KSEC.GEN_RANDOM, + null, + 0, + buffer[i..].ptr, + remaining_len, + )) { + .SUCCESS => { + i += remaining_len; + if (buffer.len - i == 0) { + return syscall.finish(); + } else { + try syscall.checkCancel(); + continue; + } + }, + .CANCELLED => { + try syscall.checkCancel(); + continue; + }, + else => return syscall.fail(error.EntropyUnavailable), } - }, - .freebsd => { - const flags = @intFromEnum(std.c.UMTX_OP.WAIT_UINT_PRIVATE); - try t.checkCancel(); - const rc = std.c._umtx_op(@intFromPtr(&ptr.raw), flags, @as(c_ulong, expect), 0, 0); - if (is_debug) switch (posix.errno(rc)) { - .SUCCESS => {}, - .FAULT => unreachable, // one of the args points to invalid memory - .INVAL => unreachable, // arguments should be correct - .TIMEDOUT => unreachable, // no timeout provided - .INTR => {}, // spurious wake - else => unreachable, - }; - }, - else => @compileError("unimplemented: futexWait"), - } -} - -pub fn futexWaitUncancelable(ptr: *const std.atomic.Value(u32), expect: u32) void { - @branchHint(.cold); - - if (builtin.cpu.arch.isWasm()) { - comptime assert(builtin.cpu.has(.wasm, .atomics)); - const timeout: i64 = -1; - const signed_expect: i32 = @bitCast(expect); - const result = asm volatile ( - \\local.get %[ptr] - \\local.get %[expected] - \\local.get %[timeout] - \\memory.atomic.wait32 0 - \\local.set %[ret] - : [ret] "=r" (-> u32), - : [ptr] "r" (&ptr.raw), - [expected] "r" (signed_expect), - [timeout] "r" (timeout), - ); - switch (result) { - 0 => {}, // ok - 1 => {}, // expected != loaded - 2 => recoverableOsBugDetected(), // timeout - else => recoverableOsBugDetected(), } - } else switch (native_os) { - .linux => { - const linux = std.os.linux; - const rc = linux.futex_4arg(ptr, .{ .cmd = .WAIT, .private = true }, expect, null); - switch (linux.errno(rc)) { - .SUCCESS => {}, // notified by `wake()` - .INTR => {}, // gives caller a chance to check cancellation - .AGAIN => {}, // ptr.* != expect - .INVAL => {}, // possibly timeout overflow - .TIMEDOUT => recoverableOsBugDetected(), - .FAULT => recoverableOsBugDetected(), // ptr was invalid - else => recoverableOsBugDetected(), - } - }, - .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => { - const c = std.c; - const flags: c.UL = .{ - .op = .COMPARE_AND_WAIT, - .NO_ERRNO = true, - }; - const status = if (darwin_supports_ulock_wait2) - c.__ulock_wait2(flags, ptr, expect, 0, 0) - else - c.__ulock_wait(flags, ptr, expect, 0); - - if (status >= 0) return; - - switch (@as(c.E, @enumFromInt(-status))) { - // Wait was interrupted by the OS or other spurious signalling. - .INTR => {}, - // Address of the futex was paged out. This is unlikely, but possible in theory, and - // pthread/libdispatch on darwin bother to handle it. In this case we'll return - // without waiting, but the caller should retry anyway. - .FAULT => {}, - .TIMEDOUT => recoverableOsBugDetected(), - else => recoverableOsBugDetected(), - } - }, - .windows => { - switch (windows.ntdll.RtlWaitOnAddress(ptr, &expect, @sizeOf(@TypeOf(expect)), null)) { - .SUCCESS, .CANCELLED => {}, - else => recoverableOsBugDetected(), + } + + if (builtin.link_libc and @TypeOf(posix.system.arc4random_buf) != void) { + if (buffer.len == 0) return; + posix.system.arc4random_buf(buffer.ptr, buffer.len); + return; + } + + if (native_os == .wasi) { + if (buffer.len == 0) return; + const syscall: Syscall = try .start(); + while (true) switch (std.os.wasi.random_get(buffer.ptr, buffer.len)) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => return syscall.fail(error.EntropyUnavailable), + }; + } + + if (@TypeOf(posix.system.getrandom) != void) { + const getrandom = if (use_libc_getrandom) std.c.getrandom else std.os.linux.getrandom; + var i: usize = 0; + const syscall: Syscall = try .start(); + while (buffer.len - i != 0) { + const buf = buffer[i..]; + const rc = getrandom(buf.ptr, buf.len, 0); + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + const n: usize = @intCast(rc); + i += n; + continue; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => return syscall.fail(error.EntropyUnavailable), } - }, - .freebsd => { - const flags = @intFromEnum(std.c.UMTX_OP.WAIT_UINT_PRIVATE); - const rc = std.c._umtx_op(@intFromPtr(&ptr.raw), flags, @as(c_ulong, expect), 0, 0); + } + return; + } + + if (native_os == .emscripten) { + if (buffer.len == 0) return; + const err = posix.errno(std.c.getentropy(buffer.ptr, buffer.len)); + switch (err) { + .SUCCESS => return, + else => return error.EntropyUnavailable, + } + } + + if (native_os == .linux) { + comptime assert(use_dev_urandom); + const urandom_fd = try getRandomFd(t); + + var i: usize = 0; + while (buffer.len - i != 0) { + const syscall: Syscall = try .start(); + const rc = posix.system.read(urandom_fd, buffer[i..].ptr, buffer.len - i); switch (posix.errno(rc)) { - .SUCCESS => {}, - .INTR => {}, // spurious wake - .FAULT => recoverableOsBugDetected(), // one of the args points to invalid memory - .INVAL => recoverableOsBugDetected(), // arguments should be correct - .TIMEDOUT => recoverableOsBugDetected(), // no timeout provided - else => recoverableOsBugDetected(), + .SUCCESS => { + syscall.finish(); + const n: usize = @intCast(rc); + if (n == 0) return error.EntropyUnavailable; + i += n; + continue; + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => return syscall.fail(error.EntropyUnavailable), } - }, - else => @compileError("unimplemented: futexWaitUncancelable"), + } } + + return error.EntropyUnavailable; } -pub fn futexWaitDurationUncancelable(ptr: *const std.atomic.Value(u32), expect: u32, timeout: Io.Duration) void { - @branchHint(.cold); +fn getRandomFd(t: *Threaded) Io.RandomSecureError!posix.fd_t { + { + t.mutex.lock(); + defer t.mutex.unlock(); - if (native_os == .linux) { - const linux = std.os.linux; - var ts = timestampToPosix(timeout.toNanoseconds()); - const rc = linux.futex_4arg(ptr, .{ .cmd = .WAIT, .private = true }, expect, &ts); - if (is_debug) switch (linux.errno(rc)) { - .SUCCESS => {}, // notified by `wake()` - .INTR => {}, // gives caller a chance to check cancellation - .AGAIN => {}, // ptr.* != expect - .TIMEDOUT => {}, - .INVAL => {}, // possibly timeout overflow - .FAULT => unreachable, // ptr was invalid - else => unreachable, - }; - return; - } else { - @compileError("TODO"); + if (t.random_file.fd == -2) return error.EntropyUnavailable; + if (t.random_file.fd != -1) return t.random_file.fd; } -} -pub fn futexWake(ptr: *const std.atomic.Value(u32), max_waiters: u32) void { - @branchHint(.cold); + const mode: posix.mode_t = 0; - if (builtin.cpu.arch.isWasm()) { - comptime assert(builtin.cpu.has(.wasm, .atomics)); - assert(max_waiters != 0); - const woken_count = asm volatile ( - \\local.get %[ptr] - \\local.get %[waiters] - \\memory.atomic.notify 0 - \\local.set %[ret] - : [ret] "=r" (-> u32), - : [ptr] "r" (&ptr.raw), - [waiters] "r" (max_waiters), - ); - _ = woken_count; // can be 0 when linker flag 'shared-memory' is not enabled - } else switch (native_os) { - .linux => { - const linux = std.os.linux; - switch (linux.errno(linux.futex_3arg( - &ptr.raw, - .{ .cmd = .WAKE, .private = true }, - @min(max_waiters, std.math.maxInt(i32)), - ))) { - .SUCCESS => return, // successful wake up - .INVAL => return, // invalid futex_wait() on ptr done elsewhere - .FAULT => return, // pointer became invalid while doing the wake - else => return recoverableOsBugDetected(), // deadlock due to operating system bug + const fd: posix.fd_t = fd: { + const syscall: Syscall = try .start(); + while (true) { + const rc = openat_sym(posix.AT.FDCWD, "/dev/urandom", .{ + .ACCMODE = .RDONLY, + .CLOEXEC = true, + }, mode); + switch (posix.errno(rc)) { + .SUCCESS => { + syscall.finish(); + break :fd @intCast(rc); + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => return syscall.fail(error.EntropyUnavailable), } - }, - .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => { - const c = std.c; - const flags: c.UL = .{ - .op = .COMPARE_AND_WAIT, - .NO_ERRNO = true, - .WAKE_ALL = max_waiters > 1, - }; + } + }; + errdefer posix.close(fd); + + switch (native_os) { + .linux => { + const sys = if (statx_use_c) std.c else std.os.linux; + const syscall: Syscall = try .start(); while (true) { - const status = c.__ulock_wake(flags, ptr, 0); - if (status >= 0) return; - switch (@as(c.E, @enumFromInt(-status))) { - .INTR, .CANCELED => continue, // spurious wake() - .FAULT => unreachable, // __ulock_wake doesn't generate EFAULT according to darwin pthread_cond_t - .NOENT => return, // nothing was woken up - .ALREADY => unreachable, // only for UL.Op.WAKE_THREAD - else => unreachable, // deadlock due to operating system bug + var statx = std.mem.zeroes(std.os.linux.Statx); + switch (sys.errno(sys.statx(fd, "", std.os.linux.AT.EMPTY_PATH, .{ .TYPE = true }, &statx))) { + .SUCCESS => { + syscall.finish(); + if (!statx.mask.TYPE) return error.EntropyUnavailable; + t.mutex.lock(); // Another thread might have won the race. + defer t.mutex.unlock(); + if (t.random_file.fd >= 0) { + posix.close(fd); + return t.random_file.fd; + } else if (!posix.S.ISCHR(statx.mode)) { + t.random_file.fd = -2; + return error.EntropyUnavailable; + } else { + t.random_file.fd = fd; + return fd; + } + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => return syscall.fail(error.EntropyUnavailable), } } }, - .windows => { - assert(max_waiters != 0); - switch (max_waiters) { - 1 => windows.ntdll.RtlWakeAddressSingle(ptr), - else => windows.ntdll.RtlWakeAddressAll(ptr), - } - }, - .freebsd => { - const rc = std.c._umtx_op( - @intFromPtr(&ptr.raw), - @intFromEnum(std.c.UMTX_OP.WAKE_PRIVATE), - @as(c_ulong, max_waiters), - 0, // there is no timeout struct - 0, // there is no timeout struct pointer - ); - switch (posix.errno(rc)) { - .SUCCESS => {}, - .FAULT => {}, // it's ok if the ptr doesn't point to valid memory - .INVAL => unreachable, // arguments should be correct - else => unreachable, // deadlock due to operating system bug + else => { + const syscall: Syscall = try .start(); + while (true) { + var stat = std.mem.zeroes(posix.Stat); + switch (posix.errno(fstat_sym(fd, &stat))) { + .SUCCESS => { + syscall.finish(); + t.mutex.lock(); // Another thread might have won the race. + defer t.mutex.unlock(); + if (t.random_file.fd >= 0) { + posix.close(fd); + return t.random_file.fd; + } else if (!posix.S.ISCHR(stat.mode)) { + t.random_file.fd = -2; + return error.EntropyUnavailable; + } else { + t.random_file.fd = fd; + return fd; + } + }, + .INTR => { + try syscall.checkCancel(); + continue; + }, + else => return syscall.fail(error.EntropyUnavailable), + } } }, - else => @compileError("unimplemented: futexWake"), } } -/// A thread-safe logical boolean value which can be `set` and `unset`. -/// -/// It can also block threads until the value is set with cancelation via timed -/// waits. Statically initializable; four bytes on all targets. -pub const ResetEvent = switch (native_os) { - .illumos, .netbsd => ResetEventPosix, - else => ResetEventFutex, +test { + _ = @import("Threaded/test.zig"); +} + +const use_parking_futex = switch (builtin.target.os.tag) { + .windows => true, // RtlWaitOnAddress is a userland implementation anyway + .netbsd => true, // NetBSD has `futex(2)`, but it's historically been quite buggy. TODO: evaluate whether it's okay to use now. + .illumos => true, // Illumos has no futex mechanism + else => false, +}; +const use_parking_sleep = switch (builtin.target.os.tag) { + // On Windows, we can implement sleep either with `NtDelayExecution` (which is how `SleepEx` in + // kernel32 works) or `NtWaitForAlertByThreadId` (thread parking). We're already using the + // latter for futex, so we may as well use it for sleeping too, to maximise code reuse. I'm + // also more confident that it will always correctly handle the cancelation race (so "unpark" + // before "park" causes "park" to return immediately): it *seems* like alertable sleeps paired + // with `NtAlertThread` do actually do this too, but there could be some caveat (e.g. it might + // fail under some specific condition), whereas `NtWaitForAlertByThreadId` must reliably trigger + // this behavior because `RtlWaitOnAddress` relies on it. + .windows => true, + + // These targets have `_lwp_park`, which is superior to POSIX nanosleep because it has a better + // cancelation mechanism. + .netbsd, + .illumos, + => true, + + else => false, }; -/// A `ResetEvent` implementation based on futexes. -const ResetEventFutex = enum(u32) { - unset = 0, - waiting = 1, - is_set = 2, +const parking_futex = struct { + comptime { + assert(use_parking_futex); + } - /// Returns whether the logical boolean is `set`. - /// - /// Once `reset` is called, this returns false until the next `set`. - /// - /// The memory accesses before the `set` can be said to happen before - /// `isSet` returns true. - pub fn isSet(ref: *const ResetEventFutex) bool { - if (builtin.single_threaded) return switch (ref.*) { - .unset => false, - .waiting => unreachable, - .is_set => true, + const Bucket = struct { + /// Used as a fast check for `wake` to avoid having to acquire `mutex` to discover there are no + /// waiters. It is important for `wait` to increment this *before* checking the futex value to + /// avoid a race. + num_waiters: std.atomic.Value(u32), + /// Protects `waiters`. + mutex: std.Thread.Mutex, + waiters: std.DoublyLinkedList, + + /// Prevent false sharing between buckets. + _: void align(std.atomic.cache_line) = {}, + + const init: Bucket = .{ .num_waiters = .init(0), .mutex = .{}, .waiters = .{} }; + }; + + const Waiter = struct { + node: std.DoublyLinkedList.Node, + address: usize, + tid: std.Thread.Id, + /// `thread_status.cancelation` is `.parked` while the thread is waiting. The single thread + /// which atomically updates it (to `.none` or `.canceling`) is responsible for: + /// + /// * Removing the `Waiter` from `Bucket.waiters` + /// * Decrementing `Bucket.num_waiters` + /// * Unparking the thread (*after* the above, so that the `Waiter` does not go out of scope + /// while it is still in the `Bucket`). + thread_status: *std.atomic.Value(Thread.Status), + }; + + fn bucketForAddress(address: usize) *Bucket { + const global = struct { + /// Length must be a power of two. The longer this array, the less likely contention is + /// between different futexes. This length seems like it'll provide a reasonable balance + /// between contention and memory usage: assuming a 128-byte `Bucket` (due to cache line + /// alignment), this uses 32 KiB of memory. + var buckets: [256]Bucket = @splat(.init); }; - // Acquire barrier ensures memory accesses before `set` happen before - // returning true. - return @atomicLoad(ResetEventFutex, ref, .acquire) == .is_set; + + // Here we use Fibonacci hashing: the golden ratio can be used to evenly redistribute input + // values across a range, giving a poor, but extremely quick to compute, hash. + + // This literal is the rounded value of '2^64 / phi' (where 'phi' is the golden ratio). The + // shift then converts it to '2^b / phi', where 'b' is the pointer bit width. + const fibonacci_multiplier = 0x9E3779B97F4A7C15 >> (64 - @bitSizeOf(usize)); + const hashed = address *% fibonacci_multiplier; + + comptime assert(std.math.isPowerOfTwo(global.buckets.len)); + // The high bits of `hashed` have better entropy than the low bits. + const index = hashed >> (@bitSizeOf(usize) - @ctz(global.buckets.len)); + + return &global.buckets[index]; } - /// Blocks the calling thread until `set` is called. - /// - /// This is effectively a more efficient version of `while (!isSet()) {}`. - /// - /// The memory accesses before the `set` can be said to happen before `wait` returns. - pub fn wait(ref: *ResetEventFutex, t: *Threaded) Io.Cancelable!void { - if (builtin.single_threaded) switch (ref.*) { - .unset => unreachable, // Deadlock, no other threads to wake us up. - .waiting => unreachable, // Invalid state. - .is_set => return, + fn wait(ptr: *const u32, expect: u32, uncancelable: bool, timeout: Io.Timeout) Io.Cancelable!void { + const bucket = bucketForAddress(@intFromPtr(ptr)); + + // Put the threadlocal access outside of the critical section. + const opt_thread = Thread.current; + const self_tid = if (opt_thread) |thread| thread.id else std.Thread.getCurrentId(); + + var waiter: Waiter = .{ + .node = undefined, // populated by list append + .address = @intFromPtr(ptr), + .tid = self_tid, + .thread_status = undefined, // populated in critical section }; - // Try to set the state from `unset` to `waiting` to indicate to the - // `set` thread that others are blocked on the ResetEventFutex. Avoid using - // any strict barriers until we know the ResetEventFutex is set. - var state = @atomicLoad(ResetEventFutex, ref, .acquire); - if (state == .is_set) { - @branchHint(.likely); - return; - } - if (state == .unset) { - state = @cmpxchgStrong(ResetEventFutex, ref, state, .waiting, .acquire, .acquire) orelse .waiting; + + var status_buf: std.atomic.Value(Thread.Status) = undefined; + + { + bucket.mutex.lock(); + defer bucket.mutex.unlock(); + + _ = bucket.num_waiters.fetchAdd(1, .acquire); + + if (@atomicLoad(u32, ptr, .monotonic) != expect) { + assert(bucket.num_waiters.fetchSub(1, .monotonic) > 0); + return; + } + + // This is in the critical section to avoid marking the thread as parked until we're + // certain that we're actually going to park. + waiter.thread_status = status: { + cancelable: { + if (uncancelable) break :cancelable; + const thread = opt_thread orelse break :cancelable; + switch (thread.cancel_protection) { + .blocked => break :cancelable, + .unblocked => {}, + } + thread.futex_waiter = &waiter; + const old_status = thread.status.fetchOr( + .{ .cancelation = @enumFromInt(0b001), .awaitable = .null }, + .release, // release `thread.futex_waiter` + ); + switch (old_status.cancelation) { + .none => {}, // status is now `.parked` + .canceling => { + // status is now `.canceled` + assert(bucket.num_waiters.fetchSub(1, .monotonic) > 0); + return error.Canceled; + }, + .canceled => break :cancelable, // status is still `.canceled` + .parked => unreachable, + .blocked => unreachable, + .blocked_windows_dns => unreachable, + .blocked_canceling => unreachable, + } + // We could now be unparked for a cancelation at any time! + break :status &thread.status; + } + // This is an uncancelable wait, so just use `status_buf`. Note that the value of + // `status_buf.awaitable` is irrelevant because this is only visible to futex code, + // while only cancelation cares about `awaitable`. + status_buf.raw = .{ .cancelation = .parked, .awaitable = .null }; + break :status &status_buf; + }; + + bucket.waiters.append(&waiter.node); } - while (state == .waiting) { - try futexWait(t, @ptrCast(ref), @intFromEnum(ResetEventFutex.waiting)); - state = @atomicLoad(ResetEventFutex, ref, .acquire); + + if (park(timeout, ptr)) { + // We were unparked by either `wake` or cancelation, so our current status is either + // `.none` or `.canceling`. In either case, they've already removed `waiter` from + // `bucket`, so we have nothing more to do! + } else |err| switch (err) { + error.Timeout => { + // We're not out of the woods yet: an unpark could race with the timeout. + const old_status = waiter.thread_status.fetchAnd( + .{ .cancelation = @enumFromInt(0b110), .awaitable = .all_ones }, + .monotonic, + ); + switch (old_status.cancelation) { + .parked => { + // No race. It is our responsibility to remove `waiter` from `bucket`. + // New status is `.none`. + bucket.mutex.lock(); + defer bucket.mutex.unlock(); + bucket.waiters.remove(&waiter.node); + assert(bucket.num_waiters.fetchSub(1, .monotonic) > 0); + }, + .none, .canceling => { + // Race condition: the timeout was reached, then `wake` or a canceler tried + // to unpark us. Whoever did that will remove us from `bucket`. Wait for + // that (and drop the unpark request in doing so). + // New status is `.none` or `.canceling` respectively. + park(.none, ptr) catch |e| switch (e) { + error.Timeout => unreachable, + }; + }, + .canceled => unreachable, + .blocked => unreachable, + .blocked_windows_dns => unreachable, + .blocked_canceling => unreachable, + } + }, } - assert(state == .is_set); } - /// Same as `wait` except uninterruptible. - pub fn waitUncancelable(ref: *ResetEventFutex) void { - if (builtin.single_threaded) switch (ref.*) { - .unset => unreachable, // Deadlock, no other threads to wake us up. - .waiting => unreachable, // Invalid state. - .is_set => return, - }; - // Try to set the state from `unset` to `waiting` to indicate to the - // `set` thread that others are blocked on the ResetEventFutex. Avoid using - // any strict barriers until we know the ResetEventFutex is set. - var state = @atomicLoad(ResetEventFutex, ref, .acquire); - if (state == .is_set) { + fn wake(ptr: *const u32, max_waiters: u32) void { + if (max_waiters == 0) return; + + const bucket = bucketForAddress(@intFromPtr(ptr)); + + // To ensure the store to `ptr` is ordered before this check, we effectively want a `.release` + // load, but that doesn't exist in the C11 memory model, so emulate it with a non-mutating rmw. + if (bucket.num_waiters.fetchAdd(0, .release) == 0) { @branchHint(.likely); - return; - } - if (state == .unset) { - state = @cmpxchgStrong(ResetEventFutex, ref, state, .waiting, .acquire, .acquire) orelse .waiting; + return; // no waiters } - while (state == .waiting) { - futexWaitUncancelable(@ptrCast(ref), @intFromEnum(ResetEventFutex.waiting)); - state = @atomicLoad(ResetEventFutex, ref, .acquire); + + // Waiters removed from the linked list under the mutex so we can unpark their threads outside + // of the critical section. This forms a singly-linked list of waiters using `Waiter.node.next`. + var waking_head: ?*std.DoublyLinkedList.Node = null; + { + bucket.mutex.lock(); + defer bucket.mutex.unlock(); + + var num_removed: u32 = 0; + var it = bucket.waiters.first; + while (num_removed < max_waiters) { + const waiter: *Waiter = @fieldParentPtr("node", it orelse break); + it = waiter.node.next; + if (waiter.address != @intFromPtr(ptr)) continue; + const old_status = waiter.thread_status.fetchAnd( + .{ .cancelation = @enumFromInt(0b110), .awaitable = .all_ones }, + .monotonic, + ); + switch (old_status.cancelation) { + .parked => {}, // state updated to `.none` + .none => unreachable, // if another `wake` call is unparking this thread, it should have removed it from the list + .canceling => continue, // race with a canceler who hasn't called `removeCanceledWaiter` yet + .canceled => unreachable, + .blocked => unreachable, + .blocked_windows_dns => unreachable, + .blocked_canceling => unreachable, + } + // We're waking this waiter. Remove them from the bucket and add them to our local list. + bucket.waiters.remove(&waiter.node); + waiter.node.next = waking_head; + waking_head = &waiter.node; + num_removed += 1; + // Signal to `waiter` that they're about to be unparked, in case we're racing with their + // timeout. See corresponding logic in `wake`. + waiter.address = 0; + } + + _ = bucket.num_waiters.fetchSub(num_removed, .monotonic); } - assert(state == .is_set); - } - /// Marks the logical boolean as `set` and unblocks any threads in `wait` - /// or `timedWait` to observe the new state. - /// - /// The logical boolean stays `set` until `reset` is called, making future - /// `set` calls do nothing semantically. - /// - /// The memory accesses before `set` can be said to happen before `isSet` - /// returns true or `wait`/`timedWait` return successfully. - pub fn set(ref: *ResetEventFutex) void { - if (builtin.single_threaded) { - ref.* = .is_set; - return; + var unpark_buf: [128]UnparkTid = undefined; + var unpark_len: usize = 0; + + // Finally, unpark the threads. + while (waking_head) |node| { + waking_head = node.next; + const waiter: *Waiter = @fieldParentPtr("node", node); + unpark_buf[unpark_len] = waiter.tid; + unpark_len += 1; + if (unpark_len == unpark_buf.len) { + unpark(&unpark_buf, ptr); + unpark_len = 0; + } } - if (@atomicRmw(ResetEventFutex, ref, .Xchg, .is_set, .release) == .waiting) { - futexWake(@ptrCast(ref), std.math.maxInt(u32)); + if (unpark_len > 0) { + unpark(unpark_buf[0..unpark_len], ptr); } } - /// Unmarks the ResetEventFutex as if `set` was never called. - /// - /// Assumes no threads are blocked in `wait` or `timedWait`. Concurrent - /// calls to `set`, `isSet` and `reset` are allowed. - pub fn reset(ref: *ResetEventFutex) void { - if (builtin.single_threaded) { - ref.* = .unset; - return; + fn removeCanceledWaiter(waiter: *Waiter) void { + const bucket = bucketForAddress(waiter.address); + bucket.mutex.lock(); + defer bucket.mutex.unlock(); + bucket.waiters.remove(&waiter.node); + assert(bucket.num_waiters.fetchSub(1, .monotonic) > 0); + } +}; +const parking_sleep = struct { + comptime { + assert(use_parking_sleep); + } + fn sleep(timeout: Io.Timeout) Io.Cancelable!void { + const opt_thread = Thread.current; + cancelable: { + const thread = opt_thread orelse break :cancelable; + switch (thread.cancel_protection) { + .blocked => break :cancelable, + .unblocked => {}, + } + thread.futex_waiter = null; + { + const old_status = thread.status.fetchOr( + .{ .cancelation = @enumFromInt(0b001), .awaitable = .null }, + .release, // release `thread.futex_waiter` + ); + switch (old_status.cancelation) { + .none => {}, // status is now `.parked` + .canceling => return error.Canceled, // status is now `.canceled` + .canceled => break :cancelable, // status is still `.canceled` + .parked => unreachable, + .blocked => unreachable, + .blocked_windows_dns => unreachable, + .blocked_canceling => unreachable, + } + } + if (park(timeout, null)) { + // The only reason this could possibly happen is cancelation. + const old_status = thread.status.load(.monotonic); + assert(old_status.cancelation == .canceling); + thread.status.store( + .{ .cancelation = .canceled, .awaitable = old_status.awaitable }, + .monotonic, + ); + return error.Canceled; + } else |err| switch (err) { + error.Timeout => { + // We're not out of the woods yet: an unpark could race with the timeout. + const old_status = thread.status.fetchAnd( + .{ .cancelation = @enumFromInt(0b110), .awaitable = .all_ones }, + .monotonic, + ); + switch (old_status.cancelation) { + .parked => return, // No race; new status is `.none` + .canceling => { + // Race condition: the timeout was reached, then someone tried to unpark + // us for a cancelation. Whoever did that will have called `unpark`, so + // drop that unpark request by waiting for it. + // Status is still `.canceling`. + park(.none, null) catch |e| switch (e) { + error.Timeout => unreachable, + }; + return; + }, + .none => unreachable, + .canceled => unreachable, + .blocked => unreachable, + .blocked_windows_dns => unreachable, + .blocked_canceling => unreachable, + } + }, + } + } + // Uncancelable sleep; we expect not to be manually unparked. + if (park(timeout, null)) { + unreachable; // unexpected unpark + } else |err| switch (err) { + error.Timeout => return, } - @atomicStore(ResetEventFutex, ref, .unset, .monotonic); } }; -/// A `ResetEvent` implementation based on pthreads API. -const ResetEventPosix = struct { - cond: std.c.pthread_cond_t, - mutex: std.c.pthread_mutex_t, - state: ResetEventFutex, - - pub const unset: ResetEventPosix = .{ - .cond = std.c.PTHREAD_COND_INITIALIZER, - .mutex = std.c.PTHREAD_MUTEX_INITIALIZER, - .state = .unset, - }; +/// `addr_hint` has no semantic effect, but may allow the OS to optimize this operation. +fn park(timeout: Io.Timeout, addr_hint: ?*const anyopaque) error{Timeout}!void { + comptime assert(use_parking_futex or use_parking_sleep); + switch (builtin.target.os.tag) { + .windows => { + var timeout_buf: windows.LARGE_INTEGER = undefined; + const raw_timeout: ?*windows.LARGE_INTEGER = timeout: switch (timeout) { + .none => null, + .deadline => |timestamp| continue :timeout .{ .duration = .{ + .clock = timestamp.clock, + .raw = (nowWindows(timestamp.clock) catch unreachable).durationTo(timestamp.raw), + } }, + .duration => |duration| { + _ = duration.clock; // Windows only supports monotonic + timeout_buf = @intCast(@divTrunc(-duration.raw.nanoseconds, 100)); + break :timeout &timeout_buf; + }, + }; + // `RtlWaitOnAddress` passes the futex address in as the first argument to this call, + // but it's unclear what that actually does, especially since `NtAlertThreadByThreadId` + // does *not* accept the address so the kernel can't really be using it as a hint. An + // old Microsoft blog post discusses a more traditional futex-like mechanism in the + // kernel which definitely isn't how `RtlWaitOnAddress` works today: + // + // https://devblogs.microsoft.com/oldnewthing/20160826-00/?p=94185 + // + // ...so it's possible this argument is simply a remnant which no longer does anything + // (perhaps the implementation changed during development but someone forgot to remove + // this parameter). However, to err on the side of caution, let's match the behavior of + // `RtlWaitOnAddress` and pass the pointer, in case the kernel ever does something + // stupid such as trying to dereference it. + switch (windows.ntdll.NtWaitForAlertByThreadId(addr_hint, raw_timeout)) { + .ALERTED => return, + .TIMEOUT => return error.Timeout, + else => unreachable, + } + }, + .netbsd => { + var ts_buf: posix.timespec = undefined; + const ts: ?*posix.timespec, const abstime: bool, const clock_real: bool = switch (timeout) { + .none => .{ null, false, false }, + .deadline => |timestamp| timeout: { + ts_buf = timestampToPosix(timestamp.raw.nanoseconds); + break :timeout .{ &ts_buf, true, timestamp.clock == .real }; + }, + .duration => |duration| timeout: { + ts_buf = timestampToPosix(duration.raw.nanoseconds); + break :timeout .{ &ts_buf, false, duration.clock == .real }; + }, + }; + switch (posix.errno(std.c._lwp_park( + if (clock_real) .REALTIME else .MONOTONIC, + .{ .ABSTIME = abstime }, + ts, + 0, + addr_hint, + null, + ))) { + .SUCCESS, .ALREADY, .INTR => return, + .TIMEDOUT => return error.Timeout, + .INVAL => unreachable, + .SRCH => unreachable, + else => unreachable, + } + }, + .illumos => @panic("TODO: illumos lwp_park"), + else => comptime unreachable, + } +} - pub fn isSet(rep: *const ResetEventPosix) bool { - if (builtin.single_threaded) return switch (rep.state) { - .unset => false, - .waiting => unreachable, - .is_set => true, - }; - return @atomicLoad(ResetEventFutex, &rep.state, .acquire) == .is_set; +const UnparkTid = switch (builtin.target.os.tag) { + // `NtAlertMultipleThreadByThreadId` is weird and wants 64-bit thread handles? + .windows => usize, + else => std.Thread.Id, +}; +/// `addr_hint` has no semantic effect, but may allow the OS to optimize this operation. +fn unpark(tids: []const UnparkTid, addr_hint: ?*const anyopaque) void { + comptime assert(use_parking_futex or use_parking_sleep); + switch (builtin.target.os.tag) { + .windows => { + // TODO: this condition is currently disabled because mingw-w64 does not contain this + // symbol. Once it's added, enable this check to use the new bulk API where possible. + if (false and (builtin.os.version_range.windows.isAtLeast(.win11_dt) orelse false)) { + _ = windows.ntdll.NtAlertMultipleThreadByThreadId(tids.ptr, @intCast(tids.len), null, null); + } else { + for (tids) |tid| { + _ = windows.ntdll.NtAlertThreadByThreadId(@intCast(tid)); + } + } + }, + .netbsd => { + switch (posix.errno(std.c._lwp_unpark_all(@ptrCast(tids.ptr), tids.len, addr_hint))) { + .SUCCESS => return, + // For errors, fall through to a loop over `tids`, though this is only expected to + // be possible for ENOMEM (and even that is questionable). + .SRCH => recoverableOsBugDetected(), + .FAULT => recoverableOsBugDetected(), + .INVAL => recoverableOsBugDetected(), + .NOMEM => {}, + else => recoverableOsBugDetected(), + } + for (tids) |tid| { + switch (posix.errno(std.c._lwp_unpark(@bitCast(tid), addr_hint))) { + .SUCCESS => {}, + .SRCH => recoverableOsBugDetected(), + else => recoverableOsBugDetected(), + } + } + }, + .illumos => @panic("TODO: illumos lwp_unpark"), + else => comptime unreachable, } +} - pub fn wait(rep: *ResetEventPosix, t: *Threaded) Io.Cancelable!void { - if (builtin.single_threaded) switch (rep.*) { - .unset => unreachable, // Deadlock, no other threads to wake us up. - .waiting => unreachable, // Invalid state. - .is_set => return, - }; - assert(std.c.pthread_mutex_lock(&rep.mutex) == .SUCCESS); - defer assert(std.c.pthread_mutex_unlock(&rep.mutex) == .SUCCESS); - sw: switch (rep.state) { - .unset => { - rep.state = .waiting; - continue :sw .waiting; - }, - .waiting => { - try t.checkCancel(); - assert(std.c.pthread_cond_wait(&rep.cond, &rep.mutex) == .SUCCESS); - continue :sw rep.state; - }, - .is_set => return, +pub const PipeError = error{ + SystemFdQuotaExceeded, + ProcessFdQuotaExceeded, +} || Io.UnexpectedError; + +pub fn pipe2(flags: posix.O) PipeError![2]posix.fd_t { + var fds: [2]posix.fd_t = undefined; + + if (@TypeOf(posix.system.pipe2) != void) { + switch (posix.errno(posix.system.pipe2(&fds, flags))) { + .SUCCESS => return fds, + .INVAL => |err| return errnoBug(err), // Invalid flags + .NFILE => return error.SystemFdQuotaExceeded, + .MFILE => return error.ProcessFdQuotaExceeded, + else => |err| return posix.unexpectedErrno(err), } } - pub fn waitUncancelable(rep: *ResetEventPosix) void { - if (builtin.single_threaded) switch (rep.*) { - .unset => unreachable, // Deadlock, no other threads to wake us up. - .waiting => unreachable, // Invalid state. - .is_set => return, - }; - assert(std.c.pthread_mutex_lock(&rep.mutex) == .SUCCESS); - defer assert(std.c.pthread_mutex_unlock(&rep.mutex) == .SUCCESS); - sw: switch (rep.state) { - .unset => { - rep.state = .waiting; - continue :sw .waiting; - }, - .waiting => { - assert(std.c.pthread_cond_wait(&rep.cond, &rep.mutex) == .SUCCESS); - continue :sw rep.state; - }, - .is_set => return, - } + switch (posix.errno(posix.system.pipe(&fds))) { + .SUCCESS => {}, + .NFILE => return error.SystemFdQuotaExceeded, + .MFILE => return error.ProcessFdQuotaExceeded, + else => |err| return posix.unexpectedErrno(err), + } + errdefer { + posix.close(fds[0]); + posix.close(fds[1]); } - pub fn set(rep: *ResetEventPosix) void { - if (builtin.single_threaded) { - rep.* = .is_set; - return; - } - if (@atomicRmw(ResetEventFutex, &rep.state, .Xchg, .is_set, .release) == .waiting) { - assert(std.c.pthread_cond_broadcast(&rep.cond) == .SUCCESS); + // https://github.com/ziglang/zig/issues/18882 + if (@as(u32, @bitCast(flags)) == 0) return fds; + + // CLOEXEC is special, it's a file descriptor flag and must be set using + // F.SETFD. + if (flags.CLOEXEC) for (fds) |fd| { + switch (posix.errno(posix.system.fcntl(fd, posix.F.SETFD, @as(u32, posix.FD_CLOEXEC)))) { + .SUCCESS => {}, + else => |err| return posix.unexpectedErrno(err), } - } + }; - pub fn reset(rep: *ResetEventPosix) void { - if (builtin.single_threaded) { - rep.* = .unset; - return; + const new_flags: u32 = f: { + var new_flags = flags; + new_flags.CLOEXEC = false; + break :f @bitCast(new_flags); + }; + + // Set every other flag affecting the file status using F.SETFL. + if (new_flags != 0) for (fds) |fd| { + switch (posix.errno(posix.system.fcntl(fd, posix.F.SETFL, new_flags))) { + .SUCCESS => {}, + .INVAL => |err| return errnoBug(err), + else => |err| return posix.unexpectedErrno(err), } - @atomicStore(ResetEventFutex, &rep.state, .unset, .monotonic); - } -}; + }; -fn closeSocketWindows(s: ws2_32.SOCKET) void { - const rc = ws2_32.closesocket(s); - if (is_debug) switch (rc) { - 0 => {}, - ws2_32.SOCKET_ERROR => switch (ws2_32.WSAGetLastError()) { - else => recoverableOsBugDetected(), + return fds; +} + +pub const DupError = error{ + ProcessFdQuotaExceeded, + SystemResources, +} || Io.UnexpectedError || Io.Cancelable; + +pub fn dup2(old_fd: posix.fd_t, new_fd: posix.fd_t) DupError!void { + const syscall: Syscall = try .start(); + while (true) switch (posix.errno(posix.system.dup2(old_fd, new_fd))) { + .SUCCESS => return syscall.finish(), + .BUSY, .INTR => { + try syscall.checkCancel(); + continue; }, - else => recoverableOsBugDetected(), + .INVAL => |err| return syscall.errnoBug(err), // invalid parameters + .BADF => |err| return syscall.errnoBug(err), // use after free + .MFILE => return syscall.fail(error.ProcessFdQuotaExceeded), + .NOMEM => return syscall.fail(error.SystemResources), + else => |err| return syscall.unexpectedErrno(err), }; } -const Wsa = struct { - status: Status = .uninitialized, - mutex: Io.Mutex = .init, - init_error: ?Wsa.InitError = null, - - const Status = enum { uninitialized, initialized, failure }; - - const InitError = error{ - ProcessFdQuotaExceeded, - NetworkDown, - VersionUnsupported, - BlockingOperationInProgress, - } || Io.UnexpectedError; -}; +pub const FchdirError = error{ + AccessDenied, + NotDir, + FileSystem, +} || Io.Cancelable || Io.UnexpectedError; -fn initializeWsa(t: *Threaded) error{NetworkDown}!void { - const t_io = io(t); - const wsa = &t.wsa; - wsa.mutex.lockUncancelable(t_io); - defer wsa.mutex.unlock(t_io); - switch (wsa.status) { - .uninitialized => { - var wsa_data: ws2_32.WSADATA = undefined; - const minor_version = 2; - const major_version = 2; - switch (ws2_32.WSAStartup((@as(windows.WORD, minor_version) << 8) | major_version, &wsa_data)) { - 0 => { - wsa.status = .initialized; - return; - }, - else => |err_int| switch (@as(ws2_32.WinsockError, @enumFromInt(@as(u16, @intCast(err_int))))) { - .SYSNOTREADY => wsa.init_error = error.NetworkDown, - .VERNOTSUPPORTED => wsa.init_error = error.VersionUnsupported, - .EINPROGRESS => wsa.init_error = error.BlockingOperationInProgress, - .EPROCLIM => wsa.init_error = error.ProcessFdQuotaExceeded, - else => |err| wsa.init_error = windows.unexpectedWSAError(err), - }, - } +pub fn fchdir(fd: posix.fd_t) FchdirError!void { + if (fd == posix.AT.FDCWD) return; + const syscall: Syscall = try .start(); + while (true) switch (posix.errno(posix.system.fchdir(fd))) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); + continue; }, - .initialized => return, - .failure => {}, - } - return error.NetworkDown; + .ACCES => return syscall.fail(error.AccessDenied), + .NOTDIR => return syscall.fail(error.NotDir), + .IO => return syscall.fail(error.FileSystem), + .BADF => |err| return syscall.errnoBug(err), + else => |err| return syscall.unexpectedErrno(err), + }; } -fn doNothingSignalHandler(_: posix.SIG) callconv(.c) void {} +pub const ChdirError = error{ + AccessDenied, + FileSystem, + SymLinkLoop, + NameTooLong, + FileNotFound, + SystemResources, + NotDir, + BadPathName, +} || Io.Cancelable || Io.UnexpectedError; -test { - _ = @import("Threaded/test.zig"); +pub fn chdir(dir_path: []const u8) ChdirError!void { + var path_buffer: [posix.PATH_MAX]u8 = undefined; + const dir_path_posix = try pathToPosix(dir_path, &path_buffer); + const syscall: Syscall = try .start(); + while (true) switch (posix.errno(posix.system.chdir(dir_path_posix))) { + .SUCCESS => return syscall.finish(), + .INTR => { + try syscall.checkCancel(); + continue; + }, + .ACCES => return syscall.fail(error.AccessDenied), + .IO => return syscall.fail(error.FileSystem), + .LOOP => return syscall.fail(error.SymLinkLoop), + .NAMETOOLONG => return syscall.fail(error.NameTooLong), + .NOENT => return syscall.fail(error.FileNotFound), + .NOMEM => return syscall.fail(error.SystemResources), + .NOTDIR => return syscall.fail(error.NotDir), + .ILSEQ => return syscall.fail(error.BadPathName), + .FAULT => |err| return syscall.errnoBug(err), + else => |err| return syscall.unexpectedErrno(err), + }; } diff --git a/lib/std/Io/Threaded/test.zig b/lib/std/Io/Threaded/test.zig index 16afae7b63af..34aa4a8c689d 100644 --- a/lib/std/Io/Threaded/test.zig +++ b/lib/std/Io/Threaded/test.zig @@ -1,3 +1,5 @@ +//! Tests belong here if they access internal state of std.Io.Threaded or +//! otherwise assume details of that particular implementation. const builtin = @import("builtin"); const std = @import("std"); @@ -6,7 +8,15 @@ const testing = std.testing; const assert = std.debug.assert; test "concurrent vs main prevents deadlock via oversubscription" { - var threaded: Io.Threaded = .init(std.testing.allocator); + if (true) { + // https://codeberg.org/ziglang/zig/issues/30141 + return error.SkipZigTest; + } + + var threaded: Io.Threaded = .init(std.testing.allocator, .{ + .argv0 = .empty, + .environ = .empty, + }); defer threaded.deinit(); const io = threaded.io(); @@ -34,7 +44,15 @@ fn get(io: Io, queue: *Io.Queue(u8)) void { } test "concurrent vs concurrent prevents deadlock via oversubscription" { - var threaded: Io.Threaded = .init(std.testing.allocator); + if (true) { + // https://codeberg.org/ziglang/zig/issues/30141 + return error.SkipZigTest; + } + + var threaded: Io.Threaded = .init(std.testing.allocator, .{ + .argv0 = .empty, + .environ = .empty, + }); defer threaded.deinit(); const io = threaded.io(); @@ -68,7 +86,10 @@ test "async/concurrent context and result alignment" { var buffer: [2048]u8 align(@alignOf(ByteArray512)) = undefined; var fba: std.heap.FixedBufferAllocator = .init(&buffer); - var threaded: std.Io.Threaded = .init(fba.allocator()); + var threaded: std.Io.Threaded = .init(fba.allocator(), .{ + .argv0 = .empty, + .environ = .empty, + }); defer threaded.deinit(); const io = threaded.io(); @@ -101,7 +122,10 @@ test "Group.async context alignment" { var buffer: [2048]u8 align(@alignOf(ByteArray512)) = undefined; var fba: std.heap.FixedBufferAllocator = .init(&buffer); - var threaded: std.Io.Threaded = .init(fba.allocator()); + var threaded: std.Io.Threaded = .init(fba.allocator(), .{ + .argv0 = .empty, + .environ = .empty, + }); defer threaded.deinit(); const io = threaded.io(); @@ -112,7 +136,7 @@ test "Group.async context alignment" { var group: std.Io.Group = .init; var result: ByteArray512 = undefined; group.async(io, concatByteArraysResultPtr, .{ a, b, &result }); - group.wait(io); + try group.await(io); try std.testing.expectEqualSlices(u8, &expected.x, &result.x); } @@ -121,7 +145,10 @@ fn returnArray() [32]u8 { } test "async with array return type" { - var threaded: std.Io.Threaded = .init(std.testing.allocator); + var threaded: std.Io.Threaded = .init(std.testing.allocator, .{ + .argv0 = .empty, + .environ = .empty, + }); defer threaded.deinit(); const io = threaded.io(); @@ -129,3 +156,51 @@ test "async with array return type" { const result = future.await(io); try std.testing.expectEqualSlices(u8, &@as([32]u8, @splat(5)), &result); } + +test "cancel blocked read from pipe" { + const global = struct { + fn readFromPipe(io: Io, pipe: Io.File) !void { + var buf: [1]u8 = undefined; + if (pipe.readStreaming(io, &.{&buf})) |_| { + return error.UnexpectedData; + } else |err| switch (err) { + error.Canceled => return, + else => |e| return e, + } + } + }; + + var threaded: std.Io.Threaded = .init(std.testing.allocator, .{ + .argv0 = .empty, + .environ = .empty, + }); + defer threaded.deinit(); + const io = threaded.io(); + + var read_end: Io.File = undefined; + var write_end: Io.File = undefined; + switch (builtin.target.os.tag) { + .wasi => return error.SkipZigTest, + .windows => try std.os.windows.CreatePipe(&read_end.handle, &write_end.handle, &.{ + .nLength = @sizeOf(std.os.windows.SECURITY_ATTRIBUTES), + .lpSecurityDescriptor = null, + .bInheritHandle = std.os.windows.FALSE, + }), + else => { + const pipe = try std.Io.Threaded.pipe2(.{}); + read_end = .{ .handle = pipe[0] }; + write_end = .{ .handle = pipe[1] }; + }, + } + defer { + read_end.close(io); + write_end.close(io); + } + + var future = io.concurrent(global.readFromPipe, .{ io, read_end }) catch |err| switch (err) { + error.ConcurrencyUnavailable => return error.SkipZigTest, + }; + defer _ = future.cancel(io) catch {}; + try io.sleep(.fromMilliseconds(10), .awake); + try future.cancel(io); +} diff --git a/lib/std/Io/Writer.zig b/lib/std/Io/Writer.zig index 1b80b5b4f72c..b7da83f3a0f1 100644 --- a/lib/std/Io/Writer.zig +++ b/lib/std/Io/Writer.zig @@ -1,7 +1,8 @@ +const Writer = @This(); + const builtin = @import("builtin"); const native_endian = builtin.target.cpu.arch.endian(); -const Writer = @This(); const std = @import("../std.zig"); const assert = std.debug.assert; const Limit = std.Io.Limit; @@ -960,7 +961,7 @@ pub fn sendFileAll(w: *Writer, file_reader: *File.Reader, limit: Limit) FileAllE const n = sendFile(w, file_reader, .limited(remaining)) catch |err| switch (err) { error.EndOfStream => break, error.Unimplemented => { - file_reader.mode = file_reader.mode.toReading(); + file_reader.mode = file_reader.mode.toSimple(); remaining -= try w.sendFileReadingAll(file_reader, .limited(remaining)); break; }, @@ -1211,10 +1212,6 @@ pub fn printValue( } const is_any = comptime std.mem.eql(u8, fmt, ANY); - if (!is_any and std.meta.hasMethod(T, "format") and fmt.len == 0) { - // after 0.15.0 is tagged, delete this compile error and its condition - @compileError("ambiguous format string; specify {f} to call format method, or {any} to skip it"); - } switch (@typeInfo(T)) { .float, .comptime_float => { @@ -1702,7 +1699,7 @@ pub fn printFloatHex(w: *Writer, value: anytype, case: std.fmt.Case, opt_precisi try w.writeAll("0x"); try w.writeByte(buf[0]); - const trimmed = std.mem.trimRight(u8, buf[1..], "0"); + const trimmed = std.mem.trimEnd(u8, buf[1..], "0"); if (opt_precision) |precision| { if (precision > 0) try w.writeAll("."); } else if (trimmed.len > 0) { @@ -1911,35 +1908,162 @@ pub fn writeSleb128(w: *Writer, value: anytype) Error!void { /// Write a single integer as LEB128 to the given writer. pub fn writeLeb128(w: *Writer, value: anytype) Error!void { - const value_info = @typeInfo(@TypeOf(value)).int; - try w.writeMultipleOf7Leb128(@as(@Int( - value_info.signedness, - @max(std.mem.alignForwardAnyAlign(u16, value_info.bits, 7), 7), - ), value)); -} + const T = @TypeOf(value); + const info = switch (@typeInfo(T)) { + .int => |info| info, + else => @compileError(@typeName(T) ++ " not supported"), + }; -fn writeMultipleOf7Leb128(w: *Writer, value: anytype) Error!void { - const value_info = @typeInfo(@TypeOf(value)).int; - const Byte = packed struct(u8) { bits: u7, more: bool }; - var bytes: [@divExact(value_info.bits, 7)]Byte = undefined; - var remaining = value; - for (&bytes, 1..) |*byte, len| { - const more = switch (value_info.signedness) { - .signed => remaining >> 6 != remaining >> (value_info.bits - 1), - .unsigned => remaining > std.math.maxInt(u7), + const BoundInt = @Int(info.signedness, 7); + if (info.bits <= 7 or (value >= std.math.minInt(BoundInt) and value <= std.math.maxInt(BoundInt))) { + const Bits = @Int(info.signedness, 8); + const byte = switch (info.signedness) { + .signed => @as(Bits, @intCast(value)) & 0x7F, + .unsigned => @as(Bits, @intCast(value)), }; - byte.* = .{ - .bits = @bitCast(@as( - @Int(value_info.signedness, 7), - @truncate(remaining), - )), - .more = more, + try w.writeByte(@bitCast(byte)); + return; + } + + const Byte = packed struct { bits: u7, more: bool }; + const Int = std.math.ByteAlignedInt(T); + + const max_bytes = @divFloor(info.bits - 1, 7) + 1; + + const sign_value = value >> (info.bits - 1); + var val: Int = value; + for (0..max_bytes) |_| { + const more = switch (info.signedness) { + .signed => val >> 6 != sign_value, + .unsigned => val > std.math.maxInt(u7), }; - if (value_info.bits > 7) remaining >>= 7; - if (!more) return w.writeAll(@ptrCast(bytes[0..len])); + + try w.writeByte(@bitCast(@as(Byte, .{ + .bits = @intCast(val & 0x7F), + .more = more, + }))); + + if (!more) return; + + val >>= 7; } else unreachable; } +test "serialize signed LEB128" { + // Small values + try testLeb128Encoding(i7, 9, "\x09"); + try testLeb128Encoding(i64, 125, "\xFD\x00"); + + try testLeb128Encoding(i7, -34, "\x5E"); + try testLeb128Encoding(i64, -3, "\x7D"); + + // Random values + try testLeb128Encoding(i16, 19373, "\xAD\x97\x01"); + try testLeb128Encoding(i32, 1628839242, "\xCA\xBA\xD8\x88\x06"); + try testLeb128Encoding(i64, 3789169920125966546, "\xD2\xB1\xD0\xD5\xF6\xBE\xF5\xCA\x34"); + try testLeb128Encoding(i128, 704622239050934257305893323522763588, "\xC4\xD6\x83\xC7\xE3\x91\x95\xC3\x96\x80\x8D\xA5\xF5\xDF\xA3\xDA\x87\x01"); + + try testLeb128Encoding(i16, -14558, "\xA2\x8E\x7F"); + try testLeb128Encoding(i32, -1702738165, "\x8B\x8E\x89\xD4\x79"); + try testLeb128Encoding(i64, -1709126996960612298, "\xB6\xE0\x87\xB1\xD3\xC1\xFD\xA3\x68"); + try testLeb128Encoding(i128, -113498719181566012704681230050325944039, "\x99\xD2\x80\xBC\xE6\x95\xBC\xC8\xDE\xB4\x9D\x81\x9F\xCA\xC6\xF8\x9C\xD5\x7E"); + + // {min,max} values + try testLeb128Encoding(i16, std.math.maxInt(i16), "\xFF\xFF\x01"); + try testLeb128Encoding(i32, std.math.maxInt(i32), "\xFF\xFF\xFF\xFF\x07"); + try testLeb128Encoding(i64, std.math.maxInt(i64), "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00"); + try testLeb128Encoding(i128, std.math.maxInt(i128), "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"); + + try testLeb128Encoding(i16, std.math.minInt(i16), "\x80\x80\x7E"); + try testLeb128Encoding(i32, std.math.minInt(i32), "\x80\x80\x80\x80\x78"); + try testLeb128Encoding(i64, std.math.minInt(i64), "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x7F"); + try testLeb128Encoding(i128, std.math.minInt(i128), "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x7E"); + + // Specific cases + try testLeb128Encoding(i0, 0, "\x00"); + try testLeb128Encoding(i8, 0, "\x00"); + + try testLeb128Encoding(i2, -1, "\x7F"); + try testLeb128Encoding(i8, -1, "\x7F"); + + try testLeb128Encoding(i2, 1, "\x01"); + try testLeb128Encoding(i8, 1, "\x01"); + + // Encode byte boundaries + try testLeb128Encoding(i7, std.math.maxInt(i7), "\x3F"); + try testLeb128Encoding(i8, std.math.maxInt(i7) + 1, "\xC0\x00"); + try testLeb128Encoding(i14, std.math.maxInt(i14), "\xFF\x3F"); + try testLeb128Encoding(i15, std.math.maxInt(i14) + 1, "\x80\xC0\x00"); + try testLeb128Encoding(i49, std.math.maxInt(i49), "\xFF\xFF\xFF\xFF\xFF\xFF\x3F"); + try testLeb128Encoding(i50, std.math.maxInt(i49) + 1, "\x80\x80\x80\x80\x80\x80\xC0\x00"); + try testLeb128Encoding(i56, std.math.maxInt(i56), "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x3F"); + try testLeb128Encoding(i57, std.math.maxInt(i56) + 1, "\x80\x80\x80\x80\x80\x80\x80\xC0\x00"); + try testLeb128Encoding(i63, std.math.maxInt(i63), "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x3F"); + try testLeb128Encoding(i64, std.math.maxInt(i63) + 1, "\x80\x80\x80\x80\x80\x80\x80\x80\xC0\x00"); + + try testLeb128Encoding(i7, std.math.minInt(i7), "\x40"); + try testLeb128Encoding(i8, std.math.minInt(i7) - 1, "\xBF\x7F"); + try testLeb128Encoding(i14, std.math.minInt(i14), "\x80\x40"); + try testLeb128Encoding(i15, std.math.minInt(i14) - 1, "\xFF\xBF\x7F"); + try testLeb128Encoding(i49, std.math.minInt(i49), "\x80\x80\x80\x80\x80\x80\x40"); + try testLeb128Encoding(i50, std.math.minInt(i49) - 1, "\xFF\xFF\xFF\xFF\xFF\xFF\xBF\x7F"); + try testLeb128Encoding(i56, std.math.minInt(i56), "\x80\x80\x80\x80\x80\x80\x80\x40"); + try testLeb128Encoding(i57, std.math.minInt(i56) - 1, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xBF\x7F"); + try testLeb128Encoding(i63, std.math.minInt(i63), "\x80\x80\x80\x80\x80\x80\x80\x80\x40"); + try testLeb128Encoding(i64, std.math.minInt(i63) - 1, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xBF\x7F"); +} + +test "serialize unsigned LEB128" { + // Small values + try testLeb128Encoding(u7, 12, "\x0C"); + try testLeb128Encoding(u64, 201, "\xC9\x01"); + + // Random values + try testLeb128Encoding(u8, 254, "\xFE\x01"); + try testLeb128Encoding(u16, 30241, "\xA1\xEC\x01"); + try testLeb128Encoding(u32, 2173531193, "\xB9\xE8\xB5\x8C\x08"); + try testLeb128Encoding(u64, 18321125691115744902, "\x86\xDD\xF2\x81\xF2\xD7\xED\xA0\xFE\x01"); + try testLeb128Encoding(u128, 122619209508942982841456325819614676193, "\xE1\x89\xF3\xD9\xE3\xAD\xEC\xF4\x98\x95\xF8\xBB\xD7\xB8\xF2\xCC\xBF\xB8\x01"); + + // Max values + try testLeb128Encoding(u8, std.math.maxInt(u8), "\xFF\x01"); + try testLeb128Encoding(u16, std.math.maxInt(u16), "\xFF\xFF\x03"); + try testLeb128Encoding(u32, std.math.maxInt(u32), "\xFF\xFF\xFF\xFF\x0F"); + try testLeb128Encoding(u64, std.math.maxInt(u64), "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"); + try testLeb128Encoding(u128, std.math.maxInt(u128), "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x03"); + + // Specific cases + try testLeb128Encoding(u0, 0, "\x00"); + try testLeb128Encoding(u1, 0, "\x00"); + try testLeb128Encoding(u8, 0, "\x00"); + + try testLeb128Encoding(u1, 1, "\x01"); + try testLeb128Encoding(u8, 1, "\x01"); + + // Encode byte boundaries + try testLeb128Encoding(u7, std.math.maxInt(u7), "\x7F"); + try testLeb128Encoding(u8, std.math.maxInt(u7) + 1, "\x80\x01"); + try testLeb128Encoding(u14, std.math.maxInt(u14), "\xFF\x7F"); + try testLeb128Encoding(u15, std.math.maxInt(u14) + 1, "\x80\x80\x01"); + try testLeb128Encoding(u49, std.math.maxInt(u49), "\xFF\xFF\xFF\xFF\xFF\xFF\x7F"); + try testLeb128Encoding(u50, std.math.maxInt(u49) + 1, "\x80\x80\x80\x80\x80\x80\x80\x01"); + try testLeb128Encoding(u56, std.math.maxInt(u56), "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F"); + try testLeb128Encoding(u57, std.math.maxInt(u56) + 1, "\x80\x80\x80\x80\x80\x80\x80\x80\x01"); + try testLeb128Encoding(u63, std.math.maxInt(u63), "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F"); + try testLeb128Encoding(u64, std.math.maxInt(u63) + 1, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01"); +} + +fn testLeb128Encoding(comptime T: type, value: T, encoding: []const u8) !void { + const info = @typeInfo(T).int; + const max_bytes = @divFloor(info.bits -| 1, 7) + 1; + var bytes: [max_bytes]u8 = undefined; + + var fw: Writer = .fixed(&bytes); + try writeLeb128(&fw, value); + + try std.testing.expectEqualSlices(u8, encoding, fw.buffered()); +} + test "printValue max_depth" { const Vec2 = struct { const SelfType = @This(); @@ -2838,14 +2962,14 @@ test "discarding sendFile" { var tmp_dir = testing.tmpDir(.{}); defer tmp_dir.cleanup(); - const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); - defer file.close(); + const file = try tmp_dir.dir.createFile(io, "input.txt", .{ .read = true }); + defer file.close(io); var r_buffer: [256]u8 = undefined; - var file_writer: std.fs.File.Writer = .init(file, &r_buffer); + var file_writer: File.Writer = .init(file, io, &r_buffer); try file_writer.interface.writeByte('h'); try file_writer.interface.flush(); - var file_reader = file_writer.moveToReader(io); + var file_reader = file_writer.moveToReader(); try file_reader.seekTo(0); var w_buffer: [256]u8 = undefined; @@ -2860,14 +2984,14 @@ test "allocating sendFile" { var tmp_dir = testing.tmpDir(.{}); defer tmp_dir.cleanup(); - const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); - defer file.close(); + const file = try tmp_dir.dir.createFile(io, "input.txt", .{ .read = true }); + defer file.close(io); var r_buffer: [2]u8 = undefined; - var file_writer: std.fs.File.Writer = .init(file, &r_buffer); + var file_writer: File.Writer = .init(file, io, &r_buffer); try file_writer.interface.writeAll("abcd"); try file_writer.interface.flush(); - var file_reader = file_writer.moveToReader(io); + var file_reader = file_writer.moveToReader(); try file_reader.seekTo(0); try file_reader.interface.fill(2); @@ -2884,14 +3008,14 @@ test sendFileReading { var tmp_dir = testing.tmpDir(.{}); defer tmp_dir.cleanup(); - const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); - defer file.close(); + const file = try tmp_dir.dir.createFile(io, "input.txt", .{ .read = true }); + defer file.close(io); var r_buffer: [2]u8 = undefined; - var file_writer: std.fs.File.Writer = .init(file, &r_buffer); + var file_writer: File.Writer = .init(file, io, &r_buffer); try file_writer.interface.writeAll("abcd"); try file_writer.interface.flush(); - var file_reader = file_writer.moveToReader(io); + var file_reader = file_writer.moveToReader(); try file_reader.seekTo(0); try file_reader.interface.fill(2); diff --git a/lib/std/Io/net.zig b/lib/std/Io/net.zig index ee1e93ced21d..76a581180d10 100644 --- a/lib/std/Io/net.zig +++ b/lib/std/Io/net.zig @@ -954,6 +954,16 @@ pub const SendFlags = packed struct(u8) { _: u3 = 0, }; +pub const ShutdownHow = enum { recv, send, both }; + +pub const ShutdownError = error{ + ConnectionAborted, + ConnectionResetByPeer, + NetworkDown, + SocketUnconnected, + SystemResources, +} || Io.UnexpectedError || Io.Cancelable; + pub const Interface = struct { /// Value 0 indicates `none`. index: u32, @@ -1043,7 +1053,11 @@ pub const Socket = struct { /// Leaves `address` in a valid state. pub fn close(s: *const Socket, io: Io) void { - io.vtable.netClose(io.userdata, s.handle); + io.vtable.netClose(io.userdata, (&s.handle)[0..1]); + } + + pub fn closeMany(io: Io, sockets: []const Socket) void { + io.vtable.netClose(io.userdata, sockets); } pub const SendError = error{ @@ -1090,7 +1104,8 @@ pub const Socket = struct { } pub fn sendMany(s: *const Socket, io: Io, messages: []OutgoingMessage, flags: SendFlags) SendError!void { - return io.vtable.netSend(io.userdata, s.handle, messages, flags); + const err, const n = io.vtable.netSend(io.userdata, s.handle, messages, flags); + if (n != messages.len) return err.?; } pub const ReceiveError = error{ @@ -1183,7 +1198,11 @@ pub const Stream = struct { const max_iovecs_len = 8; pub fn close(s: *const Stream, io: Io) void { - io.vtable.netClose(io.userdata, s.socket.handle); + io.vtable.netClose(io.userdata, (&s.socket.handle)[0..1]); + } + + pub fn shutdown(s: *const Stream, io: Io, how: ShutdownHow) ShutdownError!void { + return io.vtable.netShutdown(io.userdata, s.socket.handle, how); } pub const Reader = struct { @@ -1255,6 +1274,7 @@ pub const Stream = struct { interface: Io.Writer, stream: Stream, err: ?Error = null, + write_file_err: ?WriteFileError = null, pub const Error = error{ /// Another TCP Fast Open is already in progress. @@ -1284,12 +1304,19 @@ pub const Stream = struct { SocketNotBound, } || Io.UnexpectedError || Io.Cancelable; + pub const WriteFileError = error{ + NetworkDown, + } || Io.Cancelable || Io.UnexpectedError; + pub fn init(stream: Stream, io: Io, buffer: []u8) Writer { return .{ .io = io, .stream = stream, .interface = .{ - .vtable = &.{ .drain = drain }, + .vtable = &.{ + .drain = drain, + .sendFile = sendFile, + }, .buffer = buffer, }, }; @@ -1306,6 +1333,13 @@ pub const Stream = struct { }; return io_w.consume(n); } + + fn sendFile(io_w: *Io.Writer, file_reader: *Io.File.Reader, limit: Io.Limit) Io.Writer.FileError!usize { + _ = io_w; + _ = file_reader; + _ = limit; + return error.Unimplemented; // TODO + } }; pub fn reader(stream: Stream, io: Io, buffer: []u8) Reader { @@ -1333,6 +1367,10 @@ pub const Server = struct { /// Not enough free memory. This often means that the memory allocation is limited /// by the socket buffer limits, not by the system memory. SystemResources, + /// Either `listen` was never called, or `shutdown` was called (possibly while + /// this call was blocking). This allows `shutdown` to be used as a concurrent + /// cancellation mechanism. + SocketNotListening, /// The network subsystem has failed. NetworkDown, /// No connection is already queued and ready to be accepted, and diff --git a/lib/std/Io/net/HostName.zig b/lib/std/Io/net/HostName.zig index e2638abfaa9f..66b5b648a665 100644 --- a/lib/std/Io/net/HostName.zig +++ b/lib/std/Io/net/HostName.zig @@ -24,15 +24,82 @@ pub const ValidateError = error{ InvalidHostName, }; +/// Validates a hostname according to [RFC 1123](https://www.rfc-editor.org/rfc/rfc1123) pub fn validate(bytes: []const u8) ValidateError!void { - if (bytes.len > max_len) return error.NameTooLong; - if (!std.unicode.utf8ValidateSlice(bytes)) return error.InvalidHostName; - for (bytes) |byte| { - if (!std.ascii.isAscii(byte) or byte == '.' or byte == '-' or std.ascii.isAlphanumeric(byte)) { - continue; + if (bytes.len == 0) return error.InvalidHostName; + if (bytes[0] == '.') return error.InvalidHostName; + + // Ignore trailing dot (FQDN). It doesn't count toward our length. + const end = if (bytes[bytes.len - 1] == '.') end: { + if (bytes.len == 1) return error.InvalidHostName; + break :end bytes.len - 1; + } else bytes.len; + + // The accepted maximum length of a hostname, including labels and dots. + if (end > max_len) return error.NameTooLong; + + // Hostnames are divided into dot-separated "labels", which: + // + // - Start with a letter or digit + // - Can contain letters, digits, or hyphens + // - Must end with a letter or digit + // - Have a minimum of 1 character and a maximum of 63 + var label_start: usize = 0; + var label_len: usize = 0; + for (bytes[0..end], 0..) |c, i| { + switch (c) { + '.' => { + if (label_len == 0 or label_len > 63) return error.InvalidHostName; + if (!std.ascii.isAlphanumeric(bytes[label_start])) return error.InvalidHostName; + if (!std.ascii.isAlphanumeric(bytes[i - 1])) return error.InvalidHostName; + + label_start = i + 1; + label_len = 0; + }, + '-' => { + label_len += 1; + }, + else => { + if (!std.ascii.isAlphanumeric(c)) return error.InvalidHostName; + label_len += 1; + }, } - return error.InvalidHostName; } + + // Validate the final label + if (label_len == 0 or label_len > 63) return error.InvalidHostName; + if (!std.ascii.isAlphanumeric(bytes[label_start])) return error.InvalidHostName; + if (!std.ascii.isAlphanumeric(bytes[end - 1])) return error.InvalidHostName; +} + +test validate { + // Valid hostnames + try validate("example"); + try validate("example.com"); + try validate("www.example.com"); + try validate("sub.domain.example.com"); + try validate("example.com."); + try validate("host-name.example.com."); + try validate("123.example.com."); + try validate("a-b.com"); + try validate("a.b.c.d.e.f.g"); + try validate("127.0.0.1"); // Also a valid hostname + try validate("a" ** 63 ++ ".com"); // Label exactly 63 chars (valid) + try validate("a." ** 127 ++ "a"); // Total length 255 (valid) + + // Invalid hostnames + try std.testing.expectError(error.InvalidHostName, validate("")); + try std.testing.expectError(error.InvalidHostName, validate(".example.com")); + try std.testing.expectError(error.InvalidHostName, validate("example.com..")); + try std.testing.expectError(error.InvalidHostName, validate("host..domain")); + try std.testing.expectError(error.InvalidHostName, validate("-hostname")); + try std.testing.expectError(error.InvalidHostName, validate("hostname-")); + try std.testing.expectError(error.InvalidHostName, validate("a.-.b")); + try std.testing.expectError(error.InvalidHostName, validate("host_name.com")); + try std.testing.expectError(error.InvalidHostName, validate(".")); + try std.testing.expectError(error.InvalidHostName, validate("..")); + try std.testing.expectError(error.InvalidHostName, validate("a" ** 64 ++ ".com")); // Label length 64 (too long) + try std.testing.expectError(error.NameTooLong, validate("a." ** 127 ++ "ab")); // Total length 256 (too long) } pub fn init(bytes: []const u8) ValidateError!HostName { @@ -75,6 +142,7 @@ pub const LookupError = error{ InvalidDnsAAAARecord, InvalidDnsCnameRecord, NameServerFailure, + NoAddressReturned, /// Failed to open or read "/etc/hosts" or "/etc/resolv.conf". DetectingNetworkConfigurationFailed, } || Io.Clock.Error || IpAddress.BindError || Io.Cancelable; @@ -82,19 +150,22 @@ pub const LookupError = error{ pub const LookupResult = union(enum) { address: IpAddress, canonical_name: HostName, - end: LookupError!void, }; -/// Adds any number of `IpAddress` into resolved, exactly one canonical_name, -/// and then always finishes by adding one `LookupResult.end` entry. +/// Adds any number of `LookupResult.address` into `resolved`, and exactly one +/// `LookupResult.canonical_name`. /// /// Guaranteed not to block if provided queue has capacity at least 16. +/// +/// Closes `resolved` before return, even on error. +/// +/// Asserts `resolved` is not closed until this call returns. pub fn lookup( host_name: HostName, io: Io, resolved: *Io.Queue(LookupResult), options: LookupOptions, -) void { +) LookupError!void { return io.vtable.netLookup(io.userdata, host_name, resolved, options); } @@ -211,92 +282,104 @@ pub fn connect( port: u16, options: IpAddress.ConnectOptions, ) ConnectError!Stream { - var connect_many_buffer: [32]ConnectManyResult = undefined; - var connect_many_queue: Io.Queue(ConnectManyResult) = .init(&connect_many_buffer); + var connect_many_buffer: [32]IpAddress.ConnectError!Stream = undefined; + var connect_many_queue: Io.Queue(IpAddress.ConnectError!Stream) = .init(&connect_many_buffer); var connect_many = io.async(connectMany, .{ host_name, io, port, &connect_many_queue, options }); - var saw_end = false; defer { - connect_many.cancel(io); - if (!saw_end) while (true) switch (connect_many_queue.getOneUncancelable(io)) { - .connection => |loser| if (loser) |s| s.close(io) else |_| continue, - .end => break, - }; + connect_many.cancel(io) catch {}; + while (connect_many_queue.getOneUncancelable(io)) |loser| { + if (loser) |s| s.close(io) else |_| {} + } else |err| switch (err) { + error.Closed => {}, + } } - var aggregate_error: ConnectError = error.UnknownHostName; + var ip_connect_error: ?IpAddress.ConnectError = null; + + while (connect_many_queue.getOne(io)) |result| { + if (result) |stream| { + return stream; + } else |err| switch (err) { + error.Canceled => unreachable, - while (connect_many_queue.getOne(io)) |result| switch (result) { - .connection => |connection| if (connection) |stream| return stream else |err| switch (err) { error.SystemResources, error.OptionUnsupported, error.ProcessFdQuotaExceeded, error.SystemFdQuotaExceeded, - error.Canceled, => |e| return e, error.WouldBlock => return error.Unexpected, - else => |e| aggregate_error = e, - }, - .end => |end| { - saw_end = true; - try end; - return aggregate_error; - }, + else => |e| ip_connect_error = e, + } } else |err| switch (err) { error.Canceled => |e| return e, + error.Closed => { + // There was no successful connection attempt. If there was a lookup error, return that. + try connect_many.await(io); + // Otherwise, return the error from a failed IP connection attempt. + return ip_connect_error orelse + return error.UnknownHostName; + }, } } -pub const ConnectManyResult = union(enum) { - connection: IpAddress.ConnectError!Stream, - end: ConnectError!void, -}; - /// Asynchronously establishes a connection to all IP addresses associated with /// a host name, adding them to a results queue upon completion. +/// +/// `error.Canceled` will never be added to the queue, but other errors may be. +/// +/// Closes `results` before return, even on error. +/// +/// Asserts `results` is not closed until this call returns. pub fn connectMany( host_name: HostName, io: Io, port: u16, - results: *Io.Queue(ConnectManyResult), + results: *Io.Queue(IpAddress.ConnectError!Stream), options: IpAddress.ConnectOptions, -) void { +) LookupError!void { + defer results.close(io); + var canonical_name_buffer: [max_len]u8 = undefined; var lookup_buffer: [32]HostName.LookupResult = undefined; var lookup_queue: Io.Queue(LookupResult) = .init(&lookup_buffer); - var group: Io.Group = .init; - defer group.cancel(io); - - group.async(io, lookup, .{ host_name, io, &lookup_queue, .{ + var lookup_future = io.async(lookup, .{ host_name, io, &lookup_queue, .{ .port = port, .canonical_name_buffer = &canonical_name_buffer, } }); + defer lookup_future.cancel(io) catch {}; + + var group: Io.Group = .init; + defer group.cancel(io); while (lookup_queue.getOne(io)) |dns_result| switch (dns_result) { .address => |address| group.async(io, enqueueConnection, .{ address, io, results, options }), .canonical_name => continue, - .end => |lookup_result| { - group.wait(io); - results.putOneUncancelable(io, .{ .end = lookup_result }); - return; - }, } else |err| switch (err) { - error.Canceled => |e| { - group.cancel(io); - results.putOneUncancelable(io, .{ .end = e }); + error.Canceled => |e| return e, + error.Closed => { + try group.await(io); + return lookup_future.await(io); }, } } - fn enqueueConnection( address: IpAddress, io: Io, - queue: *Io.Queue(ConnectManyResult), + queue: *Io.Queue(IpAddress.ConnectError!Stream), options: IpAddress.ConnectOptions, -) void { - queue.putOneUncancelable(io, .{ .connection = address.connect(io, options) }); +) Io.Cancelable!void { + const result = address.connect(io, options) catch |err| switch (err) { + error.Canceled => |e| return e, + else => |e| e, // other errors go in the result queue + }; + errdefer if (result) |s| s.close(io) else |_| {}; + queue.putOne(io, result) catch |err| switch (err) { + error.Canceled => |e| return e, + error.Closed => unreachable, // `queue` must not be closed + }; } pub const ResolvConf = struct { @@ -324,7 +407,7 @@ pub const ResolvConf = struct { .attempts = 2, }; - const file = Io.File.openAbsolute(io, "/etc/resolv.conf", .{}) catch |err| switch (err) { + const file = Io.Dir.openFileAbsolute(io, "/etc/resolv.conf", .{}) catch |err| switch (err) { error.FileNotFound, error.NotDir, error.AccessDenied, diff --git a/lib/std/Io/net/test.zig b/lib/std/Io/net/test.zig index 2a7a151b5dbb..7904bc464117 100644 --- a/lib/std/Io/net/test.zig +++ b/lib/std/Io/net/test.zig @@ -129,7 +129,7 @@ test "resolve DNS" { var results_buffer: [32]net.HostName.LookupResult = undefined; var results: Io.Queue(net.HostName.LookupResult) = .init(&results_buffer); - net.HostName.lookup(try .init("localhost"), io, &results, .{ + try net.HostName.lookup(try .init("localhost"), io, &results, .{ .port = 80, .canonical_name_buffer = &canonical_name_buffer, }); @@ -142,11 +142,10 @@ test "resolve DNS" { addresses_found += 1; }, .canonical_name => |canonical_name| try testing.expectEqualStrings("localhost", canonical_name.bytes), - .end => |end| { - try end; - break; - }, - } else |err| return err; + } else |err| switch (err) { + error.Closed => {}, + error.Canceled => |e| return e, + } try testing.expect(addresses_found != 0); } @@ -161,20 +160,19 @@ test "resolve DNS" { net.HostName.lookup(try .init("example.com"), io, &results, .{ .port = 80, .canonical_name_buffer = &canonical_name_buffer, - }); + }) catch |err| switch (err) { + error.UnknownHostName => return error.SkipZigTest, + error.NameServerFailure => return error.SkipZigTest, + else => |e| return e, + }; while (results.getOne(io)) |result| switch (result) { .address => {}, .canonical_name => {}, - .end => |end| { - end catch |err| switch (err) { - error.UnknownHostName => return error.SkipZigTest, - error.NameServerFailure => return error.SkipZigTest, - else => return err, - }; - break; - }, - } else |err| return err; + } else |err| switch (err) { + error.Closed => {}, + error.Canceled => |e| return e, + } } } @@ -234,8 +232,10 @@ test "listen on an in use port" { fn testClientToHost(allocator: mem.Allocator, name: []const u8, port: u16) anyerror!void { if (builtin.os.tag == .wasi) return error.SkipZigTest; + const io = testing.io; + const connection = try net.tcpConnectToHost(allocator, name, port); - defer connection.close(); + defer connection.close(io); var buf: [100]u8 = undefined; const len = try connection.read(&buf); @@ -246,8 +246,10 @@ fn testClientToHost(allocator: mem.Allocator, name: []const u8, port: u16) anyer fn testClient(addr: net.IpAddress) anyerror!void { if (builtin.os.tag == .wasi) return error.SkipZigTest; + const io = testing.io; + const socket_file = try net.tcpConnectToAddress(addr); - defer socket_file.close(); + defer socket_file.close(io); var buf: [100]u8 = undefined; const len = try socket_file.read(&buf); @@ -269,14 +271,15 @@ test "listen on a unix socket, send bytes, receive bytes" { if (builtin.single_threaded) return error.SkipZigTest; if (!net.has_unix_sockets) return error.SkipZigTest; if (builtin.os.tag == .windows) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/25983 + if (builtin.cpu.arch == .mipsel) return error.SkipZigTest; // TODO const io = testing.io; - const socket_path = try generateFileName("socket.unix"); + const socket_path = try generateFileName(io, "socket.unix"); defer testing.allocator.free(socket_path); const socket_addr = try net.UnixAddress.init(socket_path); - defer std.fs.cwd().deleteFile(socket_path) catch {}; + defer Io.Dir.cwd().deleteFile(io, socket_path) catch {}; var server = try socket_addr.listen(io, .{}); defer server.socket.close(io); @@ -305,13 +308,13 @@ test "listen on a unix socket, send bytes, receive bytes" { try testing.expectEqualSlices(u8, "Hello world!", buf[0..n]); } -fn generateFileName(base_name: []const u8) ![]const u8 { +fn generateFileName(io: Io, base_name: []const u8) ![]const u8 { const random_bytes_count = 12; - const sub_path_len = comptime std.fs.base64_encoder.calcSize(random_bytes_count); + const sub_path_len = comptime std.base64.url_safe.Encoder.calcSize(random_bytes_count); var random_bytes: [12]u8 = undefined; - std.crypto.random.bytes(&random_bytes); + io.random(&random_bytes); var sub_path: [sub_path_len]u8 = undefined; - _ = std.fs.base64_encoder.encode(&sub_path, &random_bytes); + _ = std.base64.url_safe.Encoder.encode(&sub_path, &random_bytes); return std.fmt.allocPrint(testing.allocator, "{s}-{s}", .{ sub_path[0..], base_name }); } @@ -332,7 +335,7 @@ test "non-blocking tcp server" { try testing.expectError(error.WouldBlock, accept_err); const socket_file = try net.tcpConnectToAddress(server.socket.address); - defer socket_file.close(); + defer socket_file.close(io); var stream = try server.accept(io); defer stream.close(io); @@ -343,6 +346,8 @@ test "non-blocking tcp server" { const len = try socket_file.read(&buf); const msg = buf[0..len]; try testing.expect(mem.eql(u8, msg, "hello from server\n")); + + try stream.shutdown(io, .both); } test "decompress compressed DNS name" { diff --git a/lib/std/Io/test.zig b/lib/std/Io/test.zig index 0ac6c333c9fb..17b86af23446 100644 --- a/lib/std/Io/test.zig +++ b/lib/std/Io/test.zig @@ -3,16 +3,17 @@ const native_endian = builtin.cpu.arch.endian(); const std = @import("std"); const Io = std.Io; -const testing = std.testing; -const expect = std.testing.expect; -const expectEqual = std.testing.expectEqual; -const expectError = std.testing.expectError; const DefaultPrng = std.Random.DefaultPrng; const mem = std.mem; const fs = std.fs; -const File = std.fs.File; +const File = std.Io.File; const assert = std.debug.assert; +const testing = std.testing; +const expect = std.testing.expect; +const expectEqual = std.testing.expectEqual; +const expectError = std.testing.expectError; +const expectEqualStrings = std.testing.expectEqualStrings; const tmpDir = std.testing.tmpDir; test "write a file, read it, then delete it" { @@ -27,10 +28,10 @@ test "write a file, read it, then delete it" { random.bytes(data[0..]); const tmp_file_name = "temp_test_file.txt"; { - var file = try tmp.dir.createFile(tmp_file_name, .{}); - defer file.close(); + var file = try tmp.dir.createFile(io, tmp_file_name, .{}); + defer file.close(io); - var file_writer = file.writer(&.{}); + var file_writer = file.writer(io, &.{}); const st = &file_writer.interface; try st.print("begin", .{}); try st.writeAll(&data); @@ -40,14 +41,14 @@ test "write a file, read it, then delete it" { { // Make sure the exclusive flag is honored. - try expectError(File.OpenError.PathAlreadyExists, tmp.dir.createFile(tmp_file_name, .{ .exclusive = true })); + try expectError(File.OpenError.PathAlreadyExists, tmp.dir.createFile(io, tmp_file_name, .{ .exclusive = true })); } { - var file = try tmp.dir.openFile(tmp_file_name, .{}); - defer file.close(); + var file = try tmp.dir.openFile(io, tmp_file_name, .{}); + defer file.close(io); - const file_size = try file.getEndPos(); + const file_size = try file.length(io); const expected_file_size: u64 = "begin".len + data.len + "end".len; try expectEqual(expected_file_size, file_size); @@ -60,72 +61,127 @@ test "write a file, read it, then delete it" { try expect(mem.eql(u8, contents["begin".len .. contents.len - "end".len], &data)); try expect(mem.eql(u8, contents[contents.len - "end".len ..], "end")); } - try tmp.dir.deleteFile(tmp_file_name); + try tmp.dir.deleteFile(io, tmp_file_name); } -test "File seek ops" { +test "File.Writer.seekTo" { var tmp = tmpDir(.{}); defer tmp.cleanup(); + const io = testing.io; + + var data: [8192]u8 = undefined; + @memset(&data, 0x55); + const tmp_file_name = "temp_test_file.txt"; - var file = try tmp.dir.createFile(tmp_file_name, .{}); - defer file.close(); - - try file.writeAll(&([_]u8{0x55} ** 8192)); - - // Seek to the end - try file.seekFromEnd(0); - try expect((try file.getPos()) == try file.getEndPos()); - // Negative delta - try file.seekBy(-4096); - try expect((try file.getPos()) == 4096); - // Positive delta - try file.seekBy(10); - try expect((try file.getPos()) == 4106); - // Absolute position - try file.seekTo(1234); - try expect((try file.getPos()) == 1234); + var file = try tmp.dir.createFile(io, tmp_file_name, .{ .read = true }); + defer file.close(io); + + var fw = file.writerStreaming(io, &.{}); + + try fw.interface.writeAll(&data); + try expect(fw.logicalPos() == try file.length(io)); + try fw.seekTo(1234); + try expect(fw.logicalPos() == 1234); } -test "setEndPos" { +test "File.setLength" { + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); const tmp_file_name = "temp_test_file.txt"; - var file = try tmp.dir.createFile(tmp_file_name, .{}); - defer file.close(); + var file = try tmp.dir.createFile(io, tmp_file_name, .{ .read = true }); + defer file.close(io); + + var fw = file.writerStreaming(io, &.{}); // Verify that the file size changes and the file offset is not moved - try expect((try file.getEndPos()) == 0); - try expect((try file.getPos()) == 0); - try file.setEndPos(8192); - try expect((try file.getEndPos()) == 8192); - try expect((try file.getPos()) == 0); - try file.seekTo(100); - try file.setEndPos(4096); - try expect((try file.getEndPos()) == 4096); - try expect((try file.getPos()) == 100); - try file.setEndPos(0); - try expect((try file.getEndPos()) == 0); - try expect((try file.getPos()) == 100); + try expect((try file.length(io)) == 0); + try expect(fw.logicalPos() == 0); + try file.setLength(io, 8192); + try expect((try file.length(io)) == 8192); + try expect(fw.logicalPos() == 0); + try fw.seekTo(100); + try file.setLength(io, 4096); + try expect((try file.length(io)) == 4096); + try expect(fw.logicalPos() == 100); + try file.setLength(io, 0); + try expect((try file.length(io)) == 0); + try expect(fw.logicalPos() == 100); +} + +test "legacy setLength" { + // https://github.com/ziglang/zig/issues/20747 (open fd does not have write permission) + if (builtin.os.tag == .wasi and builtin.link_libc) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64() and (builtin.abi == .gnuabin32 or builtin.abi == .muslabin32)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/23806 + + const io = testing.io; + + var tmp = tmpDir(.{}); + defer tmp.cleanup(); + + const file_name = "afile.txt"; + try tmp.dir.writeFile(io, .{ .sub_path = file_name, .data = "ninebytes" }); + const f = try tmp.dir.openFile(io, file_name, .{ .mode = .read_write }); + defer f.close(io); + + const initial_size = try f.length(io); + var buffer: [32]u8 = undefined; + var reader = f.reader(io, &.{}); + + { + try f.setLength(io, initial_size); + try expectEqual(initial_size, try f.length(io)); + try reader.seekTo(0); + try expectEqual(initial_size, try reader.interface.readSliceShort(&buffer)); + try expectEqualStrings("ninebytes", buffer[0..@intCast(initial_size)]); + } + + { + const larger = initial_size + 4; + try f.setLength(io, larger); + try expectEqual(larger, try f.length(io)); + try reader.seekTo(0); + try expectEqual(larger, try reader.interface.readSliceShort(&buffer)); + try expectEqualStrings("ninebytes\x00\x00\x00\x00", buffer[0..@intCast(larger)]); + } + + { + const smaller = initial_size - 5; + try f.setLength(io, smaller); + try expectEqual(smaller, try f.length(io)); + try reader.seekTo(0); + try expectEqual(smaller, try reader.interface.readSliceShort(&buffer)); + try expectEqualStrings("nine", buffer[0..@intCast(smaller)]); + } + + try f.setLength(io, 0); + try expectEqual(0, try f.length(io)); + try reader.seekTo(0); + try expectEqual(0, try reader.interface.readSliceShort(&buffer)); } -test "updateTimes" { +test "setTimestamps" { + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); const tmp_file_name = "just_a_temporary_file.txt"; - var file = try tmp.dir.createFile(tmp_file_name, .{ .read = true }); - defer file.close(); + var file = try tmp.dir.createFile(io, tmp_file_name, .{ .read = true }); + defer file.close(io); + + const stat_old = try file.stat(io); - const stat_old = try file.stat(); // Set atime and mtime to 5s before - try file.updateTimes( - stat_old.atime.subDuration(.fromSeconds(5)), - stat_old.mtime.subDuration(.fromSeconds(5)), - ); - const stat_new = try file.stat(); - try expect(stat_new.atime.nanoseconds < stat_old.atime.nanoseconds); + try file.setTimestamps(io, .{ + .access_timestamp = if (stat_old.atime) |atime| .{ .new = atime.subDuration(.fromSeconds(5)) } else .unchanged, + .modify_timestamp = .{ .new = stat_old.mtime.subDuration(.fromSeconds(5)) }, + }); + const stat_new = try file.stat(io); + if (stat_old.atime) |old_atime| try expect(stat_new.atime.?.nanoseconds < old_atime.nanoseconds); try expect(stat_new.mtime.nanoseconds < stat_old.mtime.nanoseconds); } @@ -138,7 +194,7 @@ test "Group" { group.async(io, count, .{ 1, 10, &results[0] }); group.async(io, count, .{ 20, 30, &results[1] }); - group.wait(io); + try group.await(io); try testing.expectEqualSlices(usize, &.{ 45, 245 }, &results); } @@ -151,28 +207,53 @@ fn count(a: usize, b: usize, result: *usize) void { result.* = sum; } -test "Group cancellation" { +test "Group.cancel" { + const global = struct { + fn sleep(io: Io, result: *usize) Io.Cancelable!void { + defer result.* = 1; + io.sleep(.fromSeconds(100_000), .awake) catch |err| switch (err) { + error.Canceled => |e| return e, + else => {}, + }; + } + + fn sleepRecancel(io: Io, result: *usize) void { + io.sleep(.fromSeconds(100_000), .awake) catch |err| switch (err) { + error.Canceled => io.recancel(), + else => {}, + }; + result.* = 1; + } + + fn sleepUncancelable(io: Io, result: *usize) void { + const old_prot = io.swapCancelProtection(.blocked); + defer _ = io.swapCancelProtection(old_prot); + // Short sleep interval, because this one won't be canceled (that's the point!). + io.sleep(.fromMilliseconds(50), .awake) catch {}; + result.* = 1; + } + }; + const io = testing.io; var group: Io.Group = .init; - var results: [2]usize = undefined; + var results: [5]usize = @splat(0); - group.async(io, sleep, .{ io, &results[0] }); - group.async(io, sleep, .{ io, &results[1] }); + group.concurrent(io, global.sleep, .{ io, &results[0] }) catch |err| switch (err) { + error.ConcurrencyUnavailable => return error.SkipZigTest, + }; + try group.concurrent(io, global.sleep, .{ io, &results[1] }); + try group.concurrent(io, global.sleepRecancel, .{ io, &results[2] }); + try group.concurrent(io, global.sleepUncancelable, .{ io, &results[3] }); + // Because this one doesn't block until canceled, it is safe to run asynchronously. + group.async(io, global.sleepUncancelable, .{ io, &results[4] }); group.cancel(io); - try testing.expectEqualSlices(usize, &.{ 1, 1 }, &results); -} - -fn sleep(io: Io, result: *usize) void { - // TODO when cancellation race bug is fixed, make this timeout much longer so that - // it causes the unit test to be failed if not canceled. - io.sleep(.fromMilliseconds(1), .awake) catch {}; - result.* = 1; + try testing.expectEqualSlices(usize, &.{ 1, 1, 1, 1, 1 }, &results); } -test "Group concurrent" { +test "Group.concurrent" { const io = testing.io; var group: Io.Group = .init; @@ -193,7 +274,7 @@ test "Group concurrent" { }, }; - group.wait(io); + try group.await(io); try testing.expectEqualSlices(usize, &.{ 45, 245 }, &results); } @@ -209,10 +290,10 @@ test "select" { return; }, }; - defer if (get_a.cancel(io)) |_| {} else |_| @panic("fail"); + defer _ = get_a.cancel(io) catch {}; var get_b = try io.concurrent(Io.Queue(u8).getOne, .{ &queue, io }); - defer if (get_b.cancel(io)) |_| {} else |_| @panic("fail"); + defer _ = get_b.cancel(io) catch {}; var timeout = io.async(Io.sleep, .{ io, .fromMilliseconds(1), .awake }); defer timeout.cancel(io) catch {}; @@ -225,12 +306,9 @@ test "select" { .get_a => return error.TestFailure, .get_b => return error.TestFailure, .timeout => { - // Unblock the queues to avoid making this unit test depend on - // cancellation. - queue.putOneUncancelable(io, 1); - queue.putOneUncancelable(io, 1); - try testing.expectEqual(1, try get_a.await(io)); - try testing.expectEqual(1, try get_b.await(io)); + queue.close(io); + try testing.expectError(error.Closed, get_a.await(io)); + try testing.expectError(error.Closed, get_b.await(io)); }, } } @@ -255,3 +333,260 @@ test "Queue" { try testQueue(4); try testQueue(5); } + +test "Queue.close single-threaded" { + const io = std.testing.io; + + var buf: [10]u8 = undefined; + var queue: Io.Queue(u8) = .init(&buf); + + try queue.putAll(io, &.{ 0, 1, 2, 3, 4, 5, 6 }); + try expectEqual(3, try queue.put(io, &.{ 7, 8, 9, 10 }, 0)); // there is capacity for 3 more items + + var get_buf: [4]u8 = undefined; + + // Receive some elements before closing + try expectEqual(4, try queue.get(io, &get_buf, 0)); + try expectEqual(0, get_buf[0]); + try expectEqual(1, get_buf[1]); + try expectEqual(2, get_buf[2]); + try expectEqual(3, get_buf[3]); + try expectEqual(4, try queue.getOne(io)); + + // ...and add a couple more now there's space + try queue.putAll(io, &.{ 20, 21 }); + + queue.close(io); + + // Receive more elements *after* closing + try expectEqual(4, try queue.get(io, &get_buf, 0)); + try expectEqual(5, get_buf[0]); + try expectEqual(6, get_buf[1]); + try expectEqual(7, get_buf[2]); + try expectEqual(8, get_buf[3]); + try expectEqual(9, try queue.getOne(io)); + + // Cannot put anything while closed, even if the buffer has space + try expectError(error.Closed, queue.putOne(io, 100)); + try expectError(error.Closed, queue.putAll(io, &.{ 101, 102 })); + try expectError(error.Closed, queue.putUncancelable(io, &.{ 103, 104 }, 0)); + + // Even if we ask for 3 items, the queue is closed, so we only get the last 2 + try expectEqual(2, try queue.get(io, &get_buf, 4)); + try expectEqual(20, get_buf[0]); + try expectEqual(21, get_buf[1]); + + // The queue is now empty, so `get` should return `error.Closed` too + try expectError(error.Closed, queue.getOne(io)); + try expectError(error.Closed, queue.get(io, &get_buf, 0)); + try expectError(error.Closed, queue.putUncancelable(io, &get_buf, 2)); +} + +test "Event" { + const global = struct { + fn waitAndRead(io: Io, event: *Io.Event, ptr: *const u32) Io.Cancelable!u32 { + try event.wait(io); + return ptr.*; + } + }; + + const io = std.testing.io; + + var event: Io.Event = .unset; + var buffer: u32 = undefined; + + { + var future = io.concurrent(global.waitAndRead, .{ io, &event, &buffer }) catch |err| switch (err) { + error.ConcurrencyUnavailable => return error.SkipZigTest, + }; + + buffer = 123; + event.set(io); + + const result = try future.await(io); + + try std.testing.expectEqual(123, result); + } + + event.reset(); + + { + var future = io.concurrent(global.waitAndRead, .{ io, &event, &buffer }) catch |err| switch (err) { + error.ConcurrencyUnavailable => return error.SkipZigTest, + }; + try std.testing.expectError(error.Canceled, future.cancel(io)); + } +} + +test "recancel" { + const global = struct { + fn worker(io: Io) Io.Cancelable!void { + var dummy_event: Io.Event = .unset; + + if (dummy_event.wait(io)) { + return; + } else |err| switch (err) { + error.Canceled => io.recancel(), + } + + // Now we expect to see `error.Canceled` again. + return dummy_event.wait(io); + } + }; + + const io = std.testing.io; + var future = io.concurrent(global.worker, .{io}) catch |err| switch (err) { + error.ConcurrencyUnavailable => return error.SkipZigTest, + }; + if (future.cancel(io)) { + return error.UnexpectedSuccess; // both `wait` calls should have returned `error.Canceled` + } else |err| switch (err) { + error.Canceled => {}, + } +} + +test "swapCancelProtection" { + const global = struct { + fn waitTwice( + io: Io, + event: *Io.Event, + ) error{ Canceled, CanceledWhileProtected }!void { + // Wait for `event` while protected from cancelation. + { + const old_prot = io.swapCancelProtection(.blocked); + defer _ = io.swapCancelProtection(old_prot); + event.wait(io) catch |err| switch (err) { + error.Canceled => return error.CanceledWhileProtected, + }; + } + // Reset the event (it will never be set again), and this time wait for it without protection. + event.reset(); + _ = try event.wait(io); + } + fn sleepThenSet(io: Io, event: *Io.Event) !void { + // Give `waitTwice` a chance to get canceled. + try io.sleep(.fromMilliseconds(200), .awake); + event.set(io); + } + }; + + const io = std.testing.io; + + var event: Io.Event = .unset; + + var wait_future = io.concurrent(global.waitTwice, .{ io, &event }) catch |err| switch (err) { + error.ConcurrencyUnavailable => return error.SkipZigTest, + }; + defer wait_future.cancel(io) catch {}; + + var set_future = try io.concurrent(global.sleepThenSet, .{ io, &event }); + defer set_future.cancel(io) catch {}; + + if (wait_future.cancel(io)) { + return error.UnexpectedSuccess; // there was no `set` call to unblock the second `wait` + } else |err| switch (err) { + error.Canceled => {}, + error.CanceledWhileProtected => |e| return e, + } + + // Because it reached the `set`, it should be too late for `sleepThenSet` to see `error.Canceled`. + try set_future.cancel(io); +} + +test "cancel futex wait" { + const global = struct { + fn blockUntilCanceled(io: Io) void { + while (true) io.futexWait(u32, &0, 0) catch |err| switch (err) { + error.Canceled => return, + }; + } + }; + + const io = std.testing.io; + + var future = io.concurrent(global.blockUntilCanceled, .{io}) catch |err| switch (err) { + error.ConcurrencyUnavailable => return error.SkipZigTest, + }; + defer future.cancel(io); + + // Give the task some time to start so that we cancel while it is blocked. + try io.sleep(.fromMilliseconds(20), .awake); +} + +test "cancel sleep" { + const global = struct { + fn blockUntilCanceled(io: Io) void { + while (true) io.sleep(.fromSeconds(100_000), .awake) catch |err| switch (err) { + error.Canceled => return, + error.UnsupportedClock => @panic("unsupported clock"), + error.Unexpected => @panic("unexpected"), + }; + } + }; + + const io = std.testing.io; + + var future = io.concurrent(global.blockUntilCanceled, .{io}) catch |err| switch (err) { + error.ConcurrencyUnavailable => return error.SkipZigTest, + }; + defer future.cancel(io); + + // Give the task some time to start so that we cancel while it is blocked. + try io.sleep(.fromMilliseconds(20), .awake); +} + +test "tasks spawned in group after Group.cancel are canceled" { + const global = struct { + fn waitThenSpawn(io: Io, group: *Io.Group) void { + _ = io.swapCancelProtection(.blocked); + group.concurrent(io, blockUntilCanceled, .{io}) catch {}; + io.sleep(.fromMilliseconds(10), .awake) catch unreachable; + group.concurrent(io, blockUntilCanceled, .{io}) catch {}; + group.async(io, blockUntilCanceled, .{io}); + } + fn blockUntilCanceled(io: Io) Io.Cancelable!void { + while (true) io.sleep(.fromSeconds(100_000), .awake) catch |err| switch (err) { + error.Canceled => |e| return e, + error.UnsupportedClock => @panic("unsupported clock"), + error.Unexpected => @panic("unexpected"), + }; + } + }; + + const io = std.testing.io; + + var group: Io.Group = .init; + defer group.cancel(io); + + group.concurrent(io, global.blockUntilCanceled, .{io}) catch |err| switch (err) { + error.ConcurrencyUnavailable => return error.SkipZigTest, + }; + try io.sleep(.fromMilliseconds(10), .awake); // let that first sleep start up + try group.concurrent(io, global.waitThenSpawn, .{ io, &group }); +} + +test "random" { + const io = testing.io; + + var a: u64 = undefined; + var b: u64 = undefined; + var c: u64 = undefined; + + io.random(@ptrCast(&a)); + io.random(@ptrCast(&b)); + io.random(@ptrCast(&c)); + + try std.testing.expect(a ^ b ^ c != 0); +} + +test "randomSecure" { + const io = testing.io; + + var buf_a: [50]u8 = undefined; + var buf_b: [50]u8 = undefined; + try io.randomSecure(&buf_a); + try io.randomSecure(&buf_b); + // If this test fails the chance is significantly higher that there is a bug than + // that two sets of 50 bytes were equal. + try expect(!mem.eql(u8, &buf_a, &buf_b)); +} diff --git a/lib/std/Io/tty.zig b/lib/std/Io/tty.zig deleted file mode 100644 index 4f5ec8fd2d24..000000000000 --- a/lib/std/Io/tty.zig +++ /dev/null @@ -1,136 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const File = std.fs.File; -const process = std.process; -const windows = std.os.windows; -const native_os = builtin.os.tag; - -/// Deprecated in favor of `Config.detect`. -pub fn detectConfig(file: File) Config { - return .detect(file); -} - -pub const Color = enum { - black, - red, - green, - yellow, - blue, - magenta, - cyan, - white, - bright_black, - bright_red, - bright_green, - bright_yellow, - bright_blue, - bright_magenta, - bright_cyan, - bright_white, - dim, - bold, - reset, -}; - -/// Provides simple functionality for manipulating the terminal in some way, -/// such as coloring text, etc. -pub const Config = union(enum) { - no_color, - escape_codes, - windows_api: if (native_os == .windows) WindowsContext else noreturn, - - /// Detect suitable TTY configuration options for the given file (commonly stdout/stderr). - /// This includes feature checks for ANSI escape codes and the Windows console API, as well as - /// respecting the `NO_COLOR` and `CLICOLOR_FORCE` environment variables to override the default. - /// Will attempt to enable ANSI escape code support if necessary/possible. - pub fn detect(file: File) Config { - const force_color: ?bool = if (builtin.os.tag == .wasi) - null // wasi does not support environment variables - else if (process.hasNonEmptyEnvVarConstant("NO_COLOR")) - false - else if (process.hasNonEmptyEnvVarConstant("CLICOLOR_FORCE")) - true - else - null; - - if (force_color == false) return .no_color; - - if (file.getOrEnableAnsiEscapeSupport()) return .escape_codes; - - if (native_os == .windows and file.isTty()) { - var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined; - if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) == windows.FALSE) { - return if (force_color == true) .escape_codes else .no_color; - } - return .{ .windows_api = .{ - .handle = file.handle, - .reset_attributes = info.wAttributes, - } }; - } - - return if (force_color == true) .escape_codes else .no_color; - } - - pub const WindowsContext = struct { - handle: File.Handle, - reset_attributes: u16, - }; - - pub const SetColorError = std.os.windows.SetConsoleTextAttributeError || std.Io.Writer.Error; - - pub fn setColor(conf: Config, w: *std.Io.Writer, color: Color) SetColorError!void { - nosuspend switch (conf) { - .no_color => return, - .escape_codes => { - const color_string = switch (color) { - .black => "\x1b[30m", - .red => "\x1b[31m", - .green => "\x1b[32m", - .yellow => "\x1b[33m", - .blue => "\x1b[34m", - .magenta => "\x1b[35m", - .cyan => "\x1b[36m", - .white => "\x1b[37m", - .bright_black => "\x1b[90m", - .bright_red => "\x1b[91m", - .bright_green => "\x1b[92m", - .bright_yellow => "\x1b[93m", - .bright_blue => "\x1b[94m", - .bright_magenta => "\x1b[95m", - .bright_cyan => "\x1b[96m", - .bright_white => "\x1b[97m", - .bold => "\x1b[1m", - .dim => "\x1b[2m", - .reset => "\x1b[0m", - }; - try w.writeAll(color_string); - }, - .windows_api => |ctx| { - const attributes = switch (color) { - .black => 0, - .red => windows.FOREGROUND_RED, - .green => windows.FOREGROUND_GREEN, - .yellow => windows.FOREGROUND_RED | windows.FOREGROUND_GREEN, - .blue => windows.FOREGROUND_BLUE, - .magenta => windows.FOREGROUND_RED | windows.FOREGROUND_BLUE, - .cyan => windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE, - .white => windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE, - .bright_black => windows.FOREGROUND_INTENSITY, - .bright_red => windows.FOREGROUND_RED | windows.FOREGROUND_INTENSITY, - .bright_green => windows.FOREGROUND_GREEN | windows.FOREGROUND_INTENSITY, - .bright_yellow => windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_INTENSITY, - .bright_blue => windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY, - .bright_magenta => windows.FOREGROUND_RED | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY, - .bright_cyan => windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY, - .bright_white, .bold => windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY, - // "dim" is not supported using basic character attributes, but let's still make it do *something*. - // This matches the old behavior of TTY.Color before the bright variants were added. - .dim => windows.FOREGROUND_INTENSITY, - .reset => ctx.reset_attributes, - }; - try w.flush(); - try windows.SetConsoleTextAttribute(ctx.handle, attributes); - }, - }; - } -}; diff --git a/lib/std/Progress.zig b/lib/std/Progress.zig index a7274be8c7d3..75ef13ca91f1 100644 --- a/lib/std/Progress.zig +++ b/lib/std/Progress.zig @@ -1,26 +1,30 @@ //! This API is non-allocating, non-fallible, thread-safe, and lock-free. +const Progress = @This(); -const std = @import("std"); const builtin = @import("builtin"); +const is_big_endian = builtin.cpu.arch.endian() == .big; +const is_windows = builtin.os.tag == .windows; + +const std = @import("std"); +const Io = std.Io; const windows = std.os.windows; const testing = std.testing; const assert = std.debug.assert; -const Progress = @This(); const posix = std.posix; -const is_big_endian = builtin.cpu.arch.endian() == .big; -const is_windows = builtin.os.tag == .windows; const Writer = std.Io.Writer; -/// `null` if the current node (and its children) should -/// not print on update() -terminal: std.fs.File, +/// Currently this API only supports this value being set to stderr, which +/// happens automatically inside `start`. +terminal: Io.File, + +io: Io, terminal_mode: TerminalMode, -update_thread: ?std.Thread, +update_worker: ?Io.Future(void), /// Atomically set by SIGWINCH as well as the root done() function. -redraw_event: std.Thread.ResetEvent, +redraw_event: Io.Event, /// Indicates a request to shut down and reset global state. /// Accessed atomically. done: bool, @@ -48,6 +52,8 @@ node_freelist: Freelist, /// value may at times temporarily exceed the node count. node_end_index: u32, +start_failure: StartFailure, + pub const Status = enum { /// Indicates the application is progressing towards completion of a task. /// Unless the application is interactive, this is the only status the @@ -93,9 +99,9 @@ pub const Options = struct { /// Must be at least 200 bytes. draw_buffer: []u8 = &default_draw_buffer, /// How many nanoseconds between writing updates to the terminal. - refresh_rate_ns: u64 = 80 * std.time.ns_per_ms, + refresh_rate_ns: Io.Duration = .fromMilliseconds(80), /// How many nanoseconds to keep the output hidden - initial_delay_ns: u64 = 200 * std.time.ns_per_ms, + initial_delay_ns: Io.Duration = .fromMilliseconds(200), /// If provided, causes the progress item to have a denominator. /// 0 means unknown. estimated_total_items: usize = 0, @@ -121,20 +127,20 @@ pub const Node = struct { name: [max_name_len]u8 align(@alignOf(usize)), /// Not thread-safe. - fn getIpcFd(s: Storage) ?posix.fd_t { - return if (s.estimated_total_count == std.math.maxInt(u32)) switch (@typeInfo(posix.fd_t)) { + fn getIpcFd(s: Storage) ?Io.File.Handle { + return if (s.estimated_total_count == std.math.maxInt(u32)) switch (@typeInfo(Io.File.Handle)) { .int => @bitCast(s.completed_count), .pointer => @ptrFromInt(s.completed_count), - else => @compileError("unsupported fd_t of " ++ @typeName(posix.fd_t)), + else => @compileError("unsupported fd_t of " ++ @typeName(Io.File.Handle)), } else null; } /// Thread-safe. - fn setIpcFd(s: *Storage, fd: posix.fd_t) void { - const integer: u32 = switch (@typeInfo(posix.fd_t)) { + fn setIpcFd(s: *Storage, fd: Io.File.Handle) void { + const integer: u32 = switch (@typeInfo(Io.File.Handle)) { .int => @bitCast(fd), .pointer => @intFromPtr(fd), - else => @compileError("unsupported fd_t of " ++ @typeName(posix.fd_t)), + else => @compileError("unsupported fd_t of " ++ @typeName(Io.File.Handle)), }; // `estimated_total_count` max int indicates the special state that // causes `completed_count` to be treated as a file descriptor, so @@ -257,7 +263,7 @@ pub const Node = struct { const index = n.index.unwrap() orelse return; const storage = storageByIndex(index); - const name_len = @min(max_name_len, std.mem.indexOfScalar(u8, new_name, 0) orelse new_name.len); + const name_len = @min(max_name_len, std.mem.findScalar(u8, new_name, 0) orelse new_name.len); copyAtomicStore(storage.name[0..name_len], new_name[0..name_len]); if (name_len < storage.name.len) @@ -327,13 +333,14 @@ pub const Node = struct { } } else { @atomicStore(bool, &global_progress.done, true, .monotonic); - global_progress.redraw_event.set(); - if (global_progress.update_thread) |thread| thread.join(); + const io = global_progress.io; + global_progress.redraw_event.set(io); + if (global_progress.update_worker) |*worker| worker.await(io); } } /// Posix-only. Used by `std.process.Child`. Thread-safe. - pub fn setIpcFd(node: Node, fd: posix.fd_t) void { + pub fn setIpcFd(node: Node, fd: Io.File.Handle) void { const index = node.index.unwrap() orelse return; assert(fd >= 0); assert(fd != posix.STDOUT_FILENO); @@ -344,14 +351,14 @@ pub const Node = struct { /// Posix-only. Thread-safe. Assumes the node is storing an IPC file /// descriptor. - pub fn getIpcFd(node: Node) ?posix.fd_t { + pub fn getIpcFd(node: Node) ?Io.File.Handle { const index = node.index.unwrap() orelse return null; const storage = storageByIndex(index); const int = @atomicLoad(u32, &storage.completed_count, .monotonic); - return switch (@typeInfo(posix.fd_t)) { + return switch (@typeInfo(Io.File.Handle)) { .int => @bitCast(int), .pointer => @ptrFromInt(int), - else => @compileError("unsupported fd_t of " ++ @typeName(posix.fd_t)), + else => @compileError("unsupported fd_t of " ++ @typeName(Io.File.Handle)), }; } @@ -389,9 +396,10 @@ pub const Node = struct { }; var global_progress: Progress = .{ + .io = undefined, .terminal = undefined, .terminal_mode = .off, - .update_thread = null, + .update_worker = null, .redraw_event = .unset, .refresh_rate_ns = undefined, .initial_delay_ns = undefined, @@ -401,6 +409,7 @@ var global_progress: Progress = .{ .done = false, .need_clear = false, .status = .working, + .start_failure = .unstarted, .node_parents = &node_parents_buffer, .node_storage = &node_storage_buffer, @@ -409,6 +418,13 @@ var global_progress: Progress = .{ .node_end_index = 0, }; +pub const StartFailure = union(enum) { + unstarted, + spawn_ipc_worker: error{ConcurrencyUnavailable}, + spawn_update_worker: error{ConcurrencyUnavailable}, + parent_ipc: error{ UnsupportedOperation, UnrecognizedFormat }, +}; + const node_storage_buffer_len = 83; var node_parents_buffer: [node_storage_buffer_len]Node.Parent = undefined; var node_storage_buffer: [node_storage_buffer_len]Node.Storage = undefined; @@ -430,12 +446,20 @@ const noop_impl = builtin.single_threaded or switch (builtin.os.tag) { else => false, }; +pub const ParentFileError = error{ + UnsupportedOperation, + EnvironmentVariableMissing, + UnrecognizedFormat, +}; + /// Initializes a global Progress instance. /// /// Asserts there is only one global Progress instance. /// /// Call `Node.end` when done. -pub fn start(options: Options) Node { +/// +/// If an error occurs, `start_failure` will be populated. +pub fn start(io: Io, options: Options) Node { // Ensure there is only 1 global Progress object. if (global_progress.node_end_index != 0) { debug_start_trace.dump(); @@ -450,36 +474,39 @@ pub fn start(options: Options) Node { assert(options.draw_buffer.len >= 200); global_progress.draw_buffer = options.draw_buffer; - global_progress.refresh_rate_ns = options.refresh_rate_ns; - global_progress.initial_delay_ns = options.initial_delay_ns; + global_progress.refresh_rate_ns = @intCast(options.refresh_rate_ns.toNanoseconds()); + global_progress.initial_delay_ns = @intCast(options.initial_delay_ns.toNanoseconds()); if (noop_impl) return Node.none; - if (std.process.parseEnvVarInt("ZIG_PROGRESS", u31, 10)) |ipc_fd| { - global_progress.update_thread = std.Thread.spawn(.{}, ipcThreadRun, .{ - @as(posix.fd_t, switch (@typeInfo(posix.fd_t)) { - .int => ipc_fd, - .pointer => @ptrFromInt(ipc_fd), - else => @compileError("unsupported fd_t of " ++ @typeName(posix.fd_t)), - }), - }) catch |err| { - std.log.warn("failed to spawn IPC thread for communicating progress to parent: {s}", .{@errorName(err)}); + global_progress.io = io; + + if (io.vtable.progressParentFile(io.userdata)) |ipc_file| { + global_progress.update_worker = io.concurrent(ipcThreadRun, .{ io, ipc_file }) catch |err| { + global_progress.start_failure = .{ .spawn_ipc_worker = err }; return Node.none; }; } else |env_err| switch (env_err) { - error.EnvironmentVariableNotFound => { + error.EnvironmentVariableMissing => { if (options.disable_printing) { return Node.none; } - const stderr: std.fs.File = .stderr(); + const stderr: Io.File = .stderr(); global_progress.terminal = stderr; - if (stderr.getOrEnableAnsiEscapeSupport()) { + if (stderr.enableAnsiEscapeCodes(io)) |_| { global_progress.terminal_mode = .ansi_escape_codes; - } else if (is_windows and stderr.isTty()) { - global_progress.terminal_mode = TerminalMode{ .windows_api = .{ - .code_page = windows.kernel32.GetConsoleOutputCP(), - } }; + } else |_| if (is_windows) { + if (stderr.isTty(io)) |is_tty| { + if (is_tty) global_progress.terminal_mode = TerminalMode{ .windows_api = .{ + .code_page = windows.kernel32.GetConsoleOutputCP(), + } }; + } else |err| switch (err) { + error.Canceled => { + io.recancel(); + return Node.none; + }, + } } if (global_progress.terminal_mode == .off) { @@ -497,17 +524,17 @@ pub fn start(options: Options) Node { if (switch (global_progress.terminal_mode) { .off => unreachable, // handled a few lines above - .ansi_escape_codes => std.Thread.spawn(.{}, updateThreadRun, .{}), - .windows_api => if (is_windows) std.Thread.spawn(.{}, windowsApiUpdateThreadRun, .{}) else unreachable, - }) |thread| { - global_progress.update_thread = thread; + .ansi_escape_codes => io.concurrent(updateTask, .{io}), + .windows_api => if (is_windows) io.concurrent(windowsApiUpdateTask, .{io}) else unreachable, + }) |future| { + global_progress.update_worker = future; } else |err| { - std.log.warn("unable to spawn thread for printing progress to terminal: {s}", .{@errorName(err)}); + global_progress.start_failure = .{ .spawn_update_worker = err }; return Node.none; } }, else => |e| { - std.log.warn("invalid ZIG_PROGRESS file descriptor integer: {s}", .{@errorName(e)}); + global_progress.start_failure = .{ .parent_ipc = e }; return Node.none; }, } @@ -521,48 +548,57 @@ pub fn setStatus(new_status: Status) void { } /// Returns whether a resize is needed to learn the terminal size. -fn wait(timeout_ns: u64) bool { - const resize_flag = if (global_progress.redraw_event.timedWait(timeout_ns)) |_| true else |err| switch (err) { - error.Timeout => false, +fn wait(io: Io, timeout_ns: u64) bool { + const timeout: Io.Timeout = .{ .duration = .{ + .clock = .awake, + .raw = .fromNanoseconds(timeout_ns), + } }; + const resize_flag = if (global_progress.redraw_event.waitTimeout(io, timeout)) |_| true else |err| switch (err) { + error.Timeout, error.Canceled => false, }; global_progress.redraw_event.reset(); return resize_flag or (global_progress.cols == 0); } -fn updateThreadRun() void { +fn updateTask(io: Io) void { // Store this data in the thread so that it does not need to be part of the // linker data of the main executable. var serialized_buffer: Serialized.Buffer = undefined; + // In this function we bypass the wrapper code inside `Io.lockStderr` / + // `Io.tryLockStderr` in order to avoid clearing the terminal twice. + // We still want to go through the `Io` instance however in case it uses a + // task-switching mutex. + { - const resize_flag = wait(global_progress.initial_delay_ns); + const resize_flag = wait(io, global_progress.initial_delay_ns); if (@atomicLoad(bool, &global_progress.done, .monotonic)) return; maybeUpdateSize(resize_flag); const buffer, _ = computeRedraw(&serialized_buffer); - if (stderr_mutex.tryLock()) { - defer stderr_mutex.unlock(); - write(buffer) catch return; + if (io.vtable.tryLockStderr(io.userdata, null) catch return) |locked_stderr| { + defer io.unlockStderr(); global_progress.need_clear = true; + locked_stderr.file_writer.interface.writeAll(buffer) catch return; } } while (true) { - const resize_flag = wait(global_progress.refresh_rate_ns); + const resize_flag = wait(io, global_progress.refresh_rate_ns); if (@atomicLoad(bool, &global_progress.done, .monotonic)) { - stderr_mutex.lock(); - defer stderr_mutex.unlock(); - return clearWrittenWithEscapeCodes() catch {}; + const stderr = io.vtable.lockStderr(io.userdata, null) catch return; + defer io.unlockStderr(); + return clearWrittenWithEscapeCodes(stderr.file_writer) catch {}; } maybeUpdateSize(resize_flag); const buffer, _ = computeRedraw(&serialized_buffer); - if (stderr_mutex.tryLock()) { - defer stderr_mutex.unlock(); - write(buffer) catch return; + if (io.vtable.tryLockStderr(io.userdata, null) catch return) |locked_stderr| { + defer io.unlockStderr(); global_progress.need_clear = true; + locked_stderr.file_writer.interface.writeAll(buffer) catch return; } } } @@ -575,117 +611,77 @@ fn windowsApiWriteMarker() void { _ = windows.kernel32.WriteConsoleW(handle, &[_]u16{windows_api_start_marker}, 1, &num_chars_written, null); } -fn windowsApiUpdateThreadRun() void { +fn windowsApiUpdateTask(io: Io) void { var serialized_buffer: Serialized.Buffer = undefined; + // In this function we bypass the wrapper code inside `Io.lockStderr` / + // `Io.tryLockStderr` in order to avoid clearing the terminal twice. + // We still want to go through the `Io` instance however in case it uses a + // task-switching mutex. + { - const resize_flag = wait(global_progress.initial_delay_ns); + const resize_flag = wait(io, global_progress.initial_delay_ns); if (@atomicLoad(bool, &global_progress.done, .monotonic)) return; maybeUpdateSize(resize_flag); const buffer, const nl_n = computeRedraw(&serialized_buffer); - if (stderr_mutex.tryLock()) { - defer stderr_mutex.unlock(); + if (io.vtable.tryLockStderr(io.userdata, null) catch return) |locked_stderr| { + defer io.unlockStderr(); windowsApiWriteMarker(); - write(buffer) catch return; global_progress.need_clear = true; + locked_stderr.file_writer.interface.writeAll(buffer) catch return; windowsApiMoveToMarker(nl_n) catch return; } } while (true) { - const resize_flag = wait(global_progress.refresh_rate_ns); + const resize_flag = wait(io, global_progress.refresh_rate_ns); if (@atomicLoad(bool, &global_progress.done, .monotonic)) { - stderr_mutex.lock(); - defer stderr_mutex.unlock(); + _ = io.vtable.lockStderr(io.userdata, null) catch return; + defer io.unlockStderr(); return clearWrittenWindowsApi() catch {}; } maybeUpdateSize(resize_flag); const buffer, const nl_n = computeRedraw(&serialized_buffer); - if (stderr_mutex.tryLock()) { - defer stderr_mutex.unlock(); + if (io.vtable.tryLockStderr(io.userdata, null) catch return) |locked_stderr| { + defer io.unlockStderr(); clearWrittenWindowsApi() catch return; windowsApiWriteMarker(); - write(buffer) catch return; global_progress.need_clear = true; + locked_stderr.file_writer.interface.writeAll(buffer) catch return; windowsApiMoveToMarker(nl_n) catch return; } } } -/// Allows the caller to freely write to stderr until `unlockStdErr` is called. -/// -/// During the lock, any `std.Progress` information is cleared from the terminal. -/// -/// The lock is recursive; the same thread may hold the lock multiple times. -pub fn lockStdErr() void { - stderr_mutex.lock(); - clearWrittenWithEscapeCodes() catch {}; -} - -pub fn unlockStdErr() void { - stderr_mutex.unlock(); -} - -/// Protected by `stderr_mutex`. -const stderr_writer: *Writer = &stderr_file_writer.interface; -/// Protected by `stderr_mutex`. -var stderr_file_writer: std.fs.File.Writer = .{ - .interface = std.fs.File.Writer.initInterface(&.{}), - .file = if (is_windows) undefined else .stderr(), - .mode = .streaming, -}; - -/// Allows the caller to freely write to the returned `Writer`, -/// initialized with `buffer`, until `unlockStderrWriter` is called. -/// -/// During the lock, any `std.Progress` information is cleared from the terminal. -/// -/// The lock is recursive; the same thread may hold the lock multiple times. -pub fn lockStderrWriter(buffer: []u8) *Writer { - stderr_mutex.lock(); - clearWrittenWithEscapeCodes() catch {}; - if (is_windows) stderr_file_writer.file = .stderr(); - stderr_writer.flush() catch {}; - stderr_writer.buffer = buffer; - return stderr_writer; -} - -pub fn unlockStderrWriter() void { - stderr_writer.flush() catch {}; - stderr_writer.end = 0; - stderr_writer.buffer = &.{}; - stderr_mutex.unlock(); -} - -fn ipcThreadRun(fd: posix.fd_t) anyerror!void { +fn ipcThreadRun(io: Io, file: Io.File) void { // Store this data in the thread so that it does not need to be part of the // linker data of the main executable. var serialized_buffer: Serialized.Buffer = undefined; { - _ = wait(global_progress.initial_delay_ns); + _ = wait(io, global_progress.initial_delay_ns); if (@atomicLoad(bool, &global_progress.done, .monotonic)) return; const serialized = serialize(&serialized_buffer); - writeIpc(fd, serialized) catch |err| switch (err) { + writeIpc(io, file, serialized) catch |err| switch (err) { error.BrokenPipe => return, }; } while (true) { - _ = wait(global_progress.refresh_rate_ns); + _ = wait(io, global_progress.refresh_rate_ns); if (@atomicLoad(bool, &global_progress.done, .monotonic)) return; const serialized = serialize(&serialized_buffer); - writeIpc(fd, serialized) catch |err| switch (err) { + writeIpc(io, file, serialized) catch |err| switch (err) { error.BrokenPipe => return, }; } @@ -784,11 +780,10 @@ fn appendTreeSymbol(symbol: TreeSymbol, buf: []u8, start_i: usize) usize { } } -fn clearWrittenWithEscapeCodes() anyerror!void { +pub fn clearWrittenWithEscapeCodes(file_writer: *Io.File.Writer) Io.Writer.Error!void { if (noop_impl or !global_progress.need_clear) return; - + try file_writer.interface.writeAll(clear ++ progress_remove); global_progress.need_clear = false; - try write(clear ++ progress_remove); } /// U+25BA or ► @@ -948,11 +943,11 @@ const SavedMetadata = struct { const Fd = enum(i32) { _, - fn init(fd: posix.fd_t) Fd { + fn init(fd: Io.File.Handle) Fd { return @enumFromInt(if (is_windows) @as(isize, @bitCast(@intFromPtr(fd))) else fd); } - fn get(fd: Fd) posix.fd_t { + fn get(fd: Fd) Io.File.Handle { return if (is_windows) @ptrFromInt(@as(usize, @bitCast(@as(isize, @intFromEnum(fd))))) else @@ -963,6 +958,7 @@ const Fd = enum(i32) { var ipc_metadata_len: u8 = 0; fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buffer) usize { + const io = global_progress.io; const ipc_metadata_fds_copy = &serialized_buffer.ipc_metadata_fds_copy; const ipc_metadata_copy = &serialized_buffer.ipc_metadata_copy; const ipc_metadata_fds = &serialized_buffer.ipc_metadata_fds; @@ -981,14 +977,14 @@ fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buff 0.., ) |main_parent, *main_storage, main_index| { if (main_parent == .unused) continue; - const fd = main_storage.getIpcFd() orelse continue; - const opt_saved_metadata = findOld(fd, old_ipc_metadata_fds, old_ipc_metadata); + const file: Io.File = .{ .handle = main_storage.getIpcFd() orelse continue }; + const opt_saved_metadata = findOld(file.handle, old_ipc_metadata_fds, old_ipc_metadata); var bytes_read: usize = 0; while (true) { - const n = posix.read(fd, pipe_buf[bytes_read..]) catch |err| switch (err) { + const n = file.readStreaming(io, &.{pipe_buf[bytes_read..]}) catch |err| switch (err) { error.WouldBlock => break, else => |e| { - std.log.debug("failed to read child progress data: {s}", .{@errorName(e)}); + std.log.debug("failed to read child progress data: {t}", .{e}); main_storage.completed_count = 0; main_storage.estimated_total_count = 0; continue :main_loop; @@ -1014,7 +1010,7 @@ fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buff // Ignore all but the last message on the pipe. var input: []u8 = pipe_buf[0..bytes_read]; if (input.len == 0) { - serialized_len = useSavedIpcData(serialized_len, serialized_buffer, main_storage, main_index, opt_saved_metadata, 0, fd); + serialized_len = useSavedIpcData(serialized_len, serialized_buffer, main_storage, main_index, opt_saved_metadata, 0, file.handle); continue; } @@ -1024,7 +1020,7 @@ fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buff if (input.len < expected_bytes) { // Ignore short reads. We'll handle the next full message when it comes instead. const remaining_read_trash_bytes: u16 = @intCast(expected_bytes - input.len); - serialized_len = useSavedIpcData(serialized_len, serialized_buffer, main_storage, main_index, opt_saved_metadata, remaining_read_trash_bytes, fd); + serialized_len = useSavedIpcData(serialized_len, serialized_buffer, main_storage, main_index, opt_saved_metadata, remaining_read_trash_bytes, file.handle); continue :main_loop; } if (input.len > expected_bytes) { @@ -1042,7 +1038,7 @@ fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buff const nodes_len: u8 = @intCast(@min(parents.len - 1, serialized_buffer.storage.len - serialized_len)); // Remember in case the pipe is empty on next update. - ipc_metadata_fds[ipc_metadata_len] = Fd.init(fd); + ipc_metadata_fds[ipc_metadata_len] = Fd.init(file.handle); ipc_metadata[ipc_metadata_len] = .{ .remaining_read_trash_bytes = 0, .start_index = @intCast(serialized_len), @@ -1100,7 +1096,7 @@ fn copyRoot(dest: *Node.Storage, src: *align(1) Node.Storage) void { } fn findOld( - ipc_fd: posix.fd_t, + ipc_fd: Io.File.Handle, old_metadata_fds: []Fd, old_metadata: []SavedMetadata, ) ?*SavedMetadata { @@ -1118,7 +1114,7 @@ fn useSavedIpcData( main_index: usize, opt_saved_metadata: ?*SavedMetadata, remaining_read_trash_bytes: u16, - fd: posix.fd_t, + fd: Io.File.Handle, ) usize { const parents_copy = &serialized_buffer.parents_copy; const storage_copy = &serialized_buffer.storage_copy; @@ -1347,7 +1343,7 @@ fn computeNode( const storage = &serialized.storage[@intFromEnum(node_index)]; const estimated_total = storage.estimated_total_count; const completed_items = storage.completed_count; - const name = if (std.mem.indexOfScalar(u8, &storage.name, 0)) |end| storage.name[0..end] else &storage.name; + const name = if (std.mem.findScalar(u8, &storage.name, 0)) |end| storage.name[0..end] else &storage.name; const parent = serialized.parents[@intFromEnum(node_index)]; if (parent != .none) p: { @@ -1415,13 +1411,9 @@ fn withinRowLimit(p: *Progress, nl_n: usize) bool { return nl_n + 2 < p.rows; } -fn write(buf: []const u8) anyerror!void { - try global_progress.terminal.writeAll(buf); -} - var remaining_write_trash_bytes: usize = 0; -fn writeIpc(fd: posix.fd_t, serialized: Serialized) error{BrokenPipe}!void { +fn writeIpc(io: Io, file: Io.File, serialized: Serialized) error{BrokenPipe}!void { // Byteswap if necessary to ensure little endian over the pipe. This is // needed because the parent or child process might be running in qemu. if (is_big_endian) for (serialized.storage) |*s| s.byteSwap(); @@ -1432,11 +1424,7 @@ fn writeIpc(fd: posix.fd_t, serialized: Serialized) error{BrokenPipe}!void { const storage = std.mem.sliceAsBytes(serialized.storage); const parents = std.mem.sliceAsBytes(serialized.parents); - var vecs: [3]posix.iovec_const = .{ - .{ .base = header.ptr, .len = header.len }, - .{ .base = storage.ptr, .len = storage.len }, - .{ .base = parents.ptr, .len = parents.len }, - }; + var vecs: [3][]const u8 = .{ header, storage, parents }; // Ensures the packet can fit in the pipe buffer. const upper_bound_msg_len = 1 + node_storage_buffer_len * @sizeOf(Node.Storage) + @@ -1447,14 +1435,14 @@ fn writeIpc(fd: posix.fd_t, serialized: Serialized) error{BrokenPipe}!void { // We do this in a separate write call to give a better chance for the // writev below to be in a single packet. const n = @min(parents.len, remaining_write_trash_bytes); - if (posix.write(fd, parents[0..n])) |written| { + if (io.vtable.fileWriteStreaming(io.userdata, file, &.{}, &.{parents[0..n]}, 1)) |written| { remaining_write_trash_bytes -= written; continue; } else |err| switch (err) { error.WouldBlock => return, error.BrokenPipe => return error.BrokenPipe, else => |e| { - std.log.debug("failed to send progress to parent process: {s}", .{@errorName(e)}); + std.log.debug("failed to send progress to parent process: {t}", .{e}); return error.BrokenPipe; }, } @@ -1462,7 +1450,7 @@ fn writeIpc(fd: posix.fd_t, serialized: Serialized) error{BrokenPipe}!void { // If this write would block we do not want to keep trying, but we need to // know if a partial message was written. - if (writevNonblock(fd, &vecs)) |written| { + if (writevNonblock(io, file, &vecs)) |written| { const total = header.len + storage.len + parents.len; if (written < total) { remaining_write_trash_bytes = total - written; @@ -1471,13 +1459,13 @@ fn writeIpc(fd: posix.fd_t, serialized: Serialized) error{BrokenPipe}!void { error.WouldBlock => {}, error.BrokenPipe => return error.BrokenPipe, else => |e| { - std.log.debug("failed to send progress to parent process: {s}", .{@errorName(e)}); + std.log.debug("failed to send progress to parent process: {t}", .{e}); return error.BrokenPipe; }, } } -fn writevNonblock(fd: posix.fd_t, iov: []posix.iovec_const) posix.WriteError!usize { +fn writevNonblock(io: Io, file: Io.File, iov: [][]const u8) Io.File.Writer.Error!usize { var iov_index: usize = 0; var written: usize = 0; var total_written: usize = 0; @@ -1486,9 +1474,9 @@ fn writevNonblock(fd: posix.fd_t, iov: []posix.iovec_const) posix.WriteError!usi written >= iov[iov_index].len else return total_written) : (iov_index += 1) written -= iov[iov_index].len; - iov[iov_index].base += written; + iov[iov_index].ptr += written; iov[iov_index].len -= written; - written = try posix.writev(fd, iov[iov_index..]); + written = try io.vtable.fileWriteStreaming(io.userdata, file, &.{}, iov, 1); if (written == 0) return total_written; total_written += written; } @@ -1538,7 +1526,7 @@ fn handleSigWinch(sig: posix.SIG, info: *const posix.siginfo_t, ctx_ptr: ?*anyop _ = info; _ = ctx_ptr; assert(sig == .WINCH); - global_progress.redraw_event.set(); + global_progress.redraw_event.set(global_progress.io); } const have_sigwinch = switch (builtin.os.tag) { @@ -1563,11 +1551,6 @@ const have_sigwinch = switch (builtin.os.tag) { else => false, }; -/// The primary motivation for recursive mutex here is so that a panic while -/// stderr mutex is held still dumps the stack trace and other debug -/// information. -var stderr_mutex = std.Thread.Mutex.Recursive.init; - fn copyAtomicStore(dest: []align(@alignOf(usize)) u8, src: []const u8) void { assert(dest.len == src.len); const chunked_len = dest.len / @sizeOf(usize); diff --git a/lib/std/Random.zig b/lib/std/Random.zig index b90c8e39580d..218ddac1d62c 100644 --- a/lib/std/Random.zig +++ b/lib/std/Random.zig @@ -1,15 +1,13 @@ //! The engines provided here should be initialized from an external source. -//! For a thread-local cryptographically secure pseudo random number generator, -//! use `std.crypto.random`. //! Be sure to use a CSPRNG when required, otherwise using a normal PRNG will //! be faster and use substantially less stack space. +const Random = @This(); const std = @import("std.zig"); const math = std.math; const mem = std.mem; const assert = std.debug.assert; const maxInt = std.math.maxInt; -const Random = @This(); /// Fast unbiased random numbers. pub const DefaultPrng = Xoshiro256; @@ -35,6 +33,22 @@ pub const ziggurat = @import("Random/ziggurat.zig"); ptr: *anyopaque, fillFn: *const fn (ptr: *anyopaque, buf: []u8) void, +pub const IoSource = struct { + io: std.Io, + + pub fn interface(this: *const @This()) std.Random { + return .{ + .ptr = @constCast(this), + .fillFn = fill, + }; + } + + fn fill(ptr: *anyopaque, buffer: []u8) void { + const this: *const @This() = @ptrCast(@alignCast(ptr)); + this.io.random(buffer); + } +}; + pub fn init(pointer: anytype, comptime fillFn: fn (ptr: @TypeOf(pointer), buf: []u8) void) Random { const Ptr = @TypeOf(pointer); assert(@typeInfo(Ptr) == .pointer); // Must be a pointer diff --git a/lib/std/Random/ChaCha.zig b/lib/std/Random/ChaCha.zig index 5783ee415271..9c8f548ecf9c 100644 --- a/lib/std/Random/ChaCha.zig +++ b/lib/std/Random/ChaCha.zig @@ -20,7 +20,7 @@ pub const secret_seed_length = Cipher.key_length; /// The seed must be uniform, secret and `secret_seed_length` bytes long. pub fn init(secret_seed: [secret_seed_length]u8) Self { - var self = Self{ .state = undefined, .offset = 0 }; + var self: Self = .{ .state = undefined, .offset = 0 }; Cipher.stream(&self.state, 0, secret_seed, nonce); return self; } diff --git a/lib/std/Random/benchmark.zig b/lib/std/Random/benchmark.zig index 4f6198dee731..a545cda6d5db 100644 --- a/lib/std/Random/benchmark.zig +++ b/lib/std/Random/benchmark.zig @@ -1,7 +1,9 @@ // zig run -O ReleaseFast --zig-lib-dir ../.. benchmark.zig -const std = @import("std"); const builtin = @import("builtin"); + +const std = @import("std"); +const Io = std.Io; const time = std.time; const Timer = time.Timer; const Random = std.Random; @@ -121,14 +123,15 @@ fn mode(comptime x: comptime_int) comptime_int { return if (builtin.mode == .Debug) x / 64 else x; } -pub fn main() !void { +pub fn main(init: std.process.Init) !void { + const io = init.io; + const arena = init.arena.allocator(); + var stdout_buffer: [0x100]u8 = undefined; - var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); + var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer); const stdout = &stdout_writer.interface; - var buffer: [1024]u8 = undefined; - var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]); - const args = try std.process.argsAlloc(fixed.allocator()); + const args = try init.minimal.args.toSlice(arena); var filter: ?[]u8 = ""; var count: usize = mode(128 * MiB); @@ -180,7 +183,7 @@ pub fn main() !void { if (bench_prngs) { if (bench_long) { inline for (prngs) |R| { - if (filter == null or std.mem.indexOf(u8, R.name, filter.?) != null) { + if (filter == null or std.mem.find(u8, R.name, filter.?) != null) { try stdout.print("{s} (long outputs)\n", .{R.name}); try stdout.flush(); @@ -191,7 +194,7 @@ pub fn main() !void { } if (bench_short) { inline for (prngs) |R| { - if (filter == null or std.mem.indexOf(u8, R.name, filter.?) != null) { + if (filter == null or std.mem.find(u8, R.name, filter.?) != null) { try stdout.print("{s} (short outputs)\n", .{R.name}); try stdout.flush(); @@ -204,7 +207,7 @@ pub fn main() !void { if (bench_csprngs) { if (bench_long) { inline for (csprngs) |R| { - if (filter == null or std.mem.indexOf(u8, R.name, filter.?) != null) { + if (filter == null or std.mem.find(u8, R.name, filter.?) != null) { try stdout.print("{s} (cryptographic, long outputs)\n", .{R.name}); try stdout.flush(); @@ -215,7 +218,7 @@ pub fn main() !void { } if (bench_short) { inline for (csprngs) |R| { - if (filter == null or std.mem.indexOf(u8, R.name, filter.?) != null) { + if (filter == null or std.mem.find(u8, R.name, filter.?) != null) { try stdout.print("{s} (cryptographic, short outputs)\n", .{R.name}); try stdout.flush(); diff --git a/lib/std/Random/test.zig b/lib/std/Random/test.zig index 8ceacbc934f4..3db56df6553e 100644 --- a/lib/std/Random/test.zig +++ b/lib/std/Random/test.zig @@ -436,8 +436,9 @@ fn testRangeBias(r: Random, start: i8, end: i8, biased: bool) !void { } test "CSPRNG" { + const io = std.testing.io; var secret_seed: [DefaultCsprng.secret_seed_length]u8 = undefined; - std.crypto.random.bytes(&secret_seed); + io.random(&secret_seed); var csprng = DefaultCsprng.init(secret_seed); const random = csprng.random(); const a = random.int(u64); diff --git a/lib/std/SemanticVersion.zig b/lib/std/SemanticVersion.zig index 4566187eb802..2fed6cbb752d 100644 --- a/lib/std/SemanticVersion.zig +++ b/lib/std/SemanticVersion.zig @@ -84,7 +84,7 @@ pub fn order(lhs: Version, rhs: Version) std.math.Order { pub fn parse(text: []const u8) !Version { // Parse the required major, minor, and patch numbers. - const extra_index = std.mem.indexOfAny(u8, text, "-+"); + const extra_index = std.mem.findAny(u8, text, "-+"); const required = text[0..(extra_index orelse text.len)]; var it = std.mem.splitScalar(u8, required, '.'); var ver = Version{ @@ -98,7 +98,7 @@ pub fn parse(text: []const u8) !Version { // Slice optional pre-release or build metadata components. const extra: []const u8 = text[extra_index.?..text.len]; if (extra[0] == '-') { - const build_index = std.mem.indexOfScalar(u8, extra, '+'); + const build_index = std.mem.findScalar(u8, extra, '+'); ver.pre = extra[1..(build_index orelse extra.len)]; if (build_index) |idx| ver.build = extra[(idx + 1)..]; } else { diff --git a/lib/std/Target.zig b/lib/std/Target.zig index b37902d228e2..d1ce30f343eb 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -510,7 +510,7 @@ pub const Os = struct { break :blk default_min; }, - .max = .{ .major = 14, .minor = 3, .patch = 0 }, + .max = .{ .major = 15, .minor = 0, .patch = 0 }, }, }, .netbsd => .{ @@ -533,7 +533,19 @@ pub const Os = struct { }, .openbsd => .{ .semver = .{ - .min = .{ .major = 7, .minor = 7, .patch = 0 }, + .min = blk: { + const default_min: std.SemanticVersion = .{ .major = 7, .minor = 8, .patch = 0 }; + + for (std.zig.target.available_libcs) |libc| { + if (libc.arch != arch or libc.os != tag or libc.abi != abi) continue; + + if (libc.os_ver) |min| { + if (min.order(default_min) == .gt) break :blk min; + } + } + + break :blk default_min; + }, .max = .{ .major = 7, .minor = 8, .patch = 0 }, }, }, @@ -865,7 +877,6 @@ pub const Abi = enum { }, .freebsd => switch (arch) { .arm, - .powerpc, => .eabihf, else => .none, }, @@ -2120,6 +2131,10 @@ pub inline fn isMuslLibC(target: *const Target) bool { return target.os.tag == .linux and target.abi.isMusl(); } +pub inline fn isBionicLibC(target: *const Target) bool { + return target.os.tag == .linux and target.abi.isAndroid(); +} + pub inline fn isDarwinLibC(target: *const Target) bool { return switch (target.abi) { .none, .simulator => target.os.tag.isDarwin(), @@ -2141,6 +2156,13 @@ pub inline fn isNetBSDLibC(target: *const Target) bool { }; } +pub inline fn isOpenBSDLibC(target: *const Target) bool { + return switch (target.abi) { + .none, .eabi, .eabihf => target.os.tag == .openbsd, + else => false, + }; +} + pub inline fn isWasiLibC(target: *const Target) bool { return target.os.tag == .wasi and target.abi.isMusl(); } @@ -2724,7 +2746,6 @@ pub const DynamicLinker = struct { .powerpc64, .riscv64, .sh, - .sheb, .sparc64, .x86, .x86_64, diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index 93563bb245fb..c3b86d5b6ac9 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -7,6 +7,7 @@ const target = builtin.target; const native_os = builtin.os.tag; const std = @import("std.zig"); +const Io = std.Io; const math = std.math; const assert = std.debug.assert; const posix = std.posix; @@ -18,9 +19,10 @@ pub const Mutex = @import("Thread/Mutex.zig"); pub const Semaphore = @import("Thread/Semaphore.zig"); pub const Condition = @import("Thread/Condition.zig"); pub const RwLock = @import("Thread/RwLock.zig"); -pub const Pool = @import("Thread/Pool.zig"); pub const WaitGroup = @import("Thread/WaitGroup.zig"); +pub const Pool = @compileError("deprecated; consider using 'std.Io.Group' with 'std.Io.Threaded'"); + pub const use_pthreads = native_os != .windows and native_os != .wasi and builtin.link_libc; /// A thread-safe logical boolean value which can be `set` and `unset`. @@ -173,9 +175,9 @@ pub const SetNameError = error{ Unsupported, Unexpected, InvalidWtf8, -} || posix.PrctlError || posix.WriteError || std.fs.File.OpenError || std.fmt.BufPrintError; +} || posix.PrctlError || Io.File.Writer.Error || Io.File.OpenError || std.fmt.BufPrintError; -pub fn setName(self: Thread, name: []const u8) SetNameError!void { +pub fn setName(self: Thread, io: Io, name: []const u8) SetNameError!void { if (name.len > max_name_len) return error.NameTooLong; const name_with_terminator = blk: { @@ -206,10 +208,10 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void { var buf: [32]u8 = undefined; const path = try std.fmt.bufPrint(&buf, "/proc/self/task/{d}/comm", .{self.getHandle()}); - const file = try std.fs.cwd().openFile(path, .{ .mode = .write_only }); - defer file.close(); + const file = try Io.Dir.cwd().openFile(io, path, .{ .mode = .write_only }); + defer file.close(io); - try file.writeAll(name); + try file.writeStreamingAll(io, name); return; }, .windows => { @@ -226,7 +228,7 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void { switch (windows.ntdll.NtSetInformationThread( self.getHandle(), - .ThreadNameInformation, + .NameInformation, &unicode_string, @sizeOf(windows.UNICODE_STRING), )) { @@ -291,7 +293,7 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void { pub const GetNameError = error{ Unsupported, Unexpected, -} || posix.PrctlError || posix.ReadError || std.fs.File.OpenError || std.fmt.BufPrintError; +} || posix.PrctlError || posix.ReadError || Io.File.OpenError || std.fmt.BufPrintError; /// On Windows, the result is encoded as [WTF-8](https://wtf-8.codeberg.page/). /// On other platforms, the result is an opaque sequence of bytes with no particular encoding. @@ -320,11 +322,10 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co var buf: [32]u8 = undefined; const path = try std.fmt.bufPrint(&buf, "/proc/self/task/{d}/comm", .{self.getHandle()}); - var threaded: std.Io.Threaded = .init_single_threaded; - const io = threaded.ioBasic(); + const io = std.Options.debug_io; - const file = try std.fs.cwd().openFile(path, .{}); - defer file.close(); + const file = try Io.Dir.cwd().openFile(io, path, .{}); + defer file.close(io); var file_reader = file.readerStreaming(io, &.{}); const data_len = file_reader.interface.readSliceShort(buffer_ptr[0 .. max_name_len + 1]) catch |err| switch (err) { @@ -338,7 +339,7 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co switch (windows.ntdll.NtQueryInformationThread( self.getHandle(), - .ThreadNameInformation, + .NameInformation, &buf, buf_capacity, null, @@ -521,12 +522,10 @@ pub const YieldError = error{ /// Yields the current thread potentially allowing other threads to run. pub fn yield() YieldError!void { - if (native_os == .windows) { - // The return value has to do with how many other threads there are; it is not - // an error condition on Windows. - _ = windows.kernel32.SwitchToThread(); - return; - } + if (native_os == .windows) switch (windows.ntdll.NtYieldExecution()) { + .SUCCESS, .NO_YIELD_PERFORMED => return, + else => return error.SystemCannotYield, + }; switch (posix.errno(posix.system.sched_yield())) { .SUCCESS => return, .NOSYS => return error.SystemCannotYield, @@ -647,11 +646,11 @@ const WindowsThreadImpl = struct { const ThreadCompletion = struct { completion: Completion, heap_ptr: windows.PVOID, - heap_handle: windows.HANDLE, + heap_handle: *windows.HEAP, thread_handle: windows.HANDLE = undefined, fn free(self: ThreadCompletion) void { - const status = windows.kernel32.HeapFree(self.heap_handle, 0, self.heap_ptr); + const status = windows.ntdll.RtlFreeHeap(self.heap_handle, .{}, self.heap_ptr); assert(status != 0); } }; @@ -673,10 +672,10 @@ const WindowsThreadImpl = struct { } }; - const heap_handle = windows.kernel32.GetProcessHeap() orelse return error.OutOfMemory; + const heap_handle = windows.GetProcessHeap() orelse return error.OutOfMemory; const alloc_bytes = @alignOf(Instance) + @sizeOf(Instance); - const alloc_ptr = windows.ntdll.RtlAllocateHeap(heap_handle, 0, alloc_bytes) orelse return error.OutOfMemory; - errdefer assert(windows.kernel32.HeapFree(heap_handle, 0, alloc_ptr) != 0); + const alloc_ptr = windows.ntdll.RtlAllocateHeap(heap_handle, .{}, alloc_bytes) orelse return error.OutOfMemory; + errdefer assert(windows.ntdll.RtlFreeHeap(heap_handle, .{}, alloc_ptr) != 0); const instance_bytes = @as([*]u8, @ptrCast(alloc_ptr))[0..alloc_bytes]; var fba = std.heap.FixedBufferAllocator.init(instance_bytes); @@ -693,8 +692,7 @@ const WindowsThreadImpl = struct { // Windows appears to only support SYSTEM_INFO.dwAllocationGranularity minimum stack size. // Going lower makes it default to that specified in the executable (~1mb). // Its also fine if the limit here is incorrect as stack size is only a hint. - var stack_size = std.math.cast(u32, config.stack_size) orelse std.math.maxInt(u32); - stack_size = @max(64 * 1024, stack_size); + const stack_size = @max(64 * 1024, std.math.lossyCast(u32, config.stack_size)); instance.thread.thread_handle = windows.kernel32.CreateThread( null, @@ -1226,19 +1224,21 @@ const LinuxThreadImpl = struct { /// Ported over from musl libc's pthread detached implementation: /// https://github.com/ifduyue/musl/search?q=__unmapself fn freeAndExit(self: *ThreadCompletion) noreturn { + // If a signal were delivered between SYS_munmap and SYS_exit, any installed signal + // handler would immediately segfault due to the stack being unmapped. To avoid this, + // we need to mask all signals before entering the inline asm. + posix.sigprocmask(std.posix.SIG.BLOCK, &std.os.linux.sigfillset(), null); switch (target.cpu.arch) { .x86 => asm volatile ( \\ movl $91, %%eax # SYS_munmap - \\ movl %[ptr], %%ebx - \\ movl %[len], %%ecx \\ int $128 \\ movl $1, %%eax # SYS_exit \\ movl $0, %%ebx \\ int $128 : - : [ptr] "r" (@intFromPtr(self.mapped.ptr)), - [len] "r" (self.mapped.len), - : .{ .memory = true }), + : [ptr] "{ebx}" (@intFromPtr(self.mapped.ptr)), + [len] "{ecx}" (self.mapped.len), + ), .x86_64 => asm volatile (switch (target.abi) { .gnux32, .muslx32 => \\ movl $0x4000000b, %%eax # SYS_munmap @@ -1261,88 +1261,74 @@ const LinuxThreadImpl = struct { ), .arm, .armeb, .thumb, .thumbeb => asm volatile ( \\ mov r7, #91 // SYS_munmap - \\ mov r0, %[ptr] - \\ mov r1, %[len] \\ svc 0 \\ mov r7, #1 // SYS_exit \\ mov r0, #0 \\ svc 0 : - : [ptr] "r" (@intFromPtr(self.mapped.ptr)), - [len] "r" (self.mapped.len), - : .{ .memory = true }), + : [ptr] "{r0}" (@intFromPtr(self.mapped.ptr)), + [len] "{r1}" (self.mapped.len), + ), .aarch64, .aarch64_be => asm volatile ( \\ mov x8, #215 // SYS_munmap - \\ mov x0, %[ptr] - \\ mov x1, %[len] \\ svc 0 \\ mov x8, #93 // SYS_exit \\ mov x0, #0 \\ svc 0 : - : [ptr] "r" (@intFromPtr(self.mapped.ptr)), - [len] "r" (self.mapped.len), - : .{ .memory = true }), + : [ptr] "{x0}" (@intFromPtr(self.mapped.ptr)), + [len] "{x1}" (self.mapped.len), + ), .alpha => asm volatile ( \\ ldi $0, 73 # SYS_munmap - \\ mov %[ptr], $16 - \\ mov %[len], $17 \\ callsys \\ ldi $0, 1 # SYS_exit \\ ldi $16, 0 \\ callsys : - : [ptr] "r" (@intFromPtr(self.mapped.ptr)), - [len] "r" (self.mapped.len), - : .{ .memory = true }), + : [ptr] "{r16}" (@intFromPtr(self.mapped.ptr)), + [len] "{r17}" (self.mapped.len), + ), .hexagon => asm volatile ( \\ r6 = #215 // SYS_munmap - \\ r0 = %[ptr] - \\ r1 = %[len] \\ trap0(#1) \\ r6 = #93 // SYS_exit \\ r0 = #0 \\ trap0(#1) : - : [ptr] "r" (@intFromPtr(self.mapped.ptr)), - [len] "r" (self.mapped.len), - : .{ .memory = true }), + : [ptr] "{r0}" (@intFromPtr(self.mapped.ptr)), + [len] "{r1}" (self.mapped.len), + ), .hppa => asm volatile ( \\ ldi 91, %%r20 /* SYS_munmap */ - \\ copy %[ptr], %%r26 - \\ copy %[len], %%r25 \\ ble 0x100(%%sr2, %%r0) \\ ldi 1, %%r20 /* SYS_exit */ \\ ldi 0, %%r26 \\ ble 0x100(%%sr2, %%r0) : - : [ptr] "r" (@intFromPtr(self.mapped.ptr)), - [len] "r" (self.mapped.len), - : .{ .memory = true }), + : [ptr] "{r26}" (@intFromPtr(self.mapped.ptr)), + [len] "{r25}" (self.mapped.len), + ), .m68k => asm volatile ( \\ move.l #91, %%d0 // SYS_munmap - \\ move.l %[ptr], %%d1 - \\ move.l %[len], %%d2 \\ trap #0 \\ move.l #1, %%d0 // SYS_exit \\ move.l #0, %%d1 \\ trap #0 : - : [ptr] "r" (@intFromPtr(self.mapped.ptr)), - [len] "r" (self.mapped.len), - : .{ .memory = true }), + : [ptr] "{d1}" (@intFromPtr(self.mapped.ptr)), + [len] "{d2}" (self.mapped.len), + ), .microblaze, .microblazeel => asm volatile ( \\ ori r12, r0, 91 # SYS_munmap - \\ ori r5, %[ptr], 0 - \\ ori r6, %[len], 0 \\ brki r14, 0x8 \\ ori r12, r0, 1 # SYS_exit \\ or r5, r0, r0 \\ brki r14, 0x8 : - : [ptr] "r" (@intFromPtr(self.mapped.ptr)), - [len] "r" (self.mapped.len), - : .{ .memory = true }), + : [ptr] "{r5}" (@intFromPtr(self.mapped.ptr)), + [len] "{r6}" (self.mapped.len), + ), // We set `sp` to the address of the current function as a workaround for a Linux // kernel bug that caused syscalls to return EFAULT if the stack pointer is invalid. // The bug was introduced in 46e12c07b3b9603c60fc1d421ff18618241cb081 and fixed in @@ -1350,21 +1336,17 @@ const LinuxThreadImpl = struct { .mips, .mipsel => asm volatile ( \\ move $sp, $t9 \\ li $v0, 4091 # SYS_munmap - \\ move $a0, %[ptr] - \\ move $a1, %[len] \\ syscall \\ li $v0, 4001 # SYS_exit \\ li $a0, 0 \\ syscall : - : [ptr] "r" (@intFromPtr(self.mapped.ptr)), - [len] "r" (self.mapped.len), - : .{ .memory = true }), + : [ptr] "{$4}" (@intFromPtr(self.mapped.ptr)), + [len] "{$5}" (self.mapped.len), + ), .mips64, .mips64el => asm volatile (switch (target.abi) { .gnuabin32, .muslabin32 => \\ li $v0, 6011 # SYS_munmap - \\ move $a0, %[ptr] - \\ move $a1, %[len] \\ syscall \\ li $v0, 6058 # SYS_exit \\ li $a0, 0 @@ -1372,8 +1354,6 @@ const LinuxThreadImpl = struct { , else => \\ li $v0, 5011 # SYS_munmap - \\ move $a0, %[ptr] - \\ move $a1, %[len] \\ syscall \\ li $v0, 5058 # SYS_exit \\ li $a0, 0 @@ -1381,60 +1361,50 @@ const LinuxThreadImpl = struct { , } : - : [ptr] "r" (@intFromPtr(self.mapped.ptr)), - [len] "r" (self.mapped.len), - : .{ .memory = true }), + : [ptr] "{$4}" (@intFromPtr(self.mapped.ptr)), + [len] "{$5}" (self.mapped.len), + ), .or1k => asm volatile ( \\ l.ori r11, r0, 215 # SYS_munmap - \\ l.ori r3, %[ptr] - \\ l.ori r4, %[len] \\ l.sys 1 \\ l.ori r11, r0, 93 # SYS_exit \\ l.ori r3, r0, r0 \\ l.sys 1 : - : [ptr] "r" (@intFromPtr(self.mapped.ptr)), - [len] "r" (self.mapped.len), - : .{ .memory = true }), + : [ptr] "{r3}" (@intFromPtr(self.mapped.ptr)), + [len] "{r4}" (self.mapped.len), + ), .powerpc, .powerpcle, .powerpc64, .powerpc64le => asm volatile ( \\ li 0, 91 # SYS_munmap - \\ mr 3, %[ptr] - \\ mr 4, %[len] \\ sc \\ li 0, 1 # SYS_exit \\ li 3, 0 \\ sc \\ blr : - : [ptr] "r" (@intFromPtr(self.mapped.ptr)), - [len] "r" (self.mapped.len), - : .{ .memory = true }), + : [ptr] "{r3}" (@intFromPtr(self.mapped.ptr)), + [len] "{r4}" (self.mapped.len), + ), .riscv32, .riscv64 => asm volatile ( \\ li a7, 215 # SYS_munmap - \\ mv a0, %[ptr] - \\ mv a1, %[len] \\ ecall \\ li a7, 93 # SYS_exit \\ mv a0, zero \\ ecall : - : [ptr] "r" (@intFromPtr(self.mapped.ptr)), - [len] "r" (self.mapped.len), - : .{ .memory = true }), + : [ptr] "{a0}" (@intFromPtr(self.mapped.ptr)), + [len] "{a1}" (self.mapped.len), + ), .s390x => asm volatile ( - \\ lgr %%r2, %[ptr] - \\ lgr %%r3, %[len] \\ svc 91 # SYS_munmap \\ lghi %%r2, 0 \\ svc 1 # SYS_exit : - : [ptr] "r" (@intFromPtr(self.mapped.ptr)), - [len] "r" (self.mapped.len), - : .{ .memory = true }), + : [ptr] "{r2}" (@intFromPtr(self.mapped.ptr)), + [len] "{r3}" (self.mapped.len), + ), .sh, .sheb => asm volatile ( \\ mov #91, r3 ! SYS_munmap - \\ mov %[ptr], r4 - \\ mov %[len], r5 \\ trapa #31 \\ or r0, r0 \\ or r0, r0 @@ -1450,9 +1420,9 @@ const LinuxThreadImpl = struct { \\ or r0, r0 \\ or r0, r0 : - : [ptr] "r" (@intFromPtr(self.mapped.ptr)), - [len] "r" (self.mapped.len), - : .{ .memory = true }), + : [ptr] "{r4}" (@intFromPtr(self.mapped.ptr)), + [len] "{r5}" (self.mapped.len), + ), .sparc => asm volatile ( \\ # See sparc64 comments below. \\ 1: @@ -1462,17 +1432,17 @@ const LinuxThreadImpl = struct { \\ ba 1b \\ restore \\ 2: + \\ mov %%g1, %%o0 // ptr + \\ mov %%g2, %%o1 // len \\ mov 73, %%g1 // SYS_munmap - \\ mov %[ptr], %%o0 - \\ mov %[len], %%o1 \\ t 0x3 # ST_FLUSH_WINDOWS \\ t 0x10 \\ mov 1, %%g1 // SYS_exit \\ mov 0, %%o0 \\ t 0x10 : - : [ptr] "r" (@intFromPtr(self.mapped.ptr)), - [len] "r" (self.mapped.len), + : [ptr] "{g1}" (@intFromPtr(self.mapped.ptr)), + [len] "{g2}" (self.mapped.len), : .{ .memory = true }), .sparc64 => asm volatile ( \\ # SPARCs really don't like it when active stack frames @@ -1486,9 +1456,9 @@ const LinuxThreadImpl = struct { \\ ba 1b \\ restore \\ 2: + \\ mov %%g1, %%o0 // ptr + \\ mov %%g2, %%o1 // len \\ mov 73, %%g1 // SYS_munmap - \\ mov %[ptr], %%o0 - \\ mov %[len], %%o1 \\ # Flush register window contents to prevent background \\ # memory access before unmapping the stack. \\ flushw @@ -1497,20 +1467,18 @@ const LinuxThreadImpl = struct { \\ mov 0, %%o0 \\ t 0x6d : - : [ptr] "r" (@intFromPtr(self.mapped.ptr)), - [len] "r" (self.mapped.len), + : [ptr] "{g1}" (@intFromPtr(self.mapped.ptr)), + [len] "{g2}" (self.mapped.len), : .{ .memory = true }), .loongarch32, .loongarch64 => asm volatile ( - \\ or $a0, $zero, %[ptr] - \\ or $a1, $zero, %[len] \\ ori $a7, $zero, 215 # SYS_munmap \\ syscall 0 # call munmap \\ ori $a0, $zero, 0 \\ ori $a7, $zero, 93 # SYS_exit \\ syscall 0 # call exit : - : [ptr] "r" (@intFromPtr(self.mapped.ptr)), - [len] "r" (self.mapped.len), + : [ptr] "{r4}" (@intFromPtr(self.mapped.ptr)), + [len] "{r5}" (self.mapped.len), : .{ .memory = true }), else => |cpu_arch| @compileError("Unsupported linux arch: " ++ @tagName(cpu_arch)), } @@ -1677,14 +1645,14 @@ const LinuxThreadImpl = struct { } }; -fn testThreadName(thread: *Thread) !void { +fn testThreadName(io: Io, thread: *Thread) !void { const testCases = &[_][]const u8{ "mythread", "b" ** max_name_len, }; inline for (testCases) |tc| { - try thread.setName(tc); + try thread.setName(io, tc); var name_buffer: [max_name_len:0]u8 = undefined; @@ -1699,6 +1667,8 @@ fn testThreadName(thread: *Thread) !void { test "setName, getName" { if (builtin.single_threaded) return error.SkipZigTest; + const io = testing.io; + const Context = struct { start_wait_event: ResetEvent = .unset, test_done_event: ResetEvent = .unset, @@ -1712,11 +1682,11 @@ test "setName, getName" { ctx.start_wait_event.wait(); switch (native_os) { - .windows => testThreadName(&ctx.thread) catch |err| switch (err) { + .windows => testThreadName(io, &ctx.thread) catch |err| switch (err) { error.Unsupported => return error.SkipZigTest, else => return err, }, - else => try testThreadName(&ctx.thread), + else => try testThreadName(io, &ctx.thread), } // Signal our test is done @@ -1736,14 +1706,14 @@ test "setName, getName" { switch (native_os) { .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => { - const res = thread.setName("foobar"); + const res = thread.setName(io, "foobar"); try std.testing.expectError(error.Unsupported, res); }, - .windows => testThreadName(&thread) catch |err| switch (err) { + .windows => testThreadName(io, &thread) catch |err| switch (err) { error.Unsupported => return error.SkipZigTest, else => return err, }, - else => try testThreadName(&thread), + else => try testThreadName(io, &thread), } context.thread_done_event.set(); @@ -1757,7 +1727,6 @@ test { _ = Semaphore; _ = Condition; _ = RwLock; - _ = Pool; } fn testIncrementNotify(value: *usize, event: *ResetEvent) void { diff --git a/lib/std/Thread/Futex.zig b/lib/std/Thread/Futex.zig index b61062c361a0..7c44621d7221 100644 --- a/lib/std/Thread/Futex.zig +++ b/lib/std/Thread/Futex.zig @@ -20,8 +20,7 @@ const testing = std.testing; const atomic = std.atomic; /// Checks if `ptr` still contains the value `expect` and, if so, blocks the caller until either: -/// - The value at `ptr` is no longer equal to `expect`. -/// - The caller is unblocked by a matching `wake()`. +/// - The value at `ptr` is no longer equal to `expect` and `wake()` is called on the same address. /// - The caller is unblocked spuriously ("at random"). /// /// The checking of `ptr` and `expect`, along with blocking the caller, is done atomically diff --git a/lib/std/Thread/Pool.zig b/lib/std/Thread/Pool.zig deleted file mode 100644 index e836665d70cf..000000000000 --- a/lib/std/Thread/Pool.zig +++ /dev/null @@ -1,326 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const Pool = @This(); -const WaitGroup = @import("WaitGroup.zig"); - -mutex: std.Thread.Mutex = .{}, -cond: std.Thread.Condition = .{}, -run_queue: std.SinglyLinkedList = .{}, -is_running: bool = true, -allocator: std.mem.Allocator, -threads: if (builtin.single_threaded) [0]std.Thread else []std.Thread, -ids: if (builtin.single_threaded) struct { - inline fn deinit(_: @This(), _: std.mem.Allocator) void {} - fn getIndex(_: @This(), _: std.Thread.Id) usize { - return 0; - } -} else std.AutoArrayHashMapUnmanaged(std.Thread.Id, void), - -const Runnable = struct { - runFn: RunProto, - node: std.SinglyLinkedList.Node = .{}, -}; - -const RunProto = *const fn (*Runnable, id: ?usize) void; - -pub const Options = struct { - allocator: std.mem.Allocator, - n_jobs: ?usize = null, - track_ids: bool = false, - stack_size: usize = std.Thread.SpawnConfig.default_stack_size, -}; - -pub fn init(pool: *Pool, options: Options) !void { - const allocator = options.allocator; - - pool.* = .{ - .allocator = allocator, - .threads = if (builtin.single_threaded) .{} else &.{}, - .ids = .{}, - }; - - if (builtin.single_threaded) { - return; - } - - const thread_count = options.n_jobs orelse @max(1, std.Thread.getCpuCount() catch 1); - if (options.track_ids) { - try pool.ids.ensureTotalCapacity(allocator, 1 + thread_count); - pool.ids.putAssumeCapacityNoClobber(std.Thread.getCurrentId(), {}); - } - - // kill and join any threads we spawned and free memory on error. - pool.threads = try allocator.alloc(std.Thread, thread_count); - var spawned: usize = 0; - errdefer pool.join(spawned); - - for (pool.threads) |*thread| { - thread.* = try std.Thread.spawn(.{ - .stack_size = options.stack_size, - .allocator = allocator, - }, worker, .{pool}); - spawned += 1; - } -} - -pub fn deinit(pool: *Pool) void { - pool.join(pool.threads.len); // kill and join all threads. - pool.ids.deinit(pool.allocator); - pool.* = undefined; -} - -fn join(pool: *Pool, spawned: usize) void { - if (builtin.single_threaded) { - return; - } - - { - pool.mutex.lock(); - defer pool.mutex.unlock(); - - // ensure future worker threads exit the dequeue loop - pool.is_running = false; - } - - // wake up any sleeping threads (this can be done outside the mutex) - // then wait for all the threads we know are spawned to complete. - pool.cond.broadcast(); - for (pool.threads[0..spawned]) |thread| { - thread.join(); - } - - pool.allocator.free(pool.threads); -} - -/// Runs `func` in the thread pool, calling `WaitGroup.start` beforehand, and -/// `WaitGroup.finish` after it returns. -/// -/// In the case that queuing the function call fails to allocate memory, or the -/// target is single-threaded, the function is called directly. -pub fn spawnWg(pool: *Pool, wait_group: *WaitGroup, comptime func: anytype, args: anytype) void { - wait_group.start(); - - if (builtin.single_threaded) { - @call(.auto, func, args); - wait_group.finish(); - return; - } - - const Args = @TypeOf(args); - const Closure = struct { - arguments: Args, - pool: *Pool, - runnable: Runnable = .{ .runFn = runFn }, - wait_group: *WaitGroup, - - fn runFn(runnable: *Runnable, _: ?usize) void { - const closure: *@This() = @alignCast(@fieldParentPtr("runnable", runnable)); - @call(.auto, func, closure.arguments); - closure.wait_group.finish(); - - // The thread pool's allocator is protected by the mutex. - const mutex = &closure.pool.mutex; - mutex.lock(); - defer mutex.unlock(); - - closure.pool.allocator.destroy(closure); - } - }; - - { - pool.mutex.lock(); - - const closure = pool.allocator.create(Closure) catch { - pool.mutex.unlock(); - @call(.auto, func, args); - wait_group.finish(); - return; - }; - closure.* = .{ - .arguments = args, - .pool = pool, - .wait_group = wait_group, - }; - - pool.run_queue.prepend(&closure.runnable.node); - pool.mutex.unlock(); - } - - // Notify waiting threads outside the lock to try and keep the critical section small. - pool.cond.signal(); -} - -/// Runs `func` in the thread pool, calling `WaitGroup.start` beforehand, and -/// `WaitGroup.finish` after it returns. -/// -/// The first argument passed to `func` is a dense `usize` thread id, the rest -/// of the arguments are passed from `args`. Requires the pool to have been -/// initialized with `.track_ids = true`. -/// -/// In the case that queuing the function call fails to allocate memory, or the -/// target is single-threaded, the function is called directly. -pub fn spawnWgId(pool: *Pool, wait_group: *WaitGroup, comptime func: anytype, args: anytype) void { - wait_group.start(); - - if (builtin.single_threaded) { - @call(.auto, func, .{0} ++ args); - wait_group.finish(); - return; - } - - const Args = @TypeOf(args); - const Closure = struct { - arguments: Args, - pool: *Pool, - runnable: Runnable = .{ .runFn = runFn }, - wait_group: *WaitGroup, - - fn runFn(runnable: *Runnable, id: ?usize) void { - const closure: *@This() = @alignCast(@fieldParentPtr("runnable", runnable)); - @call(.auto, func, .{id.?} ++ closure.arguments); - closure.wait_group.finish(); - - // The thread pool's allocator is protected by the mutex. - const mutex = &closure.pool.mutex; - mutex.lock(); - defer mutex.unlock(); - - closure.pool.allocator.destroy(closure); - } - }; - - { - pool.mutex.lock(); - - const closure = pool.allocator.create(Closure) catch { - const id: ?usize = pool.ids.getIndex(std.Thread.getCurrentId()); - pool.mutex.unlock(); - @call(.auto, func, .{id.?} ++ args); - wait_group.finish(); - return; - }; - closure.* = .{ - .arguments = args, - .pool = pool, - .wait_group = wait_group, - }; - - pool.run_queue.prepend(&closure.runnable.node); - pool.mutex.unlock(); - } - - // Notify waiting threads outside the lock to try and keep the critical section small. - pool.cond.signal(); -} - -pub fn spawn(pool: *Pool, comptime func: anytype, args: anytype) !void { - if (builtin.single_threaded) { - @call(.auto, func, args); - return; - } - - const Args = @TypeOf(args); - const Closure = struct { - arguments: Args, - pool: *Pool, - runnable: Runnable = .{ .runFn = runFn }, - - fn runFn(runnable: *Runnable, _: ?usize) void { - const closure: *@This() = @alignCast(@fieldParentPtr("runnable", runnable)); - @call(.auto, func, closure.arguments); - - // The thread pool's allocator is protected by the mutex. - const mutex = &closure.pool.mutex; - mutex.lock(); - defer mutex.unlock(); - - closure.pool.allocator.destroy(closure); - } - }; - - { - pool.mutex.lock(); - defer pool.mutex.unlock(); - - const closure = try pool.allocator.create(Closure); - closure.* = .{ - .arguments = args, - .pool = pool, - }; - - pool.run_queue.prepend(&closure.runnable.node); - } - - // Notify waiting threads outside the lock to try and keep the critical section small. - pool.cond.signal(); -} - -test spawn { - const TestFn = struct { - fn checkRun(completed: *bool) void { - completed.* = true; - } - }; - - var completed: bool = false; - - { - var pool: Pool = undefined; - try pool.init(.{ - .allocator = std.testing.allocator, - }); - defer pool.deinit(); - try pool.spawn(TestFn.checkRun, .{&completed}); - } - - try std.testing.expectEqual(true, completed); -} - -fn worker(pool: *Pool) void { - pool.mutex.lock(); - defer pool.mutex.unlock(); - - const id: ?usize = if (pool.ids.count() > 0) @intCast(pool.ids.count()) else null; - if (id) |_| pool.ids.putAssumeCapacityNoClobber(std.Thread.getCurrentId(), {}); - - while (true) { - while (pool.run_queue.popFirst()) |run_node| { - // Temporarily unlock the mutex in order to execute the run_node - pool.mutex.unlock(); - defer pool.mutex.lock(); - - const runnable: *Runnable = @fieldParentPtr("node", run_node); - runnable.runFn(runnable, id); - } - - // Stop executing instead of waiting if the thread pool is no longer running. - if (pool.is_running) { - pool.cond.wait(&pool.mutex); - } else { - break; - } - } -} - -pub fn waitAndWork(pool: *Pool, wait_group: *WaitGroup) void { - var id: ?usize = null; - - while (!wait_group.isDone()) { - pool.mutex.lock(); - if (pool.run_queue.popFirst()) |run_node| { - id = id orelse pool.ids.getIndex(std.Thread.getCurrentId()); - pool.mutex.unlock(); - const runnable: *Runnable = @fieldParentPtr("node", run_node); - runnable.runFn(runnable, id); - continue; - } - - pool.mutex.unlock(); - wait_group.wait(); - return; - } -} - -pub fn getIdCount(pool: *Pool) usize { - return @intCast(1 + pool.threads.len); -} diff --git a/lib/std/Uri.zig b/lib/std/Uri.zig index bf183cb09fba..8783023274e4 100644 --- a/lib/std/Uri.zig +++ b/lib/std/Uri.zig @@ -65,7 +65,7 @@ pub const Component = union(enum) { pub fn toRaw(component: Component, buffer: []u8) error{NoSpaceLeft}![]const u8 { return switch (component) { .raw => |raw| raw, - .percent_encoded => |percent_encoded| if (std.mem.indexOfScalar(u8, percent_encoded, '%')) |_| + .percent_encoded => |percent_encoded| if (std.mem.findScalar(u8, percent_encoded, '%')) |_| try std.fmt.bufPrint(buffer, "{f}", .{std.fmt.alt(component, .formatRaw)}) else percent_encoded, @@ -76,7 +76,7 @@ pub const Component = union(enum) { pub fn toRawMaybeAlloc(component: Component, arena: Allocator) Allocator.Error![]const u8 { return switch (component) { .raw => |raw| raw, - .percent_encoded => |percent_encoded| if (std.mem.indexOfScalar(u8, percent_encoded, '%')) |_| + .percent_encoded => |percent_encoded| if (std.mem.findScalar(u8, percent_encoded, '%')) |_| try std.fmt.allocPrint(arena, "{f}", .{std.fmt.alt(component, .formatRaw)}) else percent_encoded, @@ -89,7 +89,7 @@ pub const Component = union(enum) { .percent_encoded => |percent_encoded| { var start: usize = 0; var index: usize = 0; - while (std.mem.indexOfScalarPos(u8, percent_encoded, index, '%')) |percent| { + while (std.mem.findScalarPos(u8, percent_encoded, index, '%')) |percent| { index = percent + 1; if (percent_encoded.len - index < 2) continue; const percent_encoded_char = @@ -213,7 +213,7 @@ pub fn parseAfterScheme(scheme: []const u8, text: []const u8) ParseError!Uri { var i: usize = 0; if (std.mem.startsWith(u8, text, "//")) a: { - i = std.mem.indexOfAnyPos(u8, text, 2, &authority_sep) orelse text.len; + i = std.mem.findAnyPos(u8, text, 2, &authority_sep) orelse text.len; const authority = text[2..i]; if (authority.len == 0) { if (!std.mem.startsWith(u8, text[2..], "/")) return error.InvalidFormat; @@ -221,11 +221,11 @@ pub fn parseAfterScheme(scheme: []const u8, text: []const u8) ParseError!Uri { } var start_of_host: usize = 0; - if (std.mem.indexOf(u8, authority, "@")) |index| { + if (std.mem.find(u8, authority, "@")) |index| { start_of_host = index + 1; const user_info = authority[0..index]; - if (std.mem.indexOf(u8, user_info, ":")) |idx| { + if (std.mem.find(u8, user_info, ":")) |idx| { uri.user = .{ .percent_encoded = user_info[0..idx] }; if (idx < user_info.len - 1) { // empty password is also "no password" uri.password = .{ .percent_encoded = user_info[idx + 1 ..] }; @@ -268,12 +268,12 @@ pub fn parseAfterScheme(scheme: []const u8, text: []const u8) ParseError!Uri { } const path_start = i; - i = std.mem.indexOfAnyPos(u8, text, path_start, &path_sep) orelse text.len; + i = std.mem.findAnyPos(u8, text, path_start, &path_sep) orelse text.len; uri.path = .{ .percent_encoded = text[path_start..i] }; if (std.mem.startsWith(u8, text[i..], "?")) { const query_start = i + 1; - i = std.mem.indexOfScalarPos(u8, text, query_start, '#') orelse text.len; + i = std.mem.findScalarPos(u8, text, query_start, '#') orelse text.len; uri.query = .{ .percent_encoded = text[query_start..i] }; } diff --git a/lib/std/array_list.zig b/lib/std/array_list.zig index 73abbd45532b..d84bafca0eee 100644 --- a/lib/std/array_list.zig +++ b/lib/std/array_list.zig @@ -599,11 +599,10 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { return if (alignment) |a| ([:s]align(a.toByteUnits()) T) else [:s]T; } - /// Initialize with capacity to hold `num` elements. - /// The resulting capacity will equal `num` exactly. - /// Deinitialize with `deinit` or use `toOwnedSlice`. + /// Initialize with capacity to hold exactly `num` elements. + /// Deinitialize with `deinit` or `toOwnedSlice`. pub fn initCapacity(gpa: Allocator, num: usize) Allocator.Error!Self { - var self = Self{}; + var self: Self = .empty; try self.ensureTotalCapacityPrecise(gpa, num); return self; } diff --git a/lib/std/ascii.zig b/lib/std/ascii.zig index f9b3ca987874..b85ff592d846 100644 --- a/lib/std/ascii.zig +++ b/lib/std/ascii.zig @@ -156,7 +156,7 @@ test whitespace { var i: u8 = 0; while (isAscii(i)) : (i += 1) { - if (isWhitespace(i)) try std.testing.expect(std.mem.indexOfScalar(u8, &whitespace, i) != null); + if (isWhitespace(i)) try std.testing.expect(std.mem.findScalar(u8, &whitespace, i) != null); } } @@ -357,19 +357,25 @@ test endsWithIgnoreCase { try std.testing.expect(!endsWithIgnoreCase("BoB", "Bo")); } +/// Deprecated in favor of `findIgnoreCase`. +pub const indexOfIgnoreCase = findIgnoreCase; + /// Finds `needle` in `haystack`, ignoring case, starting at index 0. -pub fn indexOfIgnoreCase(haystack: []const u8, needle: []const u8) ?usize { - return indexOfIgnoreCasePos(haystack, 0, needle); +pub fn findIgnoreCase(haystack: []const u8, needle: []const u8) ?usize { + return findIgnoreCasePos(haystack, 0, needle); } +/// Deprecated in favor of `findIgnoreCasePos`. +pub const indexOfIgnoreCasePos = findIgnoreCasePos; + /// Finds `needle` in `haystack`, ignoring case, starting at `start_index`. -/// Uses Boyer-Moore-Horspool algorithm on large inputs; `indexOfIgnoreCasePosLinear` on small inputs. -pub fn indexOfIgnoreCasePos(haystack: []const u8, start_index: usize, needle: []const u8) ?usize { +/// Uses Boyer-Moore-Horspool algorithm on large inputs; `findIgnoreCasePosLinear` on small inputs. +pub fn findIgnoreCasePos(haystack: []const u8, start_index: usize, needle: []const u8) ?usize { if (needle.len > haystack.len) return null; if (needle.len == 0) return start_index; if (haystack.len < 52 or needle.len <= 4) - return indexOfIgnoreCasePosLinear(haystack, start_index, needle); + return findIgnoreCasePosLinear(haystack, start_index, needle); var skip_table: [256]usize = undefined; boyerMooreHorspoolPreprocessIgnoreCase(needle, skip_table[0..]); @@ -383,9 +389,12 @@ pub fn indexOfIgnoreCasePos(haystack: []const u8, start_index: usize, needle: [] return null; } -/// Consider using `indexOfIgnoreCasePos` instead of this, which will automatically use a +/// Deprecated in favor of `findIgnoreCaseLinear`. +pub const indexOfIgnoreCasePosLinear = findIgnoreCasePosLinear; + +/// Consider using `findIgnoreCasePos` instead of this, which will automatically use a /// more sophisticated algorithm on larger inputs. -pub fn indexOfIgnoreCasePosLinear(haystack: []const u8, start_index: usize, needle: []const u8) ?usize { +pub fn findIgnoreCasePosLinear(haystack: []const u8, start_index: usize, needle: []const u8) ?usize { var i: usize = start_index; const end = haystack.len - needle.len; while (i <= end) : (i += 1) { @@ -407,15 +416,15 @@ fn boyerMooreHorspoolPreprocessIgnoreCase(pattern: []const u8, table: *[256]usiz } } -test indexOfIgnoreCase { - try std.testing.expect(indexOfIgnoreCase("one Two Three Four", "foUr").? == 14); - try std.testing.expect(indexOfIgnoreCase("one two three FouR", "gOur") == null); - try std.testing.expect(indexOfIgnoreCase("foO", "Foo").? == 0); - try std.testing.expect(indexOfIgnoreCase("foo", "fool") == null); - try std.testing.expect(indexOfIgnoreCase("FOO foo", "fOo").? == 0); +test findIgnoreCase { + try std.testing.expect(findIgnoreCase("one Two Three Four", "foUr").? == 14); + try std.testing.expect(findIgnoreCase("one two three FouR", "gOur") == null); + try std.testing.expect(findIgnoreCase("foO", "Foo").? == 0); + try std.testing.expect(findIgnoreCase("foo", "fool") == null); + try std.testing.expect(findIgnoreCase("FOO foo", "fOo").? == 0); - try std.testing.expect(indexOfIgnoreCase("one two three four five six seven eight nine ten eleven", "ThReE fOUr").? == 8); - try std.testing.expect(indexOfIgnoreCase("one two three four five six seven eight nine ten eleven", "Two tWo") == null); + try std.testing.expect(findIgnoreCase("one two three four five six seven eight nine ten eleven", "ThReE fOUr").? == 8); + try std.testing.expect(findIgnoreCase("one two three four five six seven eight nine ten eleven", "Two tWo") == null); } /// Returns the lexicographical order of two slices. O(n). diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index 1ef77de9a569..e10935f0c6a6 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -841,6 +841,9 @@ pub const FloatMode = enum { pub const Endian = enum { big, little, + + pub const native = builtin.target.cpu.arch.endian(); + pub const foreign: Endian = @enumFromInt(1 - @intFromEnum(native)); }; /// This data structure is used by the Zig language code generation and @@ -1098,6 +1101,17 @@ pub const ExternOptions = struct { is_thread_local: bool = false, is_dll_import: bool = false, relocation: Relocation = .any, + decoration: ?Decoration = null, + + pub const Decoration = union(enum) { + location: u32, + descriptor: Descriptor, + + pub const Descriptor = struct { + binding: u32, + set: u32, + }; + }; pub const Relocation = enum(u1) { /// Any type of relocation is allowed. diff --git a/lib/std/c.zig b/lib/std/c.zig index f22112a086f7..841739838461 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -114,6 +114,18 @@ pub const timespec = switch (native_os) { return @as(wasi.timestamp_t, @intCast(ts.sec * 1_000_000_000)) + @as(wasi.timestamp_t, @intCast(ts.nsec)); } + + /// For use with `utimensat` and `futimens`. + pub const NOW: timespec = .{ + .sec = 0, + .nsec = 0x3fffffff, + }; + + /// For use with `utimensat` and `futimens`. + pub const OMIT: timespec = .{ + .sec = 0, + .nsec = 0x3ffffffe, + }; }, // https://github.com/SerenityOS/serenity/blob/0a78056453578c18e0a04a0b45ebfb1c96d59005/Kernel/API/POSIX/time.h#L17-L20 .windows, .serenity => extern struct { @@ -123,14 +135,50 @@ pub const timespec = switch (native_os) { .dragonfly, .freebsd, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => extern struct { sec: isize, nsec: isize, + + /// For use with `utimensat` and `futimens`. + pub const NOW: timespec = .{ + .sec = 0, + .nsec = -1, + }; + + /// For use with `utimensat` and `futimens`. + pub const OMIT: timespec = .{ + .sec = 0, + .nsec = -2, + }; }, .netbsd, .illumos => extern struct { sec: i64, nsec: isize, + + /// For use with `utimensat` and `futimens`. + pub const NOW: timespec = .{ + .sec = 0, + .nsec = 0x3fffffff, + }; + + /// For use with `utimensat` and `futimens`. + pub const OMIT: timespec = .{ + .sec = 0, + .nsec = 0x3ffffffe, + }; }, .openbsd, .haiku => extern struct { sec: time_t, nsec: isize, + + /// For use with `utimensat` and `futimens`. + pub const NOW: timespec = .{ + .sec = 0, // ignored + .nsec = -2, + }; + + /// For use with `utimensat` and `futimens`. + pub const OMIT: timespec = .{ + .sec = 0, // ignored + .nsec = -1, + }; }, else => void, }; @@ -148,9 +196,10 @@ pub const dev_t = switch (native_os) { pub const mode_t = switch (native_os) { .linux => linux.mode_t, .emscripten => emscripten.mode_t, - .openbsd, .haiku, .netbsd, .illumos, .wasi, .windows => u32, + .openbsd, .haiku, .netbsd, .illumos, .windows => u32, // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L44 .freebsd, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos, .dragonfly, .serenity => u16, + .wasi => if (builtin.link_libc) u32 else u0, // WASI libc emulates mode. else => u0, }; @@ -160,9 +209,10 @@ pub const nlink_t = switch (native_os) { .wasi => c_ulonglong, // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L45 .freebsd, .serenity => u64, - .openbsd, .netbsd, .illumos => u32, + .openbsd, .netbsd, .dragonfly, .illumos => u32, .haiku => i32, - else => void, + .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => u16, + else => u0, }; pub const uid_t = switch (native_os) { @@ -2327,6 +2377,8 @@ pub const S = switch (native_os) { pub const IWOTH = 0o002; pub const IXOTH = 0o001; + pub const BLKSIZE = 512; + pub fn ISFIFO(m: u32) bool { return m & IFMT == IFIFO; } @@ -2631,6 +2683,7 @@ pub const SIG = switch (native_os) { ABRT = 22, /// SIGABRT compatible with other platforms, same as SIGABRT ABRT_COMPAT = 6, + _, // Signal action codes /// default signal action @@ -2724,6 +2777,7 @@ pub const SIG = switch (native_os) { USR1 = 30, /// user defined signal 2 USR2 = 31, + _, }, .freebsd => enum(u32) { pub const BLOCK = 1; @@ -2789,6 +2843,7 @@ pub const SIG = switch (native_os) { USR2 = 31, THR = 32, LIBRT = 33, + _, }, .illumos => enum(u32) { pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0); @@ -2864,6 +2919,7 @@ pub const SIG = switch (native_os) { JVM1 = 39, JVM2 = 40, INFO = 41, + _, }, .netbsd => enum(u32) { pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0); @@ -2927,6 +2983,7 @@ pub const SIG = switch (native_os) { USR1 = 30, USR2 = 31, PWR = 32, + _, }, .dragonfly => enum(u32) { pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0); @@ -2975,6 +3032,7 @@ pub const SIG = switch (native_os) { THR = 32, CKPT = 33, CKPTEXIT = 34, + _, }, .haiku => enum(u32) { pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0); @@ -3021,6 +3079,7 @@ pub const SIG = switch (native_os) { BUS = 30, RESERVED1 = 31, RESERVED2 = 32, + _, }, .openbsd => enum(u32) { pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0); @@ -3067,6 +3126,7 @@ pub const SIG = switch (native_os) { USR1 = 30, USR2 = 31, PWR = 32, + _, }, // https://github.com/SerenityOS/serenity/blob/046c23f567a17758d762a33bdf04bacbfd088f9f/Kernel/API/POSIX/signal.h // https://github.com/SerenityOS/serenity/blob/046c23f567a17758d762a33bdf04bacbfd088f9f/Kernel/API/POSIX/signal_numbers.h @@ -3112,6 +3172,7 @@ pub const SIG = switch (native_os) { INFO = 30, SYS = 31, CANCEL = 32, + _, }, else => void, }; @@ -3712,8 +3773,8 @@ pub const W = switch (native_os) { pub fn EXITSTATUS(x: u32) u8 { return @as(u8, @intCast(x >> 8)); } - pub fn TERMSIG(x: u32) u32 { - return status(x); + pub fn TERMSIG(x: u32) SIG { + return @enumFromInt(status(x)); } pub fn STOPSIG(x: u32) u32 { return x >> 8; @@ -3745,14 +3806,14 @@ pub const W = switch (native_os) { pub fn EXITSTATUS(s: u32) u8 { return @as(u8, @intCast((s & 0xff00) >> 8)); } - pub fn TERMSIG(s: u32) u32 { - return s & 0x7f; + pub fn TERMSIG(s: u32) SIG { + return @enumFromInt(s & 0x7f); } pub fn STOPSIG(s: u32) u32 { return EXITSTATUS(s); } pub fn IFEXITED(s: u32) bool { - return TERMSIG(s) == 0; + return (s & 0x7f) == 0; } pub fn IFSTOPPED(s: u32) bool { return @as(u16, @truncate((((s & 0xffff) *% 0x10001) >> 8))) > 0x7f00; @@ -3773,14 +3834,14 @@ pub const W = switch (native_os) { pub fn EXITSTATUS(s: u32) u8 { return @as(u8, @intCast((s >> 8) & 0xff)); } - pub fn TERMSIG(s: u32) u32 { - return s & 0x7f; + pub fn TERMSIG(s: u32) SIG { + return @enumFromInt(s & 0x7f); } pub fn STOPSIG(s: u32) u32 { return EXITSTATUS(s); } pub fn IFEXITED(s: u32) bool { - return TERMSIG(s) == 0; + return (s & 0x7f) == 0; } pub fn IFCONTINUED(s: u32) bool { @@ -3807,14 +3868,14 @@ pub const W = switch (native_os) { pub fn EXITSTATUS(s: u32) u8 { return @as(u8, @intCast((s >> 8) & 0xff)); } - pub fn TERMSIG(s: u32) u32 { - return s & 0x7f; + pub fn TERMSIG(s: u32) SIG { + return @enumFromInt(s & 0x7f); } pub fn STOPSIG(s: u32) u32 { return EXITSTATUS(s); } pub fn IFEXITED(s: u32) bool { - return TERMSIG(s) == 0; + return (s & 0x7f) == 0; } pub fn IFCONTINUED(s: u32) bool { @@ -3841,14 +3902,14 @@ pub const W = switch (native_os) { pub fn EXITSTATUS(s: u32) u8 { return @as(u8, @intCast((s & 0xff00) >> 8)); } - pub fn TERMSIG(s: u32) u32 { - return s & 0x7f; + pub fn TERMSIG(s: u32) SIG { + return @enumFromInt(s & 0x7f); } pub fn STOPSIG(s: u32) u32 { return EXITSTATUS(s); } pub fn IFEXITED(s: u32) bool { - return TERMSIG(s) == 0; + return (s & 0x7f) == 0; } pub fn IFSTOPPED(s: u32) bool { return @as(u16, @truncate((((s & 0xffff) *% 0x10001) >> 8))) > 0x7f00; @@ -3869,8 +3930,8 @@ pub const W = switch (native_os) { return @as(u8, @intCast(s & 0xff)); } - pub fn TERMSIG(s: u32) u32 { - return (s >> 8) & 0xff; + pub fn TERMSIG(s: u32) SIG { + return @enumFromInt((s >> 8) & 0xff); } pub fn STOPSIG(s: u32) u32 { @@ -3897,14 +3958,14 @@ pub const W = switch (native_os) { pub fn EXITSTATUS(s: u32) u8 { return @as(u8, @intCast((s >> 8) & 0xff)); } - pub fn TERMSIG(s: u32) u32 { - return (s & 0x7f); + pub fn TERMSIG(s: u32) SIG { + return @enumFromInt(s & 0x7f); } pub fn STOPSIG(s: u32) u32 { return EXITSTATUS(s); } pub fn IFEXITED(s: u32) bool { - return TERMSIG(s) == 0; + return (s & 0x7f) == 0; } pub fn IFCONTINUED(s: u32) bool { @@ -3936,12 +3997,12 @@ pub const W = switch (native_os) { return EXITSTATUS(s); } - pub fn TERMSIG(s: u32) u32 { - return s & 0x7f; + pub fn TERMSIG(s: u32) SIG { + return @enumFromInt(s & 0x7f); } pub fn IFEXITED(s: u32) bool { - return TERMSIG(s) == 0; + return (s & 0x7f) == 0; } pub fn IFSTOPPED(s: u32) bool { @@ -4471,7 +4532,7 @@ pub const rusage = switch (native_os) { pub const SELF = 1; pub const CHILDREN = 2; }, - .freebsd => extern struct { + .freebsd, .openbsd => extern struct { utime: timeval, stime: timeval, maxrss: c_long, @@ -4493,6 +4554,27 @@ pub const rusage = switch (native_os) { pub const CHILDREN = -1; pub const THREAD = 1; }, + .dragonfly, .netbsd => extern struct { + utime: timeval, + stime: timeval, + maxrss: c_long, + ixrss: c_long, + idrss: c_long, + isrss: c_long, + minflt: c_long, + majflt: c_long, + nswap: c_long, + inblock: c_long, + oublock: c_long, + msgsnd: c_long, + msgrcv: c_long, + nsignals: c_long, + nvcsw: c_long, + nivcsw: c_long, + + pub const SELF = 0; + pub const CHILDREN = -1; + }, else => void, }; @@ -4661,14 +4743,6 @@ pub const siginfo_t = switch (native_os) { }, __pad: [128 - 3 * @sizeOf(c_int)]u8, }, - - comptime { - if (@sizeOf(usize) == 4) - assert(@sizeOf(@This()) == 128) - else - // Take into account the padding between errno and data fields. - assert(@sizeOf(@This()) == 136); - } }, // https://github.com/SerenityOS/serenity/blob/ec492a1a0819e6239ea44156825c4ee7234ca3db/Kernel/API/POSIX/signal.h#L27-L37 .serenity => extern struct { @@ -7565,166 +7639,6 @@ pub const EAI = if (builtin.abi.isAndroid()) enum(c_int) { pub const dl_iterate_phdr_callback = *const fn (info: *dl_phdr_info, size: usize, data: ?*anyopaque) callconv(.c) c_int; pub const Stat = switch (native_os) { - .linux => switch (native_arch) { - .sparc64 => extern struct { - dev: u64, - __pad1: u16, - ino: ino_t, - mode: u32, - nlink: u32, - - uid: u32, - gid: u32, - rdev: u64, - __pad2: u16, - - size: off_t, - blksize: isize, - blocks: i64, - - atim: timespec, - mtim: timespec, - ctim: timespec, - __reserved: [2]usize, - - pub fn atime(self: @This()) timespec { - return self.atim; - } - - pub fn mtime(self: @This()) timespec { - return self.mtim; - } - - pub fn ctime(self: @This()) timespec { - return self.ctim; - } - }, - .mips, .mipsel => if (builtin.target.abi.isMusl()) extern struct { - dev: dev_t, - __pad0: [2]i32, - ino: ino_t, - mode: mode_t, - nlink: nlink_t, - uid: uid_t, - gid: gid_t, - rdev: dev_t, - __pad1: [2]i32, - size: off_t, - atim: timespec, - mtim: timespec, - ctim: timespec, - blksize: blksize_t, - __pad3: i32, - blocks: blkcnt_t, - __pad4: [14]i32, - - pub fn atime(self: @This()) timespec { - return self.atim; - } - - pub fn mtime(self: @This()) timespec { - return self.mtim; - } - - pub fn ctime(self: @This()) timespec { - return self.ctim; - } - } else extern struct { - dev: u32, - __pad0: [3]u32, - ino: ino_t, - mode: mode_t, - nlink: nlink_t, - uid: uid_t, - gid: gid_t, - rdev: u32, - __pad1: [3]u32, - size: off_t, - atim: timespec, - mtim: timespec, - ctim: timespec, - blksize: blksize_t, - __pad3: u32, - blocks: blkcnt_t, - __pad4: [14]u32, - - pub fn atime(self: @This()) timespec { - return self.atim; - } - - pub fn mtime(self: @This()) timespec { - return self.mtim; - } - - pub fn ctime(self: @This()) timespec { - return self.ctim; - } - }, - .mips64, .mips64el => if (builtin.target.abi.isMusl()) extern struct { - dev: dev_t, - __pad0: [3]i32, - ino: ino_t, - mode: mode_t, - nlink: nlink_t, - uid: uid_t, - gid: gid_t, - rdev: dev_t, - __pad1: [2]u32, - size: off_t, - __pad2: i32, - atim: timespec, - mtim: timespec, - ctim: timespec, - blksize: blksize_t, - __pad3: u32, - blocks: blkcnt_t, - __pad4: [14]i32, - - pub fn atime(self: @This()) timespec { - return self.atim; - } - - pub fn mtime(self: @This()) timespec { - return self.mtim; - } - - pub fn ctime(self: @This()) timespec { - return self.ctim; - } - } else extern struct { - dev: dev_t, - __pad0: [3]u32, - ino: ino_t, - mode: mode_t, - nlink: nlink_t, - uid: uid_t, - gid: gid_t, - rdev: dev_t, - __pad1: [3]u32, - size: off_t, - atim: timespec, - mtim: timespec, - ctim: timespec, - blksize: blksize_t, - __pad3: u32, - blocks: blkcnt_t, - __pad4: [14]i32, - - pub fn atime(self: @This()) timespec { - return self.atim; - } - - pub fn mtime(self: @This()) timespec { - return self.mtim; - } - - pub fn ctime(self: @This()) timespec { - return self.ctim; - } - }, - - else => std.os.linux.Stat, // libc stat is the same as kernel stat. - }, .emscripten => emscripten.Stat, .wasi => extern struct { // Match wasi-libc's `struct stat` in lib/libc/include/wasm-wasi-musl/__struct_stat.h @@ -8522,6 +8436,7 @@ pub const O = switch (native_os) { CLOEXEC: bool = false, SYNC: bool = false, PATH: bool = false, + /// This is typically invalid without also setting `DIRECTORY`. TMPFILE: bool = false, _: u9 = 0, }, @@ -8710,6 +8625,7 @@ pub const O = switch (native_os) { _19: u1 = 0, CLOEXEC: bool = false, PATH: bool = false, + /// This is typically invalid without also setting `DIRECTORY`. TMPFILE: bool = false, _: u9 = 0, }, @@ -9785,6 +9701,7 @@ pub const NSIG = switch (native_os) { .illumos => 75, // https://github.com/SerenityOS/serenity/blob/046c23f567a17758d762a33bdf04bacbfd088f9f/Kernel/API/POSIX/signal_numbers.h#L42 .openbsd, .serenity => 33, + .dragonfly => 64, else => {}, }; @@ -10401,6 +10318,7 @@ pub const fstat = switch (native_os) { else => private.fstat, }, .netbsd => private.__fstat50, + .linux => {}, else => private.fstat, }; @@ -10409,8 +10327,12 @@ pub const fstatat = switch (native_os) { .x86_64 => private.@"fstatat$INODE64", else => private.fstatat, }, + .linux => {}, else => private.fstatat, }; + +pub extern "c" fn statx(dirfd: fd_t, path: [*:0]const u8, flags: u32, mask: linux.STATX, buf: *linux.Statx) c_int; + pub extern "c" fn getpwent() ?*passwd; pub extern "c" fn endpwent() void; pub extern "c" fn setpwent() void; @@ -10484,8 +10406,6 @@ pub extern "c" fn inotify_init1(flags: c_uint) c_int; pub extern "c" fn inotify_add_watch(fd: fd_t, pathname: [*:0]const u8, mask: u32) c_int; pub extern "c" fn inotify_rm_watch(fd: fd_t, wd: c_int) c_int; -pub extern "c" fn fstat64(fd: fd_t, buf: *Stat) c_int; -pub extern "c" fn fstatat64(dirfd: fd_t, noalias path: [*:0]const u8, noalias stat_buf: *Stat, flags: u32) c_int; pub extern "c" fn fallocate64(fd: fd_t, mode: c_int, offset: off_t, len: off_t) c_int; pub extern "c" fn fopen64(noalias filename: [*:0]const u8, noalias modes: [*:0]const u8) ?*FILE; pub extern "c" fn ftruncate64(fd: c_int, length: off_t) c_int; @@ -10612,24 +10532,36 @@ pub const sigaction = switch (native_os) { }; /// Zig's version of SIGRTMIN. Actually a function. -pub fn sigrtmin() u8 { - return switch (native_os) { - .freebsd => 65, - .netbsd => 33, - .illumos => @truncate(sysconf(@intFromEnum(_SC.SIGRT_MIN))), - else => @truncate(@as(c_uint, @bitCast(private.__libc_current_sigrtmin()))), - }; -} +pub const sigrtmin = switch (native_os) { + .openbsd => {}, + else => sigrt_private.sigrtmin, +}; /// Zig's version of SIGRTMAX. Actually a function. -pub fn sigrtmax() u8 { - return switch (native_os) { - .freebsd => 126, - .netbsd => 63, - .illumos => @truncate(sysconf(@intFromEnum(_SC.SIGRT_MAX))), - else => @truncate(@as(c_uint, @bitCast(private.__libc_current_sigrtmax()))), - }; -} +pub const sigrtmax = switch (native_os) { + .openbsd => {}, + else => sigrt_private.sigrtmax, +}; + +const sigrt_private = struct { + pub fn sigrtmin() u8 { + return switch (native_os) { + .freebsd => 65, + .netbsd => 33, + .illumos => @truncate(sysconf(@intFromEnum(_SC.SIGRT_MIN))), + else => @truncate(@as(c_uint, @bitCast(private.__libc_current_sigrtmin()))), + }; + } + + pub fn sigrtmax() u8 { + return switch (native_os) { + .freebsd => 126, + .netbsd => 63, + .illumos => @truncate(sysconf(@intFromEnum(_SC.SIGRT_MAX))), + else => @truncate(@as(c_uint, @bitCast(private.__libc_current_sigrtmax()))), + }; + } +}; pub const sigfillset = switch (native_os) { .netbsd => private.__sigfillset14, @@ -10656,7 +10588,7 @@ pub const socket = switch (native_os) { pub const socketpair = switch (native_os) { // https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/#unsupported\unavailable: - .windows => void, + .windows => {}, else => private.socketpair, }; @@ -10740,12 +10672,17 @@ pub extern "c" fn munmap(addr: *align(page_size) const anyopaque, len: usize) c_ pub extern "c" fn mremap(addr: ?*align(page_size) const anyopaque, old_len: usize, new_len: usize, flags: MREMAP, ...) *anyopaque; pub extern "c" fn mprotect(addr: *align(page_size) anyopaque, len: usize, prot: c_uint) c_int; pub extern "c" fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8) c_int; -pub extern "c" fn linkat(oldfd: fd_t, oldpath: [*:0]const u8, newfd: fd_t, newpath: [*:0]const u8, flags: c_int) c_int; +pub extern "c" fn linkat(oldfd: fd_t, oldpath: [*:0]const u8, newfd: fd_t, newpath: [*:0]const u8, flags: c_uint) c_int; pub extern "c" fn unlink(path: [*:0]const u8) c_int; pub extern "c" fn unlinkat(dirfd: fd_t, path: [*:0]const u8, flags: c_uint) c_int; pub extern "c" fn getcwd(buf: [*]u8, size: usize) ?[*]u8; pub extern "c" fn waitpid(pid: pid_t, status: ?*c_int, options: c_int) pid_t; -pub extern "c" fn wait4(pid: pid_t, status: ?*c_int, options: c_int, ru: ?*rusage) pid_t; + +pub const wait4 = switch (native_os) { + .netbsd => private.__wait450, + else => private.wait4, +}; + pub const fork = switch (native_os) { .dragonfly, .freebsd, @@ -10838,11 +10775,10 @@ pub extern "c" fn recvfrom( ) if (native_os == .windows) c_int else isize; pub const recvmsg = switch (native_os) { - // Windows: Technically, a form of recvmsg() exists for Windows, but the - // user has to install some kind of callback for it. I'm not sure if/how - // we can map this to normal recvmsg() interface use. + // Technically, a form of recvmsg() exists for Windows, but the user has to + // install some kind of callback for it. // https://learn.microsoft.com/en-us/windows/win32/api/mswsock/nc-mswsock-lpfn_wsarecvmsg - .windows => void, + .windows => {}, else => private.recvmsg, }; @@ -10872,7 +10808,7 @@ pub extern "c" fn free(?*anyopaque) void; pub extern "c" fn futimes(fd: fd_t, times: ?*[2]timeval) c_int; pub extern "c" fn utimes(path: [*:0]const u8, times: ?*[2]timeval) c_int; -pub extern "c" fn utimensat(dirfd: fd_t, pathname: [*:0]const u8, times: ?*[2]timespec, flags: u32) c_int; +pub extern "c" fn utimensat(dirfd: fd_t, pathname: [*:0]const u8, times: ?*const [2]timespec, flags: u32) c_int; pub extern "c" fn futimens(fd: fd_t, times: ?*const [2]timespec) c_int; pub extern "c" fn pthread_create( @@ -10881,6 +10817,23 @@ pub extern "c" fn pthread_create( start_routine: *const fn (?*anyopaque) callconv(.c) ?*anyopaque, noalias arg: ?*anyopaque, ) E; +pub const pthread_cancelstate = switch (native_os) { + .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => enum(c_int) { + ENABLE = 1, + DISABLE = 0, + }, + .linux => if (native_abi.isMusl()) enum(c_int) { + ENABLE = 0, + DISABLE = 1, + MASKED = 2, + } else if (native_abi.isGnu()) enum(c_int) { + ENABLE = 0, + DISABLE = 1, + }, + else => void, +}; +pub extern "c" fn pthread_setcancelstate(pthread_cancelstate, ?*pthread_cancelstate) E; +pub extern "c" fn pthread_cancel(pthread_t) E; pub extern "c" fn pthread_attr_init(attr: *pthread_attr_t) E; pub extern "c" fn pthread_attr_setstack(attr: *pthread_attr_t, stackaddr: *anyopaque, stacksize: usize) E; pub extern "c" fn pthread_attr_setstacksize(attr: *pthread_attr_t, stacksize: usize) E; @@ -11106,6 +11059,26 @@ else b: c_longdouble, }; +pub const div_t = extern struct { + quot: c_int, + rem: c_int, +}; + +pub const ldiv_t = extern struct { + quot: c_long, + rem: c_long, +}; + +pub const lldiv_t = extern struct { + quot: c_longlong, + rem: c_longlong, +}; + +pub const imaxdiv_t = extern struct { + quot: intmax_t, + rem: intmax_t, +}; + pub const intmax_t = i64; pub const uintmax_t = u64; @@ -11113,6 +11086,20 @@ pub extern "c" fn pthread_getthreadid_np() c_int; pub extern "c" fn pthread_set_name_np(thread: pthread_t, name: [*:0]const u8) void; pub extern "c" fn pthread_get_name_np(thread: pthread_t, name: [*:0]u8, len: usize) void; +pub const TIMER = switch (native_os) { + .linux, .emscripten => std.os.linux.TIMER, + .openbsd, .netbsd, .wasi, .windows, .freebsd, .serenity => packed struct(u32) { + ABSTIME: bool, + _: u31 = 0, + }, + else => void, +}; + +pub const clock_nanosleep = switch (native_os) { + .linux, .emscripten, .netbsd, .wasi, .windows, .freebsd, .serenity => private.clock_nanosleep, + else => {}, +}; + // OS-specific bits. These are protected from being used on the wrong OS by // comptime assertions inside each OS-specific file. @@ -11286,6 +11273,8 @@ pub const _dyld_get_image_header = darwin._dyld_get_image_header; pub const _dyld_get_image_name = darwin._dyld_get_image_name; pub const _dyld_get_image_vmaddr_slide = darwin._dyld_get_image_vmaddr_slide; pub const _dyld_image_count = darwin._dyld_image_count; +pub const _dyld_get_image_header_containing_address = darwin._dyld_get_image_header_containing_address; +pub const dyld_image_path_containing_address = darwin.dyld_image_path_containing_address; pub const _host_page_size = darwin._host_page_size; pub const boolean_t = darwin.boolean_t; pub const clock_get_time = darwin.clock_get_time; @@ -11454,6 +11443,9 @@ pub const vm_region_flavor_t = darwin.vm_region_flavor_t; pub const _ksiginfo = netbsd._ksiginfo; pub const _lwp_self = netbsd._lwp_self; +pub const _lwp_park = netbsd.___lwp_park60; +pub const _lwp_unpark = netbsd._lwp_unpark; +pub const _lwp_unpark_all = netbsd._lwp_unpark_all; pub const lwpid_t = netbsd.lwpid_t; pub const lwp_gettid = dragonfly.lwp_gettid; @@ -11497,6 +11489,7 @@ const private = struct { extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; extern "c" fn msync(addr: *align(page_size) const anyopaque, len: usize, flags: c_int) c_int; extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int; + extern "c" fn clock_nanosleep(clockid: clockid_t, flags: TIMER, t: *const timespec, remain: ?*timespec) c_int; extern "c" fn pipe2(fds: *[2]fd_t, flags: O) c_int; extern "c" fn readdir(dir: *DIR) ?*dirent; extern "c" fn realpath(noalias file_name: [*:0]const u8, noalias resolved_name: [*]u8) ?[*:0]u8; @@ -11512,10 +11505,10 @@ const private = struct { extern "c" fn sigprocmask(how: c_int, noalias set: ?*const sigset_t, noalias oset: ?*sigset_t) c_int; extern "c" fn socket(domain: c_uint, sock_type: c_uint, protocol: c_uint) c_int; extern "c" fn socketpair(domain: c_uint, sock_type: c_uint, protocol: c_uint, sv: *[2]fd_t) c_int; - extern "c" fn stat(noalias path: [*:0]const u8, noalias buf: *Stat) c_int; extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int; extern "c" fn sysconf(sc: c_int) c_long; extern "c" fn shm_open(name: [*:0]const u8, flag: c_int, mode: mode_t) c_int; + extern "c" fn wait4(pid: pid_t, status: ?*c_int, options: c_int, ru: ?*rusage) pid_t; extern "c" fn pthread_setname_np(thread: pthread_t, name: [*:0]const u8) c_int; @@ -11568,6 +11561,7 @@ const private = struct { extern "c" fn __stat50(path: [*:0]const u8, buf: *Stat) c_int; extern "c" fn __getdents30(fd: c_int, buf_ptr: [*]u8, nbytes: usize) c_int; extern "c" fn __sigaltstack14(ss: ?*stack_t, old_ss: ?*stack_t) c_int; + extern "c" fn __wait450(pid: pid_t, status: ?*c_int, options: c_int, ru: ?*rusage) pid_t; extern "c" fn __libc_current_sigrtmin() c_int; extern "c" fn __libc_current_sigrtmax() c_int; diff --git a/lib/std/c/darwin.zig b/lib/std/c/darwin.zig index cf7d3127ebe9..d4a7dfd5db13 100644 --- a/lib/std/c/darwin.zig +++ b/lib/std/c/darwin.zig @@ -349,11 +349,13 @@ pub const VM = struct { pub const exception_type_t = c_int; pub extern "c" fn NSVersionOfRunTimeLibrary(library_name: [*:0]const u8) u32; -pub extern "c" fn _NSGetExecutablePath(buf: [*:0]u8, bufsize: *u32) c_int; +pub extern "c" fn _NSGetExecutablePath(buf: [*]u8, bufsize: *u32) c_int; pub extern "c" fn _dyld_image_count() u32; pub extern "c" fn _dyld_get_image_header(image_index: u32) ?*mach_header; pub extern "c" fn _dyld_get_image_vmaddr_slide(image_index: u32) usize; pub extern "c" fn _dyld_get_image_name(image_index: u32) [*:0]const u8; +pub extern "c" fn _dyld_get_image_header_containing_address(address: *const anyopaque) ?*mach_header; +pub extern "c" fn dyld_image_path_containing_address(address: *const anyopaque) ?[*:0]const u8; pub extern "c" fn dladdr(addr: *const anyopaque, info: *dl_info) c_int; pub const dl_info = extern struct { diff --git a/lib/std/c/freebsd.zig b/lib/std/c/freebsd.zig index 45ad812ed14e..ad67b23a1468 100644 --- a/lib/std/c/freebsd.zig +++ b/lib/std/c/freebsd.zig @@ -250,7 +250,7 @@ pub const kinfo_file = extern struct { /// Reserved for future cap_rights _cap_spare: u64, /// Path to file, if any. - path: [PATH_MAX - 1:0]u8, + path: [PATH_MAX]u8, comptime { assert(@sizeOf(@This()) == KINFO_FILE_SIZE); diff --git a/lib/std/c/netbsd.zig b/lib/std/c/netbsd.zig index a9577bc48256..2d73e634ea4f 100644 --- a/lib/std/c/netbsd.zig +++ b/lib/std/c/netbsd.zig @@ -1,17 +1,35 @@ const std = @import("../std.zig"); const clock_t = std.c.clock_t; +const clockid_t = std.c.clockid_t; const pid_t = std.c.pid_t; const pthread_t = std.c.pthread_t; const sigval_t = std.c.sigval_t; const uid_t = std.c.uid_t; +const timespec = std.c.timespec; pub extern "c" fn ptrace(request: c_int, pid: pid_t, addr: ?*anyopaque, data: c_int) c_int; pub const lwpid_t = i32; -pub extern "c" fn _lwp_self() lwpid_t; pub extern "c" fn pthread_setname_np(thread: pthread_t, name: [*:0]const u8, arg: ?*anyopaque) c_int; +pub extern "c" fn _lwp_self() lwpid_t; + +pub extern "c" fn ___lwp_park60( + clock_id: clockid_t, + flags: packed struct(u32) { + ABSTIME: bool = false, + unused: u31 = 0, + }, + ts: ?*timespec, + unpark: lwpid_t, + hint: ?*const anyopaque, + unpark_hint: ?*const anyopaque, +) c_int; + +pub extern "c" fn _lwp_unpark(lwp: lwpid_t, hint: ?*const anyopaque) c_int; +pub extern "c" fn _lwp_unpark_all(targets: [*]const lwpid_t, ntargets: usize, hint: ?*const anyopaque) c_int; + pub const TCIFLUSH = 1; pub const TCOFLUSH = 2; pub const TCIOFLUSH = 3; diff --git a/lib/std/coff.zig b/lib/std/coff.zig index 1706af24abc4..7dea0f4344c4 100644 --- a/lib/std/coff.zig +++ b/lib/std/coff.zig @@ -466,13 +466,13 @@ pub const SectionHeader = extern struct { pub fn getName(self: *align(1) const SectionHeader) ?[]const u8 { if (self.name[0] == '/') return null; - const len = std.mem.indexOfScalar(u8, &self.name, @as(u8, 0)) orelse self.name.len; + const len = std.mem.findScalar(u8, &self.name, @as(u8, 0)) orelse self.name.len; return self.name[0..len]; } pub fn getNameOffset(self: SectionHeader) ?u32 { if (self.name[0] != '/') return null; - const len = std.mem.indexOfScalar(u8, &self.name, @as(u8, 0)) orelse self.name.len; + const len = std.mem.findScalar(u8, &self.name, @as(u8, 0)) orelse self.name.len; const offset = std.fmt.parseInt(u32, self.name[1..len], 10) catch unreachable; return offset; } @@ -628,7 +628,7 @@ pub const Symbol = struct { pub fn getName(self: *const Symbol) ?[]const u8 { if (std.mem.eql(u8, self.name[0..4], "\x00\x00\x00\x00")) return null; - const len = std.mem.indexOfScalar(u8, &self.name, @as(u8, 0)) orelse self.name.len; + const len = std.mem.findScalar(u8, &self.name, @as(u8, 0)) orelse self.name.len; return self.name[0..len]; } @@ -869,7 +869,7 @@ pub const FileDefinition = struct { file_name: [18]u8, pub fn getFileName(self: *const FileDefinition) []const u8 { - const len = std.mem.indexOfScalar(u8, &self.file_name, @as(u8, 0)) orelse self.file_name.len; + const len = std.mem.findScalar(u8, &self.file_name, @as(u8, 0)) orelse self.file_name.len; return self.file_name[0..len]; } }; @@ -1044,7 +1044,7 @@ pub const Coff = struct { // Finally read the null-terminated string. const start = reader.seek; - const len = std.mem.indexOfScalar(u8, self.data[start..], 0) orelse return null; + const len = std.mem.findScalar(u8, self.data[start..], 0) orelse return null; return self.data[start .. start + len]; } diff --git a/lib/std/compress/flate/Compress.zig b/lib/std/compress/flate/Compress.zig index 36da23d79908..41b7d8bf04cc 100644 --- a/lib/std/compress/flate/Compress.zig +++ b/lib/std/compress/flate/Compress.zig @@ -598,7 +598,7 @@ fn testFuzzedMatchLen(_: void, input: []const u8) !void { const bytes = w.buffered()[bytes_off..]; old = @min(old, bytes.len - 1, token.max_length - 1); - const diff_index = mem.indexOfDiff(u8, prev, bytes).?; // unwrap since lengths are not same + const diff_index = mem.findDiff(u8, prev, bytes).?; // unwrap since lengths are not same const expected_len = @min(diff_index, 258); errdefer std.debug.print( \\prev : '{any}' diff --git a/lib/std/crypto.zig b/lib/std/crypto.zig index 1da25abe1788..7833a31237bf 100644 --- a/lib/std/crypto.zig +++ b/lib/std/crypto.zig @@ -116,6 +116,7 @@ pub const dh = struct { /// Key Encapsulation Mechanisms. pub const kem = struct { + pub const hybrid = @import("crypto/hybrid_kem.zig"); pub const kyber_d00 = @import("crypto/ml_kem.zig").d00; pub const ml_kem = @import("crypto/ml_kem.zig").nist; }; @@ -183,7 +184,7 @@ pub const pwhash = struct { pub const Error = HasherError || error{AllocatorRequired}; pub const HasherError = KdfError || phc_format.Error; - pub const KdfError = errors.Error || std.mem.Allocator.Error || std.Thread.SpawnError; + pub const KdfError = errors.Error || std.mem.Allocator.Error || std.Thread.SpawnError || std.Io.Cancelable; pub const argon2 = @import("crypto/argon2.zig"); pub const bcrypt = @import("crypto/bcrypt.zig"); @@ -234,9 +235,6 @@ pub const nacl = struct { /// Finite-field arithmetic. pub const ff = @import("crypto/ff.zig"); -/// This is a thread-local, cryptographically secure pseudo random number generator. -pub const random = @import("crypto/tlcsprng.zig").interface; - /// Encoding and decoding pub const codecs = @import("crypto/codecs.zig"); @@ -305,6 +303,9 @@ test { _ = dh.X25519; _ = kem.kyber_d00; + _ = kem.hybrid; + _ = kem.kyber_d00; + _ = kem.ml_kem; _ = ecc.Curve25519; _ = ecc.Edwards25519; @@ -342,6 +343,7 @@ test { _ = sign.Ed25519; _ = sign.ecdsa; + _ = sign.mldsa; _ = stream.chacha.ChaCha20IETF; _ = stream.chacha.ChaCha12IETF; @@ -363,20 +365,12 @@ test { _ = secureZero; _ = timing_safe; _ = ff; - _ = random; _ = errors; _ = tls; _ = Certificate; _ = codecs; } -test "CSPRNG" { - const a = random.int(u64); - const b = random.int(u64); - const c = random.int(u64); - try std.testing.expect(a ^ b ^ c != 0); -} - test "issue #4532: no index out of bounds" { const types = [_]type{ hash.Md5, diff --git a/lib/std/crypto/25519/ed25519.zig b/lib/std/crypto/25519/ed25519.zig index a78e1aa3ab2c..a224c70d903a 100644 --- a/lib/std/crypto/25519/ed25519.zig +++ b/lib/std/crypto/25519/ed25519.zig @@ -333,12 +333,10 @@ pub const Ed25519 = struct { } /// Generate a new, random key pair. - /// - /// `crypto.random.bytes` must be supported by the target. - pub fn generate() KeyPair { + pub fn generate(io: std.Io) KeyPair { var random_seed: [seed_length]u8 = undefined; while (true) { - crypto.random.bytes(&random_seed); + io.random(&random_seed); return generateDeterministic(random_seed) catch { @branchHint(.unlikely); continue; @@ -387,20 +385,23 @@ pub const Ed25519 = struct { ); } - /// Create a Signer, that can be used for incremental signing. - /// Note that the signature is not deterministic. - /// The noise parameter, if set, should be something unique for each message, - /// such as a random nonce, or a counter. - pub fn signer(key_pair: KeyPair, noise: ?[noise_length]u8) (IdentityElementError || KeyMismatchError || NonCanonicalError || WeakPublicKeyError)!Signer { + /// Create a signer that can be used for incremental signing, using a custom base nonce. + /// `base_nonce` must be unique for each signed message; otherwise, the secret key can + /// be trivially recovered by an attacker. + /// It can be generated using a cryptographically secure random number generator. + pub fn signerWithBaseNonce( + key_pair: KeyPair, + base_nonce: [32]u8, + /// If set, should be something unique for each message, such as a counter. + noise: ?[noise_length]u8, + ) (IdentityElementError || KeyMismatchError || NonCanonicalError || WeakPublicKeyError)!Signer { if (!mem.eql(u8, &key_pair.secret_key.publicKeyBytes(), &key_pair.public_key.toBytes())) { return error.KeyMismatch; } const scalar_and_prefix = key_pair.secret_key.scalarAndPrefix(); var h = Sha512.init(.{}); h.update(&scalar_and_prefix.prefix); - var noise2: [noise_length]u8 = undefined; - crypto.random.bytes(&noise2); - h.update(&noise2); + h.update(&base_nonce); if (noise) |*z| { h.update(z); } @@ -410,6 +411,20 @@ pub const Ed25519 = struct { return Signer.init(scalar_and_prefix.scalar, nonce, key_pair.public_key); } + + /// Create a Signer, that can be used for incremental signing. + /// Note that the signature is not deterministic. + pub fn signer( + key_pair: KeyPair, + /// If set, should be something unique for each message, such as a + /// random nonce, or a counter. + noise: ?[noise_length]u8, + io: std.Io, + ) (IdentityElementError || KeyMismatchError || NonCanonicalError || WeakPublicKeyError)!Signer { + var base_nonce: [32]u8 = undefined; + io.random(&base_nonce); + return key_pair.signerWithBaseNonce(base_nonce, noise); + } }; /// A (signature, message, public_key) tuple for batch verification @@ -420,7 +435,7 @@ pub const Ed25519 = struct { }; /// Verify several signatures in a single operation, much faster than verifying signatures one-by-one - pub fn verifyBatch(comptime count: usize, signature_batch: [count]BatchElement) (SignatureVerificationError || IdentityElementError || WeakPublicKeyError || EncodingError || NonCanonicalError)!void { + pub fn verifyBatch(io: std.Io, comptime count: usize, signature_batch: [count]BatchElement) (SignatureVerificationError || IdentityElementError || WeakPublicKeyError || EncodingError || NonCanonicalError)!void { var r_batch: [count]CompressedScalar = undefined; var s_batch: [count]CompressedScalar = undefined; var a_batch: [count]Curve = undefined; @@ -454,7 +469,7 @@ pub const Ed25519 = struct { var z_batch: [count]Curve.scalar.CompressedScalar = undefined; for (&z_batch) |*z| { - crypto.random.bytes(z[0..16]); + io.random(z[0..16]); @memset(z[16..], 0); } @@ -587,12 +602,14 @@ test "signature" { } test "batch verification" { + const io = std.testing.io; + for (0..16) |_| { - const key_pair = Ed25519.KeyPair.generate(); + const key_pair = Ed25519.KeyPair.generate(io); var msg1: [32]u8 = undefined; var msg2: [32]u8 = undefined; - crypto.random.bytes(&msg1); - crypto.random.bytes(&msg2); + io.random(&msg1); + io.random(&msg2); const sig1 = try key_pair.sign(&msg1, null); const sig2 = try key_pair.sign(&msg2, null); var signature_batch = [_]Ed25519.BatchElement{ @@ -607,10 +624,10 @@ test "batch verification" { .public_key = key_pair.public_key, }, }; - try Ed25519.verifyBatch(2, signature_batch); + try Ed25519.verifyBatch(io, 2, signature_batch); signature_batch[1].sig = sig1; - try std.testing.expectError(error.SignatureVerificationFailed, Ed25519.verifyBatch(signature_batch.len, signature_batch)); + try std.testing.expectError(error.SignatureVerificationFailed, Ed25519.verifyBatch(io, signature_batch.len, signature_batch)); } } @@ -718,14 +735,15 @@ test "test vectors" { } test "with blind keys" { + const io = std.testing.io; const BlindKeyPair = Ed25519.key_blinding.BlindKeyPair; // Create a standard Ed25519 key pair - const kp = Ed25519.KeyPair.generate(); + const kp = Ed25519.KeyPair.generate(io); // Create a random blinding seed var blind: [32]u8 = undefined; - crypto.random.bytes(&blind); + io.random(&blind); // Blind the key pair const blind_kp = try BlindKeyPair.init(kp, blind, "ctx"); @@ -741,9 +759,10 @@ test "with blind keys" { } test "signatures with streaming" { - const kp = Ed25519.KeyPair.generate(); + const io = std.testing.io; + const kp = Ed25519.KeyPair.generate(io); - var signer = try kp.signer(null); + var signer = try kp.signer(null, io); signer.update("mes"); signer.update("sage"); const sig = signer.finalize(); @@ -757,7 +776,8 @@ test "signatures with streaming" { } test "key pair from secret key" { - const kp = Ed25519.KeyPair.generate(); + const io = std.testing.io; + const kp = Ed25519.KeyPair.generate(io); const kp2 = try Ed25519.KeyPair.fromSecretKey(kp.secret_key); try std.testing.expectEqualSlices(u8, &kp.secret_key.toBytes(), &kp2.secret_key.toBytes()); try std.testing.expectEqualSlices(u8, &kp.public_key.toBytes(), &kp2.public_key.toBytes()); @@ -788,7 +808,8 @@ test "cofactored vs cofactorless verification" { } test "regular signature verifies with both verify and verifyStrict" { - const kp = Ed25519.KeyPair.generate(); + const io = std.testing.io; + const kp = Ed25519.KeyPair.generate(io); const msg = "test message"; const sig = try kp.sign(msg, null); try sig.verify(msg, kp.public_key); diff --git a/lib/std/crypto/25519/edwards25519.zig b/lib/std/crypto/25519/edwards25519.zig index 521ec74c6d51..0672474eabac 100644 --- a/lib/std/crypto/25519/edwards25519.zig +++ b/lib/std/crypto/25519/edwards25519.zig @@ -127,12 +127,10 @@ pub const Edwards25519 = struct { /// Check that the point does not generate a low-order group. /// Return a `WeakPublicKey` error if it does. pub fn rejectLowOrder(p: Edwards25519) WeakPublicKeyError!void { - const zi = p.z.invert(); - const x = p.x.mul(zi); - const y = p.y.mul(zi); - const x_neg = x.neg(); - const iy = Fe.sqrtm1.mul(y); - if (x.isZero() or y.isZero() or iy.equivalent(x) or iy.equivalent(x_neg)) { + const y_sqrtm1 = Fe.sqrtm1.mul(p.y); + if (p.x.isZero() or p.y.isZero() or p.z.isZero() or + y_sqrtm1.sub(p.x).isZero() or y_sqrtm1.add(p.x).isZero()) + { return error.WeakPublicKey; } } @@ -577,10 +575,11 @@ test "packing/unpacking" { } test "point addition/subtraction" { + const io = std.testing.io; var s1: [32]u8 = undefined; var s2: [32]u8 = undefined; - crypto.random.bytes(&s1); - crypto.random.bytes(&s2); + io.random(&s1); + io.random(&s2); const p = try Edwards25519.basePoint.clampedMul(s1); const q = try Edwards25519.basePoint.clampedMul(s2); const r = p.add(q).add(q).sub(q).sub(q); @@ -624,9 +623,10 @@ test "implicit reduction of invalid scalars" { } test "subgroup check" { + const io = std.testing.io; for (0..100) |_| { var p = Edwards25519.basePoint; - const s = Edwards25519.scalar.random(); + const s = Edwards25519.scalar.random(io); p = try p.mulPublic(s); try p.rejectUnexpectedSubgroup(); } diff --git a/lib/std/crypto/25519/scalar.zig b/lib/std/crypto/25519/scalar.zig index 59a4b41f7a28..97887ee004f0 100644 --- a/lib/std/crypto/25519/scalar.zig +++ b/lib/std/crypto/25519/scalar.zig @@ -101,8 +101,8 @@ pub fn sub(a: CompressedScalar, b: CompressedScalar) CompressedScalar { } /// Return a random scalar < L -pub fn random() CompressedScalar { - return Scalar.random().toBytes(); +pub fn random(io: std.Io) CompressedScalar { + return Scalar.random(io).toBytes(); } /// A scalar in unpacked representation @@ -560,10 +560,10 @@ pub const Scalar = struct { } /// Return a random scalar < L. - pub fn random() Scalar { + pub fn random(io: std.Io) Scalar { var s: [64]u8 = undefined; while (true) { - crypto.random.bytes(&s); + io.random(&s); const n = Scalar.fromBytes64(s); if (!n.isZero()) { return n; @@ -879,8 +879,9 @@ test "scalar field inversion" { } test "random scalar" { - const s1 = random(); - const s2 = random(); + const io = std.testing.io; + const s1 = random(io); + const s2 = random(io); try std.testing.expect(!mem.eql(u8, &s1, &s2)); } diff --git a/lib/std/crypto/25519/x25519.zig b/lib/std/crypto/25519/x25519.zig index ee40f34940f3..dc49d3e9a229 100644 --- a/lib/std/crypto/25519/x25519.zig +++ b/lib/std/crypto/25519/x25519.zig @@ -41,10 +41,10 @@ pub const X25519 = struct { } /// Generate a new, random key pair. - pub fn generate() KeyPair { + pub fn generate(io: std.Io) KeyPair { var random_seed: [seed_length]u8 = undefined; while (true) { - crypto.random.bytes(&random_seed); + io.random(&random_seed); return generateDeterministic(random_seed) catch { @branchHint(.unlikely); continue; diff --git a/lib/std/crypto/Certificate.zig b/lib/std/crypto/Certificate.zig index b0c02e043b4b..761cf49ade60 100644 --- a/lib/std/crypto/Certificate.zig +++ b/lib/std/crypto/Certificate.zig @@ -358,10 +358,10 @@ pub const Parsed = struct { const wildcard_suffix = dns_name[2..]; // No additional wildcards allowed in the suffix - if (mem.indexOf(u8, wildcard_suffix, "*") != null) return false; + if (mem.find(u8, wildcard_suffix, "*") != null) return false; // Find the first dot in hostname to split first label from rest - const dot_pos = mem.indexOf(u8, host_name, ".") orelse return false; + const dot_pos = mem.find(u8, host_name, ".") orelse return false; // Wildcard matches exactly one label, so compare the rest const host_suffix = host_name[dot_pos + 1 ..]; @@ -651,10 +651,16 @@ const Date = struct { }; pub fn parseTimeDigits(text: *const [2]u8, min: u8, max: u8) !u8 { - const nn: @Vector(2, u16) = .{ text[0], text[1] }; - const zero: @Vector(2, u16) = .{ '0', '0' }; - const mm: @Vector(2, u16) = .{ 10, 1 }; - const result = @reduce(.Add, (nn -% zero) *% mm); + const V = @Vector(2, u16); + const bytes: V = text.*; + const zero: V = @splat('0'); + const mm: V = .{ 10, 1 }; + const d = bytes -% zero; + if (@reduce(.Or, d > @as(V, @splat(9)))) { + @branchHint(.unlikely); + return error.CertificateTimeInvalid; + } + const result = @reduce(.Add, d *% mm); if (result < min) return error.CertificateTimeInvalid; if (result > max) return error.CertificateTimeInvalid; return @intCast(result); @@ -670,14 +676,20 @@ test parseTimeDigits { try expectError(error.CertificateTimeInvalid, parseTimeDigits("13", 1, 12)); try expectError(error.CertificateTimeInvalid, parseTimeDigits("00", 1, 12)); try expectError(error.CertificateTimeInvalid, parseTimeDigits("Di", 0, 99)); + try expectError(error.CertificateTimeInvalid, parseTimeDigits("0:", 1, 31)); } pub fn parseYear4(text: *const [4]u8) !u16 { - const nnnn: @Vector(4, u32) = .{ text[0], text[1], text[2], text[3] }; - const zero: @Vector(4, u32) = .{ '0', '0', '0', '0' }; - const mmmm: @Vector(4, u32) = .{ 1000, 100, 10, 1 }; - const result = @reduce(.Add, (nnnn -% zero) *% mmmm); - if (result > 9999) return error.CertificateTimeInvalid; + const V = @Vector(4, u32); + const bytes: V = text.*; + const zero: V = @splat('0'); + const mmmm: V = .{ 1000, 100, 10, 1 }; + const d = bytes -% zero; + if (@reduce(.Or, d > @as(V, @splat(9)))) { + @branchHint(.unlikely); + return error.CertificateTimeInvalid; + } + const result = @reduce(.Add, d *% mmmm); return @intCast(result); } @@ -691,6 +703,9 @@ test parseYear4 { try expectError(error.CertificateTimeInvalid, parseYear4("999b")); try expectError(error.CertificateTimeInvalid, parseYear4("crap")); try expectError(error.CertificateTimeInvalid, parseYear4("r:bQ")); + try expectError(error.CertificateTimeInvalid, parseYear4("000:")); + try expectError(error.CertificateTimeInvalid, parseYear4("0???")); + try expectError(error.CertificateTimeInvalid, parseYear4("*zig")); } pub fn parseAlgorithm(bytes: []const u8, element: der.Element) ParseEnumError!Algorithm { diff --git a/lib/std/crypto/Certificate/Bundle.zig b/lib/std/crypto/Certificate/Bundle.zig index c9c0b92397fa..385ef23c9c7e 100644 --- a/lib/std/crypto/Certificate/Bundle.zig +++ b/lib/std/crypto/Certificate/Bundle.zig @@ -9,8 +9,8 @@ const builtin = @import("builtin"); const std = @import("../../std.zig"); const Io = std.Io; +const Dir = std.Io.Dir; const assert = std.debug.assert; -const fs = std.fs; const mem = std.mem; const crypto = std.crypto; const Allocator = std.mem.Allocator; @@ -171,17 +171,17 @@ fn rescanWindows(cb: *Bundle, gpa: Allocator, io: Io, now: Io.Timestamp) RescanW cb.bytes.shrinkAndFree(gpa, cb.bytes.items.len); } -pub const AddCertsFromDirPathError = fs.File.OpenError || AddCertsFromDirError; +pub const AddCertsFromDirPathError = Io.File.OpenError || AddCertsFromDirError; pub fn addCertsFromDirPath( cb: *Bundle, gpa: Allocator, io: Io, - dir: fs.Dir, + dir: Io.Dir, sub_dir_path: []const u8, ) AddCertsFromDirPathError!void { - var iterable_dir = try dir.openDir(sub_dir_path, .{ .iterate = true }); - defer iterable_dir.close(); + var iterable_dir = try dir.openDir(io, sub_dir_path, .{ .iterate = true }); + defer iterable_dir.close(io); return addCertsFromDir(cb, gpa, io, iterable_dir); } @@ -192,27 +192,27 @@ pub fn addCertsFromDirPathAbsolute( now: Io.Timestamp, abs_dir_path: []const u8, ) AddCertsFromDirPathError!void { - assert(fs.path.isAbsolute(abs_dir_path)); - var iterable_dir = try fs.openDirAbsolute(abs_dir_path, .{ .iterate = true }); - defer iterable_dir.close(); + assert(Dir.path.isAbsolute(abs_dir_path)); + var iterable_dir = try Dir.openDirAbsolute(io, abs_dir_path, .{ .iterate = true }); + defer iterable_dir.close(io); return addCertsFromDir(cb, gpa, io, now, iterable_dir); } pub const AddCertsFromDirError = AddCertsFromFilePathError; -pub fn addCertsFromDir(cb: *Bundle, gpa: Allocator, io: Io, now: Io.Timestamp, iterable_dir: fs.Dir) AddCertsFromDirError!void { +pub fn addCertsFromDir(cb: *Bundle, gpa: Allocator, io: Io, now: Io.Timestamp, iterable_dir: Io.Dir) AddCertsFromDirError!void { var it = iterable_dir.iterate(); - while (try it.next()) |entry| { + while (try it.next(io)) |entry| { switch (entry.kind) { .file, .sym_link => {}, else => continue, } - try addCertsFromFilePath(cb, gpa, io, now, iterable_dir.adaptToNewApi(), entry.name); + try addCertsFromFilePath(cb, gpa, io, now, iterable_dir, entry.name); } } -pub const AddCertsFromFilePathError = fs.File.OpenError || AddCertsFromFileError || Io.Clock.Error; +pub const AddCertsFromFilePathError = Io.File.OpenError || AddCertsFromFileError || Io.Clock.Error; pub fn addCertsFromFilePathAbsolute( cb: *Bundle, @@ -221,8 +221,8 @@ pub fn addCertsFromFilePathAbsolute( now: Io.Timestamp, abs_file_path: []const u8, ) AddCertsFromFilePathError!void { - var file = try fs.openFileAbsolute(abs_file_path, .{}); - defer file.close(); + var file = try Io.Dir.openFileAbsolute(io, abs_file_path, .{}); + defer file.close(io); var file_reader = file.reader(io, &.{}); return addCertsFromFile(cb, gpa, &file_reader, now.toSeconds()); } @@ -242,8 +242,8 @@ pub fn addCertsFromFilePath( } pub const AddCertsFromFileError = Allocator.Error || - fs.File.GetSeekPosError || - fs.File.ReadError || + Io.File.Reader.Error || + Io.File.Reader.SizeError || ParseCertError || std.base64.Error || error{ CertificateAuthorityBundleTooBig, MissingEndCertificateMarker, Streaming }; @@ -269,9 +269,9 @@ pub fn addCertsFromFile(cb: *Bundle, gpa: Allocator, file_reader: *Io.File.Reade const end_marker = "-----END CERTIFICATE-----"; var start_index: usize = 0; - while (mem.indexOfPos(u8, encoded_bytes, start_index, begin_marker)) |begin_marker_start| { + while (mem.findPos(u8, encoded_bytes, start_index, begin_marker)) |begin_marker_start| { const cert_start = begin_marker_start + begin_marker.len; - const cert_end = mem.indexOfPos(u8, encoded_bytes, cert_start, end_marker) orelse + const cert_end = mem.findPos(u8, encoded_bytes, cert_start, end_marker) orelse return error.MissingEndCertificateMarker; start_index = cert_end + end_marker.len; const encoded_cert = mem.trim(u8, encoded_bytes[cert_start..cert_end], " \t\r\n"); diff --git a/lib/std/crypto/Certificate/Bundle/macos.zig b/lib/std/crypto/Certificate/Bundle/macos.zig index d32f1be8e0c3..ea8a91702d6f 100644 --- a/lib/std/crypto/Certificate/Bundle/macos.zig +++ b/lib/std/crypto/Certificate/Bundle/macos.zig @@ -6,7 +6,7 @@ const mem = std.mem; const Allocator = std.mem.Allocator; const Bundle = @import("../Bundle.zig"); -pub const RescanMacError = Allocator.Error || fs.File.OpenError || fs.File.ReadError || fs.File.SeekError || Bundle.ParseCertError || error{EndOfStream}; +pub const RescanMacError = Allocator.Error || Io.File.OpenError || Io.File.Reader.Error || Io.File.SeekError || Bundle.ParseCertError || error{EndOfStream}; pub fn rescanMac(cb: *Bundle, gpa: Allocator, io: Io, now: Io.Timestamp) RescanMacError!void { cb.bytes.clearRetainingCapacity(); @@ -17,9 +17,8 @@ pub fn rescanMac(cb: *Bundle, gpa: Allocator, io: Io, now: Io.Timestamp) RescanM "/Library/Keychains/System.keychain", }; - _ = io; // TODO migrate file system to use std.Io for (keychain_paths) |keychain_path| { - const bytes = std.fs.cwd().readFileAlloc(keychain_path, gpa, .limited(std.math.maxInt(u32))) catch |err| switch (err) { + const bytes = Io.Dir.cwd().readFileAlloc(io, keychain_path, gpa, .limited(std.math.maxInt(u32))) catch |err| switch (err) { error.StreamTooLong => return error.FileTooBig, else => |e| return e, }; diff --git a/lib/std/crypto/aes.zig b/lib/std/crypto/aes.zig index 130b461a5ebe..b660fabe25ae 100644 --- a/lib/std/crypto/aes.zig +++ b/lib/std/crypto/aes.zig @@ -108,6 +108,36 @@ test "expand 128-bit key" { } } +test "invMixColumns" { + const key = [_]u8{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; + const enc_ctx = Aes128.initEnc(key); + const dec_ctx = Aes128.initDec(key); + + for (1..10) |i| { + const enc_rk = enc_ctx.key_schedule.round_keys[10 - i]; + const dec_rk = dec_ctx.key_schedule.round_keys[i]; + const computed = enc_rk.invMixColumns(); + try testing.expectEqualSlices(u8, &dec_rk.toBytes(), &computed.toBytes()); + } +} + +test "BlockVec invMixColumns" { + const input = [_]u8{ + 0x5f, 0x57, 0xf7, 0x1d, 0x72, 0xf5, 0xbe, 0xb9, 0x64, 0xbc, 0x3b, 0xf9, 0x15, 0x92, 0x29, 0x1a, + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c, + }; + + const vec2 = BlockVec(2).fromBytes(&input); + const result_vec = vec2.invMixColumns(); + const result_bytes = result_vec.toBytes(); + + for (0..2) |i| { + const block = Block.fromBytes(input[i * 16 ..][0..16]); + const expected = block.invMixColumns().toBytes(); + try testing.expectEqualSlices(u8, &expected, result_bytes[i * 16 ..][0..16]); + } +} + test "expand 256-bit key" { const key = [_]u8{ 0x60, 0x3d, 0xeb, 0x10, diff --git a/lib/std/crypto/aes/aesni.zig b/lib/std/crypto/aes/aesni.zig index 64bf37b46ee3..c7b82e0fb964 100644 --- a/lib/std/crypto/aes/aesni.zig +++ b/lib/std/crypto/aes/aesni.zig @@ -96,6 +96,17 @@ pub const Block = struct { return Block{ .repr = block1.repr | block2.repr }; } + /// Apply the inverse MixColumns operation to a block. + pub fn invMixColumns(block: Block) Block { + return Block{ + .repr = asm ( + \\ vaesimc %[in], %[out] + : [out] "=x" (-> Repr), + : [in] "x" (block.repr), + ), + }; + } + /// Perform operations on multiple blocks in parallel. pub const parallel = struct { const cpu = std.Target.x86.cpu; @@ -308,6 +319,17 @@ pub fn BlockVec(comptime blocks_count: comptime_int) type { } return out; } + + /// Apply the inverse MixColumns operation to each block in the vector. + pub fn invMixColumns(block_vec: Self) Self { + var out_bytes: [blocks_count * 16]u8 = undefined; + const in_bytes = block_vec.toBytes(); + inline for (0..blocks_count) |i| { + const block = Block.fromBytes(in_bytes[i * 16 ..][0..16]); + out_bytes[i * 16 ..][0..16].* = block.invMixColumns().toBytes(); + } + return fromBytes(&out_bytes); + } }; } diff --git a/lib/std/crypto/aes/armcrypto.zig b/lib/std/crypto/aes/armcrypto.zig index 714f3c0c3219..02cf207777a8 100644 --- a/lib/std/crypto/aes/armcrypto.zig +++ b/lib/std/crypto/aes/armcrypto.zig @@ -99,6 +99,17 @@ pub const Block = struct { return Block{ .repr = block1.repr | block2.repr }; } + /// Apply the inverse MixColumns operation to a block. + pub fn invMixColumns(block: Block) Block { + return Block{ + .repr = asm ( + \\ aesimc %[out].16b, %[in].16b + : [out] "=x" (-> Repr), + : [in] "x" (block.repr), + ), + }; + } + /// Perform operations on multiple blocks in parallel. pub const parallel = struct { /// The recommended number of AES encryption/decryption to perform in parallel for the chosen implementation. @@ -275,6 +286,15 @@ pub fn BlockVec(comptime blocks_count: comptime_int) type { } return out; } + + /// Apply the inverse MixColumns operation to each block in the vector. + pub fn invMixColumns(block_vec: Self) Self { + var out: Self = undefined; + inline for (0..native_words) |i| { + out.repr[i] = block_vec.repr[i].invMixColumns(); + } + return out; + } }; } diff --git a/lib/std/crypto/aes/soft.zig b/lib/std/crypto/aes/soft.zig index cec5abff4888..989635208bfe 100644 --- a/lib/std/crypto/aes/soft.zig +++ b/lib/std/crypto/aes/soft.zig @@ -265,6 +265,26 @@ pub const Block = struct { return Block{ .repr = x }; } + /// Apply the inverse MixColumns operation to a block. + pub fn invMixColumns(block: Block) Block { + var out: Repr = undefined; + inline for (0..4) |i| { + const col = block.repr[i]; + const b0: u8 = @truncate(col); + const b1: u8 = @truncate(col >> 8); + const b2: u8 = @truncate(col >> 16); + const b3: u8 = @truncate(col >> 24); + + const r0 = mul(0x0e, b0) ^ mul(0x0b, b1) ^ mul(0x0d, b2) ^ mul(0x09, b3); + const r1 = mul(0x09, b0) ^ mul(0x0e, b1) ^ mul(0x0b, b2) ^ mul(0x0d, b3); + const r2 = mul(0x0d, b0) ^ mul(0x09, b1) ^ mul(0x0e, b2) ^ mul(0x0b, b3); + const r3 = mul(0x0b, b0) ^ mul(0x0d, b1) ^ mul(0x09, b2) ^ mul(0x0e, b3); + + out[i] = @as(u32, r0) | (@as(u32, r1) << 8) | (@as(u32, r2) << 16) | (@as(u32, r3) << 24); + } + return Block{ .repr = out }; + } + /// Perform operations on multiple blocks in parallel. pub const parallel = struct { /// The recommended number of AES encryption/decryption to perform in parallel for the chosen implementation. @@ -441,6 +461,15 @@ pub fn BlockVec(comptime blocks_count: comptime_int) type { } return out; } + + /// Apply the inverse MixColumns operation to each block in the vector. + pub fn invMixColumns(block_vec: Self) Self { + var out: Self = undefined; + for (0..native_words) |i| { + out.repr[i] = block_vec.repr[i].invMixColumns(); + } + return out; + } }; } diff --git a/lib/std/crypto/argon2.zig b/lib/std/crypto/argon2.zig index 3737d252e915..f6bf85782db8 100644 --- a/lib/std/crypto/argon2.zig +++ b/lib/std/crypto/argon2.zig @@ -2,17 +2,16 @@ // https://github.com/golang/crypto/tree/master/argon2 // https://github.com/P-H-C/phc-winner-argon2 -const std = @import("std"); const builtin = @import("builtin"); +const std = @import("std"); const blake2 = crypto.hash.blake2; const crypto = std.crypto; +const Io = std.Io; const math = std.math; const mem = std.mem; const phc_format = pwhash.phc_format; const pwhash = crypto.pwhash; - -const Thread = std.Thread; const Blake2b512 = blake2.Blake2b512; const Blocks = std.array_list.AlignedManaged([block_length]u64, .@"16"); const H0 = [Blake2b512.digest_length + 8]u8; @@ -54,23 +53,24 @@ pub const Mode = enum { pub const Params = struct { const Self = @This(); - /// A [t]ime cost, which defines the amount of computation realized and therefore the execution + /// Time cost, which defines the amount of computation realized and therefore the execution /// time, given in number of iterations. t: u32, - /// A [m]emory cost, which defines the memory usage, given in kibibytes. + /// Memory cost, which defines the memory usage, given in kibibytes. m: u32, - /// A [p]arallelism degree, which defines the number of parallel threads. + /// Parallelism degree, which defines the number of independent tasks, + /// to be multiplexed onto threads when possible. p: u24, - /// The [secret] parameter, which is used for keyed hashing. This allows a secret key to be input + /// The secret parameter, which is used for keyed hashing. This allows a secret key to be input /// at hashing time (from some external location) and be folded into the value of the hash. This /// means that even if your salts and hashes are compromised, an attacker cannot brute-force to /// find the password without the key. secret: ?[]const u8 = null, - /// The [ad] parameter, which is used to fold any additional data into the hash value. Functionally, + /// The ad parameter, which is used to fold any additional data into the hash value. Functionally, /// this behaves almost exactly like the secret or salt parameters; the ad parameter is folding /// into the value of the hash. However, this parameter is used for different data. The salt /// should be a random string stored alongside your password. The secret should be a random key @@ -204,24 +204,24 @@ fn initBlocks( } fn processBlocks( - allocator: mem.Allocator, blocks: *Blocks, time: u32, memory: u32, threads: u24, mode: Mode, -) KdfError!void { + io: Io, +) Io.Cancelable!void { const lanes = memory / threads; const segments = lanes / sync_points; if (builtin.single_threaded or threads == 1) { - processBlocksSt(blocks, time, memory, threads, mode, lanes, segments); + processBlocksSync(blocks, time, memory, threads, mode, lanes, segments); } else { - try processBlocksMt(allocator, blocks, time, memory, threads, mode, lanes, segments); + try processBlocksAsync(blocks, time, memory, threads, mode, lanes, segments, io); } } -fn processBlocksSt( +fn processBlocksSync( blocks: *Blocks, time: u32, memory: u32, @@ -242,8 +242,7 @@ fn processBlocksSt( } } -fn processBlocksMt( - allocator: mem.Allocator, +fn processBlocksAsync( blocks: *Blocks, time: u32, memory: u32, @@ -251,26 +250,21 @@ fn processBlocksMt( mode: Mode, lanes: u32, segments: u32, -) KdfError!void { - var threads_list = try std.array_list.Managed(Thread).initCapacity(allocator, threads); - defer threads_list.deinit(); - + io: Io, +) Io.Cancelable!void { var n: u32 = 0; while (n < time) : (n += 1) { var slice: u32 = 0; while (slice < sync_points) : (slice += 1) { + var group: Io.Group = .init; + defer group.cancel(io); var lane: u24 = 0; while (lane < threads) : (lane += 1) { - const thread = try Thread.spawn(.{}, processSegment, .{ + group.async(io, processSegment, .{ blocks, time, memory, threads, mode, lanes, segments, n, slice, lane, }); - threads_list.appendAssumeCapacity(thread); - } - lane = 0; - while (lane < threads) : (lane += 1) { - threads_list.items[lane].join(); } - threads_list.clearRetainingCapacity(); + try group.await(io); } } } @@ -489,6 +483,7 @@ pub fn kdf( salt: []const u8, params: Params, mode: Mode, + io: Io, ) KdfError!void { if (derived_key.len < 4) return KdfError.WeakParameters; if (derived_key.len > max_int) return KdfError.OutputTooLong; @@ -510,7 +505,7 @@ pub fn kdf( blocks.appendNTimesAssumeCapacity(@splat(0), memory); initBlocks(&blocks, &h0, memory, params.p); - try processBlocks(allocator, &blocks, params.t, memory, params.p, mode); + try processBlocks(&blocks, params.t, memory, params.p, mode, io); finalize(&blocks, memory, params.p, derived_key); } @@ -533,14 +528,15 @@ const PhcFormatHasher = struct { params: Params, mode: Mode, buf: []u8, + io: Io, ) HasherError![]const u8 { if (params.secret != null or params.ad != null) return HasherError.InvalidEncoding; var salt: [default_salt_len]u8 = undefined; - crypto.random.bytes(&salt); + io.random(&salt); var hash: [default_hash_len]u8 = undefined; - try kdf(allocator, &hash, password, &salt, params, mode); + try kdf(allocator, &hash, password, &salt, params, mode, io); return phc_format.serialize(HashResult{ .alg_id = @tagName(mode), @@ -557,6 +553,7 @@ const PhcFormatHasher = struct { allocator: mem.Allocator, str: []const u8, password: []const u8, + io: Io, ) HasherError!void { const hash_result = try phc_format.deserialize(HashResult, str); @@ -572,7 +569,7 @@ const PhcFormatHasher = struct { if (expected_hash.len > hash_buf.len) return HasherError.InvalidEncoding; const hash = hash_buf[0..expected_hash.len]; - try kdf(allocator, hash, password, hash_result.salt.constSlice(), params, mode); + try kdf(allocator, hash, password, hash_result.salt.constSlice(), params, mode, io); if (!mem.eql(u8, hash, expected_hash)) return HasherError.PasswordVerificationFailed; } }; @@ -595,6 +592,7 @@ pub fn strHash( password: []const u8, options: HashOptions, out: []u8, + io: Io, ) Error![]const u8 { const allocator = options.allocator orelse return Error.AllocatorRequired; switch (options.encoding) { @@ -604,6 +602,7 @@ pub fn strHash( options.params, options.mode, out, + io, ), .crypt => return Error.InvalidEncoding, } @@ -621,12 +620,15 @@ pub fn strVerify( str: []const u8, password: []const u8, options: VerifyOptions, + io: Io, ) Error!void { const allocator = options.allocator orelse return Error.AllocatorRequired; - return PhcFormatHasher.verify(allocator, str, password); + return PhcFormatHasher.verify(allocator, str, password, io); } test "argon2d" { + if (true) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30074 + const password = [_]u8{0x01} ** 32; const salt = [_]u8{0x02} ** 16; const secret = [_]u8{0x03} ** 8; @@ -640,6 +642,7 @@ test "argon2d" { &salt, .{ .t = 3, .m = 32, .p = 4, .secret = &secret, .ad = &ad }, .argon2d, + std.testing.io, ); const want = [_]u8{ @@ -665,6 +668,7 @@ test "argon2i" { &salt, .{ .t = 3, .m = 32, .p = 4, .secret = &secret, .ad = &ad }, .argon2i, + std.testing.io, ); const want = [_]u8{ @@ -690,6 +694,7 @@ test "argon2id" { &salt, .{ .t = 3, .m = 32, .p = 4, .secret = &secret, .ad = &ad }, .argon2id, + std.testing.io, ); const want = [_]u8{ @@ -800,44 +805,44 @@ test "kdf" { .{ .mode = .argon2i, .time = 4, - .memory = 4096, + .memory = 256, .threads = 4, - .hash = "a11f7b7f3f93f02ad4bddb59ab62d121e278369288a0d0e7", + .hash = "f7dbbacbf16999e3700817a7e06f65a8db2e9fa9504ede4c", }, .{ .mode = .argon2d, .time = 4, - .memory = 4096, + .memory = 256, .threads = 4, - .hash = "935598181aa8dc2b720914aa6435ac8d3e3a4210c5b0fb2d", + .hash = "ea2970501cf49faa5ba1d2e6370204e9b57ca90a8fea937b", }, .{ .mode = .argon2id, .time = 4, - .memory = 4096, + .memory = 256, .threads = 4, - .hash = "145db9733a9f4ee43edf33c509be96b934d505a4efb33c5a", + .hash = "fbd40d5a8cb92f88c20bda4b3cdb1f9d5af1efa937032410", }, .{ .mode = .argon2i, .time = 4, - .memory = 1024, + .memory = 256, .threads = 8, - .hash = "0cdd3956aa35e6b475a7b0c63488822f774f15b43f6e6e17", + .hash = "15d3c398364e53f68fd12d19baf3f21432d964254fe27467", }, .{ .mode = .argon2d, .time = 4, - .memory = 1024, + .memory = 256, .threads = 8, - .hash = "83604fc2ad0589b9d055578f4d3cc55bc616df3578a896e9", + .hash = "23c9adc06f06e21e4612c1466a1be02627690932b02c0df0", }, .{ .mode = .argon2id, .time = 4, - .memory = 1024, + .memory = 256, .threads = 8, - .hash = "8dafa8e004f8ea96bf7c0f93eecf67a6047476143d15577f", + .hash = "f22802f8ca47be93f9954e4ce20c1e944e938fbd4a125d9d", }, .{ .mode = .argon2i, @@ -863,23 +868,23 @@ test "kdf" { .{ .mode = .argon2i, .time = 3, - .memory = 1024, + .memory = 256, .threads = 6, - .hash = "d236b29c2b2a09babee842b0dec6aa1e83ccbdea8023dced", + .hash = "ebc8f91964abd8ceab49a12963b0a9e57d635bfa2aad2884", }, .{ .mode = .argon2d, .time = 3, - .memory = 1024, + .memory = 256, .threads = 6, - .hash = "a3351b0319a53229152023d9206902f4ef59661cdca89481", + .hash = "1dd7202fd68da6675f769f4034b7a1db30d8785331954117", }, .{ .mode = .argon2id, .time = 3, - .memory = 1024, + .memory = 256, .threads = 6, - .hash = "1640b932f4b60e272f5d2207b9a9c626ffa1bd88d2349016", + .hash = "424436b6ee22a66b04b9d0cf78f190305c5c166bae8baa09", }, }; for (test_vectors) |v| { @@ -894,6 +899,7 @@ test "kdf" { salt, .{ .t = v.time, .m = v.memory, .p = v.threads }, v.mode, + std.testing.io, ); try std.testing.expectEqualSlices(u8, &dk, &want); @@ -903,6 +909,7 @@ test "kdf" { test "phc format hasher" { const allocator = std.testing.allocator; const password = "testpass"; + const io = std.testing.io; var buf: [128]u8 = undefined; const hash = try PhcFormatHasher.create( @@ -911,25 +918,29 @@ test "phc format hasher" { .{ .t = 3, .m = 32, .p = 4 }, .argon2id, &buf, + io, ); - try PhcFormatHasher.verify(allocator, hash, password); + try PhcFormatHasher.verify(allocator, hash, password, io); } test "password hash and password verify" { const allocator = std.testing.allocator; const password = "testpass"; + const io = std.testing.io; var buf: [128]u8 = undefined; const hash = try strHash( password, .{ .allocator = allocator, .params = .{ .t = 3, .m = 32, .p = 4 } }, &buf, + io, ); - try strVerify(hash, password, .{ .allocator = allocator }); + try strVerify(hash, password, .{ .allocator = allocator }, io); } test "kdf derived key length" { const allocator = std.testing.allocator; + const io = std.testing.io; const password = "testpass"; const salt = "saltsalt"; @@ -937,11 +948,11 @@ test "kdf derived key length" { const mode = Mode.argon2id; var dk1: [11]u8 = undefined; - try kdf(allocator, &dk1, password, salt, params, mode); + try kdf(allocator, &dk1, password, salt, params, mode, io); var dk2: [77]u8 = undefined; - try kdf(allocator, &dk2, password, salt, params, mode); + try kdf(allocator, &dk2, password, salt, params, mode, io); var dk3: [111]u8 = undefined; - try kdf(allocator, &dk3, password, salt, params, mode); + try kdf(allocator, &dk3, password, salt, params, mode, io); } diff --git a/lib/std/crypto/bcrypt.zig b/lib/std/crypto/bcrypt.zig index 62fc4fd4ccc4..267827c75c93 100644 --- a/lib/std/crypto/bcrypt.zig +++ b/lib/std/crypto/bcrypt.zig @@ -17,7 +17,7 @@ const HasherError = pwhash.HasherError; const EncodingError = phc_format.Error; const Error = pwhash.Error; -const salt_length: usize = 16; +pub const salt_length: usize = 16; const salt_str_length: usize = 22; const ct_str_length: usize = 31; const ct_length: usize = 24; @@ -426,7 +426,7 @@ pub const Params = struct { fn bcryptWithTruncation( password: []const u8, - salt: [salt_length]u8, + salt: *const [salt_length]u8, params: Params, ) [dk_length]u8 { var state = State{}; @@ -435,13 +435,13 @@ fn bcryptWithTruncation( @memcpy(password_buf[0..trimmed_len], password[0..trimmed_len]); password_buf[trimmed_len] = 0; const passwordZ = password_buf[0 .. trimmed_len + 1]; - state.expand(salt[0..], passwordZ); + state.expand(salt, passwordZ); const rounds: u64 = @as(u64, 1) << params.rounds_log; var k: u64 = 0; while (k < rounds) : (k += 1) { state.expand0(passwordZ); - state.expand0(salt[0..]); + state.expand0(salt); } crypto.secureZero(u8, &password_buf); @@ -467,7 +467,7 @@ fn bcryptWithTruncation( /// For key derivation, use `bcrypt.pbkdf()` or `bcrypt.opensshKdf()` instead. pub fn bcrypt( password: []const u8, - salt: [salt_length]u8, + salt: *const [salt_length]u8, params: Params, ) [dk_length]u8 { if (password.len <= 72 or params.silently_truncate_password) { @@ -475,7 +475,7 @@ pub fn bcrypt( } var pre_hash: [HmacSha512.mac_length]u8 = undefined; - HmacSha512.create(&pre_hash, password, &salt); + HmacSha512.create(&pre_hash, password, salt); const Encoder = crypt_format.Codec.Encoder; var pre_hash_b64: [Encoder.calcSize(pre_hash.len)]u8 = undefined; @@ -623,16 +623,16 @@ const crypt_format = struct { fn strHashInternal( password: []const u8, - salt: [salt_length]u8, + salt: *const [salt_length]u8, params: Params, ) [hash_length]u8 { var dk = bcrypt(password, salt, params); var salt_str: [salt_str_length]u8 = undefined; - _ = Codec.Encoder.encode(salt_str[0..], salt[0..]); + _ = Codec.Encoder.encode(&salt_str, salt); var ct_str: [ct_str_length]u8 = undefined; - _ = Codec.Encoder.encode(ct_str[0..], dk[0..]); + _ = Codec.Encoder.encode(&ct_str, dk[0..]); var s_buf: [hash_length]u8 = undefined; const s = fmt.bufPrint( @@ -657,16 +657,27 @@ const PhcFormatHasher = struct { hash: BinValue(dk_length), }; - /// Return a non-deterministic hash of the password encoded as a PHC-format string + /// Return a non-deterministic hash of the password encoded as a PHC-format string. fn create( password: []const u8, params: Params, buf: []u8, + io: std.Io, ) HasherError![]const u8 { var salt: [salt_length]u8 = undefined; - crypto.random.bytes(&salt); + io.random(&salt); + return createWithSalt(password, params, buf, salt); + } - const hash = bcrypt(password, salt, params); + /// Return a deterministic hash of the password encoded as a PHC-format string. + /// Uses the provided salt instead of generating one randomly. + fn createWithSalt( + password: []const u8, + params: Params, + buf: []u8, + salt: [salt_length]u8, + ) HasherError![]const u8 { + const hash = bcrypt(password, &salt, params); return phc_format.serialize(HashResult{ .alg_id = alg_id, @@ -688,11 +699,11 @@ const PhcFormatHasher = struct { if (hash_result.salt.len != salt_length or hash_result.hash.len != dk_length) return HasherError.InvalidEncoding; - const params = Params{ + const params: Params = .{ .rounds_log = hash_result.r, .silently_truncate_password = silently_truncate_password, }; - const hash = bcrypt(password, hash_result.salt.buf, params); + const hash = bcrypt(password, &hash_result.salt.buf, params); const expected_hash = hash_result.hash.constSlice(); if (!mem.eql(u8, &hash, expected_hash)) return HasherError.PasswordVerificationFailed; @@ -709,11 +720,22 @@ const CryptFormatHasher = struct { password: []const u8, params: Params, buf: []u8, + io: std.Io, ) HasherError![]const u8 { - if (buf.len < pwhash_str_length) return HasherError.NoSpaceLeft; - var salt: [salt_length]u8 = undefined; - crypto.random.bytes(&salt); + io.random(&salt); + return createWithSalt(password, params, buf, &salt); + } + + /// Return a deterministic hash of the password encoded into the modular crypt format. + /// Uses the provided salt instead of generating one randomly. + fn createWithSalt( + password: []const u8, + params: Params, + buf: []u8, + salt: *const [salt_length]u8, + ) HasherError![]const u8 { + if (buf.len < pwhash_str_length) return HasherError.NoSpaceLeft; const hash = crypt_format.strHashInternal(password, salt, params); @memcpy(buf[0..hash.len], &hash); @@ -736,9 +758,9 @@ const CryptFormatHasher = struct { const salt_str = str[7..][0..salt_str_length]; var salt: [salt_length]u8 = undefined; - crypt_format.Codec.Decoder.decode(salt[0..], salt_str[0..]) catch return HasherError.InvalidEncoding; + crypt_format.Codec.Decoder.decode(&salt, salt_str) catch return HasherError.InvalidEncoding; - const wanted_s = crypt_format.strHashInternal(password, salt, .{ + const wanted_s = crypt_format.strHashInternal(password, &salt, .{ .rounds_log = rounds_log, .silently_truncate_password = silently_truncate_password, }); @@ -756,21 +778,42 @@ pub const HashOptions = struct { encoding: pwhash.Encoding, }; -/// Compute a hash of a password using 2^rounds_log rounds of the bcrypt key stretching function. -/// bcrypt is a computationally expensive and cache-hard function, explicitly designed to slow down exhaustive searches. +/// Compute a hash of a password using 2^rounds_log rounds of the bcrypt key +/// stretching function. /// -/// The function returns a string that includes all the parameters required for verification. +/// bcrypt is a computationally expensive and cache-hard function, explicitly +/// designed to slow down exhaustive searches. +/// +/// The function returns a string that includes all the parameters required for +/// verification. /// -/// IMPORTANT: by design, bcrypt silently truncates passwords to 72 bytes. -/// If this is an issue for your application, set the `silently_truncate_password` option to `false`. +/// By design, bcrypt silently truncates passwords to 72 bytes. If this is an +/// issue for your application, set the `silently_truncate_password` option to +/// `false`. pub fn strHash( password: []const u8, options: HashOptions, out: []u8, + io: std.Io, ) Error![]const u8 { switch (options.encoding) { - .phc => return PhcFormatHasher.create(password, options.params, out), - .crypt => return CryptFormatHasher.create(password, options.params, out), + .phc => return PhcFormatHasher.create(password, options.params, out, io), + .crypt => return CryptFormatHasher.create(password, options.params, out, io), + } +} + +/// Compute a deterministic hash of a password using the bcrypt key derivation function. +/// The function returns a string that includes all the parameters required for verification. +/// Uses the provided salt instead of generating one randomly. +pub fn strHashWithSalt( + password: []const u8, + options: HashOptions, + out: []u8, + salt: [salt_length]u8, +) Error![]const u8 { + switch (options.encoding) { + .phc => return PhcFormatHasher.createWithSalt(password, options.params, out, salt), + .crypt => return CryptFormatHasher.createWithSalt(password, options.params, out, &salt), } } @@ -796,8 +839,9 @@ pub fn strVerify( } test "bcrypt codec" { + const io = testing.io; var salt: [salt_length]u8 = undefined; - crypto.random.bytes(&salt); + io.random(&salt); var salt_str: [salt_str_length]u8 = undefined; _ = crypt_format.Codec.Encoder.encode(salt_str[0..], salt[0..]); var salt2: [salt_length]u8 = undefined; @@ -806,14 +850,16 @@ test "bcrypt codec" { } test "bcrypt crypt format" { - var hash_options = HashOptions{ + const io = testing.io; + + var hash_options: HashOptions = .{ .params = .{ .rounds_log = 5, .silently_truncate_password = false }, .encoding = .crypt, }; - var verify_options = VerifyOptions{ .silently_truncate_password = false }; + var verify_options: VerifyOptions = .{ .silently_truncate_password = false }; var buf: [hash_length]u8 = undefined; - const s = try strHash("password", hash_options, &buf); + const s = try strHash("password", hash_options, &buf, io); try testing.expect(mem.startsWith(u8, s, crypt_format.prefix)); try strVerify(s, "password", verify_options); @@ -823,7 +869,7 @@ test "bcrypt crypt format" { ); var long_buf: [hash_length]u8 = undefined; - var long_s = try strHash("password" ** 100, hash_options, &long_buf); + var long_s = try strHash("password" ** 100, hash_options, &long_buf, io); try testing.expect(mem.startsWith(u8, long_s, crypt_format.prefix)); try strVerify(long_s, "password" ** 100, verify_options); @@ -834,7 +880,7 @@ test "bcrypt crypt format" { hash_options.params.silently_truncate_password = true; verify_options.silently_truncate_password = true; - long_s = try strHash("password" ** 100, hash_options, &long_buf); + long_s = try strHash("password" ** 100, hash_options, &long_buf, io); try strVerify(long_s, "password" ** 101, verify_options); try strVerify( @@ -845,15 +891,16 @@ test "bcrypt crypt format" { } test "bcrypt phc format" { - var hash_options = HashOptions{ + const io = testing.io; + var hash_options: HashOptions = .{ .params = .{ .rounds_log = 5, .silently_truncate_password = false }, .encoding = .phc, }; - var verify_options = VerifyOptions{ .silently_truncate_password = false }; + var verify_options: VerifyOptions = .{ .silently_truncate_password = false }; const prefix = "$bcrypt$"; var buf: [hash_length * 2]u8 = undefined; - const s = try strHash("password", hash_options, &buf); + const s = try strHash("password", hash_options, &buf, io); try testing.expect(mem.startsWith(u8, s, prefix)); try strVerify(s, "password", verify_options); @@ -863,7 +910,7 @@ test "bcrypt phc format" { ); var long_buf: [hash_length * 2]u8 = undefined; - var long_s = try strHash("password" ** 100, hash_options, &long_buf); + var long_s = try strHash("password" ** 100, hash_options, &long_buf, io); try testing.expect(mem.startsWith(u8, long_s, prefix)); try strVerify(long_s, "password" ** 100, verify_options); @@ -874,7 +921,7 @@ test "bcrypt phc format" { hash_options.params.silently_truncate_password = true; verify_options.silently_truncate_password = true; - long_s = try strHash("password" ** 100, hash_options, &long_buf); + long_s = try strHash("password" ** 100, hash_options, &long_buf, io); try strVerify(long_s, "password" ** 101, verify_options); try strVerify( @@ -884,6 +931,25 @@ test "bcrypt phc format" { ); } +test "strHashWithSalt deterministic" { + const password = "testpass"; + const salt: [salt_length]u8 = "0123456789abcdef".*; + const params: Params = .{ .rounds_log = 5, .silently_truncate_password = false }; + + var buf1: [hash_length * 2]u8 = undefined; + var buf2: [hash_length * 2]u8 = undefined; + + const str1 = try strHashWithSalt(password, .{ .params = params, .encoding = .phc }, &buf1, salt); + const str2 = try strHashWithSalt(password, .{ .params = params, .encoding = .phc }, &buf2, salt); + try testing.expectEqualStrings(str1, str2); + try strVerify(str1, password, .{ .silently_truncate_password = false }); + + const str3 = try strHashWithSalt(password, .{ .params = params, .encoding = .crypt }, &buf1, salt); + const str4 = try strHashWithSalt(password, .{ .params = params, .encoding = .crypt }, &buf2, salt); + try testing.expectEqualStrings(str3, str4); + try strVerify(str3, password, .{ .silently_truncate_password = false }); +} + test "openssh kdf" { var key: [100]u8 = undefined; const pass = "password"; diff --git a/lib/std/crypto/benchmark.zig b/lib/std/crypto/benchmark.zig index f2952762105c..22f2b6fd106c 100644 --- a/lib/std/crypto/benchmark.zig +++ b/lib/std/crypto/benchmark.zig @@ -1,10 +1,12 @@ // zig run -O ReleaseFast --zig-lib-dir ../.. benchmark.zig -const std = @import("std"); const builtin = @import("builtin"); + +const std = @import("std"); +const Io = std.Io; const mem = std.mem; const time = std.time; -const Timer = time.Timer; +const Timer = std.time.Timer; const crypto = std.crypto; const KiB = 1024; @@ -450,6 +452,7 @@ fn benchmarkPwhash( comptime ty: anytype, comptime params: *const anyopaque, comptime count: comptime_int, + io: std.Io, ) !f64 { const password = "testpass" ** 2; const opts = ty.HashOptions{ @@ -459,12 +462,20 @@ fn benchmarkPwhash( }; var buf: [256]u8 = undefined; + const strHash = ty.strHash; + const strHashFnInfo = @typeInfo(@TypeOf(strHash)).@"fn"; + const needs_io = strHashFnInfo.params.len == 4; + var timer = try Timer.start(); const start = timer.lap(); { var i: usize = 0; while (i < count) : (i += 1) { - _ = try ty.strHash(password, opts, &buf); + if (needs_io) { + _ = try strHash(password, opts, &buf, io); + } else { + _ = try strHash(password, opts, &buf); + } mem.doNotOptimizeAway(&buf); } } @@ -492,16 +503,16 @@ fn mode(comptime x: comptime_int) comptime_int { return if (builtin.mode == .Debug) x / 64 else x; } -pub fn main() !void { +pub fn main(init: std.process.Init) !void { + const io = init.io; + const arena = init.arena.allocator(); + // Size of buffer is about size of printed message. var stdout_buffer: [0x100]u8 = undefined; - var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); + var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer); const stdout = &stdout_writer.interface; - var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena.deinit(); - const arena_allocator = arena.allocator(); - const args = try std.process.argsAlloc(arena_allocator); + const args = try init.minimal.args.toSlice(arena); var filter: ?[]u8 = ""; @@ -538,27 +549,23 @@ pub fn main() !void { } inline for (hashes) |H| { - if (filter == null or std.mem.indexOf(u8, H.name, filter.?) != null) { + if (filter == null or std.mem.find(u8, H.name, filter.?) != null) { const throughput = try benchmarkHash(H.ty, mode(128 * MiB)); try stdout.print("{s:>17}: {:10} MiB/s\n", .{ H.name, throughput / (1 * MiB) }); try stdout.flush(); } } - var io_threaded = std.Io.Threaded.init(arena_allocator); - defer io_threaded.deinit(); - const io = io_threaded.io(); - inline for (parallel_hashes) |H| { - if (filter == null or std.mem.indexOf(u8, H.name, filter.?) != null) { - const throughput = try benchmarkHashParallel(H.ty, mode(128 * MiB), arena_allocator, io); + if (filter == null or std.mem.find(u8, H.name, filter.?) != null) { + const throughput = try benchmarkHashParallel(H.ty, mode(128 * MiB), arena, io); try stdout.print("{s:>17}: {:10} MiB/s\n", .{ H.name, throughput / (1 * MiB) }); try stdout.flush(); } } inline for (macs) |M| { - if (filter == null or std.mem.indexOf(u8, M.name, filter.?) != null) { + if (filter == null or std.mem.find(u8, M.name, filter.?) != null) { const throughput = try benchmarkMac(M.ty, mode(128 * MiB)); try stdout.print("{s:>17}: {:10} MiB/s\n", .{ M.name, throughput / (1 * MiB) }); try stdout.flush(); @@ -566,7 +573,7 @@ pub fn main() !void { } inline for (exchanges) |E| { - if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) { + if (filter == null or std.mem.find(u8, E.name, filter.?) != null) { const throughput = try benchmarkKeyExchange(E.ty, mode(1000)); try stdout.print("{s:>17}: {:10} exchanges/s\n", .{ E.name, throughput }); try stdout.flush(); @@ -574,7 +581,7 @@ pub fn main() !void { } inline for (signatures) |E| { - if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) { + if (filter == null or std.mem.find(u8, E.name, filter.?) != null) { const throughput = try benchmarkSignature(E.ty, mode(1000)); try stdout.print("{s:>17}: {:10} signatures/s\n", .{ E.name, throughput }); try stdout.flush(); @@ -582,7 +589,7 @@ pub fn main() !void { } inline for (signature_verifications) |E| { - if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) { + if (filter == null or std.mem.find(u8, E.name, filter.?) != null) { const throughput = try benchmarkSignatureVerification(E.ty, mode(1000)); try stdout.print("{s:>17}: {:10} verifications/s\n", .{ E.name, throughput }); try stdout.flush(); @@ -590,7 +597,7 @@ pub fn main() !void { } inline for (batch_signature_verifications) |E| { - if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) { + if (filter == null or std.mem.find(u8, E.name, filter.?) != null) { const throughput = try benchmarkBatchSignatureVerification(E.ty, mode(1000)); try stdout.print("{s:>17}: {:10} verifications/s (batch)\n", .{ E.name, throughput }); try stdout.flush(); @@ -598,7 +605,7 @@ pub fn main() !void { } inline for (aeads) |E| { - if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) { + if (filter == null or std.mem.find(u8, E.name, filter.?) != null) { const throughput = try benchmarkAead(E.ty, mode(128 * MiB)); try stdout.print("{s:>17}: {:10} MiB/s\n", .{ E.name, throughput / (1 * MiB) }); try stdout.flush(); @@ -606,7 +613,7 @@ pub fn main() !void { } inline for (aes) |E| { - if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) { + if (filter == null or std.mem.find(u8, E.name, filter.?) != null) { const throughput = try benchmarkAes(E.ty, mode(100000000)); try stdout.print("{s:>17}: {:10} ops/s\n", .{ E.name, throughput }); try stdout.flush(); @@ -614,7 +621,7 @@ pub fn main() !void { } inline for (aes8) |E| { - if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) { + if (filter == null or std.mem.find(u8, E.name, filter.?) != null) { const throughput = try benchmarkAes8(E.ty, mode(10000000)); try stdout.print("{s:>17}: {:10} ops/s\n", .{ E.name, throughput }); try stdout.flush(); @@ -622,15 +629,15 @@ pub fn main() !void { } inline for (pwhashes) |H| { - if (filter == null or std.mem.indexOf(u8, H.name, filter.?) != null) { - const throughput = try benchmarkPwhash(arena_allocator, H.ty, H.params, mode(64)); + if (filter == null or std.mem.find(u8, H.name, filter.?) != null) { + const throughput = try benchmarkPwhash(arena, H.ty, H.params, mode(64), io); try stdout.print("{s:>17}: {d:10.3} s/ops\n", .{ H.name, throughput }); try stdout.flush(); } } inline for (kems) |E| { - if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) { + if (filter == null or std.mem.find(u8, E.name, filter.?) != null) { const throughput = try benchmarkKem(E.ty, mode(1000)); try stdout.print("{s:>17}: {:10} encaps/s\n", .{ E.name, throughput }); try stdout.flush(); @@ -638,7 +645,7 @@ pub fn main() !void { } inline for (kems) |E| { - if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) { + if (filter == null or std.mem.find(u8, E.name, filter.?) != null) { const throughput = try benchmarkKemDecaps(E.ty, mode(25000)); try stdout.print("{s:>17}: {:10} decaps/s\n", .{ E.name, throughput }); try stdout.flush(); @@ -646,7 +653,7 @@ pub fn main() !void { } inline for (kems) |E| { - if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) { + if (filter == null or std.mem.find(u8, E.name, filter.?) != null) { const throughput = try benchmarkKemKeyGen(E.ty, mode(25000)); try stdout.print("{s:>17}: {:10} keygen/s\n", .{ E.name, throughput }); try stdout.flush(); diff --git a/lib/std/crypto/blake3.zig b/lib/std/crypto/blake3.zig index 53b28c24a1e3..1a1afab3ee4a 100644 --- a/lib/std/crypto/blake3.zig +++ b/lib/std/crypto/blake3.zig @@ -1,9 +1,11 @@ -const std = @import("std"); const builtin = @import("builtin"); + +const std = @import("std"); const fmt = std.fmt; const mem = std.mem; const Io = std.Io; const Thread = std.Thread; +const Allocator = std.mem.Allocator; const Vec4 = @Vector(4, u32); const Vec8 = @Vector(8, u32); @@ -767,7 +769,7 @@ fn buildMerkleTreeLayerParallel( key: [8]u32, flags: Flags, io: Io, -) void { +) Io.Cancelable!void { const num_parents = input_cvs.len / 2; // Process sequentially with SIMD for smaller tree layers to avoid thread overhead @@ -787,6 +789,7 @@ fn buildMerkleTreeLayerParallel( const num_workers = Thread.getCpuCount() catch 1; const parents_per_worker = (num_parents + num_workers - 1) / num_workers; var group: Io.Group = .init; + defer group.cancel(io); for (0..num_workers) |worker_id| { const start_idx = worker_id * parents_per_worker; @@ -801,7 +804,7 @@ fn buildMerkleTreeLayerParallel( .flags = flags, }}); } - group.wait(io); + try group.await(io); } fn parentOutput(parent_block: []const u8, key: [8]u32, flags: Flags) Output { @@ -987,7 +990,7 @@ pub const Blake3 = struct { d.final(out); } - pub fn hashParallel(b: []const u8, out: []u8, options: Options, allocator: std.mem.Allocator, io: Io) !void { + pub fn hashParallel(b: []const u8, out: []u8, options: Options, allocator: Allocator, io: Io) error{ OutOfMemory, Canceled }!void { if (b.len < parallel_threshold) { return hash(b, out, options); } @@ -1008,6 +1011,7 @@ pub const Blake3 = struct { const num_workers = thread_count; const chunks_per_worker = (num_full_chunks + num_workers - 1) / num_workers; var group: Io.Group = .init; + defer group.cancel(io); for (0..num_workers) |worker_id| { const start_chunk = worker_id * chunks_per_worker; @@ -1022,7 +1026,7 @@ pub const Blake3 = struct { .flags = flags, }}); } - group.wait(io); + try group.await(io); // Build Merkle tree in parallel layers using ping-pong buffers const max_intermediate_size = (num_full_chunks + 1) / 2; @@ -1040,7 +1044,7 @@ pub const Blake3 = struct { const has_odd = current_level.len % 2 == 1; const next_level_size = num_parents + @intFromBool(has_odd); - buildMerkleTreeLayerParallel( + try buildMerkleTreeLayerParallel( current_level[0 .. num_parents * 2], next_level_buf[0..num_parents], key_words, diff --git a/lib/std/crypto/codecs/asn1/test.zig b/lib/std/crypto/codecs/asn1/test.zig index fe12cba81985..bdfb47e2dfb6 100644 --- a/lib/std/crypto/codecs/asn1/test.zig +++ b/lib/std/crypto/codecs/asn1/test.zig @@ -73,8 +73,8 @@ test AllTypes { try std.testing.expectEqualSlices(u8, encoded, buf); // Use this to update test file. - // const dir = try std.fs.cwd().openDir("lib/std/crypto/asn1", .{}); - // var file = try dir.createFile(path, .{}); - // defer file.close(); + // const dir = try Io.Dir.cwd().openDir(io, "lib/std/crypto/asn1", .{}); + // var file = try dir.createFile(io, path, .{}); + // defer file.close(io); // try file.writeAll(buf); } diff --git a/lib/std/crypto/ecdsa.zig b/lib/std/crypto/ecdsa.zig index 85f6e51006d1..ff583896b9b0 100644 --- a/lib/std/crypto/ecdsa.zig +++ b/lib/std/crypto/ecdsa.zig @@ -135,8 +135,8 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type { /// The function returns a slice, that can be shorter than der_encoded_length_max. pub fn toDer(sig: Signature, buf: *[der_encoded_length_max]u8) []u8 { var w: std.Io.Writer = .fixed(buf); - const sig_r = mem.trimLeft(u8, &sig.r, &.{0}); - const sig_s = mem.trimLeft(u8, &sig.s, &.{0}); + const sig_r = mem.trimStart(u8, &sig.r, &.{0}); + const sig_s = mem.trimStart(u8, &sig.s, &.{0}); const r_len = @as(u8, @intCast(sig_r.len + (sig_r[0] >> 7))); const s_len = @as(u8, @intCast(sig_s.len + (sig_s[0] >> 7))); const seq_len = @as(u8, @intCast(2 + r_len + 2 + s_len)); @@ -323,10 +323,10 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type { } /// Generate a new, random key pair. - pub fn generate() KeyPair { + pub fn generate(io: std.Io) KeyPair { var random_seed: [seed_length]u8 = undefined; while (true) { - crypto.random.bytes(&random_seed); + io.random(&random_seed); return generateDeterministic(random_seed) catch { @branchHint(.unlikely); continue; @@ -417,12 +417,13 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type { test "Basic operations over EcdsaP384Sha384" { if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + const io = testing.io; const Scheme = EcdsaP384Sha384; - const kp = Scheme.KeyPair.generate(); + const kp = Scheme.KeyPair.generate(io); const msg = "test"; var noise: [Scheme.noise_length]u8 = undefined; - crypto.random.bytes(&noise); + io.random(&noise); const sig = try kp.sign(msg, noise); try sig.verify(msg, kp.public_key); @@ -433,12 +434,13 @@ test "Basic operations over EcdsaP384Sha384" { test "Basic operations over Secp256k1" { if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + const io = testing.io; const Scheme = EcdsaSecp256k1Sha256oSha256; - const kp = Scheme.KeyPair.generate(); + const kp = Scheme.KeyPair.generate(io); const msg = "test"; var noise: [Scheme.noise_length]u8 = undefined; - crypto.random.bytes(&noise); + io.random(&noise); const sig = try kp.sign(msg, noise); try sig.verify(msg, kp.public_key); @@ -449,12 +451,13 @@ test "Basic operations over Secp256k1" { test "Basic operations over EcdsaP384Sha256" { if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + const io = testing.io; const Scheme = Ecdsa(crypto.ecc.P384, crypto.hash.sha2.Sha256); - const kp = Scheme.KeyPair.generate(); + const kp = Scheme.KeyPair.generate(io); const msg = "test"; var noise: [Scheme.noise_length]u8 = undefined; - crypto.random.bytes(&noise); + io.random(&noise); const sig = try kp.sign(msg, noise); try sig.verify(msg, kp.public_key); @@ -502,8 +505,10 @@ test "Verifying a existing signature with EcdsaP384Sha256" { test "Prehashed message operations" { if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + const io = testing.io; + const Scheme = EcdsaP256Sha256; - const kp = Scheme.KeyPair.generate(); + const kp = Scheme.KeyPair.generate(io); const msg = "test message for prehashed signing"; const Hash = crypto.hash.sha2.Sha256; @@ -518,7 +523,7 @@ test "Prehashed message operations" { try testing.expectError(error.SignatureVerificationFailed, sig.verifyPrehashed(bad_hash, kp.public_key)); var noise: [Scheme.noise_length]u8 = undefined; - crypto.random.bytes(&noise); + io.random(&noise); const sig_with_noise = try kp.signPrehashed(msg_hash, noise); try sig_with_noise.verifyPrehashed(msg_hash, kp.public_key); @@ -1628,8 +1633,9 @@ fn tvTry(comptime Scheme: type, vector: TestVector) !void { test "Sec1 encoding/decoding" { if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + const io = testing.io; const Scheme = EcdsaP384Sha384; - const kp = Scheme.KeyPair.generate(); + const kp = Scheme.KeyPair.generate(io); const pk = kp.public_key; const pk_compressed_sec1 = pk.toCompressedSec1(); const pk_recovered1 = try Scheme.PublicKey.fromSec1(&pk_compressed_sec1); diff --git a/lib/std/crypto/hybrid_kem.zig b/lib/std/crypto/hybrid_kem.zig new file mode 100644 index 000000000000..1ce034882a62 --- /dev/null +++ b/lib/std/crypto/hybrid_kem.zig @@ -0,0 +1,1102 @@ +//! Hybrid Post-Quantum/Traditional Key Encapsulation Mechanisms. +//! +//! Hybrid KEMs combine a post-quantum secure KEM with a traditional +//! elliptic curve Diffie-Hellman key exchange. +//! +//! The hybrid construction provides security against both classical and quantum +//! adversaries: even if one component is broken, the combined scheme remains secure +//! as long as the other component holds. +//! +//! The implementation follows the IETF CFRG draft specification for concrete hybrid KEMs: +//! https://datatracker.ietf.org/doc/draft-irtf-cfrg-concrete-hybrid-kems/ +//! +//! The combiner uses the C2PRI construction to derive the final shared secret +//! from the component shared secrets, ciphertext, and public key. + +const std = @import("std"); +const crypto = std.crypto; +const fmt = std.fmt; +const mem = std.mem; + +const sha3 = crypto.hash.sha3; +const ml_kem = crypto.kem.ml_kem; +const X25519 = crypto.dh.X25519; +const P256 = crypto.ecc.P256; +const P384 = crypto.ecc.P384; + +/// ML-KEM-768 combined with X25519 (Curve25519) aka X-Wing. +/// Targets approximately 128-bit post-quantum security level. +pub const MlKem768X25519 = HybridKem(.{ + .name = "MLKEM768-X25519", + .label = "\\.//^\\", + .PqKem = ml_kem.MLKem768, + .Group = X25519Group, + .pq_nseed = 64, + .Nseed = 32, + .Nek = 1216, + .Ndk = 32, + .Nct = 1120, + .Nss = 32, +}); + +/// ML-KEM-768 combined with NIST P-256. +/// Targets approximately 128-bit post-quantum security level. +pub const MlKem768P256 = HybridKem(.{ + .name = "MLKEM768-P256", + .label = "MLKEM768-P256", + .PqKem = ml_kem.MLKem768, + .Group = P256Group, + .pq_nseed = 64, + .Nseed = 32, + .Nek = 1249, + .Ndk = 32, + .Nct = 1153, + .Nss = 32, +}); + +/// ML-KEM-1024 combined with NIST P-384. +/// Targets approximately 192-bit post-quantum security level. +pub const MlKem1024P384 = HybridKem(.{ + .name = "MLKEM1024-P384", + .label = "MLKEM1024-P384", + .PqKem = ml_kem.MLKem1024, + .Group = P384Group, + .pq_nseed = 64, + .Nseed = 32, + .Nek = 1665, + .Ndk = 32, + .Nct = 1665, + .Nss = 32, +}); + +/// Configuration parameters for a hybrid KEM. +pub const Params = struct { + /// Human-readable name of the hybrid KEM (e.g., "MLKEM768-X25519"). + name: []const u8, + /// Domain separation label used in the combiner function. + label: []const u8, + /// The post-quantum KEM type (e.g., ml_kem.MLKem768). + PqKem: type, + /// The traditional elliptic curve group type. + Group: type, + /// Seed length in bytes for the post-quantum KEM key generation. + pq_nseed: usize, + /// Seed length in bytes for the hybrid KEM (decapsulation key size). + Nseed: usize, + /// Encapsulation key (public key) length in bytes. + Nek: usize, + /// Decapsulation key (secret key) length in bytes. + Ndk: usize, + /// Ciphertext length in bytes. + Nct: usize, + /// Shared secret length in bytes. + Nss: usize, + /// Extendable output function for seed expansion (default: SHAKE256). + Xof: type = sha3.Shake256, +}; + +/// Constructs a hybrid KEM type from the given parameters. +/// +/// A hybrid KEM combines a post-quantum KEM with a traditional elliptic curve +/// Diffie-Hellman key exchange. The shared secrets from both components are +/// combined using the C2PRI combiner construction with SHA3-256. +/// +/// The resulting type provides: +/// - `PublicKey`: The hybrid encapsulation (public) key +/// - `SecretKey`: The hybrid decapsulation (secret) key +/// - `KeyPair`: A public/secret key pair +/// - `EncapsulatedSecret`: A shared secret with its ciphertext +pub fn HybridKem(comptime params: Params) type { + return struct { + const is_nist_curve = params.Group == P256Group or params.Group == P384Group; + + fn expandRandomnessSeed(seed: [32]u8) ![params.Group.seed_length]u8 { + if (!is_nist_curve) return seed; + var xof = params.Xof.init(.{}); + xof.update(&seed); + var expanded: [params.Group.seed_length]u8 = undefined; + xof.squeeze(&expanded); + return expanded; + } + + fn expandDecapsKeyG(seed: [params.Nseed]u8) !struct { + ek_pq: params.PqKem.PublicKey, + ek_t: [params.Group.element_length]u8, + dk_pq: params.PqKem.SecretKey, + dk_t: [params.Group.scalar_length]u8, + } { + var xof = params.Xof.init(.{}); + xof.update(&seed); + var seeds: [params.pq_nseed + params.Group.seed_length]u8 = undefined; + xof.squeeze(&seeds); + + const kp_pq = try params.PqKem.KeyPair.generateDeterministic(seeds[0..params.pq_nseed].*); + const dk_t = try params.Group.randomScalar(seeds[params.pq_nseed..]); + const ek_t_point = try params.Group.mulBase(dk_t); + + return .{ + .ek_pq = kp_pq.public_key, + .ek_t = if (is_nist_curve) params.Group.encodePoint(ek_t_point) else ek_t_point, + .dk_pq = kp_pq.secret_key, + .dk_t = dk_t, + }; + } + + fn c2priCombiner(ss_pq: [32]u8, ss_t: [params.Group.scalar_length]u8, ct_t: []const u8, ek_t: []const u8) [params.Nss]u8 { + var hasher = sha3.Sha3_256.init(.{}); + hasher.update(&ss_pq); + hasher.update(&ss_t); + hasher.update(ct_t); + hasher.update(ek_t); + hasher.update(params.label); + var output: [params.Nss]u8 = undefined; + hasher.final(&output); + return output; + } + + /// A hybrid KEM public key (encapsulation key). + /// + /// The public key is the concatenation of the post-quantum KEM public key + /// and the traditional elliptic curve public key. + pub const PublicKey = struct { + bytes: [params.Nek]u8, + + /// Size of a serialized representation of the key, in bytes. + pub const encoded_length = params.Nek; + + /// Serializes the key into a byte array. + pub fn toBytes(self: PublicKey) [encoded_length]u8 { + return self.bytes; + } + + /// Deserializes the key from a byte array. + pub fn fromBytes(buf: *const [encoded_length]u8) PublicKey { + return .{ .bytes = buf.* }; + } + + /// Generates a shared secret, encapsulated for the public key, + /// using random bytes. + /// + /// This is recommended over `encapsDeterministic`. + pub fn encaps(pk: PublicKey, io: std.Io) !EncapsulatedSecret { + var seed_pq: [32]u8 = undefined; + io.random(&seed_pq); + var seed_t: [32]u8 = undefined; + io.random(&seed_t); + var seed_t_expanded: [params.Group.seed_length]u8 = try expandRandomnessSeed(seed_t); + return encapsInner(pk, &seed_pq, &seed_t_expanded); + } + + /// Generates a shared secret, encapsulated for the public key, + /// using the provided seed. + /// + /// Calling `encaps` instead is recommended. + pub fn encapsDeterministic(pk: PublicKey, seed: []const u8) !EncapsulatedSecret { + if (seed.len < 32) return error.InsufficientRandomness; + var seed_pq: [32]u8 = seed[0..32].*; + var seed_t_expanded: [params.Group.seed_length]u8 = undefined; + + const t_randomness = seed[32..]; + if (t_randomness.len < params.Group.seed_length) { + // Provided randomness is shorter than seed_length, use it directly + // (test vectors provide just enough for randomScalar) + @memcpy(seed_t_expanded[0..t_randomness.len], t_randomness); + // Pad the rest with zeros if needed (shouldn't be used by randomScalar) + if (t_randomness.len < params.Group.seed_length) { + @memset(seed_t_expanded[t_randomness.len..], 0); + } + } else { + // Full randomness provided + @memcpy(&seed_t_expanded, t_randomness[0..params.Group.seed_length]); + } + + return encapsInner(pk, &seed_pq, &seed_t_expanded); + } + + fn encapsInner( + pk: PublicKey, + seed_pq: *[32]u8, + seed_t_expanded: *[params.Group.seed_length]u8, + ) !EncapsulatedSecret { + const pq_nek = params.PqKem.PublicKey.encoded_length; + const ek_pq = try params.PqKem.PublicKey.fromBytes(pk.bytes[0..pq_nek]); + const ek_t = pk.bytes[pq_nek..][0..params.Group.element_length]; + + const pq_encap = ek_pq.encapsDeterministic(seed_pq); + const sk_e = try params.Group.randomScalar(seed_t_expanded); + const ct_t_point = try params.Group.mulBase(sk_e); + const ct_t = if (is_nist_curve) params.Group.encodePoint(ct_t_point) else ct_t_point; + + const ek_t_point = if (is_nist_curve) try params.Group.decodePoint(ek_t) else ek_t.*; + const ss_t = params.Group.elementToSharedSecret(try params.Group.mul(ek_t_point, sk_e)); + + var ct_h: [params.Nct]u8 = undefined; + @memcpy(ct_h[0..pq_encap.ciphertext.len], &pq_encap.ciphertext); + @memcpy(ct_h[pq_encap.ciphertext.len..], &ct_t); + + return .{ + .shared_secret = c2priCombiner(pq_encap.shared_secret, ss_t, &ct_t, ek_t), + .ciphertext = ct_h, + }; + } + }; + + /// A hybrid KEM secret key (decapsulation key). + /// + /// The secret key is stored as a seed from which the actual key material + /// is derived on demand. This is more compact than storing expanded keys. + pub const SecretKey = struct { + seed: [params.Nseed]u8, + + /// Size of a serialized representation of the key, in bytes. + pub const encoded_length = params.Ndk; + + /// Serializes the key into a byte array. + pub fn toBytes(self: SecretKey) [encoded_length]u8 { + return self.seed; + } + + /// Deserializes the key from a byte array. + pub fn fromBytes(buf: *const [encoded_length]u8) SecretKey { + return .{ .seed = buf.* }; + } + + /// Decapsulates the shared secret from the ciphertext using the secret key. + pub fn decaps(self: SecretKey, ct: *const [params.Nct]u8) ![params.Nss]u8 { + const expanded = try expandDecapsKeyG(self.seed); + const pq_ct_len = params.PqKem.ciphertext_length; + const ct_t = ct[pq_ct_len..][0..params.Group.element_length]; + + const ss_pq = try expanded.dk_pq.decaps(ct[0..pq_ct_len]); + const ct_t_point = if (is_nist_curve) try params.Group.decodePoint(ct_t) else ct_t.*; + const ss_t = params.Group.elementToSharedSecret(try params.Group.mul(ct_t_point, expanded.dk_t)); + + return c2priCombiner(ss_pq, ss_t, ct_t, &expanded.ek_t); + } + }; + + /// A hybrid KEM key pair. + pub const KeyPair = struct { + public_key: PublicKey, + secret_key: SecretKey, + + /// Deterministically derives a key pair from a cryptographically secure seed. + /// + /// Except in tests, applications should generally call `generate()` instead. + pub fn generateDeterministic(seed: [params.Nseed]u8) !KeyPair { + const expanded = try expandDecapsKeyG(seed); + var ek_bytes: [params.Nek]u8 = undefined; + const pq_ek = expanded.ek_pq.toBytes(); + @memcpy(ek_bytes[0..pq_ek.len], &pq_ek); + @memcpy(ek_bytes[pq_ek.len..], &expanded.ek_t); + return .{ .public_key = .{ .bytes = ek_bytes }, .secret_key = .{ .seed = seed } }; + } + + /// Generates a new random key pair. + pub fn generate(io: std.Io) !KeyPair { + var seed: [params.Nseed]u8 = undefined; + io.random(&seed); + return generateDeterministic(seed); + } + }; + + /// An encapsulated shared secret with its ciphertext. + pub const EncapsulatedSecret = struct { + /// Length in bytes of the shared secret. + pub const shared_length = params.Nss; + /// Length in bytes of the ciphertext. + pub const ciphertext_length = params.Nct; + + /// The shared secret (output of the combiner function). + shared_secret: [shared_length]u8, + /// The ciphertext to be transmitted to the decapsulating party. + ciphertext: [ciphertext_length]u8, + }; + }; +} + +fn NistCurveGroup(comptime Curve: type) type { + return struct { + pub const scalar_length = Curve.scalar.encoded_length; + pub const seed_length = scalar_length * 4; + pub const element_length = scalar_length + scalar_length + 1; + + pub fn randomScalar(seed: []const u8) ![scalar_length]u8 { + var offset: usize = 0; + while (offset + scalar_length <= seed.len) : (offset += scalar_length) { + const bytes = seed[offset..][0..scalar_length].*; + Curve.scalar.rejectNonCanonical(bytes, .big) catch continue; + return bytes; + } + return error.RejectionSamplingFailed; + } + + pub fn mul(p: Curve, scalar: [scalar_length]u8) !Curve { + return p.mul(scalar, .big); + } + + pub fn mulBase(scalar: [scalar_length]u8) !Curve { + return Curve.basePoint.mul(scalar, .big); + } + + pub fn elementToSharedSecret(p: Curve) [scalar_length]u8 { + const affine = p.affineCoordinates(); + return affine.x.toBytes(.big); + } + + pub fn encodePoint(p: Curve) [element_length]u8 { + return p.toUncompressedSec1(); + } + + pub fn decodePoint(bytes: *const [element_length]u8) !Curve { + return Curve.fromSec1(bytes); + } + }; +} + +const P256Group = NistCurveGroup(P256); +const P384Group = NistCurveGroup(P384); + +const X25519Group = struct { + pub const seed_length = 32; + pub const element_length = 32; + pub const scalar_length = 32; + + pub fn randomScalar(seed: []const u8) ![scalar_length]u8 { + if (seed.len < scalar_length) return error.InsufficientSeed; + return seed[0..scalar_length].*; + } + + pub fn mulBase(scalar: [scalar_length]u8) ![element_length]u8 { + return X25519.recoverPublicKey(scalar); + } + + pub fn mul(point: [element_length]u8, scalar: [scalar_length]u8) ![scalar_length]u8 { + return X25519.scalarmult(scalar, point); + } + + pub fn elementToSharedSecret(ss: [scalar_length]u8) [scalar_length]u8 { + return ss; + } + + pub fn encodePoint(p: [element_length]u8) [element_length]u8 { + return p; + } + + pub fn decodePoint(bytes: *const [element_length]u8) [element_length]u8 { + return bytes.*; + } +}; + +const testing = std.testing; + +test "MLKEM768-X25519 basic round trip" { + var seed: [32]u8 = undefined; + @memset(&seed, 0x42); + + const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); + + var enc_seed: [64]u8 = undefined; + @memset(&enc_seed, 0x43); + + const encap_result = try kp.public_key.encapsDeterministic(&enc_seed); + const ss_decap = try kp.secret_key.decaps(&encap_result.ciphertext); + + try testing.expectEqualSlices(u8, &encap_result.shared_secret, &ss_decap); +} + +test "MLKEM768-X25519 test vector 0" { + var seed: [32]u8 = undefined; + var expected_ek: [1216]u8 = undefined; + var randomness: [64]u8 = undefined; + var expected_ct: [1120]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0000000000000000000000000000000000000000000000000000000000000000"); + _ = try fmt.hexToBytes(&expected_ek, "3d209f716752f6408e7f89bceef97ac388530045377927644ef046c0a7cae978c8841a0133aac4f1e1a7027277f671219cf58b85d29c8fec08edd432e787a3cf9936fe0026a113cb9efb1d7214049527bfe2141ea170b0294a59403ab0ce16760a8baa95b823cbb8aacdcc17ef32775223c791e3740163941f9bb3f63346bef1c050c31f932c62719429aff14c2bd438ab135bed692d56c77c04cbbffd6335b578318b513771e84b14ea821262141ca006ccb8bf2500aa1008970f216fe7f1ae34125aa290492c069a189222adc322f97649c762c7d3128ad3bb2667971d0744014bc3b67445cbcd0b3e7ea69fb1cb9f9c331f97487920187292926d04a25a2650abbd44982bb0c3c6301fe6a61330d24d8a3c7021dc3e3392c79a139b37613bba67a2984298507b84a4d61eef18acfb979af2d39caa4c0db4513815359d76fc378c63a7f4f3053b17168d0221cf0c2eec5514ba235f81d04d67c3b5c518094917671c26a7c046457533cc32844581277a03eb065c4529a779a9a5878f2aac3f81db9ed3d8c9345697058cbb99d379bca16d8fdb61d129960390524791b9d3e501b900bd1e5002e095be06c23f1fb212f5801f24b6b28c0c5493d246d02aa29fa3acfbe15ac4e212eb0b6f69ebbea259a2703aa4c308224bdb741c65c7a5d4bff788279507bbfe513d7aa5694e7b3cdf62ab36432742d4a0ca9b3570ba742fa803b46989c8526ea586cc4fc32866143b79601725fa545fd280b404530318bbc3371194710b6d74beaa629eb18a36a953b75915ae96999ba5c88cdc56a46861c50032c9b630bcc1445a30878979bc55a2c0955bf399b231203b90c651b6afe0e242b5a543250b142f7291ed753d816098f7913302a8ce91641716623d4fc2ac6772aa5f3674042b7c4a18a2186289a4ac4e200774596ca03e6798c7506b984999db6ac142586bae0799f1e776f9f5247dc574d8556ddf9bbbc4ca3643263457f74248010d62d4311268360aecb4902b450bf2050ecb8ba7a92820d233f5a14ed31225a1d17ca6f19e825894cfb1807d922cbd60761134be419144bcf72006366a4460137ad9136c113f05eb54c409520edc72e4150cc3a24b0f819eec11bbd19ca9645b0810a60b4a8a9e9c3955396a1653955b047bcf4f98433c27236c570d75f809e44aaf2dc33665826351872c293350ab324518c8c0c80b521c80c81a56bdc968a5650315a830c8bb17532c62ccc23b1d46412c256b224fd4674491803501d0143125c7577239689965b6989ca561793c0f85c62a9e13487da17662a7188c70b1040a67ed4c3f85e74e3691822fb96314d6134fe6a626b3cbe1461d62a7b573b2cc75579ffa22967e36ceb2a1aa0b71875a22751d706b72ca9ecd0c8100ad0aa58009a5c83fffe91759e6baa0a9345af99fe3b69509dbc84032868844ab3f65bb1df8beadf36442e48e339c967023a525411544c789a2f04dacd06ffef78302210450b931f6b4c32aab34a3f5260b810f4c9a946fc22d3baabaa80ba8d9955d6dc35e8609b4256b482cdc9d8977c1a47a354e7c527fdb1672e166917b95cd6351820261daab361f8a2dcbb240c55abd6a8105e5291b427b566d731e6b7047189cff20d8b120e0b3e72472d1b0086812200fd3698e23f06e4f4e08bbb54cc2f63601b7f85accfeea2d17964c66b5194b0f08e18519faaee194e3c102823062"); + _ = try fmt.hexToBytes(&randomness, "64646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464"); + _ = try fmt.hexToBytes(&expected_ct, "d81018a94f8078e02105beaa814e003390befa4589bb614f77397af42d8e8150796f2c88a4efca81b8cf93c0ae3716c54ec1b045e3875f38c2dd12d7f717bd7fb701a9fecda5ed8b764c9a35d4a5c1d8930f6071f653eebb2d1afa77debb8302d16f17e0f5f3920a71a4d49beafa0e1c7e443f8abca64a65a9e81a97e7357bf902573363c0e1a12e5228036828e3f759121fada92441fe334e85d79347e470d2fed945541d832c54baaa3cb7526c3853954db4f73547cc7c27fd38398bfa7704952cb841e38b270e4db7435f0ee22f57d7ad3270bd0c88e71b4b864cf2277c65daa10a6dad4c7abecd95cc4ebec39c08404b522e4ecc1545713f76bebd3b5a0f2feb3461936065dbd13f6a1f61e1b142a2af2e5a482ba2c50cf0317049c0b3bfd6d5e9240eba9111d2030fdea17e33b6524020d30b0c4f8069285f3a6ca267d287d01e827d8422bf5426e11688bfc73756af1841b1c87e126cb50c914b5b2b8673488ad3b074cad77a3840eb12dd688f313ee1e9ff8c479a678f276356fc9d65e1d5b4c1e9855b4175db144f7767c12061769190fe6b5e51563b91f94d131a2b796bd2980ed0dab4ae7a7110e920007a757158a5eb8662cbf89ddffe9d8196821313cdc00108853fc4746b111d5b56da638d8ed2973918960f5dfe93ead3ae521e957cec3c8d843e8fce234c70ad055177f235439d6098bdd771b1cfcfadaab4f50a7378185c62409f383c8ff658c2a2af66498cfd81e962766ac6b774e88424fb4f331837d0a28502708477caf8780a156d723f68fca791e1cd2397bfc2b24c77c765d9b2af36f732d52107517efd8157b283b440a613f756c364ca108971a8878199a93f260baec3e850033cc032c2e53f823576affb4d3b116e2d16049152c35aaa263ab376f0ad5ede6a749607a283e3016e62191c0e8fde33e718cd989591c9a205d608d99fcb8a7471603d716cb01b56328d7d880aec2851f4e6d8b5016c25647e9026ebb441543e8012dbfcf078d4012b8c39184dd64f3821b4774ae4e36365f8baf2bd1f6667c017a1e65ff8a1554458fb3f367c02721752bfa56fc7fd566ae95ffb208f919ef12f4cf8a2fdd141a8df559bddb7b8d1f04ee6d4cf7805d142989caf216dfae985faaab9974f6d9f8aa1129084db8db912b1655f595ffbaa66491ab4655fd734cfd4bb0c0289d4bcc8fc5e9943b351cb147c8db059a24004d1c3e3bb4c14a881e5101acb736c65c5d579acb67ee85a560277b43338fe79d34b772c5da001da3b5a3383dd81319a0b4542e6d7e46eed5314cc70eb231de27b6e760db598ba19995cf69be0e4458e35f3f274aca2455d43fe3344e183c6dc47c857dbe9907b41e41006d91b25adcafc098fe66f7554be8dad493c4f4b1dbf7a51464139db474afab5572f92a2232b59be56a72c0505149dae5cde1e602877037de7802b5f6fa47a4c9a3e52d6ca15339920254e9ffb53c7b834cc0288ed9905a1841e9390ea94a8898bd4c6b6d6027e4d43c7867242515bbeefe12340fc6b3d57762f8badb69433f9c6d060f85f5e5c6b6803a816d141c075f63541ad10"); + _ = try fmt.hexToBytes(&expected_ss, "e5ba94031ea6efd69c09c254f6d9783136ba6037e2d4c43bcccf19d6f3f4343a"); + + const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM768-X25519 test vector 1" { + var seed: [32]u8 = undefined; + var expected_ek: [1216]u8 = undefined; + var randomness: [64]u8 = undefined; + var expected_ct: [1120]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0101010101010101010101010101010101010101010101010101010101010101"); + _ = try fmt.hexToBytes(&expected_ek, "ec7b50cddc8360f98b189bac73d395ef947b37d8453886a253269f7b18b9eb78c1b63212471a0f979793f9936b3f496f4b5394ea69c2a35729f91c688f6bbbb864cd5e87108676c4014c2ba98204f911becae33a71e832ac012bb827578810955f8c6e2d26c0b17b7ba574990884546ba58bf6785721f3854f434cfea602e8595c71642e8d4c70934b7e54c638f5a13e1a136bc86565e6b40abc163ca65650baf953de7bb99b138ac1b695023103c9b417853c9d42e54fdb816174659d85a783e3d4613db1cbbaa63fb667a4a636804b6c4ae821ac5d6556688bab1dc10d6779b485c63c0ddacb91837c4ff3402e6214188072b4186a39c65bde524c683c95d3c8b65e37104f551b6a3602eda50b787182d703ac6a221428b4553e3b99c2b251ef642e31256c329b21d1246a71456fce700d7f50cfe5390a1c37bc133809f102c22914a1402c205c0512b733afeea04411ca5ebb0bca9392b1ee23935eb196024732daa2a1f79358e6e74b73c965a9e74778dc6921442b19328f6216a5e814ccc0639a863a437a614def5a61f38852151011b04a37bbc78c1eba4d8d1b3a1622a0dff74d25c731abb2a5fe5919f835bd3dd97330cbb7dba0b74260c963402160c4017d92256a3713c9e77ea0f4901accbd38715511784c9ec287dd85a769e081854b32aba9322a3840f6065133228c41851afcb40ea509cfbb86145fb8853ce14c649691136b8660b0077f3b2f9da82d483c1414c39a9777665899131a8336fb828480986df102628d10b54239cc20231457d4bbb7016f76029661f14ffd3532e2f8494e1613430730ab915683c3c8c4db2b4373a3057a097e23333605398b15cc4d6ac3fbd0732f21026bb0cd51fb738a740467114e7c66256b830022f28c028392cff8013d617c77a47bbda11c4a522f8f2b49f2822cc06338605671fca4518df9b3c506532c9cca3175330f8733ce11cb3fd8b95239ceebc9483cb68bff43b622911fcf4a9c57c226caa38bf0b081535999f573016b14563ec4826dc281dbabc633868a1d903d59207fc662a293735085c01f40b5b56cbb795ecabfad709d611cac73eaca579768213c18c969c59be58fcef6bdd8a85192907cd0773f81eaa24be07e0d620e9685acb0c6b0f54b47dffb510384241c4b733fe08dacb2852b2b74cc014e974a5e9db35d80d7b83ad31da1487a0170ba7fbc1c551a6f1eecb572084180b256962748d5e3200b731ac7c3928585a153b167c92a48cd91668c773707c054af16aa7bfacaa161a620600e8d08cc97601a53391da0247e5fca60cd1bb65ec0417177a9eb78cde5aa1dfae34e948417b3cc0b223803f5f40e8ae3a382848ff80c4185824076423ae4c137bd30bd81f04095c20a01e0a49f664f8f2b7f6bf6a990993cbc0596a514ccebc578c6418e825903ae11ac52831c6a48c67727409ed7274eea03eef32094271b02d4535563aa4924a2666871a4b690540c78b06043bca31ca4e42a03650ecab74792017217d10615d0acdee124e3222c90d79362207e4f7779e097501cf140b1a3431ee0cf27b23a50373d59976d82b5b1ce165f4aa1361157afad564081c85777584dd6058a1a4663b53234d7264fbac6877351d1928c6780f77d47209337271e305370df9aeffb74d7c75de55c006e2b2a979aaa76aaed9e76fa61e2a0a9aff50c054b3f819ee2da1cc9134008b9f5ec05"); + _ = try fmt.hexToBytes(&randomness, "65656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565"); + _ = try fmt.hexToBytes(&expected_ct, "600ecf4026683898d0e339eeea9ebd437a4a802952bf32bfa326b48eb74946d0cdd5437e70df4b6b7acbf79efe60ddcde985acfd8c2d23775e1ecc54eb6ee03dcc9b4aac150172737831adfaf0e63a4782bad2a785b9c39bf5e34640ea3da447efc2a03e23a337ad1f542c32c2eb46f7b88d0bfba87d8efe8cd4456e6f21beebcf3dd502b53d537395750ce963d289eff74621545d4a5d9262bd14b3dddd4ef880e65cbe8f2f8aad826f57f727a60aaaeee8c69e89af6c539fd4f267c44bee8b5385a460a7c8e4a809959df86c1136ee23e7544cfa7524c6c04ed9ec29aed307b5dfd0108f29294aceeb517a098b8cdbad5911bc75e96258bbf38a20288c6911b2346f842c0943bf8e9c34a0a8e518e92c8761c6efe6b1d3ea8aed9b2c4feacfbf3559f3a5e46e4dfddf81936183d4d1f9c8c1616b14db2057435ad71655d743fad4987a19e821d0ac666ff3e46b7cc0e90b85e1966962279a48afe2e9bbce89c819a8ba52476af074a071495398bd497f4d4f34026025452975cfdaa3e7e183a962bda009108221ecb20d218c42e38774019d2dc32621278b5e88f99b62a9e746d16c1691ccf3e7e9185c3c493e7617f451f632c161fbe6d8ac3217f10ed4bfeee47e4960ec4a53e4852ca0241543848422044a67567a83e09d8e74b9d11af17d53c49565ca53deda7c4df076a3e1b6368b1931d81db93e87f75bea6924a321376fe73b5a5b07b80a98dc3ab8d14732540f1b4b7176e274a905d453eac1caafe2bfe4e6c904556ca91b01b2302215ab3dfe6b49f46963df632a9e7cb8439cd5ee56a1f8e2cd3faae5d8f3462d0ff931f5038cfa70259d963163d6163ef22b0c32081bff2763e98da87817048d4ce755e5d2b1cfe7d6eeab0fdbe766c95f125537a04bcf99026f9bd5be3b26b9b7614f132f6747dd6d96009a85ae6cbb1a14b9231099b67b04d7849875b6492f3b6482f8bdac305f7ec29f28ef4739934c6a7a2800fbdbff6eb2237d6a085ddfab8519db1d2b1e63aa6cb9b3b044278947dc3bcd329aa427d13267f93a6cf2aee8a2ab74d4288fe0b676ea85586834ab57e863d4805703eb8bf6e71fbb11a386e7b64a0d661dbd05f5e2924f1419bc799a089d44dda9066c6c503f8c80be8daa99bd48338daeb4911acf19328103c96f40a77ffd827d52294ba21ad1d52fc27e8b12ad65887024f41e63fcfe654152676ac363f2377c5b0b437e075897e33dd8d57227fc5a536629efad998a279103150e7d47e4b7d11a0d649d146c6560c48c9c0c56c811cfa6f3f62cf717ae571597bc297deed887672d8a8cec2929c2b55b95f26bd5d10ef30c0c4a6295d5ca601538f5a20ac1064d2f4c2a078af1b1629a0c203ad047125eb9dce0d1260eef19cd4ad8ec5d73a01ba23e266cc6dd266c5a81af58ccf1b5ce0440efdd1fe7bb42177679b5e5095ffa0d453bc17b8921008531c2d096a3a4a48563370462a59fe1faff2a81603f2d09ca2e0beac44204a4e03aa852745b1747bb6c424206ae093ecb917897fb41b1fcf75c1227fa08876056a5ed07ac44fe0c116ec2de80b8e523959d7824"); + _ = try fmt.hexToBytes(&expected_ss, "750300db25bff9620e893c2c6fcab9bf04d7f2e543b5b39420485626fa274908"); + + const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM768-X25519 test vector 2" { + var seed: [32]u8 = undefined; + var expected_ek: [1216]u8 = undefined; + var randomness: [64]u8 = undefined; + var expected_ct: [1120]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0202020202020202020202020202020202020202020202020202020202020202"); + _ = try fmt.hexToBytes(&expected_ek, "08118d8819772292c976ec971ee3039195800c823544484595cc63450b9db9414330419208c509cb62626067a8fd8259160105b6d8a4023b056f5ac2d6159fa5f245f00c719539a4601466f6b45b2a68bdb0db7424d4cad475a8d68b0d6e086c3f012414e22900f01179e8c90a8ba1d285cdcc7c7ab1c7064e2c15233acee183a1075c04f092a5e3676b1ec06d15d348e7781346ec95806a5e00f64d1e101bfb28bbc6829372f32bedcc0de9a70a02e508b760422505481709bef10697fbfa219b99a815f47e4bacab0e789ca1e414db529deb043bd8521c2d456a062a65aeba2a40dc6b9ce02474a71fdf852f343b22d2110519955b964382e74a3cf78586eaba353b98228b0268f8480b02c4b4ee208198fbc472117c4be567858c097fb0869a40588418973c58753da845e36c0adf39c53ea9c8ae24c343bc87bcc3be69ea40d9490592ec99e9a853f4f22b024a1b15962b049a62bc198706e310c8524c51872718d76c6db25cd824a1b75a94a7d341ca40be1283b2111b687be69d38b7297a90384b0c0269ac911cd80384b326357262ac13680dca37ee18477ab23e16448805676adbe1a5b7732e73c0abc3c5188e6c7ada3c1f1f124663e83ad5899674253e9bb15f39908ba4917dc11025f7504425a305848661c38cb09a82026d20c9bd23949f285519db298418718023c8d7e37a5bb1062951b4325249aad59acc06b10161416ccc78db6c6c3f685ad3d9b4916c622163017f9662da4234bab8b8b1e77290867d48c28a2cb33c7d2c7874c2be936ca0d6ba907d6a823fa24a18c56cc124209ea488ce620c18d00ffc8b8f0c11cc5850c30b3a0fb7faaf6e526f9b08972207a38f760bad1824726017a30634fd239ebda59651b4c8162346bb3652dec39f56626547829ffbb052a5a6930f2700fad33fb1eca8bbc40fcfe778189398b5527a09a24a53a958e5c25353951b78d85916457c1c5046e497ae0fa24810e82d360050e4fa1bf55b719ab8a080c23dcd80c0d4915d8458652d476f50f3a5b80ba6ffa9a76bd9524dbb39df7826cc507a9d31aa29b6207eaa52b3e224259c4931b1ced9b97a42e6745752ac0603917a694d7ec95145094ed089008af675fe51b2b79970abc282dcb632c1fc3dab85ad14893d0ab63b9e21a368845e872bb1468aa252554f59f90c9675cd044b930e37a96a213a28277614443cca4317e4a2af9f4c7124fa76e1d48f38981d7df03d2bf840610861b210300156c3f999aaac1b2983c45cf0002c922037bb4055dd1c27df511ced577bb8046e003507aa7b2c52194680b93e2eb40719539b8a93b8e83b9e205714927264cbf0653d4429f504816766bf97f14141622e91b20177d98b8db9351b39632be41a48f39ee050cc1919143a2448d09c2fb15a680ebc07963b788480631eca37e19213dbb6c5e8dac3eee81b0292cbc681563d05779b79b5d8ec37b331b3c021719cb95e69ec99a0f97b723303278b9403fbaa7f71ba70d61d082c91a6aa2c8a3543b5281e1605832c740bf67036f2373571f09482b27272c8ac2c69b01f715dda83377aa093a044541f6000848ab1ea65cab1345135a4552be42b27c4b980065694134a90d436f0e091b02a02aa99eac7339907afbbc158a5127540423f23f6927eff66915d745f4d42825a57744a69ae7c493df9ed49f2f7eb1d2a9b72432b61352a9a953730c6295c"); + _ = try fmt.hexToBytes(&randomness, "66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666"); + _ = try fmt.hexToBytes(&expected_ct, "413c55d5710bae6376761dada807daffd4dc45f9f70d825e0d46176d4a342f58f20d61879215bbe4a774588838175342628a905da0dbaa1346e8e913f4738defa0768445f1c625d296ab06cd547b93e764a388e63815b588059796e9bf3fbead072727703b036aa73223007ad1caaaea0c6cc38d385beb06fe8d372e9145c08e1bc3cb5ccb12f450ab0f6f9da5529629a3f1ff6312346b6d2fcb20461e7b3b245a97a03ef27f2e5442daf2a5ea317f454528e9749f06342aa7594ea9bda0cdcc7c0953c36372359ffd69f2aedc1adabf8a3540e32ab36ebc1350aded1072afe3b78a6ec2f943d560f4849d6bb1ee24679e8f70cc0f4cabe7d4cbc6e090353ce8414a93de9c84a32e197a2ac95e9fbc5d616f85fe199e80793f6dccac203d2f236e7bad1a4e7ff51b3f3326a9742826ac6a23ef5a945aaffb54faf50a8f0b8c09c55cf2bc812e30fb3e687eca91b494785f121241a1ea8d0cea089216c5a96a467c06d4f0a10c2a6bf551637f0fd5635dc1734e96eca5e7c545d66435b8b5dd88eff4c2cb3c73c49dfc9e56c293febef797a7d36d21ba30361f7fec7b0e51793f6fdc2214f420b713a1598f4dda1a29f9124469407e5c5c5c908e39a78ea0fcfe4df3419692435a92e0f9a5846690706cdd23b1825be8d0a843756fd97b4f277cf0714a0d9da3ccf1a31a07178399b803c7b4837980bc0172f58716b3baee5e86441d32bf31c7ed6e9c6d55eb1ed528a4a306dec7f37b3a575086385a9f4641ef28da16d35578c743c8eccb0581b2fd308a3c9fa15c8319954c8f4259ab09f178508720ebb8a0d893a8c45ec23b2c1c2e43db439ff71fea6a9fdcd8a9d3c6e0f8b9e9e71ddc2aa52fc5cbf22ed67217d847e4c84b72e7f201aca56c7d1d5e51e0c03cb596a01d20203b38e0e7d3086c83a4a1930754134904487c43fb96deb449aa832e63a82d132660cb7976d9d50742641c28c8e2e1bb00a2c65e9f8b9591501ad60568af112a5cbab134bb472fecbdf24badbc6562201e022c23fbc6354292ab743a863a139dd4d67b1bdb553b3c57a5c7f5b98cf145ac142e1ad6ad5ea3954fa3c2b8ebfb6cd05b915dd1d87262d7ab1f1b47cc0a3babc15a7a1415976644c54e29338d79afa9d12a669d3c67bf70e604157815f041556a5cc1c8429880a5449d033bb3f1f2b879f0e689fc2a3e2972f75f6f25b95bead0460f35ef71d0bdba380efbabed6365c6e7fcf2e22361b572029f0c90f2f74c8e40c7941ed8b6eef5a722bf2e5141cf43ed2a69b87901d546a85765fc494531e61f3d723107659b4ce1f294c352fc45c28a82cb3c242e5d6b9cf43d071bd55b8bc0d47b225463a5075639569cb073ffc4e07417dbc5a30a8e30545264d64d98d13336fdb6bdf8c71041e995cd433a77a9d4ee25e20f757cf76dd702f7c8f22a2677f03dcba47ea1996b9d783e44737ec501a8c75acb6d7606a2b6eb1e069576f3a87b32e587923fb79171c77083bb629efda6b9ddc1d566d72a53161c165d0ccea7674e5b1af42b219e4d800da968d2a5fcb009c784f4746c7138edb9ee4844b739e830b05cf424"); + _ = try fmt.hexToBytes(&expected_ss, "87292f18b2e7af74bb8839ddee15e832d2f4bfac14dc84f824906d951436aafa"); + + const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM768-X25519 test vector 3" { + var seed: [32]u8 = undefined; + var expected_ek: [1216]u8 = undefined; + var randomness: [64]u8 = undefined; + var expected_ct: [1120]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0303030303030303030303030303030303030303030303030303030303030303"); + _ = try fmt.hexToBytes(&expected_ek, "04ccc68ebb7b60c6148fa94574ebaedb9c5ce5eb1ad69cc5a4d7bbf9a410295540bba271ae8a178bd025ea28887ca8808aba8fac7a44260c6e39b883110155d0dcb82ae7609bc803a8f927dcc2c2033cb07ba90fc8b068188a7214e713579537e69801ce304251eabc8b34b03ad71246cc22f7671adf572cd6a2730976953535c59d7c93baa5788854ad52f48e9cdc8accf4a3441392f006378a450289053c2ea689a80699de7acc6bec4c2b182e3194acc9fb1ce3e1b389c5879ce66bc692a3b15343d6e557ff93127ae69007e6913d51ce703898c5449ed360259384819529c7b54b9f5b6c9755d0a627554772846127c8a580a5b6a9ea6695449be144306d64cc8102127278827dc25da96b6f4823ce5ed25a2b199f3902cd8bb82058d4694b40ce0ce1cac1ea8a047a1ced942d78ac2923c9ced1d563fcc24895b1683615b134856ae3f36e4b382bb160171ed400902499c6a0b1b8701d89093d6d72a992c9ad296308a2d44d26816b1c942a3bc479979516a0dcbf16bbca1140554be69885a477d078ac0a267e8294111cbb42bac3cc733269c7f84bf315258cf8cd04774f9ca932c7416785796ecd781e17b6ac32277d6d141906811430da866478499a8c94c521aa4d4663af067fcd2c823252c1dfba800c7b1681955de39112c2fc5f4a14020469bc22278a84494806d43528f8ad8efc88643038d9d71c79a50710dbacff686396c34f9800b0671b0da3c2ad4dbb3751b3b3749b63e132a336f19ae8f37a79f6c713c48b724c80465b28e578658bc8329f0c1d75d0ab1d632027a3cc8d749216f50440109ad7637f3ab1661ee7637eb06e70d4c15db81a2ea25ecae4524476106210362a7b35c013120b51ad9b2c88b452457b75a98fa3ccdcb183aebb1684b72c3fb5434c277907680e8ceca5d2fb88dcb43b050a5557b19d159a6050a6115c1c49232cb5150463e165acd4629ca4927e3ce46ddd1a733dd23f77b44dfb7b46ebe4291594015a4ab5ff00b643321856b3b062ac28f2c4cf7b30716b6c9a53271139685b3d2bc20cf5c766265a6666652393af58ac25efcb502a30b9f6bc2524cc615a911b1de63bf1710f9f829c91a573a960a44d43138a65c42d41000c601c7ad1537633433edb5023387aad5007a09827a55b6a7e7a2911307e0f226e9e52ae3ba4c0f14a1efe9571352278c5a4a08cbba7403c35ec69cc2a2b364ed145b11a4e8594087236a4ba7a2d003aa89fb2c97580c3ce115727ea0e99ea81cc8354164b0602e53cb33638dad5a39632b70f4706eb8bb6d598c6717627fe3c02420583cbdac9460a9d55588ffafba8cf748c16283b0e96b8f95100caa7a8d12029a433ab4efbb9b2067a0c615d5358aceea04b4ca4bf584a452fe2768cb5bab0fb52aec375c3337fae44b305f1389f123103669c7901a1821c4715b5cac1c89389cc9f4df192cca789ed236f7b378fb2915106ea3cc1b90ce9d6c07b36c4f09b5654e3a116c60dda685b9ef6893b1b42348a3ac87284eed683fb346d25a562b90a778e6b546e40b4fd7c1d3c01983f851474c3832297019a808ef64957d7902578981d9231b382169d533a2202e95d18f152e8fc25b615bb8a65482a2167df6ab2811c73bf8fefbec077f1e668494d422443a083b9619254ec3e6bc6f30245fb738564e071c7c638448d7882a566c87e7399522756588c2a86dad8f2021e"); + _ = try fmt.hexToBytes(&randomness, "67676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767"); + _ = try fmt.hexToBytes(&expected_ct, "f40d556d507802ebe7be0e65ab82b0aa9ff26c825d24f98148f75d7e910d6c7f5852e7023a4e246be81b807fea96928da6a8c4d23b8326ea90aa7f1f0673a57277bdd08960f7f886777f1725b882e1996632584fce4356f7345abd8f480514275fbbd96ec6d3202de46e18e7a827d4dc62c1681c36018861c33cb2f4e13ba5da65558441caa6ecf82a5e74842268f4ef5036deb2f0f6f5cb422dc2b723a7f2f69830a52326621ee034c8a9e80f39070456bfdde653314040b4f41590723b66a2d7e41153932521e8e51108d2d98841b2983baa43b0dd6a46783be063850b22a2dd05c1f9f578360dc3dfef4d79e8c20d2d0c45687ae19395355e7cdcfa039e3c36b6df4ea11b4122918fd6ec63ec672ace58a8ed9dfc61e7d3b5829d574833e0e61fa08419cbda05a85b3c4b9957a0968d5825d0d052013e75f138c8d74929a631a0ba2ec9555e2767f17e6e22890a5cb00f63f09e00b8decccf7d7d0e369c4396cb429e53d8cd4636ea630d6fc55143e6146a969ed0839ab05dd079da3f946b3deaad2774360529f2aa7e6c400b66a5c449dd8362fae1a1bbf110229810e0d4725cfa2dfdc046d4c18637e1de3ec2b52055c237238de0167eb0844c24a8fd91ac9f66f86efc945c0a50672926efab53bd0725ae9ff36e9fcbecd58212cbe7e0f248b9ab90b2f56497f196198043fa10de909b05bf3dd1d20630f9707095f4f80d044418e67ccd79e8f28db7acb1083a2bc63233a4f4798f13f21e81da6ee03c614cb367aff05410960fd366df06691b374247de70fcf916e653b2bf01b49cf116324e8104da61a621b566a62c97c6c058208e4825727cbb6c2ebaa0e888659094aa03709659e272b4209c18366196110d71120b203fc71dd5d3c17be4580e5ade64a3fdeea5b85ad33fcebf30b857dc7cfe3ba52ea8269cadd7dda308460201e0119f8918de8980f04b318f39487e65ef0e0b83c2396d2fd87f4d54dd00b405063f072659d6b11513f448b20deda3d874987c252b7d16d94c4f811c97134e5e00bff8300e718e17de3735bb4bc052100a3823f8db4be2d7554003481ce6d899d74c1ad9944c01d933305851458933b3f780ad6c1db489da507621e39be174c71f73ec9c1ef644578bb1566136f17e91b475fdbf354cf4f5a6ee300d3938f5b4a7b9bcb90188a3d9c8fab1326df69f5c3753a8ff9c5a7bbc4e2255954dfb6a2ce81381eaf9d224005e050eb5f53d05f0a41bcf4f3c0e8771e84eaa46ce27b0438d4ce3ebf9eb25b5351643a26f607c41b6494ac77e4c4a2fafac8e3cd872f31816501efd66c41795fa0d01ac0290253cf6c9d0dd8d5865684c1a02748a824417827ee374404a59ba87c3ec3caadf08b0f920667fae9ad18560edc3f8571986ca0bf1ef114d394c08ec5ff221e9f9ce7b6508eb6c38d6041fbe7319bd8874f35bace85c0bcc08cdcc642ae7fc264b9be08a26e5ec6a3618a078a128d0b8daf46e404eee4123b379a81680c8336036d9a44c12bcc23ed7b1b96442108843e5fcee6ca3bf39d976ab36a808531bd7ec2e4b4f8aae3a90134534d50f411d377a2c05"); + _ = try fmt.hexToBytes(&expected_ss, "38c469d91f19aeb79dbf1aaae4d1195216c86186b00a798ea3a6e544cf9c074a"); + + const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM768-X25519 test vector 4" { + var seed: [32]u8 = undefined; + var expected_ek: [1216]u8 = undefined; + var randomness: [64]u8 = undefined; + var expected_ct: [1120]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0404040404040404040404040404040404040404040404040404040404040404"); + _ = try fmt.hexToBytes(&expected_ek, "6afa82ec0b8e8449591cb9a11be36dc43146c18a6ad3f175897933d25944c3c643f50332f1cc4f6a9707a387b5c40661ec41b36d2bbc4507758387672fb4a1c1196eaa81b01be2864cc958a0642496f264b4042ec5f7b25a5220a8a9c9633081aef104ef9abd4da0af068a84e7b03f21e6b60212a02dc48ba7865877084a1b025443e38d60bb6fae8ba88ea4538d088bea758f6f9a5c26a9c44699ad43080d3fdcc2d910b16b297bb86436e3d5b79dc01230124867c1be64a9cab7aab9fdb47eadd15d00ed84ac9a37406a3665d7cbdd106d1e6a29a81c94e3c841fe9cb583004aa471ad2eb477623401e6959a04439bae06a07058cf2ed94bce1839e636a8c0b22f782483ce798e609bcd784605eadc0a06c7699b1b9ece550484124095a13371028101c95721c2c71b098b15f3998785b361924f89dba9f292b9b18cbe232cb76e41bb5b35cad976962fca2957eb8e06356c250525e8825dce66478fa587ab6b429bb287aaf21a58c900de0946ebc284873450c7e7a0e08c856dca2191195f73b3aecce1b1c1c29cb24a6c2fc3c14ca1495182645cf8486cb877d067440f118b80713784474bd0214f23fc09e2c8b5df357b3733c13545c9490378291646fbdb8403818f7d571a40ba7f5cea480fa00ba15373c60255e54384e96c455da13fd7dbcbc1e7a5e9d655b0145976e190780b55c9c86ca6c988d1230aabc8558ceca8d5cbb844ca8d95b30b64c02440522661c9b07c866e497b5a7daa2398a5a888a4244d90210105460fab31c6db3fd57941b869c24218b2ebd7ae67885e1fd691a3dc4388b872f4cab5fcd94067ea953d73acf1f4c752776357974b0ad7872ad603c30a174f963983739e5fa5304d1705c6791e9c90342683a3b176a2897ab9142190b3900d089c77ece41316b40611fc6bf7c81eb7b589d65524f9c6888fd7c53ba810b0c70766430638595dc3134ef5da09c668a804ea1e2f1469edba0d457acd8281828d02a915bcbc05949d2edc5c1c5856fa798e5cd3587472903c6cc2bb43b03229352587cde988ab60049b6f872a9aa82f25b5346fc56fe8686423b27e0f368a43d36a21602b4056022d25217df44a1fa330122152cd2a581ca05d3801bf9f0a31bf79b8a7394fb8c9bc1652cfea9c386ca7c703b5754c8243f7b0a36bc290e0733a17a94431d7b05e0b4298a8b287fb1ad3b32a57693a1e7867b0f3c483c0abdd2c05c81c26a60320d91207f204c2e8393a78e7572c8c296260351eb62940c394943c6a622a8710aa09a076b513dbbfddfc3105379da08b97a6fc68f2105088cb35f9683144ba24673513f0b6aaca32c0e77173d7387294a9b96a08a014ac88afaca949c2c3760b461dfc1ba5c01a956cac46a01dc7d9a992e1aa704aa15af525911857d46682b137a3719aaa71f7a8ba88afd6d43b127805f6c2cb55f88d6c590775577373ac87356a56b89341d0e8657737249bca66b0b4194a5c13dce045039164fe1530e38981f08c66ad2bb0531c3631a86f6cfa71571b777b2461601bc7a146c358955a5b44130d26b5c35322138133c083aba300a5def2c4f0d94d4267a2ad23420b768c77d8a1f0428536667d2df42127012291511a8c72738b82f0cff83b9315330886d611180d2383cf551afec4aa7515eb138a398eb44c0ca4c2487488da7b0a98110cb697ec5031f995d7022be6c799f9d3759079144e"); + _ = try fmt.hexToBytes(&randomness, "68686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868"); + _ = try fmt.hexToBytes(&expected_ct, "cfe31862853164950123baa75549418c7a406cfb60003b825eb292f1ba1f25c3b5b044dce0b8b16cb254d69658d516cd3445e3f18bcde32c4f46b4ac25dca4c4573647ab7cefd7fcbb7c192d997194654aeac0f593eddc4464e7e125672fc7265f1664b32199cad45095359a4dd80e9637f0140504a7b1303fa69d121d2d214d5ea44e0046a120fef7d573016d8edf0c20749f05edccca4a30565df6e79015f04b03623d3aa25cdbaff330633470c0289689988c27fe49acc957d3be72c4bce05f1c80f3c2ad5b4e8a2714c1d1ea518f431f97f6d68eafb06ad7226a29a2b3a9e5403cdd923400a4303054876986f834848a4902659b288d5e3ef26a9ecb3f1be3630037d147301498bfe198b8116f244a12547ffe6a5006f748c0485fd72232e0c55df090011946c8b493f8aaf92de07396e901fb4dd8a4f291645267e7ec0335eaedeca28ab4c36328c73203dbca87e40dcf007bf8687dd4a776151e9d234f52442a33c7566b007f6537837cf752602624030615d0cb88238b91f578e0728b32734363944bbfce5884dc3c777e0b3f1ee4029298895e6b82f6f2307dfc267e27ca8d7d9b49b90786b7f39d906ca7b6527d5e31316fce0214418f95ab9504c98ba9e868754cb813014cbb196eac152861af719c7632710754cd2c72544c25b66d1d016f97a409ecd11577a358647e1726da16d0a0e2591eb3b7cac7fe47fbeef10c6eeb9289aa4154d42ea75b864e0a1215ae35dd0db3fbbef39ad399c3d04d0d4ad9f2ce442bc07dabd366307eefcb2ab483dbe80b3eb4fe966131a587ffb2e3664d31e2c520722dc1a1f5d27ed0e937c4c89963576cdca001361f11bd39e2e2b367943305fcddcbce6460a8bafeff8394beba9bb893f1a7abfd2e80bf10f0546e72a4051883e1f7edfe12ee1505d9503a83ddb2b998cb2475b88d280f1df688f472968f8c718f1f9fbd39fb3073312bc54c755210d0ef49f9f2bcf06a1099132a1e08d84b68543848e1538edd881620560e54d8d6f9a71ca2fd44f8fab9d094f1dce52f40c5aafe1f73e98a2a395f48d5da98fa5c95e4afaf84e7a138807f71eb64fcb3b5169e8bedae1dffd725ad6fba9fd50f39db9432cd5f379b680c09c5313ea73517f017ddcca33a405c0ca293d8c34714aec241b9a634ec65c8c0b56e59df8e668e74d2494bca14d8102dc0592dbf93c0ad5f9dc89ac24a7e981feca0461d3fce1eec98a4afbb0b7e6c46aec385c9c0fbc203264aa6aa71c67fff159ccbac01cdd85c28835a98e9b7d0cd4c4330a0a5334b5838c072df4bd7297251cbf85dd8306e1a8ec893f4b9558133e20e0c9598f054e2b0b77d4494c393c5dd0e83a6520243edc56200f1cd34b8f69d53e4a823a46852e61672ba69447ee49522978c64616ea42a0b0c6cc953c748a550dbabd74010cdb8fd19c8862473f826267c8cf41cfc36100665ebd766390d83c1b2f795cb6d3c38dcb8e98c6ec0cd5111108a079d57f9b16960d94a4f238a6d7a25b6253b0ae0088ce414406fa7d020da785d9aa3cdc88c2401760535ad5f436dc83a542e294faaf07fb2253b009416"); + _ = try fmt.hexToBytes(&expected_ss, "a638747e2b93607e6a651d528435afe07e8733ccd150507b96b639f6ff4a10ee"); + + const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM768-X25519 test vector 5" { + var seed: [32]u8 = undefined; + var expected_ek: [1216]u8 = undefined; + var randomness: [64]u8 = undefined; + var expected_ct: [1120]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0505050505050505050505050505050505050505050505050505050505050505"); + _ = try fmt.hexToBytes(&expected_ek, "33393446a76c2c01b44da5696d8452b29ab7b91787765366bc1a15b149792427844ff68753f957187c102d0940c498b67332a7f9cbb82fd3bec9914e05a955035362dc7462071c19e225ac96c12fa34a2e86e0a84a0c633e044b3d93969705833a53a4257b7f4c1515ceaa8af9eb7f53ca7cb402a4aba11c9d3206f8209c436bc3ea0487c456a79e240fc4f5829e4977817aac9de9a0cf6cc28131be92c2a6ec672bca1a8b3758092f8b87a11565c0312e82939f8fd18024a71bb98a885c6ab99299cd43a6208d2198a45bcdbec590157375c16a456327bbd44011b635cd1f678277347aa5a765b7208acaa4316ea523f59a0671594e56121654f3581e882072396932da2e2ea02bf5489e546c452b7c6f60e8a4c6112f6ccc7e3a7a44748aa1308807a08c15d78a2e19a2750a916b8c46844b257c2663a8895b3df8c40960e6b912623c8a92c9fb435d20e6cda9fb456e55c1dd90a5f64a5ac2c6125046175751aa742971f1728328c353f4a7a08ff16b8f978ae41724494c436471505e2c17ba958ade7b2afbf9cc2665518949755fd5bb8b15ac9b80b78fa615a918c4a99549c37c6ad0017c51c3963e3408b11848ddd4afe96b67cd66c76e817d4c150de52a720505b9a4b09008243c0fb05ef004b9c2c223f9230dc57b1dd3d1873457842b47c59b9a6b39d7b61787b42a500c9f57114ec737bf7c45303b8a3fa78b3c649cfbd166c60c37dea89e2df71ce4c605fe45abcaf3a604f548ee5030fdf49ad4129b94516a22a8b728112bfd209e5a5b565e20a8dce97748a79063790bec93bc89103c32419bbadc1ffc679e48139a0c88563f170d165729e3d710365c404dfc87d7c31efd24785a9265e55c4a624315db4005019818a1e7c0367a70fbd16098e27a640b0f3dd9515d82be0637506ff171c6a31edf453b40a6162feb7c3543506bc1105ce196e46097db749b485808dcc3b4221470ac21880bc23c7ef4b315f40df40802f7324957b450032c3104f871250590a4c9a29687c70e02b46350781abc7c2b256c54bbc96eb20b891877c3a673f67c18197a0e3d657196d5673efb19ebf9b3e49691612834cb662d2828938b1ac1a45881b9e51c786c1a321814a8c396421b7f313cc2e4447e6e87971e1660d94aad5f13b26bf49fa499822b1959f48aa88dfa5101f463d5bbc8ca21b9d0857fd2e42d5c1c7a9192765a3013eef54ca9e43fa99abfd8053e9059650b964d6aea8c26c13adc0a6d91208f2dea0da4d57a3a8a6be9156a4065058cf965da10586b0945c30965bf8a436aaa115ab170071c3080f5c723c10d05963a162622438682fee1b619c2b10c207ad7d38ab1ea7eda0924d9ab6b443386af7b07fe26b8fc6911789666bc14619a381eba7966e0b4ab0e528083806f46456f97e59276d5a6119b766b1847d3a1ad3c4022cd0616bbc348d4e072f7d68272617b03bc9b25f569d0b11dab8c5a7ee11ee6c761ee684625322c6cdc815ee1c0acd29a8e1c826cf89f25944593336643a46483dcaca9e1bae9a196f692ac0532cd91113d5d974963a524bf708c44e198dd212dfcf69213a42e32e6b7c860148ed38c51002b83b0c4b979b52a753bf2c3381c027623b8a8251e60f55524b56b959a14d84637086a15567717dbda7aff9fd61d09589ac8c08808f7869e6331a5689dec617d7ce2b8d5e76c307d6b15e1e3cb07c9c51a4f42"); + _ = try fmt.hexToBytes(&randomness, "69696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969"); + _ = try fmt.hexToBytes(&expected_ct, "6dc476cbc91fa3895cfd69bda5799b95b7c0dc87e5c78dec9b367df58abf3e7852afb7b31caff856e5e4136a23a24f303c6100d9a0a6673164f6f44ea472f4614c2b42496d0049a27e02f1aa45ba04442a74b5e0035df3d8877266a4241e650a86ccdfb0c6cef22c62f376543bd5749353f808308eb74ed031e73c9f42ebdc8a484b30769a17906e39fe8fa65c0f88fcc3436c0bfe26a4995d82a41c6a99140a36d166cba6ad2dd065ac19cebadfd455c9fd5d15ab2facaf9f5c79bcd12d31ef88842403ebfef226f9a1de78d18d2a0a57a7808e5c4d9c7c510bd1813db60a2e0121e72c52edf77084222dbcd94a10cd4dc3b09080e8e5a8971761cd46ded65c78ac4d896d818a400ed832830570d492665dec3f8c11168eee66f33d0c13ce3062252f107a3777d1d91234f58598184ff827f6b2e73638fce0e4e51ef704e1d3f8dd5312191e36db31d82b2b76869d7eb03474ff616008158f3bf966a236cb3e8c52de4d010cc712abc23dff6f5ce00631fd3dbaceba030c2ec18fd0c39c9c60134a4dfca521dcd71cda1179d8ef08f06a42686c360c9272f15b4258e78514c8814ad70a1092d26557a45764041b8324bbcd69b5d2868a6fd96c871cf83413113c898e4bb983187fa4c1cbb73cd41d3d4f4db185047afdd241f1b7e7007c00b03aa8ab836cedad6127938f87861108047298d3d945b343c62e2fe852a0354ff31dadc1ed08a4ddab41d91c0262283b11fcbb1ddb4e9fddd7cc338e925cedfadf4e306f84863fd45a70f57df0384e1234220103b0f693144a5ecc9d99ab1d6f725740d1bb09c3a4b4ea614ac01bfb1288bbf14dcd572ecbb6c822fe541b04a0d6498b5a14727c2d543c9647277bd67822a5fabda4a98f23ef50ad12b321377fd4ee24b234b0f296049906aced9d08671de994956a2179394d37b585a31e405325ef880a108ec492c1c87da90adba72d8be4643ccf29431cae053f9cf5271f7e1c7a4de093ceb053351873d657737ebbef086640d417c6a05ae7fa9e30b1129213595290427032f26ebcd1546b9c9c1bcf01ff3d18fb1ebdbe0fee540f4b5318ba65877f457736d30c750e42e0e773aaa6e526bc6143ef631f6b3f8811a026374dc28e06c92acd09e1f3f97c12e512b778038563b67de0d6b34a48157f1b936abb8b9f3da3adb88b5f36d0dae48627cdc1a403810c816e32e0d1112594a4f372e9abe4e6721ff83f488421022189b82e1f7f27a33e4d11969522e91d19fbe1a3b9eb6eb3dbdc2b199db9e86e56bf695d0e6e79457226b2b3cefdd2ee3775dae268020392f0336c6fcb3928bdfdeac71246343c08f2be397daa1fb9c252653307d0f7bc24111ba8df6ab29923b4e7f3471be2923f46dccabb2063427f3d4e53baf6a9ecb88c12d9c233ff14f63ccfd76a8f046cc2d96733e72d56c835dbc9a1aa2a5bdee915ae7eb3e5dbbc8ba24df6e634bffb4364a81039b06a2c5cb31c9cd8985e7fe2985c3e0a8f1d52feb2bfc3549c3817989cc1746fcfe8938888e12274481b1b8caa8136a07b19cdc42dbff58c341de0087d8feaecf29eec0ed4fd0c3355"); + _ = try fmt.hexToBytes(&expected_ss, "0594af7fe7a398ffe68f37a9f73506d6a3f7fd82b24e26f4b93269684ed47172"); + + const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM768-X25519 test vector 6" { + var seed: [32]u8 = undefined; + var expected_ek: [1216]u8 = undefined; + var randomness: [64]u8 = undefined; + var expected_ct: [1120]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0606060606060606060606060606060606060606060606060606060606060606"); + _ = try fmt.hexToBytes(&expected_ek, "c3f9a6305222862c2c89ec0dbd805c547b2120405ba8e994947b1d74eacc58277260ba837de29a0a2b84a7fc80589334fb2626c9f61c01c88d60b20b0728110f0840fc01a6187a506ab23d2b459fe0853c44f86a699533284577f7913b69898361bb67d3711680c6c25f2524c56022227477f28a194e90b4702901b0046ba798cd1b843192f3bc841c8f9748a1ab34b5336b12c58585fcd010bfd6c48e775e761525b260c7f6e646e8f17690aab51bab30c9763fc53b8547d0b56b0c82c458c61d84587d989785600b8e987a36423d388ca11d61765a01a4a79ca20a925908494eae0a3b6db1b08cbbb7a4ab5edcd96bd76725e928055b0c2883ebce0a59bc9ec282cf300ba6c5380d1b70f13b2dc6f616c76087a73a70daab7a6f97171ca5997bf40e87b95f33a53347ba6c7ba89bcec9041701226fda1243f4b1fa047740c7b753d630fe386f09e2a2f96559ae979ed9fa5a78d1310ef311f97cc3b6a738bee45b75e3a0cc714c81f72187b105a2120b9beaaac116bf9835c504713f2218b526f13d8a8c02c95aa0f2927c27e996e4564578e056227b07bbda8af0cc5d99f55eab9868b8eb4d1b14065843b229ea3e2a0a748d89c4c304198cd44cf77180bb8664f9aa1a9511527233cdb6826976d34276f62257ec382172bf97b310bdd34056ea61f2d74ce1cc9544b02263cc3d3133a308911556345a17c32acb470444f5536fd21f81cc3c968ab7e4db9cea564c55d3a601066375f6417691c0ee3b39228860f1bc00693293c4bca327176da52b7282495bafc2932d1154c03672f4db49bd40967ca41fb8f8696382a5208c5547640e5193459b3507f4817ae3707930508969a18b1d168e67b5939532160b50a538ec9074e733dfaa4af09755f831720cec8519f3bd74809539347b8786868fb2ab9ab742fe020c87930d37c45aa9b836c986ba01804a5de26974ac647d8b921484b748d9999447875fe2746ad1112fc57ea3999f5899374ce2536c58310033ccdabc75d63a641a5651bd08079a41c1e59894cb3a1c8bac7614e960581a1d191a3a386209b6e82efc92b655c51d91e11e8d39190863909a97cc6017af2c35500b860a21c9c48d48834eb561f58c683372968fd89be52a26995317855b3123acc2071683ca669d78c3cce5bb9c9f9429a643bbb1401d1d665dbf45ace6524cba3b0d33582105dc7c38165ff0959d325914f437a4008ca751878bb8287eeaf092021b1b3647bb4a9b562a7aae80625739f66b636c309a09376ac4cec6d76ce4629aef46ae488b4c6961069527594e0c22ec55226f47085bec5e0343cbfb421ffc838b56e9553e411ce39c811a1b4a53b051b404af3b58bf651376360c040a607f946c6357020ba1fa99daf19ad3f020431a98b1647040038383719ff9fc7d4cc75d6bcb6d4f00c834874b01b9a85e0c0f5c632734a3264d156c973c14cae920bf0917cccc924ba90fef187f9783119a7a268621c7f29bbb28da1cceab369609c64efc5e91a79451bc8100eabc85541d1f2435b96b532fa14c1cb76b99908c418118e2472c66511ab558aa06f03fd8fc15f10a2099dc4df1360d15910d2a7747d8abab40fa3d77b7470d8477cd63024aa40268f55139d37548223ed5823f136805752c0b5f7f23edfd90a89dd1f90ee344df0b7e3dbaa619370b955942588f0ce49e72f156ba743af7ccf9d4a89f310c3012"); + _ = try fmt.hexToBytes(&randomness, "6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a"); + _ = try fmt.hexToBytes(&expected_ct, "56a06e6443b53c24f647cb6798257899ea1c49cbfd4c4e3e54dd73a1139dc4df519067a5934733a34538f941cd9a2d9de371623247f1bbcb728d8cfd59b59d6995a2430ab14490b336ac502cd21dea47dc7c89fa026310ec05fbbe50179b45e4b68c507fd90fab06e36fb1c9b21c06115fe42beba15083385764cde8c527c3669507bcaded45f70a8cca789ad71e9087948e4f1d682c4a77ad306c25b1e6364f43fb51c0c5d72f455da72f46041f8fcb143f67c7517b425e24cd803032645cfeba77e0d8d2d0cfb57768b8fa3238c10ebb99471710973bf9d22fea51471354e53f153dfbac695a6f8ccb10524a0453e804bb013b450f38007fe21ce898c052a132ea74c9e69512ca4c18c32ae37884df520d12721b95acb515067f3516ced73c930786d6924cc7dcc08b50a3abef4e0df82aa0b9c7bc199cb2dcbc7cbaa38ffbeea60e41ae20e8400730132f3627e1f62fc784f222213c2c479c4ed1f2159f724eddff87e6a4b5b3445e189590de4bb62bf66e930550144b44e23d6c045d779ace9f94c0a688f729a0b94821b669b5ec49652e55a8c19cfcb4d389066bb3aa4d9d7195d30c496ec4250138ea1c335d6181b25793ff5d0feaf91b7d27c826ecda49a9b9c8ff880091963a2ccbdb5cb45eaafbfc8b93e753bf323e2f76b0a61af96997d97f429db90898fbcc2dddcebf04d0e2a3d688fa56655b41b0a628e4164a31308799ea58984d44739d9720dcfdf4bcf2808217408c433d263787405d11dce0854fbafe59f58d39a2995b991187ff86d3906e1e27812d5acd2a8d11b95ea20c7bf1e8ca9146cd9bdd10f899e3289bb1838191feab937a6749c965c01b41e6febb62b515efc416b9470214d78d4a47bde46b0c8a5f8c4672e8d95dff71b9d7bcd2f94c1d115461c5a847baa8ee4a8a67dedef4ea40403326710c23394b7b38e193b01670669f2c6e06c7963da8debe103a33b49541fd5e0bc77b916dae2244d36bfc3d53f0f1ba51eec5a18c2f258edefa2946f799b88e17ea475e8bda8cffa3531ed246820882e32f7ae0425b129a8b0d20e6205d1a7f85bd8efd9fbc7dab57eb45d187a25d29b71d69254a36a5125b6af9db41caf369183987e0f7077253969d9d1c0887a35fd2ea34eea81fc930b1a1aa11db1e996a11c49c39f570d0e3cfb3ef5811a678dc4451c5cf64898ae3b53e417c69f09438c997fbb453b9d88a1cb603e2016c1ee79a36f2e9df75f65eafa3db33f0f377c71e72f77af85a0114306e1b21921d532b6d140e3a2c5a479f33c1582386c70c75e84765735b610559e8aac6149ad174213f2a1595476b29075b71a025f05fec67fed05e5f193f2b71e0352755ff4aa61bc63f02405760333516766906158a2cf812fdd5d11eed2ca3e440458ae1bf76cb642db5772d672d932a336cd838339d9df2dc2459a15c173b9e803a53112a081e7c2c945786b24e6d226aefbe7cb184a23dd504813975e25067f33bc90e13ecd4857473e0bb0fa33b3f5f0255eb51da214717511378927c0da6244664d91d63fce62edf776cbfda72c88b68025f05cb0ca76c460d37fb8d30"); + _ = try fmt.hexToBytes(&expected_ss, "d11018de4d36cb4544612190b4613a7b76c703fc4cb782fb26de49adde017e97"); + + const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM768-X25519 test vector 7" { + var seed: [32]u8 = undefined; + var expected_ek: [1216]u8 = undefined; + var randomness: [64]u8 = undefined; + var expected_ct: [1120]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0707070707070707070707070707070707070707070707070707070707070707"); + _ = try fmt.hexToBytes(&expected_ek, "0e12760b95266a50a52bc6ba3df697c1261d3ba510987a299a83cc0b9134c2ea4ddc47889b72c6dea65b49e066b1a2822f269e8ea904a667cfe6f7035aa83cd9c041efc38d23053ea6d754c550cd5d1936d4e74ea047c4dcf757de9550972c82abcbad83c32838c18451240c0907a573451dc746bc491c143d14837af83c4f4b1f5aaa59bd5a2b03c144ba6ccb445bce2d384ab40823271342128a2b7eb68624eba59b3b2b57d9a4ac7b630d063400a275ad71b6b08a8cfe93a64d368cef666a4d208b8f39c442400c1a7c4677658576417b5b026d99cb80e01428be00c720e220a2705936a62d6e737900bd8c3d0b464ed7650dd7c84c250dd73c7536abbb4013809927ccffa5391bb254294c7be0596dd29aa37445957b2aa88dfc54447894773a34e8e87b05520c9c2ab4dfd69cdd9a52c7e9352a3ab94c07a26d468f10b2632a6a524e06234fbb2008f17cee6a59efc51b4c483fa5264c9fb325e9d7b9b66c6aae91ba9f9a29743968c5533a3750bb9554223b60c8b964cfa7346948cac1000d840488c3d211b4e7d463ddb15551862f01d77e87b60899e25164cccc814caa5c0555f5413ffbdcb5101458a26061560463ab33cc2174c61f5861986b55d6206612f386c996561b51b63a11be965a1fae45b251476e96c3864925646b6246935bbfa9f4bb39437195c6b98cf81a071a70f26b0ea61628fdbc91ed299b6326ce7f220aab6965be645ff7c51248e456adb343f10990243401d8e05ebc48b58d2a77b21341ef513e66157b83596f1f447695e8c82279922e15987ab14259157ee6e07b5ee28dc41c68dbc14c39131fc7a4ccf6420f65479701413d0eab484bd55dc1669e4e3a3eebcb118c899b2cca6cb2dbacf6f5a717ab0bbaf02141299d32c88426aa4866173cc12313f2c52624005e6fe176ac02bf45a9964659020bd03b9ddb8a99322b0452a2eddc6ea752473f1c1c9ab051dc1973e81b1e8d746406148a8621575f7c71cd2879350a2970740156c69c9ff4cfe97a3ff0a90f16e90336f6825bdb8ba0a3ccb2f181d26cc88605493b442a9d5a9f788895b720516c865d575c75276c937e2252a486c90e64b1c115060dacaccc3372d1475c3381098275bda23a52083c6e671825e57b40606226247432213988a7672d80ca32a2356e161b5a3d5a218cf0c6788c62b786003154c90312001e73bcfdd3312573504a0c402666620b31606883580ea09f690c0cdd948520b19bab2b30fda60dd903c8b4f01a83238ebda1636c911895480a8e5430da58462455488b71a735ca62c1928722d57c3d86ce66760433c15357eba556db67adb16f8a02cd995c2525d21b49a06020daaaeaea50d332952f399bdc859574c9c9c6056765d1c257e5a655c9a6c619167963afc850027a00730d60b33e2b897e71b56466be0fc98a1c314b67b3bae780a622c58eb05570024c989b286763ba420ef234477c2dd8bc86b9c9adfed5a8c7b948b6735bad758c04f08025eb01d217ab9407881878466904b2e4965b2275155fd1b8000c7b2983a9e8f87243551dc31b884867b3e9418c1d5196f83b2e7edca55cb21dcee430969366fd02a85debbd759763010cb918b13460c33bda4b43c2aaec2b4d19800eb45b65c915f8b969eff9e9e356faea1c9cf69659599b22f57b8184a0ce2e4091f1b4b03b77635cf149b6492cf75d285e028a57744c424673"); + _ = try fmt.hexToBytes(&randomness, "6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"); + _ = try fmt.hexToBytes(&expected_ct, "892f7a7985caf0c231b2b35e3bc7de3e5a4739b72d3f9be342e326c0173d55a5089ebe9826c834792a3236800eecc2612b4d92ecfdbed013a6bfcd4d1ffe5c4150e7257a9e7c0b2e0cbee757fc86b5debe03aaf796c76a5825cc78667189e0e37f4a1c3dda770eb8e6b978c89181f4871be9a295832334dc3a7f2b953f7df43f321137a9ad5b27e344678a79e386e402236124753e6dfcba0dd0dd97017461c2fe039c72e9d0073676f0749d8cc9bcd6ae0fa6f14db0b52575845c5b59b82aeae93c8fa1bcec6edd081517d6f2d3ed91575b2dd7b5893f3dd755d842bcf3e8d14afc5c236ec66236b33ba875953633eaa23afe2974d00179b72d117d9b8dee5110036f418baa0be052ec09d70fa36c943bb65050468bdfd63435f2edd7962cc98a0fc6b1d2a2c31a3581c31741790e4f7acb162a7146f399605a08cc99b48a96caccc3118ad9fbfbba58f29a121ccc604e9c0987f2250be2072189d8b01d594e946f0e5bb1b4e045ac5e5608736472386584f455be6e74b9cb31d6ffce008ce283b3f834c56f64ef829dd492eb70f6815c45128c66e77324bb03f71baf57bf0e200b5a59bfb1628e2bf209e8d3d39a2fdcc9c3cc7655224efa1efa86f550e72c11b5ebaa0b375e11d77d0a4cfe4f1f5eb048f0cff1c2882fbe01d14fcd97cb2ed5a40aa97c125f81c8c91164cbe8477058ff9e380604da9c2ac1b061853c2e4e979811bebb99948911dab9cb03d7c4975461d8e723bc415a3912fe1108de37b32b49174b722022c80dfad2881ad1db9f1d6d06090cb1421d3798fab2df0f4408c11d07be121ba66b406a6bcd892cd499e35e1c2c20c15c87ee0e79612cbdd04576955bf61153eee2798c26e4d6d3050f3de5f6771add0495459e5300bb4e139839bf6a4206d7865c159d1ba9bd566e73d9a085007681d3307040c58616f369c6f2baa54fd59b4e27b806513ff678c2c6bdcd423e67047460a3a39cb04ead7b095317f0993f3ed75b5fc8b74c458a3bd6347c6a82640f4041f0168690f8f68f2cfaa4205969fb4dc9ad42d26b3fc2ba5bb08b322d0203118666b665e2041fbef0ee957f73f60fec892a65316d3f733112ef2a19c79c2595ad99a4d0c98cd148326ee8f2f7b79a161333302268c4270a96d5d67e3503b688a332f26543ce54c3dc3817ddd616624ef715a41f1a80f4510fc769892196ac3f4c62dd0391d4c5f215ab447299c7bbd0ea1af7d621ad9d662abd35ef65f900a40b36f32f0352c97a90e76217c317f1890de7703d6009a218e75037b68c6d34f0f8ca6bef01af7894883493da5c47d0fa116af94f948747c969b9779baeb8b279916b6ad0eea9ffc4afc1bd907673203413b609b47ee0fdce780e82a6987d63887c285da97609736ced5fad8faeef141d8d0344d70ab0795a6668fae59aa65d411107631415112288c7e3284e26b5dcdabf6960821bb74c79fbc6fa73da77a4220943e86cdaf4a73e1c5bd918eacd53f6e085a694b9337385b409bb1f8604ab2b9bbd390f69cdf50ec28462fb3f0798f9fe2c39f3823bb41cd3effe70bb5c81735be46a143135c58454"); + _ = try fmt.hexToBytes(&expected_ss, "eae6cff2b4d6971efa91c6333986693db4f5c46207af27ce6f5964c0eb4aef50"); + + const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM768-X25519 test vector 8" { + var seed: [32]u8 = undefined; + var expected_ek: [1216]u8 = undefined; + var randomness: [64]u8 = undefined; + var expected_ct: [1120]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0808080808080808080808080808080808080808080808080808080808080808"); + _ = try fmt.hexToBytes(&expected_ek, "003180282264d14206367c682c2a282a58c11467550795801e36393cc16e49f565bac995ab504448d4840b85526e836ca6d641f151bd50897e1f9a5f6c718a61f97f866b364a217c87e52cd28765ab18bf3c931a35150d1c0c32c6b863872a23373057bec82e671986fad2cb15a06a9687a0ce923754138b4c54ba93c082c147cdf186c0d5746cb6d54532a2afaaa701220342f6303ea7b66d9942460722298e3bc2f0a612a22a986946737d057fbf3ace20cba6f97503fe03caa5c3974e8aaaa3c7ba62bc70d1547ea9336ad15315cd8a2919b7683b568aebe54b385612f8829399d83aa3c2308c49a73379481a690afba636e14c7e6f31678c022b552b19a6b90b252a7122575ba041c2daba8db6ab6cb9d13b5bb391ef0b48fd578e67cab1d4d01cf4b492f136c9c4807b4a2479f35b255f234436d71a123b47384c1b6909b0d8c55575615a314178675cbc94e746a415bbdc912474042a93d776a89913a2102efa9377b85b0149075eaae72c6aac3d91c74f71d38c063963d3fa0c4da13f5202931f06a4515b08e22260309b882252c972ea2e06160e1537bb38eb97e19909e58a3f3aa007daba597d08ae46767beb517fab0124bb39ba6eabaf131b9611a9bbb26c1c52556030599be5382b99c79f8d4356f3dc35b08678a2a1b24b3cbb6da29f03a1bcf1bacc87a642d676abe5826e3836aecc878d2d67580e39b9c55b7ac1e6b8a4ca6ec2e8934412258c0ab6708135fd030cdb34429ee0a19c782623f081c0564b7dc0bd8c35b831672a8413754127a45ac7572185185f444f017640b8a4c0819927866332c45374c6b25b88416d4094081e832f26d44f8cdb04bde72f17e38986a6a693604c637cb75805092cfa7b2921665e0803d182600e001b6f023cc39396c20018cfdbc85ac8bbe5cb6fc094bc55c854e28aa3ceabc7f4e1ba13277628a1304d6c4527533cf9d2b6d43a1f6c71c71586121c3254315a6cdc02b9afa12184e51d3db071cc671864f2ac51fc653a1b628173061068924f890b18acc74c4524240696bee4c099552ec02354bf272c94b541b5f4495e73c181827120872cb4a36388966a081010b80a9cf37c4715556f9d0c3a5f41c587a7cead9ab40e366b53612c745632b0146368e0a52f0b078eb20a6006cbf5591e393c19ecfb8e5435a73cc0c5ce3a008f5053df1647293271e1366867232cdbb8c58066c105701735f911db1ca2c1b07737467805e304d243c733a77ce448b639c295392b1458b4a1a8474ca2968e0c78917a2b255fc247fe493bd0d9bec244351890a895e470d298052750166b75a98a855549c386b140bc24326b044a469dfa660fe51a928271d011cd54682433f5583c5205898c216cf80cc5456bce0accf8862800cd36661332261297ee9854d230b432d39c5ea6672634a294c929e091329a37bb5f348f30f482699a88deba93d58745f2b013a993816e4c1b90d28118d9cafe2a48bd024be328490b703177b50ed619a9b293944f30bd62119eb15486a6c3659eb0aa97e1832d82723627670c30b546337428a7364ec49539709dad61943a545088c754e27c857910713376b859e392d0554a09c04d29aa8adb8754a491059903221d689fbaee7d0a714487053a812bf22bd20bcc6b3aba85396dac337ad43e54945218a81ef4d5e62b8608e130d9278612d248353ce8338d4ae997cc9f20d8726e"); + _ = try fmt.hexToBytes(&randomness, "6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c"); + _ = try fmt.hexToBytes(&expected_ct, "fefebc6f6f4dab06bd9b8d0a3a688b06e4b3ce999cff7eb763d80f6d288d9d8c58d240d8d217064c9848a1508726829e177a02b99ac33ac76e50a82d31e9f952098c4731a0fc35c9da8e9c87af7306ee7171e3aee3a3d2d046bccc1594a9686a7749b906346a7c863d8dd34acced601a3953a05e8ceabf34797b4606eff63e66fbdeccaf981c13660a8b8de661c5b753f73c7e2cbc733379c4d9c36b93b756f5becb1ed569d6db0b2d2b1102e6064cc4311da3030c3f1a1126df69fcd2c5c3084ee1cc75761e5358ac39c4ebd472caf4e555f8da38dba8ef862c92eacddec9c270b5c71274c15fc38674bebabdc7cae2444dec1e7977679578f051fe3ee9d7a188565d5fce8fbcb842b28a4d38d77eb37dac58099664fd1b8069ceef1e06ba95a39bf48f7098a9bff84f6f2df86643db53455be4bfa4848d93caa1fc1398ac240d186bb3334bb5381c9d089ae3c8637deedeaa576e6b92cc7b66bd3a31f3c956b4aeb4eb688b249cf9b57a56d3656b5374f806b02875562ea15fcb619395ec913026dbe5a6d488cf907745cc65dbc9274ccb5e2461b9e923862a67744c8b8ff19dda1068fe408859f89b5b8550ed08956ce2b5c9a617e7ef6022772a58b63bbdbf5eb057c4bdf30083bc5de8a22628fd845bc6ebcfe27277d1d7f57ceeb7beb07a20ca446fc65a372929920792d2c46afe34be5a052ab43db9e0b3c2d024cb720e42bd20db4a53e5bb32a1356989b1d5850611918549e9f57001c9488b8eb12a36e85595ca45934fea1d601b42c67078a4fbe701496e443b49fc8822fad0c8fc3a25b3910a5158b380aa678cda329e2cedaec1c4a32e51b4baf7091efa5edd6ae2aec450e15cfec1ced9a1d158c9f8f19e21155e4163eaecf7f01d16ba495fde48f39645a44d3733ea265cff5d4f2129e3c83a6ca33a6223f855a91ad49776d64ecfae6878668efeeac930ab6fe9183370c61727b4049a1dff8579947bf16ad1c0e210524c4f5ae7548f3d3e532e694abed9303ff260178505542141ca980de12090eec01da3399e8e454934bb15759d348404d647bb2a409b9d8a956021bdb85ddba1978593aa56d961ede3a707e7b0bb6f325229ce754c702d9ebc35a2663c0ceec6b3d04ebd91a63854736ef4b601495c26aa4927b9ccbae3adc808b32571ff32288d46c2967a96b53e756027d5eafed7dc8d7d5337f98309ffd1a300eba2c02221a3f100b68cb066861fbcb39252ac446c3ed3a9639708fd866e9fc0bfe4a7aec198696aa13979287dcf1fdcd143a44a78cc6006beba2e1ae70e8e857764d233e54830473fbbd2b173a34c16c2032d004fe19d35d8a5277824260f32ae501e24592916ea46ec14a9bc301fd0c900e33a1b24cd153a25afaa34ee26cbc9215fc6fa18972714aab79b72939b9f4d3190b9bd64282c0e630b6d8c6755d291e33dc3cf6b6a740b565b1cc292f2cef3b8cc6a6f13a3c7b06525e4e7897f63c82502f7fd77bae5a80a63c7436fdc8387787ee34a000ac1512c5bb3820dc6a9b49ecb1b04fb2b34113e75b7e22b6b8058859d0d2a505af21b5fbbf10eff906dde67"); + _ = try fmt.hexToBytes(&expected_ss, "83ec9c8227c5306cb0e60bdf12678a5de9e24fe51855290a64f49e9795415661"); + + const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM768-X25519 test vector 9" { + var seed: [32]u8 = undefined; + var expected_ek: [1216]u8 = undefined; + var randomness: [64]u8 = undefined; + var expected_ct: [1120]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0909090909090909090909090909090909090909090909090909090909090909"); + _ = try fmt.hexToBytes(&expected_ek, "460393d6222435d92a68eb6b2384ae414ba04199ac14e561f6711facf87180a4af6156a5cf589c8ec7983054764231646f07c57ae4247de37bb73758a60b4d3334985238563005ab337c6075b81416c241fce764505acd0fe7b0fbb859e4172390e670089414107549ed298bca658a229079866b8b960a7c7fe46cc47a1773010f106b6f5cc9c2f906465851a7716649b6a67ff073807cfc7be4cac44cd1af6a372cb04161d4d39861780c6f62051dfcc39c143dcbe49bbf5b58a8769b927173e4c7096c91310a91484cc80c55217b76124d0db0965f84bef016040cf19947d61e05a14f322bbd918392f5083be540a122a3b1d7bc7c49a868f6384dd5259850d427166752bf286a3ae729e3a5a5e76209de5b9c0783a4c70504a338af3d178ebd114b7ef700cc17919b258682d21a1244a002fbca209a80cb2a94e4476aaeb7cd002929ef999095c893624667ae2bc8712b20e35815599196de478f674b50e28313d7695ce2ba3dc02594171a1ba7a095a4351a0f3306f51b4c09ccafea587693a9519f4b4976260445421a865a400a63b0a03a8d9a35ce3335bec1912460e1a5b4685f8fb039a5cb444ca21f87c522c7e6554f29007c0562e5f02eee849f29d39bc15b58ff58b252581adbb17a42f2357ce62746b1347a4123d02aa5c3974eed863eb4f309c5b265d038aa6f994e8de94da384321fc65bda704a15216451465f9d44b7e8a9b7e6d356e8a399e7eb39d0b46d85ec0cc93c56a6d570c9a8865aa6c74f358ff1c03b80042567796c41f418747126bb4ac29d738372fca1a9646ad6e7901581c6845c91c3989058a82bd80117e7c73bd2da15cff522fbf599fa6840317608e410b52b4c477827877ff612cf89cf6c87c8a72b175b6c8627e0a10b937cc672c1af54b64328c733c22585b88c54d30c1a22bfb6a2559b178db7a0aab6001ddac9250416ae5c11c0a5a26a09d38518b28f8e3a7f2eb51e0d679f1d928b77e103f4fa6218f68a1de0af5ea0bd1a26bb624879ab47a28e9c40042b29cbd678f7ab65353807d41993bfe11607313430e5aa8c27b9af3a5f10531aecb1a1c3710f2b992c99b604f7b2a3269a49091a3a56dc8b78487ad9ac24e36c97d351855ee1715083a3e9c32f52f735a76cb008714fa83bc70e4caab72c485ac8431cc97cfba727fcc0af9c542d7d9199bc4b50a9ba83db77c7dc206fda0547e2795a8dc36fd1b33d2ddab089d95eb16b15da94a74ed8b7e8daadf8180721e0a1e31002497c83ce1747fbe78cac291ffd967f23f47a8a30485aa352cfd4c6907cb8b201bc3b9281eb51985e11cbb4b5250ef7ca13c70674f395c52b177541b57b3aac77e382d5bc6e0c32aade73c74a163c0f43a59c616d76393f39166de8318fef1b2c47075c19885ecea7b4acc674d1c72a2e4ca70d28325f12cc33ac19aa9c5e5ab31c7ac6933c1a0a79065fa1e0237cd90a13c7b759980262378d4a17b85c184f84761e071a973784b1c30a9358b76a7af10727f36960f21c6e078d33fb528373a436fb237f87317b81c04926245982aea0b39c24a67effe65a91b211ad7334f8e4858a3b7d0ef21b3e443c0cb64e089408006b103f3841cab70b046b98e2c8aed94ad683208e265424b077389c2ac6571f216fac52e35cd280e51aaf66328162012edaa88f37a3f6e9c0c89861d6df5d8a3a453cca19d8746cdbee424f00c338"); + _ = try fmt.hexToBytes(&randomness, "6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d"); + _ = try fmt.hexToBytes(&expected_ct, "a857a7425c6077dafaef133c62869e523a4b41110cededea6ee66b9a6bba634d92cb41d5fbef2ccd6f5f057951fe1b44e224cd2314c9ffcdf4c358979d6d065f1f12a51033640c07965e6d4342afd7b57d528786b398e13b6eca581b96fe77778d73bfa2422e43093f7c96434103b18cbdf0aa6549da8e169b66f42921b89ac8267de35446008948d6026a0bcbe61357e97c7fe7a95337dfa3177ca6167c3a2af8dc38e3d708665824acf97d6d7b152bff781451c587a282adce031b3efa26b6d8bf4b49733c03dcc4300076049e278d3cd872174bc374d77038c75203ba45d30bd4110b62346c3f0bb1d8563d0e2d58cac839fa693ca96a56eeab1aa4d26cc95e013674eec4f8f08095059f081a0d4dfc0735653f3097f1a37da334007082ba6619844547e0d3296669eeceb02ecbf0c5c5a88d5d1c432398361529e0d91a628e568cd9a18cb3e8ca41315ccbd8ff9cbbc0677150f2e06274ec9e2733f3111cd4f1b900c7a3a80b517a7d6917fd0753f59e8bf03267e3a43d60e1857d4922cd0f14b6d28602792dbfe2b4488e807023ff4a8b65f75fe1a0826d5ff490bac7be071b9545f6e7ee758caf460e7e92e52eb83dcafb5bedeecf44a5f5ef23690bd83aa5ed2ce0420c697dfe4eaeff5d64be78fd3d9c96f66fcfbe015d8a1e75e93eed734c267fa515220e9937fdf8df271f69c8e3d6dec76152404d862434211bd1e4b53cb9951c48b796fbf4287d3386c65217b41f2c414daada2023c43c08f8b6edbecc7f750968c4f16c3c983a95d73c25d3cd4aac5bd5941fa376e1934436acecf9bb9bd4409d0944d393d852aa15d6363bbd83cc24b1ea841e00b99dbe9f7b9fc2a415063865b43ecc9db0a95336820d40ec4d7325d5066eeb2a144ed3c27f5072c9a2e596d395bd069fdb8871521a08d0e9c1810467a271b4067a54d9d81eca8f26d18acb41a7de599aab1f79ddd0128c07e44cf2ccef72368cb4474db47ef43917940a80d05aea5e8c933a0ef8a8516a6dc2a50df273288d97a9788629f001e487434e6a4192466e63f0e185810665267a021896967d833c1f108645a5d17334d5dde8fd617c786665d7df9762b8ec0676af697dca63e62b597aa2cf89c558accc872ce9a1277f88c5ac160b2d13a27de6b4027353adc3bf596d3d6527532e66225fa53e2546f6ceb240435bb93d10e4677208e990f622276d04ab8f2e4ce2e5180a436d33adbf29c2cef8704a41074ed16c164ffcd1c8f09a2f752c098caab09da3db75d84ca510542c3adea1757a553bf53657f03feec803950747c8ddceeb31bd658072f01b7972df731af5ff53bf8a8361cc918c6a00693134fe6e385cc70484d2e3e6d365c14fbe6e2332eaf86b7afb8da619dd4c13e86f62ed63da3b99895d6ee47b440e16a3615f341d4be41239336b020174819681732503f275bf8bc494c251e5448ff32bffb3fe0787482b796c37fd8d25a28ea78620046b192ce46fa4c798c0feed1819614413326eb373e622834afeaff81aff308caaf835635de5eb039fc126a017b9e789e1db721cdd51f7ed3f5515d18e2f4e2dd7851a"); + _ = try fmt.hexToBytes(&expected_ss, "d1b5f13316ff420d4ca22c9a8e3f93d27f735d1da53ebc979cce23f9747e3261"); + + const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM768-P256 test vector 0" { + var seed: [32]u8 = undefined; + var expected_ek: [1249]u8 = undefined; + var randomness: [128]u8 = undefined; + var expected_ct: [1153]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0000000000000000000000000000000000000000000000000000000000000000"); + _ = try fmt.hexToBytes(&expected_ek, "3d209f716752f6408e7f89bceef97ac388530045377927644ef046c0a7cae978c8841a0133aac4f1e1a7027277f671219cf58b85d29c8fec08edd432e787a3cf9936fe0026a113cb9efb1d7214049527bfe2141ea170b0294a59403ab0ce16760a8baa95b823cbb8aacdcc17ef32775223c791e3740163941f9bb3f63346bef1c050c31f932c62719429aff14c2bd438ab135bed692d56c77c04cbbffd6335b578318b513771e84b14ea821262141ca006ccb8bf2500aa1008970f216fe7f1ae34125aa290492c069a189222adc322f97649c762c7d3128ad3bb2667971d0744014bc3b67445cbcd0b3e7ea69fb1cb9f9c331f97487920187292926d04a25a2650abbd44982bb0c3c6301fe6a61330d24d8a3c7021dc3e3392c79a139b37613bba67a2984298507b84a4d61eef18acfb979af2d39caa4c0db4513815359d76fc378c63a7f4f3053b17168d0221cf0c2eec5514ba235f81d04d67c3b5c518094917671c26a7c046457533cc32844581277a03eb065c4529a779a9a5878f2aac3f81db9ed3d8c9345697058cbb99d379bca16d8fdb61d129960390524791b9d3e501b900bd1e5002e095be06c23f1fb212f5801f24b6b28c0c5493d246d02aa29fa3acfbe15ac4e212eb0b6f69ebbea259a2703aa4c308224bdb741c65c7a5d4bff788279507bbfe513d7aa5694e7b3cdf62ab36432742d4a0ca9b3570ba742fa803b46989c8526ea586cc4fc32866143b79601725fa545fd280b404530318bbc3371194710b6d74beaa629eb18a36a953b75915ae96999ba5c88cdc56a46861c50032c9b630bcc1445a30878979bc55a2c0955bf399b231203b90c651b6afe0e242b5a543250b142f7291ed753d816098f7913302a8ce91641716623d4fc2ac6772aa5f3674042b7c4a18a2186289a4ac4e200774596ca03e6798c7506b984999db6ac142586bae0799f1e776f9f5247dc574d8556ddf9bbbc4ca3643263457f74248010d62d4311268360aecb4902b450bf2050ecb8ba7a92820d233f5a14ed31225a1d17ca6f19e825894cfb1807d922cbd60761134be419144bcf72006366a4460137ad9136c113f05eb54c409520edc72e4150cc3a24b0f819eec11bbd19ca9645b0810a60b4a8a9e9c3955396a1653955b047bcf4f98433c27236c570d75f809e44aaf2dc33665826351872c293350ab324518c8c0c80b521c80c81a56bdc968a5650315a830c8bb17532c62ccc23b1d46412c256b224fd4674491803501d0143125c7577239689965b6989ca561793c0f85c62a9e13487da17662a7188c70b1040a67ed4c3f85e74e3691822fb96314d6134fe6a626b3cbe1461d62a7b573b2cc75579ffa22967e36ceb2a1aa0b71875a22751d706b72ca9ecd0c8100ad0aa58009a5c83fffe91759e6baa0a9345af99fe3b69509dbc84032868844ab3f65bb1df8beadf36442e48e339c967023a525411544c789a2f04dacd06ffef78302210450b931f6b4c32aab34a3f5260b810f4c9a946fc22d3baabaa80ba8d9955d6dc35e8609b4256b482cdc9d8977c1a47a354e7c527fdb1672e166917b95cd6351820261daab361f8a2dcbb240c55abd6a8105e5291b427b566d731e6b7047189cff20d8b120e0b3e72472d1b0086812200fd3698e23f06e4f4e08bbb54cc2049c039c845be659999c8fa48d7f62327c146cf1bc0b0bb1b91b30174b7bc220d422023bff6b0dee263532c503f3982e4d3e27071b855578a9a9aa63b8a8c339bf"); + _ = try fmt.hexToBytes(&randomness, "6464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464"); + _ = try fmt.hexToBytes(&expected_ct, "d81018a94f8078e02105beaa814e003390befa4589bb614f77397af42d8e8150796f2c88a4efca81b8cf93c0ae3716c54ec1b045e3875f38c2dd12d7f717bd7fb701a9fecda5ed8b764c9a35d4a5c1d8930f6071f653eebb2d1afa77debb8302d16f17e0f5f3920a71a4d49beafa0e1c7e443f8abca64a65a9e81a97e7357bf902573363c0e1a12e5228036828e3f759121fada92441fe334e85d79347e470d2fed945541d832c54baaa3cb7526c3853954db4f73547cc7c27fd38398bfa7704952cb841e38b270e4db7435f0ee22f57d7ad3270bd0c88e71b4b864cf2277c65daa10a6dad4c7abecd95cc4ebec39c08404b522e4ecc1545713f76bebd3b5a0f2feb3461936065dbd13f6a1f61e1b142a2af2e5a482ba2c50cf0317049c0b3bfd6d5e9240eba9111d2030fdea17e33b6524020d30b0c4f8069285f3a6ca267d287d01e827d8422bf5426e11688bfc73756af1841b1c87e126cb50c914b5b2b8673488ad3b074cad77a3840eb12dd688f313ee1e9ff8c479a678f276356fc9d65e1d5b4c1e9855b4175db144f7767c12061769190fe6b5e51563b91f94d131a2b796bd2980ed0dab4ae7a7110e920007a757158a5eb8662cbf89ddffe9d8196821313cdc00108853fc4746b111d5b56da638d8ed2973918960f5dfe93ead3ae521e957cec3c8d843e8fce234c70ad055177f235439d6098bdd771b1cfcfadaab4f50a7378185c62409f383c8ff658c2a2af66498cfd81e962766ac6b774e88424fb4f331837d0a28502708477caf8780a156d723f68fca791e1cd2397bfc2b24c77c765d9b2af36f732d52107517efd8157b283b440a613f756c364ca108971a8878199a93f260baec3e850033cc032c2e53f823576affb4d3b116e2d16049152c35aaa263ab376f0ad5ede6a749607a283e3016e62191c0e8fde33e718cd989591c9a205d608d99fcb8a7471603d716cb01b56328d7d880aec2851f4e6d8b5016c25647e9026ebb441543e8012dbfcf078d4012b8c39184dd64f3821b4774ae4e36365f8baf2bd1f6667c017a1e65ff8a1554458fb3f367c02721752bfa56fc7fd566ae95ffb208f919ef12f4cf8a2fdd141a8df559bddb7b8d1f04ee6d4cf7805d142989caf216dfae985faaab9974f6d9f8aa1129084db8db912b1655f595ffbaa66491ab4655fd734cfd4bb0c0289d4bcc8fc5e9943b351cb147c8db059a24004d1c3e3bb4c14a881e5101acb736c65c5d579acb67ee85a560277b43338fe79d34b772c5da001da3b5a3383dd81319a0b4542e6d7e46eed5314cc70eb231de27b6e760db598ba19995cf69be0e4458e35f3f274aca2455d43fe3344e183c6dc47c857dbe9907b41e41006d91b25adcafc098fe66f7554be8dad493c4f4b1dbf7a51464139db474afab5572f92a2232b59be56a72c0505149dae5cde1e602877037de7802b5f6fa47a4c9a3e52d6ca15339920254e9ffb53c7b834cc0288ed9905a1841e9390ea94a8898bd4c6b6d6027e4d43c7867242515bbeefe12340fc04428a824ea7cf56ad2a64ed368b71315d80cee846007cff1d2eea2c3f0f921537304ae598f98dd10d1f102811a4e2d161c3fd8bbb193d4b25bee950ac839c0f9d"); + _ = try fmt.hexToBytes(&expected_ss, "9bd018e869bb01b63fb8f5da374a73d347ea14cb2bc570b13d0908e2288ec456"); + + const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM768-P256 test vector 1" { + var seed: [32]u8 = undefined; + var expected_ek: [1249]u8 = undefined; + var randomness: [128]u8 = undefined; + var expected_ct: [1153]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0101010101010101010101010101010101010101010101010101010101010101"); + _ = try fmt.hexToBytes(&expected_ek, "ec7b50cddc8360f98b189bac73d395ef947b37d8453886a253269f7b18b9eb78c1b63212471a0f979793f9936b3f496f4b5394ea69c2a35729f91c688f6bbbb864cd5e87108676c4014c2ba98204f911becae33a71e832ac012bb827578810955f8c6e2d26c0b17b7ba574990884546ba58bf6785721f3854f434cfea602e8595c71642e8d4c70934b7e54c638f5a13e1a136bc86565e6b40abc163ca65650baf953de7bb99b138ac1b695023103c9b417853c9d42e54fdb816174659d85a783e3d4613db1cbbaa63fb667a4a636804b6c4ae821ac5d6556688bab1dc10d6779b485c63c0ddacb91837c4ff3402e6214188072b4186a39c65bde524c683c95d3c8b65e37104f551b6a3602eda50b787182d703ac6a221428b4553e3b99c2b251ef642e31256c329b21d1246a71456fce700d7f50cfe5390a1c37bc133809f102c22914a1402c205c0512b733afeea04411ca5ebb0bca9392b1ee23935eb196024732daa2a1f79358e6e74b73c965a9e74778dc6921442b19328f6216a5e814ccc0639a863a437a614def5a61f38852151011b04a37bbc78c1eba4d8d1b3a1622a0dff74d25c731abb2a5fe5919f835bd3dd97330cbb7dba0b74260c963402160c4017d92256a3713c9e77ea0f4901accbd38715511784c9ec287dd85a769e081854b32aba9322a3840f6065133228c41851afcb40ea509cfbb86145fb8853ce14c649691136b8660b0077f3b2f9da82d483c1414c39a9777665899131a8336fb828480986df102628d10b54239cc20231457d4bbb7016f76029661f14ffd3532e2f8494e1613430730ab915683c3c8c4db2b4373a3057a097e23333605398b15cc4d6ac3fbd0732f21026bb0cd51fb738a740467114e7c66256b830022f28c028392cff8013d617c77a47bbda11c4a522f8f2b49f2822cc06338605671fca4518df9b3c506532c9cca3175330f8733ce11cb3fd8b95239ceebc9483cb68bff43b622911fcf4a9c57c226caa38bf0b081535999f573016b14563ec4826dc281dbabc633868a1d903d59207fc662a293735085c01f40b5b56cbb795ecabfad709d611cac73eaca579768213c18c969c59be58fcef6bdd8a85192907cd0773f81eaa24be07e0d620e9685acb0c6b0f54b47dffb510384241c4b733fe08dacb2852b2b74cc014e974a5e9db35d80d7b83ad31da1487a0170ba7fbc1c551a6f1eecb572084180b256962748d5e3200b731ac7c3928585a153b167c92a48cd91668c773707c054af16aa7bfacaa161a620600e8d08cc97601a53391da0247e5fca60cd1bb65ec0417177a9eb78cde5aa1dfae34e948417b3cc0b223803f5f40e8ae3a382848ff80c4185824076423ae4c137bd30bd81f04095c20a01e0a49f664f8f2b7f6bf6a990993cbc0596a514ccebc578c6418e825903ae11ac52831c6a48c67727409ed7274eea03eef32094271b02d4535563aa4924a2666871a4b690540c78b06043bca31ca4e42a03650ecab74792017217d10615d0acdee124e3222c90d79362207e4f7779e097501cf140b1a3431ee0cf27b23a50373d59976d82b5b1ce165f4aa1361157afad564081c85777584dd6058a1a4663b53234d7264fbac6877351d1928c6780f77d47209337271e305370df9aeffb74d7c75de55c006e2b2a047a93f1833da6f7c4226f8c05392ba90626e4ed81bc9dff573aa243055f08a567e29577ce8dafa08297e6b04a779bed852b95ec0ac14e04b1cb58eb656455bad9"); + _ = try fmt.hexToBytes(&randomness, "6565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565"); + _ = try fmt.hexToBytes(&expected_ct, "600ecf4026683898d0e339eeea9ebd437a4a802952bf32bfa326b48eb74946d0cdd5437e70df4b6b7acbf79efe60ddcde985acfd8c2d23775e1ecc54eb6ee03dcc9b4aac150172737831adfaf0e63a4782bad2a785b9c39bf5e34640ea3da447efc2a03e23a337ad1f542c32c2eb46f7b88d0bfba87d8efe8cd4456e6f21beebcf3dd502b53d537395750ce963d289eff74621545d4a5d9262bd14b3dddd4ef880e65cbe8f2f8aad826f57f727a60aaaeee8c69e89af6c539fd4f267c44bee8b5385a460a7c8e4a809959df86c1136ee23e7544cfa7524c6c04ed9ec29aed307b5dfd0108f29294aceeb517a098b8cdbad5911bc75e96258bbf38a20288c6911b2346f842c0943bf8e9c34a0a8e518e92c8761c6efe6b1d3ea8aed9b2c4feacfbf3559f3a5e46e4dfddf81936183d4d1f9c8c1616b14db2057435ad71655d743fad4987a19e821d0ac666ff3e46b7cc0e90b85e1966962279a48afe2e9bbce89c819a8ba52476af074a071495398bd497f4d4f34026025452975cfdaa3e7e183a962bda009108221ecb20d218c42e38774019d2dc32621278b5e88f99b62a9e746d16c1691ccf3e7e9185c3c493e7617f451f632c161fbe6d8ac3217f10ed4bfeee47e4960ec4a53e4852ca0241543848422044a67567a83e09d8e74b9d11af17d53c49565ca53deda7c4df076a3e1b6368b1931d81db93e87f75bea6924a321376fe73b5a5b07b80a98dc3ab8d14732540f1b4b7176e274a905d453eac1caafe2bfe4e6c904556ca91b01b2302215ab3dfe6b49f46963df632a9e7cb8439cd5ee56a1f8e2cd3faae5d8f3462d0ff931f5038cfa70259d963163d6163ef22b0c32081bff2763e98da87817048d4ce755e5d2b1cfe7d6eeab0fdbe766c95f125537a04bcf99026f9bd5be3b26b9b7614f132f6747dd6d96009a85ae6cbb1a14b9231099b67b04d7849875b6492f3b6482f8bdac305f7ec29f28ef4739934c6a7a2800fbdbff6eb2237d6a085ddfab8519db1d2b1e63aa6cb9b3b044278947dc3bcd329aa427d13267f93a6cf2aee8a2ab74d4288fe0b676ea85586834ab57e863d4805703eb8bf6e71fbb11a386e7b64a0d661dbd05f5e2924f1419bc799a089d44dda9066c6c503f8c80be8daa99bd48338daeb4911acf19328103c96f40a77ffd827d52294ba21ad1d52fc27e8b12ad65887024f41e63fcfe654152676ac363f2377c5b0b437e075897e33dd8d57227fc5a536629efad998a279103150e7d47e4b7d11a0d649d146c6560c48c9c0c56c811cfa6f3f62cf717ae571597bc297deed887672d8a8cec2929c2b55b95f26bd5d10ef30c0c4a6295d5ca601538f5a20ac1064d2f4c2a078af1b1629a0c203ad047125eb9dce0d1260eef19cd4ad8ec5d73a01ba23e266cc6dd266c5a81af58ccf1b5ce0440efdd1fe7bb42177679b5e5095ffa0d453bc17b8921008531c2d096a3a4a48563370462a59fe1faff2a81603f2d09ca2e0beac44204a4e03aa852745b1747bb6c424206ae093ecb91789704203948060efd681edaf7f1ab49d5f631f1122d2e0cb452a2ce5490497b32df225372b80b86e5a710a64e8b4d92318414a179479b96827f3379de247163949084"); + _ = try fmt.hexToBytes(&expected_ss, "d33a83edb4fb5a7508686ba4ddff001c17ba8890e9e3be067d50c959b512f9be"); + + const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM768-P256 test vector 2" { + var seed: [32]u8 = undefined; + var expected_ek: [1249]u8 = undefined; + var randomness: [128]u8 = undefined; + var expected_ct: [1153]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0202020202020202020202020202020202020202020202020202020202020202"); + _ = try fmt.hexToBytes(&expected_ek, "08118d8819772292c976ec971ee3039195800c823544484595cc63450b9db9414330419208c509cb62626067a8fd8259160105b6d8a4023b056f5ac2d6159fa5f245f00c719539a4601466f6b45b2a68bdb0db7424d4cad475a8d68b0d6e086c3f012414e22900f01179e8c90a8ba1d285cdcc7c7ab1c7064e2c15233acee183a1075c04f092a5e3676b1ec06d15d348e7781346ec95806a5e00f64d1e101bfb28bbc6829372f32bedcc0de9a70a02e508b760422505481709bef10697fbfa219b99a815f47e4bacab0e789ca1e414db529deb043bd8521c2d456a062a65aeba2a40dc6b9ce02474a71fdf852f343b22d2110519955b964382e74a3cf78586eaba353b98228b0268f8480b02c4b4ee208198fbc472117c4be567858c097fb0869a40588418973c58753da845e36c0adf39c53ea9c8ae24c343bc87bcc3be69ea40d9490592ec99e9a853f4f22b024a1b15962b049a62bc198706e310c8524c51872718d76c6db25cd824a1b75a94a7d341ca40be1283b2111b687be69d38b7297a90384b0c0269ac911cd80384b326357262ac13680dca37ee18477ab23e16448805676adbe1a5b7732e73c0abc3c5188e6c7ada3c1f1f124663e83ad5899674253e9bb15f39908ba4917dc11025f7504425a305848661c38cb09a82026d20c9bd23949f285519db298418718023c8d7e37a5bb1062951b4325249aad59acc06b10161416ccc78db6c6c3f685ad3d9b4916c622163017f9662da4234bab8b8b1e77290867d48c28a2cb33c7d2c7874c2be936ca0d6ba907d6a823fa24a18c56cc124209ea488ce620c18d00ffc8b8f0c11cc5850c30b3a0fb7faaf6e526f9b08972207a38f760bad1824726017a30634fd239ebda59651b4c8162346bb3652dec39f56626547829ffbb052a5a6930f2700fad33fb1eca8bbc40fcfe778189398b5527a09a24a53a958e5c25353951b78d85916457c1c5046e497ae0fa24810e82d360050e4fa1bf55b719ab8a080c23dcd80c0d4915d8458652d476f50f3a5b80ba6ffa9a76bd9524dbb39df7826cc507a9d31aa29b6207eaa52b3e224259c4931b1ced9b97a42e6745752ac0603917a694d7ec95145094ed089008af675fe51b2b79970abc282dcb632c1fc3dab85ad14893d0ab63b9e21a368845e872bb1468aa252554f59f90c9675cd044b930e37a96a213a28277614443cca4317e4a2af9f4c7124fa76e1d48f38981d7df03d2bf840610861b210300156c3f999aaac1b2983c45cf0002c922037bb4055dd1c27df511ced577bb8046e003507aa7b2c52194680b93e2eb40719539b8a93b8e83b9e205714927264cbf0653d4429f504816766bf97f14141622e91b20177d98b8db9351b39632be41a48f39ee050cc1919143a2448d09c2fb15a680ebc07963b788480631eca37e19213dbb6c5e8dac3eee81b0292cbc681563d05779b79b5d8ec37b331b3c021719cb95e69ec99a0f97b723303278b9403fbaa7f71ba70d61d082c91a6aa2c8a3543b5281e1605832c740bf67036f2373571f09482b27272c8ac2c69b01f715dda83377aa093a044541f6000848ab1ea65cab1345135a4552be42b27c4b980065694134a90d436f0e091b02a02aa99eac7339907afbbc158a5127540423f23f6927eff66915d745f4d420459d5057631d94214461c9be803e9d6080e108978f60af4795fc34870e1c018198d85a4a116ee21df20fe81d9218ee22a9e81652b806a71aee14f84507485356e"); + _ = try fmt.hexToBytes(&randomness, "6666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666"); + _ = try fmt.hexToBytes(&expected_ct, "413c55d5710bae6376761dada807daffd4dc45f9f70d825e0d46176d4a342f58f20d61879215bbe4a774588838175342628a905da0dbaa1346e8e913f4738defa0768445f1c625d296ab06cd547b93e764a388e63815b588059796e9bf3fbead072727703b036aa73223007ad1caaaea0c6cc38d385beb06fe8d372e9145c08e1bc3cb5ccb12f450ab0f6f9da5529629a3f1ff6312346b6d2fcb20461e7b3b245a97a03ef27f2e5442daf2a5ea317f454528e9749f06342aa7594ea9bda0cdcc7c0953c36372359ffd69f2aedc1adabf8a3540e32ab36ebc1350aded1072afe3b78a6ec2f943d560f4849d6bb1ee24679e8f70cc0f4cabe7d4cbc6e090353ce8414a93de9c84a32e197a2ac95e9fbc5d616f85fe199e80793f6dccac203d2f236e7bad1a4e7ff51b3f3326a9742826ac6a23ef5a945aaffb54faf50a8f0b8c09c55cf2bc812e30fb3e687eca91b494785f121241a1ea8d0cea089216c5a96a467c06d4f0a10c2a6bf551637f0fd5635dc1734e96eca5e7c545d66435b8b5dd88eff4c2cb3c73c49dfc9e56c293febef797a7d36d21ba30361f7fec7b0e51793f6fdc2214f420b713a1598f4dda1a29f9124469407e5c5c5c908e39a78ea0fcfe4df3419692435a92e0f9a5846690706cdd23b1825be8d0a843756fd97b4f277cf0714a0d9da3ccf1a31a07178399b803c7b4837980bc0172f58716b3baee5e86441d32bf31c7ed6e9c6d55eb1ed528a4a306dec7f37b3a575086385a9f4641ef28da16d35578c743c8eccb0581b2fd308a3c9fa15c8319954c8f4259ab09f178508720ebb8a0d893a8c45ec23b2c1c2e43db439ff71fea6a9fdcd8a9d3c6e0f8b9e9e71ddc2aa52fc5cbf22ed67217d847e4c84b72e7f201aca56c7d1d5e51e0c03cb596a01d20203b38e0e7d3086c83a4a1930754134904487c43fb96deb449aa832e63a82d132660cb7976d9d50742641c28c8e2e1bb00a2c65e9f8b9591501ad60568af112a5cbab134bb472fecbdf24badbc6562201e022c23fbc6354292ab743a863a139dd4d67b1bdb553b3c57a5c7f5b98cf145ac142e1ad6ad5ea3954fa3c2b8ebfb6cd05b915dd1d87262d7ab1f1b47cc0a3babc15a7a1415976644c54e29338d79afa9d12a669d3c67bf70e604157815f041556a5cc1c8429880a5449d033bb3f1f2b879f0e689fc2a3e2972f75f6f25b95bead0460f35ef71d0bdba380efbabed6365c6e7fcf2e22361b572029f0c90f2f74c8e40c7941ed8b6eef5a722bf2e5141cf43ed2a69b87901d546a85765fc494531e61f3d723107659b4ce1f294c352fc45c28a82cb3c242e5d6b9cf43d071bd55b8bc0d47b225463a5075639569cb073ffc4e07417dbc5a30a8e30545264d64d98d13336fdb6bdf8c71041e995cd433a77a9d4ee25e20f757cf76dd702f7c8f22a2677f03dcba47ea1996b9d783e44737ec501a8c75acb6d7606a2b6eb1e069576f3a87b32e587923fb79171c77083bb629efda6b9ddc1d566d72a53161c165d0ccea7674e5b1af42b040bbbc5e8bc84bd33d1d3ce03ffac9a747f4c1993fddb2ec93a4116a86f022a77c3c17191559a4c2a1aa57e79b8d1977da2c959172f478e341e27028d69fffb7b"); + _ = try fmt.hexToBytes(&expected_ss, "d17a7ca859a18cfbb5fc7bcba2ec54aa0e9ac44959023199fff5b60db9f24401"); + + const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM768-P256 test vector 3" { + var seed: [32]u8 = undefined; + var expected_ek: [1249]u8 = undefined; + var randomness: [128]u8 = undefined; + var expected_ct: [1153]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0303030303030303030303030303030303030303030303030303030303030303"); + _ = try fmt.hexToBytes(&expected_ek, "04ccc68ebb7b60c6148fa94574ebaedb9c5ce5eb1ad69cc5a4d7bbf9a410295540bba271ae8a178bd025ea28887ca8808aba8fac7a44260c6e39b883110155d0dcb82ae7609bc803a8f927dcc2c2033cb07ba90fc8b068188a7214e713579537e69801ce304251eabc8b34b03ad71246cc22f7671adf572cd6a2730976953535c59d7c93baa5788854ad52f48e9cdc8accf4a3441392f006378a450289053c2ea689a80699de7acc6bec4c2b182e3194acc9fb1ce3e1b389c5879ce66bc692a3b15343d6e557ff93127ae69007e6913d51ce703898c5449ed360259384819529c7b54b9f5b6c9755d0a627554772846127c8a580a5b6a9ea6695449be144306d64cc8102127278827dc25da96b6f4823ce5ed25a2b199f3902cd8bb82058d4694b40ce0ce1cac1ea8a047a1ced942d78ac2923c9ced1d563fcc24895b1683615b134856ae3f36e4b382bb160171ed400902499c6a0b1b8701d89093d6d72a992c9ad296308a2d44d26816b1c942a3bc479979516a0dcbf16bbca1140554be69885a477d078ac0a267e8294111cbb42bac3cc733269c7f84bf315258cf8cd04774f9ca932c7416785796ecd781e17b6ac32277d6d141906811430da866478499a8c94c521aa4d4663af067fcd2c823252c1dfba800c7b1681955de39112c2fc5f4a14020469bc22278a84494806d43528f8ad8efc88643038d9d71c79a50710dbacff686396c34f9800b0671b0da3c2ad4dbb3751b3b3749b63e132a336f19ae8f37a79f6c713c48b724c80465b28e578658bc8329f0c1d75d0ab1d632027a3cc8d749216f50440109ad7637f3ab1661ee7637eb06e70d4c15db81a2ea25ecae4524476106210362a7b35c013120b51ad9b2c88b452457b75a98fa3ccdcb183aebb1684b72c3fb5434c277907680e8ceca5d2fb88dcb43b050a5557b19d159a6050a6115c1c49232cb5150463e165acd4629ca4927e3ce46ddd1a733dd23f77b44dfb7b46ebe4291594015a4ab5ff00b643321856b3b062ac28f2c4cf7b30716b6c9a53271139685b3d2bc20cf5c766265a6666652393af58ac25efcb502a30b9f6bc2524cc615a911b1de63bf1710f9f829c91a573a960a44d43138a65c42d41000c601c7ad1537633433edb5023387aad5007a09827a55b6a7e7a2911307e0f226e9e52ae3ba4c0f14a1efe9571352278c5a4a08cbba7403c35ec69cc2a2b364ed145b11a4e8594087236a4ba7a2d003aa89fb2c97580c3ce115727ea0e99ea81cc8354164b0602e53cb33638dad5a39632b70f4706eb8bb6d598c6717627fe3c02420583cbdac9460a9d55588ffafba8cf748c16283b0e96b8f95100caa7a8d12029a433ab4efbb9b2067a0c615d5358aceea04b4ca4bf584a452fe2768cb5bab0fb52aec375c3337fae44b305f1389f123103669c7901a1821c4715b5cac1c89389cc9f4df192cca789ed236f7b378fb2915106ea3cc1b90ce9d6c07b36c4f09b5654e3a116c60dda685b9ef6893b1b42348a3ac87284eed683fb346d25a562b90a778e6b546e40b4fd7c1d3c01983f851474c3832297019a808ef64957d7902578981d9231b382169d533a2202e95d18f152e8fc25b615bb8a65482a2167df6ab2811c73bf8fefbec077f1e668494d422443a083b9619254ec3e6bc6f3020478cd35c1616ff29a1960108be12b65f0a299f3e1a5efe7664ddbe33852e4805aaf60435efc123144540391b81683b5712fefe40126d070b4f9fc5e409da896a4"); + _ = try fmt.hexToBytes(&randomness, "6767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767"); + _ = try fmt.hexToBytes(&expected_ct, "f40d556d507802ebe7be0e65ab82b0aa9ff26c825d24f98148f75d7e910d6c7f5852e7023a4e246be81b807fea96928da6a8c4d23b8326ea90aa7f1f0673a57277bdd08960f7f886777f1725b882e1996632584fce4356f7345abd8f480514275fbbd96ec6d3202de46e18e7a827d4dc62c1681c36018861c33cb2f4e13ba5da65558441caa6ecf82a5e74842268f4ef5036deb2f0f6f5cb422dc2b723a7f2f69830a52326621ee034c8a9e80f39070456bfdde653314040b4f41590723b66a2d7e41153932521e8e51108d2d98841b2983baa43b0dd6a46783be063850b22a2dd05c1f9f578360dc3dfef4d79e8c20d2d0c45687ae19395355e7cdcfa039e3c36b6df4ea11b4122918fd6ec63ec672ace58a8ed9dfc61e7d3b5829d574833e0e61fa08419cbda05a85b3c4b9957a0968d5825d0d052013e75f138c8d74929a631a0ba2ec9555e2767f17e6e22890a5cb00f63f09e00b8decccf7d7d0e369c4396cb429e53d8cd4636ea630d6fc55143e6146a969ed0839ab05dd079da3f946b3deaad2774360529f2aa7e6c400b66a5c449dd8362fae1a1bbf110229810e0d4725cfa2dfdc046d4c18637e1de3ec2b52055c237238de0167eb0844c24a8fd91ac9f66f86efc945c0a50672926efab53bd0725ae9ff36e9fcbecd58212cbe7e0f248b9ab90b2f56497f196198043fa10de909b05bf3dd1d20630f9707095f4f80d044418e67ccd79e8f28db7acb1083a2bc63233a4f4798f13f21e81da6ee03c614cb367aff05410960fd366df06691b374247de70fcf916e653b2bf01b49cf116324e8104da61a621b566a62c97c6c058208e4825727cbb6c2ebaa0e888659094aa03709659e272b4209c18366196110d71120b203fc71dd5d3c17be4580e5ade64a3fdeea5b85ad33fcebf30b857dc7cfe3ba52ea8269cadd7dda308460201e0119f8918de8980f04b318f39487e65ef0e0b83c2396d2fd87f4d54dd00b405063f072659d6b11513f448b20deda3d874987c252b7d16d94c4f811c97134e5e00bff8300e718e17de3735bb4bc052100a3823f8db4be2d7554003481ce6d899d74c1ad9944c01d933305851458933b3f780ad6c1db489da507621e39be174c71f73ec9c1ef644578bb1566136f17e91b475fdbf354cf4f5a6ee300d3938f5b4a7b9bcb90188a3d9c8fab1326df69f5c3753a8ff9c5a7bbc4e2255954dfb6a2ce81381eaf9d224005e050eb5f53d05f0a41bcf4f3c0e8771e84eaa46ce27b0438d4ce3ebf9eb25b5351643a26f607c41b6494ac77e4c4a2fafac8e3cd872f31816501efd66c41795fa0d01ac0290253cf6c9d0dd8d5865684c1a02748a824417827ee374404a59ba87c3ec3caadf08b0f920667fae9ad18560edc3f8571986ca0bf1ef114d394c08ec5ff221e9f9ce7b6508eb6c38d6041fbe7319bd8874f35bace85c0bcc08cdcc642ae7fc264b9be08a26e5ec6a3618a078a128d0b8daf46e404eee4123b379a81680c8336036d9a44c12bcc23ed7b1b96442108843e5fcee042394b456984b83ea7859f7a0fb6475d53b4fd55236ecf4f33183c1d719ee10683a6b689b463a823665a40b63735647c2930f3c4b1d8787d4199bfc2db8499e61"); + _ = try fmt.hexToBytes(&expected_ss, "b3db69cc0385b1ba716128b70bd4b93288f945f418cef51d122ca7a4de564a81"); + + const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM768-P256 test vector 4" { + var seed: [32]u8 = undefined; + var expected_ek: [1249]u8 = undefined; + var randomness: [128]u8 = undefined; + var expected_ct: [1153]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0404040404040404040404040404040404040404040404040404040404040404"); + _ = try fmt.hexToBytes(&expected_ek, "6afa82ec0b8e8449591cb9a11be36dc43146c18a6ad3f175897933d25944c3c643f50332f1cc4f6a9707a387b5c40661ec41b36d2bbc4507758387672fb4a1c1196eaa81b01be2864cc958a0642496f264b4042ec5f7b25a5220a8a9c9633081aef104ef9abd4da0af068a84e7b03f21e6b60212a02dc48ba7865877084a1b025443e38d60bb6fae8ba88ea4538d088bea758f6f9a5c26a9c44699ad43080d3fdcc2d910b16b297bb86436e3d5b79dc01230124867c1be64a9cab7aab9fdb47eadd15d00ed84ac9a37406a3665d7cbdd106d1e6a29a81c94e3c841fe9cb583004aa471ad2eb477623401e6959a04439bae06a07058cf2ed94bce1839e636a8c0b22f782483ce798e609bcd784605eadc0a06c7699b1b9ece550484124095a13371028101c95721c2c71b098b15f3998785b361924f89dba9f292b9b18cbe232cb76e41bb5b35cad976962fca2957eb8e06356c250525e8825dce66478fa587ab6b429bb287aaf21a58c900de0946ebc284873450c7e7a0e08c856dca2191195f73b3aecce1b1c1c29cb24a6c2fc3c14ca1495182645cf8486cb877d067440f118b80713784474bd0214f23fc09e2c8b5df357b3733c13545c9490378291646fbdb8403818f7d571a40ba7f5cea480fa00ba15373c60255e54384e96c455da13fd7dbcbc1e7a5e9d655b0145976e190780b55c9c86ca6c988d1230aabc8558ceca8d5cbb844ca8d95b30b64c02440522661c9b07c866e497b5a7daa2398a5a888a4244d90210105460fab31c6db3fd57941b869c24218b2ebd7ae67885e1fd691a3dc4388b872f4cab5fcd94067ea953d73acf1f4c752776357974b0ad7872ad603c30a174f963983739e5fa5304d1705c6791e9c90342683a3b176a2897ab9142190b3900d089c77ece41316b40611fc6bf7c81eb7b589d65524f9c6888fd7c53ba810b0c70766430638595dc3134ef5da09c668a804ea1e2f1469edba0d457acd8281828d02a915bcbc05949d2edc5c1c5856fa798e5cd3587472903c6cc2bb43b03229352587cde988ab60049b6f872a9aa82f25b5346fc56fe8686423b27e0f368a43d36a21602b4056022d25217df44a1fa330122152cd2a581ca05d3801bf9f0a31bf79b8a7394fb8c9bc1652cfea9c386ca7c703b5754c8243f7b0a36bc290e0733a17a94431d7b05e0b4298a8b287fb1ad3b32a57693a1e7867b0f3c483c0abdd2c05c81c26a60320d91207f204c2e8393a78e7572c8c296260351eb62940c394943c6a622a8710aa09a076b513dbbfddfc3105379da08b97a6fc68f2105088cb35f9683144ba24673513f0b6aaca32c0e77173d7387294a9b96a08a014ac88afaca949c2c3760b461dfc1ba5c01a956cac46a01dc7d9a992e1aa704aa15af525911857d46682b137a3719aaa71f7a8ba88afd6d43b127805f6c2cb55f88d6c590775577373ac87356a56b89341d0e8657737249bca66b0b4194a5c13dce045039164fe1530e38981f08c66ad2bb0531c3631a86f6cfa71571b777b2461601bc7a146c358955a5b44130d26b5c35322138133c083aba300a5def2c4f0d94d4267a2ad23420b768c77d8a1f0428536667d2df42127012291511a8c72738b82f0cff83b9315330886d611180d2383cf551afec4aa7515eb138a398eb44c0499863a8fd0da2530b7deefd5f1183646010555333a6cd0e6ad0d6bf919678252c49358a35322a458530b7c2b60f3b170d50a5892e06a9f82ee0e34d56c99312b"); + _ = try fmt.hexToBytes(&randomness, "6868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868"); + _ = try fmt.hexToBytes(&expected_ct, "cfe31862853164950123baa75549418c7a406cfb60003b825eb292f1ba1f25c3b5b044dce0b8b16cb254d69658d516cd3445e3f18bcde32c4f46b4ac25dca4c4573647ab7cefd7fcbb7c192d997194654aeac0f593eddc4464e7e125672fc7265f1664b32199cad45095359a4dd80e9637f0140504a7b1303fa69d121d2d214d5ea44e0046a120fef7d573016d8edf0c20749f05edccca4a30565df6e79015f04b03623d3aa25cdbaff330633470c0289689988c27fe49acc957d3be72c4bce05f1c80f3c2ad5b4e8a2714c1d1ea518f431f97f6d68eafb06ad7226a29a2b3a9e5403cdd923400a4303054876986f834848a4902659b288d5e3ef26a9ecb3f1be3630037d147301498bfe198b8116f244a12547ffe6a5006f748c0485fd72232e0c55df090011946c8b493f8aaf92de07396e901fb4dd8a4f291645267e7ec0335eaedeca28ab4c36328c73203dbca87e40dcf007bf8687dd4a776151e9d234f52442a33c7566b007f6537837cf752602624030615d0cb88238b91f578e0728b32734363944bbfce5884dc3c777e0b3f1ee4029298895e6b82f6f2307dfc267e27ca8d7d9b49b90786b7f39d906ca7b6527d5e31316fce0214418f95ab9504c98ba9e868754cb813014cbb196eac152861af719c7632710754cd2c72544c25b66d1d016f97a409ecd11577a358647e1726da16d0a0e2591eb3b7cac7fe47fbeef10c6eeb9289aa4154d42ea75b864e0a1215ae35dd0db3fbbef39ad399c3d04d0d4ad9f2ce442bc07dabd366307eefcb2ab483dbe80b3eb4fe966131a587ffb2e3664d31e2c520722dc1a1f5d27ed0e937c4c89963576cdca001361f11bd39e2e2b367943305fcddcbce6460a8bafeff8394beba9bb893f1a7abfd2e80bf10f0546e72a4051883e1f7edfe12ee1505d9503a83ddb2b998cb2475b88d280f1df688f472968f8c718f1f9fbd39fb3073312bc54c755210d0ef49f9f2bcf06a1099132a1e08d84b68543848e1538edd881620560e54d8d6f9a71ca2fd44f8fab9d094f1dce52f40c5aafe1f73e98a2a395f48d5da98fa5c95e4afaf84e7a138807f71eb64fcb3b5169e8bedae1dffd725ad6fba9fd50f39db9432cd5f379b680c09c5313ea73517f017ddcca33a405c0ca293d8c34714aec241b9a634ec65c8c0b56e59df8e668e74d2494bca14d8102dc0592dbf93c0ad5f9dc89ac24a7e981feca0461d3fce1eec98a4afbb0b7e6c46aec385c9c0fbc203264aa6aa71c67fff159ccbac01cdd85c28835a98e9b7d0cd4c4330a0a5334b5838c072df4bd7297251cbf85dd8306e1a8ec893f4b9558133e20e0c9598f054e2b0b77d4494c393c5dd0e83a6520243edc56200f1cd34b8f69d53e4a823a46852e61672ba69447ee49522978c64616ea42a0b0c6cc953c748a550dbabd74010cdb8fd19c8862473f826267c8cf41cfc36100665ebd766390d83c1b2f795cb6d3c38dcb8e98c6ec0cd5111108a079d57f9b16960d94a4f238a6d7a25b6253b0ae0088ce414406fa7d02004692681e4d957786be9fb7f064113526389dab6ff0a2dd6dde42c5e579bf996d6ea33dc52c8b15c92b6172be0781e33960066650088274ae577e6465e8fcfcae7"); + _ = try fmt.hexToBytes(&expected_ss, "794e2f99d9a890c338c24a018035f8f51db576faf0cde96cf777a81bdccce864"); + + const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM768-P256 test vector 5" { + var seed: [32]u8 = undefined; + var expected_ek: [1249]u8 = undefined; + var randomness: [128]u8 = undefined; + var expected_ct: [1153]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0505050505050505050505050505050505050505050505050505050505050505"); + _ = try fmt.hexToBytes(&expected_ek, "33393446a76c2c01b44da5696d8452b29ab7b91787765366bc1a15b149792427844ff68753f957187c102d0940c498b67332a7f9cbb82fd3bec9914e05a955035362dc7462071c19e225ac96c12fa34a2e86e0a84a0c633e044b3d93969705833a53a4257b7f4c1515ceaa8af9eb7f53ca7cb402a4aba11c9d3206f8209c436bc3ea0487c456a79e240fc4f5829e4977817aac9de9a0cf6cc28131be92c2a6ec672bca1a8b3758092f8b87a11565c0312e82939f8fd18024a71bb98a885c6ab99299cd43a6208d2198a45bcdbec590157375c16a456327bbd44011b635cd1f678277347aa5a765b7208acaa4316ea523f59a0671594e56121654f3581e882072396932da2e2ea02bf5489e546c452b7c6f60e8a4c6112f6ccc7e3a7a44748aa1308807a08c15d78a2e19a2750a916b8c46844b257c2663a8895b3df8c40960e6b912623c8a92c9fb435d20e6cda9fb456e55c1dd90a5f64a5ac2c6125046175751aa742971f1728328c353f4a7a08ff16b8f978ae41724494c436471505e2c17ba958ade7b2afbf9cc2665518949755fd5bb8b15ac9b80b78fa615a918c4a99549c37c6ad0017c51c3963e3408b11848ddd4afe96b67cd66c76e817d4c150de52a720505b9a4b09008243c0fb05ef004b9c2c223f9230dc57b1dd3d1873457842b47c59b9a6b39d7b61787b42a500c9f57114ec737bf7c45303b8a3fa78b3c649cfbd166c60c37dea89e2df71ce4c605fe45abcaf3a604f548ee5030fdf49ad4129b94516a22a8b728112bfd209e5a5b565e20a8dce97748a79063790bec93bc89103c32419bbadc1ffc679e48139a0c88563f170d165729e3d710365c404dfc87d7c31efd24785a9265e55c4a624315db4005019818a1e7c0367a70fbd16098e27a640b0f3dd9515d82be0637506ff171c6a31edf453b40a6162feb7c3543506bc1105ce196e46097db749b485808dcc3b4221470ac21880bc23c7ef4b315f40df40802f7324957b450032c3104f871250590a4c9a29687c70e02b46350781abc7c2b256c54bbc96eb20b891877c3a673f67c18197a0e3d657196d5673efb19ebf9b3e49691612834cb662d2828938b1ac1a45881b9e51c786c1a321814a8c396421b7f313cc2e4447e6e87971e1660d94aad5f13b26bf49fa499822b1959f48aa88dfa5101f463d5bbc8ca21b9d0857fd2e42d5c1c7a9192765a3013eef54ca9e43fa99abfd8053e9059650b964d6aea8c26c13adc0a6d91208f2dea0da4d57a3a8a6be9156a4065058cf965da10586b0945c30965bf8a436aaa115ab170071c3080f5c723c10d05963a162622438682fee1b619c2b10c207ad7d38ab1ea7eda0924d9ab6b443386af7b07fe26b8fc6911789666bc14619a381eba7966e0b4ab0e528083806f46456f97e59276d5a6119b766b1847d3a1ad3c4022cd0616bbc348d4e072f7d68272617b03bc9b25f569d0b11dab8c5a7ee11ee6c761ee684625322c6cdc815ee1c0acd29a8e1c826cf89f25944593336643a46483dcaca9e1bae9a196f692ac0532cd91113d5d974963a524bf708c44e198dd212dfcf69213a42e32e6b7c860148ed38c51002b83b0c4b979b52a753bf2c3381c027623b8a8251e60f55524b56b959a14d84637086a15567717dbda7aff9fd61d09589ac8c0044538bafea1200548046b8fe3681cfcb43a8a1b5df785f3b0cc713c0bbbffd9fd691df9acd2258c9671a14b4cee573e711cf6d8eb9ee01f9563dea7438d484b5d"); + _ = try fmt.hexToBytes(&randomness, "6969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969"); + _ = try fmt.hexToBytes(&expected_ct, "6dc476cbc91fa3895cfd69bda5799b95b7c0dc87e5c78dec9b367df58abf3e7852afb7b31caff856e5e4136a23a24f303c6100d9a0a6673164f6f44ea472f4614c2b42496d0049a27e02f1aa45ba04442a74b5e0035df3d8877266a4241e650a86ccdfb0c6cef22c62f376543bd5749353f808308eb74ed031e73c9f42ebdc8a484b30769a17906e39fe8fa65c0f88fcc3436c0bfe26a4995d82a41c6a99140a36d166cba6ad2dd065ac19cebadfd455c9fd5d15ab2facaf9f5c79bcd12d31ef88842403ebfef226f9a1de78d18d2a0a57a7808e5c4d9c7c510bd1813db60a2e0121e72c52edf77084222dbcd94a10cd4dc3b09080e8e5a8971761cd46ded65c78ac4d896d818a400ed832830570d492665dec3f8c11168eee66f33d0c13ce3062252f107a3777d1d91234f58598184ff827f6b2e73638fce0e4e51ef704e1d3f8dd5312191e36db31d82b2b76869d7eb03474ff616008158f3bf966a236cb3e8c52de4d010cc712abc23dff6f5ce00631fd3dbaceba030c2ec18fd0c39c9c60134a4dfca521dcd71cda1179d8ef08f06a42686c360c9272f15b4258e78514c8814ad70a1092d26557a45764041b8324bbcd69b5d2868a6fd96c871cf83413113c898e4bb983187fa4c1cbb73cd41d3d4f4db185047afdd241f1b7e7007c00b03aa8ab836cedad6127938f87861108047298d3d945b343c62e2fe852a0354ff31dadc1ed08a4ddab41d91c0262283b11fcbb1ddb4e9fddd7cc338e925cedfadf4e306f84863fd45a70f57df0384e1234220103b0f693144a5ecc9d99ab1d6f725740d1bb09c3a4b4ea614ac01bfb1288bbf14dcd572ecbb6c822fe541b04a0d6498b5a14727c2d543c9647277bd67822a5fabda4a98f23ef50ad12b321377fd4ee24b234b0f296049906aced9d08671de994956a2179394d37b585a31e405325ef880a108ec492c1c87da90adba72d8be4643ccf29431cae053f9cf5271f7e1c7a4de093ceb053351873d657737ebbef086640d417c6a05ae7fa9e30b1129213595290427032f26ebcd1546b9c9c1bcf01ff3d18fb1ebdbe0fee540f4b5318ba65877f457736d30c750e42e0e773aaa6e526bc6143ef631f6b3f8811a026374dc28e06c92acd09e1f3f97c12e512b778038563b67de0d6b34a48157f1b936abb8b9f3da3adb88b5f36d0dae48627cdc1a403810c816e32e0d1112594a4f372e9abe4e6721ff83f488421022189b82e1f7f27a33e4d11969522e91d19fbe1a3b9eb6eb3dbdc2b199db9e86e56bf695d0e6e79457226b2b3cefdd2ee3775dae268020392f0336c6fcb3928bdfdeac71246343c08f2be397daa1fb9c252653307d0f7bc24111ba8df6ab29923b4e7f3471be2923f46dccabb2063427f3d4e53baf6a9ecb88c12d9c233ff14f63ccfd76a8f046cc2d96733e72d56c835dbc9a1aa2a5bdee915ae7eb3e5dbbc8ba24df6e634bffb4364a81039b06a2c5cb31c9cd8985e7fe2985c3e0a8f1d52feb2bfc3549c3817989cc1746fcfe8938888e12274480491e5606800961dc7aea82d793c00281add579d5b6724edf7a5baae285fbc7aebfd9c9304f962b145573b14191fae24fe3a912920593fbb7cc14186b3374849b7"); + _ = try fmt.hexToBytes(&expected_ss, "6f1c317d16608f309e6b59a48be62722081f4e2de9e2742a6d0e94679ba856f7"); + + const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM768-P256 test vector 6" { + var seed: [32]u8 = undefined; + var expected_ek: [1249]u8 = undefined; + var randomness: [128]u8 = undefined; + var expected_ct: [1153]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0606060606060606060606060606060606060606060606060606060606060606"); + _ = try fmt.hexToBytes(&expected_ek, "c3f9a6305222862c2c89ec0dbd805c547b2120405ba8e994947b1d74eacc58277260ba837de29a0a2b84a7fc80589334fb2626c9f61c01c88d60b20b0728110f0840fc01a6187a506ab23d2b459fe0853c44f86a699533284577f7913b69898361bb67d3711680c6c25f2524c56022227477f28a194e90b4702901b0046ba798cd1b843192f3bc841c8f9748a1ab34b5336b12c58585fcd010bfd6c48e775e761525b260c7f6e646e8f17690aab51bab30c9763fc53b8547d0b56b0c82c458c61d84587d989785600b8e987a36423d388ca11d61765a01a4a79ca20a925908494eae0a3b6db1b08cbbb7a4ab5edcd96bd76725e928055b0c2883ebce0a59bc9ec282cf300ba6c5380d1b70f13b2dc6f616c76087a73a70daab7a6f97171ca5997bf40e87b95f33a53347ba6c7ba89bcec9041701226fda1243f4b1fa047740c7b753d630fe386f09e2a2f96559ae979ed9fa5a78d1310ef311f97cc3b6a738bee45b75e3a0cc714c81f72187b105a2120b9beaaac116bf9835c504713f2218b526f13d8a8c02c95aa0f2927c27e996e4564578e056227b07bbda8af0cc5d99f55eab9868b8eb4d1b14065843b229ea3e2a0a748d89c4c304198cd44cf77180bb8664f9aa1a9511527233cdb6826976d34276f62257ec382172bf97b310bdd34056ea61f2d74ce1cc9544b02263cc3d3133a308911556345a17c32acb470444f5536fd21f81cc3c968ab7e4db9cea564c55d3a601066375f6417691c0ee3b39228860f1bc00693293c4bca327176da52b7282495bafc2932d1154c03672f4db49bd40967ca41fb8f8696382a5208c5547640e5193459b3507f4817ae3707930508969a18b1d168e67b5939532160b50a538ec9074e733dfaa4af09755f831720cec8519f3bd74809539347b8786868fb2ab9ab742fe020c87930d37c45aa9b836c986ba01804a5de26974ac647d8b921484b748d9999447875fe2746ad1112fc57ea3999f5899374ce2536c58310033ccdabc75d63a641a5651bd08079a41c1e59894cb3a1c8bac7614e960581a1d191a3a386209b6e82efc92b655c51d91e11e8d39190863909a97cc6017af2c35500b860a21c9c48d48834eb561f58c683372968fd89be52a26995317855b3123acc2071683ca669d78c3cce5bb9c9f9429a643bbb1401d1d665dbf45ace6524cba3b0d33582105dc7c38165ff0959d325914f437a4008ca751878bb8287eeaf092021b1b3647bb4a9b562a7aae80625739f66b636c309a09376ac4cec6d76ce4629aef46ae488b4c6961069527594e0c22ec55226f47085bec5e0343cbfb421ffc838b56e9553e411ce39c811a1b4a53b051b404af3b58bf651376360c040a607f946c6357020ba1fa99daf19ad3f020431a98b1647040038383719ff9fc7d4cc75d6bcb6d4f00c834874b01b9a85e0c0f5c632734a3264d156c973c14cae920bf0917cccc924ba90fef187f9783119a7a268621c7f29bbb28da1cceab369609c64efc5e91a79451bc8100eabc85541d1f2435b96b532fa14c1cb76b99908c418118e2472c66511ab558aa06f03fd8fc15f10a2099dc4df1360d15910d2a7747d8abab40fa3d77b7470d8477cd63024aa40268f55139d37548223ed5823f136805752c0b5f7f23edfd90a89dd1f90ee344df04636cb97be2406e5515641b4c5ad186a0789e8ba48ab830d4f570cfd158fdd63d38de1e9252baeca9a76c4afc7768266428caae913d203f4709ef6dd7e67544a9"); + _ = try fmt.hexToBytes(&randomness, "6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a"); + _ = try fmt.hexToBytes(&expected_ct, "56a06e6443b53c24f647cb6798257899ea1c49cbfd4c4e3e54dd73a1139dc4df519067a5934733a34538f941cd9a2d9de371623247f1bbcb728d8cfd59b59d6995a2430ab14490b336ac502cd21dea47dc7c89fa026310ec05fbbe50179b45e4b68c507fd90fab06e36fb1c9b21c06115fe42beba15083385764cde8c527c3669507bcaded45f70a8cca789ad71e9087948e4f1d682c4a77ad306c25b1e6364f43fb51c0c5d72f455da72f46041f8fcb143f67c7517b425e24cd803032645cfeba77e0d8d2d0cfb57768b8fa3238c10ebb99471710973bf9d22fea51471354e53f153dfbac695a6f8ccb10524a0453e804bb013b450f38007fe21ce898c052a132ea74c9e69512ca4c18c32ae37884df520d12721b95acb515067f3516ced73c930786d6924cc7dcc08b50a3abef4e0df82aa0b9c7bc199cb2dcbc7cbaa38ffbeea60e41ae20e8400730132f3627e1f62fc784f222213c2c479c4ed1f2159f724eddff87e6a4b5b3445e189590de4bb62bf66e930550144b44e23d6c045d779ace9f94c0a688f729a0b94821b669b5ec49652e55a8c19cfcb4d389066bb3aa4d9d7195d30c496ec4250138ea1c335d6181b25793ff5d0feaf91b7d27c826ecda49a9b9c8ff880091963a2ccbdb5cb45eaafbfc8b93e753bf323e2f76b0a61af96997d97f429db90898fbcc2dddcebf04d0e2a3d688fa56655b41b0a628e4164a31308799ea58984d44739d9720dcfdf4bcf2808217408c433d263787405d11dce0854fbafe59f58d39a2995b991187ff86d3906e1e27812d5acd2a8d11b95ea20c7bf1e8ca9146cd9bdd10f899e3289bb1838191feab937a6749c965c01b41e6febb62b515efc416b9470214d78d4a47bde46b0c8a5f8c4672e8d95dff71b9d7bcd2f94c1d115461c5a847baa8ee4a8a67dedef4ea40403326710c23394b7b38e193b01670669f2c6e06c7963da8debe103a33b49541fd5e0bc77b916dae2244d36bfc3d53f0f1ba51eec5a18c2f258edefa2946f799b88e17ea475e8bda8cffa3531ed246820882e32f7ae0425b129a8b0d20e6205d1a7f85bd8efd9fbc7dab57eb45d187a25d29b71d69254a36a5125b6af9db41caf369183987e0f7077253969d9d1c0887a35fd2ea34eea81fc930b1a1aa11db1e996a11c49c39f570d0e3cfb3ef5811a678dc4451c5cf64898ae3b53e417c69f09438c997fbb453b9d88a1cb603e2016c1ee79a36f2e9df75f65eafa3db33f0f377c71e72f77af85a0114306e1b21921d532b6d140e3a2c5a479f33c1582386c70c75e84765735b610559e8aac6149ad174213f2a1595476b29075b71a025f05fec67fed05e5f193f2b71e0352755ff4aa61bc63f02405760333516766906158a2cf812fdd5d11eed2ca3e440458ae1bf76cb642db5772d672d932a336cd838339d9df2dc2459a15c173b9e803a53112a081e7c2c945786b24e6d226aefbe7cb184a23dd504813975e25067f33bc90e13ecd4857473e0bb0fa33b3f5f0255eb51da214717511378927c0d04d1bd4143e815d832d69af2ab208a19243a0371c1c70ad3821863aa851b5447c53c391417dcf8e0506aab617792f24c80e4122f99ebb25341898e30d8dbda4def"); + _ = try fmt.hexToBytes(&expected_ss, "e324b3ae9780cc6d0a54aa4262db9c9c5948ebd45df2f3d10eb22ee23bdaddea"); + + const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM768-P256 test vector 7" { + var seed: [32]u8 = undefined; + var expected_ek: [1249]u8 = undefined; + var randomness: [128]u8 = undefined; + var expected_ct: [1153]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0707070707070707070707070707070707070707070707070707070707070707"); + _ = try fmt.hexToBytes(&expected_ek, "0e12760b95266a50a52bc6ba3df697c1261d3ba510987a299a83cc0b9134c2ea4ddc47889b72c6dea65b49e066b1a2822f269e8ea904a667cfe6f7035aa83cd9c041efc38d23053ea6d754c550cd5d1936d4e74ea047c4dcf757de9550972c82abcbad83c32838c18451240c0907a573451dc746bc491c143d14837af83c4f4b1f5aaa59bd5a2b03c144ba6ccb445bce2d384ab40823271342128a2b7eb68624eba59b3b2b57d9a4ac7b630d063400a275ad71b6b08a8cfe93a64d368cef666a4d208b8f39c442400c1a7c4677658576417b5b026d99cb80e01428be00c720e220a2705936a62d6e737900bd8c3d0b464ed7650dd7c84c250dd73c7536abbb4013809927ccffa5391bb254294c7be0596dd29aa37445957b2aa88dfc54447894773a34e8e87b05520c9c2ab4dfd69cdd9a52c7e9352a3ab94c07a26d468f10b2632a6a524e06234fbb2008f17cee6a59efc51b4c483fa5264c9fb325e9d7b9b66c6aae91ba9f9a29743968c5533a3750bb9554223b60c8b964cfa7346948cac1000d840488c3d211b4e7d463ddb15551862f01d77e87b60899e25164cccc814caa5c0555f5413ffbdcb5101458a26061560463ab33cc2174c61f5861986b55d6206612f386c996561b51b63a11be965a1fae45b251476e96c3864925646b6246935bbfa9f4bb39437195c6b98cf81a071a70f26b0ea61628fdbc91ed299b6326ce7f220aab6965be645ff7c51248e456adb343f10990243401d8e05ebc48b58d2a77b21341ef513e66157b83596f1f447695e8c82279922e15987ab14259157ee6e07b5ee28dc41c68dbc14c39131fc7a4ccf6420f65479701413d0eab484bd55dc1669e4e3a3eebcb118c899b2cca6cb2dbacf6f5a717ab0bbaf02141299d32c88426aa4866173cc12313f2c52624005e6fe176ac02bf45a9964659020bd03b9ddb8a99322b0452a2eddc6ea752473f1c1c9ab051dc1973e81b1e8d746406148a8621575f7c71cd2879350a2970740156c69c9ff4cfe97a3ff0a90f16e90336f6825bdb8ba0a3ccb2f181d26cc88605493b442a9d5a9f788895b720516c865d575c75276c937e2252a486c90e64b1c115060dacaccc3372d1475c3381098275bda23a52083c6e671825e57b40606226247432213988a7672d80ca32a2356e161b5a3d5a218cf0c6788c62b786003154c90312001e73bcfdd3312573504a0c402666620b31606883580ea09f690c0cdd948520b19bab2b30fda60dd903c8b4f01a83238ebda1636c911895480a8e5430da58462455488b71a735ca62c1928722d57c3d86ce66760433c15357eba556db67adb16f8a02cd995c2525d21b49a06020daaaeaea50d332952f399bdc859574c9c9c6056765d1c257e5a655c9a6c619167963afc850027a00730d60b33e2b897e71b56466be0fc98a1c314b67b3bae780a622c58eb05570024c989b286763ba420ef234477c2dd8bc86b9c9adfed5a8c7b948b6735bad758c04f08025eb01d217ab9407881878466904b2e4965b2275155fd1b8000c7b2983a9e8f87243551dc31b884867b3e9418c1d5196f83b2e7edca55cb21dcee430969366fd02a85debbd759763010cb918b13460c33bda4b43c2aaec2b4d19800eb45b65c915f8b969eff9e9e356faea1c9cf69659599b22f50436ea13cf2f1f0ec871c3a10ac0b36d877f200bfb728d9f3f8f5f014f211938c615f1f10e5000eb9d2243df6e9c8da3aa6f2f41be8f46294d2e49c4b78409101c"); + _ = try fmt.hexToBytes(&randomness, "6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"); + _ = try fmt.hexToBytes(&expected_ct, "892f7a7985caf0c231b2b35e3bc7de3e5a4739b72d3f9be342e326c0173d55a5089ebe9826c834792a3236800eecc2612b4d92ecfdbed013a6bfcd4d1ffe5c4150e7257a9e7c0b2e0cbee757fc86b5debe03aaf796c76a5825cc78667189e0e37f4a1c3dda770eb8e6b978c89181f4871be9a295832334dc3a7f2b953f7df43f321137a9ad5b27e344678a79e386e402236124753e6dfcba0dd0dd97017461c2fe039c72e9d0073676f0749d8cc9bcd6ae0fa6f14db0b52575845c5b59b82aeae93c8fa1bcec6edd081517d6f2d3ed91575b2dd7b5893f3dd755d842bcf3e8d14afc5c236ec66236b33ba875953633eaa23afe2974d00179b72d117d9b8dee5110036f418baa0be052ec09d70fa36c943bb65050468bdfd63435f2edd7962cc98a0fc6b1d2a2c31a3581c31741790e4f7acb162a7146f399605a08cc99b48a96caccc3118ad9fbfbba58f29a121ccc604e9c0987f2250be2072189d8b01d594e946f0e5bb1b4e045ac5e5608736472386584f455be6e74b9cb31d6ffce008ce283b3f834c56f64ef829dd492eb70f6815c45128c66e77324bb03f71baf57bf0e200b5a59bfb1628e2bf209e8d3d39a2fdcc9c3cc7655224efa1efa86f550e72c11b5ebaa0b375e11d77d0a4cfe4f1f5eb048f0cff1c2882fbe01d14fcd97cb2ed5a40aa97c125f81c8c91164cbe8477058ff9e380604da9c2ac1b061853c2e4e979811bebb99948911dab9cb03d7c4975461d8e723bc415a3912fe1108de37b32b49174b722022c80dfad2881ad1db9f1d6d06090cb1421d3798fab2df0f4408c11d07be121ba66b406a6bcd892cd499e35e1c2c20c15c87ee0e79612cbdd04576955bf61153eee2798c26e4d6d3050f3de5f6771add0495459e5300bb4e139839bf6a4206d7865c159d1ba9bd566e73d9a085007681d3307040c58616f369c6f2baa54fd59b4e27b806513ff678c2c6bdcd423e67047460a3a39cb04ead7b095317f0993f3ed75b5fc8b74c458a3bd6347c6a82640f4041f0168690f8f68f2cfaa4205969fb4dc9ad42d26b3fc2ba5bb08b322d0203118666b665e2041fbef0ee957f73f60fec892a65316d3f733112ef2a19c79c2595ad99a4d0c98cd148326ee8f2f7b79a161333302268c4270a96d5d67e3503b688a332f26543ce54c3dc3817ddd616624ef715a41f1a80f4510fc769892196ac3f4c62dd0391d4c5f215ab447299c7bbd0ea1af7d621ad9d662abd35ef65f900a40b36f32f0352c97a90e76217c317f1890de7703d6009a218e75037b68c6d34f0f8ca6bef01af7894883493da5c47d0fa116af94f948747c969b9779baeb8b279916b6ad0eea9ffc4afc1bd907673203413b609b47ee0fdce780e82a6987d63887c285da97609736ced5fad8faeef141d8d0344d70ab0795a6668fae59aa65d411107631415112288c7e3284e26b5dcdabf6960821bb74c79fbc6fa73da77a4220943e86cdaf4a73e1c5bd918eacd53f6e085a694b9337385b409bb1f8604ab2b9bbd390f69cdf50ec2049f2e279a3aec28262115bb6dfa3236bd67d6324c60df93974d6e02c4633cbfb821200ce8b43977992a98e1c712fd8187eaf9542db5f05267f6fcc09dc523c960"); + _ = try fmt.hexToBytes(&expected_ss, "5f8deab6c11f05ee208ba968d28917f8219ba2c0c30d41651c3382f4d56483c6"); + + const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM768-P256 test vector 8" { + var seed: [32]u8 = undefined; + var expected_ek: [1249]u8 = undefined; + var randomness: [128]u8 = undefined; + var expected_ct: [1153]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0808080808080808080808080808080808080808080808080808080808080808"); + _ = try fmt.hexToBytes(&expected_ek, "003180282264d14206367c682c2a282a58c11467550795801e36393cc16e49f565bac995ab504448d4840b85526e836ca6d641f151bd50897e1f9a5f6c718a61f97f866b364a217c87e52cd28765ab18bf3c931a35150d1c0c32c6b863872a23373057bec82e671986fad2cb15a06a9687a0ce923754138b4c54ba93c082c147cdf186c0d5746cb6d54532a2afaaa701220342f6303ea7b66d9942460722298e3bc2f0a612a22a986946737d057fbf3ace20cba6f97503fe03caa5c3974e8aaaa3c7ba62bc70d1547ea9336ad15315cd8a2919b7683b568aebe54b385612f8829399d83aa3c2308c49a73379481a690afba636e14c7e6f31678c022b552b19a6b90b252a7122575ba041c2daba8db6ab6cb9d13b5bb391ef0b48fd578e67cab1d4d01cf4b492f136c9c4807b4a2479f35b255f234436d71a123b47384c1b6909b0d8c55575615a314178675cbc94e746a415bbdc912474042a93d776a89913a2102efa9377b85b0149075eaae72c6aac3d91c74f71d38c063963d3fa0c4da13f5202931f06a4515b08e22260309b882252c972ea2e06160e1537bb38eb97e19909e58a3f3aa007daba597d08ae46767beb517fab0124bb39ba6eabaf131b9611a9bbb26c1c52556030599be5382b99c79f8d4356f3dc35b08678a2a1b24b3cbb6da29f03a1bcf1bacc87a642d676abe5826e3836aecc878d2d67580e39b9c55b7ac1e6b8a4ca6ec2e8934412258c0ab6708135fd030cdb34429ee0a19c782623f081c0564b7dc0bd8c35b831672a8413754127a45ac7572185185f444f017640b8a4c0819927866332c45374c6b25b88416d4094081e832f26d44f8cdb04bde72f17e38986a6a693604c637cb75805092cfa7b2921665e0803d182600e001b6f023cc39396c20018cfdbc85ac8bbe5cb6fc094bc55c854e28aa3ceabc7f4e1ba13277628a1304d6c4527533cf9d2b6d43a1f6c71c71586121c3254315a6cdc02b9afa12184e51d3db071cc671864f2ac51fc653a1b628173061068924f890b18acc74c4524240696bee4c099552ec02354bf272c94b541b5f4495e73c181827120872cb4a36388966a081010b80a9cf37c4715556f9d0c3a5f41c587a7cead9ab40e366b53612c745632b0146368e0a52f0b078eb20a6006cbf5591e393c19ecfb8e5435a73cc0c5ce3a008f5053df1647293271e1366867232cdbb8c58066c105701735f911db1ca2c1b07737467805e304d243c733a77ce448b639c295392b1458b4a1a8474ca2968e0c78917a2b255fc247fe493bd0d9bec244351890a895e470d298052750166b75a98a855549c386b140bc24326b044a469dfa660fe51a928271d011cd54682433f5583c5205898c216cf80cc5456bce0accf8862800cd36661332261297ee9854d230b432d39c5ea6672634a294c929e091329a37bb5f348f30f482699a88deba93d58745f2b013a993816e4c1b90d28118d9cafe2a48bd024be328490b703177b50ed619a9b293944f30bd62119eb15486a6c3659eb0aa97e1832d82723627670c30b546337428a7364ec49539709dad61943a545088c754e27c857910713376b859e392d0554a09c04d29aa8adb8754a491059903221d689fbaee7d0a714487053a812bf22bd20bcc6b3aba85396dac337ad43e5494047412cf9d1e0099d80dedf5f435390786c8a9c327e76394d42037808c7f2c12253e45cbff4a9f544b175d24b7655a9d946ab533b0fa10f5108b17c30772cf4172"); + _ = try fmt.hexToBytes(&randomness, "6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c"); + _ = try fmt.hexToBytes(&expected_ct, "fefebc6f6f4dab06bd9b8d0a3a688b06e4b3ce999cff7eb763d80f6d288d9d8c58d240d8d217064c9848a1508726829e177a02b99ac33ac76e50a82d31e9f952098c4731a0fc35c9da8e9c87af7306ee7171e3aee3a3d2d046bccc1594a9686a7749b906346a7c863d8dd34acced601a3953a05e8ceabf34797b4606eff63e66fbdeccaf981c13660a8b8de661c5b753f73c7e2cbc733379c4d9c36b93b756f5becb1ed569d6db0b2d2b1102e6064cc4311da3030c3f1a1126df69fcd2c5c3084ee1cc75761e5358ac39c4ebd472caf4e555f8da38dba8ef862c92eacddec9c270b5c71274c15fc38674bebabdc7cae2444dec1e7977679578f051fe3ee9d7a188565d5fce8fbcb842b28a4d38d77eb37dac58099664fd1b8069ceef1e06ba95a39bf48f7098a9bff84f6f2df86643db53455be4bfa4848d93caa1fc1398ac240d186bb3334bb5381c9d089ae3c8637deedeaa576e6b92cc7b66bd3a31f3c956b4aeb4eb688b249cf9b57a56d3656b5374f806b02875562ea15fcb619395ec913026dbe5a6d488cf907745cc65dbc9274ccb5e2461b9e923862a67744c8b8ff19dda1068fe408859f89b5b8550ed08956ce2b5c9a617e7ef6022772a58b63bbdbf5eb057c4bdf30083bc5de8a22628fd845bc6ebcfe27277d1d7f57ceeb7beb07a20ca446fc65a372929920792d2c46afe34be5a052ab43db9e0b3c2d024cb720e42bd20db4a53e5bb32a1356989b1d5850611918549e9f57001c9488b8eb12a36e85595ca45934fea1d601b42c67078a4fbe701496e443b49fc8822fad0c8fc3a25b3910a5158b380aa678cda329e2cedaec1c4a32e51b4baf7091efa5edd6ae2aec450e15cfec1ced9a1d158c9f8f19e21155e4163eaecf7f01d16ba495fde48f39645a44d3733ea265cff5d4f2129e3c83a6ca33a6223f855a91ad49776d64ecfae6878668efeeac930ab6fe9183370c61727b4049a1dff8579947bf16ad1c0e210524c4f5ae7548f3d3e532e694abed9303ff260178505542141ca980de12090eec01da3399e8e454934bb15759d348404d647bb2a409b9d8a956021bdb85ddba1978593aa56d961ede3a707e7b0bb6f325229ce754c702d9ebc35a2663c0ceec6b3d04ebd91a63854736ef4b601495c26aa4927b9ccbae3adc808b32571ff32288d46c2967a96b53e756027d5eafed7dc8d7d5337f98309ffd1a300eba2c02221a3f100b68cb066861fbcb39252ac446c3ed3a9639708fd866e9fc0bfe4a7aec198696aa13979287dcf1fdcd143a44a78cc6006beba2e1ae70e8e857764d233e54830473fbbd2b173a34c16c2032d004fe19d35d8a5277824260f32ae501e24592916ea46ec14a9bc301fd0c900e33a1b24cd153a25afaa34ee26cbc9215fc6fa18972714aab79b72939b9f4d3190b9bd64282c0e630b6d8c6755d291e33dc3cf6b6a740b565b1cc292f2cef3b8cc6a6f13a3c7b06525e4e7897f63c82502f7fd77bae5a80a63c7436fdc8387787ee34a000ac1512c5bb3820dc6a9b49e048ae622962818294b8210f6b88c29739ef9e92b3953c7e073ae38dde178f60320fc974a311b78d6820593ce11cff1ef147dca0d291186a45d823ee52d4faeb861"); + _ = try fmt.hexToBytes(&expected_ss, "f9d4fe89be29e5438f8ed2ee8d368c365e550b6336c55a4d91f3d96dafb3191a"); + + const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM768-P256 test vector 9" { + var seed: [32]u8 = undefined; + var expected_ek: [1249]u8 = undefined; + var randomness: [128]u8 = undefined; + var expected_ct: [1153]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0909090909090909090909090909090909090909090909090909090909090909"); + _ = try fmt.hexToBytes(&expected_ek, "460393d6222435d92a68eb6b2384ae414ba04199ac14e561f6711facf87180a4af6156a5cf589c8ec7983054764231646f07c57ae4247de37bb73758a60b4d3334985238563005ab337c6075b81416c241fce764505acd0fe7b0fbb859e4172390e670089414107549ed298bca658a229079866b8b960a7c7fe46cc47a1773010f106b6f5cc9c2f906465851a7716649b6a67ff073807cfc7be4cac44cd1af6a372cb04161d4d39861780c6f62051dfcc39c143dcbe49bbf5b58a8769b927173e4c7096c91310a91484cc80c55217b76124d0db0965f84bef016040cf19947d61e05a14f322bbd918392f5083be540a122a3b1d7bc7c49a868f6384dd5259850d427166752bf286a3ae729e3a5a5e76209de5b9c0783a4c70504a338af3d178ebd114b7ef700cc17919b258682d21a1244a002fbca209a80cb2a94e4476aaeb7cd002929ef999095c893624667ae2bc8712b20e35815599196de478f674b50e28313d7695ce2ba3dc02594171a1ba7a095a4351a0f3306f51b4c09ccafea587693a9519f4b4976260445421a865a400a63b0a03a8d9a35ce3335bec1912460e1a5b4685f8fb039a5cb444ca21f87c522c7e6554f29007c0562e5f02eee849f29d39bc15b58ff58b252581adbb17a42f2357ce62746b1347a4123d02aa5c3974eed863eb4f309c5b265d038aa6f994e8de94da384321fc65bda704a15216451465f9d44b7e8a9b7e6d356e8a399e7eb39d0b46d85ec0cc93c56a6d570c9a8865aa6c74f358ff1c03b80042567796c41f418747126bb4ac29d738372fca1a9646ad6e7901581c6845c91c3989058a82bd80117e7c73bd2da15cff522fbf599fa6840317608e410b52b4c477827877ff612cf89cf6c87c8a72b175b6c8627e0a10b937cc672c1af54b64328c733c22585b88c54d30c1a22bfb6a2559b178db7a0aab6001ddac9250416ae5c11c0a5a26a09d38518b28f8e3a7f2eb51e0d679f1d928b77e103f4fa6218f68a1de0af5ea0bd1a26bb624879ab47a28e9c40042b29cbd678f7ab65353807d41993bfe11607313430e5aa8c27b9af3a5f10531aecb1a1c3710f2b992c99b604f7b2a3269a49091a3a56dc8b78487ad9ac24e36c97d351855ee1715083a3e9c32f52f735a76cb008714fa83bc70e4caab72c485ac8431cc97cfba727fcc0af9c542d7d9199bc4b50a9ba83db77c7dc206fda0547e2795a8dc36fd1b33d2ddab089d95eb16b15da94a74ed8b7e8daadf8180721e0a1e31002497c83ce1747fbe78cac291ffd967f23f47a8a30485aa352cfd4c6907cb8b201bc3b9281eb51985e11cbb4b5250ef7ca13c70674f395c52b177541b57b3aac77e382d5bc6e0c32aade73c74a163c0f43a59c616d76393f39166de8318fef1b2c47075c19885ecea7b4acc674d1c72a2e4ca70d28325f12cc33ac19aa9c5e5ab31c7ac6933c1a0a79065fa1e0237cd90a13c7b759980262378d4a17b85c184f84761e071a973784b1c30a9358b76a7af10727f36960f21c6e078d33fb528373a436fb237f87317b81c04926245982aea0b39c24a67effe65a91b211ad7334f8e4858a3b7d0ef21b3e443c0cb64e089408006b103f3841cab70b046b98e2c8aed94ad683208e265424b077389c2ac6571f216fac52e35cd280e51aaf6632816204c82a04f09e4fda885db34fcc3be3ff41f95700e4593bf825f93ab30469733d373e450b125db222ab72f2ade96db31fee093fcf254511547ac1ca7e926778f133"); + _ = try fmt.hexToBytes(&randomness, "6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d"); + _ = try fmt.hexToBytes(&expected_ct, "a857a7425c6077dafaef133c62869e523a4b41110cededea6ee66b9a6bba634d92cb41d5fbef2ccd6f5f057951fe1b44e224cd2314c9ffcdf4c358979d6d065f1f12a51033640c07965e6d4342afd7b57d528786b398e13b6eca581b96fe77778d73bfa2422e43093f7c96434103b18cbdf0aa6549da8e169b66f42921b89ac8267de35446008948d6026a0bcbe61357e97c7fe7a95337dfa3177ca6167c3a2af8dc38e3d708665824acf97d6d7b152bff781451c587a282adce031b3efa26b6d8bf4b49733c03dcc4300076049e278d3cd872174bc374d77038c75203ba45d30bd4110b62346c3f0bb1d8563d0e2d58cac839fa693ca96a56eeab1aa4d26cc95e013674eec4f8f08095059f081a0d4dfc0735653f3097f1a37da334007082ba6619844547e0d3296669eeceb02ecbf0c5c5a88d5d1c432398361529e0d91a628e568cd9a18cb3e8ca41315ccbd8ff9cbbc0677150f2e06274ec9e2733f3111cd4f1b900c7a3a80b517a7d6917fd0753f59e8bf03267e3a43d60e1857d4922cd0f14b6d28602792dbfe2b4488e807023ff4a8b65f75fe1a0826d5ff490bac7be071b9545f6e7ee758caf460e7e92e52eb83dcafb5bedeecf44a5f5ef23690bd83aa5ed2ce0420c697dfe4eaeff5d64be78fd3d9c96f66fcfbe015d8a1e75e93eed734c267fa515220e9937fdf8df271f69c8e3d6dec76152404d862434211bd1e4b53cb9951c48b796fbf4287d3386c65217b41f2c414daada2023c43c08f8b6edbecc7f750968c4f16c3c983a95d73c25d3cd4aac5bd5941fa376e1934436acecf9bb9bd4409d0944d393d852aa15d6363bbd83cc24b1ea841e00b99dbe9f7b9fc2a415063865b43ecc9db0a95336820d40ec4d7325d5066eeb2a144ed3c27f5072c9a2e596d395bd069fdb8871521a08d0e9c1810467a271b4067a54d9d81eca8f26d18acb41a7de599aab1f79ddd0128c07e44cf2ccef72368cb4474db47ef43917940a80d05aea5e8c933a0ef8a8516a6dc2a50df273288d97a9788629f001e487434e6a4192466e63f0e185810665267a021896967d833c1f108645a5d17334d5dde8fd617c786665d7df9762b8ec0676af697dca63e62b597aa2cf89c558accc872ce9a1277f88c5ac160b2d13a27de6b4027353adc3bf596d3d6527532e66225fa53e2546f6ceb240435bb93d10e4677208e990f622276d04ab8f2e4ce2e5180a436d33adbf29c2cef8704a41074ed16c164ffcd1c8f09a2f752c098caab09da3db75d84ca510542c3adea1757a553bf53657f03feec803950747c8ddceeb31bd658072f01b7972df731af5ff53bf8a8361cc918c6a00693134fe6e385cc70484d2e3e6d365c14fbe6e2332eaf86b7afb8da619dd4c13e86f62ed63da3b99895d6ee47b440e16a3615f341d4be41239336b020174819681732503f275bf8bc494c251e5448ff32bffb3fe0787482b796c37fd8d25a28ea78620046b192ce46fa4c798c0feed1819614413326eb373e622834afeaff81aff308caaf83504d31b9898e848b396bc86cc55c519f1a01125995311ba37d96aa59ff464baf8885f3bdd10b1c92f0b286990048d58105a7ab5ec1755763ecb4d20fd1817d6b2fd"); + _ = try fmt.hexToBytes(&expected_ss, "a0071e94b4d0275ed91dfe4f3fe87dd4a534269c7a5991fdc27ac31933fad24c"); + + const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM1024-P384 test vector 0" { + var seed: [32]u8 = undefined; + var expected_ek: [1665]u8 = undefined; + var randomness: [80]u8 = undefined; + var expected_ct: [1665]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0000000000000000000000000000000000000000000000000000000000000000"); + _ = try fmt.hexToBytes(&expected_ek, "a10bc8b554cd51980cdbbccc3041420fd320fe8b74c7a84278c63c17070dc231b61ab269b9d677d920261186654b4571f51797d5c342b8070bc6c92bca16adecc631e4e94c7508b111730c749c73e2d6a6f97155cb269ccc06a71a21bef3d269463c935048a7f4636c7b320073709023f7b04d0530571a9a6f718280870bb63875d3f599bc229b95869cd5bb5d26640856d40b828198fdf2c099998ffdf772e462336c521cd326b5e4997bd95c135c57bd02c7afa80a2923d510951778ee5125b2aa18f90445453b85789224725b259279698ac9426c882baabc38d4fb3a3f6831180918b9825e0e418154d78aebab5e7e7066e69b2567476bf1177fe079a38298be6f01b098c33851ab25312b52e32a5750c2b73d293c0b810473b310aaf062f19914c7377b2e90388f575bf5e6853453b95a74aa18d62d4ae37e6996a48ab5217488a92d7b01e315c50b68204143792afc4f8367c0ce065ab32014bdb5515fe0594608aad1218994724afaaaa2df0355f46666b6e02a387b6d3da4713edb610bb048c3a2078b800e9ea483f2009c96d24c71b2cbc8e1200c0277383c5c27895e298c3607701ce58702a91903274a041408234cb0021ef2b1c5131419b444dc84b89d147d1fe43c43f676d906735d9ca2a59c2232d97fd4aa1ae2bb3d1b170ca553cb2574954fdc6689fac623cbaa31982d82424d5a564fef7a8ba51b44df15053b2b45bec4aa1ed49929123daf754175c5938258c608b24d062042ab4bbee5e553a5ea627521738ae5ab2e06bd98b020787b2f5fa51eb4c46c2bf90e55a49560340667f88ac41432b7f551dfd98c037c79f79b41b985a8b1f51345550cd816714362040778c43e378a288394bd028c8c31b5a904bc4a5648a596035cb38f0e276e12c9a96f8425056b05a136642dd2cb75463036485ba1a50539e420e1e31dfac529cad6c68ec06746749473e050a4ac92b7199beceb239b6c12c8e716b66607aeca64a5850b01f99d0b176a7759781ed77cb1ba40d17ac5c6cb06c942c002c2cf6efcb121f10ad2a45ff781426e7104cbdca73b81865ab22b00ba834355ae485a262f354248932c2be178369a3dd7e2428fdc379346ab2b754c43db657460cb09c5c48b5810cb7a5c6156cf87440c9e36a4869a8ac458b382fc178915a9ce1bcdda7c48807c207e656ffb80bf33e32bc8c7b20ef60572612ceac99ad1c56ce5a764b29b74c17a5b510b1afcb18a1afc35c12ac213725325f9b7a2eb338fe4c0080c31a58a995db7027d900e78544887f90ada467d0e383c119c5399310bc6735874e8804ff6c2bae57f2c3357cb627033c12a5924b20ce5abf113172bd2b77086cac543811793bba71734c9f005ac2656460bc30a442b388725758a623e37ba6e293abfb84f344229f373c214ca776a7c05adc465fed93b9cf77f0022ab71f1adde369dd8f420a58c057c14cc18dc47da7c12b086473eab419652967001c4e42a381c8ba539a875d21a9945133bab9bc1e53a600de77cbfb2aeab6b19ced4c6eaa8998ee6a1577255f7132d80a32d6c0c6ec44c9c4b28699a645bb0bc958e00275077925309519b0824c7000dfa61912ec049063a067d00b059053e508a5bfee63473869c8a8510af898cd7572854f5c38af96f5f97a7372632ea7bb4b6fb831c612af71191ff9806b379bcd43c6059b7b1f953741444af713c155d962722b947aa23a32a89b356a6a7508aad63968c1dea78ff18aac27a89aa7b42b0d7481dd3cc649421e51397782218ac5441760ba51a0328d66b436fec32d7aa4d68e0cad1bc14f7241c903480f809983fc2c30d93138cf63b59bc737ac08192893d039187a811bef3d3209eb7b8d1e05b5b251cef760a210b2732867ab32049ba3c354e3858aee7b71df792924730d8e842e484122b50677b0a306e61cf21b62091da18b937192936a09e5a418cf78b666157dd477af1c36a12320129522840e370941157808782a5335b0ac10d70e1beafd401074b84b9826cc58aad217bae0f419b2da896133272d8f22c6f420fcc738fccc1082fc93c7df0994c6bcf2cc8a29037b6bb2b4bcef4b0ee8caf8506bc5ecba082a56806c1cede0b944338a69a668254c1150ae05030e256b2b67661ba027d97576da613ac8c7c29051f1240b96b0c127e264d5e1dbbfe9561a567d5c9103673b446b3ccea6c5f7f34f09348a5d4a58b0498871dc940ee97b50c0336f9a60c3299f99560ac70657a27befa702265ce590583e04a28326092d3dea2118dd1df5e81d7d3014ec4b5ce67dcb45ef001769dd5d5ada76934d38d740924712bfae672169d8f8744c151346d285fbb653f83aa0f"); + _ = try fmt.hexToBytes(&randomness, "6464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464"); + _ = try fmt.hexToBytes(&expected_ct, "dc63d18bb9715fb6e3ba71cb439fcd3377a75305cc9b144e6758bf5794a272e6b4a0da33234c0ac1bb5b4e60e4c82eb1fb780d59e4e4616641a0595ba031e3ae69d971dcd5fff14e21731a8e1a221f46c7820d214630b707fa1b0de3a484698f3d49e0a75f1212b8c42d330dd909f15eac0402f19ee77fba9447e1c44304b0d8c371c17c5549fdbdec1e0a2e7be9f577d7a4b5b2618d9ba67ab95a0297cd5c5a13c89cc5a57cbd9a8ae38d66455c9a3d2bc55b498775fee2f6dc224d376d5f526a8354c8ed724f60337e900b85627972383e1fd987d407a8834005814a4fdc94c947e5f3471459288cfb127952b3208f10c914200bbaac5fcebd2bc9e2848492bab17b9288ca8b81d1c2ac9522dcc0b6d5f51e10f3afbb5d65fbf919edef6323c4e92c6b0690c10db25a9182de9e919ea1b3e65ae6150635d5180ebd7d23a2264828bc3ee1fd34dba1924ad0db30c747e05baa9148f1a032769c685e04665fd802a79c4624f69a9198a426eac1b217d903cdacf8844e73365f3a219a700dda27edf6bea33602617c5fd105b301b884bfaaa1163b791ec09f82523fef65c87b75ed063ceb127729b82c8712e1f41b547d095f55ee71f3f8b47a306cb5d9bdd817854c74a42eebf934a1136dea3fbc546ad8ce51b3171913722f08b0261d197590342bfe4108dcb08c62a98610cbfb8d3b2831f56dcac2220e29a5811f38f0824f21a6cbebc64fd89a09b110dffbe03799ffc74fe565c80dbf6a66acd7bfd14cb90acba03405a7982d4c1c68caa75f8b72e4dd6401d7dce4db4f6b820a7886a604b66b4e5b9eea5e5eddc2bca458a25977bd1f02874c5d9daf2baf56b3040f24ce7fe14cc14d61c7960db4decb37d9779c8e36d69a7763066d8c1149312d26887a693dc222daa892dd00cd8f3a558cf605e4c65c011c2e9f0d671ba10af2bb90ee0351ae5078eb7878399ec9eb4ace87a68269618bda12a7aed6fda0385496c5d10ac36b35255f4a31edfa8a2c516b65c63431013ed4909ec7a787a5efb9d3c3887b80ac18a44934b6559bd8a84b18e86fa1b0b9e1d9f92ba495ba5595d82e5095612b79e805154bf428a7071662c7cefb6450165c6f8f6954c37219bff4a49894a8aa37f940a40f4ec942c281e6c47ea408199927a724ff1c7460fc8fd47a98d0c9d4d1f07994d8084f6e084935ad7c2985282fabd5ca13b942e10d35278f4ff4cb1cb96f3c862410e79144a46b4db1a3c3d4d63018ec5c01ca48cb67081482e7d434b4abe5fa3071f2fbb533f745602b0da6183b28e6c5dfa42dab7ae0bbbf7638e106be1bd7312cba399e08c96dbd69a128a2face2d4a02951533a25e82fe63d0aaaa2e8c75150215c93ab06c22f9cab8d1cae7424f8baa09b3260ecfa3c7c8d55a276b4b317f72ec86b1b145a63aca83ef8c1204d8ab0c96ea3f742de39db47020616e139285814f188029ace4587f14cf12b5ed81086d8213cf8cb578341e04e16f519b77ff4c2644a5732639d658d0c4eaf992bd7dbd5011b700a5fa63dc1b24a84a3c80656bab5705dc3a74312c80e8bdb24a7ac6e27bcb8c07ece62c6e5777dd3dc0657181f440c7524d907dd27950bcb252aef7f8cbf453cee3fe3143a665072c787cea76de323aa41537df2f3a40a518a694b918953bde8d57084e32d3b1fdcf9d153e73f02624beaf6ebe23e6828a6a489583494f3cd790fc96bb6f5d8b198402965e2e668e6581e7cf1c8a47a92198388f2b4cd38df660f0ddd48ad126819c4435af3a12c89113d778ac544fd8079cb8aaa97d2ff1b608da574c4dcd87f4979390de3be405f0e47788dd0b01662805079fd73c64e9278c036544add3694c838bfcfb08c8a5efb09549442123eaa59fa30fbb9198105f6be00163bac076193f6721c539714108bbfae167f5db8085c5838618f32a968bbb25c40645a17c17b9bec64aea45832eec5adc25b53e677f67566fbf5ce2d9193a06bd9b477e601d589b25f422defc49105252cd9ca6adcbb36be8a01a8472b4d463f655be14ccff9b0571a2048e31c14b9b23e2d43fafa3f85ece6fd41896cc5c68993dbaa926f285ec94c72887de9564881d735c05f83aa474b3d4cd133a630ac63850771cb5270f6cb7a391170d66af3e4901b6eb0253f3f34ef57d6babd97aa99ce718c3bcb53ff13d4028a0c943bb9681106ce176242cccb75df1d3f8d3706e5b068b042c3154d5e6292581b36499e6b069b9a490aa67f0675390539da8555e6a4e8a35a86fdfea83e1387bf4acc650ec1edae7c99aa3a48306ee1d1a5e513c0c6901f64d0a3ee285de3c11d49f90cd4323dafda14832f0d8b760c0e5a48633c967cfaf"); + _ = try fmt.hexToBytes(&expected_ss, "8c028c6ea72a1c59408e2b15dd8fed8008517e861cd2329b159bda1919ea656c"); + + const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM1024-P384 test vector 1" { + var seed: [32]u8 = undefined; + var expected_ek: [1665]u8 = undefined; + var randomness: [80]u8 = undefined; + var expected_ct: [1665]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0101010101010101010101010101010101010101010101010101010101010101"); + _ = try fmt.hexToBytes(&expected_ek, "6a0684b22b798e76a4407b87f6b7540d7ab75460692a8a91070456ed6457281542abb01adcac98daf4a62f3a81dc7962b6a23cc6624d96cacf0e5c8894651ec6806792f1c9b457211567515a65a184fcb27c86bef2b215237c119c9b29d205c0a4171b70c34da35427547497f827c8642031964b10b12aafa6c0278d9917cbb39e3c7b20151c167331764b447ea7097131fb4f36814d16290c3cac0759381747b4a5a8fbc170f8afb865c2962339988acad6a17cfe12aa7102aae24124537b1042c979cbd1a03e8a15261bb9476100360a2588e19ad3dc6f124b6567c25dc00ac4a4f515a23086b5035625a88458e121ed805143b8bccd95b08295bfedc2bcbe947f75527285231109c7a197ab406f6c8b5e927572a766f5d2b6a83816afb0513e81a02049a166778774714b7d121c6fb646189102923683b68abdb2fa11bed51a5dc30f0df593fe4a459ab2aa8eec26d69525b790001b820545656b0517989c5243f6e313c08720b9052c624b9cf382b92341ab3cd31007d68353077df88126e3762e8478359778bb3d14163098c5dd35b9b9d87c5e6874004d126ddc8839f48cfb6a717737010ab66188c24314fb0104c6c14895a42b33781afc01f84214897c7f7ea48662f18e1050513d91c83337c10db5cc7cfb78d86b615d5b1c74062cfb5162cfd2499e31a6e3e8cadc6cc2066215fb78a1b986a1be2086c73a5142a35923b61f76a1b669f2690d3857c3d903d9a6647d9b2d3f545703075f7b3021225c7daab74b4e327496a9ac8088418de6ad08ba4b3a57967c6c4963b87ec1012f1356051537ceaef13956dc134dcab19729c3fada994aa706c4832ce47b0479b51c13995eb6d895a7045df0d8b696f3a8a529a1abf8bd66e91e6af46d747307cadb76e7191d2ca90c8519394d3c41524089247258014bbf1a1b8add2709f50480d5d08b4d9a64688321c6cacc03115d30e09d016a1704db4689545b3802a07f4b3fa82142bbe8940c7ac15f19c3ee20bdfac11bfe8b26495107a88b9eb911228a2c83cde5b0fb82725d4808ea5a903ba2b9698a2dad9b55ebf6199f396ee19ac2998c7f5f1b9f67e4a82fb396d7b0a4bba7343dbcacffc3b113c44d6d033781f289a3cb8255d8bed93b0194b95024549614f45622e134dcfb6df598061048796649330bf8ce4ed35097f68503e1b1d8c2a2ad43af99d830af606ac2b013cec9367a9a6b5861a6ed618b3e6291743866cf8661db45cfb9b168dc0acabf1945cd698ef2d11cc9f1548bf48eed6bc301a233098b0cfec71cb479630f2aa6567c8b2a10717ce985bd21c9b6823519c01a40f82436ac734e4b8e15e28590ea212e992fa46438fd373cfeb83071c1549171c76fc80dcb17310de56eaa624043072632b14ab9636c37fca0f283742d0c8a7634b4c7f65cceb1204b6ac55cdb5fd508b37db8182cdb9cd5e705f4baa5ae85a78c013e2e7c168f2193bee3c81c95c446741bb730611963a01b1c385f7054dee45ffa75bb7cd12f41b25cd09ca575a09928c4bec4b61f67447ff5f38dfbd2044febbf8b83760bc91f5ef2247cd63ce25a7459247e8165b848010c237967f94b11e021237ca414ec0238171a4259a581323b3d6f091620b164725144d6b326afd748f3665482748d92315628339300353c370259fe86ae62931d94e2136a8a8fe5664324d3a3cfc5acd6d00ac8b72d67377bbfe1899dbac69004a0c2b9ab047a0150f903400b6d3f009a0a6a7ff388ce1ee43d9ab6314d720b770175d3402bb7ca39690aad41904cfb54a951c64ece057d9a6b610088630b826b682990962ab9d09a5fd1533044fc131015511932192ecbac76711e28743c921aad59dbb3d4978bc3147e859c40bc98bdc8680962536f1590207ec9a7dbf795a2d48468d3abe638c7c494241dd4a3994c2b62c65593756151e6a98ba50b7165c9e5146db36285a736383f391f80270920447918011064c78d4e738d20eb54f0e45551946e79281052ab6141ecb67834a55a27082b303facc4bdc9ec7733d7c5c8625a8eb4cc444501dc2180f5eb4ffd84b9f97960a1396af06c91429a9b92c4a54d12994364cf770a0a5ff4480738890b0198d813813664af9708a21b435ed6bb883dc2682fcc5928458a22101ddb594a616c34ab8322573226cc9b498a40808330885f206b72049a068b70202d8d71fdb3cb177d4670d5a5fe04584e2dc615b45facdbf7dbd82ae961faeec8274218f2e9f4a20d6aa9c78a7894b7d83ff770d2a87504d5be54954b03ed4236c6d1485236fcbae4af881600bb618ab00c7f20c27a3a2767d729980e3607313e83cdc11aa972d4e74b4c00c2ffb9"); + _ = try fmt.hexToBytes(&randomness, "6565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565"); + _ = try fmt.hexToBytes(&expected_ct, "b7ef5cf25fce247ee4a1ac8a0b6bfcb31ff4060ee7082c257897829268f59afa7c973e233c666ede6754fe326d01dc8709797232a833a1353d651250437d21d5a97cd761a335683830b1e7167cd6ac96c812614f32cdbb6495c807f921486066c270b560a79470ff198b5c10fd5ec63b9fcb3199f3aa410688883513e47c3ad9020ee303dca0c2adfd980fbda3f7abdcb7b1c38d9df943bf12bbc2c3aa2dbb856fcb9c30aebd64f2925aada5a3b25efeb10dc7a2423d60b277730d5f3800bc8ddeb252c6824b9b805f4de3729f0306a38854d8f9a63535c3cfa0479937a5dfa59a3273dd357276d8dd4d48d23c32e316952e4c877a4a72dac1e9815f0e589ca62721165633433ef333b842c09b178c417b748d8cb2c5ad56ee3b3f1bddd7da8b263a17fe759e25c50c257689039af122233bc0828f0a6b380bc959ad3077998703e530b13b249b91f7d1547682cbb1425b6084bafeddf3009653ad1fe547c4828859fe7b060a4e8c29932919e7f06de1c5101fb26bbc899a37a9239183d05859ef00bc9a6a3832129551c16bc75fb750447f20a38f12010d1d1c9ed462f593408fab42a6ce07bc8ab6e7df262649431fe85ff80d3027a862d140d75c9ea16f73eb8f38052a535fa72b370b19802c8a4d75a0e59766c81c60e582125522f15aa3f2e187d55cd2a0ebd8982ff5c671b95ccab54ac3cc544f6b07c6dbf58293502c27ec25ebcd9a44e2adba24a220dfe5ff3fa92ba509b2f4363facaa29ad7f9ee279f9a112f5307ff98cb1be7a237f56a97ac74343e5b5f6ac04676b560fbd5ac7e633e1b2b64d63586b13c735e7073855442002c0ea27d8bfd9b5e5147a62ac903efa1876e1a026abf31c3aec9b01d58c38c8c4dc5742bac200ba347f3da2e5bac62b213fe93f500a7a4340ff9f468519aca36b1bbd44c9ae4eed93d4daa1c847fdc072145939ff3473623250aab4707031c24efedd9e14680fd9a017729d8db87a132bfbce8fb4a524c2e32d469bcbad71ced78fb80c1cd9232b60c2836f019330a3f6deab21832f60faa346fd7b251768905b538d883cd23b0c2a7c283d33e083148ea24064e3b689f922e7f5ca7ca4da9bb8412bd7909f31e0f2963f958eb1431262a522f79d86c748460df92272dddc45bea7cc9cb78c35079baa70c3ca12720109bc514efb3dbf3b60fed6c49824535f50ce417475e0efbd7599d9071cbddc94790ee5251c685fe5abaf4f05f11413cda68af6e435f944eb69ad78ffc67ed25fdcca7e4378e9c282cbfb4779c9230276d487496ab7e064ec3d2acf6daa062616fa21cab9ae9b1c69de3d986f49125d9316bc38695a27e406842e9304b5863135e8b93b2b656e2292e6995ac80b404f6fb5b4afecbb3c2d07c43c1c3f031ca1be352f2c5d6ab020f7a3d97f8fc4e74a0877fb5a01898eff75583ac512f23067b9d9235a6fe9251f8581f68ceeaad4fd2e649e887b8d6ffd6a76f79f12408928c78a8eaa870a0e213a1598a5eb009d36eb0500950d6a32457c7d8c2e1605d755eb48959324bc0c9abb103f09a0907188bfe949afdb079ee5b30caed68bfa901b31531b78584727783e9593c20cb937ae6a19503ac2877f7225ee07289170d7700dccd64f4e5cc1846405b327dc7cae6731064a1178fbb178fc4e36ce169ac7df5d981081256e03b5987dea146cdf8dda5618fa7f956f5c3ee7eeb530b84407ce251ef012f1a9427d3679233995845ec09dc6c998fb73d123d87c07ca68453458ae7131992ae1151adeaac646d85d1c58ee99dc4853ce1305733bd4b903b1f18d2071f101957338b4de94f9ff27618873ecc05a352a1ead8d63e484911465f79512042e9d9182e667ac055077de3ea66abe4c71f635d6b1f37f43ae1801ce8764cfb9342b1f0f1358b68f2ea0a9ac93996bb93c1b6e9776fc9dc95351c40b05d5c1e69568d93eb85b0ea0a4cfa2d90065ecaf7f472e44f14e15e04d1cb17da07bfa76b1eb2ecbc054298e5dd6c5be7771e2e56a8d8212d5f8381e7357255e1a669c32009ce129622fc19b18f93f06f407384045713ea5ab64e7c55e204095c57bb1e8075004e9ebdd2e63e1a4bd94134b7d1d1fa08e1de070682ad8894edf639578b70804e4ca3ed6f4dd22d570fa42dc3534fb3498609f5f5b8e77115bcd295657f9c48f3aa96cffe6412e6c969fbc49332c2a8d8ec5d6e2c3596d878a361104025f5f77f84dc9ca38e6037abc429c6f69d3a237ea0e396e4f659e41068f4a08e4fafa287f17bbccc8b357b6e49ed038b5bf39d7b22836f0309969ef69f1898cca11479f4db4ce2eaa3e7987dd35516c0b8f3157886e5732cd865f794a2a29ed"); + _ = try fmt.hexToBytes(&expected_ss, "b258b8edf4851b7c1a86cc820743811c52d4bff678e8b94cf6bb5f3714b7dbd6"); + + const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM1024-P384 test vector 2" { + var seed: [32]u8 = undefined; + var expected_ek: [1665]u8 = undefined; + var randomness: [80]u8 = undefined; + var expected_ct: [1665]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0202020202020202020202020202020202020202020202020202020202020202"); + _ = try fmt.hexToBytes(&expected_ek, "da2020c3757b1fd29fcc785aa999bfb9fb1ac97a1efa300bd08356087ca3b8e685c00013ba18266cf1cacf42879ef4cbc583a3e277328fa0385f34c179a230534061fa65a280c53c5016ca2499881c1876d9635741ca65d760070b5cbf7186c3c3747453021e2e880b8ff8578cda8d84bc3e600b07f7960107b8cccccc8486db306958486dd3cd24f89f2bd93f63757620ccb2d40cb5b40b8fec178cab0c8339c5be3af98567e1678ef79adb21437da71d710250f166577115b290b81ea5a153130cb9b0bc467a75127af4702318c99a8944218a6df1763550eccb1ee500b7ba9d8e180af6ea84f4b278385ac57a37b0cfb06872ab40c2f017aab9c1876004fc9b3484da407a8538fe86754c407868d5222c069088b95f49e83f663c9551712db139c7bc4a024b3b08fb32a5fd926109183284a2afa6e894da8838cc24549c4029c5d099ec8a4af2a23a6ac74ca2b07fec86a812ea7d2f7679a5f72445c347c6dace5e7a6c95319a58055b86d4cd92863df4fa1f96c818dde32efcd140d0332357d442fc3a6258a242005a8d7f279cc9074dbc0862ff553541e4671a879dc9415a897aa13176892a2a0e39119b8bc5159b487ea39196f09093da51a3274087f59400a8ebbfa32481596a2b22417489d0992059900c55c9321823ca5c1b3f17930ccb819560593720a417f58ac9263a74094499b74d448c9d9a96acff9b50b765cd49ab1791d82def1c80307102ac406047106f3cd787c280b42f002a35920e1839b626cc29bf922939a7bf7c4b0294368b4ef397a9015d7937ac8f7926ec022755767a2a296506242aa5c95c712a9cba5c4f20080083c5bdcb0bac0ffa0b726b1f4eb5991f8b36ce582491536f0d32ab5c651c8389b2bb85a1750cad8ff8801356266b77baab0369b6516146dc7ac0e2140fd41b0c701b4c583d7fe01b7073422ba20662d5c22f407ae4c61322151c5eea77d3712e6a442fb93939856062d1eb495f402abb764db0d43999b53abf1ba582085dadf87e1c3a6f9d11aa61016f2148ba07d4269eb543a534519823c73a570931533aa3bc7ab591c7f8cb20fc339f7bc86fd1c02fa296c610f97e93c8326273a3d1361eef770774c059b777a3e6fcbf3a3544bf22000bc574211ace2dcbb3a51721fb6295d4324400ec4ff5822947d0335926193f155b4b3aa5c07b896f9c57c957b217ebc9bce9163893b0d759875157234c4708ece63cb905a3ea2313597b20a93907f8144f28ba2056501288666f37f25608901270b5bfbff78c6f994f80854f26344c0cf49d89b45c53b9b56951ca819a48ac5144c43855a585809ad53cb35087b1e783ad0b6a4d1bbc1604c86fe46d0d286ddbbc53fb90ca779b79813220b8c224fe2317cb9740e21b14a6ca8ea473ac1c195ccb8371cc649575f3879a3a8de3f150f3968a0318b511a47a2df378b525731815c2ec3684a40aa6f96484fb646befd10895a2c40056a87ebb51257bb7e2fca1a0b8b4e6d99dbfd8625853cc455c07903b84fef6326b7a1b793aa482d59113e79439eb3d7c6c4e43e5068f369761d4454244ca235200e30bcb1a92bdd70532076bc86dec10afbb97924c8175a8b69c8b72b9b0805a621dedf28fe73679175b44d5dc97668795d7913ca8b8635c470be0947e60fa621fd0783d301b9577a6da919a1a5c2417cb6d3ef71258f72107d45f79e7204c791b9aa86af78a9ba721cb8cd29997a68ad850862b7bacf3236ae0d290f9e861396c5bcc0b7e2cea2e2160bd86fb3257f75a8ca1acd4e436b1dcb67c48c1a58496a0d4b26605cfa1766a3ed264a5a3cee8c9b9990c4fe985a3edbcc39df9908348120fb81285c8b19f2cc31286433bf949814221cbc15a92b12e3e059675075d31a16f0b44bbd1100e87c0105354109f89312b491bb4ac9e6dacc6f107282d77bee5b726e0573910cc9feaa138e7ca1869b27e6c1a4e11a2a6ef9557aac75434259792556cc9e077a1e4c28dc52e22b40dc4486e13a76aaff3c57bd89f5508908697bc9033623f416027b72740583400c1069af8227a1233aff04a9552370facbde5f728812614b6974f4612334971167388867e88151df0ad07739bd472cf80ab52cc66563dd02062695bb3223ec4163aca8c3f3bd3a04d43284be0c3c09065dc305741099a50578228d5e480b0b4eaff53ed5c441b045d40cf107477beeb65464dbb33ba8204eed3e2657e4e77785bafa23eb5ff537e3fbc747b6fff2bb8adb2fe0f4b790097f85d4da3e252de3ee068ac3c61d3eaae8585377f539b894462178f399cc673b645df5193a70442206d10f8be2229770ece52cf7ac559de87e38fa44e11596658"); + _ = try fmt.hexToBytes(&randomness, "6666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666"); + _ = try fmt.hexToBytes(&expected_ct, "dc29c7e08271fe62f2ddb83c28f8d2b9c9d921679c2db284a2dab0dad7dffb16c6e28261d013b872f006cbaaaf683c60ae425e946d0b7bfd01ed9f181af60ed1fab63327869456446ef94dcd3485cafbd6c4414593428a7d1c21021b2cd4c92a49422c95c669239d22864c60035b77811f59b0995a21ac2fdc12fdc20b660dcbf2b39b3c6ea082bcc463d8300b9ac620922fbd18e7f2450b902067d6645d3e09a90e525ee18f3f7924365a877fe78204e2b77e81530f65d3c8a999da301d5ccd4acab70412cd6c79cfdc78025b3bbb7637c36093bae04a1b78924280ddb6a79bd5c2e2ee30f73ff7ff878f028021967adda04dabd8b1b8db747e87e2144232bc1e1aeabb6ce697aaad4bba725b54bb4dc2b52687a60b68384124dcf5719e643ad63b3af8f1fb0b1d9ded7066860a7cf6a5a661d7a207dea2d330d02b1cc4744234944d0ec1ddbaf83727fcf521ff2cf04fd0360d7460dc312cd1a78231dcdbc62a378d1e6ad6fd677327f3db12c904c582189213e642683e6fb40f912d035e145d80822bf7631bef6b2f417bc9c011f5b41260b298d8efa391e777166cd9a61ca79f482244af217cf7bf600c17a2e02153d6185b259afa4cd98dccc80510857a27e4d76539feb08c06c98cac68d81162df5b6d311da9b1193a6c65070e579adfbe15ed7ed1d996bf1e70ad7a3f08500c989dd7ff9d9950c43ebcd865a6f76e5ded66ae606edeb48d492d44a3a9923c6c15a53db2130b2aa45898e80b0b2e45b986a5e47ab95b01e36d39fe0e1c3af35c8874a72a5154d088afde172d5dfd800443552ea614a8aca28d808dbc7ced4b519bce7ca0109e6d53ba8515f45d3a283c51eb6567748e9ebbf3fdb90d860ab9a062d941641d17a4051752e5b94cd20a04cd737e02a5e240e668f9a20ec8be368197255e265b3c47da59607a4f0ff49dec1db4c805fd78315d07cce287de286f7574319afdb00e806e4f1b30b56bcbfe2c86c495431edf3176b65498ce8b7a5b2bd2568cd9003686048ec8940cea9b73eee194d394408510baf0fa576be1058a6ac74ed2de2015d0a6757052dbc55ce385acc31e266e165f56f68a9019896e4b78a1d8e1c36d3a7a3c3a9f239a60d987113af9a76ce960e9e2e9855142cbb881681e0f2944f7550b27efcaf2f165eb4138f06143f59a2f9dec289b68a164e68b4a911e8b2ac96f532287a01a37a21768dcc450ce25b4c0460a162989b150d87538652b645d4c17e625eb949138f26ff01f19f8b83bad74b4e66c82291619022129bae11e53812a759a41d7e4fc922dd776a67919cd40ca26bf908996b36750006e528033b85a663bc7a717b027e8b17f761d6fdf6a4c7dea2cdeef9e72de0108a5608343f12076ff0ae0c5dde2ede197c0f72b4732f5599ba11ccff6e16768e3bbb661ea4ad0cc2c69a725f80cc820fb94bdc9dc9c61ce1a955559d5427d6c0b354cd3a83f3cfdc4e7d1f01a4d5ef1ff54239e5d9d8e6384c5516290797d5641fb290b2065be0426c7a05898df9dfd3fccc0841a96cef6d312ef36ca01bd9be5dee8b9dc95637789b1e7ca05b51bec1e8e17aaf198e2b8eec015e921b820da20126926b460a3cefad98d6111e5bb9143328eb270d38bbcbd430a7a6f3235333684a77e040bd2a3a27aa350cfdcb34edd48fea62bfc6152527300b9447c67340ad97dc43c1fccdc6812e45ac28b379ecbe8c06da3b6d3546e4acfccc0faf26cb3240eecef89690f0f884739b880c3a3940a0cdc5fedcfb5bc7044bdb7d8502a5dd6f6ab3e029c8141209b5f9e196261921d5be6f79544fa7361651039f2a97fad392392932b57259ebd740a7100c959901d587da7df9f6961052cfabfe55a12746a5dea3be2c120b25a1a50a2177d7cb4c81be846c7c67f2214f85ae223271e83747aecd899e7efe8ed67aca9936df81bcb5602e0eea600dafcde932b0d6da9e96d4021a4be612ce6e25bce8a71ec218b254e50998d436ada860cbb920b79ca917669be9d54eb63701706b5d0da2d8dcdba97ffcbd7bd76b1b5a29cef2c7cd9f5ad00fe40969ddf9b8920b1af9f86eb690f93705afae26625508ccc2c475a8ec94646999444d9326ceacf92559427b33c68dcf7c7b5fa76866ac88803d1a9ebda8700afd31af16746d1efec44259a281875066f7e30fc9631da7c0ff98727f84418da3bb39d3e63f03e8f3fd6dbe001fa9104e36e0b36bc7be4eb11f50c9b88f5afbfb0022de2db3a8148dcc1f91575b55f47bedea0e916caca594e6f6bf709c634f8fc292d6c0b83b120d5f26f21682007e17d25807dd9b42365550ee4954c5537e2d846ca833330bc465fea5d7d6a5c5bf3"); + _ = try fmt.hexToBytes(&expected_ss, "64a60015ced50f3972d4bb5cfb566f2a800056693945b309abd0ddeee3c1062a"); + + const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM1024-P384 test vector 3" { + var seed: [32]u8 = undefined; + var expected_ek: [1665]u8 = undefined; + var randomness: [80]u8 = undefined; + var expected_ct: [1665]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0303030303030303030303030303030303030303030303030303030303030303"); + _ = try fmt.hexToBytes(&expected_ek, "a7a3aa9b70890e37309eaa5b38333f8ca91ef7b72c01781d6cd542c2db1e1383c49b78757b678856016995b51709a2150aac314a815630c408fc5944004ac3709a5fa6f13367b3397338c8adea1d72e8b092e9b6659c95f1a3c25937766e1c8f02b66a7e95935022161472420086678d507dcd660df1212ffcd84c80488e33a269d192c3f09a1ba6a2bc5a5061cb32c7c18958902bb767d6bda6563023d7ace28bb0c7642c839547e46103c0c5311e5bab4f41aeb16abad34a0a92465c5aeb7085d88659a175c6e717b4778ff3ea8d19e6c793d5ac41b0532a043b6c3826352090b47a33a2b0567d555bc7484cce1120b45a55a9aa148bf135045c941805bd4243a96c2c7a9fe51aa8705c0da35b6f6689e0578ade37c2ff134d7e366ce7492b7905497502159a964cf7b1b87c1186d79892256a7f5e7228de625fb03c91560c8f52f4c6cc7714f5d70729d7a42c6057d26506b910599b10925562c02e74354551ba0b7b959610ca08b540346c3620d4b83d9b1707755432567fbf66b3df324a0a8798f16a4086ac5628743570642ff5facd9be5085e99a31a7670c33c5ba991cb1d14cdb5231704336df02c51384a2bbbaac9c210063eb5763dd291671aa511cb5738f265352661ab6cc7bac2755d0a87a0a7bdfe435ecd0714e07439eb04076f654d4e51cf86289504640d3709b6c7717634b11cf55b87a303bd28965a0d31089a6c8313fcb10bb31cf7b4a6b45c7d18189d5ec43294483ecb3073e2558c5054102e5b3f3727579dfb4277890e900c20bdf5a1619ac89e4b9c2ef3cba18748cf8b95e3ac38820476a3f254ec323eee9053626707c12a9518865372053102687b7508c7c2ca80b4fb7685509f80a3206bd28af2551c662580232ca8b6441971116723e04077bc37e0e2640b8000b9f80c372c1f69662e24d53862006fd7d445acd5457794ceb3490cc24a5281b6324e760985847b7b9612ba3ba0d0e492bfd0b47f4069a2e54373a05628957bbaa04cfbd2280abb1a9ad89d3b688656e76ec539ce8838a269b11c124b5875695ac0cb3d2d940a6cd85a2b93266d56a71618be0a577357a78817379e83abb820d1a206d779aa887e5ec402d92c9da9b9254d03a27c17aef650ac8c4381f830c588022125f4181ecb5c4d5636b7065d93454c47d784ac35a08501c520112a604b3d1ff81f94a20fc090a3cfc9754e578cd0ca9c34360ca4f08176e35cc0945f69294eb644a6a31177220c02c0149d1ec4a613bbc2168136aee307e62ac4288b0b64f39e5432983103c57771a030d3b32f053408351e48f11435b693a9560415450138bb3c703a29f2009bd8a890d9b650419bc5f1948d1358a9f041047d030d2e1026f75532ada2763f98003f8a4a2540c19aac7eb5c817d2aabff9eb556e449c8d447015799d179b8fb07684415a5b770c10a2eab05ec3908d547f6e16058fc399af653d6c440f7784bea7619056b79474eb8838cb4b83a029a0d9148ce8bb188cade92024d7f90f37c12fcf73bcec61cf81566b11171725226646230134158762a4c5d1b609c660c9b2c93f0a72b7066b8c219a07c893b89b22705ed94da06c97e31a95246b2d4773593d1b5e2c07bb6d3a5149b0ab21539f200c8445160c916a35d17930a74659321c65876342747710c4c573f69c7e25fa3c697b32d3746e2e7b34f54147b5f348d27534c73a0d6382a8b622a665da907fe40b19e0856593be36c7954976233c8219c8a86cbafcc8c5d20c0926757dd17b81666b78c0346a352a18c2ac7294b5d0a8b8d8643689c809fdc47022492dee3b15b713b07990b81230c4c0906476a09fd65445aa3061d71b277d806735218389cc903676c6eb776148396c2d32a49b6a5172a8cf56267f780a2b10175eaef72efce516812bbf3469582b1c6798a62709131cd419ab2faa5855b6451866809ae198859914d8855ba9d109419b2dc18c322da220fde6ab21ab7eadf10deab29a6bdcc46c6bb65efc06485a9e6673b665036cda98bf2c64884d08cf76b086a9ca7866b5c8ab6134fe202b82794922e083c0e354b1546ee9c6c59898c972a12a423c32f23670762c8ef95a63d4d5ba20fac2eada0abd647e2d77157e8cc7ea2c901b3a873e5b017596a30f66606ed85e452437fad731186aa9acc4c508ad2a4f246fcc0326ea60a0341c81a88c588e0fa10e146db47bf379320b4dd504621bdba7406b8a3238a2e65070ae95026f6bfc7d946e1530c334f92a50151a6e73b55a4567697045286ceb5bfc150519382c565868a75ada2db86b091661e0209b62470616819572f4580dcfc1b799f5c7e5cf37bcb9fad65a9bcdaf332e3663"); + _ = try fmt.hexToBytes(&randomness, "6767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767"); + _ = try fmt.hexToBytes(&expected_ct, "e6d40ddf8ba0b0a4a08042ab0a9c0915b51e330251fb8dfe8bb1bde64b387785de977142587424bb00533be0429643d77c8736ed8a1dcc6a8d8f6a5e5c1aaf619344eb42cb56d135b18c1eaaa5e87be1ce67eebdf514399f2161f6c2a38d597550e1e7490951938c80909063d9b6dd19434c8aef5f2ce5b4a4d393ac36c0c8e287647f6dcc584b8ab14c6f357a19fd535ca7381a76e58e6095adb0179be4a19114bcc0423f604826f5a8d813c52ae802b7beff1edda7ba0f301b552e916e650808323dde239be8dd561da9c8d07986d010219eb364d15788084725ca425218af2722a51c5741e81cb787fc60ae97e3edcd3e683b3dfebf2a8a0269c737b5ac44a03342257de219627d4b302914d09d9aafb95388098631c3ce81c0edfb7c293622868d0e080c019c9c34efd4bb8f3fb148e7267b1b9bba2f7d23d387d5accc137333e45b76182cfd29f22c477aabbf4b6e5d24f7eb2efd3c1c4e6b6e70159e44df6682b1860d329b5f5986b8a2f4f73beb6200a78edcabc6168bd63fb41a663a263d2c4f74b84fe04d393e7e5bfb684b4549887c30e26d02ba8ecd2bd0e6a9be1e2e8706305f7fc18b6baf0ecca93f82a978385227fb38cb2f0ff4b7606a5672fe2abb9bba4f27c3b33b567a4e4a18bef73672c013544ac2978e1eb589bf42242892b8ab3ffb240a1d778267137695b031fd148583ad6985a92c8c6dddd6b7f82b63c738ec8df6b969098ee7687784bf8234ff52e7fe4ba1b892ab8a38a4a5750828c50b68ddd9a8ea0ef34d2a3a779d6916c1f56e0732e44eef7535e6e1f1717e3553db771059996e78c3469d0c60b461e89f6afdfce270cc8bb45729e26f4db325d925c81585f5d29268f3e6fa4e2ecf8456d6c2edc61c025796b708d08dc497483463fe63ae5cd69c57edf7766ad1f2b231dcf376010eebe13806a1b3c51610d7b35b2b00fce2ff3b815c9197776c6b96ac1612d9af7521ccfa92fb3af0cde612f9d7c55912f98f14a14fbc4819e49115cb3007abe2c3f5069dd950ed40a79451186952e02c381b8d33c6a6b6a5538bba5c23e78091742fd816e932cad065642c13a99d64d828275683cfd16a3a6b853bd2414f3b609f9f1f5eaa3ddc25863fddcb09fc60f82ccf49679c35e2d9a6399d97d71c7ad808953deb2696f39c62d753fa291b95015b192c2914ce4a31ee540b9b396828053e45458220b52947409df006ff165f9f5cf43729274783db7562439e34fdaa4ef6de9d3ccb55bc79e3e18a5018d2ae90b1605dc397c72fab29be1b155dc21e62db17890c376564484655f0807830548892bc9a2fb70ca653d70a15d73936fd71839fb55fb83060756807e71d5f87d3999d2e86dba0116bd90b8c0d45e590425fe7cdd9dea7585180bd1817186cc52ea79bb221f8459b136e39be7feb7a489b988c3bfc9890ca8d2b91d3c6197454c138f5e12e231bc3b690829031356eeb38741553774016515994243e071f12996ace3f812efd6b79f84fd7c10f72fb751689606d94e01dac7bd28491b5ee592ab3ecdfa7bca01fb07e7cbaf94ba5bf9ec0b00ce7baf47b8cc9b9251ba505ddaea9f7f6f14ea36ecadc09cee557fe254c4353cc2b558bc9016dd0d079568d2a4de616099083ed9e13a493c9413b9a4a151d22b0fbeaf773e7e69cb37736593b1885b11a4f441d0718128ff0b5bb66a061484569d6616b57666e47a8e3696871d24636d9d1e23ec64f8bf11e7b7315d060539ef9b94051feecd6a1efd6a0c1b662a04eefd6db64ca7f7dbd36a8b637b98dc39dbec46f6d804e35d9b10d80479e45f664ae1d1f6abce7ba153bda60002244dd33ec57fd4b27d9ef5d7b2c04757baac4a222afd09dede3b5e19f6744330238410c4edde037a95faf805285e7758435128d16384186daf0a72652f19e4902112dd0c78c10446eb00dc312a9eaa190057f0dec993322d9e2c338d694ff204e7602c9898610ac462aec8bcc66ed439da1d85b6f6cdc24e0b01a018130204efa313e1ba53469b526734dff82b98489d63c44240fb93ac53858ffe056dfa935d565ce33bce416ebe9937206fcc78237ce755b1fb22c3a4ad0601e84495765f7d8b48a7e4c421a881c21b5a77964ce0e94e428ba8c4d4de25b644140cab513687dc242732f07c2f4773d8952cf1c66fb345331679bbbae98ff5162ff31e6253d71d26b054d5c7ab0fad20a2f0404b6f05e2da70b8a532584a4561e870d472388e85868a5a9040342dc362b319bc554f1b99e3ef29dd6d7b39df6ee9818eb4539eced50a45fe98cd5f5f786f1d2832bbfe1b058b8e0dca415a90f99fa7aa33e5219aecff4f39fa8b5c3edf699a9ff"); + _ = try fmt.hexToBytes(&expected_ss, "fc5e3871973b49b494090579634603099faf8f0bb022c4daba472cb771f1bac7"); + + const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM1024-P384 test vector 4" { + var seed: [32]u8 = undefined; + var expected_ek: [1665]u8 = undefined; + var randomness: [80]u8 = undefined; + var expected_ct: [1665]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0404040404040404040404040404040404040404040404040404040404040404"); + _ = try fmt.hexToBytes(&expected_ek, "27160bd008ab6864b35c32ceec05a51637cd44560833656624e34ff9cc88279b60f3a97a1ea43c2397cb1243bc2531c3db46124113c14d59b50e988bdcb86419878a4f8721f68ba3c9e8382539983b3c59808c3a50d5661f6553955170278667cc2372d82343af3a1fed09be09919ecd257fc25889fffc407745983c092e7af35cd4b23d57d935d9c399f4a4cf53967a0bc4309c106b1e3914316b1e22ac9e4a55441b35cfb54959af1332cb6435d9ba77f18ba709aa83fe4b671c89888d52304979ceaa88339f24b992648af55c4e7f4aab5e815f81936a74001b6a5ab5204935983a8073e61dbe49938c685e4c3a14cc578f11dca9a48491f05acce985bb84f14eeb8bbd62ec203bc573acd1212ef84bca45b4f523b9d8d5c15887be74447c2d877d64c175a0d45ccbb8bb82b26232256709c8a568662f08a1675baa3a698bbea2d5532287a9de62909512641295a9627bad0296ae59e3b2051372624384aa61b4e9b19f0dca1bac6c10a31277189a1331f5b05a112c26f70859163147215b4b2c00d2a4057fe39d9d28968798a66b3732a7763934f81de2a91d69e01b1d7807acdc2ef893be10224794099c3d6904deab0d9c48ab51f31b85295accb4c96e9c2296fc36ea1b826c499912275b368499423c2abb70cd08a005f17c2215972936ac5f25b2cb3ae1ba9f86be02668633e582bd2a9e5226ca2b1946c9d7503708a7877505da727cadc693420acc892701619c9ec8792c00669bb5c5a26c8045aed7390374bad5d52390730cde23237eeb2546b0aa469b3387f147bb413b170aa4812604898801a45905214b0f2fab10058a532f379bfcf96a76725704e07c3e24c5c86b504a74ad31ac8b29f9c99889a28c42256397c78ad0870aca087b36b2d1031e1e8435103072262156b93215a7f0ae8f0c5b7f7c81d5713f26d77d0ffa243241c95fd30f95164c50197b7b1a2ea1dc4efee0ce52976d89ac9d29e11ac5392ce313bb92679542dcb364ac9f764c0c192b3ed3b535de1a51f4e5895d48a5c106b0e959165f536db2ec4cab684e8c956777bcba1bf23b66730d5a2abdbca85a3c265dba69c5af5b7364018092d97a97a85a2fa38969688cf8fca69410b3b02c380352b800227b99a57144f352c3f6c7a092659553b7ac4a392b2512b90825cb28283708b2c067cedc208cdce82734d819f0447eebb17bd9d29272d15c0708760c517d8d5046b87aa51929314361a70ea4491137b288b55cbbd005abd9bf4c878a29e7b5434a15ee9731ecb42f80709993e570f7285045f8338649a335da2e03489a9a0a0257d042ce220f91b4475ab64228d64e0dbb3ee264883f605c0b7240fecc8f33ab94e0005a6df218bd393f73d3a18aaba6a8d15df009238fa3c85ae7c9170a013382a57b684964761ed6e1172f0c7e9aac6b9e040c389b3c67e04b1202aff784b954acafde9c7ac838b0407078fd1a5bed71cdb74018a3b94aa24a18960a1e22c31ea251c125013b5d7a46db184d82a35bfea1a9a609909d2686247555695a7686f69846d576212c72d1958bf27c037e2a13d8b84a7f5c10e546757bd87b3ca85a42238a4d837490742f28694b8db5c5221baadd9c7e6f09acceec5f7e39b717337970b8921d7c6861179fbac3154051ab236a56a1aa077ce90cd0157fcdb9c7a92950ea0b29f02c3478d333cb3a130cf30d9916c810b12bee8473bf2b521b278a8e458b5898a512b77f87f9840550450be694c5e9ba4b38b703519cac558296ab08881a7986c7818017393593315838b3fbcb8d95f854d391afa6589090a8ac9964b9a09c721716407f29c97e3546b4d90d60da11ef608567f0730ac09d5bbb0f93a930d8c533fc245833c4902ad0b53a8736b5770d008d2c972605c4319d78a69a64a4358929ca1e15a5329393493cac5ee83a834681268ab4dfca1e7c13c4570c56555195bf6c7af3c5a1204555ca8380d814c0e9ab830a376f46570b27171c910c41521810ea21685fc4c5fadcb5684205800703abb9b39818a2a6d4af4ce52fd73b4b620ca9a5133257d40ea91b2b6d6bccaf54c991d68222fc81dcc5b32e936d3f28157339cae6fb931c05247913812dc41682f91f75f3173bd072171aa880b1a12470276826a5bda028b23bba0708093ce795c4fa8f37c43cd70a2d06a2a858ae4dbd792ad37fbb40c43d94064c5dc13597c5981a8bddf98e045825acf2447c53b568af3835c532fb0214aca9d4626da03f97563cfdcc97c4cc773e2e79c60029468539d898913b7cedfe6179cdc1ab2b27170be8a352d83ce3cb78809392091fac41712d0ba2401e10939d93d16c77b5a1be9e9b056a8944aa"); + _ = try fmt.hexToBytes(&randomness, "6868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868"); + _ = try fmt.hexToBytes(&expected_ct, "94bb545f2e6e3baf2b0a9bfe14dfe38c34d73d7a2512ae51b8e1c92b3e335aeee4b9189567877bf56c6073b81f3f6d35c1c11a4925c4abce2da026b67ba02b2edcfe6454165ee103225987d4654f45517a4d05cfd42a18cdd4462cc6e455c54e845c5fa6b50ccf8229a35245a1adf27779aae1c97c6143223539d97d2ec7a91f602774e43be57aede2297f31cfe7bd24450a408f611ba8ec5977d7f8106df0361b7d959ea971a1c57513b99c8f61e1c48a10648d2a987bb5a86841852b5258d8df8c7c48ee5d1f24c68f4300e6f0e727cd487f747b5826edb7ecf1e291f6de1e80fdf6caf6297a2f76d735fb70c21877a9a22177891da422b1b06a0c98aa2f2847c862169829e8ce2477a494aea4bb94aa87bd0517044271dba667d4e3d0f06f52b424a1bf8b5d1d1fe2fe0eaae058f05193be403fbb8cfba5b8ea821c057cc3f5a44048d1f2fdee5567858bfc8aad944e3e2335733b16ec3bff838de5697ecfbff71d19fa6e466120728bf8d95873eca59566ecec7cfce924572ef4c4b6614c6cfd4cc6c9febf08045d813865cb810a8b67bdd2e3057b2cd5ad1385569178407beb92c7190ec91ce403f0e9636d414c299502446be23baeae5cf25976ad6f2f21ed0a582b8969e390803d2683bc91c5af92ce637c5bba627bc1dcf0d4936e84419a615a9a8ddda4100ad3f1fe6aeeee1c865b4b59efa73856a1f2bf06d661b069005ab96944322a4aedf0420893be68cfe9cc59188836a7a1fcbe7fb26806de62931f72fa5403587c425a974defaf228e9f8f71428eecf487eff5a7c71fe62c31c5911d9c96bde7f766a4bf26ae88f9d53de35e6dac62ce3ef51576a45e8b907f1ff0a5292641850cae8b2116bc5502ccdc26e27027560cb776a54114ba1ccba9f9e1f91a99f80293f50d5397121f8816c1cdbe60352cf9f9c779333cc72e7ae51cd2819394822a2c3f2edfbb0099b272c2f883fa11c3bbeaec067ca54caf11ddc45b1ea79c573b84cb96e89fdbb899571c00661e8544a64ae0a96af5ccb65268ea80841f6ef8a832ff83b9d65d313309ee8d4a15eb03b233272a83cc0fbc587d06a6deba39e2c6ab6f7b8fc7f23841f5b4b7751fafd6fe28c439c3e39f03db741b81757d443f4aa8141789e81401edafebbd6bff34bc7f1f3f5006aed3033fba74f369fe37864a592da2379ec49d97433d0f8aff262fd5465c9db351215c21fc1adf5cdab6ccfc49f28627296f6ae7075bfbffe1ab2c72fc404256aa253300b53042da954e6fd16dbfb6759f186b0d215ebfd09d21b7f5385a27c77f65d5dca4ae62550f05b8689c7c0ee041652179d5aacb1d338ef667abc1aa74a11aec98d91f92d878c6452878baa22b0595d0dd888fd498670ba01471ebc246d5faec58946f57d09b8fa49419995b75a6260f56c8657abd288d00cb6b29699394f48f02180a45dc4c595cb7a62700ad7130f19cefe07814134059f428d1f19a0c786edbabe2e1d085859fad0d3c455a3ebc1056fd1017fefd7bdaa370191fa912d5c1e8005c8f6a6a2c9b933ba2d90181202c7107ebd5d7c1dd70f52ca0ed678ede21346ac308f846c4c26cece324b2dc83d5d4b68f0fbb0a9d6a9fe5ea71c6f53fecf61913573606e5f29f23c1f683f31688399bb2856f15e11a8c3f5d9425b708d2bb74064956c43983979d6ae434610d394e5a81acb26951f81ea965d2c4dd12edfcd5954214d58abfc620a76e4f6ff37859d110a0718c397133cef8600f44596559b163626cb1557be60772374be9e5ae26fa629c1e11f931978067969231405614f602261f7fc7c77acb57d2b82e8054d0aa811cca46e0209a733f4b70fe37776768512cb2ec63d90cfcc0493aee22fc46c3ae9b47024238993228406583e200d641165fe3c4c1dcf3614842ac0840108db7a5fd136ddf7ab814d5026c4e54f9c3f40c8ab9d33b5118f22146938b0234c6ff71ac1b08a04968ec277b84a3f4b21cd20ef50c0dc2f2c71ff2171927c4cf68fb460b4837d66cf9e92051237497f9c1efdfe16a04d317263e6a825daaa91f4c073e09dbded783d13cf65cd5223ada3416d7704267c8a1a64966aa43a93b7b0524b1058b01d7281d43ed038d1a95139e280546e3123011b9d766d6685f9b5b93d8e927663a09634f38adb3f16c7c2c63992983ca5a4fcaf8c240d194f87567cfb51daca300b6c7bf21ad968b15dc1465040ad9fd3e2cfa1c805fed13a55a17e9c5922adb096d5b253299024718b53d3bf0c98bfdc0a7b4a88c321600ddf539ac791808fdf8b189c8ad00dc5397814d330521c1e357f39b9c60867b78895038ef2468175040231cdee02250b2dabb6f6ff5"); + _ = try fmt.hexToBytes(&expected_ss, "c3f7adc77f966a24f642197c478583b6eb8c2fe3fab1980925b628b9ed5ffeef"); + + const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM1024-P384 test vector 5" { + var seed: [32]u8 = undefined; + var expected_ek: [1665]u8 = undefined; + var randomness: [80]u8 = undefined; + var expected_ct: [1665]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0505050505050505050505050505050505050505050505050505050505050505"); + _ = try fmt.hexToBytes(&expected_ek, "5b91a689d96b5c8330d76361fbbaa995e78b4c5229ab4a321513988b1a8c58664d9aa70e056813a064020e51c7bd033105c72fc1aa5da5f16973919d17445a75b3cbd5c20f42c8c14717b78608b241d37c80ba20e50c20048aa67f17ccec332c4b58266b0bb4a42a099723063765578cd35614dbcbcad14755159b185865c2e6bac9c4ac5242a0b4eb63c96c90ef63869bc8a7b00a3bb62b5d35ca3bd1e0b90cb75f24d5c78201874eda2fc0985823090ba8c56778cca9c3780e2c7c3c5911515efa88ac37068d12bf95e262d9bc0c540154f168a6d2eb4ed1ac21cc295008c3ca1954919a0a76a4963090e915d2293bc0942a01eb8c5e4c3db93b32147ba890d9a5574b5e119b14d732431bf27a2bc74e8cfa205488b273c16070287b505a4c6d4b564e4188c5146532f0c87070816cb42dd80aad7a028d9105343b6724fb81952751765a0917305714dd60360cb7add1473f4651b4716577138396a3798447d549fa01cbd8d18b395259b1dc4b66d7b08e2284d9b577d3828714d6887dc243a0707d5f097c8ec33ad6247daaf92fa834042ed774b3c35da3195a290c6513d0c008d6b2de4aa0efc9500a42949a5407338890c2720f8f3a5519640436b85fb2c53ae9e8cc202c04ddcc6de99bb1a1181608a3887906cb1db845ac73c1269b1aec2582bf5865fe837355b4b3828059d812b6e2186bfd5679eaba1e2fe4a367157feb1b0f5d6161924aadf9c637e17bbeef2a8504815b40d8c43280c3c3cb9a9bf5c7d15926c1a464f90577b3fc72b9b679cd4a8a67f9576c98b5f1e4218d498af76782cf2b5c4eec64767645b338455dc4af8585ab98c8a8002c27891429850b9f0a84af0043c831778dfe79acecf868dcb6174e2bb15c96374ce968ffb6c9ec60972353b1b0a77c066c2ef9d6691ea5a7bb28b119ac91ee371865bc89d4780c3fe8955212cbfd5c12732c2e43aa0c52d133739cc7b5007a414374b5029bc983ba203000bd7a887dea2c00cb110233b5f6876d02d539c5d6027f0319fa2b9af0eba53619a4f447ca71ea97dec65ffb5541af64c406bb25c2970b2bb457b0b755ae94aaa398c38a945274a75c2beb2c4610031b7a41fb694a1a880f97bb88d3579eec2390b246ab36f208e79c65d4a6194b770ef2a0caba95b41b315545d0080e6927ac4a793a95acaa870451b6c5cad62669465c9f130548cb73ac57b616343dece0a9c1e249edd4487023a216b95862474cf8330524f4306fd640b7eabd0ce87ef55b80e721ccac2c5b0e0b16b5bb74f6139fd2d49813765988689e32358ea49b3425101a50fa1766d5880f3a3c35683000f6b2e296b069994d83b51232914d5c1325225a06ef52a49497142d06c16f485e1c10553e11a253799eb155659de16bf9eb127ceb86230cc369487c7a276991541460b6246c998bd72152770c094c5364c41357ef8105fd7a25306b33c696562a05c33f1b11d46906f9e38a4e8368ab4a5b62971d9c1b094f286077f6906f463be2ac1ba05204a129bb1334082bd71810e5be4ec75350709e57b6b266c9c5b9113675b0a7b6b5b9bb18718b90bca8f79184060e3fb13b1f75c87616cc52348e99c79458e149f3f6a4a9782523213f07b2bc9e4accab111feda22e6619b64bc04e769b7cb4c445fe5338c2a5362908a818a6b851aa1832933e30a69d9dc339ad0177a34073322211478878768b350224c3026b12ae40254d302e6392422c506cdee44f819b4bc11525a26b891ad5053623870b1957a274904e4ccdc562ae169605517c7ee3148409a78568daa374982c9c920d5821a085a529756171dc59aa253878a2d3bc6c53c8b7cc51be85233603211c87573ed90cc1d59819ba11e00a4eced6cfa6d26af46a971699038b66475e82bc23b5410c02466acc37a7d79f1a6848aa973a9d628afb4c90f1a7074698bf34f13674f62f81db5411395e9914095be77f14020711254a4078a4999c854c2ccbd196b60311305fe322ab32983a535fcb81162e6a75eba885f6d2228a28ce72f697728a1abefa9493e1388910c8977cce95ab4a5625a600fcbae4f03f2681020b18092119584d27799f7c3d0154c8a050296a4c70abb55423c57c597701770031fa2c8d5d4413f8f15cb615b15f936a93d61f8ad971c68cb4d7b239ca53a5eff8b3d99488032e03682ff7c9c54af9d21b77d559c7fa678a9487d60781bd1004f92f4a2fb94044ebc13e4afff556e83312d782870ac897002110583502b4c062955262c9edbf352a49bf3247a5144186d78d3b28fbd764132787444fa933c565091883535c7eb9b8daab2638fafccd40c49de6050e28446c1cded052f676a243"); + _ = try fmt.hexToBytes(&randomness, "6969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969"); + _ = try fmt.hexToBytes(&expected_ct, "913ebdd7649538471b99c731ad2351ab626b20bd6d9a4bf713e6669c80f750d8b1277b3f22ec2e7a73c5fd422327ee91bc5ad7046460bd27f6c10dc4d5e9688c871b4aeaee4051dcfe085a1b87354c8fd8fe4f72051b0e87f30c21f02a8dc65ad004b0ebc8facf684c8c67b0fd7d280bb5349209856ca86edb80ec2757f80d9a00c85b1b92a013a969ffa25cbee722c788d631c67914e360481cdb6414277cf71f647765924bb568df6c37c0578e145b95f487f4814fa9eaedfc235b87e5eb417c4f56a8e19c92f018e6330fbfae0c082a9c6f179bff9b79fcb0a880e14472c2b4a1ac4b2466755bfbfcb1167b8147606f8331c2d5ed62216fe475310c4e2ea6e426dc2de4e67d93bbda215aef0b3d536a6c99078e513f4b77d22728fe23efa6e881d92a5db5249b4f89aba7a703fe2333e17072199d266050cb2ff4a2319c219122988448645968fe098be68d7a30f6b13ffa8ee05f01b9d5728db03b4c37761d9cc9eae459159edcaa87442e067224d0b84b54293da273a80697158cd93ad7a08cb9427bc8d0395af0aead90b10d8c2a47f9cec11953adf2e74b5467ee2f16e0f3cb2b693a2d2541d643fac3d7bec1b03b30cc482b7b8105167f0f4478bf71f7dbd2c4199878887fa7136cbfdb329edfa2508dc5b305b844d05aaf0914b6682dec0f57def521e606b9d15ab9de438106fef0d0834c9839e765c7869b9b76aadb4cfc2d9f02393d4979bf54f59f8d55a38e4f2d653f5a4bb5c250abb6fc65d6a8496b778a19fa1a1c7fb8f4fa6f6fac1f47b3fa97f2bc9fc1a6fcdea508bebfa8b1542878dfc06413dfb414e2cc119c3709e5049e5c891d9b5188da8fa10527bc44440ceb347b7acee506634ae57636dbee18a460485cc2dbb90f34489df3b6e583ceabee9f075a72e8e2d43ef7d71ceddd61af0c7fca81a049b7e454477df86c0bdddf676afa186edd716273ccf9805c690fd8ccce852c70bcd9eceabaf807867989d52cd9280d0a4816b093335716c6b4321954c9aaa6f8fda48549987fad3d95213f6d66f62c406e101a4958588250d15d879f2f83f785a5446b396f73074ba69d98ba1be0b6ea340fcc2d0eede24972a6c460c59642546cd8ba9df1bbc050b1b7c0c4d2b123fb8dd66f32126a744b8f1af573ad36e6f8c8aeea44e04695e0ce7df7cd35a4fcdf29eca300eaf35c04ad9ec68e286fd991fefe9d58b96e6c2b86dfa6abc314d9f83432357747d7d129d69dcad7994df4b13fae3028a5b402d4fb1731ea32e6969770c0599bdc7c52e27ef1477d0e00fb97c3d8e5eac967956c05d6d35c9d956c36606e17c9e566195341ecdd6a87a98923fc7833bad39249823c3fa905cb2b69c70e8f984c3b5b165b3621a50ae69686185da98a0035d112a05a9a3a5615afac3cc95ab4cdf385c1cf3471fbcad069e6ed6944ccc27a99e85257ebff3d331fc695fdda1246ea63646a02b91764b9ba025f27c7c66fc1311d8fb6ea45b0caa563042c18a3caabe3cf8e2c3ff062e20960c73d8c5b43a9b0d47dfaa852190ff58db48eb73325211c462ee43aeeacf83d257b23a0f1f89f64e1338b2232021e0b8e2cb910b28b476f0cae0d757ef65b6a0f799ebb9a9a22b67c636fb1f1def2064b362ef6c59ec8e780054c7164d949305ea7e14fe9293e4276a3aed2e40bf46ff87565379fba60b71e57092afb970c096442d74f1bcd902e5d987f15e03d844e00a9c34b08d1bc94091e7e0bb40e92504bf12a13b8bc8a84b09ef32947f6394b0f7e07754079e77f7dac507798f3e5ff05b8a8d630f39fe954ef891f17069022e79bb677a73c4f7e4adc7e8ff5ebb48676b4e4d21a6aa9b667dad22e62338d0be0ea51694d2ef289e64a169e6c5b755c729e12aecd0f98e9c8091b86f92fa0315312289beecf266ceb67ebfbe7b1cb657be89fb8ba9f232b413abdae08a20bf7c81b4398e092edb84302a44bac26325fef80bdd0cff5dac1e0b9b59559a3c55c32aee31ef884b648f55bee6a3993eeca7cd840a60fe2fd247430eda76868c776bdee99493496f36c5c0d5af6f89fd0292f8e8fcd11547668b67da74dddad202935f91951960dc256b418d78b3dded73591bd07bae1c620d3b94125020c9bd6b0eeb0cc493858f7a83765a40e94ae875807720be76a35bb5e1784c09090efb4dac017dcd80f3445aacc24053bdb6d550fa85e23710b8a471dfb0490f44dcc658982c31b1e161fdb5abe572bfee732c8c1ea15d0eb993387e604ce6ddb7f5456c0811bb60555ff065939a2587a42b5184449fb2795853647a62b002f4b5c791869a9df2cb91fe757eb2c84299819332193e9465ffa0af6b6948fa5"); + _ = try fmt.hexToBytes(&expected_ss, "a75ad7dfa8fdd4756fe5c0bdcf287e258562c5b3b394bfd949231966dcac02df"); + + const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM1024-P384 test vector 6" { + var seed: [32]u8 = undefined; + var expected_ek: [1665]u8 = undefined; + var randomness: [80]u8 = undefined; + var expected_ct: [1665]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0606060606060606060606060606060606060606060606060606060606060606"); + _ = try fmt.hexToBytes(&expected_ek, "e6db2e7d848e7c8c6ed67c3e8304ac26d3214d361a3086c1c064bde1157745b79bf863b62a043bf31740adb250fa338a7df37dee88830ec31e511c3985c111f299135f9ccd0ab056ceb3476ee730d0735f1ecc36b2779525e184ac19bade2c8b8af42bc4b00ce5239feb4879c15b47f88bac364328c1410c92fb0e15c2c0da79bc6b8080d20b9340f346344a69da81931f79aa9232a7d54834fe71ca3e802525f16a345cce38eb3f3ec2c4adb2afe8685fc0c544127559a959074e784598f05dc6c79be84ca742f775c377cc0ecc36b8d00976b64c19821cd580aacc4a8f27841f6374bcd59b094e94ad0e1a576f6508a7308ea6cab2584a7ef50b887d8807aa76460de35d8dbb1768c335e10b05ed2a4d9ce83920fca30a00714b6aabc4e6823ad2af6fda9fda50b908a2a1f956589cdcbed50c460e3aa21511620569593c80774e7966b793639a616cca6c8f0bf5356e05ceeb27292e76b15ec82f70aa4a8afc3aa24b887d92b4c2ea81d9d1c10bc1210ab2b644c1a35a990c035ba07095a7e0569c3b4c39bd100762c6ba6fd9c0b3978b22211f6129a8dccc5032283bcac01b25141c982808c1cb11e112819ff558faa9396bb77cfdda8085a602981889cd272e56850e0e2355c0989a9ae38d2c546662a5cce84520c88973e01205dec9c6f523b34c10055d6bab3fe63864337fc6058540aa49216996c48b1d3473bc94aca4586a21e92093dc8204a1d651fcd03608b368a17c6182c52b437b7db0fc2426c03c21684962f633f2e05e293a095d40a5f5558fcb26303c8b72820115b324519e61cec83953ef3a1e8361a719a4cdcda41ef5eb89961554bc326da195bf8c2ab944c368533ac86de9b23e13951c8867e35b6fa933a432682ac365ba2aa7a529b6871d728ced34418ad58f8469972722a1a159ba04972162671815f36739723fc54768874029bc3584ee292c5c58beffa0bb51282850fc6a73fb6483eb1c224ac0ed2c1321eb42f976644340c994b2c55c035aa5c0c8c60964f263b02be9b3d6b87038722f2cf741b265b7fcba6bfe203291a09564938bca82ce69492c831a0cbe986739b54a8004bb4c5b7d0ed471f5627c67350a2d5069c80c04d335c75f4083818c6cf8a04d855b11c2c6743eac9d1d947efee59a34461f4cc0c9f1a78cfe8c883417480c3c725b958207b35b3885129fcc08719292e27491903567b3a009ab6b5f38015abbd03fe7b5ccf6b70d53b77e131640ddd37bae220b60c15a83f638e5f92d897476573c2bd5d7092a60cd42124abf32197385a1f90435be101216e81261906d2e599c2f698b029c193c17760417b436ba86fb0a41bd37ab93a37a462346cae3a65437b26fc54df4580439e22ee71c6ac82765aa7acd5b136d6889a2dc136791cb6492f7c0e655ad4ee0b3627a2cb1b8992069c6accaa9fbc5c1a098250fc148b23c3e1487bedba4a4d59722c56a9f95fc9d7234274071a16f5b5875892da1691e3be71bb017b6f97623ca01204f970eb588270c68a08f67607498122ceca637b90e0b3743e6783a0c08579433a83f0272cf863917f757ef1a18b5bba14046696dd0a473188c5dd70ce7f39d6c1123e2241843e002446145b5cc61804950038b6e4f7727d2c5043db32d445c4d0a4756fc91cc27d9330b09b8ff8c8561475b1ae3051b84343e21b3ae25029837bd48a12c95e76eeaf09011a72d378c8a0eb4c9f396ac00ec1811bc9399c987c34a3ef0777e5f575c4c227f8883a66cb43b3db75494ec0060169dc69973fec3cfd9f27d048979d48cc188668fa7729f16d489b7a73e6ef0bcfb31a41ad8179752253d38348226687f489f4d7569e74325c1e8246cfa6847b35072b553981c0b3f566d6f449f3a80a1a8534eec3136489103bfd55c3cc929e49730de9a34c89a3028336dffdc2e6df7b2aea1c43cc835530a6b99b2372556a20fa078b5c80232d36068120074707948b062b289a5d7618b74d65a7ad2b6b743048466438de17a9e571db54630c4ba881aeccdbfd45c4818b01e0240218ccb1aba0fad273899817869409f7409b77c3a2693597740921648c5669d788c479cb7fc8a743bd23228c02753ea6191523d09180d0bdc944ee37ab0e83d39d5802cd20e21c8ccab7033320cadc2104e29bc4d1612a38638cd39f299a0b95caafe5fc95956d82859b1f37ce95d3fb88d0244137561cd922cc4046f4356c2e3e6e9aaf6243a71de6c76f1c63106efae0a85abc53039d3b5d9a8e32ee03fb7abb085f9c304b8405192ce3c9508e104def48d030e57e6cc3ec1eafa408dec210645a6243de6a6c4f593c29fce358ba48539929ef3c584e5ca42af8f"); + _ = try fmt.hexToBytes(&randomness, "6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a"); + _ = try fmt.hexToBytes(&expected_ct, "aa5a25b8315b9e6c940207124c6f2ceb59a295b7683fd6762d91b7ac37f593fffd172954d708d937d99801708a7c9ab15d5fae5111ff6584c845a405376bafd33cfbb120247e010b9e82a2eb5fa7097882eb54ea99b37f5612aa95eb830fca30301e9f7e5ce1cc0e3fbd39c3ecc3cbb9b1662c8018c6039d07aae9e32d1a768f72c659b8f98af17a8180077c5918acf645d355d29a8ef0937ee354909ba30bbae355d84f954f6a909dbff2f69512960885e60e6a9da86011af4e1402be1e3fb8e83f26b7454de4fb64b9724d90ef8f5b7213acdd079dfd75e8b742ee3d161404f0b600e5906baade188d3bc192842dfcc3693709f8d3b0dc692874c7c454256004d66843ab5ee32e9c61f62b8984a28c333804af2a028dc20b9ba5785d2342112e2534480972c65a3a547bb856b8e9d348701e67f7fac37322714032415b4ad524b7fddf623501467470bacb0b79f815d3ef0f9e2237f23e601acbf3b56725bba4f158fef519fe53d94e27149a658119f6305887189c1c0f655558ddb98a1778e6b1a5deac60651bb97ca4313e1d45742f0dd0dec3b28b369ca52eb87257b37d9a50cfd825880ebe2774808be2ba9325c928ff7c2da2c9d46dec148e682d174608615da0261ba4d138b0fce3d0bf2911df0133fcfa5e1c78c419b5c4f9124d20a89a7d61e0cb2ae397e83fac851c34a058392f8df965085b7b935e98f94b1e14230b060b3df8b533d0d028b75db559b65a9d37e4158cbf9a51881c7644d56d25cff7ebce0d5b4aa43fcb01cb15b138d469d8db30eb7b72133bf2a815f65b96e1077e03715547f0093240f8c2618304b3a3ecc33396a6104b167636b9adc65e8d5ba70a9fe7323d369083f51a284d7d21d47fcb393e4fee816c36b4d46bc1239caa431c01dcfc87b865c9ce69cc2dbfd263671eb5e093c144717d07f645741b85ac5d0a214389ad1b958bdfe7f45204f49648a21494941f482c626e7af0fabdce53e76dd7ae501c50decad7203113482eaa55a4fe29ab979604a1a67ad0f446c5ba998e48abce37d387102594843f86104229c995aacfa59cd0491c621ef2abb03b75ed090545bef7f875a32aa630dc056d45e5389aab9e441ab89a3b33a651e420cc9e992ec474c7ec37842e8a0633f9fda5e39cc975575077850710ffe0db9fd220408d98efdbe501025c05345440437d7213d5523aef7d5c283778d218811c7cf11def4b665b9a62b699d1a3ce33a7c247a5e99e2ddf9c9a4b06d1ecf27c0a57b18d17d5990b2cd310629d4a7faa2343a66d6a40c45442899d5fb20e6d236692e605d2a30b535ca70518258438f7eb38b9589e3681c552cd174f88c3e729d50381299919485c3ec3a5a86da59f375304d4867b26ffb7ee194b3b1f15330cc9bfc4dabdd59446e85e4f1b168d1c05d14ae55087e1fe353205f1e873d4750cb0c425f94b822aa1d54b1f1a6bb7ed1009e19084d97aad29066a5b453211423969aab9ff456444e8ee80d37b59698bf807156e4f404d8f3d99aba1230f25cb5155105d2249e581b122abe7c8bf62b3938665acb49caa6be426ce44f9c018b59b97290a46f0978e110f8d2d07fec0d972a5d0ff0e9f56d0f55a7d7f8d11600332877a114451575101d18907083d4760b861eab94bfa67e5f58ba8883dfec7df4632178073322ca7ac66dd2b44ce73c3b410861071f166c888078c61c9dee4f810e5c0278e4ee53abb395966d82002d09d2a127ac44351a6a8ca45dedc05e4b3c45b64b855fcba017b96de8bc128c74f4569a3da57fc7d1e91d51a9d495045e203c863a2ee3711eec0d28989b03a43402b125f752f8f3dffb8b2f0eb043b2d1342633563c07b32857e487b5bac705045e43c8ecaa261e21887022203990b58ed87eea1ba73f46f69e483cec4567f285bf1e0a2d9f0e6c68771144410739bffe823b7e8ca2c31bfc381a2d6499667098d065f8e3ab61094baff3a336648ea79454f73aca9f9d45d2ffaf52258e92fa381f2478a6afb403563d9e00dd789de64503dcb08d41dd24dfaccd1babce39b344c5cdb8a3442ee66695eb4521e5f88aee992f2ac5cce42bc1baa45d9a9621b126d7c0576cd48e081b28727484dc4f135257013f3106cd8d3e1ae8cec97f8360922c2cb6c929ab81e20ae1505dba6d5178325640ebcaf0c6ab8ef74740f72a070c7bb548487a89fbecbeabf67e02e2679e3c5e50455914a6caba74acdc6697c2f4c089984587a729fdd6aee5bf96bf2c523beea2eabef56675c505e2cb191ed3428379eee81be9797e045622bfc163fdf6f4d4cc72784e2a47f1804db75d94a278a63952c7e310820983d3fcb118aa0f69567e41a"); + _ = try fmt.hexToBytes(&expected_ss, "8f81b7d72b0c023dbe66df377cfaed177c7516a06650aafec6046410dd0da9b0"); + + const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM1024-P384 test vector 7" { + var seed: [32]u8 = undefined; + var expected_ek: [1665]u8 = undefined; + var randomness: [80]u8 = undefined; + var expected_ct: [1665]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0707070707070707070707070707070707070707070707070707070707070707"); + _ = try fmt.hexToBytes(&expected_ek, "36f2b5d9481ba9714e75c63de35c4d847ab513d440e0ab2a2e42231ff448de283cce31a9b391ac3ecbb29d005dbb819d44b88490d82ebd13a4213052741b3c6f797e89040490430b4246b782c049e556824ed9744295c878773643c57db8ec4c8b6a43f5488e29e509274722bc896371f58ad761c2a747ba00e50b152c4368f8b7500003d50965aa0caa4627337290549d9aa2f23b63e84c7075c98f4a342d8fd4ba96357576ca49d991b98ca497d54a3a4a984d0aea4bd61a187f639957e27b1e69b549c923ad253318f02c2b4931a8c8299d5b8a32038f2bd05b6b10824c08a4f02c9821aa3019a45654dc40574b9cec01a758f2c9e2a94b73d982a671c54cd8ad6ae95c6f3713807aab89162dfa68734b6657aa47212c8a17fd45bbb15a9a5eb40adc0b158caa14659ca60a073d51b1c5ea8992d24b4651581095e4bd1b5151e4f33c7113a32db916af09c43d3062ed113c9d38027ef545cdb1252f34229b45b3317597dd6353e5d32674f02b0f7975ce97cefa1b8b97d1249f5108b1068eb3da77af88ba4dea14346463293260474294cdf77ff10c75e5d9a33c751d5a5a61146917f94a789a770f01500ce3a5b545e6af86608825507ae7cc604ab5718c4481e68a064a420aa853c4d559095c53a01da46004e6c89dd9995847473dc85fba5c11b222377995a90415aba01472357b3f7c524c1d413c07b1c23bf9a331a36c24e4c9edd568bf2b2bb8fb5e4ad613bfa36a9d0c5142e60aa0e5b9e5a48c2952270faa185ca59a24a098ae615fd1678e07fc7d2a727753cc2c74d189771995ed266658cb24b8dcaf067213cf6067e95c4a51b9b55e9c05e4d0c184039d88869b6b1846ac9b31cf59221ff6c5eca2274150cd5873072d8c583a35488d187f4fa1314c6a116db548b5795da2532655da402eb9069b77295205516fa810a6f9aa9af60b51819e28da1ab1e950359a9fd0ca5971c8aab5250d3f7230a07b9244b019b8ea5534e805452b0ac3dac8954b36e97b80e5314759c3886cfb5192b234fd0172d5f565d1ac8465d205bfb55f741c366d425d95e4a4483b84becaa6d5ba48bf9c9c41723c1fe54909c02fa67b62cf6a7c776748934a817c97062907850a86269999b4342c8f9f803da54a8e3079a6d7548114968a48459784b4c6eed326fed305682a39202170367571a95cb8ddeb7bce9c93ab311d656663cc88bcc6c1b2e1fc9c633830d955aef7f019726167d5f5b81c369546083e611b6314f73b3dd90b4079c5d62a6eeaf14ea5426b7551c16b371ecf537bbfe6a0fc577fbe56242dfc9db6a1035305182b6a265bda1c42982d76a59009e5aa546824233c7e60ebb865146b21408d925c2cdd01187ce7732c60643845a3a6b82ae9d8484688931f612fb7dc8d3225b392993463748f90d8689f12464235a607d68ebdb932053b75e25408a7907e03e936da36300b9b3d98f51d7b61afac32b015d3057a55022af2387701c5b04020a4217edff1c62fa25a49c407e0fa18cfd513793b86532524b64b67929727b7482b14e14116c744c4893d6f6931bce982a9c46dc6048ed8e99f3048914d4476f355cb59472cc092805910a8f53aa8dcf939698abb30730bff24be1d49c7626bb439d87621785eef26aa2da7801714c704609fd3955b9d1058dc2052aff8634076bb01426bb0f3c1696bb773f3a920d90e4aa7c839b14b69d9138b1413000aa8f3895dc0a893a6faafc2e7940d62616ed37d46578d6c03505f1588495b3537f95ade1aaee4c1c3dd0a35ead94cd30a5ced265a0842745476a164d9ad12a5aa7e3b55709c1ef6f7357442bbf63291321981d7682cfe480d03c5a12015ba4219b76cfa997736c246d888a65c470e98bc3d574b4d7ac0072b062267bf81a91181f14ba3d202bf99ae47f1cfb564966f3c3582c85ba7c66ed9058a11856730f71807e4191673b4cc324f360cc527a060e73b511ebc10f1ca2bc79318c6c748effccd928277deccb7ba36ad4dacb2b98749c89892aaec7d07c162bb6b7a3c52873993a8b7392b36a86c853494d0150b0d97171e08360b9c3f598b5673c67b145b20781a7a7c16270d2166bf633e861b0fcb6535418a6106a0aff085cdf6e73d837941e823ac064424e388b02473096c8a8d6c816a9311a5ef68897fc92cbe922749dd602e7ccd9a5faff76e5f193bfc19d784de0c826d9eb5b1585ce28204d0fe95ac293d3aacd0dc58f6fc9d801516045da004311ca5a20587611c5c4a513c4c702981b88f3de97bf00bfdf6138bd6ed1a11d3c0d2df7b7b9ebed10ffbb85db1be4abf5e9a62de86dd46530d6a7478fb6805fbd32d4495530ba393d42801"); + _ = try fmt.hexToBytes(&randomness, "6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"); + _ = try fmt.hexToBytes(&expected_ct, "4dc3b02448f339df1362f71a0929acbdfb2a0425f54adc2f98a62f468dfe9f756e898689ffc2684d66e00b15e67d85cbfd059ef9f5f72743dfdaaa99f0668ae422b41bf76584a5bd2fbabf699ea7f56be4b1f75d5859ddecf9555472ad5c56e26eb060316e25efdd57cfd367e459bbbca12ab0e3ef02111606dc4935d9d80ce9eae8348f57df27ae3c575113588e5e311f96ab3497774e0ef1e27e2c5b397028f9888fa82dee054ff4883b98b8e9f01ee8a26f35a967cbaa5c93082e67e6fca4e6bbf9c2c53a9c699642ec2d06f2db513235040a74ef68bc7f601477019bcbd47c19fc7c2edac12a570c9797a81b0d59597b1865a4d904c6ff99d0e7e6b452dfc4ccaa79e4c633079d9c280b52aaff716cd1936c4b56a517069cd1b69b1c9f08dd03403e6765d1c18fc5e3ad219d80a83c16ef440a53cd07221f12b2c4351c0cc22cbfc9a8bd648f7258194faa9f7263c1235d517c43f62fcd896b7c63bfb25d80857d6c3f5fd352221b80e780ce76c7d7a9c573de96f06173f4d9c2d8b8f3ac87e4154934b7884a3103e9fea436224e632c83bd3b07496f2b628ef8198f945de14cfc3a90998475e4a332f5646bb6f5f9b5a944ccbe0631204a110d66a7ca111b9da15245a982c2b63446bc2a2084a26f1d69cbcc68c6d4cf64efce166d4b8a6d9552a3a81999fa270ba3a9e8e7cfb280da4251875824efbb56161f2996e9d2cd6a66980256b41f10704a93d2f4cd87868a6b2967ca92a20a71b8104b5536e014ef837fc78d8dc8ee3a297395aac377b85ecf5393b33aaeddceb1e10c24f24f9480ca4e4ec275f0abdb36124ff7d7c79ecd11b678ea4bc125307e023cd4c3649e49906bface2d2b73250910c1d4cf081038008ec7f0756ca945d3362f5bcb9138e8289f77e0f8e1e54ebd2198ceff11f4ef1b53d0cb028b3cac0bfd0cad0015a1d83413f1929d6a505fc51329ea46c9680786582378724ddd4300e7147ad2b5a1f9221723bfd57c2a2d3a33e7b1cbf50ff99ed27bd1e5f541e9a5bc522685a74c7cf2f749a1ef3de87e069ffc0784e6c19b39168bed86bbcbc4b771b46839c275d0dc767ad1420f56143d031622fb792c020dd29444886eedf3b671b2a3bf875f4b6bb604de6a0dda58d8a794697829ebabc37d1249ec869b46657fbdeaf5dc5da782051107b192382b3c0820b64e0f2ec15083de32369da090b914121e41dac1dd7edfaea4e1ca0c3d98763252bfe365535c42af6460abdf64940a01f6d6ee98d28ded7098b2160a486166ab36fbaf392e57086c2ba71538c6008a9c459ed3bbb0c5340e3a11ac84d6eb2e752ac581b53a62c418f2264a79d7a1ede8861db4a4e7e404038f86229a80e184fe3d7ac24a2bb97146db09e2014d7f665a202edbb88793569f47edd5d13903913c89bdb2f64dac267307dd2db2aace86fe881de213094de8bab534ba01359ad449aa6500de2064ecf29af5b3b86c96883ed2579ebd703a97c3e982747e2c4213c6af9fb78cadd8168b007f79c9b3abc58c83e487ace180e1fb41334bdb1ce9ed54be7eaaa52613c8dd2280a87c94e94f237377a811a440ce59dd98ea59878f1496e8bd0f1b842a5ff1e9368172fbe2c800fa52bd6014d2065c6ccf2a1382fa5ca3097696a1a69a759bdaa4f529a41b70681c9aeddb1488aab7c10e290a0f353ea14004154f4b7c23baf6ed314d2b84a7c760b3df187b5b1470700aae1eb3ea84d3faf246411e282ed5d40790a1a1fc67facf4ffffd8cc6a8cceda432ad04a454bba7d0247b6042e5be5ab2445d5b730ece63c2b336fcae8232db3794d67e0ab3e98e45aebbe634e42c3be695676ec04fd8b013445bb0599a04d43fa26cb4405db6bec6188c8cc94dacfc435ee64e3356b97d45125520964d30772b5d87fc702ce02fa137f2b4c4fcc12e852fc746715d95023903cb3a7e3c2eae8196443ef3b843b979bc29ed63b31d219349a1f21b7328c3dfce4c6362c96f0dafd01f081515232700d00d00f7fea78f47342e52641ad6413d227895c49b7eded1adb3809aeb7cad24bf122269e39d7ae9e35da8f193092d2dd284e88b5bd5cfaef220b6ac9245a063676d3f9d0d3b844d6164fa23dd7cd8c60f80fc5b5e3454ed7748c65b4cf3db68384529251cd68e2dbdb3020e8d73e212f057f2fbb146a845af750fc2fe2a7e26f2e47dbf0c2968712074ae8534c356728f04ecb409f3bf877d3fda4ab6cc03ef31cd88d3804c75fcbd3ade2e41e99d0e0400c563187cb0ad529a1341d48e54d2f5aa141e925fe47cc85329490de157d7cbd77c9216fdfe4e8dc03c3b29966d08237a9db8222fe4bfd74b92d221d80a4aaf59"); + _ = try fmt.hexToBytes(&expected_ss, "0e5a2eb3ae0f3af82978e6a71b5e2a0830850af49d877a0deec5144061ce44f0"); + + const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} + +test "MLKEM1024-P384 test vector 8" { + var seed: [32]u8 = undefined; + var expected_ek: [1665]u8 = undefined; + var randomness: [80]u8 = undefined; + var expected_ct: [1665]u8 = undefined; + var expected_ss: [32]u8 = undefined; + + _ = try fmt.hexToBytes(&seed, "0808080808080808080808080808080808080808080808080808080808080808"); + _ = try fmt.hexToBytes(&expected_ek, "438844d7cbc33abcc0c58337f8e8c084c0795812ba6603a9c64bb47c84acbfd95c148414fe5410427b4f04b1c6b96cbd24958fc7e33387c22dcec51ea94c6c551688ee2981a5e8cacec65748359fcab62adf51bad4338f34b86568b679530cbbf42b475c2909cff88ab126583d80495f05a410f27b6fc3c895d492e3175c8973a18ea53f88a99ad2464a4e19c4caf5a035d77e7f173aa9e4c09f7b595cf5b69af91931d5a58edc9c7dc92ce2347f2537166879cf353c2ec22609a3c3789f80857b207ce860cacff65b504b8795993a2305cbd9e26b14d36b9d24bfa822b0a83643cd8a09f1a22a2a923081083afab30f09b085f55571de75aefae2939a387343fa602255b4ed9392b633c2945807eec74f0b212d0e685ae5075f775b09411a96ffea4d9a091d20c5200b481265150ebda2016bcb3064b08c2c929c0992c338bb58d45724fd2799df75428f7ab6ffb2785de7b66ad0c01033807e8741ba8731fef560e9566359720081a39d8615aaf99bb4dbf335f648b4dcf3991223235ecc1da6460886657e3be2c065c3cc51f30393f42c9baa84d4cc4d0d872512ab42e363acba1594d4769190c444094891c975c74d0baa484b622dc48538264837c3855d00c6f6026fa29106c3669e822b2d719b4c41e550229a145189cf2836594356b0bb9b7a95d69e22c867f314753e8c589be21268a94cfff9506f1112eff38494e6742272a05649592021643546920759b2c96570dbe05345c14cd4d6b112506f92e99948952442fca689c87fa003cd24d2857377668668c1eadc8584bccce5517e605b0730a23e46055e177503c71b44fda56489f10a2051730757caded74932f673f30483ca10c6338ca0efc509b6486bbe33b857b746d8229a14e62f8370bd58c1b0c163a8ffb5411946cfaada15faba918e24cd16d40fdff6b66f8627dddb2c6c3c2b43f48a42986671624a2c8290d9091c9f05cfb63c4d26114cbb6bc8a96c4dd5b77c83c2ba88810bfb346eec477ccf84aecbd4a34891074b331d1cf7b9bb8779a3372d7db423ef79cf734b8bc493bb52ea94536533bab89480ec86eb83214b5c1e77702124b4bb8ff2c71f976d567cce51245d6ff22b1df00bb920b42a05532951371f3c39fed7cd95343f47923a41e6496d938190665eb49b80aed185281ace2191c7c1c7ca8a808f5518b8884984660b8c8477bcbb178ab7f87a0f572436c1c19bc7a731e6a03495422823acb62861777944999180460c1d6573205779cbb3962bb779aeea3c9f5d821befd1b6f8f65504d868d1916794a05abd53b51468b9856130c6c4b81cab8ec393652aec06e7603445b83c06458e51e04bac3cc0a3450d061735be154b7e19299fc70a5fd72e11658e2cf62ff696163e7cc38406ca8fbac345b06c8a27c08f7924b53562e8472ccbc1081bf36bc9fc3e00dc005969691c3acc5a01ada084b5b7888cd03bcaf9da868bc400483755481631d5766a1b873a55d33811b584fb0280973560c5c4a75db01d5da4bc21b08bb0005013ca8972831c17209cbd4222a1f75527949ef30c3f1f7873c4e792f7454fa6a9173fc67cb66c08789985633282372038b881bf055862470a470369b00049196682cd8827a691c60e046909048a85047251b7fb2a0f0ac9ed271ffde282db57480c10bcd74890cdf91f7790b0fda7608b6c612ce5c18d30452852c3cb370642621fef811530061cc0f612fcab47ab97a4337674972c4e9542332978499f234f64d8788504031a579ab6a02add3c40366b52388368a60ca0df9a0ade438c23accb062bc586d428582a752cd4767fda155c812c0399574606cf90c009e0a7944dccbe887aa596864a71355626018105f705d0e05075362884b2c2ff929d0fa05fb4771bad5b73b5b8a9695174801087d9f64e17a026c96cb608675fb8174e74226e120c2199dc2eff362a45206b1b4a26ab511aa875ac8df8bea946c305023812ecc888227759b03aa2c260fc7b965657c2bed35ce3f82f10a2b863f65467291d4b996c2f30af4c5469292782353970e4549e180a94fdfb24a0636384e02b5a861252ec5a1acb3b0396bfdd241e3522a49f526fdf9a5647d7cd7cf27bfd3796f138616cc3a5d163071a63a83da2a8fbd7c0f020565e46b3c6182fc21462abb7605f387ccaa15c5ad115d428a8f75faf9577f754b4872cc55aa3f67683ac6830636f25cf04c77e9f4dd5fa8af50d958361b98902ee569f7c67efdd4b15aef42b7b018872346ae3d0d4f2af556401d3142b85233cf6f6a118b60c9317edf492881d1f2b651e057f202f662a54f7044ffa61b781f8c35fff2e86267ff0b8525ac13e4bf4a12e"); + _ = try fmt.hexToBytes(&randomness, "6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c"); + _ = try fmt.hexToBytes(&expected_ct, "4aaedad0befe99ae3e9d21c745135279dbafa79e9935f328ecbb3258c6dc66557da90d2ada312b9b5b113b47f1dab9de69f14e6421d336d525bd4098288854d6ea2e449af19d702cb5f22ce8d6da820b4cb76a2e5b93ab390706dbc7570a9dc6f103928db508227b37c32a00ca4b25623396ffbdbf95703203ebfef5b07a450591792fd0adbb1277655fbc908ba0952758b74610f8152d8e59bb74e2f76dcd29a530c01aa3ee35689d16ba790d3b84dc4eab52d60388eaa807a06be5d86a473fb55eff6c70e73edc73f8b6c0ec7e6b472d5a3b82f1eb6ec508f1c12d58f42f870af9173da7555b080be6a53233c0a6954d7f5501b0c522c69bb5853c6147ec2cc74e5a333d641fa130a63373497f844c16113aa7a14d8edb0097137710730d03ab6950a4a61d6659991bc70b9703f2ee670e5bb1986a9471f9c211a0ec8b38405a487b6ea425b598478caca583e3b6f968b73a72d34a81af674009c8a9c294269869c6d695982d4ba517646cd045db6e33d89bc91724608d5c7ee67e24e0613ed0c1c00e4eef02122994d6197b7da3fcd3590d42365d6b138f09e1c61eed7f73d630a96f5a392c3033cd02d823b8dde7d52e7444bdb91f76dbb4dd0c8c9c081dea1c81cfe138d15d06af32136668658b9118a065d4203911c1ed7a3ccf5f02355de1191ffdb02de1d0b3c1585f0ab81aacd405ec25b62f116b9a951f57d780a4156143cb813edad47d41408a89daa1edd5a0f4d4a80598a739f6ef0a16e8b502b9408603ce5615b632b1aa8d0940b7f04029b06ff019271f90452667c054813afdce2c5a10583913b37c01800dbb8cb4c8f7fa182079a2ac609c5209e8f9727f4edd0825e8ddbbb696f3ab76621dbef8f6df51a34cb9179ad3cb6de31a4552206ed8089c69439fdf5137012158d33bc97cd8185e94c24cc7303fcc9e801df3fb3b8f4fe268bdc50137cc1eaa1723bed666d0aae9e452e166a356d04c84c65d19f8ebddc51bba49c85866dce77a4f9193bf6b238f1ea886ffc44db55e0458391f9a252d1c20ed1921ed378b1e246a490b6221ea73db863c9bd04090a557481a24fdd75b12799d042a0e4c929e5570d41d7f562e90a314d3044daceee81cffa37ab5cb1083559bb321948437d9a5caff4562302f22f77754f834379b72e461958cf62bec4f1bcee846501b08aba0a11ca10d41dfcb04267ecfa0372896ba35acf9983b96c20fa5a0b9b2a824af911a0678c0cb6110a2ce520ee10bf32efd72b1487b48ed9689d02def24567bcfdb76cdb17d31f540e715424b2a37c5c6ee44eb951737e3718ee01b95a9eef71b7d73d7d101a3e53c9073d360fa5bb340a3e14a06cb875c66f22c6791fd3ad7f720069874c77d7ccac01f13d870acd3055f0fce01a8529e8c058e1fba29dc2387927be0c8e95de7c70fd945ddb289288b9d7d7aa5be60504ec16c8392984784715dad292c1887d7cbb2809dfd45431c820fb28085036d4c903da826c26a141645fdd1834f6ea5fa9d87023129cc6467b25902d9fdd441c7a60ffeb5280f97a05e28bbe4e8702b101ab501cf3a186519979dd7681363a877dea4aa16fcedfa55893fd69e0f4cf7be703921805e0eb6047109808d174473ebeca08f795537a8621a5cb555f2b63e763d2e7cdebe9da4cac208f737d1c86732aee5bcc40b6b469e4c5a00b5f82494ac09626beeb21925719d07cb6bc65c2d00bf18f270403db32f151818dd8a2c3f9712a02691fcd3f82e8a1c8f7c90c5dde688a3135448025c7cebc2046fedd6e920075eb2debb5804ccaed5b66955b4c4606d7d52bcbf9937e21a7bc2f35d4bd6f98986127cbb6ce68f27b88a4d0b6c3e7f97216bf500af9ab3654c278e95dee865750937662ead1d807388acc004cfb4f737c32c4ab8719e15473d128f5ae4b4ca4c0b3348d811c348e9d4fd64e74350f4eac0de6dc3ad94793e3ffeea1abf89ef586b13f93bbf176d5d6e99df043a118a183eee4d66069c18d24f5a27c1777b2e30501d64658c5bb490259b15ad7c1d07a5bc9a73f6fe1f9176a3622f207eb941be7c736bfaf356ab4280c29f9735cdc6d37f489c9dfe1fbbcb3a67206aa22d221214603d4a9bb9f32e93b01b7595cee7156d939a0b63df1d89d4a603594314127f7c751bc28215ed5963045ba3e186e429cb08165fec5fab493a7c890e29279a3265b9055cf605508f1681a3f904e68f85580d097533d64a56cfc76d712e42729b87f4c28353d317eb8c157e2a920e2f350b47387f86e8dc86a14e6e4cfbbc73f8c02d6fef675f6e74605203b670fe50f33a7b8bc670cbb6d0ced5ada15cf8e436e0e1a55c9ebc67ce0a8fb93754"); + _ = try fmt.hexToBytes(&expected_ss, "3fa279b00ab2798d2d70a2578ea2c76539cbea4bd86d1aa09e92bf0cc40e6626"); + + const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); + try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); + + const enc_result = try kp.public_key.encapsDeterministic(&randomness); + try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); + + const dec_ss = try kp.secret_key.decaps(&enc_result.ciphertext); + try testing.expectEqualSlices(u8, &expected_ss, &dec_ss); +} diff --git a/lib/std/crypto/kangarootwelve.zig b/lib/std/crypto/kangarootwelve.zig index 08adb3ba0b3d..8fb9d9a6fb75 100644 --- a/lib/std/crypto/kangarootwelve.zig +++ b/lib/std/crypto/kangarootwelve.zig @@ -1,9 +1,10 @@ -const std = @import("std"); const builtin = @import("builtin"); + +const std = @import("std"); const crypto = std.crypto; const Allocator = std.mem.Allocator; const Io = std.Io; -const Thread = std.Thread; +const assert = std.debug.assert; const TurboSHAKE128State = crypto.hash.sha3.TurboShake128(0x06); const TurboSHAKE256State = crypto.hash.sha3.TurboShake256(0x06); @@ -598,7 +599,7 @@ inline fn processNLeaves( output: []align(@alignOf(u64)) u8, ) void { const cv_size = Variant.cv_size; - comptime std.debug.assert(cv_size % @sizeOf(u64) == 0); + comptime assert(cv_size % @sizeOf(u64) == 0); if (view.tryGetSlice(j, j + N * chunk_size)) |leaf_data| { var leaf_cvs: [N * cv_size]u8 = undefined; @@ -645,7 +646,7 @@ fn processLeafBatch(comptime Variant: type, ctx: LeafBatchContext) void { j += chunk_len; } - std.debug.assert(cvs_offset == ctx.output_cvs.len); + assert(cvs_offset == ctx.output_cvs.len); } /// Helper to process N leaves in SIMD and absorb CVs into state @@ -841,7 +842,7 @@ fn ktMultiThreaded( total_len: usize, output: []u8, ) !void { - comptime std.debug.assert(bytes_per_batch % (optimal_vector_len * chunk_size) == 0); + comptime assert(bytes_per_batch % (optimal_vector_len * chunk_size) == 0); const cv_size = Variant.cv_size; const StateType = Variant.StateType; @@ -883,6 +884,7 @@ fn ktMultiThreaded( var pending_cv_lens: [256]usize = .{0} ** 256; var select: Select = .init(io, select_buf); + defer select.cancel(); var batches_spawned: usize = 0; var next_to_process: usize = 0; @@ -901,7 +903,7 @@ fn ktMultiThreaded( batches_spawned += 1; } - const result = select.wait() catch unreachable; + const result = try select.await(); const batch = result.batch; const slot = batch.batch_idx % max_concurrent; @@ -925,7 +927,7 @@ fn ktMultiThreaded( } } - select.group.wait(io); + assert(select.outstanding == 0); } if (has_partial_leaf) { @@ -1337,6 +1339,11 @@ test "KT128 sequential and parallel produce same output for small inputs" { } test "KT128 sequential and parallel produce same output for large inputs" { + if (true) { + // https://codeberg.org/ziglang/zig/issues/30676 + return error.SkipZigTest; + } + const allocator = std.testing.allocator; const io = std.testing.io; @@ -1372,6 +1379,11 @@ test "KT128 sequential and parallel produce same output for large inputs" { } test "KT128 sequential and parallel produce same output for many random lengths" { + if (true) { + // https://codeberg.org/ziglang/zig/issues/30676 + return error.SkipZigTest; + } + const allocator = std.testing.allocator; const io = std.testing.io; diff --git a/lib/std/crypto/ml_dsa.zig b/lib/std/crypto/ml_dsa.zig index 9a699e543975..5132899c487d 100644 --- a/lib/std/crypto/ml_dsa.zig +++ b/lib/std/crypto/ml_dsa.zig @@ -2019,12 +2019,9 @@ fn MLDSAImpl(comptime p: Params) type { secret_key: SecretKey, /// Generate a new random key pair. - /// This uses the system's cryptographically secure random number generator. - /// - /// `crypto.random.bytes` must be supported by the target. - pub fn generate() KeyPair { + pub fn generate(io: std.Io) KeyPair { var seed: [Self.seed_length]u8 = undefined; - crypto.random.bytes(&seed); + io.random(&seed); return generateDeterministic(seed) catch unreachable; } @@ -3198,8 +3195,9 @@ test "ML-DSA-87 KAT test vector 0" { } test "KeyPair API - generate and sign" { + const io = std.testing.io; // Test the new KeyPair API with random generation - const kp = MLDSA44.KeyPair.generate(); + const kp = MLDSA44.KeyPair.generate(io); const msg = "Test message for KeyPair API"; // Sign with deterministic mode (no noise) @@ -3222,8 +3220,9 @@ test "KeyPair API - generateDeterministic" { } test "KeyPair API - fromSecretKey" { + const io = std.testing.io; // Generate a key pair - const kp1 = MLDSA44.KeyPair.generate(); + const kp1 = MLDSA44.KeyPair.generate(io); // Derive public key from secret key const kp2 = try MLDSA44.KeyPair.fromSecretKey(kp1.secret_key); @@ -3235,8 +3234,9 @@ test "KeyPair API - fromSecretKey" { } test "Signature verification with noise" { + const io = std.testing.io; // Test signing with randomness (hedged signatures) - const kp = MLDSA65.KeyPair.generate(); + const kp = MLDSA65.KeyPair.generate(io); const msg = "Message to be signed with randomness"; // Create some noise @@ -3250,8 +3250,9 @@ test "Signature verification with noise" { } test "Signature verification failure" { + const io = std.testing.io; // Test that invalid signatures are rejected - const kp = MLDSA44.KeyPair.generate(); + const kp = MLDSA44.KeyPair.generate(io); const msg = "Original message"; const sig = try kp.sign(msg, null); diff --git a/lib/std/crypto/ml_kem.zig b/lib/std/crypto/ml_kem.zig index 9badac5d793f..468be166d087 100644 --- a/lib/std/crypto/ml_kem.zig +++ b/lib/std/crypto/ml_kem.zig @@ -244,32 +244,41 @@ fn Kyber(comptime p: Params) type { /// Size of a serialized representation of the key, in bytes. pub const encoded_length = InnerPk.encoded_length; - /// Generates a shared secret, and encapsulates it for the public key. - /// If `seed` is `null`, a random seed is used. This is recommended. - /// If `seed` is set, encapsulation is deterministic. - pub fn encaps(pk: PublicKey, seed_: ?[encaps_seed_length]u8) EncapsulatedSecret { + /// Generates a shared secret, encapsulated for the public key, + /// using random bytes. + /// + /// This is recommended over `encapsDeterministic`. + pub fn encaps(pk: PublicKey, io: std.Io) EncapsulatedSecret { var m: [inner_plaintext_length]u8 = undefined; + io.random(&m); + return encapsInner(pk, &m); + } - if (seed_) |seed| { - if (p.ml_kem) { - @memcpy(&m, &seed); - } else { - // m = H(seed) - sha3.Sha3_256.hash(&seed, &m, .{}); - } + /// Generates a shared secret, encapsulated for the public key, + /// using the provided seed. + /// + /// Calling `encaps` instead is recommended. + pub fn encapsDeterministic(pk: PublicKey, seed: *const [encaps_seed_length]u8) EncapsulatedSecret { + var m: [inner_plaintext_length]u8 = undefined; + if (p.ml_kem) { + @memcpy(&m, seed); } else { - crypto.random.bytes(&m); + // m = H(seed) + sha3.Sha3_256.hash(seed, &m, .{}); } + return encapsInner(pk, &m); + } + fn encapsInner(pk: PublicKey, m: *[inner_plaintext_length]u8) EncapsulatedSecret { // (K', r) = G(m ‖ H(pk)) var kr: [inner_plaintext_length + h_length]u8 = undefined; var g = sha3.Sha3_512.init(.{}); - g.update(&m); + g.update(m); g.update(&pk.hpk); g.final(&kr); // c = innerEncrypt(pk, m, r) - const ct = pk.pk.encrypt(&m, kr[32..64]); + const ct = pk.pk.encrypt(m, kr[32..64]); if (p.ml_kem) { return EncapsulatedSecret{ @@ -329,17 +338,19 @@ fn Kyber(comptime p: Params) type { // ct' = innerEnc(pk, m', r') const ct2 = sk.pk.encrypt(&m2, kr2[32..64]); - // Compute H(ct) and put in the second slot of kr2 which will be (K'', H(ct)). - sha3.Sha3_256.hash(ct, kr2[32..], .{}); - - // Replace K'' by z in the first slot of kr2 if ct ≠ ct'. - cmov(32, kr2[0..32], sk.z, ctneq(ciphertext_length, ct.*, ct2)); - if (p.ml_kem) { - // ML-KEM: K = K''/z + // ML-KEM: K = K'' if ct == ct', else K = J(z || c) per FIPS 203 + var k_bar: [shared_length]u8 = undefined; + var j = sha3.Shake256.init(.{}); + j.update(&sk.z); + j.update(ct); + j.squeeze(&k_bar); + cmov(shared_length, kr2[0..shared_length], k_bar, ctneq(ciphertext_length, ct.*, ct2)); return kr2[0..shared_length].*; } else { // Kyber: K = KDF(K''/z ‖ H(c)) + sha3.Sha3_256.hash(ct, kr2[32..], .{}); + cmov(32, kr2[0..32], sk.z, ctneq(ciphertext_length, ct.*, ct2)); var ss: [shared_length]u8 = undefined; sha3.Shake256.hash(&kr2, &ss, .{}); return ss; @@ -396,10 +407,10 @@ fn Kyber(comptime p: Params) type { } /// Generate a new, random key pair. - pub fn generate() KeyPair { + pub fn generate(io: std.Io) KeyPair { var random_seed: [seed_length]u8 = undefined; while (true) { - crypto.random.bytes(&random_seed); + io.random(&random_seed); return generateDeterministic(random_seed) catch { @branchHint(.unlikely); continue; @@ -1632,15 +1643,15 @@ test "Test happy flow" { } inline for (modes) |mode| { for (0..10) |i| { - seed[0] = @as(u8, @intCast(i)); + seed[0] = @intCast(i); const kp = try mode.KeyPair.generateDeterministic(seed); const sk = try mode.SecretKey.fromBytes(&kp.secret_key.toBytes()); try testing.expectEqual(sk, kp.secret_key); const pk = try mode.PublicKey.fromBytes(&kp.public_key.toBytes()); try testing.expectEqual(pk, kp.public_key); for (0..10) |j| { - seed[1] = @as(u8, @intCast(j)); - const e = pk.encaps(seed[0..32].*); + seed[1] = @intCast(j); + const e = pk.encapsDeterministic(seed[0..32]); try testing.expectEqual(e.shared_secret, try sk.decaps(&e.ciphertext)); } } @@ -1693,7 +1704,7 @@ fn testNistKat(mode: type, hash: []const u8) !void { g2.fill(kseed[32..64]); g2.fill(&eseed); const kp = try mode.KeyPair.generateDeterministic(kseed); - const e = kp.public_key.encaps(eseed); + const e = kp.public_key.encapsDeterministic(&eseed); const ss2 = try kp.secret_key.decaps(&e.ciphertext); try testing.expectEqual(ss2, e.shared_secret); try fw.writer.print("pk = {X}\n", .{&kp.public_key.toBytes()}); diff --git a/lib/std/crypto/pcurves/p256.zig b/lib/std/crypto/pcurves/p256.zig index aa9226ae0d91..4746061e0206 100644 --- a/lib/std/crypto/pcurves/p256.zig +++ b/lib/std/crypto/pcurves/p256.zig @@ -122,8 +122,8 @@ pub const P256 = struct { } /// Return a random point. - pub fn random() P256 { - const n = scalar.random(.little); + pub fn random(io: std.Io) P256 { + const n = scalar.random(io, .little); return basePoint.mul(n, .little) catch unreachable; } diff --git a/lib/std/crypto/pcurves/p256/scalar.zig b/lib/std/crypto/pcurves/p256/scalar.zig index bd071f4b8ba4..cd31d5e10fc8 100644 --- a/lib/std/crypto/pcurves/p256/scalar.zig +++ b/lib/std/crypto/pcurves/p256/scalar.zig @@ -68,8 +68,8 @@ pub fn sub(a: CompressedScalar, b: CompressedScalar, endian: std.builtin.Endian) } /// Return a random scalar -pub fn random(endian: std.builtin.Endian) CompressedScalar { - return Scalar.random().toBytes(endian); +pub fn random(io: std.Io, endian: std.builtin.Endian) CompressedScalar { + return Scalar.random(io).toBytes(endian); } /// A scalar in unpacked representation. @@ -170,10 +170,10 @@ pub const Scalar = struct { } /// Return a random scalar < L. - pub fn random() Scalar { + pub fn random(io: std.Io) Scalar { var s: [48]u8 = undefined; while (true) { - crypto.random.bytes(&s); + io.random(&s); const n = Scalar.fromBytes48(s, .little); if (!n.isZero()) { return n; diff --git a/lib/std/crypto/pcurves/p384.zig b/lib/std/crypto/pcurves/p384.zig index 61632f61edf4..0dbfdc67f159 100644 --- a/lib/std/crypto/pcurves/p384.zig +++ b/lib/std/crypto/pcurves/p384.zig @@ -122,8 +122,8 @@ pub const P384 = struct { } /// Return a random point. - pub fn random() P384 { - const n = scalar.random(.little); + pub fn random(io: std.Io) P384 { + const n = scalar.random(io, .little); return basePoint.mul(n, .little) catch unreachable; } diff --git a/lib/std/crypto/pcurves/p384/scalar.zig b/lib/std/crypto/pcurves/p384/scalar.zig index 6ea25f214a45..19e94c4b4205 100644 --- a/lib/std/crypto/pcurves/p384/scalar.zig +++ b/lib/std/crypto/pcurves/p384/scalar.zig @@ -63,8 +63,8 @@ pub fn sub(a: CompressedScalar, b: CompressedScalar, endian: std.builtin.Endian) } /// Return a random scalar -pub fn random(endian: std.builtin.Endian) CompressedScalar { - return Scalar.random().toBytes(endian); +pub fn random(io: std.Io, endian: std.builtin.Endian) CompressedScalar { + return Scalar.random(io).toBytes(endian); } /// A scalar in unpacked representation. @@ -159,10 +159,10 @@ pub const Scalar = struct { } /// Return a random scalar < L. - pub fn random() Scalar { + pub fn random(io: std.Io) Scalar { var s: [64]u8 = undefined; while (true) { - crypto.random.bytes(&s); + io.random(&s); const n = Scalar.fromBytes64(s, .little); if (!n.isZero()) { return n; diff --git a/lib/std/crypto/pcurves/secp256k1.zig b/lib/std/crypto/pcurves/secp256k1.zig index c891f414f5c7..1c1caae19aae 100644 --- a/lib/std/crypto/pcurves/secp256k1.zig +++ b/lib/std/crypto/pcurves/secp256k1.zig @@ -175,8 +175,8 @@ pub const Secp256k1 = struct { } /// Return a random point. - pub fn random() Secp256k1 { - const n = scalar.random(.little); + pub fn random(io: std.Io) Secp256k1 { + const n = scalar.random(io, .little); return basePoint.mul(n, .little) catch unreachable; } diff --git a/lib/std/crypto/pcurves/secp256k1/scalar.zig b/lib/std/crypto/pcurves/secp256k1/scalar.zig index 132325026f30..d79d2a23053f 100644 --- a/lib/std/crypto/pcurves/secp256k1/scalar.zig +++ b/lib/std/crypto/pcurves/secp256k1/scalar.zig @@ -68,8 +68,8 @@ pub fn sub(a: CompressedScalar, b: CompressedScalar, endian: std.builtin.Endian) } /// Return a random scalar -pub fn random(endian: std.builtin.Endian) CompressedScalar { - return Scalar.random().toBytes(endian); +pub fn random(io: std.Io, endian: std.builtin.Endian) CompressedScalar { + return Scalar.random(io).toBytes(endian); } /// A scalar in unpacked representation. @@ -170,10 +170,10 @@ pub const Scalar = struct { } /// Return a random scalar < L. - pub fn random() Scalar { + pub fn random(io: std.Io) Scalar { var s: [48]u8 = undefined; while (true) { - crypto.random.bytes(&s); + io.random(&s); const n = Scalar.fromBytes48(s, .little); if (!n.isZero()) { return n; diff --git a/lib/std/crypto/pcurves/tests/p256.zig b/lib/std/crypto/pcurves/tests/p256.zig index 7da68044f81c..3ca12fa24169 100644 --- a/lib/std/crypto/pcurves/tests/p256.zig +++ b/lib/std/crypto/pcurves/tests/p256.zig @@ -5,8 +5,9 @@ const testing = std.testing; const P256 = @import("../p256.zig").P256; test "p256 ECDH key exchange" { - const dha = P256.scalar.random(.little); - const dhb = P256.scalar.random(.little); + const io = testing.io; + const dha = P256.scalar.random(io, .little); + const dhb = P256.scalar.random(io, .little); const dhA = try P256.basePoint.mul(dha, .little); const dhB = try P256.basePoint.mul(dhb, .little); const shareda = try dhA.mul(dhb, .little); @@ -66,28 +67,32 @@ test "p256 test vectors - doubling" { } test "p256 compressed sec1 encoding/decoding" { - const p = P256.random(); + const io = testing.io; + const p = P256.random(io); const s = p.toCompressedSec1(); const q = try P256.fromSec1(&s); try testing.expect(p.equivalent(q)); } test "p256 uncompressed sec1 encoding/decoding" { - const p = P256.random(); + const io = testing.io; + const p = P256.random(io); const s = p.toUncompressedSec1(); const q = try P256.fromSec1(&s); try testing.expect(p.equivalent(q)); } test "p256 public key is the neutral element" { + const io = testing.io; const n = P256.scalar.Scalar.zero.toBytes(.little); - const p = P256.random(); + const p = P256.random(io); try testing.expectError(error.IdentityElement, p.mul(n, .little)); } test "p256 public key is the neutral element (public verification)" { + const io = testing.io; const n = P256.scalar.Scalar.zero.toBytes(.little); - const p = P256.random(); + const p = P256.random(io); try testing.expectError(error.IdentityElement, p.mulPublic(n, .little)); } diff --git a/lib/std/crypto/pcurves/tests/p384.zig b/lib/std/crypto/pcurves/tests/p384.zig index e51a683136e4..316e8679ad09 100644 --- a/lib/std/crypto/pcurves/tests/p384.zig +++ b/lib/std/crypto/pcurves/tests/p384.zig @@ -5,8 +5,9 @@ const testing = std.testing; const P384 = @import("../p384.zig").P384; test "p384 ECDH key exchange" { - const dha = P384.scalar.random(.little); - const dhb = P384.scalar.random(.little); + const io = testing.io; + const dha = P384.scalar.random(io, .little); + const dhb = P384.scalar.random(io, .little); const dhA = try P384.basePoint.mul(dha, .little); const dhB = try P384.basePoint.mul(dhb, .little); const shareda = try dhA.mul(dhb, .little); @@ -67,7 +68,8 @@ test "p384 test vectors - doubling" { } test "p384 compressed sec1 encoding/decoding" { - const p = P384.random(); + const io = testing.io; + const p = P384.random(io); const s0 = p.toUncompressedSec1(); const s = p.toCompressedSec1(); try testing.expectEqualSlices(u8, s0[1..49], s[1..49]); @@ -76,21 +78,24 @@ test "p384 compressed sec1 encoding/decoding" { } test "p384 uncompressed sec1 encoding/decoding" { - const p = P384.random(); + const io = testing.io; + const p = P384.random(io); const s = p.toUncompressedSec1(); const q = try P384.fromSec1(&s); try testing.expect(p.equivalent(q)); } test "p384 public key is the neutral element" { + const io = testing.io; const n = P384.scalar.Scalar.zero.toBytes(.little); - const p = P384.random(); + const p = P384.random(io); try testing.expectError(error.IdentityElement, p.mul(n, .little)); } test "p384 public key is the neutral element (public verification)" { + const io = testing.io; const n = P384.scalar.Scalar.zero.toBytes(.little); - const p = P384.random(); + const p = P384.random(io); try testing.expectError(error.IdentityElement, p.mulPublic(n, .little)); } diff --git a/lib/std/crypto/pcurves/tests/secp256k1.zig b/lib/std/crypto/pcurves/tests/secp256k1.zig index 0fb2a13cf86a..ff400c032262 100644 --- a/lib/std/crypto/pcurves/tests/secp256k1.zig +++ b/lib/std/crypto/pcurves/tests/secp256k1.zig @@ -5,8 +5,9 @@ const testing = std.testing; const Secp256k1 = @import("../secp256k1.zig").Secp256k1; test "secp256k1 ECDH key exchange" { - const dha = Secp256k1.scalar.random(.little); - const dhb = Secp256k1.scalar.random(.little); + const io = testing.io; + const dha = Secp256k1.scalar.random(io, .little); + const dhb = Secp256k1.scalar.random(io, .little); const dhA = try Secp256k1.basePoint.mul(dha, .little); const dhB = try Secp256k1.basePoint.mul(dhb, .little); const shareda = try dhA.mul(dhb, .little); @@ -15,8 +16,9 @@ test "secp256k1 ECDH key exchange" { } test "secp256k1 ECDH key exchange including public multiplication" { - const dha = Secp256k1.scalar.random(.little); - const dhb = Secp256k1.scalar.random(.little); + const io = testing.io; + const dha = Secp256k1.scalar.random(io, .little); + const dhb = Secp256k1.scalar.random(io, .little); const dhA = try Secp256k1.basePoint.mul(dha, .little); const dhB = try Secp256k1.basePoint.mulPublic(dhb, .little); const shareda = try dhA.mul(dhb, .little); @@ -77,28 +79,32 @@ test "secp256k1 test vectors - doubling" { } test "secp256k1 compressed sec1 encoding/decoding" { - const p = Secp256k1.random(); + const io = testing.io; + const p = Secp256k1.random(io); const s = p.toCompressedSec1(); const q = try Secp256k1.fromSec1(&s); try testing.expect(p.equivalent(q)); } test "secp256k1 uncompressed sec1 encoding/decoding" { - const p = Secp256k1.random(); + const io = testing.io; + const p = Secp256k1.random(io); const s = p.toUncompressedSec1(); const q = try Secp256k1.fromSec1(&s); try testing.expect(p.equivalent(q)); } test "secp256k1 public key is the neutral element" { + const io = testing.io; const n = Secp256k1.scalar.Scalar.zero.toBytes(.little); - const p = Secp256k1.random(); + const p = Secp256k1.random(io); try testing.expectError(error.IdentityElement, p.mul(n, .little)); } test "secp256k1 public key is the neutral element (public verification)" { + const io = testing.io; const n = Secp256k1.scalar.Scalar.zero.toBytes(.little); - const p = Secp256k1.random(); + const p = Secp256k1.random(io); try testing.expectError(error.IdentityElement, p.mulPublic(n, .little)); } diff --git a/lib/std/crypto/salsa20.zig b/lib/std/crypto/salsa20.zig index eb434ed15a36..d47498704d72 100644 --- a/lib/std/crypto/salsa20.zig +++ b/lib/std/crypto/salsa20.zig @@ -533,9 +533,9 @@ pub const SealedBox = struct { /// Encrypt a message `m` for a recipient whose public key is `public_key`. /// `c` must be `seal_length` bytes larger than `m`, so that the required metadata can be added. - pub fn seal(c: []u8, m: []const u8, public_key: [public_length]u8) (WeakPublicKeyError || IdentityElementError)!void { + pub fn seal(io: std.Io, c: []u8, m: []const u8, public_key: [public_length]u8) (WeakPublicKeyError || IdentityElementError)!void { debug.assert(c.len == m.len + seal_length); - var ekp = KeyPair.generate(); + var ekp = KeyPair.generate(io); const nonce = createNonce(ekp.public_key, public_key); c[0..public_length].* = ekp.public_key; try Box.seal(c[Box.public_length..], m, nonce, public_key, ekp.secret_key); @@ -573,29 +573,31 @@ test "(x)salsa20" { } test "xsalsa20poly1305" { + const io = std.testing.io; var msg: [100]u8 = undefined; var msg2: [msg.len]u8 = undefined; var c: [msg.len]u8 = undefined; var key: [XSalsa20Poly1305.key_length]u8 = undefined; var nonce: [XSalsa20Poly1305.nonce_length]u8 = undefined; var tag: [XSalsa20Poly1305.tag_length]u8 = undefined; - crypto.random.bytes(&msg); - crypto.random.bytes(&key); - crypto.random.bytes(&nonce); + io.random(&msg); + io.random(&key); + io.random(&nonce); XSalsa20Poly1305.encrypt(c[0..], &tag, msg[0..], "ad", nonce, key); try XSalsa20Poly1305.decrypt(msg2[0..], c[0..], tag, "ad", nonce, key); } test "xsalsa20poly1305 secretbox" { + const io = std.testing.io; var msg: [100]u8 = undefined; var msg2: [msg.len]u8 = undefined; var key: [XSalsa20Poly1305.key_length]u8 = undefined; var nonce: [Box.nonce_length]u8 = undefined; var boxed: [msg.len + Box.tag_length]u8 = undefined; - crypto.random.bytes(&msg); - crypto.random.bytes(&key); - crypto.random.bytes(&nonce); + io.random(&msg); + io.random(&key); + io.random(&nonce); SecretBox.seal(boxed[0..], msg[0..], nonce, key); try SecretBox.open(msg2[0..], boxed[0..], nonce, key); @@ -604,15 +606,16 @@ test "xsalsa20poly1305 secretbox" { test "xsalsa20poly1305 box" { if (builtin.cpu.has(.riscv, .v) and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/24299 + const io = std.testing.io; var msg: [100]u8 = undefined; var msg2: [msg.len]u8 = undefined; var nonce: [Box.nonce_length]u8 = undefined; var boxed: [msg.len + Box.tag_length]u8 = undefined; - crypto.random.bytes(&msg); - crypto.random.bytes(&nonce); + io.random(&msg); + io.random(&nonce); - const kp1 = Box.KeyPair.generate(); - const kp2 = Box.KeyPair.generate(); + const kp1 = Box.KeyPair.generate(io); + const kp2 = Box.KeyPair.generate(io); try Box.seal(boxed[0..], msg[0..], nonce, kp1.public_key, kp2.secret_key); try Box.open(msg2[0..], boxed[0..], nonce, kp2.public_key, kp1.secret_key); } @@ -620,13 +623,14 @@ test "xsalsa20poly1305 box" { test "xsalsa20poly1305 sealedbox" { if (builtin.cpu.has(.riscv, .v) and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/24299 + const io = std.testing.io; var msg: [100]u8 = undefined; var msg2: [msg.len]u8 = undefined; var boxed: [msg.len + SealedBox.seal_length]u8 = undefined; - crypto.random.bytes(&msg); + io.random(&msg); - const kp = Box.KeyPair.generate(); - try SealedBox.seal(boxed[0..], msg[0..], kp.public_key); + const kp = Box.KeyPair.generate(io); + try SealedBox.seal(io, boxed[0..], msg[0..], kp.public_key); try SealedBox.open(msg2[0..], boxed[0..], kp); } diff --git a/lib/std/crypto/scrypt.zig b/lib/std/crypto/scrypt.zig index 3e994b67e931..913feb4b380e 100644 --- a/lib/std/crypto/scrypt.zig +++ b/lib/std/crypto/scrypt.zig @@ -20,7 +20,7 @@ const Error = pwhash.Error; const max_size = math.maxInt(usize); const max_int = max_size >> 1; -const default_salt_len = 32; +pub const default_salt_len = 32; const default_hash_len = 32; const max_salt_len = 64; const max_hash_len = 64; @@ -358,7 +358,7 @@ const crypt_format = struct { fn intDecode(comptime T: type, src: *const [(@bitSizeOf(T) + 5) / 6]u8) !T { var v: T = 0; for (src, 0..) |x, i| { - const vi = mem.indexOfScalar(u8, &map64, x) orelse return EncodingError.InvalidEncoding; + const vi = mem.findScalar(u8, &map64, x) orelse return EncodingError.InvalidEncoding; v |= @as(T, @intCast(vi)) << @as(math.Log2Int(T), @intCast(i * 6)); } return v; @@ -417,19 +417,31 @@ const PhcFormatHasher = struct { password: []const u8, params: Params, buf: []u8, + io: std.Io, ) HasherError![]const u8 { var salt: [default_salt_len]u8 = undefined; - crypto.random.bytes(&salt); + io.random(&salt); + return createWithSalt(allocator, password, params, buf, &salt); + } + /// Return a deterministic hash of the password encoded as a PHC-format string. + /// Uses the provided salt instead of generating one randomly. + pub fn createWithSalt( + allocator: mem.Allocator, + password: []const u8, + params: Params, + buf: []u8, + salt: *const [default_salt_len]u8, + ) HasherError![]const u8 { var hash: [default_hash_len]u8 = undefined; - try kdf(allocator, &hash, password, &salt, params); + try kdf(allocator, &hash, password, salt, params); return phc_format.serialize(HashResult{ .alg_id = alg_id, .ln = params.ln, .r = params.r, .p = params.p, - .salt = try BinValue(max_salt_len).fromSlice(&salt), + .salt = try BinValue(max_salt_len).fromSlice(salt), .hash = try BinValue(max_hash_len).fromSlice(&hash), }, buf); } @@ -466,10 +478,23 @@ const CryptFormatHasher = struct { password: []const u8, params: Params, buf: []u8, + io: std.Io, ) HasherError![]const u8 { var salt_bin: [default_salt_len]u8 = undefined; - crypto.random.bytes(&salt_bin); - const salt = crypt_format.saltFromBin(salt_bin.len, salt_bin); + io.random(&salt_bin); + return createWithSalt(allocator, password, params, buf, &salt_bin); + } + + /// Return a deterministic hash of the password encoded into the modular crypt format. + /// Uses the provided salt instead of generating one randomly. + pub fn createWithSalt( + allocator: mem.Allocator, + password: []const u8, + params: Params, + buf: []u8, + salt_bin: *const [default_salt_len]u8, + ) HasherError![]const u8 { + const salt = crypt_format.saltFromBin(salt_bin.len, salt_bin.*); var hash: [default_hash_len]u8 = undefined; try kdf(allocator, &hash, password, &salt, params); @@ -515,11 +540,28 @@ pub fn strHash( password: []const u8, options: HashOptions, out: []u8, + io: std.Io, ) Error![]const u8 { const allocator = options.allocator orelse return Error.AllocatorRequired; switch (options.encoding) { - .phc => return PhcFormatHasher.create(allocator, password, options.params, out), - .crypt => return CryptFormatHasher.create(allocator, password, options.params, out), + .phc => return PhcFormatHasher.create(allocator, password, options.params, out, io), + .crypt => return CryptFormatHasher.create(allocator, password, options.params, out, io), + } +} + +/// Compute a deterministic hash of a password using the scrypt key derivation function. +/// The function returns a string that includes all the parameters required for verification. +/// Uses the provided salt instead of generating one randomly. +pub fn strHashWithSalt( + password: []const u8, + options: HashOptions, + out: []u8, + salt: *const [default_salt_len]u8, +) Error![]const u8 { + const allocator = options.allocator orelse return Error.AllocatorRequired; + switch (options.encoding) { + .phc => return PhcFormatHasher.createWithSalt(allocator, password, options.params, out, salt), + .crypt => return CryptFormatHasher.createWithSalt(allocator, password, options.params, out, salt), } } @@ -631,6 +673,7 @@ test "password hashing (crypt format)" { if (!run_long_tests) return error.SkipZigTest; const alloc = std.testing.allocator; + const io = std.testing.io; const str = "$7$A6....1....TrXs5Zk6s8sWHpQgWDIXTR8kUU3s6Jc3s.DtdS8M2i4$a4ik5hGDN7foMuHOW.cp.CtX01UyCeO0.JAG.AHPpx5"; const password = "Y0!?iQa9M%5ekffW(`"; @@ -638,7 +681,7 @@ test "password hashing (crypt format)" { const params = Params.interactive; var buf: [CryptFormatHasher.pwhash_str_length]u8 = undefined; - const str2 = try CryptFormatHasher.create(alloc, password, params, &buf); + const str2 = try CryptFormatHasher.create(alloc, password, params, &buf, io); try CryptFormatHasher.verify(alloc, str2, password); } @@ -646,6 +689,7 @@ test "strHash and strVerify" { if (!run_long_tests) return error.SkipZigTest; const alloc = std.testing.allocator; + const io = std.testing.io; const password = "testpass"; const params = Params.interactive; @@ -657,6 +701,7 @@ test "strHash and strVerify" { password, .{ .allocator = alloc, .params = params, .encoding = .crypt }, &buf, + io, ); try strVerify(str, password, verify_options); } @@ -665,6 +710,7 @@ test "strHash and strVerify" { password, .{ .allocator = alloc, .params = params, .encoding = .phc }, &buf, + io, ); try strVerify(str, password, verify_options); } @@ -721,3 +767,23 @@ test "kdf fast" { try std.testing.expectEqualSlices(u8, &dk, v.want); } } + +test "strHashWithSalt deterministic" { + const alloc = std.testing.allocator; + const password = "testpass"; + const salt: [default_salt_len]u8 = "0123456789abcdef0123456789abcdef".*; + const params: Params = .{ .ln = 1, .r = 1, .p = 1 }; + + var buf1: [128]u8 = undefined; + var buf2: [128]u8 = undefined; + + const str1 = try strHashWithSalt(password, .{ .allocator = alloc, .params = params, .encoding = .phc }, &buf1, &salt); + const str2 = try strHashWithSalt(password, .{ .allocator = alloc, .params = params, .encoding = .phc }, &buf2, &salt); + try std.testing.expectEqualStrings(str1, str2); + try strVerify(str1, password, .{ .allocator = alloc }); + + const str3 = try strHashWithSalt(password, .{ .allocator = alloc, .params = params, .encoding = .crypt }, &buf1, &salt); + const str4 = try strHashWithSalt(password, .{ .allocator = alloc, .params = params, .encoding = .crypt }, &buf2, &salt); + try std.testing.expectEqualStrings(str3, str4); + try strVerify(str3, password, .{ .allocator = alloc }); +} diff --git a/lib/std/crypto/sha2.zig b/lib/std/crypto/sha2.zig index d32f15f57b3b..86eb9f0440bd 100644 --- a/lib/std/crypto/sha2.zig +++ b/lib/std/crypto/sha2.zig @@ -211,7 +211,7 @@ fn Sha2x32(comptime iv: Iv32, digest_bits: comptime_int) type { s_v[k] = asm ( \\sha256su0.4s %[w0_3], %[w4_7] \\sha256su1.4s %[w0_3], %[w8_11], %[w12_15] - : [w0_3] "=w" (-> V4u32), + : [w0_3] "=&w" (-> V4u32), : [_] "0" (s_v[k - 4]), [w4_7] "w" (s_v[k - 3]), [w8_11] "w" (s_v[k - 2]), diff --git a/lib/std/crypto/timing_safe.zig b/lib/std/crypto/timing_safe.zig index 85767eb0067e..7d9b53c0aaf5 100644 --- a/lib/std/crypto/timing_safe.zig +++ b/lib/std/crypto/timing_safe.zig @@ -180,24 +180,24 @@ pub fn declassify(ptr: anytype) void { } test eql { - const random = std.crypto.random; + const io = std.testing.io; const expect = std.testing.expect; var a: [100]u8 = undefined; var b: [100]u8 = undefined; - random.bytes(a[0..]); - random.bytes(b[0..]); + io.random(&a); + io.random(&b); try expect(!eql([100]u8, a, b)); a = b; try expect(eql([100]u8, a, b)); } test "eql (vectors)" { - const random = std.crypto.random; + const io = std.testing.io; const expect = std.testing.expect; var a: [100]u8 = undefined; var b: [100]u8 = undefined; - random.bytes(a[0..]); - random.bytes(b[0..]); + io.random(&a); + io.random(&b); const v1: @Vector(100, u8) = a; const v2: @Vector(100, u8) = b; try expect(!eql(@Vector(100, u8), v1, v2)); @@ -220,9 +220,10 @@ test compare { } test "add and sub" { + const io = std.testing.io; + const expectEqual = std.testing.expectEqual; const expectEqualSlices = std.testing.expectEqualSlices; - const random = std.crypto.random; const len = 32; var a: [len]u8 = undefined; var b: [len]u8 = undefined; @@ -230,8 +231,8 @@ test "add and sub" { const zero = [_]u8{0} ** len; var iterations: usize = 100; while (iterations != 0) : (iterations -= 1) { - random.bytes(&a); - random.bytes(&b); + io.random(&a); + io.random(&b); const endian = if (iterations % 2 == 0) Endian.big else Endian.little; _ = sub(u8, &a, &b, &c, endian); // a-b _ = add(u8, &c, &b, &c, endian); // (a-b)+b @@ -243,11 +244,11 @@ test "add and sub" { } test classify { - const random = std.crypto.random; + const io = std.testing.io; const expect = std.testing.expect; var secret: [32]u8 = undefined; - random.bytes(&secret); + io.random(&secret); // Input of the hash function is marked as secret classify(&secret); diff --git a/lib/std/crypto/tlcsprng.zig b/lib/std/crypto/tlcsprng.zig deleted file mode 100644 index 9e20de1281c7..000000000000 --- a/lib/std/crypto/tlcsprng.zig +++ /dev/null @@ -1,169 +0,0 @@ -//! Thread-local cryptographically secure pseudo-random number generator. -//! This file has public declarations that are intended to be used internally -//! by the standard library; this namespace is not intended to be exposed -//! directly to standard library users. - -const std = @import("std"); -const builtin = @import("builtin"); -const mem = std.mem; -const native_os = builtin.os.tag; -const posix = std.posix; - -/// We use this as a layer of indirection because global const pointers cannot -/// point to thread-local variables. -pub const interface: std.Random = .{ - .ptr = undefined, - .fillFn = tlsCsprngFill, -}; - -const os_has_fork = @TypeOf(posix.fork) != void; -const os_has_arc4random = builtin.link_libc and (@TypeOf(std.c.arc4random_buf) != void); -const want_fork_safety = os_has_fork and !os_has_arc4random and std.options.crypto_fork_safety; -const maybe_have_wipe_on_fork = builtin.os.isAtLeast(.linux, .{ - .major = 4, - .minor = 14, - .patch = 0, -}) orelse true; - -const Rng = std.Random.DefaultCsprng; - -const Context = struct { - init_state: enum(u8) { uninitialized = 0, initialized, failed }, - rng: Rng, -}; - -var install_atfork_handler = std.once(struct { - // Install the global handler only once. - // The same handler is shared among threads and is inherinted by fork()-ed - // processes. - fn do() void { - const r = std.c.pthread_atfork(null, null, childAtForkHandler); - std.debug.assert(r == 0); - } -}.do); - -threadlocal var wipe_mem: []align(std.heap.page_size_min) u8 = &[_]u8{}; - -fn tlsCsprngFill(_: *anyopaque, buffer: []u8) void { - if (os_has_arc4random) { - // arc4random is already a thread-local CSPRNG. - return std.c.arc4random_buf(buffer.ptr, buffer.len); - } - // Allow applications to decide they would prefer to have every call to - // std.crypto.random always make an OS syscall, rather than rely on an - // application implementation of a CSPRNG. - if (std.options.crypto_always_getrandom) { - return std.options.cryptoRandomSeed(buffer); - } - - if (wipe_mem.len == 0) { - // Not initialized yet. - if (want_fork_safety and maybe_have_wipe_on_fork) { - // Allocate a per-process page, madvise operates with page - // granularity. - wipe_mem = posix.mmap( - null, - @sizeOf(Context), - posix.PROT.READ | posix.PROT.WRITE, - .{ .TYPE = .PRIVATE, .ANONYMOUS = true }, - -1, - 0, - ) catch { - // Could not allocate memory for the local state, fall back to - // the OS syscall. - return std.options.cryptoRandomSeed(buffer); - }; - // The memory is already zero-initialized. - } else { - // Use a static thread-local buffer. - const S = struct { - threadlocal var buf: Context align(std.heap.page_size_min) = .{ - .init_state = .uninitialized, - .rng = undefined, - }; - }; - wipe_mem = mem.asBytes(&S.buf); - } - } - const ctx: *Context = @ptrCast(wipe_mem.ptr); - - switch (ctx.init_state) { - .uninitialized => { - if (!want_fork_safety) { - return initAndFill(buffer); - } - - if (maybe_have_wipe_on_fork) wof: { - // Qemu user-mode emulation ignores any valid/invalid madvise - // hint and returns success. Check if this is the case by - // passing bogus parameters, we expect EINVAL as result. - if (posix.madvise(wipe_mem.ptr, 0, 0xffffffff)) |_| { - break :wof; - } else |_| {} - - if (posix.madvise(wipe_mem.ptr, wipe_mem.len, posix.MADV.WIPEONFORK)) |_| { - return initAndFill(buffer); - } else |_| {} - } - - if (std.Thread.use_pthreads) { - return setupPthreadAtforkAndFill(buffer); - } - - // Since we failed to set up fork safety, we fall back to always - // calling getrandom every time. - ctx.init_state = .failed; - return std.options.cryptoRandomSeed(buffer); - }, - .initialized => { - return fillWithCsprng(buffer); - }, - .failed => { - if (want_fork_safety) { - return std.options.cryptoRandomSeed(buffer); - } else { - unreachable; - } - }, - } -} - -fn setupPthreadAtforkAndFill(buffer: []u8) void { - install_atfork_handler.call(); - return initAndFill(buffer); -} - -fn childAtForkHandler() callconv(.c) void { - // The atfork handler is global, this function may be called after - // fork()-ing threads that never initialized the CSPRNG context. - if (wipe_mem.len == 0) return; - std.crypto.secureZero(u8, wipe_mem); -} - -fn fillWithCsprng(buffer: []u8) void { - const ctx: *Context = @ptrCast(wipe_mem.ptr); - return ctx.rng.fill(buffer); -} - -pub fn defaultRandomSeed(buffer: []u8) void { - posix.getrandom(buffer) catch @panic("getrandom() failed to provide entropy"); -} - -fn initAndFill(buffer: []u8) void { - var seed: [Rng.secret_seed_length]u8 = undefined; - // Because we panic on getrandom() failing, we provide the opportunity - // to override the default seed function. This also makes - // `std.crypto.random` available on freestanding targets, provided that - // the `std.options.cryptoRandomSeed` function is provided. - std.options.cryptoRandomSeed(&seed); - - const ctx: *Context = @ptrCast(wipe_mem.ptr); - ctx.rng = Rng.init(seed); - std.crypto.secureZero(u8, &seed); - - // This is at the end so that accidental recursive dependencies result - // in stack overflows instead of invalid random data. - ctx.init_state = .initialized; - - return fillWithCsprng(buffer); -} diff --git a/lib/std/crypto/tls.zig b/lib/std/crypto/tls.zig index c24283469c68..2f9099c28f54 100644 --- a/lib/std/crypto/tls.zig +++ b/lib/std/crypto/tls.zig @@ -32,7 +32,6 @@ const std = @import("../std.zig"); const Tls = @This(); -const net = std.net; const mem = std.mem; const crypto = std.crypto; const assert = std.debug.assert; @@ -134,6 +133,8 @@ pub const ExtensionType = enum(u16) { signature_algorithms_cert = 50, /// RFC 8446 key_share = 51, + /// RFC 9000 + quic_transport_parameters = 57, _, }; diff --git a/lib/std/crypto/tls/Client.zig b/lib/std/crypto/tls/Client.zig index f6e334af8efc..44a73c344a57 100644 --- a/lib/std/crypto/tls/Client.zig +++ b/lib/std/crypto/tls/Client.zig @@ -109,7 +109,7 @@ pub const Options = struct { read_buffer: []u8, /// Cryptographically secure random bytes. The pointer is not captured; data is only /// read during `init`. - entropy: *const [176]u8, + entropy: *const [entropy_len]u8, /// Current time according to the wall clock / calendar, in seconds. realtime_now_seconds: i64, @@ -130,6 +130,8 @@ pub const Options = struct { allow_truncation_attacks: bool = false, /// Populated when `error.TlsAlert` is returned from `init`. alert: ?*tls.Alert = null, + + pub const entropy_len = 240; }; const InitError = error{ @@ -200,7 +202,7 @@ pub fn init(input: *Reader, output: *Writer, options: Options) InitError!Client var server_hello_rand: [32]u8 = undefined; const legacy_session_id = options.entropy[32..64].*; - var key_share = KeyShare.init(options.entropy[64..176].*) catch |err| switch (err) { + var key_share = KeyShare.init(options.entropy[64..240]) catch |err| switch (err) { // Only possible to happen if the seed is all zeroes. error.IdentityElement => return error.InsufficientEntropy, }; @@ -1158,7 +1160,7 @@ fn readIndirect(c: *Client) Reader.Error!usize { P.AEAD.decrypt(cleartext, ciphertext, auth_tag, ad, nonce, pv.server_key) catch return failRead(c, error.TlsBadRecordMac); // TODO use scalar, non-slice version - const msg = mem.trimRight(u8, cleartext, "\x00"); + const msg = mem.trimEnd(u8, cleartext, "\x00"); break :cleartext .{ msg.len - 1, @enumFromInt(msg[msg.len - 1]) }; }, .tls_1_2 => { @@ -1330,12 +1332,12 @@ const KeyShare = struct { crypto.dh.X25519.shared_length, ); - fn init(seed: [112]u8) error{IdentityElement}!KeyShare { + fn init(seed: *const [176]u8) error{IdentityElement}!KeyShare { return .{ - .ml_kem768_kp = .generate(), - .secp256r1_kp = try .generateDeterministic(seed[0..32].*), - .secp384r1_kp = try .generateDeterministic(seed[32..80].*), - .x25519_kp = try .generateDeterministic(seed[80..112].*), + .ml_kem768_kp = try .generateDeterministic(seed[0..64].*), + .secp256r1_kp = try .generateDeterministic(seed[64..96].*), + .secp384r1_kp = try .generateDeterministic(seed[96..144].*), + .x25519_kp = try .generateDeterministic(seed[144..176].*), .sk_buf = undefined, .sk_len = 0, }; diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 29c0731f4e6e..8b76e307a154 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -1,14 +1,13 @@ const std = @import("std.zig"); const Io = std.Io; const Writer = std.Io.Writer; -const tty = std.Io.tty; const math = std.math; const mem = std.mem; const posix = std.posix; const fs = std.fs; const testing = std.testing; const Allocator = mem.Allocator; -const File = std.fs.File; +const File = std.Io.File; const windows = std.os.windows; const builtin = @import("builtin"); @@ -41,7 +40,7 @@ pub const cpu_context = @import("debug/cpu_context.zig"); /// pub fn deinit(si: *SelfInfo, gpa: Allocator) void; /// /// /// Returns the symbol and source location of the instruction at `address`. -/// pub fn getSymbol(si: *SelfInfo, gpa: Allocator, address: usize) SelfInfoError!Symbol; +/// pub fn getSymbol(si: *SelfInfo, gpa: Allocator, io: Io, address: usize) SelfInfoError!Symbol; /// /// Returns a name for the "module" (e.g. shared library or executable image) containing `address`. /// pub fn getModuleName(si: *SelfInfo, gpa: Allocator, address: usize) SelfInfoError![]const u8; /// @@ -60,7 +59,7 @@ pub const cpu_context = @import("debug/cpu_context.zig"); /// }; /// /// Only required if `can_unwind == true`. Unwinds a single stack frame, returning the frame's /// /// return address, or 0 if the end of the stack has been reached. -/// pub fn unwindFrame(si: *SelfInfo, gpa: Allocator, context: *UnwindContext) SelfInfoError!usize; +/// pub fn unwindFrame(si: *SelfInfo, gpa: Allocator, io: Io, context: *UnwindContext) SelfInfoError!usize; /// ``` pub const SelfInfo = if (@hasDecl(root, "debug") and @hasDecl(root.debug, "SelfInfo")) root.debug.SelfInfo @@ -262,53 +261,54 @@ pub const sys_can_stack_trace = switch (builtin.cpu.arch) { else => true, }; -/// Allows the caller to freely write to stderr until `unlockStdErr` is called. +/// Allows the caller to freely write to stderr until `unlockStderr` is called. /// /// During the lock, any `std.Progress` information is cleared from the terminal. -pub fn lockStdErr() void { - std.Progress.lockStdErr(); -} - -pub fn unlockStdErr() void { - std.Progress.unlockStdErr(); -} - -/// Allows the caller to freely write to stderr until `unlockStderrWriter` is called. /// -/// During the lock, any `std.Progress` information is cleared from the terminal. +/// The lock is recursive, so it is valid for the same thread to call +/// `lockStderr` multiple times, allowing the panic handler to safely +/// dump the stack trace and panic message even if the mutex was held at the +/// panic site. /// -/// The lock is recursive, so it is valid for the same thread to call `lockStderrWriter` multiple -/// times. The primary motivation is that this allows the panic handler to safely dump the stack -/// trace and panic message even if the mutex was held at the panic site. +/// The returned `Writer` does not need to be manually flushed: flushing is +/// performed automatically when the matching `unlockStderr` call occurs. /// -/// The returned `Writer` does not need to be manually flushed: flushing is performed automatically -/// when the matching `unlockStderrWriter` call occurs. -pub fn lockStderrWriter(buffer: []u8) struct { *Writer, tty.Config } { - const global = struct { - var conf: ?tty.Config = null; +/// This is a low-level debugging primitive that bypasses the `Io` interface, +/// writing directly to stderr using the most basic syscalls available. This +/// function does not switch threads, switch stacks, or suspend. +/// +/// Alternatively, use the higher-level `Io.lockStderr` to integrate with the +/// application's chosen `Io` implementation. +pub fn lockStderr(buffer: []u8) Io.LockedStderr { + const io = std.Options.debug_io; + const prev = io.swapCancelProtection(.blocked); + defer _ = io.swapCancelProtection(prev); + return io.lockStderr(buffer, null) catch |err| switch (err) { + error.Canceled => unreachable, // Cancel protection enabled above. }; - const w = std.Progress.lockStderrWriter(buffer); - // The stderr lock also locks access to `global.conf`. - if (global.conf == null) { - global.conf = .detect(.stderr()); - } - return .{ w, global.conf.? }; } -pub fn unlockStderrWriter() void { - std.Progress.unlockStderrWriter(); +pub fn unlockStderr() void { + const io = std.Options.debug_io; + io.unlockStderr(); } -/// Print to stderr, silently returning on failure. Intended for use in "printf -/// debugging". Use `std.log` functions for proper logging. +/// Writes to stderr, ignoring errors. +/// +/// This is a low-level debugging primitive that bypasses the `Io` interface, +/// writing directly to stderr using the most basic syscalls available. This +/// function does not switch threads, switch stacks, or suspend. /// /// Uses a 64-byte buffer for formatted printing which is flushed before this /// function returns. +/// +/// Alternatively, use the higher-level `std.log` or `Io.lockStderr` to +/// integrate with the application's chosen `Io` implementation. pub fn print(comptime fmt: []const u8, args: anytype) void { var buffer: [64]u8 = undefined; - const bw, _ = lockStderrWriter(&buffer); - defer unlockStderrWriter(); - nosuspend bw.print(fmt, args) catch return; + const stderr = lockStderr(&buffer); + defer unlockStderr(); + stderr.file_writer.interface.print(fmt, args) catch return; } /// Marked `inline` to propagate a comptime-known error to callers. @@ -323,43 +323,44 @@ pub inline fn getSelfDebugInfo() !*SelfInfo { /// Tries to print a hexadecimal view of the bytes, unbuffered, and ignores any error returned. /// Obtains the stderr mutex while dumping. pub fn dumpHex(bytes: []const u8) void { - const bw, const ttyconf = lockStderrWriter(&.{}); - defer unlockStderrWriter(); - dumpHexFallible(bw, ttyconf, bytes) catch {}; + const stderr = lockStderr(&.{}).terminal(); + defer unlockStderr(); + dumpHexFallible(stderr, bytes) catch {}; } /// Prints a hexadecimal view of the bytes, returning any error that occurs. -pub fn dumpHexFallible(bw: *Writer, ttyconf: tty.Config, bytes: []const u8) !void { +pub fn dumpHexFallible(t: Io.Terminal, bytes: []const u8) !void { + const w = t.writer; var chunks = mem.window(u8, bytes, 16, 16); while (chunks.next()) |window| { // 1. Print the address. const address = (@intFromPtr(bytes.ptr) + 0x10 * (std.math.divCeil(usize, chunks.index orelse bytes.len, 16) catch unreachable)) - 0x10; - try ttyconf.setColor(bw, .dim); + try t.setColor(.dim); // We print the address in lowercase and the bytes in uppercase hexadecimal to distinguish them more. // Also, make sure all lines are aligned by padding the address. - try bw.print("{x:0>[1]} ", .{ address, @sizeOf(usize) * 2 }); - try ttyconf.setColor(bw, .reset); + try w.print("{x:0>[1]} ", .{ address, @sizeOf(usize) * 2 }); + try t.setColor(.reset); // 2. Print the bytes. for (window, 0..) |byte, index| { - try bw.print("{X:0>2} ", .{byte}); - if (index == 7) try bw.writeByte(' '); + try w.print("{X:0>2} ", .{byte}); + if (index == 7) try w.writeByte(' '); } - try bw.writeByte(' '); + try w.writeByte(' '); if (window.len < 16) { var missing_columns = (16 - window.len) * 3; if (window.len < 8) missing_columns += 1; - try bw.splatByteAll(' ', missing_columns); + try w.splatByteAll(' ', missing_columns); } // 3. Print the characters. for (window) |byte| { if (std.ascii.isPrint(byte)) { - try bw.writeByte(byte); + try w.writeByte(byte); } else { // Related: https://github.com/ziglang/zig/issues/7600 - if (ttyconf == .windows_api) { - try bw.writeByte('.'); + if (t.mode == .windows_api) { + try w.writeByte('.'); continue; } @@ -367,24 +368,25 @@ pub fn dumpHexFallible(bw: *Writer, ttyconf: tty.Config, bytes: []const u8) !voi // We don't want to do this for all control codes because most control codes apart from // the ones that Zig has escape sequences for are likely not very useful to print as symbols. switch (byte) { - '\n' => try bw.writeAll("␊"), - '\r' => try bw.writeAll("␍"), - '\t' => try bw.writeAll("␉"), - else => try bw.writeByte('.'), + '\n' => try w.writeAll("␊"), + '\r' => try w.writeAll("␍"), + '\t' => try w.writeAll("␉"), + else => try w.writeByte('.'), } } } - try bw.writeByte('\n'); + try w.writeByte('\n'); } } test dumpHexFallible { + const gpa = testing.allocator; const bytes: []const u8 = &.{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01, 0x12, 0x13 }; - var aw: Writer.Allocating = .init(std.testing.allocator); + var aw: Writer.Allocating = .init(gpa); defer aw.deinit(); - try dumpHexFallible(&aw.writer, .no_color, bytes); - const expected = try std.fmt.allocPrint(std.testing.allocator, + try dumpHexFallible(.{ .writer = &aw.writer, .mode = .no_color }, bytes); + const expected = try std.fmt.allocPrint(gpa, \\{x:0>[2]} 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF .."3DUfw........ \\{x:0>[2]} 01 12 13 ... \\ @@ -393,8 +395,8 @@ test dumpHexFallible { @intFromPtr(bytes.ptr) + 16, @sizeOf(usize) * 2, }); - defer std.testing.allocator.free(expected); - try std.testing.expectEqualStrings(expected, aw.written()); + defer gpa.free(expected); + try testing.expectEqualStrings(expected, aw.written()); } /// The pointer through which a `cpu_context.Native` is received from callers of stack tracing logic. @@ -409,7 +411,7 @@ pub const CpuContextPtr = if (cpu_context.Native == noreturn) noreturn else *con /// away, and in fact the optimizer is able to use the assertion in its /// heuristics. /// -/// Inside a test block, it is best to use the `std.testing` module rather than +/// Inside a test block, it is best to use the `testing` module rather than /// this function, because this function may not detect a test failure in /// ReleaseFast and ReleaseSmall mode. Outside of a test block, this assert /// function is the correct function to use. @@ -483,10 +485,7 @@ const use_trap_panic = switch (builtin.zig_backend) { }; /// Dumps a stack trace to standard error, then aborts. -pub fn defaultPanic( - msg: []const u8, - first_trace_addr: ?usize, -) noreturn { +pub fn defaultPanic(msg: []const u8, first_trace_addr: ?usize) noreturn { @branchHint(.cold); if (use_trap_panic) @trap(); @@ -522,7 +521,7 @@ pub fn defaultPanic( } @trap(); }, - .cuda, .amdhsa => std.posix.abort(), + .cuda, .amdhsa => std.process.abort(), .plan9 => { var status: [std.os.plan9.ERRMAX]u8 = undefined; const len = @min(msg.len, status.len - 1); @@ -533,6 +532,10 @@ pub fn defaultPanic( else => {}, } + // Don't try to cancel during a panic. No need to re-enable cancelation, + // because the panic handler doesn't return. + _ = std.Options.debug_io.swapCancelProtection(.blocked); + if (enable_segfault_handler) { // If a segfault happens while panicking, we want it to actually segfault, not trigger // the handler. @@ -546,26 +549,27 @@ pub fn defaultPanic( _ = panicking.fetchAdd(1, .seq_cst); trace: { - const stderr, const tty_config = lockStderrWriter(&.{}); - defer unlockStderrWriter(); + const stderr = lockStderr(&.{}).terminal(); + defer unlockStderr(); + const writer = stderr.writer; if (builtin.single_threaded) { - stderr.print("panic: ", .{}) catch break :trace; + writer.print("panic: ", .{}) catch break :trace; } else { const current_thread_id = std.Thread.getCurrentId(); - stderr.print("thread {d} panic: ", .{current_thread_id}) catch break :trace; + writer.print("thread {d} panic: ", .{current_thread_id}) catch break :trace; } - stderr.print("{s}\n", .{msg}) catch break :trace; + writer.print("{s}\n", .{msg}) catch break :trace; if (@errorReturnTrace()) |t| if (t.index > 0) { - stderr.writeAll("error return context:\n") catch break :trace; - writeStackTrace(t, stderr, tty_config) catch break :trace; - stderr.writeAll("\nstack trace:\n") catch break :trace; + writer.writeAll("error return context:\n") catch break :trace; + writeStackTrace(t, stderr) catch break :trace; + writer.writeAll("\nstack trace:\n") catch break :trace; }; writeCurrentStackTrace(.{ .first_address = first_trace_addr orelse @returnAddress(), .allow_unsafe_unwind = true, // we're crashing anyway, give it our all! - }, stderr, tty_config) catch break :trace; + }, stderr) catch break :trace; } waitForOtherThreadToFinishPanicking(); @@ -575,12 +579,13 @@ pub fn defaultPanic( // A panic happened while trying to print a previous panic message. // We're still holding the mutex but that's fine as we're going to // call abort(). - fs.File.stderr().writeAll("aborting due to recursive panic\n") catch {}; + const stderr = lockStderr(&.{}).terminal(); + stderr.writer.writeAll("aborting due to recursive panic\n") catch {}; }, else => {}, // Panicked while printing the recursive panic message. } - posix.abort(); + std.process.abort(); } /// Must be called only after adding 1 to `panicking`. There are three callsites. @@ -621,13 +626,16 @@ pub noinline fn captureCurrentStackTrace(options: StackUnwindOptions, addr_buf: var it: StackIterator = .init(options.context); defer it.deinit(); if (!it.stratOk(options.allow_unsafe_unwind)) return empty_trace; + + const io = std.Options.debug_io; + var total_frames: usize = 0; var index: usize = 0; var wait_for = options.first_address; // Ideally, we would iterate the whole stack so that the `index` in the returned trace was // indicative of how many frames were skipped. However, this has a significant runtime cost // in some cases, so at least for now, we don't do that. - while (index < addr_buf.len) switch (it.next()) { + while (index < addr_buf.len) switch (it.next(io)) { .switch_to_fp => if (!it.stratOk(options.allow_unsafe_unwind)) break, .end => break, .frame => |ret_addr| { @@ -653,37 +661,36 @@ pub noinline fn captureCurrentStackTrace(options: StackUnwindOptions, addr_buf: /// Write the current stack trace to `writer`, annotated with source locations. /// /// See `captureCurrentStackTrace` to capture the trace addresses into a buffer instead of printing. -pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, writer: *Writer, tty_config: tty.Config) Writer.Error!void { - var threaded: Io.Threaded = .init_single_threaded; - const io = threaded.ioBasic(); - +pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, t: Io.Terminal) Writer.Error!void { + const writer = t.writer; if (!std.options.allow_stack_tracing) { - tty_config.setColor(writer, .dim) catch {}; + t.setColor(.dim) catch {}; try writer.print("Cannot print stack trace: stack tracing is disabled\n", .{}); - tty_config.setColor(writer, .reset) catch {}; + t.setColor(.reset) catch {}; return; } const di_gpa = getDebugInfoAllocator(); const di = getSelfDebugInfo() catch |err| switch (err) { error.UnsupportedTarget => { - tty_config.setColor(writer, .dim) catch {}; + t.setColor(.dim) catch {}; try writer.print("Cannot print stack trace: debug info unavailable for target\n", .{}); - tty_config.setColor(writer, .reset) catch {}; + t.setColor(.reset) catch {}; return; }, }; var it: StackIterator = .init(options.context); defer it.deinit(); if (!it.stratOk(options.allow_unsafe_unwind)) { - tty_config.setColor(writer, .dim) catch {}; + t.setColor(.dim) catch {}; try writer.print("Cannot print stack trace: safe unwind unavailable for target\n", .{}); - tty_config.setColor(writer, .reset) catch {}; + t.setColor(.reset) catch {}; return; } var total_frames: usize = 0; var wait_for = options.first_address; var printed_any_frame = false; - while (true) switch (it.next()) { + const io = std.Options.debug_io; + while (true) switch (it.next(io)) { .switch_to_fp => |unwind_error| { switch (StackIterator.fp_usability) { .useless, .unsafe => {}, @@ -700,31 +707,31 @@ pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, writer: *Wri error.Unexpected => "unexpected error", }; if (it.stratOk(options.allow_unsafe_unwind)) { - tty_config.setColor(writer, .dim) catch {}; + t.setColor(.dim) catch {}; try writer.print( "Unwind error at address `{s}:0x{x}` ({s}), remaining frames may be incorrect\n", .{ module_name, unwind_error.address, caption }, ); - tty_config.setColor(writer, .reset) catch {}; + t.setColor(.reset) catch {}; } else { - tty_config.setColor(writer, .dim) catch {}; + t.setColor(.dim) catch {}; try writer.print( "Unwind error at address `{s}:0x{x}` ({s}), stopping trace early\n", .{ module_name, unwind_error.address, caption }, ); - tty_config.setColor(writer, .reset) catch {}; + t.setColor(.reset) catch {}; return; } }, .end => break, .frame => |ret_addr| { if (total_frames > 10_000) { - tty_config.setColor(writer, .dim) catch {}; + t.setColor(.dim) catch {}; try writer.print( "Stopping trace after {d} frames (large frame count may indicate broken debug info)\n", .{total_frames}, ); - tty_config.setColor(writer, .reset) catch {}; + t.setColor(.reset) catch {}; return; } total_frames += 1; @@ -734,7 +741,7 @@ pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, writer: *Wri } // `ret_addr` is the return address, which is *after* the function call. // Subtract 1 to get an address *in* the function call for a better source location. - try printSourceAtAddress(di_gpa, io, di, writer, ret_addr -| StackIterator.ra_call_offset, tty_config); + try printSourceAtAddress(di_gpa, io, di, t, ret_addr -| StackIterator.ra_call_offset); printed_any_frame = true; }, }; @@ -742,8 +749,8 @@ pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, writer: *Wri } /// A thin wrapper around `writeCurrentStackTrace` which writes to stderr and ignores write errors. pub fn dumpCurrentStackTrace(options: StackUnwindOptions) void { - const stderr, const tty_config = lockStderrWriter(&.{}); - defer unlockStderrWriter(); + const stderr = lockStderr(&.{}).terminal(); + defer unlockStderr(); writeCurrentStackTrace(.{ .first_address = a: { if (options.first_address) |a| break :a a; @@ -752,33 +759,30 @@ pub fn dumpCurrentStackTrace(options: StackUnwindOptions) void { }, .context = options.context, .allow_unsafe_unwind = options.allow_unsafe_unwind, - }, stderr, tty_config) catch |err| switch (err) { + }, stderr) catch |err| switch (err) { error.WriteFailed => {}, }; } pub const FormatStackTrace = struct { stack_trace: StackTrace, - tty_config: tty.Config, + terminal_mode: Io.Terminal.Mode = .no_color, - pub fn format(context: @This(), writer: *Io.Writer) Io.Writer.Error!void { - try writer.writeAll("\n"); - try writeStackTrace(&context.stack_trace, writer, context.tty_config); + pub fn format(fst: FormatStackTrace, writer: *Writer) Writer.Error!void { + try writer.writeByte('\n'); + try writeStackTrace(&fst.stack_trace, .{ .writer = writer, .mode = fst.terminal_mode }); } }; /// Write a previously captured stack trace to `writer`, annotated with source locations. -pub fn writeStackTrace(st: *const StackTrace, writer: *Writer, tty_config: tty.Config) Writer.Error!void { +pub fn writeStackTrace(st: *const StackTrace, t: Io.Terminal) Writer.Error!void { + const writer = t.writer; if (!std.options.allow_stack_tracing) { - tty_config.setColor(writer, .dim) catch {}; + t.setColor(.dim) catch {}; try writer.print("Cannot print stack trace: stack tracing is disabled\n", .{}); - tty_config.setColor(writer, .reset) catch {}; + t.setColor(.reset) catch {}; return; } - // We use an independent Io implementation here in case there was a problem - // with the application's Io implementation itself. - var threaded: Io.Threaded = .init_single_threaded; - const io = threaded.ioBasic(); // Fetch `st.index` straight away. Aside from avoiding redundant loads, this prevents issues if // `st` is `@errorReturnTrace()` and errors are encountered while writing the stack trace. @@ -787,29 +791,30 @@ pub fn writeStackTrace(st: *const StackTrace, writer: *Writer, tty_config: tty.C const di_gpa = getDebugInfoAllocator(); const di = getSelfDebugInfo() catch |err| switch (err) { error.UnsupportedTarget => { - tty_config.setColor(writer, .dim) catch {}; + t.setColor(.dim) catch {}; try writer.print("Cannot print stack trace: debug info unavailable for target\n\n", .{}); - tty_config.setColor(writer, .reset) catch {}; + t.setColor(.reset) catch {}; return; }, }; + const io = std.Options.debug_io; const captured_frames = @min(n_frames, st.instruction_addresses.len); for (st.instruction_addresses[0..captured_frames]) |ret_addr| { // `ret_addr` is the return address, which is *after* the function call. // Subtract 1 to get an address *in* the function call for a better source location. - try printSourceAtAddress(di_gpa, io, di, writer, ret_addr -| StackIterator.ra_call_offset, tty_config); + try printSourceAtAddress(di_gpa, io, di, t, ret_addr -| StackIterator.ra_call_offset); } if (n_frames > captured_frames) { - tty_config.setColor(writer, .bold) catch {}; + t.setColor(.bold) catch {}; try writer.print("({d} additional stack frames skipped...)\n", .{n_frames - captured_frames}); - tty_config.setColor(writer, .reset) catch {}; + t.setColor(.reset) catch {}; } } /// A thin wrapper around `writeStackTrace` which writes to stderr and ignores write errors. pub fn dumpStackTrace(st: *const StackTrace) void { - const stderr, const tty_config = lockStderrWriter(&.{}); - defer unlockStderrWriter(); - writeStackTrace(st, stderr, tty_config) catch |err| switch (err) { + const stderr = lockStderr(&.{}).terminal(); + defer unlockStderr(); + writeStackTrace(st, stderr) catch |err| switch (err) { error.WriteFailed => {}, }; } @@ -960,7 +965,7 @@ const StackIterator = union(enum) { }, }; - fn next(it: *StackIterator) Result { + fn next(it: *StackIterator, io: Io) Result { switch (it.*) { .ctx_first => |context_ptr| { // After the first frame, start actually unwinding. @@ -976,7 +981,7 @@ const StackIterator = union(enum) { .di => |*unwind_context| { const di = getSelfDebugInfo() catch unreachable; const di_gpa = getDebugInfoAllocator(); - const ret_addr = di.unwindFrame(di_gpa, unwind_context) catch |err| { + const ret_addr = di.unwindFrame(di_gpa, io, unwind_context) catch |err| { const pc = unwind_context.pc; const fp = unwind_context.getFp(); it.* = .{ .fp = fp }; @@ -1104,170 +1109,146 @@ pub inline fn stripInstructionPtrAuthCode(ptr: usize) usize { return ptr; } -fn printSourceAtAddress(gpa: Allocator, io: Io, debug_info: *SelfInfo, writer: *Writer, address: usize, tty_config: tty.Config) Writer.Error!void { +fn printSourceAtAddress( + gpa: Allocator, + io: Io, + debug_info: *SelfInfo, + t: Io.Terminal, + address: usize, +) Writer.Error!void { const symbol: Symbol = debug_info.getSymbol(gpa, io, address) catch |err| switch (err) { error.MissingDebugInfo, error.UnsupportedDebugInfo, error.InvalidDebugInfo, => .unknown, error.ReadFailed, error.Unexpected, error.Canceled => s: { - tty_config.setColor(writer, .dim) catch {}; - try writer.print("Failed to read debug info from filesystem, trace may be incomplete\n\n", .{}); - tty_config.setColor(writer, .reset) catch {}; + t.setColor(.dim) catch {}; + try t.writer.print("Failed to read debug info from filesystem, trace may be incomplete\n\n", .{}); + t.setColor(.reset) catch {}; break :s .unknown; }, error.OutOfMemory => s: { - tty_config.setColor(writer, .dim) catch {}; - try writer.print("Ran out of memory loading debug info, trace may be incomplete\n\n", .{}); - tty_config.setColor(writer, .reset) catch {}; + t.setColor(.dim) catch {}; + try t.writer.print("Ran out of memory loading debug info, trace may be incomplete\n\n", .{}); + t.setColor(.reset) catch {}; break :s .unknown; }, }; defer if (symbol.source_location) |sl| gpa.free(sl.file_name); return printLineInfo( - writer, + io, + t, symbol.source_location, address, symbol.name orelse "???", symbol.compile_unit_name orelse debug_info.getModuleName(gpa, address) catch "???", - tty_config, ); } fn printLineInfo( - writer: *Writer, + io: Io, + t: Io.Terminal, source_location: ?SourceLocation, address: usize, symbol_name: []const u8, compile_unit_name: []const u8, - tty_config: tty.Config, ) Writer.Error!void { - nosuspend { - tty_config.setColor(writer, .bold) catch {}; + const writer = t.writer; + t.setColor(.bold) catch {}; - if (source_location) |*sl| { - try writer.print("{s}:{d}:{d}", .{ sl.file_name, sl.line, sl.column }); - } else { - try writer.writeAll("???:?:?"); - } + if (source_location) |*sl| { + try writer.print("{s}:{d}:{d}", .{ sl.file_name, sl.line, sl.column }); + } else { + try writer.writeAll("???:?:?"); + } - tty_config.setColor(writer, .reset) catch {}; - try writer.writeAll(": "); - tty_config.setColor(writer, .dim) catch {}; - try writer.print("0x{x} in {s} ({s})", .{ address, symbol_name, compile_unit_name }); - tty_config.setColor(writer, .reset) catch {}; - try writer.writeAll("\n"); - - // Show the matching source code line if possible - if (source_location) |sl| { - if (printLineFromFile(writer, sl)) { - if (sl.column > 0) { - // The caret already takes one char - const space_needed = @as(usize, @intCast(sl.column - 1)); - - try writer.splatByteAll(' ', space_needed); - tty_config.setColor(writer, .green) catch {}; - try writer.writeAll("^"); - tty_config.setColor(writer, .reset) catch {}; - } - try writer.writeAll("\n"); - } else |_| { - // Ignore all errors; it's a better UX to just print the source location without the - // corresponding line number. The user can always open the source file themselves. + t.setColor(.reset) catch {}; + try writer.writeAll(": "); + t.setColor(.dim) catch {}; + try writer.print("0x{x} in {s} ({s})", .{ address, symbol_name, compile_unit_name }); + t.setColor(.reset) catch {}; + try writer.writeAll("\n"); + + // Show the matching source code line if possible + if (source_location) |sl| { + if (printLineFromFile(io, writer, sl)) { + if (sl.column > 0) { + // The caret already takes one char + const space_needed = @as(usize, @intCast(sl.column - 1)); + + try writer.splatByteAll(' ', space_needed); + t.setColor(.green) catch {}; + try writer.writeAll("^"); + t.setColor(.reset) catch {}; } + try writer.writeAll("\n"); + } else |_| { + // Ignore all errors; it's a better UX to just print the source location without the + // corresponding line number. The user can always open the source file themselves. } } } -fn printLineFromFile(writer: *Writer, source_location: SourceLocation) !void { +fn printLineFromFile(io: Io, writer: *Writer, source_location: SourceLocation) !void { // Allow overriding the target-agnostic source line printing logic by exposing `root.debug.printLineFromFile`. if (@hasDecl(root, "debug") and @hasDecl(root.debug, "printLineFromFile")) { - return root.debug.printLineFromFile(writer, source_location); + return root.debug.printLineFromFile(io, writer, source_location); } // Need this to always block even in async I/O mode, because this could potentially // be called from e.g. the event loop code crashing. - var f = try fs.cwd().openFile(source_location.file_name, .{}); - defer f.close(); - // TODO fstat and make sure that the file has the correct size - - var buf: [4096]u8 = undefined; - var amt_read = try f.read(buf[0..]); - const line_start = seek: { - var current_line_start: usize = 0; - var next_line: usize = 1; - while (next_line != source_location.line) { - const slice = buf[current_line_start..amt_read]; - if (mem.indexOfScalar(u8, slice, '\n')) |pos| { - next_line += 1; - if (pos == slice.len - 1) { - amt_read = try f.read(buf[0..]); - current_line_start = 0; - } else current_line_start += pos + 1; - } else if (amt_read < buf.len) { - return error.EndOfFile; - } else { - amt_read = try f.read(buf[0..]); - current_line_start = 0; - } - } - break :seek current_line_start; - }; - const slice = buf[line_start..amt_read]; - if (mem.indexOfScalar(u8, slice, '\n')) |pos| { - const line = slice[0 .. pos + 1]; - mem.replaceScalar(u8, line, '\t', ' '); - return writer.writeAll(line); - } else { // Line is the last inside the buffer, and requires another read to find delimiter. Alternatively the file ends. - mem.replaceScalar(u8, slice, '\t', ' '); - try writer.writeAll(slice); - while (amt_read == buf.len) { - amt_read = try f.read(buf[0..]); - if (mem.indexOfScalar(u8, buf[0..amt_read], '\n')) |pos| { - const line = buf[0 .. pos + 1]; - mem.replaceScalar(u8, line, '\t', ' '); - return writer.writeAll(line); - } else { - const line = buf[0..amt_read]; - mem.replaceScalar(u8, line, '\t', ' '); - try writer.writeAll(line); - } + const cwd: Io.Dir = .cwd(); + var file = try cwd.openFile(io, source_location.file_name, .{}); + defer file.close(io); + + var buffer: [4096]u8 = undefined; + var file_reader: File.Reader = .init(file, io, &buffer); + var line_index: usize = 0; + const r = &file_reader.interface; + while (true) { + line_index += 1; + if (line_index == source_location.line) { + // TODO delete hard tabs from the language + _ = try r.streamDelimiterEnding(writer, '\n'); + try writer.writeByte('\n'); + return; } - // Make sure printing last line of file inserts extra newline - try writer.writeByte('\n'); + _ = try r.discardDelimiterInclusive('\n'); } } test printLineFromFile { - var aw: Writer.Allocating = .init(std.testing.allocator); + const io = testing.io; + const gpa = testing.allocator; + + var aw: Writer.Allocating = .init(gpa); defer aw.deinit(); const output_stream = &aw.writer; - const allocator = std.testing.allocator; const join = std.fs.path.join; - const expectError = std.testing.expectError; - const expectEqualStrings = std.testing.expectEqualStrings; + const expectError = testing.expectError; + const expectEqualStrings = testing.expectEqualStrings; - var test_dir = std.testing.tmpDir(.{}); + var test_dir = testing.tmpDir(.{}); defer test_dir.cleanup(); // Relies on testing.tmpDir internals which is not ideal, but SourceLocation requires paths. - const test_dir_path = try join(allocator, &.{ ".zig-cache", "tmp", test_dir.sub_path[0..] }); - defer allocator.free(test_dir_path); + const test_dir_path = try join(gpa, &.{ ".zig-cache", "tmp", test_dir.sub_path[0..] }); + defer gpa.free(test_dir_path); // Cases { - const path = try join(allocator, &.{ test_dir_path, "one_line.zig" }); - defer allocator.free(path); - try test_dir.dir.writeFile(.{ .sub_path = "one_line.zig", .data = "no new lines in this file, but one is printed anyway" }); + const path = try join(gpa, &.{ test_dir_path, "one_line.zig" }); + defer gpa.free(path); + try test_dir.dir.writeFile(io, .{ .sub_path = "one_line.zig", .data = "no new lines in this file, but one is printed anyway" }); - try expectError(error.EndOfFile, printLineFromFile(output_stream, .{ .file_name = path, .line = 2, .column = 0 })); + try expectError(error.EndOfStream, printLineFromFile(io, output_stream, .{ .file_name = path, .line = 2, .column = 0 })); - try printLineFromFile(output_stream, .{ .file_name = path, .line = 1, .column = 0 }); + try printLineFromFile(io, output_stream, .{ .file_name = path, .line = 1, .column = 0 }); try expectEqualStrings("no new lines in this file, but one is printed anyway\n", aw.written()); aw.clearRetainingCapacity(); } { - const path = try fs.path.join(allocator, &.{ test_dir_path, "three_lines.zig" }); - defer allocator.free(path); - try test_dir.dir.writeFile(.{ + const path = try fs.path.join(gpa, &.{ test_dir_path, "three_lines.zig" }); + defer gpa.free(path); + try test_dir.dir.writeFile(io, .{ .sub_path = "three_lines.zig", .data = \\1 @@ -1276,90 +1257,90 @@ test printLineFromFile { , }); - try printLineFromFile(output_stream, .{ .file_name = path, .line = 1, .column = 0 }); + try printLineFromFile(io, output_stream, .{ .file_name = path, .line = 1, .column = 0 }); try expectEqualStrings("1\n", aw.written()); aw.clearRetainingCapacity(); - try printLineFromFile(output_stream, .{ .file_name = path, .line = 3, .column = 0 }); + try printLineFromFile(io, output_stream, .{ .file_name = path, .line = 3, .column = 0 }); try expectEqualStrings("3\n", aw.written()); aw.clearRetainingCapacity(); } { - const file = try test_dir.dir.createFile("line_overlaps_page_boundary.zig", .{}); - defer file.close(); - const path = try fs.path.join(allocator, &.{ test_dir_path, "line_overlaps_page_boundary.zig" }); - defer allocator.free(path); + const file = try test_dir.dir.createFile(io, "line_overlaps_page_boundary.zig", .{}); + defer file.close(io); + const path = try fs.path.join(gpa, &.{ test_dir_path, "line_overlaps_page_boundary.zig" }); + defer gpa.free(path); const overlap = 10; var buf: [16]u8 = undefined; - var file_writer = file.writer(&buf); + var file_writer = file.writer(io, &buf); const writer = &file_writer.interface; try writer.splatByteAll('a', std.heap.page_size_min - overlap); try writer.writeByte('\n'); try writer.splatByteAll('a', overlap); try writer.flush(); - try printLineFromFile(output_stream, .{ .file_name = path, .line = 2, .column = 0 }); + try printLineFromFile(io, output_stream, .{ .file_name = path, .line = 2, .column = 0 }); try expectEqualStrings(("a" ** overlap) ++ "\n", aw.written()); aw.clearRetainingCapacity(); } { - const file = try test_dir.dir.createFile("file_ends_on_page_boundary.zig", .{}); - defer file.close(); - const path = try fs.path.join(allocator, &.{ test_dir_path, "file_ends_on_page_boundary.zig" }); - defer allocator.free(path); + const file = try test_dir.dir.createFile(io, "file_ends_on_page_boundary.zig", .{}); + defer file.close(io); + const path = try fs.path.join(gpa, &.{ test_dir_path, "file_ends_on_page_boundary.zig" }); + defer gpa.free(path); - var file_writer = file.writer(&.{}); + var file_writer = file.writer(io, &.{}); const writer = &file_writer.interface; try writer.splatByteAll('a', std.heap.page_size_max); - try printLineFromFile(output_stream, .{ .file_name = path, .line = 1, .column = 0 }); + try printLineFromFile(io, output_stream, .{ .file_name = path, .line = 1, .column = 0 }); try expectEqualStrings(("a" ** std.heap.page_size_max) ++ "\n", aw.written()); aw.clearRetainingCapacity(); } { - const file = try test_dir.dir.createFile("very_long_first_line_spanning_multiple_pages.zig", .{}); - defer file.close(); - const path = try fs.path.join(allocator, &.{ test_dir_path, "very_long_first_line_spanning_multiple_pages.zig" }); - defer allocator.free(path); + const file = try test_dir.dir.createFile(io, "very_long_first_line_spanning_multiple_pages.zig", .{}); + defer file.close(io); + const path = try fs.path.join(gpa, &.{ test_dir_path, "very_long_first_line_spanning_multiple_pages.zig" }); + defer gpa.free(path); - var file_writer = file.writer(&.{}); + var file_writer = file.writer(io, &.{}); const writer = &file_writer.interface; try writer.splatByteAll('a', 3 * std.heap.page_size_max); - try expectError(error.EndOfFile, printLineFromFile(output_stream, .{ .file_name = path, .line = 2, .column = 0 })); + try expectError(error.EndOfStream, printLineFromFile(io, output_stream, .{ .file_name = path, .line = 2, .column = 0 })); - try printLineFromFile(output_stream, .{ .file_name = path, .line = 1, .column = 0 }); + try printLineFromFile(io, output_stream, .{ .file_name = path, .line = 1, .column = 0 }); try expectEqualStrings(("a" ** (3 * std.heap.page_size_max)) ++ "\n", aw.written()); aw.clearRetainingCapacity(); try writer.writeAll("a\na"); - try printLineFromFile(output_stream, .{ .file_name = path, .line = 1, .column = 0 }); + try printLineFromFile(io, output_stream, .{ .file_name = path, .line = 1, .column = 0 }); try expectEqualStrings(("a" ** (3 * std.heap.page_size_max)) ++ "a\n", aw.written()); aw.clearRetainingCapacity(); - try printLineFromFile(output_stream, .{ .file_name = path, .line = 2, .column = 0 }); + try printLineFromFile(io, output_stream, .{ .file_name = path, .line = 2, .column = 0 }); try expectEqualStrings("a\n", aw.written()); aw.clearRetainingCapacity(); } { - const file = try test_dir.dir.createFile("file_of_newlines.zig", .{}); - defer file.close(); - const path = try fs.path.join(allocator, &.{ test_dir_path, "file_of_newlines.zig" }); - defer allocator.free(path); + const file = try test_dir.dir.createFile(io, "file_of_newlines.zig", .{}); + defer file.close(io); + const path = try fs.path.join(gpa, &.{ test_dir_path, "file_of_newlines.zig" }); + defer gpa.free(path); - var file_writer = file.writer(&.{}); + var file_writer = file.writer(io, &.{}); const writer = &file_writer.interface; const real_file_start = 3 * std.heap.page_size_min; try writer.splatByteAll('\n', real_file_start); try writer.writeAll("abc\ndef"); - try printLineFromFile(output_stream, .{ .file_name = path, .line = real_file_start + 1, .column = 0 }); + try printLineFromFile(io, output_stream, .{ .file_name = path, .line = real_file_start + 1, .column = 0 }); try expectEqualStrings("abc\n", aw.written()); aw.clearRetainingCapacity(); - try printLineFromFile(output_stream, .{ .file_name = path, .line = real_file_start + 2, .column = 0 }); + try printLineFromFile(io, output_stream, .{ .file_name = path, .line = real_file_start + 2, .column = 0 }); try expectEqualStrings("def\n", aw.written()); aw.clearRetainingCapacity(); } @@ -1556,6 +1537,10 @@ fn handleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContextPtr) noret } pub fn defaultHandleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContextPtr) noreturn { + // Don't try to cancel during a segfault. No need to re-enable cancelation, + // because the segfault handler doesn't return. + _ = std.Options.debug_io.swapCancelProtection(.blocked); + // There is very similar logic to the following in `defaultPanic`. switch (panic_stage) { 0 => { @@ -1563,19 +1548,19 @@ pub fn defaultHandleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContex _ = panicking.fetchAdd(1, .seq_cst); trace: { - const stderr, const tty_config = lockStderrWriter(&.{}); - defer unlockStderrWriter(); + const stderr = lockStderr(&.{}).terminal(); + defer unlockStderr(); if (addr) |a| { - stderr.print("{s} at address 0x{x}\n", .{ name, a }) catch break :trace; + stderr.writer.print("{s} at address 0x{x}\n", .{ name, a }) catch break :trace; } else { - stderr.print("{s} (no address available)\n", .{name}) catch break :trace; + stderr.writer.print("{s} (no address available)\n", .{name}) catch break :trace; } if (opt_ctx) |context| { writeCurrentStackTrace(.{ .context = context, .allow_unsafe_unwind = true, // we're crashing anyway, give it our all! - }, stderr, tty_config) catch break :trace; + }, stderr) catch break :trace; } } }, @@ -1584,7 +1569,8 @@ pub fn defaultHandleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContex // A segfault happened while trying to print a previous panic message. // We're still holding the mutex but that's fine as we're going to // call abort(). - fs.File.stderr().writeAll("aborting due to recursive panic\n") catch {}; + const stderr = lockStderr(&.{}).terminal(); + stderr.writer.writeAll("aborting due to recursive panic\n") catch {}; }, else => {}, // Panicked while printing the recursive panic message. } @@ -1592,7 +1578,7 @@ pub fn defaultHandleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContex // We cannot allow the signal handler to return because when it runs the original instruction // again, the memory may be mapped and undefined behavior would occur rather than repeating // the segfault. So we simply abort here. - posix.abort(); + std.process.abort(); } pub fn dumpStackPointerAddr(prefix: []const u8) void { @@ -1604,25 +1590,26 @@ pub fn dumpStackPointerAddr(prefix: []const u8) void { test "manage resources correctly" { if (SelfInfo == void) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) { + // The C backend emits an extremely large C source file, meaning it has a huge + // amount of debug information. Parsing this debug information makes this test + // take too long to be worth running. + return error.SkipZigTest; + } + const S = struct { noinline fn showMyTrace() usize { return @returnAddress(); } }; - const gpa = std.testing.allocator; - var threaded: Io.Threaded = .init_single_threaded; - const io = threaded.ioBasic(); - var discarding: Io.Writer.Discarding = .init(&.{}); + const gpa = testing.allocator; + const io = testing.io; + + var discarding: Writer.Discarding = .init(&.{}); var di: SelfInfo = .init; defer di.deinit(gpa); - try printSourceAtAddress( - gpa, - io, - &di, - &discarding.writer, - S.showMyTrace(), - .no_color, - ); + const t: Io.Terminal = .{ .writer = &discarding.writer, .mode = .no_color }; + try printSourceAtAddress(gpa, io, &di, t, S.showMyTrace()); } /// This API helps you track where a value originated and where it was mutated, @@ -1683,21 +1670,21 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize pub fn dump(t: @This()) void { if (!enabled) return; - const stderr, const tty_config = lockStderrWriter(&.{}); - defer unlockStderrWriter(); + const stderr = lockStderr(&.{}).terminal(); + defer unlockStderr(); const end = @min(t.index, size); for (t.addrs[0..end], 0..) |frames_array, i| { - stderr.print("{s}:\n", .{t.notes[i]}) catch return; + stderr.writer.print("{s}:\n", .{t.notes[i]}) catch return; var frames_array_mutable = frames_array; const frames = mem.sliceTo(frames_array_mutable[0..], 0); const stack_trace: StackTrace = .{ .index = frames.len, .instruction_addresses = frames, }; - writeStackTrace(&stack_trace, stderr, tty_config) catch return; + writeStackTrace(&stack_trace, stderr) catch return; } if (t.index > end) { - stderr.print("{d} more traces not shown; consider increasing trace size\n", .{ + stderr.writer.print("{d} more traces not shown; consider increasing trace size\n", .{ t.index - end, }) catch return; } diff --git a/lib/std/debug/Dwarf.zig b/lib/std/debug/Dwarf.zig index 16b3b86bb34b..f82b4829deb2 100644 --- a/lib/std/debug/Dwarf.zig +++ b/lib/std/debug/Dwarf.zig @@ -437,7 +437,7 @@ fn scanAllFunctions(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void { }; while (true) { - fr.seek = std.mem.indexOfNonePos(u8, fr.buffer, fr.seek, &.{ + fr.seek = std.mem.findNonePos(u8, fr.buffer, fr.seek, &.{ zig_padding_abbrev_code, 0, }) orelse fr.buffer.len; if (fr.seek >= next_unit_pos) break; @@ -1539,7 +1539,7 @@ fn getStringGeneric(opt_str: ?[]const u8, offset: u64) ![:0]const u8 { if (offset > str.len) return bad(); const casted_offset = cast(usize, offset) orelse return bad(); // Valid strings always have a terminating zero byte - const last = std.mem.indexOfScalarPos(u8, str, casted_offset, 0) orelse return bad(); + const last = std.mem.findScalarPos(u8, str, casted_offset, 0) orelse return bad(); return str[casted_offset..last :0]; } diff --git a/lib/std/debug/ElfFile.zig b/lib/std/debug/ElfFile.zig index e81943ab4980..007e815e374d 100644 --- a/lib/std/debug/ElfFile.zig +++ b/lib/std/debug/ElfFile.zig @@ -1,5 +1,13 @@ //! A helper type for loading an ELF file and collecting its DWARF debug information, unwind //! information, and symbol table. +const ElfFile = @This(); + +const std = @import("std"); +const Io = std.Io; +const Endian = std.builtin.Endian; +const Dwarf = std.debug.Dwarf; +const Allocator = std.mem.Allocator; +const elf = std.elf; is_64: bool, endian: Endian, @@ -59,15 +67,16 @@ pub const DebugInfoSearchPaths = struct { }; pub fn native(exe_path: []const u8) DebugInfoSearchPaths { - return .{ + if (std.Options.elf_debug_info_search_paths) |f| return f(exe_path); + if (std.Options.debug_threaded_io) |t| return .{ .debuginfod_client = p: { - if (std.posix.getenv("DEBUGINFOD_CACHE_PATH")) |p| { + if (t.environString("DEBUGINFOD_CACHE_PATH")) |p| { break :p .{ p, "" }; } - if (std.posix.getenv("XDG_CACHE_HOME")) |cache_path| { + if (t.environString("XDG_CACHE_HOME")) |cache_path| { break :p .{ cache_path, "/debuginfod_client" }; } - if (std.posix.getenv("HOME")) |home_path| { + if (t.environString("HOME")) |home_path| { break :p .{ home_path, "/.cache/debuginfod_client" }; } break :p null; @@ -77,6 +86,7 @@ pub const DebugInfoSearchPaths = struct { }, .exe_dir = std.fs.path.dirname(exe_path) orelse ".", }; + @compileError("std.Options.elf_debug_info_search_paths must be provided"); } }; @@ -115,7 +125,8 @@ pub const LoadError = error{ pub fn load( gpa: Allocator, - elf_file: std.fs.File, + io: Io, + elf_file: Io.File, opt_build_id: ?[]const u8, di_search_paths: *const DebugInfoSearchPaths, ) LoadError!ElfFile { @@ -123,7 +134,7 @@ pub fn load( errdefer arena_instance.deinit(); const arena = arena_instance.allocator(); - var result = loadInner(arena, elf_file, null) catch |err| switch (err) { + var result = loadInner(arena, io, elf_file, null) catch |err| switch (err) { error.CrcMismatch => unreachable, // we passed crc as null else => |e| return e, }; @@ -148,7 +159,7 @@ pub fn load( if (build_id.len < 3) break :build_id; for (di_search_paths.global_debug) |global_debug| { - if (try loadSeparateDebugFile(arena, &result, null, "{s}/.build-id/{x}/{x}.debug", .{ + if (try loadSeparateDebugFile(arena, io, &result, null, "{s}/.build-id/{x}/{x}.debug", .{ global_debug, build_id[0..1], build_id[1..], @@ -156,7 +167,7 @@ pub fn load( } if (di_search_paths.debuginfod_client) |components| { - if (try loadSeparateDebugFile(arena, &result, null, "{s}{s}/{x}/debuginfo", .{ + if (try loadSeparateDebugFile(arena, io, &result, null, "{s}{s}/{x}/debuginfo", .{ components[0], components[1], build_id, @@ -173,18 +184,18 @@ pub fn load( const exe_dir = di_search_paths.exe_dir orelse break :debug_link; - if (try loadSeparateDebugFile(arena, &result, debug_crc, "{s}/{s}", .{ + if (try loadSeparateDebugFile(arena, io, &result, debug_crc, "{s}/{s}", .{ exe_dir, debug_filename, })) |mapped| break :load_di mapped; - if (try loadSeparateDebugFile(arena, &result, debug_crc, "{s}/.debug/{s}", .{ + if (try loadSeparateDebugFile(arena, io, &result, debug_crc, "{s}/.debug/{s}", .{ exe_dir, debug_filename, })) |mapped| break :load_di mapped; for (di_search_paths.global_debug) |global_debug| { // This looks like a bug; it isn't. They really do embed the absolute path to the // exe's dirname, *under* the global debug path. - if (try loadSeparateDebugFile(arena, &result, debug_crc, "{s}/{s}/{s}", .{ + if (try loadSeparateDebugFile(arena, io, &result, debug_crc, "{s}/{s}/{s}", .{ global_debug, exe_dir, debug_filename, @@ -358,12 +369,19 @@ const Section = struct { const Array = std.enums.EnumArray(Section.Id, ?Section); }; -fn loadSeparateDebugFile(arena: Allocator, main_loaded: *LoadInnerResult, opt_crc: ?u32, comptime fmt: []const u8, args: anytype) Allocator.Error!?[]align(std.heap.page_size_min) const u8 { +fn loadSeparateDebugFile( + arena: Allocator, + io: Io, + main_loaded: *LoadInnerResult, + opt_crc: ?u32, + comptime fmt: []const u8, + args: anytype, +) Allocator.Error!?[]align(std.heap.page_size_min) const u8 { const path = try std.fmt.allocPrint(arena, fmt, args); - const elf_file = std.fs.cwd().openFile(path, .{}) catch return null; - defer elf_file.close(); + const elf_file = Io.Dir.cwd().openFile(io, path, .{}) catch return null; + defer elf_file.close(io); - const result = loadInner(arena, elf_file, opt_crc) catch |err| switch (err) { + const result = loadInner(arena, io, elf_file, opt_crc) catch |err| switch (err) { error.OutOfMemory => |e| return e, error.CrcMismatch => return null, else => return null, @@ -408,13 +426,14 @@ const LoadInnerResult = struct { }; fn loadInner( arena: Allocator, - elf_file: std.fs.File, + io: Io, + elf_file: Io.File, opt_crc: ?u32, ) (LoadError || error{ CrcMismatch, Streaming, Canceled })!LoadInnerResult { const mapped_mem: []align(std.heap.page_size_min) const u8 = mapped: { const file_len = std.math.cast( usize, - elf_file.getEndPos() catch |err| switch (err) { + elf_file.length(io) catch |err| switch (err) { error.PermissionDenied => unreachable, // not asking for PROT_EXEC else => |e| return e, }, @@ -529,10 +548,3 @@ fn loadInner( .mapped_mem = mapped_mem, }; } - -const std = @import("std"); -const Endian = std.builtin.Endian; -const Dwarf = std.debug.Dwarf; -const ElfFile = @This(); -const Allocator = std.mem.Allocator; -const elf = std.elf; diff --git a/lib/std/debug/Info.zig b/lib/std/debug/Info.zig index 921cd36ab811..34e79227d137 100644 --- a/lib/std/debug/Info.zig +++ b/lib/std/debug/Info.zig @@ -5,19 +5,18 @@ //! Unlike `std.debug.SelfInfo`, this API does not assume the debug information //! in question happens to match the host CPU architecture, OS, or other target //! properties. +const Info = @This(); const std = @import("../std.zig"); +const Io = std.Io; const Allocator = std.mem.Allocator; const Path = std.Build.Cache.Path; const assert = std.debug.assert; const Coverage = std.debug.Coverage; const SourceLocation = std.debug.Coverage.SourceLocation; - const ElfFile = std.debug.ElfFile; const MachOFile = std.debug.MachOFile; -const Info = @This(); - impl: union(enum) { elf: ElfFile, macho: MachOFile, @@ -25,15 +24,25 @@ impl: union(enum) { /// Externally managed, outlives this `Info` instance. coverage: *Coverage, -pub const LoadError = std.fs.File.OpenError || ElfFile.LoadError || MachOFile.Error || std.debug.Dwarf.ScanError || error{ MissingDebugInfo, UnsupportedDebugInfo }; +pub const LoadError = error{ + MissingDebugInfo, + UnsupportedDebugInfo, +} || Io.File.OpenError || ElfFile.LoadError || MachOFile.Error || std.debug.Dwarf.ScanError; -pub fn load(gpa: Allocator, path: Path, coverage: *Coverage, format: std.Target.ObjectFormat, arch: std.Target.Cpu.Arch) LoadError!Info { +pub fn load( + gpa: Allocator, + io: Io, + path: Path, + coverage: *Coverage, + format: std.Target.ObjectFormat, + arch: std.Target.Cpu.Arch, +) LoadError!Info { switch (format) { .elf => { - var file = try path.root_dir.handle.openFile(path.sub_path, .{}); - defer file.close(); + var file = try path.root_dir.handle.openFile(io, path.sub_path, .{}); + defer file.close(io); - var elf_file: ElfFile = try .load(gpa, file, null, &.none); + var elf_file: ElfFile = try .load(gpa, io, file, null, &.none); errdefer elf_file.deinit(gpa); if (elf_file.dwarf == null) return error.MissingDebugInfo; @@ -49,7 +58,7 @@ pub fn load(gpa: Allocator, path: Path, coverage: *Coverage, format: std.Target. const path_str = try path.toString(gpa); defer gpa.free(path_str); - var macho_file: MachOFile = try .load(gpa, path_str, arch); + var macho_file: MachOFile = try .load(gpa, io, path_str, arch); errdefer macho_file.deinit(gpa); return .{ @@ -76,6 +85,7 @@ pub const ResolveAddressesError = Coverage.ResolveAddressesDwarfError || error{U pub fn resolveAddresses( info: *Info, gpa: Allocator, + io: Io, /// Asserts the addresses are in ascending order. sorted_pc_addrs: []const u64, /// Asserts its length equals length of `sorted_pc_addrs`. @@ -88,7 +98,7 @@ pub fn resolveAddresses( // Resolving all of the addresses at once unfortunately isn't so easy in Mach-O binaries // due to split debug information. For now, we'll just resolve the addreses one by one. for (sorted_pc_addrs, output) |pc_addr, *src_loc| { - const dwarf, const dwarf_pc_addr = mf.getDwarfForAddress(gpa, pc_addr) catch |err| switch (err) { + const dwarf, const dwarf_pc_addr = mf.getDwarfForAddress(gpa, io, pc_addr) catch |err| switch (err) { error.InvalidMachO, error.InvalidDwarf => return error.InvalidDebugInfo, else => |e| return e, }; diff --git a/lib/std/debug/MachOFile.zig b/lib/std/debug/MachOFile.zig index 3be1b1daff8f..9e81fb8911d7 100644 --- a/lib/std/debug/MachOFile.zig +++ b/lib/std/debug/MachOFile.zig @@ -27,13 +27,13 @@ pub fn deinit(mf: *MachOFile, gpa: Allocator) void { posix.munmap(mf.mapped_memory); } -pub fn load(gpa: Allocator, path: []const u8, arch: std.Target.Cpu.Arch) Error!MachOFile { +pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch) Error!MachOFile { switch (arch) { .x86_64, .aarch64 => {}, else => unreachable, } - const all_mapped_memory = try mapDebugInfoFile(path); + const all_mapped_memory = try mapDebugInfoFile(io, path); errdefer posix.munmap(all_mapped_memory); // In most cases, the file we just mapped is a Mach-O binary. However, it could be a "universal @@ -239,7 +239,7 @@ pub fn load(gpa: Allocator, path: []const u8, arch: std.Target.Cpu.Arch) Error!M .text_vmaddr = text_vmaddr, }; } -pub fn getDwarfForAddress(mf: *MachOFile, gpa: Allocator, vaddr: u64) !struct { *Dwarf, u64 } { +pub fn getDwarfForAddress(mf: *MachOFile, gpa: Allocator, io: Io, vaddr: u64) !struct { *Dwarf, u64 } { const symbol = Symbol.find(mf.symbols, vaddr) orelse return error.MissingDebugInfo; if (symbol.ofile == Symbol.unknown_ofile) return error.MissingDebugInfo; @@ -254,7 +254,7 @@ pub fn getDwarfForAddress(mf: *MachOFile, gpa: Allocator, vaddr: u64) !struct { const gop = try mf.ofiles.getOrPut(gpa, symbol.ofile); if (!gop.found_existing) { const name = mem.sliceTo(mf.strings[symbol.ofile..], 0); - gop.value_ptr.* = loadOFile(gpa, name); + gop.value_ptr.* = loadOFile(gpa, io, name); } const of = &(gop.value_ptr.* catch |err| return err); @@ -356,7 +356,7 @@ test { _ = Symbol; } -fn loadOFile(gpa: Allocator, o_file_name: []const u8) !OFile { +fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile { const all_mapped_memory, const mapped_ofile = map: { const open_paren = paren: { if (std.mem.endsWith(u8, o_file_name, ")")) { @@ -365,7 +365,7 @@ fn loadOFile(gpa: Allocator, o_file_name: []const u8) !OFile { } } // Not an archive, just a normal path to a .o file - const m = try mapDebugInfoFile(o_file_name); + const m = try mapDebugInfoFile(io, o_file_name); break :map .{ m, m }; }; @@ -373,7 +373,7 @@ fn loadOFile(gpa: Allocator, o_file_name: []const u8) !OFile { const archive_path = o_file_name[0..open_paren]; const target_name_in_archive = o_file_name[open_paren + 1 .. o_file_name.len - 1]; - const mapped_archive = try mapDebugInfoFile(archive_path); + const mapped_archive = try mapDebugInfoFile(io, archive_path); errdefer posix.munmap(mapped_archive); var ar_reader: Io.Reader = .fixed(mapped_archive); @@ -511,16 +511,16 @@ fn loadOFile(gpa: Allocator, o_file_name: []const u8) !OFile { } /// Uses `mmap` to map the file at `path` into memory. -fn mapDebugInfoFile(path: []const u8) ![]align(std.heap.page_size_min) const u8 { - const file = std.fs.cwd().openFile(path, .{}) catch |err| switch (err) { +fn mapDebugInfoFile(io: Io, path: []const u8) ![]align(std.heap.page_size_min) const u8 { + const file = Io.Dir.cwd().openFile(io, path, .{}) catch |err| switch (err) { error.FileNotFound => return error.MissingDebugInfo, else => return error.ReadFailed, }; - defer file.close(); + defer file.close(io); const file_len = std.math.cast( usize, - file.getEndPos() catch return error.ReadFailed, + file.length(io) catch return error.ReadFailed, ) orelse return error.ReadFailed; return posix.mmap( diff --git a/lib/std/debug/Pdb.zig b/lib/std/debug/Pdb.zig index c10b361f7293..3ecfd1b36377 100644 --- a/lib/std/debug/Pdb.zig +++ b/lib/std/debug/Pdb.zig @@ -1,5 +1,5 @@ const std = @import("../std.zig"); -const File = std.fs.File; +const File = std.Io.File; const Allocator = std.mem.Allocator; const pdb = std.pdb; const assert = std.debug.assert; diff --git a/lib/std/debug/SelfInfo/Elf.zig b/lib/std/debug/SelfInfo/Elf.zig index 59c0b4245173..ffcb4dfd26fd 100644 --- a/lib/std/debug/SelfInfo/Elf.zig +++ b/lib/std/debug/SelfInfo/Elf.zig @@ -29,13 +29,12 @@ pub fn deinit(si: *SelfInfo, gpa: Allocator) void { } pub fn getSymbol(si: *SelfInfo, gpa: Allocator, io: Io, address: usize) Error!std.debug.Symbol { - _ = io; const module = try si.findModule(gpa, address, .exclusive); defer si.rwlock.unlock(); const vaddr = address - module.load_offset; - const loaded_elf = try module.getLoadedElf(gpa); + const loaded_elf = try module.getLoadedElf(gpa, io); if (loaded_elf.file.dwarf) |*dwarf| { if (!loaded_elf.scanned_dwarf) { dwarf.open(gpa, native_endian) catch |err| switch (err) { @@ -180,7 +179,7 @@ comptime { } } pub const UnwindContext = Dwarf.SelfUnwinder; -pub fn unwindFrame(si: *SelfInfo, gpa: Allocator, context: *UnwindContext) Error!usize { +pub fn unwindFrame(si: *SelfInfo, gpa: Allocator, io: Io, context: *UnwindContext) Error!usize { comptime assert(can_unwind); { @@ -201,7 +200,7 @@ pub fn unwindFrame(si: *SelfInfo, gpa: Allocator, context: *UnwindContext) Error @memset(si.unwind_cache.?, .empty); } - const unwind_sections = try module.getUnwindSections(gpa); + const unwind_sections = try module.getUnwindSections(gpa, io); for (unwind_sections) |*unwind| { if (context.computeRules(gpa, unwind, module.load_offset, null)) |entry| { entry.populate(si.unwind_cache.?); @@ -261,12 +260,12 @@ const Module = struct { }; /// Assumes we already hold an exclusive lock. - fn getUnwindSections(mod: *Module, gpa: Allocator) Error![]Dwarf.Unwind { - if (mod.unwind == null) mod.unwind = loadUnwindSections(mod, gpa); + fn getUnwindSections(mod: *Module, gpa: Allocator, io: Io) Error![]Dwarf.Unwind { + if (mod.unwind == null) mod.unwind = loadUnwindSections(mod, gpa, io); const us = &(mod.unwind.? catch |err| return err); return us.buf[0..us.len]; } - fn loadUnwindSections(mod: *Module, gpa: Allocator) Error!UnwindSections { + fn loadUnwindSections(mod: *Module, gpa: Allocator, io: Io) Error!UnwindSections { var us: UnwindSections = .{ .buf = undefined, .len = 0, @@ -284,7 +283,7 @@ const Module = struct { } else { // There is no `.eh_frame_hdr` section. There may still be an `.eh_frame` or `.debug_frame` // section, but we'll have to load the binary to get at it. - const loaded = try mod.getLoadedElf(gpa); + const loaded = try mod.getLoadedElf(gpa, io); // If both are present, we can't just pick one -- the info could be split between them. // `.debug_frame` is likely to be the more complete section, so we'll prioritize that one. if (loaded.file.debug_frame) |*debug_frame| { @@ -319,24 +318,25 @@ const Module = struct { } /// Assumes we already hold an exclusive lock. - fn getLoadedElf(mod: *Module, gpa: Allocator) Error!*LoadedElf { - if (mod.loaded_elf == null) mod.loaded_elf = loadElf(mod, gpa); + fn getLoadedElf(mod: *Module, gpa: Allocator, io: Io) Error!*LoadedElf { + if (mod.loaded_elf == null) mod.loaded_elf = loadElf(mod, gpa, io); return if (mod.loaded_elf.?) |*elf| elf else |err| err; } - fn loadElf(mod: *Module, gpa: Allocator) Error!LoadedElf { + + fn loadElf(mod: *Module, gpa: Allocator, io: Io) Error!LoadedElf { const load_result = if (mod.name.len > 0) res: { - var file = std.fs.cwd().openFile(mod.name, .{}) catch return error.MissingDebugInfo; - defer file.close(); - break :res std.debug.ElfFile.load(gpa, file, mod.build_id, &.native(mod.name)); + var file = Io.Dir.cwd().openFile(io, mod.name, .{}) catch return error.MissingDebugInfo; + defer file.close(io); + break :res std.debug.ElfFile.load(gpa, io, file, mod.build_id, &.native(mod.name)); } else res: { - const path = std.fs.selfExePathAlloc(gpa) catch |err| switch (err) { + const path = std.process.executablePathAlloc(io, gpa) catch |err| switch (err) { error.OutOfMemory => |e| return e, else => return error.ReadFailed, }; defer gpa.free(path); - var file = std.fs.cwd().openFile(path, .{}) catch return error.MissingDebugInfo; - defer file.close(); - break :res std.debug.ElfFile.load(gpa, file, mod.build_id, &.native(path)); + var file = Io.Dir.cwd().openFile(io, path, .{}) catch return error.MissingDebugInfo; + defer file.close(io); + break :res std.debug.ElfFile.load(gpa, io, file, mod.build_id, &.native(path)); }; var elf_file = load_result catch |err| switch (err) { diff --git a/lib/std/debug/SelfInfo/MachO.zig b/lib/std/debug/SelfInfo/MachO.zig index 94d50bbf7707..d09493adb0fe 100644 --- a/lib/std/debug/SelfInfo/MachO.zig +++ b/lib/std/debug/SelfInfo/MachO.zig @@ -21,11 +21,10 @@ pub fn deinit(si: *SelfInfo, gpa: Allocator) void { } pub fn getSymbol(si: *SelfInfo, gpa: Allocator, io: Io, address: usize) Error!std.debug.Symbol { - _ = io; const module = try si.findModule(gpa, address); defer si.mutex.unlock(); - const file = try module.getFile(gpa); + const file = try module.getFile(gpa, io); // This is not necessarily the same as the vmaddr_slide that dyld would report. This is // because the segments in the file on disk might differ from the ones in memory. Normally @@ -39,7 +38,7 @@ pub fn getSymbol(si: *SelfInfo, gpa: Allocator, io: Io, address: usize) Error!st const vaddr = address - vaddr_offset; - const ofile_dwarf, const ofile_vaddr = file.getDwarfForAddress(gpa, vaddr) catch { + const ofile_dwarf, const ofile_vaddr = file.getDwarfForAddress(gpa, io, vaddr) catch { // Return at least the symbol name if available. return .{ .name = try file.lookupSymbolName(vaddr), @@ -78,9 +77,14 @@ pub fn getSymbol(si: *SelfInfo, gpa: Allocator, io: Io, address: usize) Error!st }; } pub fn getModuleName(si: *SelfInfo, gpa: Allocator, address: usize) Error![]const u8 { - const module = try si.findModule(gpa, address); - defer si.mutex.unlock(); - return module.name; + _ = si; + _ = gpa; + // This function is marked as deprecated; however, it is significantly more + // performant than `dladdr` (since the latter also does a very slow symbol + // lookup), so let's use it since it's still available. + return std.mem.span(std.c.dyld_image_path_containing_address( + @ptrFromInt(address), + ) orelse return error.MissingDebugInfo); } pub fn getModuleSlide(si: *SelfInfo, gpa: Allocator, address: usize) Error!usize { const module = try si.findModule(gpa, address); @@ -102,7 +106,8 @@ pub const UnwindContext = std.debug.Dwarf.SelfUnwinder; /// Unwind a frame using MachO compact unwind info (from `__unwind_info`). /// If the compact encoding can't encode a way to unwind a frame, it will /// defer unwinding to DWARF, in which case `__eh_frame` will be used if available. -pub fn unwindFrame(si: *SelfInfo, gpa: Allocator, context: *UnwindContext) Error!usize { +pub fn unwindFrame(si: *SelfInfo, gpa: Allocator, io: Io, context: *UnwindContext) Error!usize { + _ = io; return unwindFrameInner(si, gpa, context) catch |err| switch (err) { error.InvalidDebugInfo, error.MissingDebugInfo, @@ -426,28 +431,26 @@ fn unwindFrameInner(si: *SelfInfo, gpa: Allocator, context: *UnwindContext) !usi /// Acquires the mutex on success. fn findModule(si: *SelfInfo, gpa: Allocator, address: usize) Error!*Module { - var info: std.c.dl_info = undefined; - if (std.c.dladdr(@ptrFromInt(address), &info) == 0) { - return error.MissingDebugInfo; - } + // This function is marked as deprecated; however, it is significantly more + // performant than `dladdr` (since the latter also does a very slow symbol + // lookup), so let's use it since it's still available. + const text_base = std.c._dyld_get_image_header_containing_address( + @ptrFromInt(address), + ) orelse return error.MissingDebugInfo; si.mutex.lock(); errdefer si.mutex.unlock(); - const gop = try si.modules.getOrPutAdapted(gpa, @intFromPtr(info.fbase), Module.Adapter{}); + const gop = try si.modules.getOrPutAdapted(gpa, @intFromPtr(text_base), Module.Adapter{}); errdefer comptime unreachable; - if (!gop.found_existing) { - gop.key_ptr.* = .{ - .text_base = @intFromPtr(info.fbase), - .name = std.mem.span(info.fname), - .unwind = null, - .file = null, - }; - } + if (!gop.found_existing) gop.key_ptr.* = .{ + .text_base = @intFromPtr(text_base), + .unwind = null, + .file = null, + }; return gop.key_ptr; } const Module = struct { text_base: usize, - name: []const u8, unwind: ?(Error!Unwind), file: ?(Error!MachOFile), @@ -543,11 +546,16 @@ const Module = struct { }; } - fn getFile(module: *Module, gpa: Allocator) Error!*MachOFile { - if (module.file == null) module.file = MachOFile.load(gpa, module.name, builtin.cpu.arch) catch |err| switch (err) { - error.InvalidMachO, error.InvalidDwarf => error.InvalidDebugInfo, - error.MissingDebugInfo, error.OutOfMemory, error.UnsupportedDebugInfo, error.ReadFailed => |e| e, - }; + fn getFile(module: *Module, gpa: Allocator, io: Io) Error!*MachOFile { + if (module.file == null) { + const path = std.mem.span( + std.c.dyld_image_path_containing_address(@ptrFromInt(module.text_base)).?, + ); + module.file = MachOFile.load(gpa, io, path, builtin.cpu.arch) catch |err| switch (err) { + error.InvalidMachO, error.InvalidDwarf => error.InvalidDebugInfo, + error.MissingDebugInfo, error.OutOfMemory, error.UnsupportedDebugInfo, error.ReadFailed => |e| e, + }; + } return if (module.file.?) |*f| f else |err| err; } }; @@ -607,14 +615,14 @@ test { } /// Uses `mmap` to map the file at `path` into memory. -fn mapDebugInfoFile(path: []const u8) ![]align(std.heap.page_size_min) const u8 { - const file = std.fs.cwd().openFile(path, .{}) catch |err| switch (err) { +fn mapDebugInfoFile(io: Io, path: []const u8) ![]align(std.heap.page_size_min) const u8 { + const file = Io.Dir.cwd().openFile(io, path, .{}) catch |err| switch (err) { error.FileNotFound => return error.MissingDebugInfo, else => return error.ReadFailed, }; - defer file.close(); + defer file.close(io); - const file_end_pos = file.getEndPos() catch |err| switch (err) { + const file_end_pos = file.length(io) catch |err| switch (err) { error.Unexpected => |e| return e, else => return error.ReadFailed, }; diff --git a/lib/std/debug/SelfInfo/Windows.zig b/lib/std/debug/SelfInfo/Windows.zig index 03fc7e28113b..0c81d0012cab 100644 --- a/lib/std/debug/SelfInfo/Windows.zig +++ b/lib/std/debug/SelfInfo/Windows.zig @@ -149,15 +149,16 @@ pub const UnwindContext = struct { return ctx.cur.getRegs().bp; } }; -pub fn unwindFrame(si: *SelfInfo, gpa: Allocator, context: *UnwindContext) Error!usize { +pub fn unwindFrame(si: *SelfInfo, gpa: Allocator, io: Io, context: *UnwindContext) Error!usize { _ = si; + _ = io; _ = gpa; const current_regs = context.cur.getRegs(); - var image_base: windows.DWORD64 = undefined; + var image_base: usize = undefined; if (windows.ntdll.RtlLookupFunctionEntry(current_regs.ip, &image_base, &context.history_table)) |runtime_function| { var handler_data: ?*anyopaque = null; - var establisher_frame: u64 = undefined; + var establisher_frame: usize = undefined; _ = windows.ntdll.RtlVirtualUnwind( windows.UNW_FLAG_NHANDLER, image_base, @@ -204,14 +205,14 @@ const Module = struct { coff_section_headers: []coff.SectionHeader, const MappedFile = struct { - file: fs.File, + file: Io.File, section_handle: windows.HANDLE, section_view: []const u8, - fn deinit(mf: *const MappedFile) void { + fn deinit(mf: *const MappedFile, io: Io) void { const process_handle = windows.GetCurrentProcess(); assert(windows.ntdll.NtUnmapViewOfSection(process_handle, @constCast(mf.section_view.ptr)) == .SUCCESS); windows.CloseHandle(mf.section_handle); - mf.file.close(); + mf.file.close(io); } }; @@ -222,7 +223,7 @@ const Module = struct { pdb.file_reader.file.close(io); pdb.deinit(); } - if (di.mapped_file) |*mf| mf.deinit(); + if (di.mapped_file) |*mf| mf.deinit(io); var arena = di.arena.promote(gpa); arena.deinit(); @@ -314,8 +315,7 @@ const Module = struct { ); if (len == 0) return error.MissingDebugInfo; const name_w = name_buffer[0 .. len + 4 :0]; - var threaded: Io.Threaded = .init_single_threaded; - const coff_file = threaded.dirOpenFileWtf16(null, name_w, .{}) catch |err| switch (err) { + const coff_file = Io.Threaded.dirOpenFileWtf16(null, name_w, .{}) catch |err| switch (err) { error.Canceled => |e| return e, error.Unexpected => |e| return e, error.FileNotFound => return error.MissingDebugInfo, @@ -331,7 +331,6 @@ const Module = struct { error.SystemResources, error.WouldBlock, error.AccessDenied, - error.ProcessNotFound, error.PermissionDenied, error.NoSpaceLeft, error.DeviceBusy, @@ -343,7 +342,7 @@ const Module = struct { error.AntivirusInterference, error.ProcessFdQuotaExceeded, error.SystemFdQuotaExceeded, - error.FileLocksNotSupported, + error.FileLocksUnsupported, error.FileBusy, => return error.ReadFailed, }; @@ -351,13 +350,19 @@ const Module = struct { var section_handle: windows.HANDLE = undefined; const create_section_rc = windows.ntdll.NtCreateSection( §ion_handle, - windows.STANDARD_RIGHTS_REQUIRED | windows.SECTION_QUERY | windows.SECTION_MAP_READ, + .{ + .SPECIFIC = .{ .SECTION = .{ + .QUERY = true, + .MAP_READ = true, + } }, + .STANDARD = .{ .RIGHTS = .REQUIRED }, + }, null, null, - windows.PAGE_READONLY, + .{ .READONLY = true }, // The documentation states that if no AllocationAttribute is specified, then SEC_COMMIT is the default. // In practice, this isn't the case and specifying 0 will result in INVALID_PARAMETER_6. - windows.SEC_COMMIT, + .{ .COMMIT = true }, coff_file.handle, ); if (create_section_rc != .SUCCESS) return error.MissingDebugInfo; @@ -372,21 +377,21 @@ const Module = struct { 0, null, &coff_len, - .ViewUnmap, - 0, - windows.PAGE_READONLY, + .Unmap, + .{}, + .{ .READONLY = true }, ); if (map_section_rc != .SUCCESS) return error.MissingDebugInfo; errdefer assert(windows.ntdll.NtUnmapViewOfSection(process_handle, @constCast(section_view_ptr.?)) == .SUCCESS); const section_view = section_view_ptr.?[0..coff_len]; coff_obj = coff.Coff.init(section_view, false) catch return error.InvalidDebugInfo; break :mapped .{ - .file = .adaptFromNewApi(coff_file), + .file = coff_file, .section_handle = section_handle, .section_view = section_view, }; }; - errdefer if (mapped_file) |*mf| mf.deinit(); + errdefer if (mapped_file) |*mf| mf.deinit(io); const coff_image_base = coff_obj.getImageBase(); @@ -426,22 +431,22 @@ const Module = struct { break :pdb null; }; const pdb_file_open_result = if (fs.path.isAbsolute(path)) res: { - break :res std.fs.cwd().openFile(path, .{}); + break :res Io.Dir.cwd().openFile(io, path, .{}); } else res: { - const self_dir = fs.selfExeDirPathAlloc(gpa) catch |err| switch (err) { + const self_dir = std.process.executableDirPathAlloc(io, gpa) catch |err| switch (err) { error.OutOfMemory, error.Unexpected => |e| return e, else => return error.ReadFailed, }; defer gpa.free(self_dir); const abs_path = try fs.path.join(gpa, &.{ self_dir, path }); defer gpa.free(abs_path); - break :res std.fs.cwd().openFile(abs_path, .{}); + break :res Io.Dir.cwd().openFile(io, abs_path, .{}); }; const pdb_file = pdb_file_open_result catch |err| switch (err) { error.FileNotFound, error.IsDir => break :pdb null, else => return error.ReadFailed, }; - errdefer pdb_file.close(); + errdefer pdb_file.close(io); const pdb_reader = try arena.create(Io.File.Reader); pdb_reader.* = pdb_file.reader(io, try arena.alloc(u8, 4096)); diff --git a/lib/std/debug/simple_panic.zig b/lib/std/debug/simple_panic.zig index 45e97777c4ba..a5a09fa1162e 100644 --- a/lib/std/debug/simple_panic.zig +++ b/lib/std/debug/simple_panic.zig @@ -14,9 +14,8 @@ const std = @import("../std.zig"); pub fn call(msg: []const u8, ra: ?usize) noreturn { @branchHint(.cold); _ = ra; - std.debug.lockStdErr(); - const stderr: std.fs.File = .stderr(); - stderr.writeAll(msg) catch {}; + const stderr_writer = &std.debug.lockStderr(&.{}).file_writer.interface; + stderr_writer.writeAll(msg) catch {}; @trap(); } diff --git a/lib/std/dynamic_library.zig b/lib/std/dynamic_library.zig index d23d1ff1dd46..1d4c8b965fdb 100644 --- a/lib/std/dynamic_library.zig +++ b/lib/std/dynamic_library.zig @@ -1,10 +1,12 @@ -const std = @import("std.zig"); const builtin = @import("builtin"); +const native_os = builtin.os.tag; + +const std = @import("std.zig"); +const Io = std.Io; const mem = std.mem; const testing = std.testing; const elf = std.elf; const windows = std.os.windows; -const native_os = builtin.os.tag; const posix = std.posix; /// Cross-platform dynamic library loading and symbol lookup. @@ -29,12 +31,20 @@ pub const DynLib = struct { /// Trusts the file. Malicious file will be able to execute arbitrary code. pub fn open(path: []const u8) Error!DynLib { - return .{ .inner = try InnerType.open(path) }; + if (InnerType == ElfDynLib) { + return .{ .inner = try InnerType.open(path, null) }; + } else { + return .{ .inner = try InnerType.open(path) }; + } } /// Trusts the file. Malicious file will be able to execute arbitrary code. pub fn openZ(path_c: [*:0]const u8) Error!DynLib { - return .{ .inner = try InnerType.openZ(path_c) }; + if (InnerType == ElfDynLib) { + return .{ .inner = try InnerType.openZ(path_c, null) }; + } else { + return .{ .inner = try InnerType.openZ(path_c) }; + } } /// Trusts the file. @@ -53,11 +63,11 @@ pub const DynLib = struct { // An iterator is provided in order to traverse the linked list in a idiomatic // fashion. const LinkMap = extern struct { - l_addr: usize, - l_name: [*:0]const u8, - l_ld: ?*elf.Dyn, - l_next: ?*LinkMap, - l_prev: ?*LinkMap, + addr: usize, + name: [*:0]const u8, + ld: ?*elf.Dyn, + next: ?*LinkMap, + prev: ?*LinkMap, pub const Iterator = struct { current: ?*LinkMap, @@ -68,7 +78,7 @@ const LinkMap = extern struct { pub fn next(self: *Iterator) ?*LinkMap { if (self.current) |it| { - self.current = it.l_next; + self.current = it.next; return it; } return null; @@ -77,10 +87,10 @@ const LinkMap = extern struct { }; const RDebug = extern struct { - r_version: i32, - r_map: ?*LinkMap, - r_brk: usize, - r_ldbase: usize, + version: i32, + map: ?*LinkMap, + brk: usize, + ldbase: usize, }; /// TODO fix comparisons of extern symbol pointers so we don't need this helper function. @@ -105,8 +115,8 @@ pub fn linkmap_iterator() error{InvalidExe}!LinkMap.Iterator { elf.DT_DEBUG => { const ptr = @as(?*RDebug, @ptrFromInt(_DYNAMIC[i].d_val)); if (ptr) |r_debug| { - if (r_debug.r_version != 1) return error.InvalidExe; - break :init r_debug.r_map; + if (r_debug.version != 1) return error.InvalidExe; + break :init r_debug.map; } }, elf.DT_PLTGOT => { @@ -138,7 +148,7 @@ const ElfDynLibError = error{ ElfHashTableNotFound, Canceled, Streaming, -} || posix.OpenError || posix.MMapError; +} || Io.File.OpenError || posix.MMapError; pub const ElfDynLib = struct { strings: [*:0]u8, @@ -155,39 +165,32 @@ pub const ElfDynLib = struct { dt_gnu_hash: *elf.gnu_hash.Header, }; - fn openPath(path: []const u8) !std.fs.Dir { + fn openPath(io: Io, path: []const u8) !Io.Dir { if (path.len == 0) return error.NotDir; var parts = std.mem.tokenizeScalar(u8, path, '/'); - var parent = if (path[0] == '/') try std.fs.cwd().openDir("/", .{}) else std.fs.cwd(); + var parent = if (path[0] == '/') try Io.Dir.cwd().openDir(io, "/", .{}) else Io.Dir.cwd(); while (parts.next()) |part| { - const child = try parent.openDir(part, .{}); - parent.close(); + const child = try parent.openDir(io, part, .{}); + parent.close(io); parent = child; } return parent; } - fn resolveFromSearchPath(search_path: []const u8, file_name: []const u8, delim: u8) ?posix.fd_t { + fn resolveFromSearchPath(io: Io, search_path: []const u8, file_name: []const u8, delim: u8) ?Io.File { var paths = std.mem.tokenizeScalar(u8, search_path, delim); while (paths.next()) |p| { - var dir = openPath(p) catch continue; - defer dir.close(); - const fd = posix.openat(dir.fd, file_name, .{ - .ACCMODE = .RDONLY, - .CLOEXEC = true, - }, 0) catch continue; - return fd; + var dir = openPath(io, p) catch continue; + defer dir.close(io); + return dir.openFile(io, file_name, .{}) catch continue; } return null; } - fn resolveFromParent(dir_path: []const u8, file_name: []const u8) ?posix.fd_t { - var dir = std.fs.cwd().openDir(dir_path, .{}) catch return null; - defer dir.close(); - return posix.openat(dir.fd, file_name, .{ - .ACCMODE = .RDONLY, - .CLOEXEC = true, - }, 0) catch null; + fn resolveFromParent(io: Io, dir_path: []const u8, file_name: []const u8) ?Io.File { + var dir = Io.Dir.cwd().openDir(io, dir_path, .{}) catch return null; + defer dir.close(io); + return dir.openFile(io, file_name, .{}) catch null; } // This implements enough to be able to load system libraries in general @@ -195,36 +198,37 @@ pub const ElfDynLib = struct { // - DT_RPATH of the calling binary is not used as a search path // - DT_RUNPATH of the calling binary is not used as a search path // - /etc/ld.so.cache is not read - fn resolveFromName(path_or_name: []const u8) !posix.fd_t { + fn resolveFromName(io: Io, path_or_name: []const u8, LD_LIBRARY_PATH: ?[]const u8) !Io.File { // If filename contains a slash ("/"), then it is interpreted as a (relative or absolute) pathname - if (std.mem.indexOfScalarPos(u8, path_or_name, 0, '/')) |_| { - return posix.open(path_or_name, .{ .ACCMODE = .RDONLY, .CLOEXEC = true }, 0); + if (std.mem.findScalarPos(u8, path_or_name, 0, '/')) |_| { + return Io.Dir.cwd().openFile(io, path_or_name, .{}); } // Only read LD_LIBRARY_PATH if the binary is not setuid/setgid if (std.os.linux.geteuid() == std.os.linux.getuid() and std.os.linux.getegid() == std.os.linux.getgid()) { - if (posix.getenvZ("LD_LIBRARY_PATH")) |ld_library_path| { - if (resolveFromSearchPath(ld_library_path, path_or_name, ':')) |fd| { - return fd; + if (LD_LIBRARY_PATH) |ld_library_path| { + if (resolveFromSearchPath(io, ld_library_path, path_or_name, ':')) |file| { + return file; } } } // Lastly the directories /lib and /usr/lib are searched (in this exact order) - if (resolveFromParent("/lib", path_or_name)) |fd| return fd; - if (resolveFromParent("/usr/lib", path_or_name)) |fd| return fd; + if (resolveFromParent(io, "/lib", path_or_name)) |file| return file; + if (resolveFromParent(io, "/usr/lib", path_or_name)) |file| return file; return error.FileNotFound; } /// Trusts the file. Malicious file will be able to execute arbitrary code. - pub fn open(path: []const u8) Error!ElfDynLib { - const fd = try resolveFromName(path); - defer posix.close(fd); + pub fn open(path: []const u8, LD_LIBRARY_PATH: ?[]const u8) Error!ElfDynLib { + const io = std.Options.debug_io; - const file: std.fs.File = .{ .handle = fd }; - const stat = try file.stat(); + const file = try resolveFromName(io, path, LD_LIBRARY_PATH); + defer file.close(io); + + const stat = try file.stat(io); const size = std.math.cast(usize, stat.size) orelse return error.FileTooBig; const page_size = std.heap.pageSize(); @@ -236,7 +240,7 @@ pub const ElfDynLib = struct { mem.alignForward(usize, size, page_size), posix.PROT.READ, .{ .TYPE = .PRIVATE }, - fd, + file.handle, 0, ); defer posix.munmap(file_bytes); @@ -306,7 +310,7 @@ pub const ElfDynLib = struct { extended_memsz, prot, .{ .TYPE = .PRIVATE, .FIXED = true }, - fd, + file.handle, ph.p_offset - extra_bytes, ); } else { @@ -367,8 +371,8 @@ pub const ElfDynLib = struct { } /// Trusts the file. Malicious file will be able to execute arbitrary code. - pub fn openZ(path_c: [*:0]const u8) Error!ElfDynLib { - return open(mem.sliceTo(path_c, 0)); + pub fn openZ(path_c: [*:0]const u8, LD_LIBRARY_PATH: ?[]const u8) Error!ElfDynLib { + return open(mem.sliceTo(path_c, 0), LD_LIBRARY_PATH); } /// Trusts the file @@ -549,11 +553,9 @@ fn checkver(def_arg: *elf.Verdef, vsym_arg: elf.Versym, vername: []const u8, str } test "ElfDynLib" { - if (native_os != .linux) { - return error.SkipZigTest; - } - - try testing.expectError(error.FileNotFound, ElfDynLib.open("invalid_so.so")); + if (native_os != .linux) return error.SkipZigTest; + try testing.expectError(error.FileNotFound, ElfDynLib.open("invalid_so.so", null)); + try testing.expectError(error.FileNotFound, ElfDynLib.openZ("invalid_so.so", null)); } /// Separated to avoid referencing `WindowsDynLib`, because its field types may not diff --git a/lib/std/elf.zig b/lib/std/elf.zig index 935507a19221..ec5e0be951d1 100644 --- a/lib/std/elf.zig +++ b/lib/std/elf.zig @@ -3039,7 +3039,7 @@ pub const ar_hdr = extern struct { pub fn name(self: *const ar_hdr) ?[]const u8 { const value = &self.ar_name; if (value[0] == '/') return null; - const sentinel = mem.indexOfScalar(u8, value, '/') orelse value.len; + const sentinel = mem.findScalar(u8, value, '/') orelse value.len; return value[0..sentinel]; } diff --git a/lib/std/enums.zig b/lib/std/enums.zig index ffc678d77207..76deff5421ad 100644 --- a/lib/std/enums.zig +++ b/lib/std/enums.zig @@ -22,7 +22,7 @@ pub fn fromInt(comptime E: type, integer: anytype) ?E { // without requiring an inline loop. // This generates better machine code. for (values(E)) |value| { - if (@intFromEnum(value) == integer) return @enumFromInt(integer); + if (@intFromEnum(value) == integer) return value; } return null; } @@ -61,7 +61,9 @@ pub fn values(comptime E: type) []const E { /// panic when `e` has no tagged value. /// Returns the tag name for `e` or null if no tag exists. pub fn tagName(comptime E: type, e: E) ?[:0]const u8 { - return inline for (@typeInfo(E).@"enum".fields) |f| { + const fields = @typeInfo(E).@"enum".fields; + @setEvalBranchQuota(fields.len); + return inline for (fields) |f| { if (@intFromEnum(e) == f.value) break f.name; } else null; } @@ -202,48 +204,6 @@ test "directEnumArrayDefault slice" { try testing.expectEqualSlices(u8, "default", array[2]); } -/// Deprecated: Use @field(E, @tagName(tag)) or @field(E, string) -pub fn nameCast(comptime E: type, comptime value: anytype) E { - return comptime blk: { - const V = @TypeOf(value); - if (V == E) break :blk value; - const name: ?[]const u8 = switch (@typeInfo(V)) { - .enum_literal, .@"enum" => @tagName(value), - .pointer => value, - else => null, - }; - if (name) |n| { - if (@hasField(E, n)) { - break :blk @field(E, n); - } - @compileError("Enum " ++ @typeName(E) ++ " has no field named " ++ n); - } - @compileError("Cannot cast from " ++ @typeName(@TypeOf(value)) ++ " to " ++ @typeName(E)); - }; -} - -test nameCast { - const A = enum(u1) { a = 0, b = 1 }; - const B = enum(u1) { a = 1, b = 0 }; - try testing.expectEqual(A.a, nameCast(A, .a)); - try testing.expectEqual(A.a, nameCast(A, A.a)); - try testing.expectEqual(A.a, nameCast(A, B.a)); - try testing.expectEqual(A.a, nameCast(A, "a")); - try testing.expectEqual(A.a, nameCast(A, @as(*const [1]u8, "a"))); - try testing.expectEqual(A.a, nameCast(A, @as([:0]const u8, "a"))); - try testing.expectEqual(A.a, nameCast(A, @as([]const u8, "a"))); - - try testing.expectEqual(B.a, nameCast(B, .a)); - try testing.expectEqual(B.a, nameCast(B, A.a)); - try testing.expectEqual(B.a, nameCast(B, B.a)); - try testing.expectEqual(B.a, nameCast(B, "a")); - - try testing.expectEqual(B.b, nameCast(B, .b)); - try testing.expectEqual(B.b, nameCast(B, A.b)); - try testing.expectEqual(B.b, nameCast(B, B.b)); - try testing.expectEqual(B.b, nameCast(B, "b")); -} - test fromInt { const E1 = enum { A, @@ -253,6 +213,7 @@ test fromInt { B, }; const E3 = enum(i8) { A, _ }; + const E4 = enum(u8) { A }; var zero: u8 = 0; var one: u16 = 1; @@ -266,6 +227,10 @@ test fromInt { try testing.expectEqual(null, fromInt(E1, one)); try testing.expectEqual(null, fromInt(E3, 128)); try testing.expectEqual(null, fromInt(E3, -129)); + + // `fromInt` used to produce a compiler error instead of `null` if trying to convert an integer + // that wasn't out of range, but also wasn't a valid value. + try testing.expectEqual(null, fromInt(E4, 1)); } /// A set of enum elements, backed by a bitfield. If the enum diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index f9d8ffed5d5f..f8affb68b299 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -182,7 +182,7 @@ pub const Parser = struct { pub fn until(self: *@This(), delimiter: u8) []const u8 { const start = self.i; - self.i = std.mem.indexOfScalarPos(u8, self.bytes, self.i, delimiter) orelse self.bytes.len; + self.i = std.mem.findScalarPos(u8, self.bytes, self.i, delimiter) orelse self.bytes.len; return self.bytes[start..self.i]; } diff --git a/lib/std/fs.zig b/lib/std/fs.zig index 26ce27e2b393..a127da1696d3 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -1,578 +1,21 @@ //! File System. -const builtin = @import("builtin"); -const native_os = builtin.os.tag; const std = @import("std.zig"); -const Io = std.Io; -const root = @import("root"); -const mem = std.mem; -const base64 = std.base64; -const crypto = std.crypto; -const Allocator = std.mem.Allocator; -const assert = std.debug.assert; -const posix = std.posix; -const windows = std.os.windows; -const is_darwin = native_os.isDarwin(); - -pub const AtomicFile = @import("fs/AtomicFile.zig"); -pub const Dir = @import("fs/Dir.zig"); -pub const File = @import("fs/File.zig"); +/// Deprecated, use `std.Io.Dir.path`. pub const path = @import("fs/path.zig"); - -pub const has_executable_bit = switch (native_os) { - .windows, .wasi => false, - else => true, -}; - -pub const wasi = @import("fs/wasi.zig"); - -// TODO audit these APIs with respect to Dir and absolute paths - -pub const realpath = posix.realpath; -pub const realpathZ = posix.realpathZ; -pub const realpathW = posix.realpathW; -pub const realpathW2 = posix.realpathW2; - -pub const getAppDataDir = @import("fs/get_app_data_dir.zig").getAppDataDir; -pub const GetAppDataDirError = @import("fs/get_app_data_dir.zig").GetAppDataDirError; - -/// The maximum length of a file path that the operating system will accept. -/// -/// Paths, including those returned from file system operations, may be longer -/// than this length, but such paths cannot be successfully passed back in -/// other file system operations. However, all path components returned by file -/// system operations are assumed to fit into a `u8` array of this length. -/// -/// The byte count includes room for a null sentinel byte. -/// -/// * On Windows, `[]u8` file paths are encoded as -/// [WTF-8](https://wtf-8.codeberg.page/). -/// * On WASI, `[]u8` file paths are encoded as valid UTF-8. -/// * On other platforms, `[]u8` file paths are opaque sequences of bytes with -/// no particular encoding. -pub const max_path_bytes = switch (native_os) { - .linux, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos, .freebsd, .openbsd, .netbsd, .dragonfly, .haiku, .illumos, .plan9, .emscripten, .wasi, .serenity => posix.PATH_MAX, - // Each WTF-16LE code unit may be expanded to 3 WTF-8 bytes. - // If it would require 4 WTF-8 bytes, then there would be a surrogate - // pair in the WTF-16LE, and we (over)account 3 bytes for it that way. - // +1 for the null byte at the end, which can be encoded in 1 byte. - .windows => windows.PATH_MAX_WIDE * 3 + 1, - else => if (@hasDecl(root, "os") and @hasDecl(root.os, "PATH_MAX")) - root.os.PATH_MAX - else - @compileError("PATH_MAX not implemented for " ++ @tagName(native_os)), -}; - -/// This represents the maximum size of a `[]u8` file name component that -/// the platform's common file systems support. File name components returned by file system -/// operations are likely to fit into a `u8` array of this length, but -/// (depending on the platform) this assumption may not hold for every configuration. -/// The byte count does not include a null sentinel byte. -/// On Windows, `[]u8` file name components are encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, file name components are encoded as valid UTF-8. -/// On other platforms, `[]u8` components are an opaque sequence of bytes with no particular encoding. -pub const max_name_bytes = switch (native_os) { - .linux, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos, .freebsd, .openbsd, .netbsd, .dragonfly, .illumos, .serenity => posix.NAME_MAX, - // Haiku's NAME_MAX includes the null terminator, so subtract one. - .haiku => posix.NAME_MAX - 1, - // Each WTF-16LE character may be expanded to 3 WTF-8 bytes. - // If it would require 4 WTF-8 bytes, then there would be a surrogate - // pair in the WTF-16LE, and we (over)account 3 bytes for it that way. - .windows => windows.NAME_MAX * 3, - // For WASI, the MAX_NAME will depend on the host OS, so it needs to be - // as large as the largest max_name_bytes (Windows) in order to work on any host OS. - // TODO determine if this is a reasonable approach - .wasi => windows.NAME_MAX * 3, - else => if (@hasDecl(root, "os") and @hasDecl(root.os, "NAME_MAX")) - root.os.NAME_MAX - else - @compileError("NAME_MAX not implemented for " ++ @tagName(native_os)), -}; - -pub const base64_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".*; - -/// Base64 encoder, replacing the standard `+/` with `-_` so that it can be used in a file name on any filesystem. -pub const base64_encoder = base64.Base64Encoder.init(base64_alphabet, null); - -/// Base64 decoder, replacing the standard `+/` with `-_` so that it can be used in a file name on any filesystem. -pub const base64_decoder = base64.Base64Decoder.init(base64_alphabet, null); - -/// Same as `Dir.copyFile`, except asserts that both `source_path` and `dest_path` -/// are absolute. See `Dir.copyFile` for a function that operates on both -/// absolute and relative paths. -/// On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, both paths should be encoded as valid UTF-8. -/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding. -pub fn copyFileAbsolute( - source_path: []const u8, - dest_path: []const u8, - args: Dir.CopyFileOptions, -) !void { - assert(path.isAbsolute(source_path)); - assert(path.isAbsolute(dest_path)); - const my_cwd = cwd(); - return Dir.copyFile(my_cwd, source_path, my_cwd, dest_path, args); -} - -test copyFileAbsolute {} - -/// Create a new directory, based on an absolute path. -/// Asserts that the path is absolute. See `Dir.makeDir` for a function that operates -/// on both absolute and relative paths. -/// On Windows, `absolute_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `absolute_path` should be encoded as valid UTF-8. -/// On other platforms, `absolute_path` is an opaque sequence of bytes with no particular encoding. -pub fn makeDirAbsolute(absolute_path: []const u8) !void { - assert(path.isAbsolute(absolute_path)); - return posix.mkdir(absolute_path, Dir.default_mode); -} - -test makeDirAbsolute {} - -/// Same as `makeDirAbsolute` except the parameter is null-terminated. -pub fn makeDirAbsoluteZ(absolute_path_z: [*:0]const u8) !void { - assert(path.isAbsoluteZ(absolute_path_z)); - return posix.mkdirZ(absolute_path_z, Dir.default_mode); -} - -test makeDirAbsoluteZ {} - -/// Same as `Dir.deleteDir` except the path is absolute. -/// On Windows, `dir_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `dir_path` should be encoded as valid UTF-8. -/// On other platforms, `dir_path` is an opaque sequence of bytes with no particular encoding. -pub fn deleteDirAbsolute(dir_path: []const u8) !void { - assert(path.isAbsolute(dir_path)); - return posix.rmdir(dir_path); -} - -/// Same as `deleteDirAbsolute` except the path parameter is null-terminated. -pub fn deleteDirAbsoluteZ(dir_path: [*:0]const u8) !void { - assert(path.isAbsoluteZ(dir_path)); - return posix.rmdirZ(dir_path); -} - -/// Same as `Dir.rename` except the paths are absolute. -/// On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, both paths should be encoded as valid UTF-8. -/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding. -pub fn renameAbsolute(old_path: []const u8, new_path: []const u8) !void { - assert(path.isAbsolute(old_path)); - assert(path.isAbsolute(new_path)); - return posix.rename(old_path, new_path); -} - -/// Same as `renameAbsolute` except the path parameters are null-terminated. -pub fn renameAbsoluteZ(old_path: [*:0]const u8, new_path: [*:0]const u8) !void { - assert(path.isAbsoluteZ(old_path)); - assert(path.isAbsoluteZ(new_path)); - return posix.renameZ(old_path, new_path); -} - -/// Same as `Dir.rename`, except `new_sub_path` is relative to `new_dir` -pub fn rename(old_dir: Dir, old_sub_path: []const u8, new_dir: Dir, new_sub_path: []const u8) !void { - return posix.renameat(old_dir.fd, old_sub_path, new_dir.fd, new_sub_path); -} - -/// Same as `rename` except the parameters are null-terminated. -pub fn renameZ(old_dir: Dir, old_sub_path_z: [*:0]const u8, new_dir: Dir, new_sub_path_z: [*:0]const u8) !void { - return posix.renameatZ(old_dir.fd, old_sub_path_z, new_dir.fd, new_sub_path_z); -} - -/// Deprecated in favor of `Io.Dir.cwd`. -pub fn cwd() Dir { - if (native_os == .windows) { - return .{ .fd = windows.peb().ProcessParameters.CurrentDirectory.Handle }; - } else if (native_os == .wasi) { - return .{ .fd = std.options.wasiCwd() }; - } else { - return .{ .fd = posix.AT.FDCWD }; - } -} - -pub fn defaultWasiCwd() std.os.wasi.fd_t { - // Expect the first preopen to be current working directory. - return 3; -} - -/// Opens a directory at the given path. The directory is a system resource that remains -/// open until `close` is called on the result. -/// See `openDirAbsoluteZ` for a function that accepts a null-terminated path. -/// -/// Asserts that the path parameter has no null bytes. -/// On Windows, `absolute_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `absolute_path` should be encoded as valid UTF-8. -/// On other platforms, `absolute_path` is an opaque sequence of bytes with no particular encoding. -pub fn openDirAbsolute(absolute_path: []const u8, flags: Dir.OpenOptions) File.OpenError!Dir { - assert(path.isAbsolute(absolute_path)); - return cwd().openDir(absolute_path, flags); -} - -/// Same as `openDirAbsolute` but the path parameter is null-terminated. -pub fn openDirAbsoluteZ(absolute_path_c: [*:0]const u8, flags: Dir.OpenOptions) File.OpenError!Dir { - assert(path.isAbsoluteZ(absolute_path_c)); - return cwd().openDirZ(absolute_path_c, flags); -} -/// Opens a file for reading or writing, without attempting to create a new file, based on an absolute path. -/// Call `File.close` to release the resource. -/// Asserts that the path is absolute. See `Dir.openFile` for a function that -/// operates on both absolute and relative paths. -/// Asserts that the path parameter has no null bytes. See `openFileAbsoluteZ` for a function -/// that accepts a null-terminated path. -/// On Windows, `absolute_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `absolute_path` should be encoded as valid UTF-8. -/// On other platforms, `absolute_path` is an opaque sequence of bytes with no particular encoding. -pub fn openFileAbsolute(absolute_path: []const u8, flags: File.OpenFlags) File.OpenError!File { - assert(path.isAbsolute(absolute_path)); - return cwd().openFile(absolute_path, flags); -} - -/// Test accessing `path`. -/// Be careful of Time-Of-Check-Time-Of-Use race conditions when using this function. -/// For example, instead of testing if a file exists and then opening it, just -/// open it and handle the error for file not found. -/// See `accessAbsoluteZ` for a function that accepts a null-terminated path. -/// On Windows, `absolute_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `absolute_path` should be encoded as valid UTF-8. -/// On other platforms, `absolute_path` is an opaque sequence of bytes with no particular encoding. -pub fn accessAbsolute(absolute_path: []const u8, flags: Io.Dir.AccessOptions) Dir.AccessError!void { - assert(path.isAbsolute(absolute_path)); - try cwd().access(absolute_path, flags); -} -/// Creates, opens, or overwrites a file with write access, based on an absolute path. -/// Call `File.close` to release the resource. -/// Asserts that the path is absolute. See `Dir.createFile` for a function that -/// operates on both absolute and relative paths. -/// Asserts that the path parameter has no null bytes. See `createFileAbsoluteC` for a function -/// that accepts a null-terminated path. -/// On Windows, `absolute_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `absolute_path` should be encoded as valid UTF-8. -/// On other platforms, `absolute_path` is an opaque sequence of bytes with no particular encoding. -pub fn createFileAbsolute(absolute_path: []const u8, flags: File.CreateFlags) File.OpenError!File { - assert(path.isAbsolute(absolute_path)); - return cwd().createFile(absolute_path, flags); -} - -/// Delete a file name and possibly the file it refers to, based on an absolute path. -/// Asserts that the path is absolute. See `Dir.deleteFile` for a function that -/// operates on both absolute and relative paths. -/// Asserts that the path parameter has no null bytes. -/// On Windows, `absolute_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `absolute_path` should be encoded as valid UTF-8. -/// On other platforms, `absolute_path` is an opaque sequence of bytes with no particular encoding. -pub fn deleteFileAbsolute(absolute_path: []const u8) Dir.DeleteFileError!void { - assert(path.isAbsolute(absolute_path)); - return cwd().deleteFile(absolute_path); -} - -/// Removes a symlink, file, or directory. -/// This is equivalent to `Dir.deleteTree` with the base directory. -/// Asserts that the path is absolute. See `Dir.deleteTree` for a function that -/// operates on both absolute and relative paths. -/// Asserts that the path parameter has no null bytes. -/// On Windows, `absolute_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `absolute_path` should be encoded as valid UTF-8. -/// On other platforms, `absolute_path` is an opaque sequence of bytes with no particular encoding. -pub fn deleteTreeAbsolute(absolute_path: []const u8) !void { - assert(path.isAbsolute(absolute_path)); - const dirname = path.dirname(absolute_path) orelse return error{ - /// Attempt to remove the root file system path. - /// This error is unreachable if `absolute_path` is relative. - CannotDeleteRootDirectory, - }.CannotDeleteRootDirectory; - - var dir = try cwd().openDir(dirname, .{}); - defer dir.close(); - - return dir.deleteTree(path.basename(absolute_path)); -} - -/// Same as `Dir.readLink`, except it asserts the path is absolute. -/// On Windows, `pathname` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `pathname` should be encoded as valid UTF-8. -/// On other platforms, `pathname` is an opaque sequence of bytes with no particular encoding. -pub fn readLinkAbsolute(pathname: []const u8, buffer: *[max_path_bytes]u8) ![]u8 { - assert(path.isAbsolute(pathname)); - return posix.readlink(pathname, buffer); -} - -/// Creates a symbolic link named `sym_link_path` which contains the string `target_path`. -/// A symbolic link (also known as a soft link) may point to an existing file or to a nonexistent -/// one; the latter case is known as a dangling link. -/// If `sym_link_path` exists, it will not be overwritten. -/// See also `symLinkAbsoluteZ` and `symLinkAbsoluteW`. -/// On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, both paths should be encoded as valid UTF-8. -/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding. -pub fn symLinkAbsolute( - target_path: []const u8, - sym_link_path: []const u8, - flags: Dir.SymLinkFlags, -) !void { - assert(path.isAbsolute(target_path)); - assert(path.isAbsolute(sym_link_path)); - if (native_os == .windows) { - const target_path_w = try windows.sliceToPrefixedFileW(null, target_path); - const sym_link_path_w = try windows.sliceToPrefixedFileW(null, sym_link_path); - return windows.CreateSymbolicLink(null, sym_link_path_w.span(), target_path_w.span(), flags.is_directory); - } - return posix.symlink(target_path, sym_link_path); -} - -/// Windows-only. Same as `symLinkAbsolute` except the parameters are null-terminated, WTF16 LE encoded. -/// Note that this function will by default try creating a symbolic link to a file. If you would -/// like to create a symbolic link to a directory, specify this with `SymLinkFlags{ .is_directory = true }`. -/// See also `symLinkAbsolute`, `symLinkAbsoluteZ`. -pub fn symLinkAbsoluteW( - target_path_w: [*:0]const u16, - sym_link_path_w: [*:0]const u16, - flags: Dir.SymLinkFlags, -) !void { - assert(path.isAbsoluteWindowsW(target_path_w)); - assert(path.isAbsoluteWindowsW(sym_link_path_w)); - return windows.CreateSymbolicLink(null, mem.span(sym_link_path_w), mem.span(target_path_w), flags.is_directory); -} - -pub const OpenSelfExeError = Io.File.OpenSelfExeError; - -/// Deprecated in favor of `Io.File.openSelfExe`. -pub fn openSelfExe(flags: File.OpenFlags) OpenSelfExeError!File { - if (native_os == .linux or native_os == .serenity or native_os == .windows) { - var threaded: Io.Threaded = .init_single_threaded; - const io = threaded.ioBasic(); - return .adaptFromNewApi(try Io.File.openSelfExe(io, flags)); - } - // Use of max_path_bytes here is valid as the resulting path is immediately - // opened with no modification. - var buf: [max_path_bytes]u8 = undefined; - const self_exe_path = try selfExePath(&buf); - buf[self_exe_path.len] = 0; - return openFileAbsolute(buf[0..self_exe_path.len :0], flags); -} - -// This is `posix.ReadLinkError || posix.RealPathError` with impossible errors excluded -pub const SelfExePathError = error{ - FileNotFound, - AccessDenied, - NameTooLong, - NotSupported, - NotDir, - SymLinkLoop, - InputOutput, - FileTooBig, - IsDir, - ProcessFdQuotaExceeded, - SystemFdQuotaExceeded, - NoDevice, - SystemResources, - NoSpaceLeft, - FileSystem, - BadPathName, - DeviceBusy, - SharingViolation, - PipeBusy, - NotLink, - PathAlreadyExists, - - /// On Windows, `\\server` or `\\server\share` was not found. - NetworkNotFound, - ProcessNotFound, - - /// On Windows, antivirus software is enabled by default. It can be - /// disabled, but Windows Update sometimes ignores the user's preference - /// and re-enables it. When enabled, antivirus software on Windows - /// intercepts file system operations and makes them significantly slower - /// in addition to possibly failing with this error code. - AntivirusInterference, - - /// On Windows, the volume does not contain a recognized file system. File - /// system drivers might not be loaded, or the volume may be corrupt. - UnrecognizedVolume, - - Canceled, -} || posix.SysCtlError; - -/// `selfExePath` except allocates the result on the heap. -/// Caller owns returned memory. -pub fn selfExePathAlloc(allocator: Allocator) ![]u8 { - // Use of max_path_bytes here is justified as, at least on one tested Linux - // system, readlink will completely fail to return a result larger than - // PATH_MAX even if given a sufficiently large buffer. This makes it - // fundamentally impossible to get the selfExePath of a program running in - // a very deeply nested directory chain in this way. - // TODO(#4812): Investigate other systems and whether it is possible to get - // this path by trying larger and larger buffers until one succeeds. - var buf: [max_path_bytes]u8 = undefined; - return allocator.dupe(u8, try selfExePath(&buf)); -} - -/// Get the path to the current executable. Follows symlinks. -/// If you only need the directory, use selfExeDirPath. -/// If you only want an open file handle, use openSelfExe. -/// This function may return an error if the current executable -/// was deleted after spawning. -/// Returned value is a slice of out_buffer. -/// On Windows, the result is encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On other platforms, the result is an opaque sequence of bytes with no particular encoding. -/// -/// On Linux, depends on procfs being mounted. If the currently executing binary has -/// been deleted, the file path looks something like `/a/b/c/exe (deleted)`. -/// TODO make the return type of this a null terminated pointer -pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 { - if (is_darwin) { - // Note that _NSGetExecutablePath() will return "a path" to - // the executable not a "real path" to the executable. - var symlink_path_buf: [max_path_bytes:0]u8 = undefined; - var u32_len: u32 = max_path_bytes + 1; // include the sentinel - const rc = std.c._NSGetExecutablePath(&symlink_path_buf, &u32_len); - if (rc != 0) return error.NameTooLong; - - var real_path_buf: [max_path_bytes]u8 = undefined; - const real_path = std.posix.realpathZ(&symlink_path_buf, &real_path_buf) catch |err| switch (err) { - error.NetworkNotFound => unreachable, // Windows-only - else => |e| return e, - }; - if (real_path.len > out_buffer.len) return error.NameTooLong; - const result = out_buffer[0..real_path.len]; - @memcpy(result, real_path); - return result; - } - switch (native_os) { - .linux, .serenity => return posix.readlinkZ("/proc/self/exe", out_buffer) catch |err| switch (err) { - error.UnsupportedReparsePointType => unreachable, // Windows-only - error.NetworkNotFound => unreachable, // Windows-only - else => |e| return e, - }, - .illumos => return posix.readlinkZ("/proc/self/path/a.out", out_buffer) catch |err| switch (err) { - error.UnsupportedReparsePointType => unreachable, // Windows-only - error.NetworkNotFound => unreachable, // Windows-only - else => |e| return e, - }, - .freebsd, .dragonfly => { - var mib = [4]c_int{ posix.CTL.KERN, posix.KERN.PROC, posix.KERN.PROC_PATHNAME, -1 }; - var out_len: usize = out_buffer.len; - try posix.sysctl(&mib, out_buffer.ptr, &out_len, null, 0); - // TODO could this slice from 0 to out_len instead? - return mem.sliceTo(out_buffer, 0); - }, - .netbsd => { - var mib = [4]c_int{ posix.CTL.KERN, posix.KERN.PROC_ARGS, -1, posix.KERN.PROC_PATHNAME }; - var out_len: usize = out_buffer.len; - try posix.sysctl(&mib, out_buffer.ptr, &out_len, null, 0); - // TODO could this slice from 0 to out_len instead? - return mem.sliceTo(out_buffer, 0); - }, - .openbsd, .haiku => { - // OpenBSD doesn't support getting the path of a running process, so try to guess it - if (std.os.argv.len == 0) - return error.FileNotFound; - - const argv0 = mem.span(std.os.argv[0]); - if (mem.indexOf(u8, argv0, "/") != null) { - // argv[0] is a path (relative or absolute): use realpath(3) directly - var real_path_buf: [max_path_bytes]u8 = undefined; - const real_path = posix.realpathZ(std.os.argv[0], &real_path_buf) catch |err| switch (err) { - error.NetworkNotFound => unreachable, // Windows-only - else => |e| return e, - }; - if (real_path.len > out_buffer.len) - return error.NameTooLong; - const result = out_buffer[0..real_path.len]; - @memcpy(result, real_path); - return result; - } else if (argv0.len != 0) { - // argv[0] is not empty (and not a path): search it inside PATH - const PATH = posix.getenvZ("PATH") orelse return error.FileNotFound; - var path_it = mem.tokenizeScalar(u8, PATH, path.delimiter); - while (path_it.next()) |a_path| { - var resolved_path_buf: [max_path_bytes - 1:0]u8 = undefined; - const resolved_path = std.fmt.bufPrintSentinel(&resolved_path_buf, "{s}/{s}", .{ - a_path, - std.os.argv[0], - 0, - }) catch continue; - - var real_path_buf: [max_path_bytes]u8 = undefined; - if (posix.realpathZ(resolved_path, &real_path_buf)) |real_path| { - // found a file, and hope it is the right file - if (real_path.len > out_buffer.len) - return error.NameTooLong; - const result = out_buffer[0..real_path.len]; - @memcpy(result, real_path); - return result; - } else |_| continue; - } - } - return error.FileNotFound; - }, - .windows => { - const image_path_unicode_string = &windows.peb().ProcessParameters.ImagePathName; - const image_path_name = image_path_unicode_string.Buffer.?[0 .. image_path_unicode_string.Length / 2 :0]; - - // If ImagePathName is a symlink, then it will contain the path of the - // symlink, not the path that the symlink points to. We want the path - // that the symlink points to, though, so we need to get the realpath. - var pathname_w = try windows.wToPrefixedFileW(null, image_path_name); - - const wide_slice = try std.fs.cwd().realpathW2(pathname_w.span(), &pathname_w.data); - - const len = std.unicode.calcWtf8Len(wide_slice); - if (len > out_buffer.len) - return error.NameTooLong; - - const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice); - return out_buffer[0..end_index]; - }, - else => @compileError("std.fs.selfExePath not supported for this target"), - } -} - -/// `selfExeDirPath` except allocates the result on the heap. -/// Caller owns returned memory. -pub fn selfExeDirPathAlloc(allocator: Allocator) ![]u8 { - // Use of max_path_bytes here is justified as, at least on one tested Linux - // system, readlink will completely fail to return a result larger than - // PATH_MAX even if given a sufficiently large buffer. This makes it - // fundamentally impossible to get the selfExeDirPath of a program running - // in a very deeply nested directory chain in this way. - // TODO(#4812): Investigate other systems and whether it is possible to get - // this path by trying larger and larger buffers until one succeeds. - var buf: [max_path_bytes]u8 = undefined; - return allocator.dupe(u8, try selfExeDirPath(&buf)); -} - -/// Get the directory path that contains the current executable. -/// Returned value is a slice of out_buffer. -/// On Windows, the result is encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On other platforms, the result is an opaque sequence of bytes with no particular encoding. -pub fn selfExeDirPath(out_buffer: []u8) SelfExePathError![]const u8 { - const self_exe_path = try selfExePath(out_buffer); - // Assume that the OS APIs return absolute paths, and therefore dirname - // will not return null. - return path.dirname(self_exe_path).?; -} - -/// `realpath`, except caller must free the returned memory. -/// On Windows, the result is encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On other platforms, the result is an opaque sequence of bytes with no particular encoding. -/// See also `Dir.realpath`. -pub fn realpathAlloc(allocator: Allocator, pathname: []const u8) ![]u8 { - // Use of max_path_bytes here is valid as the realpath function does not - // have a variant that takes an arbitrary-size buffer. - // TODO(#4812): Consider reimplementing realpath or using the POSIX.1-2008 - // NULL out parameter (GNU's canonicalize_file_name) to handle overelong - // paths. musl supports passing NULL but restricts the output to PATH_MAX - // anyway. - var buf: [max_path_bytes]u8 = undefined; - return allocator.dupe(u8, try posix.realpath(pathname, &buf)); -} +/// Deprecated, use `std.base64.url_safe_alphabet_chars`. +pub const base64_alphabet = std.base64.url_safe_alphabet_chars; +/// Deprecated, use `std.base64.url_safe.Encoder`. +pub const base64_encoder = std.base64.url_safe.Encoder; +/// Deprecated, use `std.base64.url_safe.Decoder`. +pub const base64_decoder = std.base64.url_safe.Decoder; +/// Deprecated, use `std.Io.Dir.max_path_bytes`. +pub const max_path_bytes = std.Io.Dir.max_path_bytes; +/// Deprecated, use `std.Io.Dir.max_name_bytes`. +pub const max_name_bytes = std.Io.Dir.max_name_bytes; test { - _ = AtomicFile; - _ = Dir; - _ = File; _ = path; _ = @import("fs/test.zig"); - _ = @import("fs/get_app_data_dir.zig"); } diff --git a/lib/std/fs/AtomicFile.zig b/lib/std/fs/AtomicFile.zig deleted file mode 100644 index 96793aec729f..000000000000 --- a/lib/std/fs/AtomicFile.zig +++ /dev/null @@ -1,94 +0,0 @@ -const AtomicFile = @This(); -const std = @import("../std.zig"); -const File = std.fs.File; -const Dir = std.fs.Dir; -const fs = std.fs; -const assert = std.debug.assert; -const posix = std.posix; - -file_writer: File.Writer, -random_integer: u64, -dest_basename: []const u8, -file_open: bool, -file_exists: bool, -close_dir_on_deinit: bool, -dir: Dir, - -pub const InitError = File.OpenError; - -/// Note that the `Dir.atomicFile` API may be more handy than this lower-level function. -pub fn init( - dest_basename: []const u8, - mode: File.Mode, - dir: Dir, - close_dir_on_deinit: bool, - write_buffer: []u8, -) InitError!AtomicFile { - while (true) { - const random_integer = std.crypto.random.int(u64); - const tmp_sub_path = std.fmt.hex(random_integer); - const file = dir.createFile(&tmp_sub_path, .{ .mode = mode, .exclusive = true }) catch |err| switch (err) { - error.PathAlreadyExists => continue, - else => |e| return e, - }; - return .{ - .file_writer = file.writer(write_buffer), - .random_integer = random_integer, - .dest_basename = dest_basename, - .file_open = true, - .file_exists = true, - .close_dir_on_deinit = close_dir_on_deinit, - .dir = dir, - }; - } -} - -/// Always call deinit, even after a successful finish(). -pub fn deinit(af: *AtomicFile) void { - if (af.file_open) { - af.file_writer.file.close(); - af.file_open = false; - } - if (af.file_exists) { - const tmp_sub_path = std.fmt.hex(af.random_integer); - af.dir.deleteFile(&tmp_sub_path) catch {}; - af.file_exists = false; - } - if (af.close_dir_on_deinit) { - af.dir.close(); - } - af.* = undefined; -} - -pub const FlushError = File.WriteError; - -pub fn flush(af: *AtomicFile) FlushError!void { - af.file_writer.interface.flush() catch |err| switch (err) { - error.WriteFailed => return af.file_writer.err.?, - }; -} - -pub const RenameIntoPlaceError = posix.RenameError; - -/// On Windows, this function introduces a period of time where some file -/// system operations on the destination file will result in -/// `error.AccessDenied`, including rename operations (such as the one used in -/// this function). -pub fn renameIntoPlace(af: *AtomicFile) RenameIntoPlaceError!void { - assert(af.file_exists); - if (af.file_open) { - af.file_writer.file.close(); - af.file_open = false; - } - const tmp_sub_path = std.fmt.hex(af.random_integer); - try posix.renameat(af.dir.fd, &tmp_sub_path, af.dir.fd, af.dest_basename); - af.file_exists = false; -} - -pub const FinishError = FlushError || RenameIntoPlaceError; - -/// Combination of `flush` followed by `renameIntoPlace`. -pub fn finish(af: *AtomicFile) FinishError!void { - try af.flush(); - try af.renameIntoPlace(); -} diff --git a/lib/std/fs/Dir.zig b/lib/std/fs/Dir.zig deleted file mode 100644 index 23bd903fe8df..000000000000 --- a/lib/std/fs/Dir.zig +++ /dev/null @@ -1,2066 +0,0 @@ -//! Deprecated in favor of `Io.Dir`. -const Dir = @This(); - -const builtin = @import("builtin"); -const native_os = builtin.os.tag; - -const std = @import("../std.zig"); -const Io = std.Io; -const File = std.fs.File; -const AtomicFile = std.fs.AtomicFile; -const base64_encoder = fs.base64_encoder; -const posix = std.posix; -const mem = std.mem; -const path = fs.path; -const fs = std.fs; -const Allocator = std.mem.Allocator; -const assert = std.debug.assert; -const linux = std.os.linux; -const windows = std.os.windows; -const have_flock = @TypeOf(posix.system.flock) != void; - -fd: Handle, - -pub const Handle = posix.fd_t; - -pub const default_mode = 0o755; - -pub const Entry = struct { - name: []const u8, - kind: Kind, - - pub const Kind = File.Kind; -}; - -const IteratorError = error{ - AccessDenied, - PermissionDenied, - SystemResources, -} || posix.UnexpectedError; - -pub const Iterator = switch (native_os) { - .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos, .freebsd, .netbsd, .dragonfly, .openbsd, .illumos => struct { - dir: Dir, - seek: i64, - buf: [1024]u8 align(@alignOf(posix.system.dirent)), - index: usize, - end_index: usize, - first_iter: bool, - - const Self = @This(); - - pub const Error = IteratorError; - - /// Memory such as file names referenced in this returned entry becomes invalid - /// with subsequent calls to `next`, as well as when this `Dir` is deinitialized. - pub fn next(self: *Self) Error!?Entry { - switch (native_os) { - .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => return self.nextDarwin(), - .freebsd, .netbsd, .dragonfly, .openbsd => return self.nextBsd(), - .illumos => return self.nextIllumos(), - else => @compileError("unimplemented"), - } - } - - fn nextDarwin(self: *Self) !?Entry { - start_over: while (true) { - if (self.index >= self.end_index) { - if (self.first_iter) { - posix.lseek_SET(self.dir.fd, 0) catch unreachable; // EBADF here likely means that the Dir was not opened with iteration permissions - self.first_iter = false; - } - const rc = posix.system.getdirentries( - self.dir.fd, - &self.buf, - self.buf.len, - &self.seek, - ); - if (rc == 0) return null; - if (rc < 0) { - switch (posix.errno(rc)) { - .BADF => unreachable, // Dir is invalid or was opened without iteration ability - .FAULT => unreachable, - .NOTDIR => unreachable, - .INVAL => unreachable, - else => |err| return posix.unexpectedErrno(err), - } - } - self.index = 0; - self.end_index = @as(usize, @intCast(rc)); - } - const darwin_entry = @as(*align(1) posix.system.dirent, @ptrCast(&self.buf[self.index])); - const next_index = self.index + darwin_entry.reclen; - self.index = next_index; - - const name = @as([*]u8, @ptrCast(&darwin_entry.name))[0..darwin_entry.namlen]; - - if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..") or (darwin_entry.ino == 0)) { - continue :start_over; - } - - const entry_kind: Entry.Kind = switch (darwin_entry.type) { - posix.DT.BLK => .block_device, - posix.DT.CHR => .character_device, - posix.DT.DIR => .directory, - posix.DT.FIFO => .named_pipe, - posix.DT.LNK => .sym_link, - posix.DT.REG => .file, - posix.DT.SOCK => .unix_domain_socket, - posix.DT.WHT => .whiteout, - else => .unknown, - }; - return Entry{ - .name = name, - .kind = entry_kind, - }; - } - } - - fn nextIllumos(self: *Self) !?Entry { - start_over: while (true) { - if (self.index >= self.end_index) { - if (self.first_iter) { - posix.lseek_SET(self.dir.fd, 0) catch unreachable; // EBADF here likely means that the Dir was not opened with iteration permissions - self.first_iter = false; - } - const rc = posix.system.getdents(self.dir.fd, &self.buf, self.buf.len); - switch (posix.errno(rc)) { - .SUCCESS => {}, - .BADF => unreachable, // Dir is invalid or was opened without iteration ability - .FAULT => unreachable, - .NOTDIR => unreachable, - .INVAL => unreachable, - else => |err| return posix.unexpectedErrno(err), - } - if (rc == 0) return null; - self.index = 0; - self.end_index = @as(usize, @intCast(rc)); - } - const entry = @as(*align(1) posix.system.dirent, @ptrCast(&self.buf[self.index])); - const next_index = self.index + entry.reclen; - self.index = next_index; - - const name = mem.sliceTo(@as([*:0]u8, @ptrCast(&entry.name)), 0); - if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..")) - continue :start_over; - - // illumos dirent doesn't expose type, so we have to call stat to get it. - const stat_info = posix.fstatat( - self.dir.fd, - name, - posix.AT.SYMLINK_NOFOLLOW, - ) catch |err| switch (err) { - error.NameTooLong => unreachable, - error.SymLinkLoop => unreachable, - error.FileNotFound => unreachable, // lost the race - else => |e| return e, - }; - const entry_kind: Entry.Kind = switch (stat_info.mode & posix.S.IFMT) { - posix.S.IFIFO => .named_pipe, - posix.S.IFCHR => .character_device, - posix.S.IFDIR => .directory, - posix.S.IFBLK => .block_device, - posix.S.IFREG => .file, - posix.S.IFLNK => .sym_link, - posix.S.IFSOCK => .unix_domain_socket, - posix.S.IFDOOR => .door, - posix.S.IFPORT => .event_port, - else => .unknown, - }; - return Entry{ - .name = name, - .kind = entry_kind, - }; - } - } - - fn nextBsd(self: *Self) !?Entry { - start_over: while (true) { - if (self.index >= self.end_index) { - if (self.first_iter) { - posix.lseek_SET(self.dir.fd, 0) catch unreachable; // EBADF here likely means that the Dir was not opened with iteration permissions - self.first_iter = false; - } - const rc = posix.system.getdents(self.dir.fd, &self.buf, self.buf.len); - switch (posix.errno(rc)) { - .SUCCESS => {}, - .BADF => unreachable, // Dir is invalid or was opened without iteration ability - .FAULT => unreachable, - .NOTDIR => unreachable, - .INVAL => unreachable, - // Introduced in freebsd 13.2: directory unlinked but still open. - // To be consistent, iteration ends if the directory being iterated is deleted during iteration. - .NOENT => return null, - else => |err| return posix.unexpectedErrno(err), - } - if (rc == 0) return null; - self.index = 0; - self.end_index = @as(usize, @intCast(rc)); - } - const bsd_entry = @as(*align(1) posix.system.dirent, @ptrCast(&self.buf[self.index])); - const next_index = self.index + - if (@hasField(posix.system.dirent, "reclen")) bsd_entry.reclen else bsd_entry.reclen(); - self.index = next_index; - - const name = @as([*]u8, @ptrCast(&bsd_entry.name))[0..bsd_entry.namlen]; - - const skip_zero_fileno = switch (native_os) { - // fileno=0 is used to mark invalid entries or deleted files. - .openbsd, .netbsd => true, - else => false, - }; - if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..") or - (skip_zero_fileno and bsd_entry.fileno == 0)) - { - continue :start_over; - } - - const entry_kind: Entry.Kind = switch (bsd_entry.type) { - posix.DT.BLK => .block_device, - posix.DT.CHR => .character_device, - posix.DT.DIR => .directory, - posix.DT.FIFO => .named_pipe, - posix.DT.LNK => .sym_link, - posix.DT.REG => .file, - posix.DT.SOCK => .unix_domain_socket, - posix.DT.WHT => .whiteout, - else => .unknown, - }; - return Entry{ - .name = name, - .kind = entry_kind, - }; - } - } - - pub fn reset(self: *Self) void { - self.index = 0; - self.end_index = 0; - self.first_iter = true; - } - }, - .haiku => struct { - dir: Dir, - buf: [@sizeOf(DirEnt) + posix.PATH_MAX]u8 align(@alignOf(DirEnt)), - offset: usize, - index: usize, - end_index: usize, - first_iter: bool, - - const Self = @This(); - const DirEnt = posix.system.DirEnt; - - pub const Error = IteratorError; - - /// Memory such as file names referenced in this returned entry becomes invalid - /// with subsequent calls to `next`, as well as when this `Dir` is deinitialized. - pub fn next(self: *Self) Error!?Entry { - while (true) { - if (self.index >= self.end_index) { - if (self.first_iter) { - switch (@as(posix.E, @enumFromInt(posix.system._kern_rewind_dir(self.dir.fd)))) { - .SUCCESS => {}, - .BADF => unreachable, // Dir is invalid - .FAULT => unreachable, - .NOTDIR => unreachable, - .INVAL => unreachable, - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - else => |err| return posix.unexpectedErrno(err), - } - self.first_iter = false; - } - const rc = posix.system._kern_read_dir( - self.dir.fd, - &self.buf, - self.buf.len, - self.buf.len / @sizeOf(DirEnt), - ); - if (rc == 0) return null; - if (rc < 0) { - switch (@as(posix.E, @enumFromInt(rc))) { - .BADF => unreachable, // Dir is invalid - .FAULT => unreachable, - .NOTDIR => unreachable, - .INVAL => unreachable, - .OVERFLOW => unreachable, - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - else => |err| return posix.unexpectedErrno(err), - } - } - self.offset = 0; - self.index = 0; - self.end_index = @intCast(rc); - } - const dirent: *DirEnt = @ptrCast(@alignCast(&self.buf[self.offset])); - self.offset += dirent.reclen; - self.index += 1; - const name = mem.span(dirent.getName()); - if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..") or dirent.ino == 0) continue; - - var stat_info: posix.Stat = undefined; - switch (@as(posix.E, @enumFromInt(posix.system._kern_read_stat( - self.dir.fd, - name, - false, - &stat_info, - @sizeOf(posix.Stat), - )))) { - .SUCCESS => {}, - .INVAL => unreachable, - .BADF => unreachable, // Dir is invalid - .NOMEM => return error.SystemResources, - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - .FAULT => unreachable, - .NAMETOOLONG => unreachable, - .LOOP => unreachable, - .NOENT => continue, - else => |err| return posix.unexpectedErrno(err), - } - const statmode = stat_info.mode & posix.S.IFMT; - - const entry_kind: Entry.Kind = switch (statmode) { - posix.S.IFDIR => .directory, - posix.S.IFBLK => .block_device, - posix.S.IFCHR => .character_device, - posix.S.IFLNK => .sym_link, - posix.S.IFREG => .file, - posix.S.IFIFO => .named_pipe, - else => .unknown, - }; - - return Entry{ - .name = name, - .kind = entry_kind, - }; - } - } - - pub fn reset(self: *Self) void { - self.index = 0; - self.end_index = 0; - self.first_iter = true; - } - }, - .linux => struct { - dir: Dir, - buf: [1024]u8 align(@alignOf(linux.dirent64)), - index: usize, - end_index: usize, - first_iter: bool, - - const Self = @This(); - - pub const Error = IteratorError; - - /// Memory such as file names referenced in this returned entry becomes invalid - /// with subsequent calls to `next`, as well as when this `Dir` is deinitialized. - pub fn next(self: *Self) Error!?Entry { - return self.nextLinux() catch |err| switch (err) { - // To be consistent across platforms, iteration ends if the directory being iterated is deleted during iteration. - // This matches the behavior of non-Linux UNIX platforms. - error.DirNotFound => null, - else => |e| return e, - }; - } - - pub const ErrorLinux = error{DirNotFound} || IteratorError; - - /// Implementation of `next` that can return `error.DirNotFound` if the directory being - /// iterated was deleted during iteration (this error is Linux specific). - pub fn nextLinux(self: *Self) ErrorLinux!?Entry { - start_over: while (true) { - if (self.index >= self.end_index) { - if (self.first_iter) { - posix.lseek_SET(self.dir.fd, 0) catch unreachable; // EBADF here likely means that the Dir was not opened with iteration permissions - self.first_iter = false; - } - const rc = linux.getdents64(self.dir.fd, &self.buf, self.buf.len); - switch (linux.errno(rc)) { - .SUCCESS => {}, - .BADF => unreachable, // Dir is invalid or was opened without iteration ability - .FAULT => unreachable, - .NOTDIR => unreachable, - .NOENT => return error.DirNotFound, // The directory being iterated was deleted during iteration. - .INVAL => return error.Unexpected, // Linux may in some cases return EINVAL when reading /proc/$PID/net. - .ACCES => return error.AccessDenied, // Do not have permission to iterate this directory. - else => |err| return posix.unexpectedErrno(err), - } - if (rc == 0) return null; - self.index = 0; - self.end_index = rc; - } - const linux_entry = @as(*align(1) linux.dirent64, @ptrCast(&self.buf[self.index])); - const next_index = self.index + linux_entry.reclen; - self.index = next_index; - - const name = mem.sliceTo(@as([*:0]u8, @ptrCast(&linux_entry.name)), 0); - - // skip . and .. entries - if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..")) { - continue :start_over; - } - - const entry_kind: Entry.Kind = switch (linux_entry.type) { - linux.DT.BLK => .block_device, - linux.DT.CHR => .character_device, - linux.DT.DIR => .directory, - linux.DT.FIFO => .named_pipe, - linux.DT.LNK => .sym_link, - linux.DT.REG => .file, - linux.DT.SOCK => .unix_domain_socket, - else => .unknown, - }; - return Entry{ - .name = name, - .kind = entry_kind, - }; - } - } - - pub fn reset(self: *Self) void { - self.index = 0; - self.end_index = 0; - self.first_iter = true; - } - }, - .windows => struct { - dir: Dir, - buf: [1024]u8 align(@alignOf(windows.FILE_BOTH_DIR_INFORMATION)), - index: usize, - end_index: usize, - first_iter: bool, - name_data: [fs.max_name_bytes]u8, - - const Self = @This(); - - pub const Error = IteratorError; - - /// Memory such as file names referenced in this returned entry becomes invalid - /// with subsequent calls to `next`, as well as when this `Dir` is deinitialized. - pub fn next(self: *Self) Error!?Entry { - const w = windows; - while (true) { - if (self.index >= self.end_index) { - var io: w.IO_STATUS_BLOCK = undefined; - const rc = w.ntdll.NtQueryDirectoryFile( - self.dir.fd, - null, - null, - null, - &io, - &self.buf, - self.buf.len, - .FileBothDirectoryInformation, - w.FALSE, - null, - if (self.first_iter) @as(w.BOOLEAN, w.TRUE) else @as(w.BOOLEAN, w.FALSE), - ); - self.first_iter = false; - if (io.Information == 0) return null; - self.index = 0; - self.end_index = io.Information; - switch (rc) { - .SUCCESS => {}, - .ACCESS_DENIED => return error.AccessDenied, // Double-check that the Dir was opened with iteration ability - - else => return w.unexpectedStatus(rc), - } - } - - // While the official api docs guarantee FILE_BOTH_DIR_INFORMATION to be aligned properly - // this may not always be the case (e.g. due to faulty VM/Sandboxing tools) - const dir_info: *align(2) w.FILE_BOTH_DIR_INFORMATION = @ptrCast(@alignCast(&self.buf[self.index])); - if (dir_info.NextEntryOffset != 0) { - self.index += dir_info.NextEntryOffset; - } else { - self.index = self.buf.len; - } - - const name_wtf16le = @as([*]u16, @ptrCast(&dir_info.FileName))[0 .. dir_info.FileNameLength / 2]; - - if (mem.eql(u16, name_wtf16le, &[_]u16{'.'}) or mem.eql(u16, name_wtf16le, &[_]u16{ '.', '.' })) - continue; - const name_wtf8_len = std.unicode.wtf16LeToWtf8(self.name_data[0..], name_wtf16le); - const name_wtf8 = self.name_data[0..name_wtf8_len]; - const kind: Entry.Kind = blk: { - const attrs = dir_info.FileAttributes; - if (attrs & w.FILE_ATTRIBUTE_DIRECTORY != 0) break :blk .directory; - if (attrs & w.FILE_ATTRIBUTE_REPARSE_POINT != 0) break :blk .sym_link; - break :blk .file; - }; - return Entry{ - .name = name_wtf8, - .kind = kind, - }; - } - } - - pub fn reset(self: *Self) void { - self.index = 0; - self.end_index = 0; - self.first_iter = true; - } - }, - .wasi => struct { - dir: Dir, - buf: [1024]u8 align(@alignOf(std.os.wasi.dirent_t)), - cookie: u64, - index: usize, - end_index: usize, - - const Self = @This(); - - pub const Error = IteratorError; - - /// Memory such as file names referenced in this returned entry becomes invalid - /// with subsequent calls to `next`, as well as when this `Dir` is deinitialized. - pub fn next(self: *Self) Error!?Entry { - return self.nextWasi() catch |err| switch (err) { - // To be consistent across platforms, iteration ends if the directory being iterated is deleted during iteration. - // This matches the behavior of non-Linux UNIX platforms. - error.DirNotFound => null, - else => |e| return e, - }; - } - - pub const ErrorWasi = error{DirNotFound} || IteratorError; - - /// Implementation of `next` that can return platform-dependent errors depending on the host platform. - /// When the host platform is Linux, `error.DirNotFound` can be returned if the directory being - /// iterated was deleted during iteration. - pub fn nextWasi(self: *Self) ErrorWasi!?Entry { - // We intentinally use fd_readdir even when linked with libc, - // since its implementation is exactly the same as below, - // and we avoid the code complexity here. - const w = std.os.wasi; - start_over: while (true) { - // According to the WASI spec, the last entry might be truncated, - // so we need to check if the left buffer contains the whole dirent. - if (self.end_index - self.index < @sizeOf(w.dirent_t)) { - var bufused: usize = undefined; - switch (w.fd_readdir(self.dir.fd, &self.buf, self.buf.len, self.cookie, &bufused)) { - .SUCCESS => {}, - .BADF => unreachable, // Dir is invalid or was opened without iteration ability - .FAULT => unreachable, - .NOTDIR => unreachable, - .INVAL => unreachable, - .NOENT => return error.DirNotFound, // The directory being iterated was deleted during iteration. - .NOTCAPABLE => return error.AccessDenied, - else => |err| return posix.unexpectedErrno(err), - } - if (bufused == 0) return null; - self.index = 0; - self.end_index = bufused; - } - const entry = @as(*align(1) w.dirent_t, @ptrCast(&self.buf[self.index])); - const entry_size = @sizeOf(w.dirent_t); - const name_index = self.index + entry_size; - if (name_index + entry.namlen > self.end_index) { - // This case, the name is truncated, so we need to call readdir to store the entire name. - self.end_index = self.index; // Force fd_readdir in the next loop. - continue :start_over; - } - const name = self.buf[name_index .. name_index + entry.namlen]; - - const next_index = name_index + entry.namlen; - self.index = next_index; - self.cookie = entry.next; - - // skip . and .. entries - if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..")) { - continue :start_over; - } - - const entry_kind: Entry.Kind = switch (entry.type) { - .BLOCK_DEVICE => .block_device, - .CHARACTER_DEVICE => .character_device, - .DIRECTORY => .directory, - .SYMBOLIC_LINK => .sym_link, - .REGULAR_FILE => .file, - .SOCKET_STREAM, .SOCKET_DGRAM => .unix_domain_socket, - else => .unknown, - }; - return Entry{ - .name = name, - .kind = entry_kind, - }; - } - } - - pub fn reset(self: *Self) void { - self.index = 0; - self.end_index = 0; - self.cookie = std.os.wasi.DIRCOOKIE_START; - } - }, - else => @compileError("unimplemented"), -}; - -pub fn iterate(self: Dir) Iterator { - return self.iterateImpl(true); -} - -/// Like `iterate`, but will not reset the directory cursor before the first -/// iteration. This should only be used in cases where it is known that the -/// `Dir` has not had its cursor modified yet (e.g. it was just opened). -pub fn iterateAssumeFirstIteration(self: Dir) Iterator { - return self.iterateImpl(false); -} - -fn iterateImpl(self: Dir, first_iter_start_value: bool) Iterator { - switch (native_os) { - .driverkit, - .ios, - .maccatalyst, - .macos, - .tvos, - .visionos, - .watchos, - .freebsd, - .netbsd, - .dragonfly, - .openbsd, - .illumos, - => return Iterator{ - .dir = self, - .seek = 0, - .index = 0, - .end_index = 0, - .buf = undefined, - .first_iter = first_iter_start_value, - }, - .linux => return Iterator{ - .dir = self, - .index = 0, - .end_index = 0, - .buf = undefined, - .first_iter = first_iter_start_value, - }, - .haiku => return Iterator{ - .dir = self, - .offset = 0, - .index = 0, - .end_index = 0, - .buf = undefined, - .first_iter = first_iter_start_value, - }, - .windows => return Iterator{ - .dir = self, - .index = 0, - .end_index = 0, - .first_iter = first_iter_start_value, - .buf = undefined, - .name_data = undefined, - }, - .wasi => return Iterator{ - .dir = self, - .cookie = std.os.wasi.DIRCOOKIE_START, - .index = 0, - .end_index = 0, - .buf = undefined, - }, - else => @compileError("unimplemented"), - } -} - -pub const SelectiveWalker = struct { - stack: std.ArrayList(Walker.StackItem), - name_buffer: std.ArrayList(u8), - allocator: Allocator, - - pub const Error = IteratorError || Allocator.Error; - - /// After each call to this function, and on deinit(), the memory returned - /// from this function becomes invalid. A copy must be made in order to keep - /// a reference to the path. - pub fn next(self: *SelectiveWalker) Error!?Walker.Entry { - while (self.stack.items.len > 0) { - const top = &self.stack.items[self.stack.items.len - 1]; - var dirname_len = top.dirname_len; - if (top.iter.next() catch |err| { - // If we get an error, then we want the user to be able to continue - // walking if they want, which means that we need to pop the directory - // that errored from the stack. Otherwise, all future `next` calls would - // likely just fail with the same error. - var item = self.stack.pop().?; - if (self.stack.items.len != 0) { - item.iter.dir.close(); - } - return err; - }) |entry| { - self.name_buffer.shrinkRetainingCapacity(dirname_len); - if (self.name_buffer.items.len != 0) { - try self.name_buffer.append(self.allocator, fs.path.sep); - dirname_len += 1; - } - try self.name_buffer.ensureUnusedCapacity(self.allocator, entry.name.len + 1); - self.name_buffer.appendSliceAssumeCapacity(entry.name); - self.name_buffer.appendAssumeCapacity(0); - const walker_entry: Walker.Entry = .{ - .dir = top.iter.dir, - .basename = self.name_buffer.items[dirname_len .. self.name_buffer.items.len - 1 :0], - .path = self.name_buffer.items[0 .. self.name_buffer.items.len - 1 :0], - .kind = entry.kind, - }; - return walker_entry; - } else { - var item = self.stack.pop().?; - if (self.stack.items.len != 0) { - item.iter.dir.close(); - } - } - } - return null; - } - - /// Traverses into the directory, continuing walking one level down. - pub fn enter(self: *SelectiveWalker, entry: Walker.Entry) !void { - if (entry.kind != .directory) { - @branchHint(.cold); - return; - } - - var new_dir = entry.dir.openDir(entry.basename, .{ .iterate = true }) catch |err| { - switch (err) { - error.NameTooLong => unreachable, - else => |e| return e, - } - }; - errdefer new_dir.close(); - - try self.stack.append(self.allocator, .{ - .iter = new_dir.iterateAssumeFirstIteration(), - .dirname_len = self.name_buffer.items.len - 1, - }); - } - - pub fn deinit(self: *SelectiveWalker) void { - self.name_buffer.deinit(self.allocator); - self.stack.deinit(self.allocator); - } - - /// Leaves the current directory, continuing walking one level up. - /// If the current entry is a directory entry, then the "current directory" - /// will pertain to that entry if `enter` is called before `leave`. - pub fn leave(self: *SelectiveWalker) void { - var item = self.stack.pop().?; - if (self.stack.items.len != 0) { - @branchHint(.likely); - item.iter.dir.close(); - } - } -}; - -/// Recursively iterates over a directory, but requires the user to -/// opt-in to recursing into each directory entry. -/// -/// `self` must have been opened with `OpenOptions{.iterate = true}`. -/// -/// `Walker.deinit` releases allocated memory and directory handles. -/// -/// The order of returned file system entries is undefined. -/// -/// `self` will not be closed after walking it. -/// -/// See also `walk`. -pub fn walkSelectively(self: Dir, allocator: Allocator) !SelectiveWalker { - var stack: std.ArrayList(Walker.StackItem) = .empty; - - try stack.append(allocator, .{ - .iter = self.iterate(), - .dirname_len = 0, - }); - - return .{ - .stack = stack, - .name_buffer = .{}, - .allocator = allocator, - }; -} - -pub const Walker = struct { - inner: SelectiveWalker, - - pub const Entry = struct { - /// The containing directory. This can be used to operate directly on `basename` - /// rather than `path`, avoiding `error.NameTooLong` for deeply nested paths. - /// The directory remains open until `next` or `deinit` is called. - dir: Dir, - basename: [:0]const u8, - path: [:0]const u8, - kind: Dir.Entry.Kind, - - /// Returns the depth of the entry relative to the initial directory. - /// Returns 1 for a direct child of the initial directory, 2 for an entry - /// within a direct child of the initial directory, etc. - pub fn depth(self: Walker.Entry) usize { - return mem.countScalar(u8, self.path, fs.path.sep) + 1; - } - }; - - const StackItem = struct { - iter: Dir.Iterator, - dirname_len: usize, - }; - - /// After each call to this function, and on deinit(), the memory returned - /// from this function becomes invalid. A copy must be made in order to keep - /// a reference to the path. - pub fn next(self: *Walker) !?Walker.Entry { - const entry = try self.inner.next(); - if (entry != null and entry.?.kind == .directory) { - try self.inner.enter(entry.?); - } - return entry; - } - - pub fn deinit(self: *Walker) void { - self.inner.deinit(); - } - - /// Leaves the current directory, continuing walking one level up. - /// If the current entry is a directory entry, then the "current directory" - /// is the directory pertaining to the current entry. - pub fn leave(self: *Walker) void { - self.inner.leave(); - } -}; - -/// Recursively iterates over a directory. -/// -/// `self` must have been opened with `OpenOptions{.iterate = true}`. -/// -/// `Walker.deinit` releases allocated memory and directory handles. -/// -/// The order of returned file system entries is undefined. -/// -/// `self` will not be closed after walking it. -/// -/// See also `walkSelectively`. -pub fn walk(self: Dir, allocator: Allocator) Allocator.Error!Walker { - return .{ - .inner = try walkSelectively(self, allocator), - }; -} - -pub const OpenError = Io.Dir.OpenError; - -pub fn close(self: *Dir) void { - posix.close(self.fd); - self.* = undefined; -} - -/// Deprecated in favor of `Io.Dir.openFile`. -pub fn openFile(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File { - var threaded: Io.Threaded = .init_single_threaded; - const io = threaded.ioBasic(); - return .adaptFromNewApi(try Io.Dir.openFile(self.adaptToNewApi(), io, sub_path, flags)); -} - -/// Deprecated in favor of `Io.Dir.createFile`. -pub fn createFile(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File { - var threaded: Io.Threaded = .init_single_threaded; - const io = threaded.ioBasic(); - const new_file = try Io.Dir.createFile(self.adaptToNewApi(), io, sub_path, flags); - return .adaptFromNewApi(new_file); -} - -/// Deprecated in favor of `Io.Dir.MakeError`. -pub const MakeError = Io.Dir.MakeError; - -/// Deprecated in favor of `Io.Dir.makeDir`. -pub fn makeDir(self: Dir, sub_path: []const u8) MakeError!void { - var threaded: Io.Threaded = .init_single_threaded; - const io = threaded.ioBasic(); - return Io.Dir.makeDir(.{ .handle = self.fd }, io, sub_path); -} - -/// Deprecated in favor of `Io.Dir.makeDir`. -pub fn makeDirZ(self: Dir, sub_path: [*:0]const u8) MakeError!void { - try posix.mkdiratZ(self.fd, sub_path, default_mode); -} - -/// Deprecated in favor of `Io.Dir.makeDir`. -pub fn makeDirW(self: Dir, sub_path: [*:0]const u16) MakeError!void { - try posix.mkdiratW(self.fd, mem.span(sub_path), default_mode); -} - -/// Deprecated in favor of `Io.Dir.makePath`. -pub fn makePath(self: Dir, sub_path: []const u8) MakePathError!void { - _ = try self.makePathStatus(sub_path); -} - -/// Deprecated in favor of `Io.Dir.MakePathStatus`. -pub const MakePathStatus = Io.Dir.MakePathStatus; -/// Deprecated in favor of `Io.Dir.MakePathError`. -pub const MakePathError = Io.Dir.MakePathError; - -/// Deprecated in favor of `Io.Dir.makePathStatus`. -pub fn makePathStatus(self: Dir, sub_path: []const u8) MakePathError!MakePathStatus { - var threaded: Io.Threaded = .init_single_threaded; - const io = threaded.ioBasic(); - return Io.Dir.makePathStatus(.{ .handle = self.fd }, io, sub_path); -} - -/// Deprecated in favor of `Io.Dir.makeOpenPath`. -pub fn makeOpenPath(dir: Dir, sub_path: []const u8, options: OpenOptions) Io.Dir.MakeOpenPathError!Dir { - var threaded: Io.Threaded = .init_single_threaded; - const io = threaded.ioBasic(); - return .adaptFromNewApi(try Io.Dir.makeOpenPath(dir.adaptToNewApi(), io, sub_path, options)); -} - -pub const RealPathError = posix.RealPathError || error{Canceled}; - -/// This function returns the canonicalized absolute pathname of -/// `pathname` relative to this `Dir`. If `pathname` is absolute, ignores this -/// `Dir` handle and returns the canonicalized absolute pathname of `pathname` -/// argument. -/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. -/// On Windows, the result is encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On other platforms, the result is an opaque sequence of bytes with no particular encoding. -/// This function is not universally supported by all platforms. -/// Currently supported hosts are: Linux, macOS, and Windows. -/// See also `Dir.realpathZ`, `Dir.realpathW`, and `Dir.realpathAlloc`. -pub fn realpath(self: Dir, pathname: []const u8, out_buffer: []u8) RealPathError![]u8 { - if (native_os == .wasi) { - @compileError("realpath is not available on WASI"); - } - if (native_os == .windows) { - var pathname_w = try windows.sliceToPrefixedFileW(self.fd, pathname); - - const wide_slice = try self.realpathW2(pathname_w.span(), &pathname_w.data); - - const len = std.unicode.calcWtf8Len(wide_slice); - if (len > out_buffer.len) - return error.NameTooLong; - - const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice); - return out_buffer[0..end_index]; - } - const pathname_c = try posix.toPosixPath(pathname); - return self.realpathZ(&pathname_c, out_buffer); -} - -/// Same as `Dir.realpath` except `pathname` is null-terminated. -/// See also `Dir.realpath`, `realpathZ`. -pub fn realpathZ(self: Dir, pathname: [*:0]const u8, out_buffer: []u8) RealPathError![]u8 { - if (native_os == .windows) { - var pathname_w = try windows.cStrToPrefixedFileW(self.fd, pathname); - - const wide_slice = try self.realpathW2(pathname_w.span(), &pathname_w.data); - - const len = std.unicode.calcWtf8Len(wide_slice); - if (len > out_buffer.len) - return error.NameTooLong; - - const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice); - return out_buffer[0..end_index]; - } - - var flags: posix.O = .{}; - if (@hasField(posix.O, "NONBLOCK")) flags.NONBLOCK = true; - if (@hasField(posix.O, "CLOEXEC")) flags.CLOEXEC = true; - if (@hasField(posix.O, "PATH")) flags.PATH = true; - - const fd = posix.openatZ(self.fd, pathname, flags, 0) catch |err| switch (err) { - error.FileLocksNotSupported => return error.Unexpected, - error.FileBusy => return error.Unexpected, - error.WouldBlock => return error.Unexpected, - else => |e| return e, - }; - defer posix.close(fd); - - var buffer: [fs.max_path_bytes]u8 = undefined; - const out_path = try std.os.getFdPath(fd, &buffer); - - if (out_path.len > out_buffer.len) { - return error.NameTooLong; - } - - const result = out_buffer[0..out_path.len]; - @memcpy(result, out_path); - return result; -} - -/// Deprecated: use `realpathW2`. -/// -/// Windows-only. Same as `Dir.realpath` except `pathname` is WTF16 LE encoded. -/// The result is encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// See also `Dir.realpath`, `realpathW`. -pub fn realpathW(self: Dir, pathname: []const u16, out_buffer: []u8) RealPathError![]u8 { - var wide_buf: [std.os.windows.PATH_MAX_WIDE]u16 = undefined; - const wide_slice = try self.realpathW2(pathname, &wide_buf); - - const len = std.unicode.calcWtf8Len(wide_slice); - if (len > out_buffer.len) return error.NameTooLong; - - const end_index = std.unicode.wtf16LeToWtf8(&out_buffer, wide_slice); - return out_buffer[0..end_index]; -} - -/// Windows-only. Same as `Dir.realpath` except -/// * `pathname` and the result are WTF-16 LE encoded -/// * `pathname` is relative or has the NT namespace prefix. See `windows.wToPrefixedFileW` for details. -/// -/// Additionally, `pathname` will never be accessed after `out_buffer` has been written to, so it -/// is safe to reuse a single buffer for both. -/// -/// See also `Dir.realpath`, `realpathW`. -pub fn realpathW2(self: Dir, pathname: []const u16, out_buffer: []u16) RealPathError![]u16 { - const w = windows; - - const access_mask = w.GENERIC_READ | w.SYNCHRONIZE; - const share_access = w.FILE_SHARE_READ | w.FILE_SHARE_WRITE | w.FILE_SHARE_DELETE; - const creation = w.FILE_OPEN; - const h_file = blk: { - const res = w.OpenFile(pathname, .{ - .dir = self.fd, - .access_mask = access_mask, - .share_access = share_access, - .creation = creation, - .filter = .any, - }) catch |err| switch (err) { - error.WouldBlock => unreachable, - else => |e| return e, - }; - break :blk res; - }; - defer w.CloseHandle(h_file); - - return w.GetFinalPathNameByHandle(h_file, .{}, out_buffer); -} - -pub const RealPathAllocError = RealPathError || Allocator.Error; - -/// Same as `Dir.realpath` except caller must free the returned memory. -/// See also `Dir.realpath`. -pub fn realpathAlloc(self: Dir, allocator: Allocator, pathname: []const u8) RealPathAllocError![]u8 { - // Use of max_path_bytes here is valid as the realpath function does not - // have a variant that takes an arbitrary-size buffer. - // TODO(#4812): Consider reimplementing realpath or using the POSIX.1-2008 - // NULL out parameter (GNU's canonicalize_file_name) to handle overelong - // paths. musl supports passing NULL but restricts the output to PATH_MAX - // anyway. - var buf: [fs.max_path_bytes]u8 = undefined; - return allocator.dupe(u8, try self.realpath(pathname, buf[0..])); -} - -/// Changes the current working directory to the open directory handle. -/// This modifies global state and can have surprising effects in multi- -/// threaded applications. Most applications and especially libraries should -/// not call this function as a general rule, however it can have use cases -/// in, for example, implementing a shell, or child process execution. -/// Not all targets support this. For example, WASI does not have the concept -/// of a current working directory. -pub fn setAsCwd(self: Dir) !void { - if (native_os == .wasi) { - @compileError("changing cwd is not currently possible in WASI"); - } - if (native_os == .windows) { - var dir_path_buffer: [windows.PATH_MAX_WIDE]u16 = undefined; - const dir_path = try windows.GetFinalPathNameByHandle(self.fd, .{}, &dir_path_buffer); - if (builtin.link_libc) { - return posix.chdirW(dir_path); - } - return windows.SetCurrentDirectory(dir_path); - } - try posix.fchdir(self.fd); -} - -/// Deprecated in favor of `Io.Dir.OpenOptions`. -pub const OpenOptions = Io.Dir.OpenOptions; - -/// Deprecated in favor of `Io.Dir.openDir`. -pub fn openDir(self: Dir, sub_path: []const u8, args: OpenOptions) OpenError!Dir { - var threaded: Io.Threaded = .init_single_threaded; - const io = threaded.ioBasic(); - return .adaptFromNewApi(try Io.Dir.openDir(.{ .handle = self.fd }, io, sub_path, args)); -} - -pub const DeleteFileError = posix.UnlinkError; - -/// Delete a file name and possibly the file it refers to, based on an open directory handle. -/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `sub_path` should be encoded as valid UTF-8. -/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. -/// Asserts that the path parameter has no null bytes. -pub fn deleteFile(self: Dir, sub_path: []const u8) DeleteFileError!void { - if (native_os == .windows) { - const sub_path_w = try windows.sliceToPrefixedFileW(self.fd, sub_path); - return self.deleteFileW(sub_path_w.span()); - } else if (native_os == .wasi and !builtin.link_libc) { - posix.unlinkat(self.fd, sub_path, 0) catch |err| switch (err) { - error.DirNotEmpty => unreachable, // not passing AT.REMOVEDIR - else => |e| return e, - }; - } else { - const sub_path_c = try posix.toPosixPath(sub_path); - return self.deleteFileZ(&sub_path_c); - } -} - -/// Same as `deleteFile` except the parameter is null-terminated. -pub fn deleteFileZ(self: Dir, sub_path_c: [*:0]const u8) DeleteFileError!void { - posix.unlinkatZ(self.fd, sub_path_c, 0) catch |err| switch (err) { - error.DirNotEmpty => unreachable, // not passing AT.REMOVEDIR - error.AccessDenied, error.PermissionDenied => |e| switch (native_os) { - // non-Linux POSIX systems return permission errors when trying to delete a - // directory, so we need to handle that case specifically and translate the error - .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos, .freebsd, .netbsd, .dragonfly, .openbsd, .illumos => { - // Don't follow symlinks to match unlinkat (which acts on symlinks rather than follows them) - const fstat = posix.fstatatZ(self.fd, sub_path_c, posix.AT.SYMLINK_NOFOLLOW) catch return e; - const is_dir = fstat.mode & posix.S.IFMT == posix.S.IFDIR; - return if (is_dir) error.IsDir else e; - }, - else => return e, - }, - else => |e| return e, - }; -} - -/// Same as `deleteFile` except the parameter is WTF-16 LE encoded. -pub fn deleteFileW(self: Dir, sub_path_w: []const u16) DeleteFileError!void { - posix.unlinkatW(self.fd, sub_path_w, 0) catch |err| switch (err) { - error.DirNotEmpty => unreachable, // not passing AT.REMOVEDIR - else => |e| return e, - }; -} - -pub const DeleteDirError = error{ - DirNotEmpty, - FileNotFound, - AccessDenied, - PermissionDenied, - FileBusy, - FileSystem, - SymLinkLoop, - NameTooLong, - NotDir, - SystemResources, - ReadOnlyFileSystem, - /// WASI: file paths must be valid UTF-8. - /// Windows: file paths provided by the user must be valid WTF-8. - /// https://wtf-8.codeberg.page/ - BadPathName, - /// On Windows, `\\server` or `\\server\share` was not found. - NetworkNotFound, - ProcessNotFound, - Unexpected, -}; - -/// Returns `error.DirNotEmpty` if the directory is not empty. -/// To delete a directory recursively, see `deleteTree`. -/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `sub_path` should be encoded as valid UTF-8. -/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. -/// Asserts that the path parameter has no null bytes. -pub fn deleteDir(self: Dir, sub_path: []const u8) DeleteDirError!void { - if (native_os == .windows) { - const sub_path_w = try windows.sliceToPrefixedFileW(self.fd, sub_path); - return self.deleteDirW(sub_path_w.span()); - } else if (native_os == .wasi and !builtin.link_libc) { - posix.unlinkat(self.fd, sub_path, posix.AT.REMOVEDIR) catch |err| switch (err) { - error.IsDir => unreachable, // not possible since we pass AT.REMOVEDIR - else => |e| return e, - }; - } else { - const sub_path_c = try posix.toPosixPath(sub_path); - return self.deleteDirZ(&sub_path_c); - } -} - -/// Same as `deleteDir` except the parameter is null-terminated. -pub fn deleteDirZ(self: Dir, sub_path_c: [*:0]const u8) DeleteDirError!void { - posix.unlinkatZ(self.fd, sub_path_c, posix.AT.REMOVEDIR) catch |err| switch (err) { - error.IsDir => unreachable, // not possible since we pass AT.REMOVEDIR - else => |e| return e, - }; -} - -/// Same as `deleteDir` except the parameter is WTF16LE, NT prefixed. -/// This function is Windows-only. -pub fn deleteDirW(self: Dir, sub_path_w: []const u16) DeleteDirError!void { - posix.unlinkatW(self.fd, sub_path_w, posix.AT.REMOVEDIR) catch |err| switch (err) { - error.IsDir => unreachable, // not possible since we pass AT.REMOVEDIR - else => |e| return e, - }; -} - -pub const RenameError = posix.RenameError; - -/// Change the name or location of a file or directory. -/// If new_sub_path already exists, it will be replaced. -/// Renaming a file over an existing directory or a directory -/// over an existing file will fail with `error.IsDir` or `error.NotDir` -/// On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, both paths should be encoded as valid UTF-8. -/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding. -pub fn rename(self: Dir, old_sub_path: []const u8, new_sub_path: []const u8) RenameError!void { - return posix.renameat(self.fd, old_sub_path, self.fd, new_sub_path); -} - -/// Same as `rename` except the parameters are null-terminated. -pub fn renameZ(self: Dir, old_sub_path_z: [*:0]const u8, new_sub_path_z: [*:0]const u8) RenameError!void { - return posix.renameatZ(self.fd, old_sub_path_z, self.fd, new_sub_path_z); -} - -/// Same as `rename` except the parameters are WTF16LE, NT prefixed. -/// This function is Windows-only. -pub fn renameW(self: Dir, old_sub_path_w: []const u16, new_sub_path_w: []const u16) RenameError!void { - return posix.renameatW(self.fd, old_sub_path_w, self.fd, new_sub_path_w, windows.TRUE); -} - -/// Use with `Dir.symLink`, `Dir.atomicSymLink`, and `symLinkAbsolute` to -/// specify whether the symlink will point to a file or a directory. This value -/// is ignored on all hosts except Windows where creating symlinks to different -/// resource types, requires different flags. By default, `symLinkAbsolute` is -/// assumed to point to a file. -pub const SymLinkFlags = struct { - is_directory: bool = false, -}; - -/// Creates a symbolic link named `sym_link_path` which contains the string `target_path`. -/// A symbolic link (also known as a soft link) may point to an existing file or to a nonexistent -/// one; the latter case is known as a dangling link. -/// If `sym_link_path` exists, it will not be overwritten. -/// On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, both paths should be encoded as valid UTF-8. -/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding. -pub fn symLink( - self: Dir, - target_path: []const u8, - sym_link_path: []const u8, - flags: SymLinkFlags, -) !void { - if (native_os == .wasi and !builtin.link_libc) { - return self.symLinkWasi(target_path, sym_link_path, flags); - } - if (native_os == .windows) { - // Target path does not use sliceToPrefixedFileW because certain paths - // are handled differently when creating a symlink than they would be - // when converting to an NT namespaced path. CreateSymbolicLink in - // symLinkW will handle the necessary conversion. - var target_path_w: windows.PathSpace = undefined; - target_path_w.len = try windows.wtf8ToWtf16Le(&target_path_w.data, target_path); - target_path_w.data[target_path_w.len] = 0; - // However, we need to canonicalize any path separators to `\`, since if - // the target path is relative, then it must use `\` as the path separator. - mem.replaceScalar( - u16, - target_path_w.data[0..target_path_w.len], - mem.nativeToLittle(u16, '/'), - mem.nativeToLittle(u16, '\\'), - ); - - const sym_link_path_w = try windows.sliceToPrefixedFileW(self.fd, sym_link_path); - return self.symLinkW(target_path_w.span(), sym_link_path_w.span(), flags); - } - const target_path_c = try posix.toPosixPath(target_path); - const sym_link_path_c = try posix.toPosixPath(sym_link_path); - return self.symLinkZ(&target_path_c, &sym_link_path_c, flags); -} - -/// WASI-only. Same as `symLink` except targeting WASI. -pub fn symLinkWasi( - self: Dir, - target_path: []const u8, - sym_link_path: []const u8, - _: SymLinkFlags, -) !void { - return posix.symlinkat(target_path, self.fd, sym_link_path); -} - -/// Same as `symLink`, except the pathname parameters are null-terminated. -pub fn symLinkZ( - self: Dir, - target_path_c: [*:0]const u8, - sym_link_path_c: [*:0]const u8, - flags: SymLinkFlags, -) !void { - if (native_os == .windows) { - const target_path_w = try windows.cStrToPrefixedFileW(self.fd, target_path_c); - const sym_link_path_w = try windows.cStrToPrefixedFileW(self.fd, sym_link_path_c); - return self.symLinkW(target_path_w.span(), sym_link_path_w.span(), flags); - } - return posix.symlinkatZ(target_path_c, self.fd, sym_link_path_c); -} - -/// Windows-only. Same as `symLink` except the pathname parameters -/// are WTF16 LE encoded. -pub fn symLinkW( - self: Dir, - /// WTF-16, does not need to be NT-prefixed. The NT-prefixing - /// of this path is handled by CreateSymbolicLink. - /// Any path separators must be `\`, not `/`. - target_path_w: [:0]const u16, - /// WTF-16, must be NT-prefixed or relative - sym_link_path_w: []const u16, - flags: SymLinkFlags, -) !void { - return windows.CreateSymbolicLink(self.fd, sym_link_path_w, target_path_w, flags.is_directory); -} - -/// Same as `symLink`, except tries to create the symbolic link until it -/// succeeds or encounters an error other than `error.PathAlreadyExists`. -/// -/// * On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// * On WASI, both paths should be encoded as valid UTF-8. -/// * On other platforms, both paths are an opaque sequence of bytes with no particular encoding. -pub fn atomicSymLink( - dir: Dir, - target_path: []const u8, - sym_link_path: []const u8, - flags: SymLinkFlags, -) !void { - if (dir.symLink(target_path, sym_link_path, flags)) { - return; - } else |err| switch (err) { - error.PathAlreadyExists => {}, - else => |e| return e, - } - - const dirname = path.dirname(sym_link_path) orelse "."; - - const rand_len = @sizeOf(u64) * 2; - const temp_path_len = dirname.len + 1 + rand_len; - var temp_path_buf: [fs.max_path_bytes]u8 = undefined; - - if (temp_path_len > temp_path_buf.len) return error.NameTooLong; - @memcpy(temp_path_buf[0..dirname.len], dirname); - temp_path_buf[dirname.len] = path.sep; - - const temp_path = temp_path_buf[0..temp_path_len]; - - while (true) { - const random_integer = std.crypto.random.int(u64); - temp_path[dirname.len + 1 ..][0..rand_len].* = std.fmt.hex(random_integer); - - if (dir.symLink(target_path, temp_path, flags)) { - return dir.rename(temp_path, sym_link_path); - } else |err| switch (err) { - error.PathAlreadyExists => continue, - else => |e| return e, - } - } -} - -pub const ReadLinkError = posix.ReadLinkError; - -/// Read value of a symbolic link. -/// The return value is a slice of `buffer`, from index `0`. -/// Asserts that the path parameter has no null bytes. -/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `sub_path` should be encoded as valid UTF-8. -/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. -pub fn readLink(self: Dir, sub_path: []const u8, buffer: []u8) ReadLinkError![]u8 { - if (native_os == .wasi and !builtin.link_libc) { - return self.readLinkWasi(sub_path, buffer); - } - if (native_os == .windows) { - var sub_path_w = try windows.sliceToPrefixedFileW(self.fd, sub_path); - const result_w = try self.readLinkW(sub_path_w.span(), &sub_path_w.data); - - const len = std.unicode.calcWtf8Len(result_w); - if (len > buffer.len) return error.NameTooLong; - - const end_index = std.unicode.wtf16LeToWtf8(buffer, result_w); - return buffer[0..end_index]; - } - const sub_path_c = try posix.toPosixPath(sub_path); - return self.readLinkZ(&sub_path_c, buffer); -} - -/// WASI-only. Same as `readLink` except targeting WASI. -pub fn readLinkWasi(self: Dir, sub_path: []const u8, buffer: []u8) ![]u8 { - return posix.readlinkat(self.fd, sub_path, buffer); -} - -/// Same as `readLink`, except the `sub_path_c` parameter is null-terminated. -pub fn readLinkZ(self: Dir, sub_path_c: [*:0]const u8, buffer: []u8) ![]u8 { - if (native_os == .windows) { - var sub_path_w = try windows.cStrToPrefixedFileW(self.fd, sub_path_c); - const result_w = try self.readLinkW(sub_path_w.span(), &sub_path_w.data); - - const len = std.unicode.calcWtf8Len(result_w); - if (len > buffer.len) return error.NameTooLong; - - const end_index = std.unicode.wtf16LeToWtf8(buffer, result_w); - return buffer[0..end_index]; - } - return posix.readlinkatZ(self.fd, sub_path_c, buffer); -} - -/// Windows-only. Same as `readLink` except the path parameter -/// is WTF-16 LE encoded, NT-prefixed. -/// -/// `sub_path_w` will never be accessed after `buffer` has been written to, so it -/// is safe to reuse a single buffer for both. -pub fn readLinkW(self: Dir, sub_path_w: []const u16, buffer: []u16) ![]u16 { - return windows.ReadLink(self.fd, sub_path_w, buffer); -} - -/// Deprecated in favor of `Io.Dir.readFile`. -pub fn readFile(self: Dir, file_path: []const u8, buffer: []u8) ![]u8 { - var threaded: Io.Threaded = .init_single_threaded; - const io = threaded.ioBasic(); - return Io.Dir.readFile(.{ .handle = self.fd }, io, file_path, buffer); -} - -pub const ReadFileAllocError = File.OpenError || File.ReadError || Allocator.Error || error{ - /// File size reached or exceeded the provided limit. - StreamTooLong, -}; - -/// Reads all the bytes from the named file. On success, caller owns returned -/// buffer. -/// -/// If the file size is already known, a better alternative is to initialize a -/// `File.Reader`. -/// -/// If the file size cannot be obtained, an error is returned. If -/// this is a realistic possibility, a better alternative is to initialize a -/// `File.Reader` which handles this seamlessly. -pub fn readFileAlloc( - dir: Dir, - /// On Windows, should be encoded as [WTF-8](https://wtf-8.codeberg.page/). - /// On WASI, should be encoded as valid UTF-8. - /// On other platforms, an opaque sequence of bytes with no particular encoding. - sub_path: []const u8, - /// Used to allocate the result. - gpa: Allocator, - /// If reached or exceeded, `error.StreamTooLong` is returned instead. - limit: Io.Limit, -) ReadFileAllocError![]u8 { - return readFileAllocOptions(dir, sub_path, gpa, limit, .of(u8), null); -} - -/// Reads all the bytes from the named file. On success, caller owns returned -/// buffer. -/// -/// If the file size is already known, a better alternative is to initialize a -/// `File.Reader`. -/// -/// TODO move this function to Io.Dir -pub fn readFileAllocOptions( - dir: Dir, - /// On Windows, should be encoded as [WTF-8](https://wtf-8.codeberg.page/). - /// On WASI, should be encoded as valid UTF-8. - /// On other platforms, an opaque sequence of bytes with no particular encoding. - sub_path: []const u8, - /// Used to allocate the result. - gpa: Allocator, - /// If reached or exceeded, `error.StreamTooLong` is returned instead. - limit: Io.Limit, - comptime alignment: std.mem.Alignment, - comptime sentinel: ?u8, -) ReadFileAllocError!(if (sentinel) |s| [:s]align(alignment.toByteUnits()) u8 else []align(alignment.toByteUnits()) u8) { - var threaded: Io.Threaded = .init_single_threaded; - const io = threaded.ioBasic(); - - var file = try dir.openFile(sub_path, .{}); - defer file.close(); - var file_reader = file.reader(io, &.{}); - return file_reader.interface.allocRemainingAlignedSentinel(gpa, limit, alignment, sentinel) catch |err| switch (err) { - error.ReadFailed => return file_reader.err.?, - error.OutOfMemory, error.StreamTooLong => |e| return e, - }; -} - -pub const DeleteTreeError = error{ - AccessDenied, - PermissionDenied, - FileTooBig, - SymLinkLoop, - ProcessFdQuotaExceeded, - NameTooLong, - SystemFdQuotaExceeded, - NoDevice, - SystemResources, - ReadOnlyFileSystem, - FileSystem, - FileBusy, - DeviceBusy, - ProcessNotFound, - /// One of the path components was not a directory. - /// This error is unreachable if `sub_path` does not contain a path separator. - NotDir, - /// WASI: file paths must be valid UTF-8. - /// Windows: file paths provided by the user must be valid WTF-8. - /// https://wtf-8.codeberg.page/ - /// On Windows, file paths cannot contain these characters: - /// '/', '*', '?', '"', '<', '>', '|' - BadPathName, - /// On Windows, `\\server` or `\\server\share` was not found. - NetworkNotFound, - - Canceled, -} || posix.UnexpectedError; - -/// Whether `sub_path` describes a symlink, file, or directory, this function -/// removes it. If it cannot be removed because it is a non-empty directory, -/// this function recursively removes its entries and then tries again. -/// This operation is not atomic on most file systems. -/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `sub_path` should be encoded as valid UTF-8. -/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. -pub fn deleteTree(self: Dir, sub_path: []const u8) DeleteTreeError!void { - var initial_iterable_dir = (try self.deleteTreeOpenInitialSubpath(sub_path, .file)) orelse return; - - const StackItem = struct { - name: []const u8, - parent_dir: Dir, - iter: Dir.Iterator, - - fn closeAll(items: []@This()) void { - for (items) |*item| item.iter.dir.close(); - } - }; - - var stack_buffer: [16]StackItem = undefined; - var stack = std.ArrayList(StackItem).initBuffer(&stack_buffer); - defer StackItem.closeAll(stack.items); - - stack.appendAssumeCapacity(.{ - .name = sub_path, - .parent_dir = self, - .iter = initial_iterable_dir.iterateAssumeFirstIteration(), - }); - - process_stack: while (stack.items.len != 0) { - var top = &stack.items[stack.items.len - 1]; - while (try top.iter.next()) |entry| { - var treat_as_dir = entry.kind == .directory; - handle_entry: while (true) { - if (treat_as_dir) { - if (stack.unusedCapacitySlice().len >= 1) { - var iterable_dir = top.iter.dir.openDir(entry.name, .{ - .follow_symlinks = false, - .iterate = true, - }) catch |err| switch (err) { - error.NotDir => { - treat_as_dir = false; - continue :handle_entry; - }, - error.FileNotFound => { - // That's fine, we were trying to remove this directory anyway. - break :handle_entry; - }, - - error.AccessDenied, - error.PermissionDenied, - error.SymLinkLoop, - error.ProcessFdQuotaExceeded, - error.NameTooLong, - error.SystemFdQuotaExceeded, - error.NoDevice, - error.SystemResources, - error.Unexpected, - error.BadPathName, - error.NetworkNotFound, - error.DeviceBusy, - error.Canceled, - => |e| return e, - }; - stack.appendAssumeCapacity(.{ - .name = entry.name, - .parent_dir = top.iter.dir, - .iter = iterable_dir.iterateAssumeFirstIteration(), - }); - continue :process_stack; - } else { - try top.iter.dir.deleteTreeMinStackSizeWithKindHint(entry.name, entry.kind); - break :handle_entry; - } - } else { - if (top.iter.dir.deleteFile(entry.name)) { - break :handle_entry; - } else |err| switch (err) { - error.FileNotFound => break :handle_entry, - - // Impossible because we do not pass any path separators. - error.NotDir => unreachable, - - error.IsDir => { - treat_as_dir = true; - continue :handle_entry; - }, - - error.AccessDenied, - error.PermissionDenied, - error.SymLinkLoop, - error.NameTooLong, - error.SystemResources, - error.ReadOnlyFileSystem, - error.FileSystem, - error.FileBusy, - error.BadPathName, - error.NetworkNotFound, - error.Unexpected, - => |e| return e, - } - } - } - } - - // On Windows, we can't delete until the dir's handle has been closed, so - // close it before we try to delete. - top.iter.dir.close(); - - // In order to avoid double-closing the directory when cleaning up - // the stack in the case of an error, we save the relevant portions and - // pop the value from the stack. - const parent_dir = top.parent_dir; - const name = top.name; - stack.items.len -= 1; - - var need_to_retry: bool = false; - parent_dir.deleteDir(name) catch |err| switch (err) { - error.FileNotFound => {}, - error.DirNotEmpty => need_to_retry = true, - else => |e| return e, - }; - - if (need_to_retry) { - // Since we closed the handle that the previous iterator used, we - // need to re-open the dir and re-create the iterator. - var iterable_dir = iterable_dir: { - var treat_as_dir = true; - handle_entry: while (true) { - if (treat_as_dir) { - break :iterable_dir parent_dir.openDir(name, .{ - .follow_symlinks = false, - .iterate = true, - }) catch |err| switch (err) { - error.NotDir => { - treat_as_dir = false; - continue :handle_entry; - }, - error.FileNotFound => { - // That's fine, we were trying to remove this directory anyway. - continue :process_stack; - }, - - error.AccessDenied, - error.PermissionDenied, - error.SymLinkLoop, - error.ProcessFdQuotaExceeded, - error.NameTooLong, - error.SystemFdQuotaExceeded, - error.NoDevice, - error.SystemResources, - error.Unexpected, - error.BadPathName, - error.NetworkNotFound, - error.DeviceBusy, - error.Canceled, - => |e| return e, - }; - } else { - if (parent_dir.deleteFile(name)) { - continue :process_stack; - } else |err| switch (err) { - error.FileNotFound => continue :process_stack, - - // Impossible because we do not pass any path separators. - error.NotDir => unreachable, - - error.IsDir => { - treat_as_dir = true; - continue :handle_entry; - }, - - error.AccessDenied, - error.PermissionDenied, - error.SymLinkLoop, - error.NameTooLong, - error.SystemResources, - error.ReadOnlyFileSystem, - error.FileSystem, - error.FileBusy, - error.BadPathName, - error.NetworkNotFound, - error.Unexpected, - => |e| return e, - } - } - } - }; - // We know there is room on the stack since we are just re-adding - // the StackItem that we previously popped. - stack.appendAssumeCapacity(.{ - .name = name, - .parent_dir = parent_dir, - .iter = iterable_dir.iterateAssumeFirstIteration(), - }); - continue :process_stack; - } - } -} - -/// Like `deleteTree`, but only keeps one `Iterator` active at a time to minimize the function's stack size. -/// This is slower than `deleteTree` but uses less stack space. -/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `sub_path` should be encoded as valid UTF-8. -/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. -pub fn deleteTreeMinStackSize(self: Dir, sub_path: []const u8) DeleteTreeError!void { - return self.deleteTreeMinStackSizeWithKindHint(sub_path, .file); -} - -fn deleteTreeMinStackSizeWithKindHint(self: Dir, sub_path: []const u8, kind_hint: File.Kind) DeleteTreeError!void { - start_over: while (true) { - var dir = (try self.deleteTreeOpenInitialSubpath(sub_path, kind_hint)) orelse return; - var cleanup_dir_parent: ?Dir = null; - defer if (cleanup_dir_parent) |*d| d.close(); - - var cleanup_dir = true; - defer if (cleanup_dir) dir.close(); - - // Valid use of max_path_bytes because dir_name_buf will only - // ever store a single path component that was returned from the - // filesystem. - var dir_name_buf: [fs.max_path_bytes]u8 = undefined; - var dir_name: []const u8 = sub_path; - - // Here we must avoid recursion, in order to provide O(1) memory guarantee of this function. - // Go through each entry and if it is not a directory, delete it. If it is a directory, - // open it, and close the original directory. Repeat. Then start the entire operation over. - - scan_dir: while (true) { - var dir_it = dir.iterateAssumeFirstIteration(); - dir_it: while (try dir_it.next()) |entry| { - var treat_as_dir = entry.kind == .directory; - handle_entry: while (true) { - if (treat_as_dir) { - const new_dir = dir.openDir(entry.name, .{ - .follow_symlinks = false, - .iterate = true, - }) catch |err| switch (err) { - error.NotDir => { - treat_as_dir = false; - continue :handle_entry; - }, - error.FileNotFound => { - // That's fine, we were trying to remove this directory anyway. - continue :dir_it; - }, - - error.AccessDenied, - error.PermissionDenied, - error.SymLinkLoop, - error.ProcessFdQuotaExceeded, - error.NameTooLong, - error.SystemFdQuotaExceeded, - error.NoDevice, - error.SystemResources, - error.Unexpected, - error.BadPathName, - error.NetworkNotFound, - error.DeviceBusy, - error.Canceled, - => |e| return e, - }; - if (cleanup_dir_parent) |*d| d.close(); - cleanup_dir_parent = dir; - dir = new_dir; - const result = dir_name_buf[0..entry.name.len]; - @memcpy(result, entry.name); - dir_name = result; - continue :scan_dir; - } else { - if (dir.deleteFile(entry.name)) { - continue :dir_it; - } else |err| switch (err) { - error.FileNotFound => continue :dir_it, - - // Impossible because we do not pass any path separators. - error.NotDir => unreachable, - - error.IsDir => { - treat_as_dir = true; - continue :handle_entry; - }, - - error.AccessDenied, - error.PermissionDenied, - error.SymLinkLoop, - error.NameTooLong, - error.SystemResources, - error.ReadOnlyFileSystem, - error.FileSystem, - error.FileBusy, - error.BadPathName, - error.NetworkNotFound, - error.Unexpected, - => |e| return e, - } - } - } - } - // Reached the end of the directory entries, which means we successfully deleted all of them. - // Now to remove the directory itself. - dir.close(); - cleanup_dir = false; - - if (cleanup_dir_parent) |d| { - d.deleteDir(dir_name) catch |err| switch (err) { - // These two things can happen due to file system race conditions. - error.FileNotFound, error.DirNotEmpty => continue :start_over, - else => |e| return e, - }; - continue :start_over; - } else { - self.deleteDir(sub_path) catch |err| switch (err) { - error.FileNotFound => return, - error.DirNotEmpty => continue :start_over, - else => |e| return e, - }; - return; - } - } - } -} - -/// On successful delete, returns null. -fn deleteTreeOpenInitialSubpath(self: Dir, sub_path: []const u8, kind_hint: File.Kind) !?Dir { - return iterable_dir: { - // Treat as a file by default - var treat_as_dir = kind_hint == .directory; - - handle_entry: while (true) { - if (treat_as_dir) { - break :iterable_dir self.openDir(sub_path, .{ - .follow_symlinks = false, - .iterate = true, - }) catch |err| switch (err) { - error.NotDir => { - treat_as_dir = false; - continue :handle_entry; - }, - error.FileNotFound => { - // That's fine, we were trying to remove this directory anyway. - return null; - }, - - error.AccessDenied, - error.PermissionDenied, - error.SymLinkLoop, - error.ProcessFdQuotaExceeded, - error.NameTooLong, - error.SystemFdQuotaExceeded, - error.NoDevice, - error.SystemResources, - error.Unexpected, - error.BadPathName, - error.DeviceBusy, - error.NetworkNotFound, - error.Canceled, - => |e| return e, - }; - } else { - if (self.deleteFile(sub_path)) { - return null; - } else |err| switch (err) { - error.FileNotFound => return null, - - error.IsDir => { - treat_as_dir = true; - continue :handle_entry; - }, - - error.AccessDenied, - error.PermissionDenied, - error.SymLinkLoop, - error.NameTooLong, - error.SystemResources, - error.ReadOnlyFileSystem, - error.NotDir, - error.FileSystem, - error.FileBusy, - error.BadPathName, - error.NetworkNotFound, - error.Unexpected, - => |e| return e, - } - } - } - }; -} - -pub const WriteFileError = File.WriteError || File.OpenError; - -pub const WriteFileOptions = struct { - /// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). - /// On WASI, `sub_path` should be encoded as valid UTF-8. - /// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. - sub_path: []const u8, - data: []const u8, - flags: File.CreateFlags = .{}, -}; - -/// Writes content to the file system, using the file creation flags provided. -pub fn writeFile(self: Dir, options: WriteFileOptions) WriteFileError!void { - var file = try self.createFile(options.sub_path, options.flags); - defer file.close(); - try file.writeAll(options.data); -} - -/// Deprecated in favor of `Io.Dir.AccessError`. -pub const AccessError = Io.Dir.AccessError; - -/// Deprecated in favor of `Io.Dir.access`. -pub fn access(self: Dir, sub_path: []const u8, options: Io.Dir.AccessOptions) AccessError!void { - var threaded: Io.Threaded = .init_single_threaded; - const io = threaded.ioBasic(); - return Io.Dir.access(self.adaptToNewApi(), io, sub_path, options); -} - -pub const CopyFileOptions = struct { - /// When this is `null` the mode is copied from the source file. - override_mode: ?File.Mode = null, -}; - -pub const CopyFileError = File.OpenError || File.StatError || - AtomicFile.InitError || AtomicFile.FinishError || - File.ReadError || File.WriteError || error{InvalidFileName}; - -/// Atomically creates a new file at `dest_path` within `dest_dir` with the -/// same contents as `source_path` within `source_dir`, overwriting any already -/// existing file. -/// -/// On Linux, until https://patchwork.kernel.org/patch/9636735/ is merged and -/// readily available, there is a possibility of power loss or application -/// termination leaving temporary files present in the same directory as -/// dest_path. -/// -/// On Windows, both paths should be encoded as -/// [WTF-8](https://wtf-8.codeberg.page/). On WASI, both paths should be -/// encoded as valid UTF-8. On other platforms, both paths are an opaque -/// sequence of bytes with no particular encoding. -/// -/// TODO move this function to Io.Dir -pub fn copyFile( - source_dir: Dir, - source_path: []const u8, - dest_dir: Dir, - dest_path: []const u8, - options: CopyFileOptions, -) CopyFileError!void { - var threaded: Io.Threaded = .init_single_threaded; - const io = threaded.ioBasic(); - - const file = try source_dir.openFile(source_path, .{}); - var file_reader: File.Reader = .init(.{ .handle = file.handle }, io, &.{}); - defer file_reader.file.close(io); - - const mode = options.override_mode orelse blk: { - const st = try file_reader.file.stat(io); - file_reader.size = st.size; - break :blk st.mode; - }; - - var buffer: [1024]u8 = undefined; // Used only when direct fd-to-fd is not available. - var atomic_file = try dest_dir.atomicFile(dest_path, .{ - .mode = mode, - .write_buffer = &buffer, - }); - defer atomic_file.deinit(); - - _ = atomic_file.file_writer.interface.sendFileAll(&file_reader, .unlimited) catch |err| switch (err) { - error.ReadFailed => return file_reader.err.?, - error.WriteFailed => return atomic_file.file_writer.err.?, - }; - - try atomic_file.finish(); -} - -pub const AtomicFileOptions = struct { - mode: File.Mode = File.default_mode, - make_path: bool = false, - write_buffer: []u8, -}; - -/// Directly access the `.file` field, and then call `AtomicFile.finish` to -/// atomically replace `dest_path` with contents. -/// Always call `AtomicFile.deinit` to clean up, regardless of whether -/// `AtomicFile.finish` succeeded. `dest_path` must remain valid until -/// `AtomicFile.deinit` is called. -/// On Windows, `dest_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `dest_path` should be encoded as valid UTF-8. -/// On other platforms, `dest_path` is an opaque sequence of bytes with no particular encoding. -pub fn atomicFile(self: Dir, dest_path: []const u8, options: AtomicFileOptions) !AtomicFile { - if (fs.path.dirname(dest_path)) |dirname| { - const dir = if (options.make_path) - try self.makeOpenPath(dirname, .{}) - else - try self.openDir(dirname, .{}); - - return .init(fs.path.basename(dest_path), options.mode, dir, true, options.write_buffer); - } else { - return .init(dest_path, options.mode, self, false, options.write_buffer); - } -} - -pub const Stat = File.Stat; -pub const StatError = File.StatError; - -/// Deprecated in favor of `Io.Dir.stat`. -pub fn stat(self: Dir) StatError!Stat { - const file: File = .{ .handle = self.fd }; - return file.stat(); -} - -pub const StatFileError = File.OpenError || File.StatError || posix.FStatAtError; - -/// Deprecated in favor of `Io.Dir.statPath`. -pub fn statFile(self: Dir, sub_path: []const u8) StatFileError!Stat { - var threaded: Io.Threaded = .init_single_threaded; - const io = threaded.ioBasic(); - return Io.Dir.statPath(.{ .handle = self.fd }, io, sub_path, .{}); -} - -pub const ChmodError = File.ChmodError; - -/// Changes the mode of the directory. -/// The process must have the correct privileges in order to do this -/// successfully, or must have the effective user ID matching the owner -/// of the directory. Additionally, the directory must have been opened -/// with `OpenOptions{ .iterate = true }`. -pub fn chmod(self: Dir, new_mode: File.Mode) ChmodError!void { - const file: File = .{ .handle = self.fd }; - try file.chmod(new_mode); -} - -/// Changes the owner and group of the directory. -/// The process must have the correct privileges in order to do this -/// successfully. The group may be changed by the owner of the directory to -/// any group of which the owner is a member. Additionally, the directory -/// must have been opened with `OpenOptions{ .iterate = true }`. If the -/// owner or group is specified as `null`, the ID is not changed. -pub fn chown(self: Dir, owner: ?File.Uid, group: ?File.Gid) ChownError!void { - const file: File = .{ .handle = self.fd }; - try file.chown(owner, group); -} - -pub const ChownError = File.ChownError; - -const Permissions = File.Permissions; -pub const SetPermissionsError = File.SetPermissionsError; - -/// Sets permissions according to the provided `Permissions` struct. -/// This method is *NOT* available on WASI -pub fn setPermissions(self: Dir, permissions: Permissions) SetPermissionsError!void { - const file: File = .{ .handle = self.fd }; - try file.setPermissions(permissions); -} - -pub fn adaptToNewApi(dir: Dir) Io.Dir { - return .{ .handle = dir.fd }; -} - -pub fn adaptFromNewApi(dir: Io.Dir) Dir { - return .{ .fd = dir.handle }; -} diff --git a/lib/std/fs/File.zig b/lib/std/fs/File.zig deleted file mode 100644 index 073ab6777b21..000000000000 --- a/lib/std/fs/File.zig +++ /dev/null @@ -1,1437 +0,0 @@ -const File = @This(); - -const builtin = @import("builtin"); -const native_os = builtin.os.tag; -const is_windows = native_os == .windows; - -const std = @import("../std.zig"); -const Io = std.Io; -const Os = std.builtin.Os; -const Allocator = std.mem.Allocator; -const posix = std.posix; -const math = std.math; -const assert = std.debug.assert; -const linux = std.os.linux; -const windows = std.os.windows; -const maxInt = std.math.maxInt; -const Alignment = std.mem.Alignment; - -/// The OS-specific file descriptor or file handle. -handle: Handle, - -pub const Handle = Io.File.Handle; -pub const Mode = Io.File.Mode; -pub const INode = Io.File.INode; -pub const Uid = posix.uid_t; -pub const Gid = posix.gid_t; -pub const Kind = Io.File.Kind; - -/// This is the default mode given to POSIX operating systems for creating -/// files. `0o666` is "-rw-rw-rw-" which is counter-intuitive at first, -/// since most people would expect "-rw-r--r--", for example, when using -/// the `touch` command, which would correspond to `0o644`. However, POSIX -/// libc implementations use `0o666` inside `fopen` and then rely on the -/// process-scoped "umask" setting to adjust this number for file creation. -pub const default_mode: Mode = if (Mode == u0) 0 else 0o666; - -/// Deprecated in favor of `Io.File.OpenError`. -pub const OpenError = Io.File.OpenError || error{WouldBlock}; -/// Deprecated in favor of `Io.File.OpenMode`. -pub const OpenMode = Io.File.OpenMode; -/// Deprecated in favor of `Io.File.Lock`. -pub const Lock = Io.File.Lock; -/// Deprecated in favor of `Io.File.OpenFlags`. -pub const OpenFlags = Io.File.OpenFlags; - -pub const CreateFlags = struct { - /// Whether the file will be created with read access. - read: bool = false, - - /// If the file already exists, and is a regular file, and the access - /// mode allows writing, it will be truncated to length 0. - truncate: bool = true, - - /// Ensures that this open call creates the file, otherwise causes - /// `error.PathAlreadyExists` to be returned. - exclusive: bool = false, - - /// Open the file with an advisory lock to coordinate with other processes - /// accessing it at the same time. An exclusive lock will prevent other - /// processes from acquiring a lock. A shared lock will prevent other - /// processes from acquiring a exclusive lock, but does not prevent - /// other process from getting their own shared locks. - /// - /// The lock is advisory, except on Linux in very specific circumstances[1]. - /// This means that a process that does not respect the locking API can still get access - /// to the file, despite the lock. - /// - /// On these operating systems, the lock is acquired atomically with - /// opening the file: - /// * Darwin - /// * DragonFlyBSD - /// * FreeBSD - /// * Haiku - /// * NetBSD - /// * OpenBSD - /// On these operating systems, the lock is acquired via a separate syscall - /// after opening the file: - /// * Linux - /// * Windows - /// - /// [1]: https://www.kernel.org/doc/Documentation/filesystems/mandatory-locking.txt - lock: Lock = .none, - - /// Sets whether or not to wait until the file is locked to return. If set to true, - /// `error.WouldBlock` will be returned. Otherwise, the file will wait until the file - /// is available to proceed. - lock_nonblocking: bool = false, - - /// For POSIX systems this is the file system mode the file will - /// be created with. On other systems this is always 0. - mode: Mode = default_mode, -}; - -pub fn stdout() File { - return .{ .handle = if (is_windows) windows.peb().ProcessParameters.hStdOutput else posix.STDOUT_FILENO }; -} - -pub fn stderr() File { - return .{ .handle = if (is_windows) windows.peb().ProcessParameters.hStdError else posix.STDERR_FILENO }; -} - -pub fn stdin() File { - return .{ .handle = if (is_windows) windows.peb().ProcessParameters.hStdInput else posix.STDIN_FILENO }; -} - -/// Upon success, the stream is in an uninitialized state. To continue using it, -/// you must use the open() function. -pub fn close(self: File) void { - if (is_windows) { - windows.CloseHandle(self.handle); - } else { - posix.close(self.handle); - } -} - -pub const SyncError = posix.SyncError; - -/// Blocks until all pending file contents and metadata modifications -/// for the file have been synchronized with the underlying filesystem. -/// -/// Note that this does not ensure that metadata for the -/// directory containing the file has also reached disk. -pub fn sync(self: File) SyncError!void { - return posix.fsync(self.handle); -} - -/// Test whether the file refers to a terminal. -/// See also `getOrEnableAnsiEscapeSupport` and `supportsAnsiEscapeCodes`. -pub fn isTty(self: File) bool { - return posix.isatty(self.handle); -} - -pub fn isCygwinPty(file: File) bool { - if (builtin.os.tag != .windows) return false; - - const handle = file.handle; - - // If this is a MSYS2/cygwin pty, then it will be a named pipe with a name in one of these formats: - // msys-[...]-ptyN-[...] - // cygwin-[...]-ptyN-[...] - // - // Example: msys-1888ae32e00d56aa-pty0-to-master - - // First, just check that the handle is a named pipe. - // This allows us to avoid the more costly NtQueryInformationFile call - // for handles that aren't named pipes. - { - var io_status: windows.IO_STATUS_BLOCK = undefined; - var device_info: windows.FILE_FS_DEVICE_INFORMATION = undefined; - const rc = windows.ntdll.NtQueryVolumeInformationFile(handle, &io_status, &device_info, @sizeOf(windows.FILE_FS_DEVICE_INFORMATION), .FileFsDeviceInformation); - switch (rc) { - .SUCCESS => {}, - else => return false, - } - if (device_info.DeviceType != windows.FILE_DEVICE_NAMED_PIPE) return false; - } - - const name_bytes_offset = @offsetOf(windows.FILE_NAME_INFO, "FileName"); - // `NAME_MAX` UTF-16 code units (2 bytes each) - // This buffer may not be long enough to handle *all* possible paths - // (PATH_MAX_WIDE would be necessary for that), but because we only care - // about certain paths and we know they must be within a reasonable length, - // we can use this smaller buffer and just return false on any error from - // NtQueryInformationFile. - const num_name_bytes = windows.MAX_PATH * 2; - var name_info_bytes align(@alignOf(windows.FILE_NAME_INFO)) = [_]u8{0} ** (name_bytes_offset + num_name_bytes); - - var io_status_block: windows.IO_STATUS_BLOCK = undefined; - const rc = windows.ntdll.NtQueryInformationFile(handle, &io_status_block, &name_info_bytes, @intCast(name_info_bytes.len), .FileNameInformation); - switch (rc) { - .SUCCESS => {}, - .INVALID_PARAMETER => unreachable, - else => return false, - } - - const name_info: *const windows.FILE_NAME_INFO = @ptrCast(&name_info_bytes); - const name_bytes = name_info_bytes[name_bytes_offset .. name_bytes_offset + name_info.FileNameLength]; - const name_wide = std.mem.bytesAsSlice(u16, name_bytes); - // The name we get from NtQueryInformationFile will be prefixed with a '\', e.g. \msys-1888ae32e00d56aa-pty0-to-master - return (std.mem.startsWith(u16, name_wide, &[_]u16{ '\\', 'm', 's', 'y', 's', '-' }) or - std.mem.startsWith(u16, name_wide, &[_]u16{ '\\', 'c', 'y', 'g', 'w', 'i', 'n', '-' })) and - std.mem.indexOf(u16, name_wide, &[_]u16{ '-', 'p', 't', 'y' }) != null; -} - -/// Returns whether or not ANSI escape codes will be treated as such, -/// and attempts to enable support for ANSI escape codes if necessary -/// (on Windows). -/// -/// Returns `true` if ANSI escape codes are supported or support was -/// successfully enabled. Returns false if ANSI escape codes are not -/// supported or support was unable to be enabled. -/// -/// See also `supportsAnsiEscapeCodes`. -pub fn getOrEnableAnsiEscapeSupport(self: File) bool { - if (builtin.os.tag == .windows) { - var original_console_mode: windows.DWORD = 0; - - // For Windows Terminal, VT Sequences processing is enabled by default. - if (windows.kernel32.GetConsoleMode(self.handle, &original_console_mode) != 0) { - if (original_console_mode & windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING != 0) return true; - - // For Windows Console, VT Sequences processing support was added in Windows 10 build 14361, but disabled by default. - // https://devblogs.microsoft.com/commandline/tmux-support-arrives-for-bash-on-ubuntu-on-windows/ - // - // Note: In Microsoft's example for enabling virtual terminal processing, it - // shows attempting to enable `DISABLE_NEWLINE_AUTO_RETURN` as well: - // https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#example-of-enabling-virtual-terminal-processing - // This is avoided because in the old Windows Console, that flag causes \n (as opposed to \r\n) - // to behave unexpectedly (the cursor moves down 1 row but remains on the same column). - // Additionally, the default console mode in Windows Terminal does not have - // `DISABLE_NEWLINE_AUTO_RETURN` set, so by only enabling `ENABLE_VIRTUAL_TERMINAL_PROCESSING` - // we end up matching the mode of Windows Terminal. - const requested_console_modes = windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING; - const console_mode = original_console_mode | requested_console_modes; - if (windows.kernel32.SetConsoleMode(self.handle, console_mode) != 0) return true; - } - - return self.isCygwinPty(); - } - return self.supportsAnsiEscapeCodes(); -} - -/// Test whether ANSI escape codes will be treated as such without -/// attempting to enable support for ANSI escape codes. -/// -/// See also `getOrEnableAnsiEscapeSupport`. -pub fn supportsAnsiEscapeCodes(self: File) bool { - if (builtin.os.tag == .windows) { - var console_mode: windows.DWORD = 0; - if (windows.kernel32.GetConsoleMode(self.handle, &console_mode) != 0) { - if (console_mode & windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING != 0) return true; - } - - return self.isCygwinPty(); - } - if (builtin.os.tag == .wasi) { - // WASI sanitizes stdout when fd is a tty so ANSI escape codes - // will not be interpreted as actual cursor commands, and - // stderr is always sanitized. - return false; - } - if (self.isTty()) { - if (self.handle == posix.STDOUT_FILENO or self.handle == posix.STDERR_FILENO) { - if (posix.getenvZ("TERM")) |term| { - if (std.mem.eql(u8, term, "dumb")) - return false; - } - } - return true; - } - return false; -} - -pub const SetEndPosError = posix.TruncateError; - -/// Shrinks or expands the file. -/// The file offset after this call is left unchanged. -pub fn setEndPos(self: File, length: u64) SetEndPosError!void { - try posix.ftruncate(self.handle, length); -} - -pub const SeekError = posix.SeekError; - -/// Repositions read/write file offset relative to the current offset. -/// TODO: integrate with async I/O -pub fn seekBy(self: File, offset: i64) SeekError!void { - return posix.lseek_CUR(self.handle, offset); -} - -/// Repositions read/write file offset relative to the end. -/// TODO: integrate with async I/O -pub fn seekFromEnd(self: File, offset: i64) SeekError!void { - return posix.lseek_END(self.handle, offset); -} - -/// Repositions read/write file offset relative to the beginning. -/// TODO: integrate with async I/O -pub fn seekTo(self: File, offset: u64) SeekError!void { - return posix.lseek_SET(self.handle, offset); -} - -pub const GetSeekPosError = posix.SeekError || StatError; - -/// TODO: integrate with async I/O -pub fn getPos(self: File) GetSeekPosError!u64 { - return posix.lseek_CUR_get(self.handle); -} - -pub const GetEndPosError = std.os.windows.GetFileSizeError || StatError; - -/// TODO: integrate with async I/O -pub fn getEndPos(self: File) GetEndPosError!u64 { - if (builtin.os.tag == .windows) { - return windows.GetFileSizeEx(self.handle); - } - return (try self.stat()).size; -} - -pub const ModeError = StatError; - -/// TODO: integrate with async I/O -pub fn mode(self: File) ModeError!Mode { - if (builtin.os.tag == .windows) { - return 0; - } - return (try self.stat()).mode; -} - -pub const Stat = Io.File.Stat; - -pub const StatError = posix.FStatError; - -/// Returns `Stat` containing basic information about the `File`. -pub fn stat(self: File) StatError!Stat { - var threaded: Io.Threaded = .init_single_threaded; - const io = threaded.ioBasic(); - return Io.File.stat(.{ .handle = self.handle }, io); -} - -pub const ChmodError = posix.FChmodError; - -/// Changes the mode of the file. -/// The process must have the correct privileges in order to do this -/// successfully, or must have the effective user ID matching the owner -/// of the file. -pub fn chmod(self: File, new_mode: Mode) ChmodError!void { - try posix.fchmod(self.handle, new_mode); -} - -pub const ChownError = posix.FChownError; - -/// Changes the owner and group of the file. -/// The process must have the correct privileges in order to do this -/// successfully. The group may be changed by the owner of the file to -/// any group of which the owner is a member. If the owner or group is -/// specified as `null`, the ID is not changed. -pub fn chown(self: File, owner: ?Uid, group: ?Gid) ChownError!void { - try posix.fchown(self.handle, owner, group); -} - -/// Cross-platform representation of permissions on a file. -/// The `readonly` and `setReadonly` are the only methods available across all platforms. -/// Platform-specific functionality is available through the `inner` field. -pub const Permissions = struct { - /// You may use the `inner` field to use platform-specific functionality - inner: switch (builtin.os.tag) { - .windows => PermissionsWindows, - else => PermissionsUnix, - }, - - const Self = @This(); - - /// Returns `true` if permissions represent an unwritable file. - /// On Unix, `true` is returned only if no class has write permissions. - pub fn readOnly(self: Self) bool { - return self.inner.readOnly(); - } - - /// Sets whether write permissions are provided. - /// On Unix, this affects *all* classes. If this is undesired, use `unixSet`. - /// This method *DOES NOT* set permissions on the filesystem: use `File.setPermissions(permissions)` - pub fn setReadOnly(self: *Self, read_only: bool) void { - self.inner.setReadOnly(read_only); - } -}; - -pub const PermissionsWindows = struct { - attributes: windows.DWORD, - - const Self = @This(); - - /// Returns `true` if permissions represent an unwritable file. - pub fn readOnly(self: Self) bool { - return self.attributes & windows.FILE_ATTRIBUTE_READONLY != 0; - } - - /// Sets whether write permissions are provided. - /// This method *DOES NOT* set permissions on the filesystem: use `File.setPermissions(permissions)` - pub fn setReadOnly(self: *Self, read_only: bool) void { - if (read_only) { - self.attributes |= windows.FILE_ATTRIBUTE_READONLY; - } else { - self.attributes &= ~@as(windows.DWORD, windows.FILE_ATTRIBUTE_READONLY); - } - } -}; - -pub const PermissionsUnix = struct { - mode: Mode, - - const Self = @This(); - - /// Returns `true` if permissions represent an unwritable file. - /// `true` is returned only if no class has write permissions. - pub fn readOnly(self: Self) bool { - return self.mode & 0o222 == 0; - } - - /// Sets whether write permissions are provided. - /// This affects *all* classes. If this is undesired, use `unixSet`. - /// This method *DOES NOT* set permissions on the filesystem: use `File.setPermissions(permissions)` - pub fn setReadOnly(self: *Self, read_only: bool) void { - if (read_only) { - self.mode &= ~@as(Mode, 0o222); - } else { - self.mode |= @as(Mode, 0o222); - } - } - - pub const Class = enum(u2) { - user = 2, - group = 1, - other = 0, - }; - - pub const Permission = enum(u3) { - read = 0o4, - write = 0o2, - execute = 0o1, - }; - - /// Returns `true` if the chosen class has the selected permission. - /// This method is only available on Unix platforms. - pub fn unixHas(self: Self, class: Class, permission: Permission) bool { - const mask = @as(Mode, @intFromEnum(permission)) << @as(u3, @intFromEnum(class)) * 3; - return self.mode & mask != 0; - } - - /// Sets the permissions for the chosen class. Any permissions set to `null` are left unchanged. - /// This method *DOES NOT* set permissions on the filesystem: use `File.setPermissions(permissions)` - pub fn unixSet(self: *Self, class: Class, permissions: struct { - read: ?bool = null, - write: ?bool = null, - execute: ?bool = null, - }) void { - const shift = @as(u3, @intFromEnum(class)) * 3; - if (permissions.read) |r| { - if (r) { - self.mode |= @as(Mode, 0o4) << shift; - } else { - self.mode &= ~(@as(Mode, 0o4) << shift); - } - } - if (permissions.write) |w| { - if (w) { - self.mode |= @as(Mode, 0o2) << shift; - } else { - self.mode &= ~(@as(Mode, 0o2) << shift); - } - } - if (permissions.execute) |x| { - if (x) { - self.mode |= @as(Mode, 0o1) << shift; - } else { - self.mode &= ~(@as(Mode, 0o1) << shift); - } - } - } - - /// Returns a `Permissions` struct representing the permissions from the passed mode. - pub fn unixNew(new_mode: Mode) Self { - return Self{ - .mode = new_mode, - }; - } -}; - -pub const SetPermissionsError = ChmodError; - -/// Sets permissions according to the provided `Permissions` struct. -/// This method is *NOT* available on WASI -pub fn setPermissions(self: File, permissions: Permissions) SetPermissionsError!void { - switch (builtin.os.tag) { - .windows => { - var io_status_block: windows.IO_STATUS_BLOCK = undefined; - var info = windows.FILE_BASIC_INFORMATION{ - .CreationTime = 0, - .LastAccessTime = 0, - .LastWriteTime = 0, - .ChangeTime = 0, - .FileAttributes = permissions.inner.attributes, - }; - const rc = windows.ntdll.NtSetInformationFile( - self.handle, - &io_status_block, - &info, - @sizeOf(windows.FILE_BASIC_INFORMATION), - .FileBasicInformation, - ); - switch (rc) { - .SUCCESS => return, - .INVALID_HANDLE => unreachable, - .ACCESS_DENIED => return error.AccessDenied, - else => return windows.unexpectedStatus(rc), - } - }, - .wasi => @compileError("Unsupported OS"), // Wasi filesystem does not *yet* support chmod - else => { - try self.chmod(permissions.inner.mode); - }, - } -} - -pub const UpdateTimesError = posix.FutimensError || windows.SetFileTimeError; - -/// The underlying file system may have a different granularity than nanoseconds, -/// and therefore this function cannot guarantee any precision will be stored. -/// Further, the maximum value is limited by the system ABI. When a value is provided -/// that exceeds this range, the value is clamped to the maximum. -/// TODO: integrate with async I/O -pub fn updateTimes( - self: File, - /// access timestamp in nanoseconds - atime: Io.Timestamp, - /// last modification timestamp in nanoseconds - mtime: Io.Timestamp, -) UpdateTimesError!void { - if (builtin.os.tag == .windows) { - const atime_ft = windows.nanoSecondsToFileTime(atime); - const mtime_ft = windows.nanoSecondsToFileTime(mtime); - return windows.SetFileTime(self.handle, null, &atime_ft, &mtime_ft); - } - const times = [2]posix.timespec{ - posix.timespec{ - .sec = math.cast(isize, @divFloor(atime.nanoseconds, std.time.ns_per_s)) orelse maxInt(isize), - .nsec = math.cast(isize, @mod(atime.nanoseconds, std.time.ns_per_s)) orelse maxInt(isize), - }, - posix.timespec{ - .sec = math.cast(isize, @divFloor(mtime.nanoseconds, std.time.ns_per_s)) orelse maxInt(isize), - .nsec = math.cast(isize, @mod(mtime.nanoseconds, std.time.ns_per_s)) orelse maxInt(isize), - }, - }; - try posix.futimens(self.handle, ×); -} - -pub const ReadError = posix.ReadError; -pub const PReadError = posix.PReadError; - -pub fn read(self: File, buffer: []u8) ReadError!usize { - if (is_windows) { - return windows.ReadFile(self.handle, buffer, null); - } - - return posix.read(self.handle, buffer); -} - -/// On Windows, this function currently does alter the file pointer. -/// https://github.com/ziglang/zig/issues/12783 -pub fn pread(self: File, buffer: []u8, offset: u64) PReadError!usize { - if (is_windows) { - return windows.ReadFile(self.handle, buffer, offset); - } - - return posix.pread(self.handle, buffer, offset); -} - -/// Deprecated in favor of `Reader`. -pub fn preadAll(self: File, buffer: []u8, offset: u64) PReadError!usize { - var index: usize = 0; - while (index != buffer.len) { - const amt = try self.pread(buffer[index..], offset + index); - if (amt == 0) break; - index += amt; - } - return index; -} - -/// See https://github.com/ziglang/zig/issues/7699 -pub fn readv(self: File, iovecs: []const posix.iovec) ReadError!usize { - if (is_windows) { - if (iovecs.len == 0) return 0; - const first = iovecs[0]; - return windows.ReadFile(self.handle, first.base[0..first.len], null); - } - - return posix.readv(self.handle, iovecs); -} - -/// See https://github.com/ziglang/zig/issues/7699 -/// On Windows, this function currently does alter the file pointer. -/// https://github.com/ziglang/zig/issues/12783 -pub fn preadv(self: File, iovecs: []const posix.iovec, offset: u64) PReadError!usize { - if (is_windows) { - if (iovecs.len == 0) return 0; - const first = iovecs[0]; - return windows.ReadFile(self.handle, first.base[0..first.len], offset); - } - - return posix.preadv(self.handle, iovecs, offset); -} - -pub const WriteError = posix.WriteError; -pub const PWriteError = posix.PWriteError; - -pub fn write(self: File, bytes: []const u8) WriteError!usize { - if (is_windows) { - return windows.WriteFile(self.handle, bytes, null); - } - - return posix.write(self.handle, bytes); -} - -pub fn writeAll(self: File, bytes: []const u8) WriteError!void { - var index: usize = 0; - while (index < bytes.len) { - index += try self.write(bytes[index..]); - } -} - -/// Deprecated in favor of `Writer`. -pub fn pwriteAll(self: File, bytes: []const u8, offset: u64) PWriteError!void { - var index: usize = 0; - while (index < bytes.len) { - index += try self.pwrite(bytes[index..], offset + index); - } -} - -/// On Windows, this function currently does alter the file pointer. -/// https://github.com/ziglang/zig/issues/12783 -pub fn pwrite(self: File, bytes: []const u8, offset: u64) PWriteError!usize { - if (is_windows) { - return windows.WriteFile(self.handle, bytes, offset); - } - - return posix.pwrite(self.handle, bytes, offset); -} - -/// See https://github.com/ziglang/zig/issues/7699 -pub fn writev(self: File, iovecs: []const posix.iovec_const) WriteError!usize { - if (is_windows) { - // TODO improve this to use WriteFileScatter - if (iovecs.len == 0) return 0; - const first = iovecs[0]; - return windows.WriteFile(self.handle, first.base[0..first.len], null); - } - - return posix.writev(self.handle, iovecs); -} - -/// See https://github.com/ziglang/zig/issues/7699 -/// On Windows, this function currently does alter the file pointer. -/// https://github.com/ziglang/zig/issues/12783 -pub fn pwritev(self: File, iovecs: []posix.iovec_const, offset: u64) PWriteError!usize { - if (is_windows) { - if (iovecs.len == 0) return 0; - const first = iovecs[0]; - return windows.WriteFile(self.handle, first.base[0..first.len], offset); - } - - return posix.pwritev(self.handle, iovecs, offset); -} - -/// Deprecated in favor of `Writer`. -pub const CopyRangeError = posix.CopyFileRangeError; - -/// Deprecated in favor of `Writer`. -pub fn copyRange(in: File, in_offset: u64, out: File, out_offset: u64, len: u64) CopyRangeError!u64 { - const adjusted_len = math.cast(usize, len) orelse maxInt(usize); - const result = try posix.copy_file_range(in.handle, in_offset, out.handle, out_offset, adjusted_len, 0); - return result; -} - -/// Deprecated in favor of `Writer`. -pub fn copyRangeAll(in: File, in_offset: u64, out: File, out_offset: u64, len: u64) CopyRangeError!u64 { - var total_bytes_copied: u64 = 0; - var in_off = in_offset; - var out_off = out_offset; - while (total_bytes_copied < len) { - const amt_copied = try copyRange(in, in_off, out, out_off, len - total_bytes_copied); - if (amt_copied == 0) return total_bytes_copied; - total_bytes_copied += amt_copied; - in_off += amt_copied; - out_off += amt_copied; - } - return total_bytes_copied; -} - -/// Deprecated in favor of `Io.File.Reader`. -pub const Reader = Io.File.Reader; - -pub const Writer = struct { - file: File, - err: ?WriteError = null, - mode: Writer.Mode = .positional, - /// Tracks the true seek position in the file. To obtain the logical - /// position, add the buffer size to this value. - pos: u64 = 0, - sendfile_err: ?SendfileError = null, - copy_file_range_err: ?CopyFileRangeError = null, - fcopyfile_err: ?FcopyfileError = null, - seek_err: ?Writer.SeekError = null, - interface: Io.Writer, - - pub const Mode = Reader.Mode; - - pub const SendfileError = error{ - UnsupportedOperation, - SystemResources, - InputOutput, - BrokenPipe, - WouldBlock, - Unexpected, - }; - - pub const CopyFileRangeError = std.os.freebsd.CopyFileRangeError || std.os.linux.wrapped.CopyFileRangeError; - - pub const FcopyfileError = error{ - OperationNotSupported, - OutOfMemory, - Unexpected, - }; - - pub const SeekError = File.SeekError; - - /// Number of slices to store on the stack, when trying to send as many byte - /// vectors through the underlying write calls as possible. - const max_buffers_len = 16; - - pub fn init(file: File, buffer: []u8) Writer { - return .{ - .file = file, - .interface = initInterface(buffer), - .mode = .positional, - }; - } - - /// Positional is more threadsafe, since the global seek position is not - /// affected, but when such syscalls are not available, preemptively - /// initializing in streaming mode will skip a failed syscall. - pub fn initStreaming(file: File, buffer: []u8) Writer { - return .{ - .file = file, - .interface = initInterface(buffer), - .mode = .streaming, - }; - } - - pub fn initInterface(buffer: []u8) Io.Writer { - return .{ - .vtable = &.{ - .drain = drain, - .sendFile = sendFile, - }, - .buffer = buffer, - }; - } - - /// TODO when this logic moves from fs.File to Io.File the io parameter should be deleted - pub fn moveToReader(w: *Writer, io: Io) Reader { - defer w.* = undefined; - return .{ - .io = io, - .file = .{ .handle = w.file.handle }, - .mode = w.mode, - .pos = w.pos, - .interface = Reader.initInterface(w.interface.buffer), - .seek_err = w.seek_err, - }; - } - - pub fn drain(io_w: *Io.Writer, data: []const []const u8, splat: usize) Io.Writer.Error!usize { - const w: *Writer = @alignCast(@fieldParentPtr("interface", io_w)); - const handle = w.file.handle; - const buffered = io_w.buffered(); - if (is_windows) switch (w.mode) { - .positional, .positional_reading => { - if (buffered.len != 0) { - const n = windows.WriteFile(handle, buffered, w.pos) catch |err| { - w.err = err; - return error.WriteFailed; - }; - w.pos += n; - return io_w.consume(n); - } - for (data[0 .. data.len - 1]) |buf| { - if (buf.len == 0) continue; - const n = windows.WriteFile(handle, buf, w.pos) catch |err| { - w.err = err; - return error.WriteFailed; - }; - w.pos += n; - return io_w.consume(n); - } - const pattern = data[data.len - 1]; - if (pattern.len == 0 or splat == 0) return 0; - const n = windows.WriteFile(handle, pattern, w.pos) catch |err| { - w.err = err; - return error.WriteFailed; - }; - w.pos += n; - return io_w.consume(n); - }, - .streaming, .streaming_reading => { - if (buffered.len != 0) { - const n = windows.WriteFile(handle, buffered, null) catch |err| { - w.err = err; - return error.WriteFailed; - }; - w.pos += n; - return io_w.consume(n); - } - for (data[0 .. data.len - 1]) |buf| { - if (buf.len == 0) continue; - const n = windows.WriteFile(handle, buf, null) catch |err| { - w.err = err; - return error.WriteFailed; - }; - w.pos += n; - return io_w.consume(n); - } - const pattern = data[data.len - 1]; - if (pattern.len == 0 or splat == 0) return 0; - const n = windows.WriteFile(handle, pattern, null) catch |err| { - w.err = err; - return error.WriteFailed; - }; - w.pos += n; - return io_w.consume(n); - }, - .failure => return error.WriteFailed, - }; - var iovecs: [max_buffers_len]std.posix.iovec_const = undefined; - var len: usize = 0; - if (buffered.len > 0) { - iovecs[len] = .{ .base = buffered.ptr, .len = buffered.len }; - len += 1; - } - for (data[0 .. data.len - 1]) |d| { - if (d.len == 0) continue; - iovecs[len] = .{ .base = d.ptr, .len = d.len }; - len += 1; - if (iovecs.len - len == 0) break; - } - const pattern = data[data.len - 1]; - if (iovecs.len - len != 0) switch (splat) { - 0 => {}, - 1 => if (pattern.len != 0) { - iovecs[len] = .{ .base = pattern.ptr, .len = pattern.len }; - len += 1; - }, - else => switch (pattern.len) { - 0 => {}, - 1 => { - const splat_buffer_candidate = io_w.buffer[io_w.end..]; - var backup_buffer: [64]u8 = undefined; - const splat_buffer = if (splat_buffer_candidate.len >= backup_buffer.len) - splat_buffer_candidate - else - &backup_buffer; - const memset_len = @min(splat_buffer.len, splat); - const buf = splat_buffer[0..memset_len]; - @memset(buf, pattern[0]); - iovecs[len] = .{ .base = buf.ptr, .len = buf.len }; - len += 1; - var remaining_splat = splat - buf.len; - while (remaining_splat > splat_buffer.len and iovecs.len - len != 0) { - assert(buf.len == splat_buffer.len); - iovecs[len] = .{ .base = splat_buffer.ptr, .len = splat_buffer.len }; - len += 1; - remaining_splat -= splat_buffer.len; - } - if (remaining_splat > 0 and iovecs.len - len != 0) { - iovecs[len] = .{ .base = splat_buffer.ptr, .len = remaining_splat }; - len += 1; - } - }, - else => for (0..splat) |_| { - iovecs[len] = .{ .base = pattern.ptr, .len = pattern.len }; - len += 1; - if (iovecs.len - len == 0) break; - }, - }, - }; - if (len == 0) return 0; - switch (w.mode) { - .positional, .positional_reading => { - const n = std.posix.pwritev(handle, iovecs[0..len], w.pos) catch |err| switch (err) { - error.Unseekable => { - w.mode = w.mode.toStreaming(); - const pos = w.pos; - if (pos != 0) { - w.pos = 0; - w.seekTo(@intCast(pos)) catch { - w.mode = .failure; - return error.WriteFailed; - }; - } - return 0; - }, - else => |e| { - w.err = e; - return error.WriteFailed; - }, - }; - w.pos += n; - return io_w.consume(n); - }, - .streaming, .streaming_reading => { - const n = std.posix.writev(handle, iovecs[0..len]) catch |err| { - w.err = err; - return error.WriteFailed; - }; - w.pos += n; - return io_w.consume(n); - }, - .failure => return error.WriteFailed, - } - } - - pub fn sendFile( - io_w: *Io.Writer, - file_reader: *Io.File.Reader, - limit: Io.Limit, - ) Io.Writer.FileError!usize { - const reader_buffered = file_reader.interface.buffered(); - if (reader_buffered.len >= @intFromEnum(limit)) - return sendFileBuffered(io_w, file_reader, limit.slice(reader_buffered)); - const writer_buffered = io_w.buffered(); - const file_limit = @intFromEnum(limit) - reader_buffered.len; - const w: *Writer = @alignCast(@fieldParentPtr("interface", io_w)); - const out_fd = w.file.handle; - const in_fd = file_reader.file.handle; - - if (file_reader.size) |size| { - if (size - file_reader.pos == 0) { - if (reader_buffered.len != 0) { - return sendFileBuffered(io_w, file_reader, reader_buffered); - } else { - return error.EndOfStream; - } - } - } - - if (native_os == .freebsd and w.mode == .streaming) sf: { - // Try using sendfile on FreeBSD. - if (w.sendfile_err != null) break :sf; - const offset = std.math.cast(std.c.off_t, file_reader.pos) orelse break :sf; - var hdtr_data: std.c.sf_hdtr = undefined; - var headers: [2]posix.iovec_const = undefined; - var headers_i: u8 = 0; - if (writer_buffered.len != 0) { - headers[headers_i] = .{ .base = writer_buffered.ptr, .len = writer_buffered.len }; - headers_i += 1; - } - if (reader_buffered.len != 0) { - headers[headers_i] = .{ .base = reader_buffered.ptr, .len = reader_buffered.len }; - headers_i += 1; - } - const hdtr: ?*std.c.sf_hdtr = if (headers_i == 0) null else b: { - hdtr_data = .{ - .headers = &headers, - .hdr_cnt = headers_i, - .trailers = null, - .trl_cnt = 0, - }; - break :b &hdtr_data; - }; - var sbytes: std.c.off_t = undefined; - const nbytes: usize = @min(file_limit, maxInt(usize)); - const flags = 0; - switch (posix.errno(std.c.sendfile(in_fd, out_fd, offset, nbytes, hdtr, &sbytes, flags))) { - .SUCCESS, .INTR => {}, - .INVAL, .OPNOTSUPP, .NOTSOCK, .NOSYS => w.sendfile_err = error.UnsupportedOperation, - .BADF => if (builtin.mode == .Debug) @panic("race condition") else { - w.sendfile_err = error.Unexpected; - }, - .FAULT => if (builtin.mode == .Debug) @panic("segmentation fault") else { - w.sendfile_err = error.Unexpected; - }, - .NOTCONN => w.sendfile_err = error.BrokenPipe, - .AGAIN, .BUSY => if (sbytes == 0) { - w.sendfile_err = error.WouldBlock; - }, - .IO => w.sendfile_err = error.InputOutput, - .PIPE => w.sendfile_err = error.BrokenPipe, - .NOBUFS => w.sendfile_err = error.SystemResources, - else => |err| w.sendfile_err = posix.unexpectedErrno(err), - } - if (w.sendfile_err != null) { - // Give calling code chance to observe the error before trying - // something else. - return 0; - } - if (sbytes == 0) { - file_reader.size = file_reader.pos; - return error.EndOfStream; - } - const consumed = io_w.consume(@intCast(sbytes)); - file_reader.seekBy(@intCast(consumed)) catch return error.ReadFailed; - return consumed; - } - - if (native_os.isDarwin() and w.mode == .streaming) sf: { - // Try using sendfile on macOS. - if (w.sendfile_err != null) break :sf; - const offset = std.math.cast(std.c.off_t, file_reader.pos) orelse break :sf; - var hdtr_data: std.c.sf_hdtr = undefined; - var headers: [2]posix.iovec_const = undefined; - var headers_i: u8 = 0; - if (writer_buffered.len != 0) { - headers[headers_i] = .{ .base = writer_buffered.ptr, .len = writer_buffered.len }; - headers_i += 1; - } - if (reader_buffered.len != 0) { - headers[headers_i] = .{ .base = reader_buffered.ptr, .len = reader_buffered.len }; - headers_i += 1; - } - const hdtr: ?*std.c.sf_hdtr = if (headers_i == 0) null else b: { - hdtr_data = .{ - .headers = &headers, - .hdr_cnt = headers_i, - .trailers = null, - .trl_cnt = 0, - }; - break :b &hdtr_data; - }; - const max_count = maxInt(i32); // Avoid EINVAL. - var len: std.c.off_t = @min(file_limit, max_count); - const flags = 0; - switch (posix.errno(std.c.sendfile(in_fd, out_fd, offset, &len, hdtr, flags))) { - .SUCCESS, .INTR => {}, - .OPNOTSUPP, .NOTSOCK, .NOSYS => w.sendfile_err = error.UnsupportedOperation, - .BADF => if (builtin.mode == .Debug) @panic("race condition") else { - w.sendfile_err = error.Unexpected; - }, - .FAULT => if (builtin.mode == .Debug) @panic("segmentation fault") else { - w.sendfile_err = error.Unexpected; - }, - .INVAL => if (builtin.mode == .Debug) @panic("invalid API usage") else { - w.sendfile_err = error.Unexpected; - }, - .NOTCONN => w.sendfile_err = error.BrokenPipe, - .AGAIN => if (len == 0) { - w.sendfile_err = error.WouldBlock; - }, - .IO => w.sendfile_err = error.InputOutput, - .PIPE => w.sendfile_err = error.BrokenPipe, - else => |err| w.sendfile_err = posix.unexpectedErrno(err), - } - if (w.sendfile_err != null) { - // Give calling code chance to observe the error before trying - // something else. - return 0; - } - if (len == 0) { - file_reader.size = file_reader.pos; - return error.EndOfStream; - } - const consumed = io_w.consume(@bitCast(len)); - file_reader.seekBy(@intCast(consumed)) catch return error.ReadFailed; - return consumed; - } - - if (native_os == .linux and w.mode == .streaming) sf: { - // Try using sendfile on Linux. - if (w.sendfile_err != null) break :sf; - // Linux sendfile does not support headers. - if (writer_buffered.len != 0 or reader_buffered.len != 0) - return sendFileBuffered(io_w, file_reader, reader_buffered); - const max_count = 0x7ffff000; // Avoid EINVAL. - var off: std.os.linux.off_t = undefined; - const off_ptr: ?*std.os.linux.off_t, const count: usize = switch (file_reader.mode) { - .positional => o: { - const size = file_reader.getSize() catch return 0; - off = std.math.cast(std.os.linux.off_t, file_reader.pos) orelse return error.ReadFailed; - break :o .{ &off, @min(@intFromEnum(limit), size - file_reader.pos, max_count) }; - }, - .streaming => .{ null, limit.minInt(max_count) }, - .streaming_reading, .positional_reading => break :sf, - .failure => return error.ReadFailed, - }; - const n = std.os.linux.wrapped.sendfile(out_fd, in_fd, off_ptr, count) catch |err| switch (err) { - error.Unseekable => { - file_reader.mode = file_reader.mode.toStreaming(); - const pos = file_reader.pos; - if (pos != 0) { - file_reader.pos = 0; - file_reader.seekBy(@intCast(pos)) catch { - file_reader.mode = .failure; - return error.ReadFailed; - }; - } - return 0; - }, - else => |e| { - w.sendfile_err = e; - return 0; - }, - }; - if (n == 0) { - file_reader.size = file_reader.pos; - return error.EndOfStream; - } - file_reader.pos += n; - w.pos += n; - return n; - } - - const copy_file_range = switch (native_os) { - .freebsd => std.os.freebsd.copy_file_range, - .linux => std.os.linux.wrapped.copy_file_range, - else => {}, - }; - if (@TypeOf(copy_file_range) != void) cfr: { - if (w.copy_file_range_err != null) break :cfr; - if (writer_buffered.len != 0 or reader_buffered.len != 0) - return sendFileBuffered(io_w, file_reader, reader_buffered); - var off_in: i64 = undefined; - var off_out: i64 = undefined; - const off_in_ptr: ?*i64 = switch (file_reader.mode) { - .positional_reading, .streaming_reading => return error.Unimplemented, - .positional => p: { - off_in = @intCast(file_reader.pos); - break :p &off_in; - }, - .streaming => null, - .failure => return error.WriteFailed, - }; - const off_out_ptr: ?*i64 = switch (w.mode) { - .positional_reading, .streaming_reading => return error.Unimplemented, - .positional => p: { - off_out = @intCast(w.pos); - break :p &off_out; - }, - .streaming => null, - .failure => return error.WriteFailed, - }; - const n = copy_file_range(in_fd, off_in_ptr, out_fd, off_out_ptr, @intFromEnum(limit), 0) catch |err| { - w.copy_file_range_err = err; - return 0; - }; - if (n == 0) { - file_reader.size = file_reader.pos; - return error.EndOfStream; - } - file_reader.pos += n; - w.pos += n; - return n; - } - - if (builtin.os.tag.isDarwin()) fcf: { - if (w.fcopyfile_err != null) break :fcf; - if (file_reader.pos != 0) break :fcf; - if (w.pos != 0) break :fcf; - if (limit != .unlimited) break :fcf; - const size = file_reader.getSize() catch break :fcf; - if (writer_buffered.len != 0 or reader_buffered.len != 0) - return sendFileBuffered(io_w, file_reader, reader_buffered); - const rc = std.c.fcopyfile(in_fd, out_fd, null, .{ .DATA = true }); - switch (posix.errno(rc)) { - .SUCCESS => {}, - .INVAL => if (builtin.mode == .Debug) @panic("invalid API usage") else { - w.fcopyfile_err = error.Unexpected; - return 0; - }, - .NOMEM => { - w.fcopyfile_err = error.OutOfMemory; - return 0; - }, - .OPNOTSUPP => { - w.fcopyfile_err = error.OperationNotSupported; - return 0; - }, - else => |err| { - w.fcopyfile_err = posix.unexpectedErrno(err); - return 0; - }, - } - file_reader.pos = size; - w.pos = size; - return size; - } - - return error.Unimplemented; - } - - fn sendFileBuffered( - io_w: *Io.Writer, - file_reader: *Io.File.Reader, - reader_buffered: []const u8, - ) Io.Writer.FileError!usize { - const n = try drain(io_w, &.{reader_buffered}, 1); - file_reader.seekBy(@intCast(n)) catch return error.ReadFailed; - return n; - } - - pub fn seekTo(w: *Writer, offset: u64) (Writer.SeekError || Io.Writer.Error)!void { - try w.interface.flush(); - try seekToUnbuffered(w, offset); - } - - /// Asserts that no data is currently buffered. - pub fn seekToUnbuffered(w: *Writer, offset: u64) Writer.SeekError!void { - assert(w.interface.buffered().len == 0); - switch (w.mode) { - .positional, .positional_reading => { - w.pos = offset; - }, - .streaming, .streaming_reading => { - if (w.seek_err) |err| return err; - posix.lseek_SET(w.file.handle, offset) catch |err| { - w.seek_err = err; - return err; - }; - w.pos = offset; - }, - .failure => return w.seek_err.?, - } - } - - pub const EndError = SetEndPosError || Io.Writer.Error; - - /// Flushes any buffered data and sets the end position of the file. - /// - /// If not overwriting existing contents, then calling `interface.flush` - /// directly is sufficient. - /// - /// Flush failure is handled by setting `err` so that it can be handled - /// along with other write failures. - pub fn end(w: *Writer) EndError!void { - try w.interface.flush(); - switch (w.mode) { - .positional, - .positional_reading, - => w.file.setEndPos(w.pos) catch |err| switch (err) { - error.NonResizable => return, - else => |e| return e, - }, - - .streaming, - .streaming_reading, - .failure, - => {}, - } - } -}; - -/// Defaults to positional reading; falls back to streaming. -/// -/// Positional is more threadsafe, since the global seek position is not -/// affected. -pub fn reader(file: File, io: Io, buffer: []u8) Reader { - return .init(.{ .handle = file.handle }, io, buffer); -} - -/// Positional is more threadsafe, since the global seek position is not -/// affected, but when such syscalls are not available, preemptively -/// initializing in streaming mode skips a failed syscall. -pub fn readerStreaming(file: File, io: Io, buffer: []u8) Reader { - return .initStreaming(.{ .handle = file.handle }, io, buffer); -} - -/// Defaults to positional reading; falls back to streaming. -/// -/// Positional is more threadsafe, since the global seek position is not -/// affected. -pub fn writer(file: File, buffer: []u8) Writer { - return .init(file, buffer); -} - -/// Positional is more threadsafe, since the global seek position is not -/// affected, but when such syscalls are not available, preemptively -/// initializing in streaming mode will skip a failed syscall. -pub fn writerStreaming(file: File, buffer: []u8) Writer { - return .initStreaming(file, buffer); -} - -const range_off: windows.LARGE_INTEGER = 0; -const range_len: windows.LARGE_INTEGER = 1; - -pub const LockError = error{ - SystemResources, - FileLocksNotSupported, -} || posix.UnexpectedError; - -/// Blocks when an incompatible lock is held by another process. -/// A process may hold only one type of lock (shared or exclusive) on -/// a file. When a process terminates in any way, the lock is released. -/// -/// Assumes the file is unlocked. -/// -/// TODO: integrate with async I/O -pub fn lock(file: File, l: Lock) LockError!void { - if (is_windows) { - var io_status_block: windows.IO_STATUS_BLOCK = undefined; - const exclusive = switch (l) { - .none => return, - .shared => false, - .exclusive => true, - }; - return windows.LockFile( - file.handle, - null, - null, - null, - &io_status_block, - &range_off, - &range_len, - null, - windows.FALSE, // non-blocking=false - @intFromBool(exclusive), - ) catch |err| switch (err) { - error.WouldBlock => unreachable, // non-blocking=false - else => |e| return e, - }; - } else { - return posix.flock(file.handle, switch (l) { - .none => posix.LOCK.UN, - .shared => posix.LOCK.SH, - .exclusive => posix.LOCK.EX, - }) catch |err| switch (err) { - error.WouldBlock => unreachable, // non-blocking=false - else => |e| return e, - }; - } -} - -/// Assumes the file is locked. -pub fn unlock(file: File) void { - if (is_windows) { - var io_status_block: windows.IO_STATUS_BLOCK = undefined; - return windows.UnlockFile( - file.handle, - &io_status_block, - &range_off, - &range_len, - null, - ) catch |err| switch (err) { - error.RangeNotLocked => unreachable, // Function assumes unlocked. - error.Unexpected => unreachable, // Resource deallocation must succeed. - }; - } else { - return posix.flock(file.handle, posix.LOCK.UN) catch |err| switch (err) { - error.WouldBlock => unreachable, // unlocking can't block - error.SystemResources => unreachable, // We are deallocating resources. - error.FileLocksNotSupported => unreachable, // We already got the lock. - error.Unexpected => unreachable, // Resource deallocation must succeed. - }; - } -} - -/// Attempts to obtain a lock, returning `true` if the lock is -/// obtained, and `false` if there was an existing incompatible lock held. -/// A process may hold only one type of lock (shared or exclusive) on -/// a file. When a process terminates in any way, the lock is released. -/// -/// Assumes the file is unlocked. -/// -/// TODO: integrate with async I/O -pub fn tryLock(file: File, l: Lock) LockError!bool { - if (is_windows) { - var io_status_block: windows.IO_STATUS_BLOCK = undefined; - const exclusive = switch (l) { - .none => return, - .shared => false, - .exclusive => true, - }; - windows.LockFile( - file.handle, - null, - null, - null, - &io_status_block, - &range_off, - &range_len, - null, - windows.TRUE, // non-blocking=true - @intFromBool(exclusive), - ) catch |err| switch (err) { - error.WouldBlock => return false, - else => |e| return e, - }; - } else { - posix.flock(file.handle, switch (l) { - .none => posix.LOCK.UN, - .shared => posix.LOCK.SH | posix.LOCK.NB, - .exclusive => posix.LOCK.EX | posix.LOCK.NB, - }) catch |err| switch (err) { - error.WouldBlock => return false, - else => |e| return e, - }; - } - return true; -} - -/// Assumes the file is already locked in exclusive mode. -/// Atomically modifies the lock to be in shared mode, without releasing it. -/// -/// TODO: integrate with async I/O -pub fn downgradeLock(file: File) LockError!void { - if (is_windows) { - // On Windows it works like a semaphore + exclusivity flag. To implement this - // function, we first obtain another lock in shared mode. This changes the - // exclusivity flag, but increments the semaphore to 2. So we follow up with - // an NtUnlockFile which decrements the semaphore but does not modify the - // exclusivity flag. - var io_status_block: windows.IO_STATUS_BLOCK = undefined; - windows.LockFile( - file.handle, - null, - null, - null, - &io_status_block, - &range_off, - &range_len, - null, - windows.TRUE, // non-blocking=true - windows.FALSE, // exclusive=false - ) catch |err| switch (err) { - error.WouldBlock => unreachable, // File was not locked in exclusive mode. - else => |e| return e, - }; - return windows.UnlockFile( - file.handle, - &io_status_block, - &range_off, - &range_len, - null, - ) catch |err| switch (err) { - error.RangeNotLocked => unreachable, // File was not locked. - error.Unexpected => unreachable, // Resource deallocation must succeed. - }; - } else { - return posix.flock(file.handle, posix.LOCK.SH | posix.LOCK.NB) catch |err| switch (err) { - error.WouldBlock => unreachable, // File was not locked in exclusive mode. - else => |e| return e, - }; - } -} - -pub fn adaptToNewApi(file: File) Io.File { - return .{ .handle = file.handle }; -} - -pub fn adaptFromNewApi(file: Io.File) File { - return .{ .handle = file.handle }; -} diff --git a/lib/std/fs/get_app_data_dir.zig b/lib/std/fs/get_app_data_dir.zig deleted file mode 100644 index 24741206cc9c..000000000000 --- a/lib/std/fs/get_app_data_dir.zig +++ /dev/null @@ -1,66 +0,0 @@ -const std = @import("../std.zig"); -const builtin = @import("builtin"); -const unicode = std.unicode; -const mem = std.mem; -const fs = std.fs; -const native_os = builtin.os.tag; -const posix = std.posix; - -pub const GetAppDataDirError = error{ - OutOfMemory, - AppDataDirUnavailable, -}; - -/// Caller owns returned memory. -/// TODO determine if we can remove the allocator requirement -pub fn getAppDataDir(allocator: mem.Allocator, appname: []const u8) GetAppDataDirError![]u8 { - switch (native_os) { - .windows => { - const local_app_data_dir = std.process.getEnvVarOwned(allocator, "LOCALAPPDATA") catch |err| switch (err) { - error.OutOfMemory => |e| return e, - else => return error.AppDataDirUnavailable, - }; - defer allocator.free(local_app_data_dir); - return fs.path.join(allocator, &[_][]const u8{ local_app_data_dir, appname }); - }, - .maccatalyst, .macos => { - const home_dir = posix.getenv("HOME") orelse { - // TODO look in /etc/passwd - return error.AppDataDirUnavailable; - }; - return fs.path.join(allocator, &[_][]const u8{ home_dir, "Library", "Application Support", appname }); - }, - .linux, .freebsd, .netbsd, .dragonfly, .openbsd, .illumos, .serenity => { - if (posix.getenv("XDG_DATA_HOME")) |xdg| { - if (xdg.len > 0) { - return fs.path.join(allocator, &[_][]const u8{ xdg, appname }); - } - } - - const home_dir = posix.getenv("HOME") orelse { - // TODO look in /etc/passwd - return error.AppDataDirUnavailable; - }; - return fs.path.join(allocator, &[_][]const u8{ home_dir, ".local", "share", appname }); - }, - .haiku => { - var dir_path_buf: [std.fs.max_path_bytes]u8 = undefined; - const rc = std.c.find_directory(.B_USER_SETTINGS_DIRECTORY, -1, true, &dir_path_buf, dir_path_buf.len); - const settings_dir = try allocator.dupeZ(u8, mem.sliceTo(&dir_path_buf, 0)); - defer allocator.free(settings_dir); - switch (rc) { - 0 => return fs.path.join(allocator, &[_][]const u8{ settings_dir, appname }), - else => return error.AppDataDirUnavailable, - } - }, - else => @compileError("Unsupported OS"), - } -} - -test getAppDataDir { - if (native_os == .wasi) return error.SkipZigTest; - - // We can't actually validate the result - const dir = getAppDataDir(std.testing.allocator, "zig") catch return; - defer std.testing.allocator.free(dir); -} diff --git a/lib/std/fs/path.zig b/lib/std/fs/path.zig index 62324fe5b55c..cd189cc12246 100644 --- a/lib/std/fs/path.zig +++ b/lib/std/fs/path.zig @@ -13,16 +13,15 @@ //! https://github.com/WebAssembly/wasi-filesystem/issues/17#issuecomment-1430639353 const builtin = @import("builtin"); +const native_os = builtin.target.os.tag; + const std = @import("../std.zig"); -const debug = std.debug; -const assert = debug.assert; +const assert = std.debug.assert; const testing = std.testing; const mem = std.mem; -const ascii = std.ascii; -const Allocator = mem.Allocator; -const windows = std.os.windows; -const process = std.process; -const native_os = builtin.target.os.tag; +const Allocator = std.mem.Allocator; +const eqlIgnoreCaseWtf8 = std.os.windows.eqlIgnoreCaseWtf8; +const eqlIgnoreCaseWtf16 = std.os.windows.eqlIgnoreCaseWtf16; pub const sep_windows: u8 = '\\'; pub const sep_posix: u8 = '/'; @@ -281,7 +280,7 @@ pub fn isAbsolute(path: []const u8) bool { } fn isAbsoluteWindowsImpl(comptime T: type, path: []const T) bool { - return switch (windows.getWin32PathType(T, path)) { + return switch (getWin32PathType(T, path)) { // Unambiguously absolute .drive_absolute, .unc_absolute, .local_device, .root_local_device => true, // Unambiguously relative @@ -402,9 +401,9 @@ pub fn windowsParsePath(path: []const u8) WindowsPath { if (path.len >= 2 and PathType.windows.isSep(u8, path[0]) and PathType.windows.isSep(u8, path[1])) { const root_end = root_end: { - var server_end = mem.indexOfAnyPos(u8, path, 2, "/\\") orelse break :root_end path.len; + var server_end = mem.findAnyPos(u8, path, 2, "/\\") orelse break :root_end path.len; while (server_end < path.len and PathType.windows.isSep(u8, path[server_end])) server_end += 1; - break :root_end mem.indexOfAnyPos(u8, path, server_end, "/\\") orelse path.len; + break :root_end mem.findAnyPos(u8, path, server_end, "/\\") orelse path.len; }; return WindowsPath{ .is_abs = true, @@ -515,13 +514,13 @@ test parsePathPosix { pub fn WindowsPath2(comptime T: type) type { return struct { - kind: windows.Win32PathType, + kind: Win32PathType, root: []const T, }; } pub fn parsePathWindows(comptime T: type, path: []const T) WindowsPath2(T) { - const kind = windows.getWin32PathType(T, path); + const kind = getWin32PathType(T, path); const root = root: switch (kind) { .drive_absolute, .drive_relative => { const drive_letter_len = getDriveLetter(T, path).len; @@ -722,7 +721,7 @@ fn parseUNC(comptime T: type, path: []const T) WindowsUNC(T) { // For the server, the first path separator after the initial two is always // the terminator of the server name, even if that means the server name is // zero-length. - const server_end = mem.indexOfAnyPos(T, path, 2, any_sep) orelse return .{ + const server_end = mem.findAnyPos(T, path, 2, any_sep) orelse return .{ .server = path[2..path.len], .sep_after_server = false, .share = path[path.len..path.len], @@ -731,7 +730,7 @@ fn parseUNC(comptime T: type, path: []const T) WindowsUNC(T) { // For the share, there can be any number of path separators between the server // and the share, so we want to skip over all of them instead of just looking for // the first one. - var it = std.mem.tokenizeAny(T, path[server_end + 1 ..], any_sep); + var it = mem.tokenizeAny(T, path[server_end + 1 ..], any_sep); const share = it.next() orelse return .{ .server = path[2..server_end], .sep_after_server = true, @@ -803,8 +802,8 @@ const DiskDesignatorKind = enum { drive, unc }; /// `p1` and `p2` are both assumed to be the `kind` provided. fn compareDiskDesignators(comptime T: type, kind: DiskDesignatorKind, p1: []const T, p2: []const T) bool { const eql = switch (T) { - u8 => windows.eqlIgnoreCaseWtf8, - u16 => windows.eqlIgnoreCaseWtf16, + u8 => eqlIgnoreCaseWtf8, + u16 => eqlIgnoreCaseWtf16, else => @compileError("only u8 (WTF-8) and u16 (WTF-16LE) is supported"), }; switch (kind) { @@ -872,7 +871,7 @@ pub fn resolve(allocator: Allocator, paths: []const []const u8) Allocator.Error! /// This function is like a series of `cd` statements executed one after another. /// It resolves "." and ".." to the best of its ability, but will not convert relative paths to -/// an absolute path, use std.fs.Dir.realpath instead. +/// an absolute path, use Io.Dir.realpath instead. /// ".." components may persist in the resolved path if the resolved path is relative or drive-relative. /// Path separators are canonicalized to '\\' and drives are canonicalized to capital letters. /// @@ -1094,10 +1093,14 @@ pub fn resolveWindows(allocator: Allocator, paths: []const []const u8) Allocator } /// This function is like a series of `cd` statements executed one after another. +/// /// It resolves "." and ".." to the best of its ability, but will not convert relative paths to -/// an absolute path, use std.fs.Dir.realpath instead. +/// an absolute path, use Io.Dir.realpath instead. +/// /// ".." components may persist in the resolved path if the resolved path is relative. +/// /// The result does not have a trailing path separator. +/// /// This function does not perform any syscalls. Executing this series of path /// lookups on the actual filesystem may produce different results due to /// symlinks. @@ -1494,25 +1497,54 @@ fn testBasenameWindows(input: []const u8, expected_output: []const u8) !void { try testing.expectEqualSlices(u8, expected_output, basenameWindows(input)); } -pub const RelativeError = std.process.GetCwdAllocError; - -/// Returns the relative path from `from` to `to`. If `from` and `to` each -/// resolve to the same path (after calling `resolve` on each), a zero-length -/// string is returned. -/// On Windows, the result is not guaranteed to be relative, as the paths may be -/// on different volumes. In that case, the result will be the canonicalized absolute -/// path of `to`. -pub fn relative(allocator: Allocator, from: []const u8, to: []const u8) RelativeError![]u8 { +/// Returns the non-absolute path from `from` to `to`. +/// +/// Other than memory allocation, this is a pure function; the result solely +/// depends on the input parameters. +/// +/// If `from` and `to` each resolve to the same path (after calling `resolve` +/// on each), a zero-length string is returned. +/// +/// See `relativePosix` and `relativeWindows` for operating system specific +/// details and for how `environ_map` is used. +pub fn relative( + gpa: Allocator, + cwd: []const u8, + environ_map: ?*const std.process.Environ.Map, + from: []const u8, + to: []const u8, +) Allocator.Error![]u8 { if (native_os == .windows) { - return relativeWindows(allocator, from, to); + return relativeWindows(gpa, cwd, environ_map, from, to); } else { - return relativePosix(allocator, from, to); + return relativePosix(gpa, cwd, from, to); } } -pub fn relativeWindows(allocator: Allocator, from: []const u8, to: []const u8) ![]u8 { - if (native_os != .windows) @compileError("this function relies on Windows-specific semantics"); - +/// Returns the non-absolute path from `from` to `to` according to Windows rules. +/// +/// Other than memory allocation, this is a pure function; the result solely +/// depends on the input parameters. +/// +/// If `from` and `to` each resolve to the same path (after calling `resolve` +/// on each), a zero-length string is returned. +/// +/// The result is not guaranteed to be relative, as the paths may be on +/// different volumes. In that case, the result will be the canonicalized +/// absolute path of `to`. +/// +/// Per-drive CWDs are stored in special semi-hidden environment variables of +/// the format `=:`, e.g. `=C:`. This type of CWD is purely a +/// shell concept, so there's no guarantee that it'll be set or that it'll even +/// be accurate. This is the only reason for the `environ_map` parameter. `null` is +/// treated equivalent to the environment variable missing. +pub fn relativeWindows( + gpa: Allocator, + cwd: []const u8, + environ_map: ?*const std.process.Environ.Map, + from: []const u8, + to: []const u8, +) Allocator.Error![]u8 { const parsed_from = parsePathWindows(u8, from); const parsed_to = parsePathWindows(u8, to); @@ -1533,14 +1565,14 @@ pub fn relativeWindows(allocator: Allocator, from: []const u8, to: []const u8) ! }; if (result_is_always_to) { - return windowsResolveAgainstCwd(allocator, to, parsed_to); + return windowsResolveAgainstCwd(gpa, cwd, environ_map, to, parsed_to); } - const resolved_from = try windowsResolveAgainstCwd(allocator, from, parsed_from); - defer allocator.free(resolved_from); + const resolved_from = try windowsResolveAgainstCwd(gpa, cwd, environ_map, from, parsed_from); + defer gpa.free(resolved_from); var clean_up_resolved_to = true; - const resolved_to = try windowsResolveAgainstCwd(allocator, to, parsed_to); - defer if (clean_up_resolved_to) allocator.free(resolved_to); + const resolved_to = try windowsResolveAgainstCwd(gpa, cwd, environ_map, to, parsed_to); + defer if (clean_up_resolved_to) gpa.free(resolved_to); const parsed_resolved_from = parsePathWindows(u8, resolved_from); const parsed_resolved_to = parsePathWindows(u8, resolved_to); @@ -1569,18 +1601,18 @@ pub fn relativeWindows(allocator: Allocator, from: []const u8, to: []const u8) ! var from_it = mem.tokenizeAny(u8, resolved_from[parsed_resolved_from.root.len..], "/\\"); var to_it = mem.tokenizeAny(u8, resolved_to[parsed_resolved_to.root.len..], "/\\"); while (true) { - const from_component = from_it.next() orelse return allocator.dupe(u8, to_it.rest()); + const from_component = from_it.next() orelse return gpa.dupe(u8, to_it.rest()); const to_rest = to_it.rest(); if (to_it.next()) |to_component| { - if (windows.eqlIgnoreCaseWtf8(from_component, to_component)) + if (eqlIgnoreCaseWtf8(from_component, to_component)) continue; } var up_index_end = "..".len; while (from_it.next()) |_| { up_index_end += "\\..".len; } - const result = try allocator.alloc(u8, up_index_end + @intFromBool(to_rest.len > 0) + to_rest.len); - errdefer allocator.free(result); + const result = try gpa.alloc(u8, up_index_end + @intFromBool(to_rest.len > 0) + to_rest.len); + errdefer gpa.free(result); result[0..2].* = "..".*; var result_index: usize = 2; @@ -1597,85 +1629,60 @@ pub fn relativeWindows(allocator: Allocator, from: []const u8, to: []const u8) ! result_index += to_component.len; } - return allocator.realloc(result, result_index); + return gpa.realloc(result, result_index); } return [_]u8{}; } -fn windowsResolveAgainstCwd(allocator: Allocator, path: []const u8, parsed: WindowsPath2(u8)) ![]u8 { +fn windowsResolveAgainstCwd( + gpa: Allocator, + cwd: []const u8, + environ_map: ?*const std.process.Environ.Map, + path: []const u8, + parsed: WindowsPath2(u8), +) ![]u8 { // Space for 256 WTF-16 code units; potentially 3 WTF-8 bytes per WTF-16 code unit - var temp_allocator_state = std.heap.stackFallback(256 * 3, allocator); + var temp_allocator_state = std.heap.stackFallback(256 * 3, gpa); return switch (parsed.kind) { .drive_absolute, .unc_absolute, .root_local_device, .local_device, - => try resolveWindows(allocator, &.{path}), - .relative => blk: { - const temp_allocator = temp_allocator_state.get(); + => try resolveWindows(gpa, &.{path}), - const peb_cwd = windows.peb().ProcessParameters.CurrentDirectory.DosPath; - const cwd_w = (peb_cwd.Buffer.?)[0 .. peb_cwd.Length / 2]; + .relative => try resolveWindows(gpa, &.{ cwd, path }), - const wtf8_len = std.unicode.calcWtf8Len(cwd_w); - const wtf8_buf = try temp_allocator.alloc(u8, wtf8_len); - defer temp_allocator.free(wtf8_buf); - assert(std.unicode.wtf16LeToWtf8(wtf8_buf, cwd_w) == wtf8_len); - - break :blk try resolveWindows(allocator, &.{ wtf8_buf, path }); - }, .rooted => blk: { - const peb_cwd = windows.peb().ProcessParameters.CurrentDirectory.DosPath; - const cwd_w = (peb_cwd.Buffer.?)[0 .. peb_cwd.Length / 2]; - const parsed_cwd = parsePathWindows(u16, cwd_w); + const parsed_cwd = parsePathWindows(u8, cwd); switch (parsed_cwd.kind) { .drive_absolute => { var drive_buf = "_:\\".*; - drive_buf[0] = @truncate(cwd_w[0]); - break :blk try resolveWindows(allocator, &.{ &drive_buf, path }); + drive_buf[0] = cwd[0]; + break :blk try resolveWindows(gpa, &.{ &drive_buf, path }); }, .unc_absolute => { - const temp_allocator = temp_allocator_state.get(); - var root_buf = try temp_allocator.alloc(u8, parsed_cwd.root.len * 3); - defer temp_allocator.free(root_buf); - - const wtf8_len = std.unicode.wtf16LeToWtf8(root_buf, parsed_cwd.root); - const root = root_buf[0..wtf8_len]; - break :blk try resolveWindows(allocator, &.{ root, path }); + break :blk try resolveWindows(gpa, &.{ parsed_cwd.root, path }); }, // Effectively a malformed CWD, give up and just return a normalized path - else => break :blk try resolveWindows(allocator, &.{path}), + else => break :blk try resolveWindows(gpa, &.{path}), } }, .drive_relative => blk: { const temp_allocator = temp_allocator_state.get(); const drive_cwd = drive_cwd: { - const peb_cwd = windows.peb().ProcessParameters.CurrentDirectory.DosPath; - const cwd_w = (peb_cwd.Buffer.?)[0 .. peb_cwd.Length / 2]; - const parsed_cwd = parsePathWindows(u16, cwd_w); + const parsed_cwd = parsePathWindows(u8, cwd); if (parsed_cwd.kind == .drive_absolute) { const drive_letter_w = parsed_cwd.root[0]; const drive_letters_match = drive_letter_w <= 0x7F and - ascii.toUpper(@intCast(drive_letter_w)) == ascii.toUpper(parsed.root[0]); - if (drive_letters_match) { - const wtf8_len = std.unicode.calcWtf8Len(cwd_w); - const wtf8_buf = try temp_allocator.alloc(u8, wtf8_len); - assert(std.unicode.wtf16LeToWtf8(wtf8_buf, cwd_w) == wtf8_len); - break :drive_cwd wtf8_buf[0..]; - } - - // Per-drive CWD's are stored in special semi-hidden environment variables - // of the format `=:`, e.g. `=C:`. This type of CWD is - // purely a shell concept, so there's no guarantee that it'll be set - // or that it'll even be accurate. - var key_buf = std.unicode.wtf8ToWtf16LeStringLiteral("=_:").*; - key_buf[1] = parsed.root[0]; - if (std.process.getenvW(&key_buf)) |drive_cwd_w| { - const wtf8_len = std.unicode.calcWtf8Len(drive_cwd_w); - const wtf8_buf = try temp_allocator.alloc(u8, wtf8_len); - assert(std.unicode.wtf16LeToWtf8(wtf8_buf, drive_cwd_w) == wtf8_len); - break :drive_cwd wtf8_buf[0..]; + std.ascii.toUpper(@intCast(drive_letter_w)) == std.ascii.toUpper(parsed.root[0]); + if (drive_letters_match) + break :drive_cwd cwd; + + if (environ_map) |m| { + if (m.get(&.{ '=', parsed.root[0], ':' })) |v| { + break :drive_cwd try temp_allocator.dupe(u8, v); + } } } @@ -1686,16 +1693,20 @@ fn windowsResolveAgainstCwd(allocator: Allocator, path: []const u8, parsed: Wind break :drive_cwd drive_buf; }; defer temp_allocator.free(drive_cwd); - break :blk try resolveWindows(allocator, &.{ drive_cwd, path }); + break :blk try resolveWindows(gpa, &.{ drive_cwd, path }); }, }; } -pub fn relativePosix(allocator: Allocator, from: []const u8, to: []const u8) ![]u8 { - if (native_os == .windows) @compileError("this function relies on semantics that do not apply to Windows"); - - const cwd = try process.getCwdAlloc(allocator); - defer allocator.free(cwd); +/// Returns the non-absolute path from `from` to `to` according to Windows rules. +/// +/// Other than memory allocation, this is a pure function; the result solely +/// depends on the input parameters. +/// +/// If `from` and `to` each resolve to the same path (after calling `resolve` +/// on each), a zero-length string is returned. +/// +pub fn relativePosix(allocator: Allocator, cwd: []const u8, from: []const u8, to: []const u8) Allocator.Error![]u8 { const resolved_from = try resolvePosix(allocator, &[_][]const u8{ cwd, from }); defer allocator.free(resolved_from); const resolved_to = try resolvePosix(allocator, &[_][]const u8{ cwd, to }); @@ -1736,69 +1747,67 @@ pub fn relativePosix(allocator: Allocator, from: []const u8, to: []const u8) ![] } test relative { - if (native_os == .windows) { - try testRelativeWindows("c:/blah\\blah", "d:/games", "D:\\games"); - try testRelativeWindows("c:/aaaa/bbbb", "c:/aaaa", ".."); - try testRelativeWindows("c:/aaaa/bbbb", "c:/cccc", "..\\..\\cccc"); - try testRelativeWindows("c:/aaaa/bbbb", "C:/aaaa/bbbb", ""); - try testRelativeWindows("c:/aaaa/bbbb", "c:/aaaa/cccc", "..\\cccc"); - try testRelativeWindows("c:/aaaa/", "c:/aaaa/cccc", "cccc"); - try testRelativeWindows("c:/", "c:\\aaaa\\bbbb", "aaaa\\bbbb"); - try testRelativeWindows("c:/aaaa/bbbb", "d:\\", "D:\\"); - try testRelativeWindows("c:/AaAa/bbbb", "c:/aaaa/bbbb", ""); - try testRelativeWindows("c:/aaaaa/", "c:/aaaa/cccc", "..\\aaaa\\cccc"); - try testRelativeWindows("C:\\foo\\bar\\baz\\quux", "C:\\", "..\\..\\..\\.."); - try testRelativeWindows("C:\\foo\\test", "C:\\foo\\test\\bar\\package.json", "bar\\package.json"); - try testRelativeWindows("C:\\foo\\bar\\baz-quux", "C:\\foo\\bar\\baz", "..\\baz"); - try testRelativeWindows("C:\\foo\\bar\\baz", "C:\\foo\\bar\\baz-quux", "..\\baz-quux"); - try testRelativeWindows("\\\\foo\\bar", "\\\\foo\\bar\\baz", "baz"); - try testRelativeWindows("\\\\foo\\bar\\baz", "\\\\foo\\bar", ".."); - try testRelativeWindows("\\\\foo\\bar\\baz-quux", "\\\\foo\\bar\\baz", "..\\baz"); - try testRelativeWindows("\\\\foo/bar\\baz-quux", "//foo\\bar/baz", "..\\baz"); - try testRelativeWindows("\\\\foo\\bar\\baz", "\\\\foo\\bar\\baz-quux", "..\\baz-quux"); - try testRelativeWindows("C:\\baz-quux", "C:\\baz", "..\\baz"); - try testRelativeWindows("C:\\baz", "C:\\baz-quux", "..\\baz-quux"); - try testRelativeWindows("\\\\foo\\baz-quux", "\\\\foo\\baz", "\\\\foo\\baz"); - try testRelativeWindows("\\\\foo\\baz", "\\\\foo\\baz-quux", "\\\\foo\\baz-quux"); - try testRelativeWindows("C:\\baz", "\\\\foo\\bar\\baz", "\\\\foo\\bar\\baz"); - try testRelativeWindows("\\\\foo\\bar\\baz", "C:\\baz", "C:\\baz"); - - try testRelativeWindows("c:blah\\blah", "c:foo", "..\\..\\foo"); - try testRelativeWindows("c:foo", "c:foo\\bar", "bar"); - try testRelativeWindows("\\blah\\blah", "\\foo", "..\\..\\foo"); - try testRelativeWindows("\\foo", "\\foo\\bar", "bar"); - - try testRelativeWindows("a/b/c", "a\\b", ".."); - try testRelativeWindows("a/b/c", "a", "..\\.."); - try testRelativeWindows("a/b/c", "a\\b\\c\\d", "d"); - - try testRelativeWindows("\\\\FOO\\bar\\baz", "\\\\foo\\BAR\\BAZ", ""); - // Unicode-aware case-insensitive path comparison - try testRelativeWindows("\\\\кириллица\\ελληνικά\\português", "\\\\КИРИЛЛИЦА\\ΕΛΛΗΝΙΚΆ\\PORTUGUÊS", ""); - } else { - try testRelativePosix("/var/lib", "/var", ".."); - try testRelativePosix("/var/lib", "/bin", "../../bin"); - try testRelativePosix("/var/lib", "/var/lib", ""); - try testRelativePosix("/var/lib", "/var/apache", "../apache"); - try testRelativePosix("/var/", "/var/lib", "lib"); - try testRelativePosix("/", "/var/lib", "var/lib"); - try testRelativePosix("/foo/test", "/foo/test/bar/package.json", "bar/package.json"); - try testRelativePosix("/Users/a/web/b/test/mails", "/Users/a/web/b", "../.."); - try testRelativePosix("/foo/bar/baz-quux", "/foo/bar/baz", "../baz"); - try testRelativePosix("/foo/bar/baz", "/foo/bar/baz-quux", "../baz-quux"); - try testRelativePosix("/baz-quux", "/baz", "../baz"); - try testRelativePosix("/baz", "/baz-quux", "../baz-quux"); - } + try testRelativeWindows("c:/blah\\blah", "d:/games", "D:\\games"); + try testRelativeWindows("c:/aaaa/bbbb", "c:/aaaa", ".."); + try testRelativeWindows("c:/aaaa/bbbb", "c:/cccc", "..\\..\\cccc"); + try testRelativeWindows("c:/aaaa/bbbb", "C:/aaaa/bbbb", ""); + try testRelativeWindows("c:/aaaa/bbbb", "c:/aaaa/cccc", "..\\cccc"); + try testRelativeWindows("c:/aaaa/", "c:/aaaa/cccc", "cccc"); + try testRelativeWindows("c:/", "c:\\aaaa\\bbbb", "aaaa\\bbbb"); + try testRelativeWindows("c:/aaaa/bbbb", "d:\\", "D:\\"); + try testRelativeWindows("c:/AaAa/bbbb", "c:/aaaa/bbbb", ""); + try testRelativeWindows("c:/aaaaa/", "c:/aaaa/cccc", "..\\aaaa\\cccc"); + try testRelativeWindows("C:\\foo\\bar\\baz\\quux", "C:\\", "..\\..\\..\\.."); + try testRelativeWindows("C:\\foo\\test", "C:\\foo\\test\\bar\\package.json", "bar\\package.json"); + try testRelativeWindows("C:\\foo\\bar\\baz-quux", "C:\\foo\\bar\\baz", "..\\baz"); + try testRelativeWindows("C:\\foo\\bar\\baz", "C:\\foo\\bar\\baz-quux", "..\\baz-quux"); + try testRelativeWindows("\\\\foo\\bar", "\\\\foo\\bar\\baz", "baz"); + try testRelativeWindows("\\\\foo\\bar\\baz", "\\\\foo\\bar", ".."); + try testRelativeWindows("\\\\foo\\bar\\baz-quux", "\\\\foo\\bar\\baz", "..\\baz"); + try testRelativeWindows("\\\\foo/bar\\baz-quux", "//foo\\bar/baz", "..\\baz"); + try testRelativeWindows("\\\\foo\\bar\\baz", "\\\\foo\\bar\\baz-quux", "..\\baz-quux"); + try testRelativeWindows("C:\\baz-quux", "C:\\baz", "..\\baz"); + try testRelativeWindows("C:\\baz", "C:\\baz-quux", "..\\baz-quux"); + try testRelativeWindows("\\\\foo\\baz-quux", "\\\\foo\\baz", "\\\\foo\\baz"); + try testRelativeWindows("\\\\foo\\baz", "\\\\foo\\baz-quux", "\\\\foo\\baz-quux"); + try testRelativeWindows("C:\\baz", "\\\\foo\\bar\\baz", "\\\\foo\\bar\\baz"); + try testRelativeWindows("\\\\foo\\bar\\baz", "C:\\baz", "C:\\baz"); + + try testRelativeWindows("c:blah\\blah", "c:foo", "..\\..\\foo"); + try testRelativeWindows("c:foo", "c:foo\\bar", "bar"); + try testRelativeWindows("\\blah\\blah", "\\foo", "..\\..\\foo"); + try testRelativeWindows("\\foo", "\\foo\\bar", "bar"); + + try testRelativeWindows("a/b/c", "a\\b", ".."); + try testRelativeWindows("a/b/c", "a", "..\\.."); + try testRelativeWindows("a/b/c", "a\\b\\c\\d", "d"); + + try testRelativeWindows("\\\\FOO\\bar\\baz", "\\\\foo\\BAR\\BAZ", ""); + // Unicode-aware case-insensitive path comparison + try testRelativeWindows("\\\\кириллица\\ελληνικά\\português", "\\\\КИРИЛЛИЦА\\ΕΛΛΗΝΙΚΆ\\PORTUGUÊS", ""); + + try testRelativePosix("/var/lib", "/var", ".."); + try testRelativePosix("/var/lib", "/bin", "../../bin"); + try testRelativePosix("/var/lib", "/var/lib", ""); + try testRelativePosix("/var/lib", "/var/apache", "../apache"); + try testRelativePosix("/var/", "/var/lib", "lib"); + try testRelativePosix("/", "/var/lib", "var/lib"); + try testRelativePosix("/foo/test", "/foo/test/bar/package.json", "bar/package.json"); + try testRelativePosix("/Users/a/web/b/test/mails", "/Users/a/web/b", "../.."); + try testRelativePosix("/foo/bar/baz-quux", "/foo/bar/baz", "../baz"); + try testRelativePosix("/foo/bar/baz", "/foo/bar/baz-quux", "../baz-quux"); + try testRelativePosix("/baz-quux", "/baz", "../baz"); + try testRelativePosix("/baz", "/baz-quux", "../baz-quux"); } fn testRelativePosix(from: []const u8, to: []const u8, expected_output: []const u8) !void { - const result = try relativePosix(testing.allocator, from, to); + const result = try relativePosix(testing.allocator, ".", from, to); defer testing.allocator.free(result); try testing.expectEqualStrings(expected_output, result); } fn testRelativeWindows(from: []const u8, to: []const u8, expected_output: []const u8) !void { - const result = try relativeWindows(testing.allocator, from, to); + const result = try relativeWindows(testing.allocator, ".", null, from, to); defer testing.allocator.free(result); try testing.expectEqualStrings(expected_output, result); } @@ -2554,3 +2563,124 @@ pub const fmtAsUtf8Lossy = std.unicode.fmtUtf8; /// a lossy conversion if the path contains any unpaired surrogates. /// Unpaired surrogates are replaced by the replacement character (U+FFFD). pub const fmtWtf16LeAsUtf8Lossy = std.unicode.fmtUtf16Le; + +/// Similar to `RTL_PATH_TYPE`, but without the `UNKNOWN` path type. +pub const Win32PathType = enum { + /// `\\server\share\foo` + unc_absolute, + /// `C:\foo` + drive_absolute, + /// `C:foo` + drive_relative, + /// `\foo` + rooted, + /// `foo` + relative, + /// `\\.\foo`, `\\?\foo` + local_device, + /// `\\.`, `\\?` + root_local_device, +}; + +/// Get the path type of a Win32 namespace path. +/// Similar to `RtlDetermineDosPathNameType_U`. +/// If `T` is `u16`, then `path` should be encoded as WTF-16LE. +pub fn getWin32PathType(comptime T: type, path: []const T) Win32PathType { + if (path.len < 1) return .relative; + + const windows_path = std.fs.path.PathType.windows; + if (windows_path.isSep(T, path[0])) { + // \x + if (path.len < 2 or !windows_path.isSep(T, path[1])) return .rooted; + // \\. or \\? + if (path.len > 2 and (path[2] == mem.nativeToLittle(T, '.') or path[2] == mem.nativeToLittle(T, '?'))) { + // exactly \\. or \\? with nothing trailing + if (path.len == 3) return .root_local_device; + // \\.\x or \\?\x + if (windows_path.isSep(T, path[3])) return .local_device; + } + // \\x + return .unc_absolute; + } else { + // Some choice has to be made about how non-ASCII code points as drive-letters are handled, since + // path[0] is a different size for WTF-16 vs WTF-8, leading to a potential mismatch in classification + // for a WTF-8 path and its WTF-16 equivalent. For example, `€:\` encoded in WTF-16 is three code + // units `<0x20AC>:\` whereas `€:\` encoded as WTF-8 is 6 code units `<0xE2><0x82><0xAC>:\` so + // checking path[0], path[1] and path[2] would not behave the same between WTF-8/WTF-16. + // + // `RtlDetermineDosPathNameType_U` exclusively deals with WTF-16 and considers + // `€:\` a drive-absolute path, but code points that take two WTF-16 code units to encode get + // classified as a relative path (e.g. with U+20000 as the drive-letter that'd be encoded + // in WTF-16 as `<0xD840><0xDC00>:\` and be considered a relative path). + // + // The choice made here is to emulate the behavior of `RtlDetermineDosPathNameType_U` for both + // WTF-16 and WTF-8. This is because, while unlikely and not supported by the Disk Manager GUI, + // drive letters are not actually restricted to A-Z. Using `SetVolumeMountPointW` will allow you + // to set any byte value as a drive letter, and going through `IOCTL_MOUNTMGR_CREATE_POINT` will + // allow you to set any WTF-16 code unit as a drive letter. + // + // Non-A-Z drive letters don't interact well with most of Windows, but certain things do work, e.g. + // `cd /D €:\` will work, filesystem functions still work, etc. + // + // The unfortunate part of this is that this makes handling WTF-8 more complicated as we can't + // just check path[0], path[1], path[2]. + const colon_i: usize = switch (T) { + u8 => i: { + const code_point_len = std.unicode.utf8ByteSequenceLength(path[0]) catch return .relative; + // Conveniently, 4-byte sequences in WTF-8 have the same starting code point + // as 2-code-unit sequences in WTF-16. + if (code_point_len > 3) return .relative; + break :i code_point_len; + }, + u16 => 1, + else => @compileError("unsupported type: " ++ @typeName(T)), + }; + // x + if (path.len < colon_i + 1 or path[colon_i] != mem.nativeToLittle(T, ':')) return .relative; + // x:\ + if (path.len > colon_i + 1 and windows_path.isSep(T, path[colon_i + 1])) return .drive_absolute; + // x: + return .drive_relative; + } +} + +test getWin32PathType { + try std.testing.expectEqual(.relative, getWin32PathType(u8, "")); + try std.testing.expectEqual(.relative, getWin32PathType(u8, "x")); + try std.testing.expectEqual(.relative, getWin32PathType(u8, "x\\")); + + try std.testing.expectEqual(.root_local_device, getWin32PathType(u8, "//.")); + try std.testing.expectEqual(.root_local_device, getWin32PathType(u8, "/\\?")); + try std.testing.expectEqual(.root_local_device, getWin32PathType(u8, "\\\\?")); + + try std.testing.expectEqual(.local_device, getWin32PathType(u8, "//./x")); + try std.testing.expectEqual(.local_device, getWin32PathType(u8, "/\\?\\x")); + try std.testing.expectEqual(.local_device, getWin32PathType(u8, "\\\\?\\x")); + // local device paths require a path separator after the root, otherwise it is considered a UNC path + try std.testing.expectEqual(.unc_absolute, getWin32PathType(u8, "\\\\?x")); + try std.testing.expectEqual(.unc_absolute, getWin32PathType(u8, "//.x")); + + try std.testing.expectEqual(.unc_absolute, getWin32PathType(u8, "//")); + try std.testing.expectEqual(.unc_absolute, getWin32PathType(u8, "\\\\x")); + try std.testing.expectEqual(.unc_absolute, getWin32PathType(u8, "//x")); + + try std.testing.expectEqual(.rooted, getWin32PathType(u8, "\\x")); + try std.testing.expectEqual(.rooted, getWin32PathType(u8, "/")); + + try std.testing.expectEqual(.drive_relative, getWin32PathType(u8, "x:")); + try std.testing.expectEqual(.drive_relative, getWin32PathType(u8, "x:abc")); + try std.testing.expectEqual(.drive_relative, getWin32PathType(u8, "x:a/b/c")); + + try std.testing.expectEqual(.drive_absolute, getWin32PathType(u8, "x:\\")); + try std.testing.expectEqual(.drive_absolute, getWin32PathType(u8, "x:\\abc")); + try std.testing.expectEqual(.drive_absolute, getWin32PathType(u8, "x:/a/b/c")); + + // Non-ASCII code point that is encoded as one WTF-16 code unit is considered a valid drive letter + try std.testing.expectEqual(.drive_absolute, getWin32PathType(u8, "€:\\")); + try std.testing.expectEqual(.drive_absolute, getWin32PathType(u16, std.unicode.wtf8ToWtf16LeStringLiteral("€:\\"))); + try std.testing.expectEqual(.drive_relative, getWin32PathType(u8, "€:")); + try std.testing.expectEqual(.drive_relative, getWin32PathType(u16, std.unicode.wtf8ToWtf16LeStringLiteral("€:"))); + // But code points that are encoded as two WTF-16 code units are not + try std.testing.expectEqual(.relative, getWin32PathType(u8, "\u{10000}:\\")); + try std.testing.expectEqual(.relative, getWin32PathType(u16, std.unicode.wtf8ToWtf16LeStringLiteral("\u{10000}:\\"))); +} diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig index 05e5de5f22d3..63c51e6ed5b7 100644 --- a/lib/std/fs/test.zig +++ b/lib/std/fs/test.zig @@ -3,66 +3,89 @@ const native_os = builtin.os.tag; const std = @import("../std.zig"); const Io = std.Io; -const testing = std.testing; -const fs = std.fs; const mem = std.mem; +const Allocator = std.mem.Allocator; const wasi = std.os.wasi; const windows = std.os.windows; -const posix = std.posix; - const ArenaAllocator = std.heap.ArenaAllocator; -const Dir = std.fs.Dir; -const File = std.fs.File; -const tmpDir = testing.tmpDir; -const SymLinkFlags = std.fs.Dir.SymLinkFlags; +const Dir = std.Io.Dir; +const File = std.Io.File; +const SymLinkFlags = std.Io.Dir.SymLinkFlags; + +const testing = std.testing; +const expect = std.testing.expect; +const expectEqual = std.testing.expectEqual; +const expectEqualSlices = std.testing.expectEqualSlices; +const expectEqualStrings = std.testing.expectEqualStrings; +const expectError = std.testing.expectError; +const tmpDir = std.testing.tmpDir; const PathType = enum { relative, absolute, unc, - pub fn isSupported(self: PathType, target_os: std.Target.Os) bool { + fn isSupported(self: PathType, target_os: std.Target.Os) bool { return switch (self) { .relative => true, - .absolute => std.os.isGetFdPathSupportedOnTarget(target_os), + .absolute => switch (target_os.tag) { + .windows, + .driverkit, + .ios, + .maccatalyst, + .macos, + .tvos, + .visionos, + .watchos, + .linux, + .illumos, + .freebsd, + .serenity, + => true, + + .dragonfly => target_os.version_range.semver.max.order(.{ .major = 6, .minor = 0, .patch = 0 }) != .lt, + .netbsd => target_os.version_range.semver.max.order(.{ .major = 10, .minor = 0, .patch = 0 }) != .lt, + else => false, + }, .unc => target_os.tag == .windows, }; } - pub const TransformError = posix.RealPathError || error{OutOfMemory}; - pub const TransformFn = fn (allocator: mem.Allocator, dir: Dir, relative_path: [:0]const u8) TransformError![:0]const u8; + const TransformError = Dir.RealPathError || error{OutOfMemory}; + const TransformFn = fn (Allocator, Io, Dir, relative_path: [:0]const u8) TransformError![:0]const u8; - pub fn getTransformFn(comptime path_type: PathType) TransformFn { + fn getTransformFn(comptime path_type: PathType) TransformFn { switch (path_type) { .relative => return struct { - fn transform(allocator: mem.Allocator, dir: Dir, relative_path: [:0]const u8) TransformError![:0]const u8 { + fn transform(allocator: Allocator, io: Io, dir: Dir, relative_path: [:0]const u8) TransformError![:0]const u8 { _ = allocator; + _ = io; _ = dir; return relative_path; } }.transform, .absolute => return struct { - fn transform(allocator: mem.Allocator, dir: Dir, relative_path: [:0]const u8) TransformError![:0]const u8 { + fn transform(allocator: Allocator, io: Io, dir: Dir, relative_path: [:0]const u8) TransformError![:0]const u8 { // The final path may not actually exist which would cause realpath to fail. // So instead, we get the path of the dir and join it with the relative path. - var fd_path_buf: [fs.max_path_bytes]u8 = undefined; - const dir_path = try std.os.getFdPath(dir.fd, &fd_path_buf); - return fs.path.joinZ(allocator, &.{ dir_path, relative_path }); + var fd_path_buf: [Dir.max_path_bytes]u8 = undefined; + const dir_path = fd_path_buf[0..try dir.realPath(io, &fd_path_buf)]; + return Dir.path.joinZ(allocator, &.{ dir_path, relative_path }); } }.transform, .unc => return struct { - fn transform(allocator: mem.Allocator, dir: Dir, relative_path: [:0]const u8) TransformError![:0]const u8 { + fn transform(allocator: Allocator, io: Io, dir: Dir, relative_path: [:0]const u8) TransformError![:0]const u8 { // Any drive absolute path (C:\foo) can be converted into a UNC path by // using '127.0.0.1' as the server name and '$' as the share name. - var fd_path_buf: [fs.max_path_bytes]u8 = undefined; - const dir_path = try std.os.getFdPath(dir.fd, &fd_path_buf); - const windows_path_type = windows.getWin32PathType(u8, dir_path); + var fd_path_buf: [Dir.max_path_bytes]u8 = undefined; + const dir_path = fd_path_buf[0..try dir.realPath(io, &fd_path_buf)]; + const windows_path_type = Dir.path.getWin32PathType(u8, dir_path); switch (windows_path_type) { - .unc_absolute => return fs.path.joinZ(allocator, &.{ dir_path, relative_path }), + .unc_absolute => return Dir.path.joinZ(allocator, &.{ dir_path, relative_path }), .drive_absolute => { // `C:\<...>` -> `\\127.0.0.1\C$\<...>` const prepended = "\\\\127.0.0.1\\"; - var path = try fs.path.joinZ(allocator, &.{ prepended, dir_path, relative_path }); + var path = try Dir.path.joinZ(allocator, &.{ prepended, dir_path, relative_path }); path[prepended.len + 1] = '$'; return path; }, @@ -80,10 +103,10 @@ const TestContext = struct { path_sep: u8, arena: ArenaAllocator, tmp: testing.TmpDir, - dir: std.fs.Dir, + dir: Dir, transform_fn: *const PathType.TransformFn, - pub fn init(path_type: PathType, path_sep: u8, allocator: mem.Allocator, transform_fn: *const PathType.TransformFn) TestContext { + pub fn init(path_type: PathType, path_sep: u8, allocator: Allocator, transform_fn: *const PathType.TransformFn) TestContext { const tmp = tmpDir(.{ .iterate = true }); return .{ .io = testing.io, @@ -107,7 +130,7 @@ const TestContext = struct { /// `TestContext.deinit`. pub fn transformPath(self: *TestContext, relative_path: [:0]const u8) ![:0]const u8 { const allocator = self.arena.allocator(); - const transformed_path = try self.transform_fn(allocator, self.dir, relative_path); + const transformed_path = try self.transform_fn(allocator, self.io, self.dir, relative_path); if (native_os == .windows) { const transformed_sep_path = try allocator.dupeZ(u8, transformed_path); std.mem.replaceScalar(u8, transformed_sep_path, switch (self.path_sep) { @@ -150,7 +173,7 @@ fn testWithAllSupportedPathTypes(test_func: anytype) !void { fn testWithPathTypeIfSupported(comptime path_type: PathType, comptime path_sep: u8, test_func: anytype) !void { if (!(comptime path_type.isSupported(builtin.os))) return; - if (!(comptime fs.path.isSep(path_sep))) return; + if (!(comptime Dir.path.isSep(path_sep))) return; var ctx = TestContext.init(path_type, path_sep, testing.allocator, path_type.getTransformFn()); defer ctx.deinit(); @@ -160,8 +183,8 @@ fn testWithPathTypeIfSupported(comptime path_type: PathType, comptime path_sep: // For use in test setup. If the symlink creation fails on Windows with // AccessDenied, then make the test failure silent (it is not a Zig failure). -fn setupSymlink(dir: Dir, target: []const u8, link: []const u8, flags: SymLinkFlags) !void { - return dir.symLink(target, link, flags) catch |err| switch (err) { +fn setupSymlink(io: Io, dir: Dir, target: []const u8, link: []const u8, flags: SymLinkFlags) !void { + return dir.symLink(io, target, link, flags) catch |err| switch (err) { // Symlink requires admin privileges on windows, so this test can legitimately fail. error.AccessDenied => if (native_os == .windows) return error.SkipZigTest else return err, else => return err, @@ -170,80 +193,83 @@ fn setupSymlink(dir: Dir, target: []const u8, link: []const u8, flags: SymLinkFl // For use in test setup. If the symlink creation fails on Windows with // AccessDenied, then make the test failure silent (it is not a Zig failure). -fn setupSymlinkAbsolute(target: []const u8, link: []const u8, flags: SymLinkFlags) !void { - return fs.symLinkAbsolute(target, link, flags) catch |err| switch (err) { +fn setupSymlinkAbsolute(io: Io, target: []const u8, link: []const u8, flags: SymLinkFlags) !void { + return Dir.symLinkAbsolute(io, target, link, flags) catch |err| switch (err) { error.AccessDenied => if (native_os == .windows) return error.SkipZigTest else return err, else => return err, }; } test "Dir.readLink" { + const io = testing.io; + try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { // Create some targets const file_target_path = try ctx.transformPath("file.txt"); - try ctx.dir.writeFile(.{ .sub_path = file_target_path, .data = "nonsense" }); + try ctx.dir.writeFile(io, .{ .sub_path = file_target_path, .data = "nonsense" }); const dir_target_path = try ctx.transformPath("subdir"); - try ctx.dir.makeDir(dir_target_path); + try ctx.dir.createDir(io, dir_target_path, .default_dir); // On Windows, symlink targets always use the canonical path separator const canonical_file_target_path = try ctx.toCanonicalPathSep(file_target_path); const canonical_dir_target_path = try ctx.toCanonicalPathSep(dir_target_path); // test 1: symlink to a file - try setupSymlink(ctx.dir, file_target_path, "symlink1", .{}); - try testReadLink(ctx.dir, canonical_file_target_path, "symlink1"); - if (builtin.os.tag == .windows) { - try testReadLinkW(testing.allocator, ctx.dir, canonical_file_target_path, "symlink1"); - } + try setupSymlink(io, ctx.dir, file_target_path, "symlink1", .{}); + try testReadLink(io, ctx.dir, canonical_file_target_path, "symlink1"); // test 2: symlink to a directory (can be different on Windows) - try setupSymlink(ctx.dir, dir_target_path, "symlink2", .{ .is_directory = true }); - try testReadLink(ctx.dir, canonical_dir_target_path, "symlink2"); - if (builtin.os.tag == .windows) { - try testReadLinkW(testing.allocator, ctx.dir, canonical_dir_target_path, "symlink2"); - } + try setupSymlink(io, ctx.dir, dir_target_path, "symlink2", .{ .is_directory = true }); + try testReadLink(io, ctx.dir, canonical_dir_target_path, "symlink2"); // test 3: relative path symlink - const parent_file = ".." ++ fs.path.sep_str ++ "target.txt"; + const parent_file = ".." ++ Dir.path.sep_str ++ "target.txt"; const canonical_parent_file = try ctx.toCanonicalPathSep(parent_file); - var subdir = try ctx.dir.makeOpenPath("subdir", .{}); - defer subdir.close(); - try setupSymlink(subdir, canonical_parent_file, "relative-link.txt", .{}); - try testReadLink(subdir, canonical_parent_file, "relative-link.txt"); - if (builtin.os.tag == .windows) { - try testReadLinkW(testing.allocator, subdir, canonical_parent_file, "relative-link.txt"); - } + var subdir = try ctx.dir.createDirPathOpen(io, "subdir", .{}); + defer subdir.close(io); + try setupSymlink(io, subdir, canonical_parent_file, "relative-link.txt", .{}); + try testReadLink(io, subdir, canonical_parent_file, "relative-link.txt"); } }.impl); } -fn testReadLink(dir: Dir, target_path: []const u8, symlink_path: []const u8) !void { - var buffer: [fs.max_path_bytes]u8 = undefined; - const actual = try dir.readLink(symlink_path, buffer[0..]); - try testing.expectEqualStrings(target_path, actual); +test "Dir.readLink on non-symlinks" { + try testWithAllSupportedPathTypes(struct { + fn impl(ctx: *TestContext) !void { + const io = ctx.io; + const file_path = try ctx.transformPath("file.txt"); + try ctx.dir.writeFile(io, .{ .sub_path = file_path, .data = "nonsense" }); + const dir_path = try ctx.transformPath("subdir"); + try ctx.dir.createDir(io, dir_path, .default_dir); + + // file + var buffer: [Dir.max_path_bytes]u8 = undefined; + try std.testing.expectError(error.NotLink, ctx.dir.readLink(io, file_path, &buffer)); + + // dir + try std.testing.expectError(error.NotLink, ctx.dir.readLink(io, dir_path, &buffer)); + } + }.impl); } -fn testReadLinkW(allocator: mem.Allocator, dir: Dir, target_path: []const u8, symlink_path: []const u8) !void { - const target_path_w = try std.unicode.wtf8ToWtf16LeAlloc(allocator, target_path); - defer allocator.free(target_path_w); - // Calling the W functions directly requires the path to be NT-prefixed - const symlink_path_w = try std.os.windows.sliceToPrefixedFileW(dir.fd, symlink_path); - const wtf16_buffer = try allocator.alloc(u16, target_path_w.len); - defer allocator.free(wtf16_buffer); - const actual = try dir.readLinkW(symlink_path_w.span(), wtf16_buffer); - try testing.expectEqualSlices(u16, target_path_w, actual); +fn testReadLink(io: Io, dir: Dir, target_path: []const u8, symlink_path: []const u8) !void { + var buffer: [Dir.max_path_bytes]u8 = undefined; + const actual = buffer[0..try dir.readLink(io, symlink_path, &buffer)]; + try expectEqualStrings(target_path, actual); } -fn testReadLinkAbsolute(target_path: []const u8, symlink_path: []const u8) !void { - var buffer: [fs.max_path_bytes]u8 = undefined; - const given = try fs.readLinkAbsolute(symlink_path, buffer[0..]); - try testing.expectEqualStrings(target_path, given); +fn testReadLinkAbsolute(io: Io, target_path: []const u8, symlink_path: []const u8) !void { + var buffer: [Dir.max_path_bytes]u8 = undefined; + const given = buffer[0..try Dir.readLinkAbsolute(io, symlink_path, &buffer)]; + try expectEqualStrings(target_path, given); } test "File.stat on a File that is a symlink returns Kind.sym_link" { - // This test requires getting a file descriptor of a symlink which - // is not possible on all targets + const io = testing.io; + + // This test requires getting a file descriptor of a symlink which is not + // possible on all targets. switch (builtin.target.os.tag) { .windows, .linux => {}, else => return error.SkipZigTest, @@ -252,87 +278,35 @@ test "File.stat on a File that is a symlink returns Kind.sym_link" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { const dir_target_path = try ctx.transformPath("subdir"); - try ctx.dir.makeDir(dir_target_path); - - try setupSymlink(ctx.dir, dir_target_path, "symlink", .{ .is_directory = true }); - - var symlink = switch (builtin.target.os.tag) { - .windows => windows_symlink: { - const sub_path_w = try windows.cStrToPrefixedFileW(ctx.dir.fd, "symlink"); - - var result = Dir{ - .fd = undefined, - }; - - const path_len_bytes = @as(u16, @intCast(sub_path_w.span().len * 2)); - var nt_name = windows.UNICODE_STRING{ - .Length = path_len_bytes, - .MaximumLength = path_len_bytes, - .Buffer = @constCast(&sub_path_w.data), - }; - var attr = windows.OBJECT_ATTRIBUTES{ - .Length = @sizeOf(windows.OBJECT_ATTRIBUTES), - .RootDirectory = if (fs.path.isAbsoluteWindowsW(sub_path_w.span())) null else ctx.dir.fd, - .Attributes = 0, - .ObjectName = &nt_name, - .SecurityDescriptor = null, - .SecurityQualityOfService = null, - }; - var io: windows.IO_STATUS_BLOCK = undefined; - const rc = windows.ntdll.NtCreateFile( - &result.fd, - windows.STANDARD_RIGHTS_READ | windows.FILE_READ_ATTRIBUTES | windows.FILE_READ_EA | windows.SYNCHRONIZE | windows.FILE_TRAVERSE, - &attr, - &io, - null, - windows.FILE_ATTRIBUTE_NORMAL, - windows.FILE_SHARE_READ | windows.FILE_SHARE_WRITE | windows.FILE_SHARE_DELETE, - windows.FILE_OPEN, - // FILE_OPEN_REPARSE_POINT is the important thing here - windows.FILE_OPEN_REPARSE_POINT | windows.FILE_DIRECTORY_FILE | windows.FILE_SYNCHRONOUS_IO_NONALERT | windows.FILE_OPEN_FOR_BACKUP_INTENT, - null, - 0, - ); - - switch (rc) { - .SUCCESS => break :windows_symlink result, - else => return windows.unexpectedStatus(rc), - } - }, - .linux => linux_symlink: { - const sub_path_c = try posix.toPosixPath("symlink"); - // the O_NOFOLLOW | O_PATH combination can obtain a fd to a symlink - // note that if O_DIRECTORY is set, then this will error with ENOTDIR - const flags: posix.O = .{ - .NOFOLLOW = true, - .PATH = true, - .ACCMODE = .RDONLY, - .CLOEXEC = true, - }; - const fd = try posix.openatZ(ctx.dir.fd, &sub_path_c, flags, 0); - break :linux_symlink Dir{ .fd = fd }; - }, - else => unreachable, - }; - defer symlink.close(); + try ctx.dir.createDir(io, dir_target_path, .default_dir); + + try setupSymlink(io, ctx.dir, dir_target_path, "symlink", .{ .is_directory = true }); + + var symlink: File = try ctx.dir.openFile(io, "symlink", .{ + .follow_symlinks = false, + .path_only = true, + }); + defer symlink.close(io); - const stat = try symlink.stat(); - try testing.expectEqual(File.Kind.sym_link, stat.kind); + const stat = try symlink.stat(io); + try expectEqual(File.Kind.sym_link, stat.kind); } }.impl); } test "openDir" { + const io = testing.io; + try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { const allocator = ctx.arena.allocator(); const subdir_path = try ctx.transformPath("subdir"); - try ctx.dir.makeDir(subdir_path); + try ctx.dir.createDir(io, subdir_path, .default_dir); for ([_][]const u8{ "", ".", ".." }) |sub_path| { - const dir_path = try fs.path.join(allocator, &.{ subdir_path, sub_path }); - var dir = try ctx.dir.openDir(dir_path, .{}); - defer dir.close(); + const dir_path = try Dir.path.join(allocator, &.{ subdir_path, sub_path }); + var dir = try ctx.dir.openDir(io, dir_path, .{}); + defer dir.close(io); } } }.impl); @@ -340,79 +314,89 @@ test "openDir" { test "accessAbsolute" { if (native_os == .wasi) return error.SkipZigTest; + if (native_os == .openbsd) return error.SkipZigTest; + + const io = testing.io; + const gpa = testing.allocator; var tmp = tmpDir(.{}); defer tmp.cleanup(); - const base_path = try tmp.dir.realpathAlloc(testing.allocator, "."); - defer testing.allocator.free(base_path); + const base_path = try tmp.dir.realPathFileAlloc(io, ".", gpa); + defer gpa.free(base_path); - try fs.accessAbsolute(base_path, .{}); + try Dir.accessAbsolute(io, base_path, .{}); } test "openDirAbsolute" { if (native_os == .wasi) return error.SkipZigTest; + if (native_os == .openbsd) return error.SkipZigTest; + + const io = testing.io; + const gpa = testing.allocator; var tmp = tmpDir(.{}); defer tmp.cleanup(); - const tmp_ino = (try tmp.dir.stat()).inode; + const tmp_ino = (try tmp.dir.stat(io)).inode; - try tmp.dir.makeDir("subdir"); - const sub_path = try tmp.dir.realpathAlloc(testing.allocator, "subdir"); - defer testing.allocator.free(sub_path); + try tmp.dir.createDir(io, "subdir", .default_dir); + const sub_path = try tmp.dir.realPathFileAlloc(io, "subdir", gpa); + defer gpa.free(sub_path); // Can open sub_path - var tmp_sub = try fs.openDirAbsolute(sub_path, .{}); - defer tmp_sub.close(); + var tmp_sub = try Dir.openDirAbsolute(io, sub_path, .{}); + defer tmp_sub.close(io); - const sub_ino = (try tmp_sub.stat()).inode; + const sub_ino = (try tmp_sub.stat(io)).inode; { // Can open sub_path + ".." - const dir_path = try fs.path.join(testing.allocator, &.{ sub_path, ".." }); + const dir_path = try Dir.path.join(testing.allocator, &.{ sub_path, ".." }); defer testing.allocator.free(dir_path); - var dir = try fs.openDirAbsolute(dir_path, .{}); - defer dir.close(); + var dir = try Dir.openDirAbsolute(io, dir_path, .{}); + defer dir.close(io); - const ino = (try dir.stat()).inode; - try testing.expectEqual(tmp_ino, ino); + const ino = (try dir.stat(io)).inode; + try expectEqual(tmp_ino, ino); } { // Can open sub_path + "." - const dir_path = try fs.path.join(testing.allocator, &.{ sub_path, "." }); + const dir_path = try Dir.path.join(testing.allocator, &.{ sub_path, "." }); defer testing.allocator.free(dir_path); - var dir = try fs.openDirAbsolute(dir_path, .{}); - defer dir.close(); + var dir = try Dir.openDirAbsolute(io, dir_path, .{}); + defer dir.close(io); - const ino = (try dir.stat()).inode; - try testing.expectEqual(sub_ino, ino); + const ino = (try dir.stat(io)).inode; + try expectEqual(sub_ino, ino); } { // Can open subdir + "..", with some extra "." - const dir_path = try fs.path.join(testing.allocator, &.{ sub_path, ".", "..", "." }); + const dir_path = try Dir.path.join(testing.allocator, &.{ sub_path, ".", "..", "." }); defer testing.allocator.free(dir_path); - var dir = try fs.openDirAbsolute(dir_path, .{}); - defer dir.close(); + var dir = try Dir.openDirAbsolute(io, dir_path, .{}); + defer dir.close(io); - const ino = (try dir.stat()).inode; - try testing.expectEqual(tmp_ino, ino); + const ino = (try dir.stat(io)).inode; + try expectEqual(tmp_ino, ino); } } test "openDir cwd parent '..'" { - var dir = fs.cwd().openDir("..", .{}) catch |err| { + const io = testing.io; + + var dir = Dir.cwd().openDir(io, "..", .{}) catch |err| { if (native_os == .wasi and err == error.PermissionDenied) { return; // This is okay. WASI disallows escaping from the fs sandbox } return err; }; - defer dir.close(); + defer dir.close(io); } test "openDir non-cwd parent '..'" { @@ -421,68 +405,76 @@ test "openDir non-cwd parent '..'" { else => {}, } + const io = testing.io; + const gpa = testing.allocator; + var tmp = tmpDir(.{}); defer tmp.cleanup(); - var subdir = try tmp.dir.makeOpenPath("subdir", .{}); - defer subdir.close(); + var subdir = try tmp.dir.createDirPathOpen(io, "subdir", .{}); + defer subdir.close(io); - var dir = try subdir.openDir("..", .{}); - defer dir.close(); + var dir = try subdir.openDir(io, "..", .{}); + defer dir.close(io); - const expected_path = try tmp.dir.realpathAlloc(testing.allocator, "."); - defer testing.allocator.free(expected_path); + const expected_path = try tmp.dir.realPathFileAlloc(io, ".", gpa); + defer gpa.free(expected_path); - const actual_path = try dir.realpathAlloc(testing.allocator, "."); - defer testing.allocator.free(actual_path); + const actual_path = try dir.realPathFileAlloc(io, ".", gpa); + defer gpa.free(actual_path); - try testing.expectEqualStrings(expected_path, actual_path); + try expectEqualStrings(expected_path, actual_path); } test "readLinkAbsolute" { if (native_os == .wasi) return error.SkipZigTest; + if (native_os == .openbsd) return error.SkipZigTest; + + const io = testing.io; var tmp = tmpDir(.{}); defer tmp.cleanup(); // Create some targets - try tmp.dir.writeFile(.{ .sub_path = "file.txt", .data = "nonsense" }); - try tmp.dir.makeDir("subdir"); + try tmp.dir.writeFile(io, .{ .sub_path = "file.txt", .data = "nonsense" }); + try tmp.dir.createDir(io, "subdir", .default_dir); // Get base abs path - var arena = ArenaAllocator.init(testing.allocator); - defer arena.deinit(); - const allocator = arena.allocator(); + var arena_allocator = ArenaAllocator.init(testing.allocator); + defer arena_allocator.deinit(); + const arena = arena_allocator.allocator(); - const base_path = try tmp.dir.realpathAlloc(allocator, "."); + const base_path = try tmp.dir.realPathFileAlloc(io, ".", arena); { - const target_path = try fs.path.join(allocator, &.{ base_path, "file.txt" }); - const symlink_path = try fs.path.join(allocator, &.{ base_path, "symlink1" }); + const target_path = try Dir.path.join(arena, &.{ base_path, "file.txt" }); + const symlink_path = try Dir.path.join(arena, &.{ base_path, "symlink1" }); // Create symbolic link by path - try setupSymlinkAbsolute(target_path, symlink_path, .{}); - try testReadLinkAbsolute(target_path, symlink_path); + try setupSymlinkAbsolute(io, target_path, symlink_path, .{}); + try testReadLinkAbsolute(io, target_path, symlink_path); } { - const target_path = try fs.path.join(allocator, &.{ base_path, "subdir" }); - const symlink_path = try fs.path.join(allocator, &.{ base_path, "symlink2" }); + const target_path = try Dir.path.join(arena, &.{ base_path, "subdir" }); + const symlink_path = try Dir.path.join(arena, &.{ base_path, "symlink2" }); // Create symbolic link to a directory by path - try setupSymlinkAbsolute(target_path, symlink_path, .{ .is_directory = true }); - try testReadLinkAbsolute(target_path, symlink_path); + try setupSymlinkAbsolute(io, target_path, symlink_path, .{ .is_directory = true }); + try testReadLinkAbsolute(io, target_path, symlink_path); } } test "Dir.Iterator" { + const io = testing.io; + var tmp_dir = tmpDir(.{ .iterate = true }); defer tmp_dir.cleanup(); // First, create a couple of entries to iterate over. - const file = try tmp_dir.dir.createFile("some_file", .{}); - file.close(); + const file = try tmp_dir.dir.createFile(io, "some_file", .{}); + file.close(io); - try tmp_dir.dir.makeDir("some_dir"); + try tmp_dir.dir.createDir(io, "some_dir", .default_dir); var arena = ArenaAllocator.init(testing.allocator); defer arena.deinit(); @@ -492,19 +484,21 @@ test "Dir.Iterator" { // Create iterator. var iter = tmp_dir.dir.iterate(); - while (try iter.next()) |entry| { + while (try iter.next(io)) |entry| { // We cannot just store `entry` as on Windows, we're re-using the name buffer // which means we'll actually share the `name` pointer between entries! const name = try allocator.dupe(u8, entry.name); - try entries.append(Dir.Entry{ .name = name, .kind = entry.kind }); + try entries.append(Dir.Entry{ .name = name, .kind = entry.kind, .inode = 0 }); } - try testing.expectEqual(@as(usize, 2), entries.items.len); // note that the Iterator skips '.' and '..' - try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .file })); - try testing.expect(contains(&entries, .{ .name = "some_dir", .kind = .directory })); + try expectEqual(@as(usize, 2), entries.items.len); // note that the Iterator skips '.' and '..' + try expect(contains(&entries, .{ .name = "some_file", .kind = .file, .inode = 0 })); + try expect(contains(&entries, .{ .name = "some_dir", .kind = .directory, .inode = 0 })); } test "Dir.Iterator many entries" { + const io = testing.io; + var tmp_dir = tmpDir(.{ .iterate = true }); defer tmp_dir.cleanup(); @@ -513,8 +507,8 @@ test "Dir.Iterator many entries" { var buf: [4]u8 = undefined; // Enough to store "1024". while (i < num) : (i += 1) { const name = try std.fmt.bufPrint(&buf, "{}", .{i}); - const file = try tmp_dir.dir.createFile(name, .{}); - file.close(); + const file = try tmp_dir.dir.createFile(io, name, .{}); + file.close(io); } var arena = ArenaAllocator.init(testing.allocator); @@ -525,29 +519,31 @@ test "Dir.Iterator many entries" { // Create iterator. var iter = tmp_dir.dir.iterate(); - while (try iter.next()) |entry| { + while (try iter.next(io)) |entry| { // We cannot just store `entry` as on Windows, we're re-using the name buffer // which means we'll actually share the `name` pointer between entries! const name = try allocator.dupe(u8, entry.name); - try entries.append(.{ .name = name, .kind = entry.kind }); + try entries.append(.{ .name = name, .kind = entry.kind, .inode = 0 }); } i = 0; while (i < num) : (i += 1) { const name = try std.fmt.bufPrint(&buf, "{}", .{i}); - try testing.expect(contains(&entries, .{ .name = name, .kind = .file })); + try expect(contains(&entries, .{ .name = name, .kind = .file, .inode = 0 })); } } test "Dir.Iterator twice" { + const io = testing.io; + var tmp_dir = tmpDir(.{ .iterate = true }); defer tmp_dir.cleanup(); // First, create a couple of entries to iterate over. - const file = try tmp_dir.dir.createFile("some_file", .{}); - file.close(); + const file = try tmp_dir.dir.createFile(io, "some_file", .{}); + file.close(io); - try tmp_dir.dir.makeDir("some_dir"); + try tmp_dir.dir.createDir(io, "some_dir", .default_dir); var arena = ArenaAllocator.init(testing.allocator); defer arena.deinit(); @@ -559,28 +555,30 @@ test "Dir.Iterator twice" { // Create iterator. var iter = tmp_dir.dir.iterate(); - while (try iter.next()) |entry| { + while (try iter.next(io)) |entry| { // We cannot just store `entry` as on Windows, we're re-using the name buffer // which means we'll actually share the `name` pointer between entries! const name = try allocator.dupe(u8, entry.name); - try entries.append(Dir.Entry{ .name = name, .kind = entry.kind }); + try entries.append(Dir.Entry{ .name = name, .kind = entry.kind, .inode = 0 }); } - try testing.expectEqual(@as(usize, 2), entries.items.len); // note that the Iterator skips '.' and '..' - try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .file })); - try testing.expect(contains(&entries, .{ .name = "some_dir", .kind = .directory })); + try expectEqual(@as(usize, 2), entries.items.len); // note that the Iterator skips '.' and '..' + try expect(contains(&entries, .{ .name = "some_file", .kind = .file, .inode = 0 })); + try expect(contains(&entries, .{ .name = "some_dir", .kind = .directory, .inode = 0 })); } } test "Dir.Iterator reset" { + const io = testing.io; + var tmp_dir = tmpDir(.{ .iterate = true }); defer tmp_dir.cleanup(); // First, create a couple of entries to iterate over. - const file = try tmp_dir.dir.createFile("some_file", .{}); - file.close(); + const file = try tmp_dir.dir.createFile(io, "some_file", .{}); + file.close(io); - try tmp_dir.dir.makeDir("some_dir"); + try tmp_dir.dir.createDir(io, "some_dir", .default_dir); var arena = ArenaAllocator.init(testing.allocator); defer arena.deinit(); @@ -593,48 +591,45 @@ test "Dir.Iterator reset" { while (i < 2) : (i += 1) { var entries = std.array_list.Managed(Dir.Entry).init(allocator); - while (try iter.next()) |entry| { + while (try iter.next(io)) |entry| { // We cannot just store `entry` as on Windows, we're re-using the name buffer // which means we'll actually share the `name` pointer between entries! const name = try allocator.dupe(u8, entry.name); - try entries.append(.{ .name = name, .kind = entry.kind }); + try entries.append(.{ .name = name, .kind = entry.kind, .inode = 0 }); } - try testing.expectEqual(@as(usize, 2), entries.items.len); // note that the Iterator skips '.' and '..' - try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .file })); - try testing.expect(contains(&entries, .{ .name = "some_dir", .kind = .directory })); + try expectEqual(@as(usize, 2), entries.items.len); // note that the Iterator skips '.' and '..' + try expect(contains(&entries, .{ .name = "some_file", .kind = .file, .inode = 0 })); + try expect(contains(&entries, .{ .name = "some_dir", .kind = .directory, .inode = 0 })); - iter.reset(); + iter.reader.reset(); } } test "Dir.Iterator but dir is deleted during iteration" { + const io = testing.io; + var tmp = std.testing.tmpDir(.{}); defer tmp.cleanup(); // Create directory and setup an iterator for it - var subdir = try tmp.dir.makeOpenPath("subdir", .{ .iterate = true }); - defer subdir.close(); + var subdir = try tmp.dir.createDirPathOpen(io, "subdir", .{ .open_options = .{ .iterate = true } }); + defer subdir.close(io); var iterator = subdir.iterate(); // Create something to iterate over within the subdir - try tmp.dir.makePath("subdir" ++ fs.path.sep_str ++ "b"); + try tmp.dir.createDirPath(io, "subdir" ++ Dir.path.sep_str ++ "b"); // Then, before iterating, delete the directory that we're iterating. // This is a contrived reproduction, but this could happen outside of the program, in another thread, etc. // If we get an error while trying to delete, we can skip this test (this will happen on platforms // like Windows which will give FileBusy if the directory is currently open for iteration). - tmp.dir.deleteTree("subdir") catch return error.SkipZigTest; + tmp.dir.deleteTree(io, "subdir") catch return error.SkipZigTest; // Now, when we try to iterate, the next call should return null immediately. - const entry = try iterator.next(); - try std.testing.expect(entry == null); - - // On Linux, we can opt-in to receiving a more specific error by calling `nextLinux` - if (native_os == .linux) { - try std.testing.expectError(error.DirNotFound, iterator.nextLinux()); - } + const entry = try iterator.next(io); + try testing.expect(entry == null); } fn entryEql(lhs: Dir.Entry, rhs: Dir.Entry) bool { @@ -648,112 +643,123 @@ fn contains(entries: *const std.array_list.Managed(Dir.Entry), el: Dir.Entry) bo return false; } -test "Dir.realpath smoke test" { - if (!comptime std.os.isGetFdPathSupportedOnTarget(builtin.os)) return error.SkipZigTest; +test "Dir.realPath smoke test" { + if (native_os == .wasi) return error.SkipZigTest; + if (native_os == .openbsd) return error.SkipZigTest; try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { - const allocator = ctx.arena.allocator(); + const io = ctx.io; + const arena = ctx.arena.allocator(); const test_file_path = try ctx.transformPath("test_file"); const test_dir_path = try ctx.transformPath("test_dir"); - var buf: [fs.max_path_bytes]u8 = undefined; + var buf: [Dir.max_path_bytes]u8 = undefined; // FileNotFound if the path doesn't exist - try testing.expectError(error.FileNotFound, ctx.dir.realpathAlloc(allocator, test_file_path)); - try testing.expectError(error.FileNotFound, ctx.dir.realpath(test_file_path, &buf)); - try testing.expectError(error.FileNotFound, ctx.dir.realpathAlloc(allocator, test_dir_path)); - try testing.expectError(error.FileNotFound, ctx.dir.realpath(test_dir_path, &buf)); + try expectError(error.FileNotFound, ctx.dir.realPathFileAlloc(io, test_file_path, arena)); + try expectError(error.FileNotFound, ctx.dir.realPathFile(io, test_file_path, &buf)); + try expectError(error.FileNotFound, ctx.dir.realPathFileAlloc(io, test_dir_path, arena)); + try expectError(error.FileNotFound, ctx.dir.realPathFile(io, test_dir_path, &buf)); // Now create the file and dir - try ctx.dir.writeFile(.{ .sub_path = test_file_path, .data = "" }); - try ctx.dir.makeDir(test_dir_path); + try ctx.dir.writeFile(io, .{ .sub_path = test_file_path, .data = "" }); + try ctx.dir.createDir(io, test_dir_path, .default_dir); const base_path = try ctx.transformPath("."); - const base_realpath = try ctx.dir.realpathAlloc(allocator, base_path); - const expected_file_path = try fs.path.join( - allocator, - &.{ base_realpath, "test_file" }, - ); - const expected_dir_path = try fs.path.join( - allocator, - &.{ base_realpath, "test_dir" }, - ); + const base_realpath = try ctx.dir.realPathFileAlloc(io, base_path, arena); + const expected_file_path = try Dir.path.join(arena, &.{ base_realpath, "test_file" }); + const expected_dir_path = try Dir.path.join(arena, &.{ base_realpath, "test_dir" }); // First, test non-alloc version { - const file_path = try ctx.dir.realpath(test_file_path, &buf); - try testing.expectEqualStrings(expected_file_path, file_path); + const file_path = buf[0..try ctx.dir.realPathFile(io, test_file_path, &buf)]; + try expectEqualStrings(expected_file_path, file_path); - const dir_path = try ctx.dir.realpath(test_dir_path, &buf); - try testing.expectEqualStrings(expected_dir_path, dir_path); + const dir_path = buf[0..try ctx.dir.realPathFile(io, test_dir_path, &buf)]; + try expectEqualStrings(expected_dir_path, dir_path); } // Next, test alloc version { - const file_path = try ctx.dir.realpathAlloc(allocator, test_file_path); - try testing.expectEqualStrings(expected_file_path, file_path); + const file_path = try ctx.dir.realPathFileAlloc(io, test_file_path, arena); + try expectEqualStrings(expected_file_path, file_path); - const dir_path = try ctx.dir.realpathAlloc(allocator, test_dir_path); - try testing.expectEqualStrings(expected_dir_path, dir_path); + const dir_path = try ctx.dir.realPathFileAlloc(io, test_dir_path, arena); + try expectEqualStrings(expected_dir_path, dir_path); } } }.impl); } test "readFileAlloc" { + const io = testing.io; + var tmp_dir = tmpDir(.{}); defer tmp_dir.cleanup(); - var file = try tmp_dir.dir.createFile("test_file", .{ .read = true }); - defer file.close(); + var file = try tmp_dir.dir.createFile(io, "test_file", .{ .read = true }); + defer file.close(io); - const buf1 = try tmp_dir.dir.readFileAlloc("test_file", testing.allocator, .limited(1024)); + const buf1 = try tmp_dir.dir.readFileAlloc(io, "test_file", testing.allocator, .limited(1024)); defer testing.allocator.free(buf1); - try testing.expectEqualStrings("", buf1); + try expectEqualStrings("", buf1); const write_buf: []const u8 = "this is a test.\nthis is a test.\nthis is a test.\nthis is a test.\n"; - try file.writeAll(write_buf); + try file.writeStreamingAll(io, write_buf); { // max_bytes > file_size - const buf2 = try tmp_dir.dir.readFileAlloc("test_file", testing.allocator, .limited(1024)); + const buf2 = try tmp_dir.dir.readFileAlloc(io, "test_file", testing.allocator, .limited(1024)); defer testing.allocator.free(buf2); - try testing.expectEqualStrings(write_buf, buf2); + try expectEqualStrings(write_buf, buf2); } { // max_bytes == file_size - try testing.expectError( + try expectError( error.StreamTooLong, - tmp_dir.dir.readFileAlloc("test_file", testing.allocator, .limited(write_buf.len)), + tmp_dir.dir.readFileAlloc(io, "test_file", testing.allocator, .limited(write_buf.len)), ); } { // max_bytes == file_size + 1 - const buf2 = try tmp_dir.dir.readFileAlloc("test_file", testing.allocator, .limited(write_buf.len + 1)); + const buf2 = try tmp_dir.dir.readFileAlloc(io, "test_file", testing.allocator, .limited(write_buf.len + 1)); defer testing.allocator.free(buf2); - try testing.expectEqualStrings(write_buf, buf2); + try expectEqualStrings(write_buf, buf2); } // max_bytes < file_size - try testing.expectError( + try expectError( error.StreamTooLong, - tmp_dir.dir.readFileAlloc("test_file", testing.allocator, .limited(write_buf.len - 1)), + tmp_dir.dir.readFileAlloc(io, "test_file", testing.allocator, .limited(write_buf.len - 1)), ); } test "Dir.statFile" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { - const test_file_name = try ctx.transformPath("test_file"); + const io = ctx.io; + { + const test_file_name = try ctx.transformPath("test_file"); - try testing.expectError(error.FileNotFound, ctx.dir.statFile(test_file_name)); + try expectError(error.FileNotFound, ctx.dir.statFile(io, test_file_name, .{})); - try ctx.dir.writeFile(.{ .sub_path = test_file_name, .data = "" }); + try ctx.dir.writeFile(io, .{ .sub_path = test_file_name, .data = "" }); - const stat = try ctx.dir.statFile(test_file_name); - try testing.expectEqual(File.Kind.file, stat.kind); + const stat = try ctx.dir.statFile(io, test_file_name, .{}); + try expectEqual(.file, stat.kind); + } + { + const test_dir_name = try ctx.transformPath("test_dir"); + + try expectError(error.FileNotFound, ctx.dir.statFile(io, test_dir_name, .{})); + + try ctx.dir.createDir(io, test_dir_name, .default_dir); + + const stat = try ctx.dir.statFile(io, test_dir_name, .{}); + try expectEqual(.directory, stat.kind); + } } }.impl); } @@ -761,12 +767,13 @@ test "Dir.statFile" { test "statFile on dangling symlink" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; const symlink_name = try ctx.transformPath("dangling-symlink"); - const symlink_target = "." ++ fs.path.sep_str ++ "doesnotexist"; + const symlink_target = "." ++ Dir.path.sep_str ++ "doesnotexist"; - try setupSymlink(ctx.dir, symlink_target, symlink_name, .{}); + try setupSymlink(io, ctx.dir, symlink_target, symlink_name, .{}); - try std.testing.expectError(error.FileNotFound, ctx.dir.statFile(symlink_name)); + try expectError(error.FileNotFound, ctx.dir.statFile(io, symlink_name, .{})); } }.impl); } @@ -774,25 +781,27 @@ test "statFile on dangling symlink" { test "directory operations on files" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; + const test_file_name = try ctx.transformPath("test_file"); - var file = try ctx.dir.createFile(test_file_name, .{ .read = true }); - file.close(); + var file = try ctx.dir.createFile(io, test_file_name, .{ .read = true }); + file.close(io); - try testing.expectError(error.PathAlreadyExists, ctx.dir.makeDir(test_file_name)); - try testing.expectError(error.NotDir, ctx.dir.openDir(test_file_name, .{})); - try testing.expectError(error.NotDir, ctx.dir.deleteDir(test_file_name)); + try expectError(error.PathAlreadyExists, ctx.dir.createDir(io, test_file_name, .default_dir)); + try expectError(error.NotDir, ctx.dir.openDir(io, test_file_name, .{})); + try expectError(error.NotDir, ctx.dir.deleteDir(io, test_file_name)); if (ctx.path_type == .absolute and comptime PathType.absolute.isSupported(builtin.os)) { - try testing.expectError(error.PathAlreadyExists, fs.makeDirAbsolute(test_file_name)); - try testing.expectError(error.NotDir, fs.deleteDirAbsolute(test_file_name)); + try expectError(error.PathAlreadyExists, Dir.createDirAbsolute(io, test_file_name, .default_dir)); + try expectError(error.NotDir, Dir.deleteDirAbsolute(io, test_file_name)); } // ensure the file still exists and is a file as a sanity check - file = try ctx.dir.openFile(test_file_name, .{}); - const stat = try file.stat(); - try testing.expectEqual(File.Kind.file, stat.kind); - file.close(); + file = try ctx.dir.openFile(io, test_file_name, .{}); + const stat = try file.stat(io); + try expectEqual(File.Kind.file, stat.kind); + file.close(io); } }.impl); } @@ -801,81 +810,91 @@ test "file operations on directories" { // TODO: fix this test on FreeBSD. https://github.com/ziglang/zig/issues/1759 if (native_os == .freebsd) return error.SkipZigTest; + const io = testing.io; + try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { const test_dir_name = try ctx.transformPath("test_dir"); - try ctx.dir.makeDir(test_dir_name); + try ctx.dir.createDir(io, test_dir_name, .default_dir); - try testing.expectError(error.IsDir, ctx.dir.createFile(test_dir_name, .{})); - try testing.expectError(error.IsDir, ctx.dir.deleteFile(test_dir_name)); + try expectError(error.IsDir, ctx.dir.createFile(io, test_dir_name, .{})); + try expectError(error.IsDir, ctx.dir.deleteFile(io, test_dir_name)); switch (native_os) { - .dragonfly, .netbsd => { + .netbsd => { // no error when reading a directory. See https://github.com/ziglang/zig/issues/5732 - const buf = try ctx.dir.readFileAlloc(test_dir_name, testing.allocator, .unlimited); + const buf = try ctx.dir.readFileAlloc(io, test_dir_name, testing.allocator, .unlimited); testing.allocator.free(buf); }, .wasi => { // WASI return EBADF, which gets mapped to NotOpenForReading. // See https://github.com/bytecodealliance/wasmtime/issues/1935 - try testing.expectError(error.NotOpenForReading, ctx.dir.readFileAlloc(test_dir_name, testing.allocator, .unlimited)); + try expectError(error.NotOpenForReading, ctx.dir.readFileAlloc(io, test_dir_name, testing.allocator, .unlimited)); }, else => { - try testing.expectError(error.IsDir, ctx.dir.readFileAlloc(test_dir_name, testing.allocator, .unlimited)); + try expectError(error.IsDir, ctx.dir.readFileAlloc(io, test_dir_name, testing.allocator, .unlimited)); }, } if (native_os == .wasi and builtin.link_libc) { // wasmtime unexpectedly succeeds here, see https://github.com/ziglang/zig/issues/20747 - const handle = try ctx.dir.openFile(test_dir_name, .{ .mode = .read_write }); - handle.close(); + const handle = try ctx.dir.openFile(io, test_dir_name, .{ .mode = .read_write }); + handle.close(io); } else { // Note: The `.mode = .read_write` is necessary to ensure the error occurs on all platforms. - // TODO: Add a read-only test as well, see https://github.com/ziglang/zig/issues/5732 - try testing.expectError(error.IsDir, ctx.dir.openFile(test_dir_name, .{ .mode = .read_write })); + try expectError(error.IsDir, ctx.dir.openFile(io, test_dir_name, .{ .mode = .read_write })); } + { + const handle = try ctx.dir.openFile(io, test_dir_name, .{ .allow_directory = true, .mode = .read_only }); + handle.close(io); + } + try expectError(error.IsDir, ctx.dir.openFile(io, test_dir_name, .{ .allow_directory = false, .mode = .read_only })); + if (ctx.path_type == .absolute and comptime PathType.absolute.isSupported(builtin.os)) { - try testing.expectError(error.IsDir, fs.createFileAbsolute(test_dir_name, .{})); - try testing.expectError(error.IsDir, fs.deleteFileAbsolute(test_dir_name)); + try expectError(error.IsDir, Dir.createFileAbsolute(io, test_dir_name, .{})); + try expectError(error.IsDir, Dir.deleteFileAbsolute(io, test_dir_name)); } // ensure the directory still exists as a sanity check - var dir = try ctx.dir.openDir(test_dir_name, .{}); - dir.close(); + var dir = try ctx.dir.openDir(io, test_dir_name, .{}); + dir.close(io); } }.impl); } -test "makeOpenPath parent dirs do not exist" { +test "createDirPathOpen parent dirs do not exist" { + const io = testing.io; + var tmp_dir = tmpDir(.{}); defer tmp_dir.cleanup(); - var dir = try tmp_dir.dir.makeOpenPath("root_dir/parent_dir/some_dir", .{}); - dir.close(); + var dir = try tmp_dir.dir.createDirPathOpen(io, "root_dir/parent_dir/some_dir", .{}); + dir.close(io); // double check that the full directory structure was created - var dir_verification = try tmp_dir.dir.openDir("root_dir/parent_dir/some_dir", .{}); - dir_verification.close(); + var dir_verification = try tmp_dir.dir.openDir(io, "root_dir/parent_dir/some_dir", .{}); + dir_verification.close(io); } test "deleteDir" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; const test_dir_path = try ctx.transformPath("test_dir"); - const test_file_path = try ctx.transformPath("test_dir" ++ fs.path.sep_str ++ "test_file"); + const test_file_path = try ctx.transformPath("test_dir" ++ Dir.path.sep_str ++ "test_file"); // deleting a non-existent directory - try testing.expectError(error.FileNotFound, ctx.dir.deleteDir(test_dir_path)); + try expectError(error.FileNotFound, ctx.dir.deleteDir(io, test_dir_path)); // deleting a non-empty directory - try ctx.dir.makeDir(test_dir_path); - try ctx.dir.writeFile(.{ .sub_path = test_file_path, .data = "" }); - try testing.expectError(error.DirNotEmpty, ctx.dir.deleteDir(test_dir_path)); + try ctx.dir.createDir(io, test_dir_path, .default_dir); + try ctx.dir.writeFile(io, .{ .sub_path = test_file_path, .data = "" }); + try expectError(error.DirNotEmpty, ctx.dir.deleteDir(io, test_dir_path)); // deleting an empty directory - try ctx.dir.deleteFile(test_file_path); - try ctx.dir.deleteDir(test_dir_path); + try ctx.dir.deleteFile(io, test_file_path); + try ctx.dir.deleteDir(io, test_dir_path); } }.impl); } @@ -883,6 +902,7 @@ test "deleteDir" { test "Dir.rename files" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; // Rename on Windows can hit intermittent AccessDenied errors // when certain conditions are true about the host system. // For now, skip this test when the path type is UNC to avoid them. @@ -892,32 +912,32 @@ test "Dir.rename files" { const missing_file_path = try ctx.transformPath("missing_file_name"); const something_else_path = try ctx.transformPath("something_else"); - try testing.expectError(error.FileNotFound, ctx.dir.rename(missing_file_path, something_else_path)); + try expectError(error.FileNotFound, ctx.dir.rename(missing_file_path, ctx.dir, something_else_path, io)); // Renaming files const test_file_name = try ctx.transformPath("test_file"); const renamed_test_file_name = try ctx.transformPath("test_file_renamed"); - var file = try ctx.dir.createFile(test_file_name, .{ .read = true }); - file.close(); - try ctx.dir.rename(test_file_name, renamed_test_file_name); + var file = try ctx.dir.createFile(io, test_file_name, .{ .read = true }); + file.close(io); + try ctx.dir.rename(test_file_name, ctx.dir, renamed_test_file_name, io); // Ensure the file was renamed - try testing.expectError(error.FileNotFound, ctx.dir.openFile(test_file_name, .{})); - file = try ctx.dir.openFile(renamed_test_file_name, .{}); - file.close(); + try expectError(error.FileNotFound, ctx.dir.openFile(io, test_file_name, .{})); + file = try ctx.dir.openFile(io, renamed_test_file_name, .{}); + file.close(io); // Rename to self succeeds - try ctx.dir.rename(renamed_test_file_name, renamed_test_file_name); + try ctx.dir.rename(renamed_test_file_name, ctx.dir, renamed_test_file_name, io); // Rename to existing file succeeds const existing_file_path = try ctx.transformPath("existing_file"); - var existing_file = try ctx.dir.createFile(existing_file_path, .{ .read = true }); - existing_file.close(); - try ctx.dir.rename(renamed_test_file_name, existing_file_path); + var existing_file = try ctx.dir.createFile(io, existing_file_path, .{ .read = true }); + existing_file.close(io); + try ctx.dir.rename(renamed_test_file_name, ctx.dir, existing_file_path, io); - try testing.expectError(error.FileNotFound, ctx.dir.openFile(renamed_test_file_name, .{})); - file = try ctx.dir.openFile(existing_file_path, .{}); - file.close(); + try expectError(error.FileNotFound, ctx.dir.openFile(io, renamed_test_file_name, .{})); + file = try ctx.dir.openFile(io, existing_file_path, .{}); + file.close(io); } }.impl); } @@ -925,6 +945,8 @@ test "Dir.rename files" { test "Dir.rename directories" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; + // Rename on Windows can hit intermittent AccessDenied errors // when certain conditions are true about the host system. // For now, skip this test when the path type is UNC to avoid them. @@ -935,27 +957,27 @@ test "Dir.rename directories" { const test_dir_renamed_path = try ctx.transformPath("test_dir_renamed"); // Renaming directories - try ctx.dir.makeDir(test_dir_path); - try ctx.dir.rename(test_dir_path, test_dir_renamed_path); + try ctx.dir.createDir(io, test_dir_path, .default_dir); + try ctx.dir.rename(test_dir_path, ctx.dir, test_dir_renamed_path, io); // Ensure the directory was renamed - try testing.expectError(error.FileNotFound, ctx.dir.openDir(test_dir_path, .{})); - var dir = try ctx.dir.openDir(test_dir_renamed_path, .{}); + try expectError(error.FileNotFound, ctx.dir.openDir(io, test_dir_path, .{})); + var dir = try ctx.dir.openDir(io, test_dir_renamed_path, .{}); // Put a file in the directory - var file = try dir.createFile("test_file", .{ .read = true }); - file.close(); - dir.close(); + var file = try dir.createFile(io, "test_file", .{ .read = true }); + file.close(io); + dir.close(io); const test_dir_renamed_again_path = try ctx.transformPath("test_dir_renamed_again"); - try ctx.dir.rename(test_dir_renamed_path, test_dir_renamed_again_path); + try ctx.dir.rename(test_dir_renamed_path, ctx.dir, test_dir_renamed_again_path, io); // Ensure the directory was renamed and the file still exists in it - try testing.expectError(error.FileNotFound, ctx.dir.openDir(test_dir_renamed_path, .{})); - dir = try ctx.dir.openDir(test_dir_renamed_again_path, .{}); - file = try dir.openFile("test_file", .{}); - file.close(); - dir.close(); + try expectError(error.FileNotFound, ctx.dir.openDir(io, test_dir_renamed_path, .{})); + dir = try ctx.dir.openDir(io, test_dir_renamed_again_path, .{}); + file = try dir.openFile(io, "test_file", .{}); + file.close(io); + dir.close(io); } }.impl); } @@ -966,17 +988,19 @@ test "Dir.rename directory onto empty dir" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; + const test_dir_path = try ctx.transformPath("test_dir"); const target_dir_path = try ctx.transformPath("target_dir_path"); - try ctx.dir.makeDir(test_dir_path); - try ctx.dir.makeDir(target_dir_path); - try ctx.dir.rename(test_dir_path, target_dir_path); + try ctx.dir.createDir(io, test_dir_path, .default_dir); + try ctx.dir.createDir(io, target_dir_path, .default_dir); + try ctx.dir.rename(test_dir_path, ctx.dir, target_dir_path, io); // Ensure the directory was renamed - try testing.expectError(error.FileNotFound, ctx.dir.openDir(test_dir_path, .{})); - var dir = try ctx.dir.openDir(target_dir_path, .{}); - dir.close(); + try expectError(error.FileNotFound, ctx.dir.openDir(io, test_dir_path, .{})); + var dir = try ctx.dir.openDir(io, target_dir_path, .{}); + dir.close(io); } }.impl); } @@ -987,22 +1011,22 @@ test "Dir.rename directory onto non-empty dir" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; const test_dir_path = try ctx.transformPath("test_dir"); const target_dir_path = try ctx.transformPath("target_dir_path"); - try ctx.dir.makeDir(test_dir_path); + try ctx.dir.createDir(io, test_dir_path, .default_dir); - var target_dir = try ctx.dir.makeOpenPath(target_dir_path, .{}); - var file = try target_dir.createFile("test_file", .{ .read = true }); - file.close(); - target_dir.close(); + var target_dir = try ctx.dir.createDirPathOpen(io, target_dir_path, .{}); + var file = try target_dir.createFile(io, "test_file", .{ .read = true }); + file.close(io); + target_dir.close(io); - // Rename should fail with PathAlreadyExists if target_dir is non-empty - try testing.expectError(error.PathAlreadyExists, ctx.dir.rename(test_dir_path, target_dir_path)); + try expectError(error.DirNotEmpty, ctx.dir.rename(test_dir_path, ctx.dir, target_dir_path, io)); // Ensure the directory was not renamed - var dir = try ctx.dir.openDir(test_dir_path, .{}); - dir.close(); + var dir = try ctx.dir.openDir(io, test_dir_path, .{}); + dir.close(io); } }.impl); } @@ -1013,19 +1037,22 @@ test "Dir.rename file <-> dir" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; const test_file_path = try ctx.transformPath("test_file"); const test_dir_path = try ctx.transformPath("test_dir"); - var file = try ctx.dir.createFile(test_file_path, .{ .read = true }); - file.close(); - try ctx.dir.makeDir(test_dir_path); - try testing.expectError(error.IsDir, ctx.dir.rename(test_file_path, test_dir_path)); - try testing.expectError(error.NotDir, ctx.dir.rename(test_dir_path, test_file_path)); + var file = try ctx.dir.createFile(io, test_file_path, .{ .read = true }); + file.close(io); + try ctx.dir.createDir(io, test_dir_path, .default_dir); + try expectError(error.IsDir, ctx.dir.rename(test_file_path, ctx.dir, test_dir_path, io)); + try expectError(error.NotDir, ctx.dir.rename(test_dir_path, ctx.dir, test_file_path, io)); } }.impl); } test "rename" { + const io = testing.io; + var tmp_dir1 = tmpDir(.{}); defer tmp_dir1.cleanup(); @@ -1035,18 +1062,21 @@ test "rename" { // Renaming files const test_file_name = "test_file"; const renamed_test_file_name = "test_file_renamed"; - var file = try tmp_dir1.dir.createFile(test_file_name, .{ .read = true }); - file.close(); - try fs.rename(tmp_dir1.dir, test_file_name, tmp_dir2.dir, renamed_test_file_name); + var file = try tmp_dir1.dir.createFile(io, test_file_name, .{ .read = true }); + file.close(io); + try Dir.rename(tmp_dir1.dir, test_file_name, tmp_dir2.dir, renamed_test_file_name, io); // ensure the file was renamed - try testing.expectError(error.FileNotFound, tmp_dir1.dir.openFile(test_file_name, .{})); - file = try tmp_dir2.dir.openFile(renamed_test_file_name, .{}); - file.close(); + try expectError(error.FileNotFound, tmp_dir1.dir.openFile(io, test_file_name, .{})); + file = try tmp_dir2.dir.openFile(io, renamed_test_file_name, .{}); + file.close(io); } test "renameAbsolute" { if (native_os == .wasi) return error.SkipZigTest; + if (native_os == .openbsd) return error.SkipZigTest; + + const io = testing.io; var tmp_dir = tmpDir(.{}); defer tmp_dir.cleanup(); @@ -1056,289 +1086,362 @@ test "renameAbsolute" { defer arena.deinit(); const allocator = arena.allocator(); - const base_path = try tmp_dir.dir.realpathAlloc(allocator, "."); + const base_path = try tmp_dir.dir.realPathFileAlloc(io, ".", allocator); - try testing.expectError(error.FileNotFound, fs.renameAbsolute( - try fs.path.join(allocator, &.{ base_path, "missing_file_name" }), - try fs.path.join(allocator, &.{ base_path, "something_else" }), + try expectError(error.FileNotFound, Dir.renameAbsolute( + try Dir.path.join(allocator, &.{ base_path, "missing_file_name" }), + try Dir.path.join(allocator, &.{ base_path, "something_else" }), + io, )); // Renaming files const test_file_name = "test_file"; const renamed_test_file_name = "test_file_renamed"; - var file = try tmp_dir.dir.createFile(test_file_name, .{ .read = true }); - file.close(); - try fs.renameAbsolute( - try fs.path.join(allocator, &.{ base_path, test_file_name }), - try fs.path.join(allocator, &.{ base_path, renamed_test_file_name }), + var file = try tmp_dir.dir.createFile(io, test_file_name, .{ .read = true }); + file.close(io); + try Dir.renameAbsolute( + try Dir.path.join(allocator, &.{ base_path, test_file_name }), + try Dir.path.join(allocator, &.{ base_path, renamed_test_file_name }), + io, ); // ensure the file was renamed - try testing.expectError(error.FileNotFound, tmp_dir.dir.openFile(test_file_name, .{})); - file = try tmp_dir.dir.openFile(renamed_test_file_name, .{}); - const stat = try file.stat(); - try testing.expectEqual(File.Kind.file, stat.kind); - file.close(); + try expectError(error.FileNotFound, tmp_dir.dir.openFile(io, test_file_name, .{})); + file = try tmp_dir.dir.openFile(io, renamed_test_file_name, .{}); + const stat = try file.stat(io); + try expectEqual(File.Kind.file, stat.kind); + file.close(io); // Renaming directories const test_dir_name = "test_dir"; const renamed_test_dir_name = "test_dir_renamed"; - try tmp_dir.dir.makeDir(test_dir_name); - try fs.renameAbsolute( - try fs.path.join(allocator, &.{ base_path, test_dir_name }), - try fs.path.join(allocator, &.{ base_path, renamed_test_dir_name }), + try tmp_dir.dir.createDir(io, test_dir_name, .default_dir); + try Dir.renameAbsolute( + try Dir.path.join(allocator, &.{ base_path, test_dir_name }), + try Dir.path.join(allocator, &.{ base_path, renamed_test_dir_name }), + io, ); // ensure the directory was renamed - try testing.expectError(error.FileNotFound, tmp_dir.dir.openDir(test_dir_name, .{})); - var dir = try tmp_dir.dir.openDir(renamed_test_dir_name, .{}); - dir.close(); + try expectError(error.FileNotFound, tmp_dir.dir.openDir(io, test_dir_name, .{})); + var dir = try tmp_dir.dir.openDir(io, renamed_test_dir_name, .{}); + dir.close(io); } -test "openSelfExe" { +test "openExecutable" { if (native_os == .wasi) return error.SkipZigTest; + if (native_os == .openbsd) return error.SkipZigTest; + + const io = testing.io; - const self_exe_file = try std.fs.openSelfExe(.{}); - self_exe_file.close(); + const self_exe_file = try std.process.openExecutable(io, .{}); + self_exe_file.close(io); } -test "selfExePath" { +test "executablePath" { if (native_os == .wasi) return error.SkipZigTest; + if (native_os == .openbsd) return error.SkipZigTest; - var buf: [fs.max_path_bytes]u8 = undefined; - const buf_self_exe_path = try std.fs.selfExePath(&buf); - const alloc_self_exe_path = try std.fs.selfExePathAlloc(testing.allocator); + const io = testing.io; + var buf: [Dir.max_path_bytes]u8 = undefined; + const len = try std.process.executablePath(io, &buf); + const buf_self_exe_path = buf[0..len]; + const alloc_self_exe_path = try std.process.executablePathAlloc(io, testing.allocator); defer testing.allocator.free(alloc_self_exe_path); - try testing.expectEqualSlices(u8, buf_self_exe_path, alloc_self_exe_path); + try expectEqualSlices(u8, buf_self_exe_path, alloc_self_exe_path); } test "deleteTree does not follow symlinks" { + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); - try tmp.dir.makePath("b"); + try tmp.dir.createDirPath(io, "b"); { - var a = try tmp.dir.makeOpenPath("a", .{}); - defer a.close(); + var a = try tmp.dir.createDirPathOpen(io, "a", .{}); + defer a.close(io); - try setupSymlink(a, "../b", "b", .{ .is_directory = true }); + try setupSymlink(io, a, "../b", "b", .{ .is_directory = true }); } - try tmp.dir.deleteTree("a"); + try tmp.dir.deleteTree(io, "a"); - try testing.expectError(error.FileNotFound, tmp.dir.access("a", .{})); - try tmp.dir.access("b", .{}); + try expectError(error.FileNotFound, tmp.dir.access(io, "a", .{})); + try tmp.dir.access(io, "b", .{}); } test "deleteTree on a symlink" { + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); // Symlink to a file - try tmp.dir.writeFile(.{ .sub_path = "file", .data = "" }); - try setupSymlink(tmp.dir, "file", "filelink", .{}); + try tmp.dir.writeFile(io, .{ .sub_path = "file", .data = "" }); + try setupSymlink(io, tmp.dir, "file", "filelink", .{}); - try tmp.dir.deleteTree("filelink"); - try testing.expectError(error.FileNotFound, tmp.dir.access("filelink", .{})); - try tmp.dir.access("file", .{}); + try tmp.dir.deleteTree(io, "filelink"); + try expectError(error.FileNotFound, tmp.dir.access(io, "filelink", .{})); + try tmp.dir.access(io, "file", .{}); // Symlink to a directory - try tmp.dir.makePath("dir"); - try setupSymlink(tmp.dir, "dir", "dirlink", .{ .is_directory = true }); + try tmp.dir.createDirPath(io, "dir"); + try setupSymlink(io, tmp.dir, "dir", "dirlink", .{ .is_directory = true }); - try tmp.dir.deleteTree("dirlink"); - try testing.expectError(error.FileNotFound, tmp.dir.access("dirlink", .{})); - try tmp.dir.access("dir", .{}); + try tmp.dir.deleteTree(io, "dirlink"); + try expectError(error.FileNotFound, tmp.dir.access(io, "dirlink", .{})); + try tmp.dir.access(io, "dir", .{}); } -test "makePath, put some files in it, deleteTree" { +test "createDirPath, put some files in it, deleteTree" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; const allocator = ctx.arena.allocator(); const dir_path = try ctx.transformPath("os_test_tmp"); - try ctx.dir.makePath(try fs.path.join(allocator, &.{ "os_test_tmp", "b", "c" })); - try ctx.dir.writeFile(.{ - .sub_path = try fs.path.join(allocator, &.{ "os_test_tmp", "b", "c", "file.txt" }), + try ctx.dir.createDirPath(io, try Dir.path.join(allocator, &.{ "os_test_tmp", "b", "c" })); + try ctx.dir.writeFile(io, .{ + .sub_path = try Dir.path.join(allocator, &.{ "os_test_tmp", "b", "c", "file.txt" }), .data = "nonsense", }); - try ctx.dir.writeFile(.{ - .sub_path = try fs.path.join(allocator, &.{ "os_test_tmp", "b", "file2.txt" }), + try ctx.dir.writeFile(io, .{ + .sub_path = try Dir.path.join(allocator, &.{ "os_test_tmp", "b", "file2.txt" }), .data = "blah", }); - try ctx.dir.deleteTree(dir_path); - try testing.expectError(error.FileNotFound, ctx.dir.openDir(dir_path, .{})); + try ctx.dir.deleteTree(io, dir_path); + try expectError(error.FileNotFound, ctx.dir.openDir(io, dir_path, .{})); } }.impl); } -test "makePath, put some files in it, deleteTreeMinStackSize" { +test "createDirPath, put some files in it, deleteTreeMinStackSize" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; const allocator = ctx.arena.allocator(); const dir_path = try ctx.transformPath("os_test_tmp"); - try ctx.dir.makePath(try fs.path.join(allocator, &.{ "os_test_tmp", "b", "c" })); - try ctx.dir.writeFile(.{ - .sub_path = try fs.path.join(allocator, &.{ "os_test_tmp", "b", "c", "file.txt" }), + try ctx.dir.createDirPath(io, try Dir.path.join(allocator, &.{ "os_test_tmp", "b", "c" })); + try ctx.dir.writeFile(io, .{ + .sub_path = try Dir.path.join(allocator, &.{ "os_test_tmp", "b", "c", "file.txt" }), .data = "nonsense", }); - try ctx.dir.writeFile(.{ - .sub_path = try fs.path.join(allocator, &.{ "os_test_tmp", "b", "file2.txt" }), + try ctx.dir.writeFile(io, .{ + .sub_path = try Dir.path.join(allocator, &.{ "os_test_tmp", "b", "file2.txt" }), .data = "blah", }); - try ctx.dir.deleteTreeMinStackSize(dir_path); - try testing.expectError(error.FileNotFound, ctx.dir.openDir(dir_path, .{})); + try ctx.dir.deleteTreeMinStackSize(io, dir_path); + try expectError(error.FileNotFound, ctx.dir.openDir(io, dir_path, .{})); } }.impl); } -test "makePath in a directory that no longer exists" { +test "createDirPath in a directory that no longer exists" { if (native_os == .windows) return error.SkipZigTest; // Windows returns FileBusy if attempting to remove an open dir + if (native_os == .dragonfly) return error.SkipZigTest; // DragonflyBSD does not produce error (hammer2 fs) + + const io = testing.io; var tmp = tmpDir(.{}); defer tmp.cleanup(); - try tmp.parent_dir.deleteTree(&tmp.sub_path); + try tmp.parent_dir.deleteTree(io, &tmp.sub_path); - try testing.expectError(error.FileNotFound, tmp.dir.makePath("sub-path")); + try expectError(error.FileNotFound, tmp.dir.createDirPath(io, "sub-path")); } -test "makePath but sub_path contains pre-existing file" { +test "createDirPath but sub_path contains pre-existing file" { + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); - try tmp.dir.makeDir("foo"); - try tmp.dir.writeFile(.{ .sub_path = "foo/bar", .data = "" }); + try tmp.dir.createDir(io, "foo", .default_dir); + try tmp.dir.writeFile(io, .{ .sub_path = "foo/bar", .data = "" }); - try testing.expectError(error.NotDir, tmp.dir.makePath("foo/bar/baz")); + try expectError(error.NotDir, tmp.dir.createDirPath(io, "foo/bar/baz")); } -fn expectDir(dir: Dir, path: []const u8) !void { - var d = try dir.openDir(path, .{}); - d.close(); +fn expectDir(io: Io, dir: Dir, path: []const u8) !void { + var d = try dir.openDir(io, path, .{}); + d.close(io); } test "makepath existing directories" { + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); - try tmp.dir.makeDir("A"); - var tmpA = try tmp.dir.openDir("A", .{}); - defer tmpA.close(); - try tmpA.makeDir("B"); + try tmp.dir.createDir(io, "A", .default_dir); + var tmpA = try tmp.dir.openDir(io, "A", .{}); + defer tmpA.close(io); + try tmpA.createDir(io, "B", .default_dir); - const testPath = "A" ++ fs.path.sep_str ++ "B" ++ fs.path.sep_str ++ "C"; - try tmp.dir.makePath(testPath); + const testPath = "A" ++ Dir.path.sep_str ++ "B" ++ Dir.path.sep_str ++ "C"; + try tmp.dir.createDirPath(io, testPath); - try expectDir(tmp.dir, testPath); + try expectDir(io, tmp.dir, testPath); } test "makepath through existing valid symlink" { + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); - try tmp.dir.makeDir("realfolder"); - try setupSymlink(tmp.dir, "." ++ fs.path.sep_str ++ "realfolder", "working-symlink", .{}); + try tmp.dir.createDir(io, "realfolder", .default_dir); + try setupSymlink(io, tmp.dir, "." ++ Dir.path.sep_str ++ "realfolder", "working-symlink", .{}); - try tmp.dir.makePath("working-symlink" ++ fs.path.sep_str ++ "in-realfolder"); + try tmp.dir.createDirPath(io, "working-symlink" ++ Dir.path.sep_str ++ "in-realfolder"); - try expectDir(tmp.dir, "realfolder" ++ fs.path.sep_str ++ "in-realfolder"); + try expectDir(io, tmp.dir, "realfolder" ++ Dir.path.sep_str ++ "in-realfolder"); } test "makepath relative walks" { + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); - const relPath = try fs.path.join(testing.allocator, &.{ + const relPath = try Dir.path.join(testing.allocator, &.{ "first", "..", "second", "..", "third", "..", "first", "A", "..", "B", "..", "C", }); defer testing.allocator.free(relPath); - try tmp.dir.makePath(relPath); + try tmp.dir.createDirPath(io, relPath); // How .. is handled is different on Windows than non-Windows switch (native_os) { .windows => { // On Windows, .. is resolved before passing the path to NtCreateFile, // meaning everything except `first/C` drops out. - try expectDir(tmp.dir, "first" ++ fs.path.sep_str ++ "C"); - try testing.expectError(error.FileNotFound, tmp.dir.access("second", .{})); - try testing.expectError(error.FileNotFound, tmp.dir.access("third", .{})); + try expectDir(io, tmp.dir, "first" ++ Dir.path.sep_str ++ "C"); + try expectError(error.FileNotFound, tmp.dir.access(io, "second", .{})); + try expectError(error.FileNotFound, tmp.dir.access(io, "third", .{})); }, else => { - try expectDir(tmp.dir, "first" ++ fs.path.sep_str ++ "A"); - try expectDir(tmp.dir, "first" ++ fs.path.sep_str ++ "B"); - try expectDir(tmp.dir, "first" ++ fs.path.sep_str ++ "C"); - try expectDir(tmp.dir, "second"); - try expectDir(tmp.dir, "third"); + try expectDir(io, tmp.dir, "first" ++ Dir.path.sep_str ++ "A"); + try expectDir(io, tmp.dir, "first" ++ Dir.path.sep_str ++ "B"); + try expectDir(io, tmp.dir, "first" ++ Dir.path.sep_str ++ "C"); + try expectDir(io, tmp.dir, "second"); + try expectDir(io, tmp.dir, "third"); }, } } test "makepath ignores '.'" { + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); // Path to create, with "." elements: - const dotPath = try fs.path.join(testing.allocator, &.{ + const dotPath = try Dir.path.join(testing.allocator, &.{ "first", ".", "second", ".", "third", }); defer testing.allocator.free(dotPath); // Path to expect to find: - const expectedPath = try fs.path.join(testing.allocator, &.{ + const expectedPath = try Dir.path.join(testing.allocator, &.{ "first", "second", "third", }); defer testing.allocator.free(expectedPath); - try tmp.dir.makePath(dotPath); + try tmp.dir.createDirPath(io, dotPath); - try expectDir(tmp.dir, expectedPath); + try expectDir(io, tmp.dir, expectedPath); } -fn testFilenameLimits(iterable_dir: Dir, maxed_filename: []const u8) !void { - // setup, create a dir and a nested file both with maxed filenames, and walk the dir +fn testFilenameLimits(io: Io, iterable_dir: Dir, maxed_filename: []const u8, maxed_dirname: []const u8) !void { + // create a file, a dir, and a nested file all with maxed filenames { - var maxed_dir = try iterable_dir.makeOpenPath(maxed_filename, .{}); - defer maxed_dir.close(); + try iterable_dir.writeFile(io, .{ .sub_path = maxed_filename, .data = "" }); - try maxed_dir.writeFile(.{ .sub_path = maxed_filename, .data = "" }); + var maxed_dir = try iterable_dir.createDirPathOpen(io, maxed_dirname, .{}); + defer maxed_dir.close(io); + try maxed_dir.writeFile(io, .{ .sub_path = maxed_filename, .data = "" }); + } + // Low level API with minimum buffer length + { + var reader_buf: [Dir.Reader.min_buffer_len]u8 align(@alignOf(usize)) = undefined; + var reader: Dir.Reader = .init(iterable_dir, &reader_buf); + + var file_count: usize = 0; + var dir_count: usize = 0; + while (try reader.next(io)) |entry| { + switch (entry.kind) { + .file => { + try expectEqualStrings(maxed_filename, entry.name); + file_count += 1; + }, + .directory => { + try expectEqualStrings(maxed_dirname, entry.name); + dir_count += 1; + }, + else => return error.TestFailed, + } + } + try expectEqual(@as(usize, 1), file_count); + try expectEqual(@as(usize, 1), dir_count); + } + // High level walk API + { var walker = try iterable_dir.walk(testing.allocator); defer walker.deinit(); - var count: usize = 0; - while (try walker.next()) |entry| { - try testing.expectEqualStrings(maxed_filename, entry.basename); - count += 1; + var file_count: usize = 0; + var dir_count: usize = 0; + while (try walker.next(io)) |entry| { + switch (entry.kind) { + .file => { + try expectEqualStrings(maxed_filename, entry.basename); + file_count += 1; + }, + .directory => { + try expectEqualStrings(maxed_dirname, entry.basename); + dir_count += 1; + }, + else => return error.TestFailed, + } } - try testing.expectEqual(@as(usize, 2), count); + try expectEqual(@as(usize, 2), file_count); + try expectEqual(@as(usize, 1), dir_count); } // ensure that we can delete the tree - try iterable_dir.deleteTree(maxed_filename); + try iterable_dir.deleteTree(io, maxed_filename); } test "max file name component lengths" { + const io = testing.io; + var tmp = tmpDir(.{ .iterate = true }); defer tmp.cleanup(); if (native_os == .windows) { // U+FFFF is the character with the largest code point that is encoded as a single - // UTF-16 code unit, so Windows allows for NAME_MAX of them. - const maxed_windows_filename = ("\u{FFFF}".*) ** windows.NAME_MAX; - try testFilenameLimits(tmp.dir, &maxed_windows_filename); + // WTF-16 code unit, so Windows allows for NAME_MAX of them. + const maxed_windows_filename1 = ("\u{FFFF}".*) ** windows.NAME_MAX; + // This is also a code point that is encoded as one WTF-16 code unit, but + // three WTF-8 bytes, so it exercises the limits of both WTF-16 and WTF-8 encodings. + const maxed_windows_filename2 = ("€".*) ** windows.NAME_MAX; + try testFilenameLimits(io, tmp.dir, &maxed_windows_filename1, &maxed_windows_filename2); } else if (native_os == .wasi) { // On WASI, the maxed filename depends on the host OS, so in order for this test to // work on any host, we need to use a length that will work for all platforms // (i.e. the minimum max_name_bytes of all supported platforms). - const maxed_wasi_filename = [_]u8{'1'} ** 255; - try testFilenameLimits(tmp.dir, &maxed_wasi_filename); + const maxed_wasi_filename1: [255]u8 = @splat('1'); + const maxed_wasi_filename2: [255]u8 = @splat('2'); + try testFilenameLimits(io, tmp.dir, &maxed_wasi_filename1, &maxed_wasi_filename2); } else { - const maxed_ascii_filename = [_]u8{'1'} ** std.fs.max_name_bytes; - try testFilenameLimits(tmp.dir, &maxed_ascii_filename); + const maxed_ascii_filename1: [Dir.max_name_bytes]u8 = @splat('1'); + const maxed_ascii_filename2: [Dir.max_name_bytes]u8 = @splat('2'); + try testFilenameLimits(io, tmp.dir, &maxed_ascii_filename1, &maxed_ascii_filename2); } } @@ -1356,21 +1459,21 @@ test "writev, readv" { var write_vecs: [2][]const u8 = .{ line1, line2 }; var read_vecs: [2][]u8 = .{ &buf2, &buf1 }; - var src_file = try tmp.dir.createFile("test.txt", .{ .read = true }); - defer src_file.close(); + var src_file = try tmp.dir.createFile(io, "test.txt", .{ .read = true }); + defer src_file.close(io); - var writer = src_file.writerStreaming(&.{}); + var writer = src_file.writerStreaming(io, &.{}); try writer.interface.writeVecAll(&write_vecs); try writer.interface.flush(); - try testing.expectEqual(@as(u64, line1.len + line2.len), try src_file.getEndPos()); + try expectEqual(@as(u64, line1.len + line2.len), try src_file.length(io)); - var reader = writer.moveToReader(io); + var reader = writer.moveToReader(); try reader.seekTo(0); try reader.interface.readVecAll(&read_vecs); - try testing.expectEqualStrings(&buf1, "line2\n"); - try testing.expectEqualStrings(&buf2, "line1\n"); - try testing.expectError(error.EndOfStream, reader.interface.readSliceAll(&buf1)); + try expectEqualStrings(&buf1, "line2\n"); + try expectEqualStrings(&buf2, "line1\n"); + try expectError(error.EndOfStream, reader.interface.readSliceAll(&buf1)); } test "pwritev, preadv" { @@ -1386,87 +1489,37 @@ test "pwritev, preadv" { var buf2: [line2.len]u8 = undefined; var read_vecs: [2][]u8 = .{ &buf2, &buf1 }; - var src_file = try tmp.dir.createFile("test.txt", .{ .read = true }); - defer src_file.close(); + var src_file = try tmp.dir.createFile(io, "test.txt", .{ .read = true }); + defer src_file.close(io); - var writer = src_file.writer(&.{}); + var writer = src_file.writer(io, &.{}); try writer.seekTo(16); try writer.interface.writeVecAll(&lines); try writer.interface.flush(); - try testing.expectEqual(@as(u64, 16 + line1.len + line2.len), try src_file.getEndPos()); + try expectEqual(@as(u64, 16 + line1.len + line2.len), try src_file.length(io)); - var reader = writer.moveToReader(io); + var reader = writer.moveToReader(); try reader.seekTo(16); try reader.interface.readVecAll(&read_vecs); - try testing.expectEqualStrings(&buf1, "line2\n"); - try testing.expectEqualStrings(&buf2, "line1\n"); - try testing.expectError(error.EndOfStream, reader.interface.readSliceAll(&buf1)); -} - -test "setEndPos" { - // https://github.com/ziglang/zig/issues/20747 (open fd does not have write permission) - if (native_os == .wasi and builtin.link_libc) return error.SkipZigTest; - if (builtin.cpu.arch.isMIPS64() and (builtin.abi == .gnuabin32 or builtin.abi == .muslabin32)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/23806 - - const io = testing.io; - - var tmp = tmpDir(.{}); - defer tmp.cleanup(); - - const file_name = "afile.txt"; - try tmp.dir.writeFile(.{ .sub_path = file_name, .data = "ninebytes" }); - const f = try tmp.dir.openFile(file_name, .{ .mode = .read_write }); - defer f.close(); - - const initial_size = try f.getEndPos(); - var buffer: [32]u8 = undefined; - var reader = f.reader(io, &.{}); - - { - try f.setEndPos(initial_size); - try testing.expectEqual(initial_size, try f.getEndPos()); - try reader.seekTo(0); - try testing.expectEqual(initial_size, try reader.interface.readSliceShort(&buffer)); - try testing.expectEqualStrings("ninebytes", buffer[0..@intCast(initial_size)]); - } - - { - const larger = initial_size + 4; - try f.setEndPos(larger); - try testing.expectEqual(larger, try f.getEndPos()); - try reader.seekTo(0); - try testing.expectEqual(larger, try reader.interface.readSliceShort(&buffer)); - try testing.expectEqualStrings("ninebytes\x00\x00\x00\x00", buffer[0..@intCast(larger)]); - } - - { - const smaller = initial_size - 5; - try f.setEndPos(smaller); - try testing.expectEqual(smaller, try f.getEndPos()); - try reader.seekTo(0); - try testing.expectEqual(smaller, try reader.interface.readSliceShort(&buffer)); - try testing.expectEqualStrings("nine", buffer[0..@intCast(smaller)]); - } - - try f.setEndPos(0); - try testing.expectEqual(0, try f.getEndPos()); - try reader.seekTo(0); - try testing.expectEqual(0, try reader.interface.readSliceShort(&buffer)); + try expectEqualStrings(&buf1, "line2\n"); + try expectEqualStrings(&buf2, "line1\n"); + try expectError(error.EndOfStream, reader.interface.readSliceAll(&buf1)); } test "access file" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; const dir_path = try ctx.transformPath("os_test_tmp"); - const file_path = try ctx.transformPath("os_test_tmp" ++ fs.path.sep_str ++ "file.txt"); + const file_path = try ctx.transformPath("os_test_tmp" ++ Dir.path.sep_str ++ "file.txt"); - try ctx.dir.makePath(dir_path); - try testing.expectError(error.FileNotFound, ctx.dir.access(file_path, .{})); + try ctx.dir.createDirPath(io, dir_path); + try expectError(error.FileNotFound, ctx.dir.access(io, file_path, .{})); - try ctx.dir.writeFile(.{ .sub_path = file_path, .data = "" }); - try ctx.dir.access(file_path, .{}); - try ctx.dir.deleteTree(dir_path); + try ctx.dir.writeFile(io, .{ .sub_path = file_path, .data = "" }); + try ctx.dir.access(io, file_path, .{}); + try ctx.dir.deleteTree(io, dir_path); } }.impl); } @@ -1477,24 +1530,24 @@ test "sendfile" { var tmp = tmpDir(.{}); defer tmp.cleanup(); - try tmp.dir.makePath("os_test_tmp"); + try tmp.dir.createDirPath(io, "os_test_tmp"); - var dir = try tmp.dir.openDir("os_test_tmp", .{}); - defer dir.close(); + var dir = try tmp.dir.openDir(io, "os_test_tmp", .{}); + defer dir.close(io); const line1 = "line1\n"; const line2 = "second line\n"; var vecs = [_][]const u8{ line1, line2 }; - var src_file = try dir.createFile("sendfile1.txt", .{ .read = true }); - defer src_file.close(); + var src_file = try dir.createFile(io, "sendfile1.txt", .{ .read = true }); + defer src_file.close(io); { - var fw = src_file.writer(&.{}); + var fw = src_file.writer(io, &.{}); try fw.interface.writeVecAll(&vecs); } - var dest_file = try dir.createFile("sendfile2.txt", .{ .read = true }); - defer dest_file.close(); + var dest_file = try dir.createFile(io, "sendfile2.txt", .{ .read = true }); + defer dest_file.close(io); const header1 = "header1\n"; const header2 = "second header\n"; @@ -1506,16 +1559,16 @@ test "sendfile" { var written_buf: [100]u8 = undefined; var file_reader = src_file.reader(io, &.{}); var fallback_buffer: [50]u8 = undefined; - var file_writer = dest_file.writer(&fallback_buffer); + var file_writer = dest_file.writer(io, &fallback_buffer); try file_writer.interface.writeVecAll(&headers); try file_reader.seekTo(1); - try testing.expectEqual(10, try file_writer.interface.sendFileAll(&file_reader, .limited(10))); + try expectEqual(10, try file_writer.interface.sendFileAll(&file_reader, .limited(10))); try file_writer.interface.writeVecAll(&trailers); try file_writer.interface.flush(); - var fr = file_writer.moveToReader(io); + var fr = file_writer.moveToReader(); try fr.seekTo(0); const amt = try fr.interface.readSliceShort(&written_buf); - try testing.expectEqualStrings("header1\nsecond header\nine1\nsecontrailer1\nsecond trailer\n", written_buf[0..amt]); + try expectEqualStrings("header1\nsecond header\nine1\nsecontrailer1\nsecond trailer\n", written_buf[0..amt]); } test "sendfile with buffered data" { @@ -1524,18 +1577,18 @@ test "sendfile with buffered data" { var tmp = tmpDir(.{}); defer tmp.cleanup(); - try tmp.dir.makePath("os_test_tmp"); + try tmp.dir.createDirPath(io, "os_test_tmp"); - var dir = try tmp.dir.openDir("os_test_tmp", .{}); - defer dir.close(); + var dir = try tmp.dir.openDir(io, "os_test_tmp", .{}); + defer dir.close(io); - var src_file = try dir.createFile("sendfile1.txt", .{ .read = true }); - defer src_file.close(); + var src_file = try dir.createFile(io, "sendfile1.txt", .{ .read = true }); + defer src_file.close(io); - try src_file.writeAll("AAAABBBB"); + try src_file.writeStreamingAll(io, "AAAABBBB"); - var dest_file = try dir.createFile("sendfile2.txt", .{ .read = true }); - defer dest_file.close(); + var dest_file = try dir.createFile(io, "sendfile2.txt", .{ .read = true }); + defer dest_file.close(io); var src_buffer: [32]u8 = undefined; var file_reader = src_file.reader(io, &src_buffer); @@ -1544,52 +1597,54 @@ test "sendfile with buffered data" { try file_reader.interface.fill(8); var fallback_buffer: [32]u8 = undefined; - var file_writer = dest_file.writer(&fallback_buffer); + var file_writer = dest_file.writer(io, &fallback_buffer); - try std.testing.expectEqual(4, try file_writer.interface.sendFileAll(&file_reader, .limited(4))); + try expectEqual(4, try file_writer.interface.sendFileAll(&file_reader, .limited(4))); var written_buf: [8]u8 = undefined; - var fr = file_writer.moveToReader(io); + var fr = file_writer.moveToReader(); try fr.seekTo(0); const amt = try fr.interface.readSliceShort(&written_buf); - try std.testing.expectEqual(4, amt); - try std.testing.expectEqualSlices(u8, "AAAA", written_buf[0..amt]); + try expectEqual(4, amt); + try expectEqualSlices(u8, "AAAA", written_buf[0..amt]); } test "copyFile" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; const data = "u6wj+JmdF3qHsFPE BUlH2g4gJCmEz0PP"; const src_file = try ctx.transformPath("tmp_test_copy_file.txt"); const dest_file = try ctx.transformPath("tmp_test_copy_file2.txt"); const dest_file2 = try ctx.transformPath("tmp_test_copy_file3.txt"); - try ctx.dir.writeFile(.{ .sub_path = src_file, .data = data }); - defer ctx.dir.deleteFile(src_file) catch {}; + try ctx.dir.writeFile(io, .{ .sub_path = src_file, .data = data }); + defer ctx.dir.deleteFile(io, src_file) catch {}; - try ctx.dir.copyFile(src_file, ctx.dir, dest_file, .{}); - defer ctx.dir.deleteFile(dest_file) catch {}; + try ctx.dir.copyFile(src_file, ctx.dir, dest_file, io, .{}); + defer ctx.dir.deleteFile(io, dest_file) catch {}; - try ctx.dir.copyFile(src_file, ctx.dir, dest_file2, .{ .override_mode = File.default_mode }); - defer ctx.dir.deleteFile(dest_file2) catch {}; + try ctx.dir.copyFile(src_file, ctx.dir, dest_file2, io, .{}); + defer ctx.dir.deleteFile(io, dest_file2) catch {}; - try expectFileContents(ctx.dir, dest_file, data); - try expectFileContents(ctx.dir, dest_file2, data); + try expectFileContents(io, ctx.dir, dest_file, data); + try expectFileContents(io, ctx.dir, dest_file2, data); } }.impl); } -fn expectFileContents(dir: Dir, file_path: []const u8, data: []const u8) !void { - const contents = try dir.readFileAlloc(file_path, testing.allocator, .limited(1000)); +fn expectFileContents(io: Io, dir: Dir, file_path: []const u8, data: []const u8) !void { + const contents = try dir.readFileAlloc(io, file_path, testing.allocator, .limited(1000)); defer testing.allocator.free(contents); - try testing.expectEqualSlices(u8, data, contents); + try expectEqualSlices(u8, data, contents); } test "AtomicFile" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; const allocator = ctx.arena.allocator(); const test_out_file = try ctx.transformPath("tmp_atomic_file_test_dest.txt"); const test_content = @@ -1597,17 +1652,31 @@ test "AtomicFile" { \\ this is a test file ; + // link() succeeds with no file already present + { + var af = try ctx.dir.createFileAtomic(io, test_out_file, .{ .replace = false }); + defer af.deinit(io); + try af.file.writeStreamingAll(io, test_content); + try af.link(io); + } + // link() returns error.PathAlreadyExists if file already present { - var buffer: [100]u8 = undefined; - var af = try ctx.dir.atomicFile(test_out_file, .{ .write_buffer = &buffer }); - defer af.deinit(); - try af.file_writer.interface.writeAll(test_content); - try af.finish(); + var af = try ctx.dir.createFileAtomic(io, test_out_file, .{ .replace = false }); + defer af.deinit(io); + try af.file.writeStreamingAll(io, test_content); + try expectError(error.PathAlreadyExists, af.link(io)); } - const content = try ctx.dir.readFileAlloc(test_out_file, allocator, .limited(9999)); - try testing.expectEqualStrings(test_content, content); + // replace() succeeds if file already present + { + var af = try ctx.dir.createFileAtomic(io, test_out_file, .{ .replace = true }); + defer af.deinit(io); + try af.file.writeStreamingAll(io, test_content); + try af.replace(io); + } + const content = try ctx.dir.readFileAlloc(io, test_out_file, allocator, .limited(9999)); + try expectEqualStrings(test_content, content); - try ctx.dir.deleteFile(test_out_file); + try ctx.dir.deleteFile(io, test_out_file); } }.impl); } @@ -1617,13 +1686,14 @@ test "open file with exclusive nonblocking lock twice" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; const filename = try ctx.transformPath("file_nonblocking_lock_test.txt"); - const file1 = try ctx.dir.createFile(filename, .{ .lock = .exclusive, .lock_nonblocking = true }); - defer file1.close(); + const file1 = try ctx.dir.createFile(io, filename, .{ .lock = .exclusive, .lock_nonblocking = true }); + defer file1.close(io); - const file2 = ctx.dir.createFile(filename, .{ .lock = .exclusive, .lock_nonblocking = true }); - try testing.expectError(error.WouldBlock, file2); + const file2 = ctx.dir.createFile(io, filename, .{ .lock = .exclusive, .lock_nonblocking = true }); + try expectError(error.WouldBlock, file2); } }.impl); } @@ -1633,13 +1703,14 @@ test "open file with shared and exclusive nonblocking lock" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; const filename = try ctx.transformPath("file_nonblocking_lock_test.txt"); - const file1 = try ctx.dir.createFile(filename, .{ .lock = .shared, .lock_nonblocking = true }); - defer file1.close(); + const file1 = try ctx.dir.createFile(io, filename, .{ .lock = .shared, .lock_nonblocking = true }); + defer file1.close(io); - const file2 = ctx.dir.createFile(filename, .{ .lock = .exclusive, .lock_nonblocking = true }); - try testing.expectError(error.WouldBlock, file2); + const file2 = ctx.dir.createFile(io, filename, .{ .lock = .exclusive, .lock_nonblocking = true }); + try expectError(error.WouldBlock, file2); } }.impl); } @@ -1649,13 +1720,14 @@ test "open file with exclusive and shared nonblocking lock" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; const filename = try ctx.transformPath("file_nonblocking_lock_test.txt"); - const file1 = try ctx.dir.createFile(filename, .{ .lock = .exclusive, .lock_nonblocking = true }); - defer file1.close(); + const file1 = try ctx.dir.createFile(io, filename, .{ .lock = .exclusive, .lock_nonblocking = true }); + defer file1.close(io); - const file2 = ctx.dir.createFile(filename, .{ .lock = .shared, .lock_nonblocking = true }); - try testing.expectError(error.WouldBlock, file2); + const file2 = ctx.dir.createFile(io, filename, .{ .lock = .shared, .lock_nonblocking = true }); + try expectError(error.WouldBlock, file2); } }.impl); } @@ -1665,39 +1737,35 @@ test "open file with exclusive lock twice, make sure second lock waits" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; const filename = try ctx.transformPath("file_lock_test.txt"); - const file = try ctx.dir.createFile(filename, .{ .lock = .exclusive }); - errdefer file.close(); + const file = try ctx.dir.createFile(io, filename, .{ .lock = .exclusive }); + errdefer file.close(io); const S = struct { - fn checkFn(dir: *fs.Dir, path: []const u8, started: *std.Thread.ResetEvent, locked: *std.Thread.ResetEvent) !void { + fn checkFn(inner_ctx: *TestContext, path: []const u8, started: *std.Thread.ResetEvent, locked: *std.Thread.ResetEvent) !void { started.set(); - const file1 = try dir.createFile(path, .{ .lock = .exclusive }); + const file1 = try inner_ctx.dir.createFile(inner_ctx.io, path, .{ .lock = .exclusive }); locked.set(); - file1.close(); + file1.close(inner_ctx.io); } }; var started: std.Thread.ResetEvent = .unset; var locked: std.Thread.ResetEvent = .unset; - const t = try std.Thread.spawn(.{}, S.checkFn, .{ - &ctx.dir, - filename, - &started, - &locked, - }); + const t = try std.Thread.spawn(.{}, S.checkFn, .{ ctx, filename, &started, &locked }); defer t.join(); // Wait for the spawned thread to start trying to acquire the exclusive file lock. // Then wait a bit to make sure that can't acquire it since we currently hold the file lock. started.wait(); - try testing.expectError(error.Timeout, locked.timedWait(10 * std.time.ns_per_ms)); + try expectError(error.Timeout, locked.timedWait(10 * std.time.ns_per_ms)); // Release the file lock which should unlock the thread to lock it and set the locked event. - file.close(); + file.close(io); locked.wait(); } }.impl); @@ -1706,11 +1774,13 @@ test "open file with exclusive lock twice, make sure second lock waits" { test "open file with exclusive nonblocking lock twice (absolute paths)" { if (native_os == .wasi) return error.SkipZigTest; + const io = testing.io; + var random_bytes: [12]u8 = undefined; - std.crypto.random.bytes(&random_bytes); + io.random(&random_bytes); - var random_b64: [fs.base64_encoder.calcSize(random_bytes.len)]u8 = undefined; - _ = fs.base64_encoder.encode(&random_b64, &random_bytes); + var random_b64: [std.base64.url_safe.Encoder.calcSize(random_bytes.len)]u8 = undefined; + _ = std.base64.url_safe.Encoder.encode(&random_b64, &random_bytes); const sub_path = random_b64 ++ "-zig-test-absolute-paths.txt"; @@ -1719,47 +1789,50 @@ test "open file with exclusive nonblocking lock twice (absolute paths)" { const cwd = try std.process.getCwdAlloc(gpa); defer gpa.free(cwd); - const filename = try fs.path.resolve(gpa, &.{ cwd, sub_path }); + const filename = try Dir.path.resolve(gpa, &.{ cwd, sub_path }); defer gpa.free(filename); - defer fs.deleteFileAbsolute(filename) catch {}; // createFileAbsolute can leave files on failures - const file1 = try fs.createFileAbsolute(filename, .{ + defer Dir.deleteFileAbsolute(io, filename) catch {}; // createFileAbsolute can leave files on failures + const file1 = try Dir.createFileAbsolute(io, filename, .{ .lock = .exclusive, .lock_nonblocking = true, }); - const file2 = fs.createFileAbsolute(filename, .{ + const file2 = Dir.createFileAbsolute(io, filename, .{ .lock = .exclusive, .lock_nonblocking = true, }); - file1.close(); - try testing.expectError(error.WouldBlock, file2); + file1.close(io); + try expectError(error.WouldBlock, file2); } test "read from locked file" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; const filename = try ctx.transformPath("read_lock_file_test.txt"); { - const f = try ctx.dir.createFile(filename, .{ .read = true }); - defer f.close(); + const f = try ctx.dir.createFile(io, filename, .{ .read = true }); + defer f.close(io); var buffer: [1]u8 = undefined; - _ = try f.read(&buffer); + _ = try f.readPositional(io, &.{&buffer}, 0); } { - const f = try ctx.dir.createFile(filename, .{ + const f = try ctx.dir.createFile(io, filename, .{ .read = true, .lock = .exclusive, }); - defer f.close(); - const f2 = try ctx.dir.openFile(filename, .{}); - defer f2.close(); + defer f.close(io); + const f2 = try ctx.dir.openFile(io, filename, .{}); + defer f2.close(io); + // On POSIX locks may be ignored, however on Windows they cause + // LockViolation. var buffer: [1]u8 = undefined; if (builtin.os.tag == .windows) { - try std.testing.expectError(error.LockViolation, f2.read(&buffer)); + try expectError(error.LockViolation, f2.readPositional(io, &.{&buffer}, 0)); } else { - try std.testing.expectEqual(0, f2.read(&buffer)); + try expectEqual(0, f2.readPositional(io, &.{&buffer}, 0)); } } } @@ -1767,6 +1840,8 @@ test "read from locked file" { } test "walker" { + const io = testing.io; + var tmp = tmpDir(.{ .iterate = true }); defer tmp.cleanup(); @@ -1777,9 +1852,9 @@ test "walker" { .{ "dir2", 1 }, .{ "dir3", 1 }, .{ "dir4", 1 }, - .{ "dir3" ++ fs.path.sep_str ++ "sub1", 2 }, - .{ "dir3" ++ fs.path.sep_str ++ "sub2", 2 }, - .{ "dir3" ++ fs.path.sep_str ++ "sub2" ++ fs.path.sep_str ++ "subsub1", 3 }, + .{ "dir3" ++ Dir.path.sep_str ++ "sub1", 2 }, + .{ "dir3" ++ Dir.path.sep_str ++ "sub2", 2 }, + .{ "dir3" ++ Dir.path.sep_str ++ "sub2" ++ Dir.path.sep_str ++ "subsub1", 3 }, }); const expected_basenames = std.StaticStringMap(void).initComptime(.{ @@ -1793,35 +1868,37 @@ test "walker" { }); for (expected_paths.keys()) |key| { - try tmp.dir.makePath(key); + try tmp.dir.createDirPath(io, key); } var walker = try tmp.dir.walk(testing.allocator); defer walker.deinit(); var num_walked: usize = 0; - while (try walker.next()) |entry| { - testing.expect(expected_basenames.has(entry.basename)) catch |err| { + while (try walker.next(io)) |entry| { + expect(expected_basenames.has(entry.basename)) catch |err| { std.debug.print("found unexpected basename: {f}\n", .{std.ascii.hexEscape(entry.basename, .lower)}); return err; }; - testing.expect(expected_paths.has(entry.path)) catch |err| { + expect(expected_paths.has(entry.path)) catch |err| { std.debug.print("found unexpected path: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)}); return err; }; - testing.expectEqual(expected_paths.get(entry.path).?, entry.depth()) catch |err| { + expectEqual(expected_paths.get(entry.path).?, entry.depth()) catch |err| { std.debug.print("path reported unexpected depth: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)}); return err; }; // make sure that the entry.dir is the containing dir - var entry_dir = try entry.dir.openDir(entry.basename, .{}); - defer entry_dir.close(); + var entry_dir = try entry.dir.openDir(io, entry.basename, .{}); + defer entry_dir.close(io); num_walked += 1; } - try testing.expectEqual(expected_paths.kvs.len, num_walked); + try expectEqual(expected_paths.kvs.len, num_walked); } test "selective walker, skip entries that start with ." { + const io = testing.io; + var tmp = tmpDir(.{ .iterate = true }); defer tmp.cleanup(); @@ -1836,11 +1913,11 @@ test "selective walker, skip entries that start with ." { const expected_paths = std.StaticStringMap(usize).initComptime(.{ .{ "dir1", 1 }, - .{ "dir1" ++ fs.path.sep_str ++ "foo", 2 }, + .{ "dir1" ++ Dir.path.sep_str ++ "foo", 2 }, .{ "a", 1 }, - .{ "a" ++ fs.path.sep_str ++ "b", 2 }, - .{ "a" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "c", 3 }, - .{ "a" ++ fs.path.sep_str ++ "baz", 2 }, + .{ "a" ++ Dir.path.sep_str ++ "b", 2 }, + .{ "a" ++ Dir.path.sep_str ++ "b" ++ Dir.path.sep_str ++ "c", 3 }, + .{ "a" ++ Dir.path.sep_str ++ "baz", 2 }, }); const expected_basenames = std.StaticStringMap(void).initComptime(.{ @@ -1853,41 +1930,43 @@ test "selective walker, skip entries that start with ." { }); for (paths_to_create) |path| { - try tmp.dir.makePath(path); + try tmp.dir.createDirPath(io, path); } var walker = try tmp.dir.walkSelectively(testing.allocator); defer walker.deinit(); var num_walked: usize = 0; - while (try walker.next()) |entry| { + while (try walker.next(io)) |entry| { if (entry.basename[0] == '.') continue; if (entry.kind == .directory) { - try walker.enter(entry); + try walker.enter(io, entry); } - testing.expect(expected_basenames.has(entry.basename)) catch |err| { + expect(expected_basenames.has(entry.basename)) catch |err| { std.debug.print("found unexpected basename: {f}\n", .{std.ascii.hexEscape(entry.basename, .lower)}); return err; }; - testing.expect(expected_paths.has(entry.path)) catch |err| { + expect(expected_paths.has(entry.path)) catch |err| { std.debug.print("found unexpected path: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)}); return err; }; - testing.expectEqual(expected_paths.get(entry.path).?, entry.depth()) catch |err| { + expectEqual(expected_paths.get(entry.path).?, entry.depth()) catch |err| { std.debug.print("path reported unexpected depth: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)}); return err; }; // make sure that the entry.dir is the containing dir - var entry_dir = try entry.dir.openDir(entry.basename, .{}); - defer entry_dir.close(); + var entry_dir = try entry.dir.openDir(io, entry.basename, .{}); + defer entry_dir.close(io); num_walked += 1; } - try testing.expectEqual(expected_paths.kvs.len, num_walked); + try expectEqual(expected_paths.kvs.len, num_walked); } test "walker without fully iterating" { + const io = testing.io; + var tmp = tmpDir(.{ .iterate = true }); defer tmp.cleanup(); @@ -1897,18 +1976,18 @@ test "walker without fully iterating" { // Create 2 directories inside the tmp directory, but then only iterate once before breaking. // This ensures that walker doesn't try to close the initial directory when not fully iterating. - try tmp.dir.makePath("a"); - try tmp.dir.makePath("b"); + try tmp.dir.createDirPath(io, "a"); + try tmp.dir.createDirPath(io, "b"); var num_walked: usize = 0; - while (try walker.next()) |_| { + while (try walker.next(io)) |_| { num_walked += 1; break; } - try testing.expectEqual(@as(usize, 1), num_walked); + try expectEqual(@as(usize, 1), num_walked); } -test "'.' and '..' in fs.Dir functions" { +test "'.' and '..' in Dir functions" { if (native_os == .windows and builtin.cpu.arch == .aarch64) { // https://github.com/ziglang/zig/issues/17134 return error.SkipZigTest; @@ -1923,33 +2002,36 @@ test "'.' and '..' in fs.Dir functions" { const rename_path = try ctx.transformPath("./subdir/../rename"); const update_path = try ctx.transformPath("./subdir/../update"); - try ctx.dir.makeDir(subdir_path); - try ctx.dir.access(subdir_path, .{}); - var created_subdir = try ctx.dir.openDir(subdir_path, .{}); - created_subdir.close(); + try ctx.dir.createDir(io, subdir_path, .default_dir); + try ctx.dir.access(io, subdir_path, .{}); + var created_subdir = try ctx.dir.openDir(io, subdir_path, .{}); + created_subdir.close(io); - const created_file = try ctx.dir.createFile(file_path, .{}); - created_file.close(); - try ctx.dir.access(file_path, .{}); + const created_file = try ctx.dir.createFile(io, file_path, .{}); + created_file.close(io); + try ctx.dir.access(io, file_path, .{}); - try ctx.dir.copyFile(file_path, ctx.dir, copy_path, .{}); - try ctx.dir.rename(copy_path, rename_path); - const renamed_file = try ctx.dir.openFile(rename_path, .{}); - renamed_file.close(); - try ctx.dir.deleteFile(rename_path); + try ctx.dir.copyFile(file_path, ctx.dir, copy_path, io, .{}); + try ctx.dir.rename(copy_path, ctx.dir, rename_path, io); + const renamed_file = try ctx.dir.openFile(io, rename_path, .{}); + renamed_file.close(io); + try ctx.dir.deleteFile(io, rename_path); - try ctx.dir.writeFile(.{ .sub_path = update_path, .data = "something" }); - var dir = ctx.dir.adaptToNewApi(); + try ctx.dir.writeFile(io, .{ .sub_path = update_path, .data = "something" }); + var dir = ctx.dir; const prev_status = try dir.updateFile(io, file_path, dir, update_path, .{}); - try testing.expectEqual(Io.Dir.PrevStatus.stale, prev_status); + try expectEqual(Dir.PrevStatus.stale, prev_status); - try ctx.dir.deleteDir(subdir_path); + try ctx.dir.deleteDir(io, subdir_path); } }.impl); } test "'.' and '..' in absolute functions" { if (native_os == .wasi) return error.SkipZigTest; + if (native_os == .openbsd) return error.SkipZigTest; + + const io = testing.io; var tmp = tmpDir(.{}); defer tmp.cleanup(); @@ -1958,83 +2040,71 @@ test "'.' and '..' in absolute functions" { defer arena.deinit(); const allocator = arena.allocator(); - const base_path = try tmp.dir.realpathAlloc(allocator, "."); + const base_path = try tmp.dir.realPathFileAlloc(io, ".", allocator); - const subdir_path = try fs.path.join(allocator, &.{ base_path, "./subdir" }); - try fs.makeDirAbsolute(subdir_path); - try fs.accessAbsolute(subdir_path, .{}); - var created_subdir = try fs.openDirAbsolute(subdir_path, .{}); - created_subdir.close(); + const subdir_path = try Dir.path.join(allocator, &.{ base_path, "./subdir" }); + try Dir.createDirAbsolute(io, subdir_path, .default_dir); + try Dir.accessAbsolute(io, subdir_path, .{}); + var created_subdir = try Dir.openDirAbsolute(io, subdir_path, .{}); + created_subdir.close(io); - const created_file_path = try fs.path.join(allocator, &.{ subdir_path, "../file" }); - const created_file = try fs.createFileAbsolute(created_file_path, .{}); - created_file.close(); - try fs.accessAbsolute(created_file_path, .{}); + const created_file_path = try Dir.path.join(allocator, &.{ subdir_path, "../file" }); + const created_file = try Dir.createFileAbsolute(io, created_file_path, .{}); + created_file.close(io); + try Dir.accessAbsolute(io, created_file_path, .{}); - const copied_file_path = try fs.path.join(allocator, &.{ subdir_path, "../copy" }); - try fs.copyFileAbsolute(created_file_path, copied_file_path, .{}); - const renamed_file_path = try fs.path.join(allocator, &.{ subdir_path, "../rename" }); - try fs.renameAbsolute(copied_file_path, renamed_file_path); - const renamed_file = try fs.openFileAbsolute(renamed_file_path, .{}); - renamed_file.close(); - try fs.deleteFileAbsolute(renamed_file_path); + const copied_file_path = try Dir.path.join(allocator, &.{ subdir_path, "../copy" }); + try Dir.copyFileAbsolute(created_file_path, copied_file_path, io, .{}); + const renamed_file_path = try Dir.path.join(allocator, &.{ subdir_path, "../rename" }); + try Dir.renameAbsolute(copied_file_path, renamed_file_path, io); + const renamed_file = try Dir.openFileAbsolute(io, renamed_file_path, .{}); + renamed_file.close(io); + try Dir.deleteFileAbsolute(io, renamed_file_path); - try fs.deleteDirAbsolute(subdir_path); + try Dir.deleteDirAbsolute(io, subdir_path); } test "chmod" { - if (native_os == .windows or native_os == .wasi) - return error.SkipZigTest; + if (native_os == .windows or native_os == .wasi) return; + + const io = testing.io; var tmp = tmpDir(.{}); defer tmp.cleanup(); - const file = try tmp.dir.createFile("test_file", .{ .mode = 0o600 }); - defer file.close(); - try testing.expectEqual(@as(File.Mode, 0o600), (try file.stat()).mode & 0o7777); + const file = try tmp.dir.createFile(io, "test_file", .{ .permissions = .fromMode(0o600) }); + defer file.close(io); + try expectEqual(0o600, (try file.stat(io)).permissions.toMode() & 0o7777); - try file.chmod(0o644); - try testing.expectEqual(@as(File.Mode, 0o644), (try file.stat()).mode & 0o7777); + try file.setPermissions(io, .fromMode(0o644)); + try expectEqual(0o644, (try file.stat(io)).permissions.toMode() & 0o7777); - try tmp.dir.makeDir("test_dir"); - var dir = try tmp.dir.openDir("test_dir", .{ .iterate = true }); - defer dir.close(); + try tmp.dir.createDir(io, "test_dir", .default_dir); + var dir = try tmp.dir.openDir(io, "test_dir", .{ .iterate = true }); + defer dir.close(io); - try dir.chmod(0o700); - try testing.expectEqual(@as(File.Mode, 0o700), (try dir.stat()).mode & 0o7777); + try dir.setPermissions(io, .fromMode(0o700)); + try expectEqual(0o700, (try dir.stat(io)).permissions.toMode() & 0o7777); } -test "chown" { +test "change ownership" { if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); - const file = try tmp.dir.createFile("test_file", .{}); - defer file.close(); - try file.chown(null, null); + const file = try tmp.dir.createFile(io, "test_file", .{}); + defer file.close(io); + try file.setOwner(io, null, null); - try tmp.dir.makeDir("test_dir"); + try tmp.dir.createDir(io, "test_dir", .default_dir); - var dir = try tmp.dir.openDir("test_dir", .{ .iterate = true }); - defer dir.close(); - try dir.chown(null, null); -} - -test "delete a setAsCwd directory on Windows" { - if (native_os != .windows) return error.SkipZigTest; - - var tmp = tmpDir(.{}); - // Set tmp dir as current working directory. - try tmp.dir.setAsCwd(); - tmp.dir.close(); - try testing.expectError(error.FileBusy, tmp.parent_dir.deleteTree(&tmp.sub_path)); - // Now set the parent dir as the current working dir for clean up. - try tmp.parent_dir.setAsCwd(); - try tmp.parent_dir.deleteTree(&tmp.sub_path); - // Close the parent "tmp" so we don't leak the HANDLE. - tmp.parent_dir.close(); + var dir = try tmp.dir.openDir(io, "test_dir", .{ .iterate = true }); + defer dir.close(io); + try dir.setOwner(io, null, null); } test "invalid UTF-8/WTF-8 paths" { @@ -2050,71 +2120,65 @@ test "invalid UTF-8/WTF-8 paths" { // This is both invalid UTF-8 and WTF-8, since \xFF is an invalid start byte const invalid_path = try ctx.transformPath("\xFF"); - try testing.expectError(expected_err, ctx.dir.openFile(invalid_path, .{})); + try expectError(expected_err, ctx.dir.openFile(io, invalid_path, .{})); - try testing.expectError(expected_err, ctx.dir.createFile(invalid_path, .{})); + try expectError(expected_err, ctx.dir.createFile(io, invalid_path, .{})); - try testing.expectError(expected_err, ctx.dir.makeDir(invalid_path)); + try expectError(expected_err, ctx.dir.createDir(io, invalid_path, .default_dir)); - try testing.expectError(expected_err, ctx.dir.makePath(invalid_path)); - try testing.expectError(expected_err, ctx.dir.makeOpenPath(invalid_path, .{})); + try expectError(expected_err, ctx.dir.createDirPath(io, invalid_path)); + try expectError(expected_err, ctx.dir.createDirPathOpen(io, invalid_path, .{})); - try testing.expectError(expected_err, ctx.dir.openDir(invalid_path, .{})); + try expectError(expected_err, ctx.dir.openDir(io, invalid_path, .{})); - try testing.expectError(expected_err, ctx.dir.deleteFile(invalid_path)); + try expectError(expected_err, ctx.dir.deleteFile(io, invalid_path)); - try testing.expectError(expected_err, ctx.dir.deleteDir(invalid_path)); + try expectError(expected_err, ctx.dir.deleteDir(io, invalid_path)); - try testing.expectError(expected_err, ctx.dir.rename(invalid_path, invalid_path)); + try expectError(expected_err, ctx.dir.rename(invalid_path, ctx.dir, invalid_path, io)); - try testing.expectError(expected_err, ctx.dir.symLink(invalid_path, invalid_path, .{})); - if (native_os == .wasi) { - try testing.expectError(expected_err, ctx.dir.symLinkWasi(invalid_path, invalid_path, .{})); - } + try expectError(expected_err, ctx.dir.symLink(io, invalid_path, invalid_path, .{})); - try testing.expectError(expected_err, ctx.dir.readLink(invalid_path, &[_]u8{})); - if (native_os == .wasi) { - try testing.expectError(expected_err, ctx.dir.readLinkWasi(invalid_path, &[_]u8{})); - } + try expectError(expected_err, ctx.dir.readLink(io, invalid_path, &[_]u8{})); - try testing.expectError(expected_err, ctx.dir.readFile(invalid_path, &[_]u8{})); - try testing.expectError(expected_err, ctx.dir.readFileAlloc(invalid_path, testing.allocator, .limited(0))); + try expectError(expected_err, ctx.dir.readFile(io, invalid_path, &[_]u8{})); + try expectError(expected_err, ctx.dir.readFileAlloc(io, invalid_path, testing.allocator, .limited(0))); - try testing.expectError(expected_err, ctx.dir.deleteTree(invalid_path)); - try testing.expectError(expected_err, ctx.dir.deleteTreeMinStackSize(invalid_path)); + try expectError(expected_err, ctx.dir.deleteTree(io, invalid_path)); + try expectError(expected_err, ctx.dir.deleteTreeMinStackSize(io, invalid_path)); - try testing.expectError(expected_err, ctx.dir.writeFile(.{ .sub_path = invalid_path, .data = "" })); + try expectError(expected_err, ctx.dir.writeFile(io, .{ .sub_path = invalid_path, .data = "" })); - try testing.expectError(expected_err, ctx.dir.access(invalid_path, .{})); + try expectError(expected_err, ctx.dir.access(io, invalid_path, .{})); - var dir = ctx.dir.adaptToNewApi(); - try testing.expectError(expected_err, dir.updateFile(io, invalid_path, dir, invalid_path, .{})); - try testing.expectError(expected_err, ctx.dir.copyFile(invalid_path, ctx.dir, invalid_path, .{})); + var dir = ctx.dir; + try expectError(expected_err, dir.updateFile(io, invalid_path, dir, invalid_path, .{})); + try expectError(expected_err, ctx.dir.copyFile(invalid_path, ctx.dir, invalid_path, io, .{})); - try testing.expectError(expected_err, ctx.dir.statFile(invalid_path)); + try expectError(expected_err, ctx.dir.statFile(io, invalid_path, .{})); if (native_os != .wasi) { - try testing.expectError(expected_err, ctx.dir.realpath(invalid_path, &[_]u8{})); - try testing.expectError(expected_err, ctx.dir.realpathAlloc(testing.allocator, invalid_path)); + try expectError(expected_err, ctx.dir.realPathFile(io, invalid_path, &[_]u8{})); + try expectError(expected_err, ctx.dir.realPathFileAlloc(io, invalid_path, testing.allocator)); } - try testing.expectError(expected_err, fs.rename(ctx.dir, invalid_path, ctx.dir, invalid_path)); + try expectError(expected_err, Dir.rename(ctx.dir, invalid_path, ctx.dir, invalid_path, io)); if (native_os != .wasi and ctx.path_type != .relative) { - try testing.expectError(expected_err, fs.copyFileAbsolute(invalid_path, invalid_path, .{})); - try testing.expectError(expected_err, fs.makeDirAbsolute(invalid_path)); - try testing.expectError(expected_err, fs.deleteDirAbsolute(invalid_path)); - try testing.expectError(expected_err, fs.renameAbsolute(invalid_path, invalid_path)); - try testing.expectError(expected_err, fs.openDirAbsolute(invalid_path, .{})); - try testing.expectError(expected_err, fs.openFileAbsolute(invalid_path, .{})); - try testing.expectError(expected_err, fs.accessAbsolute(invalid_path, .{})); - try testing.expectError(expected_err, fs.createFileAbsolute(invalid_path, .{})); - try testing.expectError(expected_err, fs.deleteFileAbsolute(invalid_path)); - try testing.expectError(expected_err, fs.deleteTreeAbsolute(invalid_path)); - var readlink_buf: [fs.max_path_bytes]u8 = undefined; - try testing.expectError(expected_err, fs.readLinkAbsolute(invalid_path, &readlink_buf)); - try testing.expectError(expected_err, fs.symLinkAbsolute(invalid_path, invalid_path, .{})); - try testing.expectError(expected_err, fs.realpathAlloc(testing.allocator, invalid_path)); + var buf: [Dir.max_path_bytes]u8 = undefined; + try expectError(expected_err, Dir.copyFileAbsolute(invalid_path, invalid_path, io, .{})); + try expectError(expected_err, Dir.createDirAbsolute(io, invalid_path, .default_dir)); + try expectError(expected_err, Dir.deleteDirAbsolute(io, invalid_path)); + try expectError(expected_err, Dir.renameAbsolute(invalid_path, invalid_path, io)); + try expectError(expected_err, Dir.openDirAbsolute(io, invalid_path, .{})); + try expectError(expected_err, Dir.openFileAbsolute(io, invalid_path, .{})); + try expectError(expected_err, Dir.accessAbsolute(io, invalid_path, .{})); + try expectError(expected_err, Dir.createFileAbsolute(io, invalid_path, .{})); + try expectError(expected_err, Dir.deleteFileAbsolute(io, invalid_path)); + try expectError(expected_err, Dir.readLinkAbsolute(io, invalid_path, &buf)); + try expectError(expected_err, Dir.symLinkAbsolute(io, invalid_path, invalid_path, .{})); + try expectError(expected_err, Dir.realPathFileAbsolute(io, invalid_path, &buf)); + try expectError(expected_err, Dir.realPathFileAbsoluteAlloc(io, invalid_path, testing.allocator)); } } }.impl); @@ -2128,15 +2192,15 @@ test "read file non vectored" { const contents = "hello, world!\n"; - const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); - defer file.close(); + const file = try tmp_dir.dir.createFile(io, "input.txt", .{ .read = true }); + defer file.close(io); { - var file_writer: std.fs.File.Writer = .init(file, &.{}); + var file_writer: File.Writer = .init(file, io, &.{}); try file_writer.interface.writeAll(contents); try file_writer.interface.flush(); } - var file_reader: std.Io.File.Reader = .initAdapted(file, io, &.{}); + var file_reader: std.Io.File.Reader = .init(file, io, &.{}); var write_buffer: [100]u8 = undefined; var w: std.Io.Writer = .fixed(&write_buffer); @@ -2148,8 +2212,8 @@ test "read file non vectored" { else => |e| return e, }; } - try testing.expectEqualStrings(contents, w.buffered()); - try testing.expectEqual(contents.len, i); + try expectEqualStrings(contents, w.buffered()); + try expectEqual(contents.len, i); } test "seek keeping partial buffer" { @@ -2160,18 +2224,18 @@ test "seek keeping partial buffer" { const contents = "0123456789"; - const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); - defer file.close(); + const file = try tmp_dir.dir.createFile(io, "input.txt", .{ .read = true }); + defer file.close(io); { - var file_writer: std.fs.File.Writer = .init(file, &.{}); + var file_writer: File.Writer = .init(file, io, &.{}); try file_writer.interface.writeAll(contents); try file_writer.interface.flush(); } var read_buffer: [3]u8 = undefined; - var file_reader: Io.File.Reader = .initAdapted(file, io, &read_buffer); + var file_reader: Io.File.Reader = .init(file, io, &read_buffer); - try testing.expectEqual(0, file_reader.logicalPos()); + try expectEqual(0, file_reader.logicalPos()); var buf: [4]u8 = undefined; try file_reader.interface.readSliceAll(&buf); @@ -2181,18 +2245,18 @@ test "seek keeping partial buffer" { return; } - try testing.expectEqual(4, file_reader.logicalPos()); - try testing.expectEqual(7, file_reader.pos); + try expectEqual(4, file_reader.logicalPos()); + try expectEqual(7, file_reader.pos); try file_reader.seekTo(6); - try testing.expectEqual(6, file_reader.logicalPos()); - try testing.expectEqual(7, file_reader.pos); + try expectEqual(6, file_reader.logicalPos()); + try expectEqual(7, file_reader.pos); - try testing.expectEqualStrings("0123", &buf); + try expectEqualStrings("0123", &buf); const n = try file_reader.interface.readSliceShort(&buf); - try testing.expectEqual(4, n); + try expectEqual(4, n); - try testing.expectEqualStrings("6789", &buf); + try expectEqualStrings("6789", &buf); } test "seekBy" { @@ -2201,16 +2265,16 @@ test "seekBy" { var tmp_dir = testing.tmpDir(.{}); defer tmp_dir.cleanup(); - try tmp_dir.dir.writeFile(.{ .sub_path = "blah.txt", .data = "let's test seekBy" }); - const f = try tmp_dir.dir.openFile("blah.txt", .{ .mode = .read_only }); - defer f.close(); + try tmp_dir.dir.writeFile(io, .{ .sub_path = "blah.txt", .data = "let's test seekBy" }); + const f = try tmp_dir.dir.openFile(io, "blah.txt", .{ .mode = .read_only }); + defer f.close(io); var reader = f.readerStreaming(io, &.{}); try reader.seekBy(2); var buffer: [20]u8 = undefined; const n = try reader.interface.readSliceShort(&buffer); - try testing.expectEqual(15, n); - try testing.expectEqualStrings("t's test seekBy", buffer[0..15]); + try expectEqual(15, n); + try expectEqualStrings("t's test seekBy", buffer[0..15]); } test "seekTo flushes buffered data" { @@ -2221,11 +2285,11 @@ test "seekTo flushes buffered data" { const contents = "data"; - const file = try tmp.dir.createFile("seek.bin", .{ .read = true }); - defer file.close(); + const file = try tmp.dir.createFile(io, "seek.bin", .{ .read = true }); + defer file.close(io); { var buf: [16]u8 = undefined; - var file_writer = std.fs.File.writer(file, &buf); + var file_writer = file.writer(io, &buf); try file_writer.interface.writeAll(contents); try file_writer.seekTo(8); @@ -2233,11 +2297,11 @@ test "seekTo flushes buffered data" { } var read_buffer: [16]u8 = undefined; - var file_reader: std.Io.File.Reader = .initAdapted(file, io, &read_buffer); + var file_reader: std.Io.File.Reader = .init(file, io, &read_buffer); var buf: [4]u8 = undefined; try file_reader.interface.readSliceAll(&buf); - try std.testing.expectEqualStrings(contents, &buf); + try expectEqualStrings(contents, &buf); } test "File.Writer sendfile with buffered contents" { @@ -2247,11 +2311,11 @@ test "File.Writer sendfile with buffered contents" { defer tmp_dir.cleanup(); { - try tmp_dir.dir.writeFile(.{ .sub_path = "a", .data = "bcd" }); - const in = try tmp_dir.dir.openFile("a", .{}); - defer in.close(); - const out = try tmp_dir.dir.createFile("b", .{}); - defer out.close(); + try tmp_dir.dir.writeFile(io, .{ .sub_path = "a", .data = "bcd" }); + const in = try tmp_dir.dir.openFile(io, "a", .{}); + defer in.close(io); + const out = try tmp_dir.dir.createFile(io, "b", .{}); + defer out.close(io); var in_buf: [2]u8 = undefined; var in_r = in.reader(io, &in_buf); @@ -2259,16 +2323,332 @@ test "File.Writer sendfile with buffered contents" { try in_r.interface.fill(2); var out_buf: [1]u8 = undefined; - var out_w = out.writerStreaming(&out_buf); + var out_w = out.writerStreaming(io, &out_buf); try out_w.interface.writeByte('a'); - try testing.expectEqual(3, try out_w.interface.sendFileAll(&in_r, .unlimited)); + try expectEqual(3, try out_w.interface.sendFileAll(&in_r, .unlimited)); try out_w.interface.flush(); } - var check = try tmp_dir.dir.openFile("b", .{}); - defer check.close(); + var check = try tmp_dir.dir.openFile(io, "b", .{}); + defer check.close(io); var check_buf: [4]u8 = undefined; var check_r = check.reader(io, &check_buf); - try testing.expectEqualStrings("abcd", try check_r.interface.take(4)); - try testing.expectError(error.EndOfStream, check_r.interface.takeByte()); + try expectEqualStrings("abcd", try check_r.interface.take(4)); + try expectError(error.EndOfStream, check_r.interface.takeByte()); +} + +test "readlink on Windows" { + if (native_os != .windows) return error.SkipZigTest; + + const io = testing.io; + + try testReadLinkWindows(io, "C:\\ProgramData", "C:\\Users\\All Users"); + try testReadLinkWindows(io, "C:\\Users\\Default", "C:\\Users\\Default User"); + try testReadLinkWindows(io, "C:\\Users", "C:\\Documents and Settings"); +} + +fn testReadLinkWindows(io: Io, target_path: []const u8, symlink_path: []const u8) !void { + var buffer: [Dir.max_path_bytes]u8 = undefined; + const len = try Dir.readLinkAbsolute(io, symlink_path, &buffer); + const given = buffer[0..len]; + try expect(mem.eql(u8, target_path, given)); +} + +test "readlinkat" { + const io = testing.io; + + var tmp = tmpDir(.{}); + defer tmp.cleanup(); + + // create file + try tmp.dir.writeFile(io, .{ .sub_path = "file.txt", .data = "nonsense" }); + + // create a symbolic link + tmp.dir.symLink(io, "file.txt", "link", .{}) catch |err| switch (err) { + error.AccessDenied => { + // Symlink requires admin privileges on windows, so this test can legitimately fail. + if (native_os == .windows) return error.SkipZigTest; + }, + else => |e| return e, + }; + + // read the link + var buffer: [Dir.max_path_bytes]u8 = undefined; + const read_link = buffer[0..try tmp.dir.readLink(io, "link", &buffer)]; + try expectEqualStrings("file.txt", read_link); +} + +test "fchmodat smoke test" { + if (!Io.File.Permissions.has_executable_bit) return error.SkipZigTest; + + const io = testing.io; + + var tmp = tmpDir(.{}); + defer tmp.cleanup(); + + try expectError(error.FileNotFound, tmp.dir.setFilePermissions(io, "regfile", .fromMode(0o666), .{})); + const file = try tmp.dir.createFile(io, "regfile", .{ + .exclusive = true, + .permissions = .fromMode(0o644), + }); + file.close(io); + + if ((builtin.cpu.arch == .riscv32 or builtin.cpu.arch.isLoongArch()) and + builtin.os.tag == .linux and !builtin.link_libc) + { + return error.SkipZigTest; // No `fstatat()`. + } + + try tmp.dir.symLink(io, "regfile", "symlink", .{}); + const sym_mode = blk: { + const st = try tmp.dir.statFile(io, "symlink", .{ .follow_symlinks = false }); + break :blk st.permissions.toMode() & 0b111_111_111; + }; + + try tmp.dir.setFilePermissions(io, "regfile", .fromMode(0o640), .{}); + try expectMode(io, tmp.dir, "regfile", .fromMode(0o640)); + try tmp.dir.setFilePermissions(io, "regfile", .fromMode(0o600), .{ .follow_symlinks = false }); + try expectMode(io, tmp.dir, "regfile", .fromMode(0o600)); + + try tmp.dir.setFilePermissions(io, "symlink", .fromMode(0o640), .{}); + try expectMode(io, tmp.dir, "regfile", .fromMode(0o640)); + try expectMode(io, tmp.dir, "symlink", .fromMode(sym_mode)); + + var test_link = true; + tmp.dir.setFilePermissions(io, "symlink", .fromMode(0o600), .{ .follow_symlinks = false }) catch |err| switch (err) { + error.OperationUnsupported => test_link = false, + else => |e| return e, + }; + if (test_link) try expectMode(io, tmp.dir, "symlink", .fromMode(0o600)); + try expectMode(io, tmp.dir, "regfile", .fromMode(0o640)); +} + +fn expectMode(io: Io, dir: Dir, file: []const u8, permissions: File.Permissions) !void { + const mode = permissions.toMode(); + const st = try dir.statFile(io, file, .{ .follow_symlinks = false }); + const found_mode = st.permissions.toMode(); + try expectEqual(mode, found_mode & 0b111_111_111); +} + +test "isatty" { + const io = testing.io; + + var tmp = tmpDir(.{}); + defer tmp.cleanup(); + + var file = try tmp.dir.createFile(io, "foo", .{}); + defer file.close(io); + + try expectEqual(false, try file.isTty(io)); +} + +test "read positional empty buffer" { + const io = testing.io; + + var tmp = tmpDir(.{}); + defer tmp.cleanup(); + + var file = try tmp.dir.createFile(io, "pread_empty", .{ .read = true }); + defer file.close(io); + + var buffer: [0]u8 = undefined; + try expectEqual(0, try file.readPositional(io, &.{&buffer}, 0)); +} + +test "write streaming empty buffer" { + const io = testing.io; + + var tmp = tmpDir(.{}); + defer tmp.cleanup(); + + var file = try tmp.dir.createFile(io, "write_empty", .{}); + defer file.close(io); + + const buffer: [0]u8 = .{}; + try file.writeStreamingAll(io, &buffer); +} + +test "write positional empty buffer" { + const io = testing.io; + + var tmp = tmpDir(.{}); + defer tmp.cleanup(); + + var file = try tmp.dir.createFile(io, "pwrite_empty", .{}); + defer file.close(io); + + const buffer: [0]u8 = .{}; + try expectEqual(0, try file.writePositional(io, &.{&buffer}, 0)); +} + +test "access smoke test" { + if (native_os == .wasi) return error.SkipZigTest; + if (native_os == .windows) return error.SkipZigTest; + if (native_os == .openbsd) return error.SkipZigTest; + + const io = testing.io; + + var tmp = tmpDir(.{}); + defer tmp.cleanup(); + + { + // Create some file using `open`. + const file = try tmp.dir.createFile(io, "some_file", .{ .read = true, .exclusive = true }); + file.close(io); + } + + { + // Try to access() the file + if (native_os == .windows) { + try tmp.dir.access(io, "some_file", .{}); + } else { + try tmp.dir.access(io, "some_file", .{ .read = true, .write = true }); + } + } + + { + // Try to access() a non-existent file - should fail with error.FileNotFound + try expectError(error.FileNotFound, tmp.dir.access(io, "some_other_file", .{})); + } + + { + // Create some directory + try tmp.dir.createDir(io, "some_dir", .default_dir); + } + + { + // Try to access() the directory + try tmp.dir.access(io, "some_dir", .{}); + } +} + +test "write streaming a long vector" { + const io = testing.io; + + var tmp = tmpDir(.{}); + defer tmp.cleanup(); + + var file = try tmp.dir.createFile(io, "pwritev", .{}); + defer file.close(io); + + var vecs: [2000][]const u8 = undefined; + for (&vecs) |*v| v.* = "a"; + + const n = try file.writePositional(io, &vecs, 0); + try expect(n <= vecs.len); +} + +test "open smoke test" { + if (native_os == .wasi) return error.SkipZigTest; + if (native_os == .windows) return error.SkipZigTest; + if (native_os == .openbsd) return error.SkipZigTest; + + // TODO verify file attributes using `fstat` + + var tmp = tmpDir(.{}); + defer tmp.cleanup(); + + const io = testing.io; + + { + // Create some file using `open`. + const file = try tmp.dir.createFile(io, "some_file", .{ .exclusive = true }); + file.close(io); + } + + // Try this again with the same flags. This op should fail with error.PathAlreadyExists. + try expectError( + error.PathAlreadyExists, + tmp.dir.createFile(io, "some_file", .{ .exclusive = true }), + ); + + { + // Try opening without exclusive flag. + const file = try tmp.dir.createFile(io, "some_file", .{}); + file.close(io); + } + + try expectError(error.NotDir, tmp.dir.openDir(io, "some_file", .{})); + try tmp.dir.createDir(io, "some_dir", .default_dir); + + { + const dir = try tmp.dir.openDir(io, "some_dir", .{}); + dir.close(io); + } + + // Try opening as file which should fail. + try expectError(error.IsDir, tmp.dir.openFile(io, "some_dir", .{ .allow_directory = false })); +} + +test "hard link with different directories" { + if (native_os == .wasi or native_os == .windows) return error.SkipZigTest; + + const io = testing.io; + + var tmp = tmpDir(.{}); + defer tmp.cleanup(); + + const target_name = "link-target"; + const link_name = "newlink"; + + const subdir = try tmp.dir.createDirPathOpen(io, "subdir", .{}); + + defer tmp.dir.deleteFile(io, target_name) catch {}; + try tmp.dir.writeFile(io, .{ .sub_path = target_name, .data = "example" }); + + // Test 1: link from file in subdir back up to target in parent directory + tmp.dir.hardLink(target_name, subdir, link_name, io, .{}) catch |err| switch (err) { + error.OperationUnsupported => return error.SkipZigTest, + else => |e| return e, + }; + + const efd = try tmp.dir.openFile(io, target_name, .{}); + defer efd.close(io); + + const nfd = try subdir.openFile(io, link_name, .{}); + defer nfd.close(io); + + { + const e_stat = try efd.stat(io); + const n_stat = try nfd.stat(io); + + try expectEqual(e_stat.inode, n_stat.inode); + try expectEqual(2, e_stat.nlink); + try expectEqual(2, n_stat.nlink); + } + + // Test 2: remove link + try subdir.deleteFile(io, link_name); + const e_stat = try efd.stat(io); + try expectEqual(1, e_stat.nlink); +} + +test "stat smoke test" { + if (native_os == .wasi and !builtin.link_libc) return error.SkipZigTest; + + const io = testing.io; + + var tmp = tmpDir(.{}); + defer tmp.cleanup(); + + // create dummy file + const contents = "nonsense"; + try tmp.dir.writeFile(io, .{ .sub_path = "file.txt", .data = contents }); + + // fetch file's info on the opened fd directly + const file = try tmp.dir.openFile(io, "file.txt", .{}); + const stat = try file.stat(io); + defer file.close(io); + + // now repeat but using directory handle instead + const statat = try tmp.dir.statFile(io, "file.txt", .{ .follow_symlinks = false }); + + try expectEqual(stat.inode, statat.inode); + try expectEqual(stat.nlink, statat.nlink); + try expectEqual(stat.size, statat.size); + try expectEqual(stat.permissions, statat.permissions); + try expectEqual(stat.kind, statat.kind); + try expectEqual(stat.atime, statat.atime); + try expectEqual(stat.mtime, statat.mtime); + try expectEqual(stat.ctime, statat.ctime); } diff --git a/lib/std/fs/wasi.zig b/lib/std/fs/wasi.zig deleted file mode 100644 index e17a852a9bb7..000000000000 --- a/lib/std/fs/wasi.zig +++ /dev/null @@ -1,55 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const mem = std.mem; -const math = std.math; -const fs = std.fs; -const assert = std.debug.assert; -const Allocator = mem.Allocator; -const wasi = std.os.wasi; -const fd_t = wasi.fd_t; -const prestat_t = wasi.prestat_t; - -pub const Preopens = struct { - // Indexed by file descriptor number. - names: []const []const u8, - - pub fn find(p: Preopens, name: []const u8) ?std.posix.fd_t { - for (p.names, 0..) |elem_name, i| { - if (mem.eql(u8, elem_name, name)) { - return @intCast(i); - } - } - return null; - } -}; - -pub fn preopensAlloc(gpa: Allocator) Allocator.Error!Preopens { - var names: std.ArrayList([]const u8) = .empty; - defer names.deinit(gpa); - - try names.ensureUnusedCapacity(gpa, 3); - - names.appendAssumeCapacity("stdin"); // 0 - names.appendAssumeCapacity("stdout"); // 1 - names.appendAssumeCapacity("stderr"); // 2 - while (true) { - const fd = @as(wasi.fd_t, @intCast(names.items.len)); - var prestat: prestat_t = undefined; - switch (wasi.fd_prestat_get(fd, &prestat)) { - .SUCCESS => {}, - .OPNOTSUPP, .BADF => return .{ .names = try names.toOwnedSlice(gpa) }, - else => @panic("fd_prestat_get: unexpected error"), - } - try names.ensureUnusedCapacity(gpa, 1); - // This length does not include a null byte. Let's keep it this way to - // gently encourage WASI implementations to behave properly. - const name_len = prestat.u.dir.pr_name_len; - const name = try gpa.alloc(u8, name_len); - errdefer gpa.free(name); - switch (wasi.fd_prestat_dir_name(fd, name.ptr, name.len)) { - .SUCCESS => {}, - else => @panic("fd_prestat_dir_name: unexpected error"), - } - names.appendAssumeCapacity(name); - } -} diff --git a/lib/std/gpu.zig b/lib/std/gpu.zig index d72d298b32d2..057ef4bd0b27 100644 --- a/lib/std/gpu.zig +++ b/lib/std/gpu.zig @@ -20,30 +20,6 @@ pub extern const global_invocation_id: @Vector(3, u32) addrspace(.input); pub extern const vertex_index: u32 addrspace(.input); pub extern const instance_index: u32 addrspace(.input); -/// Forms the main linkage for `input` and `output` address spaces. -/// `ptr` must be a reference to variable or struct field. -pub fn location(comptime ptr: anytype, comptime loc: u32) void { - asm volatile ( - \\OpDecorate %ptr Location $loc - : - : [ptr] "" (ptr), - [loc] "c" (loc), - ); -} - -/// Forms the main linkage for `input` and `output` address spaces. -/// `ptr` must be a reference to variable or struct field. -pub fn binding(comptime ptr: anytype, comptime set: u32, comptime bind: u32) void { - asm volatile ( - \\OpDecorate %ptr DescriptorSet $set - \\OpDecorate %ptr Binding $bind - : - : [ptr] "" (ptr), - [set] "c" (set), - [bind] "c" (bind), - ); -} - pub const ExecutionMode = union(Tag) { /// Sets origin of the framebuffer to the upper-left corner origin_upper_left, diff --git a/lib/std/hash/benchmark.zig b/lib/std/hash/benchmark.zig index 85a782340aa8..76538be4a8fb 100644 --- a/lib/std/hash/benchmark.zig +++ b/lib/std/hash/benchmark.zig @@ -1,7 +1,8 @@ // zig run -O ReleaseFast --zig-lib-dir ../.. benchmark.zig +const builtin = @import("builtin"); const std = @import("std"); -const builtin = @import("builtin"); +const Io = std.Io; const time = std.time; const Timer = time.Timer; const hash = std.hash; @@ -352,14 +353,15 @@ fn mode(comptime x: comptime_int) comptime_int { return if (builtin.mode == .Debug) x / 64 else x; } -pub fn main() !void { +pub fn main(init: std.process.Init) !void { + const io = init.io; + const arena = init.arena.allocator(); + var stdout_buffer: [0x100]u8 = undefined; - var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); + var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer); const stdout = &stdout_writer.interface; - var buffer: [1024]u8 = undefined; - var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]); - const args = try std.process.argsAlloc(fixed.allocator()); + const args = try init.minimal.args.toSlice(arena); var filter: ?[]u8 = ""; var count: usize = mode(128 * MiB); @@ -443,7 +445,7 @@ pub fn main() !void { const allocator = gpa.allocator(); inline for (hashes) |H| { - if (filter == null or std.mem.indexOf(u8, H.name, filter.?) != null) hash: { + if (filter == null or std.mem.find(u8, H.name, filter.?) != null) hash: { if (!test_iterative_only or H.has_iterative_api) { try stdout.print("{s}\n", .{H.name}); try stdout.flush(); diff --git a/lib/std/hash_map.zig b/lib/std/hash_map.zig index c8e2c70a1a27..58c9397a6b99 100644 --- a/lib/std/hash_map.zig +++ b/lib/std/hash_map.zig @@ -110,7 +110,7 @@ pub const StringIndexAdapter = struct { } pub fn hash(_: @This(), adapted_key: []const u8) u64 { - assert(mem.indexOfScalar(u8, adapted_key, 0) == null); + assert(mem.findScalar(u8, adapted_key, 0) == null); return hashString(adapted_key); } }; diff --git a/lib/std/heap.zig b/lib/std/heap.zig index 445b5da4550e..f584e3f72e46 100644 --- a/lib/std/heap.zig +++ b/lib/std/heap.zig @@ -141,7 +141,16 @@ test defaultQueryPageSize { assert(std.math.isPowerOfTwo(defaultQueryPageSize())); } -const CAllocator = struct { +/// A wrapper around the C memory allocation API which supports the full `Allocator` +/// interface, including arbitrary alignment. Simple `malloc` calls are used when +/// possible, but large requested alignments may require larger buffers in order to +/// satisfy the request. As well as `malloc`, `realloc`, and `free`, the extension +/// functions `malloc_usable_size` and `posix_memalign` are used when available. +pub const c_allocator: Allocator = .{ + .ptr = undefined, + .vtable = &c_allocator_impl.vtable, +}; +const c_allocator_impl = struct { comptime { if (!builtin.link_libc) { @compileError("C allocator is only available when linking against libc"); @@ -155,67 +164,55 @@ const CAllocator = struct { .free = free, }; - pub const supports_malloc_size = @TypeOf(malloc_size) != void; - pub const malloc_size = if (@TypeOf(c.malloc_size) != void) - c.malloc_size - else if (@TypeOf(c.malloc_usable_size) != void) - c.malloc_usable_size - else if (@TypeOf(c._msize) != void) - c._msize - else {}; - - pub const supports_posix_memalign = switch (builtin.os.tag) { - .dragonfly, .netbsd, .freebsd, .illumos, .openbsd, .linux, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos, .serenity => true, + const have_posix_memalign = switch (builtin.os.tag) { + .dragonfly, + .netbsd, + .freebsd, + .illumos, + .openbsd, + .linux, + .driverkit, + .ios, + .maccatalyst, + .macos, + .tvos, + .visionos, + .watchos, + .serenity, + => true, else => false, }; - fn getHeader(ptr: [*]u8) *[*]u8 { - return @ptrCast(@alignCast(ptr - @sizeOf(usize))); - } - - fn alignedAlloc(len: usize, alignment: Alignment) ?[*]u8 { - const alignment_bytes = alignment.toByteUnits(); - if (supports_posix_memalign) { - // The posix_memalign only accepts alignment values that are a - // multiple of the pointer size - const effective_alignment = @max(alignment_bytes, @sizeOf(usize)); - - var aligned_ptr: ?*anyopaque = undefined; - if (c.posix_memalign(&aligned_ptr, effective_alignment, len) != 0) - return null; - - return @ptrCast(aligned_ptr); + fn allocStrat(need_align: Alignment) union(enum) { + raw, + posix_memalign: if (have_posix_memalign) void else noreturn, + manual_align: if (have_posix_memalign) noreturn else void, + } { + // If `malloc` guarantees `need_align`, always prefer a raw allocation. + if (Alignment.compare(need_align, .lte, .of(c.max_align_t))) { + return .raw; } - - // Thin wrapper around regular malloc, overallocate to account for - // alignment padding and store the original malloc()'ed pointer before - // the aligned address. - const unaligned_ptr = @as([*]u8, @ptrCast(c.malloc(len + alignment_bytes - 1 + @sizeOf(usize)) orelse return null)); - const unaligned_addr = @intFromPtr(unaligned_ptr); - const aligned_addr = mem.alignForward(usize, unaligned_addr + @sizeOf(usize), alignment_bytes); - const aligned_ptr = unaligned_ptr + (aligned_addr - unaligned_addr); - getHeader(aligned_ptr).* = unaligned_ptr; - - return aligned_ptr; + // Use `posix_memalign` if available. Otherwise, we must manually align the allocation. + return if (have_posix_memalign) .posix_memalign else .manual_align; } - fn alignedFree(ptr: [*]u8) void { - if (supports_posix_memalign) { - return c.free(ptr); - } - - const unaligned_ptr = getHeader(ptr).*; - c.free(unaligned_ptr); - } - - fn alignedAllocSize(ptr: [*]u8) usize { - if (supports_posix_memalign) { - return CAllocator.malloc_size(ptr); - } - - const unaligned_ptr = getHeader(ptr).*; - const delta = @intFromPtr(ptr) - @intFromPtr(unaligned_ptr); - return CAllocator.malloc_size(unaligned_ptr) - delta; + /// If `allocStrat(a) == .manual_align`, an allocation looks like this: + /// + /// unaligned_ptr hdr_ptr aligned_ptr + /// v v v + /// +---------------+--------+--------------+ + /// | padding | header | usable bytes | + /// +---------------+--------+--------------+ + /// + /// * `unaligned_ptr` is the raw return value of `malloc`. + /// * `aligned_ptr` is computed by aligning `unaligned_ptr` forward; it is what `alloc` returns. + /// * `hdr_ptr` points to a pointer-sized header directly before the usable space. This header + /// contains the value `unaligned_ptr`, so that we can pass it to `free` later. This is + /// necessary because the width of the padding is unknown. + /// + /// This function accepts `aligned_ptr` and offsets it backwards to return `hdr_ptr`. + fn manualAlignHeader(aligned_ptr: [*]u8) *[*]u8 { + return @ptrCast(@alignCast(aligned_ptr - @sizeOf(usize))); } fn alloc( @@ -226,136 +223,125 @@ const CAllocator = struct { ) ?[*]u8 { _ = return_address; assert(len > 0); - return alignedAlloc(len, alignment); + switch (allocStrat(alignment)) { + .raw => { + // `std.c.max_align_t` isn't the whole story, because if `len` is smaller than + // every C type with alignment `max_align_t`, the allocation can be less-aligned. + // The implementation need only guarantee that any type of length `len` would be + // suitably aligned. + // + // For instance, if `len == 8` and `alignment == .@"16"`, then `malloc` may not + // fulfil this request, because there is necessarily no C type with 8-byte size + // but 16-byte alignment. + // + // In theory, the resulting rule here would be target-specific, but in practice, + // the smallest type with an alignment of `max_align_t` has the same size (it's + // usually `c_longdouble`), so we can just extend the allocation size up to the + // alignment of `max_align_t` if necessary. + const actual_len = @max(len, @alignOf(std.c.max_align_t)); + const ptr = c.malloc(actual_len) orelse return null; + assert(alignment.check(@intFromPtr(ptr))); + return @ptrCast(ptr); + }, + .posix_memalign => { + // The posix_memalign only accepts alignment values that are a + // multiple of the pointer size + const effective_alignment = @max(alignment.toByteUnits(), @sizeOf(usize)); + var aligned_ptr: ?*anyopaque = undefined; + if (c.posix_memalign(&aligned_ptr, effective_alignment, len) != 0) { + return null; + } + assert(alignment.check(@intFromPtr(aligned_ptr))); + return @ptrCast(aligned_ptr); + }, + .manual_align => { + // Overallocate to account for alignment padding and store the original pointer + // returned by `malloc` before the aligned address. + const padded_len = len + @sizeOf(usize) + alignment.toByteUnits() - 1; + const unaligned_ptr: [*]u8 = @ptrCast(c.malloc(padded_len) orelse return null); + const unaligned_addr = @intFromPtr(unaligned_ptr); + const aligned_addr = alignment.forward(unaligned_addr + @sizeOf(usize)); + const aligned_ptr = unaligned_ptr + (aligned_addr - unaligned_addr); + manualAlignHeader(aligned_ptr).* = unaligned_ptr; + return aligned_ptr; + }, + } } fn resize( _: *anyopaque, - buf: []u8, + memory: []u8, alignment: Alignment, new_len: usize, return_address: usize, ) bool { - _ = alignment; _ = return_address; - if (new_len <= buf.len) { - return true; + assert(new_len > 0); + if (new_len <= memory.len) { + return true; // in-place shrink always works } - if (CAllocator.supports_malloc_size) { - const full_len = alignedAllocSize(buf.ptr); - if (new_len <= full_len) { - return true; - } - } - return false; + const mallocSize = func: { + if (@TypeOf(c.malloc_size) != void) break :func c.malloc_size; + if (@TypeOf(c.malloc_usable_size) != void) break :func c.malloc_usable_size; + if (@TypeOf(c._msize) != void) break :func c._msize; + return false; // we don't know how much space is actually available + }; + const usable_len: usize = switch (allocStrat(alignment)) { + .raw, .posix_memalign => mallocSize(memory.ptr), + .manual_align => usable_len: { + const unaligned_ptr = manualAlignHeader(memory.ptr).*; + const full_len = mallocSize(unaligned_ptr); + const padding = @intFromPtr(memory.ptr) - @intFromPtr(unaligned_ptr); + break :usable_len full_len - padding; + }, + }; + return new_len <= usable_len; } fn remap( - context: *anyopaque, + ctx: *anyopaque, memory: []u8, alignment: Alignment, new_len: usize, return_address: usize, ) ?[*]u8 { - // realloc would potentially return a new allocation that does not - // respect the original alignment. - return if (resize(context, memory, alignment, new_len, return_address)) memory.ptr else null; + assert(new_len > 0); + // Prefer resizing in-place if possible, since `realloc` could be expensive even if legal. + if (resize(ctx, memory, alignment, new_len, return_address)) { + return memory.ptr; + } + switch (allocStrat(alignment)) { + .raw => { + // `malloc` and friends guarantee the required alignment, so we can try `realloc`. + // C only needs to respect `max_align_t` up to the allocation size due to object + // alignment rules. If necessary, extend the allocation size. + const actual_len = @max(new_len, @alignOf(std.c.max_align_t)); + const new_ptr = c.realloc(memory.ptr, actual_len) orelse return null; + assert(alignment.check(@intFromPtr(new_ptr))); + return @ptrCast(new_ptr); + }, + .posix_memalign, .manual_align => { + // `realloc` would potentially return a new allocation which does not respect + // the original alignment, so we can't do anything more. + return null; + }, + } } fn free( _: *anyopaque, - buf: []u8, + memory: []u8, alignment: Alignment, return_address: usize, ) void { - _ = alignment; _ = return_address; - alignedFree(buf.ptr); + switch (allocStrat(alignment)) { + .raw, .posix_memalign => c.free(memory.ptr), + .manual_align => c.free(manualAlignHeader(memory.ptr).*), + } } }; -/// Supports the full Allocator interface, including alignment, and exploiting -/// `malloc_usable_size` if available. For an allocator that directly calls -/// `malloc`/`free`, see `raw_c_allocator`. -pub const c_allocator: Allocator = .{ - .ptr = undefined, - .vtable = &CAllocator.vtable, -}; - -/// Asserts allocations are within `@alignOf(std.c.max_align_t)` and directly -/// calls `malloc`/`free`. Does not attempt to utilize `malloc_usable_size`. -/// This allocator is safe to use as the backing allocator with -/// `ArenaAllocator` for example and is more optimal in such a case than -/// `c_allocator`. -pub const raw_c_allocator: Allocator = .{ - .ptr = undefined, - .vtable = &raw_c_allocator_vtable, -}; -const raw_c_allocator_vtable: Allocator.VTable = .{ - .alloc = rawCAlloc, - .resize = rawCResize, - .remap = rawCRemap, - .free = rawCFree, -}; - -fn rawCAlloc( - context: *anyopaque, - len: usize, - alignment: Alignment, - return_address: usize, -) ?[*]u8 { - _ = context; - _ = return_address; - assert(alignment.compare(.lte, .of(std.c.max_align_t))); - // Note that this pointer cannot be aligncasted to max_align_t because if - // len is < max_align_t then the alignment can be smaller. For example, if - // max_align_t is 16, but the user requests 8 bytes, there is no built-in - // type in C that is size 8 and has 16 byte alignment, so the alignment may - // be 8 bytes rather than 16. Similarly if only 1 byte is requested, malloc - // is allowed to return a 1-byte aligned pointer. - return @ptrCast(c.malloc(len)); -} - -fn rawCResize( - context: *anyopaque, - memory: []u8, - alignment: Alignment, - new_len: usize, - return_address: usize, -) bool { - _ = context; - _ = memory; - _ = alignment; - _ = new_len; - _ = return_address; - return false; -} - -fn rawCRemap( - context: *anyopaque, - memory: []u8, - alignment: Alignment, - new_len: usize, - return_address: usize, -) ?[*]u8 { - _ = context; - _ = alignment; - _ = return_address; - return @ptrCast(c.realloc(memory.ptr, new_len)); -} - -fn rawCFree( - context: *anyopaque, - memory: []u8, - alignment: Alignment, - return_address: usize, -) void { - _ = context; - _ = alignment; - _ = return_address; - c.free(memory.ptr); -} - /// On operating systems that support memory mapping, this allocator makes a /// syscall directly for every allocation and free. /// @@ -508,12 +494,6 @@ test c_allocator { } } -test raw_c_allocator { - if (builtin.link_libc) { - try testAllocator(raw_c_allocator); - } -} - test smp_allocator { if (builtin.single_threaded) return; try testAllocator(smp_allocator); diff --git a/lib/std/heap/PageAllocator.zig b/lib/std/heap/PageAllocator.zig index f3e3857b581a..9bb5fba9f5ff 100644 --- a/lib/std/heap/PageAllocator.zig +++ b/lib/std/heap/PageAllocator.zig @@ -30,7 +30,8 @@ pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 { var base_addr: ?*anyopaque = null; var size: windows.SIZE_T = n; - var status = ntdll.NtAllocateVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), 0, &size, windows.MEM_COMMIT | windows.MEM_RESERVE, windows.PAGE_READWRITE); + const current_process = windows.GetCurrentProcess(); + var status = ntdll.NtAllocateVirtualMemory(current_process, @ptrCast(&base_addr), 0, &size, .{ .COMMIT = true, .RESERVE = true }, .{ .READWRITE = true }); if (status == SUCCESS and mem.isAligned(@intFromPtr(base_addr), alignment_bytes)) { return @ptrCast(base_addr); @@ -38,7 +39,7 @@ pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 { if (status == SUCCESS) { var region_size: windows.SIZE_T = 0; - _ = ntdll.NtFreeVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), ®ion_size, windows.MEM_RELEASE); + _ = ntdll.NtFreeVirtualMemory(current_process, @ptrCast(&base_addr), ®ion_size, .{ .RELEASE = true }); } const overalloc_len = n + alignment_bytes - page_size; @@ -47,7 +48,7 @@ pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 { base_addr = null; size = overalloc_len; - status = ntdll.NtAllocateVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), 0, &size, windows.MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, windows.PAGE_NOACCESS); + status = ntdll.NtAllocateVirtualMemory(current_process, @ptrCast(&base_addr), 0, &size, .{ .RESERVE = true, .RESERVE_PLACEHOLDER = true }, .{ .NOACCESS = true }); if (status != SUCCESS) return null; @@ -58,7 +59,7 @@ pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 { if (prefix_size > 0) { var prefix_base = base_addr; var prefix_size_param: windows.SIZE_T = prefix_size; - _ = ntdll.NtFreeVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&prefix_base), &prefix_size_param, windows.MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); + _ = ntdll.NtFreeVirtualMemory(current_process, @ptrCast(&prefix_base), &prefix_size_param, .{ .RELEASE = true, .PRESERVE_PLACEHOLDER = true }); } const suffix_start = aligned_addr + aligned_len; @@ -66,13 +67,13 @@ pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 { if (suffix_size > 0) { var suffix_base = @as(?*anyopaque, @ptrFromInt(suffix_start)); var suffix_size_param: windows.SIZE_T = suffix_size; - _ = ntdll.NtFreeVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&suffix_base), &suffix_size_param, windows.MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); + _ = ntdll.NtFreeVirtualMemory(current_process, @ptrCast(&suffix_base), &suffix_size_param, .{ .RELEASE = true, .PRESERVE_PLACEHOLDER = true }); } base_addr = @ptrFromInt(aligned_addr); size = aligned_len; - status = ntdll.NtAllocateVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), 0, &size, windows.MEM_COMMIT | MEM_PRESERVE_PLACEHOLDER, windows.PAGE_READWRITE); + status = ntdll.NtAllocateVirtualMemory(current_process, @ptrCast(&base_addr), 0, &size, .{ .COMMIT = true }, .{ .READWRITE = true }); if (status == SUCCESS) { return @ptrCast(base_addr); @@ -80,7 +81,7 @@ pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 { base_addr = @as(?*anyopaque, @ptrFromInt(aligned_addr)); size = aligned_len; - _ = ntdll.NtFreeVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), &size, windows.MEM_RELEASE); + _ = ntdll.NtFreeVirtualMemory(current_process, @ptrCast(&base_addr), &size, .{ .RELEASE = true }); return null; } @@ -145,7 +146,7 @@ pub fn unmap(memory: []align(page_size_min) u8) void { if (native_os == .windows) { var base_addr: ?*anyopaque = memory.ptr; var region_size: windows.SIZE_T = 0; - _ = ntdll.NtFreeVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), ®ion_size, windows.MEM_RELEASE); + _ = ntdll.NtFreeVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), ®ion_size, .{ .RELEASE = true }); } else { const page_aligned_len = mem.alignForward(usize, memory.len, std.heap.pageSize()); posix.munmap(memory.ptr[0..page_aligned_len]); @@ -166,7 +167,7 @@ pub fn realloc(uncasted_memory: []u8, new_len: usize, may_move: bool) ?[*]u8 { var decommit_addr: ?*anyopaque = @ptrFromInt(new_addr_end); var decommit_size: windows.SIZE_T = old_addr_end - new_addr_end; - _ = ntdll.NtAllocateVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&decommit_addr), 0, &decommit_size, windows.MEM_RESET, windows.PAGE_NOACCESS); + _ = ntdll.NtAllocateVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&decommit_addr), 0, &decommit_size, .{ .RESET = true }, .{ .NOACCESS = true }); } return memory.ptr; } diff --git a/lib/std/heap/debug_allocator.zig b/lib/std/heap/debug_allocator.zig index 44800097815a..c5abf6709c8d 100644 --- a/lib/std/heap/debug_allocator.zig +++ b/lib/std/heap/debug_allocator.zig @@ -84,7 +84,7 @@ const builtin = @import("builtin"); const StackTrace = std.builtin.StackTrace; const std = @import("std"); -const log = std.log.scoped(.gpa); +const log = std.log.scoped(.DebugAllocator); const math = std.math; const assert = std.debug.assert; const mem = std.mem; @@ -425,7 +425,6 @@ pub fn DebugAllocator(comptime config: Config) type { bucket: *BucketHeader, size_class_index: usize, used_bits_count: usize, - tty_config: std.Io.tty.Config, ) usize { const size_class = @as(usize, 1) << @as(Log2USize, @intCast(size_class_index)); const slot_count = slot_counts[size_class_index]; @@ -445,7 +444,7 @@ pub fn DebugAllocator(comptime config: Config) type { addr, std.debug.FormatStackTrace{ .stack_trace = stack_trace, - .tty_config = tty_config, + .terminal_mode = std.log.terminalMode(), }, }); leaks += 1; @@ -460,14 +459,12 @@ pub fn DebugAllocator(comptime config: Config) type { pub fn detectLeaks(self: *Self) usize { var leaks: usize = 0; - const tty_config = std.Io.tty.detectConfig(.stderr()); - for (self.buckets, 0..) |init_optional_bucket, size_class_index| { var optional_bucket = init_optional_bucket; const slot_count = slot_counts[size_class_index]; const used_bits_count = usedBitsCount(slot_count); while (optional_bucket) |bucket| { - leaks += detectLeaksInBucket(bucket, size_class_index, used_bits_count, tty_config); + leaks += detectLeaksInBucket(bucket, size_class_index, used_bits_count); optional_bucket = bucket.prev; } } @@ -480,7 +477,7 @@ pub fn DebugAllocator(comptime config: Config) type { @intFromPtr(large_alloc.bytes.ptr), std.debug.FormatStackTrace{ .stack_trace = stack_trace, - .tty_config = tty_config, + .terminal_mode = std.log.terminalMode(), }, }); leaks += 1; @@ -534,21 +531,21 @@ pub fn DebugAllocator(comptime config: Config) type { } fn reportDoubleFree(ret_addr: usize, alloc_stack_trace: StackTrace, free_stack_trace: StackTrace) void { + @branchHint(.cold); var addr_buf: [stack_n]usize = undefined; const second_free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = ret_addr }, &addr_buf); - const tty_config = std.Io.tty.detectConfig(.stderr()); log.err("Double free detected. Allocation: {f} First free: {f} Second free: {f}", .{ std.debug.FormatStackTrace{ .stack_trace = alloc_stack_trace, - .tty_config = tty_config, + .terminal_mode = std.log.terminalMode(), }, std.debug.FormatStackTrace{ .stack_trace = free_stack_trace, - .tty_config = tty_config, + .terminal_mode = std.log.terminalMode(), }, std.debug.FormatStackTrace{ .stack_trace = second_free_stack_trace, - .tty_config = tty_config, + .terminal_mode = std.log.terminalMode(), }, }); } @@ -588,19 +585,19 @@ pub fn DebugAllocator(comptime config: Config) type { } if (config.safety and old_mem.len != entry.value_ptr.bytes.len) { + @branchHint(.cold); var addr_buf: [stack_n]usize = undefined; const free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = ret_addr }, &addr_buf); - const tty_config = std.Io.tty.detectConfig(.stderr()); log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{ entry.value_ptr.bytes.len, old_mem.len, std.debug.FormatStackTrace{ .stack_trace = entry.value_ptr.getStackTrace(.alloc), - .tty_config = tty_config, + .terminal_mode = std.log.terminalMode(), }, std.debug.FormatStackTrace{ .stack_trace = free_stack_trace, - .tty_config = tty_config, + .terminal_mode = std.log.terminalMode(), }, }); } @@ -701,19 +698,19 @@ pub fn DebugAllocator(comptime config: Config) type { } if (config.safety and old_mem.len != entry.value_ptr.bytes.len) { + @branchHint(.cold); var addr_buf: [stack_n]usize = undefined; const free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = ret_addr }, &addr_buf); - const tty_config = std.Io.tty.detectConfig(.stderr()); log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{ entry.value_ptr.bytes.len, old_mem.len, std.debug.FormatStackTrace{ .stack_trace = entry.value_ptr.getStackTrace(.alloc), - .tty_config = tty_config, + .terminal_mode = std.log.terminalMode(), }, std.debug.FormatStackTrace{ .stack_trace = free_stack_trace, - .tty_config = tty_config, + .terminal_mode = std.log.terminalMode(), }, }); } @@ -935,32 +932,32 @@ pub fn DebugAllocator(comptime config: Config) type { var addr_buf: [stack_n]usize = undefined; const free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = return_address }, &addr_buf); if (old_memory.len != requested_size) { - const tty_config = std.Io.tty.detectConfig(.stderr()); + @branchHint(.cold); log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{ requested_size, old_memory.len, std.debug.FormatStackTrace{ .stack_trace = bucketStackTrace(bucket, slot_count, slot_index, .alloc), - .tty_config = tty_config, + .terminal_mode = std.log.terminalMode(), }, std.debug.FormatStackTrace{ .stack_trace = free_stack_trace, - .tty_config = tty_config, + .terminal_mode = std.log.terminalMode(), }, }); } if (alignment != slot_alignment) { - const tty_config = std.Io.tty.detectConfig(.stderr()); + @branchHint(.cold); log.err("Allocation alignment {d} does not match free alignment {d}. Allocation: {f} Free: {f}", .{ slot_alignment.toByteUnits(), alignment.toByteUnits(), std.debug.FormatStackTrace{ .stack_trace = bucketStackTrace(bucket, slot_count, slot_index, .alloc), - .tty_config = tty_config, + .terminal_mode = std.log.terminalMode(), }, std.debug.FormatStackTrace{ .stack_trace = free_stack_trace, - .tty_config = tty_config, + .terminal_mode = std.log.terminalMode(), }, }); } @@ -1044,32 +1041,32 @@ pub fn DebugAllocator(comptime config: Config) type { var addr_buf: [stack_n]usize = undefined; const free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = return_address }, &addr_buf); if (memory.len != requested_size) { - const tty_config = std.Io.tty.detectConfig(.stderr()); + @branchHint(.cold); log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{ requested_size, memory.len, std.debug.FormatStackTrace{ .stack_trace = bucketStackTrace(bucket, slot_count, slot_index, .alloc), - .tty_config = tty_config, + .terminal_mode = std.log.terminalMode(), }, std.debug.FormatStackTrace{ .stack_trace = free_stack_trace, - .tty_config = tty_config, + .terminal_mode = std.log.terminalMode(), }, }); } if (alignment != slot_alignment) { - const tty_config = std.Io.tty.detectConfig(.stderr()); + @branchHint(.cold); log.err("Allocation alignment {d} does not match free alignment {d}. Allocation: {f} Free: {f}", .{ slot_alignment.toByteUnits(), alignment.toByteUnits(), std.debug.FormatStackTrace{ .stack_trace = bucketStackTrace(bucket, slot_count, slot_index, .alloc), - .tty_config = tty_config, + .terminal_mode = std.log.terminalMode(), }, std.debug.FormatStackTrace{ .stack_trace = free_stack_trace, - .tty_config = tty_config, + .terminal_mode = std.log.terminalMode(), }, }); } @@ -1275,9 +1272,12 @@ test "shrink large object to large object" { } test "shrink large object to large object with larger alignment" { - if (!builtin.link_libc and builtin.os.tag == .wasi) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/22731 + if (builtin.os.tag == .wasi) { + // https://github.com/ziglang/zig/issues/22731 + return error.SkipZigTest; + } - var gpa = DebugAllocator(test_config){}; + var gpa: DebugAllocator(test_config) = .{}; defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak"); const allocator = gpa.allocator(); @@ -1350,7 +1350,10 @@ test "non-page-allocator backing allocator" { } test "realloc large object to larger alignment" { - if (!builtin.link_libc and builtin.os.tag == .wasi) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/22731 + if (builtin.os.tag == .wasi) { + // https://github.com/ziglang/zig/issues/22731 + return error.SkipZigTest; + } var gpa = DebugAllocator(test_config){}; defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak"); diff --git a/lib/std/http.zig b/lib/std/http.zig index eedd729576e0..291e22539b31 100644 --- a/lib/std/http.zig +++ b/lib/std/http.zig @@ -2,7 +2,7 @@ const builtin = @import("builtin"); const std = @import("std.zig"); const assert = std.debug.assert; const Writer = std.Io.Writer; -const File = std.fs.File; +const File = std.Io.File; pub const Client = @import("http/Client.zig"); pub const Server = @import("http/Server.zig"); @@ -44,8 +44,8 @@ pub const Method = enum { /// Actual behavior from clients may vary and should still be checked pub fn responseHasBody(m: Method) bool { return switch (m) { - .GET, .POST, .DELETE, .CONNECT, .OPTIONS, .PATCH => true, - .HEAD, .PUT, .TRACE => false, + .GET, .POST, .PUT, .DELETE, .CONNECT, .OPTIONS, .PATCH => true, + .HEAD, .TRACE => false, }; } diff --git a/lib/std/http/Client.zig b/lib/std/http/Client.zig index 431f239db30b..ddfcd96b6ab3 100644 --- a/lib/std/http/Client.zig +++ b/lib/std/http/Client.zig @@ -321,8 +321,8 @@ pub const Connection = struct { assert(base.ptr + alloc_len == socket_read_buffer.ptr + socket_read_buffer.len); @memcpy(host_buffer, remote_host.bytes); const tls: *Tls = @ptrCast(base); - var random_buffer: [176]u8 = undefined; - std.crypto.random.bytes(&random_buffer); + var random_buffer: [std.crypto.tls.Client.Options.entropy_len]u8 = undefined; + io.random(&random_buffer); tls.* = .{ .connection = .{ .client = client, @@ -529,7 +529,7 @@ pub const Response = struct { }; if (first_line[8] != ' ') return error.HttpHeadersInvalid; const status: http.Status = @enumFromInt(parseInt3(first_line[9..12])); - const reason = mem.trimLeft(u8, first_line[12..], " "); + const reason = mem.trimStart(u8, first_line[12..], " "); res.version = version; res.status = status; @@ -1307,7 +1307,7 @@ pub fn deinit(client: *Client) void { /// Asserts the client has no active connections. /// Uses `arena` for a few small allocations that must outlive the client, or /// at least until those fields are set to different values. -pub fn initDefaultProxies(client: *Client, arena: Allocator) !void { +pub fn initDefaultProxies(client: *Client, arena: Allocator, environ_map: *std.process.Environ.Map) !void { // Prevent any new connections from being created. client.connection_pool.mutex.lock(); defer client.connection_pool.mutex.unlock(); @@ -1315,27 +1315,26 @@ pub fn initDefaultProxies(client: *Client, arena: Allocator) !void { assert(client.connection_pool.used.first == null); // There are active requests. if (client.http_proxy == null) { - client.http_proxy = try createProxyFromEnvVar(arena, &.{ + client.http_proxy = try createProxyFromEnvVar(arena, environ_map, &.{ "http_proxy", "HTTP_PROXY", "all_proxy", "ALL_PROXY", }); } if (client.https_proxy == null) { - client.https_proxy = try createProxyFromEnvVar(arena, &.{ + client.https_proxy = try createProxyFromEnvVar(arena, environ_map, &.{ "https_proxy", "HTTPS_PROXY", "all_proxy", "ALL_PROXY", }); } } -fn createProxyFromEnvVar(arena: Allocator, env_var_names: []const []const u8) !?*Proxy { +fn createProxyFromEnvVar( + arena: Allocator, + environ_map: *std.process.Environ.Map, + env_var_names: []const []const u8, +) !?*Proxy { const content = for (env_var_names) |name| { - const content = std.process.getEnvVarOwned(arena, name) catch |err| switch (err) { - error.EnvironmentVariableNotFound => continue, - else => |e| return e, - }; - + const content = environ_map.get(name) orelse continue; if (content.len == 0) continue; - break content; } else return null; @@ -1473,6 +1472,8 @@ pub const ConnectUnixError = Allocator.Error || std.posix.SocketError || error{N /// /// This function is threadsafe. pub fn connectUnix(client: *Client, path: []const u8) ConnectUnixError!*Connection { + const io = client.io; + if (client.connection_pool.findConnection(.{ .host = path, .port = 0, @@ -1485,7 +1486,7 @@ pub fn connectUnix(client: *Client, path: []const u8) ConnectUnixError!*Connecti conn.* = .{ .data = undefined }; const stream = try Io.net.connectUnixSocket(path); - errdefer stream.close(); + errdefer stream.close(io); conn.data = .{ .stream = stream, @@ -1674,14 +1675,14 @@ pub fn request( if (std.debug.runtime_safety) { for (options.extra_headers) |header| { assert(header.name.len != 0); - assert(std.mem.indexOfScalar(u8, header.name, ':') == null); - assert(std.mem.indexOfPosLinear(u8, header.name, 0, "\r\n") == null); - assert(std.mem.indexOfPosLinear(u8, header.value, 0, "\r\n") == null); + assert(std.mem.findScalar(u8, header.name, ':') == null); + assert(std.mem.findPosLinear(u8, header.name, 0, "\r\n") == null); + assert(std.mem.findPosLinear(u8, header.value, 0, "\r\n") == null); } for (options.privileged_headers) |header| { assert(header.name.len != 0); - assert(std.mem.indexOfPosLinear(u8, header.name, 0, "\r\n") == null); - assert(std.mem.indexOfPosLinear(u8, header.value, 0, "\r\n") == null); + assert(std.mem.findPosLinear(u8, header.name, 0, "\r\n") == null); + assert(std.mem.findPosLinear(u8, header.value, 0, "\r\n") == null); } } diff --git a/lib/std/http/HeaderIterator.zig b/lib/std/http/HeaderIterator.zig index 518950a9ab39..0b20fd690636 100644 --- a/lib/std/http/HeaderIterator.zig +++ b/lib/std/http/HeaderIterator.zig @@ -5,17 +5,17 @@ is_trailer: bool, pub fn init(bytes: []const u8) HeaderIterator { return .{ .bytes = bytes, - .index = std.mem.indexOfPosLinear(u8, bytes, 0, "\r\n").? + 2, + .index = std.mem.findPosLinear(u8, bytes, 0, "\r\n").? + 2, .is_trailer = false, }; } pub fn next(it: *HeaderIterator) ?std.http.Header { - const end = std.mem.indexOfPosLinear(u8, it.bytes, it.index, "\r\n").?; + const end = std.mem.findPosLinear(u8, it.bytes, it.index, "\r\n").?; if (it.index == end) { // found the trailer boundary (\r\n\r\n) if (it.is_trailer) return null; - const next_end = std.mem.indexOfPosLinear(u8, it.bytes, end + 2, "\r\n") orelse + const next_end = std.mem.findPosLinear(u8, it.bytes, end + 2, "\r\n") orelse return null; var kv_it = std.mem.splitScalar(u8, it.bytes[end + 2 .. next_end], ':'); diff --git a/lib/std/http/Server.zig b/lib/std/http/Server.zig index 084f2f5855ec..7820ad6d0dc2 100644 --- a/lib/std/http/Server.zig +++ b/lib/std/http/Server.zig @@ -96,7 +96,7 @@ pub const Request = struct { if (first_line.len < 10) return error.HttpHeadersInvalid; - const method_end = mem.indexOfScalar(u8, first_line, ' ') orelse + const method_end = mem.findScalar(u8, first_line, ' ') orelse return error.HttpHeadersInvalid; const method = std.meta.stringToEnum(http.Method, first_line[0..method_end]) orelse @@ -338,9 +338,9 @@ pub const Request = struct { if (std.debug.runtime_safety) { for (options.extra_headers) |header| { assert(header.name.len != 0); - assert(std.mem.indexOfScalar(u8, header.name, ':') == null); - assert(std.mem.indexOfPosLinear(u8, header.name, 0, "\r\n") == null); - assert(std.mem.indexOfPosLinear(u8, header.value, 0, "\r\n") == null); + assert(std.mem.findScalar(u8, header.name, ':') == null); + assert(std.mem.findPosLinear(u8, header.name, 0, "\r\n") == null); + assert(std.mem.findPosLinear(u8, header.value, 0, "\r\n") == null); } } try writeExpectContinue(request); diff --git a/lib/std/http/test.zig b/lib/std/http/test.zig index cb973993ec95..73ca8ae74fb4 100644 --- a/lib/std/http/test.zig +++ b/lib/std/http/test.zig @@ -12,6 +12,8 @@ const expectEqualStrings = std.testing.expectEqualStrings; const expectError = std.testing.expectError; test "trailers" { + if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171879 + const io = std.testing.io; const test_server = try createTestServer(io, struct { fn run(test_server: *TestServer) anyerror!void { @@ -96,6 +98,8 @@ test "trailers" { } test "HTTP server handles a chunked transfer coding request" { + if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171879 + const io = std.testing.io; const test_server = try createTestServer(io, struct { fn run(test_server: *TestServer) anyerror!void { @@ -162,6 +166,8 @@ test "HTTP server handles a chunked transfer coding request" { } test "echo content server" { + if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171879 + const io = std.testing.io; const test_server = try createTestServer(io, struct { fn run(test_server: *TestServer) anyerror!void { @@ -250,6 +256,8 @@ test "echo content server" { } test "Server.Request.respondStreaming non-chunked, unknown content-length" { + if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171879 + const io = std.testing.io; if (builtin.os.tag == .windows) { @@ -326,6 +334,8 @@ test "Server.Request.respondStreaming non-chunked, unknown content-length" { } test "receiving arbitrary http headers from the client" { + if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171879 + const io = std.testing.io; const test_server = try createTestServer(io, struct { @@ -389,6 +399,8 @@ test "receiving arbitrary http headers from the client" { } test "general client/server API coverage" { + if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171879 + const io = std.testing.io; if (builtin.os.tag == .windows) { @@ -435,7 +447,7 @@ test "general client/server API coverage" { if (mem.startsWith(u8, target, "/get")) { var response = try request.respondStreaming(&.{}, .{ - .content_length = if (mem.indexOf(u8, target, "?chunked") == null) + .content_length = if (mem.find(u8, target, "?chunked") == null) 14 else null, @@ -882,6 +894,8 @@ test "general client/server API coverage" { } test "Server streams both reading and writing" { + if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171879 + const io = std.testing.io; const test_server = try createTestServer(io, struct { @@ -1125,17 +1139,32 @@ fn createTestServer(io: Io, S: type) !*TestServer { } const address = try net.IpAddress.parse("127.0.0.1", 0); - const test_server = try std.testing.allocator.create(TestServer); + + const gpa = std.testing.allocator; + + const test_server = try gpa.create(TestServer); + errdefer gpa.destroy(test_server); + + var net_server = try address.listen(io, .{ .reuse_address = true }); + errdefer net_server.deinit(io); + + // populate `test_server` first so `S.run` can use it test_server.* = .{ .io = io, - .net_server = try address.listen(io, .{ .reuse_address = true }), + .net_server = net_server, .shutting_down = false, - .server_thread = try std.Thread.spawn(.{}, S.run, .{test_server}), + .server_thread = undefined, // set below }; + + test_server.server_thread = try .spawn(.{}, S.run, .{test_server}); + errdefer comptime unreachable; + return test_server; } test "redirect to different connection" { + if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171879 + const io = std.testing.io; const test_server_new = try createTestServer(io, struct { fn run(test_server: *TestServer) anyerror!void { diff --git a/lib/std/json/Scanner.zig b/lib/std/json/Scanner.zig index 61bc474c790e..74a96d017e02 100644 --- a/lib/std/json/Scanner.zig +++ b/lib/std/json/Scanner.zig @@ -1758,7 +1758,7 @@ fn appendSlice(list: *std.array_list.Managed(u8), buf: []const u8, max_value_len /// This function will not give meaningful results on non-numeric input. pub fn isNumberFormattedLikeAnInteger(value: []const u8) bool { if (std.mem.eql(u8, value, "-0")) return false; - return std.mem.indexOfAny(u8, value, ".eE") == null; + return std.mem.findAny(u8, value, ".eE") == null; } test { diff --git a/lib/std/json/dynamic.zig b/lib/std/json/dynamic.zig index c3cccd1a9157..e38ea9cb17e1 100644 --- a/lib/std/json/dynamic.zig +++ b/lib/std/json/dynamic.zig @@ -47,10 +47,9 @@ pub const Value = union(enum) { } pub fn dump(v: Value) void { - const w, _ = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); - - json.Stringify.value(v, .{}, w) catch return; + const stderr = std.debug.lockStderr(&.{}, null); + defer std.debug.unlockStderr(); + json.Stringify.value(v, .{}, &stderr.file_writer.interface) catch return; } pub fn jsonStringify(value: @This(), jws: anytype) !void { diff --git a/lib/std/log.zig b/lib/std/log.zig index 9568f9ba5211..df11fe205b4c 100644 --- a/lib/std/log.zig +++ b/lib/std/log.zig @@ -15,7 +15,7 @@ //! //! For an example implementation of the `logFn` function, see `defaultLog`, //! which is the default implementation. It outputs to stderr, using color if -//! the detected `std.Io.tty.Config` supports it. Its output looks like this: +//! supported. Its output looks like this: //! ``` //! error: this is an error //! error(scope): this is an error with a non-default scope @@ -80,6 +80,14 @@ pub fn logEnabled(comptime level: Level, comptime scope: @EnumLiteral()) bool { return @intFromEnum(level) <= @intFromEnum(std.options.log_level); } +pub const terminalMode = std.options.logTerminalMode; + +pub fn defaultTerminalMode() std.Io.Terminal.Mode { + const stderr = std.debug.lockStderr(&.{}).terminal(); + std.debug.unlockStderr(); + return stderr.mode; +} + /// The default implementation for the log function. Custom log functions may /// forward log messages to this function. /// @@ -92,25 +100,33 @@ pub fn defaultLog( args: anytype, ) void { var buffer: [64]u8 = undefined; - const stderr, const ttyconf = std.debug.lockStderrWriter(&buffer); - defer std.debug.unlockStderrWriter(); - ttyconf.setColor(stderr, switch (level) { + const stderr = std.debug.lockStderr(&buffer).terminal(); + defer std.debug.unlockStderr(); + return defaultLogFileTerminal(level, scope, format, args, stderr) catch {}; +} + +pub fn defaultLogFileTerminal( + comptime level: Level, + comptime scope: @EnumLiteral(), + comptime format: []const u8, + args: anytype, + t: std.Io.Terminal, +) std.Io.Writer.Error!void { + t.setColor(switch (level) { .err => .red, .warn => .yellow, .info => .green, .debug => .magenta, }) catch {}; - ttyconf.setColor(stderr, .bold) catch {}; - stderr.writeAll(level.asText()) catch return; - ttyconf.setColor(stderr, .reset) catch {}; - ttyconf.setColor(stderr, .dim) catch {}; - ttyconf.setColor(stderr, .bold) catch {}; - if (scope != .default) { - stderr.print("({s})", .{@tagName(scope)}) catch return; - } - stderr.writeAll(": ") catch return; - ttyconf.setColor(stderr, .reset) catch {}; - stderr.print(format ++ "\n", args) catch return; + t.setColor(.bold) catch {}; + try t.writer.writeAll(level.asText()); + t.setColor(.reset) catch {}; + t.setColor(.dim) catch {}; + t.setColor(.bold) catch {}; + if (scope != .default) try t.writer.print("({t})", .{scope}); + try t.writer.writeAll(": "); + t.setColor(.reset) catch {}; + try t.writer.print(format ++ "\n", args); } /// Returns a scoped logging namespace that logs all messages using the scope diff --git a/lib/std/macho.zig b/lib/std/macho.zig index 7b8894e981b6..aecb5765946e 100644 --- a/lib/std/macho.zig +++ b/lib/std/macho.zig @@ -825,7 +825,7 @@ pub const section_64 = extern struct { }; fn parseName(name: *const [16]u8) []const u8 { - const len = mem.indexOfScalar(u8, name, @as(u8, 0)) orelse name.len; + const len = mem.findScalar(u8, name, @as(u8, 0)) orelse name.len; return name[0..len]; } diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index 5a00947ac365..e3dcb8d71dbb 100644 --- a/lib/std/math/big/int.zig +++ b/lib/std/math/big/int.zig @@ -17,6 +17,27 @@ const Endian = std.builtin.Endian; const Signedness = std.builtin.Signedness; const native_endian = builtin.cpu.arch.endian(); +// Comptime-computed constants for supported bases (2 - 36) +// all values are set to 0 for bases 0 - 1, to make it possible to +// access a constant for a given base b using `constants.value[b]` +const Constants = struct { + // big_bases[b] is the biggest power of b that fit in a single Limb + // i.e. big_bases[b] = b^k < 2^@bitSizeOf(Limb) and b^(k+1) >= 2^@bitSizeOf(Limb) + big_bases: [37]Limb, + // digits_per_limb[b] is the value of k used in the previous field + digits_per_limb: [37]u8, +}; +const constants: Constants = blk: { + @setEvalBranchQuota(2000); + var digits_per_limb = [_]u8{0} ** 37; + var bases = [_]Limb{0} ** 37; + for (2..37) |base| { + digits_per_limb[base] = @intCast(math.log(Limb, base, math.maxInt(Limb))); + bases[base] = std.math.pow(Limb, base, digits_per_limb[base]); + } + break :blk Constants{ .big_bases = bases, .digits_per_limb = digits_per_limb }; +}; + /// Returns the number of limbs needed to store `scalar`, which must be a /// primitive integer or float value. /// Note: A comptime-known upper bound of this value that may be used @@ -329,23 +350,15 @@ pub const Mutable = struct { /// not allowed (e.g. 0x43 should simply be 43). Underscores in the input string are /// ignored and can be used as digit separators. /// - /// Asserts there is enough memory for the value in `self.limbs`. An upper bound on number of limbs can + /// There must be enough memory for the value in `self.limbs`. An upper bound on number of limbs can /// be determined with `calcSetStringLimbCount`. /// Asserts the base is in the range [2, 36]. /// /// Returns an error if the value has invalid digits for the requested base. - /// - /// `limbs_buffer` is used for temporary storage. The size required can be found with - /// `calcSetStringLimbsBufferLen`. - /// - /// If `allocator` is provided, it will be used for temporary storage to improve - /// multiplication performance. `error.OutOfMemory` is handled with a fallback algorithm. pub fn setString( self: *Mutable, base: u8, value: []const u8, - limbs_buffer: []Limb, - allocator: ?Allocator, ) error{InvalidCharacter}!void { assert(base >= 2); assert(base <= 36); @@ -357,18 +370,41 @@ pub const Mutable = struct { i += 1; } - const ap_base: Const = .{ .limbs = &[_]Limb{base}, .positive = true }; - self.set(0); + @memset(self.limbs, 0); + self.len = 1; + var limb: Limb = 0; + var j: usize = 0; for (value[i..]) |ch| { if (ch == '_') { continue; } const d = try std.fmt.charToDigit(ch, base); - const ap_d: Const = .{ .limbs = &[_]Limb{d}, .positive = true }; - - self.mul(self.toConst(), ap_base, limbs_buffer, allocator); - self.add(self.toConst(), ap_d); + limb *= base; + limb += d; + j += 1; + + if (j == constants.digits_per_limb[base]) { + const len = @min(self.len + 1, self.limbs.len); + // r = a * b = a + a * (b - 1) + // we assert when self.limbs is not large enough to store the number + assert(!llmulLimb(.add, self.limbs[0..len], self.limbs[0..len], constants.big_bases[base] - 1)); + assert(lladdcarry(self.limbs[0..len], self.limbs[0..len], &[1]Limb{limb}) == 0); + + if (self.limbs.len > self.len and self.limbs[self.len] != 0) + self.len += 1; + j = 0; + limb = 0; + } + } + if (j > 0) { + const len = @min(self.len + 1, self.limbs.len); + // we assert when self.limbs is not large enough to store the number + assert(!llmulLimb(.add, self.limbs[0..len], self.limbs[0..len], math.pow(Limb, base, j) - 1)); + assert(lladdcarry(self.limbs[0..len], self.limbs[0..len], &[1]Limb{limb}) == 0); + + if (self.limbs.len > self.len and self.limbs[self.len] != 0) + self.len += 1; } self.positive = positive; } @@ -1658,8 +1694,8 @@ pub const Mutable = struct { // Handle trailing zero-words of divisor/dividend. These are not handled in the following // algorithms. // Note, there must be a non-zero limb for either. - // const x_trailing = std.mem.indexOfScalar(Limb, x.limbs[0..x.len], 0).?; - // const y_trailing = std.mem.indexOfScalar(Limb, y.limbs[0..y.len], 0).?; + // const x_trailing = std.mem.findScalar(Limb, x.limbs[0..x.len], 0).?; + // const y_trailing = std.mem.findScalar(Limb, y.limbs[0..y.len], 0).?; const x_trailing = for (x.limbs[0..x.len], 0..) |xi, i| { if (xi != 0) break i; @@ -2081,7 +2117,7 @@ pub const Const = struct { for (self.limbs[0..self.limbs.len]) |limb| { std.debug.print("{x} ", .{limb}); } - std.debug.print("len={} positive={}\n", .{ self.len, self.positive }); + std.debug.print("len={} positive={}\n", .{ self.limbs.len, self.positive }); } pub fn abs(self: Const) Const { @@ -2884,10 +2920,8 @@ pub const Managed = struct { pub fn setString(self: *Managed, base: u8, value: []const u8) !void { if (base < 2 or base > 36) return error.InvalidBase; try self.ensureCapacity(calcSetStringLimbCount(base, value.len)); - const limbs_buffer = try self.allocator.alloc(Limb, calcSetStringLimbsBufferLen(base, value.len)); - defer self.allocator.free(limbs_buffer); var m = self.toMutable(); - try m.setString(base, value, limbs_buffer, self.allocator); + try m.setString(base, value); self.setMetadata(m.positive, m.len); } @@ -2979,7 +3013,9 @@ pub const Managed = struct { /// /// Returns an error if memory could not be allocated. pub fn addScalar(r: *Managed, a: *const Managed, scalar: anytype) Allocator.Error!void { - try r.ensureAddScalarCapacity(a.toConst(), scalar); + const needed = @max(a.len(), calcLimbLen(scalar)) + 1; + const aliased = limbsAliasDistinct(r, a); + try r.ensureAliasAwareCapacity(needed, aliased); var m = r.toMutable(); m.addScalar(a.toConst(), scalar); r.setMetadata(m.positive, m.len); @@ -2991,7 +3027,9 @@ pub const Managed = struct { /// /// Returns an error if memory could not be allocated. pub fn add(r: *Managed, a: *const Managed, b: *const Managed) Allocator.Error!void { - try r.ensureAddCapacity(a.toConst(), b.toConst()); + const needed = @max(a.len(), b.len()) + 1; + const aliased = limbsAliasDistinct(r, a) or limbsAliasDistinct(r, b); + try r.ensureAliasAwareCapacity(needed, aliased); var m = r.toMutable(); m.add(a.toConst(), b.toConst()); r.setMetadata(m.positive, m.len); @@ -3009,7 +3047,9 @@ pub const Managed = struct { signedness: Signedness, bit_count: usize, ) Allocator.Error!bool { - try r.ensureTwosCompCapacity(bit_count); + const aliased = limbsAliasDistinct(r, a) or limbsAliasDistinct(r, b); + const needed = calcTwosCompLimbCount(bit_count); + try r.ensureAliasAwareCapacity(needed, aliased); var m = r.toMutable(); const wrapped = m.addWrap(a.toConst(), b.toConst(), signedness, bit_count); r.setMetadata(m.positive, m.len); @@ -3022,7 +3062,9 @@ pub const Managed = struct { /// /// Returns an error if memory could not be allocated. pub fn addSat(r: *Managed, a: *const Managed, b: *const Managed, signedness: Signedness, bit_count: usize) Allocator.Error!void { - try r.ensureTwosCompCapacity(bit_count); + const aliased = limbsAliasDistinct(r, a) or limbsAliasDistinct(r, b); + const needed = calcTwosCompLimbCount(bit_count); + try r.ensureAliasAwareCapacity(needed, aliased); var m = r.toMutable(); m.addSat(a.toConst(), b.toConst(), signedness, bit_count); r.setMetadata(m.positive, m.len); @@ -3034,7 +3076,9 @@ pub const Managed = struct { /// /// Returns an error if memory could not be allocated. pub fn sub(r: *Managed, a: *const Managed, b: *const Managed) !void { - try r.ensureCapacity(@max(a.len(), b.len()) + 1); + const aliased = limbsAliasDistinct(r, a) or limbsAliasDistinct(r, b); + const needed = @max(a.len(), b.len()) + 1; + try r.ensureAliasAwareCapacity(needed, aliased); var m = r.toMutable(); m.sub(a.toConst(), b.toConst()); r.setMetadata(m.positive, m.len); @@ -3052,7 +3096,9 @@ pub const Managed = struct { signedness: Signedness, bit_count: usize, ) Allocator.Error!bool { - try r.ensureTwosCompCapacity(bit_count); + const aliased = limbsAliasDistinct(r, a) or limbsAliasDistinct(r, b); + const needed = calcTwosCompLimbCount(bit_count); + try r.ensureAliasAwareCapacity(needed, aliased); var m = r.toMutable(); const wrapped = m.subWrap(a.toConst(), b.toConst(), signedness, bit_count); r.setMetadata(m.positive, m.len); @@ -3071,7 +3117,9 @@ pub const Managed = struct { signedness: Signedness, bit_count: usize, ) Allocator.Error!void { - try r.ensureTwosCompCapacity(bit_count); + const aliased = limbsAliasDistinct(r, a) or limbsAliasDistinct(r, b); + const needed = calcTwosCompLimbCount(bit_count); + try r.ensureAliasAwareCapacity(needed, aliased); var m = r.toMutable(); m.subSat(a.toConst(), b.toConst(), signedness, bit_count); r.setMetadata(m.positive, m.len); @@ -3090,7 +3138,9 @@ pub const Managed = struct { alias_count += 1; if (rma.limbs.ptr == b.limbs.ptr) alias_count += 1; - try rma.ensureMulCapacity(a.toConst(), b.toConst()); + const needed = a.len() + b.len() + 1; + const capacity_alias = limbsAliasDistinct(rma, a) or limbsAliasDistinct(rma, b); + try rma.ensureAliasAwareCapacity(needed, capacity_alias); var m = rma.toMutable(); if (alias_count == 0) { m.mulNoAlias(a.toConst(), b.toConst(), rma.allocator); @@ -3122,8 +3172,9 @@ pub const Managed = struct { alias_count += 1; if (rma.limbs.ptr == b.limbs.ptr) alias_count += 1; - - try rma.ensureTwosCompCapacity(bit_count); + const needed = calcTwosCompLimbCount(bit_count); + const capacity_alias = limbsAliasDistinct(rma, a) or limbsAliasDistinct(rma, b); + try rma.ensureAliasAwareCapacity(needed, capacity_alias); var m = rma.toMutable(); if (alias_count == 0) { m.mulWrapNoAlias(a.toConst(), b.toConst(), signedness, bit_count, rma.allocator); @@ -3140,16 +3191,40 @@ pub const Managed = struct { try r.ensureCapacity(calcTwosCompLimbCount(bit_count)); } - pub fn ensureAddScalarCapacity(r: *Managed, a: Const, scalar: anytype) !void { - try r.ensureCapacity(@max(a.limbs.len, calcLimbLen(scalar)) + 1); + /// True if two distinct `Managed` parameters share the same limbs buffer. + /// + /// We specifically exclude the case where `@intFromPtr(a) == @intFromPtr(b)` (same object). + /// When both pointers refer to the same `Managed` instance, `ensureCapacity` can reallocate + /// the buffer (if needed) without creating dangling pointers for that object. + fn limbsAliasDistinct(a: *const Managed, b: *const Managed) bool { + return @intFromPtr(a) != @intFromPtr(b) and a.limbs.ptr == b.limbs.ptr; + } + + /// When `aliased` is false (including when both pointers refer to the same object), + /// `ensureCapacity` may reallocate; callers who rely on distinct `Managed` instances + /// aliasing must ensure capacity before aliasing. + /// See https://github.com/ziglang/zig/issues/6167 + fn ensureAliasAwareCapacity(r: *Managed, needed: usize, aliased: bool) !void { + if (aliased) { + assert(needed <= r.limbs.len); + } else { + try r.ensureCapacity(needed); + } + } + + /// Use this function before doing `addScalar` if some of your parameters alias each other + pub fn ensureAddScalarCapacity(r: *Managed, a: *const Managed, scalar: anytype) !void { + try r.ensureCapacity(@max(a.len(), calcLimbLen(scalar)) + 1); } - pub fn ensureAddCapacity(r: *Managed, a: Const, b: Const) !void { - try r.ensureCapacity(@max(a.limbs.len, b.limbs.len) + 1); + /// Use this function before doing `add` if some of your parameters alias each other + pub fn ensureAddCapacity(r: *Managed, a: *const Managed, b: *const Managed) !void { + try r.ensureCapacity(@max(a.len(), b.len()) + 1); } - pub fn ensureMulCapacity(rma: *Managed, a: Const, b: Const) !void { - try rma.ensureCapacity(a.limbs.len + b.limbs.len + 1); + /// Use this function before doing `mul` if some of your parameters alias each other + pub fn ensureMulCapacity(rma: *Managed, a: *const Managed, b: *const Managed) !void { + try rma.ensureCapacity(a.len() + b.len() + 1); } /// q = a / b (rem r) @@ -3158,8 +3233,10 @@ pub const Managed = struct { /// /// Returns an error if memory could not be allocated. pub fn divFloor(q: *Managed, r: *Managed, a: *const Managed, b: *const Managed) !void { - try q.ensureCapacity(a.len()); - try r.ensureCapacity(b.len()); + const q_alias = limbsAliasDistinct(q, a) or limbsAliasDistinct(q, b); + const r_alias = limbsAliasDistinct(r, a) or limbsAliasDistinct(r, b); + try q.ensureAliasAwareCapacity(a.len(), q_alias); + try r.ensureAliasAwareCapacity(b.len(), r_alias); var mq = q.toMutable(); var mr = r.toMutable(); const limbs_buffer = try q.allocator.alloc(Limb, calcDivLimbsBufferLen(a.len(), b.len())); @@ -3175,8 +3252,10 @@ pub const Managed = struct { /// /// Returns an error if memory could not be allocated. pub fn divTrunc(q: *Managed, r: *Managed, a: *const Managed, b: *const Managed) !void { - try q.ensureCapacity(a.len()); - try r.ensureCapacity(b.len()); + const q_alias = limbsAliasDistinct(q, a) or limbsAliasDistinct(q, b); + const r_alias = limbsAliasDistinct(r, a) or limbsAliasDistinct(r, b); + try q.ensureAliasAwareCapacity(a.len(), q_alias); + try r.ensureAliasAwareCapacity(b.len(), r_alias); var mq = q.toMutable(); var mr = r.toMutable(); const limbs_buffer = try q.allocator.alloc(Limb, calcDivLimbsBufferLen(a.len(), b.len())); @@ -3189,7 +3268,9 @@ pub const Managed = struct { /// r = a << shift, in other words, r = a * 2^shift /// r and a may alias. pub fn shiftLeft(r: *Managed, a: *const Managed, shift: usize) !void { - try r.ensureCapacity(a.len() + (shift / limb_bits) + 1); + const aliased = limbsAliasDistinct(r, a); + const needed = a.len() + (shift / limb_bits) + 1; + try r.ensureAliasAwareCapacity(needed, aliased); var m = r.toMutable(); m.shiftLeft(a.toConst(), shift); r.setMetadata(m.positive, m.len); @@ -3198,7 +3279,9 @@ pub const Managed = struct { /// r = a <<| shift with 2s-complement saturating semantics. /// r and a may alias. pub fn shiftLeftSat(r: *Managed, a: *const Managed, shift: usize, signedness: Signedness, bit_count: usize) !void { - try r.ensureTwosCompCapacity(bit_count); + const aliased = limbsAliasDistinct(r, a); + const needed = calcTwosCompLimbCount(bit_count); + try r.ensureAliasAwareCapacity(needed, aliased); var m = r.toMutable(); m.shiftLeftSat(a.toConst(), shift, signedness, bit_count); r.setMetadata(m.positive, m.len); @@ -3220,7 +3303,9 @@ pub const Managed = struct { return; } - try r.ensureCapacity(a.len() - (shift / limb_bits)); + const aliased = limbsAliasDistinct(r, a); + const needed = a.len() - (shift / limb_bits); + try r.ensureAliasAwareCapacity(needed, aliased); var m = r.toMutable(); m.shiftRight(a.toConst(), shift); r.setMetadata(m.positive, m.len); @@ -3229,7 +3314,9 @@ pub const Managed = struct { /// r = ~a under 2s-complement wrapping semantics. /// r and a may alias. pub fn bitNotWrap(r: *Managed, a: *const Managed, signedness: Signedness, bit_count: usize) !void { - try r.ensureTwosCompCapacity(bit_count); + const aliased = limbsAliasDistinct(r, a); + const needed = calcTwosCompLimbCount(bit_count); + try r.ensureAliasAwareCapacity(needed, aliased); var m = r.toMutable(); m.bitNotWrap(a.toConst(), signedness, bit_count); r.setMetadata(m.positive, m.len); @@ -3239,7 +3326,9 @@ pub const Managed = struct { /// /// a and b are zero-extended to the longer of a or b. pub fn bitOr(r: *Managed, a: *const Managed, b: *const Managed) !void { - try r.ensureCapacity(@max(a.len(), b.len())); + const aliased = limbsAliasDistinct(r, a) or limbsAliasDistinct(r, b); + const needed = @max(a.len(), b.len()); + try r.ensureAliasAwareCapacity(needed, aliased); var m = r.toMutable(); m.bitOr(a.toConst(), b.toConst()); r.setMetadata(m.positive, m.len); @@ -3251,7 +3340,8 @@ pub const Managed = struct { if (b.isPositive()) b.len() else if (a.isPositive()) a.len() else a.len() + 1 else if (a.isPositive()) a.len() else if (b.isPositive()) b.len() else b.len() + 1; - try r.ensureCapacity(cap); + const aliased = limbsAliasDistinct(r, a) or limbsAliasDistinct(r, b); + try r.ensureAliasAwareCapacity(cap, aliased); var m = r.toMutable(); m.bitAnd(a.toConst(), b.toConst()); r.setMetadata(m.positive, m.len); @@ -3260,7 +3350,8 @@ pub const Managed = struct { /// r = a ^ b pub fn bitXor(r: *Managed, a: *const Managed, b: *const Managed) !void { const cap = @max(a.len(), b.len()) + @intFromBool(a.isPositive() != b.isPositive()); - try r.ensureCapacity(cap); + const aliased = limbsAliasDistinct(r, a) or limbsAliasDistinct(r, b); + try r.ensureAliasAwareCapacity(cap, aliased); var m = r.toMutable(); m.bitXor(a.toConst(), b.toConst()); @@ -3272,7 +3363,9 @@ pub const Managed = struct { /// /// rma's allocator is used for temporary storage to boost multiplication performance. pub fn gcd(rma: *Managed, x: *const Managed, y: *const Managed) !void { - try rma.ensureCapacity(@min(x.len(), y.len())); + const aliased = limbsAliasDistinct(rma, x) or limbsAliasDistinct(rma, y); + const needed = @min(x.len(), y.len()); + try rma.ensureAliasAwareCapacity(needed, aliased); var m = rma.toMutable(); var limbs_buffer = std.array_list.Managed(Limb).init(rma.allocator); defer limbs_buffer.deinit(); @@ -3283,18 +3376,20 @@ pub const Managed = struct { /// r = a * a pub fn sqr(rma: *Managed, a: *const Managed) !void { const needed_limbs = 2 * a.len() + 1; - - if (rma.limbs.ptr == a.limbs.ptr) { - var m = try Managed.initCapacity(rma.allocator, needed_limbs); - errdefer m.deinit(); - var m_mut = m.toMutable(); - m_mut.sqrNoAlias(a.toConst(), rma.allocator); - m.setMetadata(m_mut.positive, m_mut.len); - - rma.deinit(); - rma.swap(&m); + const capacity_alias = limbsAliasDistinct(rma, a); + const same_buffer = rma.limbs.ptr == a.limbs.ptr; + try rma.ensureAliasAwareCapacity(needed_limbs, capacity_alias); + + if (same_buffer) { + const a_len = a.len(); + const tmp = try rma.allocator.alloc(Limb, a_len); + defer rma.allocator.free(tmp); + @memcpy(tmp[0..a_len], a.limbs[0..a_len]); + const a_const = Const{ .limbs = tmp[0..a_len], .positive = a.isPositive() }; + var rma_mut = rma.toMutable(); + rma_mut.sqrNoAlias(a_const, rma.allocator); + rma.setMetadata(rma_mut.positive, rma_mut.len); } else { - try rma.ensureCapacity(needed_limbs); var rma_mut = rma.toMutable(); rma_mut.sqrNoAlias(a.toConst(), rma.allocator); rma.setMetadata(rma_mut.positive, rma_mut.len); @@ -3303,21 +3398,23 @@ pub const Managed = struct { pub fn pow(rma: *Managed, a: *const Managed, b: u32) !void { const needed_limbs = calcPowLimbsBufferLen(a.bitCountAbs(), b); + const capacity_alias = limbsAliasDistinct(rma, a); + const same_buffer = rma.limbs.ptr == a.limbs.ptr; + try rma.ensureAliasAwareCapacity(needed_limbs, capacity_alias); const limbs_buffer = try rma.allocator.alloc(Limb, needed_limbs); defer rma.allocator.free(limbs_buffer); - if (rma.limbs.ptr == a.limbs.ptr) { - var m = try Managed.initCapacity(rma.allocator, needed_limbs); - errdefer m.deinit(); - var m_mut = m.toMutable(); - m_mut.pow(a.toConst(), b, limbs_buffer); - m.setMetadata(m_mut.positive, m_mut.len); - - rma.deinit(); - rma.swap(&m); + if (same_buffer) { + const a_len = a.len(); + const tmp = try rma.allocator.alloc(Limb, a_len); + defer rma.allocator.free(tmp); + @memcpy(tmp[0..a_len], a.limbs[0..a_len]); + const a_const = Const{ .limbs = tmp[0..a_len], .positive = a.isPositive() }; + var rma_mut = rma.toMutable(); + rma_mut.pow(a_const, b, limbs_buffer); + rma.setMetadata(rma_mut.positive, rma_mut.len); } else { - try rma.ensureCapacity(needed_limbs); var rma_mut = rma.toMutable(); rma_mut.pow(a.toConst(), b, limbs_buffer); rma.setMetadata(rma_mut.positive, rma_mut.len); @@ -3327,6 +3424,7 @@ pub const Managed = struct { /// r = ⌊√a⌋ pub fn sqrt(rma: *Managed, a: *const Managed) !void { const bit_count = a.bitCountAbs(); + const aliased = limbsAliasDistinct(rma, a); if (bit_count == 0) { try rma.set(0); @@ -3342,7 +3440,8 @@ pub const Managed = struct { const limbs_buffer = try rma.allocator.alloc(Limb, needed_limbs); defer rma.allocator.free(limbs_buffer); - try rma.ensureCapacity((a.len() - 1) / 2 + 1); + const needed = (a.len() - 1) / 2 + 1; + try rma.ensureAliasAwareCapacity(needed, aliased); var m = rma.toMutable(); m.sqrt(a.toConst(), limbs_buffer); rma.setMetadata(m.positive, m.len); @@ -3350,7 +3449,9 @@ pub const Managed = struct { /// r = truncate(Int(signedness, bit_count), a) pub fn truncate(r: *Managed, a: *const Managed, signedness: Signedness, bit_count: usize) !void { - try r.ensureCapacity(calcTwosCompLimbCount(bit_count)); + const aliased = limbsAliasDistinct(r, a); + const needed = calcTwosCompLimbCount(bit_count); + try r.ensureAliasAwareCapacity(needed, aliased); var m = r.toMutable(); m.truncate(a.toConst(), signedness, bit_count); r.setMetadata(m.positive, m.len); @@ -3358,7 +3459,9 @@ pub const Managed = struct { /// r = saturate(Int(signedness, bit_count), a) pub fn saturate(r: *Managed, a: *const Managed, signedness: Signedness, bit_count: usize) !void { - try r.ensureCapacity(calcTwosCompLimbCount(bit_count)); + const aliased = limbsAliasDistinct(r, a); + const needed = calcTwosCompLimbCount(bit_count); + try r.ensureAliasAwareCapacity(needed, aliased); var m = r.toMutable(); m.saturate(a.toConst(), signedness, bit_count); r.setMetadata(m.positive, m.len); @@ -3367,7 +3470,9 @@ pub const Managed = struct { /// r = @popCount(a) with 2s-complement semantics. /// r and a may be aliases. pub fn popCount(r: *Managed, a: *const Managed, bit_count: usize) !void { - try r.ensureCapacity(calcTwosCompLimbCount(bit_count)); + const aliased = limbsAliasDistinct(r, a); + const needed = calcTwosCompLimbCount(bit_count); + try r.ensureAliasAwareCapacity(needed, aliased); var m = r.toMutable(); m.popCount(a.toConst(), bit_count); r.setMetadata(m.positive, m.len); @@ -3596,6 +3701,7 @@ fn llmulaccKaratsuba( /// r = r (op) a. /// The result is computed modulo `r.len`. fn llaccum(comptime op: AccOp, r: []Limb, a: []const Limb) void { + assert(!slicesOverlap(r, a) or @intFromPtr(r.ptr) <= @intFromPtr(a.ptr)); if (op == .sub) { _ = llsubcarry(r, r, a); return; @@ -3665,6 +3771,8 @@ fn llmulaccLong(comptime op: AccOp, r: []Limb, a: []const Limb, b: []const Limb) /// The result is computed modulo `r.len`. /// Returns whether the operation overflowed. fn llmulLimb(comptime op: AccOp, acc: []Limb, y: []const Limb, xi: Limb) bool { + assert(!slicesOverlap(acc, y) or @intFromPtr(acc.ptr) <= @intFromPtr(y.ptr)); + if (xi == 0) { return false; } @@ -3727,6 +3835,8 @@ fn llsubcarry(r: []Limb, a: []const Limb, b: []const Limb) Limb { assert(a.len != 0 and b.len != 0); assert(a.len >= b.len); assert(r.len >= a.len); + assert(!slicesOverlap(r, a) or @intFromPtr(r.ptr) <= @intFromPtr(a.ptr)); + assert(!slicesOverlap(r, b) or @intFromPtr(r.ptr) <= @intFromPtr(b.ptr)); var i: usize = 0; var borrow: Limb = 0; @@ -3758,6 +3868,8 @@ fn lladdcarry(r: []Limb, a: []const Limb, b: []const Limb) Limb { assert(a.len != 0 and b.len != 0); assert(a.len >= b.len); assert(r.len >= a.len); + assert(!slicesOverlap(r, a) or @intFromPtr(r.ptr) <= @intFromPtr(a.ptr)); + assert(!slicesOverlap(r, b) or @intFromPtr(r.ptr) <= @intFromPtr(b.ptr)); var i: usize = 0; var carry: Limb = 0; diff --git a/lib/std/math/big/int_test.zig b/lib/std/math/big/int_test.zig index eee6a0c7cee2..34dec3fdde9d 100644 --- a/lib/std/math/big/int_test.zig +++ b/lib/std/math/big/int_test.zig @@ -583,7 +583,9 @@ test "bitcount + sizeInBaseUpperBound" { try testing.expect(a.sizeInBaseUpperBound(2) >= 32); try testing.expect(a.sizeInBaseUpperBound(10) >= 10); - try a.shiftLeft(&a, 5000); + const shift = 5000; + try a.ensureCapacity(a.len() + (shift / @bitSizeOf(Limb)) + 1); + try a.shiftLeft(&a, shift); try testing.expectEqual(5032, a.bitCountAbs()); try testing.expect(a.sizeInBaseUpperBound(2) >= 5032); a.setSign(false); @@ -737,7 +739,7 @@ test "string to" { defer testing.allocator.free(as); const es = "120317241209124781241290847124"; - try testing.expect(mem.eql(u8, as, es)); + try testing.expectEqualSlices(u8, es, as); } test "string to base base error" { @@ -755,7 +757,7 @@ test "string to base 2" { defer testing.allocator.free(as); const es = "-1011"; - try testing.expect(mem.eql(u8, as, es)); + try testing.expectEqualSlices(u8, es, as); } test "string to base 16" { @@ -766,7 +768,7 @@ test "string to base 16" { defer testing.allocator.free(as); const es = "efffffff00000001eeeeeeefaaaaaaab"; - try testing.expect(mem.eql(u8, as, es)); + try testing.expectEqualSlices(u8, es, as); } test "string to base 36" { @@ -777,7 +779,7 @@ test "string to base 36" { defer testing.allocator.free(as); const es = "fifvthrv1mzt79ez9"; - try testing.expect(mem.eql(u8, as, es)); + try testing.expectEqualSlices(u8, es, as); } test "neg string to" { @@ -788,7 +790,7 @@ test "neg string to" { defer testing.allocator.free(as); const es = "-123907434"; - try testing.expect(mem.eql(u8, as, es)); + try testing.expectEqualSlices(u8, es, as); } test "zero string to" { @@ -799,7 +801,7 @@ test "zero string to" { defer testing.allocator.free(as); const es = "0"; - try testing.expect(mem.eql(u8, as, es)); + try testing.expectEqualSlices(u8, es, as); } test "clone" { @@ -2380,7 +2382,9 @@ test "truncate negative multi to single" { test "truncate multi unsigned many" { var a = try Managed.initSet(testing.allocator, 1); defer a.deinit(); - try a.shiftLeft(&a, 1023); + const shift = 1023; + try a.ensureCapacity(a.len() + (shift / @bitSizeOf(Limb)) + 1); + try a.shiftLeft(&a, shift); var b = try Managed.init(testing.allocator); defer b.deinit(); @@ -3263,7 +3267,7 @@ test "regression test for 1 limb overflow with alias" { var b = try Managed.initSet(testing.allocator, 12200160415121876738); defer b.deinit(); - try a.ensureAddCapacity(a.toConst(), b.toConst()); + try a.ensureAddCapacity(&a, &b); try a.add(&a, &b); try testing.expectEqual(.eq, a.toConst().orderAgainstScalar(19740274219868223167)); @@ -3277,7 +3281,7 @@ test "regression test for realloc with alias" { var b = try Managed.initSet(testing.allocator, 9079598147510263717870894449029933369491131786514446266146); defer b.deinit(); - try a.ensureAddCapacity(a.toConst(), b.toConst()); + try a.ensureAddCapacity(&a, &b); try a.add(&a, &b); try testing.expectEqual(.eq, a.toConst().orderAgainstScalar(14691098406862188148944207245954912110548093601382197697835)); @@ -3404,26 +3408,26 @@ test "big int conversion read twos complement with padding" { var bit_count: usize = 12 * 8 + 1; a.toConst().writeTwosComplement(buffer1[0..13], .little); - try testing.expect(std.mem.eql(u8, buffer1, &[_]u8{ 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0xaa, 0xaa, 0xaa })); + try testing.expectEqualSlices(u8, &[_]u8{ 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0xaa, 0xaa, 0xaa }, buffer1); a.toConst().writeTwosComplement(buffer1[0..13], .big); - try testing.expect(std.mem.eql(u8, buffer1, &[_]u8{ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xaa, 0xaa, 0xaa })); + try testing.expectEqualSlices(u8, &[_]u8{ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xaa, 0xaa, 0xaa }, buffer1); a.toConst().writeTwosComplement(buffer1[0..16], .little); - try testing.expect(std.mem.eql(u8, buffer1, &[_]u8{ 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0x0, 0x0 })); + try testing.expectEqualSlices(u8, &[_]u8{ 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0x0, 0x0 }, buffer1); a.toConst().writeTwosComplement(buffer1[0..16], .big); - try testing.expect(std.mem.eql(u8, buffer1, &[_]u8{ 0x0, 0x0, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd })); + try testing.expectEqualSlices(u8, &[_]u8{ 0x0, 0x0, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd }, buffer1); @memset(buffer1, 0xaa); try a.set(-0x01_02030405_06070809_0a0b0c0d); bit_count = 12 * 8 + 2; a.toConst().writeTwosComplement(buffer1[0..13], .little); - try testing.expect(std.mem.eql(u8, buffer1, &[_]u8{ 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xaa, 0xaa, 0xaa })); + try testing.expectEqualSlices(u8, &[_]u8{ 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xaa, 0xaa, 0xaa }, buffer1); a.toConst().writeTwosComplement(buffer1[0..13], .big); - try testing.expect(std.mem.eql(u8, buffer1, &[_]u8{ 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf3, 0xaa, 0xaa, 0xaa })); + try testing.expectEqualSlices(u8, &[_]u8{ 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf3, 0xaa, 0xaa, 0xaa }, buffer1); a.toConst().writeTwosComplement(buffer1[0..16], .little); - try testing.expect(std.mem.eql(u8, buffer1, &[_]u8{ 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xff, 0xff })); + try testing.expectEqualSlices(u8, &[_]u8{ 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xff, 0xff }, buffer1); a.toConst().writeTwosComplement(buffer1[0..16], .big); - try testing.expect(std.mem.eql(u8, buffer1, &[_]u8{ 0xff, 0xff, 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf3 })); + try testing.expectEqualSlices(u8, &[_]u8{ 0xff, 0xff, 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf3 }, buffer1); } test "big int write twos complement +/- zero" { @@ -3438,13 +3442,13 @@ test "big int write twos complement +/- zero" { // Test zero m.toConst().writeTwosComplement(buffer1[0..13], .little); - try testing.expect(std.mem.eql(u8, buffer1, &(([_]u8{0} ** 13) ++ ([_]u8{0xaa} ** 3)))); + try testing.expectEqualSlices(u8, &(([_]u8{0} ** 13) ++ ([_]u8{0xaa} ** 3)), buffer1); m.toConst().writeTwosComplement(buffer1[0..13], .big); - try testing.expect(std.mem.eql(u8, buffer1, &(([_]u8{0} ** 13) ++ ([_]u8{0xaa} ** 3)))); + try testing.expectEqualSlices(u8, &(([_]u8{0} ** 13) ++ ([_]u8{0xaa} ** 3)), buffer1); m.toConst().writeTwosComplement(buffer1[0..16], .little); - try testing.expect(std.mem.eql(u8, buffer1, &(([_]u8{0} ** 16)))); + try testing.expectEqualSlices(u8, &(([_]u8{0} ** 16)), buffer1); m.toConst().writeTwosComplement(buffer1[0..16], .big); - try testing.expect(std.mem.eql(u8, buffer1, &(([_]u8{0} ** 16)))); + try testing.expectEqualSlices(u8, &(([_]u8{0} ** 16)), buffer1); @memset(buffer1, 0xaa); m.positive = false; @@ -3452,13 +3456,13 @@ test "big int write twos complement +/- zero" { // Test negative zero m.toConst().writeTwosComplement(buffer1[0..13], .little); - try testing.expect(std.mem.eql(u8, buffer1, &(([_]u8{0} ** 13) ++ ([_]u8{0xaa} ** 3)))); + try testing.expectEqualSlices(u8, &(([_]u8{0} ** 13) ++ ([_]u8{0xaa} ** 3)), buffer1); m.toConst().writeTwosComplement(buffer1[0..13], .big); - try testing.expect(std.mem.eql(u8, buffer1, &(([_]u8{0} ** 13) ++ ([_]u8{0xaa} ** 3)))); + try testing.expectEqualSlices(u8, &(([_]u8{0} ** 13) ++ ([_]u8{0xaa} ** 3)), buffer1); m.toConst().writeTwosComplement(buffer1[0..16], .little); - try testing.expect(std.mem.eql(u8, buffer1, &(([_]u8{0} ** 16)))); + try testing.expectEqualSlices(u8, &(([_]u8{0} ** 16)), buffer1); m.toConst().writeTwosComplement(buffer1[0..16], .big); - try testing.expect(std.mem.eql(u8, buffer1, &(([_]u8{0} ** 16)))); + try testing.expectEqualSlices(u8, &(([_]u8{0} ** 16)), buffer1); } test "big int conversion write twos complement with padding" { @@ -3692,6 +3696,7 @@ test "mul multi-multi alias r with a and b" { var a = try Managed.initSet(testing.allocator, 2 * maxInt(Limb)); defer a.deinit(); + try a.ensureMulCapacity(&a, &a); try a.mul(&a, &a); var want = try Managed.initSet(testing.allocator, 4 * maxInt(Limb) * maxInt(Limb)); @@ -3816,7 +3821,7 @@ test "(BigInt) positive" { const b_fmt = try std.fmt.allocPrint(testing.allocator, "{d}", .{b}); defer testing.allocator.free(b_fmt); - try testing.expect(!mem.eql(u8, b_fmt, "(BigInt)")); + try testing.expect(!mem.eql(u8, "(BigInt)", b_fmt)); } test "(BigInt) negative" { @@ -3840,7 +3845,7 @@ test "(BigInt) negative" { const b_fmt = try std.fmt.allocPrint(testing.allocator, "{d}", .{b}); defer testing.allocator.free(b_fmt); - try testing.expect(mem.eql(u8, a_fmt, "(BigInt)")); + try testing.expectEqualSlices(u8, "(BigInt)", a_fmt); try testing.expect(!mem.eql(u8, b_fmt, "(BigInt)")); } diff --git a/lib/std/math/hypot.zig b/lib/std/math/hypot.zig index e90b6505ce04..f95c3c0bd4b9 100644 --- a/lib/std/math/hypot.zig +++ b/lib/std/math/hypot.zig @@ -1,3 +1,4 @@ +const builtin = @import("builtin"); const std = @import("../std.zig"); const math = std.math; const expect = std.testing.expect; @@ -92,10 +93,12 @@ const hypot_test_cases = .{ }; test hypot { + if (builtin.cpu.arch.isPowerPC() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869 try expect(hypot(0.3, 0.4) == 0.5); } test "hypot.correct" { + if (builtin.cpu.arch.isPowerPC() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869 inline for (.{ f16, f32, f64, f128 }) |T| { inline for (hypot_test_cases) |v| { const a: T, const b: T, const c: T = v; @@ -105,6 +108,7 @@ test "hypot.correct" { } test "hypot.precise" { + if (builtin.cpu.arch.isPowerPC() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869 inline for (.{ f16, f32, f64 }) |T| { // f128 seems to be 5 ulp inline for (hypot_test_cases) |v| { const a: T, const b: T, const c: T = v; @@ -114,6 +118,7 @@ test "hypot.precise" { } test "hypot.special" { + if (builtin.cpu.arch.isPowerPC() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869 @setEvalBranchQuota(2000); inline for (.{ f16, f32, f64, f128 }) |T| { try expect(math.isNan(hypot(nan(T), 0.0))); diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 5c1c4f43945b..b47d228f8636 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -998,7 +998,7 @@ fn lenSliceTo(ptr: anytype, comptime end: std.meta.Elem(@TypeOf(ptr))) usize { .array => |array_info| { if (array_info.sentinel()) |s| { if (s == end) { - return indexOfSentinel(array_info.child, end, ptr); + return findSentinel(array_info.child, end, ptr); } } return findScalar(array_info.child, ptr, end) orelse array_info.len; @@ -1007,7 +1007,7 @@ fn lenSliceTo(ptr: anytype, comptime end: std.meta.Elem(@TypeOf(ptr))) usize { }, .many => if (ptr_info.sentinel()) |s| { if (s == end) { - return indexOfSentinel(ptr_info.child, end, ptr); + return findSentinel(ptr_info.child, end, ptr); } // We're looking for something other than the sentinel, // but iterating past the sentinel would be a bug so we need @@ -1018,12 +1018,12 @@ fn lenSliceTo(ptr: anytype, comptime end: std.meta.Elem(@TypeOf(ptr))) usize { }, .c => { assert(ptr != null); - return indexOfSentinel(ptr_info.child, end, ptr); + return findSentinel(ptr_info.child, end, ptr); }, .slice => { if (ptr_info.sentinel()) |s| { if (s == end) { - return indexOfSentinel(ptr_info.child, s, ptr); + return findSentinel(ptr_info.child, s, ptr); } } return findScalar(ptr_info.child, ptr, end) orelse ptr.len; @@ -1076,11 +1076,11 @@ pub fn len(value: anytype) usize { .many => { const sentinel = info.sentinel() orelse @compileError("invalid type given to std.mem.len: " ++ @typeName(@TypeOf(value))); - return indexOfSentinel(info.child, sentinel, value); + return findSentinel(info.child, sentinel, value); }, .c => { assert(value != null); - return indexOfSentinel(info.child, 0, value); + return findSentinel(info.child, 0, value); }, else => @compileError("invalid type given to std.mem.len: " ++ @typeName(@TypeOf(value))), }, @@ -1166,7 +1166,7 @@ pub fn findSentinel(comptime T: type, comptime sentinel: T, p: [*:sentinel]const return i; } -test "indexOfSentinel vector paths" { +test "findSentinel vector paths" { const Types = [_]type{ u8, u16, u32, u64 }; const allocator = std.testing.allocator; const page_size = std.heap.page_size_min; @@ -1189,7 +1189,7 @@ test "indexOfSentinel vector paths" { const search_len = page_size / @sizeOf(T); memory[start + search_len] = 0; for (0..block_len) |offset| { - try testing.expectEqual(search_len - offset, indexOfSentinel(T, 0, @ptrCast(&memory[start + offset]))); + try testing.expectEqual(search_len - offset, findSentinel(T, 0, @ptrCast(&memory[start + offset]))); } memory[start + search_len] = 0xaa; @@ -1197,7 +1197,7 @@ test "indexOfSentinel vector paths" { const start_page_boundary = start + (page_size / @sizeOf(T)); memory[start_page_boundary + block_len] = 0; for (0..block_len) |offset| { - try testing.expectEqual(2 * block_len - offset, indexOfSentinel(T, 0, @ptrCast(&memory[start_page_boundary - block_len + offset]))); + try testing.expectEqual(2 * block_len - offset, findSentinel(T, 0, @ptrCast(&memory[start_page_boundary - block_len + offset]))); } } } @@ -1221,9 +1221,6 @@ test trimStart { try testing.expectEqualSlices(u8, "foo\n ", trimStart(u8, " foo\n ", " \n")); } -/// Deprecated: use `trimStart` instead. -pub const trimLeft = trimStart; - /// Remove a set of values from the end of a slice. pub fn trimEnd(comptime T: type, slice: []const T, values_to_strip: []const T) []const T { var end: usize = slice.len; @@ -1235,9 +1232,6 @@ test trimEnd { try testing.expectEqualSlices(u8, " foo", trimEnd(u8, " foo\n ", " \n")); } -/// Deprecated: use `trimEnd` instead. -pub const trimRight = trimEnd; - /// Remove a set of values from the beginning and end of a slice. pub fn trim(comptime T: type, slice: []const T, values_to_strip: []const T) []const T { var begin: usize = 0; @@ -1257,7 +1251,7 @@ pub const indexOfScalar = findScalar; /// Linear search for the index of a scalar value inside a slice. pub fn findScalar(comptime T: type, slice: []const T, value: T) ?usize { - return indexOfScalarPos(T, slice, 0, value); + return findScalarPos(T, slice, 0, value); } /// Deprecated in favor of `findScalarLast`. @@ -1340,7 +1334,7 @@ pub fn findScalarPos(comptime T: type, slice: []const T, start_index: usize, val return null; } -test indexOfScalarPos { +test findScalarPos { const Types = [_]type{ u8, u16, u32, u64 }; inline for (Types) |T| { @@ -1349,7 +1343,7 @@ test indexOfScalarPos { memory[memory.len - 1] = 0; for (0..memory.len) |i| { - try testing.expectEqual(memory.len - i - 1, indexOfScalarPos(T, memory[i..], 0, 0).?); + try testing.expectEqual(memory.len - i - 1, findScalarPos(T, memory[i..], 0, 0).?); } } } @@ -1360,7 +1354,7 @@ pub const indexOfAny = findAny; /// Linear search for the index of any value in the provided list inside a slice. /// Returns null if no values are found. pub fn findAny(comptime T: type, slice: []const T, values: []const T) ?usize { - return indexOfAnyPos(T, slice, 0, values); + return findAnyPos(T, slice, 0, values); } /// Deprecated in favor of `findLastAny`. @@ -1401,7 +1395,7 @@ pub const indexOfNone = findNone; /// /// Comparable to `strspn` in the C standard library. pub fn findNone(comptime T: type, slice: []const T, values: []const T) ?usize { - return indexOfNonePos(T, slice, 0, values); + return findNonePos(T, slice, 0, values); } test findNone { @@ -1412,7 +1406,7 @@ test findNone { try testing.expect(findNone(u8, "123123", "123") == null); try testing.expect(findNone(u8, "333333", "123") == null); - try testing.expect(indexOfNonePos(u8, "abc123", 3, "321") == null); + try testing.expect(findNonePos(u8, "abc123", 3, "321") == null); } /// Deprecated in favor of `findLastNone`. @@ -1457,7 +1451,7 @@ pub const indexOf = find; /// Uses Boyer-Moore-Horspool algorithm on large inputs; linear search on small inputs. /// Returns null if needle is not found. pub fn find(comptime T: type, haystack: []const T, needle: []const T) ?usize { - return indexOfPos(T, haystack, 0, needle); + return findPos(T, haystack, 0, needle); } /// Deprecated in favor of `findLastLinear`. @@ -1478,7 +1472,7 @@ pub fn findLastLinear(comptime T: type, haystack: []const T, needle: []const T) pub const indexOfPosLinear = findPosLinear; -/// Consider using `indexOfPos` instead of this, which will automatically use a +/// Consider using `findPos` instead of this, which will automatically use a /// more sophisticated algorithm on larger inputs. pub fn findPosLinear(comptime T: type, haystack: []const T, start_index: usize, needle: []const T) ?usize { if (needle.len > haystack.len) return null; @@ -1572,17 +1566,17 @@ pub fn findLast(comptime T: type, haystack: []const T, needle: []const T) ?usize /// Deprecated in favor of `findPos`. pub const indexOfPos = findPos; -/// Uses Boyer-Moore-Horspool algorithm on large inputs; `indexOfPosLinear` on small inputs. +/// Uses Boyer-Moore-Horspool algorithm on large inputs; `findPosLinear` on small inputs. pub fn findPos(comptime T: type, haystack: []const T, start_index: usize, needle: []const T) ?usize { if (needle.len > haystack.len) return null; if (needle.len < 2) { if (needle.len == 0) return start_index; - // indexOfScalarPos is significantly faster than indexOfPosLinear - return indexOfScalarPos(T, haystack, start_index, needle[0]); + // findScalarPos is significantly faster than findPosLinear + return findScalarPos(T, haystack, start_index, needle[0]); } if (!std.meta.hasUniqueRepresentation(T) or haystack.len < 52 or needle.len <= 4) - return indexOfPosLinear(T, haystack, start_index, needle); + return findPosLinear(T, haystack, start_index, needle); const haystack_bytes = sliceAsBytes(haystack); const needle_bytes = sliceAsBytes(needle); @@ -1601,43 +1595,43 @@ pub fn findPos(comptime T: type, haystack: []const T, start_index: usize, needle return null; } -test indexOf { - try testing.expect(indexOf(u8, "one two three four five six seven eight nine ten eleven", "three four").? == 8); +test find { + try testing.expect(find(u8, "one two three four five six seven eight nine ten eleven", "three four").? == 8); try testing.expect(lastIndexOf(u8, "one two three four five six seven eight nine ten eleven", "three four").? == 8); - try testing.expect(indexOf(u8, "one two three four five six seven eight nine ten eleven", "two two") == null); + try testing.expect(find(u8, "one two three four five six seven eight nine ten eleven", "two two") == null); try testing.expect(lastIndexOf(u8, "one two three four five six seven eight nine ten eleven", "two two") == null); - try testing.expect(indexOf(u8, "one two three four five six seven eight nine ten", "").? == 0); + try testing.expect(find(u8, "one two three four five six seven eight nine ten", "").? == 0); try testing.expect(lastIndexOf(u8, "one two three four five six seven eight nine ten", "").? == 48); - try testing.expect(indexOf(u8, "one two three four", "four").? == 14); + try testing.expect(find(u8, "one two three four", "four").? == 14); try testing.expect(lastIndexOf(u8, "one two three two four", "two").? == 14); - try testing.expect(indexOf(u8, "one two three four", "gour") == null); + try testing.expect(find(u8, "one two three four", "gour") == null); try testing.expect(lastIndexOf(u8, "one two three four", "gour") == null); - try testing.expect(indexOf(u8, "foo", "foo").? == 0); + try testing.expect(find(u8, "foo", "foo").? == 0); try testing.expect(lastIndexOf(u8, "foo", "foo").? == 0); - try testing.expect(indexOf(u8, "foo", "fool") == null); + try testing.expect(find(u8, "foo", "fool") == null); try testing.expect(lastIndexOf(u8, "foo", "lfoo") == null); try testing.expect(lastIndexOf(u8, "foo", "fool") == null); - try testing.expect(indexOf(u8, "foo foo", "foo").? == 0); + try testing.expect(find(u8, "foo foo", "foo").? == 0); try testing.expect(lastIndexOf(u8, "foo foo", "foo").? == 4); try testing.expect(lastIndexOfAny(u8, "boo, cat", "abo").? == 6); try testing.expect(findScalarLast(u8, "boo", 'o').? == 2); } -test "indexOf multibyte" { +test "find multibyte" { { // make haystack and needle long enough to trigger Boyer-Moore-Horspool algorithm const haystack = [1]u16{0} ** 100 ++ [_]u16{ 0xbbaa, 0xccbb, 0xddcc, 0xeedd, 0xffee, 0x00ff }; const needle = [_]u16{ 0xbbaa, 0xccbb, 0xddcc, 0xeedd, 0xffee }; - try testing.expectEqual(indexOfPos(u16, &haystack, 0, &needle), 100); + try testing.expectEqual(findPos(u16, &haystack, 0, &needle), 100); // check for misaligned false positives (little and big endian) const needleLE = [_]u16{ 0xbbbb, 0xcccc, 0xdddd, 0xeeee, 0xffff }; - try testing.expectEqual(indexOfPos(u16, &haystack, 0, &needleLE), null); + try testing.expectEqual(findPos(u16, &haystack, 0, &needleLE), null); const needleBE = [_]u16{ 0xaacc, 0xbbdd, 0xccee, 0xddff, 0xee00 }; - try testing.expectEqual(indexOfPos(u16, &haystack, 0, &needleBE), null); + try testing.expectEqual(findPos(u16, &haystack, 0, &needleBE), null); } { @@ -1654,8 +1648,8 @@ test "indexOf multibyte" { } } -test "indexOfPos empty needle" { - try testing.expectEqual(indexOfPos(u8, "abracadabra", 5, ""), 5); +test "findPos empty needle" { + try testing.expectEqual(findPos(u8, "abracadabra", 5, ""), 5); } /// Returns the number of needles inside the haystack @@ -1667,7 +1661,7 @@ pub fn count(comptime T: type, haystack: []const T, needle: []const T) usize { var i: usize = 0; var found: usize = 0; - while (indexOfPos(T, haystack, i, needle)) |idx| { + while (findPos(T, haystack, i, needle)) |idx| { i = idx + needle.len; found += 1; } @@ -1737,7 +1731,7 @@ pub fn containsAtLeast(comptime T: type, haystack: []const T, expected_count: us var i: usize = 0; var found: usize = 0; - while (indexOfPos(T, haystack, i, needle)) |idx| { + while (findPos(T, haystack, i, needle)) |idx| { i = idx + needle.len; found += 1; if (found == expected_count) return true; @@ -2012,11 +2006,13 @@ fn readPackedIntBig(comptime T: type, bytes: []const u8, bit_offset: usize) T { } else return @as(T, @bitCast(val)); } +/// Deprecated: use readPackedInt(T, bytes, bit_offset, value, .native) pub const readPackedIntNative = switch (native_endian) { .little => readPackedIntLittle, .big => readPackedIntBig, }; +/// Deprecated: use readPackedInt(T, bytes, bit_offset, value, .foreign) pub const readPackedIntForeign = switch (native_endian) { .little => readPackedIntBig, .big => readPackedIntLittle, @@ -2165,11 +2161,13 @@ fn writePackedIntBig(comptime T: type, bytes: []u8, bit_offset: usize, value: T) writeInt(StoreInt, write_bytes[(byte_count - store_size)..][0..store_size], write_value, .big); } +/// Deprecated: use writePackedInt(T, bytes, bit_offset, value, .native) pub const writePackedIntNative = switch (native_endian) { .little => writePackedIntLittle, .big => writePackedIntBig, }; +/// Deprecated: use writePackedInt(T, bytes, bit_offset, value, .foreign) pub const writePackedIntForeign = switch (native_endian) { .little => writePackedIntBig, .big => writePackedIntLittle, @@ -2258,16 +2256,20 @@ test writeVarPackedInt { /// Swap the byte order of all the members of the fields of a struct /// (Changing their endianness) pub fn byteSwapAllFields(comptime S: type, ptr: *S) void { + byteSwapAllFieldsAligned(S, .of(S), ptr); +} + +/// Swap the byte order of all the members of the fields of a struct +/// (Changing their endianness) +pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *align(a.toByteUnits()) S) void { switch (@typeInfo(S)) { - .@"struct" => { - inline for (std.meta.fields(S)) |f| { + .@"struct" => |struct_info| { + if (struct_info.backing_integer) |Int| { + ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*)))); + } else inline for (std.meta.fields(S)) |f| { switch (@typeInfo(f.type)) { - .@"struct" => |struct_info| if (struct_info.backing_integer) |Int| { - @field(ptr, f.name) = @bitCast(@byteSwap(@as(Int, @bitCast(@field(ptr, f.name))))); - } else { - byteSwapAllFields(f.type, &@field(ptr, f.name)); - }, - .@"union", .array => byteSwapAllFields(f.type, &@field(ptr, f.name)), + .@"struct" => byteSwapAllFieldsAligned(f.type, .fromByteUnits(f.alignment), &@field(ptr, f.name)), + .@"union", .array => byteSwapAllFieldsAligned(f.type, .fromByteUnits(f.alignment), &@field(ptr, f.name)), .@"enum" => { @field(ptr, f.name) = @enumFromInt(@byteSwap(@intFromEnum(@field(ptr, f.name)))); }, @@ -2323,6 +2325,20 @@ test byteSwapAllFields { f4: bool, f5: f32, }; + const P = packed struct(u32) { + f0: u1, + f1: u7, + f2: u4, + f3: u4, + f4: u16, + }; + const A = extern struct { + f0: u32, + f1: extern struct { + f0: u64, + } align(4), + f2: u32, + }; var s = T{ .f0 = 0x12, .f1 = 0x1234, @@ -2340,8 +2356,16 @@ test byteSwapAllFields { .f4 = false, .f5 = @as(f32, @bitCast(@as(u32, 0x45d42800))), }; + var p: P = @bitCast(@as(u32, 0x01234567)); + var a: A = A{ + .f0 = 0x12345678, + .f1 = .{ .f0 = 0x123456789ABCDEF0 }, + .f2 = 0x87654321, + }; byteSwapAllFields(T, &s); byteSwapAllFields(K, &k); + byteSwapAllFields(P, &p); + byteSwapAllFields(A, &a); try std.testing.expectEqual(T{ .f0 = 0x12, .f1 = 0x3412, @@ -2359,6 +2383,12 @@ test byteSwapAllFields { .f4 = false, .f5 = @as(f32, @bitCast(@as(u32, 0x0028d445))), }, k); + try std.testing.expectEqual(@as(P, @bitCast(@as(u32, 0x67452301))), p); + try std.testing.expectEqual(A{ + .f0 = 0x78563412, + .f1 = .{ .f0 = 0xF0DEBC9A78563412 }, + .f2 = 0x21436587, + }, a); } /// Reverses the byte order of all elements in a slice. @@ -3013,7 +3043,7 @@ pub fn window(comptime T: type, buffer: []const T, size: usize, advance: usize) assert(size != 0); assert(advance != 0); return .{ - .index = 0, + .index = if (buffer.len > 0) 0 else null, .buffer = buffer, .size = size, .advance = advance, @@ -3024,82 +3054,121 @@ test window { { // moving average size 3 var it = window(u8, "abcdefg", 3, 1); - try testing.expectEqualSlices(u8, it.next().?, "abc"); - try testing.expectEqualSlices(u8, it.next().?, "bcd"); - try testing.expectEqualSlices(u8, it.next().?, "cde"); - try testing.expectEqualSlices(u8, it.next().?, "def"); - try testing.expectEqualSlices(u8, it.next().?, "efg"); - try testing.expectEqual(it.next(), null); + try testing.expectEqualSlices(u8, "abc", it.next().?); + try testing.expectEqualSlices(u8, "bcd", it.next().?); + try testing.expectEqualSlices(u8, "cde", it.next().?); + try testing.expectEqualSlices(u8, "def", it.next().?); + try testing.expectEqualSlices(u8, "efg", it.next().?); + try testing.expectEqual(null, it.next()); // multibyte var it16 = window(u16, std.unicode.utf8ToUtf16LeStringLiteral("abcdefg"), 3, 1); - try testing.expectEqualSlices(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("abc")); - try testing.expectEqualSlices(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("bcd")); - try testing.expectEqualSlices(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("cde")); - try testing.expectEqualSlices(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("def")); - try testing.expectEqualSlices(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("efg")); + try testing.expectEqualSlices(u16, std.unicode.utf8ToUtf16LeStringLiteral("abc"), it16.next().?); + try testing.expectEqualSlices(u16, std.unicode.utf8ToUtf16LeStringLiteral("bcd"), it16.next().?); + try testing.expectEqualSlices(u16, std.unicode.utf8ToUtf16LeStringLiteral("cde"), it16.next().?); + try testing.expectEqualSlices(u16, std.unicode.utf8ToUtf16LeStringLiteral("def"), it16.next().?); + try testing.expectEqualSlices(u16, std.unicode.utf8ToUtf16LeStringLiteral("efg"), it16.next().?); try testing.expectEqual(it16.next(), null); } { // chunk/split every 3 var it = window(u8, "abcdefg", 3, 3); - try testing.expectEqualSlices(u8, it.next().?, "abc"); - try testing.expectEqualSlices(u8, it.next().?, "def"); - try testing.expectEqualSlices(u8, it.next().?, "g"); - try testing.expectEqual(it.next(), null); + try testing.expectEqualSlices(u8, "abc", it.next().?); + try testing.expectEqualSlices(u8, "def", it.next().?); + try testing.expectEqualSlices(u8, "g", it.next().?); + try testing.expectEqual(null, it.next()); } { // pick even var it = window(u8, "abcdefg", 1, 2); - try testing.expectEqualSlices(u8, it.next().?, "a"); - try testing.expectEqualSlices(u8, it.next().?, "c"); - try testing.expectEqualSlices(u8, it.next().?, "e"); - try testing.expectEqualSlices(u8, it.next().?, "g"); - try testing.expectEqual(it.next(), null); + try testing.expectEqualSlices(u8, "a", it.next().?); + try testing.expectEqualSlices(u8, "c", it.next().?); + try testing.expectEqualSlices(u8, "e", it.next().?); + try testing.expectEqualSlices(u8, "g", it.next().?); + try testing.expectEqual(null, it.next()); + + it = window(u8, "abcdefgh", 1, 2); + try testing.expectEqualSlices(u8, "a", it.next().?); + try testing.expectEqualSlices(u8, "c", it.next().?); + try testing.expectEqualSlices(u8, "e", it.next().?); + try testing.expectEqualSlices(u8, "g", it.next().?); + try testing.expectEqual(null, it.next()); } { // empty var it = window(u8, "", 1, 1); - try testing.expectEqualSlices(u8, it.next().?, ""); - try testing.expectEqual(it.next(), null); + try testing.expectEqual(null, it.next()); it = window(u8, "", 10, 1); - try testing.expectEqualSlices(u8, it.next().?, ""); - try testing.expectEqual(it.next(), null); + try testing.expectEqual(null, it.next()); it = window(u8, "", 1, 10); - try testing.expectEqualSlices(u8, it.next().?, ""); - try testing.expectEqual(it.next(), null); + try testing.expectEqual(null, it.next()); it = window(u8, "", 10, 10); - try testing.expectEqualSlices(u8, it.next().?, ""); - try testing.expectEqual(it.next(), null); + try testing.expectEqual(null, it.next()); } { // first var it = window(u8, "abcdefg", 3, 3); - try testing.expectEqualSlices(u8, it.first(), "abc"); + try testing.expectEqualSlices(u8, "abc", it.next().?); it.reset(); - try testing.expectEqualSlices(u8, it.next().?, "abc"); + try testing.expectEqualSlices(u8, "abc", it.next().?); } { // reset var it = window(u8, "abcdefg", 3, 3); - try testing.expectEqualSlices(u8, it.next().?, "abc"); - try testing.expectEqualSlices(u8, it.next().?, "def"); - try testing.expectEqualSlices(u8, it.next().?, "g"); - try testing.expectEqual(it.next(), null); + try testing.expectEqualSlices(u8, "abc", it.next().?); + try testing.expectEqualSlices(u8, "def", it.next().?); + try testing.expectEqualSlices(u8, "g", it.next().?); + try testing.expectEqual(null, it.next()); it.reset(); - try testing.expectEqualSlices(u8, it.next().?, "abc"); - try testing.expectEqualSlices(u8, it.next().?, "def"); - try testing.expectEqualSlices(u8, it.next().?, "g"); - try testing.expectEqual(it.next(), null); + try testing.expectEqualSlices(u8, "abc", it.next().?); + try testing.expectEqualSlices(u8, "def", it.next().?); + try testing.expectEqualSlices(u8, "g", it.next().?); + try testing.expectEqual(null, it.next()); + } + + { + // size > buffer.len + var it = window(u8, "abcdefg", 100, 1); + try testing.expectEqualSlices(u8, "abcdefg", it.next().?); + try testing.expectEqual(null, it.next()); + } + + { + // advance >= buffer.len + var it = window(u8, "abcdefg", 1, 7); + try testing.expectEqualSlices(u8, "a", it.next().?); + try testing.expectEqual(null, it.next()); + } + + { + // advance == 1 and size == 1 + var it = window(u8, "abcdefg", 1, 1); + try testing.expectEqualSlices(u8, "a", it.next().?); + try testing.expectEqualSlices(u8, "b", it.next().?); + try testing.expectEqualSlices(u8, "c", it.next().?); + try testing.expectEqualSlices(u8, "d", it.next().?); + try testing.expectEqualSlices(u8, "e", it.next().?); + try testing.expectEqualSlices(u8, "f", it.next().?); + try testing.expectEqualSlices(u8, "g", it.next().?); + try testing.expectEqual(null, it.next()); + } + + { + // advance > size + var it = window(u8, "abcdefg", 2, 3); + try testing.expectEqualSlices(u8, "ab", it.next().?); + try testing.expectEqualSlices(u8, "de", it.next().?); + try testing.expectEqualSlices(u8, "g", it.next().?); + try testing.expectEqual(null, it.next()); } } @@ -3113,27 +3182,17 @@ pub fn WindowIterator(comptime T: type) type { const Self = @This(); - /// Returns a slice of the first window. - /// Call this only to get the first window and then use `next` to get - /// all subsequent windows. - /// Asserts that iteration has not begun. - pub fn first(self: *Self) []const T { - assert(self.index.? == 0); - return self.next().?; - } - /// Returns a slice of the next window, or null if window is at end. pub fn next(self: *Self) ?[]const T { const start = self.index orelse return null; const next_index = start + self.advance; - const end = if (start + self.size < self.buffer.len and next_index < self.buffer.len) blk: { - self.index = next_index; + const end = if (start + self.size < self.buffer.len) blk: { + self.index = if (next_index < self.buffer.len) next_index else null; break :blk start + self.size; } else blk: { self.index = null; break :blk self.buffer.len; }; - return self.buffer[start..end]; } @@ -3362,9 +3421,9 @@ pub fn SplitIterator(comptime T: type, comptime delimiter_type: DelimiterType) t pub fn next(self: *Self) ?[]const T { const start = self.index orelse return null; const end = if (switch (delimiter_type) { - .sequence => indexOfPos(T, self.buffer, start, self.delimiter), - .any => indexOfAnyPos(T, self.buffer, start, self.delimiter), - .scalar => indexOfScalarPos(T, self.buffer, start, self.delimiter), + .sequence => findPos(T, self.buffer, start, self.delimiter), + .any => findAnyPos(T, self.buffer, start, self.delimiter), + .scalar => findScalarPos(T, self.buffer, start, self.delimiter), }) |delim_start| blk: { self.index = delim_start + switch (delimiter_type) { .sequence => self.delimiter.len, @@ -3383,9 +3442,9 @@ pub fn SplitIterator(comptime T: type, comptime delimiter_type: DelimiterType) t pub fn peek(self: *Self) ?[]const T { const start = self.index orelse return null; const end = if (switch (delimiter_type) { - .sequence => indexOfPos(T, self.buffer, start, self.delimiter), - .any => indexOfAnyPos(T, self.buffer, start, self.delimiter), - .scalar => indexOfScalarPos(T, self.buffer, start, self.delimiter), + .sequence => findPos(T, self.buffer, start, self.delimiter), + .any => findAnyPos(T, self.buffer, start, self.delimiter), + .scalar => findScalarPos(T, self.buffer, start, self.delimiter), }) |delim_start| delim_start else self.buffer.len; return self.buffer[start..end]; } diff --git a/lib/std/meta.zig b/lib/std/meta.zig index 77e288ecaaa2..a4ce8161327e 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -614,38 +614,6 @@ test activeTag { try testing.expect(activeTag(u) == UE.Float); } -/// Deprecated: Use @FieldType(U, tag_name) -const TagPayloadType = TagPayload; - -/// Deprecated: Use @FieldType(U, tag_name) -pub fn TagPayloadByName(comptime U: type, comptime tag_name: []const u8) type { - const info = @typeInfo(U).@"union"; - - inline for (info.fields) |field_info| { - if (comptime mem.eql(u8, field_info.name, tag_name)) - return field_info.type; - } - - @compileError("no field '" ++ tag_name ++ "' in union '" ++ @typeName(U) ++ "'"); -} - -/// Deprecated: Use @FieldType(U, @tagName(tag)) -pub fn TagPayload(comptime U: type, comptime tag: Tag(U)) type { - return TagPayloadByName(U, @tagName(tag)); -} - -test TagPayload { - const Event = union(enum) { - Moved: struct { - from: i32, - to: i32, - }, - }; - const MovedEvent = TagPayload(Event, Event.Moved); - const e: Event = .{ .Moved = undefined }; - try testing.expect(MovedEvent == @TypeOf(e.Moved)); -} - /// Compares two of any type for equality. Containers that do not support comparison /// on their own are compared on a field-by-field basis. Pointers are not followed. pub fn eql(a: anytype, b: @TypeOf(a)) bool { @@ -774,14 +742,6 @@ test eql { try testing.expect(!eql(v1, v3)); } -/// Deprecated: use `std.enums.fromInt` instead and handle null. -pub const IntToEnumError = error{InvalidEnumTag}; - -/// Deprecated: use `std.enums.fromInt` instead and handle null instead of an error. -pub fn intToEnum(comptime EnumTag: type, tag_int: anytype) IntToEnumError!EnumTag { - return std.enums.fromInt(EnumTag, tag_int) orelse return error.InvalidEnumTag; -} - /// Given a type and a name, return the field index according to source order. /// Returns `null` if the field is not found. pub fn fieldIndex(comptime T: type, comptime name: []const u8) ?comptime_int { @@ -1023,13 +983,13 @@ pub inline fn hasUniqueRepresentation(comptime T: type) bool { else => false, // TODO can we know if it's true for some of these types ? .@"anyframe", - .@"enum", .error_set, .@"fn", => true, .bool => false, + .@"enum" => |info| hasUniqueRepresentation(info.tag_type), .int => |info| @sizeOf(T) * 8 == info.bits, .pointer => |info| info.size != .slice, @@ -1129,9 +1089,11 @@ test hasUniqueRepresentation { inline for ([_]type{ i0, u8, i16, u32, i64 }) |T| { try testing.expect(hasUniqueRepresentation(T)); + try testing.expect(hasUniqueRepresentation(enum(T) { _ })); } inline for ([_]type{ i1, u9, i17, u33, i24 }) |T| { try testing.expect(!hasUniqueRepresentation(T)); + try testing.expect(!hasUniqueRepresentation(enum(T) { _ })); } try testing.expect(hasUniqueRepresentation(*u8)); diff --git a/lib/std/multi_array_list.zig b/lib/std/multi_array_list.zig index 958cca30a223..990b85a238eb 100644 --- a/lib/std/multi_array_list.zig +++ b/lib/std/multi_array_list.zig @@ -29,6 +29,14 @@ pub fn MultiArrayList(comptime T: type) type { .capacity = 0, }; + /// Initialize with capacity to hold exactly `num` elements. + /// Deinitialize with `deinit` or `toOwnedSlice`. + pub fn initCapacity(gpa: Allocator, num: usize) Allocator.Error!Self { + var self: Self = .empty; + try self.setCapacity(gpa, num); + return self; + } + const Elem = switch (@typeInfo(T)) { .@"struct" => T, .@"union" => |u| struct { @@ -253,31 +261,45 @@ pub fn MultiArrayList(comptime T: type) type { return self.slice().get(index); } - /// Extend the list by 1 element. Allocates more memory as necessary. - pub fn append(self: *Self, gpa: Allocator, elem: T) !void { + /// Extend the list by 1 element. + /// + /// Allocates more memory as necessary. + pub fn append(self: *Self, gpa: Allocator, elem: T) Allocator.Error!void { try self.ensureUnusedCapacity(gpa, 1); self.appendAssumeCapacity(elem); } - /// Extend the list by 1 element, but asserting `self.capacity` - /// is sufficient to hold an additional item. + /// Extend the list by 1 element. + /// + /// Asserts that capacity is sufficient to hold an additional item. pub fn appendAssumeCapacity(self: *Self, elem: T) void { assert(self.len < self.capacity); self.len += 1; self.set(self.len - 1, elem); } + /// Extend the list by 1 element. + /// + /// If capacity is not sufficient to hold an additional + /// item, returns `error.OutOfMemory`. + pub fn appendBounded(self: *Self, elem: T) error{OutOfMemory}!void { + if (self.capacity - self.len < 1) return error.OutOfMemory; + return appendAssumeCapacity(self, elem); + } + /// Extend the list by 1 element, returning the newly reserved /// index with uninitialized data. - /// Allocates more memory as necesasry. + /// + /// Allocates more memory as necessary. pub fn addOne(self: *Self, gpa: Allocator) Allocator.Error!usize { try self.ensureUnusedCapacity(gpa, 1); return self.addOneAssumeCapacity(); } - /// Extend the list by 1 element, asserting `self.capacity` - /// is sufficient to hold an additional item. Returns the - /// newly reserved index with uninitialized data. + /// Extend the list by 1 element, returning the newly reserved + /// index with uninitialized data. + /// + /// Asserts that capacity is sufficient to hold an additional item. pub fn addOneAssumeCapacity(self: *Self) usize { assert(self.len < self.capacity); const index = self.len; @@ -285,6 +307,16 @@ pub fn MultiArrayList(comptime T: type) type { return index; } + /// Extend the list by 1 element, returning the newly reserved + /// index with uninitialized data. + /// + /// If capacity is not sufficient to hold an additional + /// item, returns `error.OutOfMemory`. + pub fn addOneBounded(self: *Self) error{OutOfMemory}!usize { + if (self.capacity - self.len < 1) return error.OutOfMemory; + return addOneAssumeCapacity(self); + } + /// Remove and return the last element from the list, or return `null` if list is empty. /// Invalidates pointers to fields of the removed element. pub fn pop(self: *Self) ?T { @@ -294,19 +326,21 @@ pub fn MultiArrayList(comptime T: type) type { return val; } - /// Inserts an item into an ordered list. Shifts all elements + /// Inserts an item into the list. Shifts all elements /// after and including the specified index back by one and - /// sets the given index to the specified element. May reallocate - /// and invalidate iterators. + /// sets the given index to the specified element. + /// + /// Allocates more memory as necessary. pub fn insert(self: *Self, gpa: Allocator, index: usize, elem: T) !void { try self.ensureUnusedCapacity(gpa, 1); self.insertAssumeCapacity(index, elem); } - /// Inserts an item into an ordered list which has room for it. - /// Shifts all elements after and including the specified index - /// back by one and sets the given index to the specified element. - /// Will not reallocate the array, does not invalidate iterators. + /// Inserts an item into the list. Shifts all elements + /// after and including the specified index back by one and + /// sets the given index to the specified element. + /// + /// Asserts that capacity is sufficient to hold an additional item. pub fn insertAssumeCapacity(self: *Self, index: usize, elem: T) void { assert(self.len < self.capacity); assert(index <= self.len); @@ -327,8 +361,19 @@ pub fn MultiArrayList(comptime T: type) type { } } + /// Inserts an item into the list. Shifts all elements + /// after and including the specified index back by one and + /// sets the given index to the specified element. + /// + /// If capacity is not sufficient to hold an additional + /// item, returns `error.OutOfMemory`. + pub fn insertBounded(self: *Self, index: usize, elem: T) error{OutOfMemory}!void { + if (self.capacity - self.len < 1) return error.OutOfMemory; + return insertAssumeCapacity(self, index, elem); + } + /// Remove the specified item from the list, swapping the last - /// item in the list into its position. Fast, but does not + /// item in the list into its position. Fast, but does not /// retain list ordering. pub fn swapRemove(self: *Self, index: usize) void { const slices = self.slice(); @@ -393,7 +438,7 @@ pub fn MultiArrayList(comptime T: type) type { /// Adjust the list's length to `new_len`. /// Does not initialize added items, if any. - pub fn resize(self: *Self, gpa: Allocator, new_len: usize) !void { + pub fn resize(self: *Self, gpa: Allocator, new_len: usize) Allocator.Error!void { try self.ensureTotalCapacity(gpa, new_len); self.len = new_len; } @@ -479,14 +524,14 @@ pub fn MultiArrayList(comptime T: type) type { /// Modify the array so that it can hold at least `additional_count` **more** items. /// Invalidates pointers if additional memory is needed. - pub fn ensureUnusedCapacity(self: *Self, gpa: Allocator, additional_count: usize) !void { + pub fn ensureUnusedCapacity(self: *Self, gpa: Allocator, additional_count: usize) Allocator.Error!void { return self.ensureTotalCapacity(gpa, self.len + additional_count); } /// Modify the array so that it can hold exactly `new_capacity` items. /// Invalidates pointers if additional memory is needed. /// `new_capacity` must be greater or equal to `len`. - pub fn setCapacity(self: *Self, gpa: Allocator, new_capacity: usize) !void { + pub fn setCapacity(self: *Self, gpa: Allocator, new_capacity: usize) Allocator.Error!void { assert(new_capacity >= self.len); const new_bytes = try gpa.alignedAlloc(u8, .of(Elem), capacityInBytes(new_capacity)); if (self.len == 0) { @@ -514,7 +559,7 @@ pub fn MultiArrayList(comptime T: type) type { /// Create a copy of this list with a new backing store, /// using the specified allocator. - pub fn clone(self: Self, gpa: Allocator) !Self { + pub fn clone(self: Self, gpa: Allocator) Allocator.Error!Self { var result = Self{}; errdefer result.deinit(gpa); try result.ensureTotalCapacity(gpa, self.len); @@ -654,7 +699,7 @@ test "basic usage" { c: u8, }; - var list = MultiArrayList(Foo){}; + var list: MultiArrayList(Foo) = .empty; defer list.deinit(ally); try testing.expectEqual(@as(usize, 0), list.items(.a).len); @@ -667,7 +712,7 @@ test "basic usage" { .c = 'a', }); - list.appendAssumeCapacity(.{ + try list.appendBounded(.{ .a = 2, .b = "zigzag", .c = 'b', @@ -725,6 +770,8 @@ test "basic usage" { try testing.expectEqualStrings("zigzag", list.items(.b)[1]); try testing.expectEqualStrings("fizzbuzz", list.items(.b)[2]); + try testing.expectError(error.OutOfMemory, list.addOneBounded()); + list.set(try list.addOne(ally), .{ .a = 4, .b = "xnopyt", @@ -749,10 +796,10 @@ test "basic usage" { // function used the @reduce code path. test "regression test for @reduce bug" { const ally = testing.allocator; - var list = MultiArrayList(struct { + var list: MultiArrayList(struct { tag: std.zig.Token.Tag, start: u32, - }){}; + }) = .empty; defer list.deinit(ally); try list.ensureTotalCapacity(ally, 20); @@ -832,7 +879,7 @@ test "ensure capacity on empty list" { b: u8, }; - var list = MultiArrayList(Foo){}; + var list: MultiArrayList(Foo) = .empty; defer list.deinit(ally); try list.ensureTotalCapacity(ally, 2); @@ -867,15 +914,25 @@ test "insert elements" { b: u32, }; - var list = MultiArrayList(Foo){}; + var list = try MultiArrayList(Foo).initCapacity(ally, 2); defer list.deinit(ally); - try list.insert(ally, 0, .{ .a = 1, .b = 2 }); - try list.ensureUnusedCapacity(ally, 1); + try list.insertBounded(0, .{ .a = 1, .b = 2 }); list.insertAssumeCapacity(1, .{ .a = 2, .b = 3 }); + try list.insert(ally, 0, .{ .a = 3, .b = 4 }); + + try testing.expectEqualSlices(u8, &[_]u8{ 3, 1, 2 }, list.items(.a)); + try testing.expectEqualSlices(u32, &[_]u32{ 4, 2, 3 }, list.items(.b)); +} + +test "initCapacity" { + const gpa = testing.allocator; + + var list = try MultiArrayList(struct { a: u8, b: u32 }).initCapacity(gpa, 404); + defer list.deinit(gpa); - try testing.expectEqualSlices(u8, &[_]u8{ 1, 2 }, list.items(.a)); - try testing.expectEqualSlices(u32, &[_]u32{ 2, 3 }, list.items(.b)); + try testing.expectEqual(0, list.len); + try testing.expectEqual(404, list.capacity); } test "union" { @@ -886,7 +943,7 @@ test "union" { b: []const u8, }; - var list = MultiArrayList(Foo){}; + var list: MultiArrayList(Foo) = .empty; defer list.deinit(ally); try testing.expectEqual(@as(usize, 0), list.items(.tags).len); @@ -934,7 +991,7 @@ test "union" { } test "sorting a span" { - var list: MultiArrayList(struct { score: u32, chr: u8 }) = .{}; + var list: MultiArrayList(struct { score: u32, chr: u8 }) = .empty; defer list.deinit(testing.allocator); try list.ensureTotalCapacity(testing.allocator, 42); @@ -981,7 +1038,7 @@ test "0 sized struct field" { b: f32, }; - var list = MultiArrayList(Foo){}; + var list: MultiArrayList(Foo) = .empty; defer list.deinit(ally); try testing.expectEqualSlices(u0, &[_]u0{}, list.items(.a)); @@ -1007,7 +1064,7 @@ test "0 sized struct" { a: u0, }; - var list = MultiArrayList(Foo){}; + var list: MultiArrayList(Foo) = .empty; defer list.deinit(ally); try testing.expectEqualSlices(u0, &[_]u0{}, list.items(.a)); diff --git a/lib/std/os.zig b/lib/std/os.zig index 110c92da2b36..4f6643c3af33 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -1,28 +1,4 @@ -//! This file contains thin wrappers around OS-specific APIs, with these -//! specific goals in mind: -//! * Convert "errno"-style error codes into Zig errors. -//! * When null-terminated byte buffers are required, provide APIs which accept -//! slices as well as APIs which accept null-terminated byte buffers. Same goes -//! for WTF-16LE encoding. -//! * Where operating systems share APIs, e.g. POSIX, these thin wrappers provide -//! cross platform abstracting. -//! * When there exists a corresponding libc function and linking libc, the libc -//! implementation is used. Exceptions are made for known buggy areas of libc. -//! On Linux libc can be side-stepped by using `std.os.linux` directly. -//! * For Windows, this file represents the API that libc would provide for -//! Windows. For thin wrappers around Windows-specific APIs, see `std.os.windows`. - -const root = @import("root"); -const std = @import("std.zig"); const builtin = @import("builtin"); -const assert = std.debug.assert; -const math = std.math; -const mem = std.mem; -const elf = std.elf; -const fs = std.fs; -const dl = @import("dynamic_library.zig"); -const max_path_bytes = std.fs.max_path_bytes; -const posix = std.posix; const native_os = builtin.os.tag; pub const linux = @import("os/linux.zig"); @@ -31,175 +7,10 @@ pub const uefi = @import("os/uefi.zig"); pub const wasi = @import("os/wasi.zig"); pub const emscripten = @import("os/emscripten.zig"); pub const windows = @import("os/windows.zig"); -pub const freebsd = @import("os/freebsd.zig"); test { _ = linux; - if (native_os == .uefi) { - _ = uefi; - } + if (native_os == .uefi) _ = uefi; _ = wasi; _ = windows; } - -/// See also `getenv`. Populated by startup code before main(). -/// TODO this is a footgun because the value will be undefined when using `zig build-lib`. -/// https://github.com/ziglang/zig/issues/4524 -pub var environ: [][*:0]u8 = undefined; - -/// Populated by startup code before main(). -/// Not available on WASI or Windows without libc. See `std.process.argsAlloc` -/// or `std.process.argsWithAllocator` for a cross-platform alternative. -pub var argv: [][*:0]u8 = if (builtin.link_libc) undefined else switch (native_os) { - .windows => @compileError("argv isn't supported on Windows: use std.process.argsAlloc instead"), - .wasi => @compileError("argv isn't supported on WASI: use std.process.argsAlloc instead"), - else => undefined, -}; - -pub fn isGetFdPathSupportedOnTarget(os: std.Target.Os) bool { - return switch (os.tag) { - .windows, - .driverkit, - .ios, - .maccatalyst, - .macos, - .tvos, - .visionos, - .watchos, - .linux, - .illumos, - .freebsd, - .serenity, - => true, - - .dragonfly => os.version_range.semver.max.order(.{ .major = 6, .minor = 0, .patch = 0 }) != .lt, - .netbsd => os.version_range.semver.max.order(.{ .major = 10, .minor = 0, .patch = 0 }) != .lt, - else => false, - }; -} - -/// Return canonical path of handle `fd`. -/// -/// This function is very host-specific and is not universally supported by all hosts. -/// For example, while it generally works on Linux, macOS, FreeBSD or Windows, it is -/// unsupported on WASI. -/// -/// * On Windows, the result is encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// * On other platforms, the result is an opaque sequence of bytes with no particular encoding. -/// -/// Calling this function is usually a bug. -pub fn getFdPath(fd: std.posix.fd_t, out_buffer: *[max_path_bytes]u8) std.posix.RealPathError![]u8 { - if (!comptime isGetFdPathSupportedOnTarget(builtin.os)) { - @compileError("querying for canonical path of a handle is unsupported on this host"); - } - switch (native_os) { - .windows => { - var wide_buf: [windows.PATH_MAX_WIDE]u16 = undefined; - const wide_slice = try windows.GetFinalPathNameByHandle(fd, .{}, wide_buf[0..]); - - const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice); - return out_buffer[0..end_index]; - }, - .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => { - // On macOS, we can use F.GETPATH fcntl command to query the OS for - // the path to the file descriptor. - @memset(out_buffer[0..max_path_bytes], 0); - switch (posix.errno(posix.system.fcntl(fd, posix.F.GETPATH, out_buffer))) { - .SUCCESS => {}, - .BADF => return error.FileNotFound, - .NOSPC => return error.NameTooLong, - .NOENT => return error.FileNotFound, - // TODO man pages for fcntl on macOS don't really tell you what - // errno values to expect when command is F.GETPATH... - else => |err| return posix.unexpectedErrno(err), - } - const len = mem.indexOfScalar(u8, out_buffer[0..], 0) orelse max_path_bytes; - return out_buffer[0..len]; - }, - .linux, .serenity => { - var procfs_buf: ["/proc/self/fd/-2147483648\x00".len]u8 = undefined; - const proc_path = std.fmt.bufPrintSentinel(procfs_buf[0..], "/proc/self/fd/{d}", .{fd}, 0) catch unreachable; - - const target = posix.readlinkZ(proc_path, out_buffer) catch |err| { - switch (err) { - error.NotLink => unreachable, - error.BadPathName => unreachable, - error.UnsupportedReparsePointType => unreachable, // Windows-only - error.NetworkNotFound => unreachable, // Windows-only - else => |e| return e, - } - }; - return target; - }, - .illumos => { - var procfs_buf: ["/proc/self/path/-2147483648\x00".len]u8 = undefined; - const proc_path = std.fmt.bufPrintSentinel(procfs_buf[0..], "/proc/self/path/{d}", .{fd}, 0) catch unreachable; - - const target = posix.readlinkZ(proc_path, out_buffer) catch |err| switch (err) { - error.UnsupportedReparsePointType => unreachable, - error.NotLink => unreachable, - else => |e| return e, - }; - return target; - }, - .freebsd => { - var kfile: std.c.kinfo_file = undefined; - kfile.structsize = std.c.KINFO_FILE_SIZE; - switch (posix.errno(std.c.fcntl(fd, std.c.F.KINFO, @intFromPtr(&kfile)))) { - .SUCCESS => {}, - .BADF => return error.FileNotFound, - else => |err| return posix.unexpectedErrno(err), - } - const len = mem.indexOfScalar(u8, &kfile.path, 0) orelse max_path_bytes; - if (len == 0) return error.NameTooLong; - const result = out_buffer[0..len]; - @memcpy(result, kfile.path[0..len]); - return result; - }, - .dragonfly => { - @memset(out_buffer[0..max_path_bytes], 0); - switch (posix.errno(std.c.fcntl(fd, posix.F.GETPATH, out_buffer))) { - .SUCCESS => {}, - .BADF => return error.FileNotFound, - .RANGE => return error.NameTooLong, - else => |err| return posix.unexpectedErrno(err), - } - const len = mem.indexOfScalar(u8, out_buffer[0..], 0) orelse max_path_bytes; - return out_buffer[0..len]; - }, - .netbsd => { - @memset(out_buffer[0..max_path_bytes], 0); - switch (posix.errno(std.c.fcntl(fd, posix.F.GETPATH, out_buffer))) { - .SUCCESS => {}, - .ACCES => return error.AccessDenied, - .BADF => return error.FileNotFound, - .NOENT => return error.FileNotFound, - .NOMEM => return error.SystemResources, - .RANGE => return error.NameTooLong, - else => |err| return posix.unexpectedErrno(err), - } - const len = mem.indexOfScalar(u8, out_buffer[0..], 0) orelse max_path_bytes; - return out_buffer[0..len]; - }, - else => unreachable, // made unreachable by isGetFdPathSupportedOnTarget above - } -} - -pub const FstatError = error{ - SystemResources, - AccessDenied, - Unexpected, -}; - -pub fn fstat_wasi(fd: posix.fd_t) FstatError!wasi.filestat_t { - var stat: wasi.filestat_t = undefined; - switch (wasi.fd_filestat_get(fd, &stat)) { - .SUCCESS => return stat, - .INVAL => unreachable, - .BADF => unreachable, // Always a race condition. - .NOMEM => return error.SystemResources, - .ACCES => return error.AccessDenied, - .NOTCAPABLE => return error.AccessDenied, - else => |err| return posix.unexpectedErrno(err), - } -} diff --git a/lib/std/os/emscripten.zig b/lib/std/os/emscripten.zig index cb444b360dd0..67761d3ce57e 100644 --- a/lib/std/os/emscripten.zig +++ b/lib/std/os/emscripten.zig @@ -224,14 +224,14 @@ pub const W = struct { pub fn EXITSTATUS(s: u32) u8 { return @as(u8, @intCast((s & 0xff00) >> 8)); } - pub fn TERMSIG(s: u32) u32 { - return s & 0x7f; + pub fn TERMSIG(s: u32) SIG { + return @enumFromInt(s & 0x7f); } pub fn STOPSIG(s: u32) u32 { return EXITSTATUS(s); } pub fn IFEXITED(s: u32) bool { - return TERMSIG(s) == 0; + return (s & 0x7f) == 0; } pub fn IFSTOPPED(s: u32) bool { return @as(u16, @truncate(((s & 0xffff) *% 0x10001) >> 8)) > 0x7f00; @@ -854,7 +854,7 @@ pub extern "c" fn emscripten_wget(url: [*:0]const u8, file: [*:0]const u8) c_int pub extern "c" fn emscripten_wget_data(url: [*:0]const u8, pbuffer: *(?*anyopaque), pnum: *c_int, perror: *c_int) void; pub extern "c" fn emscripten_run_script(script: [*:0]const u8) void; pub extern "c" fn emscripten_run_script_int(script: [*:0]const u8) c_int; -pub extern "c" fn emscripten_run_script_string(script: [*:0]const u8) [*:0]u8; +pub extern "c" fn emscripten_run_script_string(script: [*:0]const u8) ?[*:0]u8; pub extern "c" fn emscripten_async_run_script(script: [*:0]const u8, millis: c_int) void; pub extern "c" fn emscripten_async_load_script(script: [*:0]const u8, onload: em_callback_func, onerror: em_callback_func) void; pub extern "c" fn emscripten_set_main_loop(func: em_callback_func, fps: c_int, simulate_infinite_loop: c_int) void; diff --git a/lib/std/os/freebsd.zig b/lib/std/os/freebsd.zig deleted file mode 100644 index 2d082bf0cdf8..000000000000 --- a/lib/std/os/freebsd.zig +++ /dev/null @@ -1,50 +0,0 @@ -const std = @import("../std.zig"); -const fd_t = std.c.fd_t; -const off_t = std.c.off_t; -const unexpectedErrno = std.posix.unexpectedErrno; -const errno = std.posix.errno; -const builtin = @import("builtin"); - -pub const CopyFileRangeError = std.posix.UnexpectedError || error{ - /// If infd is not open for reading or outfd is not open for writing, or - /// opened for writing with O_APPEND, or if infd and outfd refer to the - /// same file. - BadFileFlags, - /// If the copy exceeds the process's file size limit or the maximum - /// file size for the file system outfd re- sides on. - FileTooBig, - /// A signal interrupted the system call before it could be completed. - /// This may happen for files on some NFS mounts. When this happens, - /// the values pointed to by inoffp and outoffp are reset to the - /// initial values for the system call. - Interrupted, - /// One of: - /// * infd and outfd refer to the same file and the byte ranges overlap. - /// * The flags argument is not zero. - /// * Either infd or outfd refers to a file object that is not a regular file. - InvalidArguments, - /// An I/O error occurred while reading/writing the files. - InputOutput, - /// Corrupted data was detected while reading from a file system. - CorruptedData, - /// Either infd or outfd refers to a directory. - IsDir, - /// File system that stores outfd is full. - NoSpaceLeft, -}; - -pub fn copy_file_range(fd_in: fd_t, off_in: ?*i64, fd_out: fd_t, off_out: ?*i64, len: usize, flags: u32) CopyFileRangeError!usize { - const rc = std.c.copy_file_range(fd_in, off_in, fd_out, off_out, len, flags); - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - .BADF => return error.BadFileFlags, - .FBIG => return error.FileTooBig, - .INTR => return error.Interrupted, - .INVAL => return error.InvalidArguments, - .IO => return error.InputOutput, - .INTEGRITY => return error.CorruptedData, - .ISDIR => return error.IsDir, - .NOSPC => return error.NoSpaceLeft, - else => |err| return unexpectedErrno(err), - } -} diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 2029356a66b5..92ea207fd080 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -95,15 +95,14 @@ pub fn clone( pub const ARCH = arch_bits.ARCH; pub const HWCAP = arch_bits.HWCAP; pub const SC = arch_bits.SC; -pub const Stat = arch_bits.Stat; pub const VDSO = arch_bits.VDSO; -pub const blkcnt_t = arch_bits.blkcnt_t; -pub const blksize_t = arch_bits.blksize_t; -pub const dev_t = arch_bits.dev_t; -pub const ino_t = arch_bits.ino_t; -pub const mode_t = arch_bits.mode_t; -pub const nlink_t = arch_bits.nlink_t; -pub const off_t = arch_bits.off_t; +pub const blkcnt_t = u64; +pub const blksize_t = u32; +pub const dev_t = u64; +pub const ino_t = u64; +pub const mode_t = u32; +pub const nlink_t = u32; +pub const off_t = i64; pub const time_t = arch_bits.time_t; pub const user_desc = arch_bits.user_desc; @@ -325,6 +324,7 @@ pub const O = switch (native_arch) { CLOEXEC: bool = false, SYNC: bool = false, PATH: bool = false, + /// This is typically invalid without also setting `DIRECTORY`. TMPFILE: bool = false, _23: u9 = 0, }, @@ -347,6 +347,7 @@ pub const O = switch (native_arch) { CLOEXEC: bool = false, SYNC: bool = false, PATH: bool = false, + /// This is typically invalid without also setting `DIRECTORY`. TMPFILE: bool = false, _23: u9 = 0, }, @@ -369,6 +370,7 @@ pub const O = switch (native_arch) { CLOEXEC: bool = false, SYNC: bool = false, PATH: bool = false, + /// This is typically invalid without also setting `DIRECTORY`. TMPFILE: bool = false, _23: u9 = 0, }, @@ -394,6 +396,7 @@ pub const O = switch (native_arch) { CLOEXEC: bool = false, SYNC: bool = false, PATH: bool = false, + /// This is typically invalid without also setting `DIRECTORY`. TMPFILE: bool = false, _27: u6 = 0, }, @@ -418,6 +421,7 @@ pub const O = switch (native_arch) { CLOEXEC: bool = false, _20: u1 = 0, PATH: bool = false, + /// This is typically invalid without also setting `DIRECTORY`. TMPFILE: bool = false, _23: u9 = 0, }, @@ -440,6 +444,7 @@ pub const O = switch (native_arch) { CLOEXEC: bool = false, SYNC: bool = false, PATH: bool = false, + /// This is typically invalid without also setting `DIRECTORY`. TMPFILE: bool = false, _23: u9 = 0, }, @@ -460,13 +465,16 @@ pub const O = switch (native_arch) { NOFOLLOW: bool = false, NOATIME: bool = false, CLOEXEC: bool = false, - _20: u1 = 0, + /// This is typically invalid without also setting `TMPFILE1` and `DIRECTORY`. + TMPFILE0: bool = false, PATH: bool = false, - _22: u10 = 0, + _22: u4 = 0, + /// This is typically invalid without also setting `TMPFILE0` and `DIRECTORY`. + TMPFILE1: bool = false, + _27: u5 = 0, // #define O_RSYNC 04010000 // #define O_SYNC 04010000 - // #define O_TMPFILE 020200000 // #define O_NDELAY O_NONBLOCK }, .m68k => packed struct(u32) { @@ -493,6 +501,15 @@ pub const O = switch (native_arch) { else => @compileError("missing std.os.linux.O constants for this architecture"), }; +pub const RENAME = packed struct(u32) { + /// Cannot be set together with `EXCHANGE`. + NOREPLACE: bool = false, + /// Cannot be set together with `NOREPLACE`. + EXCHANGE: bool = false, + WHITEOUT: bool = false, + _: u29 = 0, +}; + /// Set by startup code, used by `getauxval`. pub var elf_aux_maybe: ?[*]std.elf.Auxv = null; @@ -1338,9 +1355,22 @@ pub fn rename(old: [*:0]const u8, new: [*:0]const u8) usize { if (@hasField(SYS, "rename")) { return syscall2(.rename, @intFromPtr(old), @intFromPtr(new)); } else if (@hasField(SYS, "renameat")) { - return syscall4(.renameat, @as(usize, @bitCast(@as(isize, AT.FDCWD))), @intFromPtr(old), @as(usize, @bitCast(@as(isize, AT.FDCWD))), @intFromPtr(new)); + return syscall4( + .renameat, + @as(usize, @bitCast(@as(isize, AT.FDCWD))), + @intFromPtr(old), + @as(usize, @bitCast(@as(isize, AT.FDCWD))), + @intFromPtr(new), + ); } else { - return syscall5(.renameat2, @as(usize, @bitCast(@as(isize, AT.FDCWD))), @intFromPtr(old), @as(usize, @bitCast(@as(isize, AT.FDCWD))), @intFromPtr(new), 0); + return syscall5( + .renameat2, + @as(usize, @bitCast(@as(isize, AT.FDCWD))), + @intFromPtr(old), + @as(usize, @bitCast(@as(isize, AT.FDCWD))), + @intFromPtr(new), + 0, + ); } } @@ -1365,14 +1395,14 @@ pub fn renameat(oldfd: i32, oldpath: [*:0]const u8, newfd: i32, newpath: [*:0]co } } -pub fn renameat2(oldfd: i32, oldpath: [*:0]const u8, newfd: i32, newpath: [*:0]const u8, flags: u32) usize { +pub fn renameat2(oldfd: i32, oldpath: [*:0]const u8, newfd: i32, newpath: [*:0]const u8, flags: RENAME) usize { return syscall5( .renameat2, @as(usize, @bitCast(@as(isize, oldfd))), @intFromPtr(oldpath), @as(usize, @bitCast(@as(isize, newfd))), @intFromPtr(newpath), - flags, + @as(u32, @bitCast(flags)), ); } @@ -1421,7 +1451,7 @@ pub fn chmod(path: [*:0]const u8, mode: mode_t) usize { if (@hasField(SYS, "chmod")) { return syscall2(.chmod, @intFromPtr(path), mode); } else { - return fchmodat(AT.FDCWD, path, mode, 0); + return fchmodat(AT.FDCWD, path, mode); } } @@ -1433,7 +1463,7 @@ pub fn fchown(fd: i32, owner: uid_t, group: gid_t) usize { } } -pub fn fchmodat(fd: i32, path: [*:0]const u8, mode: mode_t, _: u32) usize { +pub fn fchmodat(fd: i32, path: [*:0]const u8, mode: mode_t) usize { return syscall3(.fchmodat, @bitCast(@as(isize, fd)), @intFromPtr(path), mode); } @@ -1562,14 +1592,14 @@ pub fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8) usize { } } -pub fn linkat(oldfd: fd_t, oldpath: [*:0]const u8, newfd: fd_t, newpath: [*:0]const u8, flags: i32) usize { +pub fn linkat(oldfd: fd_t, oldpath: [*:0]const u8, newfd: fd_t, newpath: [*:0]const u8, flags: u32) usize { return syscall5( .linkat, @as(usize, @bitCast(@as(isize, oldfd))), @intFromPtr(oldpath), @as(usize, @bitCast(@as(isize, newfd))), @intFromPtr(newpath), - @as(usize, @bitCast(@as(isize, flags))), + flags, ); } @@ -1599,8 +1629,15 @@ pub fn wait4(pid: pid_t, status: *u32, flags: u32, usage: ?*rusage) usize { ); } -pub fn waitid(id_type: P, id: i32, infop: *siginfo_t, flags: u32) usize { - return syscall5(.waitid, @intFromEnum(id_type), @as(usize, @bitCast(@as(isize, id))), @intFromPtr(infop), flags, 0); +pub fn waitid(id_type: P, id: i32, infop: *siginfo_t, flags: u32, usage: ?*rusage) usize { + return syscall5( + .waitid, + @intFromEnum(id_type), + @as(usize, @bitCast(@as(isize, id))), + @intFromPtr(infop), + flags, + @intFromPtr(usage), + ); } pub const F = struct { @@ -1748,9 +1785,7 @@ pub fn settimeofday(tv: *const timeval, tz: *const timezone) usize { } pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize { - if (native_arch == .riscv32) { - @compileError("No nanosleep syscall on this architecture."); - } else return syscall2(.nanosleep, @intFromPtr(req), @intFromPtr(rem)); + return syscall2(.nanosleep, @intFromPtr(req), @intFromPtr(rem)); } pub fn pause() usize { @@ -2201,61 +2236,13 @@ pub fn accept4(fd: i32, noalias addr: ?*sockaddr, noalias len: ?*socklen_t, flag return syscall4(.accept4, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(addr), @intFromPtr(len), flags); } -pub fn fstat(fd: i32, stat_buf: *Stat) usize { - if (native_arch == .riscv32 or native_arch.isLoongArch()) { - // riscv32 and loongarch have made the interesting decision to not implement some of - // the older stat syscalls, including this one. - @compileError("No fstat syscall on this architecture."); - } else if (@hasField(SYS, "fstat64")) { - return syscall2(.fstat64, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(stat_buf)); - } else { - return syscall2(.fstat, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(stat_buf)); - } -} - -pub fn stat(pathname: [*:0]const u8, statbuf: *Stat) usize { - if (native_arch == .riscv32 or native_arch.isLoongArch()) { - // riscv32 and loongarch have made the interesting decision to not implement some of - // the older stat syscalls, including this one. - @compileError("No stat syscall on this architecture."); - } else if (@hasField(SYS, "stat64")) { - return syscall2(.stat64, @intFromPtr(pathname), @intFromPtr(statbuf)); - } else { - return syscall2(.stat, @intFromPtr(pathname), @intFromPtr(statbuf)); - } -} - -pub fn lstat(pathname: [*:0]const u8, statbuf: *Stat) usize { - if (native_arch == .riscv32 or native_arch.isLoongArch()) { - // riscv32 and loongarch have made the interesting decision to not implement some of - // the older stat syscalls, including this one. - @compileError("No lstat syscall on this architecture."); - } else if (@hasField(SYS, "lstat64")) { - return syscall2(.lstat64, @intFromPtr(pathname), @intFromPtr(statbuf)); - } else { - return syscall2(.lstat, @intFromPtr(pathname), @intFromPtr(statbuf)); - } -} - -pub fn fstatat(dirfd: i32, path: [*:0]const u8, stat_buf: *Stat, flags: u32) usize { - if (native_arch == .riscv32 or native_arch.isLoongArch()) { - // riscv32 and loongarch have made the interesting decision to not implement some of - // the older stat syscalls, including this one. - @compileError("No fstatat syscall on this architecture."); - } else if (@hasField(SYS, "fstatat64")) { - return syscall4(.fstatat64, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), @intFromPtr(stat_buf), flags); - } else { - return syscall4(.fstatat, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), @intFromPtr(stat_buf), flags); - } -} - -pub fn statx(dirfd: i32, path: [*:0]const u8, flags: u32, mask: u32, statx_buf: *Statx) usize { +pub fn statx(dirfd: i32, path: [*:0]const u8, flags: u32, mask: STATX, statx_buf: *Statx) usize { return syscall5( .statx, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), flags, - mask, + @as(u32, @bitCast(mask)), @intFromPtr(statx_buf), ); } @@ -3667,14 +3654,14 @@ pub const W = struct { pub fn EXITSTATUS(s: u32) u8 { return @as(u8, @intCast((s & 0xff00) >> 8)); } - pub fn TERMSIG(s: u32) u32 { - return s & 0x7f; + pub fn TERMSIG(s: u32) SIG { + return @enumFromInt(s & 0x7f); } pub fn STOPSIG(s: u32) u32 { return EXITSTATUS(s); } pub fn IFEXITED(s: u32) bool { - return TERMSIG(s) == 0; + return (s & 0x7f) == 0; } pub fn IFSTOPPED(s: u32) bool { return @as(u16, @truncate(((s & 0xffff) *% 0x10001) >> 8)) > 0x7f00; @@ -3773,6 +3760,7 @@ pub const SIG = if (is_mips) enum(u32) { PROF = 29, XCPU = 30, XFZ = 31, + _, } else if (is_sparc) enum(u32) { pub const BLOCK = 1; pub const UNBLOCK = 2; @@ -3818,6 +3806,7 @@ pub const SIG = if (is_mips) enum(u32) { LOST = 29, USR1 = 30, USR2 = 31, + _, } else enum(u32) { pub const BLOCK = 0; pub const UNBLOCK = 1; @@ -3861,6 +3850,7 @@ pub const SIG = if (is_mips) enum(u32) { IO = 29, PWR = 30, SYS = 31, + _, }; pub const kernel_rwf = u32; @@ -6088,7 +6078,7 @@ pub const dirent64 = extern struct { off: u64, reclen: u16, type: u8, - name: u8, // field address is the address of first byte of name https://github.com/ziglang/zig/issues/173 + name: [0]u8, }; pub const dl_phdr_info = extern struct { @@ -6253,6 +6243,16 @@ const siginfo_fields_union = extern union { }, }; +pub const CLD = enum(i32) { + EXITED = 1, + KILLED = 2, + DUMPED = 3, + TRAPPED = 4, + STOPPED = 5, + CONTINUED = 6, + _, +}; + pub const siginfo_t = if (is_mips) extern struct { signo: SIG, @@ -6939,96 +6939,159 @@ pub const utsname = extern struct { }; pub const HOST_NAME_MAX = 64; -pub const STATX_TYPE = 0x0001; -pub const STATX_MODE = 0x0002; -pub const STATX_NLINK = 0x0004; -pub const STATX_UID = 0x0008; -pub const STATX_GID = 0x0010; -pub const STATX_ATIME = 0x0020; -pub const STATX_MTIME = 0x0040; -pub const STATX_CTIME = 0x0080; -pub const STATX_INO = 0x0100; -pub const STATX_SIZE = 0x0200; -pub const STATX_BLOCKS = 0x0400; -pub const STATX_BASIC_STATS = 0x07ff; - -pub const STATX_BTIME = 0x0800; - -pub const STATX_ATTR_COMPRESSED = 0x0004; -pub const STATX_ATTR_IMMUTABLE = 0x0010; -pub const STATX_ATTR_APPEND = 0x0020; -pub const STATX_ATTR_NODUMP = 0x0040; -pub const STATX_ATTR_ENCRYPTED = 0x0800; -pub const STATX_ATTR_AUTOMOUNT = 0x1000; +pub const STATX = packed struct(u32) { + /// Want `mode & S.IFMT`. + TYPE: bool = false, + /// Want `mode & ~S.IFMT`. + MODE: bool = false, + /// Want the `nlink` member. + NLINK: bool = false, + /// Want the `uid` member. + UID: bool = false, + /// Want the `gid` member. + GID: bool = false, + /// Want the `atime` member. + ATIME: bool = false, + /// Want the `mtime` member. + MTIME: bool = false, + /// Want the `ctime` member. + CTIME: bool = false, + /// Want the `ino` member. + INO: bool = false, + /// Want the `size` member. + SIZE: bool = false, + /// Want the `blocks` member. + BLOCKS: bool = false, + /// Want the `btime` member. + BTIME: bool = false, + /// Want the `mnt_id` member. + MNT_ID: bool = false, + /// Want the `dio_mem_align` and `dio_offset_align` members. + DIOALIGN: bool = false, + /// Want the `stx_mnt_id` member. + MNT_ID_UNIQUE: bool = false, + /// Want the `sub` member. + SUBVOL: bool = false, + /// Want the `atomic_write_unit_min`, `atomic_write_unit_max` and + /// `atomic_write_segments_max` members. + WRITE_ATOMIC: bool = false, + /// Want the `dio_read_offset_align` member. + DIO_READ_ALIGN: bool = false, + __pad: u13 = 0, + /// Reserved for future expansion; must not be set. + __RESERVED: bool = false, + + pub const BASIC_STATS: STATX = @bitCast(@as(u32, 0x7ff)); +}; + +/// Attributes about the state or features of a file as a bitmask. +/// Flags marked [I] correspond to the `FS_IOC_SETFLAGS` values semantically. +/// See [FS_IOC_SETFLAGS(2const)](https://man7.org/linux/man-pages/man2/FS_IOC_GETFLAGS.2const.html) +/// for more. +pub const STATX_ATTR = packed struct(u64) { + __pad1: u3 = 0, + /// [I] File is compressed by the fs. + COMPRESSED: bool = false, + __pad2: u1 = 0, + /// [I] File is marked immutable. + IMMUTABLE: bool = false, + /// [I] File is append-only. + APPEND: bool = false, + /// [I] File is not to be dumped. + NODUMP: bool = false, + /// [I] File requires a key to decrypt in the filesystem. + ENCRYPTED: bool = false, + /// File names a directory that triggers an automount. + AUTOMOUNT: bool = false, + /// File names the root of a mount. + MOUNT_ROOT: bool = false, + /// [I] File is protected by the `dm-verity` device. + VERITY: bool = false, + /// File is currently in the CPU direct access state. + /// Does not correspond to the per-inode DAX flag that some filesystems support. + DAX: bool = false, + /// File supports atomic write operations. + WRITE_ATOMIC: bool = false, + __pad3: u50 = 0, +}; pub const statx_timestamp = extern struct { + /// Number of seconds before or after `1970-01-01T00:00:00Z`. sec: i64, + /// Number of nanoseconds (0..999,999,999) after `sec`. nsec: u32, + // Reserved for future increases in resolution. __pad1: u32, }; /// Renamed to `Statx` to not conflict with the `statx` function. pub const Statx = extern struct { - /// Mask of bits indicating filled fields - mask: u32, - - /// Block size for filesystem I/O + /// Mask of bits indicating filled fields. Updated with what information + /// the kernel returned. Callers must check this field since support varies + /// by kernel version and filesystem. + mask: STATX, + /// Block size for filesystem I/O. blksize: u32, - - /// Extra file attribute indicators - attributes: u64, - - /// Number of hard links + /// Extra file attribute indicators. + attributes: STATX_ATTR, + /// Number of hard links. nlink: u32, - - /// User ID of owner + /// User ID of owner. uid: uid_t, - - /// Group ID of owner + /// Group ID of owner. gid: gid_t, - - /// File type and mode + /// File type and mode. mode: u16, - __pad1: u16, - - /// Inode number + __spare0: u16, + /// Inode number. ino: u64, - - /// Total size in bytes + /// Total size in bytes. size: u64, - - /// Number of 512B blocks allocated + /// Number of 512B blocks allocated. blocks: u64, - /// Mask to show what's supported in `attributes`. - attributes_mask: u64, - - /// Last access file timestamp + attributes_mask: STATX_ATTR, + /// Last access file timestamp. atime: statx_timestamp, - - /// Creation file timestamp + /// Creation file timestamp. btime: statx_timestamp, - - /// Last status change file timestamp + /// Last status change file timestamp. ctime: statx_timestamp, - - /// Last modification file timestamp + /// Last modification file timestamp. mtime: statx_timestamp, - /// Major ID, if this file represents a device. rdev_major: u32, - /// Minor ID, if this file represents a device. rdev_minor: u32, - /// Major ID of the device containing the filesystem where this file resides. dev_major: u32, - /// Minor ID of the device containing the filesystem where this file resides. dev_minor: u32, - - __pad2: [14]u64, -}; + /// Mount ID + mnt_id: u64, + /// Memory buffer alignment for direct I/O. + dio_mem_align: u32, + /// File offset alignment for direct I/O. + dio_offset_align: u32, + /// Subvolume identifier. + subvol: u64, + /// Min atomic write unit in bytes. + atomic_write_unit_min: u32, + /// Max atomic write unit in bytes. + atomic_write_unit_max: u32, + /// Max atomic write segment count. + atomic_write_segments_max: u32, + /// File offset alignment for direct I/O reads. + dio_read_offset_align: u32, + /// Optimised max atomic write unit in bytes. + atomic_write_unit_max_opt: u32, + __spare2: [1]u32, + __spare3: [8]u64, +}; + +comptime { + assert(@sizeOf(Statx) == 0x100); +} pub const addrinfo = extern struct { flags: AI, @@ -8402,12 +8465,36 @@ pub const timezone = extern struct { pub const kernel_timespec = extern struct { sec: i64, nsec: i64, + + /// For use with `utimensat` and `futimens`. + pub const NOW: timespec = .{ + .sec = 0, + .nsec = 0x3fffffff, + }; + + /// For use with `utimensat` and `futimens`. + pub const OMIT: timespec = .{ + .sec = 0, + .nsec = 0x3ffffffe, + }; }; // https://github.com/ziglang/zig/issues/4726#issuecomment-2190337877 pub const timespec = if (native_arch == .hexagon or native_arch == .riscv32) kernel_timespec else extern struct { sec: isize, nsec: isize, + + /// For use with `utimensat` and `futimens`. + pub const NOW: timespec = .{ + .sec = 0, + .nsec = 0x3fffffff, + }; + + /// For use with `utimensat` and `futimens`. + pub const OMIT: timespec = .{ + .sec = 0, + .nsec = 0x3ffffffe, + }; }; pub const XDP = struct { @@ -9610,6 +9697,7 @@ pub const PERF = struct { pub const PERIOD = 1074275332; pub const SET_OUTPUT = 9221; pub const SET_FILTER = 1074275334; + pub const ID = 2148017159; pub const SET_BPF = 1074013192; pub const PAUSE_OUTPUT = 1074013193; pub const QUERY_BPF = 3221758986; @@ -9854,125 +9942,3 @@ pub const cmsghdr = extern struct { level: i32, type: i32, }; - -/// The syscalls, but with Zig error sets, going through libc if linking libc, -/// and with some footguns eliminated. -pub const wrapped = struct { - pub const lfs64_abi = builtin.link_libc and (builtin.abi.isGnu() or builtin.abi.isAndroid()); - const system = if (builtin.link_libc) std.c else std.os.linux; - - pub const SendfileError = std.posix.UnexpectedError || error{ - /// `out_fd` is an unconnected socket, or out_fd closed its read end. - BrokenPipe, - /// Descriptor is not valid or locked, or an mmap(2)-like operation is not available for in_fd. - UnsupportedOperation, - /// Nonblocking I/O has been selected but the write would block. - WouldBlock, - /// Unspecified error while reading from in_fd. - InputOutput, - /// Insufficient kernel memory to read from in_fd. - SystemResources, - /// `offset` is not `null` but the input file is not seekable. - Unseekable, - }; - - pub fn sendfile( - out_fd: fd_t, - in_fd: fd_t, - in_offset: ?*off_t, - in_len: usize, - ) SendfileError!usize { - const adjusted_len = @min(in_len, 0x7ffff000); // Prevents EOVERFLOW. - const sendfileSymbol = if (lfs64_abi) system.sendfile64 else system.sendfile; - const rc = sendfileSymbol(out_fd, in_fd, in_offset, adjusted_len); - switch (system.errno(rc)) { - .SUCCESS => return @intCast(rc), - .BADF => return invalidApiUsage(), // Always a race condition. - .FAULT => return invalidApiUsage(), // Segmentation fault. - .OVERFLOW => return unexpectedErrno(.OVERFLOW), // We avoid passing too large of a `count`. - .NOTCONN => return error.BrokenPipe, // `out_fd` is an unconnected socket - .INVAL => return error.UnsupportedOperation, - .AGAIN => return error.WouldBlock, - .IO => return error.InputOutput, - .PIPE => return error.BrokenPipe, - .NOMEM => return error.SystemResources, - .NXIO => return error.Unseekable, - .SPIPE => return error.Unseekable, - else => |err| return unexpectedErrno(err), - } - } - - pub const CopyFileRangeError = std.posix.UnexpectedError || error{ - /// One of: - /// * One or more file descriptors are not valid. - /// * fd_in is not open for reading; or fd_out is not open for writing. - /// * The O_APPEND flag is set for the open file description referred - /// to by the file descriptor fd_out. - BadFileFlags, - /// One of: - /// * An attempt was made to write at a position past the maximum file - /// offset the kernel supports. - /// * An attempt was made to write a range that exceeds the allowed - /// maximum file size. The maximum file size differs between - /// filesystem implementations and can be different from the maximum - /// allowed file offset. - /// * An attempt was made to write beyond the process's file size - /// resource limit. This may also result in the process receiving a - /// SIGXFSZ signal. - FileTooBig, - /// One of: - /// * either fd_in or fd_out is not a regular file - /// * flags argument is not zero - /// * fd_in and fd_out refer to the same file and the source and target ranges overlap. - InvalidArguments, - /// A low-level I/O error occurred while copying. - InputOutput, - /// Either fd_in or fd_out refers to a directory. - IsDir, - OutOfMemory, - /// There is not enough space on the target filesystem to complete the copy. - NoSpaceLeft, - /// (since Linux 5.19) the filesystem does not support this operation. - OperationNotSupported, - /// The requested source or destination range is too large to represent - /// in the specified data types. - Overflow, - /// fd_out refers to an immutable file. - PermissionDenied, - /// Either fd_in or fd_out refers to an active swap file. - SwapFile, - /// The files referred to by fd_in and fd_out are not on the same - /// filesystem, and the source and target filesystems are not of the - /// same type, or do not support cross-filesystem copy. - NotSameFileSystem, - }; - - pub fn copy_file_range(fd_in: fd_t, off_in: ?*i64, fd_out: fd_t, off_out: ?*i64, len: usize, flags: u32) CopyFileRangeError!usize { - const use_c = std.c.versionCheck(if (builtin.abi.isAndroid()) .{ .major = 34, .minor = 0, .patch = 0 } else .{ .major = 2, .minor = 27, .patch = 0 }); - const sys = if (use_c) std.c else std.os.linux; - const rc = sys.copy_file_range(fd_in, off_in, fd_out, off_out, len, flags); - switch (sys.errno(rc)) { - .SUCCESS => return @intCast(rc), - .BADF => return error.BadFileFlags, - .FBIG => return error.FileTooBig, - .INVAL => return error.InvalidArguments, - .IO => return error.InputOutput, - .ISDIR => return error.IsDir, - .NOMEM => return error.OutOfMemory, - .NOSPC => return error.NoSpaceLeft, - .OPNOTSUPP => return error.OperationNotSupported, - .OVERFLOW => return error.Overflow, - .PERM => return error.PermissionDenied, - .TXTBSY => return error.SwapFile, - .XDEV => return error.NotSameFileSystem, - else => |err| return unexpectedErrno(err), - } - } - - const unexpectedErrno = std.posix.unexpectedErrno; - - fn invalidApiUsage() error{Unexpected} { - if (builtin.mode == .Debug) @panic("invalid API usage"); - return error.Unexpected; - } -}; diff --git a/lib/std/os/linux/IoUring.zig b/lib/std/os/linux/IoUring.zig index 4992a352d21b..b3d6994275e9 100644 --- a/lib/std/os/linux/IoUring.zig +++ b/lib/std/os/linux/IoUring.zig @@ -1,14 +1,17 @@ const IoUring = @This(); -const std = @import("std"); + const builtin = @import("builtin"); +const is_linux = builtin.os.tag == .linux; + +const std = @import("../../std.zig"); +const Io = std.Io; +const Allocator = std.mem.Allocator; const assert = std.debug.assert; -const mem = std.mem; -const net = std.Io.net; const posix = std.posix; const linux = std.os.linux; const testing = std.testing; -const is_linux = builtin.os.tag == .linux; const page_size_min = std.heap.page_size_min; +const createSocketTestHarness = @import("IoUring/test.zig").createSocketTestHarness; fd: linux.fd_t = -1, sq: SubmissionQueue, @@ -22,7 +25,7 @@ features: u32, /// see https://github.com/torvalds/linux/blob/v5.8/fs/io_uring.c#L8027-L8050. /// Matches the interface of io_uring_queue_init() in liburing. pub fn init(entries: u16, flags: u32) !IoUring { - var params = mem.zeroInit(linux.io_uring_params, .{ + var params = std.mem.zeroInit(linux.io_uring_params, .{ .flags = flags, .sq_thread_idle = 1000, }); @@ -958,7 +961,7 @@ pub fn statx( fd: linux.fd_t, path: [:0]const u8, flags: u32, - mask: u32, + mask: linux.STATX, buf: *linux.Statx, ) !*linux.io_uring_sqe { const sqe = try self.get_sqe(); @@ -1309,7 +1312,7 @@ pub fn unregister_buffers(self: *IoUring) !void { /// io_uring subsystem of the running kernel. The io_uring_probe contains the /// list of supported operations. pub fn get_probe(self: *IoUring) !linux.io_uring_probe { - var probe = mem.zeroInit(linux.io_uring_probe, .{}); + var probe = std.mem.zeroInit(linux.io_uring_probe, .{}); const res = linux.io_uring_register(self.fd, .REGISTER_PROBE, &probe, probe.ops.len); try handle_register_buf_ring_result(res); return probe; @@ -1636,7 +1639,7 @@ pub const BufferGroup = struct { pub fn init( ring: *IoUring, - allocator: mem.Allocator, + allocator: Allocator, group_id: u16, buffer_size: u32, buffers_count: u16, @@ -1670,7 +1673,7 @@ pub const BufferGroup = struct { }; } - pub fn deinit(self: *BufferGroup, allocator: mem.Allocator) void { + pub fn deinit(self: *BufferGroup, allocator: Allocator) void { free_buf_ring(self.ring.fd, self.br, self.buffers_count, self.group_id); allocator.free(self.buffers); allocator.free(self.heads); @@ -1695,7 +1698,7 @@ pub const BufferGroup = struct { } // Get buffer by id. - fn get_by_id(self: *BufferGroup, buffer_id: u16) []u8 { + pub fn get_by_id(self: *BufferGroup, buffer_id: u16) []u8 { const pos = self.buffer_size * buffer_id; return self.buffers[pos .. pos + self.buffer_size][self.heads[buffer_id]..]; } @@ -1764,7 +1767,7 @@ fn register_buf_ring( group_id: u16, flags: linux.io_uring_buf_reg.Flags, ) !void { - var reg = mem.zeroInit(linux.io_uring_buf_reg, .{ + var reg = std.mem.zeroInit(linux.io_uring_buf_reg, .{ .ring_addr = addr, .ring_entries = entries, .bgid = group_id, @@ -1781,7 +1784,7 @@ fn register_buf_ring( } fn unregister_buf_ring(fd: linux.fd_t, group_id: u16) !void { - var reg = mem.zeroInit(linux.io_uring_buf_reg, .{ + var reg = std.mem.zeroInit(linux.io_uring_buf_reg, .{ .bgid = group_id, }); const res = linux.io_uring_register( @@ -1848,731 +1851,13 @@ pub fn buf_ring_advance(br: *linux.io_uring_buf_ring, count: u16) void { @atomicStore(u16, &br.tail, tail, .release); } -test "structs/offsets/entries" { - if (!is_linux) return error.SkipZigTest; - - try testing.expectEqual(@as(usize, 120), @sizeOf(linux.io_uring_params)); - try testing.expectEqual(@as(usize, 64), @sizeOf(linux.io_uring_sqe)); - try testing.expectEqual(@as(usize, 16), @sizeOf(linux.io_uring_cqe)); - - try testing.expectEqual(0, linux.IORING_OFF_SQ_RING); - try testing.expectEqual(0x8000000, linux.IORING_OFF_CQ_RING); - try testing.expectEqual(0x10000000, linux.IORING_OFF_SQES); - - try testing.expectError(error.EntriesZero, IoUring.init(0, 0)); - try testing.expectError(error.EntriesNotPowerOfTwo, IoUring.init(3, 0)); -} - -test "nop" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(1, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer { - ring.deinit(); - testing.expectEqual(@as(linux.fd_t, -1), ring.fd) catch @panic("test failed"); - } - - const sqe = try ring.nop(0xaaaaaaaa); - try testing.expectEqual(linux.io_uring_sqe{ - .opcode = .NOP, - .flags = 0, - .ioprio = 0, - .fd = 0, - .off = 0, - .addr = 0, - .len = 0, - .rw_flags = 0, - .user_data = 0xaaaaaaaa, - .buf_index = 0, - .personality = 0, - .splice_fd_in = 0, - .addr3 = 0, - .resv = 0, - }, sqe.*); - - try testing.expectEqual(@as(u32, 0), ring.sq.sqe_head); - try testing.expectEqual(@as(u32, 1), ring.sq.sqe_tail); - try testing.expectEqual(@as(u32, 0), ring.sq.tail.*); - try testing.expectEqual(@as(u32, 0), ring.cq.head.*); - try testing.expectEqual(@as(u32, 1), ring.sq_ready()); - try testing.expectEqual(@as(u32, 0), ring.cq_ready()); - - try testing.expectEqual(@as(u32, 1), try ring.submit()); - try testing.expectEqual(@as(u32, 1), ring.sq.sqe_head); - try testing.expectEqual(@as(u32, 1), ring.sq.sqe_tail); - try testing.expectEqual(@as(u32, 1), ring.sq.tail.*); - try testing.expectEqual(@as(u32, 0), ring.cq.head.*); - try testing.expectEqual(@as(u32, 0), ring.sq_ready()); - - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0xaaaaaaaa, - .res = 0, - .flags = 0, - }, try ring.copy_cqe()); - try testing.expectEqual(@as(u32, 1), ring.cq.head.*); - try testing.expectEqual(@as(u32, 0), ring.cq_ready()); - - const sqe_barrier = try ring.nop(0xbbbbbbbb); - sqe_barrier.flags |= linux.IOSQE_IO_DRAIN; - try testing.expectEqual(@as(u32, 1), try ring.submit()); - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0xbbbbbbbb, - .res = 0, - .flags = 0, - }, try ring.copy_cqe()); - try testing.expectEqual(@as(u32, 2), ring.sq.sqe_head); - try testing.expectEqual(@as(u32, 2), ring.sq.sqe_tail); - try testing.expectEqual(@as(u32, 2), ring.sq.tail.*); - try testing.expectEqual(@as(u32, 2), ring.cq.head.*); -} - -test "readv" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(1, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - const fd = try posix.openZ("/dev/zero", .{ .ACCMODE = .RDONLY, .CLOEXEC = true }, 0); - defer posix.close(fd); - - // Linux Kernel 5.4 supports IORING_REGISTER_FILES but not sparse fd sets (i.e. an fd of -1). - // Linux Kernel 5.5 adds support for sparse fd sets. - // Compare: - // https://github.com/torvalds/linux/blob/v5.4/fs/io_uring.c#L3119-L3124 vs - // https://github.com/torvalds/linux/blob/v5.8/fs/io_uring.c#L6687-L6691 - // We therefore avoid stressing sparse fd sets here: - var registered_fds = [_]linux.fd_t{0} ** 1; - const fd_index = 0; - registered_fds[fd_index] = fd; - try ring.register_files(registered_fds[0..]); - - var buffer = [_]u8{42} ** 128; - var iovecs = [_]posix.iovec{posix.iovec{ .base = &buffer, .len = buffer.len }}; - const sqe = try ring.read(0xcccccccc, fd_index, .{ .iovecs = iovecs[0..] }, 0); - try testing.expectEqual(linux.IORING_OP.READV, sqe.opcode); - sqe.flags |= linux.IOSQE_FIXED_FILE; - - try testing.expectError(error.SubmissionQueueFull, ring.nop(0)); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0xcccccccc, - .res = buffer.len, - .flags = 0, - }, try ring.copy_cqe()); - try testing.expectEqualSlices(u8, &([_]u8{0} ** buffer.len), buffer[0..]); - - try ring.unregister_files(); -} - -test "writev/fsync/readv" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(4, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - var tmp = std.testing.tmpDir(.{}); - defer tmp.cleanup(); - - const path = "test_io_uring_writev_fsync_readv"; - const file = try tmp.dir.createFile(path, .{ .read = true, .truncate = true }); - defer file.close(); - const fd = file.handle; - - const buffer_write = [_]u8{42} ** 128; - const iovecs_write = [_]posix.iovec_const{ - posix.iovec_const{ .base = &buffer_write, .len = buffer_write.len }, - }; - var buffer_read = [_]u8{0} ** 128; - var iovecs_read = [_]posix.iovec{ - posix.iovec{ .base = &buffer_read, .len = buffer_read.len }, - }; - - const sqe_writev = try ring.writev(0xdddddddd, fd, iovecs_write[0..], 17); - try testing.expectEqual(linux.IORING_OP.WRITEV, sqe_writev.opcode); - try testing.expectEqual(@as(u64, 17), sqe_writev.off); - sqe_writev.flags |= linux.IOSQE_IO_LINK; - - const sqe_fsync = try ring.fsync(0xeeeeeeee, fd, 0); - try testing.expectEqual(linux.IORING_OP.FSYNC, sqe_fsync.opcode); - try testing.expectEqual(fd, sqe_fsync.fd); - sqe_fsync.flags |= linux.IOSQE_IO_LINK; - - const sqe_readv = try ring.read(0xffffffff, fd, .{ .iovecs = iovecs_read[0..] }, 17); - try testing.expectEqual(linux.IORING_OP.READV, sqe_readv.opcode); - try testing.expectEqual(@as(u64, 17), sqe_readv.off); - - try testing.expectEqual(@as(u32, 3), ring.sq_ready()); - try testing.expectEqual(@as(u32, 3), try ring.submit_and_wait(3)); - try testing.expectEqual(@as(u32, 0), ring.sq_ready()); - try testing.expectEqual(@as(u32, 3), ring.cq_ready()); - - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0xdddddddd, - .res = buffer_write.len, - .flags = 0, - }, try ring.copy_cqe()); - try testing.expectEqual(@as(u32, 2), ring.cq_ready()); - - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0xeeeeeeee, - .res = 0, - .flags = 0, - }, try ring.copy_cqe()); - try testing.expectEqual(@as(u32, 1), ring.cq_ready()); - - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0xffffffff, - .res = buffer_read.len, - .flags = 0, - }, try ring.copy_cqe()); - try testing.expectEqual(@as(u32, 0), ring.cq_ready()); - - try testing.expectEqualSlices(u8, buffer_write[0..], buffer_read[0..]); -} - -test "write/read" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(2, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - var tmp = std.testing.tmpDir(.{}); - defer tmp.cleanup(); - const path = "test_io_uring_write_read"; - const file = try tmp.dir.createFile(path, .{ .read = true, .truncate = true }); - defer file.close(); - const fd = file.handle; - - const buffer_write = [_]u8{97} ** 20; - var buffer_read = [_]u8{98} ** 20; - const sqe_write = try ring.write(0x11111111, fd, buffer_write[0..], 10); - try testing.expectEqual(linux.IORING_OP.WRITE, sqe_write.opcode); - try testing.expectEqual(@as(u64, 10), sqe_write.off); - sqe_write.flags |= linux.IOSQE_IO_LINK; - const sqe_read = try ring.read(0x22222222, fd, .{ .buffer = buffer_read[0..] }, 10); - try testing.expectEqual(linux.IORING_OP.READ, sqe_read.opcode); - try testing.expectEqual(@as(u64, 10), sqe_read.off); - try testing.expectEqual(@as(u32, 2), try ring.submit()); - - const cqe_write = try ring.copy_cqe(); - const cqe_read = try ring.copy_cqe(); - // Prior to Linux Kernel 5.6 this is the only way to test for read/write support: - // https://lwn.net/Articles/809820/ - if (cqe_write.err() == .INVAL) return error.SkipZigTest; - if (cqe_read.err() == .INVAL) return error.SkipZigTest; - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0x11111111, - .res = buffer_write.len, - .flags = 0, - }, cqe_write); - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0x22222222, - .res = buffer_read.len, - .flags = 0, - }, cqe_read); - try testing.expectEqualSlices(u8, buffer_write[0..], buffer_read[0..]); -} - -test "splice/read" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(4, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - var tmp = std.testing.tmpDir(.{}); - const path_src = "test_io_uring_splice_src"; - const file_src = try tmp.dir.createFile(path_src, .{ .read = true, .truncate = true }); - defer file_src.close(); - const fd_src = file_src.handle; - - const path_dst = "test_io_uring_splice_dst"; - const file_dst = try tmp.dir.createFile(path_dst, .{ .read = true, .truncate = true }); - defer file_dst.close(); - const fd_dst = file_dst.handle; - - const buffer_write = [_]u8{97} ** 20; - var buffer_read = [_]u8{98} ** 20; - _ = try file_src.write(&buffer_write); - - const fds = try posix.pipe(); - const pipe_offset: u64 = std.math.maxInt(u64); - - const sqe_splice_to_pipe = try ring.splice(0x11111111, fd_src, 0, fds[1], pipe_offset, buffer_write.len); - try testing.expectEqual(linux.IORING_OP.SPLICE, sqe_splice_to_pipe.opcode); - try testing.expectEqual(@as(u64, 0), sqe_splice_to_pipe.addr); - try testing.expectEqual(pipe_offset, sqe_splice_to_pipe.off); - sqe_splice_to_pipe.flags |= linux.IOSQE_IO_LINK; - - const sqe_splice_from_pipe = try ring.splice(0x22222222, fds[0], pipe_offset, fd_dst, 10, buffer_write.len); - try testing.expectEqual(linux.IORING_OP.SPLICE, sqe_splice_from_pipe.opcode); - try testing.expectEqual(pipe_offset, sqe_splice_from_pipe.addr); - try testing.expectEqual(@as(u64, 10), sqe_splice_from_pipe.off); - sqe_splice_from_pipe.flags |= linux.IOSQE_IO_LINK; - - const sqe_read = try ring.read(0x33333333, fd_dst, .{ .buffer = buffer_read[0..] }, 10); - try testing.expectEqual(linux.IORING_OP.READ, sqe_read.opcode); - try testing.expectEqual(@as(u64, 10), sqe_read.off); - try testing.expectEqual(@as(u32, 3), try ring.submit()); - - const cqe_splice_to_pipe = try ring.copy_cqe(); - const cqe_splice_from_pipe = try ring.copy_cqe(); - const cqe_read = try ring.copy_cqe(); - // Prior to Linux Kernel 5.6 this is the only way to test for splice/read support: - // https://lwn.net/Articles/809820/ - if (cqe_splice_to_pipe.err() == .INVAL) return error.SkipZigTest; - if (cqe_splice_from_pipe.err() == .INVAL) return error.SkipZigTest; - if (cqe_read.err() == .INVAL) return error.SkipZigTest; - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0x11111111, - .res = buffer_write.len, - .flags = 0, - }, cqe_splice_to_pipe); - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0x22222222, - .res = buffer_write.len, - .flags = 0, - }, cqe_splice_from_pipe); - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0x33333333, - .res = buffer_read.len, - .flags = 0, - }, cqe_read); - try testing.expectEqualSlices(u8, buffer_write[0..], buffer_read[0..]); -} - -test "write_fixed/read_fixed" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(2, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - var tmp = std.testing.tmpDir(.{}); - defer tmp.cleanup(); - - const path = "test_io_uring_write_read_fixed"; - const file = try tmp.dir.createFile(path, .{ .read = true, .truncate = true }); - defer file.close(); - const fd = file.handle; - - var raw_buffers: [2][11]u8 = undefined; - // First buffer will be written to the file. - @memset(&raw_buffers[0], 'z'); - raw_buffers[0][0.."foobar".len].* = "foobar".*; - - var buffers = [2]posix.iovec{ - .{ .base = &raw_buffers[0], .len = raw_buffers[0].len }, - .{ .base = &raw_buffers[1], .len = raw_buffers[1].len }, - }; - ring.register_buffers(&buffers) catch |err| switch (err) { - error.SystemResources => { - // See https://github.com/ziglang/zig/issues/15362 - return error.SkipZigTest; - }, - else => |e| return e, - }; - - const sqe_write = try ring.write_fixed(0x45454545, fd, &buffers[0], 3, 0); - try testing.expectEqual(linux.IORING_OP.WRITE_FIXED, sqe_write.opcode); - try testing.expectEqual(@as(u64, 3), sqe_write.off); - sqe_write.flags |= linux.IOSQE_IO_LINK; - - const sqe_read = try ring.read_fixed(0x12121212, fd, &buffers[1], 0, 1); - try testing.expectEqual(linux.IORING_OP.READ_FIXED, sqe_read.opcode); - try testing.expectEqual(@as(u64, 0), sqe_read.off); - - try testing.expectEqual(@as(u32, 2), try ring.submit()); - - const cqe_write = try ring.copy_cqe(); - const cqe_read = try ring.copy_cqe(); - - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0x45454545, - .res = @as(i32, @intCast(buffers[0].len)), - .flags = 0, - }, cqe_write); - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0x12121212, - .res = @as(i32, @intCast(buffers[1].len)), - .flags = 0, - }, cqe_read); - - try testing.expectEqualSlices(u8, "\x00\x00\x00", buffers[1].base[0..3]); - try testing.expectEqualSlices(u8, "foobar", buffers[1].base[3..9]); - try testing.expectEqualSlices(u8, "zz", buffers[1].base[9..11]); -} - -test "openat" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(1, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - var tmp = std.testing.tmpDir(.{}); - defer tmp.cleanup(); - - const path = "test_io_uring_openat"; - - // Workaround for LLVM bug: https://github.com/ziglang/zig/issues/12014 - const path_addr = if (builtin.zig_backend == .stage2_llvm) p: { - var workaround = path; - _ = &workaround; - break :p @intFromPtr(workaround); - } else @intFromPtr(path); - - const flags: linux.O = .{ .CLOEXEC = true, .ACCMODE = .RDWR, .CREAT = true }; - const mode: posix.mode_t = 0o666; - const sqe_openat = try ring.openat(0x33333333, tmp.dir.fd, path, flags, mode); - try testing.expectEqual(linux.io_uring_sqe{ - .opcode = .OPENAT, - .flags = 0, - .ioprio = 0, - .fd = tmp.dir.fd, - .off = 0, - .addr = path_addr, - .len = mode, - .rw_flags = @bitCast(flags), - .user_data = 0x33333333, - .buf_index = 0, - .personality = 0, - .splice_fd_in = 0, - .addr3 = 0, - .resv = 0, - }, sqe_openat.*); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - const cqe_openat = try ring.copy_cqe(); - try testing.expectEqual(@as(u64, 0x33333333), cqe_openat.user_data); - if (cqe_openat.err() == .INVAL) return error.SkipZigTest; - if (cqe_openat.err() == .BADF) return error.SkipZigTest; - if (cqe_openat.res <= 0) std.debug.print("\ncqe_openat.res={}\n", .{cqe_openat.res}); - try testing.expect(cqe_openat.res > 0); - try testing.expectEqual(@as(u32, 0), cqe_openat.flags); - - posix.close(cqe_openat.res); -} - -test "close" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(1, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - var tmp = std.testing.tmpDir(.{}); - defer tmp.cleanup(); - - const path = "test_io_uring_close"; - const file = try tmp.dir.createFile(path, .{}); - errdefer file.close(); - - const sqe_close = try ring.close(0x44444444, file.handle); - try testing.expectEqual(linux.IORING_OP.CLOSE, sqe_close.opcode); - try testing.expectEqual(file.handle, sqe_close.fd); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - const cqe_close = try ring.copy_cqe(); - if (cqe_close.err() == .INVAL) return error.SkipZigTest; - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0x44444444, - .res = 0, - .flags = 0, - }, cqe_close); -} - -test "accept/connect/send/recv" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(16, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - const socket_test_harness = try createSocketTestHarness(&ring); - defer socket_test_harness.close(); - - const buffer_send = [_]u8{ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 }; - var buffer_recv = [_]u8{ 0, 1, 0, 1, 0 }; - - const sqe_send = try ring.send(0xeeeeeeee, socket_test_harness.client, buffer_send[0..], 0); - sqe_send.flags |= linux.IOSQE_IO_LINK; - _ = try ring.recv(0xffffffff, socket_test_harness.server, .{ .buffer = buffer_recv[0..] }, 0); - try testing.expectEqual(@as(u32, 2), try ring.submit()); - - const cqe_send = try ring.copy_cqe(); - if (cqe_send.err() == .INVAL) return error.SkipZigTest; - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0xeeeeeeee, - .res = buffer_send.len, - .flags = 0, - }, cqe_send); - - const cqe_recv = try ring.copy_cqe(); - if (cqe_recv.err() == .INVAL) return error.SkipZigTest; - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0xffffffff, - .res = buffer_recv.len, - // ignore IORING_CQE_F_SOCK_NONEMPTY since it is only set on some systems - .flags = cqe_recv.flags & linux.IORING_CQE_F_SOCK_NONEMPTY, - }, cqe_recv); - - try testing.expectEqualSlices(u8, buffer_send[0..buffer_recv.len], buffer_recv[0..]); -} - -test "sendmsg/recvmsg" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(2, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - var address_server: linux.sockaddr.in = .{ - .port = 0, - .addr = @bitCast([4]u8{ 127, 0, 0, 1 }), - }; - - const server = try posix.socket(address_server.family, posix.SOCK.DGRAM, 0); - defer posix.close(server); - try posix.setsockopt(server, posix.SOL.SOCKET, posix.SO.REUSEPORT, &mem.toBytes(@as(c_int, 1))); - try posix.setsockopt(server, posix.SOL.SOCKET, posix.SO.REUSEADDR, &mem.toBytes(@as(c_int, 1))); - try posix.bind(server, addrAny(&address_server), @sizeOf(linux.sockaddr.in)); - - // set address_server to the OS-chosen IP/port. - var slen: posix.socklen_t = @sizeOf(linux.sockaddr.in); - try posix.getsockname(server, addrAny(&address_server), &slen); - - const client = try posix.socket(address_server.family, posix.SOCK.DGRAM, 0); - defer posix.close(client); - - const buffer_send = [_]u8{42} ** 128; - const iovecs_send = [_]posix.iovec_const{ - posix.iovec_const{ .base = &buffer_send, .len = buffer_send.len }, - }; - const msg_send: linux.msghdr_const = .{ - .name = addrAny(&address_server), - .namelen = @sizeOf(linux.sockaddr.in), - .iov = &iovecs_send, - .iovlen = 1, - .control = null, - .controllen = 0, - .flags = 0, - }; - const sqe_sendmsg = try ring.sendmsg(0x11111111, client, &msg_send, 0); - sqe_sendmsg.flags |= linux.IOSQE_IO_LINK; - try testing.expectEqual(linux.IORING_OP.SENDMSG, sqe_sendmsg.opcode); - try testing.expectEqual(client, sqe_sendmsg.fd); - - var buffer_recv = [_]u8{0} ** 128; - var iovecs_recv = [_]posix.iovec{ - posix.iovec{ .base = &buffer_recv, .len = buffer_recv.len }, - }; - var address_recv: linux.sockaddr.in = .{ - .port = 0, - .addr = 0, - }; - var msg_recv: linux.msghdr = .{ - .name = addrAny(&address_recv), - .namelen = @sizeOf(linux.sockaddr.in), - .iov = &iovecs_recv, - .iovlen = 1, - .control = null, - .controllen = 0, - .flags = 0, - }; - const sqe_recvmsg = try ring.recvmsg(0x22222222, server, &msg_recv, 0); - try testing.expectEqual(linux.IORING_OP.RECVMSG, sqe_recvmsg.opcode); - try testing.expectEqual(server, sqe_recvmsg.fd); - - try testing.expectEqual(@as(u32, 2), ring.sq_ready()); - try testing.expectEqual(@as(u32, 2), try ring.submit_and_wait(2)); - try testing.expectEqual(@as(u32, 0), ring.sq_ready()); - try testing.expectEqual(@as(u32, 2), ring.cq_ready()); - - const cqe_sendmsg = try ring.copy_cqe(); - if (cqe_sendmsg.res == -@as(i32, @intFromEnum(linux.E.INVAL))) return error.SkipZigTest; - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0x11111111, - .res = buffer_send.len, - .flags = 0, - }, cqe_sendmsg); - - const cqe_recvmsg = try ring.copy_cqe(); - if (cqe_recvmsg.res == -@as(i32, @intFromEnum(linux.E.INVAL))) return error.SkipZigTest; - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0x22222222, - .res = buffer_recv.len, - // ignore IORING_CQE_F_SOCK_NONEMPTY since it is set non-deterministically - .flags = cqe_recvmsg.flags & linux.IORING_CQE_F_SOCK_NONEMPTY, - }, cqe_recvmsg); - - try testing.expectEqualSlices(u8, buffer_send[0..buffer_recv.len], buffer_recv[0..]); -} - -test "timeout (after a relative time)" { +test BufferGroup { if (!is_linux) return error.SkipZigTest; const io = testing.io; + _ = io; - var ring = IoUring.init(1, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - const ms = 10; - const margin = 5; - const ts: linux.kernel_timespec = .{ .sec = 0, .nsec = ms * 1000000 }; - - const started = try std.Io.Clock.awake.now(io); - const sqe = try ring.timeout(0x55555555, &ts, 0, 0); - try testing.expectEqual(linux.IORING_OP.TIMEOUT, sqe.opcode); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - const cqe = try ring.copy_cqe(); - const stopped = try std.Io.Clock.awake.now(io); - - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0x55555555, - .res = -@as(i32, @intFromEnum(linux.E.TIME)), - .flags = 0, - }, cqe); - - // Tests should not depend on timings: skip test if outside margin. - const ms_elapsed = started.durationTo(stopped).toMilliseconds(); - if (ms_elapsed > margin) return error.SkipZigTest; -} - -test "timeout (after a number of completions)" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(2, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - const ts: linux.kernel_timespec = .{ .sec = 3, .nsec = 0 }; - const count_completions: u64 = 1; - const sqe_timeout = try ring.timeout(0x66666666, &ts, count_completions, 0); - try testing.expectEqual(linux.IORING_OP.TIMEOUT, sqe_timeout.opcode); - try testing.expectEqual(count_completions, sqe_timeout.off); - _ = try ring.nop(0x77777777); - try testing.expectEqual(@as(u32, 2), try ring.submit()); - - const cqe_nop = try ring.copy_cqe(); - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0x77777777, - .res = 0, - .flags = 0, - }, cqe_nop); - - const cqe_timeout = try ring.copy_cqe(); - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0x66666666, - .res = 0, - .flags = 0, - }, cqe_timeout); -} - -test "timeout_remove" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(2, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - const ts: linux.kernel_timespec = .{ .sec = 3, .nsec = 0 }; - const sqe_timeout = try ring.timeout(0x88888888, &ts, 0, 0); - try testing.expectEqual(linux.IORING_OP.TIMEOUT, sqe_timeout.opcode); - try testing.expectEqual(@as(u64, 0x88888888), sqe_timeout.user_data); - - const sqe_timeout_remove = try ring.timeout_remove(0x99999999, 0x88888888, 0); - try testing.expectEqual(linux.IORING_OP.TIMEOUT_REMOVE, sqe_timeout_remove.opcode); - try testing.expectEqual(@as(u64, 0x88888888), sqe_timeout_remove.addr); - try testing.expectEqual(@as(u64, 0x99999999), sqe_timeout_remove.user_data); - - try testing.expectEqual(@as(u32, 2), try ring.submit()); - - // The order in which the CQE arrive is not clearly documented and it changed with kernel 5.18: - // * kernel 5.10 gives user data 0x88888888 first, 0x99999999 second - // * kernel 5.18 gives user data 0x99999999 first, 0x88888888 second - - var cqes: [2]linux.io_uring_cqe = undefined; - cqes[0] = try ring.copy_cqe(); - cqes[1] = try ring.copy_cqe(); - - for (cqes) |cqe| { - // IORING_OP_TIMEOUT_REMOVE is not supported by this kernel version: - // Timeout remove operations set the fd to -1, which results in EBADF before EINVAL. - // We use IORING_FEAT_RW_CUR_POS as a safety check here to make sure we are at least pre-5.6. - // We don't want to skip this test for newer kernels. - if (cqe.user_data == 0x99999999 and - cqe.err() == .BADF and - (ring.features & linux.IORING_FEAT_RW_CUR_POS) == 0) - { - return error.SkipZigTest; - } - - try testing.expect(cqe.user_data == 0x88888888 or cqe.user_data == 0x99999999); - - if (cqe.user_data == 0x88888888) { - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0x88888888, - .res = -@as(i32, @intFromEnum(linux.E.CANCELED)), - .flags = 0, - }, cqe); - } else if (cqe.user_data == 0x99999999) { - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0x99999999, - .res = 0, - .flags = 0, - }, cqe); - } - } -} - -test "accept/connect/recv/link_timeout" { - if (!is_linux) return error.SkipZigTest; - + // Init IoUring var ring = IoUring.init(16, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -2580,2052 +1865,60 @@ test "accept/connect/recv/link_timeout" { }; defer ring.deinit(); - const socket_test_harness = try createSocketTestHarness(&ring); - defer socket_test_harness.close(); - - var buffer_recv = [_]u8{ 0, 1, 0, 1, 0 }; - - const sqe_recv = try ring.recv(0xffffffff, socket_test_harness.server, .{ .buffer = buffer_recv[0..] }, 0); - sqe_recv.flags |= linux.IOSQE_IO_LINK; - - const ts = linux.kernel_timespec{ .sec = 0, .nsec = 1000000 }; - _ = try ring.link_timeout(0x22222222, &ts, 0); - - const nr_wait = try ring.submit(); - try testing.expectEqual(@as(u32, 2), nr_wait); - - var i: usize = 0; - while (i < nr_wait) : (i += 1) { - const cqe = try ring.copy_cqe(); - switch (cqe.user_data) { - 0xffffffff => { - if (cqe.res != -@as(i32, @intFromEnum(linux.E.INTR)) and - cqe.res != -@as(i32, @intFromEnum(linux.E.CANCELED))) - { - std.debug.print("Req 0x{x} got {d}\n", .{ cqe.user_data, cqe.res }); - try testing.expect(false); - } - }, - 0x22222222 => { - if (cqe.res != -@as(i32, @intFromEnum(linux.E.ALREADY)) and - cqe.res != -@as(i32, @intFromEnum(linux.E.TIME))) - { - std.debug.print("Req 0x{x} got {d}\n", .{ cqe.user_data, cqe.res }); - try testing.expect(false); - } - }, - else => @panic("should not happen"), - } - } -} - -test "fallocate" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(1, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, + // Init buffer group for ring + const group_id: u16 = 1; // buffers group id + const buffers_count: u16 = 1; // number of buffers in buffer group + const buffer_size: usize = 128; // size of each buffer in group + var buf_grp = BufferGroup.init( + &ring, + testing.allocator, + group_id, + buffer_size, + buffers_count, + ) catch |err| switch (err) { + // kernel older than 5.19 + error.ArgumentsInvalid => return error.SkipZigTest, else => return err, }; - defer ring.deinit(); - - var tmp = std.testing.tmpDir(.{}); - defer tmp.cleanup(); - - const path = "test_io_uring_fallocate"; - const file = try tmp.dir.createFile(path, .{ .truncate = true, .mode = 0o666 }); - defer file.close(); - - try testing.expectEqual(@as(u64, 0), (try file.stat()).size); + defer buf_grp.deinit(testing.allocator); - const len: u64 = 65536; - const sqe = try ring.fallocate(0xaaaaaaaa, file.handle, 0, 0, len); - try testing.expectEqual(linux.IORING_OP.FALLOCATE, sqe.opcode); - try testing.expectEqual(file.handle, sqe.fd); - try testing.expectEqual(@as(u32, 1), try ring.submit()); + // Create client/server fds + const fds = try createSocketTestHarness(&ring); + defer fds.close(); + const data = [_]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe }; - const cqe = try ring.copy_cqe(); - switch (cqe.err()) { - .SUCCESS => {}, - // This kernel's io_uring does not yet implement fallocate(): - .INVAL => return error.SkipZigTest, - // This kernel does not implement fallocate(): - .NOSYS => return error.SkipZigTest, - // The filesystem containing the file referred to by fd does not support this operation; - // or the mode is not supported by the filesystem containing the file referred to by fd: - .OPNOTSUPP => return error.SkipZigTest, - else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + // Client sends data + { + _ = try ring.send(1, fds.client, data[0..], 0); + const submitted = try ring.submit(); + try testing.expectEqual(1, submitted); + const cqe_send = try ring.copy_cqe(); + if (cqe_send.err() == .INVAL) return error.SkipZigTest; + try testing.expectEqual(linux.io_uring_cqe{ .user_data = 1, .res = data.len, .flags = 0 }, cqe_send); } - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0xaaaaaaaa, - .res = 0, - .flags = 0, - }, cqe); - - try testing.expectEqual(len, (try file.stat()).size); -} - -test "statx" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(1, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - var tmp = std.testing.tmpDir(.{}); - defer tmp.cleanup(); - const path = "test_io_uring_statx"; - const file = try tmp.dir.createFile(path, .{ .truncate = true, .mode = 0o666 }); - defer file.close(); - try testing.expectEqual(@as(u64, 0), (try file.stat()).size); - - try file.writeAll("foobar"); + // Server uses buffer group receive + { + // Submit recv operation, buffer will be chosen from buffer group + _ = try buf_grp.recv(2, fds.server, 0); + const submitted = try ring.submit(); + try testing.expectEqual(1, submitted); - var buf: linux.Statx = undefined; - const sqe = try ring.statx( - 0xaaaaaaaa, - tmp.dir.fd, - path, - 0, - linux.STATX_SIZE, - &buf, - ); - try testing.expectEqual(linux.IORING_OP.STATX, sqe.opcode); - try testing.expectEqual(@as(i32, tmp.dir.fd), sqe.fd); - try testing.expectEqual(@as(u32, 1), try ring.submit()); + // ... when we have completion for recv operation + const cqe = try ring.copy_cqe(); + try testing.expectEqual(2, cqe.user_data); // matches submitted user_data + try testing.expect(cqe.res >= 0); // success + try testing.expectEqual(posix.E.SUCCESS, cqe.err()); + try testing.expectEqual(data.len, @as(usize, @intCast(cqe.res))); // cqe.res holds received data len - const cqe = try ring.copy_cqe(); - switch (cqe.err()) { - .SUCCESS => {}, - // This kernel's io_uring does not yet implement statx(): - .INVAL => return error.SkipZigTest, - // This kernel does not implement statx(): - .NOSYS => return error.SkipZigTest, - // The filesystem containing the file referred to by fd does not support this operation; - // or the mode is not supported by the filesystem containing the file referred to by fd: - .OPNOTSUPP => return error.SkipZigTest, - // not supported on older kernels (5.4) - .BADF => return error.SkipZigTest, - else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + // Get buffer from pool + const buf = try buf_grp.get(cqe); + try testing.expectEqualSlices(u8, &data, buf); + // Release buffer to the kernel when application is done with it + try buf_grp.put(cqe); } - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0xaaaaaaaa, - .res = 0, - .flags = 0, - }, cqe); - - try testing.expect(buf.mask & linux.STATX_SIZE == linux.STATX_SIZE); - try testing.expectEqual(@as(u64, 6), buf.size); -} - -test "accept/connect/recv/cancel" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(16, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - const socket_test_harness = try createSocketTestHarness(&ring); - defer socket_test_harness.close(); - - var buffer_recv = [_]u8{ 0, 1, 0, 1, 0 }; - - _ = try ring.recv(0xffffffff, socket_test_harness.server, .{ .buffer = buffer_recv[0..] }, 0); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - const sqe_cancel = try ring.cancel(0x99999999, 0xffffffff, 0); - try testing.expectEqual(linux.IORING_OP.ASYNC_CANCEL, sqe_cancel.opcode); - try testing.expectEqual(@as(u64, 0xffffffff), sqe_cancel.addr); - try testing.expectEqual(@as(u64, 0x99999999), sqe_cancel.user_data); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - var cqe_recv = try ring.copy_cqe(); - if (cqe_recv.err() == .INVAL) return error.SkipZigTest; - var cqe_cancel = try ring.copy_cqe(); - if (cqe_cancel.err() == .INVAL) return error.SkipZigTest; - - // The recv/cancel CQEs may arrive in any order, the recv CQE will sometimes come first: - if (cqe_recv.user_data == 0x99999999 and cqe_cancel.user_data == 0xffffffff) { - const a = cqe_recv; - const b = cqe_cancel; - cqe_recv = b; - cqe_cancel = a; - } - - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0xffffffff, - .res = -@as(i32, @intFromEnum(linux.E.CANCELED)), - .flags = 0, - }, cqe_recv); - - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0x99999999, - .res = 0, - .flags = 0, - }, cqe_cancel); -} - -test "register_files_update" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(1, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - const fd = try posix.openZ("/dev/zero", .{ .ACCMODE = .RDONLY, .CLOEXEC = true }, 0); - defer posix.close(fd); - - var registered_fds = [_]linux.fd_t{0} ** 2; - const fd_index = 0; - const fd_index2 = 1; - registered_fds[fd_index] = fd; - registered_fds[fd_index2] = -1; - - ring.register_files(registered_fds[0..]) catch |err| switch (err) { - // Happens when the kernel doesn't support sparse entry (-1) in the file descriptors array. - error.FileDescriptorInvalid => return error.SkipZigTest, - else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), - }; - - // Test IORING_REGISTER_FILES_UPDATE - // Only available since Linux 5.5 - - const fd2 = try posix.openZ("/dev/zero", .{ .ACCMODE = .RDONLY, .CLOEXEC = true }, 0); - defer posix.close(fd2); - - registered_fds[fd_index] = fd2; - registered_fds[fd_index2] = -1; - try ring.register_files_update(0, registered_fds[0..]); - - var buffer = [_]u8{42} ** 128; - { - const sqe = try ring.read(0xcccccccc, fd_index, .{ .buffer = &buffer }, 0); - try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode); - sqe.flags |= linux.IOSQE_FIXED_FILE; - - try testing.expectEqual(@as(u32, 1), try ring.submit()); - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0xcccccccc, - .res = buffer.len, - .flags = 0, - }, try ring.copy_cqe()); - try testing.expectEqualSlices(u8, &([_]u8{0} ** buffer.len), buffer[0..]); - } - - // Test with a non-zero offset - - registered_fds[fd_index] = -1; - registered_fds[fd_index2] = -1; - try ring.register_files_update(1, registered_fds[1..]); - - { - // Next read should still work since fd_index in the registered file descriptors hasn't been updated yet. - const sqe = try ring.read(0xcccccccc, fd_index, .{ .buffer = &buffer }, 0); - try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode); - sqe.flags |= linux.IOSQE_FIXED_FILE; - - try testing.expectEqual(@as(u32, 1), try ring.submit()); - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0xcccccccc, - .res = buffer.len, - .flags = 0, - }, try ring.copy_cqe()); - try testing.expectEqualSlices(u8, &([_]u8{0} ** buffer.len), buffer[0..]); - } - - try ring.register_files_update(0, registered_fds[0..]); - - { - // Now this should fail since both fds are sparse (-1) - const sqe = try ring.read(0xcccccccc, fd_index, .{ .buffer = &buffer }, 0); - try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode); - sqe.flags |= linux.IOSQE_FIXED_FILE; - - try testing.expectEqual(@as(u32, 1), try ring.submit()); - const cqe = try ring.copy_cqe(); - try testing.expectEqual(linux.E.BADF, cqe.err()); - } - - try ring.unregister_files(); -} - -test "shutdown" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(16, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - var address: linux.sockaddr.in = .{ - .port = 0, - .addr = @bitCast([4]u8{ 127, 0, 0, 1 }), - }; - - // Socket bound, expect shutdown to work - { - const server = try posix.socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); - defer posix.close(server); - try posix.setsockopt(server, posix.SOL.SOCKET, posix.SO.REUSEADDR, &mem.toBytes(@as(c_int, 1))); - try posix.bind(server, addrAny(&address), @sizeOf(linux.sockaddr.in)); - try posix.listen(server, 1); - - // set address to the OS-chosen IP/port. - var slen: posix.socklen_t = @sizeOf(linux.sockaddr.in); - try posix.getsockname(server, addrAny(&address), &slen); - - const shutdown_sqe = try ring.shutdown(0x445445445, server, linux.SHUT.RD); - try testing.expectEqual(linux.IORING_OP.SHUTDOWN, shutdown_sqe.opcode); - try testing.expectEqual(@as(i32, server), shutdown_sqe.fd); - - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - const cqe = try ring.copy_cqe(); - switch (cqe.err()) { - .SUCCESS => {}, - // This kernel's io_uring does not yet implement shutdown (kernel version < 5.11) - .INVAL => return error.SkipZigTest, - else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), - } - - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0x445445445, - .res = 0, - .flags = 0, - }, cqe); - } - - // Socket not bound, expect to fail with ENOTCONN - { - const server = try posix.socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); - defer posix.close(server); - - const shutdown_sqe = ring.shutdown(0x445445445, server, linux.SHUT.RD) catch |err| switch (err) { - else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), - }; - try testing.expectEqual(linux.IORING_OP.SHUTDOWN, shutdown_sqe.opcode); - try testing.expectEqual(@as(i32, server), shutdown_sqe.fd); - - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - const cqe = try ring.copy_cqe(); - try testing.expectEqual(@as(u64, 0x445445445), cqe.user_data); - try testing.expectEqual(linux.E.NOTCONN, cqe.err()); - } -} - -test "renameat" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(1, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - const old_path = "test_io_uring_renameat_old"; - const new_path = "test_io_uring_renameat_new"; - - var tmp = std.testing.tmpDir(.{}); - defer tmp.cleanup(); - - // Write old file with data - - const old_file = try tmp.dir.createFile(old_path, .{ .truncate = true, .mode = 0o666 }); - defer old_file.close(); - try old_file.writeAll("hello"); - - // Submit renameat - - const sqe = try ring.renameat( - 0x12121212, - tmp.dir.fd, - old_path, - tmp.dir.fd, - new_path, - 0, - ); - try testing.expectEqual(linux.IORING_OP.RENAMEAT, sqe.opcode); - try testing.expectEqual(@as(i32, tmp.dir.fd), sqe.fd); - try testing.expectEqual(@as(i32, tmp.dir.fd), @as(i32, @bitCast(sqe.len))); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - const cqe = try ring.copy_cqe(); - switch (cqe.err()) { - .SUCCESS => {}, - // This kernel's io_uring does not yet implement renameat (kernel version < 5.11) - .BADF, .INVAL => return error.SkipZigTest, - else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), - } - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0x12121212, - .res = 0, - .flags = 0, - }, cqe); - - // Validate that the old file doesn't exist anymore - try testing.expectError(error.FileNotFound, tmp.dir.openFile(old_path, .{})); - - // Validate that the new file exists with the proper content - var new_file_data: [16]u8 = undefined; - try testing.expectEqualStrings("hello", try tmp.dir.readFile(new_path, &new_file_data)); -} - -test "unlinkat" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(1, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - const path = "test_io_uring_unlinkat"; - - var tmp = std.testing.tmpDir(.{}); - defer tmp.cleanup(); - - // Write old file with data - - const file = try tmp.dir.createFile(path, .{ .truncate = true, .mode = 0o666 }); - defer file.close(); - - // Submit unlinkat - - const sqe = try ring.unlinkat( - 0x12121212, - tmp.dir.fd, - path, - 0, - ); - try testing.expectEqual(linux.IORING_OP.UNLINKAT, sqe.opcode); - try testing.expectEqual(@as(i32, tmp.dir.fd), sqe.fd); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - const cqe = try ring.copy_cqe(); - switch (cqe.err()) { - .SUCCESS => {}, - // This kernel's io_uring does not yet implement unlinkat (kernel version < 5.11) - .BADF, .INVAL => return error.SkipZigTest, - else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), - } - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0x12121212, - .res = 0, - .flags = 0, - }, cqe); - - // Validate that the file doesn't exist anymore - _ = tmp.dir.openFile(path, .{}) catch |err| switch (err) { - error.FileNotFound => {}, - else => std.debug.panic("unexpected error: {}", .{err}), - }; -} - -test "mkdirat" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(1, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - var tmp = std.testing.tmpDir(.{}); - defer tmp.cleanup(); - - const path = "test_io_uring_mkdirat"; - - // Submit mkdirat - - const sqe = try ring.mkdirat( - 0x12121212, - tmp.dir.fd, - path, - 0o0755, - ); - try testing.expectEqual(linux.IORING_OP.MKDIRAT, sqe.opcode); - try testing.expectEqual(@as(i32, tmp.dir.fd), sqe.fd); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - const cqe = try ring.copy_cqe(); - switch (cqe.err()) { - .SUCCESS => {}, - // This kernel's io_uring does not yet implement mkdirat (kernel version < 5.15) - .BADF, .INVAL => return error.SkipZigTest, - else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), - } - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0x12121212, - .res = 0, - .flags = 0, - }, cqe); - - // Validate that the directory exist - _ = try tmp.dir.openDir(path, .{}); -} - -test "symlinkat" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(1, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - var tmp = std.testing.tmpDir(.{}); - defer tmp.cleanup(); - - const path = "test_io_uring_symlinkat"; - const link_path = "test_io_uring_symlinkat_link"; - - const file = try tmp.dir.createFile(path, .{ .truncate = true, .mode = 0o666 }); - defer file.close(); - - // Submit symlinkat - - const sqe = try ring.symlinkat( - 0x12121212, - path, - tmp.dir.fd, - link_path, - ); - try testing.expectEqual(linux.IORING_OP.SYMLINKAT, sqe.opcode); - try testing.expectEqual(@as(i32, tmp.dir.fd), sqe.fd); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - const cqe = try ring.copy_cqe(); - switch (cqe.err()) { - .SUCCESS => {}, - // This kernel's io_uring does not yet implement symlinkat (kernel version < 5.15) - .BADF, .INVAL => return error.SkipZigTest, - else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), - } - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0x12121212, - .res = 0, - .flags = 0, - }, cqe); - - // Validate that the symlink exist - _ = try tmp.dir.openFile(link_path, .{}); -} - -test "linkat" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(1, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - var tmp = std.testing.tmpDir(.{}); - defer tmp.cleanup(); - - const first_path = "test_io_uring_linkat_first"; - const second_path = "test_io_uring_linkat_second"; - - // Write file with data - - const first_file = try tmp.dir.createFile(first_path, .{ .truncate = true, .mode = 0o666 }); - defer first_file.close(); - try first_file.writeAll("hello"); - - // Submit linkat - - const sqe = try ring.linkat( - 0x12121212, - tmp.dir.fd, - first_path, - tmp.dir.fd, - second_path, - 0, - ); - try testing.expectEqual(linux.IORING_OP.LINKAT, sqe.opcode); - try testing.expectEqual(@as(i32, tmp.dir.fd), sqe.fd); - try testing.expectEqual(@as(i32, tmp.dir.fd), @as(i32, @bitCast(sqe.len))); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - const cqe = try ring.copy_cqe(); - switch (cqe.err()) { - .SUCCESS => {}, - // This kernel's io_uring does not yet implement linkat (kernel version < 5.15) - .BADF, .INVAL => return error.SkipZigTest, - else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), - } - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0x12121212, - .res = 0, - .flags = 0, - }, cqe); - - // Validate the second file - var second_file_data: [16]u8 = undefined; - try testing.expectEqualStrings("hello", try tmp.dir.readFile(second_path, &second_file_data)); -} - -test "provide_buffers: read" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(1, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - const fd = try posix.openZ("/dev/zero", .{ .ACCMODE = .RDONLY, .CLOEXEC = true }, 0); - defer posix.close(fd); - - const group_id = 1337; - const buffer_id = 0; - - const buffer_len = 128; - - var buffers: [4][buffer_len]u8 = undefined; - - // Provide 4 buffers - - { - const sqe = try ring.provide_buffers(0xcccccccc, @as([*]u8, @ptrCast(&buffers)), buffer_len, buffers.len, group_id, buffer_id); - try testing.expectEqual(linux.IORING_OP.PROVIDE_BUFFERS, sqe.opcode); - try testing.expectEqual(@as(i32, buffers.len), sqe.fd); - try testing.expectEqual(@as(u32, buffers[0].len), sqe.len); - try testing.expectEqual(@as(u16, group_id), sqe.buf_index); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - const cqe = try ring.copy_cqe(); - switch (cqe.err()) { - // Happens when the kernel is < 5.7 - .INVAL, .BADF => return error.SkipZigTest, - .SUCCESS => {}, - else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), - } - try testing.expectEqual(@as(u64, 0xcccccccc), cqe.user_data); - } - - // Do 4 reads which should consume all buffers - - var i: usize = 0; - while (i < buffers.len) : (i += 1) { - const sqe = try ring.read(0xdededede, fd, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); - try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode); - try testing.expectEqual(@as(i32, fd), sqe.fd); - try testing.expectEqual(@as(u64, 0), sqe.addr); - try testing.expectEqual(@as(u32, buffer_len), sqe.len); - try testing.expectEqual(@as(u16, group_id), sqe.buf_index); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - const cqe = try ring.copy_cqe(); - switch (cqe.err()) { - .SUCCESS => {}, - else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), - } - - try testing.expect(cqe.flags & linux.IORING_CQE_F_BUFFER == linux.IORING_CQE_F_BUFFER); - const used_buffer_id = cqe.flags >> 16; - try testing.expect(used_buffer_id >= 0 and used_buffer_id <= 3); - try testing.expectEqual(@as(i32, buffer_len), cqe.res); - - try testing.expectEqual(@as(u64, 0xdededede), cqe.user_data); - try testing.expectEqualSlices(u8, &([_]u8{0} ** buffer_len), buffers[used_buffer_id][0..@as(usize, @intCast(cqe.res))]); - } - - // This read should fail - - { - const sqe = try ring.read(0xdfdfdfdf, fd, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); - try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode); - try testing.expectEqual(@as(i32, fd), sqe.fd); - try testing.expectEqual(@as(u64, 0), sqe.addr); - try testing.expectEqual(@as(u32, buffer_len), sqe.len); - try testing.expectEqual(@as(u16, group_id), sqe.buf_index); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - const cqe = try ring.copy_cqe(); - switch (cqe.err()) { - // Expected - .NOBUFS => {}, - .SUCCESS => std.debug.panic("unexpected success", .{}), - else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), - } - try testing.expectEqual(@as(u64, 0xdfdfdfdf), cqe.user_data); - } - - // Provide 1 buffer again - - // Deliberately put something we don't expect in the buffers - @memset(mem.sliceAsBytes(&buffers), 42); - - const reprovided_buffer_id = 2; - - { - _ = try ring.provide_buffers(0xabababab, @as([*]u8, @ptrCast(&buffers[reprovided_buffer_id])), buffer_len, 1, group_id, reprovided_buffer_id); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - const cqe = try ring.copy_cqe(); - switch (cqe.err()) { - .SUCCESS => {}, - else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), - } - } - - // Final read which should work - - { - const sqe = try ring.read(0xdfdfdfdf, fd, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); - try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode); - try testing.expectEqual(@as(i32, fd), sqe.fd); - try testing.expectEqual(@as(u64, 0), sqe.addr); - try testing.expectEqual(@as(u32, buffer_len), sqe.len); - try testing.expectEqual(@as(u16, group_id), sqe.buf_index); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - const cqe = try ring.copy_cqe(); - switch (cqe.err()) { - .SUCCESS => {}, - else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), - } - - try testing.expect(cqe.flags & linux.IORING_CQE_F_BUFFER == linux.IORING_CQE_F_BUFFER); - const used_buffer_id = cqe.flags >> 16; - try testing.expectEqual(used_buffer_id, reprovided_buffer_id); - try testing.expectEqual(@as(i32, buffer_len), cqe.res); - try testing.expectEqual(@as(u64, 0xdfdfdfdf), cqe.user_data); - try testing.expectEqualSlices(u8, &([_]u8{0} ** buffer_len), buffers[used_buffer_id][0..@as(usize, @intCast(cqe.res))]); - } -} - -test "remove_buffers" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(1, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - const fd = try posix.openZ("/dev/zero", .{ .ACCMODE = .RDONLY, .CLOEXEC = true }, 0); - defer posix.close(fd); - - const group_id = 1337; - const buffer_id = 0; - - const buffer_len = 128; - - var buffers: [4][buffer_len]u8 = undefined; - - // Provide 4 buffers - - { - _ = try ring.provide_buffers(0xcccccccc, @as([*]u8, @ptrCast(&buffers)), buffer_len, buffers.len, group_id, buffer_id); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - const cqe = try ring.copy_cqe(); - switch (cqe.err()) { - .INVAL, .BADF => return error.SkipZigTest, - .SUCCESS => {}, - else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), - } - try testing.expectEqual(@as(u64, 0xcccccccc), cqe.user_data); - } - - // Remove 3 buffers - - { - const sqe = try ring.remove_buffers(0xbababababa, 3, group_id); - try testing.expectEqual(linux.IORING_OP.REMOVE_BUFFERS, sqe.opcode); - try testing.expectEqual(@as(i32, 3), sqe.fd); - try testing.expectEqual(@as(u64, 0), sqe.addr); - try testing.expectEqual(@as(u16, group_id), sqe.buf_index); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - const cqe = try ring.copy_cqe(); - switch (cqe.err()) { - .SUCCESS => {}, - else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), - } - try testing.expectEqual(@as(u64, 0xbababababa), cqe.user_data); - } - - // This read should work - - { - _ = try ring.read(0xdfdfdfdf, fd, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - const cqe = try ring.copy_cqe(); - switch (cqe.err()) { - .SUCCESS => {}, - else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), - } - - try testing.expect(cqe.flags & linux.IORING_CQE_F_BUFFER == linux.IORING_CQE_F_BUFFER); - const used_buffer_id = cqe.flags >> 16; - try testing.expect(used_buffer_id >= 0 and used_buffer_id < 4); - try testing.expectEqual(@as(i32, buffer_len), cqe.res); - try testing.expectEqual(@as(u64, 0xdfdfdfdf), cqe.user_data); - try testing.expectEqualSlices(u8, &([_]u8{0} ** buffer_len), buffers[used_buffer_id][0..@as(usize, @intCast(cqe.res))]); - } - - // Final read should _not_ work - - { - _ = try ring.read(0xdfdfdfdf, fd, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - const cqe = try ring.copy_cqe(); - switch (cqe.err()) { - // Expected - .NOBUFS => {}, - .SUCCESS => std.debug.panic("unexpected success", .{}), - else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), - } - } -} - -test "provide_buffers: accept/connect/send/recv" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(16, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - const group_id = 1337; - const buffer_id = 0; - - const buffer_len = 128; - var buffers: [4][buffer_len]u8 = undefined; - - // Provide 4 buffers - - { - const sqe = try ring.provide_buffers(0xcccccccc, @as([*]u8, @ptrCast(&buffers)), buffer_len, buffers.len, group_id, buffer_id); - try testing.expectEqual(linux.IORING_OP.PROVIDE_BUFFERS, sqe.opcode); - try testing.expectEqual(@as(i32, buffers.len), sqe.fd); - try testing.expectEqual(@as(u32, buffer_len), sqe.len); - try testing.expectEqual(@as(u16, group_id), sqe.buf_index); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - const cqe = try ring.copy_cqe(); - switch (cqe.err()) { - // Happens when the kernel is < 5.7 - .INVAL => return error.SkipZigTest, - // Happens on the kernel 5.4 - .BADF => return error.SkipZigTest, - .SUCCESS => {}, - else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), - } - try testing.expectEqual(@as(u64, 0xcccccccc), cqe.user_data); - } - - const socket_test_harness = try createSocketTestHarness(&ring); - defer socket_test_harness.close(); - - // Do 4 send on the socket - - { - var i: usize = 0; - while (i < buffers.len) : (i += 1) { - _ = try ring.send(0xdeaddead, socket_test_harness.server, &([_]u8{'z'} ** buffer_len), 0); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - } - - var cqes: [4]linux.io_uring_cqe = undefined; - try testing.expectEqual(@as(u32, 4), try ring.copy_cqes(&cqes, 4)); - } - - // Do 4 recv which should consume all buffers - - // Deliberately put something we don't expect in the buffers - @memset(mem.sliceAsBytes(&buffers), 1); - - var i: usize = 0; - while (i < buffers.len) : (i += 1) { - const sqe = try ring.recv(0xdededede, socket_test_harness.client, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); - try testing.expectEqual(linux.IORING_OP.RECV, sqe.opcode); - try testing.expectEqual(@as(i32, socket_test_harness.client), sqe.fd); - try testing.expectEqual(@as(u64, 0), sqe.addr); - try testing.expectEqual(@as(u32, buffer_len), sqe.len); - try testing.expectEqual(@as(u16, group_id), sqe.buf_index); - try testing.expectEqual(@as(u32, 0), sqe.rw_flags); - try testing.expectEqual(@as(u32, linux.IOSQE_BUFFER_SELECT), sqe.flags); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - const cqe = try ring.copy_cqe(); - switch (cqe.err()) { - .SUCCESS => {}, - else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), - } - - try testing.expect(cqe.flags & linux.IORING_CQE_F_BUFFER == linux.IORING_CQE_F_BUFFER); - const used_buffer_id = cqe.flags >> 16; - try testing.expect(used_buffer_id >= 0 and used_buffer_id <= 3); - try testing.expectEqual(@as(i32, buffer_len), cqe.res); - - try testing.expectEqual(@as(u64, 0xdededede), cqe.user_data); - const buffer = buffers[used_buffer_id][0..@as(usize, @intCast(cqe.res))]; - try testing.expectEqualSlices(u8, &([_]u8{'z'} ** buffer_len), buffer); - } - - // This recv should fail - - { - const sqe = try ring.recv(0xdfdfdfdf, socket_test_harness.client, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); - try testing.expectEqual(linux.IORING_OP.RECV, sqe.opcode); - try testing.expectEqual(@as(i32, socket_test_harness.client), sqe.fd); - try testing.expectEqual(@as(u64, 0), sqe.addr); - try testing.expectEqual(@as(u32, buffer_len), sqe.len); - try testing.expectEqual(@as(u16, group_id), sqe.buf_index); - try testing.expectEqual(@as(u32, 0), sqe.rw_flags); - try testing.expectEqual(@as(u32, linux.IOSQE_BUFFER_SELECT), sqe.flags); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - const cqe = try ring.copy_cqe(); - switch (cqe.err()) { - // Expected - .NOBUFS => {}, - .SUCCESS => std.debug.panic("unexpected success", .{}), - else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), - } - try testing.expectEqual(@as(u64, 0xdfdfdfdf), cqe.user_data); - } - - // Provide 1 buffer again - - const reprovided_buffer_id = 2; - - { - _ = try ring.provide_buffers(0xabababab, @as([*]u8, @ptrCast(&buffers[reprovided_buffer_id])), buffer_len, 1, group_id, reprovided_buffer_id); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - const cqe = try ring.copy_cqe(); - switch (cqe.err()) { - .SUCCESS => {}, - else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), - } - } - - // Redo 1 send on the server socket - - { - _ = try ring.send(0xdeaddead, socket_test_harness.server, &([_]u8{'w'} ** buffer_len), 0); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - _ = try ring.copy_cqe(); - } - - // Final recv which should work - - // Deliberately put something we don't expect in the buffers - @memset(mem.sliceAsBytes(&buffers), 1); - - { - const sqe = try ring.recv(0xdfdfdfdf, socket_test_harness.client, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); - try testing.expectEqual(linux.IORING_OP.RECV, sqe.opcode); - try testing.expectEqual(@as(i32, socket_test_harness.client), sqe.fd); - try testing.expectEqual(@as(u64, 0), sqe.addr); - try testing.expectEqual(@as(u32, buffer_len), sqe.len); - try testing.expectEqual(@as(u16, group_id), sqe.buf_index); - try testing.expectEqual(@as(u32, 0), sqe.rw_flags); - try testing.expectEqual(@as(u32, linux.IOSQE_BUFFER_SELECT), sqe.flags); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - const cqe = try ring.copy_cqe(); - switch (cqe.err()) { - .SUCCESS => {}, - else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), - } - - try testing.expect(cqe.flags & linux.IORING_CQE_F_BUFFER == linux.IORING_CQE_F_BUFFER); - const used_buffer_id = cqe.flags >> 16; - try testing.expectEqual(used_buffer_id, reprovided_buffer_id); - try testing.expectEqual(@as(i32, buffer_len), cqe.res); - try testing.expectEqual(@as(u64, 0xdfdfdfdf), cqe.user_data); - const buffer = buffers[used_buffer_id][0..@as(usize, @intCast(cqe.res))]; - try testing.expectEqualSlices(u8, &([_]u8{'w'} ** buffer_len), buffer); - } -} - -/// Used for testing server/client interactions. -const SocketTestHarness = struct { - listener: posix.socket_t, - server: posix.socket_t, - client: posix.socket_t, - - fn close(self: SocketTestHarness) void { - posix.close(self.client); - posix.close(self.listener); - } -}; - -fn createSocketTestHarness(ring: *IoUring) !SocketTestHarness { - // Create a TCP server socket - var address: linux.sockaddr.in = .{ - .port = 0, - .addr = @bitCast([4]u8{ 127, 0, 0, 1 }), - }; - const listener_socket = try createListenerSocket(&address); - errdefer posix.close(listener_socket); - - // Submit 1 accept - var accept_addr: posix.sockaddr = undefined; - var accept_addr_len: posix.socklen_t = @sizeOf(@TypeOf(accept_addr)); - _ = try ring.accept(0xaaaaaaaa, listener_socket, &accept_addr, &accept_addr_len, 0); - - // Create a TCP client socket - const client = try posix.socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); - errdefer posix.close(client); - _ = try ring.connect(0xcccccccc, client, addrAny(&address), @sizeOf(linux.sockaddr.in)); - - try testing.expectEqual(@as(u32, 2), try ring.submit()); - - var cqe_accept = try ring.copy_cqe(); - if (cqe_accept.err() == .INVAL) return error.SkipZigTest; - var cqe_connect = try ring.copy_cqe(); - if (cqe_connect.err() == .INVAL) return error.SkipZigTest; - - // The accept/connect CQEs may arrive in any order, the connect CQE will sometimes come first: - if (cqe_accept.user_data == 0xcccccccc and cqe_connect.user_data == 0xaaaaaaaa) { - const a = cqe_accept; - const b = cqe_connect; - cqe_accept = b; - cqe_connect = a; - } - - try testing.expectEqual(@as(u64, 0xaaaaaaaa), cqe_accept.user_data); - if (cqe_accept.res <= 0) std.debug.print("\ncqe_accept.res={}\n", .{cqe_accept.res}); - try testing.expect(cqe_accept.res > 0); - try testing.expectEqual(@as(u32, 0), cqe_accept.flags); - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0xcccccccc, - .res = 0, - .flags = 0, - }, cqe_connect); - - // All good - - return SocketTestHarness{ - .listener = listener_socket, - .server = cqe_accept.res, - .client = client, - }; -} - -fn createListenerSocket(address: *linux.sockaddr.in) !posix.socket_t { - const kernel_backlog = 1; - const listener_socket = try posix.socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); - errdefer posix.close(listener_socket); - - try posix.setsockopt(listener_socket, posix.SOL.SOCKET, posix.SO.REUSEADDR, &mem.toBytes(@as(c_int, 1))); - try posix.bind(listener_socket, addrAny(address), @sizeOf(linux.sockaddr.in)); - try posix.listen(listener_socket, kernel_backlog); - - // set address to the OS-chosen IP/port. - var slen: posix.socklen_t = @sizeOf(linux.sockaddr.in); - try posix.getsockname(listener_socket, addrAny(address), &slen); - - return listener_socket; -} - -test "accept multishot" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(16, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - var address: linux.sockaddr.in = .{ - .port = 0, - .addr = @bitCast([4]u8{ 127, 0, 0, 1 }), - }; - const listener_socket = try createListenerSocket(&address); - defer posix.close(listener_socket); - - // submit multishot accept operation - var addr: posix.sockaddr = undefined; - var addr_len: posix.socklen_t = @sizeOf(@TypeOf(addr)); - const userdata: u64 = 0xaaaaaaaa; - _ = try ring.accept_multishot(userdata, listener_socket, &addr, &addr_len, 0); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - var nr: usize = 4; // number of clients to connect - while (nr > 0) : (nr -= 1) { - // connect client - const client = try posix.socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); - errdefer posix.close(client); - try posix.connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in)); - - // test accept completion - var cqe = try ring.copy_cqe(); - if (cqe.err() == .INVAL) return error.SkipZigTest; - try testing.expect(cqe.res > 0); - try testing.expect(cqe.user_data == userdata); - try testing.expect(cqe.flags & linux.IORING_CQE_F_MORE > 0); // more flag is set - - posix.close(client); - } -} - -test "accept/connect/send_zc/recv" { - try skipKernelLessThan(.{ .major = 6, .minor = 0, .patch = 0 }); - - var ring = IoUring.init(16, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - const socket_test_harness = try createSocketTestHarness(&ring); - defer socket_test_harness.close(); - - const buffer_send = [_]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe }; - var buffer_recv = [_]u8{0} ** 10; - - // zero-copy send - const sqe_send = try ring.send_zc(0xeeeeeeee, socket_test_harness.client, buffer_send[0..], 0, 0); - sqe_send.flags |= linux.IOSQE_IO_LINK; - _ = try ring.recv(0xffffffff, socket_test_harness.server, .{ .buffer = buffer_recv[0..] }, 0); - try testing.expectEqual(@as(u32, 2), try ring.submit()); - - var cqe_send = try ring.copy_cqe(); - // First completion of zero-copy send. - // IORING_CQE_F_MORE, means that there - // will be a second completion event / notification for the - // request, with the user_data field set to the same value. - // buffer_send must be keep alive until second cqe. - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0xeeeeeeee, - .res = buffer_send.len, - .flags = linux.IORING_CQE_F_MORE, - }, cqe_send); - - cqe_send, const cqe_recv = brk: { - const cqe1 = try ring.copy_cqe(); - const cqe2 = try ring.copy_cqe(); - break :brk if (cqe1.user_data == 0xeeeeeeee) .{ cqe1, cqe2 } else .{ cqe2, cqe1 }; - }; - - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0xffffffff, - .res = buffer_recv.len, - .flags = cqe_recv.flags & linux.IORING_CQE_F_SOCK_NONEMPTY, - }, cqe_recv); - try testing.expectEqualSlices(u8, buffer_send[0..buffer_recv.len], buffer_recv[0..]); - - // Second completion of zero-copy send. - // IORING_CQE_F_NOTIF in flags signals that kernel is done with send_buffer - try testing.expectEqual(linux.io_uring_cqe{ - .user_data = 0xeeeeeeee, - .res = 0, - .flags = linux.IORING_CQE_F_NOTIF, - }, cqe_send); -} - -test "accept_direct" { - try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 }); - - var ring = IoUring.init(1, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - var address: linux.sockaddr.in = .{ - .port = 0, - .addr = @bitCast([4]u8{ 127, 0, 0, 1 }), - }; - - // register direct file descriptors - var registered_fds = [_]linux.fd_t{-1} ** 2; - try ring.register_files(registered_fds[0..]); - - const listener_socket = try createListenerSocket(&address); - defer posix.close(listener_socket); - - const accept_userdata: u64 = 0xaaaaaaaa; - const read_userdata: u64 = 0xbbbbbbbb; - const data = [_]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe }; - - for (0..2) |_| { - for (registered_fds, 0..) |_, i| { - var buffer_recv = [_]u8{0} ** 16; - const buffer_send: []const u8 = data[0 .. data.len - i]; // make it different at each loop - - // submit accept, will chose registered fd and return index in cqe - _ = try ring.accept_direct(accept_userdata, listener_socket, null, null, 0); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - // connect - const client = try posix.socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); - try posix.connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in)); - defer posix.close(client); - - // accept completion - const cqe_accept = try ring.copy_cqe(); - try testing.expectEqual(posix.E.SUCCESS, cqe_accept.err()); - const fd_index = cqe_accept.res; - try testing.expect(fd_index < registered_fds.len); - try testing.expect(cqe_accept.user_data == accept_userdata); - - // send data - _ = try posix.send(client, buffer_send, 0); - - // Example of how to use registered fd: - // Submit receive to fixed file returned by accept (fd_index). - // Fd field is set to registered file index, returned by accept. - // Flag linux.IOSQE_FIXED_FILE must be set. - const recv_sqe = try ring.recv(read_userdata, fd_index, .{ .buffer = &buffer_recv }, 0); - recv_sqe.flags |= linux.IOSQE_FIXED_FILE; - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - // accept receive - const recv_cqe = try ring.copy_cqe(); - try testing.expect(recv_cqe.user_data == read_userdata); - try testing.expect(recv_cqe.res == buffer_send.len); - try testing.expectEqualSlices(u8, buffer_send, buffer_recv[0..buffer_send.len]); - } - // no more available fds, accept will get NFILE error - { - // submit accept - _ = try ring.accept_direct(accept_userdata, listener_socket, null, null, 0); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - // connect - const client = try posix.socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); - try posix.connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in)); - defer posix.close(client); - // completion with error - const cqe_accept = try ring.copy_cqe(); - try testing.expect(cqe_accept.user_data == accept_userdata); - try testing.expectEqual(posix.E.NFILE, cqe_accept.err()); - } - // return file descriptors to kernel - try ring.register_files_update(0, registered_fds[0..]); - } - try ring.unregister_files(); -} - -test "accept_multishot_direct" { - try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 }); - - if (builtin.cpu.arch == .riscv64) { - // https://github.com/ziglang/zig/issues/25734 - return error.SkipZigTest; - } - - var ring = IoUring.init(1, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - var address: linux.sockaddr.in = .{ - .port = 0, - .addr = @bitCast([4]u8{ 127, 0, 0, 1 }), - }; - - var registered_fds = [_]linux.fd_t{-1} ** 2; - try ring.register_files(registered_fds[0..]); - - const listener_socket = try createListenerSocket(&address); - defer posix.close(listener_socket); - - const accept_userdata: u64 = 0xaaaaaaaa; - - for (0..2) |_| { - // submit multishot accept - // Will chose registered fd and return index of the selected registered file in cqe. - _ = try ring.accept_multishot_direct(accept_userdata, listener_socket, null, null, 0); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - for (registered_fds) |_| { - // connect - const client = try posix.socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); - try posix.connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in)); - defer posix.close(client); - - // accept completion - const cqe_accept = try ring.copy_cqe(); - const fd_index = cqe_accept.res; - try testing.expect(fd_index < registered_fds.len); - try testing.expect(cqe_accept.user_data == accept_userdata); - try testing.expect(cqe_accept.flags & linux.IORING_CQE_F_MORE > 0); // has more is set - } - // No more available fds, accept will get NFILE error. - // Multishot is terminated (more flag is not set). - { - // connect - const client = try posix.socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); - try posix.connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in)); - defer posix.close(client); - // completion with error - const cqe_accept = try ring.copy_cqe(); - try testing.expect(cqe_accept.user_data == accept_userdata); - try testing.expectEqual(posix.E.NFILE, cqe_accept.err()); - try testing.expect(cqe_accept.flags & linux.IORING_CQE_F_MORE == 0); // has more is not set - } - // return file descriptors to kernel - try ring.register_files_update(0, registered_fds[0..]); - } - try ring.unregister_files(); -} - -test "socket" { - try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 }); - - var ring = IoUring.init(1, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - // prepare, submit socket operation - _ = try ring.socket(0, linux.AF.INET, posix.SOCK.STREAM, 0, 0); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - // test completion - var cqe = try ring.copy_cqe(); - try testing.expectEqual(posix.E.SUCCESS, cqe.err()); - const fd: linux.fd_t = @intCast(cqe.res); - try testing.expect(fd > 2); - - posix.close(fd); -} - -test "socket_direct/socket_direct_alloc/close_direct" { - try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 }); - - var ring = IoUring.init(2, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - var registered_fds = [_]linux.fd_t{-1} ** 3; - try ring.register_files(registered_fds[0..]); - - // create socket in registered file descriptor at index 0 (last param) - _ = try ring.socket_direct(0, linux.AF.INET, posix.SOCK.STREAM, 0, 0, 0); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - var cqe_socket = try ring.copy_cqe(); - try testing.expectEqual(posix.E.SUCCESS, cqe_socket.err()); - try testing.expect(cqe_socket.res == 0); - - // create socket in registered file descriptor at index 1 (last param) - _ = try ring.socket_direct(0, linux.AF.INET, posix.SOCK.STREAM, 0, 0, 1); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - cqe_socket = try ring.copy_cqe(); - try testing.expectEqual(posix.E.SUCCESS, cqe_socket.err()); - try testing.expect(cqe_socket.res == 0); // res is 0 when index is specified - - // create socket in kernel chosen file descriptor index (_alloc version) - // completion res has index from registered files - _ = try ring.socket_direct_alloc(0, linux.AF.INET, posix.SOCK.STREAM, 0, 0); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - cqe_socket = try ring.copy_cqe(); - try testing.expectEqual(posix.E.SUCCESS, cqe_socket.err()); - try testing.expect(cqe_socket.res == 2); // returns registered file index - - // use sockets from registered_fds in connect operation - var address: linux.sockaddr.in = .{ - .port = 0, - .addr = @bitCast([4]u8{ 127, 0, 0, 1 }), - }; - const listener_socket = try createListenerSocket(&address); - defer posix.close(listener_socket); - const accept_userdata: u64 = 0xaaaaaaaa; - const connect_userdata: u64 = 0xbbbbbbbb; - const close_userdata: u64 = 0xcccccccc; - for (registered_fds, 0..) |_, fd_index| { - // prepare accept - _ = try ring.accept(accept_userdata, listener_socket, null, null, 0); - // prepare connect with fixed socket - const connect_sqe = try ring.connect(connect_userdata, @intCast(fd_index), addrAny(&address), @sizeOf(linux.sockaddr.in)); - connect_sqe.flags |= linux.IOSQE_FIXED_FILE; // fd is fixed file index - // submit both - try testing.expectEqual(@as(u32, 2), try ring.submit()); - // get completions - var cqe_connect = try ring.copy_cqe(); - var cqe_accept = try ring.copy_cqe(); - // ignore order - if (cqe_connect.user_data == accept_userdata and cqe_accept.user_data == connect_userdata) { - const a = cqe_accept; - const b = cqe_connect; - cqe_accept = b; - cqe_connect = a; - } - // test connect completion - try testing.expect(cqe_connect.user_data == connect_userdata); - try testing.expectEqual(posix.E.SUCCESS, cqe_connect.err()); - // test accept completion - try testing.expect(cqe_accept.user_data == accept_userdata); - try testing.expectEqual(posix.E.SUCCESS, cqe_accept.err()); - - // submit and test close_direct - _ = try ring.close_direct(close_userdata, @intCast(fd_index)); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - var cqe_close = try ring.copy_cqe(); - try testing.expect(cqe_close.user_data == close_userdata); - try testing.expectEqual(posix.E.SUCCESS, cqe_close.err()); - } - - try ring.unregister_files(); -} - -test "openat_direct/close_direct" { - try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 }); - - var ring = IoUring.init(2, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - var registered_fds = [_]linux.fd_t{-1} ** 3; - try ring.register_files(registered_fds[0..]); - - var tmp = std.testing.tmpDir(.{}); - defer tmp.cleanup(); - const path = "test_io_uring_close_direct"; - const flags: linux.O = .{ .ACCMODE = .RDWR, .CREAT = true }; - const mode: posix.mode_t = 0o666; - const user_data: u64 = 0; - - // use registered file at index 0 (last param) - _ = try ring.openat_direct(user_data, tmp.dir.fd, path, flags, mode, 0); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - var cqe = try ring.copy_cqe(); - try testing.expectEqual(posix.E.SUCCESS, cqe.err()); - try testing.expect(cqe.res == 0); - - // use registered file at index 1 - _ = try ring.openat_direct(user_data, tmp.dir.fd, path, flags, mode, 1); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - cqe = try ring.copy_cqe(); - try testing.expectEqual(posix.E.SUCCESS, cqe.err()); - try testing.expect(cqe.res == 0); // res is 0 when we specify index - - // let kernel choose registered file index - _ = try ring.openat_direct(user_data, tmp.dir.fd, path, flags, mode, linux.IORING_FILE_INDEX_ALLOC); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - cqe = try ring.copy_cqe(); - try testing.expectEqual(posix.E.SUCCESS, cqe.err()); - try testing.expect(cqe.res == 2); // chosen index is in res - - // close all open file descriptors - for (registered_fds, 0..) |_, fd_index| { - _ = try ring.close_direct(user_data, @intCast(fd_index)); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - var cqe_close = try ring.copy_cqe(); - try testing.expectEqual(posix.E.SUCCESS, cqe_close.err()); - } - try ring.unregister_files(); -} - -test "waitid" { - try skipKernelLessThan(.{ .major = 6, .minor = 7, .patch = 0 }); - - var ring = IoUring.init(16, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - const pid = try posix.fork(); - if (pid == 0) { - posix.exit(7); - } - - var siginfo: posix.siginfo_t = undefined; - _ = try ring.waitid(0, .PID, pid, &siginfo, posix.W.EXITED, 0); - - try testing.expectEqual(1, try ring.submit()); - - const cqe_waitid = try ring.copy_cqe(); - try testing.expectEqual(0, cqe_waitid.res); - try testing.expectEqual(pid, siginfo.fields.common.first.piduid.pid); - try testing.expectEqual(7, siginfo.fields.common.second.sigchld.status); -} - -/// For use in tests. Returns SkipZigTest if kernel version is less than required. -inline fn skipKernelLessThan(required: std.SemanticVersion) !void { - if (!is_linux) return error.SkipZigTest; - - var uts: linux.utsname = undefined; - const res = linux.uname(&uts); - switch (linux.errno(res)) { - .SUCCESS => {}, - else => |errno| return posix.unexpectedErrno(errno), - } - - const release = mem.sliceTo(&uts.release, 0); - // Strips potential extra, as kernel version might not be semver compliant, example "6.8.9-300.fc40.x86_64" - const extra_index = std.mem.indexOfAny(u8, release, "-+"); - const stripped = release[0..(extra_index orelse release.len)]; - // Make sure the input don't rely on the extra we just stripped - try testing.expect(required.pre == null and required.build == null); - - var current = try std.SemanticVersion.parse(stripped); - current.pre = null; // don't check pre field - if (required.order(current) == .gt) return error.SkipZigTest; -} - -test BufferGroup { - if (!is_linux) return error.SkipZigTest; - - // Init IoUring - var ring = IoUring.init(16, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - // Init buffer group for ring - const group_id: u16 = 1; // buffers group id - const buffers_count: u16 = 1; // number of buffers in buffer group - const buffer_size: usize = 128; // size of each buffer in group - var buf_grp = BufferGroup.init( - &ring, - testing.allocator, - group_id, - buffer_size, - buffers_count, - ) catch |err| switch (err) { - // kernel older than 5.19 - error.ArgumentsInvalid => return error.SkipZigTest, - else => return err, - }; - defer buf_grp.deinit(testing.allocator); - - // Create client/server fds - const fds = try createSocketTestHarness(&ring); - defer fds.close(); - const data = [_]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe }; - - // Client sends data - { - _ = try ring.send(1, fds.client, data[0..], 0); - const submitted = try ring.submit(); - try testing.expectEqual(1, submitted); - const cqe_send = try ring.copy_cqe(); - if (cqe_send.err() == .INVAL) return error.SkipZigTest; - try testing.expectEqual(linux.io_uring_cqe{ .user_data = 1, .res = data.len, .flags = 0 }, cqe_send); - } - - // Server uses buffer group receive - { - // Submit recv operation, buffer will be chosen from buffer group - _ = try buf_grp.recv(2, fds.server, 0); - const submitted = try ring.submit(); - try testing.expectEqual(1, submitted); - - // ... when we have completion for recv operation - const cqe = try ring.copy_cqe(); - try testing.expectEqual(2, cqe.user_data); // matches submitted user_data - try testing.expect(cqe.res >= 0); // success - try testing.expectEqual(posix.E.SUCCESS, cqe.err()); - try testing.expectEqual(data.len, @as(usize, @intCast(cqe.res))); // cqe.res holds received data len - - // Get buffer from pool - const buf = try buf_grp.get(cqe); - try testing.expectEqualSlices(u8, &data, buf); - // Release buffer to the kernel when application is done with it - try buf_grp.put(cqe); - } -} - -test "ring mapped buffers recv" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(16, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - // init buffer group - const group_id: u16 = 1; // buffers group id - const buffers_count: u16 = 2; // number of buffers in buffer group - const buffer_size: usize = 4; // size of each buffer in group - var buf_grp = BufferGroup.init( - &ring, - testing.allocator, - group_id, - buffer_size, - buffers_count, - ) catch |err| switch (err) { - // kernel older than 5.19 - error.ArgumentsInvalid => return error.SkipZigTest, - else => return err, - }; - defer buf_grp.deinit(testing.allocator); - - // create client/server fds - const fds = try createSocketTestHarness(&ring); - defer fds.close(); - - // for random user_data in sqe/cqe - var Rnd = std.Random.DefaultPrng.init(std.testing.random_seed); - var rnd = Rnd.random(); - - var round: usize = 4; // repeat send/recv cycle round times - while (round > 0) : (round -= 1) { - // client sends data - const data = [_]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe }; - { - const user_data = rnd.int(u64); - _ = try ring.send(user_data, fds.client, data[0..], 0); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - const cqe_send = try ring.copy_cqe(); - if (cqe_send.err() == .INVAL) return error.SkipZigTest; - try testing.expectEqual(linux.io_uring_cqe{ .user_data = user_data, .res = data.len, .flags = 0 }, cqe_send); - } - var pos: usize = 0; - - // read first chunk - const cqe1 = try buf_grp_recv_submit_get_cqe(&ring, &buf_grp, fds.server, rnd.int(u64)); - var buf = try buf_grp.get(cqe1); - try testing.expectEqualSlices(u8, data[pos..][0..buf.len], buf); - pos += buf.len; - // second chunk - const cqe2 = try buf_grp_recv_submit_get_cqe(&ring, &buf_grp, fds.server, rnd.int(u64)); - buf = try buf_grp.get(cqe2); - try testing.expectEqualSlices(u8, data[pos..][0..buf.len], buf); - pos += buf.len; - - // both buffers provided to the kernel are used so we get error - // 'no more buffers', until we put buffers to the kernel - { - const user_data = rnd.int(u64); - _ = try buf_grp.recv(user_data, fds.server, 0); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - const cqe = try ring.copy_cqe(); - try testing.expectEqual(user_data, cqe.user_data); - try testing.expect(cqe.res < 0); // fail - try testing.expectEqual(posix.E.NOBUFS, cqe.err()); - try testing.expect(cqe.flags & linux.IORING_CQE_F_BUFFER == 0); // IORING_CQE_F_BUFFER flags is set on success only - try testing.expectError(error.NoBufferSelected, cqe.buffer_id()); - } - - // put buffers back to the kernel - try buf_grp.put(cqe1); - try buf_grp.put(cqe2); - - // read remaining data - while (pos < data.len) { - const cqe = try buf_grp_recv_submit_get_cqe(&ring, &buf_grp, fds.server, rnd.int(u64)); - buf = try buf_grp.get(cqe); - try testing.expectEqualSlices(u8, data[pos..][0..buf.len], buf); - pos += buf.len; - try buf_grp.put(cqe); - } - } -} - -test "ring mapped buffers multishot recv" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(16, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - // init buffer group - const group_id: u16 = 1; // buffers group id - const buffers_count: u16 = 2; // number of buffers in buffer group - const buffer_size: usize = 4; // size of each buffer in group - var buf_grp = BufferGroup.init( - &ring, - testing.allocator, - group_id, - buffer_size, - buffers_count, - ) catch |err| switch (err) { - // kernel older than 5.19 - error.ArgumentsInvalid => return error.SkipZigTest, - else => return err, - }; - defer buf_grp.deinit(testing.allocator); - - // create client/server fds - const fds = try createSocketTestHarness(&ring); - defer fds.close(); - - // for random user_data in sqe/cqe - var Rnd = std.Random.DefaultPrng.init(std.testing.random_seed); - var rnd = Rnd.random(); - - var round: usize = 4; // repeat send/recv cycle round times - while (round > 0) : (round -= 1) { - // client sends data - const data = [_]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf }; - { - const user_data = rnd.int(u64); - _ = try ring.send(user_data, fds.client, data[0..], 0); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - const cqe_send = try ring.copy_cqe(); - if (cqe_send.err() == .INVAL) return error.SkipZigTest; - try testing.expectEqual(linux.io_uring_cqe{ .user_data = user_data, .res = data.len, .flags = 0 }, cqe_send); - } - - // start multishot recv - var recv_user_data = rnd.int(u64); - _ = try buf_grp.recv_multishot(recv_user_data, fds.server, 0); - try testing.expectEqual(@as(u32, 1), try ring.submit()); // submit - - // server reads data into provided buffers - // there are 2 buffers of size 4, so each read gets only chunk of data - // we read four chunks of 4, 4, 4, 4 bytes each - var chunk: []const u8 = data[0..buffer_size]; // first chunk - const cqe1 = try expect_buf_grp_cqe(&ring, &buf_grp, recv_user_data, chunk); - try testing.expect(cqe1.flags & linux.IORING_CQE_F_MORE > 0); - - chunk = data[buffer_size .. buffer_size * 2]; // second chunk - const cqe2 = try expect_buf_grp_cqe(&ring, &buf_grp, recv_user_data, chunk); - try testing.expect(cqe2.flags & linux.IORING_CQE_F_MORE > 0); - - // both buffers provided to the kernel are used so we get error - // 'no more buffers', until we put buffers to the kernel - { - const cqe = try ring.copy_cqe(); - try testing.expectEqual(recv_user_data, cqe.user_data); - try testing.expect(cqe.res < 0); // fail - try testing.expectEqual(posix.E.NOBUFS, cqe.err()); - try testing.expect(cqe.flags & linux.IORING_CQE_F_BUFFER == 0); // IORING_CQE_F_BUFFER flags is set on success only - // has more is not set - // indicates that multishot is finished - try testing.expect(cqe.flags & linux.IORING_CQE_F_MORE == 0); - try testing.expectError(error.NoBufferSelected, cqe.buffer_id()); - } - - // put buffers back to the kernel - try buf_grp.put(cqe1); - try buf_grp.put(cqe2); - - // restart multishot - recv_user_data = rnd.int(u64); - _ = try buf_grp.recv_multishot(recv_user_data, fds.server, 0); - try testing.expectEqual(@as(u32, 1), try ring.submit()); // submit - - chunk = data[buffer_size * 2 .. buffer_size * 3]; // third chunk - const cqe3 = try expect_buf_grp_cqe(&ring, &buf_grp, recv_user_data, chunk); - try testing.expect(cqe3.flags & linux.IORING_CQE_F_MORE > 0); - try buf_grp.put(cqe3); - - chunk = data[buffer_size * 3 ..]; // last chunk - const cqe4 = try expect_buf_grp_cqe(&ring, &buf_grp, recv_user_data, chunk); - try testing.expect(cqe4.flags & linux.IORING_CQE_F_MORE > 0); - try buf_grp.put(cqe4); - - // cancel pending multishot recv operation - { - const cancel_user_data = rnd.int(u64); - _ = try ring.cancel(cancel_user_data, recv_user_data, 0); - try testing.expectEqual(@as(u32, 1), try ring.submit()); - - // expect completion of cancel operation and completion of recv operation - var cqe_cancel = try ring.copy_cqe(); - if (cqe_cancel.err() == .INVAL) return error.SkipZigTest; - var cqe_recv = try ring.copy_cqe(); - if (cqe_recv.err() == .INVAL) return error.SkipZigTest; - - // don't depend on order of completions - if (cqe_cancel.user_data == recv_user_data and cqe_recv.user_data == cancel_user_data) { - const a = cqe_cancel; - const b = cqe_recv; - cqe_cancel = b; - cqe_recv = a; - } - - // Note on different kernel results: - // on older kernel (tested with v6.0.16, v6.1.57, v6.2.12, v6.4.16) - // cqe_cancel.err() == .NOENT - // cqe_recv.err() == .NOBUFS - // on kernel (tested with v6.5.0, v6.5.7) - // cqe_cancel.err() == .SUCCESS - // cqe_recv.err() == .CANCELED - // Upstream reference: https://github.com/axboe/liburing/issues/984 - - // cancel operation is success (or NOENT on older kernels) - try testing.expectEqual(cancel_user_data, cqe_cancel.user_data); - try testing.expect(cqe_cancel.err() == .NOENT or cqe_cancel.err() == .SUCCESS); - - // recv operation is failed with err CANCELED (or NOBUFS on older kernels) - try testing.expectEqual(recv_user_data, cqe_recv.user_data); - try testing.expect(cqe_recv.res < 0); - try testing.expect(cqe_recv.err() == .NOBUFS or cqe_recv.err() == .CANCELED); - try testing.expect(cqe_recv.flags & linux.IORING_CQE_F_MORE == 0); - } - } -} - -// Prepare, submit recv and get cqe using buffer group. -fn buf_grp_recv_submit_get_cqe( - ring: *IoUring, - buf_grp: *BufferGroup, - fd: linux.fd_t, - user_data: u64, -) !linux.io_uring_cqe { - // prepare and submit recv - const sqe = try buf_grp.recv(user_data, fd, 0); - try testing.expect(sqe.flags & linux.IOSQE_BUFFER_SELECT == linux.IOSQE_BUFFER_SELECT); - try testing.expect(sqe.buf_index == buf_grp.group_id); - try testing.expectEqual(@as(u32, 1), try ring.submit()); // submit - // get cqe, expect success - const cqe = try ring.copy_cqe(); - try testing.expectEqual(user_data, cqe.user_data); - try testing.expect(cqe.res >= 0); // success - try testing.expectEqual(posix.E.SUCCESS, cqe.err()); - try testing.expect(cqe.flags & linux.IORING_CQE_F_BUFFER == linux.IORING_CQE_F_BUFFER); // IORING_CQE_F_BUFFER flag is set - - return cqe; -} - -fn expect_buf_grp_cqe( - ring: *IoUring, - buf_grp: *BufferGroup, - user_data: u64, - expected: []const u8, -) !linux.io_uring_cqe { - // get cqe - const cqe = try ring.copy_cqe(); - try testing.expectEqual(user_data, cqe.user_data); - try testing.expect(cqe.res >= 0); // success - try testing.expect(cqe.flags & linux.IORING_CQE_F_BUFFER == linux.IORING_CQE_F_BUFFER); // IORING_CQE_F_BUFFER flag is set - try testing.expectEqual(expected.len, @as(usize, @intCast(cqe.res))); - try testing.expectEqual(posix.E.SUCCESS, cqe.err()); - - // get buffer from pool - const buffer_id = try cqe.buffer_id(); - const len = @as(usize, @intCast(cqe.res)); - const buf = buf_grp.get_by_id(buffer_id)[0..len]; - try testing.expectEqualSlices(u8, expected, buf); - - return cqe; -} - -test "copy_cqes with wrapping sq.cqes buffer" { - if (!is_linux) return error.SkipZigTest; - - var ring = IoUring.init(2, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - try testing.expectEqual(2, ring.sq.sqes.len); - try testing.expectEqual(4, ring.cq.cqes.len); - - // submit 2 entries, receive 2 completions - var cqes: [8]linux.io_uring_cqe = undefined; - { - for (0..2) |_| { - const sqe = try ring.get_sqe(); - sqe.prep_timeout(&.{ .sec = 0, .nsec = 10000 }, 0, 0); - try testing.expect(try ring.submit() == 1); - } - var cqe_count: u32 = 0; - while (cqe_count < 2) { - cqe_count += try ring.copy_cqes(&cqes, 2 - cqe_count); - } - } - - try testing.expectEqual(2, ring.cq.head.*); - - // sq.sqes len is 4, starting at position 2 - // every 4 entries submit wraps completion buffer - // we are reading ring.cq.cqes at indexes 2,3,0,1 - for (1..1024) |i| { - for (0..4) |_| { - const sqe = try ring.get_sqe(); - sqe.prep_timeout(&.{ .sec = 0, .nsec = 10000 }, 0, 0); - try testing.expect(try ring.submit() == 1); - } - var cqe_count: u32 = 0; - while (cqe_count < 4) { - cqe_count += try ring.copy_cqes(&cqes, 4 - cqe_count); - } - try testing.expectEqual(4, cqe_count); - try testing.expectEqual(2 + 4 * i, ring.cq.head.*); - } -} - -test "bind/listen/connect" { - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/25956 - - var ring = IoUring.init(4, 0) catch |err| switch (err) { - error.SystemOutdated => return error.SkipZigTest, - error.PermissionDenied => return error.SkipZigTest, - else => return err, - }; - defer ring.deinit(); - - const probe = ring.get_probe() catch return error.SkipZigTest; - // LISTEN is higher required operation - if (!probe.is_supported(.LISTEN)) return error.SkipZigTest; - - var addr: linux.sockaddr.in = .{ - .port = 0, - .addr = @bitCast([4]u8{ 127, 0, 0, 1 }), - }; - const proto: u32 = if (addr.family == linux.AF.UNIX) 0 else linux.IPPROTO.TCP; - - const listen_fd = brk: { - // Create socket - _ = try ring.socket(1, addr.family, linux.SOCK.STREAM | linux.SOCK.CLOEXEC, proto, 0); - try testing.expectEqual(1, try ring.submit()); - var cqe = try ring.copy_cqe(); - try testing.expectEqual(1, cqe.user_data); - try testing.expectEqual(posix.E.SUCCESS, cqe.err()); - const listen_fd: linux.fd_t = @intCast(cqe.res); - try testing.expect(listen_fd > 2); - - // Prepare: set socket option * 2, bind, listen - var optval: u32 = 1; - (try ring.setsockopt(2, listen_fd, linux.SOL.SOCKET, linux.SO.REUSEADDR, mem.asBytes(&optval))).link_next(); - (try ring.setsockopt(3, listen_fd, linux.SOL.SOCKET, linux.SO.REUSEPORT, mem.asBytes(&optval))).link_next(); - (try ring.bind(4, listen_fd, addrAny(&addr), @sizeOf(linux.sockaddr.in), 0)).link_next(); - _ = try ring.listen(5, listen_fd, 1, 0); - // Submit 4 operations - try testing.expectEqual(4, try ring.submit()); - // Expect all to succeed - for (2..6) |user_data| { - cqe = try ring.copy_cqe(); - try testing.expectEqual(user_data, cqe.user_data); - try testing.expectEqual(posix.E.SUCCESS, cqe.err()); - } - - // Check that socket option is set - optval = 0; - _ = try ring.getsockopt(5, listen_fd, linux.SOL.SOCKET, linux.SO.REUSEADDR, mem.asBytes(&optval)); - try testing.expectEqual(1, try ring.submit()); - cqe = try ring.copy_cqe(); - try testing.expectEqual(5, cqe.user_data); - try testing.expectEqual(posix.E.SUCCESS, cqe.err()); - try testing.expectEqual(1, optval); - - // Read system assigned port into addr - var addr_len: posix.socklen_t = @sizeOf(linux.sockaddr.in); - try posix.getsockname(listen_fd, addrAny(&addr), &addr_len); - - break :brk listen_fd; - }; - - const connect_fd = brk: { - // Create connect socket - _ = try ring.socket(6, addr.family, linux.SOCK.STREAM | linux.SOCK.CLOEXEC, proto, 0); - try testing.expectEqual(1, try ring.submit()); - const cqe = try ring.copy_cqe(); - try testing.expectEqual(6, cqe.user_data); - try testing.expectEqual(posix.E.SUCCESS, cqe.err()); - // Get connect socket fd - const connect_fd: linux.fd_t = @intCast(cqe.res); - try testing.expect(connect_fd > 2 and connect_fd != listen_fd); - break :brk connect_fd; - }; - - // Prepare accept/connect operations - _ = try ring.accept(7, listen_fd, null, null, 0); - _ = try ring.connect(8, connect_fd, addrAny(&addr), @sizeOf(linux.sockaddr.in)); - try testing.expectEqual(2, try ring.submit()); - // Get listener accepted socket - var accept_fd: posix.socket_t = 0; - for (0..2) |_| { - const cqe = try ring.copy_cqe(); - try testing.expectEqual(posix.E.SUCCESS, cqe.err()); - if (cqe.user_data == 7) { - accept_fd = @intCast(cqe.res); - } else { - try testing.expectEqual(8, cqe.user_data); - } - } - try testing.expect(accept_fd > 2 and accept_fd != listen_fd and accept_fd != connect_fd); - - // Communicate - try testSendRecv(&ring, connect_fd, accept_fd); - try testSendRecv(&ring, accept_fd, connect_fd); - - // Shutdown and close all sockets - for ([_]posix.socket_t{ connect_fd, accept_fd, listen_fd }) |fd| { - (try ring.shutdown(9, fd, posix.SHUT.RDWR)).link_next(); - _ = try ring.close(10, fd); - try testing.expectEqual(2, try ring.submit()); - for (0..2) |i| { - const cqe = try ring.copy_cqe(); - try testing.expectEqual(posix.E.SUCCESS, cqe.err()); - try testing.expectEqual(9 + i, cqe.user_data); - } - } -} - -fn testSendRecv(ring: *IoUring, send_fd: posix.socket_t, recv_fd: posix.socket_t) !void { - const buffer_send = "0123456789abcdf" ** 10; - var buffer_recv: [buffer_send.len * 2]u8 = undefined; - - // 2 sends - _ = try ring.send(1, send_fd, buffer_send, linux.MSG.WAITALL); - _ = try ring.send(2, send_fd, buffer_send, linux.MSG.WAITALL); - try testing.expectEqual(2, try ring.submit()); - for (0..2) |i| { - const cqe = try ring.copy_cqe(); - try testing.expectEqual(1 + i, cqe.user_data); - try testing.expectEqual(posix.E.SUCCESS, cqe.err()); - try testing.expectEqual(buffer_send.len, @as(usize, @intCast(cqe.res))); - } - - // receive - var recv_len: usize = 0; - while (recv_len < buffer_send.len * 2) { - _ = try ring.recv(3, recv_fd, .{ .buffer = buffer_recv[recv_len..] }, 0); - try testing.expectEqual(1, try ring.submit()); - const cqe = try ring.copy_cqe(); - try testing.expectEqual(3, cqe.user_data); - try testing.expectEqual(posix.E.SUCCESS, cqe.err()); - recv_len += @intCast(cqe.res); - } - - // inspect recv buffer - try testing.expectEqualSlices(u8, buffer_send, buffer_recv[0..buffer_send.len]); - try testing.expectEqualSlices(u8, buffer_send, buffer_recv[buffer_send.len..]); } -fn addrAny(addr: *linux.sockaddr.in) *linux.sockaddr { - return @ptrCast(addr); +test { + if (is_linux) _ = @import("IoUring/test.zig"); } diff --git a/lib/std/os/linux/IoUring/test.zig b/lib/std/os/linux/IoUring/test.zig new file mode 100644 index 000000000000..c924fb3d2a5f --- /dev/null +++ b/lib/std/os/linux/IoUring/test.zig @@ -0,0 +1,2734 @@ +const builtin = @import("builtin"); + +const std = @import("../../../std.zig"); +const Io = std.Io; +const mem = std.mem; +const assert = std.debug.assert; +const testing = std.testing; +const linux = std.os.linux; + +const IoUring = std.os.linux.IoUring; +const BufferGroup = IoUring.BufferGroup; + +const posix = std.posix; +const iovec = posix.iovec; +const iovec_const = posix.iovec_const; + +comptime { + assert(builtin.os.tag == .linux); +} + +test "structs/offsets/entries" { + try testing.expectEqual(@as(usize, 120), @sizeOf(linux.io_uring_params)); + try testing.expectEqual(@as(usize, 64), @sizeOf(linux.io_uring_sqe)); + try testing.expectEqual(@as(usize, 16), @sizeOf(linux.io_uring_cqe)); + + try testing.expectEqual(0, linux.IORING_OFF_SQ_RING); + try testing.expectEqual(0x8000000, linux.IORING_OFF_CQ_RING); + try testing.expectEqual(0x10000000, linux.IORING_OFF_SQES); + + try testing.expectError(error.EntriesZero, IoUring.init(0, 0)); + try testing.expectError(error.EntriesNotPowerOfTwo, IoUring.init(3, 0)); +} + +test "nop" { + var ring = IoUring.init(1, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer { + ring.deinit(); + testing.expectEqual(@as(linux.fd_t, -1), ring.fd) catch @panic("test failed"); + } + + const sqe = try ring.nop(0xaaaaaaaa); + try testing.expectEqual(linux.io_uring_sqe{ + .opcode = .NOP, + .flags = 0, + .ioprio = 0, + .fd = 0, + .off = 0, + .addr = 0, + .len = 0, + .rw_flags = 0, + .user_data = 0xaaaaaaaa, + .buf_index = 0, + .personality = 0, + .splice_fd_in = 0, + .addr3 = 0, + .resv = 0, + }, sqe.*); + + try testing.expectEqual(@as(u32, 0), ring.sq.sqe_head); + try testing.expectEqual(@as(u32, 1), ring.sq.sqe_tail); + try testing.expectEqual(@as(u32, 0), ring.sq.tail.*); + try testing.expectEqual(@as(u32, 0), ring.cq.head.*); + try testing.expectEqual(@as(u32, 1), ring.sq_ready()); + try testing.expectEqual(@as(u32, 0), ring.cq_ready()); + + try testing.expectEqual(@as(u32, 1), try ring.submit()); + try testing.expectEqual(@as(u32, 1), ring.sq.sqe_head); + try testing.expectEqual(@as(u32, 1), ring.sq.sqe_tail); + try testing.expectEqual(@as(u32, 1), ring.sq.tail.*); + try testing.expectEqual(@as(u32, 0), ring.cq.head.*); + try testing.expectEqual(@as(u32, 0), ring.sq_ready()); + + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0xaaaaaaaa, + .res = 0, + .flags = 0, + }, try ring.copy_cqe()); + try testing.expectEqual(@as(u32, 1), ring.cq.head.*); + try testing.expectEqual(@as(u32, 0), ring.cq_ready()); + + const sqe_barrier = try ring.nop(0xbbbbbbbb); + sqe_barrier.flags |= linux.IOSQE_IO_DRAIN; + try testing.expectEqual(@as(u32, 1), try ring.submit()); + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0xbbbbbbbb, + .res = 0, + .flags = 0, + }, try ring.copy_cqe()); + try testing.expectEqual(@as(u32, 2), ring.sq.sqe_head); + try testing.expectEqual(@as(u32, 2), ring.sq.sqe_tail); + try testing.expectEqual(@as(u32, 2), ring.sq.tail.*); + try testing.expectEqual(@as(u32, 2), ring.cq.head.*); +} + +test "readv" { + const io = testing.io; + + var ring = IoUring.init(1, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + const file = try Io.Dir.openFileAbsolute(io, "/dev/zero", .{}); + defer file.close(io); + + // Linux Kernel 5.4 supports IORING_REGISTER_FILES but not sparse fd sets (i.e. an fd of -1). + // Linux Kernel 5.5 adds support for sparse fd sets. + // Compare: + // https://github.com/torvalds/linux/blob/v5.4/fs/io_uring.c#L3119-L3124 vs + // https://github.com/torvalds/linux/blob/v5.8/fs/io_uring.c#L6687-L6691 + // We therefore avoid stressing sparse fd sets here: + var registered_fds = [_]linux.fd_t{0} ** 1; + const fd_index = 0; + registered_fds[fd_index] = file.handle; + try ring.register_files(registered_fds[0..]); + + var buffer = [_]u8{42} ** 128; + var iovecs = [_]iovec{iovec{ .base = &buffer, .len = buffer.len }}; + const sqe = try ring.read(0xcccccccc, fd_index, .{ .iovecs = iovecs[0..] }, 0); + try testing.expectEqual(linux.IORING_OP.READV, sqe.opcode); + sqe.flags |= linux.IOSQE_FIXED_FILE; + + try testing.expectError(error.SubmissionQueueFull, ring.nop(0)); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0xcccccccc, + .res = buffer.len, + .flags = 0, + }, try ring.copy_cqe()); + try testing.expectEqualSlices(u8, &([_]u8{0} ** buffer.len), buffer[0..]); + + try ring.unregister_files(); +} + +test "writev/fsync/readv" { + const io = testing.io; + + var ring = IoUring.init(4, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + var tmp = std.testing.tmpDir(.{}); + defer tmp.cleanup(); + + const path = "test_io_uring_writev_fsync_readv"; + const file = try tmp.dir.createFile(io, path, .{ .read = true }); + defer file.close(io); + const fd = file.handle; + + const buffer_write = [_]u8{42} ** 128; + const iovecs_write = [_]iovec_const{ + iovec_const{ .base = &buffer_write, .len = buffer_write.len }, + }; + var buffer_read = [_]u8{0} ** 128; + var iovecs_read = [_]iovec{ + iovec{ .base = &buffer_read, .len = buffer_read.len }, + }; + + const sqe_writev = try ring.writev(0xdddddddd, fd, iovecs_write[0..], 17); + try testing.expectEqual(linux.IORING_OP.WRITEV, sqe_writev.opcode); + try testing.expectEqual(@as(u64, 17), sqe_writev.off); + sqe_writev.flags |= linux.IOSQE_IO_LINK; + + const sqe_fsync = try ring.fsync(0xeeeeeeee, fd, 0); + try testing.expectEqual(linux.IORING_OP.FSYNC, sqe_fsync.opcode); + try testing.expectEqual(fd, sqe_fsync.fd); + sqe_fsync.flags |= linux.IOSQE_IO_LINK; + + const sqe_readv = try ring.read(0xffffffff, fd, .{ .iovecs = iovecs_read[0..] }, 17); + try testing.expectEqual(linux.IORING_OP.READV, sqe_readv.opcode); + try testing.expectEqual(@as(u64, 17), sqe_readv.off); + + try testing.expectEqual(@as(u32, 3), ring.sq_ready()); + try testing.expectEqual(@as(u32, 3), try ring.submit_and_wait(3)); + try testing.expectEqual(@as(u32, 0), ring.sq_ready()); + try testing.expectEqual(@as(u32, 3), ring.cq_ready()); + + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0xdddddddd, + .res = buffer_write.len, + .flags = 0, + }, try ring.copy_cqe()); + try testing.expectEqual(@as(u32, 2), ring.cq_ready()); + + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0xeeeeeeee, + .res = 0, + .flags = 0, + }, try ring.copy_cqe()); + try testing.expectEqual(@as(u32, 1), ring.cq_ready()); + + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0xffffffff, + .res = buffer_read.len, + .flags = 0, + }, try ring.copy_cqe()); + try testing.expectEqual(@as(u32, 0), ring.cq_ready()); + + try testing.expectEqualSlices(u8, buffer_write[0..], buffer_read[0..]); +} + +test "write/read" { + const io = testing.io; + + var ring = IoUring.init(2, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + var tmp = std.testing.tmpDir(.{}); + defer tmp.cleanup(); + const path = "test_io_uring_write_read"; + const file = try tmp.dir.createFile(io, path, .{ .read = true }); + defer file.close(io); + const fd = file.handle; + + const buffer_write = [_]u8{97} ** 20; + var buffer_read = [_]u8{98} ** 20; + const sqe_write = try ring.write(0x11111111, fd, buffer_write[0..], 10); + try testing.expectEqual(linux.IORING_OP.WRITE, sqe_write.opcode); + try testing.expectEqual(@as(u64, 10), sqe_write.off); + sqe_write.flags |= linux.IOSQE_IO_LINK; + const sqe_read = try ring.read(0x22222222, fd, .{ .buffer = buffer_read[0..] }, 10); + try testing.expectEqual(linux.IORING_OP.READ, sqe_read.opcode); + try testing.expectEqual(@as(u64, 10), sqe_read.off); + try testing.expectEqual(@as(u32, 2), try ring.submit()); + + const cqe_write = try ring.copy_cqe(); + const cqe_read = try ring.copy_cqe(); + // Prior to Linux Kernel 5.6 this is the only way to test for read/write support: + // https://lwn.net/Articles/809820/ + if (cqe_write.err() == .INVAL) return error.SkipZigTest; + if (cqe_read.err() == .INVAL) return error.SkipZigTest; + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x11111111, + .res = buffer_write.len, + .flags = 0, + }, cqe_write); + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x22222222, + .res = buffer_read.len, + .flags = 0, + }, cqe_read); + try testing.expectEqualSlices(u8, buffer_write[0..], buffer_read[0..]); +} + +test "splice/read" { + const io = testing.io; + + var ring = IoUring.init(4, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + var tmp = std.testing.tmpDir(.{}); + const path_src = "test_io_uring_splice_src"; + const file_src = try tmp.dir.createFile(io, path_src, .{ .read = true }); + defer file_src.close(io); + const fd_src = file_src.handle; + + const path_dst = "test_io_uring_splice_dst"; + const file_dst = try tmp.dir.createFile(io, path_dst, .{ .read = true }); + defer file_dst.close(io); + const fd_dst = file_dst.handle; + + const buffer_write = [_]u8{97} ** 20; + var buffer_read = [_]u8{98} ** 20; + try file_src.writeStreamingAll(io, &buffer_write); + + const fds = try std.Io.Threaded.pipe2(.{}); + const pipe_offset: u64 = std.math.maxInt(u64); + + const sqe_splice_to_pipe = try ring.splice(0x11111111, fd_src, 0, fds[1], pipe_offset, buffer_write.len); + try testing.expectEqual(linux.IORING_OP.SPLICE, sqe_splice_to_pipe.opcode); + try testing.expectEqual(@as(u64, 0), sqe_splice_to_pipe.addr); + try testing.expectEqual(pipe_offset, sqe_splice_to_pipe.off); + sqe_splice_to_pipe.flags |= linux.IOSQE_IO_LINK; + + const sqe_splice_from_pipe = try ring.splice(0x22222222, fds[0], pipe_offset, fd_dst, 10, buffer_write.len); + try testing.expectEqual(linux.IORING_OP.SPLICE, sqe_splice_from_pipe.opcode); + try testing.expectEqual(pipe_offset, sqe_splice_from_pipe.addr); + try testing.expectEqual(@as(u64, 10), sqe_splice_from_pipe.off); + sqe_splice_from_pipe.flags |= linux.IOSQE_IO_LINK; + + const sqe_read = try ring.read(0x33333333, fd_dst, .{ .buffer = buffer_read[0..] }, 10); + try testing.expectEqual(linux.IORING_OP.READ, sqe_read.opcode); + try testing.expectEqual(@as(u64, 10), sqe_read.off); + try testing.expectEqual(@as(u32, 3), try ring.submit()); + + const cqe_splice_to_pipe = try ring.copy_cqe(); + const cqe_splice_from_pipe = try ring.copy_cqe(); + const cqe_read = try ring.copy_cqe(); + // Prior to Linux Kernel 5.6 this is the only way to test for splice/read support: + // https://lwn.net/Articles/809820/ + if (cqe_splice_to_pipe.err() == .INVAL) return error.SkipZigTest; + if (cqe_splice_from_pipe.err() == .INVAL) return error.SkipZigTest; + if (cqe_read.err() == .INVAL) return error.SkipZigTest; + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x11111111, + .res = buffer_write.len, + .flags = 0, + }, cqe_splice_to_pipe); + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x22222222, + .res = buffer_write.len, + .flags = 0, + }, cqe_splice_from_pipe); + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x33333333, + .res = buffer_read.len, + .flags = 0, + }, cqe_read); + try testing.expectEqualSlices(u8, buffer_write[0..], buffer_read[0..]); +} + +test "write_fixed/read_fixed" { + const io = testing.io; + + var ring = IoUring.init(2, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + var tmp = std.testing.tmpDir(.{}); + defer tmp.cleanup(); + + const path = "test_io_uring_write_read_fixed"; + const file = try tmp.dir.createFile(io, path, .{ .read = true }); + defer file.close(io); + const fd = file.handle; + + var raw_buffers: [2][11]u8 = undefined; + // First buffer will be written to the file. + @memset(&raw_buffers[0], 'z'); + raw_buffers[0][0.."foobar".len].* = "foobar".*; + + var buffers = [2]iovec{ + .{ .base = &raw_buffers[0], .len = raw_buffers[0].len }, + .{ .base = &raw_buffers[1], .len = raw_buffers[1].len }, + }; + ring.register_buffers(&buffers) catch |err| switch (err) { + error.SystemResources => { + // See https://github.com/ziglang/zig/issues/15362 + return error.SkipZigTest; + }, + else => |e| return e, + }; + + const sqe_write = try ring.write_fixed(0x45454545, fd, &buffers[0], 3, 0); + try testing.expectEqual(linux.IORING_OP.WRITE_FIXED, sqe_write.opcode); + try testing.expectEqual(@as(u64, 3), sqe_write.off); + sqe_write.flags |= linux.IOSQE_IO_LINK; + + const sqe_read = try ring.read_fixed(0x12121212, fd, &buffers[1], 0, 1); + try testing.expectEqual(linux.IORING_OP.READ_FIXED, sqe_read.opcode); + try testing.expectEqual(@as(u64, 0), sqe_read.off); + + try testing.expectEqual(@as(u32, 2), try ring.submit()); + + const cqe_write = try ring.copy_cqe(); + const cqe_read = try ring.copy_cqe(); + + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x45454545, + .res = @as(i32, @intCast(buffers[0].len)), + .flags = 0, + }, cqe_write); + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x12121212, + .res = @as(i32, @intCast(buffers[1].len)), + .flags = 0, + }, cqe_read); + + try testing.expectEqualSlices(u8, "\x00\x00\x00", buffers[1].base[0..3]); + try testing.expectEqualSlices(u8, "foobar", buffers[1].base[3..9]); + try testing.expectEqualSlices(u8, "zz", buffers[1].base[9..11]); +} + +test "openat" { + var ring = IoUring.init(1, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + var tmp = std.testing.tmpDir(.{}); + defer tmp.cleanup(); + + const path = "test_io_uring_openat"; + + // Workaround for LLVM bug: https://github.com/ziglang/zig/issues/12014 + const path_addr = if (builtin.zig_backend == .stage2_llvm) p: { + var workaround = path; + _ = &workaround; + break :p @intFromPtr(workaround); + } else @intFromPtr(path); + + const flags: linux.O = .{ .CLOEXEC = true, .ACCMODE = .RDWR, .CREAT = true }; + const mode: posix.mode_t = 0o666; + const sqe_openat = try ring.openat(0x33333333, tmp.dir.handle, path, flags, mode); + try testing.expectEqual(linux.io_uring_sqe{ + .opcode = .OPENAT, + .flags = 0, + .ioprio = 0, + .fd = tmp.dir.handle, + .off = 0, + .addr = path_addr, + .len = mode, + .rw_flags = @bitCast(flags), + .user_data = 0x33333333, + .buf_index = 0, + .personality = 0, + .splice_fd_in = 0, + .addr3 = 0, + .resv = 0, + }, sqe_openat.*); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe_openat = try ring.copy_cqe(); + try testing.expectEqual(@as(u64, 0x33333333), cqe_openat.user_data); + if (cqe_openat.err() == .INVAL) return error.SkipZigTest; + if (cqe_openat.err() == .BADF) return error.SkipZigTest; + if (cqe_openat.res <= 0) std.debug.print("\ncqe_openat.res={}\n", .{cqe_openat.res}); + try testing.expect(cqe_openat.res > 0); + try testing.expectEqual(@as(u32, 0), cqe_openat.flags); + + posix.close(cqe_openat.res); +} + +test "close" { + const io = testing.io; + + var ring = IoUring.init(1, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + var tmp = std.testing.tmpDir(.{}); + defer tmp.cleanup(); + + const path = "test_io_uring_close"; + const file = try tmp.dir.createFile(io, path, .{}); + errdefer file.close(io); + + const sqe_close = try ring.close(0x44444444, file.handle); + try testing.expectEqual(linux.IORING_OP.CLOSE, sqe_close.opcode); + try testing.expectEqual(file.handle, sqe_close.fd); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe_close = try ring.copy_cqe(); + if (cqe_close.err() == .INVAL) return error.SkipZigTest; + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x44444444, + .res = 0, + .flags = 0, + }, cqe_close); +} + +test "accept/connect/send/recv" { + const io = testing.io; + _ = io; + + var ring = IoUring.init(16, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + const socket_test_harness = try createSocketTestHarness(&ring); + defer socket_test_harness.close(); + + const buffer_send = [_]u8{ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 }; + var buffer_recv = [_]u8{ 0, 1, 0, 1, 0 }; + + const sqe_send = try ring.send(0xeeeeeeee, socket_test_harness.client, buffer_send[0..], 0); + sqe_send.flags |= linux.IOSQE_IO_LINK; + _ = try ring.recv(0xffffffff, socket_test_harness.server, .{ .buffer = buffer_recv[0..] }, 0); + try testing.expectEqual(@as(u32, 2), try ring.submit()); + + const cqe_send = try ring.copy_cqe(); + if (cqe_send.err() == .INVAL) return error.SkipZigTest; + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0xeeeeeeee, + .res = buffer_send.len, + .flags = 0, + }, cqe_send); + + const cqe_recv = try ring.copy_cqe(); + if (cqe_recv.err() == .INVAL) return error.SkipZigTest; + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0xffffffff, + .res = buffer_recv.len, + // ignore IORING_CQE_F_SOCK_NONEMPTY since it is only set on some systems + .flags = cqe_recv.flags & linux.IORING_CQE_F_SOCK_NONEMPTY, + }, cqe_recv); + + try testing.expectEqualSlices(u8, buffer_send[0..buffer_recv.len], buffer_recv[0..]); +} + +test "sendmsg/recvmsg" { + var ring = IoUring.init(2, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + var address_server: linux.sockaddr.in = .{ + .port = 0, + .addr = @bitCast([4]u8{ 127, 0, 0, 1 }), + }; + + const server = try socket(address_server.family, posix.SOCK.DGRAM, 0); + defer posix.close(server); + try posix.setsockopt(server, posix.SOL.SOCKET, posix.SO.REUSEPORT, &mem.toBytes(@as(c_int, 1))); + try posix.setsockopt(server, posix.SOL.SOCKET, posix.SO.REUSEADDR, &mem.toBytes(@as(c_int, 1))); + try bind(server, addrAny(&address_server), @sizeOf(linux.sockaddr.in)); + + // set address_server to the OS-chosen IP/port. + var slen: posix.socklen_t = @sizeOf(linux.sockaddr.in); + try getsockname(server, addrAny(&address_server), &slen); + + const client = try socket(address_server.family, posix.SOCK.DGRAM, 0); + defer posix.close(client); + + const buffer_send = [_]u8{42} ** 128; + const iovecs_send = [_]iovec_const{ + iovec_const{ .base = &buffer_send, .len = buffer_send.len }, + }; + const msg_send: linux.msghdr_const = .{ + .name = addrAny(&address_server), + .namelen = @sizeOf(linux.sockaddr.in), + .iov = &iovecs_send, + .iovlen = 1, + .control = null, + .controllen = 0, + .flags = 0, + }; + const sqe_sendmsg = try ring.sendmsg(0x11111111, client, &msg_send, 0); + sqe_sendmsg.flags |= linux.IOSQE_IO_LINK; + try testing.expectEqual(linux.IORING_OP.SENDMSG, sqe_sendmsg.opcode); + try testing.expectEqual(client, sqe_sendmsg.fd); + + var buffer_recv = [_]u8{0} ** 128; + var iovecs_recv = [_]iovec{ + iovec{ .base = &buffer_recv, .len = buffer_recv.len }, + }; + var address_recv: linux.sockaddr.in = .{ + .port = 0, + .addr = 0, + }; + var msg_recv: linux.msghdr = .{ + .name = addrAny(&address_recv), + .namelen = @sizeOf(linux.sockaddr.in), + .iov = &iovecs_recv, + .iovlen = 1, + .control = null, + .controllen = 0, + .flags = 0, + }; + const sqe_recvmsg = try ring.recvmsg(0x22222222, server, &msg_recv, 0); + try testing.expectEqual(linux.IORING_OP.RECVMSG, sqe_recvmsg.opcode); + try testing.expectEqual(server, sqe_recvmsg.fd); + + try testing.expectEqual(@as(u32, 2), ring.sq_ready()); + try testing.expectEqual(@as(u32, 2), try ring.submit_and_wait(2)); + try testing.expectEqual(@as(u32, 0), ring.sq_ready()); + try testing.expectEqual(@as(u32, 2), ring.cq_ready()); + + const cqe_sendmsg = try ring.copy_cqe(); + if (cqe_sendmsg.res == -@as(i32, @intFromEnum(linux.E.INVAL))) return error.SkipZigTest; + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x11111111, + .res = buffer_send.len, + .flags = 0, + }, cqe_sendmsg); + + const cqe_recvmsg = try ring.copy_cqe(); + if (cqe_recvmsg.res == -@as(i32, @intFromEnum(linux.E.INVAL))) return error.SkipZigTest; + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x22222222, + .res = buffer_recv.len, + // ignore IORING_CQE_F_SOCK_NONEMPTY since it is set non-deterministically + .flags = cqe_recvmsg.flags & linux.IORING_CQE_F_SOCK_NONEMPTY, + }, cqe_recvmsg); + + try testing.expectEqualSlices(u8, buffer_send[0..buffer_recv.len], buffer_recv[0..]); +} + +test "timeout (after a relative time)" { + const io = testing.io; + + var ring = IoUring.init(1, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + const ms = 10; + const margin = 5; + const ts: linux.kernel_timespec = .{ .sec = 0, .nsec = ms * 1000000 }; + + const started = try std.Io.Clock.awake.now(io); + const sqe = try ring.timeout(0x55555555, &ts, 0, 0); + try testing.expectEqual(linux.IORING_OP.TIMEOUT, sqe.opcode); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + const cqe = try ring.copy_cqe(); + const stopped = try std.Io.Clock.awake.now(io); + + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x55555555, + .res = -@as(i32, @intFromEnum(linux.E.TIME)), + .flags = 0, + }, cqe); + + // Tests should not depend on timings: skip test if outside margin. + const ms_elapsed = started.durationTo(stopped).toMilliseconds(); + if (ms_elapsed > margin) return error.SkipZigTest; +} + +test "timeout (after a number of completions)" { + var ring = IoUring.init(2, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + const ts: linux.kernel_timespec = .{ .sec = 3, .nsec = 0 }; + const count_completions: u64 = 1; + const sqe_timeout = try ring.timeout(0x66666666, &ts, count_completions, 0); + try testing.expectEqual(linux.IORING_OP.TIMEOUT, sqe_timeout.opcode); + try testing.expectEqual(count_completions, sqe_timeout.off); + _ = try ring.nop(0x77777777); + try testing.expectEqual(@as(u32, 2), try ring.submit()); + + const cqe_nop = try ring.copy_cqe(); + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x77777777, + .res = 0, + .flags = 0, + }, cqe_nop); + + const cqe_timeout = try ring.copy_cqe(); + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x66666666, + .res = 0, + .flags = 0, + }, cqe_timeout); +} + +test "timeout_remove" { + var ring = IoUring.init(2, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + const ts: linux.kernel_timespec = .{ .sec = 3, .nsec = 0 }; + const sqe_timeout = try ring.timeout(0x88888888, &ts, 0, 0); + try testing.expectEqual(linux.IORING_OP.TIMEOUT, sqe_timeout.opcode); + try testing.expectEqual(@as(u64, 0x88888888), sqe_timeout.user_data); + + const sqe_timeout_remove = try ring.timeout_remove(0x99999999, 0x88888888, 0); + try testing.expectEqual(linux.IORING_OP.TIMEOUT_REMOVE, sqe_timeout_remove.opcode); + try testing.expectEqual(@as(u64, 0x88888888), sqe_timeout_remove.addr); + try testing.expectEqual(@as(u64, 0x99999999), sqe_timeout_remove.user_data); + + try testing.expectEqual(@as(u32, 2), try ring.submit()); + + // The order in which the CQE arrive is not clearly documented and it changed with kernel 5.18: + // * kernel 5.10 gives user data 0x88888888 first, 0x99999999 second + // * kernel 5.18 gives user data 0x99999999 first, 0x88888888 second + + var cqes: [2]linux.io_uring_cqe = undefined; + cqes[0] = try ring.copy_cqe(); + cqes[1] = try ring.copy_cqe(); + + for (cqes) |cqe| { + // IORING_OP_TIMEOUT_REMOVE is not supported by this kernel version: + // Timeout remove operations set the fd to -1, which results in EBADF before EINVAL. + // We use IORING_FEAT_RW_CUR_POS as a safety check here to make sure we are at least pre-5.6. + // We don't want to skip this test for newer kernels. + if (cqe.user_data == 0x99999999 and + cqe.err() == .BADF and + (ring.features & linux.IORING_FEAT_RW_CUR_POS) == 0) + { + return error.SkipZigTest; + } + + try testing.expect(cqe.user_data == 0x88888888 or cqe.user_data == 0x99999999); + + if (cqe.user_data == 0x88888888) { + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x88888888, + .res = -@as(i32, @intFromEnum(linux.E.CANCELED)), + .flags = 0, + }, cqe); + } else if (cqe.user_data == 0x99999999) { + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x99999999, + .res = 0, + .flags = 0, + }, cqe); + } + } +} + +test "accept/connect/recv/link_timeout" { + const io = testing.io; + _ = io; + + var ring = IoUring.init(16, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + const socket_test_harness = try createSocketTestHarness(&ring); + defer socket_test_harness.close(); + + var buffer_recv = [_]u8{ 0, 1, 0, 1, 0 }; + + const sqe_recv = try ring.recv(0xffffffff, socket_test_harness.server, .{ .buffer = buffer_recv[0..] }, 0); + sqe_recv.flags |= linux.IOSQE_IO_LINK; + + const ts = linux.kernel_timespec{ .sec = 0, .nsec = 1000000 }; + _ = try ring.link_timeout(0x22222222, &ts, 0); + + const nr_wait = try ring.submit(); + try testing.expectEqual(@as(u32, 2), nr_wait); + + var i: usize = 0; + while (i < nr_wait) : (i += 1) { + const cqe = try ring.copy_cqe(); + switch (cqe.user_data) { + 0xffffffff => { + if (cqe.res != -@as(i32, @intFromEnum(linux.E.INTR)) and + cqe.res != -@as(i32, @intFromEnum(linux.E.CANCELED))) + { + std.debug.print("Req 0x{x} got {d}\n", .{ cqe.user_data, cqe.res }); + try testing.expect(false); + } + }, + 0x22222222 => { + if (cqe.res != -@as(i32, @intFromEnum(linux.E.ALREADY)) and + cqe.res != -@as(i32, @intFromEnum(linux.E.TIME))) + { + std.debug.print("Req 0x{x} got {d}\n", .{ cqe.user_data, cqe.res }); + try testing.expect(false); + } + }, + else => @panic("should not happen"), + } + } +} + +test "fallocate" { + const io = testing.io; + + var ring = IoUring.init(1, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + var tmp = std.testing.tmpDir(.{}); + defer tmp.cleanup(); + + const path = "test_io_uring_fallocate"; + const file = try tmp.dir.createFile(io, path, .{}); + defer file.close(io); + + try testing.expectEqual(@as(u64, 0), (try file.stat(io)).size); + + const len: u64 = 65536; + const sqe = try ring.fallocate(0xaaaaaaaa, file.handle, 0, 0, len); + try testing.expectEqual(linux.IORING_OP.FALLOCATE, sqe.opcode); + try testing.expectEqual(file.handle, sqe.fd); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe = try ring.copy_cqe(); + switch (cqe.err()) { + .SUCCESS => {}, + // This kernel's io_uring does not yet implement fallocate(): + .INVAL => return error.SkipZigTest, + // This kernel does not implement fallocate(): + .NOSYS => return error.SkipZigTest, + // The filesystem containing the file referred to by fd does not support this operation; + // or the mode is not supported by the filesystem containing the file referred to by fd: + .OPNOTSUPP => return error.SkipZigTest, + else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + } + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0xaaaaaaaa, + .res = 0, + .flags = 0, + }, cqe); + + try testing.expectEqual(len, (try file.stat(io)).size); +} + +test "statx" { + const io = testing.io; + + var ring = IoUring.init(1, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + var tmp = std.testing.tmpDir(.{}); + defer tmp.cleanup(); + const path = "test_io_uring_statx"; + const file = try tmp.dir.createFile(io, path, .{}); + defer file.close(io); + + try testing.expectEqual(@as(u64, 0), (try file.stat(io)).size); + + try file.writeStreamingAll(io, "foobar"); + + var buf: linux.Statx = undefined; + const sqe = try ring.statx( + 0xaaaaaaaa, + tmp.dir.handle, + path, + 0, + .{ .SIZE = true }, + &buf, + ); + try testing.expectEqual(linux.IORING_OP.STATX, sqe.opcode); + try testing.expectEqual(@as(i32, tmp.dir.handle), sqe.fd); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe = try ring.copy_cqe(); + switch (cqe.err()) { + .SUCCESS => {}, + // This kernel's io_uring does not yet implement statx(): + .INVAL => return error.SkipZigTest, + // This kernel does not implement statx(): + .NOSYS => return error.SkipZigTest, + // The filesystem containing the file referred to by fd does not support this operation; + // or the mode is not supported by the filesystem containing the file referred to by fd: + .OPNOTSUPP => return error.SkipZigTest, + // not supported on older kernels (5.4) + .BADF => return error.SkipZigTest, + else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + } + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0xaaaaaaaa, + .res = 0, + .flags = 0, + }, cqe); + + try testing.expect(buf.mask.SIZE); + try testing.expectEqual(@as(u64, 6), buf.size); +} + +test "accept/connect/recv/cancel" { + const io = testing.io; + _ = io; + + var ring = IoUring.init(16, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + const socket_test_harness = try createSocketTestHarness(&ring); + defer socket_test_harness.close(); + + var buffer_recv = [_]u8{ 0, 1, 0, 1, 0 }; + + _ = try ring.recv(0xffffffff, socket_test_harness.server, .{ .buffer = buffer_recv[0..] }, 0); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const sqe_cancel = try ring.cancel(0x99999999, 0xffffffff, 0); + try testing.expectEqual(linux.IORING_OP.ASYNC_CANCEL, sqe_cancel.opcode); + try testing.expectEqual(@as(u64, 0xffffffff), sqe_cancel.addr); + try testing.expectEqual(@as(u64, 0x99999999), sqe_cancel.user_data); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + var cqe_recv = try ring.copy_cqe(); + if (cqe_recv.err() == .INVAL) return error.SkipZigTest; + var cqe_cancel = try ring.copy_cqe(); + if (cqe_cancel.err() == .INVAL) return error.SkipZigTest; + + // The recv/cancel CQEs may arrive in any order, the recv CQE will sometimes come first: + if (cqe_recv.user_data == 0x99999999 and cqe_cancel.user_data == 0xffffffff) { + const a = cqe_recv; + const b = cqe_cancel; + cqe_recv = b; + cqe_cancel = a; + } + + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0xffffffff, + .res = -@as(i32, @intFromEnum(linux.E.CANCELED)), + .flags = 0, + }, cqe_recv); + + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x99999999, + .res = 0, + .flags = 0, + }, cqe_cancel); +} + +test "register_files_update" { + const io = testing.io; + + var ring = IoUring.init(1, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + const file = try Io.Dir.openFileAbsolute(io, "/dev/zero", .{}); + defer file.close(io); + + var registered_fds = [_]linux.fd_t{0} ** 2; + const fd_index = 0; + const fd_index2 = 1; + registered_fds[fd_index] = file.handle; + registered_fds[fd_index2] = -1; + + ring.register_files(registered_fds[0..]) catch |err| switch (err) { + // Happens when the kernel doesn't support sparse entry (-1) in the file descriptors array. + error.FileDescriptorInvalid => return error.SkipZigTest, + else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + }; + + // Test IORING_REGISTER_FILES_UPDATE + // Only available since Linux 5.5 + + const file2 = try Io.Dir.openFileAbsolute(io, "/dev/zero", .{}); + defer file2.close(io); + + registered_fds[fd_index] = file2.handle; + registered_fds[fd_index2] = -1; + try ring.register_files_update(0, registered_fds[0..]); + + var buffer = [_]u8{42} ** 128; + { + const sqe = try ring.read(0xcccccccc, fd_index, .{ .buffer = &buffer }, 0); + try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode); + sqe.flags |= linux.IOSQE_FIXED_FILE; + + try testing.expectEqual(@as(u32, 1), try ring.submit()); + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0xcccccccc, + .res = buffer.len, + .flags = 0, + }, try ring.copy_cqe()); + try testing.expectEqualSlices(u8, &([_]u8{0} ** buffer.len), buffer[0..]); + } + + // Test with a non-zero offset + + registered_fds[fd_index] = -1; + registered_fds[fd_index2] = -1; + try ring.register_files_update(1, registered_fds[1..]); + + { + // Next read should still work since fd_index in the registered file descriptors hasn't been updated yet. + const sqe = try ring.read(0xcccccccc, fd_index, .{ .buffer = &buffer }, 0); + try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode); + sqe.flags |= linux.IOSQE_FIXED_FILE; + + try testing.expectEqual(@as(u32, 1), try ring.submit()); + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0xcccccccc, + .res = buffer.len, + .flags = 0, + }, try ring.copy_cqe()); + try testing.expectEqualSlices(u8, &([_]u8{0} ** buffer.len), buffer[0..]); + } + + try ring.register_files_update(0, registered_fds[0..]); + + { + // Now this should fail since both fds are sparse (-1) + const sqe = try ring.read(0xcccccccc, fd_index, .{ .buffer = &buffer }, 0); + try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode); + sqe.flags |= linux.IOSQE_FIXED_FILE; + + try testing.expectEqual(@as(u32, 1), try ring.submit()); + const cqe = try ring.copy_cqe(); + try testing.expectEqual(linux.E.BADF, cqe.err()); + } + + try ring.unregister_files(); +} + +test "shutdown" { + var ring = IoUring.init(16, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + var address: linux.sockaddr.in = .{ + .port = 0, + .addr = @bitCast([4]u8{ 127, 0, 0, 1 }), + }; + + // Socket bound, expect shutdown to work + { + const server = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); + defer posix.close(server); + try posix.setsockopt(server, posix.SOL.SOCKET, posix.SO.REUSEADDR, &mem.toBytes(@as(c_int, 1))); + try bind(server, addrAny(&address), @sizeOf(linux.sockaddr.in)); + try listen(server, 1); + + // set address to the OS-chosen IP/port. + var slen: posix.socklen_t = @sizeOf(linux.sockaddr.in); + try getsockname(server, addrAny(&address), &slen); + + const shutdown_sqe = try ring.shutdown(0x445445445, server, linux.SHUT.RD); + try testing.expectEqual(linux.IORING_OP.SHUTDOWN, shutdown_sqe.opcode); + try testing.expectEqual(@as(i32, server), shutdown_sqe.fd); + + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe = try ring.copy_cqe(); + switch (cqe.err()) { + .SUCCESS => {}, + // This kernel's io_uring does not yet implement shutdown (kernel version < 5.11) + .INVAL => return error.SkipZigTest, + else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + } + + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x445445445, + .res = 0, + .flags = 0, + }, cqe); + } + + // Socket not bound, expect to fail with ENOTCONN + { + const server = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); + defer posix.close(server); + + const shutdown_sqe = ring.shutdown(0x445445445, server, linux.SHUT.RD) catch |err| switch (err) { + else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + }; + try testing.expectEqual(linux.IORING_OP.SHUTDOWN, shutdown_sqe.opcode); + try testing.expectEqual(@as(i32, server), shutdown_sqe.fd); + + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe = try ring.copy_cqe(); + try testing.expectEqual(@as(u64, 0x445445445), cqe.user_data); + try testing.expectEqual(linux.E.NOTCONN, cqe.err()); + } +} + +test "renameat" { + const io = testing.io; + + var ring = IoUring.init(1, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + const old_path = "test_io_uring_renameat_old"; + const new_path = "test_io_uring_renameat_new"; + + var tmp = std.testing.tmpDir(.{}); + defer tmp.cleanup(); + + // Write old file with data + + const old_file = try tmp.dir.createFile(io, old_path, .{}); + defer old_file.close(io); + try old_file.writeStreamingAll(io, "hello"); + + // Submit renameat + + const sqe = try ring.renameat( + 0x12121212, + tmp.dir.handle, + old_path, + tmp.dir.handle, + new_path, + 0, + ); + try testing.expectEqual(linux.IORING_OP.RENAMEAT, sqe.opcode); + try testing.expectEqual(@as(i32, tmp.dir.handle), sqe.fd); + try testing.expectEqual(@as(i32, tmp.dir.handle), @as(i32, @bitCast(sqe.len))); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe = try ring.copy_cqe(); + switch (cqe.err()) { + .SUCCESS => {}, + // This kernel's io_uring does not yet implement renameat (kernel version < 5.11) + .BADF, .INVAL => return error.SkipZigTest, + else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + } + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x12121212, + .res = 0, + .flags = 0, + }, cqe); + + // Validate that the old file doesn't exist anymore + try testing.expectError(error.FileNotFound, tmp.dir.openFile(io, old_path, .{})); + + // Validate that the new file exists with the proper content + var new_file_data: [16]u8 = undefined; + try testing.expectEqualStrings("hello", try tmp.dir.readFile(io, new_path, &new_file_data)); +} + +test "unlinkat" { + const io = testing.io; + + var ring = IoUring.init(1, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + const path = "test_io_uring_unlinkat"; + + var tmp = std.testing.tmpDir(.{}); + defer tmp.cleanup(); + + // Write old file with data + + const file = try tmp.dir.createFile(io, path, .{}); + defer file.close(io); + + // Submit unlinkat + + const sqe = try ring.unlinkat( + 0x12121212, + tmp.dir.handle, + path, + 0, + ); + try testing.expectEqual(linux.IORING_OP.UNLINKAT, sqe.opcode); + try testing.expectEqual(@as(i32, tmp.dir.handle), sqe.fd); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe = try ring.copy_cqe(); + switch (cqe.err()) { + .SUCCESS => {}, + // This kernel's io_uring does not yet implement unlinkat (kernel version < 5.11) + .BADF, .INVAL => return error.SkipZigTest, + else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + } + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x12121212, + .res = 0, + .flags = 0, + }, cqe); + + // Validate that the file doesn't exist anymore + _ = tmp.dir.openFile(io, path, .{}) catch |err| switch (err) { + error.FileNotFound => {}, + else => std.debug.panic("unexpected error: {}", .{err}), + }; +} + +test "mkdirat" { + const io = testing.io; + + var ring = IoUring.init(1, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + var tmp = std.testing.tmpDir(.{}); + defer tmp.cleanup(); + + const path = "test_io_uring_mkdirat"; + + // Submit mkdirat + + const sqe = try ring.mkdirat( + 0x12121212, + tmp.dir.handle, + path, + 0o0755, + ); + try testing.expectEqual(linux.IORING_OP.MKDIRAT, sqe.opcode); + try testing.expectEqual(@as(i32, tmp.dir.handle), sqe.fd); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe = try ring.copy_cqe(); + switch (cqe.err()) { + .SUCCESS => {}, + // This kernel's io_uring does not yet implement mkdirat (kernel version < 5.15) + .BADF, .INVAL => return error.SkipZigTest, + else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + } + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x12121212, + .res = 0, + .flags = 0, + }, cqe); + + // Validate that the directory exist + _ = try tmp.dir.openDir(io, path, .{}); +} + +test "symlinkat" { + const io = testing.io; + + var ring = IoUring.init(1, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + var tmp = std.testing.tmpDir(.{}); + defer tmp.cleanup(); + + const path = "test_io_uring_symlinkat"; + const link_path = "test_io_uring_symlinkat_link"; + + const file = try tmp.dir.createFile(io, path, .{}); + defer file.close(io); + + // Submit symlinkat + + const sqe = try ring.symlinkat( + 0x12121212, + path, + tmp.dir.handle, + link_path, + ); + try testing.expectEqual(linux.IORING_OP.SYMLINKAT, sqe.opcode); + try testing.expectEqual(@as(i32, tmp.dir.handle), sqe.fd); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe = try ring.copy_cqe(); + switch (cqe.err()) { + .SUCCESS => {}, + // This kernel's io_uring does not yet implement symlinkat (kernel version < 5.15) + .BADF, .INVAL => return error.SkipZigTest, + else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + } + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x12121212, + .res = 0, + .flags = 0, + }, cqe); + + // Validate that the symlink exist + _ = try tmp.dir.openFile(io, link_path, .{}); +} + +test "linkat" { + const io = testing.io; + + var ring = IoUring.init(1, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + var tmp = std.testing.tmpDir(.{}); + defer tmp.cleanup(); + + const first_path = "test_io_uring_linkat_first"; + const second_path = "test_io_uring_linkat_second"; + + // Write file with data + + const first_file = try tmp.dir.createFile(io, first_path, .{}); + defer first_file.close(io); + try first_file.writeStreamingAll(io, "hello"); + + // Submit linkat + + const sqe = try ring.linkat( + 0x12121212, + tmp.dir.handle, + first_path, + tmp.dir.handle, + second_path, + 0, + ); + try testing.expectEqual(linux.IORING_OP.LINKAT, sqe.opcode); + try testing.expectEqual(@as(i32, tmp.dir.handle), sqe.fd); + try testing.expectEqual(@as(i32, tmp.dir.handle), @as(i32, @bitCast(sqe.len))); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe = try ring.copy_cqe(); + switch (cqe.err()) { + .SUCCESS => {}, + // This kernel's io_uring does not yet implement linkat (kernel version < 5.15) + .BADF, .INVAL => return error.SkipZigTest, + else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + } + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x12121212, + .res = 0, + .flags = 0, + }, cqe); + + // Validate the second file + var second_file_data: [16]u8 = undefined; + try testing.expectEqualStrings("hello", try tmp.dir.readFile(io, second_path, &second_file_data)); +} + +test "provide_buffers: read" { + const io = testing.io; + + var ring = IoUring.init(1, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + const file = try Io.Dir.openFileAbsolute(io, "/dev/zero", .{}); + defer file.close(io); + + const group_id = 1337; + const buffer_id = 0; + + const buffer_len = 128; + + var buffers: [4][buffer_len]u8 = undefined; + + // Provide 4 buffers + + { + const sqe = try ring.provide_buffers(0xcccccccc, @as([*]u8, @ptrCast(&buffers)), buffer_len, buffers.len, group_id, buffer_id); + try testing.expectEqual(linux.IORING_OP.PROVIDE_BUFFERS, sqe.opcode); + try testing.expectEqual(@as(i32, buffers.len), sqe.fd); + try testing.expectEqual(@as(u32, buffers[0].len), sqe.len); + try testing.expectEqual(@as(u16, group_id), sqe.buf_index); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe = try ring.copy_cqe(); + switch (cqe.err()) { + // Happens when the kernel is < 5.7 + .INVAL, .BADF => return error.SkipZigTest, + .SUCCESS => {}, + else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + } + try testing.expectEqual(@as(u64, 0xcccccccc), cqe.user_data); + } + + // Do 4 reads which should consume all buffers + + var i: usize = 0; + while (i < buffers.len) : (i += 1) { + const sqe = try ring.read(0xdededede, file.handle, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); + try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode); + try testing.expectEqual(@as(i32, file.handle), sqe.fd); + try testing.expectEqual(@as(u64, 0), sqe.addr); + try testing.expectEqual(@as(u32, buffer_len), sqe.len); + try testing.expectEqual(@as(u16, group_id), sqe.buf_index); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe = try ring.copy_cqe(); + switch (cqe.err()) { + .SUCCESS => {}, + else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + } + + try testing.expect(cqe.flags & linux.IORING_CQE_F_BUFFER == linux.IORING_CQE_F_BUFFER); + const used_buffer_id = cqe.flags >> 16; + try testing.expect(used_buffer_id >= 0 and used_buffer_id <= 3); + try testing.expectEqual(@as(i32, buffer_len), cqe.res); + + try testing.expectEqual(@as(u64, 0xdededede), cqe.user_data); + try testing.expectEqualSlices(u8, &([_]u8{0} ** buffer_len), buffers[used_buffer_id][0..@as(usize, @intCast(cqe.res))]); + } + + // This read should fail + + { + const sqe = try ring.read(0xdfdfdfdf, file.handle, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); + try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode); + try testing.expectEqual(@as(i32, file.handle), sqe.fd); + try testing.expectEqual(@as(u64, 0), sqe.addr); + try testing.expectEqual(@as(u32, buffer_len), sqe.len); + try testing.expectEqual(@as(u16, group_id), sqe.buf_index); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe = try ring.copy_cqe(); + switch (cqe.err()) { + // Expected + .NOBUFS => {}, + .SUCCESS => std.debug.panic("unexpected success", .{}), + else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + } + try testing.expectEqual(@as(u64, 0xdfdfdfdf), cqe.user_data); + } + + // Provide 1 buffer again + + // Deliberately put something we don't expect in the buffers + @memset(mem.sliceAsBytes(&buffers), 42); + + const reprovided_buffer_id = 2; + + { + _ = try ring.provide_buffers(0xabababab, @as([*]u8, @ptrCast(&buffers[reprovided_buffer_id])), buffer_len, 1, group_id, reprovided_buffer_id); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe = try ring.copy_cqe(); + switch (cqe.err()) { + .SUCCESS => {}, + else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + } + } + + // Final read which should work + + { + const sqe = try ring.read(0xdfdfdfdf, file.handle, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); + try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode); + try testing.expectEqual(@as(i32, file.handle), sqe.fd); + try testing.expectEqual(@as(u64, 0), sqe.addr); + try testing.expectEqual(@as(u32, buffer_len), sqe.len); + try testing.expectEqual(@as(u16, group_id), sqe.buf_index); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe = try ring.copy_cqe(); + switch (cqe.err()) { + .SUCCESS => {}, + else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + } + + try testing.expect(cqe.flags & linux.IORING_CQE_F_BUFFER == linux.IORING_CQE_F_BUFFER); + const used_buffer_id = cqe.flags >> 16; + try testing.expectEqual(used_buffer_id, reprovided_buffer_id); + try testing.expectEqual(@as(i32, buffer_len), cqe.res); + try testing.expectEqual(@as(u64, 0xdfdfdfdf), cqe.user_data); + try testing.expectEqualSlices(u8, &([_]u8{0} ** buffer_len), buffers[used_buffer_id][0..@as(usize, @intCast(cqe.res))]); + } +} + +test "remove_buffers" { + const io = testing.io; + + var ring = IoUring.init(1, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + const file = try Io.Dir.openFileAbsolute(io, "/dev/zero", .{}); + defer file.close(io); + + const group_id = 1337; + const buffer_id = 0; + + const buffer_len = 128; + + var buffers: [4][buffer_len]u8 = undefined; + + // Provide 4 buffers + + { + _ = try ring.provide_buffers(0xcccccccc, @as([*]u8, @ptrCast(&buffers)), buffer_len, buffers.len, group_id, buffer_id); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe = try ring.copy_cqe(); + switch (cqe.err()) { + .INVAL, .BADF => return error.SkipZigTest, + .SUCCESS => {}, + else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + } + try testing.expectEqual(@as(u64, 0xcccccccc), cqe.user_data); + } + + // Remove 3 buffers + + { + const sqe = try ring.remove_buffers(0xbababababa, 3, group_id); + try testing.expectEqual(linux.IORING_OP.REMOVE_BUFFERS, sqe.opcode); + try testing.expectEqual(@as(i32, 3), sqe.fd); + try testing.expectEqual(@as(u64, 0), sqe.addr); + try testing.expectEqual(@as(u16, group_id), sqe.buf_index); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe = try ring.copy_cqe(); + switch (cqe.err()) { + .SUCCESS => {}, + else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + } + try testing.expectEqual(@as(u64, 0xbababababa), cqe.user_data); + } + + // This read should work + + { + _ = try ring.read(0xdfdfdfdf, file.handle, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe = try ring.copy_cqe(); + switch (cqe.err()) { + .SUCCESS => {}, + else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + } + + try testing.expect(cqe.flags & linux.IORING_CQE_F_BUFFER == linux.IORING_CQE_F_BUFFER); + const used_buffer_id = cqe.flags >> 16; + try testing.expect(used_buffer_id >= 0 and used_buffer_id < 4); + try testing.expectEqual(@as(i32, buffer_len), cqe.res); + try testing.expectEqual(@as(u64, 0xdfdfdfdf), cqe.user_data); + try testing.expectEqualSlices(u8, &([_]u8{0} ** buffer_len), buffers[used_buffer_id][0..@as(usize, @intCast(cqe.res))]); + } + + // Final read should _not_ work + + { + _ = try ring.read(0xdfdfdfdf, file.handle, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe = try ring.copy_cqe(); + switch (cqe.err()) { + // Expected + .NOBUFS => {}, + .SUCCESS => std.debug.panic("unexpected success", .{}), + else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + } + } +} + +test "provide_buffers: accept/connect/send/recv" { + const io = testing.io; + _ = io; + + var ring = IoUring.init(16, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + const group_id = 1337; + const buffer_id = 0; + + const buffer_len = 128; + var buffers: [4][buffer_len]u8 = undefined; + + // Provide 4 buffers + + { + const sqe = try ring.provide_buffers(0xcccccccc, @as([*]u8, @ptrCast(&buffers)), buffer_len, buffers.len, group_id, buffer_id); + try testing.expectEqual(linux.IORING_OP.PROVIDE_BUFFERS, sqe.opcode); + try testing.expectEqual(@as(i32, buffers.len), sqe.fd); + try testing.expectEqual(@as(u32, buffer_len), sqe.len); + try testing.expectEqual(@as(u16, group_id), sqe.buf_index); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe = try ring.copy_cqe(); + switch (cqe.err()) { + // Happens when the kernel is < 5.7 + .INVAL => return error.SkipZigTest, + // Happens on the kernel 5.4 + .BADF => return error.SkipZigTest, + .SUCCESS => {}, + else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + } + try testing.expectEqual(@as(u64, 0xcccccccc), cqe.user_data); + } + + const socket_test_harness = try createSocketTestHarness(&ring); + defer socket_test_harness.close(); + + // Do 4 send on the socket + + { + var i: usize = 0; + while (i < buffers.len) : (i += 1) { + _ = try ring.send(0xdeaddead, socket_test_harness.server, &([_]u8{'z'} ** buffer_len), 0); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + } + + var cqes: [4]linux.io_uring_cqe = undefined; + try testing.expectEqual(@as(u32, 4), try ring.copy_cqes(&cqes, 4)); + } + + // Do 4 recv which should consume all buffers + + // Deliberately put something we don't expect in the buffers + @memset(mem.sliceAsBytes(&buffers), 1); + + var i: usize = 0; + while (i < buffers.len) : (i += 1) { + const sqe = try ring.recv(0xdededede, socket_test_harness.client, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); + try testing.expectEqual(linux.IORING_OP.RECV, sqe.opcode); + try testing.expectEqual(@as(i32, socket_test_harness.client), sqe.fd); + try testing.expectEqual(@as(u64, 0), sqe.addr); + try testing.expectEqual(@as(u32, buffer_len), sqe.len); + try testing.expectEqual(@as(u16, group_id), sqe.buf_index); + try testing.expectEqual(@as(u32, 0), sqe.rw_flags); + try testing.expectEqual(@as(u32, linux.IOSQE_BUFFER_SELECT), sqe.flags); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe = try ring.copy_cqe(); + switch (cqe.err()) { + .SUCCESS => {}, + else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + } + + try testing.expect(cqe.flags & linux.IORING_CQE_F_BUFFER == linux.IORING_CQE_F_BUFFER); + const used_buffer_id = cqe.flags >> 16; + try testing.expect(used_buffer_id >= 0 and used_buffer_id <= 3); + try testing.expectEqual(@as(i32, buffer_len), cqe.res); + + try testing.expectEqual(@as(u64, 0xdededede), cqe.user_data); + const buffer = buffers[used_buffer_id][0..@as(usize, @intCast(cqe.res))]; + try testing.expectEqualSlices(u8, &([_]u8{'z'} ** buffer_len), buffer); + } + + // This recv should fail + + { + const sqe = try ring.recv(0xdfdfdfdf, socket_test_harness.client, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); + try testing.expectEqual(linux.IORING_OP.RECV, sqe.opcode); + try testing.expectEqual(@as(i32, socket_test_harness.client), sqe.fd); + try testing.expectEqual(@as(u64, 0), sqe.addr); + try testing.expectEqual(@as(u32, buffer_len), sqe.len); + try testing.expectEqual(@as(u16, group_id), sqe.buf_index); + try testing.expectEqual(@as(u32, 0), sqe.rw_flags); + try testing.expectEqual(@as(u32, linux.IOSQE_BUFFER_SELECT), sqe.flags); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe = try ring.copy_cqe(); + switch (cqe.err()) { + // Expected + .NOBUFS => {}, + .SUCCESS => std.debug.panic("unexpected success", .{}), + else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + } + try testing.expectEqual(@as(u64, 0xdfdfdfdf), cqe.user_data); + } + + // Provide 1 buffer again + + const reprovided_buffer_id = 2; + + { + _ = try ring.provide_buffers(0xabababab, @as([*]u8, @ptrCast(&buffers[reprovided_buffer_id])), buffer_len, 1, group_id, reprovided_buffer_id); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe = try ring.copy_cqe(); + switch (cqe.err()) { + .SUCCESS => {}, + else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + } + } + + // Redo 1 send on the server socket + + { + _ = try ring.send(0xdeaddead, socket_test_harness.server, &([_]u8{'w'} ** buffer_len), 0); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + _ = try ring.copy_cqe(); + } + + // Final recv which should work + + // Deliberately put something we don't expect in the buffers + @memset(mem.sliceAsBytes(&buffers), 1); + + { + const sqe = try ring.recv(0xdfdfdfdf, socket_test_harness.client, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); + try testing.expectEqual(linux.IORING_OP.RECV, sqe.opcode); + try testing.expectEqual(@as(i32, socket_test_harness.client), sqe.fd); + try testing.expectEqual(@as(u64, 0), sqe.addr); + try testing.expectEqual(@as(u32, buffer_len), sqe.len); + try testing.expectEqual(@as(u16, group_id), sqe.buf_index); + try testing.expectEqual(@as(u32, 0), sqe.rw_flags); + try testing.expectEqual(@as(u32, linux.IOSQE_BUFFER_SELECT), sqe.flags); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + const cqe = try ring.copy_cqe(); + switch (cqe.err()) { + .SUCCESS => {}, + else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), + } + + try testing.expect(cqe.flags & linux.IORING_CQE_F_BUFFER == linux.IORING_CQE_F_BUFFER); + const used_buffer_id = cqe.flags >> 16; + try testing.expectEqual(used_buffer_id, reprovided_buffer_id); + try testing.expectEqual(@as(i32, buffer_len), cqe.res); + try testing.expectEqual(@as(u64, 0xdfdfdfdf), cqe.user_data); + const buffer = buffers[used_buffer_id][0..@as(usize, @intCast(cqe.res))]; + try testing.expectEqualSlices(u8, &([_]u8{'w'} ** buffer_len), buffer); + } +} + +test "accept multishot" { + var ring = IoUring.init(16, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + var address: linux.sockaddr.in = .{ + .port = 0, + .addr = @bitCast([4]u8{ 127, 0, 0, 1 }), + }; + const listener_socket = try createListenerSocket(&address); + defer posix.close(listener_socket); + + // submit multishot accept operation + var addr: posix.sockaddr = undefined; + var addr_len: posix.socklen_t = @sizeOf(@TypeOf(addr)); + const userdata: u64 = 0xaaaaaaaa; + _ = try ring.accept_multishot(userdata, listener_socket, &addr, &addr_len, 0); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + var nr: usize = 4; // number of clients to connect + while (nr > 0) : (nr -= 1) { + // connect client + const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); + errdefer posix.close(client); + try posix.connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in)); + + // test accept completion + var cqe = try ring.copy_cqe(); + if (cqe.err() == .INVAL) return error.SkipZigTest; + try testing.expect(cqe.res > 0); + try testing.expect(cqe.user_data == userdata); + try testing.expect(cqe.flags & linux.IORING_CQE_F_MORE > 0); // more flag is set + + posix.close(client); + } +} + +test "accept/connect/send_zc/recv" { + try skipKernelLessThan(.{ .major = 6, .minor = 0, .patch = 0 }); + + const io = testing.io; + _ = io; + + var ring = IoUring.init(16, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + const socket_test_harness = try createSocketTestHarness(&ring); + defer socket_test_harness.close(); + + const buffer_send = [_]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe }; + var buffer_recv = [_]u8{0} ** 10; + + // zero-copy send + const sqe_send = try ring.send_zc(0xeeeeeeee, socket_test_harness.client, buffer_send[0..], 0, 0); + sqe_send.flags |= linux.IOSQE_IO_LINK; + _ = try ring.recv(0xffffffff, socket_test_harness.server, .{ .buffer = buffer_recv[0..] }, 0); + try testing.expectEqual(@as(u32, 2), try ring.submit()); + + var cqe_send = try ring.copy_cqe(); + // First completion of zero-copy send. + // IORING_CQE_F_MORE, means that there + // will be a second completion event / notification for the + // request, with the user_data field set to the same value. + // buffer_send must be keep alive until second cqe. + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0xeeeeeeee, + .res = buffer_send.len, + .flags = linux.IORING_CQE_F_MORE, + }, cqe_send); + + cqe_send, const cqe_recv = brk: { + const cqe1 = try ring.copy_cqe(); + const cqe2 = try ring.copy_cqe(); + break :brk if (cqe1.user_data == 0xeeeeeeee) .{ cqe1, cqe2 } else .{ cqe2, cqe1 }; + }; + + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0xffffffff, + .res = buffer_recv.len, + .flags = cqe_recv.flags & linux.IORING_CQE_F_SOCK_NONEMPTY, + }, cqe_recv); + try testing.expectEqualSlices(u8, buffer_send[0..buffer_recv.len], buffer_recv[0..]); + + // Second completion of zero-copy send. + // IORING_CQE_F_NOTIF in flags signals that kernel is done with send_buffer + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0xeeeeeeee, + .res = 0, + .flags = linux.IORING_CQE_F_NOTIF, + }, cqe_send); +} + +test "accept_direct" { + try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 }); + + var ring = IoUring.init(1, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + var address: linux.sockaddr.in = .{ + .port = 0, + .addr = @bitCast([4]u8{ 127, 0, 0, 1 }), + }; + + // register direct file descriptors + var registered_fds = [_]linux.fd_t{-1} ** 2; + try ring.register_files(registered_fds[0..]); + + const listener_socket = try createListenerSocket(&address); + defer posix.close(listener_socket); + + const accept_userdata: u64 = 0xaaaaaaaa; + const read_userdata: u64 = 0xbbbbbbbb; + const data = [_]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe }; + + for (0..2) |_| { + for (registered_fds, 0..) |_, i| { + var buffer_recv = [_]u8{0} ** 16; + const buffer_send: []const u8 = data[0 .. data.len - i]; // make it different at each loop + + // submit accept, will chose registered fd and return index in cqe + _ = try ring.accept_direct(accept_userdata, listener_socket, null, null, 0); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + // connect + const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); + try posix.connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in)); + defer posix.close(client); + + // accept completion + const cqe_accept = try ring.copy_cqe(); + try testing.expectEqual(posix.E.SUCCESS, cqe_accept.err()); + const fd_index = cqe_accept.res; + try testing.expect(fd_index < registered_fds.len); + try testing.expect(cqe_accept.user_data == accept_userdata); + + // send data + _ = try send(client, buffer_send, 0); + + // Example of how to use registered fd: + // Submit receive to fixed file returned by accept (fd_index). + // Fd field is set to registered file index, returned by accept. + // Flag linux.IOSQE_FIXED_FILE must be set. + const recv_sqe = try ring.recv(read_userdata, fd_index, .{ .buffer = &buffer_recv }, 0); + recv_sqe.flags |= linux.IOSQE_FIXED_FILE; + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + // accept receive + const recv_cqe = try ring.copy_cqe(); + try testing.expect(recv_cqe.user_data == read_userdata); + try testing.expect(recv_cqe.res == buffer_send.len); + try testing.expectEqualSlices(u8, buffer_send, buffer_recv[0..buffer_send.len]); + } + // no more available fds, accept will get NFILE error + { + // submit accept + _ = try ring.accept_direct(accept_userdata, listener_socket, null, null, 0); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + // connect + const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); + try posix.connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in)); + defer posix.close(client); + // completion with error + const cqe_accept = try ring.copy_cqe(); + try testing.expect(cqe_accept.user_data == accept_userdata); + try testing.expectEqual(posix.E.NFILE, cqe_accept.err()); + } + // return file descriptors to kernel + try ring.register_files_update(0, registered_fds[0..]); + } + try ring.unregister_files(); +} + +test "accept_multishot_direct" { + try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 }); + + if (builtin.cpu.arch == .riscv64) { + // https://github.com/ziglang/zig/issues/25734 + return error.SkipZigTest; + } + + var ring = IoUring.init(1, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + var address: linux.sockaddr.in = .{ + .port = 0, + .addr = @bitCast([4]u8{ 127, 0, 0, 1 }), + }; + + var registered_fds = [_]linux.fd_t{-1} ** 2; + try ring.register_files(registered_fds[0..]); + + const listener_socket = try createListenerSocket(&address); + defer posix.close(listener_socket); + + const accept_userdata: u64 = 0xaaaaaaaa; + + for (0..2) |_| { + // submit multishot accept + // Will chose registered fd and return index of the selected registered file in cqe. + _ = try ring.accept_multishot_direct(accept_userdata, listener_socket, null, null, 0); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + for (registered_fds) |_| { + // connect + const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); + try posix.connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in)); + defer posix.close(client); + + // accept completion + const cqe_accept = try ring.copy_cqe(); + const fd_index = cqe_accept.res; + try testing.expect(fd_index < registered_fds.len); + try testing.expect(cqe_accept.user_data == accept_userdata); + try testing.expect(cqe_accept.flags & linux.IORING_CQE_F_MORE > 0); // has more is set + } + // No more available fds, accept will get NFILE error. + // Multishot is terminated (more flag is not set). + { + // connect + const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); + try posix.connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in)); + defer posix.close(client); + // completion with error + const cqe_accept = try ring.copy_cqe(); + try testing.expect(cqe_accept.user_data == accept_userdata); + try testing.expectEqual(posix.E.NFILE, cqe_accept.err()); + try testing.expect(cqe_accept.flags & linux.IORING_CQE_F_MORE == 0); // has more is not set + } + // return file descriptors to kernel + try ring.register_files_update(0, registered_fds[0..]); + } + try ring.unregister_files(); +} + +test "socket" { + try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 }); + + var ring = IoUring.init(1, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + // prepare, submit socket operation + _ = try ring.socket(0, linux.AF.INET, posix.SOCK.STREAM, 0, 0); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + // test completion + var cqe = try ring.copy_cqe(); + try testing.expectEqual(posix.E.SUCCESS, cqe.err()); + const fd: linux.fd_t = @intCast(cqe.res); + try testing.expect(fd > 2); + + posix.close(fd); +} + +test "socket_direct/socket_direct_alloc/close_direct" { + try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 }); + + var ring = IoUring.init(2, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + var registered_fds = [_]linux.fd_t{-1} ** 3; + try ring.register_files(registered_fds[0..]); + + // create socket in registered file descriptor at index 0 (last param) + _ = try ring.socket_direct(0, linux.AF.INET, posix.SOCK.STREAM, 0, 0, 0); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + var cqe_socket = try ring.copy_cqe(); + try testing.expectEqual(posix.E.SUCCESS, cqe_socket.err()); + try testing.expect(cqe_socket.res == 0); + + // create socket in registered file descriptor at index 1 (last param) + _ = try ring.socket_direct(0, linux.AF.INET, posix.SOCK.STREAM, 0, 0, 1); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + cqe_socket = try ring.copy_cqe(); + try testing.expectEqual(posix.E.SUCCESS, cqe_socket.err()); + try testing.expect(cqe_socket.res == 0); // res is 0 when index is specified + + // create socket in kernel chosen file descriptor index (_alloc version) + // completion res has index from registered files + _ = try ring.socket_direct_alloc(0, linux.AF.INET, posix.SOCK.STREAM, 0, 0); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + cqe_socket = try ring.copy_cqe(); + try testing.expectEqual(posix.E.SUCCESS, cqe_socket.err()); + try testing.expect(cqe_socket.res == 2); // returns registered file index + + // use sockets from registered_fds in connect operation + var address: linux.sockaddr.in = .{ + .port = 0, + .addr = @bitCast([4]u8{ 127, 0, 0, 1 }), + }; + const listener_socket = try createListenerSocket(&address); + defer posix.close(listener_socket); + const accept_userdata: u64 = 0xaaaaaaaa; + const connect_userdata: u64 = 0xbbbbbbbb; + const close_userdata: u64 = 0xcccccccc; + for (registered_fds, 0..) |_, fd_index| { + // prepare accept + _ = try ring.accept(accept_userdata, listener_socket, null, null, 0); + // prepare connect with fixed socket + const connect_sqe = try ring.connect(connect_userdata, @intCast(fd_index), addrAny(&address), @sizeOf(linux.sockaddr.in)); + connect_sqe.flags |= linux.IOSQE_FIXED_FILE; // fd is fixed file index + // submit both + try testing.expectEqual(@as(u32, 2), try ring.submit()); + // get completions + var cqe_connect = try ring.copy_cqe(); + var cqe_accept = try ring.copy_cqe(); + // ignore order + if (cqe_connect.user_data == accept_userdata and cqe_accept.user_data == connect_userdata) { + const a = cqe_accept; + const b = cqe_connect; + cqe_accept = b; + cqe_connect = a; + } + // test connect completion + try testing.expect(cqe_connect.user_data == connect_userdata); + try testing.expectEqual(posix.E.SUCCESS, cqe_connect.err()); + // test accept completion + try testing.expect(cqe_accept.user_data == accept_userdata); + try testing.expectEqual(posix.E.SUCCESS, cqe_accept.err()); + + // submit and test close_direct + _ = try ring.close_direct(close_userdata, @intCast(fd_index)); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + var cqe_close = try ring.copy_cqe(); + try testing.expect(cqe_close.user_data == close_userdata); + try testing.expectEqual(posix.E.SUCCESS, cqe_close.err()); + } + + try ring.unregister_files(); +} + +test "openat_direct/close_direct" { + try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 }); + + var ring = IoUring.init(2, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + var registered_fds = [_]linux.fd_t{-1} ** 3; + try ring.register_files(registered_fds[0..]); + + var tmp = std.testing.tmpDir(.{}); + defer tmp.cleanup(); + const path = "test_io_uring_close_direct"; + const flags: linux.O = .{ .ACCMODE = .RDWR, .CREAT = true }; + const mode: posix.mode_t = 0o666; + const user_data: u64 = 0; + + // use registered file at index 0 (last param) + _ = try ring.openat_direct(user_data, tmp.dir.handle, path, flags, mode, 0); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + var cqe = try ring.copy_cqe(); + try testing.expectEqual(posix.E.SUCCESS, cqe.err()); + try testing.expect(cqe.res == 0); + + // use registered file at index 1 + _ = try ring.openat_direct(user_data, tmp.dir.handle, path, flags, mode, 1); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + cqe = try ring.copy_cqe(); + try testing.expectEqual(posix.E.SUCCESS, cqe.err()); + try testing.expect(cqe.res == 0); // res is 0 when we specify index + + // let kernel choose registered file index + _ = try ring.openat_direct(user_data, tmp.dir.handle, path, flags, mode, linux.IORING_FILE_INDEX_ALLOC); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + cqe = try ring.copy_cqe(); + try testing.expectEqual(posix.E.SUCCESS, cqe.err()); + try testing.expect(cqe.res == 2); // chosen index is in res + + // close all open file descriptors + for (registered_fds, 0..) |_, fd_index| { + _ = try ring.close_direct(user_data, @intCast(fd_index)); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + var cqe_close = try ring.copy_cqe(); + try testing.expectEqual(posix.E.SUCCESS, cqe_close.err()); + } + try ring.unregister_files(); +} + +test "ring mapped buffers recv" { + const io = testing.io; + _ = io; + + var ring = IoUring.init(16, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + // init buffer group + const group_id: u16 = 1; // buffers group id + const buffers_count: u16 = 2; // number of buffers in buffer group + const buffer_size: usize = 4; // size of each buffer in group + var buf_grp = BufferGroup.init( + &ring, + testing.allocator, + group_id, + buffer_size, + buffers_count, + ) catch |err| switch (err) { + // kernel older than 5.19 + error.ArgumentsInvalid => return error.SkipZigTest, + else => return err, + }; + defer buf_grp.deinit(testing.allocator); + + // create client/server fds + const fds = try createSocketTestHarness(&ring); + defer fds.close(); + + // for random user_data in sqe/cqe + var Rnd = std.Random.DefaultPrng.init(std.testing.random_seed); + var rnd = Rnd.random(); + + var round: usize = 4; // repeat send/recv cycle round times + while (round > 0) : (round -= 1) { + // client sends data + const data = [_]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe }; + { + const user_data = rnd.int(u64); + _ = try ring.send(user_data, fds.client, data[0..], 0); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + const cqe_send = try ring.copy_cqe(); + if (cqe_send.err() == .INVAL) return error.SkipZigTest; + try testing.expectEqual(linux.io_uring_cqe{ .user_data = user_data, .res = data.len, .flags = 0 }, cqe_send); + } + var pos: usize = 0; + + // read first chunk + const cqe1 = try buf_grp_recv_submit_get_cqe(&ring, &buf_grp, fds.server, rnd.int(u64)); + var buf = try buf_grp.get(cqe1); + try testing.expectEqualSlices(u8, data[pos..][0..buf.len], buf); + pos += buf.len; + // second chunk + const cqe2 = try buf_grp_recv_submit_get_cqe(&ring, &buf_grp, fds.server, rnd.int(u64)); + buf = try buf_grp.get(cqe2); + try testing.expectEqualSlices(u8, data[pos..][0..buf.len], buf); + pos += buf.len; + + // both buffers provided to the kernel are used so we get error + // 'no more buffers', until we put buffers to the kernel + { + const user_data = rnd.int(u64); + _ = try buf_grp.recv(user_data, fds.server, 0); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + const cqe = try ring.copy_cqe(); + try testing.expectEqual(user_data, cqe.user_data); + try testing.expect(cqe.res < 0); // fail + try testing.expectEqual(posix.E.NOBUFS, cqe.err()); + try testing.expect(cqe.flags & linux.IORING_CQE_F_BUFFER == 0); // IORING_CQE_F_BUFFER flags is set on success only + try testing.expectError(error.NoBufferSelected, cqe.buffer_id()); + } + + // put buffers back to the kernel + try buf_grp.put(cqe1); + try buf_grp.put(cqe2); + + // read remaining data + while (pos < data.len) { + const cqe = try buf_grp_recv_submit_get_cqe(&ring, &buf_grp, fds.server, rnd.int(u64)); + buf = try buf_grp.get(cqe); + try testing.expectEqualSlices(u8, data[pos..][0..buf.len], buf); + pos += buf.len; + try buf_grp.put(cqe); + } + } +} + +test "ring mapped buffers multishot recv" { + const io = testing.io; + _ = io; + + var ring = IoUring.init(16, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + // init buffer group + const group_id: u16 = 1; // buffers group id + const buffers_count: u16 = 2; // number of buffers in buffer group + const buffer_size: usize = 4; // size of each buffer in group + var buf_grp = BufferGroup.init( + &ring, + testing.allocator, + group_id, + buffer_size, + buffers_count, + ) catch |err| switch (err) { + // kernel older than 5.19 + error.ArgumentsInvalid => return error.SkipZigTest, + else => return err, + }; + defer buf_grp.deinit(testing.allocator); + + // create client/server fds + const fds = try createSocketTestHarness(&ring); + defer fds.close(); + + // for random user_data in sqe/cqe + var Rnd = std.Random.DefaultPrng.init(std.testing.random_seed); + var rnd = Rnd.random(); + + var round: usize = 4; // repeat send/recv cycle round times + while (round > 0) : (round -= 1) { + // client sends data + const data = [_]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf }; + { + const user_data = rnd.int(u64); + _ = try ring.send(user_data, fds.client, data[0..], 0); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + const cqe_send = try ring.copy_cqe(); + if (cqe_send.err() == .INVAL) return error.SkipZigTest; + try testing.expectEqual(linux.io_uring_cqe{ .user_data = user_data, .res = data.len, .flags = 0 }, cqe_send); + } + + // start multishot recv + var recv_user_data = rnd.int(u64); + _ = try buf_grp.recv_multishot(recv_user_data, fds.server, 0); + try testing.expectEqual(@as(u32, 1), try ring.submit()); // submit + + // server reads data into provided buffers + // there are 2 buffers of size 4, so each read gets only chunk of data + // we read four chunks of 4, 4, 4, 4 bytes each + var chunk: []const u8 = data[0..buffer_size]; // first chunk + const cqe1 = try expect_buf_grp_cqe(&ring, &buf_grp, recv_user_data, chunk); + try testing.expect(cqe1.flags & linux.IORING_CQE_F_MORE > 0); + + chunk = data[buffer_size .. buffer_size * 2]; // second chunk + const cqe2 = try expect_buf_grp_cqe(&ring, &buf_grp, recv_user_data, chunk); + try testing.expect(cqe2.flags & linux.IORING_CQE_F_MORE > 0); + + // both buffers provided to the kernel are used so we get error + // 'no more buffers', until we put buffers to the kernel + { + const cqe = try ring.copy_cqe(); + try testing.expectEqual(recv_user_data, cqe.user_data); + try testing.expect(cqe.res < 0); // fail + try testing.expectEqual(posix.E.NOBUFS, cqe.err()); + try testing.expect(cqe.flags & linux.IORING_CQE_F_BUFFER == 0); // IORING_CQE_F_BUFFER flags is set on success only + // has more is not set + // indicates that multishot is finished + try testing.expect(cqe.flags & linux.IORING_CQE_F_MORE == 0); + try testing.expectError(error.NoBufferSelected, cqe.buffer_id()); + } + + // put buffers back to the kernel + try buf_grp.put(cqe1); + try buf_grp.put(cqe2); + + // restart multishot + recv_user_data = rnd.int(u64); + _ = try buf_grp.recv_multishot(recv_user_data, fds.server, 0); + try testing.expectEqual(@as(u32, 1), try ring.submit()); // submit + + chunk = data[buffer_size * 2 .. buffer_size * 3]; // third chunk + const cqe3 = try expect_buf_grp_cqe(&ring, &buf_grp, recv_user_data, chunk); + try testing.expect(cqe3.flags & linux.IORING_CQE_F_MORE > 0); + try buf_grp.put(cqe3); + + chunk = data[buffer_size * 3 ..]; // last chunk + const cqe4 = try expect_buf_grp_cqe(&ring, &buf_grp, recv_user_data, chunk); + try testing.expect(cqe4.flags & linux.IORING_CQE_F_MORE > 0); + try buf_grp.put(cqe4); + + // cancel pending multishot recv operation + { + const cancel_user_data = rnd.int(u64); + _ = try ring.cancel(cancel_user_data, recv_user_data, 0); + try testing.expectEqual(@as(u32, 1), try ring.submit()); + + // expect completion of cancel operation and completion of recv operation + var cqe_cancel = try ring.copy_cqe(); + if (cqe_cancel.err() == .INVAL) return error.SkipZigTest; + var cqe_recv = try ring.copy_cqe(); + if (cqe_recv.err() == .INVAL) return error.SkipZigTest; + + // don't depend on order of completions + if (cqe_cancel.user_data == recv_user_data and cqe_recv.user_data == cancel_user_data) { + const a = cqe_cancel; + const b = cqe_recv; + cqe_cancel = b; + cqe_recv = a; + } + + // Note on different kernel results: + // on older kernel (tested with v6.0.16, v6.1.57, v6.2.12, v6.4.16) + // cqe_cancel.err() == .NOENT + // cqe_recv.err() == .NOBUFS + // on kernel (tested with v6.5.0, v6.5.7) + // cqe_cancel.err() == .SUCCESS + // cqe_recv.err() == .CANCELED + // Upstream reference: https://github.com/axboe/liburing/issues/984 + + // cancel operation is success (or NOENT on older kernels) + try testing.expectEqual(cancel_user_data, cqe_cancel.user_data); + try testing.expect(cqe_cancel.err() == .NOENT or cqe_cancel.err() == .SUCCESS); + + // recv operation is failed with err CANCELED (or NOBUFS on older kernels) + try testing.expectEqual(recv_user_data, cqe_recv.user_data); + try testing.expect(cqe_recv.res < 0); + try testing.expect(cqe_recv.err() == .NOBUFS or cqe_recv.err() == .CANCELED); + try testing.expect(cqe_recv.flags & linux.IORING_CQE_F_MORE == 0); + } + } +} + +test "copy_cqes with wrapping sq.cqes buffer" { + var ring = IoUring.init(2, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + try testing.expectEqual(2, ring.sq.sqes.len); + try testing.expectEqual(4, ring.cq.cqes.len); + + // submit 2 entries, receive 2 completions + var cqes: [8]linux.io_uring_cqe = undefined; + { + for (0..2) |_| { + const sqe = try ring.get_sqe(); + sqe.prep_timeout(&.{ .sec = 0, .nsec = 10000 }, 0, 0); + try testing.expect(try ring.submit() == 1); + } + var cqe_count: u32 = 0; + while (cqe_count < 2) { + cqe_count += try ring.copy_cqes(&cqes, 2 - cqe_count); + } + } + + try testing.expectEqual(2, ring.cq.head.*); + + // sq.sqes len is 4, starting at position 2 + // every 4 entries submit wraps completion buffer + // we are reading ring.cq.cqes at indexes 2,3,0,1 + for (1..1024) |i| { + for (0..4) |_| { + const sqe = try ring.get_sqe(); + sqe.prep_timeout(&.{ .sec = 0, .nsec = 10000 }, 0, 0); + try testing.expect(try ring.submit() == 1); + } + var cqe_count: u32 = 0; + while (cqe_count < 4) { + cqe_count += try ring.copy_cqes(&cqes, 4 - cqe_count); + } + try testing.expectEqual(4, cqe_count); + try testing.expectEqual(2 + 4 * i, ring.cq.head.*); + } +} + +test "bind/listen/connect" { + if (builtin.cpu.arch == .s390x) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/25956 + + var ring = IoUring.init(4, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + const probe = ring.get_probe() catch return error.SkipZigTest; + // LISTEN is higher required operation + if (!probe.is_supported(.LISTEN)) return error.SkipZigTest; + + var addr: linux.sockaddr.in = .{ + .port = 0, + .addr = @bitCast([4]u8{ 127, 0, 0, 1 }), + }; + const proto: u32 = if (addr.family == linux.AF.UNIX) 0 else linux.IPPROTO.TCP; + + const listen_fd = brk: { + // Create socket + _ = try ring.socket(1, addr.family, linux.SOCK.STREAM | linux.SOCK.CLOEXEC, proto, 0); + try testing.expectEqual(1, try ring.submit()); + var cqe = try ring.copy_cqe(); + try testing.expectEqual(1, cqe.user_data); + try testing.expectEqual(posix.E.SUCCESS, cqe.err()); + const listen_fd: linux.fd_t = @intCast(cqe.res); + try testing.expect(listen_fd > 2); + + // Prepare: set socket option * 2, bind, listen + var optval: u32 = 1; + (try ring.setsockopt(2, listen_fd, linux.SOL.SOCKET, linux.SO.REUSEADDR, mem.asBytes(&optval))).link_next(); + (try ring.setsockopt(3, listen_fd, linux.SOL.SOCKET, linux.SO.REUSEPORT, mem.asBytes(&optval))).link_next(); + (try ring.bind(4, listen_fd, addrAny(&addr), @sizeOf(linux.sockaddr.in), 0)).link_next(); + _ = try ring.listen(5, listen_fd, 1, 0); + // Submit 4 operations + try testing.expectEqual(4, try ring.submit()); + // Expect all to succeed + for (2..6) |user_data| { + cqe = try ring.copy_cqe(); + try testing.expectEqual(user_data, cqe.user_data); + try testing.expectEqual(posix.E.SUCCESS, cqe.err()); + } + + // Check that socket option is set + optval = 0; + _ = try ring.getsockopt(5, listen_fd, linux.SOL.SOCKET, linux.SO.REUSEADDR, mem.asBytes(&optval)); + try testing.expectEqual(1, try ring.submit()); + cqe = try ring.copy_cqe(); + try testing.expectEqual(5, cqe.user_data); + try testing.expectEqual(posix.E.SUCCESS, cqe.err()); + try testing.expectEqual(1, optval); + + // Read system assigned port into addr + var addr_len: posix.socklen_t = @sizeOf(linux.sockaddr.in); + try getsockname(listen_fd, addrAny(&addr), &addr_len); + + break :brk listen_fd; + }; + + const connect_fd = brk: { + // Create connect socket + _ = try ring.socket(6, addr.family, linux.SOCK.STREAM | linux.SOCK.CLOEXEC, proto, 0); + try testing.expectEqual(1, try ring.submit()); + const cqe = try ring.copy_cqe(); + try testing.expectEqual(6, cqe.user_data); + try testing.expectEqual(posix.E.SUCCESS, cqe.err()); + // Get connect socket fd + const connect_fd: linux.fd_t = @intCast(cqe.res); + try testing.expect(connect_fd > 2 and connect_fd != listen_fd); + break :brk connect_fd; + }; + + // Prepare accept/connect operations + _ = try ring.accept(7, listen_fd, null, null, 0); + _ = try ring.connect(8, connect_fd, addrAny(&addr), @sizeOf(linux.sockaddr.in)); + try testing.expectEqual(2, try ring.submit()); + // Get listener accepted socket + var accept_fd: posix.socket_t = 0; + for (0..2) |_| { + const cqe = try ring.copy_cqe(); + try testing.expectEqual(posix.E.SUCCESS, cqe.err()); + if (cqe.user_data == 7) { + accept_fd = @intCast(cqe.res); + } else { + try testing.expectEqual(8, cqe.user_data); + } + } + try testing.expect(accept_fd > 2 and accept_fd != listen_fd and accept_fd != connect_fd); + + // Communicate + try testSendRecv(&ring, connect_fd, accept_fd); + try testSendRecv(&ring, accept_fd, connect_fd); + + // Shutdown and close all sockets + for ([_]posix.socket_t{ connect_fd, accept_fd, listen_fd }) |fd| { + (try ring.shutdown(9, fd, posix.SHUT.RDWR)).link_next(); + _ = try ring.close(10, fd); + try testing.expectEqual(2, try ring.submit()); + for (0..2) |i| { + const cqe = try ring.copy_cqe(); + try testing.expectEqual(posix.E.SUCCESS, cqe.err()); + try testing.expectEqual(9 + i, cqe.user_data); + } + } +} + +// Prepare, submit recv and get cqe using buffer group. +fn buf_grp_recv_submit_get_cqe( + ring: *IoUring, + buf_grp: *BufferGroup, + fd: linux.fd_t, + user_data: u64, +) !linux.io_uring_cqe { + // prepare and submit recv + const sqe = try buf_grp.recv(user_data, fd, 0); + try testing.expect(sqe.flags & linux.IOSQE_BUFFER_SELECT == linux.IOSQE_BUFFER_SELECT); + try testing.expect(sqe.buf_index == buf_grp.group_id); + try testing.expectEqual(@as(u32, 1), try ring.submit()); // submit + // get cqe, expect success + const cqe = try ring.copy_cqe(); + try testing.expectEqual(user_data, cqe.user_data); + try testing.expect(cqe.res >= 0); // success + try testing.expectEqual(posix.E.SUCCESS, cqe.err()); + try testing.expect(cqe.flags & linux.IORING_CQE_F_BUFFER == linux.IORING_CQE_F_BUFFER); // IORING_CQE_F_BUFFER flag is set + + return cqe; +} + +fn expect_buf_grp_cqe( + ring: *IoUring, + buf_grp: *BufferGroup, + user_data: u64, + expected: []const u8, +) !linux.io_uring_cqe { + // get cqe + const cqe = try ring.copy_cqe(); + try testing.expectEqual(user_data, cqe.user_data); + try testing.expect(cqe.res >= 0); // success + try testing.expect(cqe.flags & linux.IORING_CQE_F_BUFFER == linux.IORING_CQE_F_BUFFER); // IORING_CQE_F_BUFFER flag is set + try testing.expectEqual(expected.len, @as(usize, @intCast(cqe.res))); + try testing.expectEqual(posix.E.SUCCESS, cqe.err()); + + // get buffer from pool + const buffer_id = try cqe.buffer_id(); + const len = @as(usize, @intCast(cqe.res)); + const buf = buf_grp.get_by_id(buffer_id)[0..len]; + try testing.expectEqualSlices(u8, expected, buf); + + return cqe; +} + +fn testSendRecv(ring: *IoUring, send_fd: posix.socket_t, recv_fd: posix.socket_t) !void { + const buffer_send = "0123456789abcdf" ** 10; + var buffer_recv: [buffer_send.len * 2]u8 = undefined; + + // 2 sends + _ = try ring.send(1, send_fd, buffer_send, linux.MSG.WAITALL); + _ = try ring.send(2, send_fd, buffer_send, linux.MSG.WAITALL); + try testing.expectEqual(2, try ring.submit()); + for (0..2) |i| { + const cqe = try ring.copy_cqe(); + try testing.expectEqual(1 + i, cqe.user_data); + try testing.expectEqual(posix.E.SUCCESS, cqe.err()); + try testing.expectEqual(buffer_send.len, @as(usize, @intCast(cqe.res))); + } + + // receive + var recv_len: usize = 0; + while (recv_len < buffer_send.len * 2) { + _ = try ring.recv(3, recv_fd, .{ .buffer = buffer_recv[recv_len..] }, 0); + try testing.expectEqual(1, try ring.submit()); + const cqe = try ring.copy_cqe(); + try testing.expectEqual(3, cqe.user_data); + try testing.expectEqual(posix.E.SUCCESS, cqe.err()); + recv_len += @intCast(cqe.res); + } + + // inspect recv buffer + try testing.expectEqualSlices(u8, buffer_send, buffer_recv[0..buffer_send.len]); + try testing.expectEqualSlices(u8, buffer_send, buffer_recv[buffer_send.len..]); +} + +/// Used for testing server/client interactions. +pub const SocketTestHarness = struct { + listener: posix.socket_t, + server: posix.socket_t, + client: posix.socket_t, + + pub fn close(self: SocketTestHarness) void { + posix.close(self.client); + posix.close(self.listener); + } +}; + +pub fn createSocketTestHarness(ring: *IoUring) !SocketTestHarness { + // Create a TCP server socket + var address: linux.sockaddr.in = .{ + .port = 0, + .addr = @bitCast([4]u8{ 127, 0, 0, 1 }), + }; + const listener_socket = try createListenerSocket(&address); + errdefer posix.close(listener_socket); + + // Submit 1 accept + var accept_addr: posix.sockaddr = undefined; + var accept_addr_len: posix.socklen_t = @sizeOf(@TypeOf(accept_addr)); + _ = try ring.accept(0xaaaaaaaa, listener_socket, &accept_addr, &accept_addr_len, 0); + + // Create a TCP client socket + const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); + errdefer posix.close(client); + _ = try ring.connect(0xcccccccc, client, addrAny(&address), @sizeOf(linux.sockaddr.in)); + + try testing.expectEqual(@as(u32, 2), try ring.submit()); + + var cqe_accept = try ring.copy_cqe(); + if (cqe_accept.err() == .INVAL) return error.SkipZigTest; + var cqe_connect = try ring.copy_cqe(); + if (cqe_connect.err() == .INVAL) return error.SkipZigTest; + + // The accept/connect CQEs may arrive in any order, the connect CQE will sometimes come first: + if (cqe_accept.user_data == 0xcccccccc and cqe_connect.user_data == 0xaaaaaaaa) { + const a = cqe_accept; + const b = cqe_connect; + cqe_accept = b; + cqe_connect = a; + } + + try testing.expectEqual(@as(u64, 0xaaaaaaaa), cqe_accept.user_data); + if (cqe_accept.res <= 0) std.debug.print("\ncqe_accept.res={}\n", .{cqe_accept.res}); + try testing.expect(cqe_accept.res > 0); + try testing.expectEqual(@as(u32, 0), cqe_accept.flags); + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0xcccccccc, + .res = 0, + .flags = 0, + }, cqe_connect); + + // All good + + return SocketTestHarness{ + .listener = listener_socket, + .server = cqe_accept.res, + .client = client, + }; +} + +fn createListenerSocket(address: *linux.sockaddr.in) !posix.socket_t { + const kernel_backlog = 1; + const listener_socket = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); + errdefer posix.close(listener_socket); + + try posix.setsockopt(listener_socket, posix.SOL.SOCKET, posix.SO.REUSEADDR, &mem.toBytes(@as(c_int, 1))); + try bind(listener_socket, addrAny(address), @sizeOf(linux.sockaddr.in)); + try listen(listener_socket, kernel_backlog); + + // set address to the OS-chosen IP/port. + var slen: posix.socklen_t = @sizeOf(linux.sockaddr.in); + try getsockname(listener_socket, addrAny(address), &slen); + + return listener_socket; +} + +/// For use in tests. Returns SkipZigTest if kernel version is less than required. +inline fn skipKernelLessThan(required: std.SemanticVersion) !void { + var uts: linux.utsname = undefined; + const res = linux.uname(&uts); + switch (linux.errno(res)) { + .SUCCESS => {}, + else => |errno| return posix.unexpectedErrno(errno), + } + + const release = mem.sliceTo(&uts.release, 0); + // Strips potential extra, as kernel version might not be semver compliant, example "6.8.9-300.fc40.x86_64" + const extra_index = std.mem.indexOfAny(u8, release, "-+"); + const stripped = release[0..(extra_index orelse release.len)]; + // Make sure the input don't rely on the extra we just stripped + try testing.expect(required.pre == null and required.build == null); + + var current = try std.SemanticVersion.parse(stripped); + current.pre = null; // don't check pre field + if (required.order(current) == .gt) return error.SkipZigTest; +} + +fn addrAny(addr: *linux.sockaddr.in) *linux.sockaddr { + return @ptrCast(addr); +} + +fn socket(domain: u32, socket_type: u32, protocol: u32) !posix.socket_t { + const rc = posix.system.socket(domain, socket_type, protocol); + switch (posix.errno(rc)) { + .SUCCESS => return @intCast(rc), + else => return error.SocketCreationFailure, + } +} + +fn bind(sock: posix.socket_t, addr: *const posix.sockaddr, len: posix.socklen_t) !void { + switch (posix.errno(posix.system.bind(sock, addr, len))) { + .SUCCESS => return, + else => return error.BindFailure, + } +} + +fn listen(sock: posix.socket_t, backlog: u31) !void { + switch (posix.errno(posix.system.listen(sock, backlog))) { + .SUCCESS => return, + else => return error.ListenFailure, + } +} + +fn getsockname(sock: posix.socket_t, addr: *posix.sockaddr, addrlen: *posix.socklen_t) !void { + switch (posix.errno(posix.system.getsockname(sock, addr, addrlen))) { + .SUCCESS => return, + else => return error.GetSockNameFailure, + } +} + +fn send(sockfd: posix.socket_t, buf: []const u8, flags: u32) !usize { + const rc = posix.system.sendto(sockfd, buf.ptr, buf.len, flags, null, 0); + switch (posix.errno(rc)) { + .SUCCESS => return @intCast(rc), + else => return error.SendFailed, + } +} diff --git a/lib/std/os/linux/aarch64.zig b/lib/std/os/linux/aarch64.zig index 4977593ef5a9..ddf1a61a253e 100644 --- a/lib/std/os/linux/aarch64.zig +++ b/lib/std/os/linux/aarch64.zig @@ -143,43 +143,4 @@ pub const VDSO = struct { pub const CGT_VER = "LINUX_2.6.39"; }; -pub const blksize_t = i32; -pub const nlink_t = u32; pub const time_t = i64; -pub const mode_t = u32; -pub const off_t = i64; -pub const ino_t = u64; -pub const dev_t = u64; -pub const blkcnt_t = i64; - -// The `stat` definition used by the Linux kernel. -pub const Stat = extern struct { - dev: dev_t, - ino: ino_t, - mode: mode_t, - nlink: nlink_t, - uid: std.os.linux.uid_t, - gid: std.os.linux.gid_t, - rdev: dev_t, - __pad: u64, - size: off_t, - blksize: blksize_t, - __pad2: i32, - blocks: blkcnt_t, - atim: std.os.linux.timespec, - mtim: std.os.linux.timespec, - ctim: std.os.linux.timespec, - __unused: [2]u32, - - pub fn atime(self: @This()) std.os.linux.timespec { - return self.atim; - } - - pub fn mtime(self: @This()) std.os.linux.timespec { - return self.mtim; - } - - pub fn ctime(self: @This()) std.os.linux.timespec { - return self.ctim; - } -}; diff --git a/lib/std/os/linux/arm.zig b/lib/std/os/linux/arm.zig index 0a5b25f9f078..0bcdaaf31931 100644 --- a/lib/std/os/linux/arm.zig +++ b/lib/std/os/linux/arm.zig @@ -179,43 +179,4 @@ pub const HWCAP = struct { pub const EVTSTRM = 1 << 21; }; -pub const blksize_t = i32; -pub const nlink_t = u32; pub const time_t = i32; -pub const mode_t = u32; -pub const off_t = i64; -pub const ino_t = u64; -pub const dev_t = u64; -pub const blkcnt_t = i64; - -// The `stat` definition used by the Linux kernel. -pub const Stat = extern struct { - dev: dev_t, - __dev_padding: u32, - __ino_truncated: u32, - mode: mode_t, - nlink: nlink_t, - uid: std.os.linux.uid_t, - gid: std.os.linux.gid_t, - rdev: dev_t, - __rdev_padding: u32, - size: off_t, - blksize: blksize_t, - blocks: blkcnt_t, - atim: std.os.linux.timespec, - mtim: std.os.linux.timespec, - ctim: std.os.linux.timespec, - ino: ino_t, - - pub fn atime(self: @This()) std.os.linux.timespec { - return self.atim; - } - - pub fn mtime(self: @This()) std.os.linux.timespec { - return self.mtim; - } - - pub fn ctime(self: @This()) std.os.linux.timespec { - return self.ctim; - } -}; diff --git a/lib/std/os/linux/hexagon.zig b/lib/std/os/linux/hexagon.zig index d3b4149d65dd..ff5331467d15 100644 --- a/lib/std/os/linux/hexagon.zig +++ b/lib/std/os/linux/hexagon.zig @@ -119,45 +119,6 @@ pub fn clone() callconv(.naked) u32 { ); } -pub const blksize_t = i32; -pub const nlink_t = u32; pub const time_t = i64; -pub const mode_t = u32; -pub const off_t = i64; -pub const ino_t = u64; -pub const dev_t = u64; -pub const blkcnt_t = i64; - -// The `stat` definition used by the Linux kernel. -pub const Stat = extern struct { - dev: dev_t, - ino: ino_t, - mode: mode_t, - nlink: nlink_t, - uid: std.os.linux.uid_t, - gid: std.os.linux.gid_t, - rdev: dev_t, - __pad: u32, - size: off_t, - blksize: blksize_t, - __pad2: i32, - blocks: blkcnt_t, - atim: std.os.linux.timespec, - mtim: std.os.linux.timespec, - ctim: std.os.linux.timespec, - __unused: [2]u32, - - pub fn atime(self: @This()) std.os.linux.timespec { - return self.atim; - } - - pub fn mtime(self: @This()) std.os.linux.timespec { - return self.mtim; - } - - pub fn ctime(self: @This()) std.os.linux.timespec { - return self.ctim; - } -}; pub const VDSO = void; diff --git a/lib/std/os/linux/io_uring_sqe.zig b/lib/std/os/linux/io_uring_sqe.zig index 5658206a66a8..808276170a22 100644 --- a/lib/std/os/linux/io_uring_sqe.zig +++ b/lib/std/os/linux/io_uring_sqe.zig @@ -420,10 +420,10 @@ pub const io_uring_sqe = extern struct { fd: linux.fd_t, path: [*:0]const u8, flags: u32, - mask: u32, + mask: linux.STATX, buf: *linux.Statx, ) void { - sqe.prep_rw(.STATX, fd, @intFromPtr(path), mask, @intFromPtr(buf)); + sqe.prep_rw(.STATX, fd, @intFromPtr(path), @as(u32, @bitCast(mask)), @intFromPtr(buf)); sqe.rw_flags = flags; } diff --git a/lib/std/os/linux/loongarch64.zig b/lib/std/os/linux/loongarch64.zig index 41450c997670..8e7677f276ff 100644 --- a/lib/std/os/linux/loongarch64.zig +++ b/lib/std/os/linux/loongarch64.zig @@ -125,46 +125,7 @@ pub fn clone() callconv(.naked) u64 { ); } -pub const blksize_t = i32; -pub const nlink_t = u32; pub const time_t = i64; -pub const mode_t = u32; -pub const off_t = i64; -pub const ino_t = u64; -pub const dev_t = u32; -pub const blkcnt_t = i64; - -// The `stat` definition used by the Linux kernel. -pub const Stat = extern struct { - dev: dev_t, - ino: ino_t, - mode: mode_t, - nlink: nlink_t, - uid: std.os.linux.uid_t, - gid: std.os.linux.gid_t, - rdev: dev_t, - _pad1: u64, - size: off_t, - blksize: blksize_t, - _pad2: i32, - blocks: blkcnt_t, - atim: std.os.linux.timespec, - mtim: std.os.linux.timespec, - ctim: std.os.linux.timespec, - _pad3: [2]u32, - - pub fn atime(self: @This()) std.os.linux.timespec { - return self.atim; - } - - pub fn mtime(self: @This()) std.os.linux.timespec { - return self.mtim; - } - - pub fn ctime(self: @This()) std.os.linux.timespec { - return self.ctim; - } -}; pub const VDSO = struct { pub const CGT_SYM = "__vdso_clock_gettime"; diff --git a/lib/std/os/linux/m68k.zig b/lib/std/os/linux/m68k.zig index 29d9adf1f7b0..2c5f13aa6321 100644 --- a/lib/std/os/linux/m68k.zig +++ b/lib/std/os/linux/m68k.zig @@ -142,45 +142,7 @@ pub fn restore_rt() callconv(.naked) noreturn { ); } -pub const blksize_t = i32; -pub const nlink_t = u32; pub const time_t = i32; -pub const mode_t = u32; -pub const off_t = i64; -pub const ino_t = u64; -pub const dev_t = u64; -pub const blkcnt_t = i64; - -pub const Stat = extern struct { - dev: dev_t, - __pad: i16, - __ino_truncated: i32, - mode: mode_t, - nlink: nlink_t, - uid: std.os.linux.uid_t, - gid: std.os.linux.gid_t, - rdev: dev_t, - __pad2: i16, - size: off_t, - blksize: blksize_t, - blocks: blkcnt_t, - atim: std.os.linux.timespec, - mtim: std.os.linux.timespec, - ctim: std.os.linux.timespec, - ino: ino_t, - - pub fn atime(self: @This()) std.os.linux.timespec { - return self.atim; - } - - pub fn mtime(self: @This()) std.os.linux.timespec { - return self.mtim; - } - - pub fn ctime(self: @This()) std.os.linux.timespec { - return self.ctim; - } -}; // No VDSO used as of glibc 112a0ae18b831bf31f44d81b82666980312511d6. pub const VDSO = void; diff --git a/lib/std/os/linux/mips.zig b/lib/std/os/linux/mips.zig index 3bd7790bd527..bcca7d1ef205 100644 --- a/lib/std/os/linux/mips.zig +++ b/lib/std/os/linux/mips.zig @@ -230,43 +230,4 @@ pub const VDSO = struct { pub const CGT_VER = "LINUX_2.6"; }; -pub const blksize_t = u32; -pub const nlink_t = u32; pub const time_t = i32; -pub const mode_t = u32; -pub const off_t = i64; -pub const ino_t = u64; -pub const dev_t = u64; -pub const blkcnt_t = i64; - -// The `stat64` definition used by the Linux kernel. -pub const Stat = extern struct { - dev: dev_t, - __pad0: [2]u32, // -1 because our dev_t is u64 (kernel dev_t is really u32). - ino: ino_t, - mode: mode_t, - nlink: nlink_t, - uid: std.os.linux.uid_t, - gid: std.os.linux.gid_t, - rdev: dev_t, - __pad1: [2]u32, - size: off_t, - atim: std.os.linux.timespec, - mtim: std.os.linux.timespec, - ctim: std.os.linux.timespec, - blksize: blksize_t, - __pad3: u32, - blocks: blkcnt_t, - - pub fn atime(self: @This()) std.os.linux.timespec { - return self.atim; - } - - pub fn mtime(self: @This()) std.os.linux.timespec { - return self.mtim; - } - - pub fn ctime(self: @This()) std.os.linux.timespec { - return self.ctim; - } -}; diff --git a/lib/std/os/linux/mips64.zig b/lib/std/os/linux/mips64.zig index 82ad6184f1af..ec5681b5138c 100644 --- a/lib/std/os/linux/mips64.zig +++ b/lib/std/os/linux/mips64.zig @@ -184,55 +184,4 @@ pub const VDSO = struct { pub const CGT_VER = "LINUX_2.6"; }; -pub const blksize_t = u32; -pub const nlink_t = u32; pub const time_t = i32; -pub const mode_t = u32; -pub const off_t = i64; -pub const ino_t = u64; -pub const dev_t = u64; -pub const blkcnt_t = i64; - -// The `stat` definition used by the Linux kernel. -pub const Stat = extern struct { - dev: dev_t, - __pad0: [2]u32, // -1 because our dev_t is u64 (kernel dev_t is really u32). - ino: ino_t, - mode: mode_t, - nlink: nlink_t, - uid: std.os.linux.uid_t, - gid: std.os.linux.gid_t, - rdev: dev_t, - __pad1: [2]u32, // -1 because our dev_t is u64 (kernel dev_t is really u32). - size: off_t, - atim: u32, - atim_nsec: u32, - mtim: u32, - mtim_nsec: u32, - ctim: u32, - ctim_nsec: u32, - blksize: blksize_t, - __pad3: u32, - blocks: blkcnt_t, - - pub fn atime(self: @This()) std.os.linux.timespec { - return .{ - .sec = self.atim, - .nsec = self.atim_nsec, - }; - } - - pub fn mtime(self: @This()) std.os.linux.timespec { - return .{ - .sec = self.mtim, - .nsec = self.mtim_nsec, - }; - } - - pub fn ctime(self: @This()) std.os.linux.timespec { - return .{ - .sec = self.ctim, - .nsec = self.ctim_nsec, - }; - } -}; diff --git a/lib/std/os/linux/mipsn32.zig b/lib/std/os/linux/mipsn32.zig index 584edf7c8019..4f7c7d60fdfe 100644 --- a/lib/std/os/linux/mipsn32.zig +++ b/lib/std/os/linux/mipsn32.zig @@ -184,55 +184,4 @@ pub const VDSO = struct { pub const CGT_VER = "LINUX_2.6"; }; -pub const blksize_t = u32; -pub const nlink_t = u32; pub const time_t = i32; -pub const mode_t = u32; -pub const off_t = i64; -pub const ino_t = u64; -pub const dev_t = u64; -pub const blkcnt_t = i64; - -// The `stat` definition used by the Linux kernel. -pub const Stat = extern struct { - dev: dev_t, - __pad0: [2]u32, // -1 because our dev_t is u64 (kernel dev_t is really u32). - ino: ino_t, - mode: mode_t, - nlink: nlink_t, - uid: std.os.linux.uid_t, - gid: std.os.linux.gid_t, - rdev: dev_t, - __pad1: [2]u32, // -1 because our dev_t is u64 (kernel dev_t is really u32). - size: off_t, - atim: u32, - atim_nsec: u32, - mtim: u32, - mtim_nsec: u32, - ctim: u32, - ctim_nsec: u32, - blksize: blksize_t, - __pad3: u32, - blocks: blkcnt_t, - - pub fn atime(self: @This()) std.os.linux.timespec { - return .{ - .sec = self.atim, - .nsec = self.atim_nsec, - }; - } - - pub fn mtime(self: @This()) std.os.linux.timespec { - return .{ - .sec = self.mtim, - .nsec = self.mtim_nsec, - }; - } - - pub fn ctime(self: @This()) std.os.linux.timespec { - return .{ - .sec = self.ctim, - .nsec = self.ctim_nsec, - }; - } -}; diff --git a/lib/std/os/linux/or1k.zig b/lib/std/os/linux/or1k.zig index 1054e52d1991..45352e4791ee 100644 --- a/lib/std/os/linux/or1k.zig +++ b/lib/std/os/linux/or1k.zig @@ -131,43 +131,4 @@ pub fn clone() callconv(.naked) u32 { pub const VDSO = void; -pub const blksize_t = u32; -pub const nlink_t = u32; pub const time_t = i32; -pub const mode_t = u32; -pub const off_t = i64; -pub const ino_t = u64; -pub const dev_t = u64; -pub const blkcnt_t = i64; - -// The `stat64` definition used by the Linux kernel. -pub const Stat = extern struct { - dev: dev_t, - ino: ino_t, - mode: mode_t, - nlink: nlink_t, - uid: std.os.linux.uid_t, - gid: std.os.linux.gid_t, - rdev: dev_t, - _pad0: [2]u32, - size: off_t, - blksize: blksize_t, - _pad1: u32, - blocks: blkcnt_t, - atim: std.os.linux.timespec, - mtim: std.os.linux.timespec, - ctim: std.os.linux.timespec, - _pad2: [2]u32, - - pub fn atime(self: @This()) std.os.linux.timespec { - return self.atim; - } - - pub fn mtime(self: @This()) std.os.linux.timespec { - return self.mtim; - } - - pub fn ctime(self: @This()) std.os.linux.timespec { - return self.ctim; - } -}; diff --git a/lib/std/os/linux/powerpc.zig b/lib/std/os/linux/powerpc.zig index d96a9d67f01d..78c6aadda741 100644 --- a/lib/std/os/linux/powerpc.zig +++ b/lib/std/os/linux/powerpc.zig @@ -269,42 +269,4 @@ pub const VDSO = struct { pub const CGT_VER = "LINUX_2.6.15"; }; -pub const blksize_t = i32; -pub const nlink_t = u32; pub const time_t = i32; -pub const mode_t = u32; -pub const off_t = i64; -pub const ino_t = u64; -pub const dev_t = u64; -pub const blkcnt_t = i64; - -// The `stat` definition used by the Linux kernel. -pub const Stat = extern struct { - dev: dev_t, - ino: ino_t, - mode: mode_t, - nlink: nlink_t, - uid: std.os.linux.uid_t, - gid: std.os.linux.gid_t, - rdev: dev_t, - __rdev_padding: i16, - size: off_t, - blksize: blksize_t, - blocks: blkcnt_t, - atim: std.os.linux.timespec, - mtim: std.os.linux.timespec, - ctim: std.os.linux.timespec, - __unused: [2]u32, - - pub fn atime(self: @This()) std.os.linux.timespec { - return self.atim; - } - - pub fn mtime(self: @This()) std.os.linux.timespec { - return self.mtim; - } - - pub fn ctime(self: @This()) std.os.linux.timespec { - return self.ctim; - } -}; diff --git a/lib/std/os/linux/powerpc64.zig b/lib/std/os/linux/powerpc64.zig index d1663feaa88e..f4375a4545b7 100644 --- a/lib/std/os/linux/powerpc64.zig +++ b/lib/std/os/linux/powerpc64.zig @@ -254,41 +254,4 @@ pub const VDSO = struct { pub const CGT_VER = "LINUX_2.6.15"; }; -pub const blksize_t = i64; -pub const nlink_t = u64; pub const time_t = i64; -pub const mode_t = u32; -pub const off_t = i64; -pub const ino_t = u64; -pub const dev_t = u64; -pub const blkcnt_t = i64; - -// The `stat` definition used by the Linux kernel. -pub const Stat = extern struct { - dev: dev_t, - ino: ino_t, - nlink: nlink_t, - mode: mode_t, - uid: std.os.linux.uid_t, - gid: std.os.linux.gid_t, - rdev: dev_t, - size: off_t, - blksize: blksize_t, - blocks: blkcnt_t, - atim: std.os.linux.timespec, - mtim: std.os.linux.timespec, - ctim: std.os.linux.timespec, - __unused: [3]u64, - - pub fn atime(self: @This()) std.os.linux.timespec { - return self.atim; - } - - pub fn mtime(self: @This()) std.os.linux.timespec { - return self.mtim; - } - - pub fn ctime(self: @This()) std.os.linux.timespec { - return self.ctim; - } -}; diff --git a/lib/std/os/linux/riscv32.zig b/lib/std/os/linux/riscv32.zig index 34f73506a1ab..c1b216b38ede 100644 --- a/lib/std/os/linux/riscv32.zig +++ b/lib/std/os/linux/riscv32.zig @@ -124,46 +124,7 @@ pub fn clone() callconv(.naked) u32 { ); } -pub const blksize_t = i32; -pub const nlink_t = u32; pub const time_t = i64; -pub const mode_t = u32; -pub const off_t = i64; -pub const ino_t = u64; -pub const dev_t = u64; -pub const blkcnt_t = i64; - -// The `stat` definition used by the Linux kernel. -pub const Stat = extern struct { - dev: dev_t, - ino: ino_t, - mode: mode_t, - nlink: nlink_t, - uid: std.os.linux.uid_t, - gid: std.os.linux.gid_t, - rdev: dev_t, - __pad: u32, - size: off_t, - blksize: blksize_t, - __pad2: i32, - blocks: blkcnt_t, - atim: std.os.linux.timespec, - mtim: std.os.linux.timespec, - ctim: std.os.linux.timespec, - __unused: [2]u32, - - pub fn atime(self: @This()) std.os.linux.timespec { - return self.atim; - } - - pub fn mtime(self: @This()) std.os.linux.timespec { - return self.mtim; - } - - pub fn ctime(self: @This()) std.os.linux.timespec { - return self.ctim; - } -}; pub const VDSO = struct { pub const CGT_SYM = "__vdso_clock_gettime"; diff --git a/lib/std/os/linux/riscv64.zig b/lib/std/os/linux/riscv64.zig index e404693df08e..50a456836a16 100644 --- a/lib/std/os/linux/riscv64.zig +++ b/lib/std/os/linux/riscv64.zig @@ -124,46 +124,7 @@ pub fn clone() callconv(.naked) u64 { ); } -pub const blksize_t = i32; -pub const nlink_t = u32; pub const time_t = i64; -pub const mode_t = u32; -pub const off_t = i64; -pub const ino_t = u64; -pub const dev_t = u64; -pub const blkcnt_t = i64; - -// The `stat` definition used by the Linux kernel. -pub const Stat = extern struct { - dev: dev_t, - ino: ino_t, - mode: mode_t, - nlink: nlink_t, - uid: std.os.linux.uid_t, - gid: std.os.linux.gid_t, - rdev: dev_t, - __pad: u64, - size: off_t, - blksize: blksize_t, - __pad2: i32, - blocks: blkcnt_t, - atim: std.os.linux.timespec, - mtim: std.os.linux.timespec, - ctim: std.os.linux.timespec, - __unused: [2]u32, - - pub fn atime(self: @This()) std.os.linux.timespec { - return self.atim; - } - - pub fn mtime(self: @This()) std.os.linux.timespec { - return self.mtim; - } - - pub fn ctime(self: @This()) std.os.linux.timespec { - return self.ctim; - } -}; pub const VDSO = struct { pub const CGT_SYM = "__vdso_clock_gettime"; diff --git a/lib/std/os/linux/s390x.zig b/lib/std/os/linux/s390x.zig index 0a09982f2a1c..17a558e83d6e 100644 --- a/lib/std/os/linux/s390x.zig +++ b/lib/std/os/linux/s390x.zig @@ -152,44 +152,7 @@ pub fn restore_rt() callconv(.naked) noreturn { ); } -pub const blksize_t = i64; -pub const nlink_t = u64; pub const time_t = i64; -pub const mode_t = u32; -pub const off_t = i64; -pub const ino_t = u64; -pub const dev_t = u64; -pub const blkcnt_t = i64; - -// The `stat` definition used by the Linux kernel. -pub const Stat = extern struct { - dev: dev_t, - ino: ino_t, - nlink: nlink_t, - mode: mode_t, - uid: std.os.linux.uid_t, - gid: std.os.linux.gid_t, - rdev: dev_t, - size: off_t, - atim: std.os.linux.timespec, - mtim: std.os.linux.timespec, - ctim: std.os.linux.timespec, - blksize: blksize_t, - blocks: blkcnt_t, - __unused: [3]c_ulong, - - pub fn atime(self: @This()) std.os.linux.timespec { - return self.atim; - } - - pub fn mtime(self: @This()) std.os.linux.timespec { - return self.mtim; - } - - pub fn ctime(self: @This()) std.os.linux.timespec { - return self.ctim; - } -}; pub const VDSO = struct { pub const CGT_SYM = "__kernel_clock_gettime"; diff --git a/lib/std/os/linux/sparc64.zig b/lib/std/os/linux/sparc64.zig index 76506dbfa3df..59880bba873d 100644 --- a/lib/std/os/linux/sparc64.zig +++ b/lib/std/os/linux/sparc64.zig @@ -228,46 +228,4 @@ pub const VDSO = struct { pub const CGT_VER = "LINUX_2.6"; }; -pub const off_t = i64; -pub const ino_t = u64; pub const time_t = i64; -pub const mode_t = u32; -pub const dev_t = u64; -pub const nlink_t = u32; -pub const blksize_t = i64; -pub const blkcnt_t = i64; - -// The `stat64` definition used by the kernel. -pub const Stat = extern struct { - dev: dev_t, - ino: ino_t, - nlink: nlink_t, - _pad: i32, - - mode: mode_t, - uid: std.os.linux.uid_t, - gid: std.os.linux.gid_t, - __pad0: u32, - - rdev: dev_t, - size: i64, - blksize: blksize_t, - blocks: blkcnt_t, - - atim: std.os.linux.timespec, - mtim: std.os.linux.timespec, - ctim: std.os.linux.timespec, - __unused: [3]u64, - - pub fn atime(self: @This()) std.os.linux.timespec { - return self.atim; - } - - pub fn mtime(self: @This()) std.os.linux.timespec { - return self.mtim; - } - - pub fn ctime(self: @This()) std.os.linux.timespec { - return self.ctim; - } -}; diff --git a/lib/std/os/linux/syscalls.zig b/lib/std/os/linux/syscalls.zig index 58005cfa359d..c111f518b6d6 100644 --- a/lib/std/os/linux/syscalls.zig +++ b/lib/std/os/linux/syscalls.zig @@ -1,6 +1,5 @@ -// This file is automatically generated, DO NOT edit it manually. -// See tools/generate_linux_syscalls.zig for more info. -// This list current as of kernel: 6.16.0 +// This file is automatically generated by tools/generate_linux_syscalls.zig +// This list current as of kernel: 6.18.2 pub const X86 = enum(usize) { restart_syscall = 0, @@ -460,6 +459,8 @@ pub const X86 = enum(usize) { listxattrat = 465, removexattrat = 466, open_tree_attr = 467, + file_getattr = 468, + file_setattr = 469, }; pub const X64 = enum(usize) { @@ -799,6 +800,7 @@ pub const X64 = enum(usize) { io_pgetevents = 333, rseq = 334, uretprobe = 335, + uprobe = 336, pidfd_send_signal = 424, io_uring_setup = 425, io_uring_enter = 426, @@ -843,6 +845,8 @@ pub const X64 = enum(usize) { listxattrat = 465, removexattrat = 466, open_tree_attr = 467, + file_getattr = 468, + file_setattr = 469, }; pub const X32 = enum(usize) { @@ -1135,6 +1139,7 @@ pub const X32 = enum(usize) { io_pgetevents = 1073742157, rseq = 1073742158, uretprobe = 1073742159, + uprobe = 1073742160, pidfd_send_signal = 1073742248, io_uring_setup = 1073742249, io_uring_enter = 1073742250, @@ -1179,6 +1184,8 @@ pub const X32 = enum(usize) { listxattrat = 1073742289, removexattrat = 1073742290, open_tree_attr = 1073742291, + file_getattr = 1073742292, + file_setattr = 1073742293, rt_sigaction = 1073742336, rt_sigreturn = 1073742337, ioctl = 1073742338, @@ -1640,6 +1647,8 @@ pub const Arm = enum(usize) { listxattrat = 465, removexattrat = 466, open_tree_attr = 467, + file_getattr = 468, + file_setattr = 469, breakpoint = arm_base + 1, cacheflush = arm_base + 2, @@ -2086,6 +2095,8 @@ pub const Sparc = enum(usize) { listxattrat = 465, removexattrat = 466, open_tree_attr = 467, + file_getattr = 468, + file_setattr = 469, }; pub const Sparc64 = enum(usize) { @@ -2488,6 +2499,8 @@ pub const Sparc64 = enum(usize) { listxattrat = 465, removexattrat = 466, open_tree_attr = 467, + file_getattr = 468, + file_setattr = 469, }; pub const M68k = enum(usize) { @@ -2930,6 +2943,8 @@ pub const M68k = enum(usize) { listxattrat = 465, removexattrat = 466, open_tree_attr = 467, + file_getattr = 468, + file_setattr = 469, }; pub const MipsO32 = enum(usize) { @@ -3366,6 +3381,8 @@ pub const MipsO32 = enum(usize) { listxattrat = 4465, removexattrat = 4466, open_tree_attr = 4467, + file_getattr = 4468, + file_setattr = 4469, }; pub const MipsN64 = enum(usize) { @@ -3738,6 +3755,8 @@ pub const MipsN64 = enum(usize) { listxattrat = 5465, removexattrat = 5466, open_tree_attr = 5467, + file_getattr = 5468, + file_setattr = 5469, }; pub const MipsN32 = enum(usize) { @@ -4134,6 +4153,8 @@ pub const MipsN32 = enum(usize) { listxattrat = 6465, removexattrat = 6466, open_tree_attr = 6467, + file_getattr = 6468, + file_setattr = 6469, }; pub const PowerPC = enum(usize) { @@ -4585,6 +4606,8 @@ pub const PowerPC = enum(usize) { listxattrat = 465, removexattrat = 466, open_tree_attr = 467, + file_getattr = 468, + file_setattr = 469, }; pub const PowerPC64 = enum(usize) { @@ -5008,6 +5031,8 @@ pub const PowerPC64 = enum(usize) { listxattrat = 465, removexattrat = 466, open_tree_attr = 467, + file_getattr = 468, + file_setattr = 469, }; pub const S390x = enum(usize) { @@ -5397,6 +5422,8 @@ pub const S390x = enum(usize) { listxattrat = 465, removexattrat = 466, open_tree_attr = 467, + file_getattr = 468, + file_setattr = 469, }; pub const Xtensa = enum(usize) { @@ -5790,6 +5817,8 @@ pub const Xtensa = enum(usize) { listxattrat = 465, removexattrat = 466, open_tree_attr = 467, + file_getattr = 468, + file_setattr = 469, }; pub const Arm64 = enum(usize) { @@ -6116,6 +6145,8 @@ pub const Arm64 = enum(usize) { listxattrat = 465, removexattrat = 466, open_tree_attr = 467, + file_getattr = 468, + file_setattr = 469, }; pub const RiscV32 = enum(usize) { @@ -6433,6 +6464,8 @@ pub const RiscV32 = enum(usize) { listxattrat = 465, removexattrat = 466, open_tree_attr = 467, + file_getattr = 468, + file_setattr = 469, }; pub const RiscV64 = enum(usize) { @@ -6760,6 +6793,8 @@ pub const RiscV64 = enum(usize) { listxattrat = 465, removexattrat = 466, open_tree_attr = 467, + file_getattr = 468, + file_setattr = 469, }; pub const LoongArch64 = enum(usize) { @@ -7082,6 +7117,8 @@ pub const LoongArch64 = enum(usize) { listxattrat = 465, removexattrat = 466, open_tree_attr = 467, + file_getattr = 468, + file_setattr = 469, }; pub const Arc = enum(usize) { @@ -7432,6 +7469,8 @@ pub const Arc = enum(usize) { listxattrat = 465, removexattrat = 466, open_tree_attr = 467, + file_getattr = 468, + file_setattr = 469, }; pub const CSky = enum(usize) { @@ -7778,6 +7817,8 @@ pub const CSky = enum(usize) { listxattrat = 465, removexattrat = 466, open_tree_attr = 467, + file_getattr = 468, + file_setattr = 469, }; pub const Hexagon = enum(usize) { @@ -8123,6 +8164,8 @@ pub const Hexagon = enum(usize) { listxattrat = 465, removexattrat = 466, open_tree_attr = 467, + file_getattr = 468, + file_setattr = 469, }; pub const OpenRisc = enum(usize) { @@ -8469,4 +8512,6 @@ pub const OpenRisc = enum(usize) { listxattrat = 465, removexattrat = 466, open_tree_attr = 467, + file_getattr = 468, + file_setattr = 469, }; diff --git a/lib/std/os/linux/test.zig b/lib/std/os/linux/test.zig index f5533a54bdf4..974ce0a25c79 100644 --- a/lib/std/os/linux/test.zig +++ b/lib/std/os/linux/test.zig @@ -10,16 +10,18 @@ const expectEqual = std.testing.expectEqual; const fs = std.fs; test "fallocate" { - if (builtin.cpu.arch.isMIPS64() and (builtin.abi == .gnuabin32 or builtin.abi == .muslabin32)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/23809 + if (builtin.cpu.arch.isMIPS64() and (builtin.abi == .gnuabin32 or builtin.abi == .muslabin32)) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30220 + + const io = std.testing.io; var tmp = std.testing.tmpDir(.{}); defer tmp.cleanup(); const path = "test_fallocate"; - const file = try tmp.dir.createFile(path, .{ .truncate = true, .mode = 0o666 }); - defer file.close(); + const file = try tmp.dir.createFile(io, path, .{ .truncate = true, .permissions = .fromMode(0o666) }); + defer file.close(io); - try expect((try file.stat()).size == 0); + try expect((try file.stat(io)).size == 0); const len: i64 = 65536; switch (linux.errno(linux.fallocate(file.handle, 0, 0, len))) { @@ -29,7 +31,7 @@ test "fallocate" { else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), } - try expect((try file.stat()).size == len); + try expect((try file.stat(io)).size == len); } test "getpid" { @@ -77,33 +79,31 @@ test "timer" { } test "statx" { + const io = std.testing.io; + var tmp = std.testing.tmpDir(.{}); defer tmp.cleanup(); const tmp_file_name = "just_a_temporary_file.txt"; - var file = try tmp.dir.createFile(tmp_file_name, .{}); - defer file.close(); + var file = try tmp.dir.createFile(io, tmp_file_name, .{}); + defer file.close(io); - var statx_buf: linux.Statx = undefined; - switch (linux.errno(linux.statx(file.handle, "", linux.AT.EMPTY_PATH, linux.STATX_BASIC_STATS, &statx_buf))) { + var buf: linux.Statx = undefined; + switch (linux.errno(linux.statx(file.handle, "", linux.AT.EMPTY_PATH, .BASIC_STATS, &buf))) { .SUCCESS => {}, else => unreachable, } - if (builtin.cpu.arch == .riscv32 or builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; // No fstatat, so the rest of the test is meaningless. - - var stat_buf: linux.Stat = undefined; - switch (linux.errno(linux.fstatat(file.handle, "", &stat_buf, linux.AT.EMPTY_PATH))) { - .SUCCESS => {}, - else => unreachable, - } - - try expect(stat_buf.mode == statx_buf.mode); - try expect(@as(u32, @bitCast(stat_buf.uid)) == statx_buf.uid); - try expect(@as(u32, @bitCast(stat_buf.gid)) == statx_buf.gid); - try expect(@as(u64, @bitCast(@as(i64, stat_buf.size))) == statx_buf.size); - try expect(@as(u64, @bitCast(@as(i64, stat_buf.blksize))) == statx_buf.blksize); - try expect(@as(u64, @bitCast(@as(i64, stat_buf.blocks))) == statx_buf.blocks); + const uid = linux.getuid(); + const gid = linux.getgid(); + if (buf.mask.MODE) + try expectEqual(@as(linux.mode_t, linux.S.IFREG), buf.mode & linux.S.IFMT); + if (buf.mask.UID) + try expectEqual(uid, buf.uid); + if (buf.mask.GID) + try expectEqual(gid, buf.gid); + if (buf.mask.SIZE) + try expectEqual(@as(u64, 0), buf.size); } test "user and group ids" { @@ -115,15 +115,17 @@ test "user and group ids" { } test "fadvise" { + const io = std.testing.io; + var tmp = std.testing.tmpDir(.{}); defer tmp.cleanup(); const tmp_file_name = "temp_posix_fadvise.txt"; - var file = try tmp.dir.createFile(tmp_file_name, .{}); - defer file.close(); + var file = try tmp.dir.createFile(io, tmp_file_name, .{}); + defer file.close(io); var buf: [2048]u8 = undefined; - try file.writeAll(&buf); + try file.writeStreamingAll(io, &buf); const ret = linux.fadvise(file.handle, 0, 0, linux.POSIX_FADV.SEQUENTIAL); try expectEqual(@as(usize, 0), ret); @@ -138,23 +140,23 @@ test "sigset_t" { // See that none are set, then set each one, see that they're all set, then // remove them all, and then see that none are set. for (1..linux.NSIG) |i| { - const sig = std.meta.intToEnum(SIG, i) catch continue; + const sig = std.enums.fromInt(SIG, i) orelse continue; try expectEqual(false, linux.sigismember(&sigset, sig)); } for (1..linux.NSIG) |i| { - const sig = std.meta.intToEnum(SIG, i) catch continue; + const sig = std.enums.fromInt(SIG, i) orelse continue; linux.sigaddset(&sigset, sig); } for (1..linux.NSIG) |i| { - const sig = std.meta.intToEnum(SIG, i) catch continue; + const sig = std.enums.fromInt(SIG, i) orelse continue; try expectEqual(true, linux.sigismember(&sigset, sig)); } for (1..linux.NSIG) |i| { - const sig = std.meta.intToEnum(SIG, i) catch continue; + const sig = std.enums.fromInt(SIG, i) orelse continue; linux.sigdelset(&sigset, sig); } for (1..linux.NSIG) |i| { - const sig = std.meta.intToEnum(SIG, i) catch continue; + const sig = std.enums.fromInt(SIG, i) orelse continue; try expectEqual(false, linux.sigismember(&sigset, sig)); } } @@ -163,7 +165,7 @@ test "sigfillset" { // unlike the C library, all the signals are set in the kernel-level fillset const sigset = linux.sigfillset(); for (1..linux.NSIG) |i| { - const sig = std.meta.intToEnum(linux.SIG, i) catch continue; + const sig = std.enums.fromInt(linux.SIG, i) orelse continue; try expectEqual(true, linux.sigismember(&sigset, sig)); } } @@ -171,7 +173,7 @@ test "sigfillset" { test "sigemptyset" { const sigset = linux.sigemptyset(); for (1..linux.NSIG) |i| { - const sig = std.meta.intToEnum(linux.SIG, i) catch continue; + const sig = std.enums.fromInt(linux.SIG, i) orelse continue; try expectEqual(false, linux.sigismember(&sigset, sig)); } } @@ -405,14 +407,6 @@ test "futex2_requeue" { try expectEqual(0, rc); } -test "copy_file_range error" { - const fds = try std.posix.pipe(); - defer std.posix.close(fds[0]); - defer std.posix.close(fds[1]); - - try std.testing.expectError(error.InvalidArguments, linux.wrapped.copy_file_range(fds[0], null, fds[1], null, 1, 0)); -} - test { _ = linux.IoUring; } diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig index cbec3cc00a8e..e8598eb1110b 100644 --- a/lib/std/os/linux/tls.zig +++ b/lib/std/os/linux/tls.zig @@ -531,13 +531,11 @@ pub fn prepareArea(area: []u8) usize { }; } -/// The main motivation for the size chosen here is that this is how much ends up being requested for -/// the thread-local variables of the `std.crypto.random` implementation. I'm not sure why it ends up -/// being so much; the struct itself is only 64 bytes. I think it has to do with being page-aligned -/// and LLVM or LLD is not smart enough to lay out the TLS data in a space-conserving way. Anyway, I -/// think it's fine because it's less than 3 pages of memory, and putting it in the ELF like this is -/// equivalent to moving the `mmap` call below into the kernel, avoiding syscall overhead. -var main_thread_area_buffer: [0x2100]u8 align(page_size_min) = undefined; +/// The main motivation for the size chosen here is to be larger than total +/// amount of thread-local variables for most programs. Putting this allocation +/// in the ELF like this is equivalent to moving the `mmap` call below into the +/// kernel, avoiding syscall overhead. +var main_thread_area_buffer: [0x1000]u8 align(page_size_min) = undefined; /// Computes the layout of the static TLS area, allocates the area, initializes all of its fields, /// and assigns the architecture-specific value to the TP register. diff --git a/lib/std/os/linux/x32.zig b/lib/std/os/linux/x32.zig index ac596844d670..97deb7640f13 100644 --- a/lib/std/os/linux/x32.zig +++ b/lib/std/os/linux/x32.zig @@ -132,14 +132,7 @@ pub fn restore_rt() callconv(.naked) noreturn { } } -pub const mode_t = u32; pub const time_t = i32; -pub const nlink_t = u32; -pub const blksize_t = i32; -pub const blkcnt_t = i32; -pub const off_t = i64; -pub const ino_t = u64; -pub const dev_t = u64; pub const VDSO = struct { pub const CGT_SYM = "__vdso_clock_gettime"; @@ -155,36 +148,3 @@ pub const ARCH = struct { pub const GET_FS = 0x1003; pub const GET_GS = 0x1004; }; - -// The `stat` definition used by the Linux kernel. -pub const Stat = extern struct { - dev: dev_t, - ino: ino_t, - nlink: nlink_t, - - mode: mode_t, - uid: std.os.linux.uid_t, - gid: std.os.linux.gid_t, - __pad0: u32, - rdev: dev_t, - size: off_t, - blksize: blksize_t, - blocks: i64, - - atim: std.os.linux.timespec, - mtim: std.os.linux.timespec, - ctim: std.os.linux.timespec, - __unused: [3]i32, - - pub fn atime(self: @This()) std.os.linux.timespec { - return self.atim; - } - - pub fn mtime(self: @This()) std.os.linux.timespec { - return self.mtim; - } - - pub fn ctime(self: @This()) std.os.linux.timespec { - return self.ctim; - } -}; diff --git a/lib/std/os/linux/x86.zig b/lib/std/os/linux/x86.zig index a68a4af317b6..e95afe23a61b 100644 --- a/lib/std/os/linux/x86.zig +++ b/lib/std/os/linux/x86.zig @@ -195,46 +195,7 @@ pub const VDSO = struct { pub const CGT_VER = "LINUX_2.6"; }; -pub const blksize_t = i32; -pub const nlink_t = u32; pub const time_t = i32; -pub const mode_t = u32; -pub const off_t = i64; -pub const ino_t = u64; -pub const dev_t = u64; -pub const blkcnt_t = i64; - -// The `stat` definition used by the Linux kernel. -pub const Stat = extern struct { - dev: dev_t, - __dev_padding: u32, - __ino_truncated: u32, - mode: mode_t, - nlink: nlink_t, - uid: std.os.linux.uid_t, - gid: std.os.linux.gid_t, - rdev: dev_t, - __rdev_padding: u32, - size: off_t, - blksize: blksize_t, - blocks: blkcnt_t, - atim: std.os.linux.timespec, - mtim: std.os.linux.timespec, - ctim: std.os.linux.timespec, - ino: ino_t, - - pub fn atime(self: @This()) std.os.linux.timespec { - return self.atim; - } - - pub fn mtime(self: @This()) std.os.linux.timespec { - return self.mtim; - } - - pub fn ctime(self: @This()) std.os.linux.timespec { - return self.ctim; - } -}; pub const user_desc = extern struct { entry_number: u32, diff --git a/lib/std/os/linux/x86_64.zig b/lib/std/os/linux/x86_64.zig index d9c2d17f09e3..cab71d03e059 100644 --- a/lib/std/os/linux/x86_64.zig +++ b/lib/std/os/linux/x86_64.zig @@ -132,14 +132,7 @@ pub fn restore_rt() callconv(.naked) noreturn { } } -pub const mode_t = u64; pub const time_t = i64; -pub const nlink_t = u64; -pub const blksize_t = i64; -pub const blkcnt_t = i64; -pub const off_t = i64; -pub const ino_t = u64; -pub const dev_t = u64; pub const VDSO = struct { pub const CGT_SYM = "__vdso_clock_gettime"; @@ -155,36 +148,3 @@ pub const ARCH = struct { pub const GET_FS = 0x1003; pub const GET_GS = 0x1004; }; - -// The `stat` definition used by the Linux kernel. -pub const Stat = extern struct { - dev: dev_t, - ino: ino_t, - nlink: u64, - - mode: u32, - uid: std.os.linux.uid_t, - gid: std.os.linux.gid_t, - __pad0: u32, - rdev: dev_t, - size: off_t, - blksize: i64, - blocks: i64, - - atim: std.os.linux.timespec, - mtim: std.os.linux.timespec, - ctim: std.os.linux.timespec, - __unused: [3]i64, - - pub fn atime(self: @This()) std.os.linux.timespec { - return self.atim; - } - - pub fn mtime(self: @This()) std.os.linux.timespec { - return self.mtim; - } - - pub fn ctime(self: @This()) std.os.linux.timespec { - return self.ctim; - } -}; diff --git a/lib/std/os/uefi.zig b/lib/std/os/uefi.zig index c9391f956d2a..d8f08911b3eb 100644 --- a/lib/std/os/uefi.zig +++ b/lib/std/os/uefi.zig @@ -111,7 +111,7 @@ pub const Guid = extern struct { const time_mid = @byteSwap(self.time_mid); const time_high_and_version = @byteSwap(self.time_high_and_version); - return writer.print("{x:0>8}-{x:0>4}-{x:0>4}-{x:0>2}{x:0>2}-{x:0>12}", .{ + return writer.print("{x:0>8}-{x:0>4}-{x:0>4}-{x:0>2}{x:0>2}-{x}", .{ std.mem.asBytes(&time_low), std.mem.asBytes(&time_mid), std.mem.asBytes(&time_high_and_version), diff --git a/lib/std/os/uefi/protocol/file.zig b/lib/std/os/uefi/protocol/file.zig index 9e3e7cc081f9..9b371916a71b 100644 --- a/lib/std/os/uefi/protocol/file.zig +++ b/lib/std/os/uefi/protocol/file.zig @@ -163,15 +163,6 @@ pub const File = extern struct { } } - fn getEndPos(self: *File) SeekError!u64 { - const start_pos = try self.getPosition(); - // ignore error - defer self.setPosition(start_pos) catch {}; - - try self.setPosition(end_of_file); - return self.getPosition(); - } - pub fn setPosition(self: *File, position: u64) SeekError!void { switch (self._set_position(self, position)) { .success => {}, diff --git a/lib/std/os/uefi/protocol/ip6_config.zig b/lib/std/os/uefi/protocol/ip6_config.zig index bb660a3b8ef6..0ada2a7899fc 100644 --- a/lib/std/os/uefi/protocol/ip6_config.zig +++ b/lib/std/os/uefi/protocol/ip6_config.zig @@ -44,7 +44,7 @@ pub const Ip6Config = extern struct { pub fn setData( self: *const Ip6Config, comptime data_type: std.meta.Tag(DataType), - payload: *const std.meta.TagPayload(DataType, data_type), + payload: *const @FieldType(DataType, @tagName(data_type)), ) SetDataError!void { const data_size = @sizeOf(@TypeOf(payload)); switch (self._set_data(self, data_type, data_size, @ptrCast(payload))) { @@ -64,8 +64,8 @@ pub const Ip6Config = extern struct { pub fn getData( self: *const Ip6Config, comptime data_type: std.meta.Tag(DataType), - ) GetDataError!std.meta.TagPayload(DataType, data_type) { - const DataPayload = std.meta.TagPayload(DataType, data_type); + ) GetDataError!@FieldType(DataType, @tagName(data_type)) { + const DataPayload = @FieldType(DataType, @tagName(data_type)); var payload: DataPayload = undefined; var payload_size: usize = @sizeOf(DataPayload); diff --git a/lib/std/os/wasi.zig b/lib/std/os/wasi.zig index caef010683b9..87e1bc59c2e7 100644 --- a/lib/std/os/wasi.zig +++ b/lib/std/os/wasi.zig @@ -288,8 +288,9 @@ pub const oflags_t = packed struct(u16) { _: u12 = 0, }; -pub const preopentype_t = u8; -pub const PREOPENTYPE_DIR: preopentype_t = 0; +pub const preopentype_t = enum(u8) { + DIR = 0, +}; pub const prestat_t = extern struct { pr_type: preopentype_t, diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index ba05ff6057ee..52e4bd387d65 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -28,9 +28,2272 @@ pub const ws2_32 = @import("windows/ws2_32.zig"); pub const crypt32 = @import("windows/crypt32.zig"); pub const nls = @import("windows/nls.zig"); -pub const self_process_handle = @as(HANDLE, @ptrFromInt(maxInt(usize))); +pub const FILE = struct { + // ref: km/ntddk.h -const Self = @This(); + pub const END_OF_FILE_INFORMATION = extern struct { + EndOfFile: LARGE_INTEGER, + }; + + pub const ALIGNMENT_INFORMATION = extern struct { + AlignmentRequirement: ULONG, + }; + + pub const NAME_INFORMATION = extern struct { + FileNameLength: ULONG, + FileName: [1]WCHAR, + }; + + pub const DISPOSITION = packed struct(ULONG) { + DELETE: bool = false, + POSIX_SEMANTICS: bool = false, + FORCE_IMAGE_SECTION_CHECK: bool = false, + ON_CLOSE: bool = false, + IGNORE_READONLY_ATTRIBUTE: bool = false, + Reserved5: u27 = 0, + + pub const DO_NOT_DELETE: DISPOSITION = .{}; + + pub const INFORMATION = extern struct { + DeleteFile: BOOLEAN, + + pub const EX = extern struct { + Flags: DISPOSITION, + }; + }; + }; + + pub const FS_VOLUME_INFORMATION = extern struct { + VolumeCreationTime: LARGE_INTEGER, + VolumeSerialNumber: ULONG, + VolumeLabelLength: ULONG, + SupportsObjects: BOOLEAN, + VolumeLabel: [0]WCHAR, + + pub fn getVolumeLabel(fvi: *const FS_VOLUME_INFORMATION) []const WCHAR { + return (&fvi).ptr[0..@divExact(fvi.VolumeLabelLength, @sizeOf(WCHAR))]; + } + }; + + // ref: km/ntifs.h + + pub const PIPE = struct { + /// Define the `NamedPipeType` flags for `NtCreateNamedPipeFile` + pub const TYPE = packed struct(ULONG) { + TYPE: enum(u1) { + BYTE_STREAM = 0b0, + MESSAGE = 0b1, + } = .BYTE_STREAM, + REMOTE_CLIENTS: enum(u1) { + ACCEPT = 0b0, + REJECT = 0b1, + } = .ACCEPT, + Reserved2: u30 = 0, + + pub const VALID_MASK: TYPE = .{ + .TYPE = .MESSAGE, + .REMOTE_CLIENTS = .REJECT, + }; + }; + + /// Define the `CompletionMode` flags for `NtCreateNamedPipeFile` + pub const COMPLETION_MODE = packed struct(ULONG) { + OPERATION: enum(u1) { + QUEUE = 0b0, + COMPLETE = 0b1, + } = .QUEUE, + Reserved1: u31 = 0, + }; + + /// Define the `ReadMode` flags for `NtCreateNamedPipeFile` + pub const READ_MODE = packed struct(ULONG) { + MODE: enum(u1) { + BYTE_STREAM = 0b0, + MESSAGE = 0b1, + }, + Reserved1: u31 = 0, + }; + + /// Define the `NamedPipeConfiguration` flags for `NtQueryInformationFile` + pub const CONFIGURATION = enum(ULONG) { + INBOUND = 0x00000000, + OUTBOUND = 0x00000001, + FULL_DUPLEX = 0x00000002, + }; + + /// Define the `NamedPipeState` flags for `NtQueryInformationFile` + pub const STATE = enum(ULONG) { + DISCONNECTED = 0x00000001, + LISTENING = 0x00000002, + CONNECTED = 0x00000003, + CLOSING = 0x00000004, + }; + + /// Define the `NamedPipeEnd` flags for `NtQueryInformationFile` + pub const END = enum(ULONG) { + CLIENT = 0x00000000, + SERVER = 0x00000001, + }; + + pub const INFORMATION = extern struct { + ReadMode: READ_MODE, + CompletionMode: COMPLETION_MODE, + }; + + pub const LOCAL_INFORMATION = extern struct { + NamedPipeType: TYPE, + NamedPipeConfiguration: CONFIGURATION, + MaximumInstances: ULONG, + CurrentInstances: ULONG, + InboundQuota: ULONG, + ReadDataAvailable: ULONG, + OutboundQuota: ULONG, + WriteQuotaAvailable: ULONG, + NamedPipeState: STATE, + NamedPipeEnd: END, + }; + + pub const REMOTE_INFORMATION = extern struct { + CollectDataTime: LARGE_INTEGER, + MaximumCollectionCount: ULONG, + }; + + pub const WAIT_FOR_BUFFER = extern struct { + Timeout: LARGE_INTEGER, + NameLength: ULONG, + TimeoutSpecified: BOOLEAN, + Name: [PATH_MAX_WIDE]WCHAR, + + pub const WAIT_FOREVER: LARGE_INTEGER = std.math.minInt(LARGE_INTEGER); + + pub fn init(opts: struct { + Timeout: ?LARGE_INTEGER = null, + Name: []const WCHAR, + }) WAIT_FOR_BUFFER { + var fpwfb: WAIT_FOR_BUFFER = .{ + .Timeout = opts.Timeout orelse undefined, + .NameLength = @intCast(@sizeOf(WCHAR) * opts.Name.len), + .TimeoutSpecified = @intFromBool(opts.Timeout != null), + .Name = undefined, + }; + @memcpy(fpwfb.Name[0..opts.Name.len], opts.Name); + return fpwfb; + } + + pub fn getName(fpwfb: *const WAIT_FOR_BUFFER) []const WCHAR { + return fpwfb.Name[0..@divExact(fpwfb.NameLength, @sizeOf(WCHAR))]; + } + + pub fn toBuffer(fpwfb: *const WAIT_FOR_BUFFER) []const u8 { + const start: [*]const u8 = @ptrCast(fpwfb); + return start[0 .. @offsetOf(WAIT_FOR_BUFFER, "Name") + fpwfb.NameLength]; + } + }; + }; + + pub const ALL_INFORMATION = extern struct { + BasicInformation: BASIC_INFORMATION, + StandardInformation: STANDARD_INFORMATION, + InternalInformation: INTERNAL_INFORMATION, + EaInformation: EA_INFORMATION, + AccessInformation: ACCESS_INFORMATION, + PositionInformation: POSITION_INFORMATION, + ModeInformation: MODE.INFORMATION, + AlignmentInformation: ALIGNMENT_INFORMATION, + NameInformation: NAME_INFORMATION, + }; + + pub const INTERNAL_INFORMATION = extern struct { + IndexNumber: LARGE_INTEGER, + }; + + pub const EA_INFORMATION = extern struct { + EaSize: ULONG, + }; + + pub const ACCESS_INFORMATION = extern struct { + AccessFlags: ACCESS_MASK, + }; + + /// This is not separated into RENAME_INFORMATION and RENAME_INFORMATION_EX because + /// the only difference is the `Flags` type (BOOLEAN before _EX, ULONG in the _EX), + /// which doesn't affect the struct layout--the offset of RootDirectory is the same + /// regardless. + pub const RENAME_INFORMATION = extern struct { + Flags: FLAGS, + RootDirectory: ?HANDLE, + FileNameLength: ULONG, + FileName: [PATH_MAX_WIDE]WCHAR, + + pub fn init(opts: struct { + Flags: FLAGS = .{}, + RootDirectory: ?HANDLE = null, + FileName: []const WCHAR, + }) RENAME_INFORMATION { + var fri: RENAME_INFORMATION = .{ + .Flags = opts.Flags, + .RootDirectory = opts.RootDirectory, + .FileNameLength = @intCast(@sizeOf(WCHAR) * opts.FileName.len), + .FileName = undefined, + }; + @memcpy(fri.FileName[0..opts.FileName.len], opts.FileName); + return fri; + } + + pub const FLAGS = packed struct(ULONG) { + REPLACE_IF_EXISTS: bool = false, + POSIX_SEMANTICS: bool = false, + SUPPRESS_PIN_STATE_INHERITANCE: bool = false, + SUPPRESS_STORAGE_RESERVE_INHERITANCE: bool = false, + AVAILABLE_SPACE: enum(u2) { + NO_PRESERVE = 0b00, + NO_INCREASE = 0b01, + NO_DECREASE = 0b10, + PRESERVE = 0b11, + } = .NO_PRESERVE, + IGNORE_READONLY_ATTRIBUTE: bool = false, + RESIZE_SR: enum(u2) { + NO_FORCE = 0b00, + FORCE_TARGET = 0b01, + FORCE_SOURCE = 0b10, + FORCE = 0b11, + } = .NO_FORCE, + Reserved9: u23 = 0, + }; + + pub fn getFileName(ri: *const RENAME_INFORMATION) []const WCHAR { + return ri.FileName[0..@divExact(ri.FileNameLength, @sizeOf(WCHAR))]; + } + + pub fn toBuffer(fri: *const RENAME_INFORMATION) []const u8 { + const start: [*]const u8 = @ptrCast(fri); + return start[0 .. @offsetOf(RENAME_INFORMATION, "FileName") + fri.FileNameLength]; + } + }; + + // ref: km/wdm.h + + pub const INFORMATION_CLASS = enum(c_int) { + Directory = 1, + FullDirectory = 2, + BothDirectory = 3, + Basic = 4, + Standard = 5, + Internal = 6, + Ea = 7, + Access = 8, + Name = 9, + Rename = 10, + Link = 11, + Names = 12, + Disposition = 13, + Position = 14, + FullEa = 15, + Mode = 16, + Alignment = 17, + All = 18, + Allocation = 19, + EndOfFile = 20, + AlternateName = 21, + Stream = 22, + Pipe = 23, + PipeLocal = 24, + PipeRemote = 25, + MailslotQuery = 26, + MailslotSet = 27, + Compression = 28, + ObjectId = 29, + Completion = 30, + MoveCluster = 31, + Quota = 32, + ReparsePoint = 33, + NetworkOpen = 34, + AttributeTag = 35, + Tracking = 36, + IdBothDirectory = 37, + IdFullDirectory = 38, + ValidDataLength = 39, + ShortName = 40, + IoCompletionNotification = 41, + IoStatusBlockRange = 42, + IoPriorityHint = 43, + SfioReserve = 44, + SfioVolume = 45, + HardLink = 46, + ProcessIdsUsingFile = 47, + NormalizedName = 48, + NetworkPhysicalName = 49, + IdGlobalTxDirectory = 50, + IsRemoteDevice = 51, + Unused = 52, + NumaNode = 53, + StandardLink = 54, + RemoteProtocol = 55, + RenameBypassAccessCheck = 56, + LinkBypassAccessCheck = 57, + VolumeName = 58, + Id = 59, + IdExtdDirectory = 60, + ReplaceCompletion = 61, + HardLinkFullId = 62, + IdExtdBothDirectory = 63, + DispositionEx = 64, + RenameEx = 65, + RenameExBypassAccessCheck = 66, + DesiredStorageClass = 67, + Stat = 68, + MemoryPartition = 69, + StatLx = 70, + CaseSensitive = 71, + LinkEx = 72, + LinkExBypassAccessCheck = 73, + StorageReserveId = 74, + CaseSensitiveForceAccessCheck = 75, + KnownFolder = 76, + StatBasic = 77, + Id64ExtdDirectory = 78, + Id64ExtdBothDirectory = 79, + IdAllExtdDirectory = 80, + IdAllExtdBothDirectory = 81, + StreamReservation = 82, + MupProvider = 83, + + pub const Maximum: @typeInfo(@This()).@"enum".tag_type = 1 + @typeInfo(@This()).@"enum".fields.len; + }; + + pub const BASIC_INFORMATION = extern struct { + CreationTime: LARGE_INTEGER, + LastAccessTime: LARGE_INTEGER, + LastWriteTime: LARGE_INTEGER, + ChangeTime: LARGE_INTEGER, + FileAttributes: ATTRIBUTE, + }; + + pub const STANDARD_INFORMATION = extern struct { + AllocationSize: LARGE_INTEGER, + EndOfFile: LARGE_INTEGER, + NumberOfLinks: ULONG, + DeletePending: BOOLEAN, + Directory: BOOLEAN, + }; + + pub const POSITION_INFORMATION = extern struct { + CurrentByteOffset: LARGE_INTEGER, + }; + + pub const FS_DEVICE_INFORMATION = extern struct { + DeviceType: DEVICE_TYPE, + Characteristics: ULONG, + }; + + // ref: um/WinBase.h + + pub const ATTRIBUTE_TAG_INFO = extern struct { + FileAttributes: DWORD, + ReparseTag: IO_REPARSE_TAG, + }; + + // ref: um/winnt.h + + pub const SHARE = packed struct(ULONG) { + /// The file can be opened for read access by other threads. + READ: bool = false, + /// The file can be opened for write access by other threads. + WRITE: bool = false, + /// The file can be opened for delete access by other threads. + DELETE: bool = false, + Reserved3: u29 = 0, + + pub const VALID_FLAGS: SHARE = .{ + .READ = true, + .WRITE = true, + .DELETE = true, + }; + }; + + pub const ATTRIBUTE = packed struct(ULONG) { + /// The file is read only. Applications can read the file, but cannot write to or delete it. + READONLY: bool = false, + /// The file is hidden. Do not include it in an ordinary directory listing. + HIDDEN: bool = false, + /// The file is part of or used exclusively by an operating system. + SYSTEM: bool = false, + Reserved3: u1 = 0, + DIRECTORY: bool = false, + /// The file should be archived. Applications use this attribute to mark files for backup or removal. + ARCHIVE: bool = false, + DEVICE: bool = false, + /// The file does not have other attributes set. This attribute is valid only if used alone. + NORMAL: bool = false, + /// The file is being used for temporary storage. + TEMPORARY: bool = false, + SPARSE_FILE: bool = false, + REPARSE_POINT: bool = false, + COMPRESSED: bool = false, + /// The data of a file is not immediately available. This attribute indicates that file data is physically moved to offline storage. + /// This attribute is used by Remote Storage, the hierarchical storage management software. Applications should not arbitrarily change this attribute. + OFFLINE: bool = false, + NOT_CONTENT_INDEXED: bool = false, + /// The file or directory is encrypted. For a file, this means that all data in the file is encrypted. For a directory, this means that encryption is + /// the default for newly created files and subdirectories. For more information, see File Encryption. + /// + /// This flag has no effect if `SYSTEM` is also specified. + /// + /// This flag is not supported on Home, Home Premium, Starter, or ARM editions of Windows. + ENCRYPTED: bool = false, + INTEGRITY_STREAM: bool = false, + VIRTUAL: bool = false, + NO_SCRUB_DATA: bool = false, + EA_or_RECALL_ON_OPEN: bool = false, + PINNED: bool = false, + UNPINNED: bool = false, + Reserved21: u1 = 0, + RECALL_ON_DATA_ACCESS: bool = false, + Reserved23: u6 = 0, + STRICTLY_SEQUENTIAL: bool = false, + Reserved30: u2 = 0, + }; + + // ref: um/winternl.h + + /// Define the create disposition values + pub const CREATE_DISPOSITION = enum(ULONG) { + /// If the file already exists, replace it with the given file. If it does not, create the given file. + SUPERSEDE = 0x00000000, + /// If the file already exists, open it instead of creating a new file. If it does not, fail the request and do not create a new file. + OPEN = 0x00000001, + /// If the file already exists, fail the request and do not create or open the given file. If it does not, create the given file. + CREATE = 0x00000002, + /// If the file already exists, open it. If it does not, create the given file. + OPEN_IF = 0x00000003, + /// If the file already exists, open it and overwrite it. If it does not, fail the request. + OVERWRITE = 0x00000004, + /// If the file already exists, open it and overwrite it. If it does not, create the given file. + OVERWRITE_IF = 0x00000005, + + pub const MAXIMUM_DISPOSITION: CREATE_DISPOSITION = .OVERWRITE_IF; + }; + + /// Define the create/open option flags + pub const MODE = packed struct(ULONG) { + /// The file being created or opened is a directory file. With this flag, the CreateDisposition parameter must be set to `.CREATE`, `.FILE_OPEN`, or `.OPEN_IF`. + /// With this flag, other compatible CreateOptions flags include only the following: `SYNCHRONOUS_IO`, `WRITE_THROUGH`, `OPEN_FOR_BACKUP_INTENT`, and `OPEN_BY_FILE_ID`. + DIRECTORY_FILE: bool = false, + /// Applications that write data to the file must actually transfer the data into the file before any requested write operation is considered complete. + /// This flag is automatically set if the CreateOptions flag `NO_INTERMEDIATE_BUFFERING` is set. + WRITE_THROUGH: bool = false, + /// All accesses to the file are sequential. + SEQUENTIAL_ONLY: bool = false, + /// The file cannot be cached or buffered in a driver's internal buffers. This flag is incompatible with the DesiredAccess `FILE_APPEND_DATA` flag. + NO_INTERMEDIATE_BUFFERING: bool = false, + IO: enum(u2) { + /// All operations on the file are performed asynchronously. + ASYNCHRONOUS = 0b00, + /// All operations on the file are performed synchronously. Any wait on behalf of the caller is subject to premature termination from alerts. + /// This flag also causes the I/O system to maintain the file position context. If this flag is set, the DesiredAccess `SYNCHRONIZE` flag also must be set. + SYNCHRONOUS_ALERT = 0b01, + /// All operations on the file are performed synchronously. Waits in the system to synchronize I/O queuing and completion are not subject to alerts. + /// This flag also causes the I/O system to maintain the file position context. If this flag is set, the DesiredAccess `SYNCHRONIZE` flag also must be set. + SYNCHRONOUS_NONALERT = 0b10, + _, + + pub const VALID_FLAGS: @This() = @enumFromInt(0b11); + } = .ASYNCHRONOUS, + /// The file being opened must not be a directory file or this call fails. The file object being opened can represent a data file, a logical, virtual, or physical + /// device, or a volume. + NON_DIRECTORY_FILE: bool = false, + /// Create a tree connection for this file in order to open it over the network. This flag is not used by device and intermediate drivers. + CREATE_TREE_CONNECTION: bool = false, + /// Complete this operation immediately with an alternate success code of `STATUS_OPLOCK_BREAK_IN_PROGRESS` if the target file is oplocked, rather than blocking + /// the caller's thread. If the file is oplocked, another caller already has access to the file. This flag is not used by device and intermediate drivers. + COMPLETE_IF_OPLOCKED: bool = false, + /// If the extended attributes on an existing file being opened indicate that the caller must understand EAs to properly interpret the file, fail this request + /// because the caller does not understand how to deal with EAs. This flag is irrelevant for device and intermediate drivers. + NO_EA_KNOWLEDGE: bool = false, + OPEN_REMOTE_INSTANCE: bool = false, + /// Accesses to the file can be random, so no sequential read-ahead operations should be performed on the file by FSDs or the system. + RANDOM_ACCESS: bool = false, + /// Delete the file when the last handle to it is passed to `NtClose`. If this flag is set, the `DELETE` flag must be set in the DesiredAccess parameter. + DELETE_ON_CLOSE: bool = false, + /// The file name that is specified by the `ObjectAttributes` parameter includes the 8-byte file reference number for the file. This number is assigned by and + /// specific to the particular file system. If the file is a reparse point, the file name will also include the name of a device. Note that the FAT file system + /// does not support this flag. This flag is not used by device and intermediate drivers. + OPEN_BY_FILE_ID: bool = false, + /// The file is being opened for backup intent. Therefore, the system should check for certain access rights and grant the caller the appropriate access to the + /// file before checking the DesiredAccess parameter against the file's security descriptor. This flag not used by device and intermediate drivers. + OPEN_FOR_BACKUP_INTENT: bool = false, + /// Suppress inheritance of `FILE_ATTRIBUTE.COMPRESSED` from the parent directory. This allows creation of a non-compressed file in a directory that is marked + /// compressed. + NO_COMPRESSION: bool = false, + /// The file is being opened and an opportunistic lock on the file is being requested as a single atomic operation. The file system checks for oplocks before it + /// performs the create operation and will fail the create with a return code of STATUS_CANNOT_BREAK_OPLOCK if the result would be to break an existing oplock. + /// For more information, see the Remarks section. + /// + /// Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This flag is not supported. + /// + /// This flag is supported on the following file systems: NTFS, FAT, and exFAT. + OPEN_REQUIRING_OPLOCK: bool = false, + Reserved17: u3 = 0, + /// This flag allows an application to request a filter opportunistic lock to prevent other applications from getting share violations. If there are already open + /// handles, the create request will fail with STATUS_OPLOCK_NOT_GRANTED. For more information, see the Remarks section. + RESERVE_OPFILTER: bool = false, + /// Open a file with a reparse point and bypass normal reparse point processing for the file. For more information, see the Remarks section. + OPEN_REPARSE_POINT: bool = false, + /// Instructs any filters that perform offline storage or virtualization to not recall the contents of the file as a result of this open. + OPEN_NO_RECALL: bool = false, + /// This flag instructs the file system to capture the user associated with the calling thread. Any subsequent calls to `FltQueryVolumeInformation` or + /// `ZwQueryVolumeInformationFile` using the returned handle will assume the captured user, rather than the calling user at the time, for purposes of computing + /// the free space available to the caller. This applies to the following FsInformationClass values: `FileFsSizeInformation`, `FileFsFullSizeInformation`, and + /// `FileFsFullSizeInformationEx`. + OPEN_FOR_FREE_SPACE_QUERY: bool = false, + Reserved24: u8 = 0, + + pub const VALID_OPTION_FLAGS: MODE = .{ + .DIRECTORY_FILE = true, + .WRITE_THROUGH = true, + .SEQUENTIAL_ONLY = true, + .NO_INTERMEDIATE_BUFFERING = true, + .IO = .VALID_FLAGS, + .NON_DIRECTORY_FILE = true, + .CREATE_TREE_CONNECTION = true, + .COMPLETE_IF_OPLOCKED = true, + .NO_EA_KNOWLEDGE = true, + .OPEN_REMOTE_INSTANCE = true, + .RANDOM_ACCESS = true, + .DELETE_ON_CLOSE = true, + .OPEN_BY_FILE_ID = true, + .OPEN_FOR_BACKUP_INTENT = true, + .NO_COMPRESSION = true, + .OPEN_REQUIRING_OPLOCK = true, + .Reserved17 = 0b111, + .RESERVE_OPFILTER = true, + .OPEN_REPARSE_POINT = true, + .OPEN_NO_RECALL = true, + .OPEN_FOR_FREE_SPACE_QUERY = true, + }; + + pub const VALID_PIPE_OPTION_FLAGS: MODE = .{ + .WRITE_THROUGH = true, + .IO = .VALID_FLAGS, + }; + + pub const VALID_MAILSLOT_OPTION_FLAGS: MODE = .{ + .WRITE_THROUGH = true, + .IO = .VALID_FLAGS, + }; + + pub const VALID_SET_OPTION_FLAGS: MODE = .{ + .WRITE_THROUGH = true, + .SEQUENTIAL_ONLY = true, + .IO = .VALID_FLAGS, + }; + + // ref: km/ntifs.h + + pub const INFORMATION = extern struct { + /// The set of flags that specify the mode in which the file can be accessed. These flags are a subset of `MODE`. + Mode: MODE, + }; + }; +}; + +// ref: km/ntddk.h + +pub const PROCESSINFOCLASS = enum(c_int) { + BasicInformation = 0, + QuotaLimits = 1, + IoCounters = 2, + VmCounters = 3, + Times = 4, + BasePriority = 5, + RaisePriority = 6, + DebugPort = 7, + ExceptionPort = 8, + AccessToken = 9, + LdtInformation = 10, + LdtSize = 11, + DefaultHardErrorMode = 12, + IoPortHandlers = 13, + PooledUsageAndLimits = 14, + WorkingSetWatch = 15, + UserModeIOPL = 16, + EnableAlignmentFaultFixup = 17, + PriorityClass = 18, + Wx86Information = 19, + HandleCount = 20, + AffinityMask = 21, + PriorityBoost = 22, + DeviceMap = 23, + SessionInformation = 24, + ForegroundInformation = 25, + Wow64Information = 26, + ImageFileName = 27, + LUIDDeviceMapsEnabled = 28, + BreakOnTermination = 29, + DebugObjectHandle = 30, + DebugFlags = 31, + HandleTracing = 32, + IoPriority = 33, + ExecuteFlags = 34, + TlsInformation = 35, + Cookie = 36, + ImageInformation = 37, + CycleTime = 38, + PagePriority = 39, + InstrumentationCallback = 40, + ThreadStackAllocation = 41, + WorkingSetWatchEx = 42, + ImageFileNameWin32 = 43, + ImageFileMapping = 44, + AffinityUpdateMode = 45, + MemoryAllocationMode = 46, + GroupInformation = 47, + TokenVirtualizationEnabled = 48, + OwnerInformation = 49, + WindowInformation = 50, + HandleInformation = 51, + MitigationPolicy = 52, + DynamicFunctionTableInformation = 53, + HandleCheckingMode = 54, + KeepAliveCount = 55, + RevokeFileHandles = 56, + WorkingSetControl = 57, + HandleTable = 58, + CheckStackExtentsMode = 59, + CommandLineInformation = 60, + ProtectionInformation = 61, + MemoryExhaustion = 62, + FaultInformation = 63, + TelemetryIdInformation = 64, + CommitReleaseInformation = 65, + Reserved1Information = 66, + Reserved2Information = 67, + SubsystemProcess = 68, + InPrivate = 70, + RaiseUMExceptionOnInvalidHandleClose = 71, + SubsystemInformation = 75, + Win32kSyscallFilterInformation = 79, + EnergyTrackingState = 82, + NetworkIoCounters = 114, + _, + + pub const Max: @typeInfo(@This()).@"enum".tag_type = 117; +}; + +pub const THREADINFOCLASS = enum(c_int) { + BasicInformation = 0, + Times = 1, + Priority = 2, + BasePriority = 3, + AffinityMask = 4, + ImpersonationToken = 5, + DescriptorTableEntry = 6, + EnableAlignmentFaultFixup = 7, + EventPair_Reusable = 8, + QuerySetWin32StartAddress = 9, + ZeroTlsCell = 10, + PerformanceCount = 11, + AmILastThread = 12, + IdealProcessor = 13, + PriorityBoost = 14, + SetTlsArrayAddress = 15, + IsIoPending = 16, + // Windows 2000+ from here + HideFromDebugger = 17, + // Windows XP+ from here + BreakOnTermination = 18, + SwitchLegacyState = 19, + IsTerminated = 20, + // Windows Vista+ from here + LastSystemCall = 21, + IoPriority = 22, + CycleTime = 23, + PagePriority = 24, + ActualBasePriority = 25, + TebInformation = 26, + CSwitchMon = 27, + // Windows 7+ from here + CSwitchPmu = 28, + Wow64Context = 29, + GroupInformation = 30, + UmsInformation = 31, + CounterProfiling = 32, + IdealProcessorEx = 33, + // Windows 8+ from here + CpuAccountingInformation = 34, + // Windows 8.1+ from here + SuspendCount = 35, + // Windows 10+ from here + HeterogeneousCpuPolicy = 36, + ContainerId = 37, + NameInformation = 38, + SelectedCpuSets = 39, + SystemThreadInformation = 40, + ActualGroupAffinity = 41, + DynamicCodePolicyInfo = 42, + SubsystemInformation = 45, + + pub const Max: @typeInfo(@This()).@"enum".tag_type = 60; +}; + +// ref: km/ntifs.h + +pub const HEAP = opaque { + pub const FLAGS = packed struct(u8) { + /// Serialized access is not used when the heap functions access this heap. This option + /// applies to all subsequent heap function calls. Alternatively, you can specify this + /// option on individual heap function calls. + /// + /// The low-fragmentation heap (LFH) cannot be enabled for a heap created with this option. + /// + /// A heap created with this option cannot be locked. + NO_SERIALIZE: bool = false, + /// Specifies that the heap is growable. Must be specified if `HeapBase` is `NULL`. + GROWABLE: bool = false, + /// The system raises an exception to indicate failure (for example, an out-of-memory + /// condition) for calls to `HeapAlloc` and `HeapReAlloc` instead of returning `NULL`. + /// + /// To ensure that exceptions are generated for all calls to an allocation function, specify + /// `GENERATE_EXCEPTIONS` in the call to `HeapCreate`. In this case, it is not necessary to + /// additionally specify `GENERATE_EXCEPTIONS` in the allocation function calls. + GENERATE_EXCEPTIONS: bool = false, + /// The allocated memory will be initialized to zero. Otherwise, the memory is not + /// initialized to zero. + ZERO_MEMORY: bool = false, + REALLOC_IN_PLACE_ONLY: bool = false, + TAIL_CHECKING_ENABLED: bool = false, + FREE_CHECKING_ENABLED: bool = false, + DISABLE_COALESCE_ON_FREE: bool = false, + + pub const CLASS = enum(u4) { + /// process heap + PROCESS, + /// private heap + PRIVATE, + /// Kernel Heap + KERNEL, + /// GDI heap + GDI, + /// User heap + USER, + /// Console heap + CONSOLE, + /// User Desktop heap + USER_DESKTOP, + /// Csrss Shared heap + CSRSS_SHARED, + /// Csr Port heap + CSR_PORT, + _, + + pub const MASK: CLASS = @enumFromInt(maxInt(@typeInfo(CLASS).@"enum".tag_type)); + }; + + pub const CREATE = packed struct(ULONG) { + COMMON: FLAGS = .{}, + SEGMENT_HEAP: bool = false, + /// Only applies to segment heap. Applies pointer obfuscation which is + /// generally excessive and unnecessary but is necessary for certain insecure + /// heaps in win32k. + /// + /// Specifying HEAP_CREATE_HARDENED prevents the heap from using locks as + /// pointers would potentially be exposed in heap metadata lock variables. + /// Callers are therefore responsible for synchronizing access to hardened heaps. + HARDENED: bool = false, + Reserved10: u2 = 0, + CLASS: CLASS = @enumFromInt(0), + /// Create heap with 16 byte alignment (obsolete) + ALIGN_16: bool = false, + /// Create heap call tracing enabled (obsolete) + ENABLE_TRACING: bool = false, + /// Create heap with executable pages + /// + /// All memory blocks that are allocated from this heap allow code execution, if the + /// hardware enforces data execution prevention. Use this flag heap in applications that + /// run code from the heap. If `ENABLE_EXECUTE` is not specified and an application + /// attempts to run code from a protected page, the application receives an exception + /// with the status code `STATUS_ACCESS_VIOLATION`. + ENABLE_EXECUTE: bool = false, + Reserved19: u13 = 0, + + pub const VALID_MASK: CREATE = .{ + .COMMON = .{ + .NO_SERIALIZE = true, + .GROWABLE = true, + .GENERATE_EXCEPTIONS = true, + .ZERO_MEMORY = true, + .REALLOC_IN_PLACE_ONLY = true, + .TAIL_CHECKING_ENABLED = true, + .FREE_CHECKING_ENABLED = true, + .DISABLE_COALESCE_ON_FREE = true, + }, + .CLASS = .MASK, + .ALIGN_16 = true, + .ENABLE_TRACING = true, + .ENABLE_EXECUTE = true, + .SEGMENT_HEAP = true, + .HARDENED = true, + }; + }; + + pub const ALLOCATION = packed struct(ULONG) { + COMMON: FLAGS = .{}, + SETTABLE_USER: packed struct(u4) { + VALUE: u1 = 0, + FLAGS: packed struct(u3) { + FLAG1: bool = false, + FLAG2: bool = false, + FLAG3: bool = false, + } = .{}, + } = .{}, + CLASS: CLASS = @enumFromInt(0), + Reserved16: u2 = 0, + TAG: u12 = 0, + Reserved30: u2 = 0, + }; + }; + + pub const RTL_PARAMETERS = extern struct { + Length: ULONG, + SegmentReserve: SIZE_T, + SegmentCommit: SIZE_T, + DeCommitFreeBlockThreshold: SIZE_T, + DeCommitTotalFreeThreshold: SIZE_T, + MaximumAllocationSize: SIZE_T, + VirtualMemoryThreshold: SIZE_T, + InitialCommit: SIZE_T, + InitialReserve: SIZE_T, + CommitRoutine: *const COMMIT_ROUTINE, + Reserved: [2]SIZE_T = @splat(0), + + pub const COMMIT_ROUTINE = fn ( + Base: PVOID, + CommitAddress: *PVOID, + CommitSize: *SIZE_T, + ) callconv(.winapi) NTSTATUS; + + pub const SEGMENT = extern struct { + Version: VERSION, + Size: USHORT, + Flags: FLG, + MemorySource: MEMORY_SOURCE, + Reserved: [4]SIZE_T, + + pub const VERSION = enum(USHORT) { + CURRENT = 3, + _, + }; + + pub const FLG = packed struct(ULONG) { + USE_PAGE_HEAP: bool = false, + NO_LFH: bool = false, + Reserved2: u30 = 0, + + pub const VALID_FLAGS: FLG = .{ + .USE_PAGE_HEAP = true, + .NO_LFH = true, + }; + }; + + pub const MEMORY_SOURCE = extern struct { + Flags: ULONG, + MemoryTypeMask: TYPE, + NumaNode: ULONG, + u: extern union { + PartitionHandle: HANDLE, + Callbacks: *const VA_CALLBACKS, + }, + Reserved: [2]SIZE_T = @splat(0), + + pub const TYPE = enum(ULONG) { + Paged, + NonPaged, + @"64KPage", + LargePage, + HugePage, + Custom, + _, + + pub const Max: @typeInfo(@This()).@"enum".tag_type = @typeInfo(@This()).@"enum".fields.len; + }; + + pub const VA_CALLBACKS = extern struct { + CallbackContext: HANDLE, + AllocateVirtualMemory: *const ALLOCATE_VIRTUAL_MEMORY_EX_CALLBACK, + FreeVirtualMemory: *const FREE_VIRTUAL_MEMORY_EX_CALLBACK, + QueryVirtualMemory: *const QUERY_VIRTUAL_MEMORY_CALLBACK, + + pub const ALLOCATE_VIRTUAL_MEMORY_EX_CALLBACK = fn ( + CallbackContext: HANDLE, + BaseAddress: *PVOID, + RegionSize: *SIZE_T, + AllocationType: ULONG, + PageProtection: ULONG, + ExtendedParameters: ?[*]MEM.EXTENDED_PARAMETER, + ExtendedParameterCount: ULONG, + ) callconv(.c) NTSTATUS; + + pub const FREE_VIRTUAL_MEMORY_EX_CALLBACK = fn ( + CallbackContext: HANDLE, + ProcessHandle: HANDLE, + BaseAddress: *PVOID, + RegionSize: *SIZE_T, + FreeType: ULONG, + ) callconv(.c) NTSTATUS; + + pub const QUERY_VIRTUAL_MEMORY_CALLBACK = fn ( + CallbackContext: HANDLE, + ProcessHandle: HANDLE, + BaseAddress: *PVOID, + MemoryInformationClass: MEMORY_INFO_CLASS, + MemoryInformation: PVOID, + MemoryInformationLength: SIZE_T, + ReturnLength: ?*SIZE_T, + ) callconv(.c) NTSTATUS; + + pub const MEMORY_INFO_CLASS = enum(c_int) { + Basic, + _, + }; + }; + }; + }; + }; +}; + +pub const CTL_CODE = packed struct(ULONG) { + Method: METHOD, + Function: u12, + Access: FILE_ACCESS, + DeviceType: FILE_DEVICE, + + pub const METHOD = enum(u2) { + BUFFERED = 0, + IN_DIRECT = 1, + OUT_DIRECT = 2, + NEITHER = 3, + }; + + pub const FILE_ACCESS = packed struct(u2) { + READ: bool = false, + WRITE: bool = false, + + pub const ANY: FILE_ACCESS = .{ .READ = false, .WRITE = false }; + pub const SPECIAL = ANY; + }; + + pub const FILE_DEVICE = enum(u16) { + BEEP = 0x00000001, + CD_ROM = 0x00000002, + CD_ROM_FILE_SYSTEM = 0x00000003, + CONTROLLER = 0x00000004, + DATALINK = 0x00000005, + DFS = 0x00000006, + DISK = 0x00000007, + DISK_FILE_SYSTEM = 0x00000008, + FILE_SYSTEM = 0x00000009, + INPORT_PORT = 0x0000000a, + KEYBOARD = 0x0000000b, + MAILSLOT = 0x0000000c, + MIDI_IN = 0x0000000d, + MIDI_OUT = 0x0000000e, + MOUSE = 0x0000000f, + MULTI_UNC_PROVIDER = 0x00000010, + NAMED_PIPE = 0x00000011, + NETWORK = 0x00000012, + NETWORK_BROWSER = 0x00000013, + NETWORK_FILE_SYSTEM = 0x00000014, + NULL = 0x00000015, + PARALLEL_PORT = 0x00000016, + PHYSICAL_NETCARD = 0x00000017, + PRINTER = 0x00000018, + SCANNER = 0x00000019, + SERIAL_MOUSE_PORT = 0x0000001a, + SERIAL_PORT = 0x0000001b, + SCREEN = 0x0000001c, + SOUND = 0x0000001d, + STREAMS = 0x0000001e, + TAPE = 0x0000001f, + TAPE_FILE_SYSTEM = 0x00000020, + TRANSPORT = 0x00000021, + UNKNOWN = 0x00000022, + VIDEO = 0x00000023, + VIRTUAL_DISK = 0x00000024, + WAVE_IN = 0x00000025, + WAVE_OUT = 0x00000026, + @"8042_PORT" = 0x00000027, + NETWORK_REDIRECTOR = 0x00000028, + BATTERY = 0x00000029, + BUS_EXTENDER = 0x0000002a, + MODEM = 0x0000002b, + VDM = 0x0000002c, + MASS_STORAGE = 0x0000002d, + SMB = 0x0000002e, + KS = 0x0000002f, + CHANGER = 0x00000030, + SMARTCARD = 0x00000031, + ACPI = 0x00000032, + DVD = 0x00000033, + FULLSCREEN_VIDEO = 0x00000034, + DFS_FILE_SYSTEM = 0x00000035, + DFS_VOLUME = 0x00000036, + SERENUM = 0x00000037, + TERMSRV = 0x00000038, + KSEC = 0x00000039, + FIPS = 0x0000003A, + INFINIBAND = 0x0000003B, + VMBUS = 0x0000003E, + CRYPT_PROVIDER = 0x0000003F, + WPD = 0x00000040, + BLUETOOTH = 0x00000041, + MT_COMPOSITE = 0x00000042, + MT_TRANSPORT = 0x00000043, + BIOMETRIC = 0x00000044, + PMI = 0x00000045, + EHSTOR = 0x00000046, + DEVAPI = 0x00000047, + GPIO = 0x00000048, + USBEX = 0x00000049, + CONSOLE = 0x00000050, + NFP = 0x00000051, + SYSENV = 0x00000052, + VIRTUAL_BLOCK = 0x00000053, + POINT_OF_SERVICE = 0x00000054, + STORAGE_REPLICATION = 0x00000055, + TRUST_ENV = 0x00000056, + UCM = 0x00000057, + UCMTCPCI = 0x00000058, + PERSISTENT_MEMORY = 0x00000059, + NVDIMM = 0x0000005a, + HOLOGRAPHIC = 0x0000005b, + SDFXHCI = 0x0000005c, + UCMUCSI = 0x0000005d, + PRM = 0x0000005e, + EVENT_COLLECTOR = 0x0000005f, + USB4 = 0x00000060, + SOUNDWIRE = 0x00000061, + + MOUNTMGRCONTROLTYPE = 'm', + + _, + }; +}; + +pub const IOCTL = struct { + pub const KSEC = struct { + pub const GEN_RANDOM: CTL_CODE = .{ .DeviceType = .KSEC, .Function = 2, .Method = .BUFFERED, .Access = .ANY }; + }; + pub const MOUNTMGR = struct { + pub const QUERY_POINTS: CTL_CODE = .{ .DeviceType = .MOUNTMGRCONTROLTYPE, .Function = 2, .Method = .BUFFERED, .Access = .ANY }; + pub const QUERY_DOS_VOLUME_PATH: CTL_CODE = .{ .DeviceType = .MOUNTMGRCONTROLTYPE, .Function = 12, .Method = .BUFFERED, .Access = .ANY }; + }; +}; + +pub const FSCTL = struct { + pub const SET_REPARSE_POINT: CTL_CODE = .{ .DeviceType = .FILE_SYSTEM, .Function = 41, .Method = .BUFFERED, .Access = .SPECIAL }; + pub const GET_REPARSE_POINT: CTL_CODE = .{ .DeviceType = .FILE_SYSTEM, .Function = 42, .Method = .BUFFERED, .Access = .ANY }; + + pub const PIPE = struct { + pub const ASSIGN_EVENT: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 0, .Method = .BUFFERED, .Access = .ANY }; + pub const DISCONNECT: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 1, .Method = .BUFFERED, .Access = .ANY }; + pub const LISTEN: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 2, .Method = .BUFFERED, .Access = .ANY }; + pub const PEEK: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 3, .Method = .BUFFERED, .Access = .{ .READ = true } }; + pub const QUERY_EVENT: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 4, .Method = .BUFFERED, .Access = .ANY }; + pub const TRANSCEIVE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 5, .Method = .NEITHER, .Access = .{ .READ = true, .WRITE = true } }; + pub const WAIT: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 6, .Method = .BUFFERED, .Access = .ANY }; + pub const IMPERSONATE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 7, .Method = .BUFFERED, .Access = .ANY }; + pub const SET_CLIENT_PROCESS: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 8, .Method = .BUFFERED, .Access = .ANY }; + pub const QUERY_CLIENT_PROCESS: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 9, .Method = .BUFFERED, .Access = .ANY }; + pub const GET_PIPE_ATTRIBUTE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 10, .Method = .BUFFERED, .Access = .ANY }; + pub const SET_PIPE_ATTRIBUTE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 11, .Method = .BUFFERED, .Access = .ANY }; + pub const GET_CONNECTION_ATTRIBUTE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 12, .Method = .BUFFERED, .Access = .ANY }; + pub const SET_CONNECTION_ATTRIBUTE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 13, .Method = .BUFFERED, .Access = .ANY }; + pub const GET_HANDLE_ATTRIBUTE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 14, .Method = .BUFFERED, .Access = .ANY }; + pub const SET_HANDLE_ATTRIBUTE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 15, .Method = .BUFFERED, .Access = .ANY }; + pub const FLUSH: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 16, .Method = .BUFFERED, .Access = .{ .WRITE = true } }; + + pub const INTERNAL_READ: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 2045, .Method = .BUFFERED, .Access = .{ .READ = true } }; + pub const INTERNAL_WRITE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 2046, .Method = .BUFFERED, .Access = .{ .WRITE = true } }; + pub const INTERNAL_TRANSCEIVE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 2047, .Method = .NEITHER, .Access = .{ .READ = true, .WRITE = true } }; + pub const INTERNAL_READ_OVFLOW: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 2048, .Method = .BUFFERED, .Access = .{ .READ = true } }; + }; +}; + +pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: ULONG = 16 * 1024; + +pub const IO_REPARSE_TAG = packed struct(ULONG) { + Value: u12, + Index: u4 = 0, + ReservedBits: u12 = 0, + /// Can have children if a directory. + IsDirectory: bool = false, + /// Represents another named entity in the system. + IsSurrogate: bool = false, + /// Must be `false` for non-Microsoft tags. + IsReserved: bool = false, + /// Owned by Microsoft. + IsMicrosoft: bool = false, + + pub const RESERVED_INVALID: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsReserved = true, .Index = 0x8, .Value = 0x000 }; + pub const MOUNT_POINT: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsSurrogate = true, .Value = 0x003 }; + pub const HSM: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsReserved = true, .Value = 0x004 }; + pub const DRIVE_EXTENDER: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x005 }; + pub const HSM2: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x006 }; + pub const SIS: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x007 }; + pub const WIM: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x008 }; + pub const CSV: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x009 }; + pub const DFS: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x00A }; + pub const FILTER_MANAGER: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x00B }; + pub const SYMLINK: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsSurrogate = true, .Value = 0x00C }; + pub const IIS_CACHE: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsSurrogate = true, .Value = 0x010 }; + pub const DFSR: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x012 }; + pub const DEDUP: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x013 }; + pub const APPXSTRM: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsReserved = true, .Value = 0x014 }; + pub const NFS: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x014 }; + pub const FILE_PLACEHOLDER: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x015 }; + pub const DFM: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x016 }; + pub const WOF: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x017 }; + pub inline fn WCI(index: u1) IO_REPARSE_TAG { + return .{ .IsMicrosoft = true, .IsDirectory = index == 0x1, .Index = index, .Value = 0x018 }; + } + pub const GLOBAL_REPARSE: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsSurrogate = true, .Value = 0x0019 }; + pub inline fn CLOUD(index: u4) IO_REPARSE_TAG { + return .{ .IsMicrosoft = true, .IsDirectory = true, .Index = index, .Value = 0x01A }; + } + pub const APPEXECLINK: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x01B }; + pub const PROJFS: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsDirectory = true, .Value = 0x01C }; + pub const LX_SYMLINK: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsSurrogate = true, .Value = 0x01D }; + pub const STORAGE_SYNC: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x01E }; + pub const WCI_TOMBSTONE: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsSurrogate = true, .Value = 0x01F }; + pub const UNHANDLED: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x020 }; + pub const ONEDRIVE: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x021 }; + pub const PROJFS_TOMBSTONE: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsSurrogate = true, .Value = 0x022 }; + pub const AF_UNIX: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x023 }; + pub const LX_FIFO: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x024 }; + pub const LX_CHR: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x025 }; + pub const LX_BLK: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x026 }; + pub const LX_STORAGE_SYNC_FOLDER: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsDirectory = true, .Value = 0x027 }; + pub inline fn WCI_LINK(index: u1) IO_REPARSE_TAG { + return .{ .IsMicrosoft = true, .IsSurrogate = true, .Index = index, .Value = 0x027 }; + } + pub const DATALESS_CIM: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsSurrogate = true, .Value = 0x28 }; +}; + +// ref: km/wdm.h + +pub const ACCESS_MASK = packed struct(DWORD) { + SPECIFIC: Specific = .{ .bits = 0 }, + STANDARD: Standard = .{}, + Reserved21: u3 = 0, + ACCESS_SYSTEM_SECURITY: bool = false, + MAXIMUM_ALLOWED: bool = false, + Reserved26: u2 = 0, + GENERIC: Generic = .{}, + + pub const Specific = packed union { + bits: u16, + + // ref: km/wdm.h + + /// Define access rights to files and directories + FILE: File, + FILE_DIRECTORY: File.Directory, + FILE_PIPE: File.Pipe, + /// Registry Specific Access Rights. + KEY: Key, + /// Object Manager Object Type Specific Access Rights. + OBJECT_TYPE: ObjectType, + /// Object Manager Directory Specific Access Rights. + DIRECTORY: Directory, + /// Object Manager Symbolic Link Specific Access Rights. + SYMBOLIC_LINK: SymbolicLink, + /// Section Access Rights. + SECTION: Section, + /// Session Specific Access Rights. + SESSION: Session, + /// Process Specific Access Rights. + PROCESS: Process, + /// Thread Specific Access Rights. + THREAD: Thread, + /// Partition Specific Access Rights. + MEMORY_PARTITION: MemoryPartition, + /// Generic mappings for transaction manager rights. + TRANSACTIONMANAGER: TransactionManager, + /// Generic mappings for transaction rights. + TRANSACTION: Transaction, + /// Generic mappings for resource manager rights. + RESOURCEMANAGER: ResourceManager, + /// Generic mappings for enlistment rights. + ENLISTMENT: Enlistment, + /// Event Specific Access Rights. + EVENT: Event, + /// Semaphore Specific Access Rights. + SEMAPHORE: Semaphore, + + // ref: km/ntifs.h + + /// Token Specific Access Rights. + TOKEN: Token, + + // um/winnt.h + + /// Job Object Specific Access Rights. + JOB_OBJECT: JobObject, + /// Mutant Specific Access Rights. + MUTANT: Mutant, + /// Timer Specific Access Rights. + TIMER: Timer, + /// I/O Completion Specific Access Rights. + IO_COMPLETION: IoCompletion, + + pub const File = packed struct(u16) { + READ_DATA: bool = false, + WRITE_DATA: bool = false, + APPEND_DATA: bool = false, + READ_EA: bool = false, + WRITE_EA: bool = false, + EXECUTE: bool = false, + Reserved6: u1 = 0, + READ_ATTRIBUTES: bool = false, + WRITE_ATTRIBUTES: bool = false, + Reserved9: u7 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .REQUIRED, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .FILE = .{ + .READ_DATA = true, + .WRITE_DATA = true, + .APPEND_DATA = true, + .READ_EA = true, + .WRITE_EA = true, + .EXECUTE = true, + .Reserved6 = maxInt(@FieldType(File, "Reserved6")), + .READ_ATTRIBUTES = true, + .WRITE_ATTRIBUTES = true, + } }, + }; + + pub const GENERIC_READ: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .READ, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .FILE = .{ + .READ_DATA = true, + .READ_ATTRIBUTES = true, + .READ_EA = true, + } }, + }; + + pub const GENERIC_WRITE: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .WRITE, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .FILE = .{ + .WRITE_DATA = true, + .WRITE_ATTRIBUTES = true, + .WRITE_EA = true, + .APPEND_DATA = true, + } }, + }; + + pub const GENERIC_EXECUTE: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .EXECUTE, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .FILE = .{ + .READ_ATTRIBUTES = true, + .EXECUTE = true, + } }, + }; + + pub const Directory = packed struct(u16) { + LIST: bool = false, + ADD_FILE: bool = false, + ADD_SUBDIRECTORY: bool = false, + READ_EA: bool = false, + WRITE_EA: bool = false, + TRAVERSE: bool = false, + DELETE_CHILD: bool = false, + READ_ATTRIBUTES: bool = false, + WRITE_ATTRIBUTES: bool = false, + Reserved9: u7 = 0, + }; + + pub const Pipe = packed struct(u16) { + READ_DATA: bool = false, + WRITE_DATA: bool = false, + CREATE_PIPE_INSTANCE: bool = false, + Reserved3: u4 = 0, + READ_ATTRIBUTES: bool = false, + WRITE_ATTRIBUTES: bool = false, + Reserved9: u7 = 0, + }; + }; + + pub const Key = packed struct(u16) { + /// Required to query the values of a registry key. + QUERY_VALUE: bool = false, + /// Required to create, delete, or set a registry value. + SET_VALUE: bool = false, + /// Required to create a subkey of a registry key. + CREATE_SUB_KEY: bool = false, + /// Required to enumerate the subkeys of a registry key. + ENUMERATE_SUB_KEYS: bool = false, + /// Required to request change notifications for a registry key or for subkeys of a registry key. + NOTIFY: bool = false, + /// Reserved for system use. + CREATE_LINK: bool = false, + Reserved6: u2 = 0, + /// Indicates that an application on 64-bit Windows should operate on the 64-bit registry view. + /// This flag is ignored by 32-bit Windows. + WOW64_64KEY: bool = false, + /// Indicates that an application on 64-bit Windows should operate on the 32-bit registry view. + /// This flag is ignored by 32-bit Windows. + WOW64_32KEY: bool = false, + Reserved10: u6 = 0, + + pub const WOW64_RES: ACCESS_MASK = .{ + .SPECIFIC = .{ .KEY = .{ + .WOW64_32KEY = true, + .WOW64_64KEY = true, + } }, + }; + + /// Combines the STANDARD_RIGHTS_READ, KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS, and KEY_NOTIFY values. + pub const READ: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .READ, + .SYNCHRONIZE = false, + }, + .SPECIFIC = .{ .KEY = .{ + .QUERY_VALUE = true, + .ENUMERATE_SUB_KEYS = true, + .NOTIFY = true, + } }, + }; + + /// Combines the STANDARD_RIGHTS_WRITE, KEY_SET_VALUE, and KEY_CREATE_SUB_KEY access rights. + pub const WRITE: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .WRITE, + .SYNCHRONIZE = false, + }, + .SPECIFIC = .{ .KEY = .{ + .SET_VALUE = true, + .CREATE_SUB_KEY = true, + } }, + }; + + /// Equivalent to KEY_READ. + pub const EXECUTE = READ; + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .ALL, + .SYNCHRONIZE = false, + }, + .SPECIFIC = .{ .KEY = .{ + .QUERY_VALUE = true, + .SET_VALUE = true, + .CREATE_SUB_KEY = true, + .ENUMERATE_SUB_KEYS = true, + .NOTIFY = true, + .CREATE_LINK = true, + } }, + }; + }; + + pub const ObjectType = packed struct(u16) { + CREATE: bool = false, + Reserved1: u15 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .REQUIRED }, + .SPECIFIC = .{ .OBJECT_TYPE = .{ + .CREATE = true, + } }, + }; + }; + + pub const Directory = packed struct(u16) { + QUERY: bool = false, + TRAVERSE: bool = false, + CREATE_OBJECT: bool = false, + CREATE_SUBDIRECTORY: bool = false, + Reserved3: u12 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .REQUIRED }, + .SPECIFIC = .{ .DIRECTORY = .{ + .QUERY = true, + .TRAVERSE = true, + .CREATE_OBJECT = true, + .CREATE_SUBDIRECTORY = true, + } }, + }; + }; + + pub const SymbolicLink = packed struct(u16) { + QUERY: bool = false, + SET: bool = false, + Reserved2: u14 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .REQUIRED }, + .SPECIFIC = .{ .SYMBOLIC_LINK = .{ + .QUERY = true, + } }, + }; + + pub const ALL_ACCESS_EX: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .REQUIRED }, + .SPECIFIC = .{ .SYMBOLIC_LINK = .{ + .QUERY = true, + .SET = true, + .Reserved2 = maxInt(@FieldType(SymbolicLink, "Reserved2")), + } }, + }; + }; + + pub const Section = packed struct(u16) { + QUERY: bool = false, + MAP_WRITE: bool = false, + MAP_READ: bool = false, + MAP_EXECUTE: bool = false, + EXTEND_SIZE: bool = false, + /// not included in `ALL_ACCESS` + MAP_EXECUTE_EXPLICIT: bool = false, + Reserved6: u10 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .REQUIRED }, + .SPECIFIC = .{ .SECTION = .{ + .QUERY = true, + .MAP_WRITE = true, + .MAP_READ = true, + .MAP_EXECUTE = true, + .EXTEND_SIZE = true, + } }, + }; + }; + + pub const Session = packed struct(u16) { + QUERY_ACCESS: bool = false, + MODIFY_ACCESS: bool = false, + Reserved2: u14 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .REQUIRED }, + .SPECIFIC = .{ .SESSION = .{ + .QUERY_ACCESS = true, + .MODIFY_ACCESS = true, + } }, + }; + }; + + pub const Process = packed struct(u16) { + TERMINATE: bool = false, + CREATE_THREAD: bool = false, + SET_SESSIONID: bool = false, + VM_OPERATION: bool = false, + VM_READ: bool = false, + VM_WRITE: bool = false, + DUP_HANDLE: bool = false, + CREATE_PROCESS: bool = false, + SET_QUOTA: bool = false, + SET_INFORMATION: bool = false, + QUERY_INFORMATION: bool = false, + SUSPEND_RESUME: bool = false, + QUERY_LIMITED_INFORMATION: bool = false, + SET_LIMITED_INFORMATION: bool = false, + Reserved14: u2 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .REQUIRED, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .PROCESS = .{ + .TERMINATE = true, + .CREATE_THREAD = true, + .SET_SESSIONID = true, + .VM_OPERATION = true, + .VM_READ = true, + .VM_WRITE = true, + .DUP_HANDLE = true, + .CREATE_PROCESS = true, + .SET_QUOTA = true, + .SET_INFORMATION = true, + .QUERY_INFORMATION = true, + .SUSPEND_RESUME = true, + .QUERY_LIMITED_INFORMATION = true, + .SET_LIMITED_INFORMATION = true, + .Reserved14 = maxInt(@FieldType(Process, "Reserved14")), + } }, + }; + }; + + pub const Thread = packed struct(u16) { + TERMINATE: bool = false, + SUSPEND_RESUME: bool = false, + ALERT: bool = false, + GET_CONTEXT: bool = false, + SET_CONTEXT: bool = false, + SET_INFORMATION: bool = false, + QUERY_INFORMATION: bool = false, + SET_THREAD_TOKEN: bool = false, + IMPERSONATE: bool = false, + DIRECT_IMPERSONATION: bool = false, + SET_LIMITED_INFORMATION: bool = false, + QUERY_LIMITED_INFORMATION: bool = false, + RESUME: bool = false, + Reserved13: u3 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .REQUIRED, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .THREAD = .{ + .TERMINATE = true, + .SUSPEND_RESUME = true, + .ALERT = true, + .GET_CONTEXT = true, + .SET_CONTEXT = true, + .SET_INFORMATION = true, + .QUERY_INFORMATION = true, + .SET_THREAD_TOKEN = true, + .IMPERSONATE = true, + .DIRECT_IMPERSONATION = true, + .SET_LIMITED_INFORMATION = true, + .QUERY_LIMITED_INFORMATION = true, + .RESUME = true, + .Reserved13 = maxInt(@FieldType(Thread, "Reserved13")), + } }, + }; + }; + + pub const MemoryPartition = packed struct(u16) { + QUERY_ACCESS: bool = false, + MODIFY_ACCESS: bool = false, + Required2: u14 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .REQUIRED, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .MEMORY_PARTITION = .{ + .QUERY_ACCESS = true, + .MODIFY_ACCESS = true, + } }, + }; + }; + + pub const TransactionManager = packed struct(u16) { + QUERY_INFORMATION: bool = false, + SET_INFORMATION: bool = false, + RECOVER: bool = false, + RENAME: bool = false, + CREATE_RM: bool = false, + /// The following right is intended for DTC's use only; it will be deprecated, and no one else should take a dependency on it. + BIND_TRANSACTION: bool = false, + Reserved6: u10 = 0, + + pub const GENERIC_READ: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .READ }, + .SPECIFIC = .{ .TRANSACTIONMANAGER = .{ + .QUERY_INFORMATION = true, + } }, + }; + + pub const GENERIC_WRITE: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .WRITE }, + .SPECIFIC = .{ .TRANSACTIONMANAGER = .{ + .SET_INFORMATION = true, + .RECOVER = true, + .RENAME = true, + .CREATE_RM = true, + } }, + }; + + pub const GENERIC_EXECUTE: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .EXECUTE }, + .SPECIFIC = .{ .TRANSACTIONMANAGER = .{} }, + }; + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .REQUIRED }, + .SPECIFIC = .{ .TRANSACTIONMANAGER = .{ + .QUERY_INFORMATION = true, + .SET_INFORMATION = true, + .RECOVER = true, + .RENAME = true, + .CREATE_RM = true, + .BIND_TRANSACTION = true, + } }, + }; + }; + + pub const Transaction = packed struct(u16) { + QUERY_INFORMATION: bool = false, + SET_INFORMATION: bool = false, + ENLIST: bool = false, + COMMIT: bool = false, + ROLLBACK: bool = false, + PROPAGATE: bool = false, + RIGHT_RESERVED1: bool = false, + Reserved7: u9 = 0, + + pub const GENERIC_READ: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .READ, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .TRANSACTION = .{ + .QUERY_INFORMATION = true, + } }, + }; + + pub const GENERIC_WRITE: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .WRITE, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .TRANSACTION = .{ + .SET_INFORMATION = true, + .COMMIT = true, + .ENLIST = true, + .ROLLBACK = true, + .PROPAGATE = true, + } }, + }; + + pub const GENERIC_EXECUTE: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .EXECUTE, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .TRANSACTION = .{ + .COMMIT = true, + .ROLLBACK = true, + } }, + }; + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .REQUIRED, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .TRANSACTION = .{ + .QUERY_INFORMATION = true, + .SET_INFORMATION = true, + .COMMIT = true, + .ENLIST = true, + .ROLLBACK = true, + .PROPAGATE = true, + } }, + }; + + pub const RESOURCE_MANAGER_RIGHTS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .{ + .READ_CONTROL = true, + }, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .TRANSACTION = .{ + .QUERY_INFORMATION = true, + .SET_INFORMATION = true, + .ENLIST = true, + .ROLLBACK = true, + .PROPAGATE = true, + } }, + }; + }; + + pub const ResourceManager = packed struct(u16) { + QUERY_INFORMATION: bool = false, + SET_INFORMATION: bool = false, + RECOVER: bool = false, + ENLIST: bool = false, + GET_NOTIFICATION: bool = false, + REGISTER_PROTOCOL: bool = false, + COMPLETE_PROPAGATION: bool = false, + Reserved7: u9 = 0, + + pub const GENERIC_READ: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .READ, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .RESOURCEMANAGER = .{ + .QUERY_INFORMATION = true, + } }, + }; + + pub const GENERIC_WRITE: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .WRITE, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .RESOURCEMANAGER = .{ + .SET_INFORMATION = true, + .RECOVER = true, + .ENLIST = true, + .GET_NOTIFICATION = true, + .REGISTER_PROTOCOL = true, + .COMPLETE_PROPAGATION = true, + } }, + }; + + pub const GENERIC_EXECUTE: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .EXECUTE, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .RESOURCEMANAGER = .{ + .RECOVER = true, + .ENLIST = true, + .GET_NOTIFICATION = true, + .COMPLETE_PROPAGATION = true, + } }, + }; + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .REQUIRED, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .RESOURCEMANAGER = .{ + .QUERY_INFORMATION = true, + .SET_INFORMATION = true, + .RECOVER = true, + .ENLIST = true, + .GET_NOTIFICATION = true, + .REGISTER_PROTOCOL = true, + .COMPLETE_PROPAGATION = true, + } }, + }; + }; + + pub const Enlistment = packed struct(u16) { + QUERY_INFORMATION: bool = false, + SET_INFORMATION: bool = false, + RECOVER: bool = false, + SUBORDINATE_RIGHTS: bool = false, + SUPERIOR_RIGHTS: bool = false, + Reserved5: u11 = 0, + + pub const GENERIC_READ: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .READ }, + .SPECIFIC = .{ .ENLISTMENT = .{ + .QUERY_INFORMATION = true, + } }, + }; + + pub const GENERIC_WRITE: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .WRITE }, + .SPECIFIC = .{ .ENLISTMENT = .{ + .SET_INFORMATION = true, + .RECOVER = true, + .SUBORDINATE_RIGHTS = true, + .SUPERIOR_RIGHTS = true, + } }, + }; + + pub const GENERIC_EXECUTE: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .EXECUTE }, + .SPECIFIC = .{ .ENLISTMENT = .{ + .RECOVER = true, + .SUBORDINATE_RIGHTS = true, + .SUPERIOR_RIGHTS = true, + } }, + }; + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .REQUIRED }, + .SPECIFIC = .{ .ENLISTMENT = .{ + .QUERY_INFORMATION = true, + .SET_INFORMATION = true, + .RECOVER = true, + .SUBORDINATE_RIGHTS = true, + .SUPERIOR_RIGHTS = true, + } }, + }; + }; + + pub const Event = packed struct(u16) { + QUERY_STATE: bool = false, + MODIFY_STATE: bool = false, + Reserved2: u14 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .REQUIRED, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .EVENT = .{ + .QUERY_STATE = true, + .MODIFY_STATE = true, + } }, + }; + }; + + pub const Semaphore = packed struct(u16) { + QUERY_STATE: bool = false, + MODIFY_STATE: bool = false, + Reserved2: u14 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .REQUIRED, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .SEMAPHORE = .{ + .QUERY_STATE = true, + .MODIFY_STATE = true, + } }, + }; + }; + + pub const Token = packed struct(u16) { + ASSIGN_PRIMARY: bool = false, + DUPLICATE: bool = false, + IMPERSONATE: bool = false, + QUERY: bool = false, + QUERY_SOURCE: bool = false, + ADJUST_PRIVILEGES: bool = false, + ADJUST_GROUPS: bool = false, + ADJUST_DEFAULT: bool = false, + ADJUST_SESSIONID: bool = false, + Reserved9: u7 = 0, + + pub const ALL_ACCESS_P: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .REQUIRED }, + .SPECIFIC = .{ .TOKEN = .{ + .ASSIGN_PRIMARY = true, + .DUPLICATE = true, + .IMPERSONATE = true, + .QUERY = true, + .QUERY_SOURCE = true, + .ADJUST_PRIVILEGES = true, + .ADJUST_GROUPS = true, + .ADJUST_DEFAULT = true, + } }, + }; + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .REQUIRED }, + .SPECIFIC = .{ .TOKEN = .{ + .ASSIGN_PRIMARY = true, + .DUPLICATE = true, + .IMPERSONATE = true, + .QUERY = true, + .QUERY_SOURCE = true, + .ADJUST_PRIVILEGES = true, + .ADJUST_GROUPS = true, + .ADJUST_DEFAULT = true, + .ADJUST_SESSIONID = true, + } }, + }; + + pub const READ: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .READ }, + .SPECIFIC = .{ .TOKEN = .{ + .QUERY = true, + } }, + }; + + pub const WRITE: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .WRITE }, + .SPECIFIC = .{ .TOKEN = .{ + .ADJUST_PRIVILEGES = true, + .ADJUST_GROUPS = true, + .ADJUST_DEFAULT = true, + } }, + }; + + pub const EXECUTE: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .EXECUTE }, + .SPECIFIC = .{ .TOKEN = .{} }, + }; + + pub const TRUST_CONSTRAINT_MASK: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .READ }, + .SPECIFIC = .{ .TOKEN = .{ + .QUERY = true, + .QUERY_SOURCE = true, + } }, + }; + + pub const TRUST_ALLOWED_MASK: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .READ }, + .SPECIFIC = .{ .TOKEN = .{ + .QUERY = true, + .QUERY_SOURCE = true, + .DUPLICATE = true, + .IMPERSONATE = true, + } }, + }; + }; + + pub const JobObject = packed struct(u16) { + ASSIGN_PROCESS: bool = false, + SET_ATTRIBUTES: bool = false, + QUERY: bool = false, + TERMINATE: bool = false, + SET_SECURITY_ATTRIBUTES: bool = false, + IMPERSONATE: bool = false, + Reserved6: u10 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .REQUIRED, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .JOB_OBJECT = .{ + .ASSIGN_PROCESS = true, + .SET_ATTRIBUTES = true, + .QUERY = true, + .TERMINATE = true, + .SET_SECURITY_ATTRIBUTES = true, + .IMPERSONATE = true, + } }, + }; + }; + + pub const Mutant = packed struct(u16) { + QUERY_STATE: bool = false, + Reserved1: u15 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .REQUIRED, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .MUTANT = .{ + .QUERY_STATE = true, + } }, + }; + }; + + pub const Timer = packed struct(u16) { + QUERY_STATE: bool = false, + MODIFY_STATE: bool = false, + Reserved2: u14 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .REQUIRED, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .TIMER = .{ + .QUERY_STATE = true, + .MODIFY_STATE = true, + } }, + }; + }; + + pub const IoCompletion = packed struct(u16) { + Reserved0: u1 = 0, + MODIFY_STATE: bool = false, + Reserved2: u14 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .REQUIRED, .SYNCHRONIZE = true }, + .SPECIFIC = .{ .IO_COMPLETION = .{ + .Reserved0 = maxInt(@FieldType(IoCompletion, "Reserved0")), + .MODIFY_STATE = true, + } }, + }; + }; + + pub const RIGHTS_ALL: Specific = .{ .bits = maxInt(@FieldType(Specific, "bits")) }; + }; + + pub const Standard = packed struct(u5) { + RIGHTS: Rights = .{}, + SYNCHRONIZE: bool = false, + + pub const RIGHTS_ALL: Standard = .{ + .RIGHTS = .ALL, + .SYNCHRONIZE = true, + }; + + pub const Rights = packed struct(u4) { + DELETE: bool = false, + READ_CONTROL: bool = false, + WRITE_DAC: bool = false, + WRITE_OWNER: bool = false, + + pub const REQUIRED: Rights = .{ + .DELETE = true, + .READ_CONTROL = true, + .WRITE_DAC = true, + .WRITE_OWNER = true, + }; + + pub const READ: Rights = .{ + .READ_CONTROL = true, + }; + pub const WRITE: Rights = .{ + .READ_CONTROL = true, + }; + pub const EXECUTE: Rights = .{ + .READ_CONTROL = true, + }; + + pub const ALL = REQUIRED; + }; + }; + + pub const Generic = packed struct(u4) { + ALL: bool = false, + EXECUTE: bool = false, + WRITE: bool = false, + READ: bool = false, + }; +}; + +pub const DEVICE_TYPE = packed struct(ULONG) { + FileDevice: CTL_CODE.FILE_DEVICE, + Reserved16: u16 = 0, +}; + +pub const FS_INFORMATION_CLASS = enum(c_int) { + Volume = 1, + Label = 2, + Size = 3, + Device = 4, + Attribute = 5, + Control = 6, + FullSize = 7, + ObjectId = 8, + DriverPath = 9, + VolumeFlags = 10, + SectorSize = 11, + DataCopy = 12, + MetadataSize = 13, + FullSizeEx = 14, + Guid = 15, + _, + + pub const Maximum: @typeInfo(@This()).@"enum".tag_type = 1 + @typeInfo(@This()).@"enum".fields.len; +}; + +pub const SECTION_INHERIT = enum(c_int) { + Share = 1, + Unmap = 2, +}; + +pub const PAGE = packed struct(ULONG) { + NOACCESS: bool = false, + READONLY: bool = false, + READWRITE: bool = false, + WRITECOPY: bool = false, + + EXECUTE: bool = false, + EXECUTE_READ: bool = false, + EXECUTE_READWRITE: bool = false, + EXECUTE_WRITECOPY: bool = false, + + GUARD: bool = false, + NOCACHE: bool = false, + WRITECOMBINE: bool = false, + + GRAPHICS_NOACCESS: bool = false, + GRAPHICS_READONLY: bool = false, + GRAPHICS_READWRITE: bool = false, + GRAPHICS_EXECUTE: bool = false, + GRAPHICS_EXECUTE_READ: bool = false, + GRAPHICS_EXECUTE_READWRITE: bool = false, + GRAPHICS_COHERENT: bool = false, + GRAPHICS_NOCACHE: bool = false, + + Reserved19: u12 = 0, + + REVERT_TO_FILE_MAP: bool = false, +}; + +pub const MEM = struct { + pub const ALLOCATE = packed struct(ULONG) { + Reserved0: u12 = 0, + COMMIT: bool = false, + RESERVE: bool = false, + REPLACE_PLACEHOLDER: bool = false, + Reserved15: u3 = 0, + RESERVE_PLACEHOLDER: bool = false, + RESET: bool = false, + TOP_DOWN: bool = false, + WRITE_WATCH: bool = false, + PHYSICAL: bool = false, + Reserved23: u1 = 0, + RESET_UNDO: bool = false, + Reserved25: u4 = 0, + LARGE_PAGES: bool = false, + Reserved30: u1 = 0, + @"4MB_PAGES": bool = false, + + pub const @"64K_PAGES": ALLOCATE = .{ + .LARGE_PAGES = true, + .PHYSICAL = true, + }; + }; + + pub const FREE = packed struct(ULONG) { + COALESCE_PLACEHOLDERS: bool = false, + PRESERVE_PLACEHOLDER: bool = false, + Reserved2: u12 = 0, + DECOMMIT: bool = false, + RELEASE: bool = false, + FREE: bool = false, + Reserved17: u15 = 0, + }; + + pub const MAP = packed struct(ULONG) { + Reserved0: u13 = 0, + RESERVE: bool = false, + REPLACE_PLACEHOLDER: bool = false, + Reserved15: u14 = 0, + LARGE_PAGES: bool = false, + Reserved30: u2 = 0, + }; + + pub const UNMAP = packed struct(ULONG) { + WITH_TRANSIENT_BOOST: bool = false, + PRESERVE_PLACEHOLDER: bool = false, + Reserved2: u30 = 0, + }; + + pub const EXTENDED_PARAMETER = extern struct { + s: packed struct(ULONG64) { + Type: TYPE, + Reserved: u56, + }, + u: extern union { + ULong64: ULONG64, + Pointer: PVOID, + Size: SIZE_T, + Handle: HANDLE, + ULong: ULONG, + }, + + pub const TYPE = enum(u8) { + InvalidType = 0, + AddressRequirements, + NumaNode, + PartitionHandle, + UserPhysicalHandle, + AttributeFlags, + ImageMachine, + _, + + pub const Max: @typeInfo(@This()).@"enum".tag_type = @typeInfo(@This()).@"enum".fields.len; + }; + }; +}; + +pub const SEC = packed struct(ULONG) { + Reserved0: u17 = 0, + HUGE_PAGES: bool = false, + PARTITION_OWNER_HANDLE: bool = false, + @"64K_PAGES": bool = false, + Reserved19: u3 = 0, + FILE: bool = false, + IMAGE: bool = false, + PROTECTED_IMAGE: bool = false, + RESERVE: bool = false, + COMMIT: bool = false, + NOCACHE: bool = false, + Reserved29: u1 = 0, + WRITECOMBINE: bool = false, + LARGE_PAGES: bool = false, + + pub const IMAGE_NO_EXECUTE: SEC = .{ + .IMAGE = true, + .NOCACHE = true, + }; +}; + +pub const ERESOURCE = opaque {}; + +// ref: shared/ntdef.h + +pub const EVENT_TYPE = enum(c_int) { + Notification, + Synchronization, +}; + +pub const TIMER_TYPE = enum(c_int) { + Notification, + Synchronization, +}; + +pub const WAIT_TYPE = enum(c_int) { + All, + Any, +}; + +pub const LOGICAL = ULONG; + +pub const NTSTATUS = @import("windows/ntstatus.zig").NTSTATUS; + +// ref: um/heapapi.h + +pub fn GetProcessHeap() ?*HEAP { + return peb().ProcessHeap; +} + +// ref: um/winternl.h + +pub const OBJECT_ATTRIBUTES = extern struct { + Length: ULONG, + RootDirectory: ?HANDLE, + ObjectName: ?*UNICODE_STRING, + Attributes: ATTRIBUTES, + SecurityDescriptor: ?*anyopaque, + SecurityQualityOfService: ?*anyopaque, + + // Valid values for the Attributes field + pub const ATTRIBUTES = packed struct(ULONG) { + Reserved0: u1 = 0, + INHERIT: bool = false, + Reserved2: u2 = 0, + PERMANENT: bool = false, + EXCLUSIVE: bool = false, + /// If name-lookup code should ignore the case of the ObjectName member rather than performing an exact-match search. + CASE_INSENSITIVE: bool = true, + OPENIF: bool = false, + OPENLINK: bool = false, + KERNEL_HANDLE: bool = false, + FORCE_ACCESS_CHECK: bool = false, + IGNORE_IMPERSONATED_DEVICEMAP: bool = false, + DONT_REPARSE: bool = false, + Reserved13: u19 = 0, + + pub const VALID_ATTRIBUTES: ATTRIBUTES = .{ + .INHERIT = true, + .PERMANENT = true, + .EXCLUSIVE = true, + .CASE_INSENSITIVE = true, + .OPENIF = true, + .OPENLINK = true, + .KERNEL_HANDLE = true, + .FORCE_ACCESS_CHECK = true, + .IGNORE_IMPERSONATED_DEVICEMAP = true, + .DONT_REPARSE = true, + }; + }; +}; + +// ref none pub const OpenError = error{ IsDir, @@ -46,25 +2309,24 @@ pub const OpenError = error{ NetworkNotFound, AntivirusInterference, BadPathName, + OperationCanceled, }; pub const OpenFileOptions = struct { access_mask: ACCESS_MASK, dir: ?HANDLE = null, sa: ?*SECURITY_ATTRIBUTES = null, - share_access: ULONG = FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, - creation: ULONG, - /// If true, tries to open path as a directory. - /// Defaults to false. - filter: Filter = .file_only, + share_access: FILE.SHARE = .VALID_FLAGS, + creation: FILE.CREATE_DISPOSITION, + filter: Filter = .non_directory_only, /// If false, tries to open path as a reparse point without dereferencing it. /// Defaults to true. follow_symlinks: bool = true, pub const Filter = enum { /// Causes `OpenFile` to return `error.IsDir` if the opened handle would be a directory. - file_only, - /// Causes `OpenFile` to return `error.NotDir` if the opened handle would be a file. + non_directory_only, + /// Causes `OpenFile` to return `error.NotDir` if the opened handle is not a directory. dir_only, /// `OpenFile` does not discriminate between opening files and directories. any, @@ -72,42 +2334,32 @@ pub const OpenFileOptions = struct { }; pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HANDLE { - if (mem.eql(u16, sub_path_w, &[_]u16{'.'}) and options.filter == .file_only) { + if (mem.eql(u16, sub_path_w, &[_]u16{'.'}) and options.filter == .non_directory_only) { return error.IsDir; } - if (mem.eql(u16, sub_path_w, &[_]u16{ '.', '.' }) and options.filter == .file_only) { + if (mem.eql(u16, sub_path_w, &[_]u16{ '.', '.' }) and options.filter == .non_directory_only) { return error.IsDir; } var result: HANDLE = undefined; const path_len_bytes = math.cast(u16, sub_path_w.len * 2) orelse return error.NameTooLong; - var nt_name = UNICODE_STRING{ + var nt_name: UNICODE_STRING = .{ .Length = path_len_bytes, .MaximumLength = path_len_bytes, .Buffer = @constCast(sub_path_w.ptr), }; - var attr = OBJECT_ATTRIBUTES{ + const attr: OBJECT_ATTRIBUTES = .{ .Length = @sizeOf(OBJECT_ATTRIBUTES), .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else options.dir, - .Attributes = if (options.sa) |ptr| blk: { // Note we do not use OBJ_CASE_INSENSITIVE here. - const inherit: ULONG = if (ptr.bInheritHandle == TRUE) OBJ_INHERIT else 0; - break :blk inherit; - } else 0, + .Attributes = .{ + .INHERIT = if (options.sa) |sa| sa.bInheritHandle != FALSE else false, + }, .ObjectName = &nt_name, .SecurityDescriptor = if (options.sa) |ptr| ptr.lpSecurityDescriptor else null, .SecurityQualityOfService = null, }; var io: IO_STATUS_BLOCK = undefined; - const blocking_flag: ULONG = FILE_SYNCHRONOUS_IO_NONALERT; - const file_or_dir_flag: ULONG = switch (options.filter) { - .file_only => FILE_NON_DIRECTORY_FILE, - .dir_only => FILE_DIRECTORY_FILE, - .any => 0, - }; - // If we're not following symlinks, we need to ensure we don't pass in any synchronization flags such as FILE_SYNCHRONOUS_IO_NONALERT. - const flags: ULONG = if (options.follow_symlinks) file_or_dir_flag | blocking_flag else file_or_dir_flag | FILE_OPEN_REPARSE_POINT; - while (true) { const rc = ntdll.NtCreateFile( &result, @@ -115,10 +2367,15 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN &attr, &io, null, - FILE_ATTRIBUTE_NORMAL, + .{ .NORMAL = true }, options.share_access, options.creation, - flags, + .{ + .DIRECTORY_FILE = options.filter == .dir_only, + .NON_DIRECTORY_FILE = options.filter == .non_directory_only, + .IO = if (options.follow_symlinks) .SYNCHRONOUS_NONALERT else .ASYNCHRONOUS, + .OPEN_REPARSE_POINT = !options.follow_symlinks, + }, null, 0, ); @@ -152,6 +2409,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN continue; }, .VIRUS_INFECTED, .VIRUS_DELETED => return error.AntivirusInterference, + .CANCELLED => return error.OperationCanceled, else => return unexpectedStatus(rc), } } @@ -201,16 +2459,16 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C const dev_handle = opt_dev_handle orelse blk: { const str = std.unicode.utf8ToUtf16LeStringLiteral("\\Device\\NamedPipe\\"); const len: u16 = @truncate(str.len * @sizeOf(u16)); - const name = UNICODE_STRING{ + const name: UNICODE_STRING = .{ .Length = len, .MaximumLength = len, .Buffer = @ptrCast(@constCast(str)), }; - const attrs = OBJECT_ATTRIBUTES{ + const attrs: OBJECT_ATTRIBUTES = .{ .ObjectName = @constCast(&name), .Length = @sizeOf(OBJECT_ATTRIBUTES), .RootDirectory = null, - .Attributes = 0, + .Attributes = .{}, .SecurityDescriptor = null, .SecurityQualityOfService = null, }; @@ -219,14 +2477,17 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C var handle: HANDLE = undefined; switch (ntdll.NtCreateFile( &handle, - GENERIC_READ | SYNCHRONIZE, + .{ + .STANDARD = .{ .SYNCHRONIZE = true }, + .GENERIC = .{ .READ = true }, + }, @constCast(&attrs), &iosb, null, - 0, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - FILE_OPEN, - FILE_SYNCHRONOUS_IO_NONALERT, + .{}, + .VALID_FLAGS, + .OPEN, + .{ .IO = .SYNCHRONOUS_NONALERT }, null, 0, )) { @@ -242,16 +2503,15 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C } else break :blk handle; }; - const name = UNICODE_STRING{ .Buffer = null, .Length = 0, .MaximumLength = 0 }; - var attrs = OBJECT_ATTRIBUTES{ + const name: UNICODE_STRING = .{ .Buffer = null, .Length = 0, .MaximumLength = 0 }; + var attrs: OBJECT_ATTRIBUTES = .{ .ObjectName = @constCast(&name), .Length = @sizeOf(OBJECT_ATTRIBUTES), .RootDirectory = dev_handle, - .Attributes = OBJ_CASE_INSENSITIVE, + .Attributes = .{ .INHERIT = sattr.bInheritHandle != FALSE }, .SecurityDescriptor = sattr.lpSecurityDescriptor, .SecurityQualityOfService = null, }; - if (sattr.bInheritHandle != 0) attrs.Attributes |= OBJ_INHERIT; // 120 second relative timeout in 100ns units. const default_timeout: LARGE_INTEGER = (-120 * std.time.ns_per_s) / 100; @@ -259,15 +2519,21 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C var read: HANDLE = undefined; switch (ntdll.NtCreateNamedPipeFile( &read, - GENERIC_READ | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE, + .{ + .SPECIFIC = .{ .FILE_PIPE = .{ + .WRITE_ATTRIBUTES = true, + } }, + .STANDARD = .{ .SYNCHRONIZE = true }, + .GENERIC = .{ .READ = true }, + }, &attrs, &iosb, - FILE_SHARE_READ | FILE_SHARE_WRITE, - FILE_CREATE, - FILE_SYNCHRONOUS_IO_NONALERT, - FILE_PIPE_BYTE_STREAM_TYPE, - FILE_PIPE_BYTE_STREAM_MODE, - FILE_PIPE_QUEUE_OPERATION, + .{ .READ = true, .WRITE = true }, + .CREATE, + .{ .IO = .SYNCHRONOUS_NONALERT }, + .{ .TYPE = .BYTE_STREAM }, + .{ .MODE = .BYTE_STREAM }, + .{ .OPERATION = .QUEUE }, 1, 4096, 4096, @@ -285,14 +2551,23 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C var write: HANDLE = undefined; switch (ntdll.NtCreateFile( &write, - GENERIC_WRITE | SYNCHRONIZE | FILE_READ_ATTRIBUTES, + .{ + .SPECIFIC = .{ .FILE_PIPE = .{ + .READ_ATTRIBUTES = true, + } }, + .STANDARD = .{ .SYNCHRONIZE = true }, + .GENERIC = .{ .WRITE = true }, + }, &attrs, &iosb, null, - 0, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - FILE_OPEN, - FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE, + .{}, + .VALID_FLAGS, + .OPEN, + .{ + .IO = .SYNCHRONOUS_NONALERT, + .NON_DIRECTORY_FILE = true, + }, null, 0, )) { @@ -306,71 +2581,49 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C wr.* = write; } -pub const DeviceIoControlError = error{ - AccessDenied, - /// The volume does not contain a recognized file system. File system - /// drivers might not be loaded, or the volume may be corrupt. - UnrecognizedVolume, - Unexpected, -}; - /// A Zig wrapper around `NtDeviceIoControlFile` and `NtFsControlFile` syscalls. /// It implements similar behavior to `DeviceIoControl` and is meant to serve /// as a direct substitute for that call. /// TODO work out if we need to expose other arguments to the underlying syscalls. pub fn DeviceIoControl( - h: HANDLE, - ioControlCode: ULONG, - in: ?[]const u8, - out: ?[]u8, -) DeviceIoControlError!void { - // Logic from: https://doxygen.reactos.org/d3/d74/deviceio_8c.html - const is_fsctl = (ioControlCode >> 16) == FILE_DEVICE_FILE_SYSTEM; - - var io: IO_STATUS_BLOCK = undefined; - const in_ptr = if (in) |i| i.ptr else null; - const in_len = if (in) |i| @as(ULONG, @intCast(i.len)) else 0; - const out_ptr = if (out) |o| o.ptr else null; - const out_len = if (out) |o| @as(ULONG, @intCast(o.len)) else 0; - - const rc = blk: { - if (is_fsctl) { - break :blk ntdll.NtFsControlFile( - h, - null, - null, - null, - &io, - ioControlCode, - in_ptr, - in_len, - out_ptr, - out_len, - ); - } else { - break :blk ntdll.NtDeviceIoControlFile( - h, - null, - null, - null, - &io, - ioControlCode, - in_ptr, - in_len, - out_ptr, - out_len, - ); - } + device: HANDLE, + io_control_code: CTL_CODE, + opts: struct { + event: ?HANDLE = null, + apc_routine: ?*const IO_APC_ROUTINE = null, + apc_context: ?*anyopaque = null, + io_status_block: ?*IO_STATUS_BLOCK = null, + in: []const u8 = &.{}, + out: []u8 = &.{}, + }, +) NTSTATUS { + var io_status_block: IO_STATUS_BLOCK = undefined; + return switch (io_control_code.DeviceType) { + .FILE_SYSTEM, .NAMED_PIPE => ntdll.NtFsControlFile( + device, + opts.event, + opts.apc_routine, + opts.apc_context, + opts.io_status_block orelse &io_status_block, + io_control_code, + if (opts.in.len > 0) opts.in.ptr else null, + @intCast(opts.in.len), + if (opts.out.len > 0) opts.out.ptr else null, + @intCast(opts.out.len), + ), + else => ntdll.NtDeviceIoControlFile( + device, + opts.event, + opts.apc_routine, + opts.apc_context, + opts.io_status_block orelse &io_status_block, + io_control_code, + if (opts.in.len > 0) opts.in.ptr else null, + @intCast(opts.in.len), + if (opts.out.len > 0) opts.out.ptr else null, + @intCast(opts.out.len), + ), }; - switch (rc) { - .SUCCESS => {}, - .PRIVILEGE_NOT_HELD => return error.AccessDenied, - .ACCESS_DENIED => return error.AccessDenied, - .INVALID_DEVICE_REQUEST => return error.AccessDenied, // Not supported by the underlying filesystem - .INVALID_PARAMETER => unreachable, - .UNRECOGNIZED_VOLUME => return error.UnrecognizedVolume, - else => return unexpectedStatus(rc), - } } pub fn GetOverlappedResult(h: HANDLE, overlapped: *OVERLAPPED, wait: bool) !DWORD { @@ -394,33 +2647,6 @@ pub fn SetHandleInformation(h: HANDLE, mask: DWORD, flags: DWORD) SetHandleInfor } } -pub const RtlGenRandomError = error{ - /// `RtlGenRandom` has been known to fail in situations where the system is under heavy load. - /// Unfortunately, it does not call `SetLastError`, so it is not possible to get more specific - /// error information; it could actually be due to an out-of-memory condition, for example. - SystemResources, -}; - -/// Call RtlGenRandom() instead of CryptGetRandom() on Windows -/// https://github.com/rust-lang-nursery/rand/issues/111 -/// https://bugzilla.mozilla.org/show_bug.cgi?id=504270 -pub fn RtlGenRandom(output: []u8) RtlGenRandomError!void { - var total_read: usize = 0; - var buff: []u8 = output[0..]; - const max_read_size: ULONG = maxInt(ULONG); - - while (total_read < output.len) { - const to_read: ULONG = @min(buff.len, max_read_size); - - if (advapi32.RtlGenRandom(buff.ptr, to_read) == 0) { - return error.SystemResources; - } - - total_read += to_read; - buff = buff[to_read..]; - } -} - pub const WaitForSingleObjectError = error{ WaitAbandoned, WaitTimeOut, @@ -572,157 +2798,14 @@ pub fn GetQueuedCompletionStatusEx( .HANDLE_EOF => error.EOF, .WAIT_TIMEOUT => error.Timeout, else => |err| unexpectedError(err), - }; - } - - return num_entries_removed; -} - -pub fn CloseHandle(hObject: HANDLE) void { - assert(ntdll.NtClose(hObject) == .SUCCESS); -} - -pub const ReadFileError = error{ - BrokenPipe, - /// The specified network name is no longer available. - ConnectionResetByPeer, - Canceled, - /// Unable to read file due to lock. - LockViolation, - /// Known to be possible when: - /// - Unable to read from disconnected virtual com port (Windows) - AccessDenied, - NotOpenForReading, - Unexpected, -}; - -/// If buffer's length exceeds what a Windows DWORD integer can hold, it will be broken into -/// multiple non-atomic reads. -pub fn ReadFile(in_hFile: HANDLE, buffer: []u8, offset: ?u64) ReadFileError!usize { - while (true) { - const want_read_count: DWORD = @min(@as(DWORD, maxInt(DWORD)), buffer.len); - var amt_read: DWORD = undefined; - var overlapped_data: OVERLAPPED = undefined; - const overlapped: ?*OVERLAPPED = if (offset) |off| blk: { - overlapped_data = .{ - .Internal = 0, - .InternalHigh = 0, - .DUMMYUNIONNAME = .{ - .DUMMYSTRUCTNAME = .{ - .Offset = @as(u32, @truncate(off)), - .OffsetHigh = @as(u32, @truncate(off >> 32)), - }, - }, - .hEvent = null, - }; - break :blk &overlapped_data; - } else null; - if (kernel32.ReadFile(in_hFile, buffer.ptr, want_read_count, &amt_read, overlapped) == 0) { - switch (GetLastError()) { - .IO_PENDING => unreachable, - .OPERATION_ABORTED => continue, - .BROKEN_PIPE => return 0, - .HANDLE_EOF => return 0, - .NETNAME_DELETED => return error.ConnectionResetByPeer, - .LOCK_VIOLATION => return error.LockViolation, - .ACCESS_DENIED => return error.AccessDenied, - .INVALID_HANDLE => return error.NotOpenForReading, - else => |err| return unexpectedError(err), - } - } - return amt_read; - } -} - -pub const WriteFileError = error{ - SystemResources, - Canceled, - BrokenPipe, - NotOpenForWriting, - /// The process cannot access the file because another process has locked - /// a portion of the file. - LockViolation, - /// The specified network name is no longer available. - ConnectionResetByPeer, - /// Known to be possible when: - /// - Unable to write to disconnected virtual com port (Windows) - AccessDenied, - Unexpected, -}; - -pub fn WriteFile( - handle: HANDLE, - bytes: []const u8, - offset: ?u64, -) WriteFileError!usize { - var bytes_written: DWORD = undefined; - var overlapped_data: OVERLAPPED = undefined; - const overlapped: ?*OVERLAPPED = if (offset) |off| blk: { - overlapped_data = .{ - .Internal = 0, - .InternalHigh = 0, - .DUMMYUNIONNAME = .{ - .DUMMYSTRUCTNAME = .{ - .Offset = @truncate(off), - .OffsetHigh = @truncate(off >> 32), - }, - }, - .hEvent = null, - }; - break :blk &overlapped_data; - } else null; - const adjusted_len = math.cast(u32, bytes.len) orelse maxInt(u32); - if (kernel32.WriteFile(handle, bytes.ptr, adjusted_len, &bytes_written, overlapped) == 0) { - switch (GetLastError()) { - .INVALID_USER_BUFFER => return error.SystemResources, - .NOT_ENOUGH_MEMORY => return error.SystemResources, - .OPERATION_ABORTED => return error.Canceled, - .NOT_ENOUGH_QUOTA => return error.SystemResources, - .IO_PENDING => unreachable, - .NO_DATA => return error.BrokenPipe, - .INVALID_HANDLE => return error.NotOpenForWriting, - .LOCK_VIOLATION => return error.LockViolation, - .NETNAME_DELETED => return error.ConnectionResetByPeer, - .ACCESS_DENIED => return error.AccessDenied, - .WORKING_SET_QUOTA => return error.SystemResources, - else => |err| return unexpectedError(err), - } - } - return bytes_written; -} - -pub const SetCurrentDirectoryError = error{ - NameTooLong, - FileNotFound, - NotDir, - AccessDenied, - NoDevice, - BadPathName, - Unexpected, -}; - -pub fn SetCurrentDirectory(path_name: []const u16) SetCurrentDirectoryError!void { - const path_len_bytes = math.cast(u16, path_name.len * 2) orelse return error.NameTooLong; + }; + } - var nt_name = UNICODE_STRING{ - .Length = path_len_bytes, - .MaximumLength = path_len_bytes, - .Buffer = @constCast(path_name.ptr), - }; + return num_entries_removed; +} - const rc = ntdll.RtlSetCurrentDirectory_U(&nt_name); - switch (rc) { - .SUCCESS => {}, - .OBJECT_NAME_INVALID => return error.BadPathName, - .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, - .OBJECT_PATH_NOT_FOUND => return error.FileNotFound, - .NO_MEDIA_IN_DEVICE => return error.NoDevice, - .INVALID_PARAMETER => unreachable, - .ACCESS_DENIED => return error.AccessDenied, - .OBJECT_PATH_SYNTAX_BAD => unreachable, - .NOT_A_DIRECTORY => return error.NotDir, - else => return unexpectedStatus(rc), - } +pub fn CloseHandle(hObject: HANDLE) void { + assert(ntdll.NtClose(hObject) == .SUCCESS); } pub const GetCurrentDirectoryError = error{ @@ -761,9 +2844,6 @@ pub const CreateSymbolicLinkError = error{ NoDevice, NetworkNotFound, BadPathName, - /// The volume does not contain a recognized file system. File system - /// drivers might not be loaded, or the volume may be corrupt. - UnrecognizedVolume, Unexpected, }; @@ -780,7 +2860,7 @@ pub fn CreateSymbolicLink( is_directory: bool, ) CreateSymbolicLinkError!void { const SYMLINK_DATA = extern struct { - ReparseTag: ULONG, + ReparseTag: IO_REPARSE_TAG, ReparseDataLength: USHORT, Reserved: USHORT, SubstituteNameOffset: USHORT, @@ -791,10 +2871,13 @@ pub fn CreateSymbolicLink( }; const symlink_handle = OpenFile(sym_link_path, .{ - .access_mask = SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE, + .access_mask = .{ + .STANDARD = .{ .SYNCHRONIZE = true }, + .GENERIC = .{ .WRITE = true, .READ = true }, + }, .dir = dir, - .creation = FILE_CREATE, - .filter = if (is_directory) .dir_only else .file_only, + .creation = .CREATE, + .filter = if (is_directory) .dir_only else .non_directory_only, }) catch |err| switch (err) { error.IsDir => return error.PathAlreadyExists, error.NotDir => return error.Unexpected, @@ -820,7 +2903,7 @@ pub fn CreateSymbolicLink( // Already an NT path, no need to do anything to it break :target_path target_path; } else { - switch (getWin32PathType(u16, target_path)) { + switch (std.fs.path.getWin32PathType(u16, target_path)) { // Rooted paths need to avoid getting put through wToPrefixedFileW // (and they are treated as relative in this context) // Note: It seems that rooted paths in symbolic links are relative to @@ -845,8 +2928,8 @@ pub fn CreateSymbolicLink( const buf_len = @sizeOf(SYMLINK_DATA) + final_target_path.len * 4; const header_len = @sizeOf(ULONG) + @sizeOf(USHORT) * 2; const target_is_absolute = std.fs.path.isAbsoluteWindowsWtf16(final_target_path); - const symlink_data = SYMLINK_DATA{ - .ReparseTag = IO_REPARSE_TAG_SYMLINK, + const symlink_data: SYMLINK_DATA = .{ + .ReparseTag = .SYMLINK, .ReparseDataLength = @intCast(buf_len - header_len), .Reserved = 0, .SubstituteNameOffset = @intCast(final_target_path.len * 2), @@ -860,7 +2943,14 @@ pub fn CreateSymbolicLink( @memcpy(buffer[@sizeOf(SYMLINK_DATA)..][0 .. final_target_path.len * 2], @as([*]const u8, @ptrCast(final_target_path))); const paths_start = @sizeOf(SYMLINK_DATA) + final_target_path.len * 2; @memcpy(buffer[paths_start..][0 .. final_target_path.len * 2], @as([*]const u8, @ptrCast(final_target_path))); - _ = try DeviceIoControl(symlink_handle, FSCTL_SET_REPARSE_POINT, buffer[0..buf_len], null); + const rc = DeviceIoControl(symlink_handle, FSCTL.SET_REPARSE_POINT, .{ .in = buffer[0..buf_len] }); + switch (rc) { + .SUCCESS => {}, + .PRIVILEGE_NOT_HELD => return error.AccessDenied, + .ACCESS_DENIED => return error.AccessDenied, + .INVALID_DEVICE_REQUEST => return error.AccessDenied, // Not supported by the underlying filesystem + else => return unexpectedStatus(rc), + } } pub const ReadLinkError = error{ @@ -872,15 +2962,22 @@ pub const ReadLinkError = error{ BadPathName, AntivirusInterference, UnsupportedReparsePointType, + NotLink, + OperationCanceled, }; /// `sub_path_w` will never be accessed after `out_buffer` has been written to, so it /// is safe to reuse a single buffer for both. pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u16) ReadLinkError![]u16 { const result_handle = OpenFile(sub_path_w, .{ - .access_mask = FILE_READ_ATTRIBUTES | SYNCHRONIZE, + .access_mask = .{ + .SPECIFIC = .{ .FILE = .{ + .READ_ATTRIBUTES = true, + } }, + .STANDARD = .{ .SYNCHRONIZE = true }, + }, .dir = dir, - .creation = FILE_OPEN, + .creation = .OPEN, .follow_symlinks = false, .filter = .any, }) catch |err| switch (err) { @@ -894,15 +2991,18 @@ pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u16) ReadLi defer CloseHandle(result_handle); var reparse_buf: [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 align(@alignOf(REPARSE_DATA_BUFFER)) = undefined; - _ = DeviceIoControl(result_handle, FSCTL_GET_REPARSE_POINT, null, reparse_buf[0..]) catch |err| switch (err) { - error.AccessDenied => return error.Unexpected, - error.UnrecognizedVolume => return error.Unexpected, - else => |e| return e, - }; + const rc = DeviceIoControl(result_handle, FSCTL.GET_REPARSE_POINT, .{ .out = reparse_buf[0..] }); + switch (rc) { + .SUCCESS => {}, + .CANCELLED => return error.OperationCanceled, + .NOT_A_REPARSE_POINT => return error.NotLink, + else => return unexpectedStatus(rc), + } const reparse_struct: *const REPARSE_DATA_BUFFER = @ptrCast(@alignCast(&reparse_buf[0])); - switch (reparse_struct.ReparseTag) { - IO_REPARSE_TAG_SYMLINK => { + const IoReparseTagInt = @typeInfo(IO_REPARSE_TAG).@"struct".backing_integer.?; + switch (@as(IoReparseTagInt, @bitCast(reparse_struct.ReparseTag))) { + @as(IoReparseTagInt, @bitCast(IO_REPARSE_TAG.SYMLINK)) => { const buf: *const SYMBOLIC_LINK_REPARSE_BUFFER = @ptrCast(@alignCast(&reparse_struct.DataBuffer[0])); const offset = buf.SubstituteNameOffset >> 1; const len = buf.SubstituteNameLength >> 1; @@ -910,16 +3010,14 @@ pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u16) ReadLi const is_relative = buf.Flags & SYMLINK_FLAG_RELATIVE != 0; return parseReadLinkPath(path_buf[offset..][0..len], is_relative, out_buffer); }, - IO_REPARSE_TAG_MOUNT_POINT => { + @as(IoReparseTagInt, @bitCast(IO_REPARSE_TAG.MOUNT_POINT)) => { const buf: *const MOUNT_POINT_REPARSE_BUFFER = @ptrCast(@alignCast(&reparse_struct.DataBuffer[0])); const offset = buf.SubstituteNameOffset >> 1; const len = buf.SubstituteNameLength >> 1; const path_buf = @as([*]const u16, &buf.PathBuffer); return parseReadLinkPath(path_buf[offset..][0..len], false, out_buffer); }, - else => { - return error.UnsupportedReparsePointType; - }, + else => return error.UnsupportedReparsePointType, } } @@ -956,13 +3054,8 @@ pub const DeleteFileOptions = struct { }; pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFileError!void { - const create_options_flags: ULONG = if (options.remove_dir) - FILE_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT - else - FILE_NON_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT; // would we ever want to delete the target instead? - const path_len_bytes = @as(u16, @intCast(sub_path_w.len * 2)); - var nt_name = UNICODE_STRING{ + var nt_name: UNICODE_STRING = .{ .Length = path_len_bytes, .MaximumLength = path_len_bytes, // The Windows API makes this mutable, but it will not mutate here. @@ -978,26 +3071,32 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil return error.FileBusy; } - var attr = OBJECT_ATTRIBUTES{ - .Length = @sizeOf(OBJECT_ATTRIBUTES), - .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else options.dir, - .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. - .ObjectName = &nt_name, - .SecurityDescriptor = null, - .SecurityQualityOfService = null, - }; var io: IO_STATUS_BLOCK = undefined; var tmp_handle: HANDLE = undefined; var rc = ntdll.NtCreateFile( &tmp_handle, - SYNCHRONIZE | DELETE, - &attr, + .{ .STANDARD = .{ + .RIGHTS = .{ .DELETE = true }, + .SYNCHRONIZE = true, + } }, + &.{ + .Length = @sizeOf(OBJECT_ATTRIBUTES), + .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else options.dir, + .Attributes = .{}, + .ObjectName = &nt_name, + .SecurityDescriptor = null, + .SecurityQualityOfService = null, + }, &io, null, - 0, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - FILE_OPEN, - create_options_flags, + .{}, + .VALID_FLAGS, + .OPEN, + .{ + .DIRECTORY_FILE = options.remove_dir, + .NON_DIRECTORY_FILE = !options.remove_dir, + .OPEN_REPARSE_POINT = true, // would we ever want to delete the target instead? + }, null, 0, ); @@ -1031,18 +3130,17 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil // FileDispositionInformation if the return value lets us know that some aspect of it is not supported. const need_fallback = need_fallback: { // Deletion with posix semantics if the filesystem supports it. - var info = FILE_DISPOSITION_INFORMATION_EX{ - .Flags = FILE_DISPOSITION_DELETE | - FILE_DISPOSITION_POSIX_SEMANTICS | - FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE, - }; - + const info: FILE.DISPOSITION.INFORMATION.EX = .{ .Flags = .{ + .DELETE = true, + .POSIX_SEMANTICS = true, + .IGNORE_READONLY_ATTRIBUTE = true, + } }; rc = ntdll.NtSetInformationFile( tmp_handle, &io, &info, - @sizeOf(FILE_DISPOSITION_INFORMATION_EX), - .FileDispositionInformationEx, + @sizeOf(FILE.DISPOSITION.INFORMATION.EX), + .DispositionEx, ); switch (rc) { .SUCCESS => return, @@ -1061,16 +3159,15 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil if (need_fallback) { // Deletion with file pending semantics, which requires waiting or moving // files to get them removed (from here). - var file_dispo = FILE_DISPOSITION_INFORMATION{ + const file_dispo: FILE.DISPOSITION.INFORMATION = .{ .DeleteFile = TRUE, }; - rc = ntdll.NtSetInformationFile( tmp_handle, &io, &file_dispo, - @sizeOf(FILE_DISPOSITION_INFORMATION), - .FileDispositionInformation, + @sizeOf(FILE.DISPOSITION.INFORMATION), + .Disposition, ); } switch (rc) { @@ -1097,7 +3194,7 @@ pub const RenameError = error{ NetworkNotFound, AntivirusInterference, BadPathName, - RenameAcrossMountPoints, + CrossDevice, } || UnexpectedError; pub fn RenameFile( @@ -1112,8 +3209,14 @@ pub fn RenameFile( ) RenameError!void { const src_fd = OpenFile(old_path_w, .{ .dir = old_dir_fd, - .access_mask = SYNCHRONIZE | GENERIC_WRITE | DELETE, - .creation = FILE_OPEN, + .access_mask = .{ + .STANDARD = .{ + .RIGHTS = .{ .DELETE = true }, + .SYNCHRONIZE = true, + }, + .GENERIC = .{ .WRITE = true }, + }, + .creation = .OPEN, .filter = .any, // This function is supposed to rename both files and directories. .follow_symlinks = false, }) catch |err| switch (err) { @@ -1135,29 +3238,23 @@ pub fn RenameFile( // The strategy here is just to try using FileRenameInformationEx and fall back to // FileRenameInformation if the return value lets us know that some aspect of it is not supported. const need_fallback = need_fallback: { - const struct_buf_len = @sizeOf(FILE_RENAME_INFORMATION_EX) + (PATH_MAX_WIDE * 2); - var rename_info_buf: [struct_buf_len]u8 align(@alignOf(FILE_RENAME_INFORMATION_EX)) = undefined; - const struct_len = @sizeOf(FILE_RENAME_INFORMATION_EX) + new_path_w.len * 2; - if (struct_len > struct_buf_len) return error.NameTooLong; - - const rename_info: *FILE_RENAME_INFORMATION_EX = @ptrCast(&rename_info_buf); - var io_status_block: IO_STATUS_BLOCK = undefined; - - var flags: ULONG = FILE_RENAME_POSIX_SEMANTICS | FILE_RENAME_IGNORE_READONLY_ATTRIBUTE; - if (replace_if_exists) flags |= FILE_RENAME_REPLACE_IF_EXISTS; - rename_info.* = .{ - .Flags = flags, + const rename_info: FILE.RENAME_INFORMATION = .init(.{ + .Flags = .{ + .REPLACE_IF_EXISTS = replace_if_exists, + .POSIX_SEMANTICS = true, + .IGNORE_READONLY_ATTRIBUTE = true, + }, .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(new_path_w)) null else new_dir_fd, - .FileNameLength = @intCast(new_path_w.len * 2), // already checked error.NameTooLong - .FileName = undefined, - }; - @memcpy((&rename_info.FileName).ptr, new_path_w); + .FileName = new_path_w, + }); + var io_status_block: IO_STATUS_BLOCK = undefined; + const rename_info_buf = rename_info.toBuffer(); rc = ntdll.NtSetInformationFile( src_fd, &io_status_block, - rename_info, - @intCast(struct_len), // already checked for error.NameTooLong - .FileRenameInformationEx, + rename_info_buf.ptr, + @intCast(rename_info_buf.len), // already checked for error.NameTooLong + .RenameEx, ); switch (rc) { .SUCCESS => return, @@ -1174,28 +3271,19 @@ pub fn RenameFile( }; if (need_fallback) { - const struct_buf_len = @sizeOf(FILE_RENAME_INFORMATION) + (PATH_MAX_WIDE * 2); - var rename_info_buf: [struct_buf_len]u8 align(@alignOf(FILE_RENAME_INFORMATION)) = undefined; - const struct_len = @sizeOf(FILE_RENAME_INFORMATION) + new_path_w.len * 2; - if (struct_len > struct_buf_len) return error.NameTooLong; - - const rename_info: *FILE_RENAME_INFORMATION = @ptrCast(&rename_info_buf); - var io_status_block: IO_STATUS_BLOCK = undefined; - - rename_info.* = .{ - .Flags = @intFromBool(replace_if_exists), + const rename_info: FILE.RENAME_INFORMATION = .init(.{ + .Flags = .{ .REPLACE_IF_EXISTS = replace_if_exists }, .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(new_path_w)) null else new_dir_fd, - .FileNameLength = @intCast(new_path_w.len * 2), // already checked error.NameTooLong - .FileName = undefined, - }; - @memcpy((&rename_info.FileName).ptr, new_path_w); - + .FileName = new_path_w, + }); + var io_status_block: IO_STATUS_BLOCK = undefined; + const rename_info_buf = rename_info.toBuffer(); rc = ntdll.NtSetInformationFile( src_fd, &io_status_block, - rename_info, - @intCast(struct_len), // already checked for error.NameTooLong - .FileRenameInformation, + rename_info_buf.ptr, + @intCast(rename_info_buf.len), // already checked for error.NameTooLong + .Rename, ); } @@ -1207,7 +3295,7 @@ pub fn RenameFile( .ACCESS_DENIED => return error.AccessDenied, .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, .OBJECT_PATH_NOT_FOUND => return error.FileNotFound, - .NOT_SAME_DEVICE => return error.RenameAcrossMountPoints, + .NOT_SAME_DEVICE => return error.CrossDevice, .OBJECT_NAME_COLLISION => return error.PathAlreadyExists, .DIRECTORY_NOT_EMPTY => return error.PathAlreadyExists, .FILE_IS_A_DIRECTORY => return error.IsDir, @@ -1231,71 +3319,6 @@ pub fn GetStdHandle(handle_id: DWORD) GetStdHandleError!HANDLE { return handle; } -pub const SetFilePointerError = error{ - Unseekable, - Unexpected, -}; - -/// The SetFilePointerEx function with the `dwMoveMethod` parameter set to `FILE_BEGIN`. -pub fn SetFilePointerEx_BEGIN(handle: HANDLE, offset: u64) SetFilePointerError!void { - // "The starting point is zero or the beginning of the file. If [FILE_BEGIN] - // is specified, then the liDistanceToMove parameter is interpreted as an unsigned value." - // https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-setfilepointerex - const ipos = @as(LARGE_INTEGER, @bitCast(offset)); - if (kernel32.SetFilePointerEx(handle, ipos, null, FILE_BEGIN) == 0) { - switch (GetLastError()) { - .INVALID_FUNCTION => return error.Unseekable, - .NEGATIVE_SEEK => return error.Unseekable, - .INVALID_PARAMETER => unreachable, - .INVALID_HANDLE => unreachable, - else => |err| return unexpectedError(err), - } - } -} - -/// The SetFilePointerEx function with the `dwMoveMethod` parameter set to `FILE_CURRENT`. -pub fn SetFilePointerEx_CURRENT(handle: HANDLE, offset: i64) SetFilePointerError!void { - if (kernel32.SetFilePointerEx(handle, offset, null, FILE_CURRENT) == 0) { - switch (GetLastError()) { - .INVALID_FUNCTION => return error.Unseekable, - .NEGATIVE_SEEK => return error.Unseekable, - .INVALID_PARAMETER => unreachable, - .INVALID_HANDLE => unreachable, - else => |err| return unexpectedError(err), - } - } -} - -/// The SetFilePointerEx function with the `dwMoveMethod` parameter set to `FILE_END`. -pub fn SetFilePointerEx_END(handle: HANDLE, offset: i64) SetFilePointerError!void { - if (kernel32.SetFilePointerEx(handle, offset, null, FILE_END) == 0) { - switch (GetLastError()) { - .INVALID_FUNCTION => return error.Unseekable, - .NEGATIVE_SEEK => return error.Unseekable, - .INVALID_PARAMETER => unreachable, - .INVALID_HANDLE => unreachable, - else => |err| return unexpectedError(err), - } - } -} - -/// The SetFilePointerEx function with parameters to get the current offset. -pub fn SetFilePointerEx_CURRENT_get(handle: HANDLE) SetFilePointerError!u64 { - var result: LARGE_INTEGER = undefined; - if (kernel32.SetFilePointerEx(handle, 0, &result, FILE_CURRENT) == 0) { - switch (GetLastError()) { - .INVALID_FUNCTION => return error.Unseekable, - .NEGATIVE_SEEK => return error.Unseekable, - .INVALID_PARAMETER => unreachable, - .INVALID_HANDLE => unreachable, - else => |err| return unexpectedError(err), - } - } - // Based on the docs for FILE_BEGIN, it seems that the returned signed integer - // should be interpreted as an unsigned integer. - return @as(u64, @bitCast(result)); -} - pub const QueryObjectNameError = error{ AccessDenied, InvalidHandle, @@ -1308,7 +3331,7 @@ pub fn QueryObjectName(handle: HANDLE, out_buffer: []u16) QueryObjectNameError![ const info = @as(*OBJECT_NAME_INFORMATION, @ptrCast(out_buffer_aligned)); // buffer size is specified in bytes - const out_buffer_len = std.math.cast(ULONG, out_buffer_aligned.len * 2) orelse std.math.maxInt(ULONG); + const out_buffer_len = std.math.cast(ULONG, out_buffer_aligned.len * 2) orelse maxInt(ULONG); // last argument would return the length required for full_buffer, not exposed here return switch (ntdll.NtQueryObject(handle, .ObjectNameInformation, info, out_buffer_len, null)) { .SUCCESS => blk: { @@ -1335,7 +3358,7 @@ test QueryObjectName { //any file will do; canonicalization works on NTFS junctions and symlinks, hardlinks remain separate paths. var tmp = std.testing.tmpDir(.{}); defer tmp.cleanup(); - const handle = tmp.dir.fd; + const handle = tmp.dir.handle; var out_buffer: [PATH_MAX_WIDE]u16 = undefined; const result_path = try QueryObjectName(handle, &out_buffer); @@ -1348,7 +3371,6 @@ test QueryObjectName { pub const GetFinalPathNameByHandleError = error{ AccessDenied, - BadPathName, FileNotFound, NameTooLong, /// The volume does not contain a recognized file system. File system @@ -1373,6 +3395,8 @@ pub const GetFinalPathNameByHandleFormat = struct { /// NT or DOS volume name (e.g., `\Device\HarddiskVolume0\foo.txt` versus `C:\foo.txt`). /// If DOS volume name format is selected, note that this function does *not* prepend /// `\\?\` prefix to the resultant path. +/// +/// TODO move this function into std.Io.Threaded and add cancelation checks pub fn GetFinalPathNameByHandle( hFile: HANDLE, fmt: GetFinalPathNameByHandleFormat, @@ -1412,7 +3436,7 @@ pub fn GetFinalPathNameByHandle( }; } - const file_path_begin_index = mem.indexOfPos(u16, final_path, device_prefix.len, &[_]u16{'\\'}) orelse unreachable; + const file_path_begin_index = mem.findPos(u16, final_path, device_prefix.len, &[_]u16{'\\'}) orelse unreachable; const volume_name_u16 = final_path[0..file_path_begin_index]; const device_name_u16 = volume_name_u16[device_prefix.len..]; const file_name_u16 = final_path[file_path_begin_index..]; @@ -1440,9 +3464,8 @@ pub fn GetFinalPathNameByHandle( // This is the NT namespaced version of \\.\MountPointManager const mgmt_path_u16 = std.unicode.utf8ToUtf16LeStringLiteral("\\??\\MountPointManager"); const mgmt_handle = OpenFile(mgmt_path_u16, .{ - .access_mask = SYNCHRONIZE, - .share_access = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - .creation = FILE_OPEN, + .access_mask = .{ .STANDARD = .{ .SYNCHRONIZE = true } }, + .creation = .OPEN, }) catch |err| switch (err) { error.IsDir => return error.Unexpected, error.NotDir => return error.Unexpected, @@ -1453,6 +3476,8 @@ pub fn GetFinalPathNameByHandle( error.WouldBlock => return error.Unexpected, error.NetworkNotFound => return error.Unexpected, error.AntivirusInterference => return error.Unexpected, + error.BadPathName => return error.Unexpected, + error.OperationCanceled => @panic("TODO: better integrate cancelation"), else => |e| return e, }; defer CloseHandle(mgmt_handle); @@ -1462,10 +3487,14 @@ pub fn GetFinalPathNameByHandle( input_struct.DeviceNameLength = @intCast(volume_name_u16.len * 2); @memcpy(input_buf[@sizeOf(MOUNTMGR_MOUNT_POINT)..][0 .. volume_name_u16.len * 2], @as([*]const u8, @ptrCast(volume_name_u16.ptr))); - DeviceIoControl(mgmt_handle, IOCTL_MOUNTMGR_QUERY_POINTS, &input_buf, &output_buf) catch |err| switch (err) { - error.AccessDenied => return error.Unexpected, - else => |e| return e, - }; + { + const rc = DeviceIoControl(mgmt_handle, IOCTL.MOUNTMGR.QUERY_POINTS, .{ .in = &input_buf, .out = &output_buf }); + switch (rc) { + .SUCCESS => {}, + .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, + else => return unexpectedStatus(rc), + } + } const mount_points_struct: *const MOUNTMGR_MOUNT_POINTS = @ptrCast(&output_buf[0]); const mount_points = @as( @@ -1494,9 +3523,7 @@ pub fn GetFinalPathNameByHandle( const total_len = drive_letter.len + file_name_u16.len; // Validate that DOS does not contain any spurious nul bytes. - if (mem.indexOfScalar(u16, out_buffer[0..total_len], 0)) |_| { - return error.BadPathName; - } + assert(mem.findScalar(u16, out_buffer[0..total_len], 0) == null); return out_buffer[0..total_len]; } else if (mountmgrIsVolumeName(symlink)) { @@ -1517,10 +3544,12 @@ pub fn GetFinalPathNameByHandle( vol_input_struct.DeviceNameLength = @intCast(symlink.len * 2); @memcpy(@as([*]WCHAR, &vol_input_struct.DeviceName)[0..symlink.len], symlink); - DeviceIoControl(mgmt_handle, IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH, &vol_input_buf, &vol_output_buf) catch |err| switch (err) { - error.AccessDenied => return error.Unexpected, - else => |e| return e, - }; + const rc = DeviceIoControl(mgmt_handle, IOCTL.MOUNTMGR.QUERY_DOS_VOLUME_PATH, .{ .in = &vol_input_buf, .out = &vol_output_buf }); + switch (rc) { + .SUCCESS => {}, + .UNRECOGNIZED_VOLUME => return error.UnrecognizedVolume, + else => return unexpectedStatus(rc), + } const volume_paths_struct: *const MOUNTMGR_VOLUME_PATHS = @ptrCast(&vol_output_buf[0]); const volume_path = std.mem.sliceTo(@as( [*]const u16, @@ -1544,9 +3573,7 @@ pub fn GetFinalPathNameByHandle( const total_len = volume_path.len + file_name_u16.len; // Validate that DOS does not contain any spurious nul bytes. - if (mem.indexOfScalar(u16, out_buffer[0..total_len], 0)) |_| { - return error.BadPathName; - } + assert(mem.findScalar(u16, out_buffer[0..total_len], 0) == null); return out_buffer[0..total_len]; } @@ -1593,7 +3620,7 @@ test GetFinalPathNameByHandle { //any file will do var tmp = std.testing.tmpDir(.{}); defer tmp.cleanup(); - const handle = tmp.dir.fd; + const handle = tmp.dir.handle; var buffer: [PATH_MAX_WIDE]u16 = undefined; //check with sufficient size @@ -1705,17 +3732,6 @@ pub fn GetModuleFileNameW(hModule: ?HMODULE, buf_ptr: [*]u16, buf_len: DWORD) Ge return buf_ptr[0..rc :0]; } -pub const TerminateProcessError = error{ AccessDenied, Unexpected }; - -pub fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) TerminateProcessError!void { - if (kernel32.TerminateProcess(hProcess, uExitCode) == 0) { - switch (GetLastError()) { - Win32Error.ACCESS_DENIED => return error.AccessDenied, - else => |err| return unexpectedError(err), - } - } -} - pub const NtAllocateVirtualMemoryError = error{ AccessDenied, InvalidParameter, @@ -1758,7 +3774,7 @@ pub fn VirtualProtect(lpAddress: ?LPVOID, dwSize: SIZE_T, flNewProtect: DWORD, l // ntdll takes an extra level of indirection here var addr = lpAddress; var size = dwSize; - switch (ntdll.NtProtectVirtualMemory(self_process_handle, &addr, &size, flNewProtect, lpflOldProtect)) { + switch (ntdll.NtProtectVirtualMemory(GetCurrentProcess(), &addr, &size, flNewProtect, lpflOldProtect)) { .SUCCESS => {}, .INVALID_ADDRESS => return error.InvalidAddress, else => |st| return unexpectedStatus(st), @@ -1868,7 +3884,7 @@ pub fn CreateProcessW( lpThreadAttributes: ?*SECURITY_ATTRIBUTES, bInheritHandles: BOOL, dwCreationFlags: CreateProcessFlags, - lpEnvironment: ?*anyopaque, + lpEnvironment: ?[*:0]u16, lpCurrentDirectory: ?LPCWSTR, lpStartupInfo: *STARTUPINFOW, lpProcessInformation: *PROCESS_INFORMATION, @@ -1994,80 +4010,6 @@ pub fn InitOnceExecuteOnce(InitOnce: *INIT_ONCE, InitFn: INIT_ONCE_FN, Parameter assert(kernel32.InitOnceExecuteOnce(InitOnce, InitFn, Parameter, Context) != 0); } -pub const SetFileTimeError = error{Unexpected}; - -pub fn SetFileTime( - hFile: HANDLE, - lpCreationTime: ?*const FILETIME, - lpLastAccessTime: ?*const FILETIME, - lpLastWriteTime: ?*const FILETIME, -) SetFileTimeError!void { - const rc = kernel32.SetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime); - if (rc == 0) { - switch (GetLastError()) { - else => |err| return unexpectedError(err), - } - } -} - -pub const LockFileError = error{ - SystemResources, - WouldBlock, -} || UnexpectedError; - -pub fn LockFile( - FileHandle: HANDLE, - Event: ?HANDLE, - ApcRoutine: ?*IO_APC_ROUTINE, - ApcContext: ?*anyopaque, - IoStatusBlock: *IO_STATUS_BLOCK, - ByteOffset: *const LARGE_INTEGER, - Length: *const LARGE_INTEGER, - Key: ?*ULONG, - FailImmediately: BOOLEAN, - ExclusiveLock: BOOLEAN, -) !void { - const rc = ntdll.NtLockFile( - FileHandle, - Event, - ApcRoutine, - ApcContext, - IoStatusBlock, - ByteOffset, - Length, - Key, - FailImmediately, - ExclusiveLock, - ); - switch (rc) { - .SUCCESS => return, - .INSUFFICIENT_RESOURCES => return error.SystemResources, - .LOCK_NOT_GRANTED => return error.WouldBlock, - .ACCESS_VIOLATION => unreachable, // bad io_status_block pointer - else => return unexpectedStatus(rc), - } -} - -pub const UnlockFileError = error{ - RangeNotLocked, -} || UnexpectedError; - -pub fn UnlockFile( - FileHandle: HANDLE, - IoStatusBlock: *IO_STATUS_BLOCK, - ByteOffset: *const LARGE_INTEGER, - Length: *const LARGE_INTEGER, - Key: ?*ULONG, -) !void { - const rc = ntdll.NtUnlockFile(FileHandle, IoStatusBlock, ByteOffset, Length, Key); - switch (rc) { - .SUCCESS => return, - .RANGE_NOT_LOCKED => return error.RangeNotLocked, - .ACCESS_VIOLATION => unreachable, // bad io_status_block pointer - else => return unexpectedStatus(rc), - } -} - /// This is a workaround for the C backend until zig has the ability to put /// C code in inline assembly. extern fn zig_thumb_windows_teb() callconv(.c) *anyopaque; @@ -2168,13 +4110,13 @@ pub fn eqlIgnoreCaseWtf16(a: []const u16, b: []const u16) bool { // Use RtlEqualUnicodeString on Windows when not in comptime to avoid including a // redundant copy of the uppercase data. const a_bytes = @as(u16, @intCast(a.len * 2)); - const a_string = UNICODE_STRING{ + const a_string: UNICODE_STRING = .{ .Length = a_bytes, .MaximumLength = a_bytes, .Buffer = @constCast(a.ptr), }; const b_bytes = @as(u16, @intCast(b.len * 2)); - const b_string = UNICODE_STRING{ + const b_string: UNICODE_STRING = .{ .Length = b_bytes, .MaximumLength = b_bytes, .Buffer = @constCast(b.ptr), @@ -2206,7 +4148,7 @@ pub fn eqlIgnoreCaseWtf8(a: []const u8, b: []const u8) bool { const a_cp = a_wtf8_it.nextCodepoint() orelse break; const b_cp = b_wtf8_it.nextCodepoint() orelse return false; - if (a_cp <= std.math.maxInt(u16) and b_cp <= std.math.maxInt(u16)) { + if (a_cp <= maxInt(u16) and b_cp <= maxInt(u16)) { if (a_cp != b_cp and upcaseImpl(@intCast(a_cp)) != upcaseImpl(@intCast(b_cp))) { return false; } @@ -2258,7 +4200,7 @@ pub const RemoveDotDirsError = error{TooManyParentDirs}; /// 2) all repeating back slashes have been collapsed /// 3) the path is a relative one (does not start with a back slash) pub fn removeDotDirsSanitized(comptime T: type, path: []T) RemoveDotDirsError!usize { - std.debug.assert(path.len == 0 or path[0] != '\\'); + assert(path.len == 0 or path[0] != '\\'); var write_idx: usize = 0; var read_idx: usize = 0; @@ -2274,7 +4216,7 @@ pub fn removeDotDirsSanitized(comptime T: type, path: []T) RemoveDotDirsError!us } if (after_dot == '.' and (read_idx + 2 == path.len or path[read_idx + 2] == '\\')) { if (write_idx == 0) return error.TooManyParentDirs; - std.debug.assert(write_idx >= 2); + assert(write_idx >= 2); write_idx -= 1; while (true) { write_idx -= 1; @@ -2376,7 +4318,7 @@ pub fn wToPrefixedFileW(dir: ?HANDLE, path: [:0]const u16) Wtf16ToPrefixedFileWE path_space.data[path_space.len] = 0; return path_space; } else { - const path_type = getWin32PathType(u16, path); + const path_type = std.fs.path.getWin32PathType(u16, path); var path_space: PathSpace = undefined; if (path_type == .local_device) { switch (getLocalDevicePathType(u16, path)) { @@ -2459,8 +4401,8 @@ pub fn wToPrefixedFileW(dir: ?HANDLE, path: [:0]const u16) Wtf16ToPrefixedFileWE break :path_to_get path; } // We can also skip GetFinalPathNameByHandle if the handle matches - // the handle returned by fs.cwd() - if (dir.? == std.fs.cwd().fd) { + // the handle returned by Io.Dir.cwd() + if (dir.? == Io.Dir.cwd().handle) { break :path_to_get path; } // At this point, we know we have a relative path that had too many @@ -2514,8 +4456,8 @@ pub fn wToPrefixedFileW(dir: ?HANDLE, path: [:0]const u16) Wtf16ToPrefixedFileWE if (path_type == .unc_absolute) { // Now add in the UNC, the `C` should overwrite the first `\` of the // FullPathName, ultimately resulting in `\??\UNC\` - std.debug.assert(path_space.data[path_buf_offset] == '\\'); - std.debug.assert(path_space.data[path_buf_offset + 1] == '\\'); + assert(path_space.data[path_buf_offset] == '\\'); + assert(path_space.data[path_buf_offset + 1] == '\\'); const unc = [_]u16{ 'U', 'N', 'C' }; path_space.data[nt_prefix.len..][0..unc.len].* = unc; } @@ -2523,127 +4465,6 @@ pub fn wToPrefixedFileW(dir: ?HANDLE, path: [:0]const u16) Wtf16ToPrefixedFileWE } } -/// Similar to `RTL_PATH_TYPE`, but without the `UNKNOWN` path type. -pub const Win32PathType = enum { - /// `\\server\share\foo` - unc_absolute, - /// `C:\foo` - drive_absolute, - /// `C:foo` - drive_relative, - /// `\foo` - rooted, - /// `foo` - relative, - /// `\\.\foo`, `\\?\foo` - local_device, - /// `\\.`, `\\?` - root_local_device, -}; - -/// Get the path type of a Win32 namespace path. -/// Similar to `RtlDetermineDosPathNameType_U`. -/// If `T` is `u16`, then `path` should be encoded as WTF-16LE. -pub fn getWin32PathType(comptime T: type, path: []const T) Win32PathType { - if (path.len < 1) return .relative; - - const windows_path = std.fs.path.PathType.windows; - if (windows_path.isSep(T, path[0])) { - // \x - if (path.len < 2 or !windows_path.isSep(T, path[1])) return .rooted; - // \\. or \\? - if (path.len > 2 and (path[2] == mem.nativeToLittle(T, '.') or path[2] == mem.nativeToLittle(T, '?'))) { - // exactly \\. or \\? with nothing trailing - if (path.len == 3) return .root_local_device; - // \\.\x or \\?\x - if (windows_path.isSep(T, path[3])) return .local_device; - } - // \\x - return .unc_absolute; - } else { - // Some choice has to be made about how non-ASCII code points as drive-letters are handled, since - // path[0] is a different size for WTF-16 vs WTF-8, leading to a potential mismatch in classification - // for a WTF-8 path and its WTF-16 equivalent. For example, `€:\` encoded in WTF-16 is three code - // units `<0x20AC>:\` whereas `€:\` encoded as WTF-8 is 6 code units `<0xE2><0x82><0xAC>:\` so - // checking path[0], path[1] and path[2] would not behave the same between WTF-8/WTF-16. - // - // `RtlDetermineDosPathNameType_U` exclusively deals with WTF-16 and considers - // `€:\` a drive-absolute path, but code points that take two WTF-16 code units to encode get - // classified as a relative path (e.g. with U+20000 as the drive-letter that'd be encoded - // in WTF-16 as `<0xD840><0xDC00>:\` and be considered a relative path). - // - // The choice made here is to emulate the behavior of `RtlDetermineDosPathNameType_U` for both - // WTF-16 and WTF-8. This is because, while unlikely and not supported by the Disk Manager GUI, - // drive letters are not actually restricted to A-Z. Using `SetVolumeMountPointW` will allow you - // to set any byte value as a drive letter, and going through `IOCTL_MOUNTMGR_CREATE_POINT` will - // allow you to set any WTF-16 code unit as a drive letter. - // - // Non-A-Z drive letters don't interact well with most of Windows, but certain things do work, e.g. - // `cd /D €:\` will work, filesystem functions still work, etc. - // - // The unfortunate part of this is that this makes handling WTF-8 more complicated as we can't - // just check path[0], path[1], path[2]. - const colon_i: usize = switch (T) { - u8 => i: { - const code_point_len = std.unicode.utf8ByteSequenceLength(path[0]) catch return .relative; - // Conveniently, 4-byte sequences in WTF-8 have the same starting code point - // as 2-code-unit sequences in WTF-16. - if (code_point_len > 3) return .relative; - break :i code_point_len; - }, - u16 => 1, - else => @compileError("unsupported type: " ++ @typeName(T)), - }; - // x - if (path.len < colon_i + 1 or path[colon_i] != mem.nativeToLittle(T, ':')) return .relative; - // x:\ - if (path.len > colon_i + 1 and windows_path.isSep(T, path[colon_i + 1])) return .drive_absolute; - // x: - return .drive_relative; - } -} - -test getWin32PathType { - try std.testing.expectEqual(.relative, getWin32PathType(u8, "")); - try std.testing.expectEqual(.relative, getWin32PathType(u8, "x")); - try std.testing.expectEqual(.relative, getWin32PathType(u8, "x\\")); - - try std.testing.expectEqual(.root_local_device, getWin32PathType(u8, "//.")); - try std.testing.expectEqual(.root_local_device, getWin32PathType(u8, "/\\?")); - try std.testing.expectEqual(.root_local_device, getWin32PathType(u8, "\\\\?")); - - try std.testing.expectEqual(.local_device, getWin32PathType(u8, "//./x")); - try std.testing.expectEqual(.local_device, getWin32PathType(u8, "/\\?\\x")); - try std.testing.expectEqual(.local_device, getWin32PathType(u8, "\\\\?\\x")); - // local device paths require a path separator after the root, otherwise it is considered a UNC path - try std.testing.expectEqual(.unc_absolute, getWin32PathType(u8, "\\\\?x")); - try std.testing.expectEqual(.unc_absolute, getWin32PathType(u8, "//.x")); - - try std.testing.expectEqual(.unc_absolute, getWin32PathType(u8, "//")); - try std.testing.expectEqual(.unc_absolute, getWin32PathType(u8, "\\\\x")); - try std.testing.expectEqual(.unc_absolute, getWin32PathType(u8, "//x")); - - try std.testing.expectEqual(.rooted, getWin32PathType(u8, "\\x")); - try std.testing.expectEqual(.rooted, getWin32PathType(u8, "/")); - - try std.testing.expectEqual(.drive_relative, getWin32PathType(u8, "x:")); - try std.testing.expectEqual(.drive_relative, getWin32PathType(u8, "x:abc")); - try std.testing.expectEqual(.drive_relative, getWin32PathType(u8, "x:a/b/c")); - - try std.testing.expectEqual(.drive_absolute, getWin32PathType(u8, "x:\\")); - try std.testing.expectEqual(.drive_absolute, getWin32PathType(u8, "x:\\abc")); - try std.testing.expectEqual(.drive_absolute, getWin32PathType(u8, "x:/a/b/c")); - - // Non-ASCII code point that is encoded as one WTF-16 code unit is considered a valid drive letter - try std.testing.expectEqual(.drive_absolute, getWin32PathType(u8, "€:\\")); - try std.testing.expectEqual(.drive_absolute, getWin32PathType(u16, std.unicode.wtf8ToWtf16LeStringLiteral("€:\\"))); - try std.testing.expectEqual(.drive_relative, getWin32PathType(u8, "€:")); - try std.testing.expectEqual(.drive_relative, getWin32PathType(u16, std.unicode.wtf8ToWtf16LeStringLiteral("€:"))); - // But code points that are encoded as two WTF-16 code units are not - try std.testing.expectEqual(.relative, getWin32PathType(u8, "\u{10000}:\\")); - try std.testing.expectEqual(.relative, getWin32PathType(u16, std.unicode.wtf8ToWtf16LeStringLiteral("\u{10000}:\\"))); -} - /// Returns true if the path starts with `\??\`, which is indicative of an NT path /// but is not enough to fully distinguish between NT paths and Win32 paths, as /// `\??\` is not actually a distinct prefix but rather the path to a special virtual @@ -2683,10 +4504,10 @@ const LocalDevicePathType = enum { }; /// Only relevant for Win32 -> NT path conversion. -/// Asserts `path` is of type `Win32PathType.local_device`. +/// Asserts `path` is of type `std.fs.path.Win32PathType.local_device`. fn getLocalDevicePathType(comptime T: type, path: []const T) LocalDevicePathType { if (std.debug.runtime_safety) { - std.debug.assert(getWin32PathType(T, path) == .local_device); + assert(std.fs.path.getWin32PathType(T, path) == .local_device); } const backslash = mem.nativeToLittle(T, '\\'); @@ -2783,7 +4604,10 @@ pub fn unexpectedWSAError(err: ws2_32.WinsockError) UnexpectedError { /// and you get an unexpected status. pub fn unexpectedStatus(status: NTSTATUS) UnexpectedError { if (std.posix.unexpected_error_tracing) { - std.debug.print("error.Unexpected NTSTATUS=0x{x}\n", .{@intFromEnum(status)}); + std.debug.print("error.Unexpected NTSTATUS=0x{x} ({s})\n", .{ + @intFromEnum(status), + std.enums.tagName(NTSTATUS, status) orelse "", + }); std.debug.dumpCurrentStackTrace(.{ .first_address = @returnAddress() }); } return error.Unexpected; @@ -2791,20 +4615,25 @@ pub fn unexpectedStatus(status: NTSTATUS) UnexpectedError { pub fn statusBug(status: NTSTATUS) UnexpectedError { switch (builtin.mode) { - .Debug => std.debug.panic("programmer bug caused syscall status: {t}", .{status}), + .Debug => std.debug.panic("programmer bug caused syscall status: 0x{x} ({s})", .{ + @intFromEnum(status), + std.enums.tagName(NTSTATUS, status) orelse "", + }), else => return error.Unexpected, } } pub fn errorBug(err: Win32Error) UnexpectedError { switch (builtin.mode) { - .Debug => std.debug.panic("programmer bug caused syscall status: {t}", .{err}), + .Debug => std.debug.panic("programmer bug caused syscall error: 0x{x} ({s})", .{ + @intFromEnum(err), + std.enums.tagName(Win32Error, err) orelse "", + }), else => return error.Unexpected, } } pub const Win32Error = @import("windows/win32error.zig").Win32Error; -pub const NTSTATUS = @import("windows/ntstatus.zig").NTSTATUS; pub const LANG = @import("windows/lang.zig"); pub const SUBLANG = @import("windows/sublang.zig"); @@ -2885,217 +4714,9 @@ pub const PCTSTR = @compileError("Deprecated: choose between `PCSTR` or `PCWSTR` pub const TRUE = 1; pub const FALSE = 0; -pub const DEVICE_TYPE = ULONG; -pub const FILE_DEVICE_BEEP: DEVICE_TYPE = 0x0001; -pub const FILE_DEVICE_CD_ROM: DEVICE_TYPE = 0x0002; -pub const FILE_DEVICE_CD_ROM_FILE_SYSTEM: DEVICE_TYPE = 0x0003; -pub const FILE_DEVICE_CONTROLLER: DEVICE_TYPE = 0x0004; -pub const FILE_DEVICE_DATALINK: DEVICE_TYPE = 0x0005; -pub const FILE_DEVICE_DFS: DEVICE_TYPE = 0x0006; -pub const FILE_DEVICE_DISK: DEVICE_TYPE = 0x0007; -pub const FILE_DEVICE_DISK_FILE_SYSTEM: DEVICE_TYPE = 0x0008; -pub const FILE_DEVICE_FILE_SYSTEM: DEVICE_TYPE = 0x0009; -pub const FILE_DEVICE_INPORT_PORT: DEVICE_TYPE = 0x000a; -pub const FILE_DEVICE_KEYBOARD: DEVICE_TYPE = 0x000b; -pub const FILE_DEVICE_MAILSLOT: DEVICE_TYPE = 0x000c; -pub const FILE_DEVICE_MIDI_IN: DEVICE_TYPE = 0x000d; -pub const FILE_DEVICE_MIDI_OUT: DEVICE_TYPE = 0x000e; -pub const FILE_DEVICE_MOUSE: DEVICE_TYPE = 0x000f; -pub const FILE_DEVICE_MULTI_UNC_PROVIDER: DEVICE_TYPE = 0x0010; -pub const FILE_DEVICE_NAMED_PIPE: DEVICE_TYPE = 0x0011; -pub const FILE_DEVICE_NETWORK: DEVICE_TYPE = 0x0012; -pub const FILE_DEVICE_NETWORK_BROWSER: DEVICE_TYPE = 0x0013; -pub const FILE_DEVICE_NETWORK_FILE_SYSTEM: DEVICE_TYPE = 0x0014; -pub const FILE_DEVICE_NULL: DEVICE_TYPE = 0x0015; -pub const FILE_DEVICE_PARALLEL_PORT: DEVICE_TYPE = 0x0016; -pub const FILE_DEVICE_PHYSICAL_NETCARD: DEVICE_TYPE = 0x0017; -pub const FILE_DEVICE_PRINTER: DEVICE_TYPE = 0x0018; -pub const FILE_DEVICE_SCANNER: DEVICE_TYPE = 0x0019; -pub const FILE_DEVICE_SERIAL_MOUSE_PORT: DEVICE_TYPE = 0x001a; -pub const FILE_DEVICE_SERIAL_PORT: DEVICE_TYPE = 0x001b; -pub const FILE_DEVICE_SCREEN: DEVICE_TYPE = 0x001c; -pub const FILE_DEVICE_SOUND: DEVICE_TYPE = 0x001d; -pub const FILE_DEVICE_STREAMS: DEVICE_TYPE = 0x001e; -pub const FILE_DEVICE_TAPE: DEVICE_TYPE = 0x001f; -pub const FILE_DEVICE_TAPE_FILE_SYSTEM: DEVICE_TYPE = 0x0020; -pub const FILE_DEVICE_TRANSPORT: DEVICE_TYPE = 0x0021; -pub const FILE_DEVICE_UNKNOWN: DEVICE_TYPE = 0x0022; -pub const FILE_DEVICE_VIDEO: DEVICE_TYPE = 0x0023; -pub const FILE_DEVICE_VIRTUAL_DISK: DEVICE_TYPE = 0x0024; -pub const FILE_DEVICE_WAVE_IN: DEVICE_TYPE = 0x0025; -pub const FILE_DEVICE_WAVE_OUT: DEVICE_TYPE = 0x0026; -pub const FILE_DEVICE_8042_PORT: DEVICE_TYPE = 0x0027; -pub const FILE_DEVICE_NETWORK_REDIRECTOR: DEVICE_TYPE = 0x0028; -pub const FILE_DEVICE_BATTERY: DEVICE_TYPE = 0x0029; -pub const FILE_DEVICE_BUS_EXTENDER: DEVICE_TYPE = 0x002a; -pub const FILE_DEVICE_MODEM: DEVICE_TYPE = 0x002b; -pub const FILE_DEVICE_VDM: DEVICE_TYPE = 0x002c; -pub const FILE_DEVICE_MASS_STORAGE: DEVICE_TYPE = 0x002d; -pub const FILE_DEVICE_SMB: DEVICE_TYPE = 0x002e; -pub const FILE_DEVICE_KS: DEVICE_TYPE = 0x002f; -pub const FILE_DEVICE_CHANGER: DEVICE_TYPE = 0x0030; -pub const FILE_DEVICE_SMARTCARD: DEVICE_TYPE = 0x0031; -pub const FILE_DEVICE_ACPI: DEVICE_TYPE = 0x0032; -pub const FILE_DEVICE_DVD: DEVICE_TYPE = 0x0033; -pub const FILE_DEVICE_FULLSCREEN_VIDEO: DEVICE_TYPE = 0x0034; -pub const FILE_DEVICE_DFS_FILE_SYSTEM: DEVICE_TYPE = 0x0035; -pub const FILE_DEVICE_DFS_VOLUME: DEVICE_TYPE = 0x0036; -pub const FILE_DEVICE_SERENUM: DEVICE_TYPE = 0x0037; -pub const FILE_DEVICE_TERMSRV: DEVICE_TYPE = 0x0038; -pub const FILE_DEVICE_KSEC: DEVICE_TYPE = 0x0039; -pub const FILE_DEVICE_FIPS: DEVICE_TYPE = 0x003a; -pub const FILE_DEVICE_INFINIBAND: DEVICE_TYPE = 0x003b; -// TODO: missing values? -pub const FILE_DEVICE_VMBUS: DEVICE_TYPE = 0x003e; -pub const FILE_DEVICE_CRYPT_PROVIDER: DEVICE_TYPE = 0x003f; -pub const FILE_DEVICE_WPD: DEVICE_TYPE = 0x0040; -pub const FILE_DEVICE_BLUETOOTH: DEVICE_TYPE = 0x0041; -pub const FILE_DEVICE_MT_COMPOSITE: DEVICE_TYPE = 0x0042; -pub const FILE_DEVICE_MT_TRANSPORT: DEVICE_TYPE = 0x0043; -pub const FILE_DEVICE_BIOMETRIC: DEVICE_TYPE = 0x0044; -pub const FILE_DEVICE_PMI: DEVICE_TYPE = 0x0045; -pub const FILE_DEVICE_EHSTOR: DEVICE_TYPE = 0x0046; -pub const FILE_DEVICE_DEVAPI: DEVICE_TYPE = 0x0047; -pub const FILE_DEVICE_GPIO: DEVICE_TYPE = 0x0048; -pub const FILE_DEVICE_USBEX: DEVICE_TYPE = 0x0049; -pub const FILE_DEVICE_CONSOLE: DEVICE_TYPE = 0x0050; -pub const FILE_DEVICE_NFP: DEVICE_TYPE = 0x0051; -pub const FILE_DEVICE_SYSENV: DEVICE_TYPE = 0x0052; -pub const FILE_DEVICE_VIRTUAL_BLOCK: DEVICE_TYPE = 0x0053; -pub const FILE_DEVICE_POINT_OF_SERVICE: DEVICE_TYPE = 0x0054; -pub const FILE_DEVICE_STORAGE_REPLICATION: DEVICE_TYPE = 0x0055; -pub const FILE_DEVICE_TRUST_ENV: DEVICE_TYPE = 0x0056; -pub const FILE_DEVICE_UCM: DEVICE_TYPE = 0x0057; -pub const FILE_DEVICE_UCMTCPCI: DEVICE_TYPE = 0x0058; -pub const FILE_DEVICE_PERSISTENT_MEMORY: DEVICE_TYPE = 0x0059; -pub const FILE_DEVICE_NVDIMM: DEVICE_TYPE = 0x005a; -pub const FILE_DEVICE_HOLOGRAPHIC: DEVICE_TYPE = 0x005b; -pub const FILE_DEVICE_SDFXHCI: DEVICE_TYPE = 0x005c; - -/// https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/buffer-descriptions-for-i-o-control-codes -pub const TransferType = enum(u2) { - METHOD_BUFFERED = 0, - METHOD_IN_DIRECT = 1, - METHOD_OUT_DIRECT = 2, - METHOD_NEITHER = 3, -}; - -pub const FILE_ANY_ACCESS = 0; -pub const FILE_READ_ACCESS = 1; -pub const FILE_WRITE_ACCESS = 2; - -/// https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/defining-i-o-control-codes -pub fn CTL_CODE(deviceType: u16, function: u12, method: TransferType, access: u2) DWORD { - return (@as(DWORD, deviceType) << 16) | - (@as(DWORD, access) << 14) | - (@as(DWORD, function) << 2) | - @intFromEnum(method); -} - -pub const INVALID_HANDLE_VALUE = @as(HANDLE, @ptrFromInt(maxInt(usize))); - -pub const INVALID_FILE_ATTRIBUTES = @as(DWORD, maxInt(DWORD)); - -pub const FILE_ALL_INFORMATION = extern struct { - BasicInformation: FILE_BASIC_INFORMATION, - StandardInformation: FILE_STANDARD_INFORMATION, - InternalInformation: FILE_INTERNAL_INFORMATION, - EaInformation: FILE_EA_INFORMATION, - AccessInformation: FILE_ACCESS_INFORMATION, - PositionInformation: FILE_POSITION_INFORMATION, - ModeInformation: FILE_MODE_INFORMATION, - AlignmentInformation: FILE_ALIGNMENT_INFORMATION, - NameInformation: FILE_NAME_INFORMATION, -}; - -pub const FILE_BASIC_INFORMATION = extern struct { - CreationTime: LARGE_INTEGER, - LastAccessTime: LARGE_INTEGER, - LastWriteTime: LARGE_INTEGER, - ChangeTime: LARGE_INTEGER, - FileAttributes: ULONG, -}; - -pub const FILE_STANDARD_INFORMATION = extern struct { - AllocationSize: LARGE_INTEGER, - EndOfFile: LARGE_INTEGER, - NumberOfLinks: ULONG, - DeletePending: BOOLEAN, - Directory: BOOLEAN, -}; - -pub const FILE_INTERNAL_INFORMATION = extern struct { - IndexNumber: LARGE_INTEGER, -}; - -pub const FILE_EA_INFORMATION = extern struct { - EaSize: ULONG, -}; - -pub const FILE_ACCESS_INFORMATION = extern struct { - AccessFlags: ACCESS_MASK, -}; - -pub const FILE_POSITION_INFORMATION = extern struct { - CurrentByteOffset: LARGE_INTEGER, -}; - -pub const FILE_END_OF_FILE_INFORMATION = extern struct { - EndOfFile: LARGE_INTEGER, -}; - -pub const FILE_MODE_INFORMATION = extern struct { - Mode: ULONG, -}; - -pub const FILE_ALIGNMENT_INFORMATION = extern struct { - AlignmentRequirement: ULONG, -}; - -pub const FILE_NAME_INFORMATION = extern struct { - FileNameLength: ULONG, - FileName: [1]WCHAR, -}; - -pub const FILE_DISPOSITION_INFORMATION_EX = extern struct { - /// combination of FILE_DISPOSITION_* flags - Flags: ULONG, -}; - -pub const FILE_DISPOSITION_DO_NOT_DELETE: ULONG = 0x00000000; -pub const FILE_DISPOSITION_DELETE: ULONG = 0x00000001; -pub const FILE_DISPOSITION_POSIX_SEMANTICS: ULONG = 0x00000002; -pub const FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK: ULONG = 0x00000004; -pub const FILE_DISPOSITION_ON_CLOSE: ULONG = 0x00000008; -pub const FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE: ULONG = 0x00000010; - -// FILE_RENAME_INFORMATION.Flags -pub const FILE_RENAME_REPLACE_IF_EXISTS = 0x00000001; -pub const FILE_RENAME_POSIX_SEMANTICS = 0x00000002; -pub const FILE_RENAME_SUPPRESS_PIN_STATE_INHERITANCE = 0x00000004; -pub const FILE_RENAME_SUPPRESS_STORAGE_RESERVE_INHERITANCE = 0x00000008; -pub const FILE_RENAME_NO_INCREASE_AVAILABLE_SPACE = 0x00000010; -pub const FILE_RENAME_NO_DECREASE_AVAILABLE_SPACE = 0x00000020; -pub const FILE_RENAME_PRESERVE_AVAILABLE_SPACE = 0x00000030; -pub const FILE_RENAME_IGNORE_READONLY_ATTRIBUTE = 0x00000040; -pub const FILE_RENAME_FORCE_RESIZE_TARGET_SR = 0x00000080; -pub const FILE_RENAME_FORCE_RESIZE_SOURCE_SR = 0x00000100; -pub const FILE_RENAME_FORCE_RESIZE_SR = 0x00000180; - -pub const FILE_RENAME_INFORMATION = extern struct { - Flags: BOOLEAN, - RootDirectory: ?HANDLE, - FileNameLength: ULONG, - FileName: [1]WCHAR, -}; +pub const INVALID_HANDLE_VALUE: HANDLE = @ptrFromInt(maxInt(usize)); -// FileRenameInformationEx (since .win10_rs1) -pub const FILE_RENAME_INFORMATION_EX = extern struct { - Flags: ULONG, - RootDirectory: ?HANDLE, - FileNameLength: ULONG, - FileName: [1]WCHAR, -}; +pub const INVALID_FILE_ATTRIBUTES: DWORD = maxInt(DWORD); pub const IO_STATUS_BLOCK = extern struct { // "DUMMYUNIONNAME" expands to "u" @@ -3106,130 +4727,6 @@ pub const IO_STATUS_BLOCK = extern struct { Information: ULONG_PTR, }; -pub const FILE_INFORMATION_CLASS = enum(c_int) { - FileDirectoryInformation = 1, - FileFullDirectoryInformation, - FileBothDirectoryInformation, - FileBasicInformation, - FileStandardInformation, - FileInternalInformation, - FileEaInformation, - FileAccessInformation, - FileNameInformation, - FileRenameInformation, - FileLinkInformation, - FileNamesInformation, - FileDispositionInformation, - FilePositionInformation, - FileFullEaInformation, - FileModeInformation, - FileAlignmentInformation, - FileAllInformation, - FileAllocationInformation, - FileEndOfFileInformation, - FileAlternateNameInformation, - FileStreamInformation, - FilePipeInformation, - FilePipeLocalInformation, - FilePipeRemoteInformation, - FileMailslotQueryInformation, - FileMailslotSetInformation, - FileCompressionInformation, - FileObjectIdInformation, - FileCompletionInformation, - FileMoveClusterInformation, - FileQuotaInformation, - FileReparsePointInformation, - FileNetworkOpenInformation, - FileAttributeTagInformation, - FileTrackingInformation, - FileIdBothDirectoryInformation, - FileIdFullDirectoryInformation, - FileValidDataLengthInformation, - FileShortNameInformation, - FileIoCompletionNotificationInformation, - FileIoStatusBlockRangeInformation, - FileIoPriorityHintInformation, - FileSfioReserveInformation, - FileSfioVolumeInformation, - FileHardLinkInformation, - FileProcessIdsUsingFileInformation, - FileNormalizedNameInformation, - FileNetworkPhysicalNameInformation, - FileIdGlobalTxDirectoryInformation, - FileIsRemoteDeviceInformation, - FileUnusedInformation, - FileNumaNodeInformation, - FileStandardLinkInformation, - FileRemoteProtocolInformation, - FileRenameInformationBypassAccessCheck, - FileLinkInformationBypassAccessCheck, - FileVolumeNameInformation, - FileIdInformation, - FileIdExtdDirectoryInformation, - FileReplaceCompletionInformation, - FileHardLinkFullIdInformation, - FileIdExtdBothDirectoryInformation, - FileDispositionInformationEx, - FileRenameInformationEx, - FileRenameInformationExBypassAccessCheck, - FileDesiredStorageClassInformation, - FileStatInformation, - FileMemoryPartitionInformation, - FileStatLxInformation, - FileCaseSensitiveInformation, - FileLinkInformationEx, - FileLinkInformationExBypassAccessCheck, - FileStorageReserveIdInformation, - FileCaseSensitiveInformationForceAccessCheck, - FileMaximumInformation, -}; - -pub const FILE_ATTRIBUTE_TAG_INFO = extern struct { - FileAttributes: DWORD, - ReparseTag: DWORD, -}; - -/// "If this bit is set, the file or directory represents another named entity in the system." -/// https://learn.microsoft.com/en-us/windows/win32/fileio/reparse-point-tags -pub const reparse_tag_name_surrogate_bit = 0x20000000; - -pub const FILE_DISPOSITION_INFORMATION = extern struct { - DeleteFile: BOOLEAN, -}; - -pub const FILE_FS_DEVICE_INFORMATION = extern struct { - DeviceType: DEVICE_TYPE, - Characteristics: ULONG, -}; - -pub const FILE_FS_VOLUME_INFORMATION = extern struct { - VolumeCreationTime: LARGE_INTEGER, - VolumeSerialNumber: ULONG, - VolumeLabelLength: ULONG, - SupportsObjects: BOOLEAN, - // Flexible array member - VolumeLabel: [1]WCHAR, -}; - -pub const FS_INFORMATION_CLASS = enum(c_int) { - FileFsVolumeInformation = 1, - FileFsLabelInformation, - FileFsSizeInformation, - FileFsDeviceInformation, - FileFsAttributeInformation, - FileFsControlInformation, - FileFsFullSizeInformation, - FileFsObjectIdInformation, - FileFsDriverPathInformation, - FileFsVolumeFlagsInformation, - FileFsSectorSizeInformation, - FileFsDataCopyInformation, - FileFsMetadataSizeInformation, - FileFsFullSizeInformationEx, - FileFsMaximumInformation, -}; - pub const OVERLAPPED = extern struct { Internal: ULONG_PTR, InternalHigh: ULONG_PTR, @@ -3331,129 +4828,16 @@ pub const PIPE_READMODE_MESSAGE = 0x00000002; pub const PIPE_WAIT = 0x00000000; pub const PIPE_NOWAIT = 0x00000001; -pub const GENERIC_READ = 0x80000000; -pub const GENERIC_WRITE = 0x40000000; -pub const GENERIC_EXECUTE = 0x20000000; -pub const GENERIC_ALL = 0x10000000; - -pub const FILE_SHARE_DELETE = 0x00000004; -pub const FILE_SHARE_READ = 0x00000001; -pub const FILE_SHARE_WRITE = 0x00000002; - -pub const DELETE = 0x00010000; -pub const READ_CONTROL = 0x00020000; -pub const WRITE_DAC = 0x00040000; -pub const WRITE_OWNER = 0x00080000; -pub const SYNCHRONIZE = 0x00100000; -pub const STANDARD_RIGHTS_READ = READ_CONTROL; -pub const STANDARD_RIGHTS_WRITE = READ_CONTROL; -pub const STANDARD_RIGHTS_EXECUTE = READ_CONTROL; -pub const STANDARD_RIGHTS_REQUIRED = DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER; -pub const MAXIMUM_ALLOWED = 0x02000000; - -// disposition for NtCreateFile -pub const FILE_SUPERSEDE = 0; -pub const FILE_OPEN = 1; -pub const FILE_CREATE = 2; -pub const FILE_OPEN_IF = 3; -pub const FILE_OVERWRITE = 4; -pub const FILE_OVERWRITE_IF = 5; -pub const FILE_MAXIMUM_DISPOSITION = 5; - -// flags for NtCreateFile and NtOpenFile -pub const FILE_READ_DATA = 0x00000001; -pub const FILE_LIST_DIRECTORY = 0x00000001; -pub const FILE_WRITE_DATA = 0x00000002; -pub const FILE_ADD_FILE = 0x00000002; -pub const FILE_APPEND_DATA = 0x00000004; -pub const FILE_ADD_SUBDIRECTORY = 0x00000004; -pub const FILE_CREATE_PIPE_INSTANCE = 0x00000004; -pub const FILE_READ_EA = 0x00000008; -pub const FILE_WRITE_EA = 0x00000010; -pub const FILE_EXECUTE = 0x00000020; -pub const FILE_TRAVERSE = 0x00000020; -pub const FILE_DELETE_CHILD = 0x00000040; -pub const FILE_READ_ATTRIBUTES = 0x00000080; -pub const FILE_WRITE_ATTRIBUTES = 0x00000100; - -pub const FILE_DIRECTORY_FILE = 0x00000001; -pub const FILE_WRITE_THROUGH = 0x00000002; -pub const FILE_SEQUENTIAL_ONLY = 0x00000004; -pub const FILE_NO_INTERMEDIATE_BUFFERING = 0x00000008; -pub const FILE_SYNCHRONOUS_IO_ALERT = 0x00000010; -pub const FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020; -pub const FILE_NON_DIRECTORY_FILE = 0x00000040; -pub const FILE_CREATE_TREE_CONNECTION = 0x00000080; -pub const FILE_COMPLETE_IF_OPLOCKED = 0x00000100; -pub const FILE_NO_EA_KNOWLEDGE = 0x00000200; -pub const FILE_OPEN_FOR_RECOVERY = 0x00000400; -pub const FILE_RANDOM_ACCESS = 0x00000800; -pub const FILE_DELETE_ON_CLOSE = 0x00001000; -pub const FILE_OPEN_BY_FILE_ID = 0x00002000; -pub const FILE_OPEN_FOR_BACKUP_INTENT = 0x00004000; -pub const FILE_NO_COMPRESSION = 0x00008000; -pub const FILE_RESERVE_OPFILTER = 0x00100000; -pub const FILE_OPEN_REPARSE_POINT = 0x00200000; -pub const FILE_OPEN_OFFLINE_FILE = 0x00400000; -pub const FILE_OPEN_FOR_FREE_SPACE_QUERY = 0x00800000; - pub const CREATE_ALWAYS = 2; pub const CREATE_NEW = 1; pub const OPEN_ALWAYS = 4; pub const OPEN_EXISTING = 3; pub const TRUNCATE_EXISTING = 5; -pub const FILE_ATTRIBUTE_ARCHIVE = 0x20; -pub const FILE_ATTRIBUTE_COMPRESSED = 0x800; -pub const FILE_ATTRIBUTE_DEVICE = 0x40; -pub const FILE_ATTRIBUTE_DIRECTORY = 0x10; -pub const FILE_ATTRIBUTE_ENCRYPTED = 0x4000; -pub const FILE_ATTRIBUTE_HIDDEN = 0x2; -pub const FILE_ATTRIBUTE_INTEGRITY_STREAM = 0x8000; -pub const FILE_ATTRIBUTE_NORMAL = 0x80; -pub const FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x2000; -pub const FILE_ATTRIBUTE_NO_SCRUB_DATA = 0x20000; -pub const FILE_ATTRIBUTE_OFFLINE = 0x1000; -pub const FILE_ATTRIBUTE_READONLY = 0x1; -pub const FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS = 0x400000; -pub const FILE_ATTRIBUTE_RECALL_ON_OPEN = 0x40000; -pub const FILE_ATTRIBUTE_REPARSE_POINT = 0x400; -pub const FILE_ATTRIBUTE_SPARSE_FILE = 0x200; -pub const FILE_ATTRIBUTE_SYSTEM = 0x4; -pub const FILE_ATTRIBUTE_TEMPORARY = 0x100; -pub const FILE_ATTRIBUTE_VIRTUAL = 0x10000; - -pub const FILE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1ff; -pub const FILE_GENERIC_READ = STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE; -pub const FILE_GENERIC_WRITE = STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE; -pub const FILE_GENERIC_EXECUTE = STANDARD_RIGHTS_EXECUTE | FILE_READ_ATTRIBUTES | FILE_EXECUTE | SYNCHRONIZE; - -// Flags for NtCreateNamedPipeFile -// NamedPipeType -pub const FILE_PIPE_BYTE_STREAM_TYPE = 0x0; -pub const FILE_PIPE_MESSAGE_TYPE = 0x1; -pub const FILE_PIPE_ACCEPT_REMOTE_CLIENTS = 0x0; -pub const FILE_PIPE_REJECT_REMOTE_CLIENTS = 0x2; -pub const FILE_PIPE_TYPE_VALID_MASK = 0x3; -// CompletionMode -pub const FILE_PIPE_QUEUE_OPERATION = 0x0; -pub const FILE_PIPE_COMPLETE_OPERATION = 0x1; -// ReadMode -pub const FILE_PIPE_BYTE_STREAM_MODE = 0x0; -pub const FILE_PIPE_MESSAGE_MODE = 0x1; - // flags for CreateEvent pub const CREATE_EVENT_INITIAL_SET = 0x00000002; pub const CREATE_EVENT_MANUAL_RESET = 0x00000001; -pub const EVENT_ALL_ACCESS = 0x1F0003; -pub const EVENT_MODIFY_STATE = 0x0002; - -// MEMORY_BASIC_INFORMATION.Type flags for VirtualQuery -pub const MEM_IMAGE = 0x1000000; -pub const MEM_MAPPED = 0x40000; -pub const MEM_PRIVATE = 0x20000; - pub const PROCESS_INFORMATION = extern struct { hProcess: HANDLE, hThread: HANDLE, @@ -3521,45 +4905,6 @@ pub const FILE_BEGIN = 0; pub const FILE_CURRENT = 1; pub const FILE_END = 2; -pub const HEAP_CREATE_ENABLE_EXECUTE = 0x00040000; -pub const HEAP_REALLOC_IN_PLACE_ONLY = 0x00000010; -pub const HEAP_GENERATE_EXCEPTIONS = 0x00000004; -pub const HEAP_NO_SERIALIZE = 0x00000001; - -// AllocationType values -pub const MEM_COMMIT = 0x1000; -pub const MEM_RESERVE = 0x2000; -pub const MEM_FREE = 0x10000; -pub const MEM_RESET = 0x80000; -pub const MEM_RESET_UNDO = 0x1000000; -pub const MEM_LARGE_PAGES = 0x20000000; -pub const MEM_PHYSICAL = 0x400000; -pub const MEM_TOP_DOWN = 0x100000; -pub const MEM_WRITE_WATCH = 0x200000; -pub const MEM_RESERVE_PLACEHOLDER = 0x00040000; -pub const MEM_PRESERVE_PLACEHOLDER = 0x00000400; - -// Protect values -pub const PAGE_EXECUTE = 0x10; -pub const PAGE_EXECUTE_READ = 0x20; -pub const PAGE_EXECUTE_READWRITE = 0x40; -pub const PAGE_EXECUTE_WRITECOPY = 0x80; -pub const PAGE_NOACCESS = 0x01; -pub const PAGE_READONLY = 0x02; -pub const PAGE_READWRITE = 0x04; -pub const PAGE_WRITECOPY = 0x08; -pub const PAGE_TARGETS_INVALID = 0x40000000; -pub const PAGE_TARGETS_NO_UPDATE = 0x40000000; // Same as PAGE_TARGETS_INVALID -pub const PAGE_GUARD = 0x100; -pub const PAGE_NOCACHE = 0x200; -pub const PAGE_WRITECOMBINE = 0x400; - -// FreeType values -pub const MEM_COALESCE_PLACEHOLDERS = 0x1; -pub const MEM_RESERVE_PLACEHOLDERS = 0x2; -pub const MEM_DECOMMIT = 0x4000; -pub const MEM_RELEASE = 0x8000; - pub const PTHREAD_START_ROUTINE = *const fn (LPVOID) callconv(.winapi) DWORD; pub const LPTHREAD_START_ROUTINE = PTHREAD_START_ROUTINE; @@ -3743,38 +5088,8 @@ pub const PIMAGE_TLS_CALLBACK = ?*const fn (PVOID, DWORD, PVOID) callconv(.winap pub const PROV_RSA_FULL = 1; pub const REGSAM = ACCESS_MASK; -pub const ACCESS_MASK = DWORD; pub const LSTATUS = LONG; -pub const SECTION_INHERIT = enum(c_int) { - ViewShare = 0, - ViewUnmap = 1, -}; - -pub const SECTION_QUERY = 0x0001; -pub const SECTION_MAP_WRITE = 0x0002; -pub const SECTION_MAP_READ = 0x0004; -pub const SECTION_MAP_EXECUTE = 0x0008; -pub const SECTION_EXTEND_SIZE = 0x0010; -pub const SECTION_ALL_ACCESS = - STANDARD_RIGHTS_REQUIRED | - SECTION_QUERY | - SECTION_MAP_WRITE | - SECTION_MAP_READ | - SECTION_MAP_EXECUTE | - SECTION_EXTEND_SIZE; - -pub const SEC_64K_PAGES = 0x80000; -pub const SEC_FILE = 0x800000; -pub const SEC_IMAGE = 0x1000000; -pub const SEC_PROTECTED_IMAGE = 0x2000000; -pub const SEC_RESERVE = 0x4000000; -pub const SEC_COMMIT = 0x8000000; -pub const SEC_IMAGE_NO_EXECUTE = SEC_IMAGE | SEC_NOCACHE; -pub const SEC_NOCACHE = 0x10000000; -pub const SEC_WRITECOMBINE = 0x40000000; -pub const SEC_LARGE_PAGES = 0x80000000; - pub const HKEY = *opaque {}; pub const HKEY_CLASSES_ROOT: HKEY = @ptrFromInt(0x80000000); @@ -3788,34 +5103,6 @@ pub const HKEY_CURRENT_CONFIG: HKEY = @ptrFromInt(0x80000005); pub const HKEY_DYN_DATA: HKEY = @ptrFromInt(0x80000006); pub const HKEY_CURRENT_USER_LOCAL_SETTINGS: HKEY = @ptrFromInt(0x80000007); -/// Combines the STANDARD_RIGHTS_REQUIRED, KEY_QUERY_VALUE, KEY_SET_VALUE, KEY_CREATE_SUB_KEY, -/// KEY_ENUMERATE_SUB_KEYS, KEY_NOTIFY, and KEY_CREATE_LINK access rights. -pub const KEY_ALL_ACCESS = 0xF003F; -/// Reserved for system use. -pub const KEY_CREATE_LINK = 0x0020; -/// Required to create a subkey of a registry key. -pub const KEY_CREATE_SUB_KEY = 0x0004; -/// Required to enumerate the subkeys of a registry key. -pub const KEY_ENUMERATE_SUB_KEYS = 0x0008; -/// Equivalent to KEY_READ. -pub const KEY_EXECUTE = 0x20019; -/// Required to request change notifications for a registry key or for subkeys of a registry key. -pub const KEY_NOTIFY = 0x0010; -/// Required to query the values of a registry key. -pub const KEY_QUERY_VALUE = 0x0001; -/// Combines the STANDARD_RIGHTS_READ, KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS, and KEY_NOTIFY values. -pub const KEY_READ = 0x20019; -/// Required to create, delete, or set a registry value. -pub const KEY_SET_VALUE = 0x0002; -/// Indicates that an application on 64-bit Windows should operate on the 32-bit registry view. -/// This flag is ignored by 32-bit Windows. -pub const KEY_WOW64_32KEY = 0x0200; -/// Indicates that an application on 64-bit Windows should operate on the 64-bit registry view. -/// This flag is ignored by 32-bit Windows. -pub const KEY_WOW64_64KEY = 0x0100; -/// Combines the STANDARD_RIGHTS_WRITE, KEY_SET_VALUE, and KEY_CREATE_SUB_KEY access rights. -pub const KEY_WRITE = 0x20006; - /// Open symbolic link. pub const REG_OPTION_OPEN_LINK: DWORD = 0x8; @@ -4466,14 +5753,14 @@ pub const EXCEPTION_DISPOSITION = i32; pub const EXCEPTION_ROUTINE = *const fn ( ExceptionRecord: ?*EXCEPTION_RECORD, EstablisherFrame: PVOID, - ContextRecord: *(Self.CONTEXT), + ContextRecord: *CONTEXT, DispatcherContext: PVOID, ) callconv(.winapi) EXCEPTION_DISPOSITION; pub const UNWIND_HISTORY_TABLE_SIZE = 12; pub const UNWIND_HISTORY_TABLE_ENTRY = extern struct { ImageBase: ULONG64, - FunctionEntry: *Self.RUNTIME_FUNCTION, + FunctionEntry: *RUNTIME_FUNCTION, }; pub const UNWIND_HISTORY_TABLE = extern struct { @@ -4492,24 +5779,6 @@ pub const UNW_FLAG_EHANDLER = 0x1; pub const UNW_FLAG_UHANDLER = 0x2; pub const UNW_FLAG_CHAININFO = 0x4; -pub const OBJECT_ATTRIBUTES = extern struct { - Length: ULONG, - RootDirectory: ?HANDLE, - ObjectName: *UNICODE_STRING, - Attributes: ULONG, - SecurityDescriptor: ?*anyopaque, - SecurityQualityOfService: ?*anyopaque, -}; - -pub const OBJ_INHERIT = 0x00000002; -pub const OBJ_PERMANENT = 0x00000010; -pub const OBJ_EXCLUSIVE = 0x00000020; -pub const OBJ_CASE_INSENSITIVE = 0x00000040; -pub const OBJ_OPENIF = 0x00000080; -pub const OBJ_OPENLINK = 0x00000100; -pub const OBJ_KERNEL_HANDLE = 0x00000200; -pub const OBJ_VALID_ATTRIBUTES = 0x000003F2; - pub const UNICODE_STRING = extern struct { Length: c_ushort, MaximumLength: c_ushort, @@ -4617,7 +5886,7 @@ pub const PEB = extern struct { Ldr: *PEB_LDR_DATA, ProcessParameters: *RTL_USER_PROCESS_PARAMETERS, SubSystemData: PVOID, - ProcessHeap: HANDLE, + ProcessHeap: ?*HEAP, // Versions: 5.1+ FastPebLock: *RTL_CRITICAL_SECTION, @@ -4862,7 +6131,7 @@ pub const FILE_DIRECTORY_INFORMATION = extern struct { ChangeTime: LARGE_INTEGER, EndOfFile: LARGE_INTEGER, AllocationSize: LARGE_INTEGER, - FileAttributes: ULONG, + FileAttributes: FILE.ATTRIBUTE, FileNameLength: ULONG, FileName: [1]WCHAR, }; @@ -4876,7 +6145,7 @@ pub const FILE_BOTH_DIR_INFORMATION = extern struct { ChangeTime: LARGE_INTEGER, EndOfFile: LARGE_INTEGER, AllocationSize: LARGE_INTEGER, - FileAttributes: ULONG, + FileAttributes: FILE.ATTRIBUTE, FileNameLength: ULONG, EaSize: ULONG, ShortNameLength: CHAR, @@ -4905,7 +6174,7 @@ pub fn FileInformationIterator(comptime FileInformationType: type) type { }; } -pub const IO_APC_ROUTINE = *const fn (PVOID, *IO_STATUS_BLOCK, ULONG) callconv(.winapi) void; +pub const IO_APC_ROUTINE = fn (?*anyopaque, *IO_STATUS_BLOCK, ULONG) callconv(.winapi) void; pub const CURDIR = extern struct { DosPath: UNICODE_STRING, @@ -4974,7 +6243,7 @@ pub const GetProcessMemoryInfoError = error{ pub fn GetProcessMemoryInfo(hProcess: HANDLE) GetProcessMemoryInfoError!VM_COUNTERS { var vmc: VM_COUNTERS = undefined; - const rc = ntdll.NtQueryInformationProcess(hProcess, .ProcessVmCounters, &vmc, @sizeOf(VM_COUNTERS), null); + const rc = ntdll.NtQueryInformationProcess(hProcess, .VmCounters, &vmc, @sizeOf(VM_COUNTERS), null); switch (rc) { .SUCCESS => return vmc, .ACCESS_DENIED => return error.AccessDenied, @@ -5029,7 +6298,7 @@ pub const OSVERSIONINFOW = extern struct { pub const RTL_OSVERSIONINFOW = OSVERSIONINFOW; pub const REPARSE_DATA_BUFFER = extern struct { - ReparseTag: ULONG, + ReparseTag: IO_REPARSE_TAG, ReparseDataLength: USHORT, Reserved: USHORT, DataBuffer: [1]UCHAR, @@ -5049,18 +6318,11 @@ pub const MOUNT_POINT_REPARSE_BUFFER = extern struct { PrintNameLength: USHORT, PathBuffer: [1]WCHAR, }; -pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: ULONG = 16 * 1024; -pub const FSCTL_SET_REPARSE_POINT: DWORD = 0x900a4; -pub const FSCTL_GET_REPARSE_POINT: DWORD = 0x900a8; -pub const IO_REPARSE_TAG_SYMLINK: ULONG = 0xa000000c; -pub const IO_REPARSE_TAG_MOUNT_POINT: ULONG = 0xa0000003; pub const SYMLINK_FLAG_RELATIVE: ULONG = 0x1; pub const SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD = 0x1; pub const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: DWORD = 0x2; -pub const MOUNTMGRCONTROLTYPE = 0x0000006D; - pub const MOUNTMGR_MOUNT_POINT = extern struct { SymbolicLinkNameOffset: ULONG, SymbolicLinkNameLength: USHORT, @@ -5077,7 +6339,6 @@ pub const MOUNTMGR_MOUNT_POINTS = extern struct { NumberOfMountPoints: ULONG, MountPoints: [1]MOUNTMGR_MOUNT_POINT, }; -pub const IOCTL_MOUNTMGR_QUERY_POINTS = CTL_CODE(MOUNTMGRCONTROLTYPE, 2, .METHOD_BUFFERED, FILE_ANY_ACCESS); pub const MOUNTMGR_TARGET_NAME = extern struct { DeviceNameLength: USHORT, @@ -5087,7 +6348,6 @@ pub const MOUNTMGR_VOLUME_PATHS = extern struct { MultiSzLength: ULONG, MultiSz: [1]WCHAR, }; -pub const IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH = CTL_CODE(MOUNTMGRCONTROLTYPE, 12, .METHOD_BUFFERED, FILE_ANY_ACCESS); pub const OBJECT_INFORMATION_CLASS = enum(c_int) { ObjectBasicInformation = 0, @@ -5479,113 +6739,6 @@ pub const SYSTEM_BASIC_INFORMATION = extern struct { NumberOfProcessors: UCHAR, }; -pub const THREADINFOCLASS = enum(c_int) { - ThreadBasicInformation, - ThreadTimes, - ThreadPriority, - ThreadBasePriority, - ThreadAffinityMask, - ThreadImpersonationToken, - ThreadDescriptorTableEntry, - ThreadEnableAlignmentFaultFixup, - ThreadEventPair_Reusable, - ThreadQuerySetWin32StartAddress, - ThreadZeroTlsCell, - ThreadPerformanceCount, - ThreadAmILastThread, - ThreadIdealProcessor, - ThreadPriorityBoost, - ThreadSetTlsArrayAddress, - ThreadIsIoPending, - // Windows 2000+ from here - ThreadHideFromDebugger, - // Windows XP+ from here - ThreadBreakOnTermination, - ThreadSwitchLegacyState, - ThreadIsTerminated, - // Windows Vista+ from here - ThreadLastSystemCall, - ThreadIoPriority, - ThreadCycleTime, - ThreadPagePriority, - ThreadActualBasePriority, - ThreadTebInformation, - ThreadCSwitchMon, - // Windows 7+ from here - ThreadCSwitchPmu, - ThreadWow64Context, - ThreadGroupInformation, - ThreadUmsInformation, - ThreadCounterProfiling, - ThreadIdealProcessorEx, - // Windows 8+ from here - ThreadCpuAccountingInformation, - // Windows 8.1+ from here - ThreadSuspendCount, - // Windows 10+ from here - ThreadHeterogeneousCpuPolicy, - ThreadContainerId, - ThreadNameInformation, - ThreadSelectedCpuSets, - ThreadSystemThreadInformation, - ThreadActualGroupAffinity, -}; - -pub const PROCESSINFOCLASS = enum(c_int) { - ProcessBasicInformation, - ProcessQuotaLimits, - ProcessIoCounters, - ProcessVmCounters, - ProcessTimes, - ProcessBasePriority, - ProcessRaisePriority, - ProcessDebugPort, - ProcessExceptionPort, - ProcessAccessToken, - ProcessLdtInformation, - ProcessLdtSize, - ProcessDefaultHardErrorMode, - ProcessIoPortHandlers, - ProcessPooledUsageAndLimits, - ProcessWorkingSetWatch, - ProcessUserModeIOPL, - ProcessEnableAlignmentFaultFixup, - ProcessPriorityClass, - ProcessWx86Information, - ProcessHandleCount, - ProcessAffinityMask, - ProcessPriorityBoost, - ProcessDeviceMap, - ProcessSessionInformation, - ProcessForegroundInformation, - ProcessWow64Information, - ProcessImageFileName, - ProcessLUIDDeviceMapsEnabled, - ProcessBreakOnTermination, - ProcessDebugObjectHandle, - ProcessDebugFlags, - ProcessHandleTracing, - ProcessIoPriority, - ProcessExecuteFlags, - ProcessTlsInformation, - ProcessCookie, - ProcessImageInformation, - ProcessCycleTime, - ProcessPagePriority, - ProcessInstrumentationCallback, - ProcessThreadStackAllocation, - ProcessWorkingSetWatchEx, - ProcessImageFileNameWin32, - ProcessImageFileMapping, - ProcessAffinityUpdateMode, - ProcessMemoryAllocationMode, - ProcessGroupInformation, - ProcessTokenVirtualizationEnabled, - ProcessConsoleHostProcess, - ProcessWindowInformation, - MaxProcessInfoClass, -}; - pub const PROCESS_BASIC_INFORMATION = extern struct { ExitStatus: NTSTATUS, PebBaseAddress: *PEB, @@ -5641,7 +6794,7 @@ pub fn ProcessBaseAddress(handle: HANDLE) ProcessBaseAddressError!HMODULE { var nread: DWORD = 0; const rc = ntdll.NtQueryInformationProcess( handle, - .ProcessBasicInformation, + .BasicInformation, &info, @sizeOf(PROCESS_BASIC_INFORMATION), &nread, diff --git a/lib/std/os/windows/advapi32.zig b/lib/std/os/windows/advapi32.zig index bf438e277672..90f16b1ec9d0 100644 --- a/lib/std/os/windows/advapi32.zig +++ b/lib/std/os/windows/advapi32.zig @@ -28,11 +28,6 @@ pub extern "advapi32" fn RegQueryValueExW( pub extern "advapi32" fn RegCloseKey(hKey: HKEY) callconv(.winapi) LSTATUS; -// RtlGenRandom is known as SystemFunction036 under advapi32 -// http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx */ -pub extern "advapi32" fn SystemFunction036(output: [*]u8, length: ULONG) callconv(.winapi) BOOL; -pub const RtlGenRandom = SystemFunction036; - pub const RRF = struct { pub const RT_ANY: DWORD = 0x0000ffff; diff --git a/lib/std/os/windows/kernel32.zig b/lib/std/os/windows/kernel32.zig index 7f746057a962..1ef3d0e55ec6 100644 --- a/lib/std/os/windows/kernel32.zig +++ b/lib/std/os/windows/kernel32.zig @@ -1,6 +1,7 @@ const std = @import("../../std.zig"); const windows = std.os.windows; +const ACCESS_MASK = windows.ACCESS_MASK; const BOOL = windows.BOOL; const CONDITION_VARIABLE = windows.CONDITION_VARIABLE; const CONSOLE_SCREEN_BUFFER_INFO = windows.CONSOLE_SCREEN_BUFFER_INFO; @@ -66,7 +67,7 @@ pub extern "kernel32" fn CancelIoEx( pub extern "kernel32" fn CreateFileW( lpFileName: LPCWSTR, - dwDesiredAccess: DWORD, + dwDesiredAccess: ACCESS_MASK, dwShareMode: DWORD, lpSecurityAttributes: ?*SECURITY_ATTRIBUTES, dwCreationDisposition: DWORD, @@ -160,7 +161,7 @@ pub extern "kernel32" fn DuplicateHandle( hSourceHandle: HANDLE, hTargetProcessHandle: HANDLE, lpTargetHandle: *HANDLE, - dwDesiredAccess: DWORD, + dwDesiredAccess: ACCESS_MASK, bInheritHandle: BOOL, dwOptions: DWORD, ) callconv(.winapi) BOOL; @@ -264,7 +265,7 @@ pub extern "kernel32" fn CreateProcessW( lpThreadAttributes: ?*SECURITY_ATTRIBUTES, bInheritHandles: BOOL, dwCreationFlags: windows.CreateProcessFlags, - lpEnvironment: ?LPVOID, + lpEnvironment: ?[*:0]const u16, lpCurrentDirectory: ?LPCWSTR, lpStartupInfo: *STARTUPINFOW, lpProcessInformation: *PROCESS_INFORMATION, @@ -308,9 +309,6 @@ pub extern "kernel32" fn CreateThread( lpThreadId: ?*DWORD, ) callconv(.winapi) ?HANDLE; -// TODO: Wrapper around RtlDelayExecution. -pub extern "kernel32" fn SwitchToThread() callconv(.winapi) BOOL; - // Locks, critical sections, initializers pub extern "kernel32" fn InitOnceExecuteOnce( @@ -401,34 +399,6 @@ pub extern "kernel32" fn ReadConsoleOutputCharacterW( lpNumberOfCharsRead: *DWORD, ) callconv(.winapi) BOOL; -// Memory Mapping/Allocation - -// TODO: Wrapper around RtlCreateHeap. -pub extern "kernel32" fn HeapCreate( - flOptions: DWORD, - dwInitialSize: SIZE_T, - dwMaximumSize: SIZE_T, -) callconv(.winapi) ?HANDLE; - -// TODO: Fowrarder to RtlFreeHeap before win11_zn. -// Since win11_zn this function points to unexported symbol RtlFreeHeapFast. -// See https://github.com/ziglang/zig/pull/25766#discussion_r2479727640 -pub extern "kernel32" fn HeapFree( - hHeap: HANDLE, - dwFlags: DWORD, - lpMem: LPVOID, -) callconv(.winapi) BOOL; - -// TODO: Wrapper around RtlValidateHeap (BOOLEAN -> BOOL) -pub extern "kernel32" fn HeapValidate( - hHeap: HANDLE, - dwFlags: DWORD, - lpMem: ?*const anyopaque, -) callconv(.winapi) BOOL; - -// TODO: Getter for peb.ProcessHeap -pub extern "kernel32" fn GetProcessHeap() callconv(.winapi) ?HANDLE; - // Code Libraries/Modules // TODO: Wrapper around LdrGetDllFullName. diff --git a/lib/std/os/windows/ntdll.zig b/lib/std/os/windows/ntdll.zig index d323fbd5b5dc..7e22db7a9909 100644 --- a/lib/std/os/windows/ntdll.zig +++ b/lib/std/os/windows/ntdll.zig @@ -1,277 +1,279 @@ const std = @import("../../std.zig"); const windows = std.os.windows; +const ACCESS_MASK = windows.ACCESS_MASK; const BOOL = windows.BOOL; +const BOOLEAN = windows.BOOLEAN; +const CONDITION_VARIABLE = windows.CONDITION_VARIABLE; +const CONTEXT = windows.CONTEXT; +const CRITICAL_SECTION = windows.CRITICAL_SECTION; +const CTL_CODE = windows.CTL_CODE; +const CURDIR = windows.CURDIR; const DWORD = windows.DWORD; const DWORD64 = windows.DWORD64; -const ULONG = windows.ULONG; -const ULONG_PTR = windows.ULONG_PTR; -const NTSTATUS = windows.NTSTATUS; -const WORD = windows.WORD; +const ERESOURCE = windows.ERESOURCE; +const EVENT_TYPE = windows.EVENT_TYPE; +const EXCEPTION_ROUTINE = windows.EXCEPTION_ROUTINE; +const FILE = windows.FILE; +const FS_INFORMATION_CLASS = windows.FS_INFORMATION_CLASS; const HANDLE = windows.HANDLE; -const ACCESS_MASK = windows.ACCESS_MASK; +const HEAP = windows.HEAP; const IO_APC_ROUTINE = windows.IO_APC_ROUTINE; -const BOOLEAN = windows.BOOLEAN; -const OBJECT_ATTRIBUTES = windows.OBJECT_ATTRIBUTES; -const PVOID = windows.PVOID; const IO_STATUS_BLOCK = windows.IO_STATUS_BLOCK; +const KNONVOLATILE_CONTEXT_POINTERS = windows.KNONVOLATILE_CONTEXT_POINTERS; const LARGE_INTEGER = windows.LARGE_INTEGER; +const LOGICAL = windows.LOGICAL; +const LONG = windows.LONG; +const LPCVOID = windows.LPCVOID; +const LPVOID = windows.LPVOID; +const MEM = windows.MEM; +const NTSTATUS = windows.NTSTATUS; +const OBJECT_ATTRIBUTES = windows.OBJECT_ATTRIBUTES; const OBJECT_INFORMATION_CLASS = windows.OBJECT_INFORMATION_CLASS; -const FILE_INFORMATION_CLASS = windows.FILE_INFORMATION_CLASS; -const FS_INFORMATION_CLASS = windows.FS_INFORMATION_CLASS; -const UNICODE_STRING = windows.UNICODE_STRING; -const RTL_OSVERSIONINFOW = windows.RTL_OSVERSIONINFOW; -const FILE_BASIC_INFORMATION = windows.FILE_BASIC_INFORMATION; -const SIZE_T = windows.SIZE_T; -const CURDIR = windows.CURDIR; +const PAGE = windows.PAGE; const PCWSTR = windows.PCWSTR; +const PROCESSINFOCLASS = windows.PROCESSINFOCLASS; +const PVOID = windows.PVOID; +const RTL_OSVERSIONINFOW = windows.RTL_OSVERSIONINFOW; const RTL_QUERY_REGISTRY_TABLE = windows.RTL_QUERY_REGISTRY_TABLE; -const CONTEXT = windows.CONTEXT; -const UNWIND_HISTORY_TABLE = windows.UNWIND_HISTORY_TABLE; const RUNTIME_FUNCTION = windows.RUNTIME_FUNCTION; -const KNONVOLATILE_CONTEXT_POINTERS = windows.KNONVOLATILE_CONTEXT_POINTERS; -const EXCEPTION_ROUTINE = windows.EXCEPTION_ROUTINE; +const SEC = windows.SEC; +const SECTION_INHERIT = windows.SECTION_INHERIT; +const SIZE_T = windows.SIZE_T; +const SRWLOCK = windows.SRWLOCK; const SYSTEM_INFORMATION_CLASS = windows.SYSTEM_INFORMATION_CLASS; const THREADINFOCLASS = windows.THREADINFOCLASS; -const PROCESSINFOCLASS = windows.PROCESSINFOCLASS; -const LPVOID = windows.LPVOID; -const LPCVOID = windows.LPCVOID; -const SECTION_INHERIT = windows.SECTION_INHERIT; +const ULONG = windows.ULONG; +const ULONG_PTR = windows.ULONG_PTR; +const UNICODE_STRING = windows.UNICODE_STRING; +const UNWIND_HISTORY_TABLE = windows.UNWIND_HISTORY_TABLE; +const USHORT = windows.USHORT; const VECTORED_EXCEPTION_HANDLER = windows.VECTORED_EXCEPTION_HANDLER; -const CRITICAL_SECTION = windows.CRITICAL_SECTION; -const SRWLOCK = windows.SRWLOCK; -const CONDITION_VARIABLE = windows.CONDITION_VARIABLE; +const WORD = windows.WORD; -pub extern "ntdll" fn NtQueryInformationProcess( - ProcessHandle: HANDLE, - ProcessInformationClass: PROCESSINFOCLASS, - ProcessInformation: *anyopaque, - ProcessInformationLength: ULONG, - ReturnLength: ?*ULONG, -) callconv(.winapi) NTSTATUS; +// ref: km/ntifs.h -pub extern "ntdll" fn NtQueryInformationThread( - ThreadHandle: HANDLE, - ThreadInformationClass: THREADINFOCLASS, - ThreadInformation: *anyopaque, - ThreadInformationLength: ULONG, - ReturnLength: ?*ULONG, -) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn RtlCreateHeap( + Flags: HEAP.FLAGS.CREATE, + HeapBase: ?PVOID, + ReserveSize: SIZE_T, + CommitSize: SIZE_T, + Lock: ?*ERESOURCE, + Parameters: ?*const HEAP.RTL_PARAMETERS, +) callconv(.winapi) ?*HEAP; -pub extern "ntdll" fn NtQuerySystemInformation( - SystemInformationClass: SYSTEM_INFORMATION_CLASS, - SystemInformation: PVOID, - SystemInformationLength: ULONG, - ReturnLength: ?*ULONG, -) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn RtlDestroyHeap( + HeapHandle: *HEAP, +) callconv(.winapi) ?*HEAP; -pub extern "ntdll" fn NtSetInformationThread( - ThreadHandle: HANDLE, - ThreadInformationClass: THREADINFOCLASS, - ThreadInformation: *const anyopaque, - ThreadInformationLength: ULONG, -) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn RtlAllocateHeap( + HeapHandle: *HEAP, + Flags: HEAP.FLAGS.ALLOCATION, + Size: SIZE_T, +) callconv(.winapi) ?PVOID; + +pub extern "ntdll" fn RtlFreeHeap( + HeapHandle: *HEAP, + Flags: HEAP.FLAGS.ALLOCATION, + BaseAddress: ?PVOID, +) callconv(.winapi) LOGICAL; -pub extern "ntdll" fn RtlGetVersion( - lpVersionInformation: *RTL_OSVERSIONINFOW, -) callconv(.winapi) NTSTATUS; pub extern "ntdll" fn RtlCaptureStackBackTrace( - FramesToSkip: DWORD, - FramesToCapture: DWORD, + FramesToSkip: ULONG, + FramesToCapture: ULONG, BackTrace: **anyopaque, - BackTraceHash: ?*DWORD, -) callconv(.winapi) WORD; -pub extern "ntdll" fn RtlCaptureContext(ContextRecord: *CONTEXT) callconv(.winapi) void; -pub extern "ntdll" fn RtlLookupFunctionEntry( - ControlPc: DWORD64, - ImageBase: *DWORD64, - HistoryTable: *UNWIND_HISTORY_TABLE, -) callconv(.winapi) ?*RUNTIME_FUNCTION; -pub extern "ntdll" fn RtlVirtualUnwind( - HandlerType: DWORD, - ImageBase: DWORD64, - ControlPc: DWORD64, - FunctionEntry: *RUNTIME_FUNCTION, - ContextRecord: *CONTEXT, - HandlerData: *?PVOID, - EstablisherFrame: *DWORD64, - ContextPointers: ?*KNONVOLATILE_CONTEXT_POINTERS, -) callconv(.winapi) *EXCEPTION_ROUTINE; -pub extern "ntdll" fn RtlGetSystemTimePrecise() callconv(.winapi) LARGE_INTEGER; -pub extern "ntdll" fn NtQueryInformationFile( - FileHandle: HANDLE, - IoStatusBlock: *IO_STATUS_BLOCK, - FileInformation: *anyopaque, - Length: ULONG, - FileInformationClass: FILE_INFORMATION_CLASS, -) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn NtSetInformationFile( - FileHandle: HANDLE, - IoStatusBlock: *IO_STATUS_BLOCK, - FileInformation: PVOID, - Length: ULONG, - FileInformationClass: FILE_INFORMATION_CLASS, -) callconv(.winapi) NTSTATUS; + BackTraceHash: ?*ULONG, +) callconv(.winapi) USHORT; -pub extern "ntdll" fn NtQueryAttributesFile( - ObjectAttributes: *OBJECT_ATTRIBUTES, - FileAttributes: *FILE_BASIC_INFORMATION, -) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn RtlCaptureContext( + ContextRecord: *CONTEXT, +) callconv(.winapi) void; -pub extern "ntdll" fn RtlQueryPerformanceCounter(PerformanceCounter: *LARGE_INTEGER) callconv(.winapi) BOOL; -pub extern "ntdll" fn RtlQueryPerformanceFrequency(PerformanceFrequency: *LARGE_INTEGER) callconv(.winapi) BOOL; -pub extern "ntdll" fn NtQueryPerformanceCounter( - PerformanceCounter: *LARGE_INTEGER, - PerformanceFrequency: ?*LARGE_INTEGER, +pub extern "ntdll" fn NtSetInformationThread( + ThreadHandle: HANDLE, + ThreadInformationClass: THREADINFOCLASS, + ThreadInformation: *const anyopaque, + ThreadInformationLength: ULONG, ) callconv(.winapi) NTSTATUS; pub extern "ntdll" fn NtCreateFile( FileHandle: *HANDLE, DesiredAccess: ACCESS_MASK, - ObjectAttributes: *OBJECT_ATTRIBUTES, + ObjectAttributes: *const OBJECT_ATTRIBUTES, IoStatusBlock: *IO_STATUS_BLOCK, - AllocationSize: ?*LARGE_INTEGER, - FileAttributes: ULONG, - ShareAccess: ULONG, - CreateDisposition: ULONG, - CreateOptions: ULONG, + AllocationSize: ?*const LARGE_INTEGER, + FileAttributes: FILE.ATTRIBUTE, + ShareAccess: FILE.SHARE, + CreateDisposition: FILE.CREATE_DISPOSITION, + CreateOptions: FILE.MODE, EaBuffer: ?*anyopaque, EaLength: ULONG, ) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn NtCreateSection( - SectionHandle: *HANDLE, - DesiredAccess: ACCESS_MASK, - ObjectAttributes: ?*OBJECT_ATTRIBUTES, - MaximumSize: ?*LARGE_INTEGER, - SectionPageProtection: ULONG, - AllocationAttributes: ULONG, - FileHandle: ?HANDLE, -) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn NtMapViewOfSection( - SectionHandle: HANDLE, - ProcessHandle: HANDLE, - BaseAddress: *PVOID, - ZeroBits: ?*ULONG, - CommitSize: SIZE_T, - SectionOffset: ?*LARGE_INTEGER, - ViewSize: *SIZE_T, - InheritDispostion: SECTION_INHERIT, - AllocationType: ULONG, - Win32Protect: ULONG, -) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn NtUnmapViewOfSection( - ProcessHandle: HANDLE, - BaseAddress: PVOID, -) callconv(.winapi) NTSTATUS; + pub extern "ntdll" fn NtDeviceIoControlFile( FileHandle: HANDLE, Event: ?HANDLE, - ApcRoutine: ?IO_APC_ROUTINE, + ApcRoutine: ?*const IO_APC_ROUTINE, ApcContext: ?*anyopaque, IoStatusBlock: *IO_STATUS_BLOCK, - IoControlCode: ULONG, + IoControlCode: CTL_CODE, InputBuffer: ?*const anyopaque, InputBufferLength: ULONG, OutputBuffer: ?PVOID, OutputBufferLength: ULONG, ) callconv(.winapi) NTSTATUS; + pub extern "ntdll" fn NtFsControlFile( FileHandle: HANDLE, Event: ?HANDLE, - ApcRoutine: ?IO_APC_ROUTINE, + ApcRoutine: ?*const IO_APC_ROUTINE, ApcContext: ?*anyopaque, IoStatusBlock: *IO_STATUS_BLOCK, - FsControlCode: ULONG, + FsControlCode: CTL_CODE, InputBuffer: ?*const anyopaque, InputBufferLength: ULONG, OutputBuffer: ?PVOID, OutputBufferLength: ULONG, ) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn NtClose(Handle: HANDLE) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn RtlDosPathNameToNtPathName_U( - DosPathName: [*:0]const u16, - NtPathName: *UNICODE_STRING, - NtFileNamePart: ?*?[*:0]const u16, - DirectoryInfo: ?*CURDIR, -) callconv(.winapi) BOOL; -pub extern "ntdll" fn RtlFreeUnicodeString(UnicodeString: *UNICODE_STRING) callconv(.winapi) void; -/// Returns the number of bytes written to `Buffer`. -/// If the returned count is larger than `BufferByteLength`, the buffer was too small. -/// If the returned count is zero, an error occurred. -pub extern "ntdll" fn RtlGetFullPathName_U( - FileName: [*:0]const u16, - BufferByteLength: ULONG, - Buffer: [*]u16, - ShortName: ?*[*:0]const u16, -) callconv(.winapi) windows.ULONG; +pub extern "ntdll" fn NtLockFile( + FileHandle: HANDLE, + Event: ?HANDLE, + ApcRoutine: ?*const IO_APC_ROUTINE, + ApcContext: ?*anyopaque, + IoStatusBlock: *IO_STATUS_BLOCK, + ByteOffset: *const LARGE_INTEGER, + Length: *const LARGE_INTEGER, + Key: ?*const ULONG, + FailImmediately: BOOLEAN, + ExclusiveLock: BOOLEAN, +) callconv(.winapi) NTSTATUS; + +pub extern "ntdll" fn NtOpenFile( + FileHandle: *HANDLE, + DesiredAccess: ACCESS_MASK, + ObjectAttributes: *const OBJECT_ATTRIBUTES, + IoStatusBlock: *IO_STATUS_BLOCK, + ShareAccess: FILE.SHARE, + OpenOptions: FILE.MODE, +) callconv(.winapi) NTSTATUS; pub extern "ntdll" fn NtQueryDirectoryFile( FileHandle: HANDLE, Event: ?HANDLE, - ApcRoutine: ?IO_APC_ROUTINE, + ApcRoutine: ?*const IO_APC_ROUTINE, ApcContext: ?*anyopaque, IoStatusBlock: *IO_STATUS_BLOCK, FileInformation: *anyopaque, Length: ULONG, - FileInformationClass: FILE_INFORMATION_CLASS, + FileInformationClass: FILE.INFORMATION_CLASS, ReturnSingleEntry: BOOLEAN, - FileName: ?*UNICODE_STRING, + FileName: ?*const UNICODE_STRING, RestartScan: BOOLEAN, ) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn NtCreateKeyedEvent( - KeyedEventHandle: *HANDLE, - DesiredAccess: ACCESS_MASK, - ObjectAttributes: ?PVOID, - Flags: ULONG, +pub extern "ntdll" fn NtQueryInformationFile( + FileHandle: HANDLE, + IoStatusBlock: *IO_STATUS_BLOCK, + FileInformation: *anyopaque, + Length: ULONG, + FileInformationClass: FILE.INFORMATION_CLASS, ) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn NtReleaseKeyedEvent( - EventHandle: ?HANDLE, - Key: ?*const anyopaque, - Alertable: BOOLEAN, - Timeout: ?*const LARGE_INTEGER, +pub extern "ntdll" fn NtQueryVolumeInformationFile( + FileHandle: HANDLE, + IoStatusBlock: *IO_STATUS_BLOCK, + FsInformation: *anyopaque, + Length: ULONG, + FsInformationClass: FS_INFORMATION_CLASS, ) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn NtWaitForKeyedEvent( - EventHandle: ?HANDLE, - Key: ?*const anyopaque, - Alertable: BOOLEAN, - Timeout: ?*const LARGE_INTEGER, +pub extern "ntdll" fn NtReadFile( + FileHandle: HANDLE, + Event: ?HANDLE, + ApcRoutine: ?*const IO_APC_ROUTINE, + ApcContext: ?*anyopaque, + IoStatusBlock: *IO_STATUS_BLOCK, + Buffer: *anyopaque, + Length: ULONG, + ByteOffset: ?*const LARGE_INTEGER, + Key: ?*const ULONG, +) callconv(.winapi) NTSTATUS; + +pub extern "ntdll" fn NtSetInformationFile( + FileHandle: HANDLE, + IoStatusBlock: *IO_STATUS_BLOCK, + FileInformation: *const anyopaque, + Length: ULONG, + FileInformationClass: FILE.INFORMATION_CLASS, +) callconv(.winapi) NTSTATUS; + +pub extern "ntdll" fn NtWriteFile( + FileHandle: HANDLE, + Event: ?HANDLE, + ApcRoutine: ?*const IO_APC_ROUTINE, + ApcContext: ?*anyopaque, + IoStatusBlock: *IO_STATUS_BLOCK, + Buffer: *const anyopaque, + Length: ULONG, + ByteOffset: ?*const LARGE_INTEGER, + Key: ?*const ULONG, ) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn RtlSetCurrentDirectory_U(PathName: *UNICODE_STRING) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn NtUnlockFile( + FileHandle: HANDLE, + IoStatusBlock: *IO_STATUS_BLOCK, + ByteOffset: *const LARGE_INTEGER, + Length: *const LARGE_INTEGER, + Key: ULONG, +) callconv(.winapi) NTSTATUS; pub extern "ntdll" fn NtQueryObject( Handle: HANDLE, ObjectInformationClass: OBJECT_INFORMATION_CLASS, - ObjectInformation: PVOID, + ObjectInformation: ?PVOID, ObjectInformationLength: ULONG, ReturnLength: ?*ULONG, ) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn NtQueryVolumeInformationFile( - FileHandle: HANDLE, - IoStatusBlock: *IO_STATUS_BLOCK, - FsInformation: *anyopaque, - Length: ULONG, - FsInformationClass: FS_INFORMATION_CLASS, +pub extern "ntdll" fn NtClose( + Handle: HANDLE, ) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn RtlWakeAddressAll( - Address: ?*const anyopaque, -) callconv(.winapi) void; +pub extern "ntdll" fn NtCreateSection( + SectionHandle: *HANDLE, + DesiredAccess: ACCESS_MASK, + ObjectAttributes: ?*const OBJECT_ATTRIBUTES, + MaximumSize: ?*const LARGE_INTEGER, + SectionPageProtection: PAGE, + AllocationAttributes: SEC, + FileHandle: ?HANDLE, +) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn RtlWakeAddressSingle( - Address: ?*const anyopaque, -) callconv(.winapi) void; +pub extern "ntdll" fn NtAllocateVirtualMemory( + ProcessHandle: HANDLE, + BaseAddress: *PVOID, + ZeroBits: ULONG_PTR, + RegionSize: *SIZE_T, + AllocationType: MEM.ALLOCATE, + Protect: PAGE, +) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn RtlWaitOnAddress( - Address: ?*const anyopaque, - CompareAddress: ?*const anyopaque, - AddressSize: SIZE_T, - Timeout: ?*const LARGE_INTEGER, +pub extern "ntdll" fn NtFreeVirtualMemory( + ProcessHandle: HANDLE, + BaseAddress: *PVOID, + RegionSize: *SIZE_T, + FreeType: MEM.FREE, +) callconv(.winapi) NTSTATUS; + +// ref: km/wdm.h + +pub extern "ntdll" fn RtlQueryRegistryValues( + RelativeTo: ULONG, + Path: PCWSTR, + QueryTable: [*]RTL_QUERY_REGISTRY_TABLE, + Context: ?*const anyopaque, + Environment: ?*const anyopaque, ) callconv(.winapi) NTSTATUS; pub extern "ntdll" fn RtlEqualUnicodeString( @@ -284,39 +286,153 @@ pub extern "ntdll" fn RtlUpcaseUnicodeChar( SourceCharacter: u16, ) callconv(.winapi) u16; -pub extern "ntdll" fn NtLockFile( - FileHandle: HANDLE, - Event: ?HANDLE, - ApcRoutine: ?*IO_APC_ROUTINE, - ApcContext: ?*anyopaque, - IoStatusBlock: *IO_STATUS_BLOCK, - ByteOffset: *const LARGE_INTEGER, - Length: *const LARGE_INTEGER, - Key: ?*ULONG, - FailImmediately: BOOLEAN, - ExclusiveLock: BOOLEAN, +pub extern "ntdll" fn RtlFreeUnicodeString( + UnicodeString: *UNICODE_STRING, +) callconv(.winapi) void; + +pub extern "ntdll" fn RtlGetVersion( + lpVersionInformation: *RTL_OSVERSIONINFOW, ) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn NtUnlockFile( - FileHandle: HANDLE, +// ref: um/winnt.h + +pub extern "ntdll" fn RtlLookupFunctionEntry( + ControlPc: usize, + ImageBase: *usize, + HistoryTable: *UNWIND_HISTORY_TABLE, +) callconv(.winapi) ?*RUNTIME_FUNCTION; + +pub extern "ntdll" fn RtlVirtualUnwind( + HandlerType: DWORD, + ImageBase: usize, + ControlPc: usize, + FunctionEntry: *RUNTIME_FUNCTION, + ContextRecord: *CONTEXT, + HandlerData: *?PVOID, + EstablisherFrame: *usize, + ContextPointers: ?*KNONVOLATILE_CONTEXT_POINTERS, +) callconv(.winapi) *EXCEPTION_ROUTINE; + +// ref: um/winternl.h + +pub extern "ntdll" fn NtWaitForSingleObject( + Handle: HANDLE, + Alertable: BOOLEAN, + Timeout: ?*const LARGE_INTEGER, +) callconv(.winapi) NTSTATUS; + +pub extern "ntdll" fn NtQueryInformationProcess( + ProcessHandle: HANDLE, + ProcessInformationClass: PROCESSINFOCLASS, + ProcessInformation: *anyopaque, + ProcessInformationLength: ULONG, + ReturnLength: ?*ULONG, +) callconv(.winapi) NTSTATUS; + +pub extern "ntdll" fn NtQueryInformationThread( + ThreadHandle: HANDLE, + ThreadInformationClass: THREADINFOCLASS, + ThreadInformation: *anyopaque, + ThreadInformationLength: ULONG, + ReturnLength: ?*ULONG, +) callconv(.winapi) NTSTATUS; + +pub extern "ntdll" fn NtQuerySystemInformation( + SystemInformationClass: SYSTEM_INFORMATION_CLASS, + SystemInformation: PVOID, + SystemInformationLength: ULONG, + ReturnLength: ?*ULONG, +) callconv(.winapi) NTSTATUS; + +// ref none + +pub extern "ntdll" fn NtQueryAttributesFile( + ObjectAttributes: *const OBJECT_ATTRIBUTES, + FileAttributes: *FILE.BASIC_INFORMATION, +) callconv(.winapi) NTSTATUS; + +pub extern "ntdll" fn NtCreateEvent( + EventHandle: *HANDLE, + DesiredAccess: ACCESS_MASK, + ObjectAttributes: ?*const OBJECT_ATTRIBUTES, + EventType: EVENT_TYPE, + InitialState: BOOLEAN, +) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn NtSetEvent( + EventHandle: HANDLE, + PreviousState: ?*LONG, +) callconv(.winapi) NTSTATUS; + +pub extern "ntdll" fn NtCreateKeyedEvent( + KeyedEventHandle: *HANDLE, + DesiredAccess: ACCESS_MASK, + ObjectAttributes: ?*const OBJECT_ATTRIBUTES, + Flags: ULONG, +) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn NtReleaseKeyedEvent( + EventHandle: ?HANDLE, + Key: ?*const anyopaque, + Alertable: BOOLEAN, + Timeout: ?*const LARGE_INTEGER, +) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn NtWaitForKeyedEvent( + EventHandle: ?HANDLE, + Key: ?*const anyopaque, + Alertable: BOOLEAN, + Timeout: ?*const LARGE_INTEGER, +) callconv(.winapi) NTSTATUS; + +pub extern "ntdll" fn NtCreateNamedPipeFile( + FileHandle: *HANDLE, + DesiredAccess: ACCESS_MASK, + ObjectAttributes: *const OBJECT_ATTRIBUTES, IoStatusBlock: *IO_STATUS_BLOCK, - ByteOffset: *const LARGE_INTEGER, - Length: *const LARGE_INTEGER, - Key: ?*ULONG, + ShareAccess: FILE.SHARE, + CreateDisposition: FILE.CREATE_DISPOSITION, + CreateOptions: FILE.MODE, + NamedPipeType: FILE.PIPE.TYPE, + ReadMode: FILE.PIPE.READ_MODE, + CompletionMode: FILE.PIPE.COMPLETION_MODE, + MaximumInstances: ULONG, + InboundQuota: ULONG, + OutboundQuota: ULONG, + DefaultTimeout: ?*const LARGE_INTEGER, +) callconv(.winapi) NTSTATUS; + +pub extern "ntdll" fn NtMapViewOfSection( + SectionHandle: HANDLE, + ProcessHandle: HANDLE, + BaseAddress: ?*PVOID, + ZeroBits: ?*const ULONG, + CommitSize: SIZE_T, + SectionOffset: ?*LARGE_INTEGER, + ViewSize: *SIZE_T, + InheritDispostion: SECTION_INHERIT, + AllocationType: MEM.MAP, + PageProtection: PAGE, +) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn NtUnmapViewOfSection( + ProcessHandle: HANDLE, + BaseAddress: PVOID, +) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn NtUnmapViewOfSectionEx( + ProcessHandle: HANDLE, + BaseAddress: PVOID, + UnmapFlags: MEM.UNMAP, ) callconv(.winapi) NTSTATUS; pub extern "ntdll" fn NtOpenKey( KeyHandle: *HANDLE, DesiredAccess: ACCESS_MASK, - ObjectAttributes: OBJECT_ATTRIBUTES, + ObjectAttributes: *const OBJECT_ATTRIBUTES, ) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn RtlQueryRegistryValues( - RelativeTo: ULONG, - Path: PCWSTR, - QueryTable: [*]RTL_QUERY_REGISTRY_TABLE, - Context: ?*anyopaque, - Environment: ?*anyopaque, +pub extern "ntdll" fn NtQueueApcThread( + ThreadHandle: HANDLE, + ApcRoutine: *const IO_APC_ROUTINE, + ApcArgument1: ?*anyopaque, + ApcArgument2: ?*anyopaque, + ApcArgument3: ?*anyopaque, ) callconv(.winapi) NTSTATUS; pub extern "ntdll" fn NtReadVirtualMemory( @@ -326,7 +442,6 @@ pub extern "ntdll" fn NtReadVirtualMemory( NumberOfBytesToRead: SIZE_T, NumberOfBytesRead: ?*SIZE_T, ) callconv(.winapi) NTSTATUS; - pub extern "ntdll" fn NtWriteVirtualMemory( ProcessHandle: HANDLE, BaseAddress: ?PVOID, @@ -334,51 +449,15 @@ pub extern "ntdll" fn NtWriteVirtualMemory( NumberOfBytesToWrite: SIZE_T, NumberOfBytesWritten: ?*SIZE_T, ) callconv(.winapi) NTSTATUS; - pub extern "ntdll" fn NtProtectVirtualMemory( ProcessHandle: HANDLE, BaseAddress: *?PVOID, NumberOfBytesToProtect: *SIZE_T, - NewAccessProtection: ULONG, - OldAccessProtection: *ULONG, -) callconv(.winapi) NTSTATUS; - -pub extern "ntdll" fn RtlExitUserProcess( - ExitStatus: u32, -) callconv(.winapi) noreturn; - -pub extern "ntdll" fn NtCreateNamedPipeFile( - FileHandle: *HANDLE, - DesiredAccess: ULONG, - ObjectAttributes: *OBJECT_ATTRIBUTES, - IoStatusBlock: *IO_STATUS_BLOCK, - ShareAccess: ULONG, - CreateDisposition: ULONG, - CreateOptions: ULONG, - NamedPipeType: ULONG, - ReadMode: ULONG, - CompletionMode: ULONG, - MaximumInstances: ULONG, - InboundQuota: ULONG, - OutboundQuota: ULONG, - DefaultTimeout: *LARGE_INTEGER, + NewAccessProtection: PAGE, + OldAccessProtection: *PAGE, ) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn NtAllocateVirtualMemory( - ProcessHandle: HANDLE, - BaseAddress: ?*PVOID, - ZeroBits: ULONG_PTR, - RegionSize: ?*SIZE_T, - AllocationType: ULONG, - PageProtection: ULONG, -) callconv(.winapi) NTSTATUS; - -pub extern "ntdll" fn NtFreeVirtualMemory( - ProcessHandle: HANDLE, - BaseAddress: ?*PVOID, - RegionSize: *SIZE_T, - FreeType: ULONG, -) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn NtYieldExecution() callconv(.winapi) NTSTATUS; pub extern "ntdll" fn RtlAddVectoredExceptionHandler( First: ULONG, @@ -388,6 +467,29 @@ pub extern "ntdll" fn RtlRemoveVectoredExceptionHandler( Handle: HANDLE, ) callconv(.winapi) ULONG; +pub extern "ntdll" fn RtlDosPathNameToNtPathName_U( + DosPathName: [*:0]const u16, + NtPathName: *UNICODE_STRING, + NtFileNamePart: ?*?[*:0]const u16, + DirectoryInfo: ?*CURDIR, +) callconv(.winapi) BOOL; + +pub extern "ntdll" fn RtlExitUserProcess( + ExitStatus: u32, +) callconv(.winapi) noreturn; + +/// Returns the number of bytes written to `Buffer`. +/// If the returned count is larger than `BufferByteLength`, the buffer was too small. +/// If the returned count is zero, an error occurred. +pub extern "ntdll" fn RtlGetFullPathName_U( + FileName: [*:0]const u16, + BufferByteLength: ULONG, + Buffer: [*]u16, + ShortName: ?*[*:0]const u16, +) callconv(.winapi) ULONG; + +pub extern "ntdll" fn RtlGetSystemTimePrecise() callconv(.winapi) LARGE_INTEGER; + pub extern "ntdll" fn RtlInitializeCriticalSection( lpCriticalSection: *CRITICAL_SECTION, ) callconv(.winapi) NTSTATUS; @@ -401,6 +503,28 @@ pub extern "ntdll" fn RtlDeleteCriticalSection( lpCriticalSection: *CRITICAL_SECTION, ) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn RtlQueryPerformanceCounter( + PerformanceCounter: *LARGE_INTEGER, +) callconv(.winapi) BOOL; +pub extern "ntdll" fn RtlQueryPerformanceFrequency( + PerformanceFrequency: *LARGE_INTEGER, +) callconv(.winapi) BOOL; +pub extern "ntdll" fn NtQueryPerformanceCounter( + PerformanceCounter: *LARGE_INTEGER, + PerformanceFrequency: ?*LARGE_INTEGER, +) callconv(.winapi) NTSTATUS; + +pub extern "ntdll" fn RtlReAllocateHeap( + HeapHandle: *HEAP, + Flags: HEAP.FLAGS.ALLOCATION, + BaseAddress: ?PVOID, + Size: SIZE_T, +) callconv(.winapi) ?PVOID; + +pub extern "ntdll" fn RtlSetCurrentDirectory_U( + PathName: *UNICODE_STRING, +) callconv(.winapi) NTSTATUS; + pub extern "ntdll" fn RtlTryAcquireSRWLockExclusive( SRWLock: *SRWLOCK, ) callconv(.winapi) BOOLEAN; @@ -411,6 +535,19 @@ pub extern "ntdll" fn RtlReleaseSRWLockExclusive( SRWLock: *SRWLOCK, ) callconv(.winapi) void; +pub extern "ntdll" fn RtlWakeAddressAll( + Address: ?*const anyopaque, +) callconv(.winapi) void; +pub extern "ntdll" fn RtlWakeAddressSingle( + Address: ?*const anyopaque, +) callconv(.winapi) void; +pub extern "ntdll" fn RtlWaitOnAddress( + Address: ?*const anyopaque, + CompareAddress: ?*const anyopaque, + AddressSize: SIZE_T, + Timeout: ?*const LARGE_INTEGER, +) callconv(.winapi) NTSTATUS; + pub extern "ntdll" fn RtlWakeConditionVariable( ConditionVariable: *CONDITION_VARIABLE, ) callconv(.winapi) void; @@ -418,14 +555,29 @@ pub extern "ntdll" fn RtlWakeAllConditionVariable( ConditionVariable: *CONDITION_VARIABLE, ) callconv(.winapi) void; -pub extern "ntdll" fn RtlReAllocateHeap( - HeapHandle: HANDLE, - Flags: ULONG, - BaseAddress: PVOID, - Size: SIZE_T, -) callconv(.winapi) ?PVOID; -pub extern "ntdll" fn RtlAllocateHeap( - HeapHandle: HANDLE, - Flags: ULONG, - Size: SIZE_T, -) callconv(.winapi) ?PVOID; +pub extern "ntdll" fn NtWaitForAlertByThreadId( + Address: ?*const anyopaque, + Timeout: ?*const LARGE_INTEGER, +) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn NtAlertThreadByThreadId( + ThreadId: DWORD, +) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn NtAlertMultipleThreadByThreadId( + ThreadIds: [*]const ULONG_PTR, + ThreadCount: ULONG, + Unknown1: ?*const anyopaque, + Unknown2: ?*const anyopaque, +) callconv(.winapi) NTSTATUS; + +pub extern "ntdll" fn NtOpenThread( + ThreadHandle: *HANDLE, + DesiredAccess: ACCESS_MASK, + ObjectAttributes: *const OBJECT_ATTRIBUTES, + ClientId: *const windows.CLIENT_ID, +) callconv(.winapi) NTSTATUS; + +pub extern "ntdll" fn NtCancelSynchronousIoFile( + ThreadHandle: HANDLE, + RequestToCancel: ?*IO_STATUS_BLOCK, + IoStatusBlock: *IO_STATUS_BLOCK, +) callconv(.winapi) NTSTATUS; diff --git a/lib/std/os/windows/test.zig b/lib/std/os/windows/test.zig index 0245583f5ba7..58eb4e0b9764 100644 --- a/lib/std/os/windows/test.zig +++ b/lib/std/os/windows/test.zig @@ -274,8 +274,8 @@ test "getWin32PathType vs RtlDetermineDosPathNameType_U" { std.debug.assert(std.unicode.wtf16LeToWtf8(wtf8_buf.items, path) == wtf8_len); const windows_type = RtlDetermineDosPathNameType_U(path); - const wtf16_type = windows.getWin32PathType(u16, path); - const wtf8_type = windows.getWin32PathType(u8, wtf8_buf.items); + const wtf16_type = std.fs.path.getWin32PathType(u16, path); + const wtf8_type = std.fs.path.getWin32PathType(u8, wtf8_buf.items); checkPathType(windows_type, wtf16_type) catch |err| { std.debug.print("expected type {}, got {} for path: {f}\n", .{ windows_type, wtf16_type, std.unicode.fmtUtf16Le(path) }); @@ -295,7 +295,7 @@ test "getWin32PathType vs RtlDetermineDosPathNameType_U" { } } -fn checkPathType(windows_type: RTL_PATH_TYPE, zig_type: windows.Win32PathType) !void { +fn checkPathType(windows_type: RTL_PATH_TYPE, zig_type: std.fs.path.Win32PathType) !void { const expected_windows_type: RTL_PATH_TYPE = switch (zig_type) { .unc_absolute => .UncAbsolute, .drive_absolute => .DriveAbsolute, diff --git a/lib/std/pdb.zig b/lib/std/pdb.zig index 36b0e04e5cfd..7e479de8d4fe 100644 --- a/lib/std/pdb.zig +++ b/lib/std/pdb.zig @@ -12,7 +12,7 @@ const math = std.math; const mem = std.mem; const coff = std.coff; const fs = std.fs; -const File = std.fs.File; +const File = std.Io.File; const debug = std.debug; const ArrayList = std.ArrayList; diff --git a/lib/std/posix.zig b/lib/std/posix.zig index 3e80466cd3b7..e883223b93cc 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -15,15 +15,16 @@ //! deal with the exception. const builtin = @import("builtin"); -const root = @import("root"); +const native_os = builtin.os.tag; + const std = @import("std.zig"); +const Io = std.Io; const mem = std.mem; const fs = std.fs; -const max_path_bytes = fs.max_path_bytes; +const max_path_bytes = std.fs.max_path_bytes; const maxInt = std.math.maxInt; const cast = std.math.cast; const assert = std.debug.assert; -const native_os = builtin.os.tag; const page_size_min = std.heap.page_size_min; test { @@ -53,6 +54,7 @@ else switch (native_os) { pub const uid_t = void; pub const gid_t = void; pub const mode_t = u0; + pub const nlink_t = u0; pub const ino_t = void; pub const IFNAMESIZE = {}; pub const SIG = void; @@ -119,7 +121,18 @@ pub const STDIN_FILENO = system.STDIN_FILENO; pub const STDOUT_FILENO = system.STDOUT_FILENO; pub const SYS = system.SYS; pub const Sigaction = system.Sigaction; -pub const Stat = system.Stat; +pub const Stat = switch (native_os) { + // Has no concept of `stat`. + .windows => void, + // The `stat` bits/wrappers are removed due to having to maintain the + // different varying `struct stat`s per target and libc, leading to runtime + // errors. + // + // Users targeting linux should add a comptime check and use `statx`, + // similar to how `std.fs.File.stat` does. + .linux => void, + else => system.Stat, +}; pub const T = system.T; pub const TCP = system.TCP; pub const VDSO = system.VDSO; @@ -298,268 +311,6 @@ pub fn close(fd: fd_t) void { } } -pub const FChmodError = error{ - AccessDenied, - PermissionDenied, - InputOutput, - SymLinkLoop, - FileNotFound, - SystemResources, - ReadOnlyFileSystem, -} || UnexpectedError; - -/// Changes the mode of the file referred to by the file descriptor. -/// -/// The process must have the correct privileges in order to do this -/// successfully, or must have the effective user ID matching the owner -/// of the file. -pub fn fchmod(fd: fd_t, mode: mode_t) FChmodError!void { - if (!fs.has_executable_bit) @compileError("fchmod unsupported by target OS"); - - while (true) { - const res = system.fchmod(fd, mode); - switch (errno(res)) { - .SUCCESS => return, - .INTR => continue, - .BADF => unreachable, - .FAULT => unreachable, - .INVAL => unreachable, - .ACCES => return error.AccessDenied, - .IO => return error.InputOutput, - .LOOP => return error.SymLinkLoop, - .NOENT => return error.FileNotFound, - .NOMEM => return error.SystemResources, - .NOTDIR => return error.FileNotFound, - .PERM => return error.PermissionDenied, - .ROFS => return error.ReadOnlyFileSystem, - else => |err| return unexpectedErrno(err), - } - } -} - -pub const FChmodAtError = FChmodError || error{ - /// A component of `path` exceeded `NAME_MAX`, or the entire path exceeded - /// `PATH_MAX`. - NameTooLong, - /// `path` resolves to a symbolic link, and `AT.SYMLINK_NOFOLLOW` was set - /// in `flags`. This error only occurs on Linux, where changing the mode of - /// a symbolic link has no meaning and can cause undefined behaviour on - /// certain filesystems. - /// - /// The procfs fallback was used but procfs was not mounted. - OperationNotSupported, - /// The procfs fallback was used but the process exceeded its open file - /// limit. - ProcessFdQuotaExceeded, - /// The procfs fallback was used but the system exceeded it open file limit. - SystemFdQuotaExceeded, - Canceled, -}; - -/// Changes the `mode` of `path` relative to the directory referred to by -/// `dirfd`. The process must have the correct privileges in order to do this -/// successfully, or must have the effective user ID matching the owner of the -/// file. -/// -/// On Linux the `fchmodat2` syscall will be used if available, otherwise a -/// workaround using procfs will be employed. Changing the mode of a symbolic -/// link with `AT.SYMLINK_NOFOLLOW` set will also return -/// `OperationNotSupported`, as: -/// -/// 1. Permissions on the link are ignored when resolving its target. -/// 2. This operation has been known to invoke undefined behaviour across -/// different filesystems[1]. -/// -/// [1]: https://sourceware.org/legacy-ml/libc-alpha/2020-02/msg00467.html. -pub inline fn fchmodat(dirfd: fd_t, path: []const u8, mode: mode_t, flags: u32) FChmodAtError!void { - if (!fs.has_executable_bit) @compileError("fchmodat unsupported by target OS"); - - // No special handling for linux is needed if we can use the libc fallback - // or `flags` is empty. Glibc only added the fallback in 2.32. - const skip_fchmodat_fallback = native_os != .linux or - (!builtin.abi.isAndroid() and std.c.versionCheck(.{ .major = 2, .minor = 32, .patch = 0 })) or - flags == 0; - - // This function is marked inline so that when flags is comptime-known, - // skip_fchmodat_fallback will be comptime-known true. - if (skip_fchmodat_fallback) - return fchmodat1(dirfd, path, mode, flags); - - return fchmodat2(dirfd, path, mode, flags); -} - -fn fchmodat1(dirfd: fd_t, path: []const u8, mode: mode_t, flags: u32) FChmodAtError!void { - const path_c = try toPosixPath(path); - while (true) { - const res = system.fchmodat(dirfd, &path_c, mode, flags); - switch (errno(res)) { - .SUCCESS => return, - .INTR => continue, - .BADF => unreachable, - .FAULT => unreachable, - .INVAL => unreachable, - .ACCES => return error.AccessDenied, - .IO => return error.InputOutput, - .LOOP => return error.SymLinkLoop, - .MFILE => return error.ProcessFdQuotaExceeded, - .NAMETOOLONG => return error.NameTooLong, - .NFILE => return error.SystemFdQuotaExceeded, - .NOENT => return error.FileNotFound, - .NOTDIR => return error.FileNotFound, - .NOMEM => return error.SystemResources, - .OPNOTSUPP => return error.OperationNotSupported, - .PERM => return error.PermissionDenied, - .ROFS => return error.ReadOnlyFileSystem, - else => |err| return unexpectedErrno(err), - } - } -} - -fn fchmodat2(dirfd: fd_t, path: []const u8, mode: mode_t, flags: u32) FChmodAtError!void { - const global = struct { - var has_fchmodat2: bool = true; - }; - const path_c = try toPosixPath(path); - const use_fchmodat2 = (builtin.os.isAtLeast(.linux, .{ .major = 6, .minor = 6, .patch = 0 }) orelse false) and - @atomicLoad(bool, &global.has_fchmodat2, .monotonic); - while (use_fchmodat2) { - // Later on this should be changed to `system.fchmodat2` - // when the musl/glibc add a wrapper. - const res = linux.fchmodat2(dirfd, &path_c, mode, flags); - switch (linux.errno(res)) { - .SUCCESS => return, - .INTR => continue, - .BADF => unreachable, - .FAULT => unreachable, - .INVAL => unreachable, - .ACCES => return error.AccessDenied, - .IO => return error.InputOutput, - .LOOP => return error.SymLinkLoop, - .NOENT => return error.FileNotFound, - .NOMEM => return error.SystemResources, - .NOTDIR => return error.FileNotFound, - .OPNOTSUPP => return error.OperationNotSupported, - .PERM => return error.PermissionDenied, - .ROFS => return error.ReadOnlyFileSystem, - - .NOSYS => { - @atomicStore(bool, &global.has_fchmodat2, false, .monotonic); - break; - }, - else => |err| return unexpectedErrno(err), - } - } - - // Fallback to changing permissions using procfs: - // - // 1. Open `path` as a `PATH` descriptor. - // 2. Stat the fd and check if it isn't a symbolic link. - // 3. Generate the procfs reference to the fd via `/proc/self/fd/{fd}`. - // 4. Pass the procfs path to `chmod` with the `mode`. - var pathfd: fd_t = undefined; - while (true) { - const rc = system.openat(dirfd, &path_c, .{ .PATH = true, .NOFOLLOW = true, .CLOEXEC = true }, @as(mode_t, 0)); - switch (errno(rc)) { - .SUCCESS => { - pathfd = @intCast(rc); - break; - }, - .INTR => continue, - .FAULT => unreachable, - .INVAL => unreachable, - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - .LOOP => return error.SymLinkLoop, - .MFILE => return error.ProcessFdQuotaExceeded, - .NAMETOOLONG => return error.NameTooLong, - .NFILE => return error.SystemFdQuotaExceeded, - .NOENT => return error.FileNotFound, - .NOMEM => return error.SystemResources, - else => |err| return unexpectedErrno(err), - } - } - defer close(pathfd); - - const stat = fstatatZ(pathfd, "", AT.EMPTY_PATH) catch |err| switch (err) { - error.NameTooLong => unreachable, - error.FileNotFound => unreachable, - error.Streaming => unreachable, - error.BadPathName => return error.Unexpected, - error.Canceled => return error.Canceled, - else => |e| return e, - }; - if ((stat.mode & S.IFMT) == S.IFLNK) - return error.OperationNotSupported; - - var procfs_buf: ["/proc/self/fd/-2147483648\x00".len]u8 = undefined; - const proc_path = std.fmt.bufPrintSentinel(procfs_buf[0..], "/proc/self/fd/{d}", .{pathfd}, 0) catch unreachable; - while (true) { - const res = system.chmod(proc_path, mode); - switch (errno(res)) { - // Getting NOENT here means that procfs isn't mounted. - .NOENT => return error.OperationNotSupported, - - .SUCCESS => return, - .INTR => continue, - .BADF => unreachable, - .FAULT => unreachable, - .INVAL => unreachable, - .ACCES => return error.AccessDenied, - .IO => return error.InputOutput, - .LOOP => return error.SymLinkLoop, - .NOMEM => return error.SystemResources, - .NOTDIR => return error.FileNotFound, - .PERM => return error.PermissionDenied, - .ROFS => return error.ReadOnlyFileSystem, - else => |err| return unexpectedErrno(err), - } - } -} - -pub const FChownError = error{ - AccessDenied, - PermissionDenied, - InputOutput, - SymLinkLoop, - FileNotFound, - SystemResources, - ReadOnlyFileSystem, -} || UnexpectedError; - -/// Changes the owner and group of the file referred to by the file descriptor. -/// The process must have the correct privileges in order to do this -/// successfully. The group may be changed by the owner of the directory to -/// any group of which the owner is a member. If the owner or group is -/// specified as `null`, the ID is not changed. -pub fn fchown(fd: fd_t, owner: ?uid_t, group: ?gid_t) FChownError!void { - switch (native_os) { - .windows, .wasi => @compileError("Unsupported OS"), - else => {}, - } - - while (true) { - const res = system.fchown(fd, owner orelse ~@as(uid_t, 0), group orelse ~@as(gid_t, 0)); - - switch (errno(res)) { - .SUCCESS => return, - .INTR => continue, - .BADF => unreachable, // Can be reached if the fd refers to a directory opened without `Dir.OpenOptions{ .iterate = true }` - - .FAULT => unreachable, - .INVAL => unreachable, - .ACCES => return error.AccessDenied, - .IO => return error.InputOutput, - .LOOP => return error.SymLinkLoop, - .NOENT => return error.FileNotFound, - .NOMEM => return error.SystemResources, - .NOTDIR => return error.FileNotFound, - .PERM => return error.PermissionDenied, - .ROFS => return error.ReadOnlyFileSystem, - else => |err| return unexpectedErrno(err), - } - } -} - pub const RebootError = error{ PermissionDenied, } || UnexpectedError; @@ -610,137 +361,6 @@ pub fn reboot(cmd: RebootCommand) RebootError!void { } } -pub const GetRandomError = OpenError; - -/// Obtain a series of random bytes. These bytes can be used to seed user-space -/// random number generators or for cryptographic purposes. -/// When linking against libc, this calls the -/// appropriate OS-specific library call. Otherwise it uses the zig standard -/// library implementation. -pub fn getrandom(buffer: []u8) GetRandomError!void { - if (native_os == .windows) { - return windows.RtlGenRandom(buffer); - } - if (builtin.link_libc and @TypeOf(system.arc4random_buf) != void) { - system.arc4random_buf(buffer.ptr, buffer.len); - return; - } - if (native_os == .wasi) switch (wasi.random_get(buffer.ptr, buffer.len)) { - .SUCCESS => return, - else => |err| return unexpectedErrno(err), - }; - if (@TypeOf(system.getrandom) != void) { - var buf = buffer; - const use_c = native_os != .linux or - std.c.versionCheck(if (builtin.abi.isAndroid()) .{ .major = 28, .minor = 0, .patch = 0 } else .{ .major = 2, .minor = 25, .patch = 0 }); - - while (buf.len != 0) { - const num_read: usize, const err = if (use_c) res: { - const rc = std.c.getrandom(buf.ptr, buf.len, 0); - break :res .{ @bitCast(rc), errno(rc) }; - } else res: { - const rc = linux.getrandom(buf.ptr, buf.len, 0); - break :res .{ rc, linux.errno(rc) }; - }; - - switch (err) { - .SUCCESS => buf = buf[num_read..], - .INVAL => unreachable, - .FAULT => unreachable, - .INTR => continue, - else => return unexpectedErrno(err), - } - } - return; - } - if (native_os == .emscripten) { - const err = errno(std.c.getentropy(buffer.ptr, buffer.len)); - switch (err) { - .SUCCESS => return, - else => return unexpectedErrno(err), - } - } - return getRandomBytesDevURandom(buffer); -} - -fn getRandomBytesDevURandom(buf: []u8) GetRandomError!void { - const fd = try openZ("/dev/urandom", .{ .ACCMODE = .RDONLY, .CLOEXEC = true }, 0); - defer close(fd); - - const st = fstat(fd) catch |err| switch (err) { - error.Streaming => return error.NoDevice, - else => |e| return e, - }; - if (!S.ISCHR(st.mode)) { - return error.NoDevice; - } - - var i: usize = 0; - while (i < buf.len) { - i += read(fd, buf[i..]) catch return error.Unexpected; - } -} - -/// Causes abnormal process termination. -/// If linking against libc, this calls the abort() libc function. Otherwise -/// it raises SIGABRT followed by SIGKILL and finally lo -/// Invokes the current signal handler for SIGABRT, if any. -pub fn abort() noreturn { - @branchHint(.cold); - // MSVCRT abort() sometimes opens a popup window which is undesirable, so - // even when linking libc on Windows we use our own abort implementation. - // See https://github.com/ziglang/zig/issues/2071 for more details. - if (native_os == .windows) { - if (builtin.mode == .Debug and windows.peb().BeingDebugged != 0) { - @breakpoint(); - } - windows.ntdll.RtlExitUserProcess(3); - } - if (!builtin.link_libc and native_os == .linux) { - // The Linux man page says that the libc abort() function - // "first unblocks the SIGABRT signal", but this is a footgun - // for user-defined signal handlers that want to restore some state in - // some program sections and crash in others. - // So, the user-installed SIGABRT handler is run, if present. - raise(.ABRT) catch {}; - - // Disable all signal handlers. - const filledset = linux.sigfillset(); - sigprocmask(SIG.BLOCK, &filledset, null); - - // Only one thread may proceed to the rest of abort(). - if (!builtin.single_threaded) { - const global = struct { - var abort_entered: bool = false; - }; - while (@cmpxchgWeak(bool, &global.abort_entered, false, true, .seq_cst, .seq_cst)) |_| {} - } - - // Install default handler so that the tkill below will terminate. - const sigact = Sigaction{ - .handler = .{ .handler = SIG.DFL }, - .mask = sigemptyset(), - .flags = 0, - }; - sigaction(.ABRT, &sigact, null); - - _ = linux.tkill(linux.gettid(), .ABRT); - - var sigabrtmask = sigemptyset(); - sigaddset(&sigabrtmask, .ABRT); - sigprocmask(SIG.UNBLOCK, &sigabrtmask, null); - - // Beyond this point should be unreachable. - @as(*allowzero volatile u8, @ptrFromInt(0)).* = 0; - raise(.KILL) catch {}; - exit(127); // Pid 1 might not be signalled in some containers. - } - switch (native_os) { - .uefi, .wasi, .emscripten, .cuda, .amdhsa => @trap(), - else => system.abort(), - } -} - pub const RaiseError = UnexpectedError; pub fn raise(sig: SIG) RaiseError!void { @@ -781,33 +401,6 @@ pub fn kill(pid: pid_t, sig: SIG) KillError!void { } } -/// Exits all threads of the program with the specified status code. -pub fn exit(status: u8) noreturn { - if (builtin.link_libc) { - std.c.exit(status); - } - if (native_os == .windows) { - windows.ntdll.RtlExitUserProcess(status); - } - if (native_os == .wasi) { - wasi.proc_exit(status); - } - if (native_os == .linux and !builtin.single_threaded) { - linux.exit_group(status); - } - if (native_os == .uefi) { - const uefi = std.os.uefi; - // exit() is only available if exitBootServices() has not been called yet. - // This call to exit should not fail, so we catch-ignore errors. - if (uefi.system_table.boot_services) |bs| { - bs.exit(uefi.handle, @enumFromInt(status), null) catch {}; - } - // If we can't exit, reboot the system instead. - uefi.system_table.runtime_services.resetSystem(.cold, @enumFromInt(status), null); - } - system.exit(status); -} - pub const ReadError = std.Io.File.Reader.Error; /// Returns the number of bytes that were read, which can be less than @@ -822,34 +415,8 @@ pub const ReadError = std.Io.File.Reader.Error; /// The corresponding POSIX limit is `maxInt(isize)`. pub fn read(fd: fd_t, buf: []u8) ReadError!usize { if (buf.len == 0) return 0; - if (native_os == .windows) { - return windows.ReadFile(fd, buf, null); - } - if (native_os == .wasi and !builtin.link_libc) { - const iovs = [1]iovec{iovec{ - .base = buf.ptr, - .len = buf.len, - }}; - - var nread: usize = undefined; - switch (wasi.fd_read(fd, &iovs, iovs.len, &nread)) { - .SUCCESS => return nread, - .INTR => unreachable, - .INVAL => unreachable, - .FAULT => unreachable, - .AGAIN => unreachable, - .BADF => return error.NotOpenForReading, // Can be a race condition. - .IO => return error.InputOutput, - .ISDIR => return error.IsDir, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTCONN => return error.SocketUnconnected, - .CONNRESET => return error.ConnectionResetByPeer, - .TIMEDOUT => return error.Timeout, - .NOTCAPABLE => return error.AccessDenied, - else => |err| return unexpectedErrno(err), - } - } + if (native_os == .windows) @compileError("unsupported OS"); + if (native_os == .wasi) @compileError("unsupported OS"); // Prevents EINVAL. const max_count = switch (native_os) { @@ -864,7 +431,6 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize { .INTR => continue, .INVAL => unreachable, .FAULT => unreachable, - .SRCH => return error.ProcessNotFound, .AGAIN => return error.WouldBlock, .CANCELED => return error.Canceled, .BADF => return error.NotOpenForReading, // Can be a race condition. @@ -880,2322 +446,109 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize { } } -/// Number of bytes read is returned. Upon reading end-of-file, zero is returned. -/// -/// For POSIX systems, if `fd` is opened in non blocking mode, the function will -/// return error.WouldBlock when EAGAIN is received. -/// On Windows, if the application has a global event loop enabled, I/O Completion Ports are -/// used to perform the I/O. `error.WouldBlock` is not possible on Windows. -/// -/// This operation is non-atomic on the following systems: -/// * Windows -/// On these systems, the read races with concurrent writes to the same file descriptor. -/// -/// This function assumes that all vectors, including zero-length vectors, have -/// a pointer within the address space of the application. -pub fn readv(fd: fd_t, iov: []const iovec) ReadError!usize { +pub const OpenError = std.Io.File.OpenError || error{WouldBlock}; + +/// Open and possibly create a file. Keeps trying if it gets interrupted. +/// `file_path` is relative to the open directory handle `dir_fd`. +/// On Windows, `file_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). +/// On WASI, `file_path` should be encoded as valid UTF-8. +/// On other platforms, `file_path` is an opaque sequence of bytes with no particular encoding. +/// See also `openatZ`. +pub fn openat(dir_fd: fd_t, file_path: []const u8, flags: O, mode: mode_t) OpenError!fd_t { if (native_os == .windows) { - if (iov.len == 0) return 0; - const first = iov[0]; - return read(fd, first.base[0..first.len]); + @compileError("Windows does not support POSIX; use Windows-specific API or cross-platform std.fs API"); + } else if (native_os == .wasi and !builtin.link_libc) { + @compileError("use std.Io instead"); } - if (native_os == .wasi and !builtin.link_libc) { - var nread: usize = undefined; - switch (wasi.fd_read(fd, iov.ptr, iov.len, &nread)) { - .SUCCESS => return nread, - .INTR => unreachable, - .INVAL => unreachable, - .FAULT => unreachable, - .AGAIN => unreachable, // currently not support in WASI - .BADF => return error.NotOpenForReading, // can be a race condition - .IO => return error.InputOutput, - .ISDIR => return error.IsDir, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTCONN => return error.SocketUnconnected, - .CONNRESET => return error.ConnectionResetByPeer, - .TIMEDOUT => return error.Timeout, - .NOTCAPABLE => return error.AccessDenied, - else => |err| return unexpectedErrno(err), - } + const file_path_c = try toPosixPath(file_path); + return openatZ(dir_fd, &file_path_c, flags, mode); +} + +/// Open and possibly create a file. Keeps trying if it gets interrupted. +/// `file_path` is relative to the open directory handle `dir_fd`. +/// On Windows, `file_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). +/// On WASI, `file_path` should be encoded as valid UTF-8. +/// On other platforms, `file_path` is an opaque sequence of bytes with no particular encoding. +/// See also `openat`. +pub fn openatZ(dir_fd: fd_t, file_path: [*:0]const u8, flags: O, mode: mode_t) OpenError!fd_t { + if (native_os == .windows) { + @compileError("Windows does not support POSIX; use Windows-specific API or cross-platform std.fs API"); + } else if (native_os == .wasi and !builtin.link_libc) { + return openat(dir_fd, mem.sliceTo(file_path, 0), flags, mode); } - while (true) { - const rc = system.readv(fd, iov.ptr, @min(iov.len, IOV_MAX)); - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - .INTR => continue, - .INVAL => unreachable, - .FAULT => unreachable, - .SRCH => return error.ProcessNotFound, - .AGAIN => return error.WouldBlock, - .BADF => return error.NotOpenForReading, // can be a race condition - .IO => return error.InputOutput, - .ISDIR => return error.IsDir, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTCONN => return error.SocketUnconnected, - .CONNRESET => return error.ConnectionResetByPeer, - .TIMEDOUT => return error.Timeout, - else => |err| return unexpectedErrno(err), - } - } -} - -pub const PReadError = std.Io.File.ReadPositionalError; - -/// Number of bytes read is returned. Upon reading end-of-file, zero is returned. -/// -/// Retries when interrupted by a signal. -/// -/// For POSIX systems, if `fd` is opened in non blocking mode, the function will -/// return error.WouldBlock when EAGAIN is received. -/// On Windows, if the application has a global event loop enabled, I/O Completion Ports are -/// used to perform the I/O. `error.WouldBlock` is not possible on Windows. -/// -/// Linux has a limit on how many bytes may be transferred in one `pread` call, which is `0x7ffff000` -/// on both 64-bit and 32-bit systems. This is due to using a signed C int as the return value, as -/// well as stuffing the errno codes into the last `4096` values. This is noted on the `read` man page. -/// The limit on Darwin is `0x7fffffff`, trying to read more than that returns EINVAL. -/// The corresponding POSIX limit is `maxInt(isize)`. -pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize { - if (buf.len == 0) return 0; - if (native_os == .windows) { - return windows.ReadFile(fd, buf, offset); - } - if (native_os == .wasi and !builtin.link_libc) { - const iovs = [1]iovec{iovec{ - .base = buf.ptr, - .len = buf.len, - }}; - - var nread: usize = undefined; - switch (wasi.fd_pread(fd, &iovs, iovs.len, offset, &nread)) { - .SUCCESS => return nread, - .INTR => unreachable, - .INVAL => unreachable, - .FAULT => unreachable, - .AGAIN => unreachable, - .BADF => return error.NotOpenForReading, // Can be a race condition. - .IO => return error.InputOutput, - .ISDIR => return error.IsDir, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTCONN => return error.SocketUnconnected, - .CONNRESET => return error.ConnectionResetByPeer, - .TIMEDOUT => return error.Timeout, - .NXIO => return error.Unseekable, - .SPIPE => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .NOTCAPABLE => return error.AccessDenied, - else => |err| return unexpectedErrno(err), - } - } - - // Prevent EINVAL. - const max_count = switch (native_os) { - .linux => 0x7ffff000, - .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => maxInt(i32), - else => maxInt(isize), - }; - - const pread_sym = if (lfs64_abi) system.pread64 else system.pread; - while (true) { - const rc = pread_sym(fd, buf.ptr, @min(buf.len, max_count), @bitCast(offset)); - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - .INTR => continue, - .INVAL => unreachable, - .FAULT => unreachable, - .SRCH => return error.ProcessNotFound, - .AGAIN => return error.WouldBlock, - .BADF => return error.NotOpenForReading, // Can be a race condition. - .IO => return error.InputOutput, - .ISDIR => return error.IsDir, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTCONN => return error.SocketUnconnected, - .CONNRESET => return error.ConnectionResetByPeer, - .TIMEDOUT => return error.Timeout, - .NXIO => return error.Unseekable, - .SPIPE => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - else => |err| return unexpectedErrno(err), - } - } -} - -pub const TruncateError = error{ - FileTooBig, - InputOutput, - FileBusy, - AccessDenied, - PermissionDenied, - NonResizable, -} || UnexpectedError; - -/// Length must be positive when treated as an i64. -pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void { - const signed_len: i64 = @bitCast(length); - if (signed_len < 0) return error.FileTooBig; // avoid ambiguous EINVAL errors - - if (native_os == .windows) { - var io_status_block: windows.IO_STATUS_BLOCK = undefined; - var eof_info = windows.FILE_END_OF_FILE_INFORMATION{ - .EndOfFile = signed_len, - }; - - const rc = windows.ntdll.NtSetInformationFile( - fd, - &io_status_block, - &eof_info, - @sizeOf(windows.FILE_END_OF_FILE_INFORMATION), - .FileEndOfFileInformation, - ); - - switch (rc) { - .SUCCESS => return, - .INVALID_HANDLE => unreachable, // Handle not open for writing - .ACCESS_DENIED => return error.AccessDenied, - .USER_MAPPED_FILE => return error.AccessDenied, - .INVALID_PARAMETER => return error.FileTooBig, - else => return windows.unexpectedStatus(rc), - } - } - if (native_os == .wasi and !builtin.link_libc) { - switch (wasi.fd_filestat_set_size(fd, length)) { - .SUCCESS => return, - .INTR => unreachable, - .FBIG => return error.FileTooBig, - .IO => return error.InputOutput, - .PERM => return error.PermissionDenied, - .TXTBSY => return error.FileBusy, - .BADF => unreachable, // Handle not open for writing - .INVAL => return error.NonResizable, - .NOTCAPABLE => return error.AccessDenied, - else => |err| return unexpectedErrno(err), - } - } - - const ftruncate_sym = if (lfs64_abi) system.ftruncate64 else system.ftruncate; - while (true) { - switch (errno(ftruncate_sym(fd, signed_len))) { - .SUCCESS => return, - .INTR => continue, - .FBIG => return error.FileTooBig, - .IO => return error.InputOutput, - .PERM => return error.PermissionDenied, - .TXTBSY => return error.FileBusy, - .BADF => unreachable, // Handle not open for writing - .INVAL => return error.NonResizable, // This is returned for /dev/null for example. - else => |err| return unexpectedErrno(err), - } - } -} - -/// Number of bytes read is returned. Upon reading end-of-file, zero is returned. -/// -/// Retries when interrupted by a signal. -/// -/// For POSIX systems, if `fd` is opened in non blocking mode, the function will -/// return error.WouldBlock when EAGAIN is received. -/// On Windows, if the application has a global event loop enabled, I/O Completion Ports are -/// used to perform the I/O. `error.WouldBlock` is not possible on Windows. -/// -/// This operation is non-atomic on the following systems: -/// * Darwin -/// * Windows -/// On these systems, the read races with concurrent writes to the same file descriptor. -pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize { - const have_pread_but_not_preadv = switch (native_os) { - .windows, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos, .haiku => true, - else => false, - }; - if (have_pread_but_not_preadv) { - // We could loop here; but proper usage of `preadv` must handle partial reads anyway. - // So we simply read into the first vector only. - if (iov.len == 0) return 0; - const first = iov[0]; - return pread(fd, first.base[0..first.len], offset); - } - if (native_os == .wasi and !builtin.link_libc) { - var nread: usize = undefined; - switch (wasi.fd_pread(fd, iov.ptr, iov.len, offset, &nread)) { - .SUCCESS => return nread, - .INTR => unreachable, - .INVAL => unreachable, - .FAULT => unreachable, - .AGAIN => unreachable, - .BADF => return error.NotOpenForReading, // can be a race condition - .IO => return error.InputOutput, - .ISDIR => return error.IsDir, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTCONN => return error.SocketUnconnected, - .CONNRESET => return error.ConnectionResetByPeer, - .TIMEDOUT => return error.Timeout, - .NXIO => return error.Unseekable, - .SPIPE => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .NOTCAPABLE => return error.AccessDenied, - else => |err| return unexpectedErrno(err), - } - } - - const preadv_sym = if (lfs64_abi) system.preadv64 else system.preadv; - while (true) { - const rc = preadv_sym(fd, iov.ptr, @min(iov.len, IOV_MAX), @bitCast(offset)); - switch (errno(rc)) { - .SUCCESS => return @bitCast(rc), - .INTR => continue, - .INVAL => unreachable, - .FAULT => unreachable, - .SRCH => return error.ProcessNotFound, - .AGAIN => return error.WouldBlock, - .BADF => return error.NotOpenForReading, // can be a race condition - .IO => return error.InputOutput, - .ISDIR => return error.IsDir, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTCONN => return error.SocketUnconnected, - .CONNRESET => return error.ConnectionResetByPeer, - .TIMEDOUT => return error.Timeout, - .NXIO => return error.Unseekable, - .SPIPE => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - else => |err| return unexpectedErrno(err), - } - } -} - -pub const WriteError = error{ - DiskQuota, - FileTooBig, - InputOutput, - NoSpaceLeft, - DeviceBusy, - InvalidArgument, - - /// File descriptor does not hold the required rights to write to it. - AccessDenied, - PermissionDenied, - BrokenPipe, - SystemResources, - Canceled, - NotOpenForWriting, - - /// The process cannot access the file because another process has locked - /// a portion of the file. Windows-only. - LockViolation, - - /// This error occurs when no global event loop is configured, - /// and reading from the file descriptor would block. - WouldBlock, - - /// Connection reset by peer. - ConnectionResetByPeer, - - /// This error occurs in Linux if the process being written to - /// no longer exists. - ProcessNotFound, - /// This error occurs when a device gets disconnected before or mid-flush - /// while it's being written to - errno(6): No such device or address. - NoDevice, - - /// The socket type requires that message be sent atomically, and the size of the message - /// to be sent made this impossible. The message is not transmitted. - MessageOversize, -} || UnexpectedError; - -/// Write to a file descriptor. -/// Retries when interrupted by a signal. -/// Returns the number of bytes written. If nonzero bytes were supplied, this will be nonzero. -/// -/// Note that a successful write() may transfer fewer than count bytes. Such partial writes can -/// occur for various reasons; for example, because there was insufficient space on the disk -/// device to write all of the requested bytes, or because a blocked write() to a socket, pipe, or -/// similar was interrupted by a signal handler after it had transferred some, but before it had -/// transferred all of the requested bytes. In the event of a partial write, the caller can make -/// another write() call to transfer the remaining bytes. The subsequent call will either -/// transfer further bytes or may result in an error (e.g., if the disk is now full). -/// -/// For POSIX systems, if `fd` is opened in non blocking mode, the function will -/// return error.WouldBlock when EAGAIN is received. -/// On Windows, if the application has a global event loop enabled, I/O Completion Ports are -/// used to perform the I/O. `error.WouldBlock` is not possible on Windows. -/// -/// Linux has a limit on how many bytes may be transferred in one `write` call, which is `0x7ffff000` -/// on both 64-bit and 32-bit systems. This is due to using a signed C int as the return value, as -/// well as stuffing the errno codes into the last `4096` values. This is noted on the `write` man page. -/// The limit on Darwin is `0x7fffffff`, trying to read more than that returns EINVAL. -/// The corresponding POSIX limit is `maxInt(isize)`. -pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize { - if (bytes.len == 0) return 0; - if (native_os == .windows) { - return windows.WriteFile(fd, bytes, null); - } - - if (native_os == .wasi and !builtin.link_libc) { - const ciovs = [_]iovec_const{iovec_const{ - .base = bytes.ptr, - .len = bytes.len, - }}; - var nwritten: usize = undefined; - switch (wasi.fd_write(fd, &ciovs, ciovs.len, &nwritten)) { - .SUCCESS => return nwritten, - .INTR => unreachable, - .INVAL => unreachable, - .FAULT => unreachable, - .AGAIN => unreachable, - .BADF => return error.NotOpenForWriting, // can be a race condition. - .DESTADDRREQ => unreachable, // `connect` was never called. - .DQUOT => return error.DiskQuota, - .FBIG => return error.FileTooBig, - .IO => return error.InputOutput, - .NOSPC => return error.NoSpaceLeft, - .PERM => return error.PermissionDenied, - .PIPE => return error.BrokenPipe, - .NOTCAPABLE => return error.AccessDenied, - else => |err| return unexpectedErrno(err), - } - } - - const max_count = switch (native_os) { - .linux => 0x7ffff000, - .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => maxInt(i32), - else => maxInt(isize), - }; - while (true) { - const rc = system.write(fd, bytes.ptr, @min(bytes.len, max_count)); - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - .INTR => continue, - .INVAL => return error.InvalidArgument, - .FAULT => unreachable, - .SRCH => return error.ProcessNotFound, - .AGAIN => return error.WouldBlock, - .BADF => return error.NotOpenForWriting, // can be a race condition. - .DESTADDRREQ => unreachable, // `connect` was never called. - .DQUOT => return error.DiskQuota, - .FBIG => return error.FileTooBig, - .IO => return error.InputOutput, - .NOSPC => return error.NoSpaceLeft, - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - .PIPE => return error.BrokenPipe, - .CONNRESET => return error.ConnectionResetByPeer, - .BUSY => return error.DeviceBusy, - .NXIO => return error.NoDevice, - .MSGSIZE => return error.MessageOversize, - else => |err| return unexpectedErrno(err), - } - } -} - -/// Write multiple buffers to a file descriptor. -/// Retries when interrupted by a signal. -/// Returns the number of bytes written. If nonzero bytes were supplied, this will be nonzero. -/// -/// Note that a successful write() may transfer fewer bytes than supplied. Such partial writes can -/// occur for various reasons; for example, because there was insufficient space on the disk -/// device to write all of the requested bytes, or because a blocked write() to a socket, pipe, or -/// similar was interrupted by a signal handler after it had transferred some, but before it had -/// transferred all of the requested bytes. In the event of a partial write, the caller can make -/// another write() call to transfer the remaining bytes. The subsequent call will either -/// transfer further bytes or may result in an error (e.g., if the disk is now full). -/// -/// For POSIX systems, if `fd` is opened in non blocking mode, the function will -/// return error.WouldBlock when EAGAIN is received. -/// On Windows, if the application has a global event loop enabled, I/O Completion Ports are -/// used to perform the I/O. `error.WouldBlock` is not possible on Windows. -/// -/// If `iov.len` is larger than `IOV_MAX`, a partial write will occur. -/// -/// This function assumes that all vectors, including zero-length vectors, have -/// a pointer within the address space of the application. -pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!usize { - if (native_os == .windows) { - // TODO improve this to use WriteFileScatter - if (iov.len == 0) return 0; - const first = iov[0]; - return write(fd, first.base[0..first.len]); - } - if (native_os == .wasi and !builtin.link_libc) { - var nwritten: usize = undefined; - switch (wasi.fd_write(fd, iov.ptr, iov.len, &nwritten)) { - .SUCCESS => return nwritten, - .INTR => unreachable, - .INVAL => unreachable, - .FAULT => unreachable, - .AGAIN => unreachable, - .BADF => return error.NotOpenForWriting, // can be a race condition. - .DESTADDRREQ => unreachable, // `connect` was never called. - .DQUOT => return error.DiskQuota, - .FBIG => return error.FileTooBig, - .IO => return error.InputOutput, - .NOSPC => return error.NoSpaceLeft, - .PERM => return error.PermissionDenied, - .PIPE => return error.BrokenPipe, - .NOTCAPABLE => return error.AccessDenied, - else => |err| return unexpectedErrno(err), - } - } - - while (true) { - const rc = system.writev(fd, iov.ptr, @min(iov.len, IOV_MAX)); - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - .INTR => continue, - .INVAL => return error.InvalidArgument, - .FAULT => unreachable, - .SRCH => return error.ProcessNotFound, - .AGAIN => return error.WouldBlock, - .BADF => return error.NotOpenForWriting, // Can be a race condition. - .DESTADDRREQ => unreachable, // `connect` was never called. - .DQUOT => return error.DiskQuota, - .FBIG => return error.FileTooBig, - .IO => return error.InputOutput, - .NOSPC => return error.NoSpaceLeft, - .PERM => return error.PermissionDenied, - .PIPE => return error.BrokenPipe, - .CONNRESET => return error.ConnectionResetByPeer, - .BUSY => return error.DeviceBusy, - else => |err| return unexpectedErrno(err), - } - } -} - -pub const PWriteError = WriteError || error{Unseekable}; - -/// Write to a file descriptor, with a position offset. -/// Retries when interrupted by a signal. -/// Returns the number of bytes written. If nonzero bytes were supplied, this will be nonzero. -/// -/// Note that a successful write() may transfer fewer bytes than supplied. Such partial writes can -/// occur for various reasons; for example, because there was insufficient space on the disk -/// device to write all of the requested bytes, or because a blocked write() to a socket, pipe, or -/// similar was interrupted by a signal handler after it had transferred some, but before it had -/// transferred all of the requested bytes. In the event of a partial write, the caller can make -/// another write() call to transfer the remaining bytes. The subsequent call will either -/// transfer further bytes or may result in an error (e.g., if the disk is now full). -/// -/// For POSIX systems, if `fd` is opened in non blocking mode, the function will -/// return error.WouldBlock when EAGAIN is received. -/// On Windows, if the application has a global event loop enabled, I/O Completion Ports are -/// used to perform the I/O. `error.WouldBlock` is not possible on Windows. -/// -/// Linux has a limit on how many bytes may be transferred in one `pwrite` call, which is `0x7ffff000` -/// on both 64-bit and 32-bit systems. This is due to using a signed C int as the return value, as -/// well as stuffing the errno codes into the last `4096` values. This is noted on the `write` man page. -/// The limit on Darwin is `0x7fffffff`, trying to write more than that returns EINVAL. -/// The corresponding POSIX limit is `maxInt(isize)`. -pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize { - if (bytes.len == 0) return 0; - if (native_os == .windows) { - return windows.WriteFile(fd, bytes, offset); - } - if (native_os == .wasi and !builtin.link_libc) { - const ciovs = [1]iovec_const{iovec_const{ - .base = bytes.ptr, - .len = bytes.len, - }}; - - var nwritten: usize = undefined; - switch (wasi.fd_pwrite(fd, &ciovs, ciovs.len, offset, &nwritten)) { - .SUCCESS => return nwritten, - .INTR => unreachable, - .INVAL => unreachable, - .FAULT => unreachable, - .AGAIN => unreachable, - .BADF => return error.NotOpenForWriting, // can be a race condition. - .DESTADDRREQ => unreachable, // `connect` was never called. - .DQUOT => return error.DiskQuota, - .FBIG => return error.FileTooBig, - .IO => return error.InputOutput, - .NOSPC => return error.NoSpaceLeft, - .PERM => return error.PermissionDenied, - .PIPE => return error.BrokenPipe, - .NXIO => return error.Unseekable, - .SPIPE => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .NOTCAPABLE => return error.AccessDenied, - else => |err| return unexpectedErrno(err), - } - } - - // Prevent EINVAL. - const max_count = switch (native_os) { - .linux => 0x7ffff000, - .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => maxInt(i32), - else => maxInt(isize), - }; - - const pwrite_sym = if (lfs64_abi) system.pwrite64 else system.pwrite; - while (true) { - const rc = pwrite_sym(fd, bytes.ptr, @min(bytes.len, max_count), @bitCast(offset)); - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - .INTR => continue, - .INVAL => return error.InvalidArgument, - .FAULT => unreachable, - .SRCH => return error.ProcessNotFound, - .AGAIN => return error.WouldBlock, - .BADF => return error.NotOpenForWriting, // Can be a race condition. - .DESTADDRREQ => unreachable, // `connect` was never called. - .DQUOT => return error.DiskQuota, - .FBIG => return error.FileTooBig, - .IO => return error.InputOutput, - .NOSPC => return error.NoSpaceLeft, - .PERM => return error.PermissionDenied, - .PIPE => return error.BrokenPipe, - .NXIO => return error.Unseekable, - .SPIPE => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .BUSY => return error.DeviceBusy, - else => |err| return unexpectedErrno(err), - } - } -} - -/// Write multiple buffers to a file descriptor, with a position offset. -/// Retries when interrupted by a signal. -/// Returns the number of bytes written. If nonzero bytes were supplied, this will be nonzero. -/// -/// Note that a successful write() may transfer fewer than count bytes. Such partial writes can -/// occur for various reasons; for example, because there was insufficient space on the disk -/// device to write all of the requested bytes, or because a blocked write() to a socket, pipe, or -/// similar was interrupted by a signal handler after it had transferred some, but before it had -/// transferred all of the requested bytes. In the event of a partial write, the caller can make -/// another write() call to transfer the remaining bytes. The subsequent call will either -/// transfer further bytes or may result in an error (e.g., if the disk is now full). -/// -/// If `fd` is opened in non blocking mode, the function will -/// return error.WouldBlock when EAGAIN is received. -/// -/// The following systems do not have this syscall, and will return partial writes if more than one -/// vector is provided: -/// * Darwin -/// * Windows -/// -/// If `iov.len` is larger than `IOV_MAX`, a partial write will occur. -pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usize { - const have_pwrite_but_not_pwritev = switch (native_os) { - .windows, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos, .haiku => true, - else => false, - }; - - if (have_pwrite_but_not_pwritev) { - // We could loop here; but proper usage of `pwritev` must handle partial writes anyway. - // So we simply write the first vector only. - if (iov.len == 0) return 0; - const first = iov[0]; - return pwrite(fd, first.base[0..first.len], offset); - } - if (native_os == .wasi and !builtin.link_libc) { - var nwritten: usize = undefined; - switch (wasi.fd_pwrite(fd, iov.ptr, iov.len, offset, &nwritten)) { - .SUCCESS => return nwritten, - .INTR => unreachable, - .INVAL => unreachable, - .FAULT => unreachable, - .AGAIN => unreachable, - .BADF => return error.NotOpenForWriting, // Can be a race condition. - .DESTADDRREQ => unreachable, // `connect` was never called. - .DQUOT => return error.DiskQuota, - .FBIG => return error.FileTooBig, - .IO => return error.InputOutput, - .NOSPC => return error.NoSpaceLeft, - .PERM => return error.PermissionDenied, - .PIPE => return error.BrokenPipe, - .NXIO => return error.Unseekable, - .SPIPE => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .NOTCAPABLE => return error.AccessDenied, - else => |err| return unexpectedErrno(err), - } - } - - const pwritev_sym = if (lfs64_abi) system.pwritev64 else system.pwritev; - while (true) { - const rc = pwritev_sym(fd, iov.ptr, @min(iov.len, IOV_MAX), @bitCast(offset)); - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - .INTR => continue, - .INVAL => return error.InvalidArgument, - .FAULT => unreachable, - .SRCH => return error.ProcessNotFound, - .AGAIN => return error.WouldBlock, - .BADF => return error.NotOpenForWriting, // Can be a race condition. - .DESTADDRREQ => unreachable, // `connect` was never called. - .DQUOT => return error.DiskQuota, - .FBIG => return error.FileTooBig, - .IO => return error.InputOutput, - .NOSPC => return error.NoSpaceLeft, - .PERM => return error.PermissionDenied, - .PIPE => return error.BrokenPipe, - .NXIO => return error.Unseekable, - .SPIPE => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .BUSY => return error.DeviceBusy, - else => |err| return unexpectedErrno(err), - } - } -} - -pub const OpenError = std.Io.File.OpenError || error{WouldBlock}; - -/// Open and possibly create a file. Keeps trying if it gets interrupted. -/// On Windows, `file_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `file_path` should be encoded as valid UTF-8. -/// On other platforms, `file_path` is an opaque sequence of bytes with no particular encoding. -/// See also `openZ`. -pub fn open(file_path: []const u8, flags: O, perm: mode_t) OpenError!fd_t { - if (native_os == .windows) { - @compileError("Windows does not support POSIX; use Windows-specific API or cross-platform std.fs API"); - } else if (native_os == .wasi and !builtin.link_libc) { - return openat(AT.FDCWD, file_path, flags, perm); - } - const file_path_c = try toPosixPath(file_path); - return openZ(&file_path_c, flags, perm); -} - -/// Open and possibly create a file. Keeps trying if it gets interrupted. -/// On Windows, `file_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `file_path` should be encoded as valid UTF-8. -/// On other platforms, `file_path` is an opaque sequence of bytes with no particular encoding. -/// See also `open`. -pub fn openZ(file_path: [*:0]const u8, flags: O, perm: mode_t) OpenError!fd_t { - if (native_os == .windows) { - @compileError("Windows does not support POSIX; use Windows-specific API or cross-platform std.fs API"); - } else if (native_os == .wasi and !builtin.link_libc) { - return open(mem.sliceTo(file_path, 0), flags, perm); - } - - const open_sym = if (lfs64_abi) system.open64 else system.open; - while (true) { - const rc = open_sym(file_path, flags, perm); - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - .INTR => continue, - - .FAULT => unreachable, - .INVAL => return error.BadPathName, - .ACCES => return error.AccessDenied, - .FBIG => return error.FileTooBig, - .OVERFLOW => return error.FileTooBig, - .ISDIR => return error.IsDir, - .LOOP => return error.SymLinkLoop, - .MFILE => return error.ProcessFdQuotaExceeded, - .NAMETOOLONG => return error.NameTooLong, - .NFILE => return error.SystemFdQuotaExceeded, - .NODEV => return error.NoDevice, - .NOENT => return error.FileNotFound, - .SRCH => return error.ProcessNotFound, - .NOMEM => return error.SystemResources, - .NOSPC => return error.NoSpaceLeft, - .NOTDIR => return error.NotDir, - .PERM => return error.PermissionDenied, - .EXIST => return error.PathAlreadyExists, - .BUSY => return error.DeviceBusy, - .ILSEQ => return error.BadPathName, - else => |err| return unexpectedErrno(err), - } - } -} - -/// Open and possibly create a file. Keeps trying if it gets interrupted. -/// `file_path` is relative to the open directory handle `dir_fd`. -/// On Windows, `file_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `file_path` should be encoded as valid UTF-8. -/// On other platforms, `file_path` is an opaque sequence of bytes with no particular encoding. -/// See also `openatZ`. -pub fn openat(dir_fd: fd_t, file_path: []const u8, flags: O, mode: mode_t) OpenError!fd_t { - if (native_os == .windows) { - @compileError("Windows does not support POSIX; use Windows-specific API or cross-platform std.fs API"); - } else if (native_os == .wasi and !builtin.link_libc) { - @compileError("use std.Io instead"); - } - const file_path_c = try toPosixPath(file_path); - return openatZ(dir_fd, &file_path_c, flags, mode); -} - -/// Open and possibly create a file. Keeps trying if it gets interrupted. -/// `file_path` is relative to the open directory handle `dir_fd`. -/// On Windows, `file_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `file_path` should be encoded as valid UTF-8. -/// On other platforms, `file_path` is an opaque sequence of bytes with no particular encoding. -/// See also `openat`. -pub fn openatZ(dir_fd: fd_t, file_path: [*:0]const u8, flags: O, mode: mode_t) OpenError!fd_t { - if (native_os == .windows) { - @compileError("Windows does not support POSIX; use Windows-specific API or cross-platform std.fs API"); - } else if (native_os == .wasi and !builtin.link_libc) { - return openat(dir_fd, mem.sliceTo(file_path, 0), flags, mode); - } - - const openat_sym = if (lfs64_abi) system.openat64 else system.openat; - while (true) { - const rc = openat_sym(dir_fd, file_path, flags, mode); - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - .INTR => continue, - - .FAULT => unreachable, - .INVAL => return error.BadPathName, - .BADF => unreachable, - .ACCES => return error.AccessDenied, - .FBIG => return error.FileTooBig, - .OVERFLOW => return error.FileTooBig, - .ISDIR => return error.IsDir, - .LOOP => return error.SymLinkLoop, - .MFILE => return error.ProcessFdQuotaExceeded, - .NAMETOOLONG => return error.NameTooLong, - .NFILE => return error.SystemFdQuotaExceeded, - .NODEV => return error.NoDevice, - .NOENT => return error.FileNotFound, - .SRCH => return error.ProcessNotFound, - .NOMEM => return error.SystemResources, - .NOSPC => return error.NoSpaceLeft, - .NOTDIR => return error.NotDir, - .PERM => return error.PermissionDenied, - .EXIST => return error.PathAlreadyExists, - .BUSY => return error.DeviceBusy, - .OPNOTSUPP => return error.FileLocksNotSupported, - .AGAIN => return error.WouldBlock, - .TXTBSY => return error.FileBusy, - .NXIO => return error.NoDevice, - .ILSEQ => return error.BadPathName, - else => |err| return unexpectedErrno(err), - } - } -} - -pub fn dup(old_fd: fd_t) !fd_t { - const rc = system.dup(old_fd); - return switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - .MFILE => error.ProcessFdQuotaExceeded, - .BADF => unreachable, // invalid file descriptor - else => |err| return unexpectedErrno(err), - }; -} - -pub fn dup2(old_fd: fd_t, new_fd: fd_t) !void { - while (true) { - switch (errno(system.dup2(old_fd, new_fd))) { - .SUCCESS => return, - .BUSY, .INTR => continue, - .MFILE => return error.ProcessFdQuotaExceeded, - .INVAL => unreachable, // invalid parameters passed to dup2 - .BADF => unreachable, // invalid file descriptor - else => |err| return unexpectedErrno(err), - } - } -} - -pub fn getpid() pid_t { - return system.getpid(); -} - -pub fn getppid() pid_t { - return system.getppid(); -} - -pub const ExecveError = error{ - SystemResources, - AccessDenied, - PermissionDenied, - InvalidExe, - FileSystem, - IsDir, - FileNotFound, - NotDir, - FileBusy, - ProcessFdQuotaExceeded, - SystemFdQuotaExceeded, - NameTooLong, -} || UnexpectedError; - -/// This function ignores PATH environment variable. See `execvpeZ` for that. -pub fn execveZ( - path: [*:0]const u8, - child_argv: [*:null]const ?[*:0]const u8, - envp: [*:null]const ?[*:0]const u8, -) ExecveError { - switch (errno(system.execve(path, child_argv, envp))) { - .SUCCESS => unreachable, - .FAULT => unreachable, - .@"2BIG" => return error.SystemResources, - .MFILE => return error.ProcessFdQuotaExceeded, - .NAMETOOLONG => return error.NameTooLong, - .NFILE => return error.SystemFdQuotaExceeded, - .NOMEM => return error.SystemResources, - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - .INVAL => return error.InvalidExe, - .NOEXEC => return error.InvalidExe, - .IO => return error.FileSystem, - .LOOP => return error.FileSystem, - .ISDIR => return error.IsDir, - .NOENT => return error.FileNotFound, - .NOTDIR => return error.NotDir, - .TXTBSY => return error.FileBusy, - else => |err| switch (native_os) { - .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => switch (err) { - .BADEXEC => return error.InvalidExe, - .BADARCH => return error.InvalidExe, - else => return unexpectedErrno(err), - }, - .linux => switch (err) { - .LIBBAD => return error.InvalidExe, - else => return unexpectedErrno(err), - }, - else => return unexpectedErrno(err), - }, - } -} - -pub const Arg0Expand = enum { - expand, - no_expand, -}; - -/// Like `execvpeZ` except if `arg0_expand` is `.expand`, then `argv` is mutable, -/// and `argv[0]` is expanded to be the same absolute path that is passed to the execve syscall. -/// If this function returns with an error, `argv[0]` will be restored to the value it was when it was passed in. -pub fn execvpeZ_expandArg0( - comptime arg0_expand: Arg0Expand, - file: [*:0]const u8, - child_argv: switch (arg0_expand) { - .expand => [*:null]?[*:0]const u8, - .no_expand => [*:null]const ?[*:0]const u8, - }, - envp: [*:null]const ?[*:0]const u8, -) ExecveError { - const file_slice = mem.sliceTo(file, 0); - if (mem.indexOfScalar(u8, file_slice, '/') != null) return execveZ(file, child_argv, envp); - - const PATH = getenvZ("PATH") orelse "/usr/local/bin:/bin/:/usr/bin"; - // Use of PATH_MAX here is valid as the path_buf will be passed - // directly to the operating system in execveZ. - var path_buf: [PATH_MAX]u8 = undefined; - var it = mem.tokenizeScalar(u8, PATH, ':'); - var seen_eacces = false; - var err: ExecveError = error.FileNotFound; - - // In case of expanding arg0 we must put it back if we return with an error. - const prev_arg0 = child_argv[0]; - defer switch (arg0_expand) { - .expand => child_argv[0] = prev_arg0, - .no_expand => {}, - }; - - while (it.next()) |search_path| { - const path_len = search_path.len + file_slice.len + 1; - if (path_buf.len < path_len + 1) return error.NameTooLong; - @memcpy(path_buf[0..search_path.len], search_path); - path_buf[search_path.len] = '/'; - @memcpy(path_buf[search_path.len + 1 ..][0..file_slice.len], file_slice); - path_buf[path_len] = 0; - const full_path = path_buf[0..path_len :0].ptr; - switch (arg0_expand) { - .expand => child_argv[0] = full_path, - .no_expand => {}, - } - err = execveZ(full_path, child_argv, envp); - switch (err) { - error.AccessDenied => seen_eacces = true, - error.FileNotFound, error.NotDir => {}, - else => |e| return e, - } - } - if (seen_eacces) return error.AccessDenied; - return err; -} - -/// This function also uses the PATH environment variable to get the full path to the executable. -/// If `file` is an absolute path, this is the same as `execveZ`. -pub fn execvpeZ( - file: [*:0]const u8, - argv_ptr: [*:null]const ?[*:0]const u8, - envp: [*:null]const ?[*:0]const u8, -) ExecveError { - return execvpeZ_expandArg0(.no_expand, file, argv_ptr, envp); -} - -/// Get an environment variable. -/// See also `getenvZ`. -pub fn getenv(key: []const u8) ?[:0]const u8 { - if (native_os == .windows) { - @compileError("std.posix.getenv is unavailable for Windows because environment strings are in WTF-16 format. See std.process.getEnvVarOwned for a cross-platform API or std.process.getenvW for a Windows-specific API."); - } - if (mem.indexOfScalar(u8, key, '=') != null) { - return null; - } - if (builtin.link_libc) { - var ptr = std.c.environ; - while (ptr[0]) |line| : (ptr += 1) { - var line_i: usize = 0; - while (line[line_i] != 0) : (line_i += 1) { - if (line_i == key.len) break; - if (line[line_i] != key[line_i]) break; - } - if ((line_i != key.len) or (line[line_i] != '=')) continue; - - return mem.sliceTo(line + line_i + 1, 0); - } - return null; - } - if (native_os == .wasi) { - @compileError("std.posix.getenv is unavailable for WASI. See std.process.getEnvMap or std.process.getEnvVarOwned for a cross-platform API."); - } - // The simplified start logic doesn't populate environ. - if (std.start.simplified_logic) return null; - // TODO see https://github.com/ziglang/zig/issues/4524 - for (std.os.environ) |ptr| { - var line_i: usize = 0; - while (ptr[line_i] != 0) : (line_i += 1) { - if (line_i == key.len) break; - if (ptr[line_i] != key[line_i]) break; - } - if ((line_i != key.len) or (ptr[line_i] != '=')) continue; - - return mem.sliceTo(ptr + line_i + 1, 0); - } - return null; -} - -/// Get an environment variable with a null-terminated name. -/// See also `getenv`. -pub fn getenvZ(key: [*:0]const u8) ?[:0]const u8 { - if (builtin.link_libc) { - const value = system.getenv(key) orelse return null; - return mem.sliceTo(value, 0); - } - if (native_os == .windows) { - @compileError("std.posix.getenvZ is unavailable for Windows because environment string is in WTF-16 format. See std.process.getEnvVarOwned for cross-platform API or std.process.getenvW for Windows-specific API."); - } - return getenv(mem.sliceTo(key, 0)); -} - -pub const GetCwdError = error{ - NameTooLong, - CurrentWorkingDirectoryUnlinked, -} || UnexpectedError; - -/// The result is a slice of out_buffer, indexed from 0. -pub fn getcwd(out_buffer: []u8) GetCwdError![]u8 { - if (native_os == .windows) { - return windows.GetCurrentDirectory(out_buffer); - } else if (native_os == .wasi and !builtin.link_libc) { - const path = "."; - if (out_buffer.len < path.len) return error.NameTooLong; - const result = out_buffer[0..path.len]; - @memcpy(result, path); - return result; - } - - const err: E = if (builtin.link_libc) err: { - const c_err = if (std.c.getcwd(out_buffer.ptr, out_buffer.len)) |_| 0 else std.c._errno().*; - break :err @enumFromInt(c_err); - } else err: { - break :err errno(system.getcwd(out_buffer.ptr, out_buffer.len)); - }; - switch (err) { - .SUCCESS => return mem.sliceTo(out_buffer, 0), - .FAULT => unreachable, - .INVAL => unreachable, - .NOENT => return error.CurrentWorkingDirectoryUnlinked, - .RANGE => return error.NameTooLong, - else => return unexpectedErrno(err), - } -} - -pub const SymLinkError = error{ - /// In WASI, this error may occur when the file descriptor does - /// not hold the required rights to create a new symbolic link relative to it. - AccessDenied, - PermissionDenied, - DiskQuota, - PathAlreadyExists, - FileSystem, - SymLinkLoop, - FileNotFound, - SystemResources, - NoSpaceLeft, - ReadOnlyFileSystem, - NotDir, - NameTooLong, - /// WASI: file paths must be valid UTF-8. - /// Windows: file paths provided by the user must be valid WTF-8. - /// https://wtf-8.codeberg.page/ - BadPathName, -} || UnexpectedError; - -/// Creates a symbolic link named `sym_link_path` which contains the string `target_path`. -/// A symbolic link (also known as a soft link) may point to an existing file or to a nonexistent -/// one; the latter case is known as a dangling link. -/// On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, both paths should be encoded as valid UTF-8. -/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding. -/// If `sym_link_path` exists, it will not be overwritten. -/// See also `symlinkZ. -pub fn symlink(target_path: []const u8, sym_link_path: []const u8) SymLinkError!void { - if (native_os == .windows) { - @compileError("symlink is not supported on Windows; use std.os.windows.CreateSymbolicLink instead"); - } else if (native_os == .wasi and !builtin.link_libc) { - return symlinkat(target_path, AT.FDCWD, sym_link_path); - } - const target_path_c = try toPosixPath(target_path); - const sym_link_path_c = try toPosixPath(sym_link_path); - return symlinkZ(&target_path_c, &sym_link_path_c); -} - -/// This is the same as `symlink` except the parameters are null-terminated pointers. -/// See also `symlink`. -pub fn symlinkZ(target_path: [*:0]const u8, sym_link_path: [*:0]const u8) SymLinkError!void { - if (native_os == .windows) { - @compileError("symlink is not supported on Windows; use std.os.windows.CreateSymbolicLink instead"); - } else if (native_os == .wasi and !builtin.link_libc) { - return symlinkatZ(target_path, fs.cwd().fd, sym_link_path); - } - switch (errno(system.symlink(target_path, sym_link_path))) { - .SUCCESS => return, - .FAULT => unreachable, - .INVAL => unreachable, - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - .DQUOT => return error.DiskQuota, - .EXIST => return error.PathAlreadyExists, - .IO => return error.FileSystem, - .LOOP => return error.SymLinkLoop, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOTDIR => return error.NotDir, - .NOMEM => return error.SystemResources, - .NOSPC => return error.NoSpaceLeft, - .ROFS => return error.ReadOnlyFileSystem, - .ILSEQ => return error.BadPathName, - else => |err| return unexpectedErrno(err), - } -} - -/// Similar to `symlink`, however, creates a symbolic link named `sym_link_path` which contains the string -/// `target_path` **relative** to `newdirfd` directory handle. -/// A symbolic link (also known as a soft link) may point to an existing file or to a nonexistent -/// one; the latter case is known as a dangling link. -/// On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, both paths should be encoded as valid UTF-8. -/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding. -/// If `sym_link_path` exists, it will not be overwritten. -/// See also `symlinkatWasi`, `symlinkatZ` and `symlinkatW`. -pub fn symlinkat(target_path: []const u8, newdirfd: fd_t, sym_link_path: []const u8) SymLinkError!void { - if (native_os == .windows) { - @compileError("symlinkat is not supported on Windows; use std.os.windows.CreateSymbolicLink instead"); - } else if (native_os == .wasi and !builtin.link_libc) { - return symlinkatWasi(target_path, newdirfd, sym_link_path); - } - const target_path_c = try toPosixPath(target_path); - const sym_link_path_c = try toPosixPath(sym_link_path); - return symlinkatZ(&target_path_c, newdirfd, &sym_link_path_c); -} - -/// WASI-only. The same as `symlinkat` but targeting WASI. -/// See also `symlinkat`. -pub fn symlinkatWasi(target_path: []const u8, newdirfd: fd_t, sym_link_path: []const u8) SymLinkError!void { - switch (wasi.path_symlink(target_path.ptr, target_path.len, newdirfd, sym_link_path.ptr, sym_link_path.len)) { - .SUCCESS => {}, - .FAULT => unreachable, - .INVAL => unreachable, - .BADF => unreachable, - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - .DQUOT => return error.DiskQuota, - .EXIST => return error.PathAlreadyExists, - .IO => return error.FileSystem, - .LOOP => return error.SymLinkLoop, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOTDIR => return error.NotDir, - .NOMEM => return error.SystemResources, - .NOSPC => return error.NoSpaceLeft, - .ROFS => return error.ReadOnlyFileSystem, - .NOTCAPABLE => return error.AccessDenied, - .ILSEQ => return error.BadPathName, - else => |err| return unexpectedErrno(err), - } -} - -/// The same as `symlinkat` except the parameters are null-terminated pointers. -/// See also `symlinkat`. -pub fn symlinkatZ(target_path: [*:0]const u8, newdirfd: fd_t, sym_link_path: [*:0]const u8) SymLinkError!void { - if (native_os == .windows) { - @compileError("symlinkat is not supported on Windows; use std.os.windows.CreateSymbolicLink instead"); - } else if (native_os == .wasi and !builtin.link_libc) { - return symlinkat(mem.sliceTo(target_path, 0), newdirfd, mem.sliceTo(sym_link_path, 0)); - } - switch (errno(system.symlinkat(target_path, newdirfd, sym_link_path))) { - .SUCCESS => return, - .FAULT => unreachable, - .INVAL => unreachable, - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - .DQUOT => return error.DiskQuota, - .EXIST => return error.PathAlreadyExists, - .IO => return error.FileSystem, - .LOOP => return error.SymLinkLoop, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOTDIR => return error.NotDir, - .NOMEM => return error.SystemResources, - .NOSPC => return error.NoSpaceLeft, - .ROFS => return error.ReadOnlyFileSystem, - .ILSEQ => return error.BadPathName, - else => |err| return unexpectedErrno(err), - } -} - -pub const LinkError = UnexpectedError || error{ - AccessDenied, - PermissionDenied, - DiskQuota, - PathAlreadyExists, - FileSystem, - SymLinkLoop, - LinkQuotaExceeded, - NameTooLong, - FileNotFound, - SystemResources, - NoSpaceLeft, - ReadOnlyFileSystem, - NotSameFileSystem, - BadPathName, -}; - -/// On WASI, both paths should be encoded as valid UTF-8. -/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding. -pub fn linkZ(oldpath: [*:0]const u8, newpath: [*:0]const u8) LinkError!void { - if (native_os == .wasi and !builtin.link_libc) { - return link(mem.sliceTo(oldpath, 0), mem.sliceTo(newpath, 0)); - } - switch (errno(system.link(oldpath, newpath))) { - .SUCCESS => return, - .ACCES => return error.AccessDenied, - .DQUOT => return error.DiskQuota, - .EXIST => return error.PathAlreadyExists, - .FAULT => unreachable, - .IO => return error.FileSystem, - .LOOP => return error.SymLinkLoop, - .MLINK => return error.LinkQuotaExceeded, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOMEM => return error.SystemResources, - .NOSPC => return error.NoSpaceLeft, - .PERM => return error.PermissionDenied, - .ROFS => return error.ReadOnlyFileSystem, - .XDEV => return error.NotSameFileSystem, - .INVAL => unreachable, - .ILSEQ => return error.BadPathName, - else => |err| return unexpectedErrno(err), - } -} - -/// On WASI, both paths should be encoded as valid UTF-8. -/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding. -pub fn link(oldpath: []const u8, newpath: []const u8) LinkError!void { - if (native_os == .wasi and !builtin.link_libc) { - return linkat(AT.FDCWD, oldpath, AT.FDCWD, newpath, 0) catch |err| switch (err) { - error.NotDir => unreachable, // link() does not support directories - else => |e| return e, - }; - } - const old = try toPosixPath(oldpath); - const new = try toPosixPath(newpath); - return try linkZ(&old, &new); -} - -pub const LinkatError = LinkError || error{NotDir}; - -/// On WASI, both paths should be encoded as valid UTF-8. -/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding. -pub fn linkatZ( - olddir: fd_t, - oldpath: [*:0]const u8, - newdir: fd_t, - newpath: [*:0]const u8, - flags: i32, -) LinkatError!void { - if (native_os == .wasi and !builtin.link_libc) { - return linkat(olddir, mem.sliceTo(oldpath, 0), newdir, mem.sliceTo(newpath, 0), flags); - } - switch (errno(system.linkat(olddir, oldpath, newdir, newpath, flags))) { - .SUCCESS => return, - .ACCES => return error.AccessDenied, - .DQUOT => return error.DiskQuota, - .EXIST => return error.PathAlreadyExists, - .FAULT => unreachable, - .IO => return error.FileSystem, - .LOOP => return error.SymLinkLoop, - .MLINK => return error.LinkQuotaExceeded, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOMEM => return error.SystemResources, - .NOSPC => return error.NoSpaceLeft, - .NOTDIR => return error.NotDir, - .PERM => return error.PermissionDenied, - .ROFS => return error.ReadOnlyFileSystem, - .XDEV => return error.NotSameFileSystem, - .INVAL => unreachable, - .ILSEQ => return error.BadPathName, - else => |err| return unexpectedErrno(err), - } -} - -/// On WASI, both paths should be encoded as valid UTF-8. -/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding. -pub fn linkat( - olddir: fd_t, - oldpath: []const u8, - newdir: fd_t, - newpath: []const u8, - flags: i32, -) LinkatError!void { - if (native_os == .wasi and !builtin.link_libc) { - const old: RelativePathWasi = .{ .dir_fd = olddir, .relative_path = oldpath }; - const new: RelativePathWasi = .{ .dir_fd = newdir, .relative_path = newpath }; - const old_flags: wasi.lookupflags_t = .{ - .SYMLINK_FOLLOW = (flags & AT.SYMLINK_FOLLOW) != 0, - }; - switch (wasi.path_link( - old.dir_fd, - old_flags, - old.relative_path.ptr, - old.relative_path.len, - new.dir_fd, - new.relative_path.ptr, - new.relative_path.len, - )) { - .SUCCESS => return, - .ACCES => return error.AccessDenied, - .DQUOT => return error.DiskQuota, - .EXIST => return error.PathAlreadyExists, - .FAULT => unreachable, - .IO => return error.FileSystem, - .LOOP => return error.SymLinkLoop, - .MLINK => return error.LinkQuotaExceeded, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOMEM => return error.SystemResources, - .NOSPC => return error.NoSpaceLeft, - .NOTDIR => return error.NotDir, - .PERM => return error.PermissionDenied, - .ROFS => return error.ReadOnlyFileSystem, - .XDEV => return error.NotSameFileSystem, - .INVAL => unreachable, - .ILSEQ => return error.BadPathName, - else => |err| return unexpectedErrno(err), - } - } - const old = try toPosixPath(oldpath); - const new = try toPosixPath(newpath); - return try linkatZ(olddir, &old, newdir, &new, flags); -} - -pub const UnlinkError = error{ - FileNotFound, - - /// In WASI, this error may occur when the file descriptor does - /// not hold the required rights to unlink a resource by path relative to it. - AccessDenied, - PermissionDenied, - FileBusy, - FileSystem, - IsDir, - SymLinkLoop, - NameTooLong, - NotDir, - SystemResources, - ReadOnlyFileSystem, - - /// WASI: file paths must be valid UTF-8. - /// Windows: file paths provided by the user must be valid WTF-8. - /// https://wtf-8.codeberg.page/ - /// Windows: file paths cannot contain these characters: - /// '/', '*', '?', '"', '<', '>', '|' - BadPathName, - - /// On Windows, `\\server` or `\\server\share` was not found. - NetworkNotFound, -} || UnexpectedError; - -/// Delete a name and possibly the file it refers to. -/// On Windows, `file_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `file_path` should be encoded as valid UTF-8. -/// On other platforms, `file_path` is an opaque sequence of bytes with no particular encoding. -/// See also `unlinkZ`. -pub fn unlink(file_path: []const u8) UnlinkError!void { - if (native_os == .wasi and !builtin.link_libc) { - return unlinkat(AT.FDCWD, file_path, 0) catch |err| switch (err) { - error.DirNotEmpty => unreachable, // only occurs when targeting directories - else => |e| return e, - }; - } else if (native_os == .windows) { - const file_path_w = try windows.sliceToPrefixedFileW(null, file_path); - return unlinkW(file_path_w.span()); - } else { - const file_path_c = try toPosixPath(file_path); - return unlinkZ(&file_path_c); - } -} - -/// Same as `unlink` except the parameter is null terminated. -pub fn unlinkZ(file_path: [*:0]const u8) UnlinkError!void { - if (native_os == .windows) { - const file_path_w = try windows.cStrToPrefixedFileW(null, file_path); - return unlinkW(file_path_w.span()); - } else if (native_os == .wasi and !builtin.link_libc) { - return unlink(mem.sliceTo(file_path, 0)); - } - switch (errno(system.unlink(file_path))) { - .SUCCESS => return, - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - .BUSY => return error.FileBusy, - .FAULT => unreachable, - .INVAL => unreachable, - .IO => return error.FileSystem, - .ISDIR => return error.IsDir, - .LOOP => return error.SymLinkLoop, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOTDIR => return error.NotDir, - .NOMEM => return error.SystemResources, - .ROFS => return error.ReadOnlyFileSystem, - .ILSEQ => return error.BadPathName, - else => |err| return unexpectedErrno(err), - } -} - -/// Windows-only. Same as `unlink` except the parameter is null-terminated, WTF16 LE encoded. -pub fn unlinkW(file_path_w: []const u16) UnlinkError!void { - windows.DeleteFile(file_path_w, .{ .dir = fs.cwd().fd }) catch |err| switch (err) { - error.DirNotEmpty => unreachable, // we're not passing .remove_dir = true - else => |e| return e, - }; -} - -pub const UnlinkatError = UnlinkError || error{ - /// When passing `AT.REMOVEDIR`, this error occurs when the named directory is not empty. - DirNotEmpty, -}; - -/// Delete a file name and possibly the file it refers to, based on an open directory handle. -/// On Windows, `file_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `file_path` should be encoded as valid UTF-8. -/// On other platforms, `file_path` is an opaque sequence of bytes with no particular encoding. -/// Asserts that the path parameter has no null bytes. -pub fn unlinkat(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatError!void { - if (native_os == .windows) { - const file_path_w = try windows.sliceToPrefixedFileW(dirfd, file_path); - return unlinkatW(dirfd, file_path_w.span(), flags); - } else if (native_os == .wasi and !builtin.link_libc) { - return unlinkatWasi(dirfd, file_path, flags); - } else { - const file_path_c = try toPosixPath(file_path); - return unlinkatZ(dirfd, &file_path_c, flags); - } -} - -/// WASI-only. Same as `unlinkat` but targeting WASI. -/// See also `unlinkat`. -pub fn unlinkatWasi(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatError!void { - const remove_dir = (flags & AT.REMOVEDIR) != 0; - const res = if (remove_dir) - wasi.path_remove_directory(dirfd, file_path.ptr, file_path.len) - else - wasi.path_unlink_file(dirfd, file_path.ptr, file_path.len); - switch (res) { - .SUCCESS => return, - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - .BUSY => return error.FileBusy, - .FAULT => unreachable, - .IO => return error.FileSystem, - .ISDIR => return error.IsDir, - .LOOP => return error.SymLinkLoop, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOTDIR => return error.NotDir, - .NOMEM => return error.SystemResources, - .ROFS => return error.ReadOnlyFileSystem, - .NOTEMPTY => return error.DirNotEmpty, - .NOTCAPABLE => return error.AccessDenied, - .ILSEQ => return error.BadPathName, - - .INVAL => unreachable, // invalid flags, or pathname has . as last component - .BADF => unreachable, // always a race condition - - else => |err| return unexpectedErrno(err), - } -} - -/// Same as `unlinkat` but `file_path` is a null-terminated string. -pub fn unlinkatZ(dirfd: fd_t, file_path_c: [*:0]const u8, flags: u32) UnlinkatError!void { - if (native_os == .windows) { - const file_path_w = try windows.cStrToPrefixedFileW(dirfd, file_path_c); - return unlinkatW(dirfd, file_path_w.span(), flags); - } else if (native_os == .wasi and !builtin.link_libc) { - return unlinkat(dirfd, mem.sliceTo(file_path_c, 0), flags); - } - switch (errno(system.unlinkat(dirfd, file_path_c, flags))) { - .SUCCESS => return, - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - .BUSY => return error.FileBusy, - .FAULT => unreachable, - .IO => return error.FileSystem, - .ISDIR => return error.IsDir, - .LOOP => return error.SymLinkLoop, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOTDIR => return error.NotDir, - .NOMEM => return error.SystemResources, - .ROFS => return error.ReadOnlyFileSystem, - .EXIST => return error.DirNotEmpty, - .NOTEMPTY => return error.DirNotEmpty, - .ILSEQ => return error.BadPathName, - - .INVAL => unreachable, // invalid flags, or pathname has . as last component - .BADF => unreachable, // always a race condition - - else => |err| return unexpectedErrno(err), - } -} - -/// Same as `unlinkat` but `sub_path_w` is WTF16LE, NT prefixed. Windows only. -pub fn unlinkatW(dirfd: fd_t, sub_path_w: []const u16, flags: u32) UnlinkatError!void { - const remove_dir = (flags & AT.REMOVEDIR) != 0; - return windows.DeleteFile(sub_path_w, .{ .dir = dirfd, .remove_dir = remove_dir }); -} - -pub const RenameError = error{ - /// In WASI, this error may occur when the file descriptor does - /// not hold the required rights to rename a resource by path relative to it. - /// - /// On Windows, this error may be returned instead of PathAlreadyExists when - /// renaming a directory over an existing directory. - AccessDenied, - PermissionDenied, - FileBusy, - DiskQuota, - IsDir, - SymLinkLoop, - LinkQuotaExceeded, - NameTooLong, - FileNotFound, - NotDir, - SystemResources, - NoSpaceLeft, - PathAlreadyExists, - ReadOnlyFileSystem, - RenameAcrossMountPoints, - /// WASI: file paths must be valid UTF-8. - /// Windows: file paths provided by the user must be valid WTF-8. - /// https://wtf-8.codeberg.page/ - BadPathName, - NoDevice, - SharingViolation, - PipeBusy, - /// On Windows, `\\server` or `\\server\share` was not found. - NetworkNotFound, - /// On Windows, antivirus software is enabled by default. It can be - /// disabled, but Windows Update sometimes ignores the user's preference - /// and re-enables it. When enabled, antivirus software on Windows - /// intercepts file system operations and makes them significantly slower - /// in addition to possibly failing with this error code. - AntivirusInterference, -} || UnexpectedError; - -/// Change the name or location of a file. -/// On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, both paths should be encoded as valid UTF-8. -/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding. -pub fn rename(old_path: []const u8, new_path: []const u8) RenameError!void { - if (native_os == .wasi and !builtin.link_libc) { - return renameat(AT.FDCWD, old_path, AT.FDCWD, new_path); - } else if (native_os == .windows) { - const old_path_w = try windows.sliceToPrefixedFileW(null, old_path); - const new_path_w = try windows.sliceToPrefixedFileW(null, new_path); - return renameW(old_path_w.span().ptr, new_path_w.span().ptr); - } else { - const old_path_c = try toPosixPath(old_path); - const new_path_c = try toPosixPath(new_path); - return renameZ(&old_path_c, &new_path_c); - } -} - -/// Same as `rename` except the parameters are null-terminated. -pub fn renameZ(old_path: [*:0]const u8, new_path: [*:0]const u8) RenameError!void { - if (native_os == .windows) { - const old_path_w = try windows.cStrToPrefixedFileW(null, old_path); - const new_path_w = try windows.cStrToPrefixedFileW(null, new_path); - return renameW(old_path_w.span().ptr, new_path_w.span().ptr); - } else if (native_os == .wasi and !builtin.link_libc) { - return rename(mem.sliceTo(old_path, 0), mem.sliceTo(new_path, 0)); - } - switch (errno(system.rename(old_path, new_path))) { - .SUCCESS => return, - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - .BUSY => return error.FileBusy, - .DQUOT => return error.DiskQuota, - .FAULT => unreachable, - .INVAL => unreachable, - .ISDIR => return error.IsDir, - .LOOP => return error.SymLinkLoop, - .MLINK => return error.LinkQuotaExceeded, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOTDIR => return error.NotDir, - .NOMEM => return error.SystemResources, - .NOSPC => return error.NoSpaceLeft, - .EXIST => return error.PathAlreadyExists, - .NOTEMPTY => return error.PathAlreadyExists, - .ROFS => return error.ReadOnlyFileSystem, - .XDEV => return error.RenameAcrossMountPoints, - .ILSEQ => return error.BadPathName, - else => |err| return unexpectedErrno(err), - } -} - -/// Same as `rename` except the parameters are null-terminated and WTF16LE encoded. -/// Assumes target is Windows. -pub fn renameW(old_path: [*:0]const u16, new_path: [*:0]const u16) RenameError!void { - const cwd_handle = std.fs.cwd().fd; - return windows.RenameFile(cwd_handle, mem.span(old_path), cwd_handle, mem.span(new_path), true); -} - -/// Change the name or location of a file based on an open directory handle. -/// On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, both paths should be encoded as valid UTF-8. -/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding. -pub fn renameat( - old_dir_fd: fd_t, - old_path: []const u8, - new_dir_fd: fd_t, - new_path: []const u8, -) RenameError!void { - if (native_os == .windows) { - const old_path_w = try windows.sliceToPrefixedFileW(old_dir_fd, old_path); - const new_path_w = try windows.sliceToPrefixedFileW(new_dir_fd, new_path); - return renameatW(old_dir_fd, old_path_w.span(), new_dir_fd, new_path_w.span(), windows.TRUE); - } else if (native_os == .wasi and !builtin.link_libc) { - const old: RelativePathWasi = .{ .dir_fd = old_dir_fd, .relative_path = old_path }; - const new: RelativePathWasi = .{ .dir_fd = new_dir_fd, .relative_path = new_path }; - return renameatWasi(old, new); - } else { - const old_path_c = try toPosixPath(old_path); - const new_path_c = try toPosixPath(new_path); - return renameatZ(old_dir_fd, &old_path_c, new_dir_fd, &new_path_c); - } -} - -/// WASI-only. Same as `renameat` expect targeting WASI. -/// See also `renameat`. -fn renameatWasi(old: RelativePathWasi, new: RelativePathWasi) RenameError!void { - switch (wasi.path_rename(old.dir_fd, old.relative_path.ptr, old.relative_path.len, new.dir_fd, new.relative_path.ptr, new.relative_path.len)) { - .SUCCESS => return, - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - .BUSY => return error.FileBusy, - .DQUOT => return error.DiskQuota, - .FAULT => unreachable, - .INVAL => unreachable, - .ISDIR => return error.IsDir, - .LOOP => return error.SymLinkLoop, - .MLINK => return error.LinkQuotaExceeded, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOTDIR => return error.NotDir, - .NOMEM => return error.SystemResources, - .NOSPC => return error.NoSpaceLeft, - .EXIST => return error.PathAlreadyExists, - .NOTEMPTY => return error.PathAlreadyExists, - .ROFS => return error.ReadOnlyFileSystem, - .XDEV => return error.RenameAcrossMountPoints, - .NOTCAPABLE => return error.AccessDenied, - .ILSEQ => return error.BadPathName, - else => |err| return unexpectedErrno(err), - } -} - -/// An fd-relative file path -/// -/// This is currently only used for WASI-specific functionality, but the concept -/// is the same as the dirfd/pathname pairs in the `*at(...)` POSIX functions. -const RelativePathWasi = struct { - /// Handle to directory - dir_fd: fd_t, - /// Path to resource within `dir_fd`. - relative_path: []const u8, -}; - -/// Same as `renameat` except the parameters are null-terminated. -pub fn renameatZ( - old_dir_fd: fd_t, - old_path: [*:0]const u8, - new_dir_fd: fd_t, - new_path: [*:0]const u8, -) RenameError!void { - if (native_os == .windows) { - const old_path_w = try windows.cStrToPrefixedFileW(old_dir_fd, old_path); - const new_path_w = try windows.cStrToPrefixedFileW(new_dir_fd, new_path); - return renameatW(old_dir_fd, old_path_w.span(), new_dir_fd, new_path_w.span(), windows.TRUE); - } else if (native_os == .wasi and !builtin.link_libc) { - return renameat(old_dir_fd, mem.sliceTo(old_path, 0), new_dir_fd, mem.sliceTo(new_path, 0)); - } - - switch (errno(system.renameat(old_dir_fd, old_path, new_dir_fd, new_path))) { - .SUCCESS => return, - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - .BUSY => return error.FileBusy, - .DQUOT => return error.DiskQuota, - .FAULT => unreachable, - .INVAL => unreachable, - .ISDIR => return error.IsDir, - .LOOP => return error.SymLinkLoop, - .MLINK => return error.LinkQuotaExceeded, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOTDIR => return error.NotDir, - .NOMEM => return error.SystemResources, - .NOSPC => return error.NoSpaceLeft, - .EXIST => return error.PathAlreadyExists, - .NOTEMPTY => return error.PathAlreadyExists, - .ROFS => return error.ReadOnlyFileSystem, - .XDEV => return error.RenameAcrossMountPoints, - .ILSEQ => return error.BadPathName, - else => |err| return unexpectedErrno(err), - } -} - -/// Same as `renameat` but Windows-only and the path parameters are -/// [WTF-16](https://wtf-8.codeberg.page/#potentially-ill-formed-utf-16) encoded. -pub fn renameatW( - old_dir_fd: fd_t, - old_path_w: []const u16, - new_dir_fd: fd_t, - new_path_w: []const u16, - ReplaceIfExists: windows.BOOLEAN, -) RenameError!void { - return windows.RenameFile(old_dir_fd, old_path_w, new_dir_fd, new_path_w, ReplaceIfExists != 0); -} - -/// On Windows, `sub_dir_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `sub_dir_path` should be encoded as valid UTF-8. -/// On other platforms, `sub_dir_path` is an opaque sequence of bytes with no particular encoding. -pub fn mkdirat(dir_fd: fd_t, sub_dir_path: []const u8, mode: mode_t) MakeDirError!void { - if (native_os == .windows) { - @compileError("use std.Io instead"); - } else if (native_os == .wasi and !builtin.link_libc) { - @compileError("use std.Io instead"); - } else { - const sub_dir_path_c = try toPosixPath(sub_dir_path); - return mkdiratZ(dir_fd, &sub_dir_path_c, mode); - } -} - -/// Same as `mkdirat` except the parameters are null-terminated. -pub fn mkdiratZ(dir_fd: fd_t, sub_dir_path: [*:0]const u8, mode: mode_t) MakeDirError!void { - if (native_os == .windows) { - @compileError("use std.Io instead"); - } else if (native_os == .wasi and !builtin.link_libc) { - @compileError("use std.Io instead"); - } - switch (errno(system.mkdirat(dir_fd, sub_dir_path, mode))) { - .SUCCESS => return, - .ACCES => return error.AccessDenied, - .BADF => unreachable, - .PERM => return error.PermissionDenied, - .DQUOT => return error.DiskQuota, - .EXIST => return error.PathAlreadyExists, - .FAULT => unreachable, - .LOOP => return error.SymLinkLoop, - .MLINK => return error.LinkQuotaExceeded, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOMEM => return error.SystemResources, - .NOSPC => return error.NoSpaceLeft, - .NOTDIR => return error.NotDir, - .ROFS => return error.ReadOnlyFileSystem, - // dragonfly: when dir_fd is unlinked from filesystem - .NOTCONN => return error.FileNotFound, - .ILSEQ => return error.BadPathName, - else => |err| return unexpectedErrno(err), - } -} - -pub const MakeDirError = std.Io.Dir.MakeError; - -/// Create a directory. -/// `mode` is ignored on Windows and WASI. -/// On Windows, `dir_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `dir_path` should be encoded as valid UTF-8. -/// On other platforms, `dir_path` is an opaque sequence of bytes with no particular encoding. -pub fn mkdir(dir_path: []const u8, mode: mode_t) MakeDirError!void { - if (native_os == .wasi and !builtin.link_libc) { - return mkdirat(AT.FDCWD, dir_path, mode); - } else if (native_os == .windows) { - const dir_path_w = try windows.sliceToPrefixedFileW(null, dir_path); - return mkdirW(dir_path_w.span(), mode); - } else { - const dir_path_c = try toPosixPath(dir_path); - return mkdirZ(&dir_path_c, mode); - } -} - -/// Same as `mkdir` but the parameter is null-terminated. -/// On Windows, `dir_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `dir_path` should be encoded as valid UTF-8. -/// On other platforms, `dir_path` is an opaque sequence of bytes with no particular encoding. -pub fn mkdirZ(dir_path: [*:0]const u8, mode: mode_t) MakeDirError!void { - if (native_os == .windows) { - const dir_path_w = try windows.cStrToPrefixedFileW(null, dir_path); - return mkdirW(dir_path_w.span(), mode); - } else if (native_os == .wasi and !builtin.link_libc) { - return mkdir(mem.sliceTo(dir_path, 0), mode); - } - switch (errno(system.mkdir(dir_path, mode))) { - .SUCCESS => return, - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - .DQUOT => return error.DiskQuota, - .EXIST => return error.PathAlreadyExists, - .FAULT => unreachable, - .LOOP => return error.SymLinkLoop, - .MLINK => return error.LinkQuotaExceeded, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOMEM => return error.SystemResources, - .NOSPC => return error.NoSpaceLeft, - .NOTDIR => return error.NotDir, - .ROFS => return error.ReadOnlyFileSystem, - .ILSEQ => return error.BadPathName, - else => |err| return unexpectedErrno(err), - } -} - -/// Windows-only. Same as `mkdir` but the parameters is WTF16LE encoded. -pub fn mkdirW(dir_path_w: []const u16, mode: mode_t) MakeDirError!void { - _ = mode; - const sub_dir_handle = windows.OpenFile(dir_path_w, .{ - .dir = fs.cwd().fd, - .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE, - .creation = windows.FILE_CREATE, - .filter = .dir_only, - }) catch |err| switch (err) { - error.IsDir => return error.Unexpected, - error.PipeBusy => return error.Unexpected, - error.NoDevice => return error.Unexpected, - error.WouldBlock => return error.Unexpected, - error.AntivirusInterference => return error.Unexpected, - else => |e| return e, - }; - windows.CloseHandle(sub_dir_handle); -} - -pub const DeleteDirError = error{ - AccessDenied, - PermissionDenied, - FileBusy, - SymLinkLoop, - NameTooLong, - FileNotFound, - SystemResources, - NotDir, - DirNotEmpty, - ReadOnlyFileSystem, - /// WASI: file paths must be valid UTF-8. - /// Windows: file paths provided by the user must be valid WTF-8. - /// https://wtf-8.codeberg.page/ - BadPathName, - /// On Windows, `\\server` or `\\server\share` was not found. - NetworkNotFound, -} || UnexpectedError; - -/// Deletes an empty directory. -/// On Windows, `dir_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `dir_path` should be encoded as valid UTF-8. -/// On other platforms, `dir_path` is an opaque sequence of bytes with no particular encoding. -pub fn rmdir(dir_path: []const u8) DeleteDirError!void { - if (native_os == .wasi and !builtin.link_libc) { - return unlinkat(AT.FDCWD, dir_path, AT.REMOVEDIR) catch |err| switch (err) { - error.FileSystem => unreachable, // only occurs when targeting files - error.IsDir => unreachable, // only occurs when targeting files - else => |e| return e, - }; - } else if (native_os == .windows) { - const dir_path_w = try windows.sliceToPrefixedFileW(null, dir_path); - return rmdirW(dir_path_w.span()); - } else { - const dir_path_c = try toPosixPath(dir_path); - return rmdirZ(&dir_path_c); - } -} - -/// Same as `rmdir` except the parameter is null-terminated. -/// On Windows, `dir_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `dir_path` should be encoded as valid UTF-8. -/// On other platforms, `dir_path` is an opaque sequence of bytes with no particular encoding. -pub fn rmdirZ(dir_path: [*:0]const u8) DeleteDirError!void { - if (native_os == .windows) { - const dir_path_w = try windows.cStrToPrefixedFileW(null, dir_path); - return rmdirW(dir_path_w.span()); - } else if (native_os == .wasi and !builtin.link_libc) { - return rmdir(mem.sliceTo(dir_path, 0)); - } - switch (errno(system.rmdir(dir_path))) { - .SUCCESS => return, - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - .BUSY => return error.FileBusy, - .FAULT => unreachable, - .INVAL => return error.BadPathName, - .LOOP => return error.SymLinkLoop, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOMEM => return error.SystemResources, - .NOTDIR => return error.NotDir, - .EXIST => return error.DirNotEmpty, - .NOTEMPTY => return error.DirNotEmpty, - .ROFS => return error.ReadOnlyFileSystem, - .ILSEQ => return error.BadPathName, - else => |err| return unexpectedErrno(err), - } -} - -/// Windows-only. Same as `rmdir` except the parameter is WTF-16 LE encoded. -pub fn rmdirW(dir_path_w: []const u16) DeleteDirError!void { - return windows.DeleteFile(dir_path_w, .{ .dir = fs.cwd().fd, .remove_dir = true }) catch |err| switch (err) { - error.IsDir => unreachable, - else => |e| return e, - }; -} - -pub const ChangeCurDirError = error{ - AccessDenied, - FileSystem, - SymLinkLoop, - NameTooLong, - FileNotFound, - SystemResources, - NotDir, - /// WASI: file paths must be valid UTF-8. - /// Windows: file paths provided by the user must be valid WTF-8. - /// https://wtf-8.codeberg.page/ - BadPathName, -} || UnexpectedError; - -/// Changes the current working directory of the calling process. -/// On Windows, `dir_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `dir_path` should be encoded as valid UTF-8. -/// On other platforms, `dir_path` is an opaque sequence of bytes with no particular encoding. -pub fn chdir(dir_path: []const u8) ChangeCurDirError!void { - if (native_os == .wasi and !builtin.link_libc) { - @compileError("WASI does not support os.chdir"); - } else if (native_os == .windows) { - var wtf16_dir_path: [windows.PATH_MAX_WIDE]u16 = undefined; - const len = try windows.wtf8ToWtf16Le(&wtf16_dir_path, dir_path); - return chdirW(wtf16_dir_path[0..len]); - } else { - const dir_path_c = try toPosixPath(dir_path); - return chdirZ(&dir_path_c); - } -} - -/// Same as `chdir` except the parameter is null-terminated. -/// On Windows, `dir_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `dir_path` should be encoded as valid UTF-8. -/// On other platforms, `dir_path` is an opaque sequence of bytes with no particular encoding. -pub fn chdirZ(dir_path: [*:0]const u8) ChangeCurDirError!void { - if (native_os == .windows) { - const dir_path_span = mem.span(dir_path); - var wtf16_dir_path: [windows.PATH_MAX_WIDE]u16 = undefined; - const len = try windows.wtf8ToWtf16Le(&wtf16_dir_path, dir_path_span); - return chdirW(wtf16_dir_path[0..len]); - } else if (native_os == .wasi and !builtin.link_libc) { - return chdir(mem.span(dir_path)); - } - switch (errno(system.chdir(dir_path))) { - .SUCCESS => return, - .ACCES => return error.AccessDenied, - .FAULT => unreachable, - .IO => return error.FileSystem, - .LOOP => return error.SymLinkLoop, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOMEM => return error.SystemResources, - .NOTDIR => return error.NotDir, - .ILSEQ => return error.BadPathName, - else => |err| return unexpectedErrno(err), - } -} - -/// Windows-only. Same as `chdir` except the parameter is WTF16 LE encoded. -pub fn chdirW(dir_path: []const u16) ChangeCurDirError!void { - windows.SetCurrentDirectory(dir_path) catch |err| switch (err) { - error.NoDevice => return error.FileSystem, - else => |e| return e, - }; -} - -pub const FchdirError = error{ - AccessDenied, - NotDir, - FileSystem, -} || UnexpectedError; - -pub fn fchdir(dirfd: fd_t) FchdirError!void { - if (dirfd == AT.FDCWD) return; - while (true) { - switch (errno(system.fchdir(dirfd))) { - .SUCCESS => return, - .ACCES => return error.AccessDenied, - .BADF => unreachable, - .NOTDIR => return error.NotDir, - .INTR => continue, - .IO => return error.FileSystem, - else => |err| return unexpectedErrno(err), - } - } -} - -pub const ReadLinkError = error{ - /// In WASI, this error may occur when the file descriptor does - /// not hold the required rights to read value of a symbolic link relative to it. - AccessDenied, - PermissionDenied, - FileSystem, - SymLinkLoop, - NameTooLong, - FileNotFound, - SystemResources, - NotLink, - NotDir, - /// WASI: file paths must be valid UTF-8. - /// Windows: file paths provided by the user must be valid WTF-8. - /// https://wtf-8.codeberg.page/ - BadPathName, - /// Windows-only. This error may occur if the opened reparse point is - /// of unsupported type. - UnsupportedReparsePointType, - /// On Windows, `\\server` or `\\server\share` was not found. - NetworkNotFound, - /// On Windows, antivirus software is enabled by default. It can be - /// disabled, but Windows Update sometimes ignores the user's preference - /// and re-enables it. When enabled, antivirus software on Windows - /// intercepts file system operations and makes them significantly slower - /// in addition to possibly failing with this error code. - AntivirusInterference, -} || UnexpectedError; - -/// Read value of a symbolic link. -/// On Windows, `file_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `file_path` should be encoded as valid UTF-8. -/// On other platforms, `file_path` is an opaque sequence of bytes with no particular encoding. -/// The return value is a slice of `out_buffer` from index 0. -/// On Windows, the result is encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, the result is encoded as UTF-8. -/// On other platforms, the result is an opaque sequence of bytes with no particular encoding. -pub fn readlink(file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 { - if (native_os == .wasi and !builtin.link_libc) { - return readlinkat(AT.FDCWD, file_path, out_buffer); - } else if (native_os == .windows) { - var file_path_w = try windows.sliceToPrefixedFileW(null, file_path); - const result_w = try readlinkW(file_path_w.span(), &file_path_w.data); - - const len = std.unicode.calcWtf8Len(result_w); - if (len > out_buffer.len) return error.NameTooLong; - - const end_index = std.unicode.wtf16LeToWtf8(out_buffer, result_w); - return out_buffer[0..end_index]; - } else { - const file_path_c = try toPosixPath(file_path); - return readlinkZ(&file_path_c, out_buffer); - } -} - -/// Windows-only. Same as `readlink` except `file_path` is WTF-16 LE encoded, NT-prefixed. -/// The result is encoded as WTF-16 LE. -/// -/// `file_path` will never be accessed after `out_buffer` has been written to, so it -/// is safe to reuse a single buffer for both. -/// -/// See also `readlinkZ`. -pub fn readlinkW(file_path: []const u16, out_buffer: []u16) ReadLinkError![]u16 { - return windows.ReadLink(fs.cwd().fd, file_path, out_buffer); -} - -/// Same as `readlink` except `file_path` is null-terminated. -pub fn readlinkZ(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 { - if (native_os == .windows) { - var file_path_w = try windows.cStrToPrefixedFileW(null, file_path); - const result_w = try readlinkW(file_path_w.span(), &file_path_w.data); - - const len = std.unicode.calcWtf8Len(result_w); - if (len > out_buffer.len) return error.NameTooLong; - - const end_index = std.unicode.wtf16LeToWtf8(out_buffer, result_w); - return out_buffer[0..end_index]; - } else if (native_os == .wasi and !builtin.link_libc) { - return readlink(mem.sliceTo(file_path, 0), out_buffer); - } - const rc = system.readlink(file_path, out_buffer.ptr, out_buffer.len); - switch (errno(rc)) { - .SUCCESS => return out_buffer[0..@bitCast(rc)], - .ACCES => return error.AccessDenied, - .FAULT => unreachable, - .INVAL => return error.NotLink, - .IO => return error.FileSystem, - .LOOP => return error.SymLinkLoop, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOMEM => return error.SystemResources, - .NOTDIR => return error.NotDir, - .ILSEQ => return error.BadPathName, - else => |err| return unexpectedErrno(err), - } -} - -/// Similar to `readlink` except reads value of a symbolink link **relative** to `dirfd` directory handle. -/// On Windows, `file_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `file_path` should be encoded as valid UTF-8. -/// On other platforms, `file_path` is an opaque sequence of bytes with no particular encoding. -/// The return value is a slice of `out_buffer` from index 0. -/// On Windows, the result is encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, the result is encoded as UTF-8. -/// On other platforms, the result is an opaque sequence of bytes with no particular encoding. -/// See also `readlinkatWasi`, `realinkatZ` and `realinkatW`. -pub fn readlinkat(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 { - if (native_os == .wasi and !builtin.link_libc) { - return readlinkatWasi(dirfd, file_path, out_buffer); - } - if (native_os == .windows) { - var file_path_w = try windows.sliceToPrefixedFileW(dirfd, file_path); - const result_w = try readlinkatW(dirfd, file_path_w.span(), &file_path_w.data); - - const len = std.unicode.calcWtf8Len(result_w); - if (len > out_buffer.len) return error.NameTooLong; - - const end_index = std.unicode.wtf16LeToWtf8(out_buffer, result_w); - return out_buffer[0..end_index]; - } - const file_path_c = try toPosixPath(file_path); - return readlinkatZ(dirfd, &file_path_c, out_buffer); -} - -/// WASI-only. Same as `readlinkat` but targets WASI. -/// See also `readlinkat`. -pub fn readlinkatWasi(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 { - var bufused: usize = undefined; - switch (wasi.path_readlink(dirfd, file_path.ptr, file_path.len, out_buffer.ptr, out_buffer.len, &bufused)) { - .SUCCESS => return out_buffer[0..bufused], - .ACCES => return error.AccessDenied, - .FAULT => unreachable, - .INVAL => return error.NotLink, - .IO => return error.FileSystem, - .LOOP => return error.SymLinkLoop, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOMEM => return error.SystemResources, - .NOTDIR => return error.NotDir, - .NOTCAPABLE => return error.AccessDenied, - .ILSEQ => return error.BadPathName, - else => |err| return unexpectedErrno(err), - } -} - -/// Windows-only. Same as `readlinkat` except `file_path` WTF16 LE encoded, NT-prefixed. -/// The result is encoded as WTF-16 LE. -/// -/// `file_path` will never be accessed after `out_buffer` has been written to, so it -/// is safe to reuse a single buffer for both. -/// -/// See also `readlinkat`. -pub fn readlinkatW(dirfd: fd_t, file_path: []const u16, out_buffer: []u16) ReadLinkError![]u16 { - return windows.ReadLink(dirfd, file_path, out_buffer); -} - -/// Same as `readlinkat` except `file_path` is null-terminated. -/// See also `readlinkat`. -pub fn readlinkatZ(dirfd: fd_t, file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 { - if (native_os == .windows) { - var file_path_w = try windows.cStrToPrefixedFileW(dirfd, file_path); - const result_w = try readlinkatW(dirfd, file_path_w.span(), &file_path_w.data); - - const len = std.unicode.calcWtf8Len(result_w); - if (len > out_buffer.len) return error.NameTooLong; - - const end_index = std.unicode.wtf16LeToWtf8(out_buffer, result_w); - return out_buffer[0..end_index]; - } else if (native_os == .wasi and !builtin.link_libc) { - return readlinkat(dirfd, mem.sliceTo(file_path, 0), out_buffer); - } - const rc = system.readlinkat(dirfd, file_path, out_buffer.ptr, out_buffer.len); - switch (errno(rc)) { - .SUCCESS => return out_buffer[0..@bitCast(rc)], - .ACCES => return error.AccessDenied, - .FAULT => unreachable, - .INVAL => return error.NotLink, - .IO => return error.FileSystem, - .LOOP => return error.SymLinkLoop, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOMEM => return error.SystemResources, - .NOTDIR => return error.NotDir, - .ILSEQ => return error.BadPathName, - else => |err| return unexpectedErrno(err), - } -} - -pub const SetEidError = error{ - InvalidUserId, - PermissionDenied, -} || UnexpectedError; - -pub const SetIdError = error{ResourceLimitReached} || SetEidError; - -pub fn setuid(uid: uid_t) SetIdError!void { - switch (errno(system.setuid(uid))) { - .SUCCESS => return, - .AGAIN => return error.ResourceLimitReached, - .INVAL => return error.InvalidUserId, - .PERM => return error.PermissionDenied, - else => |err| return unexpectedErrno(err), - } -} - -pub fn seteuid(uid: uid_t) SetEidError!void { - switch (errno(system.seteuid(uid))) { - .SUCCESS => return, - .INVAL => return error.InvalidUserId, - .PERM => return error.PermissionDenied, - else => |err| return unexpectedErrno(err), - } -} - -pub fn setreuid(ruid: uid_t, euid: uid_t) SetIdError!void { - switch (errno(system.setreuid(ruid, euid))) { - .SUCCESS => return, - .AGAIN => return error.ResourceLimitReached, - .INVAL => return error.InvalidUserId, - .PERM => return error.PermissionDenied, - else => |err| return unexpectedErrno(err), - } -} - -pub fn setgid(gid: gid_t) SetIdError!void { - switch (errno(system.setgid(gid))) { - .SUCCESS => return, - .AGAIN => return error.ResourceLimitReached, - .INVAL => return error.InvalidUserId, - .PERM => return error.PermissionDenied, - else => |err| return unexpectedErrno(err), - } -} + const openat_sym = if (lfs64_abi) system.openat64 else system.openat; + while (true) { + const rc = openat_sym(dir_fd, file_path, flags, mode); + switch (errno(rc)) { + .SUCCESS => return @intCast(rc), + .INTR => continue, -pub fn setegid(uid: uid_t) SetEidError!void { - switch (errno(system.setegid(uid))) { - .SUCCESS => return, - .INVAL => return error.InvalidUserId, - .PERM => return error.PermissionDenied, - else => |err| return unexpectedErrno(err), + .FAULT => unreachable, + .INVAL => return error.BadPathName, + .BADF => unreachable, + .ACCES => return error.AccessDenied, + .FBIG => return error.FileTooBig, + .OVERFLOW => return error.FileTooBig, + .ISDIR => return error.IsDir, + .LOOP => return error.SymLinkLoop, + .MFILE => return error.ProcessFdQuotaExceeded, + .NAMETOOLONG => return error.NameTooLong, + .NFILE => return error.SystemFdQuotaExceeded, + .NODEV => return error.NoDevice, + .NOENT => return error.FileNotFound, + .SRCH => return error.FileNotFound, + .NOMEM => return error.SystemResources, + .NOSPC => return error.NoSpaceLeft, + .NOTDIR => return error.NotDir, + .PERM => return error.PermissionDenied, + .EXIST => return error.PathAlreadyExists, + .BUSY => return error.DeviceBusy, + .OPNOTSUPP => return error.FileLocksUnsupported, + .AGAIN => return error.WouldBlock, + .TXTBSY => return error.FileBusy, + .NXIO => return error.NoDevice, + .ILSEQ => return error.BadPathName, + else => |err| return unexpectedErrno(err), + } } } -pub fn setregid(rgid: gid_t, egid: gid_t) SetIdError!void { - switch (errno(system.setregid(rgid, egid))) { - .SUCCESS => return, - .AGAIN => return error.ResourceLimitReached, - .INVAL => return error.InvalidUserId, - .PERM => return error.PermissionDenied, - else => |err| return unexpectedErrno(err), - } +pub fn getppid() pid_t { + return system.getppid(); } -pub const SetPgidError = error{ - ProcessAlreadyExec, - InvalidProcessGroupId, - PermissionDenied, - ProcessNotFound, +pub const GetCwdError = error{ + NameTooLong, + CurrentWorkingDirectoryUnlinked, } || UnexpectedError; -pub fn setpgid(pid: pid_t, pgid: pid_t) SetPgidError!void { - switch (errno(system.setpgid(pid, pgid))) { - .SUCCESS => return, - .ACCES => return error.ProcessAlreadyExec, - .INVAL => return error.InvalidProcessGroupId, - .PERM => return error.PermissionDenied, - .SRCH => return error.ProcessNotFound, - else => |err| return unexpectedErrno(err), - } -} - -pub fn getuid() uid_t { - return system.getuid(); -} - -pub fn geteuid() uid_t { - return system.geteuid(); -} - -pub fn getgid() gid_t { - return system.getgid(); -} - -pub fn getegid() gid_t { - return system.getegid(); -} - -/// Test whether a file descriptor refers to a terminal. -pub fn isatty(handle: fd_t) bool { +/// The result is a slice of out_buffer, indexed from 0. +pub fn getcwd(out_buffer: []u8) GetCwdError![]u8 { if (native_os == .windows) { - if (fs.File.isCygwinPty(.{ .handle = handle })) - return true; - - var out: windows.DWORD = undefined; - return windows.kernel32.GetConsoleMode(handle, &out) != 0; - } - if (builtin.link_libc) { - return system.isatty(handle) != 0; - } - if (native_os == .wasi) { - var statbuf: wasi.fdstat_t = undefined; - const err = wasi.fd_fdstat_get(handle, &statbuf); - if (err != .SUCCESS) - return false; - - // A tty is a character device that we can't seek or tell on. - if (statbuf.fs_filetype != .CHARACTER_DEVICE) - return false; - if (statbuf.fs_rights_base.FD_SEEK or statbuf.fs_rights_base.FD_TELL) - return false; - - return true; + return windows.GetCurrentDirectory(out_buffer); + } else if (native_os == .wasi and !builtin.link_libc) { + const path = "."; + if (out_buffer.len < path.len) return error.NameTooLong; + const result = out_buffer[0..path.len]; + @memcpy(result, path); + return result; } - if (native_os == .linux) { - while (true) { - var wsz: winsize = undefined; - const fd: usize = @bitCast(@as(isize, handle)); - const rc = linux.syscall3(.ioctl, fd, linux.T.IOCGWINSZ, @intFromPtr(&wsz)); - switch (linux.errno(rc)) { - .SUCCESS => return true, - .INTR => continue, - else => return false, - } - } + + const err: E = if (builtin.link_libc) err: { + const c_err = if (std.c.getcwd(out_buffer.ptr, out_buffer.len)) |_| 0 else std.c._errno().*; + break :err @enumFromInt(c_err); + } else err: { + break :err errno(system.getcwd(out_buffer.ptr, out_buffer.len)); + }; + switch (err) { + .SUCCESS => return mem.sliceTo(out_buffer, 0), + .FAULT => unreachable, + .INVAL => unreachable, + .NOENT => return error.CurrentWorkingDirectoryUnlinked, + .RANGE => return error.NameTooLong, + else => return unexpectedErrno(err), } - return system.isatty(handle) != 0; } pub const SocketError = error{ @@ -3226,35 +579,6 @@ pub const SocketError = error{ SocketTypeNotSupported, } || UnexpectedError; -pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t { - const have_sock_flags = !builtin.target.os.tag.isDarwin() and native_os != .haiku; - const filtered_sock_type = if (!have_sock_flags) - socket_type & ~@as(u32, SOCK.NONBLOCK | SOCK.CLOEXEC) - else - socket_type; - const rc = system.socket(domain, filtered_sock_type, protocol); - switch (errno(rc)) { - .SUCCESS => { - const fd: fd_t = @intCast(rc); - errdefer close(fd); - if (!have_sock_flags) { - try setSockFlags(fd, socket_type); - } - return fd; - }, - .ACCES => return error.AccessDenied, - .AFNOSUPPORT => return error.AddressFamilyUnsupported, - .INVAL => return error.ProtocolFamilyNotAvailable, - .MFILE => return error.ProcessFdQuotaExceeded, - .NFILE => return error.SystemFdQuotaExceeded, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .PROTONOSUPPORT => return error.ProtocolNotSupported, - .PROTOTYPE => return error.SocketTypeNotSupported, - else => |err| return unexpectedErrno(err), - } -} - pub fn socketpair(domain: u32, socket_type: u32, protocol: u32) SocketError![2]socket_t { // Note to the future: we could provide a shim here for e.g. windows which // creates a listening socket, then creates a second socket and connects it @@ -3266,195 +590,33 @@ pub fn socketpair(domain: u32, socket_type: u32, protocol: u32) SocketError![2]s // existing filter here from pipe2(), because it sure seems like it // supports flags there too, but haiku can be hard to understand. const have_sock_flags = !builtin.target.os.tag.isDarwin() and native_os != .haiku; - const filtered_sock_type = if (!have_sock_flags) - socket_type & ~@as(u32, SOCK.NONBLOCK | SOCK.CLOEXEC) - else - socket_type; - var socks: [2]socket_t = undefined; - const rc = system.socketpair(domain, filtered_sock_type, protocol, &socks); - switch (errno(rc)) { - .SUCCESS => { - errdefer close(socks[0]); - errdefer close(socks[1]); - if (!have_sock_flags) { - try setSockFlags(socks[0], socket_type); - try setSockFlags(socks[1], socket_type); - } - return socks; - }, - .ACCES => return error.AccessDenied, - .AFNOSUPPORT => return error.AddressFamilyUnsupported, - .INVAL => return error.ProtocolFamilyNotAvailable, - .MFILE => return error.ProcessFdQuotaExceeded, - .NFILE => return error.SystemFdQuotaExceeded, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .PROTONOSUPPORT => return error.ProtocolNotSupported, - .PROTOTYPE => return error.SocketTypeNotSupported, - else => |err| return unexpectedErrno(err), - } -} - -pub const ShutdownError = error{ - ConnectionAborted, - - /// Connection was reset by peer, application should close socket as it is no longer usable. - ConnectionResetByPeer, - BlockingOperationInProgress, - - /// The network subsystem has failed. - NetworkDown, - - /// The socket is not connected (connection-oriented sockets only). - SocketUnconnected, - SystemResources, -} || UnexpectedError; - -pub const ShutdownHow = enum { recv, send, both }; - -/// Shutdown socket send/receive operations -pub fn shutdown(sock: socket_t, how: ShutdownHow) ShutdownError!void { - if (native_os == .windows) { - const result = windows.ws2_32.shutdown(sock, switch (how) { - .recv => windows.ws2_32.SD_RECEIVE, - .send => windows.ws2_32.SD_SEND, - .both => windows.ws2_32.SD_BOTH, - }); - if (0 != result) switch (windows.ws2_32.WSAGetLastError()) { - .ECONNABORTED => return error.ConnectionAborted, - .ECONNRESET => return error.ConnectionResetByPeer, - .EINPROGRESS => return error.BlockingOperationInProgress, - .EINVAL => unreachable, - .ENETDOWN => return error.NetworkDown, - .ENOTCONN => return error.SocketUnconnected, - .ENOTSOCK => unreachable, - .NOTINITIALISED => unreachable, - else => |err| return windows.unexpectedWSAError(err), - }; - } else { - const rc = system.shutdown(sock, switch (how) { - .recv => SHUT.RD, - .send => SHUT.WR, - .both => SHUT.RDWR, - }); - switch (errno(rc)) { - .SUCCESS => return, - .BADF => unreachable, - .INVAL => unreachable, - .NOTCONN => return error.SocketUnconnected, - .NOTSOCK => unreachable, - .NOBUFS => return error.SystemResources, - else => |err| return unexpectedErrno(err), - } - } -} - -pub const BindError = error{ - SymLinkLoop, - NameTooLong, - FileNotFound, - NotDir, - ReadOnlyFileSystem, - AccessDenied, -} || std.Io.net.IpAddress.BindError; - -pub fn bind(sock: socket_t, addr: *const sockaddr, len: socklen_t) BindError!void { - if (native_os == .windows) { - @compileError("use std.Io instead"); - } else { - const rc = system.bind(sock, addr, len); - switch (errno(rc)) { - .SUCCESS => return, - .ACCES, .PERM => return error.AccessDenied, - .ADDRINUSE => return error.AddressInUse, - .BADF => unreachable, // always a race condition if this error is returned - .INVAL => unreachable, // invalid parameters - .NOTSOCK => unreachable, // invalid `sockfd` - .AFNOSUPPORT => return error.AddressFamilyUnsupported, - .ADDRNOTAVAIL => return error.AddressUnavailable, - .FAULT => unreachable, // invalid `addr` pointer - .LOOP => return error.SymLinkLoop, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOMEM => return error.SystemResources, - .NOTDIR => return error.NotDir, - .ROFS => return error.ReadOnlyFileSystem, - else => |err| return unexpectedErrno(err), - } - } - unreachable; -} - -pub const ListenError = error{ - FileDescriptorNotASocket, - OperationNotSupported, -} || std.Io.net.IpAddress.ListenError || std.Io.net.UnixAddress.ListenError; - -pub fn listen(sock: socket_t, backlog: u31) ListenError!void { - if (native_os == .windows) { - @compileError("use std.Io instead"); - } else { - const rc = system.listen(sock, backlog); - switch (errno(rc)) { - .SUCCESS => return, - .ADDRINUSE => return error.AddressInUse, - .BADF => unreachable, - .NOTSOCK => return error.FileDescriptorNotASocket, - .OPNOTSUPP => return error.OperationNotSupported, - else => |err| return unexpectedErrno(err), - } - } -} - -pub const AcceptError = std.Io.net.Server.AcceptError; - -pub fn accept( - sock: socket_t, - addr: ?*sockaddr, - addr_size: ?*socklen_t, - flags: u32, -) AcceptError!socket_t { - const have_accept4 = !(builtin.target.os.tag.isDarwin() or native_os == .windows or native_os == .haiku); - assert(0 == (flags & ~@as(u32, SOCK.NONBLOCK | SOCK.CLOEXEC))); // Unsupported flag(s) - - const accepted_sock: socket_t = while (true) { - const rc = if (have_accept4) - system.accept4(sock, addr, addr_size, flags) - else - system.accept(sock, addr, addr_size); - - if (native_os == .windows) { - @compileError("use std.Io instead"); - } else { - switch (errno(rc)) { - .SUCCESS => break @intCast(rc), - .INTR => continue, - .AGAIN => return error.WouldBlock, - .BADF => unreachable, // always a race condition - .CONNABORTED => return error.ConnectionAborted, - .FAULT => unreachable, - .INVAL => return error.SocketNotListening, - .NOTSOCK => unreachable, - .MFILE => return error.ProcessFdQuotaExceeded, - .NFILE => return error.SystemFdQuotaExceeded, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .OPNOTSUPP => unreachable, - .PROTO => return error.ProtocolFailure, - .PERM => return error.BlockedByFirewall, - else => |err| return unexpectedErrno(err), + const filtered_sock_type = if (!have_sock_flags) + socket_type & ~@as(u32, SOCK.NONBLOCK | SOCK.CLOEXEC) + else + socket_type; + var socks: [2]socket_t = undefined; + const rc = system.socketpair(domain, filtered_sock_type, protocol, &socks); + switch (errno(rc)) { + .SUCCESS => { + errdefer close(socks[0]); + errdefer close(socks[1]); + if (!have_sock_flags) { + try setSockFlags(socks[0], socket_type); + try setSockFlags(socks[1], socket_type); } - } - }; - - errdefer switch (native_os) { - .windows => windows.closesocket(accepted_sock) catch unreachable, - else => close(accepted_sock), - }; - if (!have_accept4) { - try setSockFlags(accepted_sock, flags); + return socks; + }, + .ACCES => return error.AccessDenied, + .AFNOSUPPORT => return error.AddressFamilyUnsupported, + .INVAL => return error.ProtocolFamilyNotAvailable, + .MFILE => return error.ProcessFdQuotaExceeded, + .NFILE => return error.SystemFdQuotaExceeded, + .NOBUFS => return error.SystemResources, + .NOMEM => return error.SystemResources, + .PROTONOSUPPORT => return error.ProtocolNotSupported, + .PROTOTYPE => return error.SocketTypeNotSupported, + else => |err| return unexpectedErrno(err), } - return accepted_sock; } fn setSockFlags(sock: socket_t, flags: u32) !void { @@ -3515,94 +677,6 @@ fn setSockFlags(sock: socket_t, flags: u32) !void { } } -pub const EpollCreateError = error{ - /// The per-user limit on the number of epoll instances imposed by - /// /proc/sys/fs/epoll/max_user_instances was encountered. See epoll(7) for further - /// details. - /// Or, The per-process limit on the number of open file descriptors has been reached. - ProcessFdQuotaExceeded, - - /// The system-wide limit on the total number of open files has been reached. - SystemFdQuotaExceeded, - - /// There was insufficient memory to create the kernel object. - SystemResources, -} || UnexpectedError; - -pub fn epoll_create1(flags: u32) EpollCreateError!i32 { - const rc = system.epoll_create1(flags); - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - else => |err| return unexpectedErrno(err), - - .INVAL => unreachable, - .MFILE => return error.ProcessFdQuotaExceeded, - .NFILE => return error.SystemFdQuotaExceeded, - .NOMEM => return error.SystemResources, - } -} - -pub const EpollCtlError = error{ - /// op was EPOLL_CTL_ADD, and the supplied file descriptor fd is already registered - /// with this epoll instance. - FileDescriptorAlreadyPresentInSet, - - /// fd refers to an epoll instance and this EPOLL_CTL_ADD operation would result in a - /// circular loop of epoll instances monitoring one another. - OperationCausesCircularLoop, - - /// op was EPOLL_CTL_MOD or EPOLL_CTL_DEL, and fd is not registered with this epoll - /// instance. - FileDescriptorNotRegistered, - - /// There was insufficient memory to handle the requested op control operation. - SystemResources, - - /// The limit imposed by /proc/sys/fs/epoll/max_user_watches was encountered while - /// trying to register (EPOLL_CTL_ADD) a new file descriptor on an epoll instance. - /// See epoll(7) for further details. - UserResourceLimitReached, - - /// The target file fd does not support epoll. This error can occur if fd refers to, - /// for example, a regular file or a directory. - FileDescriptorIncompatibleWithEpoll, -} || UnexpectedError; - -pub fn epoll_ctl(epfd: i32, op: u32, fd: i32, event: ?*system.epoll_event) EpollCtlError!void { - const rc = system.epoll_ctl(epfd, op, fd, event); - switch (errno(rc)) { - .SUCCESS => return, - else => |err| return unexpectedErrno(err), - - .BADF => unreachable, // always a race condition if this happens - .EXIST => return error.FileDescriptorAlreadyPresentInSet, - .INVAL => unreachable, - .LOOP => return error.OperationCausesCircularLoop, - .NOENT => return error.FileDescriptorNotRegistered, - .NOMEM => return error.SystemResources, - .NOSPC => return error.UserResourceLimitReached, - .PERM => return error.FileDescriptorIncompatibleWithEpoll, - } -} - -/// Waits for an I/O event on an epoll file descriptor. -/// Returns the number of file descriptors ready for the requested I/O, -/// or zero if no file descriptor became ready during the requested timeout milliseconds. -pub fn epoll_wait(epfd: i32, events: []system.epoll_event, timeout: i32) usize { - while (true) { - // TODO get rid of the @intCast - const rc = system.epoll_wait(epfd, events.ptr, @intCast(events.len), timeout); - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - .INTR => continue, - .BADF => unreachable, - .FAULT => unreachable, - .INVAL => unreachable, - else => unreachable, - } - } -} - pub const EventFdError = error{ SystemResources, ProcessFdQuotaExceeded, @@ -3636,35 +710,6 @@ pub const GetSockNameError = error{ FileDescriptorNotASocket, } || UnexpectedError; -pub fn getsockname(sock: socket_t, addr: *sockaddr, addrlen: *socklen_t) GetSockNameError!void { - if (native_os == .windows) { - const rc = windows.getsockname(sock, addr, addrlen); - if (rc == windows.ws2_32.SOCKET_ERROR) { - switch (windows.ws2_32.WSAGetLastError()) { - .NOTINITIALISED => unreachable, - .ENETDOWN => return error.NetworkDown, - .EFAULT => unreachable, // addr or addrlen have invalid pointers or addrlen points to an incorrect value - .ENOTSOCK => return error.FileDescriptorNotASocket, - .EINVAL => return error.SocketNotBound, - else => |err| return windows.unexpectedWSAError(err), - } - } - return; - } else { - const rc = system.getsockname(sock, addr, addrlen); - switch (errno(rc)) { - .SUCCESS => return, - else => |err| return unexpectedErrno(err), - - .BADF => unreachable, // always a race condition - .FAULT => unreachable, - .INVAL => unreachable, // invalid parameters - .NOTSOCK => return error.FileDescriptorNotASocket, - .NOBUFS => return error.SystemResources, - } - } -} - pub fn getpeername(sock: socket_t, addr: *sockaddr, addrlen: *socklen_t) GetSockNameError!void { if (native_os == .windows) { const rc = windows.getpeername(sock, addr, addrlen); @@ -3728,250 +773,25 @@ pub fn connect(sock: socket_t, sock_addr: *const sockaddr, len: socklen_t) Conne } } -pub const GetSockOptError = error{ - /// The calling process does not have the appropriate privileges. - AccessDenied, - - /// The option is not supported by the protocol. - InvalidProtocolOption, - - /// Insufficient resources are available in the system to complete the call. - SystemResources, -} || UnexpectedError; - -pub fn getsockopt(fd: socket_t, level: i32, optname: u32, opt: []u8) GetSockOptError!void { - var len: socklen_t = @intCast(opt.len); - switch (errno(system.getsockopt(fd, level, optname, opt.ptr, &len))) { - .SUCCESS => { - std.debug.assert(len == opt.len); - }, - .BADF => unreachable, - .NOTSOCK => unreachable, - .INVAL => unreachable, - .FAULT => unreachable, - .NOPROTOOPT => return error.InvalidProtocolOption, - .NOMEM => return error.SystemResources, - .NOBUFS => return error.SystemResources, - .ACCES => return error.AccessDenied, - else => |err| return unexpectedErrno(err), - } -} - -pub fn getsockoptError(sockfd: fd_t) ConnectError!void { - var err_code: i32 = undefined; - var size: u32 = @sizeOf(u32); - const rc = system.getsockopt(sockfd, SOL.SOCKET, SO.ERROR, @ptrCast(&err_code), &size); - assert(size == 4); - switch (errno(rc)) { - .SUCCESS => switch (@as(E, @enumFromInt(err_code))) { - .SUCCESS => return, - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - .ADDRINUSE => return error.AddressInUse, - .ADDRNOTAVAIL => return error.AddressUnavailable, - .AFNOSUPPORT => return error.AddressFamilyUnsupported, - .AGAIN => return error.SystemResources, - .ALREADY => return error.ConnectionPending, - .BADF => unreachable, // sockfd is not a valid open file descriptor. - .CONNREFUSED => return error.ConnectionRefused, - .FAULT => unreachable, // The socket structure address is outside the user's address space. - .ISCONN => return error.AlreadyConnected, // The socket is already connected. - .HOSTUNREACH => return error.NetworkUnreachable, - .NETUNREACH => return error.NetworkUnreachable, - .NOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket. - .PROTOTYPE => unreachable, // The socket type does not support the requested communications protocol. - .TIMEDOUT => return error.Timeout, - .CONNRESET => return error.ConnectionResetByPeer, - else => |err| return unexpectedErrno(err), - }, - .BADF => unreachable, // The argument sockfd is not a valid file descriptor. - .FAULT => unreachable, // The address pointed to by optval or optlen is not in a valid part of the process address space. - .INVAL => unreachable, - .NOPROTOOPT => unreachable, // The option is unknown at the level indicated. - .NOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket. - else => |err| return unexpectedErrno(err), - } -} - -pub const WaitPidResult = struct { - pid: pid_t, - status: u32, -}; - -/// Use this version of the `waitpid` wrapper if you spawned your child process using explicit -/// `fork` and `execve` method. -pub fn waitpid(pid: pid_t, flags: u32) WaitPidResult { - var status: if (builtin.link_libc) c_int else u32 = undefined; - while (true) { - const rc = system.waitpid(pid, &status, @intCast(flags)); - switch (errno(rc)) { - .SUCCESS => return .{ - .pid = @intCast(rc), - .status = @bitCast(status), - }, - .INTR => continue, - .CHILD => unreachable, // The process specified does not exist. It would be a race condition to handle this error. - .INVAL => unreachable, // Invalid flags. - else => unreachable, - } - } -} - -pub fn wait4(pid: pid_t, flags: u32, ru: ?*rusage) WaitPidResult { - var status: if (builtin.link_libc) c_int else u32 = undefined; - while (true) { - const rc = system.wait4(pid, &status, @intCast(flags), ru); - switch (errno(rc)) { - .SUCCESS => return .{ - .pid = @intCast(rc), - .status = @bitCast(status), - }, - .INTR => continue, - .CHILD => unreachable, // The process specified does not exist. It would be a race condition to handle this error. - .INVAL => unreachable, // Invalid flags. - else => unreachable, - } - } -} - pub const FStatError = std.Io.File.StatError; /// Return information about a file descriptor. pub fn fstat(fd: fd_t) FStatError!Stat { if (native_os == .wasi and !builtin.link_libc) { - return Stat.fromFilestat(try std.os.fstat_wasi(fd)); - } - if (native_os == .windows) { - @compileError("fstat is not yet implemented on Windows"); - } - - const fstat_sym = if (lfs64_abi) system.fstat64 else system.fstat; - var stat = mem.zeroes(Stat); - switch (errno(fstat_sym(fd, &stat))) { - .SUCCESS => return stat, - .INVAL => unreachable, - .BADF => unreachable, // Always a race condition. - .NOMEM => return error.SystemResources, - .ACCES => return error.AccessDenied, - else => |err| return unexpectedErrno(err), - } -} - -pub const FStatAtError = FStatError || error{ - NameTooLong, - FileNotFound, - SymLinkLoop, - BadPathName, -}; - -/// Similar to `fstat`, but returns stat of a resource pointed to by `pathname` -/// which is relative to `dirfd` handle. -/// On WASI, `pathname` should be encoded as valid UTF-8. -/// On other platforms, `pathname` is an opaque sequence of bytes with no particular encoding. -/// See also `fstatatZ`. -pub fn fstatat(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!Stat { - if (native_os == .wasi and !builtin.link_libc) { - @compileError("use std.Io instead"); - } else if (native_os == .windows) { - @compileError("fstatat is not yet implemented on Windows"); - } else { - const pathname_c = try toPosixPath(pathname); - return fstatatZ(dirfd, &pathname_c, flags); - } -} - -/// Same as `fstatat` but `pathname` is null-terminated. -/// See also `fstatat`. -pub fn fstatatZ(dirfd: fd_t, pathname: [*:0]const u8, flags: u32) FStatAtError!Stat { - if (native_os == .wasi and !builtin.link_libc) { - @compileError("use std.Io instead"); + @compileError("unsupported OS"); } - const fstatat_sym = if (lfs64_abi) system.fstatat64 else system.fstatat; var stat = mem.zeroes(Stat); - switch (errno(fstatat_sym(dirfd, pathname, &stat, flags))) { + switch (errno(system.fstat(fd, &stat))) { .SUCCESS => return stat, .INVAL => unreachable, .BADF => unreachable, // Always a race condition. .NOMEM => return error.SystemResources, .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - .FAULT => unreachable, - .NAMETOOLONG => return error.NameTooLong, - .LOOP => return error.SymLinkLoop, - .NOENT => return error.FileNotFound, - .NOTDIR => return error.FileNotFound, - .ILSEQ => return error.BadPathName, - else => |err| return unexpectedErrno(err), - } -} - -pub const KQueueError = error{ - /// The per-process limit on the number of open file descriptors has been reached. - ProcessFdQuotaExceeded, - - /// The system-wide limit on the total number of open files has been reached. - SystemFdQuotaExceeded, -} || UnexpectedError; - -pub fn kqueue() KQueueError!i32 { - const rc = system.kqueue(); - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - .MFILE => return error.ProcessFdQuotaExceeded, - .NFILE => return error.SystemFdQuotaExceeded, else => |err| return unexpectedErrno(err), } } -pub const KEventError = error{ - /// The process does not have permission to register a filter. - AccessDenied, - - /// The event could not be found to be modified or deleted. - EventNotFound, - - /// No memory was available to register the event. - SystemResources, - - /// The specified process to attach to does not exist. - ProcessNotFound, - - /// changelist or eventlist had too many items on it. - /// TODO remove this possibility - Overflow, -}; - -pub fn kevent( - kq: i32, - changelist: []const Kevent, - eventlist: []Kevent, - timeout: ?*const timespec, -) KEventError!usize { - while (true) { - const rc = system.kevent( - kq, - changelist.ptr, - cast(c_int, changelist.len) orelse return error.Overflow, - eventlist.ptr, - cast(c_int, eventlist.len) orelse return error.Overflow, - timeout, - ); - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - .ACCES => return error.AccessDenied, - .FAULT => unreachable, - .BADF => unreachable, // Always a race condition. - .INTR => continue, - .INVAL => unreachable, - .NOENT => return error.EventNotFound, - .NOMEM => return error.SystemResources, - .SRCH => return error.ProcessNotFound, - else => unreachable, - } - } -} - pub const INotifyInitError = error{ ProcessFdQuotaExceeded, SystemFdQuotaExceeded, @@ -4067,9 +887,9 @@ pub const FanotifyMarkError = error{ SystemResources, UserMarkQuotaExceeded, NotDir, - OperationNotSupported, + OperationUnsupported, PermissionDenied, - NotSameFileSystem, + CrossDevice, NameTooLong, } || UnexpectedError; @@ -4107,9 +927,9 @@ pub fn fanotify_markZ( .NOMEM => return error.SystemResources, .NOSPC => return error.UserMarkQuotaExceeded, .NOTDIR => return error.NotDir, - .OPNOTSUPP => return error.OperationNotSupported, + .OPNOTSUPP => return error.OperationUnsupported, .PERM => return error.PermissionDenied, - .XDEV => return error.NotSameFileSystem, + .XDEV => return error.CrossDevice, else => |err| return unexpectedErrno(err), } } @@ -4215,26 +1035,14 @@ pub fn mprotect(memory: []align(page_size_min) u8, protection: u32) MProtectErro error.InvalidAddress => return error.AccessDenied, error.Unexpected => return error.Unexpected, }; - } else { - switch (errno(system.mprotect(memory.ptr, memory.len, protection))) { - .SUCCESS => return, - .INVAL => unreachable, - .ACCES => return error.AccessDenied, - .NOMEM => return error.OutOfMemory, - else => |err| return unexpectedErrno(err), - } - } -} - -pub const ForkError = error{SystemResources} || UnexpectedError; - -pub fn fork() ForkError!pid_t { - const rc = system.fork(); - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - .AGAIN => return error.SystemResources, - .NOMEM => return error.SystemResources, - else => |err| return unexpectedErrno(err), + } else { + switch (errno(system.mprotect(memory.ptr, memory.len, protection))) { + .SUCCESS => return, + .INVAL => unreachable, + .ACCES => return error.AccessDenied, + .NOMEM => return error.OutOfMemory, + else => |err| return unexpectedErrno(err), + } } } @@ -4367,141 +1175,6 @@ pub fn msync(memory: []align(page_size_min) u8, flags: i32) MSyncError!void { } } -pub const AccessError = error{ - AccessDenied, - PermissionDenied, - FileNotFound, - NameTooLong, - InputOutput, - SystemResources, - FileBusy, - SymLinkLoop, - ReadOnlyFileSystem, - /// WASI: file paths must be valid UTF-8. - /// Windows: file paths provided by the user must be valid WTF-8. - /// https://wtf-8.codeberg.page/ - BadPathName, - Canceled, -} || UnexpectedError; - -/// check user's permissions for a file -/// -/// * On Windows, asserts `path` is valid [WTF-8](https://wtf-8.codeberg.page/). -/// * On WASI, invalid UTF-8 passed to `path` causes `error.BadPathName`. -/// * On other platforms, `path` is an opaque sequence of bytes with no particular encoding. -/// -/// On Windows, `mode` is ignored. This is a POSIX API that is only partially supported by -/// Windows. See `fs` for the cross-platform file system API. -pub fn access(path: []const u8, mode: u32) AccessError!void { - if (native_os == .windows) { - @compileError("use std.Io instead"); - } else if (native_os == .wasi and !builtin.link_libc) { - @compileError("wasi doesn't support absolute paths"); - } - const path_c = try toPosixPath(path); - return accessZ(&path_c, mode); -} - -/// Same as `access` except `path` is null-terminated. -pub fn accessZ(path: [*:0]const u8, mode: u32) AccessError!void { - if (native_os == .windows) { - @compileError("use std.Io instead"); - } else if (native_os == .wasi and !builtin.link_libc) { - return access(mem.sliceTo(path, 0), mode); - } - switch (errno(system.access(path, mode))) { - .SUCCESS => return, - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - .ROFS => return error.ReadOnlyFileSystem, - .LOOP => return error.SymLinkLoop, - .TXTBSY => return error.FileBusy, - .NOTDIR => return error.FileNotFound, - .NOENT => return error.FileNotFound, - .NAMETOOLONG => return error.NameTooLong, - .INVAL => unreachable, - .FAULT => unreachable, - .IO => return error.InputOutput, - .NOMEM => return error.SystemResources, - .ILSEQ => return error.BadPathName, - else => |err| return unexpectedErrno(err), - } -} - -pub const PipeError = error{ - SystemFdQuotaExceeded, - ProcessFdQuotaExceeded, -} || UnexpectedError; - -/// Creates a unidirectional data channel that can be used for interprocess communication. -pub fn pipe() PipeError![2]fd_t { - var fds: [2]fd_t = undefined; - switch (errno(system.pipe(&fds))) { - .SUCCESS => return fds, - .INVAL => unreachable, // Invalid parameters to pipe() - .FAULT => unreachable, // Invalid fds pointer - .NFILE => return error.SystemFdQuotaExceeded, - .MFILE => return error.ProcessFdQuotaExceeded, - else => |err| return unexpectedErrno(err), - } -} - -pub fn pipe2(flags: O) PipeError![2]fd_t { - if (@TypeOf(system.pipe2) != void) { - var fds: [2]fd_t = undefined; - switch (errno(system.pipe2(&fds, flags))) { - .SUCCESS => return fds, - .INVAL => unreachable, // Invalid flags - .FAULT => unreachable, // Invalid fds pointer - .NFILE => return error.SystemFdQuotaExceeded, - .MFILE => return error.ProcessFdQuotaExceeded, - else => |err| return unexpectedErrno(err), - } - } - - const fds: [2]fd_t = try pipe(); - errdefer { - close(fds[0]); - close(fds[1]); - } - - // https://github.com/ziglang/zig/issues/18882 - if (@as(u32, @bitCast(flags)) == 0) - return fds; - - // CLOEXEC is special, it's a file descriptor flag and must be set using - // F.SETFD. - if (flags.CLOEXEC) { - for (fds) |fd| { - switch (errno(system.fcntl(fd, F.SETFD, @as(u32, FD_CLOEXEC)))) { - .SUCCESS => {}, - .INVAL => unreachable, // Invalid flags - .BADF => unreachable, // Always a race condition - else => |err| return unexpectedErrno(err), - } - } - } - - const new_flags: u32 = f: { - var new_flags = flags; - new_flags.CLOEXEC = false; - break :f @bitCast(new_flags); - }; - // Set every other flag affecting the file status using F.SETFL. - if (new_flags != 0) { - for (fds) |fd| { - switch (errno(system.fcntl(fd, F.SETFL, new_flags))) { - .SUCCESS => {}, - .INVAL => unreachable, // Invalid flags - .BADF => unreachable, // Always a race condition - else => |err| return unexpectedErrno(err), - } - } - } - - return fds; -} - pub const SysCtlError = error{ PermissionDenied, SystemResources, @@ -4572,177 +1245,6 @@ pub fn gettimeofday(tv: ?*timeval, tz: ?*timezone) void { } } -pub const SeekError = std.Io.File.SeekError; - -pub fn lseek_SET(fd: fd_t, offset: u64) SeekError!void { - if (native_os == .linux and !builtin.link_libc and @sizeOf(usize) == 4) { - var result: u64 = undefined; - switch (errno(system.llseek(fd, offset, &result, SEEK.SET))) { - .SUCCESS => return, - .BADF => unreachable, // always a race condition - .INVAL => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .SPIPE => return error.Unseekable, - .NXIO => return error.Unseekable, - else => |err| return unexpectedErrno(err), - } - } - if (native_os == .windows) { - return windows.SetFilePointerEx_BEGIN(fd, offset); - } - if (native_os == .wasi and !builtin.link_libc) { - var new_offset: wasi.filesize_t = undefined; - switch (wasi.fd_seek(fd, @bitCast(offset), .SET, &new_offset)) { - .SUCCESS => return, - .BADF => unreachable, // always a race condition - .INVAL => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .SPIPE => return error.Unseekable, - .NXIO => return error.Unseekable, - .NOTCAPABLE => return error.AccessDenied, - else => |err| return unexpectedErrno(err), - } - } - - const lseek_sym = if (lfs64_abi) system.lseek64 else system.lseek; - switch (errno(lseek_sym(fd, @bitCast(offset), SEEK.SET))) { - .SUCCESS => return, - .BADF => unreachable, // always a race condition - .INVAL => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .SPIPE => return error.Unseekable, - .NXIO => return error.Unseekable, - else => |err| return unexpectedErrno(err), - } -} - -/// Repositions read/write file offset relative to the current offset. -pub fn lseek_CUR(fd: fd_t, offset: i64) SeekError!void { - if (native_os == .linux and !builtin.link_libc and @sizeOf(usize) == 4) { - var result: u64 = undefined; - switch (errno(system.llseek(fd, @bitCast(offset), &result, SEEK.CUR))) { - .SUCCESS => return, - .BADF => unreachable, // always a race condition - .INVAL => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .SPIPE => return error.Unseekable, - .NXIO => return error.Unseekable, - else => |err| return unexpectedErrno(err), - } - } - if (native_os == .windows) { - return windows.SetFilePointerEx_CURRENT(fd, offset); - } - if (native_os == .wasi and !builtin.link_libc) { - var new_offset: wasi.filesize_t = undefined; - switch (wasi.fd_seek(fd, offset, .CUR, &new_offset)) { - .SUCCESS => return, - .BADF => unreachable, // always a race condition - .INVAL => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .SPIPE => return error.Unseekable, - .NXIO => return error.Unseekable, - .NOTCAPABLE => return error.AccessDenied, - else => |err| return unexpectedErrno(err), - } - } - const lseek_sym = if (lfs64_abi) system.lseek64 else system.lseek; - switch (errno(lseek_sym(fd, @bitCast(offset), SEEK.CUR))) { - .SUCCESS => return, - .BADF => unreachable, // always a race condition - .INVAL => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .SPIPE => return error.Unseekable, - .NXIO => return error.Unseekable, - else => |err| return unexpectedErrno(err), - } -} - -/// Repositions read/write file offset relative to the end. -pub fn lseek_END(fd: fd_t, offset: i64) SeekError!void { - if (native_os == .linux and !builtin.link_libc and @sizeOf(usize) == 4) { - var result: u64 = undefined; - switch (errno(system.llseek(fd, @bitCast(offset), &result, SEEK.END))) { - .SUCCESS => return, - .BADF => unreachable, // always a race condition - .INVAL => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .SPIPE => return error.Unseekable, - .NXIO => return error.Unseekable, - else => |err| return unexpectedErrno(err), - } - } - if (native_os == .windows) { - return windows.SetFilePointerEx_END(fd, offset); - } - if (native_os == .wasi and !builtin.link_libc) { - var new_offset: wasi.filesize_t = undefined; - switch (wasi.fd_seek(fd, offset, .END, &new_offset)) { - .SUCCESS => return, - .BADF => unreachable, // always a race condition - .INVAL => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .SPIPE => return error.Unseekable, - .NXIO => return error.Unseekable, - .NOTCAPABLE => return error.AccessDenied, - else => |err| return unexpectedErrno(err), - } - } - const lseek_sym = if (lfs64_abi) system.lseek64 else system.lseek; - switch (errno(lseek_sym(fd, @bitCast(offset), SEEK.END))) { - .SUCCESS => return, - .BADF => unreachable, // always a race condition - .INVAL => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .SPIPE => return error.Unseekable, - .NXIO => return error.Unseekable, - else => |err| return unexpectedErrno(err), - } -} - -/// Returns the read/write file offset relative to the beginning. -pub fn lseek_CUR_get(fd: fd_t) SeekError!u64 { - if (native_os == .linux and !builtin.link_libc and @sizeOf(usize) == 4) { - var result: u64 = undefined; - switch (errno(system.llseek(fd, 0, &result, SEEK.CUR))) { - .SUCCESS => return result, - .BADF => unreachable, // always a race condition - .INVAL => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .SPIPE => return error.Unseekable, - .NXIO => return error.Unseekable, - else => |err| return unexpectedErrno(err), - } - } - if (native_os == .windows) { - return windows.SetFilePointerEx_CURRENT_get(fd); - } - if (native_os == .wasi and !builtin.link_libc) { - var new_offset: wasi.filesize_t = undefined; - switch (wasi.fd_seek(fd, 0, .CUR, &new_offset)) { - .SUCCESS => return new_offset, - .BADF => unreachable, // always a race condition - .INVAL => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .SPIPE => return error.Unseekable, - .NXIO => return error.Unseekable, - .NOTCAPABLE => return error.AccessDenied, - else => |err| return unexpectedErrno(err), - } - } - const lseek_sym = if (lfs64_abi) system.lseek64 else system.lseek; - const rc = lseek_sym(fd, 0, SEEK.CUR); - switch (errno(rc)) { - .SUCCESS => return @bitCast(rc), - .BADF => unreachable, // always a race condition - .INVAL => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .SPIPE => return error.Unseekable, - .NXIO => return error.Unseekable, - else => |err| return unexpectedErrno(err), - } -} - pub const FcntlError = error{ PermissionDenied, FileBusy, @@ -4752,226 +1254,22 @@ pub const FcntlError = error{ LockedRegionLimitExceeded, } || UnexpectedError; -pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) FcntlError!usize { - while (true) { - const rc = system.fcntl(fd, cmd, arg); - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - .INTR => continue, - .AGAIN, .ACCES => return error.Locked, - .BADF => unreachable, - .BUSY => return error.FileBusy, - .INVAL => unreachable, // invalid parameters - .PERM => return error.PermissionDenied, - .MFILE => return error.ProcessFdQuotaExceeded, - .NOTDIR => unreachable, // invalid parameter - .DEADLK => return error.DeadLock, - .NOLCK => return error.LockedRegionLimitExceeded, - else => |err| return unexpectedErrno(err), - } - } -} - -pub const FlockError = error{ - WouldBlock, - - /// The kernel ran out of memory for allocating file locks - SystemResources, - - /// The underlying filesystem does not support file locks - FileLocksNotSupported, -} || UnexpectedError; - -/// Depending on the operating system `flock` may or may not interact with -/// `fcntl` locks made by other processes. -pub fn flock(fd: fd_t, operation: i32) FlockError!void { - while (true) { - const rc = system.flock(fd, operation); - switch (errno(rc)) { - .SUCCESS => return, - .BADF => unreachable, - .INTR => continue, - .INVAL => unreachable, // invalid parameters - .NOLCK => return error.SystemResources, - .AGAIN => return error.WouldBlock, // TODO: integrate with async instead of just returning an error - .OPNOTSUPP => return error.FileLocksNotSupported, - else => |err| return unexpectedErrno(err), - } - } -} - -pub const RealPathError = error{ - FileNotFound, - AccessDenied, - PermissionDenied, - NameTooLong, - NotSupported, - NotDir, - SymLinkLoop, - InputOutput, - FileTooBig, - IsDir, - ProcessFdQuotaExceeded, - SystemFdQuotaExceeded, - NoDevice, - SystemResources, - NoSpaceLeft, - FileSystem, - DeviceBusy, - ProcessNotFound, - - SharingViolation, - PipeBusy, - - /// Windows: file paths provided by the user must be valid WTF-8. - /// https://wtf-8.codeberg.page/ - BadPathName, - - /// On Windows, `\\server` or `\\server\share` was not found. - NetworkNotFound, - - PathAlreadyExists, - - /// On Windows, antivirus software is enabled by default. It can be - /// disabled, but Windows Update sometimes ignores the user's preference - /// and re-enables it. When enabled, antivirus software on Windows - /// intercepts file system operations and makes them significantly slower - /// in addition to possibly failing with this error code. - AntivirusInterference, - - /// On Windows, the volume does not contain a recognized file system. File - /// system drivers might not be loaded, or the volume may be corrupt. - UnrecognizedVolume, - - Canceled, -} || UnexpectedError; - -/// Return the canonicalized absolute pathname. -/// -/// Expands all symbolic links and resolves references to `.`, `..`, and -/// extra `/` characters in `pathname`. -/// -/// On Windows, `pathname` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// -/// On other platforms, `pathname` is an opaque sequence of bytes with no particular encoding. -/// -/// The return value is a slice of `out_buffer`, but not necessarily from the beginning. -/// -/// See also `realpathZ` and `realpathW`. -/// -/// * On Windows, the result is encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// * On other platforms, the result is an opaque sequence of bytes with no particular encoding. -/// -/// Calling this function is usually a bug. -pub fn realpath(pathname: []const u8, out_buffer: *[max_path_bytes]u8) RealPathError![]u8 { - if (native_os == .windows) { - var pathname_w = try windows.sliceToPrefixedFileW(null, pathname); - - const wide_slice = try realpathW2(pathname_w.span(), &pathname_w.data); - - const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice); - return out_buffer[0..end_index]; - } else if (native_os == .wasi and !builtin.link_libc) { - @compileError("WASI does not support os.realpath"); - } - const pathname_c = try toPosixPath(pathname); - return realpathZ(&pathname_c, out_buffer); -} - -/// Same as `realpath` except `pathname` is null-terminated. -/// -/// Calling this function is usually a bug. -pub fn realpathZ(pathname: [*:0]const u8, out_buffer: *[max_path_bytes]u8) RealPathError![]u8 { - if (native_os == .windows) { - var pathname_w = try windows.cStrToPrefixedFileW(null, pathname); - - const wide_slice = try realpathW2(pathname_w.span(), &pathname_w.data); - - const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice); - return out_buffer[0..end_index]; - } else if (native_os == .wasi and !builtin.link_libc) { - return realpath(mem.sliceTo(pathname, 0), out_buffer); - } - if (!builtin.link_libc) { - const flags: O = switch (native_os) { - .linux => .{ - .NONBLOCK = true, - .CLOEXEC = true, - .PATH = true, - }, - else => .{ - .NONBLOCK = true, - .CLOEXEC = true, - }, - }; - const fd = openZ(pathname, flags, 0) catch |err| switch (err) { - error.FileLocksNotSupported => unreachable, - error.WouldBlock => unreachable, - error.FileBusy => unreachable, // not asking for write permissions - else => |e| return e, - }; - defer close(fd); - - return std.os.getFdPath(fd, out_buffer); - } - const result_path = std.c.realpath(pathname, out_buffer) orelse switch (@as(E, @enumFromInt(std.c._errno().*))) { - .SUCCESS => unreachable, - .INVAL => unreachable, - .BADF => unreachable, - .FAULT => unreachable, - .ACCES => return error.AccessDenied, - .NOENT => return error.FileNotFound, - .OPNOTSUPP => return error.NotSupported, - .NOTDIR => return error.NotDir, - .NAMETOOLONG => return error.NameTooLong, - .LOOP => return error.SymLinkLoop, - .IO => return error.InputOutput, - else => |err| return unexpectedErrno(err), - }; - return mem.sliceTo(result_path, 0); -} - -/// Deprecated: use `realpathW2`. -/// -/// Same as `realpath` except `pathname` is WTF16LE-encoded. -/// -/// The result is encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// -/// Calling this function is usually a bug. -pub fn realpathW(pathname: []const u16, out_buffer: *[max_path_bytes]u8) RealPathError![]u8 { - return fs.cwd().realpathW(pathname, out_buffer); -} - -/// Same as `realpath` except `pathname` is WTF16LE-encoded. -/// -/// The result is encoded as WTF16LE. -/// -/// Calling this function is usually a bug. -pub fn realpathW2(pathname: []const u16, out_buffer: *[std.os.windows.PATH_MAX_WIDE]u16) RealPathError![]u16 { - return fs.cwd().realpathW2(pathname, out_buffer); -} - -/// Spurious wakeups are possible and no precision of timing is guaranteed. -pub fn nanosleep(seconds: u64, nanoseconds: u64) void { - var req = timespec{ - .sec = cast(isize, seconds) orelse maxInt(isize), - .nsec = cast(isize, nanoseconds) orelse maxInt(isize), - }; - var rem: timespec = undefined; +pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) FcntlError!usize { while (true) { - switch (errno(system.nanosleep(&req, &rem))) { - .FAULT => unreachable, - .INVAL => { - // Sometimes Darwin returns EINVAL for no reason. - // We treat it as a spurious wakeup. - return; - }, - .INTR => { - req = rem; - continue; - }, - // This prong handles success as well as unexpected errors. - else => return, + const rc = system.fcntl(fd, cmd, arg); + switch (errno(rc)) { + .SUCCESS => return @intCast(rc), + .INTR => continue, + .AGAIN, .ACCES => return error.Locked, + .BADF => unreachable, + .BUSY => return error.FileBusy, + .INVAL => unreachable, // invalid parameters + .PERM => return error.PermissionDenied, + .MFILE => return error.ProcessFdQuotaExceeded, + .NOTDIR => unreachable, // invalid parameter + .DEADLK => return error.DeadLock, + .NOLCK => return error.LockedRegionLimitExceeded, + else => |err| return unexpectedErrno(err), } } } @@ -5035,16 +1333,16 @@ pub fn dl_iterate_phdr( // Last return value from the callback function. while (it.next()) |entry| { - const phdrs: []elf.ElfN.Phdr = if (entry.l_addr != 0) phdrs: { - const ehdr: *elf.ElfN.Ehdr = @ptrFromInt(entry.l_addr); + const phdrs: []elf.ElfN.Phdr = if (entry.addr != 0) phdrs: { + const ehdr: *elf.ElfN.Ehdr = @ptrFromInt(entry.addr); assert(mem.eql(u8, ehdr.ident[0..4], elf.MAGIC)); - const phdrs: [*]elf.ElfN.Phdr = @ptrFromInt(entry.l_addr + ehdr.phoff); + const phdrs: [*]elf.ElfN.Phdr = @ptrFromInt(entry.addr + ehdr.phoff); break :phdrs phdrs[0..ehdr.phnum]; } else getSelfPhdrs(); var info: dl_phdr_info = .{ - .addr = entry.l_addr, - .name = entry.l_name, + .addr = entry.addr, + .name = entry.name, .phdr = phdrs.ptr, .phnum = @intCast(phdrs.len), }; @@ -5215,74 +1513,6 @@ pub fn sigprocmask(flags: u32, noalias set: ?*const sigset_t, noalias oldset: ?* } } -pub const FutimensError = error{ - /// times is NULL, or both nsec values are UTIME_NOW, and either: - /// * the effective user ID of the caller does not match the owner - /// of the file, the caller does not have write access to the - /// file, and the caller is not privileged (Linux: does not have - /// either the CAP_FOWNER or the CAP_DAC_OVERRIDE capability); - /// or, - /// * the file is marked immutable (see chattr(1)). - AccessDenied, - - /// The caller attempted to change one or both timestamps to a value - /// other than the current time, or to change one of the timestamps - /// to the current time while leaving the other timestamp unchanged, - /// (i.e., times is not NULL, neither nsec field is UTIME_NOW, - /// and neither nsec field is UTIME_OMIT) and either: - /// * the caller's effective user ID does not match the owner of - /// file, and the caller is not privileged (Linux: does not have - /// the CAP_FOWNER capability); or, - /// * the file is marked append-only or immutable (see chattr(1)). - PermissionDenied, - - ReadOnlyFileSystem, -} || UnexpectedError; - -pub fn futimens(fd: fd_t, times: ?*const [2]timespec) FutimensError!void { - if (native_os == .wasi and !builtin.link_libc) { - // TODO WASI encodes `wasi.fstflags` to signify magic values - // similar to UTIME_NOW and UTIME_OMIT. Currently, we ignore - // this here, but we should really handle it somehow. - const error_code = blk: { - if (times) |times_arr| { - const atim = times_arr[0].toTimestamp(); - const mtim = times_arr[1].toTimestamp(); - break :blk wasi.fd_filestat_set_times(fd, atim, mtim, .{ - .ATIM = true, - .MTIM = true, - }); - } - - break :blk wasi.fd_filestat_set_times(fd, 0, 0, .{ - .ATIM_NOW = true, - .MTIM_NOW = true, - }); - }; - switch (error_code) { - .SUCCESS => return, - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - .BADF => unreachable, // always a race condition - .FAULT => unreachable, - .INVAL => unreachable, - .ROFS => return error.ReadOnlyFileSystem, - else => |err| return unexpectedErrno(err), - } - } - - switch (errno(system.futimens(fd, times))) { - .SUCCESS => return, - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - .BADF => unreachable, // always a race condition - .FAULT => unreachable, - .INVAL => unreachable, - .ROFS => return error.ReadOnlyFileSystem, - else => |err| return unexpectedErrno(err), - } -} - pub const GetHostNameError = error{PermissionDenied} || UnexpectedError; pub fn gethostname(name_buffer: *[HOST_NAME_MAX]u8) GetHostNameError![]u8 { @@ -5315,381 +1545,6 @@ pub fn uname() utsname { } } -pub const SendError = error{ - /// (For UNIX domain sockets, which are identified by pathname) Write permission is denied - /// on the destination socket file, or search permission is denied for one of the - /// directories the path prefix. (See path_resolution(7).) - /// (For UDP sockets) An attempt was made to send to a network/broadcast address as though - /// it was a unicast address. - AccessDenied, - - /// The socket is marked nonblocking and the requested operation would block, and - /// there is no global event loop configured. - /// It's also possible to get this error under the following condition: - /// (Internet domain datagram sockets) The socket referred to by sockfd had not previously - /// been bound to an address and, upon attempting to bind it to an ephemeral port, it was - /// determined that all port numbers in the ephemeral port range are currently in use. See - /// the discussion of /proc/sys/net/ipv4/ip_local_port_range in ip(7). - WouldBlock, - - /// Another Fast Open is already in progress. - FastOpenAlreadyInProgress, - - /// Connection reset by peer. - ConnectionResetByPeer, - - /// The socket type requires that message be sent atomically, and the size of the message - /// to be sent made this impossible. The message is not transmitted. - MessageOversize, - - /// The output queue for a network interface was full. This generally indicates that the - /// interface has stopped sending, but may be caused by transient congestion. (Normally, - /// this does not occur in Linux. Packets are just silently dropped when a device queue - /// overflows.) - /// This is also caused when there is not enough kernel memory available. - SystemResources, - - /// The local end has been shut down on a connection oriented socket. In this case, the - /// process will also receive a SIGPIPE unless MSG.NOSIGNAL is set. - BrokenPipe, - - FileDescriptorNotASocket, - - /// Network is unreachable. - NetworkUnreachable, - - /// The local network interface used to reach the destination is down. - NetworkDown, - - /// The destination address is not listening. - ConnectionRefused, -} || UnexpectedError; - -pub const SendMsgError = SendError || error{ - /// The passed address didn't have the correct address family in its sa_family field. - AddressFamilyUnsupported, - - /// Returned when socket is AF.UNIX and the given path has a symlink loop. - SymLinkLoop, - - /// Returned when socket is AF.UNIX and the given path length exceeds `max_path_bytes` bytes. - NameTooLong, - - /// Returned when socket is AF.UNIX and the given path does not point to an existing file. - FileNotFound, - NotDir, - - /// The socket is not connected (connection-oriented sockets only). - SocketUnconnected, - AddressUnavailable, -}; - -pub fn sendmsg( - /// The file descriptor of the sending socket. - sockfd: socket_t, - /// Message header and iovecs - msg: *const msghdr_const, - flags: u32, -) SendMsgError!usize { - while (true) { - const rc = system.sendmsg(sockfd, msg, flags); - if (native_os == .windows) { - if (rc == windows.ws2_32.SOCKET_ERROR) { - switch (windows.ws2_32.WSAGetLastError()) { - .EACCES => return error.AccessDenied, - .EADDRNOTAVAIL => return error.AddressUnavailable, - .ECONNRESET => return error.ConnectionResetByPeer, - .EMSGSIZE => return error.MessageOversize, - .ENOBUFS => return error.SystemResources, - .ENOTSOCK => return error.FileDescriptorNotASocket, - .EAFNOSUPPORT => return error.AddressFamilyUnsupported, - .EDESTADDRREQ => unreachable, // A destination address is required. - .EFAULT => unreachable, // The lpBuffers, lpTo, lpOverlapped, lpNumberOfBytesSent, or lpCompletionRoutine parameters are not part of the user address space, or the lpTo parameter is too small. - .EHOSTUNREACH => return error.NetworkUnreachable, - // TODO: EINPROGRESS, EINTR - .EINVAL => unreachable, - .ENETDOWN => return error.NetworkDown, - .ENETRESET => return error.ConnectionResetByPeer, - .ENETUNREACH => return error.NetworkUnreachable, - .ENOTCONN => return error.SocketUnconnected, - .ESHUTDOWN => unreachable, // The socket has been shut down; it is not possible to WSASendTo on a socket after shutdown has been invoked with how set to SD_SEND or SD_BOTH. - .EWOULDBLOCK => return error.WouldBlock, - .NOTINITIALISED => unreachable, // A successful WSAStartup call must occur before using this function. - else => |err| return windows.unexpectedWSAError(err), - } - } else { - return @intCast(rc); - } - } else { - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - - .ACCES => return error.AccessDenied, - .AGAIN => return error.WouldBlock, - .ALREADY => return error.FastOpenAlreadyInProgress, - .BADF => unreachable, // always a race condition - .CONNRESET => return error.ConnectionResetByPeer, - .DESTADDRREQ => unreachable, // The socket is not connection-mode, and no peer address is set. - .FAULT => unreachable, // An invalid user space address was specified for an argument. - .INTR => continue, - .INVAL => unreachable, // Invalid argument passed. - .ISCONN => unreachable, // connection-mode socket was connected already but a recipient was specified - .MSGSIZE => return error.MessageOversize, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket. - .OPNOTSUPP => unreachable, // Some bit in the flags argument is inappropriate for the socket type. - .PIPE => return error.BrokenPipe, - .AFNOSUPPORT => return error.AddressFamilyUnsupported, - .LOOP => return error.SymLinkLoop, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOTDIR => return error.NotDir, - .HOSTUNREACH => return error.NetworkUnreachable, - .NETUNREACH => return error.NetworkUnreachable, - .NOTCONN => return error.SocketUnconnected, - .NETDOWN => return error.NetworkDown, - else => |err| return unexpectedErrno(err), - } - } - } -} - -pub const SendToError = SendMsgError || error{ - /// The destination address is not reachable by the bound address. - UnreachableAddress, - /// The destination address is not listening. - ConnectionRefused, -}; - -/// Transmit a message to another socket. -/// -/// The `sendto` call may be used only when the socket is in a connected state (so that the intended -/// recipient is known). The following call -/// -/// send(sockfd, buf, len, flags); -/// -/// is equivalent to -/// -/// sendto(sockfd, buf, len, flags, NULL, 0); -/// -/// If sendto() is used on a connection-mode (`SOCK.STREAM`, `SOCK.SEQPACKET`) socket, the arguments -/// `dest_addr` and `addrlen` are asserted to be `null` and `0` respectively, and asserted -/// that the socket was actually connected. -/// Otherwise, the address of the target is given by `dest_addr` with `addrlen` specifying its size. -/// -/// If the message is too long to pass atomically through the underlying protocol, -/// `SendError.MessageOversize` is returned, and the message is not transmitted. -/// -/// There is no indication of failure to deliver. -/// -/// When the message does not fit into the send buffer of the socket, `sendto` normally blocks, -/// unless the socket has been placed in nonblocking I/O mode. In nonblocking mode it would fail -/// with `SendError.WouldBlock`. The `select` call may be used to determine when it is -/// possible to send more data. -pub fn sendto( - /// The file descriptor of the sending socket. - sockfd: socket_t, - /// Message to send. - buf: []const u8, - flags: u32, - dest_addr: ?*const sockaddr, - addrlen: socklen_t, -) SendToError!usize { - if (native_os == .windows) { - switch (windows.sendto(sockfd, buf.ptr, buf.len, flags, dest_addr, addrlen)) { - windows.ws2_32.SOCKET_ERROR => switch (windows.ws2_32.WSAGetLastError()) { - .EACCES => return error.AccessDenied, - .EADDRNOTAVAIL => return error.AddressUnavailable, - .ECONNRESET => return error.ConnectionResetByPeer, - .EMSGSIZE => return error.MessageOversize, - .ENOBUFS => return error.SystemResources, - .ENOTSOCK => return error.FileDescriptorNotASocket, - .EAFNOSUPPORT => return error.AddressFamilyUnsupported, - .EDESTADDRREQ => unreachable, // A destination address is required. - .EFAULT => unreachable, // The lpBuffers, lpTo, lpOverlapped, lpNumberOfBytesSent, or lpCompletionRoutine parameters are not part of the user address space, or the lpTo parameter is too small. - .EHOSTUNREACH => return error.NetworkUnreachable, - // TODO: EINPROGRESS, EINTR - .EINVAL => unreachable, - .ENETDOWN => return error.NetworkDown, - .ENETRESET => return error.ConnectionResetByPeer, - .ENETUNREACH => return error.NetworkUnreachable, - .ENOTCONN => return error.SocketUnconnected, - .ESHUTDOWN => unreachable, // The socket has been shut down; it is not possible to WSASendTo on a socket after shutdown has been invoked with how set to SD_SEND or SD_BOTH. - .EWOULDBLOCK => return error.WouldBlock, - .NOTINITIALISED => unreachable, // A successful WSAStartup call must occur before using this function. - else => |err| return windows.unexpectedWSAError(err), - }, - else => |rc| return @intCast(rc), - } - } - while (true) { - const rc = system.sendto(sockfd, buf.ptr, buf.len, flags, dest_addr, addrlen); - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - - .ACCES => return error.AccessDenied, - .AGAIN => return error.WouldBlock, - .ALREADY => return error.FastOpenAlreadyInProgress, - .BADF => unreachable, // always a race condition - .CONNREFUSED => return error.ConnectionRefused, - .CONNRESET => return error.ConnectionResetByPeer, - .DESTADDRREQ => unreachable, // The socket is not connection-mode, and no peer address is set. - .FAULT => unreachable, // An invalid user space address was specified for an argument. - .INTR => continue, - .INVAL => return error.UnreachableAddress, - .ISCONN => unreachable, // connection-mode socket was connected already but a recipient was specified - .MSGSIZE => return error.MessageOversize, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket. - .OPNOTSUPP => unreachable, // Some bit in the flags argument is inappropriate for the socket type. - .PIPE => return error.BrokenPipe, - .AFNOSUPPORT => return error.AddressFamilyUnsupported, - .LOOP => return error.SymLinkLoop, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOTDIR => return error.NotDir, - .HOSTUNREACH => return error.NetworkUnreachable, - .NETUNREACH => return error.NetworkUnreachable, - .NOTCONN => return error.SocketUnconnected, - .NETDOWN => return error.NetworkDown, - else => |err| return unexpectedErrno(err), - } - } -} - -/// Transmit a message to another socket. -/// -/// The `send` call may be used only when the socket is in a connected state (so that the intended -/// recipient is known). The only difference between `send` and `write` is the presence of -/// flags. With a zero flags argument, `send` is equivalent to `write`. Also, the following -/// call -/// -/// send(sockfd, buf, len, flags); -/// -/// is equivalent to -/// -/// sendto(sockfd, buf, len, flags, NULL, 0); -/// -/// There is no indication of failure to deliver. -/// -/// When the message does not fit into the send buffer of the socket, `send` normally blocks, -/// unless the socket has been placed in nonblocking I/O mode. In nonblocking mode it would fail -/// with `SendError.WouldBlock`. The `select` call may be used to determine when it is -/// possible to send more data. -pub fn send( - /// The file descriptor of the sending socket. - sockfd: socket_t, - buf: []const u8, - flags: u32, -) SendError!usize { - return sendto(sockfd, buf, flags, null, 0) catch |err| switch (err) { - error.AddressFamilyUnsupported => unreachable, - error.SymLinkLoop => unreachable, - error.NameTooLong => unreachable, - error.FileNotFound => unreachable, - error.NotDir => unreachable, - error.NetworkUnreachable => unreachable, - error.AddressUnavailable => unreachable, - error.SocketUnconnected => unreachable, - error.UnreachableAddress => unreachable, - else => |e| return e, - }; -} - -pub const CopyFileRangeError = error{ - FileTooBig, - InputOutput, - /// `fd_in` is not open for reading; or `fd_out` is not open for writing; - /// or the `APPEND` flag is set for `fd_out`. - FilesOpenedWithWrongFlags, - IsDir, - OutOfMemory, - NoSpaceLeft, - Unseekable, - PermissionDenied, - SwapFile, - CorruptedData, -} || PReadError || PWriteError || UnexpectedError; - -/// Transfer data between file descriptors at specified offsets. -/// -/// Returns the number of bytes written, which can less than requested. -/// -/// The `copy_file_range` call copies `len` bytes from one file descriptor to another. When possible, -/// this is done within the operating system kernel, which can provide better performance -/// characteristics than transferring data from kernel to user space and back, such as with -/// `pread` and `pwrite` calls. -/// -/// `fd_in` must be a file descriptor opened for reading, and `fd_out` must be a file descriptor -/// opened for writing. They may be any kind of file descriptor; however, if `fd_in` is not a regular -/// file system file, it may cause this function to fall back to calling `pread` and `pwrite`, in which case -/// atomicity guarantees no longer apply. -/// -/// If `fd_in` and `fd_out` are the same, source and target ranges must not overlap. -/// The file descriptor seek positions are ignored and not updated. -/// When `off_in` is past the end of the input file, it successfully reads 0 bytes. -/// -/// `flags` has different meanings per operating system; refer to the respective man pages. -/// -/// These systems support in-kernel data copying: -/// * Linux (cross-filesystem from version 5.3) -/// * FreeBSD 13.0 -/// -/// Other systems fall back to calling `pread` / `pwrite`. -/// -/// Maximum offsets on Linux and FreeBSD are `maxInt(i64)`. -pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len: usize, flags: u32) CopyFileRangeError!usize { - if (builtin.os.tag == .freebsd or builtin.os.tag == .linux) { - const use_c = native_os != .linux or - std.c.versionCheck(if (builtin.abi.isAndroid()) .{ .major = 34, .minor = 0, .patch = 0 } else .{ .major = 2, .minor = 27, .patch = 0 }); - const sys = if (use_c) std.c else linux; - - var off_in_copy: i64 = @bitCast(off_in); - var off_out_copy: i64 = @bitCast(off_out); - - while (true) { - const rc = sys.copy_file_range(fd_in, &off_in_copy, fd_out, &off_out_copy, len, flags); - if (native_os == .freebsd) { - switch (sys.errno(rc)) { - .SUCCESS => return @intCast(rc), - .BADF => return error.FilesOpenedWithWrongFlags, - .FBIG => return error.FileTooBig, - .IO => return error.InputOutput, - .ISDIR => return error.IsDir, - .NOSPC => return error.NoSpaceLeft, - .INVAL => break, // these may not be regular files, try fallback - .INTEGRITY => return error.CorruptedData, - .INTR => continue, - else => |err| return unexpectedErrno(err), - } - } else { // assume linux - switch (sys.errno(rc)) { - .SUCCESS => return @intCast(rc), - .BADF => return error.FilesOpenedWithWrongFlags, - .FBIG => return error.FileTooBig, - .IO => return error.InputOutput, - .ISDIR => return error.IsDir, - .NOSPC => return error.NoSpaceLeft, - .INVAL => break, // these may not be regular files, try fallback - .NOMEM => return error.OutOfMemory, - .OVERFLOW => return error.Unseekable, - .PERM => return error.PermissionDenied, - .TXTBSY => return error.SwapFile, - .XDEV => break, // support for cross-filesystem copy added in Linux 5.3, use fallback - else => |err| return unexpectedErrno(err), - } - } - } - } - - var buf: [8 * 4096]u8 = undefined; - const amt_read = try pread(fd_in, buf[0..@min(buf.len, len)], off_in); - if (amt_read == 0) return 0; - return pwrite(fd_out, buf[0..amt_read], off_out); -} - pub const PollError = error{ /// The network subsystem has failed. NetworkDown, @@ -5753,139 +1608,6 @@ pub fn ppoll(fds: []pollfd, timeout: ?*const timespec, mask: ?*const sigset_t) P } } -pub const RecvFromError = error{ - /// The socket is marked nonblocking and the requested operation would block, and - /// there is no global event loop configured. - WouldBlock, - - /// A remote host refused to allow the network connection, typically because it is not - /// running the requested service. - ConnectionRefused, - - /// Could not allocate kernel memory. - SystemResources, - - ConnectionResetByPeer, - Timeout, - - /// The socket has not been bound. - SocketNotBound, - - /// The UDP message was too big for the buffer and part of it has been discarded - MessageOversize, - - /// The network subsystem has failed. - NetworkDown, - - /// The socket is not connected (connection-oriented sockets only). - SocketUnconnected, - - /// The other end closed the socket unexpectedly or a read is executed on a shut down socket - BrokenPipe, -} || UnexpectedError; - -pub fn recv(sock: socket_t, buf: []u8, flags: u32) RecvFromError!usize { - return recvfrom(sock, buf, flags, null, null); -} - -/// If `sockfd` is opened in non blocking mode, the function will -/// return error.WouldBlock when EAGAIN is received. -pub fn recvfrom( - sockfd: socket_t, - buf: []u8, - flags: u32, - src_addr: ?*sockaddr, - addrlen: ?*socklen_t, -) RecvFromError!usize { - while (true) { - const rc = system.recvfrom(sockfd, buf.ptr, buf.len, flags, src_addr, addrlen); - if (native_os == .windows) { - if (rc == windows.ws2_32.SOCKET_ERROR) { - switch (windows.ws2_32.WSAGetLastError()) { - .NOTINITIALISED => unreachable, - .ECONNRESET => return error.ConnectionResetByPeer, - .EINVAL => return error.SocketNotBound, - .EMSGSIZE => return error.MessageOversize, - .ENETDOWN => return error.NetworkDown, - .ENOTCONN => return error.SocketUnconnected, - .EWOULDBLOCK => return error.WouldBlock, - .ETIMEDOUT => return error.Timeout, - // TODO: handle more errors - else => |err| return windows.unexpectedWSAError(err), - } - } else { - return @intCast(rc); - } - } else { - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - .BADF => unreachable, // always a race condition - .FAULT => unreachable, - .INVAL => unreachable, - .NOTCONN => return error.SocketUnconnected, - .NOTSOCK => unreachable, - .INTR => continue, - .AGAIN => return error.WouldBlock, - .NOMEM => return error.SystemResources, - .CONNREFUSED => return error.ConnectionRefused, - .CONNRESET => return error.ConnectionResetByPeer, - .TIMEDOUT => return error.Timeout, - .PIPE => return error.BrokenPipe, - else => |err| return unexpectedErrno(err), - } - } - } -} - -pub const RecvMsgError = RecvFromError || error{ - /// Reception of SCM_RIGHTS fds via ancillary data in msg.control would - /// exceed some system limit (generally this is retryable by trying to - /// receive fewer fds or closing some existing fds) - SystemFdQuotaExceeded, - - /// Reception of SCM_RIGHTS fds via ancillary data in msg.control would - /// exceed some process limit (generally this is retryable by trying to - /// receive fewer fds, closing some existing fds, or changing the ulimit) - ProcessFdQuotaExceeded, -}; - -/// If `sockfd` is opened in non blocking mode, the function will -/// return error.WouldBlock when EAGAIN is received. -pub fn recvmsg( - /// The file descriptor of the sending socket. - sockfd: socket_t, - /// Message header and iovecs - msg: *msghdr, - flags: u32, -) RecvMsgError!usize { - if (@TypeOf(system.recvmsg) == void) - @compileError("recvmsg() not supported on this OS"); - while (true) { - const rc = system.recvmsg(sockfd, msg, flags); - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - .AGAIN => return error.WouldBlock, - .BADF => unreachable, // always a race condition - .NFILE => return error.SystemFdQuotaExceeded, - .MFILE => return error.ProcessFdQuotaExceeded, - .INTR => continue, - .FAULT => unreachable, // An invalid user space address was specified for an argument. - .INVAL => unreachable, // Invalid argument passed. - .ISCONN => unreachable, // connection-mode socket was connected already but a recipient was specified - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTCONN => return error.SocketUnconnected, - .NOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket. - .MSGSIZE => return error.MessageOversize, - .PIPE => return error.BrokenPipe, - .OPNOTSUPP => unreachable, // Some bit in the flags argument is inappropriate for the socket type. - .CONNRESET => return error.ConnectionResetByPeer, - .NETDOWN => return error.NetworkDown, - else => |err| return unexpectedErrno(err), - } - } -} - pub const SetSockOptError = error{ /// The socket is already connected, and a specified option cannot be set while the socket is connected. AlreadyConnected, @@ -5902,7 +1624,7 @@ pub const SetSockOptError = error{ /// Setting the socket option requires more elevated permissions. PermissionDenied, - OperationNotSupported, + OperationUnsupported, NetworkDown, FileDescriptorNotASocket, SocketNotBound, @@ -5938,7 +1660,7 @@ pub fn setsockopt(fd: socket_t, level: i32, optname: u32, opt: []const u8) SetSo .NOBUFS => return error.SystemResources, .PERM => return error.PermissionDenied, .NODEV => return error.NoDevice, - .OPNOTSUPP => return error.OperationNotSupported, + .OPNOTSUPP => return error.OperationUnsupported, else => |err| return unexpectedErrno(err), } } @@ -6077,20 +1799,6 @@ pub fn tcsetpgrp(handle: fd_t, pgrp: pid_t) TermioSetPgrpError!void { } } -pub const SetSidError = error{ - /// The calling process is already a process group leader, or the process group ID of a process other than the calling process matches the process ID of the calling process. - PermissionDenied, -} || UnexpectedError; - -pub fn setsid() SetSidError!pid_t { - const rc = system.setsid(); - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - .PERM => return error.PermissionDenied, - else => |err| return unexpectedErrno(err), - } -} - pub fn signalfd(fd: fd_t, mask: *const sigset_t, flags: u32) !fd_t { const rc = system.signalfd(fd, mask, flags); switch (errno(rc)) { @@ -6104,12 +1812,7 @@ pub fn signalfd(fd: fd_t, mask: *const sigset_t, flags: u32) !fd_t { } } -pub const SyncError = error{ - InputOutput, - NoSpaceLeft, - DiskQuota, - AccessDenied, -} || UnexpectedError; +pub const SyncError = std.Io.File.SyncError; /// Write all pending file contents and metadata modifications to all filesystems. pub fn sync() void { @@ -6129,38 +1832,8 @@ pub fn syncfs(fd: fd_t) SyncError!void { } } -/// Write all pending file contents and metadata modifications for the specified file descriptor to the underlying filesystem. -pub fn fsync(fd: fd_t) SyncError!void { - if (native_os == .windows) { - if (windows.kernel32.FlushFileBuffers(fd) != 0) - return; - switch (windows.GetLastError()) { - .SUCCESS => return, - .INVALID_HANDLE => unreachable, - .ACCESS_DENIED => return error.AccessDenied, // a sync was performed but the system couldn't update the access time - .UNEXP_NET_ERR => return error.InputOutput, - else => return error.InputOutput, - } - } - const rc = system.fsync(fd); - switch (errno(rc)) { - .SUCCESS => return, - .BADF, .INVAL, .ROFS => unreachable, - .IO => return error.InputOutput, - .NOSPC => return error.NoSpaceLeft, - .DQUOT => return error.DiskQuota, - else => |err| return unexpectedErrno(err), - } -} - /// Write all pending file contents for the specified file descriptor to the underlying filesystem, but not necessarily the metadata. pub fn fdatasync(fd: fd_t) SyncError!void { - if (native_os == .windows) { - return fsync(fd) catch |err| switch (err) { - SyncError.AccessDenied => return, // fdatasync doesn't promise that the access time was synced - else => return err, - }; - } const rc = system.fdatasync(fd); switch (errno(rc)) { .SUCCESS => return, @@ -6183,7 +1856,7 @@ pub const PrctlError = error{ /// or PR_MPX_DISABLE_MANAGEMENT UnsupportedFeature, /// Can only occur with PR_SET_FP_MODE - OperationNotSupported, + OperationUnsupported, PermissionDenied, } || UnexpectedError; @@ -6207,7 +1880,7 @@ pub fn prctl(option: PR, args: anytype) PrctlError!u31 { .FAULT => return error.InvalidAddress, .INVAL => unreachable, .NODEV, .NXIO => return error.UnsupportedFeature, - .OPNOTSUPP => return error.OperationNotSupported, + .OPNOTSUPP => return error.OperationUnsupported, .PERM, .BUSY => return error.PermissionDenied, .RANGE => unreachable, else => |err| return unexpectedErrno(err), @@ -6466,7 +2139,7 @@ pub const PtraceError = error{ DeviceBusy, InputOutput, NameTooLong, - OperationNotSupported, + OperationUnsupported, OutOfMemory, ProcessNotFound, PermissionDenied, @@ -6568,7 +2241,7 @@ pub fn ptrace(request: u32, pid: pid_t, addr: usize, data: usize) PtraceError!vo .INVAL => unreachable, .PERM => error.PermissionDenied, .BUSY => error.DeviceBusy, - .NOTSUP => error.OperationNotSupported, + .NOTSUP => error.OperationUnsupported, else => |err| return unexpectedErrno(err), }, @@ -6579,7 +2252,7 @@ pub fn ptrace(request: u32, pid: pid_t, addr: usize, data: usize) PtraceError!vo pub const NameToFileHandleAtError = error{ FileNotFound, NotDir, - OperationNotSupported, + OperationUnsupported, NameTooLong, Unexpected, }; @@ -6608,7 +2281,7 @@ pub fn name_to_handle_atZ( .INVAL => unreachable, // bad flags, or handle_bytes too big .NOENT => return error.FileNotFound, .NOTDIR => return error.NotDir, - .OPNOTSUPP => return error.OperationNotSupported, + .OPNOTSUPP => return error.OperationUnsupported, .OVERFLOW => return error.NameTooLong, else => |err| return unexpectedErrno(err), } @@ -6662,7 +2335,7 @@ pub fn unexpectedErrno(err: E) UnexpectedError { /// Used to convert a slice to a null terminated slice on the stack. pub fn toPosixPath(file_path: []const u8) error{NameTooLong}![PATH_MAX - 1:0]u8 { - if (std.debug.runtime_safety) assert(mem.indexOfScalar(u8, file_path, 0) == null); + if (std.debug.runtime_safety) assert(mem.findScalar(u8, file_path, 0) == null); var path_with_null: [PATH_MAX - 1:0]u8 = undefined; // >= rather than > to make room for the null byte if (file_path.len >= PATH_MAX) return error.NameTooLong; diff --git a/lib/std/posix/test.zig b/lib/std/posix/test.zig index aaaaa1d948a9..d2e34c0556da 100644 --- a/lib/std/posix/test.zig +++ b/lib/std/posix/test.zig @@ -1,40 +1,31 @@ +const builtin = @import("builtin"); +const native_os = builtin.target.os.tag; +const AtomicRmwOp = std.builtin.AtomicRmwOp; +const AtomicOrder = std.builtin.AtomicOrder; + const std = @import("../std.zig"); +const Io = std.Io; +const Dir = std.Io.Dir; const posix = std.posix; -const testing = std.testing; -const expect = testing.expect; -const expectEqual = testing.expectEqual; -const expectError = testing.expectError; -const fs = std.fs; const mem = std.mem; const elf = std.elf; const linux = std.os.linux; +const AT = std.posix.AT; -const a = std.testing.allocator; - -const builtin = @import("builtin"); -const AtomicRmwOp = std.builtin.AtomicRmwOp; -const AtomicOrder = std.builtin.AtomicOrder; -const native_os = builtin.target.os.tag; +const testing = std.testing; +const expect = std.testing.expect; +const expectEqual = std.testing.expectEqual; +const expectEqualSlices = std.testing.expectEqualSlices; +const expectEqualStrings = std.testing.expectEqualStrings; +const expectError = std.testing.expectError; const tmpDir = std.testing.tmpDir; -// NOTE: several additional tests are in test/standalone/posix/. Any tests that mutate -// process-wide POSIX state (cwd, signals, etc) cannot be Zig unit tests and should be over there. - -// https://github.com/ziglang/zig/issues/20288 -test "WTF-8 to WTF-16 conversion buffer overflows" { - if (native_os != .windows) return error.SkipZigTest; - - const input_wtf8 = "\u{10FFFF}" ** 16385; - try expectError(error.NameTooLong, posix.chdir(input_wtf8)); - try expectError(error.NameTooLong, posix.chdirZ(input_wtf8)); -} - test "check WASI CWD" { if (native_os == .wasi) { - if (std.options.wasiCwd() != 3) { + const cwd: Dir = .cwd(); + if (cwd.handle != 3) { @panic("WASI code that uses cwd (like this test) needs a preopen for cwd (add '--dir=.' to wasmtime)"); } - if (!builtin.link_libc) { // WASI without-libc hardcodes fd 3 as the FDCWD token so it can be passed directly to WASI calls try expectEqual(3, posix.AT.FDCWD); @@ -42,181 +33,16 @@ test "check WASI CWD" { } } -test "open smoke test" { - if (native_os == .wasi) return error.SkipZigTest; - if (native_os == .windows) return error.SkipZigTest; - - // TODO verify file attributes using `fstat` - - var tmp = tmpDir(.{}); - defer tmp.cleanup(); - - const base_path = try tmp.dir.realpathAlloc(a, "."); - defer a.free(base_path); - - const mode: posix.mode_t = if (native_os == .windows) 0 else 0o666; - - { - // Create some file using `open`. - const file_path = try fs.path.join(a, &.{ base_path, "some_file" }); - defer a.free(file_path); - const fd = try posix.open(file_path, .{ .ACCMODE = .RDWR, .CREAT = true, .EXCL = true }, mode); - posix.close(fd); - } - - { - // Try this again with the same flags. This op should fail with error.PathAlreadyExists. - const file_path = try fs.path.join(a, &.{ base_path, "some_file" }); - defer a.free(file_path); - try expectError(error.PathAlreadyExists, posix.open(file_path, .{ .ACCMODE = .RDWR, .CREAT = true, .EXCL = true }, mode)); - } - - { - // Try opening without `EXCL` flag. - const file_path = try fs.path.join(a, &.{ base_path, "some_file" }); - defer a.free(file_path); - const fd = try posix.open(file_path, .{ .ACCMODE = .RDWR, .CREAT = true }, mode); - posix.close(fd); - } - - { - // Try opening as a directory which should fail. - const file_path = try fs.path.join(a, &.{ base_path, "some_file" }); - defer a.free(file_path); - try expectError(error.NotDir, posix.open(file_path, .{ .ACCMODE = .RDWR, .DIRECTORY = true }, mode)); - } - - { - // Create some directory - const file_path = try fs.path.join(a, &.{ base_path, "some_dir" }); - defer a.free(file_path); - try posix.mkdir(file_path, mode); - } - - { - // Open dir using `open` - const file_path = try fs.path.join(a, &.{ base_path, "some_dir" }); - defer a.free(file_path); - const fd = try posix.open(file_path, .{ .ACCMODE = .RDONLY, .DIRECTORY = true }, mode); - posix.close(fd); - } - - { - // Try opening as file which should fail. - const file_path = try fs.path.join(a, &.{ base_path, "some_dir" }); - defer a.free(file_path); - try expectError(error.IsDir, posix.open(file_path, .{ .ACCMODE = .RDWR }, mode)); - } -} - -test "readlink on Windows" { - if (native_os != .windows) return error.SkipZigTest; - - try testReadlink("C:\\ProgramData", "C:\\Users\\All Users"); - try testReadlink("C:\\Users\\Default", "C:\\Users\\Default User"); - try testReadlink("C:\\Users", "C:\\Documents and Settings"); -} - -fn testReadlink(target_path: []const u8, symlink_path: []const u8) !void { - var buffer: [fs.max_path_bytes]u8 = undefined; - const given = try posix.readlink(symlink_path, buffer[0..]); - try expect(mem.eql(u8, target_path, given)); -} - -test "linkat with different directories" { - if ((builtin.cpu.arch == .riscv32 or builtin.cpu.arch.isLoongArch()) and builtin.os.tag == .linux and !builtin.link_libc) return error.SkipZigTest; // No `fstatat()`. - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; // `nstat.nlink` assertion is failing with LLVM 20+ for unclear reasons. - - switch (native_os) { - .wasi, .linux, .illumos => {}, - else => return error.SkipZigTest, - } - - var tmp = tmpDir(.{}); - defer tmp.cleanup(); - - const target_name = "link-target"; - const link_name = "newlink"; - - const subdir = try tmp.dir.makeOpenPath("subdir", .{}); - - defer tmp.dir.deleteFile(target_name) catch {}; - try tmp.dir.writeFile(.{ .sub_path = target_name, .data = "example" }); - - // Test 1: link from file in subdir back up to target in parent directory - try posix.linkat(tmp.dir.fd, target_name, subdir.fd, link_name, 0); - - const efd = try tmp.dir.openFile(target_name, .{}); - defer efd.close(); - - const nfd = try subdir.openFile(link_name, .{}); - defer nfd.close(); - - { - const estat = try posix.fstat(efd.handle); - const nstat = try posix.fstat(nfd.handle); - try testing.expectEqual(estat.ino, nstat.ino); - try testing.expectEqual(@as(@TypeOf(nstat.nlink), 2), nstat.nlink); - } - - // Test 2: remove link - try posix.unlinkat(subdir.fd, link_name, 0); - - { - const estat = try posix.fstat(efd.handle); - try testing.expectEqual(@as(@TypeOf(estat.nlink), 1), estat.nlink); - } -} - -test "readlinkat" { - var tmp = tmpDir(.{}); - defer tmp.cleanup(); - - // create file - try tmp.dir.writeFile(.{ .sub_path = "file.txt", .data = "nonsense" }); - - // create a symbolic link - if (native_os == .windows) { - std.os.windows.CreateSymbolicLink( - tmp.dir.fd, - &[_]u16{ 'l', 'i', 'n', 'k' }, - &[_:0]u16{ 'f', 'i', 'l', 'e', '.', 't', 'x', 't' }, - false, - ) catch |err| switch (err) { - // Symlink requires admin privileges on windows, so this test can legitimately fail. - error.AccessDenied => return error.SkipZigTest, - else => return err, - }; - } else { - try posix.symlinkat("file.txt", tmp.dir.fd, "link"); - } - - // read the link - var buffer: [fs.max_path_bytes]u8 = undefined; - const read_link = try posix.readlinkat(tmp.dir.fd, "link", buffer[0..]); - try expect(mem.eql(u8, "file.txt", read_link)); -} - -test "getrandom" { - var buf_a: [50]u8 = undefined; - var buf_b: [50]u8 = undefined; - try posix.getrandom(&buf_a); - try posix.getrandom(&buf_b); - // If this test fails the chance is significantly higher that there is a bug than - // that two sets of 50 bytes were equal. - try expect(!mem.eql(u8, &buf_a, &buf_b)); -} - test "getuid" { if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; - _ = posix.getuid(); - _ = posix.geteuid(); + _ = posix.system.getuid(); + _ = posix.system.geteuid(); } test "getgid" { if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; - _ = posix.getgid(); - _ = posix.getegid(); + _ = posix.system.getgid(); + _ = posix.system.getegid(); } test "sigaltstack" { @@ -227,7 +53,7 @@ test "sigaltstack" { // Setting a stack size less than MINSIGSTKSZ returns ENOMEM st.flags = 0; st.size = 1; - try testing.expectError(error.SizeTooSmall, posix.sigaltstack(&st, null)); + try expectError(error.SizeTooSmall, posix.sigaltstack(&st, null)); } // If the type is not available use void to avoid erroring out when `iter_fn` is @@ -295,21 +121,23 @@ test "pipe" { if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; - const fds = try posix.pipe(); - try expect((try posix.write(fds[1], "hello")) == 5); + const io = testing.io; + + const fds = try std.Io.Threaded.pipe2(.{}); + const out: Io.File = .{ .handle = fds[0] }; + const in: Io.File = .{ .handle = fds[1] }; + try in.writeStreamingAll(io, "hello"); var buf: [16]u8 = undefined; - try expect((try posix.read(fds[0], buf[0..])) == 5); - try testing.expectEqualSlices(u8, buf[0..5], "hello"); - posix.close(fds[1]); - posix.close(fds[0]); -} + try expect((try out.readStreaming(io, &.{&buf})) == 5); -test "argsAlloc" { - const args = try std.process.argsAlloc(std.testing.allocator); - std.process.argsFree(std.testing.allocator, args); + try expectEqualSlices(u8, buf[0..5], "hello"); + out.close(io); + in.close(io); } test "memfd_create" { + const io = testing.io; + // memfd_create is only supported by linux and freebsd. switch (native_os) { .linux => {}, @@ -320,21 +148,22 @@ test "memfd_create" { else => return error.SkipZigTest, } - const fd = try posix.memfd_create("test", 0); - defer posix.close(fd); - try expect((try posix.write(fd, "test")) == 4); - try posix.lseek_SET(fd, 0); + const file: Io.File = .{ .handle = try posix.memfd_create("test", 0) }; + defer file.close(io); + try file.writePositionalAll(io, "test", 0); var buf: [10]u8 = undefined; - const bytes_read = try posix.read(fd, &buf); + const bytes_read = try file.readPositionalAll(io, &buf, 0); try expect(bytes_read == 4); - try expect(mem.eql(u8, buf[0..4], "test")); + try expectEqualStrings("test", buf[0..4]); } test "mmap" { if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); @@ -350,14 +179,14 @@ test "mmap" { ); defer posix.munmap(data); - try testing.expectEqual(@as(usize, 1234), data.len); + try expectEqual(@as(usize, 1234), data.len); // By definition the data returned by mmap is zero-filled - try testing.expect(mem.eql(u8, data, &[_]u8{0x00} ** 1234)); + try expect(mem.eql(u8, data, &[_]u8{0x00} ** 1234)); // Make sure the memory is writeable as requested @memset(data, 0x55); - try testing.expect(mem.eql(u8, data, &[_]u8{0x55} ** 1234)); + try expect(mem.eql(u8, data, &[_]u8{0x55} ** 1234)); } const test_out_file = "os_tmp_test"; @@ -366,10 +195,10 @@ test "mmap" { // Create a file used for testing mmap() calls with a file descriptor { - const file = try tmp.dir.createFile(test_out_file, .{}); - defer file.close(); + const file = try tmp.dir.createFile(io, test_out_file, .{}); + defer file.close(io); - var stream = file.writer(&.{}); + var stream = file.writer(io, &.{}); var i: usize = 0; while (i < alloc_size / @sizeOf(u32)) : (i += 1) { @@ -379,8 +208,8 @@ test "mmap" { // Map the whole file { - const file = try tmp.dir.openFile(test_out_file, .{}); - defer file.close(); + const file = try tmp.dir.openFile(io, test_out_file, .{}); + defer file.close(io); const data = try posix.mmap( null, @@ -396,7 +225,7 @@ test "mmap" { var i: usize = 0; while (i < alloc_size / @sizeOf(u32)) : (i += 1) { - try testing.expectEqual(i, try stream.takeInt(u32, .little)); + try expectEqual(i, try stream.takeInt(u32, .little)); } } @@ -404,8 +233,8 @@ test "mmap" { // Map the upper half of the file { - const file = try tmp.dir.openFile(test_out_file, .{}); - defer file.close(); + const file = try tmp.dir.openFile(io, test_out_file, .{}); + defer file.close(io); const data = try posix.mmap( null, @@ -421,7 +250,7 @@ test "mmap" { var i: usize = alloc_size / 2 / @sizeOf(u32); while (i < alloc_size / @sizeOf(u32)) : (i += 1) { - try testing.expectEqual(i, try stream.takeInt(u32, .little)); + try expectEqual(i, try stream.takeInt(u32, .little)); } } } @@ -430,13 +259,15 @@ test "fcntl" { if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); const test_out_file = "os_tmp_test"; - const file = try tmp.dir.createFile(test_out_file, .{}); - defer file.close(); + const file = try tmp.dir.createFile(io, test_out_file, .{}); + defer file.close(io); // Note: The test assumes createFile opens the file with CLOEXEC { @@ -476,18 +307,20 @@ test "sync" { test "fsync" { switch (native_os) { - .linux, .windows, .illumos => {}, + .linux, .illumos => {}, else => return error.SkipZigTest, } + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); const test_out_file = "os_tmp_test"; - const file = try tmp.dir.createFile(test_out_file, .{}); - defer file.close(); + const file = try tmp.dir.createFile(io, test_out_file, .{}); + defer file.close(io); - try posix.fsync(file.handle); + try file.sync(io); try posix.fdatasync(file.handle); } @@ -521,13 +354,14 @@ test "getrlimit and setrlimit" { } test "sigrtmin/max" { - if (native_os == .wasi or native_os == .windows or native_os.isDarwin()) { - return error.SkipZigTest; - } + if (native_os.isDarwin() or switch (native_os) { + .wasi, .windows, .openbsd, .dragonfly => true, + else => false, + }) return error.SkipZigTest; - try std.testing.expect(posix.sigrtmin() >= 32); - try std.testing.expect(posix.sigrtmin() >= posix.system.sigrtmin()); - try std.testing.expect(posix.sigrtmin() < posix.system.sigrtmax()); + try expect(posix.sigrtmin() >= 32); + try expect(posix.sigrtmin() >= posix.system.sigrtmin()); + try expect(posix.sigrtmin() < posix.system.sigrtmax()); } test "sigset empty/full" { @@ -536,7 +370,7 @@ test "sigset empty/full" { var set: posix.sigset_t = posix.sigemptyset(); for (1..posix.NSIG) |i| { - const sig = std.meta.intToEnum(posix.SIG, i) catch continue; + const sig = std.enums.fromInt(posix.SIG, i) orelse continue; try expectEqual(false, posix.sigismember(&set, sig)); } @@ -553,7 +387,9 @@ fn reserved_signo(i: usize) bool { if (native_os.isDarwin()) return false; if (!builtin.link_libc) return false; const max = if (native_os == .netbsd) 32 else 31; - return i > max and i < posix.sigrtmin(); + if (i > max) return true; + if (native_os == .openbsd or native_os == .dragonfly) return false; // no RT signals + return i < posix.sigrtmin(); } test "sigset add/del" { @@ -565,67 +401,38 @@ test "sigset add/del" { // See that none are set, then set each one, see that they're all set, then // remove them all, and then see that none are set. for (1..posix.NSIG) |i| { - const sig = std.meta.intToEnum(posix.SIG, i) catch continue; + const sig = std.enums.fromInt(posix.SIG, i) orelse continue; try expectEqual(false, posix.sigismember(&sigset, sig)); } for (1..posix.NSIG) |i| { if (!reserved_signo(i)) { - const sig = std.meta.intToEnum(posix.SIG, i) catch continue; + const sig = std.enums.fromInt(posix.SIG, i) orelse continue; posix.sigaddset(&sigset, sig); } } for (1..posix.NSIG) |i| { if (!reserved_signo(i)) { - const sig = std.meta.intToEnum(posix.SIG, i) catch continue; + const sig = std.enums.fromInt(posix.SIG, i) orelse continue; try expectEqual(true, posix.sigismember(&sigset, sig)); } } for (1..posix.NSIG) |i| { if (!reserved_signo(i)) { - const sig = std.meta.intToEnum(posix.SIG, i) catch continue; + const sig = std.enums.fromInt(posix.SIG, i) orelse continue; posix.sigdelset(&sigset, sig); } } for (1..posix.NSIG) |i| { - const sig = std.meta.intToEnum(posix.SIG, i) catch continue; + const sig = std.enums.fromInt(posix.SIG, i) orelse continue; try expectEqual(false, posix.sigismember(&sigset, sig)); } } -test "dup & dup2" { - switch (native_os) { - .linux, .illumos => {}, - else => return error.SkipZigTest, - } - - var tmp = tmpDir(.{}); - defer tmp.cleanup(); - - { - var file = try tmp.dir.createFile("os_dup_test", .{}); - defer file.close(); - - var duped = std.fs.File{ .handle = try posix.dup(file.handle) }; - defer duped.close(); - try duped.writeAll("dup"); - - // Tests aren't run in parallel so using the next fd shouldn't be an issue. - const new_fd = duped.handle + 1; - try posix.dup2(file.handle, new_fd); - var dup2ed = std.fs.File{ .handle = new_fd }; - defer dup2ed.close(); - try dup2ed.writeAll("dup2"); - } - - var buffer: [8]u8 = undefined; - try testing.expectEqualStrings("dupdup2", try tmp.dir.readFile("os_dup_test", &buffer)); -} - test "getpid" { if (native_os == .wasi) return error.SkipZigTest; if (native_os == .windows) return error.SkipZigTest; - try expect(posix.getpid() != 0); + try expect(posix.system.getpid() != 0); } test "getppid" { @@ -636,203 +443,79 @@ test "getppid" { try expect(posix.getppid() >= 0); } -test "writev longer than IOV_MAX" { - if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; - - var tmp = tmpDir(.{}); - defer tmp.cleanup(); - - var file = try tmp.dir.createFile("pwritev", .{}); - defer file.close(); - - const iovecs = [_]posix.iovec_const{.{ .base = "a", .len = 1 }} ** (posix.IOV_MAX + 1); - const amt = try file.writev(&iovecs); - try testing.expectEqual(@as(usize, posix.IOV_MAX), amt); -} - -test "POSIX file locking with fcntl" { - if (native_os == .windows or native_os == .wasi) { - // Not POSIX. - return error.SkipZigTest; - } - - if (true) { - // https://github.com/ziglang/zig/issues/11074 - return error.SkipZigTest; - } - - var tmp = tmpDir(.{}); - defer tmp.cleanup(); - - // Create a temporary lock file - var file = try tmp.dir.createFile("lock", .{ .read = true }); - defer file.close(); - try file.setEndPos(2); - const fd = file.handle; - - // Place an exclusive lock on the first byte, and a shared lock on the second byte: - var struct_flock = std.mem.zeroInit(posix.Flock, .{ .type = posix.F.WRLCK }); - _ = try posix.fcntl(fd, posix.F.SETLK, @intFromPtr(&struct_flock)); - struct_flock.start = 1; - struct_flock.type = posix.F.RDLCK; - _ = try posix.fcntl(fd, posix.F.SETLK, @intFromPtr(&struct_flock)); - - // Check the locks in a child process: - const pid = try posix.fork(); - if (pid == 0) { - // child expects be denied the exclusive lock: - struct_flock.start = 0; - struct_flock.type = posix.F.WRLCK; - try expectError(error.Locked, posix.fcntl(fd, posix.F.SETLK, @intFromPtr(&struct_flock))); - // child expects to get the shared lock: - struct_flock.start = 1; - struct_flock.type = posix.F.RDLCK; - _ = try posix.fcntl(fd, posix.F.SETLK, @intFromPtr(&struct_flock)); - // child waits for the exclusive lock in order to test deadlock: - struct_flock.start = 0; - struct_flock.type = posix.F.WRLCK; - _ = try posix.fcntl(fd, posix.F.SETLKW, @intFromPtr(&struct_flock)); - // child exits without continuing: - posix.exit(0); - } else { - // parent waits for child to get shared lock: - std.Thread.sleep(1 * std.time.ns_per_ms); - // parent expects deadlock when attempting to upgrade the shared lock to exclusive: - struct_flock.start = 1; - struct_flock.type = posix.F.WRLCK; - try expectError(error.DeadLock, posix.fcntl(fd, posix.F.SETLKW, @intFromPtr(&struct_flock))); - // parent releases exclusive lock: - struct_flock.start = 0; - struct_flock.type = posix.F.UNLCK; - _ = try posix.fcntl(fd, posix.F.SETLK, @intFromPtr(&struct_flock)); - // parent releases shared lock: - struct_flock.start = 1; - struct_flock.type = posix.F.UNLCK; - _ = try posix.fcntl(fd, posix.F.SETLK, @intFromPtr(&struct_flock)); - // parent waits for child: - const result = posix.waitpid(pid, 0); - try expect(result.status == 0 * 256); - } -} - test "rename smoke test" { if (native_os == .wasi) return error.SkipZigTest; if (native_os == .windows) return error.SkipZigTest; + if (native_os == .openbsd) return error.SkipZigTest; + + const io = testing.io; + const gpa = testing.allocator; var tmp = tmpDir(.{}); defer tmp.cleanup(); - const base_path = try tmp.dir.realpathAlloc(a, "."); - defer a.free(base_path); + const base_path = try tmp.dir.realPathFileAlloc(io, ".", gpa); + defer gpa.free(base_path); const mode: posix.mode_t = if (native_os == .windows) 0 else 0o666; { // Create some file using `open`. - const file_path = try fs.path.join(a, &.{ base_path, "some_file" }); - defer a.free(file_path); - const fd = try posix.open(file_path, .{ .ACCMODE = .RDWR, .CREAT = true, .EXCL = true }, mode); - posix.close(fd); + const file_path = try Dir.path.join(gpa, &.{ base_path, "some_file" }); + defer gpa.free(file_path); + const file = try Io.Dir.cwd().createFile(io, file_path, .{ + .read = true, + .exclusive = true, + .permissions = .fromMode(mode), + }); + file.close(io); // Rename the file - const new_file_path = try fs.path.join(a, &.{ base_path, "some_other_file" }); - defer a.free(new_file_path); - try posix.rename(file_path, new_file_path); + const new_file_path = try Dir.path.join(gpa, &.{ base_path, "some_other_file" }); + defer gpa.free(new_file_path); + try Io.Dir.renameAbsolute(file_path, new_file_path, io); } { // Try opening renamed file - const file_path = try fs.path.join(a, &.{ base_path, "some_other_file" }); - defer a.free(file_path); - const fd = try posix.open(file_path, .{ .ACCMODE = .RDWR }, mode); - posix.close(fd); + const file_path = try Dir.path.join(gpa, &.{ base_path, "some_other_file" }); + defer gpa.free(file_path); + const file = try Io.Dir.cwd().openFile(io, file_path, .{ .mode = .read_write }); + file.close(io); } { // Try opening original file - should fail with error.FileNotFound - const file_path = try fs.path.join(a, &.{ base_path, "some_file" }); - defer a.free(file_path); - try expectError(error.FileNotFound, posix.open(file_path, .{ .ACCMODE = .RDWR }, mode)); + const file_path = try Dir.path.join(gpa, &.{ base_path, "some_file" }); + defer gpa.free(file_path); + try expectError(error.FileNotFound, Io.Dir.cwd().openFile(io, file_path, .{ .mode = .read_write })); } { // Create some directory - const file_path = try fs.path.join(a, &.{ base_path, "some_dir" }); - defer a.free(file_path); - try posix.mkdir(file_path, mode); + const file_path = try Dir.path.join(gpa, &.{ base_path, "some_dir" }); + defer gpa.free(file_path); + try Io.Dir.createDirAbsolute(io, file_path, .fromMode(mode)); // Rename the directory - const new_file_path = try fs.path.join(a, &.{ base_path, "some_other_dir" }); - defer a.free(new_file_path); - try posix.rename(file_path, new_file_path); + const new_file_path = try Dir.path.join(gpa, &.{ base_path, "some_other_dir" }); + defer gpa.free(new_file_path); + try Io.Dir.renameAbsolute(file_path, new_file_path, io); } { // Try opening renamed directory - const file_path = try fs.path.join(a, &.{ base_path, "some_other_dir" }); - defer a.free(file_path); - const fd = try posix.open(file_path, .{ .ACCMODE = .RDONLY, .DIRECTORY = true }, mode); - posix.close(fd); + const file_path = try Dir.path.join(gpa, &.{ base_path, "some_other_dir" }); + defer gpa.free(file_path); + const dir = try Io.Dir.cwd().openDir(io, file_path, .{}); + dir.close(io); } { // Try opening original directory - should fail with error.FileNotFound - const file_path = try fs.path.join(a, &.{ base_path, "some_dir" }); - defer a.free(file_path); - try expectError(error.FileNotFound, posix.open(file_path, .{ .ACCMODE = .RDONLY, .DIRECTORY = true }, mode)); - } -} - -test "access smoke test" { - if (native_os == .wasi) return error.SkipZigTest; - if (native_os == .windows) return error.SkipZigTest; - - var tmp = tmpDir(.{}); - defer tmp.cleanup(); - - const base_path = try tmp.dir.realpathAlloc(a, "."); - defer a.free(base_path); - - const mode: posix.mode_t = if (native_os == .windows) 0 else 0o666; - { - // Create some file using `open`. - const file_path = try fs.path.join(a, &.{ base_path, "some_file" }); - defer a.free(file_path); - const fd = try posix.open(file_path, .{ .ACCMODE = .RDWR, .CREAT = true, .EXCL = true }, mode); - posix.close(fd); - } - - { - // Try to access() the file - const file_path = try fs.path.join(a, &.{ base_path, "some_file" }); - defer a.free(file_path); - if (native_os == .windows) { - try posix.access(file_path, posix.F_OK); - } else { - try posix.access(file_path, posix.F_OK | posix.W_OK | posix.R_OK); - } - } - - { - // Try to access() a non-existent file - should fail with error.FileNotFound - const file_path = try fs.path.join(a, &.{ base_path, "some_other_file" }); - defer a.free(file_path); - try expectError(error.FileNotFound, posix.access(file_path, posix.F_OK)); - } - - { - // Create some directory - const file_path = try fs.path.join(a, &.{ base_path, "some_dir" }); - defer a.free(file_path); - try posix.mkdir(file_path, mode); - } - - { - // Try to access() the directory - const file_path = try fs.path.join(a, &.{ base_path, "some_dir" }); - defer a.free(file_path); - - try posix.access(file_path, posix.F_OK); + const file_path = try Dir.path.join(gpa, &.{ base_path, "some_dir" }); + defer gpa.free(file_path); + try expectError(error.FileNotFound, Io.Dir.cwd().openDir(io, file_path, .{})); } } @@ -853,130 +536,3 @@ test "timerfd" { const expect_disarmed_timer: linux.itimerspec = .{ .it_interval = .{ .sec = 0, .nsec = 0 }, .it_value = .{ .sec = 0, .nsec = 0 } }; try expectEqual(expect_disarmed_timer, git); } - -test "isatty" { - var tmp = tmpDir(.{}); - defer tmp.cleanup(); - - var file = try tmp.dir.createFile("foo", .{}); - defer file.close(); - - try expectEqual(posix.isatty(file.handle), false); -} - -test "pread with empty buffer" { - var tmp = tmpDir(.{}); - defer tmp.cleanup(); - - var file = try tmp.dir.createFile("pread_empty", .{ .read = true }); - defer file.close(); - - const bytes = try a.alloc(u8, 0); - defer a.free(bytes); - - const rc = try posix.pread(file.handle, bytes, 0); - try expectEqual(rc, 0); -} - -test "write with empty buffer" { - var tmp = tmpDir(.{}); - defer tmp.cleanup(); - - var file = try tmp.dir.createFile("write_empty", .{}); - defer file.close(); - - const bytes = try a.alloc(u8, 0); - defer a.free(bytes); - - const rc = try posix.write(file.handle, bytes); - try expectEqual(rc, 0); -} - -test "pwrite with empty buffer" { - var tmp = tmpDir(.{}); - defer tmp.cleanup(); - - var file = try tmp.dir.createFile("pwrite_empty", .{}); - defer file.close(); - - const bytes = try a.alloc(u8, 0); - defer a.free(bytes); - - const rc = try posix.pwrite(file.handle, bytes, 0); - try expectEqual(rc, 0); -} - -fn expectMode(dir: posix.fd_t, file: []const u8, mode: posix.mode_t) !void { - const st = try posix.fstatat(dir, file, posix.AT.SYMLINK_NOFOLLOW); - try expectEqual(mode, st.mode & 0b111_111_111); -} - -test "fchmodat smoke test" { - if (builtin.cpu.arch.isMIPS64() and (builtin.abi == .gnuabin32 or builtin.abi == .muslabin32)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/23808 - - if (!std.fs.has_executable_bit) return error.SkipZigTest; - - var tmp = tmpDir(.{}); - defer tmp.cleanup(); - - try expectError(error.FileNotFound, posix.fchmodat(tmp.dir.fd, "regfile", 0o666, 0)); - const fd = try posix.openat( - tmp.dir.fd, - "regfile", - .{ .ACCMODE = .WRONLY, .CREAT = true, .EXCL = true, .TRUNC = true }, - 0o644, - ); - posix.close(fd); - - if ((builtin.cpu.arch == .riscv32 or builtin.cpu.arch.isLoongArch()) and builtin.os.tag == .linux and !builtin.link_libc) return error.SkipZigTest; // No `fstatat()`. - - try posix.symlinkat("regfile", tmp.dir.fd, "symlink"); - const sym_mode = blk: { - const st = try posix.fstatat(tmp.dir.fd, "symlink", posix.AT.SYMLINK_NOFOLLOW); - break :blk st.mode & 0b111_111_111; - }; - - try posix.fchmodat(tmp.dir.fd, "regfile", 0o640, 0); - try expectMode(tmp.dir.fd, "regfile", 0o640); - try posix.fchmodat(tmp.dir.fd, "regfile", 0o600, posix.AT.SYMLINK_NOFOLLOW); - try expectMode(tmp.dir.fd, "regfile", 0o600); - - try posix.fchmodat(tmp.dir.fd, "symlink", 0o640, 0); - try expectMode(tmp.dir.fd, "regfile", 0o640); - try expectMode(tmp.dir.fd, "symlink", sym_mode); - - var test_link = true; - posix.fchmodat(tmp.dir.fd, "symlink", 0o600, posix.AT.SYMLINK_NOFOLLOW) catch |err| switch (err) { - error.OperationNotSupported => test_link = false, - else => |e| return e, - }; - if (test_link) - try expectMode(tmp.dir.fd, "symlink", 0o600); - try expectMode(tmp.dir.fd, "regfile", 0o640); -} - -const CommonOpenFlags = packed struct { - ACCMODE: posix.ACCMODE = .RDONLY, - CREAT: bool = false, - EXCL: bool = false, - LARGEFILE: bool = false, - DIRECTORY: bool = false, - CLOEXEC: bool = false, - NONBLOCK: bool = false, - - pub fn lower(cof: CommonOpenFlags) posix.O { - var result: posix.O = if (native_os == .wasi) .{ - .read = cof.ACCMODE != .WRONLY, - .write = cof.ACCMODE != .RDONLY, - } else .{ - .ACCMODE = cof.ACCMODE, - }; - result.CREAT = cof.CREAT; - result.EXCL = cof.EXCL; - result.DIRECTORY = cof.DIRECTORY; - result.NONBLOCK = cof.NONBLOCK; - if (@hasField(posix.O, "CLOEXEC")) result.CLOEXEC = cof.CLOEXEC; - if (@hasField(posix.O, "LARGEFILE")) result.LARGEFILE = cof.LARGEFILE; - return result; - } -}; diff --git a/lib/std/priority_queue.zig b/lib/std/priority_queue.zig index c7b315afef73..3eae43f3c6fa 100644 --- a/lib/std/priority_queue.zig +++ b/lib/std/priority_queue.zig @@ -619,7 +619,7 @@ test "siftUp in remove" { try queue.addSlice(&.{ 0, 1, 100, 2, 3, 101, 102, 4, 5, 6, 7, 103, 104, 105, 106, 8 }); - _ = queue.removeIndex(std.mem.indexOfScalar(u32, queue.items[0..queue.count()], 102).?); + _ = queue.removeIndex(std.mem.findScalar(u32, queue.items[0..queue.count()], 102).?); const sorted_items = [_]u32{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 100, 101, 103, 104, 105, 106 }; for (sorted_items) |e| { diff --git a/lib/std/process.zig b/lib/std/process.zig index a638eb649660..0936116bf02b 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -1,21 +1,67 @@ -const std = @import("std.zig"); const builtin = @import("builtin"); +const native_os = builtin.os.tag; + +const std = @import("std.zig"); +const Io = std.Io; +const File = std.Io.File; const fs = std.fs; const mem = std.mem; const math = std.math; -const Allocator = mem.Allocator; +const Allocator = std.mem.Allocator; const assert = std.debug.assert; const testing = std.testing; -const native_os = builtin.os.tag; const posix = std.posix; const windows = std.os.windows; const unicode = std.unicode; +const max_path_bytes = std.fs.max_path_bytes; pub const Child = @import("process/Child.zig"); -pub const abort = posix.abort; -pub const exit = posix.exit; -pub const changeCurDir = posix.chdir; -pub const changeCurDirZ = posix.chdirZ; +pub const Args = @import("process/Args.zig"); +pub const Environ = @import("process/Environ.zig"); +pub const Preopens = @import("process/Preopens.zig"); + +/// This is the global, process-wide protection to coordinate stderr writes. +/// +/// The primary motivation for recursive mutex here is so that a panic while +/// stderr mutex is held still dumps the stack trace and other debug +/// information. +pub var stderr_thread_mutex: std.Thread.Mutex.Recursive = .init; + +/// A standard set of pre-initialized useful APIs for programs to take +/// advantage of. This is the type of the first parameter of the main function. +/// Applications wanting more flexibility can accept `Init.Minimal` instead. +/// +/// Completion of https://github.com/ziglang/zig/issues/24510 will also allow +/// the second parameter of the main function to be a custom struct that +/// contain auto-parsed CLI arguments. +pub const Init = struct { + /// `Init` is a superset of `Minimal`; the latter is included here. + minimal: Minimal, + /// Permanent storage for the entire process, cleaned automatically on + /// exit. Not threadsafe. + arena: *std.heap.ArenaAllocator, + /// A default-selected general purpose allocator for temporary heap + /// allocations. Debug mode will set up leak checking if possible. + /// Threadsafe. + gpa: Allocator, + /// An appropriate default Io implementation based on the target + /// configuration. Debug mode will set up leak checking if possible. + io: Io, + /// Environment variables, initialized with `gpa`. Not threadsafe. + environ_map: *Environ.Map, + /// Named files that have been provided by the parent process. This is + /// mainly useful on WASI, but can be used on other systems to mimic the + /// behavior with respect to stdio. + preopens: Preopens, + + /// Alternative to `Init` as the first parameter of the main function. + pub const Minimal = struct { + /// Environment variables. + environ: Environ, + /// Command line arguments. + args: Args, + }; +}; pub const GetCwdError = posix.GetCwdError; @@ -35,7 +81,7 @@ pub const GetCwdAllocError = Allocator.Error || error{CurrentWorkingDirectoryUnl pub fn getCwdAlloc(allocator: Allocator) GetCwdAllocError![]u8 { // The use of max_path_bytes here is just a heuristic: most paths will fit // in stack_buf, avoiding an extra allocation in the common case. - var stack_buf: [fs.max_path_bytes]u8 = undefined; + var stack_buf: [max_path_bytes]u8 = undefined; var heap_buf: ?[]u8 = null; defer if (heap_buf) |buf| allocator.free(buf); @@ -64,1481 +110,6 @@ test getCwdAlloc { testing.allocator.free(cwd); } -pub const EnvMap = struct { - hash_map: HashMap, - - const HashMap = std.HashMap( - []const u8, - []const u8, - EnvNameHashContext, - std.hash_map.default_max_load_percentage, - ); - - pub const Size = HashMap.Size; - - pub const EnvNameHashContext = struct { - fn upcase(c: u21) u21 { - if (c <= std.math.maxInt(u16)) - return windows.ntdll.RtlUpcaseUnicodeChar(@as(u16, @intCast(c))); - return c; - } - - pub fn hash(self: @This(), s: []const u8) u64 { - _ = self; - if (native_os == .windows) { - var h = std.hash.Wyhash.init(0); - var it = unicode.Wtf8View.initUnchecked(s).iterator(); - while (it.nextCodepoint()) |cp| { - const cp_upper = upcase(cp); - h.update(&[_]u8{ - @as(u8, @intCast((cp_upper >> 16) & 0xff)), - @as(u8, @intCast((cp_upper >> 8) & 0xff)), - @as(u8, @intCast((cp_upper >> 0) & 0xff)), - }); - } - return h.final(); - } - return std.hash_map.hashString(s); - } - - pub fn eql(self: @This(), a: []const u8, b: []const u8) bool { - _ = self; - if (native_os == .windows) { - var it_a = unicode.Wtf8View.initUnchecked(a).iterator(); - var it_b = unicode.Wtf8View.initUnchecked(b).iterator(); - while (true) { - const c_a = it_a.nextCodepoint() orelse break; - const c_b = it_b.nextCodepoint() orelse return false; - if (upcase(c_a) != upcase(c_b)) - return false; - } - return if (it_b.nextCodepoint()) |_| false else true; - } - return std.hash_map.eqlString(a, b); - } - }; - - /// Create a EnvMap backed by a specific allocator. - /// That allocator will be used for both backing allocations - /// and string deduplication. - pub fn init(allocator: Allocator) EnvMap { - return EnvMap{ .hash_map = HashMap.init(allocator) }; - } - - /// Free the backing storage of the map, as well as all - /// of the stored keys and values. - pub fn deinit(self: *EnvMap) void { - var it = self.hash_map.iterator(); - while (it.next()) |entry| { - self.free(entry.key_ptr.*); - self.free(entry.value_ptr.*); - } - - self.hash_map.deinit(); - } - - /// Same as `put` but the key and value become owned by the EnvMap rather - /// than being copied. - /// If `putMove` fails, the ownership of key and value does not transfer. - /// On Windows `key` must be a valid [WTF-8](https://wtf-8.codeberg.page/) string. - pub fn putMove(self: *EnvMap, key: []u8, value: []u8) !void { - assert(unicode.wtf8ValidateSlice(key)); - const get_or_put = try self.hash_map.getOrPut(key); - if (get_or_put.found_existing) { - self.free(get_or_put.key_ptr.*); - self.free(get_or_put.value_ptr.*); - get_or_put.key_ptr.* = key; - } - get_or_put.value_ptr.* = value; - } - - /// `key` and `value` are copied into the EnvMap. - /// On Windows `key` must be a valid [WTF-8](https://wtf-8.codeberg.page/) string. - pub fn put(self: *EnvMap, key: []const u8, value: []const u8) !void { - assert(unicode.wtf8ValidateSlice(key)); - const value_copy = try self.copy(value); - errdefer self.free(value_copy); - const get_or_put = try self.hash_map.getOrPut(key); - if (get_or_put.found_existing) { - self.free(get_or_put.value_ptr.*); - } else { - get_or_put.key_ptr.* = self.copy(key) catch |err| { - _ = self.hash_map.remove(key); - return err; - }; - } - get_or_put.value_ptr.* = value_copy; - } - - /// Find the address of the value associated with a key. - /// The returned pointer is invalidated if the map resizes. - /// On Windows `key` must be a valid [WTF-8](https://wtf-8.codeberg.page/) string. - pub fn getPtr(self: EnvMap, key: []const u8) ?*[]const u8 { - assert(unicode.wtf8ValidateSlice(key)); - return self.hash_map.getPtr(key); - } - - /// Return the map's copy of the value associated with - /// a key. The returned string is invalidated if this - /// key is removed from the map. - /// On Windows `key` must be a valid [WTF-8](https://wtf-8.codeberg.page/) string. - pub fn get(self: EnvMap, key: []const u8) ?[]const u8 { - assert(unicode.wtf8ValidateSlice(key)); - return self.hash_map.get(key); - } - - /// Removes the item from the map and frees its value. - /// This invalidates the value returned by get() for this key. - /// On Windows `key` must be a valid [WTF-8](https://wtf-8.codeberg.page/) string. - pub fn remove(self: *EnvMap, key: []const u8) void { - assert(unicode.wtf8ValidateSlice(key)); - const kv = self.hash_map.fetchRemove(key) orelse return; - self.free(kv.key); - self.free(kv.value); - } - - /// Returns the number of KV pairs stored in the map. - pub fn count(self: EnvMap) HashMap.Size { - return self.hash_map.count(); - } - - /// Returns an iterator over entries in the map. - pub fn iterator(self: *const EnvMap) HashMap.Iterator { - return self.hash_map.iterator(); - } - - /// Returns a full copy of `em` allocated with `gpa`, which is not necessarily - /// the same allocator used to allocate `em`. - pub fn clone(em: *const EnvMap, gpa: Allocator) Allocator.Error!EnvMap { - var new: EnvMap = .init(gpa); - errdefer new.deinit(); - // Since we need to dupe the keys and values, the only way for error handling to not be a - // nightmare is to add keys to an empty map one-by-one. This could be avoided if this - // abstraction were a bit less... OOP-esque. - try new.hash_map.ensureUnusedCapacity(em.hash_map.count()); - var it = em.hash_map.iterator(); - while (it.next()) |entry| { - try new.put(entry.key_ptr.*, entry.value_ptr.*); - } - return new; - } - - fn free(self: EnvMap, value: []const u8) void { - self.hash_map.allocator.free(value); - } - - fn copy(self: EnvMap, value: []const u8) ![]u8 { - return self.hash_map.allocator.dupe(u8, value); - } -}; - -test EnvMap { - var env = EnvMap.init(testing.allocator); - defer env.deinit(); - - try env.put("SOMETHING_NEW", "hello"); - try testing.expectEqualStrings("hello", env.get("SOMETHING_NEW").?); - try testing.expectEqual(@as(EnvMap.Size, 1), env.count()); - - // overwrite - try env.put("SOMETHING_NEW", "something"); - try testing.expectEqualStrings("something", env.get("SOMETHING_NEW").?); - try testing.expectEqual(@as(EnvMap.Size, 1), env.count()); - - // a new longer name to test the Windows-specific conversion buffer - try env.put("SOMETHING_NEW_AND_LONGER", "1"); - try testing.expectEqualStrings("1", env.get("SOMETHING_NEW_AND_LONGER").?); - try testing.expectEqual(@as(EnvMap.Size, 2), env.count()); - - // case insensitivity on Windows only - if (native_os == .windows) { - try testing.expectEqualStrings("1", env.get("something_New_aNd_LONGER").?); - } else { - try testing.expect(null == env.get("something_New_aNd_LONGER")); - } - - var it = env.iterator(); - var count: EnvMap.Size = 0; - while (it.next()) |entry| { - const is_an_expected_name = std.mem.eql(u8, "SOMETHING_NEW", entry.key_ptr.*) or std.mem.eql(u8, "SOMETHING_NEW_AND_LONGER", entry.key_ptr.*); - try testing.expect(is_an_expected_name); - count += 1; - } - try testing.expectEqual(@as(EnvMap.Size, 2), count); - - env.remove("SOMETHING_NEW"); - try testing.expect(env.get("SOMETHING_NEW") == null); - - try testing.expectEqual(@as(EnvMap.Size, 1), env.count()); - - if (native_os == .windows) { - // test Unicode case-insensitivity on Windows - try env.put("КИРиллИЦА", "something else"); - try testing.expectEqualStrings("something else", env.get("кириллица").?); - - // and WTF-8 that's not valid UTF-8 - const wtf8_with_surrogate_pair = try unicode.wtf16LeToWtf8Alloc(testing.allocator, &[_]u16{ - std.mem.nativeToLittle(u16, 0xD83D), // unpaired high surrogate - }); - defer testing.allocator.free(wtf8_with_surrogate_pair); - - try env.put(wtf8_with_surrogate_pair, wtf8_with_surrogate_pair); - try testing.expectEqualSlices(u8, wtf8_with_surrogate_pair, env.get(wtf8_with_surrogate_pair).?); - } -} - -pub const GetEnvMapError = error{ - OutOfMemory, - /// WASI-only. `environ_sizes_get` or `environ_get` - /// failed for an unexpected reason. - Unexpected, -}; - -/// Returns a snapshot of the environment variables of the current process. -/// Any modifications to the resulting EnvMap will not be reflected in the environment, and -/// likewise, any future modifications to the environment will not be reflected in the EnvMap. -/// Caller owns resulting `EnvMap` and should call its `deinit` fn when done. -pub fn getEnvMap(allocator: Allocator) GetEnvMapError!EnvMap { - var result = EnvMap.init(allocator); - errdefer result.deinit(); - - if (native_os == .windows) { - const ptr = windows.peb().ProcessParameters.Environment; - - var i: usize = 0; - while (ptr[i] != 0) { - const key_start = i; - - // There are some special environment variables that start with =, - // so we need a special case to not treat = as a key/value separator - // if it's the first character. - // https://devblogs.microsoft.com/oldnewthing/20100506-00/?p=14133 - if (ptr[key_start] == '=') i += 1; - - while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {} - const key_w = ptr[key_start..i]; - const key = try unicode.wtf16LeToWtf8Alloc(allocator, key_w); - errdefer allocator.free(key); - - if (ptr[i] == '=') i += 1; - - const value_start = i; - while (ptr[i] != 0) : (i += 1) {} - const value_w = ptr[value_start..i]; - const value = try unicode.wtf16LeToWtf8Alloc(allocator, value_w); - errdefer allocator.free(value); - - i += 1; // skip over null byte - - try result.putMove(key, value); - } - return result; - } else if (native_os == .wasi and !builtin.link_libc) { - var environ_count: usize = undefined; - var environ_buf_size: usize = undefined; - - const environ_sizes_get_ret = std.os.wasi.environ_sizes_get(&environ_count, &environ_buf_size); - if (environ_sizes_get_ret != .SUCCESS) { - return posix.unexpectedErrno(environ_sizes_get_ret); - } - - if (environ_count == 0) { - return result; - } - - const environ = try allocator.alloc([*:0]u8, environ_count); - defer allocator.free(environ); - const environ_buf = try allocator.alloc(u8, environ_buf_size); - defer allocator.free(environ_buf); - - const environ_get_ret = std.os.wasi.environ_get(environ.ptr, environ_buf.ptr); - if (environ_get_ret != .SUCCESS) { - return posix.unexpectedErrno(environ_get_ret); - } - - for (environ) |env| { - const pair = mem.sliceTo(env, 0); - var parts = mem.splitScalar(u8, pair, '='); - const key = parts.first(); - const value = parts.rest(); - try result.put(key, value); - } - return result; - } else if (builtin.link_libc) { - var ptr = std.c.environ; - while (ptr[0]) |line| : (ptr += 1) { - var line_i: usize = 0; - while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {} - const key = line[0..line_i]; - - var end_i: usize = line_i; - while (line[end_i] != 0) : (end_i += 1) {} - const value = line[line_i + 1 .. end_i]; - - try result.put(key, value); - } - return result; - } else { - for (std.os.environ) |line| { - var line_i: usize = 0; - while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {} - const key = line[0..line_i]; - - var end_i: usize = line_i; - while (line[end_i] != 0) : (end_i += 1) {} - const value = line[line_i + 1 .. end_i]; - - try result.put(key, value); - } - return result; - } -} - -test getEnvMap { - var env = try getEnvMap(testing.allocator); - defer env.deinit(); -} - -pub const GetEnvVarOwnedError = error{ - OutOfMemory, - EnvironmentVariableNotFound, - - /// On Windows, environment variable keys provided by the user must be valid WTF-8. - /// https://wtf-8.codeberg.page/ - InvalidWtf8, -}; - -/// Caller must free returned memory. -/// On Windows, if `key` is not valid [WTF-8](https://wtf-8.codeberg.page/), -/// then `error.InvalidWtf8` is returned. -/// On Windows, the value is encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On other platforms, the value is an opaque sequence of bytes with no particular encoding. -pub fn getEnvVarOwned(allocator: Allocator, key: []const u8) GetEnvVarOwnedError![]u8 { - if (native_os == .windows) { - const result_w = blk: { - var stack_alloc = std.heap.stackFallback(256 * @sizeOf(u16), allocator); - const stack_allocator = stack_alloc.get(); - const key_w = try unicode.wtf8ToWtf16LeAllocZ(stack_allocator, key); - defer stack_allocator.free(key_w); - - break :blk getenvW(key_w) orelse return error.EnvironmentVariableNotFound; - }; - // wtf16LeToWtf8Alloc can only fail with OutOfMemory - return unicode.wtf16LeToWtf8Alloc(allocator, result_w); - } else if (native_os == .wasi and !builtin.link_libc) { - var envmap = getEnvMap(allocator) catch return error.OutOfMemory; - defer envmap.deinit(); - const val = envmap.get(key) orelse return error.EnvironmentVariableNotFound; - return allocator.dupe(u8, val); - } else { - const result = posix.getenv(key) orelse return error.EnvironmentVariableNotFound; - return allocator.dupe(u8, result); - } -} - -/// On Windows, `key` must be valid WTF-8. -pub fn hasEnvVarConstant(comptime key: []const u8) bool { - if (native_os == .windows) { - const key_w = comptime unicode.wtf8ToWtf16LeStringLiteral(key); - return getenvW(key_w) != null; - } else if (native_os == .wasi and !builtin.link_libc) { - @compileError("hasEnvVarConstant is not supported for WASI without libc"); - } else { - return posix.getenv(key) != null; - } -} - -/// On Windows, `key` must be valid WTF-8. -pub fn hasNonEmptyEnvVarConstant(comptime key: []const u8) bool { - if (native_os == .windows) { - const key_w = comptime unicode.wtf8ToWtf16LeStringLiteral(key); - const value = getenvW(key_w) orelse return false; - return value.len != 0; - } else if (native_os == .wasi and !builtin.link_libc) { - @compileError("hasNonEmptyEnvVarConstant is not supported for WASI without libc"); - } else { - const value = posix.getenv(key) orelse return false; - return value.len != 0; - } -} - -pub const ParseEnvVarIntError = std.fmt.ParseIntError || error{EnvironmentVariableNotFound}; - -/// Parses an environment variable as an integer. -/// -/// Since the key is comptime-known, no allocation is needed. -/// -/// On Windows, `key` must be valid WTF-8. -pub fn parseEnvVarInt(comptime key: []const u8, comptime I: type, base: u8) ParseEnvVarIntError!I { - if (native_os == .windows) { - const key_w = comptime std.unicode.wtf8ToWtf16LeStringLiteral(key); - const text = getenvW(key_w) orelse return error.EnvironmentVariableNotFound; - return std.fmt.parseIntWithGenericCharacter(I, u16, text, base); - } else if (native_os == .wasi and !builtin.link_libc) { - @compileError("parseEnvVarInt is not supported for WASI without libc"); - } else { - const text = posix.getenv(key) orelse return error.EnvironmentVariableNotFound; - return std.fmt.parseInt(I, text, base); - } -} - -pub const HasEnvVarError = error{ - OutOfMemory, - - /// On Windows, environment variable keys provided by the user must be valid WTF-8. - /// https://wtf-8.codeberg.page/ - InvalidWtf8, -}; - -/// On Windows, if `key` is not valid [WTF-8](https://wtf-8.codeberg.page/), -/// then `error.InvalidWtf8` is returned. -pub fn hasEnvVar(allocator: Allocator, key: []const u8) HasEnvVarError!bool { - if (native_os == .windows) { - var stack_alloc = std.heap.stackFallback(256 * @sizeOf(u16), allocator); - const stack_allocator = stack_alloc.get(); - const key_w = try unicode.wtf8ToWtf16LeAllocZ(stack_allocator, key); - defer stack_allocator.free(key_w); - return getenvW(key_w) != null; - } else if (native_os == .wasi and !builtin.link_libc) { - var envmap = getEnvMap(allocator) catch return error.OutOfMemory; - defer envmap.deinit(); - return envmap.getPtr(key) != null; - } else { - return posix.getenv(key) != null; - } -} - -/// On Windows, if `key` is not valid [WTF-8](https://wtf-8.codeberg.page/), -/// then `error.InvalidWtf8` is returned. -pub fn hasNonEmptyEnvVar(allocator: Allocator, key: []const u8) HasEnvVarError!bool { - if (native_os == .windows) { - var stack_alloc = std.heap.stackFallback(256 * @sizeOf(u16), allocator); - const stack_allocator = stack_alloc.get(); - const key_w = try unicode.wtf8ToWtf16LeAllocZ(stack_allocator, key); - defer stack_allocator.free(key_w); - const value = getenvW(key_w) orelse return false; - return value.len != 0; - } else if (native_os == .wasi and !builtin.link_libc) { - var envmap = getEnvMap(allocator) catch return error.OutOfMemory; - defer envmap.deinit(); - const value = envmap.getPtr(key) orelse return false; - return value.len != 0; - } else { - const value = posix.getenv(key) orelse return false; - return value.len != 0; - } -} - -/// Windows-only. Get an environment variable with a null-terminated, WTF-16 encoded name. -/// The returned slice points to memory in the PEB. -/// -/// This function performs a Unicode-aware case-insensitive lookup using RtlEqualUnicodeString. -/// -/// See also: -/// * `std.posix.getenv` -/// * `getEnvMap` -/// * `getEnvVarOwned` -/// * `hasEnvVarConstant` -/// * `hasEnvVar` -pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 { - if (native_os != .windows) { - @compileError("Windows-only"); - } - const key_slice = mem.sliceTo(key, 0); - // '=' anywhere but the start makes this an invalid environment variable name - if (key_slice.len > 0 and std.mem.indexOfScalar(u16, key_slice[1..], '=') != null) { - return null; - } - const ptr = windows.peb().ProcessParameters.Environment; - var i: usize = 0; - while (ptr[i] != 0) { - const key_value = mem.sliceTo(ptr[i..], 0); - - // There are some special environment variables that start with =, - // so we need a special case to not treat = as a key/value separator - // if it's the first character. - // https://devblogs.microsoft.com/oldnewthing/20100506-00/?p=14133 - const equal_search_start: usize = if (key_value[0] == '=') 1 else 0; - const equal_index = std.mem.indexOfScalarPos(u16, key_value, equal_search_start, '=') orelse { - // This is enforced by CreateProcess. - // If violated, CreateProcess will fail with INVALID_PARAMETER. - unreachable; // must contain a = - }; - - const this_key = key_value[0..equal_index]; - if (windows.eqlIgnoreCaseWtf16(key_slice, this_key)) { - return key_value[equal_index + 1 ..]; - } - - // skip past the NUL terminator - i += key_value.len + 1; - } - return null; -} - -test getEnvVarOwned { - try testing.expectError( - error.EnvironmentVariableNotFound, - getEnvVarOwned(std.testing.allocator, "BADENV"), - ); -} - -test hasEnvVarConstant { - if (native_os == .wasi and !builtin.link_libc) return error.SkipZigTest; - - try testing.expect(!hasEnvVarConstant("BADENV")); -} - -test hasEnvVar { - const has_env = try hasEnvVar(std.testing.allocator, "BADENV"); - try testing.expect(!has_env); -} - -pub const ArgIteratorPosix = struct { - index: usize, - count: usize, - - pub const InitError = error{}; - - pub fn init() ArgIteratorPosix { - return ArgIteratorPosix{ - .index = 0, - .count = std.os.argv.len, - }; - } - - pub fn next(self: *ArgIteratorPosix) ?[:0]const u8 { - if (self.index == self.count) return null; - - const s = std.os.argv[self.index]; - self.index += 1; - return mem.sliceTo(s, 0); - } - - pub fn skip(self: *ArgIteratorPosix) bool { - if (self.index == self.count) return false; - - self.index += 1; - return true; - } -}; - -pub const ArgIteratorWasi = struct { - allocator: Allocator, - index: usize, - args: [][:0]u8, - - pub const InitError = error{OutOfMemory} || posix.UnexpectedError; - - /// You must call deinit to free the internal buffer of the - /// iterator after you are done. - pub fn init(allocator: Allocator) InitError!ArgIteratorWasi { - const fetched_args = try ArgIteratorWasi.internalInit(allocator); - return ArgIteratorWasi{ - .allocator = allocator, - .index = 0, - .args = fetched_args, - }; - } - - fn internalInit(allocator: Allocator) InitError![][:0]u8 { - var count: usize = undefined; - var buf_size: usize = undefined; - - switch (std.os.wasi.args_sizes_get(&count, &buf_size)) { - .SUCCESS => {}, - else => |err| return posix.unexpectedErrno(err), - } - - if (count == 0) { - return &[_][:0]u8{}; - } - - const argv = try allocator.alloc([*:0]u8, count); - defer allocator.free(argv); - - const argv_buf = try allocator.alloc(u8, buf_size); - - switch (std.os.wasi.args_get(argv.ptr, argv_buf.ptr)) { - .SUCCESS => {}, - else => |err| return posix.unexpectedErrno(err), - } - - var result_args = try allocator.alloc([:0]u8, count); - var i: usize = 0; - while (i < count) : (i += 1) { - result_args[i] = mem.sliceTo(argv[i], 0); - } - - return result_args; - } - - pub fn next(self: *ArgIteratorWasi) ?[:0]const u8 { - if (self.index == self.args.len) return null; - - const arg = self.args[self.index]; - self.index += 1; - return arg; - } - - pub fn skip(self: *ArgIteratorWasi) bool { - if (self.index == self.args.len) return false; - - self.index += 1; - return true; - } - - /// Call to free the internal buffer of the iterator. - pub fn deinit(self: *ArgIteratorWasi) void { - const last_item = self.args[self.args.len - 1]; - const last_byte_addr = @intFromPtr(last_item.ptr) + last_item.len + 1; // null terminated - const first_item_ptr = self.args[0].ptr; - const len = last_byte_addr - @intFromPtr(first_item_ptr); - self.allocator.free(first_item_ptr[0..len]); - self.allocator.free(self.args); - } -}; - -/// Iterator that implements the Windows command-line parsing algorithm. -/// The implementation is intended to be compatible with the post-2008 C runtime, -/// but is *not* intended to be compatible with `CommandLineToArgvW` since -/// `CommandLineToArgvW` uses the pre-2008 parsing rules. -/// -/// This iterator faithfully implements the parsing behavior observed from the C runtime with -/// one exception: if the command-line string is empty, the iterator will immediately complete -/// without returning any arguments (whereas the C runtime will return a single argument -/// representing the name of the current executable). -/// -/// The essential parts of the algorithm are described in Microsoft's documentation: -/// -/// - https://learn.microsoft.com/en-us/cpp/cpp/main-function-command-line-args?view=msvc-170#parsing-c-command-line-arguments -/// -/// David Deley explains some additional undocumented quirks in great detail: -/// -/// - https://daviddeley.com/autohotkey/parameters/parameters.htm#WINCRULES -pub const ArgIteratorWindows = struct { - allocator: Allocator, - /// Encoded as WTF-16 LE. - cmd_line: []const u16, - index: usize = 0, - /// Owned by the iterator. Long enough to hold contiguous NUL-terminated slices - /// of each argument encoded as WTF-8. - buffer: []u8, - start: usize = 0, - end: usize = 0, - - pub const InitError = error{OutOfMemory}; - - /// `cmd_line_w` *must* be a WTF16-LE-encoded string. - /// - /// The iterator stores and uses `cmd_line_w`, so its memory must be valid for - /// at least as long as the returned ArgIteratorWindows. - pub fn init(allocator: Allocator, cmd_line_w: []const u16) InitError!ArgIteratorWindows { - const wtf8_len = unicode.calcWtf8Len(cmd_line_w); - - // This buffer must be large enough to contain contiguous NUL-terminated slices - // of each argument. - // - During parsing, the length of a parsed argument will always be equal to - // to less than its unparsed length - // - The first argument needs one extra byte of space allocated for its NUL - // terminator, but for each subsequent argument the necessary whitespace - // between arguments guarantees room for their NUL terminator(s). - const buffer = try allocator.alloc(u8, wtf8_len + 1); - errdefer allocator.free(buffer); - - return .{ - .allocator = allocator, - .cmd_line = cmd_line_w, - .buffer = buffer, - }; - } - - /// Returns the next argument and advances the iterator. Returns `null` if at the end of the - /// command-line string. The iterator owns the returned slice. - /// The result is encoded as [WTF-8](https://wtf-8.codeberg.page/). - pub fn next(self: *ArgIteratorWindows) ?[:0]const u8 { - return self.nextWithStrategy(next_strategy); - } - - /// Skips the next argument and advances the iterator. Returns `true` if an argument was - /// skipped, `false` if at the end of the command-line string. - pub fn skip(self: *ArgIteratorWindows) bool { - return self.nextWithStrategy(skip_strategy); - } - - const next_strategy = struct { - const T = ?[:0]const u8; - - const eof = null; - - /// Returns '\' if any backslashes are emitted, otherwise returns `last_emitted_code_unit`. - fn emitBackslashes(self: *ArgIteratorWindows, count: usize, last_emitted_code_unit: ?u16) ?u16 { - for (0..count) |_| { - self.buffer[self.end] = '\\'; - self.end += 1; - } - return if (count != 0) '\\' else last_emitted_code_unit; - } - - /// If `last_emitted_code_unit` and `code_unit` form a surrogate pair, then - /// the previously emitted high surrogate is overwritten by the codepoint encoded - /// by the surrogate pair, and `null` is returned. - /// Otherwise, `code_unit` is emitted and returned. - fn emitCharacter(self: *ArgIteratorWindows, code_unit: u16, last_emitted_code_unit: ?u16) ?u16 { - // Because we are emitting WTF-8, we need to - // check to see if we've emitted two consecutive surrogate - // codepoints that form a valid surrogate pair in order - // to ensure that we're always emitting well-formed WTF-8 - // (https://wtf-8.codeberg.page/#concatenating). - // - // If we do have a valid surrogate pair, we need to emit - // the UTF-8 sequence for the codepoint that they encode - // instead of the WTF-8 encoding for the two surrogate pairs - // separately. - // - // This is relevant when dealing with a WTF-16 encoded - // command line like this: - // "<0xD801>"<0xDC37> - // which would get parsed and converted to WTF-8 as: - // <0xED><0xA0><0x81><0xED><0xB0><0xB7> - // but instead, we need to recognize the surrogate pair - // and emit the codepoint it encodes, which in this - // example is U+10437 (𐐷), which is encoded in UTF-8 as: - // <0xF0><0x90><0x90><0xB7> - if (last_emitted_code_unit != null and - std.unicode.utf16IsLowSurrogate(code_unit) and - std.unicode.utf16IsHighSurrogate(last_emitted_code_unit.?)) - { - const codepoint = std.unicode.utf16DecodeSurrogatePair(&.{ last_emitted_code_unit.?, code_unit }) catch unreachable; - - // Unpaired surrogate is 3 bytes long - const dest = self.buffer[self.end - 3 ..]; - const len = unicode.utf8Encode(codepoint, dest) catch unreachable; - // All codepoints that require a surrogate pair (> U+FFFF) are encoded as 4 bytes - assert(len == 4); - self.end += 1; - return null; - } - - const wtf8_len = std.unicode.wtf8Encode(code_unit, self.buffer[self.end..]) catch unreachable; - self.end += wtf8_len; - return code_unit; - } - - fn yieldArg(self: *ArgIteratorWindows) [:0]const u8 { - self.buffer[self.end] = 0; - const arg = self.buffer[self.start..self.end :0]; - self.end += 1; - self.start = self.end; - return arg; - } - }; - - const skip_strategy = struct { - const T = bool; - - const eof = false; - - fn emitBackslashes(_: *ArgIteratorWindows, _: usize, last_emitted_code_unit: ?u16) ?u16 { - return last_emitted_code_unit; - } - - fn emitCharacter(_: *ArgIteratorWindows, _: u16, last_emitted_code_unit: ?u16) ?u16 { - return last_emitted_code_unit; - } - - fn yieldArg(_: *ArgIteratorWindows) bool { - return true; - } - }; - - fn nextWithStrategy(self: *ArgIteratorWindows, comptime strategy: type) strategy.T { - var last_emitted_code_unit: ?u16 = null; - // The first argument (the executable name) uses different parsing rules. - if (self.index == 0) { - if (self.cmd_line.len == 0 or self.cmd_line[0] == 0) { - // Immediately complete the iterator. - // The C runtime would return the name of the current executable here. - return strategy.eof; - } - - var inside_quotes = false; - while (true) : (self.index += 1) { - const char = if (self.index != self.cmd_line.len) - mem.littleToNative(u16, self.cmd_line[self.index]) - else - 0; - switch (char) { - 0 => { - return strategy.yieldArg(self); - }, - '"' => { - inside_quotes = !inside_quotes; - }, - ' ', '\t' => { - if (inside_quotes) { - last_emitted_code_unit = strategy.emitCharacter(self, char, last_emitted_code_unit); - } else { - self.index += 1; - return strategy.yieldArg(self); - } - }, - else => { - last_emitted_code_unit = strategy.emitCharacter(self, char, last_emitted_code_unit); - }, - } - } - } - - // Skip spaces and tabs. The iterator completes if we reach the end of the string here. - while (true) : (self.index += 1) { - const char = if (self.index != self.cmd_line.len) - mem.littleToNative(u16, self.cmd_line[self.index]) - else - 0; - switch (char) { - 0 => return strategy.eof, - ' ', '\t' => continue, - else => break, - } - } - - // Parsing rules for subsequent arguments: - // - // - The end of the string always terminates the current argument. - // - When not in 'inside_quotes' mode, a space or tab terminates the current argument. - // - 2n backslashes followed by a quote emit n backslashes (note: n can be zero). - // If in 'inside_quotes' and the quote is immediately followed by a second quote, - // one quote is emitted and the other is skipped, otherwise, the quote is skipped - // and 'inside_quotes' is toggled. - // - 2n + 1 backslashes followed by a quote emit n backslashes followed by a quote. - // - n backslashes not followed by a quote emit n backslashes. - var backslash_count: usize = 0; - var inside_quotes = false; - while (true) : (self.index += 1) { - const char = if (self.index != self.cmd_line.len) - mem.littleToNative(u16, self.cmd_line[self.index]) - else - 0; - switch (char) { - 0 => { - last_emitted_code_unit = strategy.emitBackslashes(self, backslash_count, last_emitted_code_unit); - return strategy.yieldArg(self); - }, - ' ', '\t' => { - last_emitted_code_unit = strategy.emitBackslashes(self, backslash_count, last_emitted_code_unit); - backslash_count = 0; - if (inside_quotes) { - last_emitted_code_unit = strategy.emitCharacter(self, char, last_emitted_code_unit); - } else return strategy.yieldArg(self); - }, - '"' => { - const char_is_escaped_quote = backslash_count % 2 != 0; - last_emitted_code_unit = strategy.emitBackslashes(self, backslash_count / 2, last_emitted_code_unit); - backslash_count = 0; - if (char_is_escaped_quote) { - last_emitted_code_unit = strategy.emitCharacter(self, '"', last_emitted_code_unit); - } else { - if (inside_quotes and - self.index + 1 != self.cmd_line.len and - mem.littleToNative(u16, self.cmd_line[self.index + 1]) == '"') - { - last_emitted_code_unit = strategy.emitCharacter(self, '"', last_emitted_code_unit); - self.index += 1; - } else { - inside_quotes = !inside_quotes; - } - } - }, - '\\' => { - backslash_count += 1; - }, - else => { - last_emitted_code_unit = strategy.emitBackslashes(self, backslash_count, last_emitted_code_unit); - backslash_count = 0; - last_emitted_code_unit = strategy.emitCharacter(self, char, last_emitted_code_unit); - }, - } - } - } - - /// Frees the iterator's copy of the command-line string and all previously returned - /// argument slices. - pub fn deinit(self: *ArgIteratorWindows) void { - self.allocator.free(self.buffer); - } -}; - -/// Optional parameters for `ArgIteratorGeneral` -pub const ArgIteratorGeneralOptions = struct { - comments: bool = false, - single_quotes: bool = false, -}; - -/// A general Iterator to parse a string into a set of arguments -pub fn ArgIteratorGeneral(comptime options: ArgIteratorGeneralOptions) type { - return struct { - allocator: Allocator, - index: usize = 0, - cmd_line: []const u8, - - /// Should the cmd_line field be free'd (using the allocator) on deinit()? - free_cmd_line_on_deinit: bool, - - /// buffer MUST be long enough to hold the cmd_line plus a null terminator. - /// buffer will we free'd (using the allocator) on deinit() - buffer: []u8, - start: usize = 0, - end: usize = 0, - - pub const Self = @This(); - - pub const InitError = error{OutOfMemory}; - - /// cmd_line_utf8 MUST remain valid and constant while using this instance - pub fn init(allocator: Allocator, cmd_line_utf8: []const u8) InitError!Self { - const buffer = try allocator.alloc(u8, cmd_line_utf8.len + 1); - errdefer allocator.free(buffer); - - return Self{ - .allocator = allocator, - .cmd_line = cmd_line_utf8, - .free_cmd_line_on_deinit = false, - .buffer = buffer, - }; - } - - /// cmd_line_utf8 will be free'd (with the allocator) on deinit() - pub fn initTakeOwnership(allocator: Allocator, cmd_line_utf8: []const u8) InitError!Self { - const buffer = try allocator.alloc(u8, cmd_line_utf8.len + 1); - errdefer allocator.free(buffer); - - return Self{ - .allocator = allocator, - .cmd_line = cmd_line_utf8, - .free_cmd_line_on_deinit = true, - .buffer = buffer, - }; - } - - // Skips over whitespace in the cmd_line. - // Returns false if the terminating sentinel is reached, true otherwise. - // Also skips over comments (if supported). - fn skipWhitespace(self: *Self) bool { - while (true) : (self.index += 1) { - const character = if (self.index != self.cmd_line.len) self.cmd_line[self.index] else 0; - switch (character) { - 0 => return false, - ' ', '\t', '\r', '\n' => continue, - '#' => { - if (options.comments) { - while (true) : (self.index += 1) { - switch (self.cmd_line[self.index]) { - '\n' => break, - 0 => return false, - else => continue, - } - } - continue; - } else { - break; - } - }, - else => break, - } - } - return true; - } - - pub fn skip(self: *Self) bool { - if (!self.skipWhitespace()) { - return false; - } - - var backslash_count: usize = 0; - var in_quote = false; - while (true) : (self.index += 1) { - const character = if (self.index != self.cmd_line.len) self.cmd_line[self.index] else 0; - switch (character) { - 0 => return true, - '"', '\'' => { - if (!options.single_quotes and character == '\'') { - backslash_count = 0; - continue; - } - const quote_is_real = backslash_count % 2 == 0; - if (quote_is_real) { - in_quote = !in_quote; - } - }, - '\\' => { - backslash_count += 1; - }, - ' ', '\t', '\r', '\n' => { - if (!in_quote) { - return true; - } - backslash_count = 0; - }, - else => { - backslash_count = 0; - continue; - }, - } - } - } - - /// Returns a slice of the internal buffer that contains the next argument. - /// Returns null when it reaches the end. - pub fn next(self: *Self) ?[:0]const u8 { - if (!self.skipWhitespace()) { - return null; - } - - var backslash_count: usize = 0; - var in_quote = false; - while (true) : (self.index += 1) { - const character = if (self.index != self.cmd_line.len) self.cmd_line[self.index] else 0; - switch (character) { - 0 => { - self.emitBackslashes(backslash_count); - self.buffer[self.end] = 0; - const token = self.buffer[self.start..self.end :0]; - self.end += 1; - self.start = self.end; - return token; - }, - '"', '\'' => { - if (!options.single_quotes and character == '\'') { - self.emitBackslashes(backslash_count); - backslash_count = 0; - self.emitCharacter(character); - continue; - } - const quote_is_real = backslash_count % 2 == 0; - self.emitBackslashes(backslash_count / 2); - backslash_count = 0; - - if (quote_is_real) { - in_quote = !in_quote; - } else { - self.emitCharacter('"'); - } - }, - '\\' => { - backslash_count += 1; - }, - ' ', '\t', '\r', '\n' => { - self.emitBackslashes(backslash_count); - backslash_count = 0; - if (in_quote) { - self.emitCharacter(character); - } else { - self.buffer[self.end] = 0; - const token = self.buffer[self.start..self.end :0]; - self.end += 1; - self.start = self.end; - return token; - } - }, - else => { - self.emitBackslashes(backslash_count); - backslash_count = 0; - self.emitCharacter(character); - }, - } - } - } - - fn emitBackslashes(self: *Self, emit_count: usize) void { - var i: usize = 0; - while (i < emit_count) : (i += 1) { - self.emitCharacter('\\'); - } - } - - fn emitCharacter(self: *Self, char: u8) void { - self.buffer[self.end] = char; - self.end += 1; - } - - /// Call to free the internal buffer of the iterator. - pub fn deinit(self: *Self) void { - self.allocator.free(self.buffer); - - if (self.free_cmd_line_on_deinit) { - self.allocator.free(self.cmd_line); - } - } - }; -} - -/// Cross-platform command line argument iterator. -pub const ArgIterator = struct { - const InnerType = switch (native_os) { - .windows => ArgIteratorWindows, - .wasi => if (builtin.link_libc) ArgIteratorPosix else ArgIteratorWasi, - else => ArgIteratorPosix, - }; - - inner: InnerType, - - /// Initialize the args iterator. Consider using initWithAllocator() instead - /// for cross-platform compatibility. - pub fn init() ArgIterator { - if (native_os == .wasi) { - @compileError("In WASI, use initWithAllocator instead."); - } - if (native_os == .windows) { - @compileError("In Windows, use initWithAllocator instead."); - } - - return ArgIterator{ .inner = InnerType.init() }; - } - - pub const InitError = InnerType.InitError; - - /// You must deinitialize iterator's internal buffers by calling `deinit` when done. - pub fn initWithAllocator(allocator: Allocator) InitError!ArgIterator { - if (native_os == .wasi and !builtin.link_libc) { - return ArgIterator{ .inner = try InnerType.init(allocator) }; - } - if (native_os == .windows) { - const cmd_line = std.os.windows.peb().ProcessParameters.CommandLine; - const cmd_line_w = cmd_line.Buffer.?[0 .. cmd_line.Length / 2]; - return ArgIterator{ .inner = try InnerType.init(allocator, cmd_line_w) }; - } - - return ArgIterator{ .inner = InnerType.init() }; - } - - /// Get the next argument. Returns 'null' if we are at the end. - /// Returned slice is pointing to the iterator's internal buffer. - /// On Windows, the result is encoded as [WTF-8](https://wtf-8.codeberg.page/). - /// On other platforms, the result is an opaque sequence of bytes with no particular encoding. - pub fn next(self: *ArgIterator) ?([:0]const u8) { - return self.inner.next(); - } - - /// Parse past 1 argument without capturing it. - /// Returns `true` if skipped an arg, `false` if we are at the end. - pub fn skip(self: *ArgIterator) bool { - return self.inner.skip(); - } - - /// Call this to free the iterator's internal buffer if the iterator - /// was created with `initWithAllocator` function. - pub fn deinit(self: *ArgIterator) void { - // Unless we're targeting WASI or Windows, this is a no-op. - if (native_os == .wasi and !builtin.link_libc) { - self.inner.deinit(); - } - - if (native_os == .windows) { - self.inner.deinit(); - } - } -}; - -/// Holds the command-line arguments, with the program name as the first entry. -/// Use argsWithAllocator() for cross-platform code. -pub fn args() ArgIterator { - return ArgIterator.init(); -} - -/// You must deinitialize iterator's internal buffers by calling `deinit` when done. -pub fn argsWithAllocator(allocator: Allocator) ArgIterator.InitError!ArgIterator { - return ArgIterator.initWithAllocator(allocator); -} - -/// Caller must call argsFree on result. -/// On Windows, the result is encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On other platforms, the result is an opaque sequence of bytes with no particular encoding. -pub fn argsAlloc(allocator: Allocator) ![][:0]u8 { - // TODO refactor to only make 1 allocation. - var it = try argsWithAllocator(allocator); - defer it.deinit(); - - var contents = std.array_list.Managed(u8).init(allocator); - defer contents.deinit(); - - var slice_list = std.array_list.Managed(usize).init(allocator); - defer slice_list.deinit(); - - while (it.next()) |arg| { - try contents.appendSlice(arg[0 .. arg.len + 1]); - try slice_list.append(arg.len); - } - - const contents_slice = contents.items; - const slice_sizes = slice_list.items; - const slice_list_bytes = try math.mul(usize, @sizeOf([]u8), slice_sizes.len); - const total_bytes = try math.add(usize, slice_list_bytes, contents_slice.len); - const buf = try allocator.alignedAlloc(u8, .of([]u8), total_bytes); - errdefer allocator.free(buf); - - const result_slice_list = mem.bytesAsSlice([:0]u8, buf[0..slice_list_bytes]); - const result_contents = buf[slice_list_bytes..]; - @memcpy(result_contents[0..contents_slice.len], contents_slice); - - var contents_index: usize = 0; - for (slice_sizes, 0..) |len, i| { - const new_index = contents_index + len; - result_slice_list[i] = result_contents[contents_index..new_index :0]; - contents_index = new_index + 1; - } - - return result_slice_list; -} - -pub fn argsFree(allocator: Allocator, args_alloc: []const [:0]u8) void { - var total_bytes: usize = 0; - for (args_alloc) |arg| { - total_bytes += @sizeOf([]u8) + arg.len + 1; - } - const unaligned_allocated_buf = @as([*]const u8, @ptrCast(args_alloc.ptr))[0..total_bytes]; - const aligned_allocated_buf: []align(@alignOf([]u8)) const u8 = @alignCast(unaligned_allocated_buf); - return allocator.free(aligned_allocated_buf); -} - -test ArgIteratorWindows { - const t = testArgIteratorWindows; - - try t( - \\"C:\Program Files\zig\zig.exe" run .\src\main.zig -target x86_64-windows-gnu -O ReleaseSafe -- --emoji=🗿 --eval="new Regex(\"Dwayne \\\"The Rock\\\" Johnson\")" - , &.{ - \\C:\Program Files\zig\zig.exe - , - \\run - , - \\.\src\main.zig - , - \\-target - , - \\x86_64-windows-gnu - , - \\-O - , - \\ReleaseSafe - , - \\-- - , - \\--emoji=🗿 - , - \\--eval=new Regex("Dwayne \"The Rock\" Johnson") - , - }); - - // Empty - try t("", &.{}); - - // Separators - try t("aa bb cc", &.{ "aa", "bb", "cc" }); - try t("aa\tbb\tcc", &.{ "aa", "bb", "cc" }); - try t("aa\nbb\ncc", &.{"aa\nbb\ncc"}); - try t("aa\r\nbb\r\ncc", &.{"aa\r\nbb\r\ncc"}); - try t("aa\rbb\rcc", &.{"aa\rbb\rcc"}); - try t("aa\x07bb\x07cc", &.{"aa\x07bb\x07cc"}); - try t("aa\x7Fbb\x7Fcc", &.{"aa\x7Fbb\x7Fcc"}); - try t("aa🦎bb🦎cc", &.{"aa🦎bb🦎cc"}); - - // Leading/trailing whitespace - try t(" ", &.{""}); - try t(" aa bb ", &.{ "", "aa", "bb" }); - try t("\t\t", &.{""}); - try t("\t\taa\t\tbb\t\t", &.{ "", "aa", "bb" }); - try t("\n\n", &.{"\n\n"}); - try t("\n\naa\n\nbb\n\n", &.{"\n\naa\n\nbb\n\n"}); - - // Executable name with quotes/backslashes - try t("\"aa bb\tcc\ndd\"", &.{"aa bb\tcc\ndd"}); - try t("\"", &.{""}); - try t("\"\"", &.{""}); - try t("\"\"\"", &.{""}); - try t("\"\"\"\"", &.{""}); - try t("\"\"\"\"\"", &.{""}); - try t("aa\"bb\"cc\"dd", &.{"aabbccdd"}); - try t("aa\"bb cc\"dd", &.{"aabb ccdd"}); - try t("\"aa\\\"bb\"", &.{"aa\\bb"}); - try t("\"aa\\\\\"", &.{"aa\\\\"}); - try t("aa\\\"bb", &.{"aa\\bb"}); - try t("aa\\\\\"bb", &.{"aa\\\\bb"}); - - // Arguments with quotes/backslashes - try t(". \"aa bb\tcc\ndd\"", &.{ ".", "aa bb\tcc\ndd" }); - try t(". aa\" \"bb\"\t\"cc\"\n\"dd\"", &.{ ".", "aa bb\tcc\ndd" }); - try t(". ", &.{"."}); - try t(". \"", &.{ ".", "" }); - try t(". \"\"", &.{ ".", "" }); - try t(". \"\"\"", &.{ ".", "\"" }); - try t(". \"\"\"\"", &.{ ".", "\"" }); - try t(". \"\"\"\"\"", &.{ ".", "\"\"" }); - try t(". \"\"\"\"\"\"", &.{ ".", "\"\"" }); - try t(". \" \"", &.{ ".", " " }); - try t(". \" \"\"", &.{ ".", " \"" }); - try t(". \" \"\"\"", &.{ ".", " \"" }); - try t(". \" \"\"\"\"", &.{ ".", " \"\"" }); - try t(". \" \"\"\"\"\"", &.{ ".", " \"\"" }); - try t(". \" \"\"\"\"\"\"", &.{ ".", " \"\"\"" }); - try t(". \\\"", &.{ ".", "\"" }); - try t(". \\\"\"", &.{ ".", "\"" }); - try t(". \\\"\"\"", &.{ ".", "\"" }); - try t(". \\\"\"\"\"", &.{ ".", "\"\"" }); - try t(". \\\"\"\"\"\"", &.{ ".", "\"\"" }); - try t(". \\\"\"\"\"\"\"", &.{ ".", "\"\"\"" }); - try t(". \" \\\"", &.{ ".", " \"" }); - try t(". \" \\\"\"", &.{ ".", " \"" }); - try t(". \" \\\"\"\"", &.{ ".", " \"\"" }); - try t(". \" \\\"\"\"\"", &.{ ".", " \"\"" }); - try t(". \" \\\"\"\"\"\"", &.{ ".", " \"\"\"" }); - try t(". \" \\\"\"\"\"\"\"", &.{ ".", " \"\"\"" }); - try t(". aa\\bb\\\\cc\\\\\\dd", &.{ ".", "aa\\bb\\\\cc\\\\\\dd" }); - try t(". \\\\\\\"aa bb\"", &.{ ".", "\\\"aa", "bb" }); - try t(". \\\\\\\\\"aa bb\"", &.{ ".", "\\\\aa bb" }); - - // From https://learn.microsoft.com/en-us/cpp/cpp/main-function-command-line-args#results-of-parsing-command-lines - try t( - \\foo.exe "abc" d e - , &.{ "foo.exe", "abc", "d", "e" }); - try t( - \\foo.exe a\\b d"e f"g h - , &.{ "foo.exe", "a\\\\b", "de fg", "h" }); - try t( - \\foo.exe a\\\"b c d - , &.{ "foo.exe", "a\\\"b", "c", "d" }); - try t( - \\foo.exe a\\\\"b c" d e - , &.{ "foo.exe", "a\\\\b c", "d", "e" }); - try t( - \\foo.exe a"b"" c d - , &.{ "foo.exe", "ab\" c d" }); - - // From https://daviddeley.com/autohotkey/parameters/parameters.htm#WINCRULESEX - try t("foo.exe CallMeIshmael", &.{ "foo.exe", "CallMeIshmael" }); - try t("foo.exe \"Call Me Ishmael\"", &.{ "foo.exe", "Call Me Ishmael" }); - try t("foo.exe Cal\"l Me I\"shmael", &.{ "foo.exe", "Call Me Ishmael" }); - try t("foo.exe CallMe\\\"Ishmael", &.{ "foo.exe", "CallMe\"Ishmael" }); - try t("foo.exe \"CallMe\\\"Ishmael\"", &.{ "foo.exe", "CallMe\"Ishmael" }); - try t("foo.exe \"Call Me Ishmael\\\\\"", &.{ "foo.exe", "Call Me Ishmael\\" }); - try t("foo.exe \"CallMe\\\\\\\"Ishmael\"", &.{ "foo.exe", "CallMe\\\"Ishmael" }); - try t("foo.exe a\\\\\\b", &.{ "foo.exe", "a\\\\\\b" }); - try t("foo.exe \"a\\\\\\b\"", &.{ "foo.exe", "a\\\\\\b" }); - - // Surrogate pair encoding of 𐐷 separated by quotes. - // Encoded as WTF-16: - // "<0xD801>"<0xDC37> - // Encoded as WTF-8: - // "<0xED><0xA0><0x81>"<0xED><0xB0><0xB7> - // During parsing, the quotes drop out and the surrogate pair - // should end up encoded as its normal UTF-8 representation. - try t("foo.exe \"\xed\xa0\x81\"\xed\xb0\xb7", &.{ "foo.exe", "𐐷" }); -} - -fn testArgIteratorWindows(cmd_line: []const u8, expected_args: []const []const u8) !void { - const cmd_line_w = try unicode.wtf8ToWtf16LeAllocZ(testing.allocator, cmd_line); - defer testing.allocator.free(cmd_line_w); - - // next - { - var it = try ArgIteratorWindows.init(testing.allocator, cmd_line_w); - defer it.deinit(); - - for (expected_args) |expected| { - if (it.next()) |actual| { - try testing.expectEqualStrings(expected, actual); - } else { - return error.TestUnexpectedResult; - } - } - try testing.expect(it.next() == null); - } - - // skip - { - var it = try ArgIteratorWindows.init(testing.allocator, cmd_line_w); - defer it.deinit(); - - for (0..expected_args.len) |_| { - try testing.expect(it.skip()); - } - try testing.expect(!it.skip()); - } -} - -test "general arg parsing" { - try testGeneralCmdLine("a b\tc d", &.{ "a", "b", "c", "d" }); - try testGeneralCmdLine("\"abc\" d e", &.{ "abc", "d", "e" }); - try testGeneralCmdLine("a\\\\\\b d\"e f\"g h", &.{ "a\\\\\\b", "de fg", "h" }); - try testGeneralCmdLine("a\\\\\\\"b c d", &.{ "a\\\"b", "c", "d" }); - try testGeneralCmdLine("a\\\\\\\\\"b c\" d e", &.{ "a\\\\b c", "d", "e" }); - try testGeneralCmdLine("a b\tc \"d f", &.{ "a", "b", "c", "d f" }); - try testGeneralCmdLine("j k l\\", &.{ "j", "k", "l\\" }); - try testGeneralCmdLine("\"\" x y z\\\\", &.{ "", "x", "y", "z\\\\" }); - - try testGeneralCmdLine("\".\\..\\zig-cache\\build\" \"bin\\zig.exe\" \".\\..\" \".\\..\\zig-cache\" \"--help\"", &.{ - ".\\..\\zig-cache\\build", - "bin\\zig.exe", - ".\\..", - ".\\..\\zig-cache", - "--help", - }); - - try testGeneralCmdLine( - \\ 'foo' "bar" - , &.{ "'foo'", "bar" }); -} - -fn testGeneralCmdLine(input_cmd_line: []const u8, expected_args: []const []const u8) !void { - var it = try ArgIteratorGeneral(.{}).init(std.testing.allocator, input_cmd_line); - defer it.deinit(); - for (expected_args) |expected_arg| { - const arg = it.next().?; - try testing.expectEqualStrings(expected_arg, arg); - } - try testing.expect(it.next() == null); -} - -test "response file arg parsing" { - try testResponseFileCmdLine( - \\a b - \\c d\ - , &.{ "a", "b", "c", "d\\" }); - try testResponseFileCmdLine("a b c d\\", &.{ "a", "b", "c", "d\\" }); - - try testResponseFileCmdLine( - \\j - \\ k l # this is a comment \\ \\\ \\\\ "none" "\\" "\\\" - \\ "m" #another comment - \\ - , &.{ "j", "k", "l", "m" }); - - try testResponseFileCmdLine( - \\ "" q "" - \\ "r s # t" "u\" v" #another comment - \\ - , &.{ "", "q", "", "r s # t", "u\" v" }); - - try testResponseFileCmdLine( - \\ -l"advapi32" a# b#c d# - \\e\\\ - , &.{ "-ladvapi32", "a#", "b#c", "d#", "e\\\\\\" }); - - try testResponseFileCmdLine( - \\ 'foo' "bar" - , &.{ "foo", "bar" }); -} - -fn testResponseFileCmdLine(input_cmd_line: []const u8, expected_args: []const []const u8) !void { - var it = try ArgIteratorGeneral(.{ .comments = true, .single_quotes = true }) - .init(std.testing.allocator, input_cmd_line); - defer it.deinit(); - for (expected_args) |expected_arg| { - const arg = it.next().?; - try testing.expectEqualStrings(expected_arg, arg); - } - try testing.expect(it.next() == null); -} - pub const UserInfo = struct { uid: posix.uid_t, gid: posix.gid_t, @@ -1568,9 +139,9 @@ pub fn getUserInfo(name: []const u8) !UserInfo { /// TODO this reads /etc/passwd. But sometimes the user/id mapping is in something else /// like NIS, AD, etc. See `man nss` or look at an strace for `id myuser`. -pub fn posixGetUserInfo(name: []const u8) !UserInfo { - const file = try std.fs.openFileAbsolute("/etc/passwd", .{}); - defer file.close(); +pub fn posixGetUserInfo(io: Io, name: []const u8) !UserInfo { + const file = try Io.Dir.openFileAbsolute(io, "/etc/passwd", .{}); + defer file.close(io); var buffer: [4096]u8 = undefined; var file_reader = file.reader(&buffer); return posixGetUserInfoPasswdStream(name, &file_reader.interface) catch |err| switch (err) { @@ -1694,71 +265,278 @@ pub fn getBaseAddress() usize { } } -/// Tells whether calling the `execv` or `execve` functions will be a compile error. -pub const can_execv = switch (native_os) { +/// Tells whether the target operating system supports replacing the current +/// process image. If this is `false` then calling `replace` or `replaceFile` +/// functions will return `error.OperationUnsupported`. +pub const can_replace = switch (native_os) { .windows, .haiku, .wasi => false, else => true, }; -/// Tells whether spawning child processes is supported (e.g. via Child) +/// Tells whether spawning child processes is supported. pub const can_spawn = switch (native_os) { .wasi, .ios, .tvos, .visionos, .watchos => false, else => true, }; -pub const ExecvError = std.posix.ExecveError || error{OutOfMemory}; - -/// Replaces the current process image with the executed process. -/// This function must allocate memory to add a null terminating bytes on path and each arg. -/// It must also convert to KEY=VALUE\0 format for environment variables, and include null -/// pointers after the args and after the environment variables. -/// `argv[0]` is the executable path. -/// This function also uses the PATH environment variable to get the full path to the executable. -/// Due to the heap-allocation, it is illegal to call this function in a fork() child. -/// For that use case, use the `std.posix` functions directly. -pub fn execv(allocator: Allocator, argv: []const []const u8) ExecvError { - return execve(allocator, argv, null); +pub const ReplaceError = error{ + /// The target operating system cannot replace the process image with a new + /// one. + OperationUnsupported, + SystemResources, + AccessDenied, + PermissionDenied, + InvalidExe, + FileSystem, + IsDir, + FileNotFound, + NotDir, + FileBusy, + ProcessFdQuotaExceeded, + SystemFdQuotaExceeded, +} || Allocator.Error || Io.Dir.PathNameError || Io.Cancelable || Io.UnexpectedError; + +pub const ReplaceOptions = struct { + argv: []const []const u8, + expand_arg0: ArgExpansion = .no_expand, + /// Replaces the environment when provided. The PATH value from here is + /// never used to resolve `argv[0]`. + environ_map: ?*const Environ.Map = null, +}; + +/// Replaces the current process image with the executed process. If this +/// function succeeds, it does not return. +/// +/// `argv[0]` is the name of the process to replace the current one with. If it +/// is not already a file path (i.e. it contains '/'), it is resolved into a +/// file path based on PATH from the parent environment. +/// +/// It is illegal to call this function in a fork() child. +pub fn replace(io: Io, options: ReplaceOptions) ReplaceError { + return io.vtable.processReplace(io.userdata, options); } -/// Replaces the current process image with the executed process. -/// This function must allocate memory to add a null terminating bytes on path and each arg. -/// It must also convert to KEY=VALUE\0 format for environment variables, and include null -/// pointers after the args and after the environment variables. -/// `argv[0]` is the executable path. -/// This function also uses the PATH environment variable to get the full path to the executable. -/// Due to the heap-allocation, it is illegal to call this function in a fork() child. -/// For that use case, use the `std.posix` functions directly. -pub fn execve( - allocator: Allocator, +/// Replaces the current process image with the executed process. If this +/// function succeeds, it does not return. +/// +/// `argv[0]` is the file path of the process to replace the current one with, +/// relative to `dir`. It is *always* treated as a file path, even if it does +/// not contain '/'. +/// +/// It is illegal to call this function in a fork() child. +pub fn replacePath(io: Io, dir: Io.Dir, options: ReplaceOptions) ReplaceError { + return io.vtable.processReplacePath(io.userdata, dir, options); +} + +pub const ArgExpansion = enum { expand, no_expand }; + +/// File name extensions supported natively by `CreateProcess()` on Windows. +pub const WindowsExtension = enum { bat, cmd, com, exe }; + +pub const SpawnError = error{ + /// The operating system does not support creating child processes. + OperationUnsupported, + OutOfMemory, + /// POSIX-only. `StdIo.ignore` was selected and opening `/dev/null` returned ENODEV. + NoDevice, + /// Windows-only. `cwd` or `argv` was provided and it was invalid WTF-8. + /// https://wtf-8.codeberg.page/ + InvalidWtf8, + /// Windows-only. `cwd` was provided, but the path did not exist when spawning the child process. + CurrentWorkingDirectoryUnlinked, + /// Windows-only. NUL (U+0000), LF (U+000A), CR (U+000D) are not allowed + /// within arguments when executing a `.bat`/`.cmd` script. + /// - NUL/LF signifiies end of arguments, so anything afterwards + /// would be lost after execution. + /// - CR is stripped by `cmd.exe`, so any CR codepoints + /// would be lost after execution. + InvalidBatchScriptArg, + SystemResources, + AccessDenied, + PermissionDenied, + InvalidExe, + FileSystem, + IsDir, + FileNotFound, + NotDir, + FileBusy, + ProcessFdQuotaExceeded, + SystemFdQuotaExceeded, + ResourceLimitReached, + InvalidUserId, + InvalidProcessGroupId, + SymLinkLoop, + InvalidName, + /// An attempt was made to change the process group ID of one of the + /// children of the calling process and the child had already performed an + /// image replacement. + ProcessAlreadyExec, +} || Io.Dir.PathNameError || Io.Cancelable || Io.UnexpectedError; + +pub const SpawnOptions = struct { argv: []const []const u8, - env_map: ?*const EnvMap, -) ExecvError { - if (!can_execv) @compileError("The target OS does not support execv"); - - var arena_allocator = std.heap.ArenaAllocator.init(allocator); - defer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); - - const argv_buf = try arena.allocSentinel(?[*:0]const u8, argv.len, null); - for (argv, 0..) |arg, i| argv_buf[i] = (try arena.dupeZ(u8, arg)).ptr; - - const envp = m: { - if (env_map) |m| { - const envp_buf = try createNullDelimitedEnvMap(arena, m); - break :m envp_buf.ptr; - } else if (builtin.link_libc) { - break :m std.c.environ; - } else if (builtin.output_mode == .Exe) { - // Then we have Zig start code and this works. - // TODO type-safety for null-termination of `os.environ`. - break :m @as([*:null]const ?[*:0]const u8, @ptrCast(std.os.environ.ptr)); - } else { - // TODO come up with a solution for this. - @compileError("missing std lib enhancement: std.process.execv implementation has no way to collect the environment variables to forward to the child process"); - } + + /// Set to change the current working directory when spawning the child process. + cwd: ?[]const u8 = null, + /// Set to change the current working directory when spawning the child process. + /// This is not yet implemented for Windows. See https://github.com/ziglang/zig/issues/5190 + /// Once that is done, `cwd` will be deprecated in favor of this field. + cwd_dir: ?Io.Dir = null, + /// Replaces the child environment when provided. The PATH value from here + /// is not used to resolve `argv[0]`; that resolution always uses parent + /// environment. + environ_map: ?*const Environ.Map = null, + expand_arg0: ArgExpansion = .no_expand, + /// When populated, a pipe will be created for the child process to + /// communicate progress back to the parent. The file descriptor of the + /// write end of the pipe will be specified in the `ZIG_PROGRESS` + /// environment variable inside the child process. The progress reported by + /// the child will be attached to this progress node in the parent process. + /// + /// The child's progress tree will be grafted into the parent's progress tree, + /// by substituting this node with the child's root node. + progress_node: std.Progress.Node = std.Progress.Node.none, + + stdin: StdIo = .inherit, + stdout: StdIo = .inherit, + stderr: StdIo = .inherit, + + /// Set to true to obtain rusage information for the child process. + /// Depending on the target platform and implementation status, the + /// requested statistics may or may not be available. If they are + /// available, then the `resource_usage_statistics` field will be populated + /// after calling `wait`. + /// On Linux and Darwin, this obtains rusage statistics from wait4(). + request_resource_usage_statistics: bool = false, + + /// Set to change the user id when spawning the child process. + uid: ?posix.uid_t = null, + /// Set to change the group id when spawning the child process. + gid: ?posix.gid_t = null, + /// Set to change the process group id when spawning the child process. + pgid: ?posix.pid_t = null, + + /// Start child process in suspended state. + /// For Posix systems it's started as if SIGSTOP was sent. + start_suspended: bool = false, + /// Windows-only. Sets the CREATE_NO_WINDOW flag in CreateProcess. + create_no_window: bool = false, + /// Darwin-only. Disable ASLR for the child process. + disable_aslr: bool = false, + + /// Behavior of the child process's standard input, output, and error streams. + pub const StdIo = union(enum) { + /// Inherit the corresponding stream from the parent process. + inherit, + /// Pass an already open file from the parent to the child. + file: File, + /// Pass a null stream to the child process by opening "/dev/null" on POSIX + /// and "NUL" on Windows. + ignore, + /// Create a new pipe for the stream. + /// + /// The corresponding field (`stdout`, `stderr`, or `stdin`) will be + /// assigned a `File` object that can be used to read from or write to the + /// pipe. + pipe, + /// Spawn the child process with the corresponding stream missing. This + /// will likely result in the child encountering EBADF if it tries to use + /// stdin, stdout, or stderr, or if only one stream is closed, it will + /// result in them getting mixed up. Generally, this option is for advanced + /// use cases only. + close, }; +}; - return posix.execvpeZ_expandArg0(.no_expand, argv_buf.ptr[0].?, argv_buf.ptr, envp); +/// Creates a child process. +/// +/// `argv[0]` is the name of the program to execute. If it is not already a +/// file path (i.e. it contains '/'), it is resolved into a file path based on +/// PATH from the parent environment. +pub fn spawn(io: Io, options: SpawnOptions) SpawnError!Child { + return io.vtable.processSpawn(io.userdata, options); +} + +/// Creates a child process. +/// +/// `argv[0]` is the file path of the program to execute, relative to `dir`. It +/// is *always* treated as a file path, even if it does not contain '/'. +pub fn spawnPath(io: Io, dir: Io.Dir, options: SpawnOptions) SpawnError!Child { + return io.vtable.processSpawnPath(io.userdata, dir, options); +} + +pub const RunError = posix.GetCwdError || posix.ReadError || SpawnError || posix.PollError || error{ + StdoutStreamTooLong, + StderrStreamTooLong, +}; + +pub const RunOptions = struct { + argv: []const []const u8, + max_output_bytes: usize = 50 * 1024, + + /// Set to change the current working directory when spawning the child process. + cwd: ?[]const u8 = null, + /// Set to change the current working directory when spawning the child process. + /// This is not yet implemented for Windows. See https://github.com/ziglang/zig/issues/5190 + /// Once that is done, `cwd` will be deprecated in favor of this field. + cwd_dir: ?Io.Dir = null, + /// Replaces the child environment when provided. The PATH value from here + /// is not used to resolve `argv[0]`; that resolution always uses parent + /// environment. + environ_map: ?*const Environ.Map = null, + expand_arg0: ArgExpansion = .no_expand, + /// When populated, a pipe will be created for the child process to + /// communicate progress back to the parent. The file descriptor of the + /// write end of the pipe will be specified in the `ZIG_PROGRESS` + /// environment variable inside the child process. The progress reported by + /// the child will be attached to this progress node in the parent process. + /// + /// The child's progress tree will be grafted into the parent's progress tree, + /// by substituting this node with the child's root node. + progress_node: std.Progress.Node = std.Progress.Node.none, + /// Windows-only. Sets the CREATE_NO_WINDOW flag in CreateProcess. + create_no_window: bool = true, + /// Darwin-only. Disable ASLR for the child process. + disable_aslr: bool = false, +}; + +pub const RunResult = struct { + term: Child.Term, + stdout: []u8, + stderr: []u8, +}; + +/// Spawns a child process, waits for it, collecting stdout and stderr, and then returns. +/// If it succeeds, the caller owns result.stdout and result.stderr memory. +pub fn run(gpa: Allocator, io: Io, options: RunOptions) RunError!RunResult { + var child = try spawn(io, .{ + .argv = options.argv, + .cwd = options.cwd, + .cwd_dir = options.cwd_dir, + .environ_map = options.environ_map, + .expand_arg0 = options.expand_arg0, + .progress_node = options.progress_node, + .create_no_window = options.create_no_window, + .disable_aslr = options.disable_aslr, + + .stdin = .ignore, + .stdout = .pipe, + .stderr = .pipe, + }); + defer child.kill(io); + + var stdout: std.ArrayList(u8) = .empty; + defer stdout.deinit(gpa); + var stderr: std.ArrayList(u8) = .empty; + defer stderr.deinit(gpa); + + try child.collectOutput(gpa, &stdout, &stderr, options.max_output_bytes); + + return .{ + .stdout = try stdout.toOwnedSlice(gpa), + .stderr = try stderr.toOwnedSlice(gpa), + .term = try child.wait(io), + }; } pub const TotalSystemMemoryError = error{ @@ -1836,21 +614,19 @@ pub fn totalSystemMemory() TotalSystemMemoryError!u64 { } } -/// Indicate that we are now terminating with a successful exit code. -/// In debug builds, this is a no-op, so that the calling code's -/// cleanup mechanisms are tested and so that external tools that -/// check for resource leaks can be accurate. In release builds, this -/// calls exit(0), and does not return. -pub fn cleanExit() void { - if (builtin.mode == .Debug) { - return; - } else { - std.debug.lockStdErr(); - exit(0); - } +/// Indicate intent to terminate with a successful exit code. +/// +/// In debug builds, this is a no-op, so that the calling code's cleanup +/// mechanisms are tested and so that external tools checking for resource +/// leaks can be accurate. In release builds, this calls `exit` with code zero, +/// and does not return. +pub fn cleanExit(io: Io) void { + if (builtin.mode == .Debug) return; + _ = io.lockStderr(&.{}, .no_color) catch {}; + exit(0); } -/// Raise the open file descriptor limit. +/// Request ability to have more open file descriptors simultaneously. /// /// On some systems, this raises the limit before seeing ProcessFdQuotaExceeded /// errors. On other systems, this does nothing. @@ -1893,217 +669,220 @@ test raiseFileDescriptorLimit { raiseFileDescriptorLimit(); } -pub const CreateEnvironOptions = struct { - /// `null` means to leave the `ZIG_PROGRESS` environment variable unmodified. - /// If non-null, negative means to remove the environment variable, and >= 0 - /// means to provide it with the given integer. - zig_progress_fd: ?i32 = null, -}; - -/// Creates a null-delimited environment variable block in the format -/// expected by POSIX, from a hash map plus options. -pub fn createEnvironFromMap( - arena: Allocator, - map: *const EnvMap, - options: CreateEnvironOptions, -) Allocator.Error![:null]?[*:0]u8 { - const ZigProgressAction = enum { nothing, edit, delete, add }; - const zig_progress_action: ZigProgressAction = a: { - const fd = options.zig_progress_fd orelse break :a .nothing; - const contains = map.get("ZIG_PROGRESS") != null; - if (fd >= 0) { - break :a if (contains) .edit else .add; - } else { - if (contains) break :a .delete; - } - break :a .nothing; - }; +/// Logs an error and then terminates the process with exit code 1. +pub fn fatal(comptime format: []const u8, format_arguments: anytype) noreturn { + std.log.err(format, format_arguments); + exit(1); +} - const envp_count: usize = c: { - var count: usize = map.count(); - switch (zig_progress_action) { - .add => count += 1, - .delete => count -= 1, - .nothing, .edit => {}, - } - break :c count; +pub const ExecutablePathBaseError = error{ + FileNotFound, + AccessDenied, + /// The operating system does not support an executable learning its own + /// path. + OperationUnsupported, + NotDir, + SymLinkLoop, + InputOutput, + FileTooBig, + IsDir, + ProcessFdQuotaExceeded, + SystemFdQuotaExceeded, + NoDevice, + SystemResources, + NoSpaceLeft, + FileSystem, + BadPathName, + DeviceBusy, + SharingViolation, + PipeBusy, + NotLink, + PathAlreadyExists, + /// On Windows, `\\server` or `\\server\share` was not found. + NetworkNotFound, + ProcessNotFound, + /// On Windows, antivirus software is enabled by default. It can be + /// disabled, but Windows Update sometimes ignores the user's preference + /// and re-enables it. When enabled, antivirus software on Windows + /// intercepts file system operations and makes them significantly slower + /// in addition to possibly failing with this error code. + AntivirusInterference, + /// On Windows, the volume does not contain a recognized file system. File + /// system drivers might not be loaded, or the volume may be corrupt. + UnrecognizedVolume, + PermissionDenied, +} || Io.Cancelable || Io.UnexpectedError; + +pub const ExecutablePathAllocError = ExecutablePathBaseError || Allocator.Error; + +pub fn executablePathAlloc(io: Io, allocator: Allocator) ExecutablePathAllocError![:0]u8 { + var buffer: [max_path_bytes]u8 = undefined; + const n = executablePath(io, &buffer) catch |err| switch (err) { + error.NameTooLong => unreachable, + else => |e| return e, }; + return allocator.dupeZ(u8, buffer[0..n]); +} - const envp_buf = try arena.allocSentinel(?[*:0]u8, envp_count, null); - var i: usize = 0; - - if (zig_progress_action == .add) { - envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?}, 0); - i += 1; - } - - { - var it = map.iterator(); - while (it.next()) |pair| { - if (mem.eql(u8, pair.key_ptr.*, "ZIG_PROGRESS")) switch (zig_progress_action) { - .add => unreachable, - .delete => continue, - .edit => { - envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "{s}={d}", .{ - pair.key_ptr.*, options.zig_progress_fd.?, - }, 0); - i += 1; - continue; - }, - .nothing => {}, - }; - - envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "{s}={s}", .{ pair.key_ptr.*, pair.value_ptr.* }, 0); - i += 1; - } - } +pub const ExecutablePathError = ExecutablePathBaseError || error{NameTooLong}; - assert(i == envp_count); - return envp_buf; +/// Get the path to the current executable, following symlinks. +/// +/// This function may return an error if the current executable +/// was deleted after spawning. +/// +/// Returned value is a slice of out_buffer. +/// +/// On Windows, the result is encoded as [WTF-8](https://wtf-8.codeberg.page/). +/// On other platforms, the result is an opaque sequence of bytes with no particular encoding. +/// +/// On Linux, depends on procfs being mounted. If the currently executing binary has +/// been deleted, the file path looks something like "/a/b/c/exe (deleted)". +/// +/// See also: +/// * `executableDirPath` - to obtain only the directory +/// * `openExecutable` - to obtain only an open file handle +pub fn executablePath(io: Io, out_buffer: []u8) ExecutablePathError!usize { + return io.vtable.processExecutablePath(io.userdata, out_buffer); } -/// Creates a null-delimited environment variable block in the format -/// expected by POSIX, from a hash map plus options. -pub fn createEnvironFromExisting( - arena: Allocator, - existing: [*:null]const ?[*:0]const u8, - options: CreateEnvironOptions, -) Allocator.Error![:null]?[*:0]u8 { - const existing_count, const contains_zig_progress = c: { - var count: usize = 0; - var contains = false; - while (existing[count]) |line| : (count += 1) { - contains = contains or mem.eql(u8, mem.sliceTo(line, '='), "ZIG_PROGRESS"); - } - break :c .{ count, contains }; - }; - const ZigProgressAction = enum { nothing, edit, delete, add }; - const zig_progress_action: ZigProgressAction = a: { - const fd = options.zig_progress_fd orelse break :a .nothing; - if (fd >= 0) { - break :a if (contains_zig_progress) .edit else .add; - } else { - if (contains_zig_progress) break :a .delete; - } - break :a .nothing; +/// Get the directory path that contains the current executable. +/// +/// Returns index into `out_buffer`. +/// +/// On Windows, the result is encoded as [WTF-8](https://wtf-8.codeberg.page/). +/// On other platforms, the result is an opaque sequence of bytes with no particular encoding. +pub fn executableDirPath(io: Io, out_buffer: []u8) ExecutablePathError!usize { + const n = try executablePath(io, out_buffer); + // Assert that the OS APIs return absolute paths, and therefore dirname + // will not return null. + return std.fs.path.dirname(out_buffer[0..n]).?.len; +} + +/// Same as `executableDirPath` except allocates the result. +pub fn executableDirPathAlloc(io: Io, allocator: Allocator) ExecutablePathAllocError![]u8 { + var buffer: [max_path_bytes]u8 = undefined; + const dir_path_len = executableDirPath(io, &buffer) catch |err| switch (err) { + error.NameTooLong => unreachable, + else => |e| return e, }; + return allocator.dupe(u8, buffer[0..dir_path_len]); +} - const envp_count: usize = c: { - var count: usize = existing_count; - switch (zig_progress_action) { - .add => count += 1, - .delete => count -= 1, - .nothing, .edit => {}, - } - break :c count; - }; +pub const OpenExecutableError = File.OpenError || ExecutablePathError || File.LockError; - const envp_buf = try arena.allocSentinel(?[*:0]u8, envp_count, null); - var i: usize = 0; - var existing_index: usize = 0; +pub fn openExecutable(io: Io, flags: File.OpenFlags) OpenExecutableError!File { + return io.vtable.processExecutableOpen(io.userdata, flags); +} - if (zig_progress_action == .add) { - envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?}, 0); - i += 1; - } +/// Causes abnormal process termination. +/// +/// If linking against libc, this calls `std.c.abort`. Otherwise it raises +/// SIGABRT followed by SIGKILL. +/// +/// Invokes the current signal handler for SIGABRT, if any. +pub fn abort() noreturn { + @branchHint(.cold); + // MSVCRT abort() sometimes opens a popup window which is undesirable, so + // even when linking libc on Windows we use our own abort implementation. + // See https://github.com/ziglang/zig/issues/2071 for more details. + if (native_os == .windows) { + if (builtin.mode == .Debug and windows.peb().BeingDebugged != 0) { + @breakpoint(); + } + windows.ntdll.RtlExitUserProcess(3); + } + if (!builtin.link_libc and native_os == .linux) { + // The Linux man page says that the libc abort() function + // "first unblocks the SIGABRT signal", but this is a footgun + // for user-defined signal handlers that want to restore some state in + // some program sections and crash in others. + // So, the user-installed SIGABRT handler is run, if present. + posix.raise(.ABRT) catch {}; + + // Disable all signal handlers. + const filledset = std.os.linux.sigfillset(); + posix.sigprocmask(posix.SIG.BLOCK, &filledset, null); + + // Only one thread may proceed to the rest of abort(). + if (!builtin.single_threaded) { + const global = struct { + var abort_entered: bool = false; + }; + while (@cmpxchgWeak(bool, &global.abort_entered, false, true, .seq_cst, .seq_cst)) |_| {} + } - while (existing[existing_index]) |line| : (existing_index += 1) { - if (mem.eql(u8, mem.sliceTo(line, '='), "ZIG_PROGRESS")) switch (zig_progress_action) { - .add => unreachable, - .delete => continue, - .edit => { - envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?}, 0); - i += 1; - continue; - }, - .nothing => {}, + // Install default handler so that the tkill below will terminate. + const sigact: posix.Sigaction = .{ + .handler = .{ .handler = posix.SIG.DFL }, + .mask = posix.sigemptyset(), + .flags = 0, }; - envp_buf[i] = try arena.dupeZ(u8, mem.span(line)); - i += 1; - } + posix.sigaction(.ABRT, &sigact, null); - assert(i == envp_count); - return envp_buf; -} + _ = std.os.linux.tkill(std.os.linux.gettid(), .ABRT); -pub fn createNullDelimitedEnvMap(arena: mem.Allocator, env_map: *const EnvMap) Allocator.Error![:null]?[*:0]u8 { - return createEnvironFromMap(arena, env_map, .{}); -} + var sigabrtmask = posix.sigemptyset(); + posix.sigaddset(&sigabrtmask, .ABRT); + posix.sigprocmask(posix.SIG.UNBLOCK, &sigabrtmask, null); -test createNullDelimitedEnvMap { - const allocator = testing.allocator; - var envmap = EnvMap.init(allocator); - defer envmap.deinit(); - - try envmap.put("HOME", "/home/ifreund"); - try envmap.put("WAYLAND_DISPLAY", "wayland-1"); - try envmap.put("DISPLAY", ":1"); - try envmap.put("DEBUGINFOD_URLS", " "); - try envmap.put("XCURSOR_SIZE", "24"); - - var arena = std.heap.ArenaAllocator.init(allocator); - defer arena.deinit(); - const environ = try createNullDelimitedEnvMap(arena.allocator(), &envmap); - - try testing.expectEqual(@as(usize, 5), environ.len); - - inline for (.{ - "HOME=/home/ifreund", - "WAYLAND_DISPLAY=wayland-1", - "DISPLAY=:1", - "DEBUGINFOD_URLS= ", - "XCURSOR_SIZE=24", - }) |target| { - for (environ) |variable| { - if (mem.eql(u8, mem.span(variable orelse continue), target)) break; - } else { - try testing.expect(false); // Environment variable not found - } + // Beyond this point should be unreachable. + @as(*allowzero volatile u8, @ptrFromInt(0)).* = 0; + posix.raise(.KILL) catch {}; + exit(127); // Pid 1 might not be signalled in some containers. + } + switch (native_os) { + .uefi, .wasi, .emscripten, .cuda, .amdhsa => @trap(), + else => posix.system.abort(), } } -/// Caller must free result. -pub fn createWindowsEnvBlock(allocator: mem.Allocator, env_map: *const EnvMap) ![]u16 { - // count bytes needed - const max_chars_needed = x: { - // Only need 2 trailing NUL code units for an empty environment - var max_chars_needed: usize = if (env_map.count() == 0) 2 else 1; - var it = env_map.iterator(); - while (it.next()) |pair| { - // +1 for '=' - // +1 for null byte - max_chars_needed += pair.key_ptr.len + pair.value_ptr.len + 2; - } - break :x max_chars_needed; - }; - const result = try allocator.alloc(u16, max_chars_needed); - errdefer allocator.free(result); - - var it = env_map.iterator(); - var i: usize = 0; - while (it.next()) |pair| { - i += try unicode.wtf8ToWtf16Le(result[i..], pair.key_ptr.*); - result[i] = '='; - i += 1; - i += try unicode.wtf8ToWtf16Le(result[i..], pair.value_ptr.*); - result[i] = 0; - i += 1; - } - result[i] = 0; - i += 1; - // An empty environment is a special case that requires a redundant - // NUL terminator. CreateProcess will read the second code unit even - // though theoretically the first should be enough to recognize that the - // environment is empty (see https://nullprogram.com/blog/2023/08/23/) - if (env_map.count() == 0) { - result[i] = 0; - i += 1; +/// Exits all threads of the program with the specified status code. +pub fn exit(status: u8) noreturn { + if (builtin.link_libc) { + std.c.exit(status); + } else switch (native_os) { + .windows => windows.ntdll.RtlExitUserProcess(status), + .wasi => std.os.wasi.proc_exit(status), + .linux => { + if (!builtin.single_threaded) std.os.linux.exit_group(status); + posix.system.exit(status); + }, + .uefi => { + const uefi = std.os.uefi; + // exit() is only available if exitBootServices() has not been called yet. + // This call to exit should not fail, so we catch-ignore errors. + if (uefi.system_table.boot_services) |bs| { + bs.exit(uefi.handle, @enumFromInt(status), null) catch {}; + } + // If we can't exit, reboot the system instead. + uefi.system_table.runtime_services.resetSystem(.cold, @enumFromInt(status), null); + }, + else => posix.system.exit(status), } - return try allocator.realloc(result, i); } -/// Logs an error and then terminates the process with exit code 1. -pub fn fatal(comptime format: []const u8, format_arguments: anytype) noreturn { - std.log.err(format, format_arguments); - exit(1); +pub const SetCurrentDirError = error{ + AccessDenied, + BadPathName, + FileNotFound, + FileSystem, + NameTooLong, + NoDevice, + NotDir, + OperationUnsupported, + UnrecognizedVolume, +} || Io.Cancelable || Io.UnexpectedError; + +/// Changes the current working directory to the open directory handle. +/// Corresponds to "fchdir" in libc. +/// +/// This modifies global process state and can have surprising effects in +/// multithreaded applications. Most applications and especially libraries +/// should not call this function as a general rule, however it can have use +/// cases in, for example, implementing a shell, or child process execution. +/// +/// Calling this function makes code less portable and less reusable. +pub fn setCurrentDir(io: Io, dir: Io.Dir) !void { + return io.vtable.processSetCurrentDir(io.userdata, dir); } diff --git a/lib/std/process/Args.zig b/lib/std/process/Args.zig new file mode 100644 index 000000000000..8e6caf2d651d --- /dev/null +++ b/lib/std/process/Args.zig @@ -0,0 +1,976 @@ +const Args = @This(); + +const builtin = @import("builtin"); +const native_os = builtin.os.tag; + +const std = @import("../std.zig"); +const Allocator = std.mem.Allocator; +const assert = std.debug.assert; +const testing = std.testing; + +vector: Vector, + +/// On WASI without libc, this is `void` because the environment has to be +/// queried and heap-allocated at runtime. +pub const Vector = switch (native_os) { + .windows => []const u16, // WTF-16 encoded + .wasi => switch (builtin.link_libc) { + false => void, + true => []const [*:0]const u8, + }, + .freestanding, .other => void, + else => []const [*:0]const u8, +}; + +/// Cross-platform access to command line one argument at a time. +pub const Iterator = struct { + const Inner = switch (native_os) { + .windows => Windows, + .wasi => if (builtin.link_libc) Posix else Wasi, + else => Posix, + }; + + inner: Inner, + + /// Initialize the args iterator. Consider using `initAllocator` instead + /// for cross-platform compatibility. + pub fn init(a: Args) Iterator { + if (native_os == .wasi) @compileError("In WASI, use initAllocator instead."); + if (native_os == .windows) @compileError("In Windows, use initAllocator instead."); + return .{ .inner = .init(a) }; + } + + pub const InitError = Inner.InitError; + + /// You must deinitialize iterator's internal buffers by calling `deinit` when done. + pub fn initAllocator(a: Args, gpa: Allocator) InitError!Iterator { + if (native_os == .wasi and !builtin.link_libc) { + return .{ .inner = try .init(gpa) }; + } + if (native_os == .windows) { + return .{ .inner = try .init(gpa, a.vector) }; + } + + return .{ .inner = .init(a) }; + } + + /// Return subsequent argument, or `null` if no more remaining. + /// + /// Returned slice is pointing to the iterator's internal buffer. + /// On Windows, the result is encoded as [WTF-8](https://wtf-8.codeberg.page/). + /// On other platforms, the result is an opaque sequence of bytes with no particular encoding. + pub fn next(it: *Iterator) ?[:0]const u8 { + return it.inner.next(); + } + + /// Parse past 1 argument without capturing it. + /// Returns `true` if skipped an arg, `false` if we are at the end. + pub fn skip(it: *Iterator) bool { + return it.inner.skip(); + } + + /// Required to release resources if the iterator was initialized with + /// `initAllocator` function. + pub fn deinit(it: *Iterator) void { + // Unless we're targeting WASI or Windows, this is a no-op. + if (native_os == .wasi and !builtin.link_libc) it.inner.deinit(); + if (native_os == .windows) it.inner.deinit(); + } + + /// Iterator that implements the Windows command-line parsing algorithm. + /// + /// The implementation is intended to be compatible with the post-2008 C runtime, + /// but is *not* intended to be compatible with `CommandLineToArgvW` since + /// `CommandLineToArgvW` uses the pre-2008 parsing rules. + /// + /// This iterator faithfully implements the parsing behavior observed from the C runtime with + /// one exception: if the command-line string is empty, the iterator will immediately complete + /// without returning any arguments (whereas the C runtime will return a single argument + /// representing the name of the current executable). + /// + /// The essential parts of the algorithm are described in Microsoft's documentation: + /// + /// - https://learn.microsoft.com/en-us/cpp/cpp/main-function-command-line-args?view=msvc-170#parsing-c-command-line-arguments + /// + /// David Deley explains some additional undocumented quirks in great detail: + /// + /// - https://daviddeley.com/autohotkey/parameters/parameters.htm#WINCRULES + pub const Windows = struct { + allocator: Allocator, + /// Encoded as WTF-16 LE. + cmd_line: []const u16, + index: usize = 0, + /// Owned by the iterator. Long enough to hold contiguous NUL-terminated slices + /// of each argument encoded as WTF-8. + buffer: []u8, + start: usize = 0, + end: usize = 0, + + pub const InitError = error{OutOfMemory}; + + /// `cmd_line_w` *must* be a WTF16-LE-encoded string. + /// + /// The iterator stores and uses `cmd_line_w`, so its memory must be valid for + /// at least as long as the returned Windows. + pub fn init(gpa: Allocator, cmd_line_w: []const u16) Windows.InitError!Windows { + const wtf8_len = std.unicode.calcWtf8Len(cmd_line_w); + + // This buffer must be large enough to contain contiguous NUL-terminated slices + // of each argument. + // - During parsing, the length of a parsed argument will always be equal to + // to less than its unparsed length + // - The first argument needs one extra byte of space allocated for its NUL + // terminator, but for each subsequent argument the necessary whitespace + // between arguments guarantees room for their NUL terminator(s). + const buffer = try gpa.alloc(u8, wtf8_len + 1); + errdefer gpa.free(buffer); + + return .{ + .allocator = gpa, + .cmd_line = cmd_line_w, + .buffer = buffer, + }; + } + + /// Returns the next argument and advances the iterator. Returns `null` if at the end of the + /// command-line string. The iterator owns the returned slice. + /// The result is encoded as [WTF-8](https://wtf-8.codeberg.page/). + pub fn next(self: *Windows) ?[:0]const u8 { + return self.nextWithStrategy(next_strategy); + } + + /// Skips the next argument and advances the iterator. Returns `true` if an argument was + /// skipped, `false` if at the end of the command-line string. + pub fn skip(self: *Windows) bool { + return self.nextWithStrategy(skip_strategy); + } + + const next_strategy = struct { + const T = ?[:0]const u8; + + const eof = null; + + /// Returns '\' if any backslashes are emitted, otherwise returns `last_emitted_code_unit`. + fn emitBackslashes(self: *Windows, count: usize, last_emitted_code_unit: ?u16) ?u16 { + for (0..count) |_| { + self.buffer[self.end] = '\\'; + self.end += 1; + } + return if (count != 0) '\\' else last_emitted_code_unit; + } + + /// If `last_emitted_code_unit` and `code_unit` form a surrogate pair, then + /// the previously emitted high surrogate is overwritten by the codepoint encoded + /// by the surrogate pair, and `null` is returned. + /// Otherwise, `code_unit` is emitted and returned. + fn emitCharacter(self: *Windows, code_unit: u16, last_emitted_code_unit: ?u16) ?u16 { + // Because we are emitting WTF-8, we need to + // check to see if we've emitted two consecutive surrogate + // codepoints that form a valid surrogate pair in order + // to ensure that we're always emitting well-formed WTF-8 + // (https://wtf-8.codeberg.page/#concatenating). + // + // If we do have a valid surrogate pair, we need to emit + // the UTF-8 sequence for the codepoint that they encode + // instead of the WTF-8 encoding for the two surrogate pairs + // separately. + // + // This is relevant when dealing with a WTF-16 encoded + // command line like this: + // "<0xD801>"<0xDC37> + // which would get parsed and converted to WTF-8 as: + // <0xED><0xA0><0x81><0xED><0xB0><0xB7> + // but instead, we need to recognize the surrogate pair + // and emit the codepoint it encodes, which in this + // example is U+10437 (𐐷), which is encoded in UTF-8 as: + // <0xF0><0x90><0x90><0xB7> + if (last_emitted_code_unit != null and + std.unicode.utf16IsLowSurrogate(code_unit) and + std.unicode.utf16IsHighSurrogate(last_emitted_code_unit.?)) + { + const codepoint = std.unicode.utf16DecodeSurrogatePair(&.{ last_emitted_code_unit.?, code_unit }) catch unreachable; + + // Unpaired surrogate is 3 bytes long + const dest = self.buffer[self.end - 3 ..]; + const len = std.unicode.utf8Encode(codepoint, dest) catch unreachable; + // All codepoints that require a surrogate pair (> U+FFFF) are encoded as 4 bytes + assert(len == 4); + self.end += 1; + return null; + } + + const wtf8_len = std.unicode.wtf8Encode(code_unit, self.buffer[self.end..]) catch unreachable; + self.end += wtf8_len; + return code_unit; + } + + fn yieldArg(self: *Windows) [:0]const u8 { + self.buffer[self.end] = 0; + const arg = self.buffer[self.start..self.end :0]; + self.end += 1; + self.start = self.end; + return arg; + } + }; + + const skip_strategy = struct { + const T = bool; + + const eof = false; + + fn emitBackslashes(_: *Windows, _: usize, last_emitted_code_unit: ?u16) ?u16 { + return last_emitted_code_unit; + } + + fn emitCharacter(_: *Windows, _: u16, last_emitted_code_unit: ?u16) ?u16 { + return last_emitted_code_unit; + } + + fn yieldArg(_: *Windows) bool { + return true; + } + }; + + fn nextWithStrategy(self: *Windows, comptime strategy: type) strategy.T { + var last_emitted_code_unit: ?u16 = null; + // The first argument (the executable name) uses different parsing rules. + if (self.index == 0) { + if (self.cmd_line.len == 0 or self.cmd_line[0] == 0) { + // Immediately complete the iterator. + // The C runtime would return the name of the current executable here. + return strategy.eof; + } + + var inside_quotes = false; + while (true) : (self.index += 1) { + const char = if (self.index != self.cmd_line.len) + std.mem.littleToNative(u16, self.cmd_line[self.index]) + else + 0; + switch (char) { + 0 => { + return strategy.yieldArg(self); + }, + '"' => { + inside_quotes = !inside_quotes; + }, + ' ', '\t' => { + if (inside_quotes) { + last_emitted_code_unit = strategy.emitCharacter(self, char, last_emitted_code_unit); + } else { + self.index += 1; + return strategy.yieldArg(self); + } + }, + else => { + last_emitted_code_unit = strategy.emitCharacter(self, char, last_emitted_code_unit); + }, + } + } + } + + // Skip spaces and tabs. The iterator completes if we reach the end of the string here. + while (true) : (self.index += 1) { + const char = if (self.index != self.cmd_line.len) + std.mem.littleToNative(u16, self.cmd_line[self.index]) + else + 0; + switch (char) { + 0 => return strategy.eof, + ' ', '\t' => continue, + else => break, + } + } + + // Parsing rules for subsequent arguments: + // + // - The end of the string always terminates the current argument. + // - When not in 'inside_quotes' mode, a space or tab terminates the current argument. + // - 2n backslashes followed by a quote emit n backslashes (note: n can be zero). + // If in 'inside_quotes' and the quote is immediately followed by a second quote, + // one quote is emitted and the other is skipped, otherwise, the quote is skipped + // and 'inside_quotes' is toggled. + // - 2n + 1 backslashes followed by a quote emit n backslashes followed by a quote. + // - n backslashes not followed by a quote emit n backslashes. + var backslash_count: usize = 0; + var inside_quotes = false; + while (true) : (self.index += 1) { + const char = if (self.index != self.cmd_line.len) + std.mem.littleToNative(u16, self.cmd_line[self.index]) + else + 0; + switch (char) { + 0 => { + last_emitted_code_unit = strategy.emitBackslashes(self, backslash_count, last_emitted_code_unit); + return strategy.yieldArg(self); + }, + ' ', '\t' => { + last_emitted_code_unit = strategy.emitBackslashes(self, backslash_count, last_emitted_code_unit); + backslash_count = 0; + if (inside_quotes) { + last_emitted_code_unit = strategy.emitCharacter(self, char, last_emitted_code_unit); + } else return strategy.yieldArg(self); + }, + '"' => { + const char_is_escaped_quote = backslash_count % 2 != 0; + last_emitted_code_unit = strategy.emitBackslashes(self, backslash_count / 2, last_emitted_code_unit); + backslash_count = 0; + if (char_is_escaped_quote) { + last_emitted_code_unit = strategy.emitCharacter(self, '"', last_emitted_code_unit); + } else { + if (inside_quotes and + self.index + 1 != self.cmd_line.len and + std.mem.littleToNative(u16, self.cmd_line[self.index + 1]) == '"') + { + last_emitted_code_unit = strategy.emitCharacter(self, '"', last_emitted_code_unit); + self.index += 1; + } else { + inside_quotes = !inside_quotes; + } + } + }, + '\\' => { + backslash_count += 1; + }, + else => { + last_emitted_code_unit = strategy.emitBackslashes(self, backslash_count, last_emitted_code_unit); + backslash_count = 0; + last_emitted_code_unit = strategy.emitCharacter(self, char, last_emitted_code_unit); + }, + } + } + } + + /// Frees the iterator's copy of the command-line string and all previously returned + /// argument slices. + pub fn deinit(self: *Windows) void { + self.allocator.free(self.buffer); + } + }; + + pub const Posix = struct { + remaining: Vector, + + pub const InitError = error{}; + + pub fn init(a: Args) Posix { + return .{ .remaining = a.vector }; + } + + pub fn next(it: *Posix) ?[:0]const u8 { + if (it.remaining.len == 0) return null; + const arg = it.remaining[0]; + it.remaining = it.remaining[1..]; + return std.mem.sliceTo(arg, 0); + } + + pub fn skip(it: *Posix) bool { + if (it.remaining.len == 0) return false; + it.remaining = it.remaining[1..]; + return true; + } + }; + + pub const Wasi = struct { + allocator: Allocator, + index: usize, + args: [][:0]u8, + + pub const InitError = error{OutOfMemory} || std.posix.UnexpectedError; + + /// You must call deinit to free the internal buffer of the + /// iterator after you are done. + pub fn init(allocator: Allocator) Wasi.InitError!Wasi { + const fetched_args = try Wasi.internalInit(allocator); + return Wasi{ + .allocator = allocator, + .index = 0, + .args = fetched_args, + }; + } + + fn internalInit(allocator: Allocator) Wasi.InitError![][:0]u8 { + var count: usize = undefined; + var buf_size: usize = undefined; + + switch (std.os.wasi.args_sizes_get(&count, &buf_size)) { + .SUCCESS => {}, + else => |err| return std.posix.unexpectedErrno(err), + } + + if (count == 0) { + return &[_][:0]u8{}; + } + + const argv = try allocator.alloc([*:0]u8, count); + defer allocator.free(argv); + + const argv_buf = try allocator.alloc(u8, buf_size); + + switch (std.os.wasi.args_get(argv.ptr, argv_buf.ptr)) { + .SUCCESS => {}, + else => |err| return std.posix.unexpectedErrno(err), + } + + var result_args = try allocator.alloc([:0]u8, count); + var i: usize = 0; + while (i < count) : (i += 1) { + result_args[i] = std.mem.sliceTo(argv[i], 0); + } + + return result_args; + } + + pub fn next(self: *Wasi) ?[:0]const u8 { + if (self.index == self.args.len) return null; + + const arg = self.args[self.index]; + self.index += 1; + return arg; + } + + pub fn skip(self: *Wasi) bool { + if (self.index == self.args.len) return false; + + self.index += 1; + return true; + } + + /// Call to free the internal buffer of the iterator. + pub fn deinit(self: *Wasi) void { + // Nothing is allocated when there are no args + if (self.args.len == 0) return; + + const last_item = self.args[self.args.len - 1]; + const last_byte_addr = @intFromPtr(last_item.ptr) + last_item.len + 1; // null terminated + const first_item_ptr = self.args[0].ptr; + const len = last_byte_addr - @intFromPtr(first_item_ptr); + self.allocator.free(first_item_ptr[0..len]); + self.allocator.free(self.args); + } + }; +}; + +/// Holds the command-line arguments, with the program name as the first entry. +/// Use `iterateAllocator` for cross-platform code. +pub fn iterate(a: Args) Iterator { + return .init(a); +} + +/// You must deinitialize iterator's internal buffers by calling `deinit` when +/// done. +pub fn iterateAllocator(a: Args, gpa: Allocator) Iterator.InitError!Iterator { + return .initAllocator(a, gpa); +} + +pub const ToSliceError = Iterator.Windows.InitError || Iterator.Wasi.InitError; + +/// Returned value may reference several allocations and may point into `a`. +/// Thefore, an arena-style allocator must be used. +/// +/// * On Windows, the result is encoded as +/// [WTF-8](https://wtf-8.codeberg.page/). +/// * On other platforms, the result is an opaque sequence of bytes with no +/// particular encoding. +/// +/// See also: +/// * `iterate` +/// * `iterateAllocator` +pub fn toSlice(a: Args, arena: Allocator) ToSliceError![]const [:0]const u8 { + if (native_os == .windows) { + var it = try a.iterateAllocator(arena); + var contents: std.ArrayList(u8) = .empty; + var slice_list: std.ArrayList(usize) = .empty; + while (it.next()) |arg| { + try contents.appendSlice(arena, arg[0 .. arg.len + 1]); + try slice_list.append(arena, arg.len); + } + const contents_slice = contents.items; + const slice_sizes = slice_list.items; + const slice_list_bytes = std.math.mul(usize, @sizeOf([]u8), slice_sizes.len) catch return error.OutOfMemory; + const total_bytes = std.math.add(usize, slice_list_bytes, contents_slice.len) catch return error.OutOfMemory; + const buf = try arena.alignedAlloc(u8, .of([]u8), total_bytes); + errdefer arena.free(buf); + + const result_slice_list = std.mem.bytesAsSlice([:0]u8, buf[0..slice_list_bytes]); + const result_contents = buf[slice_list_bytes..]; + @memcpy(result_contents[0..contents_slice.len], contents_slice); + + var contents_index: usize = 0; + for (slice_sizes, 0..) |len, i| { + const new_index = contents_index + len; + result_slice_list[i] = result_contents[contents_index..new_index :0]; + contents_index = new_index + 1; + } + + return result_slice_list; + } else if (native_os == .wasi and !builtin.link_libc) { + var count: usize = undefined; + var buf_size: usize = undefined; + + switch (std.os.wasi.args_sizes_get(&count, &buf_size)) { + .SUCCESS => {}, + else => |err| return std.posix.unexpectedErrno(err), + } + + if (count == 0) return &.{}; + + const argv = try arena.alloc([*:0]u8, count); + const argv_buf = try arena.alloc(u8, buf_size); + + switch (std.os.wasi.args_get(argv.ptr, argv_buf.ptr)) { + .SUCCESS => {}, + else => |err| return std.posix.unexpectedErrno(err), + } + + const args = try arena.alloc([:0]const u8, count); + for (args, argv) |*dst, src| dst.* = std.mem.sliceTo(src, 0); + return args; + } else { + const args = try arena.alloc([:0]const u8, a.vector.len); + for (args, a.vector) |*dst, src| dst.* = std.mem.sliceTo(src, 0); + return args; + } +} + +test "Iterator.Windows" { + const t = testIteratorWindows; + + try t( + \\"C:\Program Files\zig\zig.exe" run .\src\main.zig -target x86_64-windows-gnu -O ReleaseSafe -- --emoji=🗿 --eval="new Regex(\"Dwayne \\\"The Rock\\\" Johnson\")" + , &.{ + \\C:\Program Files\zig\zig.exe + , + \\run + , + \\.\src\main.zig + , + \\-target + , + \\x86_64-windows-gnu + , + \\-O + , + \\ReleaseSafe + , + \\-- + , + \\--emoji=🗿 + , + \\--eval=new Regex("Dwayne \"The Rock\" Johnson") + , + }); + + // Empty + try t("", &.{}); + + // Separators + try t("aa bb cc", &.{ "aa", "bb", "cc" }); + try t("aa\tbb\tcc", &.{ "aa", "bb", "cc" }); + try t("aa\nbb\ncc", &.{"aa\nbb\ncc"}); + try t("aa\r\nbb\r\ncc", &.{"aa\r\nbb\r\ncc"}); + try t("aa\rbb\rcc", &.{"aa\rbb\rcc"}); + try t("aa\x07bb\x07cc", &.{"aa\x07bb\x07cc"}); + try t("aa\x7Fbb\x7Fcc", &.{"aa\x7Fbb\x7Fcc"}); + try t("aa🦎bb🦎cc", &.{"aa🦎bb🦎cc"}); + + // Leading/trailing whitespace + try t(" ", &.{""}); + try t(" aa bb ", &.{ "", "aa", "bb" }); + try t("\t\t", &.{""}); + try t("\t\taa\t\tbb\t\t", &.{ "", "aa", "bb" }); + try t("\n\n", &.{"\n\n"}); + try t("\n\naa\n\nbb\n\n", &.{"\n\naa\n\nbb\n\n"}); + + // Executable name with quotes/backslashes + try t("\"aa bb\tcc\ndd\"", &.{"aa bb\tcc\ndd"}); + try t("\"", &.{""}); + try t("\"\"", &.{""}); + try t("\"\"\"", &.{""}); + try t("\"\"\"\"", &.{""}); + try t("\"\"\"\"\"", &.{""}); + try t("aa\"bb\"cc\"dd", &.{"aabbccdd"}); + try t("aa\"bb cc\"dd", &.{"aabb ccdd"}); + try t("\"aa\\\"bb\"", &.{"aa\\bb"}); + try t("\"aa\\\\\"", &.{"aa\\\\"}); + try t("aa\\\"bb", &.{"aa\\bb"}); + try t("aa\\\\\"bb", &.{"aa\\\\bb"}); + + // Arguments with quotes/backslashes + try t(". \"aa bb\tcc\ndd\"", &.{ ".", "aa bb\tcc\ndd" }); + try t(". aa\" \"bb\"\t\"cc\"\n\"dd\"", &.{ ".", "aa bb\tcc\ndd" }); + try t(". ", &.{"."}); + try t(". \"", &.{ ".", "" }); + try t(". \"\"", &.{ ".", "" }); + try t(". \"\"\"", &.{ ".", "\"" }); + try t(". \"\"\"\"", &.{ ".", "\"" }); + try t(". \"\"\"\"\"", &.{ ".", "\"\"" }); + try t(". \"\"\"\"\"\"", &.{ ".", "\"\"" }); + try t(". \" \"", &.{ ".", " " }); + try t(". \" \"\"", &.{ ".", " \"" }); + try t(". \" \"\"\"", &.{ ".", " \"" }); + try t(". \" \"\"\"\"", &.{ ".", " \"\"" }); + try t(". \" \"\"\"\"\"", &.{ ".", " \"\"" }); + try t(". \" \"\"\"\"\"\"", &.{ ".", " \"\"\"" }); + try t(". \\\"", &.{ ".", "\"" }); + try t(". \\\"\"", &.{ ".", "\"" }); + try t(". \\\"\"\"", &.{ ".", "\"" }); + try t(". \\\"\"\"\"", &.{ ".", "\"\"" }); + try t(". \\\"\"\"\"\"", &.{ ".", "\"\"" }); + try t(". \\\"\"\"\"\"\"", &.{ ".", "\"\"\"" }); + try t(". \" \\\"", &.{ ".", " \"" }); + try t(". \" \\\"\"", &.{ ".", " \"" }); + try t(". \" \\\"\"\"", &.{ ".", " \"\"" }); + try t(". \" \\\"\"\"\"", &.{ ".", " \"\"" }); + try t(". \" \\\"\"\"\"\"", &.{ ".", " \"\"\"" }); + try t(". \" \\\"\"\"\"\"\"", &.{ ".", " \"\"\"" }); + try t(". aa\\bb\\\\cc\\\\\\dd", &.{ ".", "aa\\bb\\\\cc\\\\\\dd" }); + try t(". \\\\\\\"aa bb\"", &.{ ".", "\\\"aa", "bb" }); + try t(". \\\\\\\\\"aa bb\"", &.{ ".", "\\\\aa bb" }); + + // From https://learn.microsoft.com/en-us/cpp/cpp/main-function-command-line-args#results-of-parsing-command-lines + try t( + \\foo.exe "abc" d e + , &.{ "foo.exe", "abc", "d", "e" }); + try t( + \\foo.exe a\\b d"e f"g h + , &.{ "foo.exe", "a\\\\b", "de fg", "h" }); + try t( + \\foo.exe a\\\"b c d + , &.{ "foo.exe", "a\\\"b", "c", "d" }); + try t( + \\foo.exe a\\\\"b c" d e + , &.{ "foo.exe", "a\\\\b c", "d", "e" }); + try t( + \\foo.exe a"b"" c d + , &.{ "foo.exe", "ab\" c d" }); + + // From https://daviddeley.com/autohotkey/parameters/parameters.htm#WINCRULESEX + try t("foo.exe CallMeIshmael", &.{ "foo.exe", "CallMeIshmael" }); + try t("foo.exe \"Call Me Ishmael\"", &.{ "foo.exe", "Call Me Ishmael" }); + try t("foo.exe Cal\"l Me I\"shmael", &.{ "foo.exe", "Call Me Ishmael" }); + try t("foo.exe CallMe\\\"Ishmael", &.{ "foo.exe", "CallMe\"Ishmael" }); + try t("foo.exe \"CallMe\\\"Ishmael\"", &.{ "foo.exe", "CallMe\"Ishmael" }); + try t("foo.exe \"Call Me Ishmael\\\\\"", &.{ "foo.exe", "Call Me Ishmael\\" }); + try t("foo.exe \"CallMe\\\\\\\"Ishmael\"", &.{ "foo.exe", "CallMe\\\"Ishmael" }); + try t("foo.exe a\\\\\\b", &.{ "foo.exe", "a\\\\\\b" }); + try t("foo.exe \"a\\\\\\b\"", &.{ "foo.exe", "a\\\\\\b" }); + + // Surrogate pair encoding of 𐐷 separated by quotes. + // Encoded as WTF-16: + // "<0xD801>"<0xDC37> + // Encoded as WTF-8: + // "<0xED><0xA0><0x81>"<0xED><0xB0><0xB7> + // During parsing, the quotes drop out and the surrogate pair + // should end up encoded as its normal UTF-8 representation. + try t("foo.exe \"\xed\xa0\x81\"\xed\xb0\xb7", &.{ "foo.exe", "𐐷" }); +} + +fn testIteratorWindows(cmd_line: []const u8, expected_args: []const []const u8) !void { + const cmd_line_w = try std.unicode.wtf8ToWtf16LeAllocZ(testing.allocator, cmd_line); + defer testing.allocator.free(cmd_line_w); + + // next + { + var it = try Iterator.Windows.init(testing.allocator, cmd_line_w); + defer it.deinit(); + + for (expected_args) |expected| { + if (it.next()) |actual| { + try testing.expectEqualStrings(expected, actual); + } else { + return error.TestUnexpectedResult; + } + } + try testing.expect(it.next() == null); + } + + // skip + { + var it = try Iterator.Windows.init(testing.allocator, cmd_line_w); + defer it.deinit(); + + for (0..expected_args.len) |_| { + try testing.expect(it.skip()); + } + try testing.expect(!it.skip()); + } +} + +test "general parsing" { + try testGeneralCmdLine("a b\tc d", &.{ "a", "b", "c", "d" }); + try testGeneralCmdLine("\"abc\" d e", &.{ "abc", "d", "e" }); + try testGeneralCmdLine("a\\\\\\b d\"e f\"g h", &.{ "a\\\\\\b", "de fg", "h" }); + try testGeneralCmdLine("a\\\\\\\"b c d", &.{ "a\\\"b", "c", "d" }); + try testGeneralCmdLine("a\\\\\\\\\"b c\" d e", &.{ "a\\\\b c", "d", "e" }); + try testGeneralCmdLine("a b\tc \"d f", &.{ "a", "b", "c", "d f" }); + try testGeneralCmdLine("j k l\\", &.{ "j", "k", "l\\" }); + try testGeneralCmdLine("\"\" x y z\\\\", &.{ "", "x", "y", "z\\\\" }); + + try testGeneralCmdLine("\".\\..\\zig-cache\\build\" \"bin\\zig.exe\" \".\\..\" \".\\..\\zig-cache\" \"--help\"", &.{ + ".\\..\\zig-cache\\build", + "bin\\zig.exe", + ".\\..", + ".\\..\\zig-cache", + "--help", + }); + + try testGeneralCmdLine( + \\ 'foo' "bar" + , &.{ "'foo'", "bar" }); +} + +fn testGeneralCmdLine(input_cmd_line: []const u8, expected_args: []const []const u8) !void { + var it = try IteratorGeneral(.{}).init(std.testing.allocator, input_cmd_line); + defer it.deinit(); + for (expected_args) |expected_arg| { + const arg = it.next().?; + try testing.expectEqualStrings(expected_arg, arg); + } + try testing.expect(it.next() == null); +} + +/// Optional parameters for `IteratorGeneral` +pub const IteratorGeneralOptions = struct { + comments: bool = false, + single_quotes: bool = false, +}; + +/// A general Iterator to parse a string into a set of arguments +pub fn IteratorGeneral(comptime options: IteratorGeneralOptions) type { + return struct { + allocator: Allocator, + index: usize = 0, + cmd_line: []const u8, + + /// Should the cmd_line field be free'd (using the allocator) on deinit()? + free_cmd_line_on_deinit: bool, + + /// buffer MUST be long enough to hold the cmd_line plus a null terminator. + /// buffer will we free'd (using the allocator) on deinit() + buffer: []u8, + start: usize = 0, + end: usize = 0, + + pub const Self = @This(); + + pub const InitError = error{OutOfMemory}; + + /// cmd_line_utf8 MUST remain valid and constant while using this instance + pub fn init(allocator: Allocator, cmd_line_utf8: []const u8) InitError!Self { + const buffer = try allocator.alloc(u8, cmd_line_utf8.len + 1); + errdefer allocator.free(buffer); + + return Self{ + .allocator = allocator, + .cmd_line = cmd_line_utf8, + .free_cmd_line_on_deinit = false, + .buffer = buffer, + }; + } + + /// cmd_line_utf8 will be free'd (with the allocator) on deinit() + pub fn initTakeOwnership(allocator: Allocator, cmd_line_utf8: []const u8) InitError!Self { + const buffer = try allocator.alloc(u8, cmd_line_utf8.len + 1); + errdefer allocator.free(buffer); + + return Self{ + .allocator = allocator, + .cmd_line = cmd_line_utf8, + .free_cmd_line_on_deinit = true, + .buffer = buffer, + }; + } + + // Skips over whitespace in the cmd_line. + // Returns false if the terminating sentinel is reached, true otherwise. + // Also skips over comments (if supported). + fn skipWhitespace(self: *Self) bool { + while (true) : (self.index += 1) { + const character = if (self.index != self.cmd_line.len) self.cmd_line[self.index] else 0; + switch (character) { + 0 => return false, + ' ', '\t', '\r', '\n' => continue, + '#' => { + if (options.comments) { + while (true) : (self.index += 1) { + switch (self.cmd_line[self.index]) { + '\n' => break, + 0 => return false, + else => continue, + } + } + continue; + } else { + break; + } + }, + else => break, + } + } + return true; + } + + pub fn skip(self: *Self) bool { + if (!self.skipWhitespace()) { + return false; + } + + var backslash_count: usize = 0; + var in_quote = false; + while (true) : (self.index += 1) { + const character = if (self.index != self.cmd_line.len) self.cmd_line[self.index] else 0; + switch (character) { + 0 => return true, + '"', '\'' => { + if (!options.single_quotes and character == '\'') { + backslash_count = 0; + continue; + } + const quote_is_real = backslash_count % 2 == 0; + if (quote_is_real) { + in_quote = !in_quote; + } + }, + '\\' => { + backslash_count += 1; + }, + ' ', '\t', '\r', '\n' => { + if (!in_quote) { + return true; + } + backslash_count = 0; + }, + else => { + backslash_count = 0; + continue; + }, + } + } + } + + /// Returns a slice of the internal buffer that contains the next argument. + /// Returns null when it reaches the end. + pub fn next(self: *Self) ?[:0]const u8 { + if (!self.skipWhitespace()) { + return null; + } + + var backslash_count: usize = 0; + var in_quote = false; + while (true) : (self.index += 1) { + const character = if (self.index != self.cmd_line.len) self.cmd_line[self.index] else 0; + switch (character) { + 0 => { + self.emitBackslashes(backslash_count); + self.buffer[self.end] = 0; + const token = self.buffer[self.start..self.end :0]; + self.end += 1; + self.start = self.end; + return token; + }, + '"', '\'' => { + if (!options.single_quotes and character == '\'') { + self.emitBackslashes(backslash_count); + backslash_count = 0; + self.emitCharacter(character); + continue; + } + const quote_is_real = backslash_count % 2 == 0; + self.emitBackslashes(backslash_count / 2); + backslash_count = 0; + + if (quote_is_real) { + in_quote = !in_quote; + } else { + self.emitCharacter('"'); + } + }, + '\\' => { + backslash_count += 1; + }, + ' ', '\t', '\r', '\n' => { + self.emitBackslashes(backslash_count); + backslash_count = 0; + if (in_quote) { + self.emitCharacter(character); + } else { + self.buffer[self.end] = 0; + const token = self.buffer[self.start..self.end :0]; + self.end += 1; + self.start = self.end; + return token; + } + }, + else => { + self.emitBackslashes(backslash_count); + backslash_count = 0; + self.emitCharacter(character); + }, + } + } + } + + fn emitBackslashes(self: *Self, emit_count: usize) void { + var i: usize = 0; + while (i < emit_count) : (i += 1) { + self.emitCharacter('\\'); + } + } + + fn emitCharacter(self: *Self, char: u8) void { + self.buffer[self.end] = char; + self.end += 1; + } + + /// Call to free the internal buffer of the iterator. + pub fn deinit(self: *Self) void { + self.allocator.free(self.buffer); + + if (self.free_cmd_line_on_deinit) { + self.allocator.free(self.cmd_line); + } + } + }; +} + +test "response file arg parsing" { + try testResponseFileCmdLine( + \\a b + \\c d\ + , &.{ "a", "b", "c", "d\\" }); + try testResponseFileCmdLine("a b c d\\", &.{ "a", "b", "c", "d\\" }); + + try testResponseFileCmdLine( + \\j + \\ k l # this is a comment \\ \\\ \\\\ "none" "\\" "\\\" + \\ "m" #another comment + \\ + , &.{ "j", "k", "l", "m" }); + + try testResponseFileCmdLine( + \\ "" q "" + \\ "r s # t" "u\" v" #another comment + \\ + , &.{ "", "q", "", "r s # t", "u\" v" }); + + try testResponseFileCmdLine( + \\ -l"advapi32" a# b#c d# + \\e\\\ + , &.{ "-ladvapi32", "a#", "b#c", "d#", "e\\\\\\" }); + + try testResponseFileCmdLine( + \\ 'foo' "bar" + , &.{ "foo", "bar" }); +} + +fn testResponseFileCmdLine(input_cmd_line: []const u8, expected_args: []const []const u8) !void { + var it = try IteratorGeneral(.{ .comments = true, .single_quotes = true }) + .init(std.testing.allocator, input_cmd_line); + defer it.deinit(); + for (expected_args) |expected_arg| { + const arg = it.next().?; + try testing.expectEqualStrings(expected_arg, arg); + } + try testing.expect(it.next() == null); +} diff --git a/lib/std/process/Child.zig b/lib/std/process/Child.zig index da8d803d6056..17e15f208da5 100644 --- a/lib/std/process/Child.zig +++ b/lib/std/process/Child.zig @@ -1,119 +1,42 @@ -const ChildProcess = @This(); +const Child = @This(); const builtin = @import("builtin"); const native_os = builtin.os.tag; const std = @import("../std.zig"); -const unicode = std.unicode; -const fs = std.fs; +const Io = std.Io; const process = std.process; -const File = std.fs.File; -const windows = std.os.windows; -const linux = std.os.linux; -const posix = std.posix; -const mem = std.mem; -const EnvMap = std.process.EnvMap; -const maxInt = std.math.maxInt; +const File = std.Io.File; const assert = std.debug.assert; const Allocator = std.mem.Allocator; const ArrayList = std.ArrayList; pub const Id = switch (native_os) { - .windows => windows.HANDLE, + .windows => std.os.windows.HANDLE, .wasi => void, - else => posix.pid_t, + else => std.posix.pid_t, }; -/// Available after calling `spawn()`. This becomes `undefined` after calling `wait()`. +/// After `wait` or `kill` is called, this becomes `null`. /// On Windows this is the hProcess. /// On POSIX this is the pid. -id: Id, -thread_handle: if (native_os == .windows) windows.HANDLE else void, - -allocator: mem.Allocator, - +id: ?Id, +thread_handle: if (native_os == .windows) std.os.windows.HANDLE else void, /// The writing end of the child process's standard input pipe. -/// Usage requires `stdin_behavior == StdIo.Pipe`. -/// Available after calling `spawn()`. +/// Usage requires `process.SpawnOptions.StdIo.pipe`. stdin: ?File, - /// The reading end of the child process's standard output pipe. -/// Usage requires `stdout_behavior == StdIo.Pipe`. -/// Available after calling `spawn()`. +/// Usage requires `process.SpawnOptions.StdIo.pipe`. stdout: ?File, - /// The reading end of the child process's standard error pipe. -/// Usage requires `stderr_behavior == StdIo.Pipe`. -/// Available after calling `spawn()`. +/// Usage requires `process.SpawnOptions.StdIo.pipe`. stderr: ?File, - -/// Terminated state of the child process. -/// Available after calling `wait()`. -term: ?(SpawnError!Term), - -argv: []const []const u8, - -/// Leave as null to use the current env map using the supplied allocator. -/// Required if unable to access the current env map (e.g. building a library on -/// some platforms). -env_map: ?*const EnvMap, - -stdin_behavior: StdIo, -stdout_behavior: StdIo, -stderr_behavior: StdIo, - -/// Set to change the user id when spawning the child process. -uid: if (native_os == .windows or native_os == .wasi) void else ?posix.uid_t, - -/// Set to change the group id when spawning the child process. -gid: if (native_os == .windows or native_os == .wasi) void else ?posix.gid_t, - -/// Set to change the process group id when spawning the child process. -pgid: if (native_os == .windows or native_os == .wasi) void else ?posix.pid_t, - -/// Set to change the current working directory when spawning the child process. -cwd: ?[]const u8, -/// Set to change the current working directory when spawning the child process. -/// This is not yet implemented for Windows. See https://github.com/ziglang/zig/issues/5190 -/// Once that is done, `cwd` will be deprecated in favor of this field. -cwd_dir: ?fs.Dir = null, - -err_pipe: if (native_os == .windows) void else ?posix.fd_t, - -expand_arg0: Arg0Expand, - -/// Darwin-only. Disable ASLR for the child process. -disable_aslr: bool = false, - -/// Start child process in suspended state. -/// For Posix systems it's started as if SIGSTOP was sent. -start_suspended: bool = false, - -/// Windows-only. Sets the CREATE_NO_WINDOW flag in CreateProcess. -create_no_window: bool = false, - -/// Set to true to obtain rusage information for the child process. -/// Depending on the target platform and implementation status, the -/// requested statistics may or may not be available. If they are -/// available, then the `resource_usage_statistics` field will be populated -/// after calling `wait`. -/// On Linux and Darwin, this obtains rusage statistics from wait4(). -request_resource_usage_statistics: bool = false, - /// This is available after calling wait if /// `request_resource_usage_statistics` was set to `true` before calling /// `spawn`. +/// TODO move this data into `Term` resource_usage_statistics: ResourceUsageStatistics = .{}, - -/// When populated, a pipe will be created for the child process to -/// communicate progress back to the parent. The file descriptor of the -/// write end of the pipe will be specified in the `ZIG_PROGRESS` -/// environment variable inside the child process. The progress reported by -/// the child will be attached to this progress node in the parent process. -/// -/// The child's progress tree will be grafted into the parent's progress tree, -/// by substituting this node with the child's root node. -progress_node: std.Progress.Node = std.Progress.Node.none, +request_resource_usage_statistics: bool, pub const ResourceUsageStatistics = struct { rusage: @TypeOf(rusage_init) = rusage_init, @@ -122,7 +45,7 @@ pub const ResourceUsageStatistics = struct { /// if available. pub inline fn getMaxRss(rus: ResourceUsageStatistics) ?usize { switch (native_os) { - .linux => { + .dragonfly, .freebsd, .netbsd, .openbsd, .illumos, .linux, .serenity => { if (rus.rusage) |ru| { return @as(usize, @intCast(ru.maxrss)) * 1024; } else { @@ -149,233 +72,74 @@ pub const ResourceUsageStatistics = struct { } const rusage_init = switch (native_os) { - .linux, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => @as(?posix.rusage, null), - .windows => @as(?windows.VM_COUNTERS, null), + .dragonfly, + .freebsd, + .netbsd, + .openbsd, + .illumos, + .linux, + .serenity, + .driverkit, + .ios, + .maccatalyst, + .macos, + .tvos, + .visionos, + .watchos, + => @as(?std.posix.rusage, null), + .windows => @as(?std.os.windows.VM_COUNTERS, null), else => {}, }; }; -pub const Arg0Expand = posix.Arg0Expand; - -pub const SpawnError = error{ - OutOfMemory, - - /// POSIX-only. `StdIo.Ignore` was selected and opening `/dev/null` returned ENODEV. - NoDevice, - - /// Windows-only. `cwd` or `argv` was provided and it was invalid WTF-8. - /// https://wtf-8.codeberg.page/ - InvalidWtf8, - - /// Windows-only. `cwd` was provided, but the path did not exist when spawning the child process. - CurrentWorkingDirectoryUnlinked, - - /// Windows-only. NUL (U+0000), LF (U+000A), CR (U+000D) are not allowed - /// within arguments when executing a `.bat`/`.cmd` script. - /// - NUL/LF signifiies end of arguments, so anything afterwards - /// would be lost after execution. - /// - CR is stripped by `cmd.exe`, so any CR codepoints - /// would be lost after execution. - InvalidBatchScriptArg, -} || - posix.ExecveError || - posix.SetIdError || - posix.SetPgidError || - posix.ChangeCurDirError || - windows.CreateProcessError || - windows.GetProcessMemoryInfoError || - windows.WaitForSingleObjectError; - pub const Term = union(enum) { - Exited: u8, - Signal: u32, - Stopped: u32, - Unknown: u32, -}; - -/// Behavior of the child process's standard input, output, and error -/// streams. -pub const StdIo = enum { - /// Inherit the stream from the parent process. - Inherit, - - /// Pass a null stream to the child process. - /// This is /dev/null on POSIX and NUL on Windows. - Ignore, - - /// Create a pipe for the stream. - /// The corresponding field (`stdout`, `stderr`, or `stdin`) - /// will be assigned a `File` object that can be used - /// to read from or write to the pipe. - Pipe, - - /// Close the stream after the child process spawns. - Close, + exited: u8, + signal: std.posix.SIG, + stopped: u32, + unknown: u32, }; -/// First argument in argv is the executable. -pub fn init(argv: []const []const u8, allocator: mem.Allocator) ChildProcess { - return .{ - .allocator = allocator, - .argv = argv, - .id = undefined, - .thread_handle = undefined, - .err_pipe = if (native_os == .windows) {} else null, - .term = null, - .env_map = null, - .cwd = null, - .uid = if (native_os == .windows or native_os == .wasi) {} else null, - .gid = if (native_os == .windows or native_os == .wasi) {} else null, - .pgid = if (native_os == .windows or native_os == .wasi) {} else null, - .stdin = null, - .stdout = null, - .stderr = null, - .stdin_behavior = .Inherit, - .stdout_behavior = .Inherit, - .stderr_behavior = .Inherit, - .expand_arg0 = .no_expand, - }; -} - -pub fn setUserName(self: *ChildProcess, name: []const u8) !void { - const user_info = try process.getUserInfo(name); - self.uid = user_info.uid; - self.gid = user_info.gid; -} - -/// On success must call `kill` or `wait`. -/// After spawning the `id` is available. -pub fn spawn(self: *ChildProcess) SpawnError!void { - if (!process.can_spawn) { - @compileError("the target operating system cannot spawn processes"); - } - - if (native_os == .windows) { - return self.spawnWindows(); - } else { - return self.spawnPosix(); - } -} - -pub fn spawnAndWait(self: *ChildProcess) SpawnError!Term { - try self.spawn(); - return self.wait(); -} - -/// Forcibly terminates child process and then cleans up all resources. -pub fn kill(self: *ChildProcess) !Term { - if (native_os == .windows) { - return self.killWindows(1); - } else { - return self.killPosix(); - } -} - -pub fn killWindows(self: *ChildProcess, exit_code: windows.UINT) !Term { - if (self.term) |term| { - self.cleanupStreams(); - return term; - } - - windows.TerminateProcess(self.id, exit_code) catch |err| switch (err) { - error.AccessDenied => { - // Usually when TerminateProcess triggers a ACCESS_DENIED error, it - // indicates that the process has already exited, but there may be - // some rare edge cases where our process handle no longer has the - // PROCESS_TERMINATE access right, so let's do another check to make - // sure the process is really no longer running: - windows.WaitForSingleObjectEx(self.id, 0, false) catch return err; - return error.AlreadyTerminated; - }, - else => return err, - }; - try self.waitUnwrappedWindows(); - return self.term.?; -} - -pub fn killPosix(self: *ChildProcess) !Term { - if (self.term) |term| { - self.cleanupStreams(); - return term; - } - posix.kill(self.id, posix.SIG.TERM) catch |err| switch (err) { - error.ProcessNotFound => return error.AlreadyTerminated, - else => return err, - }; - self.waitUnwrappedPosix(); - return self.term.?; -} - -pub const WaitError = SpawnError || std.os.windows.GetProcessMemoryInfoError; - -/// On some targets, `spawn` may not report all spawn errors, such as `error.InvalidExe`. -/// This function will block until any spawn errors can be reported, and return them. -pub fn waitForSpawn(self: *ChildProcess) SpawnError!void { - if (native_os == .windows) return; // `spawn` reports everything - if (self.term) |term| { - _ = term catch |spawn_err| return spawn_err; +/// Requests for the operating system to forcibly terminate the child process, +/// then blocks until it terminates, then cleans up all resources. +/// +/// Idempotent and does nothing after `wait` returns. +/// +/// Uncancelable. Ignores unexpected errors from the operating system. +pub fn kill(child: *Child, io: Io) void { + if (child.id == null) { + assert(child.stdin == null); + assert(child.stdout == null); + assert(child.stderr == null); return; } - - const err_pipe = self.err_pipe orelse return; - self.err_pipe = null; - // Wait for the child to report any errors in or before `execvpe`. - const report = readIntFd(err_pipe); - posix.close(err_pipe); - if (report) |child_err_int| { - const child_err: SpawnError = @errorCast(@errorFromInt(child_err_int)); - self.term = child_err; - return child_err; - } else |read_err| switch (read_err) { - error.EndOfStream => { - // Write end closed by CLOEXEC at the time of the `execvpe` call, - // indicating success. - }, - else => { - // Problem reading the error from the error reporting pipe. We - // don't know if the child is alive or dead. Better to assume it is - // alive so the resource does not risk being leaked. - }, - } + io.vtable.childKill(io.userdata, child); + assert(child.id == null); } +pub const WaitError = error{ + AccessDenied, +} || Io.Cancelable || Io.UnexpectedError; + /// Blocks until child process terminates and then cleans up all resources. -pub fn wait(self: *ChildProcess) WaitError!Term { - try self.waitForSpawn(); // report spawn errors - if (self.term) |term| { - self.cleanupStreams(); - return term; - } - switch (native_os) { - .windows => try self.waitUnwrappedWindows(), - else => self.waitUnwrappedPosix(), - } - self.id = undefined; - return self.term.?; +pub fn wait(child: *Child, io: Io) WaitError!Term { + assert(child.id != null); + return io.vtable.childWait(io.userdata, child); } -pub const RunResult = struct { - term: Term, - stdout: []u8, - stderr: []u8, -}; - /// Collect the output from the process's stdout and stderr. Will return once all output /// has been collected. This does not mean that the process has ended. `wait` should still /// be called to wait for and clean up the process. /// -/// The process must be started with stdout_behavior and stderr_behavior == .Pipe +/// The process must have been started with stdout and stderr set to +/// `process.SpawnOptions.StdIo.pipe`. pub fn collectOutput( - child: ChildProcess, + child: *const Child, /// Used for `stdout` and `stderr`. allocator: Allocator, stdout: *ArrayList(u8), stderr: *ArrayList(u8), max_output_bytes: usize, ) !void { - assert(child.stdout_behavior == .Pipe); - assert(child.stderr_behavior == .Pipe); - var poller = std.Io.poll(allocator, enum { stdout, stderr }, .{ .stdout = child.stdout.?, .stderr = child.stderr.?, @@ -412,1459 +176,3 @@ pub fn collectOutput( return error.StderrStreamTooLong; } } - -pub const RunError = posix.GetCwdError || posix.ReadError || SpawnError || posix.PollError || error{ - StdoutStreamTooLong, - StderrStreamTooLong, -}; - -/// Spawns a child process, waits for it, collecting stdout and stderr, and then returns. -/// If it succeeds, the caller owns result.stdout and result.stderr memory. -pub fn run(args: struct { - allocator: mem.Allocator, - argv: []const []const u8, - cwd: ?[]const u8 = null, - cwd_dir: ?fs.Dir = null, - /// Required if unable to access the current env map (e.g. building a - /// library on some platforms). - env_map: ?*const EnvMap = null, - max_output_bytes: usize = 50 * 1024, - expand_arg0: Arg0Expand = .no_expand, - progress_node: std.Progress.Node = std.Progress.Node.none, -}) RunError!RunResult { - var child = ChildProcess.init(args.argv, args.allocator); - child.stdin_behavior = .Ignore; - child.stdout_behavior = .Pipe; - child.stderr_behavior = .Pipe; - child.cwd = args.cwd; - child.cwd_dir = args.cwd_dir; - child.env_map = args.env_map; - child.expand_arg0 = args.expand_arg0; - child.progress_node = args.progress_node; - - var stdout: ArrayList(u8) = .empty; - defer stdout.deinit(args.allocator); - var stderr: ArrayList(u8) = .empty; - defer stderr.deinit(args.allocator); - - try child.spawn(); - errdefer { - _ = child.kill() catch {}; - } - try child.collectOutput(args.allocator, &stdout, &stderr, args.max_output_bytes); - - return .{ - .stdout = try stdout.toOwnedSlice(args.allocator), - .stderr = try stderr.toOwnedSlice(args.allocator), - .term = try child.wait(), - }; -} - -fn waitUnwrappedWindows(self: *ChildProcess) WaitError!void { - const result = windows.WaitForSingleObjectEx(self.id, windows.INFINITE, false); - - self.term = @as(SpawnError!Term, x: { - var exit_code: windows.DWORD = undefined; - if (windows.kernel32.GetExitCodeProcess(self.id, &exit_code) == 0) { - break :x Term{ .Unknown = 0 }; - } else { - break :x Term{ .Exited = @as(u8, @truncate(exit_code)) }; - } - }); - - if (self.request_resource_usage_statistics) { - self.resource_usage_statistics.rusage = try windows.GetProcessMemoryInfo(self.id); - } - - posix.close(self.id); - posix.close(self.thread_handle); - self.cleanupStreams(); - return result; -} - -fn waitUnwrappedPosix(self: *ChildProcess) void { - const res: posix.WaitPidResult = res: { - if (self.request_resource_usage_statistics) { - switch (native_os) { - .linux, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => { - var ru: posix.rusage = undefined; - const res = posix.wait4(self.id, 0, &ru); - self.resource_usage_statistics.rusage = ru; - break :res res; - }, - else => {}, - } - } - - break :res posix.waitpid(self.id, 0); - }; - const status = res.status; - self.cleanupStreams(); - self.handleWaitResult(status); -} - -fn handleWaitResult(self: *ChildProcess, status: u32) void { - self.term = statusToTerm(status); -} - -fn cleanupStreams(self: *ChildProcess) void { - if (self.stdin) |*stdin| { - stdin.close(); - self.stdin = null; - } - if (self.stdout) |*stdout| { - stdout.close(); - self.stdout = null; - } - if (self.stderr) |*stderr| { - stderr.close(); - self.stderr = null; - } -} - -fn statusToTerm(status: u32) Term { - return if (posix.W.IFEXITED(status)) - Term{ .Exited = posix.W.EXITSTATUS(status) } - else if (posix.W.IFSIGNALED(status)) - Term{ .Signal = posix.W.TERMSIG(status) } - else if (posix.W.IFSTOPPED(status)) - Term{ .Stopped = posix.W.STOPSIG(status) } - else - Term{ .Unknown = status }; -} - -fn spawnPosix(self: *ChildProcess) SpawnError!void { - // The child process does need to access (one end of) these pipes. However, - // we must initially set CLOEXEC to avoid a race condition. If another thread - // is racing to spawn a different child process, we don't want it to inherit - // these FDs in any scenario; that would mean that, for instance, calls to - // `poll` from the parent would not report the child's stdout as closing when - // expected, since the other child may retain a reference to the write end of - // the pipe. So, we create the pipes with CLOEXEC initially. After fork, we - // need to do something in the new child to make sure we preserve the reference - // we want. We could use `fcntl` to remove CLOEXEC from the FD, but as it - // turns out, we `dup2` everything anyway, so there's no need! - const pipe_flags: posix.O = .{ .CLOEXEC = true }; - - const stdin_pipe = if (self.stdin_behavior == .Pipe) try posix.pipe2(pipe_flags) else undefined; - errdefer if (self.stdin_behavior == .Pipe) { - destroyPipe(stdin_pipe); - }; - - const stdout_pipe = if (self.stdout_behavior == .Pipe) try posix.pipe2(pipe_flags) else undefined; - errdefer if (self.stdout_behavior == .Pipe) { - destroyPipe(stdout_pipe); - }; - - const stderr_pipe = if (self.stderr_behavior == .Pipe) try posix.pipe2(pipe_flags) else undefined; - errdefer if (self.stderr_behavior == .Pipe) { - destroyPipe(stderr_pipe); - }; - - const any_ignore = (self.stdin_behavior == .Ignore or self.stdout_behavior == .Ignore or self.stderr_behavior == .Ignore); - const dev_null_fd = if (any_ignore) - posix.openZ("/dev/null", .{ .ACCMODE = .RDWR }, 0) catch |err| switch (err) { - error.PathAlreadyExists => unreachable, - error.NoSpaceLeft => unreachable, - error.FileTooBig => unreachable, - error.DeviceBusy => unreachable, - error.FileLocksNotSupported => unreachable, - error.BadPathName => unreachable, // Windows-only - error.WouldBlock => unreachable, - error.NetworkNotFound => unreachable, // Windows-only - error.Canceled => unreachable, // temporarily in the posix error set - error.SharingViolation => unreachable, // Windows-only - error.PipeBusy => unreachable, // not a pipe - error.AntivirusInterference => unreachable, // Windows-only - else => |e| return e, - } - else - undefined; - defer { - if (any_ignore) posix.close(dev_null_fd); - } - - const prog_pipe: [2]posix.fd_t = p: { - if (self.progress_node.index == .none) { - break :p .{ -1, -1 }; - } else { - // We use CLOEXEC for the same reason as in `pipe_flags`. - break :p try posix.pipe2(.{ .NONBLOCK = true, .CLOEXEC = true }); - } - }; - errdefer destroyPipe(prog_pipe); - - var arena_allocator = std.heap.ArenaAllocator.init(self.allocator); - defer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); - - // The POSIX standard does not allow malloc() between fork() and execve(), - // and `self.allocator` may be a libc allocator. - // I have personally observed the child process deadlocking when it tries - // to call malloc() due to a heap allocation between fork() and execve(), - // in musl v1.1.24. - // Additionally, we want to reduce the number of possible ways things - // can fail between fork() and execve(). - // Therefore, we do all the allocation for the execve() before the fork(). - // This means we must do the null-termination of argv and env vars here. - const argv_buf = try arena.allocSentinel(?[*:0]const u8, self.argv.len, null); - for (self.argv, 0..) |arg, i| argv_buf[i] = (try arena.dupeZ(u8, arg)).ptr; - - const prog_fileno = 3; - comptime assert(@max(posix.STDIN_FILENO, posix.STDOUT_FILENO, posix.STDERR_FILENO) + 1 == prog_fileno); - - const envp: [*:null]const ?[*:0]const u8 = m: { - const prog_fd: i32 = if (prog_pipe[1] == -1) -1 else prog_fileno; - if (self.env_map) |env_map| { - break :m (try process.createEnvironFromMap(arena, env_map, .{ - .zig_progress_fd = prog_fd, - })).ptr; - } else if (builtin.link_libc) { - break :m (try process.createEnvironFromExisting(arena, std.c.environ, .{ - .zig_progress_fd = prog_fd, - })).ptr; - } else if (builtin.output_mode == .Exe) { - // Then we have Zig start code and this works. - // TODO type-safety for null-termination of `os.environ`. - break :m (try process.createEnvironFromExisting(arena, @ptrCast(std.os.environ.ptr), .{ - .zig_progress_fd = prog_fd, - })).ptr; - } else { - // TODO come up with a solution for this. - @panic("missing std lib enhancement: ChildProcess implementation has no way to collect the environment variables to forward to the child process"); - } - }; - - // This pipe communicates to the parent errors in the child between `fork` and `execvpe`. - // It is closed by the child (via CLOEXEC) without writing if `execvpe` succeeds. - const err_pipe: [2]posix.fd_t = try posix.pipe2(.{ .CLOEXEC = true }); - errdefer destroyPipe(err_pipe); - - const pid_result = try posix.fork(); - if (pid_result == 0) { - // we are the child - setUpChildIo(self.stdin_behavior, stdin_pipe[0], posix.STDIN_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err); - setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err); - setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err); - - if (self.cwd_dir) |cwd| { - posix.fchdir(cwd.fd) catch |err| forkChildErrReport(err_pipe[1], err); - } else if (self.cwd) |cwd| { - posix.chdir(cwd) catch |err| forkChildErrReport(err_pipe[1], err); - } - - // Must happen after fchdir above, the cwd file descriptor might be - // equal to prog_fileno and be clobbered by this dup2 call. - if (prog_pipe[1] != -1) posix.dup2(prog_pipe[1], prog_fileno) catch |err| forkChildErrReport(err_pipe[1], err); - - if (self.gid) |gid| { - posix.setregid(gid, gid) catch |err| forkChildErrReport(err_pipe[1], err); - } - - if (self.uid) |uid| { - posix.setreuid(uid, uid) catch |err| forkChildErrReport(err_pipe[1], err); - } - - if (self.pgid) |pid| { - posix.setpgid(0, pid) catch |err| forkChildErrReport(err_pipe[1], err); - } - - if (self.start_suspended) { - posix.kill(posix.getpid(), .STOP) catch |err| forkChildErrReport(err_pipe[1], err); - } - - const err = switch (self.expand_arg0) { - .expand => posix.execvpeZ_expandArg0(.expand, argv_buf.ptr[0].?, argv_buf.ptr, envp), - .no_expand => posix.execvpeZ_expandArg0(.no_expand, argv_buf.ptr[0].?, argv_buf.ptr, envp), - }; - forkChildErrReport(err_pipe[1], err); - } - - // we are the parent - errdefer comptime unreachable; // The child is forked; we must not error from now on - - posix.close(err_pipe[1]); // make sure only the child holds the write end open - self.err_pipe = err_pipe[0]; - - const pid: i32 = @intCast(pid_result); - if (self.stdin_behavior == .Pipe) { - self.stdin = .{ .handle = stdin_pipe[1] }; - } else { - self.stdin = null; - } - if (self.stdout_behavior == .Pipe) { - self.stdout = .{ .handle = stdout_pipe[0] }; - } else { - self.stdout = null; - } - if (self.stderr_behavior == .Pipe) { - self.stderr = .{ .handle = stderr_pipe[0] }; - } else { - self.stderr = null; - } - - self.id = pid; - self.term = null; - - if (self.stdin_behavior == .Pipe) { - posix.close(stdin_pipe[0]); - } - if (self.stdout_behavior == .Pipe) { - posix.close(stdout_pipe[1]); - } - if (self.stderr_behavior == .Pipe) { - posix.close(stderr_pipe[1]); - } - - if (prog_pipe[1] != -1) { - posix.close(prog_pipe[1]); - } - self.progress_node.setIpcFd(prog_pipe[0]); -} - -fn spawnWindows(self: *ChildProcess) SpawnError!void { - var saAttr = windows.SECURITY_ATTRIBUTES{ - .nLength = @sizeOf(windows.SECURITY_ATTRIBUTES), - .bInheritHandle = windows.TRUE, - .lpSecurityDescriptor = null, - }; - - const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore); - - const nul_handle = if (any_ignore) - // "\Device\Null" or "\??\NUL" - windows.OpenFile(&[_]u16{ '\\', 'D', 'e', 'v', 'i', 'c', 'e', '\\', 'N', 'u', 'l', 'l' }, .{ - .access_mask = windows.GENERIC_READ | windows.GENERIC_WRITE | windows.SYNCHRONIZE, - .share_access = windows.FILE_SHARE_READ | windows.FILE_SHARE_WRITE | windows.FILE_SHARE_DELETE, - .sa = &saAttr, - .creation = windows.OPEN_EXISTING, - }) catch |err| switch (err) { - error.PathAlreadyExists => return error.Unexpected, // not possible for "NUL" - error.PipeBusy => return error.Unexpected, // not possible for "NUL" - error.NoDevice => return error.Unexpected, // not possible for "NUL" - error.FileNotFound => return error.Unexpected, // not possible for "NUL" - error.AccessDenied => return error.Unexpected, // not possible for "NUL" - error.NameTooLong => return error.Unexpected, // not possible for "NUL" - error.WouldBlock => return error.Unexpected, // not possible for "NUL" - error.NetworkNotFound => return error.Unexpected, // not possible for "NUL" - error.AntivirusInterference => return error.Unexpected, // not possible for "NUL" - else => |e| return e, - } - else - undefined; - defer { - if (any_ignore) posix.close(nul_handle); - } - - var g_hChildStd_IN_Rd: ?windows.HANDLE = null; - var g_hChildStd_IN_Wr: ?windows.HANDLE = null; - switch (self.stdin_behavior) { - StdIo.Pipe => { - try windowsMakePipeIn(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr); - }, - StdIo.Ignore => { - g_hChildStd_IN_Rd = nul_handle; - }, - StdIo.Inherit => { - g_hChildStd_IN_Rd = windows.GetStdHandle(windows.STD_INPUT_HANDLE) catch null; - }, - StdIo.Close => { - g_hChildStd_IN_Rd = null; - }, - } - errdefer if (self.stdin_behavior == StdIo.Pipe) { - windowsDestroyPipe(g_hChildStd_IN_Rd, g_hChildStd_IN_Wr); - }; - - var g_hChildStd_OUT_Rd: ?windows.HANDLE = null; - var g_hChildStd_OUT_Wr: ?windows.HANDLE = null; - switch (self.stdout_behavior) { - StdIo.Pipe => { - try windowsMakeAsyncPipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr); - }, - StdIo.Ignore => { - g_hChildStd_OUT_Wr = nul_handle; - }, - StdIo.Inherit => { - g_hChildStd_OUT_Wr = windows.GetStdHandle(windows.STD_OUTPUT_HANDLE) catch null; - }, - StdIo.Close => { - g_hChildStd_OUT_Wr = null; - }, - } - errdefer if (self.stdout_behavior == StdIo.Pipe) { - windowsDestroyPipe(g_hChildStd_OUT_Rd, g_hChildStd_OUT_Wr); - }; - - var g_hChildStd_ERR_Rd: ?windows.HANDLE = null; - var g_hChildStd_ERR_Wr: ?windows.HANDLE = null; - switch (self.stderr_behavior) { - StdIo.Pipe => { - try windowsMakeAsyncPipe(&g_hChildStd_ERR_Rd, &g_hChildStd_ERR_Wr, &saAttr); - }, - StdIo.Ignore => { - g_hChildStd_ERR_Wr = nul_handle; - }, - StdIo.Inherit => { - g_hChildStd_ERR_Wr = windows.GetStdHandle(windows.STD_ERROR_HANDLE) catch null; - }, - StdIo.Close => { - g_hChildStd_ERR_Wr = null; - }, - } - errdefer if (self.stderr_behavior == StdIo.Pipe) { - windowsDestroyPipe(g_hChildStd_ERR_Rd, g_hChildStd_ERR_Wr); - }; - - var siStartInfo = windows.STARTUPINFOW{ - .cb = @sizeOf(windows.STARTUPINFOW), - .hStdError = g_hChildStd_ERR_Wr, - .hStdOutput = g_hChildStd_OUT_Wr, - .hStdInput = g_hChildStd_IN_Rd, - .dwFlags = windows.STARTF_USESTDHANDLES, - - .lpReserved = null, - .lpDesktop = null, - .lpTitle = null, - .dwX = 0, - .dwY = 0, - .dwXSize = 0, - .dwYSize = 0, - .dwXCountChars = 0, - .dwYCountChars = 0, - .dwFillAttribute = 0, - .wShowWindow = 0, - .cbReserved2 = 0, - .lpReserved2 = null, - }; - var piProcInfo: windows.PROCESS_INFORMATION = undefined; - - const cwd_w = if (self.cwd) |cwd| try unicode.wtf8ToWtf16LeAllocZ(self.allocator, cwd) else null; - defer if (cwd_w) |cwd| self.allocator.free(cwd); - const cwd_w_ptr = if (cwd_w) |cwd| cwd.ptr else null; - - const maybe_envp_buf = if (self.env_map) |env_map| try process.createWindowsEnvBlock(self.allocator, env_map) else null; - defer if (maybe_envp_buf) |envp_buf| self.allocator.free(envp_buf); - const envp_ptr = if (maybe_envp_buf) |envp_buf| envp_buf.ptr else null; - - const app_name_wtf8 = self.argv[0]; - const app_name_is_absolute = fs.path.isAbsolute(app_name_wtf8); - - // the cwd set in ChildProcess is in effect when choosing the executable path - // to match posix semantics - var cwd_path_w_needs_free = false; - const cwd_path_w = x: { - // If the app name is absolute, then we need to use its dirname as the cwd - if (app_name_is_absolute) { - cwd_path_w_needs_free = true; - const dir = fs.path.dirname(app_name_wtf8).?; - break :x try unicode.wtf8ToWtf16LeAllocZ(self.allocator, dir); - } else if (self.cwd) |cwd| { - cwd_path_w_needs_free = true; - break :x try unicode.wtf8ToWtf16LeAllocZ(self.allocator, cwd); - } else { - break :x &[_:0]u16{}; // empty for cwd - } - }; - defer if (cwd_path_w_needs_free) self.allocator.free(cwd_path_w); - - // If the app name has more than just a filename, then we need to separate that - // into the basename and dirname and use the dirname as an addition to the cwd - // path. This is because NtQueryDirectoryFile cannot accept FileName params with - // path separators. - const app_basename_wtf8 = fs.path.basename(app_name_wtf8); - // If the app name is absolute, then the cwd will already have the app's dirname in it, - // so only populate app_dirname if app name is a relative path with > 0 path separators. - const maybe_app_dirname_wtf8 = if (!app_name_is_absolute) fs.path.dirname(app_name_wtf8) else null; - const app_dirname_w: ?[:0]u16 = x: { - if (maybe_app_dirname_wtf8) |app_dirname_wtf8| { - break :x try unicode.wtf8ToWtf16LeAllocZ(self.allocator, app_dirname_wtf8); - } - break :x null; - }; - defer if (app_dirname_w != null) self.allocator.free(app_dirname_w.?); - - const app_name_w = try unicode.wtf8ToWtf16LeAllocZ(self.allocator, app_basename_wtf8); - defer self.allocator.free(app_name_w); - - const flags: windows.CreateProcessFlags = .{ - .create_suspended = self.start_suspended, - .create_unicode_environment = true, - .create_no_window = self.create_no_window, - }; - - run: { - const PATH: [:0]const u16 = process.getenvW(unicode.utf8ToUtf16LeStringLiteral("PATH")) orelse &[_:0]u16{}; - const PATHEXT: [:0]const u16 = process.getenvW(unicode.utf8ToUtf16LeStringLiteral("PATHEXT")) orelse &[_:0]u16{}; - - // In case the command ends up being a .bat/.cmd script, we need to escape things using the cmd.exe rules - // and invoke cmd.exe ourselves in order to mitigate arbitrary command execution from maliciously - // constructed arguments. - // - // We'll need to wait until we're actually trying to run the command to know for sure - // if the resolved command has the `.bat` or `.cmd` extension, so we defer actually - // serializing the command line until we determine how it should be serialized. - var cmd_line_cache = WindowsCommandLineCache.init(self.allocator, self.argv); - defer cmd_line_cache.deinit(); - - var app_buf: ArrayList(u16) = .empty; - defer app_buf.deinit(self.allocator); - - try app_buf.appendSlice(self.allocator, app_name_w); - - var dir_buf: ArrayList(u16) = .empty; - defer dir_buf.deinit(self.allocator); - - if (cwd_path_w.len > 0) { - try dir_buf.appendSlice(self.allocator, cwd_path_w); - } - if (app_dirname_w) |app_dir| { - if (dir_buf.items.len > 0) try dir_buf.append(self.allocator, fs.path.sep); - try dir_buf.appendSlice(self.allocator, app_dir); - } - - windowsCreateProcessPathExt(self.allocator, &dir_buf, &app_buf, PATHEXT, &cmd_line_cache, envp_ptr, cwd_w_ptr, flags, &siStartInfo, &piProcInfo) catch |no_path_err| { - const original_err = switch (no_path_err) { - // argv[0] contains unsupported characters that will never resolve to a valid exe. - error.InvalidArg0 => return error.FileNotFound, - error.FileNotFound, error.InvalidExe, error.AccessDenied => |e| e, - error.UnrecoverableInvalidExe => return error.InvalidExe, - else => |e| return e, - }; - - // If the app name had path separators, that disallows PATH searching, - // and there's no need to search the PATH if the app name is absolute. - // We still search the path if the cwd is absolute because of the - // "cwd set in ChildProcess is in effect when choosing the executable path - // to match posix semantics" behavior--we don't want to skip searching - // the PATH just because we were trying to set the cwd of the child process. - if (app_dirname_w != null or app_name_is_absolute) { - return original_err; - } - - var it = mem.tokenizeScalar(u16, PATH, ';'); - while (it.next()) |search_path| { - dir_buf.clearRetainingCapacity(); - try dir_buf.appendSlice(self.allocator, search_path); - - if (windowsCreateProcessPathExt(self.allocator, &dir_buf, &app_buf, PATHEXT, &cmd_line_cache, envp_ptr, cwd_w_ptr, flags, &siStartInfo, &piProcInfo)) { - break :run; - } else |err| switch (err) { - // argv[0] contains unsupported characters that will never resolve to a valid exe. - error.InvalidArg0 => return error.FileNotFound, - error.FileNotFound, error.AccessDenied, error.InvalidExe => continue, - error.UnrecoverableInvalidExe => return error.InvalidExe, - else => |e| return e, - } - } else { - return original_err; - } - }; - } - - if (g_hChildStd_IN_Wr) |h| { - self.stdin = File{ .handle = h }; - } else { - self.stdin = null; - } - if (g_hChildStd_OUT_Rd) |h| { - self.stdout = File{ .handle = h }; - } else { - self.stdout = null; - } - if (g_hChildStd_ERR_Rd) |h| { - self.stderr = File{ .handle = h }; - } else { - self.stderr = null; - } - - self.id = piProcInfo.hProcess; - self.thread_handle = piProcInfo.hThread; - self.term = null; - - if (self.stdin_behavior == StdIo.Pipe) { - posix.close(g_hChildStd_IN_Rd.?); - } - if (self.stderr_behavior == StdIo.Pipe) { - posix.close(g_hChildStd_ERR_Wr.?); - } - if (self.stdout_behavior == StdIo.Pipe) { - posix.close(g_hChildStd_OUT_Wr.?); - } -} - -fn setUpChildIo(stdio: StdIo, pipe_fd: i32, std_fileno: i32, dev_null_fd: i32) !void { - switch (stdio) { - .Pipe => try posix.dup2(pipe_fd, std_fileno), - .Close => posix.close(std_fileno), - .Inherit => {}, - .Ignore => try posix.dup2(dev_null_fd, std_fileno), - } -} - -fn destroyPipe(pipe: [2]posix.fd_t) void { - if (pipe[0] != -1) posix.close(pipe[0]); - if (pipe[0] != pipe[1]) posix.close(pipe[1]); -} - -// Child of fork calls this to report an error to the fork parent. -// Then the child exits. -fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn { - writeIntFd(fd, @as(ErrInt, @intFromError(err))) catch {}; - // If we're linking libc, some naughty applications may have registered atexit handlers - // which we really do not want to run in the fork child. I caught LLVM doing this and - // it caused a deadlock instead of doing an exit syscall. In the words of Avril Lavigne, - // "Why'd you have to go and make things so complicated?" - if (builtin.link_libc) { - // The _exit(2) function does nothing but make the exit syscall, unlike exit(3) - std.c._exit(1); - } - posix.exit(1); -} - -fn writeIntFd(fd: i32, value: ErrInt) !void { - var buffer: [8]u8 = undefined; - var fw: std.fs.File.Writer = .initStreaming(.{ .handle = fd }, &buffer); - fw.interface.writeInt(u64, value, .little) catch unreachable; - fw.interface.flush() catch return error.SystemResources; -} - -fn readIntFd(fd: i32) !ErrInt { - var buffer: [8]u8 = undefined; - var i: usize = 0; - while (i < buffer.len) { - const n = try std.posix.read(fd, buffer[i..]); - if (n == 0) return error.EndOfStream; - i += n; - } - const int = mem.readInt(u64, &buffer, .little); - return @intCast(int); -} - -const ErrInt = std.meta.Int(.unsigned, @sizeOf(anyerror) * 8); - -/// Expects `app_buf` to contain exactly the app name, and `dir_buf` to contain exactly the dir path. -/// After return, `app_buf` will always contain exactly the app name and `dir_buf` will always contain exactly the dir path. -/// Note: `app_buf` should not contain any leading path separators. -/// Note: If the dir is the cwd, dir_buf should be empty (len = 0). -fn windowsCreateProcessPathExt( - allocator: mem.Allocator, - dir_buf: *ArrayList(u16), - app_buf: *ArrayList(u16), - pathext: [:0]const u16, - cmd_line_cache: *WindowsCommandLineCache, - envp_ptr: ?[*]u16, - cwd_ptr: ?[*:0]u16, - flags: windows.CreateProcessFlags, - lpStartupInfo: *windows.STARTUPINFOW, - lpProcessInformation: *windows.PROCESS_INFORMATION, -) !void { - const app_name_len = app_buf.items.len; - const dir_path_len = dir_buf.items.len; - - if (app_name_len == 0) return error.FileNotFound; - - defer app_buf.shrinkRetainingCapacity(app_name_len); - defer dir_buf.shrinkRetainingCapacity(dir_path_len); - - // The name of the game here is to avoid CreateProcessW calls at all costs, - // and only ever try calling it when we have a real candidate for execution. - // Secondarily, we want to minimize the number of syscalls used when checking - // for each PATHEXT-appended version of the app name. - // - // An overview of the technique used: - // - Open the search directory for iteration (either cwd or a path from PATH) - // - Use NtQueryDirectoryFile with a wildcard filename of `*` to - // check if anything that could possibly match either the unappended version - // of the app name or any of the versions with a PATHEXT value appended exists. - // - If the wildcard NtQueryDirectoryFile call found nothing, we can exit early - // without needing to use PATHEXT at all. - // - // This allows us to use a sequence - // for any directory that doesn't contain any possible matches, instead of having - // to use a separate look up for each individual filename combination (unappended + - // each PATHEXT appended). For directories where the wildcard *does* match something, - // we iterate the matches and take note of any that are either the unappended version, - // or a version with a supported PATHEXT appended. We then try calling CreateProcessW - // with the found versions in the appropriate order. - - // In the future, child process execution needs to move to Io implementation. - // Under those conditions, here we will have access to lower level directory - // opening function knowing which implementation we are in. Here, we imitate - // that scenario. - var threaded: std.Io.Threaded = .init_single_threaded; - const io = threaded.ioBasic(); - - var dir = dir: { - // needs to be null-terminated - try dir_buf.append(allocator, 0); - defer dir_buf.shrinkRetainingCapacity(dir_path_len); - const dir_path_z = dir_buf.items[0 .. dir_buf.items.len - 1 :0]; - const prefixed_path = try windows.wToPrefixedFileW(null, dir_path_z); - break :dir threaded.dirOpenDirWindows(.cwd(), prefixed_path.span(), .{ - .iterate = true, - }) catch return error.FileNotFound; - }; - defer dir.close(io); - - // Add wildcard and null-terminator - try app_buf.append(allocator, '*'); - try app_buf.append(allocator, 0); - const app_name_wildcard = app_buf.items[0 .. app_buf.items.len - 1 :0]; - - // This 2048 is arbitrary, we just want it to be large enough to get multiple FILE_DIRECTORY_INFORMATION entries - // returned per NtQueryDirectoryFile call. - var file_information_buf: [2048]u8 align(@alignOf(windows.FILE_DIRECTORY_INFORMATION)) = undefined; - const file_info_maximum_single_entry_size = @sizeOf(windows.FILE_DIRECTORY_INFORMATION) + (windows.NAME_MAX * 2); - if (file_information_buf.len < file_info_maximum_single_entry_size) { - @compileError("file_information_buf must be large enough to contain at least one maximum size FILE_DIRECTORY_INFORMATION entry"); - } - var io_status: windows.IO_STATUS_BLOCK = undefined; - - const num_supported_pathext = @typeInfo(WindowsExtension).@"enum".fields.len; - var pathext_seen = [_]bool{false} ** num_supported_pathext; - var any_pathext_seen = false; - var unappended_exists = false; - - // Fully iterate the wildcard matches via NtQueryDirectoryFile and take note of all versions - // of the app_name we should try to spawn. - // Note: This is necessary because the order of the files returned is filesystem-dependent: - // On NTFS, `blah.exe*` will always return `blah.exe` first if it exists. - // On FAT32, it's possible for something like `blah.exe.obj` to be returned first. - while (true) { - const app_name_len_bytes = std.math.cast(u16, app_name_wildcard.len * 2) orelse return error.NameTooLong; - var app_name_unicode_string = windows.UNICODE_STRING{ - .Length = app_name_len_bytes, - .MaximumLength = app_name_len_bytes, - .Buffer = @constCast(app_name_wildcard.ptr), - }; - const rc = windows.ntdll.NtQueryDirectoryFile( - dir.handle, - null, - null, - null, - &io_status, - &file_information_buf, - file_information_buf.len, - .FileDirectoryInformation, - windows.FALSE, // single result - &app_name_unicode_string, - windows.FALSE, // restart iteration - ); - - // If we get nothing with the wildcard, then we can just bail out - // as we know appending PATHEXT will not yield anything. - switch (rc) { - .SUCCESS => {}, - .NO_SUCH_FILE => return error.FileNotFound, - .NO_MORE_FILES => break, - .ACCESS_DENIED => return error.AccessDenied, - else => return windows.unexpectedStatus(rc), - } - - // According to the docs, this can only happen if there is not enough room in the - // buffer to write at least one complete FILE_DIRECTORY_INFORMATION entry. - // Therefore, this condition should not be possible to hit with the buffer size we use. - std.debug.assert(io_status.Information != 0); - - var it = windows.FileInformationIterator(windows.FILE_DIRECTORY_INFORMATION){ .buf = &file_information_buf }; - while (it.next()) |info| { - // Skip directories - if (info.FileAttributes & windows.FILE_ATTRIBUTE_DIRECTORY != 0) continue; - const filename = @as([*]u16, @ptrCast(&info.FileName))[0 .. info.FileNameLength / 2]; - // Because all results start with the app_name since we're using the wildcard `app_name*`, - // if the length is equal to app_name then this is an exact match - if (filename.len == app_name_len) { - // Note: We can't break early here because it's possible that the unappended version - // fails to spawn, in which case we still want to try the PATHEXT appended versions. - unappended_exists = true; - } else if (windowsCreateProcessSupportsExtension(filename[app_name_len..])) |pathext_ext| { - pathext_seen[@intFromEnum(pathext_ext)] = true; - any_pathext_seen = true; - } - } - } - - const unappended_err = unappended: { - if (unappended_exists) { - if (dir_path_len != 0) switch (dir_buf.items[dir_buf.items.len - 1]) { - '/', '\\' => {}, - else => try dir_buf.append(allocator, fs.path.sep), - }; - try dir_buf.appendSlice(allocator, app_buf.items[0..app_name_len]); - try dir_buf.append(allocator, 0); - const full_app_name = dir_buf.items[0 .. dir_buf.items.len - 1 :0]; - - const is_bat_or_cmd = bat_or_cmd: { - const app_name = app_buf.items[0..app_name_len]; - const ext_start = std.mem.lastIndexOfScalar(u16, app_name, '.') orelse break :bat_or_cmd false; - const ext = app_name[ext_start..]; - const ext_enum = windowsCreateProcessSupportsExtension(ext) orelse break :bat_or_cmd false; - switch (ext_enum) { - .cmd, .bat => break :bat_or_cmd true, - else => break :bat_or_cmd false, - } - }; - const cmd_line_w = if (is_bat_or_cmd) - try cmd_line_cache.scriptCommandLine(full_app_name) - else - try cmd_line_cache.commandLine(); - const app_name_w = if (is_bat_or_cmd) - try cmd_line_cache.cmdExePath() - else - full_app_name; - - if (windowsCreateProcess(app_name_w.ptr, cmd_line_w.ptr, envp_ptr, cwd_ptr, flags, lpStartupInfo, lpProcessInformation)) |_| { - return; - } else |err| switch (err) { - error.FileNotFound, - error.AccessDenied, - => break :unappended err, - error.InvalidExe => { - // On InvalidExe, if the extension of the app name is .exe then - // it's treated as an unrecoverable error. Otherwise, it'll be - // skipped as normal. - const app_name = app_buf.items[0..app_name_len]; - const ext_start = std.mem.lastIndexOfScalar(u16, app_name, '.') orelse break :unappended err; - const ext = app_name[ext_start..]; - if (windows.eqlIgnoreCaseWtf16(ext, unicode.utf8ToUtf16LeStringLiteral(".EXE"))) { - return error.UnrecoverableInvalidExe; - } - break :unappended err; - }, - else => return err, - } - } - break :unappended error.FileNotFound; - }; - - if (!any_pathext_seen) return unappended_err; - - // Now try any PATHEXT appended versions that we've seen - var ext_it = mem.tokenizeScalar(u16, pathext, ';'); - while (ext_it.next()) |ext| { - const ext_enum = windowsCreateProcessSupportsExtension(ext) orelse continue; - if (!pathext_seen[@intFromEnum(ext_enum)]) continue; - - dir_buf.shrinkRetainingCapacity(dir_path_len); - if (dir_path_len != 0) switch (dir_buf.items[dir_buf.items.len - 1]) { - '/', '\\' => {}, - else => try dir_buf.append(allocator, fs.path.sep), - }; - try dir_buf.appendSlice(allocator, app_buf.items[0..app_name_len]); - try dir_buf.appendSlice(allocator, ext); - try dir_buf.append(allocator, 0); - const full_app_name = dir_buf.items[0 .. dir_buf.items.len - 1 :0]; - - const is_bat_or_cmd = switch (ext_enum) { - .cmd, .bat => true, - else => false, - }; - const cmd_line_w = if (is_bat_or_cmd) - try cmd_line_cache.scriptCommandLine(full_app_name) - else - try cmd_line_cache.commandLine(); - const app_name_w = if (is_bat_or_cmd) - try cmd_line_cache.cmdExePath() - else - full_app_name; - - if (windowsCreateProcess(app_name_w.ptr, cmd_line_w.ptr, envp_ptr, cwd_ptr, flags, lpStartupInfo, lpProcessInformation)) |_| { - return; - } else |err| switch (err) { - error.FileNotFound => continue, - error.AccessDenied => continue, - error.InvalidExe => { - // On InvalidExe, if the extension of the app name is .exe then - // it's treated as an unrecoverable error. Otherwise, it'll be - // skipped as normal. - if (windows.eqlIgnoreCaseWtf16(ext, unicode.utf8ToUtf16LeStringLiteral(".EXE"))) { - return error.UnrecoverableInvalidExe; - } - continue; - }, - else => return err, - } - } - - return unappended_err; -} - -fn windowsCreateProcess( - app_name: [*:0]u16, - cmd_line: [*:0]u16, - envp_ptr: ?[*]u16, - cwd_ptr: ?[*:0]u16, - flags: windows.CreateProcessFlags, - lpStartupInfo: *windows.STARTUPINFOW, - lpProcessInformation: *windows.PROCESS_INFORMATION, -) !void { - // TODO the docs for environment pointer say: - // > A pointer to the environment block for the new process. If this parameter - // > is NULL, the new process uses the environment of the calling process. - // > ... - // > An environment block can contain either Unicode or ANSI characters. If - // > the environment block pointed to by lpEnvironment contains Unicode - // > characters, be sure that dwCreationFlags includes CREATE_UNICODE_ENVIRONMENT. - // > If this parameter is NULL and the environment block of the parent process - // > contains Unicode characters, you must also ensure that dwCreationFlags - // > includes CREATE_UNICODE_ENVIRONMENT. - // This seems to imply that we have to somehow know whether our process parent passed - // CREATE_UNICODE_ENVIRONMENT if we want to pass NULL for the environment parameter. - // Since we do not know this information that would imply that we must not pass NULL - // for the parameter. - // However this would imply that programs compiled with -DUNICODE could not pass - // environment variables to programs that were not, which seems unlikely. - // More investigation is needed. - return windows.CreateProcessW( - app_name, - cmd_line, - null, - null, - windows.TRUE, - flags, - @as(?*anyopaque, @ptrCast(envp_ptr)), - cwd_ptr, - lpStartupInfo, - lpProcessInformation, - ); -} - -fn windowsMakePipeIn(rd: *?windows.HANDLE, wr: *?windows.HANDLE, sattr: *const windows.SECURITY_ATTRIBUTES) !void { - var rd_h: windows.HANDLE = undefined; - var wr_h: windows.HANDLE = undefined; - try windows.CreatePipe(&rd_h, &wr_h, sattr); - errdefer windowsDestroyPipe(rd_h, wr_h); - try windows.SetHandleInformation(wr_h, windows.HANDLE_FLAG_INHERIT, 0); - rd.* = rd_h; - wr.* = wr_h; -} - -fn windowsDestroyPipe(rd: ?windows.HANDLE, wr: ?windows.HANDLE) void { - if (rd) |h| posix.close(h); - if (wr) |h| posix.close(h); -} - -fn windowsMakeAsyncPipe(rd: *?windows.HANDLE, wr: *?windows.HANDLE, sattr: *const windows.SECURITY_ATTRIBUTES) !void { - var tmp_bufw: [128]u16 = undefined; - - // Anonymous pipes are built upon Named pipes. - // https://docs.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-createpipe - // Asynchronous (overlapped) read and write operations are not supported by anonymous pipes. - // https://docs.microsoft.com/en-us/windows/win32/ipc/anonymous-pipe-operations - const pipe_path = blk: { - var tmp_buf: [128]u8 = undefined; - // Forge a random path for the pipe. - const pipe_path = std.fmt.bufPrintSentinel( - &tmp_buf, - "\\\\.\\pipe\\zig-childprocess-{d}-{d}", - .{ windows.GetCurrentProcessId(), pipe_name_counter.fetchAdd(1, .monotonic) }, - 0, - ) catch unreachable; - const len = std.unicode.wtf8ToWtf16Le(&tmp_bufw, pipe_path) catch unreachable; - tmp_bufw[len] = 0; - break :blk tmp_bufw[0..len :0]; - }; - - // Create the read handle that can be used with overlapped IO ops. - const read_handle = windows.kernel32.CreateNamedPipeW( - pipe_path.ptr, - windows.PIPE_ACCESS_INBOUND | windows.FILE_FLAG_OVERLAPPED, - windows.PIPE_TYPE_BYTE, - 1, - 4096, - 4096, - 0, - sattr, - ); - if (read_handle == windows.INVALID_HANDLE_VALUE) { - switch (windows.GetLastError()) { - else => |err| return windows.unexpectedError(err), - } - } - errdefer posix.close(read_handle); - - var sattr_copy = sattr.*; - const write_handle = windows.kernel32.CreateFileW( - pipe_path.ptr, - windows.GENERIC_WRITE, - 0, - &sattr_copy, - windows.OPEN_EXISTING, - windows.FILE_ATTRIBUTE_NORMAL, - null, - ); - if (write_handle == windows.INVALID_HANDLE_VALUE) { - switch (windows.GetLastError()) { - else => |err| return windows.unexpectedError(err), - } - } - errdefer posix.close(write_handle); - - try windows.SetHandleInformation(read_handle, windows.HANDLE_FLAG_INHERIT, 0); - - rd.* = read_handle; - wr.* = write_handle; -} - -var pipe_name_counter = std.atomic.Value(u32).init(1); - -/// File name extensions supported natively by `CreateProcess()` on Windows. -// Should be kept in sync with `windowsCreateProcessSupportsExtension`. -pub const WindowsExtension = enum { - bat, - cmd, - com, - exe, -}; - -/// Case-insensitive WTF-16 lookup -fn windowsCreateProcessSupportsExtension(ext: []const u16) ?WindowsExtension { - if (ext.len != 4) return null; - const State = enum { - start, - dot, - b, - ba, - c, - cm, - co, - e, - ex, - }; - var state: State = .start; - for (ext) |c| switch (state) { - .start => switch (c) { - '.' => state = .dot, - else => return null, - }, - .dot => switch (c) { - 'b', 'B' => state = .b, - 'c', 'C' => state = .c, - 'e', 'E' => state = .e, - else => return null, - }, - .b => switch (c) { - 'a', 'A' => state = .ba, - else => return null, - }, - .c => switch (c) { - 'm', 'M' => state = .cm, - 'o', 'O' => state = .co, - else => return null, - }, - .e => switch (c) { - 'x', 'X' => state = .ex, - else => return null, - }, - .ba => switch (c) { - 't', 'T' => return .bat, - else => return null, - }, - .cm => switch (c) { - 'd', 'D' => return .cmd, - else => return null, - }, - .co => switch (c) { - 'm', 'M' => return .com, - else => return null, - }, - .ex => switch (c) { - 'e', 'E' => return .exe, - else => return null, - }, - }; - return null; -} - -test windowsCreateProcessSupportsExtension { - try std.testing.expectEqual(WindowsExtension.exe, windowsCreateProcessSupportsExtension(&[_]u16{ '.', 'e', 'X', 'e' }).?); - try std.testing.expect(windowsCreateProcessSupportsExtension(&[_]u16{ '.', 'e', 'X', 'e', 'c' }) == null); -} - -/// Serializes argv into a WTF-16 encoded command-line string for use with CreateProcessW. -/// -/// Serialization is done on-demand and the result is cached in order to allow for: -/// - Only serializing the particular type of command line needed (`.bat`/`.cmd` -/// command line serialization is different from `.exe`/etc) -/// - Reusing the serialized command lines if necessary (i.e. if the execution -/// of a command fails and the PATH is going to be continued to be searched -/// for more candidates) -const WindowsCommandLineCache = struct { - cmd_line: ?[:0]u16 = null, - script_cmd_line: ?[:0]u16 = null, - cmd_exe_path: ?[:0]u16 = null, - argv: []const []const u8, - allocator: mem.Allocator, - - fn init(allocator: mem.Allocator, argv: []const []const u8) WindowsCommandLineCache { - return .{ - .allocator = allocator, - .argv = argv, - }; - } - - fn deinit(self: *WindowsCommandLineCache) void { - if (self.cmd_line) |cmd_line| self.allocator.free(cmd_line); - if (self.script_cmd_line) |script_cmd_line| self.allocator.free(script_cmd_line); - if (self.cmd_exe_path) |cmd_exe_path| self.allocator.free(cmd_exe_path); - } - - fn commandLine(self: *WindowsCommandLineCache) ![:0]u16 { - if (self.cmd_line == null) { - self.cmd_line = try argvToCommandLineWindows(self.allocator, self.argv); - } - return self.cmd_line.?; - } - - /// Not cached, since the path to the batch script will change during PATH searching. - /// `script_path` should be as qualified as possible, e.g. if the PATH is being searched, - /// then script_path should include both the search path and the script filename - /// (this allows avoiding cmd.exe having to search the PATH again). - fn scriptCommandLine(self: *WindowsCommandLineCache, script_path: []const u16) ![:0]u16 { - if (self.script_cmd_line) |v| self.allocator.free(v); - self.script_cmd_line = try argvToScriptCommandLineWindows( - self.allocator, - script_path, - self.argv[1..], - ); - return self.script_cmd_line.?; - } - - fn cmdExePath(self: *WindowsCommandLineCache) ![:0]u16 { - if (self.cmd_exe_path == null) { - self.cmd_exe_path = try windowsCmdExePath(self.allocator); - } - return self.cmd_exe_path.?; - } -}; - -/// Returns the absolute path of `cmd.exe` within the Windows system directory. -/// The caller owns the returned slice. -fn windowsCmdExePath(allocator: mem.Allocator) error{ OutOfMemory, Unexpected }![:0]u16 { - var buf = try ArrayList(u16).initCapacity(allocator, 128); - errdefer buf.deinit(allocator); - while (true) { - const unused_slice = buf.unusedCapacitySlice(); - // TODO: Get the system directory from PEB.ReadOnlyStaticServerData - const len = windows.kernel32.GetSystemDirectoryW(@ptrCast(unused_slice), @intCast(unused_slice.len)); - if (len == 0) { - switch (windows.GetLastError()) { - else => |err| return windows.unexpectedError(err), - } - } - if (len > unused_slice.len) { - try buf.ensureUnusedCapacity(allocator, len); - } else { - buf.items.len = len; - break; - } - } - switch (buf.items[buf.items.len - 1]) { - '/', '\\' => {}, - else => try buf.append(allocator, fs.path.sep), - } - try buf.appendSlice(allocator, unicode.utf8ToUtf16LeStringLiteral("cmd.exe")); - return try buf.toOwnedSliceSentinel(allocator, 0); -} - -const ArgvToCommandLineError = error{ OutOfMemory, InvalidWtf8, InvalidArg0 }; - -/// Serializes `argv` to a Windows command-line string suitable for passing to a child process and -/// parsing by the `CommandLineToArgvW` algorithm. The caller owns the returned slice. -/// -/// To avoid arbitrary command execution, this function should not be used when spawning `.bat`/`.cmd` scripts. -/// https://flatt.tech/research/posts/batbadbut-you-cant-securely-execute-commands-on-windows/ -/// -/// When executing `.bat`/`.cmd` scripts, use `argvToScriptCommandLineWindows` instead. -fn argvToCommandLineWindows( - allocator: mem.Allocator, - argv: []const []const u8, -) ArgvToCommandLineError![:0]u16 { - var buf = std.array_list.Managed(u8).init(allocator); - defer buf.deinit(); - - if (argv.len != 0) { - const arg0 = argv[0]; - - // The first argument must be quoted if it contains spaces or ASCII control characters - // (excluding DEL). It also follows special quoting rules where backslashes have no special - // interpretation, which makes it impossible to pass certain first arguments containing - // double quotes to a child process without characters from the first argument leaking into - // subsequent ones (which could have security implications). - // - // Empty arguments technically don't need quotes, but we quote them anyway for maximum - // compatibility with different implementations of the 'CommandLineToArgvW' algorithm. - // - // Double quotes are illegal in paths on Windows, so for the sake of simplicity we reject - // all first arguments containing double quotes, even ones that we could theoretically - // serialize in unquoted form. - var needs_quotes = arg0.len == 0; - for (arg0) |c| { - if (c <= ' ') { - needs_quotes = true; - } else if (c == '"') { - return error.InvalidArg0; - } - } - if (needs_quotes) { - try buf.append('"'); - try buf.appendSlice(arg0); - try buf.append('"'); - } else { - try buf.appendSlice(arg0); - } - - for (argv[1..]) |arg| { - try buf.append(' '); - - // Subsequent arguments must be quoted if they contain spaces, tabs or double quotes, - // or if they are empty. For simplicity and for maximum compatibility with different - // implementations of the 'CommandLineToArgvW' algorithm, we also quote all ASCII - // control characters (again, excluding DEL). - needs_quotes = for (arg) |c| { - if (c <= ' ' or c == '"') { - break true; - } - } else arg.len == 0; - if (!needs_quotes) { - try buf.appendSlice(arg); - continue; - } - - try buf.append('"'); - var backslash_count: usize = 0; - for (arg) |byte| { - switch (byte) { - '\\' => { - backslash_count += 1; - }, - '"' => { - try buf.appendNTimes('\\', backslash_count * 2 + 1); - try buf.append('"'); - backslash_count = 0; - }, - else => { - try buf.appendNTimes('\\', backslash_count); - try buf.append(byte); - backslash_count = 0; - }, - } - } - try buf.appendNTimes('\\', backslash_count * 2); - try buf.append('"'); - } - } - - return try unicode.wtf8ToWtf16LeAllocZ(allocator, buf.items); -} - -test argvToCommandLineWindows { - const t = testArgvToCommandLineWindows; - - try t(&.{ - \\C:\Program Files\zig\zig.exe - , - \\run - , - \\.\src\main.zig - , - \\-target - , - \\x86_64-windows-gnu - , - \\-O - , - \\ReleaseSafe - , - \\-- - , - \\--emoji=🗿 - , - \\--eval=new Regex("Dwayne \"The Rock\" Johnson") - , - }, - \\"C:\Program Files\zig\zig.exe" run .\src\main.zig -target x86_64-windows-gnu -O ReleaseSafe -- --emoji=🗿 "--eval=new Regex(\"Dwayne \\\"The Rock\\\" Johnson\")" - ); - - try t(&.{}, ""); - try t(&.{""}, "\"\""); - try t(&.{" "}, "\" \""); - try t(&.{"\t"}, "\"\t\""); - try t(&.{"\x07"}, "\"\x07\""); - try t(&.{"🦎"}, "🦎"); - - try t( - &.{ "zig", "aa aa", "bb\tbb", "cc\ncc", "dd\r\ndd", "ee\x7Fee" }, - "zig \"aa aa\" \"bb\tbb\" \"cc\ncc\" \"dd\r\ndd\" ee\x7Fee", - ); - - try t( - &.{ "\\\\foo bar\\foo bar\\", "\\\\zig zag\\zig zag\\" }, - "\"\\\\foo bar\\foo bar\\\" \"\\\\zig zag\\zig zag\\\\\"", - ); - - try std.testing.expectError( - error.InvalidArg0, - argvToCommandLineWindows(std.testing.allocator, &.{"\"quotes\"quotes\""}), - ); - try std.testing.expectError( - error.InvalidArg0, - argvToCommandLineWindows(std.testing.allocator, &.{"quotes\"quotes"}), - ); - try std.testing.expectError( - error.InvalidArg0, - argvToCommandLineWindows(std.testing.allocator, &.{"q u o t e s \" q u o t e s"}), - ); -} - -fn testArgvToCommandLineWindows(argv: []const []const u8, expected_cmd_line: []const u8) !void { - const cmd_line_w = try argvToCommandLineWindows(std.testing.allocator, argv); - defer std.testing.allocator.free(cmd_line_w); - - const cmd_line = try unicode.wtf16LeToWtf8Alloc(std.testing.allocator, cmd_line_w); - defer std.testing.allocator.free(cmd_line); - - try std.testing.expectEqualStrings(expected_cmd_line, cmd_line); -} - -const ArgvToScriptCommandLineError = error{ - OutOfMemory, - InvalidWtf8, - /// NUL (U+0000), LF (U+000A), CR (U+000D) are not allowed - /// within arguments when executing a `.bat`/`.cmd` script. - /// - NUL/LF signifiies end of arguments, so anything afterwards - /// would be lost after execution. - /// - CR is stripped by `cmd.exe`, so any CR codepoints - /// would be lost after execution. - InvalidBatchScriptArg, -}; - -/// Serializes `argv` to a Windows command-line string that uses `cmd.exe /c` and `cmd.exe`-specific -/// escaping rules. The caller owns the returned slice. -/// -/// Escapes `argv` using the suggested mitigation against arbitrary command execution from: -/// https://flatt.tech/research/posts/batbadbut-you-cant-securely-execute-commands-on-windows/ -/// -/// The return of this function will look like -/// `cmd.exe /d /e:ON /v:OFF /c ""` -/// and should be used as the `lpCommandLine` of `CreateProcessW`, while the -/// return of `windowsCmdExePath` should be used as `lpApplicationName`. -/// -/// Should only be used when spawning `.bat`/`.cmd` scripts, see `argvToCommandLineWindows` otherwise. -/// The `.bat`/`.cmd` file must be known to both have the `.bat`/`.cmd` extension and exist on the filesystem. -fn argvToScriptCommandLineWindows( - allocator: mem.Allocator, - /// Path to the `.bat`/`.cmd` script. If this path is relative, it is assumed to be relative to the CWD. - /// The script must have been verified to exist at this path before calling this function. - script_path: []const u16, - /// Arguments, not including the script name itself. Expected to be encoded as WTF-8. - script_args: []const []const u8, -) ArgvToScriptCommandLineError![:0]u16 { - var buf = try std.array_list.Managed(u8).initCapacity(allocator, 64); - defer buf.deinit(); - - // `/d` disables execution of AutoRun commands. - // `/e:ON` and `/v:OFF` are needed for BatBadBut mitigation: - // > If delayed expansion is enabled via the registry value DelayedExpansion, - // > it must be disabled by explicitly calling cmd.exe with the /V:OFF option. - // > Escaping for % requires the command extension to be enabled. - // > If it’s disabled via the registry value EnableExtensions, it must be enabled with the /E:ON option. - // https://flatt.tech/research/posts/batbadbut-you-cant-securely-execute-commands-on-windows/ - buf.appendSliceAssumeCapacity("cmd.exe /d /e:ON /v:OFF /c \""); - - // Always quote the path to the script arg - buf.appendAssumeCapacity('"'); - // We always want the path to the batch script to include a path separator in order to - // avoid cmd.exe searching the PATH for the script. This is not part of the arbitrary - // command execution mitigation, we just know exactly what script we want to execute - // at this point, and potentially making cmd.exe re-find it is unnecessary. - // - // If the script path does not have a path separator, then we know its relative to CWD and - // we can just put `.\` in the front. - if (mem.indexOfAny(u16, script_path, &[_]u16{ mem.nativeToLittle(u16, '\\'), mem.nativeToLittle(u16, '/') }) == null) { - try buf.appendSlice(".\\"); - } - // Note that we don't do any escaping/mitigations for this argument, since the relevant - // characters (", %, etc) are illegal in file paths and this function should only be called - // with script paths that have been verified to exist. - try unicode.wtf16LeToWtf8ArrayList(&buf, script_path); - buf.appendAssumeCapacity('"'); - - for (script_args) |arg| { - // Literal carriage returns get stripped when run through cmd.exe - // and NUL/newlines act as 'end of command.' Because of this, it's basically - // always a mistake to include these characters in argv, so it's - // an error condition in order to ensure that the return of this - // function can always roundtrip through cmd.exe. - if (std.mem.indexOfAny(u8, arg, "\x00\r\n") != null) { - return error.InvalidBatchScriptArg; - } - - // Separate args with a space. - try buf.append(' '); - - // Need to quote if the argument is empty (otherwise the arg would just be lost) - // or if the last character is a `\`, since then something like "%~2" in a .bat - // script would cause the closing " to be escaped which we don't want. - var needs_quotes = arg.len == 0 or arg[arg.len - 1] == '\\'; - if (!needs_quotes) { - for (arg) |c| { - switch (c) { - // Known good characters that don't need to be quoted - 'A'...'Z', 'a'...'z', '0'...'9', '#', '$', '*', '+', '-', '.', '/', ':', '?', '@', '\\', '_' => {}, - // When in doubt, quote - else => { - needs_quotes = true; - break; - }, - } - } - } - if (needs_quotes) { - try buf.append('"'); - } - var backslashes: usize = 0; - for (arg) |c| { - switch (c) { - '\\' => { - backslashes += 1; - }, - '"' => { - try buf.appendNTimes('\\', backslashes); - try buf.append('"'); - backslashes = 0; - }, - // Replace `%` with `%%cd:~,%`. - // - // cmd.exe allows extracting a substring from an environment - // variable with the syntax: `%foo:~,%`. - // Therefore, `%cd:~,%` will always expand to an empty string - // since both the start and end index are blank, and it is assumed - // that `%cd%` is always available since it is a built-in variable - // that corresponds to the current directory. - // - // This means that replacing `%foo%` with `%%cd:~,%foo%%cd:~,%` - // will stop `%foo%` from being expanded and *after* expansion - // we'll still be left with `%foo%` (the literal string). - '%' => { - // the trailing `%` is appended outside the switch - try buf.appendSlice("%%cd:~,"); - backslashes = 0; - }, - else => { - backslashes = 0; - }, - } - try buf.append(c); - } - if (needs_quotes) { - try buf.appendNTimes('\\', backslashes); - try buf.append('"'); - } - } - - try buf.append('"'); - - return try unicode.wtf8ToWtf16LeAllocZ(allocator, buf.items); -} diff --git a/lib/std/process/Environ.zig b/lib/std/process/Environ.zig new file mode 100644 index 000000000000..5255e1af16ab --- /dev/null +++ b/lib/std/process/Environ.zig @@ -0,0 +1,822 @@ +const Environ = @This(); + +const builtin = @import("builtin"); +const native_os = builtin.os.tag; + +const std = @import("../std.zig"); +const Allocator = std.mem.Allocator; +const assert = std.debug.assert; +const testing = std.testing; +const unicode = std.unicode; +const posix = std.posix; +const mem = std.mem; + +/// Unmodified, unprocessed data provided by the operating system. +block: Block, + +pub const empty: Environ = .{ + .block = switch (Block) { + void => {}, + else => &.{}, + }, +}; + +/// On WASI without libc, this is `void` because the environment has to be +/// queried and heap-allocated at runtime. +/// +/// On Windows, the memory pointed at by the PEB changes when the environment +/// is modified, so a long-lived pointer cannot be used. Therefore, on this +/// operating system `void` is also used. +pub const Block = switch (native_os) { + .windows => void, + .wasi => switch (builtin.link_libc) { + false => void, + true => [:null]const ?[*:0]const u8, + }, + .freestanding, .other => void, + else => [:null]const ?[*:0]const u8, +}; + +pub const Map = struct { + array_hash_map: ArrayHashMap, + allocator: Allocator, + + const ArrayHashMap = std.ArrayHashMapUnmanaged([]const u8, []const u8, EnvNameHashContext, false); + + pub const Size = usize; + + pub const EnvNameHashContext = struct { + fn upcase(c: u21) u21 { + if (c <= std.math.maxInt(u16)) + return std.os.windows.ntdll.RtlUpcaseUnicodeChar(@as(u16, @intCast(c))); + return c; + } + + pub fn hash(self: @This(), s: []const u8) u32 { + _ = self; + if (native_os == .windows) { + var h = std.hash.Wyhash.init(0); + var it = unicode.Wtf8View.initUnchecked(s).iterator(); + while (it.nextCodepoint()) |cp| { + const cp_upper = upcase(cp); + h.update(&[_]u8{ + @as(u8, @intCast((cp_upper >> 16) & 0xff)), + @as(u8, @intCast((cp_upper >> 8) & 0xff)), + @as(u8, @intCast((cp_upper >> 0) & 0xff)), + }); + } + return @truncate(h.final()); + } + return std.array_hash_map.hashString(s); + } + + pub fn eql(self: @This(), a: []const u8, b: []const u8, b_index: usize) bool { + _ = self; + _ = b_index; + if (native_os == .windows) { + var it_a = unicode.Wtf8View.initUnchecked(a).iterator(); + var it_b = unicode.Wtf8View.initUnchecked(b).iterator(); + while (true) { + const c_a = it_a.nextCodepoint() orelse break; + const c_b = it_b.nextCodepoint() orelse return false; + if (upcase(c_a) != upcase(c_b)) + return false; + } + return if (it_b.nextCodepoint()) |_| false else true; + } + return std.array_hash_map.eqlString(a, b); + } + }; + + /// Create a Map backed by a specific allocator. + /// That allocator will be used for both backing allocations + /// and string deduplication. + pub fn init(allocator: Allocator) Map { + return .{ .array_hash_map = .empty, .allocator = allocator }; + } + + /// Free the backing storage of the map, as well as all + /// of the stored keys and values. + pub fn deinit(self: *Map) void { + const gpa = self.allocator; + var it = self.array_hash_map.iterator(); + while (it.next()) |entry| { + gpa.free(entry.key_ptr.*); + gpa.free(entry.value_ptr.*); + } + self.array_hash_map.deinit(gpa); + self.* = undefined; + } + + pub fn keys(m: *const Map) [][]const u8 { + return m.array_hash_map.keys(); + } + + pub fn values(m: *const Map) [][]const u8 { + return m.array_hash_map.values(); + } + + /// Same as `put` but the key and value become owned by the Map rather + /// than being copied. + /// If `putMove` fails, the ownership of key and value does not transfer. + /// On Windows `key` must be a valid [WTF-8](https://wtf-8.codeberg.page/) string. + pub fn putMove(self: *Map, key: []u8, value: []u8) !void { + const gpa = self.allocator; + assert(unicode.wtf8ValidateSlice(key)); + const get_or_put = try self.array_hash_map.getOrPut(gpa, key); + if (get_or_put.found_existing) { + gpa.free(get_or_put.key_ptr.*); + gpa.free(get_or_put.value_ptr.*); + get_or_put.key_ptr.* = key; + } + get_or_put.value_ptr.* = value; + } + + /// `key` and `value` are copied into the Map. + /// On Windows `key` must be a valid [WTF-8](https://wtf-8.codeberg.page/) string. + pub fn put(self: *Map, key: []const u8, value: []const u8) !void { + assert(unicode.wtf8ValidateSlice(key)); + const gpa = self.allocator; + const value_copy = try gpa.dupe(u8, value); + errdefer gpa.free(value_copy); + const get_or_put = try self.array_hash_map.getOrPut(gpa, key); + errdefer { + if (!get_or_put.found_existing) assert(self.array_hash_map.pop() != null); + } + if (get_or_put.found_existing) { + gpa.free(get_or_put.value_ptr.*); + } else { + get_or_put.key_ptr.* = try gpa.dupe(u8, key); + } + get_or_put.value_ptr.* = value_copy; + } + + /// Find the address of the value associated with a key. + /// The returned pointer is invalidated if the map resizes. + /// On Windows `key` must be a valid [WTF-8](https://wtf-8.codeberg.page/) string. + pub fn getPtr(self: Map, key: []const u8) ?*[]const u8 { + assert(unicode.wtf8ValidateSlice(key)); + return self.array_hash_map.getPtr(key); + } + + /// Return the map's copy of the value associated with + /// a key. The returned string is invalidated if this + /// key is removed from the map. + /// On Windows `key` must be a valid [WTF-8](https://wtf-8.codeberg.page/) string. + pub fn get(self: Map, key: []const u8) ?[]const u8 { + assert(unicode.wtf8ValidateSlice(key)); + return self.array_hash_map.get(key); + } + + pub fn contains(m: *const Map, key: []const u8) bool { + return m.array_hash_map.contains(key); + } + + /// If there is an entry with a matching key, it is deleted from the hash + /// map. The entry is removed from the underlying array by swapping it with + /// the last element. + /// + /// Returns true if an entry was removed, false otherwise. + /// + /// This invalidates the value returned by get() for this key. + /// On Windows `key` must be a valid [WTF-8](https://wtf-8.codeberg.page/) string. + pub fn swapRemove(self: *Map, key: []const u8) bool { + assert(unicode.wtf8ValidateSlice(key)); + const kv = self.array_hash_map.fetchSwapRemove(key) orelse return false; + const gpa = self.allocator; + gpa.free(kv.key); + gpa.free(kv.value); + return true; + } + + /// If there is an entry with a matching key, it is deleted from the map. + /// The entry is removed from the underlying array by shifting all elements + /// forward, thereby maintaining the current ordering. + /// + /// Returns true if an entry was removed, false otherwise. + /// + /// This invalidates the value returned by get() for this key. + /// On Windows `key` must be a valid [WTF-8](https://wtf-8.codeberg.page/) string. + pub fn orderedRemove(self: *Map, key: []const u8) bool { + assert(unicode.wtf8ValidateSlice(key)); + const kv = self.array_hash_map.fetchOrderedRemove(key) orelse return false; + const gpa = self.allocator; + gpa.free(kv.key); + gpa.free(kv.value); + return true; + } + + /// Returns the number of KV pairs stored in the map. + pub fn count(self: Map) Size { + return self.array_hash_map.count(); + } + + /// Returns an iterator over entries in the map. + pub fn iterator(self: *const Map) ArrayHashMap.Iterator { + return self.array_hash_map.iterator(); + } + + /// Returns a full copy of `em` allocated with `gpa`, which is not necessarily + /// the same allocator used to allocate `em`. + pub fn clone(m: *const Map, gpa: Allocator) Allocator.Error!Map { + // Since we need to dupe the keys and values, the only way for error handling to not be a + // nightmare is to add keys to an empty map one-by-one. This could be avoided if this + // abstraction were a bit less... OOP-esque. + var new: Map = .init(gpa); + errdefer new.deinit(); + try new.array_hash_map.ensureUnusedCapacity(gpa, m.array_hash_map.count()); + for (m.array_hash_map.keys(), m.array_hash_map.values()) |key, value| { + try new.put(key, value); + } + return new; + } + + /// Creates a null-delimited environment variable block in the format + /// expected by POSIX, from a hash map plus options. + pub fn createBlockPosix( + map: *const Map, + arena: Allocator, + options: CreateBlockPosixOptions, + ) Allocator.Error![:null]?[*:0]u8 { + const ZigProgressAction = enum { nothing, edit, delete, add }; + const zig_progress_action: ZigProgressAction = a: { + const fd = options.zig_progress_fd orelse break :a .nothing; + const exists = map.get("ZIG_PROGRESS") != null; + if (fd >= 0) { + break :a if (exists) .edit else .add; + } else { + if (exists) break :a .delete; + } + break :a .nothing; + }; + + const envp_count: usize = c: { + var c: usize = map.count(); + switch (zig_progress_action) { + .add => c += 1, + .delete => c -= 1, + .nothing, .edit => {}, + } + break :c c; + }; + + const envp_buf = try arena.allocSentinel(?[*:0]u8, envp_count, null); + var i: usize = 0; + + if (zig_progress_action == .add) { + envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?}, 0); + i += 1; + } + + { + var it = map.iterator(); + while (it.next()) |pair| { + if (mem.eql(u8, pair.key_ptr.*, "ZIG_PROGRESS")) switch (zig_progress_action) { + .add => unreachable, + .delete => continue, + .edit => { + envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "{s}={d}", .{ + pair.key_ptr.*, options.zig_progress_fd.?, + }, 0); + i += 1; + continue; + }, + .nothing => {}, + }; + + envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "{s}={s}", .{ pair.key_ptr.*, pair.value_ptr.* }, 0); + i += 1; + } + } + + assert(i == envp_count); + return envp_buf; + } + + /// Caller owns result. + pub fn createBlockWindows(map: *const Map, gpa: Allocator) error{ OutOfMemory, InvalidWtf8 }![:0]u16 { + // count bytes needed + const max_chars_needed = x: { + // Only need 2 trailing NUL code units for an empty environment + var max_chars_needed: usize = if (map.count() == 0) 2 else 1; + var it = map.iterator(); + while (it.next()) |pair| { + // +1 for '=' + // +1 for null byte + max_chars_needed += pair.key_ptr.len + pair.value_ptr.len + 2; + } + break :x max_chars_needed; + }; + const result = try gpa.alloc(u16, max_chars_needed); + errdefer gpa.free(result); + + var it = map.iterator(); + var i: usize = 0; + while (it.next()) |pair| { + i += try unicode.wtf8ToWtf16Le(result[i..], pair.key_ptr.*); + result[i] = '='; + i += 1; + i += try unicode.wtf8ToWtf16Le(result[i..], pair.value_ptr.*); + result[i] = 0; + i += 1; + } + result[i] = 0; + i += 1; + // An empty environment is a special case that requires a redundant + // NUL terminator. CreateProcess will read the second code unit even + // though theoretically the first should be enough to recognize that the + // environment is empty (see https://nullprogram.com/blog/2023/08/23/) + if (map.count() == 0) { + result[i] = 0; + i += 1; + } + const reallocated = try gpa.realloc(result, i); + return reallocated[0 .. i - 1 :0]; + } +}; + +pub const CreateMapError = error{ + OutOfMemory, + /// WASI-only. `environ_sizes_get` or `environ_get` failed for an + /// unanticipated, undocumented reason. + Unexpected, +}; + +/// Allocates a `Map` and copies environment block into it. +pub fn createMap(env: Environ, allocator: Allocator) CreateMapError!Map { + if (native_os == .windows) + return createMapWide(std.os.windows.peb().ProcessParameters.Environment, allocator); + + var result = Map.init(allocator); + errdefer result.deinit(); + + if (native_os == .wasi and !builtin.link_libc) { + var environ_count: usize = undefined; + var environ_buf_size: usize = undefined; + + const environ_sizes_get_ret = std.os.wasi.environ_sizes_get(&environ_count, &environ_buf_size); + if (environ_sizes_get_ret != .SUCCESS) { + return posix.unexpectedErrno(environ_sizes_get_ret); + } + + if (environ_count == 0) { + return result; + } + + const environ = try allocator.alloc([*:0]u8, environ_count); + defer allocator.free(environ); + const environ_buf = try allocator.alloc(u8, environ_buf_size); + defer allocator.free(environ_buf); + + const environ_get_ret = std.os.wasi.environ_get(environ.ptr, environ_buf.ptr); + if (environ_get_ret != .SUCCESS) { + return posix.unexpectedErrno(environ_get_ret); + } + + for (environ) |line| { + const pair = mem.sliceTo(line, 0); + var parts = mem.splitScalar(u8, pair, '='); + const key = parts.first(); + const value = parts.rest(); + try result.put(key, value); + } + return result; + } else { + for (env.block) |opt_line| { + const line = opt_line.?; + var line_i: usize = 0; + while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {} + const key = line[0..line_i]; + + var end_i: usize = line_i; + while (line[end_i] != 0) : (end_i += 1) {} + const value = line[line_i + 1 .. end_i]; + + try result.put(key, value); + } + return result; + } +} + +pub fn createMapWide(ptr: [*:0]u16, gpa: Allocator) CreateMapError!Map { + var result = Map.init(gpa); + errdefer result.deinit(); + + var i: usize = 0; + while (ptr[i] != 0) { + const key_start = i; + + // There are some special environment variables that start with =, + // so we need a special case to not treat = as a key/value separator + // if it's the first character. + // https://devblogs.microsoft.com/oldnewthing/20100506-00/?p=14133 + if (ptr[key_start] == '=') i += 1; + + while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {} + const key_w = ptr[key_start..i]; + const key = try unicode.wtf16LeToWtf8Alloc(gpa, key_w); + errdefer gpa.free(key); + + if (ptr[i] == '=') i += 1; + + const value_start = i; + while (ptr[i] != 0) : (i += 1) {} + const value_w = ptr[value_start..i]; + const value = try unicode.wtf16LeToWtf8Alloc(gpa, value_w); + errdefer gpa.free(value); + + i += 1; // skip over null byte + + try result.putMove(key, value); + } + return result; +} + +pub const ContainsError = error{ + OutOfMemory, + /// On Windows, environment variable keys provided by the user must be + /// valid [WTF-8](https://wtf-8.codeberg.page/). This error is unreachable + /// if the key is statically known to be valid. + InvalidWtf8, + /// WASI-only. `environ_sizes_get` or `environ_get` failed for an + /// unexpected reason. + Unexpected, +}; + +/// On Windows, if `key` is not valid [WTF-8](https://wtf-8.codeberg.page/), +/// then `error.InvalidWtf8` is returned. +/// +/// See also: +/// * `createMap` +/// * `containsConstant` +/// * `containsUnempty` +pub fn contains(environ: Environ, gpa: Allocator, key: []const u8) ContainsError!bool { + var map = try createMap(environ, gpa); + defer map.deinit(); + return map.contains(key); +} + +/// On Windows, if `key` is not valid [WTF-8](https://wtf-8.codeberg.page/), +/// then `error.InvalidWtf8` is returned. +/// +/// See also: +/// * `createMap` +/// * `containsUnemptyConstant` +/// * `contains` +pub fn containsUnempty(environ: Environ, gpa: Allocator, key: []const u8) ContainsError!bool { + var map = try createMap(environ, gpa); + defer map.deinit(); + const value = map.get(key) orelse return false; + return value.len != 0; +} + +/// This function is unavailable on WASI without libc due to the memory +/// allocation requirement. +/// +/// On Windows, `key` must be valid [WTF-8](https://wtf-8.codeberg.page/), +/// +/// See also: +/// * `contains` +/// * `containsUnemptyConstant` +/// * `createMap` +pub inline fn containsConstant(environ: Environ, comptime key: []const u8) bool { + if (native_os == .windows) { + const key_w = comptime unicode.wtf8ToWtf16LeStringLiteral(key); + return getWindows(environ, key_w) != null; + } else { + return getPosix(environ, key) != null; + } +} + +/// This function is unavailable on WASI without libc due to the memory +/// allocation requirement. +/// +/// On Windows, `key` must be valid [WTF-8](https://wtf-8.codeberg.page/), +/// +/// See also: +/// * `containsUnempty` +/// * `containsConstant` +/// * `createMap` +pub inline fn containsUnemptyConstant(environ: Environ, comptime key: []const u8) bool { + if (native_os == .windows) { + const key_w = comptime unicode.wtf8ToWtf16LeStringLiteral(key); + const value = getWindows(environ, key_w) orelse return false; + return value.len != 0; + } else { + const value = getPosix(environ, key) orelse return false; + return value.len != 0; + } +} + +/// This function is unavailable on WASI without libc due to the memory +/// allocation requirement. +/// +/// See also: +/// * `getWindows` +/// * `createMap` +pub fn getPosix(environ: Environ, key: []const u8) ?[:0]const u8 { + if (mem.findScalar(u8, key, '=') != null) return null; + for (environ.block) |opt_line| { + const line = opt_line.?; + var line_i: usize = 0; + while (line[line_i] != 0) : (line_i += 1) { + if (line_i == key.len) break; + if (line[line_i] != key[line_i]) break; + } + if ((line_i != key.len) or (line[line_i] != '=')) continue; + + return mem.sliceTo(line + line_i + 1, 0); + } + return null; +} + +/// Windows-only. Get an environment variable with a null-terminated, WTF-16 +/// encoded name. +/// +/// This function performs a Unicode-aware case-insensitive lookup using +/// RtlEqualUnicodeString. +/// +/// See also: +/// * `createMap` +/// * `containsConstant` +/// * `contains` +pub fn getWindows(environ: Environ, key: [*:0]const u16) ?[:0]const u16 { + comptime assert(native_os == .windows); + comptime assert(@TypeOf(environ.block) == void); + + // '=' anywhere but the start makes this an invalid environment variable name. + const key_slice = mem.sliceTo(key, 0); + if (key_slice.len > 0 and mem.findScalar(u16, key_slice[1..], '=') != null) return null; + + const ptr = std.os.windows.peb().ProcessParameters.Environment; + + var i: usize = 0; + while (ptr[i] != 0) { + const key_value = mem.sliceTo(ptr[i..], 0); + + // There are some special environment variables that start with =, + // so we need a special case to not treat = as a key/value separator + // if it's the first character. + // https://devblogs.microsoft.com/oldnewthing/20100506-00/?p=14133 + const equal_search_start: usize = if (key_value[0] == '=') 1 else 0; + const equal_index = mem.findScalarPos(u16, key_value, equal_search_start, '=') orelse { + // This is enforced by CreateProcess. + // If violated, CreateProcess will fail with INVALID_PARAMETER. + unreachable; // must contain a = + }; + + const this_key = key_value[0..equal_index]; + if (std.os.windows.eqlIgnoreCaseWtf16(key_slice, this_key)) { + return key_value[equal_index + 1 ..]; + } + + // skip past the NUL terminator + i += key_value.len + 1; + } + return null; +} + +pub const GetAllocError = error{ + OutOfMemory, + EnvironmentVariableMissing, + /// On Windows, environment variable keys provided by the user must be + /// valid [WTF-8](https://wtf-8.codeberg.page/). This error is unreachable + /// if the key is statically known to be valid. + InvalidWtf8, +}; + +/// Caller owns returned memory. +/// +/// On Windows: +/// * If `key` is not valid [WTF-8](https://wtf-8.codeberg.page/), then +/// `error.InvalidWtf8` is returned. +/// * The returned value is encoded as [WTF-8](https://wtf-8.codeberg.page/). +/// +/// On other platforms, the value is an opaque sequence of bytes with no +/// particular encoding. +/// +/// See also: +/// * `createMap` +pub fn getAlloc(environ: Environ, gpa: Allocator, key: []const u8) GetAllocError![]u8 { + var map = createMap(environ, gpa) catch return error.OutOfMemory; + defer map.deinit(); + const val = map.get(key) orelse return error.EnvironmentVariableMissing; + return gpa.dupe(u8, val); +} + +pub const CreateBlockPosixOptions = struct { + /// `null` means to leave the `ZIG_PROGRESS` environment variable unmodified. + /// If non-null, negative means to remove the environment variable, and >= 0 + /// means to provide it with the given integer. + zig_progress_fd: ?i32 = null, +}; + +/// Creates a null-delimited environment variable block in the format expected +/// by POSIX, from a different one. +pub fn createBlockPosix( + existing: Environ, + arena: Allocator, + options: CreateBlockPosixOptions, +) Allocator.Error![:null]?[*:0]u8 { + const contains_zig_progress = for (existing.block) |opt_line| { + if (mem.eql(u8, mem.sliceTo(opt_line.?, '='), "ZIG_PROGRESS")) break true; + } else false; + + const ZigProgressAction = enum { nothing, edit, delete, add }; + const zig_progress_action: ZigProgressAction = a: { + const fd = options.zig_progress_fd orelse break :a .nothing; + if (fd >= 0) { + break :a if (contains_zig_progress) .edit else .add; + } else { + if (contains_zig_progress) break :a .delete; + } + break :a .nothing; + }; + + const envp_count: usize = c: { + var count: usize = existing.block.len; + switch (zig_progress_action) { + .add => count += 1, + .delete => count -= 1, + .nothing, .edit => {}, + } + break :c count; + }; + + const envp_buf = try arena.allocSentinel(?[*:0]u8, envp_count, null); + var i: usize = 0; + var existing_index: usize = 0; + + if (zig_progress_action == .add) { + envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?}, 0); + i += 1; + } + + while (existing.block[existing_index]) |line| : (existing_index += 1) { + if (mem.eql(u8, mem.sliceTo(line, '='), "ZIG_PROGRESS")) switch (zig_progress_action) { + .add => unreachable, + .delete => continue, + .edit => { + envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?}, 0); + i += 1; + continue; + }, + .nothing => {}, + }; + envp_buf[i] = try arena.dupeZ(u8, mem.span(line)); + i += 1; + } + + assert(i == envp_count); + return envp_buf; +} + +test "Map.createBlock" { + const allocator = testing.allocator; + var envmap = Map.init(allocator); + defer envmap.deinit(); + + try envmap.put("HOME", "/home/ifreund"); + try envmap.put("WAYLAND_DISPLAY", "wayland-1"); + try envmap.put("DISPLAY", ":1"); + try envmap.put("DEBUGINFOD_URLS", " "); + try envmap.put("XCURSOR_SIZE", "24"); + + var arena = std.heap.ArenaAllocator.init(allocator); + defer arena.deinit(); + const environ = try envmap.createBlockPosix(arena.allocator(), .{}); + + try testing.expectEqual(@as(usize, 5), environ.len); + + inline for (.{ + "HOME=/home/ifreund", + "WAYLAND_DISPLAY=wayland-1", + "DISPLAY=:1", + "DEBUGINFOD_URLS= ", + "XCURSOR_SIZE=24", + }) |target| { + for (environ) |variable| { + if (mem.eql(u8, mem.span(variable orelse continue), target)) break; + } else { + try testing.expect(false); // Environment variable not found + } + } +} + +test Map { + var env = Map.init(testing.allocator); + defer env.deinit(); + + try env.put("SOMETHING_NEW", "hello"); + try testing.expectEqualStrings("hello", env.get("SOMETHING_NEW").?); + try testing.expectEqual(@as(Map.Size, 1), env.count()); + + // overwrite + try env.put("SOMETHING_NEW", "something"); + try testing.expectEqualStrings("something", env.get("SOMETHING_NEW").?); + try testing.expectEqual(@as(Map.Size, 1), env.count()); + + // a new longer name to test the Windows-specific conversion buffer + try env.put("SOMETHING_NEW_AND_LONGER", "1"); + try testing.expectEqualStrings("1", env.get("SOMETHING_NEW_AND_LONGER").?); + try testing.expectEqual(@as(Map.Size, 2), env.count()); + + // case insensitivity on Windows only + if (native_os == .windows) { + try testing.expectEqualStrings("1", env.get("something_New_aNd_LONGER").?); + } else { + try testing.expect(null == env.get("something_New_aNd_LONGER")); + } + + var it = env.iterator(); + var count: Map.Size = 0; + while (it.next()) |entry| { + const is_an_expected_name = mem.eql(u8, "SOMETHING_NEW", entry.key_ptr.*) or mem.eql(u8, "SOMETHING_NEW_AND_LONGER", entry.key_ptr.*); + try testing.expect(is_an_expected_name); + count += 1; + } + try testing.expectEqual(@as(Map.Size, 2), count); + + try testing.expect(env.swapRemove("SOMETHING_NEW")); + try testing.expect(!env.swapRemove("SOMETHING_NEW")); + try testing.expect(env.get("SOMETHING_NEW") == null); + + try testing.expectEqual(@as(Map.Size, 1), env.count()); + + if (native_os == .windows) { + // test Unicode case-insensitivity on Windows + try env.put("КИРиллИЦА", "something else"); + try testing.expectEqualStrings("something else", env.get("кириллица").?); + + // and WTF-8 that's not valid UTF-8 + const wtf8_with_surrogate_pair = try unicode.wtf16LeToWtf8Alloc(testing.allocator, &[_]u16{ + mem.nativeToLittle(u16, 0xD83D), // unpaired high surrogate + }); + defer testing.allocator.free(wtf8_with_surrogate_pair); + + try env.put(wtf8_with_surrogate_pair, wtf8_with_surrogate_pair); + try testing.expectEqualSlices(u8, wtf8_with_surrogate_pair, env.get(wtf8_with_surrogate_pair).?); + } +} + +test "convert from Environ to Map and back again" { + if (native_os == .windows) return; + if (native_os == .wasi and !builtin.link_libc) return; + + const gpa = testing.allocator; + + var map: Map = .init(gpa); + defer map.deinit(); + try map.put("FOO", "BAR"); + try map.put("A", ""); + try map.put("", "B"); + + var arena_allocator = std.heap.ArenaAllocator.init(gpa); + defer arena_allocator.deinit(); + const arena = arena_allocator.allocator(); + + const environ: Environ = .{ .block = try map.createBlockPosix(arena, .{}) }; + + try testing.expectEqual(true, environ.contains(gpa, "FOO")); + try testing.expectEqual(false, environ.contains(gpa, "BAR")); + try testing.expectEqual(true, environ.contains(gpa, "A")); + try testing.expectEqual(true, environ.containsConstant("A")); + try testing.expectEqual(false, environ.containsUnempty(gpa, "A")); + try testing.expectEqual(false, environ.containsUnemptyConstant("A")); + try testing.expectEqual(true, environ.contains(gpa, "")); + try testing.expectEqual(false, environ.contains(gpa, "B")); + + try testing.expectError(error.EnvironmentVariableMissing, environ.getAlloc(gpa, "BOGUS")); + { + const value = try environ.getAlloc(gpa, "FOO"); + defer gpa.free(value); + try testing.expectEqualStrings("BAR", value); + } + + var map2 = try environ.createMap(gpa); + defer map2.deinit(); + + try testing.expectEqualDeep(map.keys(), map2.keys()); + try testing.expectEqualDeep(map.values(), map2.values()); +} + +test createMapWide { + if (builtin.cpu.arch.endian() == .big) return error.SkipZigTest; // TODO + + const gpa = testing.allocator; + + var map: Map = .init(gpa); + defer map.deinit(); + try map.put("FOO", "BAR"); + try map.put("A", ""); + try map.put("", "B"); + + const environ: [:0]u16 = try map.createBlockWindows(gpa); + defer gpa.free(environ); + + var map2 = try createMapWide(environ, gpa); + defer map2.deinit(); + + try testing.expectEqualDeep(&[_][]const u8{ "FOO", "A", "=B" }, map2.keys()); + try testing.expectEqualDeep(&[_][]const u8{ "BAR", "", "" }, map2.values()); +} diff --git a/lib/std/process/Preopens.zig b/lib/std/process/Preopens.zig new file mode 100644 index 000000000000..8223c29f83fa --- /dev/null +++ b/lib/std/process/Preopens.zig @@ -0,0 +1,75 @@ +const Preopens = @This(); + +const builtin = @import("builtin"); +const native_os = builtin.os.tag; + +const std = @import("../std.zig"); +const Io = std.Io; +const Allocator = std.mem.Allocator; + +map: Map, + +pub const empty: Preopens = switch (native_os) { + .wasi => .{ .map = .empty }, + else => .{ .map = {} }, +}; + +pub const Map = switch (native_os) { + // Indexed by file descriptor number. + .wasi => std.StringArrayHashMapUnmanaged(void), + else => void, +}; + +pub const Resource = union(enum) { + file: Io.File, + dir: Io.Dir, +}; + +pub fn get(p: *const Preopens, name: []const u8) ?Resource { + switch (native_os) { + .wasi => { + const index = p.map.getIndex(name) orelse return null; + if (index <= 2) return .{ .file = .{ .handle = @intCast(index) } }; + return .{ .dir = .{ .handle = @intCast(index) } }; + }, + else => { + if (std.mem.eql(u8, name, "stdin")) return .{ .file = .stdin() }; + if (std.mem.eql(u8, name, "stdout")) return .{ .file = .stdout() }; + if (std.mem.eql(u8, name, "stderr")) return .{ .file = .stderr() }; + return null; + }, + } +} + +pub const InitError = Allocator.Error || error{Unexpected}; + +pub fn init(arena: Allocator) InitError!Preopens { + if (native_os != .wasi) return .{ .map = {} }; + const wasi = std.os.wasi; + var map: Map = .empty; + + try map.ensureUnusedCapacity(arena, 3); + + map.putAssumeCapacityNoClobber("stdin", {}); // 0 + map.putAssumeCapacityNoClobber("stdout", {}); // 1 + map.putAssumeCapacityNoClobber("stderr", {}); // 2 + while (true) { + const fd: wasi.fd_t = @intCast(map.entries.len); + var prestat: wasi.prestat_t = undefined; + switch (wasi.fd_prestat_get(fd, &prestat)) { + .SUCCESS => {}, + .OPNOTSUPP, .BADF => return .{ .map = map }, + else => return error.Unexpected, + } + try map.ensureUnusedCapacity(arena, 1); + // This length does not include a null byte. Let's keep it this way to + // gently encourage WASI implementations to behave properly. + const name_len = prestat.u.dir.pr_name_len; + const name = try arena.alloc(u8, name_len); + switch (wasi.fd_prestat_dir_name(fd, name.ptr, name.len)) { + .SUCCESS => {}, + else => return error.Unexpected, + } + map.putAssumeCapacityNoClobber(name, {}); + } +} diff --git a/lib/std/sort.zig b/lib/std/sort.zig index 8705d2401730..9bee64ebe55c 100644 --- a/lib/std/sort.zig +++ b/lib/std/sort.zig @@ -678,18 +678,23 @@ pub fn partitionPoint( context: anytype, comptime predicate: fn (@TypeOf(context), T) bool, ) usize { - var low: usize = 0; - var high: usize = items.len; + var it: usize = 0; + var len: usize = items.len; - while (low < high) { - const mid = low + (high - low) / 2; - if (predicate(context, items[mid])) { - low = mid + 1; - } else { - high = mid; + while (len > 1) { + const half: usize = len / 2; + len -= half; + if (predicate(context, items[it + half - 1])) { + @branchHint(.unpredictable); + it += half; } } - return low; + + if (it < items.len) { + it += @intFromBool(predicate(context, items[it])); + } + + return it; } test partitionPoint { diff --git a/lib/std/start.zig b/lib/std/start.zig index a5bec4123108..685fda36353f 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -1,128 +1,76 @@ // This file is included in the compilation unit when exporting an executable. -const root = @import("root"); -const std = @import("std.zig"); const builtin = @import("builtin"); +const native_arch = builtin.cpu.arch; +const native_os = builtin.os.tag; +const is_wasm = native_arch.isWasm(); + +const std = @import("std.zig"); const assert = std.debug.assert; const uefi = std.os.uefi; const elf = std.elf; -const native_arch = builtin.cpu.arch; -const native_os = builtin.os.tag; -const start_sym_name = if (native_arch.isMIPS()) "__start" else "_start"; +const root = @import("root"); -// The self-hosted compiler is not fully capable of handling all of this start.zig file. -// Until then, we have simplified logic here for self-hosted. TODO remove this once -// self-hosted is capable enough to handle all of the real start.zig logic. -pub const simplified_logic = switch (builtin.zig_backend) { - .stage2_aarch64, - .stage2_arm, - .stage2_powerpc, - .stage2_sparc64, - .stage2_spirv, - .stage2_x86, - => true, - else => false, -}; +const start_sym_name = if (native_arch.isMIPS()) "__start" else "_start"; comptime { // No matter what, we import the root file, so that any export, test, comptime // decls there get run. _ = root; - if (simplified_logic) { - if (builtin.output_mode == .Exe) { - if ((builtin.link_libc or builtin.object_format == .c) and @hasDecl(root, "main")) { - if (!@typeInfo(@TypeOf(root.main)).@"fn".calling_convention.eql(.c)) { - @export(&main2, .{ .name = "main" }); - } - } else if (builtin.os.tag == .windows) { - if (!@hasDecl(root, "wWinMainCRTStartup") and !@hasDecl(root, "mainCRTStartup")) { - @export(&wWinMainCRTStartup2, .{ .name = "wWinMainCRTStartup" }); - } - } else if (builtin.os.tag == .opencl or builtin.os.tag == .vulkan) { - if (@hasDecl(root, "main")) - @export(&spirvMain2, .{ .name = "main" }); - } else { - if (!@hasDecl(root, "_start")) { - @export(&_start2, .{ .name = "_start" }); - } - } + if (builtin.output_mode == .Lib and builtin.link_mode == .dynamic) { + if (native_os == .windows and !@hasDecl(root, "_DllMainCRTStartup")) { + @export(&_DllMainCRTStartup, .{ .name = "_DllMainCRTStartup" }); } - } else { - if (builtin.output_mode == .Lib and builtin.link_mode == .dynamic) { - if (native_os == .windows and !@hasDecl(root, "_DllMainCRTStartup")) { - @export(&_DllMainCRTStartup, .{ .name = "_DllMainCRTStartup" }); + } else if (builtin.output_mode == .Exe or @hasDecl(root, "main")) { + if (builtin.link_libc and @hasDecl(root, "main")) { + if (is_wasm) { + @export(&mainWithoutEnv, .{ .name = "__main_argc_argv" }); + } else if (!@typeInfo(@TypeOf(root.main)).@"fn".calling_convention.eql(.c)) { + @export(&main, .{ .name = "main" }); } - } else if (builtin.output_mode == .Exe or @hasDecl(root, "main")) { - if (builtin.link_libc and @hasDecl(root, "main")) { - if (native_arch.isWasm()) { - @export(&mainWithoutEnv, .{ .name = "__main_argc_argv" }); - } else if (!@typeInfo(@TypeOf(root.main)).@"fn".calling_convention.eql(.c)) { - @export(&main, .{ .name = "main" }); - } - } else if (native_os == .windows and builtin.link_libc and @hasDecl(root, "wWinMain")) { - if (!@typeInfo(@TypeOf(root.wWinMain)).@"fn".calling_convention.eql(.c)) { - @export(&wWinMain, .{ .name = "wWinMain" }); - } - } else if (native_os == .windows) { - if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and - !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup")) - { - @export(&WinStartup, .{ .name = "wWinMainCRTStartup" }); - } else if (@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and - !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup")) - { - @compileError("WinMain not supported; declare wWinMain or main instead"); - } else if (@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup") and - !@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup")) - { - @export(&wWinMainCRTStartup, .{ .name = "wWinMainCRTStartup" }); - } - } else if (native_os == .uefi) { - if (!@hasDecl(root, "EfiMain")) @export(&EfiMain, .{ .name = "EfiMain" }); - } else if (native_os == .wasi) { - const wasm_start_sym = switch (builtin.wasi_exec_model) { - .reactor => "_initialize", - .command => "_start", - }; - if (!@hasDecl(root, wasm_start_sym) and @hasDecl(root, "main")) { - // Only call main when defined. For WebAssembly it's allowed to pass `-fno-entry` in which - // case it's not required to provide an entrypoint such as main. - @export(&wasi_start, .{ .name = wasm_start_sym }); - } - } else if (native_arch.isWasm() and native_os == .freestanding) { + } else if (native_os == .windows and builtin.link_libc and @hasDecl(root, "wWinMain")) { + if (!@typeInfo(@TypeOf(root.wWinMain)).@"fn".calling_convention.eql(.c)) { + @export(&wWinMain, .{ .name = "wWinMain" }); + } + } else if (native_os == .windows) { + if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and + !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup")) + { + @export(&WinStartup, .{ .name = "wWinMainCRTStartup" }); + } else if (@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and + !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup")) + { + @compileError("WinMain not supported; declare wWinMain or main instead"); + } else if (@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup") and + !@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup")) + { + @export(&wWinMainCRTStartup, .{ .name = "wWinMainCRTStartup" }); + } + } else if (native_os == .uefi) { + if (!@hasDecl(root, "EfiMain")) @export(&EfiMain, .{ .name = "EfiMain" }); + } else if (native_os == .wasi) { + const wasm_start_sym = switch (builtin.wasi_exec_model) { + .reactor => "_initialize", + .command => "_start", + }; + if (!@hasDecl(root, wasm_start_sym) and @hasDecl(root, "main")) { // Only call main when defined. For WebAssembly it's allowed to pass `-fno-entry` in which // case it's not required to provide an entrypoint such as main. - if (!@hasDecl(root, start_sym_name) and @hasDecl(root, "main")) @export(&wasm_freestanding_start, .{ .name = start_sym_name }); - } else switch (native_os) { - .other, .freestanding, .@"3ds", .vita => {}, - else => if (!@hasDecl(root, start_sym_name)) @export(&_start, .{ .name = start_sym_name }), + @export(&startWasi, .{ .name = wasm_start_sym }); } + } else if (is_wasm and native_os == .freestanding) { + // Only call main when defined. For WebAssembly it's allowed to pass `-fno-entry` in which + // case it's not required to provide an entrypoint such as main. + if (!@hasDecl(root, start_sym_name) and @hasDecl(root, "main")) @export(&wasm_freestanding_start, .{ .name = start_sym_name }); + } else switch (native_os) { + .other, .freestanding, .@"3ds", .vita => {}, + else => if (!@hasDecl(root, start_sym_name)) @export(&_start, .{ .name = start_sym_name }), } } } -// Simplified start code for stage2 until it supports more language features /// - -fn main2() callconv(.c) c_int { - return callMain(); -} - -fn _start2() callconv(.withStackAlign(.c, 1)) noreturn { - std.posix.exit(callMain()); -} - -fn spirvMain2() callconv(.kernel) void { - root.main(); -} - -fn wWinMainCRTStartup2() callconv(.c) noreturn { - std.posix.exit(callMain()); -} - -//////////////////////////////////////////////////////////////////////////////// - fn _DllMainCRTStartup( hinstDLL: std.os.windows.HINSTANCE, fdwReason: std.os.windows.DWORD, @@ -142,15 +90,15 @@ fn _DllMainCRTStartup( fn wasm_freestanding_start() callconv(.c) void { // This is marked inline because for some reason LLVM in // release mode fails to inline it, and we want fewer call frames in stack traces. - _ = @call(.always_inline, callMain, .{}); + _ = @call(.always_inline, callMain, .{ {}, {} }); } -fn wasi_start() callconv(.c) void { +fn startWasi() callconv(.c) void { // The function call is marked inline because for some reason LLVM in // release mode fails to inline it, and we want fewer call frames in stack traces. switch (builtin.wasi_exec_model) { - .reactor => _ = @call(.always_inline, callMain, .{}), - .command => std.os.wasi.proc_exit(@call(.always_inline, callMain, .{})), + .reactor => _ = @call(.always_inline, callMain, .{ {}, {} }), + .command => std.os.wasi.proc_exit(@call(.always_inline, callMain, .{ {}, {} })), } } @@ -524,7 +472,10 @@ fn WinStartup() callconv(.withStackAlign(.c, 1)) noreturn { std.debug.maybeEnableSegfaultHandler(); - std.os.windows.ntdll.RtlExitUserProcess(callMain()); + const cmd_line = std.os.windows.peb().ProcessParameters.CommandLine; + const cmd_line_w = cmd_line.Buffer.?[0..@divExact(cmd_line.Length, 2)]; + + std.os.windows.ntdll.RtlExitUserProcess(callMain(cmd_line_w, {})); } fn wWinMainCRTStartup() callconv(.withStackAlign(.c, 1)) noreturn { @@ -556,7 +507,7 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn { const envp_optional: [*:null]?[*:0]u8 = @ptrCast(@alignCast(argv + argc + 1)); var envp_count: usize = 0; while (envp_optional[envp_count]) |_| : (envp_count += 1) {} - const envp = @as([*][*:0]u8, @ptrCast(envp_optional))[0..envp_count]; + const envp = envp_optional[0..envp_count :null]; // Find the beginning of the auxiliary vector const auxv: [*]elf.Auxv = @ptrCast(@alignCast(envp.ptr + envp_count + 1)); @@ -627,10 +578,11 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn { for (slice) |func| func(); } - std.posix.exit(callMainWithArgs(argc, argv, envp)); + std.process.exit(callMainWithArgs(argc, argv, envp)); } fn expandStackSize(phdrs: []elf.Phdr) void { + @disableInstrumentation(); for (phdrs) |*phdr| { switch (phdr.p_type) { elf.PT_GNU_STACK => { @@ -665,82 +617,141 @@ fn expandStackSize(phdrs: []elf.Phdr) void { } } -inline fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 { - std.os.argv = argv[0..argc]; - std.os.environ = envp; - +inline fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [:null]?[*:0]u8) u8 { + if (std.Options.debug_threaded_io) |t| { + if (@sizeOf(std.Io.Threaded.Argv0) != 0) t.argv0.value = argv[0]; + t.environ = .{ .process_environ = .{ .block = envp } }; + } std.debug.maybeEnableSegfaultHandler(); - - return callMain(); + return callMain(argv[0..argc], envp); } fn main(c_argc: c_int, c_argv: [*][*:0]c_char, c_envp: [*:null]?[*:0]c_char) callconv(.c) c_int { var env_count: usize = 0; while (c_envp[env_count] != null) : (env_count += 1) {} - const envp = @as([*][*:0]u8, @ptrCast(c_envp))[0..env_count]; - - if (builtin.os.tag == .linux) { - const at_phdr = std.c.getauxval(elf.AT_PHDR); - const at_phnum = std.c.getauxval(elf.AT_PHNUM); - const phdrs = (@as([*]elf.Phdr, @ptrFromInt(at_phdr)))[0..at_phnum]; - expandStackSize(phdrs); + const envp = c_envp[0..env_count :null]; + + switch (builtin.os.tag) { + .linux => { + const at_phdr = std.c.getauxval(elf.AT_PHDR); + const at_phnum = std.c.getauxval(elf.AT_PHNUM); + const phdrs = (@as([*]elf.Phdr, @ptrFromInt(at_phdr)))[0..at_phnum]; + expandStackSize(phdrs); + }, + .windows => { + // On Windows, we ignore libc environment and argv and get those + // values in their intended encoding from the PEB instead. + std.debug.maybeEnableSegfaultHandler(); + const cmd_line = std.os.windows.peb().ProcessParameters.CommandLine; + const cmd_line_w = cmd_line.Buffer.?[0..@divExact(cmd_line.Length, 2)]; + return callMain(cmd_line_w, {}); + }, + else => {}, } - return callMainWithArgs(@as(usize, @intCast(c_argc)), @as([*][*:0]u8, @ptrCast(c_argv)), envp); + return callMainWithArgs(@as(usize, @intCast(c_argc)), @as([*][*:0]u8, @ptrCast(c_argv)), @ptrCast(envp)); } fn mainWithoutEnv(c_argc: c_int, c_argv: [*][*:0]c_char) callconv(.c) c_int { - std.os.argv = @as([*][*:0]u8, @ptrCast(c_argv))[0..@intCast(c_argc)]; - return callMain(); + const argv = @as([*][*:0]u8, @ptrCast(c_argv))[0..@intCast(c_argc)]; + if (@sizeOf(std.Io.Threaded.Argv0) != 0) { + if (std.Options.debug_threaded_io) |t| t.argv0.value = argv[0]; + } + return callMain(argv, &.{}); } -// General error message for a malformed return type +/// General error message for a malformed return type const bad_main_ret = "expected return type of main to be 'void', '!void', 'noreturn', 'u8', or '!u8'"; -pub inline fn callMain() u8 { - const ReturnType = @typeInfo(@TypeOf(root.main)).@"fn".return_type.?; +const use_debug_allocator = !is_wasm and switch (builtin.mode) { + .Debug => true, + .ReleaseSafe => !builtin.link_libc, // Not ideal, but the best we have for now. + .ReleaseFast, .ReleaseSmall => !builtin.link_libc and builtin.single_threaded, // Also not ideal. +}; +var debug_allocator: std.heap.DebugAllocator(.{}) = .init; + +inline fn callMain(args: std.process.Args.Vector, environ: std.process.Environ.Block) u8 { + const fn_info = @typeInfo(@TypeOf(root.main)).@"fn"; + if (fn_info.params.len == 0) return wrapMain(root.main()); + if (fn_info.params[0].type.? == std.process.Init.Minimal) return wrapMain(root.main(.{ + .args = .{ .vector = args }, + .environ = .{ .block = environ }, + })); + + const gpa = if (use_debug_allocator) + debug_allocator.allocator() + else if (builtin.link_libc) + std.heap.c_allocator + else if (is_wasm) + std.heap.wasm_allocator + else if (!builtin.single_threaded) + std.heap.smp_allocator + else + comptime unreachable; + + defer if (use_debug_allocator) { + _ = debug_allocator.deinit(); // Leaks do not affect return code. + }; - switch (ReturnType) { - void => { - root.main(); - return 0; - }, - noreturn, u8 => { - return root.main(); - }, - else => { - if (@typeInfo(ReturnType) != .error_union) @compileError(bad_main_ret); - - const result = root.main() catch |err| { - switch (builtin.zig_backend) { - .stage2_powerpc, - .stage2_riscv64, - => { - _ = std.posix.write(std.posix.STDERR_FILENO, "error: failed with error\n") catch {}; - return 1; - }, - else => {}, - } - std.log.err("{s}", .{@errorName(err)}); - switch (native_os) { - .freestanding, .other => {}, - else => if (@errorReturnTrace()) |trace| { - std.debug.dumpStackTrace(trace); - }, - } - return 1; - }; + const arena_backing_allocator = if (is_wasm) gpa else std.heap.page_allocator; - return switch (@TypeOf(result)) { - void => 0, - u8 => result, - else => @compileError(bad_main_ret), - }; + var arena_allocator = std.heap.ArenaAllocator.init(arena_backing_allocator); + defer arena_allocator.deinit(); + + var threaded: std.Io.Threaded = .init(gpa, .{ + .argv0 = .init(.{ .vector = args }), + .environ = .{ .block = environ }, + }); + defer threaded.deinit(); + + var environ_map = std.process.Environ.createMap(.{ .block = environ }, gpa) catch |err| + std.process.fatal("failed to parse environment variables: {t}", .{err}); + defer environ_map.deinit(); + + const preopens = std.process.Preopens.init(arena_allocator.allocator()) catch |err| + std.process.fatal("failed to init preopens: {t}", .{err}); + + return wrapMain(root.main(.{ + .minimal = .{ + .args = .{ .vector = args }, + .environ = .{ .block = environ }, }, + .arena = &arena_allocator, + .gpa = gpa, + .io = threaded.io(), + .environ_map = &environ_map, + .preopens = preopens, + })); +} + +inline fn wrapMain(result: anytype) u8 { + const ReturnType = @TypeOf(result); + switch (ReturnType) { + void => return 0, + noreturn => unreachable, + u8 => return result, + else => {}, } + if (@typeInfo(ReturnType) != .error_union) @compileError(bad_main_ret); + + const unwrapped_result = result catch |err| { + std.log.err("{t}", .{err}); + switch (native_os) { + .freestanding, .other => {}, + else => if (@errorReturnTrace()) |trace| std.debug.dumpStackTrace(trace), + } + return 1; + }; + + return switch (@TypeOf(unwrapped_result)) { + noreturn => unreachable, + void => 0, + u8 => unwrapped_result, + else => @compileError(bad_main_ret), + }; } -pub fn call_wWinMain() std.os.windows.INT { +fn call_wWinMain() std.os.windows.INT { const peb = std.os.windows.peb(); const MAIN_HINSTANCE = @typeInfo(@TypeOf(root.wWinMain)).@"fn".params[0].type.?; const hInstance: MAIN_HINSTANCE = @ptrCast(peb.ImageBaseAddress); diff --git a/lib/std/std.zig b/lib/std/std.zig index 5c500d3f55d3..a22cc6d31205 100644 --- a/lib/std/std.zig +++ b/lib/std/std.zig @@ -108,15 +108,12 @@ pub const start = @import("start.zig"); const root = @import("root"); -/// Stdlib-wide options that can be overridden by the root file. +/// Compile-time known settings overridable by the root source file. pub const options: Options = if (@hasDecl(root, "std_options")) root.std_options else .{}; pub const Options = struct { enable_segfault_handler: bool = debug.default_enable_segfault_handler, - /// Function used to implement `std.fs.cwd` for WASI. - wasiCwd: fn () os.wasi.fd_t = fs.defaultWasiCwd, - /// The current log level. log_level: log.Level = log.default_level, @@ -129,6 +126,8 @@ pub const Options = struct { args: anytype, ) void = log.defaultLog, + logTerminalMode: fn () Io.Terminal.Mode = log.defaultTerminalMode, + /// Overrides `std.heap.page_size_min`. page_size_min: ?usize = null, /// Overrides `std.heap.page_size_max`. @@ -138,12 +137,6 @@ pub const Options = struct { fmt_max_depth: usize = fmt.default_max_depth, - cryptoRandomSeed: fn (buffer: []u8) void = @import("crypto/tlcsprng.zig").defaultRandomSeed, - - crypto_always_getrandom: bool = false, - - crypto_fork_safety: bool = true, - /// By default, std.http.Client will support HTTPS connections. Set this option to `true` to /// disable TLS support. /// @@ -173,6 +166,38 @@ pub const Options = struct { /// If this is `false`, then captured stack traces will always be empty, and attempts to write /// stack traces will just print an error to the relevant `Io.Writer` and return. allow_stack_tracing: bool = !@import("builtin").strip_debug_info, + + /// TODO This is a separate decl instead of a field as a workaround around + /// compilation errors due to zig not being lazy enough. + pub const elf_debug_info_search_paths: ?fn (exe_path: []const u8) switch (@import("builtin").object_format) { + .elf => debug.ElfFile.DebugInfoSearchPaths, + else => void, + } = if (@hasDecl(root, "std_options_elf_debug_info_search_paths")) + root.std_options_elf_debug_info_search_paths + else + null; + + pub const debug_threaded_io: ?*Io.Threaded = if (@hasDecl(root, "std_options_debug_threaded_io")) + root.std_options_debug_threaded_io + else + Io.Threaded.global_single_threaded; + + /// The `Io` instance that `std.debug` uses for `std.debug.print`, + /// capturing stack traces, loading debug info, finding the executable's + /// own path, and environment variables that affect terminal mode + /// detection. The default is to use statically initialized singleton that + /// is independent from the application's `Io` instance in order to make + /// debugging more straightforward. For example, while debugging an `Io` + /// implementation based on coroutines, one likely wants `std.debug.print` + /// to directly write to stderr without trying to interact with the code + /// being debugged. + pub const debug_io: Io = if (@hasDecl(root, "std_options_debug_io")) root.std_options_debug_io else debug_threaded_io.?.ioBasic(); + + /// Overrides `std.Io.File.Permissions`. + pub const FilePermissions: ?type = if (@hasDecl(root, "std_options_FilePermissions")) root.std_options_FilePermissions else null; + + /// Overrides `std.Io.Dir.cwd`. + pub const cwd: ?fn () Io.Dir = if (@hasDecl(root, "std_options_cwd")) root.std_options_cwd else null; }; // This forces the start.zig file to be imported, and the comptime logic inside that diff --git a/lib/std/tar.zig b/lib/std/tar.zig index 0fe314301a4c..024a425919af 100644 --- a/lib/std/tar.zig +++ b/lib/std/tar.zig @@ -16,6 +16,7 @@ //! pax reference: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html#tag_20_92_13 const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; const testing = std.testing; @@ -71,7 +72,7 @@ pub const Diagnostics = struct { const start_index: usize = if (path[0] == '/') 1 else 0; const end_index: usize = if (path[path.len - 1] == '/') path.len - 1 else path.len; const buf = path[start_index..end_index]; - if (std.mem.indexOfScalarPos(u8, buf, 0, '/')) |idx| { + if (std.mem.findScalarPos(u8, buf, 0, '/')) |idx| { return buf[0..idx]; } @@ -302,7 +303,7 @@ pub const FileKind = enum { /// Iterator over entries in the tar file represented by reader. pub const Iterator = struct { - reader: *std.Io.Reader, + reader: *Io.Reader, diagnostics: ?*Diagnostics = null, // buffers for heeader and file attributes @@ -328,7 +329,7 @@ pub const Iterator = struct { /// Iterates over files in tar archive. /// `next` returns each file in tar archive. - pub fn init(reader: *std.Io.Reader, options: Options) Iterator { + pub fn init(reader: *Io.Reader, options: Options) Iterator { return .{ .reader = reader, .diagnostics = options.diagnostics, @@ -473,7 +474,7 @@ pub const Iterator = struct { return null; } - pub fn streamRemaining(it: *Iterator, file: File, w: *std.Io.Writer) std.Io.Reader.StreamError!void { + pub fn streamRemaining(it: *Iterator, file: File, w: *Io.Writer) Io.Reader.StreamError!void { try it.reader.streamExact64(w, file.size); it.unread_file_bytes = 0; } @@ -499,14 +500,14 @@ const pax_max_size_attr_len = 64; pub const PaxIterator = struct { size: usize, // cumulative size of all pax attributes - reader: *std.Io.Reader, + reader: *Io.Reader, const Self = @This(); const Attribute = struct { kind: PaxAttributeKind, len: usize, // length of the attribute value - reader: *std.Io.Reader, // reader positioned at value start + reader: *Io.Reader, // reader positioned at value start // Copies pax attribute value into destination buffer. // Must be called with destination buffer of size at least Attribute.len. @@ -569,17 +570,17 @@ pub const PaxIterator = struct { } fn hasNull(str: []const u8) bool { - return (std.mem.indexOfScalar(u8, str, 0)) != null; + return (std.mem.findScalar(u8, str, 0)) != null; } // Checks that each record ends with new line. - fn validateAttributeEnding(reader: *std.Io.Reader) !void { + fn validateAttributeEnding(reader: *Io.Reader) !void { if (try reader.takeByte() != '\n') return error.PaxInvalidAttributeEnd; } }; /// Saves tar file content to the file systems. -pub fn pipeToFileSystem(dir: std.fs.Dir, reader: *std.Io.Reader, options: PipeOptions) !void { +pub fn pipeToFileSystem(io: Io, dir: Io.Dir, reader: *Io.Reader, options: PipeOptions) !void { var file_name_buffer: [std.fs.max_path_bytes]u8 = undefined; var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined; var file_contents_buffer: [1024]u8 = undefined; @@ -605,13 +606,13 @@ pub fn pipeToFileSystem(dir: std.fs.Dir, reader: *std.Io.Reader, options: PipeOp switch (file.kind) { .directory => { if (file_name.len > 0 and !options.exclude_empty_directories) { - try dir.makePath(file_name); + try dir.createDirPath(io, file_name); } }, .file => { - if (createDirAndFile(dir, file_name, fileMode(file.mode, options))) |fs_file| { - defer fs_file.close(); - var file_writer = fs_file.writer(&file_contents_buffer); + if (createDirAndFile(io, dir, file_name, filePermissions(file.mode, options))) |fs_file| { + defer fs_file.close(io); + var file_writer = fs_file.writer(io, &file_contents_buffer); try it.streamRemaining(file, &file_writer.interface); try file_writer.interface.flush(); } else |err| { @@ -624,7 +625,7 @@ pub fn pipeToFileSystem(dir: std.fs.Dir, reader: *std.Io.Reader, options: PipeOp }, .sym_link => { const link_name = file.link_name; - createDirAndSymlink(dir, link_name, file_name) catch |err| { + createDirAndSymlink(io, dir, link_name, file_name) catch |err| { const d = options.diagnostics orelse return error.UnableToCreateSymLink; try d.errors.append(d.allocator, .{ .unable_to_create_sym_link = .{ .code = err, @@ -637,12 +638,12 @@ pub fn pipeToFileSystem(dir: std.fs.Dir, reader: *std.Io.Reader, options: PipeOp } } -fn createDirAndFile(dir: std.fs.Dir, file_name: []const u8, mode: std.fs.File.Mode) !std.fs.File { - const fs_file = dir.createFile(file_name, .{ .exclusive = true, .mode = mode }) catch |err| { +fn createDirAndFile(io: Io, dir: Io.Dir, file_name: []const u8, permissions: Io.File.Permissions) !Io.File { + const fs_file = dir.createFile(io, file_name, .{ .exclusive = true, .permissions = permissions }) catch |err| { if (err == error.FileNotFound) { if (std.fs.path.dirname(file_name)) |dir_name| { - try dir.makePath(dir_name); - return try dir.createFile(file_name, .{ .exclusive = true, .mode = mode }); + try dir.createDirPath(io, dir_name); + return try dir.createFile(io, file_name, .{ .exclusive = true, .permissions = permissions }); } } return err; @@ -651,12 +652,12 @@ fn createDirAndFile(dir: std.fs.Dir, file_name: []const u8, mode: std.fs.File.Mo } // Creates a symbolic link at path `file_name` which points to `link_name`. -fn createDirAndSymlink(dir: std.fs.Dir, link_name: []const u8, file_name: []const u8) !void { - dir.symLink(link_name, file_name, .{}) catch |err| { +fn createDirAndSymlink(io: Io, dir: Io.Dir, link_name: []const u8, file_name: []const u8) !void { + dir.symLink(io, link_name, file_name, .{}) catch |err| { if (err == error.FileNotFound) { if (std.fs.path.dirname(file_name)) |dir_name| { - try dir.makePath(dir_name); - return try dir.symLink(link_name, file_name, .{}); + try dir.createDirPath(io, dir_name); + return try dir.symLink(io, link_name, file_name, .{}); } } return err; @@ -667,7 +668,7 @@ fn stripComponents(path: []const u8, count: u32) []const u8 { var i: usize = 0; var c = count; while (c > 0) : (c -= 1) { - if (std.mem.indexOfScalarPos(u8, path, i, '/')) |pos| { + if (std.mem.findScalarPos(u8, path, i, '/')) |pos| { i = pos + 1; } else { i = path.len; @@ -783,7 +784,7 @@ test PaxIterator { var buffer: [1024]u8 = undefined; outer: for (cases) |case| { - var reader: std.Io.Reader = .fixed(case.data); + var reader: Io.Reader = .fixed(case.data); var it: PaxIterator = .{ .size = case.data.len, .reader = &reader, @@ -874,25 +875,27 @@ test "header parse mode" { } test "create file and symlink" { + const io = testing.io; + var root = testing.tmpDir(.{}); defer root.cleanup(); - var file = try createDirAndFile(root.dir, "file1", default_mode); - file.close(); - file = try createDirAndFile(root.dir, "a/b/c/file2", default_mode); - file.close(); + var file = try createDirAndFile(io, root.dir, "file1", .default_file); + file.close(io); + file = try createDirAndFile(io, root.dir, "a/b/c/file2", .default_file); + file.close(io); - createDirAndSymlink(root.dir, "a/b/c/file2", "symlink1") catch |err| { + createDirAndSymlink(io, root.dir, "a/b/c/file2", "symlink1") catch |err| { // On Windows when developer mode is not enabled if (err == error.AccessDenied) return error.SkipZigTest; return err; }; - try createDirAndSymlink(root.dir, "../../../file1", "d/e/f/symlink2"); + try createDirAndSymlink(io, root.dir, "../../../file1", "d/e/f/symlink2"); // Danglink symlnik, file created later - try createDirAndSymlink(root.dir, "../../../g/h/i/file4", "j/k/l/symlink3"); - file = try createDirAndFile(root.dir, "g/h/i/file4", default_mode); - file.close(); + try createDirAndSymlink(io, root.dir, "../../../g/h/i/file4", "j/k/l/symlink3"); + file = try createDirAndFile(io, root.dir, "g/h/i/file4", .default_file); + file.close(io); } test Iterator { @@ -916,7 +919,7 @@ test Iterator { // example/empty/ const data = @embedFile("tar/testdata/example.tar"); - var reader: std.Io.Reader = .fixed(data); + var reader: Io.Reader = .fixed(data); // User provided buffers to the iterator var file_name_buffer: [std.fs.max_path_bytes]u8 = undefined; @@ -942,7 +945,7 @@ test Iterator { .file => { try testing.expectEqualStrings("example/a/file", file.name); var buf: [16]u8 = undefined; - var w: std.Io.Writer = .fixed(&buf); + var w: Io.Writer = .fixed(&buf); try it.streamRemaining(file, &w); try testing.expectEqualStrings("content\n", w.buffered()); }, @@ -955,6 +958,7 @@ test Iterator { } test pipeToFileSystem { + const io = testing.io; // Example tar file is created from this tree structure: // $ tree example // example @@ -975,14 +979,14 @@ test pipeToFileSystem { // example/empty/ const data = @embedFile("tar/testdata/example.tar"); - var reader: std.Io.Reader = .fixed(data); + var reader: Io.Reader = .fixed(data); var tmp = testing.tmpDir(.{ .follow_symlinks = false }); defer tmp.cleanup(); const dir = tmp.dir; // Save tar from reader to the file system `dir` - pipeToFileSystem(dir, &reader, .{ + pipeToFileSystem(io, dir, &reader, .{ .mode_mode = .ignore, .strip_components = 1, .exclude_empty_directories = true, @@ -992,21 +996,22 @@ test pipeToFileSystem { return err; }; - try testing.expectError(error.FileNotFound, dir.statFile("empty")); - try testing.expect((try dir.statFile("a/file")).kind == .file); - try testing.expect((try dir.statFile("b/symlink")).kind == .file); // statFile follows symlink + try testing.expectError(error.FileNotFound, dir.statFile(io, "empty", .{})); + try testing.expect((try dir.statFile(io, "a/file", .{})).kind == .file); + try testing.expect((try dir.statFile(io, "b/symlink", .{})).kind == .file); // statFile follows symlink var buf: [32]u8 = undefined; try testing.expectEqualSlices( u8, "../a/file", - normalizePath(try dir.readLink("b/symlink", &buf)), + normalizePath(buf[0..try dir.readLink(io, "b/symlink", &buf)]), ); } test "pipeToFileSystem root_dir" { + const io = testing.io; const data = @embedFile("tar/testdata/example.tar"); - var reader: std.Io.Reader = .fixed(data); + var reader: Io.Reader = .fixed(data); // with strip_components = 1 { @@ -1015,7 +1020,7 @@ test "pipeToFileSystem root_dir" { var diagnostics: Diagnostics = .{ .allocator = testing.allocator }; defer diagnostics.deinit(); - pipeToFileSystem(tmp.dir, &reader, .{ + pipeToFileSystem(io, tmp.dir, &reader, .{ .strip_components = 1, .diagnostics = &diagnostics, }) catch |err| { @@ -1037,7 +1042,7 @@ test "pipeToFileSystem root_dir" { var diagnostics: Diagnostics = .{ .allocator = testing.allocator }; defer diagnostics.deinit(); - pipeToFileSystem(tmp.dir, &reader, .{ + pipeToFileSystem(io, tmp.dir, &reader, .{ .strip_components = 0, .diagnostics = &diagnostics, }) catch |err| { @@ -1053,43 +1058,46 @@ test "pipeToFileSystem root_dir" { } test "findRoot with single file archive" { + const io = testing.io; const data = @embedFile("tar/testdata/22752.tar"); - var reader: std.Io.Reader = .fixed(data); + var reader: Io.Reader = .fixed(data); var tmp = testing.tmpDir(.{}); defer tmp.cleanup(); var diagnostics: Diagnostics = .{ .allocator = testing.allocator }; defer diagnostics.deinit(); - try pipeToFileSystem(tmp.dir, &reader, .{ .diagnostics = &diagnostics }); + try pipeToFileSystem(io, tmp.dir, &reader, .{ .diagnostics = &diagnostics }); try testing.expectEqualStrings("", diagnostics.root_dir); } test "findRoot without explicit root dir" { + const io = testing.io; const data = @embedFile("tar/testdata/19820.tar"); - var reader: std.Io.Reader = .fixed(data); + var reader: Io.Reader = .fixed(data); var tmp = testing.tmpDir(.{}); defer tmp.cleanup(); var diagnostics: Diagnostics = .{ .allocator = testing.allocator }; defer diagnostics.deinit(); - try pipeToFileSystem(tmp.dir, &reader, .{ .diagnostics = &diagnostics }); + try pipeToFileSystem(io, tmp.dir, &reader, .{ .diagnostics = &diagnostics }); try testing.expectEqualStrings("root", diagnostics.root_dir); } test "pipeToFileSystem strip_components" { + const io = testing.io; const data = @embedFile("tar/testdata/example.tar"); - var reader: std.Io.Reader = .fixed(data); + var reader: Io.Reader = .fixed(data); var tmp = testing.tmpDir(.{ .follow_symlinks = false }); defer tmp.cleanup(); var diagnostics: Diagnostics = .{ .allocator = testing.allocator }; defer diagnostics.deinit(); - pipeToFileSystem(tmp.dir, &reader, .{ + pipeToFileSystem(io, tmp.dir, &reader, .{ .strip_components = 3, .diagnostics = &diagnostics, }) catch |err| { @@ -1110,45 +1118,36 @@ fn normalizePath(bytes: []u8) []u8 { return bytes; } -const default_mode = std.fs.File.default_mode; - // File system mode based on tar header mode and mode_mode options. -fn fileMode(mode: u32, options: PipeOptions) std.fs.File.Mode { - if (!std.fs.has_executable_bit or options.mode_mode == .ignore) - return default_mode; - - const S = std.posix.S; - - // The mode from the tar file is inspected for the owner executable bit. - if (mode & S.IXUSR == 0) - return default_mode; - - // This bit is copied to the group and other executable bits. - // Other bits of the mode are left as the default when creating files. - return default_mode | S.IXUSR | S.IXGRP | S.IXOTH; +fn filePermissions(mode: u32, options: PipeOptions) Io.File.Permissions { + return if (!Io.File.Permissions.has_executable_bit or options.mode_mode == .ignore or (mode & 0o100) == 0) + .default_file + else + .executable_file; } -test fileMode { - if (!std.fs.has_executable_bit) return error.SkipZigTest; - try testing.expectEqual(default_mode, fileMode(0o744, PipeOptions{ .mode_mode = .ignore })); - try testing.expectEqual(0o777, fileMode(0o744, PipeOptions{})); - try testing.expectEqual(0o666, fileMode(0o644, PipeOptions{})); - try testing.expectEqual(0o666, fileMode(0o655, PipeOptions{})); +test filePermissions { + if (!Io.File.Permissions.has_executable_bit) return error.SkipZigTest; + try testing.expectEqual(.default_file, filePermissions(0o744, .{ .mode_mode = .ignore })); + try testing.expectEqual(.executable_file, filePermissions(0o744, .{})); + try testing.expectEqual(.default_file, filePermissions(0o644, .{})); + try testing.expectEqual(.default_file, filePermissions(0o655, .{})); } test "executable bit" { - if (!std.fs.has_executable_bit) return error.SkipZigTest; + if (!Io.File.Permissions.has_executable_bit) return error.SkipZigTest; + const io = testing.io; const S = std.posix.S; const data = @embedFile("tar/testdata/example.tar"); for ([_]PipeOptions.ModeMode{ .ignore, .executable_bit_only }) |opt| { - var reader: std.Io.Reader = .fixed(data); + var reader: Io.Reader = .fixed(data); var tmp = testing.tmpDir(.{ .follow_symlinks = false }); //defer tmp.cleanup(); - pipeToFileSystem(tmp.dir, &reader, .{ + pipeToFileSystem(io, tmp.dir, &reader, .{ .strip_components = 1, .exclude_empty_directories = true, .mode_mode = opt, @@ -1158,19 +1157,21 @@ test "executable bit" { return err; }; - const fs = try tmp.dir.statFile("a/file"); + const fs = try tmp.dir.statFile(io, "a/file", .{}); try testing.expect(fs.kind == .file); + const mode = fs.permissions.toMode(); + if (opt == .executable_bit_only) { // Executable bit is set for user, group and others - try testing.expect(fs.mode & S.IXUSR > 0); - try testing.expect(fs.mode & S.IXGRP > 0); - try testing.expect(fs.mode & S.IXOTH > 0); + try testing.expect(mode & S.IXUSR > 0); + try testing.expect(mode & S.IXGRP > 0); + try testing.expect(mode & S.IXOTH > 0); } if (opt == .ignore) { - try testing.expect(fs.mode & S.IXUSR == 0); - try testing.expect(fs.mode & S.IXGRP == 0); - try testing.expect(fs.mode & S.IXOTH == 0); + try testing.expect(mode & S.IXUSR == 0); + try testing.expect(mode & S.IXGRP == 0); + try testing.expect(mode & S.IXOTH == 0); } } } diff --git a/lib/std/tar/test.zig b/lib/std/tar/test.zig index 780e2b844cb1..61aeb03519c8 100644 --- a/lib/std/tar/test.zig +++ b/lib/std/tar/test.zig @@ -424,6 +424,7 @@ test "insufficient buffer in Header name filed" { } test "should not overwrite existing file" { + const io = testing.io; // Starting from this folder structure: // $ tree root // root @@ -469,17 +470,18 @@ test "should not overwrite existing file" { defer root.cleanup(); try testing.expectError( error.PathAlreadyExists, - tar.pipeToFileSystem(root.dir, &r, .{ .mode_mode = .ignore, .strip_components = 1 }), + tar.pipeToFileSystem(io, root.dir, &r, .{ .mode_mode = .ignore, .strip_components = 1 }), ); // Unpack with strip_components = 0 should pass r = .fixed(data); var root2 = std.testing.tmpDir(.{}); defer root2.cleanup(); - try tar.pipeToFileSystem(root2.dir, &r, .{ .mode_mode = .ignore, .strip_components = 0 }); + try tar.pipeToFileSystem(io, root2.dir, &r, .{ .mode_mode = .ignore, .strip_components = 0 }); } test "case sensitivity" { + const io = testing.io; // Mimicking issue #18089, this tar contains, same file name in two case // sensitive name version. Should fail on case insensitive file systems. // @@ -495,13 +497,13 @@ test "case sensitivity" { var root = std.testing.tmpDir(.{}); defer root.cleanup(); - tar.pipeToFileSystem(root.dir, &r, .{ .mode_mode = .ignore, .strip_components = 1 }) catch |err| { + tar.pipeToFileSystem(io, root.dir, &r, .{ .mode_mode = .ignore, .strip_components = 1 }) catch |err| { // on case insensitive fs we fail on overwrite existing file try testing.expectEqual(error.PathAlreadyExists, err); return; }; // on case sensitive os both files are created - try testing.expect((try root.dir.statFile("alacritty/darkermatrix.yml")).kind == .file); - try testing.expect((try root.dir.statFile("alacritty/Darkermatrix.yml")).kind == .file); + try testing.expect((try root.dir.statFile(io, "alacritty/darkermatrix.yml", .{})).kind == .file); + try testing.expect((try root.dir.statFile(io, "alacritty/Darkermatrix.yml", .{})).kind == .file); } diff --git a/lib/std/testing.zig b/lib/std/testing.zig index d12ac3bf21b3..03e1d06c1894 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -1,5 +1,7 @@ -const std = @import("std.zig"); const builtin = @import("builtin"); + +const std = @import("std.zig"); +const Io = std.Io; const assert = std.debug.assert; const math = std.math; @@ -28,8 +30,8 @@ pub var allocator_instance: std.heap.GeneralPurposeAllocator(.{ break :b .init; }; -pub var io_instance: std.Io.Threaded = undefined; -pub const io = io_instance.io(); +pub var io_instance: Io.Threaded = undefined; +pub const io = if (builtin.is_test) io_instance.io() else @compileError("not testing"); /// TODO https://github.com/ziglang/zig/issues/5738 pub var log_level = std.log.Level.warn; @@ -352,11 +354,10 @@ test expectApproxEqRel { } } -/// This function is intended to be used only in tests. When the two slices are not -/// equal, prints diagnostics to stderr to show exactly how they are not equal (with -/// the differences highlighted in red), then returns a test failure error. -/// The colorized output is optional and controlled by the return of `std.Io.tty.Config.detect`. -/// If your inputs are UTF-8 encoded strings, consider calling `expectEqualStrings` instead. +/// This function is intended to be used only in tests. When the two slices are +/// not equal, prints diagnostics to stderr to show exactly how they are not +/// equal (with the differences highlighted in red), then returns a test +/// failure error. pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const T) !void { const diff_index: usize = diff_index: { const shortest = @min(expected.len, actual.len); @@ -367,9 +368,11 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const break :diff_index if (expected.len == actual.len) return else shortest; }; if (!backend_can_print) return error.TestExpectedEqual; - const stderr_w, const ttyconf = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); - failEqualSlices(T, expected, actual, diff_index, stderr_w, ttyconf) catch {}; + // Intentionally using the debug Io instance rather than the testing Io instance. + const stderr = std.debug.lockStderr(&.{}); + defer std.debug.unlockStderr(); + const w = &stderr.file_writer.interface; + failEqualSlices(T, expected, actual, diff_index, w, stderr.terminal_mode) catch {}; return error.TestExpectedEqual; } @@ -378,8 +381,8 @@ fn failEqualSlices( expected: []const T, actual: []const T, diff_index: usize, - w: *std.Io.Writer, - ttyconf: std.Io.tty.Config, + w: *Io.Writer, + terminal_mode: Io.Terminal.Mode, ) !void { try w.print("slices differ. first difference occurs at index {d} (0x{X})\n", .{ diff_index, diff_index }); @@ -402,12 +405,12 @@ fn failEqualSlices( var differ = if (T == u8) BytesDiffer{ .expected = expected_window, .actual = actual_window, - .ttyconf = ttyconf, + .terminal_mode = terminal_mode, } else SliceDiffer(T){ .start_index = window_start, .expected = expected_window, .actual = actual_window, - .ttyconf = ttyconf, + .terminal_mode = terminal_mode, }; // Print indexes as hex for slices of u8 since it's more likely to be binary data where @@ -464,21 +467,22 @@ fn SliceDiffer(comptime T: type) type { start_index: usize, expected: []const T, actual: []const T, - ttyconf: std.Io.tty.Config, + terminal_mode: Io.Terminal.Mode, const Self = @This(); - pub fn write(self: Self, writer: *std.Io.Writer) !void { + pub fn write(self: Self, writer: *Io.Writer) !void { + const t: Io.Terminal = .{ .writer = writer, .mode = self.terminal_mode }; for (self.expected, 0..) |value, i| { const full_index = self.start_index + i; const diff = if (i < self.actual.len) !std.meta.eql(self.actual[i], value) else true; - if (diff) try self.ttyconf.setColor(writer, .red); + if (diff) try t.setColor(.red); if (@typeInfo(T) == .pointer) { try writer.print("[{}]{*}: {any}\n", .{ full_index, value, value }); } else { try writer.print("[{}]: {any}\n", .{ full_index, value }); } - if (diff) try self.ttyconf.setColor(writer, .reset); + if (diff) try t.setColor(.reset); } } }; @@ -487,9 +491,9 @@ fn SliceDiffer(comptime T: type) type { const BytesDiffer = struct { expected: []const u8, actual: []const u8, - ttyconf: std.Io.tty.Config, + terminal_mode: Io.Terminal.Mode, - pub fn write(self: BytesDiffer, writer: *std.Io.Writer) !void { + pub fn write(self: BytesDiffer, writer: *Io.Writer) !void { var expected_iterator = std.mem.window(u8, self.expected, 16, 16); var row: usize = 0; while (expected_iterator.next()) |chunk| { @@ -514,7 +518,7 @@ const BytesDiffer = struct { try self.writeDiff(writer, "{c}", .{byte}, diff); } else { // TODO: remove this `if` when https://github.com/ziglang/zig/issues/7600 is fixed - if (self.ttyconf == .windows_api) { + if (self.terminal_mode == .windows_api) { try self.writeDiff(writer, ".", .{}, diff); continue; } @@ -535,10 +539,14 @@ const BytesDiffer = struct { } } - fn writeDiff(self: BytesDiffer, writer: *std.Io.Writer, comptime fmt: []const u8, args: anytype, diff: bool) !void { - if (diff) try self.ttyconf.setColor(writer, .red); + fn terminal(self: *const BytesDiffer, writer: *Io.Writer) Io.Terminal { + return .{ .writer = writer, .mode = self.terminal_mode }; + } + + fn writeDiff(self: BytesDiffer, writer: *Io.Writer, comptime fmt: []const u8, args: anytype, diff: bool) !void { + if (diff) try self.terminal(writer).setColor(.red); try writer.print(fmt, args); - if (diff) try self.ttyconf.setColor(writer, .reset); + if (diff) try self.terminal(writer).setColor(.reset); } }; @@ -605,34 +613,35 @@ pub fn expect(ok: bool) !void { } pub const TmpDir = struct { - dir: std.fs.Dir, - parent_dir: std.fs.Dir, + dir: Io.Dir, + parent_dir: Io.Dir, sub_path: [sub_path_len]u8, const random_bytes_count = 12; - const sub_path_len = std.fs.base64_encoder.calcSize(random_bytes_count); + const sub_path_len = std.base64.url_safe.Encoder.calcSize(random_bytes_count); pub fn cleanup(self: *TmpDir) void { - self.dir.close(); - self.parent_dir.deleteTree(&self.sub_path) catch {}; - self.parent_dir.close(); + self.dir.close(io); + self.parent_dir.deleteTree(io, &self.sub_path) catch {}; + self.parent_dir.close(io); self.* = undefined; } }; -pub fn tmpDir(opts: std.fs.Dir.OpenOptions) TmpDir { +pub fn tmpDir(opts: Io.Dir.OpenOptions) TmpDir { + comptime assert(builtin.is_test); var random_bytes: [TmpDir.random_bytes_count]u8 = undefined; - std.crypto.random.bytes(&random_bytes); + io.random(&random_bytes); var sub_path: [TmpDir.sub_path_len]u8 = undefined; - _ = std.fs.base64_encoder.encode(&sub_path, &random_bytes); + _ = std.base64.url_safe.Encoder.encode(&sub_path, &random_bytes); - const cwd = std.fs.cwd(); - var cache_dir = cwd.makeOpenPath(".zig-cache", .{}) catch + const cwd = Io.Dir.cwd(); + var cache_dir = cwd.createDirPathOpen(io, ".zig-cache", .{}) catch @panic("unable to make tmp dir for testing: unable to make and open .zig-cache dir"); - defer cache_dir.close(); - const parent_dir = cache_dir.makeOpenPath("tmp", .{}) catch + defer cache_dir.close(io); + const parent_dir = cache_dir.createDirPathOpen(io, "tmp", .{}) catch @panic("unable to make tmp dir for testing: unable to make and open .zig-cache/tmp dir"); - const dir = parent_dir.makeOpenPath(&sub_path, opts) catch + const dir = parent_dir.createDirPathOpen(io, &sub_path, .{ .open_options = opts }) catch @panic("unable to make tmp dir for testing: unable to make and open the tmp dir"); return .{ @@ -643,7 +652,7 @@ pub fn tmpDir(opts: std.fs.Dir.OpenOptions) TmpDir { } pub fn expectEqualStrings(expected: []const u8, actual: []const u8) !void { - if (std.mem.indexOfDiff(u8, actual, expected)) |diff_index| { + if (std.mem.findDiff(u8, actual, expected)) |diff_index| { if (@inComptime()) { @compileError(std.fmt.comptimePrint("\nexpected:\n{s}\nfound:\n{s}\ndifference starts at index {d}", .{ expected, actual, diff_index, @@ -929,7 +938,7 @@ test "expectEqualDeep primitive type" { a, b, - pub fn format(self: @This(), writer: *std.Io.Writer) !void { + pub fn format(self: @This(), writer: *Io.Writer) !void { try writer.writeAll(@tagName(self)); } }; @@ -992,7 +1001,7 @@ fn printIndicatorLine(source: []const u8, indicator_index: usize) void { line_begin + 1 else 0; - const line_end_index = if (std.mem.indexOfScalar(u8, source[indicator_index..], '\n')) |line_end| + const line_end_index = if (std.mem.findScalar(u8, source[indicator_index..], '\n')) |line_end| (indicator_index + line_end) else source.len; @@ -1008,7 +1017,7 @@ fn printIndicatorLine(source: []const u8, indicator_index: usize) void { fn printWithVisibleNewlines(source: []const u8) void { var i: usize = 0; - while (std.mem.indexOfScalar(u8, source[i..], '\n')) |nl| : (i += nl + 1) { + while (std.mem.findScalar(u8, source[i..], '\n')) |nl| : (i += nl + 1) { printLine(source[i..][0..nl]); } print("{s}␃\n", .{source[i..]}); // End of Text symbol (ETX) @@ -1146,9 +1155,10 @@ pub fn checkAllAllocationFailures(backing_allocator: std.mem.Allocator, comptime break :x failing_allocator_inst.alloc_index; }; - var fail_index: usize = 0; - while (fail_index < needed_alloc_count) : (fail_index += 1) { - var failing_allocator_inst = std.testing.FailingAllocator.init(backing_allocator, .{ .fail_index = fail_index }); + for (0..needed_alloc_count) |fail_index| { + var failing_allocator_inst = std.testing.FailingAllocator.init(backing_allocator, .{ + .fail_index = fail_index, + }); args.@"0" = failing_allocator_inst.allocator(); if (@call(.auto, test_fn, args)) |_| { @@ -1160,7 +1170,6 @@ pub fn checkAllAllocationFailures(backing_allocator: std.mem.Allocator, comptime } else |err| switch (err) { error.OutOfMemory => { if (failing_allocator_inst.allocated_bytes != failing_allocator_inst.freed_bytes) { - const tty_config = std.Io.tty.detectConfig(.stderr()); print( "\nfail_index: {d}/{d}\nallocated bytes: {d}\nfreed bytes: {d}\nallocations: {d}\ndeallocations: {d}\nallocation that was made to fail: {f}", .{ @@ -1172,7 +1181,6 @@ pub fn checkAllAllocationFailures(backing_allocator: std.mem.Allocator, comptime failing_allocator_inst.deallocations, std.debug.FormatStackTrace{ .stack_trace = failing_allocator_inst.getStackTrace(), - .tty_config = tty_config, }, }, ); @@ -1220,14 +1228,14 @@ pub inline fn fuzz( return @import("root").fuzz(context, testOne, options); } -/// A `std.Io.Reader` that writes a predetermined list of buffers during `stream`. +/// A `Io.Reader` that writes a predetermined list of buffers during `stream`. pub const Reader = struct { calls: []const Call, - interface: std.Io.Reader, + interface: Io.Reader, next_call_index: usize, next_offset: usize, /// Further reduces how many bytes are written in each `stream` call. - artificial_limit: std.Io.Limit = .unlimited, + artificial_limit: Io.Limit = .unlimited, pub const Call = struct { buffer: []const u8, @@ -1247,7 +1255,7 @@ pub const Reader = struct { }; } - fn stream(io_r: *std.Io.Reader, w: *std.Io.Writer, limit: std.Io.Limit) std.Io.Reader.StreamError!usize { + fn stream(io_r: *Io.Reader, w: *Io.Writer, limit: Io.Limit) Io.Reader.StreamError!usize { const r: *Reader = @alignCast(@fieldParentPtr("interface", io_r)); if (r.calls.len - r.next_call_index == 0) return error.EndOfStream; const call = r.calls[r.next_call_index]; @@ -1262,13 +1270,13 @@ pub const Reader = struct { } }; -/// A `std.Io.Reader` that gets its data from another `std.Io.Reader`, and always +/// A `Io.Reader` that gets its data from another `Io.Reader`, and always /// writes to its own buffer (and returns 0) during `stream` and `readVec`. pub const ReaderIndirect = struct { - in: *std.Io.Reader, - interface: std.Io.Reader, + in: *Io.Reader, + interface: Io.Reader, - pub fn init(in: *std.Io.Reader, buffer: []u8) ReaderIndirect { + pub fn init(in: *Io.Reader, buffer: []u8) ReaderIndirect { return .{ .in = in, .interface = .{ @@ -1283,17 +1291,17 @@ pub const ReaderIndirect = struct { }; } - fn readVec(r: *std.Io.Reader, _: [][]u8) std.Io.Reader.Error!usize { + fn readVec(r: *Io.Reader, _: [][]u8) Io.Reader.Error!usize { try streamInner(r); return 0; } - fn stream(r: *std.Io.Reader, _: *std.Io.Writer, _: std.Io.Limit) std.Io.Reader.StreamError!usize { + fn stream(r: *Io.Reader, _: *Io.Writer, _: Io.Limit) Io.Reader.StreamError!usize { try streamInner(r); return 0; } - fn streamInner(r: *std.Io.Reader) std.Io.Reader.Error!void { + fn streamInner(r: *Io.Reader) Io.Reader.Error!void { const r_indirect: *ReaderIndirect = @alignCast(@fieldParentPtr("interface", r)); // If there's no room remaining in the buffer at all, make room. @@ -1301,12 +1309,12 @@ pub const ReaderIndirect = struct { try r.rebase(r.buffer.len); } - var writer: std.Io.Writer = .{ + var writer: Io.Writer = .{ .buffer = r.buffer, .end = r.end, .vtable = &.{ - .drain = std.Io.Writer.unreachableDrain, - .rebase = std.Io.Writer.unreachableRebase, + .drain = Io.Writer.unreachableDrain, + .rebase = Io.Writer.unreachableRebase, }, }; defer r.end = writer.end; diff --git a/lib/std/unicode/throughput_test.zig b/lib/std/unicode/throughput_test.zig index fd3f46ec584a..c02f550a4a74 100644 --- a/lib/std/unicode/throughput_test.zig +++ b/lib/std/unicode/throughput_test.zig @@ -1,8 +1,8 @@ const std = @import("std"); +const Io = std.Io; const time = std.time; const unicode = std.unicode; - -const Timer = time.Timer; +const Timer = std.time.Timer; const N = 1_000_000; @@ -41,7 +41,7 @@ fn benchmarkCodepointCount(buf: []const u8) !ResultCount { pub fn main() !void { // Size of buffer is about size of printed message. var stdout_buffer: [0x100]u8 = undefined; - var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); + var stdout_writer = Io.File.stdout().writer(&stdout_buffer); const stdout = &stdout_writer.interface; try stdout.print("short ASCII strings\n", .{}); diff --git a/lib/std/zig.zig b/lib/std/zig.zig index c8a0dcde3b7b..4f0f47b11f3d 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -46,23 +46,16 @@ pub const SrcHasher = std.crypto.hash.Blake3; pub const SrcHash = [16]u8; pub const Color = enum { - /// Determine whether stderr is a terminal or not automatically. + /// Auto-detect whether stream supports terminal colors. auto, - /// Assume stderr is not a terminal. + /// Force-enable colors. off, - /// Assume stderr is a terminal. + /// Suppress colors. on, - pub fn getTtyConf(color: Color, detected: Io.tty.Config) Io.tty.Config { + pub fn terminalMode(color: Color) ?Io.Terminal.Mode { return switch (color) { - .auto => detected, - .on => .escape_codes, - .off => .no_color, - }; - } - pub fn detectTtyConf(color: Color) Io.tty.Config { - return switch (color) { - .auto => .detect(.stderr()), + .auto => null, .on => .escape_codes, .off => .no_color, }; @@ -639,7 +632,7 @@ pub fn readSourceFileToEndAlloc(gpa: Allocator, file_reader: *Io.File.Reader) ![ return buffer.toOwnedSliceSentinel(gpa, 0); } -pub fn printAstErrorsToStderr(gpa: Allocator, tree: Ast, path: []const u8, color: Color) !void { +pub fn printAstErrorsToStderr(gpa: Allocator, io: Io, tree: Ast, path: []const u8, color: Color) !void { var wip_errors: std.zig.ErrorBundle.Wip = undefined; try wip_errors.init(gpa); defer wip_errors.deinit(); @@ -648,7 +641,7 @@ pub fn printAstErrorsToStderr(gpa: Allocator, tree: Ast, path: []const u8, color var error_bundle = try wip_errors.toOwnedBundle(""); defer error_bundle.deinit(gpa); - error_bundle.renderToStdErr(.{}, color); + return error_bundle.renderToStderr(io, .{}, color); } pub fn putAstErrorsIntoBundle( @@ -746,27 +739,39 @@ pub const EnvVar = enum { ZIG_VERBOSE_CC, ZIG_BTRFS_WORKAROUND, ZIG_DEBUG_CMD, + ZIG_IS_DETECTING_LIBC_PATHS, + ZIG_IS_TRYING_TO_NOT_CALL_ITSELF, + + // C toolchain integration + NIX_CFLAGS_COMPILE, + NIX_CFLAGS_LINK, + NIX_LDFLAGS, + C_INCLUDE_PATH, + CPLUS_INCLUDE_PATH, + LIBRARY_PATH, CC, + + // Terminal integration NO_COLOR, CLICOLOR_FORCE, + + // Debug info integration XDG_CACHE_HOME, + LOCALAPPDATA, HOME, - pub fn isSet(comptime ev: EnvVar) bool { - return std.process.hasNonEmptyEnvVarConstant(@tagName(ev)); - } + // Windows SDK integration + PROGRAMDATA, - pub fn get(ev: EnvVar, arena: std.mem.Allocator) !?[]u8 { - if (std.process.getEnvVarOwned(arena, @tagName(ev))) |value| { - return value; - } else |err| switch (err) { - error.EnvironmentVariableNotFound => return null, - else => |e| return e, - } + // Homebrew integration + HOMEBREW_PREFIX, + + pub fn isSet(ev: EnvVar, map: *const std.process.Environ.Map) bool { + return map.contains(@tagName(ev)); } - pub fn getPosix(comptime ev: EnvVar) ?[:0]const u8 { - return std.posix.getenvZ(@tagName(ev)); + pub fn get(ev: EnvVar, map: *const std.process.Environ.Map) ?[]const u8 { + return map.get(@tagName(ev)); } }; diff --git a/lib/std/zig/Ast.zig b/lib/std/zig/Ast.zig index 72ca20a6c0a6..7331f6188e92 100644 --- a/lib/std/zig/Ast.zig +++ b/lib/std/zig/Ast.zig @@ -234,7 +234,7 @@ pub fn tokenLocation(self: Ast, start_offset: ByteOffset, token_index: TokenInde const token_start = self.tokenStart(token_index); // Scan to by line until we go past the token start - while (std.mem.indexOfScalarPos(u8, self.source, loc.line_start, '\n')) |i| { + while (std.mem.findScalarPos(u8, self.source, loc.line_start, '\n')) |i| { if (i >= token_start) { break; // Went past } @@ -476,7 +476,7 @@ pub fn renderError(tree: Ast, parse_error: Error, w: *Writer) Writer.Error!void }); }, .invalid_bit_range => { - return w.writeAll("bit range not allowed on slices and arrays"); + return w.writeAll("bit range only allowed on single item pointers"); }, .same_line_doc_comment => { return w.writeAll("same line documentation comment"); @@ -636,7 +636,6 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex { .@"nosuspend", .asm_simple, .@"asm", - .asm_legacy, .array_type, .array_type_sentinel, .error_value, @@ -1050,11 +1049,6 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter } }, - .asm_legacy => { - _, const extra_index = tree.nodeData(n).node_and_extra; - const extra = tree.extraData(extra_index, Node.AsmLegacy); - return extra.rparen + end_offset; - }, .@"asm" => { _, const extra_index = tree.nodeData(n).node_and_extra; const extra = tree.extraData(extra_index, Node.Asm); @@ -1195,6 +1189,9 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { if (extra.section_node.unwrap()) |section_node| { end_offset += 1; // for the rparen n = section_node; + } else if (extra.addrspace_node.unwrap()) |addrspace_node| { + end_offset += 1; // for the rparen + n = addrspace_node; } else if (extra.align_node.unwrap()) |align_node| { end_offset += 1; // for the rparen n = align_node; @@ -1312,7 +1309,7 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { pub fn tokensOnSameLine(tree: Ast, token1: TokenIndex, token2: TokenIndex) bool { const source = tree.source[tree.tokenStart(token1)..tree.tokenStart(token2)]; - return mem.indexOfScalar(u8, source, '\n') == null; + return mem.findScalar(u8, source, '\n') == null; } pub fn getNodeSource(tree: Ast, node: Node.Index) []const u8 { @@ -1897,18 +1894,6 @@ pub fn asmSimple(tree: Ast, node: Node.Index) full.Asm { }); } -pub fn asmLegacy(tree: Ast, node: Node.Index) full.AsmLegacy { - const template, const extra_index = tree.nodeData(node).node_and_extra; - const extra = tree.extraData(extra_index, Node.AsmLegacy); - const items = tree.extraDataSlice(.{ .start = extra.items_start, .end = extra.items_end }, Node.Index); - return tree.legacyAsmComponents(.{ - .asm_token = tree.nodeMainToken(node), - .template = template, - .items = items, - .rparen = extra.rparen, - }); -} - pub fn asmFull(tree: Ast, node: Node.Index) full.Asm { const template, const extra_index = tree.nodeData(node).node_and_extra; const extra = tree.extraData(extra_index, Node.Asm); @@ -2214,67 +2199,6 @@ fn fullSwitchCaseComponents(tree: Ast, info: full.SwitchCase.Components, node: N return result; } -fn legacyAsmComponents(tree: Ast, info: full.AsmLegacy.Components) full.AsmLegacy { - var result: full.AsmLegacy = .{ - .ast = info, - .volatile_token = null, - .inputs = &.{}, - .outputs = &.{}, - .first_clobber = null, - }; - if (tree.tokenTag(info.asm_token + 1) == .keyword_volatile) { - result.volatile_token = info.asm_token + 1; - } - const outputs_end: usize = for (info.items, 0..) |item, i| { - switch (tree.nodeTag(item)) { - .asm_output => continue, - else => break i, - } - } else info.items.len; - - result.outputs = info.items[0..outputs_end]; - result.inputs = info.items[outputs_end..]; - - if (info.items.len == 0) { - // asm ("foo" ::: "a", "b"); - const template_token = tree.lastToken(info.template); - if (tree.tokenTag(template_token + 1) == .colon and - tree.tokenTag(template_token + 2) == .colon and - tree.tokenTag(template_token + 3) == .colon and - tree.tokenTag(template_token + 4) == .string_literal) - { - result.first_clobber = template_token + 4; - } - } else if (result.inputs.len != 0) { - // asm ("foo" :: [_] "" (y) : "a", "b"); - const last_input = result.inputs[result.inputs.len - 1]; - const rparen = tree.lastToken(last_input); - var i = rparen + 1; - // Allow a (useless) comma right after the closing parenthesis. - if (tree.tokenTag(i) == .comma) i = i + 1; - if (tree.tokenTag(i) == .colon and - tree.tokenTag(i + 1) == .string_literal) - { - result.first_clobber = i + 1; - } - } else { - // asm ("foo" : [_] "" (x) :: "a", "b"); - const last_output = result.outputs[result.outputs.len - 1]; - const rparen = tree.lastToken(last_output); - var i = rparen + 1; - // Allow a (useless) comma right after the closing parenthesis. - if (tree.tokenTag(i) == .comma) i = i + 1; - if (tree.tokenTag(i) == .colon and - tree.tokenTag(i + 1) == .colon and - tree.tokenTag(i + 2) == .string_literal) - { - result.first_clobber = i + 2; - } - } - - return result; -} - fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm { var result: full.Asm = .{ .ast = info, @@ -2492,14 +2416,6 @@ pub fn fullAsm(tree: Ast, node: Node.Index) ?full.Asm { }; } -/// To be deleted after 0.15.0 is tagged -pub fn legacyAsm(tree: Ast, node: Node.Index) ?full.AsmLegacy { - return switch (tree.nodeTag(node)) { - .asm_legacy => tree.asmLegacy(node), - else => null, - }; -} - pub fn fullCall(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.Call { return switch (tree.nodeTag(node)) { .call, .call_comma => tree.callFull(node), @@ -2894,21 +2810,6 @@ pub const full = struct { }; }; - pub const AsmLegacy = struct { - ast: Components, - volatile_token: ?TokenIndex, - first_clobber: ?TokenIndex, - outputs: []const Node.Index, - inputs: []const Node.Index, - - pub const Components = struct { - asm_token: TokenIndex, - template: Node.Index, - items: []const Node.Index, - rparen: TokenIndex, - }; - }; - pub const Call = struct { ast: Components, @@ -3905,14 +3806,6 @@ pub const Node = struct { /// /// The `main_token` field is the `asm` token. asm_simple, - /// `asm(lhs, a)`. - /// - /// The `data` field is a `.node_and_extra`: - /// 1. a `Node.Index` to lhs. - /// 2. a `ExtraIndex` to `AsmLegacy`. - /// - /// The `main_token` field is the `asm` token. - asm_legacy, /// `asm(a, b)`. /// /// The `data` field is a `.node_and_extra`: @@ -4089,14 +3982,6 @@ pub const Node = struct { callconv_expr: OptionalIndex, }; - /// To be removed after 0.15.0 is tagged - pub const AsmLegacy = struct { - items_start: ExtraIndex, - items_end: ExtraIndex, - /// Needed to make lastToken() work. - rparen: TokenIndex, - }; - pub const Asm = struct { items_start: ExtraIndex, items_end: ExtraIndex, diff --git a/lib/std/zig/Ast/Render.zig b/lib/std/zig/Ast/Render.zig index bc66703774d7..fb58d7e32f2d 100644 --- a/lib/std/zig/Ast/Render.zig +++ b/lib/std/zig/Ast/Render.zig @@ -896,9 +896,6 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { .@"asm", => return renderAsm(r, tree.fullAsm(node).?, space), - // To be removed after 0.15.0 is tagged - .asm_legacy => return renderAsmLegacy(r, tree.legacyAsm(node).?, space), - .enum_literal => { try renderToken(r, tree.nodeMainToken(node) - 1, .none); // . return renderIdentifier(r, tree.nodeMainToken(node), space, .eagerly_unquote); // name @@ -1420,7 +1417,7 @@ fn renderFor(r: *Render, for_node: Ast.full.For, space: Space) Error!void { try renderParamList(r, lparen, for_node.ast.inputs, .space); var cur = for_node.payload_token; - const pipe = std.mem.indexOfScalarPos(std.zig.Token.Tag, token_tags, cur, .pipe).?; + const pipe = std.mem.findScalarPos(std.zig.Token.Tag, token_tags, cur, .pipe).?; if (tree.tokenTag(@intCast(pipe - 1)) == .comma) { try ais.pushIndent(.normal); try renderToken(r, cur - 1, .newline); // | @@ -2197,7 +2194,7 @@ fn renderArrayInit( try renderExpression(&sub_render, expr, .none); const written = sub_expr_buffer.written(); const width = written.len - start; - const this_contains_newline = mem.indexOfScalar(u8, written[start..], '\n') != null; + const this_contains_newline = mem.findScalar(u8, written[start..], '\n') != null; contains_newline = contains_newline or this_contains_newline; expr_widths[i] = width; expr_newlines[i] = this_contains_newline; @@ -2221,7 +2218,7 @@ fn renderArrayInit( const written = sub_expr_buffer.written(); const width = written.len - start - 2; - const this_contains_newline = mem.indexOfScalar(u8, written[start .. written.len - 1], '\n') != null; + const this_contains_newline = mem.findScalar(u8, written[start .. written.len - 1], '\n') != null; contains_newline = contains_newline or this_contains_newline; expr_widths[i] = width; expr_newlines[i] = contains_newline; @@ -2413,185 +2410,6 @@ fn renderContainerDecl( return renderToken(r, rbrace, space); // rbrace } -fn renderAsmLegacy( - r: *Render, - asm_node: Ast.full.AsmLegacy, - space: Space, -) Error!void { - const tree = r.tree; - const ais = r.ais; - - try renderToken(r, asm_node.ast.asm_token, .space); // asm - - if (asm_node.volatile_token) |volatile_token| { - try renderToken(r, volatile_token, .space); // volatile - try renderToken(r, volatile_token + 1, .none); // lparen - } else { - try renderToken(r, asm_node.ast.asm_token + 1, .none); // lparen - } - - if (asm_node.ast.items.len == 0) { - try ais.forcePushIndent(.normal); - if (asm_node.first_clobber) |first_clobber| { - // asm ("foo" ::: "a", "b") - // asm ("foo" ::: "a", "b",) - try renderExpression(r, asm_node.ast.template, .space); - // Render the three colons. - try renderToken(r, first_clobber - 3, .none); - try renderToken(r, first_clobber - 2, .none); - try renderToken(r, first_clobber - 1, .space); - - try ais.writeAll(".{ "); - - var tok_i = first_clobber; - while (true) : (tok_i += 1) { - try ais.writeByte('.'); - _ = try writeStringLiteralAsIdentifier(r, tok_i); - try ais.writeAll(" = true"); - - tok_i += 1; - switch (tree.tokenTag(tok_i)) { - .r_paren => { - try ais.writeAll(" }"); - ais.popIndent(); - return renderToken(r, tok_i, space); - }, - .comma => { - if (tree.tokenTag(tok_i + 1) == .r_paren) { - try ais.writeAll(" }"); - ais.popIndent(); - return renderToken(r, tok_i + 1, space); - } else { - try renderToken(r, tok_i, .space); - } - }, - else => unreachable, - } - } - } else { - unreachable; - } - } - - try ais.forcePushIndent(.normal); - try renderExpression(r, asm_node.ast.template, .newline); - ais.setIndentDelta(asm_indent_delta); - const colon1 = tree.lastToken(asm_node.ast.template) + 1; - - const colon2 = if (asm_node.outputs.len == 0) colon2: { - try renderToken(r, colon1, .newline); // : - break :colon2 colon1 + 1; - } else colon2: { - try renderToken(r, colon1, .space); // : - - try ais.forcePushIndent(.normal); - for (asm_node.outputs, 0..) |asm_output, i| { - if (i + 1 < asm_node.outputs.len) { - const next_asm_output = asm_node.outputs[i + 1]; - try renderAsmOutput(r, asm_output, .none); - - const comma = tree.firstToken(next_asm_output) - 1; - try renderToken(r, comma, .newline); // , - try renderExtraNewlineToken(r, tree.firstToken(next_asm_output)); - } else if (asm_node.inputs.len == 0 and asm_node.first_clobber == null) { - try ais.pushSpace(.comma); - try renderAsmOutput(r, asm_output, .comma); - ais.popSpace(); - ais.popIndent(); - ais.setIndentDelta(indent_delta); - ais.popIndent(); - return renderToken(r, asm_node.ast.rparen, space); // rparen - } else { - try ais.pushSpace(.comma); - try renderAsmOutput(r, asm_output, .comma); - ais.popSpace(); - const comma_or_colon = tree.lastToken(asm_output) + 1; - ais.popIndent(); - break :colon2 switch (tree.tokenTag(comma_or_colon)) { - .comma => comma_or_colon + 1, - else => comma_or_colon, - }; - } - } else unreachable; - }; - - const colon3 = if (asm_node.inputs.len == 0) colon3: { - try renderToken(r, colon2, .newline); // : - break :colon3 colon2 + 1; - } else colon3: { - try renderToken(r, colon2, .space); // : - try ais.forcePushIndent(.normal); - for (asm_node.inputs, 0..) |asm_input, i| { - if (i + 1 < asm_node.inputs.len) { - const next_asm_input = asm_node.inputs[i + 1]; - try renderAsmInput(r, asm_input, .none); - - const first_token = tree.firstToken(next_asm_input); - try renderToken(r, first_token - 1, .newline); // , - try renderExtraNewlineToken(r, first_token); - } else if (asm_node.first_clobber == null) { - try ais.pushSpace(.comma); - try renderAsmInput(r, asm_input, .comma); - ais.popSpace(); - ais.popIndent(); - ais.setIndentDelta(indent_delta); - ais.popIndent(); - return renderToken(r, asm_node.ast.rparen, space); // rparen - } else { - try ais.pushSpace(.comma); - try renderAsmInput(r, asm_input, .comma); - ais.popSpace(); - const comma_or_colon = tree.lastToken(asm_input) + 1; - ais.popIndent(); - break :colon3 switch (tree.tokenTag(comma_or_colon)) { - .comma => comma_or_colon + 1, - else => comma_or_colon, - }; - } - } - unreachable; - }; - - try renderToken(r, colon3, .space); // : - try ais.writeAll(".{ "); - const first_clobber = asm_node.first_clobber.?; - var tok_i = first_clobber; - while (true) { - switch (tree.tokenTag(tok_i + 1)) { - .r_paren => { - ais.setIndentDelta(indent_delta); - try ais.writeByte('.'); - const lexeme_len = try writeStringLiteralAsIdentifier(r, tok_i); - try ais.writeAll(" = true }"); - try renderSpace(r, tok_i, lexeme_len, .newline); - ais.popIndent(); - return renderToken(r, tok_i + 1, space); - }, - .comma => { - switch (tree.tokenTag(tok_i + 2)) { - .r_paren => { - ais.setIndentDelta(indent_delta); - try ais.writeByte('.'); - const lexeme_len = try writeStringLiteralAsIdentifier(r, tok_i); - try ais.writeAll(" = true }"); - try renderSpace(r, tok_i, lexeme_len, .newline); - ais.popIndent(); - return renderToken(r, tok_i + 2, space); - }, - else => { - try ais.writeByte('.'); - _ = try writeStringLiteralAsIdentifier(r, tok_i); - try ais.writeAll(" = true"); - try renderToken(r, tok_i + 1, .space); - tok_i += 2; - }, - } - }, - else => unreachable, - } - } -} - fn renderAsm( r: *Render, asm_node: Ast.full.Asm, @@ -3092,7 +2910,7 @@ fn hasComment(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) const token: Ast.TokenIndex = @intCast(i); const start = tree.tokenStart(token) + tree.tokenSlice(token).len; const end = tree.tokenStart(token + 1); - if (mem.indexOf(u8, tree.source[start..end], "//") != null) return true; + if (mem.find(u8, tree.source[start..end], "//") != null) return true; } return false; @@ -3101,7 +2919,7 @@ fn hasComment(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) /// Returns true if there exists a multiline string literal between the start /// of token `start_token` and the start of token `end_token`. fn hasMultilineString(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool { - return std.mem.indexOfScalar( + return std.mem.findScalar( Token.Tag, tree.tokens.items(.tag)[start_token..end_token], .multiline_string_literal_line, @@ -3115,11 +2933,11 @@ fn renderComments(r: *Render, start: usize, end: usize) Error!bool { const ais = r.ais; var index: usize = start; - while (mem.indexOf(u8, tree.source[index..end], "//")) |offset| { + while (mem.find(u8, tree.source[index..end], "//")) |offset| { const comment_start = index + offset; // If there is no newline, the comment ends with EOF - const newline_index = mem.indexOfScalar(u8, tree.source[comment_start..end], '\n'); + const newline_index = mem.findScalar(u8, tree.source[comment_start..end], '\n'); const newline = if (newline_index) |i| comment_start + i else null; const untrimmed_comment = tree.source[comment_start .. newline orelse tree.source.len]; @@ -3131,7 +2949,7 @@ fn renderComments(r: *Render, start: usize, end: usize) Error!bool { // Leave up to one empty line before the first comment try ais.insertNewline(); try ais.insertNewline(); - } else if (mem.indexOfScalar(u8, tree.source[index..comment_start], '\n') != null) { + } else if (mem.findScalar(u8, tree.source[index..comment_start], '\n') != null) { // Respect the newline directly before the comment. // Note: This allows an empty line between comments try ais.insertNewline(); @@ -3190,7 +3008,7 @@ fn renderExtraNewlineToken(r: *Render, token_index: Ast.TokenIndex) Error!void { // If there is a immediately preceding comment or doc_comment, // skip it because required extra newline has already been rendered. - if (mem.indexOf(u8, tree.source[prev_token_end..token_start], "//") != null) return; + if (mem.find(u8, tree.source[prev_token_end..token_start], "//") != null) return; if (tree.isTokenPrecededByTags(token_index, &.{.doc_comment})) return; // Iterate backwards to the end of the previous token, stopping if a diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig index 6306dde4f859..2a6423a60d1c 100644 --- a/lib/std/zig/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -507,7 +507,6 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins .bool_or, .@"asm", .asm_simple, - .asm_legacy, .string_literal, .number_literal, .call, @@ -814,12 +813,6 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE .@"asm", => return asmExpr(gz, scope, ri, node, tree.fullAsm(node).?), - .asm_legacy => { - return astgen.failNodeNotes(node, "legacy asm clobbers syntax", .{}, &[_]u32{ - try astgen.errNoteNode(node, "use 'zig fmt' to auto-upgrade", .{}), - }); - }, - .string_literal => return stringLiteral(gz, ri, node), .multiline_string_literal => return multilineStringLiteral(gz, ri, node), @@ -4131,7 +4124,7 @@ fn fnDecl( const lib_name = if (fn_proto.lib_name) |lib_name_token| blk: { const lib_name_str = try astgen.strLitAsString(lib_name_token); const lib_name_slice = astgen.string_bytes.items[@intFromEnum(lib_name_str.index)..][0..lib_name_str.len]; - if (mem.indexOfScalar(u8, lib_name_slice, 0) != null) { + if (mem.findScalar(u8, lib_name_slice, 0) != null) { return astgen.failTok(lib_name_token, "library name cannot contain null bytes", .{}); } else if (lib_name_str.len == 0) { return astgen.failTok(lib_name_token, "library name cannot be empty", .{}); @@ -4547,7 +4540,7 @@ fn globalVarDecl( const lib_name = if (var_decl.lib_name) |lib_name_token| blk: { const lib_name_str = try astgen.strLitAsString(lib_name_token); const lib_name_slice = astgen.string_bytes.items[@intFromEnum(lib_name_str.index)..][0..lib_name_str.len]; - if (mem.indexOfScalar(u8, lib_name_slice, 0) != null) { + if (mem.findScalar(u8, lib_name_slice, 0) != null) { return astgen.failTok(lib_name_token, "library name cannot contain null bytes", .{}); } else if (lib_name_str.len == 0) { return astgen.failTok(lib_name_token, "library name cannot be empty", .{}); @@ -4769,7 +4762,7 @@ fn testDecl( .string_literal => name: { const name = try astgen.strLitAsString(test_name_token); const slice = astgen.string_bytes.items[@intFromEnum(name.index)..][0..name.len]; - if (mem.indexOfScalar(u8, slice, 0) != null) { + if (mem.findScalar(u8, slice, 0) != null) { return astgen.failTok(test_name_token, "test name cannot contain null bytes", .{}); } else if (slice.len == 0) { return astgen.failTok(test_name_token, "empty test name must be omitted", .{}); @@ -8779,7 +8772,7 @@ fn numberLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index, source_node: } fn failWithNumberError(astgen: *AstGen, err: std.zig.number_literal.Error, token: Ast.TokenIndex, bytes: []const u8) InnerError { - const is_float = std.mem.indexOfScalar(u8, bytes, '.') != null; + const is_float = std.mem.findScalar(u8, bytes, '.') != null; switch (err) { .leading_zero => if (is_float) { return astgen.failTok(token, "number '{s}' has leading zero", .{bytes}); @@ -9272,7 +9265,7 @@ fn builtinCall( const str_lit_token = tree.nodeMainToken(operand_node); const str = try astgen.strLitAsString(str_lit_token); const str_slice = astgen.string_bytes.items[@intFromEnum(str.index)..][0..str.len]; - if (mem.indexOfScalar(u8, str_slice, 0) != null) { + if (mem.findScalar(u8, str_slice, 0) != null) { return astgen.failTok(str_lit_token, "import path cannot contain null bytes", .{}); } else if (str.len == 0) { return astgen.failTok(str_lit_token, "import path cannot be empty", .{}); @@ -10502,7 +10495,6 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev .@"asm", .asm_simple, - .asm_legacy, .identifier, .field_access, .deref, @@ -10746,7 +10738,6 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In .tagged_union_enum_tag_trailing, .@"asm", .asm_simple, - .asm_legacy, .add, .add_wrap, .add_sat, @@ -10985,7 +10976,6 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool { .tagged_union_enum_tag_trailing, .@"asm", .asm_simple, - .asm_legacy, .add, .add_wrap, .add_sat, @@ -11418,7 +11408,7 @@ fn identifierTokenString(astgen: *AstGen, token: Ast.TokenIndex) InnerError![]co var buf: ArrayList(u8) = .empty; defer buf.deinit(astgen.gpa); try astgen.parseStrLit(token, &buf, ident_name, 1); - if (mem.indexOfScalar(u8, buf.items, 0) != null) { + if (mem.findScalar(u8, buf.items, 0) != null) { return astgen.failTok(token, "identifier cannot contain null bytes", .{}); } else if (buf.items.len == 0) { return astgen.failTok(token, "identifier cannot be empty", .{}); @@ -11444,7 +11434,7 @@ fn appendIdentStr( const start = buf.items.len; try astgen.parseStrLit(token, buf, ident_name, 1); const slice = buf.items[start..]; - if (mem.indexOfScalar(u8, slice, 0) != null) { + if (mem.findScalar(u8, slice, 0) != null) { return astgen.failTok(token, "identifier cannot contain null bytes", .{}); } else if (slice.len == 0) { return astgen.failTok(token, "identifier cannot be empty", .{}); @@ -11701,7 +11691,7 @@ fn strLitAsString(astgen: *AstGen, str_lit_token: Ast.TokenIndex) !IndexSlice { const token_bytes = astgen.tree.tokenSlice(str_lit_token); try astgen.parseStrLit(str_lit_token, string_bytes, token_bytes, 0); const key: []const u8 = string_bytes.items[str_index..]; - if (std.mem.indexOfScalar(u8, key, 0)) |_| return .{ + if (std.mem.findScalar(u8, key, 0)) |_| return .{ .index = @enumFromInt(str_index), .len = @intCast(key.len), }; @@ -13010,9 +13000,9 @@ const GenZir = struct { } const small: Zir.Inst.Asm.Small = .{ + .is_volatile = args.is_volatile, .outputs_len = @intCast(args.outputs.len), .inputs_len = @intCast(args.inputs.len), - .is_volatile = args.is_volatile, }; const new_index: Zir.Inst.Index = @enumFromInt(astgen.instructions.len); diff --git a/lib/std/zig/AstRlAnnotate.zig b/lib/std/zig/AstRlAnnotate.zig index c7e9abf2bbdb..e1a83fb75acd 100644 --- a/lib/std/zig/AstRlAnnotate.zig +++ b/lib/std/zig/AstRlAnnotate.zig @@ -310,7 +310,6 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI .unreachable_literal, .asm_simple, .@"asm", - .asm_legacy, .enum_literal, .error_value, .anyframe_literal, diff --git a/lib/std/zig/ErrorBundle.zig b/lib/std/zig/ErrorBundle.zig index ef6203cbe850..c5275729ae5f 100644 --- a/lib/std/zig/ErrorBundle.zig +++ b/lib/std/zig/ErrorBundle.zig @@ -162,45 +162,57 @@ pub const RenderOptions = struct { include_log_text: bool = true, }; -pub fn renderToStdErr(eb: ErrorBundle, options: RenderOptions, color: std.zig.Color) void { +pub const RenderToStderrError = Io.Cancelable || Io.File.Writer.Error; + +pub fn renderToStderr(eb: ErrorBundle, io: Io, options: RenderOptions, color: std.zig.Color) RenderToStderrError!void { var buffer: [256]u8 = undefined; - const w, const ttyconf = std.debug.lockStderrWriter(&buffer); - defer std.debug.unlockStderrWriter(); - renderToWriter(eb, options, w, color.getTtyConf(ttyconf)) catch return; + const stderr = try io.lockStderr(&buffer, color.terminalMode()); + defer io.unlockStderr(); + renderToTerminal(eb, options, stderr.terminal()) catch |err| switch (err) { + error.WriteFailed => return stderr.file_writer.err.?, + else => |e| return e, + }; +} + +pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, w: *Writer) Writer.Error!void { + return renderToTerminal(eb, options, .{ .writer = w, .mode = .no_color }) catch |err| switch (err) { + error.WriteFailed => |e| return e, + else => unreachable, + }; } -pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, w: *Writer, ttyconf: Io.tty.Config) (Writer.Error || std.posix.UnexpectedError)!void { +pub fn renderToTerminal(eb: ErrorBundle, options: RenderOptions, t: Io.Terminal) Io.Terminal.SetColorError!void { if (eb.extra.len == 0) return; for (eb.getMessages()) |err_msg| { - try renderErrorMessageToWriter(eb, options, err_msg, w, ttyconf, "error", .red, 0); + try renderErrorMessage(eb, options, err_msg, t, "error", .red, 0); } if (options.include_log_text) { const log_text = eb.getCompileLogOutput(); if (log_text.len != 0) { - try w.writeAll("\nCompile Log Output:\n"); - try w.writeAll(log_text); + try t.writer.writeAll("\nCompile Log Output:\n"); + try t.writer.writeAll(log_text); } } } -fn renderErrorMessageToWriter( +fn renderErrorMessage( eb: ErrorBundle, options: RenderOptions, err_msg_index: MessageIndex, - w: *Writer, - ttyconf: Io.tty.Config, + t: Io.Terminal, kind: []const u8, - color: Io.tty.Color, + color: Io.Terminal.Color, indent: usize, -) (Writer.Error || std.posix.UnexpectedError)!void { +) Io.Terminal.SetColorError!void { + const w = t.writer; const err_msg = eb.getErrorMessage(err_msg_index); if (err_msg.src_loc != .none) { const src = eb.extraData(SourceLocation, @intFromEnum(err_msg.src_loc)); var prefix: Writer.Discarding = .init(&.{}); try w.splatByteAll(' ', indent); prefix.count += indent; - try ttyconf.setColor(w, .bold); + try t.setColor(.bold); try w.print("{s}:{d}:{d}: ", .{ eb.nullTerminatedString(src.data.src_path), src.data.line + 1, @@ -211,7 +223,7 @@ fn renderErrorMessageToWriter( src.data.line + 1, src.data.column + 1, }); - try ttyconf.setColor(w, color); + try t.setColor(color); try w.writeAll(kind); prefix.count += kind.len; try w.writeAll(": "); @@ -219,17 +231,17 @@ fn renderErrorMessageToWriter( // This is the length of the part before the error message: // e.g. "file.zig:4:5: error: " const prefix_len: usize = @intCast(prefix.count); - try ttyconf.setColor(w, .reset); - try ttyconf.setColor(w, .bold); + try t.setColor(.reset); + try t.setColor(.bold); if (err_msg.count == 1) { try writeMsg(eb, err_msg, w, prefix_len); try w.writeByte('\n'); } else { try writeMsg(eb, err_msg, w, prefix_len); - try ttyconf.setColor(w, .dim); + try t.setColor(.dim); try w.print(" ({d} times)\n", .{err_msg.count}); } - try ttyconf.setColor(w, .reset); + try t.setColor(.reset); if (src.data.source_line != 0 and options.include_source_line) { const line = eb.nullTerminatedString(src.data.source_line); for (line) |b| switch (b) { @@ -242,19 +254,19 @@ fn renderErrorMessageToWriter( // -1 since span.main includes the caret const after_caret = src.data.span_end -| src.data.span_main -| 1; try w.splatByteAll(' ', src.data.column - before_caret); - try ttyconf.setColor(w, .green); + try t.setColor(.green); try w.splatByteAll('~', before_caret); try w.writeByte('^'); try w.splatByteAll('~', after_caret); try w.writeByte('\n'); - try ttyconf.setColor(w, .reset); + try t.setColor(.reset); } for (eb.getNotes(err_msg_index)) |note| { - try renderErrorMessageToWriter(eb, options, note, w, ttyconf, "note", .cyan, indent); + try renderErrorMessage(eb, options, note, t, "note", .cyan, indent); } if (src.data.reference_trace_len > 0 and options.include_reference_trace) { - try ttyconf.setColor(w, .reset); - try ttyconf.setColor(w, .dim); + try t.setColor(.reset); + try t.setColor(.dim); try w.print("referenced by:\n", .{}); var ref_index = src.end; for (0..src.data.reference_trace_len) |_| { @@ -281,25 +293,25 @@ fn renderErrorMessageToWriter( ); } } - try ttyconf.setColor(w, .reset); + try t.setColor(.reset); } } else { - try ttyconf.setColor(w, color); + try t.setColor(color); try w.splatByteAll(' ', indent); try w.writeAll(kind); try w.writeAll(": "); - try ttyconf.setColor(w, .reset); + try t.setColor(.reset); const msg = eb.nullTerminatedString(err_msg.msg); if (err_msg.count == 1) { try w.print("{s}\n", .{msg}); } else { try w.print("{s}", .{msg}); - try ttyconf.setColor(w, .dim); + try t.setColor(.dim); try w.print(" ({d} times)\n", .{err_msg.count}); } - try ttyconf.setColor(w, .reset); + try t.setColor(.reset); for (eb.getNotes(err_msg_index)) |note| { - try renderErrorMessageToWriter(eb, options, note, w, ttyconf, "note", .cyan, indent + 4); + try renderErrorMessage(eb, options, note, t, "note", .cyan, indent + 4); } } } @@ -806,12 +818,10 @@ pub const Wip = struct { }; defer bundle.deinit(std.testing.allocator); - const ttyconf: Io.tty.Config = .no_color; - var bundle_buf: Writer.Allocating = .init(std.testing.allocator); const bundle_bw = &bundle_buf.interface; defer bundle_buf.deinit(); - try bundle.renderToWriter(.{ .ttyconf = ttyconf }, bundle_bw); + try bundle.renderToWriter(bundle_bw); var copy = copy: { var wip: ErrorBundle.Wip = undefined; @@ -827,7 +837,7 @@ pub const Wip = struct { var copy_buf: Writer.Allocating = .init(std.testing.allocator); const copy_bw = ©_buf.interface; defer copy_buf.deinit(); - try copy.renderToWriter(.{ .ttyconf = ttyconf }, copy_bw); + try copy.renderToWriter(copy_bw); try std.testing.expectEqualStrings(bundle_bw.written(), copy_bw.written()); } diff --git a/lib/std/zig/LibCDirs.zig b/lib/std/zig/LibCDirs.zig index fa297cd53aae..5d2313e50ad7 100644 --- a/lib/std/zig/LibCDirs.zig +++ b/lib/std/zig/LibCDirs.zig @@ -1,3 +1,11 @@ +const LibCDirs = @This(); +const builtin = @import("builtin"); + +const std = @import("../std.zig"); +const Io = std.Io; +const LibCInstallation = std.zig.LibCInstallation; +const Allocator = std.mem.Allocator; + libc_include_dir_list: []const []const u8, libc_installation: ?*const LibCInstallation, libc_framework_dir_list: []const []const u8, @@ -14,11 +22,13 @@ pub const DarwinSdkLayout = enum { pub fn detect( arena: Allocator, + io: Io, zig_lib_dir: []const u8, target: *const std.Target, is_native_abi: bool, link_libc: bool, libc_installation: ?*const LibCInstallation, + environ_map: *const std.process.Environ.Map, ) LibCInstallation.FindError!LibCDirs { if (!link_libc) { return .{ @@ -38,7 +48,10 @@ pub fn detect( // using the system libc installation. if (is_native_abi and !target.isMinGW()) { const libc = try arena.create(LibCInstallation); - libc.* = LibCInstallation.findNative(.{ .allocator = arena, .target = target }) catch |err| switch (err) { + libc.* = LibCInstallation.findNative(arena, io, .{ + .target = target, + .environ_map = environ_map, + }) catch |err| switch (err) { error.CCompilerExitCode, error.CCompilerCrashed, error.CCompilerCannotFindHeaders, @@ -75,12 +88,16 @@ pub fn detect( if (use_system_abi) { const libc = try arena.create(LibCInstallation); - libc.* = try LibCInstallation.findNative(.{ .allocator = arena, .verbose = true, .target = target }); + libc.* = try LibCInstallation.findNative(arena, io, .{ + .verbose = true, + .target = target, + .environ_map = environ_map, + }); return detectFromInstallation(arena, target, libc); } return .{ - .libc_include_dir_list = &[0][]u8{}, + .libc_include_dir_list = &.{}, .libc_installation = null, .libc_framework_dir_list = &.{}, .sysroot = null, @@ -176,6 +193,8 @@ pub fn detectFromBuilding( std.zig.target.freebsdArchNameHeaders(target.cpu.arch) else if (target.isNetBSDLibC()) std.zig.target.netbsdArchNameHeaders(target.cpu.arch) + else if (target.isOpenBSDLibC()) + std.zig.target.openbsdArchNameHeaders(target.cpu.arch) else @tagName(target.cpu.arch); const os_name = @tagName(target.os.tag); @@ -230,6 +249,7 @@ fn libCGenericName(target: *const std.Target) [:0]const u8 { .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => return "darwin", .freebsd => return "freebsd", .netbsd => return "netbsd", + .openbsd => return "openbsd", else => {}, } switch (target.abi) { @@ -265,9 +285,3 @@ fn libCGenericName(target: *const std.Target) [:0]const u8 { => unreachable, } } - -const LibCDirs = @This(); -const builtin = @import("builtin"); -const std = @import("../std.zig"); -const LibCInstallation = std.zig.LibCInstallation; -const Allocator = std.mem.Allocator; diff --git a/lib/std/zig/LibCInstallation.zig b/lib/std/zig/LibCInstallation.zig index 2ab4e48570cb..02b3df54dce7 100644 --- a/lib/std/zig/LibCInstallation.zig +++ b/lib/std/zig/LibCInstallation.zig @@ -1,4 +1,19 @@ //! See the render function implementation for documentation of the fields. +const LibCInstallation = @This(); + +const builtin = @import("builtin"); +const is_darwin = builtin.target.os.tag.isDarwin(); +const is_windows = builtin.target.os.tag == .windows; +const is_haiku = builtin.target.os.tag == .haiku; + +const std = @import("std"); +const Io = std.Io; +const Target = std.Target; +const fs = std.fs; +const Allocator = std.mem.Allocator; +const Path = std.Build.Cache.Path; +const log = std.log.scoped(.libc_installation); +const Environ = std.process.Environ; include_dir: ?[]const u8 = null, sys_include_dir: ?[]const u8 = null, @@ -23,11 +38,7 @@ pub const FindError = error{ ZigIsTheCCompiler, }; -pub fn parse( - allocator: Allocator, - libc_file: []const u8, - target: *const std.Target, -) !LibCInstallation { +pub fn parse(allocator: Allocator, io: Io, libc_file: []const u8, target: *const std.Target) !LibCInstallation { var self: LibCInstallation = .{}; const fields = std.meta.fields(LibCInstallation); @@ -43,7 +54,7 @@ pub fn parse( } } - const contents = try std.fs.cwd().readFileAlloc(libc_file, allocator, .limited(std.math.maxInt(usize))); + const contents = try Io.Dir.cwd().readFileAlloc(io, libc_file, allocator, .limited(std.math.maxInt(usize))); defer allocator.free(contents); var it = std.mem.tokenizeScalar(u8, contents, '\n'); @@ -156,58 +167,58 @@ pub fn render(self: LibCInstallation, out: *std.Io.Writer) !void { } pub const FindNativeOptions = struct { - allocator: Allocator, target: *const std.Target, + environ_map: *const Environ.Map, /// If enabled, will print human-friendly errors to stderr. verbose: bool = false, }; /// Finds the default, native libc. -pub fn findNative(args: FindNativeOptions) FindError!LibCInstallation { +pub fn findNative(gpa: Allocator, io: Io, args: FindNativeOptions) FindError!LibCInstallation { var self: LibCInstallation = .{}; if (is_darwin and args.target.os.tag.isDarwin()) { - if (!std.zig.system.darwin.isSdkInstalled(args.allocator)) + if (!std.zig.system.darwin.isSdkInstalled(gpa, io)) return error.DarwinSdkNotFound; - const sdk = std.zig.system.darwin.getSdk(args.allocator, args.target) orelse + const sdk = std.zig.system.darwin.getSdk(gpa, io, args.target) orelse return error.DarwinSdkNotFound; - defer args.allocator.free(sdk); + defer gpa.free(sdk); - self.include_dir = try fs.path.join(args.allocator, &.{ + self.include_dir = try fs.path.join(gpa, &.{ sdk, "usr/include", }); - self.sys_include_dir = try fs.path.join(args.allocator, &.{ + self.sys_include_dir = try fs.path.join(gpa, &.{ sdk, "usr/include", }); return self; } else if (is_windows) { - const sdk = std.zig.WindowsSdk.find(args.allocator, args.target.cpu.arch) catch |err| switch (err) { + const sdk = std.zig.WindowsSdk.find(gpa, io, args.target.cpu.arch, args.environ_map) catch |err| switch (err) { error.NotFound => return error.WindowsSdkNotFound, error.PathTooLong => return error.WindowsSdkNotFound, error.OutOfMemory => return error.OutOfMemory, }; - defer sdk.free(args.allocator); + defer sdk.free(gpa); - try self.findNativeMsvcIncludeDir(args, sdk); - try self.findNativeMsvcLibDir(args, sdk); - try self.findNativeKernel32LibDir(args, sdk); - try self.findNativeIncludeDirWindows(args, sdk); - try self.findNativeCrtDirWindows(args, sdk); + try self.findNativeMsvcIncludeDir(gpa, io, sdk); + try self.findNativeMsvcLibDir(gpa, sdk); + try self.findNativeKernel32LibDir(gpa, io, args, sdk); + try self.findNativeIncludeDirWindows(gpa, io, sdk); + try self.findNativeCrtDirWindows(gpa, io, args.target, sdk); } else if (is_haiku) { - try self.findNativeIncludeDirPosix(args); - try self.findNativeGccDirHaiku(args); - self.crt_dir = try args.allocator.dupeZ(u8, "/system/develop/lib"); + try self.findNativeIncludeDirPosix(gpa, io, args); + try self.findNativeGccDirHaiku(gpa, io, args); + self.crt_dir = try gpa.dupe(u8, "/system/develop/lib"); } else if (builtin.target.os.tag == .illumos) { // There is only one libc, and its headers/libraries are always in the same spot. - self.include_dir = try args.allocator.dupeZ(u8, "/usr/include"); - self.sys_include_dir = try args.allocator.dupeZ(u8, "/usr/include"); - self.crt_dir = try args.allocator.dupeZ(u8, "/usr/lib/64"); + self.include_dir = try gpa.dupe(u8, "/usr/include"); + self.sys_include_dir = try gpa.dupe(u8, "/usr/include"); + self.crt_dir = try gpa.dupe(u8, "/usr/lib/64"); } else if (std.process.can_spawn) { - try self.findNativeIncludeDirPosix(args); + try self.findNativeIncludeDirPosix(gpa, io, args); switch (builtin.target.os.tag) { - .freebsd, .netbsd, .openbsd, .dragonfly => self.crt_dir = try args.allocator.dupeZ(u8, "/usr/lib"), - .linux => try self.findNativeCrtDirPosix(args), + .freebsd, .netbsd, .openbsd, .dragonfly => self.crt_dir = try gpa.dupe(u8, "/usr/lib"), + .linux => try self.findNativeCrtDirPosix(gpa, io, args), else => {}, } } else { @@ -227,33 +238,28 @@ pub fn deinit(self: *LibCInstallation, allocator: Allocator) void { self.* = undefined; } -fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) FindError!void { - const allocator = args.allocator; - +fn findNativeIncludeDirPosix(self: *LibCInstallation, gpa: Allocator, io: Io, args: FindNativeOptions) FindError!void { // Detect infinite loops. - var env_map = std.process.getEnvMap(allocator) catch |err| switch (err) { - error.Unexpected => unreachable, // WASI-only - else => |e| return e, - }; - defer env_map.deinit(); - const skip_cc_env_var = if (env_map.get(inf_loop_env_key)) |phase| blk: { + var environ_map = try args.environ_map.clone(gpa); + defer environ_map.deinit(); + const skip_cc_env_var = if (environ_map.get(inf_loop_env_key)) |phase| blk: { if (std.mem.eql(u8, phase, "1")) { - try env_map.put(inf_loop_env_key, "2"); + try environ_map.put(inf_loop_env_key, "2"); break :blk true; } else { return error.ZigIsTheCCompiler; } } else blk: { - try env_map.put(inf_loop_env_key, "1"); + try environ_map.put(inf_loop_env_key, "1"); break :blk false; }; const dev_null = if (is_windows) "nul" else "/dev/null"; - var argv = std.array_list.Managed([]const u8).init(allocator); + var argv = std.array_list.Managed([]const u8).init(gpa); defer argv.deinit(); - try appendCcExe(&argv, skip_cc_env_var); + try appendCcExe(&argv, skip_cc_env_var, &environ_map); try argv.appendSlice(&.{ "-E", "-Wp,-v", @@ -261,11 +267,10 @@ fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) F dev_null, }); - const run_res = std.process.Child.run(.{ - .allocator = allocator, - .argv = argv.items, + const run_res = std.process.run(gpa, io, .{ .max_output_bytes = 1024 * 1024, - .env_map = &env_map, + .argv = argv.items, + .environ_map = &environ_map, // Some C compilers, such as Clang, are known to rely on argv[0] to find the path // to their own executable, without even bothering to resolve PATH. This results in the message: // error: unable to execute command: Executable "" doesn't exist! @@ -279,11 +284,11 @@ fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) F }, }; defer { - allocator.free(run_res.stdout); - allocator.free(run_res.stderr); + gpa.free(run_res.stdout); + gpa.free(run_res.stderr); } switch (run_res.term) { - .Exited => |code| if (code != 0) { + .exited => |code| if (code != 0) { printVerboseInvocation(argv.items, null, args.verbose, run_res.stderr); return error.CCompilerExitCode; }, @@ -294,7 +299,7 @@ fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) F } var it = std.mem.tokenizeAny(u8, run_res.stderr, "\n\r"); - var search_paths = std.array_list.Managed([]const u8).init(allocator); + var search_paths = std.array_list.Managed([]const u8).init(gpa); defer search_paths.deinit(); while (it.next()) |line| { if (line.len != 0 and line[0] == ' ') { @@ -318,7 +323,7 @@ fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) F // search in reverse order const search_path_untrimmed = search_paths.items[search_paths.items.len - path_i - 1]; const search_path = std.mem.trimStart(u8, search_path_untrimmed, " "); - var search_dir = fs.cwd().openDir(search_path, .{}) catch |err| switch (err) { + var search_dir = Io.Dir.cwd().openDir(io, search_path, .{}) catch |err| switch (err) { error.FileNotFound, error.NotDir, error.NoDevice, @@ -326,11 +331,11 @@ fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) F else => return error.FileSystem, }; - defer search_dir.close(); + defer search_dir.close(io); if (self.include_dir == null) { - if (search_dir.access(include_dir_example_file, .{})) |_| { - self.include_dir = try allocator.dupeZ(u8, search_path); + if (search_dir.access(io, include_dir_example_file, .{})) |_| { + self.include_dir = try gpa.dupe(u8, search_path); } else |err| switch (err) { error.FileNotFound => {}, else => return error.FileSystem, @@ -338,8 +343,8 @@ fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) F } if (self.sys_include_dir == null) { - if (search_dir.access(sys_include_dir_example_file, .{})) |_| { - self.sys_include_dir = try allocator.dupeZ(u8, search_path); + if (search_dir.access(io, sys_include_dir_example_file, .{})) |_| { + self.sys_include_dir = try gpa.dupe(u8, search_path); } else |err| switch (err) { error.FileNotFound => {}, else => return error.FileSystem, @@ -357,22 +362,21 @@ fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) F fn findNativeIncludeDirWindows( self: *LibCInstallation, - args: FindNativeOptions, + gpa: Allocator, + io: Io, sdk: std.zig.WindowsSdk, ) FindError!void { - const allocator = args.allocator; - var install_buf: [2]std.zig.WindowsSdk.Installation = undefined; const installs = fillInstallations(&install_buf, sdk); - var result_buf = std.array_list.Managed(u8).init(allocator); + var result_buf = std.array_list.Managed(u8).init(gpa); defer result_buf.deinit(); for (installs) |install| { result_buf.shrinkAndFree(0); try result_buf.print("{s}\\Include\\{s}\\ucrt", .{ install.path, install.version }); - var dir = fs.cwd().openDir(result_buf.items, .{}) catch |err| switch (err) { + var dir = Io.Dir.cwd().openDir(io, result_buf.items, .{}) catch |err| switch (err) { error.FileNotFound, error.NotDir, error.NoDevice, @@ -380,9 +384,9 @@ fn findNativeIncludeDirWindows( else => return error.FileSystem, }; - defer dir.close(); + defer dir.close(io); - dir.access("stdlib.h", .{}) catch |err| switch (err) { + dir.access(io, "stdlib.h", .{}) catch |err| switch (err) { error.FileNotFound => continue, else => return error.FileSystem, }; @@ -396,18 +400,18 @@ fn findNativeIncludeDirWindows( fn findNativeCrtDirWindows( self: *LibCInstallation, - args: FindNativeOptions, + gpa: Allocator, + io: Io, + target: *const std.Target, sdk: std.zig.WindowsSdk, ) FindError!void { - const allocator = args.allocator; - var install_buf: [2]std.zig.WindowsSdk.Installation = undefined; const installs = fillInstallations(&install_buf, sdk); - var result_buf = std.array_list.Managed(u8).init(allocator); + var result_buf = std.array_list.Managed(u8).init(gpa); defer result_buf.deinit(); - const arch_sub_dir = switch (args.target.cpu.arch) { + const arch_sub_dir = switch (target.cpu.arch) { .x86 => "x86", .x86_64 => "x64", .arm, .armeb => "arm", @@ -419,7 +423,7 @@ fn findNativeCrtDirWindows( result_buf.shrinkAndFree(0); try result_buf.print("{s}\\Lib\\{s}\\ucrt\\{s}", .{ install.path, install.version, arch_sub_dir }); - var dir = fs.cwd().openDir(result_buf.items, .{}) catch |err| switch (err) { + var dir = Io.Dir.cwd().openDir(io, result_buf.items, .{}) catch |err| switch (err) { error.FileNotFound, error.NotDir, error.NoDevice, @@ -427,9 +431,9 @@ fn findNativeCrtDirWindows( else => return error.FileSystem, }; - defer dir.close(); + defer dir.close(io); - dir.access("ucrt.lib", .{}) catch |err| switch (err) { + dir.access(io, "ucrt.lib", .{}) catch |err| switch (err) { error.FileNotFound => continue, else => return error.FileSystem, }; @@ -440,9 +444,9 @@ fn findNativeCrtDirWindows( return error.LibCRuntimeNotFound; } -fn findNativeCrtDirPosix(self: *LibCInstallation, args: FindNativeOptions) FindError!void { - self.crt_dir = try ccPrintFileName(.{ - .allocator = args.allocator, +fn findNativeCrtDirPosix(self: *LibCInstallation, gpa: Allocator, io: Io, args: FindNativeOptions) FindError!void { + self.crt_dir = try ccPrintFileName(gpa, io, .{ + .environ_map = args.environ_map, .search_basename = switch (args.target.os.tag) { .linux => if (args.target.abi.isAndroid()) "crtbegin_dynamic.o" else "crt1.o", else => "crt1.o", @@ -452,9 +456,8 @@ fn findNativeCrtDirPosix(self: *LibCInstallation, args: FindNativeOptions) FindE }); } -fn findNativeGccDirHaiku(self: *LibCInstallation, args: FindNativeOptions) FindError!void { - self.gcc_dir = try ccPrintFileName(.{ - .allocator = args.allocator, +fn findNativeGccDirHaiku(self: *LibCInstallation, gpa: Allocator, io: Io, args: FindNativeOptions) FindError!void { + self.gcc_dir = try ccPrintFileName(gpa, io, .{ .search_basename = "crtbeginS.o", .want_dirname = .only_dir, .verbose = args.verbose, @@ -463,15 +466,15 @@ fn findNativeGccDirHaiku(self: *LibCInstallation, args: FindNativeOptions) FindE fn findNativeKernel32LibDir( self: *LibCInstallation, + gpa: Allocator, + io: Io, args: FindNativeOptions, sdk: std.zig.WindowsSdk, ) FindError!void { - const allocator = args.allocator; - var install_buf: [2]std.zig.WindowsSdk.Installation = undefined; const installs = fillInstallations(&install_buf, sdk); - var result_buf = std.array_list.Managed(u8).init(allocator); + var result_buf = std.array_list.Managed(u8).init(gpa); defer result_buf.deinit(); const arch_sub_dir = switch (args.target.cpu.arch) { @@ -486,7 +489,7 @@ fn findNativeKernel32LibDir( result_buf.shrinkAndFree(0); try result_buf.print("{s}\\Lib\\{s}\\um\\{s}", .{ install.path, install.version, arch_sub_dir }); - var dir = fs.cwd().openDir(result_buf.items, .{}) catch |err| switch (err) { + var dir = Io.Dir.cwd().openDir(io, result_buf.items, .{}) catch |err| switch (err) { error.FileNotFound, error.NotDir, error.NoDevice, @@ -494,9 +497,9 @@ fn findNativeKernel32LibDir( else => return error.FileSystem, }; - defer dir.close(); + defer dir.close(io); - dir.access("kernel32.lib", .{}) catch |err| switch (err) { + dir.access(io, "kernel32.lib", .{}) catch |err| switch (err) { error.FileNotFound => continue, else => return error.FileSystem, }; @@ -509,19 +512,18 @@ fn findNativeKernel32LibDir( fn findNativeMsvcIncludeDir( self: *LibCInstallation, - args: FindNativeOptions, + gpa: Allocator, + io: Io, sdk: std.zig.WindowsSdk, ) FindError!void { - const allocator = args.allocator; - const msvc_lib_dir = sdk.msvc_lib_dir orelse return error.LibCStdLibHeaderNotFound; const up1 = fs.path.dirname(msvc_lib_dir) orelse return error.LibCStdLibHeaderNotFound; const up2 = fs.path.dirname(up1) orelse return error.LibCStdLibHeaderNotFound; - const dir_path = try fs.path.join(allocator, &[_][]const u8{ up2, "include" }); - errdefer allocator.free(dir_path); + const dir_path = try fs.path.join(gpa, &[_][]const u8{ up2, "include" }); + errdefer gpa.free(dir_path); - var dir = fs.cwd().openDir(dir_path, .{}) catch |err| switch (err) { + var dir = Io.Dir.cwd().openDir(io, dir_path, .{}) catch |err| switch (err) { error.FileNotFound, error.NotDir, error.NoDevice, @@ -529,9 +531,9 @@ fn findNativeMsvcIncludeDir( else => return error.FileSystem, }; - defer dir.close(); + defer dir.close(io); - dir.access("vcruntime.h", .{}) catch |err| switch (err) { + dir.access(io, "vcruntime.h", .{}) catch |err| switch (err) { error.FileNotFound => return error.LibCStdLibHeaderNotFound, else => return error.FileSystem, }; @@ -541,57 +543,50 @@ fn findNativeMsvcIncludeDir( fn findNativeMsvcLibDir( self: *LibCInstallation, - args: FindNativeOptions, + gpa: Allocator, sdk: std.zig.WindowsSdk, ) FindError!void { - const allocator = args.allocator; const msvc_lib_dir = sdk.msvc_lib_dir orelse return error.LibCRuntimeNotFound; - self.msvc_lib_dir = try allocator.dupe(u8, msvc_lib_dir); + self.msvc_lib_dir = try gpa.dupe(u8, msvc_lib_dir); } pub const CCPrintFileNameOptions = struct { - allocator: Allocator, + environ_map: *const Environ.Map, search_basename: []const u8, want_dirname: enum { full_path, only_dir }, verbose: bool = false, }; /// caller owns returned memory -fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 { - const allocator = args.allocator; - +fn ccPrintFileName(gpa: Allocator, io: Io, args: CCPrintFileNameOptions) ![]u8 { // Detect infinite loops. - var env_map = std.process.getEnvMap(allocator) catch |err| switch (err) { - error.Unexpected => unreachable, // WASI-only - else => |e| return e, - }; - defer env_map.deinit(); - const skip_cc_env_var = if (env_map.get(inf_loop_env_key)) |phase| blk: { + var environ_map = try args.environ_map.clone(gpa); + defer environ_map.deinit(); + const skip_cc_env_var = if (environ_map.get(inf_loop_env_key)) |phase| blk: { if (std.mem.eql(u8, phase, "1")) { - try env_map.put(inf_loop_env_key, "2"); + try environ_map.put(inf_loop_env_key, "2"); break :blk true; } else { return error.ZigIsTheCCompiler; } } else blk: { - try env_map.put(inf_loop_env_key, "1"); + try environ_map.put(inf_loop_env_key, "1"); break :blk false; }; - var argv = std.array_list.Managed([]const u8).init(allocator); + var argv = std.array_list.Managed([]const u8).init(gpa); defer argv.deinit(); - const arg1 = try std.fmt.allocPrint(allocator, "-print-file-name={s}", .{args.search_basename}); - defer allocator.free(arg1); + const arg1 = try std.fmt.allocPrint(gpa, "-print-file-name={s}", .{args.search_basename}); + defer gpa.free(arg1); - try appendCcExe(&argv, skip_cc_env_var); + try appendCcExe(&argv, skip_cc_env_var, &environ_map); try argv.append(arg1); - const run_res = std.process.Child.run(.{ - .allocator = allocator, - .argv = argv.items, + const run_res = std.process.run(gpa, io, .{ .max_output_bytes = 1024 * 1024, - .env_map = &env_map, + .argv = argv.items, + .environ_map = &environ_map, // Some C compilers, such as Clang, are known to rely on argv[0] to find the path // to their own executable, without even bothering to resolve PATH. This results in the message: // error: unable to execute command: Executable "" doesn't exist! @@ -602,11 +597,11 @@ fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 { else => return error.UnableToSpawnCCompiler, }; defer { - allocator.free(run_res.stdout); - allocator.free(run_res.stderr); + gpa.free(run_res.stdout); + gpa.free(run_res.stderr); } switch (run_res.term) { - .Exited => |code| if (code != 0) { + .exited => |code| if (code != 0) { printVerboseInvocation(argv.items, args.search_basename, args.verbose, run_res.stderr); return error.CCompilerExitCode; }, @@ -622,10 +617,10 @@ fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 { // So we detect failure by checking if the output matches exactly the input. if (std.mem.eql(u8, line, args.search_basename)) return error.LibCRuntimeNotFound; switch (args.want_dirname) { - .full_path => return allocator.dupeZ(u8, line), + .full_path => return gpa.dupe(u8, line), .only_dir => { const dirname = fs.path.dirname(line) orelse return error.LibCRuntimeNotFound; - return allocator.dupeZ(u8, dirname); + return gpa.dupe(u8, dirname); }, } } @@ -671,14 +666,18 @@ fn fillInstallations( const inf_loop_env_key = "ZIG_IS_DETECTING_LIBC_PATHS"; -fn appendCcExe(args: *std.array_list.Managed([]const u8), skip_cc_env_var: bool) !void { +fn appendCcExe( + args: *std.array_list.Managed([]const u8), + skip_cc_env_var: bool, + environ_map: *const Environ.Map, +) !void { const default_cc_exe = if (is_windows) "cc.exe" else "cc"; try args.ensureUnusedCapacity(1); if (skip_cc_env_var) { args.appendAssumeCapacity(default_cc_exe); return; } - const cc_env_var = std.zig.EnvVar.CC.getPosix() orelse { + const cc_env_var = std.zig.EnvVar.CC.get(environ_map) orelse { args.appendAssumeCapacity(default_cc_exe); return; }; @@ -1015,17 +1014,3 @@ pub fn resolveCrtPaths( }, } } - -const LibCInstallation = @This(); -const std = @import("std"); -const builtin = @import("builtin"); -const Target = std.Target; -const fs = std.fs; -const Allocator = std.mem.Allocator; -const Path = std.Build.Cache.Path; - -const is_darwin = builtin.target.os.tag.isDarwin(); -const is_windows = builtin.target.os.tag == .windows; -const is_haiku = builtin.target.os.tag == .haiku; - -const log = std.log.scoped(.libc_installation); diff --git a/lib/std/zig/Parse.zig b/lib/std/zig/Parse.zig index 4d8c71081644..c8ad4c5fdaad 100644 --- a/lib/std/zig/Parse.zig +++ b/lib/std/zig/Parse.zig @@ -1820,50 +1820,39 @@ fn parseTypeExpr(p: *Parse) Error!?Node.Index { _ = try p.expectToken(.r_bracket); const mods = try p.parsePtrModifiers(); const elem_type = try p.expectTypeExpr(); - if (mods.bit_range_start == .none) { - if (sentinel == null and mods.addrspace_node == .none) { - return try p.addNode(.{ - .tag = .ptr_type_aligned, - .main_token = l_bracket, - .data = .{ .opt_node_and_node = .{ - mods.align_node, - elem_type, - } }, - }); - } else if (mods.align_node == .none and mods.addrspace_node == .none) { - return try p.addNode(.{ - .tag = .ptr_type_sentinel, - .main_token = l_bracket, - .data = .{ .opt_node_and_node = .{ - .fromOptional(sentinel), - elem_type, - } }, - }); - } else { - return try p.addNode(.{ - .tag = .ptr_type, - .main_token = l_bracket, - .data = .{ .extra_and_node = .{ - try p.addExtra(Node.PtrType{ - .sentinel = .fromOptional(sentinel), - .align_node = mods.align_node, - .addrspace_node = mods.addrspace_node, - }), - elem_type, - } }, - }); - } + if (mods.bit_range_start.unwrap()) |bit_range_start| { + try p.warnMsg(.{ + .tag = .invalid_bit_range, + .token = p.nodeMainToken(bit_range_start), + }); + } + if (sentinel == null and mods.addrspace_node == .none) { + return try p.addNode(.{ + .tag = .ptr_type_aligned, + .main_token = l_bracket, + .data = .{ .opt_node_and_node = .{ + mods.align_node, + elem_type, + } }, + }); + } else if (mods.align_node == .none and mods.addrspace_node == .none) { + return try p.addNode(.{ + .tag = .ptr_type_sentinel, + .main_token = l_bracket, + .data = .{ .opt_node_and_node = .{ + .fromOptional(sentinel), + elem_type, + } }, + }); } else { return try p.addNode(.{ - .tag = .ptr_type_bit_range, + .tag = .ptr_type, .main_token = l_bracket, .data = .{ .extra_and_node = .{ - try p.addExtra(Node.PtrTypeBitRange{ + try p.addExtra(Node.PtrType{ .sentinel = .fromOptional(sentinel), - .align_node = mods.align_node.unwrap().?, + .align_node = mods.align_node, .addrspace_node = mods.addrspace_node, - .bit_range_start = mods.bit_range_start.unwrap().?, - .bit_range_end = mods.bit_range_end.unwrap().?, }), elem_type, } }, @@ -2857,32 +2846,6 @@ fn expectAsmExpr(p: *Parse) !Node.Index { _ = p.eatToken(.colon) orelse break :clobbers .none; - // For automatic upgrades; delete after 0.15.0 released. - if (p.tokenTag(p.tok_i) == .string_literal) { - while (p.eatToken(.string_literal)) |_| { - switch (p.tokenTag(p.tok_i)) { - .comma => p.tok_i += 1, - .colon, .r_paren, .r_brace, .r_bracket => break, - // Likely just a missing comma; give error but continue parsing. - else => try p.warnExpected(.comma), - } - } - const rparen = try p.expectToken(.r_paren); - const span = try p.listToSpan(p.scratch.items[scratch_top..]); - return p.addNode(.{ - .tag = .asm_legacy, - .main_token = asm_token, - .data = .{ .node_and_extra = .{ - template, - try p.addExtra(Node.AsmLegacy{ - .items_start = span.start, - .items_end = span.end, - .rparen = rparen, - }), - } }, - }); - } - break :clobbers (try p.expectExpr()).toOptional(); } else .none; @@ -3686,7 +3649,7 @@ fn eatDocComments(p: *Parse) Allocator.Error!?TokenIndex { } fn tokensOnSameLine(p: *Parse, token1: TokenIndex, token2: TokenIndex) bool { - return std.mem.indexOfScalar(u8, p.source[p.tokenStart(token1)..p.tokenStart(token2)], '\n') == null; + return std.mem.findScalar(u8, p.source[p.tokenStart(token1)..p.tokenStart(token2)], '\n') == null; } fn eatToken(p: *Parse, tag: Token.Tag) ?TokenIndex { diff --git a/lib/std/zig/WindowsSdk.zig b/lib/std/zig/WindowsSdk.zig index 9c9f4bd9aaef..d6e7e35130c5 100644 --- a/lib/std/zig/WindowsSdk.zig +++ b/lib/std/zig/WindowsSdk.zig @@ -1,7 +1,12 @@ const WindowsSdk = @This(); const builtin = @import("builtin"); + const std = @import("std"); +const Io = std.Io; +const Dir = std.Io.Dir; const Writer = std.Io.Writer; +const Allocator = std.mem.Allocator; +const Environ = std.process.Environ; windows10sdk: ?Installation, windows81sdk: ?Installation, @@ -19,8 +24,13 @@ const product_version_max_length = version_major_minor_max_length + ".65535".len /// Find path and version of Windows 10 SDK and Windows 8.1 SDK, and find path to MSVC's `lib/` directory. /// Caller owns the result's fields. -/// After finishing work, call `free(allocator)`. -pub fn find(allocator: std.mem.Allocator, arch: std.Target.Cpu.Arch) error{ OutOfMemory, NotFound, PathTooLong }!WindowsSdk { +/// Returns memory allocated by `gpa` +pub fn find( + gpa: Allocator, + io: Io, + arch: std.Target.Cpu.Arch, + environ_map: *const Environ.Map, +) error{ OutOfMemory, NotFound, PathTooLong }!WindowsSdk { if (builtin.os.tag != .windows) return error.NotFound; //note(dimenus): If this key doesn't exist, neither the Win 8 SDK nor the Win 10 SDK is installed @@ -29,27 +39,27 @@ pub fn find(allocator: std.mem.Allocator, arch: std.Target.Cpu.Arch) error{ OutO }; defer roots_key.closeKey(); - const windows10sdk = Installation.find(allocator, roots_key, "KitsRoot10", "", "v10.0") catch |err| switch (err) { + const windows10sdk = Installation.find(gpa, io, roots_key, "KitsRoot10", "", "v10.0") catch |err| switch (err) { error.InstallationNotFound => null, error.PathTooLong => null, error.VersionTooLong => null, error.OutOfMemory => return error.OutOfMemory, }; - errdefer if (windows10sdk) |*w| w.free(allocator); + errdefer if (windows10sdk) |*w| w.free(gpa); - const windows81sdk = Installation.find(allocator, roots_key, "KitsRoot81", "winver", "v8.1") catch |err| switch (err) { + const windows81sdk = Installation.find(gpa, io, roots_key, "KitsRoot81", "winver", "v8.1") catch |err| switch (err) { error.InstallationNotFound => null, error.PathTooLong => null, error.VersionTooLong => null, error.OutOfMemory => return error.OutOfMemory, }; - errdefer if (windows81sdk) |*w| w.free(allocator); + errdefer if (windows81sdk) |*w| w.free(gpa); - const msvc_lib_dir: ?[]const u8 = MsvcLibDir.find(allocator, arch) catch |err| switch (err) { + const msvc_lib_dir: ?[]const u8 = MsvcLibDir.find(gpa, io, arch, environ_map) catch |err| switch (err) { error.MsvcLibDirNotFound => null, error.OutOfMemory => return error.OutOfMemory, }; - errdefer allocator.free(msvc_lib_dir); + errdefer gpa.free(msvc_lib_dir); return .{ .windows10sdk = windows10sdk, @@ -58,15 +68,15 @@ pub fn find(allocator: std.mem.Allocator, arch: std.Target.Cpu.Arch) error{ OutO }; } -pub fn free(sdk: WindowsSdk, allocator: std.mem.Allocator) void { +pub fn free(sdk: WindowsSdk, gpa: Allocator) void { if (sdk.windows10sdk) |*w10sdk| { - w10sdk.free(allocator); + w10sdk.free(gpa); } if (sdk.windows81sdk) |*w81sdk| { - w81sdk.free(allocator); + w81sdk.free(gpa); } if (sdk.msvc_lib_dir) |msvc_lib_dir| { - allocator.free(msvc_lib_dir); + gpa.free(msvc_lib_dir); } } @@ -74,8 +84,9 @@ pub fn free(sdk: WindowsSdk, allocator: std.mem.Allocator) void { /// and a version. Returns slice of version strings sorted in descending order. /// Caller owns result. fn iterateAndFilterByVersion( - iterator: *std.fs.Dir.Iterator, - allocator: std.mem.Allocator, + iterator: *Dir.Iterator, + gpa: Allocator, + io: Io, prefix: []const u8, ) error{OutOfMemory}![][]const u8 { const Version = struct { @@ -92,15 +103,15 @@ fn iterateAndFilterByVersion( std.mem.order(u8, lhs.build, rhs.build); } }; - var versions = std.array_list.Managed(Version).init(allocator); - var dirs = std.array_list.Managed([]const u8).init(allocator); + var versions = std.array_list.Managed(Version).init(gpa); + var dirs = std.array_list.Managed([]const u8).init(gpa); defer { versions.deinit(); - for (dirs.items) |filtered_dir| allocator.free(filtered_dir); + for (dirs.items) |filtered_dir| gpa.free(filtered_dir); dirs.deinit(); } - iterate: while (iterator.next() catch null) |entry| { + iterate: while (iterator.next(io) catch null) |entry| { if (entry.kind != .directory) continue; if (!std.mem.startsWith(u8, entry.name, prefix)) continue; @@ -109,15 +120,15 @@ fn iterateAndFilterByVersion( .build = "", }; const suffix = entry.name[prefix.len..]; - const underscore = std.mem.indexOfScalar(u8, entry.name, '_'); + const underscore = std.mem.findScalar(u8, entry.name, '_'); var num_it = std.mem.splitScalar(u8, suffix[0 .. underscore orelse suffix.len], '.'); version.nums[0] = Version.parseNum(num_it.first()) orelse continue; for (version.nums[1..]) |*num| num.* = Version.parseNum(num_it.next() orelse break) orelse continue :iterate else if (num_it.next()) |_| continue; - const name = try allocator.dupe(u8, suffix); - errdefer allocator.free(name); + const name = try gpa.dupe(u8, suffix); + errdefer gpa.free(name); if (underscore) |pos| version.build = name[pos + 1 ..]; try versions.append(version); @@ -174,7 +185,7 @@ const RegistryWtf8 = struct { /// Get string from registry. /// Caller owns result. - pub fn getString(reg: RegistryWtf8, allocator: std.mem.Allocator, subkey: []const u8, value_name: []const u8) error{ OutOfMemory, ValueNameNotFound, NotAString, StringNotFound }![]u8 { + pub fn getString(reg: RegistryWtf8, gpa: Allocator, subkey: []const u8, value_name: []const u8) error{ OutOfMemory, ValueNameNotFound, NotAString, StringNotFound }![]u8 { const subkey_wtf16le: [:0]const u16 = subkey_wtf16le: { var subkey_wtf16le_buf: [RegistryWtf16Le.key_name_max_len]u16 = undefined; const subkey_wtf16le_len: usize = std.unicode.wtf8ToWtf16Le(subkey_wtf16le_buf[0..], subkey) catch unreachable; @@ -190,11 +201,11 @@ const RegistryWtf8 = struct { }; const registry_wtf16le: RegistryWtf16Le = .{ .key = reg.key }; - const value_wtf16le = try registry_wtf16le.getString(allocator, subkey_wtf16le, value_name_wtf16le); - defer allocator.free(value_wtf16le); + const value_wtf16le = try registry_wtf16le.getString(gpa, subkey_wtf16le, value_name_wtf16le); + defer gpa.free(value_wtf16le); - const value_wtf8: []u8 = try std.unicode.wtf16LeToWtf8Alloc(allocator, value_wtf16le); - errdefer allocator.free(value_wtf8); + const value_wtf8: []u8 = try std.unicode.wtf16LeToWtf8Alloc(gpa, value_wtf16le); + errdefer gpa.free(value_wtf8); return value_wtf8; } @@ -250,13 +261,15 @@ const RegistryWtf16Le = struct { /// After finishing work, call `closeKey`. fn openKey(hkey: windows.HKEY, key_wtf16le: [:0]const u16, options: OpenOptions) error{KeyNotFound}!RegistryWtf16Le { var key: windows.HKEY = undefined; - var access: windows.REGSAM = windows.KEY_QUERY_VALUE | windows.KEY_ENUMERATE_SUB_KEYS; - if (options.wow64_32) access |= windows.KEY_WOW64_32KEY; const return_code_int: windows.HRESULT = windows.advapi32.RegOpenKeyExW( hkey, key_wtf16le, 0, - access, + .{ .SPECIFIC = .{ .KEY = .{ + .QUERY_VALUE = true, + .ENUMERATE_SUB_KEYS = true, + .WOW64_32KEY = options.wow64_32, + } } }, &key, ); const return_code: windows.Win32Error = @enumFromInt(return_code_int); @@ -280,7 +293,7 @@ const RegistryWtf16Le = struct { } /// Get string ([:0]const u16) from registry. - fn getString(reg: RegistryWtf16Le, allocator: std.mem.Allocator, subkey_wtf16le: [:0]const u16, value_name_wtf16le: [:0]const u16) error{ OutOfMemory, ValueNameNotFound, NotAString, StringNotFound }![]const u16 { + fn getString(reg: RegistryWtf16Le, gpa: Allocator, subkey_wtf16le: [:0]const u16, value_name_wtf16le: [:0]const u16) error{ OutOfMemory, ValueNameNotFound, NotAString, StringNotFound }![]const u16 { var actual_type: windows.ULONG = undefined; // Calculating length to allocate @@ -309,8 +322,8 @@ const RegistryWtf16Le = struct { else => return error.NotAString, } - const value_wtf16le_buf: []u16 = try allocator.alloc(u16, std.math.divCeil(u32, value_wtf16le_buf_size, 2) catch unreachable); - errdefer allocator.free(value_wtf16le_buf); + const value_wtf16le_buf: []u16 = try gpa.alloc(u16, std.math.divCeil(u32, value_wtf16le_buf_size, 2) catch unreachable); + errdefer gpa.free(value_wtf16le_buf); return_code_int = windows.advapi32.RegGetValueW( reg.key, @@ -344,7 +357,7 @@ const RegistryWtf16Le = struct { break :value_wtf16le std.mem.span(value_wtf16le_overestimated); }; - _ = allocator.resize(value_wtf16le_buf, value_wtf16le.len); + _ = gpa.resize(value_wtf16le_buf, value_wtf16le.len); return value_wtf16le; } @@ -389,7 +402,10 @@ const RegistryWtf16Le = struct { const return_code_int: windows.HRESULT = std.os.windows.advapi32.RegLoadAppKeyW( absolute_path_as_wtf16le, &key, - windows.KEY_QUERY_VALUE | windows.KEY_ENUMERATE_SUB_KEYS, + .{ .SPECIFIC = .{ .KEY = .{ + .QUERY_VALUE = true, + .ENUMERATE_SUB_KEYS = true, + } } }, 0, 0, ); @@ -409,88 +425,89 @@ pub const Installation = struct { /// Find path and version of Windows SDK. /// Caller owns the result's fields. - /// After finishing work, call `free(allocator)`. fn find( - allocator: std.mem.Allocator, + gpa: Allocator, + io: Io, roots_key: RegistryWtf8, roots_subkey: []const u8, prefix: []const u8, version_key_name: []const u8, ) error{ OutOfMemory, InstallationNotFound, PathTooLong, VersionTooLong }!Installation { roots: { - const installation = findFromRoot(allocator, roots_key, roots_subkey, prefix) catch + const installation = findFromRoot(gpa, io, roots_key, roots_subkey, prefix) catch break :roots; if (installation.isValidVersion()) return installation; - installation.free(allocator); + installation.free(gpa); } { - const installation = try findFromInstallationFolder(allocator, version_key_name); + const installation = try findFromInstallationFolder(gpa, version_key_name); if (installation.isValidVersion()) return installation; - installation.free(allocator); + installation.free(gpa); } return error.InstallationNotFound; } fn findFromRoot( - allocator: std.mem.Allocator, + gpa: Allocator, + io: Io, roots_key: RegistryWtf8, roots_subkey: []const u8, prefix: []const u8, ) error{ OutOfMemory, InstallationNotFound, PathTooLong, VersionTooLong }!Installation { const path = path: { - const path_maybe_with_trailing_slash = roots_key.getString(allocator, "", roots_subkey) catch |err| switch (err) { + const path_maybe_with_trailing_slash = roots_key.getString(gpa, "", roots_subkey) catch |err| switch (err) { error.NotAString => return error.InstallationNotFound, error.ValueNameNotFound => return error.InstallationNotFound, error.StringNotFound => return error.InstallationNotFound, error.OutOfMemory => return error.OutOfMemory, }; - if (path_maybe_with_trailing_slash.len > std.fs.max_path_bytes or !std.fs.path.isAbsolute(path_maybe_with_trailing_slash)) { - allocator.free(path_maybe_with_trailing_slash); + if (path_maybe_with_trailing_slash.len > Dir.max_path_bytes or !Dir.path.isAbsolute(path_maybe_with_trailing_slash)) { + gpa.free(path_maybe_with_trailing_slash); return error.PathTooLong; } - var path = std.array_list.Managed(u8).fromOwnedSlice(allocator, path_maybe_with_trailing_slash); + var path = std.array_list.Managed(u8).fromOwnedSlice(gpa, path_maybe_with_trailing_slash); errdefer path.deinit(); // String might contain trailing slash, so trim it here if (path.items.len > "C:\\".len and path.getLast() == '\\') _ = path.pop(); break :path try path.toOwnedSlice(); }; - errdefer allocator.free(path); + errdefer gpa.free(path); const version = version: { - var buf: [std.fs.max_path_bytes]u8 = undefined; + var buf: [Dir.max_path_bytes]u8 = undefined; const sdk_lib_dir_path = std.fmt.bufPrint(buf[0..], "{s}\\Lib\\", .{path}) catch |err| switch (err) { error.NoSpaceLeft => return error.PathTooLong, }; - if (!std.fs.path.isAbsolute(sdk_lib_dir_path)) return error.InstallationNotFound; + if (!Dir.path.isAbsolute(sdk_lib_dir_path)) return error.InstallationNotFound; // enumerate files in sdk path looking for latest version - var sdk_lib_dir = std.fs.openDirAbsolute(sdk_lib_dir_path, .{ + var sdk_lib_dir = Dir.openDirAbsolute(io, sdk_lib_dir_path, .{ .iterate = true, }) catch |err| switch (err) { error.NameTooLong => return error.PathTooLong, else => return error.InstallationNotFound, }; - defer sdk_lib_dir.close(); + defer sdk_lib_dir.close(io); var iterator = sdk_lib_dir.iterate(); - const versions = try iterateAndFilterByVersion(&iterator, allocator, prefix); + const versions = try iterateAndFilterByVersion(&iterator, gpa, io, prefix); if (versions.len == 0) return error.InstallationNotFound; defer { - for (versions[1..]) |version| allocator.free(version); - allocator.free(versions); + for (versions[1..]) |version| gpa.free(version); + gpa.free(versions); } break :version versions[0]; }; - errdefer allocator.free(version); + errdefer gpa.free(version); return .{ .path = path, .version = version }; } fn findFromInstallationFolder( - allocator: std.mem.Allocator, + gpa: Allocator, version_key_name: []const u8, ) error{ OutOfMemory, InstallationNotFound, PathTooLong, VersionTooLong }!Installation { var key_name_buf: [RegistryWtf16Le.key_name_max_len]u8 = undefined; @@ -509,7 +526,7 @@ pub const Installation = struct { defer key.closeKey(); const path: []const u8 = path: { - const path_maybe_with_trailing_slash = key.getString(allocator, "", "InstallationFolder") catch |err| switch (err) { + const path_maybe_with_trailing_slash = key.getString(gpa, "", "InstallationFolder") catch |err| switch (err) { error.NotAString => return error.InstallationNotFound, error.ValueNameNotFound => return error.InstallationNotFound, error.StringNotFound => return error.InstallationNotFound, @@ -517,12 +534,12 @@ pub const Installation = struct { error.OutOfMemory => return error.OutOfMemory, }; - if (path_maybe_with_trailing_slash.len > std.fs.max_path_bytes or !std.fs.path.isAbsolute(path_maybe_with_trailing_slash)) { - allocator.free(path_maybe_with_trailing_slash); + if (path_maybe_with_trailing_slash.len > Dir.max_path_bytes or !Dir.path.isAbsolute(path_maybe_with_trailing_slash)) { + gpa.free(path_maybe_with_trailing_slash); return error.PathTooLong; } - var path = std.array_list.Managed(u8).fromOwnedSlice(allocator, path_maybe_with_trailing_slash); + var path = std.array_list.Managed(u8).fromOwnedSlice(gpa, path_maybe_with_trailing_slash); errdefer path.deinit(); // String might contain trailing slash, so trim it here @@ -531,12 +548,12 @@ pub const Installation = struct { const path_without_trailing_slash = try path.toOwnedSlice(); break :path path_without_trailing_slash; }; - errdefer allocator.free(path); + errdefer gpa.free(path); const version: []const u8 = version: { // note(dimenus): Microsoft doesn't include the .0 in the ProductVersion key.... - const version_without_0 = key.getString(allocator, "", "ProductVersion") catch |err| switch (err) { + const version_without_0 = key.getString(gpa, "", "ProductVersion") catch |err| switch (err) { error.NotAString => return error.InstallationNotFound, error.ValueNameNotFound => return error.InstallationNotFound, error.StringNotFound => return error.InstallationNotFound, @@ -544,11 +561,11 @@ pub const Installation = struct { error.OutOfMemory => return error.OutOfMemory, }; if (version_without_0.len + ".0".len > product_version_max_length) { - allocator.free(version_without_0); + gpa.free(version_without_0); return error.VersionTooLong; } - var version = std.array_list.Managed(u8).fromOwnedSlice(allocator, version_without_0); + var version = std.array_list.Managed(u8).fromOwnedSlice(gpa, version_without_0); errdefer version.deinit(); try version.appendSlice(".0"); @@ -556,14 +573,14 @@ pub const Installation = struct { const version_with_0 = try version.toOwnedSlice(); break :version version_with_0; }; - errdefer allocator.free(version); + errdefer gpa.free(version); return .{ .path = path, .version = version }; } /// Check whether this version is enumerated in registry. fn isValidVersion(installation: Installation) bool { - var buf: [std.fs.max_path_bytes]u8 = undefined; + var buf: [Dir.max_path_bytes]u8 = undefined; const reg_query_as_wtf8 = std.fmt.bufPrint(buf[0..], "{s}\\{s}\\Installed Options", .{ windows_kits_reg_key, installation.version, @@ -592,21 +609,21 @@ pub const Installation = struct { return (reg_value == 1); } - fn free(install: Installation, allocator: std.mem.Allocator) void { - allocator.free(install.path); - allocator.free(install.version); + fn free(install: Installation, gpa: Allocator) void { + gpa.free(install.path); + gpa.free(install.version); } }; const MsvcLibDir = struct { - fn findInstancesDirViaSetup(allocator: std.mem.Allocator) error{ OutOfMemory, PathNotFound }!std.fs.Dir { + fn findInstancesDirViaSetup(gpa: Allocator, io: Io) error{ OutOfMemory, PathNotFound }!Dir { const vs_setup_key_path = "SOFTWARE\\Microsoft\\VisualStudio\\Setup"; const vs_setup_key = RegistryWtf8.openKey(windows.HKEY_LOCAL_MACHINE, vs_setup_key_path, .{}) catch |err| switch (err) { error.KeyNotFound => return error.PathNotFound, }; defer vs_setup_key.closeKey(); - const packages_path = vs_setup_key.getString(allocator, "", "CachePath") catch |err| switch (err) { + const packages_path = vs_setup_key.getString(gpa, "", "CachePath") catch |err| switch (err) { error.NotAString, error.ValueNameNotFound, error.StringNotFound, @@ -614,24 +631,24 @@ const MsvcLibDir = struct { error.OutOfMemory => return error.OutOfMemory, }; - defer allocator.free(packages_path); + defer gpa.free(packages_path); - if (!std.fs.path.isAbsolute(packages_path)) return error.PathNotFound; + if (!Dir.path.isAbsolute(packages_path)) return error.PathNotFound; - const instances_path = try std.fs.path.join(allocator, &.{ packages_path, "_Instances" }); - defer allocator.free(instances_path); + const instances_path = try Dir.path.join(gpa, &.{ packages_path, "_Instances" }); + defer gpa.free(instances_path); - return std.fs.openDirAbsolute(instances_path, .{ .iterate = true }) catch return error.PathNotFound; + return Dir.openDirAbsolute(io, instances_path, .{ .iterate = true }) catch return error.PathNotFound; } - fn findInstancesDirViaCLSID(allocator: std.mem.Allocator) error{ OutOfMemory, PathNotFound }!std.fs.Dir { + fn findInstancesDirViaCLSID(gpa: Allocator, io: Io) error{ OutOfMemory, PathNotFound }!Dir { const setup_configuration_clsid = "{177f0c4a-1cd3-4de7-a32c-71dbbb9fa36d}"; const setup_config_key = RegistryWtf8.openKey(windows.HKEY_CLASSES_ROOT, "CLSID\\" ++ setup_configuration_clsid, .{}) catch |err| switch (err) { error.KeyNotFound => return error.PathNotFound, }; defer setup_config_key.closeKey(); - const dll_path = setup_config_key.getString(allocator, "InprocServer32", "") catch |err| switch (err) { + const dll_path = setup_config_key.getString(gpa, "InprocServer32", "") catch |err| switch (err) { error.NotAString, error.ValueNameNotFound, error.StringNotFound, @@ -639,11 +656,11 @@ const MsvcLibDir = struct { error.OutOfMemory => return error.OutOfMemory, }; - defer allocator.free(dll_path); + defer gpa.free(dll_path); - if (!std.fs.path.isAbsolute(dll_path)) return error.PathNotFound; + if (!Dir.path.isAbsolute(dll_path)) return error.PathNotFound; - var path_it = std.fs.path.componentIterator(dll_path); + var path_it = Dir.path.componentIterator(dll_path); // the .dll filename _ = path_it.last(); const root_path = while (path_it.previous()) |dir_component| { @@ -654,17 +671,21 @@ const MsvcLibDir = struct { return error.PathNotFound; }; - const instances_path = try std.fs.path.join(allocator, &.{ root_path, "Packages", "_Instances" }); - defer allocator.free(instances_path); + const instances_path = try Dir.path.join(gpa, &.{ root_path, "Packages", "_Instances" }); + defer gpa.free(instances_path); - return std.fs.openDirAbsolute(instances_path, .{ .iterate = true }) catch return error.PathNotFound; + return Dir.openDirAbsolute(io, instances_path, .{ .iterate = true }) catch return error.PathNotFound; } - fn findInstancesDir(allocator: std.mem.Allocator) error{ OutOfMemory, PathNotFound }!std.fs.Dir { + fn findInstancesDir( + gpa: Allocator, + io: Io, + environ_map: *const Environ.Map, + ) error{ OutOfMemory, PathNotFound }!Dir { // First, try getting the packages cache path from the registry. // This only seems to exist when the path is different from the default. method1: { - return findInstancesDirViaSetup(allocator) catch |err| switch (err) { + return findInstancesDirViaSetup(gpa, io) catch |err| switch (err) { error.OutOfMemory => |e| return e, error.PathNotFound => break :method1, }; @@ -672,7 +693,7 @@ const MsvcLibDir = struct { // Otherwise, try to get the path from the .dll that would have been // loaded via COM for SetupConfiguration. method2: { - return findInstancesDirViaCLSID(allocator) catch |err| switch (err) { + return findInstancesDirViaCLSID(gpa, io) catch |err| switch (err) { error.OutOfMemory => |e| return e, error.PathNotFound => break :method2, }; @@ -680,19 +701,16 @@ const MsvcLibDir = struct { // If that can't be found, fall back to manually appending // `Microsoft\VisualStudio\Packages\_Instances` to %PROGRAMDATA% method3: { - const program_data = std.process.getEnvVarOwned(allocator, "PROGRAMDATA") catch |err| switch (err) { - error.OutOfMemory => |e| return e, - error.InvalidWtf8 => unreachable, - error.EnvironmentVariableNotFound => break :method3, - }; - defer allocator.free(program_data); + const program_data = std.zig.EnvVar.PROGRAMDATA.get(environ_map) orelse break :method3; - if (!std.fs.path.isAbsolute(program_data)) break :method3; + if (!Dir.path.isAbsolute(program_data)) break :method3; - const instances_path = try std.fs.path.join(allocator, &.{ program_data, "Microsoft", "VisualStudio", "Packages", "_Instances" }); - defer allocator.free(instances_path); + const instances_path = try Dir.path.join(gpa, &.{ + program_data, "Microsoft", "VisualStudio", "Packages", "_Instances", + }); + defer gpa.free(instances_path); - return std.fs.openDirAbsolute(instances_path, .{ .iterate = true }) catch break :method3; + return Dir.openDirAbsolute(io, instances_path, .{ .iterate = true }) catch break :method3; } return error.PathNotFound; } @@ -743,33 +761,38 @@ const MsvcLibDir = struct { /// /// The logic in this function is intended to match what ISetupConfiguration does /// under-the-hood, as verified using Procmon. - fn findViaCOM(allocator: std.mem.Allocator, arch: std.Target.Cpu.Arch) error{ OutOfMemory, PathNotFound }![]const u8 { + fn findViaCOM( + gpa: Allocator, + io: Io, + arch: std.Target.Cpu.Arch, + environ_map: *const Environ.Map, + ) error{ OutOfMemory, PathNotFound }![]const u8 { // Typically `%PROGRAMDATA%\Microsoft\VisualStudio\Packages\_Instances` // This will contain directories with names of instance IDs like 80a758ca, // which will contain `state.json` files that have the version and // installation directory. - var instances_dir = try findInstancesDir(allocator); - defer instances_dir.close(); + var instances_dir = try findInstancesDir(gpa, io, environ_map); + defer instances_dir.close(io); - var state_subpath_buf: [std.fs.max_name_bytes + 32]u8 = undefined; + var state_subpath_buf: [Dir.max_name_bytes + 32]u8 = undefined; var latest_version_lib_dir: std.ArrayList(u8) = .empty; - errdefer latest_version_lib_dir.deinit(allocator); + errdefer latest_version_lib_dir.deinit(gpa); var latest_version: u64 = 0; var instances_dir_it = instances_dir.iterateAssumeFirstIteration(); - while (instances_dir_it.next() catch return error.PathNotFound) |entry| { + while (instances_dir_it.next(io) catch return error.PathNotFound) |entry| { if (entry.kind != .directory) continue; var writer: Writer = .fixed(&state_subpath_buf); writer.writeAll(entry.name) catch unreachable; - writer.writeByte(std.fs.path.sep) catch unreachable; + writer.writeByte(Dir.path.sep) catch unreachable; writer.writeAll("state.json") catch unreachable; - const json_contents = instances_dir.readFileAlloc(writer.buffered(), allocator, .limited(std.math.maxInt(usize))) catch continue; - defer allocator.free(json_contents); + const json_contents = instances_dir.readFileAlloc(io, writer.buffered(), gpa, .limited(std.math.maxInt(usize))) catch continue; + defer gpa.free(json_contents); - var parsed = std.json.parseFromSlice(std.json.Value, allocator, json_contents, .{}) catch continue; + var parsed = std.json.parseFromSlice(std.json.Value, gpa, json_contents, .{}) catch continue; defer parsed.deinit(); if (parsed.value != .object) continue; @@ -786,35 +809,40 @@ const MsvcLibDir = struct { const installation_path = parsed.value.object.get("installationPath") orelse continue; if (installation_path != .string) continue; - const lib_dir_path = libDirFromInstallationPath(allocator, installation_path.string, arch) catch |err| switch (err) { + const lib_dir_path = libDirFromInstallationPath(gpa, io, installation_path.string, arch) catch |err| switch (err) { error.OutOfMemory => |e| return e, error.PathNotFound => continue, }; - defer allocator.free(lib_dir_path); + defer gpa.free(lib_dir_path); latest_version_lib_dir.clearRetainingCapacity(); - try latest_version_lib_dir.appendSlice(allocator, lib_dir_path); + try latest_version_lib_dir.appendSlice(gpa, lib_dir_path); latest_version = parsed_version; } if (latest_version_lib_dir.items.len == 0) return error.PathNotFound; - return latest_version_lib_dir.toOwnedSlice(allocator); + return latest_version_lib_dir.toOwnedSlice(gpa); } - fn libDirFromInstallationPath(allocator: std.mem.Allocator, installation_path: []const u8, arch: std.Target.Cpu.Arch) error{ OutOfMemory, PathNotFound }![]const u8 { - var lib_dir_buf = try std.array_list.Managed(u8).initCapacity(allocator, installation_path.len + 64); + fn libDirFromInstallationPath( + gpa: Allocator, + io: Io, + installation_path: []const u8, + arch: std.Target.Cpu.Arch, + ) error{ OutOfMemory, PathNotFound }![]const u8 { + var lib_dir_buf = try std.array_list.Managed(u8).initCapacity(gpa, installation_path.len + 64); errdefer lib_dir_buf.deinit(); lib_dir_buf.appendSliceAssumeCapacity(installation_path); - if (!std.fs.path.isSep(lib_dir_buf.getLast())) { + if (!Dir.path.isSep(lib_dir_buf.getLast())) { try lib_dir_buf.append('\\'); } const installation_path_with_trailing_sep_len = lib_dir_buf.items.len; try lib_dir_buf.appendSlice("VC\\Auxiliary\\Build\\Microsoft.VCToolsVersion.default.txt"); var default_tools_version_buf: [512]u8 = undefined; - const default_tools_version_contents = std.fs.cwd().readFile(lib_dir_buf.items, &default_tools_version_buf) catch { + const default_tools_version_contents = Dir.cwd().readFile(io, lib_dir_buf.items, &default_tools_version_buf) catch { return error.PathNotFound; }; var tokenizer = std.mem.tokenizeAny(u8, default_tools_version_contents, " \r\n"); @@ -832,7 +860,7 @@ const MsvcLibDir = struct { else => unreachable, }); - if (!verifyLibDir(lib_dir_buf.items)) { + if (!verifyLibDir(io, lib_dir_buf.items)) { return error.PathNotFound; } @@ -840,64 +868,72 @@ const MsvcLibDir = struct { } // https://learn.microsoft.com/en-us/visualstudio/install/tools-for-managing-visual-studio-instances?view=vs-2022#editing-the-registry-for-a-visual-studio-instance - fn findViaRegistry(allocator: std.mem.Allocator, arch: std.Target.Cpu.Arch) error{ OutOfMemory, PathNotFound }![]const u8 { + fn findViaRegistry( + gpa: Allocator, + io: Io, + arch: std.Target.Cpu.Arch, + environ_map: *const Environ.Map, + ) error{ OutOfMemory, PathNotFound }![]const u8 { // %localappdata%\Microsoft\VisualStudio\ // %appdata%\Local\Microsoft\VisualStudio\ - const visualstudio_folder_path = std.fs.getAppDataDir(allocator, "Microsoft\\VisualStudio\\") catch return error.PathNotFound; - defer allocator.free(visualstudio_folder_path); + const local_app_data_path = std.zig.EnvVar.LOCALAPPDATA.get(environ_map) orelse return error.PathNotFound; + const visualstudio_folder_path = try Dir.path.join(gpa, &.{ + local_app_data_path, "Microsoft\\VisualStudio\\", + }); + defer gpa.free(visualstudio_folder_path); const vs_versions: []const []const u8 = vs_versions: { - if (!std.fs.path.isAbsolute(visualstudio_folder_path)) return error.PathNotFound; + if (!Dir.path.isAbsolute(visualstudio_folder_path)) return error.PathNotFound; // enumerate folders that contain `privateregistry.bin`, looking for all versions // f.i. %localappdata%\Microsoft\VisualStudio\17.0_9e9cbb98\ - var visualstudio_folder = std.fs.openDirAbsolute(visualstudio_folder_path, .{ + var visualstudio_folder = Dir.openDirAbsolute(io, visualstudio_folder_path, .{ .iterate = true, }) catch return error.PathNotFound; - defer visualstudio_folder.close(); + defer visualstudio_folder.close(io); var iterator = visualstudio_folder.iterate(); - break :vs_versions try iterateAndFilterByVersion(&iterator, allocator, ""); + break :vs_versions try iterateAndFilterByVersion(&iterator, gpa, io, ""); }; defer { - for (vs_versions) |vs_version| allocator.free(vs_version); - allocator.free(vs_versions); + for (vs_versions) |vs_version| gpa.free(vs_version); + gpa.free(vs_versions); } var config_subkey_buf: [RegistryWtf16Le.key_name_max_len * 2]u8 = undefined; const source_directories: []const u8 = source_directories: for (vs_versions) |vs_version| { - const privateregistry_absolute_path = std.fs.path.join(allocator, &.{ visualstudio_folder_path, vs_version, "privateregistry.bin" }) catch continue; - defer allocator.free(privateregistry_absolute_path); - if (!std.fs.path.isAbsolute(privateregistry_absolute_path)) continue; + const privateregistry_absolute_path = Dir.path.join(gpa, &.{ visualstudio_folder_path, vs_version, "privateregistry.bin" }) catch continue; + defer gpa.free(privateregistry_absolute_path); + if (!Dir.path.isAbsolute(privateregistry_absolute_path)) continue; const visualstudio_registry = RegistryWtf8.loadFromPath(privateregistry_absolute_path) catch continue; defer visualstudio_registry.closeKey(); const config_subkey = std.fmt.bufPrint(config_subkey_buf[0..], "Software\\Microsoft\\VisualStudio\\{s}_Config", .{vs_version}) catch unreachable; - const source_directories_value = visualstudio_registry.getString(allocator, config_subkey, "Source Directories") catch |err| switch (err) { + const source_directories_value = visualstudio_registry.getString(gpa, config_subkey, "Source Directories") catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, else => continue, }; - if (source_directories_value.len > (std.fs.max_path_bytes * 30)) { // note(bratishkaerik): guessing from the fact that on my computer it has 15 paths and at least some of them are not of max length - allocator.free(source_directories_value); + if (source_directories_value.len > (Dir.max_path_bytes * 30)) { // note(bratishkaerik): guessing from the fact that on my computer it has 15 paths and at least some of them are not of max length + gpa.free(source_directories_value); continue; } break :source_directories source_directories_value; } else return error.PathNotFound; - defer allocator.free(source_directories); + defer gpa.free(source_directories); var source_directories_split = std.mem.splitScalar(u8, source_directories, ';'); const msvc_dir: []const u8 = msvc_dir: { - const msvc_include_dir_maybe_with_trailing_slash = try allocator.dupe(u8, source_directories_split.first()); + const msvc_include_dir_maybe_with_trailing_slash = try gpa.dupe(u8, source_directories_split.first()); - if (msvc_include_dir_maybe_with_trailing_slash.len > std.fs.max_path_bytes or !std.fs.path.isAbsolute(msvc_include_dir_maybe_with_trailing_slash)) { - allocator.free(msvc_include_dir_maybe_with_trailing_slash); + if (msvc_include_dir_maybe_with_trailing_slash.len > Dir.max_path_bytes or !Dir.path.isAbsolute(msvc_include_dir_maybe_with_trailing_slash)) { + gpa.free(msvc_include_dir_maybe_with_trailing_slash); return error.PathNotFound; } - var msvc_dir = std.array_list.Managed(u8).fromOwnedSlice(allocator, msvc_include_dir_maybe_with_trailing_slash); + var msvc_dir = std.array_list.Managed(u8).fromOwnedSlice(gpa, msvc_include_dir_maybe_with_trailing_slash); errdefer msvc_dir.deinit(); // String might contain trailing slash, so trim it here @@ -919,28 +955,27 @@ const MsvcLibDir = struct { const msvc_dir_with_arch = try msvc_dir.toOwnedSlice(); break :msvc_dir msvc_dir_with_arch; }; - errdefer allocator.free(msvc_dir); + errdefer gpa.free(msvc_dir); - if (!verifyLibDir(msvc_dir)) { + if (!verifyLibDir(io, msvc_dir)) { return error.PathNotFound; } return msvc_dir; } - fn findViaVs7Key(allocator: std.mem.Allocator, arch: std.Target.Cpu.Arch) error{ OutOfMemory, PathNotFound }![]const u8 { + fn findViaVs7Key( + gpa: Allocator, + io: Io, + arch: std.Target.Cpu.Arch, + environ_map: *const Environ.Map, + ) error{ OutOfMemory, PathNotFound }![]const u8 { var base_path: std.array_list.Managed(u8) = base_path: { try_env: { - var env_map = std.process.getEnvMap(allocator) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - else => break :try_env, - }; - defer env_map.deinit(); - - if (env_map.get("VS140COMNTOOLS")) |VS140COMNTOOLS| { + if (environ_map.get("VS140COMNTOOLS")) |VS140COMNTOOLS| { if (VS140COMNTOOLS.len < "C:\\Common7\\Tools".len) break :try_env; - if (!std.fs.path.isAbsolute(VS140COMNTOOLS)) break :try_env; - var list = std.array_list.Managed(u8).init(allocator); + if (!Dir.path.isAbsolute(VS140COMNTOOLS)) break :try_env; + var list = std.array_list.Managed(u8).init(gpa); errdefer list.deinit(); try list.appendSlice(VS140COMNTOOLS); // C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools @@ -954,17 +989,17 @@ const MsvcLibDir = struct { const vs7_key = RegistryWtf8.openKey(windows.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VS7", .{ .wow64_32 = true }) catch return error.PathNotFound; defer vs7_key.closeKey(); try_vs7_key: { - const path_maybe_with_trailing_slash = vs7_key.getString(allocator, "", "14.0") catch |err| switch (err) { + const path_maybe_with_trailing_slash = vs7_key.getString(gpa, "", "14.0") catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, else => break :try_vs7_key, }; - if (path_maybe_with_trailing_slash.len > std.fs.max_path_bytes or !std.fs.path.isAbsolute(path_maybe_with_trailing_slash)) { - allocator.free(path_maybe_with_trailing_slash); + if (path_maybe_with_trailing_slash.len > Dir.max_path_bytes or !Dir.path.isAbsolute(path_maybe_with_trailing_slash)) { + gpa.free(path_maybe_with_trailing_slash); break :try_vs7_key; } - var path = std.array_list.Managed(u8).fromOwnedSlice(allocator, path_maybe_with_trailing_slash); + var path = std.array_list.Managed(u8).fromOwnedSlice(gpa, path_maybe_with_trailing_slash); errdefer path.deinit(); // String might contain trailing slash, so trim it here @@ -984,7 +1019,7 @@ const MsvcLibDir = struct { else => unreachable, }); - if (!verifyLibDir(base_path.items)) { + if (!verifyLibDir(io, base_path.items)) { return error.PathNotFound; } @@ -992,13 +1027,13 @@ const MsvcLibDir = struct { return full_path; } - fn verifyLibDir(lib_dir_path: []const u8) bool { - std.debug.assert(std.fs.path.isAbsolute(lib_dir_path)); // should be already handled in `findVia*` + fn verifyLibDir(io: Io, lib_dir_path: []const u8) bool { + std.debug.assert(Dir.path.isAbsolute(lib_dir_path)); // should be already handled in `findVia*` - var dir = std.fs.openDirAbsolute(lib_dir_path, .{}) catch return false; - defer dir.close(); + var dir = Dir.openDirAbsolute(io, lib_dir_path, .{}) catch return false; + defer dir.close(io); - const stat = dir.statFile("vcruntime.lib") catch return false; + const stat = dir.statFile(io, "vcruntime.lib", .{}) catch return false; if (stat.kind != .file) return false; @@ -1007,18 +1042,23 @@ const MsvcLibDir = struct { /// Find path to MSVC's `lib/` directory. /// Caller owns the result. - pub fn find(allocator: std.mem.Allocator, arch: std.Target.Cpu.Arch) error{ OutOfMemory, MsvcLibDirNotFound }![]const u8 { - const full_path = MsvcLibDir.findViaCOM(allocator, arch) catch |err1| switch (err1) { + pub fn find( + gpa: Allocator, + io: Io, + arch: std.Target.Cpu.Arch, + environ_map: *const Environ.Map, + ) error{ OutOfMemory, MsvcLibDirNotFound }![]const u8 { + const full_path = MsvcLibDir.findViaCOM(gpa, io, arch, environ_map) catch |err1| switch (err1) { error.OutOfMemory => return error.OutOfMemory, - error.PathNotFound => MsvcLibDir.findViaRegistry(allocator, arch) catch |err2| switch (err2) { + error.PathNotFound => MsvcLibDir.findViaRegistry(gpa, io, arch, environ_map) catch |err2| switch (err2) { error.OutOfMemory => return error.OutOfMemory, - error.PathNotFound => MsvcLibDir.findViaVs7Key(allocator, arch) catch |err3| switch (err3) { + error.PathNotFound => MsvcLibDir.findViaVs7Key(gpa, io, arch, environ_map) catch |err3| switch (err3) { error.OutOfMemory => return error.OutOfMemory, error.PathNotFound => return error.MsvcLibDirNotFound, }, }, }; - errdefer allocator.free(full_path); + errdefer gpa.free(full_path); return full_path; } diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig index 08770def8d0f..37ce7b4cfa12 100644 --- a/lib/std/zig/Zir.zig +++ b/lib/std/zig/Zir.zig @@ -11,9 +11,11 @@ //! * In the future, possibly inline assembly, which needs to get parsed and //! handled by the codegen backend, and errors reported there. However for now, //! inline assembly is not an exception. +const Zir = @This(); +const builtin = @import("builtin"); const std = @import("std"); -const builtin = @import("builtin"); +const Io = std.Io; const mem = std.mem; const Allocator = std.mem.Allocator; const assert = std.debug.assert; @@ -21,8 +23,6 @@ const BigIntConst = std.math.big.int.Const; const BigIntMutable = std.math.big.int.Mutable; const Ast = std.zig.Ast; -const Zir = @This(); - instructions: std.MultiArrayList(Inst).Slice, /// In order to store references to strings in fewer bytes, we copy all /// string bytes into here. String bytes can be null. It is up to whomever @@ -45,7 +45,7 @@ pub const Header = extern struct { /// it's essentially free to have a zero field here and makes the warning go away, /// making it more likely that following Valgrind warnings will be taken seriously. unused: u32 = 0, - stat_inode: std.fs.File.INode, + stat_inode: Io.File.INode, stat_size: u64, stat_mtime: i128, }; @@ -120,7 +120,7 @@ pub const NullTerminatedString = enum(u32) { /// Given an index into `string_bytes` returns the null-terminated string found there. pub fn nullTerminatedString(code: Zir, index: NullTerminatedString) [:0]const u8 { const slice = code.string_bytes[@intFromEnum(index)..]; - return slice[0..std.mem.indexOfScalar(u8, slice, 0).? :0]; + return slice[0..std.mem.findScalar(u8, slice, 0).? :0]; } pub fn refSlice(code: Zir, start: usize, len: usize) []Inst.Ref { diff --git a/lib/std/zig/Zoir.zig b/lib/std/zig/Zoir.zig index 11fe07a4e684..d82b8f1861f3 100644 --- a/lib/std/zig/Zoir.zig +++ b/lib/std/zig/Zoir.zig @@ -1,6 +1,13 @@ //! Zig Object Intermediate Representation. //! Simplified AST for the ZON (Zig Object Notation) format. //! `ZonGen` converts `Ast` to `Zoir`. +const Zoir = @This(); + +const std = @import("std"); +const Io = std.Io; +const assert = std.debug.assert; +const Allocator = std.mem.Allocator; +const Ast = std.zig.Ast; nodes: std.MultiArrayList(Node.Repr).Slice, extra: []u32, @@ -25,7 +32,7 @@ pub const Header = extern struct { /// making it more likely that following Valgrind warnings will be taken seriously. unused: u64 = 0, - stat_inode: std.fs.File.INode, + stat_inode: Io.File.INode, stat_size: u64, stat_mtime: i128, @@ -221,7 +228,7 @@ pub const Node = union(enum) { pub const NullTerminatedString = enum(u32) { _, pub fn get(nts: NullTerminatedString, zoir: Zoir) [:0]const u8 { - const idx = std.mem.indexOfScalar(u8, zoir.string_bytes[@intFromEnum(nts)..], 0).?; + const idx = std.mem.findScalar(u8, zoir.string_bytes[@intFromEnum(nts)..], 0).?; return zoir.string_bytes[@intFromEnum(nts)..][0..idx :0]; } }; @@ -254,9 +261,3 @@ pub const CompileError = extern struct { assert(std.meta.hasUniqueRepresentation(Note)); } }; - -const std = @import("std"); -const assert = std.debug.assert; -const Allocator = std.mem.Allocator; -const Ast = std.zig.Ast; -const Zoir = @This(); diff --git a/lib/std/zig/ZonGen.zig b/lib/std/zig/ZonGen.zig index 0137f8491163..4d4cfcad9fd3 100644 --- a/lib/std/zig/ZonGen.zig +++ b/lib/std/zig/ZonGen.zig @@ -238,7 +238,7 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator => try zg.addErrorNode(node, "control flow is not allowed in ZON", .{}), .@"comptime" => try zg.addErrorNode(node, "keyword 'comptime' is not allowed in ZON", .{}), - .asm_simple, .@"asm", .asm_legacy => try zg.addErrorNode(node, "inline asm is not allowed in ZON", .{}), + .asm_simple, .@"asm" => try zg.addErrorNode(node, "inline asm is not allowed in ZON", .{}), .builtin_call_two, .builtin_call_two_comma, @@ -487,7 +487,7 @@ fn appendIdentStr(zg: *ZonGen, ident_token: Ast.TokenIndex) error{ OutOfMemory, } const slice = zg.string_bytes.items[start..]; - if (mem.indexOfScalar(u8, slice, 0) != null) { + if (mem.findScalar(u8, slice, 0) != null) { try zg.addErrorTok(ident_token, "identifier cannot contain null bytes", .{}); return error.BadString; } else if (slice.len == 0) { @@ -586,7 +586,7 @@ fn strLitAsString(zg: *ZonGen, str_node: Ast.Node.Index) error{ OutOfMemory, Bad }, } const key: []const u8 = string_bytes.items[str_index..]; - if (std.mem.indexOfScalar(u8, key, 0) != null) return .{ .slice = .{ + if (std.mem.findScalar(u8, key, 0) != null) return .{ .slice = .{ .start = str_index, .len = @intCast(key.len), } }; @@ -785,7 +785,7 @@ fn lowerStrLitError( } fn lowerNumberError(zg: *ZonGen, err: std.zig.number_literal.Error, token: Ast.TokenIndex, bytes: []const u8) Allocator.Error!void { - const is_float = std.mem.indexOfScalar(u8, bytes, '.') != null; + const is_float = std.mem.findScalar(u8, bytes, '.') != null; switch (err) { .leading_zero => if (is_float) { try zg.addErrorTok(token, "number '{s}' has leading zero", .{bytes}); diff --git a/lib/std/zig/c_translation/helpers.zig b/lib/std/zig/c_translation/helpers.zig index 7d3534bffea7..a1c4c41ee936 100644 --- a/lib/std/zig/c_translation/helpers.zig +++ b/lib/std/zig/c_translation/helpers.zig @@ -115,7 +115,7 @@ fn PromoteIntLiteralReturnType(comptime SuffixType: type, comptime number: compt else &signed_oct_hex; - var pos = std.mem.indexOfScalar(type, list, SuffixType).?; + var pos = std.mem.findScalar(type, list, SuffixType).?; while (pos < list.len) : (pos += 1) { if (number >= std.math.minInt(list[pos]) and number <= std.math.maxInt(list[pos])) { return list[pos]; diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig index 587ac82c70ff..66d20df34810 100644 --- a/lib/std/zig/llvm/Builder.zig +++ b/lib/std/zig/llvm/Builder.zig @@ -1,14 +1,17 @@ +const builtin = @import("builtin"); +const Builder = @This(); + const std = @import("../../std.zig"); +const Io = std.Io; const Allocator = std.mem.Allocator; const assert = std.debug.assert; -const bitcode_writer = @import("bitcode_writer.zig"); -const Builder = @This(); -const builtin = @import("builtin"); const DW = std.dwarf; -const ir = @import("ir.zig"); const log = std.log.scoped(.llvm); const Writer = std.Io.Writer; +const bitcode_writer = @import("bitcode_writer.zig"); +const ir = @import("ir.zig"); + gpa: Allocator, strip: bool, @@ -9573,21 +9576,21 @@ pub fn asmValue( return (try self.asmConst(ty, info, assembly, constraints)).toValue(); } -pub fn dump(b: *Builder) void { +pub fn dump(b: *Builder, io: Io) void { var buffer: [4000]u8 = undefined; - const stderr: std.fs.File = .stderr(); - b.printToFile(stderr, &buffer) catch {}; + const stderr: Io.File = .stderr(); + b.printToFile(io, stderr, &buffer) catch {}; } -pub fn printToFilePath(b: *Builder, dir: std.fs.Dir, path: []const u8) !void { +pub fn printToFilePath(b: *Builder, io: Io, dir: Io.Dir, path: []const u8) !void { var buffer: [4000]u8 = undefined; - const file = try dir.createFile(path, .{}); - defer file.close(); - try b.printToFile(file, &buffer); + const file = try dir.createFile(io, path, .{}); + defer file.close(io); + try b.printToFile(io, file, &buffer); } -pub fn printToFile(b: *Builder, file: std.fs.File, buffer: []u8) !void { - var fw = file.writer(buffer); +pub fn printToFile(b: *Builder, io: Io, file: Io.File, buffer: []u8) !void { + var fw = file.writer(io, buffer); try print(b, &fw.interface); try fw.interface.flush(); } diff --git a/lib/std/zig/llvm/bitcode_writer.zig b/lib/std/zig/llvm/bitcode_writer.zig index 77102a8a7c45..3d3246b8971a 100644 --- a/lib/std/zig/llvm/bitcode_writer.zig +++ b/lib/std/zig/llvm/bitcode_writer.zig @@ -26,7 +26,7 @@ pub fn BitcodeWriter(comptime types: []const type) type { widths: [types.len]u16, pub fn getTypeWidth(self: BcWriter, comptime Type: type) u16 { - return self.widths[comptime std.mem.indexOfScalar(type, types, Type).?]; + return self.widths[comptime std.mem.findScalar(type, types, Type).?]; } pub fn init(allocator: std.mem.Allocator, widths: [types.len]u16) BcWriter { diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index b563fa90e33c..1f1195633006 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -1,7 +1,6 @@ const std = @import("std"); -const mem = std.mem; -const print = std.debug.print; -const maxInt = std.math.maxInt; +const Io = std.Io; +const Allocator = std.mem.Allocator; test "zig fmt: remove extra whitespace at start and end of file with comment between" { try testTransform( @@ -31,54 +30,16 @@ test "zig fmt: tuple struct" { } test "zig fmt: preserves clobbers in inline asm with stray comma" { - try testTransform( - \\fn foo() void { - \\ asm volatile ("" - \\ : [_] "" (-> type), - \\ : - \\ : "clobber" - \\ ); - \\ asm volatile ("" - \\ : - \\ : [_] "" (type), - \\ : "clobber" - \\ ); - \\} - \\ - , + try testCanonical( \\fn foo() void { \\ asm volatile ("" \\ : [_] "" (-> type), \\ : - \\ : .{ .clobber = true } - \\ ); + \\ : .{ .clobber = true }); \\ asm volatile ("" \\ : \\ : [_] "" (type), - \\ : .{ .clobber = true } - \\ ); - \\} - \\ - ); -} - -test "zig fmt: remove trailing comma at the end of assembly clobber" { - try testTransform( - \\fn foo() void { - \\ asm volatile ("" - \\ : [_] "" (-> type), - \\ : - \\ : "clobber1", "clobber2", - \\ ); - \\} - \\ - , - \\fn foo() void { - \\ asm volatile ("" - \\ : [_] "" (-> type), - \\ : - \\ : .{ .clobber1 = true, .clobber2 = true } - \\ ); + \\ : .{ .clobber = true }); \\} \\ ); @@ -641,27 +602,7 @@ test "zig fmt: builtin call with trailing comma" { } test "zig fmt: asm expression with comptime content" { - try testTransform( - \\comptime { - \\ asm ("foo" ++ "bar"); - \\} - \\pub fn main() void { - \\ asm volatile ("foo" ++ "bar"); - \\ asm volatile ("foo" ++ "bar" - \\ : [_] "" (x), - \\ ); - \\ asm volatile ("foo" ++ "bar" - \\ : [_] "" (x), - \\ : [_] "" (y), - \\ ); - \\ asm volatile ("foo" ++ "bar" - \\ : [_] "" (x), - \\ : [_] "" (y), - \\ : "h", "e", "l", "l", "o" - \\ ); - \\} - \\ - , + try testCanonical( \\comptime { \\ asm ("foo" ++ "bar"); \\} @@ -677,8 +618,7 @@ test "zig fmt: asm expression with comptime content" { \\ asm volatile ("foo" ++ "bar" \\ : [_] "" (x), \\ : [_] "" (y), - \\ : .{ .h = true, .e = true, .l = true, .l = true, .o = true } - \\ ); + \\ : .{ .h = true, .e = true, .l = true, .l = true, .o = true }); \\} \\ ); @@ -728,7 +668,6 @@ test "zig fmt: pointer-to-many with modifiers" { try testCanonical( \\const x: [*]u32 = undefined; \\const y: [*]allowzero align(8) addrspace(.generic) const volatile u32 = undefined; - \\const z: [*]allowzero align(8:4:2) addrspace(.generic) const volatile u32 = undefined; \\ ); } @@ -737,7 +676,6 @@ test "zig fmt: sentinel pointer with modifiers" { try testCanonical( \\const x: [*:42]u32 = undefined; \\const y: [*:42]allowzero align(8) addrspace(.generic) const volatile u32 = undefined; - \\const y: [*:42]allowzero align(8:4:2) addrspace(.generic) const volatile u32 = undefined; \\ ); } @@ -746,7 +684,6 @@ test "zig fmt: c pointer with modifiers" { try testCanonical( \\const x: [*c]u32 = undefined; \\const y: [*c]allowzero align(8) addrspace(.generic) const volatile u32 = undefined; - \\const z: [*c]allowzero align(8:4:2) addrspace(.generic) const volatile u32 = undefined; \\ ); } @@ -2198,7 +2135,7 @@ test "zig fmt: simple asm" { \\ asm ("not real assembly" \\ :[a] "x" (->i32),:[a] "x" (1),); \\ asm ("still not real assembly" - \\ :::"a","b",); + \\ :::.{.a=true,.b=true}); \\} , \\comptime { @@ -3940,24 +3877,13 @@ test "zig fmt: fn type" { } test "zig fmt: inline asm" { - try testTransform( - \\pub fn syscall1(number: usize, arg1: usize) usize { - \\ return asm volatile ("syscall" - \\ : [ret] "={rax}" (-> usize), - \\ : [number] "{rax}" (number), - \\ [arg1] "{rdi}" (arg1), - \\ : "rcx", "r11" - \\ ); - \\} - \\ - , + try testCanonical( \\pub fn syscall1(number: usize, arg1: usize) usize { \\ return asm volatile ("syscall" \\ : [ret] "={rax}" (-> usize), \\ : [number] "{rax}" (number), \\ [arg1] "{rdi}" (arg1), - \\ : .{ .rcx = true, .r11 = true } - \\ ); + \\ : .{ .rcx = true, .r11 = true }); \\} \\ ); @@ -4609,7 +4535,7 @@ test "zig fmt: Only indent multiline string literals in function calls" { test "zig fmt: Don't add extra newline after if" { try testCanonical( \\pub fn atomicSymLink(allocator: Allocator, existing_path: []const u8, new_path: []const u8) !void { - \\ if (cwd().symLink(existing_path, new_path, .{})) { + \\ if (foo().bar(existing_path, new_path, .{})) { \\ return; \\ } \\} @@ -5789,8 +5715,7 @@ test "zig fmt: canonicalize symbols (asm)" { \\ [@"arg1"] "{rdi}" (arg), \\ [arg2] "{rsi}" (arg), \\ [arg3] "{rdx}" (arg), - \\ : "rcx", "fn" - \\ ); + \\ : .{ .rcx = true, .@"fn" = true }); \\ \\ const @"false": usize = 10; \\ const @"true" = "explode"; @@ -5811,8 +5736,7 @@ test "zig fmt: canonicalize symbols (asm)" { \\ [arg1] "{rdi}" (arg), \\ [arg2] "{rsi}" (arg), \\ [arg3] "{rdx}" (arg), - \\ : .{ .rcx = true, .@"fn" = true } - \\ ); + \\ : .{ .rcx = true, .@"fn" = true }); \\ \\ const @"false": usize = 10; \\ const @"true" = "explode"; @@ -5890,6 +5814,16 @@ test "zig fmt: error for missing sentinel value in sentinel slice" { } test "zig fmt: error for invalid bit range" { + try testError( + \\var x: [*]align(0:0:0)u8 = bar; + , &[_]Error{ + .invalid_bit_range, + }); + try testError( + \\var x: [*c]align(0:0:0)u8 = bar; + , &[_]Error{ + .invalid_bit_range, + }); try testError( \\var x: []align(0:0:0)u8 = bar; , &[_]Error{ @@ -6084,6 +6018,16 @@ test "zig fmt: do not canonicalize invalid cast builtins" { ); } +test "zig fmt: extern addrspace in struct" { + try testCanonical( + \\const namespace = struct { + \\ extern const num: u8 addrspace(.generic); + \\}; + \\// comment + \\ + ); +} + test "recovery: top level" { try testError( \\test "" {inline} @@ -6394,54 +6338,64 @@ test "ampersand" { var fixed_buffer_mem: [100 * 1024]u8 = undefined; -fn testParse(source: [:0]const u8, allocator: mem.Allocator, anything_changed: *bool) ![]u8 { +fn testParse(io: Io, source: [:0]const u8, allocator: Allocator, anything_changed: *bool) ![]u8 { var buffer: [64]u8 = undefined; - const stderr, _ = std.debug.lockStderrWriter(&buffer); - defer std.debug.unlockStderrWriter(); + const stderr = try io.lockStderr(&buffer, null); + defer io.unlockStderr(); + const writer = &stderr.file_writer.interface; var tree = try std.zig.Ast.parse(allocator, source, .zig); defer tree.deinit(allocator); for (tree.errors) |parse_error| { const loc = tree.tokenLocation(0, parse_error.token); - try stderr.print("(memory buffer):{d}:{d}: error: ", .{ loc.line + 1, loc.column + 1 }); - try tree.renderError(parse_error, stderr); - try stderr.print("\n{s}\n", .{source[loc.line_start..loc.line_end]}); + try writer.print("(memory buffer):{d}:{d}: error: ", .{ loc.line + 1, loc.column + 1 }); + try tree.renderError(parse_error, writer); + try writer.print("\n{s}\n", .{source[loc.line_start..loc.line_end]}); { var i: usize = 0; while (i < loc.column) : (i += 1) { - try stderr.writeAll(" "); + try writer.writeAll(" "); } - try stderr.writeAll("^"); + try writer.writeAll("^"); } - try stderr.writeAll("\n"); + try writer.writeAll("\n"); } if (tree.errors.len != 0) { return error.ParseError; } const formatted = try tree.renderAlloc(allocator); - anything_changed.* = !mem.eql(u8, formatted, source); + anything_changed.* = !std.mem.eql(u8, formatted, source); return formatted; } -fn testTransformImpl(allocator: mem.Allocator, fba: *std.heap.FixedBufferAllocator, source: [:0]const u8, expected_source: []const u8) !void { +fn testTransformImpl( + allocator: Allocator, + fba: *std.heap.FixedBufferAllocator, + io: Io, + source: [:0]const u8, + expected_source: []const u8, +) !void { // reset the fixed buffer allocator each run so that it can be re-used for each // iteration of the failing index fba.reset(); var anything_changed: bool = undefined; - const result_source = try testParse(source, allocator, &anything_changed); + const result_source = try testParse(io, source, allocator, &anything_changed); try std.testing.expectEqualStrings(expected_source, result_source); const changes_expected = source.ptr != expected_source.ptr; if (anything_changed != changes_expected) { - print("std.zig.render returned {} instead of {}\n", .{ anything_changed, changes_expected }); + std.debug.print("std.zig.render returned {} instead of {}\n", .{ anything_changed, changes_expected }); return error.TestFailed; } try std.testing.expect(anything_changed == changes_expected); allocator.free(result_source); } fn testTransform(source: [:0]const u8, expected_source: []const u8) !void { + const io = std.testing.io; var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]); - return std.testing.checkAllAllocationFailures(fixed_allocator.allocator(), testTransformImpl, .{ &fixed_allocator, source, expected_source }); + return std.testing.checkAllAllocationFailures(fixed_allocator.allocator(), testTransformImpl, .{ + &fixed_allocator, io, source, expected_source, + }); } fn testCanonical(source: [:0]const u8) !void { return testTransform(source, source); diff --git a/lib/std/zig/perf_test.zig b/lib/std/zig/perf_test.zig index 1566a15d2dc1..da3dd42f15fc 100644 --- a/lib/std/zig/perf_test.zig +++ b/lib/std/zig/perf_test.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const mem = std.mem; const Tokenizer = std.zig.Tokenizer; const fmtIntSizeBin = std.fmt.fmtIntSizeBin; @@ -22,7 +23,7 @@ pub fn main() !void { const bytes_per_sec = @as(u64, @intFromFloat(@floor(bytes_per_sec_float))); var stdout_buffer: [1024]u8 = undefined; - var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); + var stdout_writer = Io.File.stdout().writer(&stdout_buffer); const stdout = &stdout_writer.interface; try stdout.print("parsing speed: {Bi:.2}/s, {Bi:.2} used \n", .{ bytes_per_sec, memory_used }); try stdout.flush(); diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index 77bdaf5837da..45e777bb9396 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -1,11 +1,12 @@ const builtin = @import("builtin"); +const native_endian = builtin.cpu.arch.endian(); + const std = @import("../std.zig"); const mem = std.mem; const elf = std.elf; const fs = std.fs; const assert = std.debug.assert; const Target = std.Target; -const native_endian = builtin.cpu.arch.endian(); const posix = std.posix; const Io = std.Io; @@ -39,6 +40,7 @@ pub const GetExternalExecutorOptions = struct { /// Return whether or not the given host is capable of running executables of /// the other target. pub fn getExternalExecutor( + io: Io, host: *const std.Target, candidate: *const std.Target, options: GetExternalExecutorOptions, @@ -69,7 +71,7 @@ pub fn getExternalExecutor( if (os_match and cpu_ok) native: { if (options.link_libc) { if (candidate.dynamic_linker.get()) |candidate_dl| { - fs.cwd().access(candidate_dl, .{}) catch { + Io.Dir.cwd().access(io, candidate_dl, .{}) catch { bad_result = .{ .bad_dl = candidate_dl }; break :native; }; @@ -209,7 +211,8 @@ pub const DetectError = error{ DeviceBusy, OSVersionDetectionFail, Unexpected, - ProcessNotFound, + /// Android-only. Querying API level through `getprop` failed. + ApiLevelQueryFailed, } || Io.Cancelable; /// Given a `Target.Query`, which specifies in detail which parts of the @@ -247,7 +250,7 @@ pub fn resolveTargetQuery(io: Io, query: Target.Query) DetectError!Target { os.version_range.windows.min = detected_version; os.version_range.windows.max = detected_version; }, - .macos => try darwin.macos.detect(&os), + .macos => try darwin.macos.detect(io, &os), .freebsd, .netbsd, .dragonfly => { const key = switch (builtin.target.os.tag) { .freebsd => "kern.osreldate", @@ -322,7 +325,7 @@ pub fn resolveTargetQuery(io: Io, query: Target.Query) DetectError!Target { error.Unexpected => return error.OSVersionDetectionFail, }; - if (Target.Query.parseVersion(buf[0..len :0])) |ver| { + if (Target.Query.parseVersion(buf[0 .. len - 1 :0])) |ver| { assert(ver.build == null); assert(ver.pre == null); os.version_range.semver.min = ver; @@ -422,7 +425,6 @@ pub fn resolveTargetQuery(io: Io, query: Target.Query) DetectError!Target { error.SocketUnconnected => return error.Unexpected, error.AccessDenied, - error.ProcessNotFound, error.SymLinkLoop, error.ProcessFdQuotaExceeded, error.SystemFdQuotaExceeded, @@ -500,6 +502,28 @@ pub fn resolveTargetQuery(io: Io, query: Target.Query) DetectError!Target { } } + if (builtin.os.tag == .linux and result.isBionicLibC() and query.os_tag == null and query.android_api_level == null) { + result.os.version_range.linux.android = detectAndroidApiLevel(io) catch |err| return switch (err) { + error.InvalidWtf8, + error.CurrentWorkingDirectoryUnlinked, + error.InvalidBatchScriptArg, + => unreachable, // Windows-only + error.ApiLevelQueryFailed => |e| e, + else => blk: { + std.log.err("spawning or reading from getprop failed ({s})", .{@errorName(err)}); + switch (err) { + error.SystemResources, + error.FileSystem, + error.ProcessFdQuotaExceeded, + error.SystemFdQuotaExceeded, + error.SymLinkLoop, + => |e| break :blk e, + else => break :blk error.ApiLevelQueryFailed, + } + }, + }; + } + return result; } @@ -553,7 +577,6 @@ pub const AbiAndDynamicLinkerFromFileError = error{ SystemResources, ProcessFdQuotaExceeded, SystemFdQuotaExceeded, - ProcessNotFound, IsDir, WouldBlock, InputOutput, @@ -693,8 +716,10 @@ fn abiAndDynamicLinkerFromFile( // So far, no luck. Next we try to see if the information is // present in the symlink data for the dynamic linker path. - var link_buf: [posix.PATH_MAX]u8 = undefined; - const link_name = posix.readlink(dl_path, &link_buf) catch |err| switch (err) { + var link_buffer: [posix.PATH_MAX]u8 = undefined; + const link_name = if (Io.Dir.readLinkAbsolute(io, dl_path, &link_buffer)) |n| + link_buffer[0..n] + else |err| switch (err) { error.NameTooLong => unreachable, error.BadPathName => unreachable, // Windows only error.UnsupportedReparsePointType => unreachable, // Windows only @@ -711,6 +736,7 @@ fn abiAndDynamicLinkerFromFile( error.SystemResources, error.FileSystem, error.SymLinkLoop, + error.Canceled, error.Unexpected, => |e| return e, }; @@ -786,10 +812,11 @@ test glibcVerFromLinkName { } fn glibcVerFromRPath(io: Io, rpath: []const u8) !std.SemanticVersion { - var dir = fs.cwd().openDir(rpath, .{}) catch |err| switch (err) { + const cwd: Io.Dir = .cwd(); + + var dir = cwd.openDir(io, rpath, .{}) catch |err| switch (err) { error.NameTooLong => return error.Unexpected, error.BadPathName => return error.Unexpected, - error.DeviceBusy => return error.Unexpected, error.NetworkNotFound => return error.Unexpected, // Windows-only error.FileNotFound => return error.GLibCNotFound, @@ -805,7 +832,7 @@ fn glibcVerFromRPath(io: Io, rpath: []const u8) !std.SemanticVersion { error.Unexpected => |e| return e, error.Canceled => |e| return e, }; - defer dir.close(); + defer dir.close(io); // Now we have a candidate for the path to libc shared object. In // the past, we used readlink() here because the link name would @@ -815,14 +842,14 @@ fn glibcVerFromRPath(io: Io, rpath: []const u8) !std.SemanticVersion { // .dynstr section, and finding the max version number of symbols // that start with "GLIBC_2.". const glibc_so_basename = "libc.so.6"; - var file = dir.openFile(glibc_so_basename, .{}) catch |err| switch (err) { + var file = dir.openFile(io, glibc_so_basename, .{}) catch |err| switch (err) { error.NameTooLong => return error.Unexpected, error.BadPathName => return error.Unexpected, error.PipeBusy => return error.Unexpected, // Windows-only error.SharingViolation => return error.Unexpected, // Windows-only error.NetworkNotFound => return error.Unexpected, // Windows-only error.AntivirusInterference => return error.Unexpected, // Windows-only - error.FileLocksNotSupported => return error.Unexpected, // No lock requested. + error.FileLocksUnsupported => return error.Unexpected, // No lock requested. error.NoSpaceLeft => return error.Unexpected, // read-only error.PathAlreadyExists => return error.Unexpected, // read-only error.DeviceBusy => return error.Unexpected, // read-only @@ -837,7 +864,6 @@ fn glibcVerFromRPath(io: Io, rpath: []const u8) !std.SemanticVersion { error.NotDir => return error.GLibCNotFound, error.IsDir => return error.GLibCNotFound, - error.ProcessNotFound => |e| return e, error.ProcessFdQuotaExceeded => |e| return e, error.SystemFdQuotaExceeded => |e| return e, error.SystemResources => |e| return e, @@ -845,11 +871,11 @@ fn glibcVerFromRPath(io: Io, rpath: []const u8) !std.SemanticVersion { error.Unexpected => |e| return e, error.Canceled => |e| return e, }; - defer file.close(); + defer file.close(io); // Empirically, glibc 2.34 libc.so .dynstr section is 32441 bytes on my system. var buffer: [8000]u8 = undefined; - var file_reader: Io.File.Reader = .initAdapted(file, io, &buffer); + var file_reader: Io.File.Reader = .init(file, io, &buffer); return glibcVerFromSoFile(&file_reader) catch |err| switch (err) { error.InvalidElfMagic, @@ -1024,14 +1050,14 @@ fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Targ }; while (true) { - const file = fs.openFileAbsolute(file_name, .{}) catch |err| switch (err) { + const file = Io.Dir.openFileAbsolute(io, file_name, .{}) catch |err| switch (err) { error.NoSpaceLeft => return error.Unexpected, error.NameTooLong => return error.Unexpected, error.PathAlreadyExists => return error.Unexpected, error.SharingViolation => return error.Unexpected, error.BadPathName => return error.Unexpected, error.PipeBusy => return error.Unexpected, - error.FileLocksNotSupported => return error.Unexpected, + error.FileLocksUnsupported => return error.Unexpected, error.FileBusy => return error.Unexpected, // opened without write permissions error.AntivirusInterference => return error.Unexpected, // Windows-only error @@ -1044,14 +1070,17 @@ fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Targ error.NetworkNotFound, error.FileTooBig, error.Unexpected, - => return error.UnableToOpenElfFile, - + => |e| if (e == error.FileNotFound and os.tag == .linux and mem.eql(u8, file_name, "/usr/bin/env")) { + // Android does not have a /usr directory, so try again + file_name = "/system/bin/env"; + continue; + } else return error.UnableToOpenElfFile, else => |e| return e, }; var is_elf_file = false; - defer if (!is_elf_file) file.close(); + defer if (!is_elf_file) file.close(io); - file_reader = .initAdapted(file, io, &file_reader_buffer); + file_reader = .init(file, io, &file_reader_buffer); file_name = undefined; // it aliases file_reader_buffer const header = elf.Header.read(&file_reader.interface) catch |hdr_err| switch (hdr_err) { @@ -1076,7 +1105,7 @@ fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Targ const path_maybe_args = mem.trimEnd(u8, trimmed_line, "\n"); // Separate path and args. - const path_end = mem.indexOfAny(u8, path_maybe_args, &.{ ' ', '\t', 0 }) orelse path_maybe_args.len; + const path_end = mem.findAny(u8, path_maybe_args, &.{ ' ', '\t', 0 }) orelse path_maybe_args.len; const unvalidated_path = path_maybe_args[0..path_end]; file_name = if (fs.path.isAbsolute(unvalidated_path)) unvalidated_path else return error.RelativeShebang; continue; @@ -1101,7 +1130,6 @@ fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Targ error.SymLinkLoop, error.ProcessFdQuotaExceeded, error.SystemFdQuotaExceeded, - error.ProcessNotFound, error.Canceled, => |e| return e, @@ -1130,6 +1158,41 @@ const LdInfo = struct { abi: Target.Abi, }; +fn detectAndroidApiLevel(io: Io) !u32 { + comptime if (builtin.os.tag != .linux) unreachable; + + var child = try std.process.spawn(io, .{ + .argv = &.{ + "/system/bin/getprop", + "ro.build.version.sdk", + }, + .stdin = .ignore, + .stdout = .pipe, + .stderr = .ignore, + }); + errdefer child.kill(io); + + // PROP_VALUE_MAX is 92, output is value + newline. + // Currently API levels are two-digit numbers, but we want to make sure we never read a partial value. + var stdout_buf: [92 + 1]u8 = undefined; + var reader = child.stdout.?.readerStreaming(io, &.{}); + const n = try reader.interface.readSliceShort(&stdout_buf); + const api_level = std.fmt.parseInt(u32, stdout_buf[0 .. n - 1], 10) catch |e| { + std.log.err( + "Could not parse API level, unexpected getprop output '{s}' ({s})", + .{ stdout_buf[0 .. n - 1], @errorName(e) }, + ); + return error.ApiLevelQueryFailed; + }; + + const term = try child.wait(io); + if (term != .exited or term.exited != 0) { + std.log.err("getprop terminated abnormally: {}", .{term}); + return error.ApiLevelQueryFailed; + } + return api_level; +} + test { _ = NativePaths; diff --git a/lib/std/zig/system/NativePaths.zig b/lib/std/zig/system/NativePaths.zig index 70b72b0581c3..f8003cd62061 100644 --- a/lib/std/zig/system/NativePaths.zig +++ b/lib/std/zig/system/NativePaths.zig @@ -1,11 +1,12 @@ -const std = @import("../../std.zig"); +const NativePaths = @This(); const builtin = @import("builtin"); + +const std = @import("../../std.zig"); +const Io = std.Io; const Allocator = std.mem.Allocator; const process = std.process; const mem = std.mem; -const NativePaths = @This(); - arena: Allocator, include_dirs: std.ArrayList([]const u8) = .empty, lib_dirs: std.ArrayList([]const u8) = .empty, @@ -13,17 +14,23 @@ framework_dirs: std.ArrayList([]const u8) = .empty, rpaths: std.ArrayList([]const u8) = .empty, warnings: std.ArrayList([]const u8) = .empty, -pub fn detect(arena: Allocator, native_target: *const std.Target) !NativePaths { +pub fn detect( + arena: Allocator, + io: Io, + native_target: *const std.Target, + environ_map: *process.Environ.Map, +) !NativePaths { var self: NativePaths = .{ .arena = arena }; var is_nix = false; - if (process.getEnvVarOwned(arena, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| { + + if (std.zig.EnvVar.NIX_CFLAGS_COMPILE.get(environ_map)) |nix_cflags_compile| { is_nix = true; var it = mem.tokenizeScalar(u8, nix_cflags_compile, ' '); while (true) { const word = it.next() orelse break; - if (mem.eql(u8, word, "-isystem")) { + if (mem.eql(u8, word, "-isystem") or mem.eql(u8, word, "-idirafter")) { const include_path = it.next() orelse { - try self.addWarning("Expected argument after -isystem in NIX_CFLAGS_COMPILE"); + try self.addWarningFmt("Expected argument after {s} in NIX_CFLAGS_COMPILE", .{word}); break; }; try self.addIncludeDir(include_path); @@ -40,12 +47,9 @@ pub fn detect(arena: Allocator, native_target: *const std.Target) !NativePaths { try self.addWarningFmt("Unrecognized C flag from NIX_CFLAGS_COMPILE: {s}", .{word}); } } - } else |err| switch (err) { - error.InvalidWtf8 => unreachable, - error.EnvironmentVariableNotFound => {}, - error.OutOfMemory => |e| return e, } - if (process.getEnvVarOwned(arena, "NIX_LDFLAGS")) |nix_ldflags| { + + if (std.zig.EnvVar.NIX_LDFLAGS.get(environ_map)) |nix_ldflags| { is_nix = true; var it = mem.tokenizeScalar(u8, nix_ldflags, ' '); while (true) { @@ -65,33 +69,59 @@ pub fn detect(arena: Allocator, native_target: *const std.Target) !NativePaths { const lib_path = word[2..]; try self.addLibDir(lib_path); try self.addRPath(lib_path); - } else if (mem.startsWith(u8, word, "-l")) { + } else if (mem.startsWith(u8, word, "-l") or mem.startsWith(u8, word, "-static")) { // Ignore this argument. } else { try self.addWarningFmt("Unrecognized C flag from NIX_LDFLAGS: {s}", .{word}); break; } } - } else |err| switch (err) { - error.InvalidWtf8 => unreachable, - error.EnvironmentVariableNotFound => {}, - error.OutOfMemory => |e| return e, } + + if (std.zig.EnvVar.NIX_CFLAGS_LINK.get(environ_map)) |nix_cflags_link| { + is_nix = true; + var it = mem.tokenizeScalar(u8, nix_cflags_link, ' '); + while (true) { + const word = it.next() orelse break; + if (mem.eql(u8, word, "-rpath")) { + const rpath = it.next() orelse { + try self.addWarning("Expected argument after -rpath in NIX_CFLAGS_LINK"); + break; + }; + try self.addRPath(rpath); + } else if (mem.eql(u8, word, "-L") or mem.eql(u8, word, "-l")) { + _ = it.next() orelse { + try self.addWarning("Expected argument after -L or -l in NIX_CFLAGS_LINK"); + break; + }; + } else if (mem.startsWith(u8, word, "-L")) { + const lib_path = word[2..]; + try self.addLibDir(lib_path); + try self.addRPath(lib_path); + } else if (mem.startsWith(u8, word, "-l") or mem.startsWith(u8, word, "-static")) { + // Ignore this argument. + } else { + try self.addWarningFmt("Unrecognized C flag from NIX_CFLAGS_LINK: {s}", .{word}); + break; + } + } + } + if (is_nix) { return self; } // TODO: consider also adding macports paths if (builtin.target.os.tag.isDarwin()) { - if (std.zig.system.darwin.isSdkInstalled(arena)) sdk: { - const sdk = std.zig.system.darwin.getSdk(arena, native_target) orelse break :sdk; + if (std.zig.system.darwin.isSdkInstalled(arena, io)) sdk: { + const sdk = std.zig.system.darwin.getSdk(arena, io, native_target) orelse break :sdk; try self.addLibDir(try std.fs.path.join(arena, &.{ sdk, "usr/lib" })); try self.addFrameworkDir(try std.fs.path.join(arena, &.{ sdk, "System/Library/Frameworks" })); try self.addIncludeDir(try std.fs.path.join(arena, &.{ sdk, "usr/include" })); } // Check for homebrew paths - if (std.posix.getenv("HOMEBREW_PREFIX")) |prefix| { + if (std.zig.EnvVar.HOMEBREW_PREFIX.get(environ_map)) |prefix| { try self.addLibDir(try std.fs.path.join(arena, &.{ prefix, "/lib" })); try self.addIncludeDir(try std.fs.path.join(arena, &.{ prefix, "/include" })); } @@ -147,23 +177,21 @@ pub fn detect(arena: Allocator, native_target: *const std.Target) !NativePaths { // Distros like guix don't use FHS, so they rely on environment // variables to search for headers and libraries. - // We use os.getenv here since this part won't be executed on - // windows, to get rid of unnecessary error handling. - if (std.posix.getenv("C_INCLUDE_PATH")) |c_include_path| { + if (std.zig.EnvVar.C_INCLUDE_PATH.get(environ_map)) |c_include_path| { var it = mem.tokenizeScalar(u8, c_include_path, ':'); while (it.next()) |dir| { try self.addIncludeDir(dir); } } - if (std.posix.getenv("CPLUS_INCLUDE_PATH")) |cplus_include_path| { + if (std.zig.EnvVar.CPLUS_INCLUDE_PATH.get(environ_map)) |cplus_include_path| { var it = mem.tokenizeScalar(u8, cplus_include_path, ':'); while (it.next()) |dir| { try self.addIncludeDir(dir); } } - if (std.posix.getenv("LIBRARY_PATH")) |library_path| { + if (std.zig.EnvVar.LIBRARY_PATH.get(environ_map)) |library_path| { var it = mem.tokenizeScalar(u8, library_path, ':'); while (it.next()) |dir| { try self.addLibDir(dir); diff --git a/lib/std/zig/system/darwin.zig b/lib/std/zig/system/darwin.zig index fbd6da2a9ef6..b31dc484ceb3 100644 --- a/lib/std/zig/system/darwin.zig +++ b/lib/std/zig/system/darwin.zig @@ -1,30 +1,31 @@ const std = @import("std"); +const Io = std.Io; const mem = std.mem; -const Allocator = mem.Allocator; +const Allocator = std.mem.Allocator; const Target = std.Target; const Version = std.SemanticVersion; pub const macos = @import("darwin/macos.zig"); /// Check if SDK is installed on Darwin without triggering CLT installation popup window. -/// Note: simply invoking `xcrun` will inevitably trigger the CLT installation popup. +/// +/// Simply invoking `xcrun` will inevitably trigger the CLT installation popup. /// Therefore, we resort to invoking `xcode-select --print-path` and checking /// if the status is nonzero. +/// /// stderr from xcode-select is ignored. +/// /// If error.OutOfMemory occurs in Allocator, this function returns null. -pub fn isSdkInstalled(allocator: Allocator) bool { - const result = std.process.Child.run(.{ - .allocator = allocator, +pub fn isSdkInstalled(gpa: Allocator, io: Io) bool { + const result = std.process.run(gpa, io, .{ .argv = &.{ "xcode-select", "--print-path" }, }) catch return false; - defer { - allocator.free(result.stderr); - allocator.free(result.stdout); + gpa.free(result.stderr); + gpa.free(result.stdout); } - return switch (result.term) { - .Exited => |code| if (code == 0) result.stdout.len > 0 else false, + .exited => |code| if (code == 0) result.stdout.len > 0 else false, else => false, }; } @@ -34,7 +35,7 @@ pub fn isSdkInstalled(allocator: Allocator) bool { /// Caller owns the memory. /// stderr from xcrun is ignored. /// If error.OutOfMemory occurs in Allocator, this function returns null. -pub fn getSdk(allocator: Allocator, target: *const Target) ?[]const u8 { +pub fn getSdk(gpa: Allocator, io: Io, target: *const Target) ?[]const u8 { const is_simulator_abi = target.abi == .simulator; const sdk = switch (target.os.tag) { .driverkit => "driverkit", @@ -46,16 +47,16 @@ pub fn getSdk(allocator: Allocator, target: *const Target) ?[]const u8 { else => return null, }; const argv = &[_][]const u8{ "xcrun", "--sdk", sdk, "--show-sdk-path" }; - const result = std.process.Child.run(.{ .allocator = allocator, .argv = argv }) catch return null; + const result = std.process.run(gpa, io, .{ .argv = argv }) catch return null; defer { - allocator.free(result.stderr); - allocator.free(result.stdout); + gpa.free(result.stderr); + gpa.free(result.stdout); } switch (result.term) { - .Exited => |code| if (code != 0) return null, + .exited => |code| if (code != 0) return null, else => return null, } - return allocator.dupe(u8, mem.trimEnd(u8, result.stdout, "\r\n")) catch null; + return gpa.dupe(u8, mem.trimEnd(u8, result.stdout, "\r\n")) catch null; } test { diff --git a/lib/std/zig/system/darwin/macos.zig b/lib/std/zig/system/darwin/macos.zig index 9bb4e34e3bc3..7d80c2b588e6 100644 --- a/lib/std/zig/system/darwin/macos.zig +++ b/lib/std/zig/system/darwin/macos.zig @@ -1,14 +1,15 @@ -const std = @import("std"); const builtin = @import("builtin"); + +const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; const mem = std.mem; const testing = std.testing; - const Target = std.Target; /// Detect macOS version. /// `target_os` is not modified in case of error. -pub fn detect(target_os: *Target.Os) !void { +pub fn detect(io: Io, target_os: *Target.Os) !void { // Drop use of osproductversion sysctl because: // 1. only available 10.13.4 High Sierra and later // 2. when used from a binary built against < SDK 11.0 it returns 10.16 and masks Big Sur 11.x version @@ -54,7 +55,7 @@ pub fn detect(target_os: *Target.Os) !void { // approx. 4 times historical file size var buf: [2048]u8 = undefined; - if (std.fs.cwd().readFile(path, &buf)) |bytes| { + if (Io.Dir.cwd().readFile(io, path, &buf)) |bytes| { if (parseSystemVersion(bytes)) |ver| { // never return non-canonical `10.(16+)` if (!(ver.major == 10 and ver.minor >= 16)) { diff --git a/lib/std/zig/system/linux.zig b/lib/std/zig/system/linux.zig index d800f355efb7..60f4d7bfec86 100644 --- a/lib/std/zig/system/linux.zig +++ b/lib/std/zig/system/linux.zig @@ -35,7 +35,7 @@ const SparcCpuinfoImpl = struct { fn line_hook(self: *SparcCpuinfoImpl, key: []const u8, value: []const u8) !bool { if (mem.eql(u8, key, "cpu")) { inline for (cpu_names) |pair| { - if (mem.indexOfPos(u8, value, 0, pair[0]) != null) { + if (mem.findPos(u8, value, 0, pair[0]) != null) { self.model = pair[1]; break; } @@ -147,7 +147,7 @@ const PowerpcCpuinfoImpl = struct { // The model name is often followed by a comma or space and extra // info. inline for (cpu_names) |pair| { - const end_index = mem.indexOfAny(u8, value, ", ") orelse value.len; + const end_index = mem.findAny(u8, value, ", ") orelse value.len; if (mem.eql(u8, value[0..end_index], pair[0])) { self.model = pair[1]; break; @@ -318,7 +318,7 @@ const ArmCpuinfoImpl = struct { self.have_fields += 1; } else if (mem.eql(u8, key, "model name")) { // ARMv6 cores report "CPU architecture" equal to 7. - if (mem.indexOf(u8, value, "(v6l)")) |_| { + if (mem.find(u8, value, "(v6l)")) |_| { info.is_really_v6 = true; } } else if (mem.eql(u8, key, "CPU revision")) { @@ -427,7 +427,7 @@ fn CpuinfoParser(comptime impl: anytype) type { fn parse(arch: Target.Cpu.Arch, reader: *Io.Reader) !?Target.Cpu { var obj: impl = .{}; while (try reader.takeDelimiter('\n')) |line| { - const colon_pos = mem.indexOfScalar(u8, line, ':') orelse continue; + const colon_pos = mem.findScalar(u8, line, ':') orelse continue; const key = mem.trimEnd(u8, line[0..colon_pos], " \t"); const value = mem.trimStart(u8, line[colon_pos + 1 ..], " \t"); if (!try obj.line_hook(key, value)) break; @@ -444,10 +444,10 @@ inline fn getAArch64CpuFeature(comptime feat_reg: []const u8) u64 { } pub fn detectNativeCpuAndFeatures(io: Io) ?Target.Cpu { - var file = fs.openFileAbsolute("/proc/cpuinfo", .{}) catch |err| switch (err) { + var file = Io.Dir.openFileAbsolute(io, "/proc/cpuinfo", .{}) catch |err| switch (err) { else => return null, }; - defer file.close(); + defer file.close(io); var buffer: [4096]u8 = undefined; // "flags" lines can get pretty long. var file_reader = file.reader(io, &buffer); diff --git a/lib/std/zig/target.zig b/lib/std/zig/target.zig index d1d39948c4af..9f1aeb2310ac 100644 --- a/lib/std/zig/target.zig +++ b/lib/std/zig/target.zig @@ -20,6 +20,7 @@ pub const available_libcs = [_]ArchOsAbi{ .{ .arch = .arm, .os = .linux, .abi = .musleabihf, .os_ver = .{ .major = 2, .minor = 1, .patch = 0 } }, .{ .arch = .arm, .os = .netbsd, .abi = .eabi, .os_ver = .{ .major = 1, .minor = 2, .patch = 0 } }, .{ .arch = .arm, .os = .netbsd, .abi = .eabihf, .os_ver = .{ .major = 1, .minor = 2, .patch = 0 } }, + .{ .arch = .arm, .os = .openbsd, .abi = .eabi, .os_ver = .{ .major = 6, .minor = 1, .patch = 0 } }, .{ .arch = .armeb, .os = .linux, .abi = .gnueabi, .os_ver = .{ .major = 2, .minor = 6, .patch = 0 } }, .{ .arch = .armeb, .os = .linux, .abi = .gnueabihf, .os_ver = .{ .major = 2, .minor = 6, .patch = 0 } }, .{ .arch = .armeb, .os = .linux, .abi = .musleabi, .os_ver = .{ .major = 2, .minor = 6, .patch = 0 } }, @@ -37,6 +38,7 @@ pub const available_libcs = [_]ArchOsAbi{ .{ .arch = .aarch64, .os = .maccatalyst, .abi = .none, .os_ver = .{ .major = 11, .minor = 0, .patch = 0 } }, .{ .arch = .aarch64, .os = .macos, .abi = .none, .os_ver = .{ .major = 11, .minor = 0, .patch = 0 } }, .{ .arch = .aarch64, .os = .netbsd, .abi = .none, .os_ver = .{ .major = 9, .minor = 0, .patch = 0 } }, + .{ .arch = .aarch64, .os = .openbsd, .abi = .none, .os_ver = .{ .major = 6, .minor = 1, .patch = 0 } }, .{ .arch = .aarch64, .os = .windows, .abi = .gnu }, .{ .arch = .aarch64_be, .os = .linux, .abi = .gnu, .os_ver = .{ .major = 3, .minor = 13, .patch = 0 }, .glibc_min = .{ .major = 2, .minor = 17, .patch = 0 } }, .{ .arch = .aarch64_be, .os = .linux, .abi = .musl, .os_ver = .{ .major = 3, .minor = 13, .patch = 0 } }, @@ -67,20 +69,23 @@ pub const available_libcs = [_]ArchOsAbi{ .{ .arch = .mips64, .os = .linux, .abi = .gnuabin32, .os_ver = .{ .major = 2, .minor = 6, .patch = 0 }, .glibc_triple = "mips64-linux-gnu-n32" }, .{ .arch = .mips64, .os = .linux, .abi = .muslabi64, .os_ver = .{ .major = 2, .minor = 3, .patch = 48 } }, .{ .arch = .mips64, .os = .linux, .abi = .muslabin32, .os_ver = .{ .major = 2, .minor = 6, .patch = 0 } }, + .{ .arch = .mips64, .os = .openbsd, .abi = .none, .os_ver = .{ .major = 5, .minor = 4, .patch = 0 } }, .{ .arch = .mips64el, .os = .linux, .abi = .gnuabi64, .os_ver = .{ .major = 2, .minor = 3, .patch = 48 }, .glibc_triple = "mips64el-linux-gnu-n64" }, .{ .arch = .mips64el, .os = .linux, .abi = .gnuabin32, .os_ver = .{ .major = 2, .minor = 6, .patch = 0 }, .glibc_triple = "mips64el-linux-gnu-n32" }, .{ .arch = .mips64el, .os = .linux, .abi = .muslabi64, .os_ver = .{ .major = 2, .minor = 3, .patch = 48 } }, .{ .arch = .mips64el, .os = .linux, .abi = .muslabin32, .os_ver = .{ .major = 2, .minor = 6, .patch = 0 } }, - .{ .arch = .powerpc, .os = .freebsd, .abi = .eabihf, .os_ver = .{ .major = 7, .minor = 1, .patch = 0 } }, + .{ .arch = .mips64el, .os = .openbsd, .abi = .none, .os_ver = .{ .major = 4, .minor = 7, .patch = 0 } }, .{ .arch = .powerpc, .os = .linux, .abi = .gnueabi, .os_ver = .{ .major = 1, .minor = 3, .patch = 45 }, .glibc_triple = "powerpc-linux-gnu-soft" }, .{ .arch = .powerpc, .os = .linux, .abi = .gnueabihf, .os_ver = .{ .major = 1, .minor = 3, .patch = 45 }, .glibc_triple = "powerpc-linux-gnu" }, .{ .arch = .powerpc, .os = .linux, .abi = .musleabi, .os_ver = .{ .major = 1, .minor = 3, .patch = 45 } }, .{ .arch = .powerpc, .os = .linux, .abi = .musleabihf, .os_ver = .{ .major = 1, .minor = 3, .patch = 45 } }, .{ .arch = .powerpc, .os = .netbsd, .abi = .eabi, .os_ver = .{ .major = 6, .minor = 0, .patch = 0 } }, .{ .arch = .powerpc, .os = .netbsd, .abi = .eabihf, .os_ver = .{ .major = 1, .minor = 4, .patch = 0 } }, + .{ .arch = .powerpc, .os = .openbsd, .abi = .eabihf, .os_ver = .{ .major = 2, .minor = 8, .patch = 0 } }, .{ .arch = .powerpc64, .os = .freebsd, .abi = .none, .os_ver = .{ .major = 8, .minor = 0, .patch = 0 } }, .{ .arch = .powerpc64, .os = .linux, .abi = .gnu, .os_ver = .{ .major = 2, .minor = 6, .patch = 0 } }, .{ .arch = .powerpc64, .os = .linux, .abi = .musl, .os_ver = .{ .major = 2, .minor = 6, .patch = 0 } }, + .{ .arch = .powerpc64, .os = .openbsd, .abi = .none, .os_ver = .{ .major = 6, .minor = 8, .patch = 0 } }, .{ .arch = .powerpc64le, .os = .freebsd, .abi = .none, .os_ver = .{ .major = 13, .minor = 0, .patch = 0 } }, .{ .arch = .powerpc64le, .os = .linux, .abi = .gnu, .os_ver = .{ .major = 3, .minor = 14, .patch = 0 }, .glibc_min = .{ .major = 2, .minor = 19, .patch = 0 } }, .{ .arch = .powerpc64le, .os = .linux, .abi = .musl, .os_ver = .{ .major = 3, .minor = 14, .patch = 0 } }, @@ -89,17 +94,20 @@ pub const available_libcs = [_]ArchOsAbi{ .{ .arch = .riscv64, .os = .freebsd, .abi = .none, .os_ver = .{ .major = 12, .minor = 0, .patch = 0 } }, .{ .arch = .riscv64, .os = .linux, .abi = .gnu, .os_ver = .{ .major = 4, .minor = 15, .patch = 0 }, .glibc_min = .{ .major = 2, .minor = 27, .patch = 0 }, .glibc_triple = "riscv64-linux-gnu-rv64imafdc-lp64d" }, .{ .arch = .riscv64, .os = .linux, .abi = .musl, .os_ver = .{ .major = 4, .minor = 15, .patch = 0 } }, + .{ .arch = .riscv64, .os = .openbsd, .abi = .none, .os_ver = .{ .major = 7, .minor = 0, .patch = 0 } }, .{ .arch = .s390x, .os = .linux, .abi = .gnu, .os_ver = .{ .major = 2, .minor = 4, .patch = 2 } }, .{ .arch = .s390x, .os = .linux, .abi = .musl, .os_ver = .{ .major = 2, .minor = 4, .patch = 2 } }, .{ .arch = .sparc, .os = .linux, .abi = .gnu, .os_ver = .{ .major = 2, .minor = 1, .patch = 19 }, .glibc_triple = "sparcv9-linux-gnu" }, .{ .arch = .sparc, .os = .netbsd, .abi = .none }, .{ .arch = .sparc64, .os = .linux, .abi = .gnu, .os_ver = .{ .major = 2, .minor = 1, .patch = 19 } }, .{ .arch = .sparc64, .os = .netbsd, .abi = .none, .os_ver = .{ .major = 1, .minor = 4, .patch = 0 } }, + .{ .arch = .sparc64, .os = .openbsd, .abi = .none, .os_ver = .{ .major = 3, .minor = 0, .patch = 0 } }, .{ .arch = .wasm32, .os = .wasi, .abi = .musl }, .{ .arch = .x86, .os = .freebsd, .abi = .none }, .{ .arch = .x86, .os = .linux, .abi = .gnu, .glibc_triple = "i686-linux-gnu" }, .{ .arch = .x86, .os = .linux, .abi = .musl }, .{ .arch = .x86, .os = .netbsd, .abi = .none }, + .{ .arch = .x86, .os = .openbsd, .abi = .none }, .{ .arch = .x86, .os = .windows, .abi = .gnu }, .{ .arch = .x86_64, .os = .freebsd, .abi = .none, .os_ver = .{ .major = 5, .minor = 1, .patch = 0 } }, .{ .arch = .x86_64, .os = .linux, .abi = .gnu, .os_ver = .{ .major = 2, .minor = 6, .patch = 4 } }, @@ -109,15 +117,10 @@ pub const available_libcs = [_]ArchOsAbi{ .{ .arch = .x86_64, .os = .maccatalyst, .abi = .none, .os_ver = .{ .major = 10, .minor = 15, .patch = 0 } }, .{ .arch = .x86_64, .os = .macos, .abi = .none, .os_ver = .{ .major = 10, .minor = 7, .patch = 0 } }, .{ .arch = .x86_64, .os = .netbsd, .abi = .none, .os_ver = .{ .major = 2, .minor = 0, .patch = 0 } }, + .{ .arch = .x86_64, .os = .openbsd, .abi = .none, .os_ver = .{ .major = 3, .minor = 5, .patch = 0 } }, .{ .arch = .x86_64, .os = .windows, .abi = .gnu }, }; -/// The version of Zig's bundled FreeBSD libc used when linking libc statically. -pub const freebsd_libc_version: std.SemanticVersion = .{ .major = 14, .minor = 0, .patch = 0 }; - -/// The version of Zig's bundled NetBSD libc used when linking libc statically. -pub const netbsd_libc_version: std.SemanticVersion = .{ .major = 10, .minor = 1, .patch = 0 }; - pub fn canBuildLibC(target: *const std.Target) bool { for (available_libcs) |libc| { if (target.cpu.arch == libc.arch and target.os.tag == libc.os and target.abi == libc.abi) { @@ -278,6 +281,12 @@ pub fn netbsdAbiNameHeaders(abi: std.Target.Abi) [:0]const u8 { }; } +pub fn openbsdArchNameHeaders(arch: std.Target.Cpu.Arch) [:0]const u8 { + return switch (arch) { + else => @tagName(arch), + }; +} + pub fn isLibCLibName(target: *const std.Target, name: []const u8) bool { const ignore_case = target.os.tag.isDarwin() or target.os.tag == .windows; @@ -436,6 +445,17 @@ pub fn isLibCLibName(target: *const std.Target, name: []const u8) bool { return true; } + if (target.isOpenBSDLibC()) { + if (eqlIgnoreCase(ignore_case, name, "execinfo")) + return true; + if (eqlIgnoreCase(ignore_case, name, "m")) + return true; + if (eqlIgnoreCase(ignore_case, name, "pthread")) + return true; + if (eqlIgnoreCase(ignore_case, name, "util")) + return true; + } + if (target.os.tag == .haiku) { if (eqlIgnoreCase(ignore_case, name, "root")) return true; diff --git a/lib/std/zip.zig b/lib/std/zip.zig index 5354362f55e7..ff95587e7a83 100644 --- a/lib/std/zip.zig +++ b/lib/std/zip.zig @@ -4,9 +4,11 @@ //! Note that this file uses the abbreviation "cd" for "central directory" const builtin = @import("builtin"); -const std = @import("std"); -const File = std.fs.File; const is_le = builtin.target.cpu.arch.endian() == .little; + +const std = @import("std"); +const Io = std.Io; +const File = std.Io.File; const Writer = std.Io.Writer; const Reader = std.Io.Reader; const flate = std.compress.flate; @@ -115,7 +117,7 @@ pub const EndRecord = extern struct { return record; } - pub const FindFileError = File.Reader.SizeError || File.SeekError || File.ReadError || error{ + pub const FindFileError = File.Reader.SizeError || File.SeekError || File.Reader.Error || error{ ZipNoEndRecord, EndOfStream, ReadFailed, @@ -460,8 +462,10 @@ pub const Iterator = struct { stream: *File.Reader, options: ExtractOptions, filename_buf: []u8, - dest: std.fs.Dir, + dest: Io.Dir, ) !void { + const io = stream.io; + if (filename_buf.len < self.filename_len) return error.ZipInsufficientBuffer; switch (self.compression_method) { @@ -539,7 +543,7 @@ pub const Iterator = struct { if (options.allow_backslashes) { std.mem.replaceScalar(u8, filename, '\\', '/'); } else { - if (std.mem.indexOfScalar(u8, filename, '\\')) |_| + if (std.mem.findScalar(u8, filename, '\\')) |_| return error.ZipFilenameHasBackslash; } @@ -550,23 +554,23 @@ pub const Iterator = struct { if (filename[filename.len - 1] == '/') { if (self.uncompressed_size != 0) return error.ZipBadDirectorySize; - try dest.makePath(filename[0 .. filename.len - 1]); + try dest.createDirPath(io, filename[0 .. filename.len - 1]); return; } const out_file = blk: { if (std.fs.path.dirname(filename)) |dirname| { - var parent_dir = try dest.makeOpenPath(dirname, .{}); - defer parent_dir.close(); + var parent_dir = try dest.createDirPathOpen(io, dirname, .{}); + defer parent_dir.close(io); const basename = std.fs.path.basename(filename); - break :blk try parent_dir.createFile(basename, .{ .exclusive = true }); + break :blk try parent_dir.createFile(io, basename, .{ .exclusive = true }); } - break :blk try dest.createFile(filename, .{ .exclusive = true }); + break :blk try dest.createFile(io, filename, .{ .exclusive = true }); }; - defer out_file.close(); + defer out_file.close(io); var out_file_buffer: [1024]u8 = undefined; - var file_writer = out_file.writer(&out_file_buffer); + var file_writer = out_file.writer(io, &out_file_buffer); const local_data_file_offset: u64 = @as(u64, self.file_offset) + @as(u64, @sizeOf(LocalFileHeader)) + @@ -626,7 +630,7 @@ pub const Diagnostics = struct { if (!self.saw_first_file) { self.saw_first_file = true; std.debug.assert(self.root_dir.len == 0); - const root_len = std.mem.indexOfScalar(u8, name, '/') orelse return; + const root_len = std.mem.findScalar(u8, name, '/') orelse return; std.debug.assert(root_len > 0); self.root_dir = try self.allocator.dupe(u8, name[0..root_len]); } else if (self.root_dir.len > 0) { @@ -647,7 +651,7 @@ pub const ExtractOptions = struct { }; /// Extract the zipped files to the given `dest` directory. -pub fn extract(dest: std.fs.Dir, fr: *File.Reader, options: ExtractOptions) !void { +pub fn extract(dest: Io.Dir, fr: *File.Reader, options: ExtractOptions) !void { if (options.verify_checksums) @panic("TODO unimplemented"); var iter = try Iterator.init(fr); diff --git a/src/Air/print.zig b/src/Air/print.zig index 95c8a1fcdacf..98b0a0b242ab 100644 --- a/src/Air/print.zig +++ b/src/Air/print.zig @@ -9,7 +9,7 @@ const Type = @import("../Type.zig"); const Air = @import("../Air.zig"); const InternPool = @import("../InternPool.zig"); -pub fn write(air: Air, stream: *std.Io.Writer, pt: Zcu.PerThread, liveness: ?Air.Liveness) void { +pub fn write(air: Air, stream: *std.Io.Writer, pt: Zcu.PerThread, liveness: ?Air.Liveness) !void { comptime assert(build_options.enable_debug_extensions); const instruction_bytes = air.instructions.len * // Here we don't use @sizeOf(Air.Inst.Data) because it would include @@ -24,7 +24,7 @@ pub fn write(air: Air, stream: *std.Io.Writer, pt: Zcu.PerThread, liveness: ?Air liveness_special_bytes + tomb_bytes; // zig fmt: off - stream.print( + try stream.print( \\# Total AIR+Liveness bytes: {Bi} \\# AIR Instructions: {d} ({Bi}) \\# AIR Extra Data: {d} ({Bi}) @@ -39,7 +39,7 @@ pub fn write(air: Air, stream: *std.Io.Writer, pt: Zcu.PerThread, liveness: ?Air tomb_bytes, if (liveness) |l| l.extra.len else 0, liveness_extra_bytes, if (liveness) |l| l.special.count() else 0, liveness_special_bytes, - }) catch return; + }); // zig fmt: on var writer: Writer = .{ @@ -50,7 +50,7 @@ pub fn write(air: Air, stream: *std.Io.Writer, pt: Zcu.PerThread, liveness: ?Air .indent = 2, .skip_body = false, }; - writer.writeBody(stream, air.getMainBody()) catch return; + try writer.writeBody(stream, air.getMainBody()); } pub fn writeInst( @@ -73,15 +73,23 @@ pub fn writeInst( } pub fn dump(air: Air, pt: Zcu.PerThread, liveness: ?Air.Liveness) void { - const stderr_bw, _ = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); - air.write(stderr_bw, pt, liveness); + const comp = pt.zcu.comp; + const io = comp.io; + var buffer: [512]u8 = undefined; + const stderr = try io.lockStderr(&buffer, null); + defer io.unlockStderr(); + const w = &stderr.file_writer.interface; + air.write(w, pt, liveness); } pub fn dumpInst(air: Air, inst: Air.Inst.Index, pt: Zcu.PerThread, liveness: ?Air.Liveness) void { - const stderr_bw, _ = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); - air.writeInst(stderr_bw, inst, pt, liveness); + const comp = pt.zcu.comp; + const io = comp.io; + var buffer: [512]u8 = undefined; + const stderr = try io.lockStderr(&buffer, null); + defer io.unlockStderr(); + const w = &stderr.file_writer.interface; + air.writeInst(w, inst, pt, liveness); } const Writer = struct { diff --git a/src/Builtin.zig b/src/Builtin.zig index b0077f2276c5..92a0e40ae3fe 100644 --- a/src/Builtin.zig +++ b/src/Builtin.zig @@ -313,8 +313,9 @@ pub fn updateFileOnDisk(file: *File, comp: *Compilation) !void { assert(file.source != null); const root_dir, const sub_path = file.path.openInfo(comp.dirs); + const io = comp.io; - if (root_dir.statFile(sub_path)) |stat| { + if (root_dir.statFile(io, sub_path, .{})) |stat| { if (stat.size != file.source.?.len) { std.log.warn( "the cached file '{f}' had the wrong size. Expected {d}, found {d}. " ++ @@ -342,10 +343,10 @@ pub fn updateFileOnDisk(file: *File, comp: *Compilation) !void { } // `make_path` matters because the dir hasn't actually been created yet. - var af = try root_dir.atomicFile(sub_path, .{ .make_path = true, .write_buffer = &.{} }); - defer af.deinit(); - try af.file_writer.interface.writeAll(file.source.?); - af.finish() catch |err| switch (err) { + var af = try root_dir.createFileAtomic(io, sub_path, .{ .make_path = true, .replace = true }); + defer af.deinit(io); + try af.file.writeStreamingAll(io, file.source.?); + af.replace(io) catch |err| switch (err) { error.AccessDenied => switch (builtin.os.tag) { .windows => { // Very likely happened due to another process or thread diff --git a/src/Compilation.zig b/src/Compilation.zig index 687525cbf381..d617f0a0e5f2 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -10,8 +10,6 @@ const Allocator = std.mem.Allocator; const assert = std.debug.assert; const log = std.log.scoped(.compilation); const Target = std.Target; -const ThreadPool = std.Thread.Pool; -const WaitGroup = std.Thread.WaitGroup; const ErrorBundle = std.zig.ErrorBundle; const fatal = std.process.fatal; @@ -29,6 +27,7 @@ const glibc = @import("libs/glibc.zig"); const musl = @import("libs/musl.zig"); const freebsd = @import("libs/freebsd.zig"); const netbsd = @import("libs/netbsd.zig"); +const openbsd = @import("libs/openbsd.zig"); const mingw = @import("libs/mingw.zig"); const libunwind = @import("libs/libunwind.zig"); const libcxx = @import("libs/libcxx.zig"); @@ -56,6 +55,8 @@ gpa: Allocator, /// threads at once. arena: Allocator, io: Io, +environ_map: *const std.process.Environ.Map, +thread_limit: usize, /// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`. zcu: ?*Zcu, /// Contains different state depending on the `CacheMode` used by this `Compilation`. @@ -110,7 +111,14 @@ win32_resource_table: if (dev.env.supports(.win32_resource)) std.AutoArrayHashMa } = .{}, link_diags: link.Diags, -link_task_queue: link.Queue = .empty, +link_queue: link.Queue = .empty, + +/// This is populated during `Compilation.create` with a set of prelink tasks which need to be +/// queued on the first update. In `update`, we will send these tasks to the linker, and clear +/// them from this list. +/// +/// Allocated into `gpa`. +oneshot_prelink_tasks: std.ArrayList(link.PrelinkTask), /// Set of work that can be represented by only flags to determine whether the /// work is queued or not. @@ -173,6 +181,7 @@ verbose_llvm_bc: ?[]const u8, verbose_cimport: bool, verbose_llvm_cpu_features: bool, verbose_link: bool, +link_depfile: ?[]const u8, disable_c_depfile: bool, stack_report: bool, debug_compiler_runtime_libs: bool, @@ -197,7 +206,6 @@ libc_include_dir_list: []const []const u8, libc_framework_dir_list: []const []const u8, rc_includes: std.zig.RcIncludes, mingw_unicode_entry_point: bool, -thread_pool: *ThreadPool, /// Populated when we build the libc++ static library. A Job to build this is placed in the queue /// and resolved before calling linker.flush(). @@ -236,6 +244,7 @@ fuzzer_lib: ?CrtFile = null, glibc_so_files: ?glibc.BuiltSharedObjects = null, freebsd_so_files: ?freebsd.BuiltSharedObjects = null, netbsd_so_files: ?netbsd.BuiltSharedObjects = null, +openbsd_so_files: ?openbsd.BuiltSharedObjects = null, /// For example `Scrt1.o` and `libc_nonshared.a`. These are populated after building libc from source, /// The set of needed CRT (C runtime) files differs depending on the target and compilation settings. @@ -247,16 +256,10 @@ crt_files: std.StringHashMapUnmanaged(CrtFile) = .empty, reference_trace: ?u32 = null, /// This mutex guards all `Compilation` mutable state. -/// Disabled in single-threaded mode because the thread pool spawns in the same thread. -mutex: if (builtin.single_threaded) struct { - pub inline fn tryLock(_: @This()) void {} - pub inline fn lock(_: @This()) void {} - pub inline fn unlock(_: @This()) void {} -} else std.Thread.Mutex = .{}, +mutex: std.Io.Mutex = .init, test_filters: []const []const u8, -link_task_wait_group: WaitGroup = .{}, link_prog_node: std.Progress.Node = .none, llvm_opt_bisect_limit: c_int, @@ -306,6 +309,7 @@ const QueuedJobs = struct { glibc_crt_file: [@typeInfo(glibc.CrtFile).@"enum".fields.len]bool = @splat(false), freebsd_crt_file: [@typeInfo(freebsd.CrtFile).@"enum".fields.len]bool = @splat(false), netbsd_crt_file: [@typeInfo(netbsd.CrtFile).@"enum".fields.len]bool = @splat(false), + openbsd_crt_file: [@typeInfo(openbsd.CrtFile).@"enum".fields.len]bool = @splat(false), /// one of WASI libc static objects wasi_libc_crt_file: [@typeInfo(wasi_libc.CrtFile).@"enum".fields.len]bool = @splat(false), /// one of the mingw-w64 static objects @@ -314,6 +318,7 @@ const QueuedJobs = struct { glibc_shared_objects: bool = false, freebsd_shared_objects: bool = false, netbsd_shared_objects: bool = false, + openbsd_shared_objects: bool = false, /// libunwind.a, usually needed when linking libc libunwind: bool = false, libcxx: bool = false, @@ -446,11 +451,11 @@ pub const Path = struct { } /// Given a `Path`, returns the directory handle and sub path to be used to open the path. - pub fn openInfo(p: Path, dirs: Directories) struct { fs.Dir, []const u8 } { + pub fn openInfo(p: Path, dirs: Directories) struct { Io.Dir, []const u8 } { const dir = switch (p.root) { .none => { const cwd_sub_path = absToCwdRelative(p.sub_path, dirs.cwd); - return .{ fs.cwd(), cwd_sub_path }; + return .{ Io.Dir.cwd(), cwd_sub_path }; }, .zig_lib => dirs.zig_lib.handle, .global_cache => dirs.global_cache.handle, @@ -721,13 +726,13 @@ pub const Directories = struct { /// This may be the same as `global_cache`. local_cache: Cache.Directory, - pub fn deinit(dirs: *Directories) void { + pub fn deinit(dirs: *Directories, io: Io) void { // The local and global caches could be the same. - const close_local = dirs.local_cache.handle.fd != dirs.global_cache.handle.fd; + const close_local = dirs.local_cache.handle.handle != dirs.global_cache.handle.handle; - dirs.global_cache.handle.close(); - if (close_local) dirs.local_cache.handle.close(); - dirs.zig_lib.handle.close(); + dirs.global_cache.handle.close(io); + if (close_local) dirs.local_cache.handle.close(io); + dirs.zig_lib.handle.close(io); } /// Returns a `Directories` where `local_cache` is replaced with `global_cache`, intended for @@ -745,6 +750,7 @@ pub const Directories = struct { /// Uses `std.process.fatal` on error conditions. pub fn init( arena: Allocator, + io: Io, override_zig_lib: ?[]const u8, override_global_cache: ?[]const u8, local_cache_strat: union(enum) { @@ -752,46 +758,44 @@ pub const Directories = struct { search, global, }, - wasi_preopens: switch (builtin.target.os.tag) { - .wasi => fs.wasi.Preopens, - else => void, - }, + preopens: std.process.Preopens, self_exe_path: switch (builtin.target.os.tag) { .wasi => void, else => []const u8, }, + environ_map: *const std.process.Environ.Map, ) Directories { const wasi = builtin.target.os.tag == .wasi; const cwd = introspect.getResolvedCwd(arena) catch |err| { - fatal("unable to get cwd: {s}", .{@errorName(err)}); + fatal("unable to get cwd: {t}", .{err}); }; const zig_lib: Cache.Directory = d: { - if (override_zig_lib) |path| break :d openUnresolved(arena, cwd, path, .@"zig lib"); - if (wasi) break :d openWasiPreopen(wasi_preopens, "/lib"); - break :d introspect.findZigLibDirFromSelfExe(arena, cwd, self_exe_path) catch |err| { - fatal("unable to find zig installation directory '{s}': {s}", .{ self_exe_path, @errorName(err) }); + if (override_zig_lib) |path| break :d openUnresolved(arena, io, cwd, path, .@"zig lib"); + if (wasi) break :d getPreopen(preopens, "/lib"); + break :d introspect.findZigLibDirFromSelfExe(arena, io, cwd, self_exe_path) catch |err| { + fatal("unable to find zig installation directory '{s}': {t}", .{ self_exe_path, err }); }; }; const global_cache: Cache.Directory = d: { - if (override_global_cache) |path| break :d openUnresolved(arena, cwd, path, .@"global cache"); - if (wasi) break :d openWasiPreopen(wasi_preopens, "/cache"); - const path = introspect.resolveGlobalCacheDir(arena) catch |err| { - fatal("unable to resolve zig cache directory: {s}", .{@errorName(err)}); + if (override_global_cache) |path| break :d openUnresolved(arena, io, cwd, path, .@"global cache"); + if (wasi) break :d getPreopen(preopens, "/cache"); + const path = introspect.resolveGlobalCacheDir(arena, environ_map) catch |err| { + fatal("unable to resolve zig cache directory: {t}", .{err}); }; - break :d openUnresolved(arena, cwd, path, .@"global cache"); + break :d openUnresolved(arena, io, cwd, path, .@"global cache"); }; const local_cache: Cache.Directory = switch (local_cache_strat) { - .override => |path| openUnresolved(arena, cwd, path, .@"local cache"), + .override => |path| openUnresolved(arena, io, cwd, path, .@"local cache"), .search => d: { - const maybe_path = introspect.resolveSuitableLocalCacheDir(arena, cwd) catch |err| { - fatal("unable to resolve zig cache directory: {s}", .{@errorName(err)}); + const maybe_path = introspect.resolveSuitableLocalCacheDir(arena, io, cwd) catch |err| { + fatal("unable to resolve zig cache directory: {t}", .{err}); }; const path = maybe_path orelse break :d global_cache; - break :d openUnresolved(arena, cwd, path, .@"local cache"); + break :d openUnresolved(arena, io, cwd, path, .@"local cache"); }, .global => global_cache, }; @@ -810,22 +814,29 @@ pub const Directories = struct { .local_cache = local_cache, }; } - fn openWasiPreopen(preopens: fs.wasi.Preopens, name: []const u8) Cache.Directory { + fn getPreopen(preopens: std.process.Preopens, name: []const u8) Cache.Directory { return .{ .path = if (std.mem.eql(u8, name, ".")) null else name, - .handle = .{ - .fd = preopens.find(name) orelse fatal("WASI preopen not found: '{s}'", .{name}), + .handle = switch (preopens.get(name) orelse fatal("preopen not found: '{s}'", .{name})) { + .file => fatal("preopen {s} is not a directory", .{name}), + .dir => |d| d, }, }; } - fn openUnresolved(arena: Allocator, cwd: []const u8, unresolved_path: []const u8, thing: enum { @"zig lib", @"global cache", @"local cache" }) Cache.Directory { + fn openUnresolved( + arena: Allocator, + io: Io, + cwd: []const u8, + unresolved_path: []const u8, + thing: enum { @"zig lib", @"global cache", @"local cache" }, + ) Cache.Directory { const path = introspect.resolvePath(arena, cwd, &.{unresolved_path}) catch |err| { fatal("unable to resolve {s} directory: {s}", .{ @tagName(thing), @errorName(err) }); }; const nonempty_path = if (path.len == 0) "." else path; const handle_or_err = switch (thing) { - .@"zig lib" => fs.cwd().openDir(nonempty_path, .{}), - .@"global cache", .@"local cache" => fs.cwd().makeOpenPath(nonempty_path, .{}), + .@"zig lib" => Io.Dir.cwd().openDir(io, nonempty_path, .{}), + .@"global cache", .@"local cache" => Io.Dir.cwd().createDirPathOpen(io, nonempty_path, .{}), }; return .{ .path = if (path.len == 0) null else path, @@ -912,8 +923,8 @@ pub const CrtFile = struct { lock: Cache.Lock, full_object_path: Cache.Path, - pub fn deinit(self: *CrtFile, gpa: Allocator) void { - self.lock.release(); + pub fn deinit(self: *CrtFile, gpa: Allocator, io: Io) void { + self.lock.release(io); gpa.free(self.full_object_path.sub_path); self.* = undefined; } @@ -1104,8 +1115,8 @@ pub const CObject = struct { const source_line = source_line: { if (diag.src_loc.offset == 0 or diag.src_loc.column == 0) break :source_line 0; - const file = fs.cwd().openFile(file_name, .{}) catch break :source_line 0; - defer file.close(); + const file = Io.Dir.cwd().openFile(io, file_name, .{}) catch break :source_line 0; + defer file.close(io); var buffer: [1024]u8 = undefined; var file_reader = file.reader(io, &buffer); file_reader.seekTo(diag.src_loc.offset + 1 - diag.src_loc.column) catch break :source_line 0; @@ -1179,8 +1190,8 @@ pub const CObject = struct { }; var buffer: [1024]u8 = undefined; - const file = try fs.cwd().openFile(path, .{}); - defer file.close(); + const file = try Io.Dir.cwd().openFile(io, path, .{}); + defer file.close(io); var file_reader = file.reader(io, &buffer); var bc = std.zig.llvm.BitcodeReader.init(gpa, .{ .reader = &file_reader.interface }); defer bc.deinit(); @@ -1310,7 +1321,7 @@ pub const CObject = struct { }; /// Returns if there was failure. - pub fn clearStatus(self: *CObject, gpa: Allocator) bool { + pub fn clearStatus(self: *CObject, gpa: Allocator, io: Io) bool { switch (self.status) { .new => return false, .failure, .failure_retryable => { @@ -1319,15 +1330,15 @@ pub const CObject = struct { }, .success => |*success| { gpa.free(success.object_path.sub_path); - success.lock.release(); + success.lock.release(io); self.status = .new; return false; }, } } - pub fn destroy(self: *CObject, gpa: Allocator) void { - _ = self.clearStatus(gpa); + pub fn destroy(self: *CObject, gpa: Allocator, io: Io) void { + _ = self.clearStatus(gpa, io); gpa.destroy(self); } }; @@ -1357,7 +1368,7 @@ pub const Win32Resource = struct { }, /// Returns true if there was failure. - pub fn clearStatus(self: *Win32Resource, gpa: Allocator) bool { + pub fn clearStatus(self: *Win32Resource, gpa: Allocator, io: Io) bool { switch (self.status) { .new => return false, .failure, .failure_retryable => { @@ -1366,15 +1377,15 @@ pub const Win32Resource = struct { }, .success => |*success| { gpa.free(success.res_path); - success.lock.release(); + success.lock.release(io); self.status = .new; return false; }, } } - pub fn destroy(self: *Win32Resource, gpa: Allocator) void { - _ = self.clearStatus(gpa); + pub fn destroy(self: *Win32Resource, gpa: Allocator, io: Io) void { + _ = self.clearStatus(gpa, io); gpa.destroy(self); } }; @@ -1391,6 +1402,8 @@ pub const MiscTask = enum { freebsd_shared_objects, netbsd_crt_file, netbsd_shared_objects, + openbsd_crt_file, + openbsd_shared_objects, mingw_crt_file, windows_import_lib, libunwind, @@ -1403,6 +1416,7 @@ pub const MiscTask = enum { compiler_rt, libzigc, analyze_mod, + link_depfile, docs_copy, docs_wasm, @@ -1426,6 +1440,9 @@ pub const MiscTask = enum { @"netbsd libc Scrt0.o", @"netbsd libc shared object", + @"openbsd libc Scrt0.o", + @"openbsd libc shared object", + @"mingw-w64 crt2.o", @"mingw-w64 dllcrt2.o", @"mingw-w64 libmingw32.lib", @@ -1566,7 +1583,7 @@ pub const CacheMode = enum { pub const ParentWholeCache = struct { manifest: *Cache.Manifest, - mutex: *std.Thread.Mutex, + mutex: *std.Io.Mutex, prefix_map: [4]u8, }; @@ -1594,7 +1611,7 @@ const CacheUse = union(CacheMode) { lf_open_opts: link.File.OpenOptions, /// This is a pointer to a local variable inside `update`. cache_manifest: ?*Cache.Manifest, - cache_manifest_mutex: std.Thread.Mutex, + cache_manifest_mutex: std.Io.Mutex, /// This is non-`null` for most of the body of `update`. It is the temporary directory which /// we initially emit our artifacts to. After the main part of the update is done, it will /// be closed and moved to its final location, and this field set to `null`. @@ -1602,9 +1619,9 @@ const CacheUse = union(CacheMode) { /// Prevents other processes from clobbering files in the output directory. lock: ?Cache.Lock, - fn releaseLock(whole: *Whole) void { + fn releaseLock(whole: *Whole, io: Io) void { if (whole.lock) |*lock| { - lock.release(); + lock.release(io); whole.lock = null; } } @@ -1616,17 +1633,17 @@ const CacheUse = union(CacheMode) { } }; - fn deinit(cu: CacheUse) void { + fn deinit(cu: CacheUse, io: Io) void { switch (cu) { .none => |none| { assert(none.tmp_artifact_directory == null); }, .incremental => |incremental| { - incremental.artifact_directory.handle.close(); + incremental.artifact_directory.handle.close(io); }, .whole => |whole| { assert(whole.tmp_artifact_directory == null); - whole.releaseLock(); + whole.releaseLock(io); }, } } @@ -1634,7 +1651,7 @@ const CacheUse = union(CacheMode) { pub const CreateOptions = struct { dirs: Directories, - thread_pool: *ThreadPool, + thread_limit: usize, self_exe_path: ?[]const u8 = null, /// Options that have been resolved by calling `resolveDefaults`. @@ -1732,6 +1749,7 @@ pub const CreateOptions = struct { verbose_generic_instances: bool = false, verbose_llvm_ir: ?[]const u8 = null, verbose_llvm_bc: ?[]const u8 = null, + link_depfile: ?[]const u8 = null, verbose_cimport: bool = false, verbose_llvm_cpu_features: bool = false, debug_compiler_runtime_libs: bool = false, @@ -1788,6 +1806,8 @@ pub const CreateOptions = struct { parent_whole_cache: ?ParentWholeCache = null, + environ_map: *const std.process.Environ.Map, + pub const Entry = link.File.OpenOptions.Entry; /// Which fields are valid depends on the `cache_mode` given. @@ -1870,7 +1890,7 @@ pub const CreateDiagnostic = union(enum) { pub const CreateCachePath = struct { which: enum { local, global }, sub: []const u8, - err: (fs.Dir.MakeError || fs.Dir.OpenError || fs.Dir.StatFileError), + err: (Io.Dir.CreateDirError || Io.Dir.OpenError || Io.Dir.StatFileError), }; pub fn format(diag: CreateDiagnostic, w: *Writer) Writer.Error!void { switch (diag) { @@ -1894,13 +1914,17 @@ pub const CreateDiagnostic = union(enum) { return error.CreateFail; } }; -pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, options: CreateOptions) error{ + +pub const CreateError = error{ OutOfMemory, + Canceled, Unexpected, CurrentWorkingDirectoryUnlinked, /// An error has been stored to `diag`. CreateFail, -}!*Compilation { +}; + +pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, options: CreateOptions) CreateError!*Compilation { const output_mode = options.config.output_mode; const is_dyn_lib = switch (output_mode) { .Obj, .Exe => false, @@ -1948,11 +1972,13 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, const libc_dirs = std.zig.LibCDirs.detect( arena, + io, options.dirs.zig_lib.path.?, target, options.root_mod.resolved_target.is_native_abi, link_libc, options.libc_installation, + options.environ_map, ) catch |err| switch (err) { error.OutOfMemory => |e| return e, // Every other error is specifically related to finding the native installation @@ -2078,13 +2104,17 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, } if (options.verbose_llvm_cpu_features) { - if (options.root_mod.resolved_target.llvm_cpu_features) |cf| print: { - const stderr_w, _ = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); - stderr_w.print("compilation: {s}\n", .{options.root_name}) catch break :print; - stderr_w.print(" target: {s}\n", .{try target.zigTriple(arena)}) catch break :print; - stderr_w.print(" cpu: {s}\n", .{target.cpu.model.name}) catch break :print; - stderr_w.print(" features: {s}\n", .{cf}) catch {}; + if (options.root_mod.resolved_target.llvm_cpu_features) |cf| { + const stderr = try io.lockStderr(&.{}, null); + defer io.unlockStderr(); + const w = &stderr.file_writer.interface; + printVerboseLlvmCpuFeatures(w, arena, options.root_name, target, cf) catch |err| switch (err) { + error.WriteFailed => switch (stderr.file_writer.err.?) { + error.Canceled => |e| return e, + else => {}, + }, + error.OutOfMemory => |e| return e, + }; } } @@ -2102,16 +2132,17 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, cache.* = .{ .gpa = gpa, .io = io, - .manifest_dir = options.dirs.local_cache.handle.makeOpenPath("h", .{}) catch |err| { + .manifest_dir = options.dirs.local_cache.handle.createDirPathOpen(io, "h", .{}) catch |err| { return diag.fail(.{ .create_cache_path = .{ .which = .local, .sub = "h", .err = err } }); }, + .cwd = options.dirs.cwd, }; // These correspond to std.zig.Server.Message.PathPrefix. - cache.addPrefix(.{ .path = null, .handle = fs.cwd() }); + cache.addPrefix(.{ .path = null, .handle = Io.Dir.cwd() }); cache.addPrefix(options.dirs.zig_lib); cache.addPrefix(options.dirs.local_cache); cache.addPrefix(options.dirs.global_cache); - errdefer cache.manifest_dir.close(); + errdefer cache.manifest_dir.close(io); // This is shared hasher state common to zig source and all C source files. cache.hash.addBytes(build_options.version); @@ -2152,18 +2183,18 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, // to redundantly happen for each AstGen operation. const zir_sub_dir = "z"; - var local_zir_dir = options.dirs.local_cache.handle.makeOpenPath(zir_sub_dir, .{}) catch |err| { + var local_zir_dir = options.dirs.local_cache.handle.createDirPathOpen(io, zir_sub_dir, .{}) catch |err| { return diag.fail(.{ .create_cache_path = .{ .which = .local, .sub = zir_sub_dir, .err = err } }); }; - errdefer local_zir_dir.close(); + errdefer local_zir_dir.close(io); const local_zir_cache: Cache.Directory = .{ .handle = local_zir_dir, .path = try options.dirs.local_cache.join(arena, &.{zir_sub_dir}), }; - var global_zir_dir = options.dirs.global_cache.handle.makeOpenPath(zir_sub_dir, .{}) catch |err| { + var global_zir_dir = options.dirs.global_cache.handle.createDirPathOpen(io, zir_sub_dir, .{}) catch |err| { return diag.fail(.{ .create_cache_path = .{ .which = .global, .sub = zir_sub_dir, .err = err } }); }; - errdefer global_zir_dir.close(); + errdefer global_zir_dir.close(io); const global_zir_cache: Cache.Directory = .{ .handle = global_zir_dir, .path = try options.dirs.global_cache.join(arena, &.{zir_sub_dir}), @@ -2208,8 +2239,9 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, .llvm_object = null, .analysis_roots_buffer = undefined, .analysis_roots_len = 0, + .codegen_task_pool = try .init(arena), }; - try zcu.init(options.thread_pool.getIdCount()); + try zcu.init(gpa, io, options.thread_limit); break :blk zcu; } else blk: { if (options.emit_h != .no) return diag.fail(.emit_h_without_zcu); @@ -2221,6 +2253,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, .gpa = gpa, .arena = arena, .io = io, + .thread_limit = options.thread_limit, .zcu = opt_zcu, .cache_use = undefined, // populated below .bin_file = null, // populated below if necessary @@ -2238,7 +2271,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, .libc_framework_dir_list = libc_dirs.libc_framework_dir_list, .rc_includes = options.rc_includes, .mingw_unicode_entry_point = options.mingw_unicode_entry_point, - .thread_pool = options.thread_pool, .clang_passthrough_mode = options.clang_passthrough_mode, .clang_preprocessor_mode = options.clang_preprocessor_mode, .verbose_cc = options.verbose_cc, @@ -2247,6 +2279,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, .verbose_generic_instances = options.verbose_generic_instances, .verbose_llvm_ir = options.verbose_llvm_ir, .verbose_llvm_bc = options.verbose_llvm_bc, + .link_depfile = options.link_depfile, .verbose_cimport = options.verbose_cimport, .verbose_llvm_cpu_features = options.verbose_llvm_cpu_features, .verbose_link = options.verbose_link, @@ -2278,13 +2311,15 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, .global_cc_argv = options.global_cc_argv, .file_system_inputs = options.file_system_inputs, .parent_whole_cache = options.parent_whole_cache, - .link_diags = .init(gpa), + .link_diags = .init(gpa, io), + .oneshot_prelink_tasks = .empty, .emit_bin = try options.emit_bin.resolve(arena, &options, .bin), .emit_asm = try options.emit_asm.resolve(arena, &options, .@"asm"), .emit_implib = try options.emit_implib.resolve(arena, &options, .implib), .emit_llvm_ir = try options.emit_llvm_ir.resolve(arena, &options, .llvm_ir), .emit_llvm_bc = try options.emit_llvm_bc.resolve(arena, &options, .llvm_bc), .emit_docs = try options.emit_docs.resolve(arena, &options, .docs), + .environ_map = options.environ_map, }; errdefer { @@ -2428,10 +2463,10 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, const digest = hash.final(); const artifact_sub_dir = "o" ++ fs.path.sep_str ++ digest; - var artifact_dir = options.dirs.local_cache.handle.makeOpenPath(artifact_sub_dir, .{}) catch |err| { + var artifact_dir = options.dirs.local_cache.handle.createDirPathOpen(io, artifact_sub_dir, .{}) catch |err| { return diag.fail(.{ .create_cache_path = .{ .which = .local, .sub = artifact_sub_dir, .err = err } }); }; - errdefer artifact_dir.close(); + errdefer artifact_dir.close(io); const artifact_directory: Cache.Directory = .{ .handle = artifact_dir, .path = try options.dirs.local_cache.join(arena, &.{artifact_sub_dir}), @@ -2464,7 +2499,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, whole.* = .{ .lf_open_opts = lf_open_opts, .cache_manifest = null, - .cache_manifest_mutex = .{}, + .cache_manifest_mutex = .init, .tmp_artifact_directory = null, .lock = null, }; @@ -2549,14 +2584,14 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, }; const fields = @typeInfo(@TypeOf(paths)).@"struct".fields; - try comp.link_task_queue.queued_prelink.ensureUnusedCapacity(gpa, fields.len + 1); + try comp.oneshot_prelink_tasks.ensureUnusedCapacity(gpa, fields.len + 1); inline for (fields) |field| { if (@field(paths, field.name)) |path| { - comp.link_task_queue.queued_prelink.appendAssumeCapacity(.{ .load_object = path }); + comp.oneshot_prelink_tasks.appendAssumeCapacity(.{ .load_object = path }); } } // Loads the libraries provided by `target_util.libcFullLinkFlags(target)`. - comp.link_task_queue.queued_prelink.appendAssumeCapacity(.load_host_libc); + comp.oneshot_prelink_tasks.appendAssumeCapacity(.load_host_libc); } else if (target.isMuslLibC()) { if (!std.zig.target.canBuildLibC(target)) return diag.fail(.cross_libc_unavailable); @@ -2592,6 +2627,14 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, } comp.queued_jobs.netbsd_shared_objects = true; + } else if (target.isOpenBSDLibC()) { + if (!std.zig.target.canBuildLibC(target)) return diag.fail(.cross_libc_unavailable); + + if (openbsd.needsCrt0(comp.config.output_mode)) |f| { + comp.queued_jobs.openbsd_crt_file[@intFromEnum(f)] = true; + } + + comp.queued_jobs.openbsd_shared_objects = true; } else if (target.isWasiLibC()) { if (!std.zig.target.canBuildLibC(target)) return diag.fail(.cross_libc_unavailable); @@ -2625,10 +2668,9 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, for (0..count) |i| { try comp.queueJob(.{ .windows_import_lib = i }); } - // when integrating coff linker with prelink, the above - // queueJob will need to change into something else since those - // jobs are dispatched *after* the link_task_wait_group.wait() - // that happens when separateCodegenThreadOk() is false. + // when integrating coff linker with prelink, the above `queueJob` will need to move + // to something in `dispatchPrelinkWork`, which must queue all prelink link tasks + // *before* we begin working on the main job queue. } if (comp.wantBuildLibUnwindFromSource()) { comp.queued_jobs.libunwind = true; @@ -2677,22 +2719,32 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, } } - try comp.link_task_queue.queued_prelink.append(gpa, .load_explicitly_provided); + try comp.oneshot_prelink_tasks.append(gpa, .load_explicitly_provided); } - log.debug("queued prelink tasks: {d}", .{comp.link_task_queue.queued_prelink.items.len}); + log.debug("queued oneshot prelink tasks: {d}", .{comp.oneshot_prelink_tasks.items.len}); return comp; } +fn printVerboseLlvmCpuFeatures( + w: *Writer, + arena: Allocator, + root_name: []const u8, + target: *const std.Target, + cf: [*:0]const u8, +) (Writer.Error || Allocator.Error)!void { + try w.print("compilation: {s}\n", .{root_name}); + try w.print(" target: {s}\n", .{try target.zigTriple(arena)}); + try w.print(" cpu: {s}\n", .{target.cpu.model.name}); + try w.print(" features: {s}\n", .{cf}); +} + pub fn destroy(comp: *Compilation) void { const gpa = comp.gpa; - - // This needs to be destroyed first, because it might contain MIR which we only know - // how to interpret (which kind of MIR it is) from `comp.bin_file`. - comp.link_task_queue.deinit(comp); + const io = comp.io; if (comp.bin_file) |lf| lf.destroy(); if (comp.zcu) |zcu| zcu.deinit(); - comp.cache_use.deinit(); + comp.cache_use.deinit(io); for (&comp.work_queues) |*work_queue| work_queue.deinit(gpa); comp.c_object_work_queue.deinit(gpa); @@ -2705,36 +2757,40 @@ pub fn destroy(comp: *Compilation) void { var it = comp.crt_files.iterator(); while (it.next()) |entry| { gpa.free(entry.key_ptr.*); - entry.value_ptr.deinit(gpa); + entry.value_ptr.deinit(gpa, io); } comp.crt_files.deinit(gpa); } - if (comp.libcxx_static_lib) |*crt_file| crt_file.deinit(gpa); - if (comp.libcxxabi_static_lib) |*crt_file| crt_file.deinit(gpa); - if (comp.libunwind_static_lib) |*crt_file| crt_file.deinit(gpa); - if (comp.tsan_lib) |*crt_file| crt_file.deinit(gpa); - if (comp.ubsan_rt_lib) |*crt_file| crt_file.deinit(gpa); - if (comp.ubsan_rt_obj) |*crt_file| crt_file.deinit(gpa); - if (comp.zigc_static_lib) |*crt_file| crt_file.deinit(gpa); - if (comp.compiler_rt_lib) |*crt_file| crt_file.deinit(gpa); - if (comp.compiler_rt_obj) |*crt_file| crt_file.deinit(gpa); - if (comp.compiler_rt_dyn_lib) |*crt_file| crt_file.deinit(gpa); - if (comp.fuzzer_lib) |*crt_file| crt_file.deinit(gpa); + if (comp.libcxx_static_lib) |*crt_file| crt_file.deinit(gpa, io); + if (comp.libcxxabi_static_lib) |*crt_file| crt_file.deinit(gpa, io); + if (comp.libunwind_static_lib) |*crt_file| crt_file.deinit(gpa, io); + if (comp.tsan_lib) |*crt_file| crt_file.deinit(gpa, io); + if (comp.ubsan_rt_lib) |*crt_file| crt_file.deinit(gpa, io); + if (comp.ubsan_rt_obj) |*crt_file| crt_file.deinit(gpa, io); + if (comp.zigc_static_lib) |*crt_file| crt_file.deinit(gpa, io); + if (comp.compiler_rt_lib) |*crt_file| crt_file.deinit(gpa, io); + if (comp.compiler_rt_obj) |*crt_file| crt_file.deinit(gpa, io); + if (comp.compiler_rt_dyn_lib) |*crt_file| crt_file.deinit(gpa, io); + if (comp.fuzzer_lib) |*crt_file| crt_file.deinit(gpa, io); if (comp.glibc_so_files) |*glibc_file| { - glibc_file.deinit(gpa); + glibc_file.deinit(gpa, io); } if (comp.freebsd_so_files) |*freebsd_file| { - freebsd_file.deinit(gpa); + freebsd_file.deinit(gpa, io); } if (comp.netbsd_so_files) |*netbsd_file| { - netbsd_file.deinit(gpa); + netbsd_file.deinit(gpa, io); + } + + if (comp.openbsd_so_files) |*openbsd_file| { + openbsd_file.deinit(gpa, io); } for (comp.c_object_table.keys()) |key| { - key.destroy(gpa); + key.destroy(gpa, io); } comp.c_object_table.deinit(gpa); @@ -2744,7 +2800,7 @@ pub fn destroy(comp: *Compilation) void { comp.failed_c_objects.deinit(gpa); for (comp.win32_resource_table.keys()) |key| { - key.destroy(gpa); + key.destroy(gpa, io); } comp.win32_resource_table.deinit(gpa); @@ -2756,10 +2812,11 @@ pub fn destroy(comp: *Compilation) void { if (comp.time_report) |*tr| tr.deinit(gpa); comp.link_diags.deinit(); + comp.oneshot_prelink_tasks.deinit(gpa); comp.clearMiscFailures(); - comp.cache_parent.manifest_dir.close(); + comp.cache_parent.manifest_dir.close(io); } pub fn clearMiscFailures(comp: *Compilation) void { @@ -2790,10 +2847,12 @@ pub fn hotCodeSwap( } fn cleanupAfterUpdate(comp: *Compilation, tmp_dir_rand_int: u64) void { + const io = comp.io; + switch (comp.cache_use) { .none => |none| { if (none.tmp_artifact_directory) |*tmp_dir| { - tmp_dir.handle.close(); + tmp_dir.handle.close(io); none.tmp_artifact_directory = null; if (dev.env == .bootstrap) { // zig1 uses `CacheMode.none`, but it doesn't need to know how to delete @@ -2812,12 +2871,9 @@ fn cleanupAfterUpdate(comp: *Compilation, tmp_dir_rand_int: u64) void { return; } const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int); - comp.dirs.local_cache.handle.deleteTree(tmp_dir_sub_path) catch |err| { - log.warn("failed to delete temporary directory '{s}{c}{s}': {s}", .{ - comp.dirs.local_cache.path orelse ".", - fs.path.sep, - tmp_dir_sub_path, - @errorName(err), + comp.dirs.local_cache.handle.deleteTree(io, tmp_dir_sub_path) catch |err| { + log.warn("failed to delete temporary directory '{s}{c}{s}': {t}", .{ + comp.dirs.local_cache.path orelse ".", fs.path.sep, tmp_dir_sub_path, err, }); }; } @@ -2833,15 +2889,12 @@ fn cleanupAfterUpdate(comp: *Compilation, tmp_dir_rand_int: u64) void { comp.bin_file = null; } if (whole.tmp_artifact_directory) |*tmp_dir| { - tmp_dir.handle.close(); + tmp_dir.handle.close(io); whole.tmp_artifact_directory = null; const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int); - comp.dirs.local_cache.handle.deleteTree(tmp_dir_sub_path) catch |err| { - log.warn("failed to delete temporary directory '{s}{c}{s}': {s}", .{ - comp.dirs.local_cache.path orelse ".", - fs.path.sep, - tmp_dir_sub_path, - @errorName(err), + comp.dirs.local_cache.handle.deleteTree(io, tmp_dir_sub_path) catch |err| { + log.warn("failed to delete temporary directory '{s}{c}{s}': {t}", .{ + comp.dirs.local_cache.path orelse ".", fs.path.sep, tmp_dir_sub_path, err, }); }; } @@ -2861,8 +2914,10 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE const tracy_trace = trace(@src()); defer tracy_trace.end(); - // This arena is scoped to this one update. const gpa = comp.gpa; + const io = comp.io; + + // This arena is scoped to this one update. var arena_allocator = std.heap.ArenaAllocator.init(gpa); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); @@ -2885,10 +2940,10 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE .none => |none| { assert(none.tmp_artifact_directory == null); none.tmp_artifact_directory = d: { - tmp_dir_rand_int = std.crypto.random.int(u64); + io.random(@ptrCast(&tmp_dir_rand_int)); const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int); const path = try comp.dirs.local_cache.join(arena, &.{tmp_dir_sub_path}); - const handle = comp.dirs.local_cache.handle.makeOpenPath(tmp_dir_sub_path, .{}) catch |err| { + const handle = comp.dirs.local_cache.handle.createDirPathOpen(io, tmp_dir_sub_path, .{}) catch |err| { return comp.setMiscFailure(.open_output, "failed to create output directory '{s}': {t}", .{ path, err }); }; break :d .{ .path = path, .handle = handle }; @@ -2898,7 +2953,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE .whole => |whole| { assert(comp.bin_file == null); // We are about to obtain this lock, so here we give other processes a chance first. - whole.releaseLock(); + whole.releaseLock(io); man = comp.cache_parent.obtain(); whole.cache_manifest = &man; @@ -2942,8 +2997,8 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE // In this case the cache hit contains the full set of file system inputs. Nice! if (comp.file_system_inputs) |buf| try man.populateFileSystemInputs(buf); if (comp.parent_whole_cache) |pwc| { - pwc.mutex.lock(); - defer pwc.mutex.unlock(); + try pwc.mutex.lock(io); + defer pwc.mutex.unlock(io); try man.populateOtherManifest(pwc.manifest, pwc.prefix_map); } @@ -2966,10 +3021,10 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE // Compile the artifacts to a temporary directory. whole.tmp_artifact_directory = d: { - tmp_dir_rand_int = std.crypto.random.int(u64); + io.random(@ptrCast(&tmp_dir_rand_int)); const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int); const path = try comp.dirs.local_cache.join(arena, &.{tmp_dir_sub_path}); - const handle = comp.dirs.local_cache.handle.makeOpenPath(tmp_dir_sub_path, .{}) catch |err| { + const handle = comp.dirs.local_cache.handle.createDirPathOpen(io, tmp_dir_sub_path, .{}) catch |err| { return comp.setMiscFailure(.open_output, "failed to create output directory '{s}': {t}", .{ path, err }); }; break :d .{ .path = path, .handle = handle }; @@ -3062,7 +3117,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE comp.link_prog_node = .none; }; - try comp.performAllTheWork(main_progress_node); + try comp.performAllTheWork(main_progress_node, arena); if (comp.zcu) |zcu| { const pt: Zcu.PerThread = .activate(zcu, .main); @@ -3084,21 +3139,25 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE } if (build_options.enable_debug_extensions and comp.verbose_intern_pool) { - std.debug.print("intern pool stats for '{s}':\n", .{ - comp.root_name, - }); + std.debug.print("intern pool stats for '{s}':\n", .{comp.root_name}); zcu.intern_pool.dump(); } if (build_options.enable_debug_extensions and comp.verbose_generic_instances) { - std.debug.print("generic instances for '{s}:0x{x}':\n", .{ - comp.root_name, - @intFromPtr(zcu), - }); + std.debug.print("generic instances for '{s}:0x{x}':\n", .{ comp.root_name, @intFromPtr(zcu) }); zcu.intern_pool.dumpGenericInstances(gpa); } } + if (comp.link_depfile) |depfile_path| if (comp.bin_file) |lf| { + assert(comp.file_system_inputs != null); + comp.createDepFile(depfile_path, lf.emit) catch |err| comp.setMiscFailure( + .link_depfile, + "unable to write linker dependency file: {t}", + .{err}, + ); + }; + if (anyErrors(comp)) { // Skip flushing and keep source files loaded for error reporting. return; @@ -3119,8 +3178,8 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE .whole => |whole| { if (comp.file_system_inputs) |buf| try man.populateFileSystemInputs(buf); if (comp.parent_whole_cache) |pwc| { - pwc.mutex.lock(); - defer pwc.mutex.unlock(); + try pwc.mutex.lock(io); + defer pwc.mutex.unlock(io); try man.populateOtherManifest(pwc.manifest, pwc.prefix_map); } @@ -3140,7 +3199,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE // the file handle and re-open it in the follow up call to // `makeWritable`. if (lf.file) |f| { - f.close(); + f.close(io); lf.file = null; if (lf.closeDebugInfo()) break :w .lf_and_debug; @@ -3153,12 +3212,12 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE // Rename the temporary directory into place. // Close tmp dir and link.File to avoid open handle during rename. - whole.tmp_artifact_directory.?.handle.close(); + whole.tmp_artifact_directory.?.handle.close(io); whole.tmp_artifact_directory = null; const s = fs.path.sep_str; const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(tmp_dir_rand_int); const o_sub_path = "o" ++ s ++ hex_digest; - renameTmpIntoCache(comp.dirs.local_cache, tmp_dir_sub_path, o_sub_path) catch |err| { + renameTmpIntoCache(io, comp.dirs.local_cache, tmp_dir_sub_path, o_sub_path) catch |err| { return comp.setMiscFailure( .rename_results, "failed to rename compilation results ('{f}{s}') into local cache ('{f}{s}'): {t}", @@ -3218,8 +3277,10 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE } } +/// Thread-safe. Assumes that `comp.mutex` is *not* already held by the caller. pub fn appendFileSystemInput(comp: *Compilation, path: Compilation.Path) Allocator.Error!void { const gpa = comp.gpa; + const io = comp.io; const fsi = comp.file_system_inputs orelse return; const prefixes = comp.cache_parent.prefixes(); @@ -3238,6 +3299,10 @@ pub fn appendFileSystemInput(comp: *Compilation, path: Compilation.Path) Allocat .{ @tagName(path.root), want_prefix_dir, path.sub_path }, ); + // There may be concurrent calls to this function from C object workers and/or the main thread. + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); + try fsi.ensureUnusedCapacity(gpa, path.sub_path.len + 3); if (fsi.items.len > 0) fsi.appendAssumeCapacity(0); fsi.appendAssumeCapacity(prefix); @@ -3282,11 +3347,9 @@ pub fn resolveEmitPathFlush( }, } } -fn flush( - comp: *Compilation, - arena: Allocator, - tid: Zcu.PerThread.Id, -) Allocator.Error!void { + +fn flush(comp: *Compilation, arena: Allocator, tid: Zcu.PerThread.Id) (Io.Cancelable || Allocator.Error)!void { + const io = comp.io; if (comp.zcu) |zcu| { if (zcu.llvm_object) |llvm_object| { const pt: Zcu.PerThread = .activate(zcu, tid); @@ -3299,8 +3362,8 @@ fn flush( var timer = comp.startTimer(); defer if (timer.finish()) |ns| { - comp.mutex.lock(); - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); comp.time_report.?.stats.real_ns_llvm_emit = ns; }; @@ -3344,14 +3407,14 @@ fn flush( if (comp.bin_file) |lf| { var timer = comp.startTimer(); defer if (timer.finish()) |ns| { - comp.mutex.lock(); - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); comp.time_report.?.stats.real_ns_link_flush = ns; }; // This is needed before reading the error flags. lf.flush(arena, tid, comp.link_prog_node) catch |err| switch (err) { error.LinkFailure => {}, // Already reported. - error.OutOfMemory => return error.OutOfMemory, + error.OutOfMemory, error.Canceled => |e| return e, }; } if (comp.zcu) |zcu| { @@ -3370,17 +3433,19 @@ fn flush( /// implementation at the bottom of this function. /// This function is only called when CacheMode is `whole`. fn renameTmpIntoCache( + io: Io, cache_directory: Cache.Directory, tmp_dir_sub_path: []const u8, o_sub_path: []const u8, ) !void { var seen_eaccess = false; while (true) { - fs.rename( + Io.Dir.rename( cache_directory.handle, tmp_dir_sub_path, cache_directory.handle, o_sub_path, + io, ) catch |err| switch (err) { // On Windows, rename fails with `AccessDenied` rather than `PathAlreadyExists`. // See https://github.com/ziglang/zig/issues/8362 @@ -3388,17 +3453,17 @@ fn renameTmpIntoCache( .windows => { if (seen_eaccess) return error.AccessDenied; seen_eaccess = true; - try cache_directory.handle.deleteTree(o_sub_path); + try cache_directory.handle.deleteTree(io, o_sub_path); continue; }, else => return error.AccessDenied, }, - error.PathAlreadyExists => { - try cache_directory.handle.deleteTree(o_sub_path); + error.DirNotEmpty => { + try cache_directory.handle.deleteTree(io, o_sub_path); continue; }, error.FileNotFound => { - try cache_directory.handle.makePath("o"); + try cache_directory.handle.createDirPath(io, "o"); continue; }, else => |e| return e, @@ -3573,6 +3638,7 @@ fn emitFromCObject( new_ext: []const u8, unresolved_emit_path: []const u8, ) Allocator.Error!void { + const io = comp.io; // The dirname and stem (i.e. everything but the extension), of the sub path of the C object. // We'll append `new_ext` to it to get the path to the right thing (asm, LLVM IR, etc). const c_obj_dir_and_stem: []const u8 = p: { @@ -3582,23 +3648,18 @@ fn emitFromCObject( }; const src_path: Cache.Path = .{ .root_dir = c_obj_path.root_dir, - .sub_path = try std.fmt.allocPrint(arena, "{s}{s}", .{ - c_obj_dir_and_stem, - new_ext, - }), + .sub_path = try std.fmt.allocPrint(arena, "{s}{s}", .{ c_obj_dir_and_stem, new_ext }), }; const emit_path = comp.resolveEmitPath(unresolved_emit_path); - src_path.root_dir.handle.copyFile( + Io.Dir.copyFile( + src_path.root_dir.handle, src_path.sub_path, emit_path.root_dir.handle, emit_path.sub_path, + io, .{}, - ) catch |err| log.err("unable to copy '{f}' to '{f}': {s}", .{ - src_path, - emit_path, - @errorName(err), - }); + ) catch |err| log.err("unable to copy '{f}' to '{f}': {t}", .{ src_path, emit_path, err }); } /// Having the file open for writing is problematic as far as executing the @@ -3654,6 +3715,7 @@ pub fn saveState(comp: *Compilation) !void { const lf = comp.bin_file orelse return; const gpa = comp.gpa; + const io = comp.io; var bufs = std.array_list.Managed([]const u8).init(gpa); defer bufs.deinit(); @@ -3873,11 +3935,14 @@ pub fn saveState(comp: *Compilation) !void { // Using an atomic file prevents a crash or power failure from corrupting // the previous incremental compilation state. + var af = try lf.emit.root_dir.handle.createFileAtomic(io, basename, .{ .replace = true }); + defer af.deinit(io); + var write_buffer: [1024]u8 = undefined; - var af = try lf.emit.root_dir.handle.atomicFile(basename, .{ .write_buffer = &write_buffer }); - defer af.deinit(); - try af.file_writer.interface.writeVecAll(bufs.items); - try af.finish(); + var file_writer = af.file.writer(io, &write_buffer); + try file_writer.interface.writeVecAll(bufs.items); + try file_writer.interface.flush(); + try af.replace(io); } fn addBuf(list: *std.array_list.Managed([]const u8), buf: []const u8) void { @@ -4232,12 +4297,13 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle { // However, we haven't reported any such error. // This is a compiler bug. print_ctx: { - var stderr_w, _ = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); - stderr_w.writeAll("referenced transitive analysis errors, but none actually emitted\n") catch break :print_ctx; - stderr_w.print("{f} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)}) catch break :print_ctx; + const stderr = std.debug.lockStderr(&.{}).terminal(); + defer std.debug.unlockStderr(); + const w = stderr.writer; + w.writeAll("referenced transitive analysis errors, but none actually emitted\n") catch break :print_ctx; + w.print("{f} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)}) catch break :print_ctx; while (ref) |r| { - stderr_w.print("referenced by: {f}{s}\n", .{ + w.print("referenced by: {f}{s}\n", .{ zcu.fmtAnalUnit(r.referencer), if (zcu.transitive_failed_analysis.contains(r.referencer)) " [transitive failure]" else "", }) catch break :print_ctx; @@ -4557,44 +4623,281 @@ pub fn unableToLoadZcuFile( fn performAllTheWork( comp: *Compilation, main_progress_node: std.Progress.Node, + update_arena: Allocator, ) JobError!void { - // Regardless of errors, `comp.zcu` needs to update its generation number. defer if (comp.zcu) |zcu| { + zcu.codegen_task_pool.cancel(zcu); + // Regardless of errors, `comp.zcu` needs to update its generation number. zcu.generation += 1; }; + const io = comp.io; + // This is awkward: we don't want to start the timer until later, but we won't want to stop it // until the wait groups finish. That means we need do do this. var decl_work_timer: ?Timer = null; defer commit_timer: { const t = &(decl_work_timer orelse break :commit_timer); const ns = t.finish() orelse break :commit_timer; - comp.mutex.lock(); - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); comp.time_report.?.stats.real_ns_decls = ns; } - // Here we queue up all the AstGen tasks first, followed by C object compilation. - // We wait until the AstGen tasks are all completed before proceeding to the - // (at least for now) single-threaded main work queue. However, C object compilation - // only needs to be finished by the end of this function. - - var work_queue_wait_group: WaitGroup = .{}; - defer work_queue_wait_group.wait(); + var misc_group: Io.Group = .init; + defer misc_group.cancel(io); - comp.link_task_wait_group.reset(); - defer comp.link_task_wait_group.wait(); + try comp.link_queue.start(comp, update_arena); + defer comp.link_queue.cancel(io); - // Already-queued prelink tasks - comp.link_prog_node.increaseEstimatedTotalItems(comp.link_task_queue.queued_prelink.items.len); - comp.link_task_queue.start(comp); + misc_group.concurrent(io, dispatchPrelinkWork, .{ comp, main_progress_node }) catch |err| switch (err) { + error.ConcurrencyUnavailable => { + // Do it immediately so that the link queue isn't blocked + dispatchPrelinkWork(comp, main_progress_node); + }, + }; if (comp.emit_docs != null) { dev.check(.docs_emit); - comp.thread_pool.spawnWg(&work_queue_wait_group, workerDocsCopy, .{comp}); - work_queue_wait_group.spawnManager(workerDocsWasm, .{ comp, main_progress_node }); + misc_group.async(io, workerDocsCopy, .{comp}); + misc_group.async(io, workerDocsWasm, .{ comp, main_progress_node }); + } + + if (comp.zcu) |zcu| { + const astgen_frame = tracy.namedFrame("astgen"); + defer astgen_frame.end(); + + const zir_prog_node = main_progress_node.start("AST Lowering", 0); + defer zir_prog_node.end(); + + var timer = comp.startTimer(); + defer if (timer.finish()) |ns| { + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); + comp.time_report.?.stats.real_ns_files = ns; + }; + + const gpa = comp.gpa; + + var astgen_group: Io.Group = .init; + defer astgen_group.cancel(io); + + // We cannot reference `zcu.import_table` after we spawn any `workerUpdateFile` jobs, + // because on single-threaded targets the worker will be run eagerly, meaning the + // `import_table` could be mutated, and not even holding `comp.mutex` will save us. So, + // build up a list of the files to update *before* we spawn any jobs. + var astgen_work_items: std.MultiArrayList(struct { + file_index: Zcu.File.Index, + file: *Zcu.File, + }) = .empty; + defer astgen_work_items.deinit(gpa); + // Not every item in `import_table` will need updating, because some are builtin.zig + // files. However, most will, so let's just reserve sufficient capacity upfront. + try astgen_work_items.ensureTotalCapacity(gpa, zcu.import_table.count()); + for (zcu.import_table.keys()) |file_index| { + const file = zcu.fileByIndex(file_index); + if (file.is_builtin) { + // This is a `builtin.zig`, so updating is redundant. However, we want to make + // sure the file contents are still correct on disk, since it can improve the + // debugging experience better. That job only needs `file`, so we can kick it + // off right now. + astgen_group.async(io, workerUpdateBuiltinFile, .{ comp, file }); + continue; + } + astgen_work_items.appendAssumeCapacity(.{ + .file_index = file_index, + .file = file, + }); + } + + // Now that we're not going to touch `zcu.import_table` again, we can spawn `workerUpdateFile` jobs. + for (astgen_work_items.items(.file_index), astgen_work_items.items(.file)) |file_index, file| { + astgen_group.async(io, workerUpdateFile, .{ + comp, file, file_index, zir_prog_node, &astgen_group, + }); + } + + // On the other hand, it's fine to directly iterate `zcu.embed_table.keys()` here + // because `workerUpdateEmbedFile` can't invalidate it. The different here is that one + // `@embedFile` can't trigger analysis of a new `@embedFile`! + for (0.., zcu.embed_table.keys()) |ef_index_usize, ef| { + const ef_index: Zcu.EmbedFile.Index = @enumFromInt(ef_index_usize); + astgen_group.async(io, workerUpdateEmbedFile, .{ + comp, ef_index, ef, + }); + } + + try astgen_group.await(io); + } + + if (comp.zcu) |zcu| { + const pt: Zcu.PerThread = .activate(zcu, .main); + defer pt.deactivate(); + + const gpa = zcu.gpa; + + // On an incremental update, a source file might become "dead", in that all imports of + // the file were removed. This could even change what module the file belongs to! As such, + // we do a traversal over the files, to figure out which ones are alive and the modules + // they belong to. + const any_fatal_files = try pt.computeAliveFiles(); + + // If the cache mode is `whole`, add every alive source file to the manifest. + switch (comp.cache_use) { + .whole => |whole| if (whole.cache_manifest) |man| { + for (zcu.alive_files.keys()) |file_index| { + const file = zcu.fileByIndex(file_index); + + switch (file.status) { + .never_loaded => unreachable, // AstGen tried to load it + .retryable_failure => continue, // the file cannot be read; this is a guaranteed error + .astgen_failure, .success => {}, // the file was read successfully + } + + const path = try file.path.toAbsolute(comp.dirs, gpa); + defer gpa.free(path); + + const result = res: { + try whole.cache_manifest_mutex.lock(io); + defer whole.cache_manifest_mutex.unlock(io); + if (file.source) |source| { + break :res man.addFilePostContents(path, source, file.stat); + } else { + break :res man.addFilePost(path); + } + }; + result catch |err| switch (err) { + error.OutOfMemory => |e| return e, + else => { + try pt.reportRetryableFileError(file_index, "unable to update cache: {s}", .{@errorName(err)}); + continue; + }, + }; + } + }, + .none, .incremental => {}, + } + + if (any_fatal_files or + zcu.multi_module_err != null or + zcu.failed_imports.items.len > 0 or + comp.alloc_failure_occurred) + { + // We give up right now! No updating of ZIR refs, no nothing. The idea is that this prevents + // us from invalidating lots of incremental dependencies due to files with e.g. parse errors. + // However, this means our analysis data is invalid, so we want to omit all analysis errors. + zcu.skip_analysis_this_update = true; + // Since we're skipping analysis, there are no ZCU link tasks. + comp.link_queue.finishZcuQueue(comp); + // Let other compilation work finish to collect as many errors as possible. + try misc_group.await(io); + comp.link_queue.wait(io); + return; + } + + if (comp.time_report) |*tr| { + tr.stats.n_reachable_files = @intCast(zcu.alive_files.count()); + } + + if (comp.config.incremental) { + const update_zir_refs_node = main_progress_node.start("Update ZIR References", 0); + defer update_zir_refs_node.end(); + try pt.updateZirRefs(); + } + try zcu.flushRetryableFailures(); + + // It's analysis time! Queue up our initial analysis. + for (zcu.analysisRoots()) |mod| { + try comp.queueJob(.{ .analyze_mod = mod }); + } + + zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0); + if (comp.bin_file != null) { + zcu.codegen_prog_node = main_progress_node.start("Code Generation", 0); + } + // We increment `pending_codegen_jobs` so that it doesn't reach 0 until after analysis finishes. + // That prevents the "Code Generation" node from constantly disappearing and reappearing when + // we're probably going to analyze more functions at some point. + assert(zcu.pending_codegen_jobs.swap(1, .monotonic) == 0); // don't let this become 0 until analysis finishes + } + // When analysis ends, delete the progress nodes for "Semantic Analysis" and possibly "Code Generation". + defer if (comp.zcu) |zcu| { + zcu.sema_prog_node.end(); + zcu.sema_prog_node = .none; + if (zcu.pending_codegen_jobs.fetchSub(1, .monotonic) == 1) { + // Decremented to 0, so all done. + zcu.codegen_prog_node.end(); + zcu.codegen_prog_node = .none; + } + }; + + if (comp.zcu) |zcu| { + if (!zcu.backendSupportsFeature(.separate_thread)) { + // Close the ZCU task queue. Prelink may still be running, but the closed + // queue will cause the linker task to exit once prelink finishes. The + // closed queue also communicates to `enqueueZcu` that it should wait for + // the linker task to finish and then run ZCU tasks serially. + comp.link_queue.finishZcuQueue(comp); + } + } + + if (comp.zcu != null) { + // Start the timer for the "decls" part of the pipeline (Sema, CodeGen, link). + decl_work_timer = comp.startTimer(); + } + + work: while (true) { + for (&comp.work_queues) |*work_queue| if (work_queue.popFront()) |job| { + try processOneJob( + @intFromEnum(Zcu.PerThread.Id.main), + comp, + job, + ); + continue :work; + }; + if (comp.zcu) |zcu| { + // If there's no work queued, check if there's anything outdated + // which we need to work on, and queue it if so. + if (try zcu.findOutdatedToAnalyze()) |outdated| { + try comp.queueJob(switch (outdated.unwrap()) { + .func => |f| .{ .analyze_func = f }, + .memoized_state, + .@"comptime", + .nav_ty, + .nav_val, + .type, + => .{ .analyze_comptime_unit = outdated }, + }); + continue; + } + zcu.sema_prog_node.end(); + zcu.sema_prog_node = .none; + } + break; } + comp.link_queue.finishZcuQueue(comp); + + // Main thread work is all done, now just wait for all async work. + try misc_group.await(io); + comp.link_queue.wait(io); +} + +fn dispatchPrelinkWork(comp: *Compilation, main_progress_node: std.Progress.Node) void { + const io = comp.io; + + // TODO should this function be cancelable? + const prev_cancel_prot = io.swapCancelProtection(.blocked); + defer _ = io.swapCancelProtection(prev_cancel_prot); + + var prelink_group: Io.Group = .init; + defer prelink_group.cancel(io); + + comp.queuePrelinkTasks(comp.oneshot_prelink_tasks.items) catch |err| switch (err) { + error.Canceled => unreachable, // see swapCancelProtection above + }; + comp.oneshot_prelink_tasks.clearRetainingCapacity(); + // In case it failed last time, try again. `clearMiscFailures` was already // called at the start of `update`. if (comp.queued_jobs.compiler_rt_lib and comp.compiler_rt_lib == null) { @@ -4602,8 +4905,7 @@ fn performAllTheWork( // compiler-rt due to LLD bugs as well, e.g.: // // https://github.com/llvm/llvm-project/issues/43698#issuecomment-2542660611 - comp.link_task_queue.startPrelinkItem(); - comp.link_task_wait_group.spawnManager(buildRt, .{ + prelink_group.async(io, buildRt, .{ comp, "compiler_rt.zig", "compiler_rt", @@ -4620,8 +4922,7 @@ fn performAllTheWork( } if (comp.queued_jobs.compiler_rt_obj and comp.compiler_rt_obj == null) { - comp.link_task_queue.startPrelinkItem(); - comp.link_task_wait_group.spawnManager(buildRt, .{ + prelink_group.async(io, buildRt, .{ comp, "compiler_rt.zig", "compiler_rt", @@ -4639,8 +4940,7 @@ fn performAllTheWork( // hack for stage2_x86_64 + coff if (comp.queued_jobs.compiler_rt_dyn_lib and comp.compiler_rt_dyn_lib == null) { - comp.link_task_queue.startPrelinkItem(); - comp.link_task_wait_group.spawnManager(buildRt, .{ + prelink_group.async(io, buildRt, .{ comp, "compiler_rt.zig", "compiler_rt", @@ -4657,8 +4957,7 @@ fn performAllTheWork( } if (comp.queued_jobs.fuzzer_lib and comp.fuzzer_lib == null) { - comp.link_task_queue.startPrelinkItem(); - comp.link_task_wait_group.spawnManager(buildRt, .{ + prelink_group.async(io, buildRt, .{ comp, "fuzzer.zig", "fuzzer", @@ -4672,8 +4971,7 @@ fn performAllTheWork( } if (comp.queued_jobs.ubsan_rt_lib and comp.ubsan_rt_lib == null) { - comp.link_task_queue.startPrelinkItem(); - comp.link_task_wait_group.spawnManager(buildRt, .{ + prelink_group.async(io, buildRt, .{ comp, "ubsan_rt.zig", "ubsan_rt", @@ -4689,8 +4987,7 @@ fn performAllTheWork( } if (comp.queued_jobs.ubsan_rt_obj and comp.ubsan_rt_obj == null) { - comp.link_task_queue.startPrelinkItem(); - comp.link_task_wait_group.spawnManager(buildRt, .{ + prelink_group.async(io, buildRt, .{ comp, "ubsan_rt.zig", "ubsan_rt", @@ -4706,310 +5003,108 @@ fn performAllTheWork( } if (comp.queued_jobs.glibc_shared_objects) { - comp.link_task_queue.startPrelinkItem(); - comp.link_task_wait_group.spawnManager(buildGlibcSharedObjects, .{ comp, main_progress_node }); + prelink_group.async(io, buildGlibcSharedObjects, .{ comp, main_progress_node }); } if (comp.queued_jobs.freebsd_shared_objects) { - comp.link_task_queue.startPrelinkItem(); - comp.link_task_wait_group.spawnManager(buildFreeBSDSharedObjects, .{ comp, main_progress_node }); + prelink_group.async(io, buildFreeBSDSharedObjects, .{ comp, main_progress_node }); } if (comp.queued_jobs.netbsd_shared_objects) { - comp.link_task_queue.startPrelinkItem(); - comp.link_task_wait_group.spawnManager(buildNetBSDSharedObjects, .{ comp, main_progress_node }); + prelink_group.async(io, buildNetBSDSharedObjects, .{ comp, main_progress_node }); + } + + if (comp.queued_jobs.openbsd_shared_objects) { + prelink_group.async(io, buildOpenBSDSharedObjects, .{ comp, main_progress_node }); } if (comp.queued_jobs.libunwind) { - comp.link_task_queue.startPrelinkItem(); - comp.link_task_wait_group.spawnManager(buildLibUnwind, .{ comp, main_progress_node }); + prelink_group.async(io, buildLibUnwind, .{ comp, main_progress_node }); } if (comp.queued_jobs.libcxx) { - comp.link_task_queue.startPrelinkItem(); - comp.link_task_wait_group.spawnManager(buildLibCxx, .{ comp, main_progress_node }); + prelink_group.async(io, buildLibCxx, .{ comp, main_progress_node }); } if (comp.queued_jobs.libcxxabi) { - comp.link_task_queue.startPrelinkItem(); - comp.link_task_wait_group.spawnManager(buildLibCxxAbi, .{ comp, main_progress_node }); + prelink_group.async(io, buildLibCxxAbi, .{ comp, main_progress_node }); } if (comp.queued_jobs.libtsan) { - comp.link_task_queue.startPrelinkItem(); - comp.link_task_wait_group.spawnManager(buildLibTsan, .{ comp, main_progress_node }); + prelink_group.async(io, buildLibTsan, .{ comp, main_progress_node }); } if (comp.queued_jobs.zigc_lib and comp.zigc_static_lib == null) { - comp.link_task_queue.startPrelinkItem(); - comp.link_task_wait_group.spawnManager(buildLibZigC, .{ comp, main_progress_node }); + prelink_group.async(io, buildLibZigC, .{ comp, main_progress_node }); } for (0..@typeInfo(musl.CrtFile).@"enum".fields.len) |i| { if (comp.queued_jobs.musl_crt_file[i]) { const tag: musl.CrtFile = @enumFromInt(i); - comp.link_task_queue.startPrelinkItem(); - comp.link_task_wait_group.spawnManager(buildMuslCrtFile, .{ comp, tag, main_progress_node }); + prelink_group.async(io, buildMuslCrtFile, .{ comp, tag, main_progress_node }); } } for (0..@typeInfo(glibc.CrtFile).@"enum".fields.len) |i| { if (comp.queued_jobs.glibc_crt_file[i]) { const tag: glibc.CrtFile = @enumFromInt(i); - comp.link_task_queue.startPrelinkItem(); - comp.link_task_wait_group.spawnManager(buildGlibcCrtFile, .{ comp, tag, main_progress_node }); + prelink_group.async(io, buildGlibcCrtFile, .{ comp, tag, main_progress_node }); } } for (0..@typeInfo(freebsd.CrtFile).@"enum".fields.len) |i| { if (comp.queued_jobs.freebsd_crt_file[i]) { const tag: freebsd.CrtFile = @enumFromInt(i); - comp.link_task_queue.startPrelinkItem(); - comp.link_task_wait_group.spawnManager(buildFreeBSDCrtFile, .{ comp, tag, main_progress_node }); + prelink_group.async(io, buildFreeBSDCrtFile, .{ comp, tag, main_progress_node }); } } for (0..@typeInfo(netbsd.CrtFile).@"enum".fields.len) |i| { if (comp.queued_jobs.netbsd_crt_file[i]) { const tag: netbsd.CrtFile = @enumFromInt(i); - comp.link_task_queue.startPrelinkItem(); - comp.link_task_wait_group.spawnManager(buildNetBSDCrtFile, .{ comp, tag, main_progress_node }); + prelink_group.async(io, buildNetBSDCrtFile, .{ comp, tag, main_progress_node }); + } + } + + for (0..@typeInfo(openbsd.CrtFile).@"enum".fields.len) |i| { + if (comp.queued_jobs.openbsd_crt_file[i]) { + const tag: openbsd.CrtFile = @enumFromInt(i); + prelink_group.async(io, buildOpenBSDCrtFile, .{ comp, tag, main_progress_node }); } } for (0..@typeInfo(wasi_libc.CrtFile).@"enum".fields.len) |i| { if (comp.queued_jobs.wasi_libc_crt_file[i]) { const tag: wasi_libc.CrtFile = @enumFromInt(i); - comp.link_task_queue.startPrelinkItem(); - comp.link_task_wait_group.spawnManager(buildWasiLibcCrtFile, .{ comp, tag, main_progress_node }); + prelink_group.async(io, buildWasiLibcCrtFile, .{ comp, tag, main_progress_node }); } } for (0..@typeInfo(mingw.CrtFile).@"enum".fields.len) |i| { if (comp.queued_jobs.mingw_crt_file[i]) { const tag: mingw.CrtFile = @enumFromInt(i); - comp.link_task_queue.startPrelinkItem(); - comp.link_task_wait_group.spawnManager(buildMingwCrtFile, .{ comp, tag, main_progress_node }); - } - } - - { - const astgen_frame = tracy.namedFrame("astgen"); - defer astgen_frame.end(); - - const zir_prog_node = main_progress_node.start("AST Lowering", 0); - defer zir_prog_node.end(); - - var timer = comp.startTimer(); - defer if (timer.finish()) |ns| { - comp.mutex.lock(); - defer comp.mutex.unlock(); - comp.time_report.?.stats.real_ns_files = ns; - }; - - var astgen_wait_group: WaitGroup = .{}; - defer astgen_wait_group.wait(); - - if (comp.zcu) |zcu| { - const gpa = zcu.gpa; - - // We cannot reference `zcu.import_table` after we spawn any `workerUpdateFile` jobs, - // because on single-threaded targets the worker will be run eagerly, meaning the - // `import_table` could be mutated, and not even holding `comp.mutex` will save us. So, - // build up a list of the files to update *before* we spawn any jobs. - var astgen_work_items: std.MultiArrayList(struct { - file_index: Zcu.File.Index, - file: *Zcu.File, - }) = .empty; - defer astgen_work_items.deinit(gpa); - // Not every item in `import_table` will need updating, because some are builtin.zig - // files. However, most will, so let's just reserve sufficient capacity upfront. - try astgen_work_items.ensureTotalCapacity(gpa, zcu.import_table.count()); - for (zcu.import_table.keys()) |file_index| { - const file = zcu.fileByIndex(file_index); - if (file.is_builtin) { - // This is a `builtin.zig`, so updating is redundant. However, we want to make - // sure the file contents are still correct on disk, since it can improve the - // debugging experience better. That job only needs `file`, so we can kick it - // off right now. - comp.thread_pool.spawnWg(&astgen_wait_group, workerUpdateBuiltinFile, .{ comp, file }); - continue; - } - astgen_work_items.appendAssumeCapacity(.{ - .file_index = file_index, - .file = file, - }); - } - - // Now that we're not going to touch `zcu.import_table` again, we can spawn `workerUpdateFile` jobs. - for (astgen_work_items.items(.file_index), astgen_work_items.items(.file)) |file_index, file| { - comp.thread_pool.spawnWgId(&astgen_wait_group, workerUpdateFile, .{ - comp, file, file_index, zir_prog_node, &astgen_wait_group, - }); - } - - // On the other hand, it's fine to directly iterate `zcu.embed_table.keys()` here - // because `workerUpdateEmbedFile` can't invalidate it. The different here is that one - // `@embedFile` can't trigger analysis of a new `@embedFile`! - for (0.., zcu.embed_table.keys()) |ef_index_usize, ef| { - const ef_index: Zcu.EmbedFile.Index = @enumFromInt(ef_index_usize); - comp.thread_pool.spawnWgId(&astgen_wait_group, workerUpdateEmbedFile, .{ - comp, ef_index, ef, - }); - } - } - - while (comp.c_object_work_queue.popFront()) |c_object| { - comp.link_task_queue.startPrelinkItem(); - comp.thread_pool.spawnWg(&comp.link_task_wait_group, workerUpdateCObject, .{ - comp, c_object, main_progress_node, - }); - } - - while (comp.win32_resource_work_queue.popFront()) |win32_resource| { - comp.link_task_queue.startPrelinkItem(); - comp.thread_pool.spawnWg(&comp.link_task_wait_group, workerUpdateWin32Resource, .{ - comp, win32_resource, main_progress_node, - }); - } - } - - if (comp.zcu) |zcu| { - const pt: Zcu.PerThread = .activate(zcu, .main); - defer pt.deactivate(); - - const gpa = zcu.gpa; - - // On an incremental update, a source file might become "dead", in that all imports of - // the file were removed. This could even change what module the file belongs to! As such, - // we do a traversal over the files, to figure out which ones are alive and the modules - // they belong to. - const any_fatal_files = try pt.computeAliveFiles(); - - // If the cache mode is `whole`, add every alive source file to the manifest. - switch (comp.cache_use) { - .whole => |whole| if (whole.cache_manifest) |man| { - for (zcu.alive_files.keys()) |file_index| { - const file = zcu.fileByIndex(file_index); - - switch (file.status) { - .never_loaded => unreachable, // AstGen tried to load it - .retryable_failure => continue, // the file cannot be read; this is a guaranteed error - .astgen_failure, .success => {}, // the file was read successfully - } - - const path = try file.path.toAbsolute(comp.dirs, gpa); - defer gpa.free(path); - - const result = res: { - whole.cache_manifest_mutex.lock(); - defer whole.cache_manifest_mutex.unlock(); - if (file.source) |source| { - break :res man.addFilePostContents(path, source, file.stat); - } else { - break :res man.addFilePost(path); - } - }; - result catch |err| switch (err) { - error.OutOfMemory => |e| return e, - else => { - try pt.reportRetryableFileError(file_index, "unable to update cache: {s}", .{@errorName(err)}); - continue; - }, - }; - } - }, - .none, .incremental => {}, - } - - if (any_fatal_files or - zcu.multi_module_err != null or - zcu.failed_imports.items.len > 0 or - comp.alloc_failure_occurred) - { - // We give up right now! No updating of ZIR refs, no nothing. The idea is that this prevents - // us from invalidating lots of incremental dependencies due to files with e.g. parse errors. - // However, this means our analysis data is invalid, so we want to omit all analysis errors. - zcu.skip_analysis_this_update = true; - return; - } - - if (comp.time_report) |*tr| { - tr.stats.n_reachable_files = @intCast(zcu.alive_files.count()); + prelink_group.async(io, buildMingwCrtFile, .{ comp, tag, main_progress_node }); } - - if (comp.config.incremental) { - const update_zir_refs_node = main_progress_node.start("Update ZIR References", 0); - defer update_zir_refs_node.end(); - try pt.updateZirRefs(); - } - try zcu.flushRetryableFailures(); - - // It's analysis time! Queue up our initial analysis. - for (zcu.analysisRoots()) |mod| { - try comp.queueJob(.{ .analyze_mod = mod }); - } - - zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0); - if (comp.bin_file != null) { - zcu.codegen_prog_node = main_progress_node.start("Code Generation", 0); - } - // We increment `pending_codegen_jobs` so that it doesn't reach 0 until after analysis finishes. - // That prevents the "Code Generation" node from constantly disappearing and reappearing when - // we're probably going to analyze more functions at some point. - assert(zcu.pending_codegen_jobs.swap(1, .monotonic) == 0); // don't let this become 0 until analysis finishes } - // When analysis ends, delete the progress nodes for "Semantic Analysis" and possibly "Code Generation". - defer if (comp.zcu) |zcu| { - zcu.sema_prog_node.end(); - zcu.sema_prog_node = .none; - if (zcu.pending_codegen_jobs.rmw(.Sub, 1, .monotonic) == 1) { - // Decremented to 0, so all done. - zcu.codegen_prog_node.end(); - zcu.codegen_prog_node = .none; - } - }; - - // We aren't going to queue any more prelink tasks. - comp.link_task_queue.finishPrelinkItem(comp); - if (!comp.separateCodegenThreadOk()) { - // Waits until all input files have been parsed. - comp.link_task_wait_group.wait(); - comp.link_task_wait_group.reset(); - std.log.scoped(.link).debug("finished waiting for link_task_wait_group", .{}); + while (comp.c_object_work_queue.popFront()) |c_object| { + prelink_group.async(io, workerUpdateCObject, .{ + comp, c_object, main_progress_node, + }); } - if (comp.zcu != null) { - // Start the timer for the "decls" part of the pipeline (Sema, CodeGen, link). - decl_work_timer = comp.startTimer(); + while (comp.win32_resource_work_queue.popFront()) |win32_resource| { + prelink_group.async(io, workerUpdateWin32Resource, .{ + comp, win32_resource, main_progress_node, + }); } - work: while (true) { - for (&comp.work_queues) |*work_queue| if (work_queue.popFront()) |job| { - try processOneJob(@intFromEnum(Zcu.PerThread.Id.main), comp, job); - continue :work; - }; - if (comp.zcu) |zcu| { - // If there's no work queued, check if there's anything outdated - // which we need to work on, and queue it if so. - if (try zcu.findOutdatedToAnalyze()) |outdated| { - try comp.queueJob(switch (outdated.unwrap()) { - .func => |f| .{ .analyze_func = f }, - .memoized_state, - .@"comptime", - .nav_ty, - .nav_val, - .type, - => .{ .analyze_comptime_unit = outdated }, - }); - continue; - } - zcu.sema_prog_node.end(); - zcu.sema_prog_node = .none; - } - break; - } + prelink_group.await(io) catch |err| switch (err) { + error.Canceled => unreachable, // see swapCancelProtection above + }; + comp.link_queue.finishPrelinkQueue(comp) catch |err| switch (err) { + error.Canceled => unreachable, // see swapCancelProtection above + }; } const JobError = Allocator.Error || Io.Cancelable; @@ -5022,58 +5117,38 @@ pub fn queueJobs(comp: *Compilation, jobs: []const Job) !void { for (jobs) |job| try comp.queueJob(job); } -fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void { +fn processOneJob( + tid: usize, + comp: *Compilation, + job: Job, +) JobError!void { switch (job) { .codegen_func => |func| { const zcu = comp.zcu.?; const gpa = zcu.gpa; - var air = func.air; - errdefer { - zcu.codegen_prog_node.completeOne(); - comp.link_prog_node.completeOne(); - air.deinit(gpa); - } - if (!air.typesFullyResolved(zcu)) { + var owned_air: ?Air = func.air; + defer if (owned_air) |*air| air.deinit(gpa); + + if (!owned_air.?.typesFullyResolved(zcu)) { // Type resolution failed in a way which affects this function. This is a transitive // failure, but it doesn't need recording, because this function semantically depends // on the failed type, so when it is changed the function is updated. zcu.codegen_prog_node.completeOne(); comp.link_prog_node.completeOne(); - air.deinit(gpa); return; } - const shared_mir = try gpa.create(link.ZcuTask.LinkFunc.SharedMir); - shared_mir.* = .{ - .status = .init(.pending), - .value = undefined, - }; - assert(zcu.pending_codegen_jobs.rmw(.Add, 1, .monotonic) > 0); // the "Code Generation" node hasn't been ended - // This value is used as a heuristic to avoid queueing too much AIR/MIR at once (hence - // using a lot of memory). If this would cause too many AIR bytes to be in-flight, we - // will block on the `dispatchZcuLinkTask` call below. - const air_bytes: u32 = @intCast(air.instructions.len * 5 + air.extra.items.len * 4); - if (comp.separateCodegenThreadOk()) { - // `workerZcuCodegen` takes ownership of `air`. - comp.thread_pool.spawnWgId(&comp.link_task_wait_group, workerZcuCodegen, .{ comp, func.func, air, shared_mir }); - comp.dispatchZcuLinkTask(tid, .{ .link_func = .{ - .func = func.func, - .mir = shared_mir, - .air_bytes = air_bytes, - } }); - } else { - { - const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid)); - defer pt.deactivate(); - pt.runCodegen(func.func, &air, shared_mir); - } - assert(shared_mir.status.load(.monotonic) != .pending); - comp.dispatchZcuLinkTask(tid, .{ .link_func = .{ - .func = func.func, - .mir = shared_mir, - .air_bytes = air_bytes, - } }); - air.deinit(gpa); - } + + // Some linkers need to refer to the AIR. In that case, the linker is not running + // concurrently, so we'll just keep ownership of the AIR for ourselves instead of + // letting the codegen job destroy it. + const disown_air = zcu.backendSupportsFeature(.separate_thread); + + // Begin the codegen task. If the codegen/link queue is backed up, this might + // block until the linker is able to process some tasks. + const codegen_task = try zcu.codegen_task_pool.start(zcu, func.func, &owned_air.?, disown_air); + if (disown_air) owned_air = null; + + try comp.link_queue.enqueueZcu(comp, tid, .{ .link_func = codegen_task }); }, .link_nav => |nav_index| { const zcu = comp.zcu.?; @@ -5093,7 +5168,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void { comp.link_prog_node.completeOne(); return; } - comp.dispatchZcuLinkTask(tid, .{ .link_nav = nav_index }); + try comp.link_queue.enqueueZcu(comp, tid, .{ .link_nav = nav_index }); }, .link_type => |ty| { const zcu = comp.zcu.?; @@ -5105,10 +5180,10 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void { comp.link_prog_node.completeOne(); return; } - comp.dispatchZcuLinkTask(tid, .{ .link_type = ty }); + try comp.link_queue.enqueueZcu(comp, tid, .{ .link_type = ty }); }, - .update_line_number => |ti| { - comp.dispatchZcuLinkTask(tid, .{ .update_line_number = ti }); + .update_line_number => |tracked_inst| { + try comp.link_queue.enqueueZcu(comp, tid, .{ .update_line_number = tracked_inst }); }, .analyze_func => |func| { const named_frame = tracy.namedFrame("analyze_func"); @@ -5202,10 +5277,43 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void { } } -pub fn separateCodegenThreadOk(comp: *const Compilation) bool { - if (InternPool.single_threaded) return false; - const zcu = comp.zcu orelse return true; - return zcu.backendSupportsFeature(.separate_thread); +fn createDepFile(comp: *Compilation, dep_file: []const u8, bin_file: Cache.Path) anyerror!void { + const io = comp.io; + + var af = try Io.Dir.cwd().createFileAtomic(io, dep_file, .{ .replace = true }); + defer af.deinit(io); + + var buf: [4096]u8 = undefined; + var file_writer = af.file.writer(io, &buf); + + comp.writeDepFile(bin_file, &file_writer.interface) catch |err| switch (err) { + error.WriteFailed => return file_writer.err.?, + }; + try file_writer.flush(); + try af.replace(io); +} + +fn writeDepFile( + comp: *Compilation, + bin_file: Cache.Path, + w: *std.Io.Writer, +) std.Io.Writer.Error!void { + const prefixes = comp.cache_parent.prefixes(); + const fsi = comp.file_system_inputs.?.items; + + try w.print("{f}:", .{bin_file}); + + { + var it = std.mem.splitScalar(u8, fsi, 0); + while (it.next()) |input| try w.print(" \\\n {f}{s}", .{ prefixes[input[0] - 1], input[1..] }); + } + + { + var it = std.mem.splitScalar(u8, fsi, 0); + while (it.next()) |input| try w.print("\n\n{f}{s}:", .{ prefixes[input[0] - 1], input[1..] }); + } + + try w.writeByte('\n'); } fn workerDocsCopy(comp: *Compilation) void { @@ -5218,39 +5326,35 @@ fn workerDocsCopy(comp: *Compilation) void { fn docsCopyFallible(comp: *Compilation) anyerror!void { const zcu = comp.zcu orelse return comp.lockAndSetMiscFailure(.docs_copy, "no Zig code to document", .{}); + const io = comp.io; const docs_path = comp.resolveEmitPath(comp.emit_docs.?); - var out_dir = docs_path.root_dir.handle.makeOpenPath(docs_path.sub_path, .{}) catch |err| { + var out_dir = docs_path.root_dir.handle.createDirPathOpen(io, docs_path.sub_path, .{}) catch |err| { return comp.lockAndSetMiscFailure( .docs_copy, "unable to create output directory '{f}': {s}", .{ docs_path, @errorName(err) }, ); }; - defer out_dir.close(); + defer out_dir.close(io); for (&[_][]const u8{ "docs/main.js", "docs/index.html" }) |sub_path| { const basename = fs.path.basename(sub_path); - comp.dirs.zig_lib.handle.copyFile(sub_path, out_dir, basename, .{}) catch |err| { - comp.lockAndSetMiscFailure(.docs_copy, "unable to copy {s}: {s}", .{ - sub_path, - @errorName(err), - }); - return; - }; + comp.dirs.zig_lib.handle.copyFile(sub_path, out_dir, basename, io, .{}) catch |err| + return comp.lockAndSetMiscFailure(.docs_copy, "unable to copy {s}: {t}", .{ sub_path, err }); } - var tar_file = out_dir.createFile("sources.tar", .{}) catch |err| { + var tar_file = out_dir.createFile(io, "sources.tar", .{}) catch |err| { return comp.lockAndSetMiscFailure( .docs_copy, "unable to create '{f}/sources.tar': {s}", .{ docs_path, @errorName(err) }, ); }; - defer tar_file.close(); + defer tar_file.close(io); var buffer: [1024]u8 = undefined; - var tar_file_writer = tar_file.writer(&buffer); + var tar_file_writer = tar_file.writer(io, &buffer); var seen_table: std.AutoArrayHashMapUnmanaged(*Package.Module, []const u8) = .empty; defer seen_table.deinit(comp.gpa); @@ -5281,17 +5385,17 @@ fn docsCopyModule( comp: *Compilation, module: *Package.Module, name: []const u8, - tar_file_writer: *fs.File.Writer, + tar_file_writer: *Io.File.Writer, ) !void { const io = comp.io; const root = module.root; var mod_dir = d: { const root_dir, const sub_path = root.openInfo(comp.dirs); - break :d root_dir.openDir(sub_path, .{ .iterate = true }); + break :d root_dir.openDir(io, sub_path, .{ .iterate = true }); } catch |err| { return comp.lockAndSetMiscFailure(.docs_copy, "unable to open directory '{f}': {t}", .{ root.fmt(comp), err }); }; - defer mod_dir.close(); + defer mod_dir.close(io); var walker = try mod_dir.walk(comp.gpa); defer walker.deinit(); @@ -5301,7 +5405,7 @@ fn docsCopyModule( var buffer: [1024]u8 = undefined; - while (try walker.next()) |entry| { + while (try walker.next(io)) |entry| { switch (entry.kind) { .file => { if (!std.mem.endsWith(u8, entry.basename, ".zig")) continue; @@ -5310,14 +5414,14 @@ fn docsCopyModule( }, else => continue, } - var file = mod_dir.openFile(entry.path, .{}) catch |err| { + var file = mod_dir.openFile(io, entry.path, .{}) catch |err| { return comp.lockAndSetMiscFailure(.docs_copy, "unable to open {f}{s}: {t}", .{ root.fmt(comp), entry.path, err, }); }; - defer file.close(); - const stat = try file.stat(); - var file_reader: fs.File.Reader = .initSize(file.adaptToNewApi(), io, &buffer, stat.size); + defer file.close(io); + const stat = try file.stat(io); + var file_reader: Io.File.Reader = .initSize(file, io, &buffer, stat.size); archiver.writeFileTimestamp(entry.path, &file_reader, stat.mtime) catch |err| { return comp.lockAndSetMiscFailure(.docs_copy, "unable to archive {f}{s}: {t}", .{ @@ -5425,6 +5529,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU var sub_create_diag: CreateDiagnostic = undefined; const sub_compilation = Compilation.create(gpa, arena, io, &sub_create_diag, .{ + .thread_limit = comp.thread_limit, .dirs = dirs, .self_exe_path = comp.self_exe_path, .config = config, @@ -5432,7 +5537,6 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU .entry = .disabled, .cache_mode = .whole, .root_name = root_name, - .thread_pool = comp.thread_pool, .libc_installation = comp.libc_installation, .emit_bin = .yes_cache, .verbose_cc = comp.verbose_cc, @@ -5444,6 +5548,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU .verbose_llvm_bc = comp.verbose_llvm_bc, .verbose_cimport = comp.verbose_cimport, .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, + .environ_map = comp.environ_map, }) catch |err| switch (err) { error.CreateFail => { comp.lockAndSetMiscFailure(.docs_wasm, "sub-compilation of docs_wasm failed: {f}", .{sub_create_diag}); @@ -5456,13 +5561,13 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU try comp.updateSubCompilation(sub_compilation, .docs_wasm, prog_node); var crt_file = try sub_compilation.toCrtFile(); - defer crt_file.deinit(gpa); + defer crt_file.deinit(gpa, io); const docs_bin_file = crt_file.full_object_path; assert(docs_bin_file.sub_path.len > 0); // emitted binary is not a directory const docs_path = comp.resolveEmitPath(comp.emit_docs.?); - var out_dir = docs_path.root_dir.handle.makeOpenPath(docs_path.sub_path, .{}) catch |err| { + var out_dir = docs_path.root_dir.handle.createDirPathOpen(io, docs_path.sub_path, .{}) catch |err| { comp.lockAndSetMiscFailure( .docs_copy, "unable to create output directory '{f}': {t}", @@ -5470,12 +5575,14 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU ); return error.AlreadyReported; }; - defer out_dir.close(); + defer out_dir.close(io); - crt_file.full_object_path.root_dir.handle.copyFile( + Io.Dir.copyFile( + crt_file.full_object_path.root_dir.handle, crt_file.full_object_path.sub_path, out_dir, "main.wasm", + io, .{}, ) catch |err| { comp.lockAndSetMiscFailure(.docs_copy, "unable to copy '{f}' to '{f}': {t}", .{ @@ -5486,13 +5593,15 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU } fn workerUpdateFile( - tid: usize, comp: *Compilation, file: *Zcu.File, file_index: Zcu.File.Index, prog_node: std.Progress.Node, - wg: *WaitGroup, + group: *Io.Group, ) void { + const tid = Compilation.getTid(); + const io = comp.io; + const child_prog_node = prog_node.start(fs.path.basename(file.path.sub_path), 0); defer child_prog_node.end(); @@ -5501,8 +5610,8 @@ fn workerUpdateFile( pt.updateFile(file_index, file) catch |err| { pt.reportRetryableFileError(file_index, "unable to load '{s}': {s}", .{ fs.path.basename(file.path.sub_path), @errorName(err) }) catch |oom| switch (oom) { error.OutOfMemory => { - comp.mutex.lock(); - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); comp.setAllocFailure(); }, }; @@ -5532,14 +5641,14 @@ fn workerUpdateFile( if (pt.discoverImport(file.path, import_path)) |res| switch (res) { .module, .existing_file => {}, .new_file => |new| { - comp.thread_pool.spawnWgId(wg, workerUpdateFile, .{ - comp, new.file, new.index, prog_node, wg, + group.async(io, workerUpdateFile, .{ + comp, new.file, new.index, prog_node, group, }); }, } else |err| switch (err) { error.OutOfMemory => { - comp.mutex.lock(); - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); comp.setAllocFailure(); }, } @@ -5555,17 +5664,20 @@ fn workerUpdateBuiltinFile(comp: *Compilation, file: *Zcu.File) void { ); } -fn workerUpdateEmbedFile(tid: usize, comp: *Compilation, ef_index: Zcu.EmbedFile.Index, ef: *Zcu.EmbedFile) void { +fn workerUpdateEmbedFile(comp: *Compilation, ef_index: Zcu.EmbedFile.Index, ef: *Zcu.EmbedFile) void { + const tid = Compilation.getTid(); + const io = comp.io; comp.detectEmbedFileUpdate(@enumFromInt(tid), ef_index, ef) catch |err| switch (err) { error.OutOfMemory => { - comp.mutex.lock(); - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); comp.setAllocFailure(); }, }; } fn detectEmbedFileUpdate(comp: *Compilation, tid: Zcu.PerThread.Id, ef_index: Zcu.EmbedFile.Index, ef: *Zcu.EmbedFile) !void { + const io = comp.io; const zcu = comp.zcu.?; const pt: Zcu.PerThread = .activate(zcu, tid); defer pt.deactivate(); @@ -5578,8 +5690,8 @@ fn detectEmbedFileUpdate(comp: *Compilation, tid: Zcu.PerThread.Id, ef_index: Zc if (ef.val != .none and ef.val == old_val) return; // success, value unchanged if (ef.val == .none and old_val == .none and ef.err == old_err) return; // failure, error unchanged - comp.mutex.lock(); - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); try zcu.markDependeeOutdated(.not_marked_po, .{ .embed_file = ef_index }); } @@ -5639,16 +5751,21 @@ pub fn translateC( translated_basename: []const u8, owner_mod: *Package.Module, prog_node: std.Progress.Node, + environ_map: *const std.process.Environ.Map, ) !CImportResult { dev.check(.translate_c_command); const gpa = comp.gpa; const io = comp.io; - const tmp_basename = std.fmt.hex(std.crypto.random.int(u64)); + const tmp_basename = r: { + var x: u64 = undefined; + io.random(@ptrCast(&x)); + break :r std.fmt.hex(x); + }; const tmp_sub_path = "tmp" ++ fs.path.sep_str ++ tmp_basename; const cache_dir = comp.dirs.local_cache.handle; - var cache_tmp_dir = try cache_dir.makeOpenPath(tmp_sub_path, .{}); - defer cache_tmp_dir.close(); + var cache_tmp_dir = try cache_dir.createDirPathOpen(io, tmp_sub_path, .{}); + defer cache_tmp_dir.close(io); const translated_path = try comp.dirs.local_cache.join(arena, &.{ tmp_sub_path, translated_basename }); const source_path = switch (source) { @@ -5657,7 +5774,7 @@ pub fn translateC( const out_h_sub_path = tmp_sub_path ++ fs.path.sep_str ++ cimport_basename; const out_h_path = try comp.dirs.local_cache.join(arena, &.{out_h_sub_path}); if (comp.verbose_cimport) log.info("writing C import source to {s}", .{out_h_path}); - try cache_dir.writeFile(.{ .sub_path = out_h_sub_path, .data = c_src }); + try cache_dir.writeFile(io, .{ .sub_path = out_h_sub_path, .data = c_src }); break :path out_h_path; }, .path => |p| p, @@ -5704,11 +5821,11 @@ pub fn translateC( try argv.appendSlice(comp.global_cc_argv); try argv.appendSlice(owner_mod.cc_argv); try argv.appendSlice(&.{ source_path, "-o", translated_path }); - if (comp.verbose_cimport) dump_argv(argv.items); + if (comp.verbose_cimport) try dumpArgv(io, argv.items); } var stdout: []u8 = undefined; - try @import("main.zig").translateC(gpa, arena, io, argv.items, prog_node, &stdout); + try @import("main.zig").translateC(gpa, arena, io, argv.items, environ_map, prog_node, &stdout); if (out_dep_path) |dep_file_path| add_deps: { if (comp.verbose_cimport) log.info("processing dep file at {s}", .{dep_file_path}); @@ -5722,15 +5839,15 @@ pub fn translateC( switch (comp.cache_use) { .whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| { - whole.cache_manifest_mutex.lock(); - defer whole.cache_manifest_mutex.unlock(); + try whole.cache_manifest_mutex.lock(io); + defer whole.cache_manifest_mutex.unlock(io); try whole_cache_manifest.addDepFilePost(cache_tmp_dir, dep_basename); }, .incremental, .none => {}, } // Just to save disk space, we delete the file because it is never needed again. - cache_tmp_dir.deleteFile(dep_basename) catch |err| { + cache_tmp_dir.deleteFile(io, dep_basename) catch |err| { log.warn("failed to delete '{s}': {t}", .{ dep_file_path, err }); }; } @@ -5760,7 +5877,7 @@ pub fn translateC( const o_sub_path = "o" ++ fs.path.sep_str ++ hex_digest; if (comp.verbose_cimport) log.info("renaming {s} to {s}", .{ tmp_sub_path, o_sub_path }); - try renameTmpIntoCache(comp.dirs.local_cache, tmp_sub_path, o_sub_path); + try renameTmpIntoCache(io, comp.dirs.local_cache, tmp_sub_path, o_sub_path); return .{ .digest = bin_digest, @@ -5795,7 +5912,8 @@ pub fn cImport( defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - break :result try comp.translateC( + break :result try translateC( + comp, arena, &man, .c, @@ -5803,6 +5921,7 @@ pub fn cImport( translated_basename, owner_mod, prog_node, + comp.environ_map, ); }; @@ -5824,7 +5943,6 @@ fn workerUpdateCObject( c_object: *CObject, progress_node: std.Progress.Node, ) void { - defer comp.link_task_queue.finishPrelinkItem(comp); comp.updateCObject(c_object, progress_node) catch |err| switch (err) { error.AnalysisFail => return, else => { @@ -5842,7 +5960,6 @@ fn workerUpdateWin32Resource( win32_resource: *Win32Resource, progress_node: std.Progress.Node, ) void { - defer comp.link_task_queue.finishPrelinkItem(comp); comp.updateWin32Resource(win32_resource, progress_node) catch |err| switch (err) { error.AnalysisFail => return, else => { @@ -5860,21 +5977,6 @@ pub const RtOptions = struct { allow_lto: bool = true, }; -fn workerZcuCodegen( - tid: usize, - comp: *Compilation, - func_index: InternPool.Index, - orig_air: Air, - out: *link.ZcuTask.LinkFunc.SharedMir, -) void { - var air = orig_air; - // We own `air` now, so we are responsbile for freeing it. - defer air.deinit(comp.gpa); - const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid)); - defer pt.deactivate(); - pt.runCodegen(func_index, &air, out); -} - fn buildRt( comp: *Compilation, root_source_name: []const u8, @@ -5886,7 +5988,6 @@ fn buildRt( options: RtOptions, out: *?CrtFile, ) void { - defer comp.link_task_queue.finishPrelinkItem(comp); comp.buildOutputFromZig( root_source_name, root_name, @@ -5905,7 +6006,6 @@ fn buildRt( } fn buildMuslCrtFile(comp: *Compilation, crt_file: musl.CrtFile, prog_node: std.Progress.Node) void { - defer comp.link_task_queue.finishPrelinkItem(comp); if (musl.buildCrtFile(comp, crt_file, prog_node)) |_| { comp.queued_jobs.musl_crt_file[@intFromEnum(crt_file)] = false; } else |err| switch (err) { @@ -5917,7 +6017,6 @@ fn buildMuslCrtFile(comp: *Compilation, crt_file: musl.CrtFile, prog_node: std.P } fn buildGlibcCrtFile(comp: *Compilation, crt_file: glibc.CrtFile, prog_node: std.Progress.Node) void { - defer comp.link_task_queue.finishPrelinkItem(comp); if (glibc.buildCrtFile(comp, crt_file, prog_node)) |_| { comp.queued_jobs.glibc_crt_file[@intFromEnum(crt_file)] = false; } else |err| switch (err) { @@ -5929,7 +6028,6 @@ fn buildGlibcCrtFile(comp: *Compilation, crt_file: glibc.CrtFile, prog_node: std } fn buildGlibcSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) void { - defer comp.link_task_queue.finishPrelinkItem(comp); if (glibc.buildSharedObjects(comp, prog_node)) |_| { // The job should no longer be queued up since it succeeded. comp.queued_jobs.glibc_shared_objects = false; @@ -5940,7 +6038,6 @@ fn buildGlibcSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) voi } fn buildFreeBSDCrtFile(comp: *Compilation, crt_file: freebsd.CrtFile, prog_node: std.Progress.Node) void { - defer comp.link_task_queue.finishPrelinkItem(comp); if (freebsd.buildCrtFile(comp, crt_file, prog_node)) |_| { comp.queued_jobs.freebsd_crt_file[@intFromEnum(crt_file)] = false; } else |err| switch (err) { @@ -5952,7 +6049,6 @@ fn buildFreeBSDCrtFile(comp: *Compilation, crt_file: freebsd.CrtFile, prog_node: } fn buildFreeBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) void { - defer comp.link_task_queue.finishPrelinkItem(comp); if (freebsd.buildSharedObjects(comp, prog_node)) |_| { // The job should no longer be queued up since it succeeded. comp.queued_jobs.freebsd_shared_objects = false; @@ -5965,7 +6061,6 @@ fn buildFreeBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) v } fn buildNetBSDCrtFile(comp: *Compilation, crt_file: netbsd.CrtFile, prog_node: std.Progress.Node) void { - defer comp.link_task_queue.finishPrelinkItem(comp); if (netbsd.buildCrtFile(comp, crt_file, prog_node)) |_| { comp.queued_jobs.netbsd_crt_file[@intFromEnum(crt_file)] = false; } else |err| switch (err) { @@ -5977,7 +6072,6 @@ fn buildNetBSDCrtFile(comp: *Compilation, crt_file: netbsd.CrtFile, prog_node: s } fn buildNetBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) void { - defer comp.link_task_queue.finishPrelinkItem(comp); if (netbsd.buildSharedObjects(comp, prog_node)) |_| { // The job should no longer be queued up since it succeeded. comp.queued_jobs.netbsd_shared_objects = false; @@ -5989,8 +6083,30 @@ fn buildNetBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) vo } } +fn buildOpenBSDCrtFile(comp: *Compilation, crt_file: openbsd.CrtFile, prog_node: std.Progress.Node) void { + if (openbsd.buildCrtFile(comp, crt_file, prog_node)) |_| { + comp.queued_jobs.openbsd_crt_file[@intFromEnum(crt_file)] = false; + } else |err| switch (err) { + error.AlreadyReported => return, + else => comp.lockAndSetMiscFailure(.openbsd_crt_file, "unable to build OpenBSD {s}: {s}", .{ + @tagName(crt_file), @errorName(err), + }), + } +} + +fn buildOpenBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) void { + if (openbsd.buildSharedObjects(comp, prog_node)) |_| { + // The job should no longer be queued up since it succeeded. + comp.queued_jobs.openbsd_shared_objects = false; + } else |err| switch (err) { + error.AlreadyReported => return, + else => comp.lockAndSetMiscFailure(.openbsd_shared_objects, "unable to build OpenBSD libc shared objects: {s}", .{ + @errorName(err), + }), + } +} + fn buildMingwCrtFile(comp: *Compilation, crt_file: mingw.CrtFile, prog_node: std.Progress.Node) void { - defer comp.link_task_queue.finishPrelinkItem(comp); if (mingw.buildCrtFile(comp, crt_file, prog_node)) |_| { comp.queued_jobs.mingw_crt_file[@intFromEnum(crt_file)] = false; } else |err| switch (err) { @@ -6002,7 +6118,6 @@ fn buildMingwCrtFile(comp: *Compilation, crt_file: mingw.CrtFile, prog_node: std } fn buildWasiLibcCrtFile(comp: *Compilation, crt_file: wasi_libc.CrtFile, prog_node: std.Progress.Node) void { - defer comp.link_task_queue.finishPrelinkItem(comp); if (wasi_libc.buildCrtFile(comp, crt_file, prog_node)) |_| { comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(crt_file)] = false; } else |err| switch (err) { @@ -6014,7 +6129,6 @@ fn buildWasiLibcCrtFile(comp: *Compilation, crt_file: wasi_libc.CrtFile, prog_no } fn buildLibUnwind(comp: *Compilation, prog_node: std.Progress.Node) void { - defer comp.link_task_queue.finishPrelinkItem(comp); if (libunwind.buildStaticLib(comp, prog_node)) |_| { comp.queued_jobs.libunwind = false; } else |err| switch (err) { @@ -6024,7 +6138,6 @@ fn buildLibUnwind(comp: *Compilation, prog_node: std.Progress.Node) void { } fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) void { - defer comp.link_task_queue.finishPrelinkItem(comp); if (libcxx.buildLibCxx(comp, prog_node)) |_| { comp.queued_jobs.libcxx = false; } else |err| switch (err) { @@ -6034,7 +6147,6 @@ fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) void { } fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) void { - defer comp.link_task_queue.finishPrelinkItem(comp); if (libcxx.buildLibCxxAbi(comp, prog_node)) |_| { comp.queued_jobs.libcxxabi = false; } else |err| switch (err) { @@ -6044,7 +6156,6 @@ fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) void { } fn buildLibTsan(comp: *Compilation, prog_node: std.Progress.Node) void { - defer comp.link_task_queue.finishPrelinkItem(comp); if (libtsan.buildTsan(comp, prog_node)) |_| { comp.queued_jobs.libtsan = false; } else |err| switch (err) { @@ -6054,7 +6165,6 @@ fn buildLibTsan(comp: *Compilation, prog_node: std.Progress.Node) void { } fn buildLibZigC(comp: *Compilation, prog_node: std.Progress.Node) void { - defer comp.link_task_queue.finishPrelinkItem(comp); comp.buildOutputFromZig( "c.zig", "zigc", @@ -6084,6 +6194,8 @@ fn reportRetryableWin32ResourceError( win32_resource: *Win32Resource, err: anyerror, ) error{OutOfMemory}!void { + const io = comp.io; + win32_resource.status = .failure_retryable; var bundle: ErrorBundle.Wip = undefined; @@ -6105,8 +6217,8 @@ fn reportRetryableWin32ResourceError( }); const finished_bundle = try bundle.toOwnedBundle(""); { - comp.mutex.lock(); - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); try comp.failed_win32_resources.putNoClobber(comp.gpa, win32_resource, finished_bundle); } } @@ -6129,10 +6241,10 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr const gpa = comp.gpa; const io = comp.io; - if (c_object.clearStatus(gpa)) { + if (c_object.clearStatus(gpa, io)) { // There was previous failure. - comp.mutex.lock(); - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); // If the failure was OOM, there will not be an entry here, so we do // not assert discard. _ = comp.failed_c_objects.swapRemove(c_object); @@ -6213,7 +6325,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr // that we could "tail call" clang by doing an execve, and any use of // the caching system would actually be problematic since the user is // presumably doing their own caching by using dep file flags. - if (std.process.can_execv and direct_o and + if (std.process.can_replace and direct_o and comp.disable_c_depfile and comp.clang_passthrough_mode) { try comp.addCCArgs(arena, &argv, ext, null, c_object.src.owner); @@ -6242,18 +6354,18 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr } if (comp.verbose_cc) { - dump_argv(argv.items); + try dumpArgv(io, argv.items); } - const err = std.process.execv(arena, argv.items); - fatal("unable to execv clang: {s}", .{@errorName(err)}); + const err = std.process.replace(io, .{ .argv = argv.items }); + fatal("unable to replace process with clang: {t}", .{err}); } // We can't know the digest until we do the C compiler invocation, // so we need a temporary filename. const out_obj_path = try comp.tmpFilePath(arena, o_basename); - var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.makeOpenPath("tmp", .{}); - defer zig_cache_tmp_dir.close(); + var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.createDirPathOpen(io, "tmp", .{}); + defer zig_cache_tmp_dir.close(io); const out_diag_path = if (comp.clang_passthrough_mode or !ext.clangSupportsDiagnostics()) null @@ -6288,30 +6400,37 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr } if (comp.verbose_cc) { - dump_argv(argv.items); + try dumpArgv(io, argv.items); } // Just to save disk space, we delete the files that are never needed again. - defer if (out_diag_path) |diag_file_path| zig_cache_tmp_dir.deleteFile(fs.path.basename(diag_file_path)) catch |err| switch (err) { + defer if (out_diag_path) |diag_file_path| zig_cache_tmp_dir.deleteFile(io, fs.path.basename(diag_file_path)) catch |err| switch (err) { error.FileNotFound => {}, // the file wasn't created due to an error we reported else => log.warn("failed to delete '{s}': {s}", .{ diag_file_path, @errorName(err) }), }; - defer if (out_dep_path) |dep_file_path| zig_cache_tmp_dir.deleteFile(fs.path.basename(dep_file_path)) catch |err| switch (err) { + defer if (out_dep_path) |dep_file_path| zig_cache_tmp_dir.deleteFile(io, fs.path.basename(dep_file_path)) catch |err| switch (err) { error.FileNotFound => {}, // the file wasn't created due to an error we reported else => log.warn("failed to delete '{s}': {s}", .{ dep_file_path, @errorName(err) }), }; if (std.process.can_spawn) { - var child = std.process.Child.init(argv.items, arena); if (comp.clang_passthrough_mode) { - child.stdin_behavior = .Inherit; - child.stdout_behavior = .Inherit; - child.stderr_behavior = .Inherit; - - const term = child.spawnAndWait() catch |err| { - return comp.failCObj(c_object, "failed to spawn zig clang (passthrough mode) {s}: {s}", .{ argv.items[0], @errorName(err) }); + var child = std.process.spawn(io, .{ + .argv = argv.items, + .stdin = .inherit, + .stdout = .inherit, + .stderr = .inherit, + }) catch |err| { + return comp.failCObj(c_object, "failed to spawn zig clang (passthrough mode) {s}: {t}", .{ + argv.items[0], err, + }); + }; + const term = child.wait(io) catch |err| { + return comp.failCObj(c_object, "failed to wait zig clang (passthrough mode) {s}: {t}", .{ + argv.items[0], err, + }); }; switch (term) { - .Exited => |code| { + .exited => |code| { if (code != 0) { std.process.exit(code); } @@ -6321,21 +6440,21 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr else => std.process.abort(), } } else { - child.stdin_behavior = .Ignore; - child.stdout_behavior = .Ignore; - child.stderr_behavior = .Pipe; - - try child.spawn(); + var child = try std.process.spawn(io, .{ + .argv = argv.items, + .stdin = .ignore, + .stdout = .ignore, + .stderr = .pipe, + }); var stderr_reader = child.stderr.?.readerStreaming(io, &.{}); const stderr = try stderr_reader.interface.allocRemaining(arena, .limited(std.math.maxInt(u32))); - const term = child.wait() catch |err| { - return comp.failCObj(c_object, "failed to spawn zig clang {s}: {s}", .{ argv.items[0], @errorName(err) }); - }; + const term = child.wait(io) catch |err| + return comp.failCObj(c_object, "failed to spawn zig clang {s}: {t}", .{ argv.items[0], err }); switch (term) { - .Exited => |code| if (code != 0) if (out_diag_path) |diag_file_path| { + .exited => |code| if (code != 0) if (out_diag_path) |diag_file_path| { const bundle = CObject.Diag.Bundle.parse(gpa, io, diag_file_path) catch |err| { log.err("{}: failed to parse clang diagnostics: {s}", .{ err, stderr }); return comp.failCObj(c_object, "clang exited with code {d}", .{code}); @@ -6345,6 +6464,10 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr log.err("clang failed with stderr: {s}", .{stderr}); return comp.failCObj(c_object, "clang exited with code {d}", .{code}); }, + .signal => |sig| { + log.err("clang failed with stderr: {s}", .{stderr}); + return comp.failCObj(c_object, "clang terminated with signal {t}", .{sig}); + }, else => { log.err("clang terminated with stderr: {s}", .{stderr}); return comp.failCObj(c_object, "clang terminated unexpectedly", .{}); @@ -6369,13 +6492,41 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr if (out_dep_path) |dep_file_path| { const dep_basename = fs.path.basename(dep_file_path); + + if (comp.file_system_inputs != null) { + // Use the same file size limit as the cache code does for dependency files. + const dep_file_contents = try zig_cache_tmp_dir.readFileAlloc(io, dep_basename, gpa, .limited(Cache.manifest_file_size_max)); + defer gpa.free(dep_file_contents); + + var str_buf: std.ArrayList(u8) = .empty; + defer str_buf.deinit(gpa); + + var it: std.Build.Cache.DepTokenizer = .{ .bytes = dep_file_contents }; + while (it.next()) |token| { + const input_path: Compilation.Path = switch (token) { + .target, .target_must_resolve => continue, + .prereq => |file_path| try .fromUnresolved(arena, comp.dirs, &.{file_path}), + .prereq_must_resolve => p: { + try token.resolve(gpa, &str_buf); + break :p try .fromUnresolved(arena, comp.dirs, &.{str_buf.items}); + }, + else => |err| { + try err.printError(gpa, &str_buf); + log.err("failed parsing {s}: {s}", .{ dep_basename, str_buf.items }); + return error.InvalidDepFile; + }, + }; + try comp.appendFileSystemInput(input_path); + } + } + // Add the files depended on to the cache system. try man.addDepFilePost(zig_cache_tmp_dir, dep_basename); switch (comp.cache_use) { .whole => |whole| { if (whole.cache_manifest) |whole_cache_manifest| { - whole.cache_manifest_mutex.lock(); - defer whole.cache_manifest_mutex.unlock(); + try whole.cache_manifest_mutex.lock(io); + defer whole.cache_manifest_mutex.unlock(io); try whole_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename); } }, @@ -6389,10 +6540,10 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr // Rename into place. const digest = man.final(); const o_sub_path = try fs.path.join(arena, &[_][]const u8{ "o", &digest }); - var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(o_sub_path, .{}); - defer o_dir.close(); + var o_dir = try comp.dirs.local_cache.handle.createDirPathOpen(io, o_sub_path, .{}); + defer o_dir.close(io); const tmp_basename = fs.path.basename(out_obj_path); - try fs.rename(zig_cache_tmp_dir, tmp_basename, o_dir, o_basename); + try Io.Dir.rename(zig_cache_tmp_dir, tmp_basename, o_dir, o_basename, io); break :blk digest; }; @@ -6420,7 +6571,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr }, }; - comp.queuePrelinkTasks(&.{.{ .load_object = c_object.status.success.object_path }}); + try comp.queuePrelinkTasks(&.{.{ .load_object = c_object.status.success.object_path }}); } fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32_resource_prog_node: std.Progress.Node) !void { @@ -6442,14 +6593,16 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 log.debug("updating win32 resource: {s}", .{src_path}); + const io = comp.io; + var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - if (win32_resource.clearStatus(comp.gpa)) { + if (win32_resource.clearStatus(comp.gpa, io)) { // There was previous failure. - comp.mutex.lock(); - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); // If the failure was OOM, there will not be an entry here, so we do // not assert discard. _ = comp.failed_win32_resources.swapRemove(win32_resource); @@ -6476,8 +6629,8 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 const digest = man.final(); const o_sub_path = try fs.path.join(arena, &.{ "o", &digest }); - var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(o_sub_path, .{}); - defer o_dir.close(); + var o_dir = try comp.dirs.local_cache.handle.createDirPathOpen(io, o_sub_path, .{}); + defer o_dir.close(io); const in_rc_path = try comp.dirs.local_cache.join(comp.gpa, &.{ o_sub_path, rc_basename, @@ -6514,7 +6667,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 resource_id, resource_type, fmtRcEscape(src_path), }); - try o_dir.writeFile(.{ .sub_path = rc_basename, .data = input }); + try o_dir.writeFile(io, .{ .sub_path = rc_basename, .data = input }); var argv = std.array_list.Managed([]const u8).init(comp.gpa); defer argv.deinit(); @@ -6564,8 +6717,8 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 const rc_basename_noext = src_basename[0 .. src_basename.len - fs.path.extension(src_basename).len]; const digest = if (try man.hit()) man.final() else blk: { - var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.makeOpenPath("tmp", .{}); - defer zig_cache_tmp_dir.close(); + var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.createDirPathOpen(io, "tmp", .{}); + defer zig_cache_tmp_dir.close(io); const res_filename = try std.fmt.allocPrint(arena, "{s}.res", .{rc_basename_noext}); @@ -6607,7 +6760,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 // Read depfile and update cache manifest { const dep_basename = fs.path.basename(out_dep_path); - const dep_file_contents = try zig_cache_tmp_dir.readFileAlloc(dep_basename, arena, .limited(50 * 1024 * 1024)); + const dep_file_contents = try zig_cache_tmp_dir.readFileAlloc(io, dep_basename, arena, .limited(50 * 1024 * 1024)); defer arena.free(dep_file_contents); const value = try std.json.parseFromSliceLeaky(std.json.Value, arena, dep_file_contents, .{}); @@ -6623,8 +6776,8 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 try man.addFilePost(dep_file_path); switch (comp.cache_use) { .whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| { - whole.cache_manifest_mutex.lock(); - defer whole.cache_manifest_mutex.unlock(); + try whole.cache_manifest_mutex.lock(io); + defer whole.cache_manifest_mutex.unlock(io); try whole_cache_manifest.addFilePost(dep_file_path); }, .incremental, .none => {}, @@ -6635,10 +6788,10 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 // Rename into place. const digest = man.final(); const o_sub_path = try fs.path.join(arena, &[_][]const u8{ "o", &digest }); - var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(o_sub_path, .{}); - defer o_dir.close(); + var o_dir = try comp.dirs.local_cache.handle.createDirPathOpen(io, o_sub_path, .{}); + defer o_dir.close(io); const tmp_basename = fs.path.basename(out_res_path); - try fs.rename(zig_cache_tmp_dir, tmp_basename, o_dir, res_filename); + try Io.Dir.rename(zig_cache_tmp_dir, tmp_basename, o_dir, res_filename, io); break :blk digest; }; @@ -6671,18 +6824,20 @@ fn spawnZigRc( argv: []const []const u8, child_progress_node: std.Progress.Node, ) !void { + const io = comp.io; var node_name: std.ArrayList(u8) = .empty; defer node_name.deinit(arena); - var child = std.process.Child.init(argv, arena); - child.stdin_behavior = .Ignore; - child.stdout_behavior = .Pipe; - child.stderr_behavior = .Pipe; - child.progress_node = child_progress_node; - - child.spawn() catch |err| { - return comp.failWin32Resource(win32_resource, "unable to spawn {s} rc: {s}", .{ argv[0], @errorName(err) }); - }; + var child = std.process.spawn(io, .{ + .argv = argv, + .stdin = .ignore, + .stdout = .pipe, + .stderr = .pipe, + .progress_node = child_progress_node, + }) catch |err| return comp.failWin32Resource(win32_resource, "unable to spawn {s} rc: {t}", .{ + argv[0], err, + }); + defer child.kill(io); var poller = std.Io.poll(comp.gpa, enum { stdout, stderr }, .{ .stdout = child.stdout.?, @@ -6713,17 +6868,21 @@ fn spawnZigRc( // Just in case there's a failure that didn't send an ErrorBundle (e.g. an error return trace) const stderr = poller.reader(.stderr); - const term = child.wait() catch |err| { - return comp.failWin32Resource(win32_resource, "unable to wait for {s} rc: {s}", .{ argv[0], @errorName(err) }); + const term = child.wait(io) catch |err| { + return comp.failWin32Resource(win32_resource, "unable to wait for {s} rc: {t}", .{ argv[0], err }); }; switch (term) { - .Exited => |code| { + .exited => |code| { if (code != 0) { log.err("zig rc failed with stderr:\n{s}", .{stderr.buffered()}); return comp.failWin32Resource(win32_resource, "zig rc exited with code {d}", .{code}); } }, + .signal => |sig| { + log.err("zig rc signaled {t} with stderr:\n{s}", .{ sig, stderr.buffered() }); + return comp.failWin32Resource(win32_resource, "zig rc terminated unexpectedly", .{}); + }, else => { log.err("zig rc terminated with stderr:\n{s}", .{stderr.buffered()}); return comp.failWin32Resource(win32_resource, "zig rc terminated unexpectedly", .{}); @@ -6732,8 +6891,13 @@ fn spawnZigRc( } pub fn tmpFilePath(comp: Compilation, ally: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 { + const io = comp.io; + const rand_int = r: { + var x: u64 = undefined; + io.random(@ptrCast(&x)); + break :r x; + }; const s = fs.path.sep_str; - const rand_int = std.crypto.random.int(u64); if (comp.dirs.local_cache.path) |p| { return std.fmt.allocPrint(ally, "{s}" ++ s ++ "tmp" ++ s ++ "{x}-{s}", .{ p, rand_int, suffix }); } else { @@ -6884,6 +7048,21 @@ fn addCommonCCArgs( // would be inconsistent with header declarations. (min_ver.major * 100_000_000) + (min_ver.minor * 1_000_000), })); + } else if (target.isOpenBSDLibC()) { + const min_ver = target.os.version_range.semver.min; + // The macro in sys/param.h doesn't have the leading underscores, but we don't want to pollute the + // global namespace in all compilation units. So we use leading underscores and modify sys/param.h + // to just alias this one. + try argv.append(try std.fmt.allocPrint(arena, "-D___OpenBSD={d}", .{ + // Brilliantly, OpenBSD defines this macro to the year and month of the release, so we need to + // maintain a manual mapping here whenever we update the headers. + 202510, + })); + // We can't avoid pollution for this one... + try argv.append(try std.fmt.allocPrint(arena, "-DOpenBSD{d}_{d}", .{ + min_ver.major, + min_ver.minor, + })); } } @@ -7345,8 +7524,9 @@ fn failCObjWithOwnedDiagBundle( @branchHint(.cold); assert(diag_bundle.diags.len > 0); { - comp.mutex.lock(); - defer comp.mutex.unlock(); + const io = comp.io; + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); { errdefer diag_bundle.destroy(comp.gpa); try comp.failed_c_objects.ensureUnusedCapacity(comp.gpa, 1); @@ -7387,8 +7567,9 @@ fn failWin32ResourceWithOwnedBundle( ) error{ OutOfMemory, AnalysisFail } { @branchHint(.cold); { - comp.mutex.lock(); - defer comp.mutex.unlock(); + const io = comp.io; + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); try comp.failed_win32_resources.putNoClobber(comp.gpa, win32_resource, err_bundle); } win32_resource.status = .failure; @@ -7712,23 +7893,31 @@ pub fn lockAndSetMiscFailure( comptime format: []const u8, args: anytype, ) void { - comp.mutex.lock(); - defer comp.mutex.unlock(); - + const io = comp.io; + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); return setMiscFailure(comp, tag, format, args); } -pub fn dump_argv(argv: []const []const u8) void { +pub fn dumpArgv(io: Io, argv: []const []const u8) Io.Cancelable!void { var buffer: [64]u8 = undefined; - const stderr, _ = std.debug.lockStderrWriter(&buffer); - defer std.debug.unlockStderrWriter(); - nosuspend { - for (argv, 0..) |arg, i| { - if (i != 0) stderr.writeByte(' ') catch return; - stderr.writeAll(arg) catch return; - } - stderr.writeByte('\n') catch return; + const stderr = try io.lockStderr(&buffer, null); + defer io.unlockStderr(); + const w = &stderr.file_writer.interface; + return dumpArgvWriter(w, argv) catch |err| switch (err) { + error.WriteFailed => switch (stderr.file_writer.err.?) { + error.Canceled => return error.Canceled, + else => return, + }, + }; +} + +fn dumpArgvWriter(w: *Io.Writer, argv: []const []const u8) Io.Writer.Error!void { + for (argv, 0..) |arg, i| { + if (i != 0) try w.writeByte(' '); + try w.writeAll(arg); } + try w.writeByte('\n'); } pub fn getZigBackend(comp: Compilation) std.builtin.CompilerBackend { @@ -7757,8 +7946,8 @@ pub fn updateSubCompilation( defer errors.deinit(gpa); if (errors.errorMessageCount() > 0) { - parent_comp.mutex.lock(); - defer parent_comp.mutex.unlock(); + parent_comp.mutex.lockUncancelable(parent_comp.io); + defer parent_comp.mutex.unlock(parent_comp.io); try parent_comp.misc_failures.ensureUnusedCapacity(gpa, 1); parent_comp.misc_failures.putAssumeCapacityNoClobber(misc_task, .{ .msg = try std.fmt.allocPrint(gpa, "sub-compilation of {t} failed", .{misc_task}), @@ -7859,6 +8048,7 @@ fn buildOutputFromZig( var sub_create_diag: CreateDiagnostic = undefined; const sub_compilation = Compilation.create(gpa, arena, io, &sub_create_diag, .{ + .thread_limit = comp.thread_limit, .dirs = comp.dirs.withoutLocalCache(), .cache_mode = .whole, .parent_whole_cache = parent_whole_cache, @@ -7866,7 +8056,6 @@ fn buildOutputFromZig( .config = config, .root_mod = root_mod, .root_name = root_name, - .thread_pool = comp.thread_pool, .libc_installation = comp.libc_installation, .emit_bin = .yes_cache, .function_sections = true, @@ -7882,6 +8071,7 @@ fn buildOutputFromZig( .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .clang_passthrough_mode = comp.clang_passthrough_mode, .skip_linker_dependencies = true, + .environ_map = comp.environ_map, }) catch |err| switch (err) { error.CreateFail => { comp.lockAndSetMiscFailure(misc_task_tag, "sub-compilation of {t} failed: {f}", .{ misc_task_tag, sub_create_diag }); @@ -7897,12 +8087,12 @@ fn buildOutputFromZig( assert(out.* == null); out.* = crt_file; - comp.queuePrelinkTaskMode(crt_file.full_object_path, &config); + try comp.queuePrelinkTaskMode(crt_file.full_object_path, &config); } pub const CrtFileOptions = struct { - function_sections: ?bool = null, - data_sections: ?bool = null, + function_sections: bool = true, + data_sections: bool = true, omit_frame_pointer: ?bool = null, unwind_tables: ?std.builtin.UnwindTables = null, pic: ?bool = null, @@ -7996,17 +8186,17 @@ pub fn build_crt_file( var sub_create_diag: CreateDiagnostic = undefined; const sub_compilation = Compilation.create(gpa, arena, io, &sub_create_diag, .{ + .thread_limit = comp.thread_limit, .dirs = comp.dirs.withoutLocalCache(), .self_exe_path = comp.self_exe_path, .cache_mode = .whole, .config = config, .root_mod = root_mod, .root_name = root_name, - .thread_pool = comp.thread_pool, .libc_installation = comp.libc_installation, .emit_bin = .yes_cache, - .function_sections = options.function_sections orelse false, - .data_sections = options.data_sections orelse false, + .function_sections = options.function_sections, + .data_sections = options.data_sections, .c_source_files = c_source_files, .verbose_cc = comp.verbose_cc, .verbose_link = comp.verbose_link, @@ -8019,6 +8209,7 @@ pub fn build_crt_file( .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .clang_passthrough_mode = comp.clang_passthrough_mode, .skip_linker_dependencies = true, + .environ_map = comp.environ_map, }) catch |err| switch (err) { error.CreateFail => { comp.lockAndSetMiscFailure(misc_task_tag, "sub-compilation of {t} failed: {f}", .{ misc_task_tag, sub_create_diag }); @@ -8031,18 +8222,18 @@ pub fn build_crt_file( try comp.updateSubCompilation(sub_compilation, misc_task_tag, prog_node); const crt_file = try sub_compilation.toCrtFile(); - comp.queuePrelinkTaskMode(crt_file.full_object_path, &config); + try comp.queuePrelinkTaskMode(crt_file.full_object_path, &config); { - comp.mutex.lock(); - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); try comp.crt_files.ensureUnusedCapacity(gpa, 1); comp.crt_files.putAssumeCapacityNoClobber(basename, crt_file); } } -pub fn queuePrelinkTaskMode(comp: *Compilation, path: Cache.Path, config: *const Compilation.Config) void { - comp.queuePrelinkTasks(switch (config.output_mode) { +pub fn queuePrelinkTaskMode(comp: *Compilation, path: Cache.Path, config: *const Compilation.Config) Io.Cancelable!void { + try comp.queuePrelinkTasks(switch (config.output_mode) { .Exe => unreachable, .Obj => &.{.{ .load_object = path }}, .Lib => &.{switch (config.link_mode) { @@ -8052,33 +8243,10 @@ pub fn queuePrelinkTaskMode(comp: *Compilation, path: Cache.Path, config: *const }); } -/// Only valid to call during `update`. Automatically handles queuing up a -/// linker worker task if there is not already one. -pub fn queuePrelinkTasks(comp: *Compilation, tasks: []const link.PrelinkTask) void { +/// Only valid to call during `update`. +pub fn queuePrelinkTasks(comp: *Compilation, tasks: []const link.PrelinkTask) Io.Cancelable!void { comp.link_prog_node.increaseEstimatedTotalItems(tasks.len); - comp.link_task_queue.enqueuePrelink(comp, tasks) catch |err| switch (err) { - error.OutOfMemory => return comp.setAllocFailure(), - }; -} - -/// The reason for the double-queue here is that the first queue ensures any -/// resolve_type_fully tasks are complete before this dispatch function is called. -fn dispatchZcuLinkTask(comp: *Compilation, tid: usize, task: link.ZcuTask) void { - if (!comp.separateCodegenThreadOk()) { - assert(tid == 0); - if (task == .link_func) { - assert(task.link_func.mir.status.load(.monotonic) != .pending); - } - link.doZcuTask(comp, tid, task); - task.deinit(comp.zcu.?); - return; - } - comp.link_task_queue.enqueueZcu(comp, task) catch |err| switch (err) { - error.OutOfMemory => { - task.deinit(comp.zcu.?); - comp.setAllocFailure(); - }, - }; + try comp.link_queue.enqueuePrelink(comp, tasks); } pub fn toCrtFile(comp: *Compilation) Allocator.Error!CrtFile { @@ -8168,3 +8336,17 @@ pub fn compilerRtOptMode(comp: Compilation) std.builtin.OptimizeMode { pub fn compilerRtStrip(comp: Compilation) bool { return comp.root_mod.strip; } + +/// This is a temporary workaround put in place to migrate from `std.Thread.Pool` +/// to `std.Io.Threaded` for asynchronous/concurrent work. The eventual solution +/// will likely involve significant changes to the `InternPool` implementation. +pub fn getTid() usize { + if (my_tid == null) my_tid = next_tid.fetchAdd(1, .monotonic); + return my_tid.?; +} +pub fn setMainThread() void { + my_tid = 0; +} +/// TID 0 is reserved for the main thread. +var next_tid: std.atomic.Value(usize) = .init(1); +threadlocal var my_tid: ?usize = null; diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index 0cb442d90f6b..1506a5849780 100644 --- a/src/Compilation/Config.zig +++ b/src/Compilation/Config.zig @@ -137,7 +137,6 @@ pub const ResolveError = error{ SanitizeThreadRequiresLibCpp, LibCRequiresLibUnwind, LibCppRequiresLibUnwind, - OsRequiresLibC, LibCppRequiresLibC, LibUnwindRequiresLibC, TargetCannotDynamicLink, @@ -226,10 +225,6 @@ pub fn resolve(options: Options) ResolveError!Config { }; const link_libc = b: { - if (target_util.osRequiresLibC(target)) { - if (options.link_libc == false) return error.OsRequiresLibC; - break :b true; - } if (link_libcpp) { if (options.link_libc == false) return error.LibCppRequiresLibC; break :b true; @@ -250,7 +245,7 @@ pub fn resolve(options: Options) ResolveError!Config { if (options.ensure_libc_on_non_freestanding and target.os.tag != .freestanding) break :b true; - break :b false; + break :b target.requiresLibC(); }; const link_mode = b: { @@ -269,7 +264,7 @@ pub fn resolve(options: Options) ResolveError!Config { break :b .dynamic; } if (explicitly_exe_or_dyn_lib and link_libc and - (target_util.osRequiresLibC(target) or + (target.requiresLibC() or // For these libcs, Zig can only provide dynamic libc when cross-compiling. ((target.isGnuLibC() or target.isFreeBSDLibC() or target.isNetBSDLibC()) and !options.resolved_target.is_native_abi))) diff --git a/src/DarwinPosixSpawn.zig b/src/DarwinPosixSpawn.zig deleted file mode 100644 index 98197119845f..000000000000 --- a/src/DarwinPosixSpawn.zig +++ /dev/null @@ -1,225 +0,0 @@ -const errno = std.posix.errno; -const unexpectedErrno = std.posix.unexpectedErrno; - -pub const Error = error{ - SystemResources, - InvalidFileDescriptor, - NameTooLong, - TooBig, - AccessDenied, - PermissionDenied, - InputOutput, - FileSystem, - FileNotFound, - InvalidExe, - NotDir, - FileBusy, - /// Returned when the child fails to execute either in the pre-exec() initialization step, or - /// when exec(3) is invoked. - ChildExecFailed, -} || std.posix.UnexpectedError; - -pub const Attr = struct { - attr: std.c.posix_spawnattr_t, - - pub fn init() Error!Attr { - var attr: std.c.posix_spawnattr_t = undefined; - switch (errno(std.c.posix_spawnattr_init(&attr))) { - .SUCCESS => return Attr{ .attr = attr }, - .NOMEM => return error.SystemResources, - .INVAL => unreachable, - else => |err| return unexpectedErrno(err), - } - } - - pub fn deinit(self: *Attr) void { - defer self.* = undefined; - switch (errno(std.c.posix_spawnattr_destroy(&self.attr))) { - .SUCCESS => return, - .INVAL => unreachable, // Invalid parameters. - else => unreachable, - } - } - - pub fn get(self: Attr) Error!std.c.POSIX_SPAWN { - var flags: std.c.POSIX_SPAWN = undefined; - switch (errno(std.c.posix_spawnattr_getflags(&self.attr, &flags))) { - .SUCCESS => return flags, - .INVAL => unreachable, - else => |err| return unexpectedErrno(err), - } - } - - pub fn set(self: *Attr, flags: std.c.POSIX_SPAWN) Error!void { - switch (errno(std.c.posix_spawnattr_setflags(&self.attr, flags))) { - .SUCCESS => return, - .INVAL => unreachable, - else => |err| return unexpectedErrno(err), - } - } -}; - -pub const Actions = struct { - actions: std.c.posix_spawn_file_actions_t, - - pub fn init() Error!Actions { - var actions: std.c.posix_spawn_file_actions_t = undefined; - switch (errno(std.c.posix_spawn_file_actions_init(&actions))) { - .SUCCESS => return Actions{ .actions = actions }, - .NOMEM => return error.SystemResources, - .INVAL => unreachable, - else => |err| return unexpectedErrno(err), - } - } - - pub fn deinit(self: *Actions) void { - defer self.* = undefined; - switch (errno(std.c.posix_spawn_file_actions_destroy(&self.actions))) { - .SUCCESS => return, - .INVAL => unreachable, // Invalid parameters. - else => unreachable, - } - } - - pub fn open(self: *Actions, fd: std.c.fd_t, path: []const u8, flags: u32, mode: std.c.mode_t) Error!void { - const posix_path = try std.posix.toPosixPath(path); - return self.openZ(fd, &posix_path, flags, mode); - } - - pub fn openZ(self: *Actions, fd: std.c.fd_t, path: [*:0]const u8, flags: u32, mode: std.c.mode_t) Error!void { - switch (errno(std.c.posix_spawn_file_actions_addopen(&self.actions, fd, path, @as(c_int, @bitCast(flags)), mode))) { - .SUCCESS => return, - .BADF => return error.InvalidFileDescriptor, - .NOMEM => return error.SystemResources, - .NAMETOOLONG => return error.NameTooLong, - .INVAL => unreachable, // the value of file actions is invalid - else => |err| return unexpectedErrno(err), - } - } - - pub fn close(self: *Actions, fd: std.c.fd_t) Error!void { - switch (errno(std.c.posix_spawn_file_actions_addclose(&self.actions, fd))) { - .SUCCESS => return, - .BADF => return error.InvalidFileDescriptor, - .NOMEM => return error.SystemResources, - .INVAL => unreachable, // the value of file actions is invalid - .NAMETOOLONG => unreachable, - else => |err| return unexpectedErrno(err), - } - } - - pub fn dup2(self: *Actions, fd: std.c.fd_t, newfd: std.c.fd_t) Error!void { - switch (errno(std.c.posix_spawn_file_actions_adddup2(&self.actions, fd, newfd))) { - .SUCCESS => return, - .BADF => return error.InvalidFileDescriptor, - .NOMEM => return error.SystemResources, - .INVAL => unreachable, // the value of file actions is invalid - .NAMETOOLONG => unreachable, - else => |err| return unexpectedErrno(err), - } - } - - pub fn inherit(self: *Actions, fd: std.c.fd_t) Error!void { - switch (errno(std.c.posix_spawn_file_actions_addinherit_np(&self.actions, fd))) { - .SUCCESS => return, - .BADF => return error.InvalidFileDescriptor, - .NOMEM => return error.SystemResources, - .INVAL => unreachable, // the value of file actions is invalid - .NAMETOOLONG => unreachable, - else => |err| return unexpectedErrno(err), - } - } - - pub fn chdir(self: *Actions, path: []const u8) Error!void { - const posix_path = try std.posix.toPosixPath(path); - return self.chdirZ(&posix_path); - } - - pub fn chdirZ(self: *Actions, path: [*:0]const u8) Error!void { - switch (errno(std.c.posix_spawn_file_actions_addchdir_np(&self.actions, path))) { - .SUCCESS => return, - .NOMEM => return error.SystemResources, - .NAMETOOLONG => return error.NameTooLong, - .BADF => unreachable, - .INVAL => unreachable, // the value of file actions is invalid - else => |err| return unexpectedErrno(err), - } - } - - pub fn fchdir(self: *Actions, fd: std.c.fd_t) Error!void { - switch (errno(std.c.posix_spawn_file_actions_addfchdir_np(&self.actions, fd))) { - .SUCCESS => return, - .BADF => return error.InvalidFileDescriptor, - .NOMEM => return error.SystemResources, - .INVAL => unreachable, // the value of file actions is invalid - .NAMETOOLONG => unreachable, - else => |err| return unexpectedErrno(err), - } - } -}; - -pub fn spawn( - path: []const u8, - actions: ?Actions, - attr: ?Attr, - argv: [*:null]const ?[*:0]const u8, - envp: [*:null]const ?[*:0]const u8, -) Error!std.c.pid_t { - const posix_path = try std.posix.toPosixPath(path); - return spawnZ(&posix_path, actions, attr, argv, envp); -} - -pub fn spawnZ( - path: [*:0]const u8, - actions: ?Actions, - attr: ?Attr, - argv: [*:null]const ?[*:0]const u8, - envp: [*:null]const ?[*:0]const u8, -) Error!std.c.pid_t { - var pid: std.c.pid_t = undefined; - switch (errno(std.c.posix_spawn( - &pid, - path, - if (actions) |a| &a.actions else null, - if (attr) |a| &a.attr else null, - argv, - envp, - ))) { - .SUCCESS => return pid, - .@"2BIG" => return error.TooBig, - .NOMEM => return error.SystemResources, - .BADF => return error.InvalidFileDescriptor, - .ACCES => return error.AccessDenied, - .IO => return error.InputOutput, - .LOOP => return error.FileSystem, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOEXEC => return error.InvalidExe, - .NOTDIR => return error.NotDir, - .TXTBSY => return error.FileBusy, - .BADARCH => return error.InvalidExe, - .BADEXEC => return error.InvalidExe, - .FAULT => unreachable, - .INVAL => unreachable, - else => |err| return unexpectedErrno(err), - } -} - -pub fn waitpid(pid: std.c.pid_t, flags: u32) Error!std.posix.WaitPidResult { - var status: c_int = undefined; - while (true) { - const rc = waitpid(pid, &status, @as(c_int, @intCast(flags))); - switch (errno(rc)) { - .SUCCESS => return std.posix.WaitPidResult{ - .pid = @as(std.c.pid_t, @intCast(rc)), - .status = @as(u32, @bitCast(status)), - }, - .INTR => continue, - .CHILD => return error.ChildExecFailed, - .INVAL => unreachable, // Invalid flags. - else => unreachable, - } - } -} - -const std = @import("std"); diff --git a/src/IncrementalDebugServer.zig b/src/IncrementalDebugServer.zig index d376ec146ee3..b4bc2c812ebd 100644 --- a/src/IncrementalDebugServer.zig +++ b/src/IncrementalDebugServer.zig @@ -14,57 +14,122 @@ comptime { } zcu: *Zcu, -thread: ?std.Thread, -running: std.atomic.Value(bool), +future: ?Io.Future(void), /// Held by our owner when an update is in-progress, and held by us when responding to a command. /// So, essentially guards all access to `Compilation`, including `Zcu`. -mutex: std.Thread.Mutex, +mutex: std.Io.Mutex, pub fn init(zcu: *Zcu) IncrementalDebugServer { return .{ .zcu = zcu, - .thread = null, - .running = .init(true), - .mutex = .{}, + .future = null, + .mutex = .init, }; } pub fn deinit(ids: *IncrementalDebugServer) void { - if (ids.thread) |t| { - ids.running.store(false, .monotonic); - t.join(); - } + const io = ids.zcu.comp.io; + if (ids.future) |*f| f.cancel(io); } const port = 7623; pub fn spawn(ids: *IncrementalDebugServer) void { + const io = ids.zcu.comp.io; std.debug.print("spawning incremental debug server on port {d}\n", .{port}); - ids.thread = std.Thread.spawn(.{ .allocator = ids.zcu.comp.arena }, runThread, .{ids}) catch |err| - std.process.fatal("failed to spawn incremental debug server: {s}", .{@errorName(err)}); + ids.future = io.concurrent(runServer, .{ids}) catch |err| + std.process.fatal("failed to start incremental debug server: {s}", .{@errorName(err)}); } -fn runThread(ids: *IncrementalDebugServer) void { - const gpa = ids.zcu.gpa; +fn runServer(ids: *IncrementalDebugServer) void { const io = ids.zcu.comp.io; - var cmd_buf: [1024]u8 = undefined; - var text_out: std.ArrayList(u8) = .empty; - defer text_out.deinit(gpa); - - const addr: std.Io.net.IpAddress = .{ .ip6 = .loopback(port) }; - var server = addr.listen(io, .{}) catch @panic("IncrementalDebugServer: failed to listen"); + const addr: Io.net.IpAddress = .{ .ip6 = .loopback(port) }; + var server = addr.listen(io, .{}) catch |err| switch (err) { + error.Canceled => return, + else => |e| { + log.err("listen failed ({t}); closing server", .{e}); + return; + }, + }; defer server.deinit(io); - var stream = server.accept(io) catch @panic("IncrementalDebugServer: failed to accept"); - defer stream.close(io); - var stream_reader = stream.reader(io, &cmd_buf); - var stream_writer = stream.writer(io, &.{}); + while (true) { + var stream = server.accept(io) catch |err| switch (err) { + error.Canceled => return, + error.ConnectionAborted => { + log.warn("client disconnected during accept", .{}); + continue; + }, + else => |e| { + log.err("accept failed ({t})", .{e}); + return; + }, + }; + defer stream.close(io); + log.info("client '{f}' connected", .{stream.socket.address}); + var cmd_buf: [1024]u8 = undefined; + var reader = stream.reader(io, &cmd_buf); + var writer = stream.writer(io, &.{}); + ids.serveStream(&reader.interface, &writer.interface) catch |orig_err| { + const actual_err = switch (orig_err) { + error.Canceled, + error.OutOfMemory, + error.EndOfStream, + error.StreamTooLong, + => |e| e, + + error.ReadFailed => reader.err.?, + error.WriteFailed => writer.err.?, + }; + switch (actual_err) { + error.Canceled => return, + + error.OutOfMemory, + error.Unexpected, + error.SystemResources, + error.Timeout, + error.NetworkDown, + error.NetworkUnreachable, + error.HostUnreachable, + error.FastOpenAlreadyInProgress, + error.ConnectionRefused, + error.StreamTooLong, + => |e| log.err("failed to serve '{f}' ({t})", .{ stream.socket.address, e }), + + error.EndOfStream, + error.ConnectionResetByPeer, + => log.info("client '{f}' disconnected", .{stream.socket.address}), - while (ids.running.load(.monotonic)) { - stream_writer.interface.writeAll("zig> ") catch @panic("IncrementalDebugServer: failed to write"); - const untrimmed = stream_reader.interface.takeSentinel('\n') catch |err| switch (err) { - error.EndOfStream => break, - else => @panic("IncrementalDebugServer: failed to read command"), + error.AddressFamilyUnsupported, + error.SocketUnconnected, + error.SocketNotBound, + error.AccessDenied, + => unreachable, + } }; + } +} + +fn serveStream( + ids: *IncrementalDebugServer, + stream_reader: *Io.Reader, + stream_writer: *Io.Writer, +) error{ + Canceled, + OutOfMemory, + EndOfStream, + StreamTooLong, + ReadFailed, + WriteFailed, +}!noreturn { + const gpa = ids.zcu.gpa; + const io = ids.zcu.comp.io; + + var text_out: std.ArrayList(u8) = .empty; + defer text_out.deinit(gpa); + + while (true) { + try stream_writer.writeAll("zig> "); + const untrimmed = try stream_reader.takeSentinel('\n'); const cmd_and_arg = std.mem.trim(u8, untrimmed, " \t\r\n"); const cmd: []const u8, const arg: []const u8 = if (std.mem.indexOfScalar(u8, cmd_and_arg, ' ')) |i| .{ cmd_and_arg[0..i], cmd_and_arg[i + 1 ..] } @@ -74,18 +139,21 @@ fn runThread(ids: *IncrementalDebugServer) void { text_out.clearRetainingCapacity(); { if (!ids.mutex.tryLock()) { - stream_writer.interface.writeAll("waiting for in-progress update to finish...\n") catch @panic("IncrementalDebugServer: failed to write"); - ids.mutex.lock(); + try stream_writer.writeAll("waiting for in-progress update to finish...\n"); + try ids.mutex.lock(io); } - defer ids.mutex.unlock(); - var allocating: std.Io.Writer.Allocating = .fromArrayList(gpa, &text_out); + defer ids.mutex.unlock(io); + var allocating: Io.Writer.Allocating = .fromArrayList(gpa, &text_out); defer text_out = allocating.toArrayList(); - handleCommand(ids.zcu, &allocating.writer, cmd, arg) catch @panic("IncrementalDebugServer: out of memory"); + handleCommand(ids.zcu, &allocating.writer, cmd, arg) catch |err| switch (err) { + error.OutOfMemory, + error.WriteFailed, + => return error.OutOfMemory, + }; } - text_out.append(gpa, '\n') catch @panic("IncrementalDebugServer: out of memory"); - stream_writer.interface.writeAll(text_out.items) catch @panic("IncrementalDebugServer: failed to write"); + try text_out.append(gpa, '\n'); + try stream_writer.writeAll(text_out.items); } - std.debug.print("closing incremental debug server\n", .{}); } const help_str: []const u8 = @@ -123,7 +191,7 @@ const help_str: []const u8 = \\ ; -fn handleCommand(zcu: *Zcu, w: *std.Io.Writer, cmd_str: []const u8, arg_str: []const u8) error{ WriteFailed, OutOfMemory }!void { +fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const u8) error{ WriteFailed, OutOfMemory }!void { const ip = &zcu.intern_pool; if (std.mem.eql(u8, cmd_str, "help")) { try w.writeAll(help_str); @@ -328,7 +396,8 @@ fn printAnalUnit(unit: AnalUnit, buf: *[32]u8) []const u8 { }; return std.fmt.bufPrint(buf, "{s} {d}", .{ @tagName(unit.unwrap()), idx }) catch unreachable; } -fn printType(ty: Type, zcu: *const Zcu, w: anytype) !void { + +fn printType(ty: Type, zcu: *const Zcu, w: *Io.Writer) Io.Writer.Error!void { const ip = &zcu.intern_pool; switch (ip.indexToKey(ty.toIntern())) { .int_type => |int| try w.print("{c}{d}", .{ @@ -377,6 +446,7 @@ fn printType(ty: Type, zcu: *const Zcu, w: anytype) !void { const std = @import("std"); const Io = std.Io; const Allocator = std.mem.Allocator; +const log = std.log.scoped(.incremental_debug_server); const Compilation = @import("Compilation.zig"); const Zcu = @import("Zcu.zig"); diff --git a/src/InternPool.zig b/src/InternPool.zig index 302e71a2b169..d713adcd3082 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -1,8 +1,11 @@ //! All interned objects have both a value and a type. //! This data structure is self-contained. +const InternPool = @This(); const builtin = @import("builtin"); + const std = @import("std"); +const Io = std.Io; const Allocator = std.mem.Allocator; const assert = std.debug.assert; const BigIntConst = std.math.big.int.Const; @@ -10,10 +13,9 @@ const BigIntMutable = std.math.big.int.Mutable; const Cache = std.Build.Cache; const Limb = std.math.big.Limb; const Hash = std.hash.Wyhash; +const Zir = std.zig.Zir; -const InternPool = @This(); const Zcu = @import("Zcu.zig"); -const Zir = std.zig.Zir; /// One item per thread, indexed by `tid`, which is dense and unique per thread. locals: []Local, @@ -214,6 +216,7 @@ pub const TrackedInst = extern struct { pub fn trackZir( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, key: TrackedInst, ) Allocator.Error!TrackedInst.Index { @@ -235,8 +238,8 @@ pub fn trackZir( if (entry.hash != hash) continue; if (std.meta.eql(index.resolveFull(ip) orelse continue, key)) return index; } - shard.mutate.tracked_inst_map.mutex.lock(); - defer shard.mutate.tracked_inst_map.mutex.unlock(); + shard.mutate.tracked_inst_map.mutex.lock(io, tid); + defer shard.mutate.tracked_inst_map.mutex.unlock(io); if (map.entries != shard.shared.tracked_inst_map.entries) { map = shard.shared.tracked_inst_map; map_mask = map.header().mask(); @@ -251,7 +254,7 @@ pub fn trackZir( } defer shard.mutate.tracked_inst_map.len += 1; const local = ip.getLocal(tid); - const list = local.getMutableTrackedInsts(gpa); + const list = local.getMutableTrackedInsts(gpa, io); try list.ensureUnusedCapacity(1); const map_header = map.header().*; if (shard.mutate.tracked_inst_map.len < map_header.capacity * 3 / 5) { @@ -317,6 +320,7 @@ pub fn trackZir( pub fn rehashTrackedInsts( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, ) Allocator.Error!void { assert(tid == .main); // we shouldn't have any other threads active right now @@ -333,7 +337,7 @@ pub fn rehashTrackedInsts( for (ip.locals) |*local| { // `getMutableTrackedInsts` is okay only because no other thread is currently active. // We need the `mutate` for the len. - for (local.getMutableTrackedInsts(gpa).viewAllowEmpty().items(.@"0")) |tracked_inst| { + for (local.getMutableTrackedInsts(gpa, io).viewAllowEmpty().items(.@"0")) |tracked_inst| { if (tracked_inst.inst == .lost) continue; // we can ignore this one! const full_hash = Hash.hash(0, std.mem.asBytes(&tracked_inst)); const shard = &ip.shards[@intCast(full_hash & (ip.shards.len - 1))]; @@ -379,7 +383,7 @@ pub fn rehashTrackedInsts( for (ip.locals, 0..) |*local, local_tid| { // `getMutableTrackedInsts` is okay only because no other thread is currently active. // We need the `mutate` for the len. - for (local.getMutableTrackedInsts(gpa).viewAllowEmpty().items(.@"0"), 0..) |tracked_inst, local_inst_index| { + for (local.getMutableTrackedInsts(gpa, io).viewAllowEmpty().items(.@"0"), 0..) |tracked_inst, local_inst_index| { if (tracked_inst.inst == .lost) continue; // we can ignore this one! const full_hash = Hash.hash(0, std.mem.asBytes(&tracked_inst)); const hash: u32 = @truncate(full_hash >> 32); @@ -1113,11 +1117,11 @@ const Local = struct { const Namespaces = List(struct { *[1 << namespaces_bucket_width]Zcu.Namespace }); const ListMutate = struct { - mutex: std.Thread.Mutex, + mutex: Io.Mutex, len: u32, const empty: ListMutate = .{ - .mutex = .{}, + .mutex = .init, .len = 0, }; }; @@ -1144,6 +1148,7 @@ const Local = struct { const ListSelf = @This(); const Mutable = struct { gpa: Allocator, + io: Io, arena: *std.heap.ArenaAllocator.State, mutate: *ListMutate, list: *ListSelf, @@ -1296,6 +1301,7 @@ const Local = struct { } fn setCapacity(mutable: Mutable, capacity: u32) Allocator.Error!void { + const io = mutable.io; var arena = mutable.arena.promote(mutable.gpa); defer mutable.arena.* = arena.state; const buf = try arena.allocator().alignedAlloc( @@ -1313,8 +1319,8 @@ const Local = struct { const new_slice = new_list.view().slice(); inline for (fields) |field| @memcpy(new_slice.items(field)[0..len], old_slice.items(field)[0..len]); } - mutable.mutate.mutex.lock(); - defer mutable.mutate.mutex.unlock(); + mutable.mutate.mutex.lockUncancelable(io); + defer mutable.mutate.mutex.unlock(io); mutable.list.release(new_list); } @@ -1375,18 +1381,20 @@ const Local = struct { }; } - pub fn getMutableItems(local: *Local, gpa: Allocator) List(Item).Mutable { + pub fn getMutableItems(local: *Local, gpa: Allocator, io: Io) List(Item).Mutable { return .{ .gpa = gpa, + .io = io, .arena = &local.mutate.arena, .mutate = &local.mutate.items, .list = &local.shared.items, }; } - pub fn getMutableExtra(local: *Local, gpa: Allocator) Extra.Mutable { + pub fn getMutableExtra(local: *Local, gpa: Allocator, io: Io) Extra.Mutable { return .{ .gpa = gpa, + .io = io, .arena = &local.mutate.arena, .mutate = &local.mutate.extra, .list = &local.shared.extra, @@ -1397,11 +1405,12 @@ const Local = struct { /// On 64-bit systems, this array is used for big integers and associated metadata. /// Use the helper methods instead of accessing this directly in order to not /// violate the above mechanism. - pub fn getMutableLimbs(local: *Local, gpa: Allocator) Limbs.Mutable { + pub fn getMutableLimbs(local: *Local, gpa: Allocator, io: Io) Limbs.Mutable { return switch (@sizeOf(Limb)) { - @sizeOf(u32) => local.getMutableExtra(gpa), + @sizeOf(u32) => local.getMutableExtra(gpa, io), @sizeOf(u64) => .{ .gpa = gpa, + .io = io, .arena = &local.mutate.arena, .mutate = &local.mutate.limbs, .list = &local.shared.limbs, @@ -1411,9 +1420,10 @@ const Local = struct { } /// A list of offsets into `string_bytes` for each string. - pub fn getMutableStrings(local: *Local, gpa: Allocator) Strings.Mutable { + pub fn getMutableStrings(local: *Local, gpa: Allocator, io: Io) Strings.Mutable { return .{ .gpa = gpa, + .io = io, .arena = &local.mutate.arena, .mutate = &local.mutate.strings, .list = &local.shared.strings, @@ -1425,9 +1435,10 @@ const Local = struct { /// is referencing the data here whether they want to store both index and length, /// thus allowing null bytes, or store only index, and use null-termination. The /// `strings_bytes` array is agnostic to either usage. - pub fn getMutableStringBytes(local: *Local, gpa: Allocator) StringBytes.Mutable { + pub fn getMutableStringBytes(local: *Local, gpa: Allocator, io: Io) StringBytes.Mutable { return .{ .gpa = gpa, + .io = io, .arena = &local.mutate.arena, .mutate = &local.mutate.string_bytes, .list = &local.shared.string_bytes, @@ -1436,9 +1447,10 @@ const Local = struct { /// An index into `tracked_insts` gives a reference to a single ZIR instruction which /// persists across incremental updates. - pub fn getMutableTrackedInsts(local: *Local, gpa: Allocator) TrackedInsts.Mutable { + pub fn getMutableTrackedInsts(local: *Local, gpa: Allocator, io: Io) TrackedInsts.Mutable { return .{ .gpa = gpa, + .io = io, .arena = &local.mutate.arena, .mutate = &local.mutate.tracked_insts, .list = &local.shared.tracked_insts, @@ -1452,9 +1464,10 @@ const Local = struct { /// /// Key is the hash of the path to this file, used to store /// `InternPool.TrackedInst`. - pub fn getMutableFiles(local: *Local, gpa: Allocator) List(File).Mutable { + pub fn getMutableFiles(local: *Local, gpa: Allocator, io: Io) List(File).Mutable { return .{ .gpa = gpa, + .io = io, .arena = &local.mutate.arena, .mutate = &local.mutate.files, .list = &local.shared.files, @@ -1466,27 +1479,30 @@ const Local = struct { /// field names and values directly, relying on one of these maps, stored separately, /// to provide lookup. /// These are not serialized; it is computed upon deserialization. - pub fn getMutableMaps(local: *Local, gpa: Allocator) Maps.Mutable { + pub fn getMutableMaps(local: *Local, gpa: Allocator, io: Io) Maps.Mutable { return .{ .gpa = gpa, + .io = io, .arena = &local.mutate.arena, .mutate = &local.mutate.maps, .list = &local.shared.maps, }; } - pub fn getMutableNavs(local: *Local, gpa: Allocator) Navs.Mutable { + pub fn getMutableNavs(local: *Local, gpa: Allocator, io: Io) Navs.Mutable { return .{ .gpa = gpa, + .io = io, .arena = &local.mutate.arena, .mutate = &local.mutate.navs, .list = &local.shared.navs, }; } - pub fn getMutableComptimeUnits(local: *Local, gpa: Allocator) ComptimeUnits.Mutable { + pub fn getMutableComptimeUnits(local: *Local, gpa: Allocator, io: Io) ComptimeUnits.Mutable { return .{ .gpa = gpa, + .io = io, .arena = &local.mutate.arena, .mutate = &local.mutate.comptime_units, .list = &local.shared.comptime_units, @@ -1503,9 +1519,10 @@ const Local = struct { /// serialization trivial. /// * It provides a unique integer to be used for anonymous symbol names, avoiding /// multi-threaded contention on an atomic counter. - pub fn getMutableNamespaces(local: *Local, gpa: Allocator) Namespaces.Mutable { + pub fn getMutableNamespaces(local: *Local, gpa: Allocator, io: Io) Namespaces.Mutable { return .{ .gpa = gpa, + .io = io, .arena = &local.mutate.arena, .mutate = &local.mutate.namespaces.buckets_list, .list = &local.shared.namespaces, @@ -1535,11 +1552,63 @@ const Shard = struct { }, const Mutate = struct { - mutex: std.Thread.Mutex.Recursive, + /// This mutex needs to be recursive because `getFuncDeclIes` interns multiple things at + /// once (the function, its IES, the corresponding error union, and the resulting function + /// type), so calls `getOrPutKeyEnsuringAdditionalCapacity` multiple times. Each of these + /// calls acquires a lock which will only be released when the whole operation is finalized, + /// and these different items could be in the same shard, in which case that shard's lock + /// will be acquired multiple times. + mutex: RecursiveMutex, len: u32, + const RecursiveMutex = struct { + const OptionalTid = if (single_threaded) enum(u8) { + null, + main, + fn unwrap(ot: OptionalTid) ?Zcu.PerThread.Id { + return switch (ot) { + .null => null, + .main => .main, + }; + } + fn wrap(tid: Zcu.PerThread.Id) OptionalTid { + comptime assert(tid == .main); + return .main; + } + } else packed struct(u8) { + non_null: bool, + value: Zcu.PerThread.Id, + const @"null": OptionalTid = .{ .non_null = false, .value = .main }; + fn unwrap(ot: OptionalTid) ?Zcu.PerThread.Id { + return if (ot.non_null) ot.value else null; + } + fn wrap(tid: Zcu.PerThread.Id) OptionalTid { + return .{ .non_null = true, .value = tid }; + } + }; + mutex: Io.Mutex, + tid: std.atomic.Value(OptionalTid), + lock_count: u32, + const init: RecursiveMutex = .{ .mutex = .init, .tid = .init(.null), .lock_count = 0 }; + fn lock(r: *RecursiveMutex, io: Io, tid: Zcu.PerThread.Id) void { + if (r.tid.load(.monotonic) != OptionalTid.wrap(tid)) { + r.mutex.lockUncancelable(io); + assert(r.lock_count == 0); + r.tid.store(.wrap(tid), .monotonic); + } + r.lock_count += 1; + } + fn unlock(r: *RecursiveMutex, io: Io) void { + r.lock_count -= 1; + if (r.lock_count == 0) { + r.tid.store(.null, .monotonic); + r.mutex.unlock(io); + } + } + }; + const empty: Mutate = .{ - .mutex = std.Thread.Mutex.Recursive.init, + .mutex = .init, .len = 0, }; }; @@ -1896,7 +1965,7 @@ pub const NullTerminatedString = enum(u32) { ip: *const InternPool, id: bool, }; - fn format(data: FormatData, writer: *std.Io.Writer) std.Io.Writer.Error!void { + fn format(data: FormatData, writer: *Io.Writer) Io.Writer.Error!void { const slice = data.string.toSlice(data.ip); if (!data.id) { try writer.writeAll(slice); @@ -2247,6 +2316,7 @@ pub const Key = union(enum) { is_threadlocal: bool, is_dll_import: bool, relocation: std.builtin.ExternOptions.Relocation, + decoration: ?std.builtin.ExternOptions.Decoration, is_const: bool, alignment: Alignment, @"addrspace": std.builtin.AddressSpace, @@ -2323,10 +2393,10 @@ pub const Key = union(enum) { return @atomicLoad(FuncAnalysis, func.analysisPtr(ip), .unordered); } - pub fn setBranchHint(func: Func, ip: *InternPool, hint: std.builtin.BranchHint) void { + pub fn setBranchHint(func: Func, ip: *InternPool, io: Io, hint: std.builtin.BranchHint) void { const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const analysis_ptr = func.analysisPtr(ip); var analysis = analysis_ptr.*; @@ -2334,10 +2404,10 @@ pub const Key = union(enum) { @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release); } - pub fn setAnalyzed(func: Func, ip: *InternPool) void { + pub fn setAnalyzed(func: Func, ip: *InternPool, io: Io) void { const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const analysis_ptr = func.analysisPtr(ip); var analysis = analysis_ptr.*; @@ -2365,10 +2435,10 @@ pub const Key = union(enum) { return @atomicLoad(u32, func.branchQuotaPtr(ip), .unordered); } - pub fn maxBranchQuota(func: Func, ip: *InternPool, new_branch_quota: u32) void { + pub fn maxBranchQuota(func: Func, ip: *InternPool, io: Io, new_branch_quota: u32) void { const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const branch_quota_ptr = func.branchQuotaPtr(ip); @atomicStore(u32, branch_quota_ptr, @max(branch_quota_ptr.*, new_branch_quota), .release); @@ -2385,10 +2455,10 @@ pub const Key = union(enum) { return @atomicLoad(Index, func.resolvedErrorSetPtr(ip), .unordered); } - pub fn setResolvedErrorSet(func: Func, ip: *InternPool, ies: Index) void { + pub fn setResolvedErrorSet(func: Func, ip: *InternPool, io: Io, ies: Index) void { const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); @atomicStore(Index, func.resolvedErrorSetPtr(ip), ies, .release); } @@ -3349,10 +3419,10 @@ pub const LoadedUnionType = struct { return @atomicLoad(Index, u.tagTypePtr(ip), .unordered); } - pub fn setTagType(u: LoadedUnionType, ip: *InternPool, tag_type: Index) void { + pub fn setTagType(u: LoadedUnionType, ip: *InternPool, io: Io, tag_type: Index) void { const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); @atomicStore(Index, u.tagTypePtr(ip), tag_type, .release); } @@ -3368,10 +3438,10 @@ pub const LoadedUnionType = struct { return @atomicLoad(Tag.TypeUnion.Flags, u.flagsPtr(ip), .unordered); } - pub fn setStatus(u: LoadedUnionType, ip: *InternPool, status: Status) void { + pub fn setStatus(u: LoadedUnionType, ip: *InternPool, io: Io, status: Status) void { const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const flags_ptr = u.flagsPtr(ip); var flags = flags_ptr.*; @@ -3379,10 +3449,10 @@ pub const LoadedUnionType = struct { @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release); } - pub fn setStatusIfLayoutWip(u: LoadedUnionType, ip: *InternPool, status: Status) void { + pub fn setStatusIfLayoutWip(u: LoadedUnionType, ip: *InternPool, io: Io, status: Status) void { const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const flags_ptr = u.flagsPtr(ip); var flags = flags_ptr.*; @@ -3390,10 +3460,10 @@ pub const LoadedUnionType = struct { @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release); } - pub fn setAlignment(u: LoadedUnionType, ip: *InternPool, alignment: Alignment) void { + pub fn setAlignment(u: LoadedUnionType, ip: *InternPool, io: Io, alignment: Alignment) void { const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const flags_ptr = u.flagsPtr(ip); var flags = flags_ptr.*; @@ -3401,10 +3471,10 @@ pub const LoadedUnionType = struct { @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release); } - pub fn assumeRuntimeBitsIfFieldTypesWip(u: LoadedUnionType, ip: *InternPool) bool { + pub fn assumeRuntimeBitsIfFieldTypesWip(u: LoadedUnionType, ip: *InternPool, io: Io) bool { const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const flags_ptr = u.flagsPtr(ip); var flags = flags_ptr.*; @@ -3419,10 +3489,10 @@ pub const LoadedUnionType = struct { return u.flagsUnordered(ip).requires_comptime; } - pub fn setRequiresComptimeWip(u: LoadedUnionType, ip: *InternPool) RequiresComptime { + pub fn setRequiresComptimeWip(u: LoadedUnionType, ip: *InternPool, io: Io) RequiresComptime { const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const flags_ptr = u.flagsPtr(ip); var flags = flags_ptr.*; @@ -3433,12 +3503,12 @@ pub const LoadedUnionType = struct { return flags.requires_comptime; } - pub fn setRequiresComptime(u: LoadedUnionType, ip: *InternPool, requires_comptime: RequiresComptime) void { + pub fn setRequiresComptime(u: LoadedUnionType, ip: *InternPool, io: Io, requires_comptime: RequiresComptime) void { assert(requires_comptime != .wip); // see setRequiresComptimeWip const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const flags_ptr = u.flagsPtr(ip); var flags = flags_ptr.*; @@ -3446,10 +3516,10 @@ pub const LoadedUnionType = struct { @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release); } - pub fn assumePointerAlignedIfFieldTypesWip(u: LoadedUnionType, ip: *InternPool, ptr_align: Alignment) bool { + pub fn assumePointerAlignedIfFieldTypesWip(u: LoadedUnionType, ip: *InternPool, io: Io, ptr_align: Alignment) bool { const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const flags_ptr = u.flagsPtr(ip); var flags = flags_ptr.*; @@ -3495,10 +3565,10 @@ pub const LoadedUnionType = struct { return self.flagsUnordered(ip).status.haveLayout(); } - pub fn setHaveLayout(u: LoadedUnionType, ip: *InternPool, size: u32, padding: u32, alignment: Alignment) void { + pub fn setHaveLayout(u: LoadedUnionType, ip: *InternPool, io: Io, size: u32, padding: u32, alignment: Alignment) void { const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); @atomicStore(u32, u.sizePtr(ip), size, .unordered); @atomicStore(u32, u.paddingPtr(ip), padding, .unordered); @@ -3767,10 +3837,10 @@ pub const LoadedStructType = struct { return s.flagsUnordered(ip).requires_comptime; } - pub fn setRequiresComptimeWip(s: LoadedStructType, ip: *InternPool) RequiresComptime { + pub fn setRequiresComptimeWip(s: LoadedStructType, ip: *InternPool, io: Io) RequiresComptime { const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const flags_ptr = s.flagsPtr(ip); var flags = flags_ptr.*; @@ -3781,12 +3851,12 @@ pub const LoadedStructType = struct { return flags.requires_comptime; } - pub fn setRequiresComptime(s: LoadedStructType, ip: *InternPool, requires_comptime: RequiresComptime) void { + pub fn setRequiresComptime(s: LoadedStructType, ip: *InternPool, io: Io, requires_comptime: RequiresComptime) void { assert(requires_comptime != .wip); // see setRequiresComptimeWip const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const flags_ptr = s.flagsPtr(ip); var flags = flags_ptr.*; @@ -3794,12 +3864,12 @@ pub const LoadedStructType = struct { @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); } - pub fn assumeRuntimeBitsIfFieldTypesWip(s: LoadedStructType, ip: *InternPool) bool { + pub fn assumeRuntimeBitsIfFieldTypesWip(s: LoadedStructType, ip: *InternPool, io: Io) bool { if (s.layout == .@"packed") return false; const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const flags_ptr = s.flagsPtr(ip); var flags = flags_ptr.*; @@ -3810,12 +3880,12 @@ pub const LoadedStructType = struct { return flags.field_types_wip; } - pub fn setFieldTypesWip(s: LoadedStructType, ip: *InternPool) bool { + pub fn setFieldTypesWip(s: LoadedStructType, ip: *InternPool, io: Io) bool { if (s.layout == .@"packed") return false; const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const flags_ptr = s.flagsPtr(ip); var flags = flags_ptr.*; @@ -3826,12 +3896,12 @@ pub const LoadedStructType = struct { return flags.field_types_wip; } - pub fn clearFieldTypesWip(s: LoadedStructType, ip: *InternPool) void { + pub fn clearFieldTypesWip(s: LoadedStructType, ip: *InternPool, io: Io) void { if (s.layout == .@"packed") return; const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const flags_ptr = s.flagsPtr(ip); var flags = flags_ptr.*; @@ -3839,12 +3909,12 @@ pub const LoadedStructType = struct { @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); } - pub fn setLayoutWip(s: LoadedStructType, ip: *InternPool) bool { + pub fn setLayoutWip(s: LoadedStructType, ip: *InternPool, io: Io) bool { if (s.layout == .@"packed") return false; const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const flags_ptr = s.flagsPtr(ip); var flags = flags_ptr.*; @@ -3855,12 +3925,12 @@ pub const LoadedStructType = struct { return flags.layout_wip; } - pub fn clearLayoutWip(s: LoadedStructType, ip: *InternPool) void { + pub fn clearLayoutWip(s: LoadedStructType, ip: *InternPool, io: Io) void { if (s.layout == .@"packed") return; const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const flags_ptr = s.flagsPtr(ip); var flags = flags_ptr.*; @@ -3868,10 +3938,10 @@ pub const LoadedStructType = struct { @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); } - pub fn setAlignment(s: LoadedStructType, ip: *InternPool, alignment: Alignment) void { + pub fn setAlignment(s: LoadedStructType, ip: *InternPool, io: Io, alignment: Alignment) void { const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const flags_ptr = s.flagsPtr(ip); var flags = flags_ptr.*; @@ -3879,10 +3949,10 @@ pub const LoadedStructType = struct { @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); } - pub fn assumePointerAlignedIfFieldTypesWip(s: LoadedStructType, ip: *InternPool, ptr_align: Alignment) bool { + pub fn assumePointerAlignedIfFieldTypesWip(s: LoadedStructType, ip: *InternPool, io: Io, ptr_align: Alignment) bool { const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const flags_ptr = s.flagsPtr(ip); var flags = flags_ptr.*; @@ -3894,10 +3964,10 @@ pub const LoadedStructType = struct { return flags.field_types_wip; } - pub fn assumePointerAlignedIfWip(s: LoadedStructType, ip: *InternPool, ptr_align: Alignment) bool { + pub fn assumePointerAlignedIfWip(s: LoadedStructType, ip: *InternPool, io: Io, ptr_align: Alignment) bool { const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const flags_ptr = s.flagsPtr(ip); var flags = flags_ptr.*; @@ -3911,12 +3981,12 @@ pub const LoadedStructType = struct { return flags.alignment_wip; } - pub fn clearAlignmentWip(s: LoadedStructType, ip: *InternPool) void { + pub fn clearAlignmentWip(s: LoadedStructType, ip: *InternPool, io: Io) void { if (s.layout == .@"packed") return; const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const flags_ptr = s.flagsPtr(ip); var flags = flags_ptr.*; @@ -3924,10 +3994,10 @@ pub const LoadedStructType = struct { @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); } - pub fn setInitsWip(s: LoadedStructType, ip: *InternPool) bool { + pub fn setInitsWip(s: LoadedStructType, ip: *InternPool, io: Io) bool { const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); switch (s.layout) { .@"packed" => { @@ -3951,10 +4021,10 @@ pub const LoadedStructType = struct { } } - pub fn clearInitsWip(s: LoadedStructType, ip: *InternPool) void { + pub fn clearInitsWip(s: LoadedStructType, ip: *InternPool, io: Io) void { const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); switch (s.layout) { .@"packed" => { @@ -3972,12 +4042,12 @@ pub const LoadedStructType = struct { } } - pub fn setFullyResolved(s: LoadedStructType, ip: *InternPool) bool { + pub fn setFullyResolved(s: LoadedStructType, ip: *InternPool, io: Io) bool { if (s.layout == .@"packed") return true; const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const flags_ptr = s.flagsPtr(ip); var flags = flags_ptr.*; @@ -3988,10 +4058,10 @@ pub const LoadedStructType = struct { return flags.fully_resolved; } - pub fn clearFullyResolved(s: LoadedStructType, ip: *InternPool) void { + pub fn clearFullyResolved(s: LoadedStructType, ip: *InternPool, io: Io) void { const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const flags_ptr = s.flagsPtr(ip); var flags = flags_ptr.*; @@ -4027,10 +4097,10 @@ pub const LoadedStructType = struct { return @atomicLoad(Index, s.backingIntTypePtr(ip), .unordered); } - pub fn setBackingIntType(s: LoadedStructType, ip: *InternPool, backing_int_ty: Index) void { + pub fn setBackingIntType(s: LoadedStructType, ip: *InternPool, io: Io, backing_int_ty: Index) void { const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); @atomicStore(Index, s.backingIntTypePtr(ip), backing_int_ty, .release); } @@ -4054,10 +4124,10 @@ pub const LoadedStructType = struct { }; } - pub fn setHaveFieldInits(s: LoadedStructType, ip: *InternPool) void { + pub fn setHaveFieldInits(s: LoadedStructType, ip: *InternPool, io: Io) void { const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); switch (s.layout) { .@"packed" => { @@ -4082,10 +4152,10 @@ pub const LoadedStructType = struct { }; } - pub fn setLayoutResolved(s: LoadedStructType, ip: *InternPool, size: u32, alignment: Alignment) void { + pub fn setLayoutResolved(s: LoadedStructType, ip: *InternPool, io: Io, size: u32, alignment: Alignment) void { const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); @atomicStore(u32, s.sizePtr(ip), size, .unordered); const flags_ptr = s.flagsPtr(ip); @@ -6006,6 +6076,8 @@ pub const Tag = enum(u8) { flags: Flags, owner_nav: Nav.Index, zir_index: TrackedInst.Index, + location_or_descriptor_set: u32, + descriptor_binding: u32, pub const Flags = packed struct(u32) { linkage: std.builtin.GlobalLinkage, @@ -6014,10 +6086,22 @@ pub const Tag = enum(u8) { is_dll_import: bool, relocation: std.builtin.ExternOptions.Relocation, source: Source, - _: u24 = 0, + decoration_type: DecorationType, + _: u22 = 0, pub const Source = enum(u1) { builtin, syntax }; + pub const DecorationType = enum(u2) { none, location, descriptor }; }; + + pub fn decoration(self: Extern) ?std.builtin.ExternOptions.Decoration { + return switch (self.flags.decoration_type) { + .none => null, + .location => std.builtin.ExternOptions.Decoration{ + .location = self.location_or_descriptor_set, + }, + .descriptor => std.builtin.ExternOptions.Decoration{ .descriptor = .{ .set = self.location_or_descriptor_set, .binding = self.descriptor_binding } }, + }; + } }; /// Trailing: @@ -6826,8 +6910,8 @@ pub const MemoizedCall = struct { branch_count: u32, }; -pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void { - errdefer ip.deinit(gpa); +pub fn init(ip: *InternPool, gpa: Allocator, io: Io, available_threads: usize) !void { + errdefer ip.deinit(gpa, io); assert(ip.locals.len == 0 and ip.shards.len == 0); assert(available_threads > 0 and available_threads <= std.math.maxInt(u8)); @@ -6865,7 +6949,7 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void { .namespaces = .empty, }, }); - for (ip.locals) |*local| try local.getMutableStrings(gpa).append(.{0}); + for (ip.locals) |*local| try local.getMutableStrings(gpa, io).append(.{0}); ip.tid_width = @intCast(std.math.log2_int_ceil(usize, used_threads)); ip.tid_shift_30 = if (single_threaded) 0 else 30 - ip.tid_width; @@ -6874,28 +6958,28 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void { ip.shards = try gpa.alloc(Shard, @as(usize, 1) << ip.tid_width); @memset(ip.shards, .{ .shared = .{ - .map = Shard.Map(Index).empty, - .string_map = Shard.Map(OptionalNullTerminatedString).empty, - .tracked_inst_map = Shard.Map(TrackedInst.Index.Optional).empty, + .map = .empty, + .string_map = .empty, + .tracked_inst_map = .empty, }, .mutate = .{ - .map = Shard.Mutate.empty, - .string_map = Shard.Mutate.empty, - .tracked_inst_map = Shard.Mutate.empty, + .map = .empty, + .string_map = .empty, + .tracked_inst_map = .empty, }, }); // Reserve string index 0 for an empty string. - assert((try ip.getOrPutString(gpa, .main, "", .no_embedded_nulls)) == .empty); + assert((try ip.getOrPutString(gpa, io, .main, "", .no_embedded_nulls)) == .empty); // This inserts all the statically-known values into the intern pool in the // order expected. for (&static_keys, 0..) |key, key_index| switch (@as(Index, @enumFromInt(key_index))) { - .empty_tuple_type => assert(try ip.getTupleType(gpa, .main, .{ + .empty_tuple_type => assert(try ip.getTupleType(gpa, io, .main, .{ .types = &.{}, .values = &.{}, }) == .empty_tuple_type), - else => |expected_index| assert(try ip.get(gpa, .main, key) == expected_index), + else => |expected_index| assert(try ip.get(gpa, io, .main, key) == expected_index), }; if (std.debug.runtime_safety) { @@ -6905,7 +6989,7 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void { } } -pub fn deinit(ip: *InternPool, gpa: Allocator) void { +pub fn deinit(ip: *InternPool, gpa: Allocator, io: Io) void { if (debug_state.enable_checks) std.debug.assert(debug_state.intern_pool == null); ip.src_hash_deps.deinit(gpa); @@ -6940,7 +7024,7 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void { namespace.test_decls.deinit(gpa); } }; - const maps = local.getMutableMaps(gpa); + const maps = local.getMutableMaps(gpa, io); if (maps.mutate.len > 0) for (maps.view().items(.@"0")) |*map| map.deinit(gpa); local.mutate.arena.promote(gpa).deinit(); } @@ -7375,6 +7459,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { .is_threadlocal = extra.flags.is_threadlocal, .is_dll_import = extra.flags.is_dll_import, .relocation = extra.flags.relocation, + .decoration = extra.decoration(), .is_const = nav.status.fully_resolved.is_const, .alignment = nav.status.fully_resolved.alignment, .@"addrspace" = nav.status.fully_resolved.@"addrspace", @@ -7645,6 +7730,7 @@ const GetOrPutKey = union(enum) { new: struct { ip: *InternPool, tid: Zcu.PerThread.Id, + io: Io, shard: *Shard, map_index: u32, }, @@ -7679,7 +7765,7 @@ const GetOrPutKey = union(enum) { .new => |info| { assert(info.shard.shared.map.entries[info.map_index].value == index); info.shard.mutate.map.len += 1; - info.shard.mutate.map.mutex.unlock(); + info.shard.mutate.map.mutex.unlock(info.io); gop.* = .{ .existing = index }; }, } @@ -7688,7 +7774,7 @@ const GetOrPutKey = union(enum) { fn cancel(gop: *GetOrPutKey) void { switch (gop.*) { .existing => {}, - .new => |info| info.shard.mutate.map.mutex.unlock(), + .new => |info| info.shard.mutate.map.mutex.unlock(info.io), } gop.* = .{ .existing = undefined }; } @@ -7705,14 +7791,16 @@ const GetOrPutKey = union(enum) { fn getOrPutKey( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, key: Key, ) Allocator.Error!GetOrPutKey { - return ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, key, 0); + return ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, io, tid, key, 0); } fn getOrPutKeyEnsuringAdditionalCapacity( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, key: Key, additional_capacity: u32, @@ -7733,8 +7821,8 @@ fn getOrPutKeyEnsuringAdditionalCapacity( if (index.unwrap(ip).getTag(ip) == .removed) continue; if (ip.indexToKey(index).eql(key, ip)) return .{ .existing = index }; } - shard.mutate.map.mutex.lock(); - errdefer shard.mutate.map.mutex.unlock(); + shard.mutate.map.mutex.lock(io, tid); + errdefer shard.mutate.map.mutex.unlock(io); if (map.entries != shard.shared.map.entries) { map = shard.shared.map; map_mask = map.header().mask(); @@ -7747,7 +7835,7 @@ fn getOrPutKeyEnsuringAdditionalCapacity( if (index == .none) break; if (entry.hash != hash) continue; if (ip.indexToKey(index).eql(key, ip)) { - defer shard.mutate.map.mutex.unlock(); + defer shard.mutate.map.mutex.unlock(io); return .{ .existing = index }; } } @@ -7801,6 +7889,7 @@ fn getOrPutKeyEnsuringAdditionalCapacity( return .{ .new = .{ .ip = ip, .tid = tid, + .io = io, .shard = shard, .map_index = map_index, } }; @@ -7815,14 +7904,15 @@ fn getOrPutKeyEnsuringAdditionalCapacity( /// will be cleaned up when the `Zcu` undergoes garbage collection. fn putKeyReplace( ip: *InternPool, + io: Io, tid: Zcu.PerThread.Id, key: Key, ) GetOrPutKey { const full_hash = key.hash64(ip); const hash: u32 = @truncate(full_hash >> 32); const shard = &ip.shards[@intCast(full_hash & (ip.shards.len - 1))]; - shard.mutate.map.mutex.lock(); - errdefer shard.mutate.map.mutex.unlock(); + shard.mutate.map.mutex.lock(io, tid); + errdefer shard.mutate.map.mutex.unlock(io); const map = shard.shared.map; const map_mask = map.header().mask(); var map_index = hash; @@ -7838,18 +7928,19 @@ fn putKeyReplace( return .{ .new = .{ .ip = ip, .tid = tid, + .io = io, .shard = shard, .map_index = map_index, } }; } -pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) Allocator.Error!Index { - var gop = try ip.getOrPutKey(gpa, tid, key); +pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: Key) Allocator.Error!Index { + var gop = try ip.getOrPutKey(gpa, io, tid, key); defer gop.deinit(); if (gop == .existing) return gop.existing; const local = ip.getLocal(tid); - const items = local.getMutableItems(gpa); - const extra = local.getMutableExtra(gpa); + const items = local.getMutableItems(gpa, io); + const extra = local.getMutableExtra(gpa, io); try items.ensureUnusedCapacity(1); switch (key) { .int_type => |int_type| { @@ -7870,8 +7961,8 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All gop.cancel(); var new_key = key; new_key.ptr_type.flags.size = .many; - const ptr_type_index = try ip.get(gpa, tid, new_key); - gop = try ip.getOrPutKey(gpa, tid, key); + const ptr_type_index = try ip.get(gpa, io, tid, new_key); + gop = try ip.getOrPutKey(gpa, io, tid, key); try items.ensureUnusedCapacity(1); items.appendAssumeCapacity(.{ @@ -7953,7 +8044,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All assert(error_set_type.names_map == .none); assert(std.sort.isSorted(NullTerminatedString, error_set_type.names.get(ip), {}, NullTerminatedString.indexLessThan)); const names = error_set_type.names.get(ip); - const names_map = try ip.addMap(gpa, tid, names.len); + const names_map = try ip.addMap(gpa, io, tid, names.len); ip.addStringsToMap(names_map, names); const names_len = error_set_type.names.len; try extra.ensureUnusedCapacity(@typeInfo(Tag.ErrorSet).@"struct".fields.len + names_len); @@ -8051,7 +8142,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All gop.cancel(); var new_key = key; new_key.ptr.base_addr.uav.orig_ty = ptr.ty; - gop = try ip.getOrPutKey(gpa, tid, new_key); + gop = try ip.getOrPutKey(gpa, io, tid, new_key); if (gop == .existing) return gop.existing; } break :item .{ @@ -8123,11 +8214,11 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All else => unreachable, } gop.cancel(); - const index_index = try ip.get(gpa, tid, .{ .int = .{ + const index_index = try ip.get(gpa, io, tid, .{ .int = .{ .ty = .usize_type, .storage = .{ .u64 = base_index.index }, } }); - gop = try ip.getOrPutKey(gpa, tid, key); + gop = try ip.getOrPutKey(gpa, io, tid, key); try items.ensureUnusedCapacity(1); items.appendAssumeCapacity(.{ .tag = switch (ptr.base_addr) { @@ -8318,7 +8409,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All } else |_| {} const tag: Tag = if (big_int.positive) .int_positive else .int_negative; - try addInt(ip, gpa, tid, int.ty, tag, big_int.limbs); + try addInt(ip, gpa, io, tid, int.ty, tag, big_int.limbs); }, inline .u64, .i64 => |x| { if (std.math.cast(u32, x)) |casted| { @@ -8335,7 +8426,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All var buf: [2]Limb = undefined; const big_int = BigIntMutable.init(&buf, x).toConst(); const tag: Tag = if (big_int.positive) .int_positive else .int_negative; - try addInt(ip, gpa, tid, int.ty, tag, big_int.limbs); + try addInt(ip, gpa, io, tid, int.ty, tag, big_int.limbs); }, .lazy_align, .lazy_size => unreachable, } @@ -8546,11 +8637,11 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All const elem = switch (aggregate.storage) { .bytes => |bytes| elem: { gop.cancel(); - const elem = try ip.get(gpa, tid, .{ .int = .{ + const elem = try ip.get(gpa, io, tid, .{ .int = .{ .ty = .u8_type, .storage = .{ .u64 = bytes.at(0, ip) }, } }); - gop = try ip.getOrPutKey(gpa, tid, key); + gop = try ip.getOrPutKey(gpa, io, tid, key); try items.ensureUnusedCapacity(1); break :elem elem; }, @@ -8570,7 +8661,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All } if (child == .u8_type) bytes: { - const string_bytes = ip.getLocal(tid).getMutableStringBytes(gpa); + const string_bytes = ip.getLocal(tid).getMutableStringBytes(gpa, io); const start = string_bytes.mutate.len; try string_bytes.ensureUnusedCapacity(@intCast(len_including_sentinel + 1)); try extra.ensureUnusedCapacity(@typeInfo(Bytes).@"struct".fields.len); @@ -8598,6 +8689,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All }); const string = try ip.getOrPutTrailingString( gpa, + io, tid, @intCast(len_including_sentinel), .maybe_embedded_nulls, @@ -8647,15 +8739,16 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All pub fn getUnion( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, un: Key.Union, ) Allocator.Error!Index { - var gop = try ip.getOrPutKey(gpa, tid, .{ .un = un }); + var gop = try ip.getOrPutKey(gpa, io, tid, .{ .un = un }); defer gop.deinit(); if (gop == .existing) return gop.existing; const local = ip.getLocal(tid); - const items = local.getMutableItems(gpa); - const extra = local.getMutableExtra(gpa); + const items = local.getMutableItems(gpa, io); + const extra = local.getMutableExtra(gpa, io); try items.ensureUnusedCapacity(1); assert(un.ty != .none); @@ -8706,6 +8799,7 @@ pub const UnionTypeInit = struct { pub fn getUnionType( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, ini: UnionTypeInit, /// If it is known that there is an existing type with this key which is outdated, @@ -8727,16 +8821,16 @@ pub fn getUnionType( } }, } }; var gop = if (replace_existing) - ip.putKeyReplace(tid, key) + ip.putKeyReplace(io, tid, key) else - try ip.getOrPutKey(gpa, tid, key); + try ip.getOrPutKey(gpa, io, tid, key); defer gop.deinit(); if (gop == .existing) return .{ .existing = gop.existing }; const local = ip.getLocal(tid); - const items = local.getMutableItems(gpa); + const items = local.getMutableItems(gpa, io); try items.ensureUnusedCapacity(1); - const extra = local.getMutableExtra(gpa); + const extra = local.getMutableExtra(gpa, io); const align_elements_len = if (ini.flags.any_aligned_fields) (ini.fields_len + 3) / 4 else 0; const align_element: u32 = @bitCast([1]u8{@intFromEnum(Alignment.none)} ** 4); @@ -8903,6 +8997,7 @@ pub const StructTypeInit = struct { pub fn getStructType( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, ini: StructTypeInit, /// If it is known that there is an existing type with this key which is outdated, @@ -8924,17 +9019,17 @@ pub fn getStructType( } }, } }; var gop = if (replace_existing) - ip.putKeyReplace(tid, key) + ip.putKeyReplace(io, tid, key) else - try ip.getOrPutKey(gpa, tid, key); + try ip.getOrPutKey(gpa, io, tid, key); defer gop.deinit(); if (gop == .existing) return .{ .existing = gop.existing }; const local = ip.getLocal(tid); - const items = local.getMutableItems(gpa); - const extra = local.getMutableExtra(gpa); + const items = local.getMutableItems(gpa, io); + const extra = local.getMutableExtra(gpa, io); - const names_map = try ip.addMap(gpa, tid, ini.fields_len); + const names_map = try ip.addMap(gpa, io, tid, ini.fields_len); errdefer local.mutate.maps.len -= 1; const zir_index = switch (ini.key) { @@ -9109,6 +9204,7 @@ pub const TupleTypeInit = struct { pub fn getTupleType( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, ini: TupleTypeInit, ) Allocator.Error!Index { @@ -9116,8 +9212,8 @@ pub fn getTupleType( for (ini.types) |elem| assert(elem != .none); const local = ip.getLocal(tid); - const items = local.getMutableItems(gpa); - const extra = local.getMutableExtra(gpa); + const items = local.getMutableItems(gpa, io); + const extra = local.getMutableExtra(gpa, io); const prev_extra_len = extra.mutate.len; const fields_len: u32 = @intCast(ini.types.len); @@ -9134,7 +9230,7 @@ pub fn getTupleType( extra.appendSliceAssumeCapacity(.{@ptrCast(ini.values)}); errdefer extra.mutate.len = prev_extra_len; - var gop = try ip.getOrPutKey(gpa, tid, .{ .tuple_type = extraTypeTuple(tid, extra.list.*, extra_index) }); + var gop = try ip.getOrPutKey(gpa, io, tid, .{ .tuple_type = extraTypeTuple(tid, extra.list.*, extra_index) }); defer gop.deinit(); if (gop == .existing) { extra.mutate.len = prev_extra_len; @@ -9166,6 +9262,7 @@ pub const GetFuncTypeKey = struct { pub fn getFuncType( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, key: GetFuncTypeKey, ) Allocator.Error!Index { @@ -9174,9 +9271,9 @@ pub fn getFuncType( for (key.param_types) |param_type| assert(param_type != .none); const local = ip.getLocal(tid); - const items = local.getMutableItems(gpa); + const items = local.getMutableItems(gpa, io); try items.ensureUnusedCapacity(1); - const extra = local.getMutableExtra(gpa); + const extra = local.getMutableExtra(gpa, io); // The strategy here is to add the function type unconditionally, then to // ask if it already exists, and if so, revert the lengths of the mutated @@ -9207,7 +9304,7 @@ pub fn getFuncType( extra.appendSliceAssumeCapacity(.{@ptrCast(key.param_types)}); errdefer extra.mutate.len = prev_extra_len; - var gop = try ip.getOrPutKey(gpa, tid, .{ + var gop = try ip.getOrPutKey(gpa, io, tid, .{ .func_type = extraFuncType(tid, extra.list.*, func_type_extra_index), }); defer gop.deinit(); @@ -9228,6 +9325,7 @@ pub fn getFuncType( pub fn getExtern( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, /// `key.owner_nav` is ignored. key: Key.Extern, @@ -9236,7 +9334,7 @@ pub fn getExtern( /// Only set if the `Nav` was newly created. new_nav: Nav.Index.Optional, } { - var gop = try ip.getOrPutKey(gpa, tid, .{ .@"extern" = key }); + var gop = try ip.getOrPutKey(gpa, io, tid, .{ .@"extern" = key }); defer gop.deinit(); if (gop == .existing) return .{ .index = gop.existing, @@ -9244,18 +9342,18 @@ pub fn getExtern( }; const local = ip.getLocal(tid); - const items = local.getMutableItems(gpa); - const extra = local.getMutableExtra(gpa); + const items = local.getMutableItems(gpa, io); + const extra = local.getMutableExtra(gpa, io); try items.ensureUnusedCapacity(1); try extra.ensureUnusedCapacity(@typeInfo(Tag.Extern).@"struct".fields.len); - try local.getMutableNavs(gpa).ensureUnusedCapacity(1); + try local.getMutableNavs(gpa, io).ensureUnusedCapacity(1); // Predict the index the `@"extern" will live at, so we can construct the owner `Nav` before releasing the shard's mutex. const extern_index = Index.Unwrapped.wrap(.{ .tid = tid, .index = items.mutate.len, }, ip); - const owner_nav = ip.createNav(gpa, tid, .{ + const owner_nav = ip.createNav(gpa, io, tid, .{ .name = key.name, .fqn = key.name, .val = extern_index, @@ -9264,15 +9362,22 @@ pub fn getExtern( .@"linksection" = .none, .@"addrspace" = key.@"addrspace", }) catch unreachable; // capacity asserted above + const decoration_type, const location_or_descriptor_set, const descriptor_binding = if (key.decoration) |decoration| switch (decoration) { + .location => |location| .{ Tag.Extern.Flags.DecorationType.location, location, undefined }, + .descriptor => |descriptor| .{ Tag.Extern.Flags.DecorationType.descriptor, descriptor.binding, descriptor.set }, + } else .{ Tag.Extern.Flags.DecorationType.none, undefined, undefined }; const extra_index = addExtraAssumeCapacity(extra, Tag.Extern{ .ty = key.ty, .lib_name = key.lib_name, + .location_or_descriptor_set = location_or_descriptor_set, + .descriptor_binding = descriptor_binding, .flags = .{ .linkage = key.linkage, .visibility = key.visibility, .is_threadlocal = key.is_threadlocal, .is_dll_import = key.is_dll_import, .relocation = key.relocation, + .decoration_type = decoration_type, .source = key.source, }, .zir_index = key.zir_index, @@ -9305,13 +9410,14 @@ pub const GetFuncDeclKey = struct { pub fn getFuncDecl( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, key: GetFuncDeclKey, ) Allocator.Error!Index { const local = ip.getLocal(tid); - const items = local.getMutableItems(gpa); + const items = local.getMutableItems(gpa, io); try items.ensureUnusedCapacity(1); - const extra = local.getMutableExtra(gpa); + const extra = local.getMutableExtra(gpa, io); // The strategy here is to add the function type unconditionally, then to // ask if it already exists, and if so, revert the lengths of the mutated @@ -9340,7 +9446,7 @@ pub fn getFuncDecl( }); errdefer extra.mutate.len = prev_extra_len; - var gop = try ip.getOrPutKey(gpa, tid, .{ + var gop = try ip.getOrPutKey(gpa, io, tid, .{ .func = extraFuncDecl(tid, extra.list.*, func_decl_extra_index), }); defer gop.deinit(); @@ -9387,6 +9493,7 @@ pub const GetFuncDeclIesKey = struct { pub fn getFuncDeclIes( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, key: GetFuncDeclIesKey, ) Allocator.Error!Index { @@ -9395,9 +9502,9 @@ pub fn getFuncDeclIes( for (key.param_types) |param_type| assert(param_type != .none); const local = ip.getLocal(tid); - const items = local.getMutableItems(gpa); + const items = local.getMutableItems(gpa, io); try items.ensureUnusedCapacity(4); - const extra = local.getMutableExtra(gpa); + const extra = local.getMutableExtra(gpa, io); // The strategy here is to add the function decl unconditionally, then to // ask if it already exists, and if so, revert the lengths of the mutated @@ -9488,7 +9595,7 @@ pub fn getFuncDeclIes( extra.mutate.len = prev_extra_len; } - var func_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, .{ + var func_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, io, tid, .{ .func = extraFuncDecl(tid, extra.list.*, func_decl_extra_index), }, 3); defer func_gop.deinit(); @@ -9509,18 +9616,18 @@ pub fn getFuncDeclIes( return func_gop.existing; } func_gop.putTentative(func_index); - var error_union_type_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, .{ .error_union_type = .{ + var error_union_type_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, io, tid, .{ .error_union_type = .{ .error_set_type = error_set_type, .payload_type = key.bare_return_type, } }, 2); defer error_union_type_gop.deinit(); error_union_type_gop.putTentative(error_union_type); - var error_set_type_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, .{ + var error_set_type_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, io, tid, .{ .inferred_error_set_type = func_index, }, 1); defer error_set_type_gop.deinit(); error_set_type_gop.putTentative(error_set_type); - var func_ty_gop = try ip.getOrPutKey(gpa, tid, .{ + var func_ty_gop = try ip.getOrPutKey(gpa, io, tid, .{ .func_type = extraFuncType(tid, extra.list.*, func_type_extra_index), }); defer func_ty_gop.deinit(); @@ -9536,17 +9643,18 @@ pub fn getFuncDeclIes( pub fn getErrorSetType( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, names: []const NullTerminatedString, ) Allocator.Error!Index { assert(std.sort.isSorted(NullTerminatedString, names, {}, NullTerminatedString.indexLessThan)); const local = ip.getLocal(tid); - const items = local.getMutableItems(gpa); - const extra = local.getMutableExtra(gpa); + const items = local.getMutableItems(gpa, io); + const extra = local.getMutableExtra(gpa, io); try extra.ensureUnusedCapacity(@typeInfo(Tag.ErrorSet).@"struct".fields.len + names.len); - const names_map = try ip.addMap(gpa, tid, names.len); + const names_map = try ip.addMap(gpa, io, tid, names.len); errdefer local.mutate.maps.len -= 1; // The strategy here is to add the type unconditionally, then to ask if it @@ -9562,7 +9670,7 @@ pub fn getErrorSetType( extra.appendSliceAssumeCapacity(.{@ptrCast(names)}); errdefer extra.mutate.len = prev_extra_len; - var gop = try ip.getOrPutKey(gpa, tid, .{ + var gop = try ip.getOrPutKey(gpa, io, tid, .{ .error_set_type = extraErrorSet(tid, extra.list.*, error_set_extra_index), }); defer gop.deinit(); @@ -9599,16 +9707,17 @@ pub const GetFuncInstanceKey = struct { pub fn getFuncInstance( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, arg: GetFuncInstanceKey, ) Allocator.Error!Index { if (arg.inferred_error_set) - return getFuncInstanceIes(ip, gpa, tid, arg); + return getFuncInstanceIes(ip, gpa, io, tid, arg); const generic_owner = unwrapCoercedFunc(ip, arg.generic_owner); const generic_owner_ty = ip.indexToKey(ip.funcDeclInfo(generic_owner).ty).func_type; - const func_ty = try ip.getFuncType(gpa, tid, .{ + const func_ty = try ip.getFuncType(gpa, io, tid, .{ .param_types = arg.param_types, .return_type = arg.bare_return_type, .noalias_bits = arg.noalias_bits, @@ -9617,8 +9726,8 @@ pub fn getFuncInstance( }); const local = ip.getLocal(tid); - const items = local.getMutableItems(gpa); - const extra = local.getMutableExtra(gpa); + const items = local.getMutableItems(gpa, io); + const extra = local.getMutableExtra(gpa, io); try extra.ensureUnusedCapacity(@typeInfo(Tag.FuncInstance).@"struct".fields.len + arg.comptime_args.len); @@ -9646,7 +9755,7 @@ pub fn getFuncInstance( }); extra.appendSliceAssumeCapacity(.{@ptrCast(arg.comptime_args)}); - var gop = try ip.getOrPutKey(gpa, tid, .{ + var gop = try ip.getOrPutKey(gpa, io, tid, .{ .func = ip.extraFuncInstance(tid, extra.list.*, func_extra_index), }); defer gop.deinit(); @@ -9664,6 +9773,7 @@ pub fn getFuncInstance( try finishFuncInstance( ip, gpa, + io, tid, extra, generic_owner, @@ -9676,9 +9786,10 @@ pub fn getFuncInstance( /// This function exists separately than `getFuncInstance` because it needs to /// create 4 new items in the InternPool atomically before it can look for an /// existing item in the map. -pub fn getFuncInstanceIes( +fn getFuncInstanceIes( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, arg: GetFuncInstanceKey, ) Allocator.Error!Index { @@ -9688,8 +9799,8 @@ pub fn getFuncInstanceIes( for (arg.param_types) |param_type| assert(param_type != .none); const local = ip.getLocal(tid); - const items = local.getMutableItems(gpa); - const extra = local.getMutableExtra(gpa); + const items = local.getMutableItems(gpa, io); + const extra = local.getMutableExtra(gpa, io); try items.ensureUnusedCapacity(4); const generic_owner = unwrapCoercedFunc(ip, arg.generic_owner); @@ -9784,7 +9895,7 @@ pub fn getFuncInstanceIes( extra.mutate.len = prev_extra_len; } - var func_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, .{ + var func_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, io, tid, .{ .func = ip.extraFuncInstance(tid, extra.list.*, func_extra_index), }, 3); defer func_gop.deinit(); @@ -9795,18 +9906,18 @@ pub fn getFuncInstanceIes( return func_gop.existing; } func_gop.putTentative(func_index); - var error_union_type_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, .{ .error_union_type = .{ + var error_union_type_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, io, tid, .{ .error_union_type = .{ .error_set_type = error_set_type, .payload_type = arg.bare_return_type, } }, 2); defer error_union_type_gop.deinit(); error_union_type_gop.putTentative(error_union_type); - var error_set_type_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, .{ + var error_set_type_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, io, tid, .{ .inferred_error_set_type = func_index, }, 1); defer error_set_type_gop.deinit(); error_set_type_gop.putTentative(error_set_type); - var func_ty_gop = try ip.getOrPutKey(gpa, tid, .{ + var func_ty_gop = try ip.getOrPutKey(gpa, io, tid, .{ .func_type = extraFuncType(tid, extra.list.*, func_type_extra_index), }); defer func_ty_gop.deinit(); @@ -9814,6 +9925,7 @@ pub fn getFuncInstanceIes( try finishFuncInstance( ip, gpa, + io, tid, extra, generic_owner, @@ -9831,6 +9943,7 @@ pub fn getFuncInstanceIes( fn finishFuncInstance( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, extra: Local.Extra.Mutable, generic_owner: Index, @@ -9841,12 +9954,12 @@ fn finishFuncInstance( const fn_namespace = fn_owner_nav.analysis.?.namespace; // TODO: improve this name - const nav_name = try ip.getOrPutStringFmt(gpa, tid, "{f}__anon_{d}", .{ + const nav_name = try ip.getOrPutStringFmt(gpa, io, tid, "{f}__anon_{d}", .{ fn_owner_nav.name.fmt(ip), @intFromEnum(func_index), }, .no_embedded_nulls); - const nav_index = try ip.createNav(gpa, tid, .{ + const nav_index = try ip.createNav(gpa, io, tid, .{ .name = nav_name, - .fqn = try ip.namespacePtr(fn_namespace).internFullyQualifiedName(ip, gpa, tid, nav_name), + .fqn = try ip.namespacePtr(fn_namespace).internFullyQualifiedName(ip, gpa, io, tid, nav_name), .val = func_index, .is_const = fn_owner_nav.status.fully_resolved.is_const, .alignment = fn_owner_nav.status.fully_resolved.alignment, @@ -9967,6 +10080,7 @@ pub const WipEnumType = struct { pub fn getEnumType( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, ini: EnumTypeInit, /// If it is known that there is an existing type with this key which is outdated, @@ -9988,18 +10102,18 @@ pub fn getEnumType( } }, } }; var gop = if (replace_existing) - ip.putKeyReplace(tid, key) + ip.putKeyReplace(io, tid, key) else - try ip.getOrPutKey(gpa, tid, key); + try ip.getOrPutKey(gpa, io, tid, key); defer gop.deinit(); if (gop == .existing) return .{ .existing = gop.existing }; const local = ip.getLocal(tid); - const items = local.getMutableItems(gpa); + const items = local.getMutableItems(gpa, io); try items.ensureUnusedCapacity(1); - const extra = local.getMutableExtra(gpa); + const extra = local.getMutableExtra(gpa, io); - const names_map = try ip.addMap(gpa, tid, ini.fields_len); + const names_map = try ip.addMap(gpa, io, tid, ini.fields_len); errdefer local.mutate.maps.len -= 1; switch (ini.tag_mode) { @@ -10056,7 +10170,7 @@ pub fn getEnumType( }, .explicit, .nonexhaustive => { const values_map: OptionalMapIndex = if (!ini.has_values) .none else m: { - const values_map = try ip.addMap(gpa, tid, ini.fields_len); + const values_map = try ip.addMap(gpa, io, tid, ini.fields_len); break :m values_map.toOptional(); }; errdefer if (ini.has_values) { @@ -10141,6 +10255,7 @@ const GeneratedTagEnumTypeInit = struct { pub fn getGeneratedTagEnumType( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, ini: GeneratedTagEnumTypeInit, ) Allocator.Error!Index { @@ -10149,11 +10264,11 @@ pub fn getGeneratedTagEnumType( for (ini.values) |val| assert(ip.typeOf(val) == ini.tag_ty); const local = ip.getLocal(tid); - const items = local.getMutableItems(gpa); + const items = local.getMutableItems(gpa, io); try items.ensureUnusedCapacity(1); - const extra = local.getMutableExtra(gpa); + const extra = local.getMutableExtra(gpa, io); - const names_map = try ip.addMap(gpa, tid, ini.names.len); + const names_map = try ip.addMap(gpa, io, tid, ini.names.len); errdefer local.mutate.maps.len -= 1; ip.addStringsToMap(names_map, ini.names); @@ -10165,7 +10280,7 @@ pub fn getGeneratedTagEnumType( .index = items.mutate.len, }, ip); const parent_namespace = ip.namespacePtr(ini.parent_namespace); - const namespace = try ip.createNamespace(gpa, tid, .{ + const namespace = try ip.createNamespace(gpa, io, tid, .{ .parent = ini.parent_namespace.toOptional(), .owner_type = enum_index, .file_scope = parent_namespace.file_scope, @@ -10202,7 +10317,7 @@ pub fn getGeneratedTagEnumType( ini.values.len); // field values const values_map: OptionalMapIndex = if (ini.values.len != 0) m: { - const map = try ip.addMap(gpa, tid, ini.values.len); + const map = try ip.addMap(gpa, io, tid, ini.values.len); ip.addIndexesToMap(map, ini.values); break :m map.toOptional(); } else .none; @@ -10240,7 +10355,7 @@ pub fn getGeneratedTagEnumType( }, }; - var gop = try ip.getOrPutKey(gpa, tid, .{ .enum_type = .{ + var gop = try ip.getOrPutKey(gpa, io, tid, .{ .enum_type = .{ .generated_tag = .{ .union_type = ini.owner_union_ty }, } }); defer gop.deinit(); @@ -10256,10 +10371,11 @@ pub const OpaqueTypeInit = struct { pub fn getOpaqueType( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, ini: OpaqueTypeInit, ) Allocator.Error!WipNamespaceType.Result { - var gop = try ip.getOrPutKey(gpa, tid, .{ .opaque_type = .{ .declared = .{ + var gop = try ip.getOrPutKey(gpa, io, tid, .{ .opaque_type = .{ .declared = .{ .zir_index = ini.zir_index, .captures = .{ .external = ini.captures }, } } }); @@ -10267,8 +10383,8 @@ pub fn getOpaqueType( if (gop == .existing) return .{ .existing = gop.existing }; const local = ip.getLocal(tid); - const items = local.getMutableItems(gpa); - const extra = local.getMutableExtra(gpa); + const items = local.getMutableItems(gpa, io); + const extra = local.getMutableExtra(gpa, io); try items.ensureUnusedCapacity(1); try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeOpaque).@"struct".fields.len + ini.captures.len); @@ -10338,8 +10454,8 @@ fn addIndexesToMap( } } -fn addMap(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, cap: usize) Allocator.Error!MapIndex { - const maps = ip.getLocal(tid).getMutableMaps(gpa); +fn addMap(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, cap: usize) Allocator.Error!MapIndex { + const maps = ip.getLocal(tid).getMutableMaps(gpa, io); const unwrapped: MapIndex.Unwrapped = .{ .tid = tid, .index = maps.mutate.len }; const ptr = try maps.addOne(); errdefer maps.mutate.len = unwrapped.index; @@ -10373,14 +10489,15 @@ pub fn remove(ip: *InternPool, tid: Zcu.PerThread.Id, index: Index) void { fn addInt( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, ty: Index, tag: Tag, limbs: []const Limb, ) !void { const local = ip.getLocal(tid); - const items_list = local.getMutableItems(gpa); - const limbs_list = local.getMutableLimbs(gpa); + const items_list = local.getMutableItems(gpa, io); + const limbs_list = local.getMutableLimbs(gpa, io); const limbs_len: u32 = @intCast(limbs.len); try limbs_list.ensureUnusedCapacity(Int.limbs_items_len + limbs_len); items_list.appendAssumeCapacity(.{ @@ -10510,28 +10627,29 @@ fn extraData(extra: Local.Extra, comptime T: type, index: u32) T { test "basic usage" { const gpa = std.testing.allocator; + const io = std.testing.io; var ip: InternPool = .empty; - try ip.init(gpa, 1); - defer ip.deinit(gpa); + try ip.init(gpa, io, 1); + defer ip.deinit(gpa, io); - const i32_type = try ip.get(gpa, .main, .{ .int_type = .{ + const i32_type = try ip.get(gpa, io, .main, .{ .int_type = .{ .signedness = .signed, .bits = 32, } }); - const array_i32 = try ip.get(gpa, .main, .{ .array_type = .{ + const array_i32 = try ip.get(gpa, io, .main, .{ .array_type = .{ .len = 10, .child = i32_type, .sentinel = .none, } }); - const another_i32_type = try ip.get(gpa, .main, .{ .int_type = .{ + const another_i32_type = try ip.get(gpa, io, .main, .{ .int_type = .{ .signedness = .signed, .bits = 32, } }); try std.testing.expect(another_i32_type == i32_type); - const another_array_i32 = try ip.get(gpa, .main, .{ .array_type = .{ + const another_array_i32 = try ip.get(gpa, io, .main, .{ .array_type = .{ .len = 10, .child = i32_type, .sentinel = .none, @@ -10608,6 +10726,7 @@ pub fn sliceLen(ip: *const InternPool, index: Index) Index { pub fn getCoerced( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, val: Index, new_ty: Index, @@ -10616,22 +10735,22 @@ pub fn getCoerced( if (old_ty == new_ty) return val; switch (val) { - .undef => return ip.get(gpa, tid, .{ .undef = new_ty }), + .undef => return ip.get(gpa, io, tid, .{ .undef = new_ty }), .null_value => { - if (ip.isOptionalType(new_ty)) return ip.get(gpa, tid, .{ .opt = .{ + if (ip.isOptionalType(new_ty)) return ip.get(gpa, io, tid, .{ .opt = .{ .ty = new_ty, .val = .none, } }); if (ip.isPointerType(new_ty)) switch (ip.indexToKey(new_ty).ptr_type.flags.size) { - .one, .many, .c => return ip.get(gpa, tid, .{ .ptr = .{ + .one, .many, .c => return ip.get(gpa, io, tid, .{ .ptr = .{ .ty = new_ty, .base_addr = .int, .byte_offset = 0, } }), - .slice => return ip.get(gpa, tid, .{ .slice = .{ + .slice => return ip.get(gpa, io, tid, .{ .slice = .{ .ty = new_ty, - .ptr = try ip.get(gpa, tid, .{ .ptr = .{ + .ptr = try ip.get(gpa, io, tid, .{ .ptr = .{ .ty = ip.slicePtrType(new_ty), .base_addr = .int, .byte_offset = 0, @@ -10644,15 +10763,15 @@ pub fn getCoerced( const unwrapped_val = val.unwrap(ip); const val_item = unwrapped_val.getItem(ip); switch (val_item.tag) { - .func_decl => return getCoercedFuncDecl(ip, gpa, tid, val, new_ty), - .func_instance => return getCoercedFuncInstance(ip, gpa, tid, val, new_ty), + .func_decl => return getCoercedFuncDecl(ip, gpa, io, tid, val, new_ty), + .func_instance => return getCoercedFuncInstance(ip, gpa, io, tid, val, new_ty), .func_coerced => { const func: Index = @enumFromInt(unwrapped_val.getExtra(ip).view().items(.@"0")[ val_item.data + std.meta.fieldIndex(Tag.FuncCoerced, "func").? ]); switch (func.unwrap(ip).getTag(ip)) { - .func_decl => return getCoercedFuncDecl(ip, gpa, tid, val, new_ty), - .func_instance => return getCoercedFuncInstance(ip, gpa, tid, val, new_ty), + .func_decl => return getCoercedFuncDecl(ip, gpa, io, tid, val, new_ty), + .func_instance => return getCoercedFuncInstance(ip, gpa, io, tid, val, new_ty), else => unreachable, } }, @@ -10662,16 +10781,16 @@ pub fn getCoerced( } switch (ip.indexToKey(val)) { - .undef => return ip.get(gpa, tid, .{ .undef = new_ty }), + .undef => return ip.get(gpa, io, tid, .{ .undef = new_ty }), .func => unreachable, .int => |int| switch (ip.indexToKey(new_ty)) { - .enum_type => return ip.get(gpa, tid, .{ .enum_tag = .{ + .enum_type => return ip.get(gpa, io, tid, .{ .enum_tag = .{ .ty = new_ty, - .int = try ip.getCoerced(gpa, tid, val, ip.loadEnumType(new_ty).tag_ty), + .int = try ip.getCoerced(gpa, io, tid, val, ip.loadEnumType(new_ty).tag_ty), } }), .ptr_type => switch (int.storage) { - inline .u64, .i64 => |int_val| return ip.get(gpa, tid, .{ .ptr = .{ + inline .u64, .i64 => |int_val| return ip.get(gpa, io, tid, .{ .ptr = .{ .ty = new_ty, .base_addr = .int, .byte_offset = @intCast(int_val), @@ -10680,7 +10799,7 @@ pub fn getCoerced( .lazy_align, .lazy_size => {}, }, else => if (ip.isIntegerType(new_ty)) - return ip.getCoercedInts(gpa, tid, int, new_ty), + return ip.getCoercedInts(gpa, io, tid, int, new_ty), }, .float => |float| switch (ip.indexToKey(new_ty)) { .simple_type => |simple| switch (simple) { @@ -10691,7 +10810,7 @@ pub fn getCoerced( .f128, .c_longdouble, .comptime_float, - => return ip.get(gpa, tid, .{ .float = .{ + => return ip.get(gpa, io, tid, .{ .float = .{ .ty = new_ty, .storage = float.storage, } }), @@ -10700,17 +10819,17 @@ pub fn getCoerced( else => {}, }, .enum_tag => |enum_tag| if (ip.isIntegerType(new_ty)) - return ip.getCoercedInts(gpa, tid, ip.indexToKey(enum_tag.int).int, new_ty), + return ip.getCoercedInts(gpa, io, tid, ip.indexToKey(enum_tag.int).int, new_ty), .enum_literal => |enum_literal| switch (ip.indexToKey(new_ty)) { .enum_type => { const enum_type = ip.loadEnumType(new_ty); const index = enum_type.nameIndex(ip, enum_literal).?; - return ip.get(gpa, tid, .{ .enum_tag = .{ + return ip.get(gpa, io, tid, .{ .enum_tag = .{ .ty = new_ty, .int = if (enum_type.values.len != 0) enum_type.values.get(ip)[index] else - try ip.get(gpa, tid, .{ .int = .{ + try ip.get(gpa, io, tid, .{ .int = .{ .ty = enum_type.tag_ty, .storage = .{ .u64 = index }, } }), @@ -10719,22 +10838,22 @@ pub fn getCoerced( else => {}, }, .slice => |slice| if (ip.isPointerType(new_ty) and ip.indexToKey(new_ty).ptr_type.flags.size == .slice) - return ip.get(gpa, tid, .{ .slice = .{ + return ip.get(gpa, io, tid, .{ .slice = .{ .ty = new_ty, - .ptr = try ip.getCoerced(gpa, tid, slice.ptr, ip.slicePtrType(new_ty)), + .ptr = try ip.getCoerced(gpa, io, tid, slice.ptr, ip.slicePtrType(new_ty)), .len = slice.len, } }) else if (ip.isIntegerType(new_ty)) - return ip.getCoerced(gpa, tid, slice.ptr, new_ty), + return ip.getCoerced(gpa, io, tid, slice.ptr, new_ty), .ptr => |ptr| if (ip.isPointerType(new_ty) and ip.indexToKey(new_ty).ptr_type.flags.size != .slice) - return ip.get(gpa, tid, .{ .ptr = .{ + return ip.get(gpa, io, tid, .{ .ptr = .{ .ty = new_ty, .base_addr = ptr.base_addr, .byte_offset = ptr.byte_offset, } }) else if (ip.isIntegerType(new_ty)) switch (ptr.base_addr) { - .int => return ip.get(gpa, tid, .{ .int = .{ + .int => return ip.get(gpa, io, tid, .{ .int = .{ .ty = .usize_type, .storage = .{ .u64 = @intCast(ptr.byte_offset) }, } }), @@ -10743,14 +10862,14 @@ pub fn getCoerced( .opt => |opt| switch (ip.indexToKey(new_ty)) { .ptr_type => |ptr_type| return switch (opt.val) { .none => switch (ptr_type.flags.size) { - .one, .many, .c => try ip.get(gpa, tid, .{ .ptr = .{ + .one, .many, .c => try ip.get(gpa, io, tid, .{ .ptr = .{ .ty = new_ty, .base_addr = .int, .byte_offset = 0, } }), - .slice => try ip.get(gpa, tid, .{ .slice = .{ + .slice => try ip.get(gpa, io, tid, .{ .slice = .{ .ty = new_ty, - .ptr = try ip.get(gpa, tid, .{ .ptr = .{ + .ptr = try ip.get(gpa, io, tid, .{ .ptr = .{ .ty = ip.slicePtrType(new_ty), .base_addr = .int, .byte_offset = 0, @@ -10758,29 +10877,29 @@ pub fn getCoerced( .len = .undef_usize, } }), }, - else => |payload| try ip.getCoerced(gpa, tid, payload, new_ty), + else => |payload| try ip.getCoerced(gpa, io, tid, payload, new_ty), }, - .opt_type => |child_type| return try ip.get(gpa, tid, .{ .opt = .{ + .opt_type => |child_type| return try ip.get(gpa, io, tid, .{ .opt = .{ .ty = new_ty, .val = switch (opt.val) { .none => .none, - else => try ip.getCoerced(gpa, tid, opt.val, child_type), + else => try ip.getCoerced(gpa, io, tid, opt.val, child_type), }, } }), else => {}, }, .err => |err| if (ip.isErrorSetType(new_ty)) - return ip.get(gpa, tid, .{ .err = .{ + return ip.get(gpa, io, tid, .{ .err = .{ .ty = new_ty, .name = err.name, } }) else if (ip.isErrorUnionType(new_ty)) - return ip.get(gpa, tid, .{ .error_union = .{ + return ip.get(gpa, io, tid, .{ .error_union = .{ .ty = new_ty, .val = .{ .err_name = err.name }, } }), .error_union => |error_union| if (ip.isErrorUnionType(new_ty)) - return ip.get(gpa, tid, .{ .error_union = .{ + return ip.get(gpa, io, tid, .{ .error_union = .{ .ty = new_ty, .val = error_union.val, } }), @@ -10799,20 +10918,20 @@ pub fn getCoerced( }; if (old_ty_child != new_ty_child) break :direct; switch (aggregate.storage) { - .bytes => |bytes| return ip.get(gpa, tid, .{ .aggregate = .{ + .bytes => |bytes| return ip.get(gpa, io, tid, .{ .aggregate = .{ .ty = new_ty, .storage = .{ .bytes = bytes }, } }), .elems => |elems| { const elems_copy = try gpa.dupe(Index, elems[0..new_len]); defer gpa.free(elems_copy); - return ip.get(gpa, tid, .{ .aggregate = .{ + return ip.get(gpa, io, tid, .{ .aggregate = .{ .ty = new_ty, .storage = .{ .elems = elems_copy }, } }); }, .repeated_elem => |elem| { - return ip.get(gpa, tid, .{ .aggregate = .{ + return ip.get(gpa, io, tid, .{ .aggregate = .{ .ty = new_ty, .storage = .{ .repeated_elem = elem }, } }); @@ -10830,7 +10949,7 @@ pub fn getCoerced( // We have to intern each value here, so unfortunately we can't easily avoid // the repeated indexToKey calls. for (agg_elems, 0..) |*elem, index| { - elem.* = try ip.get(gpa, tid, .{ .int = .{ + elem.* = try ip.get(gpa, io, tid, .{ .int = .{ .ty = .u8_type, .storage = .{ .u64 = bytes.at(index, ip) }, } }); @@ -10847,27 +10966,27 @@ pub fn getCoerced( .struct_type => ip.loadStructType(new_ty).field_types.get(ip)[i], else => unreachable, }; - elem.* = try ip.getCoerced(gpa, tid, elem.*, new_elem_ty); + elem.* = try ip.getCoerced(gpa, io, tid, elem.*, new_elem_ty); } - return ip.get(gpa, tid, .{ .aggregate = .{ .ty = new_ty, .storage = .{ .elems = agg_elems } } }); + return ip.get(gpa, io, tid, .{ .aggregate = .{ .ty = new_ty, .storage = .{ .elems = agg_elems } } }); }, else => {}, } switch (ip.indexToKey(new_ty)) { .opt_type => |child_type| switch (val) { - .null_value => return ip.get(gpa, tid, .{ .opt = .{ + .null_value => return ip.get(gpa, io, tid, .{ .opt = .{ .ty = new_ty, .val = .none, } }), - else => return ip.get(gpa, tid, .{ .opt = .{ + else => return ip.get(gpa, io, tid, .{ .opt = .{ .ty = new_ty, - .val = try ip.getCoerced(gpa, tid, val, child_type), + .val = try ip.getCoerced(gpa, io, tid, val, child_type), } }), }, - .error_union_type => |error_union_type| return ip.get(gpa, tid, .{ .error_union = .{ + .error_union_type => |error_union_type| return ip.get(gpa, io, tid, .{ .error_union = .{ .ty = new_ty, - .val = .{ .payload = try ip.getCoerced(gpa, tid, val, error_union_type.payload_type) }, + .val = .{ .payload = try ip.getCoerced(gpa, io, tid, val, error_union_type.payload_type) }, } }), else => {}, } @@ -10884,6 +11003,7 @@ pub fn getCoerced( fn getCoercedFuncDecl( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, val: Index, new_ty: Index, @@ -10893,12 +11013,13 @@ fn getCoercedFuncDecl( unwrapped_val.getData(ip) + std.meta.fieldIndex(Tag.FuncDecl, "ty").? ]); if (new_ty == prev_ty) return val; - return getCoercedFunc(ip, gpa, tid, val, new_ty); + return getCoercedFunc(ip, gpa, io, tid, val, new_ty); } fn getCoercedFuncInstance( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, val: Index, new_ty: Index, @@ -10908,20 +11029,21 @@ fn getCoercedFuncInstance( unwrapped_val.getData(ip) + std.meta.fieldIndex(Tag.FuncInstance, "ty").? ]); if (new_ty == prev_ty) return val; - return getCoercedFunc(ip, gpa, tid, val, new_ty); + return getCoercedFunc(ip, gpa, io, tid, val, new_ty); } fn getCoercedFunc( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, func: Index, ty: Index, ) Allocator.Error!Index { const local = ip.getLocal(tid); - const items = local.getMutableItems(gpa); + const items = local.getMutableItems(gpa, io); try items.ensureUnusedCapacity(1); - const extra = local.getMutableExtra(gpa); + const extra = local.getMutableExtra(gpa, io); const prev_extra_len = extra.mutate.len; try extra.ensureUnusedCapacity(@typeInfo(Tag.FuncCoerced).@"struct".fields.len); @@ -10932,7 +11054,7 @@ fn getCoercedFunc( }); errdefer extra.mutate.len = prev_extra_len; - var gop = try ip.getOrPutKey(gpa, tid, .{ + var gop = try ip.getOrPutKey(gpa, io, tid, .{ .func = ip.extraFuncCoerced(extra.list.*, extra_index), }); defer gop.deinit(); @@ -10950,8 +11072,15 @@ fn getCoercedFunc( /// Asserts `val` has an integer type. /// Assumes `new_ty` is an integer type. -pub fn getCoercedInts(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, int: Key.Int, new_ty: Index) Allocator.Error!Index { - return ip.get(gpa, tid, .{ .int = .{ +pub fn getCoercedInts( + ip: *InternPool, + gpa: Allocator, + io: Io, + tid: Zcu.PerThread.Id, + int: Key.Int, + new_ty: Index, +) Allocator.Error!Index { + return ip.get(gpa, io, tid, .{ .int = .{ .ty = new_ty, .storage = int.storage, } }); @@ -11047,12 +11176,12 @@ pub fn errorUnionPayload(ip: *const InternPool, ty: Index) Index { } /// The is only legal because the initializer is not part of the hash. -pub fn mutateVarInit(ip: *InternPool, index: Index, init_index: Index) void { +pub fn mutateVarInit(ip: *InternPool, io: Io, index: Index, init_index: Index) void { const unwrapped_index = index.unwrap(ip); const local = ip.getLocal(unwrapped_index.tid); - local.mutate.extra.mutex.lock(); - defer local.mutate.extra.mutex.unlock(); + local.mutate.extra.mutex.lockUncancelable(io); + defer local.mutate.extra.mutex.unlock(io); const extra_items = local.shared.extra.view().items(.@"0"); const item = unwrapped_index.getItem(ip); @@ -11061,11 +11190,15 @@ pub fn mutateVarInit(ip: *InternPool, index: Index, init_index: Index) void { } pub fn dump(ip: *const InternPool) void { - dumpStatsFallible(ip, std.heap.page_allocator) catch return; - dumpAllFallible(ip) catch return; + var buffer: [4096]u8 = undefined; + const stderr = std.debug.lockStderr(&buffer); + defer std.debug.unlockStderr(); + const w = &stderr.file_writer.interface; + dumpStatsFallible(ip, w, std.heap.page_allocator) catch return; + dumpAllFallible(ip, w) catch return; } -fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { +fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !void { var items_len: usize = 0; var extra_len: usize = 0; var limbs_len: usize = 0; @@ -11318,18 +11451,13 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { }; counts.sort(SortContext{ .map = &counts }); const len = @min(50, counts.count()); - std.debug.print(" top 50 tags:\n", .{}); + try w.print(" top 50 tags:\n", .{}); for (counts.keys()[0..len], counts.values()[0..len]) |tag, stats| { - std.debug.print(" {s}: {d} occurrences, {d} total bytes\n", .{ - @tagName(tag), stats.count, stats.bytes, - }); + try w.print(" {t}: {d} occurrences, {d} total bytes\n", .{ tag, stats.count, stats.bytes }); } } -fn dumpAllFallible(ip: *const InternPool) anyerror!void { - var buffer: [4096]u8 = undefined; - const stderr_bw, _ = std.debug.lockStderrWriter(&buffer); - defer std.debug.unlockStderrWriter(); +fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void { for (ip.locals, 0..) |*local, tid| { const items = local.shared.items.view(); for ( @@ -11338,12 +11466,12 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { 0.., ) |tag, data, index| { const i = Index.Unwrapped.wrap(.{ .tid = @enumFromInt(tid), .index = @intCast(index) }, ip); - try stderr_bw.print("${d} = {s}(", .{ i, @tagName(tag) }); + try w.print("${d} = {s}(", .{ i, @tagName(tag) }); switch (tag) { .removed => {}, - .simple_type => try stderr_bw.print("{s}", .{@tagName(@as(SimpleType, @enumFromInt(@intFromEnum(i))))}), - .simple_value => try stderr_bw.print("{s}", .{@tagName(@as(SimpleValue, @enumFromInt(@intFromEnum(i))))}), + .simple_type => try w.print("{s}", .{@tagName(@as(SimpleType, @enumFromInt(@intFromEnum(i))))}), + .simple_value => try w.print("{s}", .{@tagName(@as(SimpleValue, @enumFromInt(@intFromEnum(i))))}), .type_int_signed, .type_int_unsigned, @@ -11416,23 +11544,27 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { .func_coerced, .union_value, .memoized_call, - => try stderr_bw.print("{d}", .{data}), + => try w.print("{d}", .{data}), .opt_null, .type_slice, .only_possible_value, - => try stderr_bw.print("${d}", .{data}), + => try w.print("${d}", .{data}), } - try stderr_bw.writeAll(")\n"); + try w.writeAll(")\n"); } } } pub fn dumpGenericInstances(ip: *const InternPool, allocator: Allocator) void { - ip.dumpGenericInstancesFallible(allocator) catch return; + var buffer: [4096]u8 = undefined; + const stderr = std.debug.lockStderr(&buffer); + defer std.debug.unlockStderr(); + const w = &stderr.file_writer.interface; + ip.dumpGenericInstancesFallible(allocator, w) catch return; } -pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator) anyerror!void { +pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator, w: *Io.Writer) !void { var arena_allocator = std.heap.ArenaAllocator.init(allocator); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); @@ -11459,10 +11591,6 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator) } } - var buffer: [4096]u8 = undefined; - const stderr_bw, _ = std.debug.lockStderrWriter(&buffer); - defer std.debug.unlockStderrWriter(); - const SortContext = struct { values: []std.ArrayList(Index), pub fn lessThan(ctx: @This(), a_index: usize, b_index: usize) bool { @@ -11474,19 +11602,19 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator) var it = instances.iterator(); while (it.next()) |entry| { const generic_fn_owner_nav = ip.getNav(ip.funcDeclInfo(entry.key_ptr.*).owner_nav); - try stderr_bw.print("{f} ({d}): \n", .{ generic_fn_owner_nav.name.fmt(ip), entry.value_ptr.items.len }); + try w.print("{f} ({d}): \n", .{ generic_fn_owner_nav.name.fmt(ip), entry.value_ptr.items.len }); for (entry.value_ptr.items) |index| { const unwrapped_index = index.unwrap(ip); const func = ip.extraFuncInstance(unwrapped_index.tid, unwrapped_index.getExtra(ip), unwrapped_index.getData(ip)); const owner_nav = ip.getNav(func.owner_nav); - try stderr_bw.print(" {f}: (", .{owner_nav.name.fmt(ip)}); + try w.print(" {f}: (", .{owner_nav.name.fmt(ip)}); for (func.comptime_args.get(ip)) |arg| { if (arg != .none) { const key = ip.indexToKey(arg); - try stderr_bw.print(" {} ", .{key}); + try w.print(" {} ", .{key}); } } - try stderr_bw.writeAll(")\n"); + try w.writeAll(")\n"); } } } @@ -11508,11 +11636,12 @@ pub fn namespacePtr(ip: *InternPool, namespace_index: NamespaceIndex) *Zcu.Names pub fn createComptimeUnit( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, zir_index: TrackedInst.Index, namespace: NamespaceIndex, ) Allocator.Error!ComptimeUnit.Id { - const comptime_units = ip.getLocal(tid).getMutableComptimeUnits(gpa); + const comptime_units = ip.getLocal(tid).getMutableComptimeUnits(gpa, io); const id_unwrapped: ComptimeUnit.Id.Unwrapped = .{ .tid = tid, .index = comptime_units.mutate.len, @@ -11532,9 +11661,10 @@ pub fn getComptimeUnit(ip: *const InternPool, id: ComptimeUnit.Id) ComptimeUnit /// Create a `Nav` which does not undergo semantic analysis. /// Since it is never analyzed, the `Nav`'s value must be known at creation time. -pub fn createNav( +fn createNav( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, opts: struct { name: NullTerminatedString, @@ -11546,7 +11676,7 @@ pub fn createNav( @"addrspace": std.builtin.AddressSpace, }, ) Allocator.Error!Nav.Index { - const navs = ip.getLocal(tid).getMutableNavs(gpa); + const navs = ip.getLocal(tid).getMutableNavs(gpa, io); const index_unwrapped: Nav.Index.Unwrapped = .{ .tid = tid, .index = navs.mutate.len, @@ -11571,13 +11701,14 @@ pub fn createNav( pub fn createDeclNav( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, name: NullTerminatedString, fqn: NullTerminatedString, zir_index: TrackedInst.Index, namespace: NamespaceIndex, ) Allocator.Error!Nav.Index { - const navs = ip.getLocal(tid).getMutableNavs(gpa); + const navs = ip.getLocal(tid).getMutableNavs(gpa, io); try navs.ensureUnusedCapacity(1); @@ -11603,6 +11734,7 @@ pub fn createDeclNav( /// If its status is already `resolved`, the old value is discarded. pub fn resolveNavType( ip: *InternPool, + io: Io, nav: Nav.Index, resolved: struct { type: InternPool.Index, @@ -11617,8 +11749,8 @@ pub fn resolveNavType( const unwrapped = nav.unwrap(ip); const local = ip.getLocal(unwrapped.tid); - local.mutate.extra.mutex.lock(); - defer local.mutate.extra.mutex.unlock(); + local.mutate.extra.mutex.lockUncancelable(io); + defer local.mutate.extra.mutex.unlock(io); const navs = local.shared.navs.view(); @@ -11647,6 +11779,7 @@ pub fn resolveNavType( /// If its status is already `resolved`, the old value is discarded. pub fn resolveNavValue( ip: *InternPool, + io: Io, nav: Nav.Index, resolved: struct { val: InternPool.Index, @@ -11659,8 +11792,8 @@ pub fn resolveNavValue( const unwrapped = nav.unwrap(ip); const local = ip.getLocal(unwrapped.tid); - local.mutate.extra.mutex.lock(); - defer local.mutate.extra.mutex.unlock(); + local.mutate.extra.mutex.lockUncancelable(io); + defer local.mutate.extra.mutex.unlock(io); const navs = local.shared.navs.view(); @@ -11687,6 +11820,7 @@ pub fn resolveNavValue( pub fn createNamespace( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, initialization: Zcu.Namespace, ) Allocator.Error!NamespaceIndex { @@ -11700,7 +11834,7 @@ pub fn createNamespace( reused_namespace.* = initialization; return reused_namespace_index; } - const namespaces = local.getMutableNamespaces(gpa); + const namespaces = local.getMutableNamespaces(gpa, io); const last_bucket_len = local.mutate.namespaces.last_bucket_len & Local.namespaces_bucket_mask; if (last_bucket_len == 0) { try namespaces.ensureUnusedCapacity(1); @@ -11748,10 +11882,11 @@ pub fn filePtr(ip: *const InternPool, file_index: FileIndex) *Zcu.File { pub fn createFile( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, file: File, ) Allocator.Error!FileIndex { - const files = ip.getLocal(tid).getMutableFiles(gpa); + const files = ip.getLocal(tid).getMutableFiles(gpa, io); const file_index_unwrapped: FileIndex.Unwrapped = .{ .tid = tid, .index = files.mutate.len, @@ -11782,20 +11917,22 @@ const EmbeddedNulls = enum { pub fn getOrPutString( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, slice: []const u8, comptime embedded_nulls: EmbeddedNulls, ) Allocator.Error!embedded_nulls.StringType() { - const string_bytes = ip.getLocal(tid).getMutableStringBytes(gpa); + const string_bytes = ip.getLocal(tid).getMutableStringBytes(gpa, io); try string_bytes.ensureUnusedCapacity(slice.len + 1); string_bytes.appendSliceAssumeCapacity(.{slice}); string_bytes.appendAssumeCapacity(.{0}); - return ip.getOrPutTrailingString(gpa, tid, @intCast(slice.len + 1), embedded_nulls); + return ip.getOrPutTrailingString(gpa, io, tid, @intCast(slice.len + 1), embedded_nulls); } pub fn getOrPutStringFmt( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, comptime format: []const u8, args: anytype, @@ -11804,20 +11941,21 @@ pub fn getOrPutStringFmt( // ensure that references to strings in args do not get invalidated const format_z = format ++ .{0}; const len: u32 = @intCast(std.fmt.count(format_z, args)); - const string_bytes = ip.getLocal(tid).getMutableStringBytes(gpa); + const string_bytes = ip.getLocal(tid).getMutableStringBytes(gpa, io); const slice = try string_bytes.addManyAsSlice(len); assert((std.fmt.bufPrint(slice[0], format_z, args) catch unreachable).len == len); - return ip.getOrPutTrailingString(gpa, tid, len, embedded_nulls); + return ip.getOrPutTrailingString(gpa, io, tid, len, embedded_nulls); } pub fn getOrPutStringOpt( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, slice: ?[]const u8, comptime embedded_nulls: EmbeddedNulls, ) Allocator.Error!embedded_nulls.OptionalStringType() { - const string = try getOrPutString(ip, gpa, tid, slice orelse return .none, embedded_nulls); + const string = try getOrPutString(ip, gpa, io, tid, slice orelse return .none, embedded_nulls); return string.toOptional(); } @@ -11825,14 +11963,15 @@ pub fn getOrPutStringOpt( pub fn getOrPutTrailingString( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, len: u32, comptime embedded_nulls: EmbeddedNulls, ) Allocator.Error!embedded_nulls.StringType() { const local = ip.getLocal(tid); - const strings = local.getMutableStrings(gpa); + const strings = local.getMutableStrings(gpa, io); try strings.ensureUnusedCapacity(1); - const string_bytes = local.getMutableStringBytes(gpa); + const string_bytes = local.getMutableStringBytes(gpa, io); const start: u32 = @intCast(string_bytes.mutate.len - len); if (len > 0 and string_bytes.view().items(.@"0")[string_bytes.mutate.len - 1] == 0) { string_bytes.mutate.len -= 1; @@ -11870,8 +12009,8 @@ pub fn getOrPutTrailingString( string_bytes.shrinkRetainingCapacity(start); return @enumFromInt(@intFromEnum(index)); } - shard.mutate.string_map.mutex.lock(); - defer shard.mutate.string_map.mutex.unlock(); + shard.mutate.string_map.mutex.lock(io, tid); + defer shard.mutate.string_map.mutex.unlock(io); if (map.entries != shard.shared.string_map.entries) { map = shard.shared.string_map; map_mask = map.header().mask(); @@ -12590,11 +12729,11 @@ pub fn funcAnalysisUnordered(ip: *const InternPool, func: Index) FuncAnalysis { return @atomicLoad(FuncAnalysis, ip.funcAnalysisPtr(func), .unordered); } -pub fn funcSetHasErrorTrace(ip: *InternPool, func: Index, has_error_trace: bool) void { +pub fn funcSetHasErrorTrace(ip: *InternPool, io: Io, func: Index, has_error_trace: bool) void { const unwrapped_func = func.unwrap(ip); const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const analysis_ptr = ip.funcAnalysisPtr(func); var analysis = analysis_ptr.*; @@ -12602,11 +12741,11 @@ pub fn funcSetHasErrorTrace(ip: *InternPool, func: Index, has_error_trace: bool) @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release); } -pub fn funcSetDisableInstrumentation(ip: *InternPool, func: Index) void { +pub fn funcSetDisableInstrumentation(ip: *InternPool, io: Io, func: Index) void { const unwrapped_func = func.unwrap(ip); const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const analysis_ptr = ip.funcAnalysisPtr(func); var analysis = analysis_ptr.*; @@ -12614,11 +12753,11 @@ pub fn funcSetDisableInstrumentation(ip: *InternPool, func: Index) void { @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release); } -pub fn funcSetDisableIntrinsics(ip: *InternPool, func: Index) void { +pub fn funcSetDisableIntrinsics(ip: *InternPool, io: Io, func: Index) void { const unwrapped_func = func.unwrap(ip); const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); const analysis_ptr = ip.funcAnalysisPtr(func); var analysis = analysis_ptr.*; @@ -12663,15 +12802,6 @@ pub fn iesFuncIndex(ip: *const InternPool, ies_index: Index) Index { return func_index; } -/// Returns a mutable pointer to the resolved error set type of an inferred -/// error set function. The returned pointer is invalidated when anything is -/// added to `ip`. -fn iesResolvedPtr(ip: *InternPool, ies_index: Index) *Index { - const ies_item = ies_index.getItem(ip); - assert(ies_item.tag == .type_inferred_error_set); - return ip.funcIesResolvedPtr(ies_item.data); -} - /// Returns a mutable pointer to the resolved error set type of an inferred /// error set function. The returned pointer is invalidated when anything is /// added to `ip`. @@ -12706,11 +12836,11 @@ pub fn funcIesResolvedUnordered(ip: *const InternPool, index: Index) Index { return @atomicLoad(Index, ip.funcIesResolvedPtr(index), .unordered); } -pub fn funcSetIesResolved(ip: *InternPool, index: Index, ies: Index) void { +pub fn funcSetIesResolved(ip: *InternPool, io: Io, index: Index, ies: Index) void { const unwrapped_func = index.unwrap(ip); const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); + extra_mutex.lockUncancelable(io); + defer extra_mutex.unlock(io); @atomicStore(Index, ip.funcIesResolvedPtr(index), ies, .release); } @@ -12777,19 +12907,19 @@ const GlobalErrorSet = struct { } align(std.atomic.cache_line), mutate: struct { names: Local.ListMutate, - map: struct { mutex: std.Thread.Mutex }, + map: struct { mutex: Io.Mutex }, } align(std.atomic.cache_line), const Names = Local.List(struct { NullTerminatedString }); const empty: GlobalErrorSet = .{ .shared = .{ - .names = Names.empty, - .map = Shard.Map(GlobalErrorSet.Index).empty, + .names = .empty, + .map = .empty, }, .mutate = .{ - .names = Local.ListMutate.empty, - .map = .{ .mutex = .{} }, + .names = .empty, + .map = .{ .mutex = .init }, }, }; @@ -12807,6 +12937,7 @@ const GlobalErrorSet = struct { fn getErrorValue( ges: *GlobalErrorSet, gpa: Allocator, + io: Io, arena_state: *std.heap.ArenaAllocator.State, name: NullTerminatedString, ) Allocator.Error!GlobalErrorSet.Index { @@ -12825,8 +12956,8 @@ const GlobalErrorSet = struct { if (entry.hash != hash) continue; if (names.view().items(.@"0")[@intFromEnum(index) - 1] == name) return index; } - ges.mutate.map.mutex.lock(); - defer ges.mutate.map.mutex.unlock(); + ges.mutate.map.mutex.lockUncancelable(io); + defer ges.mutate.map.mutex.unlock(io); if (map.entries != ges.shared.map.entries) { map = ges.shared.map; map_mask = map.header().mask(); @@ -12842,6 +12973,7 @@ const GlobalErrorSet = struct { } const mutable_names: Names.Mutable = .{ .gpa = gpa, + .io = io, .arena = arena_state, .mutate = &ges.mutate.names, .list = &ges.shared.names, @@ -12923,10 +13055,11 @@ const GlobalErrorSet = struct { pub fn getErrorValue( ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, name: NullTerminatedString, ) Allocator.Error!Zcu.ErrorInt { - return @intFromEnum(try ip.global_error_set.getErrorValue(gpa, &ip.getLocal(tid).mutate.arena, name)); + return @intFromEnum(try ip.global_error_set.getErrorValue(gpa, io, &ip.getLocal(tid).mutate.arena, name)); } pub fn getErrorValueIfExists(ip: *const InternPool, name: NullTerminatedString) ?Zcu.ErrorInt { diff --git a/src/Package.zig b/src/Package.zig index 9f05f33a469a..fda4c1c1783b 100644 --- a/src/Package.zig +++ b/src/Package.zig @@ -14,9 +14,9 @@ pub const Fingerprint = packed struct(u64) { id: u32, checksum: u32, - pub fn generate(name: []const u8) Fingerprint { + pub fn generate(rng: std.Random, name: []const u8) Fingerprint { return .{ - .id = std.crypto.random.intRangeLessThan(u32, 1, 0xffffffff), + .id = rng.intRangeLessThan(u32, 1, 0xffffffff), .checksum = std.hash.Crc32.hash(name), }; } diff --git a/src/Package/Fetch.zig b/src/Package/Fetch.zig index 9b7c83cc3915..d42e441d77c7 100644 --- a/src/Package/Fetch.zig +++ b/src/Package/Fetch.zig @@ -146,6 +146,8 @@ pub const JobQueue = struct { pub const UnlazySet = std.AutoArrayHashMapUnmanaged(Package.Hash, void); pub fn deinit(jq: *JobQueue) void { + const io = jq.io; + jq.group.cancel(io); if (jq.all_fetches.items.len == 0) return; const gpa = jq.all_fetches.items[0].arena.child_allocator; jq.table.deinit(gpa); @@ -383,14 +385,14 @@ pub fn run(f: *Fetch) RunError!void { }, .remote => |remote| remote, .path_or_url => |path_or_url| { - if (fs.cwd().openDir(path_or_url, .{ .iterate = true })) |dir| { + if (Io.Dir.cwd().openDir(io, path_or_url, .{ .iterate = true })) |dir| { var resource: Resource = .{ .dir = dir }; return f.runResource(path_or_url, &resource, null); } else |dir_err| { var server_header_buffer: [init_resource_buffer_size]u8 = undefined; const file_err = if (dir_err == error.NotDir) e: { - if (fs.cwd().openFile(path_or_url, .{})) |file| { + if (Io.Dir.cwd().openFile(io, path_or_url, .{})) |file| { var resource: Resource = .{ .file = file.reader(io, &server_header_buffer) }; return f.runResource(path_or_url, &resource, null); } else |err| break :e err; @@ -418,7 +420,7 @@ pub fn run(f: *Fetch) RunError!void { const prefixed_pkg_sub_path = prefixed_pkg_sub_path_buffer[0 .. 2 + hash_slice.len]; const prefix_len: usize = if (f.job_queue.read_only) "p/".len else 0; const pkg_sub_path = prefixed_pkg_sub_path[prefix_len..]; - if (cache_root.handle.access(pkg_sub_path, .{})) |_| { + if (cache_root.handle.access(io, pkg_sub_path, .{})) |_| { assert(f.lazy_status != .unavailable); f.package_root = .{ .root_dir = cache_root, @@ -492,7 +494,11 @@ fn runResource( const eb = &f.error_bundle; const s = fs.path.sep_str; const cache_root = f.job_queue.global_cache; - const rand_int = std.crypto.random.int(u64); + const rand_int = r: { + var x: u64 = undefined; + io.random(@ptrCast(&x)); + break :r x; + }; const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(rand_int); const package_sub_path = blk: { @@ -500,12 +506,12 @@ fn runResource( var tmp_directory: Cache.Directory = .{ .path = tmp_directory_path, .handle = handle: { - const dir = cache_root.handle.makeOpenPath(tmp_dir_sub_path, .{ - .iterate = true, + const dir = cache_root.handle.createDirPathOpen(io, tmp_dir_sub_path, .{ + .open_options = .{ .iterate = true }, }) catch |err| { try eb.addRootErrorMessage(.{ - .msg = try eb.printString("unable to create temporary directory '{s}': {s}", .{ - tmp_directory_path, @errorName(err), + .msg = try eb.printString("unable to create temporary directory '{s}': {t}", .{ + tmp_directory_path, err, }), }); return error.FetchFailed; @@ -513,7 +519,7 @@ fn runResource( break :handle dir; }, }; - defer tmp_directory.handle.close(); + defer tmp_directory.handle.close(io); // Fetch and unpack a resource into a temporary directory. var unpack_result = try unpackResource(f, resource, uri_path, tmp_directory); @@ -523,9 +529,9 @@ fn runResource( // Apply btrfs workaround if needed. Reopen tmp_directory. if (native_os == .linux and f.job_queue.work_around_btrfs_bug) { // https://github.com/ziglang/zig/issues/17095 - pkg_path.root_dir.handle.close(); - pkg_path.root_dir.handle = cache_root.handle.makeOpenPath(tmp_dir_sub_path, .{ - .iterate = true, + pkg_path.root_dir.handle.close(io); + pkg_path.root_dir.handle = cache_root.handle.createDirPathOpen(io, tmp_dir_sub_path, .{ + .open_options = .{ .iterate = true }, }) catch @panic("btrfs workaround failed"); } @@ -567,7 +573,7 @@ fn runResource( .root_dir = cache_root, .sub_path = try std.fmt.allocPrint(arena, "p" ++ s ++ "{s}", .{computed_package_hash.toSlice()}), }; - renameTmpIntoCache(cache_root.handle, package_sub_path, f.package_root.sub_path) catch |err| { + renameTmpIntoCache(io, cache_root.handle, package_sub_path, f.package_root.sub_path) catch |err| { const src = try cache_root.join(arena, &.{tmp_dir_sub_path}); const dest = try cache_root.join(arena, &.{f.package_root.sub_path}); try eb.addRootErrorMessage(.{ .msg = try eb.printString( @@ -578,7 +584,7 @@ fn runResource( }; // Remove temporary directory root if not already renamed to global cache. if (!std.mem.eql(u8, package_sub_path, tmp_dir_sub_path)) { - cache_root.handle.deleteDir(tmp_dir_sub_path) catch {}; + cache_root.handle.deleteDir(io, tmp_dir_sub_path) catch {}; } // Validate the computed hash against the expected hash. If invalid, this @@ -637,8 +643,9 @@ pub fn computedPackageHash(f: *const Fetch) Package.Hash { /// `computeHash` gets a free check for the existence of `build.zig`, but when /// not computing a hash, we need to do a syscall to check for it. fn checkBuildFileExistence(f: *Fetch) RunError!void { + const io = f.job_queue.io; const eb = &f.error_bundle; - if (f.package_root.access(Package.build_zig_basename, .{})) |_| { + if (f.package_root.access(io, Package.build_zig_basename, .{})) |_| { f.has_build_zig = true; } else |err| switch (err) { error.FileNotFound => {}, @@ -655,9 +662,11 @@ fn checkBuildFileExistence(f: *Fetch) RunError!void { /// This function populates `f.manifest` or leaves it `null`. fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void { + const io = f.job_queue.io; const eb = &f.error_bundle; const arena = f.arena.allocator(); const manifest_bytes = pkg_root.root_dir.handle.readFileAllocOptions( + io, try fs.path.join(arena, &.{ pkg_root.sub_path, Manifest.basename }), arena, .limited(Manifest.max_bytes), @@ -685,7 +694,9 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void { return error.FetchFailed; } - f.manifest = try Manifest.parse(arena, ast.*, .{ + const rng: std.Random.IoSource = .{ .io = io }; + + f.manifest = try Manifest.parse(arena, ast.*, rng.interface(), .{ .allow_missing_paths_field = f.allow_missing_paths_field, .allow_missing_fingerprint = f.allow_missing_fingerprint, .allow_name_string = f.allow_name_string, @@ -838,13 +849,13 @@ pub fn relativePathDigest(pkg_root: Cache.Path, cache_root: Cache.Directory) Pac return .initPath(pkg_root.sub_path, pkg_root.root_dir.eql(cache_root)); } -pub fn workerRun(f: *Fetch, prog_name: []const u8) void { +pub fn workerRun(f: *Fetch, prog_name: []const u8) Io.Cancelable!void { const prog_node = f.prog_node.start(prog_name, 0); defer prog_node.end(); run(f) catch |err| switch (err) { error.OutOfMemory => f.oom_flag = true, - error.Canceled => {}, + error.Canceled => |e| return e, error.FetchFailed => { // Nothing to do because the errors are already reported in `error_bundle`, // and a reference is kept to the `Fetch` task inside `all_fetches`. @@ -882,10 +893,10 @@ fn fail(f: *Fetch, msg_tok: std.zig.Ast.TokenIndex, msg_str: u32) RunError { } const Resource = union(enum) { - file: fs.File.Reader, + file: Io.File.Reader, http_request: HttpRequest, git: Git, - dir: fs.Dir, + dir: Io.Dir, const Git = struct { session: git.Session, @@ -908,7 +919,7 @@ const Resource = union(enum) { .git => |*git_resource| { git_resource.fetch_stream.deinit(); }, - .dir => |*dir| dir.close(), + .dir => |*dir| dir.close(io), } resource.* = undefined; } @@ -995,7 +1006,7 @@ fn initResource(f: *Fetch, uri: std.Uri, resource: *Resource, reader_buffer: []u if (ascii.eqlIgnoreCase(uri.scheme, "file")) { const path = try uri.path.toRawMaybeAlloc(arena); - const file = f.parent_package_root.openFile(path, .{}) catch |err| { + const file = f.parent_package_root.openFile(io, path, .{}) catch |err| { return f.fail(f.location_tok, try eb.printString("unable to open '{f}{s}': {t}", .{ f.parent_package_root, path, err, })); @@ -1247,13 +1258,14 @@ fn unpackResource( } } -fn unpackTarball(f: *Fetch, out_dir: fs.Dir, reader: *Io.Reader) RunError!UnpackResult { +fn unpackTarball(f: *Fetch, out_dir: Io.Dir, reader: *Io.Reader) RunError!UnpackResult { const eb = &f.error_bundle; const arena = f.arena.allocator(); + const io = f.job_queue.io; var diagnostics: std.tar.Diagnostics = .{ .allocator = arena }; - std.tar.pipeToFileSystem(out_dir, reader, .{ + std.tar.pipeToFileSystem(io, out_dir, reader, .{ .diagnostics = &diagnostics, .strip_components = 0, .mode_mode = .ignore, @@ -1280,7 +1292,7 @@ fn unpackTarball(f: *Fetch, out_dir: fs.Dir, reader: *Io.Reader) RunError!Unpack fn unzip( f: *Fetch, - out_dir: fs.Dir, + out_dir: Io.Dir, reader: *Io.Reader, ) error{ ReadFailed, OutOfMemory, Canceled, FetchFailed }!UnpackResult { // We write the entire contents to a file first because zip files @@ -1299,10 +1311,14 @@ fn unzip( zip_path[prefix.len + random_len ..].* = suffix.*; var zip_file = while (true) { - const random_integer = std.crypto.random.int(u64); + const random_integer = r: { + var x: u64 = undefined; + io.random(@ptrCast(&x)); + break :r x; + }; zip_path[prefix.len..][0..random_len].* = std.fmt.hex(random_integer); - break cache_root.handle.createFile(&zip_path, .{ + break cache_root.handle.createFile(io, &zip_path, .{ .exclusive = true, .read = true, }) catch |err| switch (err) { @@ -1314,10 +1330,10 @@ fn unzip( ), }; }; - defer zip_file.close(); + defer zip_file.close(io); var zip_file_buffer: [4096]u8 = undefined; var zip_file_reader = b: { - var zip_file_writer = zip_file.writer(&zip_file_buffer); + var zip_file_writer = zip_file.writer(io, &zip_file_buffer); _ = reader.streamRemaining(&zip_file_writer.interface) catch |err| switch (err) { error.ReadFailed => return error.ReadFailed, @@ -1330,7 +1346,7 @@ fn unzip( f.location_tok, try eb.printString("failed writing temporary zip file: {t}", .{err}), ); - break :b zip_file_writer.moveToReader(io); + break :b zip_file_writer.moveToReader(); }; var diagnostics: std.zip.Diagnostics = .{ .allocator = f.arena.allocator() }; @@ -1343,13 +1359,13 @@ fn unzip( .diagnostics = &diagnostics, }) catch |err| return f.fail(f.location_tok, try eb.printString("zip extract failed: {t}", .{err})); - cache_root.handle.deleteFile(&zip_path) catch |err| + cache_root.handle.deleteFile(io, &zip_path) catch |err| return f.fail(f.location_tok, try eb.printString("delete temporary zip failed: {t}", .{err})); return .{ .root_dir = diagnostics.root_dir }; } -fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!UnpackResult { +fn unpackGitPack(f: *Fetch, out_dir: Io.Dir, resource: *Resource.Git) anyerror!UnpackResult { const io = f.job_queue.io; const arena = f.arena.allocator(); // TODO don't try to get a gpa from an arena. expose this dependency higher up @@ -1362,23 +1378,23 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U // we do not attempt to replicate the exact structure of a real .git // directory, since that isn't relevant for fetching a package. { - var pack_dir = try out_dir.makeOpenPath(".git", .{}); - defer pack_dir.close(); - var pack_file = try pack_dir.createFile("pkg.pack", .{ .read = true }); - defer pack_file.close(); + var pack_dir = try out_dir.createDirPathOpen(io, ".git", .{}); + defer pack_dir.close(io); + var pack_file = try pack_dir.createFile(io, "pkg.pack", .{ .read = true }); + defer pack_file.close(io); var pack_file_buffer: [4096]u8 = undefined; var pack_file_reader = b: { - var pack_file_writer = pack_file.writer(&pack_file_buffer); + var pack_file_writer = pack_file.writer(io, &pack_file_buffer); const fetch_reader = &resource.fetch_stream.reader; _ = try fetch_reader.streamRemaining(&pack_file_writer.interface); try pack_file_writer.interface.flush(); - break :b pack_file_writer.moveToReader(io); + break :b pack_file_writer.moveToReader(); }; - var index_file = try pack_dir.createFile("pkg.idx", .{ .read = true }); - defer index_file.close(); + var index_file = try pack_dir.createFile(io, "pkg.idx", .{ .read = true }); + defer index_file.close(io); var index_file_buffer: [2000]u8 = undefined; - var index_file_writer = index_file.writer(&index_file_buffer); + var index_file_writer = index_file.writer(io, &index_file_buffer); { const index_prog_node = f.prog_node.start("Index pack", 0); defer index_prog_node.end(); @@ -1393,7 +1409,7 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U try repository.init(gpa, object_format, &pack_file_reader, &index_file_reader); defer repository.deinit(); var diagnostics: git.Diagnostics = .{ .allocator = arena }; - try repository.checkout(out_dir, resource.want_oid, &diagnostics); + try repository.checkout(io, out_dir, resource.want_oid, &diagnostics); if (diagnostics.errors.items.len > 0) { try res.allocErrors(arena, diagnostics.errors.items.len, "unable to unpack packfile"); @@ -1407,41 +1423,37 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U } } - try out_dir.deleteTree(".git"); + try out_dir.deleteTree(io, ".git"); return res; } -fn recursiveDirectoryCopy(f: *Fetch, dir: fs.Dir, tmp_dir: fs.Dir) anyerror!void { +fn recursiveDirectoryCopy(f: *Fetch, dir: Io.Dir, tmp_dir: Io.Dir) anyerror!void { const gpa = f.arena.child_allocator; + const io = f.job_queue.io; // Recursive directory copy. var it = try dir.walk(gpa); defer it.deinit(); - while (try it.next()) |entry| { + while (try it.next(io)) |entry| { switch (entry.kind) { .directory => {}, // omit empty directories .file => { - dir.copyFile( - entry.path, - tmp_dir, - entry.path, - .{}, - ) catch |err| switch (err) { + dir.copyFile(entry.path, tmp_dir, entry.path, io, .{}) catch |err| switch (err) { error.FileNotFound => { - if (fs.path.dirname(entry.path)) |dirname| try tmp_dir.makePath(dirname); - try dir.copyFile(entry.path, tmp_dir, entry.path, .{}); + if (fs.path.dirname(entry.path)) |dirname| try tmp_dir.createDirPath(io, dirname); + try dir.copyFile(entry.path, tmp_dir, entry.path, io, .{}); }, else => |e| return e, }; }, .sym_link => { var buf: [fs.max_path_bytes]u8 = undefined; - const link_name = try dir.readLink(entry.path, &buf); + const link_name = buf[0..try dir.readLink(io, entry.path, &buf)]; // TODO: if this would create a symlink to outside // the destination directory, fail with an error instead. - tmp_dir.symLink(link_name, entry.path, .{}) catch |err| switch (err) { + tmp_dir.symLink(io, link_name, entry.path, .{}) catch |err| switch (err) { error.FileNotFound => { - if (fs.path.dirname(entry.path)) |dirname| try tmp_dir.makePath(dirname); - try tmp_dir.symLink(link_name, entry.path, .{}); + if (fs.path.dirname(entry.path)) |dirname| try tmp_dir.createDirPath(io, dirname); + try tmp_dir.symLink(io, link_name, entry.path, .{}); }, else => |e| return e, }; @@ -1451,22 +1463,22 @@ fn recursiveDirectoryCopy(f: *Fetch, dir: fs.Dir, tmp_dir: fs.Dir) anyerror!void } } -pub fn renameTmpIntoCache(cache_dir: fs.Dir, tmp_dir_sub_path: []const u8, dest_dir_sub_path: []const u8) !void { +pub fn renameTmpIntoCache(io: Io, cache_dir: Io.Dir, tmp_dir_sub_path: []const u8, dest_dir_sub_path: []const u8) !void { assert(dest_dir_sub_path[1] == fs.path.sep); var handled_missing_dir = false; while (true) { - cache_dir.rename(tmp_dir_sub_path, dest_dir_sub_path) catch |err| switch (err) { + cache_dir.rename(tmp_dir_sub_path, cache_dir, dest_dir_sub_path, io) catch |err| switch (err) { error.FileNotFound => { if (handled_missing_dir) return err; - cache_dir.makeDir(dest_dir_sub_path[0..1]) catch |mkd_err| switch (mkd_err) { + cache_dir.createDir(io, dest_dir_sub_path[0..1], .default_dir) catch |mkd_err| switch (mkd_err) { error.PathAlreadyExists => handled_missing_dir = true, else => |e| return e, }; continue; }, - error.PathAlreadyExists, error.AccessDenied => { + error.DirNotEmpty, error.AccessDenied => { // Package has been already downloaded and may already be in use on the system. - cache_dir.deleteTree(tmp_dir_sub_path) catch { + cache_dir.deleteTree(io, tmp_dir_sub_path) catch { // Garbage files leftover in zig-cache/tmp/ is, as they say // on Star Trek, "operating within normal parameters". }; @@ -1517,12 +1529,12 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute // The final hash will be a hash of each file hashed independently. This // allows hashing in parallel. var group: Io.Group = .init; - defer group.wait(io); + defer group.cancel(io); - while (walker.next() catch |err| { + while (walker.next(io) catch |err| { try eb.addRootErrorMessage(.{ .msg = try eb.printString( - "unable to walk temporary directory '{f}': {s}", - .{ pkg_path, @errorName(err) }, + "unable to walk temporary directory '{f}': {t}", + .{ pkg_path, err }, ) }); return error.FetchFailed; }) |entry| { @@ -1542,7 +1554,7 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute .fs_path = fs_path, .failure = undefined, // to be populated by the worker }; - group.async(io, workerDeleteFile, .{ root_dir, deleted_file }); + group.async(io, workerDeleteFile, .{ io, root_dir, deleted_file }); try deleted_files.append(deleted_file); continue; } @@ -1552,8 +1564,8 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute .file => .file, .sym_link => .link, else => return f.fail(f.location_tok, try eb.printString( - "package contains '{s}' which has illegal file type '{s}'", - .{ entry.path, @tagName(entry.kind) }, + "package contains '{s}' which has illegal file type '{t}'", + .{ entry.path, entry.kind }, )), }; @@ -1570,9 +1582,11 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute .failure = undefined, // to be populated by the worker .size = undefined, // to be populated by the worker }; - group.async(io, workerHashFile, .{ root_dir, hashed_file }); + group.async(io, workerHashFile, .{ io, root_dir, hashed_file }); try all_files.append(hashed_file); } + + try group.await(io); } { @@ -1588,7 +1602,7 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute var i: usize = 0; while (i < sus_dirs.count()) : (i += 1) { const sus_dir = sus_dirs.keys()[i]; - root_dir.deleteDir(sus_dir) catch |err| switch (err) { + root_dir.deleteDir(io, sus_dir) catch |err| switch (err) { error.DirNotEmpty => continue, error.FileNotFound => continue, else => |e| { @@ -1638,7 +1652,7 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute assert(!f.job_queue.recursive); // Print something to stdout that can be text diffed to figure out why // the package hash is different. - dumpHashInfo(all_files.items) catch |err| { + dumpHashInfo(io, all_files.items) catch |err| { std.debug.print("unable to write to stdout: {s}\n", .{@errorName(err)}); std.process.exit(1); }; @@ -1650,9 +1664,9 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute }; } -fn dumpHashInfo(all_files: []const *const HashedFile) !void { +fn dumpHashInfo(io: Io, all_files: []const *const HashedFile) !void { var stdout_buffer: [1024]u8 = undefined; - var stdout_writer: fs.File.Writer = .initStreaming(.stdout(), &stdout_buffer); + var stdout_writer: Io.File.Writer = .initStreaming(.stdout(), io, &stdout_buffer); const w = &stdout_writer.interface; for (all_files) |hashed_file| { try w.print("{t}: {x}: {s}\n", .{ hashed_file.kind, &hashed_file.hash, hashed_file.normalized_path }); @@ -1660,15 +1674,15 @@ fn dumpHashInfo(all_files: []const *const HashedFile) !void { try w.flush(); } -fn workerHashFile(dir: fs.Dir, hashed_file: *HashedFile) void { - hashed_file.failure = hashFileFallible(dir, hashed_file); +fn workerHashFile(io: Io, dir: Io.Dir, hashed_file: *HashedFile) void { + hashed_file.failure = hashFileFallible(io, dir, hashed_file); } -fn workerDeleteFile(dir: fs.Dir, deleted_file: *DeletedFile) void { - deleted_file.failure = deleteFileFallible(dir, deleted_file); +fn workerDeleteFile(io: Io, dir: Io.Dir, deleted_file: *DeletedFile) void { + deleted_file.failure = deleteFileFallible(io, dir, deleted_file); } -fn hashFileFallible(dir: fs.Dir, hashed_file: *HashedFile) HashedFile.Error!void { +fn hashFileFallible(io: Io, dir: Io.Dir, hashed_file: *HashedFile) HashedFile.Error!void { var buf: [8000]u8 = undefined; var hasher = Package.Hash.Algo.init(.{}); hasher.update(hashed_file.normalized_path); @@ -1676,24 +1690,24 @@ fn hashFileFallible(dir: fs.Dir, hashed_file: *HashedFile) HashedFile.Error!void switch (hashed_file.kind) { .file => { - var file = try dir.openFile(hashed_file.fs_path, .{}); - defer file.close(); + var file = try dir.openFile(io, hashed_file.fs_path, .{}); + defer file.close(io); // Hard-coded false executable bit: https://github.com/ziglang/zig/issues/17463 hasher.update(&.{ 0, 0 }); var file_header: FileHeader = .{}; while (true) { - const bytes_read = try file.read(&buf); + const bytes_read = try file.readPositional(io, &.{&buf}, file_size); if (bytes_read == 0) break; file_size += bytes_read; hasher.update(buf[0..bytes_read]); file_header.update(buf[0..bytes_read]); } if (file_header.isExecutable()) { - try setExecutable(file); + try setExecutable(io, file); } }, .link => { - const link_name = try dir.readLink(hashed_file.fs_path, &buf); + const link_name = buf[0..try dir.readLink(io, hashed_file.fs_path, &buf)]; if (fs.path.sep != canonical_sep) { // Package hashes are intended to be consistent across // platforms which means we must normalize path separators @@ -1707,16 +1721,13 @@ fn hashFileFallible(dir: fs.Dir, hashed_file: *HashedFile) HashedFile.Error!void hashed_file.size = file_size; } -fn deleteFileFallible(dir: fs.Dir, deleted_file: *DeletedFile) DeletedFile.Error!void { - try dir.deleteFile(deleted_file.fs_path); +fn deleteFileFallible(io: Io, dir: Io.Dir, deleted_file: *DeletedFile) DeletedFile.Error!void { + try dir.deleteFile(io, deleted_file.fs_path); } -fn setExecutable(file: fs.File) !void { - if (!std.fs.has_executable_bit) return; - - const S = std.posix.S; - const mode = fs.File.default_mode | S.IXUSR | S.IXGRP | S.IXOTH; - try file.chmod(mode); +fn setExecutable(io: Io, file: Io.File) !void { + if (!Io.File.Permissions.has_executable_bit) return; + try file.setPermissions(io, .executable_file); } const DeletedFile = struct { @@ -1724,8 +1735,8 @@ const DeletedFile = struct { failure: Error!void, const Error = - fs.Dir.DeleteFileError || - fs.Dir.DeleteDirError; + Io.Dir.DeleteFileError || + Io.Dir.DeleteDirError; }; const HashedFile = struct { @@ -1737,11 +1748,11 @@ const HashedFile = struct { size: u64, const Error = - fs.File.OpenError || - fs.File.ReadError || - fs.File.StatError || - fs.File.ChmodError || - fs.Dir.ReadLinkError; + Io.File.OpenError || + Io.File.ReadPositionalError || + Io.File.StatError || + Io.File.SetPermissionsError || + Io.Dir.ReadLinkError; const Kind = enum { file, link }; @@ -2043,7 +2054,7 @@ const UnpackResult = struct { defer errors.deinit(gpa); var aw: Io.Writer.Allocating = .init(gpa); defer aw.deinit(); - try errors.renderToWriter(.{}, &aw.writer, .no_color); + try errors.renderToWriter(.{}, &aw.writer); try std.testing.expectEqualStrings( \\error: unable to unpack \\ note: unable to create symlink from 'dir2/file2' to 'filename': SymlinkError @@ -2074,7 +2085,7 @@ test "tarball with duplicate paths" { defer tmp.cleanup(); const tarball_name = "duplicate_paths.tar.gz"; - try saveEmbedFile(tarball_name, tmp.dir); + try saveEmbedFile(io, tarball_name, tmp.dir); const tarball_path = try std.fmt.allocPrint(gpa, ".zig-cache/tmp/{s}/{s}", .{ tmp.sub_path, tarball_name }); defer gpa.free(tarball_path); @@ -2107,7 +2118,7 @@ test "tarball with excluded duplicate paths" { defer tmp.cleanup(); const tarball_name = "duplicate_paths_excluded.tar.gz"; - try saveEmbedFile(tarball_name, tmp.dir); + try saveEmbedFile(io, tarball_name, tmp.dir); const tarball_path = try std.fmt.allocPrint(gpa, ".zig-cache/tmp/{s}/{s}", .{ tmp.sub_path, tarball_name }); defer gpa.free(tarball_path); @@ -2153,7 +2164,7 @@ test "tarball without root folder" { defer tmp.cleanup(); const tarball_name = "no_root.tar.gz"; - try saveEmbedFile(tarball_name, tmp.dir); + try saveEmbedFile(io, tarball_name, tmp.dir); const tarball_path = try std.fmt.allocPrint(gpa, ".zig-cache/tmp/{s}/{s}", .{ tmp.sub_path, tarball_name }); defer gpa.free(tarball_path); @@ -2178,7 +2189,7 @@ test "tarball without root folder" { } test "set executable bit based on file content" { - if (!std.fs.has_executable_bit) return error.SkipZigTest; + if (!Io.File.Permissions.has_executable_bit) return error.SkipZigTest; const gpa = std.testing.allocator; const io = std.testing.io; @@ -2186,7 +2197,7 @@ test "set executable bit based on file content" { defer tmp.cleanup(); const tarball_name = "executables.tar.gz"; - try saveEmbedFile(tarball_name, tmp.dir); + try saveEmbedFile(io, tarball_name, tmp.dir); const tarball_path = try std.fmt.allocPrint(gpa, ".zig-cache/tmp/{s}/{s}", .{ tmp.sub_path, tarball_name }); defer gpa.free(tarball_path); @@ -2210,16 +2221,16 @@ test "set executable bit based on file content" { ); var out = try fb.packageDir(); - defer out.close(); + defer out.close(io); const S = std.posix.S; // expect executable bit not set - try std.testing.expect((try out.statFile("file1")).mode & S.IXUSR == 0); - try std.testing.expect((try out.statFile("script_without_shebang")).mode & S.IXUSR == 0); + try std.testing.expect((try out.statFile(io, "file1", .{})).permissions.toMode() & S.IXUSR == 0); + try std.testing.expect((try out.statFile(io, "script_without_shebang", .{})).permissions.toMode() & S.IXUSR == 0); // expect executable bit set - try std.testing.expect((try out.statFile("hello")).mode & S.IXUSR != 0); - try std.testing.expect((try out.statFile("script")).mode & S.IXUSR != 0); - try std.testing.expect((try out.statFile("script_with_shebang_without_exec_bit")).mode & S.IXUSR != 0); - try std.testing.expect((try out.statFile("hello_ln")).mode & S.IXUSR != 0); + try std.testing.expect((try out.statFile(io, "hello", .{})).permissions.toMode() & S.IXUSR != 0); + try std.testing.expect((try out.statFile(io, "script", .{})).permissions.toMode() & S.IXUSR != 0); + try std.testing.expect((try out.statFile(io, "script_with_shebang_without_exec_bit", .{})).permissions.toMode() & S.IXUSR != 0); + try std.testing.expect((try out.statFile(io, "hello_ln", .{})).permissions.toMode() & S.IXUSR != 0); // // $ ls -al zig-cache/tmp/OCz9ovUcstDjTC_U/zig-global-cache/p/1220fecb4c06a9da8673c87fe8810e15785f1699212f01728eadce094d21effeeef3 @@ -2231,12 +2242,12 @@ test "set executable bit based on file content" { // -rwxrwxr-x 1 17 Apr script_with_shebang_without_exec_bit } -fn saveEmbedFile(comptime tarball_name: []const u8, dir: fs.Dir) !void { +fn saveEmbedFile(io: Io, comptime tarball_name: []const u8, dir: Io.Dir) !void { //const tarball_name = "duplicate_paths_excluded.tar.gz"; const tarball_content = @embedFile("Fetch/testdata/" ++ tarball_name); - var tmp_file = try dir.createFile(tarball_name, .{}); - defer tmp_file.close(); - try tmp_file.writeAll(tarball_content); + var tmp_file = try dir.createFile(io, tarball_name, .{}); + defer tmp_file.close(io); + try tmp_file.writeStreamingAll(io, tarball_content); } // Builds Fetch with required dependencies, clears dependencies on deinit(). @@ -2250,10 +2261,10 @@ const TestFetchBuilder = struct { self: *TestFetchBuilder, allocator: std.mem.Allocator, io: Io, - cache_parent_dir: std.fs.Dir, + cache_parent_dir: std.Io.Dir, path_or_url: []const u8, ) !*Fetch { - const cache_dir = try cache_parent_dir.makeOpenPath("zig-global-cache", .{}); + const cache_dir = try cache_parent_dir.createDirPathOpen(io, "zig-global-cache", .{}); self.http_client = .{ .allocator = allocator, .io = io }; self.global_cache_directory = .{ .handle = cache_dir, .path = null }; @@ -2301,35 +2312,40 @@ const TestFetchBuilder = struct { } fn deinit(self: *TestFetchBuilder) void { + const io = self.job_queue.io; self.fetch.deinit(); self.job_queue.deinit(); self.fetch.prog_node.end(); - self.global_cache_directory.handle.close(); + self.global_cache_directory.handle.close(io); self.http_client.deinit(); } - fn packageDir(self: *TestFetchBuilder) !fs.Dir { + fn packageDir(self: *TestFetchBuilder) !Io.Dir { + const io = self.job_queue.io; const root = self.fetch.package_root; - return try root.root_dir.handle.openDir(root.sub_path, .{ .iterate = true }); + return try root.root_dir.handle.openDir(io, root.sub_path, .{ .iterate = true }); } // Test helper, asserts thet package dir constains expected_files. // expected_files must be sorted. fn expectPackageFiles(self: *TestFetchBuilder, expected_files: []const []const u8) !void { + const io = self.job_queue.io; + const gpa = std.testing.allocator; + var package_dir = try self.packageDir(); - defer package_dir.close(); + defer package_dir.close(io); var actual_files: std.ArrayList([]u8) = .empty; - defer actual_files.deinit(std.testing.allocator); - defer for (actual_files.items) |file| std.testing.allocator.free(file); - var walker = try package_dir.walk(std.testing.allocator); + defer actual_files.deinit(gpa); + defer for (actual_files.items) |file| gpa.free(file); + var walker = try package_dir.walk(gpa); defer walker.deinit(); - while (try walker.next()) |entry| { + while (try walker.next(io)) |entry| { if (entry.kind != .file) continue; - const path = try std.testing.allocator.dupe(u8, entry.path); - errdefer std.testing.allocator.free(path); + const path = try gpa.dupe(u8, entry.path); + errdefer gpa.free(path); std.mem.replaceScalar(u8, path, std.fs.path.sep, '/'); - try actual_files.append(std.testing.allocator, path); + try actual_files.append(gpa, path); } std.mem.sortUnstable([]u8, actual_files.items, {}, struct { fn lessThan(_: void, a: []u8, b: []u8) bool { @@ -2346,17 +2362,19 @@ const TestFetchBuilder = struct { // Test helper, asserts that fetch has failed with `msg` error message. fn expectFetchErrors(self: *TestFetchBuilder, notes_len: usize, msg: []const u8) !void { + const gpa = std.testing.allocator; + var errors = try self.fetch.error_bundle.toOwnedBundle(""); - defer errors.deinit(std.testing.allocator); + defer errors.deinit(gpa); const em = errors.getErrorMessage(errors.getMessages()[0]); try std.testing.expectEqual(1, em.count); if (notes_len > 0) { try std.testing.expectEqual(notes_len, em.notes_len); } - var aw: Io.Writer.Allocating = .init(std.testing.allocator); + var aw: Io.Writer.Allocating = .init(gpa); defer aw.deinit(); - try errors.renderToWriter(.{}, &aw.writer, .no_color); + try errors.renderToWriter(.{}, &aw.writer); try std.testing.expectEqualStrings(msg, aw.written()); } }; diff --git a/src/Package/Fetch/git.zig b/src/Package/Fetch/git.zig index a2ea870c3f9f..d3bd1d701a61 100644 --- a/src/Package/Fetch/git.zig +++ b/src/Package/Fetch/git.zig @@ -198,8 +198,8 @@ pub const Repository = struct { repo: *Repository, allocator: Allocator, format: Oid.Format, - pack_file: *std.fs.File.Reader, - index_file: *std.fs.File.Reader, + pack_file: *Io.File.Reader, + index_file: *Io.File.Reader, ) !void { repo.* = .{ .odb = undefined }; try repo.odb.init(allocator, format, pack_file, index_file); @@ -213,7 +213,8 @@ pub const Repository = struct { /// Checks out the repository at `commit_oid` to `worktree`. pub fn checkout( repository: *Repository, - worktree: std.fs.Dir, + io: Io, + worktree: Io.Dir, commit_oid: Oid, diagnostics: *Diagnostics, ) !void { @@ -223,13 +224,14 @@ pub const Repository = struct { if (commit_object.type != .commit) return error.NotACommit; break :tree_oid try getCommitTree(repository.odb.format, commit_object.data); }; - try repository.checkoutTree(worktree, tree_oid, "", diagnostics); + try repository.checkoutTree(io, worktree, tree_oid, "", diagnostics); } /// Checks out the tree at `tree_oid` to `worktree`. fn checkoutTree( repository: *Repository, - dir: std.fs.Dir, + io: Io, + dir: Io.Dir, tree_oid: Oid, current_path: []const u8, diagnostics: *Diagnostics, @@ -251,18 +253,18 @@ pub const Repository = struct { while (try tree_iter.next()) |entry| { switch (entry.type) { .directory => { - try dir.makeDir(entry.name); - var subdir = try dir.openDir(entry.name, .{}); - defer subdir.close(); + try dir.createDir(io, entry.name, .default_dir); + var subdir = try dir.openDir(io, entry.name, .{}); + defer subdir.close(io); const sub_path = try std.fs.path.join(repository.odb.allocator, &.{ current_path, entry.name }); defer repository.odb.allocator.free(sub_path); - try repository.checkoutTree(subdir, entry.oid, sub_path, diagnostics); + try repository.checkoutTree(io, subdir, entry.oid, sub_path, diagnostics); }, .file => { try repository.odb.seekOid(entry.oid); const file_object = try repository.odb.readObject(); if (file_object.type != .blob) return error.InvalidFile; - var file = dir.createFile(entry.name, .{ .exclusive = true }) catch |e| { + var file = dir.createFile(io, entry.name, .{ .exclusive = true }) catch |e| { const file_name = try std.fs.path.join(diagnostics.allocator, &.{ current_path, entry.name }); errdefer diagnostics.allocator.free(file_name); try diagnostics.errors.append(diagnostics.allocator, .{ .unable_to_create_file = .{ @@ -271,15 +273,15 @@ pub const Repository = struct { } }); continue; }; - defer file.close(); - try file.writeAll(file_object.data); + defer file.close(io); + try file.writePositionalAll(io, file_object.data, 0); }, .symlink => { try repository.odb.seekOid(entry.oid); const symlink_object = try repository.odb.readObject(); if (symlink_object.type != .blob) return error.InvalidFile; const link_name = symlink_object.data; - dir.symLink(link_name, entry.name, .{}) catch |e| { + dir.symLink(io, link_name, entry.name, .{}) catch |e| { const file_name = try std.fs.path.join(diagnostics.allocator, &.{ current_path, entry.name }); errdefer diagnostics.allocator.free(file_name); const link_name_dup = try diagnostics.allocator.dupe(u8, link_name); @@ -294,7 +296,7 @@ pub const Repository = struct { .gitlink => { // Consistent with git archive behavior, create the directory but // do nothing else - try dir.makeDir(entry.name); + try dir.createDir(io, entry.name, .default_dir); }, } } @@ -370,9 +372,9 @@ pub const Repository = struct { /// [pack-format](https://git-scm.com/docs/pack-format). const Odb = struct { format: Oid.Format, - pack_file: *std.fs.File.Reader, + pack_file: *Io.File.Reader, index_header: IndexHeader, - index_file: *std.fs.File.Reader, + index_file: *Io.File.Reader, cache: ObjectCache = .{}, allocator: Allocator, @@ -381,8 +383,8 @@ const Odb = struct { odb: *Odb, allocator: Allocator, format: Oid.Format, - pack_file: *std.fs.File.Reader, - index_file: *std.fs.File.Reader, + pack_file: *Io.File.Reader, + index_file: *Io.File.Reader, ) !void { try pack_file.seekTo(0); try index_file.seekTo(0); @@ -1105,7 +1107,7 @@ pub const Session = struct { return error.ReadFailed; }) { .flush => return error.EndOfStream, - .data => |data| if (data.len > 1) switch (@as(StreamCode, @enumFromInt(data[0]))) { + .data => |data| switch (@as(StreamCode, @enumFromInt(data[0]))) { .pack_data => { input.toss(1); fs.remaining_len = data.len - 1; @@ -1115,7 +1117,9 @@ pub const Session = struct { fs.err = error.ProtocolError; return error.ReadFailed; }, - else => {}, + else => { + input.toss(data.len); + }, }, else => { fs.err = error.UnexpectedPacket; @@ -1270,8 +1274,8 @@ const IndexEntry = struct { pub fn indexPack( allocator: Allocator, format: Oid.Format, - pack: *std.fs.File.Reader, - index_writer: *std.fs.File.Writer, + pack: *Io.File.Reader, + index_writer: *Io.File.Writer, ) !void { try pack.seekTo(0); @@ -1370,7 +1374,7 @@ pub fn indexPack( fn indexPackFirstPass( allocator: Allocator, format: Oid.Format, - pack: *std.fs.File.Reader, + pack: *Io.File.Reader, index_entries: *std.AutoHashMapUnmanaged(Oid, IndexEntry), pending_deltas: *std.ArrayList(IndexEntry), ) !Oid { @@ -1423,7 +1427,7 @@ fn indexPackFirstPass( fn indexPackHashDelta( allocator: Allocator, format: Oid.Format, - pack: *std.fs.File.Reader, + pack: *Io.File.Reader, delta: IndexEntry, index_entries: std.AutoHashMapUnmanaged(Oid, IndexEntry), cache: *ObjectCache, @@ -1475,7 +1479,7 @@ fn indexPackHashDelta( fn resolveDeltaChain( allocator: Allocator, format: Oid.Format, - pack: *std.fs.File.Reader, + pack: *Io.File.Reader, base_object: Object, delta_offsets: []const u64, cache: *ObjectCache, @@ -1582,17 +1586,17 @@ fn runRepositoryTest(io: Io, comptime format: Oid.Format, head_commit: []const u var git_dir = testing.tmpDir(.{}); defer git_dir.cleanup(); - var pack_file = try git_dir.dir.createFile("testrepo.pack", .{ .read = true }); - defer pack_file.close(); - try pack_file.writeAll(testrepo_pack); + var pack_file = try git_dir.dir.createFile(io, "testrepo.pack", .{ .read = true }); + defer pack_file.close(io); + try pack_file.writeStreamingAll(io, testrepo_pack); var pack_file_buffer: [2000]u8 = undefined; var pack_file_reader = pack_file.reader(io, &pack_file_buffer); - var index_file = try git_dir.dir.createFile("testrepo.idx", .{ .read = true }); - defer index_file.close(); + var index_file = try git_dir.dir.createFile(io, "testrepo.idx", .{ .read = true }); + defer index_file.close(io); var index_file_buffer: [2000]u8 = undefined; - var index_file_writer = index_file.writer(&index_file_buffer); + var index_file_writer = index_file.writer(io, &index_file_buffer); try indexPack(testing.allocator, format, &pack_file_reader, &index_file_writer); // Arbitrary size limit on files read while checking the repository contents @@ -1600,7 +1604,7 @@ fn runRepositoryTest(io: Io, comptime format: Oid.Format, head_commit: []const u const max_file_size = 8192; if (!skip_checksums) { - const index_file_data = try git_dir.dir.readFileAlloc("testrepo.idx", testing.allocator, .limited(max_file_size)); + const index_file_data = try git_dir.dir.readFileAlloc(io, "testrepo.idx", testing.allocator, .limited(max_file_size)); defer testing.allocator.free(index_file_data); // testrepo.idx is generated by Git. The index created by this file should // match it exactly. Running `git verify-pack -v testrepo.pack` can verify @@ -1621,7 +1625,7 @@ fn runRepositoryTest(io: Io, comptime format: Oid.Format, head_commit: []const u var diagnostics: Diagnostics = .{ .allocator = testing.allocator }; defer diagnostics.deinit(); - try repository.checkout(worktree.dir, commit_id, &diagnostics); + try repository.checkout(io, worktree.dir, commit_id, &diagnostics); try testing.expect(diagnostics.errors.items.len == 0); const expected_files: []const []const u8 = &.{ @@ -1646,7 +1650,7 @@ fn runRepositoryTest(io: Io, comptime format: Oid.Format, head_commit: []const u defer for (actual_files.items) |file| testing.allocator.free(file); var walker = try worktree.dir.walk(testing.allocator); defer walker.deinit(); - while (try walker.next()) |entry| { + while (try walker.next(io)) |entry| { if (entry.kind != .file) continue; const path = try testing.allocator.dupe(u8, entry.path); errdefer testing.allocator.free(path); @@ -1676,7 +1680,7 @@ fn runRepositoryTest(io: Io, comptime format: Oid.Format, head_commit: []const u \\revision 19 \\ ; - const actual_file_contents = try worktree.dir.readFileAlloc("file", testing.allocator, .limited(max_file_size)); + const actual_file_contents = try worktree.dir.readFileAlloc(io, "file", testing.allocator, .limited(max_file_size)); defer testing.allocator.free(actual_file_contents); try testing.expectEqualStrings(expected_file_contents, actual_file_contents); } @@ -1700,7 +1704,7 @@ test "SHA-256 packfile indexing and checkout" { pub fn main() !void { const allocator = std.heap.smp_allocator; - var threaded: Io.Threaded = .init(allocator); + var threaded: Io.Threaded = .init(allocator, .{}); defer threaded.deinit(); const io = threaded.io(); @@ -1712,23 +1716,23 @@ pub fn main() !void { const format = std.meta.stringToEnum(Oid.Format, args[1]) orelse return error.InvalidFormat; - var pack_file = try std.fs.cwd().openFile(args[2], .{}); - defer pack_file.close(); + var pack_file = try Io.Dir.cwd().openFile(io, args[2], .{}); + defer pack_file.close(io); var pack_file_buffer: [4096]u8 = undefined; var pack_file_reader = pack_file.reader(io, &pack_file_buffer); const commit = try Oid.parse(format, args[3]); - var worktree = try std.fs.cwd().makeOpenPath(args[4], .{}); - defer worktree.close(); + var worktree = try Io.Dir.cwd().createDirPathOpen(io, args[4], .{}); + defer worktree.close(io); - var git_dir = try worktree.makeOpenPath(".git", .{}); - defer git_dir.close(); + var git_dir = try worktree.createDirPathOpen(io, ".git", .{}); + defer git_dir.close(io); std.debug.print("Starting index...\n", .{}); - var index_file = try git_dir.createFile("idx", .{ .read = true }); - defer index_file.close(); + var index_file = try git_dir.createFile(io, "idx", .{ .read = true }); + defer index_file.close(io); var index_file_buffer: [4096]u8 = undefined; - var index_file_writer = index_file.writer(&index_file_buffer); + var index_file_writer = index_file.writer(io, &index_file_buffer); try indexPack(allocator, format, &pack_file_reader, &index_file_writer); std.debug.print("Starting checkout...\n", .{}); @@ -1738,7 +1742,7 @@ pub fn main() !void { defer repository.deinit(); var diagnostics: Diagnostics = .{ .allocator = allocator }; defer diagnostics.deinit(); - try repository.checkout(worktree, commit, &diagnostics); + try repository.checkout(io, worktree, commit, &diagnostics); for (diagnostics.errors.items) |err| { std.debug.print("Diagnostic: {}\n", .{err}); diff --git a/src/Package/Manifest.zig b/src/Package/Manifest.zig index 90243a23e01c..a8bc8b501384 100644 --- a/src/Package/Manifest.zig +++ b/src/Package/Manifest.zig @@ -57,7 +57,7 @@ pub const ParseOptions = struct { pub const Error = Allocator.Error; -pub fn parse(gpa: Allocator, ast: Ast, options: ParseOptions) Error!Manifest { +pub fn parse(gpa: Allocator, ast: Ast, rng: std.Random, options: ParseOptions) Error!Manifest { const main_node_index = ast.nodeData(.root).node; var arena_instance = std.heap.ArenaAllocator.init(gpa); @@ -87,7 +87,7 @@ pub fn parse(gpa: Allocator, ast: Ast, options: ParseOptions) Error!Manifest { defer p.dependencies.deinit(gpa); defer p.paths.deinit(gpa); - p.parseRoot(main_node_index) catch |err| switch (err) { + p.parseRoot(main_node_index, rng) catch |err| switch (err) { error.ParseFailure => assert(p.errors.items.len > 0), else => |e| return e, }; @@ -157,7 +157,7 @@ const Parse = struct { const InnerError = error{ ParseFailure, OutOfMemory }; - fn parseRoot(p: *Parse, node: Ast.Node.Index) !void { + fn parseRoot(p: *Parse, node: Ast.Node.Index, rng: std.Random) !void { const ast = p.ast; const main_token = ast.nodeMainToken(node); @@ -217,13 +217,13 @@ const Parse = struct { if (fingerprint) |n| { if (!n.validate(p.name)) { return fail(p, main_token, "invalid fingerprint: 0x{x}; if this is a new or forked package, use this value: 0x{x}", .{ - n.int(), Package.Fingerprint.generate(p.name).int(), + n.int(), Package.Fingerprint.generate(rng, p.name).int(), }); } p.id = n.id; } else if (!p.allow_missing_fingerprint) { try appendError(p, main_token, "missing top-level 'fingerprint' field; suggested value: 0x{x}", .{ - Package.Fingerprint.generate(p.name).int(), + Package.Fingerprint.generate(rng, p.name).int(), }); } else { p.id = 0; @@ -623,7 +623,9 @@ test "basic" { try testing.expect(ast.errors.len == 0); - var manifest = try Manifest.parse(gpa, ast, .{}); + var rng = std.Random.DefaultPrng.init(0); + + var manifest = try Manifest.parse(gpa, ast, rng.random(), .{}); defer manifest.deinit(gpa); try testing.expect(manifest.errors.len == 0); @@ -666,7 +668,9 @@ test "minimum_zig_version" { try testing.expect(ast.errors.len == 0); - var manifest = try Manifest.parse(gpa, ast, .{}); + var rng = std.Random.DefaultPrng.init(0); + + var manifest = try Manifest.parse(gpa, ast, rng.random(), .{}); defer manifest.deinit(gpa); try testing.expect(manifest.errors.len == 0); @@ -698,7 +702,9 @@ test "minimum_zig_version - invalid version" { try testing.expect(ast.errors.len == 0); - var manifest = try Manifest.parse(gpa, ast, .{}); + var rng = std.Random.DefaultPrng.init(0); + + var manifest = try Manifest.parse(gpa, ast, rng.random(), .{}); defer manifest.deinit(gpa); try testing.expect(manifest.errors.len == 1); diff --git a/src/Sema.zig b/src/Sema.zig index 324f1b686757..51021f8db1ef 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -175,9 +175,11 @@ const ComptimeAlloc = struct { /// `src` may be `null` if `is_const` will be set. fn newComptimeAlloc(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type, alignment: Alignment) !ComptimeAllocIndex { + const pt = sema.pt; + const init_val = try sema.typeHasOnePossibleValue(ty) orelse try pt.undefValue(ty); const idx = sema.comptime_allocs.items.len; try sema.comptime_allocs.append(sema.gpa, .{ - .val = .{ .interned = try sema.pt.intern(.{ .undef = ty.toIntern() }) }, + .val = .{ .interned = init_val.toIntern() }, .is_const = false, .src = src, .alignment = alignment, @@ -851,8 +853,9 @@ pub const Block = struct { fn trackZir(block: *Block, inst: Zir.Inst.Index) Allocator.Error!InternPool.TrackedInst.Index { const pt = block.sema.pt; + const comp = pt.zcu.comp; block.sema.code.assertTrackable(inst); - return pt.zcu.intern_pool.trackZir(pt.zcu.gpa, pt.tid, .{ + return pt.zcu.intern_pool.trackZir(comp.gpa, comp.io, pt.tid, .{ .file = block.getFileScopeIndex(pt.zcu), .inst = inst, }); @@ -1059,7 +1062,7 @@ fn analyzeInlineBody( /// The index which a break instruction can target to break from this body. break_target: Zir.Inst.Index, ) CompileError!?Air.Inst.Ref { - if (sema.analyzeBodyInner(block, body)) |_| { + if (sema.analyzeBodyInner(block, body)) { return null; } else |err| switch (err) { error.ComptimeBreak => {}, @@ -1806,7 +1809,7 @@ fn analyzeBodyInner( child_block.instructions = block.instructions; defer block.instructions = child_block.instructions; - const break_result: ?BreakResult = if (sema.analyzeBodyInner(&child_block, inline_body)) |_| r: { + const break_result: ?BreakResult = if (sema.analyzeBodyInner(&child_block, inline_body)) r: { break :r null; } else |err| switch (err) { error.ComptimeBreak => brk_res: { @@ -1954,7 +1957,7 @@ fn analyzeBodyInner( .@"defer" => blk: { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].@"defer"; const defer_body = sema.code.bodySlice(inst_data.index, inst_data.len); - if (sema.analyzeBodyInner(block, defer_body)) |_| { + if (sema.analyzeBodyInner(block, defer_body)) { // The defer terminated noreturn - no more analysis needed. break; } else |err| switch (err) { @@ -1973,7 +1976,7 @@ fn analyzeBodyInner( const err_code = try sema.resolveInst(inst_data.err_code); try map.ensureSpaceForInstructions(sema.gpa, defer_body); map.putAssumeCapacity(extra.remapped_err_code, err_code); - if (sema.analyzeBodyInner(block, defer_body)) |_| { + if (sema.analyzeBodyInner(block, defer_body)) { // The defer terminated noreturn - no more analysis needed. break; } else |err| switch (err) { @@ -2203,10 +2206,11 @@ fn analyzeAsType( pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize) !void { const pt = sema.pt; - const zcu = pt.zcu; - const comp = zcu.comp; - const gpa = sema.gpa; - const ip = &zcu.intern_pool; + const comp = pt.zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const ip = &pt.zcu.intern_pool; + if (!comp.config.any_error_tracing) return; assert(!block.isComptime()); @@ -2229,12 +2233,12 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize) const st_ptr = try err_trace_block.addTy(.alloc, try pt.singleMutPtrType(stack_trace_ty)); // st.instruction_addresses = &addrs; - const instruction_addresses_field_name = try ip.getOrPutString(gpa, pt.tid, "instruction_addresses", .no_embedded_nulls); + const instruction_addresses_field_name = try ip.getOrPutString(gpa, io, pt.tid, "instruction_addresses", .no_embedded_nulls); const addr_field_ptr = try sema.fieldPtr(&err_trace_block, src, st_ptr, instruction_addresses_field_name, src, true); try sema.storePtr2(&err_trace_block, src, addr_field_ptr, src, addrs_ptr, src, .store); // st.index = 0; - const index_field_name = try ip.getOrPutString(gpa, pt.tid, "index", .no_embedded_nulls); + const index_field_name = try ip.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls); const index_field_ptr = try sema.fieldPtr(&err_trace_block, src, st_ptr, index_field_name, src, true); try sema.storePtr2(&err_trace_block, src, index_field_ptr, src, .zero_usize, src, .store); @@ -2664,16 +2668,18 @@ fn failWithTypeMismatch(sema: *Sema, block: *Block, src: LazySrcLoc, expected: T pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg) error{ AnalysisFail, OutOfMemory } { @branchHint(.cold); - const gpa = sema.gpa; const zcu = sema.pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; - if (build_options.enable_debug_extensions and zcu.comp.debug_compile_errors) { + if (build_options.enable_debug_extensions and comp.debug_compile_errors) { var wip_errors: std.zig.ErrorBundle.Wip = undefined; wip_errors.init(gpa) catch @panic("out of memory"); Compilation.addModuleErrorMsg(zcu, &wip_errors, err_msg.*, false) catch @panic("out of memory"); std.debug.print("compile error during Sema:\n", .{}); var error_bundle = wip_errors.toOwnedBundle("") catch @panic("out of memory"); - error_bundle.renderToStdErr(.{}, .auto); + error_bundle.renderToStderr(io, .{}, .auto) catch @panic("failed to print to stderr"); std.debug.panicExtra(@returnAddress(), "unexpected compile error occurred", .{}); } @@ -2826,9 +2832,12 @@ fn zirTupleDecl( block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { - const gpa = sema.gpa; const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const fields_len = extended.small; const extra = sema.code.extraData(Zir.Inst.TupleDecl, extended.operand); var extra_index = extra.end; @@ -2861,7 +2870,7 @@ fn zirTupleDecl( const coerced_field_init = try sema.coerce(block, field_type, uncoerced_field_init, init_src); const field_init_val = try sema.resolveConstDefinedValue(block, init_src, coerced_field_init, .{ .simple = .tuple_field_default_value }); if (field_init_val.canMutateComptimeVarState(zcu)) { - const field_name = try zcu.intern_pool.getOrPutStringFmt(gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls); + const field_name = try zcu.intern_pool.getOrPutStringFmt(gpa, io, pt.tid, "{d}", .{field_index}, .no_embedded_nulls); return sema.failWithContainsReferenceToComptimeVar(block, init_src, field_name, "field default value", field_init_val); } break :init field_init_val.toIntern(); @@ -2870,7 +2879,7 @@ fn zirTupleDecl( }; } - return Air.internedToRef(try zcu.intern_pool.getTupleType(gpa, pt.tid, .{ + return Air.internedToRef(try zcu.intern_pool.getTupleType(gpa, io, pt.tid, .{ .types = types, .values = inits, })); @@ -2909,7 +2918,11 @@ fn validateTupleFieldType( fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: usize, captures_len: u32) ![]InternPool.CaptureValue { const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; + const parent_ty: Type = .fromInterned(zcu.namespacePtr(block.namespace).owner_type); const parent_captures: InternPool.CaptureValue.Slice = parent_ty.getCaptures(zcu); @@ -2932,7 +2945,7 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us }; const loaded_val = try sema.resolveLazyValue(unresolved_loaded_val); if (loaded_val.canMutateComptimeVarState(zcu)) { - const field_name = try ip.getOrPutString(zcu.gpa, pt.tid, zir_name_slice, .no_embedded_nulls); + const field_name = try ip.getOrPutString(gpa, io, pt.tid, zir_name_slice, .no_embedded_nulls); return sema.failWithContainsReferenceToComptimeVar(block, type_src, field_name, "captured value", loaded_val); } break :capture .{ .@"comptime" = loaded_val.toIntern() }; @@ -2941,7 +2954,7 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us const air_ref = try sema.resolveInst(inst.toRef()); if (try sema.resolveValueResolveLazy(air_ref)) |val| { if (val.canMutateComptimeVarState(zcu)) { - const field_name = try ip.getOrPutString(zcu.gpa, pt.tid, zir_name_slice, .no_embedded_nulls); + const field_name = try ip.getOrPutString(gpa, io, pt.tid, zir_name_slice, .no_embedded_nulls); return sema.failWithContainsReferenceToComptimeVar(block, type_src, field_name, "captured value", val); } break :capture .{ .@"comptime" = val.toIntern() }; @@ -2950,7 +2963,8 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us }), .decl_val => |str| capture: { const decl_name = try ip.getOrPutString( - sema.gpa, + gpa, + io, pt.tid, sema.code.nullTerminatedString(str), .no_embedded_nulls, @@ -2960,7 +2974,8 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us }, .decl_ref => |str| capture: { const decl_name = try ip.getOrPutString( - sema.gpa, + gpa, + io, pt.tid, sema.code.nullTerminatedString(str), .no_embedded_nulls, @@ -2982,8 +2997,11 @@ fn zirStructDecl( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - const gpa = sema.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; + const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); const extra = sema.code.extraData(Zir.Inst.StructDecl, extended.operand); @@ -3038,7 +3056,7 @@ fn zirStructDecl( .captures = captures, } }, }; - const wip_ty = switch (try ip.getStructType(gpa, pt.tid, struct_init, false)) { + const wip_ty = switch (try ip.getStructType(gpa, io, pt.tid, struct_init, false)) { .existing => |ty| { const new_ty = try pt.ensureTypeUpToDate(ty); @@ -3106,7 +3124,9 @@ pub fn createTypeName( } { const pt = sema.pt; const zcu = pt.zcu; - const gpa = zcu.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; switch (name_strategy) { @@ -3156,7 +3176,7 @@ pub fn createTypeName( w.writeByte(')') catch return error.OutOfMemory; return .{ - .name = try ip.getOrPutString(gpa, pt.tid, aw.written(), .no_embedded_nulls), + .name = try ip.getOrPutString(gpa, io, pt.tid, aw.written(), .no_embedded_nulls), .nav = .none, }; }, @@ -3168,7 +3188,7 @@ pub fn createTypeName( for (@intFromEnum(inst.?)..zir_tags.len) |i| switch (zir_tags[i]) { .dbg_var_ptr, .dbg_var_val => if (zir_data[i].str_op.operand == ref) { return .{ - .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{f}.{s}", .{ + .name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}.{s}", .{ block.type_name_ctx.fmt(ip), zir_data[i].str_op.getStr(sema.code), }, .no_embedded_nulls), .nav = .none, @@ -3191,7 +3211,7 @@ pub fn createTypeName( // that builtin from the language, we can consider this. return .{ - .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{f}__{s}_{d}", .{ + .name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}__{s}_{d}", .{ block.type_name_ctx.fmt(ip), anon_prefix, @intFromEnum(type_index), }, .no_embedded_nulls), .nav = .none, @@ -3209,8 +3229,11 @@ fn zirEnumDecl( const pt = sema.pt; const zcu = pt.zcu; - const gpa = sema.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; + const small: Zir.Inst.EnumDecl.Small = @bitCast(extended.small); const extra = sema.code.extraData(Zir.Inst.EnumDecl, extended.operand); var extra_index: usize = extra.end; @@ -3279,7 +3302,7 @@ fn zirEnumDecl( .captures = captures, } }, }; - const wip_ty = switch (try ip.getEnumType(gpa, pt.tid, enum_init, false)) { + const wip_ty = switch (try ip.getEnumType(gpa, io, pt.tid, enum_init, false)) { .existing => |ty| { const new_ty = try pt.ensureTypeUpToDate(ty); @@ -3378,8 +3401,11 @@ fn zirUnionDecl( const pt = sema.pt; const zcu = pt.zcu; - const gpa = sema.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; + const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); const extra = sema.code.extraData(Zir.Inst.UnionDecl, extended.operand); var extra_index: usize = extra.end; @@ -3436,7 +3462,7 @@ fn zirUnionDecl( .captures = captures, } }, }; - const wip_ty = switch (try ip.getUnionType(gpa, pt.tid, union_init, false)) { + const wip_ty = switch (try ip.getUnionType(gpa, io, pt.tid, union_init, false)) { .existing => |ty| { const new_ty = try pt.ensureTypeUpToDate(ty); @@ -3501,7 +3527,9 @@ fn zirOpaqueDecl( const pt = sema.pt; const zcu = pt.zcu; - const gpa = sema.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; const small: Zir.Inst.OpaqueDecl.Small = @bitCast(extended.small); @@ -3530,7 +3558,7 @@ fn zirOpaqueDecl( .zir_index = tracked_inst, .captures = captures, }; - const wip_ty = switch (try ip.getOpaqueType(gpa, pt.tid, opaque_init)) { + const wip_ty = switch (try ip.getOpaqueType(gpa, io, pt.tid, opaque_init)) { .existing => |ty| { // Make sure we update the namespace if the declaration is re-analyzed, to pick // up on e.g. changed comptime decls. @@ -3585,7 +3613,10 @@ fn zirErrorSetDecl( const pt = sema.pt; const zcu = pt.zcu; - const gpa = sema.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index); @@ -3597,7 +3628,7 @@ fn zirErrorSetDecl( while (extra_index < extra_index_end) : (extra_index += 1) { const name_index: Zir.NullTerminatedString = @enumFromInt(sema.code.extra[extra_index]); const name = sema.code.nullTerminatedString(name_index); - const name_ip = try zcu.intern_pool.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls); + const name_ip = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls); _ = try pt.getErrorValue(name_ip); const result = names.getOrPutAssumeCapacity(name_ip); assert(!result.found_existing); // verified in AstGen @@ -3759,11 +3790,14 @@ fn indexablePtrLen( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const object_ty = sema.typeOf(object); const is_pointer_to = object_ty.isSinglePointer(zcu); const indexable_ty = if (is_pointer_to) object_ty.childType(zcu) else object_ty; try sema.checkIndexable(block, src, indexable_ty); - const field_name = try zcu.intern_pool.getOrPutString(sema.gpa, pt.tid, "len", .no_embedded_nulls); + const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "len", .no_embedded_nulls); return sema.fieldVal(block, src, object, field_name, src); } @@ -3775,13 +3809,16 @@ fn indexablePtrLenOrNone( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const operand_ty = sema.typeOf(operand); try checkMemOperand(sema, block, src, operand_ty); switch (operand_ty.ptrSize(zcu)) { .many, .c => return .none, .one, .slice => {}, } - const field_name = try zcu.intern_pool.getOrPutString(sema.gpa, pt.tid, "len", .no_embedded_nulls); + const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "len", .no_embedded_nulls); return sema.fieldVal(block, src, operand, field_name, src); } @@ -3959,6 +3996,9 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, resolved_alloc_ty: ?Type) CompileError!?InternPool.Index { const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const alloc_ty = resolved_alloc_ty orelse sema.typeOf(alloc); const ptr_info = alloc_ty.ptrInfo(zcu); @@ -4106,7 +4146,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, }; const new_ptr_ty = tmp_air.typeOfIndex(air_ptr, &zcu.intern_pool).toIntern(); const new_ptr = switch (method) { - .same_addr => try zcu.intern_pool.getCoerced(sema.gpa, pt.tid, decl_parent_ptr, new_ptr_ty), + .same_addr => try zcu.intern_pool.getCoerced(gpa, io, pt.tid, decl_parent_ptr, new_ptr_ty), .opt_payload => ptr: { // Set the optional to non-null at comptime. // If the payload is OPV, we must use that value instead of undef. @@ -4521,8 +4561,11 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - const gpa = sema.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; + const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index); const all_args = sema.code.refSlice(extra.end, extra.data.operands_len); @@ -4568,7 +4611,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. return sema.failWithOwnedErrorMsg(block, msg); } if (!object_ty.indexableHasLen(zcu)) continue; - break :l try sema.fieldVal(block, arg_src, object, try ip.getOrPutString(gpa, pt.tid, "len", .no_embedded_nulls), arg_src); + break :l try sema.fieldVal(block, arg_src, object, try ip.getOrPutString(gpa, io, pt.tid, "len", .no_embedded_nulls), arg_src); } else l: { // This argument is a range. const range_start = try sema.resolveInst(zir_arg_pair[0]); @@ -4731,6 +4774,10 @@ fn zirCoercePtrElemTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE fn zirTryOperandTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: bool) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(un_node.src_node); @@ -4756,7 +4803,7 @@ fn zirTryOperandTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: boo // This function cannot return an error. // `try` is still valid if the error case is impossible, i.e. no error is returned. // So, the result type has an error set of `error{}`. - break :err_set .fromInterned(try zcu.intern_pool.getErrorSetType(zcu.gpa, pt.tid, &.{})); + break :err_set .fromInterned(try zcu.intern_pool.getErrorSetType(gpa, io, pt.tid, &.{})); }, } } @@ -5001,7 +5048,9 @@ fn validateStructInit( ) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; - const gpa = sema.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; // Tracks whether each field was explicitly initialized. @@ -5015,6 +5064,7 @@ fn validateStructInit( const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data; const field_name = try ip.getOrPutString( gpa, + io, pt.tid, sema.code.nullTerminatedString(field_ptr_extra.field_name_start), .no_embedded_nulls, @@ -5459,9 +5509,15 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v } fn zirStr(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { + const pt = sema.pt; + const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const ip = &zcu.intern_pool; const bytes = sema.code.instructions.items(.data)[@intFromEnum(inst)].str.get(sema.code); return sema.addStrLit( - try sema.pt.zcu.intern_pool.getOrPutString(sema.gpa, sema.pt.tid, bytes, .maybe_embedded_nulls), + try ip.getOrPutString(gpa, io, pt.tid, bytes, .maybe_embedded_nulls), bytes.len, ); } @@ -5553,7 +5609,9 @@ fn zirCompileLog( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - const gpa = zcu.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; var aw: std.Io.Writer.Allocating = .init(gpa); defer aw.deinit(); @@ -5577,7 +5635,7 @@ fn zirCompileLog( } } - const line_data = try zcu.intern_pool.getOrPutString(gpa, pt.tid, aw.written(), .no_embedded_nulls); + const line_data = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, aw.written(), .no_embedded_nulls); const line_idx: Zcu.CompileLogLine.Index = if (zcu.free_compile_log_lines.pop()) |idx| idx: { zcu.compile_log_lines.items[@intFromEnum(idx)] = .{ @@ -5755,7 +5813,9 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr const pt = sema.pt; const zcu = pt.zcu; const comp = zcu.comp; - const gpa = sema.gpa; + const gpa = comp.gpa; + const io = comp.io; + const pl_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = parent_block.nodeOffset(pl_node.src_node); const extra = sema.code.extraData(Zir.Inst.Block, pl_node.payload_index); @@ -5844,7 +5904,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr errdefer c_import_file_path.deinit(gpa); const c_import_file = try gpa.create(Zcu.File); errdefer gpa.destroy(c_import_file); - const c_import_file_index = try zcu.intern_pool.createFile(gpa, pt.tid, .{ + const c_import_file_index = try zcu.intern_pool.createFile(gpa, io, pt.tid, .{ .bin_digest = c_import_file_path.digest(), .file = c_import_file, .root_type = .none, @@ -5957,7 +6017,7 @@ fn resolveBlockBody( assert(sema.air_instructions.items(.tag)[@intFromEnum(merges.block_inst)] == .block); var need_debug_scope = false; child_block.need_debug_scope = &need_debug_scope; - if (sema.analyzeBodyInner(child_block, body)) |_| { + if (sema.analyzeBodyInner(child_block, body)) { return sema.resolveAnalyzedBlock(parent_block, src, child_block, merges, need_debug_scope); } else |err| switch (err) { error.ComptimeBreak => { @@ -6348,6 +6408,7 @@ pub fn analyzeExport( fn zirDisableInstrumentation(sema: *Sema) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; + const io = zcu.comp.io; const ip = &zcu.intern_pool; const func = switch (sema.owner.unwrap()) { .func => |func| func, @@ -6358,13 +6419,14 @@ fn zirDisableInstrumentation(sema: *Sema) CompileError!void { .memoized_state, => return, // does nothing outside a function }; - ip.funcSetDisableInstrumentation(func); + ip.funcSetDisableInstrumentation(io, func); sema.allow_memoize = false; } fn zirDisableIntrinsics(sema: *Sema) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; + const io = zcu.comp.io; const ip = &zcu.intern_pool; const func = switch (sema.owner.unwrap()) { .func => |func| func, @@ -6375,7 +6437,7 @@ fn zirDisableIntrinsics(sema: *Sema) CompileError!void { .memoized_state, => return, // does nothing outside a function }; - ip.funcSetDisableIntrinsics(func); + ip.funcSetDisableIntrinsics(io, func); sema.allow_memoize = false; } @@ -6574,10 +6636,15 @@ pub fn appendAirString(sema: *Sema, str: []const u8) Allocator.Error!Air.NullTer fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok; const src = block.tokenOffset(inst_data.src_tok); const decl_name = try zcu.intern_pool.getOrPutString( - sema.gpa, + gpa, + io, pt.tid, inst_data.get(sema.code), .no_embedded_nulls, @@ -6589,10 +6656,15 @@ fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok; const src = block.tokenOffset(inst_data.src_tok); const decl_name = try zcu.intern_pool.getOrPutString( - sema.gpa, + gpa, + io, pt.tid, inst_data.get(sema.code), .no_embedded_nulls, @@ -6681,7 +6753,9 @@ fn funcDeclSrcInst(sema: *Sema, func_inst: Air.Inst.Ref) !?InternPool.TrackedIns pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - const gpa = sema.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; if (block.isComptime() or block.is_typeof) { const index_val = try pt.intValue_u64(.usize, sema.comptime_err_ret_trace.items.len); @@ -6692,7 +6766,7 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .StackTrace); try stack_trace_ty.resolveFields(pt); - const field_name = try zcu.intern_pool.getOrPutString(gpa, pt.tid, "index", .no_embedded_nulls); + const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls); const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) { error.AnalysisFail => @panic("std.builtin.StackTrace is corrupt"), error.ComptimeReturn, error.ComptimeBreak => unreachable, @@ -6719,7 +6793,9 @@ fn popErrorReturnTrace( ) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; - const gpa = sema.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; var is_non_error: ?bool = null; var is_non_error_inst: Air.Inst.Ref = undefined; if (operand != .none) { @@ -6736,7 +6812,7 @@ fn popErrorReturnTrace( try stack_trace_ty.resolveFields(pt); const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty); const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty); - const field_name = try zcu.intern_pool.getOrPutString(gpa, pt.tid, "index", .no_embedded_nulls); + const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls); const field_ptr = try sema.structFieldPtr(block, src, err_return_trace, field_name, src, stack_trace_ty, true); try sema.storePtr2(block, src, field_ptr, src, saved_error_trace_index, src, .store); } else if (is_non_error == null) { @@ -6762,7 +6838,7 @@ fn popErrorReturnTrace( try stack_trace_ty.resolveFields(pt); const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty); const err_return_trace = try then_block.addTy(.err_return_trace, ptr_stack_trace_ty); - const field_name = try zcu.intern_pool.getOrPutString(gpa, pt.tid, "index", .no_embedded_nulls); + const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls); const field_ptr = try sema.structFieldPtr(&then_block, src, err_return_trace, field_name, src, stack_trace_ty, true); try sema.storePtr2(&then_block, src, field_ptr, src, saved_error_trace_index, src, .store); _ = try then_block.addBr(cond_block_inst, .void_value); @@ -6816,6 +6892,10 @@ fn zirCall( const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const callee_src = block.src(.{ .node_offset_call_func = inst_data.src_node }); const call_src = block.nodeOffset(inst_data.src_node); @@ -6835,7 +6915,8 @@ fn zirCall( .field => blk: { const object_ptr = try sema.resolveInst(extra.data.obj_ptr); const field_name = try zcu.intern_pool.getOrPutString( - sema.gpa, + gpa, + io, pt.tid, sema.code.nullTerminatedString(extra.data.field_name_start), .no_embedded_nulls, @@ -6895,7 +6976,7 @@ fn zirCall( if (input_is_error or (pop_error_return_trace and return_ty.isError(zcu))) { const stack_trace_ty = try sema.getBuiltinType(call_src, .StackTrace); try stack_trace_ty.resolveFields(pt); - const field_name = try zcu.intern_pool.getOrPutString(sema.gpa, pt.tid, "index", .no_embedded_nulls); + const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls); const field_index = try sema.structFieldIndex(block, stack_trace_ty, field_name, call_src); // Insert a save instruction before the arg resolution + call instructions we just generated @@ -7230,7 +7311,9 @@ fn analyzeCall( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - const gpa = zcu.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; const arena = sema.arena; @@ -7542,7 +7625,7 @@ fn analyzeCall( if (func_ty_info.cc == .auto) { switch (sema.owner.unwrap()) { .@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {}, - .func => |owner_func| ip.funcSetHasErrorTrace(owner_func, true), + .func => |owner_func| ip.funcSetHasErrorTrace(io, owner_func, true), } } for (args, 0..) |arg, arg_idx| { @@ -7594,7 +7677,7 @@ fn analyzeCall( } else resolved_ret_ty; // We now need to actually create the function instance. - const func_instance = try ip.getFuncInstance(gpa, pt.tid, .{ + const func_instance = try ip.getFuncInstance(gpa, io, pt.tid, .{ .param_types = runtime_param_tys.items, .noalias_bits = noalias_bits, .bare_return_type = bare_ret_ty.toIntern(), @@ -7612,7 +7695,7 @@ fn analyzeCall( // This call is problematic as it breaks guarantees about order-independency of semantic analysis. // These guarantees are necessary for incremental compilation and parallel semantic analysis. // See: #22410 - zcu.funcInfo(func_instance).maxBranchQuota(ip, sema.branch_quota); + zcu.funcInfo(func_instance).maxBranchQuota(ip, io, sema.branch_quota); break :func .{ Air.internedToRef(func_instance), runtime_args.items }; }; @@ -8100,6 +8183,9 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; @@ -8114,7 +8200,7 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil const sentinel = try sema.coerce(block, elem_type, uncasted_sentinel, sentinel_src); const sentinel_val = try sema.resolveConstDefinedValue(block, sentinel_src, sentinel, .{ .simple = .array_sentinel }); if (sentinel_val.canMutateComptimeVarState(zcu)) { - const sentinel_name = try ip.getOrPutString(sema.gpa, pt.tid, "sentinel", .no_embedded_nulls); + const sentinel_name = try ip.getOrPutString(gpa, io, pt.tid, "sentinel", .no_embedded_nulls); return sema.failWithContainsReferenceToComptimeVar(block, sentinel_src, sentinel_name, "sentinel", sentinel_val); } const array_ty = try pt.arrayType(.{ @@ -8192,10 +8278,17 @@ fn validateErrorUnionPayloadType(sema: *Sema, block: *Block, payload_ty: Type, p fn zirErrorValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { _ = block; + const pt = sema.pt; + const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok; const name = try pt.zcu.intern_pool.getOrPutString( - sema.gpa, + gpa, + io, pt.tid, inst_data.get(sema.code), .no_embedded_nulls, @@ -8257,7 +8350,9 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD const pt = sema.pt; const zcu = pt.zcu; + const io = zcu.comp.io; const ip = &zcu.intern_pool; + const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; const src = block.nodeOffset(extra.node); const operand_src = block.builtinCallArgSrc(extra.node, 0); @@ -8269,8 +8364,8 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD const int = try sema.usizeCast(block, operand_src, try value.toUnsignedIntSema(pt)); if (int > len: { const mutate = &ip.global_error_set.mutate; - mutate.map.mutex.lock(); - defer mutate.map.mutex.unlock(); + mutate.map.mutex.lockUncancelable(io); + defer mutate.map.mutex.unlock(io); break :len mutate.names.len; } or int == 0) return sema.fail(block, operand_src, "integer value '{d}' represents no error", .{int}); @@ -8359,10 +8454,14 @@ fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok; const name = inst_data.get(sema.code); return Air.internedToRef((try pt.intern(.{ - .enum_literal = try zcu.intern_pool.getOrPutString(sema.gpa, pt.tid, name, .no_embedded_nulls), + .enum_literal = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls), }))); } @@ -8372,11 +8471,16 @@ fn zirDeclLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index, do_coerce: b const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data; const name = try zcu.intern_pool.getOrPutString( - sema.gpa, + gpa, + io, pt.tid, sema.code.nullTerminatedString(extra.field_name_start), .no_embedded_nulls, @@ -8913,7 +9017,11 @@ fn zirFunc( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; + const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index); const target = zcu.getTarget(); @@ -8968,7 +9076,7 @@ fn zirFunc( block, LazySrcLoc.unneeded, cc_type.getNamespaceIndex(zcu), - try ip.getOrPutString(sema.gpa, pt.tid, "c", .no_embedded_nulls), + try ip.getOrPutString(gpa, io, pt.tid, "c", .no_embedded_nulls), ); // The above should have errored. @panic("std.builtin is corrupt"); @@ -9441,8 +9549,11 @@ fn funcCommon( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - const gpa = sema.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; + const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = src_node_offset }); const cc_src = block.src(.{ .node_offset_fn_type_cc = src_node_offset }); const func_src = block.nodeOffset(src_node_offset); @@ -9561,7 +9672,7 @@ fn funcCommon( if (inferred_error_set) { assert(has_body); - return .fromIntern(try ip.getFuncDeclIes(gpa, pt.tid, .{ + return .fromIntern(try ip.getFuncDeclIes(gpa, io, pt.tid, .{ .owner_nav = sema.owner.unwrap().nav_val, .param_types = param_types, @@ -9581,7 +9692,7 @@ fn funcCommon( })); } - const func_ty = try ip.getFuncType(gpa, pt.tid, .{ + const func_ty = try ip.getFuncType(gpa, io, pt.tid, .{ .param_types = param_types, .noalias_bits = noalias_bits, .comptime_bits = comptime_bits, @@ -9593,7 +9704,7 @@ fn funcCommon( }); if (has_body) { - return .fromIntern(try ip.getFuncDecl(gpa, pt.tid, .{ + return .fromIntern(try ip.getFuncDecl(gpa, io, pt.tid, .{ .owner_nav = sema.owner.unwrap().nav_val, .ty = func_ty, .cc = cc, @@ -9776,12 +9887,17 @@ fn zirFieldPtrLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const field_name_src = block.src(.{ .node_offset_field_name = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data; const field_name = try zcu.intern_pool.getOrPutString( - sema.gpa, + gpa, + io, pt.tid, sema.code.nullTerminatedString(extra.field_name_start), .no_embedded_nulls, @@ -9796,12 +9912,17 @@ fn zirFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const field_name_src = block.src(.{ .node_offset_field_name = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data; const field_name = try zcu.intern_pool.getOrPutString( - sema.gpa, + gpa, + io, pt.tid, sema.code.nullTerminatedString(extra.field_name_start), .no_embedded_nulls, @@ -9816,12 +9937,17 @@ fn zirStructInitFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const field_name_src = block.src(.{ .node_offset_field_name_init = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data; const field_name = try zcu.intern_pool.getOrPutString( - sema.gpa, + gpa, + io, pt.tid, sema.code.nullTerminatedString(extra.field_name_start), .no_embedded_nulls, @@ -13939,9 +14065,14 @@ fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A fn zirRetErrValueCode(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok; const name = try zcu.intern_pool.getOrPutString( - sema.gpa, + gpa, + io, pt.tid, inst_data.get(sema.code), .no_embedded_nulls, @@ -14377,6 +14508,10 @@ fn analyzeTupleCat( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const lhs_ty = sema.typeOf(lhs); const rhs_ty = sema.typeOf(rhs); const src = block.nodeOffset(src_node); @@ -14432,7 +14567,7 @@ fn analyzeTupleCat( break :rs runtime_src; }; - const tuple_ty: Type = .fromInterned(try zcu.intern_pool.getTupleType(zcu.gpa, pt.tid, .{ + const tuple_ty: Type = .fromInterned(try zcu.intern_pool.getTupleType(gpa, io, pt.tid, .{ .types = types, .values = values, })); @@ -14819,6 +14954,10 @@ fn analyzeTupleMul( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const operand_ty = sema.typeOf(operand); const src = block.nodeOffset(src_node); const len_src = block.src(.{ .node_offset_bin_rhs = src_node }); @@ -14854,7 +14993,7 @@ fn analyzeTupleMul( break :rs runtime_src; }; - const tuple_ty: Type = .fromInterned(try zcu.intern_pool.getTupleType(zcu.gpa, pt.tid, .{ + const tuple_ty: Type = .fromInterned(try zcu.intern_pool.getTupleType(gpa, io, pt.tid, .{ .types = types, .values = values, })); @@ -16386,6 +16525,11 @@ fn zirAsm( const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const ip = &zcu.intern_pool; + const extra = sema.code.extraData(Zir.Inst.Asm, extended.operand); const src = block.nodeOffset(extra.data.src_node); const ret_ty_src = block.src(.{ .node_offset_asm_ret_ty = extra.data.src_node }); @@ -16394,7 +16538,6 @@ fn zirAsm( const inputs_len = small.inputs_len; const is_volatile = small.is_volatile; const is_global_assembly = sema.func_index == .none; - const zir_tags = sema.code.instructions.items(.tag); const asm_source: []const u8 = if (tmpl_is_expr) s: { const tmpl: Zir.Inst.Ref = @enumFromInt(@intFromEnum(extra.data.asm_source)); @@ -16424,29 +16567,37 @@ fn zirAsm( for (out_args, 0..) |*arg, out_i| { const output = sema.code.extraData(Zir.Inst.Asm.Output, extra_i); + const output_src = block.src(.{ .asm_output = .{ + .offset = src.offset.node_offset.x, + .output_index = @intCast(out_i), + } }); extra_i = output.end; const is_type = @as(u1, @truncate(output_type_bits)) != 0; output_type_bits >>= 1; + const name = sema.code.nullTerminatedString(output.data.name); + if (is_type) { // Indicate the output is the asm instruction return value. arg.* = .none; const out_ty = try sema.resolveType(block, ret_ty_src, output.data.operand); expr_ty = Air.internedToRef(out_ty.toIntern()); } else { - arg.* = try sema.resolveInst(output.data.operand); + const inst = try sema.resolveInst(output.data.operand); + if (!sema.checkRuntimeValue(inst)) { + const output_name = try ip.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls); + return sema.failWithContainsReferenceToComptimeVar(block, output_src, output_name, "assembly output", .fromInterned(inst.toInterned().?)); + } + arg.* = inst; } const constraint = sema.code.nullTerminatedString(output.data.constraint); - const name = sema.code.nullTerminatedString(output.data.name); needed_capacity += (constraint.len + name.len + (2 + 3)) / 4; - if (output.data.operand.toIndex()) |index| { - if (zir_tags[@intFromEnum(index)] == .ref) { - // TODO: better error location; it would be even nicer if there were notes that pointed at the output and the variable definition - return sema.fail(block, src, "asm cannot output to const local '{s}'", .{name}); - } + // AstGen gives us a reference to a variable + if (arg.* != .none and sema.typeOf(arg.*).isConstPtr(zcu)) { + return sema.fail(block, output_src, "asm cannot output to const '{s}'", .{name}); } outputs[out_i] = .{ .c = constraint, .n = name }; @@ -16457,9 +16608,18 @@ fn zirAsm( for (args, 0..) |*arg, arg_i| { const input = sema.code.extraData(Zir.Inst.Asm.Input, extra_i); + const input_src = block.src(.{ .asm_input = .{ + .offset = src.offset.node_offset.x, + .input_index = @intCast(arg_i), + } }); extra_i = input.end; const uncasted_arg = try sema.resolveInst(input.data.operand); + const name = sema.code.nullTerminatedString(input.data.name); + if (!sema.checkRuntimeValue(uncasted_arg)) { + const input_name = try ip.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls); + return sema.failWithContainsReferenceToComptimeVar(block, input_src, input_name, "assembly input", .fromInterned(uncasted_arg.toInterned().?)); + } const uncasted_arg_ty = sema.typeOf(uncasted_arg); switch (uncasted_arg_ty.zigTypeTag(zcu)) { .comptime_int => arg.* = try sema.coerce(block, .usize, uncasted_arg, src), @@ -16470,7 +16630,6 @@ fn zirAsm( } const constraint = sema.code.nullTerminatedString(input.data.constraint); - const name = sema.code.nullTerminatedString(input.data.name); needed_capacity += (constraint.len + name.len + (2 + 3)) / 4; inputs[arg_i] = .{ .c = constraint, .n = name }; } @@ -16482,7 +16641,6 @@ fn zirAsm( const clobbers_val = try sema.resolveConstDefinedValue(block, src, clobbers, .{ .simple = .clobber }); needed_capacity += asm_source.len / 4 + 1; - const gpa = sema.gpa; try sema.air_extra.ensureUnusedCapacity(gpa, needed_capacity); const asm_air = try block.addInst(.{ .tag = .assembly, @@ -17042,10 +17200,13 @@ fn zirBuiltinSrc( const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; + const extra = sema.code.extraData(Zir.Inst.Src, extended.operand).data; const fn_name = ip.getNav(zcu.funcInfo(sema.func_index).owner_nav).name; - const gpa = sema.gpa; const file_scope = block.getFileScope(zcu); const func_name_val = v: { @@ -17088,7 +17249,7 @@ fn zirBuiltinSrc( .val = try pt.intern(.{ .aggregate = .{ .ty = array_ty, .storage = .{ - .bytes = try ip.getOrPutString(gpa, pt.tid, module_name, .maybe_embedded_nulls), + .bytes = try ip.getOrPutString(gpa, io, pt.tid, module_name, .maybe_embedded_nulls), }, } }), } }, @@ -17114,7 +17275,7 @@ fn zirBuiltinSrc( .val = try pt.intern(.{ .aggregate = .{ .ty = array_ty, .storage = .{ - .bytes = try ip.getOrPutString(gpa, pt.tid, file_name, .maybe_embedded_nulls), + .bytes = try ip.getOrPutString(gpa, io, pt.tid, file_name, .maybe_embedded_nulls), }, } }), } }, @@ -17143,8 +17304,11 @@ fn zirBuiltinSrc( fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - const gpa = sema.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; + const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); const ty = try sema.resolveType(block, src, inst_data.operand); @@ -17493,7 +17657,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const enum_type = ip.loadEnumType(ty.toIntern()); const value_val = if (enum_type.values.len > 0) try ip.getCoercedInts( - zcu.gpa, + gpa, + io, pt.tid, ip.indexToKey(enum_type.values.get(ip)[tag_index]).int, .comptime_int_type, @@ -17711,7 +17876,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const field_ty = tuple_type.types.get(ip)[field_index]; const field_val = tuple_type.values.get(ip)[field_index]; const name_val = v: { - const field_name = try ip.getOrPutStringFmt(gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls); + const field_name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{d}", .{field_index}, .no_embedded_nulls); const field_name_len = field_name.length(ip); const new_decl_ty = try pt.arrayType(.{ .len = field_name_len, @@ -18468,6 +18633,9 @@ fn zirCondbr( break :blk try sub_block.addTyOp(.unwrap_errunion_err, result_ty, err_operand); }; + // Reset, this may have been updated by the then block analysis + sub_block.error_return_trace_index = parent_block.error_return_trace_index; + const false_hint: std.builtin.BranchHint = if (err_cond != null and try sema.maybeErrorUnwrap(&sub_block, else_body, err_cond.?, cond_src, false)) h: { @@ -18731,10 +18899,15 @@ fn zirRetErrValue( ) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok; const src = block.tokenOffset(inst_data.src_tok); const err_name = try zcu.intern_pool.getOrPutString( - sema.gpa, + gpa, + io, pt.tid, inst_data.get(sema.code), .no_embedded_nulls, @@ -18943,9 +19116,10 @@ fn restoreErrRetIndex(sema: *Sema, start_block: *Block, src: LazySrcLoc, target_ while (true) { if (block.label) |label| { if (label.zir_block == zir_block) { - const target_trace_index = if (block.parent) |parent_block| tgt: { - break :tgt parent_block.error_return_trace_index; - } else sema.error_return_trace_index_on_fn_entry; + const target_trace_index = if (block.parent) |parent_block| + parent_block.error_return_trace_index + else + sema.error_return_trace_index_on_fn_entry; if (start_block.error_return_trace_index != target_trace_index) break :b target_trace_index; @@ -19099,6 +19273,9 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].ptr_type; @@ -19136,7 +19313,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const val = try sema.resolveConstDefinedValue(block, sentinel_src, coerced, .{ .simple = .pointer_sentinel }); try checkSentinelType(sema, block, sentinel_src, elem_ty); if (val.canMutateComptimeVarState(zcu)) { - const sentinel_name = try ip.getOrPutString(sema.gpa, pt.tid, "sentinel", .no_embedded_nulls); + const sentinel_name = try ip.getOrPutString(gpa, io, pt.tid, "sentinel", .no_embedded_nulls); return sema.failWithContainsReferenceToComptimeVar(block, sentinel_src, sentinel_name, "sentinel", val); } break :blk val.toIntern(); @@ -19441,15 +19618,18 @@ fn zirStructInit( inst: Zir.Inst.Index, is_ref: bool, ) CompileError!Air.Inst.Ref { - const gpa = sema.gpa; + const pt = sema.pt; + const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const ip = &zcu.intern_pool; + const zir_datas = sema.code.instructions.items(.data); const inst_data = zir_datas[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.StructInit, inst_data.payload_index); const src = block.nodeOffset(inst_data.src_node); - const pt = sema.pt; - const zcu = pt.zcu; - const ip = &zcu.intern_pool; const first_item = sema.code.extraData(Zir.Inst.StructInit.Item, extra.end).data; const first_field_type_data = zir_datas[@intFromEnum(first_item.field_type)].pl_node; const first_field_type_extra = sema.code.extraData(Zir.Inst.FieldType, first_field_type_data.payload_index).data; @@ -19491,6 +19671,7 @@ fn zirStructInit( const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data; const field_name = try ip.getOrPutString( gpa, + io, pt.tid, sema.code.nullTerminatedString(field_type_extra.name_start), .no_embedded_nulls, @@ -19532,6 +19713,7 @@ fn zirStructInit( const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data; const field_name = try ip.getOrPutString( gpa, + io, pt.tid, sema.code.nullTerminatedString(field_type_extra.name_start), .no_embedded_nulls, @@ -19775,8 +19957,11 @@ fn structInitAnon( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - const gpa = sema.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; + const zir_datas = sema.code.instructions.items(.data); const types = try sema.arena.alloc(InternPool.Index, extra_data.fields_len); @@ -19806,7 +19991,7 @@ fn structInitAnon( }, }; - field_name.* = try zcu.intern_pool.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls); + field_name.* = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls); const init = try sema.resolveInst(item.data.init); field_ty.* = sema.typeOf(init).toIntern(); @@ -19849,7 +20034,7 @@ fn structInitAnon( break :hash hasher.final(); }; const tracked_inst = try block.trackZir(inst); - const struct_ty = switch (try ip.getStructType(gpa, pt.tid, .{ + const struct_ty = switch (try ip.getStructType(gpa, io, pt.tid, .{ .layout = .auto, .fields_len = extra_data.fields_len, .known_non_opv = false, @@ -20109,7 +20294,9 @@ fn arrayInitAnon( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - const gpa = sema.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; const types = try sema.arena.alloc(InternPool.Index, operands.len); @@ -20158,7 +20345,7 @@ fn arrayInitAnon( break :blk new_values; }; - const tuple_ty: Type = .fromInterned(try ip.getTupleType(gpa, pt.tid, .{ + const tuple_ty: Type = .fromInterned(try ip.getTupleType(gpa, io, pt.tid, .{ .types = types, .values = values_no_comptime, })); @@ -20225,7 +20412,11 @@ fn zirFieldTypeRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; + const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data; const ty_src = block.nodeOffset(inst_data.src_node); @@ -20233,7 +20424,7 @@ fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp const wrapped_aggregate_ty = try sema.resolveTypeOrPoison(block, ty_src, extra.container_type) orelse return .generic_poison_type; const aggregate_ty = wrapped_aggregate_ty.optEuBaseType(zcu); const zir_field_name = sema.code.nullTerminatedString(extra.name_start); - const field_name = try ip.getOrPutString(sema.gpa, pt.tid, zir_field_name, .no_embedded_nulls); + const field_name = try ip.getOrPutString(gpa, io, pt.tid, zir_field_name, .no_embedded_nulls); return sema.fieldType(block, aggregate_ty, field_name, field_name_src, ty_src); } @@ -20647,6 +20838,9 @@ fn zirReifyTuple( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; const operand_src = block.builtinCallArgSrc(extra.node, 0); @@ -20669,7 +20863,7 @@ fn zirReifyTuple( const field_values = try sema.arena.alloc(InternPool.Index, fields_len); @memset(field_values, .none); - return .fromIntern(try zcu.intern_pool.getTupleType(zcu.gpa, pt.tid, .{ + return .fromIntern(try zcu.intern_pool.getTupleType(gpa, io, pt.tid, .{ .types = field_types, .values = field_values, })); @@ -20682,7 +20876,9 @@ fn zirReifyPointer( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - const gpa = zcu.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; const extra = sema.code.extraData(Zir.Inst.ReifyPointer, extended.operand).data; @@ -20750,7 +20946,7 @@ fn zirReifyPointer( } try checkSentinelType(sema, block, sentinel_src, elem_ty); if (sentinel.canMutateComptimeVarState(zcu)) { - const sentinel_name = try ip.getOrPutString(gpa, pt.tid, "sentinel", .no_embedded_nulls); + const sentinel_name = try ip.getOrPutString(gpa, io, pt.tid, "sentinel", .no_embedded_nulls); return sema.failWithContainsReferenceToComptimeVar(block, sentinel_src, sentinel_name, "sentinel", sentinel); } } @@ -20779,7 +20975,9 @@ fn zirReifyFn( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - const gpa = zcu.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; const extra = sema.code.extraData(Zir.Inst.ReifyFn, extended.operand).data; @@ -20862,7 +21060,7 @@ fn zirReifyFn( return sema.fail(block, param_attrs_src, "cannot reify function type with comptime-only return type '{f}'", .{ret_ty.fmt(pt)}); } - return .fromIntern(try ip.getFuncType(gpa, pt.tid, .{ + return .fromIntern(try ip.getFuncType(gpa, io, pt.tid, .{ .param_types = param_types_ip, .noalias_bits = noalias_bits, .comptime_bits = 0, @@ -20882,7 +21080,9 @@ fn zirReifyStruct( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - const gpa = sema.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small); @@ -21057,7 +21257,7 @@ fn zirReifyStruct( return sema.fail(block, field_attrs_src, "{t} struct fields cannot be marked comptime", .{layout}); } - const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{ + const wip_ty = switch (try ip.getStructType(gpa, io, pt.tid, .{ .layout = layout, .fields_len = @intCast(fields_len), .known_non_opv = false, @@ -21201,10 +21401,10 @@ fn zirReifyStruct( } if (backing_int_ty) |ty| { try sema.checkBackingIntType(block, src, ty, fields_bit_sum); - wip_struct_type.setBackingIntType(ip, ty.toIntern()); + wip_struct_type.setBackingIntType(ip, io, ty.toIntern()); } else { const ty = try pt.intType(.unsigned, @intCast(fields_bit_sum)); - wip_struct_type.setBackingIntType(ip, ty.toIntern()); + wip_struct_type.setBackingIntType(ip, io, ty.toIntern()); } } @@ -21237,7 +21437,9 @@ fn zirReifyUnion( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - const gpa = sema.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small); @@ -21378,7 +21580,7 @@ fn zirReifyUnion( return sema.fail(block, field_attrs_src, "packed union fields cannot be aligned", .{}); } - const wip_ty = switch (try ip.getUnionType(gpa, pt.tid, .{ + const wip_ty = switch (try ip.getUnionType(gpa, io, pt.tid, .{ .flags = .{ .layout = layout, .status = .none, @@ -21536,8 +21738,8 @@ fn zirReifyUnion( } } - loaded_union.setTagType(ip, enum_tag_ty); - loaded_union.setStatus(ip, .have_field_types); + loaded_union.setTagType(ip, io, enum_tag_ty); + loaded_union.setStatus(ip, io, .have_field_types); const new_namespace_index = try pt.createNamespace(.{ .parent = block.namespace.toOptional(), @@ -21568,7 +21770,9 @@ fn zirReifyEnum( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - const gpa = sema.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small); @@ -21666,7 +21870,7 @@ fn zirReifyEnum( std.hash.autoHash(&hasher, field_name); } - const wip_ty = switch (try ip.getEnumType(gpa, pt.tid, .{ + const wip_ty = switch (try ip.getEnumType(gpa, io, pt.tid, .{ .has_values = true, .tag_mode = if (nonexhaustive) .nonexhaustive else .explicit, .fields_len = @intCast(fields_len), @@ -21822,13 +22026,16 @@ fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0); const ty = try sema.resolveType(block, ty_src, inst_data.operand); - const type_name = try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{f}", .{ty.fmt(pt)}, .no_embedded_nulls); + const type_name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}", .{ty.fmt(pt)}, .no_embedded_nulls); return sema.addNullTerminatedStrLit(type_name); } @@ -22259,6 +22466,10 @@ fn ptrCastFull( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const operand_ty = sema.typeOf(operand); try sema.checkPtrType(block, src, dest_ty, true); @@ -22430,14 +22641,14 @@ fn ptrCastFull( if (dest_info.sentinel == .none) break :check_sent; if (src_info.flags.size == .c) break :check_sent; if (src_info.sentinel != .none) { - const coerced_sent = try zcu.intern_pool.getCoerced(sema.gpa, pt.tid, src_info.sentinel, dest_info.child); + const coerced_sent = try zcu.intern_pool.getCoerced(gpa, io, pt.tid, src_info.sentinel, dest_info.child); if (dest_info.sentinel == coerced_sent) break :check_sent; } if (is_array_ptr_to_slice) { // [*]nT -> []T const arr_ty: Type = .fromInterned(src_info.child); if (arr_ty.sentinel(zcu)) |src_sentinel| { - const coerced_sent = try zcu.intern_pool.getCoerced(sema.gpa, pt.tid, src_sentinel.toIntern(), dest_info.child); + const coerced_sent = try zcu.intern_pool.getCoerced(gpa, io, pt.tid, src_sentinel.toIntern(), dest_info.child); if (dest_info.sentinel == coerced_sent) break :check_sent; } } @@ -23555,8 +23766,11 @@ fn resolveExportOptions( ) CompileError!Zcu.Export.Options { const pt = sema.pt; const zcu = pt.zcu; - const gpa = sema.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; + const export_options_ty = try sema.getBuiltinType(src, .ExportOptions); const air_ref = try sema.resolveInst(zir_ref); const options = try sema.coerce(block, export_options_ty, air_ref, src); @@ -23566,21 +23780,21 @@ fn resolveExportOptions( const section_src = block.src(.{ .init_field_section = src.offset.node_offset_builtin_call_arg.builtin_call_node }); const visibility_src = block.src(.{ .init_field_visibility = src.offset.node_offset_builtin_call_arg.builtin_call_node }); - const name_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "name", .no_embedded_nulls), name_src); + const name_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "name", .no_embedded_nulls), name_src); const name = try sema.toConstString(block, name_src, name_operand, .{ .simple = .export_options }); - const linkage_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "linkage", .no_embedded_nulls), linkage_src); + const linkage_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "linkage", .no_embedded_nulls), linkage_src); const linkage_val = try sema.resolveConstDefinedValue(block, linkage_src, linkage_operand, .{ .simple = .export_options }); const linkage = try sema.interpretBuiltinType(block, linkage_src, linkage_val, std.builtin.GlobalLinkage); - const section_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "section", .no_embedded_nulls), section_src); + const section_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "section", .no_embedded_nulls), section_src); const section_opt_val = try sema.resolveConstDefinedValue(block, section_src, section_operand, .{ .simple = .export_options }); const section = if (section_opt_val.optionalValue(zcu)) |section_val| try sema.toConstString(block, section_src, Air.internedToRef(section_val.toIntern()), .{ .simple = .export_options }) else null; - const visibility_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "visibility", .no_embedded_nulls), visibility_src); + const visibility_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "visibility", .no_embedded_nulls), visibility_src); const visibility_val = try sema.resolveConstDefinedValue(block, visibility_src, visibility_operand, .{ .simple = .export_options }); const visibility = try sema.interpretBuiltinType(block, visibility_src, visibility_val, std.builtin.SymbolVisibility); @@ -23595,9 +23809,9 @@ fn resolveExportOptions( } return .{ - .name = try ip.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls), + .name = try ip.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls), .linkage = linkage, - .section = try ip.getOrPutStringOpt(gpa, pt.tid, section, .no_embedded_nulls), + .section = try ip.getOrPutStringOpt(gpa, io, pt.tid, section, .no_embedded_nulls), .visibility = visibility, }; } @@ -25323,8 +25537,11 @@ fn zirMemcpy( fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; - const gpa = sema.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; + const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const src = block.nodeOffset(inst_data.src_node); @@ -25363,7 +25580,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void const elem = try sema.coerce(block, dest_elem_ty, uncoerced_elem, value_src); const runtime_src = rs: { - const len_air_ref = try sema.fieldVal(block, src, dest_ptr, try ip.getOrPutString(gpa, pt.tid, "len", .no_embedded_nulls), dest_src); + const len_air_ref = try sema.fieldVal(block, src, dest_ptr, try ip.getOrPutString(gpa, io, pt.tid, "len", .no_embedded_nulls), dest_src); const len_val = (try sema.resolveDefinedValue(block, dest_src, len_air_ref)) orelse break :rs dest_src; const len_u64 = try len_val.toUnsignedIntSema(pt); const len = try sema.usizeCast(block, dest_src, len_u64); @@ -25416,7 +25633,11 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; + const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index); const target = zcu.getTarget(); @@ -25460,7 +25681,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A block, LazySrcLoc.unneeded, cc_type.getNamespaceIndex(zcu), - try ip.getOrPutString(sema.gpa, pt.tid, "c", .no_embedded_nulls), + try ip.getOrPutString(gpa, io, pt.tid, "c", .no_embedded_nulls), ); // The above should have errored. @panic("std.builtin is corrupt"); @@ -25626,8 +25847,11 @@ fn resolvePrefetchOptions( ) CompileError!std.builtin.PrefetchOptions { const pt = sema.pt; const zcu = pt.zcu; - const gpa = sema.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; + const options_ty = try sema.getBuiltinType(src, .PrefetchOptions); const options = try sema.coerce(block, options_ty, try sema.resolveInst(zir_ref), src); @@ -25635,13 +25859,13 @@ fn resolvePrefetchOptions( const locality_src = block.src(.{ .init_field_locality = src.offset.node_offset_builtin_call_arg.builtin_call_node }); const cache_src = block.src(.{ .init_field_cache = src.offset.node_offset_builtin_call_arg.builtin_call_node }); - const rw = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "rw", .no_embedded_nulls), rw_src); + const rw = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "rw", .no_embedded_nulls), rw_src); const rw_val = try sema.resolveConstDefinedValue(block, rw_src, rw, .{ .simple = .prefetch_options }); - const locality = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "locality", .no_embedded_nulls), locality_src); + const locality = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "locality", .no_embedded_nulls), locality_src); const locality_val = try sema.resolveConstDefinedValue(block, locality_src, locality, .{ .simple = .prefetch_options }); - const cache = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "cache", .no_embedded_nulls), cache_src); + const cache = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "cache", .no_embedded_nulls), cache_src); const cache_val = try sema.resolveConstDefinedValue(block, cache_src, cache, .{ .simple = .prefetch_options }); return std.builtin.PrefetchOptions{ @@ -25692,11 +25916,15 @@ fn resolveExternOptions( is_thread_local: bool, is_dll_import: bool, relocation: std.builtin.ExternOptions.Relocation, + decoration: ?std.builtin.ExternOptions.Decoration, } { const pt = sema.pt; const zcu = pt.zcu; - const gpa = sema.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; + const options_inst = try sema.resolveInst(zir_ref); const extern_options_ty = try sema.getBuiltinType(src, .ExternOptions); const options = try sema.coerce(block, extern_options_ty, options_inst, src); @@ -25708,22 +25936,23 @@ fn resolveExternOptions( const thread_local_src = block.src(.{ .init_field_thread_local = src.offset.node_offset_builtin_call_arg.builtin_call_node }); const dll_import_src = block.src(.{ .init_field_dll_import = src.offset.node_offset_builtin_call_arg.builtin_call_node }); const relocation_src = block.src(.{ .init_field_relocation = src.offset.node_offset_builtin_call_arg.builtin_call_node }); + const decoration_src = block.src(.{ .init_field_decoration = src.offset.node_offset_builtin_call_arg.builtin_call_node }); - const name_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "name", .no_embedded_nulls), name_src); + const name_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "name", .no_embedded_nulls), name_src); const name = try sema.toConstString(block, name_src, name_ref, .{ .simple = .extern_options }); - const library_name_inst = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "library_name", .no_embedded_nulls), library_src); + const library_name_inst = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "library_name", .no_embedded_nulls), library_src); const library_name_val = try sema.resolveConstDefinedValue(block, library_src, library_name_inst, .{ .simple = .extern_options }); - const linkage_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "linkage", .no_embedded_nulls), linkage_src); + const linkage_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "linkage", .no_embedded_nulls), linkage_src); const linkage_val = try sema.resolveConstDefinedValue(block, linkage_src, linkage_ref, .{ .simple = .extern_options }); const linkage = try sema.interpretBuiltinType(block, linkage_src, linkage_val, std.builtin.GlobalLinkage); - const visibility_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "visibility", .no_embedded_nulls), visibility_src); + const visibility_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "visibility", .no_embedded_nulls), visibility_src); const visibility_val = try sema.resolveConstDefinedValue(block, visibility_src, visibility_ref, .{ .simple = .extern_options }); const visibility = try sema.interpretBuiltinType(block, visibility_src, visibility_val, std.builtin.SymbolVisibility); - const is_thread_local = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "is_thread_local", .no_embedded_nulls), thread_local_src); + const is_thread_local = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "is_thread_local", .no_embedded_nulls), thread_local_src); const is_thread_local_val = try sema.resolveConstDefinedValue(block, thread_local_src, is_thread_local, .{ .simple = .extern_options }); const library_name = if (library_name_val.optionalValue(zcu)) |library_name_payload| library_name: { @@ -25735,13 +25964,17 @@ fn resolveExternOptions( break :library_name library_name; } else null; - const is_dll_import_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "is_dll_import", .no_embedded_nulls), dll_import_src); + const is_dll_import_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "is_dll_import", .no_embedded_nulls), dll_import_src); const is_dll_import_val = try sema.resolveConstDefinedValue(block, dll_import_src, is_dll_import_ref, .{ .simple = .extern_options }); - const relocation_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "relocation", .no_embedded_nulls), relocation_src); + const relocation_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "relocation", .no_embedded_nulls), relocation_src); const relocation_val = try sema.resolveConstDefinedValue(block, relocation_src, relocation_ref, .{ .simple = .extern_options }); const relocation = try sema.interpretBuiltinType(block, relocation_src, relocation_val, std.builtin.ExternOptions.Relocation); + const decoration_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "decoration", .no_embedded_nulls), decoration_src); + const decoration_val = try sema.resolveConstDefinedValue(block, decoration_src, decoration_ref, .{ .simple = .extern_options }); + const decoration = try sema.interpretBuiltinType(block, decoration_src, decoration_val, ?std.builtin.ExternOptions.Decoration); + if (name.len == 0) { return sema.fail(block, name_src, "extern symbol name cannot be empty", .{}); } @@ -25751,13 +25984,14 @@ fn resolveExternOptions( } return .{ - .name = try ip.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls), - .library_name = try ip.getOrPutStringOpt(gpa, pt.tid, library_name, .no_embedded_nulls), + .name = try ip.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls), + .library_name = try ip.getOrPutStringOpt(gpa, io, pt.tid, library_name, .no_embedded_nulls), .linkage = linkage, .visibility = visibility, .is_thread_local = is_thread_local_val.toBool(), .is_dll_import = is_dll_import_val.toBool(), .relocation = relocation, + .decoration = decoration, }; } @@ -25817,6 +26051,7 @@ fn zirBuiltinExtern( .is_threadlocal = options.is_thread_local, .is_dll_import = options.is_dll_import, .relocation = options.relocation, + .decoration = options.decoration, .is_const = ptr_info.flags.is_const, .alignment = ptr_info.flags.alignment, .@"addrspace" = ptr_info.flags.address_space, @@ -25897,7 +26132,9 @@ fn zirInComptime( fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - const gpa = zcu.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand))); @@ -25933,7 +26170,7 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD block, src, callconv_ty.getNamespaceIndex(zcu), - try ip.getOrPutString(gpa, pt.tid, "c", .no_embedded_nulls), + try ip.getOrPutString(gpa, io, pt.tid, "c", .no_embedded_nulls), ) orelse @panic("std.builtin is corrupt"); }, .calling_convention_inline => { @@ -26470,11 +26707,12 @@ fn preparePanicId(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) !vo fn getPanicIdFunc(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) !InternPool.Index { const zcu = sema.pt.zcu; + const io = zcu.comp.io; try sema.ensureMemoizedStateResolved(src, .panic); const panic_fn_index = zcu.builtin_decl_values.get(panic_id.toBuiltin()); switch (sema.owner.unwrap()) { .@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {}, - .func => |owner_func| zcu.intern_pool.funcSetHasErrorTrace(owner_func, true), + .func => |owner_func| zcu.intern_pool.funcSetHasErrorTrace(io, owner_func, true), } return panic_fn_index; } @@ -28517,10 +28755,15 @@ fn coerceExtra( inst_src: LazySrcLoc, opts: CoerceOpts, ) CoersionError!Air.Inst.Ref { - if (dest_ty.isGenericPoison()) return inst; const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; + + if (dest_ty.isGenericPoison()) return inst; + const dest_ty_src = inst_src; // TODO better source location try dest_ty.resolveFields(pt); const inst_ty = sema.typeOf(inst); @@ -28882,7 +29125,7 @@ fn coerceExtra( return switch (zcu.intern_pool.indexToKey(val.toIntern())) { .undef => try pt.undefRef(dest_ty), .int => |int| Air.internedToRef( - try zcu.intern_pool.getCoercedInts(zcu.gpa, pt.tid, int, dest_ty.toIntern()), + try zcu.intern_pool.getCoercedInts(gpa, io, pt.tid, int, dest_ty.toIntern()), ), else => unreachable, }; @@ -29001,33 +29244,6 @@ fn coerceExtra( else => {}, }, .error_union => switch (inst_ty.zigTypeTag(zcu)) { - .error_union => eu: { - if (maybe_inst_val) |inst_val| { - switch (inst_val.toIntern()) { - .undef => return pt.undefRef(dest_ty), - else => switch (zcu.intern_pool.indexToKey(inst_val.toIntern())) { - .error_union => |error_union| switch (error_union.val) { - .err_name => |err_name| { - const error_set_ty = inst_ty.errorUnionSet(zcu); - const error_set_val = Air.internedToRef((try pt.intern(.{ .err = .{ - .ty = error_set_ty.toIntern(), - .name = err_name, - } }))); - return sema.wrapErrorUnionSet(block, dest_ty, error_set_val, inst_src); - }, - .payload => |payload| { - const payload_val = Air.internedToRef(payload); - return sema.wrapErrorUnionPayload(block, dest_ty, payload_val, inst_src) catch |err| switch (err) { - error.NotCoercible => break :eu, - else => |e| return e, - }; - }, - }, - else => unreachable, - }, - } - } - }, .error_set => { // E to E!T return sema.wrapErrorUnionSet(block, dest_ty, inst, inst_src); @@ -30075,6 +30291,10 @@ fn coerceInMemoryAllowedPtrs( ) !InMemoryCoercionResult { const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const dest_info = dest_ptr_ty.ptrInfo(zcu); const src_info = src_ptr_ty.ptrInfo(zcu); @@ -30180,7 +30400,7 @@ fn coerceInMemoryAllowedPtrs( const ds = dest_info.sentinel; if (ss == .none and ds == .none) break :ok true; if (ss != .none and ds != .none) { - if (ds == try zcu.intern_pool.getCoerced(sema.gpa, pt.tid, ss, dest_info.child)) break :ok true; + if (ds == try zcu.intern_pool.getCoerced(gpa, io, pt.tid, ss, dest_info.child)) break :ok true; } if (src_info.flags.size == .c) break :ok true; if (!dest_is_mut and dest_info.sentinel == .none) break :ok true; @@ -31607,13 +31827,7 @@ fn analyzeIsNonErrComptimeOnly( return .bool_false; } - if (operand.toIndex()) |operand_inst| { - switch (sema.air_instructions.items(.tag)[@intFromEnum(operand_inst)]) { - .wrap_errunion_payload => return .bool_true, - .wrap_errunion_err => return .bool_false, - else => {}, - } - } else if (operand == .undef) { + if (operand == .undef) { return .undef_bool; } else if (@intFromEnum(operand) < InternPool.static_len) { // None of the ref tags can be errors. @@ -32058,9 +32272,15 @@ fn analyzeSlice( var runtime_src: ?LazySrcLoc = null; // requirement: start <= end - if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| { - if (try sema.resolveDefinedValue(block, start_src, start)) |start_val| { - if (!by_length and !(try sema.compareAll(start_val, .lte, end_val, .usize))) { + if (try sema.resolveDefinedValue(block, start_src, start)) |start_val| { + if (try sema.compareAll(start_val, .eq, .zero_usize, .usize)) { + checked_start_lte_end = true; + } + if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| { + if (!checked_start_lte_end and + !by_length and + !(try sema.compareAll(start_val, .lte, end_val, .usize))) + { return sema.fail( block, start_src, @@ -32116,10 +32336,10 @@ fn analyzeSlice( runtime_src = ptr_src; } } else { - runtime_src = start_src; + runtime_src = end_src; } } else { - runtime_src = end_src; + runtime_src = start_src; } if (!checked_start_lte_end and block.wantSafety() and !block.isComptime()) { @@ -32182,7 +32402,9 @@ fn analyzeSlice( else end; - try sema.addSafetyCheckIndexOob(block, src, actual_end, actual_len, .cmp_lte); + if (try sema.resolveDefinedValue(block, src, actual_len) == null or + try sema.resolveDefinedValue(block, src, actual_end) == null) + try sema.addSafetyCheckIndexOob(block, src, actual_end, actual_len, .cmp_lte); } // requirement: result[new_len] == slice_sentinel @@ -32247,9 +32469,6 @@ fn analyzeSlice( end; try sema.addSafetyCheckIndexOob(block, src, actual_end, len_inst, .cmp_lte); } - - // requirement: start <= end - try sema.addSafetyCheckIndexOob(block, src, start, end, .cmp_lte); } const result = try block.addInst(.{ .tag = .slice, @@ -33097,6 +33316,9 @@ fn resolvePeerTypesInner( ) !PeerResolveResult { const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; var strat_reason: usize = 0; @@ -33423,8 +33645,8 @@ fn resolvePeerTypesInner( }).toIntern(); if (ptr_info.sentinel != .none and peer_info.sentinel != .none) { - const peer_sent = try ip.getCoerced(sema.gpa, pt.tid, ptr_info.sentinel, ptr_info.child); - const ptr_sent = try ip.getCoerced(sema.gpa, pt.tid, peer_info.sentinel, ptr_info.child); + const peer_sent = try ip.getCoerced(gpa, io, pt.tid, ptr_info.sentinel, ptr_info.child); + const ptr_sent = try ip.getCoerced(gpa, io, pt.tid, peer_info.sentinel, ptr_info.child); if (ptr_sent == peer_sent) { ptr_info.sentinel = ptr_sent; } else { @@ -33726,8 +33948,8 @@ fn resolvePeerTypesInner( no_sentinel: { if (peer_sentinel == .none) break :no_sentinel; if (cur_sentinel == .none) break :no_sentinel; - const peer_sent_coerced = try ip.getCoerced(sema.gpa, pt.tid, peer_sentinel, sentinel_ty); - const cur_sent_coerced = try ip.getCoerced(sema.gpa, pt.tid, cur_sentinel, sentinel_ty); + const peer_sent_coerced = try ip.getCoerced(gpa, io, pt.tid, peer_sentinel, sentinel_ty); + const cur_sent_coerced = try ip.getCoerced(gpa, io, pt.tid, cur_sentinel, sentinel_ty); if (peer_sent_coerced != cur_sent_coerced) break :no_sentinel; // Sentinels match if (ptr_info.flags.size == .one) switch (ip.indexToKey(ptr_info.child)) { @@ -34092,7 +34314,7 @@ fn resolvePeerTypesInner( else => |result| { const result_buf = try sema.arena.create(PeerResolveResult); result_buf.* = result; - const field_name = try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls); + const field_name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{d}", .{field_index}, .no_embedded_nulls); // The error info needs the field types, but we can't reuse sub_peer_tys // since the recursive call may have clobbered it. @@ -34147,7 +34369,7 @@ fn resolvePeerTypesInner( field_val.* = if (comptime_val) |v| v.toIntern() else .none; } - const final_ty = try ip.getTupleType(zcu.gpa, pt.tid, .{ + const final_ty = try ip.getTupleType(gpa, io, pt.tid, .{ .types = field_types, .values = field_vals, }); @@ -34285,6 +34507,7 @@ pub fn resolveStructAlignment( ) SemaError!void { const pt = sema.pt; const zcu = pt.zcu; + const io = zcu.comp.io; const ip = &zcu.intern_pool; const target = zcu.getTarget(); @@ -34298,15 +34521,15 @@ pub fn resolveStructAlignment( // We'll guess "pointer-aligned", if the struct has an // underaligned pointer field then some allocations // might require explicit alignment. - if (struct_type.assumePointerAlignedIfFieldTypesWip(ip, ptr_align)) return; + if (struct_type.assumePointerAlignedIfFieldTypesWip(ip, io, ptr_align)) return; try sema.resolveStructFieldTypes(ty, struct_type); // We'll guess "pointer-aligned", if the struct has an // underaligned pointer field then some allocations // might require explicit alignment. - if (struct_type.assumePointerAlignedIfWip(ip, ptr_align)) return; - defer struct_type.clearAlignmentWip(ip); + if (struct_type.assumePointerAlignedIfWip(ip, io, ptr_align)) return; + defer struct_type.clearAlignmentWip(ip, io); // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis. // It's just triggering *other* analysis, alongside a simple loop over already-resolved info. @@ -34325,13 +34548,14 @@ pub fn resolveStructAlignment( alignment = alignment.maxStrict(field_align); } - struct_type.setAlignment(ip, alignment); + struct_type.setAlignment(ip, io, alignment); } pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void { const pt = sema.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; + const io = zcu.comp.io; const struct_type = zcu.typeToStruct(ty) orelse return; assert(sema.owner.unwrap().type == ty.toIntern()); @@ -34352,7 +34576,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void { return; } - if (struct_type.setLayoutWip(ip)) { + if (struct_type.setLayoutWip(ip, io)) { const msg = try sema.errMsg( ty.srcLoc(zcu), "struct '{f}' depends on itself", @@ -34360,7 +34584,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void { ); return sema.failWithOwnedErrorMsg(null, msg); } - defer struct_type.clearLayoutWip(ip); + defer struct_type.clearLayoutWip(ip, io); const aligns = try sema.arena.alloc(Alignment, struct_type.field_types.len); const sizes = try sema.arena.alloc(u64, struct_type.field_types.len); @@ -34479,7 +34703,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void { ); return sema.failWithOwnedErrorMsg(null, msg); }; - struct_type.setLayoutResolved(ip, size, big_align); + struct_type.setLayoutResolved(ip, io, size, big_align); _ = try ty.comptimeOnlySema(pt); } @@ -34489,7 +34713,9 @@ fn backingIntType( ) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; - const gpa = zcu.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; var analysis_arena = std.heap.ArenaAllocator.init(gpa); @@ -34557,13 +34783,13 @@ fn backingIntType( }; try sema.checkBackingIntType(&block, backing_int_src, backing_int_ty, fields_bit_sum); - struct_type.setBackingIntType(ip, backing_int_ty.toIntern()); + struct_type.setBackingIntType(ip, io, backing_int_ty.toIntern()); } else { if (fields_bit_sum > std.math.maxInt(u16)) { return sema.fail(&block, block.nodeOffset(.zero), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum}); } const backing_int_ty = try pt.intType(.unsigned, @intCast(fields_bit_sum)); - struct_type.setBackingIntType(ip, backing_int_ty.toIntern()); + struct_type.setBackingIntType(ip, io, backing_int_ty.toIntern()); } try sema.flushExports(); @@ -34631,6 +34857,7 @@ pub fn resolveUnionAlignment( ) SemaError!void { const pt = sema.pt; const zcu = pt.zcu; + const io = zcu.comp.io; const ip = &zcu.intern_pool; const target = zcu.getTarget(); @@ -34643,7 +34870,7 @@ pub fn resolveUnionAlignment( // We'll guess "pointer-aligned", if the union has an // underaligned pointer field then some allocations // might require explicit alignment. - if (union_type.assumePointerAlignedIfFieldTypesWip(ip, ptr_align)) return; + if (union_type.assumePointerAlignedIfFieldTypesWip(ip, io, ptr_align)) return; try sema.resolveUnionFieldTypes(ty, union_type); @@ -34664,12 +34891,13 @@ pub fn resolveUnionAlignment( max_align = max_align.max(field_align); } - union_type.setAlignment(ip, max_align); + union_type.setAlignment(ip, io, max_align); } /// This logic must be kept in sync with `Type.getUnionLayout`. pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void { const pt = sema.pt; + const io = pt.zcu.comp.io; const ip = &pt.zcu.intern_pool; try sema.resolveUnionFieldTypes(ty, ip.loadUnionType(ty.ip_index)); @@ -34693,9 +34921,9 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void { .have_layout, .fully_resolved_wip, .fully_resolved => return, } - errdefer union_type.setStatusIfLayoutWip(ip, old_flags.status); + errdefer union_type.setStatusIfLayoutWip(ip, io, old_flags.status); - union_type.setStatus(ip, .layout_wip); + union_type.setStatus(ip, io, .layout_wip); // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis. // It's just triggering *other* analysis, alongside a simple loop over already-resolved info. @@ -34776,7 +35004,7 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void { ); return sema.failWithOwnedErrorMsg(null, msg); }; - union_type.setHaveLayout(ip, casted_size, padding, alignment); + union_type.setHaveLayout(ip, io, casted_size, padding, alignment); if (union_type.flagsUnordered(ip).assumed_runtime_bits and !(try ty.hasRuntimeBitsSema(pt))) { const msg = try sema.errMsg( @@ -34808,13 +35036,14 @@ pub fn resolveStructFully(sema: *Sema, ty: Type) SemaError!void { const pt = sema.pt; const zcu = pt.zcu; + const io = zcu.comp.io; const ip = &zcu.intern_pool; const struct_type = zcu.typeToStruct(ty).?; assert(sema.owner.unwrap().type == ty.toIntern()); - if (struct_type.setFullyResolved(ip)) return; - errdefer struct_type.clearFullyResolved(ip); + if (struct_type.setFullyResolved(ip, io)) return; + errdefer struct_type.clearFullyResolved(ip, io); // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis. // It's just triggering *other* analysis, alongside a simple loop over already-resolved info. @@ -34834,6 +35063,7 @@ pub fn resolveUnionFully(sema: *Sema, ty: Type) SemaError!void { const pt = sema.pt; const zcu = pt.zcu; + const io = zcu.comp.io; const ip = &zcu.intern_pool; const union_obj = zcu.typeToUnion(ty).?; @@ -34852,14 +35082,14 @@ pub fn resolveUnionFully(sema: *Sema, ty: Type) SemaError!void { // make sure pointer fields get their child types resolved as well. // See also similar code for structs. const prev_status = union_obj.flagsUnordered(ip).status; - errdefer union_obj.setStatus(ip, prev_status); + errdefer union_obj.setStatus(ip, io, prev_status); - union_obj.setStatus(ip, .fully_resolved_wip); + union_obj.setStatus(ip, io, .fully_resolved_wip); for (0..union_obj.field_types.len) |field_index| { const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); try field_ty.resolveFully(pt); } - union_obj.setStatus(ip, .fully_resolved); + union_obj.setStatus(ip, io, .fully_resolved); } // And let's not forget comptime-only status. @@ -34873,13 +35103,14 @@ pub fn resolveStructFieldTypes( ) SemaError!void { const pt = sema.pt; const zcu = pt.zcu; + const io = zcu.comp.io; const ip = &zcu.intern_pool; assert(sema.owner.unwrap().type == ty); if (struct_type.haveFieldTypes(ip)) return; - if (struct_type.setFieldTypesWip(ip)) { + if (struct_type.setFieldTypesWip(ip, io)) { const msg = try sema.errMsg( Type.fromInterned(ty).srcLoc(zcu), "struct '{f}' depends on itself", @@ -34887,7 +35118,7 @@ pub fn resolveStructFieldTypes( ); return sema.failWithOwnedErrorMsg(null, msg); } - defer struct_type.clearFieldTypesWip(ip); + defer struct_type.clearFieldTypesWip(ip, io); // can't happen earlier than this because we only want the progress node if not already resolved const tracked_unit = zcu.trackUnitSema(struct_type.name.toSlice(ip), null); @@ -34902,6 +35133,7 @@ pub fn resolveStructFieldTypes( pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void { const pt = sema.pt; const zcu = pt.zcu; + const io = zcu.comp.io; const ip = &zcu.intern_pool; const struct_type = zcu.typeToStruct(ty) orelse return; @@ -34912,7 +35144,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void { try sema.resolveStructLayout(ty); - if (struct_type.setInitsWip(ip)) { + if (struct_type.setInitsWip(ip, io)) { const msg = try sema.errMsg( ty.srcLoc(zcu), "struct '{f}' depends on itself", @@ -34920,7 +35152,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void { ); return sema.failWithOwnedErrorMsg(null, msg); } - defer struct_type.clearInitsWip(ip); + defer struct_type.clearInitsWip(ip, io); // can't happen earlier than this because we only want the progress node if not already resolved const tracked_unit = zcu.trackUnitSema(struct_type.name.toSlice(ip), null); @@ -34930,12 +35162,13 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void { error.AnalysisFail, error.OutOfMemory, error.Canceled => |e| return e, error.ComptimeBreak, error.ComptimeReturn => unreachable, }; - struct_type.setHaveFieldInits(ip); + struct_type.setHaveFieldInits(ip, io); } pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.LoadedUnionType) SemaError!void { const pt = sema.pt; const zcu = pt.zcu; + const io = zcu.comp.io; const ip = &zcu.intern_pool; assert(sema.owner.unwrap().type == ty.toIntern()); @@ -34958,13 +35191,13 @@ pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.Load const tracked_unit = zcu.trackUnitSema(union_type.name.toSlice(ip), null); defer tracked_unit.end(zcu); - union_type.setStatus(ip, .field_types_wip); - errdefer union_type.setStatus(ip, .none); + union_type.setStatus(ip, io, .field_types_wip); + errdefer union_type.setStatus(ip, io, .none); sema.unionFields(ty.toIntern(), union_type) catch |err| switch (err) { error.AnalysisFail, error.OutOfMemory, error.Canceled => |e| return e, error.ComptimeBreak, error.ComptimeReturn => unreachable, }; - union_type.setStatus(ip, .have_field_types); + union_type.setStatus(ip, io, .have_field_types); } /// Returns a normal error set corresponding to the fully populated inferred @@ -35066,11 +35299,14 @@ fn resolveAdHocInferredErrorSet( ) CompileError!InternPool.Index { const pt = sema.pt; const zcu = pt.zcu; - const gpa = sema.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; + const new_ty = try resolveAdHocInferredErrorSetTy(sema, block, src, ip.typeOf(value)); if (new_ty == .none) return value; - return ip.getCoerced(gpa, pt.tid, value, new_ty); + return ip.getCoerced(gpa, io, pt.tid, value, new_ty); } fn resolveAdHocInferredErrorSetTy( @@ -35170,8 +35406,11 @@ fn structFields( ) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; - const gpa = zcu.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; + const namespace_index = struct_type.namespace; const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir.?; const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail; @@ -35184,7 +35423,7 @@ fn structFields( return; }, .auto, .@"extern" => { - struct_type.setLayoutResolved(ip, 0, .none); + struct_type.setLayoutResolved(ip, io, 0, .none); return; }, }; @@ -35256,7 +35495,7 @@ fn structFields( extra_index += 1; // This string needs to outlive the ZIR code. - const field_name = try ip.getOrPutString(gpa, pt.tid, field_name_zir, .no_embedded_nulls); + const field_name = try ip.getOrPutString(gpa, io, pt.tid, field_name_zir, .no_embedded_nulls); assert(struct_type.addFieldName(ip, field_name) == null); if (has_align) { @@ -35356,8 +35595,8 @@ fn structFields( extra_index += zir_field.init_body_len; } - struct_type.clearFieldTypesWip(ip); - if (!any_inits) struct_type.setHaveFieldInits(ip); + struct_type.clearFieldTypesWip(ip, io); + if (!any_inits) struct_type.setHaveFieldInits(ip, io); try sema.flushExports(); } @@ -35496,8 +35735,11 @@ fn unionFields( const pt = sema.pt; const zcu = pt.zcu; - const gpa = zcu.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; + const zir = zcu.namespacePtr(union_type.namespace).fileScope(zcu).zir.?; const zir_index = union_type.zir_index.resolve(ip) orelse return error.AnalysisFail; const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; @@ -35606,7 +35848,7 @@ fn unionFields( .enum_type => ip.loadEnumType(provided_ty.toIntern()), else => return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{f}'", .{provided_ty.fmt(pt)}), }; - union_type.setTagType(ip, provided_ty.toIntern()); + union_type.setTagType(ip, io, provided_ty.toIntern()); // The fields of the union must match the enum exactly. // A flag per field is used to check for missing and extraneous fields. explicit_tags_seen = try sema.arena.alloc(bool, enum_type.names.len); @@ -35738,7 +35980,7 @@ fn unionFields( } // This string needs to outlive the ZIR code. - const field_name = try ip.getOrPutString(gpa, pt.tid, field_name_zir, .no_embedded_nulls); + const field_name = try ip.getOrPutString(gpa, io, pt.tid, field_name_zir, .no_embedded_nulls); if (enum_field_names.len != 0) { enum_field_names[field_i] = field_name; } @@ -35882,10 +36124,10 @@ fn unionFields( } } else if (enum_field_vals.count() > 0) { const enum_ty = try sema.generateUnionTagTypeNumbered(&block_scope, enum_field_names, enum_field_vals.keys(), union_ty, union_type.name); - union_type.setTagType(ip, enum_ty); + union_type.setTagType(ip, io, enum_ty); } else { const enum_ty = try sema.generateUnionTagTypeSimple(&block_scope, enum_field_names, union_ty, union_type.name); - union_type.setTagType(ip, enum_ty); + union_type.setTagType(ip, io, enum_ty); } try sema.flushExports(); @@ -35901,18 +36143,21 @@ fn generateUnionTagTypeNumbered( ) !InternPool.Index { const pt = sema.pt; const zcu = pt.zcu; - const gpa = sema.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; const name = try ip.getOrPutStringFmt( gpa, + io, pt.tid, "@typeInfo({f}).@\"union\".tag_type.?", .{union_name.fmt(ip)}, .no_embedded_nulls, ); - const enum_ty = try ip.getGeneratedTagEnumType(gpa, pt.tid, .{ + const enum_ty = try ip.getGeneratedTagEnumType(gpa, io, pt.tid, .{ .name = name, .owner_union_ty = union_type, .tag_ty = if (enum_field_vals.len == 0) @@ -35937,18 +36182,21 @@ fn generateUnionTagTypeSimple( ) !InternPool.Index { const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; - const gpa = sema.gpa; const name = try ip.getOrPutStringFmt( gpa, + io, pt.tid, "@typeInfo({f}).@\"union\".tag_type.?", .{union_name.fmt(ip)}, .no_embedded_nulls, ); - const enum_ty = try ip.getGeneratedTagEnumType(gpa, pt.tid, .{ + const enum_ty = try ip.getGeneratedTagEnumType(gpa, io, pt.tid, .{ .name = name, .owner_union_ty = union_type, .tag_ty = (try pt.smallestUnsignedInt(enum_field_names.len -| 1)).toIntern(), @@ -35969,7 +36217,11 @@ fn generateUnionTagTypeSimple( pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; + return switch (ty.toIntern()) { .u0_type, .i0_type, @@ -36313,7 +36565,8 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { (try pt.intValue(.fromInterned(enum_type.tag_ty), 0)).toIntern() else try ip.getCoercedInts( - zcu.gpa, + gpa, + io, pt.tid, ip.indexToKey(enum_type.values.get(ip)[0]).int, enum_type.tag_ty, @@ -36947,12 +37200,16 @@ fn checkRuntimeValue(sema: *Sema, ptr: Air.Inst.Ref) bool { fn validateRuntimeValue(sema: *Sema, block: *Block, val_src: LazySrcLoc, val: Air.Inst.Ref) CompileError!void { if (sema.checkRuntimeValue(val)) return; return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(val_src, "runtime value contains reference to comptime var", .{}); - errdefer msg.destroy(sema.gpa); - try sema.errNote(val_src, msg, "comptime var pointers are not available at runtime", .{}); const pt = sema.pt; const zcu = pt.zcu; - const val_str = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, "runtime_value", .no_embedded_nulls); + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + + const msg = try sema.errMsg(val_src, "runtime value contains reference to comptime var", .{}); + errdefer msg.destroy(gpa); + try sema.errNote(val_src, msg, "comptime var pointers are not available at runtime", .{}); + const val_str = try pt.zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "runtime_value", .no_embedded_nulls); try sema.explainWhyValueContainsReferenceToComptimeVar(msg, val_src, val_str, .fromInterned(val.toInterned().?)); break :msg msg; }); @@ -37396,7 +37653,9 @@ fn resolveDeclaredEnumInner( ) Zcu.CompileError!void { const pt = sema.pt; const zcu = pt.zcu; - const gpa = zcu.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable; @@ -37441,7 +37700,7 @@ fn resolveDeclaredEnumInner( const field_name_zir = zir.nullTerminatedString(field_name_index); extra_index += 1; // field name - const field_name = try ip.getOrPutString(gpa, pt.tid, field_name_zir, .no_embedded_nulls); + const field_name = try ip.getOrPutString(gpa, io, pt.tid, field_name_zir, .no_embedded_nulls); const value_src: LazySrcLoc = .{ .base_node_inst = tracked_inst, @@ -37552,7 +37811,9 @@ pub fn resolveNavPtrModifiers( ) CompileError!NavPtrModifiers { const pt = sema.pt; const zcu = pt.zcu; - const gpa = zcu.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; const align_src = block.src(.{ .node_offset_var_decl_align = .zero }); @@ -37574,7 +37835,7 @@ pub fn resolveNavPtrModifiers( } else if (bytes.len == 0) { return sema.fail(block, section_src, "linksection cannot be empty", .{}); } - break :ls try ip.getOrPutStringOpt(gpa, pt.tid, bytes, .no_embedded_nulls); + break :ls try ip.getOrPutStringOpt(gpa, io, pt.tid, bytes, .no_embedded_nulls); }; const @"addrspace": std.builtin.AddressSpace = as: { @@ -37606,8 +37867,10 @@ pub fn resolveNavPtrModifiers( pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc, builtin_namespace: InternPool.NamespaceIndex, stage: InternPool.MemoizedStateStage) CompileError!bool { const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; - const gpa = zcu.gpa; var any_changed = false; @@ -37624,7 +37887,7 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc, }, }; - const name_nts = try ip.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls); + const name_nts = try ip.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls); const nav = try sema.namespaceLookup(block, simple_src, parent_ns, name_nts) orelse return sema.fail(block, simple_src, "{s} missing {s}", .{ parent_name, name }); diff --git a/src/Sema/LowerZon.zig b/src/Sema/LowerZon.zig index eb1fba121a69..76cf3d7f2cc0 100644 --- a/src/Sema/LowerZon.zig +++ b/src/Sema/LowerZon.zig @@ -38,8 +38,11 @@ pub fn run( block: *Sema.Block, ) CompileError!InternPool.Index { const pt = sema.pt; + const comp = pt.zcu.comp; + const gpa = comp.gpa; + const io = comp.io; - const tracked_inst = try pt.zcu.intern_pool.trackZir(pt.zcu.gpa, pt.tid, .{ + const tracked_inst = try pt.zcu.intern_pool.trackZir(gpa, io, pt.tid, .{ .file = file_index, .inst = .main_struct_inst, // this is the only trackable instruction in a ZON file }); @@ -63,8 +66,10 @@ pub fn run( } fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!InternPool.Index { - const gpa = self.sema.gpa; const pt = self.sema.pt; + const comp = pt.zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &pt.zcu.intern_pool; switch (node.get(self.file.zoir.?)) { .true => return .bool_true, @@ -94,13 +99,14 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter .enum_literal => |val| return pt.intern(.{ .enum_literal = try ip.getOrPutString( gpa, + io, pt.tid, val.get(self.file.zoir.?), .no_embedded_nulls, ), }), .string_literal => |val| { - const ip_str = try ip.getOrPutString(gpa, pt.tid, val, .maybe_embedded_nulls); + const ip_str = try ip.getOrPutString(gpa, io, pt.tid, val, .maybe_embedded_nulls); const result = try self.sema.addStrLit(ip_str, val.len); return result.toInterned().?; }, @@ -112,14 +118,10 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter values[i] = try self.lowerExprAnonResTy(nodes.at(@intCast(i))); types[i] = Value.fromInterned(values[i]).typeOf(pt.zcu).toIntern(); } - const ty = try ip.getTupleType( - gpa, - pt.tid, - .{ - .types = types, - .values = values, - }, - ); + const ty = try ip.getTupleType(gpa, io, pt.tid, .{ + .types = types, + .values = values, + }); return (try pt.aggregateValue(.fromInterned(ty), values)).toIntern(); }, .struct_literal => |init| { @@ -129,6 +131,7 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter } const struct_ty = switch (try ip.getStructType( gpa, + io, pt.tid, .{ .layout = .auto, @@ -168,6 +171,7 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter for (init.names, 0..) |name, field_idx| { const name_interned = try ip.getOrPutString( gpa, + io, pt.tid, name.get(self.file.zoir.?), .no_embedded_nulls, @@ -636,11 +640,16 @@ fn lowerArray(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. } fn lowerEnum(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.Index { - const ip = &self.sema.pt.zcu.intern_pool; + const pt = self.sema.pt; + const comp = pt.zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const ip = &pt.zcu.intern_pool; switch (node.get(self.file.zoir.?)) { .enum_literal => |field_name| { const field_name_interned = try ip.getOrPutString( - self.sema.gpa, + gpa, + io, self.sema.pt.tid, field_name.get(self.file.zoir.?), .no_embedded_nulls, @@ -665,11 +674,16 @@ fn lowerEnum(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.I } fn lowerEnumLiteral(self: *LowerZon, node: Zoir.Node.Index) !InternPool.Index { - const ip = &self.sema.pt.zcu.intern_pool; + const pt = self.sema.pt; + const comp = pt.zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const ip = &pt.zcu.intern_pool; switch (node.get(self.file.zoir.?)) { .enum_literal => |field_name| { const field_name_interned = try ip.getOrPutString( - self.sema.gpa, + gpa, + io, self.sema.pt.tid, field_name.get(self.file.zoir.?), .no_embedded_nulls, @@ -747,8 +761,11 @@ fn lowerTuple(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. } fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.Index { - const ip = &self.sema.pt.zcu.intern_pool; - const gpa = self.sema.gpa; + const pt = self.sema.pt; + const comp = pt.zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const ip = &pt.zcu.intern_pool; try res_ty.resolveFields(self.sema.pt); try res_ty.resolveStructFieldInits(self.sema.pt); @@ -772,6 +789,7 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool for (0..fields.names.len) |i| { const field_name = try ip.getOrPutString( gpa, + io, self.sema.pt.tid, fields.names[i].get(self.file.zoir.?), .no_embedded_nulls, @@ -807,8 +825,11 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool } fn lowerSlice(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.Index { - const ip = &self.sema.pt.zcu.intern_pool; - const gpa = self.sema.gpa; + const pt = self.sema.pt; + const comp = pt.zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const ip = &pt.zcu.intern_pool; const ptr_info = res_ty.ptrInfo(self.sema.pt.zcu); @@ -820,7 +841,7 @@ fn lowerSlice(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. if (string_alignment and ptr_info.child == .u8_type and string_sentinel) { switch (node.get(self.file.zoir.?)) { .string_literal => |val| { - const ip_str = try ip.getOrPutString(gpa, self.sema.pt.tid, val, .maybe_embedded_nulls); + const ip_str = try ip.getOrPutString(gpa, io, self.sema.pt.tid, val, .maybe_embedded_nulls); const str_ref = try self.sema.addStrLit(ip_str, val.len); return (try self.sema.coerce( self.block, @@ -892,7 +913,11 @@ fn lowerSlice(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. } fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.Index { - const ip = &self.sema.pt.zcu.intern_pool; + const pt = self.sema.pt; + const comp = pt.zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const ip = &pt.zcu.intern_pool; try res_ty.resolveFields(self.sema.pt); const union_info = self.sema.pt.zcu.typeToUnion(res_ty).?; const enum_tag_info = union_info.loadTagType(ip); @@ -900,7 +925,8 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. const field_name, const maybe_field_node = switch (node.get(self.file.zoir.?)) { .enum_literal => |name| b: { const field_name = try ip.getOrPutString( - self.sema.gpa, + gpa, + io, self.sema.pt.tid, name.get(self.file.zoir.?), .no_embedded_nulls, @@ -916,7 +942,8 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. return error.WrongType; } const field_name = try ip.getOrPutString( - self.sema.gpa, + gpa, + io, self.sema.pt.tid, fields.names[0].get(self.file.zoir.?), .no_embedded_nulls, @@ -942,7 +969,7 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. } break :b .void_value; }; - return ip.getUnion(self.sema.pt.zcu.gpa, self.sema.pt.tid, .{ + return ip.getUnion(gpa, io, self.sema.pt.tid, .{ .ty = res_ty.toIntern(), .tag = tag.toIntern(), .val = val, diff --git a/src/Type.zig b/src/Type.zig index 3c13f3db949d..e6a8965409c6 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -486,6 +486,7 @@ pub fn hasRuntimeBitsInner( tid: strat.Tid(), ) RuntimeBitsError!bool { const ip = &zcu.intern_pool; + const io = zcu.comp.io; return switch (ty.toIntern()) { .empty_tuple_type => false, else => switch (ip.indexToKey(ty.toIntern())) { @@ -571,7 +572,7 @@ pub fn hasRuntimeBitsInner( }, .struct_type => { const struct_type = ip.loadStructType(ty.toIntern()); - if (strat != .eager and struct_type.assumeRuntimeBitsIfFieldTypesWip(ip)) { + if (strat != .eager and struct_type.assumeRuntimeBitsIfFieldTypesWip(ip, io)) { // In this case, we guess that hasRuntimeBits() for this type is true, // and then later if our guess was incorrect, we emit a compile error. return true; @@ -610,7 +611,7 @@ pub fn hasRuntimeBitsInner( .none => if (strat != .eager) { // In this case, we guess that hasRuntimeBits() for this type is true, // and then later if our guess was incorrect, we emit a compile error. - if (union_type.assumeRuntimeBitsIfFieldTypesWip(ip)) return true; + if (union_type.assumeRuntimeBitsIfFieldTypesWip(ip, io)) return true; }, .safety, .tagged => {}, } @@ -2491,8 +2492,11 @@ pub fn isNumeric(ty: Type, zcu: *const Zcu) bool { /// resolves field types rather than asserting they are already resolved. pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value { const zcu = pt.zcu; - var ty = starting_type; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; + var ty = starting_type; while (true) switch (ty.toIntern()) { .empty_tuple_type => return Value.empty_tuple, @@ -2664,7 +2668,8 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value { (try pt.intValue(.fromInterned(enum_type.tag_ty), 0)).toIntern() else try ip.getCoercedInts( - zcu.gpa, + gpa, + io, pt.tid, ip.indexToKey(enum_type.values.get(ip)[0]).int, enum_type.tag_ty, @@ -2720,6 +2725,7 @@ pub fn comptimeOnlyInner( tid: strat.Tid(), ) SemaError!bool { const ip = &zcu.intern_pool; + const io = zcu.comp.io; return switch (ty.toIntern()) { .empty_tuple_type => false, @@ -2798,16 +2804,16 @@ pub fn comptimeOnlyInner( .yes => true, .unknown => unreachable, }, - .sema => switch (struct_type.setRequiresComptimeWip(ip)) { + .sema => switch (struct_type.setRequiresComptimeWip(ip, io)) { .no, .wip => false, .yes => true, .unknown => { if (struct_type.flagsUnordered(ip).field_types_wip) { - struct_type.setRequiresComptime(ip, .unknown); + struct_type.setRequiresComptime(ip, io, .unknown); return false; } - errdefer struct_type.setRequiresComptime(ip, .unknown); + errdefer struct_type.setRequiresComptime(ip, io, .unknown); const pt = strat.pt(zcu, tid); try ty.resolveFields(pt); @@ -2821,12 +2827,12 @@ pub fn comptimeOnlyInner( // be considered resolved. Comptime-only types // still maintain a layout of their // runtime-known fields. - struct_type.setRequiresComptime(ip, .yes); + struct_type.setRequiresComptime(ip, io, .yes); return true; } } - struct_type.setRequiresComptime(ip, .no); + struct_type.setRequiresComptime(ip, io, .no); return false; }, }, @@ -2850,16 +2856,16 @@ pub fn comptimeOnlyInner( .yes => true, .unknown => unreachable, }, - .sema => switch (union_type.setRequiresComptimeWip(ip)) { + .sema => switch (union_type.setRequiresComptimeWip(ip, io)) { .no, .wip => return false, .yes => return true, .unknown => { if (union_type.flagsUnordered(ip).status == .field_types_wip) { - union_type.setRequiresComptime(ip, .unknown); + union_type.setRequiresComptime(ip, io, .unknown); return false; } - errdefer union_type.setRequiresComptime(ip, .unknown); + errdefer union_type.setRequiresComptime(ip, io, .unknown); const pt = strat.pt(zcu, tid); try ty.resolveFields(pt); @@ -2867,12 +2873,12 @@ pub fn comptimeOnlyInner( for (0..union_type.field_types.len) |field_idx| { const field_ty = union_type.field_types.get(ip)[field_idx]; if (try Type.fromInterned(field_ty).comptimeOnlyInner(strat, zcu, tid)) { - union_type.setRequiresComptime(ip, .yes); + union_type.setRequiresComptime(ip, io, .yes); return true; } } - union_type.setRequiresComptime(ip, .no); + union_type.setRequiresComptime(ip, io, .no); return false; }, }, @@ -3445,13 +3451,22 @@ pub fn optEuBaseType(ty: Type, zcu: *const Zcu) Type { pub fn toUnsigned(ty: Type, pt: Zcu.PerThread) !Type { const zcu = pt.zcu; - return switch (ty.zigTypeTag(zcu)) { - .int => pt.intType(.unsigned, ty.intInfo(zcu).bits), - .vector => try pt.vectorType(.{ - .len = ty.vectorLen(zcu), - .child = (try ty.childType(zcu).toUnsigned(pt)).toIntern(), - }), - else => unreachable, + return switch (ty.toIntern()) { + // zig fmt: off + .usize_type, .isize_type => .usize, + .c_ushort_type, .c_short_type => .c_ushort, + .c_uint_type, .c_int_type => .c_uint, + .c_ulong_type, .c_long_type => .c_ulong, + .c_ulonglong_type, .c_longlong_type => .c_ulonglong, + // zig fmt: on + else => switch (ty.zigTypeTag(zcu)) { + .int => pt.intType(.unsigned, ty.intInfo(zcu).bits), + .vector => try pt.vectorType(.{ + .len = ty.vectorLen(zcu), + .child = (try ty.childType(zcu).toUnsigned(pt)).toIntern(), + }), + else => unreachable, + }, }; } @@ -4149,8 +4164,8 @@ fn shouldDedupeType(ty: Type, ctx: *Comparison, pt: Zcu.PerThread) error{OutOfMe const type_len: i32 = @intCast(discarding.count); - const placeholder_len: i32 = 3; - const min_saved_bytes: i32 = 10; + const placeholder_len: i32 = 1; + const min_saved_bytes: i32 = 20; const saved_bytes = (type_len - placeholder_len) * (occ - 1); const max_placeholders = 7; // T to Z @@ -4183,7 +4198,7 @@ pub const Comparison = struct { index: u8, pub fn format(p: Placeholder, writer: *std.Io.Writer) error{WriteFailed}!void { - return writer.print("<{c}>", .{p.index + 'T'}); + return writer.print("{c}", .{p.index + 'T'}); } }; diff --git a/src/Value.zig b/src/Value.zig index e2699746fa25..103140d3c9a3 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -60,18 +60,21 @@ pub fn fmtValueSemaFull(ctx: print_value.FormatContext) std.fmt.Alt(print_value. /// Asserts `val` is an array of `u8` pub fn toIpString(val: Value, ty: Type, pt: Zcu.PerThread) !InternPool.NullTerminatedString { const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const ip = &zcu.intern_pool; assert(ty.zigTypeTag(zcu) == .array); assert(ty.childType(zcu).toIntern() == .u8_type); - const ip = &zcu.intern_pool; switch (zcu.intern_pool.indexToKey(val.toIntern()).aggregate.storage) { .bytes => |bytes| return bytes.toNullTerminatedString(ty.arrayLen(zcu), ip), .elems => return arrayToIpString(val, ty.arrayLen(zcu), pt), .repeated_elem => |elem| { const byte: u8 = @intCast(Value.fromInterned(elem).toUnsignedInt(zcu)); const len: u32 = @intCast(ty.arrayLen(zcu)); - const string_bytes = ip.getLocal(pt.tid).getMutableStringBytes(zcu.gpa); + const string_bytes = ip.getLocal(pt.tid).getMutableStringBytes(gpa, io); try string_bytes.appendNTimes(.{byte}, len); - return ip.getOrPutTrailingString(zcu.gpa, pt.tid, len, .no_embedded_nulls); + return ip.getOrPutTrailingString(gpa, io, pt.tid, len, .no_embedded_nulls); }, } } @@ -109,10 +112,12 @@ fn arrayToAllocatedBytes(val: Value, len: u64, allocator: Allocator, pt: Zcu.Per fn arrayToIpString(val: Value, len_u64: u64, pt: Zcu.PerThread) !InternPool.NullTerminatedString { const zcu = pt.zcu; - const gpa = zcu.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; const len: u32 = @intCast(len_u64); - const string_bytes = ip.getLocal(pt.tid).getMutableStringBytes(gpa); + const string_bytes = ip.getLocal(pt.tid).getMutableStringBytes(gpa, io); try string_bytes.ensureUnusedCapacity(len); for (0..len) |i| { // I don't think elemValue has the possibility to affect ip.string_bytes. Let's @@ -123,7 +128,7 @@ fn arrayToIpString(val: Value, len_u64: u64, pt: Zcu.PerThread) !InternPool.Null const byte: u8 = @intCast(elem_val.toUnsignedInt(zcu)); string_bytes.appendAssumeCapacity(.{byte}); } - return ip.getOrPutTrailingString(gpa, pt.tid, len, .no_embedded_nulls); + return ip.getOrPutTrailingString(gpa, io, pt.tid, len, .no_embedded_nulls); } pub fn fromInterned(i: InternPool.Index) Value { @@ -1141,6 +1146,7 @@ pub fn sliceArray( ) error{OutOfMemory}!Value { const pt = sema.pt; const ip = &pt.zcu.intern_pool; + const io = pt.zcu.comp.io; return Value.fromInterned(try pt.intern(.{ .aggregate = .{ .ty = switch (pt.zcu.intern_pool.indexToKey(pt.zcu.intern_pool.typeOf(val.toIntern()))) { @@ -1160,6 +1166,7 @@ pub fn sliceArray( try ip.string_bytes.ensureUnusedCapacity(sema.gpa, end - start + 1); break :storage .{ .bytes = try ip.getOrPutString( sema.gpa, + io, bytes.toSlice(end, ip)[start..], .maybe_embedded_nulls, ) }; @@ -2874,6 +2881,7 @@ const interpret_mode: InterpretMode = @field(InterpretMode, @tagName(build_optio /// `val` must be fully resolved. pub fn interpret(val: Value, comptime T: type, pt: Zcu.PerThread) error{ OutOfMemory, UndefinedValue, TypeMismatch }!T { const zcu = pt.zcu; + const io = zcu.comp.io; const ip = &zcu.intern_pool; const ty = val.typeOf(zcu); if (ty.zigTypeTag(zcu) != @typeInfo(T)) return error.TypeMismatch; @@ -2960,7 +2968,7 @@ pub fn interpret(val: Value, comptime T: type, pt: Zcu.PerThread) error{ OutOfMe const struct_obj = zcu.typeToStruct(ty) orelse return error.TypeMismatch; var result: T = undefined; inline for (@"struct".fields) |field| { - const field_name_ip = try ip.getOrPutString(zcu.gpa, pt.tid, field.name, .no_embedded_nulls); + const field_name_ip = try ip.getOrPutString(zcu.gpa, io, pt.tid, field.name, .no_embedded_nulls); @field(result, field.name) = if (struct_obj.nameIndex(ip, field_name_ip)) |field_idx| f: { const field_val = try val.fieldValue(pt, field_idx); break :f try field_val.interpret(field.type, pt); @@ -2979,6 +2987,7 @@ pub fn uninterpret(val: anytype, ty: Type, pt: Zcu.PerThread) error{ OutOfMemory const T = @TypeOf(val); const zcu = pt.zcu; + const io = zcu.comp.io; const ip = &zcu.intern_pool; if (ty.zigTypeTag(zcu) != @typeInfo(T)) return error.TypeMismatch; @@ -3022,7 +3031,7 @@ pub fn uninterpret(val: anytype, ty: Type, pt: Zcu.PerThread) error{ OutOfMemory .@"enum" => switch (interpret_mode) { .direct => try pt.enumValue(ty, (try uninterpret(@intFromEnum(val), ty.intTagType(zcu), pt)).toIntern()), .by_name => { - const field_name_ip = try ip.getOrPutString(zcu.gpa, pt.tid, @tagName(val), .no_embedded_nulls); + const field_name_ip = try ip.getOrPutString(zcu.gpa, io, pt.tid, @tagName(val), .no_embedded_nulls); const field_idx = ty.enumFieldIndex(field_name_ip, zcu) orelse return error.TypeMismatch; return pt.enumValueFieldIndex(ty, field_idx); }, @@ -3059,7 +3068,7 @@ pub fn uninterpret(val: anytype, ty: Type, pt: Zcu.PerThread) error{ OutOfMemory defer zcu.gpa.free(field_vals); @memset(field_vals, .none); inline for (@"struct".fields) |field| { - const field_name_ip = try ip.getOrPutString(zcu.gpa, pt.tid, field.name, .no_embedded_nulls); + const field_name_ip = try ip.getOrPutString(zcu.gpa, io, pt.tid, field.name, .no_embedded_nulls); if (struct_obj.nameIndex(ip, field_name_ip)) |field_idx| { const field_ty = ty.fieldType(field_idx, zcu); field_vals[field_idx] = (try uninterpret(@field(val, field.name), field_ty, pt)).toIntern(); diff --git a/src/Zcu.zig b/src/Zcu.zig index 6027ab07fa75..531815fdf2f2 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -37,6 +37,7 @@ const InternPool = @import("InternPool.zig"); const Alignment = InternPool.Alignment; const AnalUnit = InternPool.AnalUnit; const BuiltinFn = std.zig.BuiltinFn; +const codegen = @import("codegen.zig"); const LlvmObject = @import("codegen/llvm.zig").Object; const dev = @import("dev.zig"); const Zoir = std.zig.Zoir; @@ -317,6 +318,8 @@ incremental_debug_state: if (build_options.enable_debug_extensions) IncrementalD /// this timer must be temporarily paused and resumed later. cur_analysis_timer: ?Compilation.Timer = null, +codegen_task_pool: CodegenTaskPool, + generation: u32 = 0, pub const IncrementalDebugState = struct { @@ -895,12 +898,13 @@ pub const Namespace = struct { ns: Namespace, ip: *InternPool, gpa: Allocator, + io: Io, tid: Zcu.PerThread.Id, name: InternPool.NullTerminatedString, ) !InternPool.NullTerminatedString { const ns_name = Type.fromInterned(ns.owner_type).containerTypeName(ip); if (name == .empty) return ns_name; - return ip.getOrPutStringFmt(gpa, tid, "{f}.{f}", .{ ns_name.fmt(ip), name.fmt(ip) }, .no_embedded_nulls); + return ip.getOrPutStringFmt(gpa, io, tid, "{f}.{f}", .{ ns_name.fmt(ip), name.fmt(ip) }, .no_embedded_nulls); } }; @@ -1072,11 +1076,11 @@ pub const File = struct { var f = f: { const dir, const sub_path = file.path.openInfo(zcu.comp.dirs); - break :f try dir.openFile(sub_path, .{}); + break :f try dir.openFile(io, sub_path, .{}); }; - defer f.close(); + defer f.close(io); - const stat = f.stat() catch |err| switch (err) { + const stat = f.stat(io) catch |err| switch (err) { error.Streaming => { // Since `file.stat` is populated, this was previously a file stream; since it is // now not a file stream, it must have changed. @@ -1139,13 +1143,15 @@ pub const File = struct { } pub fn internFullyQualifiedName(file: File, pt: Zcu.PerThread) !InternPool.NullTerminatedString { - const gpa = pt.zcu.gpa; const ip = &pt.zcu.intern_pool; - const string_bytes = ip.getLocal(pt.tid).getMutableStringBytes(gpa); + const comp = pt.zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const string_bytes = ip.getLocal(pt.tid).getMutableStringBytes(gpa, io); var w: Writer = .fixed((try string_bytes.addManyAsSlice(file.fullyQualifiedNameLen()))[0]); file.renderFullyQualifiedName(&w) catch unreachable; assert(w.end == w.buffer.len); - return ip.getOrPutTrailingString(gpa, pt.tid, @intCast(w.end), .no_embedded_nulls); + return ip.getOrPutTrailingString(gpa, io, pt.tid, @intCast(w.end), .no_embedded_nulls); } pub const Index = InternPool.FileIndex; @@ -1194,7 +1200,7 @@ pub const EmbedFile = struct { /// `.none` means the file was not loaded, so `stat` is undefined. val: InternPool.Index, /// If this is `null` and `val` is `.none`, the file has never been loaded. - err: ?(std.fs.File.OpenError || std.fs.File.StatError || std.fs.File.ReadError || error{UnexpectedEof}), + err: ?(Io.File.OpenError || Io.File.StatError || Io.File.Reader.Error || error{UnexpectedEof}), stat: Cache.File.Stat, pub const Index = enum(u32) { @@ -1542,6 +1548,25 @@ pub const SrcLoc = struct { }; return tree.nodeToSpan(src_node); }, + .asm_input => |input| { + const tree = try src_loc.file_scope.getTree(zcu); + const node = input.offset.toAbsolute(src_loc.base_node); + const full = tree.fullAsm(node).?; + const asm_input = full.inputs[input.input_index]; + return tree.nodeToSpan(tree.nodeData(asm_input).node_and_token[0]); + }, + .asm_output => |output| { + const tree = try src_loc.file_scope.getTree(zcu); + const node = output.offset.toAbsolute(src_loc.base_node); + const full = tree.fullAsm(node).?; + const asm_output = full.outputs[output.output_index]; + const data = tree.nodeData(asm_output).opt_node_and_token; + return if (data[0].unwrap()) |output_node| + tree.nodeToSpan(output_node) + else + // token points to the ')' + tree.tokenToSpan(data[1] - 1); + }, .for_input => |for_input| { const tree = try src_loc.file_scope.getTree(zcu); const node = for_input.for_node_offset.toAbsolute(src_loc.base_node); @@ -2088,6 +2113,7 @@ pub const SrcLoc = struct { .init_field_thread_local, .init_field_dll_import, .init_field_relocation, + .init_field_decoration, => |builtin_call_node| { const wanted = switch (src_loc.lazy) { .init_field_name => "name", @@ -2101,6 +2127,7 @@ pub const SrcLoc = struct { .init_field_thread_local => "thread_local", .init_field_dll_import => "dll_import", .init_field_relocation => "relocation", + .init_field_decoration => "decoration", else => unreachable, }; const tree = try src_loc.file_scope.getTree(zcu); @@ -2507,6 +2534,18 @@ pub const LazySrcLoc = struct { /// The source location points to the operand of a `return` statement, or /// the `return` itself if there is no explicit operand. node_offset_return_operand: Ast.Node.Offset, + /// The source location points to an assembly input + asm_input: struct { + /// Points to the assembly node + offset: Ast.Node.Offset, + input_index: u32, + }, + /// The source location points to an assembly output + asm_output: struct { + /// Points to the assembly node + offset: Ast.Node.Offset, + output_index: u32, + }, /// The source location points to a for loop input. for_input: struct { /// Points to the for loop AST node. @@ -2569,6 +2608,7 @@ pub const LazySrcLoc = struct { init_field_thread_local: Ast.Node.Offset, init_field_dll_import: Ast.Node.Offset, init_field_relocation: Ast.Node.Offset, + init_field_decoration: Ast.Node.Offset, /// The source location points to the value of an item in a specific /// case of a `switch`. switch_case_item: SwitchItem, @@ -2770,12 +2810,13 @@ pub const CompileError = error{ ComptimeBreak, }; -pub fn init(zcu: *Zcu, thread_count: usize) !void { - const gpa = zcu.gpa; - try zcu.intern_pool.init(gpa, thread_count); +pub fn init(zcu: *Zcu, gpa: Allocator, io: Io, thread_count: usize) !void { + try zcu.intern_pool.init(gpa, io, thread_count); } pub fn deinit(zcu: *Zcu) void { + const comp = zcu.comp; + const io = comp.io; const gpa = zcu.gpa; { const pt: Zcu.PerThread = .activate(zcu, .main); @@ -2797,8 +2838,8 @@ pub fn deinit(zcu: *Zcu) void { } zcu.embed_table.deinit(gpa); - zcu.local_zir_cache.handle.close(); - zcu.global_zir_cache.handle.close(); + zcu.local_zir_cache.handle.close(io); + zcu.global_zir_cache.handle.close(io); for (zcu.failed_analysis.values()) |value| value.destroy(gpa); for (zcu.failed_codegen.values()) |value| value.destroy(gpa); @@ -2862,11 +2903,11 @@ pub fn deinit(zcu: *Zcu) void { if (zcu.resolved_references) |*r| r.deinit(gpa); - if (zcu.comp.debugIncremental()) { + if (comp.debugIncremental()) { zcu.incremental_debug_state.deinit(gpa); } } - zcu.intern_pool.deinit(gpa); + zcu.intern_pool.deinit(gpa, io); } pub fn namespacePtr(zcu: *Zcu, index: Namespace.Index) *Namespace { @@ -2889,7 +2930,7 @@ comptime { } } -pub fn loadZirCache(gpa: Allocator, io: Io, cache_file: std.fs.File) !Zir { +pub fn loadZirCache(gpa: Allocator, io: Io, cache_file: Io.File) !Zir { var buffer: [2000]u8 = undefined; var file_reader = cache_file.reader(io, &buffer); return result: { @@ -2948,7 +2989,12 @@ pub fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_br: *Io.Reader return zir; } -pub fn saveZirCache(gpa: Allocator, cache_file: std.fs.File, stat: std.fs.File.Stat, zir: Zir) (std.fs.File.WriteError || Allocator.Error)!void { +pub fn saveZirCache( + gpa: Allocator, + cache_file_writer: *Io.File.Writer, + stat: Io.File.Stat, + zir: Zir, +) (Io.File.Writer.Error || Allocator.Error)!void { const safety_buffer = if (data_has_safety_tag) try gpa.alloc([8]u8, zir.instructions.len) else @@ -2982,13 +3028,12 @@ pub fn saveZirCache(gpa: Allocator, cache_file: std.fs.File, stat: std.fs.File.S zir.string_bytes, @ptrCast(zir.extra), }; - var cache_fw = cache_file.writer(&.{}); - cache_fw.interface.writeVecAll(&vecs) catch |err| switch (err) { - error.WriteFailed => return cache_fw.err.?, + cache_file_writer.interface.writeVecAll(&vecs) catch |err| switch (err) { + error.WriteFailed => return cache_file_writer.err.?, }; } -pub fn saveZoirCache(cache_file: std.fs.File, stat: std.fs.File.Stat, zoir: Zoir) std.fs.File.WriteError!void { +pub fn saveZoirCache(cache_file_writer: *Io.File.Writer, stat: Io.File.Stat, zoir: Zoir) Io.File.Writer.Error!void { const header: Zoir.Header = .{ .nodes_len = @intCast(zoir.nodes.len), .extra_len = @intCast(zoir.extra.len), @@ -3012,9 +3057,8 @@ pub fn saveZoirCache(cache_file: std.fs.File, stat: std.fs.File.Stat, zoir: Zoir @ptrCast(zoir.compile_errors), @ptrCast(zoir.error_notes), }; - var cache_fw = cache_file.writer(&.{}); - cache_fw.interface.writeVecAll(&vecs) catch |err| switch (err) { - error.WriteFailed => return cache_fw.err.?, + cache_file_writer.interface.writeVecAll(&vecs) catch |err| switch (err) { + error.WriteFailed => return cache_file_writer.err.?, }; } @@ -4411,7 +4455,7 @@ pub fn maybeUnresolveIes(zcu: *Zcu, func_index: InternPool.Index) !void { try zcu.outdated_ready.put(gpa, unit, {}); } } - zcu.intern_pool.funcSetIesResolved(func_index, .none); + zcu.intern_pool.funcSetIesResolved(zcu.comp.io, func_index, .none); } } @@ -4589,10 +4633,12 @@ pub fn codegenFail( /// Takes ownership of `msg`, even on OOM. pub fn codegenFailMsg(zcu: *Zcu, nav_index: InternPool.Nav.Index, msg: *ErrorMsg) CodegenFailError { - const gpa = zcu.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; { - zcu.comp.mutex.lock(); - defer zcu.comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); errdefer msg.deinit(gpa); try zcu.failed_codegen.putNoClobber(gpa, nav_index, msg); } @@ -4601,8 +4647,10 @@ pub fn codegenFailMsg(zcu: *Zcu, nav_index: InternPool.Nav.Index, msg: *ErrorMsg /// Asserts that `zcu.failed_codegen` contains the key `nav`, with the necessary lock held. pub fn assertCodegenFailed(zcu: *Zcu, nav: InternPool.Nav.Index) void { - zcu.comp.mutex.lock(); - defer zcu.comp.mutex.unlock(); + const comp = zcu.comp; + const io = comp.io; + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); assert(zcu.failed_codegen.contains(nav)); } @@ -4763,8 +4811,9 @@ const TrackedUnitSema = struct { report_time: { const sema_ns = zcu.cur_analysis_timer.?.finish() orelse break :report_time; const zir_decl = tus.analysis_timer_decl orelse break :report_time; - comp.mutex.lock(); - defer comp.mutex.unlock(); + const io = comp.io; + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); comp.time_report.?.stats.cpu_ns_sema += sema_ns; const gop = comp.time_report.?.decl_sema_info.getOrPut(comp.gpa, zir_decl) catch |err| switch (err) { error.OutOfMemory => { @@ -4799,3 +4848,170 @@ pub fn trackUnitSema(zcu: *Zcu, name: []const u8, zir_inst: ?InternPool.TrackedI .analysis_timer_decl = zir_inst, }; } + +pub const CodegenTaskPool = struct { + const CodegenResult = PerThread.RunCodegenError!codegen.AnyMir; + + /// In the worst observed case, MIR is around 50 times as large as AIR. More typically, the ratio is + /// around 20. Going by that 50x multiplier, and assuming we want to consume no more than 500 MiB of + /// memory on AIR/MIR, we see a limit of around 10 MiB of AIR in-flight. + const max_air_bytes_in_flight = 10 * 1024 * 1024; + + const max_funcs_in_flight = @import("link.zig").Queue.buffer_size; + + available_air_bytes: u32, + + /// Locks the freelist and `available_air_bytes`. + mutex: Io.Mutex, + + /// Signaled when an item is added to the freelist. + free_cond: Io.Condition, + /// Pre-allocated with enough capacity for all indices. + free: std.ArrayList(Index), + + /// `.none` means this task is in the freelist. The `task_air_bytes` and + /// `task_futures` entries are `undefined`. + task_funcs: []InternPool.Index, + task_air_bytes: []u32, + task_futures: []Io.Future(CodegenResult), + + pub fn init(arena: Allocator) Allocator.Error!CodegenTaskPool { + const task_funcs = try arena.alloc(InternPool.Index, max_funcs_in_flight); + const task_air_bytes = try arena.alloc(u32, max_funcs_in_flight); + const task_futures = try arena.alloc(Io.Future(CodegenResult), max_funcs_in_flight); + @memset(task_funcs, .none); + + var free: std.ArrayList(Index) = try .initCapacity(arena, max_funcs_in_flight); + for (0..max_funcs_in_flight) |index| free.appendAssumeCapacity(@enumFromInt(index)); + + return .{ + .available_air_bytes = max_air_bytes_in_flight, + .mutex = .init, + .free_cond = .init, + .free = free, + .task_funcs = task_funcs, + .task_air_bytes = task_air_bytes, + .task_futures = task_futures, + }; + } + + pub fn cancel(pool: *CodegenTaskPool, zcu: *const Zcu) void { + const io = zcu.comp.io; + for ( + pool.task_funcs, + pool.task_air_bytes, + pool.task_futures, + ) |func, effective_air_bytes, *future| { + if (func == .none) continue; + pool.available_air_bytes += effective_air_bytes; + var mir = future.cancel(io) catch continue; + mir.deinit(zcu); + } + assert(pool.available_air_bytes == max_air_bytes_in_flight); + } + + pub fn start( + pool: *CodegenTaskPool, + zcu: *Zcu, + func_index: InternPool.Index, + air: *Air, + /// If `true`, this function will take ownership of `air`, freeing it after codegen + /// completes; it is not assumed that `air` will outlive this function. If `false`, + /// codegen will operate on `air` via the given pointer, which it is assumed will + /// outline the codegen task. + move_air: bool, + ) Io.Cancelable!Index { + const io = zcu.comp.io; + + // To avoid consuming an excessive amount of memory, there is a limit on the total number of AIR + // bytes which can be in the codegen/link pipeline at one time. If we exceed this limit, we must + // wait for codegen/link to finish some WIP functions so they catch up with us. + const actual_air_bytes: u32 = @intCast(air.instructions.len * 5 + air.extra.items.len * 4); + // We need to let all AIR through eventually, even if one function exceeds `max_air_bytes_in_flight`. + const effective_air_bytes: u32 = @min(actual_air_bytes, max_air_bytes_in_flight); + assert(effective_air_bytes > 0); + + const index: Index = index: { + try pool.mutex.lock(io); + defer pool.mutex.unlock(io); + + while (pool.free.items.len == 0 or pool.available_air_bytes < effective_air_bytes) { + // The linker thread needs to catch up! + try pool.free_cond.wait(io, &pool.mutex); + } + + pool.available_air_bytes -= effective_air_bytes; + break :index pool.free.pop().?; + }; + + // No turning back now: we're incrementing `pending_codegen_jobs` and starting the worker. + errdefer comptime unreachable; + + assert(zcu.pending_codegen_jobs.fetchAdd(1, .monotonic) > 0); // the "Code Generation" node is still active + assert(pool.task_funcs[@intFromEnum(index)] == .none); + pool.task_funcs[@intFromEnum(index)] = func_index; + pool.task_air_bytes[@intFromEnum(index)] = actual_air_bytes; + pool.task_futures[@intFromEnum(index)] = if (move_air) io.async( + workerCodegenOwnedAir, + .{ zcu, func_index, air.* }, + ) else io.async( + workerCodegenExternalAir, + .{ zcu, func_index, air }, + ); + + return index; + } + pub const Index = enum(u32) { + _, + + /// Blocks until codegen has completed, successfully or otherwise. + /// The returned MIR is owned by the caller. + pub fn wait( + index: Index, + pool: *CodegenTaskPool, + io: Io, + ) PerThread.RunCodegenError!struct { InternPool.Index, codegen.AnyMir } { + const func = pool.task_funcs[@intFromEnum(index)]; + assert(func != .none); + const effective_air_bytes = pool.task_air_bytes[@intFromEnum(index)]; + const result = pool.task_futures[@intFromEnum(index)].await(io); + + pool.task_funcs[@intFromEnum(index)] = .none; + pool.task_air_bytes[@intFromEnum(index)] = undefined; + pool.task_futures[@intFromEnum(index)] = undefined; + + { + pool.mutex.lockUncancelable(io); + defer pool.mutex.unlock(io); + pool.available_air_bytes += effective_air_bytes; + pool.free.appendAssumeCapacity(index); + pool.free_cond.signal(io); + } + + return .{ func, try result }; + } + }; + fn workerCodegenOwnedAir( + zcu: *Zcu, + func_index: InternPool.Index, + orig_air: Air, + ) CodegenResult { + // We own `air` now, so we are responsbile for freeing it. + var air = orig_air; + defer air.deinit(zcu.comp.gpa); + const tid = Compilation.getTid(); + const pt: Zcu.PerThread = .activate(zcu, @enumFromInt(tid)); + defer pt.deactivate(); + return pt.runCodegen(func_index, &air); + } + fn workerCodegenExternalAir( + zcu: *Zcu, + func_index: InternPool.Index, + air: *Air, + ) CodegenResult { + const tid = Compilation.getTid(); + const pt: Zcu.PerThread = .activate(zcu, @enumFromInt(tid)); + defer pt.deactivate(); + return pt.runCodegen(func_index, air); + } +}; diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 702e30dab013..d79b66b7c2a6 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -94,11 +94,11 @@ pub fn updateFile( // In any case we need to examine the stat of the file to determine the course of action. var source_file = f: { const dir, const sub_path = file.path.openInfo(comp.dirs); - break :f try dir.openFile(sub_path, .{}); + break :f try dir.openFile(io, sub_path, .{}); }; - defer source_file.close(); + defer source_file.close(io); - const stat = try source_file.stat(); + const stat = try source_file.stat(io); const want_local_cache = switch (file.path.root) { .none, .local_cache => true, @@ -118,7 +118,7 @@ pub fn updateFile( const zir_dir = cache_directory.handle; // Determine whether we need to reload the file from disk and redo parsing and AstGen. - var lock: std.fs.File.Lock = switch (file.status) { + var lock: Io.File.Lock = switch (file.status) { .never_loaded, .retryable_failure => lock: { // First, load the cached ZIR code, if any. log.debug("AstGen checking cache: {f} (local={}, digest={s})", .{ @@ -170,7 +170,7 @@ pub fn updateFile( // version. Likewise if we're working on AstGen and another process asks for // the cached file, they'll get it. const cache_file = while (true) { - break zir_dir.createFile(&hex_digest, .{ + break zir_dir.createFile(io, &hex_digest, .{ .read = true, .truncate = false, .lock = lock, @@ -196,7 +196,7 @@ pub fn updateFile( cache_directory, }); } - break zir_dir.createFile(&hex_digest, .{ + break zir_dir.createFile(io, &hex_digest, .{ .read = true, .truncate = false, .lock = lock, @@ -215,7 +215,7 @@ pub fn updateFile( else => |e| return e, // Retryable errors are handled at callsite. }; }; - defer cache_file.close(); + defer cache_file.close(io); // Under `--time-report`, ignore cache hits; do the work anyway for those juicy numbers. const ignore_hit = comp.time_report != null; @@ -238,18 +238,13 @@ pub fn updateFile( if (builtin.os.tag == .wasi or lock == .exclusive) break true; // Otherwise, unlock to give someone a chance to get the exclusive lock // and then upgrade to an exclusive lock. - cache_file.unlock(); + cache_file.unlock(io); lock = .exclusive; - try cache_file.lock(lock); + try cache_file.lock(io, lock); }; if (need_update) { - // The cache is definitely stale so delete the contents to avoid an underwrite later. - cache_file.setEndPos(0) catch |err| switch (err) { - error.FileTooBig => unreachable, // 0 is not too big - else => |e| return e, - }; - try cache_file.seekTo(0); + var cache_file_writer: Io.File.Writer = .init(cache_file, io, &.{}); if (stat.size > std.math.maxInt(u32)) return error.FileTooBig; @@ -269,8 +264,8 @@ pub fn updateFile( // Any potential AST errors are converted to ZIR errors when we run AstGen/ZonGen. file.tree = try Ast.parse(gpa, source, file.getMode()); if (timer.finish()) |ns_parse| { - comp.mutex.lock(); - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); comp.time_report.?.stats.cpu_ns_parse += ns_parse; } @@ -278,25 +273,31 @@ pub fn updateFile( switch (file.getMode()) { .zig => { file.zir = try AstGen.generate(gpa, file.tree.?); - Zcu.saveZirCache(gpa, cache_file, stat, file.zir.?) catch |err| switch (err) { + Zcu.saveZirCache(gpa, &cache_file_writer, stat, file.zir.?) catch |err| switch (err) { error.OutOfMemory => |e| return e, - else => log.warn("unable to write cached ZIR code for {f} to {f}{s}: {s}", .{ - file.path.fmt(comp), cache_directory, &hex_digest, @errorName(err), + else => log.warn("unable to write cached ZIR code for {f} to {f}{s}: {t}", .{ + file.path.fmt(comp), cache_directory, &hex_digest, err, }), }; }, .zon => { file.zoir = try ZonGen.generate(gpa, file.tree.?, .{}); - Zcu.saveZoirCache(cache_file, stat, file.zoir.?) catch |err| { - log.warn("unable to write cached ZOIR code for {f} to {f}{s}: {s}", .{ - file.path.fmt(comp), cache_directory, &hex_digest, @errorName(err), + Zcu.saveZoirCache(&cache_file_writer, stat, file.zoir.?) catch |err| { + log.warn("unable to write cached ZOIR code for {f} to {f}{s}: {t}", .{ + file.path.fmt(comp), cache_directory, &hex_digest, err, }); }; }, } + + cache_file_writer.end() catch |err| switch (err) { + error.WriteFailed => return cache_file_writer.err.?, + else => |e| return e, + }; + if (timer.finish()) |ns_astgen| { - comp.mutex.lock(); - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); comp.time_report.?.stats.cpu_ns_astgen += ns_astgen; } @@ -315,8 +316,8 @@ pub fn updateFile( switch (file.getMode()) { .zig => { if (file.zir.?.hasCompileErrors()) { - comp.mutex.lock(); - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); try zcu.failed_files.putNoClobber(gpa, file_index, null); } if (file.zir.?.loweringFailed()) { @@ -328,8 +329,8 @@ pub fn updateFile( .zon => { if (file.zoir.?.hasCompileErrors()) { file.status = .astgen_failure; - comp.mutex.lock(); - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); try zcu.failed_files.putNoClobber(gpa, file_index, null); } else { file.status = .success; @@ -346,8 +347,8 @@ pub fn updateFile( fn loadZirZoirCache( zcu: *Zcu, - cache_file: std.fs.File, - stat: std.fs.File.Stat, + cache_file: Io.File, + stat: Io.File.Stat, file: *Zcu.File, comptime mode: Ast.Mode, ) !enum { success, invalid, truncated, stale } { @@ -415,7 +416,8 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { const zcu = pt.zcu; const comp = zcu.comp; const ip = &zcu.intern_pool; - const gpa = zcu.gpa; + const gpa = comp.gpa; + const io = comp.io; // We need to visit every updated File for every TrackedInst in InternPool. // This only includes Zig files; ZON files are omitted. @@ -459,7 +461,7 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { return; for (ip.locals, 0..) |*local, tid| { - const tracked_insts_list = local.getMutableTrackedInsts(gpa); + const tracked_insts_list = local.getMutableTrackedInsts(gpa, io); for (tracked_insts_list.viewAllowEmpty().items(.@"0"), 0..) |*tracked_inst, tracked_inst_unwrapped_index| { const file_index = tracked_inst.file; const updated_file = updated_files.get(file_index) orelse continue; @@ -530,6 +532,7 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { if (old_decl.name == .empty) continue; const name_ip = try zcu.intern_pool.getOrPutString( zcu.gpa, + io, pt.tid, old_zir.nullTerminatedString(old_decl.name), .no_embedded_nulls, @@ -545,6 +548,7 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { if (new_decl.name == .empty) continue; const name_ip = try zcu.intern_pool.getOrPutString( zcu.gpa, + io, pt.tid, new_zir.nullTerminatedString(new_decl.name), .no_embedded_nulls, @@ -575,7 +579,7 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { } } - try ip.rehashTrackedInsts(gpa, pt.tid); + try ip.rehashTrackedInsts(gpa, io, pt.tid); for (updated_files.keys(), updated_files.values()) |file_index, updated_file| { const file = updated_file.file; @@ -700,7 +704,9 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized fn analyzeMemoizedState(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage) Zcu.CompileError!bool { const zcu = pt.zcu; const ip = &zcu.intern_pool; - const gpa = zcu.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const unit: AnalUnit = .wrap(.{ .memoized_state = stage }); @@ -716,7 +722,7 @@ fn analyzeMemoizedState(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage) const std_type: Type = .fromInterned(zcu.fileRootType(std_file_index)); const std_namespace = std_type.getNamespaceIndex(zcu); try pt.ensureNamespaceUpToDate(std_namespace); - const builtin_str = try ip.getOrPutString(gpa, pt.tid, "builtin", .no_embedded_nulls); + const builtin_str = try ip.getOrPutString(gpa, io, pt.tid, "builtin", .no_embedded_nulls); const builtin_nav = zcu.namespacePtr(std_namespace).pub_decls.getKeyAdapted(builtin_str, Zcu.Namespace.NameAdapter{ .zcu = zcu }) orelse @panic("lib/std.zig is corrupt and missing 'builtin'"); try pt.ensureNavValUpToDate(builtin_nav); @@ -857,8 +863,10 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU /// to `transitive_failed_analysis` if necessary. fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu.CompileError!void { const zcu = pt.zcu; - const gpa = zcu.gpa; const ip = &zcu.intern_pool; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const anal_unit: AnalUnit = .wrap(.{ .@"comptime" = cu_id }); const comptime_unit = ip.getComptimeUnit(cu_id); @@ -909,7 +917,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu .r = .{ .simple = .comptime_keyword }, } }, .src_base_inst = comptime_unit.zir_index, - .type_name_ctx = try ip.getOrPutStringFmt(gpa, pt.tid, "{f}.comptime", .{ + .type_name_ctx = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}.comptime", .{ Type.fromInterned(zcu.namespacePtr(comptime_unit.namespace).owner_type).containerTypeName(ip).fmt(ip), }, .no_embedded_nulls), }; @@ -1087,8 +1095,10 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileError!struct { val_changed: bool } { const zcu = pt.zcu; - const gpa = zcu.gpa; const ip = &zcu.intern_pool; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const anal_unit: AnalUnit = .wrap(.{ .nav_val = nav_id }); const old_nav = ip.getNav(nav_id); @@ -1253,12 +1263,13 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr break :val .fromInterned(try pt.getExtern(.{ .name = old_nav.name, .ty = nav_ty.toIntern(), - .lib_name = try ip.getOrPutStringOpt(gpa, pt.tid, lib_name, .no_embedded_nulls), + .lib_name = try ip.getOrPutStringOpt(gpa, io, pt.tid, lib_name, .no_embedded_nulls), .is_threadlocal = zir_decl.is_threadlocal, .linkage = .strong, .visibility = .default, .is_dll_import = false, .relocation = .any, + .decoration = null, .is_const = is_const, .alignment = modifiers.alignment, .@"addrspace" = modifiers.@"addrspace", @@ -1310,7 +1321,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr } } - ip.resolveNavValue(nav_id, .{ + ip.resolveNavValue(io, nav_id, .{ .val = nav_val.toIntern(), .is_const = is_const, .alignment = modifiers.alignment, @@ -1327,7 +1338,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr if (zir_decl.linkage == .@"export") { const export_src = block.src(.{ .token_offset = @enumFromInt(@intFromBool(zir_decl.is_pub)) }); const name_slice = zir.nullTerminatedString(zir_decl.name); - const name_ip = try ip.getOrPutString(gpa, pt.tid, name_slice, .no_embedded_nulls); + const name_ip = try ip.getOrPutString(gpa, io, pt.tid, name_slice, .no_embedded_nulls); try sema.analyzeExport(&block, export_src, .{ .name = name_ip }, nav_id); } @@ -1472,7 +1483,9 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileError!struct { type_changed: bool } { const zcu = pt.zcu; - const gpa = zcu.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; const anal_unit: AnalUnit = .wrap(.{ .nav_ty = nav_id }); @@ -1579,7 +1592,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr if (!changed) return .{ .type_changed = false }; - ip.resolveNavType(nav_id, .{ + ip.resolveNavType(io, nav_id, .{ .type = resolved_ty.toIntern(), .is_const = is_const, .alignment = modifiers.alignment, @@ -1775,6 +1788,7 @@ fn createFileRootStruct( ) Allocator.Error!InternPool.Index { const zcu = pt.zcu; const gpa = zcu.gpa; + const io = zcu.comp.io; const ip = &zcu.intern_pool; const file = zcu.fileByIndex(file_index); const extended = file.zir.?.instructions.items(.data)[@intFromEnum(Zir.Inst.Index.main_struct_inst)].extended; @@ -1797,11 +1811,11 @@ fn createFileRootStruct( const decls = file.zir.?.bodySlice(extra_index, decls_len); extra_index += decls_len; - const tracked_inst = try ip.trackZir(gpa, pt.tid, .{ + const tracked_inst = try ip.trackZir(gpa, io, pt.tid, .{ .file = file_index, .inst = .main_struct_inst, }); - const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{ + const wip_ty = switch (try ip.getStructType(gpa, io, pt.tid, .{ .layout = .auto, .fields_len = fields_len, .known_non_opv = small.known_non_opv, @@ -1916,7 +1930,9 @@ pub fn discoverImport( }, } { const zcu = pt.zcu; - const gpa = zcu.gpa; + const comp = zcu.comp; + const io = comp.io; + const gpa = comp.gpa; if (!mem.endsWith(u8, import_string, ".zig") and !mem.endsWith(u8, import_string, ".zon")) { return .module; @@ -1926,8 +1942,8 @@ pub fn discoverImport( errdefer new_path.deinit(gpa); // We're about to do a GOP on `import_table`, so we need the mutex. - zcu.comp.mutex.lock(); - defer zcu.comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); const gop = try zcu.import_table.getOrPutAdapted(gpa, new_path, Zcu.ImportTableAdapter{ .zcu = zcu }); errdefer _ = zcu.import_table.pop(); @@ -1942,7 +1958,7 @@ pub fn discoverImport( const new_file = try gpa.create(Zcu.File); errdefer gpa.destroy(new_file); - const new_file_index = try zcu.intern_pool.createFile(gpa, pt.tid, .{ + const new_file_index = try zcu.intern_pool.createFile(gpa, io, pt.tid, .{ .bin_digest = new_path.digest(), .file = new_file, .root_type = .none, @@ -2027,7 +2043,9 @@ pub fn populateModuleRootTable(pt: Zcu.PerThread) error{ IllegalZigImport, }!void { const zcu = pt.zcu; - const gpa = zcu.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; // We'll initially add [mod, undefined] pairs, and when we reach the pair while // iterating, rewrite the undefined value. @@ -2085,7 +2103,7 @@ pub fn populateModuleRootTable(pt: Zcu.PerThread) error{ const new_file = try gpa.create(Zcu.File); errdefer gpa.destroy(new_file); - const new_file_index = try zcu.intern_pool.createFile(gpa, pt.tid, .{ + const new_file_index = try zcu.intern_pool.createFile(gpa, io, pt.tid, .{ .bin_digest = path.digest(), .file = new_file, .root_type = .none, @@ -2291,7 +2309,8 @@ pub fn computeAliveFiles(pt: Zcu.PerThread) Allocator.Error!bool { pub fn updateBuiltinModule(pt: Zcu.PerThread, opts: Builtin) Allocator.Error!void { const zcu = pt.zcu; const comp = zcu.comp; - const gpa = zcu.gpa; + const gpa = comp.gpa; + const io = comp.io; const gop = try zcu.builtin_modules.getOrPut(gpa, opts.hash()); if (gop.found_existing) return; // the `File` is up-to-date @@ -2330,7 +2349,7 @@ pub fn updateBuiltinModule(pt: Zcu.PerThread, opts: Builtin) Allocator.Error!voi .zoir_invalidated = false, }; - const file_index = try zcu.intern_pool.createFile(gpa, pt.tid, .{ + const file_index = try zcu.intern_pool.createFile(gpa, io, pt.tid, .{ .bin_digest = path.digest(), .file = file, .root_type = .none, @@ -2449,11 +2468,11 @@ fn updateEmbedFileInner( var file = f: { const dir, const sub_path = ef.path.openInfo(zcu.comp.dirs); - break :f try dir.openFile(sub_path, .{}); + break :f try dir.openFile(io, sub_path, .{}); }; - defer file.close(); + defer file.close(io); - const stat: Cache.File.Stat = .fromFs(try file.stat()); + const stat: Cache.File.Stat = .fromFs(try file.stat(io)); if (ef.val != .none) { const old_stat = ef.stat; @@ -2469,7 +2488,7 @@ fn updateEmbedFileInner( // The loaded bytes of the file, including a sentinel 0 byte. const ip_str: InternPool.String = str: { - const string_bytes = ip.getLocal(tid).getMutableStringBytes(gpa); + const string_bytes = ip.getLocal(tid).getMutableStringBytes(gpa, io); const old_len = string_bytes.mutate.len; errdefer string_bytes.shrinkRetainingCapacity(old_len); const bytes = (try string_bytes.addManyAsSlice(size_plus_one))[0]; @@ -2480,7 +2499,7 @@ fn updateEmbedFileInner( error.EndOfStream => return error.UnexpectedEof, }; bytes[size] = 0; - break :str try ip.getOrPutTrailingString(gpa, tid, @intCast(bytes.len), .maybe_embedded_nulls); + break :str try ip.getOrPutTrailingString(gpa, io, tid, @intCast(bytes.len), .maybe_embedded_nulls); }; if (ip_str_out) |p| p.* = ip_str; @@ -2516,7 +2535,8 @@ fn newEmbedFile( ) !*Zcu.EmbedFile { const zcu = pt.zcu; const comp = zcu.comp; - const gpa = zcu.gpa; + const io = comp.io; + const gpa = comp.gpa; const ip = &zcu.intern_pool; const new_file = try gpa.create(Zcu.EmbedFile); @@ -2549,13 +2569,10 @@ fn newEmbedFile( const path_str = try path.toAbsolute(comp.dirs, gpa); defer gpa.free(path_str); - whole.cache_manifest_mutex.lock(); - defer whole.cache_manifest_mutex.unlock(); + try whole.cache_manifest_mutex.lock(io); + defer whole.cache_manifest_mutex.unlock(io); - man.addFilePostContents(path_str, contents, new_file.stat) catch |err| switch (err) { - error.Unexpected => unreachable, - else => |e| return e, - }; + try man.addFilePostContents(path_str, contents, new_file.stat); } return new_file; @@ -2647,13 +2664,15 @@ const ScanDeclIter = struct { fn avoidNameConflict(iter: *ScanDeclIter, comptime fmt: []const u8, args: anytype) !InternPool.NullTerminatedString { const pt = iter.pt; - const gpa = pt.zcu.gpa; const ip = &pt.zcu.intern_pool; - var name = try ip.getOrPutStringFmt(gpa, pt.tid, fmt, args, .no_embedded_nulls); + const comp = pt.zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + var name = try ip.getOrPutStringFmt(gpa, io, pt.tid, fmt, args, .no_embedded_nulls); var gop = try iter.seen_decls.getOrPut(gpa, name); var next_suffix: u32 = 0; while (gop.found_existing) { - name = try ip.getOrPutStringFmt(gpa, pt.tid, "{f}_{d}", .{ name.fmt(ip), next_suffix }, .no_embedded_nulls); + name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}_{d}", .{ name.fmt(ip), next_suffix }, .no_embedded_nulls); gop = try iter.seen_decls.getOrPut(gpa, name); next_suffix += 1; } @@ -2669,7 +2688,8 @@ const ScanDeclIter = struct { const comp = zcu.comp; const namespace_index = iter.namespace_index; const namespace = zcu.namespacePtr(namespace_index); - const gpa = zcu.gpa; + const gpa = comp.gpa; + const io = comp.io; const file = namespace.fileScope(zcu); const zir = file.zir.?; const ip = &zcu.intern_pool; @@ -2697,6 +2717,7 @@ const ScanDeclIter = struct { if (iter.pass != .named) return; const name = try ip.getOrPutString( gpa, + io, pt.tid, zir.nullTerminatedString(decl.name), .no_embedded_nulls, @@ -2706,7 +2727,7 @@ const ScanDeclIter = struct { }, }; - const tracked_inst = try ip.trackZir(gpa, pt.tid, .{ + const tracked_inst = try ip.trackZir(gpa, io, pt.tid, .{ .file = namespace.file_scope, .inst = decl_inst, }); @@ -2718,7 +2739,7 @@ const ScanDeclIter = struct { const cu = if (existing_unit) |eu| eu.unwrap().@"comptime" else - try ip.createComptimeUnit(gpa, pt.tid, tracked_inst, namespace_index); + try ip.createComptimeUnit(gpa, io, pt.tid, tracked_inst, namespace_index); const unit: AnalUnit = .wrap(.{ .@"comptime" = cu }); @@ -2737,9 +2758,9 @@ const ScanDeclIter = struct { }, else => unit: { const name = maybe_name.unwrap().?; - const fqn = try namespace.internFullyQualifiedName(ip, gpa, pt.tid, name); + const fqn = try namespace.internFullyQualifiedName(ip, gpa, io, pt.tid, name); const nav = if (existing_unit) |eu| eu.unwrap().nav_val else nav: { - const nav = try ip.createDeclNav(gpa, pt.tid, name, fqn, tracked_inst, namespace_index); + const nav = try ip.createDeclNav(gpa, io, pt.tid, name, fqn, tracked_inst, namespace_index); if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newNav(zcu, nav); break :nav nav; }; @@ -2798,7 +2819,9 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE defer tracy.end(); const zcu = pt.zcu; - const gpa = zcu.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; const anal_unit = AnalUnit.wrap(.{ .func = func_index }); @@ -2810,9 +2833,9 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, {}); errdefer _ = zcu.analysis_in_progress.swapRemove(anal_unit); - func.setAnalyzed(ip); + func.setAnalyzed(ip, io); if (func.analysisUnordered(ip).inferred_error_set) { - func.setResolvedErrorSet(ip, .none); + func.setResolvedErrorSet(ip, io, .none); } if (zcu.comp.time_report) |*tr| { @@ -2872,7 +2895,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE } // reset in case calls to errorable functions are removed. - ip.funcSetHasErrorTrace(func_index, fn_ty_info.cc == .auto); + ip.funcSetHasErrorTrace(io, func_index, fn_ty_info.cc == .auto); // First few indexes of extra are reserved and set at the end. const reserved_count = @typeInfo(Air.ExtraIndex).@"enum".fields.len; @@ -2971,7 +2994,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE }); } - func.setBranchHint(ip, sema.branch_hint orelse .none); + func.setBranchHint(ip, io, sema.branch_hint orelse .none); if (zcu.comp.config.any_error_tracing and func.analysisUnordered(ip).has_error_trace and fn_ty_info.cc != .auto) { // We're using an error trace, but didn't start out with one from the caller. @@ -3005,7 +3028,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE else => |e| return e, }; assert(ies.resolved != .none); - func.setResolvedErrorSet(ip, ies.resolved); + func.setResolvedErrorSet(ip, io, ies.resolved); } assert(zcu.analysis_in_progress.swapRemove(anal_unit)); @@ -3036,7 +3059,8 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE } pub fn createNamespace(pt: Zcu.PerThread, initialization: Zcu.Namespace) !Zcu.Namespace.Index { - return pt.zcu.intern_pool.createNamespace(pt.zcu.gpa, pt.tid, initialization); + const comp = pt.zcu.comp; + return pt.zcu.intern_pool.createNamespace(comp.gpa, comp.io, pt.tid, initialization); } pub fn destroyNamespace(pt: Zcu.PerThread, namespace_index: Zcu.Namespace.Index) void { @@ -3047,11 +3071,15 @@ pub fn getErrorValue( pt: Zcu.PerThread, name: InternPool.NullTerminatedString, ) Allocator.Error!Zcu.ErrorInt { - return pt.zcu.intern_pool.getErrorValue(pt.zcu.gpa, pt.tid, name); + const comp = pt.zcu.comp; + return pt.zcu.intern_pool.getErrorValue(comp.gpa, comp.io, pt.tid, name); } pub fn getErrorValueFromSlice(pt: Zcu.PerThread, name: []const u8) Allocator.Error!Zcu.ErrorInt { - return pt.getErrorValue(try pt.zcu.intern_pool.getOrPutString(pt.zcu.gpa, name)); + const comp = pt.zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + return pt.getErrorValue(try pt.zcu.intern_pool.getOrPutString(gpa, io, name)); } /// Removes any entry from `Zcu.failed_files` associated with `file`. Acquires `Compilation.mutex` as needed. @@ -3078,8 +3106,10 @@ fn lockAndClearFileCompileError(pt: Zcu.PerThread, file_index: Zcu.File.Index, f return; } - pt.zcu.comp.mutex.lock(); - defer pt.zcu.comp.mutex.unlock(); + const comp = pt.zcu.comp; + const io = comp.io; + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); if (pt.zcu.failed_files.fetchSwapRemove(file_index)) |kv| { assert(maybe_has_error); // the runtime safety case above if (kv.value) |msg| pt.zcu.gpa.free(msg); // delete previous error message @@ -3266,7 +3296,9 @@ fn processExportsInner( pub fn populateTestFunctions(pt: Zcu.PerThread) Allocator.Error!void { const zcu = pt.zcu; - const gpa = zcu.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; // Our job is to correctly set the value of the `test_functions` declaration if it has been @@ -3284,7 +3316,7 @@ pub fn populateTestFunctions(pt: Zcu.PerThread) Allocator.Error!void { const builtin_namespace = Type.fromInterned(builtin_root_type).getNamespace(zcu).unwrap().?; // We know that the namespace has a `test_functions`... const nav_index = zcu.namespacePtr(builtin_namespace).pub_decls.getKeyAdapted( - try ip.getOrPutString(gpa, pt.tid, "test_functions", .no_embedded_nulls), + try ip.getOrPutString(gpa, io, pt.tid, "test_functions", .no_embedded_nulls), Zcu.Namespace.NameAdapter{ .zcu = zcu }, ).?; // ...but it might not be populated, so let's check that! @@ -3392,7 +3424,7 @@ pub fn populateTestFunctions(pt: Zcu.PerThread) Allocator.Error!void { } }), .len = (try pt.intValue(Type.usize, zcu.test_functions.count())).toIntern(), } }); - ip.mutateVarInit(test_fns_val.toIntern(), new_init); + ip.mutateVarInit(io, test_fns_val.toIntern(), new_init); } // The linker thread is not running, so we actually need to dispatch this task directly. @import("../link.zig").linkTestFunctionsNav(pt, nav_index); @@ -3407,7 +3439,9 @@ pub fn reportRetryableFileError( args: anytype, ) error{OutOfMemory}!void { const zcu = pt.zcu; - const gpa = zcu.gpa; + const comp = zcu.comp; + const io = comp.io; + const gpa = comp.gpa; const file = zcu.fileByIndex(file_index); @@ -3417,8 +3451,8 @@ pub fn reportRetryableFileError( errdefer gpa.free(msg); const old_msg: ?[]u8 = old_msg: { - zcu.comp.mutex.lock(); - defer zcu.comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); const gop = try zcu.failed_files.getOrPut(gpa, file_index); const old: ?[]u8 = if (gop.found_existing) old: { @@ -3433,12 +3467,8 @@ pub fn reportRetryableFileError( /// Shortcut for calling `intern_pool.get`. pub fn intern(pt: Zcu.PerThread, key: InternPool.Key) Allocator.Error!InternPool.Index { - return pt.zcu.intern_pool.get(pt.zcu.gpa, pt.tid, key); -} - -/// Shortcut for calling `intern_pool.getUnion`. -pub fn internUnion(pt: Zcu.PerThread, un: InternPool.Key.Union) Allocator.Error!InternPool.Index { - return pt.zcu.intern_pool.getUnion(pt.zcu.gpa, pt.tid, un); + const comp = pt.zcu.comp; + return pt.zcu.intern_pool.get(comp.gpa, comp.io, pt.tid, key); } /// Essentially a shortcut for calling `intern_pool.getCoerced`. @@ -3446,6 +3476,9 @@ pub fn internUnion(pt: Zcu.PerThread, un: InternPool.Key.Union) Allocator.Error! /// this because it requires potentially pushing to the job queue. pub fn getCoerced(pt: Zcu.PerThread, val: Value, new_ty: Type) Allocator.Error!Value { const ip = &pt.zcu.intern_pool; + const comp = pt.zcu.comp; + const gpa = comp.gpa; + const io = comp.io; switch (ip.indexToKey(val.toIntern())) { .@"extern" => |e| { const coerced = try pt.getExtern(.{ @@ -3458,6 +3491,7 @@ pub fn getCoerced(pt: Zcu.PerThread, val: Value, new_ty: Type) Allocator.Error!V .visibility = e.visibility, .is_dll_import = e.is_dll_import, .relocation = e.relocation, + .decoration = e.decoration, .alignment = e.alignment, .@"addrspace" = e.@"addrspace", .zir_index = e.zir_index, @@ -3468,7 +3502,7 @@ pub fn getCoerced(pt: Zcu.PerThread, val: Value, new_ty: Type) Allocator.Error!V }, else => {}, } - return Value.fromInterned(try ip.getCoerced(pt.zcu.gpa, pt.tid, val.toIntern(), new_ty.toIntern())); + return Value.fromInterned(try ip.getCoerced(gpa, io, pt.tid, val.toIntern(), new_ty.toIntern())); } pub fn intType(pt: Zcu.PerThread, signedness: std.builtin.Signedness, bits: u16) Allocator.Error!Type { @@ -3566,7 +3600,8 @@ pub fn adjustPtrTypeChild(pt: Zcu.PerThread, ptr_ty: Type, new_child: Type) Allo } pub fn funcType(pt: Zcu.PerThread, key: InternPool.GetFuncTypeKey) Allocator.Error!Type { - return Type.fromInterned(try pt.zcu.intern_pool.getFuncType(pt.zcu.gpa, pt.tid, key)); + const comp = pt.zcu.comp; + return .fromInterned(try pt.zcu.intern_pool.getFuncType(comp.gpa, comp.io, pt.tid, key)); } /// Use this for `anyframe->T` only. @@ -3584,7 +3619,8 @@ pub fn errorUnionType(pt: Zcu.PerThread, error_set_ty: Type, payload_ty: Type) A pub fn singleErrorSetType(pt: Zcu.PerThread, name: InternPool.NullTerminatedString) Allocator.Error!Type { const names: *const [1]InternPool.NullTerminatedString = &name; - return Type.fromInterned(try pt.zcu.intern_pool.getErrorSetType(pt.zcu.gpa, pt.tid, names)); + const comp = pt.zcu.comp; + return Type.fromInterned(try pt.zcu.intern_pool.getErrorSetType(comp.gpa, comp.io, pt.tid, names)); } /// Sorts `names` in place. @@ -3598,7 +3634,8 @@ pub fn errorSetFromUnsortedNames( {}, InternPool.NullTerminatedString.indexLessThan, ); - const new_ty = try pt.zcu.intern_pool.getErrorSetType(pt.zcu.gpa, pt.tid, names); + const comp = pt.zcu.comp; + const new_ty = try pt.zcu.intern_pool.getErrorSetType(comp.gpa, comp.io, pt.tid, names); return Type.fromInterned(new_ty); } @@ -3709,9 +3746,17 @@ pub fn intValue_i64(pt: Zcu.PerThread, ty: Type, x: i64) Allocator.Error!Value { } })); } +/// Shortcut for calling `intern_pool.getUnion`. +/// TODO: remove either this or `unionValue`. +pub fn internUnion(pt: Zcu.PerThread, un: InternPool.Key.Union) Allocator.Error!InternPool.Index { + const comp = pt.zcu.comp; + return pt.zcu.intern_pool.getUnion(comp.gpa, comp.io, pt.tid, un); +} + +/// TODO: remove either this or `internUnion`. pub fn unionValue(pt: Zcu.PerThread, union_ty: Type, tag: Value, val: Value) Allocator.Error!Value { - const zcu = pt.zcu; - return Value.fromInterned(try zcu.intern_pool.getUnion(zcu.gpa, pt.tid, .{ + const comp = pt.zcu.comp; + return Value.fromInterned(try pt.zcu.intern_pool.getUnion(comp.gpa, comp.io, pt.tid, .{ .ty = union_ty.toIntern(), .tag = tag.toIntern(), .val = val.toIntern(), @@ -3771,12 +3816,12 @@ pub fn nullValue(pt: Zcu.PerThread, opt_ty: Type) Allocator.Error!Value { /// `ty` is an integer or a vector of integers. pub fn overflowArithmeticTupleType(pt: Zcu.PerThread, ty: Type) !Type { const zcu = pt.zcu; - const ip = &zcu.intern_pool; + const comp = zcu.comp; const ov_ty: Type = if (ty.zigTypeTag(zcu) == .vector) try pt.vectorType(.{ .len = ty.vectorLen(zcu), .child = .u1_type, }) else .u1; - const tuple_ty = try ip.getTupleType(zcu.gpa, pt.tid, .{ + const tuple_ty = try zcu.intern_pool.getTupleType(comp.gpa, comp.io, pt.tid, .{ .types = &.{ ty.toIntern(), ov_ty.toIntern() }, .values = &.{ .none, .none }, }); @@ -3872,12 +3917,14 @@ pub fn navPtrType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Allocator.Err /// If necessary, the new `Nav` is queued for codegen. /// `key.owner_nav` is ignored and may be `undefined`. pub fn getExtern(pt: Zcu.PerThread, key: InternPool.Key.Extern) Allocator.Error!InternPool.Index { - const result = try pt.zcu.intern_pool.getExtern(pt.zcu.gpa, pt.tid, key); + const zcu = pt.zcu; + const comp = zcu.comp; + const result = try zcu.intern_pool.getExtern(comp.gpa, comp.io, pt.tid, key); if (result.new_nav.unwrap()) |nav| { // This job depends on any resolve_type_fully jobs queued up before it. - pt.zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); - try pt.zcu.comp.queueJob(.{ .link_nav = nav }); - if (pt.zcu.comp.debugIncremental()) try pt.zcu.incremental_debug_state.newNav(pt.zcu, nav); + comp.link_prog_node.increaseEstimatedTotalItems(1); + try comp.queueJob(.{ .link_nav = nav }); + if (comp.debugIncremental()) try zcu.incremental_debug_state.newNav(zcu, nav); } return result.index; } @@ -3966,7 +4013,9 @@ fn recreateStructType( key: InternPool.Key.NamespaceType.Declared, ) Allocator.Error!InternPool.Index { const zcu = pt.zcu; - const gpa = zcu.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; const inst_info = key.zir_index.resolveFull(ip).?; @@ -3995,7 +4044,7 @@ fn recreateStructType( const struct_obj = ip.loadStructType(old_ty); - const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{ + const wip_ty = switch (try ip.getStructType(gpa, io, pt.tid, .{ .layout = small.layout, .fields_len = fields_len, .known_non_opv = small.known_non_opv, @@ -4042,7 +4091,9 @@ fn recreateUnionType( key: InternPool.Key.NamespaceType.Declared, ) Allocator.Error!InternPool.Index { const zcu = pt.zcu; - const gpa = zcu.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; const inst_info = key.zir_index.resolveFull(ip).?; @@ -4075,7 +4126,7 @@ fn recreateUnionType( const namespace_index = union_obj.namespace; - const wip_ty = switch (try ip.getUnionType(gpa, pt.tid, .{ + const wip_ty = switch (try ip.getUnionType(gpa, io, pt.tid, .{ .flags = .{ .layout = small.layout, .status = .none, @@ -4133,7 +4184,9 @@ fn recreateEnumType( key: InternPool.Key.NamespaceType.Declared, ) (Allocator.Error || Io.Cancelable)!InternPool.Index { const zcu = pt.zcu; - const gpa = zcu.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; const inst_info = key.zir_index.resolveFull(ip).?; @@ -4197,7 +4250,7 @@ fn recreateEnumType( const namespace_index = enum_obj.namespace; - const wip_ty = switch (try ip.getEnumType(gpa, pt.tid, .{ + const wip_ty = switch (try ip.getEnumType(gpa, io, pt.tid, .{ .has_values = any_values, .tag_mode = if (small.nonexhaustive) .nonexhaustive @@ -4404,7 +4457,7 @@ pub fn refValue(pt: Zcu.PerThread, val: InternPool.Index) Zcu.SemaError!InternPo pub fn addDependency(pt: Zcu.PerThread, unit: AnalUnit, dependee: InternPool.Dependee) Allocator.Error!void { const zcu = pt.zcu; - const gpa = zcu.gpa; + const gpa = zcu.comp.gpa; try zcu.intern_pool.addDependency(gpa, unit, dependee); if (zcu.comp.debugIncremental()) { const info = try zcu.incremental_debug_state.getUnitInfo(gpa, unit); @@ -4412,50 +4465,38 @@ pub fn addDependency(pt: Zcu.PerThread, unit: AnalUnit, dependee: InternPool.Dep } } -/// Performs code generation, which comes after `Sema` but before `link` in the pipeline. -/// This part of the pipeline is self-contained/"pure", so can be run in parallel with most -/// other code. This function is currently run either on the main thread, or on a separate -/// codegen thread, depending on whether the backend supports `Zcu.Feature.separate_thread`. -pub fn runCodegen(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air, out: *@import("../link.zig").ZcuTask.LinkFunc.SharedMir) void { +pub const RunCodegenError = Io.Cancelable || error{AlreadyReported}; + +/// Performs code generation, which comes after `Sema` but before `link` in the pipeline. This part +/// of the pipeline is self-contained and can usually be run concurrently with other components. +/// +/// This function is called asynchronously by `Zcu.CodegenTaskPool.start` and awaited by the linker. +/// However, if the codegen backend does not support `Zcu.Feature.separate_thread`, then +/// `Compilation.processOneJob` will immediately await the result of the linker task, meaning the +/// pipeline becomes effectively single-threaded. +pub fn runCodegen(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) RunCodegenError!codegen.AnyMir { const zcu = pt.zcu; + const comp = zcu.comp; + const io = comp.io; crash_report.CodegenFunc.start(zcu, func_index); defer crash_report.CodegenFunc.stop(func_index); - var timer = zcu.comp.startTimer(); + var timer = comp.startTimer(); - const success: bool = if (runCodegenInner(pt, func_index, air)) |mir| success: { - out.value = mir; - break :success true; - } else |err| success: { - switch (err) { - error.OutOfMemory => zcu.comp.setAllocFailure(), - error.CodegenFail => zcu.assertCodegenFailed(zcu.funcInfo(func_index).owner_nav), - error.NoLinkFile => assert(zcu.comp.bin_file == null), - error.BackendDoesNotProduceMir => switch (target_util.zigBackend( - &zcu.root_mod.resolved_target.result, - zcu.comp.config.use_llvm, - )) { - else => unreachable, // assertion failure - .stage2_spirv, - .stage2_llvm, - => {}, - }, - } - break :success false; - }; + const codegen_result = runCodegenInner(pt, func_index, air); if (timer.finish()) |ns_codegen| report_time: { const ip = &zcu.intern_pool; const nav = ip.indexToKey(func_index).func.owner_nav; const zir_decl = ip.getNav(nav).srcInst(ip); - zcu.comp.mutex.lock(); - defer zcu.comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); const tr = &zcu.comp.time_report.?; tr.stats.cpu_ns_codegen += ns_codegen; - const gop = tr.decl_codegen_ns.getOrPut(zcu.gpa, zir_decl) catch |err| switch (err) { + const gop = tr.decl_codegen_ns.getOrPut(comp.gpa, zir_decl) catch |err| switch (err) { error.OutOfMemory => { - zcu.comp.setAllocFailure(); + comp.setAllocFailure(); break :report_time; }, }; @@ -4463,17 +4504,34 @@ pub fn runCodegen(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air, ou gop.value_ptr.* += ns_codegen; } - // release `out.value` with this store; synchronizes with acquire loads in `link` - out.status.store(if (success) .ready else .failed, .release); - zcu.comp.link_task_queue.mirReady(zcu.comp, func_index, out); if (zcu.pending_codegen_jobs.rmw(.Sub, 1, .monotonic) == 1) { // Decremented to 0, so all done. zcu.codegen_prog_node.end(); zcu.codegen_prog_node = .none; } + + return codegen_result catch |err| { + switch (err) { + error.OutOfMemory => comp.setAllocFailure(), + error.CodegenFail => zcu.assertCodegenFailed(zcu.funcInfo(func_index).owner_nav), + error.NoLinkFile => assert(comp.bin_file == null), + error.BackendDoesNotProduceMir => switch (target_util.zigBackend( + &zcu.root_mod.resolved_target.result, + comp.config.use_llvm, + )) { + else => unreachable, // assertion failure + .stage2_spirv, + .stage2_llvm, + => {}, + }, + error.Canceled => |e| return e, + } + return error.AlreadyReported; + }; } fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) error{ OutOfMemory, + Canceled, CodegenFail, NoLinkFile, BackendDoesNotProduceMir, @@ -4499,12 +4557,16 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e null; defer if (liveness) |*l| l.deinit(gpa); - if (build_options.enable_debug_extensions and comp.verbose_air) { - const stderr, _ = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); - stderr.print("# Begin Function AIR: {f}:\n", .{fqn.fmt(ip)}) catch {}; - air.write(stderr, pt, liveness); - stderr.print("# End Function AIR: {f}\n\n", .{fqn.fmt(ip)}) catch {}; + if (build_options.enable_debug_extensions and comp.verbose_air) p: { + const io = comp.io; + const stderr = try io.lockStderr(&.{}, null); + defer io.unlockStderr(); + printVerboseAir(pt, liveness, fqn, air, &stderr.file_writer.interface) catch |err| switch (err) { + error.WriteFailed => switch (stderr.file_writer.err.?) { + error.Canceled => |e| return e, + else => break :p, + }, + }; } if (std.debug.runtime_safety) verify_liveness: { @@ -4519,7 +4581,7 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e verify.verify() catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, - else => return zcu.codegenFail(nav, "invalid liveness: {s}", .{@errorName(err)}), + else => return zcu.codegenFail(nav, "invalid liveness: {t}", .{err}), }; } @@ -4527,7 +4589,7 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e // "emit" step because LLVM does not support incremental linking. Our linker (LLD or self-hosted) // will just see the ZCU object file which LLVM ultimately emits. if (zcu.llvm_object) |llvm_object| { - assert(pt.tid == .main); // LLVM has a lot of shared state + assert(zcu.pending_codegen_jobs.load(.monotonic) == 2); // only one codegen at a time (but the value is 2 because 1 is the base) try llvm_object.updateFunc(pt, func_index, air, &liveness); return error.BackendDoesNotProduceMir; } @@ -4536,7 +4598,7 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e // Just like LLVM, the SPIR-V backend can't multi-threaded due to SPIR-V design limitations. if (lf.cast(.spirv)) |spirv_file| { - assert(pt.tid == .main); // SPIR-V has a lot of shared state + assert(zcu.pending_codegen_jobs.load(.monotonic) == 2); // only one codegen at a time (but the value is 2 because 1 is the base) spirv_file.updateFunc(pt, func_index, air, &liveness) catch |err| { switch (err) { error.OutOfMemory => comp.link_diags.setAllocFailure(), @@ -4555,3 +4617,17 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e => return zcu.codegenFail(nav, "unable to codegen: {s}", .{@errorName(err)}), }; } + +fn printVerboseAir( + pt: Zcu.PerThread, + liveness: ?Air.Liveness, + fqn: InternPool.NullTerminatedString, + air: *const Air, + w: *Io.Writer, +) Io.Writer.Error!void { + const zcu = pt.zcu; + const ip = &zcu.intern_pool; + try w.print("# Begin Function AIR: {f}:\n", .{fqn.fmt(ip)}); + try air.write(w, pt, liveness); + try w.print("# End Function AIR: {f}\n\n", .{fqn.fmt(ip)}); +} diff --git a/src/codegen/aarch64/Select.zig b/src/codegen/aarch64/Select.zig index f390d83f03bf..49de055b47b6 100644 --- a/src/codegen/aarch64/Select.zig +++ b/src/codegen/aarch64/Select.zig @@ -11273,15 +11273,17 @@ fn initValueAdvanced( return @enumFromInt(isel.values.items.len); } pub fn dumpValues(isel: *Select, which: enum { only_referenced, all }) void { - errdefer |err| @panic(@errorName(err)); - const stderr, _ = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); - const zcu = isel.pt.zcu; const gpa = zcu.gpa; const ip = &zcu.intern_pool; const nav = ip.getNav(isel.nav_index); + errdefer |err| @panic(@errorName(err)); + + const locked_stderr = std.debug.lockStderr(&.{}); + defer std.debug.unlockStderr(); + const stderr = &locked_stderr.file_writer.interface; + var reverse_live_values: std.AutoArrayHashMapUnmanaged(Value.Index, std.ArrayList(Air.Inst.Index)) = .empty; defer { for (reverse_live_values.values()) |*list| list.deinit(gpa); diff --git a/src/codegen/c.zig b/src/codegen/c.zig index fba8806ecd3f..f55dd408b524 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -5529,7 +5529,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { .alignas = CType.AlignAs.fromAbiAlignment(input_ty.abiAlignment(zcu)), }); try f.allocs.put(gpa, input_local.new_local, false); - try f.object.dg.renderTypeAndName(w, input_ty, input_local, Const, .none, .complete); + // Do not render the declaration as `const` qualified if we're generating an + // explicit `register` local, as GCC will ignore the constraint completely. + try f.object.dg.renderTypeAndName(w, input_ty, input_local, if (is_reg) .{} else Const, .none, .complete); if (is_reg) { try w.writeAll(" __asm(\""); try w.writeAll(constraint["{".len .. constraint.len - "}".len]); diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index f8995446b3d7..fca89ea4fcf1 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1,19 +1,22 @@ -const std = @import("std"); const builtin = @import("builtin"); + +const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; const Allocator = std.mem.Allocator; const log = std.log.scoped(.codegen); const math = std.math; const DW = std.dwarf; - const Builder = std.zig.llvm.Builder; + +const build_options = @import("build_options"); const llvm = if (build_options.have_llvm) @import("llvm/bindings.zig") else @compileError("LLVM unavailable"); + const link = @import("../link.zig"); const Compilation = @import("../Compilation.zig"); -const build_options = @import("build_options"); const Zcu = @import("../Zcu.zig"); const InternPool = @import("../InternPool.zig"); const Package = @import("../Package.zig"); @@ -799,6 +802,7 @@ pub const Object = struct { pub fn emit(o: *Object, pt: Zcu.PerThread, options: EmitOptions) error{ LinkFailure, OutOfMemory }!void { const zcu = pt.zcu; const comp = zcu.comp; + const io = comp.io; const diags = &comp.link_diags; { @@ -961,10 +965,10 @@ pub const Object = struct { const context, const module = emit: { if (options.pre_ir_path) |path| { if (std.mem.eql(u8, path, "-")) { - o.builder.dump(); + o.builder.dump(io); } else { - o.builder.printToFilePath(std.fs.cwd(), path) catch |err| { - log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) }); + o.builder.printToFilePath(io, Io.Dir.cwd(), path) catch |err| { + log.err("failed printing LLVM module to \"{s}\": {t}", .{ path, err }); }; } } @@ -977,26 +981,26 @@ pub const Object = struct { o.builder.clearAndFree(); if (options.pre_bc_path) |path| { - var file = std.fs.cwd().createFile(path, .{}) catch |err| - return diags.fail("failed to create '{s}': {s}", .{ path, @errorName(err) }); - defer file.close(); + var file = Io.Dir.cwd().createFile(io, path, .{}) catch |err| + return diags.fail("failed to create '{s}': {t}", .{ path, err }); + defer file.close(io); const ptr: [*]const u8 = @ptrCast(bitcode.ptr); - file.writeAll(ptr[0..(bitcode.len * 4)]) catch |err| - return diags.fail("failed to write to '{s}': {s}", .{ path, @errorName(err) }); + file.writeStreamingAll(io, ptr[0..(bitcode.len * 4)]) catch |err| + return diags.fail("failed to write to '{s}': {t}", .{ path, err }); } if (options.asm_path == null and options.bin_path == null and options.post_ir_path == null and options.post_bc_path == null) return; if (options.post_bc_path) |path| { - var file = std.fs.cwd().createFile(path, .{}) catch |err| - return diags.fail("failed to create '{s}': {s}", .{ path, @errorName(err) }); - defer file.close(); + var file = Io.Dir.cwd().createFile(io, path, .{}) catch |err| + return diags.fail("failed to create '{s}': {t}", .{ path, err }); + defer file.close(io); const ptr: [*]const u8 = @ptrCast(bitcode.ptr); - file.writeAll(ptr[0..(bitcode.len * 4)]) catch |err| - return diags.fail("failed to write to '{s}': {s}", .{ path, @errorName(err) }); + file.writeStreamingAll(io, ptr[0..(bitcode.len * 4)]) catch |err| + return diags.fail("failed to write to '{s}': {t}", .{ path, err }); } if (!build_options.have_llvm or !comp.config.use_lib_llvm) { @@ -1787,6 +1791,22 @@ pub const Object = struct { global_index.toConst(), ); try alias_index.rename(exp_name, &o.builder); + + const alias_global_index = alias_index.ptrConst(&o.builder).global; + alias_global_index.setUnnamedAddr(.default, &o.builder); + if (comp.config.dll_export_fns) + alias_global_index.setDllStorageClass(.dllexport, &o.builder); + alias_global_index.setLinkage(switch (first_export.opts.linkage) { + .internal => unreachable, + .strong => .external, + .weak => .weak_odr, + .link_once => .linkonce_odr, + }, &o.builder); + alias_global_index.setVisibility(switch (first_export.opts.visibility) { + .default => .default, + .hidden => .hidden, + .protected => .protected, + }, &o.builder); } } @@ -2694,7 +2714,7 @@ pub const Object = struct { } fn allocTypeName(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error![:0]const u8 { - var aw: std.Io.Writer.Allocating = .init(o.gpa); + var aw: Io.Writer.Allocating = .init(o.gpa); defer aw.deinit(); ty.print(&aw.writer, pt, null) catch |err| switch (err) { error.WriteFailed => return error.OutOfMemory, diff --git a/src/codegen/spirv/CodeGen.zig b/src/codegen/spirv/CodeGen.zig index c34dd96e25cd..d4227ddff6ac 100644 --- a/src/codegen/spirv/CodeGen.zig +++ b/src/codegen/spirv/CodeGen.zig @@ -254,7 +254,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { try cg.module.debugName(func_result_id, nav.fqn.toSlice(ip)); }, .global => { - assert(ip.indexToKey(val.toIntern()) == .@"extern"); + const key = ip.indexToKey(val.toIntern()).@"extern"; const storage_class = cg.module.storageClass(nav.getAddrspace()); assert(storage_class != .generic); // These should be instance globals @@ -277,14 +277,32 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { } } - switch (ip.indexToKey(ty.toIntern())) { - .func_type, .opaque_type => {}, - else => { - try cg.module.decorate(ptr_ty_id, .{ - .array_stride = .{ .array_stride = @intCast(ty.abiSize(zcu)) }, + try cg.module.decorate(ptr_ty_id, .{ + .array_stride = .{ .array_stride = @intCast(ty.abiSize(zcu)) }, + }); + + if (key.decoration) |decoration| switch (decoration) { + .location => |location| { + if (storage_class != .output and storage_class != .input and storage_class != .uniform_constant) { + return cg.fail("storage class must be one of (output, input, uniform_constant) but is {s}", .{@tagName(storage_class)}); + } + try cg.module.decorate(result_id, .{ + .location = .{ .location = location }, }); }, - } + .descriptor => |descriptor| { + if (storage_class != .storage_buffer and storage_class != .uniform and storage_class != .uniform_constant) { + return cg.fail("storage class must be one of (storage_buffer, uniform, uniform_constant) but is {s}", .{@tagName(storage_class)}); + } + try cg.module.decorate(result_id, .{ + .binding = .{ .binding_point = descriptor.binding }, + }); + + try cg.module.decorate(result_id, .{ + .descriptor_set = .{ .descriptor_set = descriptor.set }, + }); + }, + }; }, else => {}, } @@ -2270,6 +2288,9 @@ fn buildWideMul( ) !struct { Temporary, Temporary } { const pt = cg.pt; const zcu = cg.module.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const target = cg.module.zcu.getTarget(); const ip = &zcu.intern_pool; @@ -2297,14 +2318,14 @@ fn buildWideMul( }; for (0..ops) |i| { - try cg.body.emit(cg.module.gpa, .OpIMul, .{ + try cg.body.emit(gpa, .OpIMul, .{ .id_result_type = arith_op_ty_id, .id_result = value_results.at(i), .operand_1 = lhs_op.at(i), .operand_2 = rhs_op.at(i), }); - try cg.body.emit(cg.module.gpa, .OpExtInst, .{ + try cg.body.emit(gpa, .OpExtInst, .{ .id_result_type = arith_op_ty_id, .id_result = overflow_results.at(i), .set = set, @@ -2316,7 +2337,7 @@ fn buildWideMul( .vulkan, .opengl => { // Operations return a struct{T, T} // where T is maybe vectorized. - const op_result_ty: Type = .fromInterned(try ip.getTupleType(zcu.gpa, pt.tid, .{ + const op_result_ty: Type = .fromInterned(try ip.getTupleType(gpa, io, pt.tid, .{ .types = &.{ arith_op_ty.toIntern(), arith_op_ty.toIntern() }, .values = &.{ .none, .none }, })); @@ -2330,7 +2351,7 @@ fn buildWideMul( for (0..ops) |i| { const op_result = cg.module.allocId(); - try cg.body.emitRaw(cg.module.gpa, opcode, 4); + try cg.body.emitRaw(gpa, opcode, 4); cg.body.writeOperand(Id, op_result_ty_id); cg.body.writeOperand(Id, op_result); cg.body.writeOperand(Id, lhs_op.at(i)); @@ -2340,14 +2361,14 @@ fn buildWideMul( // Temporary to deal with the fact that these are structs eventually, // but for now, take the struct apart and return two separate vectors. - try cg.body.emit(cg.module.gpa, .OpCompositeExtract, .{ + try cg.body.emit(gpa, .OpCompositeExtract, .{ .id_result_type = arith_op_ty_id, .id_result = value_results.at(i), .composite = op_result, .indexes = &.{0}, }); - try cg.body.emit(cg.module.gpa, .OpCompositeExtract, .{ + try cg.body.emit(gpa, .OpCompositeExtract, .{ .id_result_type = arith_op_ty_id, .id_result = overflow_results.at(i), .composite = op_result, diff --git a/src/codegen/wasm/CodeGen.zig b/src/codegen/wasm/CodeGen.zig index 5d78b46702ca..5799ee614d5d 100644 --- a/src/codegen/wasm/CodeGen.zig +++ b/src/codegen/wasm/CodeGen.zig @@ -6973,9 +6973,20 @@ fn airShlSat(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { return cg.fail("TODO: Saturating shifting left for integers with bitsize '{d}'", .{int_info.bits}); } - const lhs = try cg.resolveInst(bin_op.lhs); - const rhs = try cg.resolveInst(bin_op.rhs); const wasm_bits = toWasmBits(int_info.bits).?; + + const lhs = try cg.resolveInst(bin_op.lhs); + const rhs = rhs: { + const rhs = try cg.resolveInst(bin_op.rhs); + const rhs_ty = cg.typeOf(bin_op.rhs); + // The type of `rhs` is the log2 int of the type of `lhs`, but WASM wants the lhs and rhs types to match. + if (toWasmBits(@intCast(rhs_ty.bitSize(zcu))).? == wasm_bits) { + break :rhs rhs; // the WASM types match, so no cast necessary + } + const casted = try cg.intcast(rhs, rhs_ty, ty); + break :rhs try casted.toLocal(cg, ty); + }; + const result = try cg.allocLocal(ty); if (wasm_bits == int_info.bits) { diff --git a/src/codegen/wasm/Emit.zig b/src/codegen/wasm/Emit.zig index e18bd1221363..000287524069 100644 --- a/src/codegen/wasm/Emit.zig +++ b/src/codegen/wasm/Emit.zig @@ -85,7 +85,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { if (is_obj) { @panic("TODO"); } else { - writeUleb128(code, 1 + @intFromEnum(indirect_func_idx)); + writeSleb128(code, 1 + @intFromEnum(indirect_func_idx)); } inst += 1; continue :loop tags[inst]; diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig index 99d768805f60..382c9e9c3cb1 100644 --- a/src/codegen/x86_64/CodeGen.zig +++ b/src/codegen/x86_64/CodeGen.zig @@ -171444,12 +171444,14 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { const elem_dies = bt.feed(); if (tuple_type.values.get(ip)[field_index] != .none) continue; const field_type = Type.fromInterned(tuple_type.types.get(ip)[field_index]); - elem_disp = @intCast(field_type.abiAlignment(zcu).forward(elem_disp)); - var elem = try cg.tempFromOperand(elem_ref, elem_dies); - try res.write(&elem, .{ .disp = elem_disp }, cg); - try elem.die(cg); - try cg.resetTemps(reset_index); - elem_disp += @intCast(field_type.abiSize(zcu)); + if (!hack_around_sema_opv_bugs or field_type.hasRuntimeBitsIgnoreComptime(zcu)) { + elem_disp = @intCast(field_type.abiAlignment(zcu).forward(elem_disp)); + var elem = try cg.tempFromOperand(elem_ref, elem_dies); + try res.write(&elem, .{ .disp = elem_disp }, cg); + try elem.die(cg); + try cg.resetTemps(reset_index); + elem_disp += @intCast(field_type.abiSize(zcu)); + } } }, else => return cg.fail("failed to select {s} {f}", .{ @@ -173048,11 +173050,39 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { const ty_nav = air_datas[@intFromEnum(inst)].ty_nav; const nav = ip.getNav(ty_nav.nav); const is_threadlocal = zcu.comp.config.any_non_single_threaded and nav.isThreadlocal(ip); - if (is_threadlocal) if (cg.target.ofmt == .coff or cg.mod.pic) { - try cg.spillRegisters(&.{ .rdi, .rax }); - } else { - try cg.spillRegisters(&.{.rax}); + + if (is_threadlocal) switch (cg.target.ofmt) { + .elf => if (cg.mod.pic) { + // LD model: `__tls_get_addr` uses the standard ABI + try cg.spillEflagsIfOccupied(); + try cg.spillRegisters(abi.getCallerPreservedRegs(.x86_64_sysv)); + } else { + // LE model: manual lowering uses these two registers + try cg.spillRegisters(&.{ .rdi, .rax }); + }, + + .coff => { + // manual lowering uses these registers + try cg.spillRegisters(&.{ .rdi, .rax }); + }, + + .macho => switch (cg.target.cpu.arch) { + .x86 => { + // `tlv_get_addr` returns in eax, clobbers ecx, preserves other GPRs + try cg.spillEflagsIfOccupied(); + try cg.spillRegisters(&.{ .rax, .rcx }); + }, + .x86_64 => { + // `tlv_get_addr` returns in rax, preserves other GPRs + try cg.spillEflagsIfOccupied(); + try cg.spillRegisters(&.{.rax}); + }, + else => unreachable, + }, + + else => unreachable, }; + var res = try cg.tempInit(.fromInterned(ty_nav.ty), .{ .lea_nav = ty_nav.nav }); if (is_threadlocal) while (try res.toRegClass(true, .general_purpose, cg)) {}; try res.finish(inst, &.{}, &.{}, cg); @@ -180174,6 +180204,7 @@ fn airSplat(self: *CodeGen, inst: Air.Inst.Index) !void { fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void { const pt = self.pt; const zcu = pt.zcu; + const io = zcu.comp.io; const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const extra = self.air.extraData(Air.Bin, pl_op.payload).data; const ty = self.typeOfIndex(inst); @@ -180447,7 +180478,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void { for (mask_elems, 0..) |*elem, bit| elem.* = @intCast(bit / elem_bits); const mask_mcv = try self.lowerValue(.fromInterned(try pt.intern(.{ .aggregate = .{ .ty = mask_ty.toIntern(), - .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, mask_elems, .maybe_embedded_nulls) }, + .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, io, pt.tid, mask_elems, .maybe_embedded_nulls) }, } }))); const mask_mem: Memory = .{ .base = .{ .reg = try self.copyToTmpRegister(.usize, mask_mcv.address()) }, @@ -181159,6 +181190,9 @@ fn resolveCallingConventionValues( else => unreachable, } + const save_param_gpr_index = param_gpr_index; + const save_param_sse_index = param_gpr_index; + var arg_mcv: [4]MCValue = undefined; var arg_mcv_len: u32 = 0; @@ -181258,6 +181292,9 @@ fn resolveCallingConventionValues( continue; } + param_gpr_index = save_param_gpr_index; + param_sse_index = save_param_sse_index; + const param_align = ty.abiAlignment(zcu).max(.@"8"); result.stack_byte_count = @intCast(param_align.forward(result.stack_byte_count)); result.stack_align = result.stack_align.max(param_align); @@ -188440,6 +188477,7 @@ const Select = struct { fn create(spec: TempSpec, s: *const Select) InnerError!struct { Temp, bool } { const cg = s.cg; const pt = cg.pt; + const io = pt.zcu.comp.io; return switch (spec.kind) { .unused => .{ undefined, false }, .any => .{ try cg.tempAlloc(spec.type), true }, @@ -188657,7 +188695,7 @@ const Select = struct { }; return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{ .ty = spec.type.toIntern(), - .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, elems, .maybe_embedded_nulls) }, + .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, io, pt.tid, elems, .maybe_embedded_nulls) }, } }))), true }; }, .pshufb_trunc_mem => |trunc_spec| { @@ -188684,7 +188722,7 @@ const Select = struct { }; return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{ .ty = spec.type.toIntern(), - .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, elems, .maybe_embedded_nulls) }, + .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, io, pt.tid, elems, .maybe_embedded_nulls) }, } }))), true }; }, .pand_trunc_mem => |trunc_spec| { @@ -188698,7 +188736,7 @@ const Select = struct { while (index < elems.len) : (index += from_bytes) @memset(elems[index..][0..to_bytes], std.math.maxInt(u8)); return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{ .ty = spec.type.toIntern(), - .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, elems, .maybe_embedded_nulls) }, + .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, io, pt.tid, elems, .maybe_embedded_nulls) }, } }))), true }; }, .pand_mask_mem => |mask_spec| { @@ -188717,7 +188755,7 @@ const Select = struct { @memset(elems[mask_len..], invert_mask); return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{ .ty = spec.type.toIntern(), - .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, elems, .maybe_embedded_nulls) }, + .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, io, pt.tid, elems, .maybe_embedded_nulls) }, } }))), true }; }, .ptest_mask_mem => |mask_ref| { @@ -188742,7 +188780,7 @@ const Select = struct { } return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{ .ty = spec.type.toIntern(), - .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, elems, .maybe_embedded_nulls) }, + .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, io, pt.tid, elems, .maybe_embedded_nulls) }, } }))), true }; }, .pshufb_bswap_mem => |bswap_spec| { @@ -188758,7 +188796,7 @@ const Select = struct { }; return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{ .ty = spec.type.toIntern(), - .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, elems, .maybe_embedded_nulls) }, + .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, io, pt.tid, elems, .maybe_embedded_nulls) }, } }))), true }; }, .bits_mem => |direction| { @@ -188772,7 +188810,7 @@ const Select = struct { }; return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{ .ty = spec.type.toIntern(), - .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, elems, .maybe_embedded_nulls) }, + .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, io, pt.tid, elems, .maybe_embedded_nulls) }, } }))), true }; }, .splat_int_mem => |splat_spec| { diff --git a/src/crash_report.zig b/src/crash_report.zig index d525d4b3b5d9..e56bc7cec53e 100644 --- a/src/crash_report.zig +++ b/src/crash_report.zig @@ -95,19 +95,20 @@ fn dumpCrashContext() Io.Writer.Error!void { // TODO: this does mean that a different thread could grab the stderr mutex between the context // and the actual panic printing, which would be quite confusing. - const stderr, _ = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); + const stderr = std.debug.lockStderr(&.{}); + defer std.debug.unlockStderr(); + const w = &stderr.file_writer.interface; - try stderr.writeAll("Compiler crash context:\n"); + try w.writeAll("Compiler crash context:\n"); if (CodegenFunc.current) |*cg| { const func_nav = cg.zcu.funcInfo(cg.func_index).owner_nav; const func_fqn = cg.zcu.intern_pool.getNav(func_nav).fqn; - try stderr.print("Generating function '{f}'\n\n", .{func_fqn.fmt(&cg.zcu.intern_pool)}); + try w.print("Generating function '{f}'\n\n", .{func_fqn.fmt(&cg.zcu.intern_pool)}); } else if (AnalyzeBody.current) |anal| { - try dumpCrashContextSema(anal, stderr, &S.crash_heap); + try dumpCrashContextSema(anal, w, &S.crash_heap); } else { - try stderr.writeAll("(no context)\n\n"); + try w.writeAll("(no context)\n\n"); } } fn dumpCrashContextSema(anal: *AnalyzeBody, stderr: *Io.Writer, crash_heap: []u8) Io.Writer.Error!void { diff --git a/src/fmt.zig b/src/fmt.zig index 80925200d625..a3cd7c8d7459 100644 --- a/src/fmt.zig +++ b/src/fmt.zig @@ -37,9 +37,9 @@ const Fmt = struct { arena: Allocator, io: Io, out_buffer: std.Io.Writer.Allocating, - stdout_writer: *fs.File.Writer, + stdout_writer: *Io.File.Writer, - const SeenMap = std.AutoHashMap(fs.File.INode, void); + const SeenMap = std.AutoHashMap(Io.File.INode, void); }; pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !void { @@ -59,8 +59,8 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! const arg = args[i]; if (mem.startsWith(u8, arg, "-")) { if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { - try fs.File.stdout().writeAll(usage_fmt); - return process.cleanExit(); + try Io.File.stdout().writeStreamingAll(io, usage_fmt); + return process.cleanExit(io); } else if (mem.eql(u8, arg, "--color")) { if (i + 1 >= args.len) { fatal("expected [auto|on|off] after --color", .{}); @@ -99,9 +99,9 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! fatal("cannot use --stdin with positional arguments", .{}); } - const stdin: fs.File = .stdin(); + const stdin: Io.File = .stdin(); var stdio_buffer: [1024]u8 = undefined; - var file_reader: fs.File.Reader = stdin.reader(io, &stdio_buffer); + var file_reader: Io.File.Reader = stdin.reader(io, &stdio_buffer); const source_code = std.zig.readSourceFileToEndAlloc(gpa, &file_reader) catch |err| { fatal("unable to read stdin: {}", .{err}); }; @@ -124,7 +124,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! try wip_errors.addZirErrorMessages(zir, tree, source_code, ""); var error_bundle = try wip_errors.toOwnedBundle(""); defer error_bundle.deinit(gpa); - error_bundle.renderToStdErr(.{}, color); + error_bundle.renderToStderr(io, .{}, color) catch {}; process.exit(2); } } else { @@ -138,12 +138,12 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! try wip_errors.addZoirErrorMessages(zoir, tree, source_code, ""); var error_bundle = try wip_errors.toOwnedBundle(""); defer error_bundle.deinit(gpa); - error_bundle.renderToStdErr(.{}, color); + error_bundle.renderToStderr(io, .{}, color) catch {}; process.exit(2); } } } else if (tree.errors.len != 0) { - try std.zig.printAstErrorsToStderr(gpa, tree, "", color); + std.zig.printAstErrorsToStderr(gpa, io, tree, "", color) catch {}; process.exit(2); } const formatted = try tree.renderAlloc(gpa); @@ -154,7 +154,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! process.exit(code); } - return fs.File.stdout().writeAll(formatted); + return Io.File.stdout().writeStreamingAll(io, formatted); } if (input_files.items.len == 0) { @@ -162,7 +162,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! } var stdout_buffer: [4096]u8 = undefined; - var stdout_writer = fs.File.stdout().writer(&stdout_buffer); + var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer); var fmt: Fmt = .{ .gpa = gpa, @@ -182,13 +182,13 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! // Mark any excluded files/directories as already seen, // so that they are skipped later during actual processing for (excluded_files.items) |file_path| { - const stat = fs.cwd().statFile(file_path) catch |err| switch (err) { + const stat = Io.Dir.cwd().statFile(io, file_path, .{}) catch |err| switch (err) { error.FileNotFound => continue, // On Windows, statFile does not work for directories error.IsDir => dir: { - var dir = try fs.cwd().openDir(file_path, .{}); - defer dir.close(); - break :dir try dir.stat(); + var dir = try Io.Dir.cwd().openDir(io, file_path, .{}); + defer dir.close(io); + break :dir try dir.stat(io); }, else => |e| return e, }; @@ -196,7 +196,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! } for (input_files.items) |file_path| { - try fmtPath(&fmt, file_path, check_flag, fs.cwd(), file_path); + try fmtPath(&fmt, file_path, check_flag, Io.Dir.cwd(), file_path); } try fmt.stdout_writer.interface.flush(); if (fmt.any_error) { @@ -204,7 +204,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! } } -fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool, dir: fs.Dir, sub_path: []const u8) !void { +fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool, dir: Io.Dir, sub_path: []const u8) !void { fmtPathFile(fmt, file_path, check_mode, dir, sub_path) catch |err| switch (err) { error.IsDir, error.AccessDenied => return fmtPathDir(fmt, file_path, check_mode, dir, sub_path), else => { @@ -219,17 +219,19 @@ fn fmtPathDir( fmt: *Fmt, file_path: []const u8, check_mode: bool, - parent_dir: fs.Dir, + parent_dir: Io.Dir, parent_sub_path: []const u8, ) !void { - var dir = try parent_dir.openDir(parent_sub_path, .{ .iterate = true }); - defer dir.close(); + const io = fmt.io; + + var dir = try parent_dir.openDir(io, parent_sub_path, .{ .iterate = true }); + defer dir.close(io); - const stat = try dir.stat(); + const stat = try dir.stat(io); if (try fmt.seen.fetchPut(stat.inode, {})) |_| return; var dir_it = dir.iterate(); - while (try dir_it.next()) |entry| { + while (try dir_it.next(io)) |entry| { const is_dir = entry.kind == .directory; if (mem.startsWith(u8, entry.name, ".")) continue; @@ -242,7 +244,7 @@ fn fmtPathDir( try fmtPathDir(fmt, full_path, check_mode, dir, entry.name); } else { fmtPathFile(fmt, full_path, check_mode, dir, entry.name) catch |err| { - std.log.err("unable to format '{s}': {s}", .{ full_path, @errorName(err) }); + std.log.err("unable to format '{s}': {t}", .{ full_path, err }); fmt.any_error = true; return; }; @@ -255,22 +257,22 @@ fn fmtPathFile( fmt: *Fmt, file_path: []const u8, check_mode: bool, - dir: fs.Dir, + dir: Io.Dir, sub_path: []const u8, ) !void { const io = fmt.io; - const source_file = try dir.openFile(sub_path, .{}); + const source_file = try dir.openFile(io, sub_path, .{}); var file_closed = false; - errdefer if (!file_closed) source_file.close(); + errdefer if (!file_closed) source_file.close(io); - const stat = try source_file.stat(); + const stat = try source_file.stat(io); if (stat.kind == .directory) return error.IsDir; var read_buffer: [1024]u8 = undefined; - var file_reader: fs.File.Reader = source_file.reader(io, &read_buffer); + var file_reader: Io.File.Reader = source_file.reader(io, &read_buffer); file_reader.size = stat.size; const gpa = fmt.gpa; @@ -280,7 +282,7 @@ fn fmtPathFile( }; defer gpa.free(source_code); - source_file.close(); + source_file.close(io); file_closed = true; // Add to set after no longer possible to get error.IsDir. @@ -296,7 +298,7 @@ fn fmtPathFile( defer tree.deinit(gpa); if (tree.errors.len != 0) { - try std.zig.printAstErrorsToStderr(gpa, tree, file_path, fmt.color); + try std.zig.printAstErrorsToStderr(gpa, io, tree, file_path, fmt.color); fmt.any_error = true; return; } @@ -317,7 +319,7 @@ fn fmtPathFile( try wip_errors.addZirErrorMessages(zir, tree, source_code, file_path); var error_bundle = try wip_errors.toOwnedBundle(""); defer error_bundle.deinit(gpa); - error_bundle.renderToStdErr(.{}, fmt.color); + try error_bundle.renderToStderr(io, .{}, fmt.color); fmt.any_error = true; } }, @@ -332,7 +334,7 @@ fn fmtPathFile( try wip_errors.addZoirErrorMessages(zoir, tree, source_code, file_path); var error_bundle = try wip_errors.toOwnedBundle(""); defer error_bundle.deinit(gpa); - error_bundle.renderToStdErr(.{}, fmt.color); + try error_bundle.renderToStderr(io, .{}, fmt.color); fmt.any_error = true; } }, @@ -353,11 +355,11 @@ fn fmtPathFile( try fmt.stdout_writer.interface.print("{s}\n", .{file_path}); fmt.any_error = true; } else { - var af = try dir.atomicFile(sub_path, .{ .mode = stat.mode, .write_buffer = &.{} }); - defer af.deinit(); + var af = try dir.createFileAtomic(io, sub_path, .{ .permissions = stat.permissions, .replace = true }); + defer af.deinit(io); - try af.file_writer.interface.writeAll(fmt.out_buffer.written()); - try af.finish(); + try af.file.writeStreamingAll(io, fmt.out_buffer.written()); + try af.replace(io); try fmt.stdout_writer.interface.print("{s}\n", .{file_path}); } } @@ -368,7 +370,7 @@ pub fn main() !void { var arena_instance = std.heap.ArenaAllocator.init(gpa); const arena = arena_instance.allocator(); const args = try process.argsAlloc(arena); - var threaded: std.Io.Threaded = .init(gpa); + var threaded: std.Io.Threaded = .init(gpa, .{}); defer threaded.deinit(); const io = threaded.io(); return run(gpa, arena, io, args[1..]); diff --git a/src/introspect.zig b/src/introspect.zig index 8467b566c6eb..fa04e7de58a1 100644 --- a/src/introspect.zig +++ b/src/introspect.zig @@ -1,53 +1,57 @@ -const std = @import("std"); const builtin = @import("builtin"); + +const std = @import("std"); +const Io = std.Io; +const Dir = std.Io.Dir; const mem = std.mem; -const Allocator = mem.Allocator; -const os = std.os; -const fs = std.fs; +const Allocator = std.mem.Allocator; const Cache = std.Build.Cache; +const assert = std.debug.assert; + +const build_options = @import("build_options"); + const Compilation = @import("Compilation.zig"); const Package = @import("Package.zig"); -const build_options = @import("build_options"); /// Returns the sub_path that worked, or `null` if none did. /// The path of the returned Directory is relative to `base`. /// The handle of the returned Directory is open. -fn testZigInstallPrefix(base_dir: fs.Dir) ?Cache.Directory { - const test_index_file = "std" ++ fs.path.sep_str ++ "std.zig"; +fn testZigInstallPrefix(io: Io, base_dir: Io.Dir) ?Cache.Directory { + const test_index_file = "std" ++ Dir.path.sep_str ++ "std.zig"; zig_dir: { // Try lib/zig/std/std.zig - const lib_zig = "lib" ++ fs.path.sep_str ++ "zig"; - var test_zig_dir = base_dir.openDir(lib_zig, .{}) catch break :zig_dir; - const file = test_zig_dir.openFile(test_index_file, .{}) catch { - test_zig_dir.close(); + const lib_zig = "lib" ++ Dir.path.sep_str ++ "zig"; + var test_zig_dir = base_dir.openDir(io, lib_zig, .{}) catch break :zig_dir; + const file = test_zig_dir.openFile(io, test_index_file, .{}) catch { + test_zig_dir.close(io); break :zig_dir; }; - file.close(); + file.close(io); return .{ .handle = test_zig_dir, .path = lib_zig }; } // Try lib/std/std.zig - var test_zig_dir = base_dir.openDir("lib", .{}) catch return null; - const file = test_zig_dir.openFile(test_index_file, .{}) catch { - test_zig_dir.close(); + var test_zig_dir = base_dir.openDir(io, "lib", .{}) catch return null; + const file = test_zig_dir.openFile(io, test_index_file, .{}) catch { + test_zig_dir.close(io); return null; }; - file.close(); + file.close(io); return .{ .handle = test_zig_dir, .path = "lib" }; } /// Both the directory handle and the path are newly allocated resources which the caller now owns. -pub fn findZigLibDir(gpa: Allocator) !Cache.Directory { +pub fn findZigLibDir(gpa: Allocator, io: Io) !Cache.Directory { const cwd_path = try getResolvedCwd(gpa); defer gpa.free(cwd_path); - const self_exe_path = try fs.selfExePathAlloc(gpa); + const self_exe_path = try std.process.executablePathAlloc(io, gpa); defer gpa.free(self_exe_path); - return findZigLibDirFromSelfExe(gpa, cwd_path, self_exe_path); + return findZigLibDirFromSelfExe(gpa, io, cwd_path, self_exe_path); } -/// Like `std.process.getCwdAlloc`, but also resolves the path with `std.fs.path.resolve`. This +/// Like `std.process.getCwdAlloc`, but also resolves the path with `Dir.path.resolve`. This /// means the path has no repeated separators, no "." or ".." components, and no trailing separator. /// On WASI, "" is returned instead of ".". pub fn getResolvedCwd(gpa: Allocator) error{ @@ -59,33 +63,34 @@ pub fn getResolvedCwd(gpa: Allocator) error{ if (std.debug.runtime_safety) { const cwd = try std.process.getCwdAlloc(gpa); defer gpa.free(cwd); - std.debug.assert(mem.eql(u8, cwd, ".")); + assert(mem.eql(u8, cwd, ".")); } return ""; } const cwd = try std.process.getCwdAlloc(gpa); defer gpa.free(cwd); - const resolved = try fs.path.resolve(gpa, &.{cwd}); - std.debug.assert(fs.path.isAbsolute(resolved)); + const resolved = try Dir.path.resolve(gpa, &.{cwd}); + assert(Dir.path.isAbsolute(resolved)); return resolved; } /// Both the directory handle and the path are newly allocated resources which the caller now owns. pub fn findZigLibDirFromSelfExe( allocator: Allocator, + io: Io, /// The return value of `getResolvedCwd`. /// Passed as an argument to avoid pointlessly repeating the call. cwd_path: []const u8, self_exe_path: []const u8, ) error{ OutOfMemory, FileNotFound }!Cache.Directory { - const cwd = fs.cwd(); + const cwd = Io.Dir.cwd(); var cur_path: []const u8 = self_exe_path; - while (fs.path.dirname(cur_path)) |dirname| : (cur_path = dirname) { - var base_dir = cwd.openDir(dirname, .{}) catch continue; - defer base_dir.close(); + while (Dir.path.dirname(cur_path)) |dirname| : (cur_path = dirname) { + var base_dir = cwd.openDir(io, dirname, .{}) catch continue; + defer base_dir.close(io); - const sub_directory = testZigInstallPrefix(base_dir) orelse continue; - const p = try fs.path.join(allocator, &.{ dirname, sub_directory.path.? }); + const sub_directory = testZigInstallPrefix(io, base_dir) orelse continue; + const p = try Dir.path.join(allocator, &.{ dirname, sub_directory.path.? }); defer allocator.free(p); const resolved = try resolvePath(allocator, cwd_path, &.{p}); @@ -97,30 +102,35 @@ pub fn findZigLibDirFromSelfExe( return error.FileNotFound; } -/// Caller owns returned memory. -pub fn resolveGlobalCacheDir(allocator: Allocator) ![]u8 { - if (builtin.os.tag == .wasi) - @compileError("on WASI the global cache dir must be resolved with preopens"); +pub fn resolveGlobalCacheDir(arena: Allocator, environ_map: *const std.process.Environ.Map) ![]const u8 { + if (std.zig.EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map)) |value| return value; - if (try std.zig.EnvVar.ZIG_GLOBAL_CACHE_DIR.get(allocator)) |value| return value; + const app_name = "zig"; - const appname = "zig"; - - if (builtin.os.tag != .windows) { - if (std.zig.EnvVar.XDG_CACHE_HOME.getPosix()) |cache_root| { - if (cache_root.len > 0) { - return fs.path.join(allocator, &.{ cache_root, appname }); + switch (builtin.os.tag) { + .wasi => @compileError("on WASI the global cache dir must be resolved with preopens"), + .windows => { + const local_app_data_dir = std.zig.EnvVar.LOCALAPPDATA.get(environ_map) orelse + return error.AppDataDirUnavailable; + return Dir.path.join(arena, &.{ local_app_data_dir, app_name }); + }, + else => { + if (std.zig.EnvVar.XDG_CACHE_HOME.get(environ_map)) |cache_root| { + if (cache_root.len > 0) { + return Dir.path.join(arena, &.{ cache_root, app_name }); + } } - } - if (std.zig.EnvVar.HOME.getPosix()) |home| { - return fs.path.join(allocator, &.{ home, ".cache", appname }); - } + if (std.zig.EnvVar.HOME.get(environ_map)) |home| { + if (home.len > 0) { + return Dir.path.join(arena, &.{ home, ".cache", app_name }); + } + } + return error.AppDataDirUnavailable; + }, } - - return fs.getAppDataDir(allocator, appname); } -/// Similar to `fs.path.resolve`, but converts to a cwd-relative path, or, if that would +/// Similar to `Dir.path.resolve`, but converts to a cwd-relative path, or, if that would /// start with a relative up-dir (".."), an absolute path based on the cwd. Also, the cwd /// returns the empty string ("") instead of ".". pub fn resolvePath( @@ -131,8 +141,8 @@ pub fn resolvePath( paths: []const []const u8, ) Allocator.Error![]u8 { if (builtin.target.os.tag == .wasi) { - std.debug.assert(mem.eql(u8, cwd_resolved, "")); - const res = try fs.path.resolve(gpa, paths); + assert(mem.eql(u8, cwd_resolved, "")); + const res = try Dir.path.resolve(gpa, paths); if (mem.eql(u8, res, ".")) { gpa.free(res); return ""; @@ -142,17 +152,17 @@ pub fn resolvePath( // Heuristic for a fast path: if no component is absolute and ".." never appears, we just need to resolve `paths`. for (paths) |p| { - if (fs.path.isAbsolute(p)) break; // absolute path + if (Dir.path.isAbsolute(p)) break; // absolute path if (mem.indexOf(u8, p, "..") != null) break; // may contain up-dir } else { // no absolute path, no "..". - const res = try fs.path.resolve(gpa, paths); + const res = try Dir.path.resolve(gpa, paths); if (mem.eql(u8, res, ".")) { gpa.free(res); return ""; } - std.debug.assert(!fs.path.isAbsolute(res)); - std.debug.assert(!isUpDir(res)); + assert(!Dir.path.isAbsolute(res)); + assert(!isUpDir(res)); return res; } @@ -160,19 +170,19 @@ pub fn resolvePath( // Optimization: `paths` often has just one element. const path_resolved = switch (paths.len) { 0 => unreachable, - 1 => try fs.path.resolve(gpa, &.{ cwd_resolved, paths[0] }), + 1 => try Dir.path.resolve(gpa, &.{ cwd_resolved, paths[0] }), else => r: { const all_paths = try gpa.alloc([]const u8, paths.len + 1); defer gpa.free(all_paths); all_paths[0] = cwd_resolved; @memcpy(all_paths[1..], paths); - break :r try fs.path.resolve(gpa, all_paths); + break :r try Dir.path.resolve(gpa, all_paths); }, }; errdefer gpa.free(path_resolved); - std.debug.assert(fs.path.isAbsolute(path_resolved)); - std.debug.assert(fs.path.isAbsolute(cwd_resolved)); + assert(Dir.path.isAbsolute(path_resolved)); + assert(Dir.path.isAbsolute(cwd_resolved)); if (!std.mem.startsWith(u8, path_resolved, cwd_resolved)) return path_resolved; // not in cwd if (path_resolved.len == cwd_resolved.len) { @@ -180,7 +190,7 @@ pub fn resolvePath( gpa.free(path_resolved); return ""; } - if (path_resolved[cwd_resolved.len] != std.fs.path.sep) return path_resolved; // not in cwd (last component differs) + if (path_resolved[cwd_resolved.len] != Dir.path.sep) return path_resolved; // not in cwd (last component differs) // in cwd; extract sub path const sub_path = try gpa.dupe(u8, path_resolved[cwd_resolved.len + 1 ..]); @@ -188,9 +198,8 @@ pub fn resolvePath( return sub_path; } -/// TODO move this to std.fs.path pub fn isUpDir(p: []const u8) bool { - return mem.startsWith(u8, p, "..") and (p.len == 2 or p[2] == fs.path.sep); + return mem.startsWith(u8, p, "..") and (p.len == 2 or p[2] == Dir.path.sep); } pub const default_local_zig_cache_basename = ".zig-cache"; @@ -198,15 +207,15 @@ pub const default_local_zig_cache_basename = ".zig-cache"; /// Searches upwards from `cwd` for a directory containing a `build.zig` file. /// If such a directory is found, returns the path to it joined to the `.zig_cache` name. /// Otherwise, returns `null`, indicating no suitable local cache location. -pub fn resolveSuitableLocalCacheDir(arena: Allocator, cwd: []const u8) Allocator.Error!?[]u8 { +pub fn resolveSuitableLocalCacheDir(arena: Allocator, io: Io, cwd: []const u8) Allocator.Error!?[]u8 { var cur_dir = cwd; while (true) { - const joined = try fs.path.join(arena, &.{ cur_dir, Package.build_zig_basename }); - if (fs.cwd().access(joined, .{})) |_| { - return try fs.path.join(arena, &.{ cur_dir, default_local_zig_cache_basename }); + const joined = try Dir.path.join(arena, &.{ cur_dir, Package.build_zig_basename }); + if (Io.Dir.cwd().access(io, joined, .{})) |_| { + return try Dir.path.join(arena, &.{ cur_dir, default_local_zig_cache_basename }); } else |err| switch (err) { error.FileNotFound => { - cur_dir = fs.path.dirname(cur_dir) orelse return null; + cur_dir = Dir.path.dirname(cur_dir) orelse return null; continue; }, else => return null, diff --git a/src/libs/freebsd.zig b/src/libs/freebsd.zig index ff32b4649a25..9ad7eb7e1a47 100644 --- a/src/libs/freebsd.zig +++ b/src/libs/freebsd.zig @@ -1,9 +1,9 @@ const std = @import("std"); +const Io = std.Io; const Allocator = std.mem.Allocator; const mem = std.mem; const log = std.log; -const fs = std.fs; -const path = fs.path; +const path = std.Io.Dir.path; const assert = std.debug.assert; const Version = std.SemanticVersion; const Path = std.Build.Cache.Path; @@ -139,10 +139,6 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre .path = "common" ++ path.sep_str ++ "crtbrand.S", .flags = acflags.items, }, - .{ - .path = "common" ++ path.sep_str ++ "crtend.c", - .flags = cflags.items, - }, .{ .path = "common" ++ path.sep_str ++ "feature_note.S", .flags = acflags.items, @@ -257,6 +253,12 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre pub const Lib = struct { name: []const u8, sover: u8, + added_in: ?Version = null, + + pub fn getSoVersion(lib: Lib, os: *const std.Target.Os) u8 { + if (std.mem.eql(u8, lib.name, "util") and os.version_range.semver.min.major >= 15) return 10; + return lib.sover; + } }; pub const libs = [_]Lib{ @@ -269,6 +271,7 @@ pub const libs = [_]Lib{ .{ .name = "ld", .sover = 1 }, .{ .name = "util", .sover = 9 }, .{ .name = "execinfo", .sover = 1 }, + .{ .name = "sys", .sover = 7, .added_in = .{ .major = 15, .minor = 0, .patch = 0 } }, }; pub const ABI = struct { @@ -398,8 +401,8 @@ pub const BuiltSharedObjects = struct { lock: Cache.Lock, dir_path: Path, - pub fn deinit(self: *BuiltSharedObjects, gpa: Allocator) void { - self.lock.release(); + pub fn deinit(self: *BuiltSharedObjects, gpa: Allocator, io: Io) void { + self.lock.release(io); gpa.free(self.dir_path.sub_path); self.* = undefined; } @@ -434,25 +437,27 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye const target = comp.getTarget(); // FreeBSD 7 == FBSD_1.0, ..., FreeBSD 14 == FBSD_1.7 - const target_version: Version = .{ .major = 1, .minor = target.os.version_range.semver.min.major - 7, .patch = 0 }; + const target_os_version: Version = target.os.version_range.semver.min; + const target_libc_version: Version = .{ .major = 1, .minor = target_os_version.major - 7, .patch = 0 }; // Use the global cache directory. var cache: Cache = .{ .gpa = gpa, .io = io, - .manifest_dir = try comp.dirs.global_cache.handle.makeOpenPath("h", .{}), + .manifest_dir = try comp.dirs.global_cache.handle.createDirPathOpen(io, "h", .{}), + .cwd = comp.dirs.cwd, }; - cache.addPrefix(.{ .path = null, .handle = fs.cwd() }); + cache.addPrefix(.{ .path = null, .handle = Io.Dir.cwd() }); cache.addPrefix(comp.dirs.zig_lib); cache.addPrefix(comp.dirs.global_cache); - defer cache.manifest_dir.close(); + defer cache.manifest_dir.close(io); var man = cache.obtain(); defer man.deinit(); man.hash.addBytes(build_options.version); man.hash.add(target.cpu.arch); man.hash.add(target.abi); - man.hash.add(target_version); + man.hash.add(target_os_version); const full_abilists_path = try comp.dirs.zig_lib.join(arena, &.{abilists_path}); const abilists_index = try man.addFile(full_abilists_path, abilists_max_size); @@ -464,7 +469,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye .lock = man.toOwnedLock(), .dir_path = .{ .root_dir = comp.dirs.global_cache, - .sub_path = try gpa.dupe(u8, "o" ++ fs.path.sep_str ++ digest), + .sub_path = try gpa.dupe(u8, "o" ++ path.sep_str ++ digest), }, }); } @@ -473,10 +478,10 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye const o_sub_path = try path.join(arena, &[_][]const u8{ "o", &digest }); var o_directory: Cache.Directory = .{ - .handle = try comp.dirs.global_cache.handle.makeOpenPath(o_sub_path, .{}), + .handle = try comp.dirs.global_cache.handle.createDirPathOpen(io, o_sub_path, .{}), .path = try comp.dirs.global_cache.join(arena, &.{o_sub_path}), }; - defer o_directory.handle.close(); + defer o_directory.handle.close(io); const abilists_contents = man.files.keys()[abilists_index].contents.?; const metadata = try loadMetaData(gpa, abilists_contents); @@ -494,19 +499,19 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye }; const target_ver_index = for (metadata.all_versions, 0..) |ver, i| { - switch (ver.order(target_version)) { + switch (ver.order(target_libc_version)) { .eq => break i, .lt => continue, .gt => { // TODO Expose via compile error mechanism instead of log. - log.warn("invalid target FreeBSD libc version: {f}", .{target_version}); + log.warn("invalid target FreeBSD libc version: {f}", .{target_libc_version}); return error.InvalidTargetLibCVersion; }, } } else blk: { const latest_index = metadata.all_versions.len - 1; log.warn("zig cannot build new FreeBSD libc version {f}; providing instead {f}", .{ - target_version, metadata.all_versions[latest_index], + target_libc_version, metadata.all_versions[latest_index], }); break :blk latest_index; }; @@ -516,7 +521,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye for (metadata.all_versions[0 .. target_ver_index + 1]) |ver| { try map_contents.print("FBSD_{d}.{d} {{ }};\n", .{ ver.major, ver.minor }); } - try o_directory.handle.writeFile(.{ .sub_path = all_map_basename, .data = map_contents.items }); + try o_directory.handle.writeFile(io, .{ .sub_path = all_map_basename, .data = map_contents.items }); map_contents.deinit(); } @@ -524,6 +529,11 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye defer stubs_asm.deinit(); for (libs, 0..) |lib, lib_i| { + if (lib.added_in) |add_in| { + // Note: Compare OS version, not libc version. + if (target.os.version_range.semver.min.order(add_in) == .lt) continue; + } + stubs_asm.shrinkRetainingCapacity(0); try stubs_asm.appendSlice(".text\n"); @@ -965,7 +975,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye var lib_name_buf: [32]u8 = undefined; // Larger than each of the names "c", "stdthreads", etc. const asm_file_basename = std.fmt.bufPrint(&lib_name_buf, "{s}.s", .{lib.name}) catch unreachable; - try o_directory.handle.writeFile(.{ .sub_path = asm_file_basename, .data = stubs_asm.items }); + try o_directory.handle.writeFile(io, .{ .sub_path = asm_file_basename, .data = stubs_asm.items }); try buildSharedLib(comp, arena, o_directory, asm_file_basename, lib, prog_node); } @@ -977,12 +987,16 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye .lock = man.toOwnedLock(), .dir_path = .{ .root_dir = comp.dirs.global_cache, - .sub_path = try gpa.dupe(u8, "o" ++ fs.path.sep_str ++ digest), + .sub_path = try gpa.dupe(u8, "o" ++ path.sep_str ++ digest), }, }); } -fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void { +fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) std.Io.Cancelable!void { + const io = comp.io; + const target = comp.getTarget(); + const target_os_version = target.os.version_range.semver.min; + assert(comp.freebsd_so_files == null); comp.freebsd_so_files = so_files; @@ -990,14 +1004,18 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void { var task_buffer_i: usize = 0; { - comp.mutex.lock(); // protect comp.arena - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); // protect comp.arena + defer comp.mutex.unlock(io); for (libs) |lib| { + if (lib.added_in) |add_in| { + if (target_os_version.order(add_in) == .lt) continue; + } + const so_path: Path = .{ .root_dir = so_files.dir_path.root_dir, .sub_path = std.fmt.allocPrint(comp.arena, "{s}{c}lib{s}.so.{d}", .{ - so_files.dir_path.sub_path, fs.path.sep, lib.name, lib.sover, + so_files.dir_path.sub_path, path.sep, lib.name, lib.getSoVersion(&target.os), }) catch return comp.setAllocFailure(), }; task_buffer[task_buffer_i] = .{ .load_dso = so_path }; @@ -1005,7 +1023,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void { } } - comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]); + try comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]); } fn buildSharedLib( @@ -1019,10 +1037,13 @@ fn buildSharedLib( const tracy = trace(@src()); defer tracy.end(); + const target = comp.getTarget(); + const io = comp.io; - const basename = try std.fmt.allocPrint(arena, "lib{s}.so.{d}", .{ lib.name, lib.sover }); - const version: Version = .{ .major = lib.sover, .minor = 0, .patch = 0 }; - const ld_basename = path.basename(comp.getTarget().standardDynamicLinkerPath().get().?); + const sover = lib.getSoVersion(&target.os); + const basename = try std.fmt.allocPrint(arena, "lib{s}.so.{d}", .{ lib.name, sover }); + const version: Version = .{ .major = sover, .minor = 0, .patch = 0 }; + const ld_basename = path.basename(target.standardDynamicLinkerPath().get().?); const soname = if (mem.eql(u8, lib.name, "ld")) ld_basename else basename; const map_file_path = try path.join(arena, &.{ bin_directory.path.?, all_map_basename }); @@ -1075,8 +1096,8 @@ fn buildSharedLib( var sub_create_diag: Compilation.CreateDiagnostic = undefined; const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{ + .thread_limit = comp.thread_limit, .dirs = comp.dirs.withoutLocalCache(), - .thread_pool = comp.thread_pool, .self_exe_path = comp.self_exe_path, // Because we manually cache the whole set of objects, we don't cache the individual objects // within it. In fact, we *can't* do that, because we need `emit_bin` to specify the path. @@ -1099,6 +1120,7 @@ fn buildSharedLib( .soname = soname, .c_source_files = &c_source_files, .skip_linker_dependencies = true, + .environ_map = comp.environ_map, }) catch |err| switch (err) { error.CreateFail => { comp.lockAndSetMiscFailure(misc_task, "sub-compilation of {t} failed: {f}", .{ misc_task, sub_create_diag }); diff --git a/src/libs/glibc.zig b/src/libs/glibc.zig index 76048239e014..10e8446fa4eb 100644 --- a/src/libs/glibc.zig +++ b/src/libs/glibc.zig @@ -1,9 +1,9 @@ const std = @import("std"); +const Io = std.Io; const Allocator = std.mem.Allocator; const mem = std.mem; const log = std.log; -const fs = std.fs; -const path = fs.path; +const path = std.Io.Dir.path; const assert = std.debug.assert; const Version = std.SemanticVersion; const Path = std.Build.Cache.Path; @@ -640,8 +640,8 @@ pub const BuiltSharedObjects = struct { lock: Cache.Lock, dir_path: Path, - pub fn deinit(self: *BuiltSharedObjects, gpa: Allocator) void { - self.lock.release(); + pub fn deinit(self: *BuiltSharedObjects, gpa: Allocator, io: Io) void { + self.lock.release(io); gpa.free(self.dir_path.sub_path); self.* = undefined; } @@ -679,12 +679,13 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye var cache: Cache = .{ .gpa = gpa, .io = io, - .manifest_dir = try comp.dirs.global_cache.handle.makeOpenPath("h", .{}), + .manifest_dir = try comp.dirs.global_cache.handle.createDirPathOpen(io, "h", .{}), + .cwd = comp.dirs.cwd, }; - cache.addPrefix(.{ .path = null, .handle = fs.cwd() }); + cache.addPrefix(.{ .path = null, .handle = Io.Dir.cwd() }); cache.addPrefix(comp.dirs.zig_lib); cache.addPrefix(comp.dirs.global_cache); - defer cache.manifest_dir.close(); + defer cache.manifest_dir.close(io); var man = cache.obtain(); defer man.deinit(); @@ -703,7 +704,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye .lock = man.toOwnedLock(), .dir_path = .{ .root_dir = comp.dirs.global_cache, - .sub_path = try gpa.dupe(u8, "o" ++ fs.path.sep_str ++ digest), + .sub_path = try gpa.dupe(u8, "o" ++ path.sep_str ++ digest), }, }); } @@ -712,10 +713,10 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye const o_sub_path = try path.join(arena, &[_][]const u8{ "o", &digest }); var o_directory: Cache.Directory = .{ - .handle = try comp.dirs.global_cache.handle.makeOpenPath(o_sub_path, .{}), + .handle = try comp.dirs.global_cache.handle.createDirPathOpen(io, o_sub_path, .{}), .path = try comp.dirs.global_cache.join(arena, &.{o_sub_path}), }; - defer o_directory.handle.close(); + defer o_directory.handle.close(io); const abilists_contents = man.files.keys()[abilists_index].contents.?; const metadata = try loadMetaData(gpa, abilists_contents); @@ -759,7 +760,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye try map_contents.print("GLIBC_{d}.{d}.{d} {{ }};\n", .{ ver.major, ver.minor, ver.patch }); } } - try o_directory.handle.writeFile(.{ .sub_path = all_map_basename, .data = map_contents.items }); + try o_directory.handle.writeFile(io, .{ .sub_path = all_map_basename, .data = map_contents.items }); map_contents.deinit(); // The most recent allocation of an arena can be freed :) } @@ -775,7 +776,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye try stubs_asm.appendSlice(".text\n"); var sym_i: usize = 0; - var sym_name_buf: std.Io.Writer.Allocating = .init(arena); + var sym_name_buf: Io.Writer.Allocating = .init(arena); var opt_symbol_name: ?[]const u8 = null; var versions_buffer: [32]u8 = undefined; var versions_len: usize = undefined; @@ -796,7 +797,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye // twice, which causes a "duplicate symbol" assembler error. var versions_written = std.AutoArrayHashMap(Version, void).init(arena); - var inc_reader: std.Io.Reader = .fixed(metadata.inclusions); + var inc_reader: Io.Reader = .fixed(metadata.inclusions); const fn_inclusions_len = try inc_reader.takeInt(u16, .little); @@ -1118,7 +1119,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye var lib_name_buf: [32]u8 = undefined; // Larger than each of the names "c", "pthread", etc. const asm_file_basename = std.fmt.bufPrint(&lib_name_buf, "{s}.s", .{lib.name}) catch unreachable; - try o_directory.handle.writeFile(.{ .sub_path = asm_file_basename, .data = stubs_asm.items }); + try o_directory.handle.writeFile(io, .{ .sub_path = asm_file_basename, .data = stubs_asm.items }); try buildSharedLib(comp, arena, o_directory, asm_file_basename, lib, prog_node); } @@ -1130,12 +1131,13 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye .lock = man.toOwnedLock(), .dir_path = .{ .root_dir = comp.dirs.global_cache, - .sub_path = try gpa.dupe(u8, "o" ++ fs.path.sep_str ++ digest), + .sub_path = try gpa.dupe(u8, "o" ++ path.sep_str ++ digest), }, }); } -fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void { +fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) std.Io.Cancelable!void { + const io = comp.io; const target_version = comp.getTarget().os.versionRange().gnuLibCVersion().?; assert(comp.glibc_so_files == null); @@ -1145,8 +1147,8 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void { var task_buffer_i: usize = 0; { - comp.mutex.lock(); // protect comp.arena - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); // protect comp.arena + defer comp.mutex.unlock(io); for (libs) |lib| { if (lib.removed_in) |rem_in| { @@ -1155,7 +1157,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void { const so_path: Path = .{ .root_dir = so_files.dir_path.root_dir, .sub_path = std.fmt.allocPrint(comp.arena, "{s}{c}lib{s}.so.{d}", .{ - so_files.dir_path.sub_path, fs.path.sep, lib.name, lib.sover, + so_files.dir_path.sub_path, path.sep, lib.name, lib.sover, }) catch return comp.setAllocFailure(), }; task_buffer[task_buffer_i] = .{ .load_dso = so_path }; @@ -1163,7 +1165,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void { } } - comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]); + try comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]); } fn buildSharedLib( @@ -1233,8 +1235,8 @@ fn buildSharedLib( var sub_create_diag: Compilation.CreateDiagnostic = undefined; const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{ + .thread_limit = comp.thread_limit, .dirs = comp.dirs.withoutLocalCache(), - .thread_pool = comp.thread_pool, .self_exe_path = comp.self_exe_path, // Because we manually cache the whole set of objects, we don't cache the individual objects // within it. In fact, we *can't* do that, because we need `emit_bin` to specify the path. @@ -1257,6 +1259,7 @@ fn buildSharedLib( .soname = soname, .c_source_files = &c_source_files, .skip_linker_dependencies = true, + .environ_map = comp.environ_map, }) catch |err| switch (err) { error.CreateFail => { comp.lockAndSetMiscFailure(misc_task, "sub-compilation of {t} failed: {f}", .{ misc_task, sub_create_diag }); diff --git a/src/libs/libcxx.zig b/src/libs/libcxx.zig index 405a06ba59cc..316ac6d815b3 100644 --- a/src/libs/libcxx.zig +++ b/src/libs/libcxx.zig @@ -106,7 +106,7 @@ pub const BuildError = error{ OutOfMemory, AlreadyReported, ZigCompilerNotBuiltWithLLVMExtensions, -}; +} || std.Io.Cancelable; pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!void { if (!build_options.have_llvm) { @@ -256,15 +256,17 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError! var sub_create_diag: Compilation.CreateDiagnostic = undefined; const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{ + .thread_limit = comp.thread_limit, .dirs = comp.dirs.withoutLocalCache(), .self_exe_path = comp.self_exe_path, .cache_mode = .whole, .config = config, .root_mod = root_mod, .root_name = root_name, - .thread_pool = comp.thread_pool, .libc_installation = comp.libc_installation, .emit_bin = .yes_cache, + .function_sections = true, + .data_sections = true, .c_source_files = c_source_files.items, .verbose_cc = comp.verbose_cc, .verbose_link = comp.verbose_link, @@ -275,6 +277,7 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError! .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .clang_passthrough_mode = comp.clang_passthrough_mode, .skip_linker_dependencies = true, + .environ_map = comp.environ_map, }) catch |err| { switch (err) { else => comp.lockAndSetMiscFailure(misc_task, "unable to build libc++: create compilation failed: {t}", .{err}), @@ -295,7 +298,7 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError! assert(comp.libcxx_static_lib == null); const crt_file = try sub_compilation.toCrtFile(); comp.libcxx_static_lib = crt_file; - comp.queuePrelinkTaskMode(crt_file.full_object_path, &config); + try comp.queuePrelinkTaskMode(crt_file.full_object_path, &config); } pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildError!void { @@ -449,15 +452,17 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr var sub_create_diag: Compilation.CreateDiagnostic = undefined; const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{ + .thread_limit = comp.thread_limit, .dirs = comp.dirs.withoutLocalCache(), .self_exe_path = comp.self_exe_path, .cache_mode = .whole, .config = config, .root_mod = root_mod, .root_name = root_name, - .thread_pool = comp.thread_pool, .libc_installation = comp.libc_installation, .emit_bin = .yes_cache, + .function_sections = true, + .data_sections = true, .c_source_files = c_source_files.items, .verbose_cc = comp.verbose_cc, .verbose_link = comp.verbose_link, @@ -468,6 +473,7 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .clang_passthrough_mode = comp.clang_passthrough_mode, .skip_linker_dependencies = true, + .environ_map = comp.environ_map, }) catch |err| { switch (err) { else => comp.lockAndSetMiscFailure(misc_task, "unable to build libc++abi: create compilation failed: {t}", .{err}), @@ -492,7 +498,7 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr assert(comp.libcxxabi_static_lib == null); const crt_file = try sub_compilation.toCrtFile(); comp.libcxxabi_static_lib = crt_file; - comp.queuePrelinkTaskMode(crt_file.full_object_path, &config); + try comp.queuePrelinkTaskMode(crt_file.full_object_path, &config); } pub fn addCxxArgs( diff --git a/src/libs/libtsan.zig b/src/libs/libtsan.zig index 541d2bab3c83..c9dcf609537b 100644 --- a/src/libs/libtsan.zig +++ b/src/libs/libtsan.zig @@ -11,7 +11,7 @@ pub const BuildError = error{ AlreadyReported, ZigCompilerNotBuiltWithLLVMExtensions, TSANUnsupportedCPUArchitecture, -}; +} || std.Io.Cancelable; pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!void { if (!build_options.have_llvm) { @@ -279,8 +279,8 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo var sub_create_diag: Compilation.CreateDiagnostic = undefined; const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{ + .thread_limit = comp.thread_limit, .dirs = comp.dirs.withoutLocalCache(), - .thread_pool = comp.thread_pool, .self_exe_path = comp.self_exe_path, .cache_mode = .whole, .config = config, @@ -288,6 +288,8 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo .root_name = root_name, .libc_installation = comp.libc_installation, .emit_bin = .yes_cache, + .function_sections = true, + .data_sections = true, .c_source_files = c_source_files.items, .verbose_cc = comp.verbose_cc, .verbose_link = comp.verbose_link, @@ -301,6 +303,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo .linker_allow_shlib_undefined = linker_allow_shlib_undefined, .install_name = install_name, .headerpad_size = headerpad_size, + .environ_map = comp.environ_map, }) catch |err| { switch (err) { else => comp.lockAndSetMiscFailure(misc_task, "unable to build {t}: create compilation failed: {t}", .{ misc_task, err }), @@ -319,7 +322,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo }; const crt_file = try sub_compilation.toCrtFile(); - comp.queuePrelinkTaskMode(crt_file.full_object_path, &config); + try comp.queuePrelinkTaskMode(crt_file.full_object_path, &config); assert(comp.tsan_lib == null); comp.tsan_lib = crt_file; } diff --git a/src/libs/libunwind.zig b/src/libs/libunwind.zig index 26b8ae59b44f..c1437d39bd0c 100644 --- a/src/libs/libunwind.zig +++ b/src/libs/libunwind.zig @@ -12,7 +12,7 @@ pub const BuildError = error{ OutOfMemory, AlreadyReported, ZigCompilerNotBuiltWithLLVMExtensions, -}; +} || std.Io.Cancelable; pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildError!void { if (!build_options.have_llvm) { @@ -145,6 +145,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr var sub_create_diag: Compilation.CreateDiagnostic = undefined; const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{ + .thread_limit = comp.thread_limit, .dirs = comp.dirs.withoutLocalCache(), .self_exe_path = comp.self_exe_path, .config = config, @@ -152,10 +153,10 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr .cache_mode = .whole, .root_name = root_name, .main_mod = null, - .thread_pool = comp.thread_pool, .libc_installation = comp.libc_installation, .emit_bin = .yes_cache, - .function_sections = comp.function_sections, + .function_sections = true, + .data_sections = true, .c_source_files = &c_source_files, .verbose_cc = comp.verbose_cc, .verbose_link = comp.verbose_link, @@ -166,6 +167,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .clang_passthrough_mode = comp.clang_passthrough_mode, .skip_linker_dependencies = true, + .environ_map = comp.environ_map, }) catch |err| { switch (err) { else => comp.lockAndSetMiscFailure(misc_task, "unable to build {t}: create compilation failed: {t}", .{ misc_task, err }), @@ -184,7 +186,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr }; const crt_file = try sub_compilation.toCrtFile(); - comp.queuePrelinkTaskMode(crt_file.full_object_path, &config); + try comp.queuePrelinkTaskMode(crt_file.full_object_path, &config); assert(comp.libunwind_static_lib == null); comp.libunwind_static_lib = crt_file; } diff --git a/src/libs/mingw.zig b/src/libs/mingw.zig index b706d3d4576c..62e451acfb07 100644 --- a/src/libs/mingw.zig +++ b/src/libs/mingw.zig @@ -1,7 +1,8 @@ const std = @import("std"); +const Io = std.Io; const Allocator = std.mem.Allocator; const mem = std.mem; -const path = std.fs.path; +const path = std.Io.Dir.path; const assert = std.debug.assert; const log = std.log.scoped(.mingw); @@ -55,6 +56,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre }, }; return comp.build_crt_file("crt2", .Obj, .@"mingw-w64 crt2.o", prog_node, &files, .{ + .function_sections = false, // https://codeberg.org/ziglang/zig/issues/30702 .unwind_tables = unwind_tables, }); }, @@ -241,7 +243,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - const def_file_path = findDef(arena, comp.getTarget(), comp.dirs.zig_lib, lib_name) catch |err| switch (err) { + const def_file_path = findDef(arena, io, comp.getTarget(), comp.dirs.zig_lib, lib_name) catch |err| switch (err) { error.FileNotFound => { log.debug("no {s}.def file available to make a DLL import {s}.lib", .{ lib_name, lib_name }); // In this case we will end up putting foo.lib onto the linker line and letting the linker @@ -257,12 +259,13 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { var cache: Cache = .{ .gpa = gpa, .io = io, - .manifest_dir = try comp.dirs.global_cache.handle.makeOpenPath("h", .{}), + .manifest_dir = try comp.dirs.global_cache.handle.createDirPathOpen(io, "h", .{}), + .cwd = comp.dirs.cwd, }; - cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() }); + cache.addPrefix(.{ .path = null, .handle = Io.Dir.cwd() }); cache.addPrefix(comp.dirs.zig_lib); cache.addPrefix(comp.dirs.global_cache); - defer cache.manifest_dir.close(); + defer cache.manifest_dir.close(io); cache.hash.addBytes(build_options.version); cache.hash.addOptionalBytes(comp.dirs.zig_lib.path); @@ -281,8 +284,8 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { const sub_path = try std.fs.path.join(gpa, &.{ "o", &digest, final_lib_basename }); errdefer gpa.free(sub_path); - comp.mutex.lock(); - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); try comp.crt_files.ensureUnusedCapacity(gpa, 1); comp.crt_files.putAssumeCapacityNoClobber(final_lib_basename, .{ .full_object_path = .{ @@ -296,26 +299,32 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { const digest = man.final(); const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest }); - var o_dir = try comp.dirs.global_cache.handle.makeOpenPath(o_sub_path, .{}); - defer o_dir.close(); + var o_dir = try comp.dirs.global_cache.handle.createDirPathOpen(io, o_sub_path, .{}); + defer o_dir.close(io); const aro = @import("aro"); var diagnostics: aro.Diagnostics = .{ .output = .{ .to_list = .{ .arena = .init(gpa) } }, }; defer diagnostics.deinit(); - var aro_comp = aro.Compilation.init(gpa, arena, io, &diagnostics, std.fs.cwd()); + var aro_comp = aro.Compilation.init(gpa, arena, io, &diagnostics, Io.Dir.cwd()); defer aro_comp.deinit(); aro_comp.target = .fromZigTarget(target.*); const include_dir = try comp.dirs.zig_lib.join(arena, &.{ "libc", "mingw", "def-include" }); - if (comp.verbose_cc) print: { - var stderr, _ = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); - nosuspend stderr.print("def file: {s}\n", .{def_file_path}) catch break :print; - nosuspend stderr.print("include dir: {s}\n", .{include_dir}) catch break :print; + if (comp.verbose_cc) { + var buffer: [256]u8 = undefined; + const stderr = try io.lockStderr(&buffer, null); + defer io.unlockStderr(); + const w = &stderr.file_writer.interface; + w.print("def file: {s}\n", .{def_file_path}) catch |err| switch (err) { + error.WriteFailed => return stderr.file_writer.err.?, + }; + w.print("include dir: {s}\n", .{include_dir}) catch |err| switch (err) { + error.WriteFailed => return stderr.file_writer.err.?, + }; } try aro_comp.search_path.append(gpa, .{ .path = include_dir, .kind = .normal }); @@ -332,18 +341,21 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { if (aro_comp.diagnostics.output.to_list.messages.items.len != 0) { var buffer: [64]u8 = undefined; - const w, const ttyconf = std.debug.lockStderrWriter(&buffer); - defer std.debug.unlockStderrWriter(); + const stderr = try io.lockStderr(&buffer, null); + defer io.unlockStderr(); for (aro_comp.diagnostics.output.to_list.messages.items) |msg| { if (msg.kind == .@"fatal error" or msg.kind == .@"error") { - msg.write(w, ttyconf, true) catch {}; + msg.write(stderr.terminal(), true) catch |err| switch (err) { + error.WriteFailed => return stderr.file_writer.err.?, + error.Unexpected => |e| return e, + }; return error.AroPreprocessorFailed; } } } const members = members: { - var aw: std.Io.Writer.Allocating = .init(gpa); + var aw: Io.Writer.Allocating = .init(gpa); errdefer aw.deinit(); try pp.prettyPrintTokens(&aw.writer, .result_only); @@ -356,8 +368,9 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { error.OutOfMemory => |e| return e, error.ParseError => { var buffer: [64]u8 = undefined; - const w, _ = std.debug.lockStderrWriter(&buffer); - defer std.debug.unlockStderrWriter(); + const stderr = try io.lockStderr(&buffer, null); + defer io.unlockStderr(); + const w = &stderr.file_writer.interface; try w.writeAll("error: "); try def_diagnostics.writeMsg(w, input); try w.writeByte('\n'); @@ -376,10 +389,10 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { errdefer gpa.free(lib_final_path); { - const lib_final_file = try o_dir.createFile(final_lib_basename, .{ .truncate = true }); - defer lib_final_file.close(); + const lib_final_file = try o_dir.createFile(io, final_lib_basename, .{ .truncate = true }); + defer lib_final_file.close(io); var buffer: [1024]u8 = undefined; - var file_writer = lib_final_file.writer(&buffer); + var file_writer = lib_final_file.writer(io, &buffer); try implib.writeCoffArchive(gpa, &file_writer.interface, members); try file_writer.interface.flush(); } @@ -388,8 +401,8 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { log.warn("failed to write cache manifest for DLL import {s}.lib: {s}", .{ lib_name, @errorName(err) }); }; - comp.mutex.lock(); - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); try comp.crt_files.putNoClobber(gpa, final_lib_basename, .{ .full_object_path = .{ .root_dir = comp.dirs.global_cache, @@ -401,11 +414,12 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { pub fn libExists( allocator: Allocator, + io: Io, target: *const std.Target, zig_lib_directory: Cache.Directory, lib_name: []const u8, ) !bool { - const s = findDef(allocator, target, zig_lib_directory, lib_name) catch |err| switch (err) { + const s = findDef(allocator, io, target, zig_lib_directory, lib_name) catch |err| switch (err) { error.FileNotFound => return false, else => |e| return e, }; @@ -417,6 +431,7 @@ pub fn libExists( /// see if a .def file exists. fn findDef( allocator: Allocator, + io: Io, target: *const std.Target, zig_lib_directory: Cache.Directory, lib_name: []const u8, @@ -442,7 +457,7 @@ fn findDef( } else { try override_path.print(fmt_path, .{ lib_path, lib_name }); } - if (std.fs.cwd().access(override_path.items, .{})) |_| { + if (Io.Dir.cwd().access(io, override_path.items, .{})) |_| { return override_path.toOwnedSlice(); } else |err| switch (err) { error.FileNotFound => {}, @@ -459,7 +474,7 @@ fn findDef( } else { try override_path.print(fmt_path, .{lib_name}); } - if (std.fs.cwd().access(override_path.items, .{})) |_| { + if (Io.Dir.cwd().access(io, override_path.items, .{})) |_| { return override_path.toOwnedSlice(); } else |err| switch (err) { error.FileNotFound => {}, @@ -476,7 +491,7 @@ fn findDef( } else { try override_path.print(fmt_path, .{lib_name}); } - if (std.fs.cwd().access(override_path.items, .{})) |_| { + if (Io.Dir.cwd().access(io, override_path.items, .{})) |_| { return override_path.toOwnedSlice(); } else |err| switch (err) { error.FileNotFound => {}, @@ -595,9 +610,6 @@ const mingw32_generic_src = [_][]const u8{ "gdtoa" ++ path.sep_str ++ "sum.c", "gdtoa" ++ path.sep_str ++ "ulp.c", "math" ++ path.sep_str ++ "coshl.c", - "math" ++ path.sep_str ++ "fp_consts.c", - "math" ++ path.sep_str ++ "fp_constsf.c", - "math" ++ path.sep_str ++ "fp_constsl.c", "math" ++ path.sep_str ++ "fpclassify.c", "math" ++ path.sep_str ++ "fpclassifyf.c", "math" ++ path.sep_str ++ "fpclassifyl.c", @@ -984,9 +996,6 @@ const mingw32_x86_src = [_][]const u8{ const mingw32_x86_32_src = [_][]const u8{ // ucrtbase "math" ++ path.sep_str ++ "coshf.c", - "math" ++ path.sep_str ++ "expf.c", - "math" ++ path.sep_str ++ "log10f.c", - "math" ++ path.sep_str ++ "logf.c", "math" ++ path.sep_str ++ "modff.c", "math" ++ path.sep_str ++ "powf.c", "math" ++ path.sep_str ++ "sinhf.c", diff --git a/src/libs/mingw/def.zig b/src/libs/mingw/def.zig index 24dc95c13cc3..f1c112d16e0e 100644 --- a/src/libs/mingw/def.zig +++ b/src/libs/mingw/def.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; pub const ModuleDefinitionType = enum { mingw, @@ -663,7 +664,9 @@ test parse { \\ ; - try testParse(.AMD64, source, "foo.dll", &[_]ModuleDefinition.Export{ + const io = std.testing.io; + + try testParse(io, .AMD64, source, "foo.dll", &[_]ModuleDefinition.Export{ .{ .name = "foo", .mangled_symbol_name = null, @@ -743,7 +746,7 @@ test parse { }, }); - try testParse(.I386, source, "foo.dll", &[_]ModuleDefinition.Export{ + try testParse(io, .I386, source, "foo.dll", &[_]ModuleDefinition.Export{ .{ .name = "_foo", .mangled_symbol_name = null, @@ -823,7 +826,7 @@ test parse { }, }); - try testParse(.ARMNT, source, "foo.dll", &[_]ModuleDefinition.Export{ + try testParse(io, .ARMNT, source, "foo.dll", &[_]ModuleDefinition.Export{ .{ .name = "foo", .mangled_symbol_name = null, @@ -903,7 +906,7 @@ test parse { }, }); - try testParse(.ARM64, source, "foo.dll", &[_]ModuleDefinition.Export{ + try testParse(io, .ARM64, source, "foo.dll", &[_]ModuleDefinition.Export{ .{ .name = "foo", .mangled_symbol_name = null, @@ -997,7 +1000,9 @@ test "ntdll" { \\RtlActivateActivationContextUnsafeFast@0 ; - try testParse(.AMD64, source, "ntdll.dll", &[_]ModuleDefinition.Export{ + const io = std.testing.io; + + try testParse(io, .AMD64, source, "ntdll.dll", &[_]ModuleDefinition.Export{ .{ .name = "RtlDispatchAPC@12", .mangled_symbol_name = null, @@ -1023,15 +1028,22 @@ test "ntdll" { }); } -fn testParse(machine_type: std.coff.IMAGE.FILE.MACHINE, source: [:0]const u8, expected_module_name: []const u8, expected_exports: []const ModuleDefinition.Export) !void { +fn testParse( + io: Io, + machine_type: std.coff.IMAGE.FILE.MACHINE, + source: [:0]const u8, + expected_module_name: []const u8, + expected_exports: []const ModuleDefinition.Export, +) !void { var diagnostics: Diagnostics = undefined; const module = parse(std.testing.allocator, source, machine_type, .mingw, &diagnostics) catch |err| switch (err) { error.OutOfMemory => |e| return e, error.ParseError => { - const stderr, _ = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); - try diagnostics.writeMsg(stderr, source); - try stderr.writeByte('\n'); + const stderr = try io.lockStderr(&.{}, null); + defer io.unlockStderr(); + const w = &stderr.file_writer.interface; + try diagnostics.writeMsg(w, source); + try w.writeByte('\n'); return err; }, }; diff --git a/src/libs/musl.zig b/src/libs/musl.zig index 69bd892b3b12..b12088aae39b 100644 --- a/src/libs/musl.zig +++ b/src/libs/musl.zig @@ -43,8 +43,6 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro }, }; return comp.build_crt_file("crt1", .Obj, .@"musl crt1.o", prog_node, &files, .{ - .function_sections = true, - .data_sections = true, .omit_frame_pointer = true, .no_builtin = true, }); @@ -63,8 +61,6 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro }, }; return comp.build_crt_file("rcrt1", .Obj, .@"musl rcrt1.o", prog_node, &files, .{ - .function_sections = true, - .data_sections = true, .omit_frame_pointer = true, .pic = true, .no_builtin = true, @@ -84,8 +80,6 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro }, }; return comp.build_crt_file("Scrt1", .Obj, .@"musl Scrt1.o", prog_node, &files, .{ - .function_sections = true, - .data_sections = true, .omit_frame_pointer = true, .pic = true, .no_builtin = true, @@ -172,8 +166,6 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro }; } return comp.build_crt_file("c", .Lib, .@"musl libc.a", prog_node, c_source_files.items, .{ - .function_sections = true, - .data_sections = true, .omit_frame_pointer = true, .no_builtin = true, }); @@ -248,12 +240,12 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro var sub_create_diag: Compilation.CreateDiagnostic = undefined; const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{ + .thread_limit = comp.thread_limit, .dirs = comp.dirs.withoutLocalCache(), .self_exe_path = comp.self_exe_path, .cache_mode = .whole, .config = config, .root_mod = root_mod, - .thread_pool = comp.thread_pool, .root_name = "c", .libc_installation = comp.libc_installation, .emit_bin = .yes_cache, @@ -272,6 +264,7 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro }, .skip_linker_dependencies = true, .soname = "libc.so", + .environ_map = comp.environ_map, }) catch |err| switch (err) { error.CreateFail => { comp.lockAndSetMiscFailure(misc_task, "sub-compilation of {t} failed: {f}", .{ misc_task, sub_create_diag }); @@ -287,10 +280,10 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro errdefer comp.gpa.free(basename); const crt_file = try sub_compilation.toCrtFile(); - comp.queuePrelinkTaskMode(crt_file.full_object_path, &config); + try comp.queuePrelinkTaskMode(crt_file.full_object_path, &config); { - comp.mutex.lock(); - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); try comp.crt_files.ensureUnusedCapacity(comp.gpa, 1); comp.crt_files.putAssumeCapacityNoClobber(basename, crt_file); } @@ -899,13 +892,9 @@ const src_files = [_][]const u8{ "musl/src/math/exp10.c", "musl/src/math/exp10f.c", "musl/src/math/exp10l.c", - "musl/src/math/exp2.c", - "musl/src/math/exp2f.c", "musl/src/math/exp2f_data.c", "musl/src/math/exp2l.c", - "musl/src/math/exp.c", "musl/src/math/exp_data.c", - "musl/src/math/expf.c", "musl/src/math/expl.c", "musl/src/math/expm1.c", "musl/src/math/expm1f.c", @@ -926,9 +915,6 @@ const src_files = [_][]const u8{ "musl/src/math/fmin.c", "musl/src/math/fminf.c", "musl/src/math/fminl.c", - "musl/src/math/fmod.c", - "musl/src/math/fmodf.c", - "musl/src/math/fmodl.c", "musl/src/math/__fpclassify.c", "musl/src/math/__fpclassifyf.c", "musl/src/math/__fpclassifyl.c", @@ -1023,23 +1009,17 @@ const src_files = [_][]const u8{ "musl/src/math/llround.c", "musl/src/math/llroundf.c", "musl/src/math/llroundl.c", - "musl/src/math/log10.c", - "musl/src/math/log10f.c", "musl/src/math/log10l.c", "musl/src/math/log1p.c", "musl/src/math/log1pf.c", "musl/src/math/log1pl.c", - "musl/src/math/log2.c", "musl/src/math/log2_data.c", - "musl/src/math/log2f.c", "musl/src/math/log2f_data.c", "musl/src/math/log2l.c", "musl/src/math/logb.c", "musl/src/math/logbf.c", "musl/src/math/logbl.c", - "musl/src/math/log.c", "musl/src/math/log_data.c", - "musl/src/math/logf.c", "musl/src/math/logf_data.c", "musl/src/math/logl.c", "musl/src/math/lrint.c", @@ -1065,9 +1045,6 @@ const src_files = [_][]const u8{ "musl/src/math/modf.c", "musl/src/math/modff.c", "musl/src/math/modfl.c", - "musl/src/math/nan.c", - "musl/src/math/nanf.c", - "musl/src/math/nanl.c", "musl/src/math/nearbyint.c", "musl/src/math/nearbyintf.c", "musl/src/math/nearbyintl.c", @@ -1737,21 +1714,13 @@ const src_files = [_][]const u8{ "musl/src/stdlib/atoi.c", "musl/src/stdlib/atol.c", "musl/src/stdlib/atoll.c", - "musl/src/stdlib/bsearch.c", - "musl/src/stdlib/div.c", "musl/src/stdlib/ecvt.c", "musl/src/stdlib/fcvt.c", "musl/src/stdlib/gcvt.c", - "musl/src/stdlib/imaxdiv.c", - "musl/src/stdlib/ldiv.c", - "musl/src/stdlib/lldiv.c", - "musl/src/stdlib/qsort.c", - "musl/src/stdlib/qsort_nr.c", "musl/src/stdlib/strtod.c", "musl/src/stdlib/strtol.c", "musl/src/stdlib/wcstod.c", "musl/src/stdlib/wcstol.c", - "musl/src/string/bcmp.c", "musl/src/string/bcopy.c", "musl/src/string/explicit_bzero.c", "musl/src/string/index.c", diff --git a/src/libs/netbsd.zig b/src/libs/netbsd.zig index 07a7da7f6f8e..87d2909e0782 100644 --- a/src/libs/netbsd.zig +++ b/src/libs/netbsd.zig @@ -1,9 +1,9 @@ const std = @import("std"); +const Io = std.Io; const Allocator = std.mem.Allocator; const mem = std.mem; const log = std.log; -const fs = std.fs; -const path = fs.path; +const path = std.Io.Dir.path; const assert = std.debug.assert; const Version = std.SemanticVersion; const Path = std.Build.Cache.Path; @@ -346,8 +346,8 @@ pub const BuiltSharedObjects = struct { lock: Cache.Lock, dir_path: Path, - pub fn deinit(self: *BuiltSharedObjects, gpa: Allocator) void { - self.lock.release(); + pub fn deinit(self: *BuiltSharedObjects, gpa: Allocator, io: Io) void { + self.lock.release(io); gpa.free(self.dir_path.sub_path); self.* = undefined; } @@ -385,12 +385,13 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye var cache: Cache = .{ .gpa = gpa, .io = io, - .manifest_dir = try comp.dirs.global_cache.handle.makeOpenPath("h", .{}), + .manifest_dir = try comp.dirs.global_cache.handle.createDirPathOpen(io, "h", .{}), + .cwd = comp.dirs.cwd, }; - cache.addPrefix(.{ .path = null, .handle = fs.cwd() }); + cache.addPrefix(.{ .path = null, .handle = Io.Dir.cwd() }); cache.addPrefix(comp.dirs.zig_lib); cache.addPrefix(comp.dirs.global_cache); - defer cache.manifest_dir.close(); + defer cache.manifest_dir.close(io); var man = cache.obtain(); defer man.deinit(); @@ -409,7 +410,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye .lock = man.toOwnedLock(), .dir_path = .{ .root_dir = comp.dirs.global_cache, - .sub_path = try gpa.dupe(u8, "o" ++ fs.path.sep_str ++ digest), + .sub_path = try gpa.dupe(u8, "o" ++ path.sep_str ++ digest), }, }); } @@ -418,10 +419,10 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye const o_sub_path = try path.join(arena, &[_][]const u8{ "o", &digest }); var o_directory: Cache.Directory = .{ - .handle = try comp.dirs.global_cache.handle.makeOpenPath(o_sub_path, .{}), + .handle = try comp.dirs.global_cache.handle.createDirPathOpen(io, o_sub_path, .{}), .path = try comp.dirs.global_cache.join(arena, &.{o_sub_path}), }; - defer o_directory.handle.close(); + defer o_directory.handle.close(io); const abilists_contents = man.files.keys()[abilists_index].contents.?; const metadata = try loadMetaData(gpa, abilists_contents); @@ -628,7 +629,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye var lib_name_buf: [32]u8 = undefined; // Larger than each of the names "c", "pthread", etc. const asm_file_basename = std.fmt.bufPrint(&lib_name_buf, "{s}.s", .{lib.name}) catch unreachable; - try o_directory.handle.writeFile(.{ .sub_path = asm_file_basename, .data = stubs_asm.items }); + try o_directory.handle.writeFile(io, .{ .sub_path = asm_file_basename, .data = stubs_asm.items }); try buildSharedLib(comp, arena, o_directory, asm_file_basename, lib, prog_node); } @@ -640,12 +641,13 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye .lock = man.toOwnedLock(), .dir_path = .{ .root_dir = comp.dirs.global_cache, - .sub_path = try gpa.dupe(u8, "o" ++ fs.path.sep_str ++ digest), + .sub_path = try gpa.dupe(u8, "o" ++ path.sep_str ++ digest), }, }); } -fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void { +fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) std.Io.Cancelable!void { + const io = comp.io; assert(comp.netbsd_so_files == null); comp.netbsd_so_files = so_files; @@ -653,14 +655,14 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void { var task_buffer_i: usize = 0; { - comp.mutex.lock(); // protect comp.arena - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); // protect comp.arena + defer comp.mutex.unlock(io); for (libs) |lib| { const so_path: Path = .{ .root_dir = so_files.dir_path.root_dir, .sub_path = std.fmt.allocPrint(comp.arena, "{s}{c}lib{s}.so.{d}", .{ - so_files.dir_path.sub_path, fs.path.sep, lib.name, lib.sover, + so_files.dir_path.sub_path, path.sep, lib.name, lib.sover, }) catch return comp.setAllocFailure(), }; task_buffer[task_buffer_i] = .{ .load_dso = so_path }; @@ -668,7 +670,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void { } } - comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]); + try comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]); } fn buildSharedLib( @@ -737,8 +739,8 @@ fn buildSharedLib( var sub_create_diag: Compilation.CreateDiagnostic = undefined; const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{ + .thread_limit = comp.thread_limit, .dirs = comp.dirs.withoutLocalCache(), - .thread_pool = comp.thread_pool, .self_exe_path = comp.self_exe_path, // Because we manually cache the whole set of objects, we don't cache the individual objects // within it. In fact, we *can't* do that, because we need `emit_bin` to specify the path. @@ -760,6 +762,7 @@ fn buildSharedLib( .soname = soname, .c_source_files = &c_source_files, .skip_linker_dependencies = true, + .environ_map = comp.environ_map, }) catch |err| switch (err) { error.CreateFail => { comp.lockAndSetMiscFailure(misc_task, "sub-compilation of {t} failed: {f}", .{ misc_task, sub_create_diag }); diff --git a/src/libs/openbsd.zig b/src/libs/openbsd.zig new file mode 100644 index 000000000000..57f32e83735d --- /dev/null +++ b/src/libs/openbsd.zig @@ -0,0 +1,703 @@ +const std = @import("std"); +const Io = std.Io; +const Allocator = std.mem.Allocator; +const mem = std.mem; +const log = std.log; +const fs = std.fs; +const path = fs.path; +const assert = std.debug.assert; +const Version = std.SemanticVersion; +const Path = std.Build.Cache.Path; + +const Compilation = @import("../Compilation.zig"); +const build_options = @import("build_options"); +const trace = @import("../tracy.zig").trace; +const Cache = std.Build.Cache; +const Module = @import("../Package/Module.zig"); +const link = @import("../link.zig"); + +pub const CrtFile = enum { + scrt0_o, +}; + +pub fn needsCrt0(output_mode: std.builtin.OutputMode) ?CrtFile { + // https://github.com/ziglang/zig/issues/23574#issuecomment-2869089897 + return switch (output_mode) { + .Obj, .Lib => null, + .Exe => .scrt0_o, + }; +} + +fn includePath(comp: *Compilation, arena: Allocator, sub_path: []const u8) ![]const u8 { + return path.join(arena, &.{ + comp.dirs.zig_lib.path.?, + "libc" ++ path.sep_str ++ "include", + sub_path, + }); +} + +fn csuPath(comp: *Compilation, arena: Allocator, sub_path: []const u8) ![]const u8 { + return path.join(arena, &.{ + comp.dirs.zig_lib.path.?, + "libc" ++ path.sep_str ++ "openbsd" ++ path.sep_str ++ "lib" ++ path.sep_str ++ "csu", + sub_path, + }); +} + +/// TODO replace anyerror with explicit error set, recording user-friendly errors with +/// lockAndSetMiscFailure and returning error.AlreadyReported. see libcxx.zig for example. +pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progress.Node) anyerror!void { + if (!build_options.have_llvm) return error.ZigCompilerNotBuiltWithLLVMExtensions; + + const gpa = comp.gpa; + var arena_allocator = std.heap.ArenaAllocator.init(gpa); + defer arena_allocator.deinit(); + const arena = arena_allocator.allocator(); + + const target = &comp.root_mod.resolved_target.result; + const target_version = target.os.version_range.semver.min; + + // In all cases in this function, we add the C compiler flags to + // cache_exempt_flags rather than extra_flags, because these arguments + // depend on only properties that are already covered by the cache + // manifest. Including these arguments in the cache could only possibly + // waste computation and create false negatives. + + switch (crt_file) { + .scrt0_o => { + var cflags = std.array_list.Managed([]const u8).init(arena); + try cflags.appendSlice(&.{ + "-w", // Disable all warnings. + }); + + // See `Compilation.addCommonCCArgs`. + try cflags.append(try std.fmt.allocPrint(arena, "-D___OpenBSD={d}", .{ + 202510, + })); + try cflags.append(try std.fmt.allocPrint(arena, "-DOpenBSD{d}_{d}", .{ + target_version.major, + target_version.minor, + })); + + try cflags.appendSlice(&.{ + "-I", + try includePath(comp, arena, try std.fmt.allocPrint(arena, "{s}-{s}-{s}", .{ + std.zig.target.openbsdArchNameHeaders(target.cpu.arch), + @tagName(target.os.tag), + @tagName(target.abi), + })), + "-I", + try includePath(comp, arena, "generic-openbsd"), + "-I", + try csuPath(comp, arena, switch (target.cpu.arch) { + .mips64el => "mips64", + .x86 => "i386", + .x86_64 => "amd64", + else => |t| @tagName(t), + }), + "-Qunused-arguments", + }); + + const sources = [_]struct { + path: []const u8, + flags: []const []const u8, + }{ + .{ + .path = "crt0.c", + .flags = cflags.items, + }, + .{ + .path = "crtbegin.c", + .flags = cflags.items, + }, + }; + + var files_buf: [sources.len]Compilation.CSourceFile = undefined; + var files_index: usize = 0; + for (sources) |file| { + files_buf[files_index] = .{ + .src_path = try csuPath(comp, arena, file.path), + .cache_exempt_flags = file.flags, + .owner = undefined, + }; + files_index += 1; + } + const files = files_buf[0..files_index]; + + return comp.build_crt_file("crt0", .Obj, .@"openbsd libc Scrt0.o", prog_node, files, .{ + // Unclear why OpenBSD does this, but we'll do the same. + .omit_frame_pointer = if (target.cpu.arch.isX86()) false else null, + .pic = true, + }); + }, + } +} + +pub const Lib = struct { + name: []const u8, +}; + +// Library versions are bumped frequently on OpenBSD. Fortunately, by linking to +// just libc.so, the dynamic linker will happily bind to e.g. libc.so.102.0. +pub const libs = [_]Lib{ + .{ .name = "m" }, + .{ .name = "pthread" }, + .{ .name = "c" }, + .{ .name = "ld" }, + .{ .name = "util" }, + .{ .name = "execinfo" }, +}; + +pub const ABI = struct { + all_versions: []const Version, // all defined versions (one abilist from v2.0.0 up to current) + all_targets: []const std.zig.target.ArchOsAbi, + /// The bytes from the file verbatim, starting from the u16 number + /// of function inclusions. + inclusions: []const u8, + arena_state: std.heap.ArenaAllocator.State, + + pub fn destroy(abi: *ABI, gpa: Allocator) void { + abi.arena_state.promote(gpa).deinit(); + } +}; + +pub const LoadMetaDataError = error{ + /// The files that ship with the Zig compiler were unable to be read, or otherwise had malformed data. + ZigInstallationCorrupt, + OutOfMemory, +}; + +pub const abilists_path = "libc" ++ path.sep_str ++ "openbsd" ++ path.sep_str ++ "abilists"; +pub const abilists_max_size = 300 * 1024; // Bigger than this and something is definitely borked. + +/// This function will emit a log error when there is a problem with the zig +/// installation and then return `error.ZigInstallationCorrupt`. +pub fn loadMetaData(gpa: Allocator, contents: []const u8) LoadMetaDataError!*ABI { + const tracy = trace(@src()); + defer tracy.end(); + + var arena_allocator = std.heap.ArenaAllocator.init(gpa); + errdefer arena_allocator.deinit(); + const arena = arena_allocator.allocator(); + + var index: usize = 0; + + { + const libs_len = contents[index]; + index += 1; + + var i: u8 = 0; + while (i < libs_len) : (i += 1) { + const lib_name = mem.sliceTo(contents[index..], 0); + index += lib_name.len + 1; + + if (i >= libs.len or !mem.eql(u8, libs[i].name, lib_name)) { + log.err("libc" ++ path.sep_str ++ "openbsd" ++ path.sep_str ++ + "abilists: invalid library name or index ({d}): '{s}'", .{ i, lib_name }); + return error.ZigInstallationCorrupt; + } + } + } + + const versions = b: { + const versions_len = contents[index]; + index += 1; + + const versions = try arena.alloc(Version, versions_len); + var i: u8 = 0; + while (i < versions.len) : (i += 1) { + versions[i] = .{ + .major = contents[index + 0], + .minor = contents[index + 1], + .patch = contents[index + 2], + }; + index += 3; + } + break :b versions; + }; + + const targets = b: { + const targets_len = contents[index]; + index += 1; + + const targets = try arena.alloc(std.zig.target.ArchOsAbi, targets_len); + var i: u8 = 0; + while (i < targets.len) : (i += 1) { + const target_name = mem.sliceTo(contents[index..], 0); + index += target_name.len + 1; + + var component_it = mem.tokenizeScalar(u8, target_name, '-'); + const arch_name = component_it.next() orelse { + log.err("abilists: expected arch name", .{}); + return error.ZigInstallationCorrupt; + }; + const os_name = component_it.next() orelse { + log.err("abilists: expected OS name", .{}); + return error.ZigInstallationCorrupt; + }; + const abi_name = component_it.next() orelse { + log.err("abilists: expected ABI name", .{}); + return error.ZigInstallationCorrupt; + }; + const arch_tag = std.meta.stringToEnum(std.Target.Cpu.Arch, arch_name) orelse { + log.err("abilists: unrecognized arch: '{s}'", .{arch_name}); + return error.ZigInstallationCorrupt; + }; + if (!mem.eql(u8, os_name, "openbsd")) { + log.err("abilists: expected OS 'openbsd', found '{s}'", .{os_name}); + return error.ZigInstallationCorrupt; + } + const abi_tag = std.meta.stringToEnum(std.Target.Abi, abi_name) orelse { + log.err("abilists: unrecognized ABI: '{s}'", .{abi_name}); + return error.ZigInstallationCorrupt; + }; + + targets[i] = .{ + .arch = arch_tag, + .os = .openbsd, + .abi = abi_tag, + }; + } + break :b targets; + }; + + const abi = try arena.create(ABI); + abi.* = .{ + .all_versions = versions, + .all_targets = targets, + .inclusions = contents[index..], + .arena_state = arena_allocator.state, + }; + return abi; +} + +pub const BuiltSharedObjects = struct { + lock: Cache.Lock, + dir_path: Path, + + pub fn deinit(self: *BuiltSharedObjects, gpa: Allocator, io: Io) void { + self.lock.release(io); + gpa.free(self.dir_path.sub_path); + self.* = undefined; + } +}; + +fn wordDirective(target: *const std.Target) []const u8 { + // Based on its description in the GNU `as` manual, you might assume that `.word` is sized + // according to the target word size. But no; that would just make too much sense. + return if (target.ptrBitWidth() == 64) ".quad" else ".long"; +} + +/// TODO replace anyerror with explicit error set, recording user-friendly errors with +/// lockAndSetMiscFailure and returning error.AlreadyReported. see libcxx.zig for example. +pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anyerror!void { + // See also glibc.zig which this code is based on. + + const tracy = trace(@src()); + defer tracy.end(); + + if (!build_options.have_llvm) { + return error.ZigCompilerNotBuiltWithLLVMExtensions; + } + + const gpa = comp.gpa; + const io = comp.io; + + var arena_allocator = std.heap.ArenaAllocator.init(gpa); + defer arena_allocator.deinit(); + const arena = arena_allocator.allocator(); + + const target = comp.getTarget(); + const target_version = target.os.version_range.semver.min; + + // Use the global cache directory. + var cache: Cache = .{ + .gpa = gpa, + .io = io, + .manifest_dir = try comp.dirs.global_cache.handle.createDirPathOpen(io, "h", .{}), + .cwd = comp.dirs.cwd, + }; + cache.addPrefix(.{ .path = null, .handle = Io.Dir.cwd() }); + cache.addPrefix(comp.dirs.zig_lib); + cache.addPrefix(comp.dirs.global_cache); + defer cache.manifest_dir.close(io); + + var man = cache.obtain(); + defer man.deinit(); + man.hash.addBytes(build_options.version); + man.hash.add(target.cpu.arch); + man.hash.add(target.abi); + man.hash.add(target_version); + + const full_abilists_path = try comp.dirs.zig_lib.join(arena, &.{abilists_path}); + const abilists_index = try man.addFile(full_abilists_path, abilists_max_size); + + if (try man.hit()) { + const digest = man.final(); + + return queueSharedObjects(comp, .{ + .lock = man.toOwnedLock(), + .dir_path = .{ + .root_dir = comp.dirs.global_cache, + .sub_path = try gpa.dupe(u8, "o" ++ path.sep_str ++ digest), + }, + }); + } + + const digest = man.final(); + const o_sub_path = try path.join(arena, &[_][]const u8{ "o", &digest }); + + var o_directory: Cache.Directory = .{ + .handle = try comp.dirs.global_cache.handle.createDirPathOpen(io, o_sub_path, .{}), + .path = try comp.dirs.global_cache.join(arena, &.{o_sub_path}), + }; + defer o_directory.handle.close(io); + + const abilists_contents = man.files.keys()[abilists_index].contents.?; + const metadata = try loadMetaData(gpa, abilists_contents); + defer metadata.destroy(gpa); + + const target_targ_index = for (metadata.all_targets, 0..) |targ, i| { + if (targ.arch == target.cpu.arch and + targ.os == target.os.tag and + targ.abi == target.abi) + { + break i; + } + } else { + unreachable; // std.zig.target.available_libcs prevents us from getting here + }; + + const target_ver_index = for (metadata.all_versions, 0..) |ver, i| { + switch (ver.order(target_version)) { + .eq => break i, + .lt => continue, + .gt => { + // TODO Expose via compile error mechanism instead of log. + log.warn("invalid target OpenBSD libc version: {f}", .{target_version}); + return error.InvalidTargetLibCVersion; + }, + } + } else blk: { + const latest_index = metadata.all_versions.len - 1; + log.warn("zig cannot build new OpenBSD libc version {f}; providing instead {f}", .{ + target_version, metadata.all_versions[latest_index], + }); + break :blk latest_index; + }; + + var stubs_asm = std.array_list.Managed(u8).init(gpa); + defer stubs_asm.deinit(); + + for (libs, 0..) |lib, lib_i| { + stubs_asm.shrinkRetainingCapacity(0); + + try stubs_asm.appendSlice(".text\n"); + + var sym_i: usize = 0; + var sym_name_buf: std.Io.Writer.Allocating = .init(arena); + var opt_symbol_name: ?[]const u8 = null; + + var inc_reader: std.Io.Reader = .fixed(metadata.inclusions); + + const fn_inclusions_len = try inc_reader.takeInt(u16, .little); + + var chosen_ver_index: usize = 255; + var chosen_is_weak: bool = undefined; + + while (sym_i < fn_inclusions_len) : (sym_i += 1) { + const sym_name = opt_symbol_name orelse n: { + sym_name_buf.clearRetainingCapacity(); + _ = try inc_reader.streamDelimiter(&sym_name_buf.writer, 0); + assert(inc_reader.buffered()[0] == 0); // TODO change streamDelimiter API + inc_reader.toss(1); + + opt_symbol_name = sym_name_buf.written(); + chosen_ver_index = 255; + + break :n sym_name_buf.written(); + }; + + { + const targets = try inc_reader.takeLeb128(u64); + var lib_index = try inc_reader.takeByte(); + + const is_weak = (lib_index & (1 << 6)) != 0; + const is_terminal = (lib_index & (1 << 7)) != 0; + + lib_index = @as(u5, @truncate(lib_index)); + + // Test whether the inclusion applies to our current library and target. + const ok_lib_and_target = + (lib_index == lib_i) and + ((targets & (@as(u64, 1) << @as(u6, @intCast(target_targ_index)))) != 0); + + while (true) { + const byte = try inc_reader.takeByte(); + const last = (byte & 0b1000_0000) != 0; + const ver_i = @as(u7, @truncate(byte)); + if (ok_lib_and_target and ver_i <= target_ver_index and + (chosen_ver_index == 255 or ver_i > chosen_ver_index)) + { + chosen_ver_index = ver_i; + chosen_is_weak = is_weak; + } + if (last) break; + } + + if (is_terminal) { + opt_symbol_name = null; + } else continue; + } + + if (chosen_ver_index != 255) { + // Example: + // .balign 4 + // .globl _Exit + // .type _Exit, %function + // _Exit: .long 0 + try stubs_asm.print( + \\.balign {d} + \\.{s} {s} + \\.type {s}, %function + \\{s}: {s} 0 + \\ + , .{ + target.ptrBitWidth() / 8, + if (chosen_is_weak) "weak" else "globl", + sym_name, + sym_name, + sym_name, + wordDirective(target), + }); + } + } + + try stubs_asm.appendSlice(".data\n"); + + const obj_inclusions_len = try inc_reader.takeInt(u16, .little); + + sym_i = 0; + opt_symbol_name = null; + + var chosen_size: u16 = undefined; + + while (sym_i < obj_inclusions_len) : (sym_i += 1) { + const sym_name = opt_symbol_name orelse n: { + sym_name_buf.clearRetainingCapacity(); + _ = try inc_reader.streamDelimiter(&sym_name_buf.writer, 0); + assert(inc_reader.buffered()[0] == 0); // TODO change streamDelimiter API + inc_reader.toss(1); + + opt_symbol_name = sym_name_buf.written(); + chosen_ver_index = 255; + + break :n sym_name_buf.written(); + }; + + { + const targets = try inc_reader.takeLeb128(u64); + const size = try inc_reader.takeLeb128(u16); + var lib_index = try inc_reader.takeByte(); + + const is_weak = (lib_index & (1 << 6)) != 0; + const is_terminal = (lib_index & (1 << 7)) != 0; + + lib_index = @as(u5, @truncate(lib_index)); + + // Test whether the inclusion applies to our current library and target. + const ok_lib_and_target = + (lib_index == lib_i) and + ((targets & (@as(u64, 1) << @as(u6, @intCast(target_targ_index)))) != 0); + + while (true) { + const byte = try inc_reader.takeByte(); + const last = (byte & 0b1000_0000) != 0; + const ver_i = @as(u7, @truncate(byte)); + if (ok_lib_and_target and ver_i <= target_ver_index and + (chosen_ver_index == 255 or ver_i > chosen_ver_index)) + { + chosen_ver_index = ver_i; + chosen_size = size; + chosen_is_weak = is_weak; + } + if (last) break; + } + + if (is_terminal) { + opt_symbol_name = null; + } else continue; + } + + if (chosen_ver_index != 255) { + // Example: + // .balign 4 + // .globl malloc_conf + // .type malloc_conf, %object + // .size malloc_conf, 4 + // malloc_conf: .fill 4, 1, 0 + try stubs_asm.print( + \\.balign {d} + \\.{s} {s} + \\.type {s}, %object + \\.size {s}, {d} + \\{s}: {s} 0 + \\ + , .{ + target.ptrBitWidth() / 8, + if (chosen_is_weak) "weak" else "globl", + sym_name, + sym_name, + sym_name, + chosen_size, + sym_name, + wordDirective(target), + }); + } + } + + var lib_name_buf: [32]u8 = undefined; // Larger than each of the names "c", "pthread", etc. + const asm_file_basename = std.fmt.bufPrint(&lib_name_buf, "{s}.s", .{lib.name}) catch unreachable; + try o_directory.handle.writeFile(io, .{ .sub_path = asm_file_basename, .data = stubs_asm.items }); + try buildSharedLib(comp, arena, o_directory, asm_file_basename, lib, prog_node); + } + + man.writeManifest() catch |err| { + log.warn("failed to write cache manifest for OpenBSD libc stubs: {s}", .{@errorName(err)}); + }; + + return queueSharedObjects(comp, .{ + .lock = man.toOwnedLock(), + .dir_path = .{ + .root_dir = comp.dirs.global_cache, + .sub_path = try gpa.dupe(u8, "o" ++ path.sep_str ++ digest), + }, + }); +} + +fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) std.Io.Cancelable!void { + const io = comp.io; + assert(comp.openbsd_so_files == null); + comp.openbsd_so_files = so_files; + + var task_buffer: [libs.len]link.PrelinkTask = undefined; + var task_buffer_i: usize = 0; + + { + comp.mutex.lockUncancelable(io); // protect comp.arena + defer comp.mutex.unlock(io); + + for (libs) |lib| { + const so_path: Path = .{ + .root_dir = so_files.dir_path.root_dir, + .sub_path = std.fmt.allocPrint(comp.arena, "{s}{c}lib{s}.so", .{ + so_files.dir_path.sub_path, path.sep, lib.name, + }) catch return comp.setAllocFailure(), + }; + task_buffer[task_buffer_i] = .{ .load_dso = so_path }; + task_buffer_i += 1; + } + } + + try comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]); +} + +fn buildSharedLib( + comp: *Compilation, + arena: Allocator, + bin_directory: Cache.Directory, + asm_file_basename: []const u8, + lib: Lib, + prog_node: std.Progress.Node, +) !void { + const tracy = trace(@src()); + defer tracy.end(); + + const io = comp.io; + const basename = try std.fmt.allocPrint(arena, "lib{s}.so", .{lib.name}); + const ld_basename = path.basename(comp.getTarget().standardDynamicLinkerPath().get().?); + const soname = if (mem.eql(u8, lib.name, "ld")) ld_basename else basename; + + const optimize_mode = comp.compilerRtOptMode(); + const strip = comp.compilerRtStrip(); + const config = try Compilation.Config.resolve(.{ + .output_mode = .Lib, + .link_mode = .dynamic, + .resolved_target = comp.root_mod.resolved_target, + .is_test = false, + .have_zcu = false, + .emit_bin = true, + .root_optimize_mode = optimize_mode, + .root_strip = strip, + .link_libc = false, + }); + + const root_mod = try Module.create(arena, .{ + .paths = .{ + .root = .zig_lib_root, + .root_src_path = "", + }, + .fully_qualified_name = "root", + .inherited = .{ + .resolved_target = comp.root_mod.resolved_target, + .strip = strip, + .stack_check = false, + .stack_protector = 0, + .sanitize_c = .off, + .sanitize_thread = false, + .red_zone = comp.root_mod.red_zone, + .omit_frame_pointer = comp.root_mod.omit_frame_pointer, + .valgrind = false, + .optimize_mode = optimize_mode, + .structured_cfg = comp.root_mod.structured_cfg, + }, + .global = config, + .cc_argv = &.{}, + .parent = null, + }); + + const c_source_files = [1]Compilation.CSourceFile{ + .{ + .src_path = try path.join(arena, &.{ bin_directory.path.?, asm_file_basename }), + .owner = root_mod, + }, + }; + + const misc_task: Compilation.MiscTask = .@"openbsd libc shared object"; + + var sub_create_diag: Compilation.CreateDiagnostic = undefined; + const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{ + .dirs = comp.dirs.withoutLocalCache(), + .thread_limit = comp.thread_limit, + .self_exe_path = comp.self_exe_path, + // Because we manually cache the whole set of objects, we don't cache the individual objects + // within it. In fact, we *can't* do that, because we need `emit_bin` to specify the path. + .cache_mode = .none, + .config = config, + .root_mod = root_mod, + .root_name = lib.name, + .libc_installation = comp.libc_installation, + .emit_bin = .{ .yes_path = try bin_directory.join(arena, &.{basename}) }, + .verbose_cc = comp.verbose_cc, + .verbose_link = comp.verbose_link, + .verbose_air = comp.verbose_air, + .verbose_llvm_ir = comp.verbose_llvm_ir, + .verbose_llvm_bc = comp.verbose_llvm_bc, + .verbose_cimport = comp.verbose_cimport, + .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, + .clang_passthrough_mode = comp.clang_passthrough_mode, + .soname = soname, + .c_source_files = &c_source_files, + .skip_linker_dependencies = true, + .environ_map = comp.environ_map, + }) catch |err| switch (err) { + error.CreateFail => { + comp.lockAndSetMiscFailure(misc_task, "sub-compilation of {t} failed: {f}", .{ misc_task, sub_create_diag }); + return error.AlreadyReported; + }, + else => |e| return e, + }; + defer sub_compilation.destroy(); + + try comp.updateSubCompilation(sub_compilation, misc_task, prog_node); +} diff --git a/src/libs/wasi_libc.zig b/src/libs/wasi_libc.zig index 0279e1bc85e5..cfcd2ed7a304 100644 --- a/src/libs/wasi_libc.zig +++ b/src/libs/wasi_libc.zig @@ -739,13 +739,9 @@ const libc_top_half_src_files = [_][]const u8{ "musl/src/math/exp10.c", "musl/src/math/exp10f.c", "musl/src/math/exp10l.c", - "musl/src/math/exp2.c", - "musl/src/math/exp2f.c", "musl/src/math/exp2f_data.c", "musl/src/math/exp2l.c", - "musl/src/math/exp.c", "musl/src/math/exp_data.c", - "musl/src/math/expf.c", "musl/src/math/expl.c", "musl/src/math/expm1.c", "musl/src/math/expm1f.c", @@ -759,9 +755,6 @@ const libc_top_half_src_files = [_][]const u8{ "musl/src/math/fmaf.c", "musl/src/math/fmaxl.c", "musl/src/math/fminl.c", - "musl/src/math/fmod.c", - "musl/src/math/fmodf.c", - "musl/src/math/fmodl.c", "musl/src/math/frexp.c", "musl/src/math/frexpf.c", "musl/src/math/frexpl.c", @@ -792,23 +785,17 @@ const libc_top_half_src_files = [_][]const u8{ "musl/src/math/llround.c", "musl/src/math/llroundf.c", "musl/src/math/llroundl.c", - "musl/src/math/log10.c", - "musl/src/math/log10f.c", "musl/src/math/log10l.c", "musl/src/math/log1p.c", "musl/src/math/log1pf.c", "musl/src/math/log1pl.c", - "musl/src/math/log2.c", "musl/src/math/log2_data.c", - "musl/src/math/log2f.c", "musl/src/math/log2f_data.c", "musl/src/math/log2l.c", "musl/src/math/logb.c", "musl/src/math/logbf.c", "musl/src/math/logbl.c", - "musl/src/math/log.c", "musl/src/math/log_data.c", - "musl/src/math/logf.c", "musl/src/math/logf_data.c", "musl/src/math/logl.c", "musl/src/math/lrint.c", @@ -831,9 +818,6 @@ const libc_top_half_src_files = [_][]const u8{ "musl/src/math/modf.c", "musl/src/math/modff.c", "musl/src/math/modfl.c", - "musl/src/math/nan.c", - "musl/src/math/nanf.c", - "musl/src/math/nanl.c", "musl/src/math/nearbyintl.c", "musl/src/math/nextafter.c", "musl/src/math/nextafterf.c", @@ -1020,18 +1004,10 @@ const libc_top_half_src_files = [_][]const u8{ "musl/src/stdlib/atoi.c", "musl/src/stdlib/atol.c", "musl/src/stdlib/atoll.c", - "musl/src/stdlib/bsearch.c", - "musl/src/stdlib/div.c", "musl/src/stdlib/ecvt.c", "musl/src/stdlib/fcvt.c", "musl/src/stdlib/gcvt.c", - "musl/src/stdlib/imaxdiv.c", - "musl/src/stdlib/ldiv.c", - "musl/src/stdlib/lldiv.c", - "musl/src/stdlib/qsort.c", - "musl/src/stdlib/qsort_nr.c", "musl/src/stdlib/strtol.c", - "musl/src/string/bcmp.c", "musl/src/string/bcopy.c", "musl/src/string/explicit_bzero.c", "musl/src/string/index.c", diff --git a/src/link.zig b/src/link.zig index 6be88490b07c..0e897232962b 100644 --- a/src/link.zig +++ b/src/link.zig @@ -34,7 +34,8 @@ pub const Diags = struct { /// Stored here so that function definitions can distinguish between /// needing an allocator for things besides error reporting. gpa: Allocator, - mutex: std.Thread.Mutex, + io: Io, + mutex: Io.Mutex, msgs: std.ArrayList(Msg), flags: Flags, lld: std.ArrayList(Lld), @@ -126,10 +127,11 @@ pub const Diags = struct { } }; - pub fn init(gpa: Allocator) Diags { + pub fn init(gpa: Allocator, io: Io) Diags { return .{ .gpa = gpa, - .mutex = .{}, + .io = io, + .mutex = .init, .msgs = .empty, .flags = .{}, .lld = .empty, @@ -153,8 +155,10 @@ pub const Diags = struct { } pub fn lockAndParseLldStderr(diags: *Diags, prefix: []const u8, stderr: []const u8) void { - diags.mutex.lock(); - defer diags.mutex.unlock(); + const io = diags.io; + + diags.mutex.lockUncancelable(io); + defer diags.mutex.unlock(io); diags.parseLldStderr(prefix, stderr) catch diags.setAllocFailure(); } @@ -226,9 +230,10 @@ pub const Diags = struct { pub fn addErrorSourceLocation(diags: *Diags, sl: SourceLocation, comptime format: []const u8, args: anytype) void { @branchHint(.cold); const gpa = diags.gpa; + const io = diags.io; const eu_main_msg = std.fmt.allocPrint(gpa, format, args); - diags.mutex.lock(); - defer diags.mutex.unlock(); + diags.mutex.lockUncancelable(io); + defer diags.mutex.unlock(io); addErrorLockedFallible(diags, sl, eu_main_msg) catch |err| switch (err) { error.OutOfMemory => diags.setAllocFailureLocked(), }; @@ -247,8 +252,9 @@ pub const Diags = struct { pub fn addErrorWithNotes(diags: *Diags, note_count: usize) error{OutOfMemory}!ErrorWithNotes { @branchHint(.cold); const gpa = diags.gpa; - diags.mutex.lock(); - defer diags.mutex.unlock(); + const io = diags.io; + diags.mutex.lockUncancelable(io); + defer diags.mutex.unlock(io); try diags.msgs.ensureUnusedCapacity(gpa, 1); return addErrorWithNotesAssumeCapacity(diags, note_count); } @@ -276,9 +282,10 @@ pub const Diags = struct { ) void { @branchHint(.cold); const gpa = diags.gpa; + const io = diags.io; const eu_main_msg = std.fmt.allocPrint(gpa, format, args); - diags.mutex.lock(); - defer diags.mutex.unlock(); + diags.mutex.lockUncancelable(io); + defer diags.mutex.unlock(io); addMissingLibraryErrorLockedFallible(diags, checked_paths, eu_main_msg) catch |err| switch (err) { error.OutOfMemory => diags.setAllocFailureLocked(), }; @@ -312,9 +319,10 @@ pub const Diags = struct { ) void { @branchHint(.cold); const gpa = diags.gpa; + const io = diags.io; const eu_main_msg = std.fmt.allocPrint(gpa, format, args); - diags.mutex.lock(); - defer diags.mutex.unlock(); + diags.mutex.lockUncancelable(io); + defer diags.mutex.unlock(io); addParseErrorLockedFallible(diags, path, eu_main_msg) catch |err| switch (err) { error.OutOfMemory => diags.setAllocFailureLocked(), }; @@ -349,8 +357,9 @@ pub const Diags = struct { pub fn setAllocFailure(diags: *Diags) void { @branchHint(.cold); - diags.mutex.lock(); - defer diags.mutex.unlock(); + const io = diags.io; + diags.mutex.lockUncancelable(io); + defer diags.mutex.unlock(io); setAllocFailureLocked(diags); } @@ -384,7 +393,7 @@ pub const File = struct { comp: *Compilation, emit: Path, - file: ?fs.File, + file: ?Io.File, /// When using the LLVM backend, the emitted object is written to a file with this name. This /// object file then becomes a normal link input to LLD or a self-hosted linker. /// @@ -607,20 +616,25 @@ pub const File = struct { // it will return ETXTBSY. So instead, we copy the file, atomically rename it // over top of the exe path, and then proceed normally. This changes the inode, // avoiding the error. + const random_integer = r: { + var x: u32 = undefined; + io.random(@ptrCast(&x)); + break :r x; + }; const tmp_sub_path = try std.fmt.allocPrint(gpa, "{s}-{x}", .{ - emit.sub_path, std.crypto.random.int(u32), + emit.sub_path, random_integer, }); defer gpa.free(tmp_sub_path); - try emit.root_dir.handle.copyFile(emit.sub_path, emit.root_dir.handle, tmp_sub_path, .{}); - try emit.root_dir.handle.rename(tmp_sub_path, emit.sub_path); + try emit.root_dir.handle.copyFile(emit.sub_path, emit.root_dir.handle, tmp_sub_path, io, .{}); + try emit.root_dir.handle.rename(tmp_sub_path, emit.root_dir.handle, emit.sub_path, io); switch (builtin.os.tag) { .linux => std.posix.ptrace(std.os.linux.PTRACE.ATTACH, pid, 0, 0) catch |err| { - log.warn("ptrace failure: {s}", .{@errorName(err)}); + log.warn("ptrace failure: {t}", .{err}); }, .maccatalyst, .macos => { const macho_file = base.cast(.macho).?; macho_file.ptraceAttach(pid) catch |err| { - log.warn("attaching failed with error: {s}", .{@errorName(err)}); + log.warn("attaching failed with error: {t}", .{err}); }; }, .windows => unreachable, @@ -628,7 +642,7 @@ pub const File = struct { } } } - base.file = try emit.root_dir.handle.openFile(emit.sub_path, .{ .mode = .read_write }); + base.file = try emit.root_dir.handle.openFile(io, emit.sub_path, .{ .mode = .read_write }); }, .elf2, .coff2 => if (base.file == null) { const mf = if (base.cast(.elf2)) |elf| @@ -637,10 +651,10 @@ pub const File = struct { &coff.mf else unreachable; - mf.file = try base.emit.root_dir.handle.adaptToNewApi().openFile(io, base.emit.sub_path, .{ + mf.file = try base.emit.root_dir.handle.openFile(io, base.emit.sub_path, .{ .mode = .read_write, }); - base.file = .adaptFromNewApi(mf.file); + base.file = mf.file; try mf.ensureTotalCapacity(@intCast(mf.nodes.items[0].location().resolve(mf)[1])); }, .c, .spirv => dev.checkAny(&.{ .c_linker, .spirv_linker }), @@ -678,7 +692,7 @@ pub const File = struct { .lld => assert(base.file == null), .elf => if (base.file) |f| { dev.check(.elf_linker); - f.close(); + f.close(io); base.file = null; if (base.child_pid) |pid| { @@ -692,7 +706,7 @@ pub const File = struct { }, .macho, .wasm => if (base.file) |f| { dev.checkAny(&.{ .coff_linker, .macho_linker, .plan9_linker, .wasm_linker }); - f.close(); + f.close(io); base.file = null; if (base.child_pid) |pid| { @@ -843,10 +857,12 @@ pub const File = struct { } } - pub fn releaseLock(self: *File) void { - if (self.lock) |*lock| { - lock.release(); - self.lock = null; + pub fn releaseLock(base: *File) void { + const comp = base.comp; + const io = comp.io; + if (base.lock) |*lock| { + lock.release(io); + base.lock = null; } } @@ -857,8 +873,9 @@ pub const File = struct { } pub fn destroy(base: *File) void { + const io = base.comp.io; base.releaseLock(); - if (base.file) |f| f.close(); + if (base.file) |f| f.close(io); switch (base.tag) { .plan9 => unreachable, inline else => |tag| { @@ -888,16 +905,16 @@ pub const File = struct { } } - pub const FlushError = error{ + pub const FlushError = Io.Cancelable || Allocator.Error || error{ /// Indicates an error will be present in `Compilation.link_diags`. LinkFailure, - OutOfMemory, }; /// Commit pending changes and write headers. Takes into account final output mode. /// `arena` has the lifetime of the call to `Compilation.update`. pub fn flush(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void { const comp = base.comp; + const io = comp.io; if (comp.clang_preprocessor_mode == .yes or comp.clang_preprocessor_mode == .pch) { dev.check(.clang_command); const emit = base.emit; @@ -908,12 +925,19 @@ pub const File = struct { assert(comp.c_object_table.count() == 1); const the_key = comp.c_object_table.keys()[0]; const cached_pp_file_path = the_key.status.success.object_path; - cached_pp_file_path.root_dir.handle.copyFile(cached_pp_file_path.sub_path, emit.root_dir.handle, emit.sub_path, .{}) catch |err| { + Io.Dir.copyFile( + cached_pp_file_path.root_dir.handle, + cached_pp_file_path.sub_path, + emit.root_dir.handle, + emit.sub_path, + io, + .{}, + ) catch |err| { const diags = &base.comp.link_diags; - return diags.fail("failed to copy '{f}' to '{f}': {s}", .{ + return diags.fail("failed to copy '{f}' to '{f}': {t}", .{ std.fmt.alt(@as(Path, cached_pp_file_path), .formatEscapeChar), std.fmt.alt(@as(Path, emit), .formatEscapeChar), - @errorName(err), + err, }); }; return; @@ -1051,9 +1075,10 @@ pub const File = struct { /// Opens a path as an object file and parses it into the linker. fn openLoadObject(base: *File, path: Path) anyerror!void { if (base.tag == .lld) return; + const io = base.comp.io; const diags = &base.comp.link_diags; - const input = try openObjectInput(diags, path); - errdefer input.object.file.close(); + const input = try openObjectInput(io, diags, path); + errdefer input.object.file.close(io); try loadInput(base, input); } @@ -1061,21 +1086,22 @@ pub const File = struct { /// If `query` is non-null, allows GNU ld scripts. fn openLoadArchive(base: *File, path: Path, opt_query: ?UnresolvedInput.Query) anyerror!void { if (base.tag == .lld) return; + const io = base.comp.io; if (opt_query) |query| { - const archive = try openObject(path, query.must_link, query.hidden); - errdefer archive.file.close(); + const archive = try openObject(io, path, query.must_link, query.hidden); + errdefer archive.file.close(io); loadInput(base, .{ .archive = archive }) catch |err| switch (err) { error.BadMagic, error.UnexpectedEndOfFile => { if (base.tag != .elf and base.tag != .elf2) return err; try loadGnuLdScript(base, path, query, archive.file); - archive.file.close(); + archive.file.close(io); return; }, else => return err, }; } else { - const archive = try openObject(path, false, false); - errdefer archive.file.close(); + const archive = try openObject(io, path, false, false); + errdefer archive.file.close(io); try loadInput(base, .{ .archive = archive }); } } @@ -1084,28 +1110,30 @@ pub const File = struct { /// Handles GNU ld scripts. fn openLoadDso(base: *File, path: Path, query: UnresolvedInput.Query) anyerror!void { if (base.tag == .lld) return; - const dso = try openDso(path, query.needed, query.weak, query.reexport); - errdefer dso.file.close(); + const io = base.comp.io; + const dso = try openDso(io, path, query.needed, query.weak, query.reexport); + errdefer dso.file.close(io); loadInput(base, .{ .dso = dso }) catch |err| switch (err) { error.BadMagic, error.UnexpectedEndOfFile => { if (base.tag != .elf and base.tag != .elf2) return err; try loadGnuLdScript(base, path, query, dso.file); - dso.file.close(); + dso.file.close(io); return; }, else => return err, }; } - fn loadGnuLdScript(base: *File, path: Path, parent_query: UnresolvedInput.Query, file: fs.File) anyerror!void { + fn loadGnuLdScript(base: *File, path: Path, parent_query: UnresolvedInput.Query, file: Io.File) anyerror!void { const comp = base.comp; + const io = comp.io; const diags = &comp.link_diags; const gpa = comp.gpa; - const stat = try file.stat(); + const stat = try file.stat(io); const size = std.math.cast(u32, stat.size) orelse return error.FileTooBig; const buf = try gpa.alloc(u8, size); defer gpa.free(buf); - const n = try file.preadAll(buf, 0); + const n = try file.readPositionalAll(io, buf, 0); if (buf.len != n) return error.UnexpectedEndOfFile; var ld_script = try LdScript.parse(gpa, diags, path, buf); defer ld_script.deinit(gpa); @@ -1123,8 +1151,8 @@ pub const File = struct { } else { if (fs.path.isAbsolute(arg.path)) { const new_path = Path.initCwd(path: { - comp.mutex.lock(); - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); break :path try comp.arena.dupe(u8, arg.path); }); switch (Compilation.classifyFileExt(arg.path)) { @@ -1170,6 +1198,32 @@ pub const File = struct { } } + /// Legacy function for old linker code + pub fn copyRangeAll(base: *File, old_offset: u64, new_offset: u64, size: u64) !void { + const comp = base.comp; + const io = comp.io; + const file = base.file.?; + return copyRangeAll2(io, file, file, old_offset, new_offset, size); + } + + /// Legacy function for old linker code + pub fn copyRangeAll2(io: Io, src_file: Io.File, dst_file: Io.File, old_offset: u64, new_offset: u64, size: u64) !void { + var write_buffer: [2048]u8 = undefined; + var file_reader = src_file.reader(io, &.{}); + file_reader.pos = old_offset; + var file_writer = dst_file.writer(io, &write_buffer); + file_writer.pos = new_offset; + const size_u = std.math.cast(usize, size) orelse return error.Overflow; + const n = file_writer.interface.sendFileAll(&file_reader, .limited(size_u)) catch |err| switch (err) { + error.ReadFailed => return file_reader.err.?, + error.WriteFailed => return file_writer.err.?, + }; + assert(n == size_u); + file_writer.interface.flush() catch |err| switch (err) { + error.WriteFailed => return file_writer.err.?, + }; + } + pub const Tag = enum { coff2, elf, @@ -1221,22 +1275,26 @@ pub const File = struct { ty: InternPool.Index, }; - pub fn determineMode( + pub fn determinePermissions( output_mode: std.builtin.OutputMode, link_mode: std.builtin.LinkMode, - ) fs.File.Mode { + ) Io.File.Permissions { // On common systems with a 0o022 umask, 0o777 will still result in a file created // with 0o755 permissions, but it works appropriately if the system is configured // more leniently. As another data point, C's fopen seems to open files with the // 666 mode. - const executable_mode = if (builtin.target.os.tag == .windows) 0 else 0o777; + const executable_mode: Io.File.Permissions = if (builtin.target.os.tag == .windows) + .default_file + else + .fromMode(0o777); + switch (output_mode) { .Lib => return switch (link_mode) { .dynamic => executable_mode, - .static => fs.File.default_mode, + .static => .default_file, }, .Exe => return executable_mode, - .Obj => return fs.File.default_mode, + .Obj => return .default_file, } } @@ -1309,61 +1367,13 @@ pub const ZcuTask = union(enum) { /// Write the constant value for a Decl to the output file. link_nav: InternPool.Nav.Index, /// Write the machine code for a function to the output file. - link_func: LinkFunc, + link_func: Zcu.CodegenTaskPool.Index, link_type: InternPool.Index, update_line_number: InternPool.TrackedInst.Index, - pub fn deinit(task: ZcuTask, zcu: *const Zcu) void { - switch (task) { - .link_nav, - .link_type, - .update_line_number, - => {}, - .link_func => |link_func| { - switch (link_func.mir.status.load(.acquire)) { - .pending => unreachable, // cannot deinit until MIR done - .failed => {}, // MIR not populated so doesn't need freeing - .ready => link_func.mir.value.deinit(zcu), - } - zcu.gpa.destroy(link_func.mir); - }, - } - } - pub const LinkFunc = struct { - /// This will either be a non-generic `func_decl` or a `func_instance`. - func: InternPool.Index, - /// This pointer is allocated into `gpa` and must be freed when the `ZcuTask` is processed. - /// The pointer is shared with the codegen worker, which will populate the MIR inside once - /// it has been generated. It's important that the `link_func` is queued at the same time as - /// the codegen job to ensure that the linker receives functions in a deterministic order, - /// allowing reproducible builds. - mir: *SharedMir, - /// This is not actually used by `doZcuTask`. Instead, `Queue` uses this value as a heuristic - /// to avoid queueing too much AIR/MIR for codegen/link at a time. Essentially, we cap the - /// total number of AIR bytes which are being processed at once, preventing unbounded memory - /// usage when AIR is produced faster than it is processed. - air_bytes: u32, - - pub const SharedMir = struct { - /// This is initially `.pending`. When `value` is populated, the codegen thread will set - /// this to `.ready`, and alert the queue if needed. It could also end up `.failed`. - /// The action of storing a value (other than `.pending`) to this atomic transfers - /// ownership of memory assoicated with `value` to this `ZcuTask`. - status: std.atomic.Value(enum(u8) { - /// We are waiting on codegen to generate MIR (or die trying). - pending, - /// `value` is not populated and will not be populated. Just drop the task from the queue and move on. - failed, - /// `value` is populated with the MIR from the backend in use, which is not LLVM. - ready, - }), - /// This is `undefined` until `ready` is set to `true`. Once populated, this MIR belongs - /// to the `ZcuTask`, and must be `deinit`ed when it is processed. Allocated into `gpa`. - value: codegen.AnyMir, - }; - }; }; pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { + const io = comp.io; const diags = &comp.link_diags; const base = comp.bin_file orelse { comp.link_prog_node.completeOne(); @@ -1372,8 +1382,8 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { var timer = comp.startTimer(); defer if (timer.finish()) |ns| { - comp.mutex.lock(); - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); comp.time_report.?.stats.cpu_ns_link += ns; }; @@ -1484,6 +1494,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { } } pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void { + const io = comp.io; const diags = &comp.link_diags; const zcu = comp.zcu.?; const ip = &zcu.intern_pool; @@ -1492,8 +1503,8 @@ pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void { var timer = comp.startTimer(); - switch (task) { - .link_nav => |nav_index| { + const maybe_nav: ?InternPool.Nav.Index = switch (task) { + .link_nav => |nav_index| nav: { const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip); const nav_prog_node = comp.link_prog_node.start(fqn_slice, 0); defer nav_prog_node.end(); @@ -1514,21 +1525,25 @@ pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void { }, }; } + break :nav nav_index; }, - .link_func => |func| { - const nav = zcu.funcInfo(func.func).owner_nav; + .link_func => |codegen_task| nav: { + timer.pause(); + const func, var mir = codegen_task.wait(&zcu.codegen_task_pool, io) catch |err| switch (err) { + error.Canceled, error.AlreadyReported => return, + }; + defer mir.deinit(zcu); + timer.@"resume"(); + + const nav = zcu.funcInfo(func).owner_nav; const fqn_slice = ip.getNav(nav).fqn.toSlice(ip); + const nav_prog_node = comp.link_prog_node.start(fqn_slice, 0); defer nav_prog_node.end(); - switch (func.mir.status.load(.acquire)) { - .pending => unreachable, - .ready => {}, - .failed => return, - } + assert(zcu.llvm_object == null); // LLVM codegen doesn't produce MIR - const mir = &func.mir.value; if (comp.bin_file) |lf| { - lf.updateFunc(pt, func.func, mir) catch |err| switch (err) { + lf.updateFunc(pt, func, &mir) catch |err| switch (err) { error.OutOfMemory => return diags.setAllocFailure(), error.CodegenFail => return zcu.assertCodegenFailed(nav), error.Overflow, error.RelocationNotByteAligned => { @@ -1539,8 +1554,9 @@ pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void { }, }; } + break :nav ip.indexToKey(func).func.owner_nav; }, - .link_type => |ty| { + .link_type => |ty| nav: { const name = Type.fromInterned(ty).containerTypeName(ip).toSlice(ip); const nav_prog_node = comp.link_prog_node.start(name, 0); defer nav_prog_node.end(); @@ -1552,8 +1568,9 @@ pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void { }; } } + break :nav null; }, - .update_line_number => |ti| { + .update_line_number => |ti| nav: { const nav_prog_node = comp.link_prog_node.start("Update line number", 0); defer nav_prog_node.end(); if (pt.zcu.llvm_object == null) { @@ -1564,21 +1581,18 @@ pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void { }; } } + break :nav null; }, - } + }; if (timer.finish()) |ns_link| report_time: { - const zir_decl: ?InternPool.TrackedInst.Index = switch (task) { - .link_type, .update_line_number => null, - .link_nav => |nav| ip.getNav(nav).srcInst(ip), - .link_func => |f| ip.getNav(ip.indexToKey(f.func).func.owner_nav).srcInst(ip), - }; - comp.mutex.lock(); - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); const tr = &zcu.comp.time_report.?; tr.stats.cpu_ns_link += ns_link; - if (zir_decl) |inst| { - const gop = tr.decl_link_ns.getOrPut(zcu.gpa, inst) catch |err| switch (err) { + if (maybe_nav) |nav| { + const zir_decl = ip.getNav(nav).srcInst(ip); + const gop = tr.decl_link_ns.getOrPut(zcu.gpa, zir_decl) catch |err| switch (err) { error.OutOfMemory => { zcu.comp.setAllocFailure(); break :report_time; @@ -1690,19 +1704,19 @@ pub const Input = union(enum) { pub const Object = struct { path: Path, - file: fs.File, + file: Io.File, must_link: bool, hidden: bool, }; pub const Res = struct { path: Path, - file: fs.File, + file: Io.File, }; pub const Dso = struct { path: Path, - file: fs.File, + file: Io.File, needed: bool, weak: bool, reexport: bool, @@ -1724,7 +1738,7 @@ pub const Input = union(enum) { } /// Returns `null` in the case of `dso_exact`. - pub fn pathAndFile(input: Input) ?struct { Path, fs.File } { + pub fn pathAndFile(input: Input) ?struct { Path, Io.File } { return switch (input) { .object, .archive => |obj| .{ obj.path, obj.file }, inline .res, .dso => |x| .{ x.path, x.file }, @@ -1769,6 +1783,7 @@ pub fn hashInputs(man: *Cache.Manifest, link_inputs: []const Input) !void { pub fn resolveInputs( gpa: Allocator, arena: Allocator, + io: Io, target: *const std.Target, /// This function mutates this array but does not take ownership. /// Allocated with `gpa`. @@ -1818,6 +1833,7 @@ pub fn resolveInputs( for (lib_directories) |lib_directory| switch (try resolveLibInput( gpa, arena, + io, unresolved_inputs, resolved_inputs, &checked_paths, @@ -1844,6 +1860,7 @@ pub fn resolveInputs( for (lib_directories) |lib_directory| switch (try resolveLibInput( gpa, arena, + io, unresolved_inputs, resolved_inputs, &checked_paths, @@ -1871,6 +1888,7 @@ pub fn resolveInputs( switch (try resolveLibInput( gpa, arena, + io, unresolved_inputs, resolved_inputs, &checked_paths, @@ -1889,6 +1907,7 @@ pub fn resolveInputs( switch (try resolveLibInput( gpa, arena, + io, unresolved_inputs, resolved_inputs, &checked_paths, @@ -1920,6 +1939,7 @@ pub fn resolveInputs( if (try resolvePathInput( gpa, arena, + io, unresolved_inputs, resolved_inputs, &ld_script_bytes, @@ -1937,6 +1957,7 @@ pub fn resolveInputs( switch ((try resolvePathInput( gpa, arena, + io, unresolved_inputs, resolved_inputs, &ld_script_bytes, @@ -1964,6 +1985,7 @@ pub fn resolveInputs( if (try resolvePathInput( gpa, arena, + io, unresolved_inputs, resolved_inputs, &ld_script_bytes, @@ -2003,6 +2025,7 @@ const fatal = std.process.fatal; fn resolveLibInput( gpa: Allocator, arena: Allocator, + io: Io, /// Allocated via `gpa`. unresolved_inputs: *std.ArrayList(UnresolvedInput), /// Allocated via `gpa`. @@ -2028,11 +2051,11 @@ fn resolveLibInput( .sub_path = try std.fmt.allocPrint(arena, "lib{s}.tbd", .{lib_name}), }; try checked_paths.print(gpa, "\n {f}", .{test_path}); - var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) { + var file = test_path.root_dir.handle.openFile(io, test_path.sub_path, .{}) catch |err| switch (err) { error.FileNotFound => break :tbd, else => |e| fatal("unable to search for tbd library '{f}': {s}", .{ test_path, @errorName(e) }), }; - errdefer file.close(); + errdefer file.close(io); return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query); } @@ -2047,7 +2070,7 @@ fn resolveLibInput( }), }; try checked_paths.print(gpa, "\n {f}", .{test_path}); - switch (try resolvePathInputLib(gpa, arena, unresolved_inputs, resolved_inputs, ld_script_bytes, target, .{ + switch (try resolvePathInputLib(gpa, arena, io, unresolved_inputs, resolved_inputs, ld_script_bytes, target, .{ .path = test_path, .query = name_query.query, }, link_mode, color)) { @@ -2064,13 +2087,13 @@ fn resolveLibInput( .sub_path = try std.fmt.allocPrint(arena, "lib{s}.so", .{lib_name}), }; try checked_paths.print(gpa, "\n {f}", .{test_path}); - var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) { + var file = test_path.root_dir.handle.openFile(io, test_path.sub_path, .{}) catch |err| switch (err) { error.FileNotFound => break :so, else => |e| fatal("unable to search for so library '{f}': {s}", .{ test_path, @errorName(e), }), }; - errdefer file.close(); + errdefer file.close(io); return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query); } @@ -2082,11 +2105,11 @@ fn resolveLibInput( .sub_path = try std.fmt.allocPrint(arena, "lib{s}.a", .{lib_name}), }; try checked_paths.print(gpa, "\n {f}", .{test_path}); - var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) { + var file = test_path.root_dir.handle.openFile(io, test_path.sub_path, .{}) catch |err| switch (err) { error.FileNotFound => break :mingw, else => |e| fatal("unable to search for static library '{f}': {s}", .{ test_path, @errorName(e) }), }; - errdefer file.close(); + errdefer file.close(io); return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query); } @@ -2096,7 +2119,7 @@ fn resolveLibInput( fn finishResolveLibInput( resolved_inputs: *std.ArrayList(Input), path: Path, - file: std.fs.File, + file: Io.File, link_mode: std.builtin.LinkMode, query: UnresolvedInput.Query, ) ResolveLibInputResult { @@ -2121,6 +2144,7 @@ fn finishResolveLibInput( fn resolvePathInput( gpa: Allocator, arena: Allocator, + io: Io, /// Allocated with `gpa`. unresolved_inputs: *std.ArrayList(UnresolvedInput), /// Allocated with `gpa`. @@ -2132,12 +2156,12 @@ fn resolvePathInput( color: std.zig.Color, ) Allocator.Error!?ResolveLibInputResult { switch (Compilation.classifyFileExt(pq.path.sub_path)) { - .static_library => return try resolvePathInputLib(gpa, arena, unresolved_inputs, resolved_inputs, ld_script_bytes, target, pq, .static, color), - .shared_library => return try resolvePathInputLib(gpa, arena, unresolved_inputs, resolved_inputs, ld_script_bytes, target, pq, .dynamic, color), + .static_library => return try resolvePathInputLib(gpa, arena, io, unresolved_inputs, resolved_inputs, ld_script_bytes, target, pq, .static, color), + .shared_library => return try resolvePathInputLib(gpa, arena, io, unresolved_inputs, resolved_inputs, ld_script_bytes, target, pq, .dynamic, color), .object => { - var file = pq.path.root_dir.handle.openFile(pq.path.sub_path, .{}) catch |err| + var file = pq.path.root_dir.handle.openFile(io, pq.path.sub_path, .{}) catch |err| fatal("failed to open object {f}: {s}", .{ pq.path, @errorName(err) }); - errdefer file.close(); + errdefer file.close(io); try resolved_inputs.append(gpa, .{ .object = .{ .path = pq.path, .file = file, @@ -2147,9 +2171,9 @@ fn resolvePathInput( return null; }, .res => { - var file = pq.path.root_dir.handle.openFile(pq.path.sub_path, .{}) catch |err| + var file = pq.path.root_dir.handle.openFile(io, pq.path.sub_path, .{}) catch |err| fatal("failed to open windows resource {f}: {s}", .{ pq.path, @errorName(err) }); - errdefer file.close(); + errdefer file.close(io); try resolved_inputs.append(gpa, .{ .res = .{ .path = pq.path, .file = file, @@ -2163,6 +2187,7 @@ fn resolvePathInput( fn resolvePathInputLib( gpa: Allocator, arena: Allocator, + io: Io, /// Allocated with `gpa`. unresolved_inputs: *std.ArrayList(UnresolvedInput), /// Allocated with `gpa`. @@ -2183,33 +2208,37 @@ fn resolvePathInputLib( .static_library, .shared_library => true, else => false, }) { - var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) { + var file = test_path.root_dir.handle.openFile(io, test_path.sub_path, .{}) catch |err| switch (err) { error.FileNotFound => return .no_match, - else => |e| fatal("unable to search for {s} library '{f}': {s}", .{ - @tagName(link_mode), std.fmt.alt(test_path, .formatEscapeChar), @errorName(e), + else => |e| fatal("unable to search for {t} library '{f}': {t}", .{ + link_mode, std.fmt.alt(test_path, .formatEscapeChar), e, }), }; - errdefer file.close(); + errdefer file.close(io); try ld_script_bytes.resize(gpa, @max(std.elf.MAGIC.len, std.elf.ARMAG.len)); - const n = file.preadAll(ld_script_bytes.items, 0) catch |err| fatal("failed to read '{f}': {s}", .{ - std.fmt.alt(test_path, .formatEscapeChar), @errorName(err), - }); + const n = file.readPositionalAll(io, ld_script_bytes.items, 0) catch |err| + fatal("failed to read '{f}': {t}", .{ std.fmt.alt(test_path, .formatEscapeChar), err }); const buf = ld_script_bytes.items[0..n]; if (mem.startsWith(u8, buf, std.elf.MAGIC) or mem.startsWith(u8, buf, std.elf.ARMAG)) { // Appears to be an ELF or archive file. return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query); } - const stat = file.stat() catch |err| - fatal("failed to stat {f}: {s}", .{ test_path, @errorName(err) }); + const stat = file.stat(io) catch |err| + fatal("failed to stat {f}: {t}", .{ test_path, err }); const size = std.math.cast(u32, stat.size) orelse fatal("{f}: linker script too big", .{test_path}); try ld_script_bytes.resize(gpa, size); const buf2 = ld_script_bytes.items[n..]; - const n2 = file.preadAll(buf2, n) catch |err| - fatal("failed to read {f}: {s}", .{ test_path, @errorName(err) }); + const n2 = file.readPositionalAll(io, buf2, n) catch |err| + fatal("failed to read {f}: {t}", .{ test_path, err }); if (n2 != buf2.len) fatal("failed to read {f}: unexpected end of file", .{test_path}); - var diags = Diags.init(gpa); + + // This `Io` is only used for a mutex, and we know we aren't doing anything async/concurrent. + var threaded: Io.Threaded = .init_single_threaded; + defer threaded.deinit(); + var diags: Diags = .init(gpa, threaded.io()); defer diags.deinit(); + const ld_script_result = LdScript.parse(gpa, &diags, test_path, ld_script_bytes.items); if (diags.hasErrors()) { var wip_errors: std.zig.ErrorBundle.Wip = undefined; @@ -2221,13 +2250,12 @@ fn resolvePathInputLib( var error_bundle = try wip_errors.toOwnedBundle(""); defer error_bundle.deinit(gpa); - error_bundle.renderToStdErr(.{}, color); - + error_bundle.renderToStderr(io, .{}, color) catch {}; std.process.exit(1); } var ld_script = ld_script_result catch |err| - fatal("{f}: failed to parse linker script: {s}", .{ test_path, @errorName(err) }); + fatal("{f}: failed to parse linker script: {t}", .{ test_path, err }); defer ld_script.deinit(gpa); try unresolved_inputs.ensureUnusedCapacity(gpa, ld_script.args.len); @@ -2252,23 +2280,23 @@ fn resolvePathInputLib( } }); } } - file.close(); + file.close(io); return .ok; } - var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) { + var file = test_path.root_dir.handle.openFile(io, test_path.sub_path, .{}) catch |err| switch (err) { error.FileNotFound => return .no_match, else => |e| fatal("unable to search for {s} library {f}: {s}", .{ @tagName(link_mode), test_path, @errorName(e), }), }; - errdefer file.close(); + errdefer file.close(io); return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query); } -pub fn openObject(path: Path, must_link: bool, hidden: bool) !Input.Object { - var file = try path.root_dir.handle.openFile(path.sub_path, .{}); - errdefer file.close(); +pub fn openObject(io: Io, path: Path, must_link: bool, hidden: bool) !Input.Object { + var file = try path.root_dir.handle.openFile(io, path.sub_path, .{}); + errdefer file.close(io); return .{ .path = path, .file = file, @@ -2277,9 +2305,9 @@ pub fn openObject(path: Path, must_link: bool, hidden: bool) !Input.Object { }; } -pub fn openDso(path: Path, needed: bool, weak: bool, reexport: bool) !Input.Dso { - var file = try path.root_dir.handle.openFile(path.sub_path, .{}); - errdefer file.close(); +pub fn openDso(io: Io, path: Path, needed: bool, weak: bool, reexport: bool) !Input.Dso { + var file = try path.root_dir.handle.openFile(io, path.sub_path, .{}); + errdefer file.close(io); return .{ .path = path, .file = file, @@ -2289,20 +2317,20 @@ pub fn openDso(path: Path, needed: bool, weak: bool, reexport: bool) !Input.Dso }; } -pub fn openObjectInput(diags: *Diags, path: Path) error{LinkFailure}!Input { - return .{ .object = openObject(path, false, false) catch |err| { +pub fn openObjectInput(io: Io, diags: *Diags, path: Path) error{LinkFailure}!Input { + return .{ .object = openObject(io, path, false, false) catch |err| { return diags.failParse(path, "failed to open {f}: {s}", .{ path, @errorName(err) }); } }; } -pub fn openArchiveInput(diags: *Diags, path: Path, must_link: bool, hidden: bool) error{LinkFailure}!Input { - return .{ .archive = openObject(path, must_link, hidden) catch |err| { +pub fn openArchiveInput(io: Io, diags: *Diags, path: Path, must_link: bool, hidden: bool) error{LinkFailure}!Input { + return .{ .archive = openObject(io, path, must_link, hidden) catch |err| { return diags.failParse(path, "failed to open {f}: {s}", .{ path, @errorName(err) }); } }; } -pub fn openDsoInput(diags: *Diags, path: Path, needed: bool, weak: bool, reexport: bool) error{LinkFailure}!Input { - return .{ .dso = openDso(path, needed, weak, reexport) catch |err| { +pub fn openDsoInput(io: Io, diags: *Diags, path: Path, needed: bool, weak: bool, reexport: bool) error{LinkFailure}!Input { + return .{ .dso = openDso(io, path, needed, weak, reexport) catch |err| { return diags.failParse(path, "failed to open {f}: {s}", .{ path, @errorName(err) }); } }; } diff --git a/src/link/C.zig b/src/link/C.zig index ce48e85851b1..93e771ebfc3d 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -124,6 +124,7 @@ pub fn createEmpty( emit: Path, options: link.File.OpenOptions, ) !*C { + const io = comp.io; const target = &comp.root_mod.resolved_target.result; assert(target.ofmt == .c); const optimize_mode = comp.root_mod.optimize_mode; @@ -135,11 +136,11 @@ pub fn createEmpty( assert(!use_lld); assert(!use_llvm); - const file = try emit.root_dir.handle.createFile(emit.sub_path, .{ + const file = try emit.root_dir.handle.createFile(io, emit.sub_path, .{ // Truncation is done on `flush`. .truncate = false, }); - errdefer file.close(); + errdefer file.close(io); const c_file = try arena.create(C); @@ -370,6 +371,7 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P const comp = self.base.comp; const diags = &comp.link_diags; const gpa = comp.gpa; + const io = comp.io; const zcu = self.base.comp.zcu.?; const ip = &zcu.intern_pool; const pt: Zcu.PerThread = .activate(zcu, tid); @@ -507,8 +509,8 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P }, self.getString(av_block.code)); const file = self.base.file.?; - file.setEndPos(f.file_size) catch |err| return diags.fail("failed to allocate file: {s}", .{@errorName(err)}); - var fw = file.writer(&.{}); + file.setLength(io, f.file_size) catch |err| return diags.fail("failed to allocate file: {t}", .{err}); + var fw = file.writer(io, &.{}); var w = &fw.interface; w.writeVecAll(f.all_buffers.items) catch |err| switch (err) { error.WriteFailed => return diags.fail("failed to write to '{f}': {s}", .{ @@ -763,6 +765,7 @@ pub fn flushEmitH(zcu: *Zcu) !void { if (true) return; // emit-h is regressed const emit_h = zcu.emit_h orelse return; + const io = zcu.comp.io; // We collect a list of buffers to write, and write them all at once with pwritev 😎 const num_buffers = emit_h.decl_table.count() + 1; @@ -790,14 +793,14 @@ pub fn flushEmitH(zcu: *Zcu) !void { } const directory = emit_h.loc.directory orelse zcu.comp.local_cache_directory; - const file = try directory.handle.createFile(emit_h.loc.basename, .{ + const file = try directory.handle.createFile(io, emit_h.loc.basename, .{ // We set the end position explicitly below; by not truncating the file, we possibly // make it easier on the file system by doing 1 reallocation instead of two. .truncate = false, }); - defer file.close(); + defer file.close(io); - try file.setEndPos(file_size); + try file.setLength(io, file_size); try file.pwritevAll(all_buffers.items, 0); } diff --git a/src/link/Coff.zig b/src/link/Coff.zig index f33e0ccdea8e..03b757f5b4c9 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -1,3 +1,23 @@ +const Coff = @This(); + +const builtin = @import("builtin"); +const native_endian = builtin.cpu.arch.endian(); + +const std = @import("std"); +const Io = std.Io; +const assert = std.debug.assert; +const log = std.log.scoped(.link); + +const codegen = @import("../codegen.zig"); +const Compilation = @import("../Compilation.zig"); +const InternPool = @import("../InternPool.zig"); +const link = @import("../link.zig"); +const MappedFile = @import("MappedFile.zig"); +const target_util = @import("../target.zig"); +const Type = @import("../Type.zig"); +const Value = @import("../Value.zig"); +const Zcu = @import("../Zcu.zig"); + base: link.File, mf: MappedFile, nodes: std.MultiArrayList(Node), @@ -631,12 +651,14 @@ fn create( else => return error.UnsupportedCOFFArchitecture, }; + const io = comp.io; + const coff = try arena.create(Coff); - const file = try path.root_dir.handle.adaptToNewApi().createFile(comp.io, path.sub_path, .{ + const file = try path.root_dir.handle.createFile(io, path.sub_path, .{ .read = true, - .mode = link.File.determineMode(comp.config.output_mode, comp.config.link_mode), + .permissions = link.File.determinePermissions(comp.config.output_mode, comp.config.link_mode), }); - errdefer file.close(comp.io); + errdefer file.close(io); coff.* = .{ .base = .{ .tag = .coff2, @@ -644,14 +666,14 @@ fn create( .comp = comp, .emit = path, - .file = .adaptFromNewApi(file), + .file = file, .gc_sections = false, .print_gc_sections = false, .build_id = .none, .allow_shlib_undefined = false, .stack_size = 0, }, - .mf = try .init(file, comp.gpa), + .mf = try .init(file, comp.gpa, io), .nodes = .empty, .import_table = .{ .ni = .none, @@ -1727,22 +1749,20 @@ pub fn flush( const comp = coff.base.comp; if (comp.compiler_rt_dyn_lib) |crt_file| { const gpa = comp.gpa; + const io = comp.io; const compiler_rt_sub_path = try std.fs.path.join(gpa, &.{ std.fs.path.dirname(coff.base.emit.sub_path) orelse "", std.fs.path.basename(crt_file.full_object_path.sub_path), }); defer gpa.free(compiler_rt_sub_path); - crt_file.full_object_path.root_dir.handle.copyFile( + std.Io.Dir.copyFile( + crt_file.full_object_path.root_dir.handle, crt_file.full_object_path.sub_path, coff.base.emit.root_dir.handle, compiler_rt_sub_path, + io, .{}, - ) catch |err| switch (err) { - else => |e| return comp.link_diags.fail("Copy '{s}' failed: {s}", .{ - compiler_rt_sub_path, - @errorName(e), - }), - }; + ) catch |err| return comp.link_diags.fail("copy '{s}' failed: {t}", .{ compiler_rt_sub_path, err }); } } @@ -2358,10 +2378,16 @@ pub fn deleteExport(coff: *Coff, exported: Zcu.Exported, name: InternPool.NullTe _ = name; } -pub fn dump(coff: *Coff, tid: Zcu.PerThread.Id) void { - const w, _ = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); - coff.printNode(tid, w, .root, 0) catch {}; +pub fn dump(coff: *Coff, tid: Zcu.PerThread.Id) Io.Cancelable!void { + const comp = coff.base.comp; + const io = comp.io; + var buffer: [512]u8 = undefined; + const stderr = try io.lockStderr(&buffer, null); + defer io.unlockStderr(); + const w = &stderr.file_writer.interface; + coff.printNode(tid, w, .root, 0) catch |err| switch (err) { + error.WriteFailed => return stderr.err.?, + }; } pub fn printNode( @@ -2459,19 +2485,3 @@ pub fn printNode( } } } - -const assert = std.debug.assert; -const builtin = @import("builtin"); -const codegen = @import("../codegen.zig"); -const Compilation = @import("../Compilation.zig"); -const Coff = @This(); -const InternPool = @import("../InternPool.zig"); -const link = @import("../link.zig"); -const log = std.log.scoped(.link); -const MappedFile = @import("MappedFile.zig"); -const native_endian = builtin.cpu.arch.endian(); -const std = @import("std"); -const target_util = @import("../target.zig"); -const Type = @import("../Type.zig"); -const Value = @import("../Value.zig"); -const Zcu = @import("../Zcu.zig"); diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 95f4ca8bbd4b..d3fff513f436 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -1,3 +1,24 @@ +const Dwarf = @This(); + +const std = @import("std"); +const Io = std.Io; +const Allocator = std.mem.Allocator; +const DW = std.dwarf; +const Zir = std.zig.Zir; +const assert = std.debug.assert; +const log = std.log.scoped(.dwarf); +const Writer = std.Io.Writer; + +const InternPool = @import("../InternPool.zig"); +const Module = @import("../Package.zig").Module; +const Type = @import("../Type.zig"); +const Value = @import("../Value.zig"); +const Zcu = @import("../Zcu.zig"); +const codegen = @import("../codegen.zig"); +const dev = @import("../dev.zig"); +const link = @import("../link.zig"); +const target_info = @import("../target.zig"); + gpa: Allocator, bin_file: *link.File, format: DW.Format, @@ -27,18 +48,18 @@ pub const UpdateError = error{ EndOfStream, Underflow, UnexpectedEndOfFile, + NonResizable, } || codegen.GenerateSymbolError || - std.fs.File.OpenError || - std.fs.File.SetEndPosError || - std.fs.File.CopyRangeError || - std.fs.File.PReadError || - std.fs.File.PWriteError; + Io.File.OpenError || + Io.File.LengthError || + Io.File.ReadPositionalError || + Io.File.WritePositionalError; pub const FlushError = UpdateError; pub const RelocError = - std.fs.File.PWriteError; + Io.File.PWriteError; pub const AddressSize = enum(u8) { @"32" = 4, @@ -135,11 +156,14 @@ const DebugInfo = struct { fn declAbbrevCode(debug_info: *DebugInfo, unit: Unit.Index, entry: Entry.Index) !AbbrevCode { const dwarf: *Dwarf = @fieldParentPtr("debug_info", debug_info); + const comp = dwarf.bin_file.comp; + const io = comp.io; const unit_ptr = debug_info.section.getUnit(unit); const entry_ptr = unit_ptr.getEntry(entry); if (entry_ptr.len < AbbrevCode.decl_bytes) return .null; var abbrev_code_buf: [AbbrevCode.decl_bytes]u8 = undefined; - if (try dwarf.getFile().?.preadAll( + if (try dwarf.getFile().?.readPositionalAll( + io, &abbrev_code_buf, debug_info.section.off(dwarf) + unit_ptr.off + unit_ptr.header_len + entry_ptr.off, ) != abbrev_code_buf.len) return error.InputOutput; @@ -619,13 +643,10 @@ const Unit = struct { fn move(unit: *Unit, sec: *Section, dwarf: *Dwarf, new_off: u32) UpdateError!void { if (unit.off == new_off) return; - const n = try dwarf.getFile().?.copyRangeAll( - sec.off(dwarf) + unit.off, - dwarf.getFile().?, - sec.off(dwarf) + new_off, - unit.len, - ); - if (n != unit.len) return error.InputOutput; + const comp = dwarf.bin_file.comp; + const io = comp.io; + const file = dwarf.getFile().?; + try link.File.copyRangeAll2(io, file, file, sec.off(dwarf) + unit.off, sec.off(dwarf) + new_off, unit.len); unit.off = new_off; } @@ -655,10 +676,14 @@ const Unit = struct { fn replaceHeader(unit: *Unit, sec: *Section, dwarf: *Dwarf, contents: []const u8) UpdateError!void { assert(contents.len == unit.header_len); - try dwarf.getFile().?.pwriteAll(contents, sec.off(dwarf) + unit.off); + const comp = dwarf.bin_file.comp; + const io = comp.io; + try dwarf.getFile().?.writePositionalAll(io, contents, sec.off(dwarf) + unit.off); } fn writeTrailer(unit: *Unit, sec: *Section, dwarf: *Dwarf) UpdateError!void { + const comp = dwarf.bin_file.comp; + const io = comp.io; const start = unit.off + unit.header_len + if (unit.last.unwrap()) |last_entry| end: { const last_entry_ptr = unit.getEntry(last_entry); break :end last_entry_ptr.off + last_entry_ptr.len; @@ -688,7 +713,7 @@ const Unit = struct { assert(fw.end == extended_op_bytes + op_len_bytes); fw.writeByte(DW.LNE.padding) catch unreachable; assert(fw.end >= unit.trailer_len and fw.end <= len); - return dwarf.getFile().?.pwriteAll(fw.buffered(), sec.off(dwarf) + start); + return dwarf.getFile().?.writePositionalAll(io, fw.buffered(), sec.off(dwarf) + start); } var trailer_aw: Writer.Allocating = try .initCapacity(dwarf.gpa, len); defer trailer_aw.deinit(); @@ -748,7 +773,7 @@ const Unit = struct { assert(tw.end == unit.trailer_len); tw.splatByteAll(fill_byte, len - unit.trailer_len) catch unreachable; assert(tw.end == len); - try dwarf.getFile().?.pwriteAll(trailer_aw.written(), sec.off(dwarf) + start); + try dwarf.getFile().?.writePositionalAll(io, trailer_aw.written(), sec.off(dwarf) + start); } fn resolveRelocs(unit: *Unit, sec: *Section, dwarf: *Dwarf) RelocError!void { @@ -834,6 +859,8 @@ const Entry = struct { dwarf: *Dwarf, ) (UpdateError || Writer.Error)!void { assert(entry.len > 0); + const comp = dwarf.bin_file.comp; + const io = comp.io; const start = entry.off + entry.len; if (sec == &dwarf.debug_frame.section) { const len = if (entry.next.unwrap()) |next_entry| @@ -843,11 +870,11 @@ const Entry = struct { var unit_len_buf: [8]u8 = undefined; const unit_len_bytes = unit_len_buf[0..dwarf.sectionOffsetBytes()]; dwarf.writeInt(unit_len_bytes, len - dwarf.unitLengthBytes()); - try dwarf.getFile().?.pwriteAll(unit_len_bytes, sec.off(dwarf) + unit.off + unit.header_len + entry.off); + try dwarf.getFile().?.writePositionalAll(io, unit_len_bytes, sec.off(dwarf) + unit.off + unit.header_len + entry.off); const buf = try dwarf.gpa.alloc(u8, len - entry.len); defer dwarf.gpa.free(buf); @memset(buf, DW.CFA.nop); - try dwarf.getFile().?.pwriteAll(buf, sec.off(dwarf) + unit.off + unit.header_len + start); + try dwarf.getFile().?.writePositionalAll(io, buf, sec.off(dwarf) + unit.off + unit.header_len + start); return; } const len = unit.getEntry(entry.next.unwrap() orelse return).off - start; @@ -906,7 +933,7 @@ const Entry = struct { }, } else assert(!sec.pad_entries_to_ideal and len == 0); assert(fw.end <= len); - try dwarf.getFile().?.pwriteAll(fw.buffered(), sec.off(dwarf) + unit.off + unit.header_len + start); + try dwarf.getFile().?.writePositionalAll(io, fw.buffered(), sec.off(dwarf) + unit.off + unit.header_len + start); } fn resize( @@ -949,11 +976,13 @@ const Entry = struct { fn replace(entry_ptr: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf, contents: []const u8) UpdateError!void { assert(contents.len == entry_ptr.len); - try dwarf.getFile().?.pwriteAll(contents, sec.off(dwarf) + unit.off + unit.header_len + entry_ptr.off); + const comp = dwarf.bin_file.comp; + const io = comp.io; + try dwarf.getFile().?.writePositionalAll(io, contents, sec.off(dwarf) + unit.off + unit.header_len + entry_ptr.off); if (false) { const buf = try dwarf.gpa.alloc(u8, sec.len); defer dwarf.gpa.free(buf); - _ = try dwarf.getFile().?.preadAll(buf, sec.off(dwarf)); + _ = try dwarf.getFile().?.readPositionalAll(io, buf, sec.off(dwarf)); log.info("Section{{ .first = {}, .last = {}, .off = 0x{x}, .len = 0x{x} }}", .{ @intFromEnum(sec.first), @intFromEnum(sec.last), @@ -3589,7 +3618,7 @@ fn updateLazyType( try wip_nav.strp(name); if (array_type.sentinel != .none) try wip_nav.blockValue(src_loc, .fromInterned(array_type.sentinel)); try wip_nav.refType(array_child_type); - try wip_nav.abbrevCode(.array_index); + try wip_nav.abbrevCode(.array_len); try wip_nav.refType(.usize); try diw.writeUleb128(array_type.len); try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); @@ -3598,7 +3627,7 @@ fn updateLazyType( try wip_nav.abbrevCode(.vector_type); try wip_nav.strp(name); try wip_nav.refType(.fromInterned(vector_type.child)); - try wip_nav.abbrevCode(.array_index); + try wip_nav.abbrevCode(.array_len); try wip_nav.refType(.usize); try diw.writeUleb128(vector_type.len); try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); @@ -4148,24 +4177,38 @@ fn updateLazyValue( try wip_nav.refType(.fromInterned(float.ty)); }, .ptr => |ptr| { + const Access = union(enum) { + index: u64, + field: InternPool.NullTerminatedString, + synthetic_field: []const u8, + tuple_index: u32, + }; + var zero_bit_accesses: std.ArrayList(Access) = .empty; + defer zero_bit_accesses.deinit(dwarf.gpa); location: { var base_addr = ptr.base_addr; var byte_offset = ptr.byte_offset; const base_unit, const base_entry = while (true) { - const base_ptr = base_ptr: switch (base_addr) { + const base_ptr, const access: Access = base_ptr_access: switch (base_addr) { .nav => |nav_index| break try wip_nav.getNavEntry(nav_index), .comptime_alloc, .comptime_field => unreachable, .uav => |uav| { const uav_ty: Type = .fromInterned(ip.typeOf(uav.val)); if (try uav_ty.onePossibleValue(pt)) |_| { - try wip_nav.abbrevCode(.udata_comptime_value); + try wip_nav.abbrevCode(if (zero_bit_accesses.items.len > 0) + .aggregate_udata_comptime_value + else + .udata_comptime_value); try diw.writeUleb128(ip.indexToKey(uav.orig_ty).ptr_type.flags.alignment.toByteUnits() orelse uav_ty.abiAlignment(zcu).toByteUnits().?); break :location; } else break try wip_nav.getValueEntry(.fromInterned(uav.val)); }, .int => { - try wip_nav.abbrevCode(.udata_comptime_value); + try wip_nav.abbrevCode(if (zero_bit_accesses.items.len > 0) + .aggregate_udata_comptime_value + else + .udata_comptime_value); try diw.writeUleb128(byte_offset); break :location; }, @@ -4174,16 +4217,40 @@ fn updateLazyValue( byte_offset += codegen.errUnionPayloadOffset(.fromInterned(ip.indexToKey( ip.indexToKey(base_ptr.ty).ptr_type.child, ).error_union_type.payload_type), zcu); - break :base_ptr base_ptr; + break :base_ptr_access .{ base_ptr, .{ .synthetic_field = "value" } }; + }, + .opt_payload => |opt_ptr| .{ ip.indexToKey(opt_ptr).ptr, .{ .synthetic_field = "?" } }, + .field => |field| { + const base_ptr = ip.indexToKey(field.base).ptr; + const agg_ty: Type = .fromInterned(ip.indexToKey(base_ptr.ty).ptr_type.child); + break :base_ptr_access .{ + base_ptr, + if (agg_ty.isSlice(zcu)) .{ .synthetic_field = switch (field.index) { + Value.slice_ptr_index => "ptr", + Value.slice_len_index => "len", + else => unreachable, + } } else if (agg_ty.structFieldName(@intCast(field.index), zcu).unwrap()) |field_name| + .{ .field = field_name } + else + .{ .tuple_index = @intCast(field.index) }, + }; + }, + .arr_elem => |arr_elem| .{ + ip.indexToKey(arr_elem.base).ptr, + .{ .index = arr_elem.index }, }, - .opt_payload => |opt_ptr| ip.indexToKey(opt_ptr).ptr, - .field => unreachable, - .arr_elem => unreachable, }; base_addr = base_ptr.base_addr; byte_offset += base_ptr.byte_offset; + if (Type.fromInterned(ip.indexToKey(base_ptr.ty).ptr_type.child).hasRuntimeBits(zcu)) + assert(access != .index) + else + try zero_bit_accesses.append(dwarf.gpa, access); }; - try wip_nav.abbrevCode(.location_comptime_value); + try wip_nav.abbrevCode(if (zero_bit_accesses.items.len > 0) + .aggregate_location_comptime_value + else + .location_comptime_value); try wip_nav.infoExprLoc(.{ .implicit_pointer = .{ .unit = base_unit, .entry = base_entry, @@ -4191,6 +4258,29 @@ fn updateLazyValue( } }); } try wip_nav.refType(.fromInterned(ptr.ty)); + if (zero_bit_accesses.items.len > 0) { + for (zero_bit_accesses.items) |access| switch (access) { + .index => |index| { + try wip_nav.abbrevCode(.array_index); + try diw.writeUleb128(index); + }, + .field => |field| { + try wip_nav.abbrevCode(.field); + try wip_nav.strp(field.toSlice(ip)); + }, + .synthetic_field => |field| { + try wip_nav.abbrevCode(.field); + try wip_nav.strp(field); + }, + .tuple_index => |index| { + try wip_nav.abbrevCode(.field); + var field_name_buf: [std.fmt.count("{d}", .{std.math.maxInt(u32)})]u8 = undefined; + const field_name = std.fmt.bufPrint(&field_name_buf, "{d}", .{index}) catch unreachable; + try wip_nav.strp(field_name); + }, + }; + try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); + } }, .slice => |slice| { try wip_nav.abbrevCode(.aggregate_comptime_value); @@ -4358,12 +4448,7 @@ fn updateLazyValue( try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written()); } -fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum { - unpacked, - opv_null, - error_set, - pointer, -} { +fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum { unpacked, opv_null, error_set, pointer } { if (opt_child_type.isNoReturn(zcu)) return .opv_null; return switch (opt_child_type.toIntern()) { .anyerror_type => .error_set, @@ -4682,6 +4767,8 @@ fn updateContainerTypeWriterError( } pub fn updateLineNumber(dwarf: *Dwarf, zcu: *Zcu, zir_index: InternPool.TrackedInst.Index) UpdateError!void { + const comp = dwarf.bin_file.comp; + const io = comp.io; const ip = &zcu.intern_pool; const inst_info = zir_index.resolveFull(ip).?; @@ -4701,7 +4788,7 @@ pub fn updateLineNumber(dwarf: *Dwarf, zcu: *Zcu, zir_index: InternPool.TrackedI const unit = dwarf.debug_info.section.getUnit(dwarf.getUnitIfExists(file.mod.?) orelse return); const entry = unit.getEntry(dwarf.decls.get(zir_index) orelse return); - try dwarf.getFile().?.pwriteAll(&line_buf, dwarf.debug_info.section.off(dwarf) + unit.off + unit.header_len + entry.off + DebugInfo.declEntryLineOff(dwarf)); + try dwarf.getFile().?.writePositionalAll(io, &line_buf, dwarf.debug_info.section.off(dwarf) + unit.off + unit.header_len + entry.off + DebugInfo.declEntryLineOff(dwarf)); } pub fn freeNav(dwarf: *Dwarf, nav_index: InternPool.Nav.Index) void { @@ -4738,6 +4825,8 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (FlushError || Writer.Error)!void { const zcu = pt.zcu; const ip = &zcu.intern_pool; + const comp = dwarf.bin_file.comp; + const io = comp.io; { const type_gop = try dwarf.types.getOrPut(dwarf.gpa, .anyerror_type); @@ -4957,7 +5046,7 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (FlushError || Writer.Erro if (dwarf.debug_str.section.dirty) { const contents = dwarf.debug_str.contents.items; try dwarf.debug_str.section.resize(dwarf, contents.len); - try dwarf.getFile().?.pwriteAll(contents, dwarf.debug_str.section.off(dwarf)); + try dwarf.getFile().?.writePositionalAll(io, contents, dwarf.debug_str.section.off(dwarf)); dwarf.debug_str.section.dirty = false; } if (dwarf.debug_line.section.dirty) { @@ -5069,7 +5158,7 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (FlushError || Writer.Erro if (dwarf.debug_line_str.section.dirty) { const contents = dwarf.debug_line_str.contents.items; try dwarf.debug_line_str.section.resize(dwarf, contents.len); - try dwarf.getFile().?.pwriteAll(contents, dwarf.debug_line_str.section.off(dwarf)); + try dwarf.getFile().?.writePositionalAll(io, contents, dwarf.debug_line_str.section.off(dwarf)); dwarf.debug_line_str.section.dirty = false; } if (dwarf.debug_loclists.section.dirty) { @@ -5200,6 +5289,7 @@ const AbbrevCode = enum { module, empty_file, file, + field, signed_enum_field, unsigned_enum_field, big_enum_field, @@ -5228,6 +5318,7 @@ const AbbrevCode = enum { array_sentinel_type, vector_type, array_index, + array_len, nullary_func_type, func_type, func_type_param, @@ -5275,10 +5366,12 @@ const AbbrevCode = enum { data16_comptime_value, sdata_comptime_value, udata_comptime_value, + aggregate_udata_comptime_value, block_comptime_value, string_comptime_value, location_comptime_value, aggregate_comptime_value, + aggregate_location_comptime_value, comptime_value_field_runtime_bits, comptime_value_field_comptime_state, comptime_value_elem_runtime_bits, @@ -5688,6 +5781,12 @@ const AbbrevCode = enum { .{ .alignment, .udata }, }, }, + .field = .{ + .tag = .member, + .attrs = &.{ + .{ .name, .strp }, + }, + }, .signed_enum_field = .{ .tag = .enumerator, .attrs = &.{ @@ -5903,6 +6002,12 @@ const AbbrevCode = enum { }, }, .array_index = .{ + .tag = .subrange_type, + .attrs = &.{ + .{ .lower_bound, .udata }, + }, + }, + .array_len = .{ .tag = .subrange_type, .attrs = &.{ .{ .type, .ref_addr }, @@ -6292,6 +6397,14 @@ const AbbrevCode = enum { .{ .type, .ref_addr }, }, }, + .aggregate_udata_comptime_value = .{ + .tag = .ZIG_comptime_value, + .children = true, + .attrs = &.{ + .{ .const_value, .udata }, + .{ .type, .ref_addr }, + }, + }, .block_comptime_value = .{ .tag = .ZIG_comptime_value, .attrs = &.{ @@ -6320,6 +6433,14 @@ const AbbrevCode = enum { .{ .type, .ref_addr }, }, }, + .aggregate_location_comptime_value = .{ + .tag = .ZIG_comptime_value, + .children = true, + .attrs = &.{ + .{ .location, .exprloc }, + .{ .type, .ref_addr }, + }, + }, .comptime_value_field_runtime_bits = .{ .tag = .member, .attrs = &.{ @@ -6350,7 +6471,7 @@ const AbbrevCode = enum { }); }; -fn getFile(dwarf: *Dwarf) ?std.fs.File { +fn getFile(dwarf: *Dwarf) ?Io.File { if (dwarf.bin_file.cast(.macho)) |macho_file| if (macho_file.d_sym) |*d_sym| return d_sym.file; return dwarf.bin_file.file; } @@ -6391,9 +6512,11 @@ fn writeInt(dwarf: *Dwarf, buf: []u8, int: u64) void { } fn resolveReloc(dwarf: *Dwarf, source: u64, target: u64, size: u32) RelocError!void { + const comp = dwarf.bin_file.comp; + const io = comp.io; var buf: [8]u8 = undefined; dwarf.writeInt(buf[0..size], target); - try dwarf.getFile().?.pwriteAll(buf[0..size], source); + try dwarf.getFile().?.writePositionalAll(io, buf[0..size], source); } fn unitLengthBytes(dwarf: *Dwarf) u32 { @@ -6429,21 +6552,3 @@ const force_incremental = false; inline fn incremental(dwarf: Dwarf) bool { return force_incremental or dwarf.bin_file.comp.config.incremental; } - -const Allocator = std.mem.Allocator; -const DW = std.dwarf; -const Dwarf = @This(); -const InternPool = @import("../InternPool.zig"); -const Module = @import("../Package.zig").Module; -const Type = @import("../Type.zig"); -const Value = @import("../Value.zig"); -const Zcu = @import("../Zcu.zig"); -const Zir = std.zig.Zir; -const assert = std.debug.assert; -const codegen = @import("../codegen.zig"); -const dev = @import("../dev.zig"); -const link = @import("../link.zig"); -const log = std.log.scoped(.dwarf); -const std = @import("std"); -const target_info = @import("../target.zig"); -const Writer = std.Io.Writer; diff --git a/src/link/Elf.zig b/src/link/Elf.zig index fa41c6b1deb2..85f37f88ce8b 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -313,12 +313,14 @@ pub fn createEmpty( const is_obj = output_mode == .Obj; const is_obj_or_ar = is_obj or (output_mode == .Lib and link_mode == .static); + const io = comp.io; + // What path should this ELF linker code output to? const sub_path = emit.sub_path; - self.base.file = try emit.root_dir.handle.createFile(sub_path, .{ + self.base.file = try emit.root_dir.handle.createFile(io, sub_path, .{ .truncate = true, .read = true, - .mode = link.File.determineMode(output_mode, link_mode), + .permissions = link.File.determinePermissions(output_mode, link_mode), }); const gpa = comp.gpa; @@ -406,10 +408,12 @@ pub fn open( } pub fn deinit(self: *Elf) void { - const gpa = self.base.comp.gpa; + const comp = self.base.comp; + const gpa = comp.gpa; + const io = comp.io; for (self.file_handles.items) |fh| { - fh.close(); + fh.close(io); } self.file_handles.deinit(gpa); @@ -483,6 +487,8 @@ pub fn getUavVAddr(self: *Elf, uav: InternPool.Index, reloc_info: link.File.Relo /// Returns end pos of collision, if any. fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 { + const comp = self.base.comp; + const io = comp.io; const small_ptr = self.ptr_width == .p32; const ehdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Ehdr) else @sizeOf(elf.Elf64_Ehdr); if (start < ehdr_size) @@ -522,7 +528,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 { } } - if (at_end) try self.base.file.?.setEndPos(end); + if (at_end) try self.base.file.?.setLength(io, end); return null; } @@ -552,6 +558,8 @@ pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) !u64 { } pub fn growSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment: u64) !void { + const comp = self.base.comp; + const io = comp.io; const shdr = &self.sections.items(.shdr)[shdr_index]; if (shdr.sh_type != elf.SHT_NOBITS) { @@ -574,18 +582,11 @@ pub fn growSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment: new_offset, }); - const amt = try self.base.file.?.copyRangeAll( - shdr.sh_offset, - self.base.file.?, - new_offset, - existing_size, - ); - // TODO figure out what to about this error condition - how to communicate it up. - if (amt != existing_size) return error.InputOutput; + try self.base.copyRangeAll(shdr.sh_offset, new_offset, existing_size); shdr.sh_offset = new_offset; } else if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) { - try self.base.file.?.setEndPos(shdr.sh_offset + needed_size); + try self.base.file.?.setLength(io, shdr.sh_offset + needed_size); } } @@ -713,6 +714,7 @@ pub fn allocateChunk(self: *Elf, args: struct { pub fn loadInput(self: *Elf, input: link.Input) !void { const comp = self.base.comp; const gpa = comp.gpa; + const io = comp.io; const diags = &comp.link_diags; const target = self.getTarget(); const debug_fmt_strip = comp.config.debug_format == .strip; @@ -720,8 +722,8 @@ pub fn loadInput(self: *Elf, input: link.Input) !void { const is_static_lib = self.base.isStaticLib(); if (comp.verbose_link) { - comp.mutex.lock(); // protect comp.arena - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); // protect comp.arena + defer comp.mutex.unlock(io); const argv = &self.dump_argv_list; switch (input) { @@ -736,8 +738,8 @@ pub fn loadInput(self: *Elf, input: link.Input) !void { .res => unreachable, .dso_exact => @panic("TODO"), .object => |obj| try parseObject(self, obj), - .archive => |obj| try parseArchive(gpa, diags, &self.file_handles, &self.files, target, debug_fmt_strip, default_sym_version, &self.objects, obj, is_static_lib), - .dso => |dso| try parseDso(gpa, diags, dso, &self.shared_objects, &self.files, target), + .archive => |obj| try parseArchive(gpa, io, diags, &self.file_handles, &self.files, target, debug_fmt_strip, default_sym_version, &self.objects, obj, is_static_lib), + .dso => |dso| try parseDso(gpa, io, diags, dso, &self.shared_objects, &self.files, target), } } @@ -746,9 +748,10 @@ pub fn flush(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std defer tracy.end(); const comp = self.base.comp; + const io = comp.io; const diags = &comp.link_diags; - if (comp.verbose_link) Compilation.dump_argv(self.dump_argv_list.items); + if (comp.verbose_link) try Compilation.dumpArgv(io, self.dump_argv_list.items); const sub_prog_node = prog_node.start("ELF Flush", 0); defer sub_prog_node.end(); @@ -756,7 +759,7 @@ pub fn flush(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std return flushInner(self, arena, tid) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.LinkFailure => return error.LinkFailure, - else => |e| return diags.fail("ELF flush failed: {s}", .{@errorName(e)}), + else => |e| return diags.fail("ELF flush failed: {t}", .{e}), }; } @@ -1046,9 +1049,11 @@ fn dumpArgvInit(self: *Elf, arena: Allocator) !void { } pub fn openParseObjectReportingFailure(self: *Elf, path: Path) void { - const diags = &self.base.comp.link_diags; - const obj = link.openObject(path, false, false) catch |err| { - switch (diags.failParse(path, "failed to open object: {s}", .{@errorName(err)})) { + const comp = self.base.comp; + const io = comp.io; + const diags = &comp.link_diags; + const obj = link.openObject(io, path, false, false) catch |err| { + switch (diags.failParse(path, "failed to open object: {t}", .{err})) { error.LinkFailure => return, } }; @@ -1056,10 +1061,11 @@ pub fn openParseObjectReportingFailure(self: *Elf, path: Path) void { } fn parseObjectReportingFailure(self: *Elf, obj: link.Input.Object) void { - const diags = &self.base.comp.link_diags; + const comp = self.base.comp; + const diags = &comp.link_diags; self.parseObject(obj) catch |err| switch (err) { error.LinkFailure => return, // already reported - else => |e| diags.addParseError(obj.path, "failed to parse object: {s}", .{@errorName(e)}), + else => |e| diags.addParseError(obj.path, "failed to parse object: {t}", .{e}), }; } @@ -1067,10 +1073,12 @@ fn parseObject(self: *Elf, obj: link.Input.Object) !void { const tracy = trace(@src()); defer tracy.end(); - const gpa = self.base.comp.gpa; - const diags = &self.base.comp.link_diags; - const target = &self.base.comp.root_mod.resolved_target.result; - const debug_fmt_strip = self.base.comp.config.debug_format == .strip; + const comp = self.base.comp; + const io = comp.io; + const gpa = comp.gpa; + const diags = &comp.link_diags; + const target = &comp.root_mod.resolved_target.result; + const debug_fmt_strip = comp.config.debug_format == .strip; const default_sym_version = self.default_sym_version; const file_handles = &self.file_handles; @@ -1089,14 +1097,15 @@ fn parseObject(self: *Elf, obj: link.Input.Object) !void { try self.objects.append(gpa, index); const object = self.file(index).?.object; - try object.parseCommon(gpa, diags, obj.path, handle, target); + try object.parseCommon(gpa, io, diags, obj.path, handle, target); if (!self.base.isStaticLib()) { - try object.parse(gpa, diags, obj.path, handle, target, debug_fmt_strip, default_sym_version); + try object.parse(gpa, io, diags, obj.path, handle, target, debug_fmt_strip, default_sym_version); } } fn parseArchive( gpa: Allocator, + io: Io, diags: *Diags, file_handles: *std.ArrayList(File.Handle), files: *std.MultiArrayList(File.Entry), @@ -1111,7 +1120,7 @@ fn parseArchive( defer tracy.end(); const fh = try addFileHandle(gpa, file_handles, obj.file); - var archive = try Archive.parse(gpa, diags, file_handles, obj.path, fh); + var archive = try Archive.parse(gpa, io, diags, file_handles, obj.path, fh); defer archive.deinit(gpa); const init_alive = if (is_static_lib) true else obj.must_link; @@ -1122,15 +1131,16 @@ fn parseArchive( const object = &files.items(.data)[index].object; object.index = index; object.alive = init_alive; - try object.parseCommon(gpa, diags, obj.path, obj.file, target); + try object.parseCommon(gpa, io, diags, obj.path, obj.file, target); if (!is_static_lib) - try object.parse(gpa, diags, obj.path, obj.file, target, debug_fmt_strip, default_sym_version); + try object.parse(gpa, io, diags, obj.path, obj.file, target, debug_fmt_strip, default_sym_version); try objects.append(gpa, index); } } fn parseDso( gpa: Allocator, + io: Io, diags: *Diags, dso: link.Input.Dso, shared_objects: *std.StringArrayHashMapUnmanaged(File.Index), @@ -1142,8 +1152,8 @@ fn parseDso( const handle = dso.file; - const stat = Stat.fromFs(try handle.stat()); - var header = try SharedObject.parseHeader(gpa, diags, dso.path, handle, stat, target); + const stat = Stat.fromFs(try handle.stat(io)); + var header = try SharedObject.parseHeader(gpa, io, diags, dso.path, handle, stat, target); defer header.deinit(gpa); const soname = header.soname() orelse dso.path.basename(); @@ -1157,7 +1167,7 @@ fn parseDso( gop.value_ptr.* = index; - var parsed = try SharedObject.parse(gpa, &header, handle); + var parsed = try SharedObject.parse(gpa, io, &header, handle); errdefer parsed.deinit(gpa); const duped_path: Path = .{ @@ -2887,13 +2897,7 @@ pub fn allocateAllocSections(self: *Elf) !void { if (shdr.sh_offset > 0) { // Get size actually commited to the output file. const existing_size = self.sectionSize(shndx); - const amt = try self.base.file.?.copyRangeAll( - shdr.sh_offset, - self.base.file.?, - new_offset, - existing_size, - ); - if (amt != existing_size) return error.InputOutput; + try self.base.copyRangeAll(shdr.sh_offset, new_offset, existing_size); } shdr.sh_offset = new_offset; @@ -2929,13 +2933,7 @@ pub fn allocateNonAllocSections(self: *Elf) !void { if (shdr.sh_offset > 0) { const existing_size = self.sectionSize(@intCast(shndx)); - const amt = try self.base.file.?.copyRangeAll( - shdr.sh_offset, - self.base.file.?, - new_offset, - existing_size, - ); - if (amt != existing_size) return error.InputOutput; + try self.base.copyRangeAll(shdr.sh_offset, new_offset, existing_size); } shdr.sh_offset = new_offset; @@ -3648,7 +3646,7 @@ fn fileLookup(files: std.MultiArrayList(File.Entry), index: File.Index, zig_obje pub fn addFileHandle( gpa: Allocator, file_handles: *std.ArrayList(File.Handle), - handle: fs.File, + handle: Io.File, ) Allocator.Error!File.HandleIndex { try file_handles.append(gpa, handle); return @intCast(file_handles.items.len - 1); @@ -4065,10 +4063,10 @@ fn fmtDumpState(self: *Elf, writer: *std.Io.Writer) std.Io.Writer.Error!void { } /// Caller owns the memory. -pub fn preadAllAlloc(allocator: Allocator, handle: fs.File, offset: u64, size: u64) ![]u8 { +pub fn preadAllAlloc(allocator: Allocator, io: Io, io_file: Io.File, offset: u64, size: u64) ![]u8 { const buffer = try allocator.alloc(u8, math.cast(usize, size) orelse return error.Overflow); errdefer allocator.free(buffer); - const amt = try handle.preadAll(buffer, offset); + const amt = try io_file.readPositionalAll(io, buffer, offset); if (amt != size) return error.InputOutput; return buffer; } @@ -4434,16 +4432,17 @@ pub fn stringTableLookup(strtab: []const u8, off: u32) [:0]const u8 { pub fn pwriteAll(elf_file: *Elf, bytes: []const u8, offset: u64) error{LinkFailure}!void { const comp = elf_file.base.comp; + const io = comp.io; const diags = &comp.link_diags; - elf_file.base.file.?.pwriteAll(bytes, offset) catch |err| { - return diags.fail("failed to write: {s}", .{@errorName(err)}); - }; + elf_file.base.file.?.writePositionalAll(io, bytes, offset) catch |err| + return diags.fail("failed to write: {t}", .{err}); } -pub fn setEndPos(elf_file: *Elf, length: u64) error{LinkFailure}!void { +pub fn setLength(elf_file: *Elf, length: u64) error{LinkFailure}!void { const comp = elf_file.base.comp; + const io = comp.i; const diags = &comp.link_diags; - elf_file.base.file.?.setEndPos(length) catch |err| { + elf_file.base.file.?.setLength(io, length) catch |err| { return diags.fail("failed to set file end pos: {s}", .{@errorName(err)}); }; } @@ -4457,6 +4456,7 @@ pub fn cast(elf_file: *Elf, comptime T: type, x: anytype) error{LinkFailure}!T { } const std = @import("std"); +const Io = std.Io; const build_options = @import("build_options"); const builtin = @import("builtin"); const assert = std.debug.assert; diff --git a/src/link/Elf/Archive.zig b/src/link/Elf/Archive.zig index a9961bf8f90e..14f2868956f9 100644 --- a/src/link/Elf/Archive.zig +++ b/src/link/Elf/Archive.zig @@ -1,3 +1,21 @@ +const Archive = @This(); + +const std = @import("std"); +const Io = std.Io; +const assert = std.debug.assert; +const elf = std.elf; +const fs = std.fs; +const log = std.log.scoped(.link); +const mem = std.mem; +const Path = std.Build.Cache.Path; +const Allocator = std.mem.Allocator; + +const Diags = @import("../../link.zig").Diags; +const Elf = @import("../Elf.zig"); +const File = @import("file.zig").File; +const Object = @import("Object.zig"); +const StringTable = @import("../StringTable.zig"); + objects: []const Object, /// '\n'-delimited strtab: []const u8, @@ -10,22 +28,23 @@ pub fn deinit(a: *Archive, gpa: Allocator) void { pub fn parse( gpa: Allocator, + io: Io, diags: *Diags, file_handles: *const std.ArrayList(File.Handle), path: Path, handle_index: File.HandleIndex, ) !Archive { - const handle = file_handles.items[handle_index]; + const file = file_handles.items[handle_index]; var pos: usize = 0; { var magic_buffer: [elf.ARMAG.len]u8 = undefined; - const n = try handle.preadAll(&magic_buffer, pos); + const n = try file.readPositionalAll(io, &magic_buffer, pos); if (n != magic_buffer.len) return error.BadMagic; if (!mem.eql(u8, &magic_buffer, elf.ARMAG)) return error.BadMagic; pos += magic_buffer.len; } - const size = (try handle.stat()).size; + const size = (try file.stat(io)).size; var objects: std.ArrayList(Object) = .empty; defer objects.deinit(gpa); @@ -36,7 +55,7 @@ pub fn parse( while (pos < size) { var hdr: elf.ar_hdr = undefined; { - const n = try handle.preadAll(mem.asBytes(&hdr), pos); + const n = try file.readPositionalAll(io, mem.asBytes(&hdr), pos); if (n != @sizeOf(elf.ar_hdr)) return error.UnexpectedEndOfFile; } pos += @sizeOf(elf.ar_hdr); @@ -53,7 +72,7 @@ pub fn parse( if (hdr.isSymtab() or hdr.isSymtab64()) continue; if (hdr.isStrtab()) { try strtab.resize(gpa, obj_size); - const amt = try handle.preadAll(strtab.items, pos); + const amt = try file.readPositionalAll(io, strtab.items, pos); if (amt != obj_size) return error.InputOutput; continue; } @@ -120,7 +139,7 @@ pub fn setArHdr(opts: struct { @memset(mem.asBytes(&hdr), 0x20); { - var writer: std.Io.Writer = .fixed(&hdr.ar_name); + var writer: Io.Writer = .fixed(&hdr.ar_name); switch (opts.name) { .symtab => writer.print("{s}", .{elf.SYM64NAME}) catch unreachable, .strtab => writer.print("//", .{}) catch unreachable, @@ -133,7 +152,7 @@ pub fn setArHdr(opts: struct { hdr.ar_gid[0] = '0'; hdr.ar_mode[0] = '0'; { - var writer: std.Io.Writer = .fixed(&hdr.ar_size); + var writer: Io.Writer = .fixed(&hdr.ar_size); writer.print("{d}", .{opts.size}) catch unreachable; } hdr.ar_fmag = elf.ARFMAG.*; @@ -206,7 +225,7 @@ pub const ArSymtab = struct { ar: ArSymtab, elf_file: *Elf, - fn default(f: Format, writer: *std.Io.Writer) std.Io.Writer.Error!void { + fn default(f: Format, writer: *Io.Writer) Io.Writer.Error!void { const ar = f.ar; const elf_file = f.elf_file; for (ar.symtab.items, 0..) |entry, i| { @@ -261,7 +280,7 @@ pub const ArStrtab = struct { try writer.writeAll(ar.buffer.items); } - pub fn format(ar: ArStrtab, writer: *std.Io.Writer) std.Io.Writer.Error!void { + pub fn format(ar: ArStrtab, writer: *Io.Writer) Io.Writer.Error!void { try writer.print("{f}", .{std.ascii.hexEscape(ar.buffer.items, .lower)}); } }; @@ -277,19 +296,3 @@ pub const ArState = struct { /// Total size of the contributing object (excludes ar_hdr). size: u64 = 0, }; - -const std = @import("std"); -const assert = std.debug.assert; -const elf = std.elf; -const fs = std.fs; -const log = std.log.scoped(.link); -const mem = std.mem; -const Path = std.Build.Cache.Path; -const Allocator = std.mem.Allocator; - -const Diags = @import("../../link.zig").Diags; -const Archive = @This(); -const Elf = @import("../Elf.zig"); -const File = @import("file.zig").File; -const Object = @import("Object.zig"); -const StringTable = @import("../StringTable.zig"); diff --git a/src/link/Elf/Atom.zig b/src/link/Elf/Atom.zig index 8d8bc71a3065..80ca049deb6c 100644 --- a/src/link/Elf/Atom.zig +++ b/src/link/Elf/Atom.zig @@ -1499,22 +1499,18 @@ const aarch64 = struct { .ABS64 => { try atom.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file); }, - .ADR_PREL_PG_HI21 => { try atom.scanReloc(symbol, rel, pcRelocAction(symbol, elf_file), elf_file); }, - .ADR_GOT_PAGE => { // TODO: relax if possible symbol.flags.needs_got = true; }, - .LD64_GOT_LO12_NC, .LD64_GOTPAGE_LO15, => { symbol.flags.needs_got = true; }, - .CALL26, .JUMP26, => { @@ -1522,25 +1518,21 @@ const aarch64 = struct { symbol.flags.needs_plt = true; } }, - .TLSLE_ADD_TPREL_HI12, .TLSLE_ADD_TPREL_LO12_NC, => { if (is_dyn_lib) try atom.reportPicError(symbol, rel, elf_file); }, - .TLSIE_ADR_GOTTPREL_PAGE21, .TLSIE_LD64_GOTTPREL_LO12_NC, => { symbol.flags.needs_gottp = true; }, - .TLSGD_ADR_PAGE21, .TLSGD_ADD_LO12_NC, => { symbol.flags.needs_tlsgd = true; }, - .TLSDESC_ADR_PAGE21, .TLSDESC_LD64_LO12, .TLSDESC_ADD_LO12, @@ -1551,18 +1543,17 @@ const aarch64 = struct { symbol.flags.needs_tlsdesc = true; } }, - .ADD_ABS_LO12_NC, .ADR_PREL_LO21, - .LDST8_ABS_LO12_NC, + .CONDBR19, + .LDST128_ABS_LO12_NC, .LDST16_ABS_LO12_NC, .LDST32_ABS_LO12_NC, .LDST64_ABS_LO12_NC, - .LDST128_ABS_LO12_NC, + .LDST8_ABS_LO12_NC, .PREL32, .PREL64, => {}, - else => try atom.reportUnhandledRelocError(rel, elf_file), } } @@ -1599,7 +1590,6 @@ const aarch64 = struct { r_offset, ); }, - .CALL26, .JUMP26, => { @@ -1611,27 +1601,26 @@ const aarch64 = struct { }; util.writeBranchImm(disp, code); }, - + .CONDBR19 => { + const value = math.cast(i19, S + A - P) orelse return error.Overflow; + util.writeCondBrImm(value, code); + }, .PREL32 => { const value = math.cast(i32, S + A - P) orelse return error.Overflow; mem.writeInt(u32, code, @bitCast(value), .little); }, - .PREL64 => { const value = S + A - P; mem.writeInt(u64, code_buffer[r_offset..][0..8], @bitCast(value), .little); }, - .ADR_PREL_LO21 => { const value = math.cast(i21, S + A - P) orelse return error.Overflow; util.writeAdrInst(value, code); }, - .ADR_PREL_PG_HI21 => { // TODO: check for relaxation of ADRP+ADD util.writeAdrInst(try util.calcNumberOfPages(P, S + A), code); }, - .ADR_GOT_PAGE => if (target.flags.has_got) { util.writeAdrInst(try util.calcNumberOfPages(P, G + GOT + A), code); } else { @@ -1644,18 +1633,15 @@ const aarch64 = struct { r_offset, }); }, - .LD64_GOT_LO12_NC => { assert(target.flags.has_got); const taddr = @as(u64, @intCast(G + GOT + A)); util.writeLoadStoreRegInst(@divExact(@as(u12, @truncate(taddr)), 8), code); }, - .ADD_ABS_LO12_NC => { const taddr = @as(u64, @intCast(S + A)); util.writeAddImmInst(@truncate(taddr), code); }, - .LDST8_ABS_LO12_NC, .LDST16_ABS_LO12_NC, .LDST32_ABS_LO12_NC, @@ -1674,44 +1660,37 @@ const aarch64 = struct { }; util.writeLoadStoreRegInst(off, code); }, - .TLSLE_ADD_TPREL_HI12 => { const value = math.cast(i12, (S + A - TP) >> 12) orelse return error.Overflow; util.writeAddImmInst(@bitCast(value), code); }, - .TLSLE_ADD_TPREL_LO12_NC => { const value: i12 = @truncate(S + A - TP); util.writeAddImmInst(@bitCast(value), code); }, - .TLSIE_ADR_GOTTPREL_PAGE21 => { const S_ = target.gotTpAddress(elf_file); relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); util.writeAdrInst(try util.calcNumberOfPages(P, S_ + A), code); }, - .TLSIE_LD64_GOTTPREL_LO12_NC => { const S_ = target.gotTpAddress(elf_file); relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); const off: u12 = try math.divExact(u12, @truncate(@as(u64, @bitCast(S_ + A))), 8); util.writeLoadStoreRegInst(off, code); }, - .TLSGD_ADR_PAGE21 => { const S_ = target.tlsGdAddress(elf_file); relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); util.writeAdrInst(try util.calcNumberOfPages(P, S_ + A), code); }, - .TLSGD_ADD_LO12_NC => { const S_ = target.tlsGdAddress(elf_file); relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); const off: u12 = @truncate(@as(u64, @bitCast(S_ + A))); util.writeAddImmInst(off, code); }, - .TLSDESC_ADR_PAGE21 => { if (target.flags.has_tlsdesc) { const S_ = target.tlsDescAddress(elf_file); @@ -1722,7 +1701,6 @@ const aarch64 = struct { util.encoding.Instruction.nop().write(code); } }, - .TLSDESC_LD64_LO12 => { if (target.flags.has_tlsdesc) { const S_ = target.tlsDescAddress(elf_file); @@ -1734,7 +1712,6 @@ const aarch64 = struct { util.encoding.Instruction.nop().write(code); } }, - .TLSDESC_ADD_LO12 => { if (target.flags.has_tlsdesc) { const S_ = target.tlsDescAddress(elf_file); @@ -1747,13 +1724,11 @@ const aarch64 = struct { util.encoding.Instruction.movz(.x0, value, .{ .lsl = .@"16" }).write(code); } }, - .TLSDESC_CALL => if (!target.flags.has_tlsdesc) { relocs_log.debug(" relaxing br => movk(x0, {x})", .{S + A - TP}); const value: u16 = @bitCast(@as(i16, @truncate(S + A - TP))); util.encoding.Instruction.movk(.x0, value, .{}).write(code); }, - else => try atom.reportUnhandledRelocError(rel, elf_file), } } diff --git a/src/link/Elf/AtomList.zig b/src/link/Elf/AtomList.zig index 8fdf5551159a..9350f1a276b1 100644 --- a/src/link/Elf/AtomList.zig +++ b/src/link/Elf/AtomList.zig @@ -90,7 +90,9 @@ pub fn allocate(list: *AtomList, elf_file: *Elf) !void { } pub fn write(list: AtomList, buffer: *std.Io.Writer.Allocating, undefs: anytype, elf_file: *Elf) !void { - const gpa = elf_file.base.comp.gpa; + const comp = elf_file.base.comp; + const gpa = comp.gpa; + const io = comp.io; const osec = elf_file.sections.items(.shdr)[list.output_section_index]; assert(osec.sh_type != elf.SHT_NOBITS); assert(!list.dirty); @@ -121,12 +123,14 @@ pub fn write(list: AtomList, buffer: *std.Io.Writer.Allocating, undefs: anytype, try atom_ptr.resolveRelocsAlloc(elf_file, out_code); } - try elf_file.base.file.?.pwriteAll(buffer.written(), list.offset(elf_file)); + try elf_file.base.file.?.writePositionalAll(io, buffer.written(), list.offset(elf_file)); buffer.clearRetainingCapacity(); } pub fn writeRelocatable(list: AtomList, buffer: *std.array_list.Managed(u8), elf_file: *Elf) !void { - const gpa = elf_file.base.comp.gpa; + const comp = elf_file.base.comp; + const gpa = comp.gpa; + const io = comp.io; const osec = elf_file.sections.items(.shdr)[list.output_section_index]; assert(osec.sh_type != elf.SHT_NOBITS); @@ -152,7 +156,7 @@ pub fn writeRelocatable(list: AtomList, buffer: *std.array_list.Managed(u8), elf @memcpy(out_code, code); } - try elf_file.base.file.?.pwriteAll(buffer.items, list.offset(elf_file)); + try elf_file.base.file.?.writePositionalAll(io, buffer.items, list.offset(elf_file)); buffer.clearRetainingCapacity(); } diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index d51a82b26607..ebdd1f20989a 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -1,3 +1,30 @@ +const Object = @This(); + +const std = @import("std"); +const Io = std.Io; +const assert = std.debug.assert; +const eh_frame = @import("eh_frame.zig"); +const elf = std.elf; +const fs = std.fs; +const log = std.log.scoped(.link); +const math = std.math; +const mem = std.mem; +const Path = std.Build.Cache.Path; +const Allocator = std.mem.Allocator; + +const Diags = @import("../../link.zig").Diags; +const Archive = @import("Archive.zig"); +const Atom = @import("Atom.zig"); +const AtomList = @import("AtomList.zig"); +const Cie = eh_frame.Cie; +const Elf = @import("../Elf.zig"); +const Fde = eh_frame.Fde; +const File = @import("file.zig").File; +const Merge = @import("Merge.zig"); +const Symbol = @import("Symbol.zig"); +const Alignment = Atom.Alignment; +const riscv = @import("../riscv.zig"); + archive: ?InArchive = null, /// Archive files cannot contain subdirectories, so only the basename is needed /// for output. However, the full path is kept for error reporting. @@ -65,10 +92,11 @@ pub fn deinit(self: *Object, gpa: Allocator) void { pub fn parse( self: *Object, gpa: Allocator, + io: Io, diags: *Diags, /// For error reporting purposes only. path: Path, - handle: fs.File, + handle: Io.File, target: *const std.Target, debug_fmt_strip: bool, default_sym_version: elf.Versym, @@ -78,7 +106,7 @@ pub fn parse( // Allocate atom index 0 to null atom try self.atoms.append(gpa, .{ .extra_index = try self.addAtomExtra(gpa, .{}) }); - try self.initAtoms(gpa, diags, path, handle, debug_fmt_strip, target); + try self.initAtoms(gpa, io, diags, path, handle, debug_fmt_strip, target); try self.initSymbols(gpa, default_sym_version); for (self.shdrs.items, 0..) |shdr, i| { @@ -87,7 +115,7 @@ pub fn parse( if ((target.cpu.arch == .x86_64 and shdr.sh_type == elf.SHT_X86_64_UNWIND) or mem.eql(u8, self.getString(atom_ptr.name_offset), ".eh_frame")) { - try self.parseEhFrame(gpa, handle, @intCast(i), target); + try self.parseEhFrame(gpa, io, handle, @intCast(i), target); } } } @@ -95,15 +123,16 @@ pub fn parse( pub fn parseCommon( self: *Object, gpa: Allocator, + io: Io, diags: *Diags, path: Path, - handle: fs.File, + handle: Io.File, target: *const std.Target, ) !void { const offset = if (self.archive) |ar| ar.offset else 0; - const file_size = (try handle.stat()).size; + const file_size = (try handle.stat(io)).size; - const header_buffer = try Elf.preadAllAlloc(gpa, handle, offset, @sizeOf(elf.Elf64_Ehdr)); + const header_buffer = try Elf.preadAllAlloc(gpa, io, handle, offset, @sizeOf(elf.Elf64_Ehdr)); defer gpa.free(header_buffer); self.header = @as(*align(1) const elf.Elf64_Ehdr, @ptrCast(header_buffer)).*; if (!mem.eql(u8, self.header.?.e_ident[0..4], elf.MAGIC)) { @@ -127,7 +156,7 @@ pub fn parseCommon( return diags.failParse(path, "corrupt header: section header table extends past the end of file", .{}); } - const shdrs_buffer = try Elf.preadAllAlloc(gpa, handle, offset + shoff, shsize); + const shdrs_buffer = try Elf.preadAllAlloc(gpa, io, handle, offset + shoff, shsize); defer gpa.free(shdrs_buffer); const shdrs = @as([*]align(1) const elf.Elf64_Shdr, @ptrCast(shdrs_buffer.ptr))[0..shnum]; try self.shdrs.appendUnalignedSlice(gpa, shdrs); @@ -140,7 +169,7 @@ pub fn parseCommon( } } - const shstrtab = try self.preadShdrContentsAlloc(gpa, handle, self.header.?.e_shstrndx); + const shstrtab = try self.preadShdrContentsAlloc(gpa, io, handle, self.header.?.e_shstrndx); defer gpa.free(shstrtab); for (self.shdrs.items) |shdr| { if (shdr.sh_name >= shstrtab.len) { @@ -158,7 +187,7 @@ pub fn parseCommon( const shdr = self.shdrs.items[index]; self.first_global = shdr.sh_info; - const raw_symtab = try self.preadShdrContentsAlloc(gpa, handle, index); + const raw_symtab = try self.preadShdrContentsAlloc(gpa, io, handle, index); defer gpa.free(raw_symtab); const nsyms = math.divExact(usize, raw_symtab.len, @sizeOf(elf.Elf64_Sym)) catch { return diags.failParse(path, "symbol table not evenly divisible", .{}); @@ -166,7 +195,7 @@ pub fn parseCommon( const symtab = @as([*]align(1) const elf.Elf64_Sym, @ptrCast(raw_symtab.ptr))[0..nsyms]; const strtab_bias = @as(u32, @intCast(self.strtab.items.len)); - const strtab = try self.preadShdrContentsAlloc(gpa, handle, shdr.sh_link); + const strtab = try self.preadShdrContentsAlloc(gpa, io, handle, shdr.sh_link); defer gpa.free(strtab); try self.strtab.appendSlice(gpa, strtab); @@ -262,9 +291,10 @@ pub fn validateEFlags( fn initAtoms( self: *Object, gpa: Allocator, + io: Io, diags: *Diags, path: Path, - handle: fs.File, + handle: Io.File, debug_fmt_strip: bool, target: *const std.Target, ) !void { @@ -297,7 +327,7 @@ fn initAtoms( }; const shndx: u32 = @intCast(i); - const group_raw_data = try self.preadShdrContentsAlloc(gpa, handle, shndx); + const group_raw_data = try self.preadShdrContentsAlloc(gpa, io, handle, shndx); defer gpa.free(group_raw_data); const group_nmembers = math.divExact(usize, group_raw_data.len, @sizeOf(u32)) catch { return diags.failParse(path, "corrupt section group: not evenly divisible ", .{}); @@ -338,7 +368,7 @@ fn initAtoms( const shndx: u32 = @intCast(i); if (self.skipShdr(shndx, debug_fmt_strip)) continue; const size, const alignment = if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) blk: { - const data = try self.preadShdrContentsAlloc(gpa, handle, shndx); + const data = try self.preadShdrContentsAlloc(gpa, io, handle, shndx); defer gpa.free(data); const chdr = @as(*align(1) const elf.Elf64_Chdr, @ptrCast(data.ptr)).*; break :blk .{ chdr.ch_size, Alignment.fromNonzeroByteUnits(chdr.ch_addralign) }; @@ -359,7 +389,7 @@ fn initAtoms( elf.SHT_REL, elf.SHT_RELA => { const atom_index = self.atoms_indexes.items[shdr.sh_info]; if (self.atom(atom_index)) |atom_ptr| { - const relocs = try self.preadRelocsAlloc(gpa, handle, @intCast(i)); + const relocs = try self.preadRelocsAlloc(gpa, io, handle, @intCast(i)); defer gpa.free(relocs); atom_ptr.relocs_section_index = @intCast(i); const rel_index: u32 = @intCast(self.relocs.items.len); @@ -421,7 +451,8 @@ fn initSymbols( fn parseEhFrame( self: *Object, gpa: Allocator, - handle: fs.File, + io: Io, + handle: Io.File, shndx: u32, target: *const std.Target, ) !void { @@ -430,12 +461,12 @@ fn parseEhFrame( else => {}, } else null; - const raw = try self.preadShdrContentsAlloc(gpa, handle, shndx); + const raw = try self.preadShdrContentsAlloc(gpa, io, handle, shndx); defer gpa.free(raw); const data_start: u32 = @intCast(self.eh_frame_data.items.len); try self.eh_frame_data.appendSlice(gpa, raw); const relocs = if (relocs_shndx) |index| - try self.preadRelocsAlloc(gpa, handle, index) + try self.preadRelocsAlloc(gpa, io, handle, index) else &[0]elf.Elf64_Rela{}; defer gpa.free(relocs); @@ -1095,13 +1126,18 @@ pub fn updateArSymtab(self: Object, ar_symtab: *Archive.ArSymtab, elf_file: *Elf } pub fn updateArSize(self: *Object, elf_file: *Elf) !void { + const comp = elf_file.base.comp; + const io = comp.io; self.output_ar_state.size = if (self.archive) |ar| ar.size else size: { const handle = elf_file.fileHandle(self.file_handle); - break :size (try handle.stat()).size; + break :size (try handle.stat(io)).size; }; } pub fn writeAr(self: Object, elf_file: *Elf, writer: anytype) !void { + const comp = elf_file.base.comp; + const gpa = comp.gpa; + const io = comp.io; const size = std.math.cast(usize, self.output_ar_state.size) orelse return error.Overflow; const offset: u64 = if (self.archive) |ar| ar.offset else 0; const name = fs.path.basename(self.path.sub_path); @@ -1114,10 +1150,9 @@ pub fn writeAr(self: Object, elf_file: *Elf, writer: anytype) !void { }); try writer.writeAll(mem.asBytes(&hdr)); const handle = elf_file.fileHandle(self.file_handle); - const gpa = elf_file.base.comp.gpa; const data = try gpa.alloc(u8, size); defer gpa.free(data); - const amt = try handle.preadAll(data, offset); + const amt = try handle.readPositionalAll(io, data, offset); if (amt != size) return error.InputOutput; try writer.writeAll(data); } @@ -1190,11 +1225,12 @@ pub fn writeSymtab(self: *Object, elf_file: *Elf) void { /// Caller owns the memory. pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index) ![]u8 { const comp = elf_file.base.comp; + const io = comp.io; const gpa = comp.gpa; const atom_ptr = self.atom(atom_index).?; const shdr = atom_ptr.inputShdr(elf_file); const handle = elf_file.fileHandle(self.file_handle); - const data = try self.preadShdrContentsAlloc(gpa, handle, atom_ptr.input_section_index); + const data = try self.preadShdrContentsAlloc(gpa, io, handle, atom_ptr.input_section_index); defer if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) gpa.free(data); if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) { @@ -1310,18 +1346,18 @@ fn addString(self: *Object, gpa: Allocator, str: []const u8) !u32 { } /// Caller owns the memory. -fn preadShdrContentsAlloc(self: Object, gpa: Allocator, handle: fs.File, index: u32) ![]u8 { +fn preadShdrContentsAlloc(self: Object, gpa: Allocator, io: Io, handle: Io.File, index: u32) ![]u8 { assert(index < self.shdrs.items.len); const offset = if (self.archive) |ar| ar.offset else 0; const shdr = self.shdrs.items[index]; const sh_offset = math.cast(u64, shdr.sh_offset) orelse return error.Overflow; const sh_size = math.cast(u64, shdr.sh_size) orelse return error.Overflow; - return Elf.preadAllAlloc(gpa, handle, offset + sh_offset, sh_size); + return Elf.preadAllAlloc(gpa, io, handle, offset + sh_offset, sh_size); } /// Caller owns the memory. -fn preadRelocsAlloc(self: Object, gpa: Allocator, handle: fs.File, shndx: u32) ![]align(1) const elf.Elf64_Rela { - const raw = try self.preadShdrContentsAlloc(gpa, handle, shndx); +fn preadRelocsAlloc(self: Object, gpa: Allocator, io: Io, handle: Io.File, shndx: u32) ![]align(1) const elf.Elf64_Rela { + const raw = try self.preadShdrContentsAlloc(gpa, io, handle, shndx); const num = @divExact(raw.len, @sizeOf(elf.Elf64_Rela)); return @as([*]align(1) const elf.Elf64_Rela, @ptrCast(raw.ptr))[0..num]; } @@ -1552,29 +1588,3 @@ const InArchive = struct { offset: u64, size: u32, }; - -const Object = @This(); - -const std = @import("std"); -const assert = std.debug.assert; -const eh_frame = @import("eh_frame.zig"); -const elf = std.elf; -const fs = std.fs; -const log = std.log.scoped(.link); -const math = std.math; -const mem = std.mem; -const Path = std.Build.Cache.Path; -const Allocator = std.mem.Allocator; - -const Diags = @import("../../link.zig").Diags; -const Archive = @import("Archive.zig"); -const Atom = @import("Atom.zig"); -const AtomList = @import("AtomList.zig"); -const Cie = eh_frame.Cie; -const Elf = @import("../Elf.zig"); -const Fde = eh_frame.Fde; -const File = @import("file.zig").File; -const Merge = @import("Merge.zig"); -const Symbol = @import("Symbol.zig"); -const Alignment = Atom.Alignment; -const riscv = @import("../riscv.zig"); diff --git a/src/link/Elf/SharedObject.zig b/src/link/Elf/SharedObject.zig index 1e17aa34a873..c97d53a86223 100644 --- a/src/link/Elf/SharedObject.zig +++ b/src/link/Elf/SharedObject.zig @@ -1,3 +1,20 @@ +const SharedObject = @This(); + +const std = @import("std"); +const Io = std.Io; +const assert = std.debug.assert; +const elf = std.elf; +const log = std.log.scoped(.elf); +const mem = std.mem; +const Path = std.Build.Cache.Path; +const Stat = std.Build.Cache.File.Stat; +const Allocator = mem.Allocator; + +const Elf = @import("../Elf.zig"); +const File = @import("file.zig").File; +const Symbol = @import("Symbol.zig"); +const Diags = @import("../../link.zig").Diags; + path: Path, index: File.Index, @@ -92,16 +109,17 @@ pub const Parsed = struct { pub fn parseHeader( gpa: Allocator, + io: Io, diags: *Diags, file_path: Path, - fs_file: std.fs.File, + file: Io.File, stat: Stat, target: *const std.Target, ) !Header { var ehdr: elf.Elf64_Ehdr = undefined; { const buf = mem.asBytes(&ehdr); - const amt = try fs_file.preadAll(buf, 0); + const amt = try file.readPositionalAll(io, buf, 0); if (amt != buf.len) return error.UnexpectedEndOfFile; } if (!mem.eql(u8, ehdr.e_ident[0..4], "\x7fELF")) return error.BadMagic; @@ -118,7 +136,7 @@ pub fn parseHeader( errdefer gpa.free(sections); { const buf = mem.sliceAsBytes(sections); - const amt = try fs_file.preadAll(buf, shoff); + const amt = try file.readPositionalAll(io, buf, shoff); if (amt != buf.len) return error.UnexpectedEndOfFile; } @@ -143,7 +161,7 @@ pub fn parseHeader( const dynamic_table = try gpa.alloc(elf.Elf64_Dyn, n); errdefer gpa.free(dynamic_table); const buf = mem.sliceAsBytes(dynamic_table); - const amt = try fs_file.preadAll(buf, shdr.sh_offset); + const amt = try file.readPositionalAll(io, buf, shdr.sh_offset); if (amt != buf.len) return error.UnexpectedEndOfFile; break :dt dynamic_table; } else &.{}; @@ -158,7 +176,7 @@ pub fn parseHeader( const strtab_shdr = sections[dynsym_shdr.sh_link]; const n = std.math.cast(usize, strtab_shdr.sh_size) orelse return error.Overflow; const buf = try strtab.addManyAsSlice(gpa, n); - const amt = try fs_file.preadAll(buf, strtab_shdr.sh_offset); + const amt = try file.readPositionalAll(io, buf, strtab_shdr.sh_offset); if (amt != buf.len) return error.UnexpectedEndOfFile; } @@ -190,9 +208,10 @@ pub fn parseHeader( pub fn parse( gpa: Allocator, + io: Io, /// Moves resources from header. Caller may unconditionally deinit. header: *Header, - fs_file: std.fs.File, + file: Io.File, ) !Parsed { const symtab = if (header.dynsym_sect_index) |index| st: { const shdr = header.sections[index]; @@ -200,7 +219,7 @@ pub fn parse( const symtab = try gpa.alloc(elf.Elf64_Sym, n); errdefer gpa.free(symtab); const buf = mem.sliceAsBytes(symtab); - const amt = try fs_file.preadAll(buf, shdr.sh_offset); + const amt = try file.readPositionalAll(io, buf, shdr.sh_offset); if (amt != buf.len) return error.UnexpectedEndOfFile; break :st symtab; } else &.{}; @@ -211,7 +230,7 @@ pub fn parse( if (header.verdef_sect_index) |shndx| { const shdr = header.sections[shndx]; - const verdefs = try Elf.preadAllAlloc(gpa, fs_file, shdr.sh_offset, shdr.sh_size); + const verdefs = try Elf.preadAllAlloc(gpa, io, file, shdr.sh_offset, shdr.sh_size); defer gpa.free(verdefs); var offset: u32 = 0; @@ -237,7 +256,7 @@ pub fn parse( const versyms = try gpa.alloc(elf.Versym, symtab.len); errdefer gpa.free(versyms); const buf = mem.sliceAsBytes(versyms); - const amt = try fs_file.preadAll(buf, shdr.sh_offset); + const amt = try file.readPositionalAll(io, buf, shdr.sh_offset); if (amt != buf.len) return error.UnexpectedEndOfFile; break :vs versyms; } else &.{}; @@ -534,19 +553,3 @@ const Format = struct { } } }; - -const SharedObject = @This(); - -const std = @import("std"); -const assert = std.debug.assert; -const elf = std.elf; -const log = std.log.scoped(.elf); -const mem = std.mem; -const Path = std.Build.Cache.Path; -const Stat = std.Build.Cache.File.Stat; -const Allocator = mem.Allocator; - -const Elf = @import("../Elf.zig"); -const File = @import("file.zig").File; -const Symbol = @import("Symbol.zig"); -const Diags = @import("../../link.zig").Diags; diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 1450e3ab9262..588b4e3fc39a 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -740,7 +740,9 @@ pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{O /// We need this so that we can write to an archive. /// TODO implement writing ZigObject data directly to a buffer instead. pub fn readFileContents(self: *ZigObject, elf_file: *Elf) !void { - const gpa = elf_file.base.comp.gpa; + const comp = elf_file.base.comp; + const gpa = comp.gpa; + const io = comp.io; const shsize: u64 = switch (elf_file.ptr_width) { .p32 => @sizeOf(elf.Elf32_Shdr), .p64 => @sizeOf(elf.Elf64_Shdr), @@ -753,7 +755,7 @@ pub fn readFileContents(self: *ZigObject, elf_file: *Elf) !void { const size = std.math.cast(usize, end_pos) orelse return error.Overflow; try self.data.resize(gpa, size); - const amt = try elf_file.base.file.?.preadAll(self.data.items, 0); + const amt = try elf_file.base.file.?.readPositionalAll(io, self.data.items, 0); if (amt != size) return error.InputOutput; } @@ -901,13 +903,15 @@ pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void { /// Returns atom's code. /// Caller owns the memory. pub fn codeAlloc(self: *ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 { - const gpa = elf_file.base.comp.gpa; + const comp = elf_file.base.comp; + const gpa = comp.gpa; + const io = comp.io; const atom_ptr = self.atom(atom_index).?; const file_offset = atom_ptr.offset(elf_file); const size = std.math.cast(usize, atom_ptr.size) orelse return error.Overflow; const code = try gpa.alloc(u8, size); errdefer gpa.free(code); - const amt = try elf_file.base.file.?.preadAll(code, file_offset); + const amt = try elf_file.base.file.?.readPositionalAll(io, code, file_offset); if (amt != code.len) { log.err("fetching code for {s} failed", .{atom_ptr.name(elf_file)}); return error.InputOutput; @@ -1365,6 +1369,8 @@ fn updateNavCode( ) link.File.UpdateNavError!void { const zcu = pt.zcu; const gpa = zcu.gpa; + const comp = elf_file.base.comp; + const io = comp.io; const ip = &zcu.intern_pool; const nav = ip.getNav(nav_index); @@ -1449,8 +1455,8 @@ fn updateNavCode( const shdr = elf_file.sections.items(.shdr)[shdr_index]; if (shdr.sh_type != elf.SHT_NOBITS) { const file_offset = atom_ptr.offset(elf_file); - elf_file.base.file.?.pwriteAll(code, file_offset) catch |err| - return elf_file.base.cgFail(nav_index, "failed to write to output file: {s}", .{@errorName(err)}); + elf_file.base.file.?.writePositionalAll(io, code, file_offset) catch |err| + return elf_file.base.cgFail(nav_index, "failed to write to output file: {t}", .{err}); log.debug("writing {f} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), file_offset, file_offset + code.len }); } } @@ -1467,6 +1473,8 @@ fn updateTlv( const zcu = pt.zcu; const ip = &zcu.intern_pool; const gpa = zcu.gpa; + const comp = elf_file.base.comp; + const io = comp.io; const nav = ip.getNav(nav_index); log.debug("updateTlv {f}({d})", .{ nav.fqn.fmt(ip), nav_index }); @@ -1503,8 +1511,8 @@ fn updateTlv( const shdr = elf_file.sections.items(.shdr)[shndx]; if (shdr.sh_type != elf.SHT_NOBITS) { const file_offset = atom_ptr.offset(elf_file); - elf_file.base.file.?.pwriteAll(code, file_offset) catch |err| - return elf_file.base.cgFail(nav_index, "failed to write to output file: {s}", .{@errorName(err)}); + elf_file.base.file.?.writePositionalAll(io, code, file_offset) catch |err| + return elf_file.base.cgFail(nav_index, "failed to write to output file: {t}", .{err}); log.debug("writing TLV {s} from 0x{x} to 0x{x}", .{ atom_ptr.name(elf_file), file_offset, @@ -2003,6 +2011,8 @@ fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) u64 { } fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void { + const comp = elf_file.base.comp; + const io = comp.io; const atom_ptr = tr_sym.atom(elf_file).?; const fileoff = atom_ptr.offset(elf_file); const source_addr = tr_sym.address(.{}, elf_file); @@ -2012,7 +2022,7 @@ fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void { .x86_64 => try x86_64.writeTrampolineCode(source_addr, target_addr, &buf), else => @panic("TODO implement write trampoline for this CPU arch"), }; - try elf_file.base.file.?.pwriteAll(out, fileoff); + try elf_file.base.file.?.writePositionalAll(io, out, fileoff); if (elf_file.base.child_pid) |pid| { switch (builtin.os.tag) { diff --git a/src/link/Elf/file.zig b/src/link/Elf/file.zig index 50f5159d18bb..52d3c6e6f0ee 100644 --- a/src/link/Elf/file.zig +++ b/src/link/Elf/file.zig @@ -1,3 +1,20 @@ +const std = @import("std"); +const Io = std.Io; +const elf = std.elf; +const log = std.log.scoped(.link); +const Path = std.Build.Cache.Path; +const Allocator = std.mem.Allocator; + +const Archive = @import("Archive.zig"); +const Atom = @import("Atom.zig"); +const Cie = @import("eh_frame.zig").Cie; +const Elf = @import("../Elf.zig"); +const LinkerDefined = @import("LinkerDefined.zig"); +const Object = @import("Object.zig"); +const SharedObject = @import("SharedObject.zig"); +const Symbol = @import("Symbol.zig"); +const ZigObject = @import("ZigObject.zig"); + pub const File = union(enum) { zig_object: *ZigObject, linker_defined: *LinkerDefined, @@ -279,22 +296,6 @@ pub const File = union(enum) { shared_object: SharedObject, }; - pub const Handle = std.fs.File; + pub const Handle = Io.File; pub const HandleIndex = Index; }; - -const std = @import("std"); -const elf = std.elf; -const log = std.log.scoped(.link); -const Path = std.Build.Cache.Path; -const Allocator = std.mem.Allocator; - -const Archive = @import("Archive.zig"); -const Atom = @import("Atom.zig"); -const Cie = @import("eh_frame.zig").Cie; -const Elf = @import("../Elf.zig"); -const LinkerDefined = @import("LinkerDefined.zig"); -const Object = @import("Object.zig"); -const SharedObject = @import("SharedObject.zig"); -const Symbol = @import("Symbol.zig"); -const ZigObject = @import("ZigObject.zig"); diff --git a/src/link/Elf/relocatable.zig b/src/link/Elf/relocatable.zig index 7adeecdcdedb..74ea71ce9d06 100644 --- a/src/link/Elf/relocatable.zig +++ b/src/link/Elf/relocatable.zig @@ -1,5 +1,26 @@ +const std = @import("std"); +const assert = std.debug.assert; +const elf = std.elf; +const math = std.math; +const mem = std.mem; +const Path = std.Build.Cache.Path; +const log = std.log.scoped(.link); +const state_log = std.log.scoped(.link_state); + +const build_options = @import("build_options"); + +const eh_frame = @import("eh_frame.zig"); +const link = @import("../../link.zig"); +const Archive = @import("Archive.zig"); +const Compilation = @import("../../Compilation.zig"); +const Elf = @import("../Elf.zig"); +const File = @import("file.zig").File; +const Object = @import("Object.zig"); +const Symbol = @import("Symbol.zig"); + pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void { const gpa = comp.gpa; + const io = comp.io; const diags = &comp.link_diags; if (diags.hasErrors()) return error.LinkFailure; @@ -125,8 +146,8 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void { assert(writer.buffered().len == total_size); - try elf_file.base.file.?.setEndPos(total_size); - try elf_file.base.file.?.pwriteAll(writer.buffered(), 0); + try elf_file.base.file.?.setLength(io, total_size); + try elf_file.base.file.?.writePositionalAll(io, writer.buffered(), 0); if (diags.hasErrors()) return error.LinkFailure; } @@ -330,13 +351,7 @@ fn allocateAllocSections(elf_file: *Elf) !void { if (shdr.sh_offset > 0) { const existing_size = elf_file.sectionSize(@intCast(shndx)); - const amt = try elf_file.base.file.?.copyRangeAll( - shdr.sh_offset, - elf_file.base.file.?, - new_offset, - existing_size, - ); - if (amt != existing_size) return error.InputOutput; + try elf_file.base.copyRangeAll(shdr.sh_offset, new_offset, existing_size); } shdr.sh_offset = new_offset; @@ -360,13 +375,14 @@ fn writeAtoms(elf_file: *Elf) !void { } fn writeSyntheticSections(elf_file: *Elf) !void { - const gpa = elf_file.base.comp.gpa; + const comp = elf_file.base.comp; + const io = comp.io; + const gpa = comp.gpa; const slice = elf_file.sections.slice(); const SortRelocs = struct { pub fn lessThan(ctx: void, lhs: elf.Elf64_Rela, rhs: elf.Elf64_Rela) bool { _ = ctx; - assert(lhs.r_offset != rhs.r_offset); return lhs.r_offset < rhs.r_offset; } }; @@ -397,7 +413,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void { shdr.sh_offset + shdr.sh_size, }); - try elf_file.base.file.?.pwriteAll(@ptrCast(relocs.items), shdr.sh_offset); + try elf_file.base.file.?.writePositionalAll(io, @ptrCast(relocs.items), shdr.sh_offset); } if (elf_file.section_indexes.eh_frame) |shndx| { @@ -417,7 +433,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void { shdr.sh_offset + sh_size, }); assert(writer.buffered().len == sh_size - existing_size); - try elf_file.base.file.?.pwriteAll(writer.buffered(), shdr.sh_offset + existing_size); + try elf_file.base.file.?.writePositionalAll(io, writer.buffered(), shdr.sh_offset + existing_size); } if (elf_file.section_indexes.eh_frame_rela) |shndx| { const shdr = slice.items(.shdr)[shndx]; @@ -435,7 +451,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void { shdr.sh_offset, shdr.sh_offset + shdr.sh_size, }); - try elf_file.base.file.?.pwriteAll(@ptrCast(relocs.items), shdr.sh_offset); + try elf_file.base.file.?.writePositionalAll(io, @ptrCast(relocs.items), shdr.sh_offset); } try writeGroups(elf_file); @@ -444,7 +460,9 @@ fn writeSyntheticSections(elf_file: *Elf) !void { } fn writeGroups(elf_file: *Elf) !void { - const gpa = elf_file.base.comp.gpa; + const comp = elf_file.base.comp; + const io = comp.io; + const gpa = comp.gpa; for (elf_file.group_sections.items) |cgs| { const shdr = elf_file.sections.items(.shdr)[cgs.shndx]; const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; @@ -457,25 +475,6 @@ fn writeGroups(elf_file: *Elf) !void { shdr.sh_offset, shdr.sh_offset + shdr.sh_size, }); - try elf_file.base.file.?.pwriteAll(writer.buffered(), shdr.sh_offset); + try elf_file.base.file.?.writePositionalAll(io, writer.buffered(), shdr.sh_offset); } } - -const assert = std.debug.assert; -const build_options = @import("build_options"); -const eh_frame = @import("eh_frame.zig"); -const elf = std.elf; -const link = @import("../../link.zig"); -const log = std.log.scoped(.link); -const math = std.math; -const mem = std.mem; -const state_log = std.log.scoped(.link_state); -const Path = std.Build.Cache.Path; -const std = @import("std"); - -const Archive = @import("Archive.zig"); -const Compilation = @import("../../Compilation.zig"); -const Elf = @import("../Elf.zig"); -const File = @import("file.zig").File; -const Object = @import("Object.zig"); -const Symbol = @import("Symbol.zig"); diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig index 7d12ccedb2c1..e33cf8669694 100644 --- a/src/link/Elf2.zig +++ b/src/link/Elf2.zig @@ -1,3 +1,23 @@ +const Elf = @This(); + +const builtin = @import("builtin"); +const native_endian = builtin.cpu.arch.endian(); + +const std = @import("std"); +const Io = std.Io; +const assert = std.debug.assert; +const log = std.log.scoped(.link); + +const codegen = @import("../codegen.zig"); +const Compilation = @import("../Compilation.zig"); +const InternPool = @import("../InternPool.zig"); +const link = @import("../link.zig"); +const MappedFile = @import("MappedFile.zig"); +const target_util = @import("../target.zig"); +const Type = @import("../Type.zig"); +const Value = @import("../Value.zig"); +const Zcu = @import("../Zcu.zig"); + base: link.File, options: link.File.OpenOptions, mf: MappedFile, @@ -908,6 +928,7 @@ fn create( path: std.Build.Cache.Path, options: link.File.OpenOptions, ) !*Elf { + const io = comp.io; const target = &comp.root_mod.resolved_target.result; assert(target.ofmt == .elf); const class: std.elf.CLASS = switch (target.ptrBitWidth()) { @@ -953,11 +974,11 @@ fn create( }; const elf = try arena.create(Elf); - const file = try path.root_dir.handle.adaptToNewApi().createFile(comp.io, path.sub_path, .{ + const file = try path.root_dir.handle.createFile(io, path.sub_path, .{ .read = true, - .mode = link.File.determineMode(comp.config.output_mode, comp.config.link_mode), + .permissions = link.File.determinePermissions(comp.config.output_mode, comp.config.link_mode), }); - errdefer file.close(comp.io); + errdefer file.close(io); elf.* = .{ .base = .{ .tag = .elf2, @@ -965,7 +986,7 @@ fn create( .comp = comp, .emit = path, - .file = .adaptFromNewApi(file), + .file = file, .gc_sections = false, .print_gc_sections = false, .build_id = .none, @@ -973,7 +994,7 @@ fn create( .stack_size = 0, }, .options = options, - .mf = try .init(file, comp.gpa), + .mf = try .init(file, comp.gpa, io), .ni = .{ .tls = .none, }, @@ -1105,8 +1126,10 @@ fn initHeaders( defer phnum = 0; break :expected_nodes_len 5 + phnum; }, - .EXEC, .DYN => break :expected_nodes_len 9 + phnum * 2 + - @as(usize, 4) * @intFromBool(have_dynamic_section), + .EXEC, .DYN => break :expected_nodes_len 8 + phnum * 2 + + @intFromBool(maybe_interp != null) + + @as(usize, 4) * @intFromBool(have_dynamic_section) + + @intFromBool(comp.config.any_non_single_threaded), }; try elf.nodes.ensureTotalCapacity(gpa, expected_nodes_len); try elf.shdrs.ensureTotalCapacity(gpa, shnum); @@ -1973,8 +1996,8 @@ pub fn lazySymbol(elf: *Elf, lazy: link.File.LazySymbol) !Symbol.Index { return lazy_gop.value_ptr.*; } -pub fn loadInput(elf: *Elf, input: link.Input) (std.fs.File.Reader.SizeError || - std.Io.File.Reader.Error || MappedFile.Error || error{ EndOfStream, BadMagic, LinkFailure })!void { +pub fn loadInput(elf: *Elf, input: link.Input) (Io.File.Reader.SizeError || + Io.File.Reader.Error || MappedFile.Error || error{ EndOfStream, BadMagic, LinkFailure })!void { const io = elf.base.comp.io; var buf: [4096]u8 = undefined; switch (input) { @@ -2007,7 +2030,7 @@ pub fn loadInput(elf: *Elf, input: link.Input) (std.fs.File.Reader.SizeError || .dso_exact => |dso_exact| try elf.loadDsoExact(dso_exact.name), } } -fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *std.Io.File.Reader) !void { +fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) !void { const comp = elf.base.comp; const gpa = comp.gpa; const diags = &comp.link_diags; @@ -2067,7 +2090,7 @@ fn loadObject( elf: *Elf, path: std.Build.Cache.Path, member: ?[]const u8, - fr: *std.Io.File.Reader, + fr: *Io.File.Reader, fl: MappedFile.Node.FileLocation, ) !void { const comp = elf.base.comp; @@ -2310,7 +2333,7 @@ fn loadObject( }, } } -fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *std.Io.File.Reader) !void { +fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) !void { const comp = elf.base.comp; const diags = &comp.link_diags; const r = &fr.interface; @@ -3305,12 +3328,13 @@ fn flushInputSection(elf: *Elf, isi: Node.InputSectionIndex) !void { const file_loc = isi.fileLocation(elf); if (file_loc.size == 0) return; const comp = elf.base.comp; + const io = comp.io; const gpa = comp.gpa; const ii = isi.input(elf); const path = ii.path(elf); - const file = try path.root_dir.handle.adaptToNewApi().openFile(comp.io, path.sub_path, .{}); - defer file.close(comp.io); - var fr = file.reader(comp.io, &.{}); + const file = try path.root_dir.handle.openFile(io, path.sub_path, .{}); + defer file.close(io); + var fr = file.reader(io, &.{}); try fr.seekTo(file_loc.offset); var nw: MappedFile.Node.Writer = undefined; const si = isi.symbol(elf); @@ -3707,10 +3731,16 @@ pub fn deleteExport(elf: *Elf, exported: Zcu.Exported, name: InternPool.NullTerm _ = name; } -pub fn dump(elf: *Elf, tid: Zcu.PerThread.Id) void { - const w, _ = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); - elf.printNode(tid, w, .root, 0) catch {}; +pub fn dump(elf: *Elf, tid: Zcu.PerThread.Id) Io.Cancelable!void { + const comp = elf.base.comp; + const io = comp.io; + var buffer: [512]u8 = undefined; + const stderr = try io.lockStderr(&buffer, null); + defer io.lockStderr(); + const w = &stderr.file_writer.interface; + elf.printNode(tid, w, .root, 0) catch |err| switch (err) { + error.WriteFailed => return stderr.err.?, + }; } pub fn printNode( @@ -3822,19 +3852,3 @@ pub fn printNode( try w.writeByte('\n'); } } - -const assert = std.debug.assert; -const builtin = @import("builtin"); -const codegen = @import("../codegen.zig"); -const Compilation = @import("../Compilation.zig"); -const Elf = @This(); -const InternPool = @import("../InternPool.zig"); -const link = @import("../link.zig"); -const log = std.log.scoped(.link); -const MappedFile = @import("MappedFile.zig"); -const native_endian = builtin.cpu.arch.endian(); -const std = @import("std"); -const target_util = @import("../target.zig"); -const Type = @import("../Type.zig"); -const Value = @import("../Value.zig"); -const Zcu = @import("../Zcu.zig"); diff --git a/src/link/Lld.zig b/src/link/Lld.zig index 7b1e34df7878..dd84da15d41d 100644 --- a/src/link/Lld.zig +++ b/src/link/Lld.zig @@ -359,6 +359,7 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) !void { fn coffLink(lld: *Lld, arena: Allocator) !void { const comp = lld.base.comp; const gpa = comp.gpa; + const io = comp.io; const base = &lld.base; const coff = &lld.ofmt.coff; @@ -400,11 +401,12 @@ fn coffLink(lld: *Lld, arena: Allocator) !void { // regarding eliding redundant object -> object transformations. return error.NoObjectsToLink; }; - try std.fs.Dir.copyFile( + try Io.Dir.copyFile( the_object_path.root_dir.handle, the_object_path.sub_path, directory.handle, base.emit.sub_path, + io, .{}, ); } else { @@ -718,13 +720,13 @@ fn coffLink(lld: *Lld, arena: Allocator) !void { argv.appendAssumeCapacity(try crt_file.full_object_path.toString(arena)); continue; } - if (try findLib(arena, lib_basename, coff.lib_directories)) |full_path| { + if (try findLib(arena, io, lib_basename, coff.lib_directories)) |full_path| { argv.appendAssumeCapacity(full_path); continue; } if (target.abi.isGnu()) { const fallback_name = try allocPrint(arena, "lib{s}.dll.a", .{key}); - if (try findLib(arena, fallback_name, coff.lib_directories)) |full_path| { + if (try findLib(arena, io, fallback_name, coff.lib_directories)) |full_path| { argv.appendAssumeCapacity(full_path); continue; } @@ -741,9 +743,9 @@ fn coffLink(lld: *Lld, arena: Allocator) !void { try spawnLld(comp, arena, argv.items); } } -fn findLib(arena: Allocator, name: []const u8, lib_directories: []const Cache.Directory) !?[]const u8 { +fn findLib(arena: Allocator, io: Io, name: []const u8, lib_directories: []const Cache.Directory) !?[]const u8 { for (lib_directories) |lib_directory| { - lib_directory.handle.access(name, .{}) catch |err| switch (err) { + lib_directory.handle.access(io, name, .{}) catch |err| switch (err) { error.FileNotFound => continue, else => |e| return e, }; @@ -755,6 +757,7 @@ fn findLib(arena: Allocator, name: []const u8, lib_directories: []const Cache.Di fn elfLink(lld: *Lld, arena: Allocator) !void { const comp = lld.base.comp; const gpa = comp.gpa; + const io = comp.io; const diags = &comp.link_diags; const base = &lld.base; const elf = &lld.ofmt.elf; @@ -816,11 +819,12 @@ fn elfLink(lld: *Lld, arena: Allocator) !void { // regarding eliding redundant object -> object transformations. return error.NoObjectsToLink; }; - try std.fs.Dir.copyFile( + try Io.Dir.copyFile( the_object_path.root_dir.handle, the_object_path.sub_path, directory.handle, base.emit.sub_path, + io, .{}, ); } else { @@ -1190,8 +1194,12 @@ fn elfLink(lld: *Lld, arena: Allocator) !void { })); } else if (target.isFreeBSDLibC()) { for (freebsd.libs) |lib| { + if (lib.added_in) |add_in| { + if (target.os.version_range.semver.min.order(add_in) == .lt) continue; + } + const lib_path = try std.fmt.allocPrint(arena, "{f}{c}lib{s}.so.{d}", .{ - comp.freebsd_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover, + comp.freebsd_so_files.?.dir_path, fs.path.sep, lib.name, lib.getSoVersion(&target.os), }); try argv.append(lib_path); } @@ -1202,6 +1210,13 @@ fn elfLink(lld: *Lld, arena: Allocator) !void { }); try argv.append(lib_path); } + } else if (target.isOpenBSDLibC()) { + for (openbsd.libs) |lib| { + const lib_path = try std.fmt.allocPrint(arena, "{f}{c}lib{s}.so", .{ + comp.openbsd_so_files.?.dir_path, fs.path.sep, lib.name, + }); + try argv.append(lib_path); + } } else { diags.flags.missing_libc = true; } @@ -1322,6 +1337,7 @@ fn getLDMOption(target: *const std.Target) ?[]const u8 { } fn wasmLink(lld: *Lld, arena: Allocator) !void { const comp = lld.base.comp; + const diags = &comp.link_diags; const shared_memory = comp.config.shared_memory; const export_memory = comp.config.export_memory; const import_memory = comp.config.import_memory; @@ -1330,6 +1346,7 @@ fn wasmLink(lld: *Lld, arena: Allocator) !void { const wasm = &lld.ofmt.wasm; const gpa = comp.gpa; + const io = comp.io; const directory = base.emit.root_dir; // Just an alias to make it shorter to type. const full_out_path = try directory.join(arena, &[_][]const u8{base.emit.sub_path}); @@ -1367,11 +1384,12 @@ fn wasmLink(lld: *Lld, arena: Allocator) !void { // regarding eliding redundant object -> object transformations. return error.NoObjectsToLink; }; - try fs.Dir.copyFile( + try Io.Dir.copyFile( the_object_path.root_dir.handle, the_object_path.sub_path, directory.handle, base.emit.sub_path, + io, .{}, ); } else { @@ -1561,27 +1579,23 @@ fn wasmLink(lld: *Lld, arena: Allocator) !void { // is not the case, it means we will get "exec format error" when trying to run // it, and then can react to that in the same way as trying to run an ELF file // from a foreign CPU architecture. - if (fs.has_executable_bit and target.os.tag == .wasi and + if (Io.File.Permissions.has_executable_bit and target.os.tag == .wasi and comp.config.output_mode == .Exe) { - // TODO: what's our strategy for reporting linker errors from this function? - // report a nice error here with the file path if it fails instead of - // just returning the error code. // chmod does not interact with umask, so we use a conservative -rwxr--r-- here. - std.posix.fchmodat(fs.cwd().fd, full_out_path, 0o744, 0) catch |err| switch (err) { - error.OperationNotSupported => unreachable, // Not a symlink. - else => |e| return e, - }; + Io.Dir.cwd().setFilePermissions(io, full_out_path, .fromMode(0o744), .{}) catch |err| + return diags.fail("{s}: failed to enable executable permissions: {t}", .{ full_out_path, err }); } } } fn spawnLld(comp: *Compilation, arena: Allocator, argv: []const []const u8) !void { const io = comp.io; + const gpa = comp.gpa; if (comp.verbose_link) { // Skip over our own name so that the LLD linker name is the first argv item. - Compilation.dump_argv(argv[1..]); + try Compilation.dumpArgv(io, argv[1..]); } // If possible, we run LLD as a child process because it does not always @@ -1595,38 +1609,47 @@ fn spawnLld(comp: *Compilation, arena: Allocator, argv: []const []const u8) !voi } var stderr: []u8 = &.{}; - defer comp.gpa.free(stderr); + defer gpa.free(stderr); - var child = std.process.Child.init(argv, arena); + // TODO rework this awkward logic to call child.kill() in the failure case const term = (if (comp.clang_passthrough_mode) term: { - child.stdin_behavior = .Inherit; - child.stdout_behavior = .Inherit; - child.stderr_behavior = .Inherit; - - break :term child.spawnAndWait(); + var child = std.process.spawn(io, .{ + .argv = argv, + .stdin = .inherit, + .stdout = .inherit, + .stderr = .inherit, + }) catch |err| break :term err; + + break :term child.wait(io); } else term: { - child.stdin_behavior = .Ignore; - child.stdout_behavior = .Ignore; - child.stderr_behavior = .Pipe; + var child = std.process.spawn(io, .{ + .argv = argv, + .stdin = .ignore, + .stdout = .ignore, + .stderr = .pipe, + }) catch |err| break :term err; - child.spawn() catch |err| break :term err; var stderr_reader = child.stderr.?.readerStreaming(io, &.{}); - stderr = try stderr_reader.interface.allocRemaining(comp.gpa, .unlimited); - break :term child.wait(); + stderr = try stderr_reader.interface.allocRemaining(gpa, .unlimited); + break :term child.wait(io); }) catch |first_err| term: { const err = switch (first_err) { error.NameTooLong => err: { const s = fs.path.sep_str; - const rand_int = std.crypto.random.int(u64); + const rand_int = r: { + var x: u64 = undefined; + io.random(@ptrCast(&x)); + break :r x; + }; const rsp_path = "tmp" ++ s ++ std.fmt.hex(rand_int) ++ ".rsp"; - const rsp_file = try comp.dirs.local_cache.handle.createFile(rsp_path, .{}); - defer comp.dirs.local_cache.handle.deleteFileZ(rsp_path) catch |err| - log.warn("failed to delete response file {s}: {s}", .{ rsp_path, @errorName(err) }); + const rsp_file = try comp.dirs.local_cache.handle.createFile(io, rsp_path, .{}); + defer comp.dirs.local_cache.handle.deleteFile(io, rsp_path) catch |err| + log.warn("failed to delete response file {s}: {t}", .{ rsp_path, err }); { - defer rsp_file.close(); + defer rsp_file.close(io); var rsp_file_buffer: [1024]u8 = undefined; - var rsp_file_writer = rsp_file.writer(&rsp_file_buffer); + var rsp_file_writer = rsp_file.writer(io, &rsp_file_buffer); const rsp_writer = &rsp_file_writer.interface; for (argv[2..]) |arg| { try rsp_writer.writeByte('"'); @@ -1643,37 +1666,35 @@ fn spawnLld(comp: *Compilation, arena: Allocator, argv: []const []const u8) !voi try rsp_writer.flush(); } - var rsp_child = std.process.Child.init(&.{ argv[0], argv[1], try std.fmt.allocPrint( - arena, - "@{s}", - .{try comp.dirs.local_cache.join(arena, &.{rsp_path})}, - ) }, arena); + var rsp_child = std.process.spawn(io, .{ + .argv = &.{ + argv[0], + argv[1], + try std.fmt.allocPrint(arena, "@{s}", .{ + try comp.dirs.local_cache.join(arena, &.{rsp_path}), + }), + }, + .stdin = if (comp.clang_passthrough_mode) .inherit else .ignore, + .stdout = if (comp.clang_passthrough_mode) .inherit else .ignore, + .stderr = if (comp.clang_passthrough_mode) .inherit else .pipe, + }) catch |err| break :err err; if (comp.clang_passthrough_mode) { - rsp_child.stdin_behavior = .Inherit; - rsp_child.stdout_behavior = .Inherit; - rsp_child.stderr_behavior = .Inherit; - - break :term rsp_child.spawnAndWait() catch |err| break :err err; + break :term rsp_child.wait(io) catch |err| break :err err; } else { - rsp_child.stdin_behavior = .Ignore; - rsp_child.stdout_behavior = .Ignore; - rsp_child.stderr_behavior = .Pipe; - - rsp_child.spawn() catch |err| break :err err; var stderr_reader = rsp_child.stderr.?.readerStreaming(io, &.{}); - stderr = try stderr_reader.interface.allocRemaining(comp.gpa, .unlimited); - break :term rsp_child.wait() catch |err| break :err err; + stderr = try stderr_reader.interface.allocRemaining(gpa, .unlimited); + break :term rsp_child.wait(io) catch |err| break :err err; } }, else => first_err, }; - log.err("unable to spawn LLD {s}: {s}", .{ argv[0], @errorName(err) }); + log.err("unable to spawn LLD {s}: {t}", .{ argv[0], err }); return error.UnableToSpawnSelf; }; const diags = &comp.link_diags; switch (term) { - .Exited => |code| if (code != 0) { + .exited => |code| if (code != 0) { if (comp.clang_passthrough_mode) std.process.exit(code); diags.lockAndParseLldStderr(argv[1], stderr); return error.LinkFailure; @@ -1688,6 +1709,7 @@ fn spawnLld(comp: *Compilation, arena: Allocator, argv: []const []const u8) !voi } const std = @import("std"); +const Io = std.Io; const Allocator = std.mem.Allocator; const Cache = std.Build.Cache; const allocPrint = std.fmt.allocPrint; @@ -1702,6 +1724,7 @@ const dev = @import("../dev.zig"); const freebsd = @import("../libs/freebsd.zig"); const glibc = @import("../libs/glibc.zig"); const netbsd = @import("../libs/netbsd.zig"); +const openbsd = @import("../libs/openbsd.zig"); const wasi_libc = @import("../libs/wasi_libc.zig"); const link = @import("../link.zig"); const lldMain = @import("../main.zig").lldMain; diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 035bd601558a..b747b3de5670 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -29,9 +29,9 @@ resolver: SymbolResolver = .{}, /// This table will be populated after `scanRelocs` has run. /// Key is symbol index. undefs: std.AutoArrayHashMapUnmanaged(SymbolResolver.Index, UndefRefs) = .empty, -undefs_mutex: std.Thread.Mutex = .{}, +undefs_mutex: std.Io.Mutex = .init, dupes: std.AutoArrayHashMapUnmanaged(SymbolResolver.Index, std.ArrayList(File.Index)) = .empty, -dupes_mutex: std.Thread.Mutex = .{}, +dupes_mutex: std.Io.Mutex = .init, dyld_info_cmd: macho.dyld_info_command = .{}, symtab_cmd: macho.symtab_command = .{}, @@ -219,10 +219,12 @@ pub fn createEmpty( }; errdefer self.base.destroy(); - self.base.file = try emit.root_dir.handle.createFile(emit.sub_path, .{ + const io = comp.io; + + self.base.file = try emit.root_dir.handle.createFile(io, emit.sub_path, .{ .truncate = true, .read = true, - .mode = link.File.determineMode(output_mode, link_mode), + .permissions = link.File.determinePermissions(output_mode, link_mode), }); // Append null file @@ -267,14 +269,16 @@ pub fn open( } pub fn deinit(self: *MachO) void { - const gpa = self.base.comp.gpa; + const comp = self.base.comp; + const gpa = comp.gpa; + const io = comp.io; if (self.d_sym) |*d_sym| { d_sym.deinit(); } for (self.file_handles.items) |handle| { - handle.close(); + handle.close(io); } self.file_handles.deinit(gpa); @@ -343,7 +347,8 @@ pub fn flush( const comp = self.base.comp; const gpa = comp.gpa; - const diags = &self.base.comp.link_diags; + const io = comp.io; + const diags = &comp.link_diags; const sub_prog_node = prog_node.start("MachO Flush", 0); defer sub_prog_node.end(); @@ -376,26 +381,26 @@ pub fn flush( // in this set. try positionals.ensureUnusedCapacity(comp.c_object_table.keys().len); for (comp.c_object_table.keys()) |key| { - positionals.appendAssumeCapacity(try link.openObjectInput(diags, key.status.success.object_path)); + positionals.appendAssumeCapacity(try link.openObjectInput(io, diags, key.status.success.object_path)); } - if (zcu_obj_path) |path| try positionals.append(try link.openObjectInput(diags, path)); + if (zcu_obj_path) |path| try positionals.append(try link.openObjectInput(io, diags, path)); if (comp.config.any_sanitize_thread) { - try positionals.append(try link.openObjectInput(diags, comp.tsan_lib.?.full_object_path)); + try positionals.append(try link.openObjectInput(io, diags, comp.tsan_lib.?.full_object_path)); } if (comp.config.any_fuzz) { - try positionals.append(try link.openArchiveInput(diags, comp.fuzzer_lib.?.full_object_path, false, false)); + try positionals.append(try link.openArchiveInput(io, diags, comp.fuzzer_lib.?.full_object_path, false, false)); } if (comp.ubsan_rt_lib) |crt_file| { const path = crt_file.full_object_path; - self.classifyInputFile(try link.openArchiveInput(diags, path, false, false)) catch |err| + self.classifyInputFile(try link.openArchiveInput(io, diags, path, false, false)) catch |err| diags.addParseError(path, "failed to parse archive: {s}", .{@errorName(err)}); } else if (comp.ubsan_rt_obj) |crt_file| { const path = crt_file.full_object_path; - self.classifyInputFile(try link.openObjectInput(diags, path)) catch |err| + self.classifyInputFile(try link.openObjectInput(io, diags, path)) catch |err| diags.addParseError(path, "failed to parse archive: {s}", .{@errorName(err)}); } @@ -430,7 +435,7 @@ pub fn flush( if (comp.config.link_libc and is_exe_or_dyn_lib) { if (comp.zigc_static_lib) |zigc| { const path = zigc.full_object_path; - self.classifyInputFile(try link.openArchiveInput(diags, path, false, false)) catch |err| + self.classifyInputFile(try link.openArchiveInput(io, diags, path, false, false)) catch |err| diags.addParseError(path, "failed to parse archive: {s}", .{@errorName(err)}); } } @@ -453,12 +458,12 @@ pub fn flush( for (system_libs.items) |lib| { switch (Compilation.classifyFileExt(lib.path.sub_path)) { .shared_library => { - const dso_input = try link.openDsoInput(diags, lib.path, lib.needed, lib.weak, lib.reexport); + const dso_input = try link.openDsoInput(io, diags, lib.path, lib.needed, lib.weak, lib.reexport); self.classifyInputFile(dso_input) catch |err| diags.addParseError(lib.path, "failed to parse input file: {s}", .{@errorName(err)}); }, .static_library => { - const archive_input = try link.openArchiveInput(diags, lib.path, lib.must_link, lib.hidden); + const archive_input = try link.openArchiveInput(io, diags, lib.path, lib.must_link, lib.hidden); self.classifyInputFile(archive_input) catch |err| diags.addParseError(lib.path, "failed to parse input file: {s}", .{@errorName(err)}); }, @@ -469,11 +474,11 @@ pub fn flush( // Finally, link against compiler_rt. if (comp.compiler_rt_lib) |crt_file| { const path = crt_file.full_object_path; - self.classifyInputFile(try link.openArchiveInput(diags, path, false, false)) catch |err| + self.classifyInputFile(try link.openArchiveInput(io, diags, path, false, false)) catch |err| diags.addParseError(path, "failed to parse archive: {s}", .{@errorName(err)}); } else if (comp.compiler_rt_obj) |crt_file| { const path = crt_file.full_object_path; - self.classifyInputFile(try link.openObjectInput(diags, path)) catch |err| + self.classifyInputFile(try link.openObjectInput(io, diags, path)) catch |err| diags.addParseError(path, "failed to parse archive: {s}", .{@errorName(err)}); } @@ -564,7 +569,7 @@ pub fn flush( self.writeLinkeditSectionsToFile() catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.LinkFailure => return error.LinkFailure, - else => |e| return diags.fail("failed to write linkedit sections to file: {s}", .{@errorName(e)}), + else => |e| return diags.fail("failed to write linkedit sections to file: {t}", .{e}), }; var codesig: ?CodeSignature = if (self.requiresCodeSig()) blk: { @@ -575,8 +580,8 @@ pub fn flush( // where the code signature goes into. var codesig = CodeSignature.init(self.getPageSize()); codesig.code_directory.ident = fs.path.basename(self.base.emit.sub_path); - if (self.entitlements) |path| codesig.addEntitlements(gpa, path) catch |err| - return diags.fail("failed to add entitlements from {s}: {s}", .{ path, @errorName(err) }); + if (self.entitlements) |path| codesig.addEntitlements(gpa, io, path) catch |err| + return diags.fail("failed to add entitlements from {s}: {t}", .{ path, err }); try self.writeCodeSignaturePadding(&codesig); break :blk codesig; } else null; @@ -612,15 +617,17 @@ pub fn flush( else => |e| return diags.fail("failed to write code signature: {s}", .{@errorName(e)}), }; const emit = self.base.emit; - invalidateKernelCache(emit.root_dir.handle, emit.sub_path) catch |err| switch (err) { - else => |e| return diags.fail("failed to invalidate kernel cache: {s}", .{@errorName(e)}), + invalidateKernelCache(io, emit.root_dir.handle, emit.sub_path) catch |err| switch (err) { + else => |e| return diags.fail("failed to invalidate kernel cache: {t}", .{e}), }; } } /// --verbose-link output fn dumpArgv(self: *MachO, comp: *Compilation) !void { - const gpa = self.base.comp.gpa; + const gpa = comp.gpa; + const io = comp.io; + var arena_allocator = std.heap.ArenaAllocator.init(gpa); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); @@ -815,7 +822,7 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { if (comp.ubsan_rt_obj) |obj| try argv.append(try obj.full_object_path.toString(arena)); } - Compilation.dump_argv(argv.items); + try Compilation.dumpArgv(io, argv.items); } /// TODO delete this, libsystem must be resolved when setting up the compilation pipeline @@ -825,7 +832,8 @@ pub fn resolveLibSystem( comp: *Compilation, out_libs: anytype, ) !void { - const diags = &self.base.comp.link_diags; + const io = comp.io; + const diags = &comp.link_diags; var test_path = std.array_list.Managed(u8).init(arena); var checked_paths = std.array_list.Managed([]const u8).init(arena); @@ -834,16 +842,16 @@ pub fn resolveLibSystem( if (self.sdk_layout) |sdk_layout| switch (sdk_layout) { .sdk => { const dir = try fs.path.join(arena, &.{ comp.sysroot.?, "usr", "lib" }); - if (try accessLibPath(arena, &test_path, &checked_paths, dir, "System")) break :success; + if (try accessLibPath(arena, io, &test_path, &checked_paths, dir, "System")) break :success; }, .vendored => { const dir = try comp.dirs.zig_lib.join(arena, &.{ "libc", "darwin" }); - if (try accessLibPath(arena, &test_path, &checked_paths, dir, "System")) break :success; + if (try accessLibPath(arena, io, &test_path, &checked_paths, dir, "System")) break :success; }, }; for (self.lib_directories) |directory| { - if (try accessLibPath(arena, &test_path, &checked_paths, directory.path orelse ".", "System")) break :success; + if (try accessLibPath(arena, io, &test_path, &checked_paths, directory.path orelse ".", "System")) break :success; } diags.addMissingLibraryError(checked_paths.items, "unable to find libSystem system library", .{}); @@ -861,6 +869,9 @@ pub fn classifyInputFile(self: *MachO, input: link.Input) !void { const tracy = trace(@src()); defer tracy.end(); + const comp = self.base.comp; + const io = comp.io; + const path, const file = input.pathAndFile().?; // TODO don't classify now, it's too late. The input file has already been classified log.debug("classifying input file {f}", .{path}); @@ -871,7 +882,7 @@ pub fn classifyInputFile(self: *MachO, input: link.Input) !void { const fat_arch: ?fat.Arch = try self.parseFatFile(file, path); const offset = if (fat_arch) |fa| fa.offset else 0; - if (readMachHeader(file, offset) catch null) |h| blk: { + if (readMachHeader(io, file, offset) catch null) |h| blk: { if (h.magic != macho.MH_MAGIC_64) break :blk; switch (h.filetype) { macho.MH_OBJECT => try self.addObject(path, fh, offset), @@ -880,7 +891,7 @@ pub fn classifyInputFile(self: *MachO, input: link.Input) !void { } return; } - if (readArMagic(file, offset, &buffer) catch null) |ar_magic| blk: { + if (readArMagic(io, file, offset, &buffer) catch null) |ar_magic| blk: { if (!mem.eql(u8, ar_magic, Archive.ARMAG)) break :blk; try self.addArchive(input.archive, fh, fat_arch); return; @@ -888,12 +899,14 @@ pub fn classifyInputFile(self: *MachO, input: link.Input) !void { _ = try self.addTbd(.fromLinkInput(input), true, fh); } -fn parseFatFile(self: *MachO, file: std.fs.File, path: Path) !?fat.Arch { - const diags = &self.base.comp.link_diags; - const fat_h = fat.readFatHeader(file) catch return null; +fn parseFatFile(self: *MachO, file: Io.File, path: Path) !?fat.Arch { + const comp = self.base.comp; + const io = comp.io; + const diags = &comp.link_diags; + const fat_h = fat.readFatHeader(io, file) catch return null; if (fat_h.magic != macho.FAT_MAGIC and fat_h.magic != macho.FAT_MAGIC_64) return null; var fat_archs_buffer: [2]fat.Arch = undefined; - const fat_archs = try fat.parseArchs(file, fat_h, &fat_archs_buffer); + const fat_archs = try fat.parseArchs(io, file, fat_h, &fat_archs_buffer); const cpu_arch = self.getTarget().cpu.arch; for (fat_archs) |arch| { if (arch.tag == cpu_arch) return arch; @@ -901,16 +914,16 @@ fn parseFatFile(self: *MachO, file: std.fs.File, path: Path) !?fat.Arch { return diags.failParse(path, "missing arch in universal file: expected {s}", .{@tagName(cpu_arch)}); } -pub fn readMachHeader(file: std.fs.File, offset: usize) !macho.mach_header_64 { +pub fn readMachHeader(io: Io, file: Io.File, offset: usize) !macho.mach_header_64 { var buffer: [@sizeOf(macho.mach_header_64)]u8 = undefined; - const nread = try file.preadAll(&buffer, offset); + const nread = try file.readPositionalAll(io, &buffer, offset); if (nread != buffer.len) return error.InputOutput; const hdr = @as(*align(1) const macho.mach_header_64, @ptrCast(&buffer)).*; return hdr; } -pub fn readArMagic(file: std.fs.File, offset: usize, buffer: *[Archive.SARMAG]u8) ![]const u8 { - const nread = try file.preadAll(buffer, offset); +pub fn readArMagic(io: Io, file: Io.File, offset: usize, buffer: *[Archive.SARMAG]u8) ![]const u8 { + const nread = try file.readPositionalAll(io, buffer, offset); if (nread != buffer.len) return error.InputOutput; return buffer[0..Archive.SARMAG]; } @@ -921,6 +934,7 @@ fn addObject(self: *MachO, path: Path, handle_index: File.HandleIndex, offset: u const comp = self.base.comp; const gpa = comp.gpa; + const io = comp.io; const abs_path = try std.fs.path.resolvePosix(gpa, &.{ comp.dirs.cwd, @@ -930,7 +944,7 @@ fn addObject(self: *MachO, path: Path, handle_index: File.HandleIndex, offset: u errdefer gpa.free(abs_path); const file = self.getFileHandle(handle_index); - const stat = try file.stat(); + const stat = try file.stat(io); const mtime = stat.mtime.toSeconds(); const index: File.Index = @intCast(try self.files.addOne(gpa)); self.files.set(index, .{ .object = .{ @@ -1069,6 +1083,7 @@ fn isHoisted(self: *MachO, install_name: []const u8) bool { /// TODO delete this, libraries must be instead resolved when instantiating the compilation pipeline fn accessLibPath( arena: Allocator, + io: Io, test_path: *std.array_list.Managed(u8), checked_paths: *std.array_list.Managed([]const u8), search_dir: []const u8, @@ -1080,7 +1095,7 @@ fn accessLibPath( test_path.clearRetainingCapacity(); try test_path.print("{s}" ++ sep ++ "lib{s}{s}", .{ search_dir, name, ext }); try checked_paths.append(try arena.dupe(u8, test_path.items)); - fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { + Io.Dir.cwd().access(io, test_path.items, .{}) catch |err| switch (err) { error.FileNotFound => continue, else => |e| return e, }; @@ -1092,6 +1107,7 @@ fn accessLibPath( fn accessFrameworkPath( arena: Allocator, + io: Io, test_path: *std.array_list.Managed(u8), checked_paths: *std.array_list.Managed([]const u8), search_dir: []const u8, @@ -1108,7 +1124,7 @@ fn accessFrameworkPath( ext, }); try checked_paths.append(try arena.dupe(u8, test_path.items)); - fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { + Io.Dir.cwd().access(io, test_path.items, .{}) catch |err| switch (err) { error.FileNotFound => continue, else => |e| return e, }; @@ -1124,7 +1140,9 @@ fn parseDependentDylibs(self: *MachO) !void { if (self.dylibs.items.len == 0) return; - const gpa = self.base.comp.gpa; + const comp = self.base.comp; + const gpa = comp.gpa; + const io = comp.io; const framework_dirs = self.framework_dirs; // TODO delete this, directories must instead be resolved by the frontend @@ -1165,14 +1183,14 @@ fn parseDependentDylibs(self: *MachO) !void { // Framework for (framework_dirs) |dir| { test_path.clearRetainingCapacity(); - if (try accessFrameworkPath(arena, &test_path, &checked_paths, dir, stem)) break :full_path test_path.items; + if (try accessFrameworkPath(arena, io, &test_path, &checked_paths, dir, stem)) break :full_path test_path.items; } // Library const lib_name = eatPrefix(stem, "lib") orelse stem; for (lib_directories) |lib_directory| { test_path.clearRetainingCapacity(); - if (try accessLibPath(arena, &test_path, &checked_paths, lib_directory.path orelse ".", lib_name)) break :full_path test_path.items; + if (try accessLibPath(arena, io, &test_path, &checked_paths, lib_directory.path orelse ".", lib_name)) break :full_path test_path.items; } } @@ -1181,13 +1199,13 @@ fn parseDependentDylibs(self: *MachO) !void { const path = if (existing_ext.len > 0) id.name[0 .. id.name.len - existing_ext.len] else id.name; for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| { test_path.clearRetainingCapacity(); - if (self.base.comp.sysroot) |root| { + if (comp.sysroot) |root| { try test_path.print("{s}" ++ fs.path.sep_str ++ "{s}{s}", .{ root, path, ext }); } else { try test_path.print("{s}{s}", .{ path, ext }); } try checked_paths.append(try arena.dupe(u8, test_path.items)); - fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { + Io.Dir.cwd().access(io, test_path.items, .{}) catch |err| switch (err) { error.FileNotFound => continue, else => |e| return e, }; @@ -1202,7 +1220,8 @@ fn parseDependentDylibs(self: *MachO) !void { const rel_path = try fs.path.join(arena, &.{ prefix, path }); try checked_paths.append(rel_path); var buffer: [fs.max_path_bytes]u8 = undefined; - const full_path = fs.realpath(rel_path, &buffer) catch continue; + // TODO don't use realpath + const full_path = buffer[0 .. Io.Dir.realPathFileAbsolute(io, rel_path, &buffer) catch continue]; break :full_path try arena.dupe(u8, full_path); } } else if (eatPrefix(id.name, "@loader_path/")) |_| { @@ -1215,8 +1234,9 @@ fn parseDependentDylibs(self: *MachO) !void { try checked_paths.append(try arena.dupe(u8, id.name)); var buffer: [fs.max_path_bytes]u8 = undefined; - if (fs.realpath(id.name, &buffer)) |full_path| { - break :full_path try arena.dupe(u8, full_path); + // TODO don't use realpath + if (Io.Dir.realPathFileAbsolute(io, id.name, &buffer)) |full_path_n| { + break :full_path try arena.dupe(u8, buffer[0..full_path_n]); } else |_| { try self.reportMissingDependencyError( self.getFile(dylib_index).?.dylib.getUmbrella(self).index, @@ -1233,12 +1253,12 @@ fn parseDependentDylibs(self: *MachO) !void { .path = Path.initCwd(full_path), .weak = is_weak, }; - const file = try lib.path.root_dir.handle.openFile(lib.path.sub_path, .{}); + const file = try lib.path.root_dir.handle.openFile(io, lib.path.sub_path, .{}); const fh = try self.addFileHandle(file); const fat_arch = try self.parseFatFile(file, lib.path); const offset = if (fat_arch) |fa| fa.offset else 0; const file_index = file_index: { - if (readMachHeader(file, offset) catch null) |h| blk: { + if (readMachHeader(io, file, offset) catch null) |h| blk: { if (h.magic != macho.MH_MAGIC_64) break :blk; switch (h.filetype) { macho.MH_DYLIB => break :file_index try self.addDylib(lib, false, fh, offset), @@ -3147,7 +3167,9 @@ fn detectAllocCollision(self: *MachO, start: u64, size: u64) !?u64 { } } - if (at_end) try self.base.file.?.setEndPos(end); + const comp = self.base.comp; + const io = comp.io; + if (at_end) try self.base.file.?.setLength(io, end); return null; } @@ -3232,21 +3254,36 @@ pub fn findFreeSpaceVirtual(self: *MachO, object_size: u64, min_alignment: u32) } pub fn copyRangeAll(self: *MachO, old_offset: u64, new_offset: u64, size: u64) !void { - const file = self.base.file.?; - const amt = try file.copyRangeAll(old_offset, file, new_offset, size); - if (amt != size) return error.InputOutput; + return self.base.copyRangeAll(old_offset, new_offset, size); } -/// Like File.copyRangeAll but also ensures the source region is zeroed out after copy. +/// Like copyRangeAll but also ensures the source region is zeroed out after copy. /// This is so that we guarantee zeroed out regions for mapping of zerofill sections by the loader. fn copyRangeAllZeroOut(self: *MachO, old_offset: u64, new_offset: u64, size: u64) !void { - const gpa = self.base.comp.gpa; - try self.copyRangeAll(old_offset, new_offset, size); + const comp = self.base.comp; + const io = comp.io; + const file = self.base.file.?; + var write_buffer: [2048]u8 = undefined; + var file_reader = file.reader(io, &.{}); + file_reader.pos = old_offset; + var file_writer = file.writer(io, &write_buffer); + file_writer.pos = new_offset; const size_u = math.cast(usize, size) orelse return error.Overflow; - const zeroes = try gpa.alloc(u8, size_u); // TODO no need to allocate here. - defer gpa.free(zeroes); - @memset(zeroes, 0); - try self.base.file.?.pwriteAll(zeroes, old_offset); + const n = file_writer.interface.sendFileAll(&file_reader, .limited(size_u)) catch |err| switch (err) { + error.ReadFailed => return file_reader.err.?, + error.WriteFailed => return file_writer.err.?, + }; + assert(n == size_u); + file_writer.seekTo(old_offset) catch |err| switch (err) { + error.WriteFailed => return file_writer.err.?, + else => |e| return e, + }; + file_writer.interface.splatByteAll(0, size_u) catch |err| switch (err) { + error.WriteFailed => return file_writer.err.?, + }; + file_writer.interface.flush() catch |err| switch (err) { + error.WriteFailed => return file_writer.err.?, + }; } const InitMetadataOptions = struct { @@ -3257,8 +3294,10 @@ const InitMetadataOptions = struct { }; pub fn closeDebugInfo(self: *MachO) bool { + const comp = self.base.comp; + const io = comp.io; const d_sym = &(self.d_sym orelse return false); - d_sym.file.?.close(); + d_sym.file.?.close(io); d_sym.file = null; return true; } @@ -3269,7 +3308,9 @@ pub fn reopenDebugInfo(self: *MachO) !void { assert(!self.base.comp.config.use_llvm); assert(self.base.comp.config.debug_format == .dwarf); - const gpa = self.base.comp.gpa; + const comp = self.base.comp; + const io = comp.io; + const gpa = comp.gpa; const sep = fs.path.sep_str; const d_sym_path = try std.fmt.allocPrint( gpa, @@ -3278,10 +3319,10 @@ pub fn reopenDebugInfo(self: *MachO) !void { ); defer gpa.free(d_sym_path); - var d_sym_bundle = try self.base.emit.root_dir.handle.makeOpenPath(d_sym_path, .{}); - defer d_sym_bundle.close(); + var d_sym_bundle = try self.base.emit.root_dir.handle.createDirPathOpen(io, d_sym_path, .{}); + defer d_sym_bundle.close(io); - self.d_sym.?.file = try d_sym_bundle.createFile(fs.path.basename(self.base.emit.sub_path), .{ + self.d_sym.?.file = try d_sym_bundle.createFile(io, fs.path.basename(self.base.emit.sub_path), .{ .truncate = false, .read = true, }); @@ -3289,6 +3330,10 @@ pub fn reopenDebugInfo(self: *MachO) !void { // TODO: move to ZigObject fn initMetadata(self: *MachO, options: InitMetadataOptions) !void { + const comp = self.base.comp; + const gpa = comp.gpa; + const io = comp.io; + if (!self.base.isRelocatable()) { const base_vmaddr = blk: { const pagezero_size = self.pagezero_size orelse default_pagezero_size; @@ -3343,7 +3388,11 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void { if (options.zo.dwarf) |*dwarf| { // Create dSYM bundle. log.debug("creating {s}.dSYM bundle", .{options.emit.sub_path}); - self.d_sym = .{ .allocator = self.base.comp.gpa, .file = null }; + self.d_sym = .{ + .io = io, + .allocator = gpa, + .file = null, + }; try self.reopenDebugInfo(); try self.d_sym.?.initMetadata(self); try dwarf.initMetadata(); @@ -3463,6 +3512,9 @@ fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !vo const seg_id = self.sections.items(.segment_id)[sect_index]; const seg = &self.segments.items[seg_id]; + const comp = self.base.comp; + const io = comp.io; + if (!sect.isZerofill()) { const allocated_size = self.allocatedSize(sect.offset); if (needed_size > allocated_size) { @@ -3484,7 +3536,7 @@ fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !vo sect.offset = @intCast(new_offset); } else if (sect.offset + allocated_size == std.math.maxInt(u64)) { - try self.base.file.?.setEndPos(sect.offset + needed_size); + try self.base.file.?.setLength(io, sect.offset + needed_size); } seg.filesize = needed_size; } @@ -3506,6 +3558,8 @@ fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !vo } fn growSectionRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !void { + const comp = self.base.comp; + const io = comp.io; const sect = &self.sections.items(.header)[sect_index]; if (!sect.isZerofill()) { @@ -3533,7 +3587,7 @@ fn growSectionRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !void sect.offset = @intCast(new_offset); sect.addr = new_addr; } else if (sect.offset + allocated_size == std.math.maxInt(u64)) { - try self.base.file.?.setEndPos(sect.offset + needed_size); + try self.base.file.?.setLength(io, sect.offset + needed_size); } } sect.size = needed_size; @@ -3567,11 +3621,11 @@ pub fn getTarget(self: *const MachO) *const std.Target { /// into a new inode, remove the original file, and rename the copy to match /// the original file. This is super messy, but there doesn't seem any other /// way to please the XNU. -pub fn invalidateKernelCache(dir: fs.Dir, sub_path: []const u8) !void { +pub fn invalidateKernelCache(io: Io, dir: Io.Dir, sub_path: []const u8) !void { const tracy = trace(@src()); defer tracy.end(); if (builtin.target.os.tag.isDarwin() and builtin.target.cpu.arch == .aarch64) { - try dir.copyFile(sub_path, dir, sub_path, .{}); + try dir.copyFile(sub_path, dir, sub_path, io, .{}); } } @@ -3762,7 +3816,7 @@ pub fn getInternalObject(self: *MachO) ?*InternalObject { return self.getFile(index).?.internal; } -pub fn addFileHandle(self: *MachO, file: fs.File) !File.HandleIndex { +pub fn addFileHandle(self: *MachO, file: Io.File) !File.HandleIndex { const gpa = self.base.comp.gpa; const index: File.HandleIndex = @intCast(self.file_handles.items.len); const fh = try self.file_handles.addOne(gpa); @@ -4333,11 +4387,13 @@ fn inferSdkVersion(comp: *Compilation, sdk_layout: SdkLayout) ?std.SemanticVersi defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); + const io = comp.io; + const sdk_dir = switch (sdk_layout) { .sdk => comp.sysroot.?, .vendored => fs.path.join(arena, &.{ comp.dirs.zig_lib.path.?, "libc", "darwin" }) catch return null, }; - if (readSdkVersionFromSettings(arena, sdk_dir)) |ver| { + if (readSdkVersionFromSettings(arena, io, sdk_dir)) |ver| { return parseSdkVersion(ver); } else |_| { // Read from settings should always succeed when vendored. @@ -4360,9 +4416,9 @@ fn inferSdkVersion(comp: *Compilation, sdk_layout: SdkLayout) ?std.SemanticVersi // Official Apple SDKs ship with a `SDKSettings.json` located at the top of SDK fs layout. // Use property `MinimalDisplayName` to determine version. // The file/property is also available with vendored libc. -fn readSdkVersionFromSettings(arena: Allocator, dir: []const u8) ![]const u8 { +fn readSdkVersionFromSettings(arena: Allocator, io: Io, dir: []const u8) ![]const u8 { const sdk_path = try fs.path.join(arena, &.{ dir, "SDKSettings.json" }); - const contents = try fs.cwd().readFileAlloc(sdk_path, arena, .limited(std.math.maxInt(u16))); + const contents = try Io.Dir.cwd().readFileAlloc(io, sdk_path, arena, .limited(std.math.maxInt(u16))); const parsed = try std.json.parseFromSlice(std.json.Value, arena, contents, .{}); if (parsed.value.object.get("MinimalDisplayName")) |ver| return ver.string; return error.SdkVersionFailure; @@ -5324,18 +5380,18 @@ fn isReachable(atom: *const Atom, rel: Relocation, macho_file: *MachO) bool { pub fn pwriteAll(macho_file: *MachO, bytes: []const u8, offset: u64) error{LinkFailure}!void { const comp = macho_file.base.comp; + const io = comp.io; const diags = &comp.link_diags; - macho_file.base.file.?.pwriteAll(bytes, offset) catch |err| { - return diags.fail("failed to write: {s}", .{@errorName(err)}); - }; + macho_file.base.file.?.writePositionalAll(io, bytes, offset) catch |err| + return diags.fail("failed to write: {t}", .{err}); } -pub fn setEndPos(macho_file: *MachO, length: u64) error{LinkFailure}!void { +pub fn setLength(macho_file: *MachO, length: u64) error{LinkFailure}!void { const comp = macho_file.base.comp; + const io = comp.io; const diags = &comp.link_diags; - macho_file.base.file.?.setEndPos(length) catch |err| { - return diags.fail("failed to set file end pos: {s}", .{@errorName(err)}); - }; + macho_file.base.file.?.setLength(io, length) catch |err| + return diags.fail("failed to set file end pos: {t}", .{err}); } pub fn cast(macho_file: *MachO, comptime T: type, x: anytype) error{LinkFailure}!T { @@ -5367,10 +5423,11 @@ const max_distance = (1 << (jump_bits - 1)); const max_allowed_distance = max_distance - 0x500_000; const MachO = @This(); - -const std = @import("std"); const build_options = @import("build_options"); const builtin = @import("builtin"); + +const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; const fs = std.fs; const log = std.log.scoped(.link); @@ -5380,6 +5437,11 @@ const math = std.math; const mem = std.mem; const meta = std.meta; const Writer = std.Io.Writer; +const AtomicBool = std.atomic.Value(bool); +const Cache = std.Build.Cache; +const Hash = std.hash.Wyhash; +const Md5 = std.crypto.hash.Md5; +const Allocator = std.mem.Allocator; const aarch64 = codegen.aarch64.encoding; const bind = @import("MachO/dyld_info/bind.zig"); @@ -5397,11 +5459,8 @@ const trace = @import("../tracy.zig").trace; const synthetic = @import("MachO/synthetic.zig"); const Alignment = Atom.Alignment; -const Allocator = mem.Allocator; const Archive = @import("MachO/Archive.zig"); -const AtomicBool = std.atomic.Value(bool); const Bind = bind.Bind; -const Cache = std.Build.Cache; const CodeSignature = @import("MachO/CodeSignature.zig"); const Compilation = @import("../Compilation.zig"); const DataInCode = synthetic.DataInCode; @@ -5411,14 +5470,12 @@ const ExportTrie = @import("MachO/dyld_info/Trie.zig"); const Path = Cache.Path; const File = @import("MachO/file.zig").File; const GotSection = synthetic.GotSection; -const Hash = std.hash.Wyhash; const Indsymtab = synthetic.Indsymtab; const InternalObject = @import("MachO/InternalObject.zig"); const ObjcStubsSection = synthetic.ObjcStubsSection; const Object = @import("MachO/Object.zig"); const LazyBind = bind.LazyBind; const LaSymbolPtrSection = synthetic.LaSymbolPtrSection; -const Md5 = std.crypto.hash.Md5; const Zcu = @import("../Zcu.zig"); const InternPool = @import("../InternPool.zig"); const Rebase = @import("MachO/dyld_info/Rebase.zig"); diff --git a/src/link/MachO/Archive.zig b/src/link/MachO/Archive.zig index d1962412c428..54c00e33eef7 100644 --- a/src/link/MachO/Archive.zig +++ b/src/link/MachO/Archive.zig @@ -6,6 +6,7 @@ pub fn deinit(self: *Archive, allocator: Allocator) void { pub fn unpack(self: *Archive, macho_file: *MachO, path: Path, handle_index: File.HandleIndex, fat_arch: ?fat.Arch) !void { const comp = macho_file.base.comp; + const io = comp.io; const gpa = comp.gpa; const diags = &comp.link_diags; @@ -14,7 +15,7 @@ pub fn unpack(self: *Archive, macho_file: *MachO, path: Path, handle_index: File const handle = macho_file.getFileHandle(handle_index); const offset = if (fat_arch) |ar| ar.offset else 0; - const end_pos = if (fat_arch) |ar| offset + ar.size else (try handle.stat()).size; + const end_pos = if (fat_arch) |ar| offset + ar.size else (try handle.stat(io)).size; var pos: usize = offset + SARMAG; while (true) { @@ -23,7 +24,7 @@ pub fn unpack(self: *Archive, macho_file: *MachO, path: Path, handle_index: File var hdr_buffer: [@sizeOf(ar_hdr)]u8 = undefined; { - const amt = try handle.preadAll(&hdr_buffer, pos); + const amt = try handle.readPositionalAll(io, &hdr_buffer, pos); if (amt != @sizeOf(ar_hdr)) return error.InputOutput; } const hdr = @as(*align(1) const ar_hdr, @ptrCast(&hdr_buffer)).*; @@ -41,7 +42,7 @@ pub fn unpack(self: *Archive, macho_file: *MachO, path: Path, handle_index: File if (try hdr.nameLength()) |len| { hdr_size -= len; const buf = try arena.allocator().alloc(u8, len); - const amt = try handle.preadAll(buf, pos); + const amt = try handle.readPositionalAll(io, buf, pos); if (amt != len) return error.InputOutput; pos += len; const actual_len = mem.indexOfScalar(u8, buf, @as(u8, 0)) orelse len; diff --git a/src/link/MachO/Atom.zig b/src/link/MachO/Atom.zig index a8c1ed843e25..8f0f8019493d 100644 --- a/src/link/MachO/Atom.zig +++ b/src/link/MachO/Atom.zig @@ -555,9 +555,10 @@ fn reportUndefSymbol(self: Atom, rel: Relocation, macho_file: *MachO) !bool { const file = self.getFile(macho_file); const ref = file.getSymbolRef(rel.target, macho_file); if (ref.getFile(macho_file) == null) { - macho_file.undefs_mutex.lock(); - defer macho_file.undefs_mutex.unlock(); const gpa = macho_file.base.comp.gpa; + const io = macho_file.base.comp.io; + macho_file.undefs_mutex.lockUncancelable(io); + defer macho_file.undefs_mutex.unlock(io); const gop = try macho_file.undefs.getOrPut(gpa, file.getGlobals()[rel.target]); if (!gop.found_existing) { gop.value_ptr.* = .{ .refs = .{} }; diff --git a/src/link/MachO/CodeSignature.zig b/src/link/MachO/CodeSignature.zig index 0390cc2fe4d6..0955c823b8de 100644 --- a/src/link/MachO/CodeSignature.zig +++ b/src/link/MachO/CodeSignature.zig @@ -1,20 +1,28 @@ const CodeSignature = @This(); const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; const fs = std.fs; const log = std.log.scoped(.link); const macho = std.macho; const mem = std.mem; const testing = std.testing; +const Sha256 = std.crypto.hash.sha2.Sha256; +const Allocator = std.mem.Allocator; + const trace = @import("../../tracy.zig").trace; -const Allocator = mem.Allocator; -const Hasher = @import("hasher.zig").ParallelHasher; +const ParallelHasher = @import("hasher.zig").ParallelHasher; const MachO = @import("../MachO.zig"); -const Sha256 = std.crypto.hash.sha2.Sha256; const hash_size = Sha256.digest_length; +page_size: u16, +code_directory: CodeDirectory, +requirements: ?Requirements = null, +entitlements: ?Entitlements = null, +signature: ?Signature = null, + const Blob = union(enum) { code_directory: *CodeDirectory, requirements: *Requirements, @@ -218,12 +226,6 @@ const Signature = struct { } }; -page_size: u16, -code_directory: CodeDirectory, -requirements: ?Requirements = null, -entitlements: ?Entitlements = null, -signature: ?Signature = null, - pub fn init(page_size: u16) CodeSignature { return .{ .page_size = page_size, @@ -244,13 +246,13 @@ pub fn deinit(self: *CodeSignature, allocator: Allocator) void { } } -pub fn addEntitlements(self: *CodeSignature, allocator: Allocator, path: []const u8) !void { - const inner = try fs.cwd().readFileAlloc(path, allocator, .limited(std.math.maxInt(u32))); +pub fn addEntitlements(self: *CodeSignature, allocator: Allocator, io: Io, path: []const u8) !void { + const inner = try Io.Dir.cwd().readFileAlloc(io, path, allocator, .limited(std.math.maxInt(u32))); self.entitlements = .{ .inner = inner }; } pub const WriteOpts = struct { - file: fs.File, + file: Io.File, exec_seg_base: u64, exec_seg_limit: u64, file_size: u32, @@ -266,7 +268,9 @@ pub fn writeAdhocSignature( const tracy = trace(@src()); defer tracy.end(); - const allocator = macho_file.base.comp.gpa; + const comp = macho_file.base.comp; + const gpa = comp.gpa; + const io = comp.io; var header: macho.SuperBlob = .{ .magic = macho.CSMAGIC_EMBEDDED_SIGNATURE, @@ -274,7 +278,7 @@ pub fn writeAdhocSignature( .count = 0, }; - var blobs = std.array_list.Managed(Blob).init(allocator); + var blobs = std.array_list.Managed(Blob).init(gpa); defer blobs.deinit(); self.code_directory.inner.execSegBase = opts.exec_seg_base; @@ -284,13 +288,12 @@ pub fn writeAdhocSignature( const total_pages = @as(u32, @intCast(mem.alignForward(usize, opts.file_size, self.page_size) / self.page_size)); - try self.code_directory.code_slots.ensureTotalCapacityPrecise(allocator, total_pages); + try self.code_directory.code_slots.ensureTotalCapacityPrecise(gpa, total_pages); self.code_directory.code_slots.items.len = total_pages; self.code_directory.inner.nCodeSlots = total_pages; // Calculate hash for each page (in file) and write it to the buffer - var hasher = Hasher(Sha256){ .allocator = allocator, .thread_pool = macho_file.base.comp.thread_pool }; - try hasher.hash(opts.file, self.code_directory.code_slots.items, .{ + try ParallelHasher(Sha256).hash(gpa, io, opts.file, self.code_directory.code_slots.items, .{ .chunk_size = self.page_size, .max_file_size = opts.file_size, }); @@ -302,7 +305,7 @@ pub fn writeAdhocSignature( var hash: [hash_size]u8 = undefined; if (self.requirements) |*req| { - var a: std.Io.Writer.Allocating = .init(allocator); + var a: std.Io.Writer.Allocating = .init(gpa); defer a.deinit(); try req.write(&a.writer); Sha256.hash(a.written(), &hash, .{}); @@ -314,7 +317,7 @@ pub fn writeAdhocSignature( } if (self.entitlements) |*ents| { - var a: std.Io.Writer.Allocating = .init(allocator); + var a: std.Io.Writer.Allocating = .init(gpa); defer a.deinit(); try ents.write(&a.writer); Sha256.hash(a.written(), &hash, .{}); diff --git a/src/link/MachO/DebugSymbols.zig b/src/link/MachO/DebugSymbols.zig index 5d7b9b88c3fe..3e723bd9d72a 100644 --- a/src/link/MachO/DebugSymbols.zig +++ b/src/link/MachO/DebugSymbols.zig @@ -1,5 +1,28 @@ +const DebugSymbols = @This(); + +const std = @import("std"); +const Io = std.Io; +const assert = std.debug.assert; +const fs = std.fs; +const log = std.log.scoped(.link_dsym); +const macho = std.macho; +const makeStaticString = MachO.makeStaticString; +const math = std.math; +const mem = std.mem; +const Writer = std.Io.Writer; +const Allocator = std.mem.Allocator; + +const link = @import("../../link.zig"); +const MachO = @import("../MachO.zig"); +const StringTable = @import("../StringTable.zig"); +const Type = @import("../../Type.zig"); +const trace = @import("../../tracy.zig").trace; +const load_commands = @import("load_commands.zig"); +const padToIdeal = MachO.padToIdeal; + +io: Io, allocator: Allocator, -file: ?fs.File, +file: ?Io.File, symtab_cmd: macho.symtab_command = .{}, uuid_cmd: macho.uuid_command = .{ .uuid = [_]u8{0} ** 16 }, @@ -102,6 +125,7 @@ pub fn growSection( requires_file_copy: bool, macho_file: *MachO, ) !void { + const io = self.io; const sect = self.getSectionPtr(sect_index); const allocated_size = self.allocatedSize(sect.offset); @@ -111,25 +135,17 @@ pub fn growSection( const new_offset = try self.findFreeSpace(needed_size, 1); log.debug("moving {s} section: {} bytes from 0x{x} to 0x{x}", .{ - sect.sectName(), - existing_size, - sect.offset, - new_offset, + sect.sectName(), existing_size, sect.offset, new_offset, }); if (requires_file_copy) { - const amt = try self.file.?.copyRangeAll( - sect.offset, - self.file.?, - new_offset, - existing_size, - ); - if (amt != existing_size) return error.InputOutput; + const file = self.file.?; + try link.File.copyRangeAll2(io, file, file, sect.offset, new_offset, existing_size); } sect.offset = @intCast(new_offset); } else if (sect.offset + allocated_size == std.math.maxInt(u64)) { - try self.file.?.setEndPos(sect.offset + needed_size); + try self.file.?.setLength(io, sect.offset + needed_size); } sect.size = needed_size; @@ -153,6 +169,7 @@ pub fn markDirty(self: *DebugSymbols, sect_index: u8, macho_file: *MachO) void { } fn detectAllocCollision(self: *DebugSymbols, start: u64, size: u64) !?u64 { + const io = self.io; var at_end = true; const end = start + padToIdeal(size); @@ -165,7 +182,7 @@ fn detectAllocCollision(self: *DebugSymbols, start: u64, size: u64) !?u64 { } } - if (at_end) try self.file.?.setEndPos(end); + if (at_end) try self.file.?.setLength(io, end); return null; } @@ -179,6 +196,7 @@ fn findFreeSpace(self: *DebugSymbols, object_size: u64, min_alignment: u64) !u64 } pub fn flush(self: *DebugSymbols, macho_file: *MachO) !void { + const io = self.io; const zo = macho_file.getZigObject().?; for (self.relocs.items) |*reloc| { const sym = zo.symbols.items[reloc.target]; @@ -190,12 +208,9 @@ pub fn flush(self: *DebugSymbols, macho_file: *MachO) !void { const sect = &self.sections.items[self.debug_info_section_index.?]; const file_offset = sect.offset + reloc.offset; log.debug("resolving relocation: {d}@{x} ('{s}') at offset {x}", .{ - reloc.target, - addr, - sym_name, - file_offset, + reloc.target, addr, sym_name, file_offset, }); - try self.file.?.pwriteAll(mem.asBytes(&addr), file_offset); + try self.file.?.writePositionalAll(io, mem.asBytes(&addr), file_offset); } self.finalizeDwarfSegment(macho_file); @@ -208,7 +223,8 @@ pub fn flush(self: *DebugSymbols, macho_file: *MachO) !void { pub fn deinit(self: *DebugSymbols) void { const gpa = self.allocator; - if (self.file) |file| file.close(); + const io = self.io; + if (self.file) |file| file.close(io); self.segments.deinit(gpa); self.sections.deinit(gpa); self.relocs.deinit(gpa); @@ -268,6 +284,7 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void { } fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, usize } { + const io = self.io; const gpa = self.allocator; const needed_size = load_commands.calcLoadCommandsSizeDsym(macho_file, self); const buffer = try gpa.alloc(u8, needed_size); @@ -319,12 +336,13 @@ fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, u assert(writer.end == needed_size); - try self.file.?.pwriteAll(buffer, @sizeOf(macho.mach_header_64)); + try self.file.?.writePositionalAll(io, buffer, @sizeOf(macho.mach_header_64)); return .{ ncmds, buffer.len }; } fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: usize, sizeofcmds: usize) !void { + const io = self.io; var header: macho.mach_header_64 = .{}; header.filetype = macho.MH_DSYM; @@ -345,7 +363,7 @@ fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: usize, sizeofcmds log.debug("writing Mach-O header {}", .{header}); - try self.file.?.pwriteAll(mem.asBytes(&header), 0); + try self.file.?.writePositionalAll(io, mem.asBytes(&header), 0); } fn allocatedSize(self: *DebugSymbols, start: u64) u64 { @@ -380,6 +398,8 @@ fn writeLinkeditSegmentData(self: *DebugSymbols, macho_file: *MachO) !void { pub fn writeSymtab(self: *DebugSymbols, off: u32, macho_file: *MachO) !u32 { const tracy = trace(@src()); defer tracy.end(); + + const io = self.io; const gpa = self.allocator; const cmd = &self.symtab_cmd; cmd.nsyms = macho_file.symtab_cmd.nsyms; @@ -403,15 +423,16 @@ pub fn writeSymtab(self: *DebugSymbols, off: u32, macho_file: *MachO) !u32 { internal.writeSymtab(macho_file, self); } - try self.file.?.pwriteAll(@ptrCast(self.symtab.items), cmd.symoff); + try self.file.?.writePositionalAll(io, @ptrCast(self.symtab.items), cmd.symoff); return off + cmd.nsyms * @sizeOf(macho.nlist_64); } pub fn writeStrtab(self: *DebugSymbols, off: u32) !u32 { + const io = self.io; const cmd = &self.symtab_cmd; cmd.stroff = off; - try self.file.?.pwriteAll(self.strtab.items, cmd.stroff); + try self.file.?.writePositionalAll(io, self.strtab.items, cmd.stroff); return off + cmd.strsize; } @@ -443,25 +464,3 @@ pub fn getSection(self: DebugSymbols, sect: u8) macho.section_64 { assert(sect < self.sections.items.len); return self.sections.items[sect]; } - -const DebugSymbols = @This(); - -const std = @import("std"); -const build_options = @import("build_options"); -const assert = std.debug.assert; -const fs = std.fs; -const link = @import("../../link.zig"); -const load_commands = @import("load_commands.zig"); -const log = std.log.scoped(.link_dsym); -const macho = std.macho; -const makeStaticString = MachO.makeStaticString; -const math = std.math; -const mem = std.mem; -const padToIdeal = MachO.padToIdeal; -const trace = @import("../../tracy.zig").trace; -const Writer = std.Io.Writer; - -const Allocator = mem.Allocator; -const MachO = @import("../MachO.zig"); -const StringTable = @import("../StringTable.zig"); -const Type = @import("../../Type.zig"); diff --git a/src/link/MachO/Dylib.zig b/src/link/MachO/Dylib.zig index 69c64b6717d5..638630b608b0 100644 --- a/src/link/MachO/Dylib.zig +++ b/src/link/MachO/Dylib.zig @@ -57,7 +57,9 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void { const tracy = trace(@src()); defer tracy.end(); - const gpa = macho_file.base.comp.gpa; + const comp = macho_file.base.comp; + const io = comp.io; + const gpa = comp.gpa; const file = macho_file.getFileHandle(self.file_handle); const offset = self.offset; @@ -65,7 +67,7 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void { var header_buffer: [@sizeOf(macho.mach_header_64)]u8 = undefined; { - const amt = try file.preadAll(&header_buffer, offset); + const amt = try file.readPositionalAll(io, &header_buffer, offset); if (amt != @sizeOf(macho.mach_header_64)) return error.InputOutput; } const header = @as(*align(1) const macho.mach_header_64, @ptrCast(&header_buffer)).*; @@ -86,7 +88,7 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void { const lc_buffer = try gpa.alloc(u8, header.sizeofcmds); defer gpa.free(lc_buffer); { - const amt = try file.preadAll(lc_buffer, offset + @sizeOf(macho.mach_header_64)); + const amt = try file.readPositionalAll(io, lc_buffer, offset + @sizeOf(macho.mach_header_64)); if (amt != lc_buffer.len) return error.InputOutput; } @@ -103,7 +105,7 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void { const dyld_cmd = cmd.cast(macho.dyld_info_command).?; const data = try gpa.alloc(u8, dyld_cmd.export_size); defer gpa.free(data); - const amt = try file.preadAll(data, dyld_cmd.export_off + offset); + const amt = try file.readPositionalAll(io, data, dyld_cmd.export_off + offset); if (amt != data.len) return error.InputOutput; try self.parseTrie(data, macho_file); }, @@ -111,7 +113,7 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void { const ld_cmd = cmd.cast(macho.linkedit_data_command).?; const data = try gpa.alloc(u8, ld_cmd.datasize); defer gpa.free(data); - const amt = try file.preadAll(data, ld_cmd.dataoff + offset); + const amt = try file.readPositionalAll(io, data, ld_cmd.dataoff + offset); if (amt != data.len) return error.InputOutput; try self.parseTrie(data, macho_file); }, @@ -238,13 +240,15 @@ fn parseTbd(self: *Dylib, macho_file: *MachO) !void { const tracy = trace(@src()); defer tracy.end(); - const gpa = macho_file.base.comp.gpa; + const comp = macho_file.base.comp; + const gpa = comp.gpa; + const io = comp.io; log.debug("parsing dylib from stub: {f}", .{self.path}); const file = macho_file.getFileHandle(self.file_handle); - var lib_stub = LibStub.loadFromFile(gpa, file) catch |err| { - try macho_file.reportParseError2(self.index, "failed to parse TBD file: {s}", .{@errorName(err)}); + var lib_stub = LibStub.loadFromFile(gpa, io, file) catch |err| { + try macho_file.reportParseError2(self.index, "failed to parse TBD file: {t}", .{err}); return error.MalformedTbd; }; defer lib_stub.deinit(); diff --git a/src/link/MachO/InternalObject.zig b/src/link/MachO/InternalObject.zig index 802381207ee3..fb4571d45195 100644 --- a/src/link/MachO/InternalObject.zig +++ b/src/link/MachO/InternalObject.zig @@ -512,8 +512,9 @@ pub fn checkUndefs(self: InternalObject, macho_file: *MachO) !void { const addUndef = struct { fn addUndef(mf: *MachO, index: MachO.SymbolResolver.Index, tag: anytype) !void { const gpa = mf.base.comp.gpa; - mf.undefs_mutex.lock(); - defer mf.undefs_mutex.unlock(); + const io = mf.base.comp.io; + mf.undefs_mutex.lockUncancelable(io); + defer mf.undefs_mutex.unlock(io); const gop = try mf.undefs.getOrPut(gpa, index); if (!gop.found_existing) { gop.value_ptr.* = tag; diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig index 5fc77fe7634b..b9def4568df9 100644 --- a/src/link/MachO/Object.zig +++ b/src/link/MachO/Object.zig @@ -1,3 +1,30 @@ +const Object = @This(); + +const trace = @import("../../tracy.zig").trace; +const Archive = @import("Archive.zig"); +const Atom = @import("Atom.zig"); +const Dwarf = @import("Dwarf.zig"); +const File = @import("file.zig").File; +const MachO = @import("../MachO.zig"); +const Relocation = @import("Relocation.zig"); +const Symbol = @import("Symbol.zig"); +const UnwindInfo = @import("UnwindInfo.zig"); + +const std = @import("std"); +const Io = std.Io; +const Writer = std.Io.Writer; +const assert = std.debug.assert; +const log = std.log.scoped(.link); +const macho = std.macho; +const LoadCommandIterator = macho.LoadCommandIterator; +const math = std.math; +const mem = std.mem; +const Allocator = std.mem.Allocator; + +const eh_frame = @import("eh_frame.zig"); +const Cie = eh_frame.Cie; +const Fde = eh_frame.Fde; + /// Non-zero for fat object files or archives offset: u64, /// If `in_archive` is not `null`, this is the basename of the object in the archive. Otherwise, @@ -75,7 +102,9 @@ pub fn parse(self: *Object, macho_file: *MachO) !void { log.debug("parsing {f}", .{self.fmtPath()}); - const gpa = macho_file.base.comp.gpa; + const comp = macho_file.base.comp; + const io = comp.io; + const gpa = comp.gpa; const handle = macho_file.getFileHandle(self.file_handle); const cpu_arch = macho_file.getTarget().cpu.arch; @@ -84,7 +113,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void { var header_buffer: [@sizeOf(macho.mach_header_64)]u8 = undefined; { - const amt = try handle.preadAll(&header_buffer, self.offset); + const amt = try handle.readPositionalAll(io, &header_buffer, self.offset); if (amt != @sizeOf(macho.mach_header_64)) return error.InputOutput; } self.header = @as(*align(1) const macho.mach_header_64, @ptrCast(&header_buffer)).*; @@ -105,7 +134,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void { const lc_buffer = try gpa.alloc(u8, self.header.?.sizeofcmds); defer gpa.free(lc_buffer); { - const amt = try handle.preadAll(lc_buffer, self.offset + @sizeOf(macho.mach_header_64)); + const amt = try handle.readPositionalAll(io, lc_buffer, self.offset + @sizeOf(macho.mach_header_64)); if (amt != self.header.?.sizeofcmds) return error.InputOutput; } @@ -129,14 +158,14 @@ pub fn parse(self: *Object, macho_file: *MachO) !void { const cmd = lc.cast(macho.symtab_command).?; try self.strtab.resize(gpa, cmd.strsize); { - const amt = try handle.preadAll(self.strtab.items, cmd.stroff + self.offset); + const amt = try handle.readPositionalAll(io, self.strtab.items, cmd.stroff + self.offset); if (amt != self.strtab.items.len) return error.InputOutput; } const symtab_buffer = try gpa.alloc(u8, cmd.nsyms * @sizeOf(macho.nlist_64)); defer gpa.free(symtab_buffer); { - const amt = try handle.preadAll(symtab_buffer, cmd.symoff + self.offset); + const amt = try handle.readPositionalAll(io, symtab_buffer, cmd.symoff + self.offset); if (amt != symtab_buffer.len) return error.InputOutput; } const symtab = @as([*]align(1) const macho.nlist_64, @ptrCast(symtab_buffer.ptr))[0..cmd.nsyms]; @@ -154,7 +183,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void { const buffer = try gpa.alloc(u8, cmd.datasize); defer gpa.free(buffer); { - const amt = try handle.preadAll(buffer, self.offset + cmd.dataoff); + const amt = try handle.readPositionalAll(io, buffer, self.offset + cmd.dataoff); if (amt != buffer.len) return error.InputOutput; } const ndice = @divExact(cmd.datasize, @sizeOf(macho.data_in_code_entry)); @@ -440,12 +469,14 @@ fn initCstringLiterals(self: *Object, allocator: Allocator, file: File.Handle, m const tracy = trace(@src()); defer tracy.end(); + const comp = macho_file.base.comp; + const io = comp.io; const slice = self.sections.slice(); for (slice.items(.header), 0..) |sect, n_sect| { if (!isCstringLiteral(sect)) continue; - const data = try self.readSectionData(allocator, file, @intCast(n_sect)); + const data = try self.readSectionData(allocator, io, file, @intCast(n_sect)); defer allocator.free(data); var count: u32 = 0; @@ -628,7 +659,9 @@ pub fn resolveLiterals(self: *Object, lp: *MachO.LiteralPool, macho_file: *MachO const tracy = trace(@src()); defer tracy.end(); - const gpa = macho_file.base.comp.gpa; + const comp = macho_file.base.comp; + const io = comp.io; + const gpa = comp.gpa; const file = macho_file.getFileHandle(self.file_handle); var buffer = std.array_list.Managed(u8).init(gpa); @@ -647,7 +680,7 @@ pub fn resolveLiterals(self: *Object, lp: *MachO.LiteralPool, macho_file: *MachO const slice = self.sections.slice(); for (slice.items(.header), slice.items(.subsections), 0..) |header, subs, n_sect| { if (isCstringLiteral(header) or isFixedSizeLiteral(header)) { - const data = try self.readSectionData(gpa, file, @intCast(n_sect)); + const data = try self.readSectionData(gpa, io, file, @intCast(n_sect)); defer gpa.free(data); for (subs.items) |sub| { @@ -682,7 +715,7 @@ pub fn resolveLiterals(self: *Object, lp: *MachO.LiteralPool, macho_file: *MachO buffer.resize(target_size) catch unreachable; const gop = try sections_data.getOrPut(target.n_sect); if (!gop.found_existing) { - gop.value_ptr.* = try self.readSectionData(gpa, file, @intCast(target.n_sect)); + gop.value_ptr.* = try self.readSectionData(gpa, io, file, @intCast(target.n_sect)); } const data = gop.value_ptr.*; const target_off = try macho_file.cast(usize, target.off); @@ -1037,9 +1070,11 @@ fn initEhFrameRecords(self: *Object, allocator: Allocator, sect_id: u8, file: Fi const sect = slice.items(.header)[sect_id]; const relocs = slice.items(.relocs)[sect_id]; + const comp = macho_file.base.comp; + const io = comp.io; const size = try macho_file.cast(usize, sect.size); try self.eh_frame_data.resize(allocator, size); - const amt = try file.preadAll(self.eh_frame_data.items, sect.offset + self.offset); + const amt = try file.readPositionalAll(io, self.eh_frame_data.items, sect.offset + self.offset); if (amt != self.eh_frame_data.items.len) return error.InputOutput; // Check for non-personality relocs in FDEs and apply them @@ -1138,8 +1173,10 @@ fn initUnwindRecords(self: *Object, allocator: Allocator, sect_id: u8, file: Fil } }; + const comp = macho_file.base.comp; + const io = comp.io; const header = self.sections.items(.header)[sect_id]; - const data = try self.readSectionData(allocator, file, sect_id); + const data = try self.readSectionData(allocator, io, file, sect_id); defer allocator.free(data); const nrecs = @divExact(data.len, @sizeOf(macho.compact_unwind_entry)); @@ -1348,7 +1385,9 @@ fn parseDebugInfo(self: *Object, macho_file: *MachO) !void { const tracy = trace(@src()); defer tracy.end(); - const gpa = macho_file.base.comp.gpa; + const comp = macho_file.base.comp; + const io = comp.io; + const gpa = comp.gpa; const file = macho_file.getFileHandle(self.file_handle); var dwarf: Dwarf = .{}; @@ -1358,18 +1397,18 @@ fn parseDebugInfo(self: *Object, macho_file: *MachO) !void { const n_sect: u8 = @intCast(index); if (sect.attrs() & macho.S_ATTR_DEBUG == 0) continue; if (mem.eql(u8, sect.sectName(), "__debug_info")) { - dwarf.debug_info = try self.readSectionData(gpa, file, n_sect); + dwarf.debug_info = try self.readSectionData(gpa, io, file, n_sect); } if (mem.eql(u8, sect.sectName(), "__debug_abbrev")) { - dwarf.debug_abbrev = try self.readSectionData(gpa, file, n_sect); + dwarf.debug_abbrev = try self.readSectionData(gpa, io, file, n_sect); } if (mem.eql(u8, sect.sectName(), "__debug_str")) { - dwarf.debug_str = try self.readSectionData(gpa, file, n_sect); + dwarf.debug_str = try self.readSectionData(gpa, io, file, n_sect); } // __debug_str_offs[ets] section is a new addition in DWARFv5 and is generally // required in order to correctly parse strings. if (mem.eql(u8, sect.sectName(), "__debug_str_offs")) { - dwarf.debug_str_offsets = try self.readSectionData(gpa, file, n_sect); + dwarf.debug_str_offsets = try self.readSectionData(gpa, io, file, n_sect); } } @@ -1611,12 +1650,14 @@ pub fn parseAr(self: *Object, macho_file: *MachO) !void { const tracy = trace(@src()); defer tracy.end(); - const gpa = macho_file.base.comp.gpa; + const comp = macho_file.base.comp; + const io = comp.io; + const gpa = comp.gpa; const handle = macho_file.getFileHandle(self.file_handle); var header_buffer: [@sizeOf(macho.mach_header_64)]u8 = undefined; { - const amt = try handle.preadAll(&header_buffer, self.offset); + const amt = try handle.readPositionalAll(io, &header_buffer, self.offset); if (amt != @sizeOf(macho.mach_header_64)) return error.InputOutput; } self.header = @as(*align(1) const macho.mach_header_64, @ptrCast(&header_buffer)).*; @@ -1637,7 +1678,7 @@ pub fn parseAr(self: *Object, macho_file: *MachO) !void { const lc_buffer = try gpa.alloc(u8, self.header.?.sizeofcmds); defer gpa.free(lc_buffer); { - const amt = try handle.preadAll(lc_buffer, self.offset + @sizeOf(macho.mach_header_64)); + const amt = try handle.readPositionalAll(io, lc_buffer, self.offset + @sizeOf(macho.mach_header_64)); if (amt != self.header.?.sizeofcmds) return error.InputOutput; } @@ -1647,14 +1688,14 @@ pub fn parseAr(self: *Object, macho_file: *MachO) !void { const cmd = lc.cast(macho.symtab_command).?; try self.strtab.resize(gpa, cmd.strsize); { - const amt = try handle.preadAll(self.strtab.items, cmd.stroff + self.offset); + const amt = try handle.readPositionalAll(io, self.strtab.items, cmd.stroff + self.offset); if (amt != self.strtab.items.len) return error.InputOutput; } const symtab_buffer = try gpa.alloc(u8, cmd.nsyms * @sizeOf(macho.nlist_64)); defer gpa.free(symtab_buffer); { - const amt = try handle.preadAll(symtab_buffer, cmd.symoff + self.offset); + const amt = try handle.readPositionalAll(io, symtab_buffer, cmd.symoff + self.offset); if (amt != symtab_buffer.len) return error.InputOutput; } const symtab = @as([*]align(1) const macho.nlist_64, @ptrCast(symtab_buffer.ptr))[0..cmd.nsyms]; @@ -1689,13 +1730,15 @@ pub fn updateArSymtab(self: Object, ar_symtab: *Archive.ArSymtab, macho_file: *M } pub fn updateArSize(self: *Object, macho_file: *MachO) !void { + const comp = macho_file.base.comp; + const io = comp.io; self.output_ar_state.size = if (self.in_archive) |ar| ar.size else size: { const file = macho_file.getFileHandle(self.file_handle); - break :size (try file.stat()).size; + break :size (try file.stat(io)).size; }; } -pub fn writeAr(self: Object, ar_format: Archive.Format, macho_file: *MachO, writer: anytype) !void { +pub fn writeAr(self: Object, ar_format: Archive.Format, macho_file: *MachO, writer: *Writer) !void { // Header const size = try macho_file.cast(usize, self.output_ar_state.size); const basename = std.fs.path.basename(self.path); @@ -1703,10 +1746,12 @@ pub fn writeAr(self: Object, ar_format: Archive.Format, macho_file: *MachO, writ // Data const file = macho_file.getFileHandle(self.file_handle); // TODO try using copyRangeAll - const gpa = macho_file.base.comp.gpa; + const comp = macho_file.base.comp; + const io = comp.io; + const gpa = comp.gpa; const data = try gpa.alloc(u8, size); defer gpa.free(data); - const amt = try file.preadAll(data, self.offset); + const amt = try file.readPositionalAll(io, data, self.offset); if (amt != size) return error.InputOutput; try writer.writeAll(data); } @@ -1811,7 +1856,9 @@ pub fn writeAtoms(self: *Object, macho_file: *MachO) !void { const tracy = trace(@src()); defer tracy.end(); - const gpa = macho_file.base.comp.gpa; + const comp = macho_file.base.comp; + const io = comp.io; + const gpa = comp.gpa; const headers = self.sections.items(.header); const sections_data = try gpa.alloc([]const u8, headers.len); defer { @@ -1827,7 +1874,7 @@ pub fn writeAtoms(self: *Object, macho_file: *MachO) !void { if (header.isZerofill()) continue; const size = try macho_file.cast(usize, header.size); const data = try gpa.alloc(u8, size); - const amt = try file.preadAll(data, header.offset + self.offset); + const amt = try file.readPositionalAll(io, data, header.offset + self.offset); if (amt != data.len) return error.InputOutput; sections_data[n_sect] = data; } @@ -1850,7 +1897,9 @@ pub fn writeAtomsRelocatable(self: *Object, macho_file: *MachO) !void { const tracy = trace(@src()); defer tracy.end(); - const gpa = macho_file.base.comp.gpa; + const comp = macho_file.base.comp; + const io = comp.io; + const gpa = comp.gpa; const headers = self.sections.items(.header); const sections_data = try gpa.alloc([]const u8, headers.len); defer { @@ -1866,7 +1915,7 @@ pub fn writeAtomsRelocatable(self: *Object, macho_file: *MachO) !void { if (header.isZerofill()) continue; const size = try macho_file.cast(usize, header.size); const data = try gpa.alloc(u8, size); - const amt = try file.preadAll(data, header.offset + self.offset); + const amt = try file.readPositionalAll(io, data, header.offset + self.offset); if (amt != data.len) return error.InputOutput; sections_data[n_sect] = data; } @@ -2482,11 +2531,11 @@ pub fn getUnwindRecord(self: *Object, index: UnwindInfo.Record.Index) *UnwindInf } /// Caller owns the memory. -pub fn readSectionData(self: Object, allocator: Allocator, file: File.Handle, n_sect: u8) ![]u8 { +pub fn readSectionData(self: Object, allocator: Allocator, io: Io, file: File.Handle, n_sect: u8) ![]u8 { const header = self.sections.items(.header)[n_sect]; const size = math.cast(usize, header.size) orelse return error.Overflow; const data = try allocator.alloc(u8, size); - const amt = try file.preadAll(data, header.offset + self.offset); + const amt = try file.readPositionalAll(io, data, header.offset + self.offset); errdefer allocator.free(data); if (amt != data.len) return error.InputOutput; return data; @@ -2710,15 +2759,17 @@ const x86_64 = struct { handle: File.Handle, macho_file: *MachO, ) !void { - const gpa = macho_file.base.comp.gpa; + const comp = macho_file.base.comp; + const io = comp.io; + const gpa = comp.gpa; const relocs_buffer = try gpa.alloc(u8, sect.nreloc * @sizeOf(macho.relocation_info)); defer gpa.free(relocs_buffer); - const amt = try handle.preadAll(relocs_buffer, sect.reloff + self.offset); + const amt = try handle.readPositionalAll(io, relocs_buffer, sect.reloff + self.offset); if (amt != relocs_buffer.len) return error.InputOutput; const relocs = @as([*]align(1) const macho.relocation_info, @ptrCast(relocs_buffer.ptr))[0..sect.nreloc]; - const code = try self.readSectionData(gpa, handle, n_sect); + const code = try self.readSectionData(gpa, io, handle, n_sect); defer gpa.free(code); try out.ensureTotalCapacityPrecise(gpa, relocs.len); @@ -2877,15 +2928,17 @@ const aarch64 = struct { handle: File.Handle, macho_file: *MachO, ) !void { - const gpa = macho_file.base.comp.gpa; + const comp = macho_file.base.comp; + const io = comp.io; + const gpa = comp.gpa; const relocs_buffer = try gpa.alloc(u8, sect.nreloc * @sizeOf(macho.relocation_info)); defer gpa.free(relocs_buffer); - const amt = try handle.preadAll(relocs_buffer, sect.reloff + self.offset); + const amt = try handle.readPositionalAll(io, relocs_buffer, sect.reloff + self.offset); if (amt != relocs_buffer.len) return error.InputOutput; const relocs = @as([*]align(1) const macho.relocation_info, @ptrCast(relocs_buffer.ptr))[0..sect.nreloc]; - const code = try self.readSectionData(gpa, handle, n_sect); + const code = try self.readSectionData(gpa, io, handle, n_sect); defer gpa.free(code); try out.ensureTotalCapacityPrecise(gpa, relocs.len); @@ -3061,27 +3114,3 @@ const aarch64 = struct { } } }; - -const std = @import("std"); -const assert = std.debug.assert; -const log = std.log.scoped(.link); -const macho = std.macho; -const math = std.math; -const mem = std.mem; -const Allocator = std.mem.Allocator; -const Writer = std.Io.Writer; - -const eh_frame = @import("eh_frame.zig"); -const trace = @import("../../tracy.zig").trace; -const Archive = @import("Archive.zig"); -const Atom = @import("Atom.zig"); -const Cie = eh_frame.Cie; -const Dwarf = @import("Dwarf.zig"); -const Fde = eh_frame.Fde; -const File = @import("file.zig").File; -const LoadCommandIterator = macho.LoadCommandIterator; -const MachO = @import("../MachO.zig"); -const Object = @This(); -const Relocation = @import("Relocation.zig"); -const Symbol = @import("Symbol.zig"); -const UnwindInfo = @import("UnwindInfo.zig"); diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index 5a4ea657906e..49555c2746a4 100644 --- a/src/link/MachO/ZigObject.zig +++ b/src/link/MachO/ZigObject.zig @@ -171,6 +171,9 @@ pub fn getAtomData(self: ZigObject, macho_file: *MachO, atom: Atom, buffer: []u8 const isec = atom.getInputSection(macho_file); assert(!isec.isZerofill()); + const comp = macho_file.base.comp; + const io = comp.io; + switch (isec.type()) { macho.S_THREAD_LOCAL_REGULAR => { const tlv = self.tlv_initializers.get(atom.atom_index).?; @@ -182,7 +185,7 @@ pub fn getAtomData(self: ZigObject, macho_file: *MachO, atom: Atom, buffer: []u8 else => { const sect = macho_file.sections.items(.header)[atom.out_n_sect]; const file_offset = sect.offset + atom.value; - const amt = try macho_file.base.file.?.preadAll(buffer, file_offset); + const amt = try macho_file.base.file.?.readPositionalAll(io, buffer, file_offset); if (amt != buffer.len) return error.InputOutput; }, } @@ -290,12 +293,14 @@ pub fn dedupLiterals(self: *ZigObject, lp: MachO.LiteralPool, macho_file: *MachO /// We need this so that we can write to an archive. /// TODO implement writing ZigObject data directly to a buffer instead. pub fn readFileContents(self: *ZigObject, macho_file: *MachO) !void { - const diags = &macho_file.base.comp.link_diags; + const comp = macho_file.base.comp; + const gpa = comp.gpa; + const io = comp.io; + const diags = &comp.link_diags; // Size of the output object file is always the offset + size of the strtab const size = macho_file.symtab_cmd.stroff + macho_file.symtab_cmd.strsize; - const gpa = macho_file.base.comp.gpa; try self.data.resize(gpa, size); - const amt = macho_file.base.file.?.preadAll(self.data.items, 0) catch |err| + const amt = macho_file.base.file.?.readPositionalAll(io, self.data.items, 0) catch |err| return diags.fail("failed to read output file: {s}", .{@errorName(err)}); if (amt != size) return diags.fail("unexpected EOF reading from output file", .{}); @@ -945,6 +950,8 @@ fn updateNavCode( ) link.File.UpdateNavError!void { const zcu = pt.zcu; const gpa = zcu.gpa; + const comp = zcu.comp; + const io = comp.io; const ip = &zcu.intern_pool; const nav = ip.getNav(nav_index); @@ -1012,8 +1019,8 @@ fn updateNavCode( if (!sect.isZerofill()) { const file_offset = sect.offset + atom.value; - macho_file.base.file.?.pwriteAll(code, file_offset) catch |err| - return macho_file.base.cgFail(nav_index, "failed to write output file: {s}", .{@errorName(err)}); + macho_file.base.file.?.writePositionalAll(io, code, file_offset) catch |err| + return macho_file.base.cgFail(nav_index, "failed to write output file: {t}", .{err}); } } @@ -1493,7 +1500,7 @@ fn writeTrampoline(tr_sym: Symbol, target: Symbol, macho_file: *MachO) !void { .x86_64 => try x86_64.writeTrampolineCode(source_addr, target_addr, &buf), else => @panic("TODO implement write trampoline for this CPU arch"), }; - try macho_file.base.file.?.pwriteAll(out, fileoff); + return macho_file.pwriteAll(out, fileoff); } pub fn getOrCreateMetadataForNav( diff --git a/src/link/MachO/fat.zig b/src/link/MachO/fat.zig index 7772f7a4de89..73b9c626e83d 100644 --- a/src/link/MachO/fat.zig +++ b/src/link/MachO/fat.zig @@ -1,20 +1,22 @@ +const builtin = @import("builtin"); +const native_endian = builtin.target.cpu.arch.endian(); + const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; -const builtin = @import("builtin"); const log = std.log.scoped(.macho); const macho = std.macho; const mem = std.mem; -const native_endian = builtin.target.cpu.arch.endian(); const MachO = @import("../MachO.zig"); -pub fn readFatHeader(file: std.fs.File) !macho.fat_header { - return readFatHeaderGeneric(macho.fat_header, file, 0); +pub fn readFatHeader(io: Io, file: Io.File) !macho.fat_header { + return readFatHeaderGeneric(io, macho.fat_header, file, 0); } -fn readFatHeaderGeneric(comptime Hdr: type, file: std.fs.File, offset: usize) !Hdr { +fn readFatHeaderGeneric(io: Io, comptime Hdr: type, file: Io.File, offset: usize) !Hdr { var buffer: [@sizeOf(Hdr)]u8 = undefined; - const nread = try file.preadAll(&buffer, offset); + const nread = try file.readPositionalAll(io, &buffer, offset); if (nread != buffer.len) return error.InputOutput; var hdr = @as(*align(1) const Hdr, @ptrCast(&buffer)).*; mem.byteSwapAllFields(Hdr, &hdr); @@ -27,12 +29,12 @@ pub const Arch = struct { size: u32, }; -pub fn parseArchs(file: std.fs.File, fat_header: macho.fat_header, out: *[2]Arch) ![]const Arch { +pub fn parseArchs(io: Io, file: Io.File, fat_header: macho.fat_header, out: *[2]Arch) ![]const Arch { var count: usize = 0; var fat_arch_index: u32 = 0; while (fat_arch_index < fat_header.nfat_arch and count < out.len) : (fat_arch_index += 1) { const offset = @sizeOf(macho.fat_header) + @sizeOf(macho.fat_arch) * fat_arch_index; - const fat_arch = try readFatHeaderGeneric(macho.fat_arch, file, offset); + const fat_arch = try readFatHeaderGeneric(io, macho.fat_arch, file, offset); // If we come across an architecture that we do not know how to handle, that's // fine because we can keep looking for one that might match. const arch: std.Target.Cpu.Arch = switch (fat_arch.cputype) { diff --git a/src/link/MachO/file.zig b/src/link/MachO/file.zig index ca3e1c0e8236..cd687a4941b2 100644 --- a/src/link/MachO/file.zig +++ b/src/link/MachO/file.zig @@ -242,6 +242,7 @@ pub const File = union(enum) { const tracy = trace(@src()); defer tracy.end(); + const io = macho_file.base.comp.io; const gpa = macho_file.base.comp.gpa; for (file.getSymbols(), file.getNlists(), 0..) |sym, nlist, i| { @@ -252,8 +253,8 @@ pub const File = union(enum) { const ref_file = ref.getFile(macho_file) orelse continue; if (ref_file.getIndex() == file.getIndex()) continue; - macho_file.dupes_mutex.lock(); - defer macho_file.dupes_mutex.unlock(); + macho_file.dupes_mutex.lockUncancelable(io); + defer macho_file.dupes_mutex.unlock(io); const gop = try macho_file.dupes.getOrPut(gpa, file.getGlobals()[i]); if (!gop.found_existing) { @@ -354,11 +355,12 @@ pub const File = union(enum) { dylib: Dylib, }; - pub const Handle = std.fs.File; + pub const Handle = Io.File; pub const HandleIndex = Index; }; const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; const log = std.log.scoped(.link); const macho = std.macho; diff --git a/src/link/MachO/hasher.zig b/src/link/MachO/hasher.zig index f10a2fe8cfe7..209f9495e81a 100644 --- a/src/link/MachO/hasher.zig +++ b/src/link/MachO/hasher.zig @@ -1,34 +1,36 @@ +const std = @import("std"); +const Io = std.Io; +const assert = std.debug.assert; +const Allocator = std.mem.Allocator; + +const trace = @import("../../tracy.zig").trace; + pub fn ParallelHasher(comptime Hasher: type) type { const hash_size = Hasher.digest_length; return struct { - allocator: Allocator, - thread_pool: *ThreadPool, - - pub fn hash(self: Self, file: fs.File, out: [][hash_size]u8, opts: struct { + pub fn hash(gpa: Allocator, io: Io, file: Io.File, out: [][hash_size]u8, opts: struct { chunk_size: u64 = 0x4000, max_file_size: ?u64 = null, }) !void { const tracy = trace(@src()); defer tracy.end(); - var wg: WaitGroup = .{}; - const file_size = blk: { - const file_size = opts.max_file_size orelse try file.getEndPos(); + const file_size = opts.max_file_size orelse try file.length(io); break :blk std.math.cast(usize, file_size) orelse return error.Overflow; }; const chunk_size = std.math.cast(usize, opts.chunk_size) orelse return error.Overflow; - const buffer = try self.allocator.alloc(u8, chunk_size * out.len); - defer self.allocator.free(buffer); + const buffer = try gpa.alloc(u8, chunk_size * out.len); + defer gpa.free(buffer); - const results = try self.allocator.alloc(fs.File.PReadError!usize, out.len); - defer self.allocator.free(results); + const results = try gpa.alloc(Io.File.ReadPositionalError!usize, out.len); + defer gpa.free(results); { - wg.reset(); - defer wg.wait(); + var group: Io.Group = .init; + defer group.cancel(io); for (out, results, 0..) |*out_buf, *result, i| { const fstart = i * chunk_size; @@ -36,7 +38,8 @@ pub fn ParallelHasher(comptime Hasher: type) type { file_size - fstart else chunk_size; - self.thread_pool.spawnWg(&wg, worker, .{ + group.async(io, worker, .{ + io, file, fstart, buffer[fstart..][0..fsize], @@ -44,33 +47,22 @@ pub fn ParallelHasher(comptime Hasher: type) type { &(result.*), }); } + + try group.await(io); } for (results) |result| _ = try result; } fn worker( - file: fs.File, + io: Io, + file: Io.File, fstart: usize, buffer: []u8, out: *[hash_size]u8, - err: *fs.File.PReadError!usize, + err: *Io.File.ReadPositionalError!usize, ) void { - const tracy = trace(@src()); - defer tracy.end(); - err.* = file.preadAll(buffer, fstart); + err.* = file.readPositionalAll(io, buffer, fstart); Hasher.hash(buffer, out, .{}); } - - const Self = @This(); }; } - -const assert = std.debug.assert; -const fs = std.fs; -const mem = std.mem; -const std = @import("std"); -const trace = @import("../../tracy.zig").trace; - -const Allocator = mem.Allocator; -const ThreadPool = std.Thread.Pool; -const WaitGroup = std.Thread.WaitGroup; diff --git a/src/link/MachO/relocatable.zig b/src/link/MachO/relocatable.zig index 09807a28458c..13dd35a55810 100644 --- a/src/link/MachO/relocatable.zig +++ b/src/link/MachO/relocatable.zig @@ -1,6 +1,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Path) link.File.FlushError!void { - const gpa = macho_file.base.comp.gpa; - const diags = &macho_file.base.comp.link_diags; + const gpa = comp.gpa; + const io = comp.io; + const diags = &comp.link_diags; // TODO: "positional arguments" is a CLI concept, not a linker concept. Delete this unnecessary array list. var positionals = std.array_list.Managed(link.Input).init(gpa); @@ -9,24 +10,22 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat positionals.appendSliceAssumeCapacity(comp.link_inputs); for (comp.c_object_table.keys()) |key| { - try positionals.append(try link.openObjectInput(diags, key.status.success.object_path)); + try positionals.append(try link.openObjectInput(io, diags, key.status.success.object_path)); } - if (module_obj_path) |path| try positionals.append(try link.openObjectInput(diags, path)); + if (module_obj_path) |path| try positionals.append(try link.openObjectInput(io, diags, path)); if (macho_file.getZigObject() == null and positionals.items.len == 1) { // Instead of invoking a full-blown `-r` mode on the input which sadly will strip all // debug info segments/sections (this is apparently by design by Apple), we copy // the *only* input file over. const path = positionals.items[0].path().?; - const in_file = path.root_dir.handle.openFile(path.sub_path, .{}) catch |err| + const in_file = path.root_dir.handle.openFile(io, path.sub_path, .{}) catch |err| return diags.fail("failed to open {f}: {s}", .{ path, @errorName(err) }); - const stat = in_file.stat() catch |err| + const stat = in_file.stat(io) catch |err| return diags.fail("failed to stat {f}: {s}", .{ path, @errorName(err) }); - const amt = in_file.copyRangeAll(0, macho_file.base.file.?, 0, stat.size) catch |err| - return diags.fail("failed to copy range of file {f}: {s}", .{ path, @errorName(err) }); - if (amt != stat.size) - return diags.fail("unexpected short write in copy range of file {f}", .{path}); + link.File.copyRangeAll2(io, in_file, macho_file.base.file.?, 0, 0, stat.size) catch |err| + return diags.fail("failed to copy range of file {f}: {t}", .{ path, err }); return; } @@ -79,6 +78,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Path) link.File.FlushError!void { const gpa = comp.gpa; + const io = comp.io; const diags = &macho_file.base.comp.link_diags; var positionals = std.array_list.Managed(link.Input).init(gpa); @@ -88,17 +88,17 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ? positionals.appendSliceAssumeCapacity(comp.link_inputs); for (comp.c_object_table.keys()) |key| { - try positionals.append(try link.openObjectInput(diags, key.status.success.object_path)); + try positionals.append(try link.openObjectInput(io, diags, key.status.success.object_path)); } - if (module_obj_path) |path| try positionals.append(try link.openObjectInput(diags, path)); + if (module_obj_path) |path| try positionals.append(try link.openObjectInput(io, diags, path)); if (comp.compiler_rt_strat == .obj) { - try positionals.append(try link.openObjectInput(diags, comp.compiler_rt_obj.?.full_object_path)); + try positionals.append(try link.openObjectInput(io, diags, comp.compiler_rt_obj.?.full_object_path)); } if (comp.ubsan_rt_strat == .obj) { - try positionals.append(try link.openObjectInput(diags, comp.ubsan_rt_obj.?.full_object_path)); + try positionals.append(try link.openObjectInput(io, diags, comp.ubsan_rt_obj.?.full_object_path)); } for (positionals.items) |link_input| { @@ -229,7 +229,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ? assert(writer.end == total_size); - try macho_file.setEndPos(total_size); + try macho_file.setLength(total_size); try macho_file.pwriteAll(writer.buffered(), 0); if (diags.hasErrors()) return error.LinkFailure; @@ -773,7 +773,6 @@ fn writeHeader(macho_file: *MachO, ncmds: usize, sizeofcmds: usize) !void { const std = @import("std"); const Path = std.Build.Cache.Path; -const WaitGroup = std.Thread.WaitGroup; const assert = std.debug.assert; const log = std.log.scoped(.link); const macho = std.macho; diff --git a/src/link/MachO/uuid.zig b/src/link/MachO/uuid.zig index 565ae80b2274..a75799d01ec4 100644 --- a/src/link/MachO/uuid.zig +++ b/src/link/MachO/uuid.zig @@ -1,28 +1,38 @@ +const std = @import("std"); +const Io = std.Io; +const Md5 = std.crypto.hash.Md5; + +const trace = @import("../../tracy.zig").trace; +const Compilation = @import("../../Compilation.zig"); +const ParallelHasher = @import("hasher.zig").ParallelHasher; + /// Calculates Md5 hash of each chunk in parallel and then hashes all Md5 hashes to produce /// the final digest. /// While this is NOT a correct MD5 hash of the contents, this methodology is used by LLVM/LLD /// and we will use it too as it seems accepted by Apple OSes. /// TODO LLD also hashes the output filename to disambiguate between same builds with different /// output files. Should we also do that? -pub fn calcUuid(comp: *const Compilation, file: fs.File, file_size: u64, out: *[Md5.digest_length]u8) !void { +pub fn calcUuid(comp: *const Compilation, file: Io.File, file_size: u64, out: *[Md5.digest_length]u8) !void { const tracy = trace(@src()); defer tracy.end(); + const gpa = comp.gpa; + const io = comp.io; + const chunk_size: usize = 1024 * 1024; const num_chunks: usize = std.math.cast(usize, @divTrunc(file_size, chunk_size)) orelse return error.Overflow; const actual_num_chunks = if (@rem(file_size, chunk_size) > 0) num_chunks + 1 else num_chunks; - const hashes = try comp.gpa.alloc([Md5.digest_length]u8, actual_num_chunks); - defer comp.gpa.free(hashes); + const hashes = try gpa.alloc([Md5.digest_length]u8, actual_num_chunks); + defer gpa.free(hashes); - var hasher = Hasher(Md5){ .allocator = comp.gpa, .thread_pool = comp.thread_pool }; - try hasher.hash(file, hashes, .{ + try ParallelHasher(Md5).hash(gpa, io, file, hashes, .{ .chunk_size = chunk_size, .max_file_size = file_size, }); - const final_buffer = try comp.gpa.alloc(u8, actual_num_chunks * Md5.digest_length); - defer comp.gpa.free(final_buffer); + const final_buffer = try gpa.alloc(u8, actual_num_chunks * Md5.digest_length); + defer gpa.free(final_buffer); for (hashes, 0..) |hash, i| { @memcpy(final_buffer[i * Md5.digest_length ..][0..Md5.digest_length], &hash); @@ -37,13 +47,3 @@ inline fn conform(out: *[Md5.digest_length]u8) void { out[6] = (out[6] & 0x0F) | (3 << 4); out[8] = (out[8] & 0x3F) | 0x80; } - -const fs = std.fs; -const mem = std.mem; -const std = @import("std"); -const trace = @import("../../tracy.zig").trace; - -const Compilation = @import("../../Compilation.zig"); -const Md5 = std.crypto.hash.Md5; -const Hasher = @import("hasher.zig").ParallelHasher; -const ThreadPool = std.Thread.Pool; diff --git a/src/link/MappedFile.zig b/src/link/MappedFile.zig index e189a1df9444..2986e27e242d 100644 --- a/src/link/MappedFile.zig +++ b/src/link/MappedFile.zig @@ -1,3 +1,17 @@ +/// TODO add a mapped file abstraction to std.Io +const MappedFile = @This(); + +const builtin = @import("builtin"); +const is_linux = builtin.os.tag == .linux; +const is_windows = builtin.os.tag == .windows; + +const std = @import("std"); +const Io = std.Io; +const assert = std.debug.assert; +const linux = std.os.linux; +const windows = std.os.windows; + +io: Io, file: std.Io.File, flags: packed struct { block_size: std.mem.Alignment, @@ -16,16 +30,22 @@ writers: std.SinglyLinkedList, pub const growth_factor = 4; -pub const Error = std.posix.MMapError || std.posix.MRemapError || std.fs.File.SetEndPosError || error{ +pub const Error = std.posix.MMapError || std.posix.MRemapError || Io.File.LengthError || error{ NotFile, SystemResources, IsDir, Unseekable, NoSpaceLeft, + + InputOutput, + FileTooBig, + FileBusy, + NonResizable, }; -pub fn init(file: std.Io.File, gpa: std.mem.Allocator) !MappedFile { +pub fn init(file: std.Io.File, gpa: std.mem.Allocator, io: Io) !MappedFile { var mf: MappedFile = .{ + .io = io, .file = file, .flags = undefined, .section = if (is_windows) windows.INVALID_HANDLE_VALUE else {}, @@ -54,6 +74,43 @@ pub fn init(file: std.Io.File, gpa: std.mem.Allocator) !MappedFile { }, }; } + if (is_linux) { + const use_c = std.c.versionCheck(if (builtin.abi.isAndroid()) + .{ .major = 30, .minor = 0, .patch = 0 } + else + .{ .major = 2, .minor = 28, .patch = 0 }); + const sys = if (use_c) std.c else std.os.linux; + while (true) { + var statx = std.mem.zeroes(linux.Statx); + const rc = sys.statx( + mf.file.handle, + "", + std.posix.AT.EMPTY_PATH, + .{ .TYPE = true, .SIZE = true, .BLOCKS = true }, + &statx, + ); + switch (sys.errno(rc)) { + .SUCCESS => { + assert(statx.mask.TYPE); + assert(statx.mask.SIZE); + assert(statx.mask.BLOCKS); + if (!std.posix.S.ISREG(statx.mode)) return error.PathAlreadyExists; + break :stat .{ statx.size, @max(std.heap.pageSize(), statx.blksize) }; + }, + .INTR => continue, + .ACCES => return error.AccessDenied, + .BADF => if (std.debug.runtime_safety) unreachable else return error.Unexpected, + .FAULT => if (std.debug.runtime_safety) unreachable else return error.Unexpected, + .INVAL => if (std.debug.runtime_safety) unreachable else return error.Unexpected, + .LOOP => return error.SymLinkLoop, + .NAMETOOLONG => return error.NameTooLong, + .NOENT => return error.FileNotFound, + .NOTDIR => return error.FileNotFound, + .NOMEM => return error.SystemResources, + else => |err| return std.posix.unexpectedErrno(err), + } + } + } const stat = try std.posix.fstat(mf.file.handle); if (!std.posix.S.ISREG(stat.mode)) return error.PathAlreadyExists; break :stat .{ @bitCast(stat.size), @max(std.heap.pageSize(), stat.blksize) }; @@ -419,8 +476,8 @@ pub const Node = extern struct { return n; }, .streaming, - .streaming_reading, - .positional_reading, + .streaming_simple, + .positional_simple, .failure, => { const dest = limit.slice(interface.unusedCapacitySlice()); @@ -598,13 +655,14 @@ pub fn addNodeAfter( } fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested_size: u64) !void { + const io = mf.io; const node = ni.get(mf); const old_offset, const old_size = node.location().resolve(mf); const new_size = node.flags.alignment.forward(@intCast(requested_size)); // Resize the entire file if (ni == Node.Index.root) { try mf.ensureCapacityForSetLocation(gpa); - try std.fs.File.adaptFromNewApi(mf.file).setEndPos(new_size); + try mf.file.setLength(io, new_size); try mf.ensureTotalCapacity(@intCast(new_size)); ni.setLocationAssumeCapacity(mf, old_offset, new_size); return; @@ -953,12 +1011,19 @@ pub fn ensureTotalCapacityPrecise(mf: *MappedFile, new_capacity: usize) !void { if (is_windows) { if (mf.section == windows.INVALID_HANDLE_VALUE) switch (windows.ntdll.NtCreateSection( &mf.section, - windows.STANDARD_RIGHTS_REQUIRED | windows.SECTION_QUERY | - windows.SECTION_MAP_WRITE | windows.SECTION_MAP_READ | windows.SECTION_EXTEND_SIZE, + .{ + .SPECIFIC = .{ .SECTION = .{ + .QUERY = true, + .MAP_WRITE = true, + .MAP_READ = true, + .EXTEND_SIZE = true, + } }, + .STANDARD = .{ .RIGHTS = .REQUIRED }, + }, null, @constCast(&@as(i64, @intCast(aligned_capacity))), - windows.PAGE_READWRITE, - windows.SEC_COMMIT, + .{ .READWRITE = true }, + .{ .COMMIT = true }, mf.file.handle, )) { .SUCCESS => {}, @@ -974,9 +1039,9 @@ pub fn ensureTotalCapacityPrecise(mf: *MappedFile, new_capacity: usize) !void { 0, null, &contents_len, - .ViewUnmap, - 0, - windows.PAGE_READWRITE, + .Unmap, + .{}, + .{ .READWRITE = true }, )) { .SUCCESS => mf.contents = contents_ptr.?[0..contents_len], else => return error.MemoryMappingNotSupported, @@ -1038,12 +1103,3 @@ fn verifyNode(mf: *MappedFile, parent_ni: Node.Index) void { ni = node.next; } } - -const assert = std.debug.assert; -const builtin = @import("builtin"); -const is_linux = builtin.os.tag == .linux; -const is_windows = builtin.os.tag == .windows; -const linux = std.os.linux; -const MappedFile = @This(); -const std = @import("std"); -const windows = std.os.windows; diff --git a/src/link/Queue.zig b/src/link/Queue.zig index 742b4664f178..b716800baebe 100644 --- a/src/link/Queue.zig +++ b/src/link/Queue.zig @@ -1,254 +1,172 @@ //! Stores and manages the queue of link tasks. Each task is either a `PrelinkTask` or a `ZcuTask`. //! -//! There must be at most one link thread (the thread processing these tasks) active at a time. If -//! `!comp.separateCodegenThreadOk()`, then ZCU tasks will be run on the main thread, bypassing this -//! queue entirely. +//! There are two `std.Io.Queue`s, for prelink and ZCU tasks respectively. The compiler writes tasks +//! to these queues, and a single concurrent linker task receives and processes them. `Compilation` +//! is responsible for calling `finishPrelinkQueue` and `finishZcuQueue` once all relevant tasks +//! have been queued. All prelink tasks must be queued and completed before any ZCU tasks can be +//! processed. //! -//! All prelink tasks must be processed before any ZCU tasks are processed. After all prelink tasks -//! are run, but before any ZCU tasks are run, `prelink` must be called on the `link.File`. +//! If concurrency is unavailable, the `enqueuePrelink` and `enqueueZcu` functions will instead run +//! the given tasks immediately---the queues are unused. //! -//! There will sometimes be a `ZcuTask` in the queue which is not yet ready because it depends on -//! MIR which has not yet been generated by any codegen thread. In this case, we must pause -//! processing of linker tasks until the MIR is ready. It would be incorrect to run any other link -//! tasks first, since this would make builds unreproducible. +//! If the codegen backend does not permit concurrency, then `Compilation` will call `finishZcuQueue` +//! early so that the concurrent linker task exists after prelink and ZCU tasks will run +//! non-concurrently in `enqueueZcu`. -mutex: std.Thread.Mutex, -/// Validates that only one `flushTaskQueue` thread is running at a time. -flush_safety: std.debug.SafetyLock, +/// This is the concurrent call to `runLinkTasks`. It may be set to non-`null` in `start`, and is +/// set to `null` by the main thread after it is canceled. It is not otherwise modified; as such, it +/// may be checked non-atomically. If a task is being queued and this is `null`, tasks must be run +/// eagerly. +future: ?std.Io.Future(void), -/// This value is positive while there are still prelink tasks yet to be queued. Once they are -/// all queued, this value becomes 0, and ZCU tasks can be run. Guarded by `mutex`. -prelink_wait_count: u32, +/// This is only used if `future == null` during prelink. In that case, it is used to ensure that +/// only one prelink task is run at a time. +prelink_mutex: std.Io.Mutex, -/// Prelink tasks which have been enqueued and are not yet owned by the worker thread. -/// Allocated into `gpa`, guarded by `mutex`. -queued_prelink: std.ArrayList(PrelinkTask), -/// The worker thread moves items from `queued_prelink` into this array in order to process them. -/// Allocated into `gpa`, accessed only by the worker thread. -wip_prelink: std.ArrayList(PrelinkTask), +/// Only valid if `future != null`. +prelink_queue: std.Io.Queue(PrelinkTask), +/// Only valid if `future != null`. +zcu_queue: std.Io.Queue(ZcuTask), -/// Like `queued_prelink`, but for ZCU tasks. -/// Allocated into `gpa`, guarded by `mutex`. -queued_zcu: std.ArrayList(ZcuTask), -/// Like `wip_prelink`, but for ZCU tasks. -/// Allocated into `gpa`, accessed only by the worker thread. -wip_zcu: std.ArrayList(ZcuTask), - -/// When processing ZCU link tasks, we might have to block due to unpopulated MIR. When this -/// happens, some tasks in `wip_zcu` have been run, and some are still pending. This is the -/// index into `wip_zcu` which we have reached. -wip_zcu_idx: usize, - -/// The sum of all `air_bytes` for all currently-queued `ZcuTask.link_func` tasks. Because -/// MIR bytes are approximately proportional to AIR bytes, this acts to limit the amount of -/// AIR and MIR which is queued for codegen and link respectively, to prevent excessive -/// memory usage if analysis produces AIR faster than it can be processed by codegen/link. -/// The cap is `max_air_bytes_in_flight`. -/// Guarded by `mutex`. -air_bytes_in_flight: u32, -/// If nonzero, then a call to `enqueueZcu` is blocked waiting to add a `link_func` task, but -/// cannot until `air_bytes_in_flight` is no greater than this value. -/// Guarded by `mutex`. -air_bytes_waiting: u32, -/// After setting `air_bytes_waiting`, `enqueueZcu` will wait on this condition (with `mutex`). -/// When `air_bytes_waiting` many bytes can be queued, this condition should be signaled. -air_bytes_cond: std.Thread.Condition, - -/// Guarded by `mutex`. -state: union(enum) { - /// The link thread is currently running or queued to run. - running, - /// The link thread is not running or queued, because it has exhausted all immediately available - /// tasks. It should be spawned when more tasks are enqueued. If `prelink_wait_count` is not - /// zero, we are specifically waiting for prelink tasks. - finished, - /// The link thread is not running or queued, because it is waiting for this MIR to be populated. - /// Once codegen completes, it must call `mirReady` which will restart the link thread. - wait_for_mir: InternPool.Index, -}, - -/// In the worst observed case, MIR is around 50 times as large as AIR. More typically, the ratio is -/// around 20. Going by that 50x multiplier, and assuming we want to consume no more than 500 MiB of -/// memory on AIR/MIR, we see a limit of around 10 MiB of AIR in-flight. -const max_air_bytes_in_flight = 10 * 1024 * 1024; +/// The capacity of the task queue buffers. +pub const buffer_size = 512; /// The initial `Queue` state, containing no tasks, expecting no prelink tasks, and with no running worker thread. /// The `queued_prelink` field may be appended to before calling `start`. pub const empty: Queue = .{ - .mutex = .{}, - .flush_safety = .{}, - .prelink_wait_count = undefined, // set in `start` - .queued_prelink = .empty, - .wip_prelink = .empty, - .queued_zcu = .empty, - .wip_zcu = .empty, - .wip_zcu_idx = 0, - .state = .finished, - .air_bytes_in_flight = 0, - .air_bytes_waiting = 0, - .air_bytes_cond = .{}, + .future = null, + .prelink_mutex = .init, + .prelink_queue = undefined, // set in `start` if needed + .zcu_queue = undefined, // set in `start` if needed }; -/// `lf` is needed to correctly deinit any pending `ZcuTask`s. -pub fn deinit(q: *Queue, comp: *Compilation) void { - const gpa = comp.gpa; - for (q.queued_zcu.items) |t| t.deinit(comp.zcu.?); - for (q.wip_zcu.items[q.wip_zcu_idx..]) |t| t.deinit(comp.zcu.?); - q.queued_prelink.deinit(gpa); - q.wip_prelink.deinit(gpa); - q.queued_zcu.deinit(gpa); - q.wip_zcu.deinit(gpa); + +pub fn cancel(q: *Queue, io: Io) void { + if (q.future) |*f| { + f.cancel(io); + q.future = null; + } +} + +pub fn wait(q: *Queue, io: Io) void { + if (q.future) |*f| { + f.await(io); + q.future = null; + } } /// This is expected to be called exactly once, after which the caller must not directly access /// `queued_prelink` any longer. This will spawn the link thread if necessary. -pub fn start(q: *Queue, comp: *Compilation) void { - assert(q.state == .finished); - assert(q.queued_zcu.items.len == 0); - // Reset this to 1. We can't init it to 1 in `empty`, because it would fall to 0 on successive - // incremental updates, but we still need the initial 1. - q.prelink_wait_count = 1; - if (q.queued_prelink.items.len != 0) { - q.state = .running; - comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp }); +pub fn start( + q: *Queue, + comp: *Compilation, + arena: Allocator, +) Allocator.Error!void { + assert(q.future == null); + q.prelink_queue = .init(try arena.alloc(PrelinkTask, buffer_size)); + q.zcu_queue = .init(try arena.alloc(ZcuTask, buffer_size)); + if (comp.io.concurrent(runLinkTasks, .{ q, comp })) |future| { + // We will run link tasks concurrently. + q.future = future; + } else |err| switch (err) { + error.ConcurrencyUnavailable => { + // We will run link tasks on the main thread. + q.prelink_queue = undefined; + q.zcu_queue = undefined; + }, } } -/// Every call to this must be paired with a call to `finishPrelinkItem`. -pub fn startPrelinkItem(q: *Queue) void { - q.mutex.lock(); - defer q.mutex.unlock(); - assert(q.prelink_wait_count > 0); // must not have finished everything already - q.prelink_wait_count += 1; -} -/// This function must be called exactly one more time than `startPrelinkItem` is. The final call -/// indicates that we have finished calling `startPrelinkItem`, so once all pending items finish, -/// we are ready to move on to ZCU tasks. -pub fn finishPrelinkItem(q: *Queue, comp: *Compilation) void { - { - q.mutex.lock(); - defer q.mutex.unlock(); - q.prelink_wait_count -= 1; - if (q.prelink_wait_count != 0) return; - // The prelink task count dropped to 0; restart the linker thread if necessary. - switch (q.state) { - .wait_for_mir => unreachable, // we've not started zcu tasks yet - .running => return, - .finished => {}, - } - assert(q.queued_prelink.items.len == 0); - // Even if there are no ZCU tasks, we must restart the linker thread to make sure - // that `link.File.prelink()` is called. - q.state = .running; +/// Enqueues all prelink tasks in `tasks`. Asserts that they were expected, i.e. that +/// the queue is not yet closed. Also asserts that `tasks.len` is not 0. +pub fn enqueuePrelink(q: *Queue, comp: *Compilation, tasks: []const PrelinkTask) Io.Cancelable!void { + const io = comp.io; + + if (q.future != null) { + q.prelink_queue.putAll(io, tasks) catch |err| switch (err) { + error.Canceled => |e| return e, + error.Closed => unreachable, + }; + } else { + try q.prelink_mutex.lock(io); + defer q.prelink_mutex.unlock(io); + for (tasks) |task| link.doPrelinkTask(comp, task); } - comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp }); } -/// Called by codegen workers after they have populated a `ZcuTask.LinkFunc.SharedMir`. If the link -/// thread was waiting for this MIR, it can resume. -pub fn mirReady(q: *Queue, comp: *Compilation, func_index: InternPool.Index, mir: *ZcuTask.LinkFunc.SharedMir) void { - // We would like to assert that `mir` is not pending, but that would race with a worker thread - // potentially freeing it. - { - q.mutex.lock(); - defer q.mutex.unlock(); - switch (q.state) { - .finished, .running => return, - .wait_for_mir => |wait_for| if (wait_for != func_index) return, +pub fn enqueueZcu( + q: *Queue, + comp: *Compilation, + tid: usize, + task: ZcuTask, +) Io.Cancelable!void { + const io = comp.io; + + assert(tid == 0); + + if (q.future != null) { + if (q.zcu_queue.putOne(io, task)) |_| { + return; + } else |err| switch (err) { + error.Canceled => |e| return e, + error.Closed => { + // The linker is still processing prelink tasks. Wait for those + // to finish, after which the linker task will exist, and ZCU + // tasks will be run non-concurrently. This logic exists for + // backends which do not support `Zcu.Feature.separate_thread`. + q.wait(io); + }, } - // We were waiting for `mir`, so we will restart the linker thread. - q.state = .running; } - assert(mir.status.load(.acquire) != .pending); - comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp }); + + link.doZcuTask(comp, tid, task); } -/// Enqueues all prelink tasks in `tasks`. Asserts that they were expected, i.e. that -/// `prelink_wait_count` is not yet 0. Also asserts that `tasks.len` is not 0. -pub fn enqueuePrelink(q: *Queue, comp: *Compilation, tasks: []const PrelinkTask) Allocator.Error!void { - { - q.mutex.lock(); - defer q.mutex.unlock(); - assert(q.prelink_wait_count > 0); - try q.queued_prelink.appendSlice(comp.gpa, tasks); - switch (q.state) { - .wait_for_mir => unreachable, // we've not started zcu tasks yet - .running => return, - .finished => {}, +pub fn finishPrelinkQueue(q: *Queue, comp: *Compilation) Io.Cancelable!void { + if (q.future != null) { + q.prelink_queue.close(comp.io); + return; + } + // If linking non-concurrently, we must run prelink. + prelink: { + const lf = comp.bin_file orelse break :prelink; + if (lf.post_prelink) break :prelink; + + if (lf.prelink()) |_| { + lf.post_prelink = true; + } else |err| switch (err) { + error.OutOfMemory => comp.link_diags.setAllocFailure(), + error.LinkFailure => {}, + error.Canceled => |e| return e, } - // Restart the linker thread, because it was waiting for a task - q.state = .running; } - comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp }); } -pub fn enqueueZcu(q: *Queue, comp: *Compilation, task: ZcuTask) Allocator.Error!void { - assert(comp.separateCodegenThreadOk()); - { - q.mutex.lock(); - defer q.mutex.unlock(); - // If this is a `link_func` task, we might need to wait for `air_bytes_in_flight` to fall. - if (task == .link_func) { - const max_in_flight = max_air_bytes_in_flight -| task.link_func.air_bytes; - while (q.air_bytes_in_flight > max_in_flight) { - q.air_bytes_waiting = task.link_func.air_bytes; - q.air_bytes_cond.wait(&q.mutex); - q.air_bytes_waiting = 0; - } - q.air_bytes_in_flight += task.link_func.air_bytes; - } - try q.queued_zcu.append(comp.gpa, task); - switch (q.state) { - .running, .wait_for_mir => return, - .finished => if (q.prelink_wait_count > 0) return, - } - // Restart the linker thread, unless it would immediately be blocked - if (task == .link_func and task.link_func.mir.status.load(.acquire) == .pending) { - q.state = .{ .wait_for_mir = task.link_func.func }; - return; - } - q.state = .running; +pub fn finishZcuQueue(q: *Queue, comp: *Compilation) void { + if (q.future != null) { + q.zcu_queue.close(comp.io); } - comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp }); } -fn flushTaskQueue(tid: usize, q: *Queue, comp: *Compilation) void { - q.flush_safety.lock(); // every `return` site should unlock this before unlocking `q.mutex` - if (std.debug.runtime_safety) { - q.mutex.lock(); - defer q.mutex.unlock(); - assert(q.state == .running); - } +fn runLinkTasks(q: *Queue, comp: *Compilation) void { + const tid = Compilation.getTid(); + const io = comp.io; var have_idle_tasks = true; - prelink: while (true) { - assert(q.wip_prelink.items.len == 0); - swap_queues: while (true) { - { - q.mutex.lock(); - defer q.mutex.unlock(); - std.mem.swap(std.ArrayList(PrelinkTask), &q.queued_prelink, &q.wip_prelink); - if (q.wip_prelink.items.len > 0) break :swap_queues; - if (q.prelink_wait_count == 0) break :prelink; // prelink is done - if (!have_idle_tasks) { - // We're expecting more prelink tasks so can't move on to ZCU tasks. - q.state = .finished; - q.flush_safety.unlock(); - return; - } - } - have_idle_tasks = link.doIdleTask(comp, tid) catch |err| switch (err) { - error.OutOfMemory => have_idle_tasks: { - comp.link_diags.setAllocFailure(); - break :have_idle_tasks false; - }, - error.LinkFailure => false, - }; - } - for (q.wip_prelink.items) |task| { + + prelink_tasks: while (true) { + var task_buf: [128]PrelinkTask = undefined; + const limit: usize = if (have_idle_tasks) 0 else 1; + const n = q.prelink_queue.get(io, &task_buf, limit) catch |err| switch (err) { + error.Canceled => return, + error.Closed => break :prelink_tasks, + }; + if (n == 0) { + assert(have_idle_tasks); + have_idle_tasks = runIdleTask(comp, tid); + } else for (task_buf[0..n]) |task| { link.doPrelinkTask(comp, task); + have_idle_tasks = true; } - have_idle_tasks = true; - q.wip_prelink.clearRetainingCapacity(); } // We've finished the prelink tasks, so run prelink if necessary. @@ -258,84 +176,43 @@ fn flushTaskQueue(tid: usize, q: *Queue, comp: *Compilation) void { lf.post_prelink = true; } else |err| switch (err) { error.OutOfMemory => comp.link_diags.setAllocFailure(), + error.Canceled => @panic("TODO"), error.LinkFailure => {}, } } } - // Now we can run ZCU tasks. - while (true) { - if (q.wip_zcu.items.len == q.wip_zcu_idx) swap_queues: { - q.wip_zcu.clearRetainingCapacity(); - q.wip_zcu_idx = 0; - while (true) { - { - q.mutex.lock(); - defer q.mutex.unlock(); - std.mem.swap(std.ArrayList(ZcuTask), &q.queued_zcu, &q.wip_zcu); - if (q.wip_zcu.items.len > 0) break :swap_queues; - if (!have_idle_tasks) { - // We've exhausted all available tasks. - q.state = .finished; - q.flush_safety.unlock(); - return; - } - } - have_idle_tasks = link.doIdleTask(comp, tid) catch |err| switch (err) { - error.OutOfMemory => have_idle_tasks: { - comp.link_diags.setAllocFailure(); - break :have_idle_tasks false; - }, - error.LinkFailure => false, - }; - } - } - const task = q.wip_zcu.items[q.wip_zcu_idx]; - // If the task is a `link_func`, we might have to stop until its MIR is populated. - pending: { - if (task != .link_func) break :pending; - const status_ptr = &task.link_func.mir.status; - while (true) { - // First check without the mutex to optimize for the common case where MIR is ready. - if (status_ptr.load(.acquire) != .pending) break :pending; - if (have_idle_tasks) have_idle_tasks = link.doIdleTask(comp, tid) catch |err| switch (err) { - error.OutOfMemory => have_idle_tasks: { - comp.link_diags.setAllocFailure(); - break :have_idle_tasks false; - }, - error.LinkFailure => false, - }; - if (!have_idle_tasks) break; - } - q.mutex.lock(); - defer q.mutex.unlock(); - if (status_ptr.load(.acquire) != .pending) break :pending; - // We will stop for now, and get restarted once this MIR is ready. - q.state = .{ .wait_for_mir = task.link_func.func }; - q.flush_safety.unlock(); - return; + zcu_tasks: while (true) { + var task_buf: [128]ZcuTask = undefined; + const limit: usize = if (have_idle_tasks) 0 else 1; + const n = q.zcu_queue.get(io, &task_buf, limit) catch |err| switch (err) { + error.Canceled => return, + error.Closed => break :zcu_tasks, + }; + if (n == 0) { + assert(have_idle_tasks); + have_idle_tasks = runIdleTask(comp, tid); + } else for (task_buf[0..n]) |task| { + link.doZcuTask(comp, tid, task); + have_idle_tasks = true; } - link.doZcuTask(comp, tid, task); - task.deinit(comp.zcu.?); - if (task == .link_func) { - // Decrease `air_bytes_in_flight`, since we've finished processing this MIR. - q.mutex.lock(); - defer q.mutex.unlock(); - q.air_bytes_in_flight -= task.link_func.air_bytes; - if (q.air_bytes_waiting != 0 and - q.air_bytes_in_flight <= max_air_bytes_in_flight -| q.air_bytes_waiting) - { - q.air_bytes_cond.signal(); - } - } - q.wip_zcu_idx += 1; - have_idle_tasks = true; } } +fn runIdleTask(comp: *Compilation, tid: usize) bool { + return link.doIdleTask(comp, tid) catch |err| switch (err) { + error.OutOfMemory => have_more: { + comp.link_diags.setAllocFailure(); + break :have_more false; + }, + error.LinkFailure => false, + }; +} const std = @import("std"); const assert = std.debug.assert; const Allocator = std.mem.Allocator; +const Io = std.Io; + const Compilation = @import("../Compilation.zig"); const InternPool = @import("../InternPool.zig"); const link = @import("../link.zig"); diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig index 7e28dc0a8b0b..4dbdd5c089f8 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -33,6 +33,7 @@ pub fn createEmpty( options: link.File.OpenOptions, ) !*Linker { const gpa = comp.gpa; + const io = comp.io; const target = &comp.root_mod.resolved_target.result; assert(!comp.config.use_lld); // Caught by Compilation.Config.resolve @@ -78,7 +79,7 @@ pub fn createEmpty( }; errdefer linker.deinit(); - linker.base.file = try emit.root_dir.handle.createFile(emit.sub_path, .{ + linker.base.file = try emit.root_dir.handle.createFile(io, emit.sub_path, .{ .truncate = true, .read = true, }); @@ -245,6 +246,7 @@ pub fn flush( const comp = linker.base.comp; const diags = &comp.link_diags; const gpa = comp.gpa; + const io = comp.io; // We need to export the list of error names somewhere so that we can pretty-print them in the // executor. This is not really an important thing though, so we can just dump it in any old @@ -286,8 +288,8 @@ pub fn flush( }; // TODO endianness bug. use file writer and call writeSliceEndian instead - linker.base.file.?.writeAll(@ptrCast(linked_module)) catch |err| - return diags.fail("failed to write: {s}", .{@errorName(err)}); + linker.base.file.?.writeStreamingAll(io, @ptrCast(linked_module)) catch |err| + return diags.fail("failed to write: {t}", .{err}); } fn linkModule(arena: Allocator, module: []Word, progress: std.Progress.Node) ![]Word { diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 3ee6e842de5f..af800d77d263 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -20,6 +20,7 @@ const native_endian = builtin.cpu.arch.endian(); const build_options = @import("build_options"); const std = @import("std"); +const Io = std.Io; const Allocator = std.mem.Allocator; const Cache = std.Build.Cache; const Path = Cache.Path; @@ -428,7 +429,11 @@ pub const OutputFunctionIndex = enum(u32) { pub fn fromSymbolName(wasm: *const Wasm, name: String) OutputFunctionIndex { if (wasm.flush_buffer.function_imports.getIndex(name)) |i| return @enumFromInt(i); - return fromFunctionIndex(wasm, FunctionIndex.fromSymbolName(wasm, name).?); + return fromFunctionIndex(wasm, FunctionIndex.fromSymbolName(wasm, name) orelse { + if (std.debug.runtime_safety) { + std.debug.panic("function index for symbol not found: {s}", .{name.slice(wasm)}); + } else unreachable; + }); } }; @@ -2996,16 +3001,18 @@ pub fn createEmpty( .named => |name| (try wasm.internString(name)).toOptional(), }; - wasm.base.file = try emit.root_dir.handle.createFile(emit.sub_path, .{ + const io = comp.io; + + wasm.base.file = try emit.root_dir.handle.createFile(io, emit.sub_path, .{ .truncate = true, .read = true, - .mode = if (fs.has_executable_bit) + .permissions = if (Io.File.Permissions.has_executable_bit) if (target.os.tag == .wasi and output_mode == .Exe) - fs.File.default_mode | 0b001_000_000 + .executable_file else - fs.File.default_mode + .default_file else - 0, + .default_file, }); wasm.name = emit.sub_path; @@ -3013,14 +3020,16 @@ pub fn createEmpty( } fn openParseObjectReportingFailure(wasm: *Wasm, path: Path) void { - const diags = &wasm.base.comp.link_diags; - const obj = link.openObject(path, false, false) catch |err| { - switch (diags.failParse(path, "failed to open object: {s}", .{@errorName(err)})) { + const comp = wasm.base.comp; + const io = comp.io; + const diags = &comp.link_diags; + const obj = link.openObject(io, path, false, false) catch |err| { + switch (diags.failParse(path, "failed to open object: {t}", .{err})) { error.LinkFailure => return, } }; wasm.parseObject(obj) catch |err| { - switch (diags.failParse(path, "failed to parse object: {s}", .{@errorName(err)})) { + switch (diags.failParse(path, "failed to parse object: {t}", .{err})) { error.LinkFailure => return, } }; @@ -3032,7 +3041,7 @@ fn parseObject(wasm: *Wasm, obj: link.Input.Object) !void { const io = wasm.base.comp.io; const gc_sections = wasm.base.gc_sections; - defer obj.file.close(); + defer obj.file.close(io); var file_reader = obj.file.reader(io, &.{}); @@ -3060,7 +3069,7 @@ fn parseArchive(wasm: *Wasm, obj: link.Input.Object) !void { const io = wasm.base.comp.io; const gc_sections = wasm.base.gc_sections; - defer obj.file.close(); + defer obj.file.close(io); var file_reader = obj.file.reader(io, &.{}); @@ -3393,10 +3402,11 @@ pub fn updateExports( pub fn loadInput(wasm: *Wasm, input: link.Input) !void { const comp = wasm.base.comp; const gpa = comp.gpa; + const io = comp.io; if (comp.verbose_link) { - comp.mutex.lock(); // protect comp.arena - defer comp.mutex.unlock(); + comp.mutex.lockUncancelable(io); // protect comp.arena + defer comp.mutex.unlock(io); const argv = &wasm.dump_argv_list; switch (input) { @@ -3528,7 +3538,10 @@ pub fn markFunctionImport( import: *FunctionImport, func_index: FunctionImport.Index, ) link.File.FlushError!void { - if (import.flags.alive) return; + // import.flags.alive might be already true from a previous update. In such + // case, we must still run the logic in this function, in case the item + // being marked was reverted by the `flush` logic that resets the hash + // table watermarks. import.flags.alive = true; const comp = wasm.base.comp; @@ -3548,8 +3561,9 @@ pub fn markFunctionImport( } else { try wasm.function_imports.put(gpa, name, .fromObject(func_index, wasm)); } - } else { - try markFunction(wasm, import.resolution.unpack(wasm).object_function, import.flags.exported); + } else switch (import.resolution.unpack(wasm)) { + .object_function => try markFunction(wasm, import.resolution.unpack(wasm).object_function, import.flags.exported), + else => return, } } @@ -3588,7 +3602,10 @@ fn markGlobalImport( import: *GlobalImport, global_index: GlobalImport.Index, ) link.File.FlushError!void { - if (import.flags.alive) return; + // import.flags.alive might be already true from a previous update. In such + // case, we must still run the logic in this function, in case the item + // being marked was reverted by the `flush` logic that resets the hash + // table watermarks. import.flags.alive = true; const comp = wasm.base.comp; @@ -3618,8 +3635,9 @@ fn markGlobalImport( } else { try wasm.global_imports.put(gpa, name, .fromObject(global_index, wasm)); } - } else { - try markGlobal(wasm, import.resolution.unpack(wasm).object_global, import.flags.exported); + } else switch (import.resolution.unpack(wasm)) { + .object_global => try markGlobal(wasm, import.resolution.unpack(wasm).object_global, import.flags.exported), + else => return, } } @@ -3822,8 +3840,9 @@ pub fn flush( const comp = wasm.base.comp; const diags = &comp.link_diags; const gpa = comp.gpa; + const io = comp.io; - if (comp.verbose_link) Compilation.dump_argv(wasm.dump_argv_list.items); + if (comp.verbose_link) try Compilation.dumpArgv(io, wasm.dump_argv_list.items); if (wasm.base.zcu_object_basename) |raw| { const zcu_obj_path: Path = try comp.resolveEmitPathFlush(arena, .temp, raw); @@ -4036,7 +4055,7 @@ pub fn tagNameSymbolIndex(wasm: *Wasm, ip_index: InternPool.Index) Allocator.Err const comp = wasm.base.comp; assert(comp.config.output_mode == .Obj); const gpa = comp.gpa; - const name = try wasm.internStringFmt("__zig_tag_name_{d}", .{@intFromEnum(ip_index)}); + const name = try wasm.internStringFmt("__zig_tag_name_{d}", .{ip_index}); const gop = try wasm.symbol_table.getOrPut(gpa, name); gop.value_ptr.* = {}; return @enumFromInt(gop.index); diff --git a/src/link/Wasm/Flush.zig b/src/link/Wasm/Flush.zig index 6bc1887855f5..8197d35b724f 100644 --- a/src/link/Wasm/Flush.zig +++ b/src/link/Wasm/Flush.zig @@ -108,6 +108,7 @@ pub fn deinit(f: *Flush, gpa: Allocator) void { pub fn finish(f: *Flush, wasm: *Wasm) !void { const comp = wasm.base.comp; + const io = comp.io; const shared_memory = comp.config.shared_memory; const diags = &comp.link_diags; const gpa = comp.gpa; @@ -127,17 +128,20 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { if (comp.zcu) |zcu| { const ip: *const InternPool = &zcu.intern_pool; // No mutations allowed! + log.debug("total MIR instructions: {d}", .{wasm.mir_instructions.len}); + // Detect any intrinsics that were called; they need to have dependencies on the symbols marked. // Likewise detect `@tagName` calls so those functions can be included in the output and synthesized. for (wasm.mir_instructions.items(.tag), wasm.mir_instructions.items(.data)) |tag, *data| switch (tag) { .call_intrinsic => { const symbol_name = try wasm.internString(@tagName(data.intrinsic)); const i: Wasm.FunctionImport.Index = @enumFromInt(wasm.object_function_imports.getIndex(symbol_name) orelse { - return diags.fail("missing compiler runtime intrinsic '{s}' (undefined linker symbol)", .{ - @tagName(data.intrinsic), + return diags.fail("missing compiler runtime intrinsic '{t}' (undefined linker symbol)", .{ + data.intrinsic, }); }); try wasm.markFunctionImport(symbol_name, i.value(wasm), i); + log.debug("markFunctionImport intrinsic {d}={t}", .{ i, data.intrinsic }); }, .call_tag_name => { assert(ip.indexToKey(data.ip_index) == .enum_type); @@ -146,11 +150,10 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { wasm.tag_name_table_ref_count += 1; const int_tag_ty = Zcu.Type.fromInterned(data.ip_index).intTagType(zcu); gop.value_ptr.* = .{ .tag_name = .{ - .symbol_name = try wasm.internStringFmt("__zig_tag_name_{d}", .{@intFromEnum(data.ip_index)}), + .symbol_name = try wasm.internStringFmt("__zig_tag_name_{d}", .{data.ip_index}), .type_index = try wasm.internFunctionType(.auto, &.{int_tag_ty.ip_index}, .slice_const_u8_sentinel_0, target), .table_index = @intCast(wasm.tag_name_offs.items.len), } }; - try wasm.functions.put(gpa, .fromZcuFunc(wasm, @enumFromInt(gop.index)), {}); const tag_names = ip.loadEnumType(data.ip_index).names; for (tag_names.get(ip)) |tag_name| { const slice = tag_name.toSlice(ip); @@ -158,6 +161,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { try wasm.tag_name_bytes.appendSlice(gpa, slice[0 .. slice.len + 1]); } } + try wasm.functions.put(gpa, .fromZcuFunc(wasm, @enumFromInt(gop.index)), {}); }, else => continue, }; @@ -933,6 +937,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { var segment_offset: u32 = 0; var group_start_addr: u32 = data_vaddr; var group_end_addr = f.data_segment_groups.items[group_index].end_addr; + var first_segment_in_group = true; for (segment_ids, segment_vaddrs) |segment_id, segment_vaddr| { if (segment_vaddr >= group_end_addr) { try binary_bytes.appendNTimes(gpa, 0, group_end_addr - group_start_addr - segment_offset); @@ -944,8 +949,10 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { group_start_addr = group_end_addr; group_end_addr = f.data_segment_groups.items[group_index].end_addr; segment_offset = 0; + first_segment_in_group = true; } - if (segment_offset == 0) { + if (first_segment_in_group) { + first_segment_in_group = false; const group_size = group_end_addr - group_start_addr; log.debug("emit data section group, {d} bytes", .{group_size}); const flags: Object.DataSegmentFlags = if (segment_id.isPassive(wasm)) .passive else .active; @@ -1064,7 +1071,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { } // Finally, write the entire binary into the file. - var file_writer = wasm.base.file.?.writer(&.{}); + var file_writer = wasm.base.file.?.writer(io, &.{}); file_writer.interface.writeAll(binary_bytes.items) catch |err| switch (err) { error.WriteFailed => return file_writer.err.?, }; @@ -1864,13 +1871,21 @@ fn emitTagNameFunction( const enum_type = ip.loadEnumType(enum_type_ip); const tag_values = enum_type.values.get(ip); - try code.ensureUnusedCapacity(gpa, 7 * 5 + 6 + 1 * 6); - appendReservedUleb32(code, 0); // no locals - const slice_abi_size = 8; const encoded_alignment = @ctz(@as(u32, 4)); + if (tag_values.len == 0) { - // Then it's auto-numbered and therefore a direct table lookup. + // Auto-numbered, therefore a direct table lookup. + + try code.ensureUnusedCapacity( + gpa, + 6 * @sizeOf(std.wasm.Opcode) + + 7 * 5 + // appendReservedUleb32 + 1 * 6, // appendReservedI32Const + ); + + appendReservedUleb32(code, 0); // no locals + code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_get)); appendReservedUleb32(code, 0); @@ -1887,78 +1902,91 @@ fn emitTagNameFunction( code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_store)); appendReservedUleb32(code, encoded_alignment); appendReservedUleb32(code, 0); - } else { - const int_info = Zcu.Type.intInfo(.fromInterned(enum_type.tag_ty), zcu); - const outer_block_type: std.wasm.BlockType = switch (int_info.bits) { - 0...32 => .i32, - 33...64 => .i64, - else => return diags.fail("wasm linker does not yet implement @tagName for sparse enums with more than 64 bit integer tag types", .{}), - }; - code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_get)); - appendReservedUleb32(code, 0); + code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end)); - // Outer block that computes table offset. - code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.block)); - code.appendAssumeCapacity(@intFromEnum(outer_block_type)); - - for (tag_values, 0..) |tag_value, tag_index| { - // block for this if case - code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.block)); - code.appendAssumeCapacity(@intFromEnum(std.wasm.BlockType.empty)); - - // Tag value whose name should be returned. - code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_get)); - appendReservedUleb32(code, 1); - - const val: Zcu.Value = .fromInterned(tag_value); - switch (outer_block_type) { - .i32 => { - const x: u32 = switch (int_info.signedness) { - .signed => @bitCast(@as(i32, @intCast(val.toSignedInt(zcu)))), - .unsigned => @intCast(val.toUnsignedInt(zcu)), - }; - appendReservedI32Const(code, x); - code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_ne)); - }, - .i64 => { - const x: u64 = switch (int_info.signedness) { - .signed => @bitCast(val.toSignedInt(zcu)), - .unsigned => val.toUnsignedInt(zcu), - }; - appendReservedI64Const(code, x); - code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_ne)); - }, - else => unreachable, - } + return; + } - // if they're not equal, break out of current branch - code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.br_if)); - appendReservedUleb32(code, 0); + const int_info = Zcu.Type.intInfo(.fromInterned(enum_type.tag_ty), zcu); + const outer_block_type: std.wasm.BlockType = switch (int_info.bits) { + 0...32 => .i32, + 33...64 => .i64, + else => return diags.fail("wasm linker does not yet implement @tagName for sparse enums with more than 64 bit integer tag types", .{}), + }; - // Put the table offset of the result on the stack. - appendReservedI32Const(code, @intCast(tag_index * slice_abi_size)); + try code.ensureUnusedCapacity( + gpa, + (7 + tag_values.len * 6) * @sizeOf(std.wasm.Opcode) + + (1 + tag_values.len * 1) * @sizeOf(std.wasm.BlockType) + + (6 + tag_values.len * 3) * 5 + // appendReservedUleb32 + (tag_values.len * 2) * 11, // appendReservedI32Const / appendReservedI64Const + ); - // break outside blocks - code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.br)); - appendReservedUleb32(code, 1); + appendReservedUleb32(code, 0); // no locals - // end the block for this case - code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end)); - } - code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.@"unreachable")); - code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end)); + code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_get)); + appendReservedUleb32(code, 0); - code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_load)); - appendReservedUleb32(code, encoded_alignment); - appendReservedUleb32(code, table_base_addr + table_index * 8); + // Outer block that computes table offset. + code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.block)); + code.appendAssumeCapacity(@intFromEnum(outer_block_type)); - code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_store)); - appendReservedUleb32(code, encoded_alignment); + for (tag_values, 0..) |tag_value, tag_index| { + // block for this if case + code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.block)); + code.appendAssumeCapacity(@intFromEnum(std.wasm.BlockType.empty)); + + // Tag value whose name should be returned. + code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_get)); + appendReservedUleb32(code, 1); + + const val: Zcu.Value = .fromInterned(tag_value); + switch (outer_block_type) { + .i32 => { + const x: u32 = switch (int_info.signedness) { + .signed => @bitCast(@as(i32, @intCast(val.toSignedInt(zcu)))), + .unsigned => @intCast(val.toUnsignedInt(zcu)), + }; + appendReservedI32Const(code, x); + code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_ne)); + }, + .i64 => { + const x: u64 = switch (int_info.signedness) { + .signed => @bitCast(val.toSignedInt(zcu)), + .unsigned => val.toUnsignedInt(zcu), + }; + appendReservedI64Const(code, x); + code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_ne)); + }, + else => unreachable, + } + + // if they're not equal, break out of current branch + code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.br_if)); appendReservedUleb32(code, 0); + + // Put the table offset of the result on the stack. + appendReservedI32Const(code, @intCast(tag_index * slice_abi_size)); + + // break outside blocks + code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.br)); + appendReservedUleb32(code, 1); + + // end the block for this case + code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end)); } + code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.@"unreachable")); + code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end)); + + code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_load)); + appendReservedUleb32(code, encoded_alignment); + appendReservedUleb32(code, table_base_addr + table_index * 8); + + code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_store)); + appendReservedUleb32(code, encoded_alignment); + appendReservedUleb32(code, 0); - // End of the function body code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end)); } diff --git a/src/link/aarch64.zig b/src/link/aarch64.zig index c9defc27b319..0536316f4c59 100644 --- a/src/link/aarch64.zig +++ b/src/link/aarch64.zig @@ -29,6 +29,12 @@ pub fn writeBranchImm(disp: i28, code: *[4]u8) void { inst.write(code); } +pub fn writeCondBrImm(disp: i19, code: *[4]u8) void { + var inst: encoding.Instruction = .read(code); + inst.branch_exception_generating_system.conditional_branch_immediate.group.imm19 = @intCast(@shrExact(disp, 2)); + inst.write(code); +} + const assert = std.debug.assert; const builtin = @import("builtin"); const math = std.math; diff --git a/src/link/tapi.zig b/src/link/tapi.zig index 4c1471a6b471..33c31a841508 100644 --- a/src/link/tapi.zig +++ b/src/link/tapi.zig @@ -1,10 +1,10 @@ const std = @import("std"); -const fs = std.fs; +const Io = std.Io; const mem = std.mem; const log = std.log.scoped(.tapi); -const yaml = @import("tapi/yaml.zig"); +const Allocator = std.mem.Allocator; -const Allocator = mem.Allocator; +const yaml = @import("tapi/yaml.zig"); const Yaml = yaml.Yaml; const VersionField = union(enum) { @@ -130,7 +130,7 @@ pub const Tbd = union(enum) { pub const TapiError = error{ NotLibStub, InputOutput, -} || yaml.YamlError || std.fs.File.PReadError; +} || yaml.YamlError || Io.File.ReadPositionalError; pub const LibStub = struct { /// Underlying memory for stub's contents. @@ -139,14 +139,14 @@ pub const LibStub = struct { /// Typed contents of the tbd file. inner: []Tbd, - pub fn loadFromFile(allocator: Allocator, file: fs.File) TapiError!LibStub { + pub fn loadFromFile(allocator: Allocator, io: Io, file: Io.File) TapiError!LibStub { const filesize = blk: { - const stat = file.stat() catch break :blk std.math.maxInt(u32); + const stat = file.stat(io) catch break :blk std.math.maxInt(u32); break :blk @min(stat.size, std.math.maxInt(u32)); }; const source = try allocator.alloc(u8, filesize); defer allocator.free(source); - const amt = try file.preadAll(source, 0); + const amt = try file.readPositionalAll(io, source, 0); if (amt != filesize) return error.InputOutput; var lib_stub = LibStub{ diff --git a/src/main.zig b/src/main.zig index c08e9da44951..1da2c76a1a15 100644 --- a/src/main.zig +++ b/src/main.zig @@ -11,7 +11,6 @@ const Allocator = mem.Allocator; const Ast = std.zig.Ast; const Color = std.zig.Color; const warn = std.log.warn; -const ThreadPool = std.Thread.Pool; const cleanExit = std.process.cleanExit; const Cache = std.Build.Cache; const Path = std.Build.Cache.Path; @@ -43,7 +42,6 @@ test { const thread_stack_size = 60 << 20; pub const std_options: std.Options = .{ - .wasiCwd = wasi_cwd, .logFn = log, .log_level = switch (builtin.mode) { @@ -52,16 +50,17 @@ pub const std_options: std.Options = .{ .ReleaseSmall => .err, }, }; +pub const std_options_cwd = if (native_os == .wasi) wasi_cwd else null; pub const panic = crash_report.panic; pub const debug = crash_report.debug; -var wasi_preopens: fs.wasi.Preopens = undefined; -pub fn wasi_cwd() std.os.wasi.fd_t { +var preopens: std.process.Preopens = .empty; +pub fn wasi_cwd() Io.Dir { // Expect the first preopen to be current working directory. const cwd_fd: std.posix.fd_t = 3; - assert(mem.eql(u8, wasi_preopens.names[cwd_fd], ".")); - return cwd_fd; + assert(mem.eql(u8, preopens.map.keys()[cwd_fd], ".")); + return .{ .handle = cwd_fd }; } const fatal = std.process.fatal; @@ -163,56 +162,68 @@ var debug_allocator: std.heap.DebugAllocator(.{ .stack_trace_frames = build_options.mem_leak_frames, }) = .init; -pub fn main() anyerror!void { - const gpa, const is_debug = gpa: { - if (build_options.debug_gpa) break :gpa .{ debug_allocator.allocator(), true }; - if (native_os == .wasi) break :gpa .{ std.heap.wasm_allocator, false }; - if (builtin.link_libc) { - // We would prefer to use raw libc allocator here, but cannot use - // it if it won't support the alignment we need. - if (@alignOf(std.c.max_align_t) < @max(@alignOf(i128), std.atomic.cache_line)) { - break :gpa .{ std.heap.c_allocator, false }; - } - break :gpa .{ std.heap.raw_c_allocator, false }; - } - break :gpa switch (builtin.mode) { - .Debug, .ReleaseSafe => .{ debug_allocator.allocator(), true }, - .ReleaseFast, .ReleaseSmall => .{ std.heap.smp_allocator, false }, - }; +const use_debug_allocator = build_options.debug_gpa or + (native_os != .wasi and !builtin.link_libc and switch (builtin.mode) { + .Debug, .ReleaseSafe => true, + .ReleaseFast, .ReleaseSmall => false, + }); + +pub fn main(init: std.process.Init.Minimal) anyerror!void { + const gpa = gpa: { + if (use_debug_allocator) break :gpa debug_allocator.allocator(); + if (native_os == .wasi) break :gpa std.heap.wasm_allocator; + if (builtin.link_libc) break :gpa std.heap.c_allocator; + break :gpa std.heap.smp_allocator; }; - defer if (is_debug) { + defer if (use_debug_allocator) { _ = debug_allocator.deinit(); }; var arena_instance = std.heap.ArenaAllocator.init(gpa); defer arena_instance.deinit(); const arena = arena_instance.allocator(); - const args = try process.argsAlloc(arena); + const args = try init.args.toSlice(arena); if (args.len > 0) crash_report.zig_argv0 = args[0]; + if (args.len <= 1) { + std.log.info("{s}", .{usage}); + fatal("expected command argument", .{}); + } + + var environ_map = init.environ.createMap(arena) catch |err| fatal("failed to parse environment: {t}", .{err}); + + Compilation.setMainThread(); + + var threaded: Io.Threaded = .init(gpa, .{ + .argv0 = .init(init.args), + .environ = init.environ, + }); + defer threaded.deinit(); + threaded_impl_ptr = &threaded; + threaded.stack_size = thread_stack_size; + const io = threaded.io(); + if (tracy.enable_allocation) { var gpa_tracy = tracy.tracyAllocator(gpa); - return mainArgs(gpa_tracy.allocator(), arena, args); + return mainArgs(gpa_tracy.allocator(), arena, io, args, &environ_map); } if (native_os == .wasi) { - wasi_preopens = try fs.wasi.preopensAlloc(arena); + preopens = try .init(arena); } - return mainArgs(gpa, arena, args); + return mainArgs(gpa, arena, io, args, &environ_map); } -fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { - const tr = tracy.trace(@src()); - defer tr.end(); - - if (args.len <= 1) { - std.log.info("{s}", .{usage}); - fatal("expected command argument", .{}); - } - - if (process.can_execv and std.posix.getenvZ("ZIG_IS_DETECTING_LIBC_PATHS") != null) { +fn mainArgs( + gpa: Allocator, + arena: Allocator, + io: Io, + args: []const [:0]const u8, + environ_map: *process.Environ.Map, +) !void { + if (process.can_replace and EnvVar.ZIG_IS_DETECTING_LIBC_PATHS.isSet(environ_map)) { dev.check(.cc_command); // In this case we have accidentally invoked ourselves as "the system C compiler" // to figure out where libc is installed. This is essentially infinite recursion @@ -220,54 +231,51 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { // Here we ignore the CC environment variable and exec `cc` as a child process. // However it's possible Zig is installed as *that* C compiler as well, which is // why we have this additional environment variable here to check. - var env_map = try process.getEnvMap(arena); - - const inf_loop_env_key = "ZIG_IS_TRYING_TO_NOT_CALL_ITSELF"; - if (env_map.get(inf_loop_env_key) != null) { - fatal("The compilation links against libc, but Zig is unable to provide a libc " ++ - "for this operating system, and no --libc " ++ - "parameter was provided, so Zig attempted to invoke the system C compiler " ++ - "in order to determine where libc is installed. However the system C " ++ - "compiler is `zig cc`, so no libc installation was found.", .{}); + + const inf_loop_env_key: EnvVar = .ZIG_IS_TRYING_TO_NOT_CALL_ITSELF; + if (inf_loop_env_key.isSet(environ_map)) { + fatal("{s}", .{ + "The compilation links against libc, but Zig is unable to provide a libc " ++ + "for this operating system, and no --libc " ++ + "parameter was provided, so Zig attempted to invoke the system C compiler " ++ + "in order to determine where libc is installed. However the system C " ++ + "compiler is `zig cc`, so no libc installation was found.", + }); } - try env_map.put(inf_loop_env_key, "1"); + try environ_map.put(@tagName(inf_loop_env_key), "1"); // Some programs such as CMake will strip the `cc` and subsequent args from the // CC environment variable. We detect and support this scenario here because of // the ZIG_IS_DETECTING_LIBC_PATHS environment variable. if (mem.eql(u8, args[1], "cc")) { - return process.execve(arena, args[1..], &env_map); + return process.replace(io, .{ .argv = args[1..], .environ_map = environ_map }); } else { const modified_args = try arena.dupe([]const u8, args); modified_args[0] = "cc"; - return process.execve(arena, modified_args, &env_map); + return process.replace(io, .{ .argv = modified_args, .environ_map = environ_map }); } } - var threaded: Io.Threaded = .init(gpa); - defer threaded.deinit(); - const io = threaded.io(); - const cmd = args[1]; const cmd_args = args[2..]; if (mem.eql(u8, cmd, "build-exe")) { dev.check(.build_exe_command); - return buildOutputType(gpa, arena, io, args, .{ .build = .Exe }); + return buildOutputType(gpa, arena, io, args, .{ .build = .Exe }, environ_map); } else if (mem.eql(u8, cmd, "build-lib")) { dev.check(.build_lib_command); - return buildOutputType(gpa, arena, io, args, .{ .build = .Lib }); + return buildOutputType(gpa, arena, io, args, .{ .build = .Lib }, environ_map); } else if (mem.eql(u8, cmd, "build-obj")) { dev.check(.build_obj_command); - return buildOutputType(gpa, arena, io, args, .{ .build = .Obj }); + return buildOutputType(gpa, arena, io, args, .{ .build = .Obj }, environ_map); } else if (mem.eql(u8, cmd, "test")) { dev.check(.test_command); - return buildOutputType(gpa, arena, io, args, .zig_test); + return buildOutputType(gpa, arena, io, args, .zig_test, environ_map); } else if (mem.eql(u8, cmd, "test-obj")) { dev.check(.test_command); - return buildOutputType(gpa, arena, io, args, .zig_test_obj); + return buildOutputType(gpa, arena, io, args, .zig_test_obj, environ_map); } else if (mem.eql(u8, cmd, "run")) { dev.check(.run_command); - return buildOutputType(gpa, arena, io, args, .run); + return buildOutputType(gpa, arena, io, args, .run, environ_map); } else if (mem.eql(u8, cmd, "dlltool") or mem.eql(u8, cmd, "ranlib") or mem.eql(u8, cmd, "lib") or @@ -277,7 +285,7 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { return process.exit(try llvmArMain(arena, args)); } else if (mem.eql(u8, cmd, "build")) { dev.check(.build_command); - return cmdBuild(gpa, arena, io, cmd_args); + return cmdBuild(gpa, arena, io, cmd_args, environ_map); } else if (mem.eql(u8, cmd, "clang") or mem.eql(u8, cmd, "-cc1") or mem.eql(u8, cmd, "-cc1as")) { @@ -291,16 +299,16 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { return process.exit(try lldMain(arena, args, true)); } else if (mem.eql(u8, cmd, "cc")) { dev.check(.cc_command); - return buildOutputType(gpa, arena, io, args, .cc); + return buildOutputType(gpa, arena, io, args, .cc, environ_map); } else if (mem.eql(u8, cmd, "c++")) { dev.check(.cc_command); - return buildOutputType(gpa, arena, io, args, .cpp); + return buildOutputType(gpa, arena, io, args, .cpp, environ_map); } else if (mem.eql(u8, cmd, "translate-c")) { dev.check(.translate_c_command); - return buildOutputType(gpa, arena, io, args, .translate_c); + return buildOutputType(gpa, arena, io, args, .translate_c, environ_map); } else if (mem.eql(u8, cmd, "rc")) { const use_server = cmd_args.len > 0 and std.mem.eql(u8, cmd_args[0], "--zig-integration"); - return jitCmd(gpa, arena, io, cmd_args, .{ + return jitCmd(gpa, arena, io, cmd_args, environ_map, .{ .cmd_name = "resinator", .root_src_path = "resinator/main.zig", .depend_on_aro = true, @@ -311,20 +319,20 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { dev.check(.fmt_command); return @import("fmt.zig").run(gpa, arena, io, cmd_args); } else if (mem.eql(u8, cmd, "objcopy")) { - return jitCmd(gpa, arena, io, cmd_args, .{ + return jitCmd(gpa, arena, io, cmd_args, environ_map, .{ .cmd_name = "objcopy", .root_src_path = "objcopy.zig", }); } else if (mem.eql(u8, cmd, "fetch")) { - return cmdFetch(gpa, arena, io, cmd_args); + return cmdFetch(gpa, arena, io, cmd_args, environ_map); } else if (mem.eql(u8, cmd, "libc")) { - return jitCmd(gpa, arena, io, cmd_args, .{ + return jitCmd(gpa, arena, io, cmd_args, environ_map, .{ .cmd_name = "libc", .root_src_path = "libc.zig", .prepend_zig_lib_dir_path = true, }); } else if (mem.eql(u8, cmd, "std")) { - return jitCmd(gpa, arena, io, cmd_args, .{ + return jitCmd(gpa, arena, io, cmd_args, environ_map, .{ .cmd_name = "std", .root_src_path = "std-docs.zig", .prepend_zig_lib_dir_path = true, @@ -332,40 +340,42 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { .prepend_global_cache_path = true, }); } else if (mem.eql(u8, cmd, "init")) { - return cmdInit(gpa, arena, cmd_args); + return cmdInit(gpa, arena, io, cmd_args); } else if (mem.eql(u8, cmd, "targets")) { dev.check(.targets_command); const host = std.zig.resolveTargetQueryOrFatal(io, .{}); - var stdout_writer = fs.File.stdout().writer(&stdout_buffer); - try @import("print_targets.zig").cmdTargets(arena, cmd_args, &stdout_writer.interface, &host); + var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer); + try @import("print_targets.zig").cmdTargets(arena, io, cmd_args, &stdout_writer.interface, &host); return stdout_writer.interface.flush(); } else if (mem.eql(u8, cmd, "version")) { dev.check(.version_command); - try fs.File.stdout().writeAll(build_options.version ++ "\n"); + try Io.File.stdout().writeStreamingAll(io, build_options.version ++ "\n"); return; } else if (mem.eql(u8, cmd, "env")) { dev.check(.env_command); const host = std.zig.resolveTargetQueryOrFatal(io, .{}); - var stdout_writer = fs.File.stdout().writer(&stdout_buffer); + var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer); try @import("print_env.zig").cmdEnv( arena, + io, &stdout_writer.interface, args, - if (native_os == .wasi) wasi_preopens, + preopens, &host, + environ_map, ); return stdout_writer.interface.flush(); } else if (mem.eql(u8, cmd, "reduce")) { - return jitCmd(gpa, arena, io, cmd_args, .{ + return jitCmd(gpa, arena, io, cmd_args, environ_map, .{ .cmd_name = "reduce", .root_src_path = "reduce.zig", }); } else if (mem.eql(u8, cmd, "zen")) { dev.check(.zen_command); - return fs.File.stdout().writeAll(info_zen); + return Io.File.stdout().writeStreamingAll(io, info_zen); } else if (mem.eql(u8, cmd, "help") or mem.eql(u8, cmd, "-h") or mem.eql(u8, cmd, "--help")) { dev.check(.help_command); - return fs.File.stdout().writeAll(usage); + return Io.File.stdout().writeStreamingAll(io, usage); } else if (mem.eql(u8, cmd, "ast-check")) { return cmdAstCheck(arena, io, cmd_args); } else if (mem.eql(u8, cmd, "detect-cpu")) { @@ -375,7 +385,7 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { } else if (build_options.enable_debug_extensions and mem.eql(u8, cmd, "dump-zir")) { return cmdDumpZir(arena, io, cmd_args); } else if (build_options.enable_debug_extensions and mem.eql(u8, cmd, "llvm-ints")) { - return cmdDumpLlvmInts(gpa, arena, cmd_args); + return cmdDumpLlvmInts(gpa, arena, io, cmd_args); } else { std.log.info("{s}", .{usage}); fatal("unknown command: {s}", .{args[1]}); @@ -702,7 +712,7 @@ const Emit = union(enum) { yes: []const u8, const OutputToCacheReason = enum { listen, @"zig run", @"zig test" }; - fn resolve(emit: Emit, default_basename: []const u8, output_to_cache: ?OutputToCacheReason) Compilation.CreateOptions.Emit { + fn resolve(emit: Emit, io: Io, default_basename: []const u8, output_to_cache: ?OutputToCacheReason) Compilation.CreateOptions.Emit { return switch (emit) { .no => .no, .yes_default_path => if (output_to_cache != null) .yes_cache else .{ .yes_path = default_basename }, @@ -717,10 +727,10 @@ const Emit = union(enum) { } else e: { // If there's a dirname, check that dir exists. This will give a more descriptive error than `Compilation` otherwise would. if (fs.path.dirname(path)) |dir_path| { - var dir = fs.cwd().openDir(dir_path, .{}) catch |err| { + var dir = Io.Dir.cwd().openDir(io, dir_path, .{}) catch |err| { fatal("unable to open output directory '{s}': {s}", .{ dir_path, @errorName(err) }); }; - dir.close(); + dir.close(io); } break :e .{ .yes_path = path }; }, @@ -801,6 +811,7 @@ fn buildOutputType( io: Io, all_args: []const []const u8, arg_mode: ArgMode, + environ_map: *process.Environ.Map, ) !void { var provided_name: ?[]const u8 = null; var root_src_file: ?[]const u8 = null; @@ -813,14 +824,15 @@ fn buildOutputType( var debug_compile_errors = false; var debug_incremental = false; var verbose_link = (native_os != .wasi or builtin.link_libc) and - EnvVar.ZIG_VERBOSE_LINK.isSet(); + EnvVar.ZIG_VERBOSE_LINK.isSet(environ_map); var verbose_cc = (native_os != .wasi or builtin.link_libc) and - EnvVar.ZIG_VERBOSE_CC.isSet(); + EnvVar.ZIG_VERBOSE_CC.isSet(environ_map); var verbose_air = false; var verbose_intern_pool = false; var verbose_generic_instances = false; var verbose_llvm_ir: ?[]const u8 = null; var verbose_llvm_bc: ?[]const u8 = null; + var link_depfile: ?[]const u8 = null; var verbose_cimport = false; var verbose_llvm_cpu_features = false; var time_report = false; @@ -886,9 +898,9 @@ fn buildOutputType( var runtime_args_start: ?usize = null; var test_filters: std.ArrayList([]const u8) = .empty; var test_runner_path: ?[]const u8 = null; - var override_local_cache_dir: ?[]const u8 = try EnvVar.ZIG_LOCAL_CACHE_DIR.get(arena); - var override_global_cache_dir: ?[]const u8 = try EnvVar.ZIG_GLOBAL_CACHE_DIR.get(arena); - var override_lib_dir: ?[]const u8 = try EnvVar.ZIG_LIB_DIR.get(arena); + var override_local_cache_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_CACHE_DIR.get(environ_map); + var override_global_cache_dir: ?[]const u8 = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map); + var override_lib_dir: ?[]const u8 = EnvVar.ZIG_LIB_DIR.get(environ_map); var clang_preprocessor_mode: Compilation.ClangPreprocessorMode = .no; var subsystem: ?std.zig.Subsystem = null; var major_subsystem_version: ?u16 = null; @@ -985,7 +997,7 @@ fn buildOutputType( .framework_dirs = .{}, .rpath_list = .{}, .each_lib_rpath = null, - .libc_paths_file = try EnvVar.ZIG_LIBC.get(arena), + .libc_paths_file = EnvVar.ZIG_LIBC.get(environ_map), .native_system_include_paths = &.{}, }; defer create_module.link_inputs.deinit(gpa); @@ -994,9 +1006,9 @@ fn buildOutputType( // if set, default the color setting to .off or .on, respectively // explicit --color arguments will still override this setting. // Disable color on WASI per https://github.com/WebAssembly/WASI/issues/162 - var color: Color = if (native_os == .wasi or EnvVar.NO_COLOR.isSet()) + var color: Color = if (native_os == .wasi or EnvVar.NO_COLOR.isSet(environ_map)) .off - else if (EnvVar.CLICOLOR_FORCE.isSet()) + else if (EnvVar.CLICOLOR_FORCE.isSet(environ_map)) .on else .auto; @@ -1032,13 +1044,12 @@ fn buildOutputType( if (mem.cutPrefix(u8, arg, "@")) |resp_file_path| { // This is a "compiler response file". We must parse the file and treat its // contents as command line parameters. - args_iter.resp_file = initArgIteratorResponseFile(arena, resp_file_path) catch |err| { - fatal("unable to read response file '{s}': {s}", .{ resp_file_path, @errorName(err) }); - }; + args_iter.resp_file = initArgIteratorResponseFile(arena, io, resp_file_path) catch |err| + fatal("unable to read response file '{s}': {t}", .{ resp_file_path, err }); } else if (mem.startsWith(u8, arg, "-")) { if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { - try fs.File.stdout().writeAll(usage_build_generic); - return cleanExit(); + try Io.File.stdout().writeStreamingAll(io, usage_build_generic); + return cleanExit(io); } else if (mem.eql(u8, arg, "--")) { if (arg_mode == .run) { // args_iter.i is 1, referring the next arg after "--" in ["--", ...] @@ -1501,6 +1512,7 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-fno-emit-bin")) { emit_bin = .no; } else if (mem.eql(u8, arg, "-femit-h")) { + fatal("-femit-h is currently broken, see https://github.com/ziglang/zig/issues/9698", .{}); emit_h = .yes_default_path; } else if (mem.cutPrefix(u8, arg, "-femit-h=")) |rest| { emit_h = .{ .yes = rest }; @@ -1859,9 +1871,7 @@ fn buildOutputType( var must_link = false; var file_ext: ?Compilation.FileExt = null; while (it.has_next) { - it.next() catch |err| { - fatal("unable to parse command line parameters: {s}", .{@errorName(err)}); - }; + it.next(io) catch |err| fatal("unable to parse command line parameters: {t}", .{err}); switch (it.zig_equivalent) { .target => target_arch_os_abi = it.only_arg, // example: -target riscv64-linux-unknown .o => { @@ -2070,6 +2080,8 @@ fn buildOutputType( .wl => { var split_it = mem.splitScalar(u8, it.only_arg, ','); while (split_it.next()) |linker_arg| { + // Unfortunately duplicated with the `for_linker` handling below. + // Handle nested-joined args like `-Wl,-rpath=foo`. // Must be prefixed with 1 or 2 dashes. if (linker_arg.len >= 3 and @@ -2079,6 +2091,10 @@ fn buildOutputType( if (mem.indexOfScalar(u8, linker_arg, '=')) |equals_pos| { const key = linker_arg[0..equals_pos]; const value = linker_arg[equals_pos + 1 ..]; + + // We have to handle these here because they would be ambiguous + // if split and added to `linker_args`, as there are argument-less + // variants of them. if (mem.eql(u8, key, "--build-id")) { build_id = std.zig.BuildId.parse(value) catch |err| { fatal("unable to parse --build-id style '{s}': {s}", .{ @@ -2091,22 +2107,19 @@ fn buildOutputType( // is done below. continue; } + try linker_args.append(key); try linker_args.append(value); continue; } } - if (mem.eql(u8, linker_arg, "--build-id")) { - build_id = .fast; - } else if (mem.eql(u8, linker_arg, "--as-needed")) { + + // These options are handled inline because their order matters for + // other non-linker options. + if (mem.eql(u8, linker_arg, "--as-needed")) { needed = false; } else if (mem.eql(u8, linker_arg, "--no-as-needed")) { needed = true; - } else if (mem.eql(u8, linker_arg, "-no-pie")) { - create_module.opts.pie = false; - } else if (mem.eql(u8, linker_arg, "--sort-common")) { - // from ld.lld(1): --sort-common is ignored for GNU compatibility, - // this ignores plain --sort-common } else if (mem.eql(u8, linker_arg, "--whole-archive") or mem.eql(u8, linker_arg, "-whole-archive")) { @@ -2279,7 +2292,74 @@ fn buildOutputType( disable_c_depfile = true; try cc_argv.append(arena, "-###"); }, - .for_linker => try linker_args.append(it.only_arg), + .for_linker => blk: { + // Unfortunately duplicated with the `wl` handling above. + + // Handle joined args like `--dependency-file=foo.d`. + // Must be prefixed with 1 or 2 dashes. + if (it.only_arg.len >= 3 and it.only_arg[0] == '-' and it.only_arg[2] != '-') { + if (mem.indexOfScalar(u8, it.only_arg, '=')) |equals_pos| { + const key = it.only_arg[0..equals_pos]; + const value = it.only_arg[equals_pos + 1 ..]; + + // We have to handle these here because they would be ambiguous + // if split and added to `linker_args`, as there are argument-less + // variants of them. + if (mem.eql(u8, key, "--build-id")) { + build_id = std.zig.BuildId.parse(value) catch |err| { + fatal("unable to parse --build-id style '{s}': {s}", .{ + value, @errorName(err), + }); + }; + continue; + } else if (mem.eql(u8, key, "--sort-common")) { + // this ignores --sort-common= + continue; + } + + try linker_args.append(key); + try linker_args.append(value); + break :blk; + } + } + + // These options are handled inline because their order matters for + // other non-linker options. + if (mem.eql(u8, it.only_arg, "--as-needed")) { + needed = false; + } else if (mem.eql(u8, it.only_arg, "--no-as-needed")) { + needed = true; + } else if (mem.eql(u8, it.only_arg, "--whole-archive") or + mem.eql(u8, it.only_arg, "-whole-archive")) + { + must_link = true; + } else if (mem.eql(u8, it.only_arg, "--no-whole-archive") or + mem.eql(u8, it.only_arg, "-no-whole-archive")) + { + must_link = false; + } else if (mem.eql(u8, it.only_arg, "-Bdynamic") or + mem.eql(u8, it.only_arg, "-dy") or + mem.eql(u8, it.only_arg, "-call_shared")) + { + lib_search_strategy = .no_fallback; + lib_preferred_mode = .dynamic; + } else if (mem.eql(u8, it.only_arg, "-Bstatic") or + mem.eql(u8, it.only_arg, "-dn") or + mem.eql(u8, it.only_arg, "-non_shared") or + mem.eql(u8, it.only_arg, "-static")) + { + lib_search_strategy = .no_fallback; + lib_preferred_mode = .static; + } else if (mem.eql(u8, it.only_arg, "-search_paths_first")) { + lib_search_strategy = .paths_first; + lib_preferred_mode = .dynamic; + } else if (mem.eql(u8, it.only_arg, "-search_dylibs_first")) { + lib_search_strategy = .mode_first; + lib_preferred_mode = .dynamic; + } else { + try linker_args.append(it.only_arg); + } + }, .linker_input_z => { try linker_args.append("-z"); try linker_args.append(it.only_arg); @@ -2409,8 +2489,18 @@ fn buildOutputType( } } provided_name = name[prefix..end]; + } else if (mem.eql(u8, arg, "--build-id")) { + build_id = .fast; + } else if (mem.eql(u8, arg, "-no-pie")) { + create_module.opts.pie = false; + } else if (mem.eql(u8, arg, "--sort-common")) { + // from ld.lld(1): --sort-common is ignored for GNU compatibility, + // this ignores plain --sort-common } else if (mem.eql(u8, arg, "-rpath") or mem.eql(u8, arg, "--rpath") or mem.eql(u8, arg, "-R")) { try create_module.rpath_list.append(arena, linker_args_it.nextOrFatal()); + } else if (mem.eql(u8, arg, "-rpath-link") or mem.eql(u8, arg, "--rpath-link")) { + _ = linker_args_it.nextOrFatal(); + warn("rpath-link option is unimplemented and ignored", .{}); } else if (mem.eql(u8, arg, "--subsystem")) { subsystem = try parseSubsystem(linker_args_it.nextOrFatal()); } else if (mem.eql(u8, arg, "-I") or @@ -2704,6 +2794,8 @@ fn buildOutputType( { emit_implib = .{ .yes = linker_args_it.nextOrFatal() }; emit_implib_arg_provided = true; + } else if (mem.eql(u8, arg, "--dependency-file")) { + link_depfile = linker_args_it.nextOrFatal(); } else if (mem.eql(u8, arg, "-Brepro") or mem.eql(u8, arg, "/Brepro")) { linker_repro = true; } else if (mem.eql(u8, arg, "-undefined")) { @@ -2758,9 +2850,9 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-V")) { warn("ignoring request for supported emulations: unimplemented", .{}); } else if (mem.eql(u8, arg, "-v")) { - try fs.File.stdout().writeAll("zig ld " ++ build_options.version ++ "\n"); + try Io.File.stdout().writeStreamingAll(io, "zig ld " ++ build_options.version ++ "\n"); } else if (mem.eql(u8, arg, "--version")) { - try fs.File.stdout().writeAll("zig ld " ++ build_options.version ++ "\n"); + try Io.File.stdout().writeStreamingAll(io, "zig ld " ++ build_options.version ++ "\n"); process.exit(0); } else { fatal("unsupported linker arg: {s}", .{arg}); @@ -2999,14 +3091,13 @@ fn buildOutputType( const self_exe_path = switch (native_os) { .wasi => {}, - else => fs.selfExePathAlloc(arena) catch |err| { - fatal("unable to find zig self exe path: {s}", .{@errorName(err)}); - }, + else => process.executablePathAlloc(io, arena) catch |err| fatal("unable to find zig self exe path: {t}", .{err}), }; // This `init` calls `fatal` on error. var dirs: Compilation.Directories = .init( arena, + io, override_lib_dir, override_global_cache_dir, s: { @@ -3016,14 +3107,13 @@ fn buildOutputType( else => .search, }; }, - if (native_os == .wasi) wasi_preopens, + preopens, self_exe_path, + environ_map, ); - defer dirs.deinit(); + defer dirs.deinit(io); - if (linker_optimization) |o| { - warn("ignoring deprecated linker optimization setting '{s}'", .{o}); - } + if (linker_optimization) |o| warn("ignoring deprecated linker optimization setting '{s}'", .{o}); create_module.dirs = dirs; create_module.opts.emit_llvm_ir = emit_llvm_ir != .no; @@ -3031,7 +3121,7 @@ fn buildOutputType( create_module.opts.emit_bin = emit_bin != .no; create_module.opts.any_c_source_files = create_module.c_source_files.items.len != 0; - const main_mod = try createModule(gpa, arena, io, &create_module, 0, null, color); + const main_mod = try createModule(gpa, arena, io, &create_module, 0, null, color, environ_map); for (create_module.modules.keys(), create_module.modules.values()) |key, cli_mod| { if (cli_mod.resolved == null) fatal("module '{s}' declared but not used", .{key}); @@ -3132,6 +3222,7 @@ fn buildOutputType( for (create_module.framework_dirs.items) |framework_dir_path| { if (try accessFrameworkPath( + io, &test_path, &checked_paths, framework_dir_path, @@ -3175,8 +3266,8 @@ fn buildOutputType( } } - var cleanup_emit_bin_dir: ?fs.Dir = null; - defer if (cleanup_emit_bin_dir) |*dir| dir.close(); + var cleanup_emit_bin_dir: ?Io.Dir = null; + defer if (cleanup_emit_bin_dir) |*dir| dir.close(io); // For `zig run` and `zig test`, we don't want to put the binary in the cwd by default. So, if // the binary is requested with no explicit path (as is the default), we emit to the cache. @@ -3228,10 +3319,10 @@ fn buildOutputType( } else emit: { // If there's a dirname, check that dir exists. This will give a more descriptive error than `Compilation` otherwise would. if (fs.path.dirname(path)) |dir_path| { - var dir = fs.cwd().openDir(dir_path, .{}) catch |err| { + var dir = Io.Dir.cwd().openDir(io, dir_path, .{}) catch |err| { fatal("unable to open output directory '{s}': {s}", .{ dir_path, @errorName(err) }); }; - dir.close(); + dir.close(io); } break :emit .{ .yes_path = path }; }, @@ -3245,18 +3336,18 @@ fn buildOutputType( }; const default_h_basename = try std.fmt.allocPrint(arena, "{s}.h", .{root_name}); - const emit_h_resolved = emit_h.resolve(default_h_basename, output_to_cache); + const emit_h_resolved = emit_h.resolve(io, default_h_basename, output_to_cache); const default_asm_basename = try std.fmt.allocPrint(arena, "{s}.s", .{root_name}); - const emit_asm_resolved = emit_asm.resolve(default_asm_basename, output_to_cache); + const emit_asm_resolved = emit_asm.resolve(io, default_asm_basename, output_to_cache); const default_llvm_ir_basename = try std.fmt.allocPrint(arena, "{s}.ll", .{root_name}); - const emit_llvm_ir_resolved = emit_llvm_ir.resolve(default_llvm_ir_basename, output_to_cache); + const emit_llvm_ir_resolved = emit_llvm_ir.resolve(io, default_llvm_ir_basename, output_to_cache); const default_llvm_bc_basename = try std.fmt.allocPrint(arena, "{s}.bc", .{root_name}); - const emit_llvm_bc_resolved = emit_llvm_bc.resolve(default_llvm_bc_basename, output_to_cache); + const emit_llvm_bc_resolved = emit_llvm_bc.resolve(io, default_llvm_bc_basename, output_to_cache); - const emit_docs_resolved = emit_docs.resolve("docs", output_to_cache); + const emit_docs_resolved = emit_docs.resolve(io, "docs", output_to_cache); const is_exe_or_dyn_lib = switch (create_module.resolved_options.output_mode) { .Obj => false, @@ -3277,7 +3368,7 @@ fn buildOutputType( const default_implib_basename = try std.fmt.allocPrint(arena, "{s}.lib", .{root_name}); const emit_implib_resolved: Compilation.CreateOptions.Emit = switch (emit_implib) { .no => .no, - .yes => emit_implib.resolve(default_implib_basename, output_to_cache), + .yes => emit_implib.resolve(io, default_implib_basename, output_to_cache), .yes_default_path => emit: { if (output_to_cache != null) break :emit .yes_cache; const p = try fs.path.join(arena, &.{ @@ -3288,14 +3379,11 @@ fn buildOutputType( }, }; - var thread_pool: ThreadPool = undefined; - try thread_pool.init(.{ - .allocator = gpa, - .n_jobs = @min(@max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1), std.math.maxInt(Zcu.PerThread.IdBacking)), - .track_ids = true, - .stack_size = thread_stack_size, - }); - defer thread_pool.deinit(); + const thread_limit = @min( + @max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1), + std.math.maxInt(Zcu.PerThread.IdBacking), + ); + setThreadLimit(thread_limit); for (create_module.c_source_files.items) |*src| { dev.check(.c_compiler); @@ -3307,26 +3395,26 @@ fn buildOutputType( // "-" is stdin. Dump it to a real file. const sep = fs.path.sep_str; const dump_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{x}-dump-stdin{s}", .{ - std.crypto.random.int(u64), ext.canonicalName(target), + randInt(io, u64), ext.canonicalName(target), }); - try dirs.local_cache.handle.makePath("tmp"); + try dirs.local_cache.handle.createDirPath(io, "tmp"); // Note that in one of the happy paths, execve() is used to switch to // clang in which case any cleanup logic that exists for this temporary // file will not run and this temp file will be leaked. The filename // will be a hash of its contents — so multiple invocations of // `zig cc -` will result in the same temp file name. - var f = try dirs.local_cache.handle.createFile(dump_path, .{}); - defer f.close(); + var f = try dirs.local_cache.handle.createFile(io, dump_path, .{}); + defer f.close(io); // Re-using the hasher from Cache, since the functional requirements // for the hashing algorithm here and in the cache are the same. // We are providing our own cache key, because this file has nothing // to do with the cache manifest. - var file_writer = f.writer(&.{}); + var file_writer = f.writer(io, &.{}); var buffer: [1000]u8 = undefined; var hasher = file_writer.interface.hashed(Cache.Hasher.init("0123456789abcdef"), &buffer); - var stdin_reader = fs.File.stdin().readerStreaming(io, &.{}); + var stdin_reader = Io.File.stdin().readerStreaming(io, &.{}); _ = hasher.writer.sendFileAll(&stdin_reader, .unlimited) catch |err| switch (err) { error.WriteFailed => fatal("failed to write {s}: {t}", .{ dump_path, file_writer.err.? }), else => fatal("failed to pipe stdin to {s}: {t}", .{ dump_path, err }), @@ -3338,7 +3426,7 @@ fn buildOutputType( const sub_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{x}-stdin{s}", .{ &bin_digest, ext.canonicalName(target), }); - try dirs.local_cache.handle.rename(dump_path, sub_path); + try dirs.local_cache.handle.rename(dump_path, dirs.local_cache.handle, sub_path, io); // Convert `sub_path` to be relative to current working directory. src.src_path = try dirs.local_cache.join(arena, &.{sub_path}); @@ -3388,7 +3476,7 @@ fn buildOutputType( var create_diag: Compilation.CreateDiagnostic = undefined; const comp = Compilation.create(gpa, arena, io, &create_diag, .{ .dirs = dirs, - .thread_pool = &thread_pool, + .thread_limit = thread_limit, .self_exe_path = switch (native_os) { .wasi => null, else => self_exe_path, @@ -3479,6 +3567,7 @@ fn buildOutputType( .verbose_generic_instances = verbose_generic_instances, .verbose_llvm_ir = verbose_llvm_ir, .verbose_llvm_bc = verbose_llvm_bc, + .link_depfile = link_depfile, .verbose_cimport = verbose_cimport, .verbose_llvm_cpu_features = verbose_llvm_cpu_features, .time_report = time_report, @@ -3509,6 +3598,7 @@ fn buildOutputType( .global_cc_argv = try cc_argv.toOwnedSlice(arena), .file_system_inputs = &file_system_inputs, .debug_compiler_runtime_libs = debug_compiler_runtime_libs, + .environ_map = environ_map, }) catch |err| switch (err) { error.CreateFail => switch (create_diag) { .cross_libc_unavailable => { @@ -3556,13 +3646,13 @@ fn buildOutputType( if (show_builtin) { const builtin_opts = comp.root_mod.getBuiltinOptions(comp.config); const source = try builtin_opts.generate(arena); - return fs.File.stdout().writeAll(source); + return Io.File.stdout().writeStreamingAll(io, source); } switch (listen) { .none => {}, .stdio => { - var stdin_reader = fs.File.stdin().reader(io, &stdin_buffer); - var stdout_writer = fs.File.stdout().writer(&stdout_buffer); + var stdin_reader = Io.File.stdin().reader(io, &stdin_buffer); + var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer); try serve( comp, &stdin_reader.interface, @@ -3572,8 +3662,9 @@ fn buildOutputType( arg_mode, all_args, runtime_args_start, + environ_map, ); - return cleanExit(); + return cleanExit(io); }, .ip4 => |ip4_addr| { const addr: Io.net.IpAddress = .{ .ip4 = ip4_addr }; @@ -3598,19 +3689,20 @@ fn buildOutputType( arg_mode, all_args, runtime_args_start, + environ_map, ); - return cleanExit(); + return cleanExit(io); }, } { - const root_prog_node = std.Progress.start(.{ + const root_prog_node = std.Progress.start(io, .{ .disable_printing = (color == .off), }); defer root_prog_node.end(); if (arg_mode == .translate_c) { - return cmdTranslateC(comp, arena, null, null, root_prog_node); + return cmdTranslateC(comp, arena, null, null, root_prog_node, environ_map); } updateModule(comp, color, root_prog_node) catch |err| switch (err) { @@ -3678,11 +3770,12 @@ fn buildOutputType( all_args, runtime_args_start, create_module.resolved_options.link_libc, + environ_map, ); } // Skip resource deallocation in release builds; let the OS do it. - return cleanExit(); + return cleanExit(io); } const CreateModule = struct { @@ -3733,6 +3826,7 @@ fn createModule( index: usize, parent: ?*Package.Module, color: std.zig.Color, + environ_map: *process.Environ.Map, ) Allocator.Error!*Package.Module { const cli_mod = &create_module.modules.values()[index]; if (cli_mod.resolved) |m| return m; @@ -3853,11 +3947,8 @@ fn createModule( } if (target.isMinGW()) { - const exists = mingw.libExists(arena, target, create_module.dirs.zig_lib, lib_name) catch |err| { - fatal("failed to check zig installation for DLL import libs: {s}", .{ - @errorName(err), - }); - }; + const exists = mingw.libExists(arena, io, target, create_module.dirs.zig_lib, lib_name) catch |err| + fatal("failed to check zig installation for DLL import libs: {t}", .{err}); if (exists) { try create_module.windows_libs.put(arena, lib_name, {}); continue; @@ -3885,14 +3976,14 @@ fn createModule( if (fs.path.isAbsolute(lib_dir_arg)) { const stripped_dir = lib_dir_arg[fs.path.parsePath(lib_dir_arg).root.len..]; const full_path = try fs.path.join(arena, &[_][]const u8{ root, stripped_dir }); - addLibDirectoryWarn(&create_module.lib_directories, full_path); + addLibDirectoryWarn(io, &create_module.lib_directories, full_path); } else { - addLibDirectoryWarn(&create_module.lib_directories, lib_dir_arg); + addLibDirectoryWarn(io, &create_module.lib_directories, lib_dir_arg); } } } else { for (create_module.lib_dir_args.items) |lib_dir_arg| { - addLibDirectoryWarn(&create_module.lib_directories, lib_dir_arg); + addLibDirectoryWarn(io, &create_module.lib_directories, lib_dir_arg); } } create_module.lib_dir_args = undefined; // From here we use lib_directories instead. @@ -3915,9 +4006,8 @@ fn createModule( resolved_target.is_native_os and resolved_target.is_native_abi and create_module.want_native_include_dirs) { - var paths = std.zig.system.NativePaths.detect(arena, target) catch |err| { - fatal("unable to detect native system paths: {s}", .{@errorName(err)}); - }; + var paths = std.zig.system.NativePaths.detect(arena, io, target, environ_map) catch |err| + fatal("unable to detect native system paths: {t}", .{err}); for (paths.warnings.items) |warning| { warn("{s}", .{warning}); } @@ -3928,38 +4018,36 @@ fn createModule( try create_module.rpath_list.appendSlice(arena, paths.rpaths.items); try create_module.lib_directories.ensureUnusedCapacity(arena, paths.lib_dirs.items.len); - for (paths.lib_dirs.items) |path| addLibDirectoryWarn2(&create_module.lib_directories, path, true); + for (paths.lib_dirs.items) |path| addLibDirectoryWarn2(io, &create_module.lib_directories, path, true); } if (create_module.libc_paths_file) |paths_file| { - create_module.libc_installation = LibCInstallation.parse(arena, paths_file, target) catch |err| { - fatal("unable to parse libc paths file at path {s}: {s}", .{ - paths_file, @errorName(err), - }); - }; + create_module.libc_installation = LibCInstallation.parse(arena, io, paths_file, target) catch |err| + fatal("unable to parse libc paths file at path {s}: {t}", .{ paths_file, err }); } if (target.os.tag == .windows and (target.abi == .msvc or target.abi == .itanium) and any_name_queries_remaining) { if (create_module.libc_installation == null) { - create_module.libc_installation = LibCInstallation.findNative(.{ - .allocator = arena, + create_module.libc_installation = LibCInstallation.findNative(arena, io, .{ .verbose = true, .target = target, + .environ_map = environ_map, }) catch |err| { - fatal("unable to find native libc installation: {s}", .{@errorName(err)}); + fatal("unable to find native libc installation: {t}", .{err}); }; } try create_module.lib_directories.ensureUnusedCapacity(arena, 2); - addLibDirectoryWarn(&create_module.lib_directories, create_module.libc_installation.?.msvc_lib_dir.?); - addLibDirectoryWarn(&create_module.lib_directories, create_module.libc_installation.?.kernel32_lib_dir.?); + addLibDirectoryWarn(io, &create_module.lib_directories, create_module.libc_installation.?.msvc_lib_dir.?); + addLibDirectoryWarn(io, &create_module.lib_directories, create_module.libc_installation.?.kernel32_lib_dir.?); } // Destructively mutates but does not transfer ownership of `unresolved_link_inputs`. link.resolveInputs( gpa, arena, + io, target, &unresolved_link_inputs, &create_module.link_inputs, @@ -3993,7 +4081,6 @@ fn createModule( error.SanitizeThreadRequiresLibCpp => fatal("thread sanitization is (for now) implemented in C++, so it requires linking libc++", .{}), error.LibCRequiresLibUnwind => fatal("libc of the specified target requires linking libunwind", .{}), error.LibCppRequiresLibUnwind => fatal("libc++ requires linking libunwind", .{}), - error.OsRequiresLibC => fatal("the target OS requires using libc as the stable syscall interface", .{}), error.LibCppRequiresLibC => fatal("libc++ requires linking libc", .{}), error.LibUnwindRequiresLibC => fatal("libunwind requires linking libc", .{}), error.TargetCannotDynamicLink => fatal("dynamic linking unavailable on the specified target", .{}), @@ -4050,7 +4137,7 @@ fn createModule( for (cli_mod.deps) |dep| { const dep_index = create_module.modules.getIndex(dep.value) orelse fatal("module '{s}' depends on non-existent module '{s}'", .{ name, dep.key }); - const dep_mod = try createModule(gpa, arena, io, create_module, dep_index, mod, color); + const dep_mod = try createModule(gpa, arena, io, create_module, dep_index, mod, color, environ_map); try mod.deps.put(arena, dep.key, dep_mod); } @@ -4059,9 +4146,7 @@ fn createModule( fn saveState(comp: *Compilation, incremental: bool) void { if (incremental) { - comp.saveState() catch |err| { - warn("unable to save incremental compilation state: {s}", .{@errorName(err)}); - }; + comp.saveState() catch |err| warn("unable to save incremental compilation state: {t}", .{err}); } } @@ -4074,8 +4159,10 @@ fn serve( arg_mode: ArgMode, all_args: []const []const u8, runtime_args_start: ?usize, + environ_map: *process.Environ.Map, ) !void { const gpa = comp.gpa; + const io = comp.io; var server = try Server.init(.{ .in = in, @@ -4085,7 +4172,9 @@ fn serve( var child_pid: ?std.process.Child.Id = null; - const main_progress_node = std.Progress.start(.{}); + const main_progress_node = std.Progress.start(io, .{}); + defer main_progress_node.end(); + const file_system_inputs = comp.file_system_inputs.?; const IncrementalDebugServer = if (build_options.enable_debug_extensions and !builtin.single_threaded) @@ -4104,11 +4193,11 @@ fn serve( const hdr = try server.receiveMessage(); // Lock the debug server while handling the message. - if (comp.debugIncremental()) ids.mutex.lock(); - defer if (comp.debugIncremental()) ids.mutex.unlock(); + if (comp.debugIncremental()) try ids.mutex.lock(io); + defer if (comp.debugIncremental()) ids.mutex.unlock(io); switch (hdr.tag) { - .exit => return cleanExit(), + .exit => return cleanExit(io), .update => { tracy.frameMark(); file_system_inputs.clearRetainingCapacity(); @@ -4118,7 +4207,7 @@ fn serve( defer arena_instance.deinit(); const arena = arena_instance.allocator(); var output: Compilation.CImportResult = undefined; - try cmdTranslateC(comp, arena, &output, file_system_inputs, main_progress_node); + try cmdTranslateC(comp, arena, &output, file_system_inputs, main_progress_node, environ_map); defer output.deinit(gpa); if (file_system_inputs.items.len != 0) { @@ -4318,6 +4407,7 @@ fn runOrTest( all_args: []const []const u8, runtime_args_start: ?usize, link_libc: bool, + environ_map: *process.Environ.Map, ) !void { const raw_emit_bin = comp.emit_bin orelse return; const exe_path = switch (comp.cache_use) { @@ -4343,7 +4433,7 @@ fn runOrTest( try argv.append(exe_path); if (arg_mode == .zig_test) { try argv.append( - try std.fmt.allocPrint(arena, "--seed=0x{x}", .{std.crypto.random.int(u32)}), + try std.fmt.allocPrint(arena, "--seed=0x{x}", .{randInt(io, u32)}), ); } } else { @@ -4354,77 +4444,90 @@ fn runOrTest( if (runtime_args_start) |i| { try argv.appendSlice(all_args[i..]); } - var env_map = try process.getEnvMap(arena); - try env_map.put("ZIG_EXE", self_exe_path); + try environ_map.put("ZIG_EXE", self_exe_path); // We do not execve for tests because if the test fails we want to print // the error message and invocation below. - if (process.can_execv and arg_mode == .run) { - // execv releases the locks; no need to destroy the Compilation here. - std.debug.lockStdErr(); - const err = process.execve(gpa, argv.items, &env_map); - std.debug.unlockStdErr(); + if (process.can_replace and arg_mode == .run) { + // process replacement releases the locks; no need to destroy the Compilation here. + _ = try io.lockStderr(&.{}, .no_color); + const err = process.replace(io, .{ .argv = argv.items, .environ_map = environ_map }); + io.unlockStderr(); try warnAboutForeignBinaries(io, arena, arg_mode, target, link_libc); const cmd = try std.mem.join(arena, " ", argv.items); - fatal("the following command failed to execve with '{s}':\n{s}", .{ @errorName(err), cmd }); - } else if (process.can_spawn) { - var child = std.process.Child.init(argv.items, gpa); - child.env_map = &env_map; - child.stdin_behavior = .Inherit; - child.stdout_behavior = .Inherit; - child.stderr_behavior = .Inherit; - + fatal("the following command failed to execve with '{t}':\n{s}", .{ err, cmd }); + } else if (!process.can_spawn) { + const cmd = try std.mem.join(arena, " ", argv.items); + fatal("the following command cannot be executed ({t} does not support spawning a child process):\n{s}", .{ + native_os, cmd, + }); + } + const term_result = (term: { // Here we release all the locks associated with the Compilation so // that whatever this child process wants to do won't deadlock. comp.destroy(); comp_destroyed.* = true; - const term_result = t: { - std.debug.lockStdErr(); - defer std.debug.unlockStdErr(); - break :t child.spawnAndWait(); - }; - const term = term_result catch |err| { - try warnAboutForeignBinaries(io, arena, arg_mode, target, link_libc); - const cmd = try std.mem.join(arena, " ", argv.items); - fatal("the following command failed with '{s}':\n{s}", .{ @errorName(err), cmd }); - }; - switch (arg_mode) { - .run, .build => { - switch (term) { - .Exited => |code| { - if (code == 0) { - return cleanExit(); - } else { - process.exit(code); - } - }, - else => { - process.exit(1); - }, - } - }, - .zig_test => { - switch (term) { - .Exited => |code| { - if (code == 0) { - return cleanExit(); - } else { - const cmd = try std.mem.join(arena, " ", argv.items); - fatal("the following test command failed with exit code {d}:\n{s}", .{ code, cmd }); - } - }, - else => { - const cmd = try std.mem.join(arena, " ", argv.items); - fatal("the following test command crashed:\n{s}", .{cmd}); - }, - } - }, - else => unreachable, - } - } else { + _ = try io.lockStderr(&.{}, .no_color); + defer io.unlockStderr(); + + var child = std.process.spawn(io, .{ + .argv = argv.items, + .environ_map = environ_map, + .stdin = .inherit, + .stdout = .inherit, + .stderr = .inherit, + }) catch |err| break :term err; + defer child.kill(io); + + break :term child.wait(io); + }); + + const term = term_result catch |err| { + try warnAboutForeignBinaries(io, arena, arg_mode, target, link_libc); const cmd = try std.mem.join(arena, " ", argv.items); - fatal("the following command cannot be executed ({s} does not support spawning a child process):\n{s}", .{ @tagName(native_os), cmd }); + fatal("the following command failed with {t}:\n{s}", .{ err, cmd }); + }; + switch (arg_mode) { + .run, .build => { + switch (term) { + .exited => |code| { + if (code == 0) { + return cleanExit(io); + } else { + process.exit(code); + } + }, + .signal => |sig| { + const cmd = try std.mem.join(arena, " ", argv.items); + fatal("the following command terminated with signal {t}:\n{s}", .{ sig, cmd }); + }, + else => { + process.exit(1); + }, + } + }, + .zig_test => { + switch (term) { + .exited => |code| { + if (code == 0) { + return cleanExit(io); + } else { + const cmd = try std.mem.join(arena, " ", argv.items); + fatal("the following test command failed with exit code {d}:\n{s}", .{ code, cmd }); + } + }, + .signal => |sig| { + const cmd = try std.mem.join(arena, " ", argv.items); + fatal("the following test command terminated with signal {t}:\n{s}", .{ sig, cmd }); + }, + else => { + const cmd = try std.mem.join(arena, " ", argv.items); + fatal("the following test command crashed:\n{s}", .{cmd}); + }, + } + }, + else => unreachable, } } @@ -4437,6 +4540,7 @@ fn runOrTestHotSwap( all_args: []const []const u8, runtime_args_start: ?usize, ) !std.process.Child.Id { + const io = comp.io; const lf = comp.bin_file.?; const exe_path = switch (builtin.target.os.tag) { @@ -4445,7 +4549,7 @@ fn runOrTestHotSwap( // tmp zig-cache and use it to spawn the child process. This way we are free to update // the binary with each requested hot update. .windows => blk: { - try lf.emit.root_dir.handle.copyFile(lf.emit.sub_path, comp.dirs.local_cache.handle, lf.emit.sub_path, .{}); + try lf.emit.root_dir.handle.copyFile(lf.emit.sub_path, comp.dirs.local_cache.handle, lf.emit.sub_path, io, .{}); break :blk try fs.path.join(gpa, &.{ comp.dirs.local_cache.path orelse ".", lf.emit.sub_path }); }, @@ -4486,49 +4590,21 @@ fn runOrTestHotSwap( try argv.appendSlice(all_args[i..]); } - switch (builtin.target.os.tag) { - .macos => { - const PosixSpawn = @import("DarwinPosixSpawn.zig"); - - var attr = try PosixSpawn.Attr.init(); - defer attr.deinit(); - - // ASLR is probably a good default for better debugging experience/programming - // with hot-code updates in mind. However, we can also make it work with ASLR on. - try attr.set(.{ - .SETSIGDEF = true, - .SETSIGMASK = true, - .DISABLE_ASLR = true, - }); - - var arena_allocator = std.heap.ArenaAllocator.init(gpa); - defer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); - - const argv_buf = try arena.allocSentinel(?[*:0]u8, argv.items.len, null); - for (argv.items, 0..) |arg, i| argv_buf[i] = (try arena.dupeZ(u8, arg)).ptr; - - const pid = try PosixSpawn.spawn(argv.items[0], null, attr, argv_buf, std.c.environ); - return pid; - }, - else => { - var child = std.process.Child.init(argv.items, gpa); - - child.stdin_behavior = .Inherit; - child.stdout_behavior = .Inherit; - child.stderr_behavior = .Inherit; - - try child.spawn(); - - return child.id; - }, - } + var child = try std.process.spawn(io, .{ + .argv = argv.items, + .stdin = .inherit, + .stdout = .inherit, + .stderr = .inherit, + }); + return child.id.?; } const UpdateModuleError = Compilation.UpdateError || error{ /// The update caused compile errors. The error bundle has already been /// reported to the user by being rendered to stderr. CompileErrorsReported, + /// Error occurred printing compilation errors to stderr. + PrintingErrorsFailed, }; fn updateModule(comp: *Compilation, color: Color, prog_node: std.Progress.Node) UpdateModuleError!void { try comp.update(prog_node); @@ -4537,7 +4613,11 @@ fn updateModule(comp: *Compilation, color: Color, prog_node: std.Progress.Node) defer errors.deinit(comp.gpa); if (errors.errorMessageCount() > 0) { - errors.renderToStdErr(.{}, color); + const io = comp.io; + errors.renderToStderr(io, .{}, color) catch |err| switch (err) { + error.Canceled => |e| return e, + else => return error.PrintingErrorsFailed, + }; return error.CompileErrorsReported; } } @@ -4548,6 +4628,7 @@ fn cmdTranslateC( fancy_output: ?*Compilation.CImportResult, file_system_inputs: ?*std.ArrayList(u8), prog_node: std.Progress.Node, + environ_map: *process.Environ.Map, ) !void { dev.check(.translate_c_command); @@ -4581,6 +4662,7 @@ fn cmdTranslateC( translated_basename, comp.root_mod, prog_node, + environ_map, ); if (result.errors.errorMessageCount() != 0) { @@ -4590,7 +4672,7 @@ fn cmdTranslateC( return; } else { const color: Color = .auto; - result.errors.renderToStdErr(.{}, color); + result.errors.renderToStderr(io, .{}, color) catch {}; process.exit(1); } } @@ -4605,7 +4687,7 @@ fn cmdTranslateC( } else { const hex_digest = Cache.binToHex(result.digest); const out_zig_path = try fs.path.join(arena, &.{ "o", &hex_digest, translated_basename }); - const zig_file = comp.dirs.local_cache.handle.openFile(out_zig_path, .{}) catch |err| { + const zig_file = comp.dirs.local_cache.handle.openFile(io, out_zig_path, .{}) catch |err| { const path = comp.dirs.local_cache.path orelse "."; fatal("unable to open cached translated zig file '{s}{s}{s}': {s}", .{ path, @@ -4614,12 +4696,12 @@ fn cmdTranslateC( @errorName(err), }); }; - defer zig_file.close(); - var stdout_writer = fs.File.stdout().writer(&stdout_buffer); + defer zig_file.close(io); + var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer); var file_reader = zig_file.reader(io, &.{}); _ = try stdout_writer.interface.sendFileAll(&file_reader, .unlimited); try stdout_writer.interface.flush(); - return cleanExit(); + return cleanExit(io); } } @@ -4628,10 +4710,11 @@ pub fn translateC( arena: Allocator, io: Io, argv: []const []const u8, + environ_map: *const process.Environ.Map, prog_node: std.Progress.Node, capture: ?*[]u8, ) !void { - try jitCmd(gpa, arena, io, argv, .{ + try jitCmd(gpa, arena, io, argv, environ_map, .{ .cmd_name = "translate-c", .root_src_path = "translate-c/main.zig", .depend_on_aro = true, @@ -4653,7 +4736,7 @@ const usage_init = \\ ; -fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { +fn cmdInit(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !void { dev.check(.init_command); var template: enum { example, minimal } = .example; @@ -4665,8 +4748,8 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { if (mem.eql(u8, arg, "-m") or mem.eql(u8, arg, "--minimal")) { template = .minimal; } else if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { - try fs.File.stdout().writeAll(usage_init); - return cleanExit(); + try Io.File.stdout().writeStreamingAll(io, usage_init); + return cleanExit(io); } else { fatal("unrecognized parameter: '{s}'", .{arg}); } @@ -4680,12 +4763,13 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { const cwd_basename = fs.path.basename(cwd_path); const sanitized_root_name = try sanitizeExampleName(arena, cwd_basename); - const fingerprint: Package.Fingerprint = .generate(sanitized_root_name); + const rng: std.Random.IoSource = .{ .io = io }; + const fingerprint: Package.Fingerprint = .generate(rng.interface(), sanitized_root_name); switch (template) { .example => { - var templates = findTemplates(gpa, arena); - defer templates.deinit(); + var templates = findTemplates(gpa, arena, io); + defer templates.deinit(io); const s = fs.path.sep_str; const template_paths = [_][]const u8{ @@ -4697,7 +4781,7 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { var ok_count: usize = 0; for (template_paths) |template_path| { - if (templates.write(arena, fs.cwd(), sanitized_root_name, template_path, fingerprint)) |_| { + if (templates.write(arena, io, Io.Dir.cwd(), sanitized_root_name, template_path, fingerprint)) |_| { std.log.info("created {s}", .{template_path}); ok_count += 1; } else |err| switch (err) { @@ -4711,10 +4795,10 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { if (ok_count == template_paths.len) { std.log.info("see `zig build --help` for a menu of options", .{}); } - return cleanExit(); + return cleanExit(io); }, .minimal => { - writeSimpleTemplateFile(Package.Manifest.basename, + writeSimpleTemplateFile(io, Package.Manifest.basename, \\.{{ \\ .name = .{s}, \\ .version = "0.0.1", @@ -4731,7 +4815,7 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { else => fatal("failed to create '{s}': {s}", .{ Package.Manifest.basename, @errorName(err) }), error.PathAlreadyExists => fatal("refusing to overwrite '{s}'", .{Package.Manifest.basename}), }; - writeSimpleTemplateFile(Package.build_zig_basename, + writeSimpleTemplateFile(io, Package.build_zig_basename, \\const std = @import("std"); \\ \\pub fn build(b: *std.Build) void {{ @@ -4744,11 +4828,11 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { // their `build.zig.zon` *after* writing their `build.zig`. So this one isn't fatal. error.PathAlreadyExists => { std.log.info("successfully populated '{s}', preserving existing '{s}'", .{ Package.Manifest.basename, Package.build_zig_basename }); - return cleanExit(); + return cleanExit(io); }, }; std.log.info("successfully populated '{s}' and '{s}'", .{ Package.Manifest.basename, Package.build_zig_basename }); - return cleanExit(); + return cleanExit(io); }, } } @@ -4788,21 +4872,21 @@ test sanitizeExampleName { try std.testing.expectEqualStrings("test_project", try sanitizeExampleName(arena, "test project")); } -fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !void { +fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, environ_map: *process.Environ.Map) !void { dev.check(.build_command); var build_file: ?[]const u8 = null; - var override_lib_dir: ?[]const u8 = try EnvVar.ZIG_LIB_DIR.get(arena); - var override_global_cache_dir: ?[]const u8 = try EnvVar.ZIG_GLOBAL_CACHE_DIR.get(arena); - var override_local_cache_dir: ?[]const u8 = try EnvVar.ZIG_LOCAL_CACHE_DIR.get(arena); - var override_build_runner: ?[]const u8 = try EnvVar.ZIG_BUILD_RUNNER.get(arena); + var override_lib_dir: ?[]const u8 = EnvVar.ZIG_LIB_DIR.get(environ_map); + var override_global_cache_dir: ?[]const u8 = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map); + var override_local_cache_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_CACHE_DIR.get(environ_map); + var override_build_runner: ?[]const u8 = EnvVar.ZIG_BUILD_RUNNER.get(environ_map); var child_argv = std.array_list.Managed([]const u8).init(arena); var reference_trace: ?u32 = null; var debug_compile_errors = false; var verbose_link = (native_os != .wasi or builtin.link_libc) and - EnvVar.ZIG_VERBOSE_LINK.isSet(); + EnvVar.ZIG_VERBOSE_LINK.isSet(environ_map); var verbose_cc = (native_os != .wasi or builtin.link_libc) and - EnvVar.ZIG_VERBOSE_CC.isSet(); + EnvVar.ZIG_VERBOSE_CC.isSet(environ_map); var verbose_air = false; var verbose_intern_pool = false; var verbose_generic_instances = false; @@ -4819,7 +4903,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) const argv_index_exe = child_argv.items.len; _ = try child_argv.addOne(); - const self_exe_path = try fs.selfExePathAlloc(arena); + const self_exe_path = try process.executablePathAlloc(io, arena); try child_argv.append(self_exe_path); const argv_index_zig_lib_dir = child_argv.items.len; @@ -4836,7 +4920,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) try child_argv.appendSlice(&.{ "--seed", - try std.fmt.allocPrint(arena, "0x{x}", .{std.crypto.random.int(u32)}), + try std.fmt.allocPrint(arena, "0x{x}", .{randInt(io, u32)}), }); const argv_index_seed = child_argv.items.len - 1; @@ -4854,7 +4938,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) // the strategy is to choose a temporary file name ahead of time, and then // read this file in the parent to obtain the results, in the case the child // exits with code 3. - const results_tmp_file_nonce = std.fmt.hex(std.crypto.random.int(u64)); + const results_tmp_file_nonce = std.fmt.hex(randInt(io, u64)); try child_argv.append("-Z" ++ results_tmp_file_nonce); var color: Color = .auto; @@ -4999,8 +5083,8 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) } const work_around_btrfs_bug = native_os == .linux and - EnvVar.ZIG_BTRFS_WORKAROUND.isSet(); - const root_prog_node = std.Progress.start(.{ + EnvVar.ZIG_BTRFS_WORKAROUND.isSet(environ_map); + const root_prog_node = std.Progress.start(io, .{ .disable_printing = (color == .off), .root_name = "Compile Build Script", }); @@ -5035,14 +5119,14 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) const paths_file = debug_libc_paths_file orelse break :lci null; if (!build_options.enable_debug_extensions) unreachable; const lci = try arena.create(LibCInstallation); - lci.* = try .parse(arena, paths_file, &resolved_target.result); + lci.* = try .parse(arena, io, paths_file, &resolved_target.result); break :lci lci; }; process.raiseFileDescriptorLimit(); const cwd_path = try introspect.getResolvedCwd(arena); - const build_root = try findBuildRoot(arena, .{ + const build_root = try findBuildRoot(arena, io, .{ .cwd_path = cwd_path, .build_file = build_file, }); @@ -5050,30 +5134,29 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) // This `init` calls `fatal` on error. var dirs: Compilation.Directories = .init( arena, + io, override_lib_dir, override_global_cache_dir, .{ .override = path: { if (override_local_cache_dir) |d| break :path d; break :path try build_root.directory.join(arena, &.{introspect.default_local_zig_cache_basename}); } }, - {}, + .empty, self_exe_path, + environ_map, ); - defer dirs.deinit(); + defer dirs.deinit(io); child_argv.items[argv_index_zig_lib_dir] = dirs.zig_lib.path orelse cwd_path; child_argv.items[argv_index_build_file] = build_root.directory.path orelse cwd_path; child_argv.items[argv_index_global_cache_dir] = dirs.global_cache.path orelse cwd_path; child_argv.items[argv_index_cache_dir] = dirs.local_cache.path orelse cwd_path; - var thread_pool: ThreadPool = undefined; - try thread_pool.init(.{ - .allocator = gpa, - .n_jobs = @min(@max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1), std.math.maxInt(Zcu.PerThread.IdBacking)), - .track_ids = true, - .stack_size = thread_stack_size, - }); - defer thread_pool.deinit(); + const thread_limit = @min( + @max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1), + std.math.maxInt(Zcu.PerThread.IdBacking), + ); + setThreadLimit(thread_limit); // Dummy http client that is not actually used when fetch_command is unsupported. // Prevents bootstrap from depending on a bunch of unnecessary stuff. @@ -5131,8 +5214,8 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) .parent = root_mod, }); - var cleanup_build_dir: ?fs.Dir = null; - defer if (cleanup_build_dir) |*dir| dir.close(); + var cleanup_build_dir: ?Io.Dir = null; + defer if (cleanup_build_dir) |*dir| dir.close(io); if (dev.env.supports(.fetch_command)) { const fetch_prog_node = root_prog_node.start("Fetch Packages", 0); @@ -5154,7 +5237,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) if (system_pkg_dir_path) |p| { job_queue.global_cache = .{ .path = p, - .handle = fs.cwd().openDir(p, .{}) catch |err| { + .handle = Io.Dir.cwd().openDir(io, p, .{}) catch |err| { fatal("unable to open system package directory '{s}': {s}", .{ p, @errorName(err), }); @@ -5163,7 +5246,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) job_queue.read_only = true; cleanup_build_dir = job_queue.global_cache.handle; } else { - try http_client.initDefaultProxies(arena); + try http_client.initDefaultProxies(arena, environ_map); } try job_queue.all_fetches.ensureUnusedCapacity(gpa, 1); @@ -5207,23 +5290,24 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ); job_queue.group.async(io, Package.Fetch.workerRun, .{ &fetch, "root" }); - job_queue.group.wait(io); + try job_queue.group.await(io); try job_queue.consolidateErrors(); if (fetch.error_bundle.root_list.items.len > 0) { var errors = try fetch.error_bundle.toOwnedBundle(""); - errors.renderToStdErr(.{}, color); + errors.renderToStderr(io, .{}, color) catch {}; process.exit(1); } - if (fetch_only) return cleanExit(); + if (fetch_only) return cleanExit(io); var source_buf = std.array_list.Managed(u8).init(gpa); defer source_buf.deinit(); try job_queue.createDependenciesSource(&source_buf); const deps_mod = try createDependenciesModule( arena, + io, source_buf.items, root_mod, dirs, @@ -5285,6 +5369,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) } } else try createEmptyDependenciesModule( arena, + io, root_mod, dirs, config, @@ -5302,7 +5387,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) .main_mod = build_mod, .emit_bin = .yes_cache, .self_exe_path = self_exe_path, - .thread_pool = &thread_pool, + .thread_limit = thread_limit, .verbose_cc = verbose_cc, .verbose_link = verbose_link, .verbose_air = verbose_air, @@ -5315,6 +5400,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) .cache_mode = .whole, .reference_trace = reference_trace, .debug_compile_errors = debug_compile_errors, + .environ_map = environ_map, }) catch |err| switch (err) { error.CreateFail => fatal("failed to create compilation: {f}", .{create_diag}), else => fatal("failed to create compilation: {s}", .{@errorName(err)}), @@ -5336,82 +5422,81 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) }); } - if (process.can_spawn) { - var child = std.process.Child.init(child_argv.items, gpa); - child.stdin_behavior = .Inherit; - child.stdout_behavior = .Inherit; - child.stderr_behavior = .Inherit; - - const term = t: { - std.debug.lockStdErr(); - defer std.debug.unlockStdErr(); - break :t child.spawnAndWait() catch |err| { - fatal("failed to spawn build runner {s}: {s}", .{ child_argv.items[0], @errorName(err) }); - }; - }; - - switch (term) { - .Exited => |code| { - if (code == 0) return cleanExit(); - // Indicates that the build runner has reported compile errors - // and this parent process does not need to report any further - // diagnostics. - if (code == 2) process.exit(2); - - if (code == 3) { - if (!dev.env.supports(.fetch_command)) process.exit(3); - // Indicates the configure phase failed due to missing lazy - // dependencies and stdout contains the hashes of the ones - // that are missing. - const s = fs.path.sep_str; - const tmp_sub_path = "tmp" ++ s ++ results_tmp_file_nonce; - const stdout = dirs.local_cache.handle.readFileAlloc(tmp_sub_path, arena, .limited(50 * 1024 * 1024)) catch |err| { - fatal("unable to read results of configure phase from '{f}{s}': {s}", .{ - dirs.local_cache, tmp_sub_path, @errorName(err), + if (!process.can_spawn) { + const cmd = try std.mem.join(arena, " ", child_argv.items); + fatal("the following command cannot be executed ({t} does not support spawning a child process):\n{s}", .{ native_os, cmd }); + } + switch (term: { + _ = try io.lockStderr(&.{}, .no_color); + defer io.unlockStderr(); + var child = std.process.spawn(io, .{ + .argv = child_argv.items, + }) catch |err| fatal("failed to spawn build runner {s}: {t}", .{ child_argv.items[0], err }); + defer child.kill(io); + break :term child.wait(io) catch |err| + fatal("failed to wait build runner {s}: {t}", .{ child_argv.items[0], err }); + }) { + .exited => |code| { + if (code == 0) return cleanExit(io); + // Indicates that the build runner has reported compile errors + // and this parent process does not need to report any further + // diagnostics. + if (code == 2) process.exit(2); + + if (code == 3) { + if (!dev.env.supports(.fetch_command)) process.exit(3); + // Indicates the configure phase failed due to missing lazy + // dependencies and stdout contains the hashes of the ones + // that are missing. + const s = fs.path.sep_str; + const tmp_sub_path = "tmp" ++ s ++ results_tmp_file_nonce; + const stdout = dirs.local_cache.handle.readFileAlloc(io, tmp_sub_path, arena, .limited(50 * 1024 * 1024)) catch |err| { + fatal("unable to read results of configure phase from '{f}{s}': {t}", .{ + dirs.local_cache, tmp_sub_path, err, + }); + }; + dirs.local_cache.handle.deleteFile(io, tmp_sub_path) catch {}; + + var it = mem.splitScalar(u8, stdout, '\n'); + var any_errors = false; + while (it.next()) |hash| { + if (hash.len == 0) continue; + if (hash.len > Package.Hash.max_len) { + std.log.err("invalid digest (length {d} exceeds maximum): '{s}'", .{ + hash.len, hash, }); - }; - dirs.local_cache.handle.deleteFile(tmp_sub_path) catch {}; - - var it = mem.splitScalar(u8, stdout, '\n'); - var any_errors = false; - while (it.next()) |hash| { - if (hash.len == 0) continue; - if (hash.len > Package.Hash.max_len) { - std.log.err("invalid digest (length {d} exceeds maximum): '{s}'", .{ - hash.len, hash, - }); - any_errors = true; - continue; - } - try unlazy_set.put(arena, .fromSlice(hash), {}); + any_errors = true; + continue; } - if (any_errors) process.exit(3); - if (system_pkg_dir_path) |p| { - // In this mode, the system needs to provide these packages; they - // cannot be fetched by Zig. - for (unlazy_set.keys()) |*hash| { - std.log.err("lazy dependency package not found: {s}" ++ s ++ "{s}", .{ - p, hash.toSlice(), - }); - } - std.log.info("remote package fetching disabled due to --system mode", .{}); - std.log.info("dependencies might be avoidable depending on build configuration", .{}); - process.exit(3); + try unlazy_set.put(arena, .fromSlice(hash), {}); + } + if (any_errors) process.exit(3); + if (system_pkg_dir_path) |p| { + // In this mode, the system needs to provide these packages; they + // cannot be fetched by Zig. + for (unlazy_set.keys()) |*hash| { + std.log.err("lazy dependency package not found: {s}" ++ s ++ "{s}", .{ + p, hash.toSlice(), + }); } - continue; + std.log.info("remote package fetching disabled due to --system mode", .{}); + std.log.info("dependencies might be avoidable depending on build configuration", .{}); + process.exit(3); } + continue; + } - const cmd = try std.mem.join(arena, " ", child_argv.items); - fatal("the following build command failed with exit code {d}:\n{s}", .{ code, cmd }); - }, - else => { - const cmd = try std.mem.join(arena, " ", child_argv.items); - fatal("the following build command crashed:\n{s}", .{cmd}); - }, - } - } else { - const cmd = try std.mem.join(arena, " ", child_argv.items); - fatal("the following command cannot be executed ({s} does not support spawning a child process):\n{s}", .{ @tagName(native_os), cmd }); + const cmd = try std.mem.join(arena, " ", child_argv.items); + fatal("the following build command failed with exit code {d}:\n{s}", .{ code, cmd }); + }, + .signal => |sig| { + const cmd = try std.mem.join(arena, " ", child_argv.items); + fatal("the following build command terminated with signal {t}:\n{s}", .{ sig, cmd }); + }, + else => { + const cmd = try std.mem.join(arena, " ", child_argv.items); + fatal("the following build command crashed:\n{s}", .{cmd}); + }, } } } @@ -5434,14 +5519,16 @@ fn jitCmd( arena: Allocator, io: Io, args: []const []const u8, + environ_map: *const process.Environ.Map, options: JitCmdOptions, ) !void { dev.check(.jit_command); const color: Color = .auto; - const root_prog_node = if (options.progress_node) |node| node else std.Progress.start(.{ + const root_prog_node = if (options.progress_node) |node| node else std.Progress.start(io, .{ .disable_printing = (color == .off), }); + defer root_prog_node.end(); const target_query: std.Target.Query = .{}; const resolved_target: Package.Module.ResolvedTarget = .{ @@ -5451,37 +5538,35 @@ fn jitCmd( .is_explicit_dynamic_linker = false, }; - const self_exe_path = fs.selfExePathAlloc(arena) catch |err| { - fatal("unable to find self exe path: {s}", .{@errorName(err)}); - }; + const self_exe_path = process.executablePathAlloc(io, arena) catch |err| + fatal("unable to find self exe path: {t}", .{err}); - const optimize_mode: std.builtin.OptimizeMode = if (EnvVar.ZIG_DEBUG_CMD.isSet()) + const optimize_mode: std.builtin.OptimizeMode = if (EnvVar.ZIG_DEBUG_CMD.isSet(environ_map)) .Debug else .ReleaseFast; const strip = optimize_mode != .Debug; - const override_lib_dir: ?[]const u8 = try EnvVar.ZIG_LIB_DIR.get(arena); - const override_global_cache_dir: ?[]const u8 = try EnvVar.ZIG_GLOBAL_CACHE_DIR.get(arena); + const override_lib_dir: ?[]const u8 = EnvVar.ZIG_LIB_DIR.get(environ_map); + const override_global_cache_dir: ?[]const u8 = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map); // This `init` calls `fatal` on error. var dirs: Compilation.Directories = .init( arena, + io, override_lib_dir, override_global_cache_dir, .global, - if (native_os == .wasi) wasi_preopens, + preopens, self_exe_path, + environ_map, ); - defer dirs.deinit(); - - var thread_pool: ThreadPool = undefined; - try thread_pool.init(.{ - .allocator = gpa, - .n_jobs = @min(@max(std.Thread.getCpuCount() catch 1, 1), std.math.maxInt(Zcu.PerThread.IdBacking)), - .track_ids = true, - .stack_size = thread_stack_size, - }); - defer thread_pool.deinit(); + defer dirs.deinit(io); + + const thread_limit = @min( + @max(std.Thread.getCpuCount() catch 1, 1), + std.math.maxInt(Zcu.PerThread.IdBacking), + ); + setThreadLimit(thread_limit); var child_argv: std.ArrayList([]const u8) = .empty; try child_argv.ensureUnusedCapacity(arena, args.len + 4); @@ -5545,8 +5630,9 @@ fn jitCmd( .main_mod = root_mod, .emit_bin = .yes_cache, .self_exe_path = self_exe_path, - .thread_pool = &thread_pool, + .thread_limit = thread_limit, .cache_mode = .whole, + .environ_map = environ_map, }) catch |err| switch (err) { error.CreateFail => fatal("failed to create compilation: {f}", .{create_diag}), else => fatal("failed to create compilation: {s}", .{@errorName(err)}), @@ -5554,7 +5640,7 @@ fn jitCmd( defer comp.destroy(); if (options.server) { - var stdout_writer = fs.File.stdout().writer(&stdout_buffer); + var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer); var server: std.zig.Server = .{ .out = &stdout_writer.interface, .in = undefined, // won't be receiving messages @@ -5592,45 +5678,54 @@ fn jitCmd( child_argv.appendSliceAssumeCapacity(args); - if (process.can_execv and options.capture == null) { - if (EnvVar.ZIG_DEBUG_CMD.isSet()) { + if (process.can_replace and options.capture == null) { + if (EnvVar.ZIG_DEBUG_CMD.isSet(environ_map)) { const cmd = try std.mem.join(arena, " ", child_argv.items); std.debug.print("{s}\n", .{cmd}); } - const err = process.execv(gpa, child_argv.items); + const err = process.replace(io, .{ .argv = child_argv.items, .environ_map = environ_map }); const cmd = try std.mem.join(arena, " ", child_argv.items); fatal("the following command failed to execve with '{t}':\n{s}", .{ err, cmd }); } if (!process.can_spawn) { const cmd = try std.mem.join(arena, " ", child_argv.items); - fatal("the following command cannot be executed ({s} does not support spawning a child process):\n{s}", .{ - @tagName(native_os), cmd, + fatal("the following command cannot be executed ({t} does not support spawning a child process):\n{s}", .{ + native_os, cmd, }); } - var child = std.process.Child.init(child_argv.items, gpa); - child.stdin_behavior = .Inherit; - child.stdout_behavior = if (options.capture == null) .Inherit else .Pipe; - child.stderr_behavior = .Inherit; - - try child.spawn(); - - if (options.capture) |ptr| { - var stdout_reader = child.stdout.?.readerStreaming(io, &.{}); - ptr.* = try stdout_reader.interface.allocRemaining(arena, .limited(std.math.maxInt(u32))); - } + switch (t: { + _ = try io.lockStderr(&.{}, .no_color); + defer io.unlockStderr(); + + var child = std.process.spawn(io, .{ + .argv = child_argv.items, + .stdin = .inherit, + .stdout = if (options.capture == null) .inherit else .pipe, + .stderr = .inherit, + }) catch |err| fatal("failed to spawn {s}: {t}", .{ child_argv.items[0], err }); + defer child.kill(io); + + if (options.capture) |ptr| { + var stdout_reader = child.stdout.?.readerStreaming(io, &.{}); + ptr.* = try stdout_reader.interface.allocRemaining(arena, .limited(std.math.maxInt(u32))); + } - const term = try child.wait(); - switch (term) { - .Exited => |code| { + break :t try child.wait(io); + }) { + .exited => |code| { if (code == 0) { if (options.capture != null) return; - return cleanExit(); + return cleanExit(io); } const cmd = try std.mem.join(arena, " ", child_argv.items); fatal("the following build command failed with exit code {d}:\n{s}", .{ code, cmd }); }, + .signal => |sig| { + const cmd = try std.mem.join(arena, " ", child_argv.items); + fatal("the following build command terminated with signal {t}:\n{s}", .{ sig, cmd }); + }, else => { const cmd = try std.mem.join(arena, " ", child_argv.items); fatal("the following build command crashed:\n{s}", .{cmd}); @@ -5746,12 +5841,12 @@ pub fn lldMain( return @intFromBool(!ok); } -const ArgIteratorResponseFile = process.ArgIteratorGeneral(.{ .comments = true, .single_quotes = true }); +const ArgIteratorResponseFile = process.Args.IteratorGeneral(.{ .comments = true, .single_quotes = true }); /// Initialize the arguments from a Response File. "*.rsp" -fn initArgIteratorResponseFile(allocator: Allocator, resp_file_path: []const u8) !ArgIteratorResponseFile { +fn initArgIteratorResponseFile(allocator: Allocator, io: Io, resp_file_path: []const u8) !ArgIteratorResponseFile { const max_bytes = 10 * 1024 * 1024; // 10 MiB of command line arguments is a reasonable limit - const cmd_line = try fs.cwd().readFileAlloc(resp_file_path, allocator, .limited(max_bytes)); + const cmd_line = try Io.Dir.cwd().readFileAlloc(io, resp_file_path, allocator, .limited(max_bytes)); errdefer allocator.free(cmd_line); return ArgIteratorResponseFile.initTakeOwnership(allocator, cmd_line); @@ -5879,7 +5974,7 @@ pub const ClangArgIterator = struct { }; } - fn next(self: *ClangArgIterator) !void { + fn next(self: *ClangArgIterator, io: Io) !void { assert(self.has_next); assert(self.next_index < self.argv.len); // In this state we know that the parameter we are looking at is a root parameter @@ -5897,10 +5992,8 @@ pub const ClangArgIterator = struct { const arena = self.arena; const resp_file_path = arg[1..]; - self.arg_iterator_response_file = - initArgIteratorResponseFile(arena, resp_file_path) catch |err| { - fatal("unable to read response file '{s}': {s}", .{ resp_file_path, @errorName(err) }); - }; + self.arg_iterator_response_file = initArgIteratorResponseFile(arena, io, resp_file_path) catch |err| + fatal("unable to read response file '{s}': {t}", .{ resp_file_path, err }); // NOTE: The ArgIteratorResponseFile returns tokens from next() that are slices of an // internal buffer. This internal buffer is arena allocated, so it is not cleaned up here. @@ -6087,8 +6180,8 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void { const arg = args[i]; if (mem.startsWith(u8, arg, "-")) { if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { - try fs.File.stdout().writeAll(usage_ast_check); - return cleanExit(); + try Io.File.stdout().writeStreamingAll(io, usage_ast_check); + return cleanExit(io); } else if (mem.eql(u8, arg, "-t")) { want_output_text = true; } else if (mem.eql(u8, arg, "--zon")) { @@ -6115,12 +6208,12 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void { const display_path = zig_source_path orelse ""; const source: [:0]const u8 = s: { var f = if (zig_source_path) |p| file: { - break :file fs.cwd().openFile(p, .{}) catch |err| { + break :file Io.Dir.cwd().openFile(io, p, .{}) catch |err| { fatal("unable to open file '{s}' for ast-check: {s}", .{ display_path, @errorName(err) }); }; - } else fs.File.stdin(); - defer if (zig_source_path != null) f.close(); - var file_reader: fs.File.Reader = f.reader(io, &stdin_buffer); + } else Io.File.stdin(); + defer if (zig_source_path != null) f.close(io); + var file_reader: Io.File.Reader = f.reader(io, &stdin_buffer); break :s std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err| { fatal("unable to load file '{s}' for ast-check: {s}", .{ display_path, @errorName(err) }); }; @@ -6138,7 +6231,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void { const tree = try Ast.parse(arena, source, mode); - var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer); + var stdout_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer); const stdout_bw = &stdout_writer.interface; switch (mode) { .zig => { @@ -6149,7 +6242,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void { try wip_errors.init(arena); try wip_errors.addZirErrorMessages(zir, tree, source, display_path); var error_bundle = try wip_errors.toOwnedBundle(""); - error_bundle.renderToStdErr(.{}, color); + try error_bundle.renderToStderr(io, .{}, color); if (zir.loweringFailed()) { process.exit(1); } @@ -6159,7 +6252,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void { if (zir.hasCompileErrors()) { process.exit(1); } else { - return cleanExit(); + return cleanExit(io); } } if (!build_options.enable_debug_extensions) { @@ -6210,7 +6303,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void { if (zir.hasCompileErrors()) { process.exit(1); } else { - return cleanExit(); + return cleanExit(io); } }, .zon => { @@ -6220,12 +6313,12 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void { try wip_errors.init(arena); try wip_errors.addZoirErrorMessages(zoir, tree, source, display_path); var error_bundle = try wip_errors.toOwnedBundle(""); - error_bundle.renderToStdErr(.{}, color); + error_bundle.renderToStderr(io, .{}, color) catch {}; process.exit(1); } if (!want_output_text) { - return cleanExit(); + return cleanExit(io); } if (!build_options.enable_debug_extensions) { @@ -6234,7 +6327,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void { try @import("print_zoir.zig").renderToWriter(zoir, arena, stdout_bw); try stdout_bw.flush(); - return cleanExit(); + return cleanExit(io); }, } } @@ -6261,8 +6354,8 @@ fn cmdDetectCpu(io: Io, args: []const []const u8) !void { const arg = args[i]; if (mem.startsWith(u8, arg, "-")) { if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { - try fs.File.stdout().writeAll(detect_cpu_usage); - return cleanExit(); + try Io.File.stdout().writeStreamingAll(io, detect_cpu_usage); + return cleanExit(io); } else if (mem.eql(u8, arg, "--llvm")) { use_llvm = true; } else { @@ -6282,10 +6375,10 @@ fn cmdDetectCpu(io: Io, args: []const []const u8) !void { const name = llvm.GetHostCPUName() orelse fatal("LLVM could not figure out the host cpu name", .{}); const features = llvm.GetHostCPUFeatures() orelse fatal("LLVM could not figure out the host cpu feature set", .{}); const cpu = try detectNativeCpuWithLLVM(builtin.cpu.arch, name, features); - try printCpu(cpu); + try printCpu(io, cpu); } else { const host_target = std.zig.resolveTargetQueryOrFatal(io, .{}); - try printCpu(host_target.cpu); + try printCpu(io, host_target.cpu); } } @@ -6352,8 +6445,8 @@ fn detectNativeCpuWithLLVM( return result; } -fn printCpu(cpu: std.Target.Cpu) !void { - var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer); +fn printCpu(io: Io, cpu: std.Target.Cpu) !void { + var stdout_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer); const stdout_bw = &stdout_writer.interface; if (cpu.model.llvm_name) |llvm_name| { @@ -6375,6 +6468,7 @@ fn printCpu(cpu: std.Target.Cpu) !void { fn cmdDumpLlvmInts( gpa: Allocator, arena: Allocator, + io: Io, args: []const []const u8, ) !void { dev.check(.llvm_ints_command); @@ -6402,7 +6496,7 @@ fn cmdDumpLlvmInts( const dl = tm.createTargetDataLayout(); const context = llvm.Context.create(); - var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer); + var stdout_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer); const stdout_bw = &stdout_writer.interface; for ([_]u16{ 1, 8, 16, 32, 64, 128, 256 }) |bits| { const int_type = context.intType(bits); @@ -6411,7 +6505,7 @@ fn cmdDumpLlvmInts( } try stdout_bw.flush(); - return cleanExit(); + return cleanExit(io); } /// This is only enabled for debug builds. @@ -6422,13 +6516,13 @@ fn cmdDumpZir(arena: Allocator, io: Io, args: []const []const u8) !void { const cache_file = args[0]; - var f = fs.cwd().openFile(cache_file, .{}) catch |err| { + var f = Io.Dir.cwd().openFile(io, cache_file, .{}) catch |err| { fatal("unable to open zir cache file for dumping '{s}': {s}", .{ cache_file, @errorName(err) }); }; - defer f.close(); + defer f.close(io); const zir = try Zcu.loadZirCache(arena, io, f); - var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer); + var stdout_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer); const stdout_bw = &stdout_writer.interface; { const instruction_bytes = zir.instructions.len * @@ -6469,18 +6563,18 @@ fn cmdChangelist(arena: Allocator, io: Io, args: []const []const u8) !void { const new_source_path = args[1]; const old_source = source: { - var f = fs.cwd().openFile(old_source_path, .{}) catch |err| + var f = Io.Dir.cwd().openFile(io, old_source_path, .{}) catch |err| fatal("unable to open old source file '{s}': {s}", .{ old_source_path, @errorName(err) }); - defer f.close(); - var file_reader: fs.File.Reader = f.reader(io, &stdin_buffer); + defer f.close(io); + var file_reader: Io.File.Reader = f.reader(io, &stdin_buffer); break :source std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err| fatal("unable to read old source file '{s}': {s}", .{ old_source_path, @errorName(err) }); }; const new_source = source: { - var f = fs.cwd().openFile(new_source_path, .{}) catch |err| + var f = Io.Dir.cwd().openFile(io, new_source_path, .{}) catch |err| fatal("unable to open new source file '{s}': {s}", .{ new_source_path, @errorName(err) }); - defer f.close(); - var file_reader: fs.File.Reader = f.reader(io, &stdin_buffer); + defer f.close(io); + var file_reader: Io.File.Reader = f.reader(io, &stdin_buffer); break :source std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err| fatal("unable to read new source file '{s}': {s}", .{ new_source_path, @errorName(err) }); }; @@ -6493,7 +6587,7 @@ fn cmdChangelist(arena: Allocator, io: Io, args: []const []const u8) !void { try wip_errors.init(arena); try wip_errors.addZirErrorMessages(old_zir, old_tree, old_source, old_source_path); var error_bundle = try wip_errors.toOwnedBundle(""); - error_bundle.renderToStdErr(.{}, color); + error_bundle.renderToStderr(io, .{}, color) catch {}; process.exit(1); } @@ -6505,14 +6599,14 @@ fn cmdChangelist(arena: Allocator, io: Io, args: []const []const u8) !void { try wip_errors.init(arena); try wip_errors.addZirErrorMessages(new_zir, new_tree, new_source, new_source_path); var error_bundle = try wip_errors.toOwnedBundle(""); - error_bundle.renderToStdErr(.{}, color); + error_bundle.renderToStderr(io, .{}, color) catch {}; process.exit(1); } var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .empty; try Zcu.mapOldZirToNew(arena, old_zir, new_zir, &inst_map); - var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer); + var stdout_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer); const stdout_bw = &stdout_writer.interface; { try stdout_bw.print("Instruction mappings:\n", .{}); @@ -6554,7 +6648,7 @@ fn warnAboutForeignBinaries( const host_query: std.Target.Query = .{}; const host_target = std.zig.resolveTargetQueryOrFatal(io, host_query); - switch (std.zig.system.getExternalExecutor(&host_target, target, .{ .link_libc = link_libc })) { + switch (std.zig.system.getExternalExecutor(io, &host_target, target, .{ .link_libc = link_libc })) { .native => return, .rosetta => { const host_name = try host_target.zigTriple(arena); @@ -6760,6 +6854,7 @@ const ClangSearchSanitizer = struct { }; fn accessFrameworkPath( + io: Io, test_path: *std.array_list.Managed(u8), checked_paths: *std.array_list.Managed(u8), framework_dir_path: []const u8, @@ -6773,7 +6868,7 @@ fn accessFrameworkPath( framework_dir_path, framework_name, framework_name, ext, }); try checked_paths.print("\n {s}", .{test_path.items}); - fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { + Io.Dir.cwd().access(io, test_path.items, .{}) catch |err| switch (err) { error.FileNotFound => continue, else => |e| fatal("unable to search for {s} framework '{s}': {s}", .{ ext, test_path.items, @errorName(e), @@ -6822,14 +6917,15 @@ fn cmdFetch( arena: Allocator, io: Io, args: []const []const u8, + environ_map: *process.Environ.Map, ) !void { dev.check(.fetch_command); const color: Color = .auto; const work_around_btrfs_bug = native_os == .linux and - EnvVar.ZIG_BTRFS_WORKAROUND.isSet(); + EnvVar.ZIG_BTRFS_WORKAROUND.isSet(environ_map); var opt_path_or_url: ?[]const u8 = null; - var override_global_cache_dir: ?[]const u8 = try EnvVar.ZIG_GLOBAL_CACHE_DIR.get(arena); + var override_global_cache_dir: ?[]const u8 = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map); var debug_hash: bool = false; var save: union(enum) { no, @@ -6843,8 +6939,8 @@ fn cmdFetch( const arg = args[i]; if (mem.startsWith(u8, arg, "-")) { if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { - try fs.File.stdout().writeAll(usage_fetch); - return cleanExit(); + try Io.File.stdout().writeStreamingAll(io, usage_fetch); + return cleanExit(io); } else if (mem.eql(u8, arg, "--global-cache-dir")) { if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); i += 1; @@ -6872,28 +6968,24 @@ fn cmdFetch( const path_or_url = opt_path_or_url orelse fatal("missing url or path parameter", .{}); - var thread_pool: ThreadPool = undefined; - try thread_pool.init(.{ .allocator = gpa }); - defer thread_pool.deinit(); - var http_client: std.http.Client = .{ .allocator = gpa, .io = io }; defer http_client.deinit(); - try http_client.initDefaultProxies(arena); + try http_client.initDefaultProxies(arena, environ_map); - var root_prog_node = std.Progress.start(.{ + var root_prog_node = std.Progress.start(io, .{ .root_name = "Fetch", }); defer root_prog_node.end(); var global_cache_directory: Directory = l: { - const p = override_global_cache_dir orelse try introspect.resolveGlobalCacheDir(arena); + const p = override_global_cache_dir orelse try introspect.resolveGlobalCacheDir(arena, environ_map); break :l .{ - .handle = try fs.cwd().makeOpenPath(p, .{}), + .handle = try Io.Dir.cwd().createDirPathOpen(io, p, .{}), .path = p, }; }; - defer global_cache_directory.handle.close(); + defer global_cache_directory.handle.close(io); var job_queue: Package.Fetch.JobQueue = .{ .io = io, @@ -6944,7 +7036,7 @@ fn cmdFetch( if (fetch.error_bundle.root_list.items.len > 0) { var errors = try fetch.error_bundle.toOwnedBundle(""); - errors.renderToStdErr(.{}, color); + errors.renderToStderr(io, .{}, color) catch {}; process.exit(1); } @@ -6956,10 +7048,10 @@ fn cmdFetch( const name = switch (save) { .no => { - var stdout = fs.File.stdout().writerStreaming(&stdout_buffer); + var stdout = Io.File.stdout().writerStreaming(io, &stdout_buffer); try stdout.interface.print("{s}\n", .{package_hash_slice}); try stdout.interface.flush(); - return cleanExit(); + return cleanExit(io); }, .yes, .exact => |name| name: { if (name) |n| break :name n; @@ -6971,14 +7063,14 @@ fn cmdFetch( const cwd_path = try introspect.getResolvedCwd(arena); - var build_root = try findBuildRoot(arena, .{ + var build_root = try findBuildRoot(arena, io, .{ .cwd_path = cwd_path, }); - defer build_root.deinit(); + defer build_root.deinit(io); // The name to use in case the manifest file needs to be created now. const init_root_name = fs.path.basename(build_root.directory.path orelse cwd_path); - var manifest, var ast = try loadManifest(gpa, arena, .{ + var manifest, var ast = try loadManifest(gpa, arena, io, .{ .root_name = try sanitizeExampleName(arena, init_root_name), .dir = build_root.directory.handle, .color = color, @@ -7094,15 +7186,16 @@ fn cmdFetch( try ast.render(gpa, &aw.writer, fixups); const rendered = aw.written(); - build_root.directory.handle.writeFile(.{ .sub_path = Package.Manifest.basename, .data = rendered }) catch |err| { + build_root.directory.handle.writeFile(io, .{ .sub_path = Package.Manifest.basename, .data = rendered }) catch |err| { fatal("unable to write {s} file: {t}", .{ Package.Manifest.basename, err }); }; - return cleanExit(); + return cleanExit(io); } fn createEmptyDependenciesModule( arena: Allocator, + io: Io, main_mod: *Package.Module, dirs: Compilation.Directories, global_options: Compilation.Config, @@ -7111,6 +7204,7 @@ fn createEmptyDependenciesModule( try Package.Fetch.JobQueue.createEmptyDependenciesSource(&source); _ = try createDependenciesModule( arena, + io, source.items, main_mod, dirs, @@ -7122,6 +7216,7 @@ fn createEmptyDependenciesModule( /// build runner to obtain via `@import("@dependencies")`. fn createDependenciesModule( arena: Allocator, + io: Io, source: []const u8, main_mod: *Package.Module, dirs: Compilation.Directories, @@ -7129,12 +7224,12 @@ fn createDependenciesModule( ) !*Package.Module { // Atomically create the file in a directory named after the hash of its contents. const basename = "dependencies.zig"; - const rand_int = std.crypto.random.int(u64); + const rand_int = randInt(io, u64); const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(rand_int); { - var tmp_dir = try dirs.local_cache.handle.makeOpenPath(tmp_dir_sub_path, .{}); - defer tmp_dir.close(); - try tmp_dir.writeFile(.{ .sub_path = basename, .data = source }); + var tmp_dir = try dirs.local_cache.handle.createDirPathOpen(io, tmp_dir_sub_path, .{}); + defer tmp_dir.close(io); + try tmp_dir.writeFile(io, .{ .sub_path = basename, .data = source }); } var hh: Cache.HashHelper = .{}; @@ -7143,11 +7238,7 @@ fn createDependenciesModule( const hex_digest = hh.final(); const o_dir_sub_path = try arena.dupe(u8, "o" ++ fs.path.sep_str ++ hex_digest); - try Package.Fetch.renameTmpIntoCache( - dirs.local_cache.handle, - tmp_dir_sub_path, - o_dir_sub_path, - ); + try Package.Fetch.renameTmpIntoCache(io, dirs.local_cache.handle, tmp_dir_sub_path, o_dir_sub_path); const deps_mod = try Package.Module.create(arena, .{ .paths = .{ @@ -7167,10 +7258,10 @@ fn createDependenciesModule( const BuildRoot = struct { directory: Cache.Directory, build_zig_basename: []const u8, - cleanup_build_dir: ?fs.Dir, + cleanup_build_dir: ?Io.Dir, - fn deinit(br: *BuildRoot) void { - if (br.cleanup_build_dir) |*dir| dir.close(); + fn deinit(br: *BuildRoot, io: Io) void { + if (br.cleanup_build_dir) |*dir| dir.close(io); br.* = undefined; } }; @@ -7180,7 +7271,7 @@ const FindBuildRootOptions = struct { cwd_path: ?[]const u8 = null, }; -fn findBuildRoot(arena: Allocator, options: FindBuildRootOptions) !BuildRoot { +fn findBuildRoot(arena: Allocator, io: Io, options: FindBuildRootOptions) !BuildRoot { const cwd_path = options.cwd_path orelse try introspect.getResolvedCwd(arena); const build_zig_basename = if (options.build_file) |bf| fs.path.basename(bf) @@ -7189,7 +7280,7 @@ fn findBuildRoot(arena: Allocator, options: FindBuildRootOptions) !BuildRoot { if (options.build_file) |bf| { if (fs.path.dirname(bf)) |dirname| { - const dir = fs.cwd().openDir(dirname, .{}) catch |err| { + const dir = Io.Dir.cwd().openDir(io, dirname, .{}) catch |err| { fatal("unable to open directory to build file from argument 'build-file', '{s}': {s}", .{ dirname, @errorName(err) }); }; return .{ @@ -7201,7 +7292,7 @@ fn findBuildRoot(arena: Allocator, options: FindBuildRootOptions) !BuildRoot { return .{ .build_zig_basename = build_zig_basename, - .directory = .{ .path = null, .handle = fs.cwd() }, + .directory = .{ .path = null, .handle = Io.Dir.cwd() }, .cleanup_build_dir = null, }; } @@ -7209,8 +7300,8 @@ fn findBuildRoot(arena: Allocator, options: FindBuildRootOptions) !BuildRoot { var dirname: []const u8 = cwd_path; while (true) { const joined_path = try fs.path.join(arena, &[_][]const u8{ dirname, build_zig_basename }); - if (fs.cwd().access(joined_path, .{})) |_| { - const dir = fs.cwd().openDir(dirname, .{}) catch |err| { + if (Io.Dir.cwd().access(io, joined_path, .{})) |_| { + const dir = Io.Dir.cwd().openDir(io, dirname, .{}) catch |err| { fatal("unable to open directory while searching for build.zig file, '{s}': {s}", .{ dirname, @errorName(err) }); }; return .{ @@ -7239,17 +7330,21 @@ fn findBuildRoot(arena: Allocator, options: FindBuildRootOptions) !BuildRoot { const LoadManifestOptions = struct { root_name: []const u8, - dir: fs.Dir, + dir: Io.Dir, color: Color, }; fn loadManifest( gpa: Allocator, arena: Allocator, + io: Io, options: LoadManifestOptions, ) !struct { Package.Manifest, Ast } { + const rng: std.Random.IoSource = .{ .io = io }; + const manifest_bytes = while (true) { break options.dir.readFileAllocOptions( + io, Package.Manifest.basename, arena, .limited(Package.Manifest.max_bytes), @@ -7257,7 +7352,7 @@ fn loadManifest( 0, ) catch |err| switch (err) { error.FileNotFound => { - writeSimpleTemplateFile(Package.Manifest.basename, + writeSimpleTemplateFile(io, Package.Manifest.basename, \\.{{ \\ .name = .{s}, \\ .version = "{s}", @@ -7268,26 +7363,24 @@ fn loadManifest( , .{ options.root_name, build_options.version, - Package.Fingerprint.generate(options.root_name).int(), + Package.Fingerprint.generate(rng.interface(), options.root_name).int(), }) catch |e| { - fatal("unable to write {s}: {s}", .{ Package.Manifest.basename, @errorName(e) }); + fatal("unable to write {s}: {t}", .{ Package.Manifest.basename, e }); }; continue; }, - else => |e| fatal("unable to load {s}: {s}", .{ - Package.Manifest.basename, @errorName(e), - }), + else => |e| fatal("unable to load {s}: {t}", .{ Package.Manifest.basename, e }), }; }; var ast = try Ast.parse(gpa, manifest_bytes, .zon); errdefer ast.deinit(gpa); if (ast.errors.len > 0) { - try std.zig.printAstErrorsToStderr(gpa, ast, Package.Manifest.basename, options.color); + try std.zig.printAstErrorsToStderr(gpa, io, ast, Package.Manifest.basename, options.color); process.exit(2); } - var manifest = try Package.Manifest.parse(gpa, ast, .{}); + var manifest = try Package.Manifest.parse(gpa, ast, rng.interface(), .{}); errdefer manifest.deinit(gpa); if (manifest.errors.len > 0) { @@ -7300,7 +7393,7 @@ fn loadManifest( var error_bundle = try wip_errors.toOwnedBundle(""); defer error_bundle.deinit(gpa); - error_bundle.renderToStdErr(.{}, options.color); + error_bundle.renderToStderr(io, .{}, options.color) catch {}; process.exit(2); } @@ -7309,12 +7402,12 @@ fn loadManifest( const Templates = struct { zig_lib_directory: Cache.Directory, - dir: fs.Dir, + dir: Io.Dir, buffer: std.array_list.Managed(u8), - fn deinit(templates: *Templates) void { - templates.zig_lib_directory.handle.close(); - templates.dir.close(); + fn deinit(templates: *Templates, io: Io) void { + templates.zig_lib_directory.handle.close(io); + templates.dir.close(io); templates.buffer.deinit(); templates.* = undefined; } @@ -7322,20 +7415,21 @@ const Templates = struct { fn write( templates: *Templates, arena: Allocator, - out_dir: fs.Dir, + io: Io, + out_dir: Io.Dir, root_name: []const u8, template_path: []const u8, fingerprint: Package.Fingerprint, ) !void { if (fs.path.dirname(template_path)) |dirname| { - out_dir.makePath(dirname) catch |err| { - fatal("unable to make path '{s}': {s}", .{ dirname, @errorName(err) }); + out_dir.createDirPath(io, dirname) catch |err| { + fatal("unable to make path '{s}': {t}", .{ dirname, err }); }; } const max_bytes = 10 * 1024 * 1024; - const contents = templates.dir.readFileAlloc(template_path, arena, .limited(max_bytes)) catch |err| { - fatal("unable to read template file '{s}': {s}", .{ template_path, @errorName(err) }); + const contents = templates.dir.readFileAlloc(io, template_path, arena, .limited(max_bytes)) catch |err| { + fatal("unable to read template file '{s}': {t}", .{ template_path, err }); }; templates.buffer.clearRetainingCapacity(); try templates.buffer.ensureUnusedCapacity(contents.len); @@ -7363,39 +7457,39 @@ const Templates = struct { i += 1; } - return out_dir.writeFile(.{ + return out_dir.writeFile(io, .{ .sub_path = template_path, .data = templates.buffer.items, .flags = .{ .exclusive = true }, }); } }; -fn writeSimpleTemplateFile(file_name: []const u8, comptime fmt: []const u8, args: anytype) !void { - const f = try fs.cwd().createFile(file_name, .{ .exclusive = true }); - defer f.close(); +fn writeSimpleTemplateFile(io: Io, file_name: []const u8, comptime fmt: []const u8, args: anytype) !void { + const f = try Io.Dir.cwd().createFile(io, file_name, .{ .exclusive = true }); + defer f.close(io); var buf: [4096]u8 = undefined; - var fw = f.writer(&buf); + var fw = f.writer(io, &buf); try fw.interface.print(fmt, args); try fw.interface.flush(); } -fn findTemplates(gpa: Allocator, arena: Allocator) Templates { +fn findTemplates(gpa: Allocator, arena: Allocator, io: Io) Templates { const cwd_path = introspect.getResolvedCwd(arena) catch |err| { - fatal("unable to get cwd: {s}", .{@errorName(err)}); + fatal("unable to get cwd: {t}", .{err}); }; - const self_exe_path = fs.selfExePathAlloc(arena) catch |err| { - fatal("unable to find self exe path: {s}", .{@errorName(err)}); + const self_exe_path = process.executablePathAlloc(io, arena) catch |err| { + fatal("unable to find self exe path: {t}", .{err}); }; - var zig_lib_directory = introspect.findZigLibDirFromSelfExe(arena, cwd_path, self_exe_path) catch |err| { - fatal("unable to find zig installation directory '{s}': {s}", .{ self_exe_path, @errorName(err) }); + var zig_lib_directory = introspect.findZigLibDirFromSelfExe(arena, io, cwd_path, self_exe_path) catch |err| { + fatal("unable to find zig installation directory '{s}': {t}", .{ self_exe_path, err }); }; const s = fs.path.sep_str; const template_sub_path = "init"; - const template_dir = zig_lib_directory.handle.openDir(template_sub_path, .{}) catch |err| { + const template_dir = zig_lib_directory.handle.openDir(io, template_sub_path, .{}) catch |err| { const path = zig_lib_directory.path orelse "."; - fatal("unable to open zig project template directory '{s}{s}{s}': {s}", .{ - path, s, template_sub_path, @errorName(err), + fatal("unable to open zig project template directory '{s}{s}{s}': {t}", .{ + path, s, template_sub_path, err, }); }; @@ -7509,17 +7603,18 @@ fn anyObjectLinkInputs(link_inputs: []const link.UnresolvedInput) bool { return false; } -fn addLibDirectoryWarn(lib_directories: *std.ArrayList(Directory), path: []const u8) void { - return addLibDirectoryWarn2(lib_directories, path, false); +fn addLibDirectoryWarn(io: Io, lib_directories: *std.ArrayList(Directory), path: []const u8) void { + return addLibDirectoryWarn2(io, lib_directories, path, false); } fn addLibDirectoryWarn2( + io: Io, lib_directories: *std.ArrayList(Directory), path: []const u8, ignore_not_found: bool, ) void { lib_directories.appendAssumeCapacity(.{ - .handle = fs.cwd().openDir(path, .{}) catch |err| { + .handle = Io.Dir.cwd().openDir(io, path, .{}) catch |err| { if (err == error.FileNotFound and ignore_not_found) return; warn("unable to open library directory '{s}': {s}", .{ path, @errorName(err) }); return; @@ -7527,3 +7622,20 @@ fn addLibDirectoryWarn2( .path = path, }); } + +var threaded_impl_ptr: *Io.Threaded = undefined; +fn setThreadLimit(n: usize) void { + // We want a maximum of n total threads to keep the InternPool happy, but + // the main thread doesn't count towards the limits, so use n-1. Also, the + // linker can run concurrently, so we need to set both the async *and* the + // concurrency limit. + const limit: Io.Limit = .limited(n - 1); + threaded_impl_ptr.setAsyncLimit(limit); + threaded_impl_ptr.concurrent_limit = limit; +} + +fn randInt(io: Io, comptime T: type) T { + var x: T = undefined; + io.random(@ptrCast(&x)); + return x; +} diff --git a/src/mutable_value.zig b/src/mutable_value.zig index 0f2be00d4286..c9eb993944e1 100644 --- a/src/mutable_value.zig +++ b/src/mutable_value.zig @@ -55,6 +55,9 @@ pub const MutableValue = union(enum) { }; pub fn intern(mv: MutableValue, pt: Zcu.PerThread, arena: Allocator) Allocator.Error!Value { + const zcu = pt.zcu; + const comp = zcu.comp; + const io = comp.io; return Value.fromInterned(switch (mv) { .interned => |ip_index| ip_index, .eu_payload => |sv| try pt.intern(.{ .error_union = .{ @@ -68,7 +71,7 @@ pub const MutableValue = union(enum) { .repeated => |sv| return pt.aggregateSplatValue(.fromInterned(sv.ty), try sv.child.intern(pt, arena)), .bytes => |b| try pt.intern(.{ .aggregate = .{ .ty = b.ty, - .storage = .{ .bytes = try pt.zcu.intern_pool.getOrPutString(pt.zcu.gpa, pt.tid, b.data, .maybe_embedded_nulls) }, + .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(comp.gpa, io, pt.tid, b.data, .maybe_embedded_nulls) }, } }), .aggregate => |a| { const elems = try arena.alloc(InternPool.Index, a.elems.len); diff --git a/src/print_env.zig b/src/print_env.zig index e1847688adf9..163648321e41 100644 --- a/src/print_env.zig +++ b/src/print_env.zig @@ -1,40 +1,44 @@ -const std = @import("std"); const builtin = @import("builtin"); -const build_options = @import("build_options"); -const Compilation = @import("Compilation.zig"); + +const std = @import("std"); +const Io = std.Io; const Allocator = std.mem.Allocator; const EnvVar = std.zig.EnvVar; const fatal = std.process.fatal; +const build_options = @import("build_options"); +const Compilation = @import("Compilation.zig"); + pub fn cmdEnv( arena: Allocator, + io: Io, out: *std.Io.Writer, args: []const []const u8, - wasi_preopens: switch (builtin.target.os.tag) { - .wasi => std.fs.wasi.Preopens, - else => void, - }, + preopens: std.process.Preopens, host: *const std.Target, + environ_map: *std.process.Environ.Map, ) !void { - const override_lib_dir: ?[]const u8 = try EnvVar.ZIG_LIB_DIR.get(arena); - const override_global_cache_dir: ?[]const u8 = try EnvVar.ZIG_GLOBAL_CACHE_DIR.get(arena); + const override_lib_dir: ?[]const u8 = EnvVar.ZIG_LIB_DIR.get(environ_map); + const override_global_cache_dir: ?[]const u8 = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map); const self_exe_path = switch (builtin.target.os.tag) { .wasi => args[0], - else => std.fs.selfExePathAlloc(arena) catch |err| { - fatal("unable to find zig self exe path: {s}", .{@errorName(err)}); + else => std.process.executablePathAlloc(io, arena) catch |err| { + fatal("unable to find zig self exe path: {t}", .{err}); }, }; var dirs: Compilation.Directories = .init( arena, + io, override_lib_dir, override_global_cache_dir, .global, - if (builtin.target.os.tag == .wasi) wasi_preopens, + preopens, if (builtin.target.os.tag != .wasi) self_exe_path, + environ_map, ); - defer dirs.deinit(); + defer dirs.deinit(io); const zig_lib_dir = dirs.zig_lib.path orelse ""; const zig_std_dir = try dirs.zig_lib.join(arena, &.{"std"}); @@ -51,8 +55,8 @@ pub fn cmdEnv( try root.field("version", build_options.version, .{}); try root.field("target", triple, .{}); var env = try root.beginStructField("env", .{}); - inline for (@typeInfo(std.zig.EnvVar).@"enum".fields) |field| { - try env.field(field.name, try @field(std.zig.EnvVar, field.name).get(arena), .{}); + inline for (@typeInfo(EnvVar).@"enum".fields) |field| { + try env.field(field.name, @field(EnvVar, field.name).get(environ_map), .{}); } try env.end(); try root.end(); diff --git a/src/print_targets.zig b/src/print_targets.zig index d9118b901b59..a5e89506ad02 100644 --- a/src/print_targets.zig +++ b/src/print_targets.zig @@ -1,35 +1,38 @@ const std = @import("std"); +const Io = std.Io; const fs = std.fs; const mem = std.mem; const meta = std.meta; const fatal = std.process.fatal; const Allocator = std.mem.Allocator; const Target = std.Target; -const target = @import("target.zig"); const assert = std.debug.assert; + const glibc = @import("libs/glibc.zig"); const introspect = @import("introspect.zig"); +const target = @import("target.zig"); pub fn cmdTargets( allocator: Allocator, + io: Io, args: []const []const u8, out: *std.Io.Writer, native_target: *const Target, ) !void { _ = args; - var zig_lib_directory = introspect.findZigLibDir(allocator) catch |err| { - fatal("unable to find zig installation directory: {s}\n", .{@errorName(err)}); - }; - defer zig_lib_directory.handle.close(); + var zig_lib_directory = introspect.findZigLibDir(allocator, io) catch |err| + fatal("unable to find zig installation directory: {t}", .{err}); + defer zig_lib_directory.handle.close(io); defer allocator.free(zig_lib_directory.path.?); const abilists_contents = zig_lib_directory.handle.readFileAlloc( + io, glibc.abilists_path, allocator, .limited(glibc.abilists_max_size), ) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, - else => fatal("unable to read " ++ glibc.abilists_path ++ ": {s}", .{@errorName(err)}), + else => fatal("unable to read " ++ glibc.abilists_path ++ ": {t}", .{err}), }; defer allocator.free(abilists_contents); @@ -48,9 +51,7 @@ pub fn cmdTargets( { var libc_obj = try root_obj.beginTupleField("libc", .{}); for (std.zig.target.available_libcs) |libc| { - const tmp = try std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{ - @tagName(libc.arch), @tagName(libc.os), @tagName(libc.abi), - }); + const tmp = try std.fmt.allocPrint(allocator, "{t}-{t}-{t}", .{ libc.arch, libc.os, libc.abi }); defer allocator.free(tmp); try libc_obj.field(tmp, .{}); } diff --git a/src/print_zir.zig b/src/print_zir.zig index 316632f2d330..ced6c8e82645 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -595,7 +595,7 @@ const Writer = struct { }, .reify_slice_arg_ty => { - const reify_slice_arg_info: Zir.Inst.ReifySliceArgInfo = @enumFromInt(extended.operand); + const reify_slice_arg_info: Zir.Inst.ReifySliceArgInfo = @enumFromInt(extended.small); const extra = self.code.extraData(Zir.Inst.UnNode, extended.operand).data; try stream.print("{t}, ", .{reify_slice_arg_info}); try self.writeInstRef(stream, extra.operand); @@ -1267,18 +1267,14 @@ const Writer = struct { tmpl_is_expr: bool, ) !void { const extra = self.code.extraData(Zir.Inst.Asm, extended.operand); - const outputs_len = @as(u5, @truncate(extended.small)); - const inputs_len = @as(u5, @truncate(extended.small >> 5)); - const clobbers_len = @as(u5, @truncate(extended.small >> 10)); - const is_volatile = @as(u1, @truncate(extended.small >> 15)) != 0; + const small: Zir.Inst.Asm.Small = @bitCast(extended.small); - try self.writeFlag(stream, "volatile, ", is_volatile); + try self.writeFlag(stream, "volatile, ", small.is_volatile); if (tmpl_is_expr) { try self.writeInstRef(stream, @enumFromInt(@intFromEnum(extra.data.asm_source))); - try stream.writeAll(", "); } else { const asm_source = self.code.nullTerminatedString(extra.data.asm_source); - try stream.print("\"{f}\", ", .{std.zig.fmtString(asm_source)}); + try stream.print("\"{f}\"", .{std.zig.fmtString(asm_source)}); } try stream.writeAll(", "); @@ -1286,7 +1282,7 @@ const Writer = struct { var output_type_bits = extra.data.output_type_bits; { var i: usize = 0; - while (i < outputs_len) : (i += 1) { + while (i < small.outputs_len) : (i += 1) { const output = self.code.extraData(Zir.Inst.Asm.Output, extra_i); extra_i = output.end; @@ -1298,17 +1294,14 @@ const Writer = struct { try stream.print("output({f}, \"{f}\", ", .{ std.zig.fmtIdP(name), std.zig.fmtString(constraint), }); - try self.writeFlag(stream, "->", is_type); + try self.writeFlag(stream, "-> ", is_type); try self.writeInstRef(stream, output.data.operand); - try stream.writeAll(")"); - if (i + 1 < outputs_len) { - try stream.writeAll("), "); - } + try stream.writeAll("), "); } } { var i: usize = 0; - while (i < inputs_len) : (i += 1) { + while (i < small.inputs_len) : (i += 1) { const input = self.code.extraData(Zir.Inst.Asm.Input, extra_i); extra_i = input.end; @@ -1318,24 +1311,12 @@ const Writer = struct { std.zig.fmtIdP(name), std.zig.fmtString(constraint), }); try self.writeInstRef(stream, input.data.operand); - try stream.writeAll(")"); - if (i + 1 < inputs_len) { - try stream.writeAll(", "); - } - } - } - { - var i: usize = 0; - while (i < clobbers_len) : (i += 1) { - const str_index = self.code.extra[extra_i]; - extra_i += 1; - const clobber = self.code.nullTerminatedString(@enumFromInt(str_index)); - try stream.print("{f}", .{std.zig.fmtIdP(clobber)}); - if (i + 1 < clobbers_len) { - try stream.writeAll(", "); - } + try stream.writeAll("), "); } } + + try self.writeInstRef(stream, extra.data.clobbers); + try stream.writeAll(")) "); try self.writeSrcNode(stream, extra.data.src_node); } diff --git a/src/target.zig b/src/target.zig index 7e50589ab87d..87d0522ce727 100644 --- a/src/target.zig +++ b/src/target.zig @@ -17,13 +17,6 @@ pub fn cannotDynamicLink(target: *const std.Target) bool { }; } -/// On Darwin, we always link libSystem which contains libc. -/// Similarly on FreeBSD and NetBSD we always link system libc -/// since this is the stable syscall interface. -pub fn osRequiresLibC(target: *const std.Target) bool { - return target.requiresLibC(); -} - pub fn libCNeedsLibUnwind(target: *const std.Target, link_mode: std.builtin.LinkMode) bool { return target.isGnuLibC() and link_mode == .static; } @@ -49,7 +42,7 @@ pub fn libCxxNeedsLibUnwind(target: *const std.Target) bool { pub fn requiresPIC(target: *const std.Target, linking_libc: bool) bool { return target.abi.isAndroid() or target.os.tag == .windows or target.os.tag == .uefi or - osRequiresLibC(target) or + target.requiresLibC() or (linking_libc and target.isGnuLibC()); } diff --git a/stage1/wasi.c b/stage1/wasi.c index 83240d39b41d..e4772735d9ad 100644 --- a/stage1/wasi.c +++ b/stage1/wasi.c @@ -939,6 +939,58 @@ uint32_t wasi_snapshot_preview1_path_remove_directory(uint32_t fd, uint32_t path return wasi_errno_success; } +uint32_t wasi_snapshot_preview1_path_symlink(uint32_t old_path, uint32_t old_path_len, uint32_t fd, uint32_t new_path, uint32_t new_path_len) { + uint8_t *const m = *wasm_memory; + const char *old_path_ptr = (const char *)&m[old_path]; + const char *new_path_ptr = (const char *)&m[new_path]; +#if LOG_TRACE + fprintf(stderr, "wasi_snapshot_preview1_path_symlink(\"%.*s\", %u, \"%.*s\")\n", (int)old_path_len, old_path_ptr, fd, (int)new_path_len, new_path_ptr); +#endif + (void)old_path_ptr; + (void)old_path_len; + (void)fd; + (void)new_path_ptr; + (void)new_path_len; + panic("unimplemented: path_symlink"); + return wasi_errno_success; +} + +uint32_t wasi_snapshot_preview1_path_readlink(uint32_t fd, uint32_t path, uint32_t path_len, uint32_t buf, uint32_t buf_len, uint32_t out_len) { + uint8_t *const m = *wasm_memory; + const char *path_ptr = (const char *)&m[path]; + char *buf_ptr = (char *)&m[buf]; + uint32_t *out_len_ptr = (uint32_t *)&m[out_len]; +#if LOG_TRACE + fprintf(stderr, "wasi_snapshot_preview1_path_readlink(%u, \"%.*s\", 0x%X, %u, 0x%X)\n", fd, (int)path_len, path_ptr, buf, buf_len, out_len); +#endif + (void)fd; + (void)path_ptr; + (void)path_len; + (void)buf_ptr; + (void)buf_len; + (void)out_len_ptr; + panic("unimplemented: path_readlink"); + return wasi_errno_success; +} + +uint32_t wasi_snapshot_preview1_path_link(uint32_t old_fd, uint32_t old_flags, uint32_t old_path, uint32_t old_path_len, uint32_t new_fd, uint32_t new_path, uint32_t new_path_len) { + uint8_t *const m = *wasm_memory; + const char *old_path_ptr = (const char *)&m[old_path]; + const char *new_path_ptr = (const char *)&m[new_path]; +#if LOG_TRACE + fprintf(stderr, "wasi_snapshot_preview1_path_link(%u, 0x%X, \"%.*s\", %u, \"%.*s\")\n", old_fd, old_flags, (int)old_path_len, old_path_ptr, new_fd, (int)new_path_len, new_path_ptr); +#endif + (void)old_fd; + (void)old_flags; + (void)old_path_ptr; + (void)old_path_len; + (void)new_fd; + (void)new_path_ptr; + (void)new_path_len; + panic("unimplemented: path_link"); + return wasi_errno_success; +} + uint32_t wasi_snapshot_preview1_path_unlink_file(uint32_t fd, uint32_t path, uint32_t path_len) { uint8_t *const m = *wasm_memory; const char *path_ptr = (const char *)&m[path]; @@ -1038,6 +1090,15 @@ uint32_t wasi_snapshot_preview1_fd_seek(uint32_t fd, uint64_t in_offset, uint32_ return wasi_errno_success; } +uint32_t wasi_snapshot_preview1_fd_sync(uint32_t fd) { +#if LOG_TRACE + fprintf(stderr, "wasi_snapshot_preview1_fd_sync(%u)\n", fd); +#endif + (void)fd; + panic("unimplemented: fd_sync"); + return wasi_errno_success; +} + uint32_t wasi_snapshot_preview1_poll_oneoff(uint32_t in, uint32_t out, uint32_t nsubscriptions, uint32_t res_nevents) { (void)in; (void)out; diff --git a/test/behavior/abs.zig b/test/behavior/abs.zig index 078362cf3e6c..1b12e08eccbb 100644 --- a/test/behavior/abs.zig +++ b/test/behavior/abs.zig @@ -1,5 +1,6 @@ const builtin = @import("builtin"); const std = @import("std"); +const assert = std.debug.assert; const expect = std.testing.expect; test "@abs integers" { @@ -48,6 +49,33 @@ fn testAbsIntegers() !void { } } +test "@abs signed C ABI integers" { + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO + + const S = struct { + fn doTheTest() !void { + try testOne(isize, usize); + try testOne(c_short, c_ushort); + try testOne(c_int, c_uint); + try testOne(c_long, c_ulong); + if (!builtin.cpu.arch.isSpirV()) try testOne(c_longlong, c_ulonglong); + } + fn testOne(comptime Signed: type, comptime Unsigned: type) !void { + var negative_one: Signed = undefined; + negative_one = -1; + const one = @abs(negative_one); + comptime assert(@TypeOf(one) == Unsigned); + try expect(one == 1); + } + }; + + try S.doTheTest(); + try comptime S.doTheTest(); +} + test "@abs unsigned integers" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO @@ -87,6 +115,32 @@ fn testAbsUnsignedIntegers() !void { } } +test "@abs unsigned C ABI integers" { + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO + + const S = struct { + fn doTheTest() !void { + try testOne(usize); + try testOne(c_ushort); + try testOne(c_uint); + try testOne(c_ulong); + if (!builtin.cpu.arch.isSpirV()) try testOne(c_ulonglong); + } + fn testOne(comptime Unsigned: type) !void { + var one: Unsigned = undefined; + one = 1; + const still_one = @abs(one); + comptime assert(@TypeOf(still_one) == Unsigned); + try expect(still_one == 1); + } + }; + + try S.doTheTest(); + try comptime S.doTheTest(); +} + test "@abs big int <= 128 bits" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO diff --git a/test/behavior/bitcast.zig b/test/behavior/bitcast.zig index d6827d5d43d0..90cf8a5c776b 100644 --- a/test/behavior/bitcast.zig +++ b/test/behavior/bitcast.zig @@ -422,6 +422,7 @@ test "bitcast nan float does not modify signaling bit" { if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; const snan_u16: u16 = 0x7D00; const snan_u32: u32 = 0x7FA00000; diff --git a/test/behavior/enum.zig b/test/behavior/enum.zig index 6ec436b70d26..d49b27d4d418 100644 --- a/test/behavior/enum.zig +++ b/test/behavior/enum.zig @@ -1066,6 +1066,7 @@ test "tag name with signed enum values" { test "tag name with large enum values" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; const Kdf = enum(u128) { aes_kdf = 0xea4f8ac1080d74bf60448a629af3d9c9, diff --git a/test/behavior/error.zig b/test/behavior/error.zig index aa39b685ca7a..d74a7668a97e 100644 --- a/test/behavior/error.zig +++ b/test/behavior/error.zig @@ -1090,3 +1090,22 @@ test "compare error union to error set" { try S.doTheTest(0); try comptime S.doTheTest(0); } + +test "'if' ignores error via local while 'else' ignores error directly" { + const S = struct { + /// This function is intentionally fallible despite never returning an + /// error so that it participates in error return tracing. + fn testOne(cond: bool) !void { + if (cond) { + const result = notError(); + result catch {}; + } else { + notError() catch {}; + } + } + fn notError() error{E}!void {} + }; + + try S.testOne(false); + try S.testOne(true); +} diff --git a/test/behavior/field_parent_ptr.zig b/test/behavior/field_parent_ptr.zig index 0475fcebe5f1..c30704063580 100644 --- a/test/behavior/field_parent_ptr.zig +++ b/test/behavior/field_parent_ptr.zig @@ -1033,6 +1033,7 @@ test "@fieldParentPtr packed struct first zero-bit field" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; const C = packed struct { a: u0 = 0, @@ -1139,6 +1140,7 @@ test "@fieldParentPtr packed struct middle zero-bit field" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; const C = packed struct { a: f32 = 3.14, @@ -1245,6 +1247,7 @@ test "@fieldParentPtr packed struct last zero-bit field" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; const C = packed struct { a: f32 = 3.14, diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig index 78d858774ffd..7e140f8da1c0 100644 --- a/test/behavior/floatop.zig +++ b/test/behavior/floatop.zig @@ -1298,6 +1298,24 @@ test "@ceil f80/f128/c_longdouble" { try comptime testCeil(c_longdouble); } +test "@ceil f80 maxInt(u64)" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; + + if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) { + // https://github.com/ziglang/zig/issues/12602 + return error.SkipZigTest; + } + + var x: u64 = std.math.maxInt(u64); + x = x; + const float: f80 = @floatFromInt(x); + try std.testing.expect(float == @ceil(float)); +} + fn testCeil(comptime T: type) !void { var two_point_one: T = 2.1; try expect(@ceil(two_point_one) == 3.0); diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig index 98760458ae26..4de7b26d34f7 100644 --- a/test/behavior/slice.zig +++ b/test/behavior/slice.zig @@ -158,6 +158,18 @@ test "slice of type" { } } +test "pass a slice of types to a function" { + const S = struct { + fn checkTypesSlice(types_slice: []const type) !void { + try expect(types_slice.len == 2); + try expect(types_slice[0] == anyerror); + try expect(types_slice[1] == bool); + } + }; + const types_array = [_]type{ void, anyerror, bool }; + try S.checkTypesSlice(types_array[1..]); +} + test "generic malloc free" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index 6ac60c225190..08aca075d7ec 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -749,6 +749,7 @@ test "packed struct with fp fields" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; const S = packed struct { data0: f32, @@ -2173,3 +2174,13 @@ test "avoid unused field function body compile error" { try expect(Case.entry() == 1); } + +test "pass a pointer to a comptime-only struct field to a function" { + const S = struct { + fn checkField(field_ptr: *const type) !void { + try expect(field_ptr.* == u42); + } + }; + const s: struct { x: type } = .{ .x = u42 }; + try S.checkField(&s.x); +} diff --git a/test/behavior/type.zig b/test/behavior/type.zig index 411a77f9e5fb..ef27522a6303 100644 --- a/test/behavior/type.zig +++ b/test/behavior/type.zig @@ -427,3 +427,12 @@ test "undefined type value" { }; comptime assert(@TypeOf(S.undef_type) == type); } + +test "reify struct with zero fields through const arrays" { + const names: [0][]const u8 = .{}; + const types: [0]type = .{}; + const attrs: [0]std.builtin.Type.StructField.Attributes = .{}; + const S = @Struct(.auto, null, &names, &types, &attrs); + comptime assert(@typeInfo(S) == .@"struct"); + comptime assert(@typeInfo(S).@"struct".fields.len == 0); +} diff --git a/test/behavior/union.zig b/test/behavior/union.zig index 7771f57beaef..a9e950a255cc 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -2217,6 +2217,7 @@ test "matching captures causes union equivalence" { test "signed enum tag with negative value" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const Enum = enum(i8) { diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig index e046c54ebdc6..6db7e14a00f9 100644 --- a/test/behavior/vector.zig +++ b/test/behavior/vector.zig @@ -9,6 +9,7 @@ const expectEqual = std.testing.expectEqual; test "implicit cast vector to array - bool" { if (builtin.cpu.arch == .aarch64_be and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; const S = struct { fn doTheTest() !void { @@ -32,6 +33,7 @@ test "implicit cast vector to array - bool" { test "implicit cast array to vector - bool" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; const S = struct { fn doTheTest() !void { diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c index 940ddac9d21e..a79201a9dd36 100644 --- a/test/c_abi/cfuncs.c +++ b/test/c_abi/cfuncs.c @@ -212,55 +212,64 @@ struct Struct_u64_u64 { struct Struct_u64_u64 zig_ret_struct_u64_u64(void); -void zig_struct_u64_u64_0(struct Struct_u64_u64); -void zig_struct_u64_u64_1(size_t, struct Struct_u64_u64); -void zig_struct_u64_u64_2(size_t, size_t, struct Struct_u64_u64); -void zig_struct_u64_u64_3(size_t, size_t, size_t, struct Struct_u64_u64); -void zig_struct_u64_u64_4(size_t, size_t, size_t, size_t, struct Struct_u64_u64); -void zig_struct_u64_u64_5(size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64); -void zig_struct_u64_u64_6(size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64); -void zig_struct_u64_u64_7(size_t, size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64); -void zig_struct_u64_u64_8(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64); +void zig_struct_u64_u64_0(struct Struct_u64_u64, size_t); +void zig_struct_u64_u64_1(size_t, struct Struct_u64_u64, size_t); +void zig_struct_u64_u64_2(size_t, size_t, struct Struct_u64_u64, size_t); +void zig_struct_u64_u64_3(size_t, size_t, size_t, struct Struct_u64_u64, size_t); +void zig_struct_u64_u64_4(size_t, size_t, size_t, size_t, struct Struct_u64_u64, size_t); +void zig_struct_u64_u64_5(size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64, size_t); +void zig_struct_u64_u64_6(size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64, size_t); +void zig_struct_u64_u64_7(size_t, size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64, size_t); +void zig_struct_u64_u64_8(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64, size_t); struct Struct_u64_u64 c_ret_struct_u64_u64(void) { return (struct Struct_u64_u64){ 21, 22 }; } -void c_struct_u64_u64_0(struct Struct_u64_u64 s) { +void c_struct_u64_u64_0(struct Struct_u64_u64 s, size_t i) { assert_or_panic(s.a == 23); assert_or_panic(s.b == 24); + assert_or_panic(i == 1); } -void c_struct_u64_u64_1(size_t, struct Struct_u64_u64 s) { +void c_struct_u64_u64_1(size_t a0, struct Struct_u64_u64 s, size_t i) { assert_or_panic(s.a == 25); assert_or_panic(s.b == 26); + assert_or_panic(i == 2); } -void c_struct_u64_u64_2(size_t, size_t, struct Struct_u64_u64 s) { +void c_struct_u64_u64_2(size_t, size_t, struct Struct_u64_u64 s, size_t i) { assert_or_panic(s.a == 27); assert_or_panic(s.b == 28); + assert_or_panic(i == 3); } -void c_struct_u64_u64_3(size_t, size_t, size_t, struct Struct_u64_u64 s) { +void c_struct_u64_u64_3(size_t, size_t, size_t, struct Struct_u64_u64 s, size_t i) { assert_or_panic(s.a == 29); assert_or_panic(s.b == 30); + assert_or_panic(i == 4); } -void c_struct_u64_u64_4(size_t, size_t, size_t, size_t, struct Struct_u64_u64 s) { +void c_struct_u64_u64_4(size_t, size_t, size_t, size_t, struct Struct_u64_u64 s, size_t i) { assert_or_panic(s.a == 31); assert_or_panic(s.b == 32); + assert_or_panic(i == 5); } -void c_struct_u64_u64_5(size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64 s) { +void c_struct_u64_u64_5(size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64 s, size_t i) { assert_or_panic(s.a == 33); assert_or_panic(s.b == 34); + assert_or_panic(i == 6); } -void c_struct_u64_u64_6(size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64 s) { +void c_struct_u64_u64_6(size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64 s, size_t i) { assert_or_panic(s.a == 35); assert_or_panic(s.b == 36); + assert_or_panic(i == 7); } -void c_struct_u64_u64_7(size_t, size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64 s) { +void c_struct_u64_u64_7(size_t, size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64 s, size_t i) { assert_or_panic(s.a == 37); assert_or_panic(s.b == 38); + assert_or_panic(i == 8); } -void c_struct_u64_u64_8(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64 s) { +void c_struct_u64_u64_8(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64 s, size_t i) { assert_or_panic(s.a == 39); assert_or_panic(s.b == 40); + assert_or_panic(i == 9); } struct Struct_f32 { @@ -2737,15 +2746,15 @@ void run_c_tests(void) { struct Struct_u64_u64 s = zig_ret_struct_u64_u64(); assert_or_panic(s.a == 1); assert_or_panic(s.b == 2); - zig_struct_u64_u64_0((struct Struct_u64_u64){ .a = 3, .b = 4 }); - zig_struct_u64_u64_1(0, (struct Struct_u64_u64){ .a = 5, .b = 6 }); - zig_struct_u64_u64_2(0, 1, (struct Struct_u64_u64){ .a = 7, .b = 8 }); - zig_struct_u64_u64_3(0, 1, 2, (struct Struct_u64_u64){ .a = 9, .b = 10 }); - zig_struct_u64_u64_4(0, 1, 2, 3, (struct Struct_u64_u64){ .a = 11, .b = 12 }); - zig_struct_u64_u64_5(0, 1, 2, 3, 4, (struct Struct_u64_u64){ .a = 13, .b = 14 }); - zig_struct_u64_u64_6(0, 1, 2, 3, 4, 5, (struct Struct_u64_u64){ .a = 15, .b = 16 }); - zig_struct_u64_u64_7(0, 1, 2, 3, 4, 5, 6, (struct Struct_u64_u64){ .a = 17, .b = 18 }); - zig_struct_u64_u64_8(0, 1, 2, 3, 4, 5, 6, 7, (struct Struct_u64_u64){ .a = 19, .b = 20 }); + zig_struct_u64_u64_0((struct Struct_u64_u64){ .a = 3, .b = 4 }, 1); + zig_struct_u64_u64_1(0, (struct Struct_u64_u64){ .a = 5, .b = 6 }, 2); + zig_struct_u64_u64_2(0, 1, (struct Struct_u64_u64){ .a = 7, .b = 8 }, 3); + zig_struct_u64_u64_3(0, 1, 2, (struct Struct_u64_u64){ .a = 9, .b = 10 }, 4); + zig_struct_u64_u64_4(0, 1, 2, 3, (struct Struct_u64_u64){ .a = 11, .b = 12 }, 5); + zig_struct_u64_u64_5(0, 1, 2, 3, 4, (struct Struct_u64_u64){ .a = 13, .b = 14 }, 6); + zig_struct_u64_u64_6(0, 1, 2, 3, 4, 5, (struct Struct_u64_u64){ .a = 15, .b = 16 }, 7); + zig_struct_u64_u64_7(0, 1, 2, 3, 4, 5, 6, (struct Struct_u64_u64){ .a = 17, .b = 18 }, 8); + zig_struct_u64_u64_8(0, 1, 2, 3, 4, 5, 6, 7, (struct Struct_u64_u64){ .a = 19, .b = 20 }, 9); } #if !defined(ZIG_RISCV64) diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig index f2b1b5014b4b..5d02e5e87dda 100644 --- a/test/c_abi/main.zig +++ b/test/c_abi/main.zig @@ -278,54 +278,63 @@ export fn zig_ret_struct_u64_u64() Struct_u64_u64 { return .{ .a = 1, .b = 2 }; } -export fn zig_struct_u64_u64_0(s: Struct_u64_u64) void { +export fn zig_struct_u64_u64_0(s: Struct_u64_u64, i: usize) void { expect(s.a == 3) catch @panic("test failure"); expect(s.b == 4) catch @panic("test failure"); + expect(i == 1) catch @panic("test failure"); } -export fn zig_struct_u64_u64_1(_: usize, s: Struct_u64_u64) void { +export fn zig_struct_u64_u64_1(_: usize, s: Struct_u64_u64, i: usize) void { expect(s.a == 5) catch @panic("test failure"); expect(s.b == 6) catch @panic("test failure"); + expect(i == 2) catch @panic("test failure"); } -export fn zig_struct_u64_u64_2(_: usize, _: usize, s: Struct_u64_u64) void { +export fn zig_struct_u64_u64_2(_: usize, _: usize, s: Struct_u64_u64, i: usize) void { expect(s.a == 7) catch @panic("test failure"); expect(s.b == 8) catch @panic("test failure"); + expect(i == 3) catch @panic("test failure"); } -export fn zig_struct_u64_u64_3(_: usize, _: usize, _: usize, s: Struct_u64_u64) void { +export fn zig_struct_u64_u64_3(_: usize, _: usize, _: usize, s: Struct_u64_u64, i: usize) void { expect(s.a == 9) catch @panic("test failure"); expect(s.b == 10) catch @panic("test failure"); + expect(i == 4) catch @panic("test failure"); } -export fn zig_struct_u64_u64_4(_: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64) void { +export fn zig_struct_u64_u64_4(_: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64, i: usize) void { expect(s.a == 11) catch @panic("test failure"); expect(s.b == 12) catch @panic("test failure"); + expect(i == 5) catch @panic("test failure"); } -export fn zig_struct_u64_u64_5(_: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64) void { +export fn zig_struct_u64_u64_5(_: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64, i: usize) void { expect(s.a == 13) catch @panic("test failure"); expect(s.b == 14) catch @panic("test failure"); + expect(i == 6) catch @panic("test failure"); } -export fn zig_struct_u64_u64_6(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64) void { +export fn zig_struct_u64_u64_6(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64, i: usize) void { expect(s.a == 15) catch @panic("test failure"); expect(s.b == 16) catch @panic("test failure"); + expect(i == 7) catch @panic("test failure"); } -export fn zig_struct_u64_u64_7(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64) void { +export fn zig_struct_u64_u64_7(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64, i: usize) void { expect(s.a == 17) catch @panic("test failure"); expect(s.b == 18) catch @panic("test failure"); + expect(i == 8) catch @panic("test failure"); } -export fn zig_struct_u64_u64_8(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64) void { +export fn zig_struct_u64_u64_8(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64, i: usize) void { expect(s.a == 19) catch @panic("test failure"); expect(s.b == 20) catch @panic("test failure"); + expect(i == 9) catch @panic("test failure"); } extern fn c_ret_struct_u64_u64() Struct_u64_u64; -extern fn c_struct_u64_u64_0(Struct_u64_u64) void; -extern fn c_struct_u64_u64_1(usize, Struct_u64_u64) void; -extern fn c_struct_u64_u64_2(usize, usize, Struct_u64_u64) void; -extern fn c_struct_u64_u64_3(usize, usize, usize, Struct_u64_u64) void; -extern fn c_struct_u64_u64_4(usize, usize, usize, usize, Struct_u64_u64) void; -extern fn c_struct_u64_u64_5(usize, usize, usize, usize, usize, Struct_u64_u64) void; -extern fn c_struct_u64_u64_6(usize, usize, usize, usize, usize, usize, Struct_u64_u64) void; -extern fn c_struct_u64_u64_7(usize, usize, usize, usize, usize, usize, usize, Struct_u64_u64) void; -extern fn c_struct_u64_u64_8(usize, usize, usize, usize, usize, usize, usize, usize, Struct_u64_u64) void; +extern fn c_struct_u64_u64_0(Struct_u64_u64, usize) void; +extern fn c_struct_u64_u64_1(usize, Struct_u64_u64, usize) void; +extern fn c_struct_u64_u64_2(usize, usize, Struct_u64_u64, usize) void; +extern fn c_struct_u64_u64_3(usize, usize, usize, Struct_u64_u64, usize) void; +extern fn c_struct_u64_u64_4(usize, usize, usize, usize, Struct_u64_u64, usize) void; +extern fn c_struct_u64_u64_5(usize, usize, usize, usize, usize, Struct_u64_u64, usize) void; +extern fn c_struct_u64_u64_6(usize, usize, usize, usize, usize, usize, Struct_u64_u64, usize) void; +extern fn c_struct_u64_u64_7(usize, usize, usize, usize, usize, usize, usize, Struct_u64_u64, usize) void; +extern fn c_struct_u64_u64_8(usize, usize, usize, usize, usize, usize, usize, usize, Struct_u64_u64, usize) void; test "C ABI struct u64 u64" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; @@ -336,15 +345,15 @@ test "C ABI struct u64 u64" { const s = c_ret_struct_u64_u64(); try expect(s.a == 21); try expect(s.b == 22); - c_struct_u64_u64_0(.{ .a = 23, .b = 24 }); - c_struct_u64_u64_1(0, .{ .a = 25, .b = 26 }); - c_struct_u64_u64_2(0, 1, .{ .a = 27, .b = 28 }); - c_struct_u64_u64_3(0, 1, 2, .{ .a = 29, .b = 30 }); - c_struct_u64_u64_4(0, 1, 2, 3, .{ .a = 31, .b = 32 }); - c_struct_u64_u64_5(0, 1, 2, 3, 4, .{ .a = 33, .b = 34 }); - c_struct_u64_u64_6(0, 1, 2, 3, 4, 5, .{ .a = 35, .b = 36 }); - c_struct_u64_u64_7(0, 1, 2, 3, 4, 5, 6, .{ .a = 37, .b = 38 }); - c_struct_u64_u64_8(0, 1, 2, 3, 4, 5, 6, 7, .{ .a = 39, .b = 40 }); + c_struct_u64_u64_0(.{ .a = 23, .b = 24 }, 1); + c_struct_u64_u64_1(0, .{ .a = 25, .b = 26 }, 2); + c_struct_u64_u64_2(0, 1, .{ .a = 27, .b = 28 }, 3); + c_struct_u64_u64_3(0, 1, 2, .{ .a = 29, .b = 30 }, 4); + c_struct_u64_u64_4(0, 1, 2, 3, .{ .a = 31, .b = 32 }, 5); + c_struct_u64_u64_5(0, 1, 2, 3, 4, .{ .a = 33, .b = 34 }, 6); + c_struct_u64_u64_6(0, 1, 2, 3, 4, 5, .{ .a = 35, .b = 36 }, 7); + c_struct_u64_u64_7(0, 1, 2, 3, 4, 5, 6, .{ .a = 37, .b = 38 }, 8); + c_struct_u64_u64_8(0, 1, 2, 3, 4, 5, 6, 7, .{ .a = 39, .b = 40 }, 9); } const Struct_f32 = extern struct { @@ -3364,6 +3373,7 @@ test "bool simd vector" { comptime { skip: { if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; + if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; _ = struct { export fn zig_vector_2_bool(vec: Vector2Bool) void { diff --git a/test/cases/compile_errors/asm_output_to_const.zig b/test/cases/compile_errors/asm_output_to_const.zig index a25552c3a1d8..f50080d63a3f 100644 --- a/test/cases/compile_errors/asm_output_to_const.zig +++ b/test/cases/compile_errors/asm_output_to_const.zig @@ -1,12 +1,18 @@ export fn foo() void { - const f: i64 = 1000; + const local: usize = 0; + asm volatile ("" + : [_] "=r" (local), + ); +} - asm volatile ( - \\ movq $10, %[f] - : [f] "=r" (f), +const global: usize = 0; +export fn bar() void { + asm volatile ("" + : [_] "=r" (global), ); } // error // -// :4:5: error: asm cannot output to const local 'f' +// :4:21: error: asm cannot output to const '_' +// :11:21: error: asm cannot output to const '_' diff --git a/test/cases/compile_errors/comptime_var_referenced_by_asm.zig b/test/cases/compile_errors/comptime_var_referenced_by_asm.zig new file mode 100644 index 000000000000..e6a0828f149a --- /dev/null +++ b/test/cases/compile_errors/comptime_var_referenced_by_asm.zig @@ -0,0 +1,21 @@ +export fn foo() void { + comptime var a: u32 = 0; + asm volatile ("" + : + : [in] "r" (&a), + ); +} + +export fn bar() void { + comptime var a: u32 = 0; + asm volatile ("" + : [out] "=r" (a), + ); +} + +// error +// +// :5:21: error: assembly input contains reference to comptime var +// :2:14: note: 'in' points to comptime var declared here +// :12:23: error: assembly output contains reference to comptime var +// :10:14: note: 'out' points to comptime var declared here diff --git a/test/cases/compile_errors/invalid_tail_call.zig b/test/cases/compile_errors/invalid_tail_call.zig index 8a1f298f2532..8990304b96e3 100644 --- a/test/cases/compile_errors/invalid_tail_call.zig +++ b/test/cases/compile_errors/invalid_tail_call.zig @@ -7,5 +7,6 @@ pub export fn entry() void { // error // backend=llvm +// target=x86_64-linux // // :5:5: error: unable to perform tail call: type of function being called 'fn (usize) void' does not match type of calling function 'fn () callconv(.c) void' diff --git a/test/cases/compile_errors/pointer_attributes_checked_when_coercing_pointer_to_anon_literal.zig b/test/cases/compile_errors/pointer_attributes_checked_when_coercing_pointer_to_anon_literal.zig index 12ecf9859005..00693a87f089 100644 --- a/test/cases/compile_errors/pointer_attributes_checked_when_coercing_pointer_to_anon_literal.zig +++ b/test/cases/compile_errors/pointer_attributes_checked_when_coercing_pointer_to_anon_literal.zig @@ -16,8 +16,7 @@ comptime { // // :2:29: error: expected type '[][]const u8', found '*const [2][]const u8' // :2:29: note: cast discards const qualifier -// :6:31: error: expected type '*', found '*const ' -// :6:31: note: = [2][]const u8 +// :6:31: error: expected type '*[2][]const u8', found '*const [2][]const u8' // :6:31: note: cast discards const qualifier // :11:19: error: expected type '*tmp.S', found '*const tmp.S' // :11:19: note: cast discards const qualifier diff --git a/test/cases/compile_errors/type_dedupe.zig b/test/cases/compile_errors/type_dedupe.zig index d1787d0bfac9..23174dc89a82 100644 --- a/test/cases/compile_errors/type_dedupe.zig +++ b/test/cases/compile_errors/type_dedupe.zig @@ -1,18 +1,18 @@ -const SomeVeryLongName = struct {}; +const SomeVeryVeryVeryLongName = struct {}; -fn foo(a: *SomeVeryLongName) void { +fn foo(a: *SomeVeryVeryVeryLongName) void { _ = a; } export fn entry() void { - const a: SomeVeryLongName = .{}; + const a: SomeVeryVeryVeryLongName = .{}; foo(a); } // error // -// :10:9: error: expected type '*', found '' -// :10:9: note: = tmp.SomeVeryLongName -// :1:26: note: struct declared here +// :10:9: error: expected type '*T', found 'T' +// :10:9: note: T = tmp.SomeVeryVeryVeryLongName +// :1:34: note: struct declared here // :3:11: note: parameter type declared here diff --git a/test/cases/compile_errors/type_mismatch_with_tuple_concatenation.zig b/test/cases/compile_errors/type_mismatch_with_tuple_concatenation.zig index bb6ee8ba33fa..151966f07b34 100644 --- a/test/cases/compile_errors/type_mismatch_with_tuple_concatenation.zig +++ b/test/cases/compile_errors/type_mismatch_with_tuple_concatenation.zig @@ -5,5 +5,5 @@ export fn entry() void { // error // -// :3:11: error: expected type '@TypeOf(.{})', found 'struct { comptime = 1, comptime = 2, comptime = 3 }' -// :3:11: note: = comptime_int +// :3:11: error: expected type '@TypeOf(.{})', found 'struct { comptime T = 1, comptime T = 2, comptime T = 3 }' +// :3:11: note: T = comptime_int diff --git a/test/cases/disable_stack_tracing.zig b/test/cases/disable_stack_tracing.zig index 044eaf701234..36620130c9a6 100644 --- a/test/cases/disable_stack_tracing.zig +++ b/test/cases/disable_stack_tracing.zig @@ -5,16 +5,16 @@ pub const std_options: std.Options = .{ pub fn main() !void { var st_buf: [8]usize = undefined; var buf: [1024]u8 = undefined; - var stdout = std.fs.File.stdout().writer(&buf); + var stdout = std.Io.File.stdout().writer(std.Options.debug_io, &buf); const captured_st = try foo(&stdout.interface, &st_buf); - try std.debug.writeStackTrace(&captured_st, &stdout.interface, .no_color); + try std.debug.writeStackTrace(&captured_st, .{ .writer = &stdout.interface, .mode = .no_color }); try stdout.interface.print("stack trace index: {d}\n", .{captured_st.index}); try stdout.interface.flush(); } fn foo(w: *std.Io.Writer, st_buf: []usize) !std.builtin.StackTrace { - try std.debug.writeCurrentStackTrace(.{}, w, .no_color); + try std.debug.writeCurrentStackTrace(.{}, .{ .writer = w, .mode = .no_color }); return std.debug.captureCurrentStackTrace(.{}, st_buf); } diff --git a/test/cases/error_union_variant_is_runtime_known.zig b/test/cases/error_union_variant_is_runtime_known.zig new file mode 100644 index 000000000000..2128ffa8043b --- /dev/null +++ b/test/cases/error_union_variant_is_runtime_known.zig @@ -0,0 +1,22 @@ +// This tests that the variant of an error union is runtime-known when the value is runtime-known. +// This might seem obvious but previously the compiler special-cased the situation where a const +// was assigned a payload or error value, i.e. instead of another error union. + +export fn foo() void { + var runtime_payload: u8 = 0; + _ = &runtime_payload; + const eu: error{a}!u8 = runtime_payload; + if (eu) |_| {} else |_| @compileError("analyzed"); +} + +export fn bar() void { + var runtime_error: error{a} = error.a; + _ = &runtime_error; + const eu: error{a}!u8 = runtime_error; + if (eu) |_| @compileError("analyzed") else |_| {} +} + +// error +// +// :9:29: error: analyzed +// :16:17: error: analyzed diff --git a/test/cases/function_pointers.zig b/test/cases/function_pointers.zig deleted file mode 100644 index 546eef72a480..000000000000 --- a/test/cases/function_pointers.zig +++ /dev/null @@ -1,30 +0,0 @@ -const std = @import("std"); - -const PrintFn = *const fn () void; - -pub fn main() void { - var printFn: PrintFn = stopSayingThat; - var i: u32 = 0; - while (i < 4) : (i += 1) printFn(); - - printFn = moveEveryZig; - printFn(); -} - -fn stopSayingThat() void { - _ = std.posix.write(1, "Hello, my name is Inigo Montoya; you killed my father, prepare to die.\n") catch {}; -} - -fn moveEveryZig() void { - _ = std.posix.write(1, "All your codebase are belong to us\n") catch {}; -} - -// run -// target=x86_64-macos -// -// Hello, my name is Inigo Montoya; you killed my father, prepare to die. -// Hello, my name is Inigo Montoya; you killed my father, prepare to die. -// Hello, my name is Inigo Montoya; you killed my father, prepare to die. -// Hello, my name is Inigo Montoya; you killed my father, prepare to die. -// All your codebase are belong to us -// diff --git a/test/cases/print_u32s.zig b/test/cases/print_u32s.zig deleted file mode 100644 index 0c73361278c8..000000000000 --- a/test/cases/print_u32s.zig +++ /dev/null @@ -1,28 +0,0 @@ -const std = @import("std"); - -pub fn main() void { - printNumberHex(0x00000000); - printNumberHex(0xaaaaaaaa); - printNumberHex(0xdeadbeef); - printNumberHex(0x31415926); -} - -fn printNumberHex(x: u32) void { - const digit_chars = "0123456789abcdef"; - var i: u5 = 28; - while (true) : (i -= 4) { - const digit = (x >> i) & 0xf; - _ = std.posix.write(1, &.{digit_chars[digit]}) catch {}; - if (i == 0) break; - } - _ = std.posix.write(1, "\n") catch {}; -} - -// run -// target=x86_64-macos -// -// 00000000 -// aaaaaaaa -// deadbeef -// 31415926 -// diff --git a/test/error_traces.zig b/test/error_traces.zig index 62daf1c94fa0..ef33a458c661 100644 --- a/test/error_traces.zig +++ b/test/error_traces.zig @@ -436,8 +436,10 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext) void { .{ .x86, .linux }, .{ .aarch64, .linux }, .{ .loongarch64, .linux }, + .{ .powerpc64le, .linux }, .{ .riscv64, .linux }, .{ .s390x, .linux }, + .{ .x86_64, .openbsd }, .{ .x86_64, .windows }, .{ .x86, .windows }, .{ .x86_64, .macos }, diff --git a/test/incremental/add_decl b/test/incremental/add_decl index 9efd274b9eb5..99f6b2d34fb9 100644 --- a/test/incremental/add_decl +++ b/test/incremental/add_decl @@ -7,57 +7,63 @@ #file=main.zig const std = @import("std"); pub fn main() !void { - try std.fs.File.stdout().writeAll(foo); + try std.Io.File.stdout().writeStreamingAll(io, foo); } const foo = "good morning\n"; +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="good morning\n" #update=add new declaration #file=main.zig const std = @import("std"); pub fn main() !void { - try std.fs.File.stdout().writeAll(foo); + try std.Io.File.stdout().writeStreamingAll(io, foo); } const foo = "good morning\n"; const bar = "good evening\n"; +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="good morning\n" #update=reference new declaration #file=main.zig const std = @import("std"); pub fn main() !void { - try std.fs.File.stdout().writeAll(bar); + try std.Io.File.stdout().writeStreamingAll(io, bar); } const foo = "good morning\n"; const bar = "good evening\n"; +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="good evening\n" #update=reference missing declaration #file=main.zig const std = @import("std"); pub fn main() !void { - try std.fs.File.stdout().writeAll(qux); + try std.Io.File.stdout().writeStreamingAll(io, qux); } const foo = "good morning\n"; const bar = "good evening\n"; -#expect_error=main.zig:3:39: error: use of undeclared identifier 'qux' +const io = std.Io.Threaded.global_single_threaded.ioBasic(); +#expect_error=main.zig:3:52: error: use of undeclared identifier 'qux' #update=add missing declaration #file=main.zig const std = @import("std"); pub fn main() !void { - try std.fs.File.stdout().writeAll(qux); + try std.Io.File.stdout().writeStreamingAll(io, qux); } const foo = "good morning\n"; const bar = "good evening\n"; const qux = "good night\n"; +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="good night\n" #update=remove unused declarations #file=main.zig const std = @import("std"); pub fn main() !void { - try std.fs.File.stdout().writeAll(qux); + try std.Io.File.stdout().writeStreamingAll(io, qux); } const qux = "good night\n"; +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="good night\n" diff --git a/test/incremental/add_decl_namespaced b/test/incremental/add_decl_namespaced index 1025ae24e1ce..6fc22f10b941 100644 --- a/test/incremental/add_decl_namespaced +++ b/test/incremental/add_decl_namespaced @@ -7,58 +7,64 @@ #file=main.zig const std = @import("std"); pub fn main() !void { - try std.fs.File.stdout().writeAll(@This().foo); + try std.Io.File.stdout().writeStreamingAll(io, @This().foo); } const foo = "good morning\n"; +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="good morning\n" #update=add new declaration #file=main.zig const std = @import("std"); pub fn main() !void { - try std.fs.File.stdout().writeAll(@This().foo); + try std.Io.File.stdout().writeStreamingAll(io, @This().foo); } const foo = "good morning\n"; const bar = "good evening\n"; +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="good morning\n" #update=reference new declaration #file=main.zig const std = @import("std"); pub fn main() !void { - try std.fs.File.stdout().writeAll(@This().bar); + try std.Io.File.stdout().writeStreamingAll(io, @This().bar); } const foo = "good morning\n"; const bar = "good evening\n"; +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="good evening\n" #update=reference missing declaration #file=main.zig const std = @import("std"); pub fn main() !void { - try std.fs.File.stdout().writeAll(@This().qux); + try std.Io.File.stdout().writeStreamingAll(io, @This().qux); } const foo = "good morning\n"; const bar = "good evening\n"; -#expect_error=main.zig:3:46: error: root source file struct 'main' has no member named 'qux' +const io = std.Io.Threaded.global_single_threaded.ioBasic(); +#expect_error=main.zig:3:59: error: root source file struct 'main' has no member named 'qux' #expect_error=main.zig:1:1: note: struct declared here #update=add missing declaration #file=main.zig const std = @import("std"); pub fn main() !void { - try std.fs.File.stdout().writeAll(@This().qux); + try std.Io.File.stdout().writeStreamingAll(io, @This().qux); } const foo = "good morning\n"; const bar = "good evening\n"; const qux = "good night\n"; +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="good night\n" #update=remove unused declarations #file=main.zig const std = @import("std"); pub fn main() !void { - try std.fs.File.stdout().writeAll(@This().qux); + try std.Io.File.stdout().writeStreamingAll(io, @This().qux); } const qux = "good night\n"; +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="good night\n" diff --git a/test/incremental/bad_import b/test/incremental/bad_import index 9b6be8b1767c..20bdb9ae82fc 100644 --- a/test/incremental/bad_import +++ b/test/incremental/bad_import @@ -8,9 +8,10 @@ #file=main.zig pub fn main() !void { _ = @import("foo.zig"); - try std.fs.File.stdout().writeAll("success\n"); + try std.Io.File.stdout().writeStreamingAll(io, "success\n"); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #file=foo.zig comptime { _ = @import("bad.zig"); @@ -30,7 +31,8 @@ comptime { #file=main.zig pub fn main() !void { //_ = @import("foo.zig"); - try std.fs.File.stdout().writeAll("success\n"); + try std.Io.File.stdout().writeStreamingAll(io, "success\n"); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="success\n" diff --git a/test/incremental/change_embed_file b/test/incremental/change_embed_file index 85d861ab9319..84c9c334c722 100644 --- a/test/incremental/change_embed_file +++ b/test/incremental/change_embed_file @@ -8,8 +8,9 @@ const std = @import("std"); const string = @embedFile("string.txt"); pub fn main() !void { - try std.fs.File.stdout().writeAll(string); + try std.Io.File.stdout().writeStreamingAll(io, string); } +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #file=string.txt Hello, World! #expect_stdout="Hello, World!\n" @@ -28,8 +29,9 @@ Hello again, World! const std = @import("std"); const string = @embedFile("string.txt"); pub fn main() !void { - try std.fs.File.stdout().writeAll("a hardcoded string\n"); + try std.Io.File.stdout().writeStreamingAll(io, "a hardcoded string\n"); } +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="a hardcoded string\n" #update=re-introduce reference to file @@ -37,8 +39,9 @@ pub fn main() !void { const std = @import("std"); const string = @embedFile("string.txt"); pub fn main() !void { - try std.fs.File.stdout().writeAll(string); + try std.Io.File.stdout().writeStreamingAll(io, string); } +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_error=main.zig:2:27: error: unable to open 'string.txt': FileNotFound #update=recreate file diff --git a/test/incremental/change_enum_tag_type b/test/incremental/change_enum_tag_type index 906f91027155..06b80ac04deb 100644 --- a/test/incremental/change_enum_tag_type +++ b/test/incremental/change_enum_tag_type @@ -15,10 +15,11 @@ const Foo = enum(Tag) { pub fn main() !void { var val: Foo = undefined; val = .a; - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); try stdout_writer.interface.print("{s}\n", .{@tagName(val)}); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="a\n" #update=too many enum fields #file=main.zig @@ -33,7 +34,7 @@ const Foo = enum(Tag) { pub fn main() !void { var val: Foo = undefined; val = .a; - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); try stdout_writer.interface.print("{s}\n", .{@tagName(val)}); } comptime { @@ -42,6 +43,7 @@ comptime { std.debug.assert(@TypeOf(@intFromEnum(Foo.e)) == Tag); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_error=main.zig:7:5: error: enumeration value '4' too large for type 'u2' #update=increase tag size #file=main.zig @@ -56,8 +58,9 @@ const Foo = enum(Tag) { pub fn main() !void { var val: Foo = undefined; val = .a; - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); try stdout_writer.interface.print("{s}\n", .{@tagName(val)}); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="a\n" diff --git a/test/incremental/change_exports b/test/incremental/change_exports index b0850626d6ed..a36afb4ee1aa 100644 --- a/test/incremental/change_exports +++ b/test/incremental/change_exports @@ -17,10 +17,11 @@ pub fn main() !void { extern const bar: u32; }; S.foo(); - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); try stdout_writer.interface.print("{}\n", .{S.bar}); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="123\n" #update=add conflict @@ -39,10 +40,11 @@ pub fn main() !void { extern const other: u32; }; S.foo(); - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_error=main.zig:6:5: error: exported symbol collision: foo #expect_error=main.zig:1:1: note: other symbol here @@ -62,10 +64,11 @@ pub fn main() !void { extern const other: u32; }; S.foo(); - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="123 456\n" #update=put exports in decl @@ -87,10 +90,11 @@ pub fn main() !void { extern const other: u32; }; S.foo(); - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="123 456\n" #update=remove reference to exporting decl @@ -133,10 +137,11 @@ pub fn main() !void { extern const other: u32; }; S.foo(); - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="123 456\n" #update=reintroduce reference to exporting decl, introducing conflict @@ -158,10 +163,11 @@ pub fn main() !void { extern const other: u32; }; S.foo(); - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_error=main.zig:5:5: error: exported symbol collision: bar #expect_error=main.zig:2:1: note: other symbol here #expect_error=main.zig:6:5: error: exported symbol collision: other diff --git a/test/incremental/change_fn_type b/test/incremental/change_fn_type index df788684cdc0..b4286545e381 100644 --- a/test/incremental/change_fn_type +++ b/test/incremental/change_fn_type @@ -8,10 +8,11 @@ pub fn main() !void { try foo(123); } fn foo(x: u8) !void { - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); return stdout_writer.interface.print("{d}\n", .{x}); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="123\n" #update=change function type @@ -20,10 +21,11 @@ pub fn main() !void { try foo(123); } fn foo(x: i64) !void { - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); return stdout_writer.interface.print("{d}\n", .{x}); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="123\n" #update=change function argument @@ -32,8 +34,9 @@ pub fn main() !void { try foo(-42); } fn foo(x: i64) !void { - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); return stdout_writer.interface.print("{d}\n", .{x}); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="-42\n" diff --git a/test/incremental/change_generic_line_number b/test/incremental/change_generic_line_number index f1920c67e6a4..2d731b071c64 100644 --- a/test/incremental/change_generic_line_number +++ b/test/incremental/change_generic_line_number @@ -4,10 +4,11 @@ #update=initial version #file=main.zig const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); fn Printer(message: []const u8) type { return struct { fn print() !void { - try std.fs.File.stdout().writeAll(message); + try std.Io.File.stdout().writeStreamingAll(io, message); } }; } @@ -19,11 +20,12 @@ pub fn main() !void { #update=change line number #file=main.zig const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); fn Printer(message: []const u8) type { return struct { fn print() !void { - try std.fs.File.stdout().writeAll(message); + try std.Io.File.stdout().writeStreamingAll(io, message); } }; } diff --git a/test/incremental/change_line_number b/test/incremental/change_line_number index 5c809b8fa99b..7bafbbfbdd9d 100644 --- a/test/incremental/change_line_number +++ b/test/incremental/change_line_number @@ -5,14 +5,16 @@ #file=main.zig const std = @import("std"); pub fn main() !void { - try std.fs.File.stdout().writeAll("foo\n"); + try std.Io.File.stdout().writeStreamingAll(io, "foo\n"); } +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="foo\n" #update=change line number #file=main.zig const std = @import("std"); pub fn main() !void { - try std.fs.File.stdout().writeAll("foo\n"); + try std.Io.File.stdout().writeStreamingAll(io, "foo\n"); } +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="foo\n" diff --git a/test/incremental/change_panic_handler b/test/incremental/change_panic_handler index 070384887a21..ebce3bc3121b 100644 --- a/test/incremental/change_panic_handler +++ b/test/incremental/change_panic_handler @@ -12,11 +12,12 @@ pub fn main() !u8 { } pub const panic = std.debug.FullPanic(myPanic); fn myPanic(msg: []const u8, _: ?usize) noreturn { - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); stdout_writer.interface.print("panic message: {s}\n", .{msg}) catch {}; std.process.exit(0); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="panic message: integer overflow\n" #update=change the panic handler body @@ -29,11 +30,12 @@ pub fn main() !u8 { } pub const panic = std.debug.FullPanic(myPanic); fn myPanic(msg: []const u8, _: ?usize) noreturn { - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); stdout_writer.interface.print("new panic message: {s}\n", .{msg}) catch {}; std.process.exit(0); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="new panic message: integer overflow\n" #update=change the panic handler function value @@ -46,9 +48,10 @@ pub fn main() !u8 { } pub const panic = std.debug.FullPanic(myPanicNew); fn myPanicNew(msg: []const u8, _: ?usize) noreturn { - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); stdout_writer.interface.print("third panic message: {s}\n", .{msg}) catch {}; std.process.exit(0); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="third panic message: integer overflow\n" diff --git a/test/incremental/change_panic_handler_explicit b/test/incremental/change_panic_handler_explicit index 774b18bbfd2c..366bffca45ba 100644 --- a/test/incremental/change_panic_handler_explicit +++ b/test/incremental/change_panic_handler_explicit @@ -42,11 +42,12 @@ pub const panic = struct { pub const noreturnReturned = no_panic.noreturnReturned; }; fn myPanic(msg: []const u8, _: ?usize) noreturn { - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); stdout_writer.interface.print("panic message: {s}\n", .{msg}) catch {}; std.process.exit(0); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="panic message: integer overflow\n" #update=change the panic handler body @@ -89,11 +90,12 @@ pub const panic = struct { pub const noreturnReturned = no_panic.noreturnReturned; }; fn myPanic(msg: []const u8, _: ?usize) noreturn { - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); stdout_writer.interface.print("new panic message: {s}\n", .{msg}) catch {}; std.process.exit(0); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="new panic message: integer overflow\n" #update=change the panic handler function value @@ -136,9 +138,10 @@ pub const panic = struct { pub const noreturnReturned = no_panic.noreturnReturned; }; fn myPanicNew(msg: []const u8, _: ?usize) noreturn { - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); stdout_writer.interface.print("third panic message: {s}\n", .{msg}) catch {}; std.process.exit(0); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="third panic message: integer overflow\n" diff --git a/test/incremental/change_shift_op b/test/incremental/change_shift_op index 41b5d1926644..af849c0d5b6c 100644 --- a/test/incremental/change_shift_op +++ b/test/incremental/change_shift_op @@ -9,10 +9,11 @@ pub fn main() !void { try foo(0x1300); } fn foo(x: u16) !void { - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); try stdout_writer.interface.print("0x{x}\n", .{x << 4}); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="0x3000\n" #update=change to right shift #file=main.zig @@ -20,8 +21,9 @@ pub fn main() !void { try foo(0x1300); } fn foo(x: u16) !void { - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); try stdout_writer.interface.print("0x{x}\n", .{x >> 4}); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="0x130\n" diff --git a/test/incremental/change_struct_same_fields b/test/incremental/change_struct_same_fields index 7af116132627..3ba715f906d0 100644 --- a/test/incremental/change_struct_same_fields +++ b/test/incremental/change_struct_same_fields @@ -11,13 +11,14 @@ pub fn main() !void { try foo(&val); } fn foo(val: *const S) !void { - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); try stdout_writer.interface.print( "{d} {d}\n", .{ val.x, val.y }, ); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="100 200\n" #update=change struct layout @@ -28,13 +29,14 @@ pub fn main() !void { try foo(&val); } fn foo(val: *const S) !void { - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); try stdout_writer.interface.print( "{d} {d}\n", .{ val.x, val.y }, ); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="100 200\n" #update=change values @@ -45,11 +47,12 @@ pub fn main() !void { try foo(&val); } fn foo(val: *const S) !void { - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); try stdout_writer.interface.print( "{d} {d}\n", .{ val.x, val.y }, ); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="1234 5678\n" diff --git a/test/incremental/change_zon_file b/test/incremental/change_zon_file index 62f73dd3bf79..a966df5471c2 100644 --- a/test/incremental/change_zon_file +++ b/test/incremental/change_zon_file @@ -8,8 +8,9 @@ const std = @import("std"); const message: []const u8 = @import("message.zon"); pub fn main() !void { - try std.fs.File.stdout().writeAll(message); + try std.Io.File.stdout().writeStreamingAll(io, message); } +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #file=message.zon "Hello, World!\n" #expect_stdout="Hello, World!\n" @@ -29,8 +30,9 @@ pub fn main() !void { const std = @import("std"); const message: []const u8 = @import("message.zon"); pub fn main() !void { - try std.fs.File.stdout().writeAll("a hardcoded string\n"); + try std.Io.File.stdout().writeStreamingAll(io, "a hardcoded string\n"); } +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_error=message.zon:1:1: error: unable to load 'message.zon': FileNotFound #expect_error=main.zig:2:37: note: file imported here @@ -44,6 +46,7 @@ pub fn main() !void { const std = @import("std"); const message: []const u8 = @import("message.zon"); pub fn main() !void { - try std.fs.File.stdout().writeAll(message); + try std.Io.File.stdout().writeStreamingAll(io, message); } +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="We're back, World!\n" diff --git a/test/incremental/change_zon_file_no_result_type b/test/incremental/change_zon_file_no_result_type index 498543e4f159..6b3aa73dc6ee 100644 --- a/test/incremental/change_zon_file_no_result_type +++ b/test/incremental/change_zon_file_no_result_type @@ -6,8 +6,9 @@ #update=initial version #file=main.zig const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); pub fn main() !void { - try std.fs.File.stdout().writeAll(@import("foo.zon").message); + try std.Io.File.stdout().writeStreamingAll(io, @import("foo.zon").message); } #file=foo.zon .{ diff --git a/test/incremental/compile_log b/test/incremental/compile_log index 697bb26569a7..19ff7237f275 100644 --- a/test/incremental/compile_log +++ b/test/incremental/compile_log @@ -8,17 +8,19 @@ #file=main.zig const std = @import("std"); pub fn main() !void { - try std.fs.File.stdout().writeAll("Hello, World!\n"); + try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); } +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="Hello, World!\n" #update=add compile log #file=main.zig const std = @import("std"); pub fn main() !void { - try std.fs.File.stdout().writeAll("Hello, World!\n"); + try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); @compileLog("this is a log"); } +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_error=main.zig:4:5: error: found compile log statement #expect_compile_log=@as(*const [13:0]u8, "this is a log") @@ -26,6 +28,7 @@ pub fn main() !void { #file=main.zig const std = @import("std"); pub fn main() !void { - try std.fs.File.stdout().writeAll("Hello, World!\n"); + try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); } +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="Hello, World!\n" diff --git a/test/incremental/fix_astgen_failure b/test/incremental/fix_astgen_failure index 8b1b3adbf782..dca371f52180 100644 --- a/test/incremental/fix_astgen_failure +++ b/test/incremental/fix_astgen_failure @@ -10,28 +10,31 @@ pub fn main() !void { } #file=foo.zig pub fn hello() !void { - try std.fs.File.stdout().writeAll("Hello, World!\n"); + try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); } #expect_error=foo.zig:2:9: error: use of undeclared identifier 'std' #update=fix the error #file=foo.zig const std = @import("std"); pub fn hello() !void { - try std.fs.File.stdout().writeAll("Hello, World!\n"); + try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); } +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="Hello, World!\n" #update=add new error #file=foo.zig const std = @import("std"); pub fn hello() !void { - try std.fs.File.stdout().writeAll(hello_str); + try std.Io.File.stdout().writeStreamingAll(io, hello_str); } -#expect_error=foo.zig:3:39: error: use of undeclared identifier 'hello_str' +const io = std.Io.Threaded.global_single_threaded.ioBasic(); +#expect_error=foo.zig:3:52: error: use of undeclared identifier 'hello_str' #update=fix the new error #file=foo.zig const std = @import("std"); const hello_str = "Hello, World! Again!\n"; pub fn hello() !void { - try std.fs.File.stdout().writeAll(hello_str); + try std.Io.File.stdout().writeStreamingAll(io, hello_str); } +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="Hello, World! Again!\n" diff --git a/test/incremental/function_becomes_inline b/test/incremental/function_becomes_inline index 240d7a54af49..402157584252 100644 --- a/test/incremental/function_becomes_inline +++ b/test/incremental/function_becomes_inline @@ -8,9 +8,10 @@ pub fn main() !void { try foo(); } fn foo() !void { - try std.fs.File.stdout().writeAll("Hello, World!\n"); + try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="Hello, World!\n" #update=make function inline @@ -19,9 +20,10 @@ pub fn main() !void { try foo(); } inline fn foo() !void { - try std.fs.File.stdout().writeAll("Hello, World!\n"); + try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="Hello, World!\n" #update=change string @@ -30,7 +32,8 @@ pub fn main() !void { try foo(); } inline fn foo() !void { - try std.fs.File.stdout().writeAll("Hello, `inline` World!\n"); + try std.Io.File.stdout().writeStreamingAll(io, "Hello, `inline` World!\n"); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="Hello, `inline` World!\n" diff --git a/test/incremental/hello b/test/incremental/hello index dc6f02177fc4..48659e1879ed 100644 --- a/test/incremental/hello +++ b/test/incremental/hello @@ -6,14 +6,16 @@ #update=initial version #file=main.zig const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); pub fn main() !void { - try std.fs.File.stdout().writeAll("good morning\n"); + try std.Io.File.stdout().writeStreamingAll(io, "good morning\n"); } #expect_stdout="good morning\n" #update=change the string #file=main.zig const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); pub fn main() !void { - try std.fs.File.stdout().writeAll("おはようございます\n"); + try std.Io.File.stdout().writeStreamingAll(io, "おはようございます\n"); } #expect_stdout="おはようございます\n" diff --git a/test/incremental/make_decl_pub b/test/incremental/make_decl_pub index b25b11716092..b193deb68cf0 100644 --- a/test/incremental/make_decl_pub +++ b/test/incremental/make_decl_pub @@ -12,8 +12,9 @@ pub fn main() !void { #file=foo.zig const std = @import("std"); fn hello() !void { - try std.fs.File.stdout().writeAll("Hello, World!\n"); + try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); } +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_error=main.zig:3:12: error: 'hello' is not marked 'pub' #expect_error=foo.zig:2:1: note: declared here @@ -21,6 +22,7 @@ fn hello() !void { #file=foo.zig const std = @import("std"); pub fn hello() !void { - try std.fs.File.stdout().writeAll("Hello, World!\n"); + try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); } +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="Hello, World!\n" diff --git a/test/incremental/modify_inline_fn b/test/incremental/modify_inline_fn index d485d8ffd5ea..19e201f1d9e2 100644 --- a/test/incremental/modify_inline_fn +++ b/test/incremental/modify_inline_fn @@ -8,20 +8,22 @@ const std = @import("std"); pub fn main() !void { const str = getStr(); - try std.fs.File.stdout().writeAll(str); + try std.Io.File.stdout().writeStreamingAll(io, str); } inline fn getStr() []const u8 { return "foo\n"; } +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="foo\n" #update=change the string #file=main.zig const std = @import("std"); pub fn main() !void { const str = getStr(); - try std.fs.File.stdout().writeAll(str); + try std.Io.File.stdout().writeStreamingAll(io, str); } inline fn getStr() []const u8 { return "bar\n"; } +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="bar\n" diff --git a/test/incremental/move_src b/test/incremental/move_src index 4f43e8ea6ac5..b79a25df8df1 100644 --- a/test/incremental/move_src +++ b/test/incremental/move_src @@ -7,7 +7,7 @@ #file=main.zig const std = @import("std"); pub fn main() !void { - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); try stdout_writer.interface.print("{d} {d}\n", .{ foo(), bar() }); } fn foo() u32 { @@ -16,13 +16,14 @@ fn foo() u32 { fn bar() u32 { return 123; } +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="7 123\n" #update=add newline #file=main.zig const std = @import("std"); pub fn main() !void { - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); try stdout_writer.interface.print("{d} {d}\n", .{ foo(), bar() }); } @@ -32,4 +33,5 @@ fn foo() u32 { fn bar() u32 { return 123; } +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="8 123\n" diff --git a/test/incremental/no_change_preserves_tag_names b/test/incremental/no_change_preserves_tag_names index 623496119d13..dc89face50db 100644 --- a/test/incremental/no_change_preserves_tag_names +++ b/test/incremental/no_change_preserves_tag_names @@ -7,15 +7,17 @@ #file=main.zig const std = @import("std"); var some_enum: enum { first, second } = .first; +const io = std.Io.Threaded.global_single_threaded.ioBasic(); pub fn main() !void { - try std.fs.File.stdout().writeAll(@tagName(some_enum)); + try std.Io.File.stdout().writeStreamingAll(io, @tagName(some_enum)); } #expect_stdout="first" #update=no change #file=main.zig const std = @import("std"); var some_enum: enum { first, second } = .first; +const io = std.Io.Threaded.global_single_threaded.ioBasic(); pub fn main() !void { - try std.fs.File.stdout().writeAll(@tagName(some_enum)); + try std.Io.File.stdout().writeStreamingAll(io, @tagName(some_enum)); } #expect_stdout="first" diff --git a/test/incremental/recursive_function_becomes_non_recursive b/test/incremental/recursive_function_becomes_non_recursive index a5a03749b8eb..5cee1bfbcff1 100644 --- a/test/incremental/recursive_function_becomes_non_recursive +++ b/test/incremental/recursive_function_becomes_non_recursive @@ -9,11 +9,12 @@ pub fn main() !void { try foo(false); } fn foo(recurse: bool) !void { - const stdout = std.fs.File.stdout(); + const stdout = std.Io.File.stdout(); if (recurse) return foo(true); - try stdout.writeAll("non-recursive path\n"); + try stdout.writeStreamingAll(io, "non-recursive path\n"); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="non-recursive path\n" #update=eliminate recursion and change argument @@ -22,9 +23,10 @@ pub fn main() !void { try foo(true); } fn foo(recurse: bool) !void { - const stdout = std.fs.File.stdout(); - if (recurse) return stdout.writeAll("x==1\n"); - try stdout.writeAll("non-recursive path\n"); + const stdout = std.Io.File.stdout(); + if (recurse) return stdout.writeStreamingAll(io, "x==1\n"); + try stdout.writeStreamingAll(io, "non-recursive path\n"); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="x==1\n" diff --git a/test/incremental/remove_enum_field b/test/incremental/remove_enum_field index 02daf2a0fb0e..c964285707de 100644 --- a/test/incremental/remove_enum_field +++ b/test/incremental/remove_enum_field @@ -10,10 +10,11 @@ const MyEnum = enum(u8) { bar = 2, }; pub fn main() !void { - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); try stdout_writer.interface.print("{}\n", .{@intFromEnum(MyEnum.foo)}); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="1\n" #update=remove enum field #file=main.zig @@ -22,9 +23,10 @@ const MyEnum = enum(u8) { bar = 2, }; pub fn main() !void { - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); try stdout_writer.interface.print("{}\n", .{@intFromEnum(MyEnum.foo)}); } const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_error=main.zig:7:69: error: enum 'main.MyEnum' has no member named 'foo' #expect_error=main.zig:1:16: note: enum declared here diff --git a/test/incremental/unreferenced_error b/test/incremental/unreferenced_error index 505fb3d5f414..c9a3277487c1 100644 --- a/test/incremental/unreferenced_error +++ b/test/incremental/unreferenced_error @@ -7,36 +7,40 @@ #file=main.zig const std = @import("std"); pub fn main() !void { - try std.fs.File.stdout().writeAll(a); + try std.Io.File.stdout().writeStreamingAll(io, a); } const a = "Hello, World!\n"; +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="Hello, World!\n" #update=introduce compile error #file=main.zig const std = @import("std"); pub fn main() !void { - try std.fs.File.stdout().writeAll(a); + try std.Io.File.stdout().writeStreamingAll(io, a); } const a = @compileError("bad a"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_error=main.zig:5:11: error: bad a #update=remove error reference #file=main.zig const std = @import("std"); pub fn main() !void { - try std.fs.File.stdout().writeAll(b); + try std.Io.File.stdout().writeStreamingAll(io, b); } const a = @compileError("bad a"); const b = "Hi there!\n"; +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="Hi there!\n" #update=introduce and remove reference to error #file=main.zig const std = @import("std"); pub fn main() !void { - try std.fs.File.stdout().writeAll(a); + try std.Io.File.stdout().writeStreamingAll(io, a); } const a = "Back to a\n"; const b = @compileError("bad b"); +const io = std.Io.Threaded.global_single_threaded.ioBasic(); #expect_stdout="Back to a\n" diff --git a/test/link/bss/main.zig b/test/link/bss/main.zig index 2785a8360f0b..0d69f9745033 100644 --- a/test/link/bss/main.zig +++ b/test/link/bss/main.zig @@ -4,7 +4,7 @@ const std = @import("std"); var buffer: [0x1000000]u64 = [1]u64{0} ** 0x1000000; pub fn main() anyerror!void { - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(std.Options.debug_io, &.{}); buffer[0x10] = 1; diff --git a/test/link/elf.zig b/test/link/elf.zig index 824fc76e9279..d5b0eb75196d 100644 --- a/test/link/elf.zig +++ b/test/link/elf.zig @@ -1323,7 +1323,7 @@ fn testGcSectionsZig(b: *Build, opts: Options) *Step { \\extern var live_var2: i32; \\extern fn live_fn2() void; \\pub fn main() void { - \\ var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + \\ var stdout_writer = std.Io.File.stdout().writerStreaming(std.Options.debug_io, &.{}); \\ stdout_writer.interface.print("{d} {d}\n", .{ live_var1, live_var2 }) catch @panic("fail"); \\ live_fn2(); \\} @@ -1365,7 +1365,7 @@ fn testGcSectionsZig(b: *Build, opts: Options) *Step { \\extern var live_var2: i32; \\extern fn live_fn2() void; \\pub fn main() void { - \\ var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + \\ var stdout_writer = std.Io.File.stdout().writerStreaming(std.Options.debug_io, &.{}); \\ stdout_writer.interface.print("{d} {d}\n", .{ live_var1, live_var2 }) catch @panic("fail"); \\ live_fn2(); \\} diff --git a/test/link/macho.zig b/test/link/macho.zig index 4fc0cad0eedb..ccfecefa4402 100644 --- a/test/link/macho.zig +++ b/test/link/macho.zig @@ -716,7 +716,7 @@ fn testHelloZig(b: *Build, opts: Options) *Step { const exe = addExecutable(b, opts, .{ .name = "main", .zig_source_bytes = \\const std = @import("std"); \\pub fn main() void { - \\ std.fs.File.stdout().writeAll("Hello world!\n") catch @panic("fail"); + \\ std.Io.File.stdout().writeStreamingAll(std.Options.debug_io, "Hello world!\n") catch @panic("fail"); \\} }); @@ -868,9 +868,10 @@ fn testLayout(b: *Build, opts: Options) *Step { } fn testLinkDirectlyCppTbd(b: *Build, opts: Options) *Step { + const io = b.graph.io; const test_step = addTestStep(b, "link-directly-cpp-tbd", opts); - const sdk = std.zig.system.darwin.getSdk(b.allocator, &opts.target.result) orelse + const sdk = std.zig.system.darwin.getSdk(b.allocator, io, &opts.target.result) orelse @panic("macOS SDK is required to run the test"); const exe = addExecutable(b, opts, .{ @@ -2371,7 +2372,7 @@ fn testTlsZig(b: *Build, opts: Options) *Step { \\threadlocal var x: i32 = 0; \\threadlocal var y: i32 = -1; \\pub fn main() void { - \\ var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + \\ var stdout_writer = std.Io.File.stdout().writerStreaming(std.Options.debug_io, &.{}); \\ stdout_writer.interface.print("{d} {d}\n", .{x, y}) catch unreachable; \\ x -= 1; \\ y += 1; diff --git a/test/link/wasm/extern/main.zig b/test/link/wasm/extern/main.zig index 9635f64a4000..51c5f841815c 100644 --- a/test/link/wasm/extern/main.zig +++ b/test/link/wasm/extern/main.zig @@ -3,6 +3,6 @@ const std = @import("std"); extern const foo: u32; pub fn main() void { - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(std.Options.debug_io, &.{}); stdout_writer.interface.print("Result: {d}", .{foo}) catch {}; } diff --git a/test/llvm_targets.zig b/test/llvm_targets.zig index ff6ed6830073..1ff0cf426dde 100644 --- a/test/llvm_targets.zig +++ b/test/llvm_targets.zig @@ -65,7 +65,6 @@ const targets = [_]std.Target.Query{ .{ .cpu_arch = .arm, .os_tag = .netbsd, .abi = .eabi }, .{ .cpu_arch = .arm, .os_tag = .netbsd, .abi = .eabihf }, .{ .cpu_arch = .arm, .os_tag = .openbsd, .abi = .eabi }, - .{ .cpu_arch = .arm, .os_tag = .openbsd, .abi = .eabihf }, .{ .cpu_arch = .arm, .os_tag = .rtems, .abi = .eabi }, .{ .cpu_arch = .arm, .os_tag = .rtems, .abi = .eabihf }, // .{ .cpu_arch = .arm, .os_tag = .uefi, .abi = .eabi }, @@ -187,7 +186,6 @@ const targets = [_]std.Target.Query{ .{ .cpu_arch = .powerpc, .os_tag = .linux, .abi = .musleabihf }, .{ .cpu_arch = .powerpc, .os_tag = .netbsd, .abi = .eabi }, .{ .cpu_arch = .powerpc, .os_tag = .netbsd, .abi = .eabihf }, - .{ .cpu_arch = .powerpc, .os_tag = .openbsd, .abi = .eabi }, .{ .cpu_arch = .powerpc, .os_tag = .openbsd, .abi = .eabihf }, .{ .cpu_arch = .powerpc, .os_tag = .rtems, .abi = .eabi }, .{ .cpu_arch = .powerpc, .os_tag = .rtems, .abi = .eabihf }, diff --git a/test/src/Cases.zig b/test/src/Cases.zig index 95ee7e21e751..ab28f2be6faf 100644 --- a/test/src/Cases.zig +++ b/test/src/Cases.zig @@ -1,6 +1,8 @@ const Cases = @This(); const builtin = @import("builtin"); + const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; const Allocator = std.mem.Allocator; const getExternalExecutor = std.zig.system.getExternalExecutor; @@ -8,6 +10,7 @@ const ArrayList = std.ArrayList; gpa: Allocator, arena: Allocator, +io: Io, cases: std.array_list.Managed(Case), pub const IncrementalCase = struct { @@ -313,7 +316,7 @@ pub fn addCompile( /// Each file should include a test manifest as a contiguous block of comments at /// the end of the file. The first line should be the test type, followed by a set of /// key-value config values, followed by a blank line, then the expected output. -pub fn addFromDir(ctx: *Cases, dir: std.fs.Dir, b: *std.Build) void { +pub fn addFromDir(ctx: *Cases, dir: Io.Dir, b: *std.Build) void { var current_file: []const u8 = "none"; ctx.addFromDirInner(dir, ¤t_file, b) catch |err| { std.debug.panicExtra( @@ -326,16 +329,17 @@ pub fn addFromDir(ctx: *Cases, dir: std.fs.Dir, b: *std.Build) void { fn addFromDirInner( ctx: *Cases, - iterable_dir: std.fs.Dir, + iterable_dir: Io.Dir, /// This is kept up to date with the currently being processed file so /// that if any errors occur the caller knows it happened during this file. current_file: *[]const u8, b: *std.Build, ) !void { + const io = ctx.io; var it = try iterable_dir.walk(ctx.arena); var filenames: ArrayList([]const u8) = .empty; - while (try it.next()) |entry| { + while (try it.next(io)) |entry| { if (entry.kind != .file) continue; // Ignore stuff such as .swp files @@ -347,7 +351,7 @@ fn addFromDirInner( current_file.* = filename; const max_file_size = 10 * 1024 * 1024; - const src = try iterable_dir.readFileAllocOptions(filename, ctx.arena, .limited(max_file_size), .@"1", 0); + const src = try iterable_dir.readFileAllocOptions(io, filename, ctx.arena, .limited(max_file_size), .@"1", 0); // Parse the manifest var manifest = try TestManifest.parse(ctx.arena, src); @@ -370,16 +374,18 @@ fn addFromDirInner( const resolved_target = b.resolveTargetQuery(target_query); const target = &resolved_target.result; for (backends) |backend| { - if (backend == .selfhosted and target.cpu.arch == .wasm32) { - // https://github.com/ziglang/zig/issues/25684 - continue; - } if (backend == .selfhosted and target.cpu.arch != .aarch64 and target.cpu.arch != .wasm32 and target.cpu.arch != .x86_64 and target.cpu.arch != .spirv64) { // Other backends don't support new liveness format continue; } + + if (backend == .selfhosted and target.cpu.arch == .aarch64) { + // https://codeberg.org/ziglang/zig/pulls/30232#issuecomment-9182045 + continue; + } + if (backend == .selfhosted and target.os.tag == .macos and target.cpu.arch == .x86_64 and builtin.cpu.arch == .aarch64) { @@ -431,9 +437,10 @@ fn addFromDirInner( } } -pub fn init(gpa: Allocator, arena: Allocator) Cases { +pub fn init(gpa: Allocator, arena: Allocator, io: Io) Cases { return .{ .gpa = gpa, + .io = io, .cases = .init(gpa), .arena = arena, }; @@ -444,8 +451,11 @@ pub const CaseTestOptions = struct { test_target_filters: []const []const u8, skip_compile_errors: bool, skip_non_native: bool, + skip_spirv: bool, + skip_wasm: bool, skip_freebsd: bool, skip_netbsd: bool, + skip_openbsd: bool, skip_windows: bool, skip_darwin: bool, skip_linux: bool, @@ -459,6 +469,7 @@ pub fn lowerToBuildSteps( parent_step: *std.Build.Step, options: CaseTestOptions, ) void { + const io = self.io; const host = b.resolveTargetQuery(.{}); const cases_dir_path = b.build_root.join(b.allocator, &.{ "test", "cases" }) catch @panic("OOM"); @@ -472,8 +483,12 @@ pub fn lowerToBuildSteps( if (options.skip_non_native and !case.target.query.isNative()) continue; + if (options.skip_spirv and case.target.query.cpu_arch != null and case.target.query.cpu_arch.?.isSpirV()) continue; + if (options.skip_wasm and case.target.query.cpu_arch != null and case.target.query.cpu_arch.?.isWasm()) continue; + if (options.skip_freebsd and case.target.query.os_tag == .freebsd) continue; if (options.skip_netbsd and case.target.query.os_tag == .netbsd) continue; + if (options.skip_openbsd and case.target.query.os_tag == .openbsd) continue; if (options.skip_windows and case.target.query.os_tag == .windows) continue; if (options.skip_darwin and case.target.query.os_tag != null and case.target.query.os_tag.?.isDarwin()) continue; if (options.skip_linux and case.target.query.os_tag == .linux) continue; @@ -590,7 +605,7 @@ pub fn lowerToBuildSteps( }, .Execution => |expected_stdout| no_exec: { const run = if (case.target.result.ofmt == .c) run_step: { - if (getExternalExecutor(&host.result, &case.target.result, .{ .link_libc = true }) != .native) { + if (getExternalExecutor(io, &host.result, &case.target.result, .{ .link_libc = true }) != .native) { // We wouldn't be able to run the compiled C code. break :no_exec; } diff --git a/test/src/Debugger.zig b/test/src/Debugger.zig index d975c8fbb56e..0d389f2508b2 100644 --- a/test/src/Debugger.zig +++ b/test/src/Debugger.zig @@ -2306,7 +2306,7 @@ fn addTest( run.addArgs(db_argv2); run.addArtifactArg(exe); for (expected_output) |expected| run.addCheck(.{ .expect_stdout_match = db.b.fmt("{s}\n", .{expected}) }); - run.addCheck(.{ .expect_term = .{ .Exited = success } }); + run.addCheck(.{ .expect_term = .{ .exited = success } }); run.setStdIn(.{ .bytes = "" }); db.root_step.dependOn(&run.step); } diff --git a/test/src/Libc.zig b/test/src/Libc.zig index 708e4c7bb800..7c61b58e0289 100644 --- a/test/src/Libc.zig +++ b/test/src/Libc.zig @@ -10,6 +10,7 @@ pub const Options = struct { optimize_modes: []const std.builtin.OptimizeMode, test_filters: []const []const u8, test_target_filters: []const []const u8, + skip_wasm: bool, max_rss: usize, }; @@ -41,6 +42,8 @@ pub fn addLibcTestCase( } pub fn addTarget(libc: *const Libc, target: std.Build.ResolvedTarget) void { + if (libc.options.skip_wasm and target.query.cpu_arch != null and target.query.cpu_arch.?.isWasm()) return; + if (libc.options.test_target_filters.len > 0) { const triple_txt = target.query.zigTriple(libc.b.allocator) catch @panic("OOM"); for (libc.options.test_target_filters) |filter| { diff --git a/test/src/StackTrace.zig b/test/src/StackTrace.zig index 57e29dd8000a..4e5c94668268 100644 --- a/test/src/StackTrace.zig +++ b/test/src/StackTrace.zig @@ -193,9 +193,9 @@ fn addCaseInstance( run.removeEnvironmentVariable("CLICOLOR_FORCE"); run.setEnvironmentVariable("NO_COLOR", "1"); run.addCheck(.{ .expect_term = term: { - if (!expect_panic) break :term .{ .Exited = 0 }; - if (target.result.os.tag == .windows) break :term .{ .Exited = 3 }; - break :term .{ .Signal = 6 }; + if (!expect_panic) break :term .{ .exited = 0 }; + if (target.result.os.tag == .windows) break :term .{ .exited = 3 }; + break :term .{ .signal = @enumFromInt(6) }; } }); run.expectStdOutEqual(""); diff --git a/test/src/convert-stack-trace.zig b/test/src/convert-stack-trace.zig index 91be53a8e5b2..272c43e31171 100644 --- a/test/src/convert-stack-trace.zig +++ b/test/src/convert-stack-trace.zig @@ -24,30 +24,23 @@ //! //! With these transformations, the test harness can safely do string comparisons. -pub fn main() !void { - var arena_instance: std.heap.ArenaAllocator = .init(std.heap.page_allocator); - defer arena_instance.deinit(); - const arena = arena_instance.allocator(); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const io = init.io; + const args = try init.minimal.args.toSlice(arena); - const args = try std.process.argsAlloc(arena); if (args.len != 2) std.process.fatal("usage: convert-stack-trace path/to/test/output", .{}); - const gpa = arena; - - var threaded: std.Io.Threaded = .init(gpa); - defer threaded.deinit(); - const io = threaded.io(); - var read_buf: [1024]u8 = undefined; var write_buf: [1024]u8 = undefined; - const in_file = try std.fs.cwd().openFile(args[1], .{}); - defer in_file.close(); + const in_file = try std.Io.Dir.cwd().openFile(io, args[1], .{}); + defer in_file.close(io); - const out_file: std.fs.File = .stdout(); + const out_file: std.Io.File = .stdout(); var in_fr = in_file.reader(io, &read_buf); - var out_fw = out_file.writer(&write_buf); + var out_fw = out_file.writer(io, &write_buf); const w = &out_fw.interface; diff --git a/test/standalone/build.zig b/test/standalone/build.zig index cf08c9b18284..9529e6907e4b 100644 --- a/test/standalone/build.zig +++ b/test/standalone/build.zig @@ -50,6 +50,7 @@ pub fn build(b: *std.Build) void { "../../tools/update_glibc.zig", "../../tools/update_mingw.zig", "../../tools/update_netbsd_libc.zig", + "../../tools/update_openbsd_libc.zig", }) |tool_src_path| { if (std.mem.endsWith(u8, tool_src_path, "dump-cov.zig") and tools_target.result.os.tag == .windows) continue; diff --git a/test/standalone/child_process/child.zig b/test/standalone/child_process/child.zig index 2e74f30882fd..8e19d53b3c62 100644 --- a/test/standalone/child_process/child.zig +++ b/test/standalone/child_process/child.zig @@ -4,50 +4,42 @@ const Io = std.Io; // 42 is expected by parent; other values result in test failure var exit_code: u8 = 42; -pub fn main() !void { - var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator); - const arena = arena_state.allocator(); - - var threaded: std.Io.Threaded = .init(arena); - defer threaded.deinit(); - const io = threaded.io(); - - try run(arena, io); - arena_state.deinit(); +pub fn main(init: std.process.Init) !void { + try run(init.arena.allocator(), init.io, init.minimal.args); std.process.exit(exit_code); } -fn run(allocator: std.mem.Allocator, io: Io) !void { - var args = try std.process.argsWithAllocator(allocator); - defer args.deinit(); - _ = args.next() orelse unreachable; // skip binary name +fn run(arena: std.mem.Allocator, io: Io, args: std.process.Args) !void { + var it = try args.iterateAllocator(arena); + defer it.deinit(); + _ = it.next() orelse unreachable; // skip binary name // test cmd args const hello_arg = "hello arg"; - const a1 = args.next() orelse unreachable; + const a1 = it.next() orelse unreachable; if (!std.mem.eql(u8, a1, hello_arg)) { - testError("first arg: '{s}'; want '{s}'", .{ a1, hello_arg }); + testError(io, "first arg: '{s}'; want '{s}'", .{ a1, hello_arg }); } - if (args.next()) |a2| { - testError("expected only one arg; got more: {s}", .{a2}); + if (it.next()) |a2| { + testError(io, "expected only one arg; got more: {s}", .{a2}); } // test stdout pipe; parent verifies - try std.fs.File.stdout().writeAll("hello from stdout"); + try std.Io.File.stdout().writeStreamingAll(io, "hello from stdout"); // test stdin pipe from parent const hello_stdin = "hello from stdin"; var buf: [hello_stdin.len]u8 = undefined; - const stdin: std.fs.File = .stdin(); + const stdin: std.Io.File = .stdin(); var reader = stdin.reader(io, &.{}); const n = try reader.interface.readSliceShort(&buf); if (!std.mem.eql(u8, buf[0..n], hello_stdin)) { - testError("stdin: '{s}'; want '{s}'", .{ buf[0..n], hello_stdin }); + testError(io, "stdin: '{s}'; want '{s}'", .{ buf[0..n], hello_stdin }); } } -fn testError(comptime fmt: []const u8, args: anytype) void { - var stderr_writer = std.fs.File.stderr().writer(&.{}); +fn testError(io: Io, comptime fmt: []const u8, args: anytype) void { + var stderr_writer = std.Io.File.stderr().writer(io, &.{}); const stderr = &stderr_writer.interface; stderr.print("CHILD TEST ERROR: ", .{}) catch {}; stderr.print(fmt, args) catch {}; diff --git a/test/standalone/child_process/main.zig b/test/standalone/child_process/main.zig index 5970cdd95283..2776c3e95c88 100644 --- a/test/standalone/child_process/main.zig +++ b/test/standalone/child_process/main.zig @@ -1,14 +1,21 @@ const std = @import("std"); +const Io = std.Io; -pub fn main() !void { +pub fn main(init: std.process.Init.Minimal) !void { // make sure safety checks are enabled even in release modes - var gpa_state = std.heap.GeneralPurposeAllocator(.{ .safety = true }){}; + var gpa_state: std.heap.GeneralPurposeAllocator(.{ .safety = true }) = .{}; defer if (gpa_state.deinit() != .ok) { @panic("found memory leaks"); }; const gpa = gpa_state.allocator(); - var it = try std.process.argsWithAllocator(gpa); + const process_cwd_path = try std.process.getCwdAlloc(gpa); + defer gpa.free(process_cwd_path); + + var environ_map = try init.environ.createMap(gpa); + defer environ_map.deinit(); + + var it = try init.args.iterateAllocator(gpa); defer it.deinit(); _ = it.next() orelse unreachable; // skip binary name const child_path, const needs_free = child_path: { @@ -16,22 +23,27 @@ pub fn main() !void { const cwd_path = it.next() orelse break :child_path .{ child_path, false }; // If there is a third argument, it is the current CWD somewhere within the cache directory. // In that case, modify the child path in order to test spawning a path with a leading `..` component. - break :child_path .{ try std.fs.path.relative(gpa, cwd_path, child_path), true }; + break :child_path .{ try std.fs.path.relative(gpa, process_cwd_path, &environ_map, cwd_path, child_path), true }; }; defer if (needs_free) gpa.free(child_path); - var threaded: std.Io.Threaded = .init(gpa); + var threaded: Io.Threaded = .init(gpa, .{ + .argv0 = .init(init.args), + .environ = init.environ, + }); defer threaded.deinit(); const io = threaded.io(); - var child = std.process.Child.init(&.{ child_path, "hello arg" }, gpa); - child.stdin_behavior = .Pipe; - child.stdout_behavior = .Pipe; - child.stderr_behavior = .Inherit; - try child.spawn(); + var child = try std.process.spawn(io, .{ + .argv = &.{ child_path, "hello arg" }, + .stdin = .pipe, + .stdout = .pipe, + .stderr = .inherit, + }); + const child_stdin = child.stdin.?; - try child_stdin.writeAll("hello from stdin"); // verified in child - child_stdin.close(); + try child_stdin.writeStreamingAll(io, "hello from stdin"); // verified in child + child_stdin.close(io); child.stdin = null; const hello_stdout = "hello from stdout"; @@ -39,30 +51,30 @@ pub fn main() !void { var stdout_reader = child.stdout.?.readerStreaming(io, &.{}); const n = try stdout_reader.interface.readSliceShort(&buf); if (!std.mem.eql(u8, buf[0..n], hello_stdout)) { - testError("child stdout: '{s}'; want '{s}'", .{ buf[0..n], hello_stdout }); + testError(io, "child stdout: '{s}'; want '{s}'", .{ buf[0..n], hello_stdout }); } - switch (try child.wait()) { - .Exited => |code| { + switch (try child.wait(io)) { + .exited => |code| { const child_ok_code = 42; // set by child if no test errors if (code != child_ok_code) { - testError("child exit code: {d}; want {d}", .{ code, child_ok_code }); + testError(io, "child exit code: {d}; want {d}", .{ code, child_ok_code }); } }, - else => |term| testError("abnormal child exit: {}", .{term}), + else => |term| testError(io, "abnormal child exit: {}", .{term}), } if (parent_test_error) return error.ParentTestError; // Check that FileNotFound is consistent across platforms when trying to spawn an executable that doesn't exist const missing_child_path = try std.mem.concat(gpa, u8, &.{ child_path, "_intentionally_missing" }); defer gpa.free(missing_child_path); - try std.testing.expectError(error.FileNotFound, std.process.Child.run(.{ .allocator = gpa, .argv = &.{missing_child_path} })); + try std.testing.expectError(error.FileNotFound, std.process.run(gpa, io, .{ .argv = &.{missing_child_path} })); } var parent_test_error = false; -fn testError(comptime fmt: []const u8, args: anytype) void { - var stderr_writer = std.fs.File.stderr().writer(&.{}); +fn testError(io: Io, comptime fmt: []const u8, args: anytype) void { + var stderr_writer = Io.File.stderr().writer(io, &.{}); const stderr = &stderr_writer.interface; stderr.print("PARENT TEST ERROR: ", .{}) catch {}; stderr.print(fmt, args) catch {}; diff --git a/test/standalone/cmakedefine/check.zig b/test/standalone/cmakedefine/check.zig index 782e7f4dc3c6..8db602f39d6d 100644 --- a/test/standalone/cmakedefine/check.zig +++ b/test/standalone/cmakedefine/check.zig @@ -1,16 +1,14 @@ -pub fn main() !void { - var arena_state: std.heap.ArenaAllocator = .init(std.heap.page_allocator); - defer arena_state.deinit(); - const arena = arena_state.allocator(); - - const args = try std.process.argsAlloc(arena); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const io = init.io; + const args = try init.minimal.args.toSlice(arena); if (args.len != 3) return error.BadUsage; const actual_path = args[1]; const expected_path = args[2]; - const actual = try std.fs.cwd().readFileAlloc(actual_path, arena, .limited(1024 * 1024)); - const expected = try std.fs.cwd().readFileAlloc(expected_path, arena, .limited(1024 * 1024)); + const actual = try std.Io.Dir.cwd().readFileAlloc(io, actual_path, arena, .limited(1024 * 1024)); + const expected = try std.Io.Dir.cwd().readFileAlloc(io, expected_path, arena, .limited(1024 * 1024)); // The actual output starts with a comment which we should strip out before comparing. const comment_str = "/* This file was generated by ConfigHeader using the Zig Build System. */\n"; diff --git a/test/standalone/coff_dwarf/main.zig b/test/standalone/coff_dwarf/main.zig index e7590f3f0746..79caaeb95a2f 100644 --- a/test/standalone/coff_dwarf/main.zig +++ b/test/standalone/coff_dwarf/main.zig @@ -3,18 +3,13 @@ const fatal = std.process.fatal; extern fn add(a: u32, b: u32, addr: *usize) u32; -pub fn main() void { - var debug_alloc_inst: std.heap.DebugAllocator(.{}) = .init; - defer std.debug.assert(debug_alloc_inst.deinit() == .ok); - const gpa = debug_alloc_inst.allocator(); +pub fn main(init: std.process.Init) void { + const gpa = init.gpa; + const io = init.io; var di: std.debug.SelfInfo = .init; defer di.deinit(gpa); - var threaded: std.Io.Threaded = .init(gpa); - defer threaded.deinit(); - const io = threaded.io(); - var add_addr: usize = undefined; _ = add(1, 2, &add_addr); diff --git a/test/standalone/config_header/build.zig b/test/standalone/config_header/build.zig index 3432685fceda..733a39690770 100644 --- a/test/standalone/config_header/build.zig +++ b/test/standalone/config_header/build.zig @@ -21,7 +21,7 @@ pub fn build(b: *std.Build) void { }, ); - const check_config_header = b.addCheckFile(config_header.getOutput(), .{ .expected_exact = @embedFile("config.h") }); + const check_config_header = b.addCheckFile(config_header.getOutputFile(), .{ .expected_exact = @embedFile("config.h") }); const test_step = b.step("test", "Test it"); test_step.dependOn(&check_config_header.step); diff --git a/test/standalone/dirname/build.zig b/test/standalone/dirname/build.zig index 0da85e29236d..2dc9e31d3d47 100644 --- a/test/standalone/dirname/build.zig +++ b/test/standalone/dirname/build.zig @@ -58,17 +58,9 @@ pub fn build(b: *std.Build) void { ); // Absolute path: - const abs_path = setup_abspath: { - const temp_dir = b.makeTempPath(); - - var dir = std.fs.cwd().openDir(temp_dir, .{}) catch @panic("failed to open temp dir"); - defer dir.close(); - - var file = dir.createFile("foo.txt", .{}) catch @panic("failed to create file"); - file.close(); - - break :setup_abspath std.Build.LazyPath{ .cwd_relative = temp_dir }; - }; + const write_files = b.addWriteFiles(); + _ = write_files.add("foo.txt", ""); + const abs_path = write_files.getDirectory(); addTestRun(test_step, exists_in, abs_path, &.{"foo.txt"}); } diff --git a/test/standalone/dirname/exists_in.zig b/test/standalone/dirname/exists_in.zig index 7aec1f423dce..5900e76b574b 100644 --- a/test/standalone/dirname/exists_in.zig +++ b/test/standalone/dirname/exists_in.zig @@ -11,16 +11,8 @@ const std = @import("std"); -pub fn main() !void { - var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator); - const arena = arena_state.allocator(); - defer arena_state.deinit(); - - try run(arena); -} - -fn run(allocator: std.mem.Allocator) !void { - var args = try std.process.argsWithAllocator(allocator); +pub fn main(init: std.process.Init) !void { + var args = try init.minimal.args.iterateAllocator(init.gpa); defer args.deinit(); _ = args.next() orelse unreachable; // skip binary name @@ -34,8 +26,10 @@ fn run(allocator: std.mem.Allocator) !void { return error.BadUsage; }; - var dir = try std.fs.cwd().openDir(dir_path, .{}); - defer dir.close(); + const io = std.Io.Threaded.global_single_threaded.ioBasic(); + + var dir = try std.Io.Dir.cwd().openDir(io, dir_path, .{}); + defer dir.close(io); - _ = try dir.statFile(relpath); + _ = try dir.statFile(io, relpath, .{}); } diff --git a/test/standalone/dirname/has_basename.zig b/test/standalone/dirname/has_basename.zig index 49eefa3b48e9..e0e408a3a491 100644 --- a/test/standalone/dirname/has_basename.zig +++ b/test/standalone/dirname/has_basename.zig @@ -13,16 +13,8 @@ const std = @import("std"); -pub fn main() !void { - var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator); - const arena = arena_state.allocator(); - defer arena_state.deinit(); - - try run(arena); -} - -fn run(allocator: std.mem.Allocator) !void { - var args = try std.process.argsWithAllocator(allocator); +pub fn main(init: std.process.Init) !void { + var args = try init.minimal.args.iterateAllocator(init.gpa); defer args.deinit(); _ = args.next() orelse unreachable; // skip binary name diff --git a/test/standalone/dirname/touch.zig b/test/standalone/dirname/touch.zig index 43fcabf91efa..6b0dad536e46 100644 --- a/test/standalone/dirname/touch.zig +++ b/test/standalone/dirname/touch.zig @@ -8,16 +8,8 @@ const std = @import("std"); -pub fn main() !void { - var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator); - const arena = arena_state.allocator(); - defer arena_state.deinit(); - - try run(arena); -} - -fn run(allocator: std.mem.Allocator) !void { - var args = try std.process.argsWithAllocator(allocator); +pub fn main(init: std.process.Init) !void { + var args = try init.minimal.args.iterateAllocator(init.gpa); defer args.deinit(); _ = args.next() orelse unreachable; // skip binary name @@ -26,14 +18,16 @@ fn run(allocator: std.mem.Allocator) !void { return error.BadUsage; }; - const dir_path = std.fs.path.dirname(path) orelse unreachable; - const basename = std.fs.path.basename(path); + const dir_path = std.Io.Dir.path.dirname(path) orelse unreachable; + const basename = std.Io.Dir.path.basename(path); + + const io = std.Io.Threaded.global_single_threaded.ioBasic(); - var dir = try std.fs.cwd().openDir(dir_path, .{}); - defer dir.close(); + var dir = try std.Io.Dir.cwd().openDir(io, dir_path, .{}); + defer dir.close(io); - _ = dir.statFile(basename) catch { - var file = try dir.createFile(basename, .{}); - file.close(); + _ = dir.statFile(io, basename, .{}) catch { + var file = try dir.createFile(io, basename, .{}); + file.close(io); }; } diff --git a/test/standalone/empty_env/build.zig b/test/standalone/empty_env/build.zig index 0eb8087ed2b9..97f77b9e3ed3 100644 --- a/test/standalone/empty_env/build.zig +++ b/test/standalone/empty_env/build.zig @@ -7,7 +7,7 @@ pub fn build(b: *std.Build) void { const optimize: std.builtin.OptimizeMode = .Debug; - if (builtin.os.tag == .windows and std.process.hasEnvVarConstant("ConEmuHWND")) { + if (builtin.os.tag == .windows and b.graph.environ_map.contains("ConEmuHWND")) { // ConEmu injects environment variables into processes before they are executed // depending on user settings. This obviously invalidates the test, so skipping // it is the best option. diff --git a/test/standalone/empty_env/main.zig b/test/standalone/empty_env/main.zig index 1dc435d9fa90..170a46de9e28 100644 --- a/test/standalone/empty_env/main.zig +++ b/test/standalone/empty_env/main.zig @@ -1,8 +1,5 @@ const std = @import("std"); -pub fn main() !void { - var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; - defer _ = gpa.deinit(); - const env_map = std.process.getEnvMap(gpa.allocator()) catch @panic("unable to get env map"); - try std.testing.expect(env_map.count() == 0); +pub fn main(init: std.process.Init) !void { + try std.testing.expectEqual(0, init.environ_map.count()); } diff --git a/test/standalone/entry_point/check_differ.zig b/test/standalone/entry_point/check_differ.zig index 63d1ec0294f2..be761d46ed03 100644 --- a/test/standalone/entry_point/check_differ.zig +++ b/test/standalone/entry_point/check_differ.zig @@ -1,17 +1,17 @@ -pub fn main() !void { - var arena_state: std.heap.ArenaAllocator = .init(std.heap.page_allocator); - defer arena_state.deinit(); - const arena = arena_state.allocator(); +const std = @import("std"); + +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const io = init.io; + const args = try init.minimal.args.toSlice(arena); - const args = try std.process.argsAlloc(arena); if (args.len != 3) return error.BadUsage; // usage: 'check_differ ' - const contents_1 = try std.fs.cwd().readFileAlloc(args[1], arena, .limited(1024 * 1024 * 64)); // 64 MiB ought to be plenty - const contents_2 = try std.fs.cwd().readFileAlloc(args[2], arena, .limited(1024 * 1024 * 64)); // 64 MiB ought to be plenty + const contents_1 = try std.Io.Dir.cwd().readFileAlloc(io, args[1], arena, .limited(1024 * 1024 * 64)); // 64 MiB ought to be plenty + const contents_2 = try std.Io.Dir.cwd().readFileAlloc(io, args[2], arena, .limited(1024 * 1024 * 64)); // 64 MiB ought to be plenty if (std.mem.eql(u8, contents_1, contents_2)) { return error.FilesMatch; } // success, files differ } -const std = @import("std"); diff --git a/test/standalone/env_vars/main.zig b/test/standalone/env_vars/main.zig index 12b911404a76..09167f285fe9 100644 --- a/test/standalone/env_vars/main.zig +++ b/test/standalone/env_vars/main.zig @@ -2,172 +2,150 @@ const std = @import("std"); const builtin = @import("builtin"); // Note: the environment variables under test are set by the build.zig -pub fn main() !void { - var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; - defer _ = gpa.deinit(); - const allocator = gpa.allocator(); +pub fn main(init: std.process.Init) !void { + @setEvalBranchQuota(10000); - var arena_state = std.heap.ArenaAllocator.init(allocator); - defer arena_state.deinit(); - const arena = arena_state.allocator(); + const allocator = init.gpa; + const arena = init.arena.allocator(); + const environ = init.minimal.environ; - // hasNonEmptyEnvVar + // containsUnempty { - try std.testing.expect(try std.process.hasNonEmptyEnvVar(allocator, "FOO")); - try std.testing.expect(!(try std.process.hasNonEmptyEnvVar(allocator, "FOO="))); - try std.testing.expect(!(try std.process.hasNonEmptyEnvVar(allocator, "FO"))); - try std.testing.expect(!(try std.process.hasNonEmptyEnvVar(allocator, "FOOO"))); + try std.testing.expect(try environ.containsUnempty(allocator, "FOO")); + try std.testing.expect(!(try environ.containsUnempty(allocator, "FOO="))); + try std.testing.expect(!(try environ.containsUnempty(allocator, "FO"))); + try std.testing.expect(!(try environ.containsUnempty(allocator, "FOOO"))); if (builtin.os.tag == .windows) { - try std.testing.expect(try std.process.hasNonEmptyEnvVar(allocator, "foo")); + try std.testing.expect(try environ.containsUnempty(allocator, "foo")); } - try std.testing.expect(try std.process.hasNonEmptyEnvVar(allocator, "EQUALS")); - try std.testing.expect(!(try std.process.hasNonEmptyEnvVar(allocator, "EQUALS=ABC"))); - try std.testing.expect(try std.process.hasNonEmptyEnvVar(allocator, "КИРиллИЦА")); + try std.testing.expect(try environ.containsUnempty(allocator, "EQUALS")); + try std.testing.expect(!(try environ.containsUnempty(allocator, "EQUALS=ABC"))); + try std.testing.expect(try environ.containsUnempty(allocator, "КИРиллИЦА")); if (builtin.os.tag == .windows) { - try std.testing.expect(try std.process.hasNonEmptyEnvVar(allocator, "кирИЛЛица")); + try std.testing.expect(try environ.containsUnempty(allocator, "кирИЛЛица")); } - try std.testing.expect(!(try std.process.hasNonEmptyEnvVar(allocator, "NO_VALUE"))); - try std.testing.expect(!(try std.process.hasNonEmptyEnvVar(allocator, "NOT_SET"))); + try std.testing.expect(!(try environ.containsUnempty(allocator, "NO_VALUE"))); + try std.testing.expect(!(try environ.containsUnempty(allocator, "NOT_SET"))); if (builtin.os.tag == .windows) { - try std.testing.expect(try std.process.hasNonEmptyEnvVar(allocator, "=HIDDEN")); - try std.testing.expect(try std.process.hasNonEmptyEnvVar(allocator, "INVALID_UTF16_\xed\xa0\x80")); + try std.testing.expect(try environ.containsUnempty(allocator, "=HIDDEN")); + try std.testing.expect(try environ.containsUnempty(allocator, "INVALID_UTF16_\xed\xa0\x80")); } } - // hasNonEmptyEnvVarContstant + // containsUnemptyConstant { - try std.testing.expect(std.process.hasNonEmptyEnvVarConstant("FOO")); - try std.testing.expect(!std.process.hasNonEmptyEnvVarConstant("FOO=")); - try std.testing.expect(!std.process.hasNonEmptyEnvVarConstant("FO")); - try std.testing.expect(!std.process.hasNonEmptyEnvVarConstant("FOOO")); + try std.testing.expect(environ.containsUnemptyConstant("FOO")); + try std.testing.expect(!environ.containsUnemptyConstant("FOO=")); + try std.testing.expect(!environ.containsUnemptyConstant("FO")); + try std.testing.expect(!environ.containsUnemptyConstant("FOOO")); if (builtin.os.tag == .windows) { - try std.testing.expect(std.process.hasNonEmptyEnvVarConstant("foo")); + try std.testing.expect(environ.containsUnemptyConstant("foo")); } - try std.testing.expect(std.process.hasNonEmptyEnvVarConstant("EQUALS")); - try std.testing.expect(!std.process.hasNonEmptyEnvVarConstant("EQUALS=ABC")); - try std.testing.expect(std.process.hasNonEmptyEnvVarConstant("КИРиллИЦА")); + try std.testing.expect(environ.containsUnemptyConstant("EQUALS")); + try std.testing.expect(!environ.containsUnemptyConstant("EQUALS=ABC")); + try std.testing.expect(environ.containsUnemptyConstant("КИРиллИЦА")); if (builtin.os.tag == .windows) { - try std.testing.expect(std.process.hasNonEmptyEnvVarConstant("кирИЛЛица")); + try std.testing.expect(environ.containsUnemptyConstant("кирИЛЛица")); } - try std.testing.expect(!(std.process.hasNonEmptyEnvVarConstant("NO_VALUE"))); - try std.testing.expect(!(std.process.hasNonEmptyEnvVarConstant("NOT_SET"))); + try std.testing.expect(!(environ.containsUnemptyConstant("NO_VALUE"))); + try std.testing.expect(!(environ.containsUnemptyConstant("NOT_SET"))); if (builtin.os.tag == .windows) { - try std.testing.expect(std.process.hasNonEmptyEnvVarConstant("=HIDDEN")); - try std.testing.expect(std.process.hasNonEmptyEnvVarConstant("INVALID_UTF16_\xed\xa0\x80")); + try std.testing.expect(environ.containsUnemptyConstant("=HIDDEN")); + try std.testing.expect(environ.containsUnemptyConstant("INVALID_UTF16_\xed\xa0\x80")); } } - // hasEnvVar + // contains { - try std.testing.expect(try std.process.hasEnvVar(allocator, "FOO")); - try std.testing.expect(!(try std.process.hasEnvVar(allocator, "FOO="))); - try std.testing.expect(!(try std.process.hasEnvVar(allocator, "FO"))); - try std.testing.expect(!(try std.process.hasEnvVar(allocator, "FOOO"))); + try std.testing.expect(try environ.contains(allocator, "FOO")); + try std.testing.expect(!(try environ.contains(allocator, "FOO="))); + try std.testing.expect(!(try environ.contains(allocator, "FO"))); + try std.testing.expect(!(try environ.contains(allocator, "FOOO"))); if (builtin.os.tag == .windows) { - try std.testing.expect(try std.process.hasEnvVar(allocator, "foo")); + try std.testing.expect(try environ.contains(allocator, "foo")); } - try std.testing.expect(try std.process.hasEnvVar(allocator, "EQUALS")); - try std.testing.expect(!(try std.process.hasEnvVar(allocator, "EQUALS=ABC"))); - try std.testing.expect(try std.process.hasEnvVar(allocator, "КИРиллИЦА")); + try std.testing.expect(try environ.contains(allocator, "EQUALS")); + try std.testing.expect(!(try environ.contains(allocator, "EQUALS=ABC"))); + try std.testing.expect(try environ.contains(allocator, "КИРиллИЦА")); if (builtin.os.tag == .windows) { - try std.testing.expect(try std.process.hasEnvVar(allocator, "кирИЛЛица")); + try std.testing.expect(try environ.contains(allocator, "кирИЛЛица")); } - try std.testing.expect(try std.process.hasEnvVar(allocator, "NO_VALUE")); - try std.testing.expect(!(try std.process.hasEnvVar(allocator, "NOT_SET"))); + try std.testing.expect(try environ.contains(allocator, "NO_VALUE")); + try std.testing.expect(!(try environ.contains(allocator, "NOT_SET"))); if (builtin.os.tag == .windows) { - try std.testing.expect(try std.process.hasEnvVar(allocator, "=HIDDEN")); - try std.testing.expect(try std.process.hasEnvVar(allocator, "INVALID_UTF16_\xed\xa0\x80")); + try std.testing.expect(try environ.contains(allocator, "=HIDDEN")); + try std.testing.expect(try environ.contains(allocator, "INVALID_UTF16_\xed\xa0\x80")); } } - // hasEnvVarConstant + // containsConstant { - try std.testing.expect(std.process.hasEnvVarConstant("FOO")); - try std.testing.expect(!std.process.hasEnvVarConstant("FOO=")); - try std.testing.expect(!std.process.hasEnvVarConstant("FO")); - try std.testing.expect(!std.process.hasEnvVarConstant("FOOO")); + try std.testing.expect(environ.containsConstant("FOO")); + try std.testing.expect(!environ.containsConstant("FOO=")); + try std.testing.expect(!environ.containsConstant("FO")); + try std.testing.expect(!environ.containsConstant("FOOO")); if (builtin.os.tag == .windows) { - try std.testing.expect(std.process.hasEnvVarConstant("foo")); + try std.testing.expect(environ.containsConstant("foo")); } - try std.testing.expect(std.process.hasEnvVarConstant("EQUALS")); - try std.testing.expect(!std.process.hasEnvVarConstant("EQUALS=ABC")); - try std.testing.expect(std.process.hasEnvVarConstant("КИРиллИЦА")); + try std.testing.expect(environ.containsConstant("EQUALS")); + try std.testing.expect(!environ.containsConstant("EQUALS=ABC")); + try std.testing.expect(environ.containsConstant("КИРиллИЦА")); if (builtin.os.tag == .windows) { - try std.testing.expect(std.process.hasEnvVarConstant("кирИЛЛица")); + try std.testing.expect(environ.containsConstant("кирИЛЛица")); } - try std.testing.expect(std.process.hasEnvVarConstant("NO_VALUE")); - try std.testing.expect(!(std.process.hasEnvVarConstant("NOT_SET"))); + try std.testing.expect(environ.containsConstant("NO_VALUE")); + try std.testing.expect(!(environ.containsConstant("NOT_SET"))); if (builtin.os.tag == .windows) { - try std.testing.expect(std.process.hasEnvVarConstant("=HIDDEN")); - try std.testing.expect(std.process.hasEnvVarConstant("INVALID_UTF16_\xed\xa0\x80")); + try std.testing.expect(environ.containsConstant("=HIDDEN")); + try std.testing.expect(environ.containsConstant("INVALID_UTF16_\xed\xa0\x80")); } } - // getEnvVarOwned + // getAlloc { - try std.testing.expectEqualSlices(u8, "123", try std.process.getEnvVarOwned(arena, "FOO")); - try std.testing.expectError(error.EnvironmentVariableNotFound, std.process.getEnvVarOwned(arena, "FOO=")); - try std.testing.expectError(error.EnvironmentVariableNotFound, std.process.getEnvVarOwned(arena, "FO")); - try std.testing.expectError(error.EnvironmentVariableNotFound, std.process.getEnvVarOwned(arena, "FOOO")); + try std.testing.expectEqualSlices(u8, "123", try environ.getAlloc(arena, "FOO")); + try std.testing.expectError(error.EnvironmentVariableMissing, environ.getAlloc(arena, "FOO=")); + try std.testing.expectError(error.EnvironmentVariableMissing, environ.getAlloc(arena, "FO")); + try std.testing.expectError(error.EnvironmentVariableMissing, environ.getAlloc(arena, "FOOO")); if (builtin.os.tag == .windows) { - try std.testing.expectEqualSlices(u8, "123", try std.process.getEnvVarOwned(arena, "foo")); + try std.testing.expectEqualSlices(u8, "123", try environ.getAlloc(arena, "foo")); } - try std.testing.expectEqualSlices(u8, "ABC=123", try std.process.getEnvVarOwned(arena, "EQUALS")); - try std.testing.expectError(error.EnvironmentVariableNotFound, std.process.getEnvVarOwned(arena, "EQUALS=ABC")); - try std.testing.expectEqualSlices(u8, "non-ascii አማርኛ \u{10FFFF}", try std.process.getEnvVarOwned(arena, "КИРиллИЦА")); + try std.testing.expectEqualSlices(u8, "ABC=123", try environ.getAlloc(arena, "EQUALS")); + try std.testing.expectError(error.EnvironmentVariableMissing, environ.getAlloc(arena, "EQUALS=ABC")); + try std.testing.expectEqualSlices(u8, "non-ascii አማርኛ \u{10FFFF}", try environ.getAlloc(arena, "КИРиллИЦА")); if (builtin.os.tag == .windows) { - try std.testing.expectEqualSlices(u8, "non-ascii አማርኛ \u{10FFFF}", try std.process.getEnvVarOwned(arena, "кирИЛЛица")); + try std.testing.expectEqualSlices(u8, "non-ascii አማርኛ \u{10FFFF}", try environ.getAlloc(arena, "кирИЛЛица")); } - try std.testing.expectEqualSlices(u8, "", try std.process.getEnvVarOwned(arena, "NO_VALUE")); - try std.testing.expectError(error.EnvironmentVariableNotFound, std.process.getEnvVarOwned(arena, "NOT_SET")); + try std.testing.expectEqualSlices(u8, "", try environ.getAlloc(arena, "NO_VALUE")); + try std.testing.expectError(error.EnvironmentVariableMissing, environ.getAlloc(arena, "NOT_SET")); if (builtin.os.tag == .windows) { - try std.testing.expectEqualSlices(u8, "hi", try std.process.getEnvVarOwned(arena, "=HIDDEN")); - try std.testing.expectEqualSlices(u8, "\xed\xa0\x80", try std.process.getEnvVarOwned(arena, "INVALID_UTF16_\xed\xa0\x80")); + try std.testing.expectEqualSlices(u8, "hi", try environ.getAlloc(arena, "=HIDDEN")); + try std.testing.expectEqualSlices(u8, "\xed\xa0\x80", try environ.getAlloc(arena, "INVALID_UTF16_\xed\xa0\x80")); } } - // parseEnvVarInt + // Environ.Map { - try std.testing.expectEqual(123, try std.process.parseEnvVarInt("FOO", u32, 10)); - try std.testing.expectError(error.EnvironmentVariableNotFound, std.process.parseEnvVarInt("FO", u32, 10)); - try std.testing.expectError(error.EnvironmentVariableNotFound, std.process.parseEnvVarInt("FOOO", u32, 10)); - try std.testing.expectEqual(0x123, try std.process.parseEnvVarInt("FOO", u32, 16)); - if (builtin.os.tag == .windows) { - try std.testing.expectEqual(123, try std.process.parseEnvVarInt("foo", u32, 10)); - } - try std.testing.expectError(error.InvalidCharacter, std.process.parseEnvVarInt("EQUALS", u32, 10)); - try std.testing.expectError(error.EnvironmentVariableNotFound, std.process.parseEnvVarInt("EQUALS=ABC", u32, 10)); - try std.testing.expectError(error.InvalidCharacter, std.process.parseEnvVarInt("КИРиллИЦА", u32, 10)); - try std.testing.expectError(error.InvalidCharacter, std.process.parseEnvVarInt("NO_VALUE", u32, 10)); - try std.testing.expectError(error.EnvironmentVariableNotFound, std.process.parseEnvVarInt("NOT_SET", u32, 10)); - if (builtin.os.tag == .windows) { - try std.testing.expectError(error.InvalidCharacter, std.process.parseEnvVarInt("=HIDDEN", u32, 10)); - try std.testing.expectError(error.InvalidCharacter, std.process.parseEnvVarInt("INVALID_UTF16_\xed\xa0\x80", u32, 10)); - } - } - - // EnvMap - { - var env_map = try std.process.getEnvMap(allocator); - defer env_map.deinit(); + var environ_map = try environ.createMap(allocator); + defer environ_map.deinit(); - try std.testing.expectEqualSlices(u8, "123", env_map.get("FOO").?); - try std.testing.expectEqual(null, env_map.get("FO")); - try std.testing.expectEqual(null, env_map.get("FOOO")); + try std.testing.expectEqualSlices(u8, "123", environ_map.get("FOO").?); + try std.testing.expectEqual(null, environ_map.get("FO")); + try std.testing.expectEqual(null, environ_map.get("FOOO")); if (builtin.os.tag == .windows) { - try std.testing.expectEqualSlices(u8, "123", env_map.get("foo").?); + try std.testing.expectEqualSlices(u8, "123", environ_map.get("foo").?); } - try std.testing.expectEqualSlices(u8, "ABC=123", env_map.get("EQUALS").?); - try std.testing.expectEqual(null, env_map.get("EQUALS=ABC")); - try std.testing.expectEqualSlices(u8, "non-ascii አማርኛ \u{10FFFF}", env_map.get("КИРиллИЦА").?); + try std.testing.expectEqualSlices(u8, "ABC=123", environ_map.get("EQUALS").?); + try std.testing.expectEqual(null, environ_map.get("EQUALS=ABC")); + try std.testing.expectEqualSlices(u8, "non-ascii አማርኛ \u{10FFFF}", environ_map.get("КИРиллИЦА").?); if (builtin.os.tag == .windows) { - try std.testing.expectEqualSlices(u8, "non-ascii አማርኛ \u{10FFFF}", env_map.get("кирИЛЛица").?); + try std.testing.expectEqualSlices(u8, "non-ascii አማርኛ \u{10FFFF}", environ_map.get("кирИЛЛица").?); } - try std.testing.expectEqualSlices(u8, "", env_map.get("NO_VALUE").?); - try std.testing.expectEqual(null, env_map.get("NOT_SET")); + try std.testing.expectEqualSlices(u8, "", environ_map.get("NO_VALUE").?); + try std.testing.expectEqual(null, environ_map.get("NOT_SET")); if (builtin.os.tag == .windows) { - try std.testing.expectEqualSlices(u8, "hi", env_map.get("=HIDDEN").?); - try std.testing.expectEqualSlices(u8, "\xed\xa0\x80", env_map.get("INVALID_UTF16_\xed\xa0\x80").?); + try std.testing.expectEqualSlices(u8, "hi", environ_map.get("=HIDDEN").?); + try std.testing.expectEqualSlices(u8, "\xed\xa0\x80", environ_map.get("INVALID_UTF16_\xed\xa0\x80").?); } } } diff --git a/test/standalone/glibc_compat/glibc_runtime_check.zig b/test/standalone/glibc_compat/glibc_runtime_check.zig index 30265a3adce9..78b1f7efb373 100644 --- a/test/standalone/glibc_compat/glibc_runtime_check.zig +++ b/test/standalone/glibc_compat/glibc_runtime_check.zig @@ -23,16 +23,19 @@ const c_string = @cImport( // Version of glibc this test is being built to run against const glibc_ver = builtin.os.versionRange().gnuLibCVersion().?; +extern "c" fn fstatat(dirfd: i32, path: [*:0]const u8, buf: [*]const u8, flag: u32) c_int; +extern "c" fn stat(noalias path: [*:0]const u8, noalias buf: [*]const u8) c_int; + // PR #17034 - fstat moved between libc_nonshared and libc fn checkStat() !void { - const cwdFd = std.fs.cwd().fd; + const cwd_fd = std.Io.Dir.cwd().handle; - var stat = std.mem.zeroes(std.c.Stat); - var result = std.c.fstatat(cwdFd, "a_file_that_definitely_does_not_exist", &stat, 0); + var buf: [256]u8 = @splat(0); + var result = fstatat(cwd_fd, "a_file_that_definitely_does_not_exist", &buf, 0); assert(result == -1); assert(std.posix.errno(result) == .NOENT); - result = std.c.stat("a_file_that_definitely_does_not_exist", &stat); + result = stat("a_file_that_definitely_does_not_exist", &buf); assert(result == -1); assert(std.posix.errno(result) == .NOENT); } diff --git a/test/standalone/install_headers/check_exists.zig b/test/standalone/install_headers/check_exists.zig index 62706749aac0..ac7dc62592da 100644 --- a/test/standalone/install_headers/check_exists.zig +++ b/test/standalone/install_headers/check_exists.zig @@ -2,17 +2,15 @@ const std = @import("std"); /// Checks the existence of files relative to cwd. /// A path starting with ! should not exist. -pub fn main() !void { - var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena_state.deinit(); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const io = init.io; - const arena = arena_state.allocator(); - - var arg_it = try std.process.argsWithAllocator(arena); + var arg_it = try init.minimal.args.iterateAllocator(arena); _ = arg_it.next(); - const cwd = std.fs.cwd(); - const cwd_realpath = try cwd.realpathAlloc(arena, "."); + const cwd = std.Io.Dir.cwd(); + const cwd_realpath = try cwd.realPathFileAlloc(io, ".", arena); while (arg_it.next()) |file_path| { if (file_path.len > 0 and file_path[0] == '!') { @@ -20,7 +18,7 @@ pub fn main() !void { "exclusive file check '{s}{c}{s}' failed", .{ cwd_realpath, std.fs.path.sep, file_path[1..] }, ); - if (std.fs.cwd().statFile(file_path[1..])) |_| { + if (cwd.statFile(io, file_path[1..], .{})) |_| { return error.FileFound; } else |err| switch (err) { error.FileNotFound => {}, @@ -31,7 +29,7 @@ pub fn main() !void { "inclusive file check '{s}{c}{s}' failed", .{ cwd_realpath, std.fs.path.sep, file_path }, ); - _ = try std.fs.cwd().statFile(file_path); + _ = try cwd.statFile(io, file_path, .{}); } } } diff --git a/test/standalone/ios/build.zig b/test/standalone/ios/build.zig index b07b5b17ea20..b87d55993b66 100644 --- a/test/standalone/ios/build.zig +++ b/test/standalone/ios/build.zig @@ -23,7 +23,9 @@ pub fn build(b: *std.Build) void { }), }); - if (std.zig.system.darwin.getSdk(b.allocator, &target.result)) |sdk| { + const io = b.graph.io; + + if (std.zig.system.darwin.getSdk(b.allocator, io, &target.result)) |sdk| { b.sysroot = sdk; exe.root_module.addSystemIncludePath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/usr/include" }) }); exe.root_module.addSystemFrameworkPath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/System/Library/Frameworks" }) }); diff --git a/test/standalone/libfuzzer/build.zig b/test/standalone/libfuzzer/build.zig index 54cc977abe86..ea3ae12e454c 100644 --- a/test/standalone/libfuzzer/build.zig +++ b/test/standalone/libfuzzer/build.zig @@ -6,6 +6,7 @@ pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); if (builtin.os.tag == .windows) return; // TODO: libfuzzer support for windows + if (builtin.os.tag == .openbsd) return; // https://codeberg.org/ziglang/zig/issues/30728 const run_step = b.step("run", "Run executables"); const exe = b.addExecutable(.{ diff --git a/test/standalone/libfuzzer/main.zig b/test/standalone/libfuzzer/main.zig index b275b6d593dc..836f25285b45 100644 --- a/test/standalone/libfuzzer/main.zig +++ b/test/standalone/libfuzzer/main.zig @@ -6,22 +6,17 @@ fn testOne(in: abi.Slice) callconv(.c) void { std.debug.assertReadable(in.toSlice()); } -pub fn main() !void { - var debug_gpa_ctx: std.heap.DebugAllocator(.{}) = .init; - defer _ = debug_gpa_ctx.deinit(); - const gpa = debug_gpa_ctx.allocator(); +pub fn main(init: std.process.Init) !void { + const gpa = init.gpa; + const io = init.io; - var args = try std.process.argsWithAllocator(gpa); + var args = try init.minimal.args.iterateAllocator(gpa); defer args.deinit(); _ = args.skip(); // executable name - var threaded: std.Io.Threaded = .init(gpa); - defer threaded.deinit(); - const io = threaded.io(); - const cache_dir_path = args.next() orelse @panic("expected cache directory path argument"); - var cache_dir = try std.fs.cwd().openDir(cache_dir_path, .{}); - defer cache_dir.close(); + var cache_dir = try std.Io.Dir.cwd().openDir(io, cache_dir_path, .{}); + defer cache_dir.close(io); abi.fuzzer_init(.fromSlice(cache_dir_path)); abi.fuzzer_init_test(testOne, .fromSlice("test")); @@ -30,8 +25,8 @@ pub fn main() !void { const pc_digest = abi.fuzzer_coverage().id; const coverage_file_path = "v/" ++ std.fmt.hex(pc_digest); - const coverage_file = try cache_dir.openFile(coverage_file_path, .{}); - defer coverage_file.close(); + const coverage_file = try cache_dir.openFile(io, coverage_file_path, .{}); + defer coverage_file.close(io); var read_buf: [@sizeOf(abi.SeenPcsHeader)]u8 = undefined; var r = coverage_file.reader(io, &read_buf); @@ -42,6 +37,6 @@ pub fn main() !void { const expected_len = @sizeOf(abi.SeenPcsHeader) + try std.math.divCeil(usize, pcs_header.pcs_len, @bitSizeOf(usize)) * @sizeOf(usize) + pcs_header.pcs_len * @sizeOf(usize); - if (try coverage_file.getEndPos() != expected_len) + if (try coverage_file.length(io) != expected_len) return error.WrongEnd; } diff --git a/test/standalone/load_dynamic_library/main.zig b/test/standalone/load_dynamic_library/main.zig index b9d2340d4c74..ac64e67cdadd 100644 --- a/test/standalone/load_dynamic_library/main.zig +++ b/test/standalone/load_dynamic_library/main.zig @@ -1,10 +1,7 @@ const std = @import("std"); -pub fn main() !void { - var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; - defer _ = gpa.deinit(); - const args = try std.process.argsAlloc(gpa.allocator()); - defer std.process.argsFree(gpa.allocator(), args); +pub fn main(init: std.process.Init) !void { + const args = try init.minimal.args.toSlice(init.arena.allocator()); const dynlib_name = args[1]; diff --git a/test/standalone/posix/build.zig b/test/standalone/posix/build.zig index 52ec99628db2..f163beea8a65 100644 --- a/test/standalone/posix/build.zig +++ b/test/standalone/posix/build.zig @@ -4,11 +4,13 @@ const builtin = @import("builtin"); const Case = struct { src_path: []const u8, set_env_vars: bool = false, + make_tmp_dir: bool = false, }; const cases = [_]Case{ .{ .src_path = "cwd.zig", + .make_tmp_dir = true, }, .{ .src_path = "getenv.zig", @@ -19,6 +21,7 @@ const cases = [_]Case{ }, .{ .src_path = "relpaths.zig", + .make_tmp_dir = true, }, }; @@ -69,6 +72,9 @@ fn run_exe(b: *std.Build, optimize: std.builtin.OptimizeMode, case: *const Case, }); const run_cmd = b.addRunArtifact(exe); + if (case.make_tmp_dir) { + run_cmd.addDirectoryArg(b.tmpPath()); + } if (case.set_env_vars) { run_cmd.setEnvironmentVariable("ZIG_TEST_POSIX_1EQ", "test=variable"); diff --git a/test/standalone/posix/cwd.zig b/test/standalone/posix/cwd.zig index 43dcc63bfeb2..7a9517b41281 100644 --- a/test/standalone/posix/cwd.zig +++ b/test/standalone/posix/cwd.zig @@ -1,21 +1,27 @@ -const std = @import("std"); const builtin = @import("builtin"); +const std = @import("std"); +const Io = std.Io; +const Allocator = std.mem.Allocator; +const assert = std.debug.assert; + const path_max = std.fs.max_path_bytes; -pub fn main() !void { - if (builtin.target.os.tag == .wasi) { - // WASI doesn't support changing the working directory at all. - return; +pub fn main(init: std.process.Init) !void { + switch (builtin.target.os.tag) { + .wasi => return, // WASI doesn't support changing the working directory at all. + .windows => return, // POSIX is not implemented by Windows + else => {}, } + const args = try init.minimal.args.toSlice(init.arena.allocator()); + const tmp_dir_path = args[1]; - var Allocator = std.heap.DebugAllocator(.{}){}; - const a = Allocator.allocator(); - defer std.debug.assert(Allocator.deinit() == .ok); + var tmp_dir = try Io.Dir.cwd().openDir(init.io, tmp_dir_path, .{}); + defer tmp_dir.close(init.io); try test_chdir_self(); try test_chdir_absolute(); - try test_chdir_relative(a); + try test_chdir_relative(init.gpa, init.io, tmp_dir); } // get current working directory and expect it to match given path @@ -30,7 +36,7 @@ fn test_chdir_self() !void { const old_cwd = try std.posix.getcwd(old_cwd_buf[0..]); // Try changing to the current directory - try std.posix.chdir(old_cwd); + try std.Io.Threaded.chdir(old_cwd); try expect_cwd(old_cwd); } @@ -41,35 +47,34 @@ fn test_chdir_absolute() !void { const parent = std.fs.path.dirname(old_cwd) orelse unreachable; // old_cwd should be absolute // Try changing to the parent via a full path - try std.posix.chdir(parent); + try std.Io.Threaded.chdir(parent); try expect_cwd(parent); } -fn test_chdir_relative(a: std.mem.Allocator) !void { - var tmp = std.testing.tmpDir(.{}); - defer tmp.cleanup(); +fn test_chdir_relative(gpa: Allocator, io: Io, tmp_dir: Io.Dir) !void { + const subdir_path = "subdir"; + try tmp_dir.createDir(io, "subdir", .default_dir); - // Use the tmpDir parent_dir as the "base" for the test. Then cd into the child - try tmp.parent_dir.setAsCwd(); + // Use the tmp dir as the "base" for the test. Then cd into the child + try std.process.setCurrentDir(io, tmp_dir); // Capture base working directory path, to build expected full path var base_cwd_buf: [path_max]u8 = undefined; const base_cwd = try std.posix.getcwd(base_cwd_buf[0..]); - const relative_dir_name = &tmp.sub_path; - const expected_path = try std.fs.path.resolve(a, &.{ base_cwd, relative_dir_name }); - defer a.free(expected_path); + const expected_path = try std.fs.path.resolve(gpa, &.{ base_cwd, subdir_path }); + defer gpa.free(expected_path); // change current working directory to new test directory - try std.posix.chdir(relative_dir_name); + try std.Io.Threaded.chdir(subdir_path); var new_cwd_buf: [path_max]u8 = undefined; const new_cwd = try std.posix.getcwd(new_cwd_buf[0..]); // On Windows, fs.path.resolve returns an uppercase drive letter, but the drive letter returned by getcwd may be lowercase - const resolved_cwd = try std.fs.path.resolve(a, &.{new_cwd}); - defer a.free(resolved_cwd); + const resolved_cwd = try std.fs.path.resolve(gpa, &.{new_cwd}); + defer gpa.free(resolved_cwd); try std.testing.expectEqualStrings(expected_path, resolved_cwd); } diff --git a/test/standalone/posix/getenv.zig b/test/standalone/posix/getenv.zig index 8b28d09ae76d..62c348e085b9 100644 --- a/test/standalone/posix/getenv.zig +++ b/test/standalone/posix/getenv.zig @@ -1,32 +1,28 @@ -// test getting environment variables +//! test getting environment variables const std = @import("std"); const builtin = @import("builtin"); -pub fn main() !void { - if (builtin.target.os.tag == .windows) { - return; // Windows env strings are WTF-16, so not supported by Zig's std.posix.getenv() - } +pub fn main(init: std.process.Init.Minimal) !void { + if (builtin.target.os.tag == .windows) return; + if (builtin.target.os.tag == .wasi and !builtin.link_libc) return; - if (builtin.target.os.tag == .wasi and !builtin.link_libc) { - return; // std.posix.getenv is not supported on WASI due to the need of allocation - } + const environ = init.environ; // Test some unset env vars: - - try std.testing.expectEqual(std.posix.getenv(""), null); - try std.testing.expectEqual(std.posix.getenv("BOGUSDOESNOTEXISTENVVAR"), null); - try std.testing.expectEqual(std.posix.getenvZ("BOGUSDOESNOTEXISTENVVAR"), null); + try std.testing.expectEqual(environ.getPosix(""), null); + try std.testing.expectEqual(environ.getPosix("BOGUSDOESNOTEXISTENVVAR"), null); + try std.testing.expectEqual(environ.getPosix("BOGUSDOESNOTEXISTENVVAR"), null); if (builtin.link_libc) { // Test if USER matches what C library sees const expected = std.mem.span(std.c.getenv("USER") orelse ""); - const actual = std.posix.getenv("USER") orelse ""; + const actual = environ.getPosix("USER") orelse ""; try std.testing.expectEqualStrings(expected, actual); } // env vars set by our build.zig run step: - try std.testing.expectEqualStrings("", std.posix.getenv("ZIG_TEST_POSIX_EMPTY") orelse "invalid"); - try std.testing.expectEqualStrings("test=variable", std.posix.getenv("ZIG_TEST_POSIX_1EQ") orelse "invalid"); - try std.testing.expectEqualStrings("=test=variable=", std.posix.getenv("ZIG_TEST_POSIX_3EQ") orelse "invalid"); + try std.testing.expectEqualStrings("", environ.getPosix("ZIG_TEST_POSIX_EMPTY") orelse "invalid"); + try std.testing.expectEqualStrings("test=variable", environ.getPosix("ZIG_TEST_POSIX_1EQ") orelse "invalid"); + try std.testing.expectEqualStrings("=test=variable=", environ.getPosix("ZIG_TEST_POSIX_3EQ") orelse "invalid"); } diff --git a/test/standalone/posix/relpaths.zig b/test/standalone/posix/relpaths.zig index f7ced28cdbf1..9fe92f3cef44 100644 --- a/test/standalone/posix/relpaths.zig +++ b/test/standalone/posix/relpaths.zig @@ -1,94 +1,60 @@ // Test relative paths through POSIX APIS. These tests have to change the cwd, so // they shouldn't be Zig unit tests. -const std = @import("std"); const builtin = @import("builtin"); -pub fn main() !void { +const std = @import("std"); +const Io = std.Io; + +pub fn main(init: std.process.Init) !void { if (builtin.target.os.tag == .wasi) return; // Can link, but can't change into tmpDir - var Allocator = std.heap.DebugAllocator(.{}){}; - const a = Allocator.allocator(); - defer std.debug.assert(Allocator.deinit() == .ok); + const io = init.io; - var tmp = std.testing.tmpDir(.{}); - defer tmp.cleanup(); + const args = try init.minimal.args.toSlice(init.arena.allocator()); + const tmp_dir_path = args[1]; - // Want to test relative paths, so cd into the tmpdir for these tests - try tmp.dir.setAsCwd(); + var tmp_dir = try Io.Dir.cwd().openDir(io, tmp_dir_path, .{}); + defer tmp_dir.close(io); - try test_symlink(a, tmp); - try test_link(tmp); -} - -fn test_symlink(a: std.mem.Allocator, tmp: std.testing.TmpDir) !void { - const target_name = "symlink-target"; - const symlink_name = "symlinker"; - - // Create the target file - try tmp.dir.writeFile(.{ .sub_path = target_name, .data = "nonsense" }); - - if (builtin.target.os.tag == .windows) { - const wtarget_name = try std.unicode.wtf8ToWtf16LeAllocZ(a, target_name); - const wsymlink_name = try std.unicode.wtf8ToWtf16LeAllocZ(a, symlink_name); - defer a.free(wtarget_name); - defer a.free(wsymlink_name); - - std.os.windows.CreateSymbolicLink(tmp.dir.fd, wsymlink_name, wtarget_name, false) catch |err| switch (err) { - // Symlink requires admin privileges on windows, so this test can legitimately fail. - error.AccessDenied => return, - else => return err, - }; - } else { - try std.posix.symlink(target_name, symlink_name); - } + // Want to test relative paths, so cd into the tmpdir for these tests + try std.process.setCurrentDir(io, tmp_dir); - var buffer: [std.fs.max_path_bytes]u8 = undefined; - const given = try std.posix.readlink(symlink_name, buffer[0..]); - try std.testing.expectEqualStrings(target_name, given); + try test_link(io, tmp_dir); } -fn test_link(tmp: std.testing.TmpDir) !void { +fn test_link(io: Io, tmp_dir: Io.Dir) !void { switch (builtin.target.os.tag) { .linux, .illumos => {}, else => return, } - if ((builtin.cpu.arch == .riscv32 or builtin.cpu.arch.isLoongArch()) and builtin.target.os.tag == .linux and !builtin.link_libc) { - return; // No `fstat()`. - } - - if (builtin.cpu.arch.isMIPS64()) { - return; // `nstat.nlink` assertion is failing with LLVM 20+ for unclear reasons. - } - const target_name = "link-target"; const link_name = "newlink"; - try tmp.dir.writeFile(.{ .sub_path = target_name, .data = "example" }); + try tmp_dir.writeFile(io, .{ .sub_path = target_name, .data = "example" }); - // Test 1: create the relative link from inside tmp - try std.posix.link(target_name, link_name); + // Test 1: create the relative link from inside tmp_dir + try Io.Dir.hardLink(.cwd(), target_name, .cwd(), link_name, io, .{}); // Verify - const efd = try tmp.dir.openFile(target_name, .{}); - defer efd.close(); + const efd = try tmp_dir.openFile(io, target_name, .{}); + defer efd.close(io); - const nfd = try tmp.dir.openFile(link_name, .{}); - defer nfd.close(); + const nfd = try tmp_dir.openFile(io, link_name, .{}); + defer nfd.close(io); { - const estat = try std.posix.fstat(efd.handle); - const nstat = try std.posix.fstat(nfd.handle); - try std.testing.expectEqual(estat.ino, nstat.ino); - try std.testing.expectEqual(@as(@TypeOf(nstat.nlink), 2), nstat.nlink); + const e_stat = try efd.stat(io); + const n_stat = try nfd.stat(io); + try std.testing.expectEqual(e_stat.inode, n_stat.inode); + try std.testing.expectEqual(2, n_stat.nlink); } // Test 2: Remove the link and see the stats update - try std.posix.unlink(link_name); - + try Io.Dir.cwd().deleteFile(io, link_name); { - const estat = try std.posix.fstat(efd.handle); - try std.testing.expectEqual(@as(@TypeOf(estat.nlink), 1), estat.nlink); + const e_stat = try efd.stat(io); + try std.testing.expectEqual(1, e_stat.nlink); } } diff --git a/test/standalone/run_cwd/check_file_exists.zig b/test/standalone/run_cwd/check_file_exists.zig index 640fc99a7a4a..bd4a26b6668c 100644 --- a/test/standalone/run_cwd/check_file_exists.zig +++ b/test/standalone/run_cwd/check_file_exists.zig @@ -1,14 +1,13 @@ -pub fn main() !void { - var arena_state: std.heap.ArenaAllocator = .init(std.heap.page_allocator); - defer arena_state.deinit(); - const arena = arena_state.allocator(); - - const args = try std.process.argsAlloc(arena); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const args = try init.minimal.args.toSlice(arena); if (args.len != 2) return error.BadUsage; const path = args[1]; - std.fs.cwd().access(path, .{}) catch return error.AccessFailed; + const io = std.Io.Threaded.global_single_threaded.ioBasic(); + + std.Io.Dir.cwd().access(io, path, .{}) catch return error.AccessFailed; } const std = @import("std"); diff --git a/test/standalone/run_output_caching/main.zig b/test/standalone/run_output_caching/main.zig index e4e6332f1128..8a9855f5ecef 100644 --- a/test/standalone/run_output_caching/main.zig +++ b/test/standalone/run_output_caching/main.zig @@ -1,10 +1,11 @@ const std = @import("std"); -pub fn main() !void { - var args = try std.process.argsWithAllocator(std.heap.page_allocator); +pub fn main(init: std.process.Init) !void { + const io = init.io; + var args = try init.minimal.args.iterateAllocator(init.arena.allocator()); _ = args.skip(); const filename = args.next().?; - const file = try std.fs.cwd().createFile(filename, .{}); - defer file.close(); - try file.writeAll(filename); + const file = try std.Io.Dir.cwd().createFile(io, filename, .{}); + defer file.close(io); + try file.writeStreamingAll(io, filename); } diff --git a/test/standalone/run_output_paths/create_file.zig b/test/standalone/run_output_paths/create_file.zig index 260c36f10cea..8490c1c5e9e9 100644 --- a/test/standalone/run_output_paths/create_file.zig +++ b/test/standalone/run_output_paths/create_file.zig @@ -1,16 +1,17 @@ const std = @import("std"); -pub fn main() !void { - var args = try std.process.argsWithAllocator(std.heap.page_allocator); +pub fn main(init: std.process.Init) !void { + const io = init.io; + var args = try init.minimal.args.iterateAllocator(init.arena.allocator()); _ = args.skip(); const dir_name = args.next().?; - const dir = try std.fs.cwd().openDir(if (std.mem.startsWith(u8, dir_name, "--dir=")) + const dir = try std.Io.Dir.cwd().openDir(io, if (std.mem.startsWith(u8, dir_name, "--dir=")) dir_name["--dir=".len..] else dir_name, .{}); const file_name = args.next().?; - const file = try dir.createFile(file_name, .{}); - var file_writer = file.writer(&.{}); + const file = try dir.createFile(io, file_name, .{}); + var file_writer = file.writer(io, &.{}); try file_writer.interface.print( \\{s} \\{s} diff --git a/test/standalone/self_exe_symlink/build.zig b/test/standalone/self_exe_symlink/build.zig index 651740c04be0..061dd69f3462 100644 --- a/test/standalone/self_exe_symlink/build.zig +++ b/test/standalone/self_exe_symlink/build.zig @@ -9,9 +9,7 @@ pub fn build(b: *std.Build) void { const optimize: std.builtin.OptimizeMode = .Debug; const target = b.graph.host; - // The test requires getFdPath in order to to get the path of the - // File returned by openSelfExe - if (!std.os.isGetFdPathSupportedOnTarget(target.result.os)) return; + if (target.result.os.tag == .openbsd) return; // realpath not supported const main = b.addExecutable(.{ .name = "main", diff --git a/test/standalone/self_exe_symlink/create-symlink.zig b/test/standalone/self_exe_symlink/create-symlink.zig index dac5891ba89f..32610ebcde6d 100644 --- a/test/standalone/self_exe_symlink/create-symlink.zig +++ b/test/standalone/self_exe_symlink/create-symlink.zig @@ -1,18 +1,19 @@ const std = @import("std"); -pub fn main() anyerror!void { - var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; - defer if (gpa.deinit() == .leak) @panic("found memory leaks"); - const allocator = gpa.allocator(); - - var it = try std.process.argsWithAllocator(allocator); +pub fn main(init: std.process.Init) !void { + const io = init.io; + const gpa = init.gpa; + var it = try init.minimal.args.iterateAllocator(gpa); defer it.deinit(); _ = it.next() orelse unreachable; // skip binary name const exe_path = it.next() orelse unreachable; const symlink_path = it.next() orelse unreachable; + const cwd = try std.process.getCwdAlloc(init.arena.allocator()); + // If `exe_path` is relative to our cwd, we need to convert it to be relative to the dirname of `symlink_path`. - const exe_rel_path = try std.fs.path.relative(allocator, std.fs.path.dirname(symlink_path) orelse ".", exe_path); - defer allocator.free(exe_rel_path); - try std.fs.cwd().symLink(exe_rel_path, symlink_path, .{}); + const exe_rel_path = try std.fs.path.relative(gpa, cwd, init.environ_map, std.fs.path.dirname(symlink_path) orelse ".", exe_path); + defer gpa.free(exe_rel_path); + + try std.Io.Dir.cwd().symLink(io, exe_rel_path, symlink_path, .{}); } diff --git a/test/standalone/self_exe_symlink/main.zig b/test/standalone/self_exe_symlink/main.zig index b74c4c7f95da..0b1704b18a04 100644 --- a/test/standalone/self_exe_symlink/main.zig +++ b/test/standalone/self_exe_symlink/main.zig @@ -1,17 +1,17 @@ const std = @import("std"); -pub fn main() !void { - var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; - defer std.debug.assert(gpa.deinit() == .ok); - const allocator = gpa.allocator(); +pub fn main(init: std.process.Init) !void { + const gpa = init.gpa; + const io = init.io; - const self_path = try std.fs.selfExePathAlloc(allocator); - defer allocator.free(self_path); + const self_path = try std.process.executablePathAlloc(io, gpa); + defer gpa.free(self_path); + + var self_exe = try std.process.openExecutable(io, .{}); + defer self_exe.close(io); - var self_exe = try std.fs.openSelfExe(.{}); - defer self_exe.close(); var buf: [std.fs.max_path_bytes]u8 = undefined; - const self_exe_path = try std.os.getFdPath(self_exe.handle, &buf); + const self_exe_path = buf[0..try self_exe.realPath(io, &buf)]; try std.testing.expectEqualStrings(self_exe_path, self_path); } diff --git a/test/standalone/simple/cat/main.zig b/test/standalone/simple/cat/main.zig index 9ea980aecca4..bc894d3881fd 100644 --- a/test/standalone/simple/cat/main.zig +++ b/test/standalone/simple/cat/main.zig @@ -1,28 +1,22 @@ const std = @import("std"); -const fs = std.fs; +const Io = std.Io; const mem = std.mem; const warn = std.log.warn; const fatal = std.process.fatal; -pub fn main() !void { - var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena_instance.deinit(); - const arena = arena_instance.allocator(); - - var threaded: std.Io.Threaded = .init(arena); - defer threaded.deinit(); - const io = threaded.io(); - - const args = try std.process.argsAlloc(arena); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const io = init.io; + const args = try init.minimal.args.toSlice(arena); const exe = args[0]; var catted_anything = false; var stdout_buffer: [4096]u8 = undefined; - var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer); + var stdout_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer); const stdout = &stdout_writer.interface; - var stdin_reader = fs.File.stdin().readerStreaming(io, &.{}); + var stdin_reader = Io.File.stdin().readerStreaming(io, &.{}); - const cwd = fs.cwd(); + const cwd = Io.Dir.cwd(); for (args[1..]) |arg| { if (mem.eql(u8, arg, "-")) { @@ -32,8 +26,8 @@ pub fn main() !void { } else if (mem.startsWith(u8, arg, "-")) { return usage(exe); } else { - const file = cwd.openFile(arg, .{}) catch |err| fatal("unable to open file: {t}\n", .{err}); - defer file.close(); + const file = cwd.openFile(io, arg, .{}) catch |err| fatal("unable to open file: {t}\n", .{err}); + defer file.close(io); catted_anything = true; var file_reader = file.reader(io, &.{}); diff --git a/test/standalone/simple/guess_number/main.zig b/test/standalone/simple/guess_number/main.zig index d477de2b7888..9af4787488f9 100644 --- a/test/standalone/simple/guess_number/main.zig +++ b/test/standalone/simple/guess_number/main.zig @@ -1,24 +1,29 @@ -const builtin = @import("builtin"); const std = @import("std"); -pub fn main() !void { - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); +pub fn main(init: std.process.Init) !void { + var stdout_writer = std.Io.File.stdout().writerStreaming(init.io, &.{}); const out = &stdout_writer.interface; - const stdin: std.fs.File = .stdin(); + + var line_buffer: [20]u8 = undefined; + var stdin_reader: std.Io.File.Reader = .init(.stdin(), init.io, &line_buffer); + const in = &stdin_reader.interface; try out.writeAll("Welcome to the Guess Number Game in Zig.\n"); - const answer = std.crypto.random.intRangeLessThan(u8, 0, 100) + 1; + var rng: std.Random.IoSource = .{ .io = init.io }; + const answer = rng.interface().intRangeLessThan(u8, 0, 100) + 1; while (true) { try out.writeAll("\nGuess a number between 1 and 100: "); - var line_buf: [20]u8 = undefined; - const amt = try stdin.read(&line_buf); - if (amt == line_buf.len) { - try out.writeAll("Input too long.\n"); - continue; - } - const line = std.mem.trimEnd(u8, line_buf[0..amt], "\r\n"); + const untrimmed_line = in.takeSentinel('\n') catch |err| switch (err) { + error.StreamTooLong => { + try out.writeAll("Line too long.\n"); + _ = try in.discardDelimiterInclusive('\n'); + continue; + }, + else => |e| return e, + }; + const line = std.mem.trimEnd(u8, untrimmed_line, "\r\n"); const guess = std.fmt.parseUnsigned(u8, line, 10) catch { try out.writeAll("Invalid number.\n"); diff --git a/test/standalone/simple/hello_world/hello.zig b/test/standalone/simple/hello_world/hello.zig index 3b2b91068775..27cedd428ee7 100644 --- a/test/standalone/simple/hello_world/hello.zig +++ b/test/standalone/simple/hello_world/hello.zig @@ -1,5 +1,5 @@ const std = @import("std"); -pub fn main() !void { - try std.fs.File.stdout().writeAll("Hello, World!\n"); +pub fn main(init: std.process.Init) !void { + try std.Io.File.stdout().writeStreamingAll(init.io, "Hello, World!\n"); } diff --git a/test/standalone/test_obj_link_run/build.zig b/test/standalone/test_obj_link_run/build.zig index 19d52ce68c3f..24e0e961e7e0 100644 --- a/test/standalone/test_obj_link_run/build.zig +++ b/test/standalone/test_obj_link_run/build.zig @@ -9,9 +9,9 @@ pub fn build(b: *std.Build) void { }), }); if (is_windows) { - test_obj.linkSystemLibrary("ntdll"); - test_obj.linkSystemLibrary("kernel32"); - test_obj.linkSystemLibrary("ws2_32"); + test_obj.root_module.linkSystemLibrary("ntdll", .{}); + test_obj.root_module.linkSystemLibrary("kernel32", .{}); + test_obj.root_module.linkSystemLibrary("ws2_32", .{}); } const test_exe_mod = b.createModule(.{ diff --git a/test/standalone/windows_argv/build.zig b/test/standalone/windows_argv/build.zig index df988d2371e0..019cd34fc84c 100644 --- a/test/standalone/windows_argv/build.zig +++ b/test/standalone/windows_argv/build.zig @@ -52,7 +52,7 @@ pub fn build(b: *std.Build) !void { const fuzz_seed = b.option(u64, "seed", "Seed to use for the PRNG (default: random)") orelse seed: { var buf: [8]u8 = undefined; - try std.posix.getrandom(&buf); + b.graph.io.random(&buf); break :seed std.mem.readInt(u64, &buf, builtin.cpu.arch.endian()); }; const fuzz_seed_arg = std.fmt.allocPrint(b.allocator, "{}", .{fuzz_seed}) catch @panic("oom"); @@ -67,7 +67,7 @@ pub fn build(b: *std.Build) !void { // Only target the MSVC ABI if MSVC/Windows SDK is available const has_msvc = has_msvc: { - const sdk = std.zig.WindowsSdk.find(b.allocator, builtin.cpu.arch) catch |err| switch (err) { + const sdk = std.zig.WindowsSdk.find(b.allocator, b.graph.io, builtin.cpu.arch, &b.graph.environ_map) catch |err| switch (err) { error.OutOfMemory => @panic("oom"), else => break :has_msvc false, }; diff --git a/test/standalone/windows_argv/fuzz.zig b/test/standalone/windows_argv/fuzz.zig index bdf40aa4b1d3..fde26ee5f481 100644 --- a/test/standalone/windows_argv/fuzz.zig +++ b/test/standalone/windows_argv/fuzz.zig @@ -3,19 +3,16 @@ const builtin = @import("builtin"); const windows = std.os.windows; const Allocator = std.mem.Allocator; -pub fn main() !void { - var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; - defer std.debug.assert(gpa.deinit() == .ok); - const allocator = gpa.allocator(); - - const args = try std.process.argsAlloc(allocator); - defer std.process.argsFree(allocator, args); +pub fn main(init: std.process.Init) !void { + const gpa = init.gpa; + const io = init.io; + const args = try init.minimal.args.toSlice(init.arena.allocator()); if (args.len < 2) return error.MissingArgs; const verify_path_wtf8 = args[1]; - const verify_path_w = try std.unicode.wtf8ToWtf16LeAllocZ(allocator, verify_path_wtf8); - defer allocator.free(verify_path_w); + const verify_path_w = try std.unicode.wtf8ToWtf16LeAllocZ(gpa, verify_path_wtf8); + defer gpa.free(verify_path_w); const iterations: u64 = iterations: { if (args.len < 3) break :iterations 0; @@ -27,7 +24,7 @@ pub fn main() !void { if (args.len < 4) { rand_seed = true; var buf: [8]u8 = undefined; - try std.posix.getrandom(&buf); + io.random(&buf); break :seed std.mem.readInt(u64, &buf, builtin.cpu.arch.endian()); } break :seed try std.fmt.parseUnsigned(u64, args[3], 10); @@ -41,14 +38,14 @@ pub fn main() !void { std.debug.print("rand seed: {}\n", .{seed}); } - var cmd_line_w_buf = std.array_list.Managed(u16).init(allocator); + var cmd_line_w_buf = std.array_list.Managed(u16).init(gpa); defer cmd_line_w_buf.deinit(); var i: u64 = 0; var errors: u64 = 0; while (iterations == 0 or i < iterations) { - const cmd_line_w = try randomCommandLineW(allocator, rand); - defer allocator.free(cmd_line_w); + const cmd_line_w = try randomCommandLineW(gpa, rand); + defer gpa.free(cmd_line_w); // avoid known difference for 0-length command lines if (cmd_line_w.len == 0 or cmd_line_w[0] == '\x00') continue; @@ -56,8 +53,8 @@ pub fn main() !void { const exit_code = try spawnVerify(verify_path_w, cmd_line_w); if (exit_code != 0) { std.debug.print(">>> found discrepancy <<<\n", .{}); - const cmd_line_wtf8 = try std.unicode.wtf16LeToWtf8Alloc(allocator, cmd_line_w); - defer allocator.free(cmd_line_wtf8); + const cmd_line_wtf8 = try std.unicode.wtf16LeToWtf8Alloc(gpa, cmd_line_w); + defer gpa.free(cmd_line_wtf8); std.debug.print("\"{f}\"\n\n", .{std.zig.fmtString(cmd_line_wtf8)}); errors += 1; diff --git a/test/standalone/windows_argv/lib.zig b/test/standalone/windows_argv/lib.zig index 4171d13dab40..750501edd215 100644 --- a/test/standalone/windows_argv/lib.zig +++ b/test/standalone/windows_argv/lib.zig @@ -5,7 +5,7 @@ export fn verify(argc: c_int, argv: [*]const [*:0]const u16) c_int { const argv_slice = argv[0..@intCast(argc)]; testArgv(argv_slice) catch |err| switch (err) { error.OutOfMemory => @panic("oom"), - error.Overflow => @panic("bytes needed to contain args would overflow usize"), + error.Unexpected => @panic("unexpected error"), error.ArgvMismatch => return 0, }; return 1; @@ -16,7 +16,10 @@ fn testArgv(expected_args: []const [*:0]const u16) !void { defer arena_state.deinit(); const allocator = arena_state.allocator(); - const args = try std.process.argsAlloc(allocator); + const cmd_line = std.os.windows.peb().ProcessParameters.CommandLine; + const cmd_line_w = cmd_line.Buffer.?[0..@divExact(cmd_line.Length, 2)]; + const raw_args: std.process.Args = .{ .vector = cmd_line_w }; + const args = try raw_args.toSlice(allocator); var wtf8_buf = std.array_list.Managed(u8).init(allocator); var eql = true; diff --git a/test/standalone/windows_bat_args/build.zig b/test/standalone/windows_bat_args/build.zig index b91b4fb3bbfd..d5053c5aad6d 100644 --- a/test/standalone/windows_bat_args/build.zig +++ b/test/standalone/windows_bat_args/build.zig @@ -19,6 +19,22 @@ pub fn build(b: *std.Build) !void { }), }); + const bat_files = b.addWriteFiles(); + { + const echo_args_basename = "echo-args.exe"; + const preamble = std.fmt.allocPrint(b.allocator, + \\@echo off + \\"{s}" + , .{echo_args_basename}) catch @panic("OOM"); + // Trailing newline intentionally omitted above so we can add args. + + _ = bat_files.add("args1.bat", std.mem.concat(b.allocator, u8, &.{ preamble, " %*" }) catch @panic("OOM")); + _ = bat_files.add("args2.bat", std.mem.concat(b.allocator, u8, &.{ preamble, " %1 %2 %3 %4 %5 %6 %7 %8 %9" }) catch @panic("OOM")); + _ = bat_files.add("args3.bat", std.mem.concat(b.allocator, u8, &.{ preamble, " \"%~1\" \"%~2\" \"%~3\" \"%~4\" \"%~5\" \"%~6\" \"%~7\" \"%~8\" \"%~9\"" }) catch @panic("OOM")); + + _ = bat_files.addCopyFile(echo_args.getEmittedBin(), echo_args_basename); + } + const test_exe = b.addExecutable(.{ .name = "test", .root_module = b.createModule(.{ @@ -29,7 +45,7 @@ pub fn build(b: *std.Build) !void { }); const run = b.addRunArtifact(test_exe); - run.addArtifactArg(echo_args); + run.setCwd(bat_files.getDirectory()); run.expectExitCode(0); run.skip_foreign_checks = true; @@ -49,13 +65,13 @@ pub fn build(b: *std.Build) !void { const fuzz_seed = b.option(u64, "seed", "Seed to use for the PRNG (default: random)") orelse seed: { var buf: [8]u8 = undefined; - try std.posix.getrandom(&buf); + b.graph.io.random(&buf); break :seed std.mem.readInt(u64, &buf, builtin.cpu.arch.endian()); }; const fuzz_seed_arg = std.fmt.allocPrint(b.allocator, "{}", .{fuzz_seed}) catch @panic("oom"); const fuzz_run = b.addRunArtifact(fuzz); - fuzz_run.addArtifactArg(echo_args); + fuzz_run.setCwd(bat_files.getDirectory()); fuzz_run.addArgs(&.{ fuzz_iterations_arg, fuzz_seed_arg }); fuzz_run.expectExitCode(0); fuzz_run.skip_foreign_checks = true; diff --git a/test/standalone/windows_bat_args/echo-args.zig b/test/standalone/windows_bat_args/echo-args.zig index 054c4a697544..a867a1bb2482 100644 --- a/test/standalone/windows_bat_args/echo-args.zig +++ b/test/standalone/windows_bat_args/echo-args.zig @@ -1,13 +1,12 @@ const std = @import("std"); -pub fn main() !void { - var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena_state.deinit(); - const arena = arena_state.allocator(); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const io = init.io; + const args = try init.minimal.args.toSlice(arena); - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); const stdout = &stdout_writer.interface; - var args = try std.process.argsAlloc(arena); for (args[1..], 1..) |arg, i| { try stdout.writeAll(arg); if (i != args.len - 1) try stdout.writeByte('\x00'); diff --git a/test/standalone/windows_bat_args/fuzz.zig b/test/standalone/windows_bat_args/fuzz.zig index 8b9895b52dd6..b9f0cc930d7b 100644 --- a/test/standalone/windows_bat_args/fuzz.zig +++ b/test/standalone/windows_bat_args/fuzz.zig @@ -1,16 +1,16 @@ -const std = @import("std"); const builtin = @import("builtin"); + +const std = @import("std"); +const Io = std.Io; const Allocator = std.mem.Allocator; -pub fn main() anyerror!void { - var debug_alloc_inst: std.heap.DebugAllocator(.{}) = .init; - defer std.debug.assert(debug_alloc_inst.deinit() == .ok); - const gpa = debug_alloc_inst.allocator(); +pub fn main(init: std.process.Init) !void { + const gpa = init.gpa; + const io = init.io; - var it = try std.process.argsWithAllocator(gpa); + var it = try init.minimal.args.iterateAllocator(gpa); defer it.deinit(); _ = it.next() orelse unreachable; // skip binary name - const child_exe_path_orig = it.next() orelse unreachable; const iterations: u64 = iterations: { const arg = it.next() orelse "0"; @@ -22,7 +22,7 @@ pub fn main() anyerror!void { const seed_arg = it.next() orelse { rand_seed = true; var buf: [8]u8 = undefined; - try std.posix.getrandom(&buf); + io.random(&buf); break :seed std.mem.readInt(u64, &buf, builtin.cpu.arch.endian()); }; break :seed try std.fmt.parseUnsigned(u64, seed_arg, 10); @@ -36,55 +36,24 @@ pub fn main() anyerror!void { std.debug.print("rand seed: {}\n", .{seed}); } - var tmp = std.testing.tmpDir(.{}); - defer tmp.cleanup(); - - try tmp.dir.setAsCwd(); - defer tmp.parent_dir.setAsCwd() catch {}; - - // `child_exe_path_orig` might be relative; make it relative to our new cwd. - const child_exe_path = try std.fs.path.resolve(gpa, &.{ "..\\..\\..", child_exe_path_orig }); - defer gpa.free(child_exe_path); - - var buf: std.ArrayList(u8) = .empty; - defer buf.deinit(gpa); - try buf.print(gpa, - \\@echo off - \\"{s}" - , .{child_exe_path}); - // Trailing newline intentionally omitted above so we can add args. - const preamble_len = buf.items.len; - - try buf.appendSlice(gpa, " %*"); - try tmp.dir.writeFile(.{ .sub_path = "args1.bat", .data = buf.items }); - buf.shrinkRetainingCapacity(preamble_len); - - try buf.appendSlice(gpa, " %1 %2 %3 %4 %5 %6 %7 %8 %9"); - try tmp.dir.writeFile(.{ .sub_path = "args2.bat", .data = buf.items }); - buf.shrinkRetainingCapacity(preamble_len); - - try buf.appendSlice(gpa, " \"%~1\" \"%~2\" \"%~3\" \"%~4\" \"%~5\" \"%~6\" \"%~7\" \"%~8\" \"%~9\""); - try tmp.dir.writeFile(.{ .sub_path = "args3.bat", .data = buf.items }); - buf.shrinkRetainingCapacity(preamble_len); - var i: u64 = 0; while (iterations == 0 or i < iterations) { const rand_arg = try randomArg(gpa, rand); defer gpa.free(rand_arg); - try testExec(gpa, &.{rand_arg}, null); + try testExec(gpa, io, &.{rand_arg}, null); i += 1; } } -fn testExec(gpa: std.mem.Allocator, args: []const []const u8, env: ?*std.process.EnvMap) !void { - try testExecBat(gpa, "args1.bat", args, env); - try testExecBat(gpa, "args2.bat", args, env); - try testExecBat(gpa, "args3.bat", args, env); +fn testExec(gpa: Allocator, io: Io, args: []const []const u8, env: ?*std.process.Environ.Map) !void { + try testExecBat(gpa, io, "args1.bat", args, env); + try testExecBat(gpa, io, "args2.bat", args, env); + try testExecBat(gpa, io, "args3.bat", args, env); } -fn testExecBat(gpa: std.mem.Allocator, bat: []const u8, args: []const []const u8, env: ?*std.process.EnvMap) !void { +fn testExecBat(gpa: Allocator, io: Io, bat: []const u8, args: []const []const u8, env: ?*std.process.Environ.Map) !void { const argv = try gpa.alloc([]const u8, 1 + args.len); defer gpa.free(argv); argv[0] = bat; @@ -92,9 +61,8 @@ fn testExecBat(gpa: std.mem.Allocator, bat: []const u8, args: []const []const u8 const can_have_trailing_empty_args = std.mem.eql(u8, bat, "args3.bat"); - const result = try std.process.Child.run(.{ - .allocator = gpa, - .env_map = env, + const result = try std.process.run(gpa, io, .{ + .environ_map = env, .argv = argv, }); defer gpa.free(result.stdout); diff --git a/test/standalone/windows_bat_args/test.zig b/test/standalone/windows_bat_args/test.zig index 4690d983f3a1..a923326aa140 100644 --- a/test/standalone/windows_bat_args/test.zig +++ b/test/standalone/windows_bat_args/test.zig @@ -1,82 +1,47 @@ const std = @import("std"); +const Io = std.Io; +const Allocator = std.mem.Allocator; -pub fn main() anyerror!void { - var debug_alloc_inst: std.heap.DebugAllocator(.{}) = .init; - defer std.debug.assert(debug_alloc_inst.deinit() == .ok); - const gpa = debug_alloc_inst.allocator(); - - var it = try std.process.argsWithAllocator(gpa); - defer it.deinit(); - _ = it.next() orelse unreachable; // skip binary name - const child_exe_path_orig = it.next() orelse unreachable; - - var tmp = std.testing.tmpDir(.{}); - defer tmp.cleanup(); - - try tmp.dir.setAsCwd(); - defer tmp.parent_dir.setAsCwd() catch {}; - - // `child_exe_path_orig` might be relative; make it relative to our new cwd. - const child_exe_path = try std.fs.path.resolve(gpa, &.{ "..\\..\\..", child_exe_path_orig }); - defer gpa.free(child_exe_path); - - var buf: std.ArrayList(u8) = .empty; - defer buf.deinit(gpa); - try buf.print(gpa, - \\@echo off - \\"{s}" - , .{child_exe_path}); - // Trailing newline intentionally omitted above so we can add args. - const preamble_len = buf.items.len; - - try buf.appendSlice(gpa, " %*"); - try tmp.dir.writeFile(.{ .sub_path = "args1.bat", .data = buf.items }); - buf.shrinkRetainingCapacity(preamble_len); - - try buf.appendSlice(gpa, " %1 %2 %3 %4 %5 %6 %7 %8 %9"); - try tmp.dir.writeFile(.{ .sub_path = "args2.bat", .data = buf.items }); - buf.shrinkRetainingCapacity(preamble_len); - - try buf.appendSlice(gpa, " \"%~1\" \"%~2\" \"%~3\" \"%~4\" \"%~5\" \"%~6\" \"%~7\" \"%~8\" \"%~9\""); - try tmp.dir.writeFile(.{ .sub_path = "args3.bat", .data = buf.items }); - buf.shrinkRetainingCapacity(preamble_len); +pub fn main(init: std.process.Init) !void { + const gpa = init.gpa; + const io = init.io; // Test cases are from https://github.com/rust-lang/rust/blob/master/tests/ui/std/windows-bat-args.rs - try testExecError(error.InvalidBatchScriptArg, gpa, &.{"\x00"}); - try testExecError(error.InvalidBatchScriptArg, gpa, &.{"\n"}); - try testExecError(error.InvalidBatchScriptArg, gpa, &.{"\r"}); - try testExec(gpa, &.{ "a", "b" }, null); - try testExec(gpa, &.{ "c is for cat", "d is for dog" }, null); - try testExec(gpa, &.{ "\"", " \"" }, null); - try testExec(gpa, &.{ "\\", "\\" }, null); - try testExec(gpa, &.{">file.txt"}, null); - try testExec(gpa, &.{"whoami.exe"}, null); - try testExec(gpa, &.{"&a.exe"}, null); - try testExec(gpa, &.{"&echo hello "}, null); - try testExec(gpa, &.{ "&echo hello", "&whoami", ">file.txt" }, null); - try testExec(gpa, &.{"!TMP!"}, null); - try testExec(gpa, &.{"key=value"}, null); - try testExec(gpa, &.{"\"key=value\""}, null); - try testExec(gpa, &.{"key = value"}, null); - try testExec(gpa, &.{"key=[\"value\"]"}, null); - try testExec(gpa, &.{ "", "a=b" }, null); - try testExec(gpa, &.{"key=\"foo bar\""}, null); - try testExec(gpa, &.{"key=[\"my_value]"}, null); - try testExec(gpa, &.{"key=[\"my_value\",\"other-value\"]"}, null); - try testExec(gpa, &.{"key\\=value"}, null); - try testExec(gpa, &.{"key=\"&whoami\""}, null); - try testExec(gpa, &.{"key=\"value\"=5"}, null); - try testExec(gpa, &.{"key=[\">file.txt\"]"}, null); - try testExec(gpa, &.{"%hello"}, null); - try testExec(gpa, &.{"%PATH%"}, null); - try testExec(gpa, &.{"%%cd:~,%"}, null); - try testExec(gpa, &.{"%PATH%PATH%"}, null); - try testExec(gpa, &.{"\">file.txt"}, null); - try testExec(gpa, &.{"abc\"&echo hello"}, null); - try testExec(gpa, &.{"123\">file.txt"}, null); - try testExec(gpa, &.{"\"&echo hello&whoami.exe"}, null); - try testExec(gpa, &.{ "\"hello^\"world\"", "hello &echo oh no >file.txt" }, null); - try testExec(gpa, &.{"&whoami.exe"}, null); + try testExecError(error.InvalidBatchScriptArg, gpa, io, &.{"\x00"}); + try testExecError(error.InvalidBatchScriptArg, gpa, io, &.{"\n"}); + try testExecError(error.InvalidBatchScriptArg, gpa, io, &.{"\r"}); + try testExec(gpa, io, &.{ "a", "b" }, null); + try testExec(gpa, io, &.{ "c is for cat", "d is for dog" }, null); + try testExec(gpa, io, &.{ "\"", " \"" }, null); + try testExec(gpa, io, &.{ "\\", "\\" }, null); + try testExec(gpa, io, &.{">file.txt"}, null); + try testExec(gpa, io, &.{"whoami.exe"}, null); + try testExec(gpa, io, &.{"&a.exe"}, null); + try testExec(gpa, io, &.{"&echo hello "}, null); + try testExec(gpa, io, &.{ "&echo hello", "&whoami", ">file.txt" }, null); + try testExec(gpa, io, &.{"!TMP!"}, null); + try testExec(gpa, io, &.{"key=value"}, null); + try testExec(gpa, io, &.{"\"key=value\""}, null); + try testExec(gpa, io, &.{"key = value"}, null); + try testExec(gpa, io, &.{"key=[\"value\"]"}, null); + try testExec(gpa, io, &.{ "", "a=b" }, null); + try testExec(gpa, io, &.{"key=\"foo bar\""}, null); + try testExec(gpa, io, &.{"key=[\"my_value]"}, null); + try testExec(gpa, io, &.{"key=[\"my_value\",\"other-value\"]"}, null); + try testExec(gpa, io, &.{"key\\=value"}, null); + try testExec(gpa, io, &.{"key=\"&whoami\""}, null); + try testExec(gpa, io, &.{"key=\"value\"=5"}, null); + try testExec(gpa, io, &.{"key=[\">file.txt\"]"}, null); + try testExec(gpa, io, &.{"%hello"}, null); + try testExec(gpa, io, &.{"%PATH%"}, null); + try testExec(gpa, io, &.{"%%cd:~,%"}, null); + try testExec(gpa, io, &.{"%PATH%PATH%"}, null); + try testExec(gpa, io, &.{"\">file.txt"}, null); + try testExec(gpa, io, &.{"abc\"&echo hello"}, null); + try testExec(gpa, io, &.{"123\">file.txt"}, null); + try testExec(gpa, io, &.{"\"&echo hello&whoami.exe"}, null); + try testExec(gpa, io, &.{ "\"hello^\"world\"", "hello &echo oh no >file.txt" }, null); + try testExec(gpa, io, &.{"&whoami.exe"}, null); // Ensure that trailing space and . characters can't lead to unexpected bat/cmd script execution. // In many Windows APIs (including CreateProcess), trailing space and . characters are stripped @@ -94,17 +59,17 @@ pub fn main() anyerror!void { // > "args1.bat .. " // '"args1.bat .. "' is not recognized as an internal or external command, // operable program or batch file. - try std.testing.expectError(error.FileNotFound, testExecBat(gpa, "args1.bat .. ", &.{"abc"}, null)); + try std.testing.expectError(error.FileNotFound, testExecBat(gpa, io, "args1.bat .. ", &.{"abc"}, null)); const absolute_with_trailing = blk: { - const absolute_path = try std.fs.realpathAlloc(gpa, "args1.bat"); + const absolute_path = try Io.Dir.cwd().realPathFileAlloc(io, "args1.bat", gpa); defer gpa.free(absolute_path); break :blk try std.mem.concat(gpa, u8, &.{ absolute_path, " .. " }); }; defer gpa.free(absolute_with_trailing); - try std.testing.expectError(error.FileNotFound, testExecBat(gpa, absolute_with_trailing, &.{"abc"}, null)); + try std.testing.expectError(error.FileNotFound, testExecBat(gpa, io, absolute_with_trailing, &.{"abc"}, null)); var env = env: { - var env = try std.process.getEnvMap(gpa); + var env = try init.environ_map.clone(gpa); errdefer env.deinit(); // No escaping try env.put("FOO", "123"); @@ -115,23 +80,23 @@ pub fn main() anyerror!void { break :env env; }; defer env.deinit(); - try testExec(gpa, &.{"%FOO%"}, &env); + try testExec(gpa, io, &.{"%FOO%"}, &env); // Ensure that none of the `>file.txt`s have caused file.txt to be created - try std.testing.expectError(error.FileNotFound, tmp.dir.access("file.txt", .{})); + try std.testing.expectError(error.FileNotFound, Io.Dir.cwd().access(io, "file.txt", .{})); } -fn testExecError(err: anyerror, gpa: std.mem.Allocator, args: []const []const u8) !void { - return std.testing.expectError(err, testExec(gpa, args, null)); +fn testExecError(err: anyerror, gpa: Allocator, io: Io, args: []const []const u8) !void { + return std.testing.expectError(err, testExec(gpa, io, args, null)); } -fn testExec(gpa: std.mem.Allocator, args: []const []const u8, env: ?*std.process.EnvMap) !void { - try testExecBat(gpa, "args1.bat", args, env); - try testExecBat(gpa, "args2.bat", args, env); - try testExecBat(gpa, "args3.bat", args, env); +fn testExec(gpa: Allocator, io: Io, args: []const []const u8, env: ?*std.process.Environ.Map) !void { + try testExecBat(gpa, io, "args1.bat", args, env); + try testExecBat(gpa, io, "args2.bat", args, env); + try testExecBat(gpa, io, "args3.bat", args, env); } -fn testExecBat(gpa: std.mem.Allocator, bat: []const u8, args: []const []const u8, env: ?*std.process.EnvMap) !void { +fn testExecBat(gpa: Allocator, io: Io, bat: []const u8, args: []const []const u8, env: ?*std.process.Environ.Map) !void { const argv = try gpa.alloc([]const u8, 1 + args.len); defer gpa.free(argv); argv[0] = bat; @@ -139,9 +104,8 @@ fn testExecBat(gpa: std.mem.Allocator, bat: []const u8, args: []const []const u8 const can_have_trailing_empty_args = std.mem.eql(u8, bat, "args3.bat"); - const result = try std.process.Child.run(.{ - .allocator = gpa, - .env_map = env, + const result = try std.process.run(gpa, io, .{ + .environ_map = env, .argv = argv, }); defer gpa.free(result.stdout); diff --git a/test/standalone/windows_paths/relative.zig b/test/standalone/windows_paths/relative.zig index 830154966745..7b3725e4eec0 100644 --- a/test/standalone/windows_paths/relative.zig +++ b/test/standalone/windows_paths/relative.zig @@ -1,19 +1,16 @@ const std = @import("std"); -pub fn main() !void { - var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; - defer std.debug.assert(gpa.deinit() == .ok); - const allocator = gpa.allocator(); - - const args = try std.process.argsAlloc(allocator); - defer std.process.argsFree(allocator, args); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const args = try init.minimal.args.toSlice(arena); + const io = init.io; + const cwd_path = try std.process.getCwdAlloc(arena); if (args.len < 3) return error.MissingArgs; - const relative = try std.fs.path.relative(allocator, args[1], args[2]); - defer allocator.free(relative); + const relative = try std.fs.path.relative(arena, cwd_path, init.environ_map, args[1], args[2]); - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); const stdout = &stdout_writer.interface; try stdout.writeAll(relative); } diff --git a/test/standalone/windows_paths/test.zig b/test/standalone/windows_paths/test.zig index 2ec23417e697..94afe163372b 100644 --- a/test/standalone/windows_paths/test.zig +++ b/test/standalone/windows_paths/test.zig @@ -1,11 +1,10 @@ const std = @import("std"); +const Io = std.Io; -pub fn main() anyerror!void { - var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena_state.deinit(); - const arena = arena_state.allocator(); - - const args = try std.process.argsAlloc(arena); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const args = try init.minimal.args.toSlice(arena); + const io = init.io; if (args.len < 2) return error.MissingArgs; @@ -22,10 +21,10 @@ pub fn main() anyerror!void { const alt_drive_letter = try getAltDriveLetter(cwd_path); const alt_drive_cwd_key = try std.fmt.allocPrint(arena, "={c}:", .{alt_drive_letter}); const alt_drive_cwd = try std.fmt.allocPrint(arena, "{c}:\\baz", .{alt_drive_letter}); - var alt_drive_env_map = std.process.EnvMap.init(arena); + var alt_drive_env_map = std.process.Environ.Map.init(arena); try alt_drive_env_map.put(alt_drive_cwd_key, alt_drive_cwd); - const empty_env = std.process.EnvMap.init(arena); + const empty_env = std.process.Environ.Map.init(arena); { const drive_rel = try std.fmt.allocPrint(arena, "{c}:foo", .{alt_drive_letter}); @@ -33,39 +32,39 @@ pub fn main() anyerror!void { // With the special =X: environment variable set, drive-relative paths that // don't match the CWD's drive letter are resolved against that env var. - try checkRelative(arena, "..\\..\\bar", &.{ exe_path, drive_rel, drive_abs }, null, &alt_drive_env_map); - try checkRelative(arena, "..\\baz\\foo", &.{ exe_path, drive_abs, drive_rel }, null, &alt_drive_env_map); + try checkRelative(arena, io, "..\\..\\bar", &.{ exe_path, drive_rel, drive_abs }, null, &alt_drive_env_map); + try checkRelative(arena, io, "..\\baz\\foo", &.{ exe_path, drive_abs, drive_rel }, null, &alt_drive_env_map); // Without that environment variable set, drive-relative paths that don't match the // CWD's drive letter are resolved against the root of the drive. - try checkRelative(arena, "..\\bar", &.{ exe_path, drive_rel, drive_abs }, null, &empty_env); - try checkRelative(arena, "..\\foo", &.{ exe_path, drive_abs, drive_rel }, null, &empty_env); + try checkRelative(arena, io, "..\\bar", &.{ exe_path, drive_rel, drive_abs }, null, &empty_env); + try checkRelative(arena, io, "..\\foo", &.{ exe_path, drive_abs, drive_rel }, null, &empty_env); // Bare drive-relative path with no components - try checkRelative(arena, "bar", &.{ exe_path, drive_rel[0..2], drive_abs }, null, &empty_env); - try checkRelative(arena, "..", &.{ exe_path, drive_abs, drive_rel[0..2] }, null, &empty_env); + try checkRelative(arena, io, "bar", &.{ exe_path, drive_rel[0..2], drive_abs }, null, &empty_env); + try checkRelative(arena, io, "..", &.{ exe_path, drive_abs, drive_rel[0..2] }, null, &empty_env); // Bare drive-relative path with no components, drive-CWD set - try checkRelative(arena, "..\\bar", &.{ exe_path, drive_rel[0..2], drive_abs }, null, &alt_drive_env_map); - try checkRelative(arena, "..\\baz", &.{ exe_path, drive_abs, drive_rel[0..2] }, null, &alt_drive_env_map); + try checkRelative(arena, io, "..\\bar", &.{ exe_path, drive_rel[0..2], drive_abs }, null, &alt_drive_env_map); + try checkRelative(arena, io, "..\\baz", &.{ exe_path, drive_abs, drive_rel[0..2] }, null, &alt_drive_env_map); // Bare drive-relative path relative to the CWD should be equivalent if drive-CWD is set - try checkRelative(arena, "", &.{ exe_path, alt_drive_cwd, drive_rel[0..2] }, null, &alt_drive_env_map); - try checkRelative(arena, "", &.{ exe_path, drive_rel[0..2], alt_drive_cwd }, null, &alt_drive_env_map); + try checkRelative(arena, io, "", &.{ exe_path, alt_drive_cwd, drive_rel[0..2] }, null, &alt_drive_env_map); + try checkRelative(arena, io, "", &.{ exe_path, drive_rel[0..2], alt_drive_cwd }, null, &alt_drive_env_map); // Bare drive-relative should always be equivalent to itself - try checkRelative(arena, "", &.{ exe_path, drive_rel[0..2], drive_rel[0..2] }, null, &alt_drive_env_map); - try checkRelative(arena, "", &.{ exe_path, drive_rel[0..2], drive_rel[0..2] }, null, &alt_drive_env_map); - try checkRelative(arena, "", &.{ exe_path, drive_rel[0..2], drive_rel[0..2] }, null, &empty_env); - try checkRelative(arena, "", &.{ exe_path, drive_rel[0..2], drive_rel[0..2] }, null, &empty_env); + try checkRelative(arena, io, "", &.{ exe_path, drive_rel[0..2], drive_rel[0..2] }, null, &alt_drive_env_map); + try checkRelative(arena, io, "", &.{ exe_path, drive_rel[0..2], drive_rel[0..2] }, null, &alt_drive_env_map); + try checkRelative(arena, io, "", &.{ exe_path, drive_rel[0..2], drive_rel[0..2] }, null, &empty_env); + try checkRelative(arena, io, "", &.{ exe_path, drive_rel[0..2], drive_rel[0..2] }, null, &empty_env); } if (parsed_cwd_path.kind == .unc_absolute) { const drive_abs_path = try std.fmt.allocPrint(arena, "{c}:\\foo\\bar", .{alt_drive_letter}); { - try checkRelative(arena, drive_abs_path, &.{ exe_path, cwd_path, drive_abs_path }, null, &empty_env); - try checkRelative(arena, cwd_path, &.{ exe_path, drive_abs_path, cwd_path }, null, &empty_env); + try checkRelative(arena, io, drive_abs_path, &.{ exe_path, cwd_path, drive_abs_path }, null, &empty_env); + try checkRelative(arena, io, cwd_path, &.{ exe_path, drive_abs_path, cwd_path }, null, &empty_env); } } else if (parsed_cwd_path.kind == .drive_absolute) { const cur_drive_letter = parsed_cwd_path.root[0]; @@ -73,14 +72,14 @@ pub fn main() anyerror!void { const unc_cwd = try std.fmt.allocPrint(arena, "\\\\127.0.0.1\\{c}$\\{s}", .{ cur_drive_letter, path_beyond_root }); { - try checkRelative(arena, cwd_path, &.{ exe_path, unc_cwd, cwd_path }, null, &empty_env); - try checkRelative(arena, unc_cwd, &.{ exe_path, cwd_path, unc_cwd }, null, &empty_env); + try checkRelative(arena, io, cwd_path, &.{ exe_path, unc_cwd, cwd_path }, null, &empty_env); + try checkRelative(arena, io, unc_cwd, &.{ exe_path, cwd_path, unc_cwd }, null, &empty_env); } { const drive_abs = cwd_path; const drive_rel = parsed_cwd_path.root[0..2]; - try checkRelative(arena, "", &.{ exe_path, drive_abs, drive_rel }, null, &empty_env); - try checkRelative(arena, "", &.{ exe_path, drive_rel, drive_abs }, null, &empty_env); + try checkRelative(arena, io, "", &.{ exe_path, drive_abs, drive_rel }, null, &empty_env); + try checkRelative(arena, io, "", &.{ exe_path, drive_rel, drive_abs }, null, &empty_env); } } else { return error.UnexpectedPathType; @@ -89,16 +88,16 @@ pub fn main() anyerror!void { fn checkRelative( allocator: std.mem.Allocator, + io: Io, expected_stdout: []const u8, argv: []const []const u8, cwd: ?[]const u8, - env_map: ?*const std.process.EnvMap, + environ_map: ?*const std.process.Environ.Map, ) !void { - const result = try std.process.Child.run(.{ - .allocator = allocator, + const result = try std.process.run(allocator, io, .{ .argv = argv, .cwd = cwd, - .env_map = env_map, + .environ_map = environ_map, }); defer allocator.free(result.stdout); defer allocator.free(result.stderr); diff --git a/test/standalone/windows_spawn/build.zig b/test/standalone/windows_spawn/build.zig index 2b967b16d5b3..43b0f162bf68 100644 --- a/test/standalone/windows_spawn/build.zig +++ b/test/standalone/windows_spawn/build.zig @@ -30,6 +30,7 @@ pub fn build(b: *std.Build) void { const run = b.addRunArtifact(main); run.addArtifactArg(hello); + run.addDirectoryArg(b.tmpPath()); run.expectExitCode(0); run.skip_foreign_checks = true; diff --git a/test/standalone/windows_spawn/hello.zig b/test/standalone/windows_spawn/hello.zig index fb4a827e2310..51e6aaf8bc60 100644 --- a/test/standalone/windows_spawn/hello.zig +++ b/test/standalone/windows_spawn/hello.zig @@ -1,7 +1,8 @@ const std = @import("std"); pub fn main() !void { - var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); + const io = std.Options.debug_io; + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); const stdout = &stdout_writer.interface; try stdout.writeAll("hello from exe\n"); } diff --git a/test/standalone/windows_spawn/main.zig b/test/standalone/windows_spawn/main.zig index 10ee35f4df7b..e26b581f59db 100644 --- a/test/standalone/windows_spawn/main.zig +++ b/test/standalone/windows_spawn/main.zig @@ -1,29 +1,34 @@ const std = @import("std"); +const Io = std.Io; +const Allocator = std.mem.Allocator; const windows = std.os.windows; const utf16Literal = std.unicode.utf8ToUtf16LeStringLiteral; -pub fn main() anyerror!void { - var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; - defer if (gpa.deinit() == .leak) @panic("found memory leaks"); - const allocator = gpa.allocator(); +pub fn main(init: std.process.Init) !void { + const gpa = init.gpa; + const io = init.io; + const process_cwd_path = try std.process.getCwdAlloc(init.arena.allocator()); + var initial_process_cwd = try Io.Dir.cwd().openDir(io, ".", .{}); + defer initial_process_cwd.close(io); - var it = try std.process.argsWithAllocator(allocator); + var it = try init.minimal.args.iterateAllocator(gpa); defer it.deinit(); _ = it.next() orelse unreachable; // skip binary name const hello_exe_cache_path = it.next() orelse unreachable; + const tmp_dir_path = it.next() orelse unreachable; - var tmp = std.testing.tmpDir(.{}); - defer tmp.cleanup(); + var tmp_dir = try Io.Dir.cwd().openDir(io, tmp_dir_path, .{}); + defer tmp_dir.close(io); - const tmp_absolute_path = try tmp.dir.realpathAlloc(allocator, "."); - defer allocator.free(tmp_absolute_path); - const tmp_absolute_path_w = try std.unicode.utf8ToUtf16LeAllocZ(allocator, tmp_absolute_path); - defer allocator.free(tmp_absolute_path_w); - const cwd_absolute_path = try std.fs.cwd().realpathAlloc(allocator, "."); - defer allocator.free(cwd_absolute_path); - const tmp_relative_path = try std.fs.path.relative(allocator, cwd_absolute_path, tmp_absolute_path); - defer allocator.free(tmp_relative_path); + const tmp_absolute_path = try tmp_dir.realPathFileAlloc(io, ".", gpa); + defer gpa.free(tmp_absolute_path); + const tmp_absolute_path_w = try std.unicode.utf8ToUtf16LeAllocZ(gpa, tmp_absolute_path); + defer gpa.free(tmp_absolute_path_w); + const cwd_absolute_path = try Io.Dir.cwd().realPathFileAlloc(io, ".", gpa); + defer gpa.free(cwd_absolute_path); + const tmp_relative_path = try std.fs.path.relative(gpa, process_cwd_path, init.environ_map, cwd_absolute_path, tmp_absolute_path); + defer gpa.free(tmp_relative_path); // Clear PATH std.debug.assert(windows.kernel32.SetEnvironmentVariableW( @@ -38,10 +43,10 @@ pub fn main() anyerror!void { ) == windows.TRUE); // No PATH, so it should fail to find anything not in the cwd - try testExecError(error.FileNotFound, allocator, "something_missing"); + try testExecError(error.FileNotFound, gpa, io, "something_missing"); // make sure we don't get error.BadPath traversing out of cwd with a relative path - try testExecError(error.FileNotFound, allocator, "..\\.\\.\\.\\\\..\\more_missing"); + try testExecError(error.FileNotFound, gpa, io, "..\\.\\.\\.\\\\..\\more_missing"); std.debug.assert(windows.kernel32.SetEnvironmentVariableW( utf16Literal("PATH"), @@ -49,82 +54,82 @@ pub fn main() anyerror!void { ) == windows.TRUE); // Move hello.exe into the tmp dir which is now added to the path - try std.fs.cwd().copyFile(hello_exe_cache_path, tmp.dir, "hello.exe", .{}); + try Io.Dir.cwd().copyFile(hello_exe_cache_path, tmp_dir, "hello.exe", io, .{}); // with extension should find the .exe (case insensitive) - try testExec(allocator, "HeLLo.exe", "hello from exe\n"); + try testExec(gpa, io, "HeLLo.exe", "hello from exe\n"); // without extension should find the .exe (case insensitive) - try testExec(allocator, "heLLo", "hello from exe\n"); + try testExec(gpa, io, "heLLo", "hello from exe\n"); // with invalid cwd - try std.testing.expectError(error.FileNotFound, testExecWithCwd(allocator, "hello.exe", "missing_dir", "")); + try std.testing.expectError(error.FileNotFound, testExecWithCwd(gpa, io, "hello.exe", "missing_dir", "")); // now add a .bat - try tmp.dir.writeFile(.{ .sub_path = "hello.bat", .data = "@echo hello from bat" }); + try tmp_dir.writeFile(io, .{ .sub_path = "hello.bat", .data = "@echo hello from bat" }); // and a .cmd - try tmp.dir.writeFile(.{ .sub_path = "hello.cmd", .data = "@echo hello from cmd" }); + try tmp_dir.writeFile(io, .{ .sub_path = "hello.cmd", .data = "@echo hello from cmd" }); // with extension should find the .bat (case insensitive) - try testExec(allocator, "heLLo.bat", "hello from bat\r\n"); + try testExec(gpa, io, "heLLo.bat", "hello from bat\r\n"); // with extension should find the .cmd (case insensitive) - try testExec(allocator, "heLLo.cmd", "hello from cmd\r\n"); + try testExec(gpa, io, "heLLo.cmd", "hello from cmd\r\n"); // without extension should find the .exe (since its first in PATHEXT) - try testExec(allocator, "heLLo", "hello from exe\n"); + try testExec(gpa, io, "heLLo", "hello from exe\n"); // now rename the exe to not have an extension - try renameExe(tmp.dir, "hello.exe", "hello"); + try renameExe(tmp_dir, io, "hello.exe", "hello"); // with extension should now fail - try testExecError(error.FileNotFound, allocator, "hello.exe"); + try testExecError(error.FileNotFound, gpa, io, "hello.exe"); // without extension should succeed (case insensitive) - try testExec(allocator, "heLLo", "hello from exe\n"); + try testExec(gpa, io, "heLLo", "hello from exe\n"); - try tmp.dir.makeDir("something"); - try renameExe(tmp.dir, "hello", "something/hello.exe"); + try tmp_dir.createDir(io, "something", .default_dir); + try renameExe(tmp_dir, io, "hello", "something/hello.exe"); - const relative_path_no_ext = try std.fs.path.join(allocator, &.{ tmp_relative_path, "something/hello" }); - defer allocator.free(relative_path_no_ext); + const relative_path_no_ext = try std.fs.path.join(gpa, &.{ tmp_relative_path, "something/hello" }); + defer gpa.free(relative_path_no_ext); // Giving a full relative path to something/hello should work - try testExec(allocator, relative_path_no_ext, "hello from exe\n"); + try testExec(gpa, io, relative_path_no_ext, "hello from exe\n"); // But commands with path separators get excluded from PATH searching, so this will fail - try testExecError(error.FileNotFound, allocator, "something/hello"); + try testExecError(error.FileNotFound, gpa, io, "something/hello"); // Now that .BAT is the first PATHEXT that should be found, this should succeed - try testExec(allocator, "heLLo", "hello from bat\r\n"); + try testExec(gpa, io, "heLLo", "hello from bat\r\n"); // Add a hello.exe that is not a valid executable - try tmp.dir.writeFile(.{ .sub_path = "hello.exe", .data = "invalid" }); + try tmp_dir.writeFile(io, .{ .sub_path = "hello.exe", .data = "invalid" }); // Trying to execute it with extension will give InvalidExe. This is a special // case for .EXE extensions, where if they ever try to get executed but they are // invalid, that gets treated as a fatal error wherever they are found and InvalidExe // is returned immediately. - try testExecError(error.InvalidExe, allocator, "hello.exe"); + try testExecError(error.InvalidExe, gpa, io, "hello.exe"); // Same thing applies to the command with no extension--even though there is a // hello.bat that could be executed, it should stop after it tries executing // hello.exe and getting InvalidExe. - try testExecError(error.InvalidExe, allocator, "hello"); + try testExecError(error.InvalidExe, gpa, io, "hello"); // If we now rename hello.exe to have no extension, it will behave differently - try renameExe(tmp.dir, "hello.exe", "hello"); + try renameExe(tmp_dir, io, "hello.exe", "hello"); // Now, trying to execute it without an extension should treat InvalidExe as recoverable // and skip over it and find hello.bat and execute that - try testExec(allocator, "hello", "hello from bat\r\n"); + try testExec(gpa, io, "hello", "hello from bat\r\n"); // If we rename the invalid exe to something else - try renameExe(tmp.dir, "hello", "goodbye"); + try renameExe(tmp_dir, io, "hello", "goodbye"); // Then we should now get FileNotFound when trying to execute 'goodbye', // since that is what the original error will be after searching for 'goodbye' // in the cwd. It will try to execute 'goodbye' from the PATH but the InvalidExe error // should be ignored in this case. - try testExecError(error.FileNotFound, allocator, "goodbye"); + try testExecError(error.FileNotFound, gpa, io, "goodbye"); // Now let's set the tmp dir as the cwd and set the path only include the "something" sub dir - try tmp.dir.setAsCwd(); - defer tmp.parent_dir.setAsCwd() catch {}; - const something_subdir_abs_path = try std.mem.concatWithSentinel(allocator, u16, &.{ tmp_absolute_path_w, utf16Literal("\\something") }, 0); - defer allocator.free(something_subdir_abs_path); + try std.process.setCurrentDir(io, tmp_dir); + defer std.process.setCurrentDir(io, initial_process_cwd) catch {}; + const something_subdir_abs_path = try std.mem.concatWithSentinel(gpa, u16, &.{ tmp_absolute_path_w, utf16Literal("\\something") }, 0); + defer gpa.free(something_subdir_abs_path); std.debug.assert(windows.kernel32.SetEnvironmentVariableW( utf16Literal("PATH"), @@ -133,37 +138,37 @@ pub fn main() anyerror!void { // Now trying to execute goodbye should give error.InvalidExe since it's the original // error that we got when trying within the cwd - try testExecError(error.InvalidExe, allocator, "goodbye"); + try testExecError(error.InvalidExe, gpa, io, "goodbye"); // hello should still find the .bat - try testExec(allocator, "hello", "hello from bat\r\n"); + try testExec(gpa, io, "hello", "hello from bat\r\n"); // If we rename something/hello.exe to something/goodbye.exe - try renameExe(tmp.dir, "something/hello.exe", "something/goodbye.exe"); + try renameExe(tmp_dir, io, "something/hello.exe", "something/goodbye.exe"); // And try to execute goodbye, then the one in something should be found // since the one in cwd is an invalid executable - try testExec(allocator, "goodbye", "hello from exe\n"); + try testExec(gpa, io, "goodbye", "hello from exe\n"); // If we use an absolute path to execute the invalid goodbye - const goodbye_abs_path = try std.mem.join(allocator, "\\", &.{ tmp_absolute_path, "goodbye" }); - defer allocator.free(goodbye_abs_path); + const goodbye_abs_path = try std.mem.join(gpa, "\\", &.{ tmp_absolute_path, "goodbye" }); + defer gpa.free(goodbye_abs_path); // then the PATH should not be searched and we should get InvalidExe - try testExecError(error.InvalidExe, allocator, goodbye_abs_path); + try testExecError(error.InvalidExe, gpa, io, goodbye_abs_path); // If we try to exec but provide a cwd that is an absolute path, the PATH // should still be searched and the goodbye.exe in something should be found. - try testExecWithCwd(allocator, "goodbye", tmp_absolute_path, "hello from exe\n"); + try testExecWithCwd(gpa, io, "goodbye", tmp_absolute_path, "hello from exe\n"); // introduce some extra path separators into the path which is dealt with inside the spawn call. const denormed_something_subdir_size = std.mem.replacementSize(u16, something_subdir_abs_path, utf16Literal("\\"), utf16Literal("\\\\\\\\")); - const denormed_something_subdir_abs_path = try allocator.allocSentinel(u16, denormed_something_subdir_size, 0); - defer allocator.free(denormed_something_subdir_abs_path); + const denormed_something_subdir_abs_path = try gpa.allocSentinel(u16, denormed_something_subdir_size, 0); + defer gpa.free(denormed_something_subdir_abs_path); _ = std.mem.replace(u16, something_subdir_abs_path, utf16Literal("\\"), utf16Literal("\\\\\\\\"), denormed_something_subdir_abs_path); - const denormed_something_subdir_wtf8 = try std.unicode.wtf16LeToWtf8Alloc(allocator, denormed_something_subdir_abs_path); - defer allocator.free(denormed_something_subdir_wtf8); + const denormed_something_subdir_wtf8 = try std.unicode.wtf16LeToWtf8Alloc(gpa, denormed_something_subdir_abs_path); + defer gpa.free(denormed_something_subdir_wtf8); // clear the path to ensure that the match comes from the cwd std.debug.assert(windows.kernel32.SetEnvironmentVariableW( @@ -171,21 +176,21 @@ pub fn main() anyerror!void { null, ) == windows.TRUE); - try testExecWithCwd(allocator, "goodbye", denormed_something_subdir_wtf8, "hello from exe\n"); + try testExecWithCwd(gpa, io, "goodbye", denormed_something_subdir_wtf8, "hello from exe\n"); // normalization should also work if the non-normalized path is found in the PATH var. std.debug.assert(windows.kernel32.SetEnvironmentVariableW( utf16Literal("PATH"), denormed_something_subdir_abs_path, ) == windows.TRUE); - try testExec(allocator, "goodbye", "hello from exe\n"); + try testExec(gpa, io, "goodbye", "hello from exe\n"); // now make sure we can launch executables "outside" of the cwd - var subdir_cwd = try tmp.dir.openDir(denormed_something_subdir_wtf8, .{}); - defer subdir_cwd.close(); + var subdir_cwd = try tmp_dir.openDir(io, denormed_something_subdir_wtf8, .{}); + defer subdir_cwd.close(io); - try renameExe(tmp.dir, "something/goodbye.exe", "hello.exe"); - try subdir_cwd.setAsCwd(); + try renameExe(tmp_dir, io, "something/goodbye.exe", "hello.exe"); + try std.process.setCurrentDir(io, subdir_cwd); // clear the PATH again std.debug.assert(windows.kernel32.SetEnvironmentVariableW( @@ -194,33 +199,32 @@ pub fn main() anyerror!void { ) == windows.TRUE); // while we're at it make sure non-windows separators work fine - try testExec(allocator, "../hello", "hello from exe\n"); + try testExec(gpa, io, "../hello", "hello from exe\n"); } -fn testExecError(err: anyerror, allocator: std.mem.Allocator, command: []const u8) !void { - return std.testing.expectError(err, testExec(allocator, command, "")); +fn testExecError(err: anyerror, gpa: Allocator, io: Io, command: []const u8) !void { + return std.testing.expectError(err, testExec(gpa, io, command, "")); } -fn testExec(allocator: std.mem.Allocator, command: []const u8, expected_stdout: []const u8) !void { - return testExecWithCwd(allocator, command, null, expected_stdout); +fn testExec(gpa: Allocator, io: Io, command: []const u8, expected_stdout: []const u8) !void { + return testExecWithCwd(gpa, io, command, null, expected_stdout); } -fn testExecWithCwd(allocator: std.mem.Allocator, command: []const u8, cwd: ?[]const u8, expected_stdout: []const u8) !void { - const result = try std.process.Child.run(.{ - .allocator = allocator, +fn testExecWithCwd(gpa: Allocator, io: Io, command: []const u8, cwd: ?[]const u8, expected_stdout: []const u8) !void { + const result = try std.process.run(gpa, io, .{ .argv = &[_][]const u8{command}, .cwd = cwd, }); - defer allocator.free(result.stdout); - defer allocator.free(result.stderr); + defer gpa.free(result.stdout); + defer gpa.free(result.stderr); try std.testing.expectEqualStrings("", result.stderr); try std.testing.expectEqualStrings(expected_stdout, result.stdout); } -fn renameExe(dir: std.fs.Dir, old_sub_path: []const u8, new_sub_path: []const u8) !void { +fn renameExe(dir: Io.Dir, io: Io, old_sub_path: []const u8, new_sub_path: []const u8) !void { var attempt: u5 = 0; - while (true) break dir.rename(old_sub_path, new_sub_path) catch |err| switch (err) { + while (true) break dir.rename(old_sub_path, dir, new_sub_path, io) catch |err| switch (err) { error.AccessDenied => { if (attempt == 13) return error.AccessDenied; // give the kernel a chance to finish closing the executable handle diff --git a/test/tests.zig b/test/tests.zig index 4ea42c2eb563..88ef54bb294a 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -187,29 +187,30 @@ const test_targets = blk: { .link_libc = true, }, - .{ - .target = .{ - .cpu_arch = .aarch64, - .os_tag = .linux, - .abi = .none, - }, - .use_llvm = false, - .use_lld = false, - .optimize_mode = .ReleaseFast, - .strip = true, - }, - .{ - .target = .{ - .cpu_arch = .aarch64, - .cpu_model = .{ .explicit = &std.Target.aarch64.cpu.neoverse_n1 }, - .os_tag = .linux, - .abi = .none, - }, - .use_llvm = false, - .use_lld = false, - .optimize_mode = .ReleaseFast, - .strip = true, - }, + // Disabled due to https://codeberg.org/ziglang/zig/pulls/30232#issuecomment-9203351 + //.{ + // .target = .{ + // .cpu_arch = .aarch64, + // .os_tag = .linux, + // .abi = .none, + // }, + // .use_llvm = false, + // .use_lld = false, + // .optimize_mode = .ReleaseFast, + // .strip = true, + //}, + //.{ + // .target = .{ + // .cpu_arch = .aarch64, + // .cpu_model = .{ .explicit = &std.Target.aarch64.cpu.neoverse_n1 }, + // .os_tag = .linux, + // .abi = .none, + // }, + // .use_llvm = false, + // .use_lld = false, + // .optimize_mode = .ReleaseFast, + // .strip = true, + //}, .{ .target = .{ @@ -1204,17 +1205,18 @@ const test_targets = blk: { }, }, - .{ - .target = .{ - .cpu_arch = .aarch64, - .os_tag = .macos, - .abi = .none, - }, - .use_llvm = false, - .use_lld = false, - .optimize_mode = .ReleaseFast, - .strip = true, - }, + // Disabled due to https://codeberg.org/ziglang/zig/pulls/30232#issuecomment-9203351 + //.{ + // .target = .{ + // .cpu_arch = .aarch64, + // .os_tag = .macos, + // .abi = .none, + // }, + // .use_llvm = false, + // .use_lld = false, + // .optimize_mode = .ReleaseFast, + // .strip = true, + //}, .{ .target = .{ @@ -1364,6 +1366,89 @@ const test_targets = blk: { .link_libc = true, }, + // OpenBSD Targets + + .{ + .target = .{ + .cpu_arch = .aarch64, + .os_tag = .openbsd, + .abi = .none, + }, + .link_libc = true, + }, + + .{ + .target = .{ + .cpu_arch = .arm, + .os_tag = .openbsd, + .abi = .eabi, + }, + .link_libc = true, + }, + + .{ + .target = .{ + .cpu_arch = .mips64, + .os_tag = .openbsd, + .abi = .none, + }, + .link_libc = true, + }, + + .{ + .target = .{ + .cpu_arch = .mips64el, + .os_tag = .openbsd, + .abi = .none, + }, + .link_libc = true, + }, + + .{ + .target = .{ + .cpu_arch = .powerpc, + .os_tag = .openbsd, + .abi = .eabihf, + }, + .link_libc = true, + }, + + .{ + .target = .{ + .cpu_arch = .powerpc64, + .os_tag = .openbsd, + .abi = .none, + }, + .link_libc = true, + }, + + .{ + .target = .{ + .cpu_arch = .riscv64, + .os_tag = .openbsd, + .abi = .none, + }, + .link_libc = true, + }, + + .{ + .target = .{ + .cpu_arch = .x86, + .os_tag = .openbsd, + .abi = .none, + }, + .link_libc = true, + }, + + .{ + .target = .{ + .cpu_arch = .x86_64, + .os_tag = .openbsd, + .abi = .none, + }, + .link_libc = true, + }, + // SPIR-V Targets // Disabled due to no active maintainer (feel free to fix the failures @@ -1381,18 +1466,16 @@ const test_targets = blk: { // WASI Targets - // Disabled due to no active maintainer (feel free to fix the failures - // and then re-enable at any time). The failures occur due to backend - // miscompilation of different AIR from the frontend. - //.{ - // .target = .{ - // .cpu_arch = .wasm32, - // .os_tag = .wasi, - // .abi = .none, - // }, - // .use_llvm = false, - // .use_lld = false, - //}, + .{ + .target = .{ + .cpu_arch = .wasm32, + .os_tag = .wasi, + .abi = .none, + }, + .skip_modules = &.{ "compiler-rt", "std" }, + .use_llvm = false, + .use_lld = false, + }, .{ .target = .{ .cpu_arch = .wasm32, @@ -2029,9 +2112,9 @@ pub fn addCliTests(b: *std.Build) *Step { { // Test `zig init`. - const tmp_path = b.makeTempPath(); + const tmp_path = b.tmpPath(); const init_exe = b.addSystemCommand(&.{ b.graph.zig_exe, "init" }); - init_exe.setCwd(.{ .cwd_relative = tmp_path }); + init_exe.setCwd(tmp_path); init_exe.setName("zig init"); init_exe.expectStdOutEqual(""); init_exe.expectStdErrEqual("info: created build.zig\n" ++ @@ -2052,31 +2135,28 @@ pub fn addCliTests(b: *std.Build) *Step { run_bad.step.dependOn(&init_exe.step); const run_test = b.addSystemCommand(&.{ b.graph.zig_exe, "build", "test" }); - run_test.setCwd(.{ .cwd_relative = tmp_path }); + run_test.setCwd(tmp_path); run_test.setName("zig build test"); run_test.expectStdOutEqual(""); run_test.step.dependOn(&init_exe.step); const run_run = b.addSystemCommand(&.{ b.graph.zig_exe, "build", "run" }); - run_run.setCwd(.{ .cwd_relative = tmp_path }); + run_run.setCwd(tmp_path); run_run.setName("zig build run"); run_run.expectStdOutEqual("Run `zig build test` to run the tests.\n"); - run_run.expectStdErrEqual("All your codebase are belong to us.\n"); + run_run.expectStdErrMatch("All your codebase are belong to us.\n"); run_run.step.dependOn(&init_exe.step); - const cleanup = b.addRemoveDirTree(.{ .cwd_relative = tmp_path }); - cleanup.step.dependOn(&run_test.step); - cleanup.step.dependOn(&run_run.step); - cleanup.step.dependOn(&run_bad.step); - - step.dependOn(&cleanup.step); + step.dependOn(&run_test.step); + step.dependOn(&run_run.step); + step.dependOn(&run_bad.step); } { // Test `zig init -m`. - const tmp_path = b.makeTempPath(); + const tmp_path = b.tmpPath(); const init_exe = b.addSystemCommand(&.{ b.graph.zig_exe, "init", "-m" }); - init_exe.setCwd(.{ .cwd_relative = tmp_path }); + init_exe.setCwd(tmp_path); init_exe.setName("zig init -m"); init_exe.expectStdOutEqual(""); init_exe.expectStdErrEqual("info: successfully populated 'build.zig.zon' and 'build.zig'\n"); @@ -2084,7 +2164,7 @@ pub fn addCliTests(b: *std.Build) *Step { // Test Godbolt API if (builtin.os.tag == .linux and builtin.cpu.arch == .x86_64) { - const tmp_path = b.makeTempPath(); + const tmp_path = b.tmpPath(); const example_zig = b.addWriteFiles().add("example.zig", \\// Type your code here, or load an example. @@ -2100,13 +2180,9 @@ pub fn addCliTests(b: *std.Build) *Step { ); // This is intended to be the exact CLI usage used by godbolt.org. - const run = b.addSystemCommand(&.{ - b.graph.zig_exe, "build-obj", - "--cache-dir", tmp_path, - "--name", "example", - "-fno-emit-bin", "-fno-emit-h", - "-fstrip", "-OReleaseFast", - }); + const run = b.addSystemCommand(&.{ b.graph.zig_exe, "build-obj", "--cache-dir" }); + run.addDirectoryArg(tmp_path); + run.addArgs(&.{ "--name", "example", "-fno-emit-bin", "-fno-emit-h", "-fstrip", "-OReleaseFast" }); run.addFileArg(example_zig); const example_s = run.addPrefixedOutputFileArg("-femit-asm=", "example.s"); @@ -2119,10 +2195,7 @@ pub fn addCliTests(b: *std.Build) *Step { }); checkfile.setName("check godbolt.org CLI usage generating valid asm"); - const cleanup = b.addRemoveDirTree(.{ .cwd_relative = tmp_path }); - cleanup.step.dependOn(&checkfile.step); - - step.dependOn(&cleanup.step); + step.dependOn(&checkfile.step); } { @@ -2131,22 +2204,19 @@ pub fn addCliTests(b: *std.Build) *Step { // directory because this test will be mutating the files. The cache // system relies on cache directories being mutated only by their // owners. - const tmp_path = b.makeTempPath(); + const tmp_wf = b.addTempFiles(); const unformatted_code = " // no reason for indent"; - var dir = std.fs.cwd().openDir(tmp_path, .{}) catch @panic("unhandled"); - defer dir.close(); - dir.writeFile(.{ .sub_path = "fmt1.zig", .data = unformatted_code }) catch @panic("unhandled"); - dir.writeFile(.{ .sub_path = "fmt2.zig", .data = unformatted_code }) catch @panic("unhandled"); - dir.makeDir("subdir") catch @panic("unhandled"); - var subdir = dir.openDir("subdir", .{}) catch @panic("unhandled"); - defer subdir.close(); - subdir.writeFile(.{ .sub_path = "fmt3.zig", .data = unformatted_code }) catch @panic("unhandled"); + _ = tmp_wf.add("fmt1.zig", unformatted_code); + _ = tmp_wf.add("fmt2.zig", unformatted_code); + _ = tmp_wf.add("subdir/fmt3.zig", unformatted_code); + + const tmp_path = tmp_wf.getDirectory(); // Test zig fmt affecting only the appropriate files. const run1 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "fmt1.zig" }); run1.setName("run zig fmt one file"); - run1.setCwd(.{ .cwd_relative = tmp_path }); + run1.setCwd(tmp_path); run1.has_side_effects = true; // stdout should be file path + \n run1.expectStdOutEqual("fmt1.zig\n"); @@ -2154,7 +2224,7 @@ pub fn addCliTests(b: *std.Build) *Step { // Test excluding files and directories from a run const run2 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "subdir", "." }); run2.setName("run zig fmt on directory with exclusions"); - run2.setCwd(.{ .cwd_relative = tmp_path }); + run2.setCwd(tmp_path); run2.has_side_effects = true; run2.expectStdOutEqual(""); run2.step.dependOn(&run1.step); @@ -2162,7 +2232,7 @@ pub fn addCliTests(b: *std.Build) *Step { // Test excluding non-existent file const run3 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "nonexistent.zig", "." }); run3.setName("run zig fmt on directory with non-existent exclusion"); - run3.setCwd(.{ .cwd_relative = tmp_path }); + run3.setCwd(tmp_path); run3.has_side_effects = true; run3.expectStdOutEqual("." ++ s ++ "subdir" ++ s ++ "fmt3.zig\n"); run3.step.dependOn(&run2.step); @@ -2170,7 +2240,7 @@ pub fn addCliTests(b: *std.Build) *Step { // running it on the dir, only the new file should be changed const run4 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." }); run4.setName("run zig fmt the directory"); - run4.setCwd(.{ .cwd_relative = tmp_path }); + run4.setCwd(tmp_path); run4.has_side_effects = true; run4.expectStdOutEqual("." ++ s ++ "fmt2.zig\n"); run4.step.dependOn(&run3.step); @@ -2178,37 +2248,33 @@ pub fn addCliTests(b: *std.Build) *Step { // both files have been formatted, nothing should change now const run5 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." }); run5.setName("run zig fmt with nothing to do"); - run5.setCwd(.{ .cwd_relative = tmp_path }); + run5.setCwd(tmp_path); run5.has_side_effects = true; run5.expectStdOutEqual(""); run5.step.dependOn(&run4.step); const unformatted_code_utf16 = "\xff\xfe \x00 \x00 \x00 \x00/\x00/\x00 \x00n\x00o\x00 \x00r\x00e\x00a\x00s\x00o\x00n\x00"; - const fmt6_path = b.pathJoin(&.{ tmp_path, "fmt6.zig" }); - const write6 = b.addUpdateSourceFiles(); - write6.addBytesToSource(unformatted_code_utf16, fmt6_path); + const write6 = b.addMutateFiles(tmp_path); + const fmt6_path = write6.add("fmt6.zig", unformatted_code_utf16); write6.step.dependOn(&run5.step); // Test `zig fmt` handling UTF-16 decoding. const run6 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." }); run6.setName("run zig fmt convert UTF-16 to UTF-8"); - run6.setCwd(.{ .cwd_relative = tmp_path }); + run6.setCwd(tmp_path); run6.has_side_effects = true; run6.expectStdOutEqual("." ++ s ++ "fmt6.zig\n"); run6.step.dependOn(&write6.step); // TODO change this to an exact match - const check6 = b.addCheckFile(.{ .cwd_relative = fmt6_path }, .{ + const check6 = b.addCheckFile(fmt6_path, .{ .expected_matches = &.{ "// no reason", }, }); check6.step.dependOn(&run6.step); - const cleanup = b.addRemoveDirTree(.{ .cwd_relative = tmp_path }); - cleanup.step.dependOn(&check6.step); - - step.dependOn(&cleanup.step); + step.dependOn(&check6.step); } { @@ -2246,8 +2312,11 @@ const ModuleTestOptions = struct { test_default_only: bool, skip_single_threaded: bool, skip_non_native: bool, + skip_spirv: bool, + skip_wasm: bool, skip_freebsd: bool, skip_netbsd: bool, + skip_openbsd: bool, skip_windows: bool, skip_darwin: bool, skip_linux: bool, @@ -2281,8 +2350,12 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { if (options.skip_non_native and !test_target.target.isNative()) continue; + if (options.skip_spirv and test_target.target.cpu_arch != null and test_target.target.cpu_arch.?.isSpirV()) continue; + if (options.skip_wasm and test_target.target.cpu_arch != null and test_target.target.cpu_arch.?.isWasm()) continue; + if (options.skip_freebsd and test_target.target.os_tag == .freebsd) continue; if (options.skip_netbsd and test_target.target.os_tag == .netbsd) continue; + if (options.skip_openbsd and test_target.target.os_tag == .openbsd) continue; if (options.skip_windows and test_target.target.os_tag == .windows) continue; if (options.skip_darwin and test_target.target.os_tag != null and test_target.target.os_tag.?.isDarwin()) continue; if (options.skip_linux and test_target.target.os_tag == .linux) continue; @@ -2339,8 +2412,11 @@ fn addOneModuleTest( const libc_suffix = if (test_target.link_libc == true) "-libc" else ""; const model_txt = target.cpu.model.name; - // wasm32-wasi builds need more RAM, idk why - const max_rss = if (target.os.tag == .wasi) + // These emulated targets need a lot more RAM for unknown reasons. + const max_rss = if (mem.eql(u8, options.name, "std") and + (target.cpu.arch == .hexagon or + (target.cpu.arch.isRISCV() and !resolved_target.query.isNative()) or + target.cpu.arch.isWasm())) options.max_rss * 2 else options.max_rss; @@ -2519,13 +2595,16 @@ pub fn wouldUseLlvm(use_llvm: ?bool, query: std.Target.Query, optimize_mode: Opt const CAbiTestOptions = struct { test_target_filters: []const []const u8, skip_non_native: bool, + skip_wasm: bool, skip_freebsd: bool, skip_netbsd: bool, + skip_openbsd: bool, skip_windows: bool, skip_darwin: bool, skip_linux: bool, skip_llvm: bool, skip_release: bool, + max_rss: usize = 0, }; pub fn addCAbiTests(b: *std.Build, options: CAbiTestOptions) *Step { @@ -2538,8 +2617,12 @@ pub fn addCAbiTests(b: *std.Build, options: CAbiTestOptions) *Step { for (c_abi_targets) |c_abi_target| { if (options.skip_non_native and !c_abi_target.target.isNative()) continue; + + if (options.skip_wasm and c_abi_target.target.cpu_arch != null and c_abi_target.target.cpu_arch.?.isWasm()) continue; + if (options.skip_freebsd and c_abi_target.target.os_tag == .freebsd) continue; if (options.skip_netbsd and c_abi_target.target.os_tag == .netbsd) continue; + if (options.skip_openbsd and c_abi_target.target.os_tag == .openbsd) continue; if (options.skip_windows and c_abi_target.target.os_tag == .windows) continue; if (options.skip_darwin and c_abi_target.target.os_tag != null and c_abi_target.target.os_tag.?.isDarwin()) continue; if (options.skip_linux and c_abi_target.target.os_tag == .linux) continue; @@ -2595,6 +2678,7 @@ pub fn addCAbiTests(b: *std.Build, options: CAbiTestOptions) *Step { .root_module = test_mod, .use_llvm = c_abi_target.use_llvm, .use_lld = c_abi_target.use_lld, + .max_rss = options.max_rss, }); // This test is intentionally trying to check if the external ABI is @@ -2617,11 +2701,12 @@ pub fn addCases( ) !void { const arena = b.allocator; const gpa = b.allocator; + const io = b.graph.io; - var cases = @import("src/Cases.zig").init(gpa, arena); + var cases = @import("src/Cases.zig").init(gpa, arena, io); - var dir = try b.build_root.handle.openDir("test/cases", .{ .iterate = true }); - defer dir.close(); + var dir = try b.build_root.handle.openDir(io, "test/cases", .{ .iterate = true }); + defer dir.close(io); cases.addFromDir(dir, b); try @import("cases.zig").addCases(&cases, build_options, b); @@ -2666,7 +2751,9 @@ pub fn addDebuggerTests(b: *std.Build, options: DebuggerContext.Options) ?*Step return step; } -pub fn addIncrementalTests(b: *std.Build, test_step: *Step) !void { +pub fn addIncrementalTests(b: *std.Build, test_step: *Step, test_filters: []const []const u8) !void { + const io = b.graph.io; + const incr_check = b.addExecutable(.{ .name = "incr-check", .root_module = b.createModule(.{ @@ -2676,12 +2763,17 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step) !void { }), }); - var dir = try b.build_root.handle.openDir("test/incremental", .{ .iterate = true }); - defer dir.close(); + var dir = try b.build_root.handle.openDir(io, "test/incremental", .{ .iterate = true }); + defer dir.close(io); var it = try dir.walk(b.graph.arena); - while (try it.next()) |entry| { + while (try it.next(io)) |entry| { if (entry.kind != .file) continue; + if (std.mem.endsWith(u8, entry.basename, ".swp")) continue; + + for (test_filters) |test_filter| { + if (std.mem.indexOf(u8, entry.path, test_filter)) |_| break; + } else if (test_filters.len > 0) continue; const run = b.addRunArtifact(incr_check); run.setName(b.fmt("incr-check '{s}'", .{entry.basename})); @@ -2690,7 +2782,12 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step) !void { run.addFileArg(b.path("test/incremental/").path(b, entry.path)); run.addArgs(&.{ "--zig-lib-dir", b.fmt("{f}", .{b.graph.zig_lib_directory}) }); - run.addCheck(.{ .expect_term = .{ .Exited = 0 } }); + if (b.enable_qemu) run.addArg("-fqemu"); + if (b.enable_wine) run.addArg("-fwine"); + if (b.enable_wasmtime) run.addArg("-fwasmtime"); + if (b.enable_darling) run.addArg("-fdarling"); + + run.addCheck(.{ .expect_term = .{ .exited = 0 } }); test_step.dependOn(&run.step); } diff --git a/tools/docgen.zig b/tools/docgen.zig index d23892e06c89..c526233f517c 100644 --- a/tools/docgen.zig +++ b/tools/docgen.zig @@ -1,6 +1,8 @@ -const std = @import("std"); const builtin = @import("builtin"); -const fs = std.fs; + +const std = @import("std"); +const Io = std.Io; +const Dir = std.Io.Dir; const process = std.process; const Progress = std.Progress; const print = std.debug.print; @@ -8,7 +10,6 @@ const mem = std.mem; const testing = std.testing; const Allocator = std.mem.Allocator; const ArrayList = std.ArrayList; -const getExternalExecutor = std.zig.system.getExternalExecutor; const fatal = std.process.fatal; const Writer = std.Io.Writer; @@ -27,21 +28,13 @@ const usage = \\ ; -pub fn main() !void { - var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena_instance.deinit(); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const io = init.io; - const arena = arena_instance.allocator(); - - var args_it = try process.argsWithAllocator(arena); + var args_it = try init.minimal.args.iterateAllocator(arena); if (!args_it.skip()) @panic("expected self arg"); - const gpa = arena; - - var threaded: std.Io.Threaded = .init(gpa); - defer threaded.deinit(); - const io = threaded.io(); - var opt_code_dir: ?[]const u8 = null; var opt_input: ?[]const u8 = null; var opt_output: ?[]const u8 = null; @@ -49,7 +42,7 @@ pub fn main() !void { while (args_it.next()) |arg| { if (mem.startsWith(u8, arg, "-")) { if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { - try fs.File.stdout().writeAll(usage); + try Io.File.stdout().writeStreamingAll(io, usage); process.exit(0); } else if (mem.eql(u8, arg, "--code-dir")) { if (args_it.next()) |param| { @@ -72,16 +65,16 @@ pub fn main() !void { const output_path = opt_output orelse fatal("missing output file", .{}); const code_dir_path = opt_code_dir orelse fatal("missing --code-dir argument", .{}); - var in_file = try fs.cwd().openFile(input_path, .{}); - defer in_file.close(); + var in_file = try Dir.cwd().openFile(io, input_path, .{}); + defer in_file.close(io); - var out_file = try fs.cwd().createFile(output_path, .{}); - defer out_file.close(); + var out_file = try Dir.cwd().createFile(io, output_path, .{}); + defer out_file.close(io); var out_file_buffer: [4096]u8 = undefined; - var out_file_writer = out_file.writer(&out_file_buffer); + var out_file_writer = out_file.writer(io, &out_file_buffer); - var code_dir = try fs.cwd().openDir(code_dir_path, .{}); - defer code_dir.close(); + var code_dir = try Dir.cwd().openDir(io, code_dir_path, .{}); + defer code_dir.close(io); var in_file_reader = in_file.reader(io, &.{}); const input_file_bytes = try in_file_reader.interface.allocRemaining(arena, .limited(max_doc_file_size)); @@ -89,7 +82,7 @@ pub fn main() !void { var tokenizer = Tokenizer.init(input_path, input_file_bytes); var toc = try genToc(arena, &tokenizer); - try genHtml(arena, &tokenizer, &toc, code_dir, &out_file_writer.interface); + try genHtml(arena, io, &tokenizer, &toc, code_dir, &out_file_writer.interface); try out_file_writer.end(); } @@ -988,9 +981,10 @@ fn printShell(out: *Writer, shell_content: []const u8, escape: bool) !void { fn genHtml( allocator: Allocator, + io: Io, tokenizer: *Tokenizer, toc: *Toc, - code_dir: std.fs.Dir, + code_dir: Dir, out: *Writer, ) !void { for (toc.nodes) |node| { @@ -1042,11 +1036,11 @@ fn genHtml( }, .Code => |code| { const out_basename = try std.fmt.allocPrint(allocator, "{s}.out", .{ - fs.path.stem(code.name), + Dir.path.stem(code.name), }); defer allocator.free(out_basename); - const contents = code_dir.readFileAlloc(out_basename, allocator, .limited(std.math.maxInt(u32))) catch |err| { + const contents = code_dir.readFileAlloc(io, out_basename, allocator, .limited(std.math.maxInt(u32))) catch |err| { return parseError(tokenizer, code.token, "unable to open '{s}': {t}", .{ out_basename, err }); }; defer allocator.free(contents); diff --git a/tools/doctest.zig b/tools/doctest.zig index 63b7e50778f8..5037bac2c2fc 100644 --- a/tools/doctest.zig +++ b/tools/doctest.zig @@ -2,10 +2,10 @@ const builtin = @import("builtin"); const std = @import("std"); const Io = std.Io; +const Dir = std.Io.Dir; const Writer = std.Io.Writer; const fatal = std.process.fatal; const mem = std.mem; -const fs = std.fs; const process = std.process; const Allocator = std.mem.Allocator; const testing = std.testing; @@ -29,21 +29,17 @@ const usage = \\ ; -pub fn main() !void { - var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena_instance.deinit(); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const io = init.io; + const environ_map = init.environ_map; + const cwd_path = try std.process.getCwdAlloc(arena); - const arena = arena_instance.allocator(); + try environ_map.put("CLICOLOR_FORCE", "1"); - var args_it = try process.argsWithAllocator(arena); + var args_it = try init.minimal.args.iterateAllocator(arena); if (!args_it.skip()) fatal("missing argv[0]", .{}); - const gpa = arena; - - var threaded: std.Io.Threaded = .init(gpa); - defer threaded.deinit(); - const io = threaded.io(); - var opt_input: ?[]const u8 = null; var opt_output: ?[]const u8 = null; var opt_zig: ?[]const u8 = null; @@ -53,7 +49,7 @@ pub fn main() !void { while (args_it.next()) |arg| { if (mem.startsWith(u8, arg, "-")) { if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { - try std.fs.File.stdout().writeAll(usage); + try Io.File.stdout().writeStreamingAll(io, usage); process.exit(0); } else if (mem.eql(u8, arg, "-i")) { opt_input = args_it.next() orelse fatal("expected parameter after -i", .{}); @@ -78,39 +74,41 @@ pub fn main() !void { const zig_path = opt_zig orelse fatal("missing zig compiler path (--zig)", .{}); const cache_root = opt_cache_root orelse fatal("missing cache root path (--cache-root)", .{}); - const source_bytes = try fs.cwd().readFileAlloc(input_path, arena, .limited(std.math.maxInt(u32))); + const source_bytes = try Dir.cwd().readFileAlloc(io, input_path, arena, .limited(std.math.maxInt(u32))); const code = try parseManifest(arena, source_bytes); const source = stripManifest(source_bytes); - const tmp_dir_path = try std.fmt.allocPrint(arena, "{s}/tmp/{x}", .{ - cache_root, std.crypto.random.int(u64), - }); - fs.cwd().makePath(tmp_dir_path) catch |err| - fatal("unable to create tmp dir '{s}': {s}", .{ tmp_dir_path, @errorName(err) }); - defer fs.cwd().deleteTree(tmp_dir_path) catch |err| std.log.err("unable to delete '{s}': {s}", .{ - tmp_dir_path, @errorName(err), + var random_integer: u64 = undefined; + io.random(@ptrCast(&random_integer)); + + const tmp_dir_path = try std.fmt.allocPrint(arena, "{s}/tmp/{x}", .{ cache_root, random_integer }); + Dir.cwd().createDirPath(io, tmp_dir_path) catch |err| + fatal("unable to create tmp dir '{s}': {t}", .{ tmp_dir_path, err }); + defer Dir.cwd().deleteTree(io, tmp_dir_path) catch |err| std.log.err("unable to delete '{s}': {t}", .{ + tmp_dir_path, err, }); - var out_file = try fs.cwd().createFile(output_path, .{}); - defer out_file.close(); + var out_file = try Dir.cwd().createFile(io, output_path, .{}); + defer out_file.close(io); var out_file_buffer: [4096]u8 = undefined; - var out_file_writer = out_file.writer(&out_file_buffer); + var out_file_writer = out_file.writer(io, &out_file_buffer); const out = &out_file_writer.interface; - try printSourceBlock(arena, out, source, fs.path.basename(input_path)); + try printSourceBlock(arena, out, source, Dir.path.basename(input_path)); try printOutput( arena, io, out, code, tmp_dir_path, - try std.fs.path.relative(arena, tmp_dir_path, zig_path), - try std.fs.path.relative(arena, tmp_dir_path, input_path), + try Dir.path.relative(arena, cwd_path, environ_map, tmp_dir_path, zig_path), + try Dir.path.relative(arena, cwd_path, environ_map, tmp_dir_path, input_path), if (opt_zig_lib_dir) |zig_lib_dir| - try std.fs.path.relative(arena, tmp_dir_path, zig_lib_dir) + try Dir.path.relative(arena, cwd_path, environ_map, tmp_dir_path, zig_lib_dir) else null, + environ_map, ); try out_file_writer.end(); @@ -129,10 +127,8 @@ fn printOutput( input_path: []const u8, /// Relative to `tmp_dir_path`. opt_zig_lib_dir: ?[]const u8, + environ_map: *const process.Environ.Map, ) !void { - var env_map = try process.getEnvMap(arena); - try env_map.put("CLICOLOR_FORCE", "1"); - const host = try std.zig.system.resolveTargetQuery(io, .{}); const obj_ext = builtin.object_format.fileExt(builtin.cpu.arch); const print = std.debug.print; @@ -141,7 +137,7 @@ fn printOutput( defer shell_buffer.deinit(); const shell_out = &shell_buffer.writer; - const code_name = std.fs.path.stem(input_path); + const code_name = Dir.path.stem(input_path); switch (code.id) { .exe => |expected_outcome| code_block: { @@ -201,15 +197,14 @@ fn printOutput( try shell_out.print("\n", .{}); if (expected_outcome == .build_fail) { - const result = try process.Child.run(.{ - .allocator = arena, + const result = try process.run(arena, io, .{ .argv = build_args.items, .cwd = tmp_dir_path, - .env_map = &env_map, + .environ_map = environ_map, .max_output_bytes = max_doc_file_size, }); switch (result.term) { - .Exited => |exit_code| { + .exited => |exit_code| { if (exit_code == 0) { print("{s}\nThe following command incorrectly succeeded:\n", .{result.stderr}); dumpArgs(build_args.items); @@ -227,7 +222,7 @@ fn printOutput( try shell_out.writeAll(colored_stderr); break :code_block; } - const exec_result = run(arena, &env_map, tmp_dir_path, build_args.items) catch + const exec_result = run(arena, io, environ_map, tmp_dir_path, build_args.items) catch fatal("example failed to compile", .{}); if (code.verbose_cimport) { @@ -258,27 +253,26 @@ fn printOutput( var exited_with_signal = false; const result = if (expected_outcome == .fail) blk: { - const result = try process.Child.run(.{ - .allocator = arena, + const result = try process.run(arena, io, .{ .argv = run_args, - .env_map = &env_map, + .environ_map = environ_map, .cwd = tmp_dir_path, .max_output_bytes = max_doc_file_size, }); switch (result.term) { - .Exited => |exit_code| { + .exited => |exit_code| { if (exit_code == 0) { print("{s}\nThe following command incorrectly succeeded:\n", .{result.stderr}); dumpArgs(run_args); fatal("example incorrectly compiled", .{}); } }, - .Signal => exited_with_signal = true, + .signal => exited_with_signal = true, else => {}, } break :blk result; } else blk: { - break :blk run(arena, &env_map, tmp_dir_path, run_args) catch + break :blk run(arena, io, environ_map, tmp_dir_path, run_args) catch fatal("example crashed", .{}); }; @@ -327,7 +321,7 @@ fn printOutput( .arch_os_abi = triple, }); const target = try std.zig.system.resolveTargetQuery(io, target_query); - switch (getExternalExecutor(&host, &target, .{ + switch (getExternalExecutor(io, &host, &target, .{ .link_libc = code.link_libc, })) { .native => {}, @@ -347,7 +341,7 @@ fn printOutput( } } - const result = run(arena, &env_map, tmp_dir_path, test_args.items) catch + const result = run(arena, io, environ_map, tmp_dir_path, test_args.items) catch fatal("test failed", .{}); const escaped_stderr = try escapeHtml(arena, result.stderr); const escaped_stdout = try escapeHtml(arena, result.stdout); @@ -378,15 +372,14 @@ fn printOutput( try test_args.append("-lc"); try shell_out.print("-lc ", .{}); } - const result = try process.Child.run(.{ - .allocator = arena, + const result = try process.run(arena, io, .{ .argv = test_args.items, - .env_map = &env_map, + .environ_map = environ_map, .cwd = tmp_dir_path, .max_output_bytes = max_doc_file_size, }); switch (result.term) { - .Exited => |exit_code| { + .exited => |exit_code| { if (exit_code == 0) { print("{s}\nThe following command incorrectly succeeded:\n", .{result.stderr}); dumpArgs(test_args.items); @@ -435,15 +428,14 @@ fn printOutput( }, } - const result = try process.Child.run(.{ - .allocator = arena, + const result = try process.run(arena, io, .{ .argv = test_args.items, - .env_map = &env_map, + .environ_map = environ_map, .cwd = tmp_dir_path, .max_output_bytes = max_doc_file_size, }); switch (result.term) { - .Exited => |exit_code| { + .exited => |exit_code| { if (exit_code == 0) { print("{s}\nThe following command incorrectly succeeded:\n", .{result.stderr}); dumpArgs(test_args.items); @@ -512,15 +504,14 @@ fn printOutput( } if (maybe_error_match) |error_match| { - const result = try process.Child.run(.{ - .allocator = arena, + const result = try process.run(arena, io, .{ .argv = build_args.items, - .env_map = &env_map, + .environ_map = environ_map, .cwd = tmp_dir_path, .max_output_bytes = max_doc_file_size, }); switch (result.term) { - .Exited => |exit_code| { + .exited => |exit_code| { if (exit_code == 0) { print("{s}\nThe following command incorrectly succeeded:\n", .{result.stderr}); dumpArgs(build_args.items); @@ -541,7 +532,7 @@ fn printOutput( const colored_stderr = try termColor(arena, escaped_stderr); try shell_out.print("\n{s} ", .{colored_stderr}); } else { - _ = run(arena, &env_map, tmp_dir_path, build_args.items) catch fatal("example failed to compile", .{}); + _ = run(arena, io, environ_map, tmp_dir_path, build_args.items) catch fatal("example failed to compile", .{}); } try shell_out.writeAll("\n"); }, @@ -600,7 +591,7 @@ fn printOutput( try test_args.append(option); try shell_out.print("{s} ", .{option}); } - const result = run(arena, &env_map, tmp_dir_path, test_args.items) catch fatal("test failed", .{}); + const result = run(arena, io, environ_map, tmp_dir_path, test_args.items) catch fatal("test failed", .{}); const escaped_stderr = try escapeHtml(arena, result.stderr); const escaped_stdout = try escapeHtml(arena, result.stdout); try shell_out.print("\n{s}{s}\n", .{ escaped_stderr, escaped_stdout }); @@ -1132,25 +1123,30 @@ fn in(slice: []const u8, number: u8) bool { fn run( allocator: Allocator, - env_map: *process.EnvMap, + io: Io, + environ_map: *const process.Environ.Map, cwd: []const u8, args: []const []const u8, -) !process.Child.RunResult { - const result = try process.Child.run(.{ - .allocator = allocator, +) !process.RunResult { + const result = try process.run(allocator, io, .{ .argv = args, - .env_map = env_map, + .environ_map = environ_map, .cwd = cwd, .max_output_bytes = max_doc_file_size, }); switch (result.term) { - .Exited => |exit_code| { + .exited => |exit_code| { if (exit_code != 0) { std.debug.print("{s}\nThe following command exited with code {}:\n", .{ result.stderr, exit_code }); dumpArgs(args); return error.ChildExitError; } }, + .signal => |sig| { + std.debug.print("{s}\nThe following command terminated with signal {t}:\n", .{ result.stderr, sig }); + dumpArgs(args); + return error.ChildCrashed; + }, else => { std.debug.print("{s}\nThe following command crashed:\n", .{result.stderr}); dumpArgs(args); diff --git a/tools/dump-cov.zig b/tools/dump-cov.zig index 3dd91de6122a..4a54d9f51992 100644 --- a/tools/dump-cov.zig +++ b/tools/dump-cov.zig @@ -2,25 +2,17 @@ //! including file:line:column information for each PC. const std = @import("std"); +const Io = std.Io; const fatal = std.process.fatal; const Path = std.Build.Cache.Path; const assert = std.debug.assert; const SeenPcsHeader = std.Build.abi.fuzz.SeenPcsHeader; -pub fn main() !void { - var debug_allocator: std.heap.DebugAllocator(.{}) = .init; - defer _ = debug_allocator.deinit(); - const gpa = debug_allocator.allocator(); - - var arena_instance: std.heap.ArenaAllocator = .init(gpa); - defer arena_instance.deinit(); - const arena = arena_instance.allocator(); - - var threaded: std.Io.Threaded = .init(gpa); - defer threaded.deinit(); - const io = threaded.io(); - - const args = try std.process.argsAlloc(arena); +pub fn main(init: std.process.Init) !void { + const gpa = init.gpa; + const arena = init.arena.allocator(); + const io = init.io; + const args = try init.minimal.args.toSlice(arena); const target_query_str = switch (args.len) { 3 => "native", @@ -51,12 +43,13 @@ pub fn main() !void { var coverage: std.debug.Coverage = .init; defer coverage.deinit(gpa); - var debug_info = std.debug.Info.load(gpa, exe_path, &coverage, target.ofmt, target.cpu.arch) catch |err| { - fatal("failed to load debug info for {f}: {s}", .{ exe_path, @errorName(err) }); + var debug_info = std.debug.Info.load(gpa, io, exe_path, &coverage, target.ofmt, target.cpu.arch) catch |err| { + fatal("failed to load debug info for {f}: {t}", .{ exe_path, err }); }; defer debug_info.deinit(gpa); const cov_bytes = cov_path.root_dir.handle.readFileAllocOptions( + io, cov_path.sub_path, arena, .limited(1 << 30), @@ -67,7 +60,7 @@ pub fn main() !void { }; var stdout_buffer: [4000]u8 = undefined; - var stdout_writer = std.fs.File.stdout().writerStreaming(&stdout_buffer); + var stdout_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer); const stdout = &stdout_writer.interface; const header: *SeenPcsHeader = @ptrCast(cov_bytes); @@ -83,7 +76,7 @@ pub fn main() !void { std.mem.sortUnstable(usize, sorted_pcs, {}, std.sort.asc(usize)); const source_locations = try arena.alloc(std.debug.Coverage.SourceLocation, sorted_pcs.len); - try debug_info.resolveAddresses(gpa, sorted_pcs, source_locations); + try debug_info.resolveAddresses(gpa, io, sorted_pcs, source_locations); const seen_pcs = header.seenBits(); diff --git a/tools/fetch_them_macos_headers.zig b/tools/fetch_them_macos_headers.zig index 2a2a2452e77e..cac4675bd42a 100644 --- a/tools/fetch_them_macos_headers.zig +++ b/tools/fetch_them_macos_headers.zig @@ -1,19 +1,14 @@ const std = @import("std"); const Io = std.Io; -const fs = std.fs; +const Dir = std.Io.Dir; const mem = std.mem; const process = std.process; const assert = std.debug.assert; -const tmpDir = std.testing.tmpDir; const fatal = std.process.fatal; const info = std.log.info; - -const Allocator = mem.Allocator; +const Allocator = std.mem.Allocator; const OsTag = std.Target.Os.Tag; -var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){}; -const gpa = general_purpose_allocator.allocator(); - const Arch = enum { aarch64, x86_64, @@ -67,14 +62,12 @@ const usage = \\-h, --help Print this help and exit ; -pub fn main() anyerror!void { - var arena = std.heap.ArenaAllocator.init(gpa); - defer arena.deinit(); - const allocator = arena.allocator(); - - const args = try std.process.argsAlloc(allocator); +pub fn main(init: std.process.Init) !void { + const io = init.io; + const arena = init.arena.allocator(); + const args = try init.minimal.args.toSlice(arena); - var argv = std.array_list.Managed([]const u8).init(allocator); + var argv = std.array_list.Managed([]const u8).init(arena); var sysroot: ?[]const u8 = null; var args_iter = ArgsIterator{ .args = args[1..] }; @@ -86,23 +79,19 @@ pub fn main() anyerror!void { } else try argv.append(arg); } - var threaded: Io.Threaded = .init(gpa); - defer threaded.deinit(); - const io = threaded.io(); - const sysroot_path = sysroot orelse blk: { const target = try std.zig.system.resolveTargetQuery(io, .{}); - break :blk std.zig.system.darwin.getSdk(allocator, &target) orelse + break :blk std.zig.system.darwin.getSdk(arena, io, &target) orelse fatal("no SDK found; you can provide one explicitly with '--sysroot' flag", .{}); }; - var sdk_dir = try std.fs.cwd().openDir(sysroot_path, .{}); - defer sdk_dir.close(); - const sdk_info = try sdk_dir.readFileAlloc("SDKSettings.json", allocator, .limited(std.math.maxInt(u32))); + var sdk_dir = try Dir.cwd().openDir(io, sysroot_path, .{}); + defer sdk_dir.close(io); + const sdk_info = try sdk_dir.readFileAlloc(io, "SDKSettings.json", arena, .limited(std.math.maxInt(u32))); const parsed_json = try std.json.parseFromSlice(struct { DefaultProperties: struct { MACOSX_DEPLOYMENT_TARGET: []const u8 }, - }, allocator, sdk_info, .{ .ignore_unknown_fields = true }); + }, arena, sdk_info, .{ .ignore_unknown_fields = true }); const version = Version.parse(parsed_json.value.DefaultProperties.MACOSX_DEPLOYMENT_TARGET) orelse fatal("don't know how to parse SDK version: {s}", .{ @@ -111,15 +100,14 @@ pub fn main() anyerror!void { const os_ver: OsVer = @enumFromInt(version.major); info("found SDK deployment target macOS {f} aka '{t}'", .{ version, os_ver }); - var tmp = tmpDir(.{}); - defer tmp.cleanup(); + const tmp_dir: Io.Dir = .cwd(); for (&[_]Arch{ .aarch64, .x86_64 }) |arch| { const target: Target = .{ .arch = arch, .os_ver = os_ver, }; - try fetchTarget(allocator, io, argv.items, sysroot_path, target, version, tmp); + try fetchTarget(arena, io, argv.items, sysroot_path, target, version, tmp_dir); } } @@ -130,13 +118,13 @@ fn fetchTarget( sysroot: []const u8, target: Target, ver: Version, - tmp: std.testing.TmpDir, + tmp_dir: Io.Dir, ) !void { const tmp_filename = "macos-headers"; const headers_list_filename = "macos-headers.o.d"; - const tmp_path = try tmp.dir.realpathAlloc(arena, "."); - const tmp_file_path = try fs.path.join(arena, &[_][]const u8{ tmp_path, tmp_filename }); - const headers_list_path = try fs.path.join(arena, &[_][]const u8{ tmp_path, headers_list_filename }); + const tmp_path = try tmp_dir.realPathFileAlloc(io, ".", arena); + const tmp_file_path = try Dir.path.join(arena, &[_][]const u8{ tmp_path, tmp_filename }); + const headers_list_path = try Dir.path.join(arena, &[_][]const u8{ tmp_path, headers_list_filename }); const macos_version = try std.fmt.allocPrint(arena, "-mmacosx-version-min={d}.{d}", .{ ver.major, @@ -166,20 +154,17 @@ fn fetchTarget( }); try cc_argv.appendSlice(args); - const res = try std.process.Child.run(.{ - .allocator = arena, - .argv = cc_argv.items, - }); + const res = try std.process.run(arena, io, .{ .argv = cc_argv.items }); if (res.stderr.len != 0) { std.log.err("{s}", .{res.stderr}); } // Read in the contents of `macos-headers.o.d` - const headers_list_file = try tmp.dir.openFile(headers_list_filename, .{}); - defer headers_list_file.close(); + const headers_list_file = try tmp_dir.openFile(io, headers_list_filename, .{}); + defer headers_list_file.close(io); - var headers_dir = fs.cwd().openDir(headers_source_prefix, .{}) catch |err| switch (err) { + var headers_dir = Dir.cwd().openDir(io, headers_source_prefix, .{}) catch |err| switch (err) { error.FileNotFound, error.NotDir, => fatal("path '{s}' not found or not a directory. Did you accidentally delete it?", .{ @@ -187,13 +172,13 @@ fn fetchTarget( }), else => return err, }; - defer headers_dir.close(); + defer headers_dir.close(io); const dest_path = try target.fullName(arena); - try headers_dir.deleteTree(dest_path); + try headers_dir.deleteTree(io, dest_path); - var dest_dir = try headers_dir.makeOpenPath(dest_path, .{}); - var dirs = std.StringHashMap(fs.Dir).init(arena); + var dest_dir = try headers_dir.createDirPathOpen(io, dest_path, .{}); + var dirs = std.StringHashMap(Dir).init(arena); try dirs.putNoClobber(".", dest_dir); var headers_list_file_reader = headers_list_file.reader(io, &.{}); @@ -206,25 +191,25 @@ fn fetchTarget( if (mem.lastIndexOf(u8, line, prefix[0..])) |idx| { const out_rel_path = line[idx + prefix.len + 1 ..]; const out_rel_path_stripped = mem.trim(u8, out_rel_path, " \\"); - const dirname = fs.path.dirname(out_rel_path_stripped) orelse "."; + const dirname = Dir.path.dirname(out_rel_path_stripped) orelse "."; const maybe_dir = try dirs.getOrPut(dirname); if (!maybe_dir.found_existing) { - maybe_dir.value_ptr.* = try dest_dir.makeOpenPath(dirname, .{}); + maybe_dir.value_ptr.* = try dest_dir.createDirPathOpen(io, dirname, .{}); } - const basename = fs.path.basename(out_rel_path_stripped); + const basename = Dir.path.basename(out_rel_path_stripped); const line_stripped = mem.trim(u8, line, " \\"); - const abs_dirname = fs.path.dirname(line_stripped).?; - var orig_subdir = try fs.cwd().openDir(abs_dirname, .{}); - defer orig_subdir.close(); + const abs_dirname = Dir.path.dirname(line_stripped).?; + var orig_subdir = try Dir.cwd().openDir(io, abs_dirname, .{}); + defer orig_subdir.close(io); - try orig_subdir.copyFile(basename, maybe_dir.value_ptr.*, basename, .{}); + try orig_subdir.copyFile(basename, maybe_dir.value_ptr.*, basename, io, .{}); } } var dir_it = dirs.iterator(); while (dir_it.next()) |entry| { - entry.value_ptr.close(); + entry.value_ptr.close(io); } } diff --git a/tools/gen_macos_headers_c.zig b/tools/gen_macos_headers_c.zig index fe036cf6b7e3..3e83761923e5 100644 --- a/tools/gen_macos_headers_c.zig +++ b/tools/gen_macos_headers_c.zig @@ -1,13 +1,11 @@ const std = @import("std"); +const Io = std.Io; +const Dir = std.Io.Dir; const assert = std.debug.assert; const info = std.log.info; const fatal = std.process.fatal; - const Allocator = std.mem.Allocator; -var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){}; -const gpa = general_purpose_allocator.allocator(); - const usage = \\gen_macos_headers_c [dir] \\ @@ -15,12 +13,11 @@ const usage = \\-h, --help Print this help and exit ; -pub fn main() anyerror!void { - var arena_allocator = std.heap.ArenaAllocator.init(gpa); - defer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const io = init.io; + const args = try init.minimal.args.toSlice(arena); - const args = try std.process.argsAlloc(arena); if (args.len == 1) fatal("no command or option specified", .{}); var positionals = std.array_list.Managed([]const u8).init(arena); @@ -33,10 +30,10 @@ pub fn main() anyerror!void { if (positionals.items.len != 1) fatal("expected one positional argument: [dir]", .{}); - var dir = try std.fs.cwd().openDir(positionals.items[0], .{ .follow_symlinks = false }); - defer dir.close(); + var dir = try Io.Dir.cwd().openDir(io, positionals.items[0], .{ .follow_symlinks = false }); + defer dir.close(io); var paths = std.array_list.Managed([]const u8).init(arena); - try findHeaders(arena, dir, "", &paths); + try findHeaders(arena, io, dir, "", &paths); const SortFn = struct { pub fn lessThan(ctx: void, lhs: []const u8, rhs: []const u8) bool { @@ -48,7 +45,7 @@ pub fn main() anyerror!void { std.mem.sort([]const u8, paths.items, {}, SortFn.lessThan); var buffer: [2000]u8 = undefined; - var stdout_writer = std.fs.File.stdout().writerStreaming(&buffer); + var stdout_writer = Io.File.stdout().writerStreaming(io, &buffer); const w = &stdout_writer.interface; try w.writeAll("#define _XOPEN_SOURCE\n"); for (paths.items) |path| { @@ -64,23 +61,24 @@ pub fn main() anyerror!void { fn findHeaders( arena: Allocator, - dir: std.fs.Dir, + io: Io, + dir: Dir, prefix: []const u8, paths: *std.array_list.Managed([]const u8), ) anyerror!void { var it = dir.iterate(); - while (try it.next()) |entry| { + while (try it.next(io)) |entry| { switch (entry.kind) { .directory => { - const path = try std.fs.path.join(arena, &.{ prefix, entry.name }); - var subdir = try dir.openDir(entry.name, .{ .follow_symlinks = false }); - defer subdir.close(); - try findHeaders(arena, subdir, path, paths); + const path = try Io.Dir.path.join(arena, &.{ prefix, entry.name }); + var subdir = try dir.openDir(io, entry.name, .{ .follow_symlinks = false }); + defer subdir.close(io); + try findHeaders(arena, io, subdir, path, paths); }, .file, .sym_link => { - const ext = std.fs.path.extension(entry.name); + const ext = Io.Dir.path.extension(entry.name); if (!std.mem.eql(u8, ext, ".h")) continue; - const path = try std.fs.path.join(arena, &.{ prefix, entry.name }); + const path = try Io.Dir.path.join(arena, &.{ prefix, entry.name }); try paths.append(path); }, else => {}, diff --git a/tools/gen_outline_atomics.zig b/tools/gen_outline_atomics.zig index 1dade6661019..bd36484e1e9b 100644 --- a/tools/gen_outline_atomics.zig +++ b/tools/gen_outline_atomics.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const Allocator = std.mem.Allocator; const AtomicOp = enum { @@ -10,15 +11,14 @@ const AtomicOp = enum { ldset, }; -pub fn main() !void { - var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena_instance.deinit(); - const arena = arena_instance.allocator(); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const io = init.io; //const args = try std.process.argsAlloc(arena); var stdout_buffer: [2000]u8 = undefined; - var stdout_writer = std.fs.File.stdout().writerStreaming(&stdout_buffer); + var stdout_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer); const w = &stdout_writer.interface; try w.writeAll( diff --git a/tools/gen_spirv_spec.zig b/tools/gen_spirv_spec.zig index c211d1022ea8..f53b10cbb1bf 100644 --- a/tools/gen_spirv_spec.zig +++ b/tools/gen_spirv_spec.zig @@ -1,5 +1,8 @@ const std = @import("std"); +const Io = std.Io; const Allocator = std.mem.Allocator; +const assert = std.debug.assert; + const g = @import("spirv/grammar.zig"); const CoreRegistry = g.CoreRegistry; const ExtensionRegistry = g.ExtensionRegistry; @@ -52,73 +55,71 @@ const set_names = std.StaticStringMap(struct { []const u8, []const u8 }).initCom .{ "zig", .{ "zig", "Zig" } }, }); -var arena = std.heap.ArenaAllocator.init(std.heap.smp_allocator); -const allocator = arena.allocator(); - -pub fn main() !void { - defer arena.deinit(); - - const args = try std.process.argsAlloc(allocator); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const args = try init.minimal.args.toSlice(arena); if (args.len != 3) { usageAndExit(args[0], 1); } - const json_path = try std.fs.path.join(allocator, &.{ args[1], "include/spirv/unified1/" }); - const dir = try std.fs.cwd().openDir(json_path, .{ .iterate = true }); + const io = init.io; + + const json_path = try Io.Dir.path.join(arena, &.{ args[1], "include/spirv/unified1/" }); + const dir = try Io.Dir.cwd().openDir(io, json_path, .{ .iterate = true }); - const core_spec = try readRegistry(CoreRegistry, dir, "spirv.core.grammar.json"); + const core_spec = try readRegistry(io, arena, CoreRegistry, dir, "spirv.core.grammar.json"); std.mem.sortUnstable(Instruction, core_spec.instructions, CmpInst{}, CmpInst.lt); - var exts = std.array_list.Managed(Extension).init(allocator); + var exts = std.array_list.Managed(Extension).init(arena); var it = dir.iterate(); - while (try it.next()) |entry| { + while (try it.next(io)) |entry| { if (entry.kind != .file) { continue; } - try readExtRegistry(&exts, dir, entry.name); + try readExtRegistry(io, arena, &exts, dir, entry.name); } - try readExtRegistry(&exts, std.fs.cwd(), args[2]); + try readExtRegistry(io, arena, &exts, Io.Dir.cwd(), args[2]); - var allocating: std.Io.Writer.Allocating = .init(allocator); + var allocating: std.Io.Writer.Allocating = .init(arena); defer allocating.deinit(); - try render(&allocating.writer, core_spec, exts.items); + try render(arena, &allocating.writer, core_spec, exts.items); try allocating.writer.writeByte(0); const output = allocating.written()[0 .. allocating.written().len - 1 :0]; - var tree = try std.zig.Ast.parse(allocator, output, .zig); + var tree = try std.zig.Ast.parse(arena, output, .zig); if (tree.errors.len != 0) { - try std.zig.printAstErrorsToStderr(allocator, tree, "", .auto); + try std.zig.printAstErrorsToStderr(arena, io, tree, "", .auto); return; } - var zir = try std.zig.AstGen.generate(allocator, tree); + var zir = try std.zig.AstGen.generate(arena, tree); if (zir.hasCompileErrors()) { var wip_errors: std.zig.ErrorBundle.Wip = undefined; - try wip_errors.init(allocator); + try wip_errors.init(arena); defer wip_errors.deinit(); try wip_errors.addZirErrorMessages(zir, tree, output, ""); var error_bundle = try wip_errors.toOwnedBundle(""); - defer error_bundle.deinit(allocator); - error_bundle.renderToStdErr(.{}, .auto); + defer error_bundle.deinit(arena); + try error_bundle.renderToStderr(io, .{}, .auto); } - const formatted_output = try tree.renderAlloc(allocator); - _ = try std.fs.File.stdout().write(formatted_output); + const formatted_output = try tree.renderAlloc(arena); + try Io.File.stdout().writeStreamingAll(io, formatted_output); } -fn readExtRegistry(exts: *std.array_list.Managed(Extension), dir: std.fs.Dir, sub_path: []const u8) !void { - const filename = std.fs.path.basename(sub_path); +fn readExtRegistry(io: Io, arena: Allocator, exts: *std.array_list.Managed(Extension), dir: Io.Dir, sub_path: []const u8) !void { + const filename = Io.Dir.path.basename(sub_path); if (!std.mem.startsWith(u8, filename, "extinst.")) { return; } - std.debug.assert(std.mem.endsWith(u8, filename, ".grammar.json")); + assert(std.mem.endsWith(u8, filename, ".grammar.json")); const name = filename["extinst.".len .. filename.len - ".grammar.json".len]; - const spec = try readRegistry(ExtensionRegistry, dir, sub_path); + const spec = try readRegistry(io, arena, ExtensionRegistry, dir, sub_path); const set_name = set_names.get(name) orelse { std.log.info("ignored instruction set '{s}'", .{name}); @@ -134,16 +135,16 @@ fn readExtRegistry(exts: *std.array_list.Managed(Extension), dir: std.fs.Dir, su }); } -fn readRegistry(comptime RegistryType: type, dir: std.fs.Dir, path: []const u8) !RegistryType { - const spec = try dir.readFileAlloc(path, allocator, .unlimited); +fn readRegistry(io: Io, arena: Allocator, comptime RegistryType: type, dir: Io.Dir, path: []const u8) !RegistryType { + const spec = try dir.readFileAlloc(io, path, arena, .unlimited); // Required for json parsing. // TODO: ALI @setEvalBranchQuota(10000); - var scanner = std.json.Scanner.initCompleteInput(allocator, spec); + var scanner = std.json.Scanner.initCompleteInput(arena, spec); var diagnostics = std.json.Diagnostics{}; scanner.enableDiagnostics(&diagnostics); - const parsed = std.json.parseFromTokenSource(RegistryType, allocator, &scanner, .{}) catch |err| { + const parsed = std.json.parseFromTokenSource(RegistryType, arena, &scanner, .{}) catch |err| { std.debug.print("{s}:{}:{}:\n", .{ path, diagnostics.getLine(), diagnostics.getColumn() }); return err; }; @@ -152,8 +153,8 @@ fn readRegistry(comptime RegistryType: type, dir: std.fs.Dir, path: []const u8) /// Returns a set with types that require an extra struct for the `Instruction` interface /// to the spir-v spec, or whether the original type can be used. -fn extendedStructs(kinds: []const OperandKind) !ExtendedStructSet { - var map = ExtendedStructSet.init(allocator); +fn extendedStructs(arena: Allocator, kinds: []const OperandKind) !ExtendedStructSet { + var map = ExtendedStructSet.init(arena); try map.ensureTotalCapacity(@as(u32, @intCast(kinds.len))); for (kinds) |kind| { @@ -188,6 +189,7 @@ fn tagPriorityScore(tag: []const u8) usize { } fn render( + arena: Allocator, writer: *std.Io.Writer, registry: CoreRegistry, extensions: []const Extension, @@ -293,7 +295,7 @@ fn render( ); // Merge the operand kinds from all extensions together. - var all_operand_kinds = OperandKindMap.init(allocator); + var all_operand_kinds = OperandKindMap.init(arena); for (registry.operand_kinds) |kind| { try all_operand_kinds.putNoClobber(.{ "core", kind.kind }, kind); } @@ -306,22 +308,22 @@ fn render( try all_operand_kinds.ensureUnusedCapacity(ext.spec.operand_kinds.len); for (ext.spec.operand_kinds) |kind| { var new_kind = kind; - new_kind.kind = try std.mem.join(allocator, ".", &.{ ext.name, kind.kind }); + new_kind.kind = try std.mem.join(arena, ".", &.{ ext.name, kind.kind }); try all_operand_kinds.putNoClobber(.{ ext.name, kind.kind }, new_kind); } } - const extended_structs = try extendedStructs(all_operand_kinds.values()); + const extended_structs = try extendedStructs(arena, all_operand_kinds.values()); // Note: extensions don't seem to have class. - try renderClass(writer, registry.instructions); + try renderClass(arena, writer, registry.instructions); try renderOperandKind(writer, all_operand_kinds.values()); - try renderOpcodes(writer, "Opcode", true, registry.instructions, extended_structs); + try renderOpcodes(arena, writer, "Opcode", true, registry.instructions, extended_structs); for (extensions) |ext| { - try renderOpcodes(writer, ext.opcode_name, false, ext.spec.instructions, extended_structs); + try renderOpcodes(arena, writer, ext.opcode_name, false, ext.spec.instructions, extended_structs); } - try renderOperandKinds(writer, all_operand_kinds.values(), extended_structs); + try renderOperandKinds(arena, writer, all_operand_kinds.values(), extended_structs); try renderInstructionSet(writer, registry, extensions, all_operand_kinds); } @@ -408,8 +410,8 @@ fn renderInstructionsCase( ); } -fn renderClass(writer: *std.Io.Writer, instructions: []const Instruction) !void { - var class_map = std.StringArrayHashMap(void).init(allocator); +fn renderClass(arena: Allocator, writer: *std.Io.Writer, instructions: []const Instruction) !void { + var class_map = std.StringArrayHashMap(void).init(arena); for (instructions) |inst| { if (std.mem.eql(u8, inst.class.?, "@exclude")) continue; @@ -529,16 +531,17 @@ fn renderEnumerant(writer: *std.Io.Writer, enumerant: Enumerant) !void { } fn renderOpcodes( + arena: Allocator, writer: *std.Io.Writer, opcode_type_name: []const u8, want_operands: bool, instructions: []const Instruction, extended_structs: ExtendedStructSet, ) !void { - var inst_map = std.AutoArrayHashMap(u32, usize).init(allocator); + var inst_map = std.AutoArrayHashMap(u32, usize).init(arena); try inst_map.ensureTotalCapacity(instructions.len); - var aliases = std.array_list.Managed(struct { inst: usize, alias: usize }).init(allocator); + var aliases = std.array_list.Managed(struct { inst: usize, alias: usize }).init(arena); try aliases.ensureTotalCapacity(instructions.len); for (instructions, 0..) |inst, i| { @@ -628,30 +631,32 @@ fn renderOpcodes( } fn renderOperandKinds( + arena: Allocator, writer: *std.Io.Writer, kinds: []const OperandKind, extended_structs: ExtendedStructSet, ) !void { for (kinds) |kind| { switch (kind.category) { - .ValueEnum => try renderValueEnum(writer, kind, extended_structs), - .BitEnum => try renderBitEnum(writer, kind, extended_structs), + .ValueEnum => try renderValueEnum(arena, writer, kind, extended_structs), + .BitEnum => try renderBitEnum(arena, writer, kind, extended_structs), else => {}, } } } fn renderValueEnum( + arena: Allocator, writer: *std.Io.Writer, enumeration: OperandKind, extended_structs: ExtendedStructSet, ) !void { const enumerants = enumeration.enumerants orelse return error.InvalidRegistry; - var enum_map = std.AutoArrayHashMap(u32, usize).init(allocator); + var enum_map = std.AutoArrayHashMap(u32, usize).init(arena); try enum_map.ensureTotalCapacity(enumerants.len); - var aliases = std.array_list.Managed(struct { enumerant: usize, alias: usize }).init(allocator); + var aliases = std.array_list.Managed(struct { enumerant: usize, alias: usize }).init(arena); try aliases.ensureTotalCapacity(enumerants.len); for (enumerants, 0..) |enumerant, i| { @@ -720,6 +725,7 @@ fn renderValueEnum( } fn renderBitEnum( + arena: Allocator, writer: *std.Io.Writer, enumeration: OperandKind, extended_structs: ExtendedStructSet, @@ -729,7 +735,7 @@ fn renderBitEnum( var flags_by_bitpos = [_]?usize{null} ** 32; const enumerants = enumeration.enumerants orelse return error.InvalidRegistry; - var aliases = std.array_list.Managed(struct { flag: usize, alias: u5 }).init(allocator); + var aliases = std.array_list.Managed(struct { flag: usize, alias: u5 }).init(arena); try aliases.ensureTotalCapacity(enumerants.len); for (enumerants, 0..) |enumerant, i| { @@ -743,7 +749,7 @@ fn renderBitEnum( continue; } - std.debug.assert(@popCount(value) == 1); + assert(@popCount(value) == 1); const bitpos = std.math.log2_int(u32, value); if (flags_by_bitpos[bitpos]) |*existing| { @@ -930,8 +936,9 @@ fn parseHexInt(text: []const u8) !u31 { } fn usageAndExit(arg0: []const u8, code: u8) noreturn { - const stderr, _ = std.debug.lockStderrWriter(&.{}); - stderr.print( + const stderr = std.debug.lockStderr(&.{}); + const w = &stderr.file_writer.interface; + w.print( \\Usage: {s} \\ \\Generates Zig bindings for SPIR-V specifications found in the SPIRV-Headers diff --git a/tools/gen_stubs.zig b/tools/gen_stubs.zig index 51f66d308027..bad27fd2015c 100644 --- a/tools/gen_stubs.zig +++ b/tools/gen_stubs.zig @@ -55,12 +55,14 @@ // - e.g. find a common previous symbol and put it after that one // - they definitely need to go into the correct section +const builtin = @import("builtin"); +const native_endian = builtin.cpu.arch.endian(); + const std = @import("std"); -const builtin = std.builtin; +const Io = std.Io; const mem = std.mem; const log = std.log; const elf = std.elf; -const native_endian = @import("builtin").cpu.arch.endian(); const Arch = enum { aarch64, @@ -279,15 +281,13 @@ const Parse = struct { arch: Arch, }; -pub fn main() !void { - var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena_instance.deinit(); - const arena = arena_instance.allocator(); - - const args = try std.process.argsAlloc(arena); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const io = init.io; + const args = try init.minimal.args.toSlice(arena); const build_all_path = args[1]; - var build_all_dir = try std.fs.cwd().openDir(build_all_path, .{}); + var build_all_dir = try Io.Dir.cwd().openDir(io, build_all_path, .{}); var sym_table = std.StringArrayHashMap(MultiSym).init(arena); var sections = std.StringArrayHashMap(void).init(arena); @@ -299,6 +299,7 @@ pub fn main() !void { // Read the ELF header. const elf_bytes = build_all_dir.readFileAllocOptions( + io, libc_so_path, arena, .limited(100 * 1024 * 1024), @@ -334,7 +335,7 @@ pub fn main() !void { } var stdout_buffer: [2000]u8 = undefined; - var stdout_writer = std.fs.File.stdout().writerStreaming(&stdout_buffer); + var stdout_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer); const stdout = &stdout_writer.interface; try stdout.writeAll( \\#ifdef PTR64 @@ -539,7 +540,7 @@ pub fn main() !void { try stdout.flush(); } -fn parseElf(parse: Parse, comptime is_64: bool, comptime endian: builtin.Endian) !void { +fn parseElf(parse: Parse, comptime is_64: bool, comptime endian: std.builtin.Endian) !void { const arena = parse.arena; const elf_bytes = parse.elf_bytes; const header = parse.header; diff --git a/tools/generate_JSONTestSuite.zig b/tools/generate_JSONTestSuite.zig index 2c6fee5bdd5e..d1bdd2e5cee2 100644 --- a/tools/generate_JSONTestSuite.zig +++ b/tools/generate_JSONTestSuite.zig @@ -1,13 +1,14 @@ // zig run this file inside the test_parsing/ directory of this repo: https://github.com/nst/JSONTestSuite const std = @import("std"); +const Io = std.Io; -pub fn main() !void { - var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; - var allocator = gpa.allocator(); +pub fn main(init: std.process.Init) !void { + const allocator = init.gpa; + const io = init.io; var stdout_buffer: [2000]u8 = undefined; - var stdout_writer = std.fs.File.stdout().writerStreaming(&stdout_buffer); + var stdout_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer); const output = &stdout_writer.interface; try output.writeAll( \\// This file was generated by _generate_JSONTestSuite.zig @@ -20,9 +21,9 @@ pub fn main() !void { ); var names = std.array_list.Managed([]const u8).init(allocator); - var cwd = try std.fs.cwd().openDir(".", .{ .iterate = true }); + var cwd = try Io.Dir.cwd().openDir(io, ".", .{ .iterate = true }); var it = cwd.iterate(); - while (try it.next()) |entry| { + while (try it.next(io)) |entry| { try names.append(try allocator.dupe(u8, entry.name)); } std.mem.sort([]const u8, names.items, {}, (struct { @@ -32,7 +33,7 @@ pub fn main() !void { }).lessThan); for (names.items) |name| { - const contents = try std.fs.cwd().readFileAlloc(name, allocator, .limited(250001)); + const contents = try Io.Dir.cwd().readFileAlloc(io, name, allocator, .limited(250001)); try output.writeAll("test "); try writeString(output, name); try output.writeAll(" {\n try "); diff --git a/tools/generate_c_size_and_align_checks.zig b/tools/generate_c_size_and_align_checks.zig index 3663756533ef..6041a550da6f 100644 --- a/tools/generate_c_size_and_align_checks.zig +++ b/tools/generate_c_size_and_align_checks.zig @@ -7,6 +7,7 @@ //! target. const std = @import("std"); +const Io = std.Io; fn cName(ty: std.Target.CType) []const u8 { return switch (ty) { @@ -27,27 +28,20 @@ fn cName(ty: std.Target.CType) []const u8 { var general_purpose_allocator: std.heap.GeneralPurposeAllocator(.{}) = .init; -pub fn main() !void { - const gpa = general_purpose_allocator.allocator(); - defer std.debug.assert(general_purpose_allocator.deinit() == .ok); - - const args = try std.process.argsAlloc(gpa); - defer std.process.argsFree(gpa, args); +pub fn main(init: std.process.Init) !void { + const args = try init.minimal.args.toSlice(init.arena.allocator()); + const io = init.io; if (args.len != 2) { std.debug.print("Usage: {s} [target_triple]\n", .{args[0]}); std.process.exit(1); } - var threaded: std.Io.Threaded = .init(gpa); - defer threaded.deinit(); - const io = threaded.io(); - const query = try std.Target.Query.parse(.{ .arch_os_abi = args[1] }); const target = try std.zig.system.resolveTargetQuery(io, query); var buffer: [2000]u8 = undefined; - var stdout_writer = std.fs.File.stdout().writerStreaming(&buffer); + var stdout_writer = Io.File.stdout().writerStreaming(io, &buffer); const w = &stdout_writer.interface; inline for (@typeInfo(std.Target.CType).@"enum".fields) |field| { const c_type: std.Target.CType = @enumFromInt(field.value); diff --git a/tools/generate_linux_syscalls.zig b/tools/generate_linux_syscalls.zig index e009715e2f65..70d410f806b3 100644 --- a/tools/generate_linux_syscalls.zig +++ b/tools/generate_linux_syscalls.zig @@ -170,26 +170,25 @@ const architectures: []const Arch = &.{ // .{ .@"var" = "Microblaze", .table = .{ .specific = "arch/microblaze/kernel/syscalls/syscall.tbl" } }, }; -pub fn main() !void { - var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena.deinit(); - const gpa = arena.allocator(); +pub fn main(init: std.process.Init) !void { + const gpa = init.gpa; + const io = init.io; - const args = try std.process.argsAlloc(gpa); + const args = try init.minimal.args.toSlice(init.arena.allocator()); if (args.len < 2 or mem.eql(u8, args[1], "--help")) { - const w, _ = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); + const stderr = std.debug.lockStderr(&.{}); + const w = &stderr.file_writer.interface; usage(w, args[0]) catch std.process.exit(2); std.process.exit(1); } const linux_path = args[1]; var stdout_buffer: [2048]u8 = undefined; - var stdout_writer = std.fs.File.stdout().writerStreaming(&stdout_buffer); + var stdout_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer); const stdout = &stdout_writer.interface; - var linux_dir = try std.fs.cwd().openDir(linux_path, .{}); - defer linux_dir.close(); + var linux_dir = try Io.Dir.cwd().openDir(io, linux_path, .{}); + defer linux_dir.close(io); // As of 6.11, the largest table is 24195 bytes. // 32k should be enough for now. @@ -198,7 +197,7 @@ pub fn main() !void { // Fetch the kernel version from the Makefile variables. const version = blk: { - const head = try linux_dir.readFile("Makefile", buf[0..128]); + const head = try linux_dir.readFile(io, "Makefile", buf[0..128]); var lines = mem.tokenizeScalar(u8, head, '\n'); _ = lines.next(); // Skip SPDX identifier @@ -213,15 +212,14 @@ pub fn main() !void { }; try Io.Writer.print(stdout, - \\// This file is automatically generated, DO NOT edit it manually. - \\// See tools/generate_linux_syscalls.zig for more info. + \\// This file is automatically generated by tools/generate_linux_syscalls.zig \\// This list current as of kernel: {f} \\ \\ , .{version}); for (architectures, 0..) |arch, i| { - const table = try linux_dir.readFile(switch (arch.table) { + const table = try linux_dir.readFile(io, switch (arch.table) { .generic => "scripts/syscall.tbl", .specific => |f| f, }, buf); diff --git a/tools/incr-check.zig b/tools/incr-check.zig index 5023fb85dd74..daf93be73f8e 100644 --- a/tools/incr-check.zig +++ b/tools/incr-check.zig @@ -1,48 +1,74 @@ const std = @import("std"); const Io = std.Io; +const Dir = std.Io.Dir; const Allocator = std.mem.Allocator; const Cache = std.Build.Cache; -const usage = "usage: incr-check [--zig-lib-dir lib] [--debug-zcu] [--debug-dwarf] [--debug-link] [--preserve-tmp] [--zig-cc-binary /path/to/zig]"; +const usage = "usage: incr-check [--zig-lib-dir lib] [--debug-log foo] [--preserve-tmp] [--zig-cc-binary /path/to/zig]"; -pub fn main() !void { - const fatal = std.process.fatal; - - var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena_instance.deinit(); - const arena = arena_instance.allocator(); - - const gpa = arena; +pub const std_options: std.Options = .{ + .logFn = logImpl, +}; +var log_cur_update: ?struct { *const Case.Target, *const Case.Update } = null; +fn logImpl( + comptime level: std.log.Level, + comptime scope: @EnumLiteral(), + comptime format: []const u8, + args: anytype, +) void { + const target, const update = log_cur_update orelse { + return std.log.defaultLog(level, scope, format, args); + }; + std.log.defaultLog( + level, + scope, + "[{s}-{t} '{s}'] " ++ format, + .{ target.query, target.backend, update.name } ++ args, + ); +} - var threaded: Io.Threaded = .init(gpa); - defer threaded.deinit(); - const io = threaded.io(); +pub fn main(init: std.process.Init) !void { + const fatal = std.process.fatal; + const arena = init.arena.allocator(); + const io = init.io; + const environ_map = init.environ_map; + const cwd_path = try std.process.getCwdAlloc(arena); var opt_zig_exe: ?[]const u8 = null; var opt_input_file_name: ?[]const u8 = null; var opt_lib_dir: ?[]const u8 = null; var opt_cc_zig: ?[]const u8 = null; - var debug_zcu = false; - var debug_dwarf = false; - var debug_link = false; var preserve_tmp = false; + var enable_qemu: bool = false; + var enable_wine: bool = false; + var enable_wasmtime: bool = false; + var enable_darling: bool = false; - var arg_it = try std.process.argsWithAllocator(arena); + var debug_log_args: std.ArrayList([]const u8) = .empty; + + var arg_it = try init.minimal.args.iterateAllocator(arena); _ = arg_it.skip(); while (arg_it.next()) |arg| { if (arg.len > 0 and arg[0] == '-') { if (std.mem.eql(u8, arg, "--zig-lib-dir")) { - opt_lib_dir = arg_it.next() orelse fatal("expected arg after '--zig-lib-dir'\n{s}", .{usage}); - } else if (std.mem.eql(u8, arg, "--debug-zcu")) { - debug_zcu = true; - } else if (std.mem.eql(u8, arg, "--debug-dwarf")) { - debug_dwarf = true; - } else if (std.mem.eql(u8, arg, "--debug-link")) { - debug_link = true; + opt_lib_dir = arg_it.next() orelse fatal("expected arg after --zig-lib-dir\n{s}", .{usage}); + } else if (std.mem.eql(u8, arg, "--debug-log")) { + try debug_log_args.append( + arena, + arg_it.next() orelse fatal("expected arg after --debug-log\n{s}", .{usage}), + ); } else if (std.mem.eql(u8, arg, "--preserve-tmp")) { preserve_tmp = true; + } else if (std.mem.eql(u8, arg, "-fqemu")) { + enable_qemu = true; + } else if (std.mem.eql(u8, arg, "-fwine")) { + enable_wine = true; + } else if (std.mem.eql(u8, arg, "-fwasmtime")) { + enable_wasmtime = true; + } else if (std.mem.eql(u8, arg, "-fdarling")) { + enable_darling = true; } else if (std.mem.eql(u8, arg, "--zig-cc-binary")) { - opt_cc_zig = arg_it.next() orelse fatal("expect arg after '--zig-cc-binary'\n{s}", .{usage}); + opt_cc_zig = arg_it.next() orelse fatal("expected arg after --zig-cc-binary\n{s}", .{usage}); } else { fatal("unknown option '{s}'\n{s}", .{ arg, usage }); } @@ -59,7 +85,7 @@ pub fn main() !void { const zig_exe = opt_zig_exe orelse fatal("missing path to zig\n{s}", .{usage}); const input_file_name = opt_input_file_name orelse fatal("missing input file\n{s}", .{usage}); - const input_file_bytes = try std.fs.cwd().readFileAlloc(input_file_name, arena, .limited(std.math.maxInt(u32))); + const input_file_bytes = try Dir.cwd().readFileAlloc(io, input_file_name, arena, .limited(std.math.maxInt(u32))); const case = try Case.parse(arena, io, input_file_bytes); // Check now: if there are any targets using the `cbe` backend, we need the lib dir. @@ -71,31 +97,31 @@ pub fn main() !void { } } - const prog_node = std.Progress.start(.{}); + const prog_node = std.Progress.start(io, .{}); defer prog_node.end(); - const rand_int = std.crypto.random.int(u64); + const rand_int = rand64(io); const tmp_dir_path = "tmp_" ++ std.fmt.hex(rand_int); - var tmp_dir = try std.fs.cwd().makeOpenPath(tmp_dir_path, .{}); + var tmp_dir = try Dir.cwd().createDirPathOpen(io, tmp_dir_path, .{}); defer { - tmp_dir.close(); + tmp_dir.close(io); if (!preserve_tmp) { - std.fs.cwd().deleteTree(tmp_dir_path) catch |err| { - std.log.warn("failed to delete tree '{s}': {s}", .{ tmp_dir_path, @errorName(err) }); + Dir.cwd().deleteTree(io, tmp_dir_path) catch |err| { + std.log.warn("failed to delete tree '{s}': {t}", .{ tmp_dir_path, err }); }; } } // Convert paths to be relative to the cwd of the subprocess. - const resolved_zig_exe = try std.fs.path.relative(arena, tmp_dir_path, zig_exe); + const resolved_zig_exe = try Dir.path.relative(arena, cwd_path, environ_map, tmp_dir_path, zig_exe); const opt_resolved_lib_dir = if (opt_lib_dir) |lib_dir| - try std.fs.path.relative(arena, tmp_dir_path, lib_dir) + try Dir.path.relative(arena, cwd_path, environ_map, tmp_dir_path, lib_dir) else null; const host = try std.zig.system.resolveTargetQuery(io, .{}); - const debug_log_verbose = debug_zcu or debug_dwarf or debug_link; + const debug_log_verbose = debug_log_args.items.len != 0; for (case.targets) |target| { const target_prog_node = node: { @@ -133,14 +159,8 @@ pub fn main() !void { .llvm => try child_args.appendSlice(arena, &.{ "-fllvm", "-flld" }), .cbe => try child_args.appendSlice(arena, &.{ "-ofmt=c", "-lc" }), } - if (debug_zcu) { - try child_args.appendSlice(arena, &.{ "--debug-log", "zcu" }); - } - if (debug_dwarf) { - try child_args.appendSlice(arena, &.{ "--debug-log", "dwarf" }); - } - if (debug_link) { - try child_args.appendSlice(arena, &.{ "--debug-log", "link", "--debug-log", "link_state", "--debug-log", "link_relocs" }); + for (debug_log_args.items) |arg| { + try child_args.appendSlice(arena, &.{ "--debug-log", arg }); } for (case.modules) |mod| { try child_args.appendSlice(arena, &.{ "--dep", mod.name }); @@ -153,18 +173,10 @@ pub fn main() !void { const zig_prog_node = target_prog_node.start("zig build-exe", 0); defer zig_prog_node.end(); - var child = std.process.Child.init(child_args.items, arena); - child.stdin_behavior = .Pipe; - child.stdout_behavior = .Pipe; - child.stderr_behavior = .Pipe; - child.progress_node = zig_prog_node; - child.cwd_dir = tmp_dir; - child.cwd = tmp_dir_path; - var cc_child_args: std.ArrayList([]const u8) = .empty; if (target.backend == .cbe) { const resolved_cc_zig_exe = if (opt_cc_zig) |cc_zig_exe| - try std.fs.path.relative(arena, tmp_dir_path, cc_zig_exe) + try Dir.path.relative(arena, cwd_path, environ_map, tmp_dir_path, cc_zig_exe) else resolved_zig_exe; @@ -183,8 +195,20 @@ pub fn main() !void { try cc_child_args.append(arena, "-o"); } + var child = try std.process.spawn(io, .{ + .argv = child_args.items, + .stdin = .pipe, + .stdout = .pipe, + .stderr = .pipe, + .progress_node = zig_prog_node, + .cwd_dir = tmp_dir, + .cwd = tmp_dir_path, + }); + defer child.kill(io); + var eval: Eval = .{ .arena = arena, + .io = io, .case = case, .host = host, .target = target, @@ -194,13 +218,12 @@ pub fn main() !void { .allow_stderr = debug_log_verbose, .preserve_tmp_on_fatal = preserve_tmp, .cc_child_args = &cc_child_args, + .enable_qemu = enable_qemu, + .enable_wine = enable_wine, + .enable_wasmtime = enable_wasmtime, + .enable_darling = enable_darling, }; - try child.spawn(); - errdefer { - _ = child.kill() catch {}; - } - var poller = Io.poll(arena, Eval.StreamEnum, .{ .stdout = child.stdout.?, .stderr = child.stderr.?, @@ -215,6 +238,9 @@ pub fn main() !void { std.log.scoped(.status).info("update: '{s}'", .{update.name}); } + log_cur_update = .{ &target, &update }; + defer log_cur_update = null; + eval.write(update); try eval.requestUpdate(); try eval.check(&poller, update, update_node); @@ -228,10 +254,11 @@ pub fn main() !void { const Eval = struct { arena: Allocator, + io: Io, host: std.Target, case: Case, target: Case.Target, - tmp_dir: std.fs.Dir, + tmp_dir: Dir, tmp_dir_path: []const u8, child: *std.process.Child, allow_stderr: bool, @@ -240,22 +267,28 @@ const Eval = struct { /// The arguments `out.c in.c` must be appended before spawning the subprocess. cc_child_args: *std.ArrayList([]const u8), + enable_qemu: bool, + enable_wine: bool, + enable_wasmtime: bool, + enable_darling: bool, + const StreamEnum = enum { stdout, stderr }; const Poller = Io.Poller(StreamEnum); /// Currently this function assumes the previous updates have already been written. fn write(eval: *Eval, update: Case.Update) void { + const io = eval.io; for (update.changes) |full_contents| { - eval.tmp_dir.writeFile(.{ + eval.tmp_dir.writeFile(io, .{ .sub_path = full_contents.name, .data = full_contents.bytes, }) catch |err| { - eval.fatal("failed to update '{s}': {s}", .{ full_contents.name, @errorName(err) }); + eval.fatal("failed to update '{s}': {t}", .{ full_contents.name, err }); }; } for (update.deletes) |doomed_name| { - eval.tmp_dir.deleteFile(doomed_name) catch |err| { - eval.fatal("failed to delete '{s}': {s}", .{ doomed_name, @errorName(err) }); + eval.tmp_dir.deleteFile(io, doomed_name) catch |err| { + eval.fatal("failed to delete '{s}': {t}", .{ doomed_name, err }); }; } } @@ -278,9 +311,9 @@ const Eval = struct { if (stderr.bufferedLen() > 0) { const stderr_data = try poller.toOwnedSlice(.stderr); if (eval.allow_stderr) { - std.log.info("error_bundle included stderr:\n{s}", .{stderr_data}); + std.log.info("error_bundle stderr:\n{s}", .{stderr_data}); } else { - eval.fatal("error_bundle included unexpected stderr:\n{s}", .{stderr_data}); + eval.fatal("error_bundle unexpected stderr:\n{s}", .{stderr_data}); } } if (result_error_bundle.errorMessageCount() != 0) { @@ -295,9 +328,9 @@ const Eval = struct { if (stderr.bufferedLen() > 0) { const stderr_data = try poller.toOwnedSlice(.stderr); if (eval.allow_stderr) { - std.log.info("emit_digest included stderr:\n{s}", .{stderr_data}); + std.log.info("emit_digest stderr:\n{s}", .{stderr_data}); } else { - eval.fatal("emit_digest included unexpected stderr:\n{s}", .{stderr_data}); + eval.fatal("emit_digest unexpected stderr:\n{s}", .{stderr_data}); } } @@ -307,14 +340,14 @@ const Eval = struct { } const digest = r.takeArray(Cache.bin_digest_len) catch unreachable; - const result_dir = ".local-cache" ++ std.fs.path.sep_str ++ "o" ++ std.fs.path.sep_str ++ Cache.binToHex(digest.*); + const result_dir = ".local-cache" ++ Dir.path.sep_str ++ "o" ++ Dir.path.sep_str ++ Cache.binToHex(digest.*); const bin_name = try std.zig.EmitArtifact.bin.cacheName(arena, .{ .root_name = "root", // corresponds to the module name "root" .target = &eval.target.resolved, .output_mode = .Exe, }); - const bin_path = try std.fs.path.join(arena, &.{ result_dir, bin_name }); + const bin_path = try Dir.path.join(arena, &.{ result_dir, bin_name }); try eval.checkSuccessOutcome(update, bin_path, prog_node); // This message indicates the end of the update. @@ -327,23 +360,24 @@ const Eval = struct { if (stderr.bufferedLen() > 0) { if (eval.allow_stderr) { - std.log.info("update '{s}' included stderr:\n{s}", .{ update.name, stderr.buffered() }); + std.log.info("stderr:\n{s}", .{stderr.buffered()}); } else { - eval.fatal("update '{s}' failed:\n{s}", .{ update.name, stderr.buffered() }); + eval.fatal("unexpected stderr:\n{s}", .{stderr.buffered()}); } } waitChild(eval.child, eval); - eval.fatal("update '{s}': compiler failed to send error_bundle or emit_bin_path", .{update.name}); + eval.fatal("compiler failed to send error_bundle or emit_bin_path", .{}); } fn checkErrorOutcome(eval: *Eval, update: Case.Update, error_bundle: std.zig.ErrorBundle) !void { + const io = eval.io; const expected = switch (update.outcome) { .unknown => return, .compile_errors => |ce| ce, .stdout, .exit_code => { - error_bundle.renderToStdErr(.{}, .auto); - eval.fatal("update '{s}': unexpected compile errors", .{update.name}); + try error_bundle.renderToStderr(io, .{}, .auto); + eval.fatal("unexpected compile errors", .{}); }, }; @@ -351,31 +385,30 @@ const Eval = struct { for (error_bundle.getMessages()) |err_idx| { if (expected_idx == expected.errors.len) { - error_bundle.renderToStdErr(.{}, .auto); - eval.fatal("update '{s}': more errors than expected", .{update.name}); + try error_bundle.renderToStderr(io, .{}, .auto); + eval.fatal("more errors than expected", .{}); } - try eval.checkOneError(update, error_bundle, expected.errors[expected_idx], false, err_idx); + try eval.checkOneError(error_bundle, expected.errors[expected_idx], false, err_idx); expected_idx += 1; for (error_bundle.getNotes(err_idx)) |note_idx| { if (expected_idx == expected.errors.len) { - error_bundle.renderToStdErr(.{}, .auto); - eval.fatal("update '{s}': more error notes than expected", .{update.name}); + try error_bundle.renderToStderr(io, .{}, .auto); + eval.fatal("more error notes than expected", .{}); } - try eval.checkOneError(update, error_bundle, expected.errors[expected_idx], true, note_idx); + try eval.checkOneError(error_bundle, expected.errors[expected_idx], true, note_idx); expected_idx += 1; } } if (!std.mem.eql(u8, error_bundle.getCompileLogOutput(), expected.compile_log_output)) { - error_bundle.renderToStdErr(.{}, .auto); - eval.fatal("update '{s}': unexpected compile log output", .{update.name}); + try error_bundle.renderToStderr(io, .{}, .auto); + eval.fatal("unexpected compile log output", .{}); } } fn checkOneError( eval: *Eval, - update: Case.Update, eb: std.zig.ErrorBundle, expected: Case.ExpectedError, is_note: bool, @@ -388,6 +421,8 @@ const Eval = struct { const src = eb.getSourceLocation(err.src_loc); const raw_filename = eb.nullTerminatedString(src.src_path); + const io = eval.io; + // We need to replace backslashes for consistency between platforms. const filename = name: { if (std.mem.indexOfScalar(u8, raw_filename, '\\') == null) break :name raw_filename; @@ -402,8 +437,8 @@ const Eval = struct { expected.column != src.column + 1 or !std.mem.eql(u8, expected.msg, msg)) { - eb.renderToStdErr(.{}, .auto); - eval.fatal("update '{s}': compile error did not match expected error", .{update.name}); + eb.renderToStderr(io, .{}, .auto) catch {}; + eval.fatal("compile error did not match expected error", .{}); } } @@ -417,20 +452,22 @@ const Eval = struct { std.debug.assert(eval.target.backend == .sema); return; }; + const io = eval.io; const binary_path = switch (eval.target.backend) { .sema => unreachable, .selfhosted, .llvm => emitted_path, .cbe => bin: { - const rand_int = std.crypto.random.int(u64); + const rand_int = rand64(io); const out_bin_name = "./out_" ++ std.fmt.hex(rand_int); - try eval.buildCOutput(update, emitted_path, out_bin_name, prog_node); + try eval.buildCOutput(emitted_path, out_bin_name, prog_node); break :bin out_bin_name; }, }; var argv_buf: [2][]const u8 = undefined; - const argv: []const []const u8, const is_foreign: bool = switch (std.zig.system.getExternalExecutor( + const argv: []const []const u8, const is_foreign: bool = sw: switch (std.zig.system.getExternalExecutor( + io, &eval.host, &eval.target.resolved, .{ .link_libc = eval.target.backend == .cbe }, @@ -449,18 +486,48 @@ const Eval = struct { argv_buf[0] = binary_path; break :argv .{ argv_buf[0..1], false }; }, - .qemu, .wine, .wasmtime, .darling => |executor_cmd| argv: { - argv_buf[0] = executor_cmd; - argv_buf[1] = binary_path; - break :argv .{ argv_buf[0..2], true }; + .qemu => |executor_cmd| argv: { + if (eval.enable_qemu) { + argv_buf[0] = executor_cmd; + argv_buf[1] = binary_path; + break :argv .{ argv_buf[0..2], true }; + } else { + continue :sw .bad_os_or_cpu; + } + }, + .wine => |executor_cmd| argv: { + if (eval.enable_wine) { + argv_buf[0] = executor_cmd; + argv_buf[1] = binary_path; + break :argv .{ argv_buf[0..2], true }; + } else { + continue :sw .bad_os_or_cpu; + } + }, + .wasmtime => |executor_cmd| argv: { + if (eval.enable_wasmtime) { + argv_buf[0] = executor_cmd; + argv_buf[1] = binary_path; + break :argv .{ argv_buf[0..2], true }; + } else { + continue :sw .bad_os_or_cpu; + } + }, + .darling => |executor_cmd| argv: { + if (eval.enable_darling) { + argv_buf[0] = executor_cmd; + argv_buf[1] = binary_path; + break :argv .{ argv_buf[0..2], true }; + } else { + continue :sw .bad_os_or_cpu; + } }, }; const run_prog_node = prog_node.start("run generated executable", 0); defer run_prog_node.end(); - const result = std.process.Child.run(.{ - .allocator = eval.arena, + const result = std.process.run(eval.arena, io, .{ .argv = argv, .cwd_dir = eval.tmp_dir, .cwd = eval.tmp_dir_path, @@ -468,45 +535,41 @@ const Eval = struct { if (is_foreign) { // Chances are the foreign executor isn't available. Skip this evaluation. if (eval.allow_stderr) { - std.log.warn("update '{s}': skipping execution of '{s}' via executor for foreign target '{s}': {s}", .{ - update.name, + std.log.warn("skipping execution of '{s}' via executor for foreign target '{s}': {t}", .{ binary_path, try eval.target.resolved.zigTriple(eval.arena), - @errorName(err), + err, }); } return; } - eval.fatal("update '{s}': failed to run the generated executable '{s}': {s}", .{ - update.name, binary_path, @errorName(err), - }); + eval.fatal("failed to run the generated executable '{s}': {t}", .{ binary_path, err }); }; // Some executors (looking at you, Wine) like throwing some stderr in, just for fun. // Therefore, we'll ignore stderr when using a foreign executor. if (!is_foreign and result.stderr.len != 0) { - std.log.err("update '{s}': generated executable '{s}' had unexpected stderr:\n{s}", .{ - update.name, binary_path, result.stderr, + std.log.err("generated executable '{s}' had unexpected stderr:\n{s}", .{ + binary_path, result.stderr, }); } switch (result.term) { - .Exited => |code| switch (update.outcome) { + .exited => |code| switch (update.outcome) { .unknown, .compile_errors => unreachable, .stdout => |expected_stdout| { if (code != 0) { - eval.fatal("update '{s}': generated executable '{s}' failed with code {d}", .{ - update.name, binary_path, code, - }); + eval.fatal("generated executable '{s}' failed with code {d}", .{ binary_path, code }); } try std.testing.expectEqualStrings(expected_stdout, result.stdout); }, - .exit_code => |expected_code| try std.testing.expectEqual(expected_code, result.term.Exited), + .exit_code => |expected_code| try std.testing.expectEqual(expected_code, code), }, - .Signal, .Stopped, .Unknown => { - eval.fatal("update '{s}': generated executable '{s}' terminated unexpectedly", .{ - update.name, binary_path, - }); + .signal => |sig| { + eval.fatal("generated executable '{s}' terminated with signal {t}", .{ binary_path, sig }); + }, + .stopped, .unknown => { + eval.fatal("generated executable '{s}' terminated unexpectedly", .{binary_path}); }, } @@ -514,11 +577,12 @@ const Eval = struct { } fn requestUpdate(eval: *Eval) !void { + const io = eval.io; const header: std.zig.Client.Message.Header = .{ .tag = .update, .bytes_len = 0, }; - var w = eval.child.stdin.?.writer(&.{}); + var w = eval.child.stdin.?.writer(io, &.{}); w.interface.writeStruct(header, .little) catch |err| switch (err) { error.WriteFailed => return w.err.?, }; @@ -543,7 +607,7 @@ const Eval = struct { } } - fn buildCOutput(eval: *Eval, update: Case.Update, c_path: []const u8, out_path: []const u8, prog_node: std.Progress.Node) !void { + fn buildCOutput(eval: *Eval, c_path: []const u8, out_path: []const u8, prog_node: std.Progress.Node) !void { std.debug.assert(eval.cc_child_args.items.len > 0); const child_prog_node = prog_node.start("build cbe output", 0); @@ -552,48 +616,38 @@ const Eval = struct { try eval.cc_child_args.appendSlice(eval.arena, &.{ out_path, c_path }); defer eval.cc_child_args.items.len -= 2; - const result = std.process.Child.run(.{ - .allocator = eval.arena, + const result = std.process.run(eval.arena, eval.io, .{ .argv = eval.cc_child_args.items, .cwd_dir = eval.tmp_dir, .cwd = eval.tmp_dir_path, .progress_node = child_prog_node, }) catch |err| { - eval.fatal("update '{s}': failed to spawn zig cc for '{s}': {s}", .{ - update.name, c_path, @errorName(err), - }); + eval.fatal("failed to spawn zig cc for '{s}': {t}", .{ c_path, err }); }; switch (result.term) { - .Exited => |code| if (code != 0) { + .exited => |code| if (code != 0) { if (result.stderr.len != 0) { - std.log.err("update '{s}': zig cc stderr:\n{s}", .{ - update.name, result.stderr, - }); + std.log.err("zig cc stderr:\n{s}", .{result.stderr}); } - eval.fatal("update '{s}': zig cc for '{s}' failed with code {d}", .{ - update.name, c_path, code, - }); + eval.fatal("zig cc for '{s}' failed with code {d}", .{ c_path, code }); }, - .Signal, .Stopped, .Unknown => { + .signal, .stopped, .unknown => { if (result.stderr.len != 0) { - std.log.err("update '{s}': zig cc stderr:\n{s}", .{ - update.name, result.stderr, - }); + std.log.err("zig cc stderr:\n{s}", .{result.stderr}); } - eval.fatal("update '{s}': zig cc for '{s}' terminated unexpectedly", .{ - update.name, c_path, - }); + eval.fatal("zig cc for '{s}' terminated unexpectedly", .{c_path}); }, } } fn fatal(eval: *Eval, comptime fmt: []const u8, args: anytype) noreturn { - eval.tmp_dir.close(); + const io = eval.io; + eval.tmp_dir.close(io); if (!eval.preserve_tmp_on_fatal) { // Kill the child since it holds an open handle to its CWD which is the tmp dir path - _ = eval.child.kill() catch {}; - std.fs.cwd().deleteTree(eval.tmp_dir_path) catch |err| { - std.log.warn("failed to delete tree '{s}': {s}", .{ eval.tmp_dir_path, @errorName(err) }); + eval.child.kill(io); + Dir.cwd().deleteTree(io, eval.tmp_dir_path) catch |err| { + std.log.warn("failed to delete tree '{s}': {t}", .{ eval.tmp_dir_path, err }); }; } std.process.fatal(fmt, args); @@ -759,7 +813,7 @@ const Case = struct { if (last_update.outcome != .unknown) fatal("line {d}: conflicting expect directive", .{line_n}); last_update.outcome = .{ .stdout = std.zig.string_literal.parseAlloc(arena, val) catch |err| { - fatal("line {d}: bad string literal: {s}", .{ line_n, @errorName(err) }); + fatal("line {d}: bad string literal: {t}", .{ line_n, err }); }, }; } else if (std.mem.eql(u8, key, "expect_error")) { @@ -833,30 +887,33 @@ const Case = struct { fn requestExit(child: *std.process.Child, eval: *Eval) void { if (child.stdin == null) return; + const io = eval.io; const header: std.zig.Client.Message.Header = .{ .tag = .exit, .bytes_len = 0, }; - var w = eval.child.stdin.?.writer(&.{}); + var w = eval.child.stdin.?.writer(io, &.{}); w.interface.writeStruct(header, .little) catch |err| switch (err) { error.WriteFailed => switch (w.err.?) { error.BrokenPipe => {}, - else => |e| eval.fatal("failed to send exit: {s}", .{@errorName(e)}), + else => |e| eval.fatal("failed to send exit: {t}", .{e}), }, }; // Send EOF to stdin. - child.stdin.?.close(); + child.stdin.?.close(io); child.stdin = null; } fn waitChild(child: *std.process.Child, eval: *Eval) void { + const io = eval.io; requestExit(child, eval); - const term = child.wait() catch |err| eval.fatal("child process failed: {s}", .{@errorName(err)}); + const term = child.wait(io) catch |err| eval.fatal("child process failed: {t}", .{err}); switch (term) { - .Exited => |code| if (code != 0) eval.fatal("compiler failed with code {d}", .{code}), - .Signal, .Stopped, .Unknown => eval.fatal("compiler terminated unexpectedly", .{}), + .exited => |code| if (code != 0) eval.fatal("compiler failed with code {d}", .{code}), + .signal => |sig| eval.fatal("compiler terminated with signal {t}", .{sig}), + .stopped, .unknown => eval.fatal("compiler terminated unexpectedly", .{}), } } @@ -899,3 +956,9 @@ fn parseExpectedError(str: []const u8, l: usize) Case.ExpectedError { .msg = message, }; } + +fn rand64(io: Io) u64 { + var x: u64 = undefined; + io.random(@ptrCast(&x)); + return x; +} diff --git a/tools/migrate_langref.zig b/tools/migrate_langref.zig index 3544cee17545..581d1294ff57 100644 --- a/tools/migrate_langref.zig +++ b/tools/migrate_langref.zig @@ -1,45 +1,41 @@ -const std = @import("std"); const builtin = @import("builtin"); -const fs = std.fs; + +const std = @import("std"); +const Io = std.Io; +const Dir = std.Io.Dir; const print = std.debug.print; const mem = std.mem; const testing = std.testing; const Allocator = std.mem.Allocator; -const max_doc_file_size = 10 * 1024 * 1024; const fatal = std.process.fatal; -pub fn main() !void { - var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena_instance.deinit(); - const arena = arena_instance.allocator(); +const max_doc_file_size = 10 * 1024 * 1024; - const gpa = arena; +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const io = init.io; + const args = try init.minimal.args.toSlice(arena); - const args = try std.process.argsAlloc(arena); const input_file = args[1]; const output_file = args[2]; - var threaded: std.Io.Threaded = .init(gpa); - defer threaded.deinit(); - const io = threaded.io(); - - var in_file = try fs.cwd().openFile(input_file, .{ .mode = .read_only }); - defer in_file.close(); + var in_file = try Dir.cwd().openFile(io, input_file, .{ .mode = .read_only }); + defer in_file.close(io); - var out_file = try fs.cwd().createFile(output_file, .{}); - defer out_file.close(); + var out_file = try Dir.cwd().createFile(io, output_file, .{}); + defer out_file.close(io); var out_file_buffer: [4096]u8 = undefined; - var out_file_writer = out_file.writer(&out_file_buffer); + var out_file_writer = out_file.writer(io, &out_file_buffer); - var out_dir = try fs.cwd().openDir(fs.path.dirname(output_file).?, .{}); - defer out_dir.close(); + var out_dir = try Dir.cwd().openDir(io, Dir.path.dirname(output_file).?, .{}); + defer out_dir.close(io); var in_file_reader = in_file.reader(io, &.{}); const input_file_bytes = try in_file_reader.interface.allocRemaining(arena, .unlimited); var tokenizer = Tokenizer.init(input_file, input_file_bytes); - try walk(arena, &tokenizer, out_dir, &out_file_writer.interface); + try walk(arena, io, &tokenizer, out_dir, &out_file_writer.interface); try out_file_writer.end(); } @@ -266,7 +262,7 @@ const Code = struct { }; }; -fn walk(arena: Allocator, tokenizer: *Tokenizer, out_dir: std.fs.Dir, w: anytype) !void { +fn walk(arena: Allocator, io: Io, tokenizer: *Tokenizer, out_dir: Dir, w: anytype) !void { while (true) { const token = tokenizer.next(); switch (token.id) { @@ -384,12 +380,12 @@ fn walk(arena: Allocator, tokenizer: *Tokenizer, out_dir: std.fs.Dir, w: anytype const basename = try std.fmt.allocPrint(arena, "{s}.zig", .{name}); - var file = out_dir.createFile(basename, .{ .exclusive = true }) catch |err| { + var file = out_dir.createFile(io, basename, .{ .exclusive = true }) catch |err| { fatal("unable to create file '{s}': {s}", .{ name, @errorName(err) }); }; - defer file.close(); + defer file.close(io); var file_buffer: [1024]u8 = undefined; - var file_writer = file.writer(&file_buffer); + var file_writer = file.writer(io, &file_buffer); const code = &file_writer.interface; const source = tokenizer.buffer[source_token.start..source_token.end]; diff --git a/tools/process_headers.zig b/tools/process_headers.zig index eb671193bb0d..0c72299055e1 100644 --- a/tools/process_headers.zig +++ b/tools/process_headers.zig @@ -6,12 +6,14 @@ //! this tool. //! //! First, use the glibc, musl, FreeBSD, and NetBSD build systems to create installations of all the -//! targets in the `glibc_targets`, `musl_targets`, `freebsd_targets`, and `netbsd_targets` -//! variables. Next, run this tool to create a new directory which puts .h files into +//! targets in the `glibc_targets`, `musl_targets`, `freebsd_targets`, `netbsd_targets`, and +//! `openbsd_targets` variables. Next, run this tool to create a new directory which puts .h files into //! subdirectories, with `generic` being files that apply to all architectures. //! You'll then have to manually update Zig source repo with these new files. const std = @import("std"); +const Io = std.Io; +const Dir = std.Io.Dir; const Arch = std.Target.Cpu.Arch; const Abi = std.Target.Abi; const OsTag = std.Target.Os.Tag; @@ -81,7 +83,6 @@ const musl_targets = [_]LibCTarget{ const freebsd_targets = [_]LibCTarget{ .{ .arch = .arm, .abi = .eabihf }, .{ .arch = .aarch64, .abi = .none }, - .{ .arch = .powerpc, .abi = .eabihf }, .{ .arch = .powerpc64, .abi = .none }, .{ .arch = .riscv64, .abi = .none }, .{ .arch = .x86, .abi = .none }, @@ -103,6 +104,19 @@ const netbsd_targets = [_]LibCTarget{ .{ .arch = .x86_64, .abi = .none }, }; +const openbsd_targets = [_]LibCTarget{ + .{ .arch = .arm, .abi = .eabi }, + .{ .arch = .aarch64, .abi = .none }, + .{ .arch = .mips64, .abi = .none }, + .{ .arch = .mips64el, .abi = .none }, + .{ .arch = .powerpc, .abi = .eabihf }, + .{ .arch = .powerpc64, .abi = .none }, + .{ .arch = .riscv64, .abi = .none }, + .{ .arch = .sparc64, .abi = .none }, + .{ .arch = .x86, .abi = .none }, + .{ .arch = .x86_64, .abi = .none }, +}; + const Contents = struct { bytes: []const u8, hit_count: usize, @@ -124,13 +138,17 @@ const LibCVendor = enum { glibc, freebsd, netbsd, + openbsd, }; -pub fn main() !void { - var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); - const allocator = arena.allocator(); - const args = try std.process.argsAlloc(allocator); - var search_paths = std.array_list.Managed([]const u8).init(allocator); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const io = init.io; + const args = try init.minimal.args.toSlice(arena); + const cwd_path = try std.process.getCwdAlloc(arena); + const environ_map = init.environ_map; + + var search_paths = std.array_list.Managed([]const u8).init(arena); var opt_out_dir: ?[]const u8 = null; var opt_abi: ?[]const u8 = null; @@ -166,16 +184,17 @@ pub fn main() !void { usageAndExit(args[0]); }; - const generic_name = try std.fmt.allocPrint(allocator, "generic-{s}", .{abi_name}); + const generic_name = try std.fmt.allocPrint(arena, "generic-{s}", .{abi_name}); const libc_targets = switch (vendor) { .glibc => &glibc_targets, .musl => &musl_targets, .freebsd => &freebsd_targets, .netbsd => &netbsd_targets, + .openbsd => &openbsd_targets, }; - var path_table = PathTable.init(allocator); - var hash_to_contents = HashToContents.init(allocator); + var path_table = PathTable.init(arena); + var hash_to_contents = HashToContents.init(arena); var max_bytes_saved: usize = 0; var total_bytes: usize = 0; @@ -183,7 +202,7 @@ pub fn main() !void { for (libc_targets) |libc_target| { const libc_dir = switch (vendor) { - .glibc => try std.zig.target.glibcRuntimeTriple(allocator, libc_target.arch, .linux, libc_target.abi), + .glibc => try std.zig.target.glibcRuntimeTriple(arena, libc_target.arch, .linux, libc_target.abi), .musl => std.zig.target.muslArchName(libc_target.arch, libc_target.abi), .freebsd => switch (libc_target.arch) { .arm => "armv7", @@ -211,16 +230,33 @@ pub fn main() !void { .sparc64, => |a| @tagName(a), + else => unreachable, + }, + .openbsd => switch (libc_target.arch) { + .arm => "armv7", + .aarch64 => "arm64", + .mips64 => "octeon", + .mips64el => "loongson", + .powerpc => "macppc", + .x86 => "i386", + .x86_64 => "amd64", + + .powerpc64, + .riscv64, + .sparc64, + => |a| @tagName(a), + else => unreachable, }, }; - const dest_target = if (libc_target.dest) |dest| dest else try std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{ + const dest_target = if (libc_target.dest) |dest| dest else try std.fmt.allocPrint(arena, "{s}-{s}-{s}", .{ @tagName(libc_target.arch), switch (vendor) { .musl, .glibc => "linux", .freebsd => "freebsd", .netbsd => "netbsd", + .openbsd => "openbsd", }, @tagName(libc_target.abi), }); @@ -230,34 +266,35 @@ pub fn main() !void { .glibc, .freebsd, .netbsd, + .openbsd, => &[_][]const u8{ search_path, libc_dir, "usr", "include" }, .musl => &[_][]const u8{ search_path, libc_dir, "usr", "local", "musl", "include" }, }; - const target_include_dir = try std.fs.path.join(allocator, sub_path); - var dir_stack = std.array_list.Managed([]const u8).init(allocator); + const target_include_dir = try Dir.path.join(arena, sub_path); + var dir_stack = std.array_list.Managed([]const u8).init(arena); try dir_stack.append(target_include_dir); while (dir_stack.pop()) |full_dir_name| { - var dir = std.fs.cwd().openDir(full_dir_name, .{ .iterate = true }) catch |err| switch (err) { + var dir = Dir.cwd().openDir(io, full_dir_name, .{ .iterate = true }) catch |err| switch (err) { error.FileNotFound => continue :search, error.AccessDenied => continue :search, else => return err, }; - defer dir.close(); + defer dir.close(io); var dir_it = dir.iterate(); - while (try dir_it.next()) |entry| { - const full_path = try std.fs.path.join(allocator, &[_][]const u8{ full_dir_name, entry.name }); + while (try dir_it.next(io)) |entry| { + const full_path = try Dir.path.join(arena, &[_][]const u8{ full_dir_name, entry.name }); switch (entry.kind) { .directory => try dir_stack.append(full_path), .file, .sym_link => { - const rel_path = try std.fs.path.relative(allocator, target_include_dir, full_path); + const rel_path = try Dir.path.relative(arena, cwd_path, environ_map, target_include_dir, full_path); const max_size = 2 * 1024 * 1024 * 1024; - const raw_bytes = try std.fs.cwd().readFileAlloc(full_path, allocator, .limited(max_size)); + const raw_bytes = try Dir.cwd().readFileAlloc(io, full_path, arena, .limited(max_size)); const trimmed = std.mem.trim(u8, raw_bytes, " \r\n\t"); total_bytes += raw_bytes.len; - const hash = try allocator.alloc(u8, 32); + const hash = try arena.alloc(u8, 32); hasher = Blake3.init(.{}); hasher.update(rel_path); hasher.update(trimmed); @@ -267,9 +304,7 @@ pub fn main() !void { max_bytes_saved += raw_bytes.len; gop.value_ptr.hit_count += 1; std.debug.print("duplicate: {s} {s} ({B})\n", .{ - libc_dir, - rel_path, - raw_bytes.len, + libc_dir, rel_path, raw_bytes.len, }); } else { gop.value_ptr.* = Contents{ @@ -281,8 +316,8 @@ pub fn main() !void { } const path_gop = try path_table.getOrPut(rel_path); const target_to_hash = if (path_gop.found_existing) path_gop.value_ptr.* else blk: { - const ptr = try allocator.create(TargetToHash); - ptr.* = TargetToHash.init(allocator); + const ptr = try arena.create(TargetToHash); + ptr.* = TargetToHash.init(arena); path_gop.value_ptr.* = ptr; break :blk ptr; }; @@ -315,7 +350,7 @@ pub fn main() !void { total_bytes, total_bytes - max_bytes_saved, }); - try std.fs.cwd().makePath(out_dir); + try Dir.cwd().createDirPath(io, out_dir); var missed_opportunity_bytes: usize = 0; // iterate path_table. for each path, put all the hashes into a list. sort by hit_count. @@ -323,7 +358,7 @@ pub fn main() !void { // gets their header in a separate arch directory. var path_it = path_table.iterator(); while (path_it.next()) |path_kv| { - var contents_list = std.array_list.Managed(*Contents).init(allocator); + var contents_list = std.array_list.Managed(*Contents).init(arena); { var hash_it = path_kv.value_ptr.*.iterator(); while (hash_it.next()) |hash_kv| { @@ -335,9 +370,9 @@ pub fn main() !void { const best_contents = contents_list.pop().?; if (best_contents.hit_count > 1) { // worth it to make it generic - const full_path = try std.fs.path.join(allocator, &[_][]const u8{ out_dir, generic_name, path_kv.key_ptr.* }); - try std.fs.cwd().makePath(std.fs.path.dirname(full_path).?); - try std.fs.cwd().writeFile(.{ .sub_path = full_path, .data = best_contents.bytes }); + const full_path = try Dir.path.join(arena, &[_][]const u8{ out_dir, generic_name, path_kv.key_ptr.* }); + try Dir.cwd().createDirPath(io, Dir.path.dirname(full_path).?); + try Dir.cwd().writeFile(io, .{ .sub_path = full_path, .data = best_contents.bytes }); best_contents.is_generic = true; while (contents_list.pop()) |contender| { if (contender.hit_count > 1) { @@ -356,9 +391,9 @@ pub fn main() !void { if (contents.is_generic) continue; const dest_target = hash_kv.key_ptr.*; - const full_path = try std.fs.path.join(allocator, &[_][]const u8{ out_dir, dest_target, path_kv.key_ptr.* }); - try std.fs.cwd().makePath(std.fs.path.dirname(full_path).?); - try std.fs.cwd().writeFile(.{ .sub_path = full_path, .data = contents.bytes }); + const full_path = try Dir.path.join(arena, &[_][]const u8{ out_dir, dest_target, path_kv.key_ptr.* }); + try Dir.cwd().createDirPath(io, Dir.path.dirname(full_path).?); + try Dir.cwd().writeFile(io, .{ .sub_path = full_path, .data = contents.bytes }); } } } @@ -368,6 +403,6 @@ fn usageAndExit(arg0: []const u8) noreturn { std.debug.print("--search-path can be used any number of times.\n", .{}); std.debug.print(" subdirectories of search paths look like, e.g. x86_64-linux-gnu\n", .{}); std.debug.print("--out is a dir that will be created, and populated with the results\n", .{}); - std.debug.print("--abi is either glibc, musl, freebsd, or netbsd\n", .{}); + std.debug.print("--abi is either glibc, musl, freebsd, netbsd, or openbsd\n", .{}); std.process.exit(1); } diff --git a/tools/update-linux-headers.zig b/tools/update-linux-headers.zig index bf9edf0753c2..e05ba082031c 100644 --- a/tools/update-linux-headers.zig +++ b/tools/update-linux-headers.zig @@ -15,6 +15,8 @@ //! You'll then have to manually update Zig source repo with these new files. const std = @import("std"); +const Io = std.Io; +const Dir = std.Io.Dir; const Arch = std.Target.Cpu.Arch; const Abi = std.Target.Abi; const assert = std.debug.assert; @@ -139,10 +141,13 @@ const HashToContents = std.StringHashMap(Contents); const TargetToHash = std.ArrayHashMap(DestTarget, []const u8, DestTarget.HashContext, true); const PathTable = std.StringHashMap(*TargetToHash); -pub fn main() !void { - var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator); - const arena = arena_state.allocator(); - const args = try std.process.argsAlloc(arena); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const io = init.io; + const args = try init.minimal.args.toSlice(arena); + const environ_map = init.environ_map; + const cwd = try std.process.getCwdAlloc(arena); + var search_paths = std.array_list.Managed([]const u8).init(arena); var opt_out_dir: ?[]const u8 = null; @@ -183,30 +188,30 @@ pub fn main() !void { .arch = linux_target.arch, }; search: for (search_paths.items) |search_path| { - const target_include_dir = try std.fs.path.join(arena, &.{ + const target_include_dir = try Dir.path.join(arena, &.{ search_path, linux_target.name, "include", }); var dir_stack = std.array_list.Managed([]const u8).init(arena); try dir_stack.append(target_include_dir); while (dir_stack.pop()) |full_dir_name| { - var dir = std.fs.cwd().openDir(full_dir_name, .{ .iterate = true }) catch |err| switch (err) { + var dir = Dir.cwd().openDir(io, full_dir_name, .{ .iterate = true }) catch |err| switch (err) { error.FileNotFound => continue :search, error.AccessDenied => continue :search, else => return err, }; - defer dir.close(); + defer dir.close(io); var dir_it = dir.iterate(); - while (try dir_it.next()) |entry| { - const full_path = try std.fs.path.join(arena, &[_][]const u8{ full_dir_name, entry.name }); + while (try dir_it.next(io)) |entry| { + const full_path = try Dir.path.join(arena, &[_][]const u8{ full_dir_name, entry.name }); switch (entry.kind) { .directory => try dir_stack.append(full_path), .file => { - const rel_path = try std.fs.path.relative(arena, target_include_dir, full_path); + const rel_path = try Dir.path.relative(arena, cwd, environ_map, target_include_dir, full_path); const max_size = 2 * 1024 * 1024 * 1024; - const raw_bytes = try std.fs.cwd().readFileAlloc(full_path, arena, .limited(max_size)); + const raw_bytes = try Dir.cwd().readFileAlloc(io, full_path, arena, .limited(max_size)); const trimmed = std.mem.trim(u8, raw_bytes, " \r\n\t"); total_bytes += raw_bytes.len; const hash = try arena.alloc(u8, 32); @@ -253,7 +258,7 @@ pub fn main() !void { total_bytes, total_bytes - max_bytes_saved, }); - try std.fs.cwd().makePath(out_dir); + try Dir.cwd().createDirPath(io, out_dir); var missed_opportunity_bytes: usize = 0; // iterate path_table. for each path, put all the hashes into a list. sort by hit_count. @@ -273,9 +278,9 @@ pub fn main() !void { const best_contents = contents_list.pop().?; if (best_contents.hit_count > 1) { // worth it to make it generic - const full_path = try std.fs.path.join(arena, &[_][]const u8{ out_dir, generic_name, path_kv.key_ptr.* }); - try std.fs.cwd().makePath(std.fs.path.dirname(full_path).?); - try std.fs.cwd().writeFile(.{ .sub_path = full_path, .data = best_contents.bytes }); + const full_path = try Dir.path.join(arena, &[_][]const u8{ out_dir, generic_name, path_kv.key_ptr.* }); + try Dir.cwd().createDirPath(io, Dir.path.dirname(full_path).?); + try Dir.cwd().writeFile(io, .{ .sub_path = full_path, .data = best_contents.bytes }); best_contents.is_generic = true; while (contents_list.pop()) |contender| { if (contender.hit_count > 1) { @@ -299,9 +304,9 @@ pub fn main() !void { else => @tagName(dest_target.arch), }; const out_subpath = try std.fmt.allocPrint(arena, "{s}-linux-any", .{arch_name}); - const full_path = try std.fs.path.join(arena, &[_][]const u8{ out_dir, out_subpath, path_kv.key_ptr.* }); - try std.fs.cwd().makePath(std.fs.path.dirname(full_path).?); - try std.fs.cwd().writeFile(.{ .sub_path = full_path, .data = contents.bytes }); + const full_path = try Dir.path.join(arena, &[_][]const u8{ out_dir, out_subpath, path_kv.key_ptr.* }); + try Dir.cwd().createDirPath(io, Dir.path.dirname(full_path).?); + try Dir.cwd().writeFile(io, .{ .sub_path = full_path, .data = contents.bytes }); } } @@ -316,8 +321,8 @@ pub fn main() !void { "any-linux-any/linux/netfilter_ipv6/ip6t_HL.h", }; for (bad_files) |bad_file| { - const full_path = try std.fs.path.join(arena, &[_][]const u8{ out_dir, bad_file }); - try std.fs.cwd().deleteFile(full_path); + const full_path = try Dir.path.join(arena, &[_][]const u8{ out_dir, bad_file }); + try Dir.cwd().deleteFile(io, full_path); } } diff --git a/tools/update_clang_options.zig b/tools/update_clang_options.zig index c8b941cbfac3..b52267a3fbd2 100644 --- a/tools/update_clang_options.zig +++ b/tools/update_clang_options.zig @@ -10,7 +10,7 @@ //! would mean that the next parameter specifies the target. const std = @import("std"); -const fs = std.fs; +const Io = std.Io; const assert = std.debug.assert; const json = std.json; @@ -627,15 +627,13 @@ const cpu_targets = struct { pub const xtensa = std.Target.xtensa; }; -pub fn main() anyerror!void { - var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena.deinit(); - - const allocator = arena.allocator(); - const args = try std.process.argsAlloc(allocator); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const args = try init.minimal.args.toSlice(arena); + const io = init.io; var stdout_buffer: [4000]u8 = undefined; - var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer); + var stdout_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer); const stdout = &stdout_writer.interface; if (args.len <= 1) printUsageAndExit(args[0]); @@ -654,7 +652,7 @@ pub fn main() anyerror!void { const llvm_src_root = args[2]; if (std.mem.startsWith(u8, llvm_src_root, "-")) printUsageAndExit(args[0]); - var llvm_to_zig_cpu_features = std.StringHashMap([]const u8).init(allocator); + var llvm_to_zig_cpu_features = std.StringHashMap([]const u8).init(arena); inline for (@typeInfo(cpu_targets).@"struct".decls) |decl| { const Feature = @field(cpu_targets, decl.name).Feature; @@ -671,13 +669,12 @@ pub fn main() anyerror!void { const child_args = [_][]const u8{ llvm_tblgen_exe, "--dump-json", - try std.fmt.allocPrint(allocator, "{s}/clang/include/clang/Driver/Options.td", .{llvm_src_root}), - try std.fmt.allocPrint(allocator, "-I={s}/llvm/include", .{llvm_src_root}), - try std.fmt.allocPrint(allocator, "-I={s}/clang/include/clang/Driver", .{llvm_src_root}), + try std.fmt.allocPrint(arena, "{s}/clang/include/clang/Driver/Options.td", .{llvm_src_root}), + try std.fmt.allocPrint(arena, "-I={s}/llvm/include", .{llvm_src_root}), + try std.fmt.allocPrint(arena, "-I={s}/clang/include/clang/Driver", .{llvm_src_root}), }; - const child_result = try std.process.Child.run(.{ - .allocator = allocator, + const child_result = try std.process.run(arena, io, .{ .argv = &child_args, .max_output_bytes = 100 * 1024 * 1024, }); @@ -685,7 +682,7 @@ pub fn main() anyerror!void { std.debug.print("{s}\n", .{child_result.stderr}); const json_text = switch (child_result.term) { - .Exited => |code| if (code == 0) child_result.stdout else { + .exited => |code| if (code == 0) child_result.stdout else { std.debug.print("llvm-tblgen exited with code {d}\n", .{code}); std.process.exit(1); }, @@ -695,11 +692,11 @@ pub fn main() anyerror!void { }, }; - const parsed = try json.parseFromSlice(json.Value, allocator, json_text, .{}); + const parsed = try json.parseFromSlice(json.Value, arena, json_text, .{}); defer parsed.deinit(); const root_map = &parsed.value.object; - var all_objects = std.array_list.Managed(*json.ObjectMap).init(allocator); + var all_objects = std.array_list.Managed(*json.ObjectMap).init(arena); { var it = root_map.iterator(); it_map: while (it.next()) |kv| { @@ -961,8 +958,8 @@ fn objectLessThan(context: void, a: *json.ObjectMap, b: *json.ObjectMap) bool { } fn printUsageAndExit(arg0: []const u8) noreturn { - const w, _ = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); + const stderr = std.debug.lockStderr(&.{}); + const w = &stderr.file_writer.interface; printUsage(w, arg0) catch std.process.exit(2); std.process.exit(1); } diff --git a/tools/update_cpu_features.zig b/tools/update_cpu_features.zig index 4c29c16e7e87..3041ee6acc51 100644 --- a/tools/update_cpu_features.zig +++ b/tools/update_cpu_features.zig @@ -1,6 +1,8 @@ -const std = @import("std"); const builtin = @import("builtin"); -const fs = std.fs; + +const std = @import("std"); +const Io = std.Io; +const Dir = std.Io.Dir; const mem = std.mem; const json = std.json; const assert = std.debug.assert; @@ -1881,12 +1883,11 @@ const targets = [_]ArchTarget{ }, }; -pub fn main() anyerror!void { - var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena_state.deinit(); - const arena = arena_state.allocator(); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const io = init.io; - var args = try std.process.argsWithAllocator(arena); + var args = try init.minimal.args.iterateAllocator(arena); const args0 = args.next().?; const llvm_tblgen_exe = args.next() orelse @@ -1919,51 +1920,40 @@ pub fn main() anyerror!void { // there shouldn't be any more argument after the optional filter if (args.skip()) usageAndExit(args0, 1); - var zig_src_dir = try fs.cwd().openDir(zig_src_root, .{}); - defer zig_src_dir.close(); + var zig_src_dir = try Dir.cwd().openDir(io, zig_src_root, .{}); + defer zig_src_dir.close(io); - const root_progress = std.Progress.start(.{ .estimated_total_items = targets.len }); + const root_progress = std.Progress.start(io, .{ .estimated_total_items = targets.len }); defer root_progress.end(); - if (builtin.single_threaded) { - for (targets) |target| { - if (filter) |zig_name| if (!std.mem.eql(u8, target.zig_name, zig_name)) continue; - try processOneTarget(.{ - .llvm_tblgen_exe = llvm_tblgen_exe, - .llvm_src_root = llvm_src_root, - .zig_src_dir = zig_src_dir, - .root_progress = root_progress, - .target = target, - }); - } - } else { - var pool: std.Thread.Pool = undefined; - try pool.init(.{ .allocator = arena, .n_jobs = targets.len }); - defer pool.deinit(); - - for (targets) |target| { - if (filter) |zig_name| if (!std.mem.eql(u8, target.zig_name, zig_name)) continue; - const job = Job{ - .llvm_tblgen_exe = llvm_tblgen_exe, - .llvm_src_root = llvm_src_root, - .zig_src_dir = zig_src_dir, - .root_progress = root_progress, - .target = target, - }; - try pool.spawn(processOneTarget, .{job}); + var group: Io.Group = .init; + defer group.cancel(io); + + for (targets) |target| { + if (filter) |zig_name| { + if (!std.mem.eql(u8, target.zig_name, zig_name)) continue; } + group.async(io, processOneTarget, .{ io, .{ + .llvm_tblgen_exe = llvm_tblgen_exe, + .llvm_src_root = llvm_src_root, + .zig_src_dir = zig_src_dir, + .root_progress = root_progress, + .target = target, + } }); } + + try group.await(io); } const Job = struct { llvm_tblgen_exe: []const u8, llvm_src_root: []const u8, - zig_src_dir: std.fs.Dir, + zig_src_dir: Dir, root_progress: std.Progress.Node, target: ArchTarget, }; -fn processOneTarget(job: Job) void { +fn processOneTarget(io: Io, job: Job) void { errdefer |err| std.debug.panic("panic: {s}", .{@errorName(err)}); const target = job.target; @@ -1995,8 +1985,7 @@ fn processOneTarget(job: Job) void { }), }; - const child_result = try std.process.Child.run(.{ - .allocator = arena, + const child_result = try std.process.run(arena, io, .{ .argv = &child_args, .max_output_bytes = 500 * 1024 * 1024, }); @@ -2006,7 +1995,7 @@ fn processOneTarget(job: Job) void { } const json_text = switch (child_result.term) { - .Exited => |code| if (code == 0) child_result.stdout else { + .exited => |code| if (code == 0) child_result.stdout else { std.debug.print("llvm-tblgen exited with code {d}\n", .{code}); std.process.exit(1); }, @@ -2243,15 +2232,15 @@ fn processOneTarget(job: Job) void { const render_progress = progress_node.start("rendering Zig code", 0); - var target_dir = try job.zig_src_dir.openDir("lib/std/Target", .{}); - defer target_dir.close(); + var target_dir = try job.zig_src_dir.openDir(io, "lib/std/Target", .{}); + defer target_dir.close(io); const zig_code_basename = try std.fmt.allocPrint(arena, "{s}.zig", .{target.zig_name}); - var zig_code_file = try target_dir.createFile(zig_code_basename, .{}); - defer zig_code_file.close(); + var zig_code_file = try target_dir.createFile(io, zig_code_basename, .{}); + defer zig_code_file.close(io); var zig_code_file_buffer: [4096]u8 = undefined; - var zig_code_file_writer = zig_code_file.writer(&zig_code_file_buffer); + var zig_code_file_writer = zig_code_file.writer(io, &zig_code_file_buffer); const w = &zig_code_file_writer.interface; try w.writeAll( @@ -2427,8 +2416,9 @@ fn processOneTarget(job: Job) void { } fn usageAndExit(arg0: []const u8, code: u8) noreturn { - const stderr, _ = std.debug.lockStderrWriter(&.{}); - stderr.print( + const stderr = std.debug.lockStderr(&.{}); + const w = &stderr.file_writer.interface; + w.print( \\Usage: {s} /path/to/llvm-tblgen /path/git/llvm-project /path/git/zig [zig_name filter] \\ \\Updates lib/std/target/.zig from llvm/lib/Target//.td . diff --git a/tools/update_crc_catalog.zig b/tools/update_crc_catalog.zig index 4c8614e02fda..57eedf375b29 100644 --- a/tools/update_crc_catalog.zig +++ b/tools/update_crc_catalog.zig @@ -1,36 +1,39 @@ const std = @import("std"); -const fs = std.fs; +const Io = std.Io; +const Dir = std.Io.Dir; const mem = std.mem; const ascii = std.ascii; const catalog_txt = @embedFile("crc/catalog.txt"); -pub fn main() anyerror!void { - var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena_state.deinit(); - const arena = arena_state.allocator(); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const io = init.io; + const args = try init.minimal.args.toSlice(arena); + return @"i like cheese"(arena, io, args); +} - const args = try std.process.argsAlloc(arena); +fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8) !void { if (args.len <= 1) printUsageAndExit(args[0]); const zig_src_root = args[1]; if (mem.startsWith(u8, zig_src_root, "-")) printUsageAndExit(args[0]); - var zig_src_dir = try fs.cwd().openDir(zig_src_root, .{}); - defer zig_src_dir.close(); + var zig_src_dir = try Dir.cwd().openDir(io, zig_src_root, .{}); + defer zig_src_dir.close(io); - const hash_sub_path = try fs.path.join(arena, &.{ "lib", "std", "hash" }); - var hash_target_dir = try zig_src_dir.makeOpenPath(hash_sub_path, .{}); - defer hash_target_dir.close(); + const hash_sub_path = try Dir.path.join(arena, &.{ "lib", "std", "hash" }); + var hash_target_dir = try zig_src_dir.createDirPathOpen(io, hash_sub_path, .{}); + defer hash_target_dir.close(io); - const crc_sub_path = try fs.path.join(arena, &.{ "lib", "std", "hash", "crc" }); - var crc_target_dir = try zig_src_dir.makeOpenPath(crc_sub_path, .{}); - defer crc_target_dir.close(); + const crc_sub_path = try Dir.path.join(arena, &.{ "lib", "std", "hash", "crc" }); + var crc_target_dir = try zig_src_dir.createDirPathOpen(io, crc_sub_path, .{}); + defer crc_target_dir.close(io); - var zig_code_file = try hash_target_dir.createFile("crc.zig", .{}); - defer zig_code_file.close(); + var zig_code_file = try hash_target_dir.createFile(io, "crc.zig", .{}); + defer zig_code_file.close(io); var zig_code_file_buffer: [4096]u8 = undefined; - var zig_code_file_writer = zig_code_file.writer(&zig_code_file_buffer); + var zig_code_file_writer = zig_code_file.writer(io, &zig_code_file_buffer); const code_writer = &zig_code_file_writer.interface; try code_writer.writeAll( @@ -51,10 +54,10 @@ pub fn main() anyerror!void { \\ ); - var zig_test_file = try crc_target_dir.createFile("test.zig", .{}); - defer zig_test_file.close(); + var zig_test_file = try crc_target_dir.createFile(io, "test.zig", .{}); + defer zig_test_file.close(io); var zig_test_file_buffer: [4096]u8 = undefined; - var zig_test_file_writer = zig_test_file.writer(&zig_test_file_buffer); + var zig_test_file_writer = zig_test_file.writer(io, &zig_test_file_buffer); const test_writer = &zig_test_file_writer.interface; try test_writer.writeAll( @@ -190,8 +193,8 @@ pub fn main() anyerror!void { } fn printUsageAndExit(arg0: []const u8) noreturn { - const w, _ = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); + const stderr = std.debug.lockStderr(&.{}); + const w = &stderr.file_writer.interface; printUsage(w, arg0) catch std.process.exit(2); std.process.exit(1); } diff --git a/tools/update_freebsd_libc.zig b/tools/update_freebsd_libc.zig index 420147e0dfb4..c2b251da0fda 100644 --- a/tools/update_freebsd_libc.zig +++ b/tools/update_freebsd_libc.zig @@ -5,40 +5,38 @@ //! `zig run tools/update_freebsd_libc.zig -- ~/Downloads/freebsd-src .` const std = @import("std"); +const Io = std.Io; const exempt_files = [_][]const u8{ // This file is maintained by a separate project and does not come from FreeBSD. "abilists", }; -pub fn main() !void { - var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena_instance.deinit(); - const arena = arena_instance.allocator(); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const io = init.io; + const args = try init.minimal.args.toSlice(arena); - const args = try std.process.argsAlloc(arena); const freebsd_src_path = args[1]; const zig_src_path = args[2]; const dest_dir_path = try std.fmt.allocPrint(arena, "{s}/lib/libc/freebsd", .{zig_src_path}); - var dest_dir = std.fs.cwd().openDir(dest_dir_path, .{ .iterate = true }) catch |err| { - std.log.err("unable to open destination directory '{s}': {s}", .{ - dest_dir_path, @errorName(err), - }); + var dest_dir = Io.Dir.cwd().openDir(io, dest_dir_path, .{ .iterate = true }) catch |err| { + std.log.err("unable to open destination directory '{s}': {t}", .{ dest_dir_path, err }); std.process.exit(1); }; - defer dest_dir.close(); + defer dest_dir.close(io); - var freebsd_src_dir = try std.fs.cwd().openDir(freebsd_src_path, .{}); - defer freebsd_src_dir.close(); + var freebsd_src_dir = try Io.Dir.cwd().openDir(io, freebsd_src_path, .{}); + defer freebsd_src_dir.close(io); // Copy updated files from upstream. { var walker = try dest_dir.walk(arena); defer walker.deinit(); - walk: while (try walker.next()) |entry| { + walk: while (try walker.next(io)) |entry| { if (entry.kind != .file) continue; if (std.mem.startsWith(u8, entry.basename, ".")) continue; for (exempt_files) |p| { @@ -46,18 +44,15 @@ pub fn main() !void { } std.log.info("updating '{s}/{s}' from '{s}/{s}'", .{ - dest_dir_path, entry.path, - freebsd_src_path, entry.path, + dest_dir_path, entry.path, freebsd_src_path, entry.path, }); - freebsd_src_dir.copyFile(entry.path, dest_dir, entry.path, .{}) catch |err| { - std.log.warn("unable to copy '{s}/{s}' to '{s}/{s}': {s}", .{ - freebsd_src_path, entry.path, - dest_dir_path, entry.path, - @errorName(err), + freebsd_src_dir.copyFile(entry.path, dest_dir, entry.path, io, .{}) catch |err| { + std.log.warn("unable to copy '{s}/{s}' to '{s}/{s}': {t}", .{ + freebsd_src_path, entry.path, dest_dir_path, entry.path, err, }); if (err == error.FileNotFound) { - try dest_dir.deleteFile(entry.path); + try dest_dir.deleteFile(io, entry.path); } }; } diff --git a/tools/update_glibc.zig b/tools/update_glibc.zig index 297c5c65b562..29df298bf6c4 100644 --- a/tools/update_glibc.zig +++ b/tools/update_glibc.zig @@ -1,15 +1,17 @@ //! This script updates the .c, .h, .s, and .S files that make up the start //! files such as crt1.o. Not to be confused with -//! https://github.com/ziglang/glibc-abi-tool/ which updates the `abilists` +//! https://codeberg.org/ziglang/libc-abi-tools which updates the `abilists` //! file. //! //! Example usage: //! `zig run ../tools/update_glibc.zig -- ~/Downloads/glibc ..` const std = @import("std"); +const Io = std.Io; +const Dir = std.Io.Dir; const mem = std.mem; const log = std.log; -const fs = std.fs; +const fatal = std.process.fatal; const exempt_files = [_][]const u8{ // This file is maintained by a separate project and does not come from glibc. @@ -36,33 +38,30 @@ const exempt_extensions = [_][]const u8{ "-2.33.c", }; -pub fn main() !void { - var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena_instance.deinit(); - const arena = arena_instance.allocator(); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const io = init.io; + const args = try init.minimal.args.toSlice(arena); - const args = try std.process.argsAlloc(arena); const glibc_src_path = args[1]; const zig_src_path = args[2]; const dest_dir_path = try std.fmt.allocPrint(arena, "{s}/lib/libc/glibc", .{zig_src_path}); - var dest_dir = fs.cwd().openDir(dest_dir_path, .{ .iterate = true }) catch |err| { - fatal("unable to open destination directory '{s}': {s}", .{ - dest_dir_path, @errorName(err), - }); + var dest_dir = Dir.cwd().openDir(io, dest_dir_path, .{ .iterate = true }) catch |err| { + fatal("unable to open destination directory '{s}': {t}", .{ dest_dir_path, err }); }; - defer dest_dir.close(); + defer dest_dir.close(io); - var glibc_src_dir = try fs.cwd().openDir(glibc_src_path, .{}); - defer glibc_src_dir.close(); + var glibc_src_dir = try Dir.cwd().openDir(io, glibc_src_path, .{}); + defer glibc_src_dir.close(io); // Copy updated files from upstream. { var walker = try dest_dir.walk(arena); defer walker.deinit(); - walk: while (try walker.next()) |entry| { + walk: while (try walker.next(io)) |entry| { if (entry.kind != .file) continue; if (mem.startsWith(u8, entry.basename, ".")) continue; for (exempt_files) |p| { @@ -72,14 +71,12 @@ pub fn main() !void { if (mem.endsWith(u8, entry.path, ext)) continue :walk; } - glibc_src_dir.copyFile(entry.path, dest_dir, entry.path, .{}) catch |err| { - log.warn("unable to copy '{s}/{s}' to '{s}/{s}': {s}", .{ - glibc_src_path, entry.path, - dest_dir_path, entry.path, - @errorName(err), + glibc_src_dir.copyFile(entry.path, dest_dir, entry.path, io, .{}) catch |err| { + log.warn("unable to copy '{s}/{s}' to '{s}/{s}': {t}", .{ + glibc_src_path, entry.path, dest_dir_path, entry.path, err, }); if (err == error.FileNotFound) { - try dest_dir.deleteFile(entry.path); + try dest_dir.deleteFile(io, entry.path); } }; } @@ -88,25 +85,23 @@ pub fn main() !void { // Warn about duplicated files inside glibc/include/* that can be omitted // because they are already in generic-glibc/*. - var include_dir = dest_dir.openDir("include", .{ .iterate = true }) catch |err| { - fatal("unable to open directory '{s}/include': {s}", .{ - dest_dir_path, @errorName(err), - }); + var include_dir = dest_dir.openDir(io, "include", .{ .iterate = true }) catch |err| { + fatal("unable to open directory '{s}/include': {t}", .{ dest_dir_path, err }); }; - defer include_dir.close(); + defer include_dir.close(io); const generic_glibc_path = try std.fmt.allocPrint( arena, "{s}/lib/libc/include/generic-glibc", .{zig_src_path}, ); - var generic_glibc_dir = try fs.cwd().openDir(generic_glibc_path, .{}); - defer generic_glibc_dir.close(); + var generic_glibc_dir = try Dir.cwd().openDir(io, generic_glibc_path, .{}); + defer generic_glibc_dir.close(io); var walker = try include_dir.walk(arena); defer walker.deinit(); - walk: while (try walker.next()) |entry| { + walk: while (try walker.next(io)) |entry| { if (entry.kind != .file) continue; if (mem.startsWith(u8, entry.basename, ".")) continue; for (exempt_files) |p| { @@ -116,23 +111,21 @@ pub fn main() !void { const max_file_size = 10 * 1024 * 1024; const generic_glibc_contents = generic_glibc_dir.readFileAlloc( + io, entry.path, arena, .limited(max_file_size), ) catch |err| switch (err) { error.FileNotFound => continue, - else => |e| fatal("unable to load '{s}/include/{s}': {s}", .{ - generic_glibc_path, entry.path, @errorName(e), - }), + else => |e| fatal("unable to load '{s}/include/{s}': {t}", .{ generic_glibc_path, entry.path, e }), }; const glibc_include_contents = include_dir.readFileAlloc( + io, entry.path, arena, .limited(max_file_size), ) catch |err| { - fatal("unable to load '{s}/include/{s}': {s}", .{ - dest_dir_path, entry.path, @errorName(err), - }); + fatal("unable to load '{s}/include/{s}': {t}", .{ dest_dir_path, entry.path, err }); }; const whitespace = " \r\n\t"; @@ -140,14 +133,8 @@ pub fn main() !void { const glibc_include_trimmed = mem.trim(u8, glibc_include_contents, whitespace); if (mem.eql(u8, generic_glibc_trimmed, glibc_include_trimmed)) { log.warn("same contents: '{s}/include/{s}' and '{s}/include/{s}'", .{ - generic_glibc_path, entry.path, - dest_dir_path, entry.path, + generic_glibc_path, entry.path, dest_dir_path, entry.path, }); } } } - -fn fatal(comptime format: []const u8, args: anytype) noreturn { - log.err(format, args); - std.process.exit(1); -} diff --git a/tools/update_mingw.zig b/tools/update_mingw.zig index 6288807cf1fa..ad3237d1ff08 100644 --- a/tools/update_mingw.zig +++ b/tools/update_mingw.zig @@ -1,35 +1,36 @@ const std = @import("std"); +const Io = std.Io; +const Dir = std.Io.Dir; -pub fn main() !void { - var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena_instance.deinit(); - const arena = arena_instance.allocator(); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const io = init.io; + const args = try init.minimal.args.toSlice(arena); - const args = try std.process.argsAlloc(arena); const zig_src_lib_path = args[1]; const mingw_src_path = args[2]; - const dest_mingw_crt_path = try std.fs.path.join(arena, &.{ + const dest_mingw_crt_path = try Dir.path.join(arena, &.{ zig_src_lib_path, "libc", "mingw", }); - const src_mingw_crt_path = try std.fs.path.join(arena, &.{ + const src_mingw_crt_path = try Dir.path.join(arena, &.{ mingw_src_path, "mingw-w64-crt", }); // Update only the set of existing files we have already chosen to include // in zig's installation. - var dest_crt_dir = std.fs.cwd().openDir(dest_mingw_crt_path, .{ .iterate = true }) catch |err| { - std.log.err("unable to open directory '{s}': {s}", .{ dest_mingw_crt_path, @errorName(err) }); + var dest_crt_dir = Dir.cwd().openDir(io, dest_mingw_crt_path, .{ .iterate = true }) catch |err| { + std.log.err("unable to open directory '{s}': {t}", .{ dest_mingw_crt_path, err }); std.process.exit(1); }; - defer dest_crt_dir.close(); + defer dest_crt_dir.close(io); - var src_crt_dir = std.fs.cwd().openDir(src_mingw_crt_path, .{ .iterate = true }) catch |err| { - std.log.err("unable to open directory '{s}': {s}", .{ src_mingw_crt_path, @errorName(err) }); + var src_crt_dir = Dir.cwd().openDir(io, src_mingw_crt_path, .{ .iterate = true }) catch |err| { + std.log.err("unable to open directory '{s}': {t}", .{ src_mingw_crt_path, err }); std.process.exit(1); }; - defer src_crt_dir.close(); + defer src_crt_dir.close(io); { var walker = try dest_crt_dir.walk(arena); @@ -37,10 +38,10 @@ pub fn main() !void { var fail = false; - while (try walker.next()) |entry| { + while (try walker.next(io)) |entry| { if (entry.kind != .file) continue; - src_crt_dir.copyFile(entry.path, dest_crt_dir, entry.path, .{}) catch |err| switch (err) { + src_crt_dir.copyFile(entry.path, dest_crt_dir, entry.path, io, .{}) catch |err| switch (err) { error.FileNotFound => { const keep = for (kept_crt_files) |item| { if (std.mem.eql(u8, entry.path, item)) break true; @@ -49,11 +50,11 @@ pub fn main() !void { if (!keep) { std.log.warn("deleting {s}", .{entry.path}); - try dest_crt_dir.deleteFile(entry.path); + try dest_crt_dir.deleteFile(io, entry.path); } }, else => { - std.log.err("unable to copy {s}: {s}", .{ entry.path, @errorName(err) }); + std.log.err("unable to copy {s}: {t}", .{ entry.path, err }); fail = true; }, }; @@ -63,24 +64,24 @@ pub fn main() !void { } { - const dest_mingw_winpthreads_path = try std.fs.path.join(arena, &.{ + const dest_mingw_winpthreads_path = try Dir.path.join(arena, &.{ zig_src_lib_path, "libc", "mingw", "winpthreads", }); - const src_mingw_libraries_winpthreads_src_path = try std.fs.path.join(arena, &.{ + const src_mingw_libraries_winpthreads_src_path = try Dir.path.join(arena, &.{ mingw_src_path, "mingw-w64-libraries", "winpthreads", "src", }); - var dest_winpthreads_dir = std.fs.cwd().openDir(dest_mingw_winpthreads_path, .{ .iterate = true }) catch |err| { + var dest_winpthreads_dir = Dir.cwd().openDir(io, dest_mingw_winpthreads_path, .{ .iterate = true }) catch |err| { std.log.err("unable to open directory '{s}': {s}", .{ dest_mingw_winpthreads_path, @errorName(err) }); std.process.exit(1); }; - defer dest_winpthreads_dir.close(); + defer dest_winpthreads_dir.close(io); - var src_winpthreads_dir = std.fs.cwd().openDir(src_mingw_libraries_winpthreads_src_path, .{ .iterate = true }) catch |err| { + var src_winpthreads_dir = Dir.cwd().openDir(io, src_mingw_libraries_winpthreads_src_path, .{ .iterate = true }) catch |err| { std.log.err("unable to open directory '{s}': {s}", .{ src_mingw_libraries_winpthreads_src_path, @errorName(err) }); std.process.exit(1); }; - defer src_winpthreads_dir.close(); + defer src_winpthreads_dir.close(io); { var walker = try dest_winpthreads_dir.walk(arena); @@ -88,16 +89,16 @@ pub fn main() !void { var fail = false; - while (try walker.next()) |entry| { + while (try walker.next(io)) |entry| { if (entry.kind != .file) continue; - src_winpthreads_dir.copyFile(entry.path, dest_winpthreads_dir, entry.path, .{}) catch |err| switch (err) { + src_winpthreads_dir.copyFile(entry.path, dest_winpthreads_dir, entry.path, io, .{}) catch |err| switch (err) { error.FileNotFound => { std.log.warn("deleting {s}", .{entry.path}); - try dest_winpthreads_dir.deleteFile(entry.path); + try dest_winpthreads_dir.deleteFile(io, entry.path); }, else => { - std.log.err("unable to copy {s}: {s}", .{ entry.path, @errorName(err) }); + std.log.err("unable to copy {s}: {t}", .{ entry.path, err }); fail = true; }, }; @@ -114,17 +115,17 @@ pub fn main() !void { var fail = false; - while (try walker.next()) |entry| { + while (try walker.next(io)) |entry| { switch (entry.kind) { .directory => { switch (entry.depth()) { 1 => if (def_dirs.has(entry.basename)) { - try walker.enter(entry); + try walker.enter(io, entry); continue; }, else => { // The top-level directory was already validated - try walker.enter(entry); + try walker.enter(io, entry); continue; }, } @@ -151,20 +152,20 @@ pub fn main() !void { if (std.mem.endsWith(u8, entry.basename, "_onecore.def")) continue; - src_crt_dir.copyFile(entry.path, dest_crt_dir, entry.path, .{}) catch |err| { - std.log.err("unable to copy {s}: {s}", .{ entry.path, @errorName(err) }); + src_crt_dir.copyFile(entry.path, dest_crt_dir, entry.path, io, .{}) catch |err| { + std.log.err("unable to copy {s}: {t}", .{ entry.path, err }); fail = true; }; } if (fail) std.process.exit(1); } - return std.process.cleanExit(); + return std.process.cleanExit(io); } const kept_crt_files = [_][]const u8{ "COPYING", - "include" ++ std.fs.path.sep_str ++ "config.h", + "include" ++ Dir.path.sep_str ++ "config.h", }; const def_exts = [_][]const u8{ diff --git a/tools/update_netbsd_libc.zig b/tools/update_netbsd_libc.zig index 7bfe99b09494..7a466c324657 100644 --- a/tools/update_netbsd_libc.zig +++ b/tools/update_netbsd_libc.zig @@ -5,40 +5,38 @@ //! `zig run tools/update_netbsd_libc.zig -- ~/Downloads/netbsd-src .` const std = @import("std"); +const Io = std.Io; const exempt_files = [_][]const u8{ // This file is maintained by a separate project and does not come from NetBSD. "abilists", }; -pub fn main() !void { - var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena_instance.deinit(); - const arena = arena_instance.allocator(); +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const io = init.io; + const args = try init.minimal.args.toSlice(arena); - const args = try std.process.argsAlloc(arena); const netbsd_src_path = args[1]; const zig_src_path = args[2]; const dest_dir_path = try std.fmt.allocPrint(arena, "{s}/lib/libc/netbsd", .{zig_src_path}); - var dest_dir = std.fs.cwd().openDir(dest_dir_path, .{ .iterate = true }) catch |err| { - std.log.err("unable to open destination directory '{s}': {s}", .{ - dest_dir_path, @errorName(err), - }); + var dest_dir = Io.Dir.cwd().openDir(io, dest_dir_path, .{ .iterate = true }) catch |err| { + std.log.err("unable to open destination directory '{s}': {t}", .{ dest_dir_path, err }); std.process.exit(1); }; - defer dest_dir.close(); + defer dest_dir.close(io); - var netbsd_src_dir = try std.fs.cwd().openDir(netbsd_src_path, .{}); - defer netbsd_src_dir.close(); + var netbsd_src_dir = try Io.Dir.cwd().openDir(io, netbsd_src_path, .{}); + defer netbsd_src_dir.close(io); // Copy updated files from upstream. { var walker = try dest_dir.walk(arena); defer walker.deinit(); - walk: while (try walker.next()) |entry| { + walk: while (try walker.next(io)) |entry| { if (entry.kind != .file) continue; if (std.mem.startsWith(u8, entry.basename, ".")) continue; for (exempt_files) |p| { @@ -50,14 +48,12 @@ pub fn main() !void { netbsd_src_path, entry.path, }); - netbsd_src_dir.copyFile(entry.path, dest_dir, entry.path, .{}) catch |err| { - std.log.warn("unable to copy '{s}/{s}' to '{s}/{s}': {s}", .{ - netbsd_src_path, entry.path, - dest_dir_path, entry.path, - @errorName(err), + netbsd_src_dir.copyFile(entry.path, dest_dir, entry.path, io, .{}) catch |err| { + std.log.warn("unable to copy '{s}/{s}' to '{s}/{s}': {t}", .{ + netbsd_src_path, entry.path, dest_dir_path, entry.path, err, }); if (err == error.FileNotFound) { - try dest_dir.deleteFile(entry.path); + try dest_dir.deleteFile(io, entry.path); } }; } diff --git a/tools/update_openbsd_libc.zig b/tools/update_openbsd_libc.zig new file mode 100644 index 000000000000..9da755f8ffea --- /dev/null +++ b/tools/update_openbsd_libc.zig @@ -0,0 +1,61 @@ +//! This script updates the .c, .h, .s, and .S files that make up the start +//! files such as crt1.o. +//! +//! Example usage: +//! `zig run tools/update_openbsd_libc.zig -- ~/Downloads/openbsd-src .` + +const std = @import("std"); +const Io = std.Io; + +const exempt_files = [_][]const u8{ + // This file is maintained by a separate project and does not come from OpenBSD. + "abilists", +}; + +pub fn main(init: std.process.Init) !void { + const arena = init.arena.allocator(); + const io = init.io; + const args = try init.minimal.args.toSlice(arena); + + const openbsd_src_path = args[1]; + const zig_src_path = args[2]; + + const dest_dir_path = try std.fmt.allocPrint(arena, "{s}/lib/libc/openbsd", .{zig_src_path}); + + var dest_dir = Io.Dir.cwd().openDir(io, dest_dir_path, .{ .iterate = true }) catch |err| { + std.log.err("unable to open destination directory '{s}': {t}", .{ dest_dir_path, err }); + std.process.exit(1); + }; + defer dest_dir.close(io); + + var openbsd_src_dir = try Io.Dir.cwd().openDir(io, openbsd_src_path, .{}); + defer openbsd_src_dir.close(io); + + // Copy updated files from upstream. + { + var walker = try dest_dir.walk(arena); + defer walker.deinit(); + + walk: while (try walker.next(io)) |entry| { + if (entry.kind != .file) continue; + if (std.mem.startsWith(u8, entry.basename, ".")) continue; + for (exempt_files) |p| { + if (std.mem.eql(u8, entry.path, p)) continue :walk; + } + + std.log.info("updating '{s}/{s}' from '{s}/{s}'", .{ + dest_dir_path, entry.path, + openbsd_src_path, entry.path, + }); + + openbsd_src_dir.copyFile(entry.path, dest_dir, entry.path, io, .{}) catch |err| { + std.log.warn("unable to copy '{s}/{s}' to '{s}/{s}': {t}", .{ + openbsd_src_path, entry.path, dest_dir_path, entry.path, err, + }); + if (err == error.FileNotFound) { + try dest_dir.deleteFile(io, entry.path); + } + }; + } + } +}